From 5caf49ff63ef84961f0b489706d6fcf3bcc0c6f0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 26 Jan 2015 15:16:37 +1300 Subject: Commit changes code using map of adjustments --- src/changes.rs | 251 ++++++++++++++++++++ src/rope.rs | 703 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 954 insertions(+) create mode 100644 src/changes.rs create mode 100644 src/rope.rs (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs new file mode 100644 index 00000000000..ba2b90d185d --- /dev/null +++ b/src/changes.rs @@ -0,0 +1,251 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// TODO +// composable changes +// print to files (maybe that shouldn't be here, but in mod) +// tests +// docs + +use rope::{Rope, RopeSlice}; +use std::collections::{HashMap, BTreeMap}; +use std::collections::Bound::{Included, Unbounded}; +use syntax::codemap::{CodeMap, Span, Pos}; +use std::fmt; + +pub struct ChangeSet<'a> { + file_map: HashMap, + // FIXME, we only keep a codemap around so we can have convenience methods + // taking Spans, it would be more resuable to factor this (and the methods) + // out into an adaptor. + codemap: &'a CodeMap, + pub count: u64, + // TODO we need to map the start and end of spans differently + // TODO needs to be per file + adjusts: BTreeMap, +} + +// An extent over which we must adjust the position values. +#[derive(Show, Clone, Eq, PartialEq)] +struct Adjustment { + // Start is implicit, given by its position in the map. + end: usize, + delta: isize, +} + +impl Adjustment { + fn chop_left(&self, new_end: usize) -> Adjustment { + Adjustment { + end: new_end, + delta: self.delta, + } + } + + fn move_left(&self, mov: usize) -> Adjustment { + assert!(self.delta > mov); + Adjustment { + end: self.end, + delta: self.delta - mov, + } + } +} + +pub struct FileIterator<'c, 'a: 'c> { + change_set: &'c ChangeSet<'a>, + keys: Vec<&'c String>, + cur_key: usize, +} + +impl<'a> ChangeSet<'a> { + pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> { + let mut result = ChangeSet { + file_map: HashMap::new(), + codemap: codemap, + count: 0, + adjusts: BTreeMap::new(), + }; + + for f in codemap.files.borrow().iter() { + let contents = Rope::from_string(f.src.clone()); + result.file_map.insert(f.name.clone(), contents); + } + + result + } + + // start and end are unadjusted. + pub fn change(&mut self, file_name: &str, start: usize, end: usize, text: String) { + println!("change: {}:{}-{} \"{}\"", file_name, start, end, text); + + let new_len = text.len(); + self.count += 1; + + let (key_start, adj_start, abs_start): (Option, Option, usize) = { + let before_start = self.adjusts.range(Unbounded, Included(&start)).next_back(); + match before_start { + Some((k, a)) if a.end > start => (Some(*k), Some(a.clone()), (start as isize + a.delta) as usize), + _ => (None, None, start) + } + }; + let (key_end, adj_end, abs_end) = { + let before_end = self.adjusts.range(Unbounded, Included(&end)).next_back(); + match before_end { + Some((k, a)) if a.end > end => (Some(*k), Some(a.clone()), (end as isize + a.delta) as usize), + _ => (None, None, end) + } + }; + + { + let file = &mut self.file_map[*file_name]; + + println!("change: absolute values {}-{}, replaces \"{}\"", + abs_start, abs_end, file.slice(abs_start..abs_end)); + + file.remove(abs_start, abs_end); + file.insert(abs_start, text); + + // Record the changed locations. + // TODO what if there is a change to the right of end? - need to iterate over all changes to the right :-( + match (key_start, key_end) { + (None, None) => { + // Factor this out? + let old_len = end as isize - start as isize; + let delta = new_len as isize - old_len; + self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); + } + (Some(k), None) => { + // Adjust the old change. + self.adjusts[k] = adj_start.unwrap().chop_left(end); + + // Add the new one. + let old_len = end as isize - start as isize; + let delta = new_len as isize - old_len; + self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); + } + (None, Some(k)) => { + let old_len = end as isize - start as isize; + let delta = new_len as isize - old_len; + + // Adjust the old change. + // TODO only if we move left, but what if moving right? + self.adjusts[abs_end] = adj_end.unwrap().move_left(TODO); + self.adjusts.remove(&k); + + // Add the new one. + self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); + } + _ => { + println!("{}", file); + panic!(); + } + } + } + + debug_assert!(self.verify_adjustments(), "Bad change, created an overlapping adjustment"); + } + + // Intended for debugging. + fn verify_adjustments(&self) -> bool { + let mut prev_end = 0; + let mut prev_delta = 0; + for (&k, a) in self.adjusts.iter() { + if k < prev_end { + debug!("Found bad adjustment at start {}, overlaps with previous adjustment", k); + return false; + } + if k as isize + a.delta < 0 { + debug!("Found bad adjustment at start {}, absolute start < 0", k); + return false; + } + if k as isize + a.delta < prev_end as isize + prev_delta { + debug!("Found bad adjustment at start {}, \ + projection overlaps with previous projection", k); + return false; + } + // TODO Check end + delta <= file.len - needs per file + + prev_end = a.end; + prev_delta = a.delta; + } + true + } + + // span is unadjusted. + pub fn change_span(&mut self, span: Span, text: String) { + let l_loc = self.codemap.lookup_char_pos(span.lo); + let file_offset = l_loc.file.start_pos.0; + self.change(&l_loc.file.name[], + (span.lo.0 - file_offset) as usize, + (span.hi.0 - file_offset) as usize, + text) + } + + // start and end are unadjusted. + pub fn slice(&self, file_name: &str, start: usize, end: usize) -> RopeSlice { + // TODO refactor with change? + let abs_start = { + let before_start = self.adjusts.range(Unbounded, Included(&start)).next_back(); + match before_start { + Some((k, ref a)) if a.end > start => (start as isize + a.delta) as usize, + _ => start + } + }; + let abs_end = { + let before_end = self.adjusts.range(Unbounded, Included(&end)).next_back(); + match before_end { + Some((k, ref a)) if a.end > end => (end as isize + a.delta) as usize, + _ => end + } + }; + + let file = &self.file_map[*file_name]; + file.slice(abs_start..abs_end) + } + + // span is unadjusted. + pub fn slice_span(&self, span:Span) -> RopeSlice { + let l_loc = self.codemap.lookup_char_pos(span.lo); + let file_offset = l_loc.file.start_pos.0; + self.slice(&l_loc.file.name[], + (span.lo.0 - file_offset) as usize, + (span.hi.0 - file_offset) as usize) + } + + pub fn text<'c>(&'c self) -> FileIterator<'c, 'a> { + FileIterator { + change_set: self, + keys: self.file_map.keys().collect(), + cur_key: 0, + } + } +} + +impl<'c, 'a> Iterator for FileIterator<'c, 'a> { + type Item = (&'c str, &'c Rope); + fn next(&mut self) -> Option<(&'c str, &'c Rope)> { + if self.cur_key >= self.keys.len() { + return None; + } + + let key = self.keys[self.cur_key]; + self.cur_key += 1; + return Some((&key[], &self.change_set.file_map[*key])) + } +} + +impl<'a> fmt::Display for ChangeSet<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + for (f, r) in self.text() { + try!(write!(fmt, "{}:\n", f)); + try!(write!(fmt, "{}", r)); + } + Ok(()) + } +} diff --git a/src/rope.rs b/src/rope.rs new file mode 100644 index 00000000000..263a7923c3b --- /dev/null +++ b/src/rope.rs @@ -0,0 +1,703 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// TODO +// ---- +// docs - mod docs, item docs +// tests +// pull out into its own crate +// impl Default, Extend +// impl DOubleEndedIter and ExactSizeIter for RopeChars +// better allocation +// balancing +// thread safety/parallisation + +extern crate unicode; +use std::fmt; +use std::ops::Range; + +// A Rope, based on an unbalanced binary tree. + +pub struct Rope { + root: Node, + len: usize, + // FIXME: Allocation is very dumb at the moment, we always add another buffer for every inserted string and we never resuse or collect old memory + storage: Vec> +} + +pub struct RopeSlice<'rope> { + // All nodes which make up the slice, in order. + nodes: Vec<&'rope Lnode>, + // The offset of the start point in the first node. + start: usize, + // The length of text in the last node. + len: usize, +} + +pub struct RopeChars<'rope> { + data: RopeSlice<'rope>, + cur_node: usize, + cur_byte: usize, + abs_byte: usize, +} + + +impl Rope { + pub fn new() -> Rope { + Rope { + root: Node::empty_inner(), + len: 0, + storage: vec![], + } + } + + // Uses text as initial storage. + pub fn from_string(text: String) -> Rope { + // TODO should split large texts into segments as we insert + + let mut result = Rope::new(); + result.insert(0, text); + result + } + + pub fn len(&self) -> usize { + self.len + } + + pub fn insert(&mut self, start: usize, text: String) { + if text.len() == 0 { + return; + } + + debug_assert!(start <= self.len(), "insertion out of bounds of rope"); + + let len = text.len(); + let storage = text.into_bytes(); + let new_node = box Node::new_leaf(&storage[][0] as *const u8, len); + self.storage.push(storage); + + match self.root.insert(new_node, start) { + NodeAction::Change(n, adj) => { + assert!(adj as usize == len); + self.root = *n; + } + NodeAction::Adjust(adj) => { + assert!(adj as usize == len); + } + _ => panic!("Unexpected action") + } + self.len += len; + } + + pub fn insert_copy(&mut self, start: usize, text: &str) { + // If we did clever things with allocation, we could do better here + self.insert(start, text.to_string()); + } + + pub fn push(&mut self, text: String) { + let len = self.len(); + self.insert(len, text); + } + + pub fn push_copy(&mut self, text: &str) { + // If we did clever things with allocation, we could do better here + let len = self.len(); + self.insert(len, text.to_string()); + } + + pub fn remove(&mut self, start: usize, end: usize) { + assert!(end >= start); + if start == end { + return; + } + + let action = self.root.remove(start, end, 0); + match action { + NodeAction::None => {} + NodeAction::Remove => { + self.root = Node::empty_inner(); + self.len = 0; + } + NodeAction::Adjust(adj) => self.len = (self.len as isize + adj) as usize, + NodeAction::Change(node, adj) => { + self.root = *node; + self.len = (self.len as isize + adj) as usize; + } + } + } + + // This can go horribly wrong if you overwrite a grapheme of different size. + // It is the callers responsibility to ensure that the grapheme at point start + // has the same size as new_char. + pub fn replace(&mut self, start: usize, new_char: char) { + assert!(start + new_char.len_utf8() <= self.len); + // This is pretty wasteful in that we're allocating for no point, but + // I think that is better than duplicating a bunch of code. + // It should be possible to view a &char as a &[u8] somehow, and then + // we can optimise this (FIXME). + self.replace_str(start, &new_char.to_string()[]); + } + + pub fn replace_str(&mut self, start: usize, new_str: &str) { + assert!(start + new_str.len() <= self.len); + self.root.replace(start, new_str); + } + + pub fn slice(&self, Range { start, end }: Range) -> RopeSlice { + debug_assert!(end > start && start <= self.len && end <= self.len); + if start == end { + return RopeSlice::empty(); + } + + let mut result = RopeSlice::empty(); + self.root.find_slice(start, end, &mut result); + result + } + + pub fn full_slice(&self) -> RopeSlice { + self.slice(0..self.len) + } + + pub fn chars(&self) -> RopeChars { + RopeChars { + data: self.full_slice(), + cur_node: 0, + cur_byte: 0, + abs_byte: 0, + } + } +} + +impl<'rope> RopeSlice<'rope> { + fn empty<'r>() -> RopeSlice<'r> { + RopeSlice { + nodes: vec![], + start: 0, + len: 0, + } + } +} + +impl<'rope> Iterator for RopeChars<'rope> { + type Item = (char, usize); + fn next(&mut self) -> Option<(char, usize)> { + if self.cur_node >= self.data.nodes.len() { + return None; + } + + let byte = self.abs_byte; + let node = self.data.nodes[self.cur_node]; + if self.cur_byte >= node.len { + self.cur_byte = 0; + self.cur_node += 1; + return self.next(); + } + + let result = self.read_char(); + return Some((result, byte)); + } +} + +impl<'rope> RopeChars<'rope> { + fn read_char(&mut self) -> char { + let first_byte = self.read_byte(); + let width = unicode::str::utf8_char_width(first_byte); + if width == 1 { + return first_byte as char + } + if width == 0 { + panic!("non-utf8 char in rope"); + } + let mut buf = [first_byte, 0, 0, 0]; + { + let mut start = 1; + while start < width { + buf[start] = self.read_byte(); + start += 1; + } + } + match ::std::str::from_utf8(&buf[..width]).ok() { + Some(s) => s.char_at(0), + None => panic!("bad chars in rope") + } + } + + fn read_byte(&mut self) -> u8 { + let node = self.data.nodes[self.cur_node]; + let addr = node.text as usize + self.cur_byte; + self.cur_byte += 1; + self.abs_byte += 1; + let addr = addr as *const u8; + unsafe { + *addr + } + } +} + +impl ::std::str::FromStr for Rope { + fn from_str(text: &str) -> Option { + // TODO should split large texts into segments as we insert + + let mut result = Rope::new(); + result.insert_copy(0, text); + Some(result) + } +} + +impl<'a> fmt::Display for RopeSlice<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let last_idx = self.nodes.len() - 1; + for (i, n) in self.nodes.iter().enumerate() { + let mut ptr = n.text; + let mut len = n.len; + if i == 0 { + ptr = (ptr as usize + self.start) as *const u8; + len -= self.start; + } + if i == last_idx { + len = self.len; + } + unsafe { + try!(write!(fmt, + "{}", + ::std::str::from_utf8(::std::slice::from_raw_buf(&ptr, len)).unwrap())); + } + } + Ok(()) + } +} + +impl<'a> fmt::Debug for RopeSlice<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let last_idx = self.nodes.len() - 1; + for (i, n) in self.nodes.iter().enumerate() { + let mut ptr = n.text; + let mut len = n.len; + if i == 0 { + ptr = (ptr as usize + self.start) as *const u8; + len -= self.start; + } else { + try!(write!(fmt, "|")); + } + if i == last_idx { + len = self.len; + } + unsafe { + try!(write!(fmt, + "\"{}\"", + ::std::str::from_utf8(::std::slice::from_raw_buf(&ptr, len)).unwrap())); + } + } + Ok(()) + } +} + +impl fmt::Display for Rope { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(fmt, "{}", self.root) + } +} + +impl fmt::Debug for Rope { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(fmt, "{:?}", self.root) + } +} + +impl fmt::Display for Node { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Node::InnerNode(Inode { ref left, ref right, .. }) => { + if let Some(ref left) = *left { + write!(fmt, "{}", left) + } else { + Ok(()) + }.and_then(|_| if let Some(ref right) = *right { + write!(fmt, "{}", right) + } else { + Ok(()) + }) + } + Node::LeafNode(Lnode{ ref text, len }) => { + unsafe { + write!(fmt, + "{}", + ::std::str::from_utf8(::std::slice::from_raw_buf(text, len)).unwrap()) + } + } + } + } +} + +impl fmt::Debug for Node { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Node::InnerNode(Inode { ref left, ref right, weight }) => { + try!(write!(fmt, "(")); + if let Some(ref left) = *left { + try!(write!(fmt, "left: {:?}", &**left)); + } else { + try!(write!(fmt, "left: ()")); + } + try!(write!(fmt, ", ")); + if let Some(ref right) = *right { + try!(write!(fmt, "right: {:?}", &**right)); + } else { + try!(write!(fmt, "right: ()")); + } + write!(fmt, "; {})", weight) + } + Node::LeafNode(Lnode{ ref text, len }) => { + unsafe { + write!(fmt, + "\"{}\"; {}", + ::std::str::from_utf8(::std::slice::from_raw_buf(text, len)).unwrap(), + len) + } + } + } + } +} + +#[derive(Clone, Eq, PartialEq)] +enum Node { + InnerNode(Inode), + LeafNode(Lnode), +} + +#[derive(Clone, Eq, PartialEq)] +struct Inode { + weight: usize, + left: Option>, + right: Option>, +} + +#[derive(Clone, Eq, PartialEq)] +struct Lnode { + text: *const u8, + len: usize, +} + +impl Node { + fn empty_inner() -> Node { + Node::InnerNode(Inode { + left: None, + right: None, + weight: 0 + }) + } + + fn new_inner(left: Option>, + right: Option>, + weight: usize) + -> Node { + Node::InnerNode(Inode { + left: left, + right: right, + weight: weight + }) + } + + fn new_leaf(text: *const u8, len: usize) -> Node { + Node::LeafNode(Lnode { + text: text, + len: len + }) + } + + fn len(&self) -> usize { + match *self { + Node::InnerNode(Inode { weight, ref right, .. }) => { + match *right { + Some(ref r) => weight + r.len(), + None => weight + } + } + Node::LeafNode(Lnode { len, .. }) => len, + } + } + + // precond: start < end + fn remove(&mut self, start: usize, end: usize, offset: usize) -> NodeAction { + if end < offset { + // The span to remove is to the left of this node. + return NodeAction::None; + } + + match *self { + Node::InnerNode(ref mut i) => i.remove(start, end, offset), + Node::LeafNode(ref mut l) => l.remove(start, end, offset), + } + } + + fn insert(&mut self, node: Box, start: usize) -> NodeAction { + match *self { + Node::InnerNode(ref mut i) => i.insert(node, start), + Node::LeafNode(ref mut l) => l.insert(node, start), + } + } + + fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { + match *self { + Node::InnerNode(ref i) => i.find_slice(start, end, slice), + Node::LeafNode(ref l) => l.find_slice(start, end, slice), + } + } + + fn replace(&mut self, start: usize, new_str: &str) { + match *self { + Node::InnerNode(ref mut i) => i.replace(start, new_str), + Node::LeafNode(ref mut l) => l.replace(start, new_str), + } + } +} + +#[derive(Show, Clone, Eq, PartialEq)] +enum NodeAction { + None, + Remove, + Adjust(isize), // Arg is the length of the old node - the length of the newly adjusted node. + Change(Box, isize) // Args are the new node and the change in length. +} + +impl Inode { + // precond: start < end && end >= offset + fn remove(&mut self, start: usize, end: usize, offset: usize) -> NodeAction { + debug!("Inode::remove: {}, {}, {}, {}", start, end, offset, self.weight); + if start >= offset + self.weight { + // The removal cannot affect our left side. + match self.right { + Some(_) => {} + None => {} + } + } + + let left_action = if let Some(ref mut left) = self.left { + left.remove(start, end, offset) + } else { + NodeAction::None + }; + let right_action = if let Some(ref mut right) = self.right { + right.remove(start, end, offset + self.weight) + } else { + NodeAction::None + }; + + if left_action == NodeAction::Remove && right_action == NodeAction::Remove || + left_action == NodeAction::Remove && self.right.is_none() || + right_action == NodeAction::Remove && self.left.is_none() { + return NodeAction::Remove; + } + + if left_action == NodeAction::Remove { + return NodeAction::Change(self.right.clone().unwrap(), + -(self.weight as isize)); + } + if right_action == NodeAction::Remove { + return NodeAction::Change(self.left.clone().unwrap(), + -(self.right.as_ref().map(|n| n.len()).unwrap() as isize)); + } + + let mut total_adj = 0; + if let NodeAction::Change(ref n, adj) = left_action { + self.left = Some(n.clone()); + self.weight = (self.weight as isize + adj) as usize; + total_adj += adj; + } + if let NodeAction::Change(ref n, adj) = right_action { + self.right = Some(n.clone()); + total_adj += adj; + } + + if let NodeAction::Adjust(adj) = left_action { + self.weight = (self.weight as isize + adj) as usize; + total_adj += adj; + } + if let NodeAction::Adjust(adj) = right_action { + total_adj += adj; + } + + return NodeAction::Adjust(total_adj); + } + + fn insert(&mut self, node: Box, start: usize) -> NodeAction { + let mut total_adj = 0; + if start < self.weight { + let action = if let Some(ref mut left) = self.left { + left.insert(node, start) + } else { + assert!(self.weight == 0); + let len = node.len() as isize; + NodeAction::Change(node, len) + }; + + match action { + NodeAction::Change(n, adj) => { + self.left = Some(n); + self.weight += adj as usize; + total_adj += adj; + } + NodeAction::Adjust(adj) => { + self.weight += adj as usize; + total_adj += adj; + } + _ => panic!("Unexpected action"), + } + } else { + let action = if let Some(ref mut right) = self.right { + assert!(start >= self.weight); + right.insert(node, start - self.weight) + } else { + let len = node.len() as isize; + NodeAction::Change(node, len) + }; + + match action { + NodeAction::Change(n, adj) => { + self.right = Some(n); + total_adj += adj; + } + NodeAction::Adjust(adj) => total_adj += adj, + _ => panic!("Unexpected action"), + } + } + + NodeAction::Adjust(total_adj) + } + + fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { + debug!("Inode::find_slice: {}, {}, {}", start, end, self.weight); + if start < self.weight { + self.left.as_ref().unwrap().find_slice(start, end, slice); + } + if end > self.weight { + let start = if start < self.weight { + 0 + } else { + start - self.weight + }; + self.right.as_ref().unwrap().find_slice(start, end - self.weight, slice) + } + } + + fn replace(&mut self, start: usize, new_str: &str) { + debug!("Inode::replace: {}, {}, {}", start, new_str, self.weight); + let end = start + new_str.len(); + if start < self.weight { + if let Some(ref mut left) = self.left { + left.replace(start, &new_str[..::std::cmp::min(self.weight-start, new_str.len())]); + } else { + panic!(); + } + } + if end > self.weight { + let (start, offset) = if start < self.weight { + (0, self.weight - start) + } else { + (start - self.weight, 0) + }; + if let Some(ref mut right) = self.right { + right.replace(start, &new_str[offset..]); + } else { + panic!(); + } + } + } +} + +impl Lnode { + // precond: start < end && end >= offset + fn remove(&mut self, start: usize, end: usize, offset: usize) -> NodeAction { + debug!("Lnode::remove: {}, {}, {}, {}", start, end, offset, self.len); + if start > offset + self.len { + // The span to remove is to the right of this node. + return NodeAction::None; + } + + if start <= offset && end >= offset + self.len { + // The removal span includes us, remove ourselves. + return NodeAction::Remove; + } + + let old_len = self.len; + if start <= offset { + // Truncate the left of the node. + self.text = (self.text as usize + (end - offset)) as *const u8; + self.len = old_len - (end - offset); + return NodeAction::Adjust(self.len as isize - old_len as isize); + } + + if end >= offset + self.len { + // Truncate the right of the node. + self.len = start - offset; + return NodeAction::Adjust(self.len as isize - old_len as isize); + } + + // Split the node (span to remove is in the middle of the node). + let new_node = Node::new_inner( + Some(box Node::new_leaf(self.text, start - offset)), + Some(box Node::new_leaf((self.text as usize + (end - offset)) as *const u8, + old_len - (end - offset))), + start - offset); + return NodeAction::Change(box new_node, -((end - start) as isize)); + } + + fn insert(&mut self, node: Box, start: usize) -> NodeAction { + let len = node.len(); + if start == 0 { + // Insert at the start of the node + let new_node = box Node::new_inner(Some(node), + Some(box Node::LeafNode(self.clone())), + len); + return NodeAction::Change(new_node, len as isize) + } + + if start == self.len { + // Insert at the end of the node + let new_node = box Node::new_inner(Some(box Node::LeafNode(self.clone())), + Some(node), + self.len); + return NodeAction::Change(new_node, len as isize) + } + + // Insert into the middle of the node + let left = Some(box Node::new_leaf(self.text, start)); + let new_left = box Node::new_inner(left, Some(node), start); + let right = Some(box Node::new_leaf((self.text as usize + (start)) as *const u8, + self.len - (start))); + let new_node = box Node::new_inner(Some(new_left), right, start + len); + + return NodeAction::Change(new_node, len as isize) + } + + fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { + debug!("Lnode::find_slice: {}, {}, {}", start, end, self.len); + debug_assert!(start < self.len, "Shouldn't have called this fn, we're out of bounds"); + + slice.nodes.push(self); + let mut len = end; + if start > 0 { + slice.start = start; + len -= start; + } + if end <= self.len { + slice.len = len; + } + } + + fn replace(&mut self, start: usize, new_str: &str) { + debug!("Lnode::replace: {}, {}, {}", start, new_str, self.len); + debug_assert!(start + new_str.len() <= self.len); + let addr = (self.text as usize + start) as *mut u8; + unsafe { + ::std::intrinsics::copy_nonoverlapping_memory(addr, &new_str.as_bytes()[0], new_str.len()); + } + } +} -- cgit 1.4.1-3-g733a5 From f1e698c838defa9535750312d3fc11ebf3a830e9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 2 Feb 2015 21:59:03 +1300 Subject: Save changes in the rope. Also changes to using the new rustc interface --- src/changes.rs | 158 ++------------- src/rope.rs | 591 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 540 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index ba2b90d185d..22fdc0ff51d 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -15,9 +15,8 @@ // docs use rope::{Rope, RopeSlice}; -use std::collections::{HashMap, BTreeMap}; -use std::collections::Bound::{Included, Unbounded}; -use syntax::codemap::{CodeMap, Span, Pos}; +use std::collections::HashMap; +use syntax::codemap::{CodeMap, Span, Pos, BytePos}; use std::fmt; pub struct ChangeSet<'a> { @@ -27,34 +26,6 @@ pub struct ChangeSet<'a> { // out into an adaptor. codemap: &'a CodeMap, pub count: u64, - // TODO we need to map the start and end of spans differently - // TODO needs to be per file - adjusts: BTreeMap, -} - -// An extent over which we must adjust the position values. -#[derive(Show, Clone, Eq, PartialEq)] -struct Adjustment { - // Start is implicit, given by its position in the map. - end: usize, - delta: isize, -} - -impl Adjustment { - fn chop_left(&self, new_end: usize) -> Adjustment { - Adjustment { - end: new_end, - delta: self.delta, - } - } - - fn move_left(&self, mov: usize) -> Adjustment { - assert!(self.delta > mov); - Adjustment { - end: self.end, - delta: self.delta - mov, - } - } } pub struct FileIterator<'c, 'a: 'c> { @@ -69,7 +40,6 @@ impl<'a> ChangeSet<'a> { file_map: HashMap::new(), codemap: codemap, count: 0, - adjusts: BTreeMap::new(), }; for f in codemap.files.borrow().iter() { @@ -84,100 +54,21 @@ impl<'a> ChangeSet<'a> { pub fn change(&mut self, file_name: &str, start: usize, end: usize, text: String) { println!("change: {}:{}-{} \"{}\"", file_name, start, end, text); - let new_len = text.len(); self.count += 1; - let (key_start, adj_start, abs_start): (Option, Option, usize) = { - let before_start = self.adjusts.range(Unbounded, Included(&start)).next_back(); - match before_start { - Some((k, a)) if a.end > start => (Some(*k), Some(a.clone()), (start as isize + a.delta) as usize), - _ => (None, None, start) - } - }; - let (key_end, adj_end, abs_end) = { - let before_end = self.adjusts.range(Unbounded, Included(&end)).next_back(); - match before_end { - Some((k, a)) if a.end > end => (Some(*k), Some(a.clone()), (end as isize + a.delta) as usize), - _ => (None, None, end) - } - }; - - { - let file = &mut self.file_map[*file_name]; - - println!("change: absolute values {}-{}, replaces \"{}\"", - abs_start, abs_end, file.slice(abs_start..abs_end)); - - file.remove(abs_start, abs_end); - file.insert(abs_start, text); - - // Record the changed locations. - // TODO what if there is a change to the right of end? - need to iterate over all changes to the right :-( - match (key_start, key_end) { - (None, None) => { - // Factor this out? - let old_len = end as isize - start as isize; - let delta = new_len as isize - old_len; - self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); - } - (Some(k), None) => { - // Adjust the old change. - self.adjusts[k] = adj_start.unwrap().chop_left(end); - - // Add the new one. - let old_len = end as isize - start as isize; - let delta = new_len as isize - old_len; - self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); - } - (None, Some(k)) => { - let old_len = end as isize - start as isize; - let delta = new_len as isize - old_len; - - // Adjust the old change. - // TODO only if we move left, but what if moving right? - self.adjusts[abs_end] = adj_end.unwrap().move_left(TODO); - self.adjusts.remove(&k); - - // Add the new one. - self.adjusts.insert(end, Adjustment { end: file.len(), delta: delta }); - } - _ => { - println!("{}", file); - panic!(); - } - } - } - - debug_assert!(self.verify_adjustments(), "Bad change, created an overlapping adjustment"); - } + let file = &mut self.file_map[*file_name]; - // Intended for debugging. - fn verify_adjustments(&self) -> bool { - let mut prev_end = 0; - let mut prev_delta = 0; - for (&k, a) in self.adjusts.iter() { - if k < prev_end { - debug!("Found bad adjustment at start {}, overlaps with previous adjustment", k); - return false; - } - if k as isize + a.delta < 0 { - debug!("Found bad adjustment at start {}, absolute start < 0", k); - return false; - } - if k as isize + a.delta < prev_end as isize + prev_delta { - debug!("Found bad adjustment at start {}, \ - projection overlaps with previous projection", k); - return false; - } - // TODO Check end + delta <= file.len - needs per file - - prev_end = a.end; - prev_delta = a.delta; + if end - start == text.len() { + // TODO + panic!(); + file.replace_str(start, &text[]); + } else { + // TODO if we do this in one op, could we get better change info? + file.src_remove(start, end); + file.src_insert(start, text); } - true } - // span is unadjusted. pub fn change_span(&mut self, span: Span, text: String) { let l_loc = self.codemap.lookup_char_pos(span.lo); let file_offset = l_loc.file.start_pos.0; @@ -187,29 +78,11 @@ impl<'a> ChangeSet<'a> { text) } - // start and end are unadjusted. pub fn slice(&self, file_name: &str, start: usize, end: usize) -> RopeSlice { - // TODO refactor with change? - let abs_start = { - let before_start = self.adjusts.range(Unbounded, Included(&start)).next_back(); - match before_start { - Some((k, ref a)) if a.end > start => (start as isize + a.delta) as usize, - _ => start - } - }; - let abs_end = { - let before_end = self.adjusts.range(Unbounded, Included(&end)).next_back(); - match before_end { - Some((k, ref a)) if a.end > end => (end as isize + a.delta) as usize, - _ => end - } - }; - let file = &self.file_map[*file_name]; - file.slice(abs_start..abs_end) + file.src_slice(start..end) } - // span is unadjusted. pub fn slice_span(&self, span:Span) -> RopeSlice { let l_loc = self.codemap.lookup_char_pos(span.lo); let file_offset = l_loc.file.start_pos.0; @@ -225,6 +98,13 @@ impl<'a> ChangeSet<'a> { cur_key: 0, } } + + pub fn col(&self, loc: BytePos) -> usize { + let l_loc = self.codemap.lookup_char_pos(loc); + let file_offset = l_loc.file.start_pos.0; + let file = &self.file_map[l_loc.file.name[]]; + file.col_for_src_loc(loc.0 as usize - file_offset as usize) + } } impl<'c, 'a> Iterator for FileIterator<'c, 'a> { diff --git a/src/rope.rs b/src/rope.rs index 263a7923c3b..150e51b4bd3 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -28,6 +28,7 @@ use std::ops::Range; pub struct Rope { root: Node, len: usize, + src_len: usize, // FIXME: Allocation is very dumb at the moment, we always add another buffer for every inserted string and we never resuse or collect old memory storage: Vec> } @@ -54,6 +55,7 @@ impl Rope { Rope { root: Node::empty_inner(), len: 0, + src_len: 0, storage: vec![], } } @@ -64,9 +66,15 @@ impl Rope { let mut result = Rope::new(); result.insert(0, text); + result.fix_src(); result } + fn fix_src(&mut self) { + self.root.fix_src(); + self.src_len = self.len; + } + pub fn len(&self) -> usize { self.len } @@ -80,10 +88,10 @@ impl Rope { let len = text.len(); let storage = text.into_bytes(); - let new_node = box Node::new_leaf(&storage[][0] as *const u8, len); + let new_node = box Node::new_leaf(&storage[][0] as *const u8, len, 0); self.storage.push(storage); - match self.root.insert(new_node, start) { + match self.root.insert(new_node, start, start) { NodeAction::Change(n, adj) => { assert!(adj as usize == len); self.root = *n; @@ -101,6 +109,32 @@ impl Rope { self.insert(start, text.to_string()); } + pub fn src_insert(&mut self, start: usize, text: String) { + // TODO refactor with insert + if text.len() == 0 { + return; + } + + debug_assert!(start <= self.src_len, "insertion out of bounds of rope"); + + let len = text.len(); + let storage = text.into_bytes(); + let new_node = box Node::new_leaf(&storage[][0] as *const u8, len, 0); + self.storage.push(storage); + + match self.root.src_insert(new_node, start, start) { + NodeAction::Change(n, adj) => { + assert!(adj as usize == len); + self.root = *n; + } + NodeAction::Adjust(adj) => { + assert!(adj as usize == len); + } + _ => panic!("Unexpected action") + } + self.len += len; + } + pub fn push(&mut self, text: String) { let len = self.len(); self.insert(len, text); @@ -118,7 +152,7 @@ impl Rope { return; } - let action = self.root.remove(start, end, 0); + let action = self.root.remove(start, end, start); match action { NodeAction::None => {} NodeAction::Remove => { @@ -133,6 +167,30 @@ impl Rope { } } + pub fn src_remove(&mut self, start: usize, end: usize) { + // TODO refactor with remove + assert!(end >= start); + if start == end { + return; + } + + let action = self.root.src_remove(start, end, start); + match action { + NodeAction::None => {} + NodeAction::Remove => { + self.root = Node::empty_inner(); + self.len = 0; + } + NodeAction::Adjust(adj) => self.len = (self.len as isize + adj) as usize, + NodeAction::Change(node, adj) => { + self.root = *node; + self.len = (self.len as isize + adj) as usize; + } + } + } + + // TODO src_replace + // This can go horribly wrong if you overwrite a grapheme of different size. // It is the callers responsibility to ensure that the grapheme at point start // has the same size as new_char. @@ -150,6 +208,14 @@ impl Rope { self.root.replace(start, new_str); } + // Note, this is not necessarily cheap. + pub fn col_for_src_loc(&self, src_loc: usize) -> usize { + assert!(src_loc <= self.src_len); + match self.root.col_for_src_loc(src_loc) { + Search::Done(c) | Search::Continue(c) => c + } + } + pub fn slice(&self, Range { start, end }: Range) -> RopeSlice { debug_assert!(end > start && start <= self.len && end <= self.len); if start == end { @@ -165,6 +231,17 @@ impl Rope { self.slice(0..self.len) } + pub fn src_slice(&self, Range { start, end }: Range) -> RopeSlice { + debug_assert!(end > start && start <= self.src_len && end <= self.src_len); + if start == end { + return RopeSlice::empty(); + } + + let mut result = RopeSlice::empty(); + self.root.find_src_slice(start, end, &mut result); + result + } + pub fn chars(&self) -> RopeChars { RopeChars { data: self.full_slice(), @@ -242,12 +319,14 @@ impl<'rope> RopeChars<'rope> { } impl ::std::str::FromStr for Rope { - fn from_str(text: &str) -> Option { + type Err = (); + fn from_str(text: &str) -> Result { // TODO should split large texts into segments as we insert let mut result = Rope::new(); result.insert_copy(0, text); - Some(result) + result.fix_src(); + Ok(result) } } @@ -325,7 +404,7 @@ impl fmt::Display for Node { Ok(()) }) } - Node::LeafNode(Lnode{ ref text, len }) => { + Node::LeafNode(Lnode{ ref text, len, .. }) => { unsafe { write!(fmt, "{}", @@ -339,7 +418,7 @@ impl fmt::Display for Node { impl fmt::Debug for Node { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - Node::InnerNode(Inode { ref left, ref right, weight }) => { + Node::InnerNode(Inode { ref left, ref right, weight, .. }) => { try!(write!(fmt, "(")); if let Some(ref left) = *left { try!(write!(fmt, "left: {:?}", &**left)); @@ -354,10 +433,10 @@ impl fmt::Debug for Node { } write!(fmt, "; {})", weight) } - Node::LeafNode(Lnode{ ref text, len }) => { + Node::LeafNode(Lnode{ ref text, len, .. }) => { unsafe { write!(fmt, - "\"{}\"; {}", + "(\"{}\"; {})", ::std::str::from_utf8(::std::slice::from_raw_buf(text, len)).unwrap(), len) } @@ -375,6 +454,7 @@ enum Node { #[derive(Clone, Eq, PartialEq)] struct Inode { weight: usize, + src_weight: usize, left: Option>, right: Option>, } @@ -383,6 +463,8 @@ struct Inode { struct Lnode { text: *const u8, len: usize, + // text + src_offset = src text (src_offset should always be <= 0) + src_offset: isize, } impl Node { @@ -390,25 +472,29 @@ impl Node { Node::InnerNode(Inode { left: None, right: None, - weight: 0 + weight: 0, + src_weight: 0, }) } fn new_inner(left: Option>, right: Option>, - weight: usize) + weight: usize, + src_weight: usize) -> Node { Node::InnerNode(Inode { left: left, right: right, - weight: weight + weight: weight, + src_weight: src_weight, }) } - fn new_leaf(text: *const u8, len: usize) -> Node { + fn new_leaf(text: *const u8, len: usize, src_offset: isize) -> Node { Node::LeafNode(Lnode { text: text, - len: len + len: len, + src_offset: src_offset, }) } @@ -424,23 +510,77 @@ impl Node { } } + fn fix_src(&mut self) { + match *self { + Node::InnerNode(ref mut i) => i.fix_src(), + Node::LeafNode(ref mut l) => { + l.src_offset = 0; + }, + } + } + + // All these methods are just doing dynamic dispatch, TODO use a macro + // precond: start < end - fn remove(&mut self, start: usize, end: usize, offset: usize) -> NodeAction { - if end < offset { - // The span to remove is to the left of this node. - return NodeAction::None; + fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { + match *self { + Node::InnerNode(ref mut i) => i.remove(start, end, src_start), + Node::LeafNode(ref mut l) => l.remove(start, end, src_start), + } + } + + fn src_remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { + match *self { + Node::InnerNode(ref mut i) => i.src_remove(start, end, src_start), + Node::LeafNode(ref mut l) => { + debug!("src_remove: pre-adjust {}-{}; {}", start, end, l.src_offset); + let mut start = start as isize + l.src_offset; + if start < 0 { + start = 0; + } + let mut end = end as isize + l.src_offset; + if end < 0 { + end = 0; + } + // TODO src_start? + let mut src_start = src_start as isize + l.src_offset; + if src_start < 0 { + src_start = 0; + } + debug!("src_remove: post-adjust {}-{}, {}", start, end, src_start); + if end > start { + l.remove(start as usize, end as usize, src_start as usize) + } else { + NodeAction::None + } + } } + } + fn insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { match *self { - Node::InnerNode(ref mut i) => i.remove(start, end, offset), - Node::LeafNode(ref mut l) => l.remove(start, end, offset), + Node::InnerNode(ref mut i) => i.insert(node, start, src_start), + Node::LeafNode(ref mut l) => l.insert(node, start, src_start), } } - fn insert(&mut self, node: Box, start: usize) -> NodeAction { + fn src_insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { match *self { - Node::InnerNode(ref mut i) => i.insert(node, start), - Node::LeafNode(ref mut l) => l.insert(node, start), + Node::InnerNode(ref mut i) => i.src_insert(node, start, src_start), + Node::LeafNode(ref mut l) => { + debug!("src_insert: pre-adjust {}, {}; {}", start, src_start, l.src_offset); + let mut start = start as isize + l.src_offset; + if start < 0 { + start = 0; + } + // TODO src_start? + let mut src_start = src_start as isize + l.src_offset; + if src_start < 0 { + src_start = 0; + } + debug!("src_insert: post-adjust {}, {}", start, src_start); + l.insert(node, start as usize, src_start as usize) + } } } @@ -451,15 +591,50 @@ impl Node { } } + fn find_src_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { + match *self { + Node::InnerNode(ref i) => i.find_src_slice(start, end, slice), + Node::LeafNode(ref l) => { + debug!("find_src_slice: pre-adjust {}-{}; {}", start, end, l.src_offset); + let mut start = start as isize + l.src_offset; + if start < 0 { + start = 0; + } + let mut end = end as isize + l.src_offset; + if end < 0 { + end = 0; + } + debug!("find_src_slice: post-adjust {}-{}", start, end); + if end > start { + l.find_slice(start as usize, end as usize, slice); + } + } + } + } + fn replace(&mut self, start: usize, new_str: &str) { match *self { Node::InnerNode(ref mut i) => i.replace(start, new_str), Node::LeafNode(ref mut l) => l.replace(start, new_str), } } + + fn col_for_src_loc(&self, src_loc: usize) -> Search { + match *self { + Node::InnerNode(ref i) => i.col_for_src_loc(src_loc), + Node::LeafNode(ref l) => l.col_for_src_loc(src_loc), + } + } + + fn find_last_char(&self, c: char) -> Option { + match *self { + Node::InnerNode(ref i) => i.find_last_char(c), + Node::LeafNode(ref l) => l.find_last_char(c), + } + } } -#[derive(Show, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] enum NodeAction { None, Remove, @@ -468,28 +643,113 @@ enum NodeAction { } impl Inode { - // precond: start < end && end >= offset - fn remove(&mut self, start: usize, end: usize, offset: usize) -> NodeAction { - debug!("Inode::remove: {}, {}, {}, {}", start, end, offset, self.weight); - if start >= offset + self.weight { - // The removal cannot affect our left side. - match self.right { - Some(_) => {} - None => {} + fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { + debug!("Inode::remove: {}, {}, {}", start, end, self.weight); + + let left_action = if start <= self.weight { + if let Some(ref mut left) = self.left { + left.remove(start, end, src_start) + } else { + panic!(); } + } else { + NodeAction::None + }; + + let right_action = if end > self.weight { + if let Some(ref mut right) = self.right { + let start = if start < self.weight { + 0 + } else { + start - self.weight + }; + let src_start = if src_start < self.src_weight { + 0 + } else { + src_start - self.src_weight + }; + right.remove(start, end - self.weight, src_start) + } else { + panic!(); + } + } else { + NodeAction::None + }; + + + if left_action == NodeAction::Remove && right_action == NodeAction::Remove || + left_action == NodeAction::Remove && self.right.is_none() || + right_action == NodeAction::Remove && self.left.is_none() { + return NodeAction::Remove; } - let left_action = if let Some(ref mut left) = self.left { - left.remove(start, end, offset) + if left_action == NodeAction::Remove { + return NodeAction::Change(self.right.clone().unwrap(), + -(self.weight as isize)); + } + if right_action == NodeAction::Remove { + return NodeAction::Change(self.left.clone().unwrap(), + -(self.right.as_ref().map(|n| n.len()).unwrap() as isize)); + } + + let mut total_adj = 0; + if let NodeAction::Change(ref n, adj) = left_action { + self.left = Some(n.clone()); + self.weight = (self.weight as isize + adj) as usize; + total_adj += adj; + } + if let NodeAction::Change(ref n, adj) = right_action { + self.right = Some(n.clone()); + total_adj += adj; + } + + if let NodeAction::Adjust(adj) = left_action { + self.weight = (self.weight as isize + adj) as usize; + total_adj += adj; + } + if let NodeAction::Adjust(adj) = right_action { + total_adj += adj; + } + + return NodeAction::Adjust(total_adj); + } + + fn src_remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { + // TODO refactor with remove + + debug!("Inode::src_remove: {}, {}, {}/{}", start, end, self.src_weight, self.weight); + + let left_action = if start <= self.src_weight { + if let Some(ref mut left) = self.left { + left.src_remove(start, end, src_start) + } else { + panic!(); + } } else { NodeAction::None }; - let right_action = if let Some(ref mut right) = self.right { - right.remove(start, end, offset + self.weight) + + let right_action = if end > self.src_weight { + if let Some(ref mut right) = self.right { + let start = if start < self.src_weight { + 0 + } else { + start - self.src_weight + }; + let src_start = if src_start < self.src_weight { + 0 + } else { + src_start - self.src_weight + }; + right.src_remove(start, end - self.src_weight, src_start) + } else { + panic!(); + } } else { NodeAction::None }; + if left_action == NodeAction::Remove && right_action == NodeAction::Remove || left_action == NodeAction::Remove && self.right.is_none() || right_action == NodeAction::Remove && self.left.is_none() { @@ -527,11 +787,11 @@ impl Inode { return NodeAction::Adjust(total_adj); } - fn insert(&mut self, node: Box, start: usize) -> NodeAction { + fn insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { let mut total_adj = 0; - if start < self.weight { + if start <= self.weight { let action = if let Some(ref mut left) = self.left { - left.insert(node, start) + left.insert(node, start, src_start) } else { assert!(self.weight == 0); let len = node.len() as isize; @@ -553,7 +813,53 @@ impl Inode { } else { let action = if let Some(ref mut right) = self.right { assert!(start >= self.weight); - right.insert(node, start - self.weight) + assert!(src_start >= self.src_weight); + right.insert(node, start - self.weight, src_start - self.src_weight) + } else { + let len = node.len() as isize; + NodeAction::Change(node, len) + }; + + match action { + NodeAction::Change(n, adj) => { + self.right = Some(n); + total_adj += adj; + } + NodeAction::Adjust(adj) => total_adj += adj, + _ => panic!("Unexpected action"), + } + } + + NodeAction::Adjust(total_adj) + } + + fn src_insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { + let mut total_adj = 0; + if start <= self.src_weight { + let action = if let Some(ref mut left) = self.left { + left.src_insert(node, start, src_start) + } else { + let len = node.len() as isize; + NodeAction::Change(node, len) + }; + + match action { + NodeAction::Change(n, adj) => { + self.left = Some(n); + self.weight += adj as usize; + total_adj += adj; + } + NodeAction::Adjust(adj) => { + self.weight += adj as usize; + total_adj += adj; + } + _ => panic!("Unexpected action"), + } + } else { + let action = if let Some(ref mut right) = self.right { + assert!(start >= self.src_weight); + assert!(src_start >= self.src_weight); + right.src_insert(node, start - self.src_weight, src_start - self.src_weight) } else { let len = node.len() as isize; NodeAction::Change(node, len) @@ -587,6 +893,21 @@ impl Inode { } } + fn find_src_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { + debug!("Inode::find_src_slice: {}, {}, {}", start, end, self.src_weight); + if start < self.src_weight && self.left.is_some() { + self.left.as_ref().unwrap().find_src_slice(start, end, slice); + } + if end > self.src_weight && self.right.is_some() { + let start = if start < self.src_weight { + 0 + } else { + start - self.src_weight + }; + self.right.as_ref().unwrap().find_src_slice(start, end - self.src_weight, slice) + } + } + fn replace(&mut self, start: usize, new_str: &str) { debug!("Inode::replace: {}, {}, {}", start, new_str, self.weight); let end = start + new_str.len(); @@ -610,52 +931,124 @@ impl Inode { } } } + + fn fix_src(&mut self) { + self.src_weight = self.weight; + if let Some(ref mut left) = self.left { + left.fix_src(); + } + if let Some(ref mut right) = self.right { + right.fix_src(); + } + } + + fn col_for_src_loc(&self, src_loc: usize) -> Search { + debug!("Inode::col_for_src_loc: {}, {}", src_loc, self.src_weight); + let result = if src_loc < self.src_weight { + if self.left.is_some() { + Some(self.left.as_ref().unwrap().col_for_src_loc(src_loc)) + } else { + None + } + } else { + None + }; + if result.is_none() { + if self.right.is_some() { + match self.right.as_ref().unwrap().col_for_src_loc(src_loc - self.src_weight) { + Search::Continue(c) if self.left.is_some() => { + // TODO broken - need number of chars, not bytes + match self.left.as_ref().unwrap().find_last_char('\n') { + Some(l) => { + Search::Done((self.weight - l - 1) + c) + } + None => { + Search::Continue(c + self.weight) + } + } + } + result => result, + } + } else { + panic!("Can't look up source location"); + } + } else { + // TODO don't do it this way + result.unwrap() + } + } + + fn find_last_char(&self, c: char) -> Option { + // TODO use map or something + match self.right { + Some(ref right) => match right.find_last_char(c) { + Some(x) => return Some(x), + None => {}, + }, + None => {} + } + match self.left { + Some(ref left) => match left.find_last_char(c) { + Some(x) => return Some(x), + None => {}, + }, + None => {} + } + None + } } impl Lnode { - // precond: start < end && end >= offset - fn remove(&mut self, start: usize, end: usize, offset: usize) -> NodeAction { - debug!("Lnode::remove: {}, {}, {}, {}", start, end, offset, self.len); - if start > offset + self.len { - // The span to remove is to the right of this node. - return NodeAction::None; - } + fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { + debug!("Lnode::remove: {}, {}, {}", start, end, self.len); + assert!(start <= self.len); - if start <= offset && end >= offset + self.len { + if start == 0 && end >= self.len { // The removal span includes us, remove ourselves. return NodeAction::Remove; } let old_len = self.len; - if start <= offset { + if start == 0 { // Truncate the left of the node. - self.text = (self.text as usize + (end - offset)) as *const u8; - self.len = old_len - (end - offset); - return NodeAction::Adjust(self.len as isize - old_len as isize); + self.text = (self.text as usize + end) as *const u8; + self.len = old_len - end; + let delta = self.len as isize - old_len as isize; + self.src_offset += delta; + return NodeAction::Adjust(delta); } - if end >= offset + self.len { + if end >= self.len { // Truncate the right of the node. - self.len = start - offset; + self.len = start; return NodeAction::Adjust(self.len as isize - old_len as isize); } + let delta = -((end - start) as isize); // Split the node (span to remove is in the middle of the node). let new_node = Node::new_inner( - Some(box Node::new_leaf(self.text, start - offset)), - Some(box Node::new_leaf((self.text as usize + (end - offset)) as *const u8, - old_len - (end - offset))), - start - offset); - return NodeAction::Change(box new_node, -((end - start) as isize)); + Some(box Node::new_leaf(self.text, start, self.src_offset)), + Some(box Node::new_leaf((self.text as usize + end) as *const u8, + old_len - end, + self.src_offset + delta)), + start, + src_start); + return NodeAction::Change(box new_node, delta); } - fn insert(&mut self, node: Box, start: usize) -> NodeAction { + fn insert(&mut self, mut node: Box, start: usize, src_start: usize) -> NodeAction { + match node { + box Node::LeafNode(ref mut node) => node.src_offset = self.src_offset, + _ => panic!() + } + let len = node.len(); if start == 0 { // Insert at the start of the node let new_node = box Node::new_inner(Some(node), Some(box Node::LeafNode(self.clone())), - len); + len, + 0); return NodeAction::Change(new_node, len as isize) } @@ -663,33 +1056,33 @@ impl Lnode { // Insert at the end of the node let new_node = box Node::new_inner(Some(box Node::LeafNode(self.clone())), Some(node), + self.len, self.len); return NodeAction::Change(new_node, len as isize) } // Insert into the middle of the node - let left = Some(box Node::new_leaf(self.text, start)); - let new_left = box Node::new_inner(left, Some(node), start); + let left = Some(box Node::new_leaf(self.text, start, self.src_offset)); + let new_left = box Node::new_inner(left, Some(node), start, src_start); let right = Some(box Node::new_leaf((self.text as usize + (start)) as *const u8, - self.len - (start))); - let new_node = box Node::new_inner(Some(new_left), right, start + len); + self.len - start, + self.src_offset)); + let new_node = box Node::new_inner(Some(new_left), right, start + len, src_start); return NodeAction::Change(new_node, len as isize) } fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { - debug!("Lnode::find_slice: {}, {}, {}", start, end, self.len); + debug!("Lnode::find_slice: {}, {}, {}, {}", start, end, self.len, self.src_offset); debug_assert!(start < self.len, "Shouldn't have called this fn, we're out of bounds"); slice.nodes.push(self); - let mut len = end; + let mut len = ::std::cmp::min(end, self.len); if start > 0 { slice.start = start; len -= start; } - if end <= self.len { - slice.len = len; - } + slice.len = len; } fn replace(&mut self, start: usize, new_str: &str) { @@ -700,4 +1093,62 @@ impl Lnode { ::std::intrinsics::copy_nonoverlapping_memory(addr, &new_str.as_bytes()[0], new_str.len()); } } + + fn col_for_src_loc(&self, src_loc: usize) -> Search { + debug!("Lnode::col_for_src_loc {}; {}; {}", src_loc, self.len, self.src_offset); + let loc = if (src_loc as isize) > (self.len as isize - self.src_offset) { + // The source location we are looking up has been removed + self.len as isize + } else { + (src_loc as isize + self.src_offset) + }; + + // FIXME if '/n' as u8 is part of a multi-byte grapheme, then this will + // cause false positives. + let mut i = loc - 1; + while i >= 0 { + unsafe { + let c = *((self.text as usize + i as usize) as *const u8); + if c as char == '\n' { + debug!("Lnode::col_for_src_loc, return Done({})", loc - i - 1); + return Search::Done((loc - i - 1) as usize) + } + } + i -= 1; + } + + let loc = if loc < 0 { + 0 + } else { + loc as usize + }; + debug!("Lnode::col_for_src_loc, return Continue({})", loc); + Search::Continue(loc) + } + + fn find_last_char(&self, needle: char) -> Option { + // FIXME due to multi-byte chars, this will give false positives + // I think we must search forwards from the start :-( Perhaps we could + // track unicode vs ascii or something (I don't think there is an efficient + // way to read unicode backwards, I might be wrong). + // std::str::GraphemeIndices can do this! + let mut loc = self.len as isize - 1; + while loc >= 0 { + unsafe { + let c = *((self.text as usize + loc as usize) as *const u8); + if c as char == needle { + return Some(loc as usize) + } + } + loc -= 1; + } + + return None + } +} + +//TODO comment etc. +enum Search { + Continue(usize), + Done(usize) } -- cgit 1.4.1-3-g733a5 From 7417ab5aed7336cfc961e067cadf9114bb426a3d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 8 Mar 2015 11:46:35 +1300 Subject: Working prototype Implements a few formatting options using an approach where we modify the source using a rope. Uses very ad-hoc rules for formatting. --- Cargo.toml | 17 +++ src/changes.rs | 57 ++++--- src/mod.rs | 468 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rope.rs | 335 ++++++++++++++++++++++++++++------------- 4 files changed, 751 insertions(+), 126 deletions(-) create mode 100644 Cargo.toml create mode 100644 src/mod.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000000..31edfbbdc06 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] + +name = "rustfmt" +version = "0.0.1" +authors = ["Nicholas Cameron "] +description = "tool to find and fix Rust formatting issues" +repository = "https://github.com/nick29581/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" + +#[dependencies.reprint] +#reprint = "0.0.1" +#path = "/home/ncameron/reprint" + +[[bin]] +name = "rustfmt" +path = "src/mod.rs" diff --git a/src/changes.rs b/src/changes.rs index 22fdc0ff51d..bcfbed17f5b 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -8,33 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // TODO -// composable changes // print to files (maybe that shouldn't be here, but in mod) // tests -// docs use rope::{Rope, RopeSlice}; use std::collections::HashMap; -use syntax::codemap::{CodeMap, Span, Pos, BytePos}; +use syntax::codemap::{CodeMap, Span, BytePos}; use std::fmt; +// This is basically a wrapper around a bunch of Ropes which makes it convenient +// to work with libsyntax. It is badly named. pub struct ChangeSet<'a> { file_map: HashMap, - // FIXME, we only keep a codemap around so we can have convenience methods - // taking Spans, it would be more resuable to factor this (and the methods) - // out into an adaptor. codemap: &'a CodeMap, pub count: u64, } -pub struct FileIterator<'c, 'a: 'c> { - change_set: &'c ChangeSet<'a>, - keys: Vec<&'c String>, - cur_key: usize, -} - impl<'a> ChangeSet<'a> { + // Create a new ChangeSet for a given libsyntax CodeMap. pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> { let mut result = ChangeSet { file_map: HashMap::new(), @@ -43,14 +36,16 @@ impl<'a> ChangeSet<'a> { }; for f in codemap.files.borrow().iter() { - let contents = Rope::from_string(f.src.clone()); + let contents = Rope::from_string((&**f.src.as_ref().unwrap()).clone()); result.file_map.insert(f.name.clone(), contents); } result } - // start and end are unadjusted. + // Change a span of text in our stored text into the new text (`text`). + // The span of text to change is given in the coordinates of the original + // source text, not the current text, pub fn change(&mut self, file_name: &str, start: usize, end: usize, text: String) { println!("change: {}:{}-{} \"{}\"", file_name, start, end, text); @@ -59,9 +54,10 @@ impl<'a> ChangeSet<'a> { let file = &mut self.file_map[*file_name]; if end - start == text.len() { - // TODO - panic!(); - file.replace_str(start, &text[]); + // TODO src_replace_str would be much more efficient + //file.src_replace_str(start, &text); + file.src_remove(start, end); + file.src_insert(start, text); } else { // TODO if we do this in one op, could we get better change info? file.src_remove(start, end); @@ -69,28 +65,34 @@ impl<'a> ChangeSet<'a> { } } + // As for `change()`, but use a Span to indicate the text to change. pub fn change_span(&mut self, span: Span, text: String) { let l_loc = self.codemap.lookup_char_pos(span.lo); let file_offset = l_loc.file.start_pos.0; - self.change(&l_loc.file.name[], + self.change(&l_loc.file.name, (span.lo.0 - file_offset) as usize, (span.hi.0 - file_offset) as usize, text) } + // Get a slice of the current text. Coordinates are relative to the source + // text. I.e., this method returns the text which has been changed from the + // indicated span. pub fn slice(&self, file_name: &str, start: usize, end: usize) -> RopeSlice { let file = &self.file_map[*file_name]; file.src_slice(start..end) } + // As for `slice()`, but use a Span to indicate the text to return. pub fn slice_span(&self, span:Span) -> RopeSlice { let l_loc = self.codemap.lookup_char_pos(span.lo); let file_offset = l_loc.file.start_pos.0; - self.slice(&l_loc.file.name[], + self.slice(&l_loc.file.name, (span.lo.0 - file_offset) as usize, (span.hi.0 - file_offset) as usize) } + // Return an iterator over the entire changed text. pub fn text<'c>(&'c self) -> FileIterator<'c, 'a> { FileIterator { change_set: self, @@ -99,16 +101,26 @@ impl<'a> ChangeSet<'a> { } } + // Get the current line-relative position of a position in the source text. pub fn col(&self, loc: BytePos) -> usize { let l_loc = self.codemap.lookup_char_pos(loc); let file_offset = l_loc.file.start_pos.0; - let file = &self.file_map[l_loc.file.name[]]; + let file = &self.file_map[l_loc.file.name[..]]; file.col_for_src_loc(loc.0 as usize - file_offset as usize) } } +// Iterates over each file in the ChangSet. Yields the filename and the changed +// text for that file. +pub struct FileIterator<'c, 'a: 'c> { + change_set: &'c ChangeSet<'a>, + keys: Vec<&'c String>, + cur_key: usize, +} + impl<'c, 'a> Iterator for FileIterator<'c, 'a> { type Item = (&'c str, &'c Rope); + fn next(&mut self) -> Option<(&'c str, &'c Rope)> { if self.cur_key >= self.keys.len() { return None; @@ -116,15 +128,16 @@ impl<'c, 'a> Iterator for FileIterator<'c, 'a> { let key = self.keys[self.cur_key]; self.cur_key += 1; - return Some((&key[], &self.change_set.file_map[*key])) + return Some((&key, &self.change_set.file_map[*key])) } } impl<'a> fmt::Display for ChangeSet<'a> { + // Prints the entire changed text. fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { for (f, r) in self.text() { try!(write!(fmt, "{}:\n", f)); - try!(write!(fmt, "{}", r)); + try!(write!(fmt, "{}\n\n", r)); } Ok(()) } diff --git a/src/mod.rs b/src/mod.rs new file mode 100644 index 00000000000..c0bad7a0e31 --- /dev/null +++ b/src/mod.rs @@ -0,0 +1,468 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![feature(box_patterns)] +#![feature(rustc_private)] +#![feature(collections)] +#![feature(os)] +#![feature(core)] +#![feature(unicode)] +#![feature(old_path)] +#![feature(exit_status)] + +#[macro_use] +extern crate log; + +extern crate getopts; +extern crate rustc; +extern crate rustc_driver; +extern crate syntax; + +use rustc::session::Session; +use rustc::session::config::{self, Input}; +use rustc_driver::{driver, CompilerCalls, Compilation}; + +use syntax::ast; +use syntax::codemap::{self, CodeMap, Span, Pos}; +use syntax::diagnostics; +use syntax::parse::token; +use syntax::print::pprust; +use syntax::visit; + +use std::mem; + +use changes::ChangeSet; + +pub mod rope; +mod changes; + +const IDEAL_WIDTH: usize = 80; +const MAX_WIDTH: usize = 100; +const MIN_STRING: usize = 10; + +// Formatting which depends on the AST. +fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { + let mut visitor = FmtVisitor { codemap: codemap, + changes: ChangeSet::from_codemap(codemap) }; + visit::walk_crate(&mut visitor, krate); + + visitor.changes +} + +// Formatting done on a char by char basis. +fn fmt_lines(changes: &mut ChangeSet) { + // Iterate over the chars in the change set. + for (f, text) in changes.text() { + let mut trims = vec![]; + let mut last_wspace = None; + let mut line_len = 0; + let mut cur_line = 1; + for (c, b) in text.chars() { + if c == '\n' { // TOOD test for \r too + // Check for (and record) trailing whitespace. + if let Some(lw) = last_wspace { + trims.push((lw, b)); + line_len -= b - lw; + } + // Check for any line width errors we couldn't correct. + if line_len > MAX_WIDTH { + // FIXME store the error rather than reporting immediately. + println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", + f, cur_line, MAX_WIDTH); + } + line_len = 0; + cur_line += 1; + last_wspace = None; + } else { + line_len += 1; + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(b); + } + } else { + last_wspace = None; + } + } + } + + unsafe { + // Invariant: we only mutate a rope after we have searched it, then + // we will not search it again. + let mut_text: &mut rope::Rope = mem::transmute(text); + let mut_count: &mut u64 = mem::transmute(&changes.count); + let mut offset = 0; + // Get rid of any trailing whitespace we recorded earlier. + for &(s, e) in trims.iter() { + // Note that we change the underlying ropes directly, we don't + // go through the changeset because our change positions are + // relative to the newest text, not the original. + debug!("Stripping trailing whitespace {}:{}-{} \"{}\"", + f, s, e, text.slice(s-offset..e-offset)); + mut_text.remove(s-offset, e-offset); + *mut_count += 1; + offset += e - s; + } + } + } +} + +struct FmtVisitor<'a> { + codemap: &'a CodeMap, + changes: ChangeSet<'a>, +} + +impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { + fn visit_expr(&mut self, ex: &'v ast::Expr) { + match ex.node { + ast::Expr_::ExprLit(ref l) => match l.node { + ast::Lit_::LitStr(ref is, _) => { + self.rewrite_string(&is, l.span); + } + _ => {} + }, + _ => {} + } + + visit::walk_expr(self, ex) + } + + fn visit_fn(&mut self, + fk: visit::FnKind<'v>, + fd: &'v ast::FnDecl, + b: &'v ast::Block, + s: Span, + _: ast::NodeId) { + self.fix_formal_args(fd); + visit::walk_fn(self, fk, fd, b, s); + } + + fn visit_item(&mut self, item: &'v ast::Item) { + // TODO check each item is on a new line and is correctly indented. + match item.node { + ast::Item_::ItemUse(ref vp) => { + match vp.node { + ast::ViewPath_::ViewPathList(ref path, ref path_list) => { + let new_str = self.fix_use_list(path, path_list, vp.span); + + // TODO move these optimisations to ChangeSet + if new_str != self.codemap.span_to_snippet(item.span).unwrap() { + self.changes.change_span(item.span, new_str); + } + } + ast::ViewPath_::ViewPathGlob(_) => { + // FIXME convert to list? + } + _ => {} + } + } + _ => {} + } + visit::walk_item(self, item); + } +} + +fn make_indent(width: usize) -> String { + let mut indent = String::with_capacity(width); + for _ in 0..width { + indent.push(' ') + } + indent +} + +impl<'a> FmtVisitor<'a> { + // TODO NEEDS TESTS + fn rewrite_string(&mut self, s: &str, span: Span) { + // FIXME I bet this stomps unicode escapes in the source string + + // Check if there is anything to fix: we always try to fixup multi-line + // strings, or if the string is too long for the line. + let l_loc = self.codemap.lookup_char_pos(span.lo); + let r_loc = self.codemap.lookup_char_pos(span.hi); + if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH { + return; + } + + // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) + + let s = s.escape_default(); + + // TODO use fixed value. + let l_loc = self.codemap.lookup_char_pos(span.lo); + let l_col = l_loc.col.to_usize(); + + let indent = make_indent(l_col + 1); + let indent = &indent; + + let max_chars = MAX_WIDTH - (l_col + 1); + + let mut cur_start = 0; + let mut result = String::new(); + result.push('"'); + loop { + let mut cur_end = cur_start + max_chars; + + if cur_end >= s.len() { + result.push_str(&s[cur_start..]); + break; + } + + // Make sure we're on a char boundary. + cur_end = next_char(&s, cur_end); + + // Push cur_end left until we reach whitespace + while !s.char_at(cur_end-1).is_whitespace() { + cur_end = prev_char(&s, cur_end); + + if cur_end - cur_start < MIN_STRING { + // We can't break at whitespace, fall back to splitting + // anywhere that doesn't break an escape sequence + cur_end = next_char(&s, cur_start + max_chars); + while s.char_at(cur_end) == '\\' { + cur_end = prev_char(&s, cur_end); + } + } + } + // Make sure there is no whitespace to the right of the break. + while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { + cur_end = next_char(&s, cur_end+1); + } + result.push_str(&s[cur_start..cur_end]); + result.push_str("\\\n"); + result.push_str(indent); + + cur_start = cur_end; + } + result.push('"'); + + // Check that we actually changed something. + if result == self.codemap.span_to_snippet(span).unwrap() { + return; + } + + self.changes.change_span(span, result); + } + + // Basically just pretty prints a multi-item import. + fn fix_use_list(&mut self, + path: &ast::Path, + path_list: &[ast::PathListItem], + vp_span: Span) -> String { + // FIXME remove unused imports + + // FIXME check indentation + let l_loc = self.codemap.lookup_char_pos(vp_span.lo); + let path_str = pprust::path_to_string(&path); + let indent = l_loc.col.0; + // After accounting for the overhead, how much space left for + // the item list? ( 5 = :: + { + } + ; ) + let space = IDEAL_WIDTH - (indent + path_str.len() + 5); + // 4 = `use` + one space + // TODO might be pub use + let indent = make_indent(indent-4); + + let mut cur_str = String::new(); + let mut first = true; + // If `self` is in the list, put it first. + if path_list.iter().any(|vpi| + if let ast::PathListItem_::PathListMod{ .. } = vpi.node { + true + } else { + false + } + ) { + cur_str = "self".to_string(); + first = false; + } + + let mut new_str = String::new(); + for vpi in path_list.iter() { + match vpi.node { + ast::PathListItem_::PathListIdent{ name, .. } => { + let next_item = &token::get_ident(name); + if cur_str.len() + next_item.len() > space { + let cur_line = format!("{}use {}::{{{}}};\n", indent, path_str, cur_str); + new_str.push_str(&cur_line); + + cur_str = String::new(); + first = true; + } + + if first { + first = false; + } else { + cur_str.push_str(", "); + } + + cur_str.push_str(next_item); + } + ast::PathListItem_::PathListMod{ .. } => {} + } + } + + assert!(!first); + let cur_line = format!("{}use {}::{{{}}};", indent, path_str, cur_str); + new_str.push_str(&cur_line); + + new_str + } + + fn fix_formal_args<'v>(&mut self, fd: &'v ast::FnDecl) { + // For now, just check the arguments line up and make them per-row if the line is too long. + let args = &fd.inputs; + if args.len() <= 1 { + return; + } + // TODO not really using the hi positions + let spans: Vec<_> = args.iter().map(|a| (a.pat.span.lo, a.ty.span.hi)).collect(); + let locs: Vec<_> = spans.iter().map(|&(a, b)| (self.codemap.lookup_char_pos(a), self.codemap.lookup_char_pos(b))).collect(); + let first_loc = &locs[0].0; + // TODO need to adjust for previous changes here. + let same_row = locs.iter().all(|&(ref l, _)| l.line == first_loc.line); + let same_col = locs.iter().all(|&(ref l, _)| l.col == first_loc.col); + + if same_col { + // TODO Check one arg per line and no lines in between (except comments) + return; + } + + if same_row { // TODO check line is < 100 && first_loc.line { + // TODO could also fix whitespace around punctuaton here + // TODO and could check that we're on the same line as the function call, if possible + return; + } + + let col = self.changes.col(spans[0].0); + let mut indent = String::with_capacity(col); + indent.push('\n'); + for _ in 0..col { indent.push(' '); } + let last_idx = spans.len() - 1; + for (i, s) in spans.iter().enumerate() { + // Take the span from lo to lo (or the last hi for the last arg), + // trim, push on top of indent, then replace the old lo-lo span with it. + let mut new_text = if i == 0 { + "".to_string() + } else { + indent.clone() + }; + let hi = if i == last_idx { + s.1 + } else { + spans[i+1].0 + }; + // TODO need a version of slice taking locs, not a span + let snippet = self.changes.slice_span(Span{ lo: s.0, hi: hi, expn_id: codemap::NO_EXPANSION }).to_string(); + let snippet = snippet.trim(); + new_text.push_str(snippet); + self.changes.change(&first_loc.file.name, (s.0).0 as usize, hi.0 as usize, new_text); + } + } +} + +#[inline] +fn prev_char(s: &str, mut i: usize) -> usize { + if i == 0 { return 0; } + + i -= 1; + while !s.is_char_boundary(i) { + i -= 1; + } + i +} + +#[inline] +fn next_char(s: &str, mut i: usize) -> usize { + if i >= s.len() { return s.len(); } + + while !s.is_char_boundary(i) { + i += 1; + } + i +} + +struct RustFmtCalls { + input_path: Option, +} + +impl<'a> CompilerCalls<'a> for RustFmtCalls { + fn early_callback(&mut self, + _: &getopts::Matches, + _: &diagnostics::registry::Registry) + -> Compilation { + Compilation::Continue + } + + fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { + match input_path { + Some(ref ip) => self.input_path = Some(ip.clone()), + _ => { + // FIXME should handle string input and write to stdout or something + panic!("No input path"); + } + } + (input, input_path) + } + + fn no_input(&mut self, + _: &getopts::Matches, + _: &config::Options, + _: &Option, + _: &Option, + _: &diagnostics::registry::Registry) + -> Option<(Input, Option)> { + panic!("No input supplied to RustFmt"); + } + + fn late_callback(&mut self, + _: &getopts::Matches, + _: &Session, + _: &Input, + _: &Option, + _: &Option) + -> Compilation { + Compilation::Continue + } + + fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { + let mut control = driver::CompileController::basic(); + control.after_parse.stop = Compilation::Stop; + control.after_parse.callback = box |state| { + let krate = state.krate.unwrap(); + let codemap = state.session.codemap(); + let mut changes = fmt_ast(krate, codemap); + fmt_lines(&mut changes); + + println!("Making {} changes", changes.count); + println!("{}", changes); + // FIXME(#5) Should be user specified whether to show or replace. + }; + + control + } +} + +fn main() { + let args = std::os::args(); + let mut call_ctxt = RustFmtCalls { input_path: None }; + rustc_driver::run_compiler(&args, &mut call_ctxt); + std::env::set_exit_status(0); +} + +// FIXME comments +// comments aren't in the AST, which makes processing them difficult, but then +// comments are complicated anyway. I think I am happy putting off tackling them +// for now. Long term the soluton is for comments to be in the AST, but that means +// only the libsyntax AST, not the rustc one, which means waiting for the ASTs +// to diverge one day.... + +// Once we do have comments, we just have to implement a simple word wrapping +// algorithm to keep the width under IDEAL_WIDTH. We should also convert multiline +// /* ... */ comments to // and check doc comments are in the right place and of +// the right kind. diff --git a/src/rope.rs b/src/rope.rs index 150e51b4bd3..5a96370308a 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -14,25 +14,31 @@ // tests // pull out into its own crate // impl Default, Extend -// impl DOubleEndedIter and ExactSizeIter for RopeChars +// impl DoubleEndedIter and ExactSizeIter for RopeChars // better allocation -// balancing -// thread safety/parallisation +// balancing? extern crate unicode; use std::fmt; use std::ops::Range; +use std::num::{SignedInt, Int}; -// A Rope, based on an unbalanced binary tree. - +// A Rope, based on an unbalanced binary tree. The rope is somewhat special in +// that it tracks positions in the source text. So when locating a position in +// the rope, the user can use either a current position in the text or a +// position in the source text, which the Rope will adjust to a current position +// whilst searching. pub struct Rope { root: Node, len: usize, src_len: usize, - // FIXME: Allocation is very dumb at the moment, we always add another buffer for every inserted string and we never resuse or collect old memory + // FIXME: Allocation is very dumb at the moment, we always add another + // buffer for every inserted string and we never resuse or collect old + // memory storage: Vec> } +// A view over a portion of a Rope. Analagous to string slices (`str`); pub struct RopeSlice<'rope> { // All nodes which make up the slice, in order. nodes: Vec<&'rope Lnode>, @@ -42,6 +48,7 @@ pub struct RopeSlice<'rope> { len: usize, } +// An iterator over the chars in a rope. pub struct RopeChars<'rope> { data: RopeSlice<'rope>, cur_node: usize, @@ -49,8 +56,8 @@ pub struct RopeChars<'rope> { abs_byte: usize, } - impl Rope { + // Create an empty rope. pub fn new() -> Rope { Rope { root: Node::empty_inner(), @@ -62,7 +69,7 @@ impl Rope { // Uses text as initial storage. pub fn from_string(text: String) -> Rope { - // TODO should split large texts into segments as we insert + // TODO should split very large texts into segments as we insert let mut result = Rope::new(); result.insert(0, text); @@ -70,47 +77,41 @@ impl Rope { result } + // When initialising a rope, indicates that the rope is complete wrt the + // source text. fn fix_src(&mut self) { self.root.fix_src(); self.src_len = self.len; } + // Length of the rope. pub fn len(&self) -> usize { self.len } - pub fn insert(&mut self, start: usize, text: String) { - if text.len() == 0 { - return; - } - - debug_assert!(start <= self.len(), "insertion out of bounds of rope"); - - let len = text.len(); - let storage = text.into_bytes(); - let new_node = box Node::new_leaf(&storage[][0] as *const u8, len, 0); - self.storage.push(storage); - - match self.root.insert(new_node, start, start) { - NodeAction::Change(n, adj) => { - assert!(adj as usize == len); - self.root = *n; - } - NodeAction::Adjust(adj) => { - assert!(adj as usize == len); - } - _ => panic!("Unexpected action") - } - self.len += len; - } - pub fn insert_copy(&mut self, start: usize, text: &str) { - // If we did clever things with allocation, we could do better here + // FIXME If we did clever things with allocation, we could do better here. self.insert(start, text.to_string()); } + pub fn insert(&mut self, start: usize, text: String) { + self.insert_inner(start, + text, + |this, node| this.root.insert(node, start, start)) + } + pub fn src_insert(&mut self, start: usize, text: String) { - // TODO refactor with insert + self.insert_inner(start, + text, + |this, node| this.root.src_insert(node, start, start)) + } + + fn insert_inner(&mut self, + start: usize, + text: String, + do_insert: F) + where F: Fn(&mut Rope, Box) -> NodeAction + { if text.len() == 0 { return; } @@ -119,10 +120,10 @@ impl Rope { let len = text.len(); let storage = text.into_bytes(); - let new_node = box Node::new_leaf(&storage[][0] as *const u8, len, 0); + let new_node = box Node::new_leaf(&storage[..][0] as *const u8, len, 0); self.storage.push(storage); - match self.root.src_insert(new_node, start, start) { + match do_insert(self, new_node) { NodeAction::Change(n, adj) => { assert!(adj as usize == len); self.root = *n; @@ -147,35 +148,25 @@ impl Rope { } pub fn remove(&mut self, start: usize, end: usize) { - assert!(end >= start); - if start == end { - return; - } - - let action = self.root.remove(start, end, start); - match action { - NodeAction::None => {} - NodeAction::Remove => { - self.root = Node::empty_inner(); - self.len = 0; - } - NodeAction::Adjust(adj) => self.len = (self.len as isize + adj) as usize, - NodeAction::Change(node, adj) => { - self.root = *node; - self.len = (self.len as isize + adj) as usize; - } - } + self.remove_inner(start, end, |this| this.root.remove(start, end, start)) } pub fn src_remove(&mut self, start: usize, end: usize) { - // TODO refactor with remove + self.remove_inner(start, end, |this| this.root.src_remove(start, end, start)) + } + + fn remove_inner(&mut self, + start: usize, + end: usize, + do_remove: F) + where F: Fn(&mut Rope) -> NodeAction + { assert!(end >= start); if start == end { return; } - let action = self.root.src_remove(start, end, start); - match action { + match do_remove(self) { NodeAction::None => {} NodeAction::Remove => { self.root = Node::empty_inner(); @@ -190,6 +181,7 @@ impl Rope { } // TODO src_replace + // TODO src_replace_str // This can go horribly wrong if you overwrite a grapheme of different size. // It is the callers responsibility to ensure that the grapheme at point start @@ -200,7 +192,7 @@ impl Rope { // I think that is better than duplicating a bunch of code. // It should be possible to view a &char as a &[u8] somehow, and then // we can optimise this (FIXME). - self.replace_str(start, &new_char.to_string()[]); + self.replace_str(start, &new_char.to_string()[..]); } pub fn replace_str(&mut self, start: usize, new_str: &str) { @@ -332,6 +324,10 @@ impl ::std::str::FromStr for Rope { impl<'a> fmt::Display for RopeSlice<'a> { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + if self.nodes.len() == 0 { + return Ok(()); + } + let last_idx = self.nodes.len() - 1; for (i, n) in self.nodes.iter().enumerate() { let mut ptr = n.text; @@ -346,7 +342,7 @@ impl<'a> fmt::Display for RopeSlice<'a> { unsafe { try!(write!(fmt, "{}", - ::std::str::from_utf8(::std::slice::from_raw_buf(&ptr, len)).unwrap())); + ::std::str::from_utf8(::std::slice::from_raw_parts(ptr, len)).unwrap())); } } Ok(()) @@ -371,7 +367,7 @@ impl<'a> fmt::Debug for RopeSlice<'a> { unsafe { try!(write!(fmt, "\"{}\"", - ::std::str::from_utf8(::std::slice::from_raw_buf(&ptr, len)).unwrap())); + ::std::str::from_utf8(::std::slice::from_raw_parts(ptr, len)).unwrap())); } } Ok(()) @@ -408,7 +404,7 @@ impl fmt::Display for Node { unsafe { write!(fmt, "{}", - ::std::str::from_utf8(::std::slice::from_raw_buf(text, len)).unwrap()) + ::std::str::from_utf8(::std::slice::from_raw_parts(*text, len)).unwrap()) } } } @@ -437,7 +433,7 @@ impl fmt::Debug for Node { unsafe { write!(fmt, "(\"{}\"; {})", - ::std::str::from_utf8(::std::slice::from_raw_buf(text, len)).unwrap(), + ::std::str::from_utf8(::std::slice::from_raw_parts(*text, len)).unwrap(), len) } } @@ -519,7 +515,7 @@ impl Node { } } - // All these methods are just doing dynamic dispatch, TODO use a macro + // Most of these methods are just doing dynamic dispatch, TODO use a macro // precond: start < end fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { @@ -534,19 +530,9 @@ impl Node { Node::InnerNode(ref mut i) => i.src_remove(start, end, src_start), Node::LeafNode(ref mut l) => { debug!("src_remove: pre-adjust {}-{}; {}", start, end, l.src_offset); - let mut start = start as isize + l.src_offset; - if start < 0 { - start = 0; - } - let mut end = end as isize + l.src_offset; - if end < 0 { - end = 0; - } - // TODO src_start? - let mut src_start = src_start as isize + l.src_offset; - if src_start < 0 { - src_start = 0; - } + let start = minz(start as isize + l.src_offset); + let end = minz(end as isize + l.src_offset); + let src_start = minz(src_start as isize + l.src_offset); debug!("src_remove: post-adjust {}-{}, {}", start, end, src_start); if end > start { l.remove(start as usize, end as usize, src_start as usize) @@ -569,15 +555,8 @@ impl Node { Node::InnerNode(ref mut i) => i.src_insert(node, start, src_start), Node::LeafNode(ref mut l) => { debug!("src_insert: pre-adjust {}, {}; {}", start, src_start, l.src_offset); - let mut start = start as isize + l.src_offset; - if start < 0 { - start = 0; - } - // TODO src_start? - let mut src_start = src_start as isize + l.src_offset; - if src_start < 0 { - src_start = 0; - } + let start = minz(start as isize + l.src_offset); + let src_start = minz(src_start as isize + l.src_offset); debug!("src_insert: post-adjust {}, {}", start, src_start); l.insert(node, start as usize, src_start as usize) } @@ -596,14 +575,8 @@ impl Node { Node::InnerNode(ref i) => i.find_src_slice(start, end, slice), Node::LeafNode(ref l) => { debug!("find_src_slice: pre-adjust {}-{}; {}", start, end, l.src_offset); - let mut start = start as isize + l.src_offset; - if start < 0 { - start = 0; - } - let mut end = end as isize + l.src_offset; - if end < 0 { - end = 0; - } + let start = minz(start as isize + l.src_offset); + let end = minz(end as isize + l.src_offset); debug!("find_src_slice: post-adjust {}-{}", start, end); if end > start { l.find_slice(start as usize, end as usize, slice); @@ -1117,21 +1090,14 @@ impl Lnode { i -= 1; } - let loc = if loc < 0 { - 0 - } else { - loc as usize - }; + let loc = minz(loc) as usize; debug!("Lnode::col_for_src_loc, return Continue({})", loc); Search::Continue(loc) } fn find_last_char(&self, needle: char) -> Option { // FIXME due to multi-byte chars, this will give false positives - // I think we must search forwards from the start :-( Perhaps we could - // track unicode vs ascii or something (I don't think there is an efficient - // way to read unicode backwards, I might be wrong). - // std::str::GraphemeIndices can do this! + // FIXME use std::str::GraphemeIndices to do this! let mut loc = self.len as isize - 1; while loc >= 0 { unsafe { @@ -1147,8 +1113,169 @@ impl Lnode { } } -//TODO comment etc. +// The state of searching through a rope. enum Search { + // TODO comment Continue(usize), + // TODO comment Done(usize) } + +fn minz(x: I) -> I { + if x.is_negative() { + return I::zero(); + } + + x +} + +#[cfg(test)] +mod test { + use super::*; + // FIXME is this a Rust bug? Why is minz not imported by the glob import? + use super::minz; + + #[test] + fn test_new() { + let r = Rope::new(); + assert!(r.len() == 0); + assert!(r.to_string() == ""); + + let r = Rope::from_string("Hello world!".to_string()); + assert!(r.len() == 12); + assert!(r.to_string() == "Hello world!"); + } + + #[test] + fn test_minz() { + let x: i32 = 0; + assert!(super::minz(x) == 0); + let x: i32 = 42; + assert!(minz(x) == 42); + let x: i32 = -42; + assert!(minz(x) == 0); + let x: isize = 0; + assert!(minz(x) == 0); + let x: isize = 42; + assert!(minz(x) == 42); + let x: isize = -42; + assert!(minz(x) == 0); + } + + #[test] + fn test_from_string() { + let mut r: Rope = "Hello world!".parse().unwrap(); + assert!(r.to_string() == "Hello world!"); + } + + #[test] + fn test_remove() { + let mut r: Rope = "Hello world!".parse().unwrap(); + r.remove(0, 10); + assert!(r.to_string() == "d!"); + assert!(r.src_slice(0..5).to_string() == ""); + assert!(r.src_slice(10..12).to_string() == "d!"); + + let mut r: Rope = "Hello world!".parse().unwrap(); + r.remove(4, 12); + assert!(r.to_string() == "Hell"); + // TODO + //assert!(r.src_slice(0..4).to_string() == "Hell"); + //assert!(r.src_slice(10..12).to_string() == ""); + + let mut r: Rope = "Hello world!".parse().unwrap(); + r.remove(4, 10); + assert!(r.to_string() == "Helld!"); + // TODO + //assert!(r.src_slice(1..5).to_string() == "ell"); + assert!(r.src_slice(9..12).to_string() == "d!"); + } + + #[test] + fn test_insert_copy() { + let mut r: Rope = "Hello world!".parse().unwrap(); + r.insert_copy(0, "foo"); + assert!(r.to_string() == "fooHello world!"); + assert!(r.slice(2..8).to_string() == "oHello"); + + let mut r: Rope = "Hello world!".parse().unwrap(); + r.insert_copy(12, "foo"); + assert!(r.to_string() == "Hello world!foo"); + assert!(r.slice(2..8).to_string() == "llo wo"); + + let mut r: Rope = "Hello world!".parse().unwrap(); + r.insert_copy(5, "foo"); + assert!(r.to_string() == "Hellofoo world!"); + assert!(r.slice(2..8).to_string() == "llofoo"); + } + + #[test] + fn test_push_copy() { + let mut r: Rope = "Hello world!".parse().unwrap(); + r.push_copy("foo"); + assert!(r.to_string() == "Hello world!foo"); + assert!(r.slice(2..8).to_string() == "llo wo"); + } + + #[test] + fn test_insert_replace() { + let mut r: Rope = "hello worl\u{00bb0}!".parse().unwrap(); + r.insert_copy(5, "bb"); + assert!(r.to_string() == "hellobb worlர!"); + r.replace(0, 'H'); + r.replace(15, '~'); + r.replace_str(5, "fo\u{00cb0}"); + assert!(r.to_string() == "Hellofoರrlர~"); + assert!(r.slice(0..10).to_string() == "Hellofoರ"); + assert!(r.slice(5..10).to_string() == "foರ"); + assert!(r.slice(10..15).to_string() == "rlர"); + + let expected = "Hellofoರrlர~"; + let mut byte_pos = 0; + for ((c, b), e) in r.chars().zip(expected.chars()) { + assert!(c == e); + assert!(b == byte_pos); + byte_pos += e.len_utf8(); + } + } + + #[test] + fn test_src_insert_remove_col_for_src_loc() { + let mut r: Rope = "hello\n world!".parse().unwrap(); + r.src_insert(4, "foo".to_string()); + r.src_insert(5, "bar".to_string()); + assert!(r.to_string() == "hellfooobar\n world!"); + + r.src_remove(2, 4); + r.src_remove(10, 12); + assert!(r.to_string() == "hefooobar\n wor!"); + + let expected = "hefooobar\n wor!"; + let mut byte_pos = 0; + for ((c, b), e) in r.chars().zip(expected.chars()) { + assert!(c == e); + assert!(b == byte_pos); + byte_pos += e.len_utf8(); + } + + let expected = [0, 1, 2, 2, 5, 9, 0, 1, 2, 3, 4, 4, 4]; + for i in 0..13 { + assert!(r.col_for_src_loc(i) == expected[i]); + } + } + + #[test] + fn test_src_insert() { + let mut r: Rope = "Hello world!".parse().unwrap(); + r.src_insert(4, "foo".to_string()); + r.src_insert(0, "foo".to_string()); + r.src_insert(12, "foo".to_string()); + assert!(r.to_string() == "fooHellfooo world!foo"); + r.src_insert(4, "bar".to_string()); + r.src_insert(5, "bar".to_string()); + r.src_insert(3, "bar".to_string()); + r.src_insert(0, "bar".to_string()); + r.src_insert(12, "bar".to_string()); + assert!(r.to_string() == "barfooHelbarlbarfooobar world!barfoo"); + } +} -- cgit 1.4.1-3-g733a5 From 4fd5f867321104734ba163f20f71d2a8c076a90a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 8 Mar 2015 19:24:56 +1300 Subject: Add string_buffer (not used yet) --- src/string_buffer.rs | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 src/string_buffer.rs (limited to 'src') diff --git a/src/string_buffer.rs b/src/string_buffer.rs new file mode 100644 index 00000000000..f3ec7a33ecb --- /dev/null +++ b/src/string_buffer.rs @@ -0,0 +1,291 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// A specialised string-like structure that is optimised for appending text and +// sequential reading. + +// TODO +// Debug +// docs +// char iterator +// Chars -> CharsAndPos +// Eq + +extern crate unicode; + +use std::str::FromStr; +use std::{cmp, fmt}; + +const MAX_CAPACITY: usize = 0xffff; +const INIT_CAPACITY: usize = 0xff; + +pub struct StringBuffer { + first: Box, + // last: &self StringNode + // Optimisation that saves us from walking the whole list of nodes everytime + // we append a string. + last: *mut StringNode, + // The length of the whole StringBuffer. + len: usize, +} + +pub struct Chars<'a> { + // Node we're currently iterating over. + cur_node: &'a StringNode, + // Byte in cur_node. + cur_byte: usize, + // Byte since start of StringBuffer. + abs_byte: usize, +} + +struct StringNode { + data: String, + next: Option>, +} + +impl StringBuffer { + pub fn new() -> StringBuffer { + StringBuffer::with_capacity(INIT_CAPACITY) + } + + pub fn with_capacity(capacity: usize) -> StringBuffer { + let mut result = StringBuffer { + first: box StringNode::with_capacity(capacity), + last: 0 as *mut StringNode, + len: 0, + }; + result.last = &mut *result.first; + result + } + + pub fn push_str(&mut self, text: &str) { + self.len += text.len(); + unsafe { + // Safety invariant: the `last` field will only ever point to + // a node owned by self, and will live until destruction of self. + self.last = (&mut *self.last).push_str(text); + } + } + + pub fn chars<'a>(&'a self) -> Chars<'a> { + Chars::new(&self.first) + } +} + +impl StringNode { + fn with_capacity(capacity: usize) -> StringNode { + StringNode { + data: String::with_capacity(capacity), + next: None, + } + } + + // Returns a reference to the new last node. + fn push_str(&mut self, text: &str) -> &mut StringNode { + if let Some(ref mut n) = self.next { + return n.push_str(text); + } + + if self.data.capacity() - self.data.len() >= text.len() { + self.data.push_str(text); + self + } else { + self.data.shrink_to_fit(); + let next_cap = cmp::min(cmp::max(self.data.capacity(), + INIT_CAPACITY) * 2, + MAX_CAPACITY); + let next_cap = cmp::max(next_cap, text.len()); + self.next = Some(box StringNode::with_capacity(next_cap)); + let next = self.next.as_mut().unwrap(); + next.push_str(text); + &mut **next + } + } +} + +impl FromStr for StringBuffer { + type Err = (); + fn from_str(text: &str) -> Result { + let mut result = StringBuffer::with_capacity(cmp::max(INIT_CAPACITY, text.len())); + result.push_str(text); + Ok(result) + } +} + +impl fmt::Display for StringBuffer { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt_node(node: &StringNode, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + try!(write!(fmt, "{}", node.data)); + if let Some(ref n) = node.next { + fmt_node(n, fmt) + } else { + Ok(()) + } + } + + fmt_node(&self.first, fmt) + } +} + +impl<'a> Iterator for Chars<'a> { + type Item = (char, usize); + + fn next(&mut self) -> Option<(char, usize)> { + while self.cur_byte >= self.cur_node.data.len() { + if let Some(ref n) = self.cur_node.next { + self.cur_byte = 0; + self.cur_node = n; + } else { + return None; + } + } + + let byte = self.abs_byte; + let result = self.read_char(); + + return Some((result, byte)); + } +} + +impl<'a> Chars<'a> { + fn new<'b>(first_node: &'b StringNode) -> Chars<'b> { + Chars { + cur_node: first_node, + cur_byte: 0, + abs_byte: 0, + } + } + + fn read_char(&mut self) -> char { + let first_byte = self.read_byte(); + let width = unicode::str::utf8_char_width(first_byte); + if width == 1 { + return first_byte as char + } + if width == 0 { + panic!("non-utf8 char in StringBuffer"); + } + let mut buf = [first_byte, 0, 0, 0]; + { + let mut start = 1; + while start < width { + buf[start] = self.read_byte(); + start += 1; + } + } + match ::std::str::from_utf8(&buf[..width]).ok() { + Some(s) => s.char_at(0), + None => panic!("bad chars in StringBuffer") + } + } + + fn read_byte(&mut self) -> u8 { + let result = self.cur_node.data.as_bytes()[self.cur_byte]; + self.cur_byte += 1; + self.abs_byte += 1; + result + } +} + + +#[cfg(test)] +mod test { + use super::*; + // Bug #23157 + use super::{StringNode, INIT_CAPACITY}; + + #[test] + fn test_new() { + let s = StringBuffer::new(); + assert!(s.len == 0); + assert!(s.to_string() == ""); + assert!(count_nodes(&s) == 1); + assert!(first_capacity(&s) == INIT_CAPACITY); + + let s = StringBuffer::with_capacity(64); + assert!(s.len == 0); + assert!(s.to_string() == ""); + assert!(count_nodes(&s) == 1); + assert!(first_capacity(&s) == 64); + } + + #[test] + fn test_from_str() { + let s: StringBuffer = "Hello".parse().unwrap(); + assert!(s.len == 5); + assert!(s.to_string() == "Hello"); + assert!(count_nodes(&s) == 1); + assert!(first_capacity(&s) == INIT_CAPACITY); + + let expected = "Hello"; + for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) { + assert!(c == cc); + assert!(i == b); + } + } + + #[test] + fn test_push_str() { + let mut s: StringBuffer = "Hello".parse().unwrap(); + assert!(first_capacity(&s) == INIT_CAPACITY); + + s.push_str(" world!"); + assert!(s.to_string() == "Hello world!"); + assert!(s.len == 12); + s.push_str(" foo"); + assert!(s.to_string() == "Hello world! foo"); + assert!(s.len == 16); + + assert!(count_nodes(&s) == 1); + + let expected = "Hello world! foo"; + for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) { + assert!(c == cc); + assert!(i == b); + } + } + + // push_str requiring multiple nodes + #[test] + fn test_push_str_multi() { + let mut s: StringBuffer = StringBuffer::with_capacity(2); + assert!(first_capacity(&s) == 2); + + s.push_str("Hello"); + assert!(s.to_string() == "Hello"); + assert!(s.len == 5); + assert!(count_nodes(&s) == 2); + s.push_str(" world!"); + assert!(s.to_string() == "Hello world!"); + assert!(s.len == 12); + assert!(count_nodes(&s) == 2); + + let expected = "Hello world!"; + for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) { + assert!(c == cc); + assert!(i == b); + } + } + + // TODO test unicode + + fn count_nodes(s: &StringBuffer) -> usize { + count_nodes_from(&s.first) + } + fn count_nodes_from(s: &StringNode) -> usize { + match s.next { + Some(ref n) => 1 + count_nodes_from(n), + None => 1, + } + } + fn first_capacity(s: &StringBuffer) -> usize { + s.first.data.capacity() + } +} -- cgit 1.4.1-3-g733a5 From 3f58f829f3f875b6395759f346751d16729a84a8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Mar 2015 17:18:48 +1300 Subject: A different, more pretty printing approach. No longer uses the Rope data strucure. --- src/changes.rs | 79 +++--------- src/mod.rs | 352 +++++++++++++++++++++++++++++++++++++-------------- src/rope.rs | 2 +- src/string_buffer.rs | 19 ++- 4 files changed, 295 insertions(+), 157 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index bcfbed17f5b..7b56318be09 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -10,20 +10,19 @@ // TODO -// print to files (maybe that shouldn't be here, but in mod) +// print to files // tests -use rope::{Rope, RopeSlice}; +use string_buffer::StringBuffer; use std::collections::HashMap; -use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::codemap::{CodeMap, Span}; use std::fmt; // This is basically a wrapper around a bunch of Ropes which makes it convenient // to work with libsyntax. It is badly named. pub struct ChangeSet<'a> { - file_map: HashMap, + file_map: HashMap, codemap: &'a CodeMap, - pub count: u64, } impl<'a> ChangeSet<'a> { @@ -32,64 +31,35 @@ impl<'a> ChangeSet<'a> { let mut result = ChangeSet { file_map: HashMap::new(), codemap: codemap, - count: 0, }; for f in codemap.files.borrow().iter() { - let contents = Rope::from_string((&**f.src.as_ref().unwrap()).clone()); - result.file_map.insert(f.name.clone(), contents); + // Use the length of the file as a heuristic for how much space we + // need. I hope that at some stage someone rounds this up to the next + // power of two. TODO check that or do it here. + result.file_map.insert(f.name.clone(), + StringBuffer::with_capacity(f.src.as_ref().unwrap().len())); } result } - // Change a span of text in our stored text into the new text (`text`). - // The span of text to change is given in the coordinates of the original - // source text, not the current text, - pub fn change(&mut self, file_name: &str, start: usize, end: usize, text: String) { - println!("change: {}:{}-{} \"{}\"", file_name, start, end, text); - - self.count += 1; - - let file = &mut self.file_map[*file_name]; - - if end - start == text.len() { - // TODO src_replace_str would be much more efficient - //file.src_replace_str(start, &text); - file.src_remove(start, end); - file.src_insert(start, text); - } else { - // TODO if we do this in one op, could we get better change info? - file.src_remove(start, end); - file.src_insert(start, text); - } + pub fn push_str(&mut self, file_name: &str, text: &str) { + self.file_map[*file_name].push_str(text) } - // As for `change()`, but use a Span to indicate the text to change. - pub fn change_span(&mut self, span: Span, text: String) { - let l_loc = self.codemap.lookup_char_pos(span.lo); - let file_offset = l_loc.file.start_pos.0; - self.change(&l_loc.file.name, - (span.lo.0 - file_offset) as usize, - (span.hi.0 - file_offset) as usize, - text) + pub fn push_str_span(&mut self, span: Span, text: &str) { + let file_name = self.codemap.span_to_filename(span); + self.push_str(&file_name, text) } - // Get a slice of the current text. Coordinates are relative to the source - // text. I.e., this method returns the text which has been changed from the - // indicated span. - pub fn slice(&self, file_name: &str, start: usize, end: usize) -> RopeSlice { - let file = &self.file_map[*file_name]; - file.src_slice(start..end) + pub fn cur_offset(&mut self, file_name: &str) -> usize { + self.file_map[*file_name].cur_offset() } - // As for `slice()`, but use a Span to indicate the text to return. - pub fn slice_span(&self, span:Span) -> RopeSlice { - let l_loc = self.codemap.lookup_char_pos(span.lo); - let file_offset = l_loc.file.start_pos.0; - self.slice(&l_loc.file.name, - (span.lo.0 - file_offset) as usize, - (span.hi.0 - file_offset) as usize) + pub fn cur_offset_span(&mut self, span: Span) -> usize { + let file_name = self.codemap.span_to_filename(span); + self.cur_offset(&file_name) } // Return an iterator over the entire changed text. @@ -101,13 +71,6 @@ impl<'a> ChangeSet<'a> { } } - // Get the current line-relative position of a position in the source text. - pub fn col(&self, loc: BytePos) -> usize { - let l_loc = self.codemap.lookup_char_pos(loc); - let file_offset = l_loc.file.start_pos.0; - let file = &self.file_map[l_loc.file.name[..]]; - file.col_for_src_loc(loc.0 as usize - file_offset as usize) - } } // Iterates over each file in the ChangSet. Yields the filename and the changed @@ -119,9 +82,9 @@ pub struct FileIterator<'c, 'a: 'c> { } impl<'c, 'a> Iterator for FileIterator<'c, 'a> { - type Item = (&'c str, &'c Rope); + type Item = (&'c str, &'c StringBuffer); - fn next(&mut self) -> Option<(&'c str, &'c Rope)> { + fn next(&mut self) -> Option<(&'c str, &'c StringBuffer)> { if self.cur_key >= self.keys.len() { return None; } diff --git a/src/mod.rs b/src/mod.rs index c0bad7a0e31..16e9c84ab84 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -18,6 +18,9 @@ #![feature(old_path)] #![feature(exit_status)] +// TODO we're going to allocate a whole bunch of temp Strings, is it worth +// keeping some scratch mem for this and running our own StrPool? + #[macro_use] extern crate log; @@ -30,29 +33,34 @@ use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; -use syntax::ast; -use syntax::codemap::{self, CodeMap, Span, Pos}; +use syntax::{ast, ptr}; +use syntax::codemap::{self, CodeMap, Span, Pos, BytePos}; use syntax::diagnostics; use syntax::parse::token; use syntax::print::pprust; use syntax::visit; -use std::mem; +use std::slice::SliceConcatExt; use changes::ChangeSet; pub mod rope; +pub mod string_buffer; mod changes; const IDEAL_WIDTH: usize = 80; +const LEEWAY: usize = 5; const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut visitor = FmtVisitor { codemap: codemap, - changes: ChangeSet::from_codemap(codemap) }; + let mut visitor = FmtVisitor::from_codemap(codemap); visit::walk_crate(&mut visitor, krate); + let files = codemap.files.borrow(); + if let Some(last) = files.last() { + visitor.format_missing(last.end_pos); + } visitor.changes } @@ -69,7 +77,7 @@ fn fmt_lines(changes: &mut ChangeSet) { if c == '\n' { // TOOD test for \r too // Check for (and record) trailing whitespace. if let Some(lw) = last_wspace { - trims.push((lw, b)); + trims.push((cur_line, lw, b)); line_len -= b - lw; } // Check for any line width errors we couldn't correct. @@ -93,23 +101,9 @@ fn fmt_lines(changes: &mut ChangeSet) { } } - unsafe { - // Invariant: we only mutate a rope after we have searched it, then - // we will not search it again. - let mut_text: &mut rope::Rope = mem::transmute(text); - let mut_count: &mut u64 = mem::transmute(&changes.count); - let mut offset = 0; - // Get rid of any trailing whitespace we recorded earlier. - for &(s, e) in trims.iter() { - // Note that we change the underlying ropes directly, we don't - // go through the changeset because our change positions are - // relative to the newest text, not the original. - debug!("Stripping trailing whitespace {}:{}-{} \"{}\"", - f, s, e, text.slice(s-offset..e-offset)); - mut_text.remove(s-offset, e-offset); - *mut_count += 1; - offset += e - s; - } + for &(l, _, _) in trims.iter() { + // FIXME store the error rather than reporting immediately. + println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); } } } @@ -117,21 +111,43 @@ fn fmt_lines(changes: &mut ChangeSet) { struct FmtVisitor<'a> { codemap: &'a CodeMap, changes: ChangeSet<'a>, + last_pos: BytePos, + block_indent: usize, } impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_expr(&mut self, ex: &'v ast::Expr) { - match ex.node { - ast::Expr_::ExprLit(ref l) => match l.node { - ast::Lit_::LitStr(ref is, _) => { - self.rewrite_string(&is, l.span); - } - _ => {} - }, - _ => {} + self.format_missing(ex.span.lo); + let offset = self.changes.cur_offset_span(ex.span); + let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset); + self.changes.push_str_span(ex.span, &new_str); + self.last_pos = ex.span.hi; + } + + fn visit_block(&mut self, b: &'v ast::Block) { + self.format_missing(b.span.lo); + + self.changes.push_str_span(b.span, "{"); + self.last_pos = self.last_pos + BytePos(1); + self.block_indent += 4; + + for stmt in &b.stmts { + self.format_missing_with_indent(stmt.span.lo); + self.visit_stmt(&**stmt) + } + match b.expr { + Some(ref e) => { + self.format_missing_with_indent(e.span.lo); + self.visit_expr(e); + } + None => {} } - visit::walk_expr(self, ex) + self.block_indent -= 4; + // TODO we should compress any newlines here to just one + self.format_missing_with_indent(b.span.hi - BytePos(1)); + self.changes.push_str_span(b.span, "}"); + self.last_pos = b.span.hi; } fn visit_fn(&mut self, @@ -140,32 +156,38 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { - self.fix_formal_args(fd); + if let Some(new_str) = self.formal_args(fk, fd) { + self.changes.push_str_span(s, &new_str); + } visit::walk_fn(self, fk, fd, b, s); } fn visit_item(&mut self, item: &'v ast::Item) { - // TODO check each item is on a new line and is correctly indented. match item.node { ast::Item_::ItemUse(ref vp) => { match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { + self.format_missing(item.span.lo); let new_str = self.fix_use_list(path, path_list, vp.span); - - // TODO move these optimisations to ChangeSet - if new_str != self.codemap.span_to_snippet(item.span).unwrap() { - self.changes.change_span(item.span, new_str); - } + self.changes.push_str_span(item.span, &new_str); + self.last_pos = item.span.hi; } ast::ViewPath_::ViewPathGlob(_) => { // FIXME convert to list? } _ => {} } + visit::walk_item(self, item); + } + ast::Item_::ItemImpl(..) => { + self.block_indent += 4; + visit::walk_item(self, item); + self.block_indent -= 4; + } + _ => { + visit::walk_item(self, item); } - _ => {} } - visit::walk_item(self, item); } } @@ -178,8 +200,88 @@ fn make_indent(width: usize) -> String { } impl<'a> FmtVisitor<'a> { + fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { + FmtVisitor { + codemap: codemap, + changes: ChangeSet::from_codemap(codemap), + last_pos: BytePos(0), + block_indent: 0, + } + } + + fn format_missing(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, span, _| { + this.changes.push_str_span(span, last_snippet) + }) + } + + fn format_missing_with_indent(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, span, snippet| { + if last_snippet == snippet { + // No new lines + this.changes.push_str_span(span, last_snippet); + this.changes.push_str_span(span, "\n"); + } else { + this.changes.push_str_span(span, last_snippet.trim_right()); + } + let indent = make_indent(this.block_indent); + this.changes.push_str_span(span, &indent); + }) + } + + fn format_missing_inner(&mut self, + end: BytePos, + process_last_snippet: F) + { + let start = self.last_pos; + // TODO(#11) gets tricky if we're missing more than one file + assert!(self.codemap.lookup_char_pos(start).file.name == self.codemap.lookup_char_pos(end).file.name, + "not implemented: unformated span across files"); + + self.last_pos = end; + let span = codemap::mk_sp(start, end); + let snippet = self.snippet(span); + + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let mut line_start = 0; + let mut last_wspace = None; + for (i, c) in snippet.char_indices() { + if c == '\n' { + if let Some(lw) = last_wspace { + self.changes.push_str_span(span, &snippet[line_start..lw]); + self.changes.push_str_span(span, "\n"); + } else { + self.changes.push_str_span(span, &snippet[line_start..i+1]); + } + + line_start = i + 1; + last_wspace = None; + } else { + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(i); + } + } else { + last_wspace = None; + } + } + } + process_last_snippet(self, &snippet[line_start..], span, &snippet); + } + + fn snippet(&self, span: Span) -> String { + match self.codemap.span_to_snippet(span) { + Ok(s) => s, + Err(_) => { + println!("Couldn't make snippet for span {:?}", span); + "".to_string() + } + } + } + // TODO NEEDS TESTS - fn rewrite_string(&mut self, s: &str, span: Span) { + fn rewrite_string(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { // FIXME I bet this stomps unicode escapes in the source string // Check if there is anything to fix: we always try to fixup multi-line @@ -187,21 +289,18 @@ impl<'a> FmtVisitor<'a> { let l_loc = self.codemap.lookup_char_pos(span.lo); let r_loc = self.codemap.lookup_char_pos(span.hi); if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH { - return; + return self.snippet(span); } // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) let s = s.escape_default(); - // TODO use fixed value. - let l_loc = self.codemap.lookup_char_pos(span.lo); - let l_col = l_loc.col.to_usize(); - - let indent = make_indent(l_col + 1); + let offset = offset + 1; + let indent = make_indent(offset); let indent = &indent; - let max_chars = MAX_WIDTH - (l_col + 1); + let max_chars = width - 1; let mut cur_start = 0; let mut result = String::new(); @@ -242,12 +341,7 @@ impl<'a> FmtVisitor<'a> { } result.push('"'); - // Check that we actually changed something. - if result == self.codemap.span_to_snippet(span).unwrap() { - return; - } - - self.changes.change_span(span, result); + result } // Basically just pretty prints a multi-item import. @@ -314,55 +408,115 @@ impl<'a> FmtVisitor<'a> { new_str } - fn fix_formal_args<'v>(&mut self, fd: &'v ast::FnDecl) { + fn formal_args<'v>(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl) -> Option { // For now, just check the arguments line up and make them per-row if the line is too long. let args = &fd.inputs; - if args.len() <= 1 { - return; + + let ret_str = match fd.output { + ast::FunctionRetTy::DefaultReturn(_) => "".to_string(), + ast::FunctionRetTy::NoReturn(_) => " -> !".to_string(), + ast::FunctionRetTy::Return(ref ty) => pprust::ty_to_string(ty), + }; + + // TODO don't return, want to do the return type etc. + if args.len() == 0 { + return None; } + // TODO not really using the hi positions let spans: Vec<_> = args.iter().map(|a| (a.pat.span.lo, a.ty.span.hi)).collect(); - let locs: Vec<_> = spans.iter().map(|&(a, b)| (self.codemap.lookup_char_pos(a), self.codemap.lookup_char_pos(b))).collect(); - let first_loc = &locs[0].0; - // TODO need to adjust for previous changes here. - let same_row = locs.iter().all(|&(ref l, _)| l.line == first_loc.line); - let same_col = locs.iter().all(|&(ref l, _)| l.col == first_loc.col); - - if same_col { - // TODO Check one arg per line and no lines in between (except comments) - return; - } - - if same_row { // TODO check line is < 100 && first_loc.line { - // TODO could also fix whitespace around punctuaton here - // TODO and could check that we're on the same line as the function call, if possible - return; + let locs: Vec<_> = spans.iter().map(|&(a, b)| { + (self.codemap.lookup_char_pos(a), self.codemap.lookup_char_pos(b)) + }).collect(); + let first_col = locs[0].0.col.0; + + // Print up to the start of the args. + self.format_missing(spans[0].0); + self.last_pos = spans.last().unwrap().1; + + let arg_strs: Vec<_> = args.iter().map(|a| format!("{}: {}", + pprust::pat_to_string(&a.pat), + pprust::ty_to_string(&a.ty))).collect(); + + // Try putting everything on one row: + let mut len = arg_strs.iter().fold(0, |a, b| a + b.len()); + // Account for punctuation and spacing. + len += 2 * arg_strs.len() + 2 * (arg_strs.len()-1); + // Return type. + len += ret_str.len(); + // Opening brace if no where clause. + match fk { + visit::FnKind::FkItemFn(_, g, _, _) | + visit::FnKind::FkMethod(_, g, _) + if g.where_clause.predicates.len() > 0 => {} + _ => len += 2 // ` {` } + len += first_col; + + if len <= IDEAL_WIDTH + LEEWAY || args.len() == 1 { + // It should all fit on one line. + return Some(arg_strs.connect(", ")); + } else { + // TODO multi-line + let mut indent = String::with_capacity(first_col + 2); + indent.push_str(",\n"); + for _ in 0..first_col { indent.push(' '); } + return Some(arg_strs.connect(&indent)); + } + } - let col = self.changes.col(spans[0].0); - let mut indent = String::with_capacity(col); - indent.push('\n'); - for _ in 0..col { indent.push(' '); } - let last_idx = spans.len() - 1; - for (i, s) in spans.iter().enumerate() { - // Take the span from lo to lo (or the last hi for the last arg), - // trim, push on top of indent, then replace the old lo-lo span with it. - let mut new_text = if i == 0 { - "".to_string() - } else { - indent.clone() - }; - let hi = if i == last_idx { - s.1 - } else { - spans[i+1].0 - }; - // TODO need a version of slice taking locs, not a span - let snippet = self.changes.slice_span(Span{ lo: s.0, hi: hi, expn_id: codemap::NO_EXPANSION }).to_string(); - let snippet = snippet.trim(); - new_text.push_str(snippet); - self.changes.change(&first_loc.file.name, (s.0).0 as usize, hi.0 as usize, new_text); + fn rewrite_call(&mut self, + callee: &ast::Expr, + args: &[ptr::P], + width: usize, + offset: usize) + -> String + { + debug!("rewrite_call, width: {}, offset: {}", width, offset); + + // TODO using byte lens instead of char lens (and probably all over the place too) + let callee_str = self.rewrite_expr(callee, width, offset); + debug!("rewrite_call, callee_str: `{}`", callee_str); + // 2 is for parens. + let remaining_width = width - callee_str.len() - 2; + let offset = callee_str.len() + 1 + offset; + let arg_count = args.len(); + let args: Vec<_> = args.iter().map(|e| self.rewrite_expr(e, + remaining_width, + offset)).collect(); + debug!("rewrite_call, args: `{}`", args.connect(",")); + + let multi_line = args.iter().any(|s| s.contains('\n')); + let args_width = args.iter().map(|s| s.len()).fold(0, |a, l| a + l); + let over_wide = args_width + (arg_count - 1) * 2 > remaining_width; + let args_str = if multi_line || over_wide { + args.connect(&(",\n".to_string() + &make_indent(offset))) + } else { + args.connect(", ") + }; + + format!("{}({})", callee_str, args_str) + } + + fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { + match expr.node { + ast::Expr_::ExprLit(ref l) => { + match l.node { + ast::Lit_::LitStr(ref is, _) => { + return self.rewrite_string(&is, l.span, width, offset); + } + _ => {} + } + } + ast::Expr_::ExprCall(ref callee, ref args) => { + return self.rewrite_call(callee, args, width, offset); + } + _ => {} } + + let result = self.snippet(expr.span); + debug!("snippet: {}", result); + result } } @@ -439,9 +593,11 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { let mut changes = fmt_ast(krate, codemap); fmt_lines(&mut changes); - println!("Making {} changes", changes.count); println!("{}", changes); // FIXME(#5) Should be user specified whether to show or replace. + + // TODO we stop before expansion, but we still seem to get expanded for loops which + // cause problems - probably a rustc bug }; control @@ -466,3 +622,5 @@ fn main() { // algorithm to keep the width under IDEAL_WIDTH. We should also convert multiline // /* ... */ comments to // and check doc comments are in the right place and of // the right kind. + +// Should also make sure comments have the right indent diff --git a/src/rope.rs b/src/rope.rs index 5a96370308a..c7ed62afb05 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -1164,7 +1164,7 @@ mod test { #[test] fn test_from_string() { - let mut r: Rope = "Hello world!".parse().unwrap(); + let r: Rope = "Hello world!".parse().unwrap(); assert!(r.to_string() == "Hello world!"); } diff --git a/src/string_buffer.rs b/src/string_buffer.rs index f3ec7a33ecb..142231b6d7d 100644 --- a/src/string_buffer.rs +++ b/src/string_buffer.rs @@ -15,7 +15,7 @@ // Debug // docs // char iterator -// Chars -> CharsAndPos +// chars -> char_indices and flip order of char/index // Eq extern crate unicode; @@ -74,6 +74,17 @@ impl StringBuffer { } } + // Returns the number of characters from start of the last line in the + // StringBuffer. + // Note that it is possible for this operation to take a long time in + // pathological cases (lots of nodes, few line breaks). + pub fn cur_offset(&self) -> usize { + unsafe { + let result = (&*self.last).cur_offset(); + result.unwrap_or_else(|| panic!("Unimplemented cur_offset across node boundaries")) + } + } + pub fn chars<'a>(&'a self) -> Chars<'a> { Chars::new(&self.first) } @@ -108,6 +119,11 @@ impl StringNode { &mut **next } } + + // None if there is no new line in this node. + fn cur_offset(&self) -> Option { + self.data.rfind('\n').map(|i| self.data.len() - i - 1) + } } impl FromStr for StringBuffer { @@ -276,6 +292,7 @@ mod test { // TODO test unicode + // Helper methods. fn count_nodes(s: &StringBuffer) -> usize { count_nodes_from(&s.first) } -- cgit 1.4.1-3-g733a5 From 33e12c58b9b24008618e31044911d5c7399b76fe Mon Sep 17 00:00:00 2001 From: Dan Glastonbury Date: Mon, 9 Mar 2015 16:17:14 +1000 Subject: Update from Path to PathBuf --- src/mod.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 16e9c84ab84..d4320fb7b18 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -15,8 +15,8 @@ #![feature(os)] #![feature(core)] #![feature(unicode)] -#![feature(old_path)] #![feature(exit_status)] +#![feature(path)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? @@ -40,6 +40,7 @@ use syntax::parse::token; use syntax::print::pprust; use syntax::visit; +use std::path::PathBuf; use std::slice::SliceConcatExt; use changes::ChangeSet; @@ -542,7 +543,7 @@ fn next_char(s: &str, mut i: usize) -> usize { } struct RustFmtCalls { - input_path: Option, + input_path: Option, } impl<'a> CompilerCalls<'a> for RustFmtCalls { @@ -553,7 +554,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { Compilation::Continue } - fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { + fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { match input_path { Some(ref ip) => self.input_path = Some(ip.clone()), _ => { @@ -567,10 +568,10 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { fn no_input(&mut self, _: &getopts::Matches, _: &config::Options, - _: &Option, - _: &Option, + _: &Option, + _: &Option, _: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { + -> Option<(Input, Option)> { panic!("No input supplied to RustFmt"); } @@ -578,8 +579,8 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { _: &getopts::Matches, _: &Session, _: &Input, - _: &Option, - _: &Option) + _: &Option, + _: &Option) -> Compilation { Compilation::Continue } -- cgit 1.4.1-3-g733a5 From 0fd4b6a15025f3efee55dd72d7ea8ec0d552cad4 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 22 Mar 2015 09:30:04 -0700 Subject: Update for new FnKind::FkMethod signature --- src/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index d4320fb7b18..132d56b6832 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -447,8 +447,8 @@ impl<'a> FmtVisitor<'a> { len += ret_str.len(); // Opening brace if no where clause. match fk { - visit::FnKind::FkItemFn(_, g, _, _) | - visit::FnKind::FkMethod(_, g, _) + visit::FnKind::FkItemFn(_, &ref g, _, _) | + visit::FnKind::FkMethod(_, &ast::MethodSig { generics: ref g, ..}) if g.where_clause.predicates.len() > 0 => {} _ => len += 2 // ` {` } -- cgit 1.4.1-3-g733a5 From 76854677c1b730ecb262b5277a6520fc2ff75974 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 14 Apr 2015 13:00:46 +1200 Subject: New reformatting of fns --- src/changes.rs | 7 +- src/mod.rs | 661 ++++++++++++++++++++++++++++++++++++++++++--------- src/rope.rs | 2 +- src/string_buffer.rs | 6 +- 4 files changed, 555 insertions(+), 121 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 7b56318be09..562aada3103 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -45,7 +45,8 @@ impl<'a> ChangeSet<'a> { } pub fn push_str(&mut self, file_name: &str, text: &str) { - self.file_map[*file_name].push_str(text) + let buf = self.file_map.get_mut(&*file_name).unwrap(); + buf.push_str(text) } pub fn push_str_span(&mut self, span: Span, text: &str) { @@ -54,7 +55,7 @@ impl<'a> ChangeSet<'a> { } pub fn cur_offset(&mut self, file_name: &str) -> usize { - self.file_map[*file_name].cur_offset() + self.file_map[&*file_name].cur_offset() } pub fn cur_offset_span(&mut self, span: Span) -> usize { @@ -91,7 +92,7 @@ impl<'c, 'a> Iterator for FileIterator<'c, 'a> { let key = self.keys[self.cur_key]; self.cur_key += 1; - return Some((&key, &self.change_set.file_map[*key])) + return Some((&key, &self.change_set.file_map[&*key])) } } diff --git a/src/mod.rs b/src/mod.rs index 132d56b6832..34f79e63916 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -12,14 +12,21 @@ #![feature(box_patterns)] #![feature(rustc_private)] #![feature(collections)] -#![feature(os)] #![feature(core)] #![feature(unicode)] #![feature(exit_status)] -#![feature(path)] +#![feature(str_char)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? +// TODO for lint violations of names, emit a refactor script + +// TODO priorities +// Fix fns and methods properly - need visibility in visit +// Use strings crate +// Writing output +// Working on multiple files, inclding empty ones +// Smoke testing till we can use it #[macro_use] extern crate log; @@ -33,7 +40,7 @@ use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; -use syntax::{ast, ptr}; +use syntax::{ast, ptr, abi}; use syntax::codemap::{self, CodeMap, Span, Pos, BytePos}; use syntax::diagnostics; use syntax::parse::token; @@ -41,7 +48,6 @@ use syntax::print::pprust; use syntax::visit; use std::path::PathBuf; -use std::slice::SliceConcatExt; use changes::ChangeSet; @@ -53,6 +59,7 @@ const IDEAL_WIDTH: usize = 80; const LEEWAY: usize = 5; const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; +const TAB_SPACES: usize = 4; // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { @@ -71,7 +78,7 @@ fn fmt_lines(changes: &mut ChangeSet) { // Iterate over the chars in the change set. for (f, text) in changes.text() { let mut trims = vec![]; - let mut last_wspace = None; + let mut last_wspace: Option = None; let mut line_len = 0; let mut cur_line = 1; for (c, b) in text.chars() { @@ -113,11 +120,16 @@ struct FmtVisitor<'a> { codemap: &'a CodeMap, changes: ChangeSet<'a>, last_pos: BytePos, + // TODO RAII util for indenting block_indent: usize, } impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_expr(&mut self, ex: &'v ast::Expr) { + // TODO uncomment + // debug!("visit_expr: {:?} {:?}", + // self.codemap.lookup_char_pos(ex.span.lo), + // self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset); @@ -126,15 +138,19 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_block(&mut self, b: &'v ast::Block) { + // TODO uncomment + // debug!("visit_block: {:?} {:?}", + // self.codemap.lookup_char_pos(b.span.lo), + // self.codemap.lookup_char_pos(b.span.hi)); self.format_missing(b.span.lo); self.changes.push_str_span(b.span, "{"); self.last_pos = self.last_pos + BytePos(1); - self.block_indent += 4; + self.block_indent += TAB_SPACES; for stmt in &b.stmts { self.format_missing_with_indent(stmt.span.lo); - self.visit_stmt(&**stmt) + self.visit_stmt(&stmt) } match b.expr { Some(ref e) => { @@ -144,7 +160,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { None => {} } - self.block_indent -= 4; + self.block_indent -= TAB_SPACES; // TODO we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - BytePos(1)); self.changes.push_str_span(b.span, "}"); @@ -157,10 +173,44 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { - if let Some(new_str) = self.formal_args(fk, fd) { - self.changes.push_str_span(s, &new_str); + // TODO need to get the visibility from somewhere + self.format_missing(s.lo); + self.last_pos = s.lo; + + // TODO need to check against expected indent + let indent = self.codemap.lookup_char_pos(s.lo).col.0; + match fk { + visit::FkItemFn(ident, ref generics, ref unsafety, ref abi) => { + let new_fn = self.rewrite_fn(indent, + ident, + fd, + None, + generics, + unsafety, + abi, + ast::Visibility::Inherited); + self.changes.push_str_span(s, &new_fn); + } + visit::FkMethod(ident, ref sig) => { + let new_fn = self.rewrite_fn(indent, + ident, + fd, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.abi, + ast::Visibility::Inherited); + self.changes.push_str_span(s, &new_fn); + } + visit::FkFnBlock(..) => {} } - visit::walk_fn(self, fk, fd, b, s); + + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + self.changes.push_str_span(s, "\n"); + self.changes.push_str_span(s, &make_indent(self.block_indent)); + self.last_pos = b.span.lo; + self.visit_block(b) } fn visit_item(&mut self, item: &'v ast::Item) { @@ -169,7 +219,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { self.format_missing(item.span.lo); - let new_str = self.fix_use_list(path, path_list, vp.span); + let new_str = self.rewrite_use_list(path, path_list, vp.span); self.changes.push_str_span(item.span, &new_str); self.last_pos = item.span.hi; } @@ -181,15 +231,19 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { visit::walk_item(self, item); } ast::Item_::ItemImpl(..) => { - self.block_indent += 4; + self.block_indent += TAB_SPACES; visit::walk_item(self, item); - self.block_indent -= 4; + self.block_indent -= TAB_SPACES; } _ => { visit::walk_item(self, item); } } } + + fn visit_mac(&mut self, mac: &'v ast::Mac) { + visit::walk_mac(self, mac) + } } fn make_indent(width: usize) -> String { @@ -200,6 +254,131 @@ fn make_indent(width: usize) -> String { indent } +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +enum ListTactic { + // One item per row. + Vertical, + // All items on one row. + Horizontal, + // Try Horizontal layout, if that fails then vertical + HorizontalVertical, + // Pack as many items as possible per row over (possibly) many rows. + Mixed, +} + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +enum SeparatorTactic { + Always, + Never, + Vertical, +} + +struct ListFormatting<'a> { + tactic: ListTactic, + separator: &'a str, + trailing_separator: SeparatorTactic, + indent: usize, + // Available width if we layout horizontally. + h_width: usize, + // Available width if we layout vertically + v_width: usize, +} + +// Format a list of strings into a string. +fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b>) -> String { + if items.len() == 0 { + return String::new(); + } + + let mut tactic = formatting.tactic; + + let h_width = formatting.h_width; + let v_width = formatting.v_width; + let sep_len = formatting.separator.len(); + + // Conservatively overestimates because of the changing separator tactic. + let sep_count = if formatting.trailing_separator != SeparatorTactic::Never { + items.len() + } else { + items.len() - 1 + }; + + // TODO count dead space too. + let total_width = items.iter().map(|&(ref s, _)| s.len()).fold(0, |a, l| a + l); + + // Check if we need to fallback from horizontal listing, if possible. + if tactic == ListTactic::HorizontalVertical { + if (total_width + (sep_len + 1) * sep_count) > h_width { + tactic = ListTactic::Vertical; + } else { + tactic = ListTactic::Horizontal; + } + } + + // Now that we know how we will layout, we can decide for sure if there + // will be a trailing separator. + let trailing_separator = match formatting.trailing_separator { + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => tactic == ListTactic::Vertical, + SeparatorTactic::Never => false, + }; + + // Create a buffer for the result. + // TODO could use a StringBuffer or rope for this + let alloc_width = if tactic == ListTactic::Horizontal { + total_width + (sep_len + 1) * sep_count + } else { + total_width + items.len() * (formatting.indent + 1) + }; + let mut result = String::with_capacity(alloc_width); + + let mut line_len = 0; + let indent_str = &make_indent(formatting.indent); + for (i, &(ref item, _)) in items.iter().enumerate() { + let first = i == 0; + let separate = i != items.len() - 1 || trailing_separator; + + match tactic { + ListTactic::Horizontal if !first => { + result.push(' '); + } + ListTactic::Vertical if !first => { + result.push('\n'); + result.push_str(indent_str); + } + ListTactic::Mixed => { + let mut item_width = item.len(); + if separate { + item_width += sep_len; + } + + if line_len > 0 && line_len + item_width > v_width { + result.push('\n'); + result.push_str(indent_str); + line_len = 0; + } + + if line_len > 0 { + result.push(' '); + line_len += 1; + } + + line_len += item_width; + } + _ => {} + } + + result.push_str(item); + + if separate { + result.push_str(formatting.separator); + } + // TODO dead spans + } + + result +} + impl<'a> FmtVisitor<'a> { fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { FmtVisitor { @@ -210,6 +389,8 @@ impl<'a> FmtVisitor<'a> { } } + // TODO these format_missing methods are ugly. Refactor and add unit tests + // for the central whitespace stripping loop. fn format_missing(&mut self, end: BytePos) { self.format_missing_inner(end, |this, last_snippet, span, _| { this.changes.push_str_span(span, last_snippet) @@ -226,7 +407,7 @@ impl<'a> FmtVisitor<'a> { this.changes.push_str_span(span, last_snippet.trim_right()); } let indent = make_indent(this.block_indent); - this.changes.push_str_span(span, &indent); + this.changes.push_str_span(span, &indent); }) } @@ -235,14 +416,30 @@ impl<'a> FmtVisitor<'a> { process_last_snippet: F) { let start = self.last_pos; + // TODO uncomment + // debug!("format_missing_inner: {:?} to {:?}", + // self.codemap.lookup_char_pos(start), + // self.codemap.lookup_char_pos(end)); + // TODO(#11) gets tricky if we're missing more than one file - assert!(self.codemap.lookup_char_pos(start).file.name == self.codemap.lookup_char_pos(end).file.name, - "not implemented: unformated span across files"); + // assert!(self.codemap.lookup_char_pos(start).file.name == self.codemap.lookup_char_pos(end).file.name, + // "not implemented: unformated span across files: {} and {}", + // self.codemap.lookup_char_pos(start).file.name, + // self.codemap.lookup_char_pos(end).file.name); + // assert!(start <= end, + // "Request to format inverted span: {:?} to {:?}", + // self.codemap.lookup_char_pos(start), + // self.codemap.lookup_char_pos(end)); + + if start == end { + return; + } self.last_pos = end; let span = codemap::mk_sp(start, end); let snippet = self.snippet(span); + // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. let mut line_start = 0; @@ -282,7 +479,7 @@ impl<'a> FmtVisitor<'a> { } // TODO NEEDS TESTS - fn rewrite_string(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { + fn rewrite_string_lit(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { // FIXME I bet this stomps unicode escapes in the source string // Check if there is anything to fix: we always try to fixup multi-line @@ -346,123 +543,328 @@ impl<'a> FmtVisitor<'a> { } // Basically just pretty prints a multi-item import. - fn fix_use_list(&mut self, - path: &ast::Path, - path_list: &[ast::PathListItem], - vp_span: Span) -> String { + fn rewrite_use_list(&mut self, + path: &ast::Path, + path_list: &[ast::PathListItem], + vp_span: Span) -> String { // FIXME remove unused imports // FIXME check indentation let l_loc = self.codemap.lookup_char_pos(vp_span.lo); + let path_str = pprust::path_to_string(&path); - let indent = l_loc.col.0; - // After accounting for the overhead, how much space left for - // the item list? ( 5 = :: + { + } + ; ) - let space = IDEAL_WIDTH - (indent + path_str.len() + 5); - // 4 = `use` + one space - // TODO might be pub use - let indent = make_indent(indent-4); - - let mut cur_str = String::new(); - let mut first = true; + + // 3 = :: + { + let indent = l_loc.col.0 + path_str.len() + 3; + let fmt = ListFormatting { + tactic: ListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + // 2 = } + ; + h_width: IDEAL_WIDTH - (indent + path_str.len() + 2), + v_width: IDEAL_WIDTH - (indent + path_str.len() + 2), + }; + + // TODO handle any comments inbetween items. // If `self` is in the list, put it first. - if path_list.iter().any(|vpi| + let head = if path_list.iter().any(|vpi| if let ast::PathListItem_::PathListMod{ .. } = vpi.node { true } else { false } ) { - cur_str = "self".to_string(); - first = false; - } + Some(("self".to_string(), String::new())) + } else { + None + }; - let mut new_str = String::new(); - for vpi in path_list.iter() { + let items: Vec<_> = head.into_iter().chain(path_list.iter().filter_map(|vpi| { match vpi.node { ast::PathListItem_::PathListIdent{ name, .. } => { - let next_item = &token::get_ident(name); - if cur_str.len() + next_item.len() > space { - let cur_line = format!("{}use {}::{{{}}};\n", indent, path_str, cur_str); - new_str.push_str(&cur_line); + Some((token::get_ident(name).to_string(), String::new())) + } + // Skip `self`, because we added it above. + ast::PathListItem_::PathListMod{ .. } => None, + } + })).collect(); - cur_str = String::new(); - first = true; - } + format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) + } - if first { - first = false; - } else { - cur_str.push_str(", "); - } + fn rewrite_fn(&mut self, + indent: usize, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: &ast::Unsafety, + abi: &abi::Abi, + vis: ast::Visibility) + -> String + { + // FIXME we'll lose any comments in between parts of the function decl, but anyone + // who comments there probably deserves what they get. + + let mut result = String::with_capacity(1024); + // Vis unsafety abi. + if vis == ast::Visibility::Public { + result.push_str("pub "); + } + if let &ast::Unsafety::Unsafe = unsafety { + result.push_str("unsafe "); + } + if *abi != abi::Rust { + result.push_str("extern "); + result.push_str(&abi.to_string()); + result.push(' '); + } + + // fn foo + result.push_str("fn "); + result.push_str(&token::get_ident(ident)); + + // Generics. + // FIXME convert bounds to where clauses where they get too big or if + // there is a where clause at all. + let lifetimes: &[_] = &generics.lifetimes; + let tys: &[_] = &generics.ty_params; + let where_clause = &generics.where_clause; + if lifetimes.len() + tys.len() > 0 { + let budget = MAX_WIDTH - indent - result.len() - 2; + // TODO might need to insert a newline if the generics are really long + result.push('<'); + + let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); + let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); + let generics_strs: Vec<_> = lt_strs.chain(ty_strs).map(|s| (s, String::new())).collect(); + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + result.len() + 1, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&generics_strs, &fmt)); + + result.push('>'); + } + + let ret_str = match fd.output { + ast::FunctionRetTy::DefaultReturn(_) => String::new(), + ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), + ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), + }; + + // Args. + let args = &fd.inputs; + + let mut budgets = None; + + // Try keeping everything on the same line + if !result.contains("\n") { + // 3 = `() `, space is before ret_string + let used_space = indent + result.len() + 3 + ret_str.len(); + let one_line_budget = if used_space > MAX_WIDTH { + 0 + } else { + MAX_WIDTH - used_space + }; + + let used_space = indent + result.len() + 2; + let max_space = IDEAL_WIDTH + LEEWAY; + if used_space < max_space { + budgets = Some((one_line_budget, + // 2 = `()` + max_space - used_space, + indent + result.len() + 1)); + } + } + + // Didn't work. we must force vertical layout and put args on a newline. + if let None = budgets { + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + // 6 = new indent + `()` + let used_space = indent + 6; + let max_space = IDEAL_WIDTH + LEEWAY; + if used_space > max_space { + // Whoops! bankrupt. + // TODO take evasive action, perhaps kill the indent or something. + } else { + // 5 = new indent + `(` + budgets = Some((0, max_space - used_space, indent + 5)); + } + } + + let (one_line_budget, multi_line_budget, arg_indent) = budgets.unwrap(); + result.push('('); - cur_str.push_str(next_item); + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: arg_indent, + h_width: one_line_budget, + v_width: multi_line_budget, + }; + // TODO dead spans + let mut arg_strs: Vec<_> = args.iter().map(|a| (self.rewrite_fn_input(a), String::new())).collect(); + // Account for sugary self. + if let Some(explicit_self) = explicit_self { + match explicit_self.node { + ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { + let lt_str = match lt { + &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), + &None => String::new(), + }; + let mut_str = match m { + &ast::Mutability::MutMutable => "mut ".to_string(), + &ast::Mutability::MutImmutable => String::new(), + }; + arg_strs[0].0 = format!("&{}{}self", lt_str, mut_str) + } + ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { + arg_strs[0].0 = format!("self: {}", pprust::ty_to_string(ty)) } - ast::PathListItem_::PathListMod{ .. } => {} + _ => {} } } + result.push_str(&write_list(&arg_strs, &fmt)); + + result.push(')'); + + // Where clause. + if where_clause.predicates.len() > 0 { + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + result.push_str("where "); + + let budget = IDEAL_WIDTH + LEEWAY - indent - 10; + let fmt = ListFormatting { + tactic: ListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Always, + indent: indent + 10, + h_width: budget, + v_width: budget, + }; + let where_strs: Vec<_> = where_clause.predicates.iter().map(|p| (self.rewrite_pred(p), String::new())).collect(); + result.push_str(&write_list(&where_strs, &fmt)); + } - assert!(!first); - let cur_line = format!("{}use {}::{{{}}};", indent, path_str, cur_str); - new_str.push_str(&cur_line); + // Return type. + if ret_str.len() > 0 { + // If we've already gone multi-line, or the return type would push + // over the max width, then put the return type on a new line. + if result.contains("\n") || + result.len() + indent + ret_str.len() > MAX_WIDTH { + let indent = indent + 4; + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + result.push_str(&ret_str); + } - new_str + result } - fn formal_args<'v>(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl) -> Option { - // For now, just check the arguments line up and make them per-row if the line is too long. - let args = &fd.inputs; + // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly + fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { + format!("{}: {}", + pprust::pat_to_string(&arg.pat), + pprust::ty_to_string(&arg.ty)) + } - let ret_str = match fd.output { - ast::FunctionRetTy::DefaultReturn(_) => "".to_string(), - ast::FunctionRetTy::NoReturn(_) => " -> !".to_string(), - ast::FunctionRetTy::Return(ref ty) => pprust::ty_to_string(ty), - }; + fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String + { + // TODO dead spans + // TODO assumes we'll always fit on one line... + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, + ref bounded_ty, + ref bounds, + ..}) => { + if bound_lifetimes.len() > 0 { + format!("for<{}> {}: {}", + bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), + pprust::ty_to_string(bounded_ty), + bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) - // TODO don't return, want to do the return type etc. - if args.len() == 0 { - return None; + } else { + format!("{}: {}", + pprust::ty_to_string(bounded_ty), + bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) + } + } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bounds, + ..}) => { + format!("{}: {}", + pprust::lifetime_to_string(lifetime), + bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) + } } + } - // TODO not really using the hi positions - let spans: Vec<_> = args.iter().map(|a| (a.pat.span.lo, a.ty.span.hi)).collect(); - let locs: Vec<_> = spans.iter().map(|&(a, b)| { - (self.codemap.lookup_char_pos(a), self.codemap.lookup_char_pos(b)) - }).collect(); - let first_col = locs[0].0.col.0; + fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String + { + if lifetime.bounds.len() == 0 { + return pprust::lifetime_to_string(&lifetime.lifetime); + } - // Print up to the start of the args. - self.format_missing(spans[0].0); - self.last_pos = spans.last().unwrap().1; + format!("{}: {}", + pprust::lifetime_to_string(&lifetime.lifetime), + lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) + } - let arg_strs: Vec<_> = args.iter().map(|a| format!("{}: {}", - pprust::pat_to_string(&a.pat), - pprust::ty_to_string(&a.ty))).collect(); + fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String + { + match *bound { + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { + self.rewrite_poly_trait_ref(tref) + } + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { + format!("?{}", self.rewrite_poly_trait_ref(tref)) + } + ast::TyParamBound::RegionTyParamBound(ref l) => { + pprust::lifetime_to_string(l) + } + } + } - // Try putting everything on one row: - let mut len = arg_strs.iter().fold(0, |a, b| a + b.len()); - // Account for punctuation and spacing. - len += 2 * arg_strs.len() + 2 * (arg_strs.len()-1); - // Return type. - len += ret_str.len(); - // Opening brace if no where clause. - match fk { - visit::FnKind::FkItemFn(_, &ref g, _, _) | - visit::FnKind::FkMethod(_, &ast::MethodSig { generics: ref g, ..}) - if g.where_clause.predicates.len() > 0 => {} - _ => len += 2 // ` {` + fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String + { + let mut result = String::with_capacity(128); + result.push_str(&token::get_ident(ty_param.ident)); + if ty_param.bounds.len() > 0 { + result.push_str(": "); + result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(", ")); + } + if let Some(ref def) = ty_param.default { + result.push_str(" = "); + result.push_str(&pprust::ty_to_string(&def)); } - len += first_col; - if len <= IDEAL_WIDTH + LEEWAY || args.len() == 1 { - // It should all fit on one line. - return Some(arg_strs.connect(", ")); + result + } + + fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String + { + if t.bound_lifetimes.len() > 0 { + format!("for<{}> {}", + t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), + pprust::path_to_string(&t.trait_ref.path)) + } else { - // TODO multi-line - let mut indent = String::with_capacity(first_col + 2); - indent.push_str(",\n"); - for _ in 0..first_col { indent.push(' '); } - return Some(arg_strs.connect(&indent)); + pprust::path_to_string(&t.trait_ref.path) } } @@ -482,18 +884,28 @@ impl<'a> FmtVisitor<'a> { let remaining_width = width - callee_str.len() - 2; let offset = callee_str.len() + 1 + offset; let arg_count = args.len(); - let args: Vec<_> = args.iter().map(|e| self.rewrite_expr(e, - remaining_width, - offset)).collect(); - debug!("rewrite_call, args: `{}`", args.connect(",")); - - let multi_line = args.iter().any(|s| s.contains('\n')); - let args_width = args.iter().map(|s| s.len()).fold(0, |a, l| a + l); - let over_wide = args_width + (arg_count - 1) * 2 > remaining_width; - let args_str = if multi_line || over_wide { - args.connect(&(",\n".to_string() + &make_indent(offset))) + + let args_str = if arg_count > 0 { + let args: Vec<_> = args.iter().map(|e| (self.rewrite_expr(e, + remaining_width, + offset), String::new())).collect(); + // TODO move this into write_list + let tactics = if args.iter().any(|&(ref s, _)| s.contains('\n')) { + ListTactic::Vertical + } else { + ListTactic::HorizontalVertical + }; + let fmt = ListFormatting { + tactic: tactics, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: remaining_width, + v_width: remaining_width, + }; + write_list(&args, &fmt) } else { - args.connect(", ") + String::new() }; format!("{}({})", callee_str, args_str) @@ -504,7 +916,7 @@ impl<'a> FmtVisitor<'a> { ast::Expr_::ExprLit(ref l) => { match l.node { ast::Lit_::LitStr(ref is, _) => { - return self.rewrite_string(&is, l.span, width, offset); + return self.rewrite_string_lit(&is, l.span, width, offset); } _ => {} } @@ -596,9 +1008,6 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { println!("{}", changes); // FIXME(#5) Should be user specified whether to show or replace. - - // TODO we stop before expansion, but we still seem to get expanded for loops which - // cause problems - probably a rustc bug }; control @@ -606,10 +1015,30 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } fn main() { - let args = std::os::args(); + let args: Vec<_> = std::env::args().collect(); let mut call_ctxt = RustFmtCalls { input_path: None }; rustc_driver::run_compiler(&args, &mut call_ctxt); std::env::set_exit_status(0); + + // TODO unit tests + // let fmt = ListFormatting { + // tactic: ListTactic::Horizontal, + // separator: ",", + // trailing_separator: SeparatorTactic::Vertical, + // indent: 2, + // h_width: 80, + // v_width: 100, + // }; + // let inputs = vec![(format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new())]; + // let s = write_list(&inputs, &fmt); + // println!(" {}", s); } // FIXME comments diff --git a/src/rope.rs b/src/rope.rs index c7ed62afb05..61f543175cf 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -1063,7 +1063,7 @@ impl Lnode { debug_assert!(start + new_str.len() <= self.len); let addr = (self.text as usize + start) as *mut u8; unsafe { - ::std::intrinsics::copy_nonoverlapping_memory(addr, &new_str.as_bytes()[0], new_str.len()); + ::std::intrinsics::volatile_copy_nonoverlapping_memory(addr, &new_str.as_bytes()[0], new_str.len()); } } diff --git a/src/string_buffer.rs b/src/string_buffer.rs index 142231b6d7d..df11e79d318 100644 --- a/src/string_buffer.rs +++ b/src/string_buffer.rs @@ -81,7 +81,11 @@ impl StringBuffer { pub fn cur_offset(&self) -> usize { unsafe { let result = (&*self.last).cur_offset(); - result.unwrap_or_else(|| panic!("Unimplemented cur_offset across node boundaries")) + // TODO + result.unwrap_or_else(|| { + println!(" FIXME Unimplemented cur_offset across node boundaries"); + 0 + }) } } -- cgit 1.4.1-3-g733a5 From 8f5b899c8533046f0eed7a6148ce60ce591b4666 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 14 Apr 2015 13:12:56 +1200 Subject: Use strings.rs rather than local modules --- Cargo.toml | 6 +- src/changes.rs | 2 +- src/mod.rs | 7 +- src/rope.rs | 1281 -------------------------------------------------- src/string_buffer.rs | 312 ------------ 5 files changed, 6 insertions(+), 1602 deletions(-) delete mode 100644 src/rope.rs delete mode 100644 src/string_buffer.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 31edfbbdc06..770a1c1b945 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,9 @@ repository = "https://github.com/nick29581/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" -#[dependencies.reprint] -#reprint = "0.0.1" -#path = "/home/ncameron/reprint" +[dependencies.strings] +strings = "0.0.1" +git = "https://github.com/nrc/strings.rs.git" [[bin]] name = "rustfmt" diff --git a/src/changes.rs b/src/changes.rs index 562aada3103..752ae942f1f 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -13,7 +13,7 @@ // print to files // tests -use string_buffer::StringBuffer; +use strings::string_buffer::StringBuffer; use std::collections::HashMap; use syntax::codemap::{CodeMap, Span}; use std::fmt; diff --git a/src/mod.rs b/src/mod.rs index 34f79e63916..a124eb9e2b4 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -12,8 +12,6 @@ #![feature(box_patterns)] #![feature(rustc_private)] #![feature(collections)] -#![feature(core)] -#![feature(unicode)] #![feature(exit_status)] #![feature(str_char)] @@ -23,7 +21,6 @@ // TODO priorities // Fix fns and methods properly - need visibility in visit -// Use strings crate // Writing output // Working on multiple files, inclding empty ones // Smoke testing till we can use it @@ -36,6 +33,8 @@ extern crate rustc; extern crate rustc_driver; extern crate syntax; +extern crate strings; + use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; @@ -51,8 +50,6 @@ use std::path::PathBuf; use changes::ChangeSet; -pub mod rope; -pub mod string_buffer; mod changes; const IDEAL_WIDTH: usize = 80; diff --git a/src/rope.rs b/src/rope.rs deleted file mode 100644 index 61f543175cf..00000000000 --- a/src/rope.rs +++ /dev/null @@ -1,1281 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// TODO -// ---- -// docs - mod docs, item docs -// tests -// pull out into its own crate -// impl Default, Extend -// impl DoubleEndedIter and ExactSizeIter for RopeChars -// better allocation -// balancing? - -extern crate unicode; -use std::fmt; -use std::ops::Range; -use std::num::{SignedInt, Int}; - -// A Rope, based on an unbalanced binary tree. The rope is somewhat special in -// that it tracks positions in the source text. So when locating a position in -// the rope, the user can use either a current position in the text or a -// position in the source text, which the Rope will adjust to a current position -// whilst searching. -pub struct Rope { - root: Node, - len: usize, - src_len: usize, - // FIXME: Allocation is very dumb at the moment, we always add another - // buffer for every inserted string and we never resuse or collect old - // memory - storage: Vec> -} - -// A view over a portion of a Rope. Analagous to string slices (`str`); -pub struct RopeSlice<'rope> { - // All nodes which make up the slice, in order. - nodes: Vec<&'rope Lnode>, - // The offset of the start point in the first node. - start: usize, - // The length of text in the last node. - len: usize, -} - -// An iterator over the chars in a rope. -pub struct RopeChars<'rope> { - data: RopeSlice<'rope>, - cur_node: usize, - cur_byte: usize, - abs_byte: usize, -} - -impl Rope { - // Create an empty rope. - pub fn new() -> Rope { - Rope { - root: Node::empty_inner(), - len: 0, - src_len: 0, - storage: vec![], - } - } - - // Uses text as initial storage. - pub fn from_string(text: String) -> Rope { - // TODO should split very large texts into segments as we insert - - let mut result = Rope::new(); - result.insert(0, text); - result.fix_src(); - result - } - - // When initialising a rope, indicates that the rope is complete wrt the - // source text. - fn fix_src(&mut self) { - self.root.fix_src(); - self.src_len = self.len; - } - - // Length of the rope. - pub fn len(&self) -> usize { - self.len - } - - pub fn insert_copy(&mut self, start: usize, text: &str) { - // FIXME If we did clever things with allocation, we could do better here. - self.insert(start, text.to_string()); - } - - pub fn insert(&mut self, start: usize, text: String) { - self.insert_inner(start, - text, - |this, node| this.root.insert(node, start, start)) - } - - pub fn src_insert(&mut self, start: usize, text: String) { - self.insert_inner(start, - text, - |this, node| this.root.src_insert(node, start, start)) - } - - fn insert_inner(&mut self, - start: usize, - text: String, - do_insert: F) - where F: Fn(&mut Rope, Box) -> NodeAction - { - if text.len() == 0 { - return; - } - - debug_assert!(start <= self.src_len, "insertion out of bounds of rope"); - - let len = text.len(); - let storage = text.into_bytes(); - let new_node = box Node::new_leaf(&storage[..][0] as *const u8, len, 0); - self.storage.push(storage); - - match do_insert(self, new_node) { - NodeAction::Change(n, adj) => { - assert!(adj as usize == len); - self.root = *n; - } - NodeAction::Adjust(adj) => { - assert!(adj as usize == len); - } - _ => panic!("Unexpected action") - } - self.len += len; - } - - pub fn push(&mut self, text: String) { - let len = self.len(); - self.insert(len, text); - } - - pub fn push_copy(&mut self, text: &str) { - // If we did clever things with allocation, we could do better here - let len = self.len(); - self.insert(len, text.to_string()); - } - - pub fn remove(&mut self, start: usize, end: usize) { - self.remove_inner(start, end, |this| this.root.remove(start, end, start)) - } - - pub fn src_remove(&mut self, start: usize, end: usize) { - self.remove_inner(start, end, |this| this.root.src_remove(start, end, start)) - } - - fn remove_inner(&mut self, - start: usize, - end: usize, - do_remove: F) - where F: Fn(&mut Rope) -> NodeAction - { - assert!(end >= start); - if start == end { - return; - } - - match do_remove(self) { - NodeAction::None => {} - NodeAction::Remove => { - self.root = Node::empty_inner(); - self.len = 0; - } - NodeAction::Adjust(adj) => self.len = (self.len as isize + adj) as usize, - NodeAction::Change(node, adj) => { - self.root = *node; - self.len = (self.len as isize + adj) as usize; - } - } - } - - // TODO src_replace - // TODO src_replace_str - - // This can go horribly wrong if you overwrite a grapheme of different size. - // It is the callers responsibility to ensure that the grapheme at point start - // has the same size as new_char. - pub fn replace(&mut self, start: usize, new_char: char) { - assert!(start + new_char.len_utf8() <= self.len); - // This is pretty wasteful in that we're allocating for no point, but - // I think that is better than duplicating a bunch of code. - // It should be possible to view a &char as a &[u8] somehow, and then - // we can optimise this (FIXME). - self.replace_str(start, &new_char.to_string()[..]); - } - - pub fn replace_str(&mut self, start: usize, new_str: &str) { - assert!(start + new_str.len() <= self.len); - self.root.replace(start, new_str); - } - - // Note, this is not necessarily cheap. - pub fn col_for_src_loc(&self, src_loc: usize) -> usize { - assert!(src_loc <= self.src_len); - match self.root.col_for_src_loc(src_loc) { - Search::Done(c) | Search::Continue(c) => c - } - } - - pub fn slice(&self, Range { start, end }: Range) -> RopeSlice { - debug_assert!(end > start && start <= self.len && end <= self.len); - if start == end { - return RopeSlice::empty(); - } - - let mut result = RopeSlice::empty(); - self.root.find_slice(start, end, &mut result); - result - } - - pub fn full_slice(&self) -> RopeSlice { - self.slice(0..self.len) - } - - pub fn src_slice(&self, Range { start, end }: Range) -> RopeSlice { - debug_assert!(end > start && start <= self.src_len && end <= self.src_len); - if start == end { - return RopeSlice::empty(); - } - - let mut result = RopeSlice::empty(); - self.root.find_src_slice(start, end, &mut result); - result - } - - pub fn chars(&self) -> RopeChars { - RopeChars { - data: self.full_slice(), - cur_node: 0, - cur_byte: 0, - abs_byte: 0, - } - } -} - -impl<'rope> RopeSlice<'rope> { - fn empty<'r>() -> RopeSlice<'r> { - RopeSlice { - nodes: vec![], - start: 0, - len: 0, - } - } -} - -impl<'rope> Iterator for RopeChars<'rope> { - type Item = (char, usize); - fn next(&mut self) -> Option<(char, usize)> { - if self.cur_node >= self.data.nodes.len() { - return None; - } - - let byte = self.abs_byte; - let node = self.data.nodes[self.cur_node]; - if self.cur_byte >= node.len { - self.cur_byte = 0; - self.cur_node += 1; - return self.next(); - } - - let result = self.read_char(); - return Some((result, byte)); - } -} - -impl<'rope> RopeChars<'rope> { - fn read_char(&mut self) -> char { - let first_byte = self.read_byte(); - let width = unicode::str::utf8_char_width(first_byte); - if width == 1 { - return first_byte as char - } - if width == 0 { - panic!("non-utf8 char in rope"); - } - let mut buf = [first_byte, 0, 0, 0]; - { - let mut start = 1; - while start < width { - buf[start] = self.read_byte(); - start += 1; - } - } - match ::std::str::from_utf8(&buf[..width]).ok() { - Some(s) => s.char_at(0), - None => panic!("bad chars in rope") - } - } - - fn read_byte(&mut self) -> u8 { - let node = self.data.nodes[self.cur_node]; - let addr = node.text as usize + self.cur_byte; - self.cur_byte += 1; - self.abs_byte += 1; - let addr = addr as *const u8; - unsafe { - *addr - } - } -} - -impl ::std::str::FromStr for Rope { - type Err = (); - fn from_str(text: &str) -> Result { - // TODO should split large texts into segments as we insert - - let mut result = Rope::new(); - result.insert_copy(0, text); - result.fix_src(); - Ok(result) - } -} - -impl<'a> fmt::Display for RopeSlice<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - if self.nodes.len() == 0 { - return Ok(()); - } - - let last_idx = self.nodes.len() - 1; - for (i, n) in self.nodes.iter().enumerate() { - let mut ptr = n.text; - let mut len = n.len; - if i == 0 { - ptr = (ptr as usize + self.start) as *const u8; - len -= self.start; - } - if i == last_idx { - len = self.len; - } - unsafe { - try!(write!(fmt, - "{}", - ::std::str::from_utf8(::std::slice::from_raw_parts(ptr, len)).unwrap())); - } - } - Ok(()) - } -} - -impl<'a> fmt::Debug for RopeSlice<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let last_idx = self.nodes.len() - 1; - for (i, n) in self.nodes.iter().enumerate() { - let mut ptr = n.text; - let mut len = n.len; - if i == 0 { - ptr = (ptr as usize + self.start) as *const u8; - len -= self.start; - } else { - try!(write!(fmt, "|")); - } - if i == last_idx { - len = self.len; - } - unsafe { - try!(write!(fmt, - "\"{}\"", - ::std::str::from_utf8(::std::slice::from_raw_parts(ptr, len)).unwrap())); - } - } - Ok(()) - } -} - -impl fmt::Display for Rope { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "{}", self.root) - } -} - -impl fmt::Debug for Rope { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "{:?}", self.root) - } -} - -impl fmt::Display for Node { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Node::InnerNode(Inode { ref left, ref right, .. }) => { - if let Some(ref left) = *left { - write!(fmt, "{}", left) - } else { - Ok(()) - }.and_then(|_| if let Some(ref right) = *right { - write!(fmt, "{}", right) - } else { - Ok(()) - }) - } - Node::LeafNode(Lnode{ ref text, len, .. }) => { - unsafe { - write!(fmt, - "{}", - ::std::str::from_utf8(::std::slice::from_raw_parts(*text, len)).unwrap()) - } - } - } - } -} - -impl fmt::Debug for Node { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Node::InnerNode(Inode { ref left, ref right, weight, .. }) => { - try!(write!(fmt, "(")); - if let Some(ref left) = *left { - try!(write!(fmt, "left: {:?}", &**left)); - } else { - try!(write!(fmt, "left: ()")); - } - try!(write!(fmt, ", ")); - if let Some(ref right) = *right { - try!(write!(fmt, "right: {:?}", &**right)); - } else { - try!(write!(fmt, "right: ()")); - } - write!(fmt, "; {})", weight) - } - Node::LeafNode(Lnode{ ref text, len, .. }) => { - unsafe { - write!(fmt, - "(\"{}\"; {})", - ::std::str::from_utf8(::std::slice::from_raw_parts(*text, len)).unwrap(), - len) - } - } - } - } -} - -#[derive(Clone, Eq, PartialEq)] -enum Node { - InnerNode(Inode), - LeafNode(Lnode), -} - -#[derive(Clone, Eq, PartialEq)] -struct Inode { - weight: usize, - src_weight: usize, - left: Option>, - right: Option>, -} - -#[derive(Clone, Eq, PartialEq)] -struct Lnode { - text: *const u8, - len: usize, - // text + src_offset = src text (src_offset should always be <= 0) - src_offset: isize, -} - -impl Node { - fn empty_inner() -> Node { - Node::InnerNode(Inode { - left: None, - right: None, - weight: 0, - src_weight: 0, - }) - } - - fn new_inner(left: Option>, - right: Option>, - weight: usize, - src_weight: usize) - -> Node { - Node::InnerNode(Inode { - left: left, - right: right, - weight: weight, - src_weight: src_weight, - }) - } - - fn new_leaf(text: *const u8, len: usize, src_offset: isize) -> Node { - Node::LeafNode(Lnode { - text: text, - len: len, - src_offset: src_offset, - }) - } - - fn len(&self) -> usize { - match *self { - Node::InnerNode(Inode { weight, ref right, .. }) => { - match *right { - Some(ref r) => weight + r.len(), - None => weight - } - } - Node::LeafNode(Lnode { len, .. }) => len, - } - } - - fn fix_src(&mut self) { - match *self { - Node::InnerNode(ref mut i) => i.fix_src(), - Node::LeafNode(ref mut l) => { - l.src_offset = 0; - }, - } - } - - // Most of these methods are just doing dynamic dispatch, TODO use a macro - - // precond: start < end - fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { - match *self { - Node::InnerNode(ref mut i) => i.remove(start, end, src_start), - Node::LeafNode(ref mut l) => l.remove(start, end, src_start), - } - } - - fn src_remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { - match *self { - Node::InnerNode(ref mut i) => i.src_remove(start, end, src_start), - Node::LeafNode(ref mut l) => { - debug!("src_remove: pre-adjust {}-{}; {}", start, end, l.src_offset); - let start = minz(start as isize + l.src_offset); - let end = minz(end as isize + l.src_offset); - let src_start = minz(src_start as isize + l.src_offset); - debug!("src_remove: post-adjust {}-{}, {}", start, end, src_start); - if end > start { - l.remove(start as usize, end as usize, src_start as usize) - } else { - NodeAction::None - } - } - } - } - - fn insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { - match *self { - Node::InnerNode(ref mut i) => i.insert(node, start, src_start), - Node::LeafNode(ref mut l) => l.insert(node, start, src_start), - } - } - - fn src_insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { - match *self { - Node::InnerNode(ref mut i) => i.src_insert(node, start, src_start), - Node::LeafNode(ref mut l) => { - debug!("src_insert: pre-adjust {}, {}; {}", start, src_start, l.src_offset); - let start = minz(start as isize + l.src_offset); - let src_start = minz(src_start as isize + l.src_offset); - debug!("src_insert: post-adjust {}, {}", start, src_start); - l.insert(node, start as usize, src_start as usize) - } - } - } - - fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { - match *self { - Node::InnerNode(ref i) => i.find_slice(start, end, slice), - Node::LeafNode(ref l) => l.find_slice(start, end, slice), - } - } - - fn find_src_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { - match *self { - Node::InnerNode(ref i) => i.find_src_slice(start, end, slice), - Node::LeafNode(ref l) => { - debug!("find_src_slice: pre-adjust {}-{}; {}", start, end, l.src_offset); - let start = minz(start as isize + l.src_offset); - let end = minz(end as isize + l.src_offset); - debug!("find_src_slice: post-adjust {}-{}", start, end); - if end > start { - l.find_slice(start as usize, end as usize, slice); - } - } - } - } - - fn replace(&mut self, start: usize, new_str: &str) { - match *self { - Node::InnerNode(ref mut i) => i.replace(start, new_str), - Node::LeafNode(ref mut l) => l.replace(start, new_str), - } - } - - fn col_for_src_loc(&self, src_loc: usize) -> Search { - match *self { - Node::InnerNode(ref i) => i.col_for_src_loc(src_loc), - Node::LeafNode(ref l) => l.col_for_src_loc(src_loc), - } - } - - fn find_last_char(&self, c: char) -> Option { - match *self { - Node::InnerNode(ref i) => i.find_last_char(c), - Node::LeafNode(ref l) => l.find_last_char(c), - } - } -} - -#[derive(Debug, Clone, Eq, PartialEq)] -enum NodeAction { - None, - Remove, - Adjust(isize), // Arg is the length of the old node - the length of the newly adjusted node. - Change(Box, isize) // Args are the new node and the change in length. -} - -impl Inode { - fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { - debug!("Inode::remove: {}, {}, {}", start, end, self.weight); - - let left_action = if start <= self.weight { - if let Some(ref mut left) = self.left { - left.remove(start, end, src_start) - } else { - panic!(); - } - } else { - NodeAction::None - }; - - let right_action = if end > self.weight { - if let Some(ref mut right) = self.right { - let start = if start < self.weight { - 0 - } else { - start - self.weight - }; - let src_start = if src_start < self.src_weight { - 0 - } else { - src_start - self.src_weight - }; - right.remove(start, end - self.weight, src_start) - } else { - panic!(); - } - } else { - NodeAction::None - }; - - - if left_action == NodeAction::Remove && right_action == NodeAction::Remove || - left_action == NodeAction::Remove && self.right.is_none() || - right_action == NodeAction::Remove && self.left.is_none() { - return NodeAction::Remove; - } - - if left_action == NodeAction::Remove { - return NodeAction::Change(self.right.clone().unwrap(), - -(self.weight as isize)); - } - if right_action == NodeAction::Remove { - return NodeAction::Change(self.left.clone().unwrap(), - -(self.right.as_ref().map(|n| n.len()).unwrap() as isize)); - } - - let mut total_adj = 0; - if let NodeAction::Change(ref n, adj) = left_action { - self.left = Some(n.clone()); - self.weight = (self.weight as isize + adj) as usize; - total_adj += adj; - } - if let NodeAction::Change(ref n, adj) = right_action { - self.right = Some(n.clone()); - total_adj += adj; - } - - if let NodeAction::Adjust(adj) = left_action { - self.weight = (self.weight as isize + adj) as usize; - total_adj += adj; - } - if let NodeAction::Adjust(adj) = right_action { - total_adj += adj; - } - - return NodeAction::Adjust(total_adj); - } - - fn src_remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { - // TODO refactor with remove - - debug!("Inode::src_remove: {}, {}, {}/{}", start, end, self.src_weight, self.weight); - - let left_action = if start <= self.src_weight { - if let Some(ref mut left) = self.left { - left.src_remove(start, end, src_start) - } else { - panic!(); - } - } else { - NodeAction::None - }; - - let right_action = if end > self.src_weight { - if let Some(ref mut right) = self.right { - let start = if start < self.src_weight { - 0 - } else { - start - self.src_weight - }; - let src_start = if src_start < self.src_weight { - 0 - } else { - src_start - self.src_weight - }; - right.src_remove(start, end - self.src_weight, src_start) - } else { - panic!(); - } - } else { - NodeAction::None - }; - - - if left_action == NodeAction::Remove && right_action == NodeAction::Remove || - left_action == NodeAction::Remove && self.right.is_none() || - right_action == NodeAction::Remove && self.left.is_none() { - return NodeAction::Remove; - } - - if left_action == NodeAction::Remove { - return NodeAction::Change(self.right.clone().unwrap(), - -(self.weight as isize)); - } - if right_action == NodeAction::Remove { - return NodeAction::Change(self.left.clone().unwrap(), - -(self.right.as_ref().map(|n| n.len()).unwrap() as isize)); - } - - let mut total_adj = 0; - if let NodeAction::Change(ref n, adj) = left_action { - self.left = Some(n.clone()); - self.weight = (self.weight as isize + adj) as usize; - total_adj += adj; - } - if let NodeAction::Change(ref n, adj) = right_action { - self.right = Some(n.clone()); - total_adj += adj; - } - - if let NodeAction::Adjust(adj) = left_action { - self.weight = (self.weight as isize + adj) as usize; - total_adj += adj; - } - if let NodeAction::Adjust(adj) = right_action { - total_adj += adj; - } - - return NodeAction::Adjust(total_adj); - } - - fn insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { - let mut total_adj = 0; - if start <= self.weight { - let action = if let Some(ref mut left) = self.left { - left.insert(node, start, src_start) - } else { - assert!(self.weight == 0); - let len = node.len() as isize; - NodeAction::Change(node, len) - }; - - match action { - NodeAction::Change(n, adj) => { - self.left = Some(n); - self.weight += adj as usize; - total_adj += adj; - } - NodeAction::Adjust(adj) => { - self.weight += adj as usize; - total_adj += adj; - } - _ => panic!("Unexpected action"), - } - } else { - let action = if let Some(ref mut right) = self.right { - assert!(start >= self.weight); - assert!(src_start >= self.src_weight); - right.insert(node, start - self.weight, src_start - self.src_weight) - } else { - let len = node.len() as isize; - NodeAction::Change(node, len) - }; - - match action { - NodeAction::Change(n, adj) => { - self.right = Some(n); - total_adj += adj; - } - NodeAction::Adjust(adj) => total_adj += adj, - _ => panic!("Unexpected action"), - } - } - - NodeAction::Adjust(total_adj) - } - - fn src_insert(&mut self, node: Box, start: usize, src_start: usize) -> NodeAction { - let mut total_adj = 0; - if start <= self.src_weight { - let action = if let Some(ref mut left) = self.left { - left.src_insert(node, start, src_start) - } else { - let len = node.len() as isize; - NodeAction::Change(node, len) - }; - - match action { - NodeAction::Change(n, adj) => { - self.left = Some(n); - self.weight += adj as usize; - total_adj += adj; - } - NodeAction::Adjust(adj) => { - self.weight += adj as usize; - total_adj += adj; - } - _ => panic!("Unexpected action"), - } - } else { - let action = if let Some(ref mut right) = self.right { - assert!(start >= self.src_weight); - assert!(src_start >= self.src_weight); - right.src_insert(node, start - self.src_weight, src_start - self.src_weight) - } else { - let len = node.len() as isize; - NodeAction::Change(node, len) - }; - - match action { - NodeAction::Change(n, adj) => { - self.right = Some(n); - total_adj += adj; - } - NodeAction::Adjust(adj) => total_adj += adj, - _ => panic!("Unexpected action"), - } - } - - NodeAction::Adjust(total_adj) - } - - fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { - debug!("Inode::find_slice: {}, {}, {}", start, end, self.weight); - if start < self.weight { - self.left.as_ref().unwrap().find_slice(start, end, slice); - } - if end > self.weight { - let start = if start < self.weight { - 0 - } else { - start - self.weight - }; - self.right.as_ref().unwrap().find_slice(start, end - self.weight, slice) - } - } - - fn find_src_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { - debug!("Inode::find_src_slice: {}, {}, {}", start, end, self.src_weight); - if start < self.src_weight && self.left.is_some() { - self.left.as_ref().unwrap().find_src_slice(start, end, slice); - } - if end > self.src_weight && self.right.is_some() { - let start = if start < self.src_weight { - 0 - } else { - start - self.src_weight - }; - self.right.as_ref().unwrap().find_src_slice(start, end - self.src_weight, slice) - } - } - - fn replace(&mut self, start: usize, new_str: &str) { - debug!("Inode::replace: {}, {}, {}", start, new_str, self.weight); - let end = start + new_str.len(); - if start < self.weight { - if let Some(ref mut left) = self.left { - left.replace(start, &new_str[..::std::cmp::min(self.weight-start, new_str.len())]); - } else { - panic!(); - } - } - if end > self.weight { - let (start, offset) = if start < self.weight { - (0, self.weight - start) - } else { - (start - self.weight, 0) - }; - if let Some(ref mut right) = self.right { - right.replace(start, &new_str[offset..]); - } else { - panic!(); - } - } - } - - fn fix_src(&mut self) { - self.src_weight = self.weight; - if let Some(ref mut left) = self.left { - left.fix_src(); - } - if let Some(ref mut right) = self.right { - right.fix_src(); - } - } - - fn col_for_src_loc(&self, src_loc: usize) -> Search { - debug!("Inode::col_for_src_loc: {}, {}", src_loc, self.src_weight); - let result = if src_loc < self.src_weight { - if self.left.is_some() { - Some(self.left.as_ref().unwrap().col_for_src_loc(src_loc)) - } else { - None - } - } else { - None - }; - if result.is_none() { - if self.right.is_some() { - match self.right.as_ref().unwrap().col_for_src_loc(src_loc - self.src_weight) { - Search::Continue(c) if self.left.is_some() => { - // TODO broken - need number of chars, not bytes - match self.left.as_ref().unwrap().find_last_char('\n') { - Some(l) => { - Search::Done((self.weight - l - 1) + c) - } - None => { - Search::Continue(c + self.weight) - } - } - } - result => result, - } - } else { - panic!("Can't look up source location"); - } - } else { - // TODO don't do it this way - result.unwrap() - } - } - - fn find_last_char(&self, c: char) -> Option { - // TODO use map or something - match self.right { - Some(ref right) => match right.find_last_char(c) { - Some(x) => return Some(x), - None => {}, - }, - None => {} - } - match self.left { - Some(ref left) => match left.find_last_char(c) { - Some(x) => return Some(x), - None => {}, - }, - None => {} - } - None - } -} - -impl Lnode { - fn remove(&mut self, start: usize, end: usize, src_start: usize) -> NodeAction { - debug!("Lnode::remove: {}, {}, {}", start, end, self.len); - assert!(start <= self.len); - - if start == 0 && end >= self.len { - // The removal span includes us, remove ourselves. - return NodeAction::Remove; - } - - let old_len = self.len; - if start == 0 { - // Truncate the left of the node. - self.text = (self.text as usize + end) as *const u8; - self.len = old_len - end; - let delta = self.len as isize - old_len as isize; - self.src_offset += delta; - return NodeAction::Adjust(delta); - } - - if end >= self.len { - // Truncate the right of the node. - self.len = start; - return NodeAction::Adjust(self.len as isize - old_len as isize); - } - - let delta = -((end - start) as isize); - // Split the node (span to remove is in the middle of the node). - let new_node = Node::new_inner( - Some(box Node::new_leaf(self.text, start, self.src_offset)), - Some(box Node::new_leaf((self.text as usize + end) as *const u8, - old_len - end, - self.src_offset + delta)), - start, - src_start); - return NodeAction::Change(box new_node, delta); - } - - fn insert(&mut self, mut node: Box, start: usize, src_start: usize) -> NodeAction { - match node { - box Node::LeafNode(ref mut node) => node.src_offset = self.src_offset, - _ => panic!() - } - - let len = node.len(); - if start == 0 { - // Insert at the start of the node - let new_node = box Node::new_inner(Some(node), - Some(box Node::LeafNode(self.clone())), - len, - 0); - return NodeAction::Change(new_node, len as isize) - } - - if start == self.len { - // Insert at the end of the node - let new_node = box Node::new_inner(Some(box Node::LeafNode(self.clone())), - Some(node), - self.len, - self.len); - return NodeAction::Change(new_node, len as isize) - } - - // Insert into the middle of the node - let left = Some(box Node::new_leaf(self.text, start, self.src_offset)); - let new_left = box Node::new_inner(left, Some(node), start, src_start); - let right = Some(box Node::new_leaf((self.text as usize + (start)) as *const u8, - self.len - start, - self.src_offset)); - let new_node = box Node::new_inner(Some(new_left), right, start + len, src_start); - - return NodeAction::Change(new_node, len as isize) - } - - fn find_slice<'a>(&'a self, start: usize, end: usize, slice: &mut RopeSlice<'a>) { - debug!("Lnode::find_slice: {}, {}, {}, {}", start, end, self.len, self.src_offset); - debug_assert!(start < self.len, "Shouldn't have called this fn, we're out of bounds"); - - slice.nodes.push(self); - let mut len = ::std::cmp::min(end, self.len); - if start > 0 { - slice.start = start; - len -= start; - } - slice.len = len; - } - - fn replace(&mut self, start: usize, new_str: &str) { - debug!("Lnode::replace: {}, {}, {}", start, new_str, self.len); - debug_assert!(start + new_str.len() <= self.len); - let addr = (self.text as usize + start) as *mut u8; - unsafe { - ::std::intrinsics::volatile_copy_nonoverlapping_memory(addr, &new_str.as_bytes()[0], new_str.len()); - } - } - - fn col_for_src_loc(&self, src_loc: usize) -> Search { - debug!("Lnode::col_for_src_loc {}; {}; {}", src_loc, self.len, self.src_offset); - let loc = if (src_loc as isize) > (self.len as isize - self.src_offset) { - // The source location we are looking up has been removed - self.len as isize - } else { - (src_loc as isize + self.src_offset) - }; - - // FIXME if '/n' as u8 is part of a multi-byte grapheme, then this will - // cause false positives. - let mut i = loc - 1; - while i >= 0 { - unsafe { - let c = *((self.text as usize + i as usize) as *const u8); - if c as char == '\n' { - debug!("Lnode::col_for_src_loc, return Done({})", loc - i - 1); - return Search::Done((loc - i - 1) as usize) - } - } - i -= 1; - } - - let loc = minz(loc) as usize; - debug!("Lnode::col_for_src_loc, return Continue({})", loc); - Search::Continue(loc) - } - - fn find_last_char(&self, needle: char) -> Option { - // FIXME due to multi-byte chars, this will give false positives - // FIXME use std::str::GraphemeIndices to do this! - let mut loc = self.len as isize - 1; - while loc >= 0 { - unsafe { - let c = *((self.text as usize + loc as usize) as *const u8); - if c as char == needle { - return Some(loc as usize) - } - } - loc -= 1; - } - - return None - } -} - -// The state of searching through a rope. -enum Search { - // TODO comment - Continue(usize), - // TODO comment - Done(usize) -} - -fn minz(x: I) -> I { - if x.is_negative() { - return I::zero(); - } - - x -} - -#[cfg(test)] -mod test { - use super::*; - // FIXME is this a Rust bug? Why is minz not imported by the glob import? - use super::minz; - - #[test] - fn test_new() { - let r = Rope::new(); - assert!(r.len() == 0); - assert!(r.to_string() == ""); - - let r = Rope::from_string("Hello world!".to_string()); - assert!(r.len() == 12); - assert!(r.to_string() == "Hello world!"); - } - - #[test] - fn test_minz() { - let x: i32 = 0; - assert!(super::minz(x) == 0); - let x: i32 = 42; - assert!(minz(x) == 42); - let x: i32 = -42; - assert!(minz(x) == 0); - let x: isize = 0; - assert!(minz(x) == 0); - let x: isize = 42; - assert!(minz(x) == 42); - let x: isize = -42; - assert!(minz(x) == 0); - } - - #[test] - fn test_from_string() { - let r: Rope = "Hello world!".parse().unwrap(); - assert!(r.to_string() == "Hello world!"); - } - - #[test] - fn test_remove() { - let mut r: Rope = "Hello world!".parse().unwrap(); - r.remove(0, 10); - assert!(r.to_string() == "d!"); - assert!(r.src_slice(0..5).to_string() == ""); - assert!(r.src_slice(10..12).to_string() == "d!"); - - let mut r: Rope = "Hello world!".parse().unwrap(); - r.remove(4, 12); - assert!(r.to_string() == "Hell"); - // TODO - //assert!(r.src_slice(0..4).to_string() == "Hell"); - //assert!(r.src_slice(10..12).to_string() == ""); - - let mut r: Rope = "Hello world!".parse().unwrap(); - r.remove(4, 10); - assert!(r.to_string() == "Helld!"); - // TODO - //assert!(r.src_slice(1..5).to_string() == "ell"); - assert!(r.src_slice(9..12).to_string() == "d!"); - } - - #[test] - fn test_insert_copy() { - let mut r: Rope = "Hello world!".parse().unwrap(); - r.insert_copy(0, "foo"); - assert!(r.to_string() == "fooHello world!"); - assert!(r.slice(2..8).to_string() == "oHello"); - - let mut r: Rope = "Hello world!".parse().unwrap(); - r.insert_copy(12, "foo"); - assert!(r.to_string() == "Hello world!foo"); - assert!(r.slice(2..8).to_string() == "llo wo"); - - let mut r: Rope = "Hello world!".parse().unwrap(); - r.insert_copy(5, "foo"); - assert!(r.to_string() == "Hellofoo world!"); - assert!(r.slice(2..8).to_string() == "llofoo"); - } - - #[test] - fn test_push_copy() { - let mut r: Rope = "Hello world!".parse().unwrap(); - r.push_copy("foo"); - assert!(r.to_string() == "Hello world!foo"); - assert!(r.slice(2..8).to_string() == "llo wo"); - } - - #[test] - fn test_insert_replace() { - let mut r: Rope = "hello worl\u{00bb0}!".parse().unwrap(); - r.insert_copy(5, "bb"); - assert!(r.to_string() == "hellobb worlர!"); - r.replace(0, 'H'); - r.replace(15, '~'); - r.replace_str(5, "fo\u{00cb0}"); - assert!(r.to_string() == "Hellofoರrlர~"); - assert!(r.slice(0..10).to_string() == "Hellofoರ"); - assert!(r.slice(5..10).to_string() == "foರ"); - assert!(r.slice(10..15).to_string() == "rlர"); - - let expected = "Hellofoರrlர~"; - let mut byte_pos = 0; - for ((c, b), e) in r.chars().zip(expected.chars()) { - assert!(c == e); - assert!(b == byte_pos); - byte_pos += e.len_utf8(); - } - } - - #[test] - fn test_src_insert_remove_col_for_src_loc() { - let mut r: Rope = "hello\n world!".parse().unwrap(); - r.src_insert(4, "foo".to_string()); - r.src_insert(5, "bar".to_string()); - assert!(r.to_string() == "hellfooobar\n world!"); - - r.src_remove(2, 4); - r.src_remove(10, 12); - assert!(r.to_string() == "hefooobar\n wor!"); - - let expected = "hefooobar\n wor!"; - let mut byte_pos = 0; - for ((c, b), e) in r.chars().zip(expected.chars()) { - assert!(c == e); - assert!(b == byte_pos); - byte_pos += e.len_utf8(); - } - - let expected = [0, 1, 2, 2, 5, 9, 0, 1, 2, 3, 4, 4, 4]; - for i in 0..13 { - assert!(r.col_for_src_loc(i) == expected[i]); - } - } - - #[test] - fn test_src_insert() { - let mut r: Rope = "Hello world!".parse().unwrap(); - r.src_insert(4, "foo".to_string()); - r.src_insert(0, "foo".to_string()); - r.src_insert(12, "foo".to_string()); - assert!(r.to_string() == "fooHellfooo world!foo"); - r.src_insert(4, "bar".to_string()); - r.src_insert(5, "bar".to_string()); - r.src_insert(3, "bar".to_string()); - r.src_insert(0, "bar".to_string()); - r.src_insert(12, "bar".to_string()); - assert!(r.to_string() == "barfooHelbarlbarfooobar world!barfoo"); - } -} diff --git a/src/string_buffer.rs b/src/string_buffer.rs deleted file mode 100644 index df11e79d318..00000000000 --- a/src/string_buffer.rs +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A specialised string-like structure that is optimised for appending text and -// sequential reading. - -// TODO -// Debug -// docs -// char iterator -// chars -> char_indices and flip order of char/index -// Eq - -extern crate unicode; - -use std::str::FromStr; -use std::{cmp, fmt}; - -const MAX_CAPACITY: usize = 0xffff; -const INIT_CAPACITY: usize = 0xff; - -pub struct StringBuffer { - first: Box, - // last: &self StringNode - // Optimisation that saves us from walking the whole list of nodes everytime - // we append a string. - last: *mut StringNode, - // The length of the whole StringBuffer. - len: usize, -} - -pub struct Chars<'a> { - // Node we're currently iterating over. - cur_node: &'a StringNode, - // Byte in cur_node. - cur_byte: usize, - // Byte since start of StringBuffer. - abs_byte: usize, -} - -struct StringNode { - data: String, - next: Option>, -} - -impl StringBuffer { - pub fn new() -> StringBuffer { - StringBuffer::with_capacity(INIT_CAPACITY) - } - - pub fn with_capacity(capacity: usize) -> StringBuffer { - let mut result = StringBuffer { - first: box StringNode::with_capacity(capacity), - last: 0 as *mut StringNode, - len: 0, - }; - result.last = &mut *result.first; - result - } - - pub fn push_str(&mut self, text: &str) { - self.len += text.len(); - unsafe { - // Safety invariant: the `last` field will only ever point to - // a node owned by self, and will live until destruction of self. - self.last = (&mut *self.last).push_str(text); - } - } - - // Returns the number of characters from start of the last line in the - // StringBuffer. - // Note that it is possible for this operation to take a long time in - // pathological cases (lots of nodes, few line breaks). - pub fn cur_offset(&self) -> usize { - unsafe { - let result = (&*self.last).cur_offset(); - // TODO - result.unwrap_or_else(|| { - println!(" FIXME Unimplemented cur_offset across node boundaries"); - 0 - }) - } - } - - pub fn chars<'a>(&'a self) -> Chars<'a> { - Chars::new(&self.first) - } -} - -impl StringNode { - fn with_capacity(capacity: usize) -> StringNode { - StringNode { - data: String::with_capacity(capacity), - next: None, - } - } - - // Returns a reference to the new last node. - fn push_str(&mut self, text: &str) -> &mut StringNode { - if let Some(ref mut n) = self.next { - return n.push_str(text); - } - - if self.data.capacity() - self.data.len() >= text.len() { - self.data.push_str(text); - self - } else { - self.data.shrink_to_fit(); - let next_cap = cmp::min(cmp::max(self.data.capacity(), - INIT_CAPACITY) * 2, - MAX_CAPACITY); - let next_cap = cmp::max(next_cap, text.len()); - self.next = Some(box StringNode::with_capacity(next_cap)); - let next = self.next.as_mut().unwrap(); - next.push_str(text); - &mut **next - } - } - - // None if there is no new line in this node. - fn cur_offset(&self) -> Option { - self.data.rfind('\n').map(|i| self.data.len() - i - 1) - } -} - -impl FromStr for StringBuffer { - type Err = (); - fn from_str(text: &str) -> Result { - let mut result = StringBuffer::with_capacity(cmp::max(INIT_CAPACITY, text.len())); - result.push_str(text); - Ok(result) - } -} - -impl fmt::Display for StringBuffer { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fn fmt_node(node: &StringNode, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - try!(write!(fmt, "{}", node.data)); - if let Some(ref n) = node.next { - fmt_node(n, fmt) - } else { - Ok(()) - } - } - - fmt_node(&self.first, fmt) - } -} - -impl<'a> Iterator for Chars<'a> { - type Item = (char, usize); - - fn next(&mut self) -> Option<(char, usize)> { - while self.cur_byte >= self.cur_node.data.len() { - if let Some(ref n) = self.cur_node.next { - self.cur_byte = 0; - self.cur_node = n; - } else { - return None; - } - } - - let byte = self.abs_byte; - let result = self.read_char(); - - return Some((result, byte)); - } -} - -impl<'a> Chars<'a> { - fn new<'b>(first_node: &'b StringNode) -> Chars<'b> { - Chars { - cur_node: first_node, - cur_byte: 0, - abs_byte: 0, - } - } - - fn read_char(&mut self) -> char { - let first_byte = self.read_byte(); - let width = unicode::str::utf8_char_width(first_byte); - if width == 1 { - return first_byte as char - } - if width == 0 { - panic!("non-utf8 char in StringBuffer"); - } - let mut buf = [first_byte, 0, 0, 0]; - { - let mut start = 1; - while start < width { - buf[start] = self.read_byte(); - start += 1; - } - } - match ::std::str::from_utf8(&buf[..width]).ok() { - Some(s) => s.char_at(0), - None => panic!("bad chars in StringBuffer") - } - } - - fn read_byte(&mut self) -> u8 { - let result = self.cur_node.data.as_bytes()[self.cur_byte]; - self.cur_byte += 1; - self.abs_byte += 1; - result - } -} - - -#[cfg(test)] -mod test { - use super::*; - // Bug #23157 - use super::{StringNode, INIT_CAPACITY}; - - #[test] - fn test_new() { - let s = StringBuffer::new(); - assert!(s.len == 0); - assert!(s.to_string() == ""); - assert!(count_nodes(&s) == 1); - assert!(first_capacity(&s) == INIT_CAPACITY); - - let s = StringBuffer::with_capacity(64); - assert!(s.len == 0); - assert!(s.to_string() == ""); - assert!(count_nodes(&s) == 1); - assert!(first_capacity(&s) == 64); - } - - #[test] - fn test_from_str() { - let s: StringBuffer = "Hello".parse().unwrap(); - assert!(s.len == 5); - assert!(s.to_string() == "Hello"); - assert!(count_nodes(&s) == 1); - assert!(first_capacity(&s) == INIT_CAPACITY); - - let expected = "Hello"; - for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) { - assert!(c == cc); - assert!(i == b); - } - } - - #[test] - fn test_push_str() { - let mut s: StringBuffer = "Hello".parse().unwrap(); - assert!(first_capacity(&s) == INIT_CAPACITY); - - s.push_str(" world!"); - assert!(s.to_string() == "Hello world!"); - assert!(s.len == 12); - s.push_str(" foo"); - assert!(s.to_string() == "Hello world! foo"); - assert!(s.len == 16); - - assert!(count_nodes(&s) == 1); - - let expected = "Hello world! foo"; - for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) { - assert!(c == cc); - assert!(i == b); - } - } - - // push_str requiring multiple nodes - #[test] - fn test_push_str_multi() { - let mut s: StringBuffer = StringBuffer::with_capacity(2); - assert!(first_capacity(&s) == 2); - - s.push_str("Hello"); - assert!(s.to_string() == "Hello"); - assert!(s.len == 5); - assert!(count_nodes(&s) == 2); - s.push_str(" world!"); - assert!(s.to_string() == "Hello world!"); - assert!(s.len == 12); - assert!(count_nodes(&s) == 2); - - let expected = "Hello world!"; - for ((i, (c, b)), cc) in s.chars().enumerate().zip(expected.chars()) { - assert!(c == cc); - assert!(i == b); - } - } - - // TODO test unicode - - // Helper methods. - fn count_nodes(s: &StringBuffer) -> usize { - count_nodes_from(&s.first) - } - fn count_nodes_from(s: &StringNode) -> usize { - match s.next { - Some(ref n) => 1 + count_nodes_from(n), - None => 1, - } - } - fn first_capacity(s: &StringBuffer) -> usize { - s.first.data.capacity() - } -} -- cgit 1.4.1-3-g733a5 From 0a67babb954d10f03cec65bf2fbf4e058ee898be Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 14 Apr 2015 21:52:12 +1200 Subject: Work across multiple files --- src/changes.rs | 42 +++++++++++++++++++++- src/mod.rs | 109 +++++++++++++++++++++++++++++++-------------------------- 2 files changed, 101 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 752ae942f1f..068b6b7736c 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -15,7 +15,7 @@ use strings::string_buffer::StringBuffer; use std::collections::HashMap; -use syntax::codemap::{CodeMap, Span}; +use syntax::codemap::{CodeMap, Span,BytePos}; use std::fmt; // This is basically a wrapper around a bunch of Ropes which makes it convenient @@ -23,6 +23,7 @@ use std::fmt; pub struct ChangeSet<'a> { file_map: HashMap, codemap: &'a CodeMap, + file_spans: Vec<(u32, u32)>, } impl<'a> ChangeSet<'a> { @@ -31,6 +32,7 @@ impl<'a> ChangeSet<'a> { let mut result = ChangeSet { file_map: HashMap::new(), codemap: codemap, + file_spans: Vec::with_capacity(codemap.files.borrow().len()), }; for f in codemap.files.borrow().iter() { @@ -39,11 +41,49 @@ impl<'a> ChangeSet<'a> { // power of two. TODO check that or do it here. result.file_map.insert(f.name.clone(), StringBuffer::with_capacity(f.src.as_ref().unwrap().len())); + + result.file_spans.push((f.start_pos.0, f.end_pos.0)); } + result.file_spans.sort(); + result } + pub fn filespans_for_span(&self, start: BytePos, end: BytePos) -> Vec<(u32, u32)> { + assert!(start.0 <= end.0); + + if self.file_spans.len() == 0 { + return Vec::new(); + } + + let mut idx = match self.file_spans.binary_search(&(start.0, ::std::u32::MAX)) { + Ok(i) => i, + Err(0) => 0, + Err(i) => i - 1, + }; + + let mut result = Vec::new(); + let mut start = start.0; + loop { + let cur_file = &self.file_spans[idx]; + idx += 1; + + if idx >= self.file_spans.len() || start >= end.0 { + if start < end.0 { + result.push((start, end.0)); + } + return result; + } + + let end = ::std::cmp::min(cur_file.1 - 1, end.0); + if start < end { + result.push((start, end)); + } + start = self.file_spans[idx].0; + } + } + pub fn push_str(&mut self, file_name: &str, text: &str) { let buf = self.file_map.get_mut(&*file_name).unwrap(); buf.push_str(text) diff --git a/src/mod.rs b/src/mod.rs index a124eb9e2b4..65951638c1c 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -22,8 +22,8 @@ // TODO priorities // Fix fns and methods properly - need visibility in visit // Writing output -// Working on multiple files, inclding empty ones // Smoke testing till we can use it +// end of multi-line string has wspace #[macro_use] extern crate log; @@ -123,10 +123,9 @@ struct FmtVisitor<'a> { impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_expr(&mut self, ex: &'v ast::Expr) { - // TODO uncomment - // debug!("visit_expr: {:?} {:?}", - // self.codemap.lookup_char_pos(ex.span.lo), - // self.codemap.lookup_char_pos(ex.span.hi)); + debug!("visit_expr: {:?} {:?}", + self.codemap.lookup_char_pos(ex.span.lo), + self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset); @@ -135,10 +134,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_block(&mut self, b: &'v ast::Block) { - // TODO uncomment - // debug!("visit_block: {:?} {:?}", - // self.codemap.lookup_char_pos(b.span.lo), - // self.codemap.lookup_char_pos(b.span.hi)); + debug!("visit_block: {:?} {:?}", + self.codemap.lookup_char_pos(b.span.lo), + self.codemap.lookup_char_pos(b.span.hi)); self.format_missing(b.span.lo); self.changes.push_str_span(b.span, "{"); @@ -241,6 +239,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_mac(&mut self, mac: &'v ast::Mac) { visit::walk_mac(self, mac) } + + fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) { + // Only visit inline mods here. + if self.codemap.lookup_char_pos(s.lo).file.name != + self.codemap.lookup_char_pos(m.inner.lo).file.name { + return; + } + visit::walk_mod(self, m); + } } fn make_indent(width: usize) -> String { @@ -413,63 +420,67 @@ impl<'a> FmtVisitor<'a> { process_last_snippet: F) { let start = self.last_pos; - // TODO uncomment - // debug!("format_missing_inner: {:?} to {:?}", - // self.codemap.lookup_char_pos(start), - // self.codemap.lookup_char_pos(end)); - - // TODO(#11) gets tricky if we're missing more than one file - // assert!(self.codemap.lookup_char_pos(start).file.name == self.codemap.lookup_char_pos(end).file.name, - // "not implemented: unformated span across files: {} and {}", - // self.codemap.lookup_char_pos(start).file.name, - // self.codemap.lookup_char_pos(end).file.name); - // assert!(start <= end, - // "Request to format inverted span: {:?} to {:?}", - // self.codemap.lookup_char_pos(start), - // self.codemap.lookup_char_pos(end)); + debug!("format_missing_inner: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end)); if start == end { return; } - self.last_pos = end; - let span = codemap::mk_sp(start, end); - let snippet = self.snippet(span); - - // Trim whitespace from the right hand side of each line. - // Annoyingly, the library functions for splitting by lines etc. are not - // quite right, so we must do it ourselves. - let mut line_start = 0; - let mut last_wspace = None; - for (i, c) in snippet.char_indices() { - if c == '\n' { - if let Some(lw) = last_wspace { - self.changes.push_str_span(span, &snippet[line_start..lw]); - self.changes.push_str_span(span, "\n"); - } else { - self.changes.push_str_span(span, &snippet[line_start..i+1]); - } + assert!(start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end)); - line_start = i + 1; - last_wspace = None; - } else { - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(i); + + self.last_pos = end; + let spans = self.changes.filespans_for_span(start, end); + for (i, &(start, end)) in spans.iter().enumerate() { + let span = codemap::mk_sp(BytePos(start), BytePos(end)); + let snippet = self.snippet(span); + + // Trim whitespace from the right hand side of each line. + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let mut line_start = 0; + let mut last_wspace = None; + for (i, c) in snippet.char_indices() { + if c == '\n' { + if let Some(lw) = last_wspace { + self.changes.push_str_span(span, &snippet[line_start..lw]); + self.changes.push_str_span(span, "\n"); + } else { + self.changes.push_str_span(span, &snippet[line_start..i+1]); } - } else { + + line_start = i + 1; last_wspace = None; + } else { + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(i); + } + } else { + last_wspace = None; + } } } + if i == spans.len() - 1 { + process_last_snippet(self, &snippet[line_start..], span, &snippet); + } else { + self.changes.push_str_span(span, &snippet[line_start..]); + } } - process_last_snippet(self, &snippet[line_start..], span, &snippet); } fn snippet(&self, span: Span) -> String { match self.codemap.span_to_snippet(span) { Ok(s) => s, Err(_) => { - println!("Couldn't make snippet for span {:?}", span); + println!("Couldn't make snippet for span {:?}->{:?}", + self.codemap.lookup_char_pos(span.lo), + self.codemap.lookup_char_pos(span.hi)); "".to_string() } } -- cgit 1.4.1-3-g733a5 From 6dbb3ef2f18c82ee767add5e78e15cf49940dd7e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 09:38:16 +1200 Subject: Function visibility --- src/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 65951638c1c..32dbd321e9b 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -20,7 +20,7 @@ // TODO for lint violations of names, emit a refactor script // TODO priorities -// Fix fns and methods properly - need visibility in visit +// Fix fns and methods properly // Writing output // Smoke testing till we can use it // end of multi-line string has wspace @@ -168,14 +168,13 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { - // TODO need to get the visibility from somewhere self.format_missing(s.lo); self.last_pos = s.lo; // TODO need to check against expected indent let indent = self.codemap.lookup_char_pos(s.lo).col.0; match fk { - visit::FkItemFn(ident, ref generics, ref unsafety, ref abi) => { + visit::FkItemFn(ident, ref generics, ref unsafety, ref abi, vis) => { let new_fn = self.rewrite_fn(indent, ident, fd, @@ -183,10 +182,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { generics, unsafety, abi, - ast::Visibility::Inherited); + vis); self.changes.push_str_span(s, &new_fn); } - visit::FkMethod(ident, ref sig) => { + visit::FkMethod(ident, ref sig, vis) => { let new_fn = self.rewrite_fn(indent, ident, fd, @@ -194,7 +193,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &sig.generics, &sig.unsafety, &sig.abi, - ast::Visibility::Inherited); + vis.unwrap_or(ast::Visibility::Inherited)); self.changes.push_str_span(s, &new_fn); } visit::FkFnBlock(..) => {} @@ -721,6 +720,7 @@ impl<'a> FmtVisitor<'a> { // TODO dead spans let mut arg_strs: Vec<_> = args.iter().map(|a| (self.rewrite_fn_input(a), String::new())).collect(); // Account for sugary self. + // TODO busted with by value self if let Some(explicit_self) = explicit_self { match explicit_self.node { ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { -- cgit 1.4.1-3-g733a5 From 5ff6a45022e69a8ddd2205d8d63b86d17ac62c0d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 09:54:04 +1200 Subject: By value self in functions --- src/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 32dbd321e9b..8e652c19718 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -720,7 +720,6 @@ impl<'a> FmtVisitor<'a> { // TODO dead spans let mut arg_strs: Vec<_> = args.iter().map(|a| (self.rewrite_fn_input(a), String::new())).collect(); // Account for sugary self. - // TODO busted with by value self if let Some(explicit_self) = explicit_self { match explicit_self.node { ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { @@ -732,10 +731,13 @@ impl<'a> FmtVisitor<'a> { &ast::Mutability::MutMutable => "mut ".to_string(), &ast::Mutability::MutImmutable => String::new(), }; - arg_strs[0].0 = format!("&{}{}self", lt_str, mut_str) + arg_strs[0].0 = format!("&{}{}self", lt_str, mut_str); } ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { - arg_strs[0].0 = format!("self: {}", pprust::ty_to_string(ty)) + arg_strs[0].0 = format!("self: {}", pprust::ty_to_string(ty)); + } + ast::ExplicitSelf_::SelfValue(_) => { + arg_strs[0].0 = "self".to_string(); } _ => {} } -- cgit 1.4.1-3-g733a5 From eccf43536be15e6c57bd2d00d82bdbaca5406ae2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 12:02:30 +1200 Subject: Some configuration options for function layout --- src/mod.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 8e652c19718..a7c3b1c4fb8 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -21,9 +21,11 @@ // TODO priorities // Fix fns and methods properly +// dead spans +// // Writing output // Smoke testing till we can use it -// end of multi-line string has wspace +// end of multi-line string has wspace #[macro_use] extern crate log; @@ -57,6 +59,26 @@ const LEEWAY: usize = 5; const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; const TAB_SPACES: usize = 4; +const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; +const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum BraceStyle { + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +// How to indent a function's return type. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum ReturnIndent { + // Aligned with the arguments + WithArgs, + // Aligned with the where clause + WithWhereClause, +} // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { @@ -162,6 +184,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = b.span.hi; } + // Note that this only gets called for function defintions. Required methods + // on traits do not get handled here. fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, @@ -199,10 +223,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { visit::FkFnBlock(..) => {} } - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. - self.changes.push_str_span(s, "\n"); - self.changes.push_str_span(s, &make_indent(self.block_indent)); self.last_pos = b.span.lo; self.visit_block(b) } @@ -614,6 +634,13 @@ impl<'a> FmtVisitor<'a> { // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. + let where_clause = &generics.where_clause; + let newline_brace = match FN_BRACE_STYLE { + BraceStyle::AlwaysNextLine => true, + BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, + _ => false, + }; + let mut result = String::with_capacity(1024); // Vis unsafety abi. if vis == ast::Visibility::Public { @@ -637,7 +664,6 @@ impl<'a> FmtVisitor<'a> { // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; let tys: &[_] = &generics.ty_params; - let where_clause = &generics.where_clause; if lifetimes.len() + tys.len() > 0 { let budget = MAX_WIDTH - indent - result.len() - 2; // TODO might need to insert a newline if the generics are really long @@ -673,7 +699,10 @@ impl<'a> FmtVisitor<'a> { // Try keeping everything on the same line if !result.contains("\n") { // 3 = `() `, space is before ret_string - let used_space = indent + result.len() + 3 + ret_str.len(); + let mut used_space = indent + result.len() + 3 + ret_str.len(); + if newline_brace { + used_space += 2; + } let one_line_budget = if used_space > MAX_WIDTH { 0 } else { @@ -771,7 +800,14 @@ impl<'a> FmtVisitor<'a> { // over the max width, then put the return type on a new line. if result.contains("\n") || result.len() + indent + ret_str.len() > MAX_WIDTH { - let indent = indent + 4; + let indent = match FN_RETURN_INDENT { + ReturnIndent::WithWhereClause => indent + 4, + // TODO we might want to check that using the arg indent doesn't + // blow our budget, and if it does, then fallback to the where + // clause indent. + ReturnIndent::WithArgs => arg_indent, + }; + result.push('\n'); result.push_str(&make_indent(indent)); } else { @@ -780,6 +816,16 @@ impl<'a> FmtVisitor<'a> { result.push_str(&ret_str); } + // Prepare for the function body by possibly adding a newline and indent. + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + if newline_brace { + result.push('\n'); + result.push_str(&make_indent(self.block_indent)); + } else { + result.push(' '); + } + result } -- cgit 1.4.1-3-g733a5 From 986de65b979bde3968c9c438c4cc9c1f98ba9e2a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 16:28:10 +1200 Subject: Write output to files --- src/changes.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++------ src/mod.rs | 17 +++++++++++++++-- 2 files changed, 64 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 068b6b7736c..dd8f220eb27 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -17,6 +17,9 @@ use strings::string_buffer::StringBuffer; use std::collections::HashMap; use syntax::codemap::{CodeMap, Span,BytePos}; use std::fmt; +use std::fs::File; +use std::io::Write; +use WriteMode; // This is basically a wrapper around a bunch of Ropes which makes it convenient // to work with libsyntax. It is badly named. @@ -84,8 +87,8 @@ impl<'a> ChangeSet<'a> { } } - pub fn push_str(&mut self, file_name: &str, text: &str) { - let buf = self.file_map.get_mut(&*file_name).unwrap(); + pub fn push_str(&mut self, filename: &str, text: &str) { + let buf = self.file_map.get_mut(&*filename).unwrap(); buf.push_str(text) } @@ -94,13 +97,13 @@ impl<'a> ChangeSet<'a> { self.push_str(&file_name, text) } - pub fn cur_offset(&mut self, file_name: &str) -> usize { - self.file_map[&*file_name].cur_offset() + pub fn cur_offset(&mut self, filename: &str) -> usize { + self.file_map[&*filename].cur_offset() } pub fn cur_offset_span(&mut self, span: Span) -> usize { - let file_name = self.codemap.span_to_filename(span); - self.cur_offset(&file_name) + let filename = self.codemap.span_to_filename(span); + self.cur_offset(&filename) } // Return an iterator over the entire changed text. @@ -112,6 +115,46 @@ impl<'a> ChangeSet<'a> { } } + pub fn write_all_files(&self, mode: WriteMode) -> Result<(), ::std::io::Error> { + for filename in self.file_map.keys() { + try!(self.write_file(filename, mode)); + } + + Ok(()) + } + + pub fn write_file(&self, filename: &str, mode: WriteMode) -> Result<(), ::std::io::Error> { + let text = &self.file_map[filename]; + + match mode { + WriteMode::Overwrite => { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.to_string() + ".tmp"; + let bk_name = filename.to_string() + ".bk"; + { + // Write text to temp file + let mut tmp_file = try!(File::create(&tmp_name)); + try!(write!(tmp_file, "{}", text)); + } + + try!(::std::fs::rename(filename, bk_name)); + try!(::std::fs::rename(tmp_name, filename)); + } + WriteMode::NewFile(extn) => { + let filename = filename.to_string() + "." + extn; + let mut file = try!(File::create(&filename)); + try!(write!(file, "{}", text)); + } + _ => { + println!("{}:\n", filename); + println!("{}", text); + } + } + + Ok(()) + } } // Iterates over each file in the ChangSet. Yields the filename and the changed diff --git a/src/mod.rs b/src/mod.rs index a7c3b1c4fb8..f8263e6b0ae 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -23,9 +23,9 @@ // Fix fns and methods properly // dead spans // -// Writing output // Smoke testing till we can use it // end of multi-line string has wspace +// no newline at the end of doc.rs #[macro_use] extern crate log; @@ -62,6 +62,15 @@ const TAB_SPACES: usize = 4; const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum WriteMode { + Overwrite, + // str is the extension of the new file + NewFile(&'static str), + // Write the output to stdout. + Display, +} + #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum BraceStyle { AlwaysNextLine, @@ -1062,8 +1071,12 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { let mut changes = fmt_ast(krate, codemap); fmt_lines(&mut changes); - println!("{}", changes); // FIXME(#5) Should be user specified whether to show or replace. + let result = changes.write_all_files(WriteMode::Display); + + if let Err(msg) = result { + println!("Error writing files: {}", msg); + } }; control -- cgit 1.4.1-3-g733a5 From defcceb8796ea98d429297e2cf8c414064aa0234 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 16:47:15 +1200 Subject: Pull out some functionality into separate files --- src/functions.rs | 234 ++++++++++++++++++++++++++++ src/lists.rs | 136 +++++++++++++++++ src/missed_spans.rs | 95 ++++++++++++ src/mod.rs | 428 +--------------------------------------------------- 4 files changed, 471 insertions(+), 422 deletions(-) create mode 100644 src/functions.rs create mode 100644 src/lists.rs create mode 100644 src/missed_spans.rs (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs new file mode 100644 index 00000000000..f1a9c395470 --- /dev/null +++ b/src/functions.rs @@ -0,0 +1,234 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use {FmtVisitor, ReturnIndent, make_indent, MAX_WIDTH, BraceStyle, + IDEAL_WIDTH, LEEWAY, FN_BRACE_STYLE, FN_RETURN_INDENT}; +use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use syntax::{ast, abi}; +use syntax::print::pprust; +use syntax::parse::token; + +impl<'a> FmtVisitor<'a> { + pub fn rewrite_fn(&mut self, + indent: usize, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: &ast::Unsafety, + abi: &abi::Abi, + vis: ast::Visibility) + -> String + { + // FIXME we'll lose any comments in between parts of the function decl, but anyone + // who comments there probably deserves what they get. + + let where_clause = &generics.where_clause; + let newline_brace = match FN_BRACE_STYLE { + BraceStyle::AlwaysNextLine => true, + BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, + _ => false, + }; + + let mut result = String::with_capacity(1024); + // Vis unsafety abi. + if vis == ast::Visibility::Public { + result.push_str("pub "); + } + if let &ast::Unsafety::Unsafe = unsafety { + result.push_str("unsafe "); + } + if *abi != abi::Rust { + result.push_str("extern "); + result.push_str(&abi.to_string()); + result.push(' '); + } + + // fn foo + result.push_str("fn "); + result.push_str(&token::get_ident(ident)); + + // Generics. + // FIXME convert bounds to where clauses where they get too big or if + // there is a where clause at all. + let lifetimes: &[_] = &generics.lifetimes; + let tys: &[_] = &generics.ty_params; + if lifetimes.len() + tys.len() > 0 { + let budget = MAX_WIDTH - indent - result.len() - 2; + // TODO might need to insert a newline if the generics are really long + result.push('<'); + + let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); + let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); + let generics_strs: Vec<_> = lt_strs.chain(ty_strs).map(|s| (s, String::new())).collect(); + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + result.len() + 1, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&generics_strs, &fmt)); + + result.push('>'); + } + + let ret_str = match fd.output { + ast::FunctionRetTy::DefaultReturn(_) => String::new(), + ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), + ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), + }; + + // Args. + let args = &fd.inputs; + + let mut budgets = None; + + // Try keeping everything on the same line + if !result.contains("\n") { + // 3 = `() `, space is before ret_string + let mut used_space = indent + result.len() + 3 + ret_str.len(); + if newline_brace { + used_space += 2; + } + let one_line_budget = if used_space > MAX_WIDTH { + 0 + } else { + MAX_WIDTH - used_space + }; + + let used_space = indent + result.len() + 2; + let max_space = IDEAL_WIDTH + LEEWAY; + if used_space < max_space { + budgets = Some((one_line_budget, + // 2 = `()` + max_space - used_space, + indent + result.len() + 1)); + } + } + + // Didn't work. we must force vertical layout and put args on a newline. + if let None = budgets { + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + // 6 = new indent + `()` + let used_space = indent + 6; + let max_space = IDEAL_WIDTH + LEEWAY; + if used_space > max_space { + // Whoops! bankrupt. + // TODO take evasive action, perhaps kill the indent or something. + } else { + // 5 = new indent + `(` + budgets = Some((0, max_space - used_space, indent + 5)); + } + } + + let (one_line_budget, multi_line_budget, arg_indent) = budgets.unwrap(); + result.push('('); + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: arg_indent, + h_width: one_line_budget, + v_width: multi_line_budget, + }; + // TODO dead spans + let mut arg_strs: Vec<_> = args.iter().map(|a| (self.rewrite_fn_input(a), String::new())).collect(); + // Account for sugary self. + if let Some(explicit_self) = explicit_self { + match explicit_self.node { + ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { + let lt_str = match lt { + &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), + &None => String::new(), + }; + let mut_str = match m { + &ast::Mutability::MutMutable => "mut ".to_string(), + &ast::Mutability::MutImmutable => String::new(), + }; + arg_strs[0].0 = format!("&{}{}self", lt_str, mut_str); + } + ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { + arg_strs[0].0 = format!("self: {}", pprust::ty_to_string(ty)); + } + ast::ExplicitSelf_::SelfValue(_) => { + arg_strs[0].0 = "self".to_string(); + } + _ => {} + } + } + result.push_str(&write_list(&arg_strs, &fmt)); + + result.push(')'); + + // Where clause. + if where_clause.predicates.len() > 0 { + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + result.push_str("where "); + + let budget = IDEAL_WIDTH + LEEWAY - indent - 10; + let fmt = ListFormatting { + tactic: ListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Always, + indent: indent + 10, + h_width: budget, + v_width: budget, + }; + let where_strs: Vec<_> = where_clause.predicates.iter().map(|p| (self.rewrite_pred(p), String::new())).collect(); + result.push_str(&write_list(&where_strs, &fmt)); + } + + // Return type. + if ret_str.len() > 0 { + // If we've already gone multi-line, or the return type would push + // over the max width, then put the return type on a new line. + if result.contains("\n") || + result.len() + indent + ret_str.len() > MAX_WIDTH { + let indent = match FN_RETURN_INDENT { + ReturnIndent::WithWhereClause => indent + 4, + // TODO we might want to check that using the arg indent doesn't + // blow our budget, and if it does, then fallback to the where + // clause indent. + ReturnIndent::WithArgs => arg_indent, + }; + + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + result.push_str(&ret_str); + } + + // Prepare for the function body by possibly adding a newline and indent. + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + if newline_brace { + result.push('\n'); + result.push_str(&make_indent(self.block_indent)); + } else { + result.push(' '); + } + + result + } + + // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly + fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { + format!("{}: {}", + pprust::pat_to_string(&arg.pat), + pprust::ty_to_string(&arg.ty)) + } +} diff --git a/src/lists.rs b/src/lists.rs new file mode 100644 index 00000000000..5800f76b95a --- /dev/null +++ b/src/lists.rs @@ -0,0 +1,136 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use make_indent; + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum ListTactic { + // One item per row. + Vertical, + // All items on one row. + Horizontal, + // Try Horizontal layout, if that fails then vertical + HorizontalVertical, + // Pack as many items as possible per row over (possibly) many rows. + Mixed, +} + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorTactic { + Always, + Never, + Vertical, +} + +pub struct ListFormatting<'a> { + pub tactic: ListTactic, + pub separator: &'a str, + pub trailing_separator: SeparatorTactic, + pub indent: usize, + // Available width if we layout horizontally. + pub h_width: usize, + // Available width if we layout vertically + pub v_width: usize, +} + +// Format a list of strings into a string. +pub fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b>) -> String { + if items.len() == 0 { + return String::new(); + } + + let mut tactic = formatting.tactic; + + let h_width = formatting.h_width; + let v_width = formatting.v_width; + let sep_len = formatting.separator.len(); + + // Conservatively overestimates because of the changing separator tactic. + let sep_count = if formatting.trailing_separator != SeparatorTactic::Never { + items.len() + } else { + items.len() - 1 + }; + + // TODO count dead space too. + let total_width = items.iter().map(|&(ref s, _)| s.len()).fold(0, |a, l| a + l); + + // Check if we need to fallback from horizontal listing, if possible. + if tactic == ListTactic::HorizontalVertical { + if (total_width + (sep_len + 1) * sep_count) > h_width { + tactic = ListTactic::Vertical; + } else { + tactic = ListTactic::Horizontal; + } + } + + // Now that we know how we will layout, we can decide for sure if there + // will be a trailing separator. + let trailing_separator = match formatting.trailing_separator { + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => tactic == ListTactic::Vertical, + SeparatorTactic::Never => false, + }; + + // Create a buffer for the result. + // TODO could use a StringBuffer or rope for this + let alloc_width = if tactic == ListTactic::Horizontal { + total_width + (sep_len + 1) * sep_count + } else { + total_width + items.len() * (formatting.indent + 1) + }; + let mut result = String::with_capacity(alloc_width); + + let mut line_len = 0; + let indent_str = &make_indent(formatting.indent); + for (i, &(ref item, _)) in items.iter().enumerate() { + let first = i == 0; + let separate = i != items.len() - 1 || trailing_separator; + + match tactic { + ListTactic::Horizontal if !first => { + result.push(' '); + } + ListTactic::Vertical if !first => { + result.push('\n'); + result.push_str(indent_str); + } + ListTactic::Mixed => { + let mut item_width = item.len(); + if separate { + item_width += sep_len; + } + + if line_len > 0 && line_len + item_width > v_width { + result.push('\n'); + result.push_str(indent_str); + line_len = 0; + } + + if line_len > 0 { + result.push(' '); + line_len += 1; + } + + line_len += item_width; + } + _ => {} + } + + result.push_str(item); + + if separate { + result.push_str(formatting.separator); + } + // TODO dead spans + } + + result +} diff --git a/src/missed_spans.rs b/src/missed_spans.rs new file mode 100644 index 00000000000..bea83a4f90f --- /dev/null +++ b/src/missed_spans.rs @@ -0,0 +1,95 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use {FmtVisitor, make_indent}; +use syntax::codemap::{self, Span, BytePos}; + +impl<'a> FmtVisitor<'a> { + // TODO these format_missing methods are ugly. Refactor and add unit tests + // for the central whitespace stripping loop. + pub fn format_missing(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, span, _| { + this.changes.push_str_span(span, last_snippet) + }) + } + + pub fn format_missing_with_indent(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, span, snippet| { + if last_snippet == snippet { + // No new lines + this.changes.push_str_span(span, last_snippet); + this.changes.push_str_span(span, "\n"); + } else { + this.changes.push_str_span(span, last_snippet.trim_right()); + } + let indent = make_indent(this.block_indent); + this.changes.push_str_span(span, &indent); + }) + } + + fn format_missing_inner(&mut self, + end: BytePos, + process_last_snippet: F) + { + let start = self.last_pos; + debug!("format_missing_inner: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end)); + + if start == end { + return; + } + + assert!(start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end)); + + + self.last_pos = end; + let spans = self.changes.filespans_for_span(start, end); + for (i, &(start, end)) in spans.iter().enumerate() { + let span = codemap::mk_sp(BytePos(start), BytePos(end)); + let snippet = self.snippet(span); + + // Trim whitespace from the right hand side of each line. + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let mut line_start = 0; + let mut last_wspace = None; + for (i, c) in snippet.char_indices() { + if c == '\n' { + if let Some(lw) = last_wspace { + self.changes.push_str_span(span, &snippet[line_start..lw]); + self.changes.push_str_span(span, "\n"); + } else { + self.changes.push_str_span(span, &snippet[line_start..i+1]); + } + + line_start = i + 1; + last_wspace = None; + } else { + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(i); + } + } else { + last_wspace = None; + } + } + } + if i == spans.len() - 1 { + process_last_snippet(self, &snippet[line_start..], span, &snippet); + } else { + self.changes.push_str_span(span, &snippet[line_start..]); + } + } + } +} diff --git a/src/mod.rs b/src/mod.rs index f8263e6b0ae..750b3159a93 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -41,8 +41,8 @@ use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; -use syntax::{ast, ptr, abi}; -use syntax::codemap::{self, CodeMap, Span, Pos, BytePos}; +use syntax::{ast, ptr}; +use syntax::codemap::{CodeMap, Span, Pos, BytePos}; use syntax::diagnostics; use syntax::parse::token; use syntax::print::pprust; @@ -51,8 +51,12 @@ use syntax::visit; use std::path::PathBuf; use changes::ChangeSet; +use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; mod changes; +mod functions; +mod missed_spans; +mod lists; const IDEAL_WIDTH: usize = 80; const LEEWAY: usize = 5; @@ -286,130 +290,6 @@ fn make_indent(width: usize) -> String { indent } -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -enum ListTactic { - // One item per row. - Vertical, - // All items on one row. - Horizontal, - // Try Horizontal layout, if that fails then vertical - HorizontalVertical, - // Pack as many items as possible per row over (possibly) many rows. - Mixed, -} - -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -enum SeparatorTactic { - Always, - Never, - Vertical, -} - -struct ListFormatting<'a> { - tactic: ListTactic, - separator: &'a str, - trailing_separator: SeparatorTactic, - indent: usize, - // Available width if we layout horizontally. - h_width: usize, - // Available width if we layout vertically - v_width: usize, -} - -// Format a list of strings into a string. -fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b>) -> String { - if items.len() == 0 { - return String::new(); - } - - let mut tactic = formatting.tactic; - - let h_width = formatting.h_width; - let v_width = formatting.v_width; - let sep_len = formatting.separator.len(); - - // Conservatively overestimates because of the changing separator tactic. - let sep_count = if formatting.trailing_separator != SeparatorTactic::Never { - items.len() - } else { - items.len() - 1 - }; - - // TODO count dead space too. - let total_width = items.iter().map(|&(ref s, _)| s.len()).fold(0, |a, l| a + l); - - // Check if we need to fallback from horizontal listing, if possible. - if tactic == ListTactic::HorizontalVertical { - if (total_width + (sep_len + 1) * sep_count) > h_width { - tactic = ListTactic::Vertical; - } else { - tactic = ListTactic::Horizontal; - } - } - - // Now that we know how we will layout, we can decide for sure if there - // will be a trailing separator. - let trailing_separator = match formatting.trailing_separator { - SeparatorTactic::Always => true, - SeparatorTactic::Vertical => tactic == ListTactic::Vertical, - SeparatorTactic::Never => false, - }; - - // Create a buffer for the result. - // TODO could use a StringBuffer or rope for this - let alloc_width = if tactic == ListTactic::Horizontal { - total_width + (sep_len + 1) * sep_count - } else { - total_width + items.len() * (formatting.indent + 1) - }; - let mut result = String::with_capacity(alloc_width); - - let mut line_len = 0; - let indent_str = &make_indent(formatting.indent); - for (i, &(ref item, _)) in items.iter().enumerate() { - let first = i == 0; - let separate = i != items.len() - 1 || trailing_separator; - - match tactic { - ListTactic::Horizontal if !first => { - result.push(' '); - } - ListTactic::Vertical if !first => { - result.push('\n'); - result.push_str(indent_str); - } - ListTactic::Mixed => { - let mut item_width = item.len(); - if separate { - item_width += sep_len; - } - - if line_len > 0 && line_len + item_width > v_width { - result.push('\n'); - result.push_str(indent_str); - line_len = 0; - } - - if line_len > 0 { - result.push(' '); - line_len += 1; - } - - line_len += item_width; - } - _ => {} - } - - result.push_str(item); - - if separate { - result.push_str(formatting.separator); - } - // TODO dead spans - } - - result -} impl<'a> FmtVisitor<'a> { fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { @@ -421,87 +301,6 @@ impl<'a> FmtVisitor<'a> { } } - // TODO these format_missing methods are ugly. Refactor and add unit tests - // for the central whitespace stripping loop. - fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, span, _| { - this.changes.push_str_span(span, last_snippet) - }) - } - - fn format_missing_with_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, span, snippet| { - if last_snippet == snippet { - // No new lines - this.changes.push_str_span(span, last_snippet); - this.changes.push_str_span(span, "\n"); - } else { - this.changes.push_str_span(span, last_snippet.trim_right()); - } - let indent = make_indent(this.block_indent); - this.changes.push_str_span(span, &indent); - }) - } - - fn format_missing_inner(&mut self, - end: BytePos, - process_last_snippet: F) - { - let start = self.last_pos; - debug!("format_missing_inner: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end)); - - if start == end { - return; - } - - assert!(start < end, - "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end)); - - - self.last_pos = end; - let spans = self.changes.filespans_for_span(start, end); - for (i, &(start, end)) in spans.iter().enumerate() { - let span = codemap::mk_sp(BytePos(start), BytePos(end)); - let snippet = self.snippet(span); - - // Trim whitespace from the right hand side of each line. - // Annoyingly, the library functions for splitting by lines etc. are not - // quite right, so we must do it ourselves. - let mut line_start = 0; - let mut last_wspace = None; - for (i, c) in snippet.char_indices() { - if c == '\n' { - if let Some(lw) = last_wspace { - self.changes.push_str_span(span, &snippet[line_start..lw]); - self.changes.push_str_span(span, "\n"); - } else { - self.changes.push_str_span(span, &snippet[line_start..i+1]); - } - - line_start = i + 1; - last_wspace = None; - } else { - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(i); - } - } else { - last_wspace = None; - } - } - } - if i == spans.len() - 1 { - process_last_snippet(self, &snippet[line_start..], span, &snippet); - } else { - self.changes.push_str_span(span, &snippet[line_start..]); - } - } - } - fn snippet(&self, span: Span) -> String { match self.codemap.span_to_snippet(span) { Ok(s) => s, @@ -629,221 +428,6 @@ impl<'a> FmtVisitor<'a> { format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) } - fn rewrite_fn(&mut self, - indent: usize, - ident: ast::Ident, - fd: &ast::FnDecl, - explicit_self: Option<&ast::ExplicitSelf>, - generics: &ast::Generics, - unsafety: &ast::Unsafety, - abi: &abi::Abi, - vis: ast::Visibility) - -> String - { - // FIXME we'll lose any comments in between parts of the function decl, but anyone - // who comments there probably deserves what they get. - - let where_clause = &generics.where_clause; - let newline_brace = match FN_BRACE_STYLE { - BraceStyle::AlwaysNextLine => true, - BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, - _ => false, - }; - - let mut result = String::with_capacity(1024); - // Vis unsafety abi. - if vis == ast::Visibility::Public { - result.push_str("pub "); - } - if let &ast::Unsafety::Unsafe = unsafety { - result.push_str("unsafe "); - } - if *abi != abi::Rust { - result.push_str("extern "); - result.push_str(&abi.to_string()); - result.push(' '); - } - - // fn foo - result.push_str("fn "); - result.push_str(&token::get_ident(ident)); - - // Generics. - // FIXME convert bounds to where clauses where they get too big or if - // there is a where clause at all. - let lifetimes: &[_] = &generics.lifetimes; - let tys: &[_] = &generics.ty_params; - if lifetimes.len() + tys.len() > 0 { - let budget = MAX_WIDTH - indent - result.len() - 2; - // TODO might need to insert a newline if the generics are really long - result.push('<'); - - let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); - let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); - let generics_strs: Vec<_> = lt_strs.chain(ty_strs).map(|s| (s, String::new())).collect(); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + result.len() + 1, - h_width: budget, - v_width: budget, - }; - result.push_str(&write_list(&generics_strs, &fmt)); - - result.push('>'); - } - - let ret_str = match fd.output { - ast::FunctionRetTy::DefaultReturn(_) => String::new(), - ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), - ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), - }; - - // Args. - let args = &fd.inputs; - - let mut budgets = None; - - // Try keeping everything on the same line - if !result.contains("\n") { - // 3 = `() `, space is before ret_string - let mut used_space = indent + result.len() + 3 + ret_str.len(); - if newline_brace { - used_space += 2; - } - let one_line_budget = if used_space > MAX_WIDTH { - 0 - } else { - MAX_WIDTH - used_space - }; - - let used_space = indent + result.len() + 2; - let max_space = IDEAL_WIDTH + LEEWAY; - if used_space < max_space { - budgets = Some((one_line_budget, - // 2 = `()` - max_space - used_space, - indent + result.len() + 1)); - } - } - - // Didn't work. we must force vertical layout and put args on a newline. - if let None = budgets { - result.push('\n'); - result.push_str(&make_indent(indent + 4)); - // 6 = new indent + `()` - let used_space = indent + 6; - let max_space = IDEAL_WIDTH + LEEWAY; - if used_space > max_space { - // Whoops! bankrupt. - // TODO take evasive action, perhaps kill the indent or something. - } else { - // 5 = new indent + `(` - budgets = Some((0, max_space - used_space, indent + 5)); - } - } - - let (one_line_budget, multi_line_budget, arg_indent) = budgets.unwrap(); - result.push('('); - - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: arg_indent, - h_width: one_line_budget, - v_width: multi_line_budget, - }; - // TODO dead spans - let mut arg_strs: Vec<_> = args.iter().map(|a| (self.rewrite_fn_input(a), String::new())).collect(); - // Account for sugary self. - if let Some(explicit_self) = explicit_self { - match explicit_self.node { - ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { - let lt_str = match lt { - &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), - &None => String::new(), - }; - let mut_str = match m { - &ast::Mutability::MutMutable => "mut ".to_string(), - &ast::Mutability::MutImmutable => String::new(), - }; - arg_strs[0].0 = format!("&{}{}self", lt_str, mut_str); - } - ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { - arg_strs[0].0 = format!("self: {}", pprust::ty_to_string(ty)); - } - ast::ExplicitSelf_::SelfValue(_) => { - arg_strs[0].0 = "self".to_string(); - } - _ => {} - } - } - result.push_str(&write_list(&arg_strs, &fmt)); - - result.push(')'); - - // Where clause. - if where_clause.predicates.len() > 0 { - result.push('\n'); - result.push_str(&make_indent(indent + 4)); - result.push_str("where "); - - let budget = IDEAL_WIDTH + LEEWAY - indent - 10; - let fmt = ListFormatting { - tactic: ListTactic::Vertical, - separator: ",", - trailing_separator: SeparatorTactic::Always, - indent: indent + 10, - h_width: budget, - v_width: budget, - }; - let where_strs: Vec<_> = where_clause.predicates.iter().map(|p| (self.rewrite_pred(p), String::new())).collect(); - result.push_str(&write_list(&where_strs, &fmt)); - } - - // Return type. - if ret_str.len() > 0 { - // If we've already gone multi-line, or the return type would push - // over the max width, then put the return type on a new line. - if result.contains("\n") || - result.len() + indent + ret_str.len() > MAX_WIDTH { - let indent = match FN_RETURN_INDENT { - ReturnIndent::WithWhereClause => indent + 4, - // TODO we might want to check that using the arg indent doesn't - // blow our budget, and if it does, then fallback to the where - // clause indent. - ReturnIndent::WithArgs => arg_indent, - }; - - result.push('\n'); - result.push_str(&make_indent(indent)); - } else { - result.push(' '); - } - result.push_str(&ret_str); - } - - // Prepare for the function body by possibly adding a newline and indent. - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. - if newline_brace { - result.push('\n'); - result.push_str(&make_indent(self.block_indent)); - } else { - result.push(' '); - } - - result - } - - // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly - fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { - format!("{}: {}", - pprust::pat_to_string(&arg.pat), - pprust::ty_to_string(&arg.ty)) - } fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String { -- cgit 1.4.1-3-g733a5 From a652a83ffd1ba897efa87cdcdd8a5d364410b7a8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 16:49:16 +1200 Subject: Trivial reformatting --- src/mod.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 750b3159a93..7ea31aec732 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -282,15 +282,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } -fn make_indent(width: usize) -> String { - let mut indent = String::with_capacity(width); - for _ in 0..width { - indent.push(' ') - } - indent -} - - impl<'a> FmtVisitor<'a> { fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { FmtVisitor { @@ -603,6 +594,15 @@ fn next_char(s: &str, mut i: usize) -> usize { i } +#[inline] +fn make_indent(width: usize) -> String { + let mut indent = String::with_capacity(width); + for _ in 0..width { + indent.push(' ') + } + indent +} + struct RustFmtCalls { input_path: Option, } @@ -615,7 +615,10 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { Compilation::Continue } - fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { + fn some_input(&mut self, + input: Input, + input_path: Option) + -> (Input, Option) { match input_path { Some(ref ip) => self.input_path = Some(ip.clone()), _ => { -- cgit 1.4.1-3-g733a5 From 6e082f7aad35afa89563180d1cdecab3afdf573f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 19:59:48 +1200 Subject: Extract some methods for functions. --- src/functions.rs | 72 +++++++++++++++++++++++++++++++++++--------------------- src/mod.rs | 1 + 2 files changed, 46 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index f1a9c395470..ffacfa8cf56 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -16,6 +16,7 @@ use syntax::print::pprust; use syntax::parse::token; impl<'a> FmtVisitor<'a> { + // TODO extract methods for args and generics pub fn rewrite_fn(&mut self, indent: usize, ident: ast::Ident, @@ -31,11 +32,7 @@ impl<'a> FmtVisitor<'a> { // who comments there probably deserves what they get. let where_clause = &generics.where_clause; - let newline_brace = match FN_BRACE_STYLE { - BraceStyle::AlwaysNextLine => true, - BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, - _ => false, - }; + let newline_brace = self.newline_for_brace(where_clause); let mut result = String::with_capacity(1024); // Vis unsafety abi. @@ -81,11 +78,7 @@ impl<'a> FmtVisitor<'a> { result.push('>'); } - let ret_str = match fd.output { - ast::FunctionRetTy::DefaultReturn(_) => String::new(), - ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), - ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), - }; + let ret_str = self.rewrite_return(&fd.output); // Args. let args = &fd.inputs; @@ -172,23 +165,7 @@ impl<'a> FmtVisitor<'a> { result.push(')'); // Where clause. - if where_clause.predicates.len() > 0 { - result.push('\n'); - result.push_str(&make_indent(indent + 4)); - result.push_str("where "); - - let budget = IDEAL_WIDTH + LEEWAY - indent - 10; - let fmt = ListFormatting { - tactic: ListTactic::Vertical, - separator: ",", - trailing_separator: SeparatorTactic::Always, - indent: indent + 10, - h_width: budget, - v_width: budget, - }; - let where_strs: Vec<_> = where_clause.predicates.iter().map(|p| (self.rewrite_pred(p), String::new())).collect(); - result.push_str(&write_list(&where_strs, &fmt)); - } + result.push_str(&self.rewrite_where_clause(where_clause, indent)); // Return type. if ret_str.len() > 0 { @@ -225,6 +202,47 @@ impl<'a> FmtVisitor<'a> { result } + fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { + match FN_BRACE_STYLE { + BraceStyle::AlwaysNextLine => true, + BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, + _ => false, + } + } + + fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, indent: usize) -> String { + let mut result = String::new(); + if where_clause.predicates.len() == 0 { + return result; + } + + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + result.push_str("where "); + + let budget = IDEAL_WIDTH + LEEWAY - indent - 10; + let fmt = ListFormatting { + tactic: ListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Always, + indent: indent + 10, + h_width: budget, + v_width: budget, + }; + let where_strs: Vec<_> = where_clause.predicates.iter().map(|p| (self.rewrite_pred(p), String::new())).collect(); + result.push_str(&write_list(&where_strs, &fmt)); + + result + } + + fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { + match *ret { + ast::FunctionRetTy::DefaultReturn(_) => String::new(), + ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), + ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), + } + } + // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { format!("{}: {}", diff --git a/src/mod.rs b/src/mod.rs index 7ea31aec732..0e3ad3a088b 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -192,6 +192,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent -= TAB_SPACES; // TODO we should compress any newlines here to just one + // TODO somewhere here we are preserving bogus whitespace self.format_missing_with_indent(b.span.hi - BytePos(1)); self.changes.push_str_span(b.span, "}"); self.last_pos = b.span.hi; -- cgit 1.4.1-3-g733a5 From 8ca3dc063e51a985425adfa61571f26002b4a4d2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 20:40:36 +1200 Subject: Refactor missing spans and fix bug with trailing whitespace --- src/functions.rs | 2 +- src/missed_spans.rs | 85 +++++++++++++++++++++++++++++------------------------ src/mod.rs | 7 ++--- 3 files changed, 51 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index ffacfa8cf56..d4f5be8108f 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -224,7 +224,7 @@ impl<'a> FmtVisitor<'a> { let fmt = ListFormatting { tactic: ListTactic::Vertical, separator: ",", - trailing_separator: SeparatorTactic::Always, + trailing_separator: SeparatorTactic::Never, indent: indent + 10, h_width: budget, v_width: budget, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index bea83a4f90f..eb12f8ec1e1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -9,32 +9,30 @@ // except according to those terms. use {FmtVisitor, make_indent}; -use syntax::codemap::{self, Span, BytePos}; +use syntax::codemap::{self, BytePos}; impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, span, _| { - this.changes.push_str_span(span, last_snippet) + self.format_missing_inner(end, |this, last_snippet, file_name, _| { + this.changes.push_str(file_name, last_snippet) }) } pub fn format_missing_with_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, span, snippet| { + self.format_missing_inner(end, |this, last_snippet, file_name, snippet| { + this.changes.push_str(file_name, last_snippet.trim_right()); if last_snippet == snippet { - // No new lines - this.changes.push_str_span(span, last_snippet); - this.changes.push_str_span(span, "\n"); - } else { - this.changes.push_str_span(span, last_snippet.trim_right()); + // No new lines in the snippet. + this.changes.push_str(file_name, "\n"); } let indent = make_indent(this.block_indent); - this.changes.push_str_span(span, &indent); + this.changes.push_str(file_name, &indent); }) } - fn format_missing_inner(&mut self, + fn format_missing_inner(&mut self, end: BytePos, process_last_snippet: F) { @@ -52,44 +50,55 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(start), self.codemap.lookup_char_pos(end)); - self.last_pos = end; let spans = self.changes.filespans_for_span(start, end); for (i, &(start, end)) in spans.iter().enumerate() { let span = codemap::mk_sp(BytePos(start), BytePos(end)); + let file_name = &self.codemap.span_to_filename(span); let snippet = self.snippet(span); - // Trim whitespace from the right hand side of each line. - // Annoyingly, the library functions for splitting by lines etc. are not - // quite right, so we must do it ourselves. - let mut line_start = 0; - let mut last_wspace = None; - for (i, c) in snippet.char_indices() { - if c == '\n' { - if let Some(lw) = last_wspace { - self.changes.push_str_span(span, &snippet[line_start..lw]); - self.changes.push_str_span(span, "\n"); - } else { - self.changes.push_str_span(span, &snippet[line_start..i+1]); - } + self.write_snippet(&snippet, + file_name, + i == spans.len() - 1, + &process_last_snippet); + } + } - line_start = i + 1; - last_wspace = None; + fn write_snippet(&mut self, + snippet: &str, + file_name: &str, + last_snippet: bool, + process_last_snippet: F) { + // Trim whitespace from the right hand side of each line. + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let mut line_start = 0; + let mut last_wspace = None; + for (i, c) in snippet.char_indices() { + if c == '\n' { + if let Some(lw) = last_wspace { + self.changes.push_str(file_name, &snippet[line_start..lw]); + self.changes.push_str(file_name, "\n"); } else { - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(i); - } - } else { - last_wspace = None; - } + self.changes.push_str(file_name, &snippet[line_start..i+1]); } - } - if i == spans.len() - 1 { - process_last_snippet(self, &snippet[line_start..], span, &snippet); + + line_start = i + 1; + last_wspace = None; } else { - self.changes.push_str_span(span, &snippet[line_start..]); + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(i); + } + } else { + last_wspace = None; + } } } + if last_snippet { + process_last_snippet(self, &snippet[line_start..], file_name, snippet); + } else { + self.changes.push_str(file_name, &snippet[line_start..]); + } } } diff --git a/src/mod.rs b/src/mod.rs index 0e3ad3a088b..6a312ca6653 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -24,7 +24,6 @@ // dead spans // // Smoke testing till we can use it -// end of multi-line string has wspace // no newline at the end of doc.rs #[macro_use] @@ -192,7 +191,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent -= TAB_SPACES; // TODO we should compress any newlines here to just one - // TODO somewhere here we are preserving bogus whitespace self.format_missing_with_indent(b.span.hi - BytePos(1)); self.changes.push_str_span(b.span, "}"); self.last_pos = b.span.hi; @@ -557,7 +555,9 @@ impl<'a> FmtVisitor<'a> { ast::Expr_::ExprLit(ref l) => { match l.node { ast::Lit_::LitStr(ref is, _) => { - return self.rewrite_string_lit(&is, l.span, width, offset); + let result = self.rewrite_string_lit(&is, l.span, width, offset); + debug!("string lit: `{}`", result); + return result; } _ => {} } @@ -569,7 +569,6 @@ impl<'a> FmtVisitor<'a> { } let result = self.snippet(expr.span); - debug!("snippet: {}", result); result } } -- cgit 1.4.1-3-g733a5 From 4c869a1b9d3b7b93dd5f5328466a105c18277d91 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 21:01:19 +1200 Subject: Extract out more files --- src/expr.rs | 149 +++++++++++++++++ src/functions.rs | 4 +- src/imports.rs | 72 ++++++++ src/lists.rs | 2 +- src/missed_spans.rs | 4 +- src/mod.rs | 469 +--------------------------------------------------- src/types.rs | 105 ++++++++++++ src/utils.rs | 40 +++++ src/visitor.rs | 173 +++++++++++++++++++ 9 files changed, 554 insertions(+), 464 deletions(-) create mode 100644 src/expr.rs create mode 100644 src/imports.rs create mode 100644 src/types.rs create mode 100644 src/utils.rs create mode 100644 src/visitor.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs new file mode 100644 index 00000000000..1da66c4e328 --- /dev/null +++ b/src/expr.rs @@ -0,0 +1,149 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use visitor::FmtVisitor; +use utils::*; +use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; + +use syntax::{ast, ptr}; +use syntax::codemap::{Span, Pos}; + +use {MAX_WIDTH, MIN_STRING}; + +impl<'a> FmtVisitor<'a> { + // TODO NEEDS TESTS + fn rewrite_string_lit(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { + // FIXME I bet this stomps unicode escapes in the source string + + // Check if there is anything to fix: we always try to fixup multi-line + // strings, or if the string is too long for the line. + let l_loc = self.codemap.lookup_char_pos(span.lo); + let r_loc = self.codemap.lookup_char_pos(span.hi); + if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH { + return self.snippet(span); + } + + // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) + + let s = s.escape_default(); + + let offset = offset + 1; + let indent = make_indent(offset); + let indent = &indent; + + let max_chars = width - 1; + + let mut cur_start = 0; + let mut result = String::new(); + result.push('"'); + loop { + let mut cur_end = cur_start + max_chars; + + if cur_end >= s.len() { + result.push_str(&s[cur_start..]); + break; + } + + // Make sure we're on a char boundary. + cur_end = next_char(&s, cur_end); + + // Push cur_end left until we reach whitespace + while !s.char_at(cur_end-1).is_whitespace() { + cur_end = prev_char(&s, cur_end); + + if cur_end - cur_start < MIN_STRING { + // We can't break at whitespace, fall back to splitting + // anywhere that doesn't break an escape sequence + cur_end = next_char(&s, cur_start + max_chars); + while s.char_at(cur_end) == '\\' { + cur_end = prev_char(&s, cur_end); + } + } + } + // Make sure there is no whitespace to the right of the break. + while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { + cur_end = next_char(&s, cur_end+1); + } + result.push_str(&s[cur_start..cur_end]); + result.push_str("\\\n"); + result.push_str(indent); + + cur_start = cur_end; + } + result.push('"'); + + result + } + + fn rewrite_call(&mut self, + callee: &ast::Expr, + args: &[ptr::P], + width: usize, + offset: usize) + -> String + { + debug!("rewrite_call, width: {}, offset: {}", width, offset); + + // TODO using byte lens instead of char lens (and probably all over the place too) + let callee_str = self.rewrite_expr(callee, width, offset); + debug!("rewrite_call, callee_str: `{}`", callee_str); + // 2 is for parens. + let remaining_width = width - callee_str.len() - 2; + let offset = callee_str.len() + 1 + offset; + let arg_count = args.len(); + + let args_str = if arg_count > 0 { + let args: Vec<_> = args.iter().map(|e| (self.rewrite_expr(e, + remaining_width, + offset), String::new())).collect(); + // TODO move this into write_list + let tactics = if args.iter().any(|&(ref s, _)| s.contains('\n')) { + ListTactic::Vertical + } else { + ListTactic::HorizontalVertical + }; + let fmt = ListFormatting { + tactic: tactics, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: remaining_width, + v_width: remaining_width, + }; + write_list(&args, &fmt) + } else { + String::new() + }; + + format!("{}({})", callee_str, args_str) + } + + pub fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { + match expr.node { + ast::Expr_::ExprLit(ref l) => { + match l.node { + ast::Lit_::LitStr(ref is, _) => { + let result = self.rewrite_string_lit(&is, l.span, width, offset); + debug!("string lit: `{}`", result); + return result; + } + _ => {} + } + } + ast::Expr_::ExprCall(ref callee, ref args) => { + return self.rewrite_call(callee, args, width, offset); + } + _ => {} + } + + let result = self.snippet(expr.span); + result + } +} diff --git a/src/functions.rs b/src/functions.rs index d4f5be8108f..cf459931ba7 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {FmtVisitor, ReturnIndent, make_indent, MAX_WIDTH, BraceStyle, +use {ReturnIndent, MAX_WIDTH, BraceStyle, IDEAL_WIDTH, LEEWAY, FN_BRACE_STYLE, FN_RETURN_INDENT}; +use utils::make_indent; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use visitor::FmtVisitor; use syntax::{ast, abi}; use syntax::print::pprust; use syntax::parse::token; diff --git a/src/imports.rs b/src/imports.rs new file mode 100644 index 00000000000..34cab06b2fc --- /dev/null +++ b/src/imports.rs @@ -0,0 +1,72 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use visitor::FmtVisitor; +use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; + +use syntax::ast; +use syntax::codemap::Span; +use syntax::parse::token; +use syntax::print::pprust; + +use IDEAL_WIDTH; + +impl<'a> FmtVisitor<'a> { + // Basically just pretty prints a multi-item import. + pub fn rewrite_use_list(&mut self, + path: &ast::Path, + path_list: &[ast::PathListItem], + vp_span: Span) -> String { + // FIXME remove unused imports + + // FIXME check indentation + let l_loc = self.codemap.lookup_char_pos(vp_span.lo); + + let path_str = pprust::path_to_string(&path); + + // 3 = :: + { + let indent = l_loc.col.0 + path_str.len() + 3; + let fmt = ListFormatting { + tactic: ListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + // 2 = } + ; + h_width: IDEAL_WIDTH - (indent + path_str.len() + 2), + v_width: IDEAL_WIDTH - (indent + path_str.len() + 2), + }; + + // TODO handle any comments inbetween items. + // If `self` is in the list, put it first. + let head = if path_list.iter().any(|vpi| + if let ast::PathListItem_::PathListMod{ .. } = vpi.node { + true + } else { + false + } + ) { + Some(("self".to_string(), String::new())) + } else { + None + }; + + let items: Vec<_> = head.into_iter().chain(path_list.iter().filter_map(|vpi| { + match vpi.node { + ast::PathListItem_::PathListIdent{ name, .. } => { + Some((token::get_ident(name).to_string(), String::new())) + } + // Skip `self`, because we added it above. + ast::PathListItem_::PathListMod{ .. } => None, + } + })).collect(); + + format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) + } +} diff --git a/src/lists.rs b/src/lists.rs index 5800f76b95a..0cfa592f03e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use make_indent; +use utils::make_indent; #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index eb12f8ec1e1..7b352dc8a04 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {FmtVisitor, make_indent}; +use utils::make_indent; +use visitor::FmtVisitor; + use syntax::codemap::{self, BytePos}; impl<'a> FmtVisitor<'a> { diff --git a/src/mod.rs b/src/mod.rs index 6a312ca6653..5c179dc910e 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -40,22 +40,25 @@ use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; -use syntax::{ast, ptr}; -use syntax::codemap::{CodeMap, Span, Pos, BytePos}; +use syntax::ast; +use syntax::codemap::CodeMap; use syntax::diagnostics; -use syntax::parse::token; -use syntax::print::pprust; use syntax::visit; use std::path::PathBuf; use changes::ChangeSet; -use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use visitor::FmtVisitor; mod changes; +mod visitor; mod functions; mod missed_spans; mod lists; +mod utils; +mod types; +mod expr; +mod imports; const IDEAL_WIDTH: usize = 80; const LEEWAY: usize = 5; @@ -147,462 +150,6 @@ fn fmt_lines(changes: &mut ChangeSet) { } } -struct FmtVisitor<'a> { - codemap: &'a CodeMap, - changes: ChangeSet<'a>, - last_pos: BytePos, - // TODO RAII util for indenting - block_indent: usize, -} - -impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { - fn visit_expr(&mut self, ex: &'v ast::Expr) { - debug!("visit_expr: {:?} {:?}", - self.codemap.lookup_char_pos(ex.span.lo), - self.codemap.lookup_char_pos(ex.span.hi)); - self.format_missing(ex.span.lo); - let offset = self.changes.cur_offset_span(ex.span); - let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset); - self.changes.push_str_span(ex.span, &new_str); - self.last_pos = ex.span.hi; - } - - fn visit_block(&mut self, b: &'v ast::Block) { - debug!("visit_block: {:?} {:?}", - self.codemap.lookup_char_pos(b.span.lo), - self.codemap.lookup_char_pos(b.span.hi)); - self.format_missing(b.span.lo); - - self.changes.push_str_span(b.span, "{"); - self.last_pos = self.last_pos + BytePos(1); - self.block_indent += TAB_SPACES; - - for stmt in &b.stmts { - self.format_missing_with_indent(stmt.span.lo); - self.visit_stmt(&stmt) - } - match b.expr { - Some(ref e) => { - self.format_missing_with_indent(e.span.lo); - self.visit_expr(e); - } - None => {} - } - - self.block_indent -= TAB_SPACES; - // TODO we should compress any newlines here to just one - self.format_missing_with_indent(b.span.hi - BytePos(1)); - self.changes.push_str_span(b.span, "}"); - self.last_pos = b.span.hi; - } - - // Note that this only gets called for function defintions. Required methods - // on traits do not get handled here. - fn visit_fn(&mut self, - fk: visit::FnKind<'v>, - fd: &'v ast::FnDecl, - b: &'v ast::Block, - s: Span, - _: ast::NodeId) { - self.format_missing(s.lo); - self.last_pos = s.lo; - - // TODO need to check against expected indent - let indent = self.codemap.lookup_char_pos(s.lo).col.0; - match fk { - visit::FkItemFn(ident, ref generics, ref unsafety, ref abi, vis) => { - let new_fn = self.rewrite_fn(indent, - ident, - fd, - None, - generics, - unsafety, - abi, - vis); - self.changes.push_str_span(s, &new_fn); - } - visit::FkMethod(ident, ref sig, vis) => { - let new_fn = self.rewrite_fn(indent, - ident, - fd, - Some(&sig.explicit_self), - &sig.generics, - &sig.unsafety, - &sig.abi, - vis.unwrap_or(ast::Visibility::Inherited)); - self.changes.push_str_span(s, &new_fn); - } - visit::FkFnBlock(..) => {} - } - - self.last_pos = b.span.lo; - self.visit_block(b) - } - - fn visit_item(&mut self, item: &'v ast::Item) { - match item.node { - ast::Item_::ItemUse(ref vp) => { - match vp.node { - ast::ViewPath_::ViewPathList(ref path, ref path_list) => { - self.format_missing(item.span.lo); - let new_str = self.rewrite_use_list(path, path_list, vp.span); - self.changes.push_str_span(item.span, &new_str); - self.last_pos = item.span.hi; - } - ast::ViewPath_::ViewPathGlob(_) => { - // FIXME convert to list? - } - _ => {} - } - visit::walk_item(self, item); - } - ast::Item_::ItemImpl(..) => { - self.block_indent += TAB_SPACES; - visit::walk_item(self, item); - self.block_indent -= TAB_SPACES; - } - _ => { - visit::walk_item(self, item); - } - } - } - - fn visit_mac(&mut self, mac: &'v ast::Mac) { - visit::walk_mac(self, mac) - } - - fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) { - // Only visit inline mods here. - if self.codemap.lookup_char_pos(s.lo).file.name != - self.codemap.lookup_char_pos(m.inner.lo).file.name { - return; - } - visit::walk_mod(self, m); - } -} - -impl<'a> FmtVisitor<'a> { - fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { - FmtVisitor { - codemap: codemap, - changes: ChangeSet::from_codemap(codemap), - last_pos: BytePos(0), - block_indent: 0, - } - } - - fn snippet(&self, span: Span) -> String { - match self.codemap.span_to_snippet(span) { - Ok(s) => s, - Err(_) => { - println!("Couldn't make snippet for span {:?}->{:?}", - self.codemap.lookup_char_pos(span.lo), - self.codemap.lookup_char_pos(span.hi)); - "".to_string() - } - } - } - - // TODO NEEDS TESTS - fn rewrite_string_lit(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { - // FIXME I bet this stomps unicode escapes in the source string - - // Check if there is anything to fix: we always try to fixup multi-line - // strings, or if the string is too long for the line. - let l_loc = self.codemap.lookup_char_pos(span.lo); - let r_loc = self.codemap.lookup_char_pos(span.hi); - if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH { - return self.snippet(span); - } - - // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) - - let s = s.escape_default(); - - let offset = offset + 1; - let indent = make_indent(offset); - let indent = &indent; - - let max_chars = width - 1; - - let mut cur_start = 0; - let mut result = String::new(); - result.push('"'); - loop { - let mut cur_end = cur_start + max_chars; - - if cur_end >= s.len() { - result.push_str(&s[cur_start..]); - break; - } - - // Make sure we're on a char boundary. - cur_end = next_char(&s, cur_end); - - // Push cur_end left until we reach whitespace - while !s.char_at(cur_end-1).is_whitespace() { - cur_end = prev_char(&s, cur_end); - - if cur_end - cur_start < MIN_STRING { - // We can't break at whitespace, fall back to splitting - // anywhere that doesn't break an escape sequence - cur_end = next_char(&s, cur_start + max_chars); - while s.char_at(cur_end) == '\\' { - cur_end = prev_char(&s, cur_end); - } - } - } - // Make sure there is no whitespace to the right of the break. - while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { - cur_end = next_char(&s, cur_end+1); - } - result.push_str(&s[cur_start..cur_end]); - result.push_str("\\\n"); - result.push_str(indent); - - cur_start = cur_end; - } - result.push('"'); - - result - } - - // Basically just pretty prints a multi-item import. - fn rewrite_use_list(&mut self, - path: &ast::Path, - path_list: &[ast::PathListItem], - vp_span: Span) -> String { - // FIXME remove unused imports - - // FIXME check indentation - let l_loc = self.codemap.lookup_char_pos(vp_span.lo); - - let path_str = pprust::path_to_string(&path); - - // 3 = :: + { - let indent = l_loc.col.0 + path_str.len() + 3; - let fmt = ListFormatting { - tactic: ListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - // 2 = } + ; - h_width: IDEAL_WIDTH - (indent + path_str.len() + 2), - v_width: IDEAL_WIDTH - (indent + path_str.len() + 2), - }; - - // TODO handle any comments inbetween items. - // If `self` is in the list, put it first. - let head = if path_list.iter().any(|vpi| - if let ast::PathListItem_::PathListMod{ .. } = vpi.node { - true - } else { - false - } - ) { - Some(("self".to_string(), String::new())) - } else { - None - }; - - let items: Vec<_> = head.into_iter().chain(path_list.iter().filter_map(|vpi| { - match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => { - Some((token::get_ident(name).to_string(), String::new())) - } - // Skip `self`, because we added it above. - ast::PathListItem_::PathListMod{ .. } => None, - } - })).collect(); - - format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) - } - - - fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String - { - // TODO dead spans - // TODO assumes we'll always fit on one line... - match predicate { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, - ref bounded_ty, - ref bounds, - ..}) => { - if bound_lifetimes.len() > 0 { - format!("for<{}> {}: {}", - bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), - pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) - - } else { - format!("{}: {}", - pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) - } - } - &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, - ref bounds, - ..}) => { - format!("{}: {}", - pprust::lifetime_to_string(lifetime), - bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) - } - &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) - } - } - } - - fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String - { - if lifetime.bounds.len() == 0 { - return pprust::lifetime_to_string(&lifetime.lifetime); - } - - format!("{}: {}", - pprust::lifetime_to_string(&lifetime.lifetime), - lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) - } - - fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String - { - match *bound { - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { - self.rewrite_poly_trait_ref(tref) - } - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { - format!("?{}", self.rewrite_poly_trait_ref(tref)) - } - ast::TyParamBound::RegionTyParamBound(ref l) => { - pprust::lifetime_to_string(l) - } - } - } - - fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String - { - let mut result = String::with_capacity(128); - result.push_str(&token::get_ident(ty_param.ident)); - if ty_param.bounds.len() > 0 { - result.push_str(": "); - result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(", ")); - } - if let Some(ref def) = ty_param.default { - result.push_str(" = "); - result.push_str(&pprust::ty_to_string(&def)); - } - - result - } - - fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String - { - if t.bound_lifetimes.len() > 0 { - format!("for<{}> {}", - t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), - pprust::path_to_string(&t.trait_ref.path)) - - } else { - pprust::path_to_string(&t.trait_ref.path) - } - } - - fn rewrite_call(&mut self, - callee: &ast::Expr, - args: &[ptr::P], - width: usize, - offset: usize) - -> String - { - debug!("rewrite_call, width: {}, offset: {}", width, offset); - - // TODO using byte lens instead of char lens (and probably all over the place too) - let callee_str = self.rewrite_expr(callee, width, offset); - debug!("rewrite_call, callee_str: `{}`", callee_str); - // 2 is for parens. - let remaining_width = width - callee_str.len() - 2; - let offset = callee_str.len() + 1 + offset; - let arg_count = args.len(); - - let args_str = if arg_count > 0 { - let args: Vec<_> = args.iter().map(|e| (self.rewrite_expr(e, - remaining_width, - offset), String::new())).collect(); - // TODO move this into write_list - let tactics = if args.iter().any(|&(ref s, _)| s.contains('\n')) { - ListTactic::Vertical - } else { - ListTactic::HorizontalVertical - }; - let fmt = ListFormatting { - tactic: tactics, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: remaining_width, - v_width: remaining_width, - }; - write_list(&args, &fmt) - } else { - String::new() - }; - - format!("{}({})", callee_str, args_str) - } - - fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { - match expr.node { - ast::Expr_::ExprLit(ref l) => { - match l.node { - ast::Lit_::LitStr(ref is, _) => { - let result = self.rewrite_string_lit(&is, l.span, width, offset); - debug!("string lit: `{}`", result); - return result; - } - _ => {} - } - } - ast::Expr_::ExprCall(ref callee, ref args) => { - return self.rewrite_call(callee, args, width, offset); - } - _ => {} - } - - let result = self.snippet(expr.span); - result - } -} - -#[inline] -fn prev_char(s: &str, mut i: usize) -> usize { - if i == 0 { return 0; } - - i -= 1; - while !s.is_char_boundary(i) { - i -= 1; - } - i -} - -#[inline] -fn next_char(s: &str, mut i: usize) -> usize { - if i >= s.len() { return s.len(); } - - while !s.is_char_boundary(i) { - i += 1; - } - i -} - -#[inline] -fn make_indent(width: usize) -> String { - let mut indent = String::with_capacity(width); - for _ in 0..width { - indent.push(' ') - } - indent -} - struct RustFmtCalls { input_path: Option, } diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 00000000000..839482f921a --- /dev/null +++ b/src/types.rs @@ -0,0 +1,105 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use visitor::FmtVisitor; + +use syntax::ast; +use syntax::parse::token; +use syntax::print::pprust; + +impl<'a> FmtVisitor<'a> { + pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String + { + // TODO dead spans + // TODO assumes we'll always fit on one line... + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, + ref bounded_ty, + ref bounds, + ..}) => { + if bound_lifetimes.len() > 0 { + format!("for<{}> {}: {}", + bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), + pprust::ty_to_string(bounded_ty), + bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) + + } else { + format!("{}: {}", + pprust::ty_to_string(bounded_ty), + bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) + } + } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bounds, + ..}) => { + format!("{}: {}", + pprust::lifetime_to_string(lifetime), + bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) + } + } + } + + pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String + { + if lifetime.bounds.len() == 0 { + return pprust::lifetime_to_string(&lifetime.lifetime); + } + + format!("{}: {}", + pprust::lifetime_to_string(&lifetime.lifetime), + lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) + } + + pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String + { + match *bound { + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { + self.rewrite_poly_trait_ref(tref) + } + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { + format!("?{}", self.rewrite_poly_trait_ref(tref)) + } + ast::TyParamBound::RegionTyParamBound(ref l) => { + pprust::lifetime_to_string(l) + } + } + } + + pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String + { + let mut result = String::with_capacity(128); + result.push_str(&token::get_ident(ty_param.ident)); + if ty_param.bounds.len() > 0 { + result.push_str(": "); + result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(", ")); + } + if let Some(ref def) = ty_param.default { + result.push_str(" = "); + result.push_str(&pprust::ty_to_string(&def)); + } + + result + } + + fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String + { + if t.bound_lifetimes.len() > 0 { + format!("for<{}> {}", + t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), + pprust::path_to_string(&t.trait_ref.path)) + + } else { + pprust::path_to_string(&t.trait_ref.path) + } + } +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 00000000000..c22b85f4563 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,40 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#[inline] +pub fn prev_char(s: &str, mut i: usize) -> usize { + if i == 0 { return 0; } + + i -= 1; + while !s.is_char_boundary(i) { + i -= 1; + } + i +} + +#[inline] +pub fn next_char(s: &str, mut i: usize) -> usize { + if i >= s.len() { return s.len(); } + + while !s.is_char_boundary(i) { + i += 1; + } + i +} + +#[inline] +pub fn make_indent(width: usize) -> String { + let mut indent = String::with_capacity(width); + for _ in 0..width { + indent.push(' ') + } + indent +} diff --git a/src/visitor.rs b/src/visitor.rs new file mode 100644 index 00000000000..7e8a885c657 --- /dev/null +++ b/src/visitor.rs @@ -0,0 +1,173 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::ast; +use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::visit; + +use {MAX_WIDTH, TAB_SPACES}; +use changes::ChangeSet; + +pub struct FmtVisitor<'a> { + pub codemap: &'a CodeMap, + pub changes: ChangeSet<'a>, + pub last_pos: BytePos, + // TODO RAII util for indenting + pub block_indent: usize, +} + +impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { + fn visit_expr(&mut self, ex: &'v ast::Expr) { + debug!("visit_expr: {:?} {:?}", + self.codemap.lookup_char_pos(ex.span.lo), + self.codemap.lookup_char_pos(ex.span.hi)); + self.format_missing(ex.span.lo); + let offset = self.changes.cur_offset_span(ex.span); + let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset); + self.changes.push_str_span(ex.span, &new_str); + self.last_pos = ex.span.hi; + } + + fn visit_block(&mut self, b: &'v ast::Block) { + debug!("visit_block: {:?} {:?}", + self.codemap.lookup_char_pos(b.span.lo), + self.codemap.lookup_char_pos(b.span.hi)); + self.format_missing(b.span.lo); + + self.changes.push_str_span(b.span, "{"); + self.last_pos = self.last_pos + BytePos(1); + self.block_indent += TAB_SPACES; + + for stmt in &b.stmts { + self.format_missing_with_indent(stmt.span.lo); + self.visit_stmt(&stmt) + } + match b.expr { + Some(ref e) => { + self.format_missing_with_indent(e.span.lo); + self.visit_expr(e); + } + None => {} + } + + self.block_indent -= TAB_SPACES; + // TODO we should compress any newlines here to just one + self.format_missing_with_indent(b.span.hi - BytePos(1)); + self.changes.push_str_span(b.span, "}"); + self.last_pos = b.span.hi; + } + + // Note that this only gets called for function defintions. Required methods + // on traits do not get handled here. + fn visit_fn(&mut self, + fk: visit::FnKind<'v>, + fd: &'v ast::FnDecl, + b: &'v ast::Block, + s: Span, + _: ast::NodeId) { + self.format_missing(s.lo); + self.last_pos = s.lo; + + // TODO need to check against expected indent + let indent = self.codemap.lookup_char_pos(s.lo).col.0; + match fk { + visit::FkItemFn(ident, ref generics, ref unsafety, ref abi, vis) => { + let new_fn = self.rewrite_fn(indent, + ident, + fd, + None, + generics, + unsafety, + abi, + vis); + self.changes.push_str_span(s, &new_fn); + } + visit::FkMethod(ident, ref sig, vis) => { + let new_fn = self.rewrite_fn(indent, + ident, + fd, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.abi, + vis.unwrap_or(ast::Visibility::Inherited)); + self.changes.push_str_span(s, &new_fn); + } + visit::FkFnBlock(..) => {} + } + + self.last_pos = b.span.lo; + self.visit_block(b) + } + + fn visit_item(&mut self, item: &'v ast::Item) { + match item.node { + ast::Item_::ItemUse(ref vp) => { + match vp.node { + ast::ViewPath_::ViewPathList(ref path, ref path_list) => { + self.format_missing(item.span.lo); + let new_str = self.rewrite_use_list(path, path_list, vp.span); + self.changes.push_str_span(item.span, &new_str); + self.last_pos = item.span.hi; + } + ast::ViewPath_::ViewPathGlob(_) => { + // FIXME convert to list? + } + _ => {} + } + visit::walk_item(self, item); + } + ast::Item_::ItemImpl(..) => { + self.block_indent += TAB_SPACES; + visit::walk_item(self, item); + self.block_indent -= TAB_SPACES; + } + _ => { + visit::walk_item(self, item); + } + } + } + + fn visit_mac(&mut self, mac: &'v ast::Mac) { + visit::walk_mac(self, mac) + } + + fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) { + // Only visit inline mods here. + if self.codemap.lookup_char_pos(s.lo).file.name != + self.codemap.lookup_char_pos(m.inner.lo).file.name { + return; + } + visit::walk_mod(self, m); + } +} + +impl<'a> FmtVisitor<'a> { + pub fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { + FmtVisitor { + codemap: codemap, + changes: ChangeSet::from_codemap(codemap), + last_pos: BytePos(0), + block_indent: 0, + } + } + + pub fn snippet(&self, span: Span) -> String { + match self.codemap.span_to_snippet(span) { + Ok(s) => s, + Err(_) => { + println!("Couldn't make snippet for span {:?}->{:?}", + self.codemap.lookup_char_pos(span.lo), + self.codemap.lookup_char_pos(span.hi)); + "".to_string() + } + } + } +} -- cgit 1.4.1-3-g733a5 From 854b52dbedbfe4944309514e98a7aba4185c2c5c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Apr 2015 22:50:43 +1200 Subject: Keep comments on fn arguments --- src/functions.rs | 288 ++++++++++++++++++++++++++++++++++++------------------- src/imports.rs | 4 + src/lists.rs | 59 ++++++++---- src/mod.rs | 13 ++- 4 files changed, 242 insertions(+), 122 deletions(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index cf459931ba7..5b08fa797bc 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -14,6 +14,7 @@ use utils::make_indent; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use visitor::FmtVisitor; use syntax::{ast, abi}; +use syntax::codemap::{self, Span}; use syntax::print::pprust; use syntax::parse::token; @@ -55,42 +56,164 @@ impl<'a> FmtVisitor<'a> { result.push_str(&token::get_ident(ident)); // Generics. - // FIXME convert bounds to where clauses where they get too big or if - // there is a where clause at all. - let lifetimes: &[_] = &generics.lifetimes; - let tys: &[_] = &generics.ty_params; - if lifetimes.len() + tys.len() > 0 { - let budget = MAX_WIDTH - indent - result.len() - 2; - // TODO might need to insert a newline if the generics are really long - result.push('<'); + result.push_str(&self.rewrite_generics(generics, indent)); - let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); - let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); - let generics_strs: Vec<_> = lt_strs.chain(ty_strs).map(|s| (s, String::new())).collect(); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + result.len() + 1, - h_width: budget, - v_width: budget, - }; - result.push_str(&write_list(&generics_strs, &fmt)); + let ret_str = self.rewrite_return(&fd.output); - result.push('>'); + // Args. + let (one_line_budget, multi_line_budget, arg_indent) = + self.compute_budgets_for_args(&mut result, indent, ret_str.len(), newline_brace); + + result.push('('); + result.push_str(&self.rewrite_args(&fd.inputs, + explicit_self, + one_line_budget, + multi_line_budget, + arg_indent, + span_for_return(&fd.output))); + result.push(')'); + + // Where clause. + result.push_str(&self.rewrite_where_clause(where_clause, indent)); + + // Return type. + if ret_str.len() > 0 { + // If we've already gone multi-line, or the return type would push + // over the max width, then put the return type on a new line. + if result.contains("\n") || + result.len() + indent + ret_str.len() > MAX_WIDTH { + let indent = match FN_RETURN_INDENT { + ReturnIndent::WithWhereClause => indent + 4, + // TODO we might want to check that using the arg indent doesn't + // blow our budget, and if it does, then fallback to the where + // clause indent. + ReturnIndent::WithArgs => arg_indent, + }; + + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + result.push_str(&ret_str); } - let ret_str = self.rewrite_return(&fd.output); + // Prepare for the function body by possibly adding a newline and indent. + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + if newline_brace { + result.push('\n'); + result.push_str(&make_indent(self.block_indent)); + } else { + result.push(' '); + } - // Args. - let args = &fd.inputs; + result + } + + fn rewrite_args(&self, + args: &[ast::Arg], + explicit_self: Option<&ast::ExplicitSelf>, + one_line_budget: usize, + multi_line_budget: usize, + arg_indent: usize, + ret_span: Span) + -> String + { + let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); + // Account for sugary self. + let mut min_args = 1; + if let Some(explicit_self) = explicit_self { + match explicit_self.node { + ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { + let lt_str = match lt { + &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), + &None => String::new(), + }; + let mut_str = match m { + &ast::Mutability::MutMutable => "mut ".to_string(), + &ast::Mutability::MutImmutable => String::new(), + }; + arg_item_strs[0] = format!("&{}{}self", lt_str, mut_str); + min_args = 2; + } + ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { + arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); + } + ast::ExplicitSelf_::SelfValue(_) => { + arg_item_strs[0] = "self".to_string(); + min_args = 2; + } + _ => {} + } + } + + // Comments between args + let mut arg_comments = Vec::new(); + if min_args == 2 { + arg_comments.push("".to_string()); + } + // TODO if there are no args, there might still be a comment, but without + // spans for the comment or parens, there is no chance of getting it right. + // You also don't get to put a comment on self, unless it is explicit. + if args.len() >= min_args { + let mut prev_end = args[min_args-1].ty.span.hi; + for arg in &args[min_args..] { + let cur_start = arg.pat.span.lo; + let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); + let mut snippet = snippet.trim(); + if snippet.starts_with(",") { + snippet = snippet[1..].trim(); + } else if snippet.ends_with(",") { + snippet = snippet[..snippet.len()-1].trim(); + } + arg_comments.push(snippet.to_string()); + prev_end = arg.ty.span.hi; + } + // Get the last commment. + // FIXME If you thought the crap with the commas was ugly, just wait. + // This is awful. We're going to look from the last arg span to the + // start of the return type span, then we drop everything after the + // first closing paren. Obviously, this will break if there is a + // closing paren in the comment. + // The fix is comments in the AST or a span for the closing paren. + let snippet = self.snippet(codemap::mk_sp(prev_end, ret_span.lo)); + let snippet = snippet.trim(); + let snippet = &snippet[..snippet.find(")").unwrap()]; + let snippet = snippet.trim(); + arg_comments.push(snippet.to_string()); + } + + debug!("comments: {:?}", arg_comments); + + assert_eq!(arg_item_strs.len(), arg_comments.len()); + let arg_strs: Vec<_> = arg_item_strs.into_iter().zip(arg_comments.into_iter()).collect(); + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: arg_indent, + h_width: one_line_budget, + v_width: multi_line_budget, + }; + + write_list(&arg_strs, &fmt) + } + fn compute_budgets_for_args(&self, + result: &mut String, + indent: usize, + ret_str_len: usize, + newline_brace: bool) + -> (usize, usize, usize) + { let mut budgets = None; // Try keeping everything on the same line if !result.contains("\n") { // 3 = `() `, space is before ret_string - let mut used_space = indent + result.len() + 3 + ret_str.len(); + let mut used_space = indent + result.len() + 3 + ret_str_len; if newline_brace { used_space += 2; } @@ -126,82 +249,7 @@ impl<'a> FmtVisitor<'a> { } } - let (one_line_budget, multi_line_budget, arg_indent) = budgets.unwrap(); - result.push('('); - - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: arg_indent, - h_width: one_line_budget, - v_width: multi_line_budget, - }; - // TODO dead spans - let mut arg_strs: Vec<_> = args.iter().map(|a| (self.rewrite_fn_input(a), String::new())).collect(); - // Account for sugary self. - if let Some(explicit_self) = explicit_self { - match explicit_self.node { - ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { - let lt_str = match lt { - &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), - &None => String::new(), - }; - let mut_str = match m { - &ast::Mutability::MutMutable => "mut ".to_string(), - &ast::Mutability::MutImmutable => String::new(), - }; - arg_strs[0].0 = format!("&{}{}self", lt_str, mut_str); - } - ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { - arg_strs[0].0 = format!("self: {}", pprust::ty_to_string(ty)); - } - ast::ExplicitSelf_::SelfValue(_) => { - arg_strs[0].0 = "self".to_string(); - } - _ => {} - } - } - result.push_str(&write_list(&arg_strs, &fmt)); - - result.push(')'); - - // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent)); - - // Return type. - if ret_str.len() > 0 { - // If we've already gone multi-line, or the return type would push - // over the max width, then put the return type on a new line. - if result.contains("\n") || - result.len() + indent + ret_str.len() > MAX_WIDTH { - let indent = match FN_RETURN_INDENT { - ReturnIndent::WithWhereClause => indent + 4, - // TODO we might want to check that using the arg indent doesn't - // blow our budget, and if it does, then fallback to the where - // clause indent. - ReturnIndent::WithArgs => arg_indent, - }; - - result.push('\n'); - result.push_str(&make_indent(indent)); - } else { - result.push(' '); - } - result.push_str(&ret_str); - } - - // Prepare for the function body by possibly adding a newline and indent. - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. - if newline_brace { - result.push('\n'); - result.push_str(&make_indent(self.block_indent)); - } else { - result.push(' '); - } - - result + budgets.unwrap() } fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { @@ -212,6 +260,36 @@ impl<'a> FmtVisitor<'a> { } } + fn rewrite_generics(&self, generics: &ast::Generics, indent: usize) -> String { + // FIXME convert bounds to where clauses where they get too big or if + // there is a where clause at all. + let mut result = String::new(); + let lifetimes: &[_] = &generics.lifetimes; + let tys: &[_] = &generics.ty_params; + if lifetimes.len() + tys.len() > 0 { + let budget = MAX_WIDTH - indent - result.len() - 2; + // TODO might need to insert a newline if the generics are really long + result.push('<'); + + let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); + let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); + let generics_strs: Vec<_> = lt_strs.chain(ty_strs).map(|s| (s, String::new())).collect(); + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + result.len() + 1, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&generics_strs, &fmt)); + + result.push('>'); + } + + result + } + fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, indent: usize) -> String { let mut result = String::new(); if where_clause.predicates.len() == 0 { @@ -252,3 +330,11 @@ impl<'a> FmtVisitor<'a> { pprust::ty_to_string(&arg.ty)) } } + +fn span_for_return(ret: &ast::FunctionRetTy) -> Span { + match *ret { + ast::FunctionRetTy::NoReturn(ref span) | + ast::FunctionRetTy::DefaultReturn(ref span) => span.clone(), + ast::FunctionRetTy::Return(ref ty) => ty.span, + } +} diff --git a/src/imports.rs b/src/imports.rs index 34cab06b2fc..7e64308eafc 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -18,6 +18,10 @@ use syntax::print::pprust; use IDEAL_WIDTH; +// TODO change import lists with one item to a single import +// remove empty lists (if they're even possible) +// TODO (some day) remove unused imports, expand globs, compress many single imports into a list import + impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. pub fn rewrite_use_list(&mut self, diff --git a/src/lists.rs b/src/lists.rs index 0cfa592f03e..01bad45b6af 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -41,30 +41,28 @@ pub struct ListFormatting<'a> { } // Format a list of strings into a string. -pub fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b>) -> String { +// Precondition: all strings in items are trimmed. +pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b>) -> String { if items.len() == 0 { return String::new(); } let mut tactic = formatting.tactic; - let h_width = formatting.h_width; - let v_width = formatting.v_width; - let sep_len = formatting.separator.len(); - // Conservatively overestimates because of the changing separator tactic. let sep_count = if formatting.trailing_separator != SeparatorTactic::Never { items.len() } else { items.len() - 1 }; + let sep_len = formatting.separator.len(); + let total_sep_len = (sep_len + 1) * sep_count; - // TODO count dead space too. - let total_width = items.iter().map(|&(ref s, _)| s.len()).fold(0, |a, l| a + l); + let total_width = calculate_width(items); // Check if we need to fallback from horizontal listing, if possible. if tactic == ListTactic::HorizontalVertical { - if (total_width + (sep_len + 1) * sep_count) > h_width { + if total_width + total_sep_len > formatting.h_width { tactic = ListTactic::Vertical; } else { tactic = ListTactic::Horizontal; @@ -73,16 +71,12 @@ pub fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b> // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. - let trailing_separator = match formatting.trailing_separator { - SeparatorTactic::Always => true, - SeparatorTactic::Vertical => tactic == ListTactic::Vertical, - SeparatorTactic::Never => false, - }; + let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); // Create a buffer for the result. // TODO could use a StringBuffer or rope for this let alloc_width = if tactic == ListTactic::Horizontal { - total_width + (sep_len + 1) * sep_count + total_width + total_sep_len } else { total_width + items.len() * (formatting.indent + 1) }; @@ -90,7 +84,7 @@ pub fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b> let mut line_len = 0; let indent_str = &make_indent(formatting.indent); - for (i, &(ref item, _)) in items.iter().enumerate() { + for (i, &(ref item, ref comment)) in items.iter().enumerate() { let first = i == 0; let separate = i != items.len() - 1 || trailing_separator; @@ -108,7 +102,7 @@ pub fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b> item_width += sep_len; } - if line_len > 0 && line_len + item_width > v_width { + if line_len > 0 && line_len + item_width > formatting.v_width { result.push('\n'); result.push_str(indent_str); line_len = 0; @@ -126,11 +120,42 @@ pub fn write_list<'b>(items:&[(String, String)], formatting: &ListFormatting<'b> result.push_str(item); + if tactic != ListTactic::Vertical && comment.len() > 0 { + result.push(' '); + result.push_str(comment); + } + if separate { result.push_str(formatting.separator); } - // TODO dead spans + + if tactic == ListTactic::Vertical && comment.len() > 0 { + result.push(' '); + result.push_str(comment); + } } result } + +fn needs_trailing_separator(separator_tactic: SeparatorTactic, list_tactic: ListTactic) -> bool { + match separator_tactic { + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => list_tactic == ListTactic::Vertical, + SeparatorTactic::Never => false, + } +} + +fn calculate_width(items:&[(String, String)]) -> usize { + let missed_width = items.iter().map(|&(_, ref s)| { + let text_len = s.trim().len(); + if text_len > 0 { + // We'll put a space before any comment. + text_len + 1 + } else { + text_len + } + }).fold(0, |a, l| a + l); + let item_width = items.iter().map(|&(ref s, _)| s.len()).fold(0, |a, l| a + l); + missed_width + item_width +} diff --git a/src/mod.rs b/src/mod.rs index 5c179dc910e..23fe92438c3 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -21,10 +21,12 @@ // TODO priorities // Fix fns and methods properly -// dead spans +// dead spans (comments) - in generics // // Smoke testing till we can use it // no newline at the end of doc.rs +// fmt_skip annotations +// take config options from a file #[macro_use] extern crate log; @@ -107,7 +109,10 @@ fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { visitor.changes } -// Formatting done on a char by char basis. +// Formatting done on a char by char or line by line basis. +// TODO warn on TODOs and FIXMEs without an issue number +// TODO warn on bad license +// TODO other stuff for parity with make tidy fn fmt_lines(changes: &mut ChangeSet) { // Iterate over the chars in the change set. for (f, text) in changes.text() { @@ -124,7 +129,7 @@ fn fmt_lines(changes: &mut ChangeSet) { } // Check for any line width errors we couldn't correct. if line_len > MAX_WIDTH { - // FIXME store the error rather than reporting immediately. + // TODO store the error rather than reporting immediately. println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", f, cur_line, MAX_WIDTH); } @@ -144,7 +149,7 @@ fn fmt_lines(changes: &mut ChangeSet) { } for &(l, _, _) in trims.iter() { - // FIXME store the error rather than reporting immediately. + // TODO store the error rather than reporting immediately. println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); } } -- cgit 1.4.1-3-g733a5 From bc7855d34749f8371847cda317fc8bc26afde681 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 16:22:48 +1200 Subject: Idempotent tests and comments in function decls --- src/changes.rs | 19 +++-- src/functions.rs | 214 +++++++++++++++++++++++++++++++++++++++++-------------- src/mod.rs | 100 +++++++++++++++++++++++--- src/visitor.rs | 33 ++++++++- 4 files changed, 295 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index dd8f220eb27..ce89c2625fc 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -115,15 +115,19 @@ impl<'a> ChangeSet<'a> { } } - pub fn write_all_files(&self, mode: WriteMode) -> Result<(), ::std::io::Error> { + pub fn write_all_files(&self, mode: WriteMode) -> Result<(HashMap), ::std::io::Error> { + let mut result = HashMap::new(); for filename in self.file_map.keys() { - try!(self.write_file(filename, mode)); + let one_result = try!(self.write_file(filename, mode)); + if let Some(r) = one_result { + result.insert(filename.clone(), r); + } } - Ok(()) + Ok(result) } - pub fn write_file(&self, filename: &str, mode: WriteMode) -> Result<(), ::std::io::Error> { + pub fn write_file(&self, filename: &str, mode: WriteMode) -> Result, ::std::io::Error> { let text = &self.file_map[filename]; match mode { @@ -147,13 +151,16 @@ impl<'a> ChangeSet<'a> { let mut file = try!(File::create(&filename)); try!(write!(file, "{}", text)); } - _ => { + WriteMode::Display => { println!("{}:\n", filename); println!("{}", text); } + WriteMode::Return(_) => { + return Ok(Some(text.to_string())); + } } - Ok(()) + Ok(None) } } diff --git a/src/functions.rs b/src/functions.rs index 5b08fa797bc..e7f80922e8a 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -14,12 +14,11 @@ use utils::make_indent; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use visitor::FmtVisitor; use syntax::{ast, abi}; -use syntax::codemap::{self, Span}; +use syntax::codemap::{self, Span, BytePos}; use syntax::print::pprust; use syntax::parse::token; impl<'a> FmtVisitor<'a> { - // TODO extract methods for args and generics pub fn rewrite_fn(&mut self, indent: usize, ident: ast::Ident, @@ -28,7 +27,9 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, unsafety: &ast::Unsafety, abi: &abi::Abi, - vis: ast::Visibility) + vis: ast::Visibility, + next_span: Span) // next_span is a nasty hack, its a loose upper + // bound on any comments after the where clause. -> String { // FIXME we'll lose any comments in between parts of the function decl, but anyone @@ -56,7 +57,10 @@ impl<'a> FmtVisitor<'a> { result.push_str(&token::get_ident(ident)); // Generics. - result.push_str(&self.rewrite_generics(generics, indent)); + let generics_indent = indent + result.len(); + result.push_str(&self.rewrite_generics(generics, + generics_indent, + span_for_return(&fd.output))); let ret_str = self.rewrite_return(&fd.output); @@ -74,7 +78,7 @@ impl<'a> FmtVisitor<'a> { result.push(')'); // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent)); + result.push_str(&self.rewrite_where_clause(where_clause, indent, next_span)); // Return type. if ret_str.len() > 0 { @@ -98,6 +102,8 @@ impl<'a> FmtVisitor<'a> { result.push_str(&ret_str); } + // TODO any comments here? + // Prepare for the function body by possibly adding a newline and indent. // FIXME we'll miss anything between the end of the signature and the start // of the body, but we need more spans from the compiler to solve this. @@ -157,40 +163,28 @@ impl<'a> FmtVisitor<'a> { // spans for the comment or parens, there is no chance of getting it right. // You also don't get to put a comment on self, unless it is explicit. if args.len() >= min_args { - let mut prev_end = args[min_args-1].ty.span.hi; - for arg in &args[min_args..] { - let cur_start = arg.pat.span.lo; - let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); - let mut snippet = snippet.trim(); - if snippet.starts_with(",") { - snippet = snippet[1..].trim(); - } else if snippet.ends_with(",") { - snippet = snippet[..snippet.len()-1].trim(); - } - arg_comments.push(snippet.to_string()); - prev_end = arg.ty.span.hi; - } - // Get the last commment. - // FIXME If you thought the crap with the commas was ugly, just wait. - // This is awful. We're going to look from the last arg span to the - // start of the return type span, then we drop everything after the - // first closing paren. Obviously, this will break if there is a - // closing paren in the comment. - // The fix is comments in the AST or a span for the closing paren. - let snippet = self.snippet(codemap::mk_sp(prev_end, ret_span.lo)); - let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find(")").unwrap()]; - let snippet = snippet.trim(); - arg_comments.push(snippet.to_string()); + arg_comments = self.make_comments_for_list(arg_comments, + args[min_args-1..].iter(), + ",", + ")", + |arg| arg.pat.span.lo, + |arg| arg.ty.span.hi, + ret_span.lo); } debug!("comments: {:?}", arg_comments); + // If there are // comments, keep them multi-line. + let mut list_tactic = ListTactic::HorizontalVertical; + if arg_comments.iter().any(|c| c.contains("//")) { + list_tactic = ListTactic::Vertical; + } + assert_eq!(arg_item_strs.len(), arg_comments.len()); let arg_strs: Vec<_> = arg_item_strs.into_iter().zip(arg_comments.into_iter()).collect(); let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, + tactic: list_tactic, separator: ",", trailing_separator: SeparatorTactic::Never, indent: arg_indent, @@ -201,6 +195,51 @@ impl<'a> FmtVisitor<'a> { write_list(&arg_strs, &fmt) } + // Gets comments in between items of a list. + fn make_comments_for_list(&self, + prefix: Vec, + mut it: I, + separator: &str, + terminator: &str, + get_lo: F1, + get_hi: F2, + next_span_start: BytePos) + -> Vec + where I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos + { + let mut result = prefix; + + let mut prev_end = get_hi(&it.next().unwrap()); + for item in it { + let cur_start = get_lo(&item); + let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); + let mut snippet = snippet.trim(); + if snippet.starts_with(separator) { + snippet = snippet[1..].trim(); + } else if snippet.ends_with(separator) { + snippet = snippet[..snippet.len()-1].trim(); + } + result.push(snippet.to_string()); + prev_end = get_hi(&item); + } + // Get the last commment. + // FIXME If you thought the crap with the commas was ugly, just wait. + // This is awful. We're going to look from the last item span to the + // start of the return type span, then we drop everything after the + // first closing paren. Obviously, this will break if there is a + // closing paren in the comment. + // The fix is comments in the AST or a span for the closing paren. + let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); + let snippet = snippet.trim(); + let snippet = &snippet[..snippet.find(terminator).unwrap()]; + let snippet = snippet.trim(); + result.push(snippet.to_string()); + + result + } + fn compute_budgets_for_args(&self, result: &mut String, indent: usize, @@ -260,37 +299,70 @@ impl<'a> FmtVisitor<'a> { } } - fn rewrite_generics(&self, generics: &ast::Generics, indent: usize) -> String { + fn rewrite_generics(&self, generics: &ast::Generics, indent: usize, ret_span: Span) -> String { // FIXME convert bounds to where clauses where they get too big or if // there is a where clause at all. let mut result = String::new(); let lifetimes: &[_] = &generics.lifetimes; let tys: &[_] = &generics.ty_params; - if lifetimes.len() + tys.len() > 0 { - let budget = MAX_WIDTH - indent - result.len() - 2; - // TODO might need to insert a newline if the generics are really long - result.push('<'); - - let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); - let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); - let generics_strs: Vec<_> = lt_strs.chain(ty_strs).map(|s| (s, String::new())).collect(); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + result.len() + 1, - h_width: budget, - v_width: budget, - }; - result.push_str(&write_list(&generics_strs, &fmt)); + if lifetimes.len() + tys.len() == 0 { + return result; + } - result.push('>'); + let budget = MAX_WIDTH - indent - 2; + // TODO might need to insert a newline if the generics are really long + result.push('<'); + + // Strings for the generics. + let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); + let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); + + // Extract comments between generics. + let lt_spans = lifetimes.iter().map(|l| { + let hi = if l.bounds.len() == 0 { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + codemap::mk_sp(l.lifetime.span.lo, hi) + }); + let ty_spans = tys.iter().map(span_for_ty_param); + let comments = self.make_comments_for_list(Vec::new(), + lt_spans.chain(ty_spans), + ",", + ">", + |sp| sp.lo, + |sp| sp.hi, + ret_span.lo); + + // If there are // comments, keep them multi-line. + let mut list_tactic = ListTactic::HorizontalVertical; + if comments.iter().any(|c| c.contains("//")) { + list_tactic = ListTactic::Vertical; } + let generics_strs: Vec<_> = lt_strs.chain(ty_strs).zip(comments.into_iter()).collect(); + let fmt = ListFormatting { + tactic: list_tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + 1, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&generics_strs, &fmt)); + + result.push('>'); + result } - fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, indent: usize) -> String { + fn rewrite_where_clause(&self, + where_clause: &ast::WhereClause, + indent: usize, + next_span: Span) + -> String + { let mut result = String::new(); if where_clause.predicates.len() == 0 { return result; @@ -300,6 +372,21 @@ impl<'a> FmtVisitor<'a> { result.push_str(&make_indent(indent + 4)); result.push_str("where "); + // TODO uncomment when spans are fixed + //println!("{:?} {:?}", where_clause.predicates.iter().map(|p| self.snippet(span_for_where_pred(p))).collect::>(), next_span.lo); + // let comments = self.make_comments_for_list(Vec::new(), + // where_clause.predicates.iter(), + // ",", + // "{", + // |pred| span_for_where_pred(pred).lo, + // |pred| span_for_where_pred(pred).hi, + // next_span.lo); + let comments = vec![String::new(); where_clause.predicates.len()]; + let where_strs: Vec<_> = where_clause.predicates.iter() + .map(|p| (self.rewrite_pred(p))) + .zip(comments.into_iter()) + .collect(); + let budget = IDEAL_WIDTH + LEEWAY - indent - 10; let fmt = ListFormatting { tactic: ListTactic::Vertical, @@ -309,7 +396,6 @@ impl<'a> FmtVisitor<'a> { h_width: budget, v_width: budget, }; - let where_strs: Vec<_> = where_clause.predicates.iter().map(|p| (self.rewrite_pred(p), String::new())).collect(); result.push_str(&write_list(&where_strs, &fmt)); result @@ -338,3 +424,27 @@ fn span_for_return(ret: &ast::FunctionRetTy) -> Span { ast::FunctionRetTy::Return(ref ty) => ty.span, } } + +fn span_for_ty_param(ty: &ast::TyParam) -> Span { + // Note that ty.span is the span for ty.ident, not the whole item. + let lo = ty.span.lo; + if let Some(ref def) = ty.default { + return codemap::mk_sp(lo, def.span.hi); + } + if ty.bounds.len() == 0 { + return ty.span; + } + let hi = match ty.bounds[ty.bounds.len() - 1] { + ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span.hi, + ast::TyParamBound::RegionTyParamBound(ref l) => l.span.hi, + }; + codemap::mk_sp(lo, hi) +} + +fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { + match *pred { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } +} diff --git a/src/mod.rs b/src/mod.rs index 23fe92438c3..fd508a56b2f 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -21,11 +21,10 @@ // TODO priorities // Fix fns and methods properly -// dead spans (comments) - in generics +// dead spans (comments) - in where clause (wait for fixed spans, test) // // Smoke testing till we can use it -// no newline at the end of doc.rs -// fmt_skip annotations +// ** no newline at the end of doc.rs // take config options from a file #[macro_use] @@ -48,6 +47,7 @@ use syntax::diagnostics; use syntax::visit; use std::path::PathBuf; +use std::collections::HashMap; use changes::ChangeSet; use visitor::FmtVisitor; @@ -69,14 +69,18 @@ const MIN_STRING: usize = 10; const TAB_SPACES: usize = 4; const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; +// When we get scoped annotations, we should have rustfmt::skip. +const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; -#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[derive(Copy, Clone)] pub enum WriteMode { Overwrite, // str is the extension of the new file NewFile(&'static str), // Write the output to stdout. Display, + // Return the result as a mapping from filenames to StringBuffers. + Return(&'static Fn(HashMap)), } #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -157,6 +161,7 @@ fn fmt_lines(changes: &mut ChangeSet) { struct RustFmtCalls { input_path: Option, + write_mode: WriteMode, } impl<'a> CompilerCalls<'a> for RustFmtCalls { @@ -202,19 +207,25 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { + let write_mode = self.write_mode; let mut control = driver::CompileController::basic(); control.after_parse.stop = Compilation::Stop; - control.after_parse.callback = box |state| { + control.after_parse.callback = box move |state| { let krate = state.krate.unwrap(); let codemap = state.session.codemap(); let mut changes = fmt_ast(krate, codemap); fmt_lines(&mut changes); // FIXME(#5) Should be user specified whether to show or replace. - let result = changes.write_all_files(WriteMode::Display); + let result = changes.write_all_files(write_mode); - if let Err(msg) = result { - println!("Error writing files: {}", msg); + match result { + Err(msg) => println!("Error writing files: {}", msg), + Ok(result) => { + if let WriteMode::Return(callback) = write_mode { + callback(result); + } + } } }; @@ -222,10 +233,14 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } } +fn run(args: Vec, write_mode: WriteMode) { + let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; + rustc_driver::run_compiler(&args, &mut call_ctxt); +} + fn main() { let args: Vec<_> = std::env::args().collect(); - let mut call_ctxt = RustFmtCalls { input_path: None }; - rustc_driver::run_compiler(&args, &mut call_ctxt); + run(args, WriteMode::Display); std::env::set_exit_status(0); // TODO unit tests @@ -262,3 +277,68 @@ fn main() { // the right kind. // Should also make sure comments have the right indent + +#[cfg(test)] +mod test { + use std::collections::HashMap; + use std::fs; + use std::io::Read; + use super::*; + use super::run; + + // For now, the only supported regression tests are idempotent tests - the input and + // output must match exactly. + // TODO would be good to check for error messages and fail on them, or at least report. + #[test] + fn idempotent_tests() { + println!("Idempotent tests:"); + unsafe { FAILURES = 0; } + + // Get all files in the tests/idem directory + let files = fs::read_dir("tests/idem").unwrap(); + // For each file, run rustfmt and collect the output + let mut count = 0; + for entry in files { + let path = entry.unwrap().path(); + let file_name = path.to_str().unwrap(); + println!("Testing '{}'...", file_name); + run(vec!["rustfmt".to_string(), file_name.to_string()], WriteMode::Return(HANDLE_RESULT)); + count += 1; + } + // And also dogfood ourselves! + println!("Testing 'src/mod.rs'..."); + run(vec!["rustfmt".to_string(), "src/mod.rs".to_string()], WriteMode::Return(HANDLE_RESULT)); + count += 1; + + // Display results + let fails = unsafe { FAILURES }; + println!("Ran {} idempotent tests; {} failures.", count, fails); + assert!(fails == 0, "{} idempotent tests failed", fails); + } + + // 'global' used by sys_tests and handle_result. + static mut FAILURES: i32 = 0; + // Ick, just needed to get a &'static to handle_result. + static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; + + // Compare output to input. + fn handle_result(result: HashMap) { + let mut fails = 0; + + for file_name in result.keys() { + let mut f = fs::File::open(file_name).unwrap(); + let mut text = String::new(); + f.read_to_string(&mut text).unwrap(); + if result[file_name] != text { + fails += 1; + println!("Mismatch in {}.", file_name); + } + } + + if fails > 0 { + unsafe { + FAILURES += 1; + } + } + } +} diff --git a/src/visitor.rs b/src/visitor.rs index 7e8a885c657..e76d87afe9d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -12,7 +12,7 @@ use syntax::ast; use syntax::codemap::{CodeMap, Span, BytePos}; use syntax::visit; -use {MAX_WIDTH, TAB_SPACES}; +use {MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION}; use changes::ChangeSet; pub struct FmtVisitor<'a> { @@ -86,7 +86,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { generics, unsafety, abi, - vis); + vis, + b.span); self.changes.push_str_span(s, &new_fn); } visit::FkMethod(ident, ref sig, vis) => { @@ -97,7 +98,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &sig.generics, &sig.unsafety, &sig.abi, - vis.unwrap_or(ast::Visibility::Inherited)); + vis.unwrap_or(ast::Visibility::Inherited), + b.span); self.changes.push_str_span(s, &new_fn); } visit::FkFnBlock(..) => {} @@ -108,6 +110,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_item(&mut self, item: &'v ast::Item) { + if item.attrs.iter().any(|a| is_skip(&a.node.value)) { + return; + } + match item.node { ast::Item_::ItemUse(ref vp) => { match vp.node { @@ -135,6 +141,20 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } + fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { + if ti.attrs.iter().any(|a| is_skip(&a.node.value)) { + return; + } + visit::walk_trait_item(self, ti) + } + + fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { + if ii.attrs.iter().any(|a| is_skip(&a.node.value)) { + return; + } + visit::walk_impl_item(self, ii) + } + fn visit_mac(&mut self, mac: &'v ast::Mac) { visit::walk_mac(self, mac) } @@ -171,3 +191,10 @@ impl<'a> FmtVisitor<'a> { } } } + +fn is_skip(meta_item: &ast::MetaItem) -> bool { + match meta_item.node { + ast::MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, + _ => false, + } +} -- cgit 1.4.1-3-g733a5 From 2819738ff159eab7cb3a12988f0cdcc4f771e73a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 16:30:19 +1200 Subject: Fix formatting in changes.rs --- src/changes.rs | 15 ++++++++++----- src/mod.rs | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index ce89c2625fc..741c79a396b 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -10,12 +10,12 @@ // TODO -// print to files +// print to files // tests use strings::string_buffer::StringBuffer; use std::collections::HashMap; -use syntax::codemap::{CodeMap, Span,BytePos}; +use syntax::codemap::{CodeMap, Span, BytePos}; use std::fmt; use std::fs::File; use std::io::Write; @@ -115,7 +115,9 @@ impl<'a> ChangeSet<'a> { } } - pub fn write_all_files(&self, mode: WriteMode) -> Result<(HashMap), ::std::io::Error> { + pub fn write_all_files(&self, + mode: WriteMode) + -> Result<(HashMap), ::std::io::Error> { let mut result = HashMap::new(); for filename in self.file_map.keys() { let one_result = try!(self.write_file(filename, mode)); @@ -127,7 +129,10 @@ impl<'a> ChangeSet<'a> { Ok(result) } - pub fn write_file(&self, filename: &str, mode: WriteMode) -> Result, ::std::io::Error> { + pub fn write_file(&self, + filename: &str, + mode: WriteMode) + -> Result, ::std::io::Error> { let text = &self.file_map[filename]; match mode { @@ -194,5 +199,5 @@ impl<'a> fmt::Display for ChangeSet<'a> { try!(write!(fmt, "{}\n\n", r)); } Ok(()) - } + } } diff --git a/src/mod.rs b/src/mod.rs index fd508a56b2f..44af8b08baf 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -240,7 +240,8 @@ fn run(args: Vec, write_mode: WriteMode) { fn main() { let args: Vec<_> = std::env::args().collect(); - run(args, WriteMode::Display); + //run(args, WriteMode::Display); + run(args, WriteMode::NewFile("new")); std::env::set_exit_status(0); // TODO unit tests -- cgit 1.4.1-3-g733a5 From 0c5f5082dcaf19944abc17d8b2275a6dc35a0e9b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 17:04:07 +1200 Subject: terminating newline bug --- src/changes.rs | 9 +++++++++ src/functions.rs | 4 ++-- src/lists.rs | 1 + src/mod.rs | 4 +++- 4 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 741c79a396b..8119dc540ac 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -60,6 +60,8 @@ impl<'a> ChangeSet<'a> { return Vec::new(); } + // idx is the index into file_spans which indicates the current file, we + // with the file start denotes. let mut idx = match self.file_spans.binary_search(&(start.0, ::std::u32::MAX)) { Ok(i) => i, Err(0) => 0, @@ -115,6 +117,13 @@ impl<'a> ChangeSet<'a> { } } + // Append a newline to the end of each file. + pub fn append_newlines(&mut self) { + for (_, s) in self.file_map.iter_mut() { + s.push_str("\n"); + } + } + pub fn write_all_files(&self, mode: WriteMode) -> Result<(HashMap), ::std::io::Error> { diff --git a/src/functions.rs b/src/functions.rs index e7f80922e8a..492754a39aa 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -372,8 +372,9 @@ impl<'a> FmtVisitor<'a> { result.push_str(&make_indent(indent + 4)); result.push_str("where "); + let comments = vec![String::new(); where_clause.predicates.len()]; // TODO uncomment when spans are fixed - //println!("{:?} {:?}", where_clause.predicates.iter().map(|p| self.snippet(span_for_where_pred(p))).collect::>(), next_span.lo); + // println!("{:?} {:?}", where_clause.predicates.iter().map(|p| self.snippet(span_for_where_pred(p))).collect::>(), next_span.lo); // let comments = self.make_comments_for_list(Vec::new(), // where_clause.predicates.iter(), // ",", @@ -381,7 +382,6 @@ impl<'a> FmtVisitor<'a> { // |pred| span_for_where_pred(pred).lo, // |pred| span_for_where_pred(pred).hi, // next_span.lo); - let comments = vec![String::new(); where_clause.predicates.len()]; let where_strs: Vec<_> = where_clause.predicates.iter() .map(|p| (self.rewrite_pred(p))) .zip(comments.into_iter()) diff --git a/src/lists.rs b/src/lists.rs index 01bad45b6af..4f443475afa 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -29,6 +29,7 @@ pub enum SeparatorTactic { Vertical, } +// TODO having some helpful ctors for ListFormatting would be nice. pub struct ListFormatting<'a> { pub tactic: ListTactic, pub separator: &'a str, diff --git a/src/mod.rs b/src/mod.rs index 44af8b08baf..3720eaad192 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -24,7 +24,6 @@ // dead spans (comments) - in where clause (wait for fixed spans, test) // // Smoke testing till we can use it -// ** no newline at the end of doc.rs // take config options from a file #[macro_use] @@ -214,6 +213,9 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { let krate = state.krate.unwrap(); let codemap = state.session.codemap(); let mut changes = fmt_ast(krate, codemap); + // For some reason, the codemap does not include terminating newlines + // so we must add one on for each file. This is sad. + changes.append_newlines(); fmt_lines(&mut changes); // FIXME(#5) Should be user specified whether to show or replace. -- cgit 1.4.1-3-g733a5 From 28d90bc439f86ddf8a97133982986296271f4a35 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 18:02:55 +1200 Subject: trailing newline hell fixed --- src/changes.rs | 4 ++++ src/lists.rs | 4 ++-- src/mod.rs | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 8119dc540ac..2b42c164690 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -99,6 +99,10 @@ impl<'a> ChangeSet<'a> { self.push_str(&file_name, text) } + pub fn get_mut(&mut self, file_name: &str) -> &mut StringBuffer { + self.file_map.get_mut(file_name).unwrap() + } + pub fn cur_offset(&mut self, filename: &str) -> usize { self.file_map[&*filename].cur_offset() } diff --git a/src/lists.rs b/src/lists.rs index 4f443475afa..5a892e5713b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -62,7 +62,7 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b let total_width = calculate_width(items); // Check if we need to fallback from horizontal listing, if possible. - if tactic == ListTactic::HorizontalVertical { + if tactic == ListTactic::HorizontalVertical { if total_width + total_sep_len > formatting.h_width { tactic = ListTactic::Vertical; } else { @@ -120,7 +120,7 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b } result.push_str(item); - + if tactic != ListTactic::Vertical && comment.len() > 0 { result.push(' '); result.push_str(comment); diff --git a/src/mod.rs b/src/mod.rs index 3720eaad192..21db1e902bb 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -117,12 +117,15 @@ fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { // TODO warn on bad license // TODO other stuff for parity with make tidy fn fmt_lines(changes: &mut ChangeSet) { + let mut truncate_todo = Vec::new(); + // Iterate over the chars in the change set. for (f, text) in changes.text() { let mut trims = vec![]; let mut last_wspace: Option = None; let mut line_len = 0; let mut cur_line = 1; + let mut newline_count = 0; for (c, b) in text.chars() { if c == '\n' { // TOOD test for \r too // Check for (and record) trailing whitespace. @@ -138,8 +141,10 @@ fn fmt_lines(changes: &mut ChangeSet) { } line_len = 0; cur_line += 1; + newline_count += 1; last_wspace = None; } else { + newline_count = 0; line_len += 1; if c.is_whitespace() { if last_wspace.is_none() { @@ -151,11 +156,24 @@ fn fmt_lines(changes: &mut ChangeSet) { } } + if newline_count > 1 { + truncate_todo.push((f, text.len - newline_count + 1)) + } + for &(l, _, _) in trims.iter() { // TODO store the error rather than reporting immediately. println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); } } + + for (f, l) in truncate_todo { + // This unsafe block and the ridiculous dance with the cast is because + // the borrow checker thinks the first borrow of changes lasts for the + // whole function. + unsafe { + (*(changes as *const ChangeSet as *mut ChangeSet)).get_mut(f).truncate(l); + } + } } struct RustFmtCalls { -- cgit 1.4.1-3-g733a5 From 4faaa4dab2d77ac3bc75b927ae3307665e5aff3d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 18:10:43 +1200 Subject: minor reformatting --- src/functions.rs | 6 +++--- src/mod.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 492754a39aa..32ad65befe7 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -195,7 +195,7 @@ impl<'a> FmtVisitor<'a> { write_list(&arg_strs, &fmt) } - // Gets comments in between items of a list. + // Gets comments in between items of a list. fn make_comments_for_list(&self, prefix: Vec, mut it: I, @@ -228,7 +228,7 @@ impl<'a> FmtVisitor<'a> { // FIXME If you thought the crap with the commas was ugly, just wait. // This is awful. We're going to look from the last item span to the // start of the return type span, then we drop everything after the - // first closing paren. Obviously, this will break if there is a + // first closing paren. Obviously, this will break if there is a // closing paren in the comment. // The fix is comments in the AST or a span for the closing paren. let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); @@ -406,7 +406,7 @@ impl<'a> FmtVisitor<'a> { ast::FunctionRetTy::DefaultReturn(_) => String::new(), ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), - } + } } // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly diff --git a/src/mod.rs b/src/mod.rs index 21db1e902bb..71ce9120fe1 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -255,13 +255,13 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { fn run(args: Vec, write_mode: WriteMode) { let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; - rustc_driver::run_compiler(&args, &mut call_ctxt); + rustc_driver::run_compiler(&args, &mut call_ctxt); } fn main() { let args: Vec<_> = std::env::args().collect(); - //run(args, WriteMode::Display); - run(args, WriteMode::NewFile("new")); + run(args, WriteMode::Display); + //run(args, WriteMode::NewFile("new")); std::env::set_exit_status(0); // TODO unit tests -- cgit 1.4.1-3-g733a5 From daff43f7613cbcce60dbabf7dd1a32f0d88858eb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 18:30:12 +1200 Subject: Arg/line length bug --- src/functions.rs | 11 ++++++++--- src/lists.rs | 2 ++ src/mod.rs | 1 + tests/idem/long-fn-1.rs | 13 +++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/idem/long-fn-1.rs (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 32ad65befe7..777120f5b97 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -68,6 +68,9 @@ impl<'a> FmtVisitor<'a> { let (one_line_budget, multi_line_budget, arg_indent) = self.compute_budgets_for_args(&mut result, indent, ret_str.len(), newline_brace); + debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", + one_line_budget, multi_line_budget, arg_indent); + result.push('('); result.push_str(&self.rewrite_args(&fd.inputs, explicit_self, @@ -252,8 +255,8 @@ impl<'a> FmtVisitor<'a> { // Try keeping everything on the same line if !result.contains("\n") { // 3 = `() `, space is before ret_string - let mut used_space = indent + result.len() + 3 + ret_str_len; - if newline_brace { + let mut used_space = indent + result.len() + ret_str_len + 3; + if !newline_brace { used_space += 2; } let one_line_budget = if used_space > MAX_WIDTH { @@ -262,11 +265,13 @@ impl<'a> FmtVisitor<'a> { MAX_WIDTH - used_space }; + // 2 = `()` let used_space = indent + result.len() + 2; let max_space = IDEAL_WIDTH + LEEWAY; + debug!("compute_budgets_for_args: used_space: {}, max_space: {}", + used_space, max_space); if used_space < max_space { budgets = Some((one_line_budget, - // 2 = `()` max_space - used_space, indent + result.len() + 1)); } diff --git a/src/lists.rs b/src/lists.rs index 5a892e5713b..d5f058a301b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -63,6 +63,8 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b // Check if we need to fallback from horizontal listing, if possible. if tactic == ListTactic::HorizontalVertical { + debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", + total_width, total_sep_len, formatting.h_width); if total_width + total_sep_len > formatting.h_width { tactic = ListTactic::Vertical; } else { diff --git a/src/mod.rs b/src/mod.rs index 71ce9120fe1..c5f5150b3bb 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -157,6 +157,7 @@ fn fmt_lines(changes: &mut ChangeSet) { } if newline_count > 1 { + debug!("track truncate: {} {} {}", f, text.len, newline_count); truncate_todo.push((f, text.len - newline_count + 1)) } diff --git a/tests/idem/long-fn-1.rs b/tests/idem/long-fn-1.rs new file mode 100644 index 00000000000..0e299aaecc1 --- /dev/null +++ b/tests/idem/long-fn-1.rs @@ -0,0 +1,13 @@ +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input(&mut self, + input: Input, + input_path: Option) + -> (Input, Option) { + } + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { + } +} -- cgit 1.4.1-3-g733a5 From c00970f5e946a9c451360455e079a24ecb5eb786 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Apr 2015 18:43:46 +1200 Subject: Indenting for modules rustfmt now bootstraps! --- src/visitor.rs | 5 +++++ tests/idem/mod-1.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/idem/mod-1.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index e76d87afe9d..2a6dbc876f8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -135,6 +135,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { visit::walk_item(self, item); self.block_indent -= TAB_SPACES; } + ast::Item_::ItemMod(_) => { + self.block_indent += TAB_SPACES; + visit::walk_item(self, item); + self.block_indent -= TAB_SPACES; + } _ => { visit::walk_item(self, item); } diff --git a/tests/idem/mod-1.rs b/tests/idem/mod-1.rs new file mode 100644 index 00000000000..c6d5f355f61 --- /dev/null +++ b/tests/idem/mod-1.rs @@ -0,0 +1,15 @@ +// Deeply indented modules. + +mod foo { + mod bar { + mod baz { + fn foo() { + bar() + } + } + } + + mod qux { + + } +} -- cgit 1.4.1-3-g733a5 From a84287c6b06026ecc1eced2ef4d0351c11b130f0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Apr 2015 20:56:01 +1200 Subject: Comments in function decls and annotations/doc comments --- src/functions.rs | 47 +++++++++++++++++++++++++++++++---------------- src/mod.rs | 8 ++++++-- src/visitor.rs | 25 ++++++++++++++++++++----- tests/idem/attrib.rs | 22 ++++++++++++++++++++++ tests/idem/comments-fn.rs | 19 +++++++++++++++++++ 5 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 tests/idem/attrib.rs create mode 100644 tests/idem/comments-fn.rs (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 777120f5b97..0afcb66f64a 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -80,9 +80,6 @@ impl<'a> FmtVisitor<'a> { span_for_return(&fd.output))); result.push(')'); - // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent, next_span)); - // Return type. if ret_str.len() > 0 { // If we've already gone multi-line, or the return type would push @@ -91,10 +88,13 @@ impl<'a> FmtVisitor<'a> { result.len() + indent + ret_str.len() > MAX_WIDTH { let indent = match FN_RETURN_INDENT { ReturnIndent::WithWhereClause => indent + 4, + ReturnIndent::WithWhereClauseOrArgs if where_clause.predicates.len() > 0 => { + indent + 4 + } // TODO we might want to check that using the arg indent doesn't // blow our budget, and if it does, then fallback to the where // clause indent. - ReturnIndent::WithArgs => arg_indent, + _ => arg_indent, }; result.push('\n'); @@ -103,9 +103,27 @@ impl<'a> FmtVisitor<'a> { result.push(' '); } result.push_str(&ret_str); + + // Comment between return type and the end of the decl. + let snippet_lo = fd.output.span().hi; + if where_clause.predicates.len() == 0 { + let snippet_hi = next_span.lo; + let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); + let snippet = snippet.trim(); + if snippet.len() > 0 { + println!("found comment {}", snippet); + result.push(' '); + result.push_str(snippet); + } + } else { + // FIXME it would be nice to catch comments between the return type + // and the where clause, but we don't have a span for the where + // clause. + } } - // TODO any comments here? + // Where clause. + result.push_str(&self.rewrite_where_clause(where_clause, indent, next_span)); // Prepare for the function body by possibly adding a newline and indent. // FIXME we'll miss anything between the end of the signature and the start @@ -236,7 +254,7 @@ impl<'a> FmtVisitor<'a> { // The fix is comments in the AST or a span for the closing paren. let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find(terminator).unwrap()]; + let snippet = &snippet[..snippet.find(terminator).unwrap_or(snippet.len())]; let snippet = snippet.trim(); result.push(snippet.to_string()); @@ -377,16 +395,13 @@ impl<'a> FmtVisitor<'a> { result.push_str(&make_indent(indent + 4)); result.push_str("where "); - let comments = vec![String::new(); where_clause.predicates.len()]; - // TODO uncomment when spans are fixed - // println!("{:?} {:?}", where_clause.predicates.iter().map(|p| self.snippet(span_for_where_pred(p))).collect::>(), next_span.lo); - // let comments = self.make_comments_for_list(Vec::new(), - // where_clause.predicates.iter(), - // ",", - // "{", - // |pred| span_for_where_pred(pred).lo, - // |pred| span_for_where_pred(pred).hi, - // next_span.lo); + let comments = self.make_comments_for_list(Vec::new(), + where_clause.predicates.iter(), + ",", + "{", + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + next_span.lo); let where_strs: Vec<_> = where_clause.predicates.iter() .map(|p| (self.rewrite_pred(p))) .zip(comments.into_iter()) diff --git a/src/mod.rs b/src/mod.rs index c5f5150b3bb..537752d17a3 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -20,8 +20,9 @@ // TODO for lint violations of names, emit a refactor script // TODO priorities +// annotations/doc comments // Fix fns and methods properly -// dead spans (comments) - in where clause (wait for fixed spans, test) +// dead spans (comments) - in where clause - test // // Smoke testing till we can use it // take config options from a file @@ -67,7 +68,7 @@ const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; const TAB_SPACES: usize = 4; const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; -const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; +const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithWhereClauseOrArgs; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; @@ -98,6 +99,8 @@ enum ReturnIndent { WithArgs, // Aligned with the where clause WithWhereClause, + // Aligned with the where clause if there is one, otherwise the args. + WithWhereClauseOrArgs, } // Formatting which depends on the AST. @@ -354,6 +357,7 @@ mod test { if result[file_name] != text { fails += 1; println!("Mismatch in {}.", file_name); + println!("{}", result[file_name]); } } diff --git a/src/visitor.rs b/src/visitor.rs index 2a6dbc876f8..df974b7e8fa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -75,8 +75,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.format_missing(s.lo); self.last_pos = s.lo; - // TODO need to check against expected indent - let indent = self.codemap.lookup_char_pos(s.lo).col.0; + let indent = self.block_indent; match fk { visit::FkItemFn(ident, ref generics, ref unsafety, ref abi, vis) => { let new_fn = self.rewrite_fn(indent, @@ -110,7 +109,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_item(&mut self, item: &'v ast::Item) { - if item.attrs.iter().any(|a| is_skip(&a.node.value)) { + if self.visit_attrs(&item.attrs) { return; } @@ -147,14 +146,14 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { - if ti.attrs.iter().any(|a| is_skip(&a.node.value)) { + if self.visit_attrs(&ti.attrs) { return; } visit::walk_trait_item(self, ti) } fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { - if ii.attrs.iter().any(|a| is_skip(&a.node.value)) { + if self.visit_attrs(&ii.attrs) { return; } visit::walk_impl_item(self, ii) @@ -195,6 +194,22 @@ impl<'a> FmtVisitor<'a> { } } } + + // Returns true if we should skip the following item. + fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { + for a in attrs { + self.format_missing_with_indent(a.span.lo); + if is_skip(&a.node.value) { + return true; + } + + let attr_str = self.snippet(a.span); + self.changes.push_str_span(a.span, &attr_str); + self.last_pos = a.span.hi; + } + + false + } } fn is_skip(meta_item: &ast::MetaItem) -> bool { diff --git a/tests/idem/attrib.rs b/tests/idem/attrib.rs new file mode 100644 index 00000000000..b66be08c728 --- /dev/null +++ b/tests/idem/attrib.rs @@ -0,0 +1,22 @@ +// Test attributes and doc comments are preserved. + +/// Blah blah blah. +impl Bar { + /// Blah blah blooo. + #[an_attribute] + fn foo(&mut self) -> isize {} + + /// Blah blah bing. + pub fn f2(self) { + (foo, bar) + } + + #[another_attribute] + fn f3(self) -> Dog { + } +} + +/// Blah +fn main() { + println!("Hello world!"); +} diff --git a/tests/idem/comments-fn.rs b/tests/idem/comments-fn.rs new file mode 100644 index 00000000000..ec1b87cde0d --- /dev/null +++ b/tests/idem/comments-fn.rs @@ -0,0 +1,19 @@ +// Test comments on functions are preserved. + +// Comment on foo. +fn foo(a: aaaaaaaaaaaaa, // A comment + b: bbbbbbbbbbbbb, /* a second comment */ + c: ccccccccccccc, + d: ddddddddddddd, + e: eeeeeeeeeeeee /* comment before paren*/) + -> bar + where F: Foo, // COmment after where clause + G: Goo /* final comment */ +{ + +} + +fn bar() {} + +fn baz() -> Baz /* Comment after return type */ { +} -- cgit 1.4.1-3-g733a5 From 9070a055def9df90f7e50531dab176c30804011a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Apr 2015 21:24:56 +1200 Subject: Comments after return --- src/functions.rs | 1 - src/imports.rs | 25 ++++++++++++++++++------- src/mod.rs | 4 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 0afcb66f64a..982bfe87500 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -111,7 +111,6 @@ impl<'a> FmtVisitor<'a> { let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); let snippet = snippet.trim(); if snippet.len() > 0 { - println!("found comment {}", snippet); result.push(' '); result.push_str(snippet); } diff --git a/src/imports.rs b/src/imports.rs index 7e64308eafc..e7557242e1b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -16,7 +16,7 @@ use syntax::codemap::Span; use syntax::parse::token; use syntax::print::pprust; -use IDEAL_WIDTH; +use {IDEAL_WIDTH, MAX_WIDTH}; // TODO change import lists with one item to a single import // remove empty lists (if they're even possible) @@ -25,9 +25,9 @@ use IDEAL_WIDTH; impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. pub fn rewrite_use_list(&mut self, - path: &ast::Path, - path_list: &[ast::PathListItem], - vp_span: Span) -> String { + path: &ast::Path, + path_list: &[ast::PathListItem], + vp_span: Span) -> String { // FIXME remove unused imports // FIXME check indentation @@ -37,14 +37,25 @@ impl<'a> FmtVisitor<'a> { // 3 = :: + { let indent = l_loc.col.0 + path_str.len() + 3; + // 2 = } + ; + let used_width = indent + path_str.len() + 2; + let budget = if used_width >= IDEAL_WIDTH { + if used_width < MAX_WIDTH { + MAX_WIDTH - used_width + } else { + // Give up + return String::new(); + } + } else { + IDEAL_WIDTH - used_width + }; let fmt = ListFormatting { tactic: ListTactic::Mixed, separator: ",", trailing_separator: SeparatorTactic::Never, indent: indent, - // 2 = } + ; - h_width: IDEAL_WIDTH - (indent + path_str.len() + 2), - v_width: IDEAL_WIDTH - (indent + path_str.len() + 2), + h_width: budget, + v_width: budget, }; // TODO handle any comments inbetween items. diff --git a/src/mod.rs b/src/mod.rs index 537752d17a3..18ddb64e47f 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -264,8 +264,8 @@ fn run(args: Vec, write_mode: WriteMode) { fn main() { let args: Vec<_> = std::env::args().collect(); - run(args, WriteMode::Display); - //run(args, WriteMode::NewFile("new")); + //run(args, WriteMode::Display); + run(args, WriteMode::NewFile("new")); std::env::set_exit_status(0); // TODO unit tests -- cgit 1.4.1-3-g733a5 From cdfda8801e871744a384eba8289f1114fd8b6d66 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Apr 2015 21:36:31 +1200 Subject: Absolute paths --- src/imports.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index e7557242e1b..1532050522a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -28,17 +28,20 @@ impl<'a> FmtVisitor<'a> { path: &ast::Path, path_list: &[ast::PathListItem], vp_span: Span) -> String { - // FIXME remove unused imports - // FIXME check indentation let l_loc = self.codemap.lookup_char_pos(vp_span.lo); let path_str = pprust::path_to_string(&path); - // 3 = :: + { - let indent = l_loc.col.0 + path_str.len() + 3; + + // 1 = { + let mut indent = l_loc.col.0 + path_str.len() + 1; + if path_str.len() > 0 { + // 2 = :: + indent += 2; + } // 2 = } + ; - let used_width = indent + path_str.len() + 2; + let used_width = indent + 2; let budget = if used_width >= IDEAL_WIDTH { if used_width < MAX_WIDTH { MAX_WIDTH - used_width @@ -82,6 +85,10 @@ impl<'a> FmtVisitor<'a> { } })).collect(); - format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) + if path_str.len() == 0 { + format!("use {{{}}};", write_list(&items, &fmt)) + } else { + format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) + } } } -- cgit 1.4.1-3-g733a5 From 81b8eb7993897345120e112561a355dc51a6802f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Apr 2015 21:57:16 +1200 Subject: Comments on their own lines between args --- src/functions.rs | 5 +++-- src/lists.rs | 8 ++++++-- tests/idem/comments-fn.rs | 3 +++ 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 982bfe87500..039e7efd085 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -236,10 +236,11 @@ impl<'a> FmtVisitor<'a> { let cur_start = get_lo(&item); let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); let mut snippet = snippet.trim(); + let white_space: &[_] = &[' ', '\t']; if snippet.starts_with(separator) { - snippet = snippet[1..].trim(); + snippet = snippet[separator.len()..].trim_matches(white_space); } else if snippet.ends_with(separator) { - snippet = snippet[..snippet.len()-1].trim(); + snippet = snippet[..snippet.len()-separator.len()].trim_matches(white_space); } result.push(snippet.to_string()); prev_end = get_hi(&item); diff --git a/src/lists.rs b/src/lists.rs index d5f058a301b..47b6491544d 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -124,7 +124,9 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b result.push_str(item); if tactic != ListTactic::Vertical && comment.len() > 0 { - result.push(' '); + if !comment.starts_with('\n') { + result.push(' '); + } result.push_str(comment); } @@ -133,7 +135,9 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b } if tactic == ListTactic::Vertical && comment.len() > 0 { - result.push(' '); + if !comment.starts_with('\n') { + result.push(' '); + } result.push_str(comment); } } diff --git a/tests/idem/comments-fn.rs b/tests/idem/comments-fn.rs index ec1b87cde0d..f9f7bb27c07 100644 --- a/tests/idem/comments-fn.rs +++ b/tests/idem/comments-fn.rs @@ -4,7 +4,10 @@ fn foo(a: aaaaaaaaaaaaa, // A comment b: bbbbbbbbbbbbb, /* a second comment */ c: ccccccccccccc, + // Newline comment d: ddddddddddddd, + // A multi line comment + // between args. e: eeeeeeeeeeeee /* comment before paren*/) -> bar where F: Foo, // COmment after where clause -- cgit 1.4.1-3-g733a5 From 40be79304e3889cf69f7d80789ca0c5fde1faf73 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Apr 2015 22:19:25 +1200 Subject: Tweak rules around attributes for modules --- src/mod.rs | 2 +- src/visitor.rs | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 18ddb64e47f..8d360ab3376 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -265,7 +265,7 @@ fn run(args: Vec, write_mode: WriteMode) { fn main() { let args: Vec<_> = std::env::args().collect(); //run(args, WriteMode::Display); - run(args, WriteMode::NewFile("new")); + run(args, WriteMode::Overwrite); std::env::set_exit_status(0); // TODO unit tests diff --git a/src/visitor.rs b/src/visitor.rs index df974b7e8fa..8825a094792 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -109,8 +109,17 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_item(&mut self, item: &'v ast::Item) { - if self.visit_attrs(&item.attrs) { - return; + // Don't look at attributes for modules. + // We want to avoid looking at attributes in another file, which the AST + // doesn't distinguish. FIXME This is overly conservative and means we miss + // attributes on inline modules. + match item.node { + ast::Item_::ItemMod(_) => {} + _ => { + if self.visit_attrs(&item.attrs) { + return; + } + } } match item.node { -- cgit 1.4.1-3-g733a5 From decafbbaea1f2131f2c414dfb21da594b43464cd Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 29 Apr 2015 09:53:33 +1200 Subject: Fix trailing commas in where clauses --- src/functions.rs | 6 ++---- src/mod.rs | 4 +--- tests/idem/attrib.rs | 7 +++++++ tests/idem/comments-fn.rs | 2 +- tests/idem/fn.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 tests/idem/fn.rs (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 039e7efd085..a753f38d9f7 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -88,9 +88,6 @@ impl<'a> FmtVisitor<'a> { result.len() + indent + ret_str.len() > MAX_WIDTH { let indent = match FN_RETURN_INDENT { ReturnIndent::WithWhereClause => indent + 4, - ReturnIndent::WithWhereClauseOrArgs if where_clause.predicates.len() > 0 => { - indent + 4 - } // TODO we might want to check that using the arg indent doesn't // blow our budget, and if it does, then fallback to the where // clause indent. @@ -254,7 +251,8 @@ impl<'a> FmtVisitor<'a> { // The fix is comments in the AST or a span for the closing paren. let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find(terminator).unwrap_or(snippet.len())]; + let snippet = &snippet[..snippet.find(terminator) + .unwrap_or(snippet.find(separator).unwrap_or(snippet.len()))]; let snippet = snippet.trim(); result.push(snippet.to_string()); diff --git a/src/mod.rs b/src/mod.rs index 8d360ab3376..7b18664b672 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -68,7 +68,7 @@ const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; const TAB_SPACES: usize = 4; const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; -const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithWhereClauseOrArgs; +const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; @@ -99,8 +99,6 @@ enum ReturnIndent { WithArgs, // Aligned with the where clause WithWhereClause, - // Aligned with the where clause if there is one, otherwise the args. - WithWhereClauseOrArgs, } // Formatting which depends on the AST. diff --git a/tests/idem/attrib.rs b/tests/idem/attrib.rs index b66be08c728..aa2b1a69df0 100644 --- a/tests/idem/attrib.rs +++ b/tests/idem/attrib.rs @@ -1,5 +1,12 @@ // Test attributes and doc comments are preserved. +extern crate Foo; +#[Attr1] +extern crate Bar; +#[Attr2] +#[Attr2] +extern crate Baz; + /// Blah blah blah. impl Bar { /// Blah blah blooo. diff --git a/tests/idem/comments-fn.rs b/tests/idem/comments-fn.rs index f9f7bb27c07..12c0e72193f 100644 --- a/tests/idem/comments-fn.rs +++ b/tests/idem/comments-fn.rs @@ -9,7 +9,7 @@ fn foo(a: aaaaaaaaaaaaa, // A comment // A multi line comment // between args. e: eeeeeeeeeeeee /* comment before paren*/) - -> bar + -> bar where F: Foo, // COmment after where clause G: Goo /* final comment */ { diff --git a/tests/idem/fn.rs b/tests/idem/fn.rs new file mode 100644 index 00000000000..e5013a61cee --- /dev/null +++ b/tests/idem/fn.rs @@ -0,0 +1,42 @@ +// Tests different fns + +fn foo(a: AAAA, b: BBB, c: CCC) -> RetType { + +} + +fn foo(a: AAAA, b: BBB, c: CCC) -> RetType + where T: Blah +{ + +} + +fn foo(a: AAA) + where T: Blah +{ + +} + +fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType + where T: Blah +{ + +} + + +fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType + where T: Blah, + U: dsfasdfasdfasd +{ + +} + +impl Foo { + fn with_no_errors(&mut self, f: F) -> T + where F: FnOnce(&mut Resolver) -> T + { + } +} -- cgit 1.4.1-3-g733a5 From 2e485ea086990ed6a13c4f3116006635a6266ca1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 29 Apr 2015 15:00:58 +1200 Subject: Better attribute handling --- src/missed_spans.rs | 2 + src/mod.rs | 4 +- src/visitor.rs | 77 ++++++++++++++++++++++++++++++++++----- tests/idem/attrib-extern-crate.rs | 17 +++++++++ tests/idem/attrib.rs | 15 +------- tests/idem/comments-fn.rs | 3 +- tests/idem/imports.rs | 8 ++++ 7 files changed, 101 insertions(+), 25 deletions(-) create mode 100644 tests/idem/attrib-extern-crate.rs create mode 100644 tests/idem/imports.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7b352dc8a04..c861d631be8 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -44,6 +44,8 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(end)); if start == end { + let file_name = &self.codemap.lookup_char_pos(start).file.name; + process_last_snippet(self, "", file_name, ""); return; } diff --git a/src/mod.rs b/src/mod.rs index 7b18664b672..076a826035b 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -262,8 +262,8 @@ fn run(args: Vec, write_mode: WriteMode) { fn main() { let args: Vec<_> = std::env::args().collect(); - //run(args, WriteMode::Display); - run(args, WriteMode::Overwrite); + run(args, WriteMode::Display); + //run(args, WriteMode::Overwrite); std::env::set_exit_status(0); // TODO unit tests diff --git a/src/visitor.rs b/src/visitor.rs index 8825a094792..e4d48201dd6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -9,9 +9,11 @@ // except according to those terms. use syntax::ast; -use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; +use utils; + use {MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION}; use changes::ChangeSet; @@ -35,6 +37,26 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = ex.span.hi; } + fn visit_stmt(&mut self, stmt: &'v ast::Stmt) { + // If the stmt is actually an item, then we'll handle any missing spans + // there. This is important because of annotations. + // Although it might make more sense for the statement span to include + // any annotations on the item. + let skip_missing = match stmt.node { + ast::Stmt_::StmtDecl(ref decl, _) => { + match decl.node { + ast::Decl_::DeclItem(_) => true, + _ => false, + } + } + _ => false, + }; + if !skip_missing { + self.format_missing_with_indent(stmt.span.lo); + } + visit::walk_stmt(self, stmt); + } + fn visit_block(&mut self, b: &'v ast::Block) { debug!("visit_block: {:?} {:?}", self.codemap.lookup_char_pos(b.span.lo), @@ -46,7 +68,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent += TAB_SPACES; for stmt in &b.stmts { - self.format_missing_with_indent(stmt.span.lo); self.visit_stmt(&stmt) } match b.expr { @@ -148,6 +169,12 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { visit::walk_item(self, item); self.block_indent -= TAB_SPACES; } + ast::Item_::ItemExternCrate(_) => { + self.format_missing_with_indent(item.span.lo); + let new_str = self.snippet(item.span); + self.changes.push_str_span(item.span, &new_str); + self.last_pos = item.span.hi; + } _ => { visit::walk_item(self, item); } @@ -206,18 +233,50 @@ impl<'a> FmtVisitor<'a> { // Returns true if we should skip the following item. fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { - for a in attrs { - self.format_missing_with_indent(a.span.lo); + if attrs.len() == 0 { + return false; + } + + let first = &attrs[0]; + self.format_missing_with_indent(first.span.lo); + + match self.rewrite_attrs(attrs, self.block_indent) { + Some(s) => { + self.changes.push_str_span(first.span, &s); + let last = attrs.last().unwrap(); + self.last_pos = last.span.hi; + false + } + None => true + } + } + + fn rewrite_attrs(&self, attrs: &[ast::Attribute], indent: usize) -> Option { + let mut result = String::new(); + let indent = utils::make_indent(indent); + + for (i, a) in attrs.iter().enumerate() { if is_skip(&a.node.value) { - return true; + return None; } - let attr_str = self.snippet(a.span); - self.changes.push_str_span(a.span, &attr_str); - self.last_pos = a.span.hi; + result.push_str(&self.snippet(a.span)); + + if i < attrs.len() - 1 { + result.push('\n'); + result.push_str(&indent); + + let comment = self.snippet(codemap::mk_sp(a.span.hi, attrs[i+1].span.lo)); + let comment = comment.trim(); + if comment.len() > 0 { + result.push_str(&self.snippet(a.span)); + result.push('\n'); + result.push_str(comment); + } + } } - false + Some(result) } } diff --git a/tests/idem/attrib-extern-crate.rs b/tests/idem/attrib-extern-crate.rs new file mode 100644 index 00000000000..fe06195b154 --- /dev/null +++ b/tests/idem/attrib-extern-crate.rs @@ -0,0 +1,17 @@ +// Attributes on extern crate. + +extern crate Foo; +#[Attr1] +extern crate Bar; +#[Attr2] +#[Attr2] +extern crate Baz; + +fn foo() { + extern crate Foo; + #[Attr1] + extern crate Bar; + #[Attr2] + #[Attr2] + extern crate Baz; +} diff --git a/tests/idem/attrib.rs b/tests/idem/attrib.rs index aa2b1a69df0..e36f6425421 100644 --- a/tests/idem/attrib.rs +++ b/tests/idem/attrib.rs @@ -1,17 +1,11 @@ // Test attributes and doc comments are preserved. -extern crate Foo; -#[Attr1] -extern crate Bar; -#[Attr2] -#[Attr2] -extern crate Baz; - /// Blah blah blah. impl Bar { /// Blah blah blooo. #[an_attribute] - fn foo(&mut self) -> isize {} + fn foo(&mut self) -> isize { + } /// Blah blah bing. pub fn f2(self) { @@ -22,8 +16,3 @@ impl Bar { fn f3(self) -> Dog { } } - -/// Blah -fn main() { - println!("Hello world!"); -} diff --git a/tests/idem/comments-fn.rs b/tests/idem/comments-fn.rs index 12c0e72193f..748a6edb6ca 100644 --- a/tests/idem/comments-fn.rs +++ b/tests/idem/comments-fn.rs @@ -16,7 +16,8 @@ fn foo(a: aaaaaaaaaaaaa, // A comment } -fn bar() {} +fn bar() { +} fn baz() -> Baz /* Comment after return type */ { } diff --git a/tests/idem/imports.rs b/tests/idem/imports.rs new file mode 100644 index 00000000000..9891994c66e --- /dev/null +++ b/tests/idem/imports.rs @@ -0,0 +1,8 @@ +// Imports. + +// Long import. +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, + ItemDefaultImpl}; + +use {Foo, Bar}; +use Foo::{Bar, Baz}; -- cgit 1.4.1-3-g733a5 From 16f905797520febe7a6f0757c09fd7a2758fc70e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 29 Apr 2015 15:24:20 +1200 Subject: Better handle trait items --- src/visitor.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index e4d48201dd6..a669732b6c7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -159,12 +159,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } visit::walk_item(self, item); } - ast::Item_::ItemImpl(..) => { - self.block_indent += TAB_SPACES; - visit::walk_item(self, item); - self.block_indent -= TAB_SPACES; - } - ast::Item_::ItemMod(_) => { + ast::Item_::ItemImpl(..) | + ast::Item_::ItemMod(_) | + ast::Item_::ItemTrait(..) => { self.block_indent += TAB_SPACES; visit::walk_item(self, item); self.block_indent -= TAB_SPACES; -- cgit 1.4.1-3-g733a5 From f61ad354943ed95700c51a969666a509778640ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 29 Apr 2015 16:21:04 +1200 Subject: Preserve linebreaks in doc comments --- src/mod.rs | 4 ++-- src/visitor.rs | 26 ++++++++++++++++++-------- tests/idem/attrib.rs | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index 076a826035b..7b18664b672 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -262,8 +262,8 @@ fn run(args: Vec, write_mode: WriteMode) { fn main() { let args: Vec<_> = std::env::args().collect(); - run(args, WriteMode::Display); - //run(args, WriteMode::Overwrite); + //run(args, WriteMode::Display); + run(args, WriteMode::Overwrite); std::env::set_exit_status(0); // TODO unit tests diff --git a/src/visitor.rs b/src/visitor.rs index a669732b6c7..75dcdb12601 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -257,19 +257,29 @@ impl<'a> FmtVisitor<'a> { return None; } - result.push_str(&self.snippet(a.span)); + let a_str = self.snippet(a.span); - if i < attrs.len() - 1 { - result.push('\n'); - result.push_str(&indent); - - let comment = self.snippet(codemap::mk_sp(a.span.hi, attrs[i+1].span.lo)); + if i > 0 { + let comment = self.snippet(codemap::mk_sp(attrs[i-1].span.hi, a.span.lo)); + // This particular horror show is to preserve line breaks in between doc + // comments. An alternative would be to force such line breaks to start + // with the usual doc comment token. + let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; let comment = comment.trim(); if comment.len() > 0 { - result.push_str(&self.snippet(a.span)); - result.push('\n'); + result.push_str(&indent); result.push_str(comment); + result.push('\n'); + } else if multi_line { + result.push('\n'); } + result.push_str(&indent); + } + + result.push_str(&a_str); + + if i < attrs.len() -1 { + result.push('\n'); } } diff --git a/tests/idem/attrib.rs b/tests/idem/attrib.rs index e36f6425421..ee7da10081e 100644 --- a/tests/idem/attrib.rs +++ b/tests/idem/attrib.rs @@ -1,12 +1,26 @@ // Test attributes and doc comments are preserved. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. + /// Blah blah blah. impl Bar { + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. /// Blah blah blooo. #[an_attribute] fn foo(&mut self) -> isize { } + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + + /// Blah blah bing. + /// Blah blah bing. /// Blah blah bing. pub fn f2(self) { (foo, bar) -- cgit 1.4.1-3-g733a5 From 2d5226b825857cec813a97a129124ac40d2dfb7b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 29 Apr 2015 16:44:29 +1200 Subject: Use + for type bounds --- src/types.rs | 2 +- tests/idem/fn.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 839482f921a..2d1c7a3d442 100644 --- a/src/types.rs +++ b/src/types.rs @@ -81,7 +81,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&token::get_ident(ty_param.ident)); if ty_param.bounds.len() > 0 { result.push_str(": "); - result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(", ")); + result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")); } if let Some(ref def) = ty_param.default { result.push_str(" = "); diff --git a/tests/idem/fn.rs b/tests/idem/fn.rs index e5013a61cee..a4875815e5d 100644 --- a/tests/idem/fn.rs +++ b/tests/idem/fn.rs @@ -40,3 +40,10 @@ impl Foo { { } } + +pub fn render<'a, N: Clone+'a, E: Clone+'a, G: Labeller<'a, N, E>+GraphWalk<'a, N, E>, W: Write> + (g: &'a G, + w: &mut W) + -> io::Result<()> { + render_opts(g, w, &[]) +} -- cgit 1.4.1-3-g733a5 From 25fcb7754a3cc20e10ff43d530e66859ef6244f2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 30 Apr 2015 15:09:33 +1200 Subject: Add README.md --- README.md | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mod.rs | 22 +------ 2 files changed, 219 insertions(+), 21 deletions(-) create mode 100644 README.md (limited to 'src') diff --git a/README.md b/README.md new file mode 100644 index 00000000000..2835eafeaae --- /dev/null +++ b/README.md @@ -0,0 +1,218 @@ +# rustfmt + +A tool for formatting Rust code according to style guidelines. + + +## How to use + +`cargo build` to build. + +`cargo test` to run all tests. + +`cargo run filename` to run on a file, if the file includes out of line modules, +then we reformat those too. So to run on a whole module or crate, you just need +to run on the top file. You'll probably want to set the `WriteMode` in the call +to `run` in `main()`. Eventually you should be able to set the mode from the +command line or from a config file or something. + + +## Use cases + +A formatting tool can be used in different ways and the different use cases can +affect the design of the tool. The use cases I'm particularly concerned with are: + +* running on a whole repo before check-in + - in particular, to replace the `make tidy` pass on the Rust distro +* running on code from another project that you are adding to your own +* using for mass changes in code style over a project + +Some valid use cases for a formatting tool which I am explicitly not trying to +address (although it would be nice, if possible): + +* running 'as you type' in an IDE +* running on arbitrary snippets of code +* running on Rust-like code, specifically code which doesn't parse +* use as a pretty printer inside the compiler +* refactoring +* formatting totally unformatted source code + + +## Scope and vision + +I do not subscribe to the notion that a formatting tool should only change +whitespace. I believe that we should semantics preserving, but not necessarily +syntax preserving, i.e., we can change the AST of a program. + +I.e., we might change glob imports to list or single imports, re-order imports, +move bounds to where clauses, combine multiple impls into a single impl, etc. + +However, we will not change the names of variables or make any changes which +*could* change the semantics. To be ever so slightly formal, we might imagine +a compilers high level intermediate representation, we should strive to only +make changes which do change the HIR, even if they do change the AST. + +I would like to be able to output refactoring scripts for making deeper changes +though. (E.g., renaming variables to satisfy our style guidelines). + +My long term goal is that all style lints can be moved from the compiler to +rustfmt and, as well as warning, can either fix problems or emit refactoring +scripts to do so. + +### Configurability + +I believe reformatting should be configurable to some extent. We should read in +options from a configuration file and reformat accordingly. We should supply at +least a config file which matches the Rust style guidelines. + +There should be multiple modes for running the tool. As well as simply replacing +each file, we should be able to show the user a list of the changes we would +make, or show a list of violations without corrections (the difference being +that there are multiple ways to satisfy a given set of style guidelines, and we +should distinguish violations from deviations from our own model). + + +## Implementation philosophy + +Some details of the philosophy behind the implementation. + + +### Operate on the AST + +A reformatting tool can be based on either the AST or a token stream (in Rust +this is actually a stream of token trees, but its not a fundamental difference). +There are pros and cons to the two approaches. I have chosen to use the AST +approach. The primary reasons are that it allows us to do more sophisticated +manipulations, rather than just change whitespace, and it gives us more context +when making those changes. + +The advantage of the tokens approach are that you can operate on non-parsable +code. I don't care too much about that, it would be nice, but I think being able +to sophisticated transformations is more important. In the future I hope to +(optionally) be able to use type information for informing reformatting too. One +specific case of unparsable code is macros. Using tokens is certainly easier +here, but I believe it is perfectly solvable with the AST approach. At the limit, +we can operate on just tokens in the macro case. + +I believe that there is not in fact that much difference between the two +approaches. Due to imperfect span information, under the AST approach, we +sometimes are reduced to examining tokens or do some re-lexing of our own. Under +the tokens approach you need to implement your own (much simpler) parser. I +believe that as the tool gets more sophisticated, you end up doing more at the +token-level, or having an increasingly sophisticated parser, until at the limit +you have the same tool. + +However, I believe starting from the AST gets you more quickly to a usable and +useful tool. + + +### Heuristic rather than algorithmic + +Many formatting tools use a very general algorithmic or even algebraic tool for +pretty printing. This results in very elegant code, but I believe does not give +the best results. I prefer a more ad hoc approach where each expression/item is +formatted using custom rules. We hopefully don't end up with too much code due +to good old fashioned abstraction and code sharing. This will give a bigger code +base, but hopefully a better result. + +It also means that there will be some cases we can't format and we have to give +up. I think that is OK. Hopefully they are rare enough that manually fixing them +is not painful. Better to have a tool that gives great code in 99% of cases and +fails in 1% than a tool which gives 50% great code and 50% ugly code, but never +fails. + + +### Incremental development + +I want rustfmt to be useful as soon as possible and to always be useful. I +specifically don't want to have to wait for a feature (or worse, the whole tool) +to be perfect before it is useful. The main ways this is achieved is to output +the source code where we can't yet reformat, be able to turn off new features +until they are ready, and the 'do no harm' principle (see next section). + + +### First, do no harm + +Until rustfmt it perfect, there will always be a trade-off between doing more and +doing existing things well. I want to err on the side of the latter. +Specifically, rustfmt should never take OK code and make it look worse. If we +can't make it better, we should leave it as is. That might mean being less +aggressive than we like or using configurability. + + +### Use the source code as guidance + +There are often multiple ways to format code and satisfy standards. Where this +is the case, we should use the source code as a hint for reformatting. +Furthermore, where the code has been formatted in a particular way that satisfies +the coding standard, it should not be changed (this is sometimes not possible or +not worthwhile due to uniformity being desirable, but it is a useful goal). + + +### Architecture details + +We use the AST from libsyntax. We use libsyntax's visit module to walk the AST +to find starting points for reformatting. Eventually, we should reformat everything +and we shouldn't need the visit module. We keep track of the last formatted +position in the code, and when we reformat the next piece of code we make sure +to output the span for all the code in between (handled by missed_spans.rs). + +Our visitor keeps track of the desired current indent due to blocks ( +`block_indent`). Each `visit_*` method reformats code according to this indent +and `IDEAL_WIDTH` and `MAX_WIDTH` (which should one day be supplied from a +config file). Most reformatting done in the `visit_*` methods is a bit hackey +and is meant to be temporary until it can be done properly. + +There are a bunch of methods called `rewrite_*`. There do the bulk of the +reformatting. These take the AST node to be reformatted (this may not literally +be an AST node from libsyntax, there might be multiple parameters describing a +logical node), the current indent, and the current width budget. They return a +`String` (or sometimes an `Option`) which formats the code in the box +given by the indent and width budget. If the method fails, it returns `None` and +the calling method then has to fallback in some way to give the callee more space. + +So, in summary to format a node, we calculate the width budget and then walk down +the tree from the node. At a leaf, we generate an actual string and then unwind, +combining these strings as we go back up the tree. + +For example, consider a method definition: + +``` + fn foo(a: A, b: B) { + ... + } +``` + +We start at indent 4, the rewrite function for the whole function knows it must +write `fn foo(` before the arguments and `) {` after them, assuming the max width +is 100, it thus asks the rewrite argument list function to rewrite with an indent +of 11 and in a width of 86. Assuming that is possible (obviously in this case), +it returns a string for the arguments and it can make a string for the function +header. If the arguments couldn't be fitted in that space, we might try to +fallback to a hanging indent, so we try again with indent 8 and width 89. + + +## Contributing + +### Test and file issues + +It would be really useful to have people use rustfmt on their projects and file +issues where it does something you don't expect. + +A really useful thing to do that on a crate from the Rust repo. If it does +something unexpected, file an issue; if not, make a PR to the Rust repo with the +reformatted code. I hope to get the whole repo consistently rustfmt'ed and to +replace `make tidy` with rustfmt as a medium-term goal. + +### Create test cases + +Having a strong test suite for a tool like this is essential. It is very easy +to create regressions. Any tests you can add are very much appreciated. + +### Hack! + +Here are some [good starting issues](https://github.com/nrc/rustfmt/issues?q=is%3Aopen+is%3Aissue+label%3Aeasy). +Note than some of those issues tagged 'easy' are not that easy and might be better +second issues, rather than good first issues to fix. + +If you've found areas which need polish and don't have issues, please submit a +PR, don't feel there needs to be an issue. diff --git a/src/mod.rs b/src/mod.rs index 7b18664b672..be0bea4b70c 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -19,13 +19,6 @@ // keeping some scratch mem for this and running our own StrPool? // TODO for lint violations of names, emit a refactor script -// TODO priorities -// annotations/doc comments -// Fix fns and methods properly -// dead spans (comments) - in where clause - test -// -// Smoke testing till we can use it -// take config options from a file #[macro_use] extern crate log; @@ -287,19 +280,6 @@ fn main() { // println!(" {}", s); } -// FIXME comments -// comments aren't in the AST, which makes processing them difficult, but then -// comments are complicated anyway. I think I am happy putting off tackling them -// for now. Long term the soluton is for comments to be in the AST, but that means -// only the libsyntax AST, not the rustc one, which means waiting for the ASTs -// to diverge one day.... - -// Once we do have comments, we just have to implement a simple word wrapping -// algorithm to keep the width under IDEAL_WIDTH. We should also convert multiline -// /* ... */ comments to // and check doc comments are in the right place and of -// the right kind. - -// Should also make sure comments have the right indent #[cfg(test)] mod test { @@ -311,7 +291,7 @@ mod test { // For now, the only supported regression tests are idempotent tests - the input and // output must match exactly. - // TODO would be good to check for error messages and fail on them, or at least report. + // FIXME(#28) would be good to check for error messages and fail on them, or at least report. #[test] fn idempotent_tests() { println!("Idempotent tests:"); -- cgit 1.4.1-3-g733a5 From dc3e23659940a149f6e3cffbe9dfc5859284b227 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 30 Apr 2015 09:32:38 +0200 Subject: Fix warnings in `cargo test` --- src/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index be0bea4b70c..83e3a199020 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -12,9 +12,10 @@ #![feature(box_patterns)] #![feature(rustc_private)] #![feature(collections)] -#![feature(exit_status)] #![feature(str_char)] +#![cfg_attr(not(test), feature(exit_status))] + // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? // TODO for lint violations of names, emit a refactor script @@ -253,6 +254,7 @@ fn run(args: Vec, write_mode: WriteMode) { rustc_driver::run_compiler(&args, &mut call_ctxt); } +#[cfg(not(test))] fn main() { let args: Vec<_> = std::env::args().collect(); //run(args, WriteMode::Display); -- cgit 1.4.1-3-g733a5 From 9398aed82cac204e94bfed0e50b9881230d228b8 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 30 Apr 2015 13:33:26 +0530 Subject: Handle pub use (fixes #23) --- src/imports.rs | 12 ++++++++---- src/visitor.rs | 5 ++++- tests/idem/imports.rs | 2 ++ 3 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 1532050522a..59bac9d73a7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -27,12 +27,17 @@ impl<'a> FmtVisitor<'a> { pub fn rewrite_use_list(&mut self, path: &ast::Path, path_list: &[ast::PathListItem], + visibility: ast::Visibility, vp_span: Span) -> String { // FIXME check indentation let l_loc = self.codemap.lookup_char_pos(vp_span.lo); let path_str = pprust::path_to_string(&path); + let vis = match visibility { + ast::Public => "pub ", + _ => "" + }; // 1 = { let mut indent = l_loc.col.0 + path_str.len() + 1; @@ -41,7 +46,7 @@ impl<'a> FmtVisitor<'a> { indent += 2; } // 2 = } + ; - let used_width = indent + 2; + let used_width = indent + 2 + vis.len(); let budget = if used_width >= IDEAL_WIDTH { if used_width < MAX_WIDTH { MAX_WIDTH - used_width @@ -84,11 +89,10 @@ impl<'a> FmtVisitor<'a> { ast::PathListItem_::PathListMod{ .. } => None, } })).collect(); - if path_str.len() == 0 { - format!("use {{{}}};", write_list(&items, &fmt)) + format!("{}use {{{}}};", vis, write_list(&items, &fmt)) } else { - format!("use {}::{{{}}};", path_str, write_list(&items, &fmt)) + format!("{}use {}::{{{}}};", vis, path_str, write_list(&items, &fmt)) } } } diff --git a/src/visitor.rs b/src/visitor.rs index 75dcdb12601..5b99d700c9c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -148,7 +148,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { self.format_missing(item.span.lo); - let new_str = self.rewrite_use_list(path, path_list, vp.span); + let new_str = self.rewrite_use_list(path, + path_list, + item.vis, + vp.span); self.changes.push_str_span(item.span, &new_str); self.last_pos = item.span.hi; } diff --git a/tests/idem/imports.rs b/tests/idem/imports.rs index 9891994c66e..13910c8a628 100644 --- a/tests/idem/imports.rs +++ b/tests/idem/imports.rs @@ -6,3 +6,5 @@ use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, use {Foo, Bar}; use Foo::{Bar, Baz}; +pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, + ExprPath}; -- cgit 1.4.1-3-g733a5 From 5247d98d31898326555c6e35780e0388d5e35514 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 30 Apr 2015 10:31:42 +0200 Subject: Change `to_string` to `to_owned` when it just creates a `String` from a `&str` This means that it doesn't have to go through the formatting hierarchy and can just immediately reserve enough memory. --- src/changes.rs | 6 +++--- src/functions.rs | 14 +++++++------- src/imports.rs | 2 +- src/mod.rs | 4 ++-- src/visitor.rs | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 2b42c164690..8884b05d77e 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -153,8 +153,8 @@ impl<'a> ChangeSet<'a> { // Do a little dance to make writing safer - write to a temp file // rename the original to a .bk, then rename the temp file to the // original. - let tmp_name = filename.to_string() + ".tmp"; - let bk_name = filename.to_string() + ".bk"; + let tmp_name = filename.to_owned() + ".tmp"; + let bk_name = filename.to_owned() + ".bk"; { // Write text to temp file let mut tmp_file = try!(File::create(&tmp_name)); @@ -165,7 +165,7 @@ impl<'a> ChangeSet<'a> { try!(::std::fs::rename(tmp_name, filename)); } WriteMode::NewFile(extn) => { - let filename = filename.to_string() + "." + extn; + let filename = filename.to_owned() + "." + extn; let mut file = try!(File::create(&filename)); try!(write!(file, "{}", text)); } diff --git a/src/functions.rs b/src/functions.rs index a753f38d9f7..3d6fcb88c25 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -154,7 +154,7 @@ impl<'a> FmtVisitor<'a> { &None => String::new(), }; let mut_str = match m { - &ast::Mutability::MutMutable => "mut ".to_string(), + &ast::Mutability::MutMutable => "mut ".to_owned(), &ast::Mutability::MutImmutable => String::new(), }; arg_item_strs[0] = format!("&{}{}self", lt_str, mut_str); @@ -164,7 +164,7 @@ impl<'a> FmtVisitor<'a> { arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); } ast::ExplicitSelf_::SelfValue(_) => { - arg_item_strs[0] = "self".to_string(); + arg_item_strs[0] = "self".to_owned(); min_args = 2; } _ => {} @@ -174,7 +174,7 @@ impl<'a> FmtVisitor<'a> { // Comments between args let mut arg_comments = Vec::new(); if min_args == 2 { - arg_comments.push("".to_string()); + arg_comments.push("".to_owned()); } // TODO if there are no args, there might still be a comment, but without // spans for the comment or parens, there is no chance of getting it right. @@ -239,7 +239,7 @@ impl<'a> FmtVisitor<'a> { } else if snippet.ends_with(separator) { snippet = snippet[..snippet.len()-separator.len()].trim_matches(white_space); } - result.push(snippet.to_string()); + result.push(snippet.to_owned()); prev_end = get_hi(&item); } // Get the last commment. @@ -254,7 +254,7 @@ impl<'a> FmtVisitor<'a> { let snippet = &snippet[..snippet.find(terminator) .unwrap_or(snippet.find(separator).unwrap_or(snippet.len()))]; let snippet = snippet.trim(); - result.push(snippet.to_string()); + result.push(snippet.to_owned()); result } @@ -422,8 +422,8 @@ impl<'a> FmtVisitor<'a> { fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { match *ret { ast::FunctionRetTy::DefaultReturn(_) => String::new(), - ast::FunctionRetTy::NoReturn(_) => "-> !".to_string(), - ast::FunctionRetTy::Return(ref ty) => "-> ".to_string() + &pprust::ty_to_string(ty), + ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(), + ast::FunctionRetTy::Return(ref ty) => "-> ".to_owned() + &pprust::ty_to_string(ty), } } diff --git a/src/imports.rs b/src/imports.rs index 1532050522a..09a702dbaa1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -70,7 +70,7 @@ impl<'a> FmtVisitor<'a> { false } ) { - Some(("self".to_string(), String::new())) + Some(("self".to_owned(), String::new())) } else { None }; diff --git a/src/mod.rs b/src/mod.rs index be0bea4b70c..45b2bce1638 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -305,12 +305,12 @@ mod test { let path = entry.unwrap().path(); let file_name = path.to_str().unwrap(); println!("Testing '{}'...", file_name); - run(vec!["rustfmt".to_string(), file_name.to_string()], WriteMode::Return(HANDLE_RESULT)); + run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); count += 1; } // And also dogfood ourselves! println!("Testing 'src/mod.rs'..."); - run(vec!["rustfmt".to_string(), "src/mod.rs".to_string()], WriteMode::Return(HANDLE_RESULT)); + run(vec!["rustfmt".to_owned(), "src/mod.rs".to_owned()], WriteMode::Return(HANDLE_RESULT)); count += 1; // Display results diff --git a/src/visitor.rs b/src/visitor.rs index 75dcdb12601..7a9c8583039 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -223,7 +223,7 @@ impl<'a> FmtVisitor<'a> { println!("Couldn't make snippet for span {:?}->{:?}", self.codemap.lookup_char_pos(span.lo), self.codemap.lookup_char_pos(span.hi)); - "".to_string() + "".to_owned() } } } -- cgit 1.4.1-3-g733a5 From 2f221fd0957d4786a719e2e1087d4ad0d764aedb Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 30 Apr 2015 10:40:37 +0200 Subject: Use `AtomicUsize` instead of `static mut` that require `unsafe` --- src/mod.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/mod.rs b/src/mod.rs index be0bea4b70c..48eb3d3cc0b 100644 --- a/src/mod.rs +++ b/src/mod.rs @@ -286,6 +286,7 @@ mod test { use std::collections::HashMap; use std::fs; use std::io::Read; + use std::sync::atomic; use super::*; use super::run; @@ -295,7 +296,7 @@ mod test { #[test] fn idempotent_tests() { println!("Idempotent tests:"); - unsafe { FAILURES = 0; } + FAILURES.store(0, atomic::Ordering::Relaxed); // Get all files in the tests/idem directory let files = fs::read_dir("tests/idem").unwrap(); @@ -314,13 +315,13 @@ mod test { count += 1; // Display results - let fails = unsafe { FAILURES }; + let fails = FAILURES.load(atomic::Ordering::Relaxed); println!("Ran {} idempotent tests; {} failures.", count, fails); assert!(fails == 0, "{} idempotent tests failed", fails); } // 'global' used by sys_tests and handle_result. - static mut FAILURES: i32 = 0; + static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; // Ick, just needed to get a &'static to handle_result. static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; @@ -340,9 +341,7 @@ mod test { } if fails > 0 { - unsafe { - FAILURES += 1; - } + FAILURES.fetch_add(1, atomic::Ordering::Relaxed); } } } -- cgit 1.4.1-3-g733a5 From 21451080439ac46ef176c4953f10aa08759f6605 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 30 Apr 2015 10:26:59 +0200 Subject: Rename `src/mod.rs` to `src/main.rs` to adhere to the standard crate format --- Cargo.toml | 6 +- src/main.rs | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/mod.rs | 349 ----------------------------------------------------------- 3 files changed, 351 insertions(+), 354 deletions(-) create mode 100644 src/main.rs delete mode 100644 src/mod.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 770a1c1b945..49c473fb008 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "rustfmt" version = "0.0.1" authors = ["Nicholas Cameron "] -description = "tool to find and fix Rust formatting issues" +description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/nick29581/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" @@ -11,7 +11,3 @@ license = "Apache-2.0/MIT" [dependencies.strings] strings = "0.0.1" git = "https://github.com/nrc/strings.rs.git" - -[[bin]] -name = "rustfmt" -path = "src/mod.rs" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 00000000000..8cd95ddf626 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,350 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![feature(box_patterns)] +#![feature(rustc_private)] +#![feature(collections)] +#![feature(str_char)] + +#![cfg_attr(not(test), feature(exit_status))] + +// TODO we're going to allocate a whole bunch of temp Strings, is it worth +// keeping some scratch mem for this and running our own StrPool? +// TODO for lint violations of names, emit a refactor script + + +#[macro_use] +extern crate log; + +extern crate getopts; +extern crate rustc; +extern crate rustc_driver; +extern crate syntax; + +extern crate strings; + +use rustc::session::Session; +use rustc::session::config::{self, Input}; +use rustc_driver::{driver, CompilerCalls, Compilation}; + +use syntax::ast; +use syntax::codemap::CodeMap; +use syntax::diagnostics; +use syntax::visit; + +use std::path::PathBuf; +use std::collections::HashMap; + +use changes::ChangeSet; +use visitor::FmtVisitor; + +mod changes; +mod visitor; +mod functions; +mod missed_spans; +mod lists; +mod utils; +mod types; +mod expr; +mod imports; + +const IDEAL_WIDTH: usize = 80; +const LEEWAY: usize = 5; +const MAX_WIDTH: usize = 100; +const MIN_STRING: usize = 10; +const TAB_SPACES: usize = 4; +const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; +const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; +// When we get scoped annotations, we should have rustfmt::skip. +const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; + +#[derive(Copy, Clone)] +pub enum WriteMode { + Overwrite, + // str is the extension of the new file + NewFile(&'static str), + // Write the output to stdout. + Display, + // Return the result as a mapping from filenames to StringBuffers. + Return(&'static Fn(HashMap)), +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum BraceStyle { + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +// How to indent a function's return type. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum ReturnIndent { + // Aligned with the arguments + WithArgs, + // Aligned with the where clause + WithWhereClause, +} + +// Formatting which depends on the AST. +fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { + let mut visitor = FmtVisitor::from_codemap(codemap); + visit::walk_crate(&mut visitor, krate); + let files = codemap.files.borrow(); + if let Some(last) = files.last() { + visitor.format_missing(last.end_pos); + } + + visitor.changes +} + +// Formatting done on a char by char or line by line basis. +// TODO warn on TODOs and FIXMEs without an issue number +// TODO warn on bad license +// TODO other stuff for parity with make tidy +fn fmt_lines(changes: &mut ChangeSet) { + let mut truncate_todo = Vec::new(); + + // Iterate over the chars in the change set. + for (f, text) in changes.text() { + let mut trims = vec![]; + let mut last_wspace: Option = None; + let mut line_len = 0; + let mut cur_line = 1; + let mut newline_count = 0; + for (c, b) in text.chars() { + if c == '\n' { // TOOD test for \r too + // Check for (and record) trailing whitespace. + if let Some(lw) = last_wspace { + trims.push((cur_line, lw, b)); + line_len -= b - lw; + } + // Check for any line width errors we couldn't correct. + if line_len > MAX_WIDTH { + // TODO store the error rather than reporting immediately. + println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", + f, cur_line, MAX_WIDTH); + } + line_len = 0; + cur_line += 1; + newline_count += 1; + last_wspace = None; + } else { + newline_count = 0; + line_len += 1; + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(b); + } + } else { + last_wspace = None; + } + } + } + + if newline_count > 1 { + debug!("track truncate: {} {} {}", f, text.len, newline_count); + truncate_todo.push((f, text.len - newline_count + 1)) + } + + for &(l, _, _) in trims.iter() { + // TODO store the error rather than reporting immediately. + println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); + } + } + + for (f, l) in truncate_todo { + // This unsafe block and the ridiculous dance with the cast is because + // the borrow checker thinks the first borrow of changes lasts for the + // whole function. + unsafe { + (*(changes as *const ChangeSet as *mut ChangeSet)).get_mut(f).truncate(l); + } + } +} + +struct RustFmtCalls { + input_path: Option, + write_mode: WriteMode, +} + +impl<'a> CompilerCalls<'a> for RustFmtCalls { + fn early_callback(&mut self, + _: &getopts::Matches, + _: &diagnostics::registry::Registry) + -> Compilation { + Compilation::Continue + } + + fn some_input(&mut self, + input: Input, + input_path: Option) + -> (Input, Option) { + match input_path { + Some(ref ip) => self.input_path = Some(ip.clone()), + _ => { + // FIXME should handle string input and write to stdout or something + panic!("No input path"); + } + } + (input, input_path) + } + + fn no_input(&mut self, + _: &getopts::Matches, + _: &config::Options, + _: &Option, + _: &Option, + _: &diagnostics::registry::Registry) + -> Option<(Input, Option)> { + panic!("No input supplied to RustFmt"); + } + + fn late_callback(&mut self, + _: &getopts::Matches, + _: &Session, + _: &Input, + _: &Option, + _: &Option) + -> Compilation { + Compilation::Continue + } + + fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { + let write_mode = self.write_mode; + let mut control = driver::CompileController::basic(); + control.after_parse.stop = Compilation::Stop; + control.after_parse.callback = box move |state| { + let krate = state.krate.unwrap(); + let codemap = state.session.codemap(); + let mut changes = fmt_ast(krate, codemap); + // For some reason, the codemap does not include terminating newlines + // so we must add one on for each file. This is sad. + changes.append_newlines(); + fmt_lines(&mut changes); + + // FIXME(#5) Should be user specified whether to show or replace. + let result = changes.write_all_files(write_mode); + + match result { + Err(msg) => println!("Error writing files: {}", msg), + Ok(result) => { + if let WriteMode::Return(callback) = write_mode { + callback(result); + } + } + } + }; + + control + } +} + +fn run(args: Vec, write_mode: WriteMode) { + let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; + rustc_driver::run_compiler(&args, &mut call_ctxt); +} + +#[cfg(not(test))] +fn main() { + let args: Vec<_> = std::env::args().collect(); + //run(args, WriteMode::Display); + run(args, WriteMode::Overwrite); + std::env::set_exit_status(0); + + // TODO unit tests + // let fmt = ListFormatting { + // tactic: ListTactic::Horizontal, + // separator: ",", + // trailing_separator: SeparatorTactic::Vertical, + // indent: 2, + // h_width: 80, + // v_width: 100, + // }; + // let inputs = vec![(format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new())]; + // let s = write_list(&inputs, &fmt); + // println!(" {}", s); +} + + +#[cfg(test)] +mod test { + use std::collections::HashMap; + use std::fs; + use std::io::Read; + use std::sync::atomic; + use super::*; + use super::run; + + // For now, the only supported regression tests are idempotent tests - the input and + // output must match exactly. + // FIXME(#28) would be good to check for error messages and fail on them, or at least report. + #[test] + fn idempotent_tests() { + println!("Idempotent tests:"); + FAILURES.store(0, atomic::Ordering::Relaxed); + + // Get all files in the tests/idem directory + let files = fs::read_dir("tests/idem").unwrap(); + // For each file, run rustfmt and collect the output + let mut count = 0; + for entry in files { + let path = entry.unwrap().path(); + let file_name = path.to_str().unwrap(); + println!("Testing '{}'...", file_name); + run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); + count += 1; + } + // And also dogfood ourselves! + println!("Testing 'src/main.rs'..."); + run(vec!["rustfmt".to_string(), "src/main.rs".to_string()], + WriteMode::Return(HANDLE_RESULT)); + count += 1; + + // Display results + let fails = FAILURES.load(atomic::Ordering::Relaxed); + println!("Ran {} idempotent tests; {} failures.", count, fails); + assert!(fails == 0, "{} idempotent tests failed", fails); + } + + // 'global' used by sys_tests and handle_result. + static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; + // Ick, just needed to get a &'static to handle_result. + static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; + + // Compare output to input. + fn handle_result(result: HashMap) { + let mut fails = 0; + + for file_name in result.keys() { + let mut f = fs::File::open(file_name).unwrap(); + let mut text = String::new(); + f.read_to_string(&mut text).unwrap(); + if result[file_name] != text { + fails += 1; + println!("Mismatch in {}.", file_name); + println!("{}", result[file_name]); + } + } + + if fails > 0 { + FAILURES.fetch_add(1, atomic::Ordering::Relaxed); + } + } +} diff --git a/src/mod.rs b/src/mod.rs deleted file mode 100644 index bbba035b8b5..00000000000 --- a/src/mod.rs +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(box_syntax)] -#![feature(box_patterns)] -#![feature(rustc_private)] -#![feature(collections)] -#![feature(str_char)] - -#![cfg_attr(not(test), feature(exit_status))] - -// TODO we're going to allocate a whole bunch of temp Strings, is it worth -// keeping some scratch mem for this and running our own StrPool? -// TODO for lint violations of names, emit a refactor script - - -#[macro_use] -extern crate log; - -extern crate getopts; -extern crate rustc; -extern crate rustc_driver; -extern crate syntax; - -extern crate strings; - -use rustc::session::Session; -use rustc::session::config::{self, Input}; -use rustc_driver::{driver, CompilerCalls, Compilation}; - -use syntax::ast; -use syntax::codemap::CodeMap; -use syntax::diagnostics; -use syntax::visit; - -use std::path::PathBuf; -use std::collections::HashMap; - -use changes::ChangeSet; -use visitor::FmtVisitor; - -mod changes; -mod visitor; -mod functions; -mod missed_spans; -mod lists; -mod utils; -mod types; -mod expr; -mod imports; - -const IDEAL_WIDTH: usize = 80; -const LEEWAY: usize = 5; -const MAX_WIDTH: usize = 100; -const MIN_STRING: usize = 10; -const TAB_SPACES: usize = 4; -const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; -const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; -// When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; - -#[derive(Copy, Clone)] -pub enum WriteMode { - Overwrite, - // str is the extension of the new file - NewFile(&'static str), - // Write the output to stdout. - Display, - // Return the result as a mapping from filenames to StringBuffers. - Return(&'static Fn(HashMap)), -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum BraceStyle { - AlwaysNextLine, - PreferSameLine, - // Prefer same line except where there is a where clause, in which case force - // the brace to the next line. - SameLineWhere, -} - -// How to indent a function's return type. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum ReturnIndent { - // Aligned with the arguments - WithArgs, - // Aligned with the where clause - WithWhereClause, -} - -// Formatting which depends on the AST. -fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut visitor = FmtVisitor::from_codemap(codemap); - visit::walk_crate(&mut visitor, krate); - let files = codemap.files.borrow(); - if let Some(last) = files.last() { - visitor.format_missing(last.end_pos); - } - - visitor.changes -} - -// Formatting done on a char by char or line by line basis. -// TODO warn on TODOs and FIXMEs without an issue number -// TODO warn on bad license -// TODO other stuff for parity with make tidy -fn fmt_lines(changes: &mut ChangeSet) { - let mut truncate_todo = Vec::new(); - - // Iterate over the chars in the change set. - for (f, text) in changes.text() { - let mut trims = vec![]; - let mut last_wspace: Option = None; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - for (c, b) in text.chars() { - if c == '\n' { // TOOD test for \r too - // Check for (and record) trailing whitespace. - if let Some(lw) = last_wspace { - trims.push((cur_line, lw, b)); - line_len -= b - lw; - } - // Check for any line width errors we couldn't correct. - if line_len > MAX_WIDTH { - // TODO store the error rather than reporting immediately. - println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", - f, cur_line, MAX_WIDTH); - } - line_len = 0; - cur_line += 1; - newline_count += 1; - last_wspace = None; - } else { - newline_count = 0; - line_len += 1; - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(b); - } - } else { - last_wspace = None; - } - } - } - - if newline_count > 1 { - debug!("track truncate: {} {} {}", f, text.len, newline_count); - truncate_todo.push((f, text.len - newline_count + 1)) - } - - for &(l, _, _) in trims.iter() { - // TODO store the error rather than reporting immediately. - println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); - } - } - - for (f, l) in truncate_todo { - // This unsafe block and the ridiculous dance with the cast is because - // the borrow checker thinks the first borrow of changes lasts for the - // whole function. - unsafe { - (*(changes as *const ChangeSet as *mut ChangeSet)).get_mut(f).truncate(l); - } - } -} - -struct RustFmtCalls { - input_path: Option, - write_mode: WriteMode, -} - -impl<'a> CompilerCalls<'a> for RustFmtCalls { - fn early_callback(&mut self, - _: &getopts::Matches, - _: &diagnostics::registry::Registry) - -> Compilation { - Compilation::Continue - } - - fn some_input(&mut self, - input: Input, - input_path: Option) - -> (Input, Option) { - match input_path { - Some(ref ip) => self.input_path = Some(ip.clone()), - _ => { - // FIXME should handle string input and write to stdout or something - panic!("No input path"); - } - } - (input, input_path) - } - - fn no_input(&mut self, - _: &getopts::Matches, - _: &config::Options, - _: &Option, - _: &Option, - _: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { - panic!("No input supplied to RustFmt"); - } - - fn late_callback(&mut self, - _: &getopts::Matches, - _: &Session, - _: &Input, - _: &Option, - _: &Option) - -> Compilation { - Compilation::Continue - } - - fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { - let write_mode = self.write_mode; - let mut control = driver::CompileController::basic(); - control.after_parse.stop = Compilation::Stop; - control.after_parse.callback = box move |state| { - let krate = state.krate.unwrap(); - let codemap = state.session.codemap(); - let mut changes = fmt_ast(krate, codemap); - // For some reason, the codemap does not include terminating newlines - // so we must add one on for each file. This is sad. - changes.append_newlines(); - fmt_lines(&mut changes); - - // FIXME(#5) Should be user specified whether to show or replace. - let result = changes.write_all_files(write_mode); - - match result { - Err(msg) => println!("Error writing files: {}", msg), - Ok(result) => { - if let WriteMode::Return(callback) = write_mode { - callback(result); - } - } - } - }; - - control - } -} - -fn run(args: Vec, write_mode: WriteMode) { - let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; - rustc_driver::run_compiler(&args, &mut call_ctxt); -} - -#[cfg(not(test))] -fn main() { - let args: Vec<_> = std::env::args().collect(); - //run(args, WriteMode::Display); - run(args, WriteMode::Overwrite); - std::env::set_exit_status(0); - - // TODO unit tests - // let fmt = ListFormatting { - // tactic: ListTactic::Horizontal, - // separator: ",", - // trailing_separator: SeparatorTactic::Vertical, - // indent: 2, - // h_width: 80, - // v_width: 100, - // }; - // let inputs = vec![(format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new())]; - // let s = write_list(&inputs, &fmt); - // println!(" {}", s); -} - - -#[cfg(test)] -mod test { - use std::collections::HashMap; - use std::fs; - use std::io::Read; - use std::sync::atomic; - use super::*; - use super::run; - - // For now, the only supported regression tests are idempotent tests - the input and - // output must match exactly. - // FIXME(#28) would be good to check for error messages and fail on them, or at least report. - #[test] - fn idempotent_tests() { - println!("Idempotent tests:"); - FAILURES.store(0, atomic::Ordering::Relaxed); - - // Get all files in the tests/idem directory - let files = fs::read_dir("tests/idem").unwrap(); - // For each file, run rustfmt and collect the output - let mut count = 0; - for entry in files { - let path = entry.unwrap().path(); - let file_name = path.to_str().unwrap(); - println!("Testing '{}'...", file_name); - run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); - count += 1; - } - // And also dogfood ourselves! - println!("Testing 'src/mod.rs'..."); - run(vec!["rustfmt".to_owned(), "src/mod.rs".to_owned()], WriteMode::Return(HANDLE_RESULT)); - count += 1; - - // Display results - let fails = FAILURES.load(atomic::Ordering::Relaxed); - println!("Ran {} idempotent tests; {} failures.", count, fails); - assert!(fails == 0, "{} idempotent tests failed", fails); - } - - // 'global' used by sys_tests and handle_result. - static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; - // Ick, just needed to get a &'static to handle_result. - static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; - - // Compare output to input. - fn handle_result(result: HashMap) { - let mut fails = 0; - - for file_name in result.keys() { - let mut f = fs::File::open(file_name).unwrap(); - let mut text = String::new(); - f.read_to_string(&mut text).unwrap(); - if result[file_name] != text { - fails += 1; - println!("Mismatch in {}.", file_name); - println!("{}", result[file_name]); - } - } - - if fails > 0 { - FAILURES.fetch_add(1, atomic::Ordering::Relaxed); - } - } -} -- cgit 1.4.1-3-g733a5 From 4f7522771433e0329e76eaeec9fd0f3bfa89d2e1 Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Thu, 30 Apr 2015 16:52:11 -1000 Subject: Spaces around in type bounds --- src/types.rs | 10 +++++----- tests/idem/fn.rs | 6 +++++- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 2d1c7a3d442..c16b9eadf4e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -28,12 +28,12 @@ impl<'a> FmtVisitor<'a> { format!("for<{}> {}: {}", bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) + bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(" + ")) } else { format!("{}: {}", pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")) + bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(" + ")) } } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, @@ -41,7 +41,7 @@ impl<'a> FmtVisitor<'a> { ..}) => { format!("{}: {}", pprust::lifetime_to_string(lifetime), - bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) + bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect(" + ")) } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) @@ -57,7 +57,7 @@ impl<'a> FmtVisitor<'a> { format!("{}: {}", pprust::lifetime_to_string(&lifetime.lifetime), - lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect("+")) + lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect(" + ")) } pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String @@ -81,7 +81,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&token::get_ident(ty_param.ident)); if ty_param.bounds.len() > 0 { result.push_str(": "); - result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect("+")); + result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(" + ")); } if let Some(ref def) = ty_param.default { result.push_str(" = "); diff --git a/tests/idem/fn.rs b/tests/idem/fn.rs index a4875815e5d..aec27597b7a 100644 --- a/tests/idem/fn.rs +++ b/tests/idem/fn.rs @@ -41,7 +41,11 @@ impl Foo { } } -pub fn render<'a, N: Clone+'a, E: Clone+'a, G: Labeller<'a, N, E>+GraphWalk<'a, N, E>, W: Write> +pub fn render<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write> (g: &'a G, w: &mut W) -> io::Result<()> { -- cgit 1.4.1-3-g733a5 From 81c9db32756316c0068530fc479137ab63f77614 Mon Sep 17 00:00:00 2001 From: defyrlt Date: Fri, 1 May 2015 14:08:22 +0300 Subject: Resolved #56 -- `mut` was eaten out of `mut self` in fn args. --- src/functions.rs | 17 ++++++++++++++++- tests/idem/fn.rs | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 3d6fcb88c25..d4f06c1c7ac 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -164,7 +164,22 @@ impl<'a> FmtVisitor<'a> { arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); } ast::ExplicitSelf_::SelfValue(_) => { - arg_item_strs[0] = "self".to_owned(); + assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); + + // this hacky solution caused by absence of `Mutability` in `SelfValue`. + let mut_str = { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) + = args[0].pat.node { + match mutability { + ast::Mutability::MutMutable => "mut ", + ast::Mutability::MutImmutable => "", + } + } else { + panic!("there is a bug or change in structure of AST, aborting."); + } + }; + + arg_item_strs[0] = format!("{}self", mut_str); min_args = 2; } _ => {} diff --git a/tests/idem/fn.rs b/tests/idem/fn.rs index a4875815e5d..8566ad0d3b9 100644 --- a/tests/idem/fn.rs +++ b/tests/idem/fn.rs @@ -39,6 +39,12 @@ impl Foo { where F: FnOnce(&mut Resolver) -> T { } + + fn foo(mut self, mut bar: u32) { + } + + fn bar(self, mut bazz: u32) { + } } pub fn render<'a, N: Clone+'a, E: Clone+'a, G: Labeller<'a, N, E>+GraphWalk<'a, N, E>, W: Write> -- cgit 1.4.1-3-g733a5 From c006b84d878039f35455a79618bac4a768034cca Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 1 May 2015 12:17:14 -0400 Subject: Trust the borrow checker. --- src/main.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 8cd95ddf626..e16537198f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -153,7 +153,7 @@ fn fmt_lines(changes: &mut ChangeSet) { if newline_count > 1 { debug!("track truncate: {} {} {}", f, text.len, newline_count); - truncate_todo.push((f, text.len - newline_count + 1)) + truncate_todo.push((f.to_string(), text.len - newline_count + 1)) } for &(l, _, _) in trims.iter() { @@ -163,12 +163,7 @@ fn fmt_lines(changes: &mut ChangeSet) { } for (f, l) in truncate_todo { - // This unsafe block and the ridiculous dance with the cast is because - // the borrow checker thinks the first borrow of changes lasts for the - // whole function. - unsafe { - (*(changes as *const ChangeSet as *mut ChangeSet)).get_mut(f).truncate(l); - } + changes.get_mut(&f).truncate(l); } } -- cgit 1.4.1-3-g733a5 From e6e7ce178f39b837e1b2b8dff33d587780a2a37e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 1 May 2015 18:40:05 +0200 Subject: main.rs -> lib.rs --- src/lib.rs | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 345 ------------------------------------------------------------ 2 files changed, 345 insertions(+), 345 deletions(-) create mode 100644 src/lib.rs delete mode 100644 src/main.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000000..e16537198f6 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,345 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![feature(box_patterns)] +#![feature(rustc_private)] +#![feature(collections)] +#![feature(str_char)] + +#![cfg_attr(not(test), feature(exit_status))] + +// TODO we're going to allocate a whole bunch of temp Strings, is it worth +// keeping some scratch mem for this and running our own StrPool? +// TODO for lint violations of names, emit a refactor script + + +#[macro_use] +extern crate log; + +extern crate getopts; +extern crate rustc; +extern crate rustc_driver; +extern crate syntax; + +extern crate strings; + +use rustc::session::Session; +use rustc::session::config::{self, Input}; +use rustc_driver::{driver, CompilerCalls, Compilation}; + +use syntax::ast; +use syntax::codemap::CodeMap; +use syntax::diagnostics; +use syntax::visit; + +use std::path::PathBuf; +use std::collections::HashMap; + +use changes::ChangeSet; +use visitor::FmtVisitor; + +mod changes; +mod visitor; +mod functions; +mod missed_spans; +mod lists; +mod utils; +mod types; +mod expr; +mod imports; + +const IDEAL_WIDTH: usize = 80; +const LEEWAY: usize = 5; +const MAX_WIDTH: usize = 100; +const MIN_STRING: usize = 10; +const TAB_SPACES: usize = 4; +const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; +const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; +// When we get scoped annotations, we should have rustfmt::skip. +const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; + +#[derive(Copy, Clone)] +pub enum WriteMode { + Overwrite, + // str is the extension of the new file + NewFile(&'static str), + // Write the output to stdout. + Display, + // Return the result as a mapping from filenames to StringBuffers. + Return(&'static Fn(HashMap)), +} + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum BraceStyle { + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +// How to indent a function's return type. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum ReturnIndent { + // Aligned with the arguments + WithArgs, + // Aligned with the where clause + WithWhereClause, +} + +// Formatting which depends on the AST. +fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { + let mut visitor = FmtVisitor::from_codemap(codemap); + visit::walk_crate(&mut visitor, krate); + let files = codemap.files.borrow(); + if let Some(last) = files.last() { + visitor.format_missing(last.end_pos); + } + + visitor.changes +} + +// Formatting done on a char by char or line by line basis. +// TODO warn on TODOs and FIXMEs without an issue number +// TODO warn on bad license +// TODO other stuff for parity with make tidy +fn fmt_lines(changes: &mut ChangeSet) { + let mut truncate_todo = Vec::new(); + + // Iterate over the chars in the change set. + for (f, text) in changes.text() { + let mut trims = vec![]; + let mut last_wspace: Option = None; + let mut line_len = 0; + let mut cur_line = 1; + let mut newline_count = 0; + for (c, b) in text.chars() { + if c == '\n' { // TOOD test for \r too + // Check for (and record) trailing whitespace. + if let Some(lw) = last_wspace { + trims.push((cur_line, lw, b)); + line_len -= b - lw; + } + // Check for any line width errors we couldn't correct. + if line_len > MAX_WIDTH { + // TODO store the error rather than reporting immediately. + println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", + f, cur_line, MAX_WIDTH); + } + line_len = 0; + cur_line += 1; + newline_count += 1; + last_wspace = None; + } else { + newline_count = 0; + line_len += 1; + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(b); + } + } else { + last_wspace = None; + } + } + } + + if newline_count > 1 { + debug!("track truncate: {} {} {}", f, text.len, newline_count); + truncate_todo.push((f.to_string(), text.len - newline_count + 1)) + } + + for &(l, _, _) in trims.iter() { + // TODO store the error rather than reporting immediately. + println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); + } + } + + for (f, l) in truncate_todo { + changes.get_mut(&f).truncate(l); + } +} + +struct RustFmtCalls { + input_path: Option, + write_mode: WriteMode, +} + +impl<'a> CompilerCalls<'a> for RustFmtCalls { + fn early_callback(&mut self, + _: &getopts::Matches, + _: &diagnostics::registry::Registry) + -> Compilation { + Compilation::Continue + } + + fn some_input(&mut self, + input: Input, + input_path: Option) + -> (Input, Option) { + match input_path { + Some(ref ip) => self.input_path = Some(ip.clone()), + _ => { + // FIXME should handle string input and write to stdout or something + panic!("No input path"); + } + } + (input, input_path) + } + + fn no_input(&mut self, + _: &getopts::Matches, + _: &config::Options, + _: &Option, + _: &Option, + _: &diagnostics::registry::Registry) + -> Option<(Input, Option)> { + panic!("No input supplied to RustFmt"); + } + + fn late_callback(&mut self, + _: &getopts::Matches, + _: &Session, + _: &Input, + _: &Option, + _: &Option) + -> Compilation { + Compilation::Continue + } + + fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { + let write_mode = self.write_mode; + let mut control = driver::CompileController::basic(); + control.after_parse.stop = Compilation::Stop; + control.after_parse.callback = box move |state| { + let krate = state.krate.unwrap(); + let codemap = state.session.codemap(); + let mut changes = fmt_ast(krate, codemap); + // For some reason, the codemap does not include terminating newlines + // so we must add one on for each file. This is sad. + changes.append_newlines(); + fmt_lines(&mut changes); + + // FIXME(#5) Should be user specified whether to show or replace. + let result = changes.write_all_files(write_mode); + + match result { + Err(msg) => println!("Error writing files: {}", msg), + Ok(result) => { + if let WriteMode::Return(callback) = write_mode { + callback(result); + } + } + } + }; + + control + } +} + +fn run(args: Vec, write_mode: WriteMode) { + let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; + rustc_driver::run_compiler(&args, &mut call_ctxt); +} + +#[cfg(not(test))] +fn main() { + let args: Vec<_> = std::env::args().collect(); + //run(args, WriteMode::Display); + run(args, WriteMode::Overwrite); + std::env::set_exit_status(0); + + // TODO unit tests + // let fmt = ListFormatting { + // tactic: ListTactic::Horizontal, + // separator: ",", + // trailing_separator: SeparatorTactic::Vertical, + // indent: 2, + // h_width: 80, + // v_width: 100, + // }; + // let inputs = vec![(format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new())]; + // let s = write_list(&inputs, &fmt); + // println!(" {}", s); +} + + +#[cfg(test)] +mod test { + use std::collections::HashMap; + use std::fs; + use std::io::Read; + use std::sync::atomic; + use super::*; + use super::run; + + // For now, the only supported regression tests are idempotent tests - the input and + // output must match exactly. + // FIXME(#28) would be good to check for error messages and fail on them, or at least report. + #[test] + fn idempotent_tests() { + println!("Idempotent tests:"); + FAILURES.store(0, atomic::Ordering::Relaxed); + + // Get all files in the tests/idem directory + let files = fs::read_dir("tests/idem").unwrap(); + // For each file, run rustfmt and collect the output + let mut count = 0; + for entry in files { + let path = entry.unwrap().path(); + let file_name = path.to_str().unwrap(); + println!("Testing '{}'...", file_name); + run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); + count += 1; + } + // And also dogfood ourselves! + println!("Testing 'src/main.rs'..."); + run(vec!["rustfmt".to_string(), "src/main.rs".to_string()], + WriteMode::Return(HANDLE_RESULT)); + count += 1; + + // Display results + let fails = FAILURES.load(atomic::Ordering::Relaxed); + println!("Ran {} idempotent tests; {} failures.", count, fails); + assert!(fails == 0, "{} idempotent tests failed", fails); + } + + // 'global' used by sys_tests and handle_result. + static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; + // Ick, just needed to get a &'static to handle_result. + static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; + + // Compare output to input. + fn handle_result(result: HashMap) { + let mut fails = 0; + + for file_name in result.keys() { + let mut f = fs::File::open(file_name).unwrap(); + let mut text = String::new(); + f.read_to_string(&mut text).unwrap(); + if result[file_name] != text { + fails += 1; + println!("Mismatch in {}.", file_name); + println!("{}", result[file_name]); + } + } + + if fails > 0 { + FAILURES.fetch_add(1, atomic::Ordering::Relaxed); + } + } +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e16537198f6..00000000000 --- a/src/main.rs +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(box_syntax)] -#![feature(box_patterns)] -#![feature(rustc_private)] -#![feature(collections)] -#![feature(str_char)] - -#![cfg_attr(not(test), feature(exit_status))] - -// TODO we're going to allocate a whole bunch of temp Strings, is it worth -// keeping some scratch mem for this and running our own StrPool? -// TODO for lint violations of names, emit a refactor script - - -#[macro_use] -extern crate log; - -extern crate getopts; -extern crate rustc; -extern crate rustc_driver; -extern crate syntax; - -extern crate strings; - -use rustc::session::Session; -use rustc::session::config::{self, Input}; -use rustc_driver::{driver, CompilerCalls, Compilation}; - -use syntax::ast; -use syntax::codemap::CodeMap; -use syntax::diagnostics; -use syntax::visit; - -use std::path::PathBuf; -use std::collections::HashMap; - -use changes::ChangeSet; -use visitor::FmtVisitor; - -mod changes; -mod visitor; -mod functions; -mod missed_spans; -mod lists; -mod utils; -mod types; -mod expr; -mod imports; - -const IDEAL_WIDTH: usize = 80; -const LEEWAY: usize = 5; -const MAX_WIDTH: usize = 100; -const MIN_STRING: usize = 10; -const TAB_SPACES: usize = 4; -const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; -const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; -// When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; - -#[derive(Copy, Clone)] -pub enum WriteMode { - Overwrite, - // str is the extension of the new file - NewFile(&'static str), - // Write the output to stdout. - Display, - // Return the result as a mapping from filenames to StringBuffers. - Return(&'static Fn(HashMap)), -} - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum BraceStyle { - AlwaysNextLine, - PreferSameLine, - // Prefer same line except where there is a where clause, in which case force - // the brace to the next line. - SameLineWhere, -} - -// How to indent a function's return type. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum ReturnIndent { - // Aligned with the arguments - WithArgs, - // Aligned with the where clause - WithWhereClause, -} - -// Formatting which depends on the AST. -fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut visitor = FmtVisitor::from_codemap(codemap); - visit::walk_crate(&mut visitor, krate); - let files = codemap.files.borrow(); - if let Some(last) = files.last() { - visitor.format_missing(last.end_pos); - } - - visitor.changes -} - -// Formatting done on a char by char or line by line basis. -// TODO warn on TODOs and FIXMEs without an issue number -// TODO warn on bad license -// TODO other stuff for parity with make tidy -fn fmt_lines(changes: &mut ChangeSet) { - let mut truncate_todo = Vec::new(); - - // Iterate over the chars in the change set. - for (f, text) in changes.text() { - let mut trims = vec![]; - let mut last_wspace: Option = None; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - for (c, b) in text.chars() { - if c == '\n' { // TOOD test for \r too - // Check for (and record) trailing whitespace. - if let Some(lw) = last_wspace { - trims.push((cur_line, lw, b)); - line_len -= b - lw; - } - // Check for any line width errors we couldn't correct. - if line_len > MAX_WIDTH { - // TODO store the error rather than reporting immediately. - println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", - f, cur_line, MAX_WIDTH); - } - line_len = 0; - cur_line += 1; - newline_count += 1; - last_wspace = None; - } else { - newline_count = 0; - line_len += 1; - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(b); - } - } else { - last_wspace = None; - } - } - } - - if newline_count > 1 { - debug!("track truncate: {} {} {}", f, text.len, newline_count); - truncate_todo.push((f.to_string(), text.len - newline_count + 1)) - } - - for &(l, _, _) in trims.iter() { - // TODO store the error rather than reporting immediately. - println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); - } - } - - for (f, l) in truncate_todo { - changes.get_mut(&f).truncate(l); - } -} - -struct RustFmtCalls { - input_path: Option, - write_mode: WriteMode, -} - -impl<'a> CompilerCalls<'a> for RustFmtCalls { - fn early_callback(&mut self, - _: &getopts::Matches, - _: &diagnostics::registry::Registry) - -> Compilation { - Compilation::Continue - } - - fn some_input(&mut self, - input: Input, - input_path: Option) - -> (Input, Option) { - match input_path { - Some(ref ip) => self.input_path = Some(ip.clone()), - _ => { - // FIXME should handle string input and write to stdout or something - panic!("No input path"); - } - } - (input, input_path) - } - - fn no_input(&mut self, - _: &getopts::Matches, - _: &config::Options, - _: &Option, - _: &Option, - _: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { - panic!("No input supplied to RustFmt"); - } - - fn late_callback(&mut self, - _: &getopts::Matches, - _: &Session, - _: &Input, - _: &Option, - _: &Option) - -> Compilation { - Compilation::Continue - } - - fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { - let write_mode = self.write_mode; - let mut control = driver::CompileController::basic(); - control.after_parse.stop = Compilation::Stop; - control.after_parse.callback = box move |state| { - let krate = state.krate.unwrap(); - let codemap = state.session.codemap(); - let mut changes = fmt_ast(krate, codemap); - // For some reason, the codemap does not include terminating newlines - // so we must add one on for each file. This is sad. - changes.append_newlines(); - fmt_lines(&mut changes); - - // FIXME(#5) Should be user specified whether to show or replace. - let result = changes.write_all_files(write_mode); - - match result { - Err(msg) => println!("Error writing files: {}", msg), - Ok(result) => { - if let WriteMode::Return(callback) = write_mode { - callback(result); - } - } - } - }; - - control - } -} - -fn run(args: Vec, write_mode: WriteMode) { - let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; - rustc_driver::run_compiler(&args, &mut call_ctxt); -} - -#[cfg(not(test))] -fn main() { - let args: Vec<_> = std::env::args().collect(); - //run(args, WriteMode::Display); - run(args, WriteMode::Overwrite); - std::env::set_exit_status(0); - - // TODO unit tests - // let fmt = ListFormatting { - // tactic: ListTactic::Horizontal, - // separator: ",", - // trailing_separator: SeparatorTactic::Vertical, - // indent: 2, - // h_width: 80, - // v_width: 100, - // }; - // let inputs = vec![(format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new())]; - // let s = write_list(&inputs, &fmt); - // println!(" {}", s); -} - - -#[cfg(test)] -mod test { - use std::collections::HashMap; - use std::fs; - use std::io::Read; - use std::sync::atomic; - use super::*; - use super::run; - - // For now, the only supported regression tests are idempotent tests - the input and - // output must match exactly. - // FIXME(#28) would be good to check for error messages and fail on them, or at least report. - #[test] - fn idempotent_tests() { - println!("Idempotent tests:"); - FAILURES.store(0, atomic::Ordering::Relaxed); - - // Get all files in the tests/idem directory - let files = fs::read_dir("tests/idem").unwrap(); - // For each file, run rustfmt and collect the output - let mut count = 0; - for entry in files { - let path = entry.unwrap().path(); - let file_name = path.to_str().unwrap(); - println!("Testing '{}'...", file_name); - run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); - count += 1; - } - // And also dogfood ourselves! - println!("Testing 'src/main.rs'..."); - run(vec!["rustfmt".to_string(), "src/main.rs".to_string()], - WriteMode::Return(HANDLE_RESULT)); - count += 1; - - // Display results - let fails = FAILURES.load(atomic::Ordering::Relaxed); - println!("Ran {} idempotent tests; {} failures.", count, fails); - assert!(fails == 0, "{} idempotent tests failed", fails); - } - - // 'global' used by sys_tests and handle_result. - static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; - // Ick, just needed to get a &'static to handle_result. - static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; - - // Compare output to input. - fn handle_result(result: HashMap) { - let mut fails = 0; - - for file_name in result.keys() { - let mut f = fs::File::open(file_name).unwrap(); - let mut text = String::new(); - f.read_to_string(&mut text).unwrap(); - if result[file_name] != text { - fails += 1; - println!("Mismatch in {}.", file_name); - println!("{}", result[file_name]); - } - } - - if fails > 0 { - FAILURES.fetch_add(1, atomic::Ordering::Relaxed); - } - } -} -- cgit 1.4.1-3-g733a5 From 62e583d4cfc1a5c9135bff3f2bb9414cfac6882d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 1 May 2015 18:43:36 +0200 Subject: split main function and test function into their own files small modifications to make executable and test compile properly --- src/bin/rustfmt.rs | 42 +++++++++++++++++++++++ src/lib.rs | 99 +----------------------------------------------------- tests/idem.rs | 73 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 98 deletions(-) create mode 100644 src/bin/rustfmt.rs create mode 100644 tests/idem.rs (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs new file mode 100644 index 00000000000..67b2e6316a6 --- /dev/null +++ b/src/bin/rustfmt.rs @@ -0,0 +1,42 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(exit_status)] + +extern crate rustfmt; + +use rustfmt::{WriteMode, run}; + +fn main() { + let args: Vec<_> = std::env::args().collect(); + //run(args, WriteMode::Display); + run(args, WriteMode::Overwrite); + std::env::set_exit_status(0); + + // TODO unit tests + // let fmt = ListFormatting { + // tactic: ListTactic::Horizontal, + // separator: ",", + // trailing_separator: SeparatorTactic::Vertical, + // indent: 2, + // h_width: 80, + // v_width: 100, + // }; + // let inputs = vec![(format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new()), + // (format!("foo"), String::new())]; + // let s = write_list(&inputs, &fmt); + // println!(" {}", s); +} diff --git a/src/lib.rs b/src/lib.rs index e16537198f6..e22a0861390 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,6 @@ #![feature(collections)] #![feature(str_char)] -#![cfg_attr(not(test), feature(exit_status))] - // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? // TODO for lint violations of names, emit a refactor script @@ -244,102 +242,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } } -fn run(args: Vec, write_mode: WriteMode) { +pub fn run(args: Vec, write_mode: WriteMode) { let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; rustc_driver::run_compiler(&args, &mut call_ctxt); } - -#[cfg(not(test))] -fn main() { - let args: Vec<_> = std::env::args().collect(); - //run(args, WriteMode::Display); - run(args, WriteMode::Overwrite); - std::env::set_exit_status(0); - - // TODO unit tests - // let fmt = ListFormatting { - // tactic: ListTactic::Horizontal, - // separator: ",", - // trailing_separator: SeparatorTactic::Vertical, - // indent: 2, - // h_width: 80, - // v_width: 100, - // }; - // let inputs = vec![(format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new())]; - // let s = write_list(&inputs, &fmt); - // println!(" {}", s); -} - - -#[cfg(test)] -mod test { - use std::collections::HashMap; - use std::fs; - use std::io::Read; - use std::sync::atomic; - use super::*; - use super::run; - - // For now, the only supported regression tests are idempotent tests - the input and - // output must match exactly. - // FIXME(#28) would be good to check for error messages and fail on them, or at least report. - #[test] - fn idempotent_tests() { - println!("Idempotent tests:"); - FAILURES.store(0, atomic::Ordering::Relaxed); - - // Get all files in the tests/idem directory - let files = fs::read_dir("tests/idem").unwrap(); - // For each file, run rustfmt and collect the output - let mut count = 0; - for entry in files { - let path = entry.unwrap().path(); - let file_name = path.to_str().unwrap(); - println!("Testing '{}'...", file_name); - run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); - count += 1; - } - // And also dogfood ourselves! - println!("Testing 'src/main.rs'..."); - run(vec!["rustfmt".to_string(), "src/main.rs".to_string()], - WriteMode::Return(HANDLE_RESULT)); - count += 1; - - // Display results - let fails = FAILURES.load(atomic::Ordering::Relaxed); - println!("Ran {} idempotent tests; {} failures.", count, fails); - assert!(fails == 0, "{} idempotent tests failed", fails); - } - - // 'global' used by sys_tests and handle_result. - static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; - // Ick, just needed to get a &'static to handle_result. - static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; - - // Compare output to input. - fn handle_result(result: HashMap) { - let mut fails = 0; - - for file_name in result.keys() { - let mut f = fs::File::open(file_name).unwrap(); - let mut text = String::new(); - f.read_to_string(&mut text).unwrap(); - if result[file_name] != text { - fails += 1; - println!("Mismatch in {}.", file_name); - println!("{}", result[file_name]); - } - } - - if fails > 0 { - FAILURES.fetch_add(1, atomic::Ordering::Relaxed); - } - } -} diff --git a/tests/idem.rs b/tests/idem.rs new file mode 100644 index 00000000000..a82d326087e --- /dev/null +++ b/tests/idem.rs @@ -0,0 +1,73 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate rustfmt; + +use std::collections::HashMap; +use std::fs; +use std::io::Read; +use std::sync::atomic; +use rustfmt::*; + +// For now, the only supported regression tests are idempotent tests - the input and +// output must match exactly. +// FIXME(#28) would be good to check for error messages and fail on them, or at least report. +#[test] +fn idempotent_tests() { + println!("Idempotent tests:"); + FAILURES.store(0, atomic::Ordering::Relaxed); + + // Get all files in the tests/idem directory + let files = fs::read_dir("tests/idem").unwrap(); + // For each file, run rustfmt and collect the output + let mut count = 0; + for entry in files { + let path = entry.unwrap().path(); + let file_name = path.to_str().unwrap(); + println!("Testing '{}'...", file_name); + run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT)); + count += 1; + } + // And also dogfood ourselves! + println!("Testing 'src/lib.rs'..."); + run(vec!["rustfmt".to_string(), "src/lib.rs".to_string()], + WriteMode::Return(HANDLE_RESULT)); + count += 1; + + // Display results + let fails = FAILURES.load(atomic::Ordering::Relaxed); + println!("Ran {} idempotent tests; {} failures.", count, fails); + assert!(fails == 0, "{} idempotent tests failed", fails); +} + +// 'global' used by sys_tests and handle_result. +static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; +// Ick, just needed to get a &'static to handle_result. +static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; + +// Compare output to input. +fn handle_result(result: HashMap) { + let mut fails = 0; + + for file_name in result.keys() { + let mut f = fs::File::open(file_name).unwrap(); + let mut text = String::new(); + f.read_to_string(&mut text).unwrap(); + if result[file_name] != text { + fails += 1; + println!("Mismatch in {}.", file_name); + println!("{}", result[file_name]); + } + } + + if fails > 0 { + FAILURES.fetch_add(1, atomic::Ordering::Relaxed); + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 59554dd5e1121d39cc9c1d716277de03c153a46b Mon Sep 17 00:00:00 2001 From: defyrlt Date: Fri, 1 May 2015 14:08:22 +0300 Subject: Resolved #56 -- `mut` was eaten out of `mut self` in fn args. --- src/functions.rs | 17 ++++++++++++++++- tests/idem/fn.rs | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/functions.rs b/src/functions.rs index 3d6fcb88c25..d4f06c1c7ac 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -164,7 +164,22 @@ impl<'a> FmtVisitor<'a> { arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); } ast::ExplicitSelf_::SelfValue(_) => { - arg_item_strs[0] = "self".to_owned(); + assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); + + // this hacky solution caused by absence of `Mutability` in `SelfValue`. + let mut_str = { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) + = args[0].pat.node { + match mutability { + ast::Mutability::MutMutable => "mut ", + ast::Mutability::MutImmutable => "", + } + } else { + panic!("there is a bug or change in structure of AST, aborting."); + } + }; + + arg_item_strs[0] = format!("{}self", mut_str); min_args = 2; } _ => {} diff --git a/tests/idem/fn.rs b/tests/idem/fn.rs index aec27597b7a..62a059dc464 100644 --- a/tests/idem/fn.rs +++ b/tests/idem/fn.rs @@ -39,6 +39,12 @@ impl Foo { where F: FnOnce(&mut Resolver) -> T { } + + fn foo(mut self, mut bar: u32) { + } + + fn bar(self, mut bazz: u32) { + } } pub fn render<'a, -- cgit 1.4.1-3-g733a5 From 59352172b3539c1ecd3a03919fc7e06a7c06af4a Mon Sep 17 00:00:00 2001 From: Matthew Hall Date: Fri, 1 May 2015 17:27:54 +0100 Subject: Change import lists with one item to single import Changes lists such as ``use std::{fmt}`` to a form without a list, eg ``use std::fmt``. --- src/imports.rs | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index d29e9eb6e84..aea983e261f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -18,10 +18,28 @@ use syntax::print::pprust; use {IDEAL_WIDTH, MAX_WIDTH}; -// TODO change import lists with one item to a single import -// remove empty lists (if they're even possible) +// TODO remove empty lists (if they're even possible) // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import +fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem, vis: &str) -> String { + if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { + let name_str = token::get_ident(name).to_string(); + if path_str.len() == 0 { + format!("{}use {};", vis, name_str) + } else { + format!("{}use {}::{};", vis, path_str, name_str) + } + } else { + if path_str.len() != 0 { + format!("{}use {};", vis, path_str) + } else { + // This catches the import: use {self}, which is a compiler error, so we just + // leave it alone. + format!("{}use {{self}};", vis) + } + } +} + impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. pub fn rewrite_use_list(&mut self, @@ -29,9 +47,6 @@ impl<'a> FmtVisitor<'a> { path_list: &[ast::PathListItem], visibility: ast::Visibility, vp_span: Span) -> String { - // FIXME check indentation - let l_loc = self.codemap.lookup_char_pos(vp_span.lo); - let path_str = pprust::path_to_string(&path); let vis = match visibility { @@ -39,6 +54,13 @@ impl<'a> FmtVisitor<'a> { _ => "" }; + if path_list.len() == 1 { + return rewrite_single_use_list(path_str, path_list[0], vis); + } + + // FIXME check indentation + let l_loc = self.codemap.lookup_char_pos(vp_span.lo); + // 1 = { let mut indent = l_loc.col.0 + path_str.len() + 1; if path_str.len() > 0 { -- cgit 1.4.1-3-g733a5 From 58a14fbc793f6a3522ebe4db736a664f3271772a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 2 May 2015 19:12:16 +0200 Subject: Correctly indent use items and functions --- src/imports.rs | 46 ++++++++++++++++++---------------------------- src/visitor.rs | 24 ++++++++++++++---------- tests/idem/imports.rs | 13 +++++++++++++ 3 files changed, 45 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index d29e9eb6e84..9cdd89df0cb 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -12,12 +12,9 @@ use visitor::FmtVisitor; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use syntax::ast; -use syntax::codemap::Span; use syntax::parse::token; use syntax::print::pprust; -use {IDEAL_WIDTH, MAX_WIDTH}; - // TODO change import lists with one item to a single import // remove empty lists (if they're even possible) // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import @@ -25,13 +22,11 @@ use {IDEAL_WIDTH, MAX_WIDTH}; impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. pub fn rewrite_use_list(&mut self, + block_indent: usize, + budget: usize, // excluding indentation path: &ast::Path, path_list: &[ast::PathListItem], - visibility: ast::Visibility, - vp_span: Span) -> String { - // FIXME check indentation - let l_loc = self.codemap.lookup_char_pos(vp_span.lo); - + visibility: ast::Visibility) -> Option { let path_str = pprust::path_to_string(&path); let vis = match visibility { @@ -39,31 +34,26 @@ impl<'a> FmtVisitor<'a> { _ => "" }; - // 1 = { - let mut indent = l_loc.col.0 + path_str.len() + 1; - if path_str.len() > 0 { - // 2 = :: - indent += 2; - } + // 2 = :: + let path_separation_w = if path_str.len() > 0 { 2 } else { 0 }; + // 5 = "use " + { + let indent = path_str.len() + 5 + path_separation_w + vis.len(); // 2 = } + ; - let used_width = indent + 2 + vis.len(); - let budget = if used_width >= IDEAL_WIDTH { - if used_width < MAX_WIDTH { - MAX_WIDTH - used_width - } else { - // Give up - return String::new(); - } + let used_width = indent + 2; + + let remaining_budget = if used_width >= budget { + return None; } else { - IDEAL_WIDTH - used_width + budget - used_width }; + let fmt = ListFormatting { tactic: ListTactic::Mixed, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: indent, - h_width: budget, - v_width: budget, + indent: block_indent + indent, + h_width: remaining_budget, + v_width: remaining_budget, }; // TODO handle any comments inbetween items. @@ -89,10 +79,10 @@ impl<'a> FmtVisitor<'a> { ast::PathListItem_::PathListMod{ .. } => None, } })).collect(); - if path_str.len() == 0 { + Some(if path_str.len() == 0 { format!("{}use {{{}}};", vis, write_list(&items, &fmt)) } else { format!("{}use {}::{{{}}};", vis, path_str, write_list(&items, &fmt)) - } + }) } } diff --git a/src/visitor.rs b/src/visitor.rs index 138be5f3636..b4fe95c9dd3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -14,7 +14,7 @@ use syntax::visit; use utils; -use {MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION}; +use {IDEAL_WIDTH, MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION}; use changes::ChangeSet; pub struct FmtVisitor<'a> { @@ -93,7 +93,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { - self.format_missing(s.lo); + self.format_missing_with_indent(s.lo); self.last_pos = s.lo; let indent = self.block_indent; @@ -145,20 +145,24 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match item.node { ast::Item_::ItemUse(ref vp) => { + self.format_missing_with_indent(item.span.lo); match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { - self.format_missing(item.span.lo); - let new_str = self.rewrite_use_list(path, - path_list, - item.vis, - vp.span); - self.changes.push_str_span(item.span, &new_str); - self.last_pos = item.span.hi; + let block_indent = self.block_indent; + let budget = IDEAL_WIDTH - block_indent; + if let Some(new_str) = self.rewrite_use_list(block_indent, + budget, + path, + path_list, + item.vis) { + self.changes.push_str_span(item.span, &new_str); + self.last_pos = item.span.hi; + } } ast::ViewPath_::ViewPathGlob(_) => { // FIXME convert to list? } - _ => {} + ast::ViewPath_::ViewPathSimple(_,_) => {} } visit::walk_item(self, item); } diff --git a/tests/idem/imports.rs b/tests/idem/imports.rs index 13910c8a628..72c4a1fb769 100644 --- a/tests/idem/imports.rs +++ b/tests/idem/imports.rs @@ -8,3 +8,16 @@ use {Foo, Bar}; use Foo::{Bar, Baz}; pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; + +mod Foo { + pub use syntax::ast::{Expr_, ExprEval, ToExpr, ExprMethodCall, ToExprPath}; + + mod Foo2 { + pub use syntax::ast::{Expr_, ExprEval, ToExpr, ExprMethodCall, + ToExprPath}; + } +} + +fn test() { + use Baz::*; +} -- cgit 1.4.1-3-g733a5 From 1655583b02578150d2ef08e16bda0c8bfe8194aa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Apr 2015 13:13:20 +0200 Subject: handle windows newlines --- src/changes.rs | 44 +++++++++++++++++++++++++++++++++++++------- src/lib.rs | 7 +++++++ 2 files changed, 44 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 8884b05d77e..f0aebe7c94f 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -18,8 +18,10 @@ use std::collections::HashMap; use syntax::codemap::{CodeMap, Span, BytePos}; use std::fmt; use std::fs::File; -use std::io::Write; +use std::io::{Write, stdout}; use WriteMode; +use NEWLINE_STYLE; +use NewlineStyle; // This is basically a wrapper around a bunch of Ropes which makes it convenient // to work with libsyntax. It is badly named. @@ -148,6 +150,28 @@ impl<'a> ChangeSet<'a> { -> Result, ::std::io::Error> { let text = &self.file_map[filename]; + // prints all newlines either as `\n` or as `\r\n` + fn write_system_newlines( + mut writer: T, + text: &StringBuffer) + -> Result<(), ::std::io::Error> + where T: Write, + { + match NEWLINE_STYLE { + NewlineStyle::Unix => write!(writer, "{}", text), + NewlineStyle::Windows => { + for (c, _) in text.chars() { + match c { + '\n' => try!(write!(writer, "\r\n")), + '\r' => continue, + c => try!(write!(writer, "{}", c)), + } + } + Ok(()) + }, + } + } + match mode { WriteMode::Overwrite => { // Do a little dance to make writing safer - write to a temp file @@ -157,8 +181,8 @@ impl<'a> ChangeSet<'a> { let bk_name = filename.to_owned() + ".bk"; { // Write text to temp file - let mut tmp_file = try!(File::create(&tmp_name)); - try!(write!(tmp_file, "{}", text)); + let tmp_file = try!(File::create(&tmp_name)); + try!(write_system_newlines(tmp_file, text)); } try!(::std::fs::rename(filename, bk_name)); @@ -166,15 +190,21 @@ impl<'a> ChangeSet<'a> { } WriteMode::NewFile(extn) => { let filename = filename.to_owned() + "." + extn; - let mut file = try!(File::create(&filename)); - try!(write!(file, "{}", text)); + let file = try!(File::create(&filename)); + try!(write_system_newlines(file, text)); } WriteMode::Display => { println!("{}:\n", filename); - println!("{}", text); + let stdout = stdout(); + let stdout_lock = stdout.lock(); + try!(write_system_newlines(stdout_lock, text)); } WriteMode::Return(_) => { - return Ok(Some(text.to_string())); + // io::Write is not implemented for String, working around with Vec + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text)); + // won't panic, we are writing correct utf8 + return Ok(Some(String::from_utf8(v).unwrap())); } } diff --git a/src/lib.rs b/src/lib.rs index e22a0861390..cf191f04f95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,7 @@ const LEEWAY: usize = 5; const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; const TAB_SPACES: usize = 4; +const NEWLINE_STYLE: NewlineStyle = NewlineStyle::Unix; const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; // When we get scoped annotations, we should have rustfmt::skip. @@ -75,6 +76,12 @@ pub enum WriteMode { Return(&'static Fn(HashMap)), } +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +enum NewlineStyle { + Windows, // \r\n + Unix, // \n +} + #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum BraceStyle { AlwaysNextLine, -- cgit 1.4.1-3-g733a5 From cd3b032e11f71ecdb640d9270c63a2d2019eb315 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 4 May 2015 14:32:48 +0200 Subject: prevent bogus whitespace error messages due to \r --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cf191f04f95..34a801dd369 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,7 +127,8 @@ fn fmt_lines(changes: &mut ChangeSet) { let mut cur_line = 1; let mut newline_count = 0; for (c, b) in text.chars() { - if c == '\n' { // TOOD test for \r too + if c == '\r' { continue; } + if c == '\n' { // Check for (and record) trailing whitespace. if let Some(lw) = last_wspace { trims.push((cur_line, lw, b)); -- cgit 1.4.1-3-g733a5 From c790d7d5507118598b7f25cc00e07217046c5f53 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 4 May 2015 17:16:51 +0200 Subject: Keep import lists on a single line when possible --- src/imports.rs | 25 ++++++++++++++++--------- src/lists.rs | 16 +++++++++++----- src/visitor.rs | 19 ++++++++++--------- tests/idem/imports.rs | 14 +++++++------- 4 files changed, 44 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9cdd89df0cb..9968d8b5315 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -23,10 +23,11 @@ impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. pub fn rewrite_use_list(&mut self, block_indent: usize, - budget: usize, // excluding indentation + one_line_budget: usize, // excluding indentation + multi_line_budget: usize, path: &ast::Path, path_list: &[ast::PathListItem], - visibility: ast::Visibility) -> Option { + visibility: ast::Visibility) -> String { let path_str = pprust::path_to_string(&path); let vis = match visibility { @@ -41,10 +42,16 @@ impl<'a> FmtVisitor<'a> { // 2 = } + ; let used_width = indent + 2; - let remaining_budget = if used_width >= budget { - return None; + // Break as early as possible when we've blown our budget. + let remaining_line_budget = if used_width > one_line_budget { + 0 } else { - budget - used_width + one_line_budget - used_width + }; + let remaining_multi_budget = if used_width > multi_line_budget { + 0 + } else { + multi_line_budget - used_width }; let fmt = ListFormatting { @@ -52,8 +59,8 @@ impl<'a> FmtVisitor<'a> { separator: ",", trailing_separator: SeparatorTactic::Never, indent: block_indent + indent, - h_width: remaining_budget, - v_width: remaining_budget, + h_width: remaining_line_budget, + v_width: remaining_multi_budget, }; // TODO handle any comments inbetween items. @@ -79,10 +86,10 @@ impl<'a> FmtVisitor<'a> { ast::PathListItem_::PathListMod{ .. } => None, } })).collect(); - Some(if path_str.len() == 0 { + if path_str.len() == 0 { format!("{}use {{{}}};", vis, write_list(&items, &fmt)) } else { format!("{}use {}::{{{}}};", vis, path_str, write_list(&items, &fmt)) - }) + } } } diff --git a/src/lists.rs b/src/lists.rs index 47b6491544d..06fb93f71e1 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -58,18 +58,24 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b }; let sep_len = formatting.separator.len(); let total_sep_len = (sep_len + 1) * sep_count; - let total_width = calculate_width(items); + let fits_single = total_width + total_sep_len <= formatting.h_width; // Check if we need to fallback from horizontal listing, if possible. if tactic == ListTactic::HorizontalVertical { debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", total_width, total_sep_len, formatting.h_width); - if total_width + total_sep_len > formatting.h_width { - tactic = ListTactic::Vertical; + tactic = if fits_single { + ListTactic::Horizontal } else { - tactic = ListTactic::Horizontal; - } + ListTactic::Vertical + }; + } + + // Check if we can fit everything on a single line in mixed mode. + // The horizontal tactic does not break after v_width columns. + if tactic == ListTactic::Mixed && fits_single { + tactic = ListTactic::Horizontal; } // Now that we know how we will layout, we can decide for sure if there diff --git a/src/visitor.rs b/src/visitor.rs index b4fe95c9dd3..55957464ef7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -149,15 +149,16 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { let block_indent = self.block_indent; - let budget = IDEAL_WIDTH - block_indent; - if let Some(new_str) = self.rewrite_use_list(block_indent, - budget, - path, - path_list, - item.vis) { - self.changes.push_str_span(item.span, &new_str); - self.last_pos = item.span.hi; - } + let one_line_budget = MAX_WIDTH - block_indent; + let multi_line_budget = IDEAL_WIDTH - block_indent; + let new_str = self.rewrite_use_list(block_indent, + one_line_budget, + multi_line_budget, + path, + path_list, + item.vis); + self.changes.push_str_span(item.span, &new_str); + self.last_pos = item.span.hi; } ast::ViewPath_::ViewPathGlob(_) => { // FIXME convert to list? diff --git a/tests/idem/imports.rs b/tests/idem/imports.rs index 72c4a1fb769..9644c62dde7 100644 --- a/tests/idem/imports.rs +++ b/tests/idem/imports.rs @@ -1,20 +1,20 @@ // Imports. // Long import. -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, - ItemDefaultImpl}; +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; use {Foo, Bar}; use Foo::{Bar, Baz}; -pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, - ExprPath}; +pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; mod Foo { - pub use syntax::ast::{Expr_, ExprEval, ToExpr, ExprMethodCall, ToExprPath}; + pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; mod Foo2 { - pub use syntax::ast::{Expr_, ExprEval, ToExpr, ExprMethodCall, - ToExprPath}; + pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, + ItemStatic, ItemDefaultImpl}; } } -- cgit 1.4.1-3-g733a5 From 853b58901b101e9ff3bbc6288ee4214cd9c232d7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 11 May 2015 15:05:12 +0200 Subject: typo --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index b4fe95c9dd3..1ca958f27b2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -85,7 +85,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = b.span.hi; } - // Note that this only gets called for function defintions. Required methods + // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. fn visit_fn(&mut self, fk: visit::FnKind<'v>, -- cgit 1.4.1-3-g733a5 From 4aa35187035b551d27045b6c712979b6fecbd74f Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 4 May 2015 00:12:39 +0200 Subject: Format required methods on traits --- src/bin/rustfmt.rs | 1 + src/functions.rs | 89 +++++++++++++++++++++++++++++++++++++++++++---------- src/visitor.rs | 19 ++++++++++-- tests/idem/trait.rs | 20 ++++++++++++ 4 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 tests/idem/trait.rs (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 67b2e6316a6..32c38ea15e4 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg(not(test))] #![feature(exit_status)] extern crate rustfmt; diff --git a/src/functions.rs b/src/functions.rs index d4f06c1c7ac..2133b7c4418 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -28,15 +28,79 @@ impl<'a> FmtVisitor<'a> { unsafety: &ast::Unsafety, abi: &abi::Abi, vis: ast::Visibility, - next_span: Span) // next_span is a nasty hack, its a loose upper - // bound on any comments after the where clause. + span_end: BytePos) + -> String + { + let newline_brace = self.newline_for_brace(&generics.where_clause); + + let mut result = self.rewrite_fn_base(indent, + ident, + fd, + explicit_self, + generics, + unsafety, + abi, + vis, + span_end, + newline_brace); + + // Prepare for the function body by possibly adding a newline and indent. + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + if newline_brace { + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + + result + } + + pub fn rewrite_required_fn(&mut self, + indent: usize, + ident: ast::Ident, + sig: &ast::MethodSig, + span: Span) + -> String + { + // Drop semicolon or it will be interpreted as comment + let span_end = span.hi - BytePos(1); + + let mut result = self.rewrite_fn_base(indent, + ident, + &sig.decl, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.abi, + ast::Visibility::Inherited, + span_end, + false); + + // Re-attach semicolon + result.push(';'); + + result + } + + fn rewrite_fn_base(&mut self, + indent: usize, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: &ast::Unsafety, + abi: &abi::Abi, + vis: ast::Visibility, + span_end: BytePos, + newline_brace: bool) -> String { // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. let where_clause = &generics.where_clause; - let newline_brace = self.newline_for_brace(where_clause); let mut result = String::with_capacity(1024); // Vis unsafety abi. @@ -104,7 +168,7 @@ impl<'a> FmtVisitor<'a> { // Comment between return type and the end of the decl. let snippet_lo = fd.output.span().hi; if where_clause.predicates.len() == 0 { - let snippet_hi = next_span.lo; + let snippet_hi = span_end; let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); let snippet = snippet.trim(); if snippet.len() > 0 { @@ -119,17 +183,7 @@ impl<'a> FmtVisitor<'a> { } // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent, next_span)); - - // Prepare for the function body by possibly adding a newline and indent. - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. - if newline_brace { - result.push('\n'); - result.push_str(&make_indent(self.block_indent)); - } else { - result.push(' '); - } + result.push_str(&self.rewrite_where_clause(where_clause, indent, span_end)); result } @@ -396,7 +450,7 @@ impl<'a> FmtVisitor<'a> { fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, indent: usize, - next_span: Span) + span_end: BytePos) -> String { let mut result = String::new(); @@ -414,7 +468,8 @@ impl<'a> FmtVisitor<'a> { "{", |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - next_span.lo); + span_end); + let where_strs: Vec<_> = where_clause.predicates.iter() .map(|p| (self.rewrite_pred(p))) .zip(comments.into_iter()) diff --git a/src/visitor.rs b/src/visitor.rs index 382dce97050..3cc9b36222b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -107,7 +107,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { unsafety, abi, vis, - b.span); + b.span.lo); self.changes.push_str_span(s, &new_fn); } visit::FkMethod(ident, ref sig, vis) => { @@ -119,7 +119,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &sig.unsafety, &sig.abi, vis.unwrap_or(ast::Visibility::Inherited), - b.span); + b.span.lo); self.changes.push_str_span(s, &new_fn); } visit::FkFnBlock(..) => {} @@ -190,6 +190,21 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { if self.visit_attrs(&ti.attrs) { return; } + + if let ast::TraitItem_::MethodTraitItem(ref sig, None) = ti.node { + self.format_missing_with_indent(ti.span.lo); + + let indent = self.block_indent; + let new_fn = self.rewrite_required_fn(indent, + ti.ident, + sig, + ti.span); + + self.changes.push_str_span(ti.span, &new_fn); + self.last_pos = ti.span.hi; + } + // TODO format trait types + visit::walk_trait_item(self, ti) } diff --git a/tests/idem/trait.rs b/tests/idem/trait.rs new file mode 100644 index 00000000000..8f7f4be67c9 --- /dev/null +++ b/tests/idem/trait.rs @@ -0,0 +1,20 @@ +// Test traits + +trait Foo { + fn bar(x: i32) -> Baz { + Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; + + fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType; // Some comment + + fn baz(&mut self) -> i32; + + fn increment(&mut self, x: i32); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where R: Read; +} -- cgit 1.4.1-3-g733a5 From 2fbb445b671405e40aaf9eeaaecdd08340d67fd9 Mon Sep 17 00:00:00 2001 From: Alex HotShot Newman Date: Wed, 20 May 2015 11:20:15 -0700 Subject: Remove old box syntax --- src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 34a801dd369..08ee465dddf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(box_syntax)] -#![feature(box_patterns)] #![feature(rustc_private)] #![feature(collections)] #![feature(str_char)] @@ -224,7 +222,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { let write_mode = self.write_mode; let mut control = driver::CompileController::basic(); control.after_parse.stop = Compilation::Stop; - control.after_parse.callback = box move |state| { + control.after_parse.callback = Box::new(move |state| { let krate = state.krate.unwrap(); let codemap = state.session.codemap(); let mut changes = fmt_ast(krate, codemap); @@ -244,7 +242,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } } } - }; + }); control } -- cgit 1.4.1-3-g733a5 From aa6f7e8d3cad4ee2737d9dce662977f216e01096 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 23 May 2015 15:28:41 +1200 Subject: Add default.toml and modify the build system for it --- Cargo.lock | 14 ++++++++++++++ Cargo.toml | 2 ++ build.rs | 28 ++++++++++++++++++++++++++++ src/default.toml | 2 ++ 4 files changed, 46 insertions(+) create mode 100644 build.rs create mode 100644 src/default.toml (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 60496ff2ccd..a1534ecd913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,6 +4,7 @@ version = "0.0.1" dependencies = [ "diff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", + "toml 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -11,8 +12,21 @@ name = "diff" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-serialize" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strings" version = "0.0.1" source = "git+https://github.com/nrc/strings.rs.git#551331d01911b7e8da056a4a019eb367cfaf03bd" +[[package]] +name = "toml" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + diff --git a/Cargo.toml b/Cargo.toml index a78a31d11c3..acf53b77e7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/nick29581/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" +build = "build.rs" [dependencies.strings] strings = "0.0.1" @@ -14,3 +15,4 @@ git = "https://github.com/nrc/strings.rs.git" [dev-dependencies] diff = "0.1.0" +toml = "0.1.20" diff --git a/build.rs b/build.rs new file mode 100644 index 00000000000..ac27db56493 --- /dev/null +++ b/build.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Build script. Just copies default.toml from the src to the target dir. + +use std::env; +use std::path::{Path, PathBuf}; + +fn main() { + let in_file = Path::new("src/default.toml"); + + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let profile = env::var("PROFILE").unwrap(); + let mut out_file = PathBuf::new(); + out_file.push(manifest_dir); + out_file.push("target"); + out_file.push(profile); + out_file.push("default.toml"); + + std::fs::copy(in_file, out_file).unwrap(); +} diff --git a/src/default.toml b/src/default.toml new file mode 100644 index 00000000000..e049dfa59ba --- /dev/null +++ b/src/default.toml @@ -0,0 +1,2 @@ +max-width = 100 +ideal-width = 80 -- cgit 1.4.1-3-g733a5 From 1a09a6d00a782db90501c0921dd4c7587f6eba72 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 23 May 2015 17:02:59 +1200 Subject: Use config file for constants --- Cargo.lock | 1 + Cargo.toml | 5 +++- build.rs | 3 --- src/bin/rustfmt.rs | 12 +++++++-- src/changes.rs | 3 +-- src/default.toml | 9 +++++-- src/expr.rs | 4 +-- src/functions.rs | 21 ++++++++-------- src/lib.rs | 73 +++++++++++++++++++++++++++++++++++++++++++----------- src/visitor.rs | 16 ++++++------ tests/idem.rs | 24 ++++++++++-------- 11 files changed, 115 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index a1534ecd913..297e4f65fe1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,6 +3,7 @@ name = "rustfmt" version = "0.0.1" dependencies = [ "diff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", "toml 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index acf53b77e7c..f76d45d39c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,9 @@ build = "build.rs" strings = "0.0.1" git = "https://github.com/nrc/strings.rs.git" +[dependencies] +toml = "0.1.20" +rustc-serialize = "0.3.14" + [dev-dependencies] diff = "0.1.0" -toml = "0.1.20" diff --git a/build.rs b/build.rs index ac27db56493..3e6d051d9b1 100644 --- a/build.rs +++ b/build.rs @@ -17,11 +17,8 @@ fn main() { let in_file = Path::new("src/default.toml"); let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - let profile = env::var("PROFILE").unwrap(); let mut out_file = PathBuf::new(); out_file.push(manifest_dir); - out_file.push("target"); - out_file.push(profile); out_file.push("default.toml"); std::fs::copy(in_file, out_file).unwrap(); diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 32c38ea15e4..5a12dbd639b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -15,10 +15,18 @@ extern crate rustfmt; use rustfmt::{WriteMode, run}; +use std::fs::File; +use std::io::Read; + fn main() { let args: Vec<_> = std::env::args().collect(); - //run(args, WriteMode::Display); - run(args, WriteMode::Overwrite); + let mut def_config_file = File::open("default.toml").unwrap(); + let mut def_config = String::new(); + def_config_file.read_to_string(&mut def_config).unwrap(); + + //run(args, WriteMode::Display, &def_config); + run(args, WriteMode::Overwrite, &def_config); + std::env::set_exit_status(0); // TODO unit tests diff --git a/src/changes.rs b/src/changes.rs index f0aebe7c94f..5ed1c82b22f 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -20,7 +20,6 @@ use std::fmt; use std::fs::File; use std::io::{Write, stdout}; use WriteMode; -use NEWLINE_STYLE; use NewlineStyle; // This is basically a wrapper around a bunch of Ropes which makes it convenient @@ -157,7 +156,7 @@ impl<'a> ChangeSet<'a> { -> Result<(), ::std::io::Error> where T: Write, { - match NEWLINE_STYLE { + match config!(newline_style) { NewlineStyle::Unix => write!(writer, "{}", text), NewlineStyle::Windows => { for (c, _) in text.chars() { diff --git a/src/default.toml b/src/default.toml index e049dfa59ba..218f2a04fb2 100644 --- a/src/default.toml +++ b/src/default.toml @@ -1,2 +1,7 @@ -max-width = 100 -ideal-width = 80 +max_width = 100 +ideal_width = 80 +leeway = 5 +tab_spaces = 4 +newline_style = "Unix" +fn_brace_style = "SameLineWhere" +fn_return_indent = "WithArgs" diff --git a/src/expr.rs b/src/expr.rs index 1da66c4e328..c1cbf175645 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -15,7 +15,7 @@ use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use syntax::{ast, ptr}; use syntax::codemap::{Span, Pos}; -use {MAX_WIDTH, MIN_STRING}; +use MIN_STRING; impl<'a> FmtVisitor<'a> { // TODO NEEDS TESTS @@ -26,7 +26,7 @@ impl<'a> FmtVisitor<'a> { // strings, or if the string is too long for the line. let l_loc = self.codemap.lookup_char_pos(span.lo); let r_loc = self.codemap.lookup_char_pos(span.hi); - if l_loc.line == r_loc.line && r_loc.col.to_usize() <= MAX_WIDTH { + if l_loc.line == r_loc.line && r_loc.col.to_usize() <= config!(max_width) { return self.snippet(span); } diff --git a/src/functions.rs b/src/functions.rs index 2133b7c4418..2ca5423f0c8 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {ReturnIndent, MAX_WIDTH, BraceStyle, - IDEAL_WIDTH, LEEWAY, FN_BRACE_STYLE, FN_RETURN_INDENT}; +use {ReturnIndent, BraceStyle}; use utils::make_indent; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use visitor::FmtVisitor; @@ -149,8 +148,8 @@ impl<'a> FmtVisitor<'a> { // If we've already gone multi-line, or the return type would push // over the max width, then put the return type on a new line. if result.contains("\n") || - result.len() + indent + ret_str.len() > MAX_WIDTH { - let indent = match FN_RETURN_INDENT { + result.len() + indent + ret_str.len() > config!(max_width) { + let indent = match config!(fn_return_indent) { ReturnIndent::WithWhereClause => indent + 4, // TODO we might want to check that using the arg indent doesn't // blow our budget, and if it does, then fallback to the where @@ -344,15 +343,15 @@ impl<'a> FmtVisitor<'a> { if !newline_brace { used_space += 2; } - let one_line_budget = if used_space > MAX_WIDTH { + let one_line_budget = if used_space > config!(max_width) { 0 } else { - MAX_WIDTH - used_space + config!(max_width) - used_space }; // 2 = `()` let used_space = indent + result.len() + 2; - let max_space = IDEAL_WIDTH + LEEWAY; + let max_space = config!(ideal_width) + config!(leeway); debug!("compute_budgets_for_args: used_space: {}, max_space: {}", used_space, max_space); if used_space < max_space { @@ -368,7 +367,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&make_indent(indent + 4)); // 6 = new indent + `()` let used_space = indent + 6; - let max_space = IDEAL_WIDTH + LEEWAY; + let max_space = config!(ideal_width) + config!(leeway); if used_space > max_space { // Whoops! bankrupt. // TODO take evasive action, perhaps kill the indent or something. @@ -382,7 +381,7 @@ impl<'a> FmtVisitor<'a> { } fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { - match FN_BRACE_STYLE { + match config!(fn_brace_style) { BraceStyle::AlwaysNextLine => true, BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, _ => false, @@ -399,7 +398,7 @@ impl<'a> FmtVisitor<'a> { return result; } - let budget = MAX_WIDTH - indent - 2; + let budget = config!(max_width) - indent - 2; // TODO might need to insert a newline if the generics are really long result.push('<'); @@ -475,7 +474,7 @@ impl<'a> FmtVisitor<'a> { .zip(comments.into_iter()) .collect(); - let budget = IDEAL_WIDTH + LEEWAY - indent - 10; + let budget = config!(ideal_width) + config!(leeway) - indent - 10; let fmt = ListFormatting { tactic: ListTactic::Vertical, separator: ",", diff --git a/src/lib.rs b/src/lib.rs index 08ee465dddf..1c0fe0105ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,13 +24,17 @@ extern crate getopts; extern crate rustc; extern crate rustc_driver; extern crate syntax; +extern crate rustc_serialize; extern crate strings; use rustc::session::Session; -use rustc::session::config::{self, Input}; +use rustc::session::config as rustc_config; +use rustc::session::config::Input; use rustc_driver::{driver, CompilerCalls, Compilation}; +use rustc_serialize::{Decodable, Decoder}; + use syntax::ast; use syntax::codemap::CodeMap; use syntax::diagnostics; @@ -42,6 +46,8 @@ use std::collections::HashMap; use changes::ChangeSet; use visitor::FmtVisitor; +#[macro_use] +mod config; mod changes; mod visitor; mod functions; @@ -52,17 +58,12 @@ mod types; mod expr; mod imports; -const IDEAL_WIDTH: usize = 80; -const LEEWAY: usize = 5; -const MAX_WIDTH: usize = 100; const MIN_STRING: usize = 10; -const TAB_SPACES: usize = 4; -const NEWLINE_STYLE: NewlineStyle = NewlineStyle::Unix; -const FN_BRACE_STYLE: BraceStyle = BraceStyle::SameLineWhere; -const FN_RETURN_INDENT: ReturnIndent = ReturnIndent::WithArgs; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; +static mut CONFIG: Option = None; + #[derive(Copy, Clone)] pub enum WriteMode { Overwrite, @@ -75,13 +76,24 @@ pub enum WriteMode { } #[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum NewlineStyle { +pub enum NewlineStyle { Windows, // \r\n Unix, // \n } +impl Decodable for NewlineStyle { + fn decode(d: &mut D) -> Result { + let s = try!(d.read_str()); + match &*s { + "Windows" => Ok(NewlineStyle::Windows), + "Unix" => Ok(NewlineStyle::Unix), + _ => Err(d.error("Bad variant")), + } + } +} + #[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum BraceStyle { +pub enum BraceStyle { AlwaysNextLine, PreferSameLine, // Prefer same line except where there is a where clause, in which case force @@ -89,15 +101,39 @@ enum BraceStyle { SameLineWhere, } +impl Decodable for BraceStyle { + fn decode(d: &mut D) -> Result { + let s = try!(d.read_str()); + match &*s { + "AlwaysNextLine" => Ok(BraceStyle::AlwaysNextLine), + "PreferSameLine" => Ok(BraceStyle::PreferSameLine), + "SameLineWhere" => Ok(BraceStyle::SameLineWhere), + _ => Err(d.error("Bad variant")), + } + } +} + // How to indent a function's return type. #[derive(Copy, Clone, Eq, PartialEq, Debug)] -enum ReturnIndent { +pub enum ReturnIndent { // Aligned with the arguments WithArgs, // Aligned with the where clause WithWhereClause, } +// TODO could use a macro for all these Decodable impls. +impl Decodable for ReturnIndent { + fn decode(d: &mut D) -> Result { + let s = try!(d.read_str()); + match &*s { + "WithArgs" => Ok(ReturnIndent::WithArgs), + "WithWhereClause" => Ok(ReturnIndent::WithWhereClause), + _ => Err(d.error("Bad variant")), + } + } +} + // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { let mut visitor = FmtVisitor::from_codemap(codemap); @@ -133,10 +169,10 @@ fn fmt_lines(changes: &mut ChangeSet) { line_len -= b - lw; } // Check for any line width errors we couldn't correct. - if line_len > MAX_WIDTH { + if line_len > config!(max_width) { // TODO store the error rather than reporting immediately. println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", - f, cur_line, MAX_WIDTH); + f, cur_line, config!(max_width)); } line_len = 0; cur_line += 1; @@ -200,7 +236,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { fn no_input(&mut self, _: &getopts::Matches, - _: &config::Options, + _: &rustc_config::Options, _: &Option, _: &Option, _: &diagnostics::registry::Registry) @@ -248,7 +284,14 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } } -pub fn run(args: Vec, write_mode: WriteMode) { +// args are the arguments passed on the command line, generally passed through +// to the compiler. +// write_mode determines what happens to the result of running rustfmt, see +// WriteMode. +// default_config is a string of toml data to be used to configure rustfmt. +pub fn run(args: Vec, write_mode: WriteMode, default_config: &str) { + config::set_config(default_config); + let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; rustc_driver::run_compiler(&args, &mut call_ctxt); } diff --git a/src/visitor.rs b/src/visitor.rs index 3cc9b36222b..2aac931c4e6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -14,7 +14,7 @@ use syntax::visit; use utils; -use {IDEAL_WIDTH, MAX_WIDTH, TAB_SPACES, SKIP_ANNOTATION}; +use SKIP_ANNOTATION; use changes::ChangeSet; pub struct FmtVisitor<'a> { @@ -32,7 +32,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); - let new_str = self.rewrite_expr(ex, MAX_WIDTH - offset, offset); + let new_str = self.rewrite_expr(ex, config!(max_width) - offset, offset); self.changes.push_str_span(ex.span, &new_str); self.last_pos = ex.span.hi; } @@ -65,7 +65,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.changes.push_str_span(b.span, "{"); self.last_pos = self.last_pos + BytePos(1); - self.block_indent += TAB_SPACES; + self.block_indent += config!(tab_spaces); for stmt in &b.stmts { self.visit_stmt(&stmt) @@ -78,7 +78,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { None => {} } - self.block_indent -= TAB_SPACES; + self.block_indent -= config!(tab_spaces); // TODO we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - BytePos(1)); self.changes.push_str_span(b.span, "}"); @@ -149,8 +149,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { let block_indent = self.block_indent; - let one_line_budget = MAX_WIDTH - block_indent; - let multi_line_budget = IDEAL_WIDTH - block_indent; + let one_line_budget = config!(max_width) - block_indent; + let multi_line_budget = config!(ideal_width) - block_indent; let new_str = self.rewrite_use_list(block_indent, one_line_budget, multi_line_budget, @@ -170,9 +170,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { ast::Item_::ItemImpl(..) | ast::Item_::ItemMod(_) | ast::Item_::ItemTrait(..) => { - self.block_indent += TAB_SPACES; + self.block_indent += config!(tab_spaces); visit::walk_item(self, item); - self.block_indent -= TAB_SPACES; + self.block_indent -= config!(tab_spaces); } ast::Item_::ItemExternCrate(_) => { self.format_missing_with_indent(item.span.lo); diff --git a/tests/idem.rs b/tests/idem.rs index 1b74b1aa83e..40474b8dfee 100644 --- a/tests/idem.rs +++ b/tests/idem.rs @@ -58,7 +58,6 @@ fn idempotent_tests() { // Compare output to input. fn print_mismatches(result: HashMap) { for (file_name, fmt_text) in result { - println!("Mismatch in {}.", file_name); println!("{}", fmt_text); } } @@ -68,14 +67,16 @@ static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; pub fn idempotent_check(filename: String) -> Result<(), HashMap> { let args = vec!["rustfmt".to_owned(), filename]; + let mut def_config_file = fs::File::open("default.toml").unwrap(); + let mut def_config = String::new(); + def_config_file.read_to_string(&mut def_config).unwrap(); // this thread is not used for concurrency, but rather to workaround the issue that the passed // function handle needs to have static lifetime. Instead of using a global RefCell, we use // panic to return a result in case of failure. This has the advantage of smoothing the road to // multithreaded rustfmt thread::catch_panic(move || { - run(args, WriteMode::Return(HANDLE_RESULT)); + run(args, WriteMode::Return(HANDLE_RESULT), &def_config); }).map_err(|any| - // i know it is a hashmap *any.downcast().unwrap() ) } @@ -90,8 +91,8 @@ fn handle_result(result: HashMap) { // TODO: speedup by running through bytes iterator f.read_to_string(&mut text).unwrap(); if fmt_text != text { - show_diff(&file_name, &fmt_text, &text); - failures.insert(file_name, fmt_text); + let diff_str = make_diff(&file_name, &fmt_text, &text); + failures.insert(file_name, diff_str); } } if !failures.is_empty() { @@ -100,24 +101,25 @@ fn handle_result(result: HashMap) { } -fn show_diff(file_name: &str, expected: &str, actual: &str) { +fn make_diff(file_name: &str, expected: &str, actual: &str) -> String { let mut line_number = 1; let mut prev_both = true; + let mut text = String::new(); for result in diff::lines(expected, actual) { match result { diff::Result::Left(str) => { if prev_both { - println!("Mismatch @ {}:{}", file_name, line_number); + text.push_str(&format!("Mismatch @ {}:{}\n", file_name, line_number)); } - println!("-{}⏎", str); + text.push_str(&format!("-{}⏎\n", str)); prev_both = false; } diff::Result::Right(str) => { if prev_both { - println!("Mismatch @ {}:{}", file_name, line_number); + text.push_str(&format!("Mismatch @ {}:{}\n", file_name, line_number)); } - println!("+{}⏎", str); + text.push_str(&format!("+{}⏎\n", str)); prev_both = false; line_number += 1; } @@ -127,4 +129,6 @@ fn show_diff(file_name: &str, expected: &str, actual: &str) { } } } + + text } -- cgit 1.4.1-3-g733a5 From 6a5ef17eb12e1599ac6e14e267eaa6a246488cc2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 23 May 2015 22:25:36 +1200 Subject: Add config.rs which I forgot for the last commit Closes #73 --- src/config.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 - 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/config.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 00000000000..d1045293ee3 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,42 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate toml; + +#[derive(RustcDecodable)] +pub struct Config { + pub max_width: usize, + pub ideal_width: usize, + pub leeway: usize, + pub tab_spaces: usize, + pub newline_style: ::NewlineStyle, + pub fn_brace_style: ::BraceStyle, + pub fn_return_indent: ::ReturnIndent, +} + +impl Config { + fn from_toml(toml: &str) -> Config { + println!("About to parse: {}", toml); + let parsed = toml.parse().unwrap(); + toml::decode(parsed).unwrap() + } +} + +pub fn set_config(toml: &str) { + unsafe { + ::CONFIG = Some(Config::from_toml(toml)); + } +} + +macro_rules! config { + ($name: ident) => { + unsafe { ::CONFIG.as_ref().unwrap().$name } + }; +} diff --git a/src/lib.rs b/src/lib.rs index 1c0fe0105ef..386c39ad472 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -267,7 +267,6 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { changes.append_newlines(); fmt_lines(&mut changes); - // FIXME(#5) Should be user specified whether to show or replace. let result = changes.write_all_files(write_mode); match result { -- cgit 1.4.1-3-g733a5 From 0baeca5829b745f4fdd3f29a24e6413b8421ce02 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 24 May 2015 19:57:13 +0200 Subject: Add rewrite for ExprParen --- src/expr.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c1cbf175645..66a79a3a777 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -125,6 +125,23 @@ impl<'a> FmtVisitor<'a> { format!("{}({})", callee_str, args_str) } + fn rewrite_paren(&mut self, subexpr: &ast::Expr, width: usize, offset: usize) -> String { + debug!("rewrite_paren, width: {}, offset: {}", width, offset); + // 1 is for opening paren + let subexpr_str = self.rewrite_expr(subexpr, width-1, offset+1); + debug!("rewrite_paren, subexpr_str: `{}`", subexpr_str); + let mut lines = subexpr_str.rsplit('\n'); + let last_line_len = lines.next().unwrap().len(); + let last_line_offset = if lines.next().is_none() {offset+1} else {0}; + if width + offset - last_line_offset - last_line_len > 0 { + format!("({})", subexpr_str) + } else { + // FIXME That's correct unless we have width < 2. Return an Optrion for such cases ? + format!("({}\n{} )", subexpr_str, make_indent(offset)) + } + } + + pub fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { match expr.node { ast::Expr_::ExprLit(ref l) => { @@ -140,6 +157,9 @@ impl<'a> FmtVisitor<'a> { ast::Expr_::ExprCall(ref callee, ref args) => { return self.rewrite_call(callee, args, width, offset); } + ast::Expr_::ExprParen(ref subexpr) => { + return self.rewrite_paren(subexpr, width, offset); + } _ => {} } -- cgit 1.4.1-3-g733a5 From c1fc693c5e5676f93a331a0498dc6ba36193cd66 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 24 May 2015 23:35:40 +0200 Subject: syle correction --- src/expr.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 66a79a3a777..c242322a51d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -132,11 +132,14 @@ impl<'a> FmtVisitor<'a> { debug!("rewrite_paren, subexpr_str: `{}`", subexpr_str); let mut lines = subexpr_str.rsplit('\n'); let last_line_len = lines.next().unwrap().len(); - let last_line_offset = if lines.next().is_none() {offset+1} else {0}; + let last_line_offset = match lines.next() { + None => offset+1, + Some(_) => 0, + }; if width + offset - last_line_offset - last_line_len > 0 { format!("({})", subexpr_str) } else { - // FIXME That's correct unless we have width < 2. Return an Optrion for such cases ? + // FIXME That's correct unless we have width < 2. Return an Option for such cases ? format!("({}\n{} )", subexpr_str, make_indent(offset)) } } -- cgit 1.4.1-3-g733a5 From 09bd4a74e4dfa64fd1223662eef71bf6bd9c2f44 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 24 May 2015 23:46:02 +0200 Subject: Avoid dangling ) --- src/expr.rs | 19 ++++--------------- tests/idem/paren.rs | 13 ++----------- 2 files changed, 6 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c242322a51d..79234eb7f13 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -127,24 +127,13 @@ impl<'a> FmtVisitor<'a> { fn rewrite_paren(&mut self, subexpr: &ast::Expr, width: usize, offset: usize) -> String { debug!("rewrite_paren, width: {}, offset: {}", width, offset); - // 1 is for opening paren - let subexpr_str = self.rewrite_expr(subexpr, width-1, offset+1); + // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing + // paren on the same line as the subexpr + let subexpr_str = self.rewrite_expr(subexpr, width-2, offset+1); debug!("rewrite_paren, subexpr_str: `{}`", subexpr_str); - let mut lines = subexpr_str.rsplit('\n'); - let last_line_len = lines.next().unwrap().len(); - let last_line_offset = match lines.next() { - None => offset+1, - Some(_) => 0, - }; - if width + offset - last_line_offset - last_line_len > 0 { - format!("({})", subexpr_str) - } else { - // FIXME That's correct unless we have width < 2. Return an Option for such cases ? - format!("({}\n{} )", subexpr_str, make_indent(offset)) - } + format!("({})", subexpr_str) } - pub fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { match expr.node { ast::Expr_::ExprLit(ref l) => { diff --git a/tests/idem/paren.rs b/tests/idem/paren.rs index f04068e3462..98169883575 100644 --- a/tests/idem/paren.rs +++ b/tests/idem/paren.rs @@ -2,15 +2,6 @@ fn foo() { let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = (write + something + here + to + fill + the + line + 12 + 34 + 567 - ); - let very_long_variable_name = (write + something + here + to + fill + the + line + 12 + 34 + 567 - + 78); - let very_long_variable_name = (write + something + here + to + fill + the + line + 12 + 34 + 567 - + 78 + fill + another + line + AAAA + BBBBBBB + CCCCCCCCCCCCCCCCC - ); - let very_long_variable_name = (write + something + here + to + fill + the + line + 12 + 34 + 567 - + 78 + fill + another + line + AAAA + BBBBBBB + CCCCCCCCCCCCCCC + - DDDDDDD + EEEEEE); - + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBBB + + b + c); } -- cgit 1.4.1-3-g733a5 From e7adf64155abb3bdc2dcb6bb52ee24ed87206eff Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 25 May 2015 11:03:26 +1200 Subject: Format structs --- src/bin/rustfmt.rs | 4 +- src/config.rs | 1 - src/functions.rs | 537 ----------------------------------------- src/items.rs | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/visitor.rs | 11 +- tests/idem.rs | 2 +- tests/idem/structs.rs | 37 +++ 8 files changed, 708 insertions(+), 543 deletions(-) delete mode 100644 src/functions.rs create mode 100644 src/items.rs create mode 100644 tests/idem/structs.rs (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5a12dbd639b..3b87ac7eb03 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -24,8 +24,8 @@ fn main() { let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).unwrap(); - //run(args, WriteMode::Display, &def_config); - run(args, WriteMode::Overwrite, &def_config); + run(args, WriteMode::Display, &def_config); + //run(args, WriteMode::Overwrite, &def_config); std::env::set_exit_status(0); diff --git a/src/config.rs b/src/config.rs index d1045293ee3..080926b03a2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,7 +23,6 @@ pub struct Config { impl Config { fn from_toml(toml: &str) -> Config { - println!("About to parse: {}", toml); let parsed = toml.parse().unwrap(); toml::decode(parsed).unwrap() } diff --git a/src/functions.rs b/src/functions.rs deleted file mode 100644 index 2ca5423f0c8..00000000000 --- a/src/functions.rs +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use {ReturnIndent, BraceStyle}; -use utils::make_indent; -use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; -use visitor::FmtVisitor; -use syntax::{ast, abi}; -use syntax::codemap::{self, Span, BytePos}; -use syntax::print::pprust; -use syntax::parse::token; - -impl<'a> FmtVisitor<'a> { - pub fn rewrite_fn(&mut self, - indent: usize, - ident: ast::Ident, - fd: &ast::FnDecl, - explicit_self: Option<&ast::ExplicitSelf>, - generics: &ast::Generics, - unsafety: &ast::Unsafety, - abi: &abi::Abi, - vis: ast::Visibility, - span_end: BytePos) - -> String - { - let newline_brace = self.newline_for_brace(&generics.where_clause); - - let mut result = self.rewrite_fn_base(indent, - ident, - fd, - explicit_self, - generics, - unsafety, - abi, - vis, - span_end, - newline_brace); - - // Prepare for the function body by possibly adding a newline and indent. - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. - if newline_brace { - result.push('\n'); - result.push_str(&make_indent(indent)); - } else { - result.push(' '); - } - - result - } - - pub fn rewrite_required_fn(&mut self, - indent: usize, - ident: ast::Ident, - sig: &ast::MethodSig, - span: Span) - -> String - { - // Drop semicolon or it will be interpreted as comment - let span_end = span.hi - BytePos(1); - - let mut result = self.rewrite_fn_base(indent, - ident, - &sig.decl, - Some(&sig.explicit_self), - &sig.generics, - &sig.unsafety, - &sig.abi, - ast::Visibility::Inherited, - span_end, - false); - - // Re-attach semicolon - result.push(';'); - - result - } - - fn rewrite_fn_base(&mut self, - indent: usize, - ident: ast::Ident, - fd: &ast::FnDecl, - explicit_self: Option<&ast::ExplicitSelf>, - generics: &ast::Generics, - unsafety: &ast::Unsafety, - abi: &abi::Abi, - vis: ast::Visibility, - span_end: BytePos, - newline_brace: bool) - -> String - { - // FIXME we'll lose any comments in between parts of the function decl, but anyone - // who comments there probably deserves what they get. - - let where_clause = &generics.where_clause; - - let mut result = String::with_capacity(1024); - // Vis unsafety abi. - if vis == ast::Visibility::Public { - result.push_str("pub "); - } - if let &ast::Unsafety::Unsafe = unsafety { - result.push_str("unsafe "); - } - if *abi != abi::Rust { - result.push_str("extern "); - result.push_str(&abi.to_string()); - result.push(' '); - } - - // fn foo - result.push_str("fn "); - result.push_str(&token::get_ident(ident)); - - // Generics. - let generics_indent = indent + result.len(); - result.push_str(&self.rewrite_generics(generics, - generics_indent, - span_for_return(&fd.output))); - - let ret_str = self.rewrite_return(&fd.output); - - // Args. - let (one_line_budget, multi_line_budget, arg_indent) = - self.compute_budgets_for_args(&mut result, indent, ret_str.len(), newline_brace); - - debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", - one_line_budget, multi_line_budget, arg_indent); - - result.push('('); - result.push_str(&self.rewrite_args(&fd.inputs, - explicit_self, - one_line_budget, - multi_line_budget, - arg_indent, - span_for_return(&fd.output))); - result.push(')'); - - // Return type. - if ret_str.len() > 0 { - // If we've already gone multi-line, or the return type would push - // over the max width, then put the return type on a new line. - if result.contains("\n") || - result.len() + indent + ret_str.len() > config!(max_width) { - let indent = match config!(fn_return_indent) { - ReturnIndent::WithWhereClause => indent + 4, - // TODO we might want to check that using the arg indent doesn't - // blow our budget, and if it does, then fallback to the where - // clause indent. - _ => arg_indent, - }; - - result.push('\n'); - result.push_str(&make_indent(indent)); - } else { - result.push(' '); - } - result.push_str(&ret_str); - - // Comment between return type and the end of the decl. - let snippet_lo = fd.output.span().hi; - if where_clause.predicates.len() == 0 { - let snippet_hi = span_end; - let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); - let snippet = snippet.trim(); - if snippet.len() > 0 { - result.push(' '); - result.push_str(snippet); - } - } else { - // FIXME it would be nice to catch comments between the return type - // and the where clause, but we don't have a span for the where - // clause. - } - } - - // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent, span_end)); - - result - } - - fn rewrite_args(&self, - args: &[ast::Arg], - explicit_self: Option<&ast::ExplicitSelf>, - one_line_budget: usize, - multi_line_budget: usize, - arg_indent: usize, - ret_span: Span) - -> String - { - let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); - // Account for sugary self. - let mut min_args = 1; - if let Some(explicit_self) = explicit_self { - match explicit_self.node { - ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { - let lt_str = match lt { - &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), - &None => String::new(), - }; - let mut_str = match m { - &ast::Mutability::MutMutable => "mut ".to_owned(), - &ast::Mutability::MutImmutable => String::new(), - }; - arg_item_strs[0] = format!("&{}{}self", lt_str, mut_str); - min_args = 2; - } - ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { - arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); - } - ast::ExplicitSelf_::SelfValue(_) => { - assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); - - // this hacky solution caused by absence of `Mutability` in `SelfValue`. - let mut_str = { - if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) - = args[0].pat.node { - match mutability { - ast::Mutability::MutMutable => "mut ", - ast::Mutability::MutImmutable => "", - } - } else { - panic!("there is a bug or change in structure of AST, aborting."); - } - }; - - arg_item_strs[0] = format!("{}self", mut_str); - min_args = 2; - } - _ => {} - } - } - - // Comments between args - let mut arg_comments = Vec::new(); - if min_args == 2 { - arg_comments.push("".to_owned()); - } - // TODO if there are no args, there might still be a comment, but without - // spans for the comment or parens, there is no chance of getting it right. - // You also don't get to put a comment on self, unless it is explicit. - if args.len() >= min_args { - arg_comments = self.make_comments_for_list(arg_comments, - args[min_args-1..].iter(), - ",", - ")", - |arg| arg.pat.span.lo, - |arg| arg.ty.span.hi, - ret_span.lo); - } - - debug!("comments: {:?}", arg_comments); - - // If there are // comments, keep them multi-line. - let mut list_tactic = ListTactic::HorizontalVertical; - if arg_comments.iter().any(|c| c.contains("//")) { - list_tactic = ListTactic::Vertical; - } - - assert_eq!(arg_item_strs.len(), arg_comments.len()); - let arg_strs: Vec<_> = arg_item_strs.into_iter().zip(arg_comments.into_iter()).collect(); - - let fmt = ListFormatting { - tactic: list_tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: arg_indent, - h_width: one_line_budget, - v_width: multi_line_budget, - }; - - write_list(&arg_strs, &fmt) - } - - // Gets comments in between items of a list. - fn make_comments_for_list(&self, - prefix: Vec, - mut it: I, - separator: &str, - terminator: &str, - get_lo: F1, - get_hi: F2, - next_span_start: BytePos) - -> Vec - where I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos - { - let mut result = prefix; - - let mut prev_end = get_hi(&it.next().unwrap()); - for item in it { - let cur_start = get_lo(&item); - let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); - let mut snippet = snippet.trim(); - let white_space: &[_] = &[' ', '\t']; - if snippet.starts_with(separator) { - snippet = snippet[separator.len()..].trim_matches(white_space); - } else if snippet.ends_with(separator) { - snippet = snippet[..snippet.len()-separator.len()].trim_matches(white_space); - } - result.push(snippet.to_owned()); - prev_end = get_hi(&item); - } - // Get the last commment. - // FIXME If you thought the crap with the commas was ugly, just wait. - // This is awful. We're going to look from the last item span to the - // start of the return type span, then we drop everything after the - // first closing paren. Obviously, this will break if there is a - // closing paren in the comment. - // The fix is comments in the AST or a span for the closing paren. - let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); - let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find(terminator) - .unwrap_or(snippet.find(separator).unwrap_or(snippet.len()))]; - let snippet = snippet.trim(); - result.push(snippet.to_owned()); - - result - } - - fn compute_budgets_for_args(&self, - result: &mut String, - indent: usize, - ret_str_len: usize, - newline_brace: bool) - -> (usize, usize, usize) - { - let mut budgets = None; - - // Try keeping everything on the same line - if !result.contains("\n") { - // 3 = `() `, space is before ret_string - let mut used_space = indent + result.len() + ret_str_len + 3; - if !newline_brace { - used_space += 2; - } - let one_line_budget = if used_space > config!(max_width) { - 0 - } else { - config!(max_width) - used_space - }; - - // 2 = `()` - let used_space = indent + result.len() + 2; - let max_space = config!(ideal_width) + config!(leeway); - debug!("compute_budgets_for_args: used_space: {}, max_space: {}", - used_space, max_space); - if used_space < max_space { - budgets = Some((one_line_budget, - max_space - used_space, - indent + result.len() + 1)); - } - } - - // Didn't work. we must force vertical layout and put args on a newline. - if let None = budgets { - result.push('\n'); - result.push_str(&make_indent(indent + 4)); - // 6 = new indent + `()` - let used_space = indent + 6; - let max_space = config!(ideal_width) + config!(leeway); - if used_space > max_space { - // Whoops! bankrupt. - // TODO take evasive action, perhaps kill the indent or something. - } else { - // 5 = new indent + `(` - budgets = Some((0, max_space - used_space, indent + 5)); - } - } - - budgets.unwrap() - } - - fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { - match config!(fn_brace_style) { - BraceStyle::AlwaysNextLine => true, - BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, - _ => false, - } - } - - fn rewrite_generics(&self, generics: &ast::Generics, indent: usize, ret_span: Span) -> String { - // FIXME convert bounds to where clauses where they get too big or if - // there is a where clause at all. - let mut result = String::new(); - let lifetimes: &[_] = &generics.lifetimes; - let tys: &[_] = &generics.ty_params; - if lifetimes.len() + tys.len() == 0 { - return result; - } - - let budget = config!(max_width) - indent - 2; - // TODO might need to insert a newline if the generics are really long - result.push('<'); - - // Strings for the generics. - let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); - let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); - - // Extract comments between generics. - let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.len() == 0 { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - codemap::mk_sp(l.lifetime.span.lo, hi) - }); - let ty_spans = tys.iter().map(span_for_ty_param); - let comments = self.make_comments_for_list(Vec::new(), - lt_spans.chain(ty_spans), - ",", - ">", - |sp| sp.lo, - |sp| sp.hi, - ret_span.lo); - - // If there are // comments, keep them multi-line. - let mut list_tactic = ListTactic::HorizontalVertical; - if comments.iter().any(|c| c.contains("//")) { - list_tactic = ListTactic::Vertical; - } - - let generics_strs: Vec<_> = lt_strs.chain(ty_strs).zip(comments.into_iter()).collect(); - let fmt = ListFormatting { - tactic: list_tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + 1, - h_width: budget, - v_width: budget, - }; - result.push_str(&write_list(&generics_strs, &fmt)); - - result.push('>'); - - result - } - - fn rewrite_where_clause(&self, - where_clause: &ast::WhereClause, - indent: usize, - span_end: BytePos) - -> String - { - let mut result = String::new(); - if where_clause.predicates.len() == 0 { - return result; - } - - result.push('\n'); - result.push_str(&make_indent(indent + 4)); - result.push_str("where "); - - let comments = self.make_comments_for_list(Vec::new(), - where_clause.predicates.iter(), - ",", - "{", - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, - span_end); - - let where_strs: Vec<_> = where_clause.predicates.iter() - .map(|p| (self.rewrite_pred(p))) - .zip(comments.into_iter()) - .collect(); - - let budget = config!(ideal_width) + config!(leeway) - indent - 10; - let fmt = ListFormatting { - tactic: ListTactic::Vertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + 10, - h_width: budget, - v_width: budget, - }; - result.push_str(&write_list(&where_strs, &fmt)); - - result - } - - fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { - match *ret { - ast::FunctionRetTy::DefaultReturn(_) => String::new(), - ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(), - ast::FunctionRetTy::Return(ref ty) => "-> ".to_owned() + &pprust::ty_to_string(ty), - } - } - - // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly - fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { - format!("{}: {}", - pprust::pat_to_string(&arg.pat), - pprust::ty_to_string(&arg.ty)) - } -} - -fn span_for_return(ret: &ast::FunctionRetTy) -> Span { - match *ret { - ast::FunctionRetTy::NoReturn(ref span) | - ast::FunctionRetTy::DefaultReturn(ref span) => span.clone(), - ast::FunctionRetTy::Return(ref ty) => ty.span, - } -} - -fn span_for_ty_param(ty: &ast::TyParam) -> Span { - // Note that ty.span is the span for ty.ident, not the whole item. - let lo = ty.span.lo; - if let Some(ref def) = ty.default { - return codemap::mk_sp(lo, def.span.hi); - } - if ty.bounds.len() == 0 { - return ty.span; - } - let hi = match ty.bounds[ty.bounds.len() - 1] { - ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span.hi, - ast::TyParamBound::RegionTyParamBound(ref l) => l.span.hi, - }; - codemap::mk_sp(lo, hi) -} - -fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { - match *pred { - ast::WherePredicate::BoundPredicate(ref p) => p.span, - ast::WherePredicate::RegionPredicate(ref p) => p.span, - ast::WherePredicate::EqPredicate(ref p) => p.span, - } -} diff --git a/src/items.rs b/src/items.rs new file mode 100644 index 00000000000..a2027d89b88 --- /dev/null +++ b/src/items.rs @@ -0,0 +1,657 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Formatting top-level items - functions, structs, enums, traits, impls. + +use {ReturnIndent, BraceStyle}; +use utils::make_indent; +use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use visitor::FmtVisitor; +use syntax::{ast, abi}; +use syntax::codemap::{self, Span, BytePos}; +use syntax::print::pprust; +use syntax::parse::token; + +impl<'a> FmtVisitor<'a> { + pub fn rewrite_fn(&mut self, + indent: usize, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: &ast::Unsafety, + abi: &abi::Abi, + vis: ast::Visibility, + span_end: BytePos) + -> String + { + let newline_brace = self.newline_for_brace(&generics.where_clause); + + let mut result = self.rewrite_fn_base(indent, + ident, + fd, + explicit_self, + generics, + unsafety, + abi, + vis, + span_end, + newline_brace); + + // Prepare for the function body by possibly adding a newline and indent. + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + if newline_brace { + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + + result + } + + pub fn rewrite_required_fn(&mut self, + indent: usize, + ident: ast::Ident, + sig: &ast::MethodSig, + span: Span) + -> String + { + // Drop semicolon or it will be interpreted as comment + let span_end = span.hi - BytePos(1); + + let mut result = self.rewrite_fn_base(indent, + ident, + &sig.decl, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.abi, + ast::Visibility::Inherited, + span_end, + false); + + // Re-attach semicolon + result.push(';'); + + result + } + + fn rewrite_fn_base(&mut self, + indent: usize, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: &ast::Unsafety, + abi: &abi::Abi, + vis: ast::Visibility, + span_end: BytePos, + newline_brace: bool) + -> String + { + // FIXME we'll lose any comments in between parts of the function decl, but anyone + // who comments there probably deserves what they get. + + let where_clause = &generics.where_clause; + + let mut result = String::with_capacity(1024); + // Vis unsafety abi. + if vis == ast::Visibility::Public { + result.push_str("pub "); + } + if let &ast::Unsafety::Unsafe = unsafety { + result.push_str("unsafe "); + } + if *abi != abi::Rust { + result.push_str("extern "); + result.push_str(&abi.to_string()); + result.push(' '); + } + + // fn foo + result.push_str("fn "); + result.push_str(&token::get_ident(ident)); + + // Generics. + let generics_indent = indent + result.len(); + result.push_str(&self.rewrite_generics(generics, + generics_indent, + span_for_return(&fd.output).lo)); + + let ret_str = self.rewrite_return(&fd.output); + + // Args. + let (one_line_budget, multi_line_budget, arg_indent) = + self.compute_budgets_for_args(&mut result, indent, ret_str.len(), newline_brace); + + debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", + one_line_budget, multi_line_budget, arg_indent); + + result.push('('); + result.push_str(&self.rewrite_args(&fd.inputs, + explicit_self, + one_line_budget, + multi_line_budget, + arg_indent, + span_for_return(&fd.output))); + result.push(')'); + + // Return type. + if ret_str.len() > 0 { + // If we've already gone multi-line, or the return type would push + // over the max width, then put the return type on a new line. + if result.contains("\n") || + result.len() + indent + ret_str.len() > config!(max_width) { + let indent = match config!(fn_return_indent) { + ReturnIndent::WithWhereClause => indent + 4, + // TODO we might want to check that using the arg indent doesn't + // blow our budget, and if it does, then fallback to the where + // clause indent. + _ => arg_indent, + }; + + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + result.push_str(&ret_str); + + // Comment between return type and the end of the decl. + let snippet_lo = fd.output.span().hi; + if where_clause.predicates.len() == 0 { + let snippet_hi = span_end; + let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); + let snippet = snippet.trim(); + if snippet.len() > 0 { + result.push(' '); + result.push_str(snippet); + } + } else { + // FIXME it would be nice to catch comments between the return type + // and the where clause, but we don't have a span for the where + // clause. + } + } + + // Where clause. + result.push_str(&self.rewrite_where_clause(where_clause, indent, span_end)); + + result + } + + fn rewrite_args(&self, + args: &[ast::Arg], + explicit_self: Option<&ast::ExplicitSelf>, + one_line_budget: usize, + multi_line_budget: usize, + arg_indent: usize, + ret_span: Span) + -> String + { + let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); + // Account for sugary self. + let mut min_args = 1; + if let Some(explicit_self) = explicit_self { + match explicit_self.node { + ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { + let lt_str = match lt { + &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), + &None => String::new(), + }; + let mut_str = match m { + &ast::Mutability::MutMutable => "mut ".to_owned(), + &ast::Mutability::MutImmutable => String::new(), + }; + arg_item_strs[0] = format!("&{}{}self", lt_str, mut_str); + min_args = 2; + } + ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { + arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); + } + ast::ExplicitSelf_::SelfValue(_) => { + assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); + + // this hacky solution caused by absence of `Mutability` in `SelfValue`. + let mut_str = { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) + = args[0].pat.node { + match mutability { + ast::Mutability::MutMutable => "mut ", + ast::Mutability::MutImmutable => "", + } + } else { + panic!("there is a bug or change in structure of AST, aborting."); + } + }; + + arg_item_strs[0] = format!("{}self", mut_str); + min_args = 2; + } + _ => {} + } + } + + // Comments between args + let mut arg_comments = Vec::new(); + if min_args == 2 { + arg_comments.push("".to_owned()); + } + // TODO if there are no args, there might still be a comment, but without + // spans for the comment or parens, there is no chance of getting it right. + // You also don't get to put a comment on self, unless it is explicit. + if args.len() >= min_args { + arg_comments = self.make_comments_for_list(arg_comments, + args[min_args-1..].iter(), + ",", + ")", + |arg| arg.pat.span.lo, + |arg| arg.ty.span.hi, + ret_span.lo); + } + + debug!("comments: {:?}", arg_comments); + + // If there are // comments, keep them multi-line. + let mut list_tactic = ListTactic::HorizontalVertical; + if arg_comments.iter().any(|c| c.contains("//")) { + list_tactic = ListTactic::Vertical; + } + + assert_eq!(arg_item_strs.len(), arg_comments.len()); + let arg_strs: Vec<_> = arg_item_strs.into_iter().zip(arg_comments.into_iter()).collect(); + + let fmt = ListFormatting { + tactic: list_tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: arg_indent, + h_width: one_line_budget, + v_width: multi_line_budget, + }; + + write_list(&arg_strs, &fmt) + } + + // Gets comments in between items of a list. + fn make_comments_for_list(&self, + prefix: Vec, + mut it: I, + separator: &str, + terminator: &str, + get_lo: F1, + get_hi: F2, + next_span_start: BytePos) + -> Vec + where I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos + { + let mut result = prefix; + + let mut prev_end = get_hi(&it.next().unwrap()); + for item in it { + let cur_start = get_lo(&item); + let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); + let mut snippet = snippet.trim(); + let white_space: &[_] = &[' ', '\t']; + if snippet.starts_with(separator) { + snippet = snippet[separator.len()..].trim_matches(white_space); + } else if snippet.ends_with(separator) { + snippet = snippet[..snippet.len()-separator.len()].trim_matches(white_space); + } + result.push(snippet.to_owned()); + prev_end = get_hi(&item); + } + // Get the last commment. + // FIXME If you thought the crap with the commas was ugly, just wait. + // This is awful. We're going to look from the last item span to the + // start of the return type span, then we drop everything after the + // first closing paren. Obviously, this will break if there is a + // closing paren in the comment. + // The fix is comments in the AST or a span for the closing paren. + let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); + let snippet = snippet.trim(); + let snippet = &snippet[..snippet.find(terminator) + .unwrap_or(snippet.find(separator).unwrap_or(snippet.len()))]; + let snippet = snippet.trim(); + result.push(snippet.to_owned()); + + result + } + + fn compute_budgets_for_args(&self, + result: &mut String, + indent: usize, + ret_str_len: usize, + newline_brace: bool) + -> (usize, usize, usize) + { + let mut budgets = None; + + // Try keeping everything on the same line + if !result.contains("\n") { + // 3 = `() `, space is before ret_string + let mut used_space = indent + result.len() + ret_str_len + 3; + if !newline_brace { + used_space += 2; + } + let one_line_budget = if used_space > config!(max_width) { + 0 + } else { + config!(max_width) - used_space + }; + + // 2 = `()` + let used_space = indent + result.len() + 2; + let max_space = config!(ideal_width) + config!(leeway); + debug!("compute_budgets_for_args: used_space: {}, max_space: {}", + used_space, max_space); + if used_space < max_space { + budgets = Some((one_line_budget, + max_space - used_space, + indent + result.len() + 1)); + } + } + + // Didn't work. we must force vertical layout and put args on a newline. + if let None = budgets { + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + // 6 = new indent + `()` + let used_space = indent + 6; + let max_space = config!(ideal_width) + config!(leeway); + if used_space > max_space { + // Whoops! bankrupt. + // TODO take evasive action, perhaps kill the indent or something. + } else { + // 5 = new indent + `(` + budgets = Some((0, max_space - used_space, indent + 5)); + } + } + + budgets.unwrap() + } + + fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { + match config!(fn_brace_style) { + BraceStyle::AlwaysNextLine => true, + BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, + _ => false, + } + } + + pub fn visit_struct(&mut self, + ident: ast::Ident, + vis: ast::Visibility, + struct_def: &ast::StructDef, + generics: &ast::Generics, + span: Span) + { + let header_str = self.struct_header(ident, vis); + self.changes.push_str_span(span, &header_str); + + if struct_def.fields.len() == 0 { + assert!(generics.where_clause.predicates.len() == 0, + "No-field struct with where clause?"); + assert!(generics.lifetimes.len() == 0, "No-field struct with generics?"); + assert!(generics.ty_params.len() == 0, "No-field struct with generics?"); + + self.changes.push_str_span(span, ";"); + return; + } + + let mut generics_buf = String::new(); + let generics_str = self.rewrite_generics(generics, self.block_indent, struct_def.fields[0].span.lo); + generics_buf.push_str(&generics_str); + + if generics.where_clause.predicates.len() > 0 { + generics_buf.push_str(&self.rewrite_where_clause(&generics.where_clause, + self.block_indent, + struct_def.fields[0].span.lo)); + generics_buf.push_str(&make_indent(self.block_indent)); + generics_buf.push_str("\n{"); + + } else { + generics_buf.push_str(" {"); + } + self.changes.push_str_span(span, &generics_buf); + + let struct_snippet = self.snippet(span); + // FIXME this will give incorrect results if there is a { in a commet. + self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1); + + self.block_indent += config!(tab_spaces); + for f in &struct_def.fields { + self.visit_field(f, span.lo, &struct_snippet); + } + self.block_indent -= config!(tab_spaces); + + self.format_missing_with_indent(span.lo + BytePos(struct_snippet.rfind('}').unwrap() as u32)); + self.changes.push_str_span(span, "}"); + } + + fn struct_header(&self, + ident: ast::Ident, + vis: ast::Visibility) + -> String + { + let vis = if vis == ast::Visibility::Public { + "pub " + } else { + "" + }; + + format!("{}struct {}", vis, &token::get_ident(ident)) + } + + // Field of a struct + fn visit_field(&mut self, + field: &ast::StructField, + // These two args are for missing spans hacks. + struct_start: BytePos, + struct_snippet: &str) + { + if self.visit_attrs(&field.node.attrs) { + return; + } + self.format_missing_with_indent(field.span.lo); + + let name = match field.node.kind { + ast::StructFieldKind::NamedField(ident, _) => Some(token::get_ident(ident)), + ast::StructFieldKind::UnnamedField(_) => None, + }; + let vis = match field.node.kind { + ast::StructFieldKind::NamedField(_, vis) | + ast::StructFieldKind::UnnamedField(vis) => if vis == ast::Visibility::Public { + "pub " + } else { + "" + } + }; + let typ = pprust::ty_to_string(&field.node.ty); + + let field_str = match name { + Some(name) => { + let budget = config!(ideal_width) - self.block_indent; + if self.block_indent + vis.len() + name.len() + typ.len() + 3 > budget { + format!("{}{}:\n{}{},", + vis, + name, + &make_indent(self.block_indent + config!(tab_spaces)), + typ) + } else { + format!("{}{}: {},", vis, name, typ) + } + } + None => format!("{}{},", vis, typ), + }; + self.changes.push_str_span(field.span, &field_str); + + // This hack makes sure we only add comments etc. after the comma, and + // makes sure we don't repeat any commas. + let hi = field.span.hi; + // FIXME a comma in a comment will break this hack. + let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find(',') { + Some(i) => i, + None => 0, + }; + self.last_pos = hi + BytePos(comma_pos as u32 + 1); + } + + fn rewrite_generics(&self, generics: &ast::Generics, indent: usize, span_end: BytePos) -> String { + // FIXME convert bounds to where clauses where they get too big or if + // there is a where clause at all. + let mut result = String::new(); + let lifetimes: &[_] = &generics.lifetimes; + let tys: &[_] = &generics.ty_params; + if lifetimes.len() + tys.len() == 0 { + return result; + } + + let budget = config!(max_width) - indent - 2; + // TODO might need to insert a newline if the generics are really long + result.push('<'); + + // Strings for the generics. + let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); + let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); + + // Extract comments between generics. + let lt_spans = lifetimes.iter().map(|l| { + let hi = if l.bounds.len() == 0 { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + codemap::mk_sp(l.lifetime.span.lo, hi) + }); + let ty_spans = tys.iter().map(span_for_ty_param); + let comments = self.make_comments_for_list(Vec::new(), + lt_spans.chain(ty_spans), + ",", + ">", + |sp| sp.lo, + |sp| sp.hi, + span_end); + + // If there are // comments, keep them multi-line. + let mut list_tactic = ListTactic::HorizontalVertical; + if comments.iter().any(|c| c.contains("//")) { + list_tactic = ListTactic::Vertical; + } + + let generics_strs: Vec<_> = lt_strs.chain(ty_strs).zip(comments.into_iter()).collect(); + let fmt = ListFormatting { + tactic: list_tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + 1, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&generics_strs, &fmt)); + + result.push('>'); + + result + } + + fn rewrite_where_clause(&self, + where_clause: &ast::WhereClause, + indent: usize, + span_end: BytePos) + -> String + { + let mut result = String::new(); + if where_clause.predicates.len() == 0 { + return result; + } + + result.push('\n'); + result.push_str(&make_indent(indent + 4)); + result.push_str("where "); + + let comments = self.make_comments_for_list(Vec::new(), + where_clause.predicates.iter(), + ",", + "{", + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + span_end); + + let where_strs: Vec<_> = where_clause.predicates.iter() + .map(|p| (self.rewrite_pred(p))) + .zip(comments.into_iter()) + .collect(); + + let budget = config!(ideal_width) + config!(leeway) - indent - 10; + let fmt = ListFormatting { + tactic: ListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + 10, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&where_strs, &fmt)); + + result + } + + fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { + match *ret { + ast::FunctionRetTy::DefaultReturn(_) => String::new(), + ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(), + ast::FunctionRetTy::Return(ref ty) => "-> ".to_owned() + &pprust::ty_to_string(ty), + } + } + + // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly + fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { + format!("{}: {}", + pprust::pat_to_string(&arg.pat), + pprust::ty_to_string(&arg.ty)) + } +} + +fn span_for_return(ret: &ast::FunctionRetTy) -> Span { + match *ret { + ast::FunctionRetTy::NoReturn(ref span) | + ast::FunctionRetTy::DefaultReturn(ref span) => span.clone(), + ast::FunctionRetTy::Return(ref ty) => ty.span, + } +} + +fn span_for_ty_param(ty: &ast::TyParam) -> Span { + // Note that ty.span is the span for ty.ident, not the whole item. + let lo = ty.span.lo; + if let Some(ref def) = ty.default { + return codemap::mk_sp(lo, def.span.hi); + } + if ty.bounds.len() == 0 { + return ty.span; + } + let hi = match ty.bounds[ty.bounds.len() - 1] { + ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span.hi, + ast::TyParamBound::RegionTyParamBound(ref l) => l.span.hi, + }; + codemap::mk_sp(lo, hi) +} + +fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { + match *pred { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } +} diff --git a/src/lib.rs b/src/lib.rs index 386c39ad472..1a690b4945a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,7 +50,7 @@ use visitor::FmtVisitor; mod config; mod changes; mod visitor; -mod functions; +mod items; mod missed_spans; mod lists; mod utils; diff --git a/src/visitor.rs b/src/visitor.rs index 2aac931c4e6..256c1e6e132 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -180,6 +180,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.changes.push_str_span(item.span, &new_str); self.last_pos = item.span.hi; } + ast::Item_::ItemStruct(ref def, ref generics) => { + self.format_missing_with_indent(item.span.lo); + self.visit_struct(item.ident, + item.vis, + def, + generics, + item.span); + self.last_pos = item.span.hi; + } _ => { visit::walk_item(self, item); } @@ -252,7 +261,7 @@ impl<'a> FmtVisitor<'a> { } // Returns true if we should skip the following item. - fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { + pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { if attrs.len() == 0 { return false; } diff --git a/tests/idem.rs b/tests/idem.rs index 40474b8dfee..50329b258d1 100644 --- a/tests/idem.rs +++ b/tests/idem.rs @@ -57,7 +57,7 @@ fn idempotent_tests() { // Compare output to input. fn print_mismatches(result: HashMap) { - for (file_name, fmt_text) in result { + for (_, fmt_text) in result { println!("{}", fmt_text); } } diff --git a/tests/idem/structs.rs b/tests/idem/structs.rs new file mode 100644 index 00000000000..0852b5c3199 --- /dev/null +++ b/tests/idem/structs.rs @@ -0,0 +1,37 @@ + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, +} + +struct Bar; + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +struct Baz { + // Comment A + a: A, + // Comment B + b: B, + // Comment C + c: C, +} -- cgit 1.4.1-3-g733a5 From 972f494e4e3007e0c3bc7216d49eb4bb0cb3f24c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 25 May 2015 17:14:39 +1200 Subject: Pref for comma on the last field --- src/config.rs | 1 + src/default.toml | 1 + src/items.rs | 17 +++++++++++------ 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 080926b03a2..6b3e8916e3b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ pub struct Config { pub newline_style: ::NewlineStyle, pub fn_brace_style: ::BraceStyle, pub fn_return_indent: ::ReturnIndent, + pub struct_trailing_comma: bool, } impl Config { diff --git a/src/default.toml b/src/default.toml index 218f2a04fb2..3d063398893 100644 --- a/src/default.toml +++ b/src/default.toml @@ -5,3 +5,4 @@ tab_spaces = 4 newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" +struct_trailing_comma = true diff --git a/src/items.rs b/src/items.rs index a2027d89b88..55613ab1bb8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -431,8 +431,8 @@ impl<'a> FmtVisitor<'a> { self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1); self.block_indent += config!(tab_spaces); - for f in &struct_def.fields { - self.visit_field(f, span.lo, &struct_snippet); + for (i, f) in struct_def.fields.iter().enumerate() { + self.visit_field(f, i == struct_def.fields.len() - 1, span.lo, &struct_snippet); } self.block_indent -= config!(tab_spaces); @@ -457,6 +457,7 @@ impl<'a> FmtVisitor<'a> { // Field of a struct fn visit_field(&mut self, field: &ast::StructField, + last_field: bool, // These two args are for missing spans hacks. struct_start: BytePos, struct_snippet: &str) @@ -480,21 +481,25 @@ impl<'a> FmtVisitor<'a> { }; let typ = pprust::ty_to_string(&field.node.ty); - let field_str = match name { + let mut field_str = match name { Some(name) => { let budget = config!(ideal_width) - self.block_indent; + // 3 is being conservative and assuming that there will be a trailing comma. if self.block_indent + vis.len() + name.len() + typ.len() + 3 > budget { - format!("{}{}:\n{}{},", + format!("{}{}:\n{}{}", vis, name, &make_indent(self.block_indent + config!(tab_spaces)), typ) } else { - format!("{}{}: {},", vis, name, typ) + format!("{}{}: {}", vis, name, typ) } } - None => format!("{}{},", vis, typ), + None => format!("{}{}", vis, typ), }; + if !last_field || config!(struct_trailing_comma) { + field_str.push(','); + } self.changes.push_str_span(field.span, &field_str); // This hack makes sure we only add comments etc. after the comma, and -- cgit 1.4.1-3-g733a5 From 46818d405a9f2fb3cb0da42b5567b638862b4f3f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 25 May 2015 19:11:53 +1200 Subject: Struct literals --- src/bin/rustfmt.rs | 4 +-- src/config.rs | 1 + src/default.toml | 1 + src/expr.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++- src/imports.rs | 2 +- src/lists.rs | 14 ++++++++++ tests/idem/struct_lits.rs | 24 +++++++++++++++++ 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 tests/idem/struct_lits.rs (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 3b87ac7eb03..5a12dbd639b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -24,8 +24,8 @@ fn main() { let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).unwrap(); - run(args, WriteMode::Display, &def_config); - //run(args, WriteMode::Overwrite, &def_config); + //run(args, WriteMode::Display, &def_config); + run(args, WriteMode::Overwrite, &def_config); std::env::set_exit_status(0); diff --git a/src/config.rs b/src/config.rs index 6b3e8916e3b..8e6c376209f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,6 +20,7 @@ pub struct Config { pub fn_brace_style: ::BraceStyle, pub fn_return_indent: ::ReturnIndent, pub struct_trailing_comma: bool, + pub struct_lit_trailing_comma: ::lists::SeparatorTactic, } impl Config { diff --git a/src/default.toml b/src/default.toml index 3d063398893..e8c74879b59 100644 --- a/src/default.toml +++ b/src/default.toml @@ -6,3 +6,4 @@ newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" struct_trailing_comma = true +struct_lit_trailing_comma = "Vertical" diff --git a/src/expr.rs b/src/expr.rs index 79234eb7f13..4b32301fe91 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -13,7 +13,9 @@ use utils::*; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use syntax::{ast, ptr}; -use syntax::codemap::{Span, Pos}; +use syntax::codemap::{Pos, Span}; +use syntax::parse::token; +use syntax::print::pprust; use MIN_STRING; @@ -134,6 +136,64 @@ impl<'a> FmtVisitor<'a> { format!("({})", subexpr_str) } + fn rewrite_struct_lit(&mut self, + path: &ast::Path, + fields: &[ast::Field], + base: Option<&ast::Expr>, + width: usize, + offset: usize) + -> String + { + debug!("rewrite_struct_lit: width {}, offset {}", width, offset); + assert!(fields.len() > 0 || base.is_some()); + + let path_str = pprust::path_to_string(path); + // Foo { a: Foo } - indent is +3, width is -5. + let indent = offset + path_str.len() + 3; + let budget = width - (path_str.len() + 5); + + let mut field_strs: Vec<_> = + fields.iter().map(|f| self.rewrite_field(f, budget, indent)).collect(); + if let Some(expr) = base { + // Another 2 on the width/indent for the .. + field_strs.push(format!("..{}", self.rewrite_expr(expr, budget - 2, indent + 2))) + } + + // FIXME comments + let field_strs: Vec<_> = field_strs.into_iter().map(|s| (s, String::new())).collect(); + let tactics = if field_strs.iter().any(|&(ref s, _)| s.contains('\n')) { + ListTactic::Vertical + } else { + ListTactic::HorizontalVertical + }; + let fmt = ListFormatting { + tactic: tactics, + separator: ",", + trailing_separator: if base.is_some() { + SeparatorTactic::Never + } else { + config!(struct_lit_trailing_comma) + }, + indent: indent, + h_width: budget, + v_width: budget, + }; + let fields_str = write_list(&field_strs, &fmt); + format!("{} {{ {} }}", path_str, fields_str) + + // FIXME if the usual multi-line layout is too wide, we should fall back to + // Foo { + // a: ..., + // } + } + + fn rewrite_field(&mut self, field: &ast::Field, width: usize, offset: usize) -> String { + let name = &token::get_ident(field.ident.node); + let overhead = name.len() + 2; + let expr = self.rewrite_expr(&field.expr, width - overhead, offset + overhead); + format!("{}: {}", name, expr) + } + pub fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { match expr.node { ast::Expr_::ExprLit(ref l) => { @@ -152,6 +212,13 @@ impl<'a> FmtVisitor<'a> { ast::Expr_::ExprParen(ref subexpr) => { return self.rewrite_paren(subexpr, width, offset); } + ast::Expr_::ExprStruct(ref path, ref fields, ref base) => { + return self.rewrite_struct_lit(path, + fields, + base.as_ref().map(|e| &**e), + width, + offset); + } _ => {} } diff --git a/src/imports.rs b/src/imports.rs index 9c0b81cc902..cab3fa452e4 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -47,7 +47,7 @@ impl<'a> FmtVisitor<'a> { path: &ast::Path, path_list: &[ast::PathListItem], visibility: ast::Visibility) -> String { - let path_str = pprust::path_to_string(&path); + let path_str = pprust::path_to_string(path); let vis = match visibility { ast::Public => "pub ", diff --git a/src/lists.rs b/src/lists.rs index 06fb93f71e1..58e810fce20 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -9,6 +9,7 @@ // except according to those terms. use utils::make_indent; +use rustc_serialize::{Decodable, Decoder}; #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { @@ -29,6 +30,19 @@ pub enum SeparatorTactic { Vertical, } +// TODO could use a macro for all these Decodable impls. +impl Decodable for SeparatorTactic { + fn decode(d: &mut D) -> Result { + let s = try!(d.read_str()); + match &*s { + "Always" => Ok(SeparatorTactic::Always), + "Never" => Ok(SeparatorTactic::Never), + "Vertical" => Ok(SeparatorTactic::Vertical), + _ => Err(d.error("Bad variant")), + } + } +} + // TODO having some helpful ctors for ListFormatting would be nice. pub struct ListFormatting<'a> { pub tactic: ListTactic, diff --git a/tests/idem/struct_lits.rs b/tests/idem/struct_lits.rs new file mode 100644 index 00000000000..1d32171d7d0 --- /dev/null +++ b/tests/idem/struct_lits.rs @@ -0,0 +1,24 @@ +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: Bar, b: foo() }; + + Foo { a: foo(), b: bar(), ..something }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar() }; + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), + c: bar(), + d: bar(), + e: bar(), + f: bar(), + ..baz() }; +} -- cgit 1.4.1-3-g733a5 From 113bdaa119d856bdca0a87b20ab41d62a76f1723 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 25 May 2015 13:21:29 +0200 Subject: Fix #79 --- src/items.rs | 7 +++++++ src/visitor.rs | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 55613ab1bb8..3b174190643 100644 --- a/src/items.rs +++ b/src/items.rs @@ -27,6 +27,7 @@ impl<'a> FmtVisitor<'a> { explicit_self: Option<&ast::ExplicitSelf>, generics: &ast::Generics, unsafety: &ast::Unsafety, + constness: &ast::Constness, abi: &abi::Abi, vis: ast::Visibility, span_end: BytePos) @@ -40,6 +41,7 @@ impl<'a> FmtVisitor<'a> { explicit_self, generics, unsafety, + constness, abi, vis, span_end, @@ -74,6 +76,7 @@ impl<'a> FmtVisitor<'a> { Some(&sig.explicit_self), &sig.generics, &sig.unsafety, + &sig.constness, &sig.abi, ast::Visibility::Inherited, span_end, @@ -92,6 +95,7 @@ impl<'a> FmtVisitor<'a> { explicit_self: Option<&ast::ExplicitSelf>, generics: &ast::Generics, unsafety: &ast::Unsafety, + constness: &ast::Constness, abi: &abi::Abi, vis: ast::Visibility, span_end: BytePos, @@ -111,6 +115,9 @@ impl<'a> FmtVisitor<'a> { if let &ast::Unsafety::Unsafe = unsafety { result.push_str("unsafe "); } + if let &ast::Constness::Const = constness { + result.push_str("const "); + } if *abi != abi::Rust { result.push_str("extern "); result.push_str(&abi.to_string()); diff --git a/src/visitor.rs b/src/visitor.rs index 256c1e6e132..c15b3c34af0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -98,13 +98,19 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { let indent = self.block_indent; match fk { - visit::FkItemFn(ident, ref generics, ref unsafety, ref abi, vis) => { + visit::FkItemFn(ident, + ref generics, + ref unsafety, + ref constness, + ref abi, + vis) => { let new_fn = self.rewrite_fn(indent, ident, fd, None, generics, unsafety, + constness, abi, vis, b.span.lo); @@ -117,6 +123,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { Some(&sig.explicit_self), &sig.generics, &sig.unsafety, + &sig.constness, &sig.abi, vis.unwrap_or(ast::Visibility::Inherited), b.span.lo); -- cgit 1.4.1-3-g733a5 From fdd7baeae92ead4dfae0a367df367bf074e6cfc4 Mon Sep 17 00:00:00 2001 From: Tomasz Dudziak Date: Mon, 25 May 2015 16:02:38 +0200 Subject: Optionally put the opening paren on the previous line for args --- src/config.rs | 1 + src/default.toml | 1 + src/items.rs | 25 ++++++++++++++++++------- 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 8e6c376209f..5c861e83908 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ pub struct Config { pub newline_style: ::NewlineStyle, pub fn_brace_style: ::BraceStyle, pub fn_return_indent: ::ReturnIndent, + pub fn_args_paren_newline: bool, pub struct_trailing_comma: bool, pub struct_lit_trailing_comma: ::lists::SeparatorTactic, } diff --git a/src/default.toml b/src/default.toml index e8c74879b59..1a84f476db8 100644 --- a/src/default.toml +++ b/src/default.toml @@ -5,5 +5,6 @@ tab_spaces = 4 newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" +fn_args_paren_newline = true struct_trailing_comma = true struct_lit_trailing_comma = "Vertical" diff --git a/src/items.rs b/src/items.rs index 55613ab1bb8..eeb05bc9201 100644 --- a/src/items.rs +++ b/src/items.rs @@ -130,13 +130,26 @@ impl<'a> FmtVisitor<'a> { let ret_str = self.rewrite_return(&fd.output); // Args. - let (one_line_budget, multi_line_budget, arg_indent) = - self.compute_budgets_for_args(&mut result, indent, ret_str.len(), newline_brace); + let (one_line_budget, multi_line_budget, mut arg_indent) = + self.compute_budgets_for_args(&result, indent, ret_str.len(), newline_brace); debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", one_line_budget, multi_line_budget, arg_indent); - result.push('('); + if one_line_budget <= 0 { + if config!(fn_args_paren_newline) { + result.push('\n'); + result.push_str(&make_indent(arg_indent)); + arg_indent = arg_indent + 1; + result.push('('); + } else { + result.push_str("(\n"); + result.push_str(&make_indent(arg_indent)); + } + } else { + result.push('('); + } + result.push_str(&self.rewrite_args(&fd.inputs, explicit_self, one_line_budget, @@ -330,7 +343,7 @@ impl<'a> FmtVisitor<'a> { } fn compute_budgets_for_args(&self, - result: &mut String, + result: &String, indent: usize, ret_str_len: usize, newline_brace: bool) @@ -365,8 +378,6 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. if let None = budgets { - result.push('\n'); - result.push_str(&make_indent(indent + 4)); // 6 = new indent + `()` let used_space = indent + 6; let max_space = config!(ideal_width) + config!(leeway); @@ -375,7 +386,7 @@ impl<'a> FmtVisitor<'a> { // TODO take evasive action, perhaps kill the indent or something. } else { // 5 = new indent + `(` - budgets = Some((0, max_space - used_space, indent + 5)); + budgets = Some((0, max_space - used_space, indent + 4)); } } -- cgit 1.4.1-3-g733a5 From 21a0f1b78740eef691f2f65a3aebf370da43fbfa Mon Sep 17 00:00:00 2001 From: Tomasz Dudziak Date: Mon, 25 May 2015 21:29:02 +0200 Subject: Clarify indent calcs in `compute_budget_for_args` --- src/items.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index eeb05bc9201..001136b538c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -136,11 +136,12 @@ impl<'a> FmtVisitor<'a> { debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", one_line_budget, multi_line_budget, arg_indent); + // Check if vertical layout was forced by compute_budget_for_args. if one_line_budget <= 0 { if config!(fn_args_paren_newline) { result.push('\n'); result.push_str(&make_indent(arg_indent)); - arg_indent = arg_indent + 1; + arg_indent = arg_indent + 1; // extra space for `(` result.push('('); } else { result.push_str("(\n"); @@ -378,15 +379,14 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. if let None = budgets { - // 6 = new indent + `()` - let used_space = indent + 6; + let new_indent = indent + 4; + let used_space = new_indent + 2; // account for `(` and `)` let max_space = config!(ideal_width) + config!(leeway); if used_space > max_space { // Whoops! bankrupt. // TODO take evasive action, perhaps kill the indent or something. } else { - // 5 = new indent + `(` - budgets = Some((0, max_space - used_space, indent + 4)); + budgets = Some((0, max_space - used_space, new_indent)); } } -- cgit 1.4.1-3-g733a5 From 1bb3c9e555c4725793c591bda585527f403a9fdb Mon Sep 17 00:00:00 2001 From: Tomasz Dudziak Date: Tue, 26 May 2015 09:31:16 +0200 Subject: Use config!(tab_spaces) instead of hardcoded `4`. --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 001136b538c..dc92377ec6c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -379,7 +379,7 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. if let None = budgets { - let new_indent = indent + 4; + let new_indent = indent + config!(tab_spaces); let used_space = new_indent + 2; // account for `(` and `)` let max_space = config!(ideal_width) + config!(leeway); if used_space > max_space { -- cgit 1.4.1-3-g733a5 From 092d6be3683192bdbcd780d950817c622f44b62e Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 25 May 2015 22:14:05 +0200 Subject: Implement reformat of tuple litterals --- src/expr.rs | 37 +++++++++++++++++++++++++++++++++++++ tests/idem/tuple.rs | 9 +++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/idem/tuple.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4b32301fe91..e731abde4e7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -194,6 +194,40 @@ impl<'a> FmtVisitor<'a> { format!("{}: {}", name, expr) } + fn rewrite_tuple_lit(&mut self, items: &[ptr::P], width: usize, offset: usize) + -> String { + // opening paren + let indent = offset + 1; + // Only last line has width-1 as budget, other may take max_width + let item_strs: Vec<_> = + items.iter() + .enumerate() + .map(|(i, item)| self.rewrite_expr( + item, + // for last line, -2 is for indent + ")", for other lines, -1 is for comma + if i == items.len() - 1 { width - 2 } else { config!(max_width) - indent - 1 }, + indent)) + .collect(); + let tactics = if item_strs.iter().any(|s| s.contains('\n')) { + ListTactic::Vertical + } else { + ListTactic::HorizontalVertical + }; + // FIXME handle comments + let item_strs: Vec<_> = item_strs.into_iter().map(|s| (s, String::new())).collect(); + let fmt = ListFormatting { + tactic: tactics, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + h_width: width - 2, + v_width: width - 2, + }; + let item_str = write_list(&item_strs, &fmt); + format!("({})", item_str) + } + + pub fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { match expr.node { ast::Expr_::ExprLit(ref l) => { @@ -219,6 +253,9 @@ impl<'a> FmtVisitor<'a> { width, offset); } + ast::Expr_::ExprTup(ref items) => { + return self.rewrite_tuple_lit(items, width, offset); + } _ => {} } diff --git a/tests/idem/tuple.rs b/tests/idem/tuple.rs new file mode 100644 index 00000000000..a0ca2c1e145 --- /dev/null +++ b/tests/idem/tuple.rs @@ -0,0 +1,9 @@ +// Test tuple litterals + +fn foo() { + let a = (a, a, a, a, a); + let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaa); + let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa); +} -- cgit 1.4.1-3-g733a5 From 38f421b764f119cdeeee38f43167cfd49793e865 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sat, 30 May 2015 16:44:07 +0200 Subject: fix : width available --- src/expr.rs | 5 +++-- tests/idem/tuple.rs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e731abde4e7..ccc5017ea60 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -204,8 +204,9 @@ impl<'a> FmtVisitor<'a> { .enumerate() .map(|(i, item)| self.rewrite_expr( item, - // for last line, -2 is for indent + ")", for other lines, -1 is for comma - if i == items.len() - 1 { width - 2 } else { config!(max_width) - indent - 1 }, + // last line : given width (minus "("+")"), other lines : max_width + // (minus "("+",")) + if i == items.len() - 1 { width - 2 } else { config!(max_width) - indent - 2 }, indent)) .collect(); let tactics = if item_strs.iter().any(|s| s.contains('\n')) { diff --git a/tests/idem/tuple.rs b/tests/idem/tuple.rs index a0ca2c1e145..ab2d9e6272c 100644 --- a/tests/idem/tuple.rs +++ b/tests/idem/tuple.rs @@ -2,8 +2,9 @@ fn foo() { let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaa); + let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa, aaaa); } -- cgit 1.4.1-3-g733a5 From 7a6b4db819745e5e3553ea2e5094ccb17a914f5c Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sat, 30 May 2015 16:52:46 +0200 Subject: Handle tuples of length 1 --- src/expr.rs | 4 ++++ tests/idem/tuple.rs | 1 + 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ccc5017ea60..70695f30c4f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -198,6 +198,10 @@ impl<'a> FmtVisitor<'a> { -> String { // opening paren let indent = offset + 1; + // In case of length 1, need a trailing comma + if items.len() == 1 { + return format!("({},)", self.rewrite_expr(&*items[0], width - 3, indent)); + } // Only last line has width-1 as budget, other may take max_width let item_strs: Vec<_> = items.iter() diff --git a/tests/idem/tuple.rs b/tests/idem/tuple.rs index ab2d9e6272c..3655cab0663 100644 --- a/tests/idem/tuple.rs +++ b/tests/idem/tuple.rs @@ -7,4 +7,5 @@ fn foo() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa, aaaa); + let a = (a,); } -- cgit 1.4.1-3-g733a5 From 90bc40a11179096a9a11a3a2680b680bae9b2034 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 29 May 2015 12:41:26 +0200 Subject: Implement basic enum formatting --- src/config.rs | 1 + src/default.toml | 1 + src/expr.rs | 3 +- src/imports.rs | 7 +-- src/items.rs | 176 +++++++++++++++++++++++++++++++++++++++++++---------- src/utils.rs | 9 +++ src/visitor.rs | 9 +++ tests/idem/enum.rs | 34 +++++++++++ 8 files changed, 200 insertions(+), 40 deletions(-) create mode 100644 tests/idem/enum.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 5c861e83908..8d6fa827b66 100644 --- a/src/config.rs +++ b/src/config.rs @@ -22,6 +22,7 @@ pub struct Config { pub fn_args_paren_newline: bool, pub struct_trailing_comma: bool, pub struct_lit_trailing_comma: ::lists::SeparatorTactic, + pub enum_trailing_comma: bool, } impl Config { diff --git a/src/default.toml b/src/default.toml index 1a84f476db8..1a7b01473f3 100644 --- a/src/default.toml +++ b/src/default.toml @@ -8,3 +8,4 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = true struct_lit_trailing_comma = "Vertical" +enum_trailing_comma = true diff --git a/src/expr.rs b/src/expr.rs index 70695f30c4f..e91b164a186 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -264,7 +264,6 @@ impl<'a> FmtVisitor<'a> { _ => {} } - let result = self.snippet(expr.span); - result + self.snippet(expr.span) } } diff --git a/src/imports.rs b/src/imports.rs index cab3fa452e4..60f1d2806af 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -10,6 +10,7 @@ use visitor::FmtVisitor; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use utils::format_visibility; use syntax::ast; use syntax::parse::token; @@ -48,11 +49,7 @@ impl<'a> FmtVisitor<'a> { path_list: &[ast::PathListItem], visibility: ast::Visibility) -> String { let path_str = pprust::path_to_string(path); - - let vis = match visibility { - ast::Public => "pub ", - _ => "" - }; + let vis = format_visibility(visibility); if path_list.len() == 1 { return rewrite_single_use_list(path_str, path_list[0], vis); diff --git a/src/items.rs b/src/items.rs index d51ddd4c7a5..a24e02957fa 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use {ReturnIndent, BraceStyle}; -use utils::make_indent; +use utils::{format_visibility, make_indent}; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use visitor::FmtVisitor; use syntax::{ast, abi}; @@ -109,9 +109,8 @@ impl<'a> FmtVisitor<'a> { let mut result = String::with_capacity(1024); // Vis unsafety abi. - if vis == ast::Visibility::Public { - result.push_str("pub "); - } + result.push_str(format_visibility(vis)); + if let &ast::Unsafety::Unsafe = unsafety { result.push_str("unsafe "); } @@ -351,7 +350,7 @@ impl<'a> FmtVisitor<'a> { } fn compute_budgets_for_args(&self, - result: &String, + result: &str, indent: usize, ret_str_len: usize, newline_brace: bool) @@ -408,6 +407,118 @@ impl<'a> FmtVisitor<'a> { } } + pub fn visit_enum(&mut self, + ident: ast::Ident, + vis: ast::Visibility, + enum_def: &ast::EnumDef, + generics: &ast::Generics, + span: Span) + { + let header_str = self.format_header("enum", ident, vis); + self.changes.push_str_span(span, &header_str); + + let enum_snippet = self.snippet(span); + // FIXME this will give incorrect results if there is a { in a comment. + let body_start = span.lo + BytePos(enum_snippet.find('{').unwrap() as u32 + 1); + let generics_str = self.format_generics(generics, body_start); + self.changes.push_str_span(span, &generics_str); + + self.last_pos = body_start; + self.block_indent += config!(tab_spaces); + for (i, f) in enum_def.variants.iter().enumerate() { + let next_span_start: BytePos = if i == enum_def.variants.len() - 1 { + span.hi + } else { + enum_def.variants[i + 1].span.lo + }; + + self.visit_variant(f, i == enum_def.variants.len() - 1, next_span_start); + } + self.block_indent -= config!(tab_spaces); + + self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32)); + self.changes.push_str_span(span, "}"); + } + + // Variant of an enum + fn visit_variant(&mut self, + field: &ast::Variant, + last_field: bool, + next_span_start: BytePos) + { + if self.visit_attrs(&field.node.attrs) { + return; + } + + if let ast::VariantKind::TupleVariantKind(ref types) = field.node.kind { + self.format_missing_with_indent(field.span.lo); + + let vis = format_visibility(field.node.vis); + self.changes.push_str_span(field.span, vis); + let name = field.node.name.to_string(); + self.changes.push_str_span(field.span, &name); + + let mut result = String::new(); + + if types.len() > 0 { + let comments = self.make_comments_for_list(Vec::new(), + types.iter().map(|arg| arg.ty.span), + ",", + ")", + |span| span.lo, + |span| span.hi, + next_span_start); + + let type_strings: Vec<_> = types.iter() + .map(|arg| pprust::ty_to_string(&arg.ty)) + .zip(comments.into_iter()) + .collect(); + + result.push('('); + + let indent = self.block_indent + + vis.len() + + field.node.name.to_string().len() + + 1; // 1 = ( + + let comma_cost = if config!(enum_trailing_comma) { 1 } else { 0 }; + let budget = config!(ideal_width) - indent - comma_cost - 1; // 1 = ) + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + h_width: budget, + v_width: budget, + }; + result.push_str(&write_list(&type_strings, &fmt)); + result.push(')'); + } + + if let Some(ref expr) = field.node.disr_expr { + result.push_str(" = "); + let expr_snippet = self.snippet(expr.span); + result.push_str(&expr_snippet); + + // Make sure we do not exceed column limit + // 4 = " = ," + assert!(config!(max_width) >= vis.len() + name.len() + expr_snippet.len() + 4, + "Enum variant exceeded column limit"); + } + + self.changes.push_str_span(field.span, &result); + + if !last_field || config!(enum_trailing_comma) { + self.changes.push_str_span(field.span, ","); + } + } + + // TODO: deal with struct-like variants + + self.last_pos = field.span.hi + BytePos(1); + } + pub fn visit_struct(&mut self, ident: ast::Ident, vis: ast::Visibility, @@ -415,7 +526,7 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span) { - let header_str = self.struct_header(ident, vis); + let header_str = self.format_header("struct", ident, vis); self.changes.push_str_span(span, &header_str); if struct_def.fields.len() == 0 { @@ -428,24 +539,11 @@ impl<'a> FmtVisitor<'a> { return; } - let mut generics_buf = String::new(); - let generics_str = self.rewrite_generics(generics, self.block_indent, struct_def.fields[0].span.lo); - generics_buf.push_str(&generics_str); - - if generics.where_clause.predicates.len() > 0 { - generics_buf.push_str(&self.rewrite_where_clause(&generics.where_clause, - self.block_indent, - struct_def.fields[0].span.lo)); - generics_buf.push_str(&make_indent(self.block_indent)); - generics_buf.push_str("\n{"); - - } else { - generics_buf.push_str(" {"); - } - self.changes.push_str_span(span, &generics_buf); + let generics_str = self.format_generics(generics, struct_def.fields[0].span.lo); + self.changes.push_str_span(span, &generics_str); let struct_snippet = self.snippet(span); - // FIXME this will give incorrect results if there is a { in a commet. + // FIXME this will give incorrect results if there is a { in a comment. self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1); self.block_indent += config!(tab_spaces); @@ -458,18 +556,34 @@ impl<'a> FmtVisitor<'a> { self.changes.push_str_span(span, "}"); } - fn struct_header(&self, + fn format_header(&self, + item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { - let vis = if vis == ast::Visibility::Public { - "pub " + format!("{}{} {}", format_visibility(vis), item_name, &token::get_ident(ident)) + } + + fn format_generics(&self, + generics: &ast::Generics, + span_end: BytePos) + -> String + { + let mut result = self.rewrite_generics(generics, self.block_indent, span_end); + + if generics.where_clause.predicates.len() > 0 { + result.push_str(&self.rewrite_where_clause(&generics.where_clause, + self.block_indent, + span_end)); + result.push_str(&make_indent(self.block_indent)); + result.push_str("\n{"); + } else { - "" - }; + result.push_str(" {"); + } - format!("{}struct {}", vis, &token::get_ident(ident)) + result } // Field of a struct @@ -491,11 +605,7 @@ impl<'a> FmtVisitor<'a> { }; let vis = match field.node.kind { ast::StructFieldKind::NamedField(_, vis) | - ast::StructFieldKind::UnnamedField(vis) => if vis == ast::Visibility::Public { - "pub " - } else { - "" - } + ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis) }; let typ = pprust::ty_to_string(&field.node.ty); diff --git a/src/utils.rs b/src/utils.rs index c22b85f4563..520877c79c8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use syntax::ast::Visibility; #[inline] pub fn prev_char(s: &str, mut i: usize) -> usize { @@ -38,3 +39,11 @@ pub fn make_indent(width: usize) -> String { } indent } + +#[inline] +pub fn format_visibility(vis: Visibility) -> &'static str { + match vis { + Visibility::Public => "pub ", + Visibility::Inherited => "" + } +} diff --git a/src/visitor.rs b/src/visitor.rs index c15b3c34af0..3c9f3ac1b23 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -196,6 +196,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { item.span); self.last_pos = item.span.hi; } + ast::Item_::ItemEnum(ref def, ref generics) => { + self.format_missing_with_indent(item.span.lo); + self.visit_enum(item.ident, + item.vis, + def, + generics, + item.span); + self.last_pos = item.span.hi; + } _ => { visit::walk_item(self, item); } diff --git a/tests/idem/enum.rs b/tests/idem/enum.rs new file mode 100644 index 00000000000..2f7b3bb66a9 --- /dev/null +++ b/tests/idem/enum.rs @@ -0,0 +1,34 @@ +// Enums test + +#[atrr] +pub enum Test { + A, + B(u32, A /* comment */), + /// Doc comment + C, +} + +pub enum Foo<'a, Y: Baz> + where X: Whatever +{ + A, +} + +enum EmtpyWithComment { + // Some comment +} + +// C-style enum +enum Bar { + A = 1, + #[someAttr(test)] + B = 2, // comment + C, +} + +enum LongVariants { + First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // small comment + VARIANT), + // This is the second variant + Second, +} -- cgit 1.4.1-3-g733a5 From 27d6558964dd9e5704d23a722d3ae8598bd3c13c Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 2 Jun 2015 18:44:33 +0200 Subject: Remove empty list imports --- src/imports.rs | 15 ++++++++------- src/visitor.rs | 27 +++++++++++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index cab3fa452e4..586caa76b64 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -15,8 +15,6 @@ use syntax::ast; use syntax::parse::token; use syntax::print::pprust; - -// TODO remove empty lists (if they're even possible) // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem, vis: &str) -> String { @@ -40,13 +38,14 @@ fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem, vis: &str) impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. + // Returns None when the import can be removed. pub fn rewrite_use_list(&mut self, block_indent: usize, one_line_budget: usize, // excluding indentation multi_line_budget: usize, path: &ast::Path, path_list: &[ast::PathListItem], - visibility: ast::Visibility) -> String { + visibility: ast::Visibility) -> Option { let path_str = pprust::path_to_string(path); let vis = match visibility { @@ -54,8 +53,10 @@ impl<'a> FmtVisitor<'a> { _ => "" }; - if path_list.len() == 1 { - return rewrite_single_use_list(path_str, path_list[0], vis); + match path_list.len() { + 0 => return None, + 1 => return Some(rewrite_single_use_list(path_str, path_list[0], vis)), + _ => () } // 2 = :: @@ -110,10 +111,10 @@ impl<'a> FmtVisitor<'a> { ast::PathListItem_::PathListMod{ .. } => None, } })).collect(); - if path_str.len() == 0 { + Some(if path_str.len() == 0 { format!("{}use {{{}}};", vis, write_list(&items, &fmt)) } else { format!("{}use {}::{{{}}};", vis, path_str, write_list(&items, &fmt)) - } + }) } } diff --git a/src/visitor.rs b/src/visitor.rs index c15b3c34af0..630638e7bda 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -152,19 +152,30 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match item.node { ast::Item_::ItemUse(ref vp) => { - self.format_missing_with_indent(item.span.lo); match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { let block_indent = self.block_indent; let one_line_budget = config!(max_width) - block_indent; let multi_line_budget = config!(ideal_width) - block_indent; - let new_str = self.rewrite_use_list(block_indent, - one_line_budget, - multi_line_budget, - path, - path_list, - item.vis); - self.changes.push_str_span(item.span, &new_str); + let formatted = self.rewrite_use_list(block_indent, + one_line_budget, + multi_line_budget, + path, + path_list, + item.vis); + + if let Some(new_str) = formatted { + self.format_missing_with_indent(item.span.lo); + self.changes.push_str_span(item.span, &new_str); + } else { + // Format up to last newline + let span = codemap::mk_sp(self.last_pos, item.span.lo); + let span_end = match self.snippet(span).rfind('\n') { + Some(offset) => self.last_pos + BytePos(offset as u32), + None => item.span.lo + }; + self.format_missing(span_end); + } self.last_pos = item.span.hi; } ast::ViewPath_::ViewPathGlob(_) => { -- cgit 1.4.1-3-g733a5 From 1ef7e23dd1654b761716ab64f37f499a965c305f Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 4 Jun 2015 13:47:35 +0200 Subject: Move vertical mode override to write_list --- src/expr.rs | 15 ++------------- src/lists.rs | 3 ++- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e91b164a186..c5fb9355b84 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -105,14 +105,8 @@ impl<'a> FmtVisitor<'a> { let args: Vec<_> = args.iter().map(|e| (self.rewrite_expr(e, remaining_width, offset), String::new())).collect(); - // TODO move this into write_list - let tactics = if args.iter().any(|&(ref s, _)| s.contains('\n')) { - ListTactic::Vertical - } else { - ListTactic::HorizontalVertical - }; let fmt = ListFormatting { - tactic: tactics, + tactic: ListTactic::HorizontalVertical, separator: ",", trailing_separator: SeparatorTactic::Never, indent: offset, @@ -161,13 +155,8 @@ impl<'a> FmtVisitor<'a> { // FIXME comments let field_strs: Vec<_> = field_strs.into_iter().map(|s| (s, String::new())).collect(); - let tactics = if field_strs.iter().any(|&(ref s, _)| s.contains('\n')) { - ListTactic::Vertical - } else { - ListTactic::HorizontalVertical - }; let fmt = ListFormatting { - tactic: tactics, + tactic: ListTactic::HorizontalVertical, separator: ",", trailing_separator: if base.is_some() { SeparatorTactic::Never diff --git a/src/lists.rs b/src/lists.rs index 58e810fce20..61ad8c08a0c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -79,7 +79,8 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b if tactic == ListTactic::HorizontalVertical { debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", total_width, total_sep_len, formatting.h_width); - tactic = if fits_single { + tactic = if fits_single && + !items.iter().any(|&(ref s, _)| s.contains('\n')) { ListTactic::Horizontal } else { ListTactic::Vertical -- cgit 1.4.1-3-g733a5 From 227322ddba1fab63e7103a73abf342a4ab56c4d7 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 4 Jun 2015 14:08:32 +0200 Subject: Add macro for enum implementations of Decodable --- src/lib.rs | 52 ++++++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 1a690b4945a..868f0ca663b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,23 @@ const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; static mut CONFIG: Option = None; +// Macro for deriving implementations of Decodable for enums +macro_rules! impl_enum_decodable { + ( $e:ident, $( $x:ident ),* ) => { + impl Decodable for $e { + fn decode(d: &mut D) -> Result { + let s = try!(d.read_str()); + match &*s { + $( + stringify!($x) => Ok($e::$x), + )* + _ => Err(d.error("Bad variant")), + } + } + } + }; +} + #[derive(Copy, Clone)] pub enum WriteMode { Overwrite, @@ -81,16 +98,7 @@ pub enum NewlineStyle { Unix, // \n } -impl Decodable for NewlineStyle { - fn decode(d: &mut D) -> Result { - let s = try!(d.read_str()); - match &*s { - "Windows" => Ok(NewlineStyle::Windows), - "Unix" => Ok(NewlineStyle::Unix), - _ => Err(d.error("Bad variant")), - } - } -} +impl_enum_decodable!(NewlineStyle, Windows, Unix); #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum BraceStyle { @@ -101,17 +109,7 @@ pub enum BraceStyle { SameLineWhere, } -impl Decodable for BraceStyle { - fn decode(d: &mut D) -> Result { - let s = try!(d.read_str()); - match &*s { - "AlwaysNextLine" => Ok(BraceStyle::AlwaysNextLine), - "PreferSameLine" => Ok(BraceStyle::PreferSameLine), - "SameLineWhere" => Ok(BraceStyle::SameLineWhere), - _ => Err(d.error("Bad variant")), - } - } -} +impl_enum_decodable!(BraceStyle, AlwaysNextLine, PreferSameLine, SameLineWhere); // How to indent a function's return type. #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -122,17 +120,7 @@ pub enum ReturnIndent { WithWhereClause, } -// TODO could use a macro for all these Decodable impls. -impl Decodable for ReturnIndent { - fn decode(d: &mut D) -> Result { - let s = try!(d.read_str()); - match &*s { - "WithArgs" => Ok(ReturnIndent::WithArgs), - "WithWhereClause" => Ok(ReturnIndent::WithWhereClause), - _ => Err(d.error("Bad variant")), - } - } -} +impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { -- cgit 1.4.1-3-g733a5 From 13141e261b4df0ee99fd196466f0bb04c8ce0632 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 4 Jun 2015 15:05:50 +0200 Subject: Remove duplicate statement in make_comments_for_list --- src/items.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a24e02957fa..2817b23b33e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -341,8 +341,7 @@ impl<'a> FmtVisitor<'a> { // The fix is comments in the AST or a span for the closing paren. let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find(terminator) - .unwrap_or(snippet.find(separator).unwrap_or(snippet.len()))]; + let snippet = &snippet[..snippet.find(terminator).unwrap_or(snippet.len())]; let snippet = snippet.trim(); result.push(snippet.to_owned()); -- cgit 1.4.1-3-g733a5 From adedba45a85c712a32d250bdcee8c1146fe80250 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 8 Jun 2015 19:40:22 +0200 Subject: Use impl_enum_decodable for SeparatorTactic --- src/lib.rs | 18 +----------------- src/lists.rs | 13 +------------ src/utils.rs | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 868f0ca663b..6591ded8db2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,7 @@ mod visitor; mod items; mod missed_spans; mod lists; +#[macro_use] mod utils; mod types; mod expr; @@ -64,23 +65,6 @@ const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; static mut CONFIG: Option = None; -// Macro for deriving implementations of Decodable for enums -macro_rules! impl_enum_decodable { - ( $e:ident, $( $x:ident ),* ) => { - impl Decodable for $e { - fn decode(d: &mut D) -> Result { - let s = try!(d.read_str()); - match &*s { - $( - stringify!($x) => Ok($e::$x), - )* - _ => Err(d.error("Bad variant")), - } - } - } - }; -} - #[derive(Copy, Clone)] pub enum WriteMode { Overwrite, diff --git a/src/lists.rs b/src/lists.rs index 61ad8c08a0c..f31458fcc57 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -30,18 +30,7 @@ pub enum SeparatorTactic { Vertical, } -// TODO could use a macro for all these Decodable impls. -impl Decodable for SeparatorTactic { - fn decode(d: &mut D) -> Result { - let s = try!(d.read_str()); - match &*s { - "Always" => Ok(SeparatorTactic::Always), - "Never" => Ok(SeparatorTactic::Never), - "Vertical" => Ok(SeparatorTactic::Vertical), - _ => Err(d.error("Bad variant")), - } - } -} +impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical); // TODO having some helpful ctors for ListFormatting would be nice. pub struct ListFormatting<'a> { diff --git a/src/utils.rs b/src/utils.rs index 520877c79c8..45bf6ffe7b5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -47,3 +47,22 @@ pub fn format_visibility(vis: Visibility) -> &'static str { Visibility::Inherited => "" } } + +// Macro for deriving implementations of Decodable for enums +#[macro_export] +macro_rules! impl_enum_decodable { + ( $e:ident, $( $x:ident ),* ) => { + impl Decodable for $e { + fn decode(d: &mut D) -> Result { + let s = try!(d.read_str()); + match &*s { + $( + stringify!($x) => Ok($e::$x), + )* + _ => Err(d.error("Bad variant")), + } + } + } + }; +} + -- cgit 1.4.1-3-g733a5 From 4d6d0b81a79a2edbaeb052d80005a71694dfadcf Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 8 Jun 2015 20:23:24 +0200 Subject: Fix mod ordering + formatting --- src/lib.rs | 4 ++-- src/utils.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 6591ded8db2..9d80f259ebd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,13 +48,13 @@ use visitor::FmtVisitor; #[macro_use] mod config; +#[macro_use] +mod utils; mod changes; mod visitor; mod items; mod missed_spans; mod lists; -#[macro_use] -mod utils; mod types; mod expr; mod imports; diff --git a/src/utils.rs b/src/utils.rs index 45bf6ffe7b5..0e992e9f7da 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -65,4 +65,3 @@ macro_rules! impl_enum_decodable { } }; } - -- cgit 1.4.1-3-g733a5 From d335d0457536d985f5f4ff406ccf8a7a8c933133 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 9 Jun 2015 01:42:29 +0200 Subject: Implement checks for unnumbered TODOs and FIXMEs --- src/changes.rs | 8 +- src/config.rs | 14 +- src/default.toml | 2 + src/issues.rs | 298 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 95 ++++++++++++-- src/lists.rs | 1 - src/utils.rs | 37 +++++- tests/config/small_tabs.toml | 2 + 8 files changed, 435 insertions(+), 22 deletions(-) create mode 100644 src/issues.rs (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 5ed1c82b22f..97133ab67fb 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -21,6 +21,7 @@ use std::fs::File; use std::io::{Write, stdout}; use WriteMode; use NewlineStyle; +use utils::round_up_to_power_of_two; // This is basically a wrapper around a bunch of Ropes which makes it convenient // to work with libsyntax. It is badly named. @@ -41,11 +42,10 @@ impl<'a> ChangeSet<'a> { for f in codemap.files.borrow().iter() { // Use the length of the file as a heuristic for how much space we - // need. I hope that at some stage someone rounds this up to the next - // power of two. TODO check that or do it here. - result.file_map.insert(f.name.clone(), - StringBuffer::with_capacity(f.src.as_ref().unwrap().len())); + // need. Round to the next power of two. + let buffer_cap = round_up_to_power_of_two(f.src.as_ref().unwrap().len()); + result.file_map.insert(f.name.clone(), StringBuffer::with_capacity(buffer_cap)); result.file_spans.push((f.start_pos.0, f.end_pos.0)); } diff --git a/src/config.rs b/src/config.rs index 8d6fa827b66..c803a07d9d0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,19 +10,25 @@ extern crate toml; +use {NewlineStyle, BraceStyle, ReturnIndent}; +use lists::SeparatorTactic; +use issues::ReportTactic; + #[derive(RustcDecodable)] pub struct Config { pub max_width: usize, pub ideal_width: usize, pub leeway: usize, pub tab_spaces: usize, - pub newline_style: ::NewlineStyle, - pub fn_brace_style: ::BraceStyle, - pub fn_return_indent: ::ReturnIndent, + pub newline_style: NewlineStyle, + pub fn_brace_style: BraceStyle, + pub fn_return_indent: ReturnIndent, pub fn_args_paren_newline: bool, pub struct_trailing_comma: bool, - pub struct_lit_trailing_comma: ::lists::SeparatorTactic, + pub struct_lit_trailing_comma: SeparatorTactic, pub enum_trailing_comma: bool, + pub report_todo: ReportTactic, + pub report_fixme: ReportTactic, } impl Config { diff --git a/src/default.toml b/src/default.toml index 1a7b01473f3..75ab3a60164 100644 --- a/src/default.toml +++ b/src/default.toml @@ -9,3 +9,5 @@ fn_args_paren_newline = true struct_trailing_comma = true struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true +report_todo = "Always" +report_fixme = "Never" diff --git a/src/issues.rs b/src/issues.rs new file mode 100644 index 00000000000..9ee70e1aadc --- /dev/null +++ b/src/issues.rs @@ -0,0 +1,298 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Objects for seeking through a char stream for occurences of TODO and FIXME. +// Depending on the loaded configuration, may also check that these have an +// associated issue number. + +use std::fmt; + +static TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O']; +static FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; + +#[derive(Clone, Copy)] +pub enum ReportTactic { + Always, + Unnumbered, + Never +} + +impl ReportTactic { + fn is_enabled(&self) -> bool { + match *self { + ReportTactic::Always => true, + ReportTactic::Unnumbered => true, + ReportTactic::Never => false + } + } +} + +impl_enum_decodable!(ReportTactic, Always, Unnumbered, Never); + +#[derive(Clone, Copy)] +enum Seeking { + Issue { + todo_idx: usize, + fixme_idx: usize + }, + Number { + issue: Issue, + part: NumberPart + } +} + +#[derive(Clone, Copy)] +enum NumberPart { + OpenParen, + Pound, + Number, + CloseParen +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub struct Issue { + issue_type: IssueType, + // Indicates whether we're looking for issues with missing numbers, or + // all issues of this type. + missing_number: bool, +} + +impl fmt::Display for Issue { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let msg = match self.issue_type { + IssueType::Todo => "TODO", + IssueType::Fixme => "FIXME", + }; + let details = if self.missing_number { " without issue number" } else { "" }; + + write!(fmt, "{}{}", msg, details) + } +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum IssueType { + Todo, + Fixme +} + +enum IssueClassification { + Good, + Bad(Issue), + None +} + +pub struct BadIssueSeeker { + state: Seeking, + report_todo: ReportTactic, + report_fixme: ReportTactic, +} + +impl BadIssueSeeker { + pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { + BadIssueSeeker { + state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 }, + report_todo: report_todo, + report_fixme: report_fixme, + } + } + + // Check whether or not the current char is conclusive evidence for an + // unnumbered TO-DO or FIX-ME. + pub fn inspect(&mut self, c: char) -> Option { + match self.state { + Seeking::Issue { todo_idx, fixme_idx } => { + self.state = self.inspect_issue(c, todo_idx, fixme_idx); + }, + Seeking::Number { issue, part } => { + let result = self.inspect_number(c, issue, part); + + if let IssueClassification::None = result { + return None; + } + + self.state = Seeking::Issue { todo_idx: 0, fixme_idx: 0 }; + + if let IssueClassification::Bad(issue) = result { + return Some(issue); + } + } + } + + None + } + + fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking { + // FIXME: Should we also check for lower case characters? + if self.report_todo.is_enabled() && c == TO_DO_CHARS[todo_idx] { + todo_idx += 1; + if todo_idx == TO_DO_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Todo, + missing_number: if let ReportTactic::Unnumbered = self.report_todo { + true + } else { + false + } + }, + part: NumberPart::OpenParen + }; + } + fixme_idx = 0; + } else if self.report_fixme.is_enabled() && c == FIX_ME_CHARS[fixme_idx] { + // Exploit the fact that the character sets of todo and fixme + // are disjoint by adding else. + fixme_idx += 1; + if fixme_idx == FIX_ME_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Fixme, + missing_number: if let ReportTactic::Unnumbered = self.report_fixme { + true + } else { + false + } + }, + part: NumberPart::OpenParen + }; + } + todo_idx = 0; + } else { + todo_idx = 0; + fixme_idx = 0; + } + + Seeking::Issue { todo_idx: todo_idx, fixme_idx: fixme_idx } + } + + fn inspect_number(&mut self, + c: char, + issue: Issue, + mut part: NumberPart) + -> IssueClassification + { + if ! issue.missing_number || c == '\n' { + return IssueClassification::Bad(issue); + } else if c == ')' { + return if let NumberPart::CloseParen = part { + IssueClassification::Good + } else { + IssueClassification::Bad(issue) + }; + } + + match part { + NumberPart::OpenParen => { + if c != '(' { + return IssueClassification::Bad(issue); + } else { + part = NumberPart::Pound; + } + }, + NumberPart::Pound => { + if c == '#' { + part = NumberPart::Number; + } + }, + NumberPart::Number => { + if c >= '0' && c <= '9' { + part = NumberPart::CloseParen; + } else { + return IssueClassification::Bad(issue); + } + }, + NumberPart::CloseParen => {} + } + + self.state = Seeking::Number { + part: part, + issue: issue + }; + + IssueClassification::None + } +} + +#[test] +fn find_unnumbered_issue() { + fn check_fail(text: &str, failing_pos: usize) { + println!("{:?}", text); + let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); + assert_eq!(Some(failing_pos), text.chars().position(|c| seeker.inspect(c).is_some())); + } + + fn check_pass(text: &str) { + let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); + assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); + } + + check_fail("TODO\n", 4); + check_pass(" TO FIX DOME\n"); + check_fail(" \n FIXME\n", 8); + check_fail("FIXME(\n", 6); + check_fail("FIXME(#\n", 7); + check_fail("FIXME(#1\n", 8); + check_fail("FIXME(#)1\n", 7); + check_pass("FIXME(#1222)\n"); + check_fail("FIXME(#12\n22)\n", 9); + check_pass("FIXME(@maintainer, #1222, hello)\n"); + check_fail("TODO(#22) FIXME\n", 15); +} + +#[test] +fn find_issue() { + fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { + let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); + text.chars().any(|c| seeker.inspect(c).is_some()) + } + + assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n", + ReportTactic::Always, + ReportTactic::Never)); + + assert!(! is_bad_issue("TODO: no number\n", + ReportTactic::Never, + ReportTactic::Always)); + + assert!(is_bad_issue("This is a FIXME(#1)\n", + ReportTactic::Never, + ReportTactic::Always)); + + assert!(! is_bad_issue("bad FIXME\n", + ReportTactic::Always, + ReportTactic::Never)); +} + +#[test] +fn issue_type() { + let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); + let expected = Some(Issue { + issue_type: IssueType::Todo, + missing_number: false + }); + + assert_eq!(expected, + "TODO(#100): more awesomeness".chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap()); + + let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); + let expected = Some(Issue { + issue_type: IssueType::Fixme, + missing_number: true + }); + + assert_eq!(expected, + "Test. FIXME: bad, bad, not good".chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap()); +} diff --git a/src/lib.rs b/src/lib.rs index 9d80f259ebd..c8fdc2eab96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,8 +33,6 @@ use rustc::session::config as rustc_config; use rustc::session::config::Input; use rustc_driver::{driver, CompilerCalls, Compilation}; -use rustc_serialize::{Decodable, Decoder}; - use syntax::ast; use syntax::codemap::CodeMap; use syntax::diagnostics; @@ -42,7 +40,9 @@ use syntax::visit; use std::path::PathBuf; use std::collections::HashMap; +use std::fmt; +use issues::{BadIssueSeeker, Issue}; use changes::ChangeSet; use visitor::FmtVisitor; @@ -58,6 +58,7 @@ mod lists; mod types; mod expr; mod imports; +mod issues; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. @@ -106,6 +107,58 @@ pub enum ReturnIndent { impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); +enum ErrorKind { + // Line has more than config!(max_width) characters + LineOverflow, + // Line ends in whitespace + TrailingWhitespace, + // TO-DO or FIX-ME item without an issue number + BadIssue(Issue), +} + +impl fmt::Display for ErrorKind { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ErrorKind::LineOverflow => { + write!(fmt, "line exceeded maximum length") + }, + ErrorKind::TrailingWhitespace => { + write!(fmt, "left behind trailing whitespace") + }, + ErrorKind::BadIssue(issue) => { + write!(fmt, "found {}", issue) + }, + } + } +} + +// Formatting errors that are identified *after* rustfmt has run +struct FormattingError { + line: u32, + kind: ErrorKind, +} + +struct FormatReport { + // Maps stringified file paths to their associated formatting errors + file_error_map: HashMap>, +} + +impl fmt::Display for FormatReport { + // Prints all the formatting errors. + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + for (file, errors) in self.file_error_map.iter() { + for error in errors { + try!(write!(fmt, + "Rustfmt failed at {}:{}: {} (sorry)\n", + file, + error.line, + error.kind)); + } + } + Ok(()) + } +} + // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { let mut visitor = FmtVisitor::from_codemap(codemap); @@ -119,11 +172,11 @@ fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { } // Formatting done on a char by char or line by line basis. -// TODO warn on TODOs and FIXMEs without an issue number // TODO warn on bad license // TODO other stuff for parity with make tidy -fn fmt_lines(changes: &mut ChangeSet) { +fn fmt_lines(changes: &mut ChangeSet) -> FormatReport { let mut truncate_todo = Vec::new(); + let mut report = FormatReport { file_error_map: HashMap::new() }; // Iterate over the chars in the change set. for (f, text) in changes.text() { @@ -132,8 +185,21 @@ fn fmt_lines(changes: &mut ChangeSet) { let mut line_len = 0; let mut cur_line = 1; let mut newline_count = 0; + let mut errors = vec![]; + let mut issue_seeker = BadIssueSeeker::new(config!(report_todo), + config!(report_fixme)); + for (c, b) in text.chars() { if c == '\r' { continue; } + + // Add warnings for bad todos/ fixmes + if let Some(issue) = issue_seeker.inspect(c) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::BadIssue(issue) + }); + } + if c == '\n' { // Check for (and record) trailing whitespace. if let Some(lw) = last_wspace { @@ -142,9 +208,10 @@ fn fmt_lines(changes: &mut ChangeSet) { } // Check for any line width errors we couldn't correct. if line_len > config!(max_width) { - // TODO store the error rather than reporting immediately. - println!("Rustfmt couldn't fix (sorry). {}:{}: line longer than {} characters", - f, cur_line, config!(max_width)); + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::LineOverflow + }); } line_len = 0; cur_line += 1; @@ -165,18 +232,24 @@ fn fmt_lines(changes: &mut ChangeSet) { if newline_count > 1 { debug!("track truncate: {} {} {}", f, text.len, newline_count); - truncate_todo.push((f.to_string(), text.len - newline_count + 1)) + truncate_todo.push((f.to_owned(), text.len - newline_count + 1)) } for &(l, _, _) in trims.iter() { - // TODO store the error rather than reporting immediately. - println!("Rustfmt left trailing whitespace at {}:{} (sorry)", f, l); + errors.push(FormattingError { + line: l, + kind: ErrorKind::TrailingWhitespace + }); } + + report.file_error_map.insert(f.to_owned(), errors); } for (f, l) in truncate_todo { changes.get_mut(&f).truncate(l); } + + report } struct RustFmtCalls { @@ -237,7 +310,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { // For some reason, the codemap does not include terminating newlines // so we must add one on for each file. This is sad. changes.append_newlines(); - fmt_lines(&mut changes); + println!("{}", fmt_lines(&mut changes)); let result = changes.write_all_files(write_mode); diff --git a/src/lists.rs b/src/lists.rs index f31458fcc57..9f1006c39f0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -9,7 +9,6 @@ // except according to those terms. use utils::make_indent; -use rustc_serialize::{Decodable, Decoder}; #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { diff --git a/src/utils.rs b/src/utils.rs index 0e992e9f7da..c32a9293326 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -48,12 +48,38 @@ pub fn format_visibility(vis: Visibility) -> &'static str { } } +#[inline] +#[cfg(target_pointer_width="64")] +// Based on the trick layed out at +// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 +pub fn round_up_to_power_of_two(mut x: usize) -> usize { + x -= 1; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + x + 1 +} + +#[cfg(target_pointer_width="32")] +pub fn round_up_to_power_of_two(mut x: usize) -> usize { + x -= 1; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x + 1 +} + // Macro for deriving implementations of Decodable for enums #[macro_export] macro_rules! impl_enum_decodable { ( $e:ident, $( $x:ident ),* ) => { - impl Decodable for $e { - fn decode(d: &mut D) -> Result { + impl ::rustc_serialize::Decodable for $e { + fn decode(d: &mut D) -> Result { let s = try!(d.read_str()); match &*s { $( @@ -65,3 +91,10 @@ macro_rules! impl_enum_decodable { } }; } + +#[test] +fn power_rounding() { + assert_eq!(1, round_up_to_power_of_two(1)); + assert_eq!(64, round_up_to_power_of_two(33)); + assert_eq!(256, round_up_to_power_of_two(256)); +} diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 316ee8ae288..68824838644 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -9,3 +9,5 @@ fn_args_paren_newline = true struct_trailing_comma = true struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true +report_todo = "Always" +report_fixme = "Never" -- cgit 1.4.1-3-g733a5 From b17c920e46403921f1d45db68715f1615a6b985d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 5 Jun 2015 16:56:59 +0200 Subject: Deal with problematic characters in comments --- src/items.rs | 17 ++++++-------- src/utils.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/target/fn.rs | 4 ++-- 3 files changed, 76 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2817b23b33e..29c950f1464 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use {ReturnIndent, BraceStyle}; -use utils::{format_visibility, make_indent}; +use utils::{format_visibility, make_indent, FindUncommented}; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use visitor::FmtVisitor; use syntax::{ast, abi}; @@ -336,12 +336,11 @@ impl<'a> FmtVisitor<'a> { // FIXME If you thought the crap with the commas was ugly, just wait. // This is awful. We're going to look from the last item span to the // start of the return type span, then we drop everything after the - // first closing paren. Obviously, this will break if there is a - // closing paren in the comment. + // first closing paren. // The fix is comments in the AST or a span for the closing paren. let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find(terminator).unwrap_or(snippet.len())]; + let snippet = &snippet[..snippet.find_uncommented(terminator).unwrap_or(snippet.len())]; let snippet = snippet.trim(); result.push(snippet.to_owned()); @@ -417,8 +416,7 @@ impl<'a> FmtVisitor<'a> { self.changes.push_str_span(span, &header_str); let enum_snippet = self.snippet(span); - // FIXME this will give incorrect results if there is a { in a comment. - let body_start = span.lo + BytePos(enum_snippet.find('{').unwrap() as u32 + 1); + let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); let generics_str = self.format_generics(generics, body_start); self.changes.push_str_span(span, &generics_str); @@ -542,8 +540,8 @@ impl<'a> FmtVisitor<'a> { self.changes.push_str_span(span, &generics_str); let struct_snippet = self.snippet(span); - // FIXME this will give incorrect results if there is a { in a comment. - self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1); + // This will drop the comment in between the header and body. + self.last_pos = span.lo + BytePos(struct_snippet.find_uncommented("{").unwrap() as u32 + 1); self.block_indent += config!(tab_spaces); for (i, f) in struct_def.fields.iter().enumerate() { @@ -632,8 +630,7 @@ impl<'a> FmtVisitor<'a> { // This hack makes sure we only add comments etc. after the comma, and // makes sure we don't repeat any commas. let hi = field.span.hi; - // FIXME a comma in a comment will break this hack. - let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find(',') { + let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find_uncommented(",") { Some(i) => i, None => 0, }; diff --git a/src/utils.rs b/src/utils.rs index c32a9293326..5e7f8baf1dc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,6 +10,72 @@ use syntax::ast::Visibility; +pub trait FindUncommented { + fn find_uncommented(&self, pat: &str) -> Option; +} + +impl FindUncommented for str { + fn find_uncommented(&self, pat: &str) -> Option { + let mut needle_iter = pat.chars(); + let mut possible_comment = false; + + for (i, b) in self.char_indices() { + match needle_iter.next() { + Some(c) => { + if b != c { + needle_iter = pat.chars(); + } + }, + None => return Some(i - pat.len()) + } + + if possible_comment { + if b == '/' { + return self[(i+1)..].find('\n') + .and_then(|end| { + self[(end + i + 2)..].find_uncommented(pat) + .map(|idx| idx + end + i + 2) + }); + } else if b == '*' { + return self[(i+1)..].find("*/") + .and_then(|end| { + self[(end + i + 3)..].find_uncommented(pat) + .map(|idx| idx + end + i + 3) + }); + } else { + possible_comment = false; + } + } else { + possible_comment = b == '/'; + } + } + + // Handle case where the pattern is a suffix of the search string + match needle_iter.next() { + Some(_) => None, + None => Some(self.len() - pat.len()) + } + } +} + +#[test] +fn test_find_uncommented() { + fn check(haystack: &str, needle: &str, expected: Option) { + assert_eq!(expected, haystack.find_uncommented(needle)); + } + + check("/*//*/test", "test", Some(6)); + check("//test\ntest", "test", Some(7)); + check("/* comment only */", "whatever", None); + check("/* comment */ some text /* more commentary */ result", "result", Some(46)); + check("sup // sup", "p", Some(2)); + check("sup", "x", None); + check("π? /**/ π is nice!", "π is nice", Some(9)); + check("/*sup yo? \n sup*/ sup", "p", Some(20)); + check("hel/*lohello*/lo", "hello", None); + check("acb", "ab", None); +} + #[inline] pub fn prev_char(s: &str, mut i: usize) -> usize { if i == 0 { return 0; } @@ -63,6 +129,7 @@ pub fn round_up_to_power_of_two(mut x: usize) -> usize { x + 1 } +#[inline] #[cfg(target_pointer_width="32")] pub fn round_up_to_power_of_two(mut x: usize) -> usize { x -= 1; diff --git a/tests/target/fn.rs b/tests/target/fn.rs index b78f6d9ffc3..dff8085136e 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -4,13 +4,13 @@ fn foo(a: AAAA, b: BBB, c: CCC) -> RetType { } -fn foo(a: AAAA, b: BBB, c: CCC) -> RetType +fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType where T: Blah { } -fn foo(a: AAA) +fn foo(a: AAA /* (comment) */) where T: Blah { -- cgit 1.4.1-3-g733a5 From 74f050bb5a2545086fe6bff785f47660d1890328 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 15 Jun 2015 21:34:52 +0200 Subject: Fix off-by-one bugs in `rewrite_string_lit` Multi-line literals would typically have a character too many. Splitting of escape sequences also wasn't working correctly. --- src/expr.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c5fb9355b84..eaa7b362b7d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,6 @@ use syntax::print::pprust; use MIN_STRING; impl<'a> FmtVisitor<'a> { - // TODO NEEDS TESTS fn rewrite_string_lit(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { // FIXME I bet this stomps unicode escapes in the source string @@ -40,12 +39,17 @@ impl<'a> FmtVisitor<'a> { let indent = make_indent(offset); let indent = &indent; - let max_chars = width - 1; - let mut cur_start = 0; - let mut result = String::new(); + let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); result.push('"'); loop { + let max_chars = if cur_start == 0 { + // First line. + width - 2 // 2 = " + \ + } else { + config!(max_width) - offset - 1 // 1 = either \ or ; + }; + let mut cur_end = cur_start + max_chars; if cur_end >= s.len() { @@ -64,9 +68,10 @@ impl<'a> FmtVisitor<'a> { // We can't break at whitespace, fall back to splitting // anywhere that doesn't break an escape sequence cur_end = next_char(&s, cur_start + max_chars); - while s.char_at(cur_end) == '\\' { + while s.char_at(prev_char(&s, cur_end)) == '\\' { cur_end = prev_char(&s, cur_end); } + break; } } // Make sure there is no whitespace to the right of the break. -- cgit 1.4.1-3-g733a5 From 5924b83829d5ae53a88bfcb2ea094604e04e3b8a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 20 Jun 2015 01:39:13 +0200 Subject: Rustup --- Cargo.lock | 43 +++++++++++++++++++++++++++++++++---------- src/bin/rustfmt.rs | 24 +----------------------- src/lib.rs | 2 +- 3 files changed, 35 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 975888e0267..97593cfad4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,46 +2,69 @@ name = "rustfmt" version = "0.0.1" dependencies = [ - "diff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "diff 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", "toml 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aho-corasick" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "diff" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libc" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" -version = "0.1.33" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex-syntax 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strings" version = "0.0.1" -source = "git+https://github.com/nrc/strings.rs.git#551331d01911b7e8da056a4a019eb367cfaf03bd" +source = "git+https://github.com/nrc/strings.rs.git#b7f37c4545b7dba24fb28161cd9c405fae978be4" [[package]] name = "toml" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5a12dbd639b..3ee7d888af0 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -9,7 +9,6 @@ // except according to those terms. #![cfg(not(test))] -#![feature(exit_status)] extern crate rustfmt; @@ -24,28 +23,7 @@ fn main() { let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).unwrap(); - //run(args, WriteMode::Display, &def_config); run(args, WriteMode::Overwrite, &def_config); - std::env::set_exit_status(0); - - // TODO unit tests - // let fmt = ListFormatting { - // tactic: ListTactic::Horizontal, - // separator: ",", - // trailing_separator: SeparatorTactic::Vertical, - // indent: 2, - // h_width: 80, - // v_width: 100, - // }; - // let inputs = vec![(format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new()), - // (format!("foo"), String::new())]; - // let s = write_list(&inputs, &fmt); - // println!(" {}", s); + std::process::exit(0); } diff --git a/src/lib.rs b/src/lib.rs index c8fdc2eab96..a07d31bd87d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ // except according to those terms. #![feature(rustc_private)] -#![feature(collections)] +#![feature(str_escape)] #![feature(str_char)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth -- cgit 1.4.1-3-g733a5 From 35c996054a42499f2195ad1945658389812f550a Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 22 Jun 2015 16:49:00 +0200 Subject: Use wrapping operations for bit-level functions This handles a underflow panic on round_up_to_power_of_two(0). --- src/utils.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 5e7f8baf1dc..5bcf16ea36b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -119,26 +119,26 @@ pub fn format_visibility(vis: Visibility) -> &'static str { // Based on the trick layed out at // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 pub fn round_up_to_power_of_two(mut x: usize) -> usize { - x -= 1; + x = x.wrapping_sub(1); x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x |= x >> 32; - x + 1 + x.wrapping_add(1) } #[inline] #[cfg(target_pointer_width="32")] pub fn round_up_to_power_of_two(mut x: usize) -> usize { - x -= 1; + x = x.wrapping_sub(1); x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; - x + 1 + x.wrapping_add(1) } // Macro for deriving implementations of Decodable for enums @@ -161,6 +161,7 @@ macro_rules! impl_enum_decodable { #[test] fn power_rounding() { + assert_eq!(0, round_up_to_power_of_two(0)); assert_eq!(1, round_up_to_power_of_two(1)); assert_eq!(64, round_up_to_power_of_two(33)); assert_eq!(256, round_up_to_power_of_two(256)); -- cgit 1.4.1-3-g733a5 From c012d311c42523c674bf5a01ab0871a4ef267b9c Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Tue, 16 Jun 2015 17:29:05 +0200 Subject: A basic impl of Rewrite for ast::Expr --- src/expr.rs | 372 ++++++++++++++++++++++++++++++--------------------------- src/lib.rs | 1 + src/rewrite.rs | 19 +++ src/visitor.rs | 14 ++- 4 files changed, 225 insertions(+), 181 deletions(-) create mode 100644 src/rewrite.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index eaa7b362b7d..9bf68eb7c12 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use visitor::FmtVisitor; use utils::*; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use rewrite::{Rewrite, RewriteContext}; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span}; @@ -19,194 +19,246 @@ use syntax::print::pprust; use MIN_STRING; -impl<'a> FmtVisitor<'a> { - fn rewrite_string_lit(&mut self, s: &str, span: Span, width: usize, offset: usize) -> String { - // FIXME I bet this stomps unicode escapes in the source string - - // Check if there is anything to fix: we always try to fixup multi-line - // strings, or if the string is too long for the line. - let l_loc = self.codemap.lookup_char_pos(span.lo); - let r_loc = self.codemap.lookup_char_pos(span.hi); - if l_loc.line == r_loc.line && r_loc.col.to_usize() <= config!(max_width) { - return self.snippet(span); +impl Rewrite for ast::Expr { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + match self.node { + ast::Expr_::ExprLit(ref l) => { + match l.node { + ast::Lit_::LitStr(ref is, _) => { + let result = rewrite_string_lit(context, &is, l.span, width, offset); + debug!("string lit: `{:?}`", result); + return result; + } + _ => {} + } + } + ast::Expr_::ExprCall(ref callee, ref args) => { + return rewrite_call(context, callee, args, width, offset); + } + ast::Expr_::ExprParen(ref subexpr) => { + return rewrite_paren(context, subexpr, width, offset); + } + ast::Expr_::ExprStruct(ref path, ref fields, ref base) => { + return rewrite_struct_lit(context, path, + fields, + base.as_ref().map(|e| &**e), + width, + offset); + } + ast::Expr_::ExprTup(ref items) => { + return rewrite_tuple_lit(context, items, width, offset); + } + _ => {} } - // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) + context.codemap.span_to_snippet(self.span).ok() + } +} - let s = s.escape_default(); +fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, width: usize, offset: usize) -> Option { + // FIXME I bet this stomps unicode escapes in the source string - let offset = offset + 1; - let indent = make_indent(offset); - let indent = &indent; + // Check if there is anything to fix: we always try to fixup multi-line + // strings, or if the string is too long for the line. + let l_loc = context.codemap.lookup_char_pos(span.lo); + let r_loc = context.codemap.lookup_char_pos(span.hi); + if l_loc.line == r_loc.line && r_loc.col.to_usize() <= config!(max_width) { + return context.codemap.span_to_snippet(span).ok(); + } - let mut cur_start = 0; - let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); - result.push('"'); - loop { - let max_chars = if cur_start == 0 { - // First line. - width - 2 // 2 = " + \ - } else { - config!(max_width) - offset - 1 // 1 = either \ or ; - }; + // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) - let mut cur_end = cur_start + max_chars; + let s = s.escape_default(); - if cur_end >= s.len() { - result.push_str(&s[cur_start..]); - break; - } + let offset = offset + 1; + let indent = make_indent(offset); + let indent = &indent; + + let mut cur_start = 0; + let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); + result.push('"'); + loop { + let max_chars = if cur_start == 0 { + // First line. + width - 2 // 2 = " + \ + } else { + config!(max_width) - offset - 1 // 1 = either \ or ; + }; - // Make sure we're on a char boundary. - cur_end = next_char(&s, cur_end); + let mut cur_end = cur_start + max_chars; - // Push cur_end left until we reach whitespace - while !s.char_at(cur_end-1).is_whitespace() { - cur_end = prev_char(&s, cur_end); + if cur_end >= s.len() { + result.push_str(&s[cur_start..]); + break; + } - if cur_end - cur_start < MIN_STRING { - // We can't break at whitespace, fall back to splitting - // anywhere that doesn't break an escape sequence - cur_end = next_char(&s, cur_start + max_chars); - while s.char_at(prev_char(&s, cur_end)) == '\\' { - cur_end = prev_char(&s, cur_end); - } - break; + // Make sure we're on a char boundary. + cur_end = next_char(&s, cur_end); + + // Push cur_end left until we reach whitespace + while !s.char_at(cur_end-1).is_whitespace() { + cur_end = prev_char(&s, cur_end); + + if cur_end - cur_start < MIN_STRING { + // We can't break at whitespace, fall back to splitting + // anywhere that doesn't break an escape sequence + cur_end = next_char(&s, cur_start + max_chars); + while s.char_at(prev_char(&s, cur_end)) == '\\' { + cur_end = prev_char(&s, cur_end); } + break; } - // Make sure there is no whitespace to the right of the break. - while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { - cur_end = next_char(&s, cur_end+1); - } - result.push_str(&s[cur_start..cur_end]); - result.push_str("\\\n"); - result.push_str(indent); - - cur_start = cur_end; } - result.push('"'); + // Make sure there is no whitespace to the right of the break. + while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { + cur_end = next_char(&s, cur_end+1); + } + result.push_str(&s[cur_start..cur_end]); + result.push_str("\\\n"); + result.push_str(indent); - result + cur_start = cur_end; } + result.push('"'); - fn rewrite_call(&mut self, + Some(result) +} + +fn rewrite_call(context: &RewriteContext, callee: &ast::Expr, args: &[ptr::P], width: usize, offset: usize) - -> String - { - debug!("rewrite_call, width: {}, offset: {}", width, offset); + -> Option +{ + debug!("rewrite_call, width: {}, offset: {}", width, offset); - // TODO using byte lens instead of char lens (and probably all over the place too) - let callee_str = self.rewrite_expr(callee, width, offset); - debug!("rewrite_call, callee_str: `{}`", callee_str); - // 2 is for parens. - let remaining_width = width - callee_str.len() - 2; - let offset = callee_str.len() + 1 + offset; - let arg_count = args.len(); + // TODO using byte lens instead of char lens (and probably all over the place too) + let callee_str = match callee.rewrite(context, width, offset) { + Some(s) => s, + None => { return None; } + }; + debug!("rewrite_call, callee_str: `{:?}`", callee_str); + // 2 is for parens. + let remaining_width = width - callee_str.len() - 2; + let offset = callee_str.len() + 1 + offset; + let arg_count = args.len(); - let args_str = if arg_count > 0 { - let args: Vec<_> = args.iter().map(|e| (self.rewrite_expr(e, - remaining_width, - offset), String::new())).collect(); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: remaining_width, - v_width: remaining_width, - }; - write_list(&args, &fmt) - } else { - String::new() + let args_str = if arg_count > 0 { + let mut args_rewritten = Vec::with_capacity(args.len()); + for arg in args.iter() { + match arg.rewrite(context, remaining_width, offset) { + Some(s) => { args_rewritten.push((s, String::new())); } + None => { return None; } + } + } + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: remaining_width, + v_width: remaining_width, }; + write_list(&args_rewritten, &fmt) + } else { + String::new() + }; - format!("{}({})", callee_str, args_str) - } + Some(format!("{}({})", callee_str, args_str)) +} - fn rewrite_paren(&mut self, subexpr: &ast::Expr, width: usize, offset: usize) -> String { - debug!("rewrite_paren, width: {}, offset: {}", width, offset); - // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing - // paren on the same line as the subexpr - let subexpr_str = self.rewrite_expr(subexpr, width-2, offset+1); - debug!("rewrite_paren, subexpr_str: `{}`", subexpr_str); - format!("({})", subexpr_str) - } +fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, offset: usize) -> Option { + debug!("rewrite_paren, width: {}, offset: {}", width, offset); + // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing + // paren on the same line as the subexpr + let subexpr_str = subexpr.rewrite(context, width-2, offset+1); + debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); + subexpr_str.map(|s| format!("({})", s)) +} - fn rewrite_struct_lit(&mut self, +fn rewrite_struct_lit(context: &RewriteContext, path: &ast::Path, fields: &[ast::Field], base: Option<&ast::Expr>, width: usize, offset: usize) - -> String - { - debug!("rewrite_struct_lit: width {}, offset {}", width, offset); - assert!(fields.len() > 0 || base.is_some()); + -> Option +{ + debug!("rewrite_struct_lit: width {}, offset {}", width, offset); + assert!(fields.len() > 0 || base.is_some()); - let path_str = pprust::path_to_string(path); - // Foo { a: Foo } - indent is +3, width is -5. - let indent = offset + path_str.len() + 3; - let budget = width - (path_str.len() + 5); + let path_str = pprust::path_to_string(path); + // Foo { a: Foo } - indent is +3, width is -5. + let indent = offset + path_str.len() + 3; + let budget = width - (path_str.len() + 5); - let mut field_strs: Vec<_> = - fields.iter().map(|f| self.rewrite_field(f, budget, indent)).collect(); - if let Some(expr) = base { - // Another 2 on the width/indent for the .. - field_strs.push(format!("..{}", self.rewrite_expr(expr, budget - 2, indent + 2))) + let mut field_strs = Vec::with_capacity(fields.len()); + for field in fields.iter() { + match rewrite_field(context, field, budget, indent) { + Some(s) => { field_strs.push(s); } + None => { return None; } } + } + if let Some(expr) = base { + // Another 2 on the width/indent for the .. + field_strs.push(match expr.rewrite(context, budget - 2, indent + 2) { + Some(s) => format!("..{}", s), + None => { return None; } + }); + } - // FIXME comments - let field_strs: Vec<_> = field_strs.into_iter().map(|s| (s, String::new())).collect(); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: if base.is_some() { - SeparatorTactic::Never - } else { - config!(struct_lit_trailing_comma) - }, - indent: indent, - h_width: budget, - v_width: budget, - }; - let fields_str = write_list(&field_strs, &fmt); - format!("{} {{ {} }}", path_str, fields_str) + // FIXME comments + let field_strs: Vec<_> = field_strs.into_iter().map(|s| (s, String::new())).collect(); + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: if base.is_some() { + SeparatorTactic::Never + } else { + config!(struct_lit_trailing_comma) + }, + indent: indent, + h_width: budget, + v_width: budget, + }; + let fields_str = write_list(&field_strs, &fmt); + Some(format!("{} {{ {} }}", path_str, fields_str)) // FIXME if the usual multi-line layout is too wide, we should fall back to // Foo { // a: ..., // } - } +} - fn rewrite_field(&mut self, field: &ast::Field, width: usize, offset: usize) -> String { - let name = &token::get_ident(field.ident.node); - let overhead = name.len() + 2; - let expr = self.rewrite_expr(&field.expr, width - overhead, offset + overhead); - format!("{}: {}", name, expr) - } +fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, offset: usize) -> Option { + let name = &token::get_ident(field.ident.node); + let overhead = name.len() + 2; + let expr = field.expr.rewrite(context, width - overhead, offset + overhead); + expr.map(|s| format!("{}: {}", name, s)) +} - fn rewrite_tuple_lit(&mut self, items: &[ptr::P], width: usize, offset: usize) - -> String { +fn rewrite_tuple_lit(context: &RewriteContext, items: &[ptr::P], width: usize, offset: usize) + -> Option { // opening paren let indent = offset + 1; // In case of length 1, need a trailing comma if items.len() == 1 { - return format!("({},)", self.rewrite_expr(&*items[0], width - 3, indent)); + return items[0].rewrite(context, width - 3, indent).map(|s| format!("({},)", s)); } // Only last line has width-1 as budget, other may take max_width - let item_strs: Vec<_> = - items.iter() - .enumerate() - .map(|(i, item)| self.rewrite_expr( - item, - // last line : given width (minus "("+")"), other lines : max_width - // (minus "("+",")) - if i == items.len() - 1 { width - 2 } else { config!(max_width) - indent - 2 }, - indent)) - .collect(); + let mut item_strs = Vec::with_capacity(items.len()); + for (i, item) in items.iter().enumerate() { + let rem_width = if i == items.len() - 1 { + width - 2 + } else { + config!(max_width) - indent - 2 + }; + match item.rewrite(context, rem_width, indent) { + Some(s) => { item_strs.push(s); } + None => {return None; } + } + } let tactics = if item_strs.iter().any(|s| s.contains('\n')) { ListTactic::Vertical } else { @@ -223,41 +275,5 @@ impl<'a> FmtVisitor<'a> { v_width: width - 2, }; let item_str = write_list(&item_strs, &fmt); - format!("({})", item_str) - } - - - pub fn rewrite_expr(&mut self, expr: &ast::Expr, width: usize, offset: usize) -> String { - match expr.node { - ast::Expr_::ExprLit(ref l) => { - match l.node { - ast::Lit_::LitStr(ref is, _) => { - let result = self.rewrite_string_lit(&is, l.span, width, offset); - debug!("string lit: `{}`", result); - return result; - } - _ => {} - } - } - ast::Expr_::ExprCall(ref callee, ref args) => { - return self.rewrite_call(callee, args, width, offset); - } - ast::Expr_::ExprParen(ref subexpr) => { - return self.rewrite_paren(subexpr, width, offset); - } - ast::Expr_::ExprStruct(ref path, ref fields, ref base) => { - return self.rewrite_struct_lit(path, - fields, - base.as_ref().map(|e| &**e), - width, - offset); - } - ast::Expr_::ExprTup(ref items) => { - return self.rewrite_tuple_lit(items, width, offset); - } - _ => {} - } - - self.snippet(expr.span) + Some(format!("({})", item_str)) } -} diff --git a/src/lib.rs b/src/lib.rs index a07d31bd87d..1b360433e94 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,7 @@ mod types; mod expr; mod imports; mod issues; +mod rewrite; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. diff --git a/src/rewrite.rs b/src/rewrite.rs new file mode 100644 index 00000000000..4eed7421ff0 --- /dev/null +++ b/src/rewrite.rs @@ -0,0 +1,19 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::codemap::CodeMap; + +pub trait Rewrite { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option; +} + +pub struct RewriteContext<'a> { + pub codemap: &'a CodeMap, +} diff --git a/src/visitor.rs b/src/visitor.rs index 3c9f3ac1b23..1f8e0d5fa2e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,6 +16,7 @@ use utils; use SKIP_ANNOTATION; use changes::ChangeSet; +use rewrite::{Rewrite, RewriteContext}; pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, @@ -32,9 +33,16 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); - let new_str = self.rewrite_expr(ex, config!(max_width) - offset, offset); - self.changes.push_str_span(ex.span, &new_str); - self.last_pos = ex.span.hi; + match ex.rewrite(&RewriteContext { codemap: self.codemap }, + config!(max_width) - offset, + offset) { + Some(new_str) => { + //let new_str = self.rewrite_expr(ex, config!(max_width) - offset, offset); + self.changes.push_str_span(ex.span, &new_str); + self.last_pos = ex.span.hi; + } + None => { self.last_pos = ex.span.lo; } + } } fn visit_stmt(&mut self, stmt: &'v ast::Stmt) { -- cgit 1.4.1-3-g733a5 From 2161400c7da89dbae504a9ca620e0b37c9af8782 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 22 Jun 2015 02:53:28 +0200 Subject: Add a try_opt! macro for ease of work with Rewrite --- src/expr.rs | 49 +++++++++++++++++++------------------------------ src/utils.rs | 9 +++++++++ 2 files changed, 28 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9bf68eb7c12..dbb526ac482 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -125,19 +125,16 @@ fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, width: usiz } fn rewrite_call(context: &RewriteContext, - callee: &ast::Expr, - args: &[ptr::P], - width: usize, - offset: usize) + callee: &ast::Expr, + args: &[ptr::P], + width: usize, + offset: usize) -> Option { debug!("rewrite_call, width: {}, offset: {}", width, offset); // TODO using byte lens instead of char lens (and probably all over the place too) - let callee_str = match callee.rewrite(context, width, offset) { - Some(s) => s, - None => { return None; } - }; + let callee_str = try_opt!(callee.rewrite(context, width, offset)); debug!("rewrite_call, callee_str: `{:?}`", callee_str); // 2 is for parens. let remaining_width = width - callee_str.len() - 2; @@ -147,10 +144,8 @@ fn rewrite_call(context: &RewriteContext, let args_str = if arg_count > 0 { let mut args_rewritten = Vec::with_capacity(args.len()); for arg in args.iter() { - match arg.rewrite(context, remaining_width, offset) { - Some(s) => { args_rewritten.push((s, String::new())); } - None => { return None; } - } + args_rewritten.push((try_opt!(arg.rewrite(context, remaining_width, offset)), + String::new())); } let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, @@ -178,11 +173,11 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, of } fn rewrite_struct_lit(context: &RewriteContext, - path: &ast::Path, - fields: &[ast::Field], - base: Option<&ast::Expr>, - width: usize, - offset: usize) + path: &ast::Path, + fields: &[ast::Field], + base: Option<&ast::Expr>, + width: usize, + offset: usize) -> Option { debug!("rewrite_struct_lit: width {}, offset {}", width, offset); @@ -195,17 +190,11 @@ fn rewrite_struct_lit(context: &RewriteContext, let mut field_strs = Vec::with_capacity(fields.len()); for field in fields.iter() { - match rewrite_field(context, field, budget, indent) { - Some(s) => { field_strs.push(s); } - None => { return None; } - } + field_strs.push(try_opt!(rewrite_field(context, field, budget, indent))); } if let Some(expr) = base { // Another 2 on the width/indent for the .. - field_strs.push(match expr.rewrite(context, budget - 2, indent + 2) { - Some(s) => format!("..{}", s), - None => { return None; } - }); + field_strs.push(format!("..{}", try_opt!(expr.rewrite(context, budget - 2, indent + 2)))); } // FIXME comments @@ -238,7 +227,10 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, off expr.map(|s| format!("{}: {}", name, s)) } -fn rewrite_tuple_lit(context: &RewriteContext, items: &[ptr::P], width: usize, offset: usize) +fn rewrite_tuple_lit(context: &RewriteContext, + items: &[ptr::P], + width: usize, + offset: usize) -> Option { // opening paren let indent = offset + 1; @@ -254,10 +246,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, items: &[ptr::P], widt } else { config!(max_width) - indent - 2 }; - match item.rewrite(context, rem_width, indent) { - Some(s) => { item_strs.push(s); } - None => {return None; } - } + item_strs.push(try_opt!(item.rewrite(context, rem_width, indent))); } let tactics = if item_strs.iter().any(|s| s.contains('\n')) { ListTactic::Vertical diff --git a/src/utils.rs b/src/utils.rs index 5bcf16ea36b..795c0d98309 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -159,6 +159,15 @@ macro_rules! impl_enum_decodable { }; } +// Same as try!, but for Option +#[macro_export] +macro_rules! try_opt { + ($expr:expr) => (match $expr { + Some(val) => val, + None => { return None; } + }) +} + #[test] fn power_rounding() { assert_eq!(0, round_up_to_power_of_two(0)); -- cgit 1.4.1-3-g733a5 From ad658885d421119dcc33d8d5df41a5740eb33454 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 22 Jun 2015 03:04:34 +0200 Subject: Comments for Rewrite --- src/rewrite.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/rewrite.rs b/src/rewrite.rs index 4eed7421ff0..354e9b17061 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -8,9 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// A generic trait to abstract the rewriting of an element (of the AST). + use syntax::codemap::CodeMap; pub trait Rewrite { + /// Rewrite self into offset and width. + /// `offset` is the indentation of the first line. The next lines + /// should begin with a least `offset` spaces (except backwards + /// indentation). The first line should not begin with indentation. + /// `width` is the maximum number of characters on the last line + /// (excluding offset). The width of other lines is not limited by + /// `width`. fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option; } -- cgit 1.4.1-3-g733a5 From b7ead806f4309485ec1cf27eb04fc9c3d524895d Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 22 Jun 2015 13:33:19 +0200 Subject: Use FromIterator implementation for Option Combined with try_opt!, this avoid an explicit for loop or another macro. --- src/expr.rs | 50 +++++++++++++++++++++++++++----------------------- src/visitor.rs | 1 - 2 files changed, 27 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dbb526ac482..85ea41fb060 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -142,11 +142,11 @@ fn rewrite_call(context: &RewriteContext, let arg_count = args.len(); let args_str = if arg_count > 0 { - let mut args_rewritten = Vec::with_capacity(args.len()); - for arg in args.iter() { - args_rewritten.push((try_opt!(arg.rewrite(context, remaining_width, offset)), - String::new())); - } + let args_rewritten: Vec<_> = + try_opt!(args.iter() + .map(|arg| arg.rewrite(context, remaining_width, offset) + .map(|arg_str| (arg_str, String::new()))) + .collect()); let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, separator: ",", @@ -188,15 +188,16 @@ fn rewrite_struct_lit(context: &RewriteContext, let indent = offset + path_str.len() + 3; let budget = width - (path_str.len() + 5); - let mut field_strs = Vec::with_capacity(fields.len()); - for field in fields.iter() { - field_strs.push(try_opt!(rewrite_field(context, field, budget, indent))); - } - if let Some(expr) = base { - // Another 2 on the width/indent for the .. - field_strs.push(format!("..{}", try_opt!(expr.rewrite(context, budget - 2, indent + 2)))); - } - + let field_strs: Vec<_> = + try_opt!(fields.iter() + .map(|field| rewrite_field(context, field, budget, indent)) + .chain(base.iter() + .map(|expr| expr.rewrite(context, + // 2 = ".." + budget - 2, + indent + 2) + .map(|s| format!("..{}", s)))) + .collect()); // FIXME comments let field_strs: Vec<_> = field_strs.into_iter().map(|s| (s, String::new())).collect(); let fmt = ListFormatting { @@ -239,15 +240,18 @@ fn rewrite_tuple_lit(context: &RewriteContext, return items[0].rewrite(context, width - 3, indent).map(|s| format!("({},)", s)); } // Only last line has width-1 as budget, other may take max_width - let mut item_strs = Vec::with_capacity(items.len()); - for (i, item) in items.iter().enumerate() { - let rem_width = if i == items.len() - 1 { - width - 2 - } else { - config!(max_width) - indent - 2 - }; - item_strs.push(try_opt!(item.rewrite(context, rem_width, indent))); - } + let item_strs: Vec<_> = + try_opt!(items.iter() + .enumerate() + .map(|(i, item)| { + let rem_width = if i == items.len() - 1 { + width - 2 + } else { + config!(max_width) - indent - 2 + }; + item.rewrite(context, rem_width, indent) + }) + .collect()); let tactics = if item_strs.iter().any(|s| s.contains('\n')) { ListTactic::Vertical } else { diff --git a/src/visitor.rs b/src/visitor.rs index 1f8e0d5fa2e..0b9a9cfa46b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -37,7 +37,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { config!(max_width) - offset, offset) { Some(new_str) => { - //let new_str = self.rewrite_expr(ex, config!(max_width) - offset, offset); self.changes.push_str_span(ex.span, &new_str); self.last_pos = ex.span.hi; } -- cgit 1.4.1-3-g733a5 From d7b49fd76ce4d38beda129c7b8a733e62729bcb0 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 23 Jun 2015 13:26:04 +0200 Subject: Remove global mutable config to allow for concurrency --- src/changes.rs | 22 +++++++++++++--------- src/config.rs | 16 ++-------------- src/expr.rs | 8 ++++---- src/items.rs | 44 ++++++++++++++++++++++---------------------- src/lib.rs | 35 ++++++++++++++++++++--------------- src/rewrite.rs | 3 +++ src/visitor.rs | 32 +++++++++++++++++--------------- tests/system.rs | 50 ++++++++++++++++++++++++++------------------------ 8 files changed, 107 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 97133ab67fb..7a16a5bca66 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -21,6 +21,7 @@ use std::fs::File; use std::io::{Write, stdout}; use WriteMode; use NewlineStyle; +use config::Config; use utils::round_up_to_power_of_two; // This is basically a wrapper around a bunch of Ropes which makes it convenient @@ -130,11 +131,12 @@ impl<'a> ChangeSet<'a> { } pub fn write_all_files(&self, - mode: WriteMode) + mode: WriteMode, + config: &Config) -> Result<(HashMap), ::std::io::Error> { let mut result = HashMap::new(); for filename in self.file_map.keys() { - let one_result = try!(self.write_file(filename, mode)); + let one_result = try!(self.write_file(filename, mode, config)); if let Some(r) = one_result { result.insert(filename.clone(), r); } @@ -145,18 +147,20 @@ impl<'a> ChangeSet<'a> { pub fn write_file(&self, filename: &str, - mode: WriteMode) + mode: WriteMode, + config: &Config) -> Result, ::std::io::Error> { let text = &self.file_map[filename]; // prints all newlines either as `\n` or as `\r\n` fn write_system_newlines( mut writer: T, - text: &StringBuffer) + text: &StringBuffer, + config: &Config) -> Result<(), ::std::io::Error> where T: Write, { - match config!(newline_style) { + match config.newline_style { NewlineStyle::Unix => write!(writer, "{}", text), NewlineStyle::Windows => { for (c, _) in text.chars() { @@ -181,7 +185,7 @@ impl<'a> ChangeSet<'a> { { // Write text to temp file let tmp_file = try!(File::create(&tmp_name)); - try!(write_system_newlines(tmp_file, text)); + try!(write_system_newlines(tmp_file, text, config)); } try!(::std::fs::rename(filename, bk_name)); @@ -190,18 +194,18 @@ impl<'a> ChangeSet<'a> { WriteMode::NewFile(extn) => { let filename = filename.to_owned() + "." + extn; let file = try!(File::create(&filename)); - try!(write_system_newlines(file, text)); + try!(write_system_newlines(file, text, config)); } WriteMode::Display => { println!("{}:\n", filename); let stdout = stdout(); let stdout_lock = stdout.lock(); - try!(write_system_newlines(stdout_lock, text)); + try!(write_system_newlines(stdout_lock, text, config)); } WriteMode::Return(_) => { // io::Write is not implemented for String, working around with Vec let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text)); + try!(write_system_newlines(&mut v, text, config)); // won't panic, we are writing correct utf8 return Ok(Some(String::from_utf8(v).unwrap())); } diff --git a/src/config.rs b/src/config.rs index c803a07d9d0..23285167689 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,7 +14,7 @@ use {NewlineStyle, BraceStyle, ReturnIndent}; use lists::SeparatorTactic; use issues::ReportTactic; -#[derive(RustcDecodable)] +#[derive(RustcDecodable, Clone)] pub struct Config { pub max_width: usize, pub ideal_width: usize, @@ -32,20 +32,8 @@ pub struct Config { } impl Config { - fn from_toml(toml: &str) -> Config { + pub fn from_toml(toml: &str) -> Config { let parsed = toml.parse().unwrap(); toml::decode(parsed).unwrap() } } - -pub fn set_config(toml: &str) { - unsafe { - ::CONFIG = Some(Config::from_toml(toml)); - } -} - -macro_rules! config { - ($name: ident) => { - unsafe { ::CONFIG.as_ref().unwrap().$name } - }; -} diff --git a/src/expr.rs b/src/expr.rs index 85ea41fb060..dae64891ab3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -62,7 +62,7 @@ fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, width: usiz // strings, or if the string is too long for the line. let l_loc = context.codemap.lookup_char_pos(span.lo); let r_loc = context.codemap.lookup_char_pos(span.hi); - if l_loc.line == r_loc.line && r_loc.col.to_usize() <= config!(max_width) { + if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width { return context.codemap.span_to_snippet(span).ok(); } @@ -82,7 +82,7 @@ fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, width: usiz // First line. width - 2 // 2 = " + \ } else { - config!(max_width) - offset - 1 // 1 = either \ or ; + context.config.max_width - offset - 1 // 1 = either \ or ; }; let mut cur_end = cur_start + max_chars; @@ -206,7 +206,7 @@ fn rewrite_struct_lit(context: &RewriteContext, trailing_separator: if base.is_some() { SeparatorTactic::Never } else { - config!(struct_lit_trailing_comma) + context.config.struct_lit_trailing_comma }, indent: indent, h_width: budget, @@ -247,7 +247,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, let rem_width = if i == items.len() - 1 { width - 2 } else { - config!(max_width) - indent - 2 + context.config.max_width - indent - 2 }; item.rewrite(context, rem_width, indent) }) diff --git a/src/items.rs b/src/items.rs index 29c950f1464..2dfa8a5fe65 100644 --- a/src/items.rs +++ b/src/items.rs @@ -144,7 +144,7 @@ impl<'a> FmtVisitor<'a> { // Check if vertical layout was forced by compute_budget_for_args. if one_line_budget <= 0 { - if config!(fn_args_paren_newline) { + if self.config.fn_args_paren_newline { result.push('\n'); result.push_str(&make_indent(arg_indent)); arg_indent = arg_indent + 1; // extra space for `(` @@ -170,8 +170,8 @@ impl<'a> FmtVisitor<'a> { // If we've already gone multi-line, or the return type would push // over the max width, then put the return type on a new line. if result.contains("\n") || - result.len() + indent + ret_str.len() > config!(max_width) { - let indent = match config!(fn_return_indent) { + result.len() + indent + ret_str.len() > self.config.max_width { + let indent = match self.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, // TODO we might want to check that using the arg indent doesn't // blow our budget, and if it does, then fallback to the where @@ -363,15 +363,15 @@ impl<'a> FmtVisitor<'a> { if !newline_brace { used_space += 2; } - let one_line_budget = if used_space > config!(max_width) { + let one_line_budget = if used_space > self.config.max_width { 0 } else { - config!(max_width) - used_space + self.config.max_width - used_space }; // 2 = `()` let used_space = indent + result.len() + 2; - let max_space = config!(ideal_width) + config!(leeway); + let max_space = self.config.ideal_width + self.config.leeway; debug!("compute_budgets_for_args: used_space: {}, max_space: {}", used_space, max_space); if used_space < max_space { @@ -383,9 +383,9 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. if let None = budgets { - let new_indent = indent + config!(tab_spaces); + let new_indent = indent + self.config.tab_spaces; let used_space = new_indent + 2; // account for `(` and `)` - let max_space = config!(ideal_width) + config!(leeway); + let max_space = self.config.ideal_width + self.config.leeway; if used_space > max_space { // Whoops! bankrupt. // TODO take evasive action, perhaps kill the indent or something. @@ -398,7 +398,7 @@ impl<'a> FmtVisitor<'a> { } fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { - match config!(fn_brace_style) { + match self.config.fn_brace_style { BraceStyle::AlwaysNextLine => true, BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, _ => false, @@ -421,7 +421,7 @@ impl<'a> FmtVisitor<'a> { self.changes.push_str_span(span, &generics_str); self.last_pos = body_start; - self.block_indent += config!(tab_spaces); + self.block_indent += self.config.tab_spaces; for (i, f) in enum_def.variants.iter().enumerate() { let next_span_start: BytePos = if i == enum_def.variants.len() - 1 { span.hi @@ -431,7 +431,7 @@ impl<'a> FmtVisitor<'a> { self.visit_variant(f, i == enum_def.variants.len() - 1, next_span_start); } - self.block_indent -= config!(tab_spaces); + self.block_indent -= self.config.tab_spaces; self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32)); self.changes.push_str_span(span, "}"); @@ -478,8 +478,8 @@ impl<'a> FmtVisitor<'a> { + field.node.name.to_string().len() + 1; // 1 = ( - let comma_cost = if config!(enum_trailing_comma) { 1 } else { 0 }; - let budget = config!(ideal_width) - indent - comma_cost - 1; // 1 = ) + let comma_cost = if self.config.enum_trailing_comma { 1 } else { 0 }; + let budget = self.config.ideal_width - indent - comma_cost - 1; // 1 = ) let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, @@ -500,13 +500,13 @@ impl<'a> FmtVisitor<'a> { // Make sure we do not exceed column limit // 4 = " = ," - assert!(config!(max_width) >= vis.len() + name.len() + expr_snippet.len() + 4, + assert!(self.config.max_width >= vis.len() + name.len() + expr_snippet.len() + 4, "Enum variant exceeded column limit"); } self.changes.push_str_span(field.span, &result); - if !last_field || config!(enum_trailing_comma) { + if !last_field || self.config.enum_trailing_comma { self.changes.push_str_span(field.span, ","); } } @@ -543,11 +543,11 @@ impl<'a> FmtVisitor<'a> { // This will drop the comment in between the header and body. self.last_pos = span.lo + BytePos(struct_snippet.find_uncommented("{").unwrap() as u32 + 1); - self.block_indent += config!(tab_spaces); + self.block_indent += self.config.tab_spaces; for (i, f) in struct_def.fields.iter().enumerate() { self.visit_field(f, i == struct_def.fields.len() - 1, span.lo, &struct_snippet); } - self.block_indent -= config!(tab_spaces); + self.block_indent -= self.config.tab_spaces; self.format_missing_with_indent(span.lo + BytePos(struct_snippet.rfind('}').unwrap() as u32)); self.changes.push_str_span(span, "}"); @@ -608,13 +608,13 @@ impl<'a> FmtVisitor<'a> { let mut field_str = match name { Some(name) => { - let budget = config!(ideal_width) - self.block_indent; + let budget = self.config.ideal_width - self.block_indent; // 3 is being conservative and assuming that there will be a trailing comma. if self.block_indent + vis.len() + name.len() + typ.len() + 3 > budget { format!("{}{}:\n{}{}", vis, name, - &make_indent(self.block_indent + config!(tab_spaces)), + &make_indent(self.block_indent + self.config.tab_spaces), typ) } else { format!("{}{}: {}", vis, name, typ) @@ -622,7 +622,7 @@ impl<'a> FmtVisitor<'a> { } None => format!("{}{}", vis, typ), }; - if !last_field || config!(struct_trailing_comma) { + if !last_field || self.config.struct_trailing_comma { field_str.push(','); } self.changes.push_str_span(field.span, &field_str); @@ -647,7 +647,7 @@ impl<'a> FmtVisitor<'a> { return result; } - let budget = config!(max_width) - indent - 2; + let budget = self.config.max_width - indent - 2; // TODO might need to insert a newline if the generics are really long result.push('<'); @@ -723,7 +723,7 @@ impl<'a> FmtVisitor<'a> { .zip(comments.into_iter()) .collect(); - let budget = config!(ideal_width) + config!(leeway) - indent - 10; + let budget = self.config.ideal_width + self.config.leeway - indent - 10; let fmt = ListFormatting { tactic: ListTactic::Vertical, separator: ",", diff --git a/src/lib.rs b/src/lib.rs index 1b360433e94..dfcf4c70424 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,10 +41,12 @@ use syntax::visit; use std::path::PathBuf; use std::collections::HashMap; use std::fmt; +use std::mem::swap; use issues::{BadIssueSeeker, Issue}; use changes::ChangeSet; use visitor::FmtVisitor; +use config::Config; #[macro_use] mod config; @@ -65,8 +67,6 @@ const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; -static mut CONFIG: Option = None; - #[derive(Copy, Clone)] pub enum WriteMode { Overwrite, @@ -109,7 +109,7 @@ pub enum ReturnIndent { impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); enum ErrorKind { - // Line has more than config!(max_width) characters + // Line has exceeded character limit LineOverflow, // Line ends in whitespace TrailingWhitespace, @@ -161,8 +161,8 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut visitor = FmtVisitor::from_codemap(codemap); +fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> { + let mut visitor = FmtVisitor::from_codemap(codemap, config); visit::walk_crate(&mut visitor, krate); let files = codemap.files.borrow(); if let Some(last) = files.last() { @@ -175,7 +175,7 @@ fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap) -> ChangeSet<'a> { // Formatting done on a char by char or line by line basis. // TODO warn on bad license // TODO other stuff for parity with make tidy -fn fmt_lines(changes: &mut ChangeSet) -> FormatReport { +fn fmt_lines(changes: &mut ChangeSet, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; @@ -187,8 +187,8 @@ fn fmt_lines(changes: &mut ChangeSet) -> FormatReport { let mut cur_line = 1; let mut newline_count = 0; let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config!(report_todo), - config!(report_fixme)); + let mut issue_seeker = BadIssueSeeker::new(config.report_todo, + config.report_fixme); for (c, b) in text.chars() { if c == '\r' { continue; } @@ -208,7 +208,7 @@ fn fmt_lines(changes: &mut ChangeSet) -> FormatReport { line_len -= b - lw; } // Check for any line width errors we couldn't correct. - if line_len > config!(max_width) { + if line_len > config.max_width { errors.push(FormattingError { line: cur_line, kind: ErrorKind::LineOverflow @@ -256,6 +256,7 @@ fn fmt_lines(changes: &mut ChangeSet) -> FormatReport { struct RustFmtCalls { input_path: Option, write_mode: WriteMode, + config: Option>, } impl<'a> CompilerCalls<'a> for RustFmtCalls { @@ -302,18 +303,23 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { let write_mode = self.write_mode; + + let mut config_option = None; + swap(&mut self.config, &mut config_option); + let config = config_option.unwrap(); + let mut control = driver::CompileController::basic(); control.after_parse.stop = Compilation::Stop; control.after_parse.callback = Box::new(move |state| { let krate = state.krate.unwrap(); let codemap = state.session.codemap(); - let mut changes = fmt_ast(krate, codemap); + let mut changes = fmt_ast(krate, codemap, &*config); // For some reason, the codemap does not include terminating newlines // so we must add one on for each file. This is sad. changes.append_newlines(); - println!("{}", fmt_lines(&mut changes)); + println!("{}", fmt_lines(&mut changes, &*config)); - let result = changes.write_all_files(write_mode); + let result = changes.write_all_files(write_mode, &*config); match result { Err(msg) => println!("Error writing files: {}", msg), @@ -335,8 +341,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { // WriteMode. // default_config is a string of toml data to be used to configure rustfmt. pub fn run(args: Vec, write_mode: WriteMode, default_config: &str) { - config::set_config(default_config); - - let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode }; + let config = Some(Box::new(config::Config::from_toml(default_config))); + let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode, config: config }; rustc_driver::run_compiler(&args, &mut call_ctxt); } diff --git a/src/rewrite.rs b/src/rewrite.rs index 354e9b17061..78d611253dd 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -12,6 +12,8 @@ use syntax::codemap::CodeMap; +use config::Config; + pub trait Rewrite { /// Rewrite self into offset and width. /// `offset` is the indentation of the first line. The next lines @@ -25,4 +27,5 @@ pub trait Rewrite { pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, + pub config: &'a Config, } diff --git a/src/visitor.rs b/src/visitor.rs index e70ecc95b4f..88b5d4b18dc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -13,6 +13,7 @@ use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; use utils; +use config::Config; use SKIP_ANNOTATION; use changes::ChangeSet; @@ -24,6 +25,7 @@ pub struct FmtVisitor<'a> { pub last_pos: BytePos, // TODO RAII util for indenting pub block_indent: usize, + pub config: &'a Config, } impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { @@ -33,14 +35,12 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); - match ex.rewrite(&RewriteContext { codemap: self.codemap }, - config!(max_width) - offset, - offset) { - Some(new_str) => { - self.changes.push_str_span(ex.span, &new_str); - self.last_pos = ex.span.hi; - } - None => { self.last_pos = ex.span.lo; } + let context = RewriteContext { codemap: self.codemap, config: self.config }; + let rewrite = ex.rewrite(&context, self.config.max_width - offset, offset); + + if let Some(new_str) = rewrite { + self.changes.push_str_span(ex.span, &new_str); + self.last_pos = ex.span.hi; } } @@ -72,7 +72,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.changes.push_str_span(b.span, "{"); self.last_pos = self.last_pos + BytePos(1); - self.block_indent += config!(tab_spaces); + self.block_indent += self.config.tab_spaces; for stmt in &b.stmts { self.visit_stmt(&stmt) @@ -85,7 +85,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { None => {} } - self.block_indent -= config!(tab_spaces); + self.block_indent -= self.config.tab_spaces; // TODO we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - BytePos(1)); self.changes.push_str_span(b.span, "}"); @@ -162,8 +162,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match vp.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { let block_indent = self.block_indent; - let one_line_budget = config!(max_width) - block_indent; - let multi_line_budget = config!(ideal_width) - block_indent; + let one_line_budget = self.config.max_width - block_indent; + let multi_line_budget = self.config.ideal_width - block_indent; let formatted = self.rewrite_use_list(block_indent, one_line_budget, multi_line_budget, @@ -183,6 +183,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { }; self.format_missing(span_end); } + self.last_pos = item.span.hi; } ast::ViewPath_::ViewPathGlob(_) => { @@ -195,9 +196,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { ast::Item_::ItemImpl(..) | ast::Item_::ItemMod(_) | ast::Item_::ItemTrait(..) => { - self.block_indent += config!(tab_spaces); + self.block_indent += self.config.tab_spaces; visit::walk_item(self, item); - self.block_indent -= config!(tab_spaces); + self.block_indent -= self.config.tab_spaces; } ast::Item_::ItemExternCrate(_) => { self.format_missing_with_indent(item.span.lo); @@ -273,12 +274,13 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } impl<'a> FmtVisitor<'a> { - pub fn from_codemap<'b>(codemap: &'b CodeMap) -> FmtVisitor<'b> { + pub fn from_codemap<'b>(codemap: &'b CodeMap, config: &'b Config) -> FmtVisitor<'b> { FmtVisitor { codemap: codemap, changes: ChangeSet::from_codemap(codemap), last_pos: BytePos(0), block_indent: 0, + config: config } } diff --git a/tests/system.rs b/tests/system.rs index d0769a855ac..4b29376ffa7 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -26,39 +26,44 @@ fn get_path_string(dir_entry: io::Result) -> String { path.to_str().expect("Couldn't stringify path.").to_owned() } -// Integration tests and idempotence tests. The files in the tests/source are -// formatted and compared to their equivalent in tests/target. The target file -// and config can be overriden by annotations in the source file. The input and -// output must match exactly. -// Files in tests/target are checked to be unaltered by rustfmt. -// FIXME(#28) would be good to check for error messages and fail on them, or at least report. +// Integration tests. The files in the tests/source are formatted and compared +// to their equivalent in tests/target. The target file and config can be +// overriden by annotations in the source file. The input and output must match +// exactly. +// FIXME(#28) would be good to check for error messages and fail on them, or at +// least report. #[test] fn system_tests() { - // Get all files in the tests/target directory - let files = fs::read_dir("tests/target").ok().expect("Couldn't read dir 1."); - let files = files.chain(fs::read_dir("tests").ok().expect("Couldn't read dir 2.")); - let files = files.chain(fs::read_dir("src/bin").ok().expect("Couldn't read dir 3.")); + // Get all files in the tests/source directory + let files = fs::read_dir("tests/source").ok().expect("Couldn't read source dir."); // turn a DirEntry into a String that represents the relative path to the file let files = files.map(get_path_string); - // hack because there's no `IntoIterator` impl for `[T; N]` - let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); let (count, fails) = check_files(files); // Display results - println!("Ran {} idempotent tests.", count); - assert!(fails == 0, "{} idempotent tests failed", fails); + println!("Ran {} system tests.", count); + assert!(fails == 0, "{} system tests failed", fails); +} - // Get all files in the tests/source directory - let files = fs::read_dir("tests/source").ok().expect("Couldn't read dir 4."); +// Idempotence tests. Files in tests/target are checked to be unaltered by +// rustfmt. +#[test] +fn idempotence_tests() { + // Get all files in the tests/target directory + let files = fs::read_dir("tests/target").ok().expect("Couldn't read target dir."); + let files = files.chain(fs::read_dir("tests").ok().expect("Couldn't read tests dir.")); + let files = files.chain(fs::read_dir("src/bin").ok().expect("Couldn't read src dir.")); // turn a DirEntry into a String that represents the relative path to the file let files = files.map(get_path_string); + // hack because there's no `IntoIterator` impl for `[T; N]` + let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); let (count, fails) = check_files(files); // Display results - println!("Ran {} system tests.", count); - assert!(fails == 0, "{} system tests failed", fails); + println!("Ran {} idempotent tests.", count); + assert!(fails == 0, "{} idempotent tests failed", fails); } // For each file, run rustfmt and collect the output. @@ -71,12 +76,9 @@ fn check_files(files: I) -> (u32, u32) for file_name in files.filter(|f| f.ends_with(".rs")) { println!("Testing '{}'...", file_name); - match idempotent_check(file_name) { - Ok(()) => {}, - Err(m) => { - print_mismatches(m); - fails += 1; - }, + if let Err(msg) = idempotent_check(file_name) { + print_mismatches(msg); + fails += 1; } count += 1; } -- cgit 1.4.1-3-g733a5 From 0ef5db9496fddfb5a26131a5a4dc8b2fcce40dde Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 23 Jun 2015 15:58:58 +0200 Subject: Format tuple-like structs --- src/comment.rs | 202 +++++++++++++++++ src/config.rs | 2 +- src/default.toml | 2 +- src/expr.rs | 223 ++++++++---------- src/imports.rs | 20 +- src/issues.rs | 1 - src/items.rs | 524 +++++++++++++++++++++++-------------------- src/lib.rs | 2 + src/lists.rs | 241 +++++++++++++++++--- src/string.rs | 103 +++++++++ src/utils.rs | 80 ++----- src/visitor.rs | 36 +-- tests/config/small_tabs.toml | 2 +- tests/source/fn-simple.rs | 11 + tests/source/multiple.rs | 2 +- tests/source/structs.rs | 70 ++++++ tests/target/comments-fn.rs | 4 +- tests/target/enum.rs | 14 +- tests/target/fn-simple.rs | 16 ++ tests/target/multiple.rs | 9 +- tests/target/structs.rs | 29 +++ tests/target/tuple.rs | 4 + 22 files changed, 1079 insertions(+), 518 deletions(-) create mode 100644 src/comment.rs create mode 100644 src/string.rs create mode 100644 tests/source/fn-simple.rs create mode 100644 tests/source/structs.rs create mode 100644 tests/target/fn-simple.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs new file mode 100644 index 00000000000..a1338d5b369 --- /dev/null +++ b/src/comment.rs @@ -0,0 +1,202 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format comments. + +use string::{StringFormat, rewrite_string}; +use utils::make_indent; + +pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usize) -> String { + let s = orig.trim(); + + // Edge case: block comments. Let's not trim their lines (for now). + let opener = if block_style { "/* " } else { "// " }; + let closer = if block_style { " */" } else { "" }; + let line_start = if block_style { " * " } else { "// " }; + + let max_chars = width.checked_sub(closer.len()).unwrap_or(1) + .checked_sub(opener.len()).unwrap_or(1); + + let fmt = StringFormat { + opener: "", + closer: "", + line_start: line_start, + line_end: "", + width: max_chars, + offset: offset + opener.len() - line_start.len(), + trim_end: true + }; + + let indent_str = make_indent(offset); + let line_breaks = s.chars().filter(|&c| c == '\n').count(); + + let (_, mut s) = s.lines().enumerate() + .map(|(i, mut line)| { + line = line.trim(); + + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = &line[..(line.len() - 2)]; + } + + line.trim_right_matches(' ') + }) + .map(left_trim_comment_line) + .fold((true, opener.to_owned()), |(first, mut acc), line| { + if !first { + acc.push('\n'); + acc.push_str(&indent_str); + acc.push_str(line_start); + } + + if line.len() > max_chars { + acc.push_str(&rewrite_string(line, &fmt)); + } else { + acc.push_str(line); + } + + (false, acc) + }); + + s.push_str(closer); + + s +} + +fn left_trim_comment_line<'a>(line: &'a str) -> &'a str { + if line.starts_with("/* ") || line.starts_with("// ") { + &line[3..] + } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") { + &line[2..] + } else if line.starts_with("*") { + &line[1..] + } else { + line + } +} + +#[test] +fn format_comments() { + assert_eq!("/* test */", rewrite_comment(" //test", true, 100, 100)); + assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, 0)); + + assert_eq!("// A multi line comment\n // between args.", + rewrite_comment("// A multi line comment\n // between args.", + false, + 60, + 12)); + + let input = "// comment"; + let expected_output = "/* com\n \ + * men\n \ + * t */"; + assert_eq!(expected_output, rewrite_comment(input, true, 9, 69)); +} + + +pub trait FindUncommented { + fn find_uncommented(&self, pat: &str) -> Option; +} + +impl FindUncommented for str { + fn find_uncommented(&self, pat: &str) -> Option { + let mut needle_iter = pat.chars(); + let mut possible_comment = false; + + for (i, b) in self.char_indices() { + match needle_iter.next() { + Some(c) => { + if b != c { + needle_iter = pat.chars(); + } + }, + None => return Some(i - pat.len()) + } + + if possible_comment && (b == '/' || b == '*') { + return find_comment_end(&self[(i-1)..]) + .and_then(|end| { + self[(end + i - 1)..].find_uncommented(pat) + .map(|idx| idx + end + i - 1) + }); + } + + possible_comment = b == '/'; + } + + // Handle case where the pattern is a suffix of the search string + match needle_iter.next() { + Some(_) => None, + None => Some(self.len() - pat.len()) + } + } +} + +#[test] +fn test_find_uncommented() { + fn check(haystack: &str, needle: &str, expected: Option) { + println!("haystack {:?}, needle: {:?}", haystack, needle); + assert_eq!(expected, haystack.find_uncommented(needle)); + } + + check("/*/ */test", "test", Some(6)); + check("//test\ntest", "test", Some(7)); + check("/* comment only */", "whatever", None); + check("/* comment */ some text /* more commentary */ result", "result", Some(46)); + check("sup // sup", "p", Some(2)); + check("sup", "x", None); + check("π? /**/ π is nice!", "π is nice", Some(9)); + check("/*sup yo? \n sup*/ sup", "p", Some(20)); + check("hel/*lohello*/lo", "hello", None); + check("acb", "ab", None); +} + +// Returns the first byte position after the first comment. The given string +// is expected to be prefixed by a comment, including delimiters. +// Good: "/* /* inner */ outer */ code();" +// Bad: "code(); // hello\n world!" +pub fn find_comment_end(s: &str) -> Option { + if s.starts_with("//") { + s.find('\n').map(|idx| idx + 1) + } else { + // Block comment + let mut levels = 0; + let mut prev_char = 'a'; + + for (i, mut c) in s.char_indices() { + if c == '*' && prev_char == '/' { + levels += 1; + c = 'a'; // Invalidate prev_char + } else if c == '/' && prev_char == '*' { + levels -= 1; + + if levels == 0 { + return Some(i + 1); + } + c = 'a'; + } + + prev_char = c; + } + + None + } +} + +#[test] +fn comment_end() { + assert_eq!(Some(6), find_comment_end("// hi\n")); + assert_eq!(Some(9), find_comment_end("/* sup */ ")); + assert_eq!(Some(9), find_comment_end("/*/**/ */ ")); + assert_eq!(Some(6), find_comment_end("/*/ */ weird!")); + assert_eq!(None, find_comment_end("/* hi /* test */")); + assert_eq!(None, find_comment_end("// hi /* test */")); + assert_eq!(Some(9), find_comment_end("// hi /*\n.")); +} diff --git a/src/config.rs b/src/config.rs index 23285167689..8bcf12854a8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,7 +24,7 @@ pub struct Config { pub fn_brace_style: BraceStyle, pub fn_return_indent: ReturnIndent, pub fn_args_paren_newline: bool, - pub struct_trailing_comma: bool, + pub struct_trailing_comma: SeparatorTactic, pub struct_lit_trailing_comma: SeparatorTactic, pub enum_trailing_comma: bool, pub report_todo: ReportTactic, diff --git a/src/default.toml b/src/default.toml index 75ab3a60164..2d5ba9c03ee 100644 --- a/src/default.toml +++ b/src/default.toml @@ -6,7 +6,7 @@ newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true -struct_trailing_comma = true +struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true report_todo = "Always" diff --git a/src/expr.rs b/src/expr.rs index dae64891ab3..f3509b10da8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,17 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use utils::*; -use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; use rewrite::{Rewrite, RewriteContext}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use string::{StringFormat, rewrite_string}; use syntax::{ast, ptr}; -use syntax::codemap::{Pos, Span}; +use syntax::codemap::{Pos, Span, BytePos}; use syntax::parse::token; use syntax::print::pprust; -use MIN_STRING; - impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { match self.node { @@ -33,7 +31,7 @@ impl Rewrite for ast::Expr { } } ast::Expr_::ExprCall(ref callee, ref args) => { - return rewrite_call(context, callee, args, width, offset); + return rewrite_call(context, callee, args, self.span, width, offset); } ast::Expr_::ExprParen(ref subexpr) => { return rewrite_paren(context, subexpr, width, offset); @@ -46,7 +44,7 @@ impl Rewrite for ast::Expr { offset); } ast::Expr_::ExprTup(ref items) => { - return rewrite_tuple_lit(context, items, width, offset); + return rewrite_tuple_lit(context, items, self.span, width, offset); } _ => {} } @@ -55,9 +53,12 @@ impl Rewrite for ast::Expr { } } -fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, width: usize, offset: usize) -> Option { - // FIXME I bet this stomps unicode escapes in the source string - +fn rewrite_string_lit(context: &RewriteContext, + s: &str, + span: Span, + width: usize, + offset: usize) + -> Option { // Check if there is anything to fix: we always try to fixup multi-line // strings, or if the string is too long for the line. let l_loc = context.codemap.lookup_char_pos(span.lo); @@ -65,102 +66,63 @@ fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, width: usiz if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width { return context.codemap.span_to_snippet(span).ok(); } + let fmt = StringFormat { + opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + width: width, + offset: offset, + trim_end: false + }; - // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) - - let s = s.escape_default(); - - let offset = offset + 1; - let indent = make_indent(offset); - let indent = &indent; - - let mut cur_start = 0; - let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); - result.push('"'); - loop { - let max_chars = if cur_start == 0 { - // First line. - width - 2 // 2 = " + \ - } else { - context.config.max_width - offset - 1 // 1 = either \ or ; - }; - - let mut cur_end = cur_start + max_chars; - - if cur_end >= s.len() { - result.push_str(&s[cur_start..]); - break; - } - - // Make sure we're on a char boundary. - cur_end = next_char(&s, cur_end); - - // Push cur_end left until we reach whitespace - while !s.char_at(cur_end-1).is_whitespace() { - cur_end = prev_char(&s, cur_end); - - if cur_end - cur_start < MIN_STRING { - // We can't break at whitespace, fall back to splitting - // anywhere that doesn't break an escape sequence - cur_end = next_char(&s, cur_start + max_chars); - while s.char_at(prev_char(&s, cur_end)) == '\\' { - cur_end = prev_char(&s, cur_end); - } - break; - } - } - // Make sure there is no whitespace to the right of the break. - while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { - cur_end = next_char(&s, cur_end+1); - } - result.push_str(&s[cur_start..cur_end]); - result.push_str("\\\n"); - result.push_str(indent); - - cur_start = cur_end; - } - result.push('"'); - - Some(result) + Some(rewrite_string(&s.escape_default(), &fmt)) } fn rewrite_call(context: &RewriteContext, callee: &ast::Expr, args: &[ptr::P], + span: Span, width: usize, offset: usize) - -> Option -{ + -> Option { debug!("rewrite_call, width: {}, offset: {}", width, offset); // TODO using byte lens instead of char lens (and probably all over the place too) let callee_str = try_opt!(callee.rewrite(context, width, offset)); - debug!("rewrite_call, callee_str: `{:?}`", callee_str); + debug!("rewrite_call, callee_str: `{}`", callee_str); + + if args.len() == 0 { + return Some(format!("{}()", callee_str)); + } + // 2 is for parens. let remaining_width = width - callee_str.len() - 2; let offset = callee_str.len() + 1 + offset; - let arg_count = args.len(); - let args_str = if arg_count > 0 { - let args_rewritten: Vec<_> = - try_opt!(args.iter() - .map(|arg| arg.rewrite(context, remaining_width, offset) - .map(|arg_str| (arg_str, String::new()))) - .collect()); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: remaining_width, - v_width: remaining_width, - }; - write_list(&args_rewritten, &fmt) - } else { - String::new() + let items = itemize_list(context.codemap, + Vec::new(), + args.iter(), + ",", + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, remaining_width, offset) + .unwrap(), // FIXME: don't unwrap, take span literal + callee.span.hi + BytePos(1), + span.hi); + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: remaining_width, + v_width: remaining_width, + is_expression: true, }; - Some(format!("{}({})", callee_str, args_str)) + Some(format!("{}({})", callee_str, write_list(&items, &fmt))) } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, offset: usize) -> Option { @@ -198,8 +160,9 @@ fn rewrite_struct_lit(context: &RewriteContext, indent + 2) .map(|s| format!("..{}", s)))) .collect()); + // FIXME comments - let field_strs: Vec<_> = field_strs.into_iter().map(|s| (s, String::new())).collect(); + let field_strs: Vec<_> = field_strs.into_iter().map(ListItem::from_str).collect(); let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, separator: ",", @@ -211,14 +174,15 @@ fn rewrite_struct_lit(context: &RewriteContext, indent: indent, h_width: budget, v_width: budget, + is_expression: true, }; let fields_str = write_list(&field_strs, &fmt); Some(format!("{} {{ {} }}", path_str, fields_str)) - // FIXME if the usual multi-line layout is too wide, we should fall back to - // Foo { - // a: ..., - // } + // FIXME if the usual multi-line layout is too wide, we should fall back to + // Foo { + // a: ..., + // } } fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, offset: usize) -> Option { @@ -230,43 +194,42 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, off fn rewrite_tuple_lit(context: &RewriteContext, items: &[ptr::P], + span: Span, width: usize, offset: usize) -> Option { - // opening paren - let indent = offset + 1; - // In case of length 1, need a trailing comma - if items.len() == 1 { - return items[0].rewrite(context, width - 3, indent).map(|s| format!("({},)", s)); - } - // Only last line has width-1 as budget, other may take max_width - let item_strs: Vec<_> = - try_opt!(items.iter() - .enumerate() - .map(|(i, item)| { - let rem_width = if i == items.len() - 1 { - width - 2 - } else { - context.config.max_width - indent - 2 - }; - item.rewrite(context, rem_width, indent) - }) - .collect()); - let tactics = if item_strs.iter().any(|s| s.contains('\n')) { - ListTactic::Vertical - } else { - ListTactic::HorizontalVertical - }; - // FIXME handle comments - let item_strs: Vec<_> = item_strs.into_iter().map(|s| (s, String::new())).collect(); - let fmt = ListFormatting { - tactic: tactics, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - h_width: width - 2, - v_width: width - 2, - }; - let item_str = write_list(&item_strs, &fmt); - Some(format!("({})", item_str)) - } + let indent = offset + 1; + + let items = itemize_list(context.codemap, + Vec::new(), + items.into_iter(), + ",", + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, + context.config.max_width - indent - 2, + indent) + .unwrap(), // FIXME: don't unwrap, take span literal + span.lo + BytePos(1), // Remove parens + span.hi - BytePos(1)); + + // In case of length 1, need a trailing comma + let trailing_separator_tactic = if items.len() == 1 { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + }; + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: trailing_separator_tactic, + indent: indent, + h_width: width - 2, + v_width: width - 2, + is_expression: true, + }; + + Some(format!("({})", write_list(&items, &fmt))) +} diff --git a/src/imports.rs b/src/imports.rs index d4fe81218b8..552e86f5261 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -9,7 +9,7 @@ // except according to those terms. use visitor::FmtVisitor; -use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use lists::{write_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use utils::format_visibility; use syntax::ast; @@ -65,16 +65,8 @@ impl<'a> FmtVisitor<'a> { let used_width = indent + 2; // Break as early as possible when we've blown our budget. - let remaining_line_budget = if used_width > one_line_budget { - 0 - } else { - one_line_budget - used_width - }; - let remaining_multi_budget = if used_width > multi_line_budget { - 0 - } else { - multi_line_budget - used_width - }; + let remaining_line_budget = one_line_budget.checked_sub(used_width).unwrap_or(0); + let remaining_multi_budget = multi_line_budget.checked_sub(used_width).unwrap_or(0); let fmt = ListFormatting { tactic: ListTactic::Mixed, @@ -83,6 +75,7 @@ impl<'a> FmtVisitor<'a> { indent: block_indent + indent, h_width: remaining_line_budget, v_width: remaining_multi_budget, + is_expression: true, }; // TODO handle any comments inbetween items. @@ -94,7 +87,7 @@ impl<'a> FmtVisitor<'a> { false } ) { - Some(("self".to_owned(), String::new())) + Some(ListItem::from_str("self")) } else { None }; @@ -102,12 +95,13 @@ impl<'a> FmtVisitor<'a> { let items: Vec<_> = head.into_iter().chain(path_list.iter().filter_map(|vpi| { match vpi.node { ast::PathListItem_::PathListIdent{ name, .. } => { - Some((token::get_ident(name).to_string(), String::new())) + Some(ListItem::from_str(token::get_ident(name).to_string())) } // Skip `self`, because we added it above. ast::PathListItem_::PathListMod{ .. } => None, } })).collect(); + Some(if path_str.len() == 0 { format!("{}use {{{}}};", vis, write_list(&items, &fmt)) } else { diff --git a/src/issues.rs b/src/issues.rs index 9ee70e1aadc..0efe0c31c78 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -223,7 +223,6 @@ impl BadIssueSeeker { #[test] fn find_unnumbered_issue() { fn check_fail(text: &str, failing_pos: usize) { - println!("{:?}", text); let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); assert_eq!(Some(failing_pos), text.chars().position(|c| seeker.inspect(c).is_some())); } diff --git a/src/items.rs b/src/items.rs index 2dfa8a5fe65..77b750eb475 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,9 +11,11 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use {ReturnIndent, BraceStyle}; -use utils::{format_visibility, make_indent, FindUncommented}; -use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; +use utils::{format_visibility, make_indent, contains_skip}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use comment::FindUncommented; use visitor::FmtVisitor; + use syntax::{ast, abi}; use syntax::codemap::{self, Span, BytePos}; use syntax::print::pprust; @@ -30,7 +32,7 @@ impl<'a> FmtVisitor<'a> { constness: &ast::Constness, abi: &abi::Abi, vis: ast::Visibility, - span_end: BytePos) + span: Span) -> String { let newline_brace = self.newline_for_brace(&generics.where_clause); @@ -44,7 +46,7 @@ impl<'a> FmtVisitor<'a> { constness, abi, vis, - span_end, + span, newline_brace); // Prepare for the function body by possibly adding a newline and indent. @@ -68,7 +70,7 @@ impl<'a> FmtVisitor<'a> { -> String { // Drop semicolon or it will be interpreted as comment - let span_end = span.hi - BytePos(1); + let span = codemap::mk_sp(span.lo, span.hi - BytePos(1)); let mut result = self.rewrite_fn_base(indent, ident, @@ -79,7 +81,7 @@ impl<'a> FmtVisitor<'a> { &sig.constness, &sig.abi, ast::Visibility::Inherited, - span_end, + span, false); // Re-attach semicolon @@ -98,7 +100,7 @@ impl<'a> FmtVisitor<'a> { constness: &ast::Constness, abi: &abi::Abi, vis: ast::Visibility, - span_end: BytePos, + span: Span, newline_brace: bool) -> String { @@ -131,7 +133,8 @@ impl<'a> FmtVisitor<'a> { let generics_indent = indent + result.len(); result.push_str(&self.rewrite_generics(generics, generics_indent, - span_for_return(&fd.output).lo)); + codemap::mk_sp(span.lo, + span_for_return(&fd.output).lo))); let ret_str = self.rewrite_return(&fd.output); @@ -162,7 +165,8 @@ impl<'a> FmtVisitor<'a> { one_line_budget, multi_line_budget, arg_indent, - span_for_return(&fd.output))); + codemap::mk_sp(self.span_after(span, "("), + span_for_return(&fd.output).lo))); result.push(')'); // Return type. @@ -189,7 +193,7 @@ impl<'a> FmtVisitor<'a> { // Comment between return type and the end of the decl. let snippet_lo = fd.output.span().hi; if where_clause.predicates.len() == 0 { - let snippet_hi = span_end; + let snippet_hi = span.hi; let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); let snippet = snippet.trim(); if snippet.len() > 0 { @@ -204,7 +208,9 @@ impl<'a> FmtVisitor<'a> { } // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent, span_end)); + result.push_str(&self.rewrite_where_clause(where_clause, + indent, + span.hi)); result } @@ -215,7 +221,7 @@ impl<'a> FmtVisitor<'a> { one_line_budget: usize, multi_line_budget: usize, arg_indent: usize, - ret_span: Span) + span: Span) -> String { let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); @@ -262,89 +268,50 @@ impl<'a> FmtVisitor<'a> { } // Comments between args - let mut arg_comments = Vec::new(); + let mut arg_items = Vec::new(); if min_args == 2 { - arg_comments.push("".to_owned()); + arg_items.push(ListItem::from_str("")); } + // TODO if there are no args, there might still be a comment, but without // spans for the comment or parens, there is no chance of getting it right. // You also don't get to put a comment on self, unless it is explicit. if args.len() >= min_args { - arg_comments = self.make_comments_for_list(arg_comments, - args[min_args-1..].iter(), - ",", - ")", - |arg| arg.pat.span.lo, - |arg| arg.ty.span.hi, - ret_span.lo); + let comment_span_start = if min_args == 2 { + self.span_after(span, ",") + } else { + span.lo + }; + + arg_items = itemize_list(self.codemap, + arg_items, + args[min_args-1..].iter(), + ",", + ")", + |arg| arg.pat.span.lo, + |arg| arg.ty.span.hi, + |_| String::new(), + comment_span_start, + span.hi); } - debug!("comments: {:?}", arg_comments); + assert_eq!(arg_item_strs.len(), arg_items.len()); - // If there are // comments, keep them multi-line. - let mut list_tactic = ListTactic::HorizontalVertical; - if arg_comments.iter().any(|c| c.contains("//")) { - list_tactic = ListTactic::Vertical; + for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { + item.item = arg; } - assert_eq!(arg_item_strs.len(), arg_comments.len()); - let arg_strs: Vec<_> = arg_item_strs.into_iter().zip(arg_comments.into_iter()).collect(); - let fmt = ListFormatting { - tactic: list_tactic, + tactic: ListTactic::HorizontalVertical, separator: ",", trailing_separator: SeparatorTactic::Never, indent: arg_indent, h_width: one_line_budget, v_width: multi_line_budget, + is_expression: true, }; - write_list(&arg_strs, &fmt) - } - - // Gets comments in between items of a list. - fn make_comments_for_list(&self, - prefix: Vec, - mut it: I, - separator: &str, - terminator: &str, - get_lo: F1, - get_hi: F2, - next_span_start: BytePos) - -> Vec - where I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos - { - let mut result = prefix; - - let mut prev_end = get_hi(&it.next().unwrap()); - for item in it { - let cur_start = get_lo(&item); - let snippet = self.snippet(codemap::mk_sp(prev_end, cur_start)); - let mut snippet = snippet.trim(); - let white_space: &[_] = &[' ', '\t']; - if snippet.starts_with(separator) { - snippet = snippet[separator.len()..].trim_matches(white_space); - } else if snippet.ends_with(separator) { - snippet = snippet[..snippet.len()-separator.len()].trim_matches(white_space); - } - result.push(snippet.to_owned()); - prev_end = get_hi(&item); - } - // Get the last commment. - // FIXME If you thought the crap with the commas was ugly, just wait. - // This is awful. We're going to look from the last item span to the - // start of the return type span, then we drop everything after the - // first closing paren. - // The fix is comments in the AST or a span for the closing paren. - let snippet = self.snippet(codemap::mk_sp(prev_end, next_span_start)); - let snippet = snippet.trim(); - let snippet = &snippet[..snippet.find_uncommented(terminator).unwrap_or(snippet.len())]; - let snippet = snippet.trim(); - result.push(snippet.to_owned()); - - result + write_list(&arg_items, &fmt) } fn compute_budgets_for_args(&self, @@ -412,12 +379,16 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span) { - let header_str = self.format_header("enum", ident, vis); + let header_str = self.format_header("enum ", ident, vis); self.changes.push_str_span(span, &header_str); let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); - let generics_str = self.format_generics(generics, body_start); + let generics_str = self.format_generics(generics, + " {", + self.block_indent + self.config.tab_spaces, + codemap::mk_sp(span.lo, + body_start)); self.changes.push_str_span(span, &generics_str); self.last_pos = body_start; @@ -447,73 +418,183 @@ impl<'a> FmtVisitor<'a> { return; } - if let ast::VariantKind::TupleVariantKind(ref types) = field.node.kind { - self.format_missing_with_indent(field.span.lo); - - let vis = format_visibility(field.node.vis); - self.changes.push_str_span(field.span, vis); - let name = field.node.name.to_string(); - self.changes.push_str_span(field.span, &name); + self.format_missing_with_indent(field.span.lo); - let mut result = String::new(); + match field.node.kind { + ast::VariantKind::TupleVariantKind(ref types) => { + let vis = format_visibility(field.node.vis); + self.changes.push_str_span(field.span, vis); + let name = field.node.name.to_string(); + self.changes.push_str_span(field.span, &name); + + let mut result = String::new(); + + if types.len() > 0 { + let items = itemize_list(self.codemap, + Vec::new(), + types.iter(), + ",", + ")", + |arg| arg.ty.span.lo, + |arg| arg.ty.span.hi, + |arg| pprust::ty_to_string(&arg.ty), + self.span_after(field.span, "("), + next_span_start); + + result.push('('); + + let indent = self.block_indent + + vis.len() + + field.node.name.to_string().len() + + 1; // Open paren + + let comma_cost = if self.config.enum_trailing_comma { 1 } else { 0 }; + let budget = self.config.ideal_width - indent - comma_cost - 1; // 1 = ) + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + h_width: budget, + v_width: budget, + is_expression: false, + }; + result.push_str(&write_list(&items, &fmt)); + result.push(')'); + } - if types.len() > 0 { - let comments = self.make_comments_for_list(Vec::new(), - types.iter().map(|arg| arg.ty.span), - ",", - ")", - |span| span.lo, - |span| span.hi, - next_span_start); + if let Some(ref expr) = field.node.disr_expr { + result.push_str(" = "); + let expr_snippet = self.snippet(expr.span); + result.push_str(&expr_snippet); - let type_strings: Vec<_> = types.iter() - .map(|arg| pprust::ty_to_string(&arg.ty)) - .zip(comments.into_iter()) - .collect(); + // Make sure we do not exceed column limit + // 4 = " = ," + assert!(self.config.max_width >= vis.len() + name.len() + expr_snippet.len() + 4, + "Enum variant exceeded column limit"); + } - result.push('('); + self.changes.push_str_span(field.span, &result); - let indent = self.block_indent - + vis.len() - + field.node.name.to_string().len() - + 1; // 1 = ( - - let comma_cost = if self.config.enum_trailing_comma { 1 } else { 0 }; - let budget = self.config.ideal_width - indent - comma_cost - 1; // 1 = ) - - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - h_width: budget, - v_width: budget, - }; - result.push_str(&write_list(&type_strings, &fmt)); - result.push(')'); + if !last_field || self.config.enum_trailing_comma { + self.changes.push_str_span(field.span, ","); + } + }, + ast::VariantKind::StructVariantKind(ref struct_def) => { + let result = self.format_struct("", + field.node.name, + field.node.vis, + struct_def, + None, + field.span, + self.block_indent); + + self.changes.push_str_span(field.span, &result) } + } - if let Some(ref expr) = field.node.disr_expr { - result.push_str(" = "); - let expr_snippet = self.snippet(expr.span); - result.push_str(&expr_snippet); + self.last_pos = field.span.hi + BytePos(1); + } - // Make sure we do not exceed column limit - // 4 = " = ," - assert!(self.config.max_width >= vis.len() + name.len() + expr_snippet.len() + 4, - "Enum variant exceeded column limit"); - } + fn format_struct(&self, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + struct_def: &ast::StructDef, + generics: Option<&ast::Generics>, + span: Span, + offset: usize) -> String + { + let mut result = String::with_capacity(1024); - self.changes.push_str_span(field.span, &result); + let header_str = self.format_header(item_name, ident, vis); + result.push_str(&header_str); - if !last_field || self.config.enum_trailing_comma { - self.changes.push_str_span(field.span, ","); - } + if struct_def.fields.len() == 0 { + result.push(';'); + return result; } - // TODO: deal with struct-like variants + let is_tuple = match struct_def.fields[0].node.kind { + ast::StructFieldKind::NamedField(..) => false, + ast::StructFieldKind::UnnamedField(..) => true + }; - self.last_pos = field.span.hi + BytePos(1); + let (opener, terminator) = if is_tuple { ("(", ")") } else { (" {", "}") }; + + let generics_str = match generics { + Some(g) => self.format_generics(g, + opener, + offset + header_str.len(), + codemap::mk_sp(span.lo, + struct_def.fields[0].span.lo)), + None => opener.to_owned() + }; + result.push_str(&generics_str); + + let items = itemize_list(self.codemap, + Vec::new(), + struct_def.fields.iter(), + ",", + terminator, + |field| { + // Include attributes and doc comments, + // if present + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.node.ty.span.hi, + |field| self.format_field(field), + self.span_after(span, opener.trim()), + span.hi); + + // 2 terminators and a semicolon + let used_budget = offset + header_str.len() + generics_str.len() + 3; + + // Conservative approximation + let single_line_cost = (span.hi - struct_def.fields[0].span.lo).0; + let break_line = !is_tuple || + generics_str.contains('\n') || + single_line_cost as usize + used_budget > self.config.max_width; + + if break_line { + let indentation = make_indent(offset + self.config.tab_spaces); + result.push('\n'); + result.push_str(&indentation); + } + + let tactic = if break_line { ListTactic::Vertical } else { ListTactic::Horizontal }; + + // 1 = , + let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1; + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: self.config.struct_trailing_comma, + indent: offset + self.config.tab_spaces, + h_width: self.config.max_width, + v_width: budget, + is_expression: false, + }; + + result.push_str(&write_list(&items, &fmt)); + + if break_line { + result.push('\n'); + result.push_str(&make_indent(offset)); + } + + result.push_str(terminator); + + if is_tuple { + result.push(';'); + } + + result } pub fn visit_struct(&mut self, @@ -523,34 +604,16 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span) { - let header_str = self.format_header("struct", ident, vis); - self.changes.push_str_span(span, &header_str); - - if struct_def.fields.len() == 0 { - assert!(generics.where_clause.predicates.len() == 0, - "No-field struct with where clause?"); - assert!(generics.lifetimes.len() == 0, "No-field struct with generics?"); - assert!(generics.ty_params.len() == 0, "No-field struct with generics?"); - - self.changes.push_str_span(span, ";"); - return; - } - - let generics_str = self.format_generics(generics, struct_def.fields[0].span.lo); - self.changes.push_str_span(span, &generics_str); - - let struct_snippet = self.snippet(span); - // This will drop the comment in between the header and body. - self.last_pos = span.lo + BytePos(struct_snippet.find_uncommented("{").unwrap() as u32 + 1); - - self.block_indent += self.config.tab_spaces; - for (i, f) in struct_def.fields.iter().enumerate() { - self.visit_field(f, i == struct_def.fields.len() - 1, span.lo, &struct_snippet); - } - self.block_indent -= self.config.tab_spaces; - - self.format_missing_with_indent(span.lo + BytePos(struct_snippet.rfind('}').unwrap() as u32)); - self.changes.push_str_span(span, "}"); + let indent = self.block_indent; + let result = self.format_struct("struct ", + ident, + vis, + struct_def, + Some(generics), + span, + indent); + self.changes.push_str_span(span, &result); + self.last_pos = span.hi; } fn format_header(&self, @@ -559,42 +622,37 @@ impl<'a> FmtVisitor<'a> { vis: ast::Visibility) -> String { - format!("{}{} {}", format_visibility(vis), item_name, &token::get_ident(ident)) + format!("{}{}{}", format_visibility(vis), item_name, &token::get_ident(ident)) } fn format_generics(&self, generics: &ast::Generics, - span_end: BytePos) + opener: &str, + offset: usize, + span: Span) -> String { - let mut result = self.rewrite_generics(generics, self.block_indent, span_end); + let mut result = self.rewrite_generics(generics, offset, span); - if generics.where_clause.predicates.len() > 0 { + if generics.where_clause.predicates.len() > 0 || result.contains('\n') { result.push_str(&self.rewrite_where_clause(&generics.where_clause, - self.block_indent, - span_end)); + self.block_indent, + span.hi)); result.push_str(&make_indent(self.block_indent)); - result.push_str("\n{"); - + result.push('\n'); + result.push_str(opener.trim()); } else { - result.push_str(" {"); + result.push_str(opener); } result } // Field of a struct - fn visit_field(&mut self, - field: &ast::StructField, - last_field: bool, - // These two args are for missing spans hacks. - struct_start: BytePos, - struct_snippet: &str) - { - if self.visit_attrs(&field.node.attrs) { - return; + fn format_field(&self, field: &ast::StructField) -> String { + if contains_skip(&field.node.attrs) { + return self.snippet(codemap::mk_sp(field.node.attrs[0].span.lo, field.span.hi)); } - self.format_missing_with_indent(field.span.lo); let name = match field.node.kind { ast::StructFieldKind::NamedField(ident, _) => Some(token::get_ident(ident)), @@ -606,38 +664,20 @@ impl<'a> FmtVisitor<'a> { }; let typ = pprust::ty_to_string(&field.node.ty); - let mut field_str = match name { - Some(name) => { - let budget = self.config.ideal_width - self.block_indent; - // 3 is being conservative and assuming that there will be a trailing comma. - if self.block_indent + vis.len() + name.len() + typ.len() + 3 > budget { - format!("{}{}:\n{}{}", - vis, - name, - &make_indent(self.block_indent + self.config.tab_spaces), - typ) - } else { - format!("{}{}: {}", vis, name, typ) - } - } - None => format!("{}{}", vis, typ), - }; - if !last_field || self.config.struct_trailing_comma { - field_str.push(','); + let indent = self.block_indent + self.config.tab_spaces; + let mut attr_str = self.rewrite_attrs(&field.node.attrs, indent); + if attr_str.len() > 0 { + attr_str.push('\n'); + attr_str.push_str(&make_indent(indent)); + } + + match name { + Some(name) => format!("{}{}{}: {}", attr_str, vis, name, typ), + None => format!("{}{}{}", attr_str, vis, typ) } - self.changes.push_str_span(field.span, &field_str); - - // This hack makes sure we only add comments etc. after the comma, and - // makes sure we don't repeat any commas. - let hi = field.span.hi; - let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find_uncommented(",") { - Some(i) => i, - None => 0, - }; - self.last_pos = hi + BytePos(comma_pos as u32 + 1); } - fn rewrite_generics(&self, generics: &ast::Generics, indent: usize, span_end: BytePos) -> String { + fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span) -> String { // FIXME convert bounds to where clauses where they get too big or if // there is a where clause at all. let mut result = String::new(); @@ -647,7 +687,7 @@ impl<'a> FmtVisitor<'a> { return result; } - let budget = self.config.max_width - indent - 2; + let budget = self.config.max_width - offset - 2; // TODO might need to insert a newline if the generics are really long result.push('<'); @@ -665,30 +705,32 @@ impl<'a> FmtVisitor<'a> { codemap::mk_sp(l.lifetime.span.lo, hi) }); let ty_spans = tys.iter().map(span_for_ty_param); - let comments = self.make_comments_for_list(Vec::new(), - lt_spans.chain(ty_spans), - ",", - ">", - |sp| sp.lo, - |sp| sp.hi, - span_end); - - // If there are // comments, keep them multi-line. - let mut list_tactic = ListTactic::HorizontalVertical; - if comments.iter().any(|c| c.contains("//")) { - list_tactic = ListTactic::Vertical; + + let mut items = itemize_list(self.codemap, + Vec::new(), + lt_spans.chain(ty_spans), + ",", + ">", + |sp| sp.lo, + |sp| sp.hi, + |_| String::new(), + self.span_after(span, "<"), + span.hi); + + for (item, ty) in items.iter_mut().zip(lt_strs.chain(ty_strs)) { + item.item = ty; } - let generics_strs: Vec<_> = lt_strs.chain(ty_strs).zip(comments.into_iter()).collect(); let fmt = ListFormatting { - tactic: list_tactic, + tactic: ListTactic::HorizontalVertical, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: indent + 1, + indent: offset + 1, h_width: budget, v_width: budget, + is_expression: true, }; - result.push_str(&write_list(&generics_strs, &fmt)); + result.push_str(&write_list(&items, &fmt)); result.push('>'); @@ -710,18 +752,17 @@ impl<'a> FmtVisitor<'a> { result.push_str(&make_indent(indent + 4)); result.push_str("where "); - let comments = self.make_comments_for_list(Vec::new(), - where_clause.predicates.iter(), - ",", - "{", - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, - span_end); - - let where_strs: Vec<_> = where_clause.predicates.iter() - .map(|p| (self.rewrite_pred(p))) - .zip(comments.into_iter()) - .collect(); + let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; + let items = itemize_list(self.codemap, + Vec::new(), + where_clause.predicates.iter(), + ",", + "{", + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + |pred| self.rewrite_pred(pred), + span_start, + span_end); let budget = self.config.ideal_width + self.config.leeway - indent - 10; let fmt = ListFormatting { @@ -731,8 +772,9 @@ impl<'a> FmtVisitor<'a> { indent: indent + 10, h_width: budget, v_width: budget, + is_expression: true, }; - result.push_str(&write_list(&where_strs, &fmt)); + result.push_str(&write_list(&items, &fmt)); result } @@ -751,6 +793,12 @@ impl<'a> FmtVisitor<'a> { pprust::pat_to_string(&arg.pat), pprust::ty_to_string(&arg.ty)) } + + fn span_after(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.snippet(original); + + original.lo + BytePos(snippet.find_uncommented(needle).unwrap() as u32 + 1) + } } fn span_for_return(ret: &ast::FunctionRetTy) -> Span { diff --git a/src/lib.rs b/src/lib.rs index dfcf4c70424..5ee68e70cf5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,8 @@ mod expr; mod imports; mod issues; mod rewrite; +mod string; +mod comment; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. diff --git a/src/lists.rs b/src/lists.rs index 9f1006c39f0..d27a1943e2b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -8,7 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use utils::make_indent; +use std::cmp; + +use syntax::codemap::{self, CodeMap, BytePos}; + +use utils::{round_up_to_power_of_two, make_indent}; +use comment::{FindUncommented, rewrite_comment, find_comment_end}; +use string::before; #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { @@ -41,11 +47,38 @@ pub struct ListFormatting<'a> { pub h_width: usize, // Available width if we layout vertically pub v_width: usize, + // Non-expressions, e.g. items, will have a new line at the end of the list. + // Important for comment styles. + pub is_expression: bool +} + +pub struct ListItem { + pub pre_comment: Option, + // Item should include attributes and doc comments + pub item: String, + pub post_comment: Option } -// Format a list of strings into a string. -// Precondition: all strings in items are trimmed. -pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b>) -> String { +impl ListItem { + pub fn is_multiline(&self) -> bool { + self.item.contains('\n') || + self.pre_comment.is_some() || + self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false) + } + + pub fn from_str>(s: S) -> ListItem { + ListItem { + pre_comment: None, + item: s.into(), + post_comment: None + } + } +} + +// Format a list of commented items into a string. +// FIXME: this has grown into a monstrosity +// TODO: add unit tests +pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> String { if items.len() == 0 { return String::new(); } @@ -68,7 +101,7 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", total_width, total_sep_len, formatting.h_width); tactic = if fits_single && - !items.iter().any(|&(ref s, _)| s.contains('\n')) { + !items.iter().any(ListItem::is_multiline) { ListTactic::Horizontal } else { ListTactic::Vertical @@ -81,6 +114,11 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b tactic = ListTactic::Horizontal; } + // Switch to vertical mode if we find non-block comments. + if items.iter().any(has_line_pre_comment) { + tactic = ListTactic::Vertical; + } + // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); @@ -92,13 +130,16 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b } else { total_width + items.len() * (formatting.indent + 1) }; - let mut result = String::with_capacity(alloc_width); + let mut result = String::with_capacity(round_up_to_power_of_two(alloc_width)); let mut line_len = 0; let indent_str = &make_indent(formatting.indent); - for (i, &(ref item, ref comment)) in items.iter().enumerate() { + for (i, item) in items.iter().enumerate() { let first = i == 0; - let separate = i != items.len() - 1 || trailing_separator; + let last = i == items.len() - 1; + let separate = !last || trailing_separator; + let item_sep_len = if separate { sep_len } else { 0 }; + let item_width = item.item.len() + item_sep_len; match tactic { ListTactic::Horizontal if !first => { @@ -109,12 +150,9 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b result.push_str(indent_str); } ListTactic::Mixed => { - let mut item_width = item.len(); - if separate { - item_width += sep_len; - } + let total_width = total_item_width(item) + item_sep_len; - if line_len > 0 && line_len + item_width > formatting.v_width { + if line_len > 0 && line_len + total_width > formatting.v_width { result.push('\n'); result.push_str(indent_str); line_len = 0; @@ -125,30 +163,156 @@ pub fn write_list<'b>(items: &[(String, String)], formatting: &ListFormatting<'b line_len += 1; } - line_len += item_width; + line_len += total_width; } _ => {} } - result.push_str(item); + // Pre-comments + if let Some(ref comment) = item.pre_comment { + result.push_str(&rewrite_comment(comment, + // Block style in non-vertical mode + tactic != ListTactic::Vertical, + 1000, + formatting.indent)); - if tactic != ListTactic::Vertical && comment.len() > 0 { - if !comment.starts_with('\n') { + if tactic == ListTactic::Vertical { + result.push('\n'); + result.push_str(indent_str); + } else { result.push(' '); } - result.push_str(comment); + } + + result.push_str(&item.item); + + // Post-comments + if tactic != ListTactic::Vertical && item.post_comment.is_some() { + // We'll assume it'll fit on one line at this point + let formatted_comment = rewrite_comment(item.post_comment.as_ref().unwrap(), + true, + 1000, + 0); + + result.push(' '); + result.push_str(&formatted_comment); } if separate { result.push_str(formatting.separator); } - if tactic == ListTactic::Vertical && comment.len() > 0 { - if !comment.starts_with('\n') { - result.push(' '); + if tactic == ListTactic::Vertical && item.post_comment.is_some() { + let width = formatting.v_width - item_width - 1; // Space between item and comment + let offset = formatting.indent + item_width + 1; + let comment = item.post_comment.as_ref().unwrap(); + // Use block-style only for the last item or multiline comments + let block_style = formatting.is_expression && last || + comment.trim().contains('\n') || + comment.trim().len() > width; + + let formatted_comment = rewrite_comment(comment, + block_style, + width, + offset); + + result.push(' '); + result.push_str(&formatted_comment); + } + } + + result +} + +fn has_line_pre_comment(item: &ListItem) -> bool { + match item.pre_comment { + Some(ref comment) => comment.starts_with("//"), + None => false + } +} + +// Turns a list into a vector of items with associated comments. +// TODO: we probably do not want to take a terminator any more. Instead, we +// should demand a proper span end. +pub fn itemize_list(codemap: &CodeMap, + prefix: Vec, + it: I, + separator: &str, + terminator: &str, + get_lo: F1, + get_hi: F2, + get_item: F3, + mut prev_span_end: BytePos, + next_span_start: BytePos) + -> Vec + where I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> String +{ + let mut result = prefix; + let mut new_it = it.peekable(); + let white_space: &[_] = &[' ', '\t']; + + while let Some(item) = new_it.next() { + // Pre-comment + let pre_snippet = codemap.span_to_snippet(codemap::mk_sp(prev_span_end, + get_lo(&item))) + .unwrap(); + let pre_snippet = pre_snippet.trim(); + let pre_comment = if pre_snippet.len() > 0 { + Some(pre_snippet.to_owned()) + } else { + None + }; + + // Post-comment + let next_start = match new_it.peek() { + Some(ref next_item) => get_lo(next_item), + None => next_span_start + }; + let post_snippet = codemap.span_to_snippet(codemap::mk_sp(get_hi(&item), + next_start)) + .unwrap(); + + let comment_end = match new_it.peek() { + Some(..) => { + if let Some(start) = before(&post_snippet, "/*", "\n") { + // Block-style post-comment. Either before or after the separator. + cmp::max(find_comment_end(&post_snippet[start..]).unwrap() + start, + post_snippet.find_uncommented(separator).unwrap() + separator.len()) + } else if let Some(idx) = post_snippet.find('\n') { + idx + 1 + } else { + post_snippet.len() + } + }, + None => { + post_snippet.find_uncommented(terminator) + .unwrap_or(post_snippet.len()) } - result.push_str(comment); + }; + + prev_span_end = get_hi(&item) + BytePos(comment_end as u32); + let mut post_snippet = post_snippet[..comment_end].trim(); + + if post_snippet.starts_with(separator) { + post_snippet = post_snippet[separator.len()..] + .trim_matches(white_space); + } else if post_snippet.ends_with(separator) { + post_snippet = post_snippet[..post_snippet.len()-separator.len()] + .trim_matches(white_space); } + + result.push(ListItem { + pre_comment: pre_comment, + item: get_item(&item), + post_comment: if post_snippet.len() > 0 { + Some(post_snippet.to_owned()) + } else { + None + } + }); } result @@ -162,16 +326,25 @@ fn needs_trailing_separator(separator_tactic: SeparatorTactic, list_tactic: List } } -fn calculate_width(items:&[(String, String)]) -> usize { - let missed_width = items.iter().map(|&(_, ref s)| { - let text_len = s.trim().len(); - if text_len > 0 { - // We'll put a space before any comment. - text_len + 1 - } else { - text_len - } - }).fold(0, |a, l| a + l); - let item_width = items.iter().map(|&(ref s, _)| s.len()).fold(0, |a, l| a + l); - missed_width + item_width +fn calculate_width(items: &[ListItem]) -> usize { + items.iter().map(total_item_width).fold(0, |a, l| a + l) +} + +fn total_item_width(item: &ListItem) -> usize { + comment_len(&item.pre_comment) + comment_len(&item.post_comment) + item.item.len() +} + +fn comment_len(comment: &Option) -> usize { + match comment { + &Some(ref s) => { + let text_len = s.trim().len(); + if text_len > 0 { + // We'll put " /*" before and " */" after inline comments. + text_len + 6 + } else { + text_len + } + }, + &None => 0 + } } diff --git a/src/string.rs b/src/string.rs new file mode 100644 index 00000000000..d474fdb468e --- /dev/null +++ b/src/string.rs @@ -0,0 +1,103 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format string literals. + +use utils::{make_indent, next_char, prev_char, round_up_to_power_of_two}; + +use MIN_STRING; + +pub struct StringFormat<'a> { + pub opener: &'a str, + pub closer: &'a str, + pub line_start: &'a str, + pub line_end: &'a str, + pub width: usize, + pub offset: usize, + pub trim_end: bool, +} + +// TODO: simplify this! +pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { + // FIXME I bet this stomps unicode escapes in the source string + // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) + + let indent = make_indent(fmt.offset); + let indent = &indent; + + let mut cur_start = 0; + let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); + result.push_str(fmt.opener); + + let ender_length = fmt.line_end.len(); + let max_chars = fmt.width.checked_sub(fmt.opener.len()).unwrap_or(0) + .checked_sub(ender_length).unwrap_or(1); + + loop { + let mut cur_end = cur_start + max_chars; + + if cur_end >= s.len() { + result.push_str(&s[cur_start..]); + break; + } + + // Make sure we're on a char boundary. + cur_end = next_char(&s, cur_end); + + // Push cur_end left until we reach whitespace. + while !s.char_at(cur_end - 1).is_whitespace() { + cur_end = prev_char(&s, cur_end); + + if cur_end - cur_start < MIN_STRING { + // We can't break at whitespace, fall back to splitting + // anywhere that doesn't break an escape sequence. + cur_end = next_char(&s, cur_start + max_chars); + while s.char_at(prev_char(&s, cur_end)) == '\\' { + cur_end = prev_char(&s, cur_end); + } + break; + } + } + // Make sure there is no whitespace to the right of the break. + while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { + cur_end = next_char(&s, cur_end + 1); + } + + let line: &str = if fmt.trim_end { + &s[cur_start..cur_end].trim_right_matches(char::is_whitespace) + } else { + &s[cur_start..cur_end] + }; + + result.push_str(line); + result.push_str(fmt.line_end); + result.push('\n'); + result.push_str(indent); + result.push_str(fmt.line_start); + + cur_start = cur_end; + } + result.push_str(fmt.closer); + + result +} + +#[inline] +// Checks if a appears before b in given string and, if so, returns the index of +// a. +// FIXME: could be more generic +pub fn before<'x>(s: &'x str, a: &str, b: &str) -> Option { + s.find(a).and_then(|i| { + match s.find(b) { + Some(j) if j <= i => None, + _ => Some(i) + } + }) +} diff --git a/src/utils.rs b/src/utils.rs index 795c0d98309..e1a152e42c6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,73 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::Visibility; +use syntax::ast::{Visibility, Attribute, MetaItem, MetaItem_}; -pub trait FindUncommented { - fn find_uncommented(&self, pat: &str) -> Option; -} - -impl FindUncommented for str { - fn find_uncommented(&self, pat: &str) -> Option { - let mut needle_iter = pat.chars(); - let mut possible_comment = false; - - for (i, b) in self.char_indices() { - match needle_iter.next() { - Some(c) => { - if b != c { - needle_iter = pat.chars(); - } - }, - None => return Some(i - pat.len()) - } - - if possible_comment { - if b == '/' { - return self[(i+1)..].find('\n') - .and_then(|end| { - self[(end + i + 2)..].find_uncommented(pat) - .map(|idx| idx + end + i + 2) - }); - } else if b == '*' { - return self[(i+1)..].find("*/") - .and_then(|end| { - self[(end + i + 3)..].find_uncommented(pat) - .map(|idx| idx + end + i + 3) - }); - } else { - possible_comment = false; - } - } else { - possible_comment = b == '/'; - } - } - - // Handle case where the pattern is a suffix of the search string - match needle_iter.next() { - Some(_) => None, - None => Some(self.len() - pat.len()) - } - } -} - -#[test] -fn test_find_uncommented() { - fn check(haystack: &str, needle: &str, expected: Option) { - assert_eq!(expected, haystack.find_uncommented(needle)); - } - - check("/*//*/test", "test", Some(6)); - check("//test\ntest", "test", Some(7)); - check("/* comment only */", "whatever", None); - check("/* comment */ some text /* more commentary */ result", "result", Some(46)); - check("sup // sup", "p", Some(2)); - check("sup", "x", None); - check("π? /**/ π is nice!", "π is nice", Some(9)); - check("/*sup yo? \n sup*/ sup", "p", Some(20)); - check("hel/*lohello*/lo", "hello", None); - check("acb", "ab", None); -} +use SKIP_ANNOTATION; #[inline] pub fn prev_char(s: &str, mut i: usize) -> usize { @@ -114,6 +50,18 @@ pub fn format_visibility(vis: Visibility) -> &'static str { } } +fn is_skip(meta_item: &MetaItem) -> bool { + match meta_item.node { + MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, + _ => false, + } +} + +#[inline] +pub fn contains_skip(attrs: &[Attribute]) -> bool { + attrs.iter().any(|a| is_skip(&a.node.value)) +} + #[inline] #[cfg(target_pointer_width="64")] // Based on the trick layed out at diff --git a/src/visitor.rs b/src/visitor.rs index 88b5d4b18dc..ebd59f0cf20 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -15,7 +15,6 @@ use syntax::visit; use utils; use config::Config; -use SKIP_ANNOTATION; use changes::ChangeSet; use rewrite::{Rewrite, RewriteContext}; @@ -120,7 +119,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { constness, abi, vis, - b.span.lo); + codemap::mk_sp(s.lo, b.span.lo)); self.changes.push_str_span(s, &new_fn); } visit::FkMethod(ident, ref sig, vis) => { @@ -133,7 +132,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &sig.constness, &sig.abi, vis.unwrap_or(ast::Visibility::Inherited), - b.span.lo); + codemap::mk_sp(s.lo, b.span.lo)); self.changes.push_str_span(s, &new_fn); } visit::FkFnBlock(..) => {} @@ -305,26 +304,22 @@ impl<'a> FmtVisitor<'a> { let first = &attrs[0]; self.format_missing_with_indent(first.span.lo); - match self.rewrite_attrs(attrs, self.block_indent) { - Some(s) => { - self.changes.push_str_span(first.span, &s); - let last = attrs.last().unwrap(); - self.last_pos = last.span.hi; - false - } - None => true + if utils::contains_skip(attrs) { + true + } else { + let rewrite = self.rewrite_attrs(attrs, self.block_indent); + self.changes.push_str_span(first.span, &rewrite); + let last = attrs.last().unwrap(); + self.last_pos = last.span.hi; + false } } - fn rewrite_attrs(&self, attrs: &[ast::Attribute], indent: usize) -> Option { + pub fn rewrite_attrs(&self, attrs: &[ast::Attribute], indent: usize) -> String { let mut result = String::new(); let indent = utils::make_indent(indent); for (i, a) in attrs.iter().enumerate() { - if is_skip(&a.node.value) { - return None; - } - let a_str = self.snippet(a.span); if i > 0 { @@ -351,13 +346,6 @@ impl<'a> FmtVisitor<'a> { } } - Some(result) - } -} - -fn is_skip(meta_item: &ast::MetaItem) -> bool { - match meta_item.node { - ast::MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, - _ => false, + result } } diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 68824838644..da39ac1a8f4 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -6,7 +6,7 @@ newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true -struct_trailing_comma = true +struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true report_todo = "Always" diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs new file mode 100644 index 00000000000..9bcf3166722 --- /dev/null +++ b/tests/source/fn-simple.rs @@ -0,0 +1,11 @@ + +fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ + ,response: NoWay /* hose */) {"cool"} + + +fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* tripple, even */*/*/, +// Does this work? +y: World +) { + simple(/* does this preserve comments now? */ 42, NoWay) +} diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 024817353da..2ba2b0f9930 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -43,7 +43,7 @@ fn qux(a: dadsfa, // Comment 1 /// Blah blah blah. impl Bar { - fn foo(&mut self, a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a + fn foo(&mut self, a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a b: sdfasdfsdfasfs /*closing comment*/ ) -> isize {} /// Blah blah blah. diff --git a/tests/source/structs.rs b/tests/source/structs.rs new file mode 100644 index 00000000000..ace13fe2889 --- /dev/null +++ b/tests/source/structs.rs @@ -0,0 +1,70 @@ + + /// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct +NewInt (pub i32, SomeType /* inline comment */, T /* sup */ + + + ); + +struct Qux<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy> +( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +struct Baz +{ + // Comment A + a: A, + // Comment B +b: B, + // Comment C + c: C,} + +// Will this be a one-liner? +struct Tuple( + A, //Comment + B +); diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 748a6edb6ca..0b21d84074a 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -2,13 +2,13 @@ // Comment on foo. fn foo(a: aaaaaaaaaaaaa, // A comment - b: bbbbbbbbbbbbb, /* a second comment */ + b: bbbbbbbbbbbbb, // a second comment c: ccccccccccccc, // Newline comment d: ddddddddddddd, // A multi line comment // between args. - e: eeeeeeeeeeeee /* comment before paren*/) + e: eeeeeeeeeeeee /* comment before paren */) -> bar where F: Foo, // COmment after where clause G: Goo /* final comment */ diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 2f7b3bb66a9..8c534ef89c8 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -3,7 +3,7 @@ #[atrr] pub enum Test { A, - B(u32, A /* comment */), + B(u32, A /* comment */, SomeType), /// Doc comment C, } @@ -27,8 +27,18 @@ enum Bar { } enum LongVariants { - First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // small comment + First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment VARIANT), // This is the second variant Second, } + +enum StructLikeVariants { + Normal(u32, String), + StructLike { + x: i32, // Test comment + // Pre-comment + #[Attr50] + y: SomeType, // Aanother Comment + } +} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs new file mode 100644 index 00000000000..eb133d568ed --- /dev/null +++ b/tests/target/fn-simple.rs @@ -0,0 +1,16 @@ + +fn simple(// pre-comment on a function!? + i: i32, // yes, it's possible! + response: NoWay /* hose */) { + "cool" +} + + +fn weird_comment(// /*/ double level */ comment + x: Hello, // /*/* tripple, even */*/ + // Does this work? + y: World) { + simple(// does this preserve comments now? + 42, + NoWay) +} diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 0e89af29c15..828f1b163a9 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -36,10 +36,10 @@ fn foo() hello!() } -fn baz<'a: 'b, /* comment on 'a */ +fn baz<'a: 'b, // comment on 'a T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */> (a: A, - b: B, /* comment on b */ + b: B, // comment on b c: C) -> Bob { #[attr1] @@ -65,8 +65,9 @@ fn qux(a: dadsfa, // Comment 1 /// Blah blah blah. impl Bar { fn foo(&mut self, - a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a - b: sdfasdfsdfasfs /*closing comment*/) + a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, /* commen + * t on a */ + b: sdfasdfsdfasfs /* closing comment */) -> isize { } diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 507c9eba46b..84b7334008d 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -15,6 +15,32 @@ pub struct Foo { struct Bar; +struct NewType(Type, OtherType); + +struct NewInt(pub i32, SomeType /* inline comment */, T /* sup */); + +struct Qux<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy> +( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple( + // Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +); + // With a where clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever @@ -36,3 +62,6 @@ struct Baz { // Comment C c: C, } + +// Will this be a one-liner? +struct Tuple(A /* Comment */, B); diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 3655cab0663..2d126cacf96 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -8,4 +8,8 @@ fn foo() { aaaaaaaaaaaaaaaaaaaaaaaaa, aaaa); let a = (a,); + + let b = (// This is a comment + b, // Comment + b /* Trailing comment */); } -- cgit 1.4.1-3-g733a5 From 9f3ab0b5fe31bec1cc27e8748f82f17134d21603 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 24 Jun 2015 01:11:29 +0200 Subject: Format comments in struct literals --- src/expr.rs | 95 ++++++++++++++++++++++++++++++++++-------------- src/items.rs | 18 +++------ src/lists.rs | 9 +++-- src/utils.rs | 10 +++++ tests/target/multiple.rs | 23 ++++++++++-- 5 files changed, 108 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f3509b10da8..56c8772dd9e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,8 +9,9 @@ // except according to those terms. use rewrite::{Rewrite, RewriteContext}; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; +use utils::span_after; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos}; @@ -37,11 +38,13 @@ impl Rewrite for ast::Expr { return rewrite_paren(context, subexpr, width, offset); } ast::Expr_::ExprStruct(ref path, ref fields, ref base) => { - return rewrite_struct_lit(context, path, - fields, - base.as_ref().map(|e| &**e), - width, - offset); + return rewrite_struct_lit(context, + path, + fields, + base.as_ref().map(|e| &**e), + self.span, + width, + offset); } ast::Expr_::ExprTup(ref items) => { return rewrite_tuple_lit(context, items, self.span, width, offset); @@ -107,8 +110,10 @@ fn rewrite_call(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, + // Take old span when rewrite fails. |item| item.rewrite(context, remaining_width, offset) - .unwrap(), // FIXME: don't unwrap, take span literal + .unwrap_or(context.codemap.span_to_snippet(item.span) + .unwrap()), callee.span.hi + BytePos(1), span.hi); @@ -134,35 +139,68 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, of subexpr_str.map(|s| format!("({})", s)) } -fn rewrite_struct_lit(context: &RewriteContext, - path: &ast::Path, - fields: &[ast::Field], - base: Option<&ast::Expr>, - width: usize, - offset: usize) +fn rewrite_struct_lit<'a>(context: &RewriteContext, + path: &ast::Path, + fields: &'a [ast::Field], + base: Option<&'a ast::Expr>, + span: Span, + width: usize, + offset: usize) -> Option { debug!("rewrite_struct_lit: width {}, offset {}", width, offset); assert!(fields.len() > 0 || base.is_some()); + enum StructLitField<'a> { + Regular(&'a ast::Field), + Base(&'a ast::Expr) + } + let path_str = pprust::path_to_string(path); // Foo { a: Foo } - indent is +3, width is -5. let indent = offset + path_str.len() + 3; let budget = width - (path_str.len() + 5); - let field_strs: Vec<_> = - try_opt!(fields.iter() - .map(|field| rewrite_field(context, field, budget, indent)) - .chain(base.iter() - .map(|expr| expr.rewrite(context, - // 2 = ".." - budget - 2, - indent + 2) - .map(|s| format!("..{}", s)))) - .collect()); - - // FIXME comments - let field_strs: Vec<_> = field_strs.into_iter().map(ListItem::from_str).collect(); + let field_iter = fields.into_iter().map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); + + let items = itemize_list(context.codemap, + Vec::new(), + field_iter, + ",", + "}", + |item| { + match *item { + StructLitField::Regular(ref field) => field.span.lo, + // 2 = .. + StructLitField::Base(ref expr) => expr.span.lo - BytePos(2) + } + }, + |item| { + match *item { + StructLitField::Regular(ref field) => field.span.hi, + StructLitField::Base(ref expr) => expr.span.hi + } + }, + |item| { + match *item { + StructLitField::Regular(ref field) => { + rewrite_field(context, &field, budget, indent) + .unwrap_or(context.codemap.span_to_snippet(field.span) + .unwrap()) + }, + StructLitField::Base(ref expr) => { + // 2 = .. + expr.rewrite(context, budget - 2, indent + 2) + .map(|s| format!("..{}", s)) + .unwrap_or(context.codemap.span_to_snippet(expr.span) + .unwrap()) + } + } + }, + span_after(span, "{", context.codemap), + span.hi); + let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, separator: ",", @@ -176,7 +214,7 @@ fn rewrite_struct_lit(context: &RewriteContext, v_width: budget, is_expression: true, }; - let fields_str = write_list(&field_strs, &fmt); + let fields_str = write_list(&items, &fmt); Some(format!("{} {{ {} }}", path_str, fields_str)) // FIXME if the usual multi-line layout is too wide, we should fall back to @@ -210,7 +248,8 @@ fn rewrite_tuple_lit(context: &RewriteContext, |item| item.rewrite(context, context.config.max_width - indent - 2, indent) - .unwrap(), // FIXME: don't unwrap, take span literal + .unwrap_or(context.codemap.span_to_snippet(item.span) + .unwrap()), span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); diff --git a/src/items.rs b/src/items.rs index 77b750eb475..10a93c23033 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use {ReturnIndent, BraceStyle}; -use utils::{format_visibility, make_indent, contains_skip}; +use utils::{format_visibility, make_indent, contains_skip, span_after}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use comment::FindUncommented; use visitor::FmtVisitor; @@ -165,7 +165,7 @@ impl<'a> FmtVisitor<'a> { one_line_budget, multi_line_budget, arg_indent, - codemap::mk_sp(self.span_after(span, "("), + codemap::mk_sp(span_after(span, "(", self.codemap), span_for_return(&fd.output).lo))); result.push(')'); @@ -278,7 +278,7 @@ impl<'a> FmtVisitor<'a> { // You also don't get to put a comment on self, unless it is explicit. if args.len() >= min_args { let comment_span_start = if min_args == 2 { - self.span_after(span, ",") + span_after(span, ",", self.codemap) } else { span.lo }; @@ -438,7 +438,7 @@ impl<'a> FmtVisitor<'a> { |arg| arg.ty.span.lo, |arg| arg.ty.span.hi, |arg| pprust::ty_to_string(&arg.ty), - self.span_after(field.span, "("), + span_after(field.span, "(", self.codemap), next_span_start); result.push('('); @@ -549,7 +549,7 @@ impl<'a> FmtVisitor<'a> { }, |field| field.node.ty.span.hi, |field| self.format_field(field), - self.span_after(span, opener.trim()), + span_after(span, opener.trim(), self.codemap), span.hi); // 2 terminators and a semicolon @@ -714,7 +714,7 @@ impl<'a> FmtVisitor<'a> { |sp| sp.lo, |sp| sp.hi, |_| String::new(), - self.span_after(span, "<"), + span_after(span, "<", self.codemap), span.hi); for (item, ty) in items.iter_mut().zip(lt_strs.chain(ty_strs)) { @@ -793,12 +793,6 @@ impl<'a> FmtVisitor<'a> { pprust::pat_to_string(&arg.pat), pprust::ty_to_string(&arg.ty)) } - - fn span_after(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.snippet(original); - - original.lo + BytePos(snippet.find_uncommented(needle).unwrap() as u32 + 1) - } } fn span_for_return(ret: &ast::FunctionRetTy) -> Span { diff --git a/src/lists.rs b/src/lists.rs index d27a1943e2b..aefc93d7c86 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -203,10 +203,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St } if tactic == ListTactic::Vertical && item.post_comment.is_some() { - let width = formatting.v_width - item_width - 1; // Space between item and comment + // 1 = space between item and comment. + let width = formatting.v_width.checked_sub(item_width + 1).unwrap_or(1); let offset = formatting.indent + item_width + 1; let comment = item.post_comment.as_ref().unwrap(); - // Use block-style only for the last item or multiline comments + // Use block-style only for the last item or multiline comments. let block_style = formatting.is_expression && last || comment.trim().contains('\n') || comment.trim().len() > width; @@ -241,7 +242,7 @@ pub fn itemize_list(codemap: &CodeMap, terminator: &str, get_lo: F1, get_hi: F2, - get_item: F3, + get_item_string: F3, mut prev_span_end: BytePos, next_span_start: BytePos) -> Vec @@ -306,7 +307,7 @@ pub fn itemize_list(codemap: &CodeMap, result.push(ListItem { pre_comment: pre_comment, - item: get_item(&item), + item: get_item_string(&item), post_comment: if post_snippet.len() > 0 { Some(post_snippet.to_owned()) } else { diff --git a/src/utils.rs b/src/utils.rs index e1a152e42c6..de17f989f7a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,9 +9,19 @@ // except according to those terms. use syntax::ast::{Visibility, Attribute, MetaItem, MetaItem_}; +use syntax::codemap::{CodeMap, Span, BytePos}; + +use comment::FindUncommented; use SKIP_ANNOTATION; +#[inline] +pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { + let snippet = codemap.span_to_snippet(original).unwrap(); + + original.lo + BytePos(snippet.find_uncommented(needle).unwrap() as u32 + 1) +} + #[inline] pub fn prev_char(s: &str, mut i: usize) -> usize { if i == 0 { return 0; } diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 828f1b163a9..ad6e1c085b3 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -145,11 +145,28 @@ fn struct_lits() { let x = Bar; // Comment let y = Foo { a: x }; - Foo { a: foo(), b: bar(), ..something }; + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Comment + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ }; Foo { a: Bar, b: foo() }; } -- cgit 1.4.1-3-g733a5 From 28f7bd42059be794ad8ceb05d564f5e2b14676b5 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 24 Jun 2015 21:14:08 +0200 Subject: Fixup comment wrapping in lists --- src/expr.rs | 6 +++--- src/imports.rs | 2 +- src/items.rs | 10 +++++----- src/lists.rs | 16 +++++++-------- tests/source/multiple.rs | 18 ----------------- tests/source/struct_lits.rs | 37 ++++++++++++++++++++++++++++++++++ tests/target/multiple.rs | 31 ----------------------------- tests/target/struct_lits.rs | 48 ++++++++++++++++++++++++++++++++++----------- 8 files changed, 90 insertions(+), 78 deletions(-) create mode 100644 tests/source/struct_lits.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 56c8772dd9e..d66630e5179 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -124,7 +124,7 @@ fn rewrite_call(context: &RewriteContext, indent: offset, h_width: remaining_width, v_width: remaining_width, - is_expression: true, + ends_with_newline: true, }; Some(format!("{}({})", callee_str, write_list(&items, &fmt))) @@ -212,7 +212,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, indent: indent, h_width: budget, v_width: budget, - is_expression: true, + ends_with_newline: true, }; let fields_str = write_list(&items, &fmt); Some(format!("{} {{ {} }}", path_str, fields_str)) @@ -267,7 +267,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, indent: indent, h_width: width - 2, v_width: width - 2, - is_expression: true, + ends_with_newline: true, }; Some(format!("({})", write_list(&items, &fmt))) diff --git a/src/imports.rs b/src/imports.rs index 552e86f5261..de33be849ba 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -75,7 +75,7 @@ impl<'a> FmtVisitor<'a> { indent: block_indent + indent, h_width: remaining_line_budget, v_width: remaining_multi_budget, - is_expression: true, + ends_with_newline: true, }; // TODO handle any comments inbetween items. diff --git a/src/items.rs b/src/items.rs index 10a93c23033..17941dcd242 100644 --- a/src/items.rs +++ b/src/items.rs @@ -308,7 +308,7 @@ impl<'a> FmtVisitor<'a> { indent: arg_indent, h_width: one_line_budget, v_width: multi_line_budget, - is_expression: true, + ends_with_newline: true, }; write_list(&arg_items, &fmt) @@ -458,7 +458,7 @@ impl<'a> FmtVisitor<'a> { indent: indent, h_width: budget, v_width: budget, - is_expression: false, + ends_with_newline: false, }; result.push_str(&write_list(&items, &fmt)); result.push(')'); @@ -578,7 +578,7 @@ impl<'a> FmtVisitor<'a> { indent: offset + self.config.tab_spaces, h_width: self.config.max_width, v_width: budget, - is_expression: false, + ends_with_newline: false, }; result.push_str(&write_list(&items, &fmt)); @@ -728,7 +728,7 @@ impl<'a> FmtVisitor<'a> { indent: offset + 1, h_width: budget, v_width: budget, - is_expression: true, + ends_with_newline: true, }; result.push_str(&write_list(&items, &fmt)); @@ -772,7 +772,7 @@ impl<'a> FmtVisitor<'a> { indent: indent + 10, h_width: budget, v_width: budget, - is_expression: true, + ends_with_newline: true, }; result.push_str(&write_list(&items, &fmt)); diff --git a/src/lists.rs b/src/lists.rs index aefc93d7c86..adabb00566c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -49,7 +49,7 @@ pub struct ListFormatting<'a> { pub v_width: usize, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. - pub is_expression: bool + pub ends_with_newline: bool } pub struct ListItem { @@ -173,7 +173,9 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St result.push_str(&rewrite_comment(comment, // Block style in non-vertical mode tactic != ListTactic::Vertical, - 1000, + // Width restriction is only + // relevant in vertical mode. + formatting.v_width, formatting.indent)); if tactic == ListTactic::Vertical { @@ -188,10 +190,9 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St // Post-comments if tactic != ListTactic::Vertical && item.post_comment.is_some() { - // We'll assume it'll fit on one line at this point let formatted_comment = rewrite_comment(item.post_comment.as_ref().unwrap(), true, - 1000, + formatting.v_width, 0); result.push(' '); @@ -208,14 +209,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St let offset = formatting.indent + item_width + 1; let comment = item.post_comment.as_ref().unwrap(); // Use block-style only for the last item or multiline comments. - let block_style = formatting.is_expression && last || + let block_style = formatting.ends_with_newline && last || comment.trim().contains('\n') || comment.trim().len() > width; - let formatted_comment = rewrite_comment(comment, - block_style, - width, - offset); + let formatted_comment = rewrite_comment(comment, block_style, width, offset); result.push(' '); result.push_str(&formatted_comment); diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 2ba2b0f9930..04ecb2bc734 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -107,21 +107,3 @@ fn main() { let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; } - - -fn struct_lits() { - let x = Bar; - // Comment - let y = Foo { a: x }; - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a: Bar, - b: foo() }; -} diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs new file mode 100644 index 00000000000..b7e1a854b0b --- /dev/null +++ b/tests/source/struct_lits.rs @@ -0,0 +1,37 @@ +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index ad6e1c085b3..0fb0c94e3a8 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -139,34 +139,3 @@ fn main() { abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd"; } - - -fn struct_lits() { - let x = Bar; - // Comment - let y = Foo { a: x }; - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* C - * o - * m - * m - * e - * n - * t */ - // Comment - b: bar(), /* C - * o - * m - * m - * e - * n - * t */ }; - - Foo { a: Bar, b: foo() }; -} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 1d32171d7d0..c46909825a1 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -6,19 +6,45 @@ fn main() { // Comment let y = Foo { a: x }; - Foo { a: Bar, b: foo() }; - - Foo { a: foo(), b: bar(), ..something }; + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar() }; Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), - c: bar(), - d: bar(), - e: bar(), - f: bar(), - ..baz() }; + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Comment + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ }; + + Foo { a: Bar, b: foo() }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } } -- cgit 1.4.1-3-g733a5 From 482f200b0b3f7e6b248c38e463bc231c53263199 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 26 Jun 2015 03:29:54 +0200 Subject: Update import list formatting Include comments and sort items alphabetically. --- src/comment.rs | 12 +++++- src/config.rs | 1 + src/default.toml | 1 + src/imports.rs | 77 +++++++++++++++++++++++++-------------- src/lib.rs | 1 + src/lists.rs | 44 ++++++++++++++-------- src/string.rs | 13 ------- src/visitor.rs | 8 +++- tests/config/reorder_imports.toml | 14 +++++++ tests/config/small_tabs.toml | 1 + tests/source/imports-reorder.rs | 5 +++ tests/source/imports.rs | 41 +++++++++++++++++++++ tests/target/imports-reorder.rs | 5 +++ tests/target/imports.rs | 15 +++++++- 14 files changed, 176 insertions(+), 62 deletions(-) create mode 100644 tests/config/reorder_imports.toml create mode 100644 tests/source/imports-reorder.rs create mode 100644 tests/source/imports.rs create mode 100644 tests/target/imports-reorder.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index a1338d5b369..1a16d349208 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -46,9 +46,16 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz line = &line[..(line.len() - 2)]; } - line.trim_right_matches(' ') + line.trim_right() }) .map(left_trim_comment_line) + .map(|line| { + if line_breaks == 0 { + line.trim_left() + } else { + line + } + }) .fold((true, opener.to_owned()), |(first, mut acc), line| { if !first { acc.push('\n'); @@ -98,6 +105,8 @@ fn format_comments() { * men\n \ * t */"; assert_eq!(expected_output, rewrite_comment(input, true, 9, 69)); + + assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); } @@ -156,6 +165,7 @@ fn test_find_uncommented() { check("/*sup yo? \n sup*/ sup", "p", Some(20)); check("hel/*lohello*/lo", "hello", None); check("acb", "ab", None); + check(",/*A*/ ", ",", Some(0)); } // Returns the first byte position after the first comment. The given string diff --git a/src/config.rs b/src/config.rs index 8bcf12854a8..0ea13768457 100644 --- a/src/config.rs +++ b/src/config.rs @@ -29,6 +29,7 @@ pub struct Config { pub enum_trailing_comma: bool, pub report_todo: ReportTactic, pub report_fixme: ReportTactic, + pub reorder_imports: bool, // Alphabetically, case sensitive. } impl Config { diff --git a/src/default.toml b/src/default.toml index 2d5ba9c03ee..951fde9d665 100644 --- a/src/default.toml +++ b/src/default.toml @@ -11,3 +11,4 @@ struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" +reorder_imports = false diff --git a/src/imports.rs b/src/imports.rs index de33be849ba..535e409288b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -9,12 +9,13 @@ // except according to those terms. use visitor::FmtVisitor; -use lists::{write_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; -use utils::format_visibility; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use utils::{span_after, format_visibility}; use syntax::ast; use syntax::parse::token; use syntax::print::pprust; +use syntax::codemap::Span; // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import @@ -40,13 +41,14 @@ fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem, vis: &str) impl<'a> FmtVisitor<'a> { // Basically just pretty prints a multi-item import. // Returns None when the import can be removed. - pub fn rewrite_use_list(&mut self, + pub fn rewrite_use_list(&self, block_indent: usize, one_line_budget: usize, // excluding indentation multi_line_budget: usize, path: &ast::Path, path_list: &[ast::PathListItem], - visibility: ast::Visibility) -> Option { + visibility: ast::Visibility, + span: Span) -> Option { let path_str = pprust::path_to_string(path); let vis = format_visibility(visibility); @@ -78,34 +80,53 @@ impl<'a> FmtVisitor<'a> { ends_with_newline: true, }; - // TODO handle any comments inbetween items. - // If `self` is in the list, put it first. - let head = if path_list.iter().any(|vpi| - if let ast::PathListItem_::PathListMod{ .. } = vpi.node { - true - } else { - false - } - ) { - Some(ListItem::from_str("self")) - } else { - None - }; + let mut items = itemize_list(self.codemap, + vec![ListItem::from_str("")], // Dummy value, explanation below + path_list.iter(), + ",", + "}", + |vpi| vpi.span.lo, + |vpi| vpi.span.hi, + |vpi| match vpi.node { + ast::PathListItem_::PathListIdent{ name, .. } => { + token::get_ident(name).to_string() + } + ast::PathListItem_::PathListMod{ .. } => { + "self".to_owned() + } + }, + span_after(span, "{", self.codemap), + span.hi); + + // We prefixed the item list with a dummy value so that we can + // potentially move "self" to the front of the vector without touching + // the rest of the items. + // FIXME: Make more efficient by using a linked list? That would + // require changes to the signatures of itemize_list and write_list. + let has_self = move_self_to_front(&mut items); + let first_index = if has_self { 0 } else { 1 }; + + if self.config.reorder_imports { + items.tail_mut().sort_by(|a, b| a.item.cmp(&b.item)); + } - let items: Vec<_> = head.into_iter().chain(path_list.iter().filter_map(|vpi| { - match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => { - Some(ListItem::from_str(token::get_ident(name).to_string())) - } - // Skip `self`, because we added it above. - ast::PathListItem_::PathListMod{ .. } => None, - } - })).collect(); + let list = write_list(&items[first_index..], &fmt); Some(if path_str.len() == 0 { - format!("{}use {{{}}};", vis, write_list(&items, &fmt)) + format!("{}use {{{}}};", vis, list) } else { - format!("{}use {}::{{{}}};", vis, path_str, write_list(&items, &fmt)) + format!("{}use {}::{{{}}};", vis, path_str, list) }) } } + +// Returns true when self item was found. +fn move_self_to_front(items: &mut Vec) -> bool { + match items.iter().position(|item| item.item == "self") { + Some(pos) => { + items[0] = items.remove(pos); + true + }, + None => false + } +} diff --git a/src/lib.rs b/src/lib.rs index 5ee68e70cf5..e0e72f90e6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ #![feature(rustc_private)] #![feature(str_escape)] #![feature(str_char)] +#![feature(slice_extras)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? diff --git a/src/lists.rs b/src/lists.rs index adabb00566c..87a71578e96 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -14,7 +14,6 @@ use syntax::codemap::{self, CodeMap, BytePos}; use utils::{round_up_to_power_of_two, make_indent}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; -use string::before; #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { @@ -66,6 +65,10 @@ impl ListItem { self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false) } + pub fn has_line_pre_comment(&self) -> bool { + self.pre_comment.as_ref().map_or(false, |comment| comment.starts_with("//")) + } + pub fn from_str>(s: S) -> ListItem { ListItem { pre_comment: None, @@ -115,7 +118,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St } // Switch to vertical mode if we find non-block comments. - if items.iter().any(has_line_pre_comment) { + if items.iter().any(ListItem::has_line_pre_comment) { tactic = ListTactic::Vertical; } @@ -223,13 +226,6 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St result } -fn has_line_pre_comment(item: &ListItem) -> bool { - match item.pre_comment { - Some(ref comment) => comment.starts_with("//"), - None => false - } -} - // Turns a list into a vector of items with associated comments. // TODO: we probably do not want to take a terminator any more. Instead, we // should demand a proper span end. @@ -250,6 +246,8 @@ pub fn itemize_list(codemap: &CodeMap, F3: Fn(&T) -> String { let mut result = prefix; + result.reserve(it.size_hint().0); + let mut new_it = it.peekable(); let white_space: &[_] = &[' ', '\t']; @@ -276,14 +274,27 @@ pub fn itemize_list(codemap: &CodeMap, let comment_end = match new_it.peek() { Some(..) => { - if let Some(start) = before(&post_snippet, "/*", "\n") { + let block_open_index = post_snippet.find("/*"); + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(separator).unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => { separator_index + separator.len() } + // Block-style post-comment before the separator. + (Some(i), None) => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + separator.len()) + } // Block-style post-comment. Either before or after the separator. - cmp::max(find_comment_end(&post_snippet[start..]).unwrap() + start, - post_snippet.find_uncommented(separator).unwrap() + separator.len()) - } else if let Some(idx) = post_snippet.find('\n') { - idx + 1 - } else { - post_snippet.len() + (Some(i), Some(j)) if i < j => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + separator.len()) + } + // Potential *single* line comment. + (_, Some(j)) => { j + 1 } + _ => post_snippet.len() } }, None => { @@ -292,6 +303,7 @@ pub fn itemize_list(codemap: &CodeMap, } }; + // Cleanup post-comment: strip separators and whitespace. prev_span_end = get_hi(&item) + BytePos(comment_end as u32); let mut post_snippet = post_snippet[..comment_end].trim(); diff --git a/src/string.rs b/src/string.rs index d474fdb468e..413237e182c 100644 --- a/src/string.rs +++ b/src/string.rs @@ -88,16 +88,3 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { result } - -#[inline] -// Checks if a appears before b in given string and, if so, returns the index of -// a. -// FIXME: could be more generic -pub fn before<'x>(s: &'x str, a: &str, b: &str) -> Option { - s.find(a).and_then(|i| { - match s.find(b) { - Some(j) if j <= i => None, - _ => Some(i) - } - }) -} diff --git a/src/visitor.rs b/src/visitor.rs index ebd59f0cf20..df50f6cda27 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -168,7 +168,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { multi_line_budget, path, path_list, - item.vis); + item.vis, + item.span); if let Some(new_str) = formatted { self.format_missing_with_indent(item.span.lo); @@ -186,9 +187,12 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = item.span.hi; } ast::ViewPath_::ViewPathGlob(_) => { + self.format_missing_with_indent(item.span.lo); // FIXME convert to list? } - ast::ViewPath_::ViewPathSimple(_,_) => {} + ast::ViewPath_::ViewPathSimple(_,_) => { + self.format_missing_with_indent(item.span.lo); + } } visit::walk_item(self, item); } diff --git a/tests/config/reorder_imports.toml b/tests/config/reorder_imports.toml new file mode 100644 index 00000000000..31b0e2c6217 --- /dev/null +++ b/tests/config/reorder_imports.toml @@ -0,0 +1,14 @@ +max_width = 100 +ideal_width = 80 +leeway = 5 +tab_spaces = 4 +newline_style = "Unix" +fn_brace_style = "SameLineWhere" +fn_return_indent = "WithArgs" +fn_args_paren_newline = true +struct_trailing_comma = "Vertical" +struct_lit_trailing_comma = "Vertical" +enum_trailing_comma = true +report_todo = "Always" +report_fixme = "Never" +reorder_imports = true diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index da39ac1a8f4..35477559e43 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -11,3 +11,4 @@ struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" +reorder_imports = false diff --git a/tests/source/imports-reorder.rs b/tests/source/imports-reorder.rs new file mode 100644 index 00000000000..2a90c212148 --- /dev/null +++ b/tests/source/imports-reorder.rs @@ -0,0 +1,5 @@ +// rustfmt-config: reorder_imports.toml + +use path::{C,/*A*/ A, B /* B */, self /* self */}; + +use {ab, ac, aa, Z, b}; diff --git a/tests/source/imports.rs b/tests/source/imports.rs new file mode 100644 index 00000000000..3590ecae61f --- /dev/null +++ b/tests/source/imports.rs @@ -0,0 +1,41 @@ +// Imports. + +// Long import. +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; + +use list::{ + // Some item + SomeItem /* Comment */, /* Another item */ AnotherItem /* Another Comment */, // Last Item + LastItem +}; + +use test::{ Other /* C */ , /* A */ self /* B */ }; + +use syntax::{self}; +use {/* Pre-comment! */ + Foo, Bar /* comment */}; +use Foo::{Bar, Baz}; +pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; +use syntax::some::{}; + +mod Foo { + pub use syntax::ast::{ + ItemForeignMod, + ItemImpl, + ItemMac, + ItemMod, + ItemStatic, + ItemDefaultImpl + }; + + mod Foo2 { + pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; + } +} + +fn test() { +use Baz::*; + use Qux; +} diff --git a/tests/target/imports-reorder.rs b/tests/target/imports-reorder.rs new file mode 100644 index 00000000000..27d394238e8 --- /dev/null +++ b/tests/target/imports-reorder.rs @@ -0,0 +1,5 @@ +// rustfmt-config: reorder_imports.toml + +use path::{self /* self */, /* A */ A, B /* B */, C}; + +use {Z, aa, ab, ac, b}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 9644c62dde7..372b4f2051f 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -5,7 +5,17 @@ use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDe use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; -use {Foo, Bar}; +use list::{// Some item + SomeItem, // Comment + // Another item + AnotherItem, // Another Comment + // Last Item + LastItem}; + +use test::{/* A */ self /* B */, Other /* C */}; + +use syntax; +use {/* Pre-comment! */ Foo, Bar /* comment */}; use Foo::{Bar, Baz}; pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; @@ -13,11 +23,12 @@ mod Foo { pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; mod Foo2 { - pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, + pub use syntax::ast::{self, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; } } fn test() { use Baz::*; + use Qux; } -- cgit 1.4.1-3-g733a5 From 2d4b4b856a691578e6962406d6ca34b3b7582edf Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 2 Jul 2015 22:40:20 +0200 Subject: Format expressions with binary and unary operators --- src/expr.rs | 95 ++++++++++++++++++++++++++++++++++++++++----------- tests/source/expr.rs | 14 ++++++++ tests/target/expr.rs | 14 ++++++++ tests/target/paren.rs | 7 ---- 4 files changed, 104 insertions(+), 26 deletions(-) create mode 100644 tests/source/expr.rs create mode 100644 tests/target/expr.rs delete mode 100644 tests/target/paren.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d66630e5179..2f97fa7e97a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -11,7 +11,7 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; -use utils::span_after; +use utils::{span_after, make_indent}; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos}; @@ -24,35 +24,37 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprLit(ref l) => { match l.node { ast::Lit_::LitStr(ref is, _) => { - let result = rewrite_string_lit(context, &is, l.span, width, offset); - debug!("string lit: `{:?}`", result); - return result; + rewrite_string_lit(context, &is, l.span, width, offset) } - _ => {} + _ => context.codemap.span_to_snippet(self.span).ok() } } ast::Expr_::ExprCall(ref callee, ref args) => { - return rewrite_call(context, callee, args, self.span, width, offset); + rewrite_call(context, callee, args, self.span, width, offset) } ast::Expr_::ExprParen(ref subexpr) => { - return rewrite_paren(context, subexpr, width, offset); + rewrite_paren(context, subexpr, width, offset) + } + ast::Expr_::ExprBinary(ref op, ref lhs, ref rhs) => { + rewrite_binary_op(context, op, lhs, rhs, width, offset) + } + ast::Expr_::ExprUnary(ref op, ref subexpr) => { + rewrite_unary_op(context, op, subexpr, width, offset) } ast::Expr_::ExprStruct(ref path, ref fields, ref base) => { - return rewrite_struct_lit(context, - path, - fields, - base.as_ref().map(|e| &**e), - self.span, - width, - offset); + rewrite_struct_lit(context, + path, + fields, + base.as_ref().map(|e| &**e), + self.span, + width, + offset) } ast::Expr_::ExprTup(ref items) => { - return rewrite_tuple_lit(context, items, self.span, width, offset); + rewrite_tuple_lit(context, items, self.span, width, offset) } - _ => {} + _ => context.codemap.span_to_snippet(self.span).ok() } - - context.codemap.span_to_snippet(self.span).ok() } } @@ -235,7 +237,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, span: Span, width: usize, offset: usize) - -> Option { + -> Option { let indent = offset + 1; let items = itemize_list(context.codemap, @@ -272,3 +274,58 @@ fn rewrite_tuple_lit(context: &RewriteContext, Some(format!("({})", write_list(&items, &fmt))) } + +fn rewrite_binary_op(context: &RewriteContext, + op: &ast::BinOp, + lhs: &ast::Expr, + rhs: &ast::Expr, + width: usize, + offset: usize) + -> Option { + // FIXME: format comments between operands and operator + + let operator_str = context.codemap.span_to_snippet(op.span).unwrap(); + + // 1 = space between lhs expr and operator + let mut result = try_opt!(lhs.rewrite(context, width - 1 - operator_str.len(), offset)); + + result.push(' '); + result.push_str(&operator_str); + + let remaining_width = match result.rfind('\n') { + Some(idx) => (context.config.max_width + idx).checked_sub(result.len()).unwrap_or(0), + None => width.checked_sub(result.len()).unwrap_or(0) + }; + + // Get "full width" rhs and see if it fits on the current line. This + // usually works fairly well since it tends to place operands of + // operations with high precendence close together. + let rhs_result = try_opt!(rhs.rewrite(context, width, offset)); + + if rhs_result.len() > remaining_width { + result.push('\n'); + result.push_str(&make_indent(offset)); + } else { + result.push(' '); + }; + + result.push_str(&rhs_result); + Some(result) +} + +fn rewrite_unary_op(context: &RewriteContext, + op: &ast::UnOp, + expr: &ast::Expr, + width: usize, + offset: usize) + -> Option { + // For some reason, an UnOp is not spanned like BinOp! + let operator_str = match *op { + ast::UnOp::UnUniq => "&", + ast::UnOp::UnDeref => "*", + ast::UnOp::UnNot => "!", + ast::UnOp::UnNeg => "-" + }; + + Some(format!("{}{}", operator_str, try_opt!(expr.rewrite(context, width - 1, offset)))) +} diff --git a/tests/source/expr.rs b/tests/source/expr.rs new file mode 100644 index 00000000000..d7013a312f1 --- /dev/null +++ b/tests/source/expr.rs @@ -0,0 +1,14 @@ +// Test expressions + +fn foo() -> bool { + let very_long_variable_name = ( a + first + simple + test ); + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - + function_call(x, *very_long_pointer, y)) + + 1000; + +some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 + - 50000 * sqrt(-1), + trivial_value) +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs new file mode 100644 index 00000000000..c565c94b2ac --- /dev/null +++ b/tests/target/expr.rs @@ -0,0 +1,14 @@ +// Test expressions + +fn foo() -> bool { + let very_long_variable_name = (a + first + simple + test); + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + + b + c); + + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / + (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; + + some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + + 40000 / 1002200000000 - 50000 * sqrt(-1), + trivial_value) +} diff --git a/tests/target/paren.rs b/tests/target/paren.rs deleted file mode 100644 index 98169883575..00000000000 --- a/tests/target/paren.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Test parenthesis - -fn foo() { - let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBBB + - b + c); -} -- cgit 1.4.1-3-g733a5 From 163fbf62ee5c5b9ad1a39482ebf2f8c2e464e6b5 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Fri, 3 Jul 2015 00:50:55 +0200 Subject: Fix bugs in width computation --- src/expr.rs | 9 ++++++--- tests/source/expr.rs | 4 +++- tests/target/expr.rs | 5 ++++- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2f97fa7e97a..6fff8be9fc7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -287,13 +287,14 @@ fn rewrite_binary_op(context: &RewriteContext, let operator_str = context.codemap.span_to_snippet(op.span).unwrap(); // 1 = space between lhs expr and operator - let mut result = try_opt!(lhs.rewrite(context, width - 1 - operator_str.len(), offset)); + let mut result = + try_opt!(lhs.rewrite(context, context.config.max_width - offset - 1 - operator_str.len(), offset)); result.push(' '); result.push_str(&operator_str); let remaining_width = match result.rfind('\n') { - Some(idx) => (context.config.max_width + idx).checked_sub(result.len()).unwrap_or(0), + Some(idx) => (offset + width + idx).checked_sub(result.len()).unwrap_or(0), None => width.checked_sub(result.len()).unwrap_or(0) }; @@ -302,7 +303,9 @@ fn rewrite_binary_op(context: &RewriteContext, // operations with high precendence close together. let rhs_result = try_opt!(rhs.rewrite(context, width, offset)); - if rhs_result.len() > remaining_width { + // Second condition is needed in case of line break not caused by a + // shortage of space, but by end-of-line comments, for example. + if rhs_result.len() > remaining_width || rhs_result.contains('\n') { result.push('\n'); result.push_str(&make_indent(offset)); } else { diff --git a/tests/source/expr.rs b/tests/source/expr.rs index d7013a312f1..373e42d67c5 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -10,5 +10,7 @@ fn foo() -> bool { some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), - trivial_value) + trivial_value); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index c565c94b2ac..25c84511c41 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -10,5 +10,8 @@ fn foo() -> bool { some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), - trivial_value) + trivial_value); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaa))))))))) } -- cgit 1.4.1-3-g733a5 From fc4483748c83e972a76dd3f2c215e2d8a480cb98 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Thu, 2 Jul 2015 01:20:07 +0200 Subject: Fix fn decl rewriting in case of generics An opening paren in generics caused a false-positive detection of args beginning. The result was the creation of comments with some code into it. --- src/items.rs | 13 ++++++++++--- src/utils.rs | 10 +++++++++- tests/target/fn.rs | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 17941dcd242..396778352d1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use {ReturnIndent, BraceStyle}; -use utils::{format_visibility, make_indent, contains_skip, span_after}; +use utils::{format_visibility, make_indent, contains_skip, span_after, end_typaram}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use comment::FindUncommented; use visitor::FmtVisitor; @@ -160,13 +160,20 @@ impl<'a> FmtVisitor<'a> { result.push('('); } + // A conservative estimation, to goal is to be over all parens in generics + let args_start = generics.ty_params + .last() + .map(|tp| end_typaram(tp)) + .unwrap_or(span.lo); + let args_span = codemap::mk_sp( + span_after(codemap::mk_sp(args_start, span.hi), "(", self.codemap), + span_for_return(&fd.output).lo); result.push_str(&self.rewrite_args(&fd.inputs, explicit_self, one_line_budget, multi_line_budget, arg_indent, - codemap::mk_sp(span_after(span, "(", self.codemap), - span_for_return(&fd.output).lo))); + args_span)); result.push(')'); // Return type. diff --git a/src/utils.rs b/src/utils.rs index de17f989f7a..47203a0754f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::{Visibility, Attribute, MetaItem, MetaItem_}; +use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; use syntax::codemap::{CodeMap, Span, BytePos}; use comment::FindUncommented; @@ -72,6 +72,14 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { attrs.iter().any(|a| is_skip(&a.node.value)) } +// Find the end of a TyParam +pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { + typaram.bounds.last().map(|bound| match *bound { + ast::RegionTyParamBound(ref lt) => lt.span, + ast::TraitTyParamBound(ref prt, _) => prt.span, + }).unwrap_or(typaram.span).hi +} + #[inline] #[cfg(target_pointer_width="64")] // Based on the trick layed out at diff --git a/tests/target/fn.rs b/tests/target/fn.rs index dff8085136e..bc05efa5351 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -34,6 +34,9 @@ fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, } +fn foo B /* paren inside generics */>() { +} + impl Foo { fn with_no_errors(&mut self, f: F) -> T where F: FnOnce(&mut Resolver) -> T -- cgit 1.4.1-3-g733a5 From 83290f15ada755a71f3cfc0c66c3631a66d6b461 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Wed, 1 Jul 2015 20:49:45 +0200 Subject: Add comma after struct-like enum variant This is mandatory. --- src/items.rs | 30 +++++++++++++++--------------- tests/target/enum.rs | 5 ++++- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 396778352d1..f4eb8123603 100644 --- a/src/items.rs +++ b/src/items.rs @@ -427,7 +427,7 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(field.span.lo); - match field.node.kind { + let result = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { let vis = format_visibility(field.node.vis); self.changes.push_str_span(field.span, vis); @@ -482,23 +482,23 @@ impl<'a> FmtVisitor<'a> { "Enum variant exceeded column limit"); } - self.changes.push_str_span(field.span, &result); - - if !last_field || self.config.enum_trailing_comma { - self.changes.push_str_span(field.span, ","); - } + result }, ast::VariantKind::StructVariantKind(ref struct_def) => { - let result = self.format_struct("", - field.node.name, - field.node.vis, - struct_def, - None, - field.span, - self.block_indent); - - self.changes.push_str_span(field.span, &result) + // TODO Should limit the width, as we have a trailing comma + self.format_struct("", + field.node.name, + field.node.vis, + struct_def, + None, + field.span, + self.block_indent) } + }; + self.changes.push_str_span(field.span, &result); + + if !last_field || self.config.enum_trailing_comma { + self.changes.push_str_span(field.span, ","); } self.last_pos = field.span.hi + BytePos(1); diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 8c534ef89c8..2e2e47e25c2 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -40,5 +40,8 @@ enum StructLikeVariants { // Pre-comment #[Attr50] y: SomeType, // Aanother Comment - } + }, + SL { + a: A, + }, } -- cgit 1.4.1-3-g733a5 From 3de366d282de6de5dd1d69c40ea32f98a051fc66 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Wed, 1 Jul 2015 21:13:10 +0200 Subject: Format modules into separate files --- src/changes.rs | 4 ++ src/lib.rs | 5 -- src/visitor.rs | 96 ++++++++++++++++++++++++++++++++--- tests/source/mod-2.rs | 3 ++ tests/source/nestedmod/mod.rs | 12 +++++ tests/source/nestedmod/mod2a.rs | 4 ++ tests/source/nestedmod/mod2b.rs | 3 ++ tests/source/nestedmod/mod2c.rs | 3 ++ tests/source/nestedmod/submod2/a.rs | 6 +++ tests/source/nestedmod/submod2/mod.rs | 5 ++ tests/target/mod-2.rs | 3 ++ tests/target/nestedmod/mod.rs | 12 +++++ tests/target/nestedmod/mod2a.rs | 4 ++ tests/target/nestedmod/mod2b.rs | 3 ++ tests/target/nestedmod/mod2c.rs | 4 ++ tests/target/nestedmod/submod2/a.rs | 7 +++ tests/target/nestedmod/submod2/mod.rs | 5 ++ 17 files changed, 167 insertions(+), 12 deletions(-) create mode 100644 tests/source/mod-2.rs create mode 100644 tests/source/nestedmod/mod.rs create mode 100644 tests/source/nestedmod/mod2a.rs create mode 100644 tests/source/nestedmod/mod2b.rs create mode 100644 tests/source/nestedmod/mod2c.rs create mode 100644 tests/source/nestedmod/submod2/a.rs create mode 100644 tests/source/nestedmod/submod2/mod.rs create mode 100644 tests/target/mod-2.rs create mode 100644 tests/target/nestedmod/mod.rs create mode 100644 tests/target/nestedmod/mod2a.rs create mode 100644 tests/target/nestedmod/mod2b.rs create mode 100644 tests/target/nestedmod/mod2c.rs create mode 100644 tests/target/nestedmod/submod2/a.rs create mode 100644 tests/target/nestedmod/submod2/mod.rs (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 7a16a5bca66..74ee088105c 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -213,6 +213,10 @@ impl<'a> ChangeSet<'a> { Ok(None) } + + pub fn is_changed(&self, filename: &str) -> bool { + self.file_map.get(filename).expect("Unknown filename").len != 0 + } } // Iterates over each file in the ChangSet. Yields the filename and the changed diff --git a/src/lib.rs b/src/lib.rs index e0e72f90e6e..252b3ad05b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,11 +167,6 @@ impl fmt::Display for FormatReport { fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> { let mut visitor = FmtVisitor::from_codemap(codemap, config); visit::walk_crate(&mut visitor, krate); - let files = codemap.files.borrow(); - if let Some(last) = files.last() { - visitor.format_missing(last.end_pos); - } - visitor.changes } diff --git a/src/visitor.rs b/src/visitor.rs index df50f6cda27..ed5a5f5da1b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,9 +11,13 @@ use syntax::ast; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; +use syntax::parse::token; +use syntax::attr; +use std::path::PathBuf; use utils; use config::Config; +use comment::FindUncommented; use changes::ChangeSet; use rewrite::{Rewrite, RewriteContext}; @@ -197,7 +201,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { visit::walk_item(self, item); } ast::Item_::ItemImpl(..) | - ast::Item_::ItemMod(_) | ast::Item_::ItemTrait(..) => { self.block_indent += self.config.tab_spaces; visit::walk_item(self, item); @@ -227,6 +230,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { item.span); self.last_pos = item.span.hi; } + ast::Item_::ItemMod(ref module) => { + self.format_missing_with_indent(item.span.lo); + self.format_mod(module, item.span, item.ident, &item.attrs); + } _ => { visit::walk_item(self, item); } @@ -267,12 +274,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) { - // Only visit inline mods here. - if self.codemap.lookup_char_pos(s.lo).file.name != - self.codemap.lookup_char_pos(m.inner.lo).file.name { - return; - } - visit::walk_mod(self, m); + // This is only called for the root module + let filename = self.codemap.span_to_filename(s); + self.format_separate_mod(m, &filename); } } @@ -352,4 +356,82 @@ impl<'a> FmtVisitor<'a> { result } + + fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast::Attribute]) { + debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); + // Decide whether this is an inline mod or an external mod. + // There isn't any difference between inline and external mod in AST, + // so we use the trick of searching for an opening brace. + // We can't use the inner span of the mod since it is weird when it + // is empty (no items). + // FIXME Use the inner span once rust-lang/rust#26755 is fixed. + let open_brace = self.codemap.span_to_snippet(s).unwrap().find_uncommented("{"); + match open_brace { + None => { + debug!("FmtVisitor::format_mod: external mod"); + let file_path = self.module_file(ident, attrs, s); + let filename = file_path.to_str().unwrap(); + if self.changes.is_changed(filename) { + // The file has already been reformatted, do nothing + } else { + self.format_separate_mod(m, filename); + } + // TODO Should rewrite properly `mod X;` + } + Some(open_brace) => { + debug!("FmtVisitor::format_mod: internal mod"); + debug!("... open_brace: {}, str: {:?}", open_brace, self.codemap.span_to_snippet(s)); + // Format everything until opening brace + // TODO Shoud rewrite properly + self.format_missing(s.lo + BytePos(open_brace as u32)); + self.block_indent += self.config.tab_spaces; + visit::walk_mod(self, m); + debug!("... last_pos after: {:?}", self.last_pos); + self.block_indent -= self.config.tab_spaces; + } + } + self.format_missing(s.hi); + debug!("FmtVisitor::format_mod: exit"); + } + + /// Find the file corresponding to an external mod + /// Same algorithm as syntax::parse::eval_src_mod + fn module_file(&self, id: ast::Ident, outer_attrs: &[ast::Attribute], id_sp: Span) -> PathBuf { + // FIXME use libsyntax once rust-lang/rust#26750 is merged + let mut prefix = PathBuf::from(&self.codemap.span_to_filename(id_sp)); + prefix.pop(); + let mod_string = token::get_ident(id); + match attr::first_attr_value_str_by_name(outer_attrs, "path") { + Some(d) => prefix.join(&*d), + None => { + let default_path_str = format!("{}.rs", mod_string); + let secondary_path_str = format!("{}/mod.rs", mod_string); + let default_path = prefix.join(&default_path_str); + let secondary_path = prefix.join(&secondary_path_str); + let default_exists = self.codemap.file_exists(&default_path); + let secondary_exists = self.codemap.file_exists(&secondary_path); + if default_exists { + default_path + } else if secondary_exists { + secondary_path + } else { + // Should never appens since rustc parsed everything sucessfully + panic!("Didn't found module {}", mod_string); + } + } + } + } + + /// Format the content of a module into a separate file + fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) { + let last_pos = self.last_pos; + let block_indent = self.block_indent; + let filemap = self.codemap.get_filemap(filename); + self.last_pos = filemap.start_pos; + self.block_indent = 0; + visit::walk_mod(self, m); + self.format_missing(filemap.end_pos); + self.last_pos = last_pos; + self.block_indent = block_indent; + } } diff --git a/tests/source/mod-2.rs b/tests/source/mod-2.rs new file mode 100644 index 00000000000..75b560ce93f --- /dev/null +++ b/tests/source/mod-2.rs @@ -0,0 +1,3 @@ +// Some nested mods + +mod nestedmod; diff --git a/tests/source/nestedmod/mod.rs b/tests/source/nestedmod/mod.rs new file mode 100644 index 00000000000..23dfa444257 --- /dev/null +++ b/tests/source/nestedmod/mod.rs @@ -0,0 +1,12 @@ + +mod mod2a; +mod mod2b; + +mod mymod1 { + use mod2a::{Foo,Bar}; +} + +#[path="mod2c.rs"] +mod mymod2; + +mod submod2; diff --git a/tests/source/nestedmod/mod2a.rs b/tests/source/nestedmod/mod2a.rs new file mode 100644 index 00000000000..5df457a8316 --- /dev/null +++ b/tests/source/nestedmod/mod2a.rs @@ -0,0 +1,4 @@ +// This is an empty file containing only +// comments + +// ................... diff --git a/tests/source/nestedmod/mod2b.rs b/tests/source/nestedmod/mod2b.rs new file mode 100644 index 00000000000..f128e2da6db --- /dev/null +++ b/tests/source/nestedmod/mod2b.rs @@ -0,0 +1,3 @@ + +#[path="mod2a.rs"] +mod c; diff --git a/tests/source/nestedmod/mod2c.rs b/tests/source/nestedmod/mod2c.rs new file mode 100644 index 00000000000..eda6b233e4b --- /dev/null +++ b/tests/source/nestedmod/mod2c.rs @@ -0,0 +1,3 @@ +// A standard mod + +fn a( ) {} diff --git a/tests/source/nestedmod/submod2/a.rs b/tests/source/nestedmod/submod2/a.rs new file mode 100644 index 00000000000..0eaf08f0d2c --- /dev/null +++ b/tests/source/nestedmod/submod2/a.rs @@ -0,0 +1,6 @@ +// Yet Another mod +// Nested + +use c::a; + +fn foo( ) { } diff --git a/tests/source/nestedmod/submod2/mod.rs b/tests/source/nestedmod/submod2/mod.rs new file mode 100644 index 00000000000..52f8be91022 --- /dev/null +++ b/tests/source/nestedmod/submod2/mod.rs @@ -0,0 +1,5 @@ +// Another mod + +mod a; + +use a::a; diff --git a/tests/target/mod-2.rs b/tests/target/mod-2.rs new file mode 100644 index 00000000000..75b560ce93f --- /dev/null +++ b/tests/target/mod-2.rs @@ -0,0 +1,3 @@ +// Some nested mods + +mod nestedmod; diff --git a/tests/target/nestedmod/mod.rs b/tests/target/nestedmod/mod.rs new file mode 100644 index 00000000000..be22f6d4037 --- /dev/null +++ b/tests/target/nestedmod/mod.rs @@ -0,0 +1,12 @@ + +mod mod2a; +mod mod2b; + +mod mymod1 { + use mod2a::{Foo, Bar}; +} + +#[path="mod2c.rs"] +mod mymod2; + +mod submod2; diff --git a/tests/target/nestedmod/mod2a.rs b/tests/target/nestedmod/mod2a.rs new file mode 100644 index 00000000000..5df457a8316 --- /dev/null +++ b/tests/target/nestedmod/mod2a.rs @@ -0,0 +1,4 @@ +// This is an empty file containing only +// comments + +// ................... diff --git a/tests/target/nestedmod/mod2b.rs b/tests/target/nestedmod/mod2b.rs new file mode 100644 index 00000000000..f128e2da6db --- /dev/null +++ b/tests/target/nestedmod/mod2b.rs @@ -0,0 +1,3 @@ + +#[path="mod2a.rs"] +mod c; diff --git a/tests/target/nestedmod/mod2c.rs b/tests/target/nestedmod/mod2c.rs new file mode 100644 index 00000000000..9027adeb212 --- /dev/null +++ b/tests/target/nestedmod/mod2c.rs @@ -0,0 +1,4 @@ +// A standard mod + +fn a() { +} diff --git a/tests/target/nestedmod/submod2/a.rs b/tests/target/nestedmod/submod2/a.rs new file mode 100644 index 00000000000..078a1d99f2c --- /dev/null +++ b/tests/target/nestedmod/submod2/a.rs @@ -0,0 +1,7 @@ +// Yet Another mod +// Nested + +use c::a; + +fn foo() { +} diff --git a/tests/target/nestedmod/submod2/mod.rs b/tests/target/nestedmod/submod2/mod.rs new file mode 100644 index 00000000000..52f8be91022 --- /dev/null +++ b/tests/target/nestedmod/submod2/mod.rs @@ -0,0 +1,5 @@ +// Another mod + +mod a; + +use a::a; -- cgit 1.4.1-3-g733a5 From 990a123e1c7beb1740a629d9a1ded8f84ea3546f Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Fri, 3 Jul 2015 11:13:28 +0200 Subject: Run rustfmt on the code --- src/changes.rs | 25 ++++------- src/comment.rs | 20 ++++----- src/expr.rs | 85 +++++++++++++++++++------------------ src/imports.rs | 22 +++++----- src/issues.rs | 35 ++++++---------- src/items.rs | 118 ++++++++++++++++++++-------------------------------- src/lists.rs | 17 +++----- src/missed_spans.rs | 3 +- src/types.rs | 15 +++---- src/visitor.rs | 12 +++--- 10 files changed, 147 insertions(+), 205 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 74ee088105c..3f0d985da48 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -35,11 +35,9 @@ pub struct ChangeSet<'a> { impl<'a> ChangeSet<'a> { // Create a new ChangeSet for a given libsyntax CodeMap. pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut result = ChangeSet { - file_map: HashMap::new(), - codemap: codemap, - file_spans: Vec::with_capacity(codemap.files.borrow().len()), - }; + let mut result = ChangeSet { file_map: HashMap::new(), + codemap: codemap, + file_spans: Vec::with_capacity(codemap.files.borrow().len()), }; for f in codemap.files.borrow().iter() { // Use the length of the file as a heuristic for how much space we @@ -116,11 +114,7 @@ impl<'a> ChangeSet<'a> { // Return an iterator over the entire changed text. pub fn text<'c>(&'c self) -> FileIterator<'c, 'a> { - FileIterator { - change_set: self, - keys: self.file_map.keys().collect(), - cur_key: 0, - } + FileIterator { change_set: self, keys: self.file_map.keys().collect(), cur_key: 0 } } // Append a newline to the end of each file. @@ -153,12 +147,11 @@ impl<'a> ChangeSet<'a> { let text = &self.file_map[filename]; // prints all newlines either as `\n` or as `\r\n` - fn write_system_newlines( - mut writer: T, - text: &StringBuffer, - config: &Config) - -> Result<(), ::std::io::Error> - where T: Write, + fn write_system_newlines(mut writer: T, + text: &StringBuffer, + config: &Config) + -> Result<(), ::std::io::Error> + where T: Write { match config.newline_style { NewlineStyle::Unix => write!(writer, "{}", text), diff --git a/src/comment.rs b/src/comment.rs index 1a16d349208..064cace6c51 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -24,15 +24,13 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz let max_chars = width.checked_sub(closer.len()).unwrap_or(1) .checked_sub(opener.len()).unwrap_or(1); - let fmt = StringFormat { - opener: "", - closer: "", - line_start: line_start, - line_end: "", - width: max_chars, - offset: offset + opener.len() - line_start.len(), - trim_end: true - }; + let fmt = StringFormat { opener: "", + closer: "", + line_start: line_start, + line_end: "", + width: max_chars, + offset: offset + opener.len() - line_start.len(), + trim_end: true, }; let indent_str = make_indent(offset); let line_breaks = s.chars().filter(|&c| c == '\n').count(); @@ -102,8 +100,8 @@ fn format_comments() { let input = "// comment"; let expected_output = "/* com\n \ - * men\n \ - * t */"; + * men\n \ + * t */"; assert_eq!(expected_output, rewrite_comment(input, true, 9, 69)); assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); diff --git a/src/expr.rs b/src/expr.rs index 6fff8be9fc7..da706c4afa7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -63,7 +63,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, width: usize, offset: usize) - -> Option { + -> Option { // Check if there is anything to fix: we always try to fixup multi-line // strings, or if the string is too long for the line. let l_loc = context.codemap.lookup_char_pos(span.lo); @@ -71,15 +71,13 @@ fn rewrite_string_lit(context: &RewriteContext, if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width { return context.codemap.span_to_snippet(span).ok(); } - let fmt = StringFormat { - opener: "\"", - closer: "\"", - line_start: " ", - line_end: "\\", - width: width, - offset: offset, - trim_end: false - }; + let fmt = StringFormat { opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + width: width, + offset: offset, + trim_end: false, }; Some(rewrite_string(&s.escape_default(), &fmt)) } @@ -90,7 +88,7 @@ fn rewrite_call(context: &RewriteContext, span: Span, width: usize, offset: usize) - -> Option { + -> Option { debug!("rewrite_call, width: {}, offset: {}", width, offset); // TODO using byte lens instead of char lens (and probably all over the place too) @@ -119,20 +117,22 @@ fn rewrite_call(context: &RewriteContext, callee.span.hi + BytePos(1), span.hi); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: remaining_width, - v_width: remaining_width, - ends_with_newline: true, - }; + let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: remaining_width, + v_width: remaining_width, + ends_with_newline: true, }; Some(format!("{}({})", callee_str, write_list(&items, &fmt))) } -fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, offset: usize) -> Option { +fn rewrite_paren(context: &RewriteContext, + subexpr: &ast::Expr, + width: usize, + offset: usize) + -> Option { debug!("rewrite_paren, width: {}, offset: {}", width, offset); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr @@ -148,14 +148,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span: Span, width: usize, offset: usize) - -> Option -{ + -> Option { debug!("rewrite_struct_lit: width {}, offset {}", width, offset); assert!(fields.len() > 0 || base.is_some()); enum StructLitField<'a> { Regular(&'a ast::Field), - Base(&'a ast::Expr) + Base(&'a ast::Expr), } let path_str = pprust::path_to_string(path); @@ -203,19 +202,17 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span_after(span, "{", context.codemap), span.hi); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: if base.is_some() { + let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: if base.is_some() { SeparatorTactic::Never } else { context.config.struct_lit_trailing_comma }, - indent: indent, - h_width: budget, - v_width: budget, - ends_with_newline: true, - }; + indent: indent, + h_width: budget, + v_width: budget, + ends_with_newline: true, }; let fields_str = write_list(&items, &fmt); Some(format!("{} {{ {} }}", path_str, fields_str)) @@ -225,7 +222,11 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // } } -fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, offset: usize) -> Option { +fn rewrite_field(context: &RewriteContext, + field: &ast::Field, + width: usize, + offset: usize) + -> Option { let name = &token::get_ident(field.ident.node); let overhead = name.len() + 2; let expr = field.expr.rewrite(context, width - overhead, offset + overhead); @@ -262,15 +263,13 @@ fn rewrite_tuple_lit(context: &RewriteContext, SeparatorTactic::Never }; - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: trailing_separator_tactic, - indent: indent, - h_width: width - 2, - v_width: width - 2, - ends_with_newline: true, - }; + let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: trailing_separator_tactic, + indent: indent, + h_width: width - 2, + v_width: width - 2, + ends_with_newline: true, }; Some(format!("({})", write_list(&items, &fmt))) } diff --git a/src/imports.rs b/src/imports.rs index 535e409288b..d9eb7b772a3 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -48,7 +48,8 @@ impl<'a> FmtVisitor<'a> { path: &ast::Path, path_list: &[ast::PathListItem], visibility: ast::Visibility, - span: Span) -> Option { + span: Span) + -> Option { let path_str = pprust::path_to_string(path); let vis = format_visibility(visibility); @@ -70,18 +71,17 @@ impl<'a> FmtVisitor<'a> { let remaining_line_budget = one_line_budget.checked_sub(used_width).unwrap_or(0); let remaining_multi_budget = multi_line_budget.checked_sub(used_width).unwrap_or(0); - let fmt = ListFormatting { - tactic: ListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: block_indent + indent, - h_width: remaining_line_budget, - v_width: remaining_multi_budget, - ends_with_newline: true, - }; + let fmt = ListFormatting { tactic: ListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: block_indent + indent, + h_width: remaining_line_budget, + v_width: remaining_multi_budget, + ends_with_newline: true, }; let mut items = itemize_list(self.codemap, - vec![ListItem::from_str("")], // Dummy value, explanation below + vec![ListItem::from_str("")], /* Dummy value, explanation + * below */ path_list.iter(), ",", "}", diff --git a/src/issues.rs b/src/issues.rs index 0efe0c31c78..bb7e9ba14e3 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -21,7 +21,7 @@ static FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; pub enum ReportTactic { Always, Unnumbered, - Never + Never, } impl ReportTactic { @@ -40,12 +40,12 @@ impl_enum_decodable!(ReportTactic, Always, Unnumbered, Never); enum Seeking { Issue { todo_idx: usize, - fixme_idx: usize + fixme_idx: usize, }, Number { issue: Issue, - part: NumberPart - } + part: NumberPart, + }, } #[derive(Clone, Copy)] @@ -53,7 +53,7 @@ enum NumberPart { OpenParen, Pound, Number, - CloseParen + CloseParen, } #[derive(PartialEq, Eq, Debug, Clone, Copy)] @@ -79,13 +79,13 @@ impl fmt::Display for Issue { #[derive(PartialEq, Eq, Debug, Clone, Copy)] enum IssueType { Todo, - Fixme + Fixme, } enum IssueClassification { Good, Bad(Issue), - None + None, } pub struct BadIssueSeeker { @@ -96,11 +96,9 @@ pub struct BadIssueSeeker { impl BadIssueSeeker { pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { - BadIssueSeeker { - state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 }, - report_todo: report_todo, - report_fixme: report_fixme, - } + BadIssueSeeker { state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 }, + report_todo: report_todo, + report_fixme: report_fixme, } } // Check whether or not the current char is conclusive evidence for an @@ -176,8 +174,7 @@ impl BadIssueSeeker { c: char, issue: Issue, mut part: NumberPart) - -> IssueClassification - { + -> IssueClassification { if ! issue.missing_number || c == '\n' { return IssueClassification::Bad(issue); } else if c == ')' { @@ -272,10 +269,7 @@ fn find_issue() { #[test] fn issue_type() { let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); - let expected = Some(Issue { - issue_type: IssueType::Todo, - missing_number: false - }); + let expected = Some(Issue { issue_type: IssueType::Todo, missing_number: false }); assert_eq!(expected, "TODO(#100): more awesomeness".chars() @@ -284,10 +278,7 @@ fn issue_type() { .unwrap()); let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); - let expected = Some(Issue { - issue_type: IssueType::Fixme, - missing_number: true - }); + let expected = Some(Issue { issue_type: IssueType::Fixme, missing_number: true }); assert_eq!(expected, "Test. FIXME: bad, bad, not good".chars() diff --git a/src/items.rs b/src/items.rs index f4eb8123603..0f7f44f8d99 100644 --- a/src/items.rs +++ b/src/items.rs @@ -33,8 +33,7 @@ impl<'a> FmtVisitor<'a> { abi: &abi::Abi, vis: ast::Visibility, span: Span) - -> String - { + -> String { let newline_brace = self.newline_for_brace(&generics.where_clause); let mut result = self.rewrite_fn_base(indent, @@ -67,8 +66,7 @@ impl<'a> FmtVisitor<'a> { ident: ast::Ident, sig: &ast::MethodSig, span: Span) - -> String - { + -> String { // Drop semicolon or it will be interpreted as comment let span = codemap::mk_sp(span.lo, span.hi - BytePos(1)); @@ -102,8 +100,7 @@ impl<'a> FmtVisitor<'a> { vis: ast::Visibility, span: Span, newline_brace: bool) - -> String - { + -> String { // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. @@ -165,9 +162,10 @@ impl<'a> FmtVisitor<'a> { .last() .map(|tp| end_typaram(tp)) .unwrap_or(span.lo); - let args_span = codemap::mk_sp( - span_after(codemap::mk_sp(args_start, span.hi), "(", self.codemap), - span_for_return(&fd.output).lo); + let args_span = codemap::mk_sp(span_after(codemap::mk_sp(args_start, span.hi), + "(", + self.codemap), + span_for_return(&fd.output).lo); result.push_str(&self.rewrite_args(&fd.inputs, explicit_self, one_line_budget, @@ -229,8 +227,7 @@ impl<'a> FmtVisitor<'a> { multi_line_budget: usize, arg_indent: usize, span: Span) - -> String - { + -> String { let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); // Account for sugary self. let mut min_args = 1; @@ -308,15 +305,13 @@ impl<'a> FmtVisitor<'a> { item.item = arg; } - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: arg_indent, - h_width: one_line_budget, - v_width: multi_line_budget, - ends_with_newline: true, - }; + let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: arg_indent, + h_width: one_line_budget, + v_width: multi_line_budget, + ends_with_newline: true, }; write_list(&arg_items, &fmt) } @@ -326,8 +321,7 @@ impl<'a> FmtVisitor<'a> { indent: usize, ret_str_len: usize, newline_brace: bool) - -> (usize, usize, usize) - { + -> (usize, usize, usize) { let mut budgets = None; // Try keeping everything on the same line @@ -384,8 +378,7 @@ impl<'a> FmtVisitor<'a> { vis: ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, - span: Span) - { + span: Span) { let header_str = self.format_header("enum ", ident, vis); self.changes.push_str_span(span, &header_str); @@ -416,11 +409,7 @@ impl<'a> FmtVisitor<'a> { } // Variant of an enum - fn visit_variant(&mut self, - field: &ast::Variant, - last_field: bool, - next_span_start: BytePos) - { + fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_start: BytePos) { if self.visit_attrs(&field.node.attrs) { return; } @@ -511,8 +500,8 @@ impl<'a> FmtVisitor<'a> { struct_def: &ast::StructDef, generics: Option<&ast::Generics>, span: Span, - offset: usize) -> String - { + offset: usize) + -> String { let mut result = String::with_capacity(1024); let header_str = self.format_header(item_name, ident, vis); @@ -564,8 +553,7 @@ impl<'a> FmtVisitor<'a> { // Conservative approximation let single_line_cost = (span.hi - struct_def.fields[0].span.lo).0; - let break_line = !is_tuple || - generics_str.contains('\n') || + let break_line = !is_tuple || generics_str.contains('\n') || single_line_cost as usize + used_budget > self.config.max_width; if break_line { @@ -578,15 +566,13 @@ impl<'a> FmtVisitor<'a> { // 1 = , let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1; - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: self.config.struct_trailing_comma, - indent: offset + self.config.tab_spaces, - h_width: self.config.max_width, - v_width: budget, - ends_with_newline: false, - }; + let fmt = ListFormatting { tactic: tactic, + separator: ",", + trailing_separator: self.config.struct_trailing_comma, + indent: offset + self.config.tab_spaces, + h_width: self.config.max_width, + v_width: budget, + ends_with_newline: false, }; result.push_str(&write_list(&items, &fmt)); @@ -609,8 +595,7 @@ impl<'a> FmtVisitor<'a> { vis: ast::Visibility, struct_def: &ast::StructDef, generics: &ast::Generics, - span: Span) - { + span: Span) { let indent = self.block_indent; let result = self.format_struct("struct ", ident, @@ -623,12 +608,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = span.hi; } - fn format_header(&self, - item_name: &str, - ident: ast::Ident, - vis: ast::Visibility) - -> String - { + fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { format!("{}{}{}", format_visibility(vis), item_name, &token::get_ident(ident)) } @@ -637,8 +617,7 @@ impl<'a> FmtVisitor<'a> { opener: &str, offset: usize, span: Span) - -> String - { + -> String { let mut result = self.rewrite_generics(generics, offset, span); if generics.where_clause.predicates.len() > 0 || result.contains('\n') { @@ -728,15 +707,13 @@ impl<'a> FmtVisitor<'a> { item.item = ty; } - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset + 1, - h_width: budget, - v_width: budget, - ends_with_newline: true, - }; + let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset + 1, + h_width: budget, + v_width: budget, + ends_with_newline: true, }; result.push_str(&write_list(&items, &fmt)); result.push('>'); @@ -748,8 +725,7 @@ impl<'a> FmtVisitor<'a> { where_clause: &ast::WhereClause, indent: usize, span_end: BytePos) - -> String - { + -> String { let mut result = String::new(); if where_clause.predicates.len() == 0 { return result; @@ -772,15 +748,13 @@ impl<'a> FmtVisitor<'a> { span_end); let budget = self.config.ideal_width + self.config.leeway - indent - 10; - let fmt = ListFormatting { - tactic: ListTactic::Vertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + 10, - h_width: budget, - v_width: budget, - ends_with_newline: true, - }; + let fmt = ListFormatting { tactic: ListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + 10, + h_width: budget, + v_width: budget, + ends_with_newline: true, }; result.push_str(&write_list(&items, &fmt)); result diff --git a/src/lists.rs b/src/lists.rs index 87a71578e96..155c8ab08cb 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -48,20 +48,19 @@ pub struct ListFormatting<'a> { pub v_width: usize, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. - pub ends_with_newline: bool + pub ends_with_newline: bool, } pub struct ListItem { pub pre_comment: Option, // Item should include attributes and doc comments pub item: String, - pub post_comment: Option + pub post_comment: Option, } impl ListItem { pub fn is_multiline(&self) -> bool { - self.item.contains('\n') || - self.pre_comment.is_some() || + self.item.contains('\n') || self.pre_comment.is_some() || self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false) } @@ -70,11 +69,7 @@ impl ListItem { } pub fn from_str>(s: S) -> ListItem { - ListItem { - pre_comment: None, - item: s.into(), - post_comment: None - } + ListItem { pre_comment: None, item: s.into(), post_comment: None } } } @@ -239,8 +234,8 @@ pub fn itemize_list(codemap: &CodeMap, get_item_string: F3, mut prev_span_end: BytePos, next_span_start: BytePos) - -> Vec - where I: Iterator, + -> Vec + where I: Iterator, F1: Fn(&T) -> BytePos, F2: Fn(&T) -> BytePos, F3: Fn(&T) -> String diff --git a/src/missed_spans.rs b/src/missed_spans.rs index c861d631be8..d560b3f2027 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -36,8 +36,7 @@ impl<'a> FmtVisitor<'a> { fn format_missing_inner(&mut self, end: BytePos, - process_last_snippet: F) - { + process_last_snippet: F) { let start = self.last_pos; debug!("format_missing_inner: {:?} to {:?}", self.codemap.lookup_char_pos(start), diff --git a/src/types.rs b/src/types.rs index c16b9eadf4e..6880cd8bcc2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -15,8 +15,7 @@ use syntax::parse::token; use syntax::print::pprust; impl<'a> FmtVisitor<'a> { - pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String - { + pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String { // TODO dead spans // TODO assumes we'll always fit on one line... match predicate { @@ -49,8 +48,7 @@ impl<'a> FmtVisitor<'a> { } } - pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String - { + pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String { if lifetime.bounds.len() == 0 { return pprust::lifetime_to_string(&lifetime.lifetime); } @@ -60,8 +58,7 @@ impl<'a> FmtVisitor<'a> { lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect(" + ")) } - pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String - { + pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String { match *bound { ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { self.rewrite_poly_trait_ref(tref) @@ -75,8 +72,7 @@ impl<'a> FmtVisitor<'a> { } } - pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String - { + pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String { let mut result = String::with_capacity(128); result.push_str(&token::get_ident(ty_param.ident)); if ty_param.bounds.len() > 0 { @@ -91,8 +87,7 @@ impl<'a> FmtVisitor<'a> { result } - fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String - { + fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String { if t.bound_lifetimes.len() > 0 { format!("for<{}> {}", t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), diff --git a/src/visitor.rs b/src/visitor.rs index ed5a5f5da1b..5c15e1bf523 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -282,13 +282,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { impl<'a> FmtVisitor<'a> { pub fn from_codemap<'b>(codemap: &'b CodeMap, config: &'b Config) -> FmtVisitor<'b> { - FmtVisitor { - codemap: codemap, - changes: ChangeSet::from_codemap(codemap), - last_pos: BytePos(0), - block_indent: 0, - config: config - } + FmtVisitor { codemap: codemap, + changes: ChangeSet::from_codemap(codemap), + last_pos: BytePos(0), + block_indent: 0, + config: config, } } pub fn snippet(&self, span: Span) -> String { -- cgit 1.4.1-3-g733a5 From b93b64381f4431e80f3752fe74714a5c4399d514 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Wed, 15 Jul 2015 00:38:54 +0200 Subject: Fix bug in rewrite_tup_lit Wasn't using all width available when the lenght is more than 1. --- src/expr.rs | 17 ++++++++--------- tests/target/tuple.rs | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index da706c4afa7..5dde0419c14 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -239,7 +239,13 @@ fn rewrite_tuple_lit(context: &RewriteContext, width: usize, offset: usize) -> Option { + debug!("rewrite_tuple_lit: width: {}, offset: {}", width, offset); let indent = offset + 1; + // In case of length 1, need a trailing comma + if items.len() == 1 { + // 3 = "(" + ",)" + return items[0].rewrite(context, width - 3, indent).map(|s| format!("({},)", s)); + } let items = itemize_list(context.codemap, Vec::new(), @@ -249,23 +255,16 @@ fn rewrite_tuple_lit(context: &RewriteContext, |item| item.span.lo, |item| item.span.hi, |item| item.rewrite(context, - context.config.max_width - indent - 2, + context.config.max_width - indent - 1, indent) .unwrap_or(context.codemap.span_to_snippet(item.span) .unwrap()), span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); - // In case of length 1, need a trailing comma - let trailing_separator_tactic = if items.len() == 1 { - SeparatorTactic::Always - } else { - SeparatorTactic::Never - }; - let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, separator: ",", - trailing_separator: trailing_separator_tactic, + trailing_separator: SeparatorTactic::Never, indent: indent, h_width: width - 2, v_width: width - 2, diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 2d126cacf96..a77fae11cb4 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -13,3 +13,17 @@ fn foo() { b, // Comment b /* Trailing comment */); } + +fn a() { + ((aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa),) +} + +fn b() { + ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + bbbbbbbbbbbbbbbbbb) +} -- cgit 1.4.1-3-g733a5 From b473c2bd2a56a61275a47b95f75b0aff8fdb600a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 13 Jul 2015 21:51:56 +0200 Subject: Format loops --- src/changes.rs | 8 ++++++++ src/expr.rs | 31 ++++++++++++++++++++++++++++++- src/rewrite.rs | 1 + src/visitor.rs | 4 +++- tests/source/loop.rs | 11 +++++++++++ tests/target/loop.rs | 14 ++++++++++++++ 6 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 tests/source/loop.rs create mode 100644 tests/target/loop.rs (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 3f0d985da48..4cce45e5eb3 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -99,6 +99,14 @@ impl<'a> ChangeSet<'a> { self.push_str(&file_name, text) } + // Fetch the output buffer for the given file name. + // Panics on unknown files. + pub fn get(&mut self, file_name: &str) -> &StringBuffer { + self.file_map.get(file_name).unwrap() + } + + // Fetch a mutable reference to the output buffer for the given file name. + // Panics on unknown files. pub fn get_mut(&mut self, file_name: &str) -> &mut StringBuffer { self.file_map.get_mut(file_name).unwrap() } diff --git a/src/expr.rs b/src/expr.rs index da706c4afa7..e87020f4ae1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,11 +12,13 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; use utils::{span_after, make_indent}; +use visitor::FmtVisitor; use syntax::{ast, ptr}; -use syntax::codemap::{Pos, Span, BytePos}; +use syntax::codemap::{Pos, Span, BytePos, mk_sp}; use syntax::parse::token; use syntax::print::pprust; +use syntax::visit::Visitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { @@ -53,11 +55,38 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprTup(ref items) => { rewrite_tuple_lit(context, items, self.span, width, offset) } + ast::Expr_::ExprLoop(ref block, _) => { + // FIXME: this drops any comment between "loop" and the block. + // TODO: format label + block.rewrite(context, width, offset).map(|result| { + format!("loop {}", result) + }) + } _ => context.codemap.span_to_snippet(self.span).ok() } } } +impl Rewrite for ast::Block { + fn rewrite(&self, context: &RewriteContext, _: usize, _: usize) -> Option { + let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config); + visitor.last_pos = self.span.lo; + visitor.block_indent = context.block_indent; + + visitor.visit_block(self); + + // Push text between last block item and end of block + let snippet = visitor.snippet(mk_sp(visitor.last_pos, self.span.hi)); + visitor.changes.push_str_span(self.span, &snippet); + + // Stringify visitor + let file_name = context.codemap.span_to_filename(self.span); + let string_buffer = visitor.changes.get(&file_name); + + Some(string_buffer.to_string()) + } +} + fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, diff --git a/src/rewrite.rs b/src/rewrite.rs index 78d611253dd..33e4d5fbbf3 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -28,4 +28,5 @@ pub trait Rewrite { pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, pub config: &'a Config, + pub block_indent: usize, } diff --git a/src/visitor.rs b/src/visitor.rs index 5c15e1bf523..1b1fd9d17c6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -38,7 +38,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); - let context = RewriteContext { codemap: self.codemap, config: self.config }; + let context = RewriteContext { codemap: self.codemap, + config: self.config, + block_indent: self.block_indent, }; let rewrite = ex.rewrite(&context, self.config.max_width - offset, offset); if let Some(new_str) = rewrite { diff --git a/tests/source/loop.rs b/tests/source/loop.rs new file mode 100644 index 00000000000..ad5ef93521d --- /dev/null +++ b/tests/source/loop.rs @@ -0,0 +1,11 @@ + +fn main() { + loop + { return some_val;} + +let x = loop { do_forever(); }; + + loop { + // Just comments + } +} diff --git a/tests/target/loop.rs b/tests/target/loop.rs new file mode 100644 index 00000000000..3eb506eb6ed --- /dev/null +++ b/tests/target/loop.rs @@ -0,0 +1,14 @@ + +fn main() { + loop { + return some_val; + } + + let x = loop { + do_forever(); + }; + + loop { + // Just comments + } +} -- cgit 1.4.1-3-g733a5 From 7518f688613a58bc2a070f2eb2e66364dfea7fe5 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 16 Jul 2015 10:44:43 +1200 Subject: Add an option to format struct lits with either block or visual indent --- src/config.rs | 13 +++++++-- src/default.toml | 1 + src/expr.rs | 28 +++++++++++++----- src/lib.rs | 13 +++++++++ tests/config/reorder_imports.toml | 1 + tests/config/small_tabs.toml | 1 + tests/config/visual_struct_lits.toml | 15 ++++++++++ tests/source/struct_lits_visual.rs | 39 +++++++++++++++++++++++++ tests/target/struct_lits.rs | 55 ++++++++++++++++++++---------------- tests/target/struct_lits_visual.rs | 52 ++++++++++++++++++++++++++++++++++ 10 files changed, 185 insertions(+), 33 deletions(-) create mode 100644 tests/config/visual_struct_lits.toml create mode 100644 tests/source/struct_lits_visual.rs create mode 100644 tests/target/struct_lits_visual.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 0ea13768457..a01d3e64689 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,7 +10,7 @@ extern crate toml; -use {NewlineStyle, BraceStyle, ReturnIndent}; +use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle}; use lists::SeparatorTactic; use issues::ReportTactic; @@ -26,6 +26,7 @@ pub struct Config { pub fn_args_paren_newline: bool, pub struct_trailing_comma: SeparatorTactic, pub struct_lit_trailing_comma: SeparatorTactic, + pub struct_lit_style: StructLitStyle, pub enum_trailing_comma: bool, pub report_todo: ReportTactic, pub report_fixme: ReportTactic, @@ -35,6 +36,14 @@ pub struct Config { impl Config { pub fn from_toml(toml: &str) -> Config { let parsed = toml.parse().unwrap(); - toml::decode(parsed).unwrap() + match toml::decode(parsed) { + Some(decoded) => decoded, + None => { + println!("Decoding config file failed. Config:\n{}", toml); + let parsed: toml::Value = toml.parse().unwrap(); + println!("\n\nParsed:\n{:?}", parsed); + panic!(); + } + } } } diff --git a/src/default.toml b/src/default.toml index 951fde9d665..e31a0f257e9 100644 --- a/src/default.toml +++ b/src/default.toml @@ -7,6 +7,7 @@ fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true report_todo = "Always" diff --git a/src/expr.rs b/src/expr.rs index 33a82da0f29..c6e9a84421a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -11,6 +11,7 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; +use StructLitStyle; use utils::{span_after, make_indent}; use visitor::FmtVisitor; @@ -188,8 +189,15 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let path_str = pprust::path_to_string(path); // Foo { a: Foo } - indent is +3, width is -5. - let indent = offset + path_str.len() + 3; - let budget = width - (path_str.len() + 5); + let (indent, budget) = match context.config.struct_lit_style { + StructLitStyle::VisualIndent => { + (offset + path_str.len() + 3, width - (path_str.len() + 5)) + } + StructLitStyle::BlockIndent => { + let indent = context.block_indent + context.config.tab_spaces; + (indent, width - indent) + } + }; let field_iter = fields.into_iter().map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); @@ -243,12 +251,18 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, v_width: budget, ends_with_newline: true, }; let fields_str = write_list(&items, &fmt); - Some(format!("{} {{ {} }}", path_str, fields_str)) - // FIXME if the usual multi-line layout is too wide, we should fall back to - // Foo { - // a: ..., - // } + match context.config.struct_lit_style { + StructLitStyle::BlockIndent if fields_str.contains('\n') => { + let inner_indent = make_indent(context.block_indent + context.config.tab_spaces); + let outer_indent = make_indent(context.block_indent); + Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) + } + _ => Some(format!("{} {{ {} }}", path_str, fields_str)), + } + + // FIXME if context.config.struct_lit_style == VisualIndent, but we run out + // of space, we should fall back to BlockIndent. } fn rewrite_field(context: &RewriteContext, diff --git a/src/lib.rs b/src/lib.rs index 252b3ad05b7..296a462ed38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,6 +111,19 @@ pub enum ReturnIndent { impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); +// How to stle a struct literal. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum StructLitStyle { + // First line on the same line as the opening brace, all lines aligned with + // the first line. + VisualIndent, + // First line is on a new line and all lines align with block indent. + BlockIndent, + // FIXME Maybe we should also have an option to align types. +} + +impl_enum_decodable!(StructLitStyle, VisualIndent, BlockIndent); + enum ErrorKind { // Line has exceeded character limit LineOverflow, diff --git a/tests/config/reorder_imports.toml b/tests/config/reorder_imports.toml index 31b0e2c6217..ddab2479f2c 100644 --- a/tests/config/reorder_imports.toml +++ b/tests/config/reorder_imports.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 35477559e43..303433dbcc1 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" diff --git a/tests/config/visual_struct_lits.toml b/tests/config/visual_struct_lits.toml new file mode 100644 index 00000000000..cf601303e9b --- /dev/null +++ b/tests/config/visual_struct_lits.toml @@ -0,0 +1,15 @@ +max_width = 100 +ideal_width = 80 +leeway = 5 +tab_spaces = 4 +newline_style = "Unix" +fn_brace_style = "SameLineWhere" +fn_return_indent = "WithArgs" +fn_args_paren_newline = true +struct_trailing_comma = "Vertical" +struct_lit_style = "VisualIndent" +struct_lit_trailing_comma = "Vertical" +enum_trailing_comma = true +report_todo = "Always" +report_fixme = "Never" +reorder_imports = false diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs new file mode 100644 index 00000000000..b629ffa1263 --- /dev/null +++ b/tests/source/struct_lits_visual.rs @@ -0,0 +1,39 @@ +// rustfmt-config: visual_struct_lits.toml + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index c46909825a1..befeede14df 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -6,30 +6,35 @@ fn main() { // Comment let y = Foo { a: x }; - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* C - * o - * m - * m - * e - * n - * t */ - // Comment - b: bar(), /* C - * o - * m - * m - * e - * n - * t */ }; + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Comment + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ + }; Foo { a: Bar, b: foo() }; @@ -39,12 +44,14 @@ fn main() { first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; + second: Item, + }; Diagram { // o This graph demonstrates how // / \ significant whitespace is // o o preserved. // /|\ \ // o o o o - graph: G, } + graph: G, + } } diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs new file mode 100644 index 00000000000..651cd2b883b --- /dev/null +++ b/tests/target/struct_lits_visual.rs @@ -0,0 +1,52 @@ +// rustfmt-config: visual_struct_lits.toml + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Comment + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ }; + + Foo { a: Bar, b: foo() }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +} -- cgit 1.4.1-3-g733a5 From 018fa8545359b8580a89a1cdf79ed186c997ed41 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 16 Jul 2015 13:31:20 +1200 Subject: Reformat code to new struct lit style --- src/changes.rs | 8 +++++--- src/comment.rs | 16 ++++++++------- src/expr.rs | 64 +++++++++++++++++++++++++++++++++------------------------- src/imports.rs | 16 ++++++++------- src/issues.rs | 8 +++++--- src/items.rs | 64 +++++++++++++++++++++++++++++++++------------------------- src/visitor.rs | 20 ++++++++++-------- 7 files changed, 112 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index 4cce45e5eb3..ab5968dbf76 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -35,9 +35,11 @@ pub struct ChangeSet<'a> { impl<'a> ChangeSet<'a> { // Create a new ChangeSet for a given libsyntax CodeMap. pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut result = ChangeSet { file_map: HashMap::new(), - codemap: codemap, - file_spans: Vec::with_capacity(codemap.files.borrow().len()), }; + let mut result = ChangeSet { + file_map: HashMap::new(), + codemap: codemap, + file_spans: Vec::with_capacity(codemap.files.borrow().len()), + }; for f in codemap.files.borrow().iter() { // Use the length of the file as a heuristic for how much space we diff --git a/src/comment.rs b/src/comment.rs index 064cace6c51..7e4119880c3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -24,13 +24,15 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz let max_chars = width.checked_sub(closer.len()).unwrap_or(1) .checked_sub(opener.len()).unwrap_or(1); - let fmt = StringFormat { opener: "", - closer: "", - line_start: line_start, - line_end: "", - width: max_chars, - offset: offset + opener.len() - line_start.len(), - trim_end: true, }; + let fmt = StringFormat { + opener: "", + closer: "", + line_start: line_start, + line_end: "", + width: max_chars, + offset: offset + opener.len() - line_start.len(), + trim_end: true, + }; let indent_str = make_indent(offset); let line_breaks = s.chars().filter(|&c| c == '\n').count(); diff --git a/src/expr.rs b/src/expr.rs index c6e9a84421a..e6390a08793 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -101,13 +101,15 @@ fn rewrite_string_lit(context: &RewriteContext, if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width { return context.codemap.span_to_snippet(span).ok(); } - let fmt = StringFormat { opener: "\"", - closer: "\"", - line_start: " ", - line_end: "\\", - width: width, - offset: offset, - trim_end: false, }; + let fmt = StringFormat { + opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + width: width, + offset: offset, + trim_end: false, + }; Some(rewrite_string(&s.escape_default(), &fmt)) } @@ -147,13 +149,15 @@ fn rewrite_call(context: &RewriteContext, callee.span.hi + BytePos(1), span.hi); - let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: remaining_width, - v_width: remaining_width, - ends_with_newline: true, }; + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: remaining_width, + v_width: remaining_width, + ends_with_newline: true, + }; Some(format!("{}({})", callee_str, write_list(&items, &fmt))) } @@ -239,17 +243,19 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span_after(span, "{", context.codemap), span.hi); - let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: if base.is_some() { + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: if base.is_some() { SeparatorTactic::Never } else { context.config.struct_lit_trailing_comma }, - indent: indent, - h_width: budget, - v_width: budget, - ends_with_newline: true, }; + indent: indent, + h_width: budget, + v_width: budget, + ends_with_newline: true, + }; let fields_str = write_list(&items, &fmt); match context.config.struct_lit_style { @@ -305,13 +311,15 @@ fn rewrite_tuple_lit(context: &RewriteContext, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); - let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - h_width: width - 2, - v_width: width - 2, - ends_with_newline: true, }; + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + h_width: width - 2, + v_width: width - 2, + ends_with_newline: true, + }; Some(format!("({})", write_list(&items, &fmt))) } diff --git a/src/imports.rs b/src/imports.rs index d9eb7b772a3..45a8e94dee5 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -71,13 +71,15 @@ impl<'a> FmtVisitor<'a> { let remaining_line_budget = one_line_budget.checked_sub(used_width).unwrap_or(0); let remaining_multi_budget = multi_line_budget.checked_sub(used_width).unwrap_or(0); - let fmt = ListFormatting { tactic: ListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: block_indent + indent, - h_width: remaining_line_budget, - v_width: remaining_multi_budget, - ends_with_newline: true, }; + let fmt = ListFormatting { + tactic: ListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: block_indent + indent, + h_width: remaining_line_budget, + v_width: remaining_multi_budget, + ends_with_newline: true, + }; let mut items = itemize_list(self.codemap, vec![ListItem::from_str("")], /* Dummy value, explanation diff --git a/src/issues.rs b/src/issues.rs index bb7e9ba14e3..31f544605b5 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -96,9 +96,11 @@ pub struct BadIssueSeeker { impl BadIssueSeeker { pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { - BadIssueSeeker { state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 }, - report_todo: report_todo, - report_fixme: report_fixme, } + BadIssueSeeker { + state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 }, + report_todo: report_todo, + report_fixme: report_fixme, + } } // Check whether or not the current char is conclusive evidence for an diff --git a/src/items.rs b/src/items.rs index 0f7f44f8d99..42a0d609dd0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -305,13 +305,15 @@ impl<'a> FmtVisitor<'a> { item.item = arg; } - let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: arg_indent, - h_width: one_line_budget, - v_width: multi_line_budget, - ends_with_newline: true, }; + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: arg_indent, + h_width: one_line_budget, + v_width: multi_line_budget, + ends_with_newline: true, + }; write_list(&arg_items, &fmt) } @@ -566,13 +568,15 @@ impl<'a> FmtVisitor<'a> { // 1 = , let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1; - let fmt = ListFormatting { tactic: tactic, - separator: ",", - trailing_separator: self.config.struct_trailing_comma, - indent: offset + self.config.tab_spaces, - h_width: self.config.max_width, - v_width: budget, - ends_with_newline: false, }; + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: self.config.struct_trailing_comma, + indent: offset + self.config.tab_spaces, + h_width: self.config.max_width, + v_width: budget, + ends_with_newline: false, + }; result.push_str(&write_list(&items, &fmt)); @@ -707,13 +711,15 @@ impl<'a> FmtVisitor<'a> { item.item = ty; } - let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset + 1, - h_width: budget, - v_width: budget, - ends_with_newline: true, }; + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset + 1, + h_width: budget, + v_width: budget, + ends_with_newline: true, + }; result.push_str(&write_list(&items, &fmt)); result.push('>'); @@ -748,13 +754,15 @@ impl<'a> FmtVisitor<'a> { span_end); let budget = self.config.ideal_width + self.config.leeway - indent - 10; - let fmt = ListFormatting { tactic: ListTactic::Vertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent + 10, - h_width: budget, - v_width: budget, - ends_with_newline: true, }; + let fmt = ListFormatting { + tactic: ListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent + 10, + h_width: budget, + v_width: budget, + ends_with_newline: true, + }; result.push_str(&write_list(&items, &fmt)); result diff --git a/src/visitor.rs b/src/visitor.rs index 1b1fd9d17c6..53446d6e119 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -38,9 +38,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); let offset = self.changes.cur_offset_span(ex.span); - let context = RewriteContext { codemap: self.codemap, - config: self.config, - block_indent: self.block_indent, }; + let context = RewriteContext { + codemap: self.codemap, + config: self.config, + block_indent: self.block_indent, + }; let rewrite = ex.rewrite(&context, self.config.max_width - offset, offset); if let Some(new_str) = rewrite { @@ -284,11 +286,13 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { impl<'a> FmtVisitor<'a> { pub fn from_codemap<'b>(codemap: &'b CodeMap, config: &'b Config) -> FmtVisitor<'b> { - FmtVisitor { codemap: codemap, - changes: ChangeSet::from_codemap(codemap), - last_pos: BytePos(0), - block_indent: 0, - config: config, } + FmtVisitor { + codemap: codemap, + changes: ChangeSet::from_codemap(codemap), + last_pos: BytePos(0), + block_indent: 0, + config: config, + } } pub fn snippet(&self, span: Span) -> String { -- cgit 1.4.1-3-g733a5 From a32b0e7627ea31d1967568aa034f74a082de4bec Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 16 Jul 2015 14:03:52 +1200 Subject: Fix some bugs --- src/expr.rs | 19 +++++++++++-------- tests/source/struct_lits.rs | 4 +++- tests/target/struct_lits.rs | 39 ++++++++++++++++----------------------- 3 files changed, 30 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e6390a08793..23caa933e1d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -192,14 +192,17 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } let path_str = pprust::path_to_string(path); - // Foo { a: Foo } - indent is +3, width is -5. - let (indent, budget) = match context.config.struct_lit_style { + let (indent, h_budget, v_budget) = match context.config.struct_lit_style { StructLitStyle::VisualIndent => { - (offset + path_str.len() + 3, width - (path_str.len() + 5)) + // Foo { a: Foo } - indent is +3, width is -5. + let budget = width - (path_str.len() + 5); + (offset + path_str.len() + 3, budget, budget) } StructLitStyle::BlockIndent => { + // If we are all on one line, then we'll ignore the indent, and we + // have a smaller budget. let indent = context.block_indent + context.config.tab_spaces; - (indent, width - indent) + (indent, width - (path_str.len() + 5), width - indent) } }; @@ -227,13 +230,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| { match *item { StructLitField::Regular(ref field) => { - rewrite_field(context, &field, budget, indent) + rewrite_field(context, &field, h_budget, indent) .unwrap_or(context.codemap.span_to_snippet(field.span) .unwrap()) }, StructLitField::Base(ref expr) => { // 2 = .. - expr.rewrite(context, budget - 2, indent + 2) + expr.rewrite(context, h_budget - 2, indent + 2) .map(|s| format!("..{}", s)) .unwrap_or(context.codemap.span_to_snippet(expr.span) .unwrap()) @@ -252,8 +255,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, context.config.struct_lit_trailing_comma }, indent: indent, - h_width: budget, - v_width: budget, + h_width: h_budget, + v_width: v_budget, ends_with_newline: true, }; let fields_str = write_list(&items, &fmt); diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index b7e1a854b0b..f2726821e55 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -8,7 +8,9 @@ fn main() { Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index befeede14df..293a2a97b7a 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -13,33 +13,25 @@ fn main() { ..something }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* C - * o - * m - * m - * e - * n - * t */ + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment // Comment - b: bar(), /* C - * o - * m - * m - * e - * n - * t */ + b: bar(), /* Comment */ }; Foo { a: Bar, b: foo() }; - A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed + // sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante // hendrerit. Donec et mollis dolor. first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. @@ -47,11 +39,12 @@ fn main() { second: Item, }; - Diagram { // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o graph: G, } } -- cgit 1.4.1-3-g733a5 From 9ab1587a9840c6debac688f7b41b35b944831d99 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 16 Jul 2015 14:17:07 +1200 Subject: Don't apologise if its not our fault in warnings --- src/lib.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 252b3ad05b7..c296b3cda00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,13 +125,13 @@ impl fmt::Display for ErrorKind { match *self { ErrorKind::LineOverflow => { write!(fmt, "line exceeded maximum length") - }, + } ErrorKind::TrailingWhitespace => { write!(fmt, "left behind trailing whitespace") - }, + } ErrorKind::BadIssue(issue) => { write!(fmt, "found {}", issue) - }, + } } } } @@ -142,6 +142,24 @@ struct FormattingError { kind: ErrorKind, } +impl FormattingError { + fn msg_prefix(&self) -> &str { + match self.kind { + ErrorKind::LineOverflow | + ErrorKind::TrailingWhitespace => "Rustfmt failed at", + ErrorKind::BadIssue(_) => "WARNING:", + } + } + + fn msg_suffix(&self) -> &str { + match self.kind { + ErrorKind::LineOverflow | + ErrorKind::TrailingWhitespace => "(sorry)", + ErrorKind::BadIssue(_) => "", + } + } +} + struct FormatReport { // Maps stringified file paths to their associated formatting errors file_error_map: HashMap>, @@ -153,10 +171,12 @@ impl fmt::Display for FormatReport { for (file, errors) in self.file_error_map.iter() { for error in errors { try!(write!(fmt, - "Rustfmt failed at {}:{}: {} (sorry)\n", + "{} {}:{}: {} {}\n", + error.msg_prefix(), file, error.line, - error.kind)); + error.kind, + error.msg_suffix())); } } Ok(()) -- cgit 1.4.1-3-g733a5 From f2bcee9d873adaf31dfdc5aee06ff89c0373e2b3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 16 Jul 2015 14:23:48 +1200 Subject: Tidy up some overrunning lines --- src/expr.rs | 4 +++- src/items.rs | 8 +++++--- src/types.rs | 21 ++++++++++++++------- src/visitor.rs | 4 +++- 4 files changed, 25 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 33a82da0f29..7110d508d5d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -315,7 +315,9 @@ fn rewrite_binary_op(context: &RewriteContext, // 1 = space between lhs expr and operator let mut result = - try_opt!(lhs.rewrite(context, context.config.max_width - offset - 1 - operator_str.len(), offset)); + try_opt!(lhs.rewrite(context, + context.config.max_width - offset - 1 - operator_str.len(), + offset)); result.push(' '); result.push_str(&operator_str); diff --git a/src/items.rs b/src/items.rs index 0f7f44f8d99..4b473dff4ba 100644 --- a/src/items.rs +++ b/src/items.rs @@ -467,8 +467,9 @@ impl<'a> FmtVisitor<'a> { // Make sure we do not exceed column limit // 4 = " = ," - assert!(self.config.max_width >= vis.len() + name.len() + expr_snippet.len() + 4, - "Enum variant exceeded column limit"); + assert!( + self.config.max_width >= vis.len() + name.len() + expr_snippet.len() + 4, + "Enum variant exceeded column limit"); } result @@ -768,7 +769,8 @@ impl<'a> FmtVisitor<'a> { } } - // TODO we farm this out, but this could spill over the column limit, so we ought to handle it properly + // TODO we farm this out, but this could spill over the column limit, so we + // ought to handle it properly. fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { format!("{}: {}", pprust::pat_to_string(&arg.pat), diff --git a/src/types.rs b/src/types.rs index 6880cd8bcc2..3ac82ae27ee 100644 --- a/src/types.rs +++ b/src/types.rs @@ -25,14 +25,17 @@ impl<'a> FmtVisitor<'a> { ..}) => { if bound_lifetimes.len() > 0 { format!("for<{}> {}: {}", - bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), + bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)) + .collect::>().connect(", "), pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(" + ")) + bounds.iter().map(|b| self.rewrite_ty_bound(b)) + .collect::>().connect(" + ")) } else { format!("{}: {}", pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(" + ")) + bounds.iter().map(|b| self.rewrite_ty_bound(b)) + .collect::>().connect(" + ")) } } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, @@ -40,7 +43,8 @@ impl<'a> FmtVisitor<'a> { ..}) => { format!("{}: {}", pprust::lifetime_to_string(lifetime), - bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect(" + ")) + bounds.iter().map(|l| pprust::lifetime_to_string(l)) + .collect::>().connect(" + ")) } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) @@ -55,7 +59,8 @@ impl<'a> FmtVisitor<'a> { format!("{}: {}", pprust::lifetime_to_string(&lifetime.lifetime), - lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::>().connect(" + ")) + lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)) + .collect::>().connect(" + ")) } pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String { @@ -77,7 +82,8 @@ impl<'a> FmtVisitor<'a> { result.push_str(&token::get_ident(ty_param.ident)); if ty_param.bounds.len() > 0 { result.push_str(": "); - result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)).collect::>().connect(" + ")); + result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)) + .collect::>().connect(" + ")); } if let Some(ref def) = ty_param.default { result.push_str(" = "); @@ -90,7 +96,8 @@ impl<'a> FmtVisitor<'a> { fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String { if t.bound_lifetimes.len() > 0 { format!("for<{}> {}", - t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::>().connect(", "), + t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)) + .collect::>().connect(", "), pprust::path_to_string(&t.trait_ref.path)) } else { diff --git a/src/visitor.rs b/src/visitor.rs index 1b1fd9d17c6..eb3c4be80f7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -380,7 +380,9 @@ impl<'a> FmtVisitor<'a> { } Some(open_brace) => { debug!("FmtVisitor::format_mod: internal mod"); - debug!("... open_brace: {}, str: {:?}", open_brace, self.codemap.span_to_snippet(s)); + debug!("... open_brace: {}, str: {:?}", + open_brace, + self.codemap.span_to_snippet(s)); // Format everything until opening brace // TODO Shoud rewrite properly self.format_missing(s.lo + BytePos(open_brace as u32)); -- cgit 1.4.1-3-g733a5 From 979d0c975636cd87a27dd020c1ace644aa1aa4e9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 17 Jul 2015 18:26:10 +1200 Subject: Resolve some warnings --- src/imports.rs | 2 +- src/lib.rs | 2 +- src/types.rs | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 45a8e94dee5..1973115cd43 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -109,7 +109,7 @@ impl<'a> FmtVisitor<'a> { let first_index = if has_self { 0 } else { 1 }; if self.config.reorder_imports { - items.tail_mut().sort_by(|a, b| a.item.cmp(&b.item)); + items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } let list = write_list(&items[first_index..], &fmt); diff --git a/src/lib.rs b/src/lib.rs index a4100fc53e9..a3a0659c292 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ #![feature(rustc_private)] #![feature(str_escape)] #![feature(str_char)] -#![feature(slice_extras)] + // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? diff --git a/src/types.rs b/src/types.rs index 3ac82ae27ee..474881b8ad2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -26,16 +26,16 @@ impl<'a> FmtVisitor<'a> { if bound_lifetimes.len() > 0 { format!("for<{}> {}: {}", bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)) - .collect::>().connect(", "), + .collect::>().join(", "), pprust::ty_to_string(bounded_ty), bounds.iter().map(|b| self.rewrite_ty_bound(b)) - .collect::>().connect(" + ")) + .collect::>().join(" + ")) } else { format!("{}: {}", pprust::ty_to_string(bounded_ty), bounds.iter().map(|b| self.rewrite_ty_bound(b)) - .collect::>().connect(" + ")) + .collect::>().join(" + ")) } } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, @@ -44,7 +44,7 @@ impl<'a> FmtVisitor<'a> { format!("{}: {}", pprust::lifetime_to_string(lifetime), bounds.iter().map(|l| pprust::lifetime_to_string(l)) - .collect::>().connect(" + ")) + .collect::>().join(" + ")) } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) @@ -60,7 +60,7 @@ impl<'a> FmtVisitor<'a> { format!("{}: {}", pprust::lifetime_to_string(&lifetime.lifetime), lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)) - .collect::>().connect(" + ")) + .collect::>().join(" + ")) } pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String { @@ -83,7 +83,7 @@ impl<'a> FmtVisitor<'a> { if ty_param.bounds.len() > 0 { result.push_str(": "); result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)) - .collect::>().connect(" + ")); + .collect::>().join(" + ")); } if let Some(ref def) = ty_param.default { result.push_str(" = "); @@ -97,7 +97,7 @@ impl<'a> FmtVisitor<'a> { if t.bound_lifetimes.len() > 0 { format!("for<{}> {}", t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)) - .collect::>().connect(", "), + .collect::>().join(", "), pprust::path_to_string(&t.trait_ref.path)) } else { -- cgit 1.4.1-3-g733a5 From e47e91013ed69e967bb3a07145e86a789c28a1b4 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 16 Jul 2015 16:29:28 +0200 Subject: Format while loops, including labels --- src/expr.rs | 26 +++++++++++++++++++++++--- tests/source/loop.rs | 7 ++++++- tests/target/loop.rs | 9 ++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8dbe5c6d1dd..e0a76308b44 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -56,11 +56,24 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprTup(ref items) => { rewrite_tuple_lit(context, items, self.span, width, offset) } - ast::Expr_::ExprLoop(ref block, _) => { + ast::Expr_::ExprWhile(ref subexpr, ref block, label) => { + let label_string = rewrite_label(label); + // 6 = "while " + // 2 = " {" + let expr_width = width - 6 - 2 - label_string.len(); + let expr_offset = offset + 6 + label_string.len(); + + subexpr.rewrite(context, expr_width, expr_offset).and_then(|expr_string| { + // FIXME: this drops any comment between "loop" and the block. + block.rewrite(context, width, offset).map(|result| { + format!("{}while {} {}", rewrite_label(label), expr_string, result) + }) + }) + } + ast::Expr_::ExprLoop(ref block, label) => { // FIXME: this drops any comment between "loop" and the block. - // TODO: format label block.rewrite(context, width, offset).map(|result| { - format!("loop {}", result) + format!("{}loop {}", rewrite_label(label), result) }) } _ => context.codemap.span_to_snippet(self.span).ok() @@ -88,6 +101,13 @@ impl Rewrite for ast::Block { } } +fn rewrite_label(label: Option) -> String { + match label { + Some(ident) => format!("{}: ", ident.as_str()), + None => "".to_owned() + } +} + fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, diff --git a/tests/source/loop.rs b/tests/source/loop.rs index ad5ef93521d..143a3a23760 100644 --- a/tests/source/loop.rs +++ b/tests/source/loop.rs @@ -5,7 +5,12 @@ fn main() { let x = loop { do_forever(); }; - loop { + 'label : loop { // Just comments } + + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value{} + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { + } } diff --git a/tests/target/loop.rs b/tests/target/loop.rs index 3eb506eb6ed..cec8b2bff61 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -8,7 +8,14 @@ fn main() { do_forever(); }; - loop { + 'label: loop { // Just comments } + + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > + some_other_value { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { + } } -- cgit 1.4.1-3-g733a5 From b161815fe0aace4baa7007386b783a88547d7548 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 19 Jul 2015 23:42:54 +0200 Subject: Format if-else expressions --- src/comment.rs | 8 +++++--- src/expr.rs | 40 ++++++++++++++++++++++++++++++++++++-- src/imports.rs | 12 ++++++++++-- src/issues.rs | 8 ++++++-- src/items.rs | 18 ++++++++++++++--- src/utils.rs | 8 ++++++-- tests/source/expr.rs | 13 ++++++++++++- tests/source/struct_lits_visual.rs | 2 ++ tests/target/expr.rs | 19 +++++++++++++++++- tests/target/struct_lits_visual.rs | 5 +++++ 10 files changed, 117 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 7e4119880c3..6d453bd5c88 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -17,9 +17,11 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz let s = orig.trim(); // Edge case: block comments. Let's not trim their lines (for now). - let opener = if block_style { "/* " } else { "// " }; - let closer = if block_style { " */" } else { "" }; - let line_start = if block_style { " * " } else { "// " }; + let (opener, closer, line_start) = if block_style { + ("/* ", " */", " * ") + } else { + ("// ", "", "// ") + }; let max_chars = width.checked_sub(closer.len()).unwrap_or(1) .checked_sub(opener.len()).unwrap_or(1); diff --git a/src/expr.rs b/src/expr.rs index e0a76308b44..89846527cff 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -76,6 +76,17 @@ impl Rewrite for ast::Expr { format!("{}loop {}", rewrite_label(label), result) }) } + ast::Expr_::ExprBlock(ref block) => { + block.rewrite(context, width, offset) + } + ast::Expr_::ExprIf(ref cond, ref if_block, ref else_block) => { + rewrite_if_else(context, + cond, + if_block, + else_block.as_ref().map(|e| &**e), + width, + offset) + } _ => context.codemap.span_to_snippet(self.span).ok() } } @@ -108,6 +119,29 @@ fn rewrite_label(label: Option) -> String { } } +fn rewrite_if_else(context: &RewriteContext, + cond: &ast::Expr, + if_block: &ast::Block, + else_block: Option<&ast::Expr>, + width: usize, + offset: usize) + -> Option { + // FIXME: missing comments between control statements and blocks + let cond_string = try_opt!(cond.rewrite(context, width - 3 - 2, offset + 3)); + let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); + + match else_block { + Some(else_block) => { + else_block.rewrite(context, width, offset).map(|else_block_string| { + format!("if {} {} else {}", cond_string, if_block_string, else_block_string) + }) + } + None => { + Some(format!("if {} {}", cond_string, if_block_string)) + } + } +} + fn rewrite_string_lit(context: &RewriteContext, s: &str, span: Span, @@ -229,6 +263,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let field_iter = fields.into_iter().map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); + let inner_context = &RewriteContext { block_indent: indent, ..*context }; + let items = itemize_list(context.codemap, Vec::new(), field_iter, @@ -250,13 +286,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| { match *item { StructLitField::Regular(ref field) => { - rewrite_field(context, &field, h_budget, indent) + rewrite_field(inner_context, &field, h_budget, indent) .unwrap_or(context.codemap.span_to_snippet(field.span) .unwrap()) }, StructLitField::Base(ref expr) => { // 2 = .. - expr.rewrite(context, h_budget - 2, indent + 2) + expr.rewrite(inner_context, h_budget - 2, indent + 2) .map(|s| format!("..{}", s)) .unwrap_or(context.codemap.span_to_snippet(expr.span) .unwrap()) diff --git a/src/imports.rs b/src/imports.rs index 1973115cd43..66bf26b041d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -60,7 +60,11 @@ impl<'a> FmtVisitor<'a> { } // 2 = :: - let path_separation_w = if path_str.len() > 0 { 2 } else { 0 }; + let path_separation_w = if path_str.len() > 0 { + 2 + } else { + 0 + }; // 5 = "use " + { let indent = path_str.len() + 5 + path_separation_w + vis.len(); @@ -106,7 +110,11 @@ impl<'a> FmtVisitor<'a> { // FIXME: Make more efficient by using a linked list? That would // require changes to the signatures of itemize_list and write_list. let has_self = move_self_to_front(&mut items); - let first_index = if has_self { 0 } else { 1 }; + let first_index = if has_self { + 0 + } else { + 1 + }; if self.config.reorder_imports { items[1..].sort_by(|a, b| a.item.cmp(&b.item)); diff --git a/src/issues.rs b/src/issues.rs index 31f544605b5..34d5b8ab2c4 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -70,7 +70,11 @@ impl fmt::Display for Issue { IssueType::Todo => "TODO", IssueType::Fixme => "FIXME", }; - let details = if self.missing_number { " without issue number" } else { "" }; + let details = if self.missing_number { + " without issue number" + } else { + "" + }; write!(fmt, "{}{}", msg, details) } @@ -177,7 +181,7 @@ impl BadIssueSeeker { issue: Issue, mut part: NumberPart) -> IssueClassification { - if ! issue.missing_number || c == '\n' { + if !issue.missing_number || c == '\n' { return IssueClassification::Bad(issue); } else if c == ')' { return if let NumberPart::CloseParen = part { diff --git a/src/items.rs b/src/items.rs index b3f4a0a63a4..3c35b20fb3f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -446,7 +446,11 @@ impl<'a> FmtVisitor<'a> { + field.node.name.to_string().len() + 1; // Open paren - let comma_cost = if self.config.enum_trailing_comma { 1 } else { 0 }; + let comma_cost = if self.config.enum_trailing_comma { + 1 + } else { + 0 + }; let budget = self.config.ideal_width - indent - comma_cost - 1; // 1 = ) let fmt = ListFormatting { @@ -520,7 +524,11 @@ impl<'a> FmtVisitor<'a> { ast::StructFieldKind::UnnamedField(..) => true }; - let (opener, terminator) = if is_tuple { ("(", ")") } else { (" {", "}") }; + let (opener, terminator) = if is_tuple { + ("(", ")") + } else { + (" {", "}") + }; let generics_str = match generics { Some(g) => self.format_generics(g, @@ -565,7 +573,11 @@ impl<'a> FmtVisitor<'a> { result.push_str(&indentation); } - let tactic = if break_line { ListTactic::Vertical } else { ListTactic::Horizontal }; + let tactic = if break_line { + ListTactic::Vertical + } else { + ListTactic::Horizontal + }; // 1 = , let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1; diff --git a/src/utils.rs b/src/utils.rs index 47203a0754f..246f7cb2dc3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -24,7 +24,9 @@ pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { #[inline] pub fn prev_char(s: &str, mut i: usize) -> usize { - if i == 0 { return 0; } + if i == 0 { + return 0; + } i -= 1; while !s.is_char_boundary(i) { @@ -35,7 +37,9 @@ pub fn prev_char(s: &str, mut i: usize) -> usize { #[inline] pub fn next_char(s: &str, mut i: usize) -> usize { - if i >= s.len() { return s.len(); } + if i >= s.len() { + return s.len(); + } while !s.is_char_boundary(i) { i += 1; diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 373e42d67c5..d26c57ebbd0 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -12,5 +12,16 @@ some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 - 50000 * sqrt(-1), trivial_value); (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))); + + if 1 + 2 > 0 { let result = 5; result } else { 4}; + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + // Check subformatting + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } } diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index b629ffa1263..f14a56397ec 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -22,6 +22,8 @@ fn main() { Foo { a:Bar, b:foo() }; + Quux { x: if cond { bar(); }, y: baz() }; + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. first: item(), diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 25c84511c41..3a8605b7c42 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -13,5 +13,22 @@ fn foo() -> bool { trivial_value); (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaa))))))))) + aaaaa))))))))); + + if 1 + 2 > 0 { + let result = 5; + result + } else { + 4 + }; + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + // Check subformatting + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } } diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 651cd2b883b..248839cb869 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -35,6 +35,11 @@ fn main() { Foo { a: Bar, b: foo() }; + Quux { x: if cond { + bar(); + }, + y: baz(), }; + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante // hendrerit. Donec et mollis dolor. -- cgit 1.4.1-3-g733a5 From 2fda8dd883f5de6989280884a37e408981dfc2ee Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 19 Jul 2015 22:25:44 +0200 Subject: Format if-let-else expressions --- src/expr.rs | 59 ++++++++++++++++++++++++++++++++++++++++++---------- tests/source/expr.rs | 14 +++++++++++++ tests/target/expr.rs | 17 +++++++++++++++ 3 files changed, 79 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 89846527cff..68b780b414a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -84,6 +84,16 @@ impl Rewrite for ast::Expr { cond, if_block, else_block.as_ref().map(|e| &**e), + None, + width, + offset) + } + ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref else_block) => { + rewrite_if_else(context, + cond, + if_block, + else_block.as_ref().map(|e| &**e), + Some(pat), width, offset) } @@ -112,9 +122,16 @@ impl Rewrite for ast::Block { } } +// TODO(#18): implement pattern formatting +impl Rewrite for ast::Pat { + fn rewrite(&self, context: &RewriteContext, _: usize, _: usize) -> Option { + context.codemap.span_to_snippet(self.span).ok() + } +} + fn rewrite_label(label: Option) -> String { match label { - Some(ident) => format!("{}: ", ident.as_str()), + Some(ident) => format!("{}: ", ident), None => "".to_owned() } } @@ -123,23 +140,43 @@ fn rewrite_if_else(context: &RewriteContext, cond: &ast::Expr, if_block: &ast::Block, else_block: Option<&ast::Expr>, + pat: Option<&ast::Pat>, width: usize, offset: usize) -> Option { // FIXME: missing comments between control statements and blocks - let cond_string = try_opt!(cond.rewrite(context, width - 3 - 2, offset + 3)); + // 3 = "if ", 2 = " {" + let pat_string = match pat { + Some(pat) => { + // 7 = "let ".len() + " = ".len() + // 4 = "let ".len() + let pat_string = try_opt!(pat.rewrite(context, width - 3 - 2 - 7, offset + 3 + 4)); + format!("let {} = ", pat_string) + } + None => String::new() + }; + + // Consider only the last line of the pat string + let extra_offset = match pat_string.rfind('\n') { + // 1 for newline character + Some(idx) => pat_string.len() - idx - 1 - offset, + None => 3 + pat_string.len() + }; + + let cond_string = try_opt!(cond.rewrite(context, + width - extra_offset - 2, + offset + extra_offset)); let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); + let mut result = format!("if {}{} {}", pat_string, cond_string, if_block_string); - match else_block { - Some(else_block) => { - else_block.rewrite(context, width, offset).map(|else_block_string| { - format!("if {} {} else {}", cond_string, if_block_string, else_block_string) - }) - } - None => { - Some(format!("if {} {}", cond_string, if_block_string)) - } + if let Some(else_block) = else_block { + let else_block_string = try_opt!(else_block.rewrite(context, width, offset)); + + result.push_str(" else "); + result.push_str(&else_block_string); } + + Some(result) } fn rewrite_string_lit(context: &RewriteContext, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index d26c57ebbd0..19baa90ace2 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -16,6 +16,20 @@ some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 if 1 + 2 > 0 { let result = 5; result } else { 4}; + if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + // Nothing + } + + if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + + 2 + 3 { + } + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} + if cond() { something(); } else if different_cond() { diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 3a8605b7c42..86ad2dd406d 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -22,6 +22,23 @@ fn foo() -> bool { 4 }; + if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + // Nothing + } + + if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) { + } + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { + } + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + + 2222 { + } + if cond() { something(); } else if different_cond() { -- cgit 1.4.1-3-g733a5 From 2fa6220f57228d149f99272a4b3f97b560359738 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 19 Jul 2015 23:39:48 +0200 Subject: Format all the loops! --- src/expr.rs | 172 +++++++++++++++++++++++++++++++++++++++++---------- src/lib.rs | 7 ++- src/lists.rs | 9 ++- src/visitor.rs | 2 +- tests/source/loop.rs | 9 +++ tests/target/loop.rs | 9 +++ 6 files changed, 169 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 68b780b414a..35bd90f5f32 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -56,21 +56,45 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprTup(ref items) => { rewrite_tuple_lit(context, items, self.span, width, offset) } - ast::Expr_::ExprWhile(ref subexpr, ref block, label) => { - let label_string = rewrite_label(label); - // 6 = "while " - // 2 = " {" - let expr_width = width - 6 - 2 - label_string.len(); - let expr_offset = offset + 6 + label_string.len(); - - subexpr.rewrite(context, expr_width, expr_offset).and_then(|expr_string| { - // FIXME: this drops any comment between "loop" and the block. - block.rewrite(context, width, offset).map(|result| { - format!("{}while {} {}", rewrite_label(label), expr_string, result) - }) - }) + ast::Expr_::ExprWhile(ref cond, ref block, label) => { + rewrite_loop(context, + cond, + block, + label, + None, + "while ", + "let ", + " = ", + width, + offset) + } + ast::Expr_::ExprWhileLet(ref pat, ref cond, ref block, label) => { + rewrite_loop(context, + cond, + block, + label, + Some(pat), + "while ", + "let ", + " = ", + width, + offset) + } + ast::Expr_::ExprForLoop(ref pat, ref cond, ref block, label) => { + rewrite_loop(context, + cond, + block, + label, + Some(pat), + "for ", + "", + " in ", + width, + offset) } ast::Expr_::ExprLoop(ref block, label) => { + // Of all the loops, this is the only one that does not use + // rewrite_loop! // FIXME: this drops any comment between "loop" and the block. block.rewrite(context, width, offset).map(|result| { format!("{}loop {}", rewrite_label(label), result) @@ -97,6 +121,14 @@ impl Rewrite for ast::Expr { width, offset) } + // We reformat it ourselves because rustc gives us a bad span for ranges + ast::Expr_::ExprRange(ref left, ref right) => { + rewrite_range(context, + left.as_ref().map(|e| &**e), + right.as_ref().map(|e| &**e), + width, + offset) + } _ => context.codemap.span_to_snippet(self.span).ok() } } @@ -136,6 +168,61 @@ fn rewrite_label(label: Option) -> String { } } +// FIXME: this doesn't play well with line breaks +fn rewrite_range(context: &RewriteContext, + left: Option<&ast::Expr>, + right: Option<&ast::Expr>, + width: usize, + offset: usize) + -> Option { + let left_string = match left { + // 2 = .. + Some(expr) => try_opt!(expr.rewrite(context, width - 2, offset)), + None => String::new() + }; + + let right_string = match right { + Some(expr) => { + // 2 = .. + let max_width = (width - 2).checked_sub(left_string.len()).unwrap_or(0); + try_opt!(expr.rewrite(context, max_width, offset + 2 + left_string.len())) + } + None => String::new() + }; + + Some(format!("{}..{}", left_string, right_string)) +} + +fn rewrite_loop(context: &RewriteContext, + cond: &ast::Expr, + block: &ast::Block, + label: Option, + pat: Option<&ast::Pat>, + keyword: &str, + matcher: &str, // FIXME: think of better identifiers + connector: &str, + width: usize, + offset: usize) + -> Option { + let label_string = rewrite_label(label); + // 2 = " {" + let inner_width = width - keyword.len() - 2 - label_string.len(); + let inner_offset = offset + keyword.len() + label_string.len(); + + let pat_expr_string = try_opt!(rewrite_pat_expr(context, + pat, + cond, + matcher, + connector, + inner_width, + inner_offset)); + + // FIXME: this drops any comment between "loop" and the block. + block.rewrite(context, width, offset).map(|result| { + format!("{}{}{} {}", label_string, keyword, pat_expr_string, result) + }) +} + fn rewrite_if_else(context: &RewriteContext, cond: &ast::Expr, if_block: &ast::Block, @@ -144,37 +231,58 @@ fn rewrite_if_else(context: &RewriteContext, width: usize, offset: usize) -> Option { - // FIXME: missing comments between control statements and blocks // 3 = "if ", 2 = " {" - let pat_string = match pat { + let pat_expr_string = try_opt!(rewrite_pat_expr(context, + pat, + cond, + "let ", + " = ", + width - 3 - 2, + offset + 3)); + + let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); + let mut result = format!("if {} {}", pat_expr_string, if_block_string); + + if let Some(else_block) = else_block { + let else_block_string = try_opt!(else_block.rewrite(context, width, offset)); + + result.push_str(" else "); + result.push_str(&else_block_string); + } + + Some(result) +} + +fn rewrite_pat_expr(context: &RewriteContext, + pat: Option<&ast::Pat>, + expr: &ast::Expr, + matcher: &str, + connector: &str, + width: usize, + offset: usize) + -> Option { + let mut result = match pat { Some(pat) => { - // 7 = "let ".len() + " = ".len() - // 4 = "let ".len() - let pat_string = try_opt!(pat.rewrite(context, width - 3 - 2 - 7, offset + 3 + 4)); - format!("let {} = ", pat_string) + let pat_string = try_opt!(pat.rewrite(context, + width - connector.len() - matcher.len(), + offset + matcher.len())); + format!("{}{}{}", matcher, pat_string, connector) } None => String::new() }; // Consider only the last line of the pat string - let extra_offset = match pat_string.rfind('\n') { + let extra_offset = match result.rfind('\n') { // 1 for newline character - Some(idx) => pat_string.len() - idx - 1 - offset, - None => 3 + pat_string.len() + Some(idx) => result.len() - idx - 1 - offset, + None => result.len() }; - let cond_string = try_opt!(cond.rewrite(context, - width - extra_offset - 2, + let expr_string = try_opt!(expr.rewrite(context, + width - extra_offset, offset + extra_offset)); - let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); - let mut result = format!("if {}{} {}", pat_string, cond_string, if_block_string); - if let Some(else_block) = else_block { - let else_block_string = try_opt!(else_block.rewrite(context, width, offset)); - - result.push_str(" else "); - result.push_str(&else_block_string); - } + result.push_str(&expr_string); Some(result) } diff --git a/src/lib.rs b/src/lib.rs index a3a0659c292..5ea4812e144 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,11 +218,12 @@ fn fmt_lines(changes: &mut ChangeSet, config: &Config) -> FormatReport { let mut cur_line = 1; let mut newline_count = 0; let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo, - config.report_fixme); + let mut issue_seeker = BadIssueSeeker::new(config.report_todo, config.report_fixme); for (c, b) in text.chars() { - if c == '\r' { continue; } + if c == '\r' { + continue; + } // Add warnings for bad todos/ fixmes if let Some(issue) = issue_seeker.inspect(c) { diff --git a/src/lists.rs b/src/lists.rs index 155c8ab08cb..13c0cf763e3 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -136,7 +136,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St let first = i == 0; let last = i == items.len() - 1; let separate = !last || trailing_separator; - let item_sep_len = if separate { sep_len } else { 0 }; + let item_sep_len = if separate { + sep_len + } else { + 0 + }; let item_width = item.item.len() + item_sep_len; match tactic { @@ -208,8 +212,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St let comment = item.post_comment.as_ref().unwrap(); // Use block-style only for the last item or multiline comments. let block_style = formatting.ends_with_newline && last || - comment.trim().contains('\n') || - comment.trim().len() > width; + comment.trim().contains('\n') || comment.trim().len() > width; let formatted_comment = rewrite_comment(comment, block_style, width, offset); diff --git a/src/visitor.rs b/src/visitor.rs index ae5b2083ccc..ee5688c14a1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -353,7 +353,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&a_str); - if i < attrs.len() -1 { + if i < attrs.len() - 1 { result.push('\n'); } } diff --git a/tests/source/loop.rs b/tests/source/loop.rs index 143a3a23760..36e6ab43de8 100644 --- a/tests/source/loop.rs +++ b/tests/source/loop.rs @@ -13,4 +13,13 @@ let x = loop { do_forever(); }; while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } + + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { + // do smth + } + + while let Some(i) = x.find('s') + { + x.update(); + } } diff --git a/tests/target/loop.rs b/tests/target/loop.rs index cec8b2bff61..e1f2ccc91a4 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -18,4 +18,13 @@ fn main() { while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } + + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, + arg2) { + // do smth + } + + while let Some(i) = x.find('s') { + x.update(); + } } -- cgit 1.4.1-3-g733a5 From 500fb78a3393a76e7790a38eb4df0b346eda9fe5 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 19 Jul 2015 14:33:02 +0200 Subject: Format unnamed function arguments --- src/items.rs | 30 +++++++++++++++++++++++++----- tests/target/trait.rs | 4 ++++ 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index b3f4a0a63a4..3250a93b997 100644 --- a/src/items.rs +++ b/src/items.rs @@ -289,10 +289,10 @@ impl<'a> FmtVisitor<'a> { arg_items = itemize_list(self.codemap, arg_items, - args[min_args-1..].iter(), + args[min_args-1..].iter().cloned(), ",", ")", - |arg| arg.pat.span.lo, + span_lo_for_arg, |arg| arg.ty.span.hi, |_| String::new(), comment_span_start, @@ -780,9 +780,29 @@ impl<'a> FmtVisitor<'a> { // TODO we farm this out, but this could spill over the column limit, so we // ought to handle it properly. fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { - format!("{}: {}", - pprust::pat_to_string(&arg.pat), - pprust::ty_to_string(&arg.ty)) + if is_named_arg(arg) { + format!("{}: {}", + pprust::pat_to_string(&arg.pat), + pprust::ty_to_string(&arg.ty)) + } else { + pprust::ty_to_string(&arg.ty) + } + } +} + +fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { + if is_named_arg(arg) { + arg.pat.span.lo + } else { + arg.ty.span.lo + } +} + +fn is_named_arg(arg: &ast::Arg) -> bool { + if let ast::Pat_::PatIdent(_, ident, _) = arg.pat.node { + ident.node != token::special_idents::invalid + } else { + true } } diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 8f7f4be67c9..b7d711f8b00 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -18,3 +18,7 @@ trait Foo { fn read(&mut self, x: BufReader /* Used to be MemReader */) where R: Read; } + +pub trait WriteMessage { + fn write_message(&mut self, &FrontendMessage) -> io::Result<()>; +} -- cgit 1.4.1-3-g733a5 From c10c732425436d44f6166cdf924d5cd4c973eeaa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Jul 2015 08:05:34 +1200 Subject: Simplify CompilerCalls impl --- src/lib.rs | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index a3a0659c292..b2a0f7aed4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -285,33 +285,11 @@ fn fmt_lines(changes: &mut ChangeSet, config: &Config) -> FormatReport { } struct RustFmtCalls { - input_path: Option, write_mode: WriteMode, config: Option>, } impl<'a> CompilerCalls<'a> for RustFmtCalls { - fn early_callback(&mut self, - _: &getopts::Matches, - _: &diagnostics::registry::Registry) - -> Compilation { - Compilation::Continue - } - - fn some_input(&mut self, - input: Input, - input_path: Option) - -> (Input, Option) { - match input_path { - Some(ref ip) => self.input_path = Some(ip.clone()), - _ => { - // FIXME should handle string input and write to stdout or something - panic!("No input path"); - } - } - (input, input_path) - } - fn no_input(&mut self, _: &getopts::Matches, _: &rustc_config::Options, @@ -322,16 +300,6 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { panic!("No input supplied to RustFmt"); } - fn late_callback(&mut self, - _: &getopts::Matches, - _: &Session, - _: &Input, - _: &Option, - _: &Option) - -> Compilation { - Compilation::Continue - } - fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { let write_mode = self.write_mode; @@ -373,6 +341,6 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { // default_config is a string of toml data to be used to configure rustfmt. pub fn run(args: Vec, write_mode: WriteMode, default_config: &str) { let config = Some(Box::new(config::Config::from_toml(default_config))); - let mut call_ctxt = RustFmtCalls { input_path: None, write_mode: write_mode, config: config }; + let mut call_ctxt = RustFmtCalls { write_mode: write_mode, config: config }; rustc_driver::run_compiler(&args, &mut call_ctxt); } -- cgit 1.4.1-3-g733a5 From d13fc2289acebe8a6f52507fb53408cbac46d35f Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 22 Jul 2015 23:39:37 +0200 Subject: Fix underflow bug in rewrite_call Fixes https://github.com/nrc/rustfmt/issues/148. Now properly propagates the rewrite failure instead of panicking. Added regression test from servo code. This example will be properly rewritten when https://github.com/nrc/rustfmt/issues/17 is addressed. --- src/expr.rs | 2 +- tests/target/fn.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8dbe5c6d1dd..0beaee9dbf2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -132,7 +132,7 @@ fn rewrite_call(context: &RewriteContext, } // 2 is for parens. - let remaining_width = width - callee_str.len() - 2; + let remaining_width = try_opt!(width.checked_sub(callee_str.len() + 2)); let offset = callee_str.len() + 1 + offset; let items = itemize_list(context.codemap, diff --git a/tests/target/fn.rs b/tests/target/fn.rs index bc05efa5351..6c41f62a8b2 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -79,3 +79,17 @@ fn main() { let _ = function(move || 5); let _ = move || 42; } + +fn servo() { + let constellation_chan = Constellation::::start( + compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard); +} -- cgit 1.4.1-3-g733a5 From d7fe47d858d55fcca7445436dd0517a98c6a13bb Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 23 Jul 2015 23:08:41 +0200 Subject: Preserve box syntax --- src/expr.rs | 6 ++++-- tests/source/expr.rs | 3 +++ tests/target/expr.rs | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0beaee9dbf2..cb5188017fd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -378,11 +378,13 @@ fn rewrite_unary_op(context: &RewriteContext, -> Option { // For some reason, an UnOp is not spanned like BinOp! let operator_str = match *op { - ast::UnOp::UnUniq => "&", + ast::UnOp::UnUniq => "box ", ast::UnOp::UnDeref => "*", ast::UnOp::UnNot => "!", ast::UnOp::UnNeg => "-" }; - Some(format!("{}{}", operator_str, try_opt!(expr.rewrite(context, width - 1, offset)))) + let subexpr = try_opt!(expr.rewrite(context, width - operator_str.len(), offset)); + + Some(format!("{}{}", operator_str, subexpr)) } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 373e42d67c5..4f6e1b6f74a 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -1,6 +1,9 @@ // Test expressions fn foo() -> bool { + let boxed: Box = box 5; + let referenced = &5; + let very_long_variable_name = ( a + first + simple + test ); let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 25c84511c41..e5a584ecb96 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -1,6 +1,9 @@ // Test expressions fn foo() -> bool { + let boxed: Box = box 5; + let referenced = &5; + let very_long_variable_name = (a + first + simple + test); let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); -- cgit 1.4.1-3-g733a5 From c4101de53d8a0707907cb03c67a9224ab9943d37 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 20 Jul 2015 23:29:25 +0200 Subject: Refactor some things; add extra tests. --- src/config.rs | 13 +++ src/default.toml | 1 + src/expr.rs | 219 ++++++++++++++++++++++------------- src/imports.rs | 8 +- src/lib.rs | 3 +- tests/config/expr_visual_indent.toml | 16 +++ tests/config/reorder_imports.toml | 1 + tests/config/small_tabs.toml | 1 + tests/config/visual_struct_lits.toml | 1 + tests/source/expr-visual-indent.rs | 9 ++ tests/source/expr.rs | 24 ++++ tests/source/struct_lits.rs | 11 ++ tests/target/expr-visual-indent.rs | 9 ++ tests/target/expr.rs | 44 +++++++ tests/target/struct_lits.rs | 20 +++- 15 files changed, 292 insertions(+), 88 deletions(-) create mode 100644 tests/config/expr_visual_indent.toml create mode 100644 tests/source/expr-visual-indent.rs create mode 100644 tests/target/expr-visual-indent.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index a01d3e64689..3d41b51661e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,6 +14,18 @@ use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle}; use lists::SeparatorTactic; use issues::ReportTactic; +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum BlockIndentStyle { + // Same level as parent. + Inherit, + // One level deeper than parent. + Tabbed, + // Aligned with block open. + Visual, +} + +impl_enum_decodable!(BlockIndentStyle, Inherit, Tabbed, Visual); + #[derive(RustcDecodable, Clone)] pub struct Config { pub max_width: usize, @@ -31,6 +43,7 @@ pub struct Config { pub report_todo: ReportTactic, pub report_fixme: ReportTactic, pub reorder_imports: bool, // Alphabetically, case sensitive. + pub expr_indent_style: BlockIndentStyle, } impl Config { diff --git a/src/default.toml b/src/default.toml index e31a0f257e9..035fa21e917 100644 --- a/src/default.toml +++ b/src/default.toml @@ -13,3 +13,4 @@ enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = false +expr_indent_style = "Tabbed" diff --git a/src/expr.rs b/src/expr.rs index 35bd90f5f32..e81314eba79 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -14,6 +14,7 @@ use string::{StringFormat, rewrite_string}; use StructLitStyle; use utils::{span_after, make_indent}; use visitor::FmtVisitor; +use config::BlockIndentStyle; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos, mk_sp}; @@ -57,48 +58,16 @@ impl Rewrite for ast::Expr { rewrite_tuple_lit(context, items, self.span, width, offset) } ast::Expr_::ExprWhile(ref cond, ref block, label) => { - rewrite_loop(context, - cond, - block, - label, - None, - "while ", - "let ", - " = ", - width, - offset) + Loop::new_while(None, cond, block, label).rewrite(context, width, offset) } ast::Expr_::ExprWhileLet(ref pat, ref cond, ref block, label) => { - rewrite_loop(context, - cond, - block, - label, - Some(pat), - "while ", - "let ", - " = ", - width, - offset) + Loop::new_while(Some(pat), cond, block, label).rewrite(context, width, offset) } ast::Expr_::ExprForLoop(ref pat, ref cond, ref block, label) => { - rewrite_loop(context, - cond, - block, - label, - Some(pat), - "for ", - "", - " in ", - width, - offset) + Loop::new_for(pat, cond, block, label).rewrite(context, width, offset) } ast::Expr_::ExprLoop(ref block, label) => { - // Of all the loops, this is the only one that does not use - // rewrite_loop! - // FIXME: this drops any comment between "loop" and the block. - block.rewrite(context, width, offset).map(|result| { - format!("{}loop {}", rewrite_label(label), result) - }) + Loop::new_loop(block, label).rewrite(context, width, offset) } ast::Expr_::ExprBlock(ref block) => { block.rewrite(context, width, offset) @@ -121,7 +90,8 @@ impl Rewrite for ast::Expr { width, offset) } - // We reformat it ourselves because rustc gives us a bad span for ranges + // We reformat it ourselves because rustc gives us a bad span + // for ranges, see rust#27162 ast::Expr_::ExprRange(ref left, ref right) => { rewrite_range(context, left.as_ref().map(|e| &**e), @@ -161,6 +131,91 @@ impl Rewrite for ast::Pat { } } +// Abstraction over for, while and loop expressions +struct Loop<'a> { + cond: Option<&'a ast::Expr>, + block: &'a ast::Block, + label: Option, + pat: Option<&'a ast::Pat>, + keyword: &'a str, + matcher: &'a str, + connector: &'a str, +} + +impl<'a> Loop<'a> { + fn new_loop(block: &'a ast::Block, label: Option) -> Loop<'a> { + Loop { + cond: None, + block: block, + label: label, + pat: None, + keyword: "loop", + matcher: "", + connector: "", + } + } + + fn new_while(pat: Option<&'a ast::Pat>, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option) + -> Loop<'a> { + Loop { + cond: Some(cond), + block: block, + label: label, + pat: pat, + keyword: "while ", + matcher: match pat { + Some(..) => "let ", + None => "" + }, + connector: " =", + } + } + + fn new_for(pat: &'a ast::Pat, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option) + -> Loop<'a> { + Loop { + cond: Some(cond), + block: block, + label: label, + pat: Some(pat), + keyword: "for ", + matcher: "", + connector: " in", + } + } +} + +impl<'a> Rewrite for Loop<'a> { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + let label_string = rewrite_label(self.label); + // 2 = " {".len() + let inner_width = width - self.keyword.len() - 2 - label_string.len(); + let inner_offset = offset + self.keyword.len() + label_string.len(); + + let pat_expr_string = match self.cond { + Some(cond) => try_opt!(rewrite_pat_expr(context, + self.pat, + cond, + self.matcher, + self.connector, + inner_width, + inner_offset)), + None => String::new() + }; + + // FIXME: this drops any comment between "loop" and the block. + self.block.rewrite(context, width, offset).map(|result| { + format!("{}{}{} {}", label_string, self.keyword, pat_expr_string, result) + }) + } +} + fn rewrite_label(label: Option) -> String { match label { Some(ident) => format!("{}: ", ident), @@ -193,36 +248,8 @@ fn rewrite_range(context: &RewriteContext, Some(format!("{}..{}", left_string, right_string)) } -fn rewrite_loop(context: &RewriteContext, - cond: &ast::Expr, - block: &ast::Block, - label: Option, - pat: Option<&ast::Pat>, - keyword: &str, - matcher: &str, // FIXME: think of better identifiers - connector: &str, - width: usize, - offset: usize) - -> Option { - let label_string = rewrite_label(label); - // 2 = " {" - let inner_width = width - keyword.len() - 2 - label_string.len(); - let inner_offset = offset + keyword.len() + label_string.len(); - - let pat_expr_string = try_opt!(rewrite_pat_expr(context, - pat, - cond, - matcher, - connector, - inner_width, - inner_offset)); - - // FIXME: this drops any comment between "loop" and the block. - block.rewrite(context, width, offset).map(|result| { - format!("{}{}{} {}", label_string, keyword, pat_expr_string, result) - }) -} - +// Rewrites if-else blocks. If let Some(_) = pat, the expression is +// treated as an if-let-else expression. fn rewrite_if_else(context: &RewriteContext, cond: &ast::Expr, if_block: &ast::Block, @@ -236,7 +263,7 @@ fn rewrite_if_else(context: &RewriteContext, pat, cond, "let ", - " = ", + " =", width - 3 - 2, offset + 3)); @@ -261,28 +288,49 @@ fn rewrite_pat_expr(context: &RewriteContext, width: usize, offset: usize) -> Option { + let pat_offset = offset + matcher.len(); let mut result = match pat { Some(pat) => { let pat_string = try_opt!(pat.rewrite(context, width - connector.len() - matcher.len(), - offset + matcher.len())); + pat_offset)); format!("{}{}{}", matcher, pat_string, connector) } None => String::new() }; - // Consider only the last line of the pat string + // Consider only the last line of the pat string. let extra_offset = match result.rfind('\n') { // 1 for newline character Some(idx) => result.len() - idx - 1 - offset, None => result.len() }; - let expr_string = try_opt!(expr.rewrite(context, - width - extra_offset, - offset + extra_offset)); + // The expression may (partionally) fit on the current line. + if width > extra_offset + 1 { + let mut corrected_offset = extra_offset; - result.push_str(&expr_string); + if pat.is_some() { + result.push(' '); + corrected_offset += 1; + } + + let expr_rewrite = expr.rewrite(context, + width - corrected_offset, + offset + corrected_offset); + + if let Some(expr_string) = expr_rewrite { + result.push_str(&expr_string); + return Some(result); + } + } + + // The expression won't fit on the current line, jump to next. + result.push('\n'); + result.push_str(&make_indent(pat_offset)); + + let expr_rewrite = expr.rewrite(context, context.config.max_width - pat_offset, pat_offset); + result.push_str(&&try_opt!(expr_rewrite)); Some(result) } @@ -333,6 +381,8 @@ fn rewrite_call(context: &RewriteContext, // 2 is for parens. let remaining_width = width - callee_str.len() - 2; let offset = callee_str.len() + 1 + offset; + let block_indent = expr_block_indent(context, offset); + let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; let items = itemize_list(context.codemap, Vec::new(), @@ -342,7 +392,7 @@ fn rewrite_call(context: &RewriteContext, |item| item.span.lo, |item| item.span.hi, // Take old span when rewrite fails. - |item| item.rewrite(context, remaining_width, offset) + |item| item.rewrite(inner_context, remaining_width, offset) .unwrap_or(context.codemap.span_to_snippet(item.span) .unwrap()), callee.span.hi + BytePos(1), @@ -361,6 +411,14 @@ fn rewrite_call(context: &RewriteContext, Some(format!("{}({})", callee_str, write_list(&items, &fmt))) } +fn expr_block_indent(context: &RewriteContext, offset: usize) -> usize { + match context.config.expr_indent_style { + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Tabbed => context.block_indent + context.config.tab_spaces, + BlockIndentStyle::Visual => offset, + } +} + fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, @@ -391,17 +449,18 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } let path_str = pprust::path_to_string(path); - let (indent, h_budget, v_budget) = match context.config.struct_lit_style { + // Foo { a: Foo } - indent is +3, width is -5. + let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); + let (indent, v_budget) = match context.config.struct_lit_style { StructLitStyle::VisualIndent => { - // Foo { a: Foo } - indent is +3, width is -5. - let budget = width - (path_str.len() + 5); - (offset + path_str.len() + 3, budget, budget) + (offset + path_str.len() + 3, h_budget) } StructLitStyle::BlockIndent => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. let indent = context.block_indent + context.config.tab_spaces; - (indent, width - (path_str.len() + 5), width - indent) + let v_budget = context.config.max_width.checked_sub(indent).unwrap_or(0); + (indent, v_budget) } }; diff --git a/src/imports.rs b/src/imports.rs index 66bf26b041d..12ce3368eb3 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -123,10 +123,10 @@ impl<'a> FmtVisitor<'a> { let list = write_list(&items[first_index..], &fmt); Some(if path_str.len() == 0 { - format!("{}use {{{}}};", vis, list) - } else { - format!("{}use {}::{{{}}};", vis, path_str, list) - }) + format!("{}use {{{}}};", vis, list) + } else { + format!("{}use {}::{{{}}};", vis, path_str, list) + }) } } diff --git a/src/lib.rs b/src/lib.rs index 5ea4812e144..7c36229e774 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,10 +49,9 @@ use changes::ChangeSet; use visitor::FmtVisitor; use config::Config; -#[macro_use] -mod config; #[macro_use] mod utils; +pub mod config; mod changes; mod visitor; mod items; diff --git a/tests/config/expr_visual_indent.toml b/tests/config/expr_visual_indent.toml new file mode 100644 index 00000000000..38a099e3bed --- /dev/null +++ b/tests/config/expr_visual_indent.toml @@ -0,0 +1,16 @@ +max_width = 100 +ideal_width = 80 +leeway = 5 +tab_spaces = 4 +newline_style = "Unix" +fn_brace_style = "SameLineWhere" +fn_return_indent = "WithArgs" +fn_args_paren_newline = true +struct_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" +struct_lit_trailing_comma = "Vertical" +enum_trailing_comma = true +report_todo = "Always" +report_fixme = "Never" +reorder_imports = false +expr_indent_style = "Visual" diff --git a/tests/config/reorder_imports.toml b/tests/config/reorder_imports.toml index ddab2479f2c..5b1ce49a2f2 100644 --- a/tests/config/reorder_imports.toml +++ b/tests/config/reorder_imports.toml @@ -13,3 +13,4 @@ enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = true +expr_indent_style = "Tabbed" diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 303433dbcc1..b2c7f5fc43f 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -13,3 +13,4 @@ enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = false +expr_indent_style = "Tabbed" diff --git a/tests/config/visual_struct_lits.toml b/tests/config/visual_struct_lits.toml index cf601303e9b..61bf4b0aee5 100644 --- a/tests/config/visual_struct_lits.toml +++ b/tests/config/visual_struct_lits.toml @@ -13,3 +13,4 @@ enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = false +expr_indent_style = "Tabbed" diff --git a/tests/source/expr-visual-indent.rs b/tests/source/expr-visual-indent.rs new file mode 100644 index 00000000000..c173d7bd7c4 --- /dev/null +++ b/tests/source/expr-visual-indent.rs @@ -0,0 +1,9 @@ +// rustfmt-config: expr_visual_indent.toml + +// Visual level block indentation. + +fn matcher() { + Some(while true { + test(); + }) +} \ No newline at end of file diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 19baa90ace2..1c063cf7f9d 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -14,6 +14,10 @@ some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))); + { for _ in 0..10 {} } + + {{{{}}}} + if 1 + 2 > 0 { let result = 5; result } else { 4}; if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { @@ -30,6 +34,10 @@ some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} + if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + + 2 + 3 { + } + if cond() { something(); } else if different_cond() { @@ -39,3 +47,19 @@ some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } } + +fn bar() { + let range = ( 111111111 + 333333333333333333 + 1111 + 400000000000000000) .. (2222 + 2333333333333333); + + let another_range = 5..some_func( a , b /* comment */); + + for _ in 1 ..{ call_forever(); } + + syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 }); + + let third = ..10; + let infi_range = ..; + let foo = 1..; + let bar = 5; + let nonsense = (10 .. 0)..(0..10); +} diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index f2726821e55..54f2ea5441b 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -22,6 +22,8 @@ fn main() { Foo { a:Bar, b:foo() }; + Quux { x: if cond { bar(); }, y: baz() }; + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. first: item(), @@ -37,3 +39,12 @@ fn main() { * o o o o */ graph: G, } } + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" bool { a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))); + { + for _ in 0..10 { + } + } + + { + { + { + { + } + } + } + } + if 1 + 2 > 0 { let result = 5; result @@ -39,6 +53,10 @@ fn foo() -> bool { 2222 { } + if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = + 1 + 2 + 3 { + } + if cond() { something(); } else if different_cond() { @@ -49,3 +67,29 @@ fn foo() -> bool { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } } + +fn bar() { + let range = (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + + 2333333333333333); + + let another_range = 5..some_func(a, b /* comment */); + + for _ in 1.. { + call_forever(); + } + + syntactically_correct(loop { + sup('?'); + }, + if cond { + 0 + } else { + 1 + }); + + let third = ..10; + let infi_range = ..; + let foo = 1..; + let bar = 5; + let nonsense = (10..0)..(0..10); +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 293a2a97b7a..9f7ab5cb428 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -29,9 +29,16 @@ fn main() { Foo { a: Bar, b: foo() }; + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed - // sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante // hendrerit. Donec et mollis dolor. first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. @@ -48,3 +55,12 @@ fn main() { graph: G, } } + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" Date: Fri, 24 Jul 2015 15:29:04 +0200 Subject: Use new module code from libsyntax --- src/comment.rs | 8 ++--- src/expr.rs | 6 ++-- src/visitor.rs | 94 ++++++++++++++++++++-------------------------------- tests/source/expr.rs | 2 ++ tests/target/expr.rs | 3 ++ 5 files changed, 49 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 7e4119880c3..5c042ddaf5e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -101,10 +101,10 @@ fn format_comments() { 12)); let input = "// comment"; - let expected_output = "/* com\n \ - * men\n \ - * t */"; - assert_eq!(expected_output, rewrite_comment(input, true, 9, 69)); + let expected = "/* com\n \ + * men\n * \ + t */"; + assert_eq!(expected, rewrite_comment(input, true, 9, 69)); assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); } diff --git a/src/expr.rs b/src/expr.rs index 0beaee9dbf2..9c651e1314a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -347,9 +347,11 @@ fn rewrite_binary_op(context: &RewriteContext, result.push(' '); result.push_str(&operator_str); + // 1 = space between operator and rhs + let used_width = result.len() + operator_str.len() + 1; let remaining_width = match result.rfind('\n') { - Some(idx) => (offset + width + idx).checked_sub(result.len()).unwrap_or(0), - None => width.checked_sub(result.len()).unwrap_or(0) + Some(idx) => (offset + width + idx).checked_sub(used_width).unwrap_or(0), + None => width.checked_sub(used_width).unwrap_or(0) }; // Get "full width" rhs and see if it fits on the current line. This diff --git a/src/visitor.rs b/src/visitor.rs index ae5b2083ccc..09592e9c8b2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,13 +11,11 @@ use syntax::ast; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; -use syntax::parse::token; -use syntax::attr; +use syntax::parse::{token, parser}; use std::path::PathBuf; use utils; use config::Config; -use comment::FindUncommented; use changes::ChangeSet; use rewrite::{Rewrite, RewriteContext}; @@ -363,68 +361,48 @@ impl<'a> FmtVisitor<'a> { fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast::Attribute]) { debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); + // Decide whether this is an inline mod or an external mod. - // There isn't any difference between inline and external mod in AST, - // so we use the trick of searching for an opening brace. - // We can't use the inner span of the mod since it is weird when it - // is empty (no items). - // FIXME Use the inner span once rust-lang/rust#26755 is fixed. - let open_brace = self.codemap.span_to_snippet(s).unwrap().find_uncommented("{"); - match open_brace { - None => { - debug!("FmtVisitor::format_mod: external mod"); - let file_path = self.module_file(ident, attrs, s); - let filename = file_path.to_str().unwrap(); - if self.changes.is_changed(filename) { - // The file has already been reformatted, do nothing - } else { - self.format_separate_mod(m, filename); - } - // TODO Should rewrite properly `mod X;` - } - Some(open_brace) => { - debug!("FmtVisitor::format_mod: internal mod"); - debug!("... open_brace: {}, str: {:?}", - open_brace, - self.codemap.span_to_snippet(s)); - // Format everything until opening brace - // TODO Shoud rewrite properly - self.format_missing(s.lo + BytePos(open_brace as u32)); - self.block_indent += self.config.tab_spaces; - visit::walk_mod(self, m); - debug!("... last_pos after: {:?}", self.last_pos); - self.block_indent -= self.config.tab_spaces; + let local_file_name = self.codemap.span_to_filename(s); + let is_internal = local_file_name == self.codemap.span_to_filename(m.inner); + + // TODO Should rewrite properly `mod X;` + + if is_internal { + debug!("FmtVisitor::format_mod: internal mod"); + self.block_indent += self.config.tab_spaces; + visit::walk_mod(self, m); + debug!("... last_pos after: {:?}", self.last_pos); + self.block_indent -= self.config.tab_spaces; + } else { + debug!("FmtVisitor::format_mod: external mod"); + let file_path = self.module_file(ident, attrs, local_file_name); + let filename = file_path.to_str().unwrap(); + if self.changes.is_changed(filename) { + // The file has already been reformatted, do nothing + } else { + self.format_separate_mod(m, filename); } } - self.format_missing(s.hi); + debug!("FmtVisitor::format_mod: exit"); } /// Find the file corresponding to an external mod - /// Same algorithm as syntax::parse::eval_src_mod - fn module_file(&self, id: ast::Ident, outer_attrs: &[ast::Attribute], id_sp: Span) -> PathBuf { - // FIXME use libsyntax once rust-lang/rust#26750 is merged - let mut prefix = PathBuf::from(&self.codemap.span_to_filename(id_sp)); - prefix.pop(); - let mod_string = token::get_ident(id); - match attr::first_attr_value_str_by_name(outer_attrs, "path") { - Some(d) => prefix.join(&*d), - None => { - let default_path_str = format!("{}.rs", mod_string); - let secondary_path_str = format!("{}/mod.rs", mod_string); - let default_path = prefix.join(&default_path_str); - let secondary_path = prefix.join(&secondary_path_str); - let default_exists = self.codemap.file_exists(&default_path); - let secondary_exists = self.codemap.file_exists(&secondary_path); - if default_exists { - default_path - } else if secondary_exists { - secondary_path - } else { - // Should never appens since rustc parsed everything sucessfully - panic!("Didn't found module {}", mod_string); - } - } + fn module_file(&self, id: ast::Ident, attrs: &[ast::Attribute], filename: String) -> PathBuf { + let dir_path = { + let mut path = PathBuf::from(&filename); + path.pop(); + path + }; + + if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &dir_path) { + return path; + } + + match parser::Parser::default_submod_path(id, &dir_path, &self.codemap).result { + Ok(parser::ModulePathSuccess { path, .. }) => path, + _ => panic!("Couldn't find module {}", token::get_ident(id)) } } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 373e42d67c5..5e30ed47a07 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -4,6 +4,8 @@ fn foo() -> bool { let very_long_variable_name = ( a + first + simple + test ); let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 25c84511c41..1296b297887 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -5,6 +5,9 @@ fn foo() -> bool { let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + let is_internalxxxx = self.codemap.span_to_filename(s) == + self.codemap.span_to_filename(m.inner); + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; -- cgit 1.4.1-3-g733a5 From ff301efa4e0f433dccaa9de920da19b5492e24e8 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sat, 25 Jul 2015 18:58:16 +0200 Subject: Fix width computation in rewrite_binary_op Operator width was counted twice. --- src/expr.rs | 2 +- tests/source/expr.rs | 1 + tests/target/expr.rs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1f92ed5d719..81cc2049081 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -608,7 +608,7 @@ fn rewrite_binary_op(context: &RewriteContext, result.push_str(&operator_str); // 1 = space between operator and rhs - let used_width = result.len() + operator_str.len() + 1; + let used_width = result.len() + 1; let remaining_width = match result.rfind('\n') { Some(idx) => (offset + width + idx).checked_sub(used_width).unwrap_or(0), None => width.checked_sub(used_width).unwrap_or(0) diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 74538c13597..9a69d68987f 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -7,6 +7,7 @@ fn foo() -> bool { let very_long_variable_name = ( a + first + simple + test ); let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + //FIXME this exceeds width limit. Needs assignments reformatting let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - diff --git a/tests/target/expr.rs b/tests/target/expr.rs index a52ad51b0c6..1ec5e0168fa 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -8,8 +8,8 @@ fn foo() -> bool { let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - let is_internalxxxx = self.codemap.span_to_filename(s) == - self.codemap.span_to_filename(m.inner); + //FIXME this exceeds width limit. Needs assignments reformatting + let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; -- cgit 1.4.1-3-g733a5 From 30b16bc47424f6aefcfbe7c2d9bb501262acbd24 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Fri, 17 Jul 2015 15:58:47 +0200 Subject: Move 'use' to Rewrite Implements Rewrite for ViewPath Behavior change: always use max_width instead of ideal_width for use list rewrite. I think it looks better, was also suggested by @nrc in https://github.com/nrc/rustfmt/issues/82#issuecomment-105314265 --- src/imports.rs | 205 ++++++++++++++++++++++++++--------------------- src/visitor.rs | 48 +++++------ tests/target/imports.rs | 4 +- tests/target/multiple.rs | 7 +- 4 files changed, 136 insertions(+), 128 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 12ce3368eb3..722c6a87012 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,126 +8,145 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use visitor::FmtVisitor; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; -use utils::{span_after, format_visibility}; +use utils::span_after; +use rewrite::{Rewrite, RewriteContext}; +use config::Config; use syntax::ast; use syntax::parse::token; use syntax::print::pprust; -use syntax::codemap::Span; +use syntax::codemap::{CodeMap, Span}; // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import -fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem, vis: &str) -> String { +impl Rewrite for ast::ViewPath { + // Returns an empty string when the ViewPath is empty (like foo::bar::{}) + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + match self.node { + ast::ViewPath_::ViewPathList(ref path, ref path_list) => { + Some(rewrite_use_list(width, + offset, + path, + path_list, + self.span, + context.codemap, + context.config).unwrap_or("".to_owned())) + } + ast::ViewPath_::ViewPathGlob(_) => { + // FIXME convert to list? + None + } + ast::ViewPath_::ViewPathSimple(_,_) => { + None + } + } + } +} + +fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { let name_str = token::get_ident(name).to_string(); if path_str.len() == 0 { - format!("{}use {};", vis, name_str) + name_str } else { - format!("{}use {}::{};", vis, path_str, name_str) + format!("{}::{}", path_str, name_str) } } else { if path_str.len() != 0 { - format!("{}use {};", vis, path_str) + path_str } else { // This catches the import: use {self}, which is a compiler error, so we just // leave it alone. - format!("{}use {{self}};", vis) + "{self}".to_owned() } } } -impl<'a> FmtVisitor<'a> { - // Basically just pretty prints a multi-item import. - // Returns None when the import can be removed. - pub fn rewrite_use_list(&self, - block_indent: usize, - one_line_budget: usize, // excluding indentation - multi_line_budget: usize, - path: &ast::Path, - path_list: &[ast::PathListItem], - visibility: ast::Visibility, - span: Span) - -> Option { - let path_str = pprust::path_to_string(path); - let vis = format_visibility(visibility); - - match path_list.len() { - 0 => return None, - 1 => return Some(rewrite_single_use_list(path_str, path_list[0], vis)), - _ => () - } - - // 2 = :: - let path_separation_w = if path_str.len() > 0 { - 2 - } else { - 0 - }; - // 5 = "use " + { - let indent = path_str.len() + 5 + path_separation_w + vis.len(); - - // 2 = } + ; - let used_width = indent + 2; +// Basically just pretty prints a multi-item import. +// Returns None when the import can be removed. +pub fn rewrite_use_list(width: usize, + offset: usize, + path: &ast::Path, + path_list: &[ast::PathListItem], + span: Span, + codemap: &CodeMap, + config: &Config) + -> Option { + let path_str = pprust::path_to_string(path); + + match path_list.len() { + 0 => return None, + 1 => return Some(rewrite_single_use_list(path_str, path_list[0])), + _ => () + } - // Break as early as possible when we've blown our budget. - let remaining_line_budget = one_line_budget.checked_sub(used_width).unwrap_or(0); - let remaining_multi_budget = multi_line_budget.checked_sub(used_width).unwrap_or(0); + // 2 = :: + let path_separation_w = if path_str.len() > 0 { + 2 + } else { + 0 + }; + // 1 = { + let supp_indent = path_str.len() + path_separation_w + 1; + // 1 = } + let remaining_width = width.checked_sub(supp_indent + 1).unwrap_or(0); + + let fmt = ListFormatting { + tactic: ListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset + supp_indent, + h_width: remaining_width, + // FIXME This is too conservative, and will not use all width + // available + // (loose 1 column (";")) + v_width: remaining_width, + ends_with_newline: true, + }; + + let mut items = itemize_list(codemap, + vec![ListItem::from_str("")], /* Dummy value, explanation + * below */ + path_list.iter(), + ",", + "}", + |vpi| vpi.span.lo, + |vpi| vpi.span.hi, + |vpi| match vpi.node { + ast::PathListItem_::PathListIdent{ name, .. } => { + token::get_ident(name).to_string() + } + ast::PathListItem_::PathListMod{ .. } => { + "self".to_owned() + } + }, + span_after(span, "{", codemap), + span.hi); + + // We prefixed the item list with a dummy value so that we can + // potentially move "self" to the front of the vector without touching + // the rest of the items. + // FIXME: Make more efficient by using a linked list? That would + // require changes to the signatures of itemize_list and write_list. + let has_self = move_self_to_front(&mut items); + let first_index = if has_self { + 0 + } else { + 1 + }; - let fmt = ListFormatting { - tactic: ListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: block_indent + indent, - h_width: remaining_line_budget, - v_width: remaining_multi_budget, - ends_with_newline: true, - }; + if config.reorder_imports { + items[1..].sort_by(|a, b| a.item.cmp(&b.item)); + } - let mut items = itemize_list(self.codemap, - vec![ListItem::from_str("")], /* Dummy value, explanation - * below */ - path_list.iter(), - ",", - "}", - |vpi| vpi.span.lo, - |vpi| vpi.span.hi, - |vpi| match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => { - token::get_ident(name).to_string() - } - ast::PathListItem_::PathListMod{ .. } => { - "self".to_owned() - } - }, - span_after(span, "{", self.codemap), - span.hi); + let list = write_list(&items[first_index..], &fmt); - // We prefixed the item list with a dummy value so that we can - // potentially move "self" to the front of the vector without touching - // the rest of the items. - // FIXME: Make more efficient by using a linked list? That would - // require changes to the signatures of itemize_list and write_list. - let has_self = move_self_to_front(&mut items); - let first_index = if has_self { - 0 + Some(if path_str.len() == 0 { + format!("{{{}}}", list) } else { - 1 - }; - - if self.config.reorder_imports { - items[1..].sort_by(|a, b| a.item.cmp(&b.item)); - } - - let list = write_list(&items[first_index..], &fmt); - - Some(if path_str.len() == 0 { - format!("{}use {{{}}};", vis, list) - } else { - format!("{}use {}::{{{}}};", vis, path_str, list) - }) - } + format!("{}::{{{}}}", path_str, list) + }) } // Returns true when self item was found. diff --git a/src/visitor.rs b/src/visitor.rs index 594d3328595..375107c00ea 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -164,39 +164,29 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match item.node { ast::Item_::ItemUse(ref vp) => { - match vp.node { - ast::ViewPath_::ViewPathList(ref path, ref path_list) => { - let block_indent = self.block_indent; - let one_line_budget = self.config.max_width - block_indent; - let multi_line_budget = self.config.ideal_width - block_indent; - let formatted = self.rewrite_use_list(block_indent, - one_line_budget, - multi_line_budget, - path, - path_list, - item.vis, - item.span); - - if let Some(new_str) = formatted { - self.format_missing_with_indent(item.span.lo); - self.changes.push_str_span(item.span, &new_str); - } else { - // Format up to last newline - let span = codemap::mk_sp(self.last_pos, item.span.lo); - let span_end = match self.snippet(span).rfind('\n') { - Some(offset) => self.last_pos + BytePos(offset as u32), - None => item.span.lo - }; - self.format_missing(span_end); - } - + let vis = utils::format_visibility(item.vis); + let offset = self.block_indent + vis.len() + "use ".len(); + let context = RewriteContext { + codemap: self.codemap, config: self.config, block_indent: self.block_indent }; + // 1 = ";" + match vp.rewrite(&context, self.config.max_width - offset - 1, offset) { + Some(ref s) if s.len() == 0 => { + // Format up to last newline + let span = codemap::mk_sp(self.last_pos, item.span.lo); + let span_end = match self.snippet(span).rfind('\n') { + Some(offset) => self.last_pos + BytePos(offset as u32), + None => item.span.lo + }; + self.format_missing(span_end); self.last_pos = item.span.hi; } - ast::ViewPath_::ViewPathGlob(_) => { + Some(ref s) => { + let s = format!("{}use {};", vis, s); self.format_missing_with_indent(item.span.lo); - // FIXME convert to list? + self.changes.push_str_span(item.span, &s); + self.last_pos = item.span.hi; } - ast::ViewPath_::ViewPathSimple(_,_) => { + None => { self.format_missing_with_indent(item.span.lo); } } diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 372b4f2051f..a799c096210 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -23,8 +23,8 @@ mod Foo { pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; mod Foo2 { - pub use syntax::ast::{self, ItemForeignMod, ItemImpl, ItemMac, ItemMod, - ItemStatic, ItemDefaultImpl}; + pub use syntax::ast::{self, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, + ItemDefaultImpl}; } } diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 0fb0c94e3a8..5573ea7e96e 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -14,10 +14,9 @@ extern crate foo; extern crate foo; use std::cell::*; -use std::{self, any, ascii, borrow, boxed, char, borrow, boxed, char, borrow, - borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, - borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, - borrow, boxed, char, borrow, boxed, char}; +use std::{self, any, ascii, borrow, boxed, char, borrow, boxed, char, borrow, borrow, boxed, char, + borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, + borrow, boxed, char, borrow, boxed, char, borrow, boxed, char}; mod doc; mod other; -- cgit 1.4.1-3-g733a5 From 5168d7458a6fc532a3fcb672246898d696867264 Mon Sep 17 00:00:00 2001 From: cassiersg Date: Mon, 20 Jul 2015 21:14:45 +0200 Subject: Indent fix --- src/imports.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 722c6a87012..37b1d9e5d46 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -26,12 +26,12 @@ impl Rewrite for ast::ViewPath { match self.node { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { Some(rewrite_use_list(width, - offset, - path, - path_list, - self.span, - context.codemap, - context.config).unwrap_or("".to_owned())) + offset, + path, + path_list, + self.span, + context.codemap, + context.config).unwrap_or("".to_owned())) } ast::ViewPath_::ViewPathGlob(_) => { // FIXME convert to list? -- cgit 1.4.1-3-g733a5 From 92b3f69934efb61433223fc10888746e0c705afe Mon Sep 17 00:00:00 2001 From: cassiersg Date: Mon, 20 Jul 2015 21:33:23 +0200 Subject: Add a helper method to format imports --- src/visitor.rs | 62 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 375107c00ea..6e550c2f330 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -164,33 +164,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match item.node { ast::Item_::ItemUse(ref vp) => { - let vis = utils::format_visibility(item.vis); - let offset = self.block_indent + vis.len() + "use ".len(); - let context = RewriteContext { - codemap: self.codemap, config: self.config, block_indent: self.block_indent }; - // 1 = ";" - match vp.rewrite(&context, self.config.max_width - offset - 1, offset) { - Some(ref s) if s.len() == 0 => { - // Format up to last newline - let span = codemap::mk_sp(self.last_pos, item.span.lo); - let span_end = match self.snippet(span).rfind('\n') { - Some(offset) => self.last_pos + BytePos(offset as u32), - None => item.span.lo - }; - self.format_missing(span_end); - self.last_pos = item.span.hi; - } - Some(ref s) => { - let s = format!("{}use {};", vis, s); - self.format_missing_with_indent(item.span.lo); - self.changes.push_str_span(item.span, &s); - self.last_pos = item.span.hi; - } - None => { - self.format_missing_with_indent(item.span.lo); - } - } - visit::walk_item(self, item); + self.format_import(item.vis, vp, item.span); } ast::Item_::ItemImpl(..) | ast::Item_::ItemTrait(..) => { @@ -211,7 +185,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { def, generics, item.span); - self.last_pos = item.span.hi; } ast::Item_::ItemEnum(ref def, ref generics) => { self.format_missing_with_indent(item.span.lo); @@ -408,4 +381,37 @@ impl<'a> FmtVisitor<'a> { self.last_pos = last_pos; self.block_indent = block_indent; } + + fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span) { + let vis = utils::format_visibility(vis); + let offset = self.block_indent + vis.len() + "use ".len(); + let context = RewriteContext { + codemap: self.codemap, + config: self.config, + block_indent: self.block_indent, + }; + // 1 = ";" + match vp.rewrite(&context, self.config.max_width - offset - 1, offset) { + Some(ref s) if s.len() == 0 => { + // Format up to last newline + let prev_span = codemap::mk_sp(self.last_pos, span.lo); + let span_end = match self.snippet(prev_span).rfind('\n') { + Some(offset) => self.last_pos + BytePos(offset as u32), + None => span.lo + }; + self.format_missing(span_end); + self.last_pos = span.hi; + } + Some(ref s) => { + let s = format!("{}use {};", vis, s); + self.format_missing_with_indent(span.lo); + self.changes.push_str_span(span, &s); + self.last_pos = span.hi; + } + None => { + self.format_missing_with_indent(span.lo); + self.format_missing(span.hi); + } + } + } } -- cgit 1.4.1-3-g733a5 From 397d0d3d72bf962fa37b1ed8457c5a42126c06b8 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 25 Jul 2015 23:10:48 +0200 Subject: Format simple imports --- src/imports.rs | 10 ++++++++-- tests/source/imports.rs | 5 +++++ tests/target/imports.rs | 5 +++++ 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 37b1d9e5d46..ec6a9f1e593 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -37,8 +37,14 @@ impl Rewrite for ast::ViewPath { // FIXME convert to list? None } - ast::ViewPath_::ViewPathSimple(_,_) => { - None + ast::ViewPath_::ViewPathSimple(ident, ref path) => { + let path_str = pprust::path_to_string(path); + + Some(if path.segments.last().unwrap().identifier == ident { + path_str + } else { + format!("{} as {}", path_str, ident) + }) } } } diff --git a/tests/source/imports.rs b/tests/source/imports.rs index 3590ecae61f..f759de3e7bb 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -39,3 +39,8 @@ fn test() { use Baz::*; use Qux; } + +// Simple imports +use foo::bar::baz as baz ; +use bar::quux as kaas; +use foo; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index a799c096210..bbef3e85e16 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -32,3 +32,8 @@ fn test() { use Baz::*; use Qux; } + +// Simple imports +use foo::bar::baz; +use bar::quux as kaas; +use foo; -- cgit 1.4.1-3-g733a5 From 54a96355ddfa222669ddad46e263d612a1530c8c Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 31 Jul 2015 13:06:28 +0200 Subject: Phase out token::get_ident in favour of ToString token::get_ident was removed in rust commit 00a5e66f818ad9d79cc4425f5564c7b07e3213a6 --- src/expr.rs | 3 +-- src/imports.rs | 8 +++----- src/items.rs | 6 +++--- src/types.rs | 3 +-- src/visitor.rs | 4 ++-- 5 files changed, 10 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 81cc2049081..930f19af453 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -18,7 +18,6 @@ use config::BlockIndentStyle; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos, mk_sp}; -use syntax::parse::token; use syntax::print::pprust; use syntax::visit::Visitor; @@ -539,7 +538,7 @@ fn rewrite_field(context: &RewriteContext, width: usize, offset: usize) -> Option { - let name = &token::get_ident(field.ident.node); + let name = &field.ident.node.to_string(); let overhead = name.len() + 2; let expr = field.expr.rewrite(context, width - overhead, offset + overhead); expr.map(|s| format!("{}: {}", name, s)) diff --git a/src/imports.rs b/src/imports.rs index ec6a9f1e593..958dfadff66 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -14,7 +14,6 @@ use rewrite::{Rewrite, RewriteContext}; use config::Config; use syntax::ast; -use syntax::parse::token; use syntax::print::pprust; use syntax::codemap::{CodeMap, Span}; @@ -52,11 +51,10 @@ impl Rewrite for ast::ViewPath { fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { - let name_str = token::get_ident(name).to_string(); if path_str.len() == 0 { - name_str + name.to_string() } else { - format!("{}::{}", path_str, name_str) + format!("{}::{}", path_str, name) } } else { if path_str.len() != 0 { @@ -121,7 +119,7 @@ pub fn rewrite_use_list(width: usize, |vpi| vpi.span.hi, |vpi| match vpi.node { ast::PathListItem_::PathListIdent{ name, .. } => { - token::get_ident(name).to_string() + name.to_string() } ast::PathListItem_::PathListMod{ .. } => { "self".to_owned() diff --git a/src/items.rs b/src/items.rs index 866dad65c85..eb727a20a56 100644 --- a/src/items.rs +++ b/src/items.rs @@ -124,7 +124,7 @@ impl<'a> FmtVisitor<'a> { // fn foo result.push_str("fn "); - result.push_str(&token::get_ident(ident)); + result.push_str(&ident.to_string()); // Generics. let generics_indent = indent + result.len(); @@ -626,7 +626,7 @@ impl<'a> FmtVisitor<'a> { } fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, &token::get_ident(ident)) + format!("{}{}{}", format_visibility(vis), item_name, ident) } fn format_generics(&self, @@ -658,7 +658,7 @@ impl<'a> FmtVisitor<'a> { } let name = match field.node.kind { - ast::StructFieldKind::NamedField(ident, _) => Some(token::get_ident(ident)), + ast::StructFieldKind::NamedField(ident, _) => Some(ident.to_string()), ast::StructFieldKind::UnnamedField(_) => None, }; let vis = match field.node.kind { diff --git a/src/types.rs b/src/types.rs index 474881b8ad2..c2e27c31684 100644 --- a/src/types.rs +++ b/src/types.rs @@ -11,7 +11,6 @@ use visitor::FmtVisitor; use syntax::ast; -use syntax::parse::token; use syntax::print::pprust; impl<'a> FmtVisitor<'a> { @@ -79,7 +78,7 @@ impl<'a> FmtVisitor<'a> { pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String { let mut result = String::with_capacity(128); - result.push_str(&token::get_ident(ty_param.ident)); + result.push_str(&ty_param.ident.to_string()); if ty_param.bounds.len() > 0 { result.push_str(": "); result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)) diff --git a/src/visitor.rs b/src/visitor.rs index 6e550c2f330..0f41b94ac4b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,7 +11,7 @@ use syntax::ast; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; -use syntax::parse::{token, parser}; +use syntax::parse::parser; use std::path::PathBuf; use utils; @@ -365,7 +365,7 @@ impl<'a> FmtVisitor<'a> { match parser::Parser::default_submod_path(id, &dir_path, &self.codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => path, - _ => panic!("Couldn't find module {}", token::get_ident(id)) + _ => panic!("Couldn't find module {}", id) } } -- cgit 1.4.1-3-g733a5 From 0f640b06ddac1ff6033fba2836f3ad0e71390db7 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 1 Aug 2015 14:22:31 +0200 Subject: Properly format unsafe blocks --- src/expr.rs | 31 ++++++++++++++++++++++++++++--- src/visitor.rs | 2 +- tests/source/expr.rs | 18 ++++++++++++++++++ tests/target/expr.rs | 19 +++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 930f19af453..b8c37dcab4c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -15,6 +15,7 @@ use StructLitStyle; use utils::{span_after, make_indent}; use visitor::FmtVisitor; use config::BlockIndentStyle; +use comment::{FindUncommented, rewrite_comment}; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos, mk_sp}; @@ -104,11 +105,35 @@ impl Rewrite for ast::Expr { } impl Rewrite for ast::Block { - fn rewrite(&self, context: &RewriteContext, _: usize, _: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config); - visitor.last_pos = self.span.lo; visitor.block_indent = context.block_indent; + let prefix = match self.rules { + ast::BlockCheckMode::PushUnsafeBlock(..) | + ast::BlockCheckMode::UnsafeBlock(..) => { + let snippet = try_opt!(context.codemap.span_to_snippet(self.span).ok()); + let open_pos = try_opt!(snippet.find_uncommented("{")); + visitor.last_pos = self.span.lo + BytePos(open_pos as u32); + + // Extract comment between unsafe and block start. + let trimmed = &snippet[6..open_pos].trim(); + + if trimmed.len() > 0 { + // 9 = "unsafe {".len(), 7 = "unsafe ".len() + format!("unsafe {} ", rewrite_comment(trimmed, true, width - 9, offset + 7)) + } else { + "unsafe ".to_owned() + } + } + ast::BlockCheckMode::PopUnsafeBlock(..) | + ast::BlockCheckMode::DefaultBlock => { + visitor.last_pos = self.span.lo; + + String::new() + } + }; + visitor.visit_block(self); // Push text between last block item and end of block @@ -119,7 +144,7 @@ impl Rewrite for ast::Block { let file_name = context.codemap.span_to_filename(self.span); let string_buffer = visitor.changes.get(&file_name); - Some(string_buffer.to_string()) + Some(format!("{}{}", prefix, string_buffer)) } } diff --git a/src/visitor.rs b/src/visitor.rs index 0f41b94ac4b..f4ccfdd5c25 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -73,7 +73,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { debug!("visit_block: {:?} {:?}", self.codemap.lookup_char_pos(b.span.lo), self.codemap.lookup_char_pos(b.span.hi)); - self.format_missing(b.span.lo); self.changes.push_str_span(b.span, "{"); self.last_pos = self.last_pos + BytePos(1); @@ -82,6 +81,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { for stmt in &b.stmts { self.visit_stmt(&stmt) } + match b.expr { Some(ref e) => { self.format_missing_with_indent(e.span.lo); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index bfa1edc5311..e7862b83e50 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -73,3 +73,21 @@ fn bar() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a); } + +fn baz() { + unsafe /* {}{}{}{{{{}} */ { + let foo = 1u32; + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} + + unsafe // So this is a very long comment. + // Multi-line, too. + // Will it still format correctly? + { + } + + unsafe { + // Regular unsafe block + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index b76bd408ac9..a1875a0ec26 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -102,3 +102,22 @@ fn bar() { let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, a); } + +fn baz() { + unsafe /* {}{}{}{{{{}} */ { + let foo = 1u32; + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + * comment */ { + } + + unsafe /* So this is a very long comment. + * Multi-line, too. + * Will it still format correctly? */ { + } + + unsafe { + // Regular unsafe block + } +} -- cgit 1.4.1-3-g733a5 From 0e10329dc74fac5a1579cf62989629ddca06117a Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 26 Jul 2015 12:55:25 +0200 Subject: Separate modules and files listing of reformatting As suggested in #141 Closes #156 --- src/changes.rs | 4 -- src/lib.rs | 6 ++- src/modules.rs | 73 ++++++++++++++++++++++++++++++++++ src/visitor.rs | 48 ++-------------------- tests/source/nestedmod/mod.rs | 1 + tests/source/nestedmod/mymod1/mod3a.rs | 2 + tests/target/nestedmod/mod.rs | 1 + tests/target/nestedmod/mymod1/mod3a.rs | 3 ++ 8 files changed, 87 insertions(+), 51 deletions(-) create mode 100644 src/modules.rs create mode 100644 tests/source/nestedmod/mymod1/mod3a.rs create mode 100644 tests/target/nestedmod/mymod1/mod3a.rs (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index ab5968dbf76..aba6eaa3250 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -216,10 +216,6 @@ impl<'a> ChangeSet<'a> { Ok(None) } - - pub fn is_changed(&self, filename: &str) -> bool { - self.file_map.get(filename).expect("Unknown filename").len != 0 - } } // Iterates over each file in the ChangSet. Yields the filename and the changed diff --git a/src/lib.rs b/src/lib.rs index 93b66f45b56..b52ba9b7217 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ use rustc_driver::{driver, CompilerCalls, Compilation}; use syntax::ast; use syntax::codemap::CodeMap; use syntax::diagnostics; -use syntax::visit; use std::path::PathBuf; use std::collections::HashMap; @@ -64,6 +63,7 @@ mod issues; mod rewrite; mod string; mod comment; +mod modules; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. @@ -198,7 +198,9 @@ impl fmt::Display for FormatReport { // Formatting which depends on the AST. fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> { let mut visitor = FmtVisitor::from_codemap(codemap, config); - visit::walk_crate(&mut visitor, krate); + for (path, module) in modules::list_modules(krate, codemap) { + visitor.format_separate_mod(module, path.to_str().unwrap()); + } visitor.changes } diff --git a/src/modules.rs b/src/modules.rs new file mode 100644 index 00000000000..04906c44e7a --- /dev/null +++ b/src/modules.rs @@ -0,0 +1,73 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use utils; + +use std::path::{Path, PathBuf}; +use std::collections::HashMap; + +use syntax::ast; +use syntax::codemap; +use syntax::parse::{parser, token}; + + +/// List all the files containing modules of a crate. +/// If a file is used twice in a crate, it appears only once. +pub fn list_modules<'a>(krate: &'a ast::Crate, + codemap: &codemap::CodeMap) + -> HashMap { + let mut result = HashMap::new(); + let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); + list_submodules(&krate.module, root_filename.parent().unwrap(), codemap, &mut result); + result.insert(root_filename, &krate.module); + result +} + +/// Recursively list all external modules included in a module. +fn list_submodules<'a>(module: &'a ast::Mod, + search_dir: &Path, + codemap: &codemap::CodeMap, + result: &mut HashMap) { + debug!("list_submodules: search_dir: {:?}", search_dir); + for item in module.items.iter() { + if let ast::ItemMod(ref sub_mod) = item.node { + if !utils::contains_skip(&item.attrs) { + let is_internal = codemap.span_to_filename(item.span) == + codemap.span_to_filename(sub_mod.inner); + let dir_path = if is_internal { + let dir: &str = &token::get_ident(item.ident); + search_dir.join(dir) + } else { + let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap); + let dir_path = mod_path.parent().unwrap().to_owned(); + result.insert(mod_path, sub_mod); + dir_path + }; + list_submodules(sub_mod, &dir_path, codemap, result); + } + } + } +} + +/// Find the file corresponding to an external mod +fn module_file(id: ast::Ident, + attrs: &[ast::Attribute], + dir_path: &Path, + codemap: &codemap::CodeMap) + -> PathBuf { + if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &dir_path) { + return path; + } + + match parser::Parser::default_submod_path(id, &dir_path, codemap).result { + Ok(parser::ModulePathSuccess { path, .. }) => path, + Err(_) => panic!("Couldn't find module {}", token::get_ident(id)) + } +} diff --git a/src/visitor.rs b/src/visitor.rs index f4ccfdd5c25..718a540fe94 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,8 +11,6 @@ use syntax::ast; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; -use syntax::parse::parser; -use std::path::PathBuf; use utils; use config::Config; @@ -197,7 +195,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemMod(ref module) => { self.format_missing_with_indent(item.span.lo); - self.format_mod(module, item.span, item.ident, &item.attrs); + self.format_mod(module, item.span, item.ident); } _ => { visit::walk_item(self, item); @@ -237,12 +235,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_mac(&mut self, mac: &'v ast::Mac) { visit::walk_mac(self, mac) } - - fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) { - // This is only called for the root module - let filename = self.codemap.span_to_filename(s); - self.format_separate_mod(m, &filename); - } } impl<'a> FmtVisitor<'a> { @@ -322,7 +314,7 @@ impl<'a> FmtVisitor<'a> { result } - fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast::Attribute]) { + fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); // Decide whether this is an inline mod or an external mod. @@ -337,49 +329,15 @@ impl<'a> FmtVisitor<'a> { visit::walk_mod(self, m); debug!("... last_pos after: {:?}", self.last_pos); self.block_indent -= self.config.tab_spaces; - } else { - debug!("FmtVisitor::format_mod: external mod"); - let file_path = self.module_file(ident, attrs, local_file_name); - let filename = file_path.to_str().unwrap(); - if self.changes.is_changed(filename) { - // The file has already been reformatted, do nothing - } else { - self.format_separate_mod(m, filename); - } - } - - debug!("FmtVisitor::format_mod: exit"); - } - - /// Find the file corresponding to an external mod - fn module_file(&self, id: ast::Ident, attrs: &[ast::Attribute], filename: String) -> PathBuf { - let dir_path = { - let mut path = PathBuf::from(&filename); - path.pop(); - path - }; - - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &dir_path) { - return path; - } - - match parser::Parser::default_submod_path(id, &dir_path, &self.codemap).result { - Ok(parser::ModulePathSuccess { path, .. }) => path, - _ => panic!("Couldn't find module {}", id) } } - /// Format the content of a module into a separate file - fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) { - let last_pos = self.last_pos; - let block_indent = self.block_indent; + pub fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) { let filemap = self.codemap.get_filemap(filename); self.last_pos = filemap.start_pos; self.block_indent = 0; visit::walk_mod(self, m); self.format_missing(filemap.end_pos); - self.last_pos = last_pos; - self.block_indent = block_indent; } fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span) { diff --git a/tests/source/nestedmod/mod.rs b/tests/source/nestedmod/mod.rs index 23dfa444257..d04e49570a4 100644 --- a/tests/source/nestedmod/mod.rs +++ b/tests/source/nestedmod/mod.rs @@ -4,6 +4,7 @@ mod mod2b; mod mymod1 { use mod2a::{Foo,Bar}; +mod mod3a; } #[path="mod2c.rs"] diff --git a/tests/source/nestedmod/mymod1/mod3a.rs b/tests/source/nestedmod/mymod1/mod3a.rs new file mode 100644 index 00000000000..f28bde5e56d --- /dev/null +++ b/tests/source/nestedmod/mymod1/mod3a.rs @@ -0,0 +1,2 @@ +// Another mod +fn a( ) { } diff --git a/tests/target/nestedmod/mod.rs b/tests/target/nestedmod/mod.rs index be22f6d4037..b3456bf0d0f 100644 --- a/tests/target/nestedmod/mod.rs +++ b/tests/target/nestedmod/mod.rs @@ -4,6 +4,7 @@ mod mod2b; mod mymod1 { use mod2a::{Foo, Bar}; + mod mod3a; } #[path="mod2c.rs"] diff --git a/tests/target/nestedmod/mymod1/mod3a.rs b/tests/target/nestedmod/mymod1/mod3a.rs new file mode 100644 index 00000000000..a6399f5565d --- /dev/null +++ b/tests/target/nestedmod/mymod1/mod3a.rs @@ -0,0 +1,3 @@ +// Another mod +fn a() { +} -- cgit 1.4.1-3-g733a5 From 0eab4bf4307914368e6c79d09bbbed0e2a7fcc58 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 26 Jul 2015 14:05:43 +0200 Subject: Remove ChangeSet of FmtVisitor --- src/changes.rs | 102 ++++++---------------------------------------------- src/expr.rs | 8 ++--- src/items.rs | 16 ++++----- src/lib.rs | 11 +++--- src/missed_spans.rs | 53 ++++++++++++--------------- src/modules.rs | 7 ++-- src/visitor.rs | 28 +++++++-------- 7 files changed, 67 insertions(+), 158 deletions(-) (limited to 'src') diff --git a/src/changes.rs b/src/changes.rs index aba6eaa3250..ab758f71d95 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -15,96 +15,23 @@ use strings::string_buffer::StringBuffer; use std::collections::HashMap; -use syntax::codemap::{CodeMap, Span, BytePos}; use std::fmt; use std::fs::File; use std::io::{Write, stdout}; use WriteMode; use NewlineStyle; use config::Config; -use utils::round_up_to_power_of_two; // This is basically a wrapper around a bunch of Ropes which makes it convenient // to work with libsyntax. It is badly named. -pub struct ChangeSet<'a> { - file_map: HashMap, - codemap: &'a CodeMap, - file_spans: Vec<(u32, u32)>, +pub struct ChangeSet { + pub file_map: HashMap, } -impl<'a> ChangeSet<'a> { +impl ChangeSet { // Create a new ChangeSet for a given libsyntax CodeMap. - pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> { - let mut result = ChangeSet { - file_map: HashMap::new(), - codemap: codemap, - file_spans: Vec::with_capacity(codemap.files.borrow().len()), - }; - - for f in codemap.files.borrow().iter() { - // Use the length of the file as a heuristic for how much space we - // need. Round to the next power of two. - let buffer_cap = round_up_to_power_of_two(f.src.as_ref().unwrap().len()); - - result.file_map.insert(f.name.clone(), StringBuffer::with_capacity(buffer_cap)); - result.file_spans.push((f.start_pos.0, f.end_pos.0)); - } - - result.file_spans.sort(); - - result - } - - pub fn filespans_for_span(&self, start: BytePos, end: BytePos) -> Vec<(u32, u32)> { - assert!(start.0 <= end.0); - - if self.file_spans.len() == 0 { - return Vec::new(); - } - - // idx is the index into file_spans which indicates the current file, we - // with the file start denotes. - let mut idx = match self.file_spans.binary_search(&(start.0, ::std::u32::MAX)) { - Ok(i) => i, - Err(0) => 0, - Err(i) => i - 1, - }; - - let mut result = Vec::new(); - let mut start = start.0; - loop { - let cur_file = &self.file_spans[idx]; - idx += 1; - - if idx >= self.file_spans.len() || start >= end.0 { - if start < end.0 { - result.push((start, end.0)); - } - return result; - } - - let end = ::std::cmp::min(cur_file.1 - 1, end.0); - if start < end { - result.push((start, end)); - } - start = self.file_spans[idx].0; - } - } - - pub fn push_str(&mut self, filename: &str, text: &str) { - let buf = self.file_map.get_mut(&*filename).unwrap(); - buf.push_str(text) - } - - pub fn push_str_span(&mut self, span: Span, text: &str) { - let file_name = self.codemap.span_to_filename(span); - self.push_str(&file_name, text) - } - - // Fetch the output buffer for the given file name. - // Panics on unknown files. - pub fn get(&mut self, file_name: &str) -> &StringBuffer { - self.file_map.get(file_name).unwrap() + pub fn new() -> ChangeSet { + ChangeSet { file_map: HashMap::new() } } // Fetch a mutable reference to the output buffer for the given file name. @@ -113,17 +40,8 @@ impl<'a> ChangeSet<'a> { self.file_map.get_mut(file_name).unwrap() } - pub fn cur_offset(&mut self, filename: &str) -> usize { - self.file_map[&*filename].cur_offset() - } - - pub fn cur_offset_span(&mut self, span: Span) -> usize { - let filename = self.codemap.span_to_filename(span); - self.cur_offset(&filename) - } - // Return an iterator over the entire changed text. - pub fn text<'c>(&'c self) -> FileIterator<'c, 'a> { + pub fn text<'c>(&'c self) -> FileIterator<'c> { FileIterator { change_set: self, keys: self.file_map.keys().collect(), cur_key: 0 } } @@ -220,13 +138,13 @@ impl<'a> ChangeSet<'a> { // Iterates over each file in the ChangSet. Yields the filename and the changed // text for that file. -pub struct FileIterator<'c, 'a: 'c> { - change_set: &'c ChangeSet<'a>, +pub struct FileIterator<'c> { + change_set: &'c ChangeSet, keys: Vec<&'c String>, cur_key: usize, } -impl<'c, 'a> Iterator for FileIterator<'c, 'a> { +impl<'c> Iterator for FileIterator<'c> { type Item = (&'c str, &'c StringBuffer); fn next(&mut self) -> Option<(&'c str, &'c StringBuffer)> { @@ -240,7 +158,7 @@ impl<'c, 'a> Iterator for FileIterator<'c, 'a> { } } -impl<'a> fmt::Display for ChangeSet<'a> { +impl fmt::Display for ChangeSet { // Prints the entire changed text. fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { for (f, r) in self.text() { diff --git a/src/expr.rs b/src/expr.rs index b8c37dcab4c..334c509c59d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -138,13 +138,9 @@ impl Rewrite for ast::Block { // Push text between last block item and end of block let snippet = visitor.snippet(mk_sp(visitor.last_pos, self.span.hi)); - visitor.changes.push_str_span(self.span, &snippet); + visitor.buffer.push_str(&snippet); - // Stringify visitor - let file_name = context.codemap.span_to_filename(self.span); - let string_buffer = visitor.changes.get(&file_name); - - Some(format!("{}{}", prefix, string_buffer)) + Some(format!("{}{}", prefix, visitor.buffer)) } } diff --git a/src/items.rs b/src/items.rs index eb727a20a56..378d822d413 100644 --- a/src/items.rs +++ b/src/items.rs @@ -382,7 +382,7 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span) { let header_str = self.format_header("enum ", ident, vis); - self.changes.push_str_span(span, &header_str); + self.buffer.push_str(&header_str); let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); @@ -391,7 +391,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent + self.config.tab_spaces, codemap::mk_sp(span.lo, body_start)); - self.changes.push_str_span(span, &generics_str); + self.buffer.push_str(&generics_str); self.last_pos = body_start; self.block_indent += self.config.tab_spaces; @@ -407,7 +407,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent -= self.config.tab_spaces; self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32)); - self.changes.push_str_span(span, "}"); + self.buffer.push_str("}"); } // Variant of an enum @@ -421,9 +421,9 @@ impl<'a> FmtVisitor<'a> { let result = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { let vis = format_visibility(field.node.vis); - self.changes.push_str_span(field.span, vis); + self.buffer.push_str(vis); let name = field.node.name.to_string(); - self.changes.push_str_span(field.span, &name); + self.buffer.push_str(&name); let mut result = String::new(); @@ -491,10 +491,10 @@ impl<'a> FmtVisitor<'a> { self.block_indent) } }; - self.changes.push_str_span(field.span, &result); + self.buffer.push_str(&result); if !last_field || self.config.enum_trailing_comma { - self.changes.push_str_span(field.span, ","); + self.buffer.push_str(","); } self.last_pos = field.span.hi + BytePos(1); @@ -621,7 +621,7 @@ impl<'a> FmtVisitor<'a> { Some(generics), span, indent); - self.changes.push_str_span(span, &result); + self.buffer.push_str(&result); self.last_pos = span.hi; } diff --git a/src/lib.rs b/src/lib.rs index b52ba9b7217..f25e323504e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -196,12 +196,15 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> { - let mut visitor = FmtVisitor::from_codemap(codemap, config); +fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> ChangeSet { + let mut changes = ChangeSet::new(); for (path, module) in modules::list_modules(krate, codemap) { - visitor.format_separate_mod(module, path.to_str().unwrap()); + let path = path.to_str().unwrap(); + let mut visitor = FmtVisitor::from_codemap(codemap, config); + visitor.format_separate_mod(module, path); + changes.file_map.insert(path.to_owned(), visitor.buffer); } - visitor.changes + changes } // Formatting done on a char by char or line by line basis. diff --git a/src/missed_spans.rs b/src/missed_spans.rs index d560b3f2027..2f1a014a6e8 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -17,34 +17,33 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, file_name, _| { - this.changes.push_str(file_name, last_snippet) + self.format_missing_inner(end, |this, last_snippet, _| { + this.buffer.push_str(last_snippet) }) } pub fn format_missing_with_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, file_name, snippet| { - this.changes.push_str(file_name, last_snippet.trim_right()); + self.format_missing_inner(end, |this, last_snippet, snippet| { + this.buffer.push_str(last_snippet.trim_right()); if last_snippet == snippet { // No new lines in the snippet. - this.changes.push_str(file_name, "\n"); + this.buffer.push_str("\n"); } let indent = make_indent(this.block_indent); - this.changes.push_str(file_name, &indent); + this.buffer.push_str(&indent); }) } - fn format_missing_inner(&mut self, - end: BytePos, - process_last_snippet: F) { + fn format_missing_inner(&mut self, + end: BytePos, + process_last_snippet: F) { let start = self.last_pos; debug!("format_missing_inner: {:?} to {:?}", self.codemap.lookup_char_pos(start), self.codemap.lookup_char_pos(end)); if start == end { - let file_name = &self.codemap.lookup_char_pos(start).file.name; - process_last_snippet(self, "", file_name, ""); + process_last_snippet(self, "", ""); return; } @@ -54,24 +53,18 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(end)); self.last_pos = end; - let spans = self.changes.filespans_for_span(start, end); - for (i, &(start, end)) in spans.iter().enumerate() { - let span = codemap::mk_sp(BytePos(start), BytePos(end)); - let file_name = &self.codemap.span_to_filename(span); - let snippet = self.snippet(span); + let span = codemap::mk_sp(start, end); + let snippet = self.snippet(span); - self.write_snippet(&snippet, - file_name, - i == spans.len() - 1, + self.write_snippet(&snippet, + true, &process_last_snippet); - } } - fn write_snippet(&mut self, - snippet: &str, - file_name: &str, - last_snippet: bool, - process_last_snippet: F) { + fn write_snippet(&mut self, + snippet: &str, + last_snippet: bool, + process_last_snippet: F) { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. @@ -80,10 +73,10 @@ impl<'a> FmtVisitor<'a> { for (i, c) in snippet.char_indices() { if c == '\n' { if let Some(lw) = last_wspace { - self.changes.push_str(file_name, &snippet[line_start..lw]); - self.changes.push_str(file_name, "\n"); + self.buffer.push_str(&snippet[line_start..lw]); + self.buffer.push_str("\n"); } else { - self.changes.push_str(file_name, &snippet[line_start..i+1]); + self.buffer.push_str(&snippet[line_start..i+1]); } line_start = i + 1; @@ -99,9 +92,9 @@ impl<'a> FmtVisitor<'a> { } } if last_snippet { - process_last_snippet(self, &snippet[line_start..], file_name, snippet); + process_last_snippet(self, &snippet[line_start..], snippet); } else { - self.changes.push_str(file_name, &snippet[line_start..]); + self.buffer.push_str(&snippet[line_start..]); } } } diff --git a/src/modules.rs b/src/modules.rs index 04906c44e7a..6b3c223a4ff 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -15,7 +15,7 @@ use std::collections::HashMap; use syntax::ast; use syntax::codemap; -use syntax::parse::{parser, token}; +use syntax::parse::parser; /// List all the files containing modules of a crate. @@ -42,8 +42,7 @@ fn list_submodules<'a>(module: &'a ast::Mod, let is_internal = codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); let dir_path = if is_internal { - let dir: &str = &token::get_ident(item.ident); - search_dir.join(dir) + search_dir.join(&item.ident.to_string()) } else { let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap); let dir_path = mod_path.parent().unwrap().to_owned(); @@ -68,6 +67,6 @@ fn module_file(id: ast::Ident, match parser::Parser::default_submod_path(id, &dir_path, codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => path, - Err(_) => panic!("Couldn't find module {}", token::get_ident(id)) + Err(_) => panic!("Couldn't find module {}", id) } } diff --git a/src/visitor.rs b/src/visitor.rs index 718a540fe94..23908edf8d0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -12,15 +12,15 @@ use syntax::ast; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::visit; +use strings::string_buffer::StringBuffer; + use utils; use config::Config; - -use changes::ChangeSet; use rewrite::{Rewrite, RewriteContext}; pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, - pub changes: ChangeSet<'a>, + pub buffer: StringBuffer, pub last_pos: BytePos, // TODO RAII util for indenting pub block_indent: usize, @@ -33,7 +33,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.lo), self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); - let offset = self.changes.cur_offset_span(ex.span); + let offset = self.buffer.cur_offset(); let context = RewriteContext { codemap: self.codemap, config: self.config, @@ -42,7 +42,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { let rewrite = ex.rewrite(&context, self.config.max_width - offset, offset); if let Some(new_str) = rewrite { - self.changes.push_str_span(ex.span, &new_str); + self.buffer.push_str(&new_str); self.last_pos = ex.span.hi; } } @@ -72,7 +72,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(b.span.lo), self.codemap.lookup_char_pos(b.span.hi)); - self.changes.push_str_span(b.span, "{"); + self.buffer.push_str("{"); self.last_pos = self.last_pos + BytePos(1); self.block_indent += self.config.tab_spaces; @@ -91,7 +91,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent -= self.config.tab_spaces; // TODO we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - BytePos(1)); - self.changes.push_str_span(b.span, "}"); + self.buffer.push_str("}"); self.last_pos = b.span.hi; } @@ -124,7 +124,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { abi, vis, codemap::mk_sp(s.lo, b.span.lo)); - self.changes.push_str_span(s, &new_fn); + self.buffer.push_str(&new_fn); } visit::FkMethod(ident, ref sig, vis) => { let new_fn = self.rewrite_fn(indent, @@ -137,7 +137,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &sig.abi, vis.unwrap_or(ast::Visibility::Inherited), codemap::mk_sp(s.lo, b.span.lo)); - self.changes.push_str_span(s, &new_fn); + self.buffer.push_str(&new_fn); } visit::FkFnBlock(..) => {} } @@ -173,7 +173,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { ast::Item_::ItemExternCrate(_) => { self.format_missing_with_indent(item.span.lo); let new_str = self.snippet(item.span); - self.changes.push_str_span(item.span, &new_str); + self.buffer.push_str(&new_str); self.last_pos = item.span.hi; } ast::Item_::ItemStruct(ref def, ref generics) => { @@ -217,7 +217,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { sig, ti.span); - self.changes.push_str_span(ti.span, &new_fn); + self.buffer.push_str(&new_fn); self.last_pos = ti.span.hi; } // TODO format trait types @@ -241,7 +241,7 @@ impl<'a> FmtVisitor<'a> { pub fn from_codemap<'b>(codemap: &'b CodeMap, config: &'b Config) -> FmtVisitor<'b> { FmtVisitor { codemap: codemap, - changes: ChangeSet::from_codemap(codemap), + buffer: StringBuffer::new(), last_pos: BytePos(0), block_indent: 0, config: config, @@ -273,7 +273,7 @@ impl<'a> FmtVisitor<'a> { true } else { let rewrite = self.rewrite_attrs(attrs, self.block_indent); - self.changes.push_str_span(first.span, &rewrite); + self.buffer.push_str(&rewrite); let last = attrs.last().unwrap(); self.last_pos = last.span.hi; false @@ -363,7 +363,7 @@ impl<'a> FmtVisitor<'a> { Some(ref s) => { let s = format!("{}use {};", vis, s); self.format_missing_with_indent(span.lo); - self.changes.push_str_span(span, &s); + self.buffer.push_str(&s); self.last_pos = span.hi; } None => { -- cgit 1.4.1-3-g733a5 From 5b5927996f9c78e16d75235d5953d072757c8bae Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sat, 1 Aug 2015 15:02:59 +0200 Subject: Kill ChangeSet and replace remaining part by FileMap Also fix style issues Cargo update to get fixes of strings.rs (was cause of a misformatted function call). --- Cargo.lock | 22 +++---- src/changes.rs | 170 ---------------------------------------------------- src/filemap.rs | 113 ++++++++++++++++++++++++++++++++++ src/lib.rs | 30 +++++----- src/missed_spans.rs | 4 +- src/modules.rs | 6 +- 6 files changed, 144 insertions(+), 201 deletions(-) delete mode 100644 src/changes.rs create mode 100644 src/filemap.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 97593cfad4c..82dbafd47d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,16 +2,16 @@ name = "rustfmt" version = "0.0.1" dependencies = [ - "diff 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "diff 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", - "toml 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -19,7 +19,7 @@ dependencies = [ [[package]] name = "diff" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -37,17 +37,17 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.38" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -58,11 +58,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strings" version = "0.0.1" -source = "git+https://github.com/nrc/strings.rs.git#b7f37c4545b7dba24fb28161cd9c405fae978be4" +source = "git+https://github.com/nrc/strings.rs.git#6d748148fbe3bf2d9e5ac2ede65ac503d7491a4f" [[package]] name = "toml" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/changes.rs b/src/changes.rs deleted file mode 100644 index ab758f71d95..00000000000 --- a/src/changes.rs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -// TODO -// print to files -// tests - -use strings::string_buffer::StringBuffer; -use std::collections::HashMap; -use std::fmt; -use std::fs::File; -use std::io::{Write, stdout}; -use WriteMode; -use NewlineStyle; -use config::Config; - -// This is basically a wrapper around a bunch of Ropes which makes it convenient -// to work with libsyntax. It is badly named. -pub struct ChangeSet { - pub file_map: HashMap, -} - -impl ChangeSet { - // Create a new ChangeSet for a given libsyntax CodeMap. - pub fn new() -> ChangeSet { - ChangeSet { file_map: HashMap::new() } - } - - // Fetch a mutable reference to the output buffer for the given file name. - // Panics on unknown files. - pub fn get_mut(&mut self, file_name: &str) -> &mut StringBuffer { - self.file_map.get_mut(file_name).unwrap() - } - - // Return an iterator over the entire changed text. - pub fn text<'c>(&'c self) -> FileIterator<'c> { - FileIterator { change_set: self, keys: self.file_map.keys().collect(), cur_key: 0 } - } - - // Append a newline to the end of each file. - pub fn append_newlines(&mut self) { - for (_, s) in self.file_map.iter_mut() { - s.push_str("\n"); - } - } - - pub fn write_all_files(&self, - mode: WriteMode, - config: &Config) - -> Result<(HashMap), ::std::io::Error> { - let mut result = HashMap::new(); - for filename in self.file_map.keys() { - let one_result = try!(self.write_file(filename, mode, config)); - if let Some(r) = one_result { - result.insert(filename.clone(), r); - } - } - - Ok(result) - } - - pub fn write_file(&self, - filename: &str, - mode: WriteMode, - config: &Config) - -> Result, ::std::io::Error> { - let text = &self.file_map[filename]; - - // prints all newlines either as `\n` or as `\r\n` - fn write_system_newlines(mut writer: T, - text: &StringBuffer, - config: &Config) - -> Result<(), ::std::io::Error> - where T: Write - { - match config.newline_style { - NewlineStyle::Unix => write!(writer, "{}", text), - NewlineStyle::Windows => { - for (c, _) in text.chars() { - match c { - '\n' => try!(write!(writer, "\r\n")), - '\r' => continue, - c => try!(write!(writer, "{}", c)), - } - } - Ok(()) - }, - } - } - - match mode { - WriteMode::Overwrite => { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.to_owned() + ".tmp"; - let bk_name = filename.to_owned() + ".bk"; - { - // Write text to temp file - let tmp_file = try!(File::create(&tmp_name)); - try!(write_system_newlines(tmp_file, text, config)); - } - - try!(::std::fs::rename(filename, bk_name)); - try!(::std::fs::rename(tmp_name, filename)); - } - WriteMode::NewFile(extn) => { - let filename = filename.to_owned() + "." + extn; - let file = try!(File::create(&filename)); - try!(write_system_newlines(file, text, config)); - } - WriteMode::Display => { - println!("{}:\n", filename); - let stdout = stdout(); - let stdout_lock = stdout.lock(); - try!(write_system_newlines(stdout_lock, text, config)); - } - WriteMode::Return(_) => { - // io::Write is not implemented for String, working around with Vec - let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); - // won't panic, we are writing correct utf8 - return Ok(Some(String::from_utf8(v).unwrap())); - } - } - - Ok(None) - } -} - -// Iterates over each file in the ChangSet. Yields the filename and the changed -// text for that file. -pub struct FileIterator<'c> { - change_set: &'c ChangeSet, - keys: Vec<&'c String>, - cur_key: usize, -} - -impl<'c> Iterator for FileIterator<'c> { - type Item = (&'c str, &'c StringBuffer); - - fn next(&mut self) -> Option<(&'c str, &'c StringBuffer)> { - if self.cur_key >= self.keys.len() { - return None; - } - - let key = self.keys[self.cur_key]; - self.cur_key += 1; - return Some((&key, &self.change_set.file_map[&*key])) - } -} - -impl fmt::Display for ChangeSet { - // Prints the entire changed text. - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - for (f, r) in self.text() { - try!(write!(fmt, "{}:\n", f)); - try!(write!(fmt, "{}\n\n", r)); - } - Ok(()) - } -} diff --git a/src/filemap.rs b/src/filemap.rs new file mode 100644 index 00000000000..750bea9b862 --- /dev/null +++ b/src/filemap.rs @@ -0,0 +1,113 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// TODO tests + +use strings::string_buffer::StringBuffer; +use std::collections::HashMap; +use std::fs::File; +use std::io::{Write, stdout}; +use WriteMode; +use NewlineStyle; +use config::Config; + +// A map of the files of a crate, with their new content +pub type FileMap = HashMap; + +// Append a newline to the end of each file. +pub fn append_newlines(file_map: &mut FileMap) { + for (_, s) in file_map.iter_mut() { + s.push_str("\n"); + } +} + +pub fn write_all_files(file_map: &FileMap, + mode: WriteMode, + config: &Config) + -> Result<(HashMap), ::std::io::Error> { + let mut result = HashMap::new(); + for filename in file_map.keys() { + let one_result = try!(write_file(file_map, filename, mode, config)); + if let Some(r) = one_result { + result.insert(filename.clone(), r); + } + } + + Ok(result) +} + +fn write_file(file_map: &FileMap, + filename: &str, + mode: WriteMode, + config: &Config) + -> Result, ::std::io::Error> { + let text = &file_map[filename]; + + // prints all newlines either as `\n` or as `\r\n` + fn write_system_newlines(mut writer: T, + text: &StringBuffer, + config: &Config) + -> Result<(), ::std::io::Error> + where T: Write + { + match config.newline_style { + NewlineStyle::Unix => write!(writer, "{}", text), + NewlineStyle::Windows => { + for (c, _) in text.chars() { + match c { + '\n' => try!(write!(writer, "\r\n")), + '\r' => continue, + c => try!(write!(writer, "{}", c)), + } + } + Ok(()) + }, + } + } + + match mode { + WriteMode::Overwrite => { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.to_owned() + ".tmp"; + let bk_name = filename.to_owned() + ".bk"; + { + // Write text to temp file + let tmp_file = try!(File::create(&tmp_name)); + try!(write_system_newlines(tmp_file, text, config)); + } + + try!(::std::fs::rename(filename, bk_name)); + try!(::std::fs::rename(tmp_name, filename)); + } + WriteMode::NewFile(extn) => { + let filename = filename.to_owned() + "." + extn; + let file = try!(File::create(&filename)); + try!(write_system_newlines(file, text, config)); + } + WriteMode::Display => { + println!("{}:\n", filename); + let stdout = stdout(); + let stdout_lock = stdout.lock(); + try!(write_system_newlines(stdout_lock, text, config)); + } + WriteMode::Return(_) => { + // io::Write is not implemented for String, working around with Vec + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text, config)); + // won't panic, we are writing correct utf8 + return Ok(Some(String::from_utf8(v).unwrap())); + } + } + + Ok(None) +} diff --git a/src/lib.rs b/src/lib.rs index f25e323504e..c0aff9a05b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,14 +44,14 @@ use std::fmt; use std::mem::swap; use issues::{BadIssueSeeker, Issue}; -use changes::ChangeSet; +use filemap::FileMap; use visitor::FmtVisitor; use config::Config; #[macro_use] mod utils; pub mod config; -mod changes; +mod filemap; mod visitor; mod items; mod missed_spans; @@ -196,26 +196,26 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> ChangeSet { - let mut changes = ChangeSet::new(); - for (path, module) in modules::list_modules(krate, codemap) { +fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> FileMap { + let mut file_map = FileMap::new(); + for (path, module) in modules::list_files(krate, codemap) { let path = path.to_str().unwrap(); let mut visitor = FmtVisitor::from_codemap(codemap, config); visitor.format_separate_mod(module, path); - changes.file_map.insert(path.to_owned(), visitor.buffer); + file_map.insert(path.to_owned(), visitor.buffer); } - changes + file_map } // Formatting done on a char by char or line by line basis. // TODO warn on bad license // TODO other stuff for parity with make tidy -fn fmt_lines(changes: &mut ChangeSet, config: &Config) -> FormatReport { +fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; - // Iterate over the chars in the change set. - for (f, text) in changes.text() { + // Iterate over the chars in the file map. + for (f, text) in file_map.iter() { let mut trims = vec![]; let mut last_wspace: Option = None; let mut line_len = 0; @@ -283,7 +283,7 @@ fn fmt_lines(changes: &mut ChangeSet, config: &Config) -> FormatReport { } for (f, l) in truncate_todo { - changes.get_mut(&f).truncate(l); + file_map.get_mut(&f).unwrap().truncate(l); } report @@ -317,13 +317,13 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { control.after_parse.callback = Box::new(move |state| { let krate = state.krate.unwrap(); let codemap = state.session.codemap(); - let mut changes = fmt_ast(krate, codemap, &*config); + let mut file_map = fmt_ast(krate, codemap, &*config); // For some reason, the codemap does not include terminating newlines // so we must add one on for each file. This is sad. - changes.append_newlines(); - println!("{}", fmt_lines(&mut changes, &*config)); + filemap::append_newlines(&mut file_map); + println!("{}", fmt_lines(&mut file_map, &*config)); - let result = changes.write_all_files(write_mode, &*config); + let result = filemap::write_all_files(&file_map, write_mode, &*config); match result { Err(msg) => println!("Error writing files: {}", msg), diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2f1a014a6e8..64025550410 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -57,8 +57,8 @@ impl<'a> FmtVisitor<'a> { let snippet = self.snippet(span); self.write_snippet(&snippet, - true, - &process_last_snippet); + true, + &process_last_snippet); } fn write_snippet(&mut self, diff --git a/src/modules.rs b/src/modules.rs index 6b3c223a4ff..2f40fd33a55 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -20,9 +20,9 @@ use syntax::parse::parser; /// List all the files containing modules of a crate. /// If a file is used twice in a crate, it appears only once. -pub fn list_modules<'a>(krate: &'a ast::Crate, - codemap: &codemap::CodeMap) - -> HashMap { +pub fn list_files<'a>(krate: &'a ast::Crate, + codemap: &codemap::CodeMap) + -> HashMap { let mut result = HashMap::new(); let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); list_submodules(&krate.module, root_filename.parent().unwrap(), codemap, &mut result); -- cgit 1.4.1-3-g733a5 From 5a29d2f08153d8132e63f2e41424b063fe3d8be0 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 2 Aug 2015 14:49:35 +0200 Subject: Fix nits for filemap --- src/filemap.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 750bea9b862..8e09837df0a 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -13,8 +13,8 @@ use strings::string_buffer::StringBuffer; use std::collections::HashMap; -use std::fs::File; -use std::io::{Write, stdout}; +use std::fs::{self, File}; +use std::io::{self, Write, stdout}; use WriteMode; use NewlineStyle; use config::Config; @@ -32,10 +32,10 @@ pub fn append_newlines(file_map: &mut FileMap) { pub fn write_all_files(file_map: &FileMap, mode: WriteMode, config: &Config) - -> Result<(HashMap), ::std::io::Error> { + -> Result<(HashMap), io::Error> { let mut result = HashMap::new(); for filename in file_map.keys() { - let one_result = try!(write_file(file_map, filename, mode, config)); + let one_result = try!(write_file(&file_map[filename], filename, mode, config)); if let Some(r) = one_result { result.insert(filename.clone(), r); } @@ -44,18 +44,17 @@ pub fn write_all_files(file_map: &FileMap, Ok(result) } -fn write_file(file_map: &FileMap, +fn write_file(text: &StringBuffer, filename: &str, mode: WriteMode, config: &Config) - -> Result, ::std::io::Error> { - let text = &file_map[filename]; + -> Result, io::Error> { - // prints all newlines either as `\n` or as `\r\n` + // prints all newlines either as `\n` or as `\r\n` fn write_system_newlines(mut writer: T, text: &StringBuffer, config: &Config) - -> Result<(), ::std::io::Error> + -> Result<(), io::Error> where T: Write { match config.newline_style { @@ -86,8 +85,8 @@ fn write_file(file_map: &FileMap, try!(write_system_newlines(tmp_file, text, config)); } - try!(::std::fs::rename(filename, bk_name)); - try!(::std::fs::rename(tmp_name, filename)); + try!(fs::rename(filename, bk_name)); + try!(fs::rename(tmp_name, filename)); } WriteMode::NewFile(extn) => { let filename = filename.to_owned() + "." + extn; -- cgit 1.4.1-3-g733a5 From 82b27fc4ab604f71e87accc0c7dc8fb6f30e19eb Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 24 Jul 2015 19:54:38 +0200 Subject: Correctly format typed self in function arguments --- src/items.rs | 82 +++++++++++++++++++++++++-------------------------- src/utils.rs | 8 +++++ tests/target/trait.rs | 4 +++ 3 files changed, 53 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 378d822d413..55b55918131 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,8 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use {ReturnIndent, BraceStyle}; -use utils::{format_visibility, make_indent, contains_skip, span_after, end_typaram}; +use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, + end_typaram}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use comment::FindUncommented; use visitor::FmtVisitor; @@ -230,46 +231,14 @@ impl<'a> FmtVisitor<'a> { -> String { let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); // Account for sugary self. - let mut min_args = 1; - if let Some(explicit_self) = explicit_self { - match explicit_self.node { - ast::ExplicitSelf_::SelfRegion(ref lt, ref m, _) => { - let lt_str = match lt { - &Some(ref l) => format!("{} ", pprust::lifetime_to_string(l)), - &None => String::new(), - }; - let mut_str = match m { - &ast::Mutability::MutMutable => "mut ".to_owned(), - &ast::Mutability::MutImmutable => String::new(), - }; - arg_item_strs[0] = format!("&{}{}self", lt_str, mut_str); - min_args = 2; - } - ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { - arg_item_strs[0] = format!("self: {}", pprust::ty_to_string(ty)); - } - ast::ExplicitSelf_::SelfValue(_) => { - assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); - - // this hacky solution caused by absence of `Mutability` in `SelfValue`. - let mut_str = { - if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) - = args[0].pat.node { - match mutability { - ast::Mutability::MutMutable => "mut ", - ast::Mutability::MutImmutable => "", - } - } else { - panic!("there is a bug or change in structure of AST, aborting."); - } - }; - - arg_item_strs[0] = format!("{}self", mut_str); - min_args = 2; - } - _ => {} - } - } + // FIXME: the comment for the self argument is dropped. This is blocked + // on rust issue #27522. + let min_args = explicit_self.and_then(|explicit_self| { + rewrite_explicit_self(explicit_self, args) + }).map(|self_str| { + arg_item_strs[0] = self_str; + 2 + }).unwrap_or(1); // Comments between args let mut arg_items = Vec::new(); @@ -802,6 +771,37 @@ impl<'a> FmtVisitor<'a> { } } +fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) -> Option { + match explicit_self.node { + ast::ExplicitSelf_::SelfRegion(lt, m, _) => { + let mut_str = format_mutability(m); + match lt { + Some(ref l) => Some(format!("&{} {}self", pprust::lifetime_to_string(l), mut_str)), + None => Some(format!("&{}self", mut_str)), + } + } + ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { + Some(format!("self: {}", pprust::ty_to_string(ty))) + } + ast::ExplicitSelf_::SelfValue(_) => { + assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); + + // this hacky solution caused by absence of `Mutability` in `SelfValue`. + let mut_str = { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) + = args[0].pat.node { + format_mutability(mutability) + } else { + panic!("there is a bug or change in structure of AST, aborting."); + } + }; + + Some(format!("{}self", mut_str)) + } + _ => None + } +} + fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { if is_named_arg(arg) { arg.pat.span.lo diff --git a/src/utils.rs b/src/utils.rs index 246f7cb2dc3..3ff30da9784 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -64,6 +64,14 @@ pub fn format_visibility(vis: Visibility) -> &'static str { } } +#[inline] +pub fn format_mutability(mutability: ast::Mutability) -> &'static str { + match mutability { + ast::Mutability::MutMutable => "mut ", + ast::Mutability::MutImmutable => "" + } +} + fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, diff --git a/tests/target/trait.rs b/tests/target/trait.rs index b7d711f8b00..5b69c46b18d 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -22,3 +22,7 @@ trait Foo { pub trait WriteMessage { fn write_message(&mut self, &FrontendMessage) -> io::Result<()>; } + +trait Runnable { + fn handler(self: &Runnable); +} -- cgit 1.4.1-3-g733a5 From 41bca58100260323e54ff83e5bc74dd920beabcd Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 14 Aug 2015 14:09:19 +0200 Subject: Format paths --- src/expr.rs | 32 ++-- src/imports.rs | 27 ++- src/items.rs | 40 +++-- src/lists.rs | 2 +- src/types.rs | 396 +++++++++++++++++++++++++++++++++++++++----- src/utils.rs | 10 ++ src/visitor.rs | 16 +- tests/source/fn-simple.rs | 8 + tests/source/paths.rs | 22 +++ tests/source/struct_lits.rs | 5 + tests/target/fn-simple.rs | 13 ++ tests/target/fn.rs | 14 -- tests/target/paths.rs | 21 +++ tests/target/struct_lits.rs | 7 + 14 files changed, 507 insertions(+), 106 deletions(-) create mode 100644 tests/source/paths.rs create mode 100644 tests/target/paths.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 334c509c59d..4cfa5a0b879 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,14 +12,14 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; use StructLitStyle; -use utils::{span_after, make_indent}; +use utils::{span_after, make_indent, extra_offset}; use visitor::FmtVisitor; use config::BlockIndentStyle; use comment::{FindUncommented, rewrite_comment}; +use types::rewrite_path; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos, mk_sp}; -use syntax::print::pprust; use syntax::visit::Visitor; impl Rewrite for ast::Expr { @@ -99,6 +99,9 @@ impl Rewrite for ast::Expr { width, offset) } + ast::Expr_::ExprPath(ref qself, ref path) => { + rewrite_path(context, qself.as_ref(), path, width, offset) + } _ => context.codemap.span_to_snippet(self.span).ok() } } @@ -320,11 +323,7 @@ fn rewrite_pat_expr(context: &RewriteContext, }; // Consider only the last line of the pat string. - let extra_offset = match result.rfind('\n') { - // 1 for newline character - Some(idx) => result.len() - idx - 1 - offset, - None => result.len() - }; + let extra_offset = extra_offset(&result, offset); // The expression may (partionally) fit on the current line. if width > extra_offset + 1 { @@ -391,16 +390,19 @@ fn rewrite_call(context: &RewriteContext, debug!("rewrite_call, width: {}, offset: {}", width, offset); // TODO using byte lens instead of char lens (and probably all over the place too) - let callee_str = try_opt!(callee.rewrite(context, width, offset)); + // 2 is for parens + let max_callee_width = try_opt!(width.checked_sub(2)); + let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); debug!("rewrite_call, callee_str: `{}`", callee_str); if args.len() == 0 { return Some(format!("{}()", callee_str)); } + let extra_offset = extra_offset(&callee_str, offset); // 2 is for parens. - let remaining_width = try_opt!(width.checked_sub(callee_str.len() + 2)); - let offset = callee_str.len() + 1 + offset; + let remaining_width = try_opt!(width.checked_sub(extra_offset + 2)); + let offset = offset + extra_offset + 1; let block_indent = expr_block_indent(context, offset); let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; @@ -425,7 +427,7 @@ fn rewrite_call(context: &RewriteContext, indent: offset, h_width: remaining_width, v_width: remaining_width, - ends_with_newline: true, + ends_with_newline: false, }; Some(format!("{}({})", callee_str, write_list(&items, &fmt))) @@ -468,7 +470,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, Base(&'a ast::Expr), } - let path_str = pprust::path_to_string(path); + // 2 = " {".len() + let path_str = try_opt!(path.rewrite(context, width - 2, offset)); + // Foo { a: Foo } - indent is +3, width is -5. let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); let (indent, v_budget) = match context.config.struct_lit_style { @@ -537,7 +541,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, indent: indent, h_width: h_budget, v_width: v_budget, - ends_with_newline: true, + ends_with_newline: false, }; let fields_str = write_list(&items, &fmt); @@ -601,7 +605,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, indent: indent, h_width: width - 2, v_width: width - 2, - ends_with_newline: true, + ends_with_newline: false, }; Some(format!("({})", write_list(&items, &fmt))) diff --git a/src/imports.rs b/src/imports.rs index 958dfadff66..e3629410c6c 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -11,11 +11,9 @@ use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use utils::span_after; use rewrite::{Rewrite, RewriteContext}; -use config::Config; use syntax::ast; -use syntax::print::pprust; -use syntax::codemap::{CodeMap, Span}; +use syntax::codemap::Span; // TODO (some day) remove unused imports, expand globs, compress many single imports into a list import @@ -29,20 +27,21 @@ impl Rewrite for ast::ViewPath { path, path_list, self.span, - context.codemap, - context.config).unwrap_or("".to_owned())) + context).unwrap_or("".to_owned())) } ast::ViewPath_::ViewPathGlob(_) => { // FIXME convert to list? None } ast::ViewPath_::ViewPathSimple(ident, ref path) => { - let path_str = pprust::path_to_string(path); + let ident_str = ident.to_string(); + // 4 = " as ".len() + let path_str = try_opt!(path.rewrite(context, width - ident_str.len() - 4, offset)); Some(if path.segments.last().unwrap().identifier == ident { path_str } else { - format!("{} as {}", path_str, ident) + format!("{} as {}", path_str, ident_str) }) } } @@ -74,10 +73,10 @@ pub fn rewrite_use_list(width: usize, path: &ast::Path, path_list: &[ast::PathListItem], span: Span, - codemap: &CodeMap, - config: &Config) + context: &RewriteContext) -> Option { - let path_str = pprust::path_to_string(path); + // 1 = {} + let path_str = try_opt!(path.rewrite(context, width - 1, offset)); match path_list.len() { 0 => return None, @@ -106,10 +105,10 @@ pub fn rewrite_use_list(width: usize, // available // (loose 1 column (";")) v_width: remaining_width, - ends_with_newline: true, + ends_with_newline: false, }; - let mut items = itemize_list(codemap, + let mut items = itemize_list(context.codemap, vec![ListItem::from_str("")], /* Dummy value, explanation * below */ path_list.iter(), @@ -125,7 +124,7 @@ pub fn rewrite_use_list(width: usize, "self".to_owned() } }, - span_after(span, "{", codemap), + span_after(span, "{", context.codemap), span.hi); // We prefixed the item list with a dummy value so that we can @@ -140,7 +139,7 @@ pub fn rewrite_use_list(width: usize, 1 }; - if config.reorder_imports { + if context.config.reorder_imports { items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } diff --git a/src/items.rs b/src/items.rs index 55b55918131..bbe80bf1231 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,6 +16,8 @@ use utils::{format_mutability, format_visibility, make_indent, contains_skip, sp use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use comment::FindUncommented; use visitor::FmtVisitor; +use rewrite::Rewrite; +use config::Config; use syntax::{ast, abi}; use syntax::codemap::{self, Span, BytePos}; @@ -215,6 +217,7 @@ impl<'a> FmtVisitor<'a> { // Where clause. result.push_str(&self.rewrite_where_clause(where_clause, + self.config, indent, span.hi)); @@ -281,7 +284,7 @@ impl<'a> FmtVisitor<'a> { indent: arg_indent, h_width: one_line_budget, v_width: multi_line_budget, - ends_with_newline: true, + ends_with_newline: false, }; write_list(&arg_items, &fmt) @@ -429,7 +432,7 @@ impl<'a> FmtVisitor<'a> { indent: indent, h_width: budget, v_width: budget, - ends_with_newline: false, + ends_with_newline: true, }; result.push_str(&write_list(&items, &fmt)); result.push(')'); @@ -557,7 +560,7 @@ impl<'a> FmtVisitor<'a> { indent: offset + self.config.tab_spaces, h_width: self.config.max_width, v_width: budget, - ends_with_newline: false, + ends_with_newline: true, }; result.push_str(&write_list(&items, &fmt)); @@ -608,6 +611,7 @@ impl<'a> FmtVisitor<'a> { if generics.where_clause.predicates.len() > 0 || result.contains('\n') { result.push_str(&self.rewrite_where_clause(&generics.where_clause, + self.config, self.block_indent, span.hi)); result.push_str(&make_indent(self.block_indent)); @@ -664,8 +668,15 @@ impl<'a> FmtVisitor<'a> { result.push('<'); // Strings for the generics. - let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)); - let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty)); + // 1 = < + let context = self.get_context(); + // FIXME: don't unwrap + let lt_strs = lifetimes.iter().map(|lt| { + lt.rewrite(&context, budget, offset + 1).unwrap() + }); + let ty_strs = tys.iter().map(|ty_param| { + ty_param.rewrite(&context, budget, offset + 1).unwrap() + }); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { @@ -700,7 +711,7 @@ impl<'a> FmtVisitor<'a> { indent: offset + 1, h_width: budget, v_width: budget, - ends_with_newline: true, + ends_with_newline: false, }; result.push_str(&write_list(&items, &fmt)); @@ -711,6 +722,7 @@ impl<'a> FmtVisitor<'a> { fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, + config: &Config, indent: usize, span_end: BytePos) -> String { @@ -720,9 +732,13 @@ impl<'a> FmtVisitor<'a> { } result.push('\n'); - result.push_str(&make_indent(indent + 4)); + result.push_str(&make_indent(indent + config.tab_spaces)); result.push_str("where "); + let context = self.get_context(); + // 6 = "where ".len() + let offset = indent + config.tab_spaces + 6; + let budget = self.config.ideal_width + self.config.leeway - offset; let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; let items = itemize_list(self.codemap, Vec::new(), @@ -731,19 +747,21 @@ impl<'a> FmtVisitor<'a> { "{", |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - |pred| self.rewrite_pred(pred), + // FIXME: we should handle failure better + // this will be taken care of when write_list + // takes Rewrite object: see issue #133 + |pred| pred.rewrite(&context, budget, offset).unwrap(), span_start, span_end); - let budget = self.config.ideal_width + self.config.leeway - indent - 10; let fmt = ListFormatting { tactic: ListTactic::Vertical, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: indent + 10, + indent: offset, h_width: budget, v_width: budget, - ends_with_newline: true, + ends_with_newline: false, }; result.push_str(&write_list(&items, &fmt)); diff --git a/src/lists.rs b/src/lists.rs index 13c0cf763e3..6398c19c9ea 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -211,7 +211,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St let offset = formatting.indent + item_width + 1; let comment = item.post_comment.as_ref().unwrap(); // Use block-style only for the last item or multiline comments. - let block_style = formatting.ends_with_newline && last || + let block_style = !formatting.ends_with_newline && last || comment.trim().contains('\n') || comment.trim().len() > width; let formatted_comment = rewrite_comment(comment, block_style, width, offset); diff --git a/src/types.rs b/src/types.rs index c2e27c31684..4917d6ac3c9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,33 +8,311 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use visitor::FmtVisitor; +use std::fmt; use syntax::ast; use syntax::print::pprust; +use syntax::codemap::{self, Span, BytePos, CodeMap}; -impl<'a> FmtVisitor<'a> { - pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String { - // TODO dead spans +use lists::{itemize_list, write_list, ListTactic, SeparatorTactic, ListFormatting}; +use rewrite::{Rewrite, RewriteContext}; +use utils::{extra_offset, span_after}; + +impl Rewrite for ast::Path { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + rewrite_path(context, None, self, width, offset) + } +} + +// Does not wrap on simple segments. +pub fn rewrite_path(context: &RewriteContext, + qself: Option<&ast::QSelf>, + path: &ast::Path, + width: usize, + offset: usize) + -> Option { + let skip_count = qself.map(|x| x.position).unwrap_or(0); + + let mut result = if path.global { + "::".to_owned() + } else { + String::new() + }; + + let mut span_lo = path.span.lo; + + if let Some(ref qself) = qself { + result.push('<'); + result.push_str(&pprust::ty_to_string(&qself.ty)); + result.push_str(" as "); + + let extra_offset = extra_offset(&result, offset); + // 3 = ">::".len() + let budget = try_opt!(width.checked_sub(extra_offset)) - 3; + + result = try_opt!(rewrite_path_segments(result, + path.segments.iter().take(skip_count), + span_lo, + path.span.hi, + context, + budget, + offset + extra_offset)); + + result.push_str(">::"); + span_lo = qself.ty.span.hi + BytePos(1); + } + + let extra_offset = extra_offset(&result, offset); + let budget = try_opt!(width.checked_sub(extra_offset)); + rewrite_path_segments(result, + path.segments.iter().skip(skip_count), + span_lo, + path.span.hi, + context, + budget, + offset + extra_offset) +} + +fn rewrite_path_segments<'a, I>(mut buffer: String, + iter: I, + mut span_lo: BytePos, + span_hi: BytePos, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option + where I: Iterator +{ + let mut first = true; + + for segment in iter { + let extra_offset = extra_offset(&buffer, offset); + let remaining_width = try_opt!(width.checked_sub(extra_offset)); + let new_offset = offset + extra_offset; + let segment_string = try_opt!(rewrite_segment(segment, + &mut span_lo, + span_hi, + context, + remaining_width, + new_offset)); + + if first { + first = false; + } else { + buffer.push_str("::"); + } + + buffer.push_str(&segment_string); + } + + Some(buffer) +} + +enum SegmentParam<'a> { + LifeTime(&'a ast::Lifetime), + Type(&'a ast::Ty), + Binding(&'a ast::TypeBinding), +} + +impl<'a> SegmentParam<'a> { + fn get_span(&self) -> Span { + match *self { + SegmentParam::LifeTime(ref lt) => lt.span, + SegmentParam::Type(ref ty) => ty.span, + SegmentParam::Binding(ref binding) => binding.span, + } + } +} + +impl<'a> fmt::Display for SegmentParam<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + SegmentParam::LifeTime(ref lt) => { + write!(f, "{}", pprust::lifetime_to_string(lt)) + } + SegmentParam::Type(ref ty) => { + write!(f, "{}", pprust::ty_to_string(ty)) + } + SegmentParam::Binding(ref binding) => { + write!(f, "{} = {}", binding.ident, pprust::ty_to_string(&*binding.ty)) + } + } + } +} + +// This is a dirty hack to determine if we're in an expression or not. Generic +// parameters are passed differently in expressions and items. We'd declare +// a struct with Foo, but call its functions with Foo::::f(). +// We'd really rather not do this, but there doesn't seem to be an alternative +// at this point. +// FIXME: fails with spans containing comments with the characters < or : +fn get_path_separator(codemap: &CodeMap, + path_start: BytePos, + segment_start: BytePos) + -> &'static str { + let span = codemap::mk_sp(path_start, segment_start); + let snippet = codemap.span_to_snippet(span).unwrap(); + + for c in snippet.chars().rev() { + if c == ':' { + return "::" + } else if c.is_whitespace() || c == '<' { + continue; + } else { + return ""; + } + } + + unreachable!(); +} + +// Formats a path segment. There are some hacks involved to correctly determine +// the segment's associated span since it's not part of the AST. +// +// The span_lo is assumed to be greater than the end of any previous segment's +// parameters and lesser or equal than the start of current segment. +// +// span_hi is assumed equal to the end of the entire path. +// +// When the segment contains a positive number of parameters, we update span_lo +// so that invariants described above will hold for the next segment. +fn rewrite_segment(segment: &ast::PathSegment, + span_lo: &mut BytePos, + span_hi: BytePos, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option { + let ident_len = segment.identifier.to_string().len(); + let width = try_opt!(width.checked_sub(ident_len)); + let offset = offset + ident_len; + + let params = match segment.parameters { + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => { + let param_list = data.lifetimes.iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter() + .map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter() + .map(|x| SegmentParam::Binding(&*x))) + .collect::>(); + + let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); + let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); + let separator = get_path_separator(context.codemap, *span_lo, list_lo); + + let items = itemize_list(context.codemap, + Vec::new(), + param_list.into_iter(), + ",", + ">", + |param| param.get_span().lo, + |param| param.get_span().hi, + ToString::to_string, + list_lo, + span_hi); + + // 1 for < + let extra_offset = 1 + separator.len(); + // 1 for > + let list_width = try_opt!(width.checked_sub(extra_offset + 1)); + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset + extra_offset, + h_width: list_width, + v_width: list_width, + ends_with_newline: false, + }; + + // update pos + *span_lo = next_span_lo; + + format!("{}<{}>", separator, write_list(&items, &fmt)) + } + ast::PathParameters::ParenthesizedParameters(ref data) => { + let output = match data.output { + Some(ref ty) => format!(" -> {}", pprust::ty_to_string(&*ty)), + None => String::new() + }; + + let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap); + let items = itemize_list(context.codemap, + Vec::new(), + data.inputs.iter(), + ",", + ")", + |ty| ty.span.lo, + |ty| ty.span.hi, + |ty| pprust::ty_to_string(ty), + list_lo, + span_hi); + + // 2 for () + let budget = try_opt!(width.checked_sub(output.len() + 2)); + + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + // 1 for ( + indent: offset + 1, + h_width: budget, + v_width: budget, + ends_with_newline: false, + }; + + // update pos + *span_lo = data.inputs.last().unwrap().span.hi + BytePos(1); + + format!("({}){}", write_list(&items, &fmt), output) + } + _ => String::new() + }; + + Some(format!("{}{}", segment.identifier, params)) +} + +impl Rewrite for ast::WherePredicate { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + // TODO dead spans? // TODO assumes we'll always fit on one line... - match predicate { + Some(match self { &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, ref bounded_ty, ref bounds, ..}) => { if bound_lifetimes.len() > 0 { - format!("for<{}> {}: {}", - bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)) - .collect::>().join(", "), - pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)) - .collect::>().join(" + ")) + let lifetime_str = bound_lifetimes.iter().map(|lt| { + lt.rewrite(context, width, offset).unwrap() + }).collect::>().join(", "); + let type_str = pprust::ty_to_string(bounded_ty); + // 8 = "for<> : ".len() + let used_width = lifetime_str.len() + type_str.len() + 8; + let bounds_str = bounds.iter().map(|ty_bound| { + ty_bound.rewrite(context, + width - used_width, + offset + used_width) + .unwrap() + }).collect::>().join(" + "); + format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { - format!("{}: {}", - pprust::ty_to_string(bounded_ty), - bounds.iter().map(|b| self.rewrite_ty_bound(b)) - .collect::>().join(" + ")) + let type_str = pprust::ty_to_string(bounded_ty); + // 2 = ": ".len() + let used_width = type_str.len() + 2; + let bounds_str = bounds.iter().map(|ty_bound| { + ty_bound.rewrite(context, + width - used_width, + offset + used_width) + .unwrap() + }).collect::>().join(" + "); + + format!("{}: {}", type_str, bounds_str) } } &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, @@ -42,65 +320,91 @@ impl<'a> FmtVisitor<'a> { ..}) => { format!("{}: {}", pprust::lifetime_to_string(lifetime), - bounds.iter().map(|l| pprust::lifetime_to_string(l)) - .collect::>().join(" + ")) + bounds.iter().map(pprust::lifetime_to_string) + .collect::>().join(" + ")) } &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty)) + let ty_str = pprust::ty_to_string(ty); + // 3 = " = ".len() + let used_width = 3 + ty_str.len(); + let path_str = try_opt!(path.rewrite(context, + width - used_width, + offset + used_width)); + format!("{} = {}", path_str, ty_str) } - } + }) } +} - pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String { - if lifetime.bounds.len() == 0 { - return pprust::lifetime_to_string(&lifetime.lifetime); +impl Rewrite for ast::LifetimeDef { + fn rewrite(&self, _: &RewriteContext, _: usize, _: usize) -> Option { + if self.bounds.len() == 0 { + Some(pprust::lifetime_to_string(&self.lifetime)) + } else { + Some(format!("{}: {}", + pprust::lifetime_to_string(&self.lifetime), + self.bounds.iter().map(pprust::lifetime_to_string) + .collect::>().join(" + "))) } - - format!("{}: {}", - pprust::lifetime_to_string(&lifetime.lifetime), - lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)) - .collect::>().join(" + ")) } +} - pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String { - match *bound { +impl Rewrite for ast::TyParamBound { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + match *self { ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { - self.rewrite_poly_trait_ref(tref) + tref.rewrite(context, width, offset) } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { - format!("?{}", self.rewrite_poly_trait_ref(tref)) + Some(format!("?{}", try_opt!(tref.rewrite(context, width - 1, offset + 1)))) } ast::TyParamBound::RegionTyParamBound(ref l) => { - pprust::lifetime_to_string(l) + Some(pprust::lifetime_to_string(l)) } } } +} - pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String { +// FIXME: this assumes everything will fit on one line +impl Rewrite for ast::TyParam { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let mut result = String::with_capacity(128); - result.push_str(&ty_param.ident.to_string()); - if ty_param.bounds.len() > 0 { + result.push_str(&self.ident.to_string()); + if self.bounds.len() > 0 { result.push_str(": "); - result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b)) - .collect::>().join(" + ")); + + let bounds = self.bounds.iter().map(|ty_bound| { + ty_bound.rewrite(context, width, offset).unwrap() + }).collect::>().join(" + "); + + result.push_str(&bounds); } - if let Some(ref def) = ty_param.default { + if let Some(ref def) = self.default { result.push_str(" = "); result.push_str(&pprust::ty_to_string(&def)); } - result + Some(result) } +} - fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String { - if t.bound_lifetimes.len() > 0 { - format!("for<{}> {}", - t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)) - .collect::>().join(", "), - pprust::path_to_string(&t.trait_ref.path)) +// FIXME: this assumes everything will fit on one line +impl Rewrite for ast::PolyTraitRef { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + if self.bound_lifetimes.len() > 0 { + let lifetime_str = self.bound_lifetimes.iter().map(|lt| { + lt.rewrite(context, width, offset).unwrap() + }).collect::>().join(", "); + // 6 is "for<> ".len() + let extra_offset = lifetime_str.len() + 6; + let max_path_width = try_opt!(width.checked_sub(extra_offset)); + let path_str = try_opt!(self.trait_ref.path.rewrite(context, + max_path_width, + offset + extra_offset)); + Some(format!("for<{}> {}", lifetime_str, path_str)) } else { - pprust::path_to_string(&t.trait_ref.path) + self.trait_ref.path.rewrite(context, width, offset) } } } diff --git a/src/utils.rs b/src/utils.rs index 3ff30da9784..59f85b3ad27 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,6 +15,16 @@ use comment::FindUncommented; use SKIP_ANNOTATION; +// Computes the length of a string's last line, minus offset. +#[inline] +pub fn extra_offset(text: &str, offset: usize) -> usize { + match text.rfind('\n') { + // 1 for newline character + Some(idx) => text.len() - idx - 1 - offset, + None => text.len() + } +} + #[inline] pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { let snippet = codemap.span_to_snippet(original).unwrap(); diff --git a/src/visitor.rs b/src/visitor.rs index 23908edf8d0..e107a32abf8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -33,13 +33,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.lo), self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); + let offset = self.buffer.cur_offset(); - let context = RewriteContext { - codemap: self.codemap, - config: self.config, - block_indent: self.block_indent, - }; - let rewrite = ex.rewrite(&context, self.config.max_width - offset, offset); + let rewrite = ex.rewrite(&self.get_context(), self.config.max_width - offset, offset); if let Some(new_str) = rewrite { self.buffer.push_str(&new_str); @@ -372,4 +368,12 @@ impl<'a> FmtVisitor<'a> { } } } + + pub fn get_context(&self) -> RewriteContext { + RewriteContext { + codemap: self.codemap, + config: self.config, + block_indent: self.block_indent, + } + } } diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 9bcf3166722..b5682d36cfa 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -9,3 +9,11 @@ y: World ) { simple(/* does this preserve comments now? */ 42, NoWay) } + +fn generic(arg: T) -> &SomeType + where T: Fn(// First arg + A, + // Second argument + B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { + arg(a, b, c, d, e) +} diff --git a/tests/source/paths.rs b/tests/source/paths.rs new file mode 100644 index 00000000000..4225aa9dab3 --- /dev/null +++ b/tests/source/paths.rs @@ -0,0 +1,22 @@ + +fn main() { + // FIXME(#133): the list rewrite should fail and force a different format + let constellation_chan = Constellation:: ::start( + compositor_proxy, + resource_task, + image_cache_task,font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard + ); + + Quux::::some_func(); + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux(); +} + +fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 54f2ea5441b..225d3a16985 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -48,3 +48,8 @@ fn matcher() { }, }; } + +fn issue177() { + struct Foo { memb: T } + let foo = Foo:: { memb: 10 }; +} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index eb133d568ed..dbb4f82924a 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -14,3 +14,16 @@ fn weird_comment(// /*/ double level */ comment 42, NoWay) } + +fn generic(arg: T) -> &SomeType + where T: Fn(// First arg + A, + // Second argument + B, + C, + D, + // pre comment + E /* last comment */) -> &SomeType +{ + arg(a, b, c, d, e) +} diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 6c41f62a8b2..bc05efa5351 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -79,17 +79,3 @@ fn main() { let _ = function(move || 5); let _ = move || 42; } - -fn servo() { - let constellation_chan = Constellation::::start( - compositor_proxy, - resource_task, - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard); -} diff --git a/tests/target/paths.rs b/tests/target/paths.rs new file mode 100644 index 00000000000..c358104e1fa --- /dev/null +++ b/tests/target/paths.rs @@ -0,0 +1,21 @@ + +fn main() { + // FIXME(#133): the list rewrite should fail and force a different format + let constellation_chan = Constellation::::start(compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard); + + Quux::::some_func(); + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux(); +} + +fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 9f7ab5cb428..cc2887fc51f 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -64,3 +64,10 @@ fn matcher() { }, }; } + +fn issue177() { + struct Foo { + memb: T, + } + let foo = Foo:: { memb: 10 }; +} -- cgit 1.4.1-3-g733a5 From 2f4ef7dd1e78d6d73d5d983ccc97d2fee68b4b7f Mon Sep 17 00:00:00 2001 From: Alex Newman Date: Tue, 18 Aug 2015 11:04:58 -0700 Subject: Provide information about default.toml --- README.md | 7 ++++--- src/bin/rustfmt.rs | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 2bddeb869da..03db8f375f2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ A tool for formatting Rust code according to style guidelines. ## How to use -You'll need a pretty up to date version of the **nightly** version of Rust. +You'll need a pretty up to date version of the **nightly** version of Rust. +You will need a default.toml file in the current working directory when you run +the rustfmt command. You can look at this repo for an example default.toml file. `cargo build` to build. @@ -201,8 +203,7 @@ It would be really useful to have people use rustfmt on their projects and file issues where it does something you don't expect. A really useful thing to do that on a crate from the Rust repo. If it does -something unexpected, file an issue; if not, make a PR to the Rust repo with the -reformatted code. I hope to get the whole repo consistently rustfmt'ed and to +something unexpected, file an issue; if not, make a PR to the Rust repo with the reformatted code. I hope to get the whole repo consistently rustfmt'ed and to replace `make tidy` with rustfmt as a medium-term goal. ### Create test cases diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 3ee7d888af0..a7f65b0bee0 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -19,7 +19,9 @@ use std::io::Read; fn main() { let args: Vec<_> = std::env::args().collect(); - let mut def_config_file = File::open("default.toml").unwrap(); + let mut def_config_file = File::open("default.toml").unwrap_or_else(|e| { + panic!("Unable to open configuration file [default.toml] {}",e) + }); let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).unwrap(); -- cgit 1.4.1-3-g733a5 From 4e0a8da447e57c1b9bc045828b77dd787b1e449e Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 19 Aug 2015 18:12:05 +0200 Subject: Refactor itemize list so that it produces an iterator --- src/expr.rs | 14 ++-- src/imports.rs | 31 +++++---- src/items.rs | 51 +++++++-------- src/lists.rs | 198 ++++++++++++++++++++++++++++++++------------------------- src/types.rs | 8 +-- 5 files changed, 158 insertions(+), 144 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4cfa5a0b879..1dfff001475 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -407,9 +407,7 @@ fn rewrite_call(context: &RewriteContext, let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; let items = itemize_list(context.codemap, - Vec::new(), args.iter(), - ",", ")", |item| item.span.lo, |item| item.span.hi, @@ -430,7 +428,7 @@ fn rewrite_call(context: &RewriteContext, ends_with_newline: false, }; - Some(format!("{}({})", callee_str, write_list(&items, &fmt))) + Some(format!("{}({})", callee_str, write_list(&items.collect::>(), &fmt))) } fn expr_block_indent(context: &RewriteContext, offset: usize) -> usize { @@ -494,9 +492,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let inner_context = &RewriteContext { block_indent: indent, ..*context }; let items = itemize_list(context.codemap, - Vec::new(), field_iter, - ",", "}", |item| { match *item { @@ -543,7 +539,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, v_width: v_budget, ends_with_newline: false, }; - let fields_str = write_list(&items, &fmt); + let fields_str = write_list(&items.collect::>(), &fmt); match context.config.struct_lit_style { StructLitStyle::BlockIndent if fields_str.contains('\n') => { @@ -584,9 +580,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, } let items = itemize_list(context.codemap, - Vec::new(), - items.into_iter(), - ",", + items.iter(), ")", |item| item.span.lo, |item| item.span.hi, @@ -608,7 +602,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, ends_with_newline: false, }; - Some(format!("({})", write_list(&items, &fmt))) + Some(format!("({})", write_list(&items.collect::>(), &fmt))) } fn rewrite_binary_op(context: &RewriteContext, diff --git a/src/imports.rs b/src/imports.rs index e3629410c6c..392e6fb838a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -108,30 +108,33 @@ pub fn rewrite_use_list(width: usize, ends_with_newline: false, }; - let mut items = itemize_list(context.codemap, - vec![ListItem::from_str("")], /* Dummy value, explanation - * below */ - path_list.iter(), - ",", - "}", - |vpi| vpi.span.lo, - |vpi| vpi.span.hi, - |vpi| match vpi.node { + let mut items = { + // Dummy value, see explanation below. + let mut items = vec![ListItem::from_str("")]; + let iter = itemize_list(context.codemap, + path_list.iter(), + "}", + |vpi| vpi.span.lo, + |vpi| vpi.span.hi, + |vpi| match vpi.node { ast::PathListItem_::PathListIdent{ name, .. } => { name.to_string() } ast::PathListItem_::PathListMod{ .. } => { "self".to_owned() } - }, - span_after(span, "{", context.codemap), - span.hi); + }, + span_after(span, "{", context.codemap), + span.hi); + items.extend(iter); + items + }; // We prefixed the item list with a dummy value so that we can // potentially move "self" to the front of the vector without touching // the rest of the items. - // FIXME: Make more efficient by using a linked list? That would - // require changes to the signatures of itemize_list and write_list. + // FIXME: Make more efficient by using a linked list? That would require + // changes to the signatures of write_list. let has_self = move_self_to_front(&mut items); let first_index = if has_self { 0 diff --git a/src/items.rs b/src/items.rs index bbe80bf1231..458a7b0b336 100644 --- a/src/items.rs +++ b/src/items.rs @@ -259,16 +259,16 @@ impl<'a> FmtVisitor<'a> { span.lo }; - arg_items = itemize_list(self.codemap, - arg_items, - args[min_args-1..].iter().cloned(), - ",", - ")", - span_lo_for_arg, - |arg| arg.ty.span.hi, - |_| String::new(), - comment_span_start, - span.hi); + let more_items = itemize_list(self.codemap, + args[min_args-1..].iter(), + ")", + |arg| span_lo_for_arg(arg), + |arg| arg.ty.span.hi, + |_| String::new(), + comment_span_start, + span.hi); + + arg_items.extend(more_items); } assert_eq!(arg_item_strs.len(), arg_items.len()); @@ -401,9 +401,7 @@ impl<'a> FmtVisitor<'a> { if types.len() > 0 { let items = itemize_list(self.codemap, - Vec::new(), types.iter(), - ",", ")", |arg| arg.ty.span.lo, |arg| arg.ty.span.hi, @@ -434,7 +432,7 @@ impl<'a> FmtVisitor<'a> { v_width: budget, ends_with_newline: true, }; - result.push_str(&write_list(&items, &fmt)); + result.push_str(&write_list(&items.collect::>(), &fmt)); result.push(')'); } @@ -513,9 +511,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&generics_str); let items = itemize_list(self.codemap, - Vec::new(), struct_def.fields.iter(), - ",", terminator, |field| { // Include attributes and doc comments, @@ -563,7 +559,7 @@ impl<'a> FmtVisitor<'a> { ends_with_newline: true, }; - result.push_str(&write_list(&items, &fmt)); + result.push_str(&write_list(&items.collect::>(), &fmt)); if break_line { result.push('\n'); @@ -689,16 +685,15 @@ impl<'a> FmtVisitor<'a> { }); let ty_spans = tys.iter().map(span_for_ty_param); - let mut items = itemize_list(self.codemap, - Vec::new(), - lt_spans.chain(ty_spans), - ",", - ">", - |sp| sp.lo, - |sp| sp.hi, - |_| String::new(), - span_after(span, "<", self.codemap), - span.hi); + let items = itemize_list(self.codemap, + lt_spans.chain(ty_spans), + ">", + |sp| sp.lo, + |sp| sp.hi, + |_| String::new(), + span_after(span, "<", self.codemap), + span.hi); + let mut items = items.collect::>(); for (item, ty) in items.iter_mut().zip(lt_strs.chain(ty_strs)) { item.item = ty; @@ -741,9 +736,7 @@ impl<'a> FmtVisitor<'a> { let budget = self.config.ideal_width + self.config.leeway - offset; let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; let items = itemize_list(self.codemap, - Vec::new(), where_clause.predicates.iter(), - ",", "{", |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, @@ -763,7 +756,7 @@ impl<'a> FmtVisitor<'a> { v_width: budget, ends_with_newline: false, }; - result.push_str(&write_list(&items, &fmt)); + result.push_str(&write_list(&items.collect::>(), &fmt)); result } diff --git a/src/lists.rs b/src/lists.rs index 6398c19c9ea..8f1d8a743c2 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::cmp; +use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; @@ -224,107 +225,134 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St result } -// Turns a list into a vector of items with associated comments. -// TODO: we probably do not want to take a terminator any more. Instead, we -// should demand a proper span end. -pub fn itemize_list(codemap: &CodeMap, - prefix: Vec, - it: I, - separator: &str, - terminator: &str, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - mut prev_span_end: BytePos, - next_span_start: BytePos) - -> Vec +pub struct ListItems<'a, I, F1, F2, F3> + where I: Iterator +{ + codemap: &'a CodeMap, + inner: Peekable, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos, + terminator: &'a str, +} + +impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> where I: Iterator, F1: Fn(&T) -> BytePos, F2: Fn(&T) -> BytePos, F3: Fn(&T) -> String { - let mut result = prefix; - result.reserve(it.size_hint().0); - - let mut new_it = it.peekable(); - let white_space: &[_] = &[' ', '\t']; - - while let Some(item) = new_it.next() { - // Pre-comment - let pre_snippet = codemap.span_to_snippet(codemap::mk_sp(prev_span_end, - get_lo(&item))) - .unwrap(); - let pre_snippet = pre_snippet.trim(); - let pre_comment = if pre_snippet.len() > 0 { - Some(pre_snippet.to_owned()) - } else { - None - }; - - // Post-comment - let next_start = match new_it.peek() { - Some(ref next_item) => get_lo(next_item), - None => next_span_start - }; - let post_snippet = codemap.span_to_snippet(codemap::mk_sp(get_hi(&item), - next_start)) - .unwrap(); - - let comment_end = match new_it.peek() { - Some(..) => { - let block_open_index = post_snippet.find("/*"); - let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(separator).unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => { separator_index + separator.len() } - // Block-style post-comment before the separator. - (Some(i), None) => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + separator.len()) - } - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + separator.len()) + type Item = ListItem; + + fn next(&mut self) -> Option { + let white_space: &[_] = &[' ', '\t']; + + self.inner.next().map(|item| { + // Pre-comment + let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end, + (self.get_lo)(&item))) + .unwrap(); + let pre_snippet = pre_snippet.trim(); + let pre_comment = if pre_snippet.len() > 0 { + Some(pre_snippet.to_owned()) + } else { + None + }; + + // Post-comment + let next_start = match self.inner.peek() { + Some(ref next_item) => (self.get_lo)(next_item), + None => self.next_span_start + }; + let post_snippet = self.codemap.span_to_snippet(codemap::mk_sp((self.get_hi)(&item), + next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let block_open_index = post_snippet.find("/*"); + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(",").unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => { + separator_index + 1 + } + // Block-style post-comment before the separator. + (Some(i), None) => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Potential *single* line comment. + (_, Some(j)) => { j + 1 } + _ => post_snippet.len() } - // Potential *single* line comment. - (_, Some(j)) => { j + 1 } - _ => post_snippet.len() + }, + None => { + post_snippet.find_uncommented(self.terminator) + .unwrap_or(post_snippet.len()) } - }, - None => { - post_snippet.find_uncommented(terminator) - .unwrap_or(post_snippet.len()) - } - }; + }; - // Cleanup post-comment: strip separators and whitespace. - prev_span_end = get_hi(&item) + BytePos(comment_end as u32); - let mut post_snippet = post_snippet[..comment_end].trim(); + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let mut post_snippet = post_snippet[..comment_end].trim(); - if post_snippet.starts_with(separator) { - post_snippet = post_snippet[separator.len()..] - .trim_matches(white_space); - } else if post_snippet.ends_with(separator) { - post_snippet = post_snippet[..post_snippet.len()-separator.len()] - .trim_matches(white_space); - } + if post_snippet.starts_with(',') { + post_snippet = post_snippet[1..].trim_matches(white_space); + } else if post_snippet.ends_with(",") { + post_snippet = post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space); + } - result.push(ListItem { - pre_comment: pre_comment, - item: get_item_string(&item), - post_comment: if post_snippet.len() > 0 { + let post_comment = if post_snippet.len() > 0 { Some(post_snippet.to_owned()) } else { None + }; + + ListItem { + pre_comment: pre_comment, + item: (self.get_item_string)(&item), + post_comment: post_comment, } - }); + }) } +} - result +// Creates an iterator over a list's items with associated comments. +pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap, + inner: I, + terminator: &'a str, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos) + -> ListItems<'a, I, F1, F2, F3> + where I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> String +{ + ListItems { + codemap: codemap, + inner: inner.peekable(), + get_lo: get_lo, + get_hi: get_hi, + get_item_string: get_item_string, + prev_span_end: prev_span_end, + next_span_start: next_span_start, + terminator: terminator, + } } fn needs_trailing_separator(separator_tactic: SeparatorTactic, list_tactic: ListTactic) -> bool { diff --git a/src/types.rs b/src/types.rs index 4917d6ac3c9..ea8787bd846 100644 --- a/src/types.rs +++ b/src/types.rs @@ -204,9 +204,7 @@ fn rewrite_segment(segment: &ast::PathSegment, let separator = get_path_separator(context.codemap, *span_lo, list_lo); let items = itemize_list(context.codemap, - Vec::new(), param_list.into_iter(), - ",", ">", |param| param.get_span().lo, |param| param.get_span().hi, @@ -232,7 +230,7 @@ fn rewrite_segment(segment: &ast::PathSegment, // update pos *span_lo = next_span_lo; - format!("{}<{}>", separator, write_list(&items, &fmt)) + format!("{}<{}>", separator, write_list(&items.collect::>(), &fmt)) } ast::PathParameters::ParenthesizedParameters(ref data) => { let output = match data.output { @@ -242,9 +240,7 @@ fn rewrite_segment(segment: &ast::PathSegment, let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap); let items = itemize_list(context.codemap, - Vec::new(), data.inputs.iter(), - ",", ")", |ty| ty.span.lo, |ty| ty.span.hi, @@ -269,7 +265,7 @@ fn rewrite_segment(segment: &ast::PathSegment, // update pos *span_lo = data.inputs.last().unwrap().span.hi + BytePos(1); - format!("({}){}", write_list(&items, &fmt), output) + format!("({}){}", write_list(&items.collect::>(), &fmt), output) } _ => String::new() }; -- cgit 1.4.1-3-g733a5 From 10a80bb8bed24392f6f0cde6a42a7c5f2d578ab8 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 18 Aug 2015 21:10:30 +0200 Subject: Add an option to forgo backups --- README.md | 14 +++++++---- src/bin/rustfmt.rs | 28 ++++++++++++++++++++-- src/filemap.rs | 70 +++++++++++++++++++++++++++++------------------------- src/lib.rs | 25 +++++++++++++++---- tests/system.rs | 7 +++--- 5 files changed, 98 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 03db8f375f2..61e01dcb9fd 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,18 @@ the rustfmt command. You can look at this repo for an example default.toml file. `cargo test` to run all tests. -`cargo run filename` to run on a file, if the file includes out of line modules, +`cargo run -- filename` to run on a file, if the file includes out of line modules, then we reformat those too. So to run on a whole module or crate, you just need -to run on the top file. You'll probably want to set the `WriteMode` in the call -to `run` in `main()`. Eventually you should be able to set the mode from the -command line or from a config file or something. +to run on the top file. +You'll probably want to specify the write mode. Currently, there are the replace, +overwrite and display mode. The replace mode is the default and overwrites the +original files after renaming them. In overwrite mode, rustfmt does not backup +the source files. To print the output to stdout, use the display mode. The write +mode can be set by passing the `--write-mode` flag on the command line. + +`cargo run -- filename --write-mode=display` prints the output of rustfmt to the +screen, for example. ## Use cases diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index a7f65b0bee0..6ec0f9556c8 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -9,23 +9,47 @@ // except according to those terms. #![cfg(not(test))] +#![feature(result_expect)] extern crate rustfmt; use rustfmt::{WriteMode, run}; +use rustfmt::config::Config; use std::fs::File; use std::io::Read; +use std::str::FromStr; fn main() { - let args: Vec<_> = std::env::args().collect(); let mut def_config_file = File::open("default.toml").unwrap_or_else(|e| { panic!("Unable to open configuration file [default.toml] {}",e) }); let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).unwrap(); + let config = Box::new(Config::from_toml(&def_config)); + let (args, write_mode) = determine_params(std::env::args()); - run(args, WriteMode::Overwrite, &def_config); + run(args, write_mode, config); std::process::exit(0); } + +fn determine_params(args: I) -> (Vec, WriteMode) + where I: Iterator +{ + let prefix = "--write-mode="; + let mut write_mode = WriteMode::Replace; + + // The NewFile option currently isn't supported because it requires another + // parameter, but it can be added later. + let args = args.filter(|arg| { + if arg.starts_with(prefix) { + write_mode = FromStr::from_str(&arg[prefix.len()..]).expect("Unrecognized write mode"); + false + } else { + true + } + }).collect(); + + (args, write_mode) +} diff --git a/src/filemap.rs b/src/filemap.rs index 8e09837df0a..ff50522eec6 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -73,40 +73,46 @@ fn write_file(text: &StringBuffer, } match mode { - WriteMode::Overwrite => { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.to_owned() + ".tmp"; - let bk_name = filename.to_owned() + ".bk"; - { - // Write text to temp file - let tmp_file = try!(File::create(&tmp_name)); - try!(write_system_newlines(tmp_file, text, config)); - } - - try!(fs::rename(filename, bk_name)); - try!(fs::rename(tmp_name, filename)); - } - WriteMode::NewFile(extn) => { - let filename = filename.to_owned() + "." + extn; - let file = try!(File::create(&filename)); - try!(write_system_newlines(file, text, config)); - } - WriteMode::Display => { - println!("{}:\n", filename); - let stdout = stdout(); - let stdout_lock = stdout.lock(); - try!(write_system_newlines(stdout_lock, text, config)); - } - WriteMode::Return(_) => { - // io::Write is not implemented for String, working around with Vec - let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); - // won't panic, we are writing correct utf8 - return Ok(Some(String::from_utf8(v).unwrap())); + WriteMode::Replace => { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.to_owned() + ".tmp"; + let bk_name = filename.to_owned() + ".bk"; + { + // Write text to temp file + let tmp_file = try!(File::create(&tmp_name)); + try!(write_system_newlines(tmp_file, text, config)); } + + try!(fs::rename(filename, bk_name)); + try!(fs::rename(tmp_name, filename)); } + WriteMode::Overwrite => { + // Write text directly over original file. + let file = try!(File::create(filename)); + try!(write_system_newlines(file, text, config)); + } + WriteMode::NewFile(extn) => { + let filename = filename.to_owned() + "." + extn; + let file = try!(File::create(&filename)); + try!(write_system_newlines(file, text, config)); + } + WriteMode::Display => { + println!("{}:\n", filename); + let stdout = stdout(); + let stdout_lock = stdout.lock(); + try!(write_system_newlines(stdout_lock, text, config)); + } + WriteMode::Return(_) => { + // io::Write is not implemented for String, working around with + // Vec + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text, config)); + // won't panic, we are writing correct utf8 + return Ok(Some(String::from_utf8(v).unwrap())); + } + } Ok(None) } diff --git a/src/lib.rs b/src/lib.rs index c0aff9a05b3..cc7111aae27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ use std::path::PathBuf; use std::collections::HashMap; use std::fmt; use std::mem::swap; +use std::str::FromStr; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; @@ -71,8 +72,11 @@ const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; #[derive(Copy, Clone)] pub enum WriteMode { + // Backups the original file and overwrites the orignal. + Replace, + // Overwrites original file without backup. Overwrite, - // str is the extension of the new file + // str is the extension of the new file. NewFile(&'static str), // Write the output to stdout. Display, @@ -80,6 +84,19 @@ pub enum WriteMode { Return(&'static Fn(HashMap)), } +impl FromStr for WriteMode { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "replace" => Ok(WriteMode::Replace), + "display" => Ok(WriteMode::Display), + "overwrite" => Ok(WriteMode::Overwrite), + _ => Err(()) + } + } +} + #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum NewlineStyle { Windows, // \r\n @@ -343,9 +360,7 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { // to the compiler. // write_mode determines what happens to the result of running rustfmt, see // WriteMode. -// default_config is a string of toml data to be used to configure rustfmt. -pub fn run(args: Vec, write_mode: WriteMode, default_config: &str) { - let config = Some(Box::new(config::Config::from_toml(default_config))); - let mut call_ctxt = RustFmtCalls { write_mode: write_mode, config: config }; +pub fn run(args: Vec, write_mode: WriteMode, config: Box) { + let mut call_ctxt = RustFmtCalls { write_mode: write_mode, config: Some(config) }; rustc_driver::run_compiler(&args, &mut call_ctxt); } diff --git a/tests/system.rs b/tests/system.rs index 4b29376ffa7..19a68fc4b7b 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -19,6 +19,7 @@ use std::fs; use std::io::{self, Read, BufRead, BufReader}; use std::thread; use rustfmt::*; +use rustfmt::config::Config; fn get_path_string(dir_entry: io::Result) -> String { let path = dir_entry.ok().expect("Couldn't get DirEntry.").path(); @@ -103,14 +104,14 @@ pub fn idempotent_check(filename: String) -> Result<(), HashMap> // panic to return a result in case of failure. This has the advantage of smoothing the road to // multithreaded rustfmt thread::catch_panic(move || { - run(args, WriteMode::Return(HANDLE_RESULT), &config); + run(args, WriteMode::Return(HANDLE_RESULT), config); }).map_err(|any| *any.downcast().ok().expect("Downcast failed.") ) } // Reads test config file from comments and loads it -fn get_config(file_name: &str) -> String { +fn get_config(file_name: &str) -> Box { let config_file_name = read_significant_comment(file_name, "config") .map(|file_name| { let mut full_path = "tests/config/".to_owned(); @@ -123,7 +124,7 @@ fn get_config(file_name: &str) -> String { let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).ok().expect("Couldn't read config."); - def_config + Box::new(Config::from_toml(&def_config)) } fn read_significant_comment(file_name: &str, option: &str) -> Option { -- cgit 1.4.1-3-g733a5 From 8e22a73cb73db27e4d4e30b263839164c97efcd6 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 19 Aug 2015 21:41:19 +0200 Subject: Add option to override single configuration lines for tests --- src/config.rs | 79 ++++++++++++++++++++++-------------- src/expr.rs | 6 +-- src/lib.rs | 2 +- src/utils.rs | 13 ++++++ tests/config/expr_visual_indent.toml | 16 -------- tests/config/reorder_imports.toml | 16 -------- tests/config/visual_struct_lits.toml | 16 -------- tests/source/expr-visual-indent.rs | 2 +- tests/source/imports-reorder.rs | 2 +- tests/source/struct_lits_visual.rs | 2 +- tests/system.rs | 66 ++++++++++++++++++------------ tests/target/expr-visual-indent.rs | 2 +- tests/target/imports-reorder.rs | 2 +- tests/target/struct_lits_visual.rs | 2 +- 14 files changed, 110 insertions(+), 116 deletions(-) delete mode 100644 tests/config/expr_visual_indent.toml delete mode 100644 tests/config/reorder_imports.toml delete mode 100644 tests/config/visual_struct_lits.toml (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 3d41b51661e..357f99a6097 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,37 +26,56 @@ pub enum BlockIndentStyle { impl_enum_decodable!(BlockIndentStyle, Inherit, Tabbed, Visual); -#[derive(RustcDecodable, Clone)] -pub struct Config { - pub max_width: usize, - pub ideal_width: usize, - pub leeway: usize, - pub tab_spaces: usize, - pub newline_style: NewlineStyle, - pub fn_brace_style: BraceStyle, - pub fn_return_indent: ReturnIndent, - pub fn_args_paren_newline: bool, - pub struct_trailing_comma: SeparatorTactic, - pub struct_lit_trailing_comma: SeparatorTactic, - pub struct_lit_style: StructLitStyle, - pub enum_trailing_comma: bool, - pub report_todo: ReportTactic, - pub report_fixme: ReportTactic, - pub reorder_imports: bool, // Alphabetically, case sensitive. - pub expr_indent_style: BlockIndentStyle, -} +macro_rules! create_config { + ($($i:ident: $ty:ty),+ $(,)*) => ( + #[derive(RustcDecodable, Clone)] + pub struct Config { + $(pub $i: $ty),+ + } + + impl Config { + pub fn from_toml(toml: &str) -> Config { + let parsed = toml.parse().unwrap(); + match toml::decode(parsed) { + Some(decoded) => decoded, + None => { + println!("Decoding config file failed. Config:\n{}", toml); + let parsed: toml::Value = toml.parse().unwrap(); + println!("\n\nParsed:\n{:?}", parsed); + panic!(); + } + } + } -impl Config { - pub fn from_toml(toml: &str) -> Config { - let parsed = toml.parse().unwrap(); - match toml::decode(parsed) { - Some(decoded) => decoded, - None => { - println!("Decoding config file failed. Config:\n{}", toml); - let parsed: toml::Value = toml.parse().unwrap(); - println!("\n\nParsed:\n{:?}", parsed); - panic!(); + pub fn override_value(&mut self, key: &str, val: &str) { + match key { + $( + stringify!($i) => { + self.$i = val.parse::<$ty>().unwrap(); + } + )+ + _ => panic!("Bad config key!") + } } } - } + ) +} + +create_config! { + max_width: usize, + ideal_width: usize, + leeway: usize, + tab_spaces: usize, + newline_style: NewlineStyle, + fn_brace_style: BraceStyle, + fn_return_indent: ReturnIndent, + fn_args_paren_newline: bool, + struct_trailing_comma: SeparatorTactic, + struct_lit_trailing_comma: SeparatorTactic, + struct_lit_style: StructLitStyle, + enum_trailing_comma: bool, + report_todo: ReportTactic, + report_fixme: ReportTactic, + reorder_imports: bool, // Alphabetically, case sensitive. + expr_indent_style: BlockIndentStyle, } diff --git a/src/expr.rs b/src/expr.rs index 1dfff001475..2fbdcb7d6c9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -617,10 +617,8 @@ fn rewrite_binary_op(context: &RewriteContext, let operator_str = context.codemap.span_to_snippet(op.span).unwrap(); // 1 = space between lhs expr and operator - let mut result = - try_opt!(lhs.rewrite(context, - context.config.max_width - offset - 1 - operator_str.len(), - offset)); + let max_width = try_opt!(context.config.max_width.checked_sub(operator_str.len() + offset + 1)); + let mut result = try_opt!(lhs.rewrite(context, max_width, offset)); result.push(' '); result.push_str(&operator_str); diff --git a/src/lib.rs b/src/lib.rs index cc7111aae27..cd43be56a99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,7 +80,7 @@ pub enum WriteMode { NewFile(&'static str), // Write the output to stdout. Display, - // Return the result as a mapping from filenames to StringBuffers. + // Return the result as a mapping from filenames to Strings. Return(&'static Fn(HashMap)), } diff --git a/src/utils.rs b/src/utils.rs index 59f85b3ad27..a57ffb008ea 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -144,6 +144,19 @@ macro_rules! impl_enum_decodable { } } } + + impl ::std::str::FromStr for $e { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match &*s { + $( + stringify!($x) => Ok($e::$x), + )* + _ => Err("Bad variant"), + } + } + } }; } diff --git a/tests/config/expr_visual_indent.toml b/tests/config/expr_visual_indent.toml deleted file mode 100644 index 38a099e3bed..00000000000 --- a/tests/config/expr_visual_indent.toml +++ /dev/null @@ -1,16 +0,0 @@ -max_width = 100 -ideal_width = 80 -leeway = 5 -tab_spaces = 4 -newline_style = "Unix" -fn_brace_style = "SameLineWhere" -fn_return_indent = "WithArgs" -fn_args_paren_newline = true -struct_trailing_comma = "Vertical" -struct_lit_style = "BlockIndent" -struct_lit_trailing_comma = "Vertical" -enum_trailing_comma = true -report_todo = "Always" -report_fixme = "Never" -reorder_imports = false -expr_indent_style = "Visual" diff --git a/tests/config/reorder_imports.toml b/tests/config/reorder_imports.toml deleted file mode 100644 index 5b1ce49a2f2..00000000000 --- a/tests/config/reorder_imports.toml +++ /dev/null @@ -1,16 +0,0 @@ -max_width = 100 -ideal_width = 80 -leeway = 5 -tab_spaces = 4 -newline_style = "Unix" -fn_brace_style = "SameLineWhere" -fn_return_indent = "WithArgs" -fn_args_paren_newline = true -struct_trailing_comma = "Vertical" -struct_lit_trailing_comma = "Vertical" -struct_lit_style = "BlockIndent" -enum_trailing_comma = true -report_todo = "Always" -report_fixme = "Never" -reorder_imports = true -expr_indent_style = "Tabbed" diff --git a/tests/config/visual_struct_lits.toml b/tests/config/visual_struct_lits.toml deleted file mode 100644 index 61bf4b0aee5..00000000000 --- a/tests/config/visual_struct_lits.toml +++ /dev/null @@ -1,16 +0,0 @@ -max_width = 100 -ideal_width = 80 -leeway = 5 -tab_spaces = 4 -newline_style = "Unix" -fn_brace_style = "SameLineWhere" -fn_return_indent = "WithArgs" -fn_args_paren_newline = true -struct_trailing_comma = "Vertical" -struct_lit_style = "VisualIndent" -struct_lit_trailing_comma = "Vertical" -enum_trailing_comma = true -report_todo = "Always" -report_fixme = "Never" -reorder_imports = false -expr_indent_style = "Tabbed" diff --git a/tests/source/expr-visual-indent.rs b/tests/source/expr-visual-indent.rs index c173d7bd7c4..3d7c1b92be8 100644 --- a/tests/source/expr-visual-indent.rs +++ b/tests/source/expr-visual-indent.rs @@ -1,4 +1,4 @@ -// rustfmt-config: expr_visual_indent.toml +// rustfmt-expr_indent_style: Visual // Visual level block indentation. diff --git a/tests/source/imports-reorder.rs b/tests/source/imports-reorder.rs index 2a90c212148..4feb8e90561 100644 --- a/tests/source/imports-reorder.rs +++ b/tests/source/imports-reorder.rs @@ -1,4 +1,4 @@ -// rustfmt-config: reorder_imports.toml +// rustfmt-reorder_imports: true use path::{C,/*A*/ A, B /* B */, self /* self */}; diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index f14a56397ec..ea76a088a32 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -1,4 +1,4 @@ -// rustfmt-config: visual_struct_lits.toml +// rustfmt-struct_lit_style: VisualIndent // Struct literal expressions. diff --git a/tests/system.rs b/tests/system.rs index 19a68fc4b7b..3f63d224576 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -97,8 +97,16 @@ fn print_mismatches(result: HashMap) { static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; pub fn idempotent_check(filename: String) -> Result<(), HashMap> { - let config = get_config(&filename); + let sig_comments = read_significant_comments(&filename); + let mut config = get_config(sig_comments.get("config").map(|x| &(*x)[..])); let args = vec!["rustfmt".to_owned(), filename]; + + for (key, val) in sig_comments { + if key != "target" && key != "config" { + config.override_value(&key, &val); + } + } + // this thread is not used for concurrency, but rather to workaround the issue that the passed // function handle needs to have static lifetime. Instead of using a global RefCell, we use // panic to return a result in case of failure. This has the advantage of smoothing the road to @@ -110,15 +118,15 @@ pub fn idempotent_check(filename: String) -> Result<(), HashMap> ) } -// Reads test config file from comments and loads it -fn get_config(file_name: &str) -> Box { - let config_file_name = read_significant_comment(file_name, "config") - .map(|file_name| { - let mut full_path = "tests/config/".to_owned(); - full_path.push_str(&file_name); - full_path - }) - .unwrap_or("default.toml".to_owned()); + +// Reads test config file from comments and reads its contents. +fn get_config(config_file: Option<&str>) -> Box { + let config_file_name = config_file.map(|file_name| { + let mut full_path = "tests/config/".to_owned(); + full_path.push_str(&file_name); + full_path + }) + .unwrap_or("default.toml".to_owned()); let mut def_config_file = fs::File::open(config_file_name).ok().expect("Couldn't open config."); let mut def_config = String::new(); @@ -127,14 +135,16 @@ fn get_config(file_name: &str) -> Box { Box::new(Config::from_toml(&def_config)) } -fn read_significant_comment(file_name: &str, option: &str) -> Option { - let file = fs::File::open(file_name).ok().expect("Couldn't read file for comment."); +// Reads significant comments of the form: // rustfmt-key: value +// into a hash map. +fn read_significant_comments(file_name: &str) -> HashMap { + let file = fs::File::open(file_name).ok().expect(&format!("Couldn't read file {}.", file_name)); let reader = BufReader::new(file); - let pattern = format!("^\\s*//\\s*rustfmt-{}:\\s*(\\S+)", option); + let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; let regex = regex::Regex::new(&pattern).ok().expect("Failed creating pattern 1."); - // matches exactly the lines containing significant comments or whitespace - let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[:alpha:]+:\s*\S+)") + // Matches lines containing significant comments or whitespace. + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") .ok().expect("Failed creating pattern 2."); reader.lines() @@ -142,20 +152,26 @@ fn read_significant_comment(file_name: &str, option: &str) -> Option { .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { - capture.at(1).expect("Couldn't unwrap capture.").to_owned() + (capture.at(1).expect("Couldn't unwrap capture.").to_owned(), + capture.at(2).expect("Couldn't unwrap capture.").to_owned()) }) }) - .next() + .collect() } // Compare output to input. +// TODO: needs a better name, more explanation. fn handle_result(result: HashMap) { let mut failures = HashMap::new(); for (file_name, fmt_text) in result { - // If file is in tests/source, compare to file with same name in tests/target - let target_file_name = get_target(&file_name); - let mut f = fs::File::open(&target_file_name).ok().expect("Couldn't open target."); + // FIXME: reading significant comments again. Is there a way we can just + // pass the target to this function? + let sig_comments = read_significant_comments(&file_name); + + // If file is in tests/source, compare to file with same name in tests/target. + let target = get_target(&file_name, sig_comments.get("target").map(|x| &(*x)[..])); + let mut f = fs::File::open(&target).ok().expect("Couldn't open target."); let mut text = String::new(); // TODO: speedup by running through bytes iterator @@ -171,15 +187,11 @@ fn handle_result(result: HashMap) { } // Map source file paths to their target paths. -fn get_target(file_name: &str) -> String { +fn get_target(file_name: &str, target: Option<&str>) -> String { if file_name.starts_with("tests/source/") { - let target = read_significant_comment(file_name, "target"); - let base = target.unwrap_or(file_name.trim_left_matches("tests/source/").to_owned()); - - let mut target_file = "tests/target/".to_owned(); - target_file.push_str(&base); + let base = target.unwrap_or(file_name.trim_left_matches("tests/source/")); - target_file + format!("tests/target/{}", base) } else { file_name.to_owned() } diff --git a/tests/target/expr-visual-indent.rs b/tests/target/expr-visual-indent.rs index 3488e8c93c0..d74b5aae93c 100644 --- a/tests/target/expr-visual-indent.rs +++ b/tests/target/expr-visual-indent.rs @@ -1,4 +1,4 @@ -// rustfmt-config: expr_visual_indent.toml +// rustfmt-expr_indent_style: Visual // Visual level block indentation. diff --git a/tests/target/imports-reorder.rs b/tests/target/imports-reorder.rs index 27d394238e8..63ebbf1ec7b 100644 --- a/tests/target/imports-reorder.rs +++ b/tests/target/imports-reorder.rs @@ -1,4 +1,4 @@ -// rustfmt-config: reorder_imports.toml +// rustfmt-reorder_imports: true use path::{self /* self */, /* A */ A, B /* B */, C}; diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 248839cb869..bf73db5a815 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -1,4 +1,4 @@ -// rustfmt-config: visual_struct_lits.toml +// rustfmt-struct_lit_style: VisualIndent // Struct literal expressions. -- cgit 1.4.1-3-g733a5 From dc2544712c19720cd82f70461f6ad5525dc2db7e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 14 Aug 2015 20:00:22 +1200 Subject: Rewrite match expressions --- src/expr.rs | 174 +++++++++++++++++++++++++++++++++++++++++++++++++- src/rewrite.rs | 10 +++ src/utils.rs | 20 ++++++ tests/target/match.rs | 42 ++++++++++++ 4 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 tests/target/match.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2fbdcb7d6c9..ce5dfb8cddf 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,7 +12,7 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; use StructLitStyle; -use utils::{span_after, make_indent, extra_offset}; +use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width}; use visitor::FmtVisitor; use config::BlockIndentStyle; use comment::{FindUncommented, rewrite_comment}; @@ -99,6 +99,9 @@ impl Rewrite for ast::Expr { width, offset) } + ast::Expr_::ExprMatch(ref cond, ref arms, _) => { + rewrite_match(context, cond, arms, width, offset) + } ast::Expr_::ExprPath(ref qself, ref path) => { rewrite_path(context, qself.as_ref(), path, width, offset) } @@ -303,6 +306,175 @@ fn rewrite_if_else(context: &RewriteContext, Some(result) } +fn rewrite_match(context: &RewriteContext, + cond: &ast::Expr, + arms: &[ast::Arm], + width: usize, + offset: usize) + -> Option { + // TODO comments etc. (I am somewhat surprised we don't need handling for these). + + // `match `cond` {` + let cond_str = try_opt!(cond.rewrite(context, width - 8, offset + 6)); + let mut result = format!("match {} {{", cond_str); + + let block_indent = context.block_indent; + let nested_context = context.nested_context(); + let arm_indent_str = make_indent(nested_context.block_indent); + + for arm in arms { + result.push('\n'); + result.push_str(&arm_indent_str); + result.push_str(&&try_opt!(arm.rewrite(&nested_context, + context.config.max_width - + nested_context.block_indent, + nested_context.block_indent))); + } + + result.push('\n'); + result.push_str(&make_indent(block_indent)); + result.push('}'); + Some(result) +} + +// Match arms. +impl Rewrite for ast::Arm { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; + let indent_str = make_indent(offset); + + // TODO attrs + + // Patterns + let pat_strs = pats.iter().map(|p| p.rewrite(context, + // 5 = ` => {` + width - 5, + offset + context.config.tab_spaces)).collect::>(); + if pat_strs.iter().any(|p| p.is_none()) { + return None; + } + let pat_strs = pat_strs.into_iter().map(|p| p.unwrap()).collect::>(); + + let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); + // Add ` | `.len(). + total_width += (pat_strs.len() - 1) * 3; + + let mut vertical = total_width > width - 5 || pat_strs.iter().any(|p| p.contains('\n')); + if !vertical { + // If the patterns were previously stacked, keep them stacked. + // FIXME should be an option. + let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi); + let pat_str = context.codemap.span_to_snippet(pat_span).unwrap(); + vertical = pat_str.find('\n').is_some(); + } + + + let pats_width = if vertical { + pat_strs[pat_strs.len() - 1].len() + } else { + total_width + }; + + let mut pats_str = String::new(); + for p in pat_strs { + if pats_str.len() > 0 { + if vertical { + pats_str.push_str(" |\n"); + pats_str.push_str(&indent_str); + } else { + pats_str.push_str(" | "); + } + } + pats_str.push_str(&p); + } + + // TODO probably want to compute the guard width first, then the rest + // TODO also, only subtract the guard width from the last pattern. + // If guard. + let guard_str = try_opt!(rewrite_guard(context, guard, width, offset, pats_width)); + + let pats_str = format!("{}{}", pats_str, guard_str); + // Where the next text can start. + let mut line_start = last_line_width(&pats_str); + if pats_str.find('\n').is_none() { + line_start += offset; + } + + let comma = if let ast::ExprBlock(_) = body.node { + String::new() + } else { + ",".to_owned() + }; + + // Let's try and get the arm body on the same line as the condition. + // 4 = ` => `.len() + if context.config.max_width > line_start + comma.len() + 4 { + let budget = context.config.max_width - line_start - comma.len() - 4; + if let Some(ref body_str) = body.rewrite(context, + budget, + offset + context.config.tab_spaces) { + if first_line_width(body_str) <= budget { + return Some(format!("{} => {}{}", pats_str, body_str, comma)); + } + } + } + + // We have to push the body to the next line. + if comma.len() > 0 { + // We're trying to fit a block in, but it still failed, give up. + return None; + } + + let body_str = try_opt!(body.rewrite(context, + width - context.config.tab_spaces, + offset + context.config.tab_spaces)); + Some(format!("{} =>\n{}{}", + pats_str, + make_indent(offset + context.config.tab_spaces), + body_str)) + } +} + +// The `if ...` guard on a match arm. +fn rewrite_guard(context: &RewriteContext, + guard: &Option>, + width: usize, + offset: usize, + // The amount of space used up on this line for the pattern in + // the arm. + pattern_width: usize) + -> Option { + if let &Some(ref guard) = guard { + // 4 = ` if `, 5 = ` => {` + let overhead = pattern_width + 4 + 5; + if overhead < width { + let cond_str = guard.rewrite(context, + width - overhead, + offset + context.config.tab_spaces); + if let Some(cond_str) = cond_str { + return Some(format!(" if {}", cond_str)); + } + } + + // Not enough space to put the guard after the pattern, try a newline. + let overhead = context.config.tab_spaces + 4 + 5; + if overhead < width { + let cond_str = guard.rewrite(context, + width - overhead, + offset + context.config.tab_spaces); + if let Some(cond_str) = cond_str { + return Some(format!("\n{}if {}", + make_indent(offset + context.config.tab_spaces), + cond_str)); + } + } + + None + } else { + Some(String::new()) + } +} + fn rewrite_pat_expr(context: &RewriteContext, pat: Option<&ast::Pat>, expr: &ast::Expr, diff --git a/src/rewrite.rs b/src/rewrite.rs index 33e4d5fbbf3..d30d81a4885 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -30,3 +30,13 @@ pub struct RewriteContext<'a> { pub config: &'a Config, pub block_indent: usize, } + +impl<'a> RewriteContext<'a> { + pub fn nested_context(&self) -> RewriteContext<'a> { + RewriteContext { + codemap: self.codemap, + config: self.config, + block_indent: self.block_indent + self.config.tab_spaces, + } + } +} diff --git a/src/utils.rs b/src/utils.rs index a57ffb008ea..f80e1185bae 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -82,6 +82,25 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } } +// The width of the first line in s. +#[inline] +pub fn first_line_width(s: &str) -> usize { + match s.find('\n') { + Some(n) => n, + None => s.len(), + } +} + +// The width of the last line in s. +#[inline] +pub fn last_line_width(s: &str) -> usize { + match s.rfind('\n') { + Some(n) => s.len() - n, + None => s.len(), + } +} + +#[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, @@ -95,6 +114,7 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { } // Find the end of a TyParam +#[inline] pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { typaram.bounds.last().map(|bound| match *bound { ast::RegionTyParamBound(ref lt) => lt.span, diff --git a/tests/target/match.rs b/tests/target/match.rs new file mode 100644 index 00000000000..9d8a484028b --- /dev/null +++ b/tests/target/match.rs @@ -0,0 +1,42 @@ +// Match expressions. + +fn foo() { + // A match expression. + match x { + // Some comment. + a => foo(), + b if 0 < 42 => foo(), + c => { // Another comment. + // Comment. + an_expression; + foo() + } + // Perhaps this should introduce braces? + Foo(ref bar) => + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Pattern1 | Pattern2 | Pattern3 => false, + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + blah + } + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn => meh, + + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, + + Patternnnnnnnnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnnnnnnnn + if looooooooooooooooooooooooooooooooooooooooong_guard => meh, + _ => {} + } + + let whatever = match something { + /// DOC COMMENT! + Some(_) => 42, + #[an_attribute] + None => 0, + }; +} -- cgit 1.4.1-3-g733a5 From d10629d8a5149e224126d2e05943122763f2f4cc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 16 Aug 2015 16:13:55 +1200 Subject: Allow `{}` to remain. --- src/expr.rs | 5 +++++ tests/source/expr.rs | 13 +++++++++++++ tests/target/expr.rs | 26 ++++++++++++++++++-------- tests/target/loop.rs | 3 +-- 4 files changed, 37 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ce5dfb8cddf..3fb8f85295c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -112,6 +112,11 @@ impl Rewrite for ast::Expr { impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + let user_str = context.codemap.span_to_snippet(self.span).unwrap(); + if user_str == "{}" && width > 1 { + return Some(user_str); + } + let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config); visitor.block_indent = context.block_indent; diff --git a/tests/source/expr.rs b/tests/source/expr.rs index e7862b83e50..6b3b3daf0a9 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -91,3 +91,16 @@ fn baz() { // Regular unsafe block } } + +// Test some empty blocks. +fn qux() { + {} + // FIXME this one could be done better. + { /* a block with a comment */ } + { + + } + { + // A block with a comment. + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index a1875a0ec26..356c5b7dbbd 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -22,15 +22,13 @@ fn foo() -> bool { aaaaa))))))))); { - for _ in 0..10 { - } + for _ in 0..10 {} } { { { - { - } + {} } } } @@ -47,8 +45,7 @@ fn foo() -> bool { } if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) { - } + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { @@ -56,8 +53,7 @@ fn foo() -> bool { if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + - 2222 { - } + 2222 {} if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { @@ -121,3 +117,17 @@ fn baz() { // Regular unsafe block } } + +// Test some empty blocks. +fn qux() { + {} + // FIXME this one could be done better. + { /* a block with a comment */ + } + { + + } + { + // A block with a comment. + } +} diff --git a/tests/target/loop.rs b/tests/target/loop.rs index e1f2ccc91a4..fea5bfe2cb2 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -13,8 +13,7 @@ fn main() { } 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > - some_other_value { - } + some_other_value {} while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } -- cgit 1.4.1-3-g733a5 From a43e2b5ae837604511557133f5e7554184465677 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 16 Aug 2015 15:58:17 +1200 Subject: Formatting --- src/comment.rs | 6 +++--- src/expr.rs | 26 +++++++++++++------------- src/filemap.rs | 20 ++++++++++---------- src/imports.rs | 17 +++++++++-------- src/issues.rs | 10 +++++----- src/items.rs | 21 +++++++++------------ src/lib.rs | 4 ++-- src/lists.rs | 7 ++++--- src/modules.rs | 2 +- src/types.rs | 52 ++++++++++++++++++++++++++-------------------------- src/utils.rs | 6 +++--- src/visitor.rs | 2 +- 12 files changed, 86 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 46c698ecbbb..14ca718e318 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -127,8 +127,8 @@ impl FindUncommented for str { if b != c { needle_iter = pat.chars(); } - }, - None => return Some(i - pat.len()) + } + None => return Some(i - pat.len()), } if possible_comment && (b == '/' || b == '*') { @@ -145,7 +145,7 @@ impl FindUncommented for str { // Handle case where the pattern is a suffix of the search string match needle_iter.next() { Some(_) => None, - None => Some(self.len() - pat.len()) + None => Some(self.len() - pat.len()), } } } diff --git a/src/expr.rs b/src/expr.rs index 3fb8f85295c..db646dafaba 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -30,7 +30,7 @@ impl Rewrite for ast::Expr { ast::Lit_::LitStr(ref is, _) => { rewrite_string_lit(context, &is, l.span, width, offset) } - _ => context.codemap.span_to_snippet(self.span).ok() + _ => context.codemap.span_to_snippet(self.span).ok(), } } ast::Expr_::ExprCall(ref callee, ref args) => { @@ -105,7 +105,7 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprPath(ref qself, ref path) => { rewrite_path(context, qself.as_ref(), path, width, offset) } - _ => context.codemap.span_to_snippet(self.span).ok() + _ => context.codemap.span_to_snippet(self.span).ok(), } } } @@ -199,7 +199,7 @@ impl<'a> Loop<'a> { keyword: "while ", matcher: match pat { Some(..) => "let ", - None => "" + None => "", }, connector: " =", } @@ -237,7 +237,7 @@ impl<'a> Rewrite for Loop<'a> { self.connector, inner_width, inner_offset)), - None => String::new() + None => String::new(), }; // FIXME: this drops any comment between "loop" and the block. @@ -250,7 +250,7 @@ impl<'a> Rewrite for Loop<'a> { fn rewrite_label(label: Option) -> String { match label { Some(ident) => format!("{}: ", ident), - None => "".to_owned() + None => "".to_owned(), } } @@ -262,9 +262,8 @@ fn rewrite_range(context: &RewriteContext, offset: usize) -> Option { let left_string = match left { - // 2 = .. Some(expr) => try_opt!(expr.rewrite(context, width - 2, offset)), - None => String::new() + None => String::new(), }; let right_string = match right { @@ -273,7 +272,7 @@ fn rewrite_range(context: &RewriteContext, let max_width = (width - 2).checked_sub(left_string.len()).unwrap_or(0); try_opt!(expr.rewrite(context, max_width, offset + 2 + left_string.len())) } - None => String::new() + None => String::new(), }; Some(format!("{}..{}", left_string, right_string)) @@ -354,12 +353,13 @@ impl Rewrite for ast::Arm { let pat_strs = pats.iter().map(|p| p.rewrite(context, // 5 = ` => {` width - 5, - offset + context.config.tab_spaces)).collect::>(); + offset + context.config.tab_spaces)) + .collect::>(); if pat_strs.iter().any(|p| p.is_none()) { return None; } let pat_strs = pat_strs.into_iter().map(|p| p.unwrap()).collect::>(); - + let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); // Add ` | `.len(). total_width += (pat_strs.len() - 1) * 3; @@ -496,7 +496,7 @@ fn rewrite_pat_expr(context: &RewriteContext, pat_offset)); format!("{}{}{}", matcher, pat_string, connector) } - None => String::new() + None => String::new(), }; // Consider only the last line of the pat string. @@ -804,7 +804,7 @@ fn rewrite_binary_op(context: &RewriteContext, let used_width = result.len() + 1; let remaining_width = match result.rfind('\n') { Some(idx) => (offset + width + idx).checked_sub(used_width).unwrap_or(0), - None => width.checked_sub(used_width).unwrap_or(0) + None => width.checked_sub(used_width).unwrap_or(0), }; // Get "full width" rhs and see if it fits on the current line. This @@ -836,7 +836,7 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::UnUniq => "box ", ast::UnOp::UnDeref => "*", ast::UnOp::UnNot => "!", - ast::UnOp::UnNeg => "-" + ast::UnOp::UnNeg => "-", }; let subexpr = try_opt!(expr.rewrite(context, width - operator_str.len(), offset)); diff --git a/src/filemap.rs b/src/filemap.rs index ff50522eec6..8bb5a7285bb 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -58,18 +58,18 @@ fn write_file(text: &StringBuffer, where T: Write { match config.newline_style { - NewlineStyle::Unix => write!(writer, "{}", text), - NewlineStyle::Windows => { - for (c, _) in text.chars() { - match c { - '\n' => try!(write!(writer, "\r\n")), - '\r' => continue, - c => try!(write!(writer, "{}", c)), - } + NewlineStyle::Unix => write!(writer, "{}", text), + NewlineStyle::Windows => { + for (c, _) in text.chars() { + match c { + '\n' => try!(write!(writer, "\r\n")), + '\r' => continue, + c => try!(write!(writer, "{}", c)), } - Ok(()) - }, + } + Ok(()) } + } } match mode { diff --git a/src/imports.rs b/src/imports.rs index 392e6fb838a..7d7300fb562 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -15,7 +15,8 @@ use rewrite::{Rewrite, RewriteContext}; use syntax::ast; use syntax::codemap::Span; -// TODO (some day) remove unused imports, expand globs, compress many single imports into a list import +// TODO (some day) remove unused imports, expand globs, compress many single +// imports into a list import. impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) @@ -39,10 +40,10 @@ impl Rewrite for ast::ViewPath { let path_str = try_opt!(path.rewrite(context, width - ident_str.len() - 4, offset)); Some(if path.segments.last().unwrap().identifier == ident { - path_str - } else { - format!("{} as {}", path_str, ident_str) - }) + path_str + } else { + format!("{} as {}", path_str, ident_str) + }) } } } @@ -81,7 +82,7 @@ pub fn rewrite_use_list(width: usize, match path_list.len() { 0 => return None, 1 => return Some(rewrite_single_use_list(path_str, path_list[0])), - _ => () + _ => (), } // 2 = :: @@ -161,7 +162,7 @@ fn move_self_to_front(items: &mut Vec) -> bool { Some(pos) => { items[0] = items.remove(pos); true - }, - None => false + } + None => false, } } diff --git a/src/issues.rs b/src/issues.rs index 34d5b8ab2c4..e9f8255cc91 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -29,7 +29,7 @@ impl ReportTactic { match *self { ReportTactic::Always => true, ReportTactic::Unnumbered => true, - ReportTactic::Never => false + ReportTactic::Never => false, } } } @@ -113,7 +113,7 @@ impl BadIssueSeeker { match self.state { Seeking::Issue { todo_idx, fixme_idx } => { self.state = self.inspect_issue(c, todo_idx, fixme_idx); - }, + } Seeking::Number { issue, part } => { let result = self.inspect_number(c, issue, part); @@ -198,19 +198,19 @@ impl BadIssueSeeker { } else { part = NumberPart::Pound; } - }, + } NumberPart::Pound => { if c == '#' { part = NumberPart::Number; } - }, + } NumberPart::Number => { if c >= '0' && c <= '9' { part = NumberPart::CloseParen; } else { return IssueClassification::Bad(issue); } - }, + } NumberPart::CloseParen => {} } diff --git a/src/items.rs b/src/items.rs index 458a7b0b336..79d374f85ec 100644 --- a/src/items.rs +++ b/src/items.rs @@ -411,10 +411,8 @@ impl<'a> FmtVisitor<'a> { result.push('('); - let indent = self.block_indent - + vis.len() - + field.node.name.to_string().len() - + 1; // Open paren + let indent = self.block_indent + vis.len() + field.node.name.to_string().len() + + 1; // Open paren let comma_cost = if self.config.enum_trailing_comma { 1 @@ -449,7 +447,7 @@ impl<'a> FmtVisitor<'a> { } result - }, + } ast::VariantKind::StructVariantKind(ref struct_def) => { // TODO Should limit the width, as we have a trailing comma self.format_struct("", @@ -491,7 +489,7 @@ impl<'a> FmtVisitor<'a> { let is_tuple = match struct_def.fields[0].node.kind { ast::StructFieldKind::NamedField(..) => false, - ast::StructFieldKind::UnnamedField(..) => true + ast::StructFieldKind::UnnamedField(..) => true, }; let (opener, terminator) = if is_tuple { @@ -506,7 +504,7 @@ impl<'a> FmtVisitor<'a> { offset + header_str.len(), codemap::mk_sp(span.lo, struct_def.fields[0].span.lo)), - None => opener.to_owned() + None => opener.to_owned(), }; result.push_str(&generics_str); @@ -632,7 +630,7 @@ impl<'a> FmtVisitor<'a> { }; let vis = match field.node.kind { ast::StructFieldKind::NamedField(_, vis) | - ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis) + ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; let typ = pprust::ty_to_string(&field.node.ty); @@ -645,7 +643,7 @@ impl<'a> FmtVisitor<'a> { match name { Some(name) => format!("{}{}{}: {}", attr_str, vis, name, typ), - None => format!("{}{}{}", attr_str, vis, typ) + None => format!("{}{}{}", attr_str, vis, typ), } } @@ -799,8 +797,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) - // this hacky solution caused by absence of `Mutability` in `SelfValue`. let mut_str = { - if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) - = args[0].pat.node { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = args[0].pat.node { format_mutability(mutability) } else { panic!("there is a bug or change in structure of AST, aborting."); @@ -809,7 +806,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) - Some(format!("{}self", mut_str)) } - _ => None + _ => None, } } diff --git a/src/lib.rs b/src/lib.rs index cd43be56a99..9ec401b129d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,7 @@ impl FromStr for WriteMode { "replace" => Ok(WriteMode::Replace), "display" => Ok(WriteMode::Display), "overwrite" => Ok(WriteMode::Overwrite), - _ => Err(()) + _ => Err(()), } } } @@ -243,7 +243,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { for (c, b) in text.chars() { if c == '\r' { - continue; + continuecontinue } // Add warnings for bad todos/ fixmes diff --git a/src/lists.rs b/src/lists.rs index 8f1d8a743c2..eadefe2e0fb 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -213,7 +213,8 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St let comment = item.post_comment.as_ref().unwrap(); // Use block-style only for the last item or multiline comments. let block_style = !formatting.ends_with_newline && last || - comment.trim().contains('\n') || comment.trim().len() > width; + comment.trim().contains('\n') || + comment.trim().len() > width; let formatted_comment = rewrite_comment(comment, block_style, width, offset); @@ -381,7 +382,7 @@ fn comment_len(comment: &Option) -> usize { } else { text_len } - }, - &None => 0 + } + &None => 0, } } diff --git a/src/modules.rs b/src/modules.rs index 2f40fd33a55..681bb1c8ade 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -67,6 +67,6 @@ fn module_file(id: ast::Ident, match parser::Parser::default_submod_path(id, &dir_path, codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => path, - Err(_) => panic!("Couldn't find module {}", id) + Err(_) => panic!("Couldn't find module {}", id), } } diff --git a/src/types.rs b/src/types.rs index ea8787bd846..10ab7b246cd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -157,7 +157,7 @@ fn get_path_separator(codemap: &CodeMap, if c == ':' { return "::" } else if c.is_whitespace() || c == '<' { - continue; + continuecontinue } else { return ""; } @@ -235,7 +235,7 @@ fn rewrite_segment(segment: &ast::PathSegment, ast::PathParameters::ParenthesizedParameters(ref data) => { let output = match data.output { Some(ref ty) => format!(" -> {}", pprust::ty_to_string(&*ty)), - None => String::new() + None => String::new(), }; let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap); @@ -267,7 +267,7 @@ fn rewrite_segment(segment: &ast::PathSegment, format!("({}){}", write_list(&items.collect::>(), &fmt), output) } - _ => String::new() + _ => String::new(), }; Some(format!("{}{}", segment.identifier, params)) @@ -278,57 +278,57 @@ impl Rewrite for ast::WherePredicate { // TODO dead spans? // TODO assumes we'll always fit on one line... Some(match self { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, ref bounded_ty, ref bounds, ..}) => { - if bound_lifetimes.len() > 0 { - let lifetime_str = bound_lifetimes.iter().map(|lt| { + if bound_lifetimes.len() > 0 { + let lifetime_str = bound_lifetimes.iter().map(|lt| { lt.rewrite(context, width, offset).unwrap() }).collect::>().join(", "); - let type_str = pprust::ty_to_string(bounded_ty); + let type_str = pprust::ty_to_string(bounded_ty); // 8 = "for<> : ".len() - let used_width = lifetime_str.len() + type_str.len() + 8; - let bounds_str = bounds.iter().map(|ty_bound| { + let used_width = lifetime_str.len() + type_str.len() + 8; + let bounds_str = bounds.iter().map(|ty_bound| { ty_bound.rewrite(context, width - used_width, offset + used_width) .unwrap() }).collect::>().join(" + "); - format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) - } else { - let type_str = pprust::ty_to_string(bounded_ty); + format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) + } else { + let type_str = pprust::ty_to_string(bounded_ty); // 2 = ": ".len() - let used_width = type_str.len() + 2; - let bounds_str = bounds.iter().map(|ty_bound| { + let used_width = type_str.len() + 2; + let bounds_str = bounds.iter().map(|ty_bound| { ty_bound.rewrite(context, width - used_width, offset + used_width) .unwrap() }).collect::>().join(" + "); - format!("{}: {}", type_str, bounds_str) + format!("{}: {}", type_str, bounds_str) + } } - } - &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { - format!("{}: {}", + format!("{}: {}", pprust::lifetime_to_string(lifetime), bounds.iter().map(pprust::lifetime_to_string) .collect::>().join(" + ")) - } - &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - let ty_str = pprust::ty_to_string(ty); + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + let ty_str = pprust::ty_to_string(ty); // 3 = " = ".len() - let used_width = 3 + ty_str.len(); - let path_str = try_opt!(path.rewrite(context, + let used_width = 3 + ty_str.len(); + let path_str = try_opt!(path.rewrite(context, width - used_width, offset + used_width)); - format!("{} = {}", path_str, ty_str) - } - }) + format!("{} = {}", path_str, ty_str) + } + }) } } diff --git a/src/utils.rs b/src/utils.rs index f80e1185bae..a8f7a7c7b1d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -21,7 +21,7 @@ pub fn extra_offset(text: &str, offset: usize) -> usize { match text.rfind('\n') { // 1 for newline character Some(idx) => text.len() - idx - 1 - offset, - None => text.len() + None => text.len(), } } @@ -70,7 +70,7 @@ pub fn make_indent(width: usize) -> String { pub fn format_visibility(vis: Visibility) -> &'static str { match vis { Visibility::Public => "pub ", - Visibility::Inherited => "" + Visibility::Inherited => "", } } @@ -78,7 +78,7 @@ pub fn format_visibility(vis: Visibility) -> &'static str { pub fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { ast::Mutability::MutMutable => "mut ", - ast::Mutability::MutImmutable => "" + ast::Mutability::MutImmutable => "", } } diff --git a/src/visitor.rs b/src/visitor.rs index e107a32abf8..86b1197822b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -351,7 +351,7 @@ impl<'a> FmtVisitor<'a> { let prev_span = codemap::mk_sp(self.last_pos, span.lo); let span_end = match self.snippet(prev_span).rfind('\n') { Some(offset) => self.last_pos + BytePos(offset as u32), - None => span.lo + None => span.lo, }; self.format_missing(span_end); self.last_pos = span.hi; -- cgit 1.4.1-3-g733a5 From ae1eec81af19fae54b7417148f841675d2ccf770 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 17 Aug 2015 09:41:45 +1200 Subject: Rewrite match expressions (continued). --- src/expr.rs | 105 +++++++++++++++++++++++++++++++++++++++++++------- src/utils.rs | 2 +- tests/target/match.rs | 13 ++++++- 3 files changed, 103 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index db646dafaba..face73d72f0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -113,7 +113,7 @@ impl Rewrite for ast::Expr { impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let user_str = context.codemap.span_to_snippet(self.span).unwrap(); - if user_str == "{}" && width > 1 { + if user_str == "{}" && width >= 2 { return Some(user_str); } @@ -316,7 +316,9 @@ fn rewrite_match(context: &RewriteContext, width: usize, offset: usize) -> Option { - // TODO comments etc. (I am somewhat surprised we don't need handling for these). + if arms.len() == 0 { + return None; + } // `match `cond` {` let cond_str = try_opt!(cond.rewrite(context, width - 8, offset + 6)); @@ -326,28 +328,101 @@ fn rewrite_match(context: &RewriteContext, let nested_context = context.nested_context(); let arm_indent_str = make_indent(nested_context.block_indent); - for arm in arms { + let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), + "{", + context.codemap); + + for (i, arm) in arms.iter().enumerate() { + // Make sure we get the stuff between arms. + let missed_str = if i == 0 { + context.codemap.span_to_snippet(mk_sp(open_brace_pos + BytePos(1), + arm_start_pos(arm))).unwrap() + } else { + context.codemap.span_to_snippet(mk_sp(arm_end_pos(&arms[i-1]), + arm_start_pos(arm))).unwrap() + }; + let missed_str = match missed_str.find_uncommented(",") { + Some(n) => &missed_str[n+1..], + None => &missed_str[..], + }; + // first = first non-whitespace byte index. + let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or(missed_str.len()); + if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { + // There were multiple line breaks which got trimmed to nothing + // that means there should be some vertical white space. Lets + // replace that with just one blank line. + result.push('\n'); + } + let missed_str = missed_str.trim(); + if missed_str.len() > 0 { + result.push('\n'); + result.push_str(&arm_indent_str); + result.push_str(missed_str); + } result.push('\n'); result.push_str(&arm_indent_str); - result.push_str(&&try_opt!(arm.rewrite(&nested_context, - context.config.max_width - - nested_context.block_indent, - nested_context.block_indent))); + + let arm_str = arm.rewrite(&nested_context, + context.config.max_width - + nested_context.block_indent, + nested_context.block_indent); + if let Some(ref arm_str) = arm_str { + result.push_str(arm_str); + } else { + // We couldn't format the arm, just reproduce the source. + let snippet = context.codemap.span_to_snippet(mk_sp(arm_start_pos(arm), + arm_end_pos(arm))).unwrap(); + result.push_str(&snippet); + } } + // We'll miss any comments etc. between the last arm and the end of the + // match expression, but meh. + result.push('\n'); result.push_str(&make_indent(block_indent)); result.push('}'); Some(result) } +fn arm_start_pos(arm: &ast::Arm) -> BytePos { + let &ast::Arm { ref attrs, ref pats, .. } = arm; + if attrs.len() > 0 { + return attrs[0].span.lo + } + + pats[0].span.lo +} + +fn arm_end_pos(arm: &ast::Arm) -> BytePos { + arm.body.span.hi +} + // Match arms. impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; let indent_str = make_indent(offset); - // TODO attrs + // FIXME this is all a bit grotty, would be nice to abstract out the + // treatment of attributes. + let attr_str = if attrs.len() > 0 { + // We only use this visitor for the attributes, should we use it for + // more? + let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config); + attr_visitor.block_indent = context.block_indent; + attr_visitor.last_pos = attrs[0].span.lo; + if attr_visitor.visit_attrs(attrs) { + // Attributes included a skip instruction. + let snippet = context.codemap.span_to_snippet(mk_sp(attrs[0].span.lo, + body.span.hi)).unwrap(); + return Some(snippet); + } + attr_visitor.format_missing(pats[0].span.lo); + attr_visitor.buffer.to_string() + } else { + String::new() + }; // Patterns let pat_strs = pats.iter().map(|p| p.rewrite(context, @@ -393,9 +468,6 @@ impl Rewrite for ast::Arm { pats_str.push_str(&p); } - // TODO probably want to compute the guard width first, then the rest - // TODO also, only subtract the guard width from the last pattern. - // If guard. let guard_str = try_opt!(rewrite_guard(context, guard, width, offset, pats_width)); let pats_str = format!("{}{}", pats_str, guard_str); @@ -419,13 +491,17 @@ impl Rewrite for ast::Arm { budget, offset + context.config.tab_spaces) { if first_line_width(body_str) <= budget { - return Some(format!("{} => {}{}", pats_str, body_str, comma)); + return Some(format!("{}{} => {}{}", + attr_str.trim_left(), + pats_str, + body_str, + comma)); } } } // We have to push the body to the next line. - if comma.len() > 0 { + if comma.len() == 0 { // We're trying to fit a block in, but it still failed, give up. return None; } @@ -433,7 +509,8 @@ impl Rewrite for ast::Arm { let body_str = try_opt!(body.rewrite(context, width - context.config.tab_spaces, offset + context.config.tab_spaces)); - Some(format!("{} =>\n{}{}", + Some(format!("{}{} =>\n{}{},", + attr_str.trim_left(), pats_str, make_indent(offset + context.config.tab_spaces), body_str)) diff --git a/src/utils.rs b/src/utils.rs index a8f7a7c7b1d..00e18c3a65b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -95,7 +95,7 @@ pub fn first_line_width(s: &str) -> usize { #[inline] pub fn last_line_width(s: &str) -> usize { match s.rfind('\n') { - Some(n) => s.len() - n, + Some(n) => s.len() - n - 1, None => s.len(), } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 9d8a484028b..04bc7c87127 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -28,15 +28,24 @@ fn foo() { Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, Patternnnnnnnnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnnnnnnnn - if looooooooooooooooooooooooooooooooooooooooong_guard => meh, + Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => + meh, + + // Test that earlier patterns can take the guard space + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} + _ => {} } let whatever = match something { /// DOC COMMENT! Some(_) => 42, + // COmment on an attribute. #[an_attribute] + // Comment after an attribute. None => 0, + #[rustfmt_skip] + Blurb => { } }; } -- cgit 1.4.1-3-g733a5 From 81f2e449d7b31652e08722f85d44dcc1b31694c6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 16 Aug 2015 16:43:59 +1200 Subject: Handle span error with `continue` This should be properly addressed by #184, but requires a change to the rustc parser, so this patch just works around the issue. --- src/expr.rs | 10 ++++++++++ src/lib.rs | 5 ++++- tests/source/loop.rs | 3 +++ tests/target/loop.rs | 3 +++ 4 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index face73d72f0..2e526895e25 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -105,6 +105,16 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprPath(ref qself, ref path) => { rewrite_path(context, qself.as_ref(), path, width, offset) } + // FIXME #184 Note that this formatting is broken due to a bad span + // from the parser. + // `continue` + ast::Expr_::ExprAgain(ref opt_ident) => { + let id_str = match *opt_ident { + Some(ident) => format!(" {}", ident), + None => String::new(), + }; + Some(format!("continue{}", id_str)) + } _ => context.codemap.span_to_snippet(self.span).ok(), } } diff --git a/src/lib.rs b/src/lib.rs index 9ec401b129d..11d9e76bac8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,8 @@ #![feature(rustc_private)] #![feature(str_escape)] #![feature(str_char)] - +#![feature(custom_attribute)] +#![allow(unused_attributes)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? @@ -227,6 +228,8 @@ fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> FileMap { // Formatting done on a char by char or line by line basis. // TODO warn on bad license // TODO other stuff for parity with make tidy +// FIXME skipping due to `continue`, #184. +#[rustfmt_skip] fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; diff --git a/tests/source/loop.rs b/tests/source/loop.rs index 36e6ab43de8..c7f7da71831 100644 --- a/tests/source/loop.rs +++ b/tests/source/loop.rs @@ -21,5 +21,8 @@ let x = loop { do_forever(); }; while let Some(i) = x.find('s') { x.update(); + // FIXME #184 + // continue; + // continue 'foo; } } diff --git a/tests/target/loop.rs b/tests/target/loop.rs index fea5bfe2cb2..648fe826e8f 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -25,5 +25,8 @@ fn main() { while let Some(i) = x.find('s') { x.update(); + // FIXME #184 + // continue; + // continue 'foo; } } -- cgit 1.4.1-3-g733a5 From df0fd0e1190c5d79bbc9c493ce739c8f8416d688 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 17 Aug 2015 09:55:26 +1200 Subject: reformatting/rebasing --- src/types.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 10ab7b246cd..834548a20fc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -146,6 +146,8 @@ impl<'a> fmt::Display for SegmentParam<'a> { // We'd really rather not do this, but there doesn't seem to be an alternative // at this point. // FIXME: fails with spans containing comments with the characters < or : +// FIXME #184 skip due to continue. +#[rustfmt_skip] fn get_path_separator(codemap: &CodeMap, path_start: BytePos, segment_start: BytePos) @@ -155,7 +157,7 @@ fn get_path_separator(codemap: &CodeMap, for c in snippet.chars().rev() { if c == ':' { - return "::" + return "::"; } else if c.is_whitespace() || c == '<' { continuecontinue } else { @@ -188,9 +190,8 @@ fn rewrite_segment(segment: &ast::PathSegment, let offset = offset + ident_len; let params = match segment.parameters { - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || - data.types.len() > 0 || - data.bindings.len() > 0 => { + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || data.types.len() > 0 || + data.bindings.len() > 0 => { let param_list = data.lifetimes.iter() .map(SegmentParam::LifeTime) .chain(data.types.iter() -- cgit 1.4.1-3-g733a5 From 43ad7ad7a0f6139c25606435828d835c26091fdf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 19 Aug 2015 15:15:54 +1200 Subject: Re-jig binop formatting and misc other fixes from the reviews. --- src/expr.rs | 88 +++++++++++++++++++++++++++++---------------------- src/lib.rs | 2 +- src/types.rs | 7 ++-- tests/target/expr.rs | 10 +++--- tests/target/match.rs | 6 +++- 5 files changed, 67 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2e526895e25..0cdaf060714 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -165,7 +165,7 @@ impl Rewrite for ast::Block { } } -// TODO(#18): implement pattern formatting +// FIXME(#18): implement pattern formatting impl Rewrite for ast::Pat { fn rewrite(&self, context: &RewriteContext, _: usize, _: usize) -> Option { context.codemap.span_to_snippet(self.span).ok() @@ -435,15 +435,11 @@ impl Rewrite for ast::Arm { }; // Patterns - let pat_strs = pats.iter().map(|p| p.rewrite(context, + let pat_strs = try_opt!(pats.iter().map(|p| p.rewrite(context, // 5 = ` => {` width - 5, offset + context.config.tab_spaces)) - .collect::>(); - if pat_strs.iter().any(|p| p.is_none()) { - return None; - } - let pat_strs = pat_strs.into_iter().map(|p| p.unwrap()).collect::>(); + .collect::>>()); let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); // Add ` | `.len(). @@ -488,10 +484,11 @@ impl Rewrite for ast::Arm { } let comma = if let ast::ExprBlock(_) = body.node { - String::new() + "" } else { - ",".to_owned() + "," }; + let nested_indent = context.block_indent + context.config.tab_spaces; // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() @@ -499,7 +496,7 @@ impl Rewrite for ast::Arm { let budget = context.config.max_width - line_start - comma.len() - 4; if let Some(ref body_str) = body.rewrite(context, budget, - offset + context.config.tab_spaces) { + nested_indent) { if first_line_width(body_str) <= budget { return Some(format!("{}{} => {}{}", attr_str.trim_left(), @@ -518,7 +515,7 @@ impl Rewrite for ast::Arm { let body_str = try_opt!(body.rewrite(context, width - context.config.tab_spaces, - offset + context.config.tab_spaces)); + nested_indent)); Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, @@ -533,16 +530,17 @@ fn rewrite_guard(context: &RewriteContext, width: usize, offset: usize, // The amount of space used up on this line for the pattern in - // the arm. + // the arm (excludes offset). pattern_width: usize) -> Option { if let &Some(ref guard) = guard { + // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; if overhead < width { let cond_str = guard.rewrite(context, width - overhead, - offset + context.config.tab_spaces); + offset + pattern_width + 4); if let Some(cond_str) = cond_str { return Some(format!(" if {}", cond_str)); } @@ -653,7 +651,7 @@ fn rewrite_call(context: &RewriteContext, -> Option { debug!("rewrite_call, width: {}, offset: {}", width, offset); - // TODO using byte lens instead of char lens (and probably all over the place too) + // FIXME using byte lens instead of char lens (and probably all over the place too) // 2 is for parens let max_callee_width = try_opt!(width.checked_sub(2)); let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); @@ -710,7 +708,7 @@ fn rewrite_paren(context: &RewriteContext, -> Option { debug!("rewrite_paren, width: {}, offset: {}", width, offset); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing - // paren on the same line as the subexpr + // paren on the same line as the subexpr. let subexpr_str = subexpr.rewrite(context, width-2, offset+1); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); subexpr_str.map(|s| format!("({})", s)) @@ -880,20 +878,6 @@ fn rewrite_binary_op(context: &RewriteContext, let operator_str = context.codemap.span_to_snippet(op.span).unwrap(); - // 1 = space between lhs expr and operator - let max_width = try_opt!(context.config.max_width.checked_sub(operator_str.len() + offset + 1)); - let mut result = try_opt!(lhs.rewrite(context, max_width, offset)); - - result.push(' '); - result.push_str(&operator_str); - - // 1 = space between operator and rhs - let used_width = result.len() + 1; - let remaining_width = match result.rfind('\n') { - Some(idx) => (offset + width + idx).checked_sub(used_width).unwrap_or(0), - None => width.checked_sub(used_width).unwrap_or(0), - }; - // Get "full width" rhs and see if it fits on the current line. This // usually works fairly well since it tends to place operands of // operations with high precendence close together. @@ -901,15 +885,45 @@ fn rewrite_binary_op(context: &RewriteContext, // Second condition is needed in case of line break not caused by a // shortage of space, but by end-of-line comments, for example. - if rhs_result.len() > remaining_width || rhs_result.contains('\n') { - result.push('\n'); - result.push_str(&make_indent(offset)); - } else { - result.push(' '); - }; + // Note that this is non-conservative, but its just to see if it's even + // worth trying to put everything on one line. + if rhs_result.len() + 2 + operator_str.len() < width && !rhs_result.contains('\n') { + // 1 = space between lhs expr and operator + if let Some(mut result) = lhs.rewrite(context, + width - 1 - operator_str.len(), + offset) { - result.push_str(&rhs_result); - Some(result) + result.push(' '); + result.push_str(&operator_str); + result.push(' '); + + let remaining_width = width.checked_sub(last_line_width(&result)).unwrap_or(0); + + if rhs_result.len() <= remaining_width { + result.push_str(&rhs_result); + return Some(result); + } + + if let Some(rhs_result) = rhs.rewrite(context, + remaining_width, + offset + result.len()) { + if rhs_result.len() <= remaining_width { + result.push_str(&rhs_result); + return Some(result); + } + } + } + } + + // We have to use multiple lines. + + // Re-evaluate the lhs because we have more space now: + let budget = try_opt!(context.config.max_width.checked_sub(offset + 1 + operator_str.len())); + Some(format!("{} {}\n{}{}", + try_opt!(lhs.rewrite(context, budget, offset)), + operator_str, + make_indent(offset), + rhs_result)) } fn rewrite_unary_op(context: &RewriteContext, diff --git a/src/lib.rs b/src/lib.rs index 11d9e76bac8..4efd919649a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -246,7 +246,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { for (c, b) in text.chars() { if c == '\r' { - continuecontinue + continue; } // Add warnings for bad todos/ fixmes diff --git a/src/types.rs b/src/types.rs index 834548a20fc..3bdb08cc0d2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -159,7 +159,7 @@ fn get_path_separator(codemap: &CodeMap, if c == ':' { return "::"; } else if c.is_whitespace() || c == '<' { - continuecontinue + continue; } else { return ""; } @@ -190,8 +190,9 @@ fn rewrite_segment(segment: &ast::PathSegment, let offset = offset + ident_len; let params = match segment.parameters { - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || data.types.len() > 0 || - data.bindings.len() > 0 => { + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => { let param_list = data.lifetimes.iter() .map(SegmentParam::LifeTime) .chain(data.types.iter() diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 356c5b7dbbd..dfbf0032011 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -5,8 +5,8 @@ fn foo() -> bool { let referenced = &5; let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + - b + c); + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + + BBBBBBBBBBBBBBBBB + b + c); //FIXME this exceeds width limit. Needs assignments reformatting let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); @@ -15,10 +15,12 @@ fn foo() -> bool { (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + - 40000 / 1002200000000 - 50000 * sqrt(-1), + 40000 / 1002200000000 - + 50000 * sqrt(-1), trivial_value); (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))); { diff --git a/tests/target/match.rs b/tests/target/match.rs index 04bc7c87127..e5f1fad967a 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -36,12 +36,16 @@ fn foo() { Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} _ => {} + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => { + } } let whatever = match something { /// DOC COMMENT! Some(_) => 42, - // COmment on an attribute. + // Comment on an attribute. #[an_attribute] // Comment after an attribute. None => 0, -- cgit 1.4.1-3-g733a5 From 5fcd313b0841534259e578c9a0a33962f8dbeb03 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 19 Aug 2015 22:39:45 +0200 Subject: Format closures --- src/config.rs | 1 + src/default.toml | 1 + src/expr.rs | 140 ++++++++++++++++++++++++++++++++++--------- src/imports.rs | 16 ++--- src/items.rs | 77 +++++++++++------------- src/lists.rs | 14 +++++ src/types.rs | 25 ++------ tests/config/small_tabs.toml | 1 + tests/source/closure.rs | 30 ++++++++++ tests/target/closure.rs | 48 +++++++++++++++ tests/target/comments-fn.rs | 2 +- 11 files changed, 255 insertions(+), 100 deletions(-) create mode 100644 tests/source/closure.rs create mode 100644 tests/target/closure.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 357f99a6097..341f1d45afd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -78,4 +78,5 @@ create_config! { report_fixme: ReportTactic, reorder_imports: bool, // Alphabetically, case sensitive. expr_indent_style: BlockIndentStyle, + closure_indent_style: BlockIndentStyle, } diff --git a/src/default.toml b/src/default.toml index 035fa21e917..5792079a407 100644 --- a/src/default.toml +++ b/src/default.toml @@ -14,3 +14,4 @@ report_todo = "Always" report_fixme = "Never" reorder_imports = false expr_indent_style = "Tabbed" +closure_indent_style = "Visual" diff --git a/src/expr.rs b/src/expr.rs index 0cdaf060714..af6e9ce1e35 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -17,6 +17,7 @@ use visitor::FmtVisitor; use config::BlockIndentStyle; use comment::{FindUncommented, rewrite_comment}; use types::rewrite_path; +use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; use syntax::{ast, ptr}; use syntax::codemap::{Pos, Span, BytePos, mk_sp}; @@ -115,11 +116,98 @@ impl Rewrite for ast::Expr { }; Some(format!("continue{}", id_str)) } + ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { + rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) + } _ => context.codemap.span_to_snippet(self.span).ok(), } } } +// This functions is pretty messy because of the wrapping and unwrapping of +// expressions into and from blocks. See rust issue #27872. +fn rewrite_closure(capture: ast::CaptureClause, + fn_decl: &ast::FnDecl, + body: &ast::Block, + span: Span, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option { + let mover = if capture == ast::CaptureClause::CaptureByValue { + "move " + } else { + "" + }; + let offset = offset + mover.len(); + + // 4 = "|| {".len(), which is overconservative when the closure consists of + // a single expression. + let argument_budget = try_opt!(width.checked_sub(4 + mover.len())); + // 1 = | + let argument_offset = offset + 1; + + let arg_items = itemize_list(context.codemap, + fn_decl.inputs.iter(), + "|", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(arg), + |arg| rewrite_fn_input(arg), + span_after(span, "|", context.codemap), + body.span.lo); + + let fmt = ListFormatting::for_fn(argument_budget, argument_offset); + let prefix = format!("{}|{}|", mover, write_list(&arg_items.collect::>(), &fmt)); + let block_indent = closure_block_indent(context, offset); + + let body_rewrite = if body.stmts.is_empty() { + let expr = body.expr.as_ref().unwrap(); + // All closure bodies are blocks in the eyes of the AST, but we may not + // want to unwrap them when they only contain a single expression. + let inner_expr = match expr.node { + ast::Expr_::ExprBlock(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() => { + inner.expr.as_ref().unwrap() + } + _ => expr, + }; + + // 1 = the separating space between arguments and the body. + let extra_offset = extra_offset(&prefix, offset) + 1; + let rewrite = inner_expr.rewrite(context, width - extra_offset, offset + extra_offset); + + // Checks if rewrite succeeded and fits on a single line. + let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false); + + if accept_rewrite { + rewrite + } else { + if let ast::Expr_::ExprBlock(ref inner_body) = expr.node { + // Closure body is a proper block, with braces and all. + let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; + inner_body.rewrite(inner_context, 0, 0) + } else { + // Closure body is an expression, but not a block. It does not + // fit a single line, so we format it as it were wrapped in a + // block. + let inner_context = &RewriteContext { + block_indent: block_indent + context.config.tab_spaces, + ..*context + }; + let indent = offset + context.config.tab_spaces; + expr.rewrite(inner_context, context.config.max_width - indent, indent) + .map(|result| { + format!("{{\n{}{}\n{}}}", make_indent(indent), result, make_indent(offset)) + }) + } + } + } else { + let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; + body.rewrite(inner_context, 0, 0) + }; + + Some(format!("{} {}", prefix, try_opt!(body_rewrite))) +} + impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let user_str = context.codemap.span_to_snippet(self.span).unwrap(); @@ -674,21 +762,14 @@ fn rewrite_call(context: &RewriteContext, |item| item.span.lo, |item| item.span.hi, // Take old span when rewrite fails. - |item| item.rewrite(inner_context, remaining_width, offset) - .unwrap_or(context.codemap.span_to_snippet(item.span) - .unwrap()), + |item| { + item.rewrite(inner_context, remaining_width, offset) + .unwrap_or(context.codemap.span_to_snippet(item.span).unwrap()) + }, callee.span.hi + BytePos(1), span.hi); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: remaining_width, - v_width: remaining_width, - ends_with_newline: false, - }; + let fmt = ListFormatting::for_fn(remaining_width, offset); Some(format!("{}({})", callee_str, write_list(&items.collect::>(), &fmt))) } @@ -701,6 +782,15 @@ fn expr_block_indent(context: &RewriteContext, offset: usize) -> usize { } } +// FIXME: Code duplication; is there a better solution? +fn closure_block_indent(context: &RewriteContext, offset: usize) -> usize { + match context.config.closure_indent_style { + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Tabbed => context.block_indent + context.config.tab_spaces, + BlockIndentStyle::Visual => offset, + } +} + fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, @@ -760,13 +850,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => field.span.lo, // 2 = .. - StructLitField::Base(ref expr) => expr.span.lo - BytePos(2) + StructLitField::Base(ref expr) => expr.span.lo - BytePos(2), } }, |item| { match *item { StructLitField::Regular(ref field) => field.span.hi, - StructLitField::Base(ref expr) => expr.span.hi + StructLitField::Base(ref expr) => expr.span.hi, } }, |item| { @@ -775,7 +865,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, rewrite_field(inner_context, &field, h_budget, indent) .unwrap_or(context.codemap.span_to_snippet(field.span) .unwrap()) - }, + } StructLitField::Base(ref expr) => { // 2 = .. expr.rewrite(inner_context, h_budget - 2, indent + 2) @@ -846,23 +936,15 @@ fn rewrite_tuple_lit(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - |item| item.rewrite(context, - context.config.max_width - indent - 1, - indent) - .unwrap_or(context.codemap.span_to_snippet(item.span) - .unwrap()), + |item| { + let inner_width = context.config.max_width - indent - 1; + item.rewrite(context, inner_width, indent) + .unwrap_or(context.codemap.span_to_snippet(item.span).unwrap()) + }, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - h_width: width - 2, - v_width: width - 2, - ends_with_newline: false, - }; + let fmt = ListFormatting::for_fn(width - 2, indent); Some(format!("({})", write_list(&items.collect::>(), &fmt))) } diff --git a/src/imports.rs b/src/imports.rs index 7d7300fb562..a0ba88de6f2 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -117,13 +117,15 @@ pub fn rewrite_use_list(width: usize, "}", |vpi| vpi.span.lo, |vpi| vpi.span.hi, - |vpi| match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => { - name.to_string() - } - ast::PathListItem_::PathListMod{ .. } => { - "self".to_owned() - } + |vpi| { + match vpi.node { + ast::PathListItem_::PathListIdent{ name, .. } => { + name.to_string() + } + ast::PathListItem_::PathListMod{ .. } => { + "self".to_owned() + } + } }, span_after(span, "{", context.codemap), span.hi); diff --git a/src/items.rs b/src/items.rs index 79d374f85ec..e853dc90c30 100644 --- a/src/items.rs +++ b/src/items.rs @@ -232,7 +232,7 @@ impl<'a> FmtVisitor<'a> { arg_indent: usize, span: Span) -> String { - let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect(); + let mut arg_item_strs: Vec<_> = args.iter().map(rewrite_fn_input).collect(); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. @@ -512,13 +512,12 @@ impl<'a> FmtVisitor<'a> { struct_def.fields.iter(), terminator, |field| { - // Include attributes and doc comments, - // if present - if field.node.attrs.len() > 0 { - field.node.attrs[0].span.lo - } else { - field.span.lo - } + // Include attributes and doc comments, if present + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo + } else { + field.span.lo + } }, |field| field.node.ty.span.hi, |field| self.format_field(field), @@ -650,16 +649,14 @@ impl<'a> FmtVisitor<'a> { fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span) -> String { // FIXME convert bounds to where clauses where they get too big or if // there is a where clause at all. - let mut result = String::new(); let lifetimes: &[_] = &generics.lifetimes; let tys: &[_] = &generics.ty_params; if lifetimes.len() + tys.len() == 0 { - return result; + return String::new(); } let budget = self.config.max_width - offset - 2; // TODO might need to insert a newline if the generics are really long - result.push('<'); // Strings for the generics. // 1 = < @@ -697,20 +694,9 @@ impl<'a> FmtVisitor<'a> { item.item = ty; } - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset + 1, - h_width: budget, - v_width: budget, - ends_with_newline: false, - }; - result.push_str(&write_list(&items, &fmt)); - - result.push('>'); + let fmt = ListFormatting::for_fn(budget, offset + 1); - result + format!("<{}>", write_list(&items, &fmt)) } fn rewrite_where_clause(&self, @@ -719,15 +705,10 @@ impl<'a> FmtVisitor<'a> { indent: usize, span_end: BytePos) -> String { - let mut result = String::new(); if where_clause.predicates.len() == 0 { - return result; + return String::new(); } - result.push('\n'); - result.push_str(&make_indent(indent + config.tab_spaces)); - result.push_str("where "); - let context = self.get_context(); // 6 = "where ".len() let offset = indent + config.tab_spaces + 6; @@ -752,11 +733,12 @@ impl<'a> FmtVisitor<'a> { indent: offset, h_width: budget, v_width: budget, - ends_with_newline: false, + ends_with_newline: true, }; - result.push_str(&write_list(&items.collect::>(), &fmt)); - result + format!("\n{}where {}", + make_indent(indent + config.tab_spaces), + write_list(&items.collect::>(), &fmt)) } fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { @@ -766,17 +748,21 @@ impl<'a> FmtVisitor<'a> { ast::FunctionRetTy::Return(ref ty) => "-> ".to_owned() + &pprust::ty_to_string(ty), } } +} - // TODO we farm this out, but this could spill over the column limit, so we - // ought to handle it properly. - fn rewrite_fn_input(&self, arg: &ast::Arg) -> String { - if is_named_arg(arg) { - format!("{}: {}", - pprust::pat_to_string(&arg.pat), - pprust::ty_to_string(&arg.ty)) +// TODO we farm this out, but this could spill over the column limit, so we +// ought to handle it properly. +pub fn rewrite_fn_input(arg: &ast::Arg) -> String { + if is_named_arg(arg) { + if let ast::Ty_::TyInfer = arg.ty.node { + pprust::pat_to_string(&arg.pat) } else { - pprust::ty_to_string(&arg.ty) + format!("{}: {}", + pprust::pat_to_string(&arg.pat), + pprust::ty_to_string(&arg.ty)) } + } else { + pprust::ty_to_string(&arg.ty) } } @@ -810,7 +796,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) - } } -fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { +pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { if is_named_arg(arg) { arg.pat.span.lo } else { @@ -818,6 +804,13 @@ fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { } } +pub fn span_hi_for_arg(arg: &ast::Arg) -> BytePos { + match arg.ty.node { + ast::Ty_::TyInfer if is_named_arg(arg) => arg.pat.span.hi, + _ => arg.ty.span.hi, + } +} + fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::Pat_::PatIdent(_, ident, _) = arg.pat.node { ident.node != token::special_idents::invalid diff --git a/src/lists.rs b/src/lists.rs index eadefe2e0fb..dd1a489b847 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -52,6 +52,20 @@ pub struct ListFormatting<'a> { pub ends_with_newline: bool, } +impl<'a> ListFormatting<'a> { + pub fn for_fn(width: usize, offset: usize) -> ListFormatting<'a> { + ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: width, + v_width: width, + ends_with_newline: false, + } + } +} + pub struct ListItem { pub pre_comment: Option, // Item should include attributes and doc comments diff --git a/src/types.rs b/src/types.rs index 3bdb08cc0d2..fa3d61603b8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -14,7 +14,7 @@ use syntax::ast; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; -use lists::{itemize_list, write_list, ListTactic, SeparatorTactic, ListFormatting}; +use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after}; @@ -218,16 +218,7 @@ fn rewrite_segment(segment: &ast::PathSegment, let extra_offset = 1 + separator.len(); // 1 for > let list_width = try_opt!(width.checked_sub(extra_offset + 1)); - - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset + extra_offset, - h_width: list_width, - v_width: list_width, - ends_with_newline: false, - }; + let fmt = ListFormatting::for_fn(list_width, offset + extra_offset); // update pos *span_lo = next_span_lo; @@ -253,16 +244,8 @@ fn rewrite_segment(segment: &ast::PathSegment, // 2 for () let budget = try_opt!(width.checked_sub(output.len() + 2)); - let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - // 1 for ( - indent: offset + 1, - h_width: budget, - v_width: budget, - ends_with_newline: false, - }; + // 1 for ( + let fmt = ListFormatting::for_fn(budget, offset + 1); // update pos *span_lo = data.inputs.last().unwrap().span.hi + BytePos(1); diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index b2c7f5fc43f..2aff85506a4 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -14,3 +14,4 @@ report_todo = "Always" report_fixme = "Never" reorder_imports = false expr_indent_style = "Tabbed" +closure_indent_style = "Visual" diff --git a/tests/source/closure.rs b/tests/source/closure.rs new file mode 100644 index 00000000000..292cef376dd --- /dev/null +++ b/tests/source/closure.rs @@ -0,0 +1,30 @@ +// Closures + +fn main() { + let square = ( |i: i32 | i * i ); + + let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // TODO(#27): format comments. + if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo + } else { + field.span.lo + }}; + + let block_me = |field| if true_story() { 1 } else { 2 }; + + let unblock_me = |trivial| { + closure() + }; + + let empty = |arg| {}; +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs new file mode 100644 index 00000000000..7ebfbf12521 --- /dev/null +++ b/tests/target/closure.rs @@ -0,0 +1,48 @@ +// Closures + +fn main() { + let square = (|i: i32| i * i); + + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| { + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) + }; + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // TODO(#27): format comments. + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }; + + let block_me = |field| { + if true_story() { + 1 + } else { + 2 + } + }; + + let unblock_me = |trivial| closure(); + + let empty = |arg| {}; +} diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 0b21d84074a..57b6ae63381 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -11,7 +11,7 @@ fn foo(a: aaaaaaaaaaaaa, // A comment e: eeeeeeeeeeeee /* comment before paren */) -> bar where F: Foo, // COmment after where clause - G: Goo /* final comment */ + G: Goo // final comment { } -- cgit 1.4.1-3-g733a5 From c8fd23ca6822477199542d6d1f153da0d41fa629 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 20 Aug 2015 23:05:41 +0200 Subject: Refactor closure formatting routine --- src/expr.rs | 32 ++++++++++---------------------- src/visitor.rs | 15 ++++++++++++--- tests/source/closure.rs | 4 ++++ tests/target/closure.rs | 8 ++++++++ 4 files changed, 34 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index af6e9ce1e35..6ed8470fbea 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -160,7 +160,8 @@ fn rewrite_closure(capture: ast::CaptureClause, let prefix = format!("{}|{}|", mover, write_list(&arg_items.collect::>(), &fmt)); let block_indent = closure_block_indent(context, offset); - let body_rewrite = if body.stmts.is_empty() { + // Try to format closure body as a single line expression without braces. + if body.stmts.is_empty() { let expr = body.expr.as_ref().unwrap(); // All closure bodies are blocks in the eyes of the AST, but we may not // want to unwrap them when they only contain a single expression. @@ -179,29 +180,16 @@ fn rewrite_closure(capture: ast::CaptureClause, let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false); if accept_rewrite { - rewrite - } else { - if let ast::Expr_::ExprBlock(ref inner_body) = expr.node { - // Closure body is a proper block, with braces and all. - let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; - inner_body.rewrite(inner_context, 0, 0) - } else { - // Closure body is an expression, but not a block. It does not - // fit a single line, so we format it as it were wrapped in a - // block. - let inner_context = &RewriteContext { - block_indent: block_indent + context.config.tab_spaces, - ..*context - }; - let indent = offset + context.config.tab_spaces; - expr.rewrite(inner_context, context.config.max_width - indent, indent) - .map(|result| { - format!("{{\n{}{}\n{}}}", make_indent(indent), result, make_indent(offset)) - }) - } + return Some(format!("{} {}", prefix, rewrite.unwrap())); } + } + + // We couldn't format the closure body as a single line expression; fall + // back to block formatting. + let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; + let body_rewrite = if let ast::Expr_::ExprBlock(ref inner) = body.expr.as_ref().unwrap().node { + inner.rewrite(inner_context, 0, 0) } else { - let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; body.rewrite(inner_context, 0, 0) }; diff --git a/src/visitor.rs b/src/visitor.rs index 86b1197822b..2489a8c1a9d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -68,9 +68,18 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(b.span.lo), self.codemap.lookup_char_pos(b.span.hi)); - self.buffer.push_str("{"); - self.last_pos = self.last_pos + BytePos(1); + // Check if this block has braces. + let snippet = self.snippet(b.span); + let has_braces = snippet.chars().next().unwrap() == '{' || &snippet[..6] == "unsafe"; + let brace_compensation = if has_braces { + BytePos(1) + } else { + BytePos(0) + }; + + self.last_pos = self.last_pos + brace_compensation; self.block_indent += self.config.tab_spaces; + self.buffer.push_str("{"); for stmt in &b.stmts { self.visit_stmt(&stmt) @@ -86,7 +95,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent -= self.config.tab_spaces; // TODO we should compress any newlines here to just one - self.format_missing_with_indent(b.span.hi - BytePos(1)); + self.format_missing_with_indent(b.span.hi - brace_compensation); self.buffer.push_str("}"); self.last_pos = b.span.hi; } diff --git a/tests/source/closure.rs b/tests/source/closure.rs index e7d54716e4c..06b10758011 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -30,6 +30,10 @@ fn main() { let test = | | { do_something(); do_something_else(); }; + let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; arg2 * arg1 - temp } } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index e25549b1079..5042f1d037a 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -51,6 +51,14 @@ fn main() { do_something_else(); }; + let arg_test = |big_argument_name, test123| { + looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() + }; + + let arg_test = |big_argument_name, test123| { + looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() + }; + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; arg2 * arg1 - temp -- cgit 1.4.1-3-g733a5 From e0ae162ae12a5efa93739895e41a62893807a2ea Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 21 Aug 2015 12:57:17 +0200 Subject: Reduce code duplication for block indentation helpers --- src/expr.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6ed8470fbea..b8f94230c23 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -762,22 +762,20 @@ fn rewrite_call(context: &RewriteContext, Some(format!("{}({})", callee_str, write_list(&items.collect::>(), &fmt))) } -fn expr_block_indent(context: &RewriteContext, offset: usize) -> usize { - match context.config.expr_indent_style { - BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Tabbed => context.block_indent + context.config.tab_spaces, - BlockIndentStyle::Visual => offset, - } +macro_rules! block_indent_helper { + ($name:ident, $option:ident) => ( + fn $name(context: &RewriteContext, offset: usize) -> usize { + match context.config.$option { + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Tabbed => context.block_indent + context.config.tab_spaces, + BlockIndentStyle::Visual => offset, + } + } + ); } -// FIXME: Code duplication; is there a better solution? -fn closure_block_indent(context: &RewriteContext, offset: usize) -> usize { - match context.config.closure_indent_style { - BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Tabbed => context.block_indent + context.config.tab_spaces, - BlockIndentStyle::Visual => offset, - } -} +block_indent_helper!(expr_block_indent, expr_indent_style); +block_indent_helper!(closure_block_indent, closure_indent_style); fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, -- cgit 1.4.1-3-g733a5 From 150c333e6cb9b86ed307c3e1ceb8b71abf6de298 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 21 Aug 2015 16:28:32 +0200 Subject: Fix bug in path formatting --- src/types.rs | 4 ++-- tests/source/structs.rs | 6 ++++++ tests/target/structs.rs | 12 ++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 3bdb08cc0d2..6df5a788b1e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -240,7 +240,7 @@ fn rewrite_segment(segment: &ast::PathSegment, None => String::new(), }; - let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap); + let list_lo = span_after(data.span, "(", context.codemap); let items = itemize_list(context.codemap, data.inputs.iter(), ")", @@ -265,7 +265,7 @@ fn rewrite_segment(segment: &ast::PathSegment, }; // update pos - *span_lo = data.inputs.last().unwrap().span.hi + BytePos(1); + *span_lo = data.span.hi + BytePos(1); format!("({}){}", write_list(&items.collect::>(), &fmt), output) } diff --git a/tests/source/structs.rs b/tests/source/structs.rs index ace13fe2889..68c7ff0df3c 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -68,3 +68,9 @@ struct Tuple( A, //Comment B ); + +pub struct State time::Timespec> { now: F } + +pub struct State ()> { now: F } + +pub struct State { now: F } diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 84b7334008d..1f48c66b6a4 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -65,3 +65,15 @@ struct Baz { // Will this be a one-liner? struct Tuple(A /* Comment */, B); + +pub struct State time::Timespec> { + now: F, +} + +pub struct State ()> { + now: F, +} + +pub struct State { + now: F, +} -- cgit 1.4.1-3-g733a5 From 5047091f087cc5410750898e24ccf337e79e4afb Mon Sep 17 00:00:00 2001 From: Léo Stefanesco Date: Fri, 21 Aug 2015 19:13:46 +0200 Subject: Don't format raw strings --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b8f94230c23..c849d58efae 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -28,7 +28,7 @@ impl Rewrite for ast::Expr { match self.node { ast::Expr_::ExprLit(ref l) => { match l.node { - ast::Lit_::LitStr(ref is, _) => { + ast::Lit_::LitStr(ref is, ast::StrStyle::CookedStr) => { rewrite_string_lit(context, &is, l.span, width, offset) } _ => context.codemap.span_to_snippet(self.span).ok(), -- cgit 1.4.1-3-g733a5 From 49cae9c48566a37dd4e8bcab69c8598dc0343ee9 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Sat, 22 Aug 2015 18:08:11 -0400 Subject: Fix https://github.com/nrc/rustfmt/issues/190 --- src/missed_spans.rs | 4 ++++ tests/target/no_new_line_beginning.rs | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 tests/target/no_new_line_beginning.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 64025550410..aa1d4679e9a 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -43,6 +43,10 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(end)); if start == end { + // Do nothing if this is the beginning of the file. + if start == BytePos(0) { + return; + } process_last_snippet(self, "", ""); return; } diff --git a/tests/target/no_new_line_beginning.rs b/tests/target/no_new_line_beginning.rs new file mode 100644 index 00000000000..f79c691f085 --- /dev/null +++ b/tests/target/no_new_line_beginning.rs @@ -0,0 +1,2 @@ +fn main() { +} -- cgit 1.4.1-3-g733a5 From 76ea7e3b643a85aee4bec55a3a840edb5295819d Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Mon, 24 Aug 2015 22:01:01 +0200 Subject: Fix #190 for submodules --- src/missed_spans.rs | 2 +- tests/source/mod-2.rs | 1 + tests/source/no_new_line_beginning.rs | 2 ++ tests/target/mod-2.rs | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 tests/source/no_new_line_beginning.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index aa1d4679e9a..33d096c3ba0 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -44,7 +44,7 @@ impl<'a> FmtVisitor<'a> { if start == end { // Do nothing if this is the beginning of the file. - if start == BytePos(0) { + if start == self.codemap.lookup_char_pos(start).file.start_pos { return; } process_last_snippet(self, "", ""); diff --git a/tests/source/mod-2.rs b/tests/source/mod-2.rs index 75b560ce93f..c4a148a616e 100644 --- a/tests/source/mod-2.rs +++ b/tests/source/mod-2.rs @@ -1,3 +1,4 @@ // Some nested mods mod nestedmod; +mod no_new_line_beginning; diff --git a/tests/source/no_new_line_beginning.rs b/tests/source/no_new_line_beginning.rs new file mode 100644 index 00000000000..f79c691f085 --- /dev/null +++ b/tests/source/no_new_line_beginning.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/tests/target/mod-2.rs b/tests/target/mod-2.rs index 75b560ce93f..c4a148a616e 100644 --- a/tests/target/mod-2.rs +++ b/tests/target/mod-2.rs @@ -1,3 +1,4 @@ // Some nested mods mod nestedmod; +mod no_new_line_beginning; -- cgit 1.4.1-3-g733a5 From c7e6d0b54af1ae4cb14dcc4473dd819913f263a4 Mon Sep 17 00:00:00 2001 From: Ivan Apachev Date: Tue, 25 Aug 2015 00:54:47 +0300 Subject: Replace uses of x.len() == 0 by x.is_empty() #187 --- src/expr.rs | 8 ++++---- src/imports.rs | 8 ++++---- src/items.rs | 26 +++++++++++++------------- src/lists.rs | 6 +++--- src/types.rs | 14 +++++++------- src/visitor.rs | 6 +++--- 6 files changed, 34 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c849d58efae..4f58c19c8fd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -216,7 +216,7 @@ impl Rewrite for ast::Block { // Extract comment between unsafe and block start. let trimmed = &snippet[6..open_pos].trim(); - if trimmed.len() > 0 { + if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() format!("unsafe {} ", rewrite_comment(trimmed, true, width - 9, offset + 7)) } else { @@ -733,7 +733,7 @@ fn rewrite_call(context: &RewriteContext, let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); debug!("rewrite_call, callee_str: `{}`", callee_str); - if args.len() == 0 { + if args.is_empty() { return Some(format!("{}()", callee_str)); } @@ -799,7 +799,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, offset: usize) -> Option { debug!("rewrite_struct_lit: width {}, offset {}", width, offset); - assert!(fields.len() > 0 || base.is_some()); + assert!(!fields.is_empty() || base.is_some()); enum StructLitField<'a> { Regular(&'a ast::Field), @@ -1008,7 +1008,7 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::UnNeg => "-", }; - let subexpr = try_opt!(expr.rewrite(context, width - operator_str.len(), offset)); + let subexpr = try_opt!(expr.rewrite(context, try_opt!(width.checked_sub(operator_str.len())), offset)); Some(format!("{}{}", operator_str, subexpr)) } diff --git a/src/imports.rs b/src/imports.rs index a0ba88de6f2..cf9e174f9b0 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -51,13 +51,13 @@ impl Rewrite for ast::ViewPath { fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { - if path_str.len() == 0 { + if path_str.is_empty() { name.to_string() } else { format!("{}::{}", path_str, name) } } else { - if path_str.len() != 0 { + if !path_str.is_empty() { path_str } else { // This catches the import: use {self}, which is a compiler error, so we just @@ -86,7 +86,7 @@ pub fn rewrite_use_list(width: usize, } // 2 = :: - let path_separation_w = if path_str.len() > 0 { + let path_separation_w = if !path_str.is_empty() { 2 } else { 0 @@ -151,7 +151,7 @@ pub fn rewrite_use_list(width: usize, let list = write_list(&items[first_index..], &fmt); - Some(if path_str.len() == 0 { + Some(if path_str.is_empty() { format!("{{{}}}", list) } else { format!("{}::{{{}}}", path_str, list) diff --git a/src/items.rs b/src/items.rs index e853dc90c30..e39638ba427 100644 --- a/src/items.rs +++ b/src/items.rs @@ -178,7 +178,7 @@ impl<'a> FmtVisitor<'a> { result.push(')'); // Return type. - if ret_str.len() > 0 { + if !ret_str.is_empty() { // If we've already gone multi-line, or the return type would push // over the max width, then put the return type on a new line. if result.contains("\n") || @@ -200,11 +200,11 @@ impl<'a> FmtVisitor<'a> { // Comment between return type and the end of the decl. let snippet_lo = fd.output.span().hi; - if where_clause.predicates.len() == 0 { + if where_clause.predicates.is_empty() { let snippet_hi = span.hi; let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); let snippet = snippet.trim(); - if snippet.len() > 0 { + if !snippet.is_empty() { result.push(' '); result.push_str(snippet); } @@ -342,7 +342,7 @@ impl<'a> FmtVisitor<'a> { fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { match self.config.fn_brace_style { BraceStyle::AlwaysNextLine => true, - BraceStyle::SameLineWhere if where_clause.predicates.len() > 0 => true, + BraceStyle::SameLineWhere if !where_clause.predicates.is_empty() => true, _ => false, } } @@ -399,7 +399,7 @@ impl<'a> FmtVisitor<'a> { let mut result = String::new(); - if types.len() > 0 { + if !types.is_empty() { let items = itemize_list(self.codemap, types.iter(), ")", @@ -482,7 +482,7 @@ impl<'a> FmtVisitor<'a> { let header_str = self.format_header(item_name, ident, vis); result.push_str(&header_str); - if struct_def.fields.len() == 0 { + if struct_def.fields.is_empty() { result.push(';'); return result; } @@ -513,7 +513,7 @@ impl<'a> FmtVisitor<'a> { terminator, |field| { // Include attributes and doc comments, if present - if field.node.attrs.len() > 0 { + if !field.node.attrs.is_empty() { field.node.attrs[0].span.lo } else { field.span.lo @@ -602,7 +602,7 @@ impl<'a> FmtVisitor<'a> { -> String { let mut result = self.rewrite_generics(generics, offset, span); - if generics.where_clause.predicates.len() > 0 || result.contains('\n') { + if !generics.where_clause.predicates.is_empty() || result.contains('\n') { result.push_str(&self.rewrite_where_clause(&generics.where_clause, self.config, self.block_indent, @@ -635,7 +635,7 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent + self.config.tab_spaces; let mut attr_str = self.rewrite_attrs(&field.node.attrs, indent); - if attr_str.len() > 0 { + if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&make_indent(indent)); } @@ -651,7 +651,7 @@ impl<'a> FmtVisitor<'a> { // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; let tys: &[_] = &generics.ty_params; - if lifetimes.len() + tys.len() == 0 { + if lifetimes.is_empty() && tys.is_empty() { return String::new(); } @@ -671,7 +671,7 @@ impl<'a> FmtVisitor<'a> { // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.len() == 0 { + let hi = if l.bounds.is_empty() { l.lifetime.span.hi } else { l.bounds[l.bounds.len() - 1].span.hi @@ -705,7 +705,7 @@ impl<'a> FmtVisitor<'a> { indent: usize, span_end: BytePos) -> String { - if where_clause.predicates.len() == 0 { + if where_clause.predicates.is_empty() { return String::new(); } @@ -833,7 +833,7 @@ fn span_for_ty_param(ty: &ast::TyParam) -> Span { if let Some(ref def) = ty.default { return codemap::mk_sp(lo, def.span.hi); } - if ty.bounds.len() == 0 { + if ty.bounds.is_empty() { return ty.span; } let hi = match ty.bounds[ty.bounds.len() - 1] { diff --git a/src/lists.rs b/src/lists.rs index dd1a489b847..12c8d14574a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -92,7 +92,7 @@ impl ListItem { // FIXME: this has grown into a monstrosity // TODO: add unit tests pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> String { - if items.len() == 0 { + if items.is_empty() { return String::new(); } @@ -270,7 +270,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> (self.get_lo)(&item))) .unwrap(); let pre_snippet = pre_snippet.trim(); - let pre_comment = if pre_snippet.len() > 0 { + let pre_comment = if !pre_snippet.is_empty() { Some(pre_snippet.to_owned()) } else { None @@ -328,7 +328,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> post_snippet = post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space); } - let post_comment = if post_snippet.len() > 0 { + let post_comment = if !post_snippet.is_empty() { Some(post_snippet.to_owned()) } else { None diff --git a/src/types.rs b/src/types.rs index 8792580d872..5969c1e1018 100644 --- a/src/types.rs +++ b/src/types.rs @@ -190,9 +190,9 @@ fn rewrite_segment(segment: &ast::PathSegment, let offset = offset + ident_len; let params = match segment.parameters { - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || - data.types.len() > 0 || - data.bindings.len() > 0 => { + ast::PathParameters::AngleBracketedParameters(ref data) if !data.lifetimes.is_empty() || + !data.types.is_empty() || + !data.bindings.is_empty() => { let param_list = data.lifetimes.iter() .map(SegmentParam::LifeTime) .chain(data.types.iter() @@ -267,7 +267,7 @@ impl Rewrite for ast::WherePredicate { ref bounded_ty, ref bounds, ..}) => { - if bound_lifetimes.len() > 0 { + if !bound_lifetimes.is_empty() { let lifetime_str = bound_lifetimes.iter().map(|lt| { lt.rewrite(context, width, offset).unwrap() }).collect::>().join(", "); @@ -319,7 +319,7 @@ impl Rewrite for ast::WherePredicate { impl Rewrite for ast::LifetimeDef { fn rewrite(&self, _: &RewriteContext, _: usize, _: usize) -> Option { - if self.bounds.len() == 0 { + if self.bounds.is_empty() { Some(pprust::lifetime_to_string(&self.lifetime)) } else { Some(format!("{}: {}", @@ -351,7 +351,7 @@ impl Rewrite for ast::TyParam { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let mut result = String::with_capacity(128); result.push_str(&self.ident.to_string()); - if self.bounds.len() > 0 { + if !self.bounds.is_empty() { result.push_str(": "); let bounds = self.bounds.iter().map(|ty_bound| { @@ -372,7 +372,7 @@ impl Rewrite for ast::TyParam { // FIXME: this assumes everything will fit on one line impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { - if self.bound_lifetimes.len() > 0 { + if !self.bound_lifetimes.is_empty() { let lifetime_str = self.bound_lifetimes.iter().map(|lt| { lt.rewrite(context, width, offset).unwrap() }).collect::>().join(", "); diff --git a/src/visitor.rs b/src/visitor.rs index 2489a8c1a9d..fccd619d403 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -267,7 +267,7 @@ impl<'a> FmtVisitor<'a> { // Returns true if we should skip the following item. pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { - if attrs.len() == 0 { + if attrs.is_empty() { return false; } @@ -299,7 +299,7 @@ impl<'a> FmtVisitor<'a> { // with the usual doc comment token. let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; let comment = comment.trim(); - if comment.len() > 0 { + if !comment.is_empty() { result.push_str(&indent); result.push_str(comment); result.push('\n'); @@ -355,7 +355,7 @@ impl<'a> FmtVisitor<'a> { }; // 1 = ";" match vp.rewrite(&context, self.config.max_width - offset - 1, offset) { - Some(ref s) if s.len() == 0 => { + Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, span.lo); let span_end = match self.snippet(prev_span).rfind('\n') { -- cgit 1.4.1-3-g733a5 From 120fd2426e271afea0332bbbd5c408c5d0e88412 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 21 Aug 2015 13:31:09 +0200 Subject: Format assignment --- src/comment.rs | 5 +- src/expr.rs | 134 ++++++++++++++++++++++++++++++++----- src/issues.rs | 5 +- src/items.rs | 74 ++++++++++++++++++-- src/lib.rs | 2 + src/lists.rs | 17 ++--- src/visitor.rs | 42 ++++++++---- tests/source/assignment.rs | 16 +++++ tests/source/expr.rs | 11 ++- tests/source/paths.rs | 2 - tests/target/assignment.rs | 18 +++++ tests/target/expr.rs | 4 +- tests/target/multiple.rs | 4 +- tests/target/paths.rs | 2 - tests/target/string-lit.rs | 15 +++-- tests/target/struct_lits_visual.rs | 9 +-- 16 files changed, 284 insertions(+), 76 deletions(-) create mode 100644 tests/source/assignment.rs create mode 100644 tests/target/assignment.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 14ca718e318..4cee78f271d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -104,14 +104,13 @@ fn format_comments() { let input = "// comment"; let expected = "/* com\n \ - * men\n * \ - t */"; + * men\n \ + * t */"; assert_eq!(expected, rewrite_comment(input, true, 9, 69)); assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); } - pub trait FindUncommented { fn find_uncommented(&self, pat: &str) -> Option; } diff --git a/src/expr.rs b/src/expr.rs index 4f58c19c8fd..f1279d93a5a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -106,6 +106,12 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprPath(ref qself, ref path) => { rewrite_path(context, qself.as_ref(), path, width, offset) } + ast::Expr_::ExprAssign(ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, None, width, offset) + } + ast::Expr_::ExprAssignOp(ref op, ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, Some(op), width, offset) + } // FIXME #184 Note that this formatting is broken due to a bad span // from the parser. // `continue` @@ -116,10 +122,47 @@ impl Rewrite for ast::Expr { }; Some(format!("continue{}", id_str)) } + ast::Expr_::ExprBreak(ref opt_ident) => { + let id_str = match *opt_ident { + Some(ident) => format!(" {}", ident), + None => String::new(), + }; + Some(format!("break{}", id_str)) + } ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } - _ => context.codemap.span_to_snippet(self.span).ok(), + _ => { + // We do not format these expressions yet, but they should still + // satisfy our width restrictions. + let snippet = context.codemap.span_to_snippet(self.span).unwrap(); + + { + let mut lines = snippet.lines(); + + // The caller of this function has already placed `offset` + // characters on the first line. + let first_line_max_len = try_opt!(context.config.max_width.checked_sub(offset)); + if lines.next().unwrap().len() > first_line_max_len { + return None; + } + + // The other lines must fit within the maximum width. + if lines.find(|line| line.len() > context.config.max_width).is_some() { + return None; + } + + // `width` is the maximum length of the last line, excluding + // indentation. + // A special check for the last line, since the caller may + // place trailing characters on this line. + if snippet.lines().rev().next().unwrap().len() > offset + width { + return None; + } + } + + Some(snippet) + } } } } @@ -402,7 +445,7 @@ fn rewrite_match(context: &RewriteContext, width: usize, offset: usize) -> Option { - if arms.len() == 0 { + if arms.is_empty() { return None; } @@ -440,7 +483,7 @@ fn rewrite_match(context: &RewriteContext, result.push('\n'); } let missed_str = missed_str.trim(); - if missed_str.len() > 0 { + if !missed_str.is_empty() { result.push('\n'); result.push_str(&arm_indent_str); result.push_str(missed_str); @@ -473,7 +516,7 @@ fn rewrite_match(context: &RewriteContext, fn arm_start_pos(arm: &ast::Arm) -> BytePos { let &ast::Arm { ref attrs, ref pats, .. } = arm; - if attrs.len() > 0 { + if !attrs.is_empty() { return attrs[0].span.lo } @@ -492,7 +535,7 @@ impl Rewrite for ast::Arm { // FIXME this is all a bit grotty, would be nice to abstract out the // treatment of attributes. - let attr_str = if attrs.len() > 0 { + let attr_str = if !attrs.is_empty() { // We only use this visitor for the attributes, should we use it for // more? let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config); @@ -539,7 +582,7 @@ impl Rewrite for ast::Arm { let mut pats_str = String::new(); for p in pat_strs { - if pats_str.len() > 0 { + if !pats_str.is_empty() { if vertical { pats_str.push_str(" |\n"); pats_str.push_str(&indent_str); @@ -584,7 +627,7 @@ impl Rewrite for ast::Arm { } // We have to push the body to the next line. - if comma.len() == 0 { + if comma.is_empty() { // We're trying to fit a block in, but it still failed, give up. return None; } @@ -645,6 +688,8 @@ fn rewrite_pat_expr(context: &RewriteContext, pat: Option<&ast::Pat>, expr: &ast::Expr, matcher: &str, + // Connecting piece between pattern and expression, + // *without* trailing space. connector: &str, width: usize, offset: usize) @@ -665,18 +710,18 @@ fn rewrite_pat_expr(context: &RewriteContext, // The expression may (partionally) fit on the current line. if width > extra_offset + 1 { - let mut corrected_offset = extra_offset; - - if pat.is_some() { - result.push(' '); - corrected_offset += 1; - } + let spacer = if pat.is_some() { + " " + } else { + "" + }; let expr_rewrite = expr.rewrite(context, - width - corrected_offset, - offset + corrected_offset); + width - extra_offset - spacer.len(), + offset + extra_offset + spacer.len()); if let Some(expr_string) = expr_rewrite { + result.push_str(spacer); result.push_str(&expr_string); return Some(result); } @@ -810,7 +855,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let path_str = try_opt!(path.rewrite(context, width - 2, offset)); // Foo { a: Foo } - indent is +3, width is -5. - let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); + let h_budget = try_opt!(width.checked_sub(path_str.len() + 5)); let (indent, v_budget) = match context.config.struct_lit_style { StructLitStyle::VisualIndent => { (offset + path_str.len() + 3, h_budget) @@ -1008,7 +1053,62 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::UnNeg => "-", }; - let subexpr = try_opt!(expr.rewrite(context, try_opt!(width.checked_sub(operator_str.len())), offset)); + let subexpr = + try_opt!(expr.rewrite(context, try_opt!(width.checked_sub(operator_str.len())), offset)); Some(format!("{}{}", operator_str, subexpr)) } + +fn rewrite_assignment(context: &RewriteContext, + lhs: &ast::Expr, + rhs: &ast::Expr, + op: Option<&ast::BinOp>, + width: usize, + offset: usize) + -> Option { + let operator_str = match op { + Some(op) => context.codemap.span_to_snippet(op.span).unwrap(), + None => "=".to_owned(), + }; + + // 1 = space between lhs and operator. + let max_width = try_opt!(width.checked_sub(operator_str.len() + 1)); + let lhs_str = format!("{} {}", try_opt!(lhs.rewrite(context, max_width, offset)), operator_str); + + rewrite_assign_rhs(&context, lhs_str, rhs, width, offset) +} + +// The left hand side must contain everything up to, and including, the +// assignment operator. +pub fn rewrite_assign_rhs>(context: &RewriteContext, + lhs: S, + ex: &ast::Expr, + width: usize, + offset: usize) + -> Option { + let mut result = lhs.into(); + + // 1 = space between operator and rhs. + let max_width = try_opt!(width.checked_sub(result.len() + 1)); + let rhs = ex.rewrite(&context, max_width, offset + result.len() + 1); + + match rhs { + Some(new_str) => { + result.push(' '); + result.push_str(&new_str) + } + None => { + // Expression did not fit on the same line as the identifier. Retry + // on the next line. + let new_offset = offset + context.config.tab_spaces; + result.push_str(&format!("\n{}", make_indent(new_offset))); + + let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1)); + let rhs = try_opt!(ex.rewrite(&context, max_width, new_offset)); + + result.push_str(&rhs); + } + } + + Some(result) +} diff --git a/src/issues.rs b/src/issues.rs index e9f8255cc91..7d100d6db2a 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -214,10 +214,7 @@ impl BadIssueSeeker { NumberPart::CloseParen => {} } - self.state = Seeking::Number { - part: part, - issue: issue - }; + self.state = Seeking::Number { part: part, issue: issue }; IssueClassification::None } diff --git a/src/items.rs b/src/items.rs index e39638ba427..1501a904fdf 100644 --- a/src/items.rs +++ b/src/items.rs @@ -14,8 +14,10 @@ use {ReturnIndent, BraceStyle}; use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, end_typaram}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; + use rewrite::Rewrite; use config::Config; @@ -25,6 +27,67 @@ use syntax::print::pprust; use syntax::parse::token; impl<'a> FmtVisitor<'a> { + pub fn visit_let(&mut self, local: &ast::Local, span: Span) { + self.format_missing_with_indent(span.lo); + + // String that is placed within the assignment pattern and expression. + let infix = { + let mut infix = String::new(); + + if let Some(ref ty) = local.ty { + infix.push_str(": "); + infix.push_str(&pprust::ty_to_string(ty)); + } + + if local.init.is_some() { + infix.push_str(" ="); + } + + infix + }; + + // New scope so we drop the borrow of self (context) in time to mutably + // borrow self to mutate its buffer. + let result = { + let context = self.get_context(); + let mut result = "let ".to_owned(); + let pattern_offset = self.block_indent + result.len() + infix.len(); + // 1 = ; + let pattern_width = match self.config.max_width.checked_sub(pattern_offset + 1) { + Some(width) => width, + None => return, + }; + + match local.pat.rewrite(&context, pattern_offset, pattern_width) { + Some(ref pat_string) => result.push_str(pat_string), + None => return, + } + + result.push_str(&infix); + + if let Some(ref ex) = local.init { + let max_width = match self.config.max_width.checked_sub(context.block_indent + 1) { + Some(width) => width, + None => return, + }; + + // 1 = trailing semicolon; + let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent); + + match rhs { + Some(result) => result, + None => return, + } + } else { + result + } + }; + + self.buffer.push_str(&result); + self.buffer.push_str(";"); + self.last_pos = span.hi; + } + pub fn rewrite_fn(&mut self, indent: usize, ident: ast::Ident, @@ -51,9 +114,11 @@ impl<'a> FmtVisitor<'a> { span, newline_brace); - // Prepare for the function body by possibly adding a newline and indent. - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. + // Prepare for the function body by possibly adding a newline and + // indent. + // FIXME we'll miss anything between the end of the signature and the + // start of the body, but we need more spans from the compiler to solve + // this. if newline_brace { result.push('\n'); result.push_str(&make_indent(indent)); @@ -783,7 +848,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) - // this hacky solution caused by absence of `Mutability` in `SelfValue`. let mut_str = { - if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = args[0].pat.node { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = + args[0].pat.node { format_mutability(mutability) } else { panic!("there is a bug or change in structure of AST, aborting."); diff --git a/src/lib.rs b/src/lib.rs index 4efd919649a..f410f7e5468 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,6 +325,8 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { panic!("No input supplied to RustFmt"); } + #[rustfmt_skip] + // FIXME(#195): closure is formatted poorly. fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { let write_mode = self.write_mode; diff --git a/src/lists.rs b/src/lists.rs index 12c8d14574a..931baaa1073 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -99,7 +99,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St let mut tactic = formatting.tactic; // Conservatively overestimates because of the changing separator tactic. - let sep_count = if formatting.trailing_separator != SeparatorTactic::Never { + let sep_count = if formatting.trailing_separator == SeparatorTactic::Always { items.len() } else { items.len() - 1 @@ -113,8 +113,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St if tactic == ListTactic::HorizontalVertical { debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", total_width, total_sep_len, formatting.h_width); - tactic = if fits_single && - !items.iter().any(ListItem::is_multiline) { + tactic = if fits_single && !items.iter().any(ListItem::is_multiline) { ListTactic::Horizontal } else { ListTactic::Vertical @@ -187,13 +186,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St // Pre-comments if let Some(ref comment) = item.pre_comment { - result.push_str(&rewrite_comment(comment, - // Block style in non-vertical mode - tactic != ListTactic::Vertical, - // Width restriction is only - // relevant in vertical mode. - formatting.v_width, - formatting.indent)); + // Block style in non-vertical mode. + let block_mode = tactic != ListTactic::Vertical; + // Width restriction is only relevant in vertical mode. + let max_width = formatting.v_width; + result.push_str(&rewrite_comment(comment, block_mode, max_width, formatting.indent)); if tactic == ListTactic::Vertical { result.push('\n'); diff --git a/src/visitor.rs b/src/visitor.rs index fccd619d403..e479b49f06a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -28,6 +28,8 @@ pub struct FmtVisitor<'a> { } impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { + // FIXME: We'd rather not format expressions here, as we have little + // context. How are we still reaching this? fn visit_expr(&mut self, ex: &'v ast::Expr) { debug!("visit_expr: {:?} {:?}", self.codemap.lookup_char_pos(ex.span.lo), @@ -44,23 +46,37 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_stmt(&mut self, stmt: &'v ast::Stmt) { - // If the stmt is actually an item, then we'll handle any missing spans - // there. This is important because of annotations. - // Although it might make more sense for the statement span to include - // any annotations on the item. - let skip_missing = match stmt.node { + match stmt.node { ast::Stmt_::StmtDecl(ref decl, _) => { - match decl.node { - ast::Decl_::DeclItem(_) => true, - _ => false, + return match decl.node { + ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span), + ast::Decl_::DeclItem(..) => visit::walk_stmt(self, stmt), + }; + } + ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { + self.format_missing_with_indent(stmt.span.lo); + let suffix = if let ast::Stmt_::StmtExpr(..) = stmt.node { + "" + } else { + ";" + }; + + // 1 = trailing semicolon; + let rewrite = ex.rewrite(&self.get_context(), + self.config.max_width - self.block_indent - suffix.len(), + self.block_indent); + + if let Some(new_str) = rewrite { + self.buffer.push_str(&new_str); + self.buffer.push_str(suffix); + self.last_pos = stmt.span.hi; } } - _ => false, - }; - if !skip_missing { - self.format_missing_with_indent(stmt.span.lo); + ast::Stmt_::StmtMac(..) => { + self.format_missing_with_indent(stmt.span.lo); + visit::walk_stmt(self, stmt); + } } - visit::walk_stmt(self, stmt); } fn visit_block(&mut self, b: &'v ast::Block) { diff --git a/tests/source/assignment.rs b/tests/source/assignment.rs new file mode 100644 index 00000000000..347966cf555 --- /dev/null +++ b/tests/source/assignment.rs @@ -0,0 +1,16 @@ +// Test assignment + +fn main() { + let some_var : Type ; + + let mut mutable; + + let variable = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; + + variable = LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; + + let single_line_fit = + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + single_line_fit = 5;single_lit_fit >>= 10; +} diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 6b3b3daf0a9..d304093ebb2 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -2,23 +2,22 @@ fn foo() -> bool { let boxed: Box = box 5; - let referenced = &5; + let referenced = &5 ; let very_long_variable_name = ( a + first + simple + test ); let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - //FIXME this exceeds width limit. Needs assignments reformatting let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) - + 1000; + + 1000 ; some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), trivial_value); (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))); + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; { for _ in 0..10 {} } @@ -64,9 +63,9 @@ fn bar() { syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 }); let third = ..10; - let infi_range = ..; + let infi_range = .. ; let foo = 1..; - let bar = 5; + let bar = 5 ; let nonsense = (10 .. 0)..(0..10); let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && diff --git a/tests/source/paths.rs b/tests/source/paths.rs index 4225aa9dab3..51edf707645 100644 --- a/tests/source/paths.rs +++ b/tests/source/paths.rs @@ -15,8 +15,6 @@ fn main() { Quux::::some_func(); - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux(); } fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/target/assignment.rs b/tests/target/assignment.rs new file mode 100644 index 00000000000..72b85a53e55 --- /dev/null +++ b/tests/target/assignment.rs @@ -0,0 +1,18 @@ +// Test assignment + +fn main() { + let some_var: Type; + + let mut mutable; + + let variable = + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; + + variable = + LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; + + let single_line_fit = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + single_line_fit = 5; + single_lit_fit >>= 10; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index dfbf0032011..df5e98e4f1b 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -8,8 +8,8 @@ fn foo() -> bool { let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - //FIXME this exceeds width limit. Needs assignments reformatting - let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + let is_internalxxxx = self.codemap.span_to_filename(s) == + self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 5573ea7e96e..b6e4750d886 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -134,7 +134,7 @@ fn main() { 42usize); let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd"; + abcd abcd"; } diff --git a/tests/target/paths.rs b/tests/target/paths.rs index c358104e1fa..c69275c7ff9 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -13,8 +13,6 @@ fn main() { supports_clipboard); Quux::::some_func(); - - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux(); } fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 2ccb3480d6f..f90461030ac 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -3,21 +3,22 @@ fn main() -> &'static str { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAA\ + AAAAAAAAAAAAaAa"; let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; let too_many_lines = "Hello"; // Make sure we don't break after an escape character. - let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ - \n\n"; + let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ + \n\n\n"; let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ \n\n\n"; - let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ + AA"; let raw_string = r#"Do not diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index bf73db5a815..77467a40ce7 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -13,10 +13,10 @@ fn main() { b: bar(), ..something }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar() }; - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Commen + // t a: foo(), /* C * o * m @@ -24,7 +24,8 @@ fn main() { * e * n * t */ - // Comment + // Commen + // t b: bar(), /* C * o * m -- cgit 1.4.1-3-g733a5 From b7a71250f46e368a411c6708a93b090c129b3c52 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 25 Aug 2015 21:46:58 +0200 Subject: Implement single line if-else formatting --- src/config.rs | 1 + src/default.toml | 1 + src/expr.rs | 65 ++++++++++++++++++++++++++++++++++--- tests/config/small_tabs.toml | 1 + tests/source/expr.rs | 2 ++ tests/source/single-line-if-else.rs | 46 ++++++++++++++++++++++++++ tests/target/expr.rs | 6 ++++ tests/target/single-line-if-else.rs | 46 ++++++++++++++++++++++++++ 8 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 tests/source/single-line-if-else.rs create mode 100644 tests/target/single-line-if-else.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 341f1d45afd..1af346265de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -79,4 +79,5 @@ create_config! { reorder_imports: bool, // Alphabetically, case sensitive. expr_indent_style: BlockIndentStyle, closure_indent_style: BlockIndentStyle, + single_line_if_else: bool, } diff --git a/src/default.toml b/src/default.toml index 5792079a407..0af42981522 100644 --- a/src/default.toml +++ b/src/default.toml @@ -15,3 +15,4 @@ report_fixme = "Never" reorder_imports = false expr_indent_style = "Tabbed" closure_indent_style = "Visual" +single_line_if_else = false diff --git a/src/expr.rs b/src/expr.rs index f1279d93a5a..1797617e7fd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,7 @@ use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; use syntax::{ast, ptr}; -use syntax::codemap::{Pos, Span, BytePos, mk_sp}; +use syntax::codemap::{CodeMap, Pos, Span, BytePos, mk_sp}; use syntax::visit::Visitor; impl Rewrite for ast::Expr { @@ -412,7 +412,7 @@ fn rewrite_range(context: &RewriteContext, fn rewrite_if_else(context: &RewriteContext, cond: &ast::Expr, if_block: &ast::Block, - else_block: Option<&ast::Expr>, + else_block_opt: Option<&ast::Expr>, pat: Option<&ast::Pat>, width: usize, offset: usize) @@ -423,13 +423,22 @@ fn rewrite_if_else(context: &RewriteContext, cond, "let ", " =", - width - 3 - 2, + try_opt!(width.checked_sub(3 + 2)), offset + 3)); + // Try to format if-else on single line. + if context.config.single_line_if_else { + let trial = single_line_if_else(context, &pat_expr_string, if_block, else_block_opt, width); + + if trial.is_some() { + return trial; + } + } + let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); let mut result = format!("if {} {}", pat_expr_string, if_block_string); - if let Some(else_block) = else_block { + if let Some(else_block) = else_block_opt { let else_block_string = try_opt!(else_block.rewrite(context, width, offset)); result.push_str(" else "); @@ -439,6 +448,52 @@ fn rewrite_if_else(context: &RewriteContext, Some(result) } +fn single_line_if_else(context: &RewriteContext, + pat_expr_str: &str, + if_node: &ast::Block, + else_block_opt: Option<&ast::Expr>, + width: usize) + -> Option { + let else_block = try_opt!(else_block_opt); + let fixed_cost = "if { } else { }".len(); + + if let ast::ExprBlock(ref else_node) = else_block.node { + if !is_simple_block(if_node, context.codemap) || + !is_simple_block(else_node, context.codemap) || pat_expr_str.contains('\n') { + return None; + } + + let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); + let if_expr = if_node.expr.as_ref().unwrap(); + let if_str = try_opt!(if_expr.rewrite(context, new_width, 0)); + + let new_width = try_opt!(new_width.checked_sub(if_str.len())); + let else_expr = else_node.expr.as_ref().unwrap(); + let else_str = try_opt!(else_expr.rewrite(context, new_width, 0)); + + // FIXME: this check shouldn't be necessary. Rewrites should either fail + // or wrap to a newline when the object does not fit the width. + let fits_line = fixed_cost + pat_expr_str.len() + if_str.len() + else_str.len() <= width; + + if fits_line && !if_str.contains('\n') && !else_str.contains('\n') { + return Some(format!("if {} {{ {} }} else {{ {} }}", pat_expr_str, if_str, else_str)); + } + } + + None +} + +// Checks that a block contains no statements, an expression and no comments. +fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { + if !block.stmts.is_empty() || block.expr.is_none() { + return false; + } + + let snippet = codemap.span_to_snippet(block.span).unwrap(); + + !snippet.contains("//") && !snippet.contains("/*") +} + fn rewrite_match(context: &RewriteContext, cond: &ast::Expr, arms: &[ast::Arm], @@ -830,7 +885,7 @@ fn rewrite_paren(context: &RewriteContext, debug!("rewrite_paren, width: {}, offset: {}", width, offset); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr. - let subexpr_str = subexpr.rewrite(context, width-2, offset+1); + let subexpr_str = subexpr.rewrite(context, try_opt!(width.checked_sub(2)), offset + 1); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); subexpr_str.map(|s| format!("({})", s)) } diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 2aff85506a4..1b4ab5cb7e9 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -15,3 +15,4 @@ report_fixme = "Never" reorder_imports = false expr_indent_style = "Tabbed" closure_indent_style = "Visual" +single_line_if_else = false diff --git a/tests/source/expr.rs b/tests/source/expr.rs index d304093ebb2..85ee7727451 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -43,6 +43,8 @@ some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 + 2 + 3 { } + let test = if true { 5 } else { 3 }; + if cond() { something(); } else if different_cond() { diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs new file mode 100644 index 00000000000..25ba58cabf8 --- /dev/null +++ b/tests/source/single-line-if-else.rs @@ -0,0 +1,46 @@ +// rustfmt-single_line_if_else: true + +// Format if-else expressions on a single line, when possible. + +fn main() { + let a = if 1 > 2 { + unreachable!() + } else { + 10 + }; + + let a = if x { 1 } else if y { 2 } else { 3 }; + + let b = if cond() { + 5 + } else { + // Brief comment. + 10 + }; + + let c = if cond() { + statement(); + + 5 + } else { + 10 + }; + + if cond() { statement(); } else { other_statement(); } + + if true { + do_something() + } + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { + bbbbbbbbbb }; + + funk(if test() { + 1 + } else { + 2 + }, + arg2); +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index df5e98e4f1b..45c654b738f 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -61,6 +61,12 @@ fn foo() -> bool { 1 + 2 + 3 { } + let test = if true { + 5 + } else { + 3 + }; + if cond() { something(); } else if different_cond() { diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs new file mode 100644 index 00000000000..dff06e69b2d --- /dev/null +++ b/tests/target/single-line-if-else.rs @@ -0,0 +1,46 @@ +// rustfmt-single_line_if_else: true + +// Format if-else expressions on a single line, when possible. + +fn main() { + let a = if 1 > 2 { unreachable!() } else { 10 }; + + let a = if x { + 1 + } else if y { 2 } else { 3 }; + + let b = if cond() { + 5 + } else { + // Brief comment. + 10 + }; + + let c = if cond() { + statement(); + + 5 + } else { + 10 + }; + + if cond() { + statement(); + } else { + other_statement(); + } + + if true { + do_something() + } + + let x = if veeeeeeeeery_loooooong_condition() { + aaaaaaaaaaaaaaaaaaaaaaaaaaa + } else { + bbbbbbbbbb + }; + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; + + funk(if test() { 1 } else { 2 }, arg2); +} -- cgit 1.4.1-3-g733a5 From d92dd3d915c0936f78fb0cf80c830dbd7fda211e Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 25 Aug 2015 22:07:02 +0200 Subject: Prevent nested if-else from being put on a single line. This is done using a pretty terribad hack, introducing an extra function parameter and some code duplication. Unfortunately, there seem to be few alternatives. --- src/expr.rs | 40 +++++++++++++++++++++++++++++++------ tests/source/single-line-if-else.rs | 4 ++++ tests/target/single-line-if-else.rs | 8 +++++++- 3 files changed, 45 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1797617e7fd..14659815d72 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -80,7 +80,8 @@ impl Rewrite for ast::Expr { else_block.as_ref().map(|e| &**e), None, width, - offset) + offset, + true) } ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref else_block) => { rewrite_if_else(context, @@ -89,7 +90,8 @@ impl Rewrite for ast::Expr { else_block.as_ref().map(|e| &**e), Some(pat), width, - offset) + offset, + true) } // We reformat it ourselves because rustc gives us a bad span // for ranges, see rust#27162 @@ -415,7 +417,8 @@ fn rewrite_if_else(context: &RewriteContext, else_block_opt: Option<&ast::Expr>, pat: Option<&ast::Pat>, width: usize, - offset: usize) + offset: usize, + allow_single_line: bool) -> Option { // 3 = "if ", 2 = " {" let pat_expr_string = try_opt!(rewrite_pat_expr(context, @@ -427,7 +430,7 @@ fn rewrite_if_else(context: &RewriteContext, offset + 3)); // Try to format if-else on single line. - if context.config.single_line_if_else { + if allow_single_line && context.config.single_line_if_else { let trial = single_line_if_else(context, &pat_expr_string, if_block, else_block_opt, width); if trial.is_some() { @@ -439,10 +442,34 @@ fn rewrite_if_else(context: &RewriteContext, let mut result = format!("if {} {}", pat_expr_string, if_block_string); if let Some(else_block) = else_block_opt { - let else_block_string = try_opt!(else_block.rewrite(context, width, offset)); + let rewrite = match else_block.node { + // If the else expression is another if-else expression, prevent it + // from being formatted on a single line. + ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref else_block) => { + rewrite_if_else(context, + cond, + if_block, + else_block.as_ref().map(|e| &**e), + Some(pat), + width, + offset, + false) + } + ast::Expr_::ExprIf(ref cond, ref if_block, ref else_block) => { + rewrite_if_else(context, + cond, + if_block, + else_block.as_ref().map(|e| &**e), + None, + width, + offset, + false) + } + _ => else_block.rewrite(context, width, offset), + }; result.push_str(" else "); - result.push_str(&else_block_string); + result.push_str(&&try_opt!(rewrite)); } Some(result) @@ -491,6 +518,7 @@ fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { let snippet = codemap.span_to_snippet(block.span).unwrap(); + // FIXME: fails when either // or /* is contained in a string literal. !snippet.contains("//") && !snippet.contains("/*") } diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs index 25ba58cabf8..42629ab8e37 100644 --- a/tests/source/single-line-if-else.rs +++ b/tests/source/single-line-if-else.rs @@ -26,6 +26,10 @@ fn main() { 10 }; + let d = if let Some(val) = turbo + { "cool" } else { + "beans" }; + if cond() { statement(); } else { other_statement(); } if true { diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs index dff06e69b2d..27b6d773da5 100644 --- a/tests/target/single-line-if-else.rs +++ b/tests/target/single-line-if-else.rs @@ -7,7 +7,11 @@ fn main() { let a = if x { 1 - } else if y { 2 } else { 3 }; + } else if y { + 2 + } else { + 3 + }; let b = if cond() { 5 @@ -24,6 +28,8 @@ fn main() { 10 }; + let d = if let Some(val) = turbo { "cool" } else { "beans" }; + if cond() { statement(); } else { -- cgit 1.4.1-3-g733a5 From 6adb6a1d1ace57b10864b845d38f16b12387e2f9 Mon Sep 17 00:00:00 2001 From: Simon Bernier St-Pierre Date: Tue, 25 Aug 2015 17:37:48 -0400 Subject: Fix build on nightly https://github.com/rust-lang/rust/pull/27857 --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index e479b49f06a..20909391f09 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -160,7 +160,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { codemap::mk_sp(s.lo, b.span.lo)); self.buffer.push_str(&new_fn); } - visit::FkFnBlock(..) => {} + visit::FkClosure(..) => {} } self.last_pos = b.span.lo; -- cgit 1.4.1-3-g733a5 From 9ead47151e22f68fcbd0fe5194cbd09cd2482680 Mon Sep 17 00:00:00 2001 From: Simon Bernier St-Pierre Date: Fri, 31 Jul 2015 19:21:44 -0400 Subject: Add project-specific configuration file support --- Cargo.toml | 1 - build.rs | 25 ------------------------- src/bin/rustfmt.rs | 53 +++++++++++++++++++++++++++++++++++++++++++---------- src/config.rs | 27 +++++++++++++++++++++++++++ tests/system.rs | 14 ++++++++------ 5 files changed, 78 insertions(+), 42 deletions(-) delete mode 100644 build.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 57c47fec54c..a71d4abae86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/nick29581/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" -build = "build.rs" [dependencies.strings] strings = "0.0.1" diff --git a/build.rs b/build.rs deleted file mode 100644 index 3e6d051d9b1..00000000000 --- a/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Build script. Just copies default.toml from the src to the target dir. - -use std::env; -use std::path::{Path, PathBuf}; - -fn main() { - let in_file = Path::new("src/default.toml"); - - let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - let mut out_file = PathBuf::new(); - out_file.push(manifest_dir); - out_file.push("default.toml"); - - std::fs::copy(in_file, out_file).unwrap(); -} diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 6ec0f9556c8..2f61e788ed2 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -7,30 +7,63 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. - +#![feature(path_ext)] +#![feature(rustc_private)] #![cfg(not(test))] #![feature(result_expect)] +#[macro_use] +extern crate log; extern crate rustfmt; +extern crate toml; use rustfmt::{WriteMode, run}; use rustfmt::config::Config; -use std::fs::File; -use std::io::Read; +use std::env; +use std::fs::{File, PathExt}; +use std::io::{self, Read}; +use std::path::PathBuf; use std::str::FromStr; +// Try to find a project file in the current directory and its parents. +fn lookup_project_file() -> io::Result { + let mut current = try!(env::current_dir()); + loop { + let config_file = current.join("rustfmt.toml"); + if config_file.exists() { + return Ok(config_file); + } else { + current = match current.parent() { + // if the current directory has no parent, we're done searching + None => return Err(io::Error::new(io::ErrorKind::NotFound, "config not found")), + Some(path) => path.to_path_buf(), + }; + } + } +} + +// Try to find a project file. If it's found, read it. +fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> { + let path = try!(lookup_project_file()); + let mut file = try!(File::open(&path)); + let mut toml = String::new(); + try!(file.read_to_string(&mut toml)); + Ok((path, toml)) +} + fn main() { - let mut def_config_file = File::open("default.toml").unwrap_or_else(|e| { - panic!("Unable to open configuration file [default.toml] {}",e) - }); - let mut def_config = String::new(); - def_config_file.read_to_string(&mut def_config).unwrap(); - let config = Box::new(Config::from_toml(&def_config)); let (args, write_mode) = determine_params(std::env::args()); - run(args, write_mode, config); + let config = match lookup_and_read_project_file() { + Ok((path, toml)) => { + println!("Project config file: {}", path.display()); + Config::from_toml(&toml) + } + Err(_) => Default::default(), + }; + run(args, write_mode, Box::new(config)); std::process::exit(0); } diff --git a/src/config.rs b/src/config.rs index 1af346265de..02ee8e63789 100644 --- a/src/config.rs +++ b/src/config.rs @@ -81,3 +81,30 @@ create_config! { closure_indent_style: BlockIndentStyle, single_line_if_else: bool, } + +impl Default for Config { + + fn default() -> Config { + Config { + max_width: 100, + ideal_width: 80, + leeway: 5, + tab_spaces: 4, + newline_style: NewlineStyle::Unix, + fn_brace_style: BraceStyle::SameLineWhere, + fn_return_indent: ReturnIndent::WithArgs, + fn_args_paren_newline: true, + struct_trailing_comma: SeparatorTactic::Vertical, + struct_lit_trailing_comma: SeparatorTactic::Vertical, + struct_lit_style: StructLitStyle::BlockIndent, + enum_trailing_comma: true, + report_todo: ReportTactic::Always, + report_fixme: ReportTactic::Never, + reorder_imports: false, + expr_indent_style: BlockIndentStyle::Tabbed, + closure_indent_style: BlockIndentStyle::Visual, + single_line_if_else: false, + } + } + +} diff --git a/tests/system.rs b/tests/system.rs index 3f63d224576..19e98a64889 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -121,12 +121,14 @@ pub fn idempotent_check(filename: String) -> Result<(), HashMap> // Reads test config file from comments and reads its contents. fn get_config(config_file: Option<&str>) -> Box { - let config_file_name = config_file.map(|file_name| { - let mut full_path = "tests/config/".to_owned(); - full_path.push_str(&file_name); - full_path - }) - .unwrap_or("default.toml".to_owned()); + let config_file_name = match config_file { + None => return Box::new(Default::default()), + Some(file_name) => { + let mut full_path = "tests/config/".to_owned(); + full_path.push_str(&file_name); + full_path + } + }; let mut def_config_file = fs::File::open(config_file_name).ok().expect("Couldn't open config."); let mut def_config = String::new(); -- cgit 1.4.1-3-g733a5 From 99b0aa95f2cacd3a7f30106cc8cb612b07be10e3 Mon Sep 17 00:00:00 2001 From: Simon Bernier St-Pierre Date: Wed, 26 Aug 2015 14:03:11 -0400 Subject: Delete src/default.toml file --- src/default.toml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 src/default.toml (limited to 'src') diff --git a/src/default.toml b/src/default.toml deleted file mode 100644 index 0af42981522..00000000000 --- a/src/default.toml +++ /dev/null @@ -1,18 +0,0 @@ -max_width = 100 -ideal_width = 80 -leeway = 5 -tab_spaces = 4 -newline_style = "Unix" -fn_brace_style = "SameLineWhere" -fn_return_indent = "WithArgs" -fn_args_paren_newline = true -struct_trailing_comma = "Vertical" -struct_lit_style = "BlockIndent" -struct_lit_trailing_comma = "Vertical" -enum_trailing_comma = true -report_todo = "Always" -report_fixme = "Never" -reorder_imports = false -expr_indent_style = "Tabbed" -closure_indent_style = "Visual" -single_line_if_else = false -- cgit 1.4.1-3-g733a5 From 39538a0c772694930185178eb6aa9bf83cc47c60 Mon Sep 17 00:00:00 2001 From: Alex HotShot Newman Date: Wed, 26 Aug 2015 15:02:06 -0700 Subject: Fix usage of the tool. Provide -h and --help --- src/bin/rustfmt.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2f61e788ed2..eda3eba107c 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -67,22 +67,40 @@ fn main() { std::process::exit(0); } +fn usage>(reason: S) { + print!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[true/false]] ", reason.into()); + std::process::exit(1); +} + fn determine_params(args: I) -> (Vec, WriteMode) where I: Iterator { - let prefix = "--write-mode="; + let arg_prefix = "-"; + let write_mode_prefix = "--write-mode="; + let help_mode = "-h"; + let long_help_mode = "--help"; let mut write_mode = WriteMode::Replace; // The NewFile option currently isn't supported because it requires another // parameter, but it can be added later. - let args = args.filter(|arg| { - if arg.starts_with(prefix) { - write_mode = FromStr::from_str(&arg[prefix.len()..]).expect("Unrecognized write mode"); + let args:Vec = args.filter(|arg| { + if arg.starts_with(write_mode_prefix) { + write_mode = FromStr::from_str(&arg[write_mode_prefix.len()..]).expect("Unrecognized write mode"); + false + } else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) { + usage(""); + false + } else if arg.starts_with(arg_prefix) { + usage("Invalid argument"); false } else { true } }).collect(); + if args.len() < 2 { + usage("Please provide a file to be formatted"); + } + (args, write_mode) } -- cgit 1.4.1-3-g733a5 From 5e445697ce5932ce666c94a29ab512abf115a166 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Fri, 17 Jul 2015 23:10:15 +0200 Subject: Implement Rewrite for [ast::Attribute] --- src/expr.rs | 40 +++++++++++------------- src/items.rs | 7 +++-- src/rewrite.rs | 6 +++- src/visitor.rs | 83 +++++++++++++++++++++++++++++--------------------- tests/source/attrib.rs | 43 ++++++++++++++++++++++++++ tests/target/attrib.rs | 10 ++++++ 6 files changed, 128 insertions(+), 61 deletions(-) create mode 100644 tests/source/attrib.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 14659815d72..f39dece3272 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,7 +31,7 @@ impl Rewrite for ast::Expr { ast::Lit_::LitStr(ref is, ast::StrStyle::CookedStr) => { rewrite_string_lit(context, &is, l.span, width, offset) } - _ => context.codemap.span_to_snippet(self.span).ok(), + _ => Some(context.snippet(self.span)), } } ast::Expr_::ExprCall(ref callee, ref args) => { @@ -137,7 +137,7 @@ impl Rewrite for ast::Expr { _ => { // We do not format these expressions yet, but they should still // satisfy our width restrictions. - let snippet = context.codemap.span_to_snippet(self.span).unwrap(); + let snippet = context.snippet(self.span); { let mut lines = snippet.lines(); @@ -243,7 +243,7 @@ fn rewrite_closure(capture: ast::CaptureClause, impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { - let user_str = context.codemap.span_to_snippet(self.span).unwrap(); + let user_str = context.snippet(self.span); if user_str == "{}" && width >= 2 { return Some(user_str); } @@ -254,7 +254,7 @@ impl Rewrite for ast::Block { let prefix = match self.rules { ast::BlockCheckMode::PushUnsafeBlock(..) | ast::BlockCheckMode::UnsafeBlock(..) => { - let snippet = try_opt!(context.codemap.span_to_snippet(self.span).ok()); + let snippet = context.snippet(self.span); let open_pos = try_opt!(snippet.find_uncommented("{")); visitor.last_pos = self.span.lo + BytePos(open_pos as u32); @@ -289,7 +289,7 @@ impl Rewrite for ast::Block { // FIXME(#18): implement pattern formatting impl Rewrite for ast::Pat { fn rewrite(&self, context: &RewriteContext, _: usize, _: usize) -> Option { - context.codemap.span_to_snippet(self.span).ok() + Some(context.snippet(self.span)) } } @@ -547,11 +547,9 @@ fn rewrite_match(context: &RewriteContext, for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. let missed_str = if i == 0 { - context.codemap.span_to_snippet(mk_sp(open_brace_pos + BytePos(1), - arm_start_pos(arm))).unwrap() + context.snippet(mk_sp(open_brace_pos + BytePos(1), arm_start_pos(arm))) } else { - context.codemap.span_to_snippet(mk_sp(arm_end_pos(&arms[i-1]), - arm_start_pos(arm))).unwrap() + context.snippet(mk_sp(arm_end_pos(&arms[i-1]), arm_start_pos(arm))) }; let missed_str = match missed_str.find_uncommented(",") { Some(n) => &missed_str[n+1..], @@ -582,8 +580,7 @@ fn rewrite_match(context: &RewriteContext, result.push_str(arm_str); } else { // We couldn't format the arm, just reproduce the source. - let snippet = context.codemap.span_to_snippet(mk_sp(arm_start_pos(arm), - arm_end_pos(arm))).unwrap(); + let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); } } @@ -626,8 +623,7 @@ impl Rewrite for ast::Arm { attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { // Attributes included a skip instruction. - let snippet = context.codemap.span_to_snippet(mk_sp(attrs[0].span.lo, - body.span.hi)).unwrap(); + let snippet = context.snippet(mk_sp(attrs[0].span.lo, body.span.hi)); return Some(snippet); } attr_visitor.format_missing(pats[0].span.lo); @@ -652,7 +648,7 @@ impl Rewrite for ast::Arm { // If the patterns were previously stacked, keep them stacked. // FIXME should be an option. let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi); - let pat_str = context.codemap.span_to_snippet(pat_span).unwrap(); + let pat_str = context.snippet(pat_span); vertical = pat_str.find('\n').is_some(); } @@ -831,7 +827,7 @@ fn rewrite_string_lit(context: &RewriteContext, let l_loc = context.codemap.lookup_char_pos(span.lo); let r_loc = context.codemap.lookup_char_pos(span.hi); if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width { - return context.codemap.span_to_snippet(span).ok(); + return Some(context.snippet(span)); } let fmt = StringFormat { opener: "\"", @@ -880,7 +876,7 @@ fn rewrite_call(context: &RewriteContext, // Take old span when rewrite fails. |item| { item.rewrite(inner_context, remaining_width, offset) - .unwrap_or(context.codemap.span_to_snippet(item.span).unwrap()) + .unwrap_or(context.snippet(item.span)) }, callee.span.hi + BytePos(1), span.hi); @@ -977,15 +973,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => { rewrite_field(inner_context, &field, h_budget, indent) - .unwrap_or(context.codemap.span_to_snippet(field.span) - .unwrap()) + .unwrap_or(context.snippet(field.span)) } StructLitField::Base(ref expr) => { // 2 = .. expr.rewrite(inner_context, h_budget - 2, indent + 2) .map(|s| format!("..{}", s)) - .unwrap_or(context.codemap.span_to_snippet(expr.span) - .unwrap()) + .unwrap_or(context.snippet(expr.span)) } } }, @@ -1053,7 +1047,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, |item| { let inner_width = context.config.max_width - indent - 1; item.rewrite(context, inner_width, indent) - .unwrap_or(context.codemap.span_to_snippet(item.span).unwrap()) + .unwrap_or(context.snippet(item.span)) }, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); @@ -1072,7 +1066,7 @@ fn rewrite_binary_op(context: &RewriteContext, -> Option { // FIXME: format comments between operands and operator - let operator_str = context.codemap.span_to_snippet(op.span).unwrap(); + let operator_str = context.snippet(op.span); // Get "full width" rhs and see if it fits on the current line. This // usually works fairly well since it tends to place operands of @@ -1150,7 +1144,7 @@ fn rewrite_assignment(context: &RewriteContext, offset: usize) -> Option { let operator_str = match op { - Some(op) => context.codemap.span_to_snippet(op.span).unwrap(), + Some(op) => context.snippet(op.span), None => "=".to_owned(), }; diff --git a/src/items.rs b/src/items.rs index 1501a904fdf..bcc851a5b35 100644 --- a/src/items.rs +++ b/src/items.rs @@ -17,7 +17,6 @@ use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; - use rewrite::Rewrite; use config::Config; @@ -699,7 +698,11 @@ impl<'a> FmtVisitor<'a> { let typ = pprust::ty_to_string(&field.node.ty); let indent = self.block_indent + self.config.tab_spaces; - let mut attr_str = self.rewrite_attrs(&field.node.attrs, indent); + let mut attr_str = field.node.attrs + .rewrite(&self.get_context(), + self.config.max_width - indent, + indent) + .unwrap(); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&make_indent(indent)); diff --git a/src/rewrite.rs b/src/rewrite.rs index d30d81a4885..5f1549846b5 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -10,7 +10,7 @@ // A generic trait to abstract the rewriting of an element (of the AST). -use syntax::codemap::CodeMap; +use syntax::codemap::{CodeMap, Span}; use config::Config; @@ -39,4 +39,8 @@ impl<'a> RewriteContext<'a> { block_indent: self.block_indent + self.config.tab_spaces, } } + + pub fn snippet(&self, span: Span) -> String { + self.codemap.span_to_snippet(span).unwrap() + } } diff --git a/src/visitor.rs b/src/visitor.rs index 20909391f09..b773a20fe6f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,6 +17,7 @@ use strings::string_buffer::StringBuffer; use utils; use config::Config; use rewrite::{Rewrite, RewriteContext}; +use comment::rewrite_comment; pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, @@ -293,7 +294,10 @@ impl<'a> FmtVisitor<'a> { if utils::contains_skip(attrs) { true } else { - let rewrite = self.rewrite_attrs(attrs, self.block_indent); + let rewrite = attrs.rewrite(&self.get_context(), + self.config.max_width - self.block_indent, + self.block_indent) + .unwrap(); self.buffer.push_str(&rewrite); let last = attrs.last().unwrap(); self.last_pos = last.span.hi; @@ -301,40 +305,6 @@ impl<'a> FmtVisitor<'a> { } } - pub fn rewrite_attrs(&self, attrs: &[ast::Attribute], indent: usize) -> String { - let mut result = String::new(); - let indent = utils::make_indent(indent); - - for (i, a) in attrs.iter().enumerate() { - let a_str = self.snippet(a.span); - - if i > 0 { - let comment = self.snippet(codemap::mk_sp(attrs[i-1].span.hi, a.span.lo)); - // This particular horror show is to preserve line breaks in between doc - // comments. An alternative would be to force such line breaks to start - // with the usual doc comment token. - let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; - let comment = comment.trim(); - if !comment.is_empty() { - result.push_str(&indent); - result.push_str(comment); - result.push('\n'); - } else if multi_line { - result.push('\n'); - } - result.push_str(&indent); - } - - result.push_str(&a_str); - - if i < attrs.len() - 1 { - result.push('\n'); - } - } - - result - } - fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); @@ -402,3 +372,46 @@ impl<'a> FmtVisitor<'a> { } } } + +impl<'a> Rewrite for [ast::Attribute] { + fn rewrite(&self, context: &RewriteContext, _: usize, offset: usize) -> Option { + let mut result = String::new(); + if self.is_empty() { + return Some(result); + } + let indent = utils::make_indent(offset); + + for (i, a) in self.iter().enumerate() { + let a_str = context.snippet(a.span); + + if i > 0 { + let comment = context.snippet(codemap::mk_sp(self[i-1].span.hi, a.span.lo)); + // This particular horror show is to preserve line breaks in between doc + // comments. An alternative would be to force such line breaks to start + // with the usual doc comment token. + let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; + let comment = comment.trim(); + if !comment.is_empty() { + let comment = rewrite_comment(comment, + false, + context.config.max_width - offset, + offset); + result.push_str(&indent); + result.push_str(&comment); + result.push('\n'); + } else if multi_line { + result.push('\n'); + } + result.push_str(&indent); + } + + result.push_str(&a_str); + + if i < self.len() - 1 { + result.push('\n'); + } + } + + Some(result) + } +} diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs new file mode 100644 index 00000000000..ac44a6504fd --- /dev/null +++ b/tests/source/attrib.rs @@ -0,0 +1,43 @@ +// Test attributes and doc comments are preserved. + +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. + +/// Blah blah blah. +impl Bar { + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + #[an_attribute] + fn foo(&mut self) -> isize { + } + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + pub fn f2(self) { + (foo, bar) + } + + #[another_attribute] + fn f3(self) -> Dog { + } + + /// Blah blah bing. + + #[attrib1] + /// Blah blah bing. + #[attrib2] + // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo loooooooooooong. + /// Blah blah bing. + fn f4(self) -> Cat { + } +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index ee7da10081e..62657ad3b5d 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -29,4 +29,14 @@ impl Bar { #[another_attribute] fn f3(self) -> Dog { } + + /// Blah blah bing. + #[attrib1] + /// Blah blah bing. + #[attrib2] + // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo + // loooooooooooong. + /// Blah blah bing. + fn f4(self) -> Cat { + } } -- cgit 1.4.1-3-g733a5 From 660f41865b43f38d68b649328c04b1702e37655e Mon Sep 17 00:00:00 2001 From: Mika Attila Date: Fri, 28 Aug 2015 10:28:28 +0200 Subject: Only exit after running all destructors and flushing stdout --- src/bin/rustfmt.rs | 60 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index eda3eba107c..e57ba18614d 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -10,7 +10,6 @@ #![feature(path_ext)] #![feature(rustc_private)] #![cfg(not(test))] -#![feature(result_expect)] #[macro_use] extern crate log; @@ -52,8 +51,11 @@ fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> { Ok((path, toml)) } -fn main() { - let (args, write_mode) = determine_params(std::env::args()); +fn execute() -> i32 { + let (args, write_mode) = match determine_params(std::env::args()) { + Some((args, write_mode)) => (args, write_mode), + None => return 1, + }; let config = match lookup_and_read_project_file() { Ok((path, toml)) => { @@ -64,15 +66,26 @@ fn main() { }; run(args, write_mode, Box::new(config)); - std::process::exit(0); + 0 } -fn usage>(reason: S) { - print!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[true/false]] ", reason.into()); - std::process::exit(1); +fn main() { + use std::io::Write; + let exit_code = execute(); + // Make sure standard output is flushed before we exit + std::io::stdout().flush().unwrap(); + // Exit with given exit code. + // + // NOTE: This immediately terminates the process without doing any cleanup, + // so make sure to finish all necessary cleanup before this is called. + std::process::exit(exit_code); } -fn determine_params(args: I) -> (Vec, WriteMode) +fn print_usage>(reason: S) { + println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[true/false]] ", reason.into()); +} + +fn determine_params(args: I) -> Option<(Vec, WriteMode)> where I: Iterator { let arg_prefix = "-"; @@ -80,27 +93,38 @@ fn determine_params(args: I) -> (Vec, WriteMode) let help_mode = "-h"; let long_help_mode = "--help"; let mut write_mode = WriteMode::Replace; + let args: Vec = args.collect(); // The NewFile option currently isn't supported because it requires another // parameter, but it can be added later. - let args:Vec = args.filter(|arg| { + if args.iter().any(|arg| { if arg.starts_with(write_mode_prefix) { - write_mode = FromStr::from_str(&arg[write_mode_prefix.len()..]).expect("Unrecognized write mode"); + write_mode = match FromStr::from_str(&arg[write_mode_prefix.len()..]) { + Ok(mode) => mode, + Err(_) => { + print_usage("Unrecognized write mode"); + return true; + } + }; false } else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) { - usage(""); - false + print_usage(""); + true } else if arg.starts_with(arg_prefix) { - usage("Invalid argument"); - false - } else { + print_usage("Invalid argument"); true + } else { + false } - }).collect(); + }) { + return None; + } + if args.len() < 2 { - usage("Please provide a file to be formatted"); + print_usage("Please provide a file to be formatted"); + return None; } - (args, write_mode) + Some((args, write_mode)) } -- cgit 1.4.1-3-g733a5 From 145a90da0544bb483ff3322687fb65b7d32f0ca6 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Thu, 27 Aug 2015 23:15:21 -0400 Subject: Fix #201 --- src/expr.rs | 10 ++++++++-- tests/source/struct_lits.rs | 8 ++++++++ tests/target/struct_lits.rs | 8 ++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f39dece3272..20b5ea92bd0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -959,8 +959,14 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| { match *item { StructLitField::Regular(ref field) => field.span.lo, - // 2 = .. - StructLitField::Base(ref expr) => expr.span.lo - BytePos(2), + StructLitField::Base(ref expr) => { + let last_field_hi = + fields.last().map_or(span.lo, |field| field.span.hi); + let snippet = + context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } } }, |item| { diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 225d3a16985..1caf20e99a5 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -53,3 +53,11 @@ fn issue177() { struct Foo { memb: T } let foo = Foo:: { memb: 10 }; } + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index cc2887fc51f..6dd4180a708 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -71,3 +71,11 @@ fn issue177() { } let foo = Foo:: { memb: 10 }; } + +fn issue201() { + let s = S { a: 0, ..b }; +} + +fn issue201_2() { + let s = S { a: S2 { ..c }, ..b }; +} -- cgit 1.4.1-3-g733a5 From ce2516545018bf146ec1c898531eed942bb42da7 Mon Sep 17 00:00:00 2001 From: Mika Attila Date: Fri, 28 Aug 2015 13:07:08 +0200 Subject: Don't pass --write-mode argument to rustc Fixes regression introduced by 660f41865b43f38d68b649328c04b1702e37655e --- src/bin/rustfmt.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index e57ba18614d..c527ae1504a 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -93,38 +93,36 @@ fn determine_params(args: I) -> Option<(Vec, WriteMode)> let help_mode = "-h"; let long_help_mode = "--help"; let mut write_mode = WriteMode::Replace; - let args: Vec = args.collect(); + let mut rustc_args = Vec::new(); // The NewFile option currently isn't supported because it requires another // parameter, but it can be added later. - if args.iter().any(|arg| { + for arg in args { if arg.starts_with(write_mode_prefix) { - write_mode = match FromStr::from_str(&arg[write_mode_prefix.len()..]) { - Ok(mode) => mode, + match FromStr::from_str(&arg[write_mode_prefix.len()..]) { + Ok(mode) => write_mode = mode, Err(_) => { print_usage("Unrecognized write mode"); - return true; + return None; } - }; - false + } } else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) { print_usage(""); - true + return None; } else if arg.starts_with(arg_prefix) { print_usage("Invalid argument"); - true + return None; } else { - false + // Pass everything else to rustc + rustc_args.push(arg); } - }) { - return None; } - if args.len() < 2 { + if rustc_args.len() < 2 { print_usage("Please provide a file to be formatted"); return None; } - Some((args, write_mode)) + Some((rustc_args, write_mode)) } -- cgit 1.4.1-3-g733a5 From e5ea13da6e2d9365fea063e6df5507c527390029 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Thu, 27 Aug 2015 14:07:15 +0200 Subject: Add a generic tool for searching comments in code This make a base for all functions searching for comments, or searching code excluding comments, etc. These functions where too simple and didn't handle complicated cases like nested comments or comment marks inside string litterals ("/*"). --- src/comment.rs | 223 +++++++++++++++++++++++++++++++++++++++++++++++---------- src/expr.rs | 5 +- 2 files changed, 187 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4cee78f271d..9c97325ec96 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -10,6 +10,8 @@ // Format comments. +use std::iter; + use string::{StringFormat, rewrite_string}; use utils::make_indent; @@ -118,27 +120,18 @@ pub trait FindUncommented { impl FindUncommented for str { fn find_uncommented(&self, pat: &str) -> Option { let mut needle_iter = pat.chars(); - let mut possible_comment = false; - - for (i, b) in self.char_indices() { + for (kind, (i, b)) in CharClasses::new(self.char_indices()) { match needle_iter.next() { - Some(c) => { - if b != c { + None => { + return Some(i - pat.len()); + } + Some(c) => match kind { + CodeCharKind::Normal if b == c => {} + _ => { needle_iter = pat.chars(); } - } - None => return Some(i - pat.len()), + }, } - - if possible_comment && (b == '/' || b == '*') { - return find_comment_end(&self[(i-1)..]) - .and_then(|end| { - self[(end + i - 1)..].find_uncommented(pat) - .map(|idx| idx + end + i - 1) - }); - } - - possible_comment = b == '/'; } // Handle case where the pattern is a suffix of the search string @@ -167,6 +160,11 @@ fn test_find_uncommented() { check("hel/*lohello*/lo", "hello", None); check("acb", "ab", None); check(",/*A*/ ", ",", Some(0)); + check("abc", "abc", Some(0)); + check("/* abc */", "abc", None); + check("/**/abc/* */", "abc", Some(4)); + check("\"/* abc */\"", "abc", Some(4)); + check("\"/* abc", "abc", Some(4)); } // Returns the first byte position after the first comment. The given string @@ -174,29 +172,17 @@ fn test_find_uncommented() { // Good: "/* /* inner */ outer */ code();" // Bad: "code(); // hello\n world!" pub fn find_comment_end(s: &str) -> Option { - if s.starts_with("//") { - s.find('\n').map(|idx| idx + 1) - } else { - // Block comment - let mut levels = 0; - let mut prev_char = 'a'; - - for (i, mut c) in s.char_indices() { - if c == '*' && prev_char == '/' { - levels += 1; - c = 'a'; // Invalidate prev_char - } else if c == '/' && prev_char == '*' { - levels -= 1; - - if levels == 0 { - return Some(i + 1); - } - c = 'a'; - } - - prev_char = c; + let mut iter = CharClasses::new(s.char_indices()); + for (kind, (i, _c)) in &mut iter { + if kind == CodeCharKind::Normal { + return Some(i); } + } + // Handle case where the comment ends at the end of s. + if iter.status == CharClassesStatus::Normal { + Some(s.len()) + } else { None } } @@ -211,3 +197,164 @@ fn comment_end() { assert_eq!(None, find_comment_end("// hi /* test */")); assert_eq!(Some(9), find_comment_end("// hi /*\n.")); } + + +/// Returns true if text contains any comment. +pub fn contains_comment(text: &str) -> bool { + CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment ) +} + +pub fn uncommented(text: &str) -> String { + CharClasses::new(text.chars()).filter_map(|(s, c)| match s { + CodeCharKind::Normal => Some(c), + CodeCharKind::Comment => None + }).collect() +} + +#[test] +fn test_uncommented() { + assert_eq!(&uncommented("abc/*...*/"), "abc"); + assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); +} + +#[test] +fn test_contains_comment() { + assert_eq!(contains_comment("abc"), false); + assert_eq!(contains_comment("abc // qsdf"), true); + assert_eq!(contains_comment("abc /* kqsdf"), true); + assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); +} + +struct CharClasses + where T: Iterator, + T::Item: RichChar +{ + base: iter::Peekable, + status: CharClassesStatus, +} + +trait RichChar { + fn get_char(&self) -> char; +} + +impl RichChar for char { + fn get_char(&self) -> char { + *self + } +} + +impl RichChar for (usize, char) { + fn get_char(&self) -> char { + self.1 + } +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum CharClassesStatus { + Normal, + LitString, + LitStringEscape, + LitChar, + LitCharEscape, + // The u32 is the nesting deepness of the comment + BlockComment(u32), + // Status when the '/' has been consumed, but not yet the '*', deepness is the new deepness + // (after the comment opening). + BlockCommentOpening(u32), + // Status when the '*' has been consumed, but not yet the '/', deepness is the new deepness + // (after the comment closing). + BlockCommentClosing(u32), + LineComment, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum CodeCharKind { + Normal, + Comment, +} + +impl CharClasses where T: Iterator, T::Item: RichChar { + fn new(base: T) -> CharClasses { + CharClasses { base: base.peekable(), status: CharClassesStatus::Normal } + } +} + +impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { + type Item = (CodeCharKind, T::Item); + + fn next(&mut self) -> Option<(CodeCharKind, T::Item)> { + let item = try_opt!(self.base.next()); + let chr = item.get_char(); + self.status = match self.status { + CharClassesStatus::LitString => match chr { + '"' => CharClassesStatus::Normal, + '\\' => CharClassesStatus::LitStringEscape, + _ => CharClassesStatus::LitString, + }, + CharClassesStatus::LitStringEscape => CharClassesStatus::LitString, + CharClassesStatus::LitChar => match chr { + '\\' => CharClassesStatus::LitCharEscape, + '\'' => CharClassesStatus::Normal, + _ => CharClassesStatus::LitChar, + }, + CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, + CharClassesStatus::Normal => { + match chr { + '"' => CharClassesStatus::LitString, + '\'' => CharClassesStatus::LitChar, + '/' => match self.base.peek() { + Some(next) if next.get_char() == '*' => { + self.status = CharClassesStatus::BlockCommentOpening(1); + return Some((CodeCharKind::Comment, item)); + } + Some(next) if next.get_char() == '/' => { + self.status = CharClassesStatus::LineComment; + return Some((CodeCharKind::Comment, item)); + } + _ => CharClassesStatus::Normal, + }, + _ => CharClassesStatus::Normal, + } + } + CharClassesStatus::BlockComment(deepness) => { + if deepness == 0 { + // This is the closing '/' + assert_eq!(chr, '/'); + self.status = CharClassesStatus::Normal; + return Some((CodeCharKind::Comment, item)); + } + self.status = match self.base.peek() { + Some(next) if next.get_char() == '/' && chr == '*' => + CharClassesStatus::BlockCommentClosing(deepness - 1), + Some(next) if next.get_char() == '*' && chr == '/' => + CharClassesStatus::BlockCommentOpening(deepness + 1), + _ => CharClassesStatus::BlockComment(deepness), + }; + return Some((CodeCharKind::Comment, item)); + } + CharClassesStatus::BlockCommentOpening(deepness) => { + assert_eq!(chr, '*'); + self.status = CharClassesStatus::BlockComment(deepness); + return Some((CodeCharKind::Comment, item)); + } + CharClassesStatus::BlockCommentClosing(deepness) => { + assert_eq!(chr, '/'); + self.status = if deepness == 0 { + CharClassesStatus::Normal + } else { + CharClassesStatus::BlockComment(deepness) + }; + return Some((CodeCharKind::Comment, item)); + } + CharClassesStatus::LineComment => { + self.status = match chr { + '\n' => CharClassesStatus::Normal, + _ => CharClassesStatus::LineComment, + }; + return Some((CodeCharKind::Comment, item)); + } + }; + return Some((CodeCharKind::Normal, item)); + } +} diff --git a/src/expr.rs b/src/expr.rs index 14659815d72..cbcecc4cdcf 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -15,7 +15,7 @@ use StructLitStyle; use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width}; use visitor::FmtVisitor; use config::BlockIndentStyle; -use comment::{FindUncommented, rewrite_comment}; +use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; @@ -518,8 +518,7 @@ fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { let snippet = codemap.span_to_snippet(block.span).unwrap(); - // FIXME: fails when either // or /* is contained in a string literal. - !snippet.contains("//") && !snippet.contains("/*") + !contains_comment(&snippet) } fn rewrite_match(context: &RewriteContext, -- cgit 1.4.1-3-g733a5 From 1f974fca014b0538422dfe42fd97723d832384aa Mon Sep 17 00:00:00 2001 From: Mika Attila Date: Fri, 28 Aug 2015 23:51:26 +0200 Subject: Simplify match expression --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index c527ae1504a..2dc0168aa7f 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -53,7 +53,7 @@ fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> { fn execute() -> i32 { let (args, write_mode) = match determine_params(std::env::args()) { - Some((args, write_mode)) => (args, write_mode), + Some(params) => params, None => return 1, }; -- cgit 1.4.1-3-g733a5 From 6cf74956b3dcfda950c1e353e30415f377ae683e Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sun, 30 Aug 2015 23:15:14 -0400 Subject: Avoid an integer underflow panic. Fixes #229. --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e1778dc8a30..332d1f5a2f3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1026,7 +1026,7 @@ fn rewrite_field(context: &RewriteContext, -> Option { let name = &field.ident.node.to_string(); let overhead = name.len() + 2; - let expr = field.expr.rewrite(context, width - overhead, offset + overhead); + let expr = field.expr.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); expr.map(|s| format!("{}: {}", name, s)) } -- cgit 1.4.1-3-g733a5 From a896d91ff681f6113db00dacb660c2088c0bbbbe Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 31 Aug 2015 19:15:40 +0200 Subject: Fix offset for unary operations Fixes https://github.com/nrc/rustfmt/issues/227. --- src/expr.rs | 7 +++---- tests/source/expr.rs | 6 ++++++ tests/target/expr.rs | 7 +++++++ 3 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 332d1f5a2f3..2bcb1d6d727 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1134,11 +1134,10 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::UnNot => "!", ast::UnOp::UnNeg => "-", }; + let operator_len = operator_str.len(); - let subexpr = - try_opt!(expr.rewrite(context, try_opt!(width.checked_sub(operator_str.len())), offset)); - - Some(format!("{}{}", operator_str, subexpr)) + expr.rewrite(context, try_opt!(width.checked_sub(operator_len)), offset + operator_len) + .map(|r| format!("{}{}", operator_str, r)) } fn rewrite_assignment(context: &RewriteContext, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 85ee7727451..d5e98f959d1 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -105,3 +105,9 @@ fn qux() { // A block with a comment. } } + +fn issue227() { + { + let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 45c654b738f..afc152ac828 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -139,3 +139,10 @@ fn qux() { // A block with a comment. } } + +fn issue227() { + { + let handler = box DocumentProgressHandler::new(addr, + DocumentProgressTask::DOMContentLoaded); + } +} -- cgit 1.4.1-3-g733a5 From 0f4bf9b3ba81fd7324907ec29400fb210c92b9d0 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 31 Aug 2015 19:30:00 +0200 Subject: Fix some potential arithmetic underflow issues There have been many of this sort already. These were just bugs waiting to happen. --- src/expr.rs | 52 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2bcb1d6d727..28ed927b05e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -219,7 +219,8 @@ fn rewrite_closure(capture: ast::CaptureClause, // 1 = the separating space between arguments and the body. let extra_offset = extra_offset(&prefix, offset) + 1; - let rewrite = inner_expr.rewrite(context, width - extra_offset, offset + extra_offset); + let budget = try_opt!(width.checked_sub(extra_offset)); + let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); // Checks if rewrite succeeded and fits on a single line. let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false); @@ -263,7 +264,8 @@ impl Rewrite for ast::Block { if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() - format!("unsafe {} ", rewrite_comment(trimmed, true, width - 9, offset + 7)) + let budget = try_opt!(width.checked_sub(9)); + format!("unsafe {} ", rewrite_comment(trimmed, true, budget, offset + 7)) } else { "unsafe ".to_owned() } @@ -357,7 +359,7 @@ impl<'a> Rewrite for Loop<'a> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { let label_string = rewrite_label(self.label); // 2 = " {".len() - let inner_width = width - self.keyword.len() - 2 - label_string.len(); + let inner_width = try_opt!(width.checked_sub(self.keyword.len() + 2 + label_string.len())); let inner_offset = offset + self.keyword.len() + label_string.len(); let pat_expr_string = match self.cond { @@ -393,14 +395,17 @@ fn rewrite_range(context: &RewriteContext, offset: usize) -> Option { let left_string = match left { - Some(expr) => try_opt!(expr.rewrite(context, width - 2, offset)), + Some(expr) => { + // 2 = .. + let max_width = try_opt!(width.checked_sub(2)); + try_opt!(expr.rewrite(context, max_width, offset)) + } None => String::new(), }; let right_string = match right { Some(expr) => { - // 2 = .. - let max_width = (width - 2).checked_sub(left_string.len()).unwrap_or(0); + let max_width = try_opt!(width.checked_sub(left_string.len() + 2)); try_opt!(expr.rewrite(context, max_width, offset + 2 + left_string.len())) } None => String::new(), @@ -532,7 +537,8 @@ fn rewrite_match(context: &RewriteContext, } // `match `cond` {` - let cond_str = try_opt!(cond.rewrite(context, width - 8, offset + 6)); + let cond_budget = try_opt!(width.checked_sub(8)); + let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6)); let mut result = format!("match {} {{", cond_str); let block_indent = context.block_indent; @@ -632,17 +638,20 @@ impl Rewrite for ast::Arm { }; // Patterns - let pat_strs = try_opt!(pats.iter().map(|p| p.rewrite(context, - // 5 = ` => {` - width - 5, - offset + context.config.tab_spaces)) + // 5 = ` => {` + let pat_budget = try_opt!(width.checked_sub(5)); + let pat_strs = try_opt!(pats.iter().map(|p| { + p.rewrite(context, + pat_budget, + offset + context.config.tab_spaces) + }) .collect::>>()); let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); // Add ` | `.len(). total_width += (pat_strs.len() - 1) * 3; - let mut vertical = total_width > width - 5 || pat_strs.iter().any(|p| p.contains('\n')); + let mut vertical = total_width > pat_budget || pat_strs.iter().any(|p| p.contains('\n')); if !vertical { // If the patterns were previously stacked, keep them stacked. // FIXME should be an option. @@ -710,9 +719,8 @@ impl Rewrite for ast::Arm { return None; } - let body_str = try_opt!(body.rewrite(context, - width - context.config.tab_spaces, - nested_indent)); + let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); + let body_str = try_opt!(body.rewrite(context, body_budget, nested_indent)); Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, @@ -775,9 +783,8 @@ fn rewrite_pat_expr(context: &RewriteContext, let pat_offset = offset + matcher.len(); let mut result = match pat { Some(pat) => { - let pat_string = try_opt!(pat.rewrite(context, - width - connector.len() - matcher.len(), - pat_offset)); + let pat_budget = try_opt!(width.checked_sub(connector.len() + matcher.len())); + let pat_string = try_opt!(pat.rewrite(context, pat_budget, pat_offset)); format!("{}{}{}", matcher, pat_string, connector) } None => String::new(), @@ -930,7 +937,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } // 2 = " {".len() - let path_str = try_opt!(path.rewrite(context, width - 2, offset)); + let path_budget = try_opt!(width.checked_sub(2)); + let path_str = try_opt!(path.rewrite(context, path_budget, offset)); // Foo { a: Foo } - indent is +3, width is -5. let h_budget = try_opt!(width.checked_sub(path_str.len() + 5)); @@ -1041,7 +1049,8 @@ fn rewrite_tuple_lit(context: &RewriteContext, // In case of length 1, need a trailing comma if items.len() == 1 { // 3 = "(" + ",)" - return items[0].rewrite(context, width - 3, indent).map(|s| format!("({},)", s)); + let budget = try_opt!(width.checked_sub(3)); + return items[0].rewrite(context, budget, indent).map(|s| format!("({},)", s)); } let items = itemize_list(context.codemap, @@ -1057,7 +1066,8 @@ fn rewrite_tuple_lit(context: &RewriteContext, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); - let fmt = ListFormatting::for_fn(width - 2, indent); + let budget = try_opt!(width.checked_sub(2)); + let fmt = ListFormatting::for_fn(budget, indent); Some(format!("({})", write_list(&items.collect::>(), &fmt))) } -- cgit 1.4.1-3-g733a5 From 4b3262f514066ef8ac5ad82b445f111b91fe3990 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 15:39:37 +1200 Subject: Add a test module to comments --- src/comment.rs | 140 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 9c97325ec96..f692337cacc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -93,26 +93,6 @@ fn left_trim_comment_line<'a>(line: &'a str) -> &'a str { } } -#[test] -fn format_comments() { - assert_eq!("/* test */", rewrite_comment(" //test", true, 100, 100)); - assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, 0)); - - assert_eq!("// A multi line comment\n // between args.", - rewrite_comment("// A multi line comment\n // between args.", - false, - 60, - 12)); - - let input = "// comment"; - let expected = "/* com\n \ - * men\n \ - * t */"; - assert_eq!(expected, rewrite_comment(input, true, 9, 69)); - - assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); -} - pub trait FindUncommented { fn find_uncommented(&self, pat: &str) -> Option; } @@ -142,31 +122,6 @@ impl FindUncommented for str { } } -#[test] -fn test_find_uncommented() { - fn check(haystack: &str, needle: &str, expected: Option) { - println!("haystack {:?}, needle: {:?}", haystack, needle); - assert_eq!(expected, haystack.find_uncommented(needle)); - } - - check("/*/ */test", "test", Some(6)); - check("//test\ntest", "test", Some(7)); - check("/* comment only */", "whatever", None); - check("/* comment */ some text /* more commentary */ result", "result", Some(46)); - check("sup // sup", "p", Some(2)); - check("sup", "x", None); - check("π? /**/ π is nice!", "π is nice", Some(9)); - check("/*sup yo? \n sup*/ sup", "p", Some(20)); - check("hel/*lohello*/lo", "hello", None); - check("acb", "ab", None); - check(",/*A*/ ", ",", Some(0)); - check("abc", "abc", Some(0)); - check("/* abc */", "abc", None); - check("/**/abc/* */", "abc", Some(4)); - check("\"/* abc */\"", "abc", Some(4)); - check("\"/* abc", "abc", Some(4)); -} - // Returns the first byte position after the first comment. The given string // is expected to be prefixed by a comment, including delimiters. // Good: "/* /* inner */ outer */ code();" @@ -204,27 +159,6 @@ pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment ) } -pub fn uncommented(text: &str) -> String { - CharClasses::new(text.chars()).filter_map(|(s, c)| match s { - CodeCharKind::Normal => Some(c), - CodeCharKind::Comment => None - }).collect() -} - -#[test] -fn test_uncommented() { - assert_eq!(&uncommented("abc/*...*/"), "abc"); - assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); - assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); -} - -#[test] -fn test_contains_comment() { - assert_eq!(contains_comment("abc"), false); - assert_eq!(contains_comment("abc // qsdf"), true); - assert_eq!(contains_comment("abc /* kqsdf"), true); - assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); -} struct CharClasses where T: Iterator, @@ -358,3 +292,77 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { return Some((CodeCharKind::Normal, item)); } } + +#[cfg(test)] +mod test { + use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented}; + + #[test] + fn format_comments() { + assert_eq!("/* test */", rewrite_comment(" //test", true, 100, 100)); + assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, 0)); + + assert_eq!("// A multi line comment\n // between args.", + rewrite_comment("// A multi line comment\n // between args.", + false, + 60, + 12)); + + let input = "// comment"; + let expected = "/* com\n \ + * men\n \ + * t */"; + assert_eq!(expected, rewrite_comment(input, true, 9, 69)); + + assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); + } + + // This is probably intended to be a non-test fn, but it is not used. I'm + // keeping it around unless it helps us test stuff. + fn uncommented(text: &str) -> String { + CharClasses::new(text.chars()).filter_map(|(s, c)| match s { + CodeCharKind::Normal => Some(c), + CodeCharKind::Comment => None + }).collect() + } + + #[test] + fn test_uncommented() { + assert_eq!(&uncommented("abc/*...*/"), "abc"); + assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); + } + + #[test] + fn test_contains_comment() { + assert_eq!(contains_comment("abc"), false); + assert_eq!(contains_comment("abc // qsdf"), true); + assert_eq!(contains_comment("abc /* kqsdf"), true); + assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); + } + + #[test] + fn test_find_uncommented() { + fn check(haystack: &str, needle: &str, expected: Option) { + println!("haystack {:?}, needle: {:?}", haystack, needle); + assert_eq!(expected, haystack.find_uncommented(needle)); + } + + check("/*/ */test", "test", Some(6)); + check("//test\ntest", "test", Some(7)); + check("/* comment only */", "whatever", None); + check("/* comment */ some text /* more commentary */ result", "result", Some(46)); + check("sup // sup", "p", Some(2)); + check("sup", "x", None); + check("π? /**/ π is nice!", "π is nice", Some(9)); + check("/*sup yo? \n sup*/ sup", "p", Some(20)); + check("hel/*lohello*/lo", "hello", None); + check("acb", "ab", None); + check(",/*A*/ ", ",", Some(0)); + check("abc", "abc", Some(0)); + check("/* abc */", "abc", None); + check("/**/abc/* */", "abc", Some(4)); + check("\"/* abc */\"", "abc", Some(4)); + check("\"/* abc", "abc", Some(4)); + } +} -- cgit 1.4.1-3-g733a5 From 89cda8d43a92f16060319515343b69f5cbf3e1da Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 17:06:41 +1200 Subject: Option to pack fn args on fewer lines --- src/config.rs | 23 ++++++++++++++++++++++- src/items.rs | 2 +- tests/config/small_tabs.toml | 1 + tests/source/fn-custom.rs | 13 +++++++++++++ tests/target/fn-custom.rs | 15 +++++++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 tests/source/fn-custom.rs create mode 100644 tests/target/fn-custom.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 02ee8e63789..1abdc9e80b7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,7 +11,7 @@ extern crate toml; use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle}; -use lists::SeparatorTactic; +use lists::{SeparatorTactic, ListTactic}; use issues::ReportTactic; #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -26,6 +26,25 @@ pub enum BlockIndentStyle { impl_enum_decodable!(BlockIndentStyle, Inherit, Tabbed, Visual); +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum Density { + // Fit as much on one line as possible. + Compressed, + // Use more lines. + Tall, +} + +impl_enum_decodable!(Density, Compressed, Tall); + +impl Density { + pub fn to_list_tactic(self) -> ListTactic { + match self { + Density::Compressed => ListTactic::Mixed, + Density::Tall => ListTactic::HorizontalVertical, + } + } +} + macro_rules! create_config { ($($i:ident: $ty:ty),+ $(,)*) => ( #[derive(RustcDecodable, Clone)] @@ -70,6 +89,7 @@ create_config! { fn_brace_style: BraceStyle, fn_return_indent: ReturnIndent, fn_args_paren_newline: bool, + fn_args_layout: Density, struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, struct_lit_style: StructLitStyle, @@ -94,6 +114,7 @@ impl Default for Config { fn_brace_style: BraceStyle::SameLineWhere, fn_return_indent: ReturnIndent::WithArgs, fn_args_paren_newline: true, + fn_args_layout: Density::Tall, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, struct_lit_style: StructLitStyle::BlockIndent, diff --git a/src/items.rs b/src/items.rs index bcc851a5b35..18cf58b667b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -342,7 +342,7 @@ impl<'a> FmtVisitor<'a> { } let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, + tactic: self.config.fn_args_layout.to_list_tactic(), separator: ",", trailing_separator: SeparatorTactic::Never, indent: arg_indent, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 1b4ab5cb7e9..c05f173177b 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -6,6 +6,7 @@ newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true +fn_args_layout = "Tall" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" struct_lit_style = "BlockIndent" diff --git a/tests/source/fn-custom.rs b/tests/source/fn-custom.rs new file mode 100644 index 00000000000..77ced4c5e0e --- /dev/null +++ b/tests/source/fn-custom.rs @@ -0,0 +1,13 @@ +// rustfmt-fn_args_layout: Compressed +// Test some of the ways function signatures can be customised. + +// Test compressed layout of args. +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } +} diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs new file mode 100644 index 00000000000..01abeaebb9e --- /dev/null +++ b/tests/target/fn-custom.rs @@ -0,0 +1,15 @@ +// rustfmt-fn_args_layout: Compressed +// Test some of the ways function signatures can be customised. + +// Test compressed layout of args. +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } +} -- cgit 1.4.1-3-g733a5 From 0413c47a09d24ecd4494b2dc73442b88087f1020 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 17:22:00 +1200 Subject: Support different tabbing of function args (Although, frankly anything other than visual is deeply wrong). --- src/config.rs | 2 ++ src/items.rs | 12 ++++++++++-- tests/config/small_tabs.toml | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 1abdc9e80b7..8ba88725d01 100644 --- a/src/config.rs +++ b/src/config.rs @@ -90,6 +90,7 @@ create_config! { fn_return_indent: ReturnIndent, fn_args_paren_newline: bool, fn_args_layout: Density, + fn_arg_indent: BlockIndentStyle, struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, struct_lit_style: StructLitStyle, @@ -115,6 +116,7 @@ impl Default for Config { fn_return_indent: ReturnIndent::WithArgs, fn_args_paren_newline: true, fn_args_layout: Density::Tall, + fn_arg_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, struct_lit_style: StructLitStyle::BlockIndent, diff --git a/src/items.rs b/src/items.rs index 18cf58b667b..694662b4eed 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,7 +18,7 @@ use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; use rewrite::Rewrite; -use config::Config; +use config::{Config, BlockIndentStyle}; use syntax::{ast, abi}; use syntax::codemap::{self, Span, BytePos}; @@ -237,6 +237,7 @@ impl<'a> FmtVisitor<'a> { explicit_self, one_line_budget, multi_line_budget, + indent, arg_indent, args_span)); result.push(')'); @@ -293,6 +294,7 @@ impl<'a> FmtVisitor<'a> { explicit_self: Option<&ast::ExplicitSelf>, one_line_budget: usize, multi_line_budget: usize, + indent: usize, arg_indent: usize, span: Span) -> String { @@ -341,11 +343,17 @@ impl<'a> FmtVisitor<'a> { item.item = arg; } + let indent = match self.config.fn_arg_indent { + BlockIndentStyle::Inherit => indent, + BlockIndentStyle::Tabbed => indent + self.config.tab_spaces, + BlockIndentStyle::Visual => arg_indent, + }; + let fmt = ListFormatting { tactic: self.config.fn_args_layout.to_list_tactic(), separator: ",", trailing_separator: SeparatorTactic::Never, - indent: arg_indent, + indent: indent, h_width: one_line_budget, v_width: multi_line_budget, ends_with_newline: false, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index c05f173177b..d489f960917 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -7,6 +7,7 @@ fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_layout = "Tall" +fn_arg_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" struct_lit_style = "BlockIndent" -- cgit 1.4.1-3-g733a5 From fc2fb8be43debb483d9bb94e334d298e39ead24f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 18:20:17 +1200 Subject: Support different indent styles for generics --- src/config.rs | 2 ++ src/items.rs | 29 ++++++++++++++++++++++------- tests/config/small_tabs.toml | 1 + tests/source/fn-custom-2.rs | 25 +++++++++++++++++++++++++ tests/source/fn-custom-3.rs | 25 +++++++++++++++++++++++++ tests/target/fn-custom-2.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ tests/target/fn-custom-3.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 tests/source/fn-custom-2.rs create mode 100644 tests/source/fn-custom-3.rs create mode 100644 tests/target/fn-custom-2.rs create mode 100644 tests/target/fn-custom-3.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 8ba88725d01..fdfca063172 100644 --- a/src/config.rs +++ b/src/config.rs @@ -91,6 +91,7 @@ create_config! { fn_args_paren_newline: bool, fn_args_layout: Density, fn_arg_indent: BlockIndentStyle, + generics_indent: BlockIndentStyle, struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, struct_lit_style: StructLitStyle, @@ -117,6 +118,7 @@ impl Default for Config { fn_args_paren_newline: true, fn_args_layout: Density::Tall, fn_arg_indent: BlockIndentStyle::Visual, + generics_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, struct_lit_style: StructLitStyle::BlockIndent, diff --git a/src/items.rs b/src/items.rs index 694662b4eed..ae440826bdf 100644 --- a/src/items.rs +++ b/src/items.rs @@ -196,6 +196,7 @@ impl<'a> FmtVisitor<'a> { // Generics. let generics_indent = indent + result.len(); result.push_str(&self.rewrite_generics(generics, + indent, generics_indent, codemap::mk_sp(span.lo, span_for_return(&fd.output).lo))); @@ -432,6 +433,7 @@ impl<'a> FmtVisitor<'a> { let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); let generics_str = self.format_generics(generics, " {", + self.block_indent, self.block_indent + self.config.tab_spaces, codemap::mk_sp(span.lo, body_start)); @@ -573,6 +575,7 @@ impl<'a> FmtVisitor<'a> { let generics_str = match generics { Some(g) => self.format_generics(g, opener, + offset, offset + header_str.len(), codemap::mk_sp(span.lo, struct_def.fields[0].span.lo)), @@ -670,9 +673,10 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, opener: &str, offset: usize, + generics_offset: usize, span: Span) -> String { - let mut result = self.rewrite_generics(generics, offset, span); + let mut result = self.rewrite_generics(generics, offset, generics_offset, span); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { result.push_str(&self.rewrite_where_clause(&generics.where_clause, @@ -722,7 +726,12 @@ impl<'a> FmtVisitor<'a> { } } - fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span) -> String { + fn rewrite_generics(&self, + generics: &ast::Generics, + offset: usize, + generics_offset: usize, + span: Span) + -> String { // FIXME convert bounds to where clauses where they get too big or if // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; @@ -731,18 +740,24 @@ impl<'a> FmtVisitor<'a> { return String::new(); } - let budget = self.config.max_width - offset - 2; + let offset = match self.config.generics_indent { + BlockIndentStyle::Inherit => offset, + BlockIndentStyle::Tabbed => offset + self.config.tab_spaces, + // 1 = < + BlockIndentStyle::Visual => generics_offset + 1, + }; + + let h_budget = self.config.max_width - generics_offset - 2; // TODO might need to insert a newline if the generics are really long // Strings for the generics. - // 1 = < let context = self.get_context(); // FIXME: don't unwrap let lt_strs = lifetimes.iter().map(|lt| { - lt.rewrite(&context, budget, offset + 1).unwrap() + lt.rewrite(&context, h_budget, offset).unwrap() }); let ty_strs = tys.iter().map(|ty_param| { - ty_param.rewrite(&context, budget, offset + 1).unwrap() + ty_param.rewrite(&context, h_budget, offset).unwrap() }); // Extract comments between generics. @@ -770,7 +785,7 @@ impl<'a> FmtVisitor<'a> { item.item = ty; } - let fmt = ListFormatting::for_fn(budget, offset + 1); + let fmt = ListFormatting::for_fn(h_budget, offset); format!("<{}>", write_list(&items, &fmt)) } diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index d489f960917..e621547a010 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_layout = "Tall" fn_arg_indent = "Visual" +generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" struct_lit_style = "BlockIndent" diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs new file mode 100644 index 00000000000..1b7e6ad78ad --- /dev/null +++ b/tests/source/fn-custom-2.rs @@ -0,0 +1,25 @@ +// rustfmt-fn_arg_indent: Inherit +// rustfmt-generics_indent: Tabbed +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); + } +} + +struct Foo { + foo: Foo, +} diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs new file mode 100644 index 00000000000..68939eee6b5 --- /dev/null +++ b/tests/source/fn-custom-3.rs @@ -0,0 +1,25 @@ +// rustfmt-fn_arg_indent: Tabbed +// rustfmt-generics_indent: Inherit +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); + } +} + +struct Foo { + foo: Foo, +} diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs new file mode 100644 index 00000000000..1bb7ef401ec --- /dev/null +++ b/tests/target/fn-custom-2.rs @@ -0,0 +1,44 @@ +// rustfmt-fn_arg_indent: Inherit +// rustfmt-generics_indent: Tabbed +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, +b: Bbbbbbbbbbbbbbbb, +c: Ccccccccccccccccc, +d: Ddddddddddddddddddddddddd, +e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> + (a: Aaaaaaaaaaaaaaa) { + bar(); +} + +impl Foo { + fn foo(self, + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> + (a: Aaaaaaaaaaaaaaa) { + bar(); + } +} + +struct Foo +{ + foo: Foo, +} diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs new file mode 100644 index 00000000000..61194dd04f3 --- /dev/null +++ b/tests/target/fn-custom-3.rs @@ -0,0 +1,44 @@ +// rustfmt-fn_arg_indent: Tabbed +// rustfmt-generics_indent: Inherit +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, +TTTTTTTTTTTTT, +UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> + (a: Aaaaaaaaaaaaaaa) { + bar(); +} + +impl Foo { + fn foo(self, + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> + (a: Aaaaaaaaaaaaaaa) { + bar(); + } +} + +struct Foo +{ + foo: Foo, +} -- cgit 1.4.1-3-g733a5 From 6f3c329500fc0e1f67d454864f658e72a52183b3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 18:38:12 +1200 Subject: Support non-indented where clauses --- src/config.rs | 2 ++ src/items.rs | 9 +++++++-- tests/config/small_tabs.toml | 1 + tests/source/fn-custom-2.rs | 9 +++++++++ tests/target/fn-custom-2.rs | 13 +++++++++++++ 5 files changed, 32 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index fdfca063172..03b522be366 100644 --- a/src/config.rs +++ b/src/config.rs @@ -91,6 +91,7 @@ create_config! { fn_args_paren_newline: bool, fn_args_layout: Density, fn_arg_indent: BlockIndentStyle, + where_indent: BlockIndentStyle, // Visual will be treated like Tabbed generics_indent: BlockIndentStyle, struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, @@ -118,6 +119,7 @@ impl Default for Config { fn_args_paren_newline: true, fn_args_layout: Density::Tall, fn_arg_indent: BlockIndentStyle::Visual, + where_indent: BlockIndentStyle::Tabbed, generics_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, diff --git a/src/items.rs b/src/items.rs index ae440826bdf..94083e81c11 100644 --- a/src/items.rs +++ b/src/items.rs @@ -800,9 +800,14 @@ impl<'a> FmtVisitor<'a> { return String::new(); } + let extra_indent = match self.config.where_indent { + BlockIndentStyle::Inherit => 0, + BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => config.tab_spaces, + }; + let context = self.get_context(); // 6 = "where ".len() - let offset = indent + config.tab_spaces + 6; + let offset = indent + extra_indent + 6; let budget = self.config.ideal_width + self.config.leeway - offset; let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; let items = itemize_list(self.codemap, @@ -828,7 +833,7 @@ impl<'a> FmtVisitor<'a> { }; format!("\n{}where {}", - make_indent(indent + config.tab_spaces), + make_indent(indent + extra_indent), write_list(&items.collect::>(), &fmt)) } diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index e621547a010..3d6f01d7375 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_layout = "Tall" fn_arg_indent = "Visual" +where_indent = "Tabbed" generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index 1b7e6ad78ad..6c9238e8087 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,5 +1,6 @@ // rustfmt-fn_arg_indent: Inherit // rustfmt-generics_indent: Tabbed +// rustfmt-where_indent: Inherit // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { @@ -10,6 +11,10 @@ fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WW bar(); } +fn baz() where X: TTTTTTTT { + baz(); +} + impl Foo { fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { foo(); @@ -18,6 +23,10 @@ impl Foo { fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { bar(); } + + fn baz() where X: TTTTTTTT { + baz(); + } } struct Foo { diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index 1bb7ef401ec..e5c8af9a38b 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,5 +1,6 @@ // rustfmt-fn_arg_indent: Inherit // rustfmt-generics_indent: Tabbed +// rustfmt-where_indent: Inherit // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, @@ -17,6 +18,12 @@ fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, bar(); } +fn baz() +where X: TTTTTTTT +{ + baz(); +} + impl Foo { fn foo(self, a: Aaaaaaaaaaaaaaa, @@ -33,6 +40,12 @@ impl Foo { (a: Aaaaaaaaaaaaaaa) { bar(); } + + fn baz() + where X: TTTTTTTT + { + baz(); + } } struct Foo Date: Tue, 1 Sep 2015 18:53:16 +1200 Subject: Support where predicates on the same line --- src/config.rs | 2 ++ src/items.rs | 2 +- src/lists.rs | 2 ++ tests/config/small_tabs.toml | 1 + tests/source/fn-custom-2.rs | 5 +++++ tests/source/fn-custom-3.rs | 9 +++++++++ tests/target/fn-custom-2.rs | 8 ++++++++ tests/target/fn-custom-3.rs | 16 ++++++++++++++++ 8 files changed, 44 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 03b522be366..b788052a047 100644 --- a/src/config.rs +++ b/src/config.rs @@ -92,6 +92,7 @@ create_config! { fn_args_layout: Density, fn_arg_indent: BlockIndentStyle, where_indent: BlockIndentStyle, // Visual will be treated like Tabbed + where_layout: ListTactic, generics_indent: BlockIndentStyle, struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, @@ -120,6 +121,7 @@ impl Default for Config { fn_args_layout: Density::Tall, fn_arg_indent: BlockIndentStyle::Visual, where_indent: BlockIndentStyle::Tabbed, + where_layout: ListTactic::Vertical, generics_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, diff --git a/src/items.rs b/src/items.rs index 94083e81c11..d2265fe9db1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -823,7 +823,7 @@ impl<'a> FmtVisitor<'a> { span_end); let fmt = ListFormatting { - tactic: ListTactic::Vertical, + tactic: self.config.where_layout, separator: ",", trailing_separator: SeparatorTactic::Never, indent: offset, diff --git a/src/lists.rs b/src/lists.rs index 931baaa1073..3b9bb3f4af2 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -28,6 +28,8 @@ pub enum ListTactic { Mixed, } +impl_enum_decodable!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); + #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum SeparatorTactic { Always, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 3d6f01d7375..21d12c7d4ea 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -9,6 +9,7 @@ fn_args_paren_newline = true fn_args_layout = "Tall" fn_arg_indent = "Visual" where_indent = "Tabbed" +where_layout = "Vertical" generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index 6c9238e8087..a45f5501ea7 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,6 +1,7 @@ // rustfmt-fn_arg_indent: Inherit // rustfmt-generics_indent: Tabbed // rustfmt-where_indent: Inherit +// rustfmt-where_layout: Mixed // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { @@ -15,6 +16,10 @@ fn baz() where X: TTTTTTTT { baz(); } +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + impl Foo { fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { foo(); diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs index 68939eee6b5..e63b642d19c 100644 --- a/tests/source/fn-custom-3.rs +++ b/tests/source/fn-custom-3.rs @@ -1,5 +1,6 @@ // rustfmt-fn_arg_indent: Tabbed // rustfmt-generics_indent: Inherit +// rustfmt-where_layout: HorizontalVertical // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { @@ -10,6 +11,14 @@ fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WW bar(); } +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + impl Foo { fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { foo(); diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index e5c8af9a38b..acac301fa53 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,6 +1,7 @@ // rustfmt-fn_arg_indent: Inherit // rustfmt-generics_indent: Tabbed // rustfmt-where_indent: Inherit +// rustfmt-where_layout: Mixed // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, @@ -24,6 +25,13 @@ where X: TTTTTTTT baz(); } +fn qux() +where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +{ + baz(); +} + impl Foo { fn foo(self, a: Aaaaaaaaaaaaaaa, diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 61194dd04f3..110fcf36714 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -1,5 +1,6 @@ // rustfmt-fn_arg_indent: Tabbed // rustfmt-generics_indent: Inherit +// rustfmt-where_layout: HorizontalVertical // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, @@ -17,6 +18,21 @@ UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> bar(); } +fn qux() + where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +{ + baz(); +} + +fn qux() + where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +{ + baz(); +} + impl Foo { fn foo(self, a: Aaaaaaaaaaaaaaa, -- cgit 1.4.1-3-g733a5 From 6216dce14e92007d8943b11f37879683fc31f2a2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 19:04:41 +1200 Subject: Support where clause predicates at different indentations --- src/config.rs | 2 ++ src/items.rs | 12 ++++++++++-- tests/config/small_tabs.toml | 1 + tests/source/fn-custom-4.rs | 6 ++++++ tests/source/fn-custom-5.rs | 6 ++++++ tests/target/fn-custom-4.rs | 11 +++++++++++ tests/target/fn-custom-5.rs | 11 +++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/source/fn-custom-4.rs create mode 100644 tests/source/fn-custom-5.rs create mode 100644 tests/target/fn-custom-4.rs create mode 100644 tests/target/fn-custom-5.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b788052a047..12dfce4de33 100644 --- a/src/config.rs +++ b/src/config.rs @@ -93,6 +93,7 @@ create_config! { fn_arg_indent: BlockIndentStyle, where_indent: BlockIndentStyle, // Visual will be treated like Tabbed where_layout: ListTactic, + where_pred_indent: BlockIndentStyle, generics_indent: BlockIndentStyle, struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, @@ -122,6 +123,7 @@ impl Default for Config { fn_arg_indent: BlockIndentStyle::Visual, where_indent: BlockIndentStyle::Tabbed, where_layout: ListTactic::Vertical, + where_pred_indent: BlockIndentStyle::Visual, generics_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, diff --git a/src/items.rs b/src/items.rs index d2265fe9db1..b93db659eba 100644 --- a/src/items.rs +++ b/src/items.rs @@ -806,8 +806,16 @@ impl<'a> FmtVisitor<'a> { }; let context = self.get_context(); - // 6 = "where ".len() - let offset = indent + extra_indent + 6; + + let offset = match self.config.where_pred_indent { + BlockIndentStyle::Inherit => indent + extra_indent, + BlockIndentStyle::Tabbed => indent + extra_indent + config.tab_spaces, + // 6 = "where ".len() + BlockIndentStyle::Visual => indent + extra_indent + 6, + }; + // FIXME: if where_pred_indent != Visual, then the budgets below might + // be out by a char or two. + let budget = self.config.ideal_width + self.config.leeway - offset; let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; let items = itemize_list(self.codemap, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 21d12c7d4ea..912638c91f8 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -10,6 +10,7 @@ fn_args_layout = "Tall" fn_arg_indent = "Visual" where_indent = "Tabbed" where_layout = "Vertical" +where_pred_indent = "Visual" generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" diff --git a/tests/source/fn-custom-4.rs b/tests/source/fn-custom-4.rs new file mode 100644 index 00000000000..0293f1b1959 --- /dev/null +++ b/tests/source/fn-custom-4.rs @@ -0,0 +1,6 @@ +// rustfmt-where_pred_indent: Tabbed +// Test different indents. + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} diff --git a/tests/source/fn-custom-5.rs b/tests/source/fn-custom-5.rs new file mode 100644 index 00000000000..98f11a72eab --- /dev/null +++ b/tests/source/fn-custom-5.rs @@ -0,0 +1,6 @@ +// rustfmt-where_pred_indent: Inherit +// Test different indents. + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs new file mode 100644 index 00000000000..e1da6524565 --- /dev/null +++ b/tests/target/fn-custom-4.rs @@ -0,0 +1,11 @@ +// rustfmt-where_pred_indent: Tabbed +// Test different indents. + +fn qux() + where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +{ + baz(); +} diff --git a/tests/target/fn-custom-5.rs b/tests/target/fn-custom-5.rs new file mode 100644 index 00000000000..08c717538f2 --- /dev/null +++ b/tests/target/fn-custom-5.rs @@ -0,0 +1,11 @@ +// rustfmt-where_pred_indent: Inherit +// Test different indents. + +fn qux() + where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +{ + baz(); +} -- cgit 1.4.1-3-g733a5 From 55fe34a00ff09323035955129ee4b29908664998 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Tue, 1 Sep 2015 08:14:52 -0400 Subject: Format strings option https://github.com/nrc/rustfmt/issues/202 --- src/config.rs | 2 ++ src/expr.rs | 3 +++ tests/config/small_tabs.toml | 1 + tests/target/string-lit-custom.rs | 22 ++++++++++++++++++++++ 4 files changed, 28 insertions(+) create mode 100644 tests/target/string-lit-custom.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 02ee8e63789..bc420ab2c1c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -80,6 +80,7 @@ create_config! { expr_indent_style: BlockIndentStyle, closure_indent_style: BlockIndentStyle, single_line_if_else: bool, + format_strings: bool, } impl Default for Config { @@ -104,6 +105,7 @@ impl Default for Config { expr_indent_style: BlockIndentStyle::Tabbed, closure_indent_style: BlockIndentStyle::Visual, single_line_if_else: false, + format_strings: true, } } diff --git a/src/expr.rs b/src/expr.rs index 28ed927b05e..0945433319c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -828,6 +828,9 @@ fn rewrite_string_lit(context: &RewriteContext, width: usize, offset: usize) -> Option { + if context.config.format_strings == false { + return Some(context.snippet(span)); + } // Check if there is anything to fix: we always try to fixup multi-line // strings, or if the string is too long for the line. let l_loc = context.codemap.lookup_char_pos(span.lo); diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 1b4ab5cb7e9..386efe171c6 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -16,3 +16,4 @@ reorder_imports = false expr_indent_style = "Tabbed" closure_indent_style = "Visual" single_line_if_else = false +format_strings = true diff --git a/tests/target/string-lit-custom.rs b/tests/target/string-lit-custom.rs new file mode 100644 index 00000000000..50ebb97491b --- /dev/null +++ b/tests/target/string-lit-custom.rs @@ -0,0 +1,22 @@ +// rustfmt-format_strings: false + +fn main() { + let expected = "; ModuleID = \'foo\' + +; Function Attrs: nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 + +declare i32 @write(i32, i8*, i32) + +declare i32 @putchar(i32) + +declare i32 @getchar() + +define i32 @main() { +entry: + ret i32 0 +} + +attributes #0 = { nounwind } +"; +} -- cgit 1.4.1-3-g733a5 From 85ddf35385f69396178c58ee3a05d387df8c3b3f Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 1 Sep 2015 20:28:38 +0200 Subject: Rustup Fix breakage caused by rust commit 2076cdd. --- src/visitor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index b773a20fe6f..c9c84d7c2a2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -130,7 +130,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { let indent = self.block_indent; match fk { - visit::FkItemFn(ident, + visit::FnKind::ItemFn(ident, ref generics, ref unsafety, ref constness, @@ -148,7 +148,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { codemap::mk_sp(s.lo, b.span.lo)); self.buffer.push_str(&new_fn); } - visit::FkMethod(ident, ref sig, vis) => { + visit::FnKind::Method(ident, ref sig, vis) => { let new_fn = self.rewrite_fn(indent, ident, fd, @@ -161,7 +161,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { codemap::mk_sp(s.lo, b.span.lo)); self.buffer.push_str(&new_fn); } - visit::FkClosure(..) => {} + visit::FnKind::Closure => {} } self.last_pos = b.span.lo; -- cgit 1.4.1-3-g733a5 From 1ae2d417b88798dc94d60c59f67722e8d8d81f01 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 1 Sep 2015 20:42:07 +0200 Subject: Remove faulty shortcut in `rewrite_string_lit` Rustfmt would leave the literal unchanged when it did not exceed the column limit in its original position, not considering its position after formatting. --- src/comment.rs | 2 +- src/expr.rs | 10 ++-------- tests/source/string-lit.rs | 3 +++ tests/target/string-lit.rs | 5 +++++ 4 files changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index f692337cacc..e6e083d84bc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -354,7 +354,7 @@ mod test { check("/* comment */ some text /* more commentary */ result", "result", Some(46)); check("sup // sup", "p", Some(2)); check("sup", "x", None); - check("π? /**/ π is nice!", "π is nice", Some(9)); + check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); check("/*sup yo? \n sup*/ sup", "p", Some(20)); check("hel/*lohello*/lo", "hello", None); check("acb", "ab", None); diff --git a/src/expr.rs b/src/expr.rs index 0945433319c..20c56ccd34f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,7 @@ use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; use syntax::{ast, ptr}; -use syntax::codemap::{CodeMap, Pos, Span, BytePos, mk_sp}; +use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; use syntax::visit::Visitor; impl Rewrite for ast::Expr { @@ -831,13 +831,7 @@ fn rewrite_string_lit(context: &RewriteContext, if context.config.format_strings == false { return Some(context.snippet(span)); } - // Check if there is anything to fix: we always try to fixup multi-line - // strings, or if the string is too long for the line. - let l_loc = context.codemap.lookup_char_pos(span.lo); - let r_loc = context.codemap.lookup_char_pos(span.hi); - if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width { - return Some(context.snippet(span)); - } + let fmt = StringFormat { opener: "\"", closer: "\"", diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index 0c4a371df17..d7e57ea65c7 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -22,5 +22,8 @@ not remove formatting"#; + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + "stuff" } diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index f90461030ac..2107d902e19 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -25,5 +25,10 @@ not remove formatting"#; + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion("yyyyyyyyyyyyyyyyyyyyy\ + yyyyyyyyyyyyyyyyyyyyy\ + yyyyyyyyyyyyyyyyyyyyy\ + yyyyyyyyyy"); + "stuff" } -- cgit 1.4.1-3-g733a5 From 8d81aa1991a92bc23c8629f1ef79b9c5dc13ff93 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 1 Sep 2015 19:36:00 +1200 Subject: Support where clauses on the same line as the function decl where it all fits on one line. --- src/config.rs | 3 +++ src/items.rs | 33 +++++++++++++++++++++++++++------ tests/config/small_tabs.toml | 1 + tests/source/fn-custom-4.rs | 9 +++++++++ tests/target/fn-custom-4.rs | 12 ++++++++++++ 5 files changed, 52 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 12dfce4de33..457c2eb2adf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -91,6 +91,8 @@ create_config! { fn_args_paren_newline: bool, fn_args_layout: Density, fn_arg_indent: BlockIndentStyle, + where_density: Density, // Should we at least try to put the where clause on the same line as + // the rest of the function decl? where_indent: BlockIndentStyle, // Visual will be treated like Tabbed where_layout: ListTactic, where_pred_indent: BlockIndentStyle, @@ -121,6 +123,7 @@ impl Default for Config { fn_args_paren_newline: true, fn_args_layout: Density::Tall, fn_arg_indent: BlockIndentStyle::Visual, + where_density: Density::Tall, where_indent: BlockIndentStyle::Tabbed, where_layout: ListTactic::Vertical, where_pred_indent: BlockIndentStyle::Visual, diff --git a/src/items.rs b/src/items.rs index b93db659eba..cc431792c10 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,7 +18,7 @@ use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; use rewrite::Rewrite; -use config::{Config, BlockIndentStyle}; +use config::{Config, BlockIndentStyle, Density}; use syntax::{ast, abi}; use syntax::codemap::{self, Span, BytePos}; @@ -99,7 +99,7 @@ impl<'a> FmtVisitor<'a> { vis: ast::Visibility, span: Span) -> String { - let newline_brace = self.newline_for_brace(&generics.where_clause); + let mut newline_brace = self.newline_for_brace(&generics.where_clause); let mut result = self.rewrite_fn_base(indent, ident, @@ -113,6 +113,10 @@ impl<'a> FmtVisitor<'a> { span, newline_brace); + if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { + newline_brace = false; + } + // Prepare for the function body by possibly adding a newline and // indent. // FIXME we'll miss anything between the end of the signature and the @@ -281,10 +285,18 @@ impl<'a> FmtVisitor<'a> { } } + let where_density = if self.config.where_density == Density::Compressed && + !result.contains('\n') { + Density::Compressed + } else { + Density::Tall + }; + // Where clause. result.push_str(&self.rewrite_where_clause(where_clause, self.config, indent, + where_density, span.hi)); result @@ -682,6 +694,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&self.rewrite_where_clause(&generics.where_clause, self.config, self.block_indent, + Density::Tall, span.hi)); result.push_str(&make_indent(self.block_indent)); result.push('\n'); @@ -794,6 +807,7 @@ impl<'a> FmtVisitor<'a> { where_clause: &ast::WhereClause, config: &Config, indent: usize, + density: Density, span_end: BytePos) -> String { if where_clause.predicates.is_empty() { @@ -839,10 +853,17 @@ impl<'a> FmtVisitor<'a> { v_width: budget, ends_with_newline: true, }; - - format!("\n{}where {}", - make_indent(indent + extra_indent), - write_list(&items.collect::>(), &fmt)) + let preds_str = write_list(&items.collect::>(), &fmt); + + // 9 = " where ".len() + " {".len() + if density == Density::Tall || preds_str.contains('\n') || + indent + 9 + preds_str.len() > self.config.max_width { + format!("\n{}where {}", + make_indent(indent + extra_indent), + preds_str) + } else { + format!(" where {}", preds_str) + } } fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 912638c91f8..146ceb2a62c 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_layout = "Tall" fn_arg_indent = "Visual" +where_density = "Tall" where_indent = "Tabbed" where_layout = "Vertical" where_pred_indent = "Visual" diff --git a/tests/source/fn-custom-4.rs b/tests/source/fn-custom-4.rs index 0293f1b1959..7b3e4c4a163 100644 --- a/tests/source/fn-custom-4.rs +++ b/tests/source/fn-custom-4.rs @@ -1,6 +1,15 @@ // rustfmt-where_pred_indent: Tabbed +// rustfmt-where_density: Compressed // Test different indents. fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { baz(); } + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux(a: Aaaaaaaaaaaaaaaaa) where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs index e1da6524565..70ec49f34bc 100644 --- a/tests/target/fn-custom-4.rs +++ b/tests/target/fn-custom-4.rs @@ -1,4 +1,5 @@ // rustfmt-where_pred_indent: Tabbed +// rustfmt-where_density: Compressed // Test different indents. fn qux() @@ -9,3 +10,14 @@ fn qux() { baz(); } + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux(a: Aaaaaaaaaaaaaaaaa) + where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +{ + baz(); +} -- cgit 1.4.1-3-g733a5 From f81485d9d6a93baf86affbcc60d0ea84bedc3556 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 Sep 2015 08:56:37 +1200 Subject: Rename fn_args_layout to fn_args_density --- src/config.rs | 4 ++-- src/items.rs | 2 +- tests/config/small_tabs.toml | 2 +- tests/source/fn-custom.rs | 2 +- tests/target/fn-custom.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 1119f92bd62..329c67d2b0d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -89,7 +89,7 @@ create_config! { fn_brace_style: BraceStyle, fn_return_indent: ReturnIndent, fn_args_paren_newline: bool, - fn_args_layout: Density, + fn_args_density: Density, fn_arg_indent: BlockIndentStyle, where_density: Density, // Should we at least try to put the where clause on the same line as // the rest of the function decl? @@ -122,7 +122,7 @@ impl Default for Config { fn_brace_style: BraceStyle::SameLineWhere, fn_return_indent: ReturnIndent::WithArgs, fn_args_paren_newline: true, - fn_args_layout: Density::Tall, + fn_args_density: Density::Tall, fn_arg_indent: BlockIndentStyle::Visual, where_density: Density::Tall, where_indent: BlockIndentStyle::Tabbed, diff --git a/src/items.rs b/src/items.rs index cc431792c10..fd163cec680 100644 --- a/src/items.rs +++ b/src/items.rs @@ -363,7 +363,7 @@ impl<'a> FmtVisitor<'a> { }; let fmt = ListFormatting { - tactic: self.config.fn_args_layout.to_list_tactic(), + tactic: self.config.fn_args_density.to_list_tactic(), separator: ",", trailing_separator: SeparatorTactic::Never, indent: indent, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 4c220dbc5d2..08a0c22cc10 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -6,7 +6,7 @@ newline_style = "Unix" fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true -fn_args_layout = "Tall" +fn_args_density = "Tall" fn_arg_indent = "Visual" where_density = "Tall" where_indent = "Tabbed" diff --git a/tests/source/fn-custom.rs b/tests/source/fn-custom.rs index 77ced4c5e0e..b8d734bfbaf 100644 --- a/tests/source/fn-custom.rs +++ b/tests/source/fn-custom.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_args_density: Compressed // Test some of the ways function signatures can be customised. // Test compressed layout of args. diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index 01abeaebb9e..ad36de7a997 100644 --- a/tests/target/fn-custom.rs +++ b/tests/target/fn-custom.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Compressed +// rustfmt-fn_args_density: Compressed // Test some of the ways function signatures can be customised. // Test compressed layout of args. -- cgit 1.4.1-3-g733a5 From fae93abbdaa9d2bcf7a3c2cff0c5c7beadc62cc7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 Sep 2015 09:41:08 +1200 Subject: Support struct-like layouts for fn args --- src/config.rs | 4 ++- src/expr.rs | 8 ++--- src/items.rs | 23 ++++++++++--- src/lib.rs | 6 ++-- tests/config/small_tabs.toml | 3 +- tests/source/fn-custom-6.rs | 36 ++++++++++++++++++++ tests/source/struct_lits_visual.rs | 2 +- tests/target/fn-custom-6.rs | 70 ++++++++++++++++++++++++++++++++++++++ tests/target/struct_lits_visual.rs | 2 +- 9 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 tests/source/fn-custom-6.rs create mode 100644 tests/target/fn-custom-6.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 329c67d2b0d..1b4d79ab6ee 100644 --- a/src/config.rs +++ b/src/config.rs @@ -90,6 +90,7 @@ create_config! { fn_return_indent: ReturnIndent, fn_args_paren_newline: bool, fn_args_density: Density, + fn_args_layout: StructLitStyle, fn_arg_indent: BlockIndentStyle, where_density: Density, // Should we at least try to put the where clause on the same line as // the rest of the function decl? @@ -123,6 +124,7 @@ impl Default for Config { fn_return_indent: ReturnIndent::WithArgs, fn_args_paren_newline: true, fn_args_density: Density::Tall, + fn_args_layout: StructLitStyle::Visual, fn_arg_indent: BlockIndentStyle::Visual, where_density: Density::Tall, where_indent: BlockIndentStyle::Tabbed, @@ -131,7 +133,7 @@ impl Default for Config { generics_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, - struct_lit_style: StructLitStyle::BlockIndent, + struct_lit_style: StructLitStyle::Block, enum_trailing_comma: true, report_todo: ReportTactic::Always, report_fixme: ReportTactic::Never, diff --git a/src/expr.rs b/src/expr.rs index 20c56ccd34f..19b3693d94b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -940,10 +940,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // Foo { a: Foo } - indent is +3, width is -5. let h_budget = try_opt!(width.checked_sub(path_str.len() + 5)); let (indent, v_budget) = match context.config.struct_lit_style { - StructLitStyle::VisualIndent => { + StructLitStyle::Visual => { (offset + path_str.len() + 3, h_budget) } - StructLitStyle::BlockIndent => { + StructLitStyle::Block => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. let indent = context.block_indent + context.config.tab_spaces; @@ -1012,7 +1012,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let fields_str = write_list(&items.collect::>(), &fmt); match context.config.struct_lit_style { - StructLitStyle::BlockIndent if fields_str.contains('\n') => { + StructLitStyle::Block if fields_str.contains('\n') => { let inner_indent = make_indent(context.block_indent + context.config.tab_spaces); let outer_indent = make_indent(context.block_indent); Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) @@ -1020,7 +1020,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, _ => Some(format!("{} {{ {} }}", path_str, fields_str)), } - // FIXME if context.config.struct_lit_style == VisualIndent, but we run out + // FIXME if context.config.struct_lit_style == Visual, but we run out // of space, we should fall back to BlockIndent. } diff --git a/src/items.rs b/src/items.rs index fd163cec680..4d84a142045 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,7 +10,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. -use {ReturnIndent, BraceStyle}; +use {ReturnIndent, BraceStyle, StructLitStyle}; use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, end_typaram}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; @@ -225,6 +225,10 @@ impl<'a> FmtVisitor<'a> { result.push_str("(\n"); result.push_str(&make_indent(arg_indent)); } + } else if self.config.fn_args_layout == StructLitStyle::Block { + arg_indent = indent + self.config.tab_spaces; + result.push_str("(\n"); + result.push_str(&make_indent(arg_indent)); } else { result.push('('); } @@ -245,14 +249,20 @@ impl<'a> FmtVisitor<'a> { indent, arg_indent, args_span)); + if self.config.fn_args_layout == StructLitStyle::Block { + result.push('\n'); + } result.push(')'); // Return type. if !ret_str.is_empty() { // If we've already gone multi-line, or the return type would push // over the max width, then put the return type on a new line. - if result.contains("\n") || - result.len() + indent + ret_str.len() > self.config.max_width { + // Unless we are formatting args like a block, in which case there + // should always be room for the return type. + if (result.contains("\n") || + result.len() + indent + ret_str.len() > self.config.max_width) && + self.config.fn_args_layout != StructLitStyle::Block { let indent = match self.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, // TODO we might want to check that using the arg indent doesn't @@ -285,8 +295,11 @@ impl<'a> FmtVisitor<'a> { } } - let where_density = if self.config.where_density == Density::Compressed && - !result.contains('\n') { + let where_density = if (self.config.where_density == Density::Compressed && + (!result.contains('\n') || + self.config.fn_args_layout == StructLitStyle::Block)) || + (self.config.fn_args_layout == StructLitStyle::Block && + ret_str.is_empty()) { Density::Compressed } else { Density::Tall diff --git a/src/lib.rs b/src/lib.rs index f410f7e5468..83c0c5ae1b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,13 +133,13 @@ impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); pub enum StructLitStyle { // First line on the same line as the opening brace, all lines aligned with // the first line. - VisualIndent, + Visual, // First line is on a new line and all lines align with block indent. - BlockIndent, + Block, // FIXME Maybe we should also have an option to align types. } -impl_enum_decodable!(StructLitStyle, VisualIndent, BlockIndent); +impl_enum_decodable!(StructLitStyle, Visual, Block); enum ErrorKind { // Line has exceeded character limit diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 08a0c22cc10..c5122b760a0 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -7,6 +7,7 @@ fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" +fn_args_layout = "Visual" fn_arg_indent = "Visual" where_density = "Tall" where_indent = "Tabbed" @@ -15,7 +16,7 @@ where_pred_indent = "Visual" generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" -struct_lit_style = "BlockIndent" +struct_lit_style = "Block" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs new file mode 100644 index 00000000000..1042fa5bd88 --- /dev/null +++ b/tests/source/fn-custom-6.rs @@ -0,0 +1,36 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_indent: Inherit +// rustfmt-fn_brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index ea76a088a32..180a1229faa 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: VisualIndent +// rustfmt-struct_lit_style: Visual // Struct literal expressions. diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs new file mode 100644 index 00000000000..bea50c6a3ce --- /dev/null +++ b/tests/target/fn-custom-6.rs @@ -0,0 +1,70 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_indent: Inherit +// rustfmt-fn_brace_style: PreferSameLine +// Test different indents. + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) where T: UUUUUUUUUUU { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) where T: UUUUUUUUUUU { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) -> String +where T: UUUUUUUUUUU { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String +where T: UUUUUUUUUUU { + bar(); +} diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 77467a40ce7..4274c916777 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: VisualIndent +// rustfmt-struct_lit_style: Visual // Struct literal expressions. -- cgit 1.4.1-3-g733a5 From 97e92b35cc13c7afac277451db8997a2bf69678c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 Sep 2015 14:11:19 +1200 Subject: Preserve some whitespace between struct fields etc. --- src/items.rs | 4 +--- src/lists.rs | 62 +++++++++++++++++++++++++++++++++++-------------- tests/source/structs.rs | 28 ++++++++++++++++++++++ tests/target/structs.rs | 18 ++++++++++++++ 4 files changed, 92 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 4d84a142045..36728ce84fa 100644 --- a/src/items.rs +++ b/src/items.rs @@ -632,13 +632,11 @@ impl<'a> FmtVisitor<'a> { let break_line = !is_tuple || generics_str.contains('\n') || single_line_cost as usize + used_budget > self.config.max_width; - if break_line { + let tactic = if break_line { let indentation = make_indent(offset + self.config.tab_spaces); result.push('\n'); result.push_str(&indentation); - } - let tactic = if break_line { ListTactic::Vertical } else { ListTactic::Horizontal diff --git a/src/lists.rs b/src/lists.rs index 3b9bb3f4af2..6938e4eb4d4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -70,9 +70,11 @@ impl<'a> ListFormatting<'a> { pub struct ListItem { pub pre_comment: Option, - // Item should include attributes and doc comments + // Item should include attributes and doc comments. pub item: String, pub post_comment: Option, + // Whether there is extra whitespace before this item. + pub new_lines: bool, } impl ListItem { @@ -86,7 +88,7 @@ impl ListItem { } pub fn from_str>(s: S) -> ListItem { - ListItem { pre_comment: None, item: s.into(), post_comment: None } + ListItem { pre_comment: None, item: s.into(), post_comment: None, new_lines: false } } } @@ -206,10 +208,8 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St // Post-comments if tactic != ListTactic::Vertical && item.post_comment.is_some() { - let formatted_comment = rewrite_comment(item.post_comment.as_ref().unwrap(), - true, - formatting.v_width, - 0); + let comment = item.post_comment.as_ref().unwrap(); + let formatted_comment = rewrite_comment(comment, true, formatting.v_width, 0); result.push(' '); result.push_str(&formatted_comment); @@ -234,6 +234,10 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St result.push(' '); result.push_str(&formatted_comment); } + + if !last && tactic == ListTactic::Vertical && item.new_lines { + result.push('\n'); + } } result @@ -264,13 +268,14 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let white_space: &[_] = &[' ', '\t']; self.inner.next().map(|item| { + let mut new_lines = false; // Pre-comment let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap(); - let pre_snippet = pre_snippet.trim(); - let pre_comment = if !pre_snippet.is_empty() { - Some(pre_snippet.to_owned()) + let trimmed_pre_snippet = pre_snippet.trim(); + let pre_comment = if !trimmed_pre_snippet.is_empty() { + Some(trimmed_pre_snippet.to_owned()) } else { None }; @@ -307,7 +312,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> separator_index + 1) } // Potential *single* line comment. - (_, Some(j)) => { j + 1 } + (_, Some(j)) => j + 1, _ => post_snippet.len() } }, @@ -317,18 +322,40 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> } }; + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end-1..]; + let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet.find(|c: char| !c.is_whitespace()) + .unwrap_or(test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; + } + } + // Cleanup post-comment: strip separators and whitespace. self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let mut post_snippet = post_snippet[..comment_end].trim(); + let post_snippet = post_snippet[..comment_end].trim(); - if post_snippet.starts_with(',') { - post_snippet = post_snippet[1..].trim_matches(white_space); + let post_snippet_trimmed = if post_snippet.starts_with(',') { + post_snippet[1..].trim_matches(white_space) } else if post_snippet.ends_with(",") { - post_snippet = post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space); - } + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; - let post_comment = if !post_snippet.is_empty() { - Some(post_snippet.to_owned()) + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) } else { None }; @@ -337,6 +364,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> pre_comment: pre_comment, item: (self.get_item_string)(&item), post_comment: post_comment, + new_lines: new_lines, } }) } diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 68c7ff0df3c..76602a7a561 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -49,15 +49,43 @@ pub struct Foo<'a, Y: Baz> } struct Baz { + a: A, // Comment A b: B, // Comment B c: C, // Comment C + +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +struct Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + } struct Baz { // Comment A a: A, + // Comment B b: B, // Comment C diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 1f48c66b6a4..31e32a51b42 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -54,9 +54,27 @@ struct Baz { c: C, // Comment C } +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +struct Baz { + a: A, + + b: B, + c: C, + + d: D, +} + struct Baz { // Comment A a: A, + // Comment B b: B, // Comment C -- cgit 1.4.1-3-g733a5 From a5f8b37eeb3e388500e736579ce11533c254fd16 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 Sep 2015 14:29:47 +1200 Subject: Format match expressions properly when they appear on an overflowing line. --- src/expr.rs | 14 +++++++------- src/rewrite.rs | 17 +++++++++++++++++ src/visitor.rs | 2 ++ tests/target/match.rs | 9 +++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 19b3693d94b..f22dd04358f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -250,7 +250,7 @@ impl Rewrite for ast::Block { } let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config); - visitor.block_indent = context.block_indent; + visitor.block_indent = context.block_indent + context.overflow_indent; let prefix = match self.rules { ast::BlockCheckMode::PushUnsafeBlock(..) | @@ -541,9 +541,9 @@ fn rewrite_match(context: &RewriteContext, let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6)); let mut result = format!("match {} {{", cond_str); - let block_indent = context.block_indent; let nested_context = context.nested_context(); - let arm_indent_str = make_indent(nested_context.block_indent); + let arm_indent = nested_context.block_indent + context.overflow_indent; + let arm_indent_str = make_indent(arm_indent); let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{", @@ -579,8 +579,8 @@ fn rewrite_match(context: &RewriteContext, let arm_str = arm.rewrite(&nested_context, context.config.max_width - - nested_context.block_indent, - nested_context.block_indent); + arm_indent, + arm_indent); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); } else { @@ -594,7 +594,7 @@ fn rewrite_match(context: &RewriteContext, // match expression, but meh. result.push('\n'); - result.push_str(&make_indent(block_indent)); + result.push_str(&make_indent(context.block_indent + context.overflow_indent)); result.push('}'); Some(result) } @@ -1192,7 +1192,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, result.push_str(&format!("\n{}", make_indent(new_offset))); let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1)); - let rhs = try_opt!(ex.rewrite(&context, max_width, new_offset)); + let rhs = try_opt!(ex.rewrite(&context.overflow_context(), max_width, new_offset)); result.push_str(&rhs); } diff --git a/src/rewrite.rs b/src/rewrite.rs index 5f1549846b5..e3a239430a5 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -28,7 +28,14 @@ pub trait Rewrite { pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, pub config: &'a Config, + + // Indentation due to nesting of blocks. pub block_indent: usize, + // *Extra* indentation due to overflowing to the next line, e.g., + // let foo = + // bar(); + // The extra 4 spaces when formatting `bar()` is overflow_indent. + pub overflow_indent: usize, } impl<'a> RewriteContext<'a> { @@ -37,6 +44,16 @@ impl<'a> RewriteContext<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent + self.config.tab_spaces, + overflow_indent: self.overflow_indent, + } + } + + pub fn overflow_context(&self) -> RewriteContext<'a> { + RewriteContext { + codemap: self.codemap, + config: self.config, + block_indent: self.block_indent, + overflow_indent: self.overflow_indent + self.config.tab_spaces, } } diff --git a/src/visitor.rs b/src/visitor.rs index c9c84d7c2a2..0b29086daf6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -338,6 +338,7 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, + overflow_indent: 0, }; // 1 = ";" match vp.rewrite(&context, self.config.max_width - offset - 1, offset) { @@ -369,6 +370,7 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, + overflow_indent: 0, } } } diff --git a/tests/target/match.rs b/tests/target/match.rs index e5f1fad967a..88d63112e37 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -53,3 +53,12 @@ fn foo() { Blurb => { } }; } + +// Test that a match on an overflow line is laid out properly. +fn main() { + let sub_span = + match self.span.sub_span_after_keywooooooooooooooooooooord(use_item.span, keywords::As) { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; +} -- cgit 1.4.1-3-g733a5 From ce4d5aa39cf3a334a1281c613c9b56afec885030 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 Sep 2015 14:45:56 +1200 Subject: Fix a bug with alignment in one-line match arms --- src/expr.rs | 10 +++++----- tests/target/match.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f22dd04358f..e5e8bc7088c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -578,8 +578,7 @@ fn rewrite_match(context: &RewriteContext, result.push_str(&arm_indent_str); let arm_str = arm.rewrite(&nested_context, - context.config.max_width - - arm_indent, + context.config.max_width - arm_indent, arm_indent); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); @@ -694,7 +693,6 @@ impl Rewrite for ast::Arm { } else { "," }; - let nested_indent = context.block_indent + context.config.tab_spaces; // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() @@ -702,7 +700,7 @@ impl Rewrite for ast::Arm { let budget = context.config.max_width - line_start - comma.len() - 4; if let Some(ref body_str) = body.rewrite(context, budget, - nested_indent) { + line_start + 4) { if first_line_width(body_str) <= budget { return Some(format!("{}{} => {}{}", attr_str.trim_left(), @@ -720,7 +718,9 @@ impl Rewrite for ast::Arm { } let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let body_str = try_opt!(body.rewrite(context, body_budget, nested_indent)); + let body_str = try_opt!(body.rewrite(context, + body_budget, + context.block_indent)); Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, diff --git a/tests/target/match.rs b/tests/target/match.rs index 88d63112e37..eab8c604084 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -62,3 +62,18 @@ fn main() { None => sub_span, }; } + +// Test that one-line bodies align. +fn main() { + match r { + Variableeeeeeeeeeeeeeeeee => ("variable", + vec!("id","name","qualname","value","type","scopeid"), + true, + true), + Enummmmmmmmmmmmmmmmmmmmm => ("enum", vec!("id","qualname","scopeid","value"), true, true), + Variantttttttttttttttttttttttt => ("variant", + vec!("id","name","qualname","type","value","scopeid"), + true, + true), + } +} -- cgit 1.4.1-3-g733a5 From 183dac91a33562965645e3a4eb6fdc2908e0944e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 Sep 2015 15:36:17 +1200 Subject: Fix a bug where struct lits nested in fn calls were over-indented --- src/expr.rs | 22 ++++++++++++---------- src/rewrite.rs | 4 ++-- tests/source/struct_lits.rs | 7 +++++++ tests/target/struct_lits.rs | 7 +++++++ 4 files changed, 28 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e5e8bc7088c..e11c6e470f6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -203,7 +203,7 @@ fn rewrite_closure(capture: ast::CaptureClause, let fmt = ListFormatting::for_fn(argument_budget, argument_offset); let prefix = format!("{}|{}|", mover, write_list(&arg_items.collect::>(), &fmt)); - let block_indent = closure_block_indent(context, offset); + let closure_indent = closure_indent(context, offset); // Try to format closure body as a single line expression without braces. if body.stmts.is_empty() { @@ -232,11 +232,11 @@ fn rewrite_closure(capture: ast::CaptureClause, // We couldn't format the closure body as a single line expression; fall // back to block formatting. - let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; + let inner_context = context.overflow_context(closure_indent - context.block_indent); let body_rewrite = if let ast::Expr_::ExprBlock(ref inner) = body.expr.as_ref().unwrap().node { - inner.rewrite(inner_context, 0, 0) + inner.rewrite(&inner_context, 0, 0) } else { - body.rewrite(inner_context, 0, 0) + body.rewrite(&inner_context, 0, 0) }; Some(format!("{} {}", prefix, try_opt!(body_rewrite))) @@ -868,8 +868,8 @@ fn rewrite_call(context: &RewriteContext, // 2 is for parens. let remaining_width = try_opt!(width.checked_sub(extra_offset + 2)); let offset = offset + extra_offset + 1; - let block_indent = expr_block_indent(context, offset); - let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; + let inner_indent = expr_indent(context, offset); + let inner_context = context.overflow_context(inner_indent - context.block_indent); let items = itemize_list(context.codemap, args.iter(), @@ -878,7 +878,7 @@ fn rewrite_call(context: &RewriteContext, |item| item.span.hi, // Take old span when rewrite fails. |item| { - item.rewrite(inner_context, remaining_width, offset) + item.rewrite(&inner_context, remaining_width, offset) .unwrap_or(context.snippet(item.span)) }, callee.span.hi + BytePos(1), @@ -901,8 +901,8 @@ macro_rules! block_indent_helper { ); } -block_indent_helper!(expr_block_indent, expr_indent_style); -block_indent_helper!(closure_block_indent, closure_indent_style); +block_indent_helper!(expr_indent, expr_indent_style); +block_indent_helper!(closure_indent, closure_indent_style); fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, @@ -1192,7 +1192,9 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, result.push_str(&format!("\n{}", make_indent(new_offset))); let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1)); - let rhs = try_opt!(ex.rewrite(&context.overflow_context(), max_width, new_offset)); + let rhs = try_opt!(ex.rewrite(&context.overflow_context(context.config.tab_spaces), + max_width, + new_offset)); result.push_str(&rhs); } diff --git a/src/rewrite.rs b/src/rewrite.rs index e3a239430a5..49c09ac53d1 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -48,12 +48,12 @@ impl<'a> RewriteContext<'a> { } } - pub fn overflow_context(&self) -> RewriteContext<'a> { + pub fn overflow_context(&self, overflow: usize) -> RewriteContext<'a> { RewriteContext { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: self.overflow_indent + self.config.tab_spaces, + overflow_indent: overflow, } } diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 1caf20e99a5..8894508fd98 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -32,6 +32,13 @@ fn main() { second: Item }; + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + Diagram { /* o This graph demonstrates how * / \ significant whitespace is * o o preserved. diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 6dd4180a708..81c60381ed8 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -46,6 +46,13 @@ fn main() { second: Item, }; + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + Diagram { // o This graph demonstrates how // / \ significant whitespace is -- cgit 1.4.1-3-g733a5 From 61f642f6f89bfb364171587426be954207539b35 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Thu, 3 Sep 2015 23:38:12 -0400 Subject: Support unicode in string literals. --- Cargo.lock | 6 ++++++ Cargo.toml | 2 ++ src/expr.rs | 10 ++++++---- src/lib.rs | 5 +++-- src/string.rs | 44 ++++++++++++++++++++++++-------------------- src/utils.rs | 25 ------------------------- tests/source/string-lit.rs | 5 +++++ tests/target/string-lit.rs | 6 ++++++ 8 files changed, 52 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index be9e8be98ca..63854ccae46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", "term 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -87,6 +88,11 @@ dependencies = [ "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-segmentation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index 4716be7098e..377c88a955b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ git = "https://github.com/nrc/strings.rs.git" [dependencies] toml = "0.1.20" rustc-serialize = "0.3.14" +unicode-segmentation = "0.1.2" +regex = "0.1.41" [dev-dependencies] diff = "0.1.0" diff --git a/src/expr.rs b/src/expr.rs index e11c6e470f6..d82e34d6d80 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -28,8 +28,8 @@ impl Rewrite for ast::Expr { match self.node { ast::Expr_::ExprLit(ref l) => { match l.node { - ast::Lit_::LitStr(ref is, ast::StrStyle::CookedStr) => { - rewrite_string_lit(context, &is, l.span, width, offset) + ast::Lit_::LitStr(_, ast::StrStyle::CookedStr) => { + rewrite_string_lit(context, l.span, width, offset) } _ => Some(context.snippet(self.span)), } @@ -823,7 +823,6 @@ fn rewrite_pat_expr(context: &RewriteContext, } fn rewrite_string_lit(context: &RewriteContext, - s: &str, span: Span, width: usize, offset: usize) @@ -842,7 +841,10 @@ fn rewrite_string_lit(context: &RewriteContext, trim_end: false, }; - Some(rewrite_string(&s.escape_default(), &fmt)) + let string_lit = context.snippet(span); + let str_lit = &string_lit[1..string_lit.len() - 1]; // Remove the quote characters. + + Some(rewrite_string(str_lit, &fmt)) } fn rewrite_call(context: &RewriteContext, diff --git a/src/lib.rs b/src/lib.rs index 83c0c5ae1b7..3257d4c6018 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,6 @@ // except according to those terms. #![feature(rustc_private)] -#![feature(str_escape)] -#![feature(str_char)] #![feature(custom_attribute)] #![allow(unused_attributes)] @@ -30,6 +28,9 @@ extern crate rustc_serialize; extern crate strings; +extern crate unicode_segmentation; +extern crate regex; + use rustc::session::Session; use rustc::session::config as rustc_config; use rustc::session::config::Input; diff --git a/src/string.rs b/src/string.rs index 413237e182c..ba93b2db81d 100644 --- a/src/string.rs +++ b/src/string.rs @@ -10,7 +10,12 @@ // Format string literals. -use utils::{make_indent, next_char, prev_char, round_up_to_power_of_two}; + + +use unicode_segmentation::UnicodeSegmentation; +use regex::Regex; + +use utils::{make_indent, round_up_to_power_of_two}; use MIN_STRING; @@ -26,8 +31,12 @@ pub struct StringFormat<'a> { // TODO: simplify this! pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { - // FIXME I bet this stomps unicode escapes in the source string // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) + // Strip line breaks. + let re = Regex::new(r"(\\[:space:]+)").unwrap(); + let stripped_str = re.replace_all(s, ""); + + let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); let indent = make_indent(fmt.offset); let indent = &indent; @@ -39,41 +48,36 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { let ender_length = fmt.line_end.len(); let max_chars = fmt.width.checked_sub(fmt.opener.len()).unwrap_or(0) .checked_sub(ender_length).unwrap_or(1); - loop { let mut cur_end = cur_start + max_chars; - if cur_end >= s.len() { - result.push_str(&s[cur_start..]); + if cur_end >= graphemes.len() { + let line = &graphemes[cur_start..].join(""); + result.push_str(line); break; } - - // Make sure we're on a char boundary. - cur_end = next_char(&s, cur_end); - // Push cur_end left until we reach whitespace. - while !s.char_at(cur_end - 1).is_whitespace() { - cur_end = prev_char(&s, cur_end); - + while !(graphemes[cur_end - 1].trim().len() == 0) { + cur_end -= 1; if cur_end - cur_start < MIN_STRING { // We can't break at whitespace, fall back to splitting // anywhere that doesn't break an escape sequence. - cur_end = next_char(&s, cur_start + max_chars); - while s.char_at(prev_char(&s, cur_end)) == '\\' { - cur_end = prev_char(&s, cur_end); + cur_end = cur_start + max_chars; + while graphemes[cur_end - 1] == "\\" { + cur_end -= 1; } break; } } // Make sure there is no whitespace to the right of the break. - while cur_end < s.len() && s.char_at(cur_end).is_whitespace() { - cur_end = next_char(&s, cur_end + 1); + while cur_end < s.len() && graphemes[cur_end].trim().len() == 0 { + cur_end += 1; } - + let raw_line = graphemes[cur_start..cur_end].join(""); let line: &str = if fmt.trim_end { - &s[cur_start..cur_end].trim_right_matches(char::is_whitespace) + &(raw_line.trim()) } else { - &s[cur_start..cur_end] + &raw_line }; result.push_str(line); diff --git a/src/utils.rs b/src/utils.rs index 00e18c3a65b..936a712ca18 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -32,31 +32,6 @@ pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { original.lo + BytePos(snippet.find_uncommented(needle).unwrap() as u32 + 1) } -#[inline] -pub fn prev_char(s: &str, mut i: usize) -> usize { - if i == 0 { - return 0; - } - - i -= 1; - while !s.is_char_boundary(i) { - i -= 1; - } - i -} - -#[inline] -pub fn next_char(s: &str, mut i: usize) -> usize { - if i >= s.len() { - return s.len(); - } - - while !s.is_char_boundary(i) { - i += 1; - } - i -} - #[inline] pub fn make_indent(width: usize) -> String { let mut indent = String::with_capacity(width); diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index d7e57ea65c7..e95aaae75e0 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -24,6 +24,11 @@ formatting"#; let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + let unicode = "a̐éö̲\r\n"; + let unicode2 = "Löwe 老虎 Léopard"; + let unicode3 = "中华Việt Nam"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; "stuff" } diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 2107d902e19..21cdc199d6e 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -30,5 +30,11 @@ formatting"#; yyyyyyyyyyyyyyyyyyyyy\ yyyyyyyyyy"); + let unicode = "a̐éö̲\r\n"; + let unicode2 = "Löwe 老虎 Léopard"; + let unicode3 = "中华Việt Nam"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃\ + ☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + "stuff" } -- cgit 1.4.1-3-g733a5 From fb9e051fd85f3341a5fb45450548315aa3f1819e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 3 Sep 2015 08:57:22 +1200 Subject: Format nicely --- src/items.rs | 21 ++++++++++----- src/types.rs | 67 +++++++++++++++++++++++++++++++++--------------- tests/source/multiple.rs | 2 +- tests/target/multiple.rs | 2 +- 4 files changed, 64 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 36728ce84fa..972866f2638 100644 --- a/src/items.rs +++ b/src/items.rs @@ -35,7 +35,8 @@ impl<'a> FmtVisitor<'a> { if let Some(ref ty) = local.ty { infix.push_str(": "); - infix.push_str(&pprust::ty_to_string(ty)); + // FIXME silly width, indent + infix.push_str(&ty.rewrite(&self.get_context(), 1000, 0).unwrap()); } if local.init.is_some() { @@ -205,7 +206,7 @@ impl<'a> FmtVisitor<'a> { codemap::mk_sp(span.lo, span_for_return(&fd.output).lo))); - let ret_str = self.rewrite_return(&fd.output); + let ret_str = self.rewrite_return(&fd.output, indent); // Args. let (one_line_budget, multi_line_budget, mut arg_indent) = @@ -504,7 +505,11 @@ impl<'a> FmtVisitor<'a> { ")", |arg| arg.ty.span.lo, |arg| arg.ty.span.hi, - |arg| pprust::ty_to_string(&arg.ty), + |arg| { + // FIXME silly width, indent + arg.ty.rewrite(&self.get_context(), 1000, 0) + .unwrap() + }, span_after(field.span, "(", self.codemap), next_span_start); @@ -731,7 +736,8 @@ impl<'a> FmtVisitor<'a> { ast::StructFieldKind::NamedField(_, vis) | ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; - let typ = pprust::ty_to_string(&field.node.ty); + // FIXME silly width, indent + let typ = field.node.ty.rewrite(&self.get_context(), 1000, 0).unwrap(); let indent = self.block_indent + self.config.tab_spaces; let mut attr_str = field.node.attrs @@ -877,11 +883,14 @@ impl<'a> FmtVisitor<'a> { } } - fn rewrite_return(&self, ret: &ast::FunctionRetTy) -> String { + fn rewrite_return(&self, ret: &ast::FunctionRetTy, indent: usize) -> String { match *ret { ast::FunctionRetTy::DefaultReturn(_) => String::new(), ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(), - ast::FunctionRetTy::Return(ref ty) => "-> ".to_owned() + &pprust::ty_to_string(ty), + ast::FunctionRetTy::Return(ref ty) => { + let ctxt = &self.get_context(); + format!("-> {}", ty.rewrite(ctxt, ctxt.config.max_width, indent).unwrap()) + } } } } diff --git a/src/types.rs b/src/types.rs index 5969c1e1018..c04d694a68e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt; - use syntax::ast; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; @@ -108,6 +106,7 @@ fn rewrite_path_segments<'a, I>(mut buffer: String, Some(buffer) } +#[derive(Debug)] enum SegmentParam<'a> { LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), @@ -124,19 +123,20 @@ impl<'a> SegmentParam<'a> { } } -impl<'a> fmt::Display for SegmentParam<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - SegmentParam::LifeTime(ref lt) => { - write!(f, "{}", pprust::lifetime_to_string(lt)) - } - SegmentParam::Type(ref ty) => { - write!(f, "{}", pprust::ty_to_string(ty)) - } - SegmentParam::Binding(ref binding) => { - write!(f, "{} = {}", binding.ident, pprust::ty_to_string(&*binding.ty)) - } - } +impl<'a> Rewrite for SegmentParam<'a> { + // FIXME doesn't always use width, offset + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + Some(match *self { + SegmentParam::LifeTime(ref lt) => { + pprust::lifetime_to_string(lt) + } + SegmentParam::Type(ref ty) => { + try_opt!(ty.rewrite(context, width, offset)) + } + SegmentParam::Binding(ref binding) => { + format!("{} = {}", binding.ident, try_opt!(binding.ty.rewrite(context, width, offset))) + } + }) } } @@ -205,19 +205,22 @@ fn rewrite_segment(segment: &ast::PathSegment, let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); let separator = get_path_separator(context.codemap, *span_lo, list_lo); + // 1 for < + let extra_offset = 1 + separator.len(); + // 1 for > + let list_width = try_opt!(width.checked_sub(extra_offset + 1)); + let items = itemize_list(context.codemap, param_list.into_iter(), ">", |param| param.get_span().lo, |param| param.get_span().hi, - ToString::to_string, + |seg| { + seg.rewrite(context, list_width, offset + extra_offset).unwrap() + }, list_lo, span_hi); - // 1 for < - let extra_offset = 1 + separator.len(); - // 1 for > - let list_width = try_opt!(width.checked_sub(extra_offset + 1)); let fmt = ListFormatting::for_fn(list_width, offset + extra_offset); // update pos @@ -346,6 +349,13 @@ impl Rewrite for ast::TyParamBound { } } +impl Rewrite for ast::TyParamBounds { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + let strs: Vec<_> = self.iter().map(|b| b.rewrite(context, width, offset).unwrap()).collect(); + Some(strs.join(" + ")) + } +} + // FIXME: this assumes everything will fit on one line impl Rewrite for ast::TyParam { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { @@ -389,3 +399,20 @@ impl Rewrite for ast::PolyTraitRef { } } } + +impl Rewrite for ast::Ty { + // FIXME doesn't always use width, offset + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + match self.node { + ast::TyPath(None, ref p) => { + p.rewrite(context, width, offset) + } + ast::TyObjectSum(ref ty, ref bounds) => { + Some(format!("{} + {}", + try_opt!(ty.rewrite(context, width, offset)), + try_opt!(bounds.rewrite(context, width, offset)))) + } + _ => Some(pprust::ty_to_string(self)), + } + } +} diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 04ecb2bc734..abc16035be2 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -22,7 +22,7 @@ mod other; } -fn foo() where 'a: 'b, for<'a> D<'b>: 'a { +fn foo()->Box where 'a: 'b, for<'a> D<'b>: 'a { hello!() } diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index b6e4750d886..9ff3f2cf7a8 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -28,7 +28,7 @@ fn foo(a: isize, b: u32 /* blah blah */, c: f64) { } -fn foo() +fn foo() -> Box where 'a: 'b, for<'a> D<'b>: 'a { -- cgit 1.4.1-3-g733a5 From 56183ce0e95f498fe69b7d4e284e1abfb458d2d9 Mon Sep 17 00:00:00 2001 From: Christoph Burgdorf Date: Fri, 4 Sep 2015 21:28:37 +0200 Subject: fix outdated help text --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2dc0168aa7f..86a4faa05f5 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -82,7 +82,7 @@ fn main() { } fn print_usage>(reason: S) { - println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[true/false]] ", reason.into()); + println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display]] ", reason.into()); } fn determine_params(args: I) -> Option<(Vec, WriteMode)> -- cgit 1.4.1-3-g733a5 From d6c652e33c37cfc996bfd1442960edf1df3a0a9d Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Fri, 4 Sep 2015 23:39:33 +0200 Subject: code improvements suggested by clippy --- src/comment.rs | 4 ++-- src/lib.rs | 4 ++-- src/lists.rs | 6 +++--- src/modules.rs | 2 +- src/types.rs | 8 ++++---- src/visitor.rs | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e6e083d84bc..0db2aefe013 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -81,7 +81,7 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz s } -fn left_trim_comment_line<'a>(line: &'a str) -> &'a str { +fn left_trim_comment_line(line: &str) -> &str { if line.starts_with("/* ") || line.starts_with("// ") { &line[3..] } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") { @@ -289,7 +289,7 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { return Some((CodeCharKind::Comment, item)); } }; - return Some((CodeCharKind::Normal, item)); + Some((CodeCharKind::Normal, item)) } } diff --git a/src/lib.rs b/src/lib.rs index 83c0c5ae1b7..8214012a908 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -198,7 +198,7 @@ struct FormatReport { impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - for (file, errors) in self.file_error_map.iter() { + for (file, errors) in &self.file_error_map { for error in errors { try!(write!(fmt, "{} {}:{}: {} {}\n", @@ -292,7 +292,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { truncate_todo.push((f.to_owned(), text.len - newline_count + 1)) } - for &(l, _, _) in trims.iter() { + for &(l, _, _) in &trims { errors.push(FormattingError { line: l, kind: ErrorKind::TrailingWhitespace diff --git a/src/lists.rs b/src/lists.rs index 6938e4eb4d4..cc51e1286b9 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -414,8 +414,8 @@ fn total_item_width(item: &ListItem) -> usize { } fn comment_len(comment: &Option) -> usize { - match comment { - &Some(ref s) => { + match *comment { + Some(ref s) => { let text_len = s.trim().len(); if text_len > 0 { // We'll put " /*" before and " */" after inline comments. @@ -424,6 +424,6 @@ fn comment_len(comment: &Option) -> usize { text_len } } - &None => 0, + None => 0, } } diff --git a/src/modules.rs b/src/modules.rs index 681bb1c8ade..b50c9e26895 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -36,7 +36,7 @@ fn list_submodules<'a>(module: &'a ast::Mod, codemap: &codemap::CodeMap, result: &mut HashMap) { debug!("list_submodules: search_dir: {:?}", search_dir); - for item in module.items.iter() { + for item in &module.items { if let ast::ItemMod(ref sub_mod) = item.node { if !utils::contains_skip(&item.attrs) { let is_internal = codemap.span_to_filename(item.span) == diff --git a/src/types.rs b/src/types.rs index c04d694a68e..0c0d9e54424 100644 --- a/src/types.rs +++ b/src/types.rs @@ -265,8 +265,8 @@ impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { // TODO dead spans? // TODO assumes we'll always fit on one line... - Some(match self { - &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, + Some(match *self { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, ref bounded_ty, ref bounds, ..}) => { @@ -299,7 +299,7 @@ impl Rewrite for ast::WherePredicate { format!("{}: {}", type_str, bounds_str) } } - &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { format!("{}: {}", @@ -307,7 +307,7 @@ impl Rewrite for ast::WherePredicate { bounds.iter().map(pprust::lifetime_to_string) .collect::>().join(" + ")) } - &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { let ty_str = pprust::ty_to_string(ty); // 3 = " = ".len() let used_width = 3 + ty_str.len(); diff --git a/src/visitor.rs b/src/visitor.rs index 0b29086daf6..c2e4013e182 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -49,10 +49,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &'v ast::Stmt) { match stmt.node { ast::Stmt_::StmtDecl(ref decl, _) => { - return match decl.node { + match decl.node { ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span), ast::Decl_::DeclItem(..) => visit::walk_stmt(self, stmt), - }; + } } ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { self.format_missing_with_indent(stmt.span.lo); -- cgit 1.4.1-3-g733a5 From 14a94f0bcd4d6892674cbe7dcaf8f3613cac30fc Mon Sep 17 00:00:00 2001 From: Christoph Burgdorf Date: Fri, 4 Sep 2015 23:01:20 +0200 Subject: Allow partial rustfmt.toml With this change one can use a config file that only specifies a subset of config keys to overwrite. E.g. a config file that looks like this struct_trailing_comma = "Never" struct_lit_trailing_comma = "Never" Fixes #255 --- src/config.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 1b4d79ab6ee..c7525e930ec 100644 --- a/src/config.rs +++ b/src/config.rs @@ -52,10 +52,30 @@ macro_rules! create_config { $(pub $i: $ty),+ } + // Just like the Config struct but with each property wrapped + // as Option. This is used to parse a rustfmt.toml that doesn't + // specity all properties of `Config`. + // We first parse into `ParsedConfig`, then create a default `Config` + // and overwrite the properties with corresponding values from `ParsedConfig` + #[derive(RustcDecodable, Clone)] + pub struct ParsedConfig { + $(pub $i: Option<$ty>),+ + } + impl Config { + + fn fill_from_parsed_config(mut self, parsed: &ParsedConfig) -> Config { + $( + if let Some(val) = parsed.$i { + self.$i = val; + } + )+ + self + } + pub fn from_toml(toml: &str) -> Config { let parsed = toml.parse().unwrap(); - match toml::decode(parsed) { + let parsed_config:ParsedConfig = match toml::decode(parsed) { Some(decoded) => decoded, None => { println!("Decoding config file failed. Config:\n{}", toml); @@ -63,7 +83,8 @@ macro_rules! create_config { println!("\n\nParsed:\n{:?}", parsed); panic!(); } - } + }; + Config::default().fill_from_parsed_config(&parsed_config) } pub fn override_value(&mut self, key: &str, val: &str) { -- cgit 1.4.1-3-g733a5 From 490821ef30cacb04a38edee09900d28a9d484374 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 5 Sep 2015 14:00:16 +0200 Subject: Work with spanned labels in break and continue --- src/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e11c6e470f6..aac13f552d0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -119,14 +119,14 @@ impl Rewrite for ast::Expr { // `continue` ast::Expr_::ExprAgain(ref opt_ident) => { let id_str = match *opt_ident { - Some(ident) => format!(" {}", ident), + Some(ident) => format!(" {}", ident.node), None => String::new(), }; Some(format!("continue{}", id_str)) } ast::Expr_::ExprBreak(ref opt_ident) => { let id_str = match *opt_ident { - Some(ident) => format!(" {}", ident), + Some(ident) => format!(" {}", ident.node), None => String::new(), }; Some(format!("break{}", id_str)) -- cgit 1.4.1-3-g733a5 From e0c197cab4fb8ffeb87ca56be850894be2ec7e25 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 5 Sep 2015 18:26:28 +1200 Subject: Single line unsafe blocks --- src/expr.rs | 15 ++++++++++++++- tests/source/expr.rs | 8 ++++++++ tests/target/expr.rs | 6 ++++++ 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index aac13f552d0..3a8b9c9ab4b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -262,13 +262,26 @@ impl Rewrite for ast::Block { // Extract comment between unsafe and block start. let trimmed = &snippet[6..open_pos].trim(); - if !trimmed.is_empty() { + let prefix = if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() let budget = try_opt!(width.checked_sub(9)); format!("unsafe {} ", rewrite_comment(trimmed, true, budget, offset + 7)) } else { "unsafe ".to_owned() + }; + + if is_simple_block(self, context.codemap) && prefix.len() < width { + let body = + self.expr.as_ref().unwrap().rewrite(context, width - prefix.len(), offset); + if let Some(ref expr_str) = body { + let result = format!("{}{{ {} }}", prefix, expr_str); + if result.len() <= width && !result.contains('\n') { + return Some(result); + } + } } + + prefix } ast::BlockCheckMode::PopUnsafeBlock(..) | ast::BlockCheckMode::DefaultBlock => { diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 0bb46086ca8..bf9a8359aad 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -93,6 +93,14 @@ fn baz() { unsafe { // Regular unsafe block } + + unsafe { + foo() + } + + unsafe { + foo(); + } } // Test some empty blocks. diff --git a/tests/target/expr.rs b/tests/target/expr.rs index e2ed9c598ce..9bfe51e0b26 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -130,6 +130,12 @@ fn baz() { unsafe { // Regular unsafe block } + + unsafe { foo() } + + unsafe { + foo(); + } } // Test some empty blocks. -- cgit 1.4.1-3-g733a5 From c3cb348169474b8e75a7f7deb8f532b67a84a7f9 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 6 Sep 2015 23:18:27 +0200 Subject: Fix qself rewrites without explicit casts --- src/types.rs | 29 ++++++++++++++++------------- tests/source/paths.rs | 2 ++ tests/target/paths.rs | 2 ++ 3 files changed, 20 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 0c0d9e54424..dfb7f255a98 100644 --- a/src/types.rs +++ b/src/types.rs @@ -42,19 +42,22 @@ pub fn rewrite_path(context: &RewriteContext, if let Some(ref qself) = qself { result.push('<'); result.push_str(&pprust::ty_to_string(&qself.ty)); - result.push_str(" as "); - - let extra_offset = extra_offset(&result, offset); - // 3 = ">::".len() - let budget = try_opt!(width.checked_sub(extra_offset)) - 3; - - result = try_opt!(rewrite_path_segments(result, - path.segments.iter().take(skip_count), - span_lo, - path.span.hi, - context, - budget, - offset + extra_offset)); + + if skip_count > 0 { + result.push_str(" as "); + + let extra_offset = extra_offset(&result, offset); + // 3 = ">::".len() + let budget = try_opt!(width.checked_sub(extra_offset)) - 3; + + result = try_opt!(rewrite_path_segments(result, + path.segments.iter().take(skip_count), + span_lo, + path.span.hi, + context, + budget, + offset + extra_offset)); + } result.push_str(">::"); span_lo = qself.ty.span.hi + BytePos(1); diff --git a/tests/source/paths.rs b/tests/source/paths.rs index 51edf707645..d2b4a66622a 100644 --- a/tests/source/paths.rs +++ b/tests/source/paths.rs @@ -15,6 +15,8 @@ fn main() { Quux::::some_func(); + + < *mut JSObject >:: relocate(entry); } fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/target/paths.rs b/tests/target/paths.rs index c69275c7ff9..4fa3a52fe6c 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -13,6 +13,8 @@ fn main() { supports_clipboard); Quux::::some_func(); + + <*mut JSObject>::relocate(entry); } fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { -- cgit 1.4.1-3-g733a5 From 94a26f3c9cdb335ec0ae67d4dd56d656309acefb Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Mon, 7 Sep 2015 00:24:24 -0400 Subject: Fix https://github.com/nrc/rustfmt/issues/278 --- src/comment.rs | 6 +++++- tests/source/struct_lits.rs | 15 +++++++++++++++ tests/target/struct_lits.rs | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0db2aefe013..f1cecd7318b 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -70,7 +70,11 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz if line.len() > max_chars { acc.push_str(&rewrite_string(line, &fmt)); } else { - acc.push_str(line); + if line.len() == 0 { + acc.pop(); // Remove space if this is an empty comment. + } else { + acc.push_str(line); + } } (false, acc) diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 8894508fd98..ead7b749d5a 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -68,3 +68,18 @@ fn issue201() { fn issue201_2() { let s = S{a: S2{ .. c}, .. b}; } + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 81c60381ed8..b95772d41ec 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -86,3 +86,18 @@ fn issue201() { fn issue201_2() { let s = S { a: S2 { ..c }, ..b }; } + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} -- cgit 1.4.1-3-g733a5 From d05a41c7738fcdaa91510ba9ab0e1cfbe9dea278 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 4 Sep 2015 18:09:05 +0200 Subject: Add failure mode to `write_list` --- src/expr.rs | 119 ++++++++++++++++++------------ src/imports.rs | 22 +++--- src/items.rs | 192 ++++++++++++++++++++++++++---------------------- src/lists.rs | 12 +-- src/types.rs | 24 +++--- src/utils.rs | 32 ++++++++ src/visitor.rs | 75 ++++++++++--------- tests/source/imports.rs | 4 +- tests/source/paths.rs | 1 - tests/target/imports.rs | 5 +- tests/target/paths.rs | 22 +++--- tests/target/tuple.rs | 2 +- 12 files changed, 296 insertions(+), 214 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 3f88e45884e..08acd5de67d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp::Ordering; + use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; use StructLitStyle; -use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width}; +use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width, wrap_str}; use visitor::FmtVisitor; use config::BlockIndentStyle; use comment::{FindUncommented, rewrite_comment, contains_comment}; @@ -134,37 +136,9 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } - _ => { - // We do not format these expressions yet, but they should still - // satisfy our width restrictions. - let snippet = context.snippet(self.span); - - { - let mut lines = snippet.lines(); - - // The caller of this function has already placed `offset` - // characters on the first line. - let first_line_max_len = try_opt!(context.config.max_width.checked_sub(offset)); - if lines.next().unwrap().len() > first_line_max_len { - return None; - } - - // The other lines must fit within the maximum width. - if lines.find(|line| line.len() > context.config.max_width).is_some() { - return None; - } - - // `width` is the maximum length of the last line, excluding - // indentation. - // A special check for the last line, since the caller may - // place trailing characters on this line. - if snippet.lines().rev().next().unwrap().len() > offset + width { - return None; - } - } - - Some(snippet) - } + // We do not format these expressions yet, but they should still + // satisfy our width restrictions. + _ => wrap_str(context.snippet(self.span), context.config.max_width, width, offset), } } } @@ -202,7 +176,8 @@ fn rewrite_closure(capture: ast::CaptureClause, body.span.lo); let fmt = ListFormatting::for_fn(argument_budget, argument_offset); - let prefix = format!("{}|{}|", mover, write_list(&arg_items.collect::>(), &fmt)); + let list_str = try_opt!(write_list(&arg_items.collect::>(), &fmt)); + let prefix = format!("{}|{}|", mover, list_str); let closure_indent = closure_indent(context, offset); // Try to format closure body as a single line expression without braces. @@ -869,19 +844,58 @@ fn rewrite_call(context: &RewriteContext, -> Option { debug!("rewrite_call, width: {}, offset: {}", width, offset); - // FIXME using byte lens instead of char lens (and probably all over the place too) // 2 is for parens - let max_callee_width = try_opt!(width.checked_sub(2)); - let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); - debug!("rewrite_call, callee_str: `{}`", callee_str); - - if args.is_empty() { - return Some(format!("{}()", callee_str)); + let mut hi = try_opt!(width.checked_sub(2)) * 2; + let mut lo = 0; + let mut tries = 0; + + // Binary search for the best split between callee and arguments. + loop { + let middle = (lo + hi) / 2; + + match rewrite_call_inner(context, callee, middle, args, span, width, offset) { + _ if tries > 10 => return None, + Ok(result) => return Some(result), + Err(Ordering::Less) => { + lo = middle; + tries += 1; + } + Err(Ordering::Greater) => { + hi = middle; + tries += 1; + } + _ => unreachable!(), + } } +} + +fn rewrite_call_inner(context: &RewriteContext, + callee: &ast::Expr, + max_callee_width: usize, + args: &[ptr::P], + span: Span, + width: usize, + offset: usize) + -> Result { + // FIXME using byte lens instead of char lens (and probably all over the place too) + let callee_str = match callee.rewrite(context, max_callee_width, offset) { + Some(string) => { + if !string.contains('\n') && string.len() > max_callee_width { + panic!("{:?} {}", string, max_callee_width); + } else { + string + } + } + None => return Err(Ordering::Less), + }; + debug!("rewrite_call, callee_str: `{}`", callee_str); let extra_offset = extra_offset(&callee_str, offset); // 2 is for parens. - let remaining_width = try_opt!(width.checked_sub(extra_offset + 2)); + let remaining_width = match width.checked_sub(extra_offset + 2) { + Some(str) => str, + None => return Err(Ordering::Greater), + }; let offset = offset + extra_offset + 1; let inner_indent = expr_indent(context, offset); let inner_context = context.overflow_context(inner_indent - context.block_indent); @@ -900,8 +914,12 @@ fn rewrite_call(context: &RewriteContext, span.hi); let fmt = ListFormatting::for_fn(remaining_width, offset); + let list_str = match write_list(&items.collect::>(), &fmt) { + Some(str) => str, + None => return Err(Ordering::Greater), + }; - Some(format!("{}({})", callee_str, write_list(&items.collect::>(), &fmt))) + Ok(format!("{}({})", callee_str, list_str)) } macro_rules! block_indent_helper { @@ -1024,7 +1042,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, v_width: v_budget, ends_with_newline: false, }; - let fields_str = write_list(&items.collect::>(), &fmt); + let fields_str = try_opt!(write_list(&items.collect::>(), &fmt)); match context.config.struct_lit_style { StructLitStyle::Block if fields_str.contains('\n') => { @@ -1046,7 +1064,8 @@ fn rewrite_field(context: &RewriteContext, -> Option { let name = &field.ident.node.to_string(); let overhead = name.len() + 2; - let expr = field.expr.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); + let expr = + field.expr.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); expr.map(|s| format!("{}: {}", name, s)) } @@ -1080,8 +1099,9 @@ fn rewrite_tuple_lit(context: &RewriteContext, let budget = try_opt!(width.checked_sub(2)); let fmt = ListFormatting::for_fn(budget, indent); + let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); - Some(format!("({})", write_list(&items.collect::>(), &fmt))) + Some(format!("({})", list_str)) } fn rewrite_binary_op(context: &RewriteContext, @@ -1206,12 +1226,13 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let new_offset = offset + context.config.tab_spaces; result.push_str(&format!("\n{}", make_indent(new_offset))); + // FIXME: we probably should related max_width to width instead of config.max_width + // where is the 1 coming from anyway? let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1)); - let rhs = try_opt!(ex.rewrite(&context.overflow_context(context.config.tab_spaces), - max_width, - new_offset)); + let overflow_context = context.overflow_context(context.config.tab_spaces); + let rhs = ex.rewrite(&overflow_context, max_width, new_offset); - result.push_str(&rhs); + result.push_str(&&try_opt!(rhs)); } } diff --git a/src/imports.rs b/src/imports.rs index cf9e174f9b0..8411b3208df 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -22,13 +22,11 @@ impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { match self.node { + ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => { + Some(String::new()) + } ast::ViewPath_::ViewPathList(ref path, ref path_list) => { - Some(rewrite_use_list(width, - offset, - path, - path_list, - self.span, - context).unwrap_or("".to_owned())) + rewrite_use_list(width, offset, path, path_list, self.span, context) } ast::ViewPath_::ViewPathGlob(_) => { // FIXME convert to list? @@ -67,8 +65,8 @@ fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { } } -// Basically just pretty prints a multi-item import. -// Returns None when the import can be removed. +// Pretty prints a multi-item import. +// Assumes that path_list.len() > 0. pub fn rewrite_use_list(width: usize, offset: usize, path: &ast::Path, @@ -80,7 +78,7 @@ pub fn rewrite_use_list(width: usize, let path_str = try_opt!(path.rewrite(context, width - 1, offset)); match path_list.len() { - 0 => return None, + 0 => unreachable!(), 1 => return Some(rewrite_single_use_list(path_str, path_list[0])), _ => (), } @@ -149,12 +147,12 @@ pub fn rewrite_use_list(width: usize, items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } - let list = write_list(&items[first_index..], &fmt); + let list_str = try_opt!(write_list(&items[first_index..], &fmt)); Some(if path_str.is_empty() { - format!("{{{}}}", list) + format!("{{{}}}", list_str) } else { - format!("{}::{{{}}}", path_str, list) + format!("{}::{{{}}}", path_str, list_str) }) } diff --git a/src/items.rs b/src/items.rs index 972866f2638..e2224ce4eff 100644 --- a/src/items.rs +++ b/src/items.rs @@ -99,20 +99,20 @@ impl<'a> FmtVisitor<'a> { abi: &abi::Abi, vis: ast::Visibility, span: Span) - -> String { + -> Option { let mut newline_brace = self.newline_for_brace(&generics.where_clause); - let mut result = self.rewrite_fn_base(indent, - ident, - fd, - explicit_self, - generics, - unsafety, - constness, - abi, - vis, - span, - newline_brace); + let mut result = try_opt!(self.rewrite_fn_base(indent, + ident, + fd, + explicit_self, + generics, + unsafety, + constness, + abi, + vis, + span, + newline_brace)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; @@ -130,7 +130,7 @@ impl<'a> FmtVisitor<'a> { result.push(' '); } - result + Some(result) } pub fn rewrite_required_fn(&mut self, @@ -138,26 +138,26 @@ impl<'a> FmtVisitor<'a> { ident: ast::Ident, sig: &ast::MethodSig, span: Span) - -> String { + -> Option { // Drop semicolon or it will be interpreted as comment let span = codemap::mk_sp(span.lo, span.hi - BytePos(1)); - let mut result = self.rewrite_fn_base(indent, - ident, - &sig.decl, - Some(&sig.explicit_self), - &sig.generics, - &sig.unsafety, - &sig.constness, - &sig.abi, - ast::Visibility::Inherited, - span, - false); + let mut result = try_opt!(self.rewrite_fn_base(indent, + ident, + &sig.decl, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.constness, + &sig.abi, + ast::Visibility::Inherited, + span, + false)); // Re-attach semicolon result.push(';'); - result + Some(result) } fn rewrite_fn_base(&mut self, @@ -172,7 +172,7 @@ impl<'a> FmtVisitor<'a> { vis: ast::Visibility, span: Span, newline_brace: bool) - -> String { + -> Option { // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. @@ -200,11 +200,12 @@ impl<'a> FmtVisitor<'a> { // Generics. let generics_indent = indent + result.len(); - result.push_str(&self.rewrite_generics(generics, - indent, - generics_indent, - codemap::mk_sp(span.lo, - span_for_return(&fd.output).lo))); + let generics_span = codemap::mk_sp(span.lo, span_for_return(&fd.output).lo); + let generics_str = try_opt!(self.rewrite_generics(generics, + indent, + generics_indent, + generics_span)); + result.push_str(&generics_str); let ret_str = self.rewrite_return(&fd.output, indent); @@ -243,13 +244,14 @@ impl<'a> FmtVisitor<'a> { "(", self.codemap), span_for_return(&fd.output).lo); - result.push_str(&self.rewrite_args(&fd.inputs, - explicit_self, - one_line_budget, - multi_line_budget, - indent, - arg_indent, - args_span)); + let arg_str = try_opt!(self.rewrite_args(&fd.inputs, + explicit_self, + one_line_budget, + multi_line_budget, + indent, + arg_indent, + args_span)); + result.push_str(&arg_str); if self.config.fn_args_layout == StructLitStyle::Block { result.push('\n'); } @@ -307,13 +309,14 @@ impl<'a> FmtVisitor<'a> { }; // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, - self.config, - indent, - where_density, - span.hi)); - - result + let where_clause_str = try_opt!(self.rewrite_where_clause(where_clause, + self.config, + indent, + where_density, + span.hi)); + result.push_str(&where_clause_str); + + Some(result) } fn rewrite_args(&self, @@ -324,7 +327,7 @@ impl<'a> FmtVisitor<'a> { indent: usize, arg_indent: usize, span: Span) - -> String { + -> Option { let mut arg_item_strs: Vec<_> = args.iter().map(rewrite_fn_input).collect(); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked @@ -461,8 +464,8 @@ impl<'a> FmtVisitor<'a> { " {", self.block_indent, self.block_indent + self.config.tab_spaces, - codemap::mk_sp(span.lo, - body_start)); + codemap::mk_sp(span.lo, body_start)) + .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; @@ -534,7 +537,12 @@ impl<'a> FmtVisitor<'a> { v_width: budget, ends_with_newline: true, }; - result.push_str(&write_list(&items.collect::>(), &fmt)); + let list_str = match write_list(&items.collect::>(), &fmt) { + Some(list_str) => list_str, + None => return, + }; + + result.push_str(&list_str); result.push(')'); } @@ -554,13 +562,18 @@ impl<'a> FmtVisitor<'a> { } ast::VariantKind::StructVariantKind(ref struct_def) => { // TODO Should limit the width, as we have a trailing comma - self.format_struct("", - field.node.name, - field.node.vis, - struct_def, - None, - field.span, - self.block_indent) + let struct_rewrite = self.format_struct("", + field.node.name, + field.node.vis, + struct_def, + None, + field.span, + self.block_indent); + + match struct_rewrite { + Some(struct_str) => struct_str, + None => return, + } } }; self.buffer.push_str(&result); @@ -580,7 +593,7 @@ impl<'a> FmtVisitor<'a> { generics: Option<&ast::Generics>, span: Span, offset: usize) - -> String { + -> Option { let mut result = String::with_capacity(1024); let header_str = self.format_header(item_name, ident, vis); @@ -588,7 +601,7 @@ impl<'a> FmtVisitor<'a> { if struct_def.fields.is_empty() { result.push(';'); - return result; + return Some(result); } let is_tuple = match struct_def.fields[0].node.kind { @@ -603,12 +616,14 @@ impl<'a> FmtVisitor<'a> { }; let generics_str = match generics { - Some(g) => self.format_generics(g, - opener, - offset, - offset + header_str.len(), - codemap::mk_sp(span.lo, - struct_def.fields[0].span.lo)), + Some(g) => { + try_opt!(self.format_generics(g, + opener, + offset, + offset + header_str.len(), + codemap::mk_sp(span.lo, + struct_def.fields[0].span.lo))) + } None => opener.to_owned(), }; result.push_str(&generics_str); @@ -658,8 +673,9 @@ impl<'a> FmtVisitor<'a> { v_width: budget, ends_with_newline: true, }; + let list_str = write_list(&items.collect::>(), &fmt).unwrap(); - result.push_str(&write_list(&items.collect::>(), &fmt)); + result.push_str(&list_str); if break_line { result.push('\n'); @@ -672,7 +688,7 @@ impl<'a> FmtVisitor<'a> { result.push(';'); } - result + Some(result) } pub fn visit_struct(&mut self, @@ -688,7 +704,9 @@ impl<'a> FmtVisitor<'a> { struct_def, Some(generics), span, - indent); + indent) + .unwrap(); + self.buffer.push_str(&result); self.last_pos = span.hi; } @@ -703,15 +721,16 @@ impl<'a> FmtVisitor<'a> { offset: usize, generics_offset: usize, span: Span) - -> String { - let mut result = self.rewrite_generics(generics, offset, generics_offset, span); + -> Option { + let mut result = try_opt!(self.rewrite_generics(generics, offset, generics_offset, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - result.push_str(&self.rewrite_where_clause(&generics.where_clause, - self.config, - self.block_indent, - Density::Tall, - span.hi)); + let where_clause_str = try_opt!(self.rewrite_where_clause(&generics.where_clause, + self.config, + self.block_indent, + Density::Tall, + span.hi)); + result.push_str(&where_clause_str); result.push_str(&make_indent(self.block_indent)); result.push('\n'); result.push_str(opener.trim()); @@ -719,7 +738,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(opener); } - result + Some(result) } // Field of a struct @@ -761,13 +780,13 @@ impl<'a> FmtVisitor<'a> { offset: usize, generics_offset: usize, span: Span) - -> String { + -> Option { // FIXME convert bounds to where clauses where they get too big or if // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; let tys: &[_] = &generics.ty_params; if lifetimes.is_empty() && tys.is_empty() { - return String::new(); + return Some(String::new()); } let offset = match self.config.generics_indent { @@ -816,8 +835,9 @@ impl<'a> FmtVisitor<'a> { } let fmt = ListFormatting::for_fn(h_budget, offset); + let list_str = try_opt!(write_list(&items, &fmt)); - format!("<{}>", write_list(&items, &fmt)) + Some(format!("<{}>", list_str)) } fn rewrite_where_clause(&self, @@ -826,9 +846,9 @@ impl<'a> FmtVisitor<'a> { indent: usize, density: Density, span_end: BytePos) - -> String { + -> Option { if where_clause.predicates.is_empty() { - return String::new(); + return Some(String::new()); } let extra_indent = match self.config.where_indent { @@ -870,16 +890,16 @@ impl<'a> FmtVisitor<'a> { v_width: budget, ends_with_newline: true, }; - let preds_str = write_list(&items.collect::>(), &fmt); + let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); // 9 = " where ".len() + " {".len() if density == Density::Tall || preds_str.contains('\n') || indent + 9 + preds_str.len() > self.config.max_width { - format!("\n{}where {}", - make_indent(indent + extra_indent), - preds_str) + Some(format!("\n{}where {}", + make_indent(indent + extra_indent), + preds_str)) } else { - format!(" where {}", preds_str) + Some(format!(" where {}", preds_str)) } } diff --git a/src/lists.rs b/src/lists.rs index cc51e1286b9..e21327631d4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -13,7 +13,7 @@ use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; -use utils::{round_up_to_power_of_two, make_indent}; +use utils::{round_up_to_power_of_two, make_indent, wrap_str}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; #[derive(Eq, PartialEq, Debug, Copy, Clone)] @@ -95,9 +95,9 @@ impl ListItem { // Format a list of commented items into a string. // FIXME: this has grown into a monstrosity // TODO: add unit tests -pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> String { +pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Option { if items.is_empty() { - return String::new(); + return Some(String::new()); } let mut tactic = formatting.tactic; @@ -204,7 +204,9 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St } } - result.push_str(&item.item); + // FIXME: no magic numbers! + let item_str = wrap_str(&item.item[..], 100, formatting.v_width, formatting.indent); + result.push_str(&&try_opt!(item_str)); // Post-comments if tactic != ListTactic::Vertical && item.post_comment.is_some() { @@ -240,7 +242,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St } } - result + Some(result) } pub struct ListItems<'a, I, F1, F2, F3> diff --git a/src/types.rs b/src/types.rs index dfb7f255a98..58bb930510c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -87,6 +87,12 @@ fn rewrite_path_segments<'a, I>(mut buffer: String, let mut first = true; for segment in iter { + if first { + first = false; + } else { + buffer.push_str("::"); + } + let extra_offset = extra_offset(&buffer, offset); let remaining_width = try_opt!(width.checked_sub(extra_offset)); let new_offset = offset + extra_offset; @@ -97,12 +103,6 @@ fn rewrite_path_segments<'a, I>(mut buffer: String, remaining_width, new_offset)); - if first { - first = false; - } else { - buffer.push_str("::"); - } - buffer.push_str(&segment_string); } @@ -218,18 +218,20 @@ fn rewrite_segment(segment: &ast::PathSegment, ">", |param| param.get_span().lo, |param| param.get_span().hi, + // FIXME: need better params |seg| { - seg.rewrite(context, list_width, offset + extra_offset).unwrap() + seg.rewrite(context, 1000, offset + extra_offset).unwrap() }, list_lo, span_hi); let fmt = ListFormatting::for_fn(list_width, offset + extra_offset); + let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); // update pos *span_lo = next_span_lo; - format!("{}<{}>", separator, write_list(&items.collect::>(), &fmt)) + format!("{}<{}>", separator, list_str) } ast::PathParameters::ParenthesizedParameters(ref data) => { let output = match data.output { @@ -252,11 +254,12 @@ fn rewrite_segment(segment: &ast::PathSegment, // 1 for ( let fmt = ListFormatting::for_fn(budget, offset + 1); + let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); // update pos *span_lo = data.span.hi + BytePos(1); - format!("({}){}", write_list(&items.collect::>(), &fmt), output) + format!("({}){}", list_str, output) } _ => String::new(), }; @@ -354,7 +357,8 @@ impl Rewrite for ast::TyParamBound { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { - let strs: Vec<_> = self.iter().map(|b| b.rewrite(context, width, offset).unwrap()).collect(); + let strs: Vec<_> = + self.iter().map(|b| b.rewrite(context, width, offset).unwrap()).collect(); Some(strs.join(" + ")) } } diff --git a/src/utils.rs b/src/utils.rs index 936a712ca18..07807bf31aa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -164,6 +164,38 @@ macro_rules! try_opt { }) } +pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usize) -> Option { + let snippet = s.as_ref(); + + if !snippet.contains('\n') && snippet.len() > width { + return None; + } else { + let mut lines = snippet.lines(); + + // The caller of this function has already placed `offset` + // characters on the first line. + let first_line_max_len = try_opt!(max_width.checked_sub(offset)); + if lines.next().unwrap().len() > first_line_max_len { + return None; + } + + // The other lines must fit within the maximum width. + if lines.find(|line| line.len() > max_width).is_some() { + return None; + } + + // `width` is the maximum length of the last line, excluding + // indentation. + // A special check for the last line, since the caller may + // place trailing characters on this line. + if snippet.lines().rev().next().unwrap().len() > offset + width { + return None; + } + } + + Some(s) +} + #[test] fn power_rounding() { assert_eq!(0, round_up_to_power_of_two(0)); diff --git a/src/visitor.rs b/src/visitor.rs index c2e4013e182..c1c1f2fcbbd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -87,7 +87,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { // Check if this block has braces. let snippet = self.snippet(b.span); - let has_braces = snippet.chars().next().unwrap() == '{' || &snippet[..6] == "unsafe"; + let has_braces = &snippet[..1] == "{" || &snippet[..6] == "unsafe"; let brace_compensation = if has_braces { BytePos(1) } else { @@ -125,43 +125,45 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { - self.format_missing_with_indent(s.lo); - self.last_pos = s.lo; - let indent = self.block_indent; - match fk { + let rewrite = match fk { visit::FnKind::ItemFn(ident, - ref generics, - ref unsafety, - ref constness, - ref abi, - vis) => { - let new_fn = self.rewrite_fn(indent, - ident, - fd, - None, - generics, - unsafety, - constness, - abi, - vis, - codemap::mk_sp(s.lo, b.span.lo)); - self.buffer.push_str(&new_fn); + ref generics, + ref unsafety, + ref constness, + ref abi, + vis) => { + self.rewrite_fn(indent, + ident, + fd, + None, + generics, + unsafety, + constness, + abi, + vis, + codemap::mk_sp(s.lo, b.span.lo)) } visit::FnKind::Method(ident, ref sig, vis) => { - let new_fn = self.rewrite_fn(indent, - ident, - fd, - Some(&sig.explicit_self), - &sig.generics, - &sig.unsafety, - &sig.constness, - &sig.abi, - vis.unwrap_or(ast::Visibility::Inherited), - codemap::mk_sp(s.lo, b.span.lo)); - self.buffer.push_str(&new_fn); + self.rewrite_fn(indent, + ident, + fd, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.constness, + &sig.abi, + vis.unwrap_or(ast::Visibility::Inherited), + codemap::mk_sp(s.lo, b.span.lo)) } - visit::FnKind::Closure => {} + visit::FnKind::Closure => None, + }; + + if let Some(fn_str) = rewrite { + self.format_missing_with_indent(s.lo); + self.buffer.push_str(&fn_str); + } else { + self.format_missing(b.span.lo); } self.last_pos = b.span.lo; @@ -239,8 +241,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { sig, ti.span); - self.buffer.push_str(&new_fn); - self.last_pos = ti.span.hi; + + if let Some(fn_str) = new_fn { + self.buffer.push_str(&fn_str); + self.last_pos = ti.span.hi; + } } // TODO format trait types diff --git a/tests/source/imports.rs b/tests/source/imports.rs index f759de3e7bb..92380ea51b0 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -2,8 +2,8 @@ // Long import. use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; +use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; use list::{ // Some item diff --git a/tests/source/paths.rs b/tests/source/paths.rs index d2b4a66622a..9a5513e1589 100644 --- a/tests/source/paths.rs +++ b/tests/source/paths.rs @@ -1,6 +1,5 @@ fn main() { - // FIXME(#133): the list rewrite should fail and force a different format let constellation_chan = Constellation:: ::start( compositor_proxy, resource_task, diff --git a/tests/target/imports.rs b/tests/target/imports.rs index bbef3e85e16..07449a51982 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -2,8 +2,9 @@ // Long import. use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; +use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; use list::{// Some item SomeItem, // Comment diff --git a/tests/target/paths.rs b/tests/target/paths.rs index 4fa3a52fe6c..fd97bb4d71c 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -1,16 +1,16 @@ fn main() { - // FIXME(#133): the list rewrite should fail and force a different format - let constellation_chan = Constellation::::start(compositor_proxy, - resource_task, - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard); + let constellation_chan = + Constellation::::start(compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard); Quux::::some_func(); diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index a77fae11cb4..a5bcc7f701a 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -4,7 +4,7 @@ fn foo() { let a = (a, a, a, a, a); let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa, aaaa); let a = (a,); -- cgit 1.4.1-3-g733a5 From f80dcbbd84b90042499b0fd7675a2c9c85cbecdf Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 7 Sep 2015 21:34:37 +0200 Subject: Split off binary search --- src/expr.rs | 45 +++++++++++------------------ src/lists.rs | 4 +-- src/types.rs | 14 +++++---- src/utils.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 98 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 08acd5de67d..e3146170f82 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -14,7 +14,8 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; use StructLitStyle; -use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width, wrap_str}; +use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width, wrap_str, + binary_search}; use visitor::FmtVisitor; use config::BlockIndentStyle; use comment::{FindUncommented, rewrite_comment, contains_comment}; @@ -842,31 +843,19 @@ fn rewrite_call(context: &RewriteContext, width: usize, offset: usize) -> Option { - debug!("rewrite_call, width: {}, offset: {}", width, offset); + let callback = |callee_max_width| { + rewrite_call_inner(context, + callee, + callee_max_width, + args, + span, + width, + offset) + }; // 2 is for parens - let mut hi = try_opt!(width.checked_sub(2)) * 2; - let mut lo = 0; - let mut tries = 0; - - // Binary search for the best split between callee and arguments. - loop { - let middle = (lo + hi) / 2; - - match rewrite_call_inner(context, callee, middle, args, span, width, offset) { - _ if tries > 10 => return None, - Ok(result) => return Some(result), - Err(Ordering::Less) => { - lo = middle; - tries += 1; - } - Err(Ordering::Greater) => { - hi = middle; - tries += 1; - } - _ => unreachable!(), - } - } + let max_width = try_opt!(width.checked_sub(2)); + binary_search(1, max_width, callback) } fn rewrite_call_inner(context: &RewriteContext, @@ -877,7 +866,8 @@ fn rewrite_call_inner(context: &RewriteContext, width: usize, offset: usize) -> Result { - // FIXME using byte lens instead of char lens (and probably all over the place too) + // FIXME using byte lens instead of char lens (and probably all over the + // place too) let callee_str = match callee.rewrite(context, max_callee_width, offset) { Some(string) => { if !string.contains('\n') && string.len() > max_callee_width { @@ -886,9 +876,8 @@ fn rewrite_call_inner(context: &RewriteContext, string } } - None => return Err(Ordering::Less), + None => return Err(Ordering::Greater), }; - debug!("rewrite_call, callee_str: `{}`", callee_str); let extra_offset = extra_offset(&callee_str, offset); // 2 is for parens. @@ -916,7 +905,7 @@ fn rewrite_call_inner(context: &RewriteContext, let fmt = ListFormatting::for_fn(remaining_width, offset); let list_str = match write_list(&items.collect::>(), &fmt) { Some(str) => str, - None => return Err(Ordering::Greater), + None => return Err(Ordering::Less), }; Ok(format!("{}({})", callee_str, list_str)) diff --git a/src/lists.rs b/src/lists.rs index e21327631d4..cf68d86dd2b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -204,8 +204,8 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op } } - // FIXME: no magic numbers! - let item_str = wrap_str(&item.item[..], 100, formatting.v_width, formatting.indent); + let max_width = formatting.indent + formatting.v_width; + let item_str = wrap_str(&item.item[..], max_width, formatting.v_width, formatting.indent); result.push_str(&&try_opt!(item_str)); // Post-comments diff --git a/src/types.rs b/src/types.rs index 58bb930510c..dace1d84bca 100644 --- a/src/types.rs +++ b/src/types.rs @@ -218,9 +218,14 @@ fn rewrite_segment(segment: &ast::PathSegment, ">", |param| param.get_span().lo, |param| param.get_span().hi, - // FIXME: need better params + // FIXME(#133): write_list should call + // rewrite itself, because it has a better + // context. |seg| { - seg.rewrite(context, 1000, offset + extra_offset).unwrap() + seg.rewrite(context, + context.config.max_width, + offset + extra_offset) + .unwrap() }, list_lo, span_hi); @@ -228,7 +233,7 @@ fn rewrite_segment(segment: &ast::PathSegment, let fmt = ListFormatting::for_fn(list_width, offset + extra_offset); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); - // update pos + // Update position of last bracket. *span_lo = next_span_lo; format!("{}<{}>", separator, list_str) @@ -256,9 +261,6 @@ fn rewrite_segment(segment: &ast::PathSegment, let fmt = ListFormatting::for_fn(budget, offset + 1); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); - // update pos - *span_lo = data.span.hi + BytePos(1); - format!("({}){}", list_str, output) } _ => String::new(), diff --git a/src/utils.rs b/src/utils.rs index 07807bf31aa..94f8fec2b0d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp::Ordering; + use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; use syntax::codemap::{CodeMap, Span, BytePos}; @@ -164,38 +166,86 @@ macro_rules! try_opt { }) } +// Wraps string-like values in an Option. Returns Some when the string adheres +// to the Rewrite constraints defined for the Rewrite trait and else otherwise. pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usize) -> Option { - let snippet = s.as_ref(); - - if !snippet.contains('\n') && snippet.len() > width { - return None; - } else { - let mut lines = snippet.lines(); + { + let snippet = s.as_ref(); - // The caller of this function has already placed `offset` - // characters on the first line. - let first_line_max_len = try_opt!(max_width.checked_sub(offset)); - if lines.next().unwrap().len() > first_line_max_len { + if !snippet.contains('\n') && snippet.len() > width { return None; - } + } else { + let mut lines = snippet.lines(); + + // The caller of this function has already placed `offset` + // characters on the first line. + let first_line_max_len = try_opt!(max_width.checked_sub(offset)); + if lines.next().unwrap().len() > first_line_max_len { + return None; + } - // The other lines must fit within the maximum width. - if lines.find(|line| line.len() > max_width).is_some() { - return None; - } + // The other lines must fit within the maximum width. + if lines.find(|line| line.len() > max_width).is_some() { + return None; + } - // `width` is the maximum length of the last line, excluding - // indentation. - // A special check for the last line, since the caller may - // place trailing characters on this line. - if snippet.lines().rev().next().unwrap().len() > offset + width { - return None; + // `width` is the maximum length of the last line, excluding + // indentation. + // A special check for the last line, since the caller may + // place trailing characters on this line. + if snippet.lines().rev().next().unwrap().len() > offset + width { + return None; + } } } Some(s) } +// Binary search in integer range. Returns the first Ok value returned by the +// callback. +// The callback takes an integer and returns either an Ok, or an Err indicating +// whether the `guess' was too high (Ordering::Less), or too low. +// This function is guaranteed to try to the hi value first. +pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option + where C: Fn(usize) -> Result +{ + let mut middle = hi; + + while lo <= hi { + match callback(middle) { + Ok(val) => return Some(val), + Err(Ordering::Less) => { + hi = middle - 1; + } + Err(..) => { + lo = middle + 1; + } + } + middle = (hi + lo) / 2; + } + + None +} + +#[test] +fn bin_search_test() { + let closure = |i| { + match i { + 4 => Ok(()), + j if j > 4 => Err(Ordering::Less), + j if j < 4 => Err(Ordering::Greater), + _ => unreachable!(), + } + }; + + assert_eq!(Some(()), binary_search(1, 10, &closure)); + assert_eq!(None, binary_search(1, 3, &closure)); + assert_eq!(Some(()), binary_search(0, 44, &closure)); + assert_eq!(Some(()), binary_search(4, 125, &closure)); + assert_eq!(None, binary_search(6, 100, &closure)); +} + #[test] fn power_rounding() { assert_eq!(0, round_up_to_power_of_two(0)); -- cgit 1.4.1-3-g733a5 From 33c5776d30723e68d40a84dca57f7895feadb1c4 Mon Sep 17 00:00:00 2001 From: Christoph Burgdorf Date: Sat, 5 Sep 2015 01:31:39 +0200 Subject: Implements struct_lit_force_multiline With struct_lit_force_multiline set to true rustfmt won't ever mangle multiple struct properties into one line. Fixes #253 --- src/config.rs | 22 ++++++ src/expr.rs | 23 ++++-- tests/source/struct_lits_multiline.rs | 72 ++++++++++++++++++ tests/source/struct_lits_visual_multiline.rs | 42 +++++++++++ tests/target/struct_lits_multiline.rs | 108 +++++++++++++++++++++++++++ tests/target/struct_lits_visual_multiline.rs | 61 +++++++++++++++ 6 files changed, 320 insertions(+), 8 deletions(-) create mode 100644 tests/source/struct_lits_multiline.rs create mode 100644 tests/source/struct_lits_visual_multiline.rs create mode 100644 tests/target/struct_lits_multiline.rs create mode 100644 tests/target/struct_lits_visual_multiline.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c7525e930ec..95994531950 100644 --- a/src/config.rs +++ b/src/config.rs @@ -45,6 +45,26 @@ impl Density { } } +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum MultilineStyle { + // Use horizontal layout if it fits in one line, fall back to vertical + PreferSingle, + // Use vertical layout + ForceMulti, +} + + +impl_enum_decodable!(MultilineStyle, PreferSingle, ForceMulti); + +impl MultilineStyle { + pub fn to_list_tactic(self) -> ListTactic { + match self { + MultilineStyle::PreferSingle => ListTactic::HorizontalVertical, + MultilineStyle::ForceMulti => ListTactic::Vertical, + } + } +} + macro_rules! create_config { ($($i:ident: $ty:ty),+ $(,)*) => ( #[derive(RustcDecodable, Clone)] @@ -122,6 +142,7 @@ create_config! { struct_trailing_comma: SeparatorTactic, struct_lit_trailing_comma: SeparatorTactic, struct_lit_style: StructLitStyle, + struct_lit_multiline_style: MultilineStyle, enum_trailing_comma: bool, report_todo: ReportTactic, report_fixme: ReportTactic, @@ -155,6 +176,7 @@ impl Default for Config { struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, struct_lit_style: StructLitStyle::Block, + struct_lit_multiline_style: MultilineStyle::PreferSingle, enum_trailing_comma: true, report_todo: ReportTactic::Always, report_fixme: ReportTactic::Never, diff --git a/src/expr.rs b/src/expr.rs index e11c6e470f6..3e26f8b46b4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -14,7 +14,7 @@ use string::{StringFormat, rewrite_string}; use StructLitStyle; use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width}; use visitor::FmtVisitor; -use config::BlockIndentStyle; +use config::{BlockIndentStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; @@ -997,7 +997,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span.hi); let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, + tactic: match (context.config.struct_lit_style, fields.len()) { + (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, + _ => context.config.struct_lit_multiline_style.to_list_tactic(), + }, separator: ",", trailing_separator: if base.is_some() { SeparatorTactic::Never @@ -1011,12 +1014,16 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }; let fields_str = write_list(&items.collect::>(), &fmt); - match context.config.struct_lit_style { - StructLitStyle::Block if fields_str.contains('\n') => { - let inner_indent = make_indent(context.block_indent + context.config.tab_spaces); - let outer_indent = make_indent(context.block_indent); - Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) - } + let format_on_newline = || { + let inner_indent = make_indent(context.block_indent + + context.config.tab_spaces); + let outer_indent = make_indent(context.block_indent); + Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) + }; + + match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { + (StructLitStyle::Block, _) if fields_str.contains('\n') => format_on_newline(), + (StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(), _ => Some(format!("{} {{ {} }}", path_str, fields_str)), } diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs new file mode 100644 index 00000000000..d0cf7d4069f --- /dev/null +++ b/tests/source/struct_lits_multiline.rs @@ -0,0 +1,72 @@ +// rustfmt-struct_lit_multiline_style: ForceMulti + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs new file mode 100644 index 00000000000..192d88a3903 --- /dev/null +++ b/tests/source/struct_lits_visual_multiline.rs @@ -0,0 +1,42 @@ +// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_multiline_style: ForceMulti + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs new file mode 100644 index 00000000000..2670ef6de1d --- /dev/null +++ b/tests/target/struct_lits_multiline.rs @@ -0,0 +1,108 @@ +// rustfmt-struct_lit_multiline_style: ForceMulti + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { + a: x, + }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), /* Comment */ + }; + + Foo { + a: Bar, + b: foo(), + }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { + memb: 10, + }; +} + +fn issue201() { + let s = S { + a: 0, + ..b + }; +} + +fn issue201_2() { + let s = S { + a: S2 { + ..c + }, + ..b + }; +} diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs new file mode 100644 index 00000000000..94aa121b7a4 --- /dev/null +++ b/tests/target/struct_lits_visual_multiline.rs @@ -0,0 +1,61 @@ +// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_multiline_style: ForceMulti + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Commen + // t + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Commen + // t + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ }; + + Foo { a: Bar, + b: foo(), }; + + Quux { x: if cond { + bar(); + }, + y: baz(), }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +} -- cgit 1.4.1-3-g733a5 From 582aa4f2fed9ab3e6bcfe4112c20cae42a5570e0 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 8 Sep 2015 20:56:33 +0200 Subject: Format closures' return types --- src/expr.rs | 58 +++++++++++++++++++++++++++++++++++++------------ src/items.rs | 25 ++++++++++++++------- tests/source/closure.rs | 13 ++++++++--- tests/target/closure.rs | 21 ++++++++++++------ 4 files changed, 85 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2923aa45097..ab20dc1738d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -163,9 +163,12 @@ fn rewrite_closure(capture: ast::CaptureClause, // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. - let argument_budget = try_opt!(width.checked_sub(4 + mover.len())); + let budget = try_opt!(width.checked_sub(4 + mover.len())); // 1 = | let argument_offset = offset + 1; + let ret_str = try_opt!(fn_decl.output.rewrite(context, budget, argument_offset)); + // 1 = space between arguments and return type. + let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0); let arg_items = itemize_list(context.codemap, fn_decl.inputs.iter(), @@ -176,13 +179,37 @@ fn rewrite_closure(capture: ast::CaptureClause, span_after(span, "|", context.codemap), body.span.lo); - let fmt = ListFormatting::for_fn(argument_budget, argument_offset); + let fmt = ListFormatting { + tactic: ListTactic::HorizontalVertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: argument_offset, + h_width: horizontal_budget, + v_width: budget, + ends_with_newline: false, + }; let list_str = try_opt!(write_list(&arg_items.collect::>(), &fmt)); - let prefix = format!("{}|{}|", mover, list_str); + let mut prefix = format!("{}|{}|", mover, list_str); + + if !ret_str.is_empty() { + if prefix.contains('\n') { + prefix.push('\n'); + prefix.push_str(&make_indent(argument_offset)); + } else { + prefix.push(' '); + } + prefix.push_str(&ret_str); + } + let closure_indent = closure_indent(context, offset); // Try to format closure body as a single line expression without braces. - if body.stmts.is_empty() { + if is_simple_block(body, context.codemap) && !prefix.contains('\n') { + let (spacer, closer) = if ret_str.is_empty() { + (" ", "") + } else { + (" { ", " }") + }; let expr = body.expr.as_ref().unwrap(); // All closure bodies are blocks in the eyes of the AST, but we may not // want to unwrap them when they only contain a single expression. @@ -192,28 +219,31 @@ fn rewrite_closure(capture: ast::CaptureClause, } _ => expr, }; - - // 1 = the separating space between arguments and the body. - let extra_offset = extra_offset(&prefix, offset) + 1; - let budget = try_opt!(width.checked_sub(extra_offset)); + let extra_offset = extra_offset(&prefix, offset) + spacer.len(); + let budget = try_opt!(width.checked_sub(extra_offset + closer.len())); let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); // Checks if rewrite succeeded and fits on a single line. let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false); if accept_rewrite { - return Some(format!("{} {}", prefix, rewrite.unwrap())); + return Some(format!("{}{}{}{}", prefix, spacer, rewrite.unwrap(), closer)); } } // We couldn't format the closure body as a single line expression; fall // back to block formatting. let inner_context = context.overflow_context(closure_indent - context.block_indent); - let body_rewrite = if let ast::Expr_::ExprBlock(ref inner) = body.expr.as_ref().unwrap().node { - inner.rewrite(&inner_context, 0, 0) - } else { - body.rewrite(&inner_context, 0, 0) - }; + let body_rewrite = body.expr + .as_ref() + .and_then(|body_expr| { + if let ast::Expr_::ExprBlock(ref inner) = body_expr.node { + Some(inner.rewrite(&inner_context, 2, 0)) + } else { + None + } + }) + .unwrap_or_else(|| body.rewrite(&inner_context, 2, 0)); Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } diff --git a/src/items.rs b/src/items.rs index e2224ce4eff..7555ea01199 100644 --- a/src/items.rs +++ b/src/items.rs @@ -17,7 +17,7 @@ use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; -use rewrite::Rewrite; +use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density}; use syntax::{ast, abi}; @@ -207,7 +207,8 @@ impl<'a> FmtVisitor<'a> { generics_span)); result.push_str(&generics_str); - let ret_str = self.rewrite_return(&fd.output, indent); + let context = self.get_context(); + let ret_str = fd.output.rewrite(&context, self.config.max_width - indent, indent).unwrap(); // Args. let (one_line_budget, multi_line_budget, mut arg_indent) = @@ -902,14 +903,22 @@ impl<'a> FmtVisitor<'a> { Some(format!(" where {}", preds_str)) } } +} - fn rewrite_return(&self, ret: &ast::FunctionRetTy, indent: usize) -> String { - match *ret { - ast::FunctionRetTy::DefaultReturn(_) => String::new(), - ast::FunctionRetTy::NoReturn(_) => "-> !".to_owned(), +impl Rewrite for ast::FunctionRetTy { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + match *self { + ast::FunctionRetTy::DefaultReturn(_) => Some(String::new()), + ast::FunctionRetTy::NoReturn(_) => { + if width >= 4 { + Some("-> !".to_owned()) + } else { + None + } + } ast::FunctionRetTy::Return(ref ty) => { - let ctxt = &self.get_context(); - format!("-> {}", ty.rewrite(ctxt, ctxt.config.max_width, indent).unwrap()) + let inner_width = try_opt!(width.checked_sub(3)); + ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r)) } } } diff --git a/tests/source/closure.rs b/tests/source/closure.rs index 06b10758011..43ec6860243 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -3,9 +3,6 @@ fn main() { let square = ( |i: i32 | i * i ); - let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb); - let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); @@ -28,12 +25,22 @@ fn main() { let empty = |arg| {}; + let simple = |arg| { /* TODO(#27): comment formatting */ foo(arg) }; + let test = | | { do_something(); do_something_else(); }; let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { + foo() + }; + + let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; arg2 * arg1 - temp } } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 5042f1d037a..a0565167093 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -3,13 +3,6 @@ fn main() { let square = (|i: i32| i * i); - let commented = |// first - a, // argument - // second - b: WithType, // argument - // ignored - _| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbb); - let commented = |// first a, // argument // second @@ -46,6 +39,10 @@ fn main() { let empty = |arg| {}; + let simple = |arg| { /* TODO(#27): comment formatting */ + foo(arg) + }; + let test = || { do_something(); do_something_else(); @@ -59,6 +56,16 @@ fn main() { looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() }; + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { foo() }; + + let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, + aaaaaaaaaaaaaaaaaaaaaaarg2| + -> Strong { + "sup".to_owned() + }; + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; arg2 * arg1 - temp -- cgit 1.4.1-3-g733a5 From e47646b44b6598dc8578bf9ede76893dbcc07ea9 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Wed, 9 Sep 2015 07:56:56 -0400 Subject: Small style fixes. --- Cargo.toml | 1 - src/expr.rs | 2 +- src/string.rs | 9 ++++----- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 377c88a955b..597eb8f942d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,5 +20,4 @@ regex = "0.1.41" [dev-dependencies] diff = "0.1.0" -regex = "0.1" term = "0.2" diff --git a/src/expr.rs b/src/expr.rs index ab20dc1738d..e641d7c6762 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -846,7 +846,7 @@ fn rewrite_string_lit(context: &RewriteContext, width: usize, offset: usize) -> Option { - if context.config.format_strings == false { + if !context.config.format_strings { return Some(context.snippet(span)); } diff --git a/src/string.rs b/src/string.rs index ba93b2db81d..aba6a7f48da 100644 --- a/src/string.rs +++ b/src/string.rs @@ -10,8 +10,6 @@ // Format string literals. - - use unicode_segmentation::UnicodeSegmentation; use regex::Regex; @@ -74,10 +72,11 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { cur_end += 1; } let raw_line = graphemes[cur_start..cur_end].join(""); - let line: &str = if fmt.trim_end { - &(raw_line.trim()) + let line = if fmt.trim_end { + raw_line.trim() } else { - &raw_line + // TODO: use as_str once it's stable. + &*raw_line }; result.push_str(line); -- cgit 1.4.1-3-g733a5 From e7a5f9327ea8abbac1e953b31c6e25c1717f6c3d Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Thu, 10 Sep 2015 18:27:22 -0400 Subject: Add diff write mode https://github.com/nrc/rustfmt/issues/261 --- Cargo.lock | 4 +- Cargo.toml | 4 +- src/bin/rustfmt.rs | 2 +- src/filemap.rs | 14 ++++++- src/lib.rs | 6 +++ src/rustfmt_diff.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/system.rs | 104 ++----------------------------------------------- 7 files changed, 137 insertions(+), 106 deletions(-) create mode 100644 src/rustfmt_diff.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 63854ccae46..30f07fd4f98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ name = "rustfmt" version = "0.0.1" dependencies = [ - "diff 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "diff 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", @@ -21,7 +21,7 @@ dependencies = [ [[package]] name = "diff" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/Cargo.toml b/Cargo.toml index 597eb8f942d..9cb4f929344 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ toml = "0.1.20" rustc-serialize = "0.3.14" unicode-segmentation = "0.1.2" regex = "0.1.41" +diff = "0.1.5" +term = "0.2.11" [dev-dependencies] -diff = "0.1.0" -term = "0.2" diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 86a4faa05f5..9f2387f5c2c 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -82,7 +82,7 @@ fn main() { } fn print_usage>(reason: S) { - println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display]] ", reason.into()); + println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] ", reason.into()); } fn determine_params(args: I) -> Option<(Vec, WriteMode)> diff --git a/src/filemap.rs b/src/filemap.rs index 8bb5a7285bb..91aaece6558 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -14,10 +14,11 @@ use strings::string_buffer::StringBuffer; use std::collections::HashMap; use std::fs::{self, File}; -use std::io::{self, Write, stdout}; +use std::io::{self, Write, Read, stdout}; use WriteMode; use NewlineStyle; use config::Config; +use rustfmt_diff::{make_diff, print_diff}; // A map of the files of a crate, with their new content pub type FileMap = HashMap; @@ -104,6 +105,17 @@ fn write_file(text: &StringBuffer, let stdout_lock = stdout.lock(); try!(write_system_newlines(stdout_lock, text, config)); } + WriteMode::Diff => { + println!("Diff of {}:\n", filename); + let mut f = try!(File::open(filename)); + let mut ori_text = String::new(); + try!(f.read_to_string(&mut ori_text)); + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text, config)); + let fmt_text = String::from_utf8(v).unwrap(); + let diff = make_diff(&ori_text, &fmt_text, 3); + print_diff(diff, |line_num| format!("\nDiff at line {}:", line_num)); + } WriteMode::Return(_) => { // io::Write is not implemented for String, working around with // Vec diff --git a/src/lib.rs b/src/lib.rs index ab748f62a95..7975c77e06d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,8 @@ extern crate strings; extern crate unicode_segmentation; extern crate regex; +extern crate diff; +extern crate term; use rustc::session::Session; use rustc::session::config as rustc_config; @@ -67,6 +69,7 @@ mod rewrite; mod string; mod comment; mod modules; +pub mod rustfmt_diff; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. @@ -82,6 +85,8 @@ pub enum WriteMode { NewFile(&'static str), // Write the output to stdout. Display, + // Write the diff to stdout. + Diff, // Return the result as a mapping from filenames to Strings. Return(&'static Fn(HashMap)), } @@ -94,6 +99,7 @@ impl FromStr for WriteMode { "replace" => Ok(WriteMode::Replace), "display" => Ok(WriteMode::Display), "overwrite" => Ok(WriteMode::Overwrite), + "diff" => Ok(WriteMode::Diff), _ => Err(()), } } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs new file mode 100644 index 00000000000..375cfd661fa --- /dev/null +++ b/src/rustfmt_diff.rs @@ -0,0 +1,109 @@ +use std::collections::VecDeque; +use diff; +use term; + +pub enum DiffLine { + Context(String), + Expected(String), + Resulting(String), +} + +pub struct Mismatch { + pub line_number: u32, + pub lines: Vec, +} + +impl Mismatch { + fn new(line_number: u32) -> Mismatch { + Mismatch { line_number: line_number, lines: Vec::new() } + } +} + +// Produces a diff between the expected output and actual output of rustfmt. +pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { + let mut line_number = 1; + let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); + let mut lines_since_mismatch = context_size + 1; + let mut results = Vec::new(); + let mut mismatch = Mismatch::new(0); + + for result in diff::lines(expected, actual) { + match result { + diff::Result::Left(str) => { + if lines_since_mismatch >= context_size { + results.push(mismatch); + mismatch = Mismatch::new(line_number - context_queue.len() as u32); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Resulting(str.to_owned())); + lines_since_mismatch = 0; + } + diff::Result::Right(str) => { + if lines_since_mismatch >= context_size { + results.push(mismatch); + mismatch = Mismatch::new(line_number - context_queue.len() as u32); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Expected(str.to_owned())); + line_number += 1; + lines_since_mismatch = 0; + } + diff::Result::Both(str, _) => { + if context_queue.len() >= context_size { + let _ = context_queue.pop_front(); + } + + if lines_since_mismatch < context_size { + mismatch.lines.push(DiffLine::Context(str.to_owned())); + } else { + context_queue.push_back(str); + } + + line_number += 1; + lines_since_mismatch += 1; + } + } + } + + results.push(mismatch); + results.remove(0); + + results +} + +pub fn print_diff(diff: Vec, get_section_title: F) + where F: Fn(u32) -> String +{ + let mut t = term::stdout().unwrap(); + for mismatch in diff { + t.fg(term::color::BRIGHT_WHITE).unwrap(); + let title = get_section_title(mismatch.line_number); + writeln!(t, "{}", title).unwrap(); + + for line in mismatch.lines { + match line { + DiffLine::Context(ref str) => { + t.fg(term::color::WHITE).unwrap(); + writeln!(t, " {}⏎", str).unwrap(); + } + DiffLine::Expected(ref str) => { + t.fg(term::color::GREEN).unwrap(); + writeln!(t, "+{}⏎", str).unwrap(); + } + DiffLine::Resulting(ref str) => { + t.fg(term::color::RED).unwrap(); + writeln!(t, "-{}⏎", str).unwrap(); + } + } + } + } + t.reset().unwrap(); +} diff --git a/tests/system.rs b/tests/system.rs index d6ba46c9cf5..b0d96468eca 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -15,12 +15,13 @@ extern crate diff; extern crate regex; extern crate term; -use std::collections::{VecDeque, HashMap}; +use std::collections::HashMap; use std::fs; use std::io::{self, Read, BufRead, BufReader}; use std::thread; use rustfmt::*; use rustfmt::config::Config; +use rustfmt::rustfmt_diff::*; static DIFF_CONTEXT_SIZE: usize = 3; @@ -94,27 +95,7 @@ fn print_mismatches(result: HashMap>) { let mut t = term::stdout().unwrap(); for (file_name, diff) in result { - for mismatch in diff { - t.fg(term::color::BRIGHT_WHITE).unwrap(); - writeln!(t, "\nMismatch at {}:{}:", file_name, mismatch.line_number).unwrap(); - - for line in mismatch.lines { - match line { - DiffLine::Context(ref str) => { - t.fg(term::color::WHITE).unwrap(); - writeln!(t, " {}⏎", str).unwrap(); - } - DiffLine::Expected(ref str) => { - t.fg(term::color::GREEN).unwrap(); - writeln!(t, "+{}⏎", str).unwrap(); - } - DiffLine::Resulting(ref str) => { - t.fg(term::color::RED).unwrap(); - writeln!(t, "-{}⏎", str).unwrap(); - } - } - } - } + print_diff(diff, |line_num| format!("\nMismatch at {}:{}:", file_name, line_num)); } assert!(t.reset().unwrap()); @@ -206,7 +187,7 @@ fn handle_result(result: HashMap) { // TODO: speedup by running through bytes iterator f.read_to_string(&mut text).ok().expect("Failed reading target."); if fmt_text != text { - let diff = make_diff(&fmt_text, &text, DIFF_CONTEXT_SIZE); + let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); failures.insert(file_name, diff); } } @@ -226,80 +207,3 @@ fn get_target(file_name: &str, target: Option<&str>) -> String { file_name.to_owned() } } - -pub enum DiffLine { - Context(String), - Expected(String), - Resulting(String), -} - -pub struct Mismatch { - line_number: u32, - pub lines: Vec, -} - -impl Mismatch { - fn new(line_number: u32) -> Mismatch { - Mismatch { line_number: line_number, lines: Vec::new() } - } -} - -// Produces a diff between the expected output and actual output of rustfmt. -fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { - let mut line_number = 1; - let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); - let mut lines_since_mismatch = context_size + 1; - let mut results = Vec::new(); - let mut mismatch = Mismatch::new(0); - - for result in diff::lines(expected, actual) { - match result { - diff::Result::Left(str) => { - if lines_since_mismatch >= context_size { - results.push(mismatch); - mismatch = Mismatch::new(line_number - context_queue.len() as u32); - } - - while let Some(line) = context_queue.pop_front() { - mismatch.lines.push(DiffLine::Context(line.to_owned())); - } - - mismatch.lines.push(DiffLine::Resulting(str.to_owned())); - lines_since_mismatch = 0; - } - diff::Result::Right(str) => { - if lines_since_mismatch >= context_size { - results.push(mismatch); - mismatch = Mismatch::new(line_number - context_queue.len() as u32); - } - - while let Some(line) = context_queue.pop_front() { - mismatch.lines.push(DiffLine::Context(line.to_owned())); - } - - mismatch.lines.push(DiffLine::Expected(str.to_owned())); - line_number += 1; - lines_since_mismatch = 0; - } - diff::Result::Both(str, _) => { - if context_queue.len() >= context_size { - let _ = context_queue.pop_front(); - } - - if lines_since_mismatch < context_size { - mismatch.lines.push(DiffLine::Context(str.to_owned())); - } else { - context_queue.push_back(str); - } - - line_number += 1; - lines_since_mismatch += 1; - } - } - } - - results.push(mismatch); - results.remove(0); - - results -} -- cgit 1.4.1-3-g733a5 From c680bb4030784ca15cc7d6c39caf297c9fb010e4 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 11 Sep 2015 00:52:16 +0200 Subject: Implement basic chain formatting --- src/chains.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/comment.rs | 45 ++++++++++++++---- src/expr.rs | 109 +++++++++++++++++++++++------------------- src/items.rs | 59 +++++++++++------------ src/lib.rs | 1 + src/lists.rs | 32 ++++++------- src/missed_spans.rs | 25 +++++----- src/string.rs | 4 +- src/types.rs | 56 +++++++++++----------- src/utils.rs | 22 +++++++-- src/visitor.rs | 24 +++------- tests/system.rs | 30 ++++++------ 12 files changed, 354 insertions(+), 186 deletions(-) create mode 100644 src/chains.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs new file mode 100644 index 00000000000..094cd358696 --- /dev/null +++ b/src/chains.rs @@ -0,0 +1,133 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rewrite::{Rewrite, RewriteContext}; +use utils::{span_after, make_indent, extra_offset}; +use expr::rewrite_call; + +use syntax::{ast, ptr}; +use syntax::codemap::{mk_sp, Span}; +use syntax::print::pprust; + +pub fn rewrite_chain(orig_expr: &ast::Expr, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option { + let mut expr = orig_expr; + let mut rewrites = Vec::new(); + let indent = context.block_indent + context.config.tab_spaces; + let max_width = context.config.max_width - context.config.tab_spaces; + + loop { + match expr.node { + ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { + // FIXME: a lot of duplication between this and the + // rewrite_method_call in expr.rs. + let new_span = mk_sp(expressions[0].span.hi, expr.span.hi); + let lo = span_after(new_span, "(", context.codemap); + let new_span = mk_sp(lo, expr.span.hi); + + let rewrite = rewrite_method_call(method_name.node, + types, + &expressions[1..], + new_span, + context, + max_width, + indent); + rewrites.push(try_opt!(rewrite)); + expr = &expressions[0]; + } + ast::Expr_::ExprField(ref subexpr, ref field) => { + expr = subexpr; + rewrites.push(format!(".{}", field.node)); + } + ast::Expr_::ExprTupField(ref subexpr, ref field) => { + expr = subexpr; + rewrites.push(format!(".{}", field.node)); + } + _ => break, + } + } + + let parent_rewrite = try_opt!(expr.rewrite(context, width, offset)); + + // TODO: add exception for when rewrites.len() == 1 + if rewrites.len() == 1 { + let extra_offset = extra_offset(&parent_rewrite, offset); + let max_width = try_opt!(width.checked_sub(extra_offset)); + // FIXME: massive duplication + let rerewrite = match orig_expr.node { + ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { + let new_span = mk_sp(expressions[0].span.hi, orig_expr.span.hi); + let lo = span_after(new_span, "(", context.codemap); + let new_span = mk_sp(lo, orig_expr.span.hi); + + rewrite_method_call(method_name.node, + types, + &expressions[1..], + new_span, + context, + max_width, + offset + extra_offset) + } + ast::Expr_::ExprField(_, ref field) => { + Some(format!(".{}", field.node)) + } + ast::Expr_::ExprTupField(_, ref field) => { + Some(format!(".{}", field.node)) + } + _ => unreachable!(), + }; + + return Some(format!("{}{}", parent_rewrite, try_opt!(rerewrite))); + } + + let total_width = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len(); + + let connector = if total_width <= width && rewrites.iter().all(|s| !s.contains('\n')) { + String::new() + } else { + format!("\n{}", make_indent(indent)) + }; + + // FIXME: don't do this. There's a more efficient way. VecDeque? + rewrites.reverse(); + + // Put the first link on the same line as parent, if it fits. + let first_connector = if parent_rewrite.len() + rewrites[0].len() <= width && + !rewrites[0].contains('\n') { + "" + } else { + &connector[..] + }; + + Some(format!("{}{}{}", parent_rewrite, first_connector, rewrites.join(&connector))) +} + +fn rewrite_method_call(method_name: ast::Ident, + types: &[ptr::P], + args: &[ptr::P], + span: Span, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option { + let type_str = if types.is_empty() { + String::new() + } else { + let type_list = types.iter().map(|ty| pprust::ty_to_string(ty)).collect::>(); + format!("::<{}>", type_list.join(", ")) + }; + + let callee_str = format!(".{}{}", method_name, type_str); + + rewrite_call(context, &callee_str, args, span, width, offset) +} diff --git a/src/comment.rs b/src/comment.rs index f1cecd7318b..5cec1678ac2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -25,8 +25,7 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz ("// ", "", "// ") }; - let max_chars = width.checked_sub(closer.len()).unwrap_or(1) - .checked_sub(opener.len()).unwrap_or(1); + let max_chars = width.checked_sub(closer.len() + opener.len()).unwrap_or(1); let fmt = StringFormat { opener: "", @@ -41,17 +40,18 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz let indent_str = make_indent(offset); let line_breaks = s.chars().filter(|&c| c == '\n').count(); - let (_, mut s) = s.lines().enumerate() + let (_, mut s) = s.lines() + .enumerate() .map(|(i, mut line)| { - line = line.trim(); + line = line.trim(); // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = &line[..(line.len() - 2)]; - } + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = &line[..(line.len() - 2)]; + } - line.trim_right() - }) + line.trim_right() + }) .map(left_trim_comment_line) .map(|line| { if line_breaks == 0 { @@ -160,9 +160,34 @@ fn comment_end() { /// Returns true if text contains any comment. pub fn contains_comment(text: &str) -> bool { - CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment ) + CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment) +} + +pub fn uncommented(text: &str) -> String { + CharClasses::new(text.chars()) + .filter_map(|(s, c)| { + match s { + CodeCharKind::Normal => Some(c), + CodeCharKind::Comment => None, + } + }) + .collect() } +#[test] +fn test_uncommented() { + assert_eq!(&uncommented("abc/*...*/"), "abc"); + assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); +} + +#[test] +fn test_contains_comment() { + assert_eq!(contains_comment("abc"), false); + assert_eq!(contains_comment("abc // qsdf"), true); + assert_eq!(contains_comment("abc /* kqsdf"), true); + assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); +} struct CharClasses where T: Iterator, diff --git a/src/expr.rs b/src/expr.rs index e641d7c6762..2c77cdc9e78 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::cmp::Ordering; +use std::borrow::Borrow; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; @@ -21,6 +22,7 @@ use config::{BlockIndentStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; +use chains::rewrite_chain; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; @@ -38,7 +40,16 @@ impl Rewrite for ast::Expr { } } ast::Expr_::ExprCall(ref callee, ref args) => { - rewrite_call(context, callee, args, self.span, width, offset) + // // FIXME using byte lens instead of char lens (and probably all over the place too) + // // 2 is for parens + // let max_callee_width = try_opt!(width.checked_sub(2)); + // let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); + + // let new_span = mk_sp(callee.span.hi, self.span.hi); + // let lo = span_after(new_span, "(", context.codemap); + // let new_span = mk_sp(lo, self.span.hi); + + rewrite_call(context, &**callee, args, self.span, width, offset) } ast::Expr_::ExprParen(ref subexpr) => { rewrite_paren(context, subexpr, width, offset) @@ -137,6 +148,11 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } + ast::Expr_::ExprField(..) | + ast::Expr_::ExprTupField(..) | + ast::Expr_::ExprMethodCall(..) => { + rewrite_chain(self, context, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. _ => wrap_str(context.snippet(self.span), context.config.max_width, width, offset), @@ -393,9 +409,9 @@ impl<'a> Rewrite for Loop<'a> { }; // FIXME: this drops any comment between "loop" and the block. - self.block.rewrite(context, width, offset).map(|result| { - format!("{}{}{} {}", label_string, self.keyword, pat_expr_string, result) - }) + self.block + .rewrite(context, width, offset) + .map(|result| format!("{}{}{} {}", label_string, self.keyword, pat_expr_string, result)) } } @@ -762,9 +778,7 @@ fn rewrite_guard(context: &RewriteContext, // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; if overhead < width { - let cond_str = guard.rewrite(context, - width - overhead, - offset + pattern_width + 4); + let cond_str = guard.rewrite(context, width - overhead, offset + pattern_width + 4); if let Some(cond_str) = cond_str { return Some(format!(" if {}", cond_str)); } @@ -866,36 +880,39 @@ fn rewrite_string_lit(context: &RewriteContext, Some(rewrite_string(str_lit, &fmt)) } -fn rewrite_call(context: &RewriteContext, - callee: &ast::Expr, - args: &[ptr::P], - span: Span, - width: usize, - offset: usize) - -> Option { - let callback = |callee_max_width| { - rewrite_call_inner(context, - callee, - callee_max_width, - args, - span, - width, - offset) - }; - +pub fn rewrite_call(context: &RewriteContext, + callee: &R, + args: &[ptr::P], + span: Span, + width: usize, + offset: usize) + -> Option + where R: Rewrite +{ // 2 is for parens let max_width = try_opt!(width.checked_sub(2)); - binary_search(1, max_width, callback) + binary_search(1, max_width, |callee_max_width| { + rewrite_call_inner(context, + callee, + callee_max_width, + args, + span, + width, + offset) + }) } -fn rewrite_call_inner(context: &RewriteContext, - callee: &ast::Expr, - max_callee_width: usize, - args: &[ptr::P], - span: Span, - width: usize, - offset: usize) - -> Result { +fn rewrite_call_inner(context: &RewriteContext, + callee: &R, + max_callee_width: usize, + args: &[ptr::P], + span: Span, + width: usize, + offset: usize) + -> Result + where R: Rewrite +{ + let callee = callee.borrow(); // FIXME using byte lens instead of char lens (and probably all over the // place too) let callee_str = match callee.rewrite(context, max_callee_width, offset) { @@ -929,7 +946,7 @@ fn rewrite_call_inner(context: &RewriteContext, item.rewrite(&inner_context, remaining_width, offset) .unwrap_or(context.snippet(item.span)) }, - callee.span.hi + BytePos(1), + span.lo, span.hi); let fmt = ListFormatting::for_fn(remaining_width, offset); @@ -1004,8 +1021,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } }; - let field_iter = fields.into_iter().map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + let field_iter = fields.into_iter() + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); let inner_context = &RewriteContext { block_indent: indent, ..*context }; @@ -1016,10 +1034,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => field.span.lo, StructLitField::Base(ref expr) => { - let last_field_hi = - fields.last().map_or(span.lo, |field| field.span.hi); - let snippet = - context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let last_field_hi = fields.last() + .map_or(span.lo, |field| field.span.hi); + let snippet = context.snippet(mk_sp(last_field_hi, + expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) } @@ -1035,7 +1053,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => { rewrite_field(inner_context, &field, h_budget, indent) - .unwrap_or(context.snippet(field.span)) + .unwrap_or(context.snippet(field.span)) } StructLitField::Base(ref expr) => { // 2 = .. @@ -1152,10 +1170,7 @@ fn rewrite_binary_op(context: &RewriteContext, // worth trying to put everything on one line. if rhs_result.len() + 2 + operator_str.len() < width && !rhs_result.contains('\n') { // 1 = space between lhs expr and operator - if let Some(mut result) = lhs.rewrite(context, - width - 1 - operator_str.len(), - offset) { - + if let Some(mut result) = lhs.rewrite(context, width - 1 - operator_str.len(), offset) { result.push(' '); result.push_str(&operator_str); result.push(' '); @@ -1167,9 +1182,7 @@ fn rewrite_binary_op(context: &RewriteContext, return Some(result); } - if let Some(rhs_result) = rhs.rewrite(context, - remaining_width, - offset + result.len()) { + if let Some(rhs_result) = rhs.rewrite(context, remaining_width, offset + result.len()) { if rhs_result.len() <= remaining_width { result.push_str(&rhs_result); return Some(result); diff --git a/src/items.rs b/src/items.rs index 7555ea01199..c7a8c4eb0d7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -211,8 +211,10 @@ impl<'a> FmtVisitor<'a> { let ret_str = fd.output.rewrite(&context, self.config.max_width - indent, indent).unwrap(); // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = - self.compute_budgets_for_args(&result, indent, ret_str.len(), newline_brace); + let (one_line_budget, multi_line_budget, mut arg_indent) = self.compute_budgets_for_args(&result, + indent, + ret_str.len(), + newline_brace); debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", one_line_budget, multi_line_budget, arg_indent); @@ -237,10 +239,7 @@ impl<'a> FmtVisitor<'a> { } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics.ty_params - .last() - .map(|tp| end_typaram(tp)) - .unwrap_or(span.lo); + let args_start = generics.ty_params.last().map(|tp| end_typaram(tp)).unwrap_or(span.lo); let args_span = codemap::mk_sp(span_after(codemap::mk_sp(args_start, span.hi), "(", self.codemap), @@ -333,12 +332,13 @@ impl<'a> FmtVisitor<'a> { // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. - let min_args = explicit_self.and_then(|explicit_self| { - rewrite_explicit_self(explicit_self, args) - }).map(|self_str| { - arg_item_strs[0] = self_str; - 2 - }).unwrap_or(1); + let min_args = explicit_self + .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args)) + .map(|self_str| { + arg_item_strs[0] = self_str; + 2 + }) + .unwrap_or(1); // Comments between args let mut arg_items = Vec::new(); @@ -760,11 +760,10 @@ impl<'a> FmtVisitor<'a> { let typ = field.node.ty.rewrite(&self.get_context(), 1000, 0).unwrap(); let indent = self.block_indent + self.config.tab_spaces; - let mut attr_str = field.node.attrs - .rewrite(&self.get_context(), - self.config.max_width - indent, - indent) - .unwrap(); + let mut attr_str = field.node + .attrs + .rewrite(&self.get_context(), self.config.max_width - indent, indent) + .unwrap(); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&make_indent(indent)); @@ -803,22 +802,20 @@ impl<'a> FmtVisitor<'a> { // Strings for the generics. let context = self.get_context(); // FIXME: don't unwrap - let lt_strs = lifetimes.iter().map(|lt| { - lt.rewrite(&context, h_budget, offset).unwrap() - }); - let ty_strs = tys.iter().map(|ty_param| { - ty_param.rewrite(&context, h_budget, offset).unwrap() - }); + let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset).unwrap()); + let ty_strs = tys.iter() + .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); // Extract comments between generics. - let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - codemap::mk_sp(l.lifetime.span.lo, hi) - }); + let lt_spans = lifetimes.iter() + .map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + codemap::mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(self.codemap, diff --git a/src/lib.rs b/src/lib.rs index 7975c77e06d..6993d3044d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,6 +70,7 @@ mod string; mod comment; mod modules; pub mod rustfmt_diff; +mod chains; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. diff --git a/src/lists.rs b/src/lists.rs index cf68d86dd2b..a8cf0830f97 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -283,22 +283,22 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> }; // Post-comment - let next_start = match self.inner.peek() { - Some(ref next_item) => (self.get_lo)(next_item), - None => self.next_span_start - }; - let post_snippet = self.codemap.span_to_snippet(codemap::mk_sp((self.get_hi)(&item), - next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let block_open_index = post_snippet.find("/*"); - let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(",").unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. + let next_start = match self.inner.peek() { + Some(ref next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.codemap + .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let block_open_index = post_snippet.find("/*"); + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(",").unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. // Comment belongs to next item. (Some(i), None) if i > separator_index => { separator_index + 1 diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 33d096c3ba0..535fc4c8ad9 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -17,21 +17,20 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| { - this.buffer.push_str(last_snippet) - }) + self.format_missing_inner(end, |this, last_snippet, _| this.buffer.push_str(last_snippet)) } pub fn format_missing_with_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, snippet| { - this.buffer.push_str(last_snippet.trim_right()); - if last_snippet == snippet { + self.format_missing_inner(end, + |this, last_snippet, snippet| { + this.buffer.push_str(last_snippet.trim_right()); + if last_snippet == snippet { // No new lines in the snippet. - this.buffer.push_str("\n"); - } - let indent = make_indent(this.block_indent); - this.buffer.push_str(&indent); - }) + this.buffer.push_str("\n"); + } + let indent = make_indent(this.block_indent); + this.buffer.push_str(&indent); + }) } fn format_missing_inner(&mut self, @@ -60,9 +59,7 @@ impl<'a> FmtVisitor<'a> { let span = codemap::mk_sp(start, end); let snippet = self.snippet(span); - self.write_snippet(&snippet, - true, - &process_last_snippet); + self.write_snippet(&snippet, true, &process_last_snippet); } fn write_snippet(&mut self, diff --git a/src/string.rs b/src/string.rs index aba6a7f48da..5e5af61faf5 100644 --- a/src/string.rs +++ b/src/string.rs @@ -44,8 +44,8 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); - let max_chars = fmt.width.checked_sub(fmt.opener.len()).unwrap_or(0) - .checked_sub(ender_length).unwrap_or(1); + let max_chars = fmt.width.checked_sub(fmt.opener.len() + ender_length).unwrap_or(1); + loop { let mut cur_end = cur_start + max_chars; diff --git a/src/types.rs b/src/types.rs index dace1d84bca..1e0da1aba4d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -196,13 +196,12 @@ fn rewrite_segment(segment: &ast::PathSegment, ast::PathParameters::AngleBracketedParameters(ref data) if !data.lifetimes.is_empty() || !data.types.is_empty() || !data.bindings.is_empty() => { - let param_list = data.lifetimes.iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter() - .map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter() - .map(|x| SegmentParam::Binding(&*x))) - .collect::>(); + let param_list = data.lifetimes + .iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); @@ -279,30 +278,27 @@ impl Rewrite for ast::WherePredicate { ref bounds, ..}) => { if !bound_lifetimes.is_empty() { - let lifetime_str = bound_lifetimes.iter().map(|lt| { - lt.rewrite(context, width, offset).unwrap() - }).collect::>().join(", "); + let lifetime_str = bound_lifetimes.iter() + .map(|lt| lt.rewrite(context, width, offset).unwrap()) + .collect::>() + .join(", "); let type_str = pprust::ty_to_string(bounded_ty); // 8 = "for<> : ".len() let used_width = lifetime_str.len() + type_str.len() + 8; - let bounds_str = bounds.iter().map(|ty_bound| { - ty_bound.rewrite(context, - width - used_width, - offset + used_width) - .unwrap() - }).collect::>().join(" + "); + let bounds_str = bounds.iter() + .map(|ty_bound| ty_bound.rewrite(context, width - used_width, offset + used_width).unwrap()) + .collect::>() + .join(" + "); format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { let type_str = pprust::ty_to_string(bounded_ty); // 2 = ": ".len() let used_width = type_str.len() + 2; - let bounds_str = bounds.iter().map(|ty_bound| { - ty_bound.rewrite(context, - width - used_width, - offset + used_width) - .unwrap() - }).collect::>().join(" + "); + let bounds_str = bounds.iter() + .map(|ty_bound| ty_bound.rewrite(context, width - used_width, offset + used_width).unwrap()) + .collect::>() + .join(" + "); format!("{}: {}", type_str, bounds_str) } @@ -373,9 +369,11 @@ impl Rewrite for ast::TyParam { if !self.bounds.is_empty() { result.push_str(": "); - let bounds = self.bounds.iter().map(|ty_bound| { - ty_bound.rewrite(context, width, offset).unwrap() - }).collect::>().join(" + "); + let bounds = self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, width, offset).unwrap()) + .collect::>() + .join(" + "); result.push_str(&bounds); } @@ -392,9 +390,11 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { if !self.bound_lifetimes.is_empty() { - let lifetime_str = self.bound_lifetimes.iter().map(|lt| { - lt.rewrite(context, width, offset).unwrap() - }).collect::>().join(", "); + let lifetime_str = self.bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, width, offset).unwrap()) + .collect::>() + .join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); diff --git a/src/utils.rs b/src/utils.rs index 94f8fec2b0d..d8acea40d2a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -14,6 +14,7 @@ use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; use syntax::codemap::{CodeMap, Span, BytePos}; use comment::FindUncommented; +use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; @@ -93,10 +94,16 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { // Find the end of a TyParam #[inline] pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { - typaram.bounds.last().map(|bound| match *bound { - ast::RegionTyParamBound(ref lt) => lt.span, - ast::TraitTyParamBound(ref prt, _) => prt.span, - }).unwrap_or(typaram.span).hi + typaram.bounds + .last() + .map(|bound| { + match *bound { + ast::RegionTyParamBound(ref lt) => lt.span, + ast::TraitTyParamBound(ref prt, _) => prt.span, + } + }) + .unwrap_or(typaram.span) + .hi } #[inline] @@ -202,6 +209,13 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usi Some(s) } +impl Rewrite for String { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + // FIXME: unnecessary clone + wrap_str(self.clone(), context.config.max_width, width, offset) + } +} + // Binary search in integer range. Returns the first Ok value returned by the // callback. // The callback takes an integer and returns either an Ok, or an Err indicating diff --git a/src/visitor.rs b/src/visitor.rs index c1c1f2fcbbd..7e02d0f1d1f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -202,19 +202,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemStruct(ref def, ref generics) => { self.format_missing_with_indent(item.span.lo); - self.visit_struct(item.ident, - item.vis, - def, - generics, - item.span); + self.visit_struct(item.ident, item.vis, def, generics, item.span); } ast::Item_::ItemEnum(ref def, ref generics) => { self.format_missing_with_indent(item.span.lo); - self.visit_enum(item.ident, - item.vis, - def, - generics, - item.span); + self.visit_enum(item.ident, item.vis, def, generics, item.span); self.last_pos = item.span.hi; } ast::Item_::ItemMod(ref module) => { @@ -236,10 +228,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.format_missing_with_indent(ti.span.lo); let indent = self.block_indent; - let new_fn = self.rewrite_required_fn(indent, - ti.ident, - sig, - ti.span); + let new_fn = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); if let Some(fn_str) = new_fn { @@ -299,10 +288,9 @@ impl<'a> FmtVisitor<'a> { if utils::contains_skip(attrs) { true } else { - let rewrite = attrs.rewrite(&self.get_context(), - self.config.max_width - self.block_indent, - self.block_indent) - .unwrap(); + let rewrite = attrs + .rewrite(&self.get_context(), self.config.max_width - self.block_indent, self.block_indent) + .unwrap(); self.buffer.push_str(&rewrite); let last = attrs.last().unwrap(); self.last_pos = last.span.hi; diff --git a/tests/system.rs b/tests/system.rs index b0d96468eca..10dc629c805 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -120,10 +120,8 @@ pub fn idempotent_check(filename: String) -> Result<(), HashMap HashMap { let regex = regex::Regex::new(&pattern).ok().expect("Failed creating pattern 1."); // Matches lines containing significant comments or whitespace. - let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") - .ok().expect("Failed creating pattern 2."); + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)").ok() + .expect("Failed creating pattern 2."); reader.lines() - .map(|line| line.ok().expect("Failed getting line.")) - .take_while(|line| line_regex.is_match(&line)) - .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { - (capture.at(1).expect("Couldn't unwrap capture.").to_owned(), - capture.at(2).expect("Couldn't unwrap capture.").to_owned()) - }) - }) - .collect() + .map(|line| line.ok().expect("Failed getting line.")) + .take_while(|line| line_regex.is_match(&line)) + .filter_map(|line| { + regex.captures_iter(&line) + .next() + .map(|capture| { + (capture.at(1).expect("Couldn't unwrap capture.").to_owned(), + capture.at(2).expect("Couldn't unwrap capture.").to_owned()) + }) + }) + .collect() } // Compare output to input. -- cgit 1.4.1-3-g733a5 From 659c9b90373183620eeb6118d41b1e94b8ad70a2 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:09:39 +0200 Subject: Update indentation heuristics for single arg functions --- src/chains.rs | 13 +++-- src/comment.rs | 16 ++--- src/expr.rs | 7 ++- src/imports.rs | 8 +-- src/items.rs | 36 ++++++------ src/lists.rs | 33 ++++++----- src/types.rs | 116 ++++++++++++++++++++----------------- src/utils.rs | 10 ++-- src/visitor.rs | 6 +- tests/system.rs | 20 +++---- tests/target/closure.rs | 47 ++++++++------- tests/target/expr-visual-indent.rs | 4 +- tests/target/expr.rs | 12 ++-- 13 files changed, 174 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 094cd358696..23e669d08af 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -23,8 +23,8 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, -> Option { let mut expr = orig_expr; let mut rewrites = Vec::new(); - let indent = context.block_indent + context.config.tab_spaces; - let max_width = context.config.max_width - context.config.tab_spaces; + let indent = offset + context.config.tab_spaces; + let max_width = try_opt!(context.config.max_width.checked_sub(indent)); loop { match expr.node { @@ -103,7 +103,8 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, // Put the first link on the same line as parent, if it fits. let first_connector = if parent_rewrite.len() + rewrites[0].len() <= width && - !rewrites[0].contains('\n') { + !rewrites[0].contains('\n') || + parent_rewrite.len() <= context.config.tab_spaces { "" } else { &connector[..] @@ -128,6 +129,10 @@ fn rewrite_method_call(method_name: ast::Ident, }; let callee_str = format!(".{}{}", method_name, type_str); + let inner_context = &RewriteContext { + block_indent: offset, + ..*context + }; - rewrite_call(context, &callee_str, args, span, width, offset) + rewrite_call(inner_context, &callee_str, args, span, width, offset) } diff --git a/src/comment.rs b/src/comment.rs index 5cec1678ac2..ed06ff7e5b6 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -41,9 +41,9 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz let line_breaks = s.chars().filter(|&c| c == '\n').count(); let (_, mut s) = s.lines() - .enumerate() - .map(|(i, mut line)| { - line = line.trim(); + .enumerate() + .map(|(i, mut line)| { + line = line.trim(); // Drop old closer. if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { @@ -166,11 +166,11 @@ pub fn contains_comment(text: &str) -> bool { pub fn uncommented(text: &str) -> String { CharClasses::new(text.chars()) .filter_map(|(s, c)| { - match s { - CodeCharKind::Normal => Some(c), - CodeCharKind::Comment => None, - } - }) + match s { + CodeCharKind::Normal => Some(c), + CodeCharKind::Comment => None, + } + }) .collect() } diff --git a/src/expr.rs b/src/expr.rs index 2c77cdc9e78..710fb6f8703 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1022,8 +1022,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }; let field_iter = fields.into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); let inner_context = &RewriteContext { block_indent: indent, ..*context }; @@ -1035,7 +1035,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, StructLitField::Regular(ref field) => field.span.lo, StructLitField::Base(ref expr) => { let last_field_hi = fields.last() - .map_or(span.lo, |field| field.span.hi); + .map_or(span.lo, + |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); diff --git a/src/imports.rs b/src/imports.rs index 8411b3208df..4b08a8b35e1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -38,10 +38,10 @@ impl Rewrite for ast::ViewPath { let path_str = try_opt!(path.rewrite(context, width - ident_str.len() - 4, offset)); Some(if path.segments.last().unwrap().identifier == ident { - path_str - } else { - format!("{} as {}", path_str, ident_str) - }) + path_str + } else { + format!("{} as {}", path_str, ident_str) + }) } } } diff --git a/src/items.rs b/src/items.rs index c7a8c4eb0d7..ef8ad37b126 100644 --- a/src/items.rs +++ b/src/items.rs @@ -333,12 +333,12 @@ impl<'a> FmtVisitor<'a> { // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. let min_args = explicit_self - .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args)) - .map(|self_str| { - arg_item_strs[0] = self_str; - 2 - }) - .unwrap_or(1); + .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args)) + .map(|self_str| { + arg_item_strs[0] = self_str; + 2 + }) + .unwrap_or(1); // Comments between args let mut arg_items = Vec::new(); @@ -761,9 +761,9 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent + self.config.tab_spaces; let mut attr_str = field.node - .attrs - .rewrite(&self.get_context(), self.config.max_width - indent, indent) - .unwrap(); + .attrs + .rewrite(&self.get_context(), self.config.max_width - indent, indent) + .unwrap(); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&make_indent(indent)); @@ -804,18 +804,18 @@ impl<'a> FmtVisitor<'a> { // FIXME: don't unwrap let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset).unwrap()); let ty_strs = tys.iter() - .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); + .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); // Extract comments between generics. let lt_spans = lifetimes.iter() - .map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - codemap::mk_sp(l.lifetime.span.lo, hi) - }); + .map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + codemap::mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(self.codemap, diff --git a/src/lists.rs b/src/lists.rs index a8cf0830f97..b07b81bd672 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -283,22 +283,23 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> }; // Post-comment - let next_start = match self.inner.peek() { - Some(ref next_item) => (self.get_lo)(next_item), - None => self.next_span_start, - }; - let post_snippet = self.codemap - .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let block_open_index = post_snippet.find("/*"); - let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(",").unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. + let next_start = match self.inner.peek() { + Some(ref next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.codemap + .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), + next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let block_open_index = post_snippet.find("/*"); + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(",").unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. // Comment belongs to next item. (Some(i), None) if i > separator_index => { separator_index + 1 diff --git a/src/types.rs b/src/types.rs index 1e0da1aba4d..9f3cc17e4c7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -197,11 +197,11 @@ fn rewrite_segment(segment: &ast::PathSegment, !data.types.is_empty() || !data.bindings.is_empty() => { let param_list = data.lifetimes - .iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) - .collect::>(); + .iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); @@ -273,54 +273,66 @@ impl Rewrite for ast::WherePredicate { // TODO dead spans? // TODO assumes we'll always fit on one line... Some(match *self { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, - ref bounded_ty, - ref bounds, - ..}) => { - if !bound_lifetimes.is_empty() { - let lifetime_str = bound_lifetimes.iter() - .map(|lt| lt.rewrite(context, width, offset).unwrap()) - .collect::>() - .join(", "); - let type_str = pprust::ty_to_string(bounded_ty); + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ref bound_lifetimes, + ref bounded_ty, + ref bounds, + .. }) => { + if !bound_lifetimes.is_empty() { + let lifetime_str = bound_lifetimes.iter() + .map(|lt| lt.rewrite(context, width, offset).unwrap()) + .collect::>() + .join(", "); + let type_str = pprust::ty_to_string(bounded_ty); // 8 = "for<> : ".len() - let used_width = lifetime_str.len() + type_str.len() + 8; - let bounds_str = bounds.iter() - .map(|ty_bound| ty_bound.rewrite(context, width - used_width, offset + used_width).unwrap()) - .collect::>() - .join(" + "); - - format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) - } else { - let type_str = pprust::ty_to_string(bounded_ty); + let used_width = lifetime_str.len() + type_str.len() + 8; + let bounds_str = bounds.iter() + .map(|ty_bound| { + ty_bound + .rewrite(context, + width - used_width, + offset + used_width) + .unwrap() + }) + .collect::>() + .join(" + "); + + format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) + } else { + let type_str = pprust::ty_to_string(bounded_ty); // 2 = ": ".len() - let used_width = type_str.len() + 2; - let bounds_str = bounds.iter() - .map(|ty_bound| ty_bound.rewrite(context, width - used_width, offset + used_width).unwrap()) - .collect::>() - .join(" + "); - - format!("{}: {}", type_str, bounds_str) - } + let used_width = type_str.len() + 2; + let bounds_str = bounds.iter() + .map(|ty_bound| { + ty_bound + .rewrite(context, + width - used_width, + offset + used_width) + .unwrap() + }) + .collect::>() + .join(" + "); + + format!("{}: {}", type_str, bounds_str) } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, - ref bounds, - ..}) => { - format!("{}: {}", + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, + ref bounds, + .. }) => { + format!("{}: {}", pprust::lifetime_to_string(lifetime), bounds.iter().map(pprust::lifetime_to_string) .collect::>().join(" + ")) - } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { - let ty_str = pprust::ty_to_string(ty); + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref path, ref ty, .. }) => { + let ty_str = pprust::ty_to_string(ty); // 3 = " = ".len() - let used_width = 3 + ty_str.len(); - let path_str = try_opt!(path.rewrite(context, + let used_width = 3 + ty_str.len(); + let path_str = try_opt!(path.rewrite(context, width - used_width, offset + used_width)); - format!("{} = {}", path_str, ty_str) - } - }) + format!("{} = {}", path_str, ty_str) + } + }) } } @@ -370,10 +382,10 @@ impl Rewrite for ast::TyParam { result.push_str(": "); let bounds = self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, width, offset).unwrap()) - .collect::>() - .join(" + "); + .iter() + .map(|ty_bound| ty_bound.rewrite(context, width, offset).unwrap()) + .collect::>() + .join(" + "); result.push_str(&bounds); } @@ -391,10 +403,10 @@ impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { if !self.bound_lifetimes.is_empty() { let lifetime_str = self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, width, offset).unwrap()) - .collect::>() - .join(", "); + .iter() + .map(|lt| lt.rewrite(context, width, offset).unwrap()) + .collect::>() + .join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); diff --git a/src/utils.rs b/src/utils.rs index d8acea40d2a..faa953ebea3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -97,11 +97,11 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { typaram.bounds .last() .map(|bound| { - match *bound { - ast::RegionTyParamBound(ref lt) => lt.span, - ast::TraitTyParamBound(ref prt, _) => prt.span, - } - }) + match *bound { + ast::RegionTyParamBound(ref lt) => lt.span, + ast::TraitTyParamBound(ref prt, _) => prt.span, + } + }) .unwrap_or(typaram.span) .hi } diff --git a/src/visitor.rs b/src/visitor.rs index 7e02d0f1d1f..1159116b010 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -289,8 +289,10 @@ impl<'a> FmtVisitor<'a> { true } else { let rewrite = attrs - .rewrite(&self.get_context(), self.config.max_width - self.block_indent, self.block_indent) - .unwrap(); + .rewrite(&self.get_context(), + self.config.max_width - self.block_indent, + self.block_indent) + .unwrap(); self.buffer.push_str(&rewrite); let last = attrs.last().unwrap(); self.last_pos = last.span.hi; diff --git a/tests/system.rs b/tests/system.rs index 10dc629c805..e77257663db 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -120,8 +120,8 @@ pub fn idempotent_check(filename: String) -> Result<(), HashMap HashMap { // Matches lines containing significant comments or whitespace. let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)").ok() - .expect("Failed creating pattern 2."); + .expect("Failed creating pattern 2."); reader.lines() .map(|line| line.ok().expect("Failed getting line.")) .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { - regex.captures_iter(&line) - .next() - .map(|capture| { - (capture.at(1).expect("Couldn't unwrap capture.").to_owned(), - capture.at(2).expect("Couldn't unwrap capture.").to_owned()) - }) - }) + regex.captures_iter(&line) + .next() + .map(|capture| { + (capture.at(1).expect("Couldn't unwrap capture.").to_owned(), + capture.at(2).expect("Couldn't unwrap capture.").to_owned()) + }) + }) .collect() } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index a0565167093..ec095ad8fcc 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -9,31 +9,30 @@ fn main() { b: WithType, // argument // ignored _| { - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) - }; + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) + }; let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - }; + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; let loooooooooooooong_name = |field| { // TODO(#27): format comments. - if field.node.attrs.len() > 0 { - field.node.attrs[0].span.lo - } else { - field.span.lo - } - }; + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }; let block_me = |field| { - if true_story() { - 1 - } else { - 2 - } - }; + if true_story() { + 1 + } else { + 2 + } + }; let unblock_me = |trivial| closure(); @@ -44,17 +43,17 @@ fn main() { }; let test = || { - do_something(); - do_something_else(); - }; + do_something(); + do_something_else(); + }; let arg_test = |big_argument_name, test123| { - looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() - }; + looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() + }; let arg_test = |big_argument_name, test123| { - looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() - }; + looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() + }; let simple_closure = move || -> () {}; diff --git a/tests/target/expr-visual-indent.rs b/tests/target/expr-visual-indent.rs index d74b5aae93c..f5b79d74fcb 100644 --- a/tests/target/expr-visual-indent.rs +++ b/tests/target/expr-visual-indent.rs @@ -4,6 +4,6 @@ fn matcher() { Some(while true { - test(); - }) + test(); + }) } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 9bfe51e0b26..d24d463c2c2 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -89,13 +89,13 @@ fn bar() { } syntactically_correct(loop { - sup('?'); - }, + sup('?'); + }, if cond { - 0 - } else { - 1 - }); + 0 + } else { + 1 + }); let third = ..10; let infi_range = ..; -- cgit 1.4.1-3-g733a5 From a53be867105394f09c33d929535d37bc6522ff8b Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:10:51 +0200 Subject: address mini offset bug in rewrite_match --- src/expr.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 710fb6f8703..353150197b1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -732,6 +732,7 @@ impl Rewrite for ast::Arm { // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() if context.config.max_width > line_start + comma.len() + 4 { + let inner_offset = line_start + 4; let budget = context.config.max_width - line_start - comma.len() - 4; if let Some(ref body_str) = body.rewrite(context, budget, -- cgit 1.4.1-3-g733a5 From 749a9689be022f2737820a87fe09d930907435a5 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 11 Sep 2015 00:52:57 +0200 Subject: Break chains that don't start with path expressions --- src/bin/rustfmt.rs | 5 +-- src/chains.rs | 103 +++++++++++++++++++++++++---------------------------- src/comment.rs | 1 - src/expr.rs | 12 ++----- src/lists.rs | 2 +- tests/system.rs | 3 +- 6 files changed, 58 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9f2387f5c2c..9913c68cdfa 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -82,7 +82,9 @@ fn main() { } fn print_usage>(reason: S) { - println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] ", reason.into()); + println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] \ + ", + reason.into()); } fn determine_params(args: I) -> Option<(Vec, WriteMode)> @@ -123,6 +125,5 @@ fn determine_params(args: I) -> Option<(Vec, WriteMode)> return None; } - Some((rustc_args, write_mode)) } diff --git a/src/chains.rs b/src/chains.rs index 23e669d08af..4f395df0487 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -9,7 +9,7 @@ // except according to those terms. use rewrite::{Rewrite, RewriteContext}; -use utils::{span_after, make_indent, extra_offset}; +use utils::{make_indent, extra_offset}; use expr::rewrite_call; use syntax::{ast, ptr}; @@ -26,66 +26,23 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, let indent = offset + context.config.tab_spaces; let max_width = try_opt!(context.config.max_width.checked_sub(indent)); - loop { - match expr.node { - ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { - // FIXME: a lot of duplication between this and the - // rewrite_method_call in expr.rs. - let new_span = mk_sp(expressions[0].span.hi, expr.span.hi); - let lo = span_after(new_span, "(", context.codemap); - let new_span = mk_sp(lo, expr.span.hi); - - let rewrite = rewrite_method_call(method_name.node, - types, - &expressions[1..], - new_span, - context, - max_width, - indent); - rewrites.push(try_opt!(rewrite)); - expr = &expressions[0]; - } - ast::Expr_::ExprField(ref subexpr, ref field) => { - expr = subexpr; - rewrites.push(format!(".{}", field.node)); - } - ast::Expr_::ExprTupField(ref subexpr, ref field) => { - expr = subexpr; - rewrites.push(format!(".{}", field.node)); - } - _ => break, - } + while let Some(pair) = pop_expr_chain(expr, orig_expr.span, context, max_width, indent) { + let (rewrite, parent_expr) = pair; + + rewrites.push(try_opt!(rewrite)); + expr = parent_expr; } let parent_rewrite = try_opt!(expr.rewrite(context, width, offset)); - // TODO: add exception for when rewrites.len() == 1 if rewrites.len() == 1 { let extra_offset = extra_offset(&parent_rewrite, offset); + let offset = offset + extra_offset; let max_width = try_opt!(width.checked_sub(extra_offset)); - // FIXME: massive duplication - let rerewrite = match orig_expr.node { - ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { - let new_span = mk_sp(expressions[0].span.hi, orig_expr.span.hi); - let lo = span_after(new_span, "(", context.codemap); - let new_span = mk_sp(lo, orig_expr.span.hi); - - rewrite_method_call(method_name.node, - types, - &expressions[1..], - new_span, - context, - max_width, - offset + extra_offset) - } - ast::Expr_::ExprField(_, ref field) => { - Some(format!(".{}", field.node)) - } - ast::Expr_::ExprTupField(_, ref field) => { - Some(format!(".{}", field.node)) - } - _ => unreachable!(), - }; + + let rerewrite = pop_expr_chain(orig_expr, orig_expr.span, context, max_width, offset) + .unwrap() + .0; return Some(format!("{}{}", parent_rewrite, try_opt!(rerewrite))); } @@ -103,6 +60,7 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, // Put the first link on the same line as parent, if it fits. let first_connector = if parent_rewrite.len() + rewrites[0].len() <= width && + is_continuable(expr) && !rewrites[0].contains('\n') || parent_rewrite.len() <= context.config.tab_spaces { "" @@ -113,6 +71,43 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, Some(format!("{}{}{}", parent_rewrite, first_connector, rewrites.join(&connector))) } +// Returns None when the expression is not a chainable. Otherwise, rewrites the +// outermost chain element and returns the remaining chain. +fn pop_expr_chain<'a>(expr: &'a ast::Expr, + span: Span, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option<(Option, &'a ast::Expr)> { + match expr.node { + ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { + Some((rewrite_method_call(method_name.node, + types, + expressions, + span, + context, + width, + offset), + &expressions[0])) + } + ast::Expr_::ExprField(ref subexpr, ref field) => { + Some((Some(format!(".{}", field.node)), subexpr)) + } + ast::Expr_::ExprTupField(ref subexpr, ref field) => { + Some((Some(format!(".{}", field.node)), subexpr)) + } + _ => None, + } +} + +// Determines we can continue formatting a given expression on the same line. +fn is_continuable(expr: &ast::Expr) -> bool { + match expr.node { + ast::Expr_::ExprPath(..) => true, + _ => false, + } +} + fn rewrite_method_call(method_name: ast::Ident, types: &[ptr::P], args: &[ptr::P], diff --git a/src/comment.rs b/src/comment.rs index ed06ff7e5b6..313510f02b7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -44,7 +44,6 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz .enumerate() .map(|(i, mut line)| { line = line.trim(); - // Drop old closer. if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { line = &line[..(line.len() - 2)]; diff --git a/src/expr.rs b/src/expr.rs index 353150197b1..69fea0e5927 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -40,15 +40,6 @@ impl Rewrite for ast::Expr { } } ast::Expr_::ExprCall(ref callee, ref args) => { - // // FIXME using byte lens instead of char lens (and probably all over the place too) - // // 2 is for parens - // let max_callee_width = try_opt!(width.checked_sub(2)); - // let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); - - // let new_span = mk_sp(callee.span.hi, self.span.hi); - // let lo = span_after(new_span, "(", context.codemap); - // let new_span = mk_sp(lo, self.span.hi); - rewrite_call(context, &**callee, args, self.span, width, offset) } ast::Expr_::ExprParen(ref subexpr) => { @@ -927,6 +918,9 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Greater), }; + let span_lo = span_after(span, "(", context.codemap); + let span = mk_sp(span_lo, span.hi); + let extra_offset = extra_offset(&callee_str, offset); // 2 is for parens. let remaining_width = match width.checked_sub(extra_offset + 2) { diff --git a/src/lists.rs b/src/lists.rs index b07b81bd672..0afee8f79ac 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -282,7 +282,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> None }; - // Post-comment + // Post-comment let next_start = match self.inner.peek() { Some(ref next_item) => (self.get_lo)(next_item), None => self.next_span_start, diff --git a/tests/system.rs b/tests/system.rs index e77257663db..9cfe9101986 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -152,7 +152,8 @@ fn read_significant_comments(file_name: &str) -> HashMap { let regex = regex::Regex::new(&pattern).ok().expect("Failed creating pattern 1."); // Matches lines containing significant comments or whitespace. - let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)").ok() + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") + .ok() .expect("Failed creating pattern 2."); reader.lines() -- cgit 1.4.1-3-g733a5 From abe8e7de990b88e2b3d7349bc1fc240b4eb49bad Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:13:37 +0200 Subject: Add tests for chain expressions --- src/chains.rs | 9 +++++---- src/comment.rs | 27 --------------------------- tests/source/chains.rs | 33 +++++++++++++++++++++++++++++++++ tests/system.rs | 3 ++- tests/target/chains.rs | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 32 deletions(-) create mode 100644 tests/source/chains.rs create mode 100644 tests/target/chains.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4f395df0487..e5d2a43840b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -34,8 +34,11 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, } let parent_rewrite = try_opt!(expr.rewrite(context, width, offset)); + let total_width = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len(); + let fits_single_line = total_width <= width && rewrites.iter().all(|s| !s.contains('\n')); - if rewrites.len() == 1 { + if rewrites.len() == 1 && !fits_single_line && + (is_continuable(expr) || parent_rewrite.len() <= context.config.tab_spaces) { let extra_offset = extra_offset(&parent_rewrite, offset); let offset = offset + extra_offset; let max_width = try_opt!(width.checked_sub(extra_offset)); @@ -47,9 +50,7 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, return Some(format!("{}{}", parent_rewrite, try_opt!(rerewrite))); } - let total_width = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len(); - - let connector = if total_width <= width && rewrites.iter().all(|s| !s.contains('\n')) { + let connector = if fits_single_line { String::new() } else { format!("\n{}", make_indent(indent)) diff --git a/src/comment.rs b/src/comment.rs index 313510f02b7..290fc62e15a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -145,18 +145,6 @@ pub fn find_comment_end(s: &str) -> Option { } } -#[test] -fn comment_end() { - assert_eq!(Some(6), find_comment_end("// hi\n")); - assert_eq!(Some(9), find_comment_end("/* sup */ ")); - assert_eq!(Some(9), find_comment_end("/*/**/ */ ")); - assert_eq!(Some(6), find_comment_end("/*/ */ weird!")); - assert_eq!(None, find_comment_end("/* hi /* test */")); - assert_eq!(None, find_comment_end("// hi /* test */")); - assert_eq!(Some(9), find_comment_end("// hi /*\n.")); -} - - /// Returns true if text contains any comment. pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment) @@ -173,21 +161,6 @@ pub fn uncommented(text: &str) -> String { .collect() } -#[test] -fn test_uncommented() { - assert_eq!(&uncommented("abc/*...*/"), "abc"); - assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); - assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); -} - -#[test] -fn test_contains_comment() { - assert_eq!(contains_comment("abc"), false); - assert_eq!(contains_comment("abc // qsdf"), true); - assert_eq!(contains_comment("abc /* kqsdf"), true); - assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); -} - struct CharClasses where T: Iterator, T::Item: RichChar diff --git a/tests/source/chains.rs b/tests/source/chains.rs new file mode 100644 index 00000000000..7e4bda0671e --- /dev/null +++ b/tests/source/chains.rs @@ -0,0 +1,33 @@ +// Test chain formatting. + +fn main() { + let a = b.c + .d + .1 + .foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + + x() + .y(|| match cond() { true => (), false => () }); + + loong_func() + .quux(move || if true { + 1 + } else { + 2 + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }).filter(some_mod::some_filter) +} diff --git a/tests/system.rs b/tests/system.rs index 9cfe9101986..fb877993daf 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -121,7 +121,8 @@ pub fn idempotent_check(filename: String) -> Result<(), HashMap (), + false => (), + } + }); + + loong_func() + .quux(move || { + if true { + 1 + } else { + 2 + } + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa + .map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) +} -- cgit 1.4.1-3-g733a5 From 8e471ece31abb7e329bffef977e1bd0c7d876b8c Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:14:09 +0200 Subject: Add some tests for match blocks --- src/chains.rs | 11 +++++++++++ src/comment.rs | 23 ++++++++--------------- tests/source/chains.rs | 9 +++++++++ tests/target/chains.rs | 8 ++++++++ 4 files changed, 36 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index e5d2a43840b..4eaf0f5acb5 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -8,6 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Formatting of chained expressions, i.e. expressions which are chained by +// dots: struct and enum field access and method calls. +// +// Instead of walking these subexpressions one-by-one, as is our usual strategy +// for expression formatting, we collect maximal sequences of these expressions +// and handle them simultaneously. +// +// Whenever possible, the entire chain is put on a single line. If that fails, +// we put each subexpression on a separate, much like the (default) function +// argument function argument strategy. + use rewrite::{Rewrite, RewriteContext}; use utils::{make_indent, extra_offset}; use expr::rewrite_call; diff --git a/src/comment.rs b/src/comment.rs index 290fc62e15a..d0eeba9a7c1 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -150,17 +150,6 @@ pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment) } -pub fn uncommented(text: &str) -> String { - CharClasses::new(text.chars()) - .filter_map(|(s, c)| { - match s { - CodeCharKind::Normal => Some(c), - CodeCharKind::Comment => None, - } - }) - .collect() -} - struct CharClasses where T: Iterator, T::Item: RichChar @@ -321,10 +310,14 @@ mod test { // This is probably intended to be a non-test fn, but it is not used. I'm // keeping it around unless it helps us test stuff. fn uncommented(text: &str) -> String { - CharClasses::new(text.chars()).filter_map(|(s, c)| match s { - CodeCharKind::Normal => Some(c), - CodeCharKind::Comment => None - }).collect() + CharClasses::new(text.chars()) + .filter_map(|(s, c)| { + match s { + CodeCharKind::Normal => Some(c), + CodeCharKind::Comment => None, + } + }) + .collect() } #[test] diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 7e4bda0671e..8282c3baa6b 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -21,6 +21,15 @@ fn main() { 2 }); + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + // Another case of write_list failing us. + *root.borrow_mut() = Some(&script_task); + }); + }); + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx .map(|x| x + 5) .map(|x| x / 2) diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 2ed91a2eb8e..daa60d09855 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -25,6 +25,14 @@ fn main() { } }); + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT.with(|root| { + // Another case of write_list failing us. + *root.borrow_mut() = Some(&script_task); + }); + }); + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) .map(|x| x / 2) .fold(0, |acc, x| acc + x); -- cgit 1.4.1-3-g733a5 From a9814149c93ddec27d38028667f67f75d469c3cc Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:14:54 +0200 Subject: Align dots in chained expressions --- src/chains.rs | 99 +++++++++++++++++++++++++------------------------- src/expr.rs | 12 +++--- src/items.rs | 41 +++++++++++---------- src/types.rs | 43 +++++++++++----------- src/utils.rs | 18 ++++----- src/visitor.rs | 9 ++--- tests/system.rs | 22 +++++------ tests/target/chains.rs | 22 +++++------ 8 files changed, 135 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4eaf0f5acb5..4556946649a 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -20,61 +20,58 @@ // argument function argument strategy. use rewrite::{Rewrite, RewriteContext}; -use utils::{make_indent, extra_offset}; +use utils::make_indent; use expr::rewrite_call; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; use syntax::print::pprust; -pub fn rewrite_chain(orig_expr: &ast::Expr, +pub fn rewrite_chain(mut expr: &ast::Expr, context: &RewriteContext, width: usize, offset: usize) -> Option { - let mut expr = orig_expr; - let mut rewrites = Vec::new(); - let indent = offset + context.config.tab_spaces; - let max_width = try_opt!(context.config.max_width.checked_sub(indent)); + let total_span = expr.span; + let mut subexpr_list = vec![expr]; - while let Some(pair) = pop_expr_chain(expr, orig_expr.span, context, max_width, indent) { - let (rewrite, parent_expr) = pair; - - rewrites.push(try_opt!(rewrite)); - expr = parent_expr; + while let Some(subexpr) = pop_expr_chain(expr) { + subexpr_list.push(subexpr); + expr = subexpr; } + let parent = subexpr_list.pop().unwrap(); let parent_rewrite = try_opt!(expr.rewrite(context, width, offset)); + let (extra_indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || + parent_rewrite.len() <= context.config.tab_spaces { + (parent_rewrite.len(), true) + } else { + (context.config.tab_spaces, false) + }; + let indent = offset + extra_indent; + + let max_width = try_opt!(width.checked_sub(extra_indent)); + let rewrites = try_opt!(subexpr_list.into_iter() + .rev() + .map(|e| { + rewrite_chain_expr(e, + total_span, + context, + max_width, + indent) + }) + .collect::>>()); + let total_width = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len(); let fits_single_line = total_width <= width && rewrites.iter().all(|s| !s.contains('\n')); - if rewrites.len() == 1 && !fits_single_line && - (is_continuable(expr) || parent_rewrite.len() <= context.config.tab_spaces) { - let extra_offset = extra_offset(&parent_rewrite, offset); - let offset = offset + extra_offset; - let max_width = try_opt!(width.checked_sub(extra_offset)); - - let rerewrite = pop_expr_chain(orig_expr, orig_expr.span, context, max_width, offset) - .unwrap() - .0; - - return Some(format!("{}{}", parent_rewrite, try_opt!(rerewrite))); - } - let connector = if fits_single_line { String::new() } else { format!("\n{}", make_indent(indent)) }; - // FIXME: don't do this. There's a more efficient way. VecDeque? - rewrites.reverse(); - - // Put the first link on the same line as parent, if it fits. - let first_connector = if parent_rewrite.len() + rewrites[0].len() <= width && - is_continuable(expr) && - !rewrites[0].contains('\n') || - parent_rewrite.len() <= context.config.tab_spaces { + let first_connector = if extend { "" } else { &connector[..] @@ -83,32 +80,36 @@ pub fn rewrite_chain(orig_expr: &ast::Expr, Some(format!("{}{}{}", parent_rewrite, first_connector, rewrites.join(&connector))) } -// Returns None when the expression is not a chainable. Otherwise, rewrites the -// outermost chain element and returns the remaining chain. -fn pop_expr_chain<'a>(expr: &'a ast::Expr, +fn pop_expr_chain<'a>(expr: &'a ast::Expr) -> Option<&'a ast::Expr> { + match expr.node { + ast::Expr_::ExprMethodCall(_, _, ref expressions) => { + Some(&expressions[0]) + } + ast::Expr_::ExprTupField(ref subexpr, _) | + ast::Expr_::ExprField(ref subexpr, _) => { + Some(subexpr) + } + _ => None, + } +} + +fn rewrite_chain_expr(expr: &ast::Expr, span: Span, context: &RewriteContext, width: usize, offset: usize) - -> Option<(Option, &'a ast::Expr)> { + -> Option { match expr.node { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { - Some((rewrite_method_call(method_name.node, - types, - expressions, - span, - context, - width, - offset), - &expressions[0])) + rewrite_method_call(method_name.node, types, expressions, span, context, width, offset) } - ast::Expr_::ExprField(ref subexpr, ref field) => { - Some((Some(format!(".{}", field.node)), subexpr)) + ast::Expr_::ExprField(_, ref field) => { + Some(format!(".{}", field.node)) } - ast::Expr_::ExprTupField(ref subexpr, ref field) => { - Some((Some(format!(".{}", field.node)), subexpr)) + ast::Expr_::ExprTupField(_, ref field) => { + Some(format!(".{}", field.node)) } - _ => None, + _ => unreachable!(), } } diff --git a/src/expr.rs b/src/expr.rs index 69fea0e5927..986b5d50a1f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1017,8 +1017,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }; let field_iter = fields.into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); let inner_context = &RewriteContext { block_indent: indent, ..*context }; @@ -1030,8 +1030,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, StructLitField::Regular(ref field) => field.span.lo, StructLitField::Base(ref expr) => { let last_field_hi = fields.last() - .map_or(span.lo, - |field| field.span.hi); + .map_or(span.lo, + |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); @@ -1104,8 +1104,8 @@ fn rewrite_field(context: &RewriteContext, -> Option { let name = &field.ident.node.to_string(); let overhead = name.len() + 2; - let expr = - field.expr.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); + let expr = field.expr + .rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); expr.map(|s| format!("{}: {}", name, s)) } diff --git a/src/items.rs b/src/items.rs index ef8ad37b126..a2e562d9d26 100644 --- a/src/items.rs +++ b/src/items.rs @@ -332,13 +332,14 @@ impl<'a> FmtVisitor<'a> { // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. - let min_args = explicit_self - .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args)) - .map(|self_str| { - arg_item_strs[0] = self_str; - 2 - }) - .unwrap_or(1); + let min_args = explicit_self.and_then(|explicit_self| { + rewrite_explicit_self(explicit_self, args) + }) + .map(|self_str| { + arg_item_strs[0] = self_str; + 2 + }) + .unwrap_or(1); // Comments between args let mut arg_items = Vec::new(); @@ -761,9 +762,11 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent + self.config.tab_spaces; let mut attr_str = field.node - .attrs - .rewrite(&self.get_context(), self.config.max_width - indent, indent) - .unwrap(); + .attrs + .rewrite(&self.get_context(), + self.config.max_width - indent, + indent) + .unwrap(); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&make_indent(indent)); @@ -804,18 +807,18 @@ impl<'a> FmtVisitor<'a> { // FIXME: don't unwrap let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset).unwrap()); let ty_strs = tys.iter() - .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); + .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); // Extract comments between generics. let lt_spans = lifetimes.iter() - .map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - codemap::mk_sp(l.lifetime.span.lo, hi) - }); + .map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + codemap::mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(self.codemap, diff --git a/src/types.rs b/src/types.rs index 9f3cc17e4c7..83e92ff314b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -279,22 +279,24 @@ impl Rewrite for ast::WherePredicate { .. }) => { if !bound_lifetimes.is_empty() { let lifetime_str = bound_lifetimes.iter() - .map(|lt| lt.rewrite(context, width, offset).unwrap()) - .collect::>() - .join(", "); + .map(|lt| { + lt.rewrite(context, width, offset) + .unwrap() + }) + .collect::>() + .join(", "); let type_str = pprust::ty_to_string(bounded_ty); // 8 = "for<> : ".len() let used_width = lifetime_str.len() + type_str.len() + 8; let bounds_str = bounds.iter() - .map(|ty_bound| { - ty_bound - .rewrite(context, - width - used_width, - offset + used_width) - .unwrap() - }) - .collect::>() - .join(" + "); + .map(|ty_bound| { + ty_bound.rewrite(context, + width - used_width, + offset + used_width) + .unwrap() + }) + .collect::>() + .join(" + "); format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { @@ -302,15 +304,14 @@ impl Rewrite for ast::WherePredicate { // 2 = ": ".len() let used_width = type_str.len() + 2; let bounds_str = bounds.iter() - .map(|ty_bound| { - ty_bound - .rewrite(context, - width - used_width, - offset + used_width) - .unwrap() - }) - .collect::>() - .join(" + "); + .map(|ty_bound| { + ty_bound.rewrite(context, + width - used_width, + offset + used_width) + .unwrap() + }) + .collect::>() + .join(" + "); format!("{}: {}", type_str, bounds_str) } diff --git a/src/utils.rs b/src/utils.rs index faa953ebea3..cb1dd718375 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -95,15 +95,15 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { #[inline] pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { typaram.bounds - .last() - .map(|bound| { - match *bound { - ast::RegionTyParamBound(ref lt) => lt.span, - ast::TraitTyParamBound(ref prt, _) => prt.span, - } - }) - .unwrap_or(typaram.span) - .hi + .last() + .map(|bound| { + match *bound { + ast::RegionTyParamBound(ref lt) => lt.span, + ast::TraitTyParamBound(ref prt, _) => prt.span, + } + }) + .unwrap_or(typaram.span) + .hi } #[inline] diff --git a/src/visitor.rs b/src/visitor.rs index 1159116b010..54ada1b7455 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -288,11 +288,10 @@ impl<'a> FmtVisitor<'a> { if utils::contains_skip(attrs) { true } else { - let rewrite = attrs - .rewrite(&self.get_context(), - self.config.max_width - self.block_indent, - self.block_indent) - .unwrap(); + let rewrite = attrs.rewrite(&self.get_context(), + self.config.max_width - self.block_indent, + self.block_indent) + .unwrap(); self.buffer.push_str(&rewrite); let last = attrs.last().unwrap(); self.last_pos = last.span.hi; diff --git a/tests/system.rs b/tests/system.rs index ea98d94f412..4db15dbcfd1 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -162,17 +162,17 @@ fn read_significant_comments(file_name: &str) -> HashMap { .expect("Failed creating pattern 2."); reader.lines() - .map(|line| line.ok().expect("Failed getting line.")) - .take_while(|line| line_regex.is_match(&line)) - .filter_map(|line| { - regex.captures_iter(&line) - .next() - .map(|capture| { - (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), - capture.at(2).expect("Couldn\'t unwrap capture.").to_owned()) - }) - }) - .collect() + .map(|line| line.ok().expect("Failed getting line.")) + .take_while(|line| line_regex.is_match(&line)) + .filter_map(|line| { + regex.captures_iter(&line) + .next() + .map(|capture| { + (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), + capture.at(2).expect("Couldn\'t unwrap capture.").to_owned()) + }) + }) + .collect() } // Compare output to input. diff --git a/tests/target/chains.rs b/tests/target/chains.rs index daa60d09855..282dc58b492 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -6,8 +6,8 @@ fn main() { bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); + .ddddddddddddddddddddddddddd + .eeeeeeee(); x().y(|| { match cond() { @@ -34,13 +34,13 @@ fn main() { }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa - .map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) + .map(|x| x / 2) + .fold(0, + |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) } -- cgit 1.4.1-3-g733a5 From 48d17f54d34c5457e88ef7ffa234601c6e342a70 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:15:37 +0200 Subject: Rebase onto master --- src/expr.rs | 28 +++------ src/lists.rs | 154 +++++++++++++++++++++++++------------------------- tests/target/match.rs | 2 +- 3 files changed, 86 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 986b5d50a1f..4da191e8bf8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -723,11 +723,8 @@ impl Rewrite for ast::Arm { // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() if context.config.max_width > line_start + comma.len() + 4 { - let inner_offset = line_start + 4; let budget = context.config.max_width - line_start - comma.len() - 4; - if let Some(ref body_str) = body.rewrite(context, - budget, - line_start + 4) { + if let Some(ref body_str) = body.rewrite(context, budget, line_start + 4) { if first_line_width(body_str) <= budget { return Some(format!("{}{} => {}{}", attr_str.trim_left(), @@ -928,8 +925,12 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Greater), }; let offset = offset + extra_offset + 1; - let inner_indent = expr_indent(context, offset); - let inner_context = context.overflow_context(inner_indent - context.block_indent); + let block_indent = if args.len() == 1 { + context.block_indent + } else { + offset + }; + let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; let items = itemize_list(context.codemap, args.iter(), @@ -953,21 +954,6 @@ fn rewrite_call_inner(context: &RewriteContext, Ok(format!("{}({})", callee_str, list_str)) } -macro_rules! block_indent_helper { - ($name:ident, $option:ident) => ( - fn $name(context: &RewriteContext, offset: usize) -> usize { - match context.config.$option { - BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Tabbed => context.block_indent + context.config.tab_spaces, - BlockIndentStyle::Visual => offset, - } - } - ); -} - -block_indent_helper!(expr_indent, expr_indent_style); -block_indent_helper!(closure_indent, closure_indent_style); - fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, diff --git a/src/lists.rs b/src/lists.rs index 0afee8f79ac..3435bd8170b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -269,18 +269,21 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> fn next(&mut self) -> Option { let white_space: &[_] = &[' ', '\t']; - self.inner.next().map(|item| { - let mut new_lines = false; - // Pre-comment - let pre_snippet = self.codemap.span_to_snippet(codemap::mk_sp(self.prev_span_end, - (self.get_lo)(&item))) - .unwrap(); - let trimmed_pre_snippet = pre_snippet.trim(); - let pre_comment = if !trimmed_pre_snippet.is_empty() { - Some(trimmed_pre_snippet.to_owned()) - } else { - None - }; + self.inner + .next() + .map(|item| { + let mut new_lines = false; + // Pre-comment + let pre_snippet = self.codemap + .span_to_snippet(codemap::mk_sp(self.prev_span_end, + (self.get_lo)(&item))) + .unwrap(); + let trimmed_pre_snippet = pre_snippet.trim(); + let pre_comment = if !trimmed_pre_snippet.is_empty() { + Some(trimmed_pre_snippet.to_owned()) + } else { + None + }; // Post-comment let next_start = match self.inner.peek() { @@ -300,76 +303,75 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> match (block_open_index, newline_index) { // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => { - separator_index + 1 - } - // Block-style post-comment before the separator. - (Some(i), None) => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) + // Comment belongs to next item. + (Some(i), None) if i > separator_index => { + separator_index + 1 + } + // Block-style post-comment before the separator. + (Some(i), None) => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Potential *single* line comment. + (_, Some(j)) => j + 1, + _ => post_snippet.len(), } - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) - } - // Potential *single* line comment. - (_, Some(j)) => j + 1, - _ => post_snippet.len() } - }, - None => { - post_snippet.find_uncommented(self.terminator) - .unwrap_or(post_snippet.len()) - } - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end-1..]; - let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet.find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; + None => { + post_snippet.find_uncommented(self.terminator).unwrap_or(post_snippet.len()) + } + }; + + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end-1..]; + let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet.find(|c: char| !c.is_whitespace()) + .unwrap_or(test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; + } } - } - // Cleanup post-comment: strip separators and whitespace. - self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let post_snippet = post_snippet[..comment_end].trim(); - let post_snippet_trimmed = if post_snippet.starts_with(',') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(",") { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { - post_snippet - }; + let post_snippet_trimmed = if post_snippet.starts_with(',') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.ends_with(",") { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; - - ListItem { - pre_comment: pre_comment, - item: (self.get_item_string)(&item), - post_comment: post_comment, - new_lines: new_lines, - } - }) + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + }; + + ListItem { + pre_comment: pre_comment, + item: (self.get_item_string)(&item), + post_comment: post_comment, + new_lines: new_lines, + } + }) } } diff --git a/tests/target/match.rs b/tests/target/match.rs index eab8c604084..5cfbb5a7072 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -57,7 +57,7 @@ fn foo() { // Test that a match on an overflow line is laid out properly. fn main() { let sub_span = - match self.span.sub_span_after_keywooooooooooooooooooooord(use_item.span, keywords::As) { + match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { Some(sub_span) => Some(sub_span), None => sub_span, }; -- cgit 1.4.1-3-g733a5 From 03c660633fbac0492f891aed6c47731be90f23ca Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 9 Sep 2015 23:17:31 +0200 Subject: Refine chain breaking heuristics Don't make a single line chain when it is was multi line in the source; allow overflow of the last chain element onto the next lines without breaking the chain. --- src/chains.rs | 89 ++++++++++++---- src/config.rs | 15 ++- src/expr.rs | 23 +++-- src/items.rs | 22 ++-- src/lib.rs | 1 + src/lists.rs | 196 ++++++++++++++++++------------------ src/types.rs | 25 ++--- tests/config/small_tabs.toml | 4 +- tests/source/chains-no-overflow.rs | 38 +++++++ tests/source/chains.rs | 9 +- tests/source/expr-no-hints.rs | 8 ++ tests/source/expr-visual-indent.rs | 9 -- tests/system.rs | 10 +- tests/target/chains-no-overflow.rs | 45 +++++++++ tests/target/chains-no-overlow-2.rs | 16 +++ tests/target/chains.rs | 38 +++---- tests/target/expr-no-hints.rs | 6 ++ tests/target/expr-visual-indent.rs | 9 -- 18 files changed, 356 insertions(+), 207 deletions(-) create mode 100644 tests/source/chains-no-overflow.rs create mode 100644 tests/source/expr-no-hints.rs delete mode 100644 tests/source/expr-visual-indent.rs create mode 100644 tests/target/chains-no-overflow.rs create mode 100644 tests/target/chains-no-overlow-2.rs create mode 100644 tests/target/expr-no-hints.rs delete mode 100644 tests/target/expr-visual-indent.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4556946649a..bd9f302824b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -20,7 +20,7 @@ // argument function argument strategy. use rewrite::{Rewrite, RewriteContext}; -use utils::make_indent; +use utils::{first_line_width, make_indent}; use expr::rewrite_call; use syntax::{ast, ptr}; @@ -51,19 +51,67 @@ pub fn rewrite_chain(mut expr: &ast::Expr, let indent = offset + extra_indent; let max_width = try_opt!(width.checked_sub(extra_indent)); - let rewrites = try_opt!(subexpr_list.into_iter() - .rev() - .map(|e| { - rewrite_chain_expr(e, - total_span, - context, - max_width, - indent) - }) - .collect::>>()); - - let total_width = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len(); - let fits_single_line = total_width <= width && rewrites.iter().all(|s| !s.contains('\n')); + let mut rewrites = try_opt!(subexpr_list.iter() + .rev() + .map(|e| { + rewrite_chain_expr(e, + total_span, + context, + max_width, + indent) + }) + .collect::>>()); + + // Total of all items excluding the last. + let almost_total = rewrites.split_last() + .unwrap() + .1 + .iter() + .fold(0, |a, b| a + first_line_width(b)) + + parent_rewrite.len(); + let total_width = almost_total + first_line_width(rewrites.last().unwrap()); + let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { + // Look at the source code. Unless all chain elements start on the same + // line, we won't consider putting them on a single line either. + let first_line_no = context.codemap.lookup_char_pos(subexpr_list[0].span.lo).line; + + subexpr_list[1..] + .iter() + .any(|ex| context.codemap.lookup_char_pos(ex.span.hi).line != first_line_no) + } else { + false + }; + + let fits_single_line = !veto_single_line && + match subexpr_list[0].node { + ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) + if context.config.chains_overflow_last => { + let (last, init) = rewrites.split_last_mut().unwrap(); + + if init.iter().all(|s| !s.contains('\n')) && total_width <= width { + let last_rewrite = width.checked_sub(almost_total) + .and_then(|inner_width| { + rewrite_method_call(method_name.node, + types, + expressions, + total_span, + context, + inner_width, + offset + almost_total) + }); + match last_rewrite { + Some(mut string) => { + ::std::mem::swap(&mut string, last); + true + } + None => false, + } + } else { + false + } + } + _ => total_width <= width && rewrites.iter().all(|s| !s.contains('\n')), + }; let connector = if fits_single_line { String::new() @@ -101,7 +149,11 @@ fn rewrite_chain_expr(expr: &ast::Expr, -> Option { match expr.node { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { - rewrite_method_call(method_name.node, types, expressions, span, context, width, offset) + let inner = &RewriteContext { + block_indent: offset, + ..*context + }; + rewrite_method_call(method_name.node, types, expressions, span, inner, width, offset) } ast::Expr_::ExprField(_, ref field) => { Some(format!(".{}", field.node)) @@ -137,10 +189,7 @@ fn rewrite_method_call(method_name: ast::Ident, }; let callee_str = format!(".{}{}", method_name, type_str); - let inner_context = &RewriteContext { - block_indent: offset, - ..*context - }; + let span = mk_sp(args[0].span.hi, span.hi); - rewrite_call(inner_context, &callee_str, args, span, width, offset) + rewrite_call(context, &callee_str, &args[1..], span, width, offset) } diff --git a/src/config.rs b/src/config.rs index 95994531950..d45f184051f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -133,8 +133,8 @@ create_config! { fn_args_density: Density, fn_args_layout: StructLitStyle, fn_arg_indent: BlockIndentStyle, - where_density: Density, // Should we at least try to put the where clause on the same line as - // the rest of the function decl? + where_density: Density, // Should we at least try to put the where clause on + // the same line as the rest of the function decl? where_indent: BlockIndentStyle, // Visual will be treated like Tabbed where_layout: ListTactic, where_pred_indent: BlockIndentStyle, @@ -147,14 +147,14 @@ create_config! { report_todo: ReportTactic, report_fixme: ReportTactic, reorder_imports: bool, // Alphabetically, case sensitive. - expr_indent_style: BlockIndentStyle, - closure_indent_style: BlockIndentStyle, single_line_if_else: bool, format_strings: bool, + chains_overflow_last: bool, + take_source_hints: bool, // Retain some formatting characteristics from + // the source code. } impl Default for Config { - fn default() -> Config { Config { max_width: 100, @@ -181,11 +181,10 @@ impl Default for Config { report_todo: ReportTactic::Always, report_fixme: ReportTactic::Never, reorder_imports: false, - expr_indent_style: BlockIndentStyle::Tabbed, - closure_indent_style: BlockIndentStyle::Visual, single_line_if_else: false, format_strings: true, + chains_overflow_last: true, + take_source_hints: true, } } - } diff --git a/src/expr.rs b/src/expr.rs index 4da191e8bf8..98b93a5faa7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -40,6 +40,12 @@ impl Rewrite for ast::Expr { } } ast::Expr_::ExprCall(ref callee, ref args) => { + // FIXME using byte lens instead of char lens (and probably all over the place too) + // 2 is for parens + let max_callee_width = try_opt!(width.checked_sub(2)); + let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); + let span = mk_sp(callee.span.hi, self.span.hi); + rewrite_call(context, &**callee, args, self.span, width, offset) } ast::Expr_::ExprParen(ref subexpr) => { @@ -284,8 +290,10 @@ impl Rewrite for ast::Block { }; if is_simple_block(self, context.codemap) && prefix.len() < width { - let body = - self.expr.as_ref().unwrap().rewrite(context, width - prefix.len(), offset); + let body = self.expr + .as_ref() + .unwrap() + .rewrite(context, width - prefix.len(), offset); if let Some(ref expr_str) = body { let result = format!("{}{{ {} }}", prefix, expr_str); if result.len() <= width && !result.contains('\n') { @@ -677,15 +685,13 @@ impl Rewrite for ast::Arm { total_width += (pat_strs.len() - 1) * 3; let mut vertical = total_width > pat_budget || pat_strs.iter().any(|p| p.contains('\n')); - if !vertical { + if !vertical && context.config.take_source_hints { // If the patterns were previously stacked, keep them stacked. - // FIXME should be an option. let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi); let pat_str = context.snippet(pat_span); vertical = pat_str.find('\n').is_some(); } - let pats_width = if vertical { pat_strs[pat_strs.len() - 1].len() } else { @@ -1015,9 +1021,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => field.span.lo, StructLitField::Base(ref expr) => { - let last_field_hi = fields.last() - .map_or(span.lo, - |field| field.span.hi); + let last_field_hi = fields.last().map_or(span.lo, + |field| { + field.span.hi + }); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); diff --git a/src/items.rs b/src/items.rs index a2e562d9d26..2547e8f5dd5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -512,8 +512,9 @@ impl<'a> FmtVisitor<'a> { |arg| arg.ty.span.hi, |arg| { // FIXME silly width, indent - arg.ty.rewrite(&self.get_context(), 1000, 0) - .unwrap() + arg.ty + .rewrite(&self.get_context(), 1000, 0) + .unwrap() }, span_after(field.span, "(", self.codemap), next_span_start); @@ -810,15 +811,14 @@ impl<'a> FmtVisitor<'a> { .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); // Extract comments between generics. - let lt_spans = lifetimes.iter() - .map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - codemap::mk_sp(l.lifetime.span.lo, hi) - }); + let lt_spans = lifetimes.iter().map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + codemap::mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(self.codemap, diff --git a/src/lib.rs b/src/lib.rs index 6993d3044d3..3f8900d6713 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ #![feature(rustc_private)] #![feature(custom_attribute)] +#![feature(slice_splits)] #![allow(unused_attributes)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth diff --git a/src/lists.rs b/src/lists.rs index 3435bd8170b..678c84c199a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -269,109 +269,107 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> fn next(&mut self) -> Option { let white_space: &[_] = &[' ', '\t']; - self.inner - .next() - .map(|item| { - let mut new_lines = false; - // Pre-comment - let pre_snippet = self.codemap - .span_to_snippet(codemap::mk_sp(self.prev_span_end, - (self.get_lo)(&item))) - .unwrap(); - let trimmed_pre_snippet = pre_snippet.trim(); - let pre_comment = if !trimmed_pre_snippet.is_empty() { - Some(trimmed_pre_snippet.to_owned()) - } else { - None - }; - - // Post-comment - let next_start = match self.inner.peek() { - Some(ref next_item) => (self.get_lo)(next_item), - None => self.next_span_start, - }; - let post_snippet = self.codemap - .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), - next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let block_open_index = post_snippet.find("/*"); - let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(",").unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => { - separator_index + 1 - } - // Block-style post-comment before the separator. - (Some(i), None) => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) - } - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) - } - // Potential *single* line comment. - (_, Some(j)) => j + 1, - _ => post_snippet.len(), + self.inner.next().map(|item| { + let mut new_lines = false; + // Pre-comment + let pre_snippet = self.codemap + .span_to_snippet(codemap::mk_sp(self.prev_span_end, + (self.get_lo)(&item))) + .unwrap(); + let trimmed_pre_snippet = pre_snippet.trim(); + let pre_comment = if !trimmed_pre_snippet.is_empty() { + Some(trimmed_pre_snippet.to_owned()) + } else { + None + }; + + // Post-comment + let next_start = match self.inner.peek() { + Some(ref next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.codemap + .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), + next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let block_open_index = post_snippet.find("/*"); + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(",").unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => { + separator_index + 1 } - } - None => { - post_snippet.find_uncommented(self.terminator).unwrap_or(post_snippet.len()) - } - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end-1..]; - let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet.find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; + // Block-style post-comment before the separator. + (Some(i), None) => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Potential *single* line comment. + (_, Some(j)) => j + 1, + _ => post_snippet.len(), } } - - // Cleanup post-comment: strip separators and whitespace. - self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); - - let post_snippet_trimmed = if post_snippet.starts_with(',') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(",") { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { - post_snippet - }; - - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; - - ListItem { - pre_comment: pre_comment, - item: (self.get_item_string)(&item), - post_comment: post_comment, - new_lines: new_lines, + None => { + post_snippet.find_uncommented(self.terminator).unwrap_or(post_snippet.len()) + } + }; + + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end-1..]; + let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet.find(|c: char| !c.is_whitespace()) + .unwrap_or(test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; } - }) + } + + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let post_snippet = post_snippet[..comment_end].trim(); + + let post_snippet_trimmed = if post_snippet.starts_with(',') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.ends_with(",") { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; + + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + }; + + ListItem { + pre_comment: pre_comment, + item: (self.get_item_string)(&item), + post_comment: post_comment, + new_lines: new_lines, + } + }) } } diff --git a/src/types.rs b/src/types.rs index 83e92ff314b..e0f3140d4d9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -130,16 +130,16 @@ impl<'a> Rewrite for SegmentParam<'a> { // FIXME doesn't always use width, offset fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { Some(match *self { - SegmentParam::LifeTime(ref lt) => { - pprust::lifetime_to_string(lt) - } - SegmentParam::Type(ref ty) => { - try_opt!(ty.rewrite(context, width, offset)) - } - SegmentParam::Binding(ref binding) => { - format!("{} = {}", binding.ident, try_opt!(binding.ty.rewrite(context, width, offset))) - } - }) + SegmentParam::LifeTime(ref lt) => { + pprust::lifetime_to_string(lt) + } + SegmentParam::Type(ref ty) => { + try_opt!(ty.rewrite(context, width, offset)) + } + SegmentParam::Binding(ref binding) => { + format!("{} = {}", binding.ident, try_opt!(binding.ty.rewrite(context, width, offset))) + } + }) } } @@ -368,8 +368,9 @@ impl Rewrite for ast::TyParamBound { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { - let strs: Vec<_> = - self.iter().map(|b| b.rewrite(context, width, offset).unwrap()).collect(); + let strs: Vec<_> = self.iter() + .map(|b| b.rewrite(context, width, offset).unwrap()) + .collect(); Some(strs.join(" + ")) } } diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index c5122b760a0..754cde57cd9 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -21,7 +21,7 @@ enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = false -expr_indent_style = "Tabbed" -closure_indent_style = "Visual" single_line_if_else = false format_strings = true +chains_overflow_last = true +take_source_hints = true diff --git a/tests/source/chains-no-overflow.rs b/tests/source/chains-no-overflow.rs new file mode 100644 index 00000000000..fa2c66524fc --- /dev/null +++ b/tests/source/chains-no-overflow.rs @@ -0,0 +1,38 @@ +// rustfmt-chains_overflow_last: false +// Test chain formatting without overflowing the last item. + +fn main() { + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + + x() + .y(|| match cond() { true => (), false => () }); + + loong_func() + .quux(move || if true { + 1 + } else { + 2 + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + // Another case of write_list failing us. + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }).filter(some_mod::some_filter) +} diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 8282c3baa6b..d2f11f1dcbe 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,10 +1,10 @@ // Test chain formatting. fn main() { - let a = b.c - .d - .1 - .foo(|x| x + 1); + // Don't put chains on a single list if it wasn't so in source. + let a = b .c + .d.1 + .foo(|x| x + 1); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc .ddddddddddddddddddddddddddd(); @@ -25,7 +25,6 @@ fn main() { { SCRIPT_TASK_ROOT .with(|root| { - // Another case of write_list failing us. *root.borrow_mut() = Some(&script_task); }); }); diff --git a/tests/source/expr-no-hints.rs b/tests/source/expr-no-hints.rs new file mode 100644 index 00000000000..7329a742bac --- /dev/null +++ b/tests/source/expr-no-hints.rs @@ -0,0 +1,8 @@ +// rustfmt-take_source_hints: false +// We know best! + +fn main() { + a.b + .c + .d(); +} diff --git a/tests/source/expr-visual-indent.rs b/tests/source/expr-visual-indent.rs deleted file mode 100644 index 3d7c1b92be8..00000000000 --- a/tests/source/expr-visual-indent.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-expr_indent_style: Visual - -// Visual level block indentation. - -fn matcher() { - Some(while true { - test(); - }) -} \ No newline at end of file diff --git a/tests/system.rs b/tests/system.rs index 4db15dbcfd1..d0b6ae78faa 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -165,12 +165,10 @@ fn read_significant_comments(file_name: &str) -> HashMap { .map(|line| line.ok().expect("Failed getting line.")) .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { - regex.captures_iter(&line) - .next() - .map(|capture| { - (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), - capture.at(2).expect("Couldn\'t unwrap capture.").to_owned()) - }) + regex.captures_iter(&line).next().map(|capture| { + (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), + capture.at(2).expect("Couldn\'t unwrap capture.").to_owned()) + }) }) .collect() } diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs new file mode 100644 index 00000000000..b4fdb9f99ce --- /dev/null +++ b/tests/target/chains-no-overflow.rs @@ -0,0 +1,45 @@ +// rustfmt-chains_overflow_last: false +// Test chain formatting without overflowing the last item. + +fn main() { + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd + .eeeeeeee(); + + x().y(|| { + match cond() { + true => (), + false => (), + } + }); + + loong_func() + .quux(move || { + if true { + 1 + } else { + 2 + } + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT.with(|root| { + // Another case of write_list failing us. + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) + .map(|x| x / 2) + .fold(0, + |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) +} diff --git a/tests/target/chains-no-overlow-2.rs b/tests/target/chains-no-overlow-2.rs new file mode 100644 index 00000000000..d795fa2f961 --- /dev/null +++ b/tests/target/chains-no-overlow-2.rs @@ -0,0 +1,16 @@ +// rustfmt-chains_overflow_last: false + +fn main() { + reader.lines() + .map(|line| line.ok().expect("Failed getting line.")) + .take_while(|line| line_regex.is_match(&line)) + .filter_map(|line| { + regex.captures_iter(&line) + .next() + .map(|capture| { + (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), + capture.at(2).expect("Couldn\'t unwrap capture.").to_owned()) + }) + }) + .collect(); +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 282dc58b492..e49233e22a2 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,7 +1,11 @@ // Test chain formatting. fn main() { - let a = b.c.d.1.foo(|x| x + 1); + // Don't put chains on a single list if it wasn't so in source. + let a = b.c + .d + .1 + .foo(|x| x + 1); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); @@ -10,27 +14,25 @@ fn main() { .eeeeeeee(); x().y(|| { - match cond() { - true => (), - false => (), - } - }); - - loong_func() - .quux(move || { - if true { - 1 - } else { - 2 - } - }); + match cond() { + true => (), + false => (), + } + }); + + loong_func().quux(move || { + if true { + 1 + } else { + 2 + } + }); fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { - // Another case of write_list failing us. - *root.borrow_mut() = Some(&script_task); - }); + *root.borrow_mut() = Some(&script_task); + }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) diff --git a/tests/target/expr-no-hints.rs b/tests/target/expr-no-hints.rs new file mode 100644 index 00000000000..62dd64c28a6 --- /dev/null +++ b/tests/target/expr-no-hints.rs @@ -0,0 +1,6 @@ +// rustfmt-take_source_hints: false +// We know best! + +fn main() { + a.b.c.d(); +} diff --git a/tests/target/expr-visual-indent.rs b/tests/target/expr-visual-indent.rs deleted file mode 100644 index f5b79d74fcb..00000000000 --- a/tests/target/expr-visual-indent.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-expr_indent_style: Visual - -// Visual level block indentation. - -fn matcher() { - Some(while true { - test(); - }) -} -- cgit 1.4.1-3-g733a5 From 7f576b06022357672eb24d6103673f982a6ba817 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 11 Sep 2015 00:53:21 +0200 Subject: General cleanup after rebase --- src/comment.rs | 75 +++++++++++++++++++------------------- src/expr.rs | 57 +++++++++++------------------ src/imports.rs | 8 ++-- src/items.rs | 11 +++--- src/utils.rs | 17 ++++----- tests/source/chains-no-overflow.rs | 5 +-- tests/source/chains.rs | 4 +- tests/source/string-lit.rs | 2 +- tests/system.rs | 24 ++++++------ tests/target/chains-no-overflow.rs | 4 +- tests/target/chains.rs | 4 +- tests/target/closure.rs | 8 ++-- tests/target/string-lit.rs | 2 +- 13 files changed, 105 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d0eeba9a7c1..ff7558131d2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -41,43 +41,44 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz let line_breaks = s.chars().filter(|&c| c == '\n').count(); let (_, mut s) = s.lines() - .enumerate() - .map(|(i, mut line)| { - line = line.trim(); - // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = &line[..(line.len() - 2)]; - } - - line.trim_right() - }) - .map(left_trim_comment_line) - .map(|line| { - if line_breaks == 0 { - line.trim_left() - } else { - line - } - }) - .fold((true, opener.to_owned()), |(first, mut acc), line| { - if !first { - acc.push('\n'); - acc.push_str(&indent_str); - acc.push_str(line_start); - } - - if line.len() > max_chars { - acc.push_str(&rewrite_string(line, &fmt)); - } else { - if line.len() == 0 { - acc.pop(); // Remove space if this is an empty comment. - } else { - acc.push_str(line); - } - } - - (false, acc) - }); + .enumerate() + .map(|(i, mut line)| { + line = line.trim(); + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = &line[..(line.len() - 2)]; + } + + line.trim_right() + }) + .map(left_trim_comment_line) + .map(|line| { + if line_breaks == 0 { + line.trim_left() + } else { + line + } + }) + .fold((true, opener.to_owned()), + |(first, mut acc), line| { + if !first { + acc.push('\n'); + acc.push_str(&indent_str); + acc.push_str(line_start); + } + + if line.len() > max_chars { + acc.push_str(&rewrite_string(line, &fmt)); + } else { + if line.len() == 0 { + acc.pop(); // Remove space if this is an empty comment. + } else { + acc.push_str(line); + } + } + + (false, acc) + }); s.push_str(closer); diff --git a/src/expr.rs b/src/expr.rs index 98b93a5faa7..c7dad3d2ccf 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -18,7 +18,7 @@ use StructLitStyle; use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width, wrap_str, binary_search}; use visitor::FmtVisitor; -use config::{BlockIndentStyle, MultilineStyle}; +use config::MultilineStyle; use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; @@ -40,12 +40,6 @@ impl Rewrite for ast::Expr { } } ast::Expr_::ExprCall(ref callee, ref args) => { - // FIXME using byte lens instead of char lens (and probably all over the place too) - // 2 is for parens - let max_callee_width = try_opt!(width.checked_sub(2)); - let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset)); - let span = mk_sp(callee.span.hi, self.span.hi); - rewrite_call(context, &**callee, args, self.span, width, offset) } ast::Expr_::ExprParen(ref subexpr) => { @@ -214,8 +208,6 @@ fn rewrite_closure(capture: ast::CaptureClause, prefix.push_str(&ret_str); } - let closure_indent = closure_indent(context, offset); - // Try to format closure body as a single line expression without braces. if is_simple_block(body, context.codemap) && !prefix.contains('\n') { let (spacer, closer) = if ret_str.is_empty() { @@ -246,17 +238,16 @@ fn rewrite_closure(capture: ast::CaptureClause, // We couldn't format the closure body as a single line expression; fall // back to block formatting. - let inner_context = context.overflow_context(closure_indent - context.block_indent); let body_rewrite = body.expr .as_ref() .and_then(|body_expr| { if let ast::Expr_::ExprBlock(ref inner) = body_expr.node { - Some(inner.rewrite(&inner_context, 2, 0)) + Some(inner.rewrite(&context, 2, 0)) } else { None } }) - .unwrap_or_else(|| body.rewrite(&inner_context, 2, 0)); + .unwrap_or_else(|| body.rewrite(&context, 2, 0)); Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } @@ -876,25 +867,21 @@ fn rewrite_string_lit(context: &RewriteContext, } pub fn rewrite_call(context: &RewriteContext, - callee: &R, - args: &[ptr::P], - span: Span, - width: usize, - offset: usize) - -> Option + callee: &R, + args: &[ptr::P], + span: Span, + width: usize, + offset: usize) + -> Option where R: Rewrite { + let closure = |callee_max_width| { + rewrite_call_inner(context, callee, callee_max_width, args, span, width, offset) + }; + // 2 is for parens let max_width = try_opt!(width.checked_sub(2)); - binary_search(1, max_width, |callee_max_width| { - rewrite_call_inner(context, - callee, - callee_max_width, - args, - span, - width, - offset) - }) + binary_search(1, max_width, closure) } fn rewrite_call_inner(context: &RewriteContext, @@ -1021,10 +1008,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => field.span.lo, StructLitField::Base(ref expr) => { - let last_field_hi = fields.last().map_or(span.lo, - |field| { - field.span.hi - }); + let last_field_hi = fields.last() + .map_or(span.lo, + |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); @@ -1074,11 +1060,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let fields_str = try_opt!(write_list(&items.collect::>(), &fmt)); let format_on_newline = || { - let inner_indent = make_indent(context.block_indent + - context.config.tab_spaces); - let outer_indent = make_indent(context.block_indent); - Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) - }; + let inner_indent = make_indent(context.block_indent + context.config.tab_spaces); + let outer_indent = make_indent(context.block_indent); + Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) + }; match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { (StructLitStyle::Block, _) if fields_str.contains('\n') => format_on_newline(), diff --git a/src/imports.rs b/src/imports.rs index 4b08a8b35e1..1d215d022d1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -150,10 +150,10 @@ pub fn rewrite_use_list(width: usize, let list_str = try_opt!(write_list(&items[first_index..], &fmt)); Some(if path_str.is_empty() { - format!("{{{}}}", list_str) - } else { - format!("{}::{{{}}}", path_str, list_str) - }) + format!("{{{}}}", list_str) + } else { + format!("{}::{{{}}}", path_str, list_str) + }) } // Returns true when self item was found. diff --git a/src/items.rs b/src/items.rs index 2547e8f5dd5..958dbb20df0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -211,10 +211,8 @@ impl<'a> FmtVisitor<'a> { let ret_str = fd.output.rewrite(&context, self.config.max_width - indent, indent).unwrap(); // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = self.compute_budgets_for_args(&result, - indent, - ret_str.len(), - newline_brace); + let (one_line_budget, multi_line_budget, mut arg_indent) = + self.compute_budgets_for_args(&result, indent, ret_str.len(), newline_brace); debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", one_line_budget, multi_line_budget, arg_indent); @@ -239,7 +237,10 @@ impl<'a> FmtVisitor<'a> { } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics.ty_params.last().map(|tp| end_typaram(tp)).unwrap_or(span.lo); + let args_start = generics.ty_params + .last() + .map(|tp| end_typaram(tp)) + .unwrap_or(span.lo); let args_span = codemap::mk_sp(span_after(codemap::mk_sp(args_start, span.hi), "(", self.codemap), diff --git a/src/utils.rs b/src/utils.rs index cb1dd718375..973f0fa56ab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -211,8 +211,7 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usi impl Rewrite for String { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { - // FIXME: unnecessary clone - wrap_str(self.clone(), context.config.max_width, width, offset) + wrap_str(self, context.config.max_width, width, offset).map(ToOwned::to_owned) } } @@ -245,13 +244,13 @@ pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option< #[test] fn bin_search_test() { let closure = |i| { - match i { - 4 => Ok(()), - j if j > 4 => Err(Ordering::Less), - j if j < 4 => Err(Ordering::Greater), - _ => unreachable!(), - } - }; + match i { + 4 => Ok(()), + j if j > 4 => Err(Ordering::Less), + j if j < 4 => Err(Ordering::Greater), + _ => unreachable!(), + } + }; assert_eq!(Some(()), binary_search(1, 10, &closure)); assert_eq!(None, binary_search(1, 3, &closure)); diff --git a/tests/source/chains-no-overflow.rs b/tests/source/chains-no-overflow.rs index fa2c66524fc..b94ca21b258 100644 --- a/tests/source/chains-no-overflow.rs +++ b/tests/source/chains-no-overflow.rs @@ -21,9 +21,8 @@ fn main() { { SCRIPT_TASK_ROOT .with(|root| { - // Another case of write_list failing us. - *root.borrow_mut() = Some(&script_task); - }); + *root.borrow_mut() = Some(&script_task); + }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx diff --git a/tests/source/chains.rs b/tests/source/chains.rs index d2f11f1dcbe..f53afaa0c28 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,7 +1,7 @@ // Test chain formatting. fn main() { - // Don't put chains on a single list if it wasn't so in source. + // Don't put chains on a single line if it wasn't so in source. let a = b .c .d.1 .foo(|x| x + 1); @@ -11,6 +11,8 @@ fn main() { bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. x() .y(|| match cond() { true => (), false => () }); diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index e95aaae75e0..35d8ec072c2 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -30,5 +30,5 @@ formatting"#; let unicode3 = "中华Việt Nam"; let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; - "stuff" + "stuffin'" } diff --git a/tests/system.rs b/tests/system.rs index d0b6ae78faa..9086697978e 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -26,9 +26,9 @@ use rustfmt::rustfmt_diff::*; static DIFF_CONTEXT_SIZE: usize = 3; fn get_path_string(dir_entry: io::Result) -> String { - let path = dir_entry.ok().expect("Couldn\'t get DirEntry.").path(); + let path = dir_entry.ok().expect("Couldn't get DirEntry.").path(); - path.to_str().expect("Couldn\'t stringify path.").to_owned() + path.to_str().expect("Couldn't stringify path.").to_owned() } // Integration tests. The files in the tests/source are formatted and compared @@ -40,7 +40,7 @@ fn get_path_string(dir_entry: io::Result) -> String { #[test] fn system_tests() { // Get all files in the tests/source directory - let files = fs::read_dir("tests/source").ok().expect("Couldn\'t read source dir."); + let files = fs::read_dir("tests/source").ok().expect("Couldn't read source dir."); // turn a DirEntry into a String that represents the relative path to the file let files = files.map(get_path_string); @@ -56,9 +56,9 @@ fn system_tests() { #[test] fn idempotence_tests() { // Get all files in the tests/target directory - let files = fs::read_dir("tests/target").ok().expect("Couldn\'t read target dir."); - let files = files.chain(fs::read_dir("tests").ok().expect("Couldn\'t read tests dir.")); - let files = files.chain(fs::read_dir("src/bin").ok().expect("Couldn\'t read src dir.")); + let files = fs::read_dir("tests/target").ok().expect("Couldn't read target dir."); + let files = files.chain(fs::read_dir("tests").ok().expect("Couldn't read tests dir.")); + let files = files.chain(fs::read_dir("src/bin").ok().expect("Couldn't read src dir.")); // turn a DirEntry into a String that represents the relative path to the file let files = files.map(get_path_string); // hack because there's no `IntoIterator` impl for `[T; N]` @@ -139,9 +139,9 @@ fn get_config(config_file: Option<&str>) -> Box { let mut def_config_file = fs::File::open(config_file_name) .ok() - .expect("Couldn\'t open config."); + .expect("Couldn't open config."); let mut def_config = String::new(); - def_config_file.read_to_string(&mut def_config).ok().expect("Couldn\'t read config."); + def_config_file.read_to_string(&mut def_config).ok().expect("Couldn't read config."); Box::new(Config::from_toml(&def_config)) } @@ -151,7 +151,7 @@ fn get_config(config_file: Option<&str>) -> Box { fn read_significant_comments(file_name: &str) -> HashMap { let file = fs::File::open(file_name) .ok() - .expect(&format!("Couldn\'t read file {}.", file_name)); + .expect(&format!("Couldn't read file {}.", file_name)); let reader = BufReader::new(file); let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; let regex = regex::Regex::new(&pattern).ok().expect("Failed creating pattern 1."); @@ -166,8 +166,8 @@ fn read_significant_comments(file_name: &str) -> HashMap { .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { - (capture.at(1).expect("Couldn\'t unwrap capture.").to_owned(), - capture.at(2).expect("Couldn\'t unwrap capture.").to_owned()) + (capture.at(1).expect("Couldn't unwrap capture.").to_owned(), + capture.at(2).expect("Couldn't unwrap capture.").to_owned()) }) }) .collect() @@ -185,7 +185,7 @@ fn handle_result(result: HashMap) { // If file is in tests/source, compare to file with same name in tests/target. let target = get_target(&file_name, sig_comments.get("target").map(|x| &(*x)[..])); - let mut f = fs::File::open(&target).ok().expect("Couldn\'t open target."); + let mut f = fs::File::open(&target).ok().expect("Couldn't open target."); let mut text = String::new(); // TODO: speedup by running through bytes iterator diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs index b4fdb9f99ce..9b1f244637d 100644 --- a/tests/target/chains-no-overflow.rs +++ b/tests/target/chains-no-overflow.rs @@ -27,8 +27,8 @@ fn main() { fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { - // Another case of write_list failing us. - *root.borrow_mut() = Some(&script_task); + *root.borrow_mut() = + Some(&script_task); }); }); diff --git a/tests/target/chains.rs b/tests/target/chains.rs index e49233e22a2..590f0a5b156 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,7 +1,7 @@ // Test chain formatting. fn main() { - // Don't put chains on a single list if it wasn't so in source. + // Don't put chains on a single line if it wasn't so in source. let a = b.c .d .1 @@ -13,6 +13,8 @@ fn main() { .ddddddddddddddddddddddddddd .eeeeeeee(); + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. x().y(|| { match cond() { true => (), diff --git a/tests/target/closure.rs b/tests/target/closure.rs index ec095ad8fcc..b42296487be 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -39,8 +39,8 @@ fn main() { let empty = |arg| {}; let simple = |arg| { /* TODO(#27): comment formatting */ - foo(arg) - }; + foo(arg) + }; let test = || { do_something(); @@ -62,8 +62,8 @@ fn main() { let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { - "sup".to_owned() - }; + "sup".to_owned() + }; |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 21cdc199d6e..36f8f6a48f9 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -36,5 +36,5 @@ formatting"#; let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃\ ☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; - "stuff" + "stuffin'" } -- cgit 1.4.1-3-g733a5 From 623d6c972a3765cf8e297ccd0570011c6807e0c0 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 11 Sep 2015 12:24:13 +0200 Subject: Rewrite types in function arguments --- src/expr.rs | 12 ++++++++++-- src/items.rs | 37 +++++++++++++++++++++++-------------- tests/source/fn-simple.rs | 3 +++ tests/target/fn-simple.rs | 4 ++++ 4 files changed, 40 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c7dad3d2ccf..530cf8eda47 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -21,7 +21,7 @@ use visitor::FmtVisitor; use config::MultilineStyle; use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; -use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input}; +use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; use syntax::{ast, ptr}; @@ -182,7 +182,15 @@ fn rewrite_closure(capture: ast::CaptureClause, "|", |arg| span_lo_for_arg(arg), |arg| span_hi_for_arg(arg), - |arg| rewrite_fn_input(arg), + |arg| { + // FIXME: we should just escalate failure + // here, but itemize_list doesn't allow it. + arg.rewrite(context, budget, argument_offset) + .unwrap_or_else(|| { + context.snippet(mk_sp(span_lo_for_arg(arg), + span_hi_for_arg(arg))) + }) + }, span_after(span, "|", context.codemap), body.span.lo); diff --git a/src/items.rs b/src/items.rs index 958dbb20df0..842f2699c2a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -12,7 +12,7 @@ use {ReturnIndent, BraceStyle, StructLitStyle}; use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, - end_typaram}; + end_typaram, wrap_str}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use expr::rewrite_assign_rhs; use comment::FindUncommented; @@ -329,7 +329,13 @@ impl<'a> FmtVisitor<'a> { arg_indent: usize, span: Span) -> Option { - let mut arg_item_strs: Vec<_> = args.iter().map(rewrite_fn_input).collect(); + let context = self.get_context(); + let mut arg_item_strs = try_opt!(args.iter() + .map(|arg| { + arg.rewrite(&context, multi_line_budget, indent) + }) + .collect::>>()); + // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. @@ -342,7 +348,7 @@ impl<'a> FmtVisitor<'a> { }) .unwrap_or(1); - // Comments between args + // Comments between args. let mut arg_items = Vec::new(); if min_args == 2 { arg_items.push(ListItem::from_str("")); @@ -925,19 +931,22 @@ impl Rewrite for ast::FunctionRetTy { } } -// TODO we farm this out, but this could spill over the column limit, so we -// ought to handle it properly. -pub fn rewrite_fn_input(arg: &ast::Arg) -> String { - if is_named_arg(arg) { - if let ast::Ty_::TyInfer = arg.ty.node { - pprust::pat_to_string(&arg.pat) +impl Rewrite for ast::Arg { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + if is_named_arg(self) { + if let ast::Ty_::TyInfer = self.ty.node { + wrap_str(pprust::pat_to_string(&self.pat), context.config.max_width, width, offset) + } else { + let mut result = pprust::pat_to_string(&self.pat); + result.push_str(": "); + let max_width = try_opt!(width.checked_sub(result.len())); + let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len())); + result.push_str(&ty_str); + Some(result) + } } else { - format!("{}: {}", - pprust::pat_to_string(&arg.pat), - pprust::ty_to_string(&arg.ty)) + self.ty.rewrite(context, width, offset) } - } else { - pprust::ty_to_string(&arg.ty) } } diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index b71fdc47875..30d11dbc71e 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -18,4 +18,7 @@ fn generic(arg: T) -> &SomeType arg(a, b, c, d, e) } +pub fn http_fetch_async(listener:Box< AsyncCORSResponseListener+Send >, script_chan: Box) { +} + fn some_func>(val:T){} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 899a73d5157..f01e85193f5 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -28,5 +28,9 @@ fn generic(arg: T) -> &SomeType arg(a, b, c, d, e) } +pub fn http_fetch_async(listener: Box, + script_chan: Box) { +} + fn some_func>(val: T) { } -- cgit 1.4.1-3-g733a5 From 7deee6daf58cdd9487680d964871436c146656a3 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 12 Sep 2015 00:06:17 +0200 Subject: Format array literals --- src/expr.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++- tests/source/expr.rs | 44 ++++++++++++++++++++++++++++++++++++++++ tests/target/expr.rs | 17 ++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 530cf8eda47..68b5bd7d487 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,12 +31,20 @@ use syntax::visit::Visitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { match self.node { + ast::Expr_::ExprVec(ref expr_vec) => { + rewrite_array(expr_vec.iter().map(|e| &**e), self.span, context, width, offset) + } ast::Expr_::ExprLit(ref l) => { match l.node { ast::Lit_::LitStr(_, ast::StrStyle::CookedStr) => { rewrite_string_lit(context, l.span, width, offset) } - _ => Some(context.snippet(self.span)), + _ => { + wrap_str(context.snippet(self.span), + context.config.max_width, + width, + offset) + } } } ast::Expr_::ExprCall(ref callee, ref args) => { @@ -151,6 +159,53 @@ impl Rewrite for ast::Expr { } } +fn rewrite_array<'a, I>(expr_iter: I, + span: Span, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option + where I: Iterator + ExactSizeIterator +{ + // 2 for brackets; + let max_item_width = try_opt!(width.checked_sub(2)); + let items = itemize_list(context.codemap, + expr_iter, + "]", + |item| item.span.lo, + |item| item.span.hi, + // 1 = [ + // FIXME(#133): itemize_list doesn't support + // rewrite failure. This may not be its + // responsibility, but that of write_list. + |item| { + item.rewrite(context, max_item_width, offset + 1) + .unwrap_or_else(|| context.snippet(item.span)) + }, + span_after(span, "[", context.codemap), + span.hi) + .collect::>(); + + let tactic = if items.iter().any(|li| li.item.len() > 10 || li.is_multiline()) { + ListTactic::HorizontalVertical + } else { + ListTactic::Mixed + }; + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset + 1, + h_width: max_item_width, + v_width: max_item_width, + ends_with_newline: false, + }; + let list_str = try_opt!(write_list(&items, &fmt)); + + Some(format!("[{}]", list_str)) +} + // This functions is pretty messy because of the wrapping and unwrapping of // expressions into and from blocks. See rust issue #27872. fn rewrite_closure(capture: ast::CaptureClause, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 083715dc8e7..faa0d3775c7 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -129,3 +129,47 @@ fn issue184(source: &str) { } } } + +fn arrays() { + let x = [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; + + [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 9017fd8bee0..bb629f12126 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -166,3 +166,20 @@ fn issue184(source: &str) { } } } + +fn arrays() { + let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 0]; + + let y = [// comment + 1, + 2, // post comment + 3]; + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q]; + + [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] +} -- cgit 1.4.1-3-g733a5 From ffa7e8d59972d7a61fa3e8192210ce17d7c86ee4 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 12 Sep 2015 14:31:51 +0200 Subject: Prevent generation of bogus comment in some function calls This would happen when the callee contained parentheses. --- src/expr.rs | 3 ++- tests/source/closure.rs | 6 ++++++ tests/target/closure.rs | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 530cf8eda47..b5fd09e0e01 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -40,7 +40,8 @@ impl Rewrite for ast::Expr { } } ast::Expr_::ExprCall(ref callee, ref args) => { - rewrite_call(context, &**callee, args, self.span, width, offset) + let inner_span = mk_sp(callee.span.hi, self.span.hi); + rewrite_call(context, &**callee, args, inner_span, width, offset) } ast::Expr_::ExprParen(ref subexpr) => { rewrite_paren(context, subexpr, width, offset) diff --git a/tests/source/closure.rs b/tests/source/closure.rs index 43ec6860243..6abd7f9c0a7 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -44,3 +44,9 @@ fn main() { |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; arg2 * arg1 - temp } } + +fn issue311() { + let func = |x| println!("{}", x); + + (func)(0.0); +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index b42296487be..146d967c8d5 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -70,3 +70,9 @@ fn main() { arg2 * arg1 - temp } } + +fn issue311() { + let func = |x| println!("{}", x); + + (func)(0.0); +} -- cgit 1.4.1-3-g733a5 From 8b808de6ff9aed5c631f088bf1293874b5299cff Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Mon, 14 Sep 2015 00:29:15 -0700 Subject: Fixed https://github.com/nrc/rustfmt/issues/291; added output to --help runtime option with possible config values --- src/bin/rustfmt.rs | 11 +++++ src/config.rs | 122 +++++++++++++++++++++++++++++++++++++++-------------- src/utils.rs | 11 +++++ 3 files changed, 113 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9913c68cdfa..f2eb4f46ac1 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,6 +18,7 @@ extern crate toml; use rustfmt::{WriteMode, run}; use rustfmt::config::Config; +use rustfmt::config::ConfigHelpVariantTypes; use std::env; use std::fs::{File, PathExt}; @@ -85,6 +86,16 @@ fn print_usage>(reason: S) { println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] \ ", reason.into()); + + for option in Config::get_docs() { + let variants = option.variant_names(); + let variant_names: String = match *variants { + ConfigHelpVariantTypes::UsizeConfig => "".into(), + ConfigHelpVariantTypes::BoolConfig => "".into(), + ConfigHelpVariantTypes::EnumConfig(ref variants) => variants.join(", "), + }; + println!("{}, {}, Possible values: {}", option.option_name(), option.doc_string(), variant_names); + } } fn determine_params(args: I) -> Option<(Vec, WriteMode)> diff --git a/src/config.rs b/src/config.rs index d45f184051f..4026ea856cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -66,7 +66,7 @@ impl MultilineStyle { } macro_rules! create_config { - ($($i:ident: $ty:ty),+ $(,)*) => ( + ($($i:ident: $ty:ty, $dstring: tt),+ $(,)*) => ( #[derive(RustcDecodable, Clone)] pub struct Config { $(pub $i: $ty),+ @@ -82,6 +82,50 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } + // This trait and the following impl blocks are there only so that we + // can use UCFS inside the get_docs() function on builtin types for configs. + trait IsConfigType { + fn get_variant_names() -> Vec<&'static str>; + } + + impl IsConfigType for bool { + fn get_variant_names() -> Vec<&'static str> { + unreachable!() + } + } + + impl IsConfigType for usize { + fn get_variant_names() -> Vec<&'static str> { + unreachable!() + } + } + + pub struct ConfigHelpItem { + option_name: &'static str, + doc_string : &'static str, + variant_names: ConfigHelpVariantTypes, + } + + pub enum ConfigHelpVariantTypes { + UsizeConfig, + BoolConfig, + EnumConfig(Vec<&'static str>), + } + + impl ConfigHelpItem { + pub fn option_name(&self) -> &'static str { + self.option_name + } + + pub fn doc_string(&self) -> &'static str { + self.doc_string + } + + pub fn variant_names(&self) -> &ConfigHelpVariantTypes { + &self.variant_names + } + } + impl Config { fn fill_from_parsed_config(mut self, parsed: &ParsedConfig) -> Config { @@ -117,41 +161,57 @@ macro_rules! create_config { _ => panic!("Bad config key!") } } + + pub fn get_docs() -> Vec { + let mut options: Vec = Vec::new(); + $( + let config_variant_type = match stringify!($ty) { + "bool" => ConfigHelpVariantTypes::BoolConfig, + "usize" => ConfigHelpVariantTypes::UsizeConfig, + _ => ConfigHelpVariantTypes::EnumConfig(<$ty>::get_variant_names()), + }; + options.push(ConfigHelpItem { + option_name: stringify!($i), + doc_string: stringify!($dstring), + variant_names: config_variant_type, + }); + )+ + options + } } ) } create_config! { - max_width: usize, - ideal_width: usize, - leeway: usize, - tab_spaces: usize, - newline_style: NewlineStyle, - fn_brace_style: BraceStyle, - fn_return_indent: ReturnIndent, - fn_args_paren_newline: bool, - fn_args_density: Density, - fn_args_layout: StructLitStyle, - fn_arg_indent: BlockIndentStyle, - where_density: Density, // Should we at least try to put the where clause on - // the same line as the rest of the function decl? - where_indent: BlockIndentStyle, // Visual will be treated like Tabbed - where_layout: ListTactic, - where_pred_indent: BlockIndentStyle, - generics_indent: BlockIndentStyle, - struct_trailing_comma: SeparatorTactic, - struct_lit_trailing_comma: SeparatorTactic, - struct_lit_style: StructLitStyle, - struct_lit_multiline_style: MultilineStyle, - enum_trailing_comma: bool, - report_todo: ReportTactic, - report_fixme: ReportTactic, - reorder_imports: bool, // Alphabetically, case sensitive. - single_line_if_else: bool, - format_strings: bool, - chains_overflow_last: bool, - take_source_hints: bool, // Retain some formatting characteristics from - // the source code. + max_width: usize, "Maximum width of each line", + ideal_width: usize, "Ideal width of each line", + leeway: usize, "Leeway of line width", + tab_spaces: usize, "Number of spaces per tab", + newline_style: NewlineStyle, "Unix or Windows line endings", + fn_brace_style: BraceStyle, "Brace style for functions", + fn_return_indent: ReturnIndent, "Location of return type in function declaration", + fn_args_paren_newline: bool, "If function argument parenthases goes on a newline", + fn_args_density: Density, "Argument density in functions", + fn_args_layout: StructLitStyle, "Layout of function arguments", + fn_arg_indent: BlockIndentStyle, "Indent on function arguments", + where_density: Density, "Density of a where clause", // Should we at least try to put the where clause on the same line as + // the rest of the function decl? + where_indent: BlockIndentStyle, "Indentation of a where clause", // Visual will be treated like Tabbed + where_layout: ListTactic, "Element layout inside a where clause", + where_pred_indent: BlockIndentStyle, "Indentation style of a where predicate", + generics_indent: BlockIndentStyle, "Indentation of generics", + struct_trailing_comma: SeparatorTactic, "If there is a trailing comma on structs", + struct_lit_trailing_comma: SeparatorTactic, "If there is a trailing comma on literal structs", + struct_lit_style: StructLitStyle, "Style of struct definition", + struct_lit_multiline_style: MultilineStyle, "Multilline style on literal structs", + enum_trailing_comma: bool, "Put a trailing comma on enum declarations", + report_todo: ReportTactic, "Report all occurences of TODO in source file comments", + report_fixme: ReportTactic, "Report all occurences of FIXME in source file comments", + reorder_imports: bool, "Reorder import statements alphabetically", // Alphabetically, case sensitive. + single_line_if_else: bool, "Put else on same line as closing brace for if statements", + format_strings: bool, "Format string literals, or leave as is", + chains_overflow_last: bool, "chains overflow last", + take_source_hints: bool, "Retain some formatting characteristics from the source code", } impl Default for Config { diff --git a/src/utils.rs b/src/utils.rs index 973f0fa56ab..0ba0c2c4a48 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -161,6 +161,17 @@ macro_rules! impl_enum_decodable { } } } + + impl $e { + pub fn get_variant_names() -> Vec<&'static str> { + let mut variants = Vec::new(); + $( + variants.push(stringify!($x)); + )* + + variants + } + } }; } -- cgit 1.4.1-3-g733a5 From cd9e9b5db08f03dff80e91cbc7e6beaf441cf3ec Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Mon, 14 Sep 2015 13:06:09 -0700 Subject: Merged config imports --- src/bin/rustfmt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index f2eb4f46ac1..ee023c9eca8 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,8 +17,7 @@ extern crate rustfmt; extern crate toml; use rustfmt::{WriteMode, run}; -use rustfmt::config::Config; -use rustfmt::config::ConfigHelpVariantTypes; +use rustfmt::config::{Config, ConfigHelpVariantTypes}; use std::env; use std::fs::{File, PathExt}; -- cgit 1.4.1-3-g733a5 From d773580715ae3f4dd7ea1a4561b25f0b29f47bf8 Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Mon, 14 Sep 2015 13:43:55 -0700 Subject: Changed ConfigType trait to only return a string of variants, rather than a vec --- src/bin/rustfmt.rs | 10 ++-------- src/config.rs | 37 +++++++++++++------------------------ src/utils.rs | 6 +++--- 3 files changed, 18 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index ee023c9eca8..2bc6e255ac0 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,7 +17,7 @@ extern crate rustfmt; extern crate toml; use rustfmt::{WriteMode, run}; -use rustfmt::config::{Config, ConfigHelpVariantTypes}; +use rustfmt::config::Config; use std::env; use std::fs::{File, PathExt}; @@ -87,13 +87,7 @@ fn print_usage>(reason: S) { reason.into()); for option in Config::get_docs() { - let variants = option.variant_names(); - let variant_names: String = match *variants { - ConfigHelpVariantTypes::UsizeConfig => "".into(), - ConfigHelpVariantTypes::BoolConfig => "".into(), - ConfigHelpVariantTypes::EnumConfig(ref variants) => variants.join(", "), - }; - println!("{}, {}, Possible values: {}", option.option_name(), option.doc_string(), variant_names); + println!("{}, {}, Possible values: {}", option.option_name(), option.doc_string(), option.variant_names()); } } diff --git a/src/config.rs b/src/config.rs index 4026ea856cb..e3ff126ee83 100644 --- a/src/config.rs +++ b/src/config.rs @@ -82,34 +82,28 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } - // This trait and the following impl blocks are there only so that we - // can use UCFS inside the get_docs() function on builtin types for configs. - trait IsConfigType { - fn get_variant_names() -> Vec<&'static str>; + // This trait and the following impl blocks are there so that we an use + // UCFS inside the get_docs() function on types for configs. + pub trait ConfigType { + fn get_variant_names() -> String; } - impl IsConfigType for bool { - fn get_variant_names() -> Vec<&'static str> { - unreachable!() + impl ConfigType for bool { + fn get_variant_names() -> String { + String::from("") } } - impl IsConfigType for usize { - fn get_variant_names() -> Vec<&'static str> { - unreachable!() + impl ConfigType for usize { + fn get_variant_names() -> String { + String::from("") } } pub struct ConfigHelpItem { option_name: &'static str, doc_string : &'static str, - variant_names: ConfigHelpVariantTypes, - } - - pub enum ConfigHelpVariantTypes { - UsizeConfig, - BoolConfig, - EnumConfig(Vec<&'static str>), + variant_names: String, } impl ConfigHelpItem { @@ -121,7 +115,7 @@ macro_rules! create_config { self.doc_string } - pub fn variant_names(&self) -> &ConfigHelpVariantTypes { + pub fn variant_names(&self) -> &String { &self.variant_names } } @@ -165,15 +159,10 @@ macro_rules! create_config { pub fn get_docs() -> Vec { let mut options: Vec = Vec::new(); $( - let config_variant_type = match stringify!($ty) { - "bool" => ConfigHelpVariantTypes::BoolConfig, - "usize" => ConfigHelpVariantTypes::UsizeConfig, - _ => ConfigHelpVariantTypes::EnumConfig(<$ty>::get_variant_names()), - }; options.push(ConfigHelpItem { option_name: stringify!($i), doc_string: stringify!($dstring), - variant_names: config_variant_type, + variant_names: <$ty>::get_variant_names(), }); )+ options diff --git a/src/utils.rs b/src/utils.rs index 0ba0c2c4a48..42d1151ba38 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -162,14 +162,14 @@ macro_rules! impl_enum_decodable { } } - impl $e { - pub fn get_variant_names() -> Vec<&'static str> { + impl ::config::ConfigType for $e { + fn get_variant_names() -> String { let mut variants = Vec::new(); $( variants.push(stringify!($x)); )* - variants + variants.join(", ") } } }; -- cgit 1.4.1-3-g733a5 From a29023a191c4b48234a051e5f93220061e3183dc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Sep 2015 11:42:54 +1200 Subject: Remove a few unnecessary `rustfmt_skip`s --- src/expr.rs | 3 --- src/lib.rs | 17 +++-------------- src/types.rs | 2 -- 3 files changed, 3 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e738976b5c5..c61e12fcb8b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -128,9 +128,6 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprAssignOp(ref op, ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, Some(op), width, offset) } - // FIXME #184 Note that this formatting is broken due to a bad span - // from the parser. - // `continue` ast::Expr_::ExprAgain(ref opt_ident) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), diff --git a/src/lib.rs b/src/lib.rs index 3f8900d6713..e5017387a25 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -237,8 +237,6 @@ fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> FileMap { // Formatting done on a char by char or line by line basis. // TODO warn on bad license // TODO other stuff for parity with make tidy -// FIXME skipping due to `continue`, #184. -#[rustfmt_skip] fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; @@ -260,10 +258,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { // Add warnings for bad todos/ fixmes if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue) - }); + errors.push(FormattingError { line: cur_line, kind: ErrorKind::BadIssue(issue) }); } if c == '\n' { @@ -274,10 +269,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } // Check for any line width errors we couldn't correct. if line_len > config.max_width { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LineOverflow - }); + errors.push(FormattingError { line: cur_line, kind: ErrorKind::LineOverflow }); } line_len = 0; cur_line += 1; @@ -302,10 +294,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } for &(l, _, _) in &trims { - errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace - }); + errors.push(FormattingError { line: l, kind: ErrorKind::TrailingWhitespace }); } report.file_error_map.insert(f.to_owned(), errors); diff --git a/src/types.rs b/src/types.rs index e0f3140d4d9..d474eb22b70 100644 --- a/src/types.rs +++ b/src/types.rs @@ -149,8 +149,6 @@ impl<'a> Rewrite for SegmentParam<'a> { // We'd really rather not do this, but there doesn't seem to be an alternative // at this point. // FIXME: fails with spans containing comments with the characters < or : -// FIXME #184 skip due to continue. -#[rustfmt_skip] fn get_path_separator(codemap: &CodeMap, path_start: BytePos, segment_start: BytePos) -- cgit 1.4.1-3-g733a5 From e4cca21a107b0fe9c79817fcbc907cff6b3d08e3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Sep 2015 17:45:54 +1200 Subject: Preserve unsafe blocks in closures Fixes #321 --- src/expr.rs | 4 +++- tests/target/fn.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c61e12fcb8b..1f82c5e10a3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -280,7 +280,9 @@ fn rewrite_closure(capture: ast::CaptureClause, // All closure bodies are blocks in the eyes of the AST, but we may not // want to unwrap them when they only contain a single expression. let inner_expr = match expr.node { - ast::Expr_::ExprBlock(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() => { + ast::Expr_::ExprBlock(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() && + inner.rules == + ast::BlockCheckMode::DefaultBlock => { inner.expr.as_ref().unwrap() } _ => expr, diff --git a/tests/target/fn.rs b/tests/target/fn.rs index f48e8eaddc6..f9ea3f0c0c5 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -82,4 +82,5 @@ fn homura>(_: T) { fn main() { let _ = function(move || 5); let _ = move || 42; + let _ = || unsafe { abort() }; } -- cgit 1.4.1-3-g733a5 From 07f7926bc22bc4e83a696865f2e7bc986e7dbb57 Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Tue, 15 Sep 2015 21:15:46 -0700 Subject: Added help string for chains_overflow_last config parameter --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index e3ff126ee83..7ee7d200b8b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -199,7 +199,7 @@ create_config! { reorder_imports: bool, "Reorder import statements alphabetically", // Alphabetically, case sensitive. single_line_if_else: bool, "Put else on same line as closing brace for if statements", format_strings: bool, "Format string literals, or leave as is", - chains_overflow_last: bool, "chains overflow last", + chains_overflow_last: bool, "Allow last call in method chain to break the line", take_source_hints: bool, "Retain some formatting characteristics from the source code", } -- cgit 1.4.1-3-g733a5 From f7513569102f18c65d13de3530b9ca879ec05e18 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 14 Sep 2015 22:53:30 +0200 Subject: Format macro invocations --- src/comment.rs | 1 + src/expr.rs | 35 +++++++------- src/issues.rs | 30 ++++++------ src/items.rs | 17 +++---- src/lib.rs | 8 ++-- src/lists.rs | 4 +- src/macros.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ src/types.rs | 23 +++++---- src/visitor.rs | 18 ++++++- tests/source/macros.rs | 30 ++++++++++++ tests/target/macros.rs | 33 +++++++++++++ tests/target/match.rs | 14 ++++-- 12 files changed, 278 insertions(+), 59 deletions(-) create mode 100644 src/macros.rs create mode 100644 tests/source/macros.rs create mode 100644 tests/target/macros.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index ff7558131d2..42aaaa4f8c9 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -288,6 +288,7 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { mod test { use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented}; + // TODO(#217): prevent string literal from going over the limit. #[test] fn format_comments() { assert_eq!("/* test */", rewrite_comment(" //test", true, 100, 100)); diff --git a/src/expr.rs b/src/expr.rs index 1f82c5e10a3..e0ad66ba34f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,6 +23,7 @@ use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; +use macros::rewrite_macro; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; @@ -150,6 +151,9 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprMethodCall(..) => { rewrite_chain(self, context, width, offset) } + ast::Expr_::ExprMac(ref mac) => { + rewrite_macro(mac, context, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. _ => wrap_str(context.snippet(self.span), context.config.max_width, width, offset), @@ -157,13 +161,13 @@ impl Rewrite for ast::Expr { } } -fn rewrite_array<'a, I>(expr_iter: I, - span: Span, - context: &RewriteContext, - width: usize, - offset: usize) - -> Option - where I: Iterator + ExactSizeIterator +pub fn rewrite_array<'a, I>(expr_iter: I, + span: Span, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option + where I: Iterator { // 2 for brackets; let max_item_width = try_opt!(width.checked_sub(2)); @@ -727,12 +731,13 @@ impl Rewrite for ast::Arm { // Patterns // 5 = ` => {` let pat_budget = try_opt!(width.checked_sub(5)); - let pat_strs = try_opt!(pats.iter().map(|p| { - p.rewrite(context, - pat_budget, - offset + context.config.tab_spaces) - }) - .collect::>>()); + let pat_strs = try_opt!(pats.iter() + .map(|p| { + p.rewrite(context, + pat_budget, + offset + context.config.tab_spaces) + }) + .collect::>>()); let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); // Add ` | `.len(). @@ -802,9 +807,7 @@ impl Rewrite for ast::Arm { } let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let body_str = try_opt!(body.rewrite(context, - body_budget, - context.block_indent)); + let body_str = try_opt!(body.rewrite(context, body_budget, context.block_indent)); Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, diff --git a/src/issues.rs b/src/issues.rs index 7d100d6db2a..6b35add20bf 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -256,17 +256,11 @@ fn find_issue() { ReportTactic::Always, ReportTactic::Never)); - assert!(! is_bad_issue("TODO: no number\n", - ReportTactic::Never, - ReportTactic::Always)); + assert!(!is_bad_issue("TODO: no number\n", ReportTactic::Never, ReportTactic::Always)); - assert!(is_bad_issue("This is a FIXME(#1)\n", - ReportTactic::Never, - ReportTactic::Always)); + assert!(is_bad_issue("This is a FIXME(#1)\n", ReportTactic::Never, ReportTactic::Always)); - assert!(! is_bad_issue("bad FIXME\n", - ReportTactic::Always, - ReportTactic::Never)); + assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Always, ReportTactic::Never)); } #[test] @@ -275,17 +269,19 @@ fn issue_type() { let expected = Some(Issue { issue_type: IssueType::Todo, missing_number: false }); assert_eq!(expected, - "TODO(#100): more awesomeness".chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap()); + "TODO(#100): more awesomeness" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap()); let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); let expected = Some(Issue { issue_type: IssueType::Fixme, missing_number: true }); assert_eq!(expected, - "Test. FIXME: bad, bad, not good".chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap()); + "Test. FIXME: bad, bad, not good" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap()); } diff --git a/src/items.rs b/src/items.rs index 842f2699c2a..6351813f996 100644 --- a/src/items.rs +++ b/src/items.rs @@ -215,7 +215,9 @@ impl<'a> FmtVisitor<'a> { self.compute_budgets_for_args(&result, indent, ret_str.len(), newline_brace); debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", - one_line_budget, multi_line_budget, arg_indent); + one_line_budget, + multi_line_budget, + arg_indent); // Check if vertical layout was forced by compute_budget_for_args. if one_line_budget <= 0 { @@ -426,7 +428,8 @@ impl<'a> FmtVisitor<'a> { let used_space = indent + result.len() + 2; let max_space = self.config.ideal_width + self.config.leeway; debug!("compute_budgets_for_args: used_space: {}, max_space: {}", - used_space, max_space); + used_space, + max_space); if used_space < max_space { budgets = Some((one_line_budget, max_space - used_space, @@ -563,9 +566,9 @@ impl<'a> FmtVisitor<'a> { // Make sure we do not exceed column limit // 4 = " = ," - assert!( - self.config.max_width >= vis.len() + name.len() + expr_snippet.len() + 4, - "Enum variant exceeded column limit"); + assert!(self.config.max_width >= + vis.len() + name.len() + expr_snippet.len() + 4, + "Enum variant exceeded column limit"); } result @@ -903,9 +906,7 @@ impl<'a> FmtVisitor<'a> { // 9 = " where ".len() + " {".len() if density == Density::Tall || preds_str.contains('\n') || indent + 9 + preds_str.len() > self.config.max_width { - Some(format!("\n{}where {}", - make_indent(indent + extra_indent), - preds_str)) + Some(format!("\n{}where {}", make_indent(indent + extra_indent), preds_str)) } else { Some(format!(" where {}", preds_str)) } diff --git a/src/lib.rs b/src/lib.rs index e5017387a25..4ab1782700d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ #![feature(rustc_private)] #![feature(custom_attribute)] #![feature(slice_splits)] +#![feature(catch_panic)] #![allow(unused_attributes)] // TODO we're going to allocate a whole bunch of temp Strings, is it worth @@ -72,6 +73,7 @@ mod comment; mod modules; pub mod rustfmt_diff; mod chains; +mod macros; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. @@ -323,8 +325,6 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { panic!("No input supplied to RustFmt"); } - #[rustfmt_skip] - // FIXME(#195): closure is formatted poorly. fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { let write_mode = self.write_mode; @@ -338,8 +338,8 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { let krate = state.krate.unwrap(); let codemap = state.session.codemap(); let mut file_map = fmt_ast(krate, codemap, &*config); - // For some reason, the codemap does not include terminating newlines - // so we must add one on for each file. This is sad. + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. filemap::append_newlines(&mut file_map); println!("{}", fmt_lines(&mut file_map, &*config)); diff --git a/src/lists.rs b/src/lists.rs index 678c84c199a..2b85c994581 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -116,7 +116,9 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op // Check if we need to fallback from horizontal listing, if possible. if tactic == ListTactic::HorizontalVertical { debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", - total_width, total_sep_len, formatting.h_width); + total_width, + total_sep_len, + formatting.h_width); tactic = if fits_single && !items.iter().any(ListItem::is_multiline) { ListTactic::Horizontal } else { diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 00000000000..dd742ad46c8 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,124 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format list-like macro invocations. These are invocations whose token trees +// can be interpreted as expressions and separated by commas. +// Note that these token trees do not actually have to be interpreted as +// expressions by the compiler. An example of an invocation we would reformat is +// foo!( x, y, z ). The token x may represent an identifier in the code, but we +// interpreted as an expression. +// Macro uses which are not-list like, such as bar!(key => val), will not be +// reformated. +// List-like invocations with parentheses will be formatted as function calls, +// and those with brackets will be formatted as array literals. + +use std::thread; + +use syntax::ast; +use syntax::parse::token::{Eof, Comma, Token}; +use syntax::parse::{ParseSess, tts_to_parser}; + +use rewrite::RewriteContext; +use expr::{rewrite_call, rewrite_array}; +use comment::FindUncommented; +use utils::wrap_str; + +// We need to pass `TokenTree`s to our expression parsing thread, but they are +// not `Send`. We wrap them in a `Send` container to force our will. +// FIXME: this is a pretty terrible hack. Any other solution would be preferred. +struct ForceSend(pub T); +unsafe impl Send for ForceSend {} + +// FIXME: use the enum from libsyntax? +enum MacroStyle { + Parens, + Brackets, + Braces, +} + +pub fn rewrite_macro(mac: &ast::Mac, + context: &RewriteContext, + width: usize, + offset: usize) + -> Option { + let ast::Mac_::MacInvocTT(ref path, ref tt_vec, _) = mac.node; + let style = macro_style(mac, context); + let macro_name = format!("{}!", path); + + if let MacroStyle::Braces = style { + return None; + } else if tt_vec.is_empty() { + return if let MacroStyle::Parens = style { + Some(format!("{}()", macro_name)) + } else { + Some(format!("{}[]", macro_name)) + }; + } + + let wrapped_tt_vec = ForceSend((*tt_vec).clone()); + // Wrap expression parsing logic in a thread since the libsyntax parser + // panicks on failure, which we do not want to propagate. + let expr_vec_result = thread::catch_panic(move || { + let parse_session = ParseSess::new(); + let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]); + let mut expr_vec = vec![]; + + loop { + expr_vec.push(parser.parse_expr()); + + match parser.token { + Token::Eof => break, + Token::Comma => (), + _ => panic!("Macro not list-like, skiping..."), + } + + let _ = parser.bump(); + } + + expr_vec + }); + let expr_vec = try_opt!(expr_vec_result.ok()); + + match style { + MacroStyle::Parens => { + // Format macro invocation as function call. + rewrite_call(context, ¯o_name, &expr_vec, mac.span, width, offset) + } + MacroStyle::Brackets => { + // Format macro invocation as array literal. + let extra_offset = macro_name.len(); + let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mac.span, + context, + try_opt!(width.checked_sub(extra_offset)), + offset + extra_offset)); + Some(format!("{}{}", macro_name, rewrite)) + } + MacroStyle::Braces => { + // Skip macro invocations with braces, for now. + wrap_str(context.snippet(mac.span), context.config.max_width, width, offset) + } + } +} + +fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { + let snippet = context.snippet(mac.span); + let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); + let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); + let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); + + if paren_pos < bracket_pos && paren_pos < brace_pos { + MacroStyle::Parens + } else if bracket_pos < brace_pos { + MacroStyle::Brackets + } else { + MacroStyle::Braces + } +} diff --git a/src/types.rs b/src/types.rs index d474eb22b70..1f5e667c6fa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -137,7 +137,9 @@ impl<'a> Rewrite for SegmentParam<'a> { try_opt!(ty.rewrite(context, width, offset)) } SegmentParam::Binding(ref binding) => { - format!("{} = {}", binding.ident, try_opt!(binding.ty.rewrite(context, width, offset))) + format!("{} = {}", + binding.ident, + try_opt!(binding.ty.rewrite(context, width, offset))) } }) } @@ -319,8 +321,10 @@ impl Rewrite for ast::WherePredicate { .. }) => { format!("{}: {}", pprust::lifetime_to_string(lifetime), - bounds.iter().map(pprust::lifetime_to_string) - .collect::>().join(" + ")) + bounds.iter() + .map(pprust::lifetime_to_string) + .collect::>() + .join(" + ")) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref path, ref ty, .. }) => { let ty_str = pprust::ty_to_string(ty); @@ -342,8 +346,11 @@ impl Rewrite for ast::LifetimeDef { } else { Some(format!("{}: {}", pprust::lifetime_to_string(&self.lifetime), - self.bounds.iter().map(pprust::lifetime_to_string) - .collect::>().join(" + "))) + self.bounds + .iter() + .map(pprust::lifetime_to_string) + .collect::>() + .join(" + "))) } } } @@ -410,9 +417,9 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref.path.rewrite(context, - max_path_width, - offset + extra_offset)); + let path_str = try_opt!(self.trait_ref + .path + .rewrite(context, max_path_width, offset + extra_offset)); Some(format!("for<{}> {}", lifetime_str, path_str)) } else { diff --git a/src/visitor.rs b/src/visitor.rs index 54ada1b7455..f09c198ca33 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -18,6 +18,7 @@ use utils; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; +use macros::rewrite_macro; pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, @@ -73,7 +74,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = stmt.span.hi; } } - ast::Stmt_::StmtMac(..) => { + ast::Stmt_::StmtMac(ref _mac, _macro_style) => { self.format_missing_with_indent(stmt.span.lo); visit::walk_stmt(self, stmt); } @@ -213,6 +214,12 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.format_missing_with_indent(item.span.lo); self.format_mod(module, item.span, item.ident); } + ast::Item_::ItemMac(..) => { + self.format_missing_with_indent(item.span.lo); + // TODO: we cannot format these yet, because of a bad span. + // See rust lang issue #28424. + // visit::walk_item(self, item); + } _ => { visit::walk_item(self, item); } @@ -249,7 +256,14 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } fn visit_mac(&mut self, mac: &'v ast::Mac) { - visit::walk_mac(self, mac) + // 1 = ; + let width = self.config.max_width - self.block_indent - 1; + let rewrite = rewrite_macro(mac, &self.get_context(), width, self.block_indent); + + if let Some(res) = rewrite { + self.buffer.push_str(&res); + self.last_pos = mac.span.hi; + } } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs new file mode 100644 index 00000000000..8487e0c5deb --- /dev/null +++ b/tests/source/macros.rs @@ -0,0 +1,30 @@ +itemmacro!(this, is.not() .formatted(yet)); + +fn main() { + foo! ( ); + + bar!( a , b , c ); + + baz!(1+2+3, quux. kaas()); + + quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + + kaas!(/* comments */ a /* post macro */, b /* another */); + + trailingcomma!( a , b , c , ); + + noexpr!( i am not an expression, OK? ); + + vec! [ a , b , c]; + + vec! [AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, + BBBBB, 5, 100-30, 1.33, b, b, b]; + + vec! [a /* comment */]; + + foo(makro!(1, 3)); + + hamkaas!{ () }; + + macrowithbraces! {dont, format, me} +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs new file mode 100644 index 00000000000..ac87b693246 --- /dev/null +++ b/tests/target/macros.rs @@ -0,0 +1,33 @@ +itemmacro!(this, is.not() .formatted(yet)); + +fn main() { + foo!(); + + bar!(a, b, c); + + baz!(1 + 2 + 3, quux.kaas()); + + quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + + kaas!(// comments + a, // post macro + b /* another */); + + trailingcomma!( a , b , c , ); + + noexpr!( i am not an expression, OK? ); + + vec![a, b, c]; + + vec![AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, BBBBB, 5, + 100 - 30, 1.33, b, b, b]; + + vec![a /* comment */]; + + foo(makro!(1, 3)); + + hamkaas!{ () }; + + macrowithbraces! {dont, format, me} +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 5cfbb5a7072..e18c04bf02a 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -67,12 +67,20 @@ fn main() { fn main() { match r { Variableeeeeeeeeeeeeeeeee => ("variable", - vec!("id","name","qualname","value","type","scopeid"), + vec!("id", "name", "qualname", "value", "type", "scopeid"), true, true), - Enummmmmmmmmmmmmmmmmmmmm => ("enum", vec!("id","qualname","scopeid","value"), true, true), + Enummmmmmmmmmmmmmmmmmmmm => ("enum", + vec!("id", "qualname", "scopeid", "value"), + true, + true), Variantttttttttttttttttttttttt => ("variant", - vec!("id","name","qualname","type","value","scopeid"), + vec!("id", + "name", + "qualname", + "type", + "value", + "scopeid"), true, true), } -- cgit 1.4.1-3-g733a5 From 110f7206e6e08b75dfa1f3d1b45c562a19dc9e20 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 16 Sep 2015 21:52:32 +0200 Subject: Split formatting function from side effects This makes rustfmt more usable as a library. --- src/lib.rs | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 4ab1782700d..c5ff601e109 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,8 @@ use std::collections::HashMap; use std::fmt; use std::mem::swap; use std::str::FromStr; +use std::rc::Rc; +use std::cell::RefCell; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; @@ -310,8 +312,9 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } struct RustFmtCalls { - write_mode: WriteMode, config: Option>, + // FIXME: there's likely a better type for the job. + result: Rc>>, } impl<'a> CompilerCalls<'a> for RustFmtCalls { @@ -326,11 +329,10 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { - let write_mode = self.write_mode; - let mut config_option = None; swap(&mut self.config, &mut config_option); let config = config_option.unwrap(); + let result = self.result.clone(); let mut control = driver::CompileController::basic(); control.after_parse.stop = Compilation::Stop; @@ -341,29 +343,44 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. filemap::append_newlines(&mut file_map); - println!("{}", fmt_lines(&mut file_map, &*config)); - - let result = filemap::write_all_files(&file_map, write_mode, &*config); - match result { - Err(msg) => println!("Error writing files: {}", msg), - Ok(result) => { - if let WriteMode::Return(callback) = write_mode { - callback(result); - } - } - } + *result.borrow_mut() = Some(file_map); }); control } } +pub fn format(args: Vec, config: Box) -> FileMap { + let result = Rc::new(RefCell::new(None)); + { + let mut call_ctxt = RustFmtCalls { config: Some(config), result: result.clone() }; + rustc_driver::run_compiler(&args, &mut call_ctxt); + } + + // Peel the union. + Rc::try_unwrap(result).ok().unwrap().into_inner().unwrap() +} + // args are the arguments passed on the command line, generally passed through // to the compiler. // write_mode determines what happens to the result of running rustfmt, see // WriteMode. pub fn run(args: Vec, write_mode: WriteMode, config: Box) { - let mut call_ctxt = RustFmtCalls { write_mode: write_mode, config: Some(config) }; - rustc_driver::run_compiler(&args, &mut call_ctxt); + // FIXME: we probs don't need a full clone + let config_clone = (&config).clone(); + let mut result = format(args, config); + + println!("{}", fmt_lines(&mut result, &config_clone)); + + let write_result = filemap::write_all_files(&result, write_mode, &config_clone); + + match write_result { + Err(msg) => println!("Error writing files: {}", msg), + Ok(result) => { + if let WriteMode::Return(callback) = write_mode { + callback(result); + } + } + } } -- cgit 1.4.1-3-g733a5 From e72d4882819d8d747746199ade3adcf06292e3a3 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 17 Sep 2015 20:21:06 +0200 Subject: Refactor test code No longer use callbacks or thread::catch_panic; reduce stdout spew; guard against rustfmt breaking the column limit. --- src/bin/rustfmt.rs | 7 ++- src/comment.rs | 10 +++-- src/config.rs | 57 ++++++++++++++++++++--- src/expr.rs | 3 +- src/filemap.rs | 9 ++-- src/items.rs | 26 +++++------ src/lib.rs | 100 +++++++++++------------------------------ src/types.rs | 6 +-- src/visitor.rs | 9 ++-- tests/system.rs | 130 ++++++++++++++++++++++++++++++++--------------------- 10 files changed, 193 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2bc6e255ac0..af83cf13f85 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -65,7 +65,7 @@ fn execute() -> i32 { Err(_) => Default::default(), }; - run(args, write_mode, Box::new(config)); + run(args, write_mode, &config); 0 } @@ -87,7 +87,10 @@ fn print_usage>(reason: S) { reason.into()); for option in Config::get_docs() { - println!("{}, {}, Possible values: {}", option.option_name(), option.doc_string(), option.variant_names()); + println!("{}, {}, Possible values: {}", + option.option_name(), + option.doc_string(), + option.variant_names()); } } diff --git a/src/comment.rs b/src/comment.rs index 42aaaa4f8c9..05117a7cb76 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -288,8 +288,9 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { mod test { use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented}; - // TODO(#217): prevent string literal from going over the limit. + // FIXME(#217): prevent string literal from going over the limit. #[test] + #[rustfmt_skip] fn format_comments() { assert_eq!("/* test */", rewrite_comment(" //test", true, 100, 100)); assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, 0)); @@ -301,9 +302,10 @@ mod test { 12)); let input = "// comment"; - let expected = "/* com\n \ - * men\n \ - * t */"; + let expected = + "/* com\n \ + * men\n \ + * t */"; assert_eq!(expected, rewrite_comment(input, true, 9, 69)); assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); diff --git a/src/config.rs b/src/config.rs index 7ee7d200b8b..2ecee9f98fe 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,9 +10,51 @@ extern crate toml; -use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle}; use lists::{SeparatorTactic, ListTactic}; -use issues::ReportTactic; +pub use issues::ReportTactic; + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum NewlineStyle { + Windows, // \r\n + Unix, // \n +} + +impl_enum_decodable!(NewlineStyle, Windows, Unix); + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum BraceStyle { + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +impl_enum_decodable!(BraceStyle, AlwaysNextLine, PreferSameLine, SameLineWhere); + +// How to indent a function's return type. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum ReturnIndent { + // Aligned with the arguments + WithArgs, + // Aligned with the where clause + WithWhereClause, +} + +impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); + +// How to stle a struct literal. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum StructLitStyle { + // First line on the same line as the opening brace, all lines aligned with + // the first line. + Visual, + // First line is on a new line and all lines align with block indent. + Block, + // FIXME Maybe we should also have an option to align types. +} + +impl_enum_decodable!(StructLitStyle, Visual, Block); #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum BlockIndentStyle { @@ -183,9 +225,11 @@ create_config! { fn_args_density: Density, "Argument density in functions", fn_args_layout: StructLitStyle, "Layout of function arguments", fn_arg_indent: BlockIndentStyle, "Indent on function arguments", - where_density: Density, "Density of a where clause", // Should we at least try to put the where clause on the same line as - // the rest of the function decl? - where_indent: BlockIndentStyle, "Indentation of a where clause", // Visual will be treated like Tabbed + // Should we at least try to put the where clause on the same line as the rest of the + // function decl? + where_density: Density, "Density of a where clause", + // Visual will be treated like Tabbed + where_indent: BlockIndentStyle, "Indentation of a where clause", where_layout: ListTactic, "Element layout inside a where clause", where_pred_indent: BlockIndentStyle, "Indentation style of a where predicate", generics_indent: BlockIndentStyle, "Indentation of generics", @@ -196,7 +240,8 @@ create_config! { enum_trailing_comma: bool, "Put a trailing comma on enum declarations", report_todo: ReportTactic, "Report all occurences of TODO in source file comments", report_fixme: ReportTactic, "Report all occurences of FIXME in source file comments", - reorder_imports: bool, "Reorder import statements alphabetically", // Alphabetically, case sensitive. + // Alphabetically, case sensitive. + reorder_imports: bool, "Reorder import statements alphabetically", single_line_if_else: bool, "Put else on same line as closing brace for if statements", format_strings: bool, "Format string literals, or leave as is", chains_overflow_last: bool, "Allow last call in method chain to break the line", diff --git a/src/expr.rs b/src/expr.rs index e0ad66ba34f..a91c6c38572 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -14,11 +14,10 @@ use std::borrow::Borrow; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; -use StructLitStyle; use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width, wrap_str, binary_search}; use visitor::FmtVisitor; -use config::MultilineStyle; +use config::{StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; diff --git a/src/filemap.rs b/src/filemap.rs index 91aaece6558..d94c1501734 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -9,15 +9,16 @@ // except according to those terms. -// TODO tests +// TODO: add tests use strings::string_buffer::StringBuffer; + use std::collections::HashMap; use std::fs::{self, File}; use std::io::{self, Write, Read, stdout}; + use WriteMode; -use NewlineStyle; -use config::Config; +use config::{NewlineStyle, Config}; use rustfmt_diff::{make_diff, print_diff}; // A map of the files of a crate, with their new content @@ -116,7 +117,7 @@ fn write_file(text: &StringBuffer, let diff = make_diff(&ori_text, &fmt_text, 3); print_diff(diff, |line_num| format!("\nDiff at line {}:", line_num)); } - WriteMode::Return(_) => { + WriteMode::Return => { // io::Write is not implemented for String, working around with // Vec let mut v = Vec::new(); diff --git a/src/items.rs b/src/items.rs index 6351813f996..2b470e03f95 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,7 +10,6 @@ // Formatting top-level items - functions, structs, enums, traits, impls. -use {ReturnIndent, BraceStyle, StructLitStyle}; use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, end_typaram, wrap_str}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; @@ -18,7 +17,7 @@ use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, BlockIndentStyle, Density}; +use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; use syntax::{ast, abi}; use syntax::codemap::{self, Span, BytePos}; @@ -35,7 +34,7 @@ impl<'a> FmtVisitor<'a> { if let Some(ref ty) = local.ty { infix.push_str(": "); - // FIXME silly width, indent + // FIXME: silly width, indent infix.push_str(&ty.rewrite(&self.get_context(), 1000, 0).unwrap()); } @@ -271,9 +270,9 @@ impl<'a> FmtVisitor<'a> { self.config.fn_args_layout != StructLitStyle::Block { let indent = match self.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, - // TODO we might want to check that using the arg indent doesn't - // blow our budget, and if it does, then fallback to the where - // clause indent. + // TODO: we might want to check that using the arg indent + // doesn't blow our budget, and if it does, then fallback to + // the where clause indent. _ => arg_indent, }; @@ -356,9 +355,10 @@ impl<'a> FmtVisitor<'a> { arg_items.push(ListItem::from_str("")); } - // TODO if there are no args, there might still be a comment, but without - // spans for the comment or parens, there is no chance of getting it right. - // You also don't get to put a comment on self, unless it is explicit. + // TODO(#21): if there are no args, there might still be a comment, but + // without spans for the comment or parens, there is no chance of + // getting it right. You also don't get to put a comment on self, unless + // it is explicit. if args.len() >= min_args { let comment_span_start = if min_args == 2 { span_after(span, ",", self.codemap) @@ -444,7 +444,7 @@ impl<'a> FmtVisitor<'a> { let max_space = self.config.ideal_width + self.config.leeway; if used_space > max_space { // Whoops! bankrupt. - // TODO take evasive action, perhaps kill the indent or something. + // TODO: take evasive action, perhaps kill the indent or something. } else { budgets = Some((0, max_space - used_space, new_indent)); } @@ -574,7 +574,7 @@ impl<'a> FmtVisitor<'a> { result } ast::VariantKind::StructVariantKind(ref struct_def) => { - // TODO Should limit the width, as we have a trailing comma + // TODO: Should limit the width, as we have a trailing comma let struct_rewrite = self.format_struct("", field.node.name, field.node.vis, @@ -795,7 +795,7 @@ impl<'a> FmtVisitor<'a> { generics_offset: usize, span: Span) -> Option { - // FIXME convert bounds to where clauses where they get too big or if + // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; let tys: &[_] = &generics.ty_params; @@ -811,7 +811,7 @@ impl<'a> FmtVisitor<'a> { }; let h_budget = self.config.max_width - generics_offset - 2; - // TODO might need to insert a newline if the generics are really long + // TODO: might need to insert a newline if the generics are really long. // Strings for the generics. let context = self.get_context(); diff --git a/src/lib.rs b/src/lib.rs index c5ff601e109..7b6adeba2c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,6 @@ use syntax::diagnostics; use std::path::PathBuf; use std::collections::HashMap; use std::fmt; -use std::mem::swap; use std::str::FromStr; use std::rc::Rc; use std::cell::RefCell; @@ -60,7 +59,7 @@ use config::Config; #[macro_use] mod utils; pub mod config; -mod filemap; +pub mod filemap; mod visitor; mod items; mod missed_spans; @@ -94,7 +93,7 @@ pub enum WriteMode { // Write the diff to stdout. Diff, // Return the result as a mapping from filenames to Strings. - Return(&'static Fn(HashMap)), + Return, } impl FromStr for WriteMode { @@ -111,50 +110,7 @@ impl FromStr for WriteMode { } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum NewlineStyle { - Windows, // \r\n - Unix, // \n -} - -impl_enum_decodable!(NewlineStyle, Windows, Unix); - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum BraceStyle { - AlwaysNextLine, - PreferSameLine, - // Prefer same line except where there is a where clause, in which case force - // the brace to the next line. - SameLineWhere, -} - -impl_enum_decodable!(BraceStyle, AlwaysNextLine, PreferSameLine, SameLineWhere); - -// How to indent a function's return type. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum ReturnIndent { - // Aligned with the arguments - WithArgs, - // Aligned with the where clause - WithWhereClause, -} - -impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); - -// How to stle a struct literal. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum StructLitStyle { - // First line on the same line as the opening brace, all lines aligned with - // the first line. - Visual, - // First line is on a new line and all lines align with block indent. - Block, - // FIXME Maybe we should also have an option to align types. -} - -impl_enum_decodable!(StructLitStyle, Visual, Block); - -enum ErrorKind { +pub enum ErrorKind { // Line has exceeded character limit LineOverflow, // Line ends in whitespace @@ -179,8 +135,8 @@ impl fmt::Display for ErrorKind { } } -// Formatting errors that are identified *after* rustfmt has run -struct FormattingError { +// Formatting errors that are identified *after* rustfmt has run. +pub struct FormattingError { line: u32, kind: ErrorKind, } @@ -203,11 +159,17 @@ impl FormattingError { } } -struct FormatReport { - // Maps stringified file paths to their associated formatting errors +pub struct FormatReport { + // Maps stringified file paths to their associated formatting errors. file_error_map: HashMap>, } +impl FormatReport { + pub fn warning_count(&self) -> usize { + self.file_error_map.iter().map(|(_, ref errors)| errors.len()).fold(0, |acc, x| acc + x) + } +} + impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -239,9 +201,9 @@ fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> FileMap { } // Formatting done on a char by char or line by line basis. -// TODO warn on bad license -// TODO other stuff for parity with make tidy -fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { +// TODO(#209) warn on bad license +// TODO(#20) other stuff for parity with make tidy +pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; @@ -312,8 +274,7 @@ fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } struct RustFmtCalls { - config: Option>, - // FIXME: there's likely a better type for the job. + config: Rc, result: Rc>>, } @@ -329,10 +290,8 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { - let mut config_option = None; - swap(&mut self.config, &mut config_option); - let config = config_option.unwrap(); let result = self.result.clone(); + let config = self.config.clone(); let mut control = driver::CompileController::basic(); control.after_parse.stop = Compilation::Stop; @@ -351,10 +310,12 @@ impl<'a> CompilerCalls<'a> for RustFmtCalls { } } -pub fn format(args: Vec, config: Box) -> FileMap { +pub fn format(args: Vec, config: &Config) -> FileMap { let result = Rc::new(RefCell::new(None)); + { - let mut call_ctxt = RustFmtCalls { config: Some(config), result: result.clone() }; + let config = Rc::new(config.clone()); + let mut call_ctxt = RustFmtCalls { config: config, result: result.clone() }; rustc_driver::run_compiler(&args, &mut call_ctxt); } @@ -366,21 +327,14 @@ pub fn format(args: Vec, config: Box) -> FileMap { // to the compiler. // write_mode determines what happens to the result of running rustfmt, see // WriteMode. -pub fn run(args: Vec, write_mode: WriteMode, config: Box) { - // FIXME: we probs don't need a full clone - let config_clone = (&config).clone(); +pub fn run(args: Vec, write_mode: WriteMode, config: &Config) { let mut result = format(args, config); - println!("{}", fmt_lines(&mut result, &config_clone)); + println!("{}", fmt_lines(&mut result, config)); - let write_result = filemap::write_all_files(&result, write_mode, &config_clone); + let write_result = filemap::write_all_files(&result, write_mode, config); - match write_result { - Err(msg) => println!("Error writing files: {}", msg), - Ok(result) => { - if let WriteMode::Return(callback) = write_mode { - callback(result); - } - } + if let Err(msg) = write_result { + println!("Error writing files: {}", msg); } } diff --git a/src/types.rs b/src/types.rs index 1f5e667c6fa..e52909b0d5c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -127,7 +127,7 @@ impl<'a> SegmentParam<'a> { } impl<'a> Rewrite for SegmentParam<'a> { - // FIXME doesn't always use width, offset + // FIXME: doesn't always use width, offset. fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { Some(match *self { SegmentParam::LifeTime(ref lt) => { @@ -270,8 +270,8 @@ fn rewrite_segment(segment: &ast::PathSegment, impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { - // TODO dead spans? - // TODO assumes we'll always fit on one line... + // TODO: dead spans? + // TODO: don't assume we'll always fit on one line... Some(match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ref bound_lifetimes, ref bounded_ty, diff --git a/src/visitor.rs b/src/visitor.rs index f09c198ca33..1e3ebf71cef 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -24,7 +24,7 @@ pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, pub buffer: StringBuffer, pub last_pos: BytePos, - // TODO RAII util for indenting + // TODO: RAII util for indenting pub block_indent: usize, pub config: &'a Config, } @@ -112,7 +112,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } self.block_indent -= self.config.tab_spaces; - // TODO we should compress any newlines here to just one + // TODO: we should compress any newlines here to just one. self.format_missing_with_indent(b.span.hi - brace_compensation); self.buffer.push_str("}"); self.last_pos = b.span.hi; @@ -237,13 +237,12 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { let indent = self.block_indent; let new_fn = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); - if let Some(fn_str) = new_fn { self.buffer.push_str(&fn_str); self.last_pos = ti.span.hi; } } - // TODO format trait types + // TODO: format trait types. visit::walk_trait_item(self, ti) } @@ -320,7 +319,7 @@ impl<'a> FmtVisitor<'a> { let local_file_name = self.codemap.span_to_filename(s); let is_internal = local_file_name == self.codemap.span_to_filename(m.inner); - // TODO Should rewrite properly `mod X;` + // TODO: Should rewrite properly `mod X;` if is_internal { debug!("FmtVisitor::format_mod: internal mod"); diff --git a/tests/system.rs b/tests/system.rs index 9086697978e..4e7ec958c18 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(catch_panic)] - extern crate rustfmt; extern crate diff; extern crate regex; @@ -18,9 +16,9 @@ extern crate term; use std::collections::HashMap; use std::fs; use std::io::{self, Read, BufRead, BufReader}; -use std::thread; + use rustfmt::*; -use rustfmt::config::Config; +use rustfmt::config::{Config, ReportTactic}; use rustfmt::rustfmt_diff::*; static DIFF_CONTEXT_SIZE: usize = 3; @@ -39,14 +37,14 @@ fn get_path_string(dir_entry: io::Result) -> String { // least report. #[test] fn system_tests() { - // Get all files in the tests/source directory + // Get all files in the tests/source directory. let files = fs::read_dir("tests/source").ok().expect("Couldn't read source dir."); - // turn a DirEntry into a String that represents the relative path to the file + // Turn a DirEntry into a String that represents the relative path to the + // file. let files = files.map(get_path_string); + let (_reports, count, fails) = check_files(files); - let (count, fails) = check_files(files); - - // Display results + // Display results. println!("Ran {} system tests.", count); assert!(fails == 0, "{} system tests failed", fails); } @@ -55,40 +53,69 @@ fn system_tests() { // rustfmt. #[test] fn idempotence_tests() { - // Get all files in the tests/target directory - let files = fs::read_dir("tests/target").ok().expect("Couldn't read target dir."); - let files = files.chain(fs::read_dir("tests").ok().expect("Couldn't read tests dir.")); - let files = files.chain(fs::read_dir("src/bin").ok().expect("Couldn't read src dir.")); - // turn a DirEntry into a String that represents the relative path to the file - let files = files.map(get_path_string); - // hack because there's no `IntoIterator` impl for `[T; N]` + // Get all files in the tests/target directory. + let files = fs::read_dir("tests/target") + .ok() + .expect("Couldn't read target dir.") + .map(get_path_string); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} idempotent tests.", count); + assert!(fails == 0, "{} idempotent tests failed", fails); +} + +// Run rustfmt on itself. This operation must be idempotent. We also check that +// no warnings are emitted. +#[test] +fn self_tests() { + let files = fs::read_dir("src/bin") + .ok() + .expect("Couldn't read src dir.") + .chain(fs::read_dir("tests").ok().expect("Couldn't read tests dir.")) + .map(get_path_string); + // Hack because there's no `IntoIterator` impl for `[T; N]`. let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); - let (count, fails) = check_files(files); + let (reports, count, fails) = check_files(files); + let mut warnings = 0; - // Display results - println!("Ran {} idempotent tests.", count); - assert!(fails == 0, "{} idempotent tests failed", fails); + // Display results. + println!("Ran {} self tests.", count); + assert!(fails == 0, "{} self tests failed", fails); + + for format_report in reports { + println!("{}", format_report); + warnings += format_report.warning_count(); + } + + assert!(warnings == 0, "Rustfmt's code generated {} warnings", warnings); } // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. -fn check_files(files: I) -> (u32, u32) +fn check_files(files: I) -> (Vec, u32, u32) where I: Iterator { let mut count = 0; let mut fails = 0; + let mut reports = vec![]; for file_name in files.filter(|f| f.ends_with(".rs")) { println!("Testing '{}'...", file_name); - if let Err(msg) = idempotent_check(file_name) { - print_mismatches(msg); - fails += 1; + + match idempotent_check(file_name) { + Ok(report) => reports.push(report), + Err(msg) => { + print_mismatches(msg); + fails += 1; + } } + count += 1; } - (count, fails) + (reports, count, fails) } fn print_mismatches(result: HashMap>) { @@ -101,35 +128,34 @@ fn print_mismatches(result: HashMap>) { assert!(t.reset().unwrap()); } -// Ick, just needed to get a &'static to handle_result. -static HANDLE_RESULT: &'static Fn(HashMap) = &handle_result; - -pub fn idempotent_check(filename: String) -> Result<(), HashMap>> { +pub fn idempotent_check(filename: String) -> Result>> { let sig_comments = read_significant_comments(&filename); let mut config = get_config(sig_comments.get("config").map(|x| &(*x)[..])); let args = vec!["rustfmt".to_owned(), filename]; - for (key, val) in sig_comments { + for (key, val) in &sig_comments { if key != "target" && key != "config" { - config.override_value(&key, &val); + config.override_value(key, val); } } - // this thread is not used for concurrency, but rather to workaround the issue that the passed - // function handle needs to have static lifetime. Instead of using a global RefCell, we use - // panic to return a result in case of failure. This has the advantage of smoothing the road to - // multithreaded rustfmt - thread::catch_panic(move || { - run(args, WriteMode::Return(HANDLE_RESULT), config); - }) - .map_err(|any| *any.downcast().ok().expect("Downcast failed.")) -} + // Don't generate warnings for to-do items. + config.report_todo = ReportTactic::Never; + let mut file_map = format(args, &config); + let format_report = fmt_lines(&mut file_map, &config); + + // Won't panic, as we're not doing any IO. + let write_result = filemap::write_all_files(&file_map, WriteMode::Return, &config).unwrap(); + let target = sig_comments.get("target").map(|x| &(*x)[..]); + + handle_result(write_result, target).map(|_| format_report) +} // Reads test config file from comments and reads its contents. -fn get_config(config_file: Option<&str>) -> Box { +fn get_config(config_file: Option<&str>) -> Config { let config_file_name = match config_file { - None => return Box::new(Default::default()), + None => return Default::default(), Some(file_name) => { let mut full_path = "tests/config/".to_owned(); full_path.push_str(&file_name); @@ -143,7 +169,7 @@ fn get_config(config_file: Option<&str>) -> Box { let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).ok().expect("Couldn't read config."); - Box::new(Config::from_toml(&def_config)) + Config::from_toml(&def_config) } // Reads significant comments of the form: // rustfmt-key: value @@ -175,29 +201,29 @@ fn read_significant_comments(file_name: &str) -> HashMap { // Compare output to input. // TODO: needs a better name, more explanation. -fn handle_result(result: HashMap) { +fn handle_result(result: HashMap, + target: Option<&str>) + -> Result<(), HashMap>> { let mut failures = HashMap::new(); for (file_name, fmt_text) in result { - // FIXME: reading significant comments again. Is there a way we can just - // pass the target to this function? - let sig_comments = read_significant_comments(&file_name); - // If file is in tests/source, compare to file with same name in tests/target. - let target = get_target(&file_name, sig_comments.get("target").map(|x| &(*x)[..])); + let target = get_target(&file_name, target); let mut f = fs::File::open(&target).ok().expect("Couldn't open target."); let mut text = String::new(); - // TODO: speedup by running through bytes iterator f.read_to_string(&mut text).ok().expect("Failed reading target."); + if fmt_text != text { let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); failures.insert(file_name, diff); } } - if !failures.is_empty() { - panic!(failures); + if failures.is_empty() { + Ok(()) + } else { + Err(failures) } } -- cgit 1.4.1-3-g733a5 From 3da7adbc3f15849ed28d84e7b66d028c6f25b3f4 Mon Sep 17 00:00:00 2001 From: Sebastian Ullrich Date: Sat, 19 Sep 2015 17:28:00 +0200 Subject: rustc update: Remove variant visibility https://github.com/rust-lang/rust/pull/28440 --- src/items.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2b470e03f95..a14310e94ef 100644 --- a/src/items.rs +++ b/src/items.rs @@ -507,8 +507,6 @@ impl<'a> FmtVisitor<'a> { let result = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { - let vis = format_visibility(field.node.vis); - self.buffer.push_str(vis); let name = field.node.name.to_string(); self.buffer.push_str(&name); @@ -531,8 +529,7 @@ impl<'a> FmtVisitor<'a> { result.push('('); - let indent = self.block_indent + vis.len() + field.node.name.to_string().len() + - 1; // Open paren + let indent = self.block_indent + field.node.name.to_string().len() + "(".len(); let comma_cost = if self.config.enum_trailing_comma { 1 @@ -565,9 +562,8 @@ impl<'a> FmtVisitor<'a> { result.push_str(&expr_snippet); // Make sure we do not exceed column limit - // 4 = " = ," assert!(self.config.max_width >= - vis.len() + name.len() + expr_snippet.len() + 4, + name.len() + expr_snippet.len() + " = ,".len(), "Enum variant exceeded column limit"); } @@ -577,7 +573,7 @@ impl<'a> FmtVisitor<'a> { // TODO: Should limit the width, as we have a trailing comma let struct_rewrite = self.format_struct("", field.node.name, - field.node.vis, + ast::Visibility::Inherited, struct_def, None, field.span, -- cgit 1.4.1-3-g733a5 From d4108a3029cecf7855514f568f8b3b88edcbfdb7 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Sat, 5 Sep 2015 22:39:28 -0700 Subject: Initial implementation of hard tab indentation. --- src/chains.rs | 9 ++-- src/comment.rs | 31 ++++++++---- src/config.rs | 2 + src/expr.rs | 133 +++++++++++++++++++++++++++++---------------------- src/imports.rs | 6 ++- src/items.rs | 135 +++++++++++++++++++++++++++++----------------------- src/lib.rs | 74 ++++++++++++++++++++++++++++ src/lists.rs | 32 +++++++++---- src/macros.rs | 3 +- src/missed_spans.rs | 7 +-- src/rewrite.rs | 11 +++-- src/string.rs | 7 ++- src/types.rs | 29 +++++------ src/utils.rs | 22 ++++----- src/visitor.rs | 81 +++++++++++++++++-------------- 15 files changed, 368 insertions(+), 214 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index bd9f302824b..daf800ace08 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -19,6 +19,7 @@ // we put each subexpression on a separate, much like the (default) function // argument function argument strategy. +use Indent; use rewrite::{Rewrite, RewriteContext}; use utils::{first_line_width, make_indent}; use expr::rewrite_call; @@ -30,7 +31,7 @@ use syntax::print::pprust; pub fn rewrite_chain(mut expr: &ast::Expr, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option { let total_span = expr.span; let mut subexpr_list = vec![expr]; @@ -116,7 +117,7 @@ pub fn rewrite_chain(mut expr: &ast::Expr, let connector = if fits_single_line { String::new() } else { - format!("\n{}", make_indent(indent)) + format!("\n{}", make_indent(indent, context.config)) }; let first_connector = if extend { @@ -145,7 +146,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, span: Span, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option { match expr.node { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { @@ -179,7 +180,7 @@ fn rewrite_method_call(method_name: ast::Ident, span: Span, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option { let type_str = if types.is_empty() { String::new() diff --git a/src/comment.rs b/src/comment.rs index 05117a7cb76..683bf4b650c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -12,10 +12,17 @@ use std::iter; +use Indent; +use config::Config; use string::{StringFormat, rewrite_string}; use utils::make_indent; -pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usize) -> String { +pub fn rewrite_comment(orig: &str, + block_style: bool, + width: usize, + offset: Indent, + config: &Config) + -> String { let s = orig.trim(); // Edge case: block comments. Let's not trim their lines (for now). @@ -33,11 +40,12 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz line_start: line_start, line_end: "", width: max_chars, - offset: offset + opener.len() - line_start.len(), + offset: offset + (opener.len() - line_start.len()), trim_end: true, + config: config, }; - let indent_str = make_indent(offset); + let indent_str = make_indent(offset, config); let line_breaks = s.chars().filter(|&c| c == '\n').count(); let (_, mut s) = s.lines() @@ -288,27 +296,32 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { mod test { use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented}; - // FIXME(#217): prevent string literal from going over the limit. + use Indent; #[test] #[rustfmt_skip] fn format_comments() { - assert_eq!("/* test */", rewrite_comment(" //test", true, 100, 100)); - assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, 0)); + let config = Default::default(); + assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100), + &config)); + assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, + Indent::new(0, 0), &config)); assert_eq!("// A multi line comment\n // between args.", rewrite_comment("// A multi line comment\n // between args.", false, 60, - 12)); + Indent::new(0, 12), + &config)); let input = "// comment"; let expected = "/* com\n \ * men\n \ * t */"; - assert_eq!(expected, rewrite_comment(input, true, 9, 69)); + assert_eq!(expected, rewrite_comment(input, true, 9, Indent::new(0, 69), &config)); - assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100)); + assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, + Indent::new(0, 100), &config)); } // This is probably intended to be a non-test fn, but it is not used. I'm diff --git a/src/config.rs b/src/config.rs index 2ecee9f98fe..c5b777e1d81 100644 --- a/src/config.rs +++ b/src/config.rs @@ -246,6 +246,7 @@ create_config! { format_strings: bool, "Format string literals, or leave as is", chains_overflow_last: bool, "Allow last call in method chain to break the line", take_source_hints: bool, "Retain some formatting characteristics from the source code", + hard_tabs: bool, "Use tab characters for indentation, spaces for alignment", } impl Default for Config { @@ -279,6 +280,7 @@ impl Default for Config { format_strings: true, chains_overflow_last: true, take_source_hints: true, + hard_tabs: false, } } } diff --git a/src/expr.rs b/src/expr.rs index a91c6c38572..3e8401af8b9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -11,6 +11,7 @@ use std::cmp::Ordering; use std::borrow::Borrow; +use Indent; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; @@ -29,7 +30,7 @@ use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; use syntax::visit::Visitor; impl Rewrite for ast::Expr { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { ast::Expr_::ExprVec(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), self.span, context, width, offset) @@ -164,7 +165,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, span: Span, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option where I: Iterator { @@ -201,6 +202,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, h_width: max_item_width, v_width: max_item_width, ends_with_newline: false, + config: context.config, }; let list_str = try_opt!(write_list(&items, &fmt)); @@ -215,7 +217,7 @@ fn rewrite_closure(capture: ast::CaptureClause, span: Span, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option { let mover = if capture == ast::CaptureClause::CaptureByValue { "move " @@ -258,6 +260,7 @@ fn rewrite_closure(capture: ast::CaptureClause, h_width: horizontal_budget, v_width: budget, ends_with_newline: false, + config: context.config, }; let list_str = try_opt!(write_list(&arg_items.collect::>(), &fmt)); let mut prefix = format!("{}|{}|", mover, list_str); @@ -265,7 +268,7 @@ fn rewrite_closure(capture: ast::CaptureClause, if !ret_str.is_empty() { if prefix.contains('\n') { prefix.push('\n'); - prefix.push_str(&make_indent(argument_offset)); + prefix.push_str(&make_indent(argument_offset, context.config)); } else { prefix.push(' '); } @@ -308,18 +311,18 @@ fn rewrite_closure(capture: ast::CaptureClause, .as_ref() .and_then(|body_expr| { if let ast::Expr_::ExprBlock(ref inner) = body_expr.node { - Some(inner.rewrite(&context, 2, 0)) + Some(inner.rewrite(&context, 2, Indent::new(0, 0))) } else { None } }) - .unwrap_or_else(|| body.rewrite(&context, 2, 0)); + .unwrap_or_else(|| body.rewrite(&context, 2, Indent::new(0, 0))); Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } impl Rewrite for ast::Block { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let user_str = context.snippet(self.span); if user_str == "{}" && width >= 2 { return Some(user_str); @@ -341,7 +344,8 @@ impl Rewrite for ast::Block { let prefix = if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() let budget = try_opt!(width.checked_sub(9)); - format!("unsafe {} ", rewrite_comment(trimmed, true, budget, offset + 7)) + format!("unsafe {} ", + rewrite_comment(trimmed, true, budget, offset + 7, context.config)) } else { "unsafe ".to_owned() }; @@ -381,7 +385,7 @@ impl Rewrite for ast::Block { // FIXME(#18): implement pattern formatting impl Rewrite for ast::Pat { - fn rewrite(&self, context: &RewriteContext, _: usize, _: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, _: usize, _: Indent) -> Option { Some(context.snippet(self.span)) } } @@ -447,7 +451,7 @@ impl<'a> Loop<'a> { } impl<'a> Rewrite for Loop<'a> { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let label_string = rewrite_label(self.label); // 2 = " {".len() let inner_width = try_opt!(width.checked_sub(self.keyword.len() + 2 + label_string.len())); @@ -483,7 +487,7 @@ fn rewrite_range(context: &RewriteContext, left: Option<&ast::Expr>, right: Option<&ast::Expr>, width: usize, - offset: usize) + offset: Indent) -> Option { let left_string = match left { Some(expr) => { @@ -513,7 +517,7 @@ fn rewrite_if_else(context: &RewriteContext, else_block_opt: Option<&ast::Expr>, pat: Option<&ast::Pat>, width: usize, - offset: usize, + offset: Indent, allow_single_line: bool) -> Option { // 3 = "if ", 2 = " {" @@ -588,11 +592,11 @@ fn single_line_if_else(context: &RewriteContext, let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); let if_expr = if_node.expr.as_ref().unwrap(); - let if_str = try_opt!(if_expr.rewrite(context, new_width, 0)); + let if_str = try_opt!(if_expr.rewrite(context, new_width, Indent::new(0, 0))); let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = else_node.expr.as_ref().unwrap(); - let else_str = try_opt!(else_expr.rewrite(context, new_width, 0)); + let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::new(0, 0))); // FIXME: this check shouldn't be necessary. Rewrites should either fail // or wrap to a newline when the object does not fit the width. @@ -621,7 +625,7 @@ fn rewrite_match(context: &RewriteContext, cond: &ast::Expr, arms: &[ast::Arm], width: usize, - offset: usize) + offset: Indent) -> Option { if arms.is_empty() { return None; @@ -634,7 +638,7 @@ fn rewrite_match(context: &RewriteContext, let nested_context = context.nested_context(); let arm_indent = nested_context.block_indent + context.overflow_indent; - let arm_indent_str = make_indent(arm_indent); + let arm_indent_str = make_indent(arm_indent, context.config); let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{", @@ -669,7 +673,7 @@ fn rewrite_match(context: &RewriteContext, result.push_str(&arm_indent_str); let arm_str = arm.rewrite(&nested_context, - context.config.max_width - arm_indent, + context.config.max_width - arm_indent.width(), arm_indent); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); @@ -684,7 +688,7 @@ fn rewrite_match(context: &RewriteContext, // match expression, but meh. result.push('\n'); - result.push_str(&make_indent(context.block_indent + context.overflow_indent)); + result.push_str(&make_indent(context.block_indent + context.overflow_indent, context.config)); result.push('}'); Some(result) } @@ -704,9 +708,9 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { // Match arms. impl Rewrite for ast::Arm { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; - let indent_str = make_indent(offset); + let indent_str = make_indent(offset, context.config); // FIXME this is all a bit grotty, would be nice to abstract out the // treatment of attributes. @@ -734,7 +738,7 @@ impl Rewrite for ast::Arm { .map(|p| { p.rewrite(context, pat_budget, - offset + context.config.tab_spaces) + offset.block_indent(context.config.tab_spaces)) }) .collect::>>()); @@ -775,7 +779,12 @@ impl Rewrite for ast::Arm { // Where the next text can start. let mut line_start = last_line_width(&pats_str); if pats_str.find('\n').is_none() { - line_start += offset; + line_start += offset.width(); + } + + let mut line_indent = offset + pats_width; + if vertical { + line_indent = line_indent.block_indent(context.config.tab_spaces); } let comma = if let ast::ExprBlock(_) = body.node { @@ -788,7 +797,7 @@ impl Rewrite for ast::Arm { // 4 = ` => `.len() if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; - if let Some(ref body_str) = body.rewrite(context, budget, line_start + 4) { + if let Some(ref body_str) = body.rewrite(context, budget, line_indent + 4) { if first_line_width(body_str) <= budget { return Some(format!("{}{} => {}{}", attr_str.trim_left(), @@ -810,7 +819,7 @@ impl Rewrite for ast::Arm { Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, - make_indent(offset + context.config.tab_spaces), + make_indent(offset.block_indent(context.config.tab_spaces), context.config), body_str)) } } @@ -819,7 +828,7 @@ impl Rewrite for ast::Arm { fn rewrite_guard(context: &RewriteContext, guard: &Option>, width: usize, - offset: usize, + offset: Indent, // The amount of space used up on this line for the pattern in // the arm (excludes offset). pattern_width: usize) @@ -840,10 +849,11 @@ fn rewrite_guard(context: &RewriteContext, if overhead < width { let cond_str = guard.rewrite(context, width - overhead, - offset + context.config.tab_spaces); + offset.block_indent(context.config.tab_spaces)); if let Some(cond_str) = cond_str { return Some(format!("\n{}if {}", - make_indent(offset + context.config.tab_spaces), + make_indent(offset.block_indent(context.config.tab_spaces), + context.config), cond_str)); } } @@ -862,7 +872,7 @@ fn rewrite_pat_expr(context: &RewriteContext, // *without* trailing space. connector: &str, width: usize, - offset: usize) + offset: Indent) -> Option { let pat_offset = offset + matcher.len(); let mut result = match pat { @@ -898,9 +908,11 @@ fn rewrite_pat_expr(context: &RewriteContext, // The expression won't fit on the current line, jump to next. result.push('\n'); - result.push_str(&make_indent(pat_offset)); + result.push_str(&make_indent(pat_offset, context.config)); - let expr_rewrite = expr.rewrite(context, context.config.max_width - pat_offset, pat_offset); + let expr_rewrite = expr.rewrite(context, + context.config.max_width - pat_offset.width(), + pat_offset); result.push_str(&&try_opt!(expr_rewrite)); Some(result) @@ -909,7 +921,7 @@ fn rewrite_pat_expr(context: &RewriteContext, fn rewrite_string_lit(context: &RewriteContext, span: Span, width: usize, - offset: usize) + offset: Indent) -> Option { if !context.config.format_strings { return Some(context.snippet(span)); @@ -923,6 +935,7 @@ fn rewrite_string_lit(context: &RewriteContext, width: width, offset: offset, trim_end: false, + config: context.config, }; let string_lit = context.snippet(span); @@ -936,7 +949,7 @@ pub fn rewrite_call(context: &RewriteContext, args: &[ptr::P], span: Span, width: usize, - offset: usize) + offset: Indent) -> Option where R: Rewrite { @@ -955,7 +968,7 @@ fn rewrite_call_inner(context: &RewriteContext, args: &[ptr::P], span: Span, width: usize, - offset: usize) + offset: Indent) -> Result where R: Rewrite { @@ -1003,7 +1016,7 @@ fn rewrite_call_inner(context: &RewriteContext, span.lo, span.hi); - let fmt = ListFormatting::for_fn(remaining_width, offset); + let fmt = ListFormatting::for_fn(remaining_width, offset, context.config); let list_str = match write_list(&items.collect::>(), &fmt) { Some(str) => str, None => return Err(Ordering::Less), @@ -1015,9 +1028,9 @@ fn rewrite_call_inner(context: &RewriteContext, fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, - offset: usize) + offset: Indent) -> Option { - debug!("rewrite_paren, width: {}, offset: {}", width, offset); + debug!("rewrite_paren, width: {}, offset: {:?}", width, offset); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr. let subexpr_str = subexpr.rewrite(context, try_opt!(width.checked_sub(2)), offset + 1); @@ -1031,9 +1044,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, base: Option<&'a ast::Expr>, span: Span, width: usize, - offset: usize) + offset: Indent) -> Option { - debug!("rewrite_struct_lit: width {}, offset {}", width, offset); + debug!("rewrite_struct_lit: width {}, offset {:?}", width, offset); assert!(!fields.is_empty() || base.is_some()); enum StructLitField<'a> { @@ -1054,8 +1067,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, StructLitStyle::Block => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. - let indent = context.block_indent + context.config.tab_spaces; - let v_budget = context.config.max_width.checked_sub(indent).unwrap_or(0); + let indent = context.block_indent.block_indent(context.config.tab_spaces); + let v_budget = context.config.max_width.checked_sub(indent.width()).unwrap_or(0); (indent, v_budget) } }; @@ -1121,12 +1134,15 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, h_width: h_budget, v_width: v_budget, ends_with_newline: false, + config: context.config, }; let fields_str = try_opt!(write_list(&items.collect::>(), &fmt)); let format_on_newline = || { - let inner_indent = make_indent(context.block_indent + context.config.tab_spaces); - let outer_indent = make_indent(context.block_indent); + let inner_indent = make_indent(context.block_indent + .block_indent(context.config.tab_spaces), + context.config); + let outer_indent = make_indent(context.block_indent, context.config); Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) }; @@ -1143,7 +1159,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, - offset: usize) + offset: Indent) -> Option { let name = &field.ident.node.to_string(); let overhead = name.len() + 2; @@ -1156,9 +1172,9 @@ fn rewrite_tuple_lit(context: &RewriteContext, items: &[ptr::P], span: Span, width: usize, - offset: usize) + offset: Indent) -> Option { - debug!("rewrite_tuple_lit: width: {}, offset: {}", width, offset); + debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset); let indent = offset + 1; // In case of length 1, need a trailing comma if items.len() == 1 { @@ -1173,7 +1189,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, |item| item.span.lo, |item| item.span.hi, |item| { - let inner_width = context.config.max_width - indent - 1; + let inner_width = context.config.max_width - indent.width() - 1; item.rewrite(context, inner_width, indent) .unwrap_or(context.snippet(item.span)) }, @@ -1181,7 +1197,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, span.hi - BytePos(1)); let budget = try_opt!(width.checked_sub(2)); - let fmt = ListFormatting::for_fn(budget, indent); + let fmt = ListFormatting::for_fn(budget, indent, context.config); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); Some(format!("({})", list_str)) @@ -1192,7 +1208,7 @@ fn rewrite_binary_op(context: &RewriteContext, lhs: &ast::Expr, rhs: &ast::Expr, width: usize, - offset: usize) + offset: Indent) -> Option { // FIXME: format comments between operands and operator @@ -1233,11 +1249,13 @@ fn rewrite_binary_op(context: &RewriteContext, // We have to use multiple lines. // Re-evaluate the lhs because we have more space now: - let budget = try_opt!(context.config.max_width.checked_sub(offset + 1 + operator_str.len())); + let budget = try_opt!(context.config + .max_width + .checked_sub(offset.width() + 1 + operator_str.len())); Some(format!("{} {}\n{}{}", try_opt!(lhs.rewrite(context, budget, offset)), operator_str, - make_indent(offset), + make_indent(offset, context.config), rhs_result)) } @@ -1245,7 +1263,7 @@ fn rewrite_unary_op(context: &RewriteContext, op: &ast::UnOp, expr: &ast::Expr, width: usize, - offset: usize) + offset: Indent) -> Option { // For some reason, an UnOp is not spanned like BinOp! let operator_str = match *op { @@ -1265,7 +1283,7 @@ fn rewrite_assignment(context: &RewriteContext, rhs: &ast::Expr, op: Option<&ast::BinOp>, width: usize, - offset: usize) + offset: Indent) -> Option { let operator_str = match op { Some(op) => context.snippet(op.span), @@ -1285,7 +1303,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, lhs: S, ex: &ast::Expr, width: usize, - offset: usize) + offset: Indent) -> Option { let mut result = lhs.into(); @@ -1301,13 +1319,14 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, None => { // Expression did not fit on the same line as the identifier. Retry // on the next line. - let new_offset = offset + context.config.tab_spaces; - result.push_str(&format!("\n{}", make_indent(new_offset))); + let new_offset = offset.block_indent(context.config.tab_spaces); + result.push_str(&format!("\n{}", make_indent(new_offset, context.config))); // FIXME: we probably should related max_width to width instead of config.max_width // where is the 1 coming from anyway? - let max_width = try_opt!(context.config.max_width.checked_sub(new_offset + 1)); - let overflow_context = context.overflow_context(context.config.tab_spaces); + let max_width = try_opt!(context.config.max_width.checked_sub(new_offset.width() + 1)); + let rhs_indent = Indent::new(context.config.tab_spaces, 0); + let overflow_context = context.overflow_context(rhs_indent); let rhs = ex.rewrite(&overflow_context, max_width, new_offset); result.push_str(&&try_opt!(rhs)); diff --git a/src/imports.rs b/src/imports.rs index 1d215d022d1..f5f81015efb 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use Indent; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use utils::span_after; use rewrite::{Rewrite, RewriteContext}; @@ -20,7 +21,7 @@ use syntax::codemap::Span; impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => { Some(String::new()) @@ -68,7 +69,7 @@ fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { // Pretty prints a multi-item import. // Assumes that path_list.len() > 0. pub fn rewrite_use_list(width: usize, - offset: usize, + offset: Indent, path: &ast::Path, path_list: &[ast::PathListItem], span: Span, @@ -105,6 +106,7 @@ pub fn rewrite_use_list(width: usize, // (loose 1 column (";")) v_width: remaining_width, ends_with_newline: false, + config: context.config, }; let mut items = { diff --git a/src/items.rs b/src/items.rs index a14310e94ef..ae55fdf4c29 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,6 +10,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. +use Indent; use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, end_typaram, wrap_str}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; @@ -26,7 +27,7 @@ use syntax::parse::token; impl<'a> FmtVisitor<'a> { pub fn visit_let(&mut self, local: &ast::Local, span: Span) { - self.format_missing_with_indent(span.lo); + self.format_missing_with_indent(span.lo, self.config); // String that is placed within the assignment pattern and expression. let infix = { @@ -34,8 +35,7 @@ impl<'a> FmtVisitor<'a> { if let Some(ref ty) = local.ty { infix.push_str(": "); - // FIXME: silly width, indent - infix.push_str(&ty.rewrite(&self.get_context(), 1000, 0).unwrap()); + infix.push_str(&ty.rewrite(&self.get_context(), 1000, Indent::new(0, 0)).unwrap()); } if local.init.is_some() { @@ -52,12 +52,13 @@ impl<'a> FmtVisitor<'a> { let mut result = "let ".to_owned(); let pattern_offset = self.block_indent + result.len() + infix.len(); // 1 = ; - let pattern_width = match self.config.max_width.checked_sub(pattern_offset + 1) { + let pattern_width = self.config.max_width.checked_sub(pattern_offset.width() + 1); + let pattern_width = match pattern_width { Some(width) => width, None => return, }; - match local.pat.rewrite(&context, pattern_offset, pattern_width) { + match local.pat.rewrite(&context, pattern_width, pattern_offset) { Some(ref pat_string) => result.push_str(pat_string), None => return, } @@ -65,7 +66,8 @@ impl<'a> FmtVisitor<'a> { result.push_str(&infix); if let Some(ref ex) = local.init { - let max_width = match self.config.max_width.checked_sub(context.block_indent + 1) { + let max_width = self.config.max_width.checked_sub(context.block_indent.width() + 1); + let max_width = match max_width { Some(width) => width, None => return, }; @@ -88,7 +90,7 @@ impl<'a> FmtVisitor<'a> { } pub fn rewrite_fn(&mut self, - indent: usize, + indent: Indent, ident: ast::Ident, fd: &ast::FnDecl, explicit_self: Option<&ast::ExplicitSelf>, @@ -124,7 +126,7 @@ impl<'a> FmtVisitor<'a> { // this. if newline_brace { result.push('\n'); - result.push_str(&make_indent(indent)); + result.push_str(&make_indent(indent, self.config)); } else { result.push(' '); } @@ -133,7 +135,7 @@ impl<'a> FmtVisitor<'a> { } pub fn rewrite_required_fn(&mut self, - indent: usize, + indent: Indent, ident: ast::Ident, sig: &ast::MethodSig, span: Span) @@ -160,7 +162,7 @@ impl<'a> FmtVisitor<'a> { } fn rewrite_fn_base(&mut self, - indent: usize, + indent: Indent, ident: ast::Ident, fd: &ast::FnDecl, explicit_self: Option<&ast::ExplicitSelf>, @@ -207,13 +209,15 @@ impl<'a> FmtVisitor<'a> { result.push_str(&generics_str); let context = self.get_context(); - let ret_str = fd.output.rewrite(&context, self.config.max_width - indent, indent).unwrap(); + let ret_str = fd.output + .rewrite(&context, self.config.max_width - indent.width(), indent) + .unwrap(); // Args. let (one_line_budget, multi_line_budget, mut arg_indent) = self.compute_budgets_for_args(&result, indent, ret_str.len(), newline_brace); - debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {}", + debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", one_line_budget, multi_line_budget, arg_indent); @@ -222,17 +226,17 @@ impl<'a> FmtVisitor<'a> { if one_line_budget <= 0 { if self.config.fn_args_paren_newline { result.push('\n'); - result.push_str(&make_indent(arg_indent)); + result.push_str(&make_indent(arg_indent, self.config)); arg_indent = arg_indent + 1; // extra space for `(` result.push('('); } else { result.push_str("(\n"); - result.push_str(&make_indent(arg_indent)); + result.push_str(&make_indent(arg_indent, self.config)); } } else if self.config.fn_args_layout == StructLitStyle::Block { - arg_indent = indent + self.config.tab_spaces; + arg_indent = indent.block_indent(self.config.tab_spaces); result.push_str("(\n"); - result.push_str(&make_indent(arg_indent)); + result.push_str(&make_indent(arg_indent, self.config)); } else { result.push('('); } @@ -266,7 +270,7 @@ impl<'a> FmtVisitor<'a> { // Unless we are formatting args like a block, in which case there // should always be room for the return type. if (result.contains("\n") || - result.len() + indent + ret_str.len() > self.config.max_width) && + result.len() + indent.width() + ret_str.len() > self.config.max_width) && self.config.fn_args_layout != StructLitStyle::Block { let indent = match self.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, @@ -277,7 +281,7 @@ impl<'a> FmtVisitor<'a> { }; result.push('\n'); - result.push_str(&make_indent(indent)); + result.push_str(&make_indent(indent, self.config)); } else { result.push(' '); } @@ -326,8 +330,8 @@ impl<'a> FmtVisitor<'a> { explicit_self: Option<&ast::ExplicitSelf>, one_line_budget: usize, multi_line_budget: usize, - indent: usize, - arg_indent: usize, + indent: Indent, + arg_indent: Indent, span: Span) -> Option { let context = self.get_context(); @@ -386,7 +390,7 @@ impl<'a> FmtVisitor<'a> { let indent = match self.config.fn_arg_indent { BlockIndentStyle::Inherit => indent, - BlockIndentStyle::Tabbed => indent + self.config.tab_spaces, + BlockIndentStyle::Tabbed => indent.block_indent(self.config.tab_spaces), BlockIndentStyle::Visual => arg_indent, }; @@ -398,6 +402,7 @@ impl<'a> FmtVisitor<'a> { h_width: one_line_budget, v_width: multi_line_budget, ends_with_newline: false, + config: self.config, }; write_list(&arg_items, &fmt) @@ -405,16 +410,16 @@ impl<'a> FmtVisitor<'a> { fn compute_budgets_for_args(&self, result: &str, - indent: usize, + indent: Indent, ret_str_len: usize, newline_brace: bool) - -> (usize, usize, usize) { + -> (usize, usize, Indent) { let mut budgets = None; // Try keeping everything on the same line if !result.contains("\n") { // 3 = `() `, space is before ret_string - let mut used_space = indent + result.len() + ret_str_len + 3; + let mut used_space = indent.width() + result.len() + ret_str_len + 3; if !newline_brace { used_space += 2; } @@ -425,7 +430,7 @@ impl<'a> FmtVisitor<'a> { }; // 2 = `()` - let used_space = indent + result.len() + 2; + let used_space = indent.width() + result.len() + 2; let max_space = self.config.ideal_width + self.config.leeway; debug!("compute_budgets_for_args: used_space: {}, max_space: {}", used_space, @@ -439,8 +444,8 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. if let None = budgets { - let new_indent = indent + self.config.tab_spaces; - let used_space = new_indent + 2; // account for `(` and `)` + let new_indent = indent.block_indent(self.config.tab_spaces); + let used_space = new_indent.width() + 2; // account for `(` and `)` let max_space = self.config.ideal_width + self.config.leeway; if used_space > max_space { // Whoops! bankrupt. @@ -475,13 +480,14 @@ impl<'a> FmtVisitor<'a> { let generics_str = self.format_generics(generics, " {", self.block_indent, - self.block_indent + self.config.tab_spaces, + self.block_indent + .block_indent(self.config.tab_spaces), codemap::mk_sp(span.lo, body_start)) .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; - self.block_indent += self.config.tab_spaces; + self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); for (i, f) in enum_def.variants.iter().enumerate() { let next_span_start: BytePos = if i == enum_def.variants.len() - 1 { span.hi @@ -491,9 +497,10 @@ impl<'a> FmtVisitor<'a> { self.visit_variant(f, i == enum_def.variants.len() - 1, next_span_start); } - self.block_indent -= self.config.tab_spaces; + self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); - self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32)); + self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32), + self.config); self.buffer.push_str("}"); } @@ -503,7 +510,7 @@ impl<'a> FmtVisitor<'a> { return; } - self.format_missing_with_indent(field.span.lo); + self.format_missing_with_indent(field.span.lo, self.config); let result = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { @@ -521,7 +528,9 @@ impl<'a> FmtVisitor<'a> { |arg| { // FIXME silly width, indent arg.ty - .rewrite(&self.get_context(), 1000, 0) + .rewrite(&self.get_context(), + 1000, + Indent::new(0, 0)) .unwrap() }, span_after(field.span, "(", self.codemap), @@ -536,7 +545,7 @@ impl<'a> FmtVisitor<'a> { } else { 0 }; - let budget = self.config.ideal_width - indent - comma_cost - 1; // 1 = ) + let budget = self.config.ideal_width - indent.width() - comma_cost - 1; // 1 = ) let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, @@ -546,6 +555,7 @@ impl<'a> FmtVisitor<'a> { h_width: budget, v_width: budget, ends_with_newline: true, + config: self.config, }; let list_str = match write_list(&items.collect::>(), &fmt) { Some(list_str) => list_str, @@ -601,7 +611,7 @@ impl<'a> FmtVisitor<'a> { struct_def: &ast::StructDef, generics: Option<&ast::Generics>, span: Span, - offset: usize) + offset: Indent) -> Option { let mut result = String::with_capacity(1024); @@ -654,7 +664,7 @@ impl<'a> FmtVisitor<'a> { span.hi); // 2 terminators and a semicolon - let used_budget = offset + header_str.len() + generics_str.len() + 3; + let used_budget = offset.width() + header_str.len() + generics_str.len() + 3; // Conservative approximation let single_line_cost = (span.hi - struct_def.fields[0].span.lo).0; @@ -662,7 +672,7 @@ impl<'a> FmtVisitor<'a> { single_line_cost as usize + used_budget > self.config.max_width; let tactic = if break_line { - let indentation = make_indent(offset + self.config.tab_spaces); + let indentation = make_indent(offset.block_indent(self.config.tab_spaces), self.config); result.push('\n'); result.push_str(&indentation); @@ -672,15 +682,16 @@ impl<'a> FmtVisitor<'a> { }; // 1 = , - let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1; + let budget = self.config.ideal_width - offset.width() + self.config.tab_spaces - 1; let fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: self.config.struct_trailing_comma, - indent: offset + self.config.tab_spaces, + indent: offset.block_indent(self.config.tab_spaces), h_width: self.config.max_width, v_width: budget, ends_with_newline: true, + config: self.config, }; let list_str = write_list(&items.collect::>(), &fmt).unwrap(); @@ -688,7 +699,7 @@ impl<'a> FmtVisitor<'a> { if break_line { result.push('\n'); - result.push_str(&make_indent(offset)); + result.push_str(&make_indent(offset, self.config)); } result.push_str(terminator); @@ -727,8 +738,8 @@ impl<'a> FmtVisitor<'a> { fn format_generics(&self, generics: &ast::Generics, opener: &str, - offset: usize, - generics_offset: usize, + offset: Indent, + generics_offset: Indent, span: Span) -> Option { let mut result = try_opt!(self.rewrite_generics(generics, offset, generics_offset, span)); @@ -740,7 +751,7 @@ impl<'a> FmtVisitor<'a> { Density::Tall, span.hi)); result.push_str(&where_clause_str); - result.push_str(&make_indent(self.block_indent)); + result.push_str(&make_indent(self.block_indent, self.config)); result.push('\n'); result.push_str(opener.trim()); } else { @@ -765,18 +776,18 @@ impl<'a> FmtVisitor<'a> { ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; // FIXME silly width, indent - let typ = field.node.ty.rewrite(&self.get_context(), 1000, 0).unwrap(); + let typ = field.node.ty.rewrite(&self.get_context(), 1000, Indent::new(0, 0)).unwrap(); let indent = self.block_indent + self.config.tab_spaces; let mut attr_str = field.node .attrs .rewrite(&self.get_context(), - self.config.max_width - indent, + self.config.max_width - indent.width(), indent) .unwrap(); if !attr_str.is_empty() { attr_str.push('\n'); - attr_str.push_str(&make_indent(indent)); + attr_str.push_str(&make_indent(indent, self.config)); } match name { @@ -787,8 +798,8 @@ impl<'a> FmtVisitor<'a> { fn rewrite_generics(&self, generics: &ast::Generics, - offset: usize, - generics_offset: usize, + offset: Indent, + generics_offset: Indent, span: Span) -> Option { // FIXME: convert bounds to where clauses where they get too big or if @@ -801,12 +812,12 @@ impl<'a> FmtVisitor<'a> { let offset = match self.config.generics_indent { BlockIndentStyle::Inherit => offset, - BlockIndentStyle::Tabbed => offset + self.config.tab_spaces, + BlockIndentStyle::Tabbed => offset.block_indent(self.config.tab_spaces), // 1 = < BlockIndentStyle::Visual => generics_offset + 1, }; - let h_budget = self.config.max_width - generics_offset - 2; + let h_budget = self.config.max_width - generics_offset.width() - 2; // TODO: might need to insert a newline if the generics are really long. // Strings for the generics. @@ -841,7 +852,7 @@ impl<'a> FmtVisitor<'a> { item.item = ty; } - let fmt = ListFormatting::for_fn(h_budget, offset); + let fmt = ListFormatting::for_fn(h_budget, offset, self.config); let list_str = try_opt!(write_list(&items, &fmt)); Some(format!("<{}>", list_str)) @@ -850,7 +861,7 @@ impl<'a> FmtVisitor<'a> { fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, config: &Config, - indent: usize, + indent: Indent, density: Density, span_end: BytePos) -> Option { @@ -859,22 +870,23 @@ impl<'a> FmtVisitor<'a> { } let extra_indent = match self.config.where_indent { - BlockIndentStyle::Inherit => 0, - BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => config.tab_spaces, + BlockIndentStyle::Inherit => Indent::new(0, 0), + BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => Indent::new(config.tab_spaces, + 0), }; let context = self.get_context(); let offset = match self.config.where_pred_indent { BlockIndentStyle::Inherit => indent + extra_indent, - BlockIndentStyle::Tabbed => indent + extra_indent + config.tab_spaces, + BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config.tab_spaces), // 6 = "where ".len() BlockIndentStyle::Visual => indent + extra_indent + 6, }; // FIXME: if where_pred_indent != Visual, then the budgets below might // be out by a char or two. - let budget = self.config.ideal_width + self.config.leeway - offset; + let budget = self.config.ideal_width + self.config.leeway - offset.width(); let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; let items = itemize_list(self.codemap, where_clause.predicates.iter(), @@ -896,13 +908,16 @@ impl<'a> FmtVisitor<'a> { h_width: budget, v_width: budget, ends_with_newline: true, + config: self.config, }; let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); // 9 = " where ".len() + " {".len() if density == Density::Tall || preds_str.contains('\n') || - indent + 9 + preds_str.len() > self.config.max_width { - Some(format!("\n{}where {}", make_indent(indent + extra_indent), preds_str)) + indent.width() + 9 + preds_str.len() > self.config.max_width { + Some(format!("\n{}where {}", + make_indent(indent + extra_indent, self.config), + preds_str)) } else { Some(format!(" where {}", preds_str)) } @@ -910,7 +925,7 @@ impl<'a> FmtVisitor<'a> { } impl Rewrite for ast::FunctionRetTy { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { ast::FunctionRetTy::DefaultReturn(_) => Some(String::new()), ast::FunctionRetTy::NoReturn(_) => { @@ -929,7 +944,7 @@ impl Rewrite for ast::FunctionRetTy { } impl Rewrite for ast::Arg { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if is_named_arg(self) { if let ast::Ty_::TyInfer = self.ty.node { wrap_str(pprust::pat_to_string(&self.pat), context.config.max_width, width, offset) diff --git a/src/lib.rs b/src/lib.rs index 7b6adeba2c8..2ca206665e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,7 @@ use syntax::ast; use syntax::codemap::CodeMap; use syntax::diagnostics; +use std::ops::{Add, Sub}; use std::path::PathBuf; use std::collections::HashMap; use std::fmt; @@ -80,6 +81,79 @@ const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; +#[derive(Copy, Clone, Debug)] +pub struct Indent { + block_indent: usize, + alignment: usize, +} + +impl Indent { + pub fn new(block_indent: usize, alignment: usize) -> Indent { + Indent { block_indent: block_indent, alignment: alignment } + } + + pub fn block_indent(mut self, block_indent: usize) -> Indent { + self.block_indent += block_indent; + self + } + + pub fn block_unindent(mut self, block_indent: usize) -> Indent { + self.block_indent -= block_indent; + self + } + + pub fn width(&self) -> usize { + self.block_indent + self.alignment + } + + pub fn to_string(&self, config: &Config) -> String { + let (num_tabs, num_spaces) = if config.hard_tabs { + (self.block_indent / config.tab_spaces, self.alignment) + } else { + (0, self.block_indent + self.alignment) + }; + let num_chars = num_tabs + num_spaces; + let mut indent = String::with_capacity(num_chars); + for _ in 0..num_tabs { + indent.push('\t') + } + for _ in 0..num_spaces { + indent.push(' ') + } + indent + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: Indent) -> Indent { + Indent { + block_indent: self.block_indent + rhs.block_indent, + alignment: self.alignment + rhs.alignment, + } + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: Indent) -> Indent { + Indent { + block_indent: self.block_indent - rhs.block_indent, + alignment: self.alignment - rhs.alignment, + } + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: usize) -> Indent { + Indent { block_indent: self.block_indent, alignment: self.alignment + rhs } + } +} + #[derive(Copy, Clone)] pub enum WriteMode { // Backups the original file and overwrites the orignal. diff --git a/src/lists.rs b/src/lists.rs index 2b85c994581..40da7af198e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -13,8 +13,10 @@ use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; +use Indent; use utils::{round_up_to_power_of_two, make_indent, wrap_str}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; +use config::Config; #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { @@ -44,7 +46,7 @@ pub struct ListFormatting<'a> { pub tactic: ListTactic, pub separator: &'a str, pub trailing_separator: SeparatorTactic, - pub indent: usize, + pub indent: Indent, // Available width if we layout horizontally. pub h_width: usize, // Available width if we layout vertically @@ -52,10 +54,11 @@ pub struct ListFormatting<'a> { // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. pub ends_with_newline: bool, + pub config: &'a Config, } impl<'a> ListFormatting<'a> { - pub fn for_fn(width: usize, offset: usize) -> ListFormatting<'a> { + pub fn for_fn(width: usize, offset: Indent, config: &'a Config) -> ListFormatting<'a> { ListFormatting { tactic: ListTactic::HorizontalVertical, separator: ",", @@ -64,6 +67,7 @@ impl<'a> ListFormatting<'a> { h_width: width, v_width: width, ends_with_newline: false, + config: config, } } } @@ -146,12 +150,12 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let alloc_width = if tactic == ListTactic::Horizontal { total_width + total_sep_len } else { - total_width + items.len() * (formatting.indent + 1) + total_width + items.len() * (formatting.indent.width() + 1) }; let mut result = String::with_capacity(round_up_to_power_of_two(alloc_width)); let mut line_len = 0; - let indent_str = &make_indent(formatting.indent); + let indent_str = &make_indent(formatting.indent, formatting.config); for (i, item) in items.iter().enumerate() { let first = i == 0; let last = i == items.len() - 1; @@ -196,7 +200,8 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let block_mode = tactic != ListTactic::Vertical; // Width restriction is only relevant in vertical mode. let max_width = formatting.v_width; - result.push_str(&rewrite_comment(comment, block_mode, max_width, formatting.indent)); + result.push_str(&rewrite_comment(comment, block_mode, max_width, formatting.indent, + formatting.config)); if tactic == ListTactic::Vertical { result.push('\n'); @@ -206,14 +211,18 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op } } - let max_width = formatting.indent + formatting.v_width; + let max_width = formatting.indent.width() + formatting.v_width; let item_str = wrap_str(&item.item[..], max_width, formatting.v_width, formatting.indent); result.push_str(&&try_opt!(item_str)); // Post-comments if tactic != ListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = rewrite_comment(comment, true, formatting.v_width, 0); + let formatted_comment = rewrite_comment(comment, + true, + formatting.v_width, + Indent::new(0, 0), + formatting.config); result.push(' '); result.push_str(&formatted_comment); @@ -226,14 +235,19 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op if tactic == ListTactic::Vertical && item.post_comment.is_some() { // 1 = space between item and comment. let width = formatting.v_width.checked_sub(item_width + 1).unwrap_or(1); - let offset = formatting.indent + item_width + 1; + let mut offset = formatting.indent; + offset.alignment += item_width + 1; let comment = item.post_comment.as_ref().unwrap(); // Use block-style only for the last item or multiline comments. let block_style = !formatting.ends_with_newline && last || comment.trim().contains('\n') || comment.trim().len() > width; - let formatted_comment = rewrite_comment(comment, block_style, width, offset); + let formatted_comment = rewrite_comment(comment, + block_style, + width, + offset, + formatting.config); result.push(' '); result.push_str(&formatted_comment); diff --git a/src/macros.rs b/src/macros.rs index dd742ad46c8..8c38326ee8a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -25,6 +25,7 @@ use syntax::ast; use syntax::parse::token::{Eof, Comma, Token}; use syntax::parse::{ParseSess, tts_to_parser}; +use Indent; use rewrite::RewriteContext; use expr::{rewrite_call, rewrite_array}; use comment::FindUncommented; @@ -46,7 +47,7 @@ enum MacroStyle { pub fn rewrite_macro(mac: &ast::Mac, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option { let ast::Mac_::MacInvocTT(ref path, ref tt_vec, _) = mac.node; let style = macro_style(mac, context); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 535fc4c8ad9..c8da3e76b63 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use config::Config; use utils::make_indent; use visitor::FmtVisitor; @@ -20,15 +21,15 @@ impl<'a> FmtVisitor<'a> { self.format_missing_inner(end, |this, last_snippet, _| this.buffer.push_str(last_snippet)) } - pub fn format_missing_with_indent(&mut self, end: BytePos) { + pub fn format_missing_with_indent(&mut self, end: BytePos, config: &Config) { self.format_missing_inner(end, |this, last_snippet, snippet| { this.buffer.push_str(last_snippet.trim_right()); if last_snippet == snippet { - // No new lines in the snippet. + // No new lines in the snippet. this.buffer.push_str("\n"); } - let indent = make_indent(this.block_indent); + let indent = make_indent(this.block_indent, config); this.buffer.push_str(&indent); }) } diff --git a/src/rewrite.rs b/src/rewrite.rs index 49c09ac53d1..2e0f5691d2e 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -12,6 +12,7 @@ use syntax::codemap::{CodeMap, Span}; +use Indent; use config::Config; pub trait Rewrite { @@ -22,7 +23,7 @@ pub trait Rewrite { /// `width` is the maximum number of characters on the last line /// (excluding offset). The width of other lines is not limited by /// `width`. - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option; + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option; } pub struct RewriteContext<'a> { @@ -30,12 +31,12 @@ pub struct RewriteContext<'a> { pub config: &'a Config, // Indentation due to nesting of blocks. - pub block_indent: usize, + pub block_indent: Indent, // *Extra* indentation due to overflowing to the next line, e.g., // let foo = // bar(); // The extra 4 spaces when formatting `bar()` is overflow_indent. - pub overflow_indent: usize, + pub overflow_indent: Indent, } impl<'a> RewriteContext<'a> { @@ -43,12 +44,12 @@ impl<'a> RewriteContext<'a> { RewriteContext { codemap: self.codemap, config: self.config, - block_indent: self.block_indent + self.config.tab_spaces, + block_indent: self.block_indent.block_indent(self.config.tab_spaces), overflow_indent: self.overflow_indent, } } - pub fn overflow_context(&self, overflow: usize) -> RewriteContext<'a> { + pub fn overflow_context(&self, overflow: Indent) -> RewriteContext<'a> { RewriteContext { codemap: self.codemap, config: self.config, diff --git a/src/string.rs b/src/string.rs index 5e5af61faf5..3da0a5f4a25 100644 --- a/src/string.rs +++ b/src/string.rs @@ -13,6 +13,8 @@ use unicode_segmentation::UnicodeSegmentation; use regex::Regex; +use Indent; +use config::Config; use utils::{make_indent, round_up_to_power_of_two}; use MIN_STRING; @@ -23,8 +25,9 @@ pub struct StringFormat<'a> { pub line_start: &'a str, pub line_end: &'a str, pub width: usize, - pub offset: usize, + pub offset: Indent, pub trim_end: bool, + pub config: &'a Config, } // TODO: simplify this! @@ -36,7 +39,7 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let indent = make_indent(fmt.offset); + let indent = make_indent(fmt.offset, fmt.config); let indent = &indent; let mut cur_start = 0; diff --git a/src/types.rs b/src/types.rs index e52909b0d5c..9ba50a59cd9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -12,12 +12,13 @@ use syntax::ast; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; +use Indent; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after}; impl Rewrite for ast::Path { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { rewrite_path(context, None, self, width, offset) } } @@ -27,7 +28,7 @@ pub fn rewrite_path(context: &RewriteContext, qself: Option<&ast::QSelf>, path: &ast::Path, width: usize, - offset: usize) + offset: Indent) -> Option { let skip_count = qself.map(|x| x.position).unwrap_or(0); @@ -80,7 +81,7 @@ fn rewrite_path_segments<'a, I>(mut buffer: String, span_hi: BytePos, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option where I: Iterator { @@ -128,7 +129,7 @@ impl<'a> SegmentParam<'a> { impl<'a> Rewrite for SegmentParam<'a> { // FIXME: doesn't always use width, offset. - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { Some(match *self { SegmentParam::LifeTime(ref lt) => { pprust::lifetime_to_string(lt) @@ -186,7 +187,7 @@ fn rewrite_segment(segment: &ast::PathSegment, span_hi: BytePos, context: &RewriteContext, width: usize, - offset: usize) + offset: Indent) -> Option { let ident_len = segment.identifier.to_string().len(); let width = try_opt!(width.checked_sub(ident_len)); @@ -229,7 +230,7 @@ fn rewrite_segment(segment: &ast::PathSegment, list_lo, span_hi); - let fmt = ListFormatting::for_fn(list_width, offset + extra_offset); + let fmt = ListFormatting::for_fn(list_width, offset + extra_offset, context.config); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); // Update position of last bracket. @@ -257,7 +258,7 @@ fn rewrite_segment(segment: &ast::PathSegment, let budget = try_opt!(width.checked_sub(output.len() + 2)); // 1 for ( - let fmt = ListFormatting::for_fn(budget, offset + 1); + let fmt = ListFormatting::for_fn(budget, offset + 1, context.config); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); format!("({}){}", list_str, output) @@ -269,7 +270,7 @@ fn rewrite_segment(segment: &ast::PathSegment, } impl Rewrite for ast::WherePredicate { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { // TODO: dead spans? // TODO: don't assume we'll always fit on one line... Some(match *self { @@ -340,7 +341,7 @@ impl Rewrite for ast::WherePredicate { } impl Rewrite for ast::LifetimeDef { - fn rewrite(&self, _: &RewriteContext, _: usize, _: usize) -> Option { + fn rewrite(&self, _: &RewriteContext, _: usize, _: Indent) -> Option { if self.bounds.is_empty() { Some(pprust::lifetime_to_string(&self.lifetime)) } else { @@ -356,7 +357,7 @@ impl Rewrite for ast::LifetimeDef { } impl Rewrite for ast::TyParamBound { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { tref.rewrite(context, width, offset) @@ -372,7 +373,7 @@ impl Rewrite for ast::TyParamBound { } impl Rewrite for ast::TyParamBounds { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let strs: Vec<_> = self.iter() .map(|b| b.rewrite(context, width, offset).unwrap()) .collect(); @@ -382,7 +383,7 @@ impl Rewrite for ast::TyParamBounds { // FIXME: this assumes everything will fit on one line impl Rewrite for ast::TyParam { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let mut result = String::with_capacity(128); result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { @@ -407,7 +408,7 @@ impl Rewrite for ast::TyParam { // FIXME: this assumes everything will fit on one line impl Rewrite for ast::PolyTraitRef { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if !self.bound_lifetimes.is_empty() { let lifetime_str = self.bound_lifetimes .iter() @@ -430,7 +431,7 @@ impl Rewrite for ast::PolyTraitRef { impl Rewrite for ast::Ty { // FIXME doesn't always use width, offset - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { ast::TyPath(None, ref p) => { p.rewrite(context, width, offset) diff --git a/src/utils.rs b/src/utils.rs index 42d1151ba38..3843e75973e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -13,17 +13,19 @@ use std::cmp::Ordering; use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; use syntax::codemap::{CodeMap, Span, BytePos}; +use Indent; use comment::FindUncommented; +use config::Config; use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; // Computes the length of a string's last line, minus offset. #[inline] -pub fn extra_offset(text: &str, offset: usize) -> usize { +pub fn extra_offset(text: &str, offset: Indent) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => text.len() - idx - 1 - offset, + Some(idx) => text.len() - idx - 1 - offset.width(), None => text.len(), } } @@ -36,12 +38,8 @@ pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { } #[inline] -pub fn make_indent(width: usize) -> String { - let mut indent = String::with_capacity(width); - for _ in 0..width { - indent.push(' ') - } - indent +pub fn make_indent(indent: Indent, config: &Config) -> String { + indent.to_string(config) } #[inline] @@ -186,7 +184,7 @@ macro_rules! try_opt { // Wraps string-like values in an Option. Returns Some when the string adheres // to the Rewrite constraints defined for the Rewrite trait and else otherwise. -pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usize) -> Option { +pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: Indent) -> Option { { let snippet = s.as_ref(); @@ -197,7 +195,7 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usi // The caller of this function has already placed `offset` // characters on the first line. - let first_line_max_len = try_opt!(max_width.checked_sub(offset)); + let first_line_max_len = try_opt!(max_width.checked_sub(offset.width())); if lines.next().unwrap().len() > first_line_max_len { return None; } @@ -211,7 +209,7 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usi // indentation. // A special check for the last line, since the caller may // place trailing characters on this line. - if snippet.lines().rev().next().unwrap().len() > offset + width { + if snippet.lines().rev().next().unwrap().len() > offset.width() + width { return None; } } @@ -221,7 +219,7 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: usi } impl Rewrite for String { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { wrap_str(self, context.config.max_width, width, offset).map(ToOwned::to_owned) } } diff --git a/src/visitor.rs b/src/visitor.rs index 1e3ebf71cef..d0a5df12221 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -14,6 +14,7 @@ use syntax::visit; use strings::string_buffer::StringBuffer; +use Indent; use utils; use config::Config; use rewrite::{Rewrite, RewriteContext}; @@ -25,7 +26,7 @@ pub struct FmtVisitor<'a> { pub buffer: StringBuffer, pub last_pos: BytePos, // TODO: RAII util for indenting - pub block_indent: usize, + pub block_indent: Indent, pub config: &'a Config, } @@ -39,7 +40,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.format_missing(ex.span.lo); let offset = self.buffer.cur_offset(); - let rewrite = ex.rewrite(&self.get_context(), self.config.max_width - offset, offset); + // FIXME: We put the entire offset into the block_indent, which might not be correct in all + // situations. + let rewrite = ex.rewrite(&self.get_context(), + self.config.max_width - offset, + Indent::new(offset, 0)); if let Some(new_str) = rewrite { self.buffer.push_str(&new_str); @@ -56,7 +61,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { - self.format_missing_with_indent(stmt.span.lo); + self.format_missing_with_indent(stmt.span.lo, self.config); let suffix = if let ast::Stmt_::StmtExpr(..) = stmt.node { "" } else { @@ -65,7 +70,8 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { // 1 = trailing semicolon; let rewrite = ex.rewrite(&self.get_context(), - self.config.max_width - self.block_indent - suffix.len(), + self.config.max_width - self.block_indent.width() - + suffix.len(), self.block_indent); if let Some(new_str) = rewrite { @@ -75,7 +81,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } ast::Stmt_::StmtMac(ref _mac, _macro_style) => { - self.format_missing_with_indent(stmt.span.lo); + self.format_missing_with_indent(stmt.span.lo, self.config); visit::walk_stmt(self, stmt); } } @@ -96,7 +102,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { }; self.last_pos = self.last_pos + brace_compensation; - self.block_indent += self.config.tab_spaces; + self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); self.buffer.push_str("{"); for stmt in &b.stmts { @@ -105,15 +111,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match b.expr { Some(ref e) => { - self.format_missing_with_indent(e.span.lo); + self.format_missing_with_indent(e.span.lo, self.config); self.visit_expr(e); } None => {} } - self.block_indent -= self.config.tab_spaces; - // TODO: we should compress any newlines here to just one. - self.format_missing_with_indent(b.span.hi - brace_compensation); + self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); + // TODO: we should compress any newlines here to just one + self.format_missing_with_indent(b.span.hi - brace_compensation, self.config); self.buffer.push_str("}"); self.last_pos = b.span.hi; } @@ -126,6 +132,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { + let indent = self.block_indent; let rewrite = match fk { visit::FnKind::ItemFn(ident, @@ -161,7 +168,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { }; if let Some(fn_str) = rewrite { - self.format_missing_with_indent(s.lo); + self.format_missing_with_indent(s.lo, self.config); self.buffer.push_str(&fn_str); } else { self.format_missing(b.span.lo); @@ -191,31 +198,31 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemImpl(..) | ast::Item_::ItemTrait(..) => { - self.block_indent += self.config.tab_spaces; + self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); visit::walk_item(self, item); - self.block_indent -= self.config.tab_spaces; + self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); } ast::Item_::ItemExternCrate(_) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(item.span.lo, self.config); let new_str = self.snippet(item.span); self.buffer.push_str(&new_str); self.last_pos = item.span.hi; } ast::Item_::ItemStruct(ref def, ref generics) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(item.span.lo, self.config); self.visit_struct(item.ident, item.vis, def, generics, item.span); } ast::Item_::ItemEnum(ref def, ref generics) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(item.span.lo, self.config); self.visit_enum(item.ident, item.vis, def, generics, item.span); self.last_pos = item.span.hi; } ast::Item_::ItemMod(ref module) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(item.span.lo, self.config); self.format_mod(module, item.span, item.ident); } ast::Item_::ItemMac(..) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(item.span.lo, self.config); // TODO: we cannot format these yet, because of a bad span. // See rust lang issue #28424. // visit::walk_item(self, item); @@ -232,7 +239,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } if let ast::TraitItem_::MethodTraitItem(ref sig, None) = ti.node { - self.format_missing_with_indent(ti.span.lo); + self.format_missing_with_indent(ti.span.lo, self.config); let indent = self.block_indent; let new_fn = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); @@ -256,7 +263,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fn visit_mac(&mut self, mac: &'v ast::Mac) { // 1 = ; - let width = self.config.max_width - self.block_indent - 1; + let width = self.config.max_width - self.block_indent.width() - 1; let rewrite = rewrite_macro(mac, &self.get_context(), width, self.block_indent); if let Some(res) = rewrite { @@ -272,7 +279,7 @@ impl<'a> FmtVisitor<'a> { codemap: codemap, buffer: StringBuffer::new(), last_pos: BytePos(0), - block_indent: 0, + block_indent: Indent { block_indent: 0, alignment: 0 }, config: config, } } @@ -296,13 +303,13 @@ impl<'a> FmtVisitor<'a> { } let first = &attrs[0]; - self.format_missing_with_indent(first.span.lo); + self.format_missing_with_indent(first.span.lo, self.config); if utils::contains_skip(attrs) { true } else { let rewrite = attrs.rewrite(&self.get_context(), - self.config.max_width - self.block_indent, + self.config.max_width - self.block_indent.width(), self.block_indent) .unwrap(); self.buffer.push_str(&rewrite); @@ -323,32 +330,33 @@ impl<'a> FmtVisitor<'a> { if is_internal { debug!("FmtVisitor::format_mod: internal mod"); - self.block_indent += self.config.tab_spaces; + self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); visit::walk_mod(self, m); debug!("... last_pos after: {:?}", self.last_pos); - self.block_indent -= self.config.tab_spaces; + self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); } } pub fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) { let filemap = self.codemap.get_filemap(filename); self.last_pos = filemap.start_pos; - self.block_indent = 0; + self.block_indent = Indent::new(0, 0); visit::walk_mod(self, m); self.format_missing(filemap.end_pos); } fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span) { let vis = utils::format_visibility(vis); - let offset = self.block_indent + vis.len() + "use ".len(); + let mut offset = self.block_indent; + offset.alignment += vis.len() + "use ".len(); let context = RewriteContext { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: 0, + overflow_indent: Indent::new(0, 0), }; // 1 = ";" - match vp.rewrite(&context, self.config.max_width - offset - 1, offset) { + match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, span.lo); @@ -361,12 +369,12 @@ impl<'a> FmtVisitor<'a> { } Some(ref s) => { let s = format!("{}use {};", vis, s); - self.format_missing_with_indent(span.lo); + self.format_missing_with_indent(span.lo, self.config); self.buffer.push_str(&s); self.last_pos = span.hi; } None => { - self.format_missing_with_indent(span.lo); + self.format_missing_with_indent(span.lo, self.config); self.format_missing(span.hi); } } @@ -377,18 +385,18 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: 0, + overflow_indent: Indent::new(0, 0), } } } impl<'a> Rewrite for [ast::Attribute] { - fn rewrite(&self, context: &RewriteContext, _: usize, offset: usize) -> Option { + fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option { let mut result = String::new(); if self.is_empty() { return Some(result); } - let indent = utils::make_indent(offset); + let indent = utils::make_indent(offset, context.config); for (i, a) in self.iter().enumerate() { let a_str = context.snippet(a.span); @@ -403,8 +411,9 @@ impl<'a> Rewrite for [ast::Attribute] { if !comment.is_empty() { let comment = rewrite_comment(comment, false, - context.config.max_width - offset, - offset); + context.config.max_width - offset.width(), + offset, + context.config); result.push_str(&indent); result.push_str(&comment); result.push('\n'); -- cgit 1.4.1-3-g733a5 From 03e1b2782616cbc8f06ba4e484b1540ae23e32be Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Fri, 18 Sep 2015 21:50:44 -0700 Subject: Add Indent::none(), remove make_indent. --- src/chains.rs | 4 ++-- src/comment.rs | 5 ++--- src/expr.rs | 48 +++++++++++++++++++++++------------------------ src/items.rs | 54 +++++++++++++++++++++++++---------------------------- src/lib.rs | 22 +++++++++++++--------- src/lists.rs | 6 +++--- src/missed_spans.rs | 3 +-- src/rewrite.rs | 2 +- src/string.rs | 4 ++-- src/utils.rs | 6 ------ src/visitor.rs | 20 ++++++++++---------- 11 files changed, 82 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index daf800ace08..c59638d9e50 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -21,7 +21,7 @@ use Indent; use rewrite::{Rewrite, RewriteContext}; -use utils::{first_line_width, make_indent}; +use utils::first_line_width; use expr::rewrite_call; use syntax::{ast, ptr}; @@ -117,7 +117,7 @@ pub fn rewrite_chain(mut expr: &ast::Expr, let connector = if fits_single_line { String::new() } else { - format!("\n{}", make_indent(indent, context.config)) + format!("\n{}", indent.to_string(context.config)) }; let first_connector = if extend { diff --git a/src/comment.rs b/src/comment.rs index 683bf4b650c..765d61cfa11 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -15,7 +15,6 @@ use std::iter; use Indent; use config::Config; use string::{StringFormat, rewrite_string}; -use utils::make_indent; pub fn rewrite_comment(orig: &str, block_style: bool, @@ -45,7 +44,7 @@ pub fn rewrite_comment(orig: &str, config: config, }; - let indent_str = make_indent(offset, config); + let indent_str = offset.to_string(config); let line_breaks = s.chars().filter(|&c| c == '\n').count(); let (_, mut s) = s.lines() @@ -304,7 +303,7 @@ mod test { assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100), &config)); assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, - Indent::new(0, 0), &config)); + Indent::empty(), &config)); assert_eq!("// A multi line comment\n // between args.", rewrite_comment("// A multi line comment\n // between args.", diff --git a/src/expr.rs b/src/expr.rs index 3e8401af8b9..74d5522cc59 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -15,8 +15,7 @@ use Indent; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; -use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width, wrap_str, - binary_search}; +use utils::{span_after, extra_offset, first_line_width, last_line_width, wrap_str, binary_search}; use visitor::FmtVisitor; use config::{StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; @@ -268,7 +267,7 @@ fn rewrite_closure(capture: ast::CaptureClause, if !ret_str.is_empty() { if prefix.contains('\n') { prefix.push('\n'); - prefix.push_str(&make_indent(argument_offset, context.config)); + prefix.push_str(&argument_offset.to_string(context.config)); } else { prefix.push(' '); } @@ -311,12 +310,12 @@ fn rewrite_closure(capture: ast::CaptureClause, .as_ref() .and_then(|body_expr| { if let ast::Expr_::ExprBlock(ref inner) = body_expr.node { - Some(inner.rewrite(&context, 2, Indent::new(0, 0))) + Some(inner.rewrite(&context, 2, Indent::empty())) } else { None } }) - .unwrap_or_else(|| body.rewrite(&context, 2, Indent::new(0, 0))); + .unwrap_or_else(|| body.rewrite(&context, 2, Indent::empty())); Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } @@ -592,11 +591,11 @@ fn single_line_if_else(context: &RewriteContext, let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); let if_expr = if_node.expr.as_ref().unwrap(); - let if_str = try_opt!(if_expr.rewrite(context, new_width, Indent::new(0, 0))); + let if_str = try_opt!(if_expr.rewrite(context, new_width, Indent::empty())); let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = else_node.expr.as_ref().unwrap(); - let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::new(0, 0))); + let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::empty())); // FIXME: this check shouldn't be necessary. Rewrites should either fail // or wrap to a newline when the object does not fit the width. @@ -638,7 +637,7 @@ fn rewrite_match(context: &RewriteContext, let nested_context = context.nested_context(); let arm_indent = nested_context.block_indent + context.overflow_indent; - let arm_indent_str = make_indent(arm_indent, context.config); + let arm_indent_str = arm_indent.to_string(context.config); let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{", @@ -688,7 +687,7 @@ fn rewrite_match(context: &RewriteContext, // match expression, but meh. result.push('\n'); - result.push_str(&make_indent(context.block_indent + context.overflow_indent, context.config)); + result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); result.push('}'); Some(result) } @@ -710,7 +709,7 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; - let indent_str = make_indent(offset, context.config); + let indent_str = offset.to_string(context.config); // FIXME this is all a bit grotty, would be nice to abstract out the // treatment of attributes. @@ -738,7 +737,7 @@ impl Rewrite for ast::Arm { .map(|p| { p.rewrite(context, pat_budget, - offset.block_indent(context.config.tab_spaces)) + offset.block_indent(context.config)) }) .collect::>>()); @@ -784,7 +783,7 @@ impl Rewrite for ast::Arm { let mut line_indent = offset + pats_width; if vertical { - line_indent = line_indent.block_indent(context.config.tab_spaces); + line_indent = line_indent.block_indent(context.config); } let comma = if let ast::ExprBlock(_) = body.node { @@ -819,7 +818,7 @@ impl Rewrite for ast::Arm { Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, - make_indent(offset.block_indent(context.config.tab_spaces), context.config), + offset.block_indent(context.config).to_string(context.config), body_str)) } } @@ -849,11 +848,10 @@ fn rewrite_guard(context: &RewriteContext, if overhead < width { let cond_str = guard.rewrite(context, width - overhead, - offset.block_indent(context.config.tab_spaces)); + offset.block_indent(context.config)); if let Some(cond_str) = cond_str { return Some(format!("\n{}if {}", - make_indent(offset.block_indent(context.config.tab_spaces), - context.config), + offset.block_indent(context.config).to_string(context.config), cond_str)); } } @@ -908,7 +906,7 @@ fn rewrite_pat_expr(context: &RewriteContext, // The expression won't fit on the current line, jump to next. result.push('\n'); - result.push_str(&make_indent(pat_offset, context.config)); + result.push_str(&pat_offset.to_string(context.config)); let expr_rewrite = expr.rewrite(context, context.config.max_width - pat_offset.width(), @@ -1067,7 +1065,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, StructLitStyle::Block => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. - let indent = context.block_indent.block_indent(context.config.tab_spaces); + let indent = context.block_indent.block_indent(context.config); let v_budget = context.config.max_width.checked_sub(indent.width()).unwrap_or(0); (indent, v_budget) } @@ -1139,10 +1137,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let fields_str = try_opt!(write_list(&items.collect::>(), &fmt)); let format_on_newline = || { - let inner_indent = make_indent(context.block_indent - .block_indent(context.config.tab_spaces), - context.config); - let outer_indent = make_indent(context.block_indent, context.config); + let inner_indent = context.block_indent + .block_indent(context.config) + .to_string(context.config); + let outer_indent = context.block_indent.to_string(context.config); Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) }; @@ -1255,7 +1253,7 @@ fn rewrite_binary_op(context: &RewriteContext, Some(format!("{} {}\n{}{}", try_opt!(lhs.rewrite(context, budget, offset)), operator_str, - make_indent(offset, context.config), + offset.to_string(context.config), rhs_result)) } @@ -1319,8 +1317,8 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, None => { // Expression did not fit on the same line as the identifier. Retry // on the next line. - let new_offset = offset.block_indent(context.config.tab_spaces); - result.push_str(&format!("\n{}", make_indent(new_offset, context.config))); + let new_offset = offset.block_indent(context.config); + result.push_str(&format!("\n{}", new_offset.to_string(context.config))); // FIXME: we probably should related max_width to width instead of config.max_width // where is the 1 coming from anyway? diff --git a/src/items.rs b/src/items.rs index ae55fdf4c29..e72251815cf 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,8 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use Indent; -use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, - end_typaram, wrap_str}; +use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, wrap_str}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; use expr::rewrite_assign_rhs; use comment::FindUncommented; @@ -35,7 +34,7 @@ impl<'a> FmtVisitor<'a> { if let Some(ref ty) = local.ty { infix.push_str(": "); - infix.push_str(&ty.rewrite(&self.get_context(), 1000, Indent::new(0, 0)).unwrap()); + infix.push_str(&ty.rewrite(&self.get_context(), 1000, Indent::empty()).unwrap()); } if local.init.is_some() { @@ -126,7 +125,7 @@ impl<'a> FmtVisitor<'a> { // this. if newline_brace { result.push('\n'); - result.push_str(&make_indent(indent, self.config)); + result.push_str(&indent.to_string(self.config)); } else { result.push(' '); } @@ -226,17 +225,17 @@ impl<'a> FmtVisitor<'a> { if one_line_budget <= 0 { if self.config.fn_args_paren_newline { result.push('\n'); - result.push_str(&make_indent(arg_indent, self.config)); + result.push_str(&arg_indent.to_string(self.config)); arg_indent = arg_indent + 1; // extra space for `(` result.push('('); } else { result.push_str("(\n"); - result.push_str(&make_indent(arg_indent, self.config)); + result.push_str(&arg_indent.to_string(self.config)); } } else if self.config.fn_args_layout == StructLitStyle::Block { - arg_indent = indent.block_indent(self.config.tab_spaces); + arg_indent = indent.block_indent(self.config); result.push_str("(\n"); - result.push_str(&make_indent(arg_indent, self.config)); + result.push_str(&arg_indent.to_string(self.config)); } else { result.push('('); } @@ -281,7 +280,7 @@ impl<'a> FmtVisitor<'a> { }; result.push('\n'); - result.push_str(&make_indent(indent, self.config)); + result.push_str(&indent.to_string(self.config)); } else { result.push(' '); } @@ -390,7 +389,7 @@ impl<'a> FmtVisitor<'a> { let indent = match self.config.fn_arg_indent { BlockIndentStyle::Inherit => indent, - BlockIndentStyle::Tabbed => indent.block_indent(self.config.tab_spaces), + BlockIndentStyle::Tabbed => indent.block_indent(self.config), BlockIndentStyle::Visual => arg_indent, }; @@ -444,7 +443,7 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. if let None = budgets { - let new_indent = indent.block_indent(self.config.tab_spaces); + let new_indent = indent.block_indent(self.config); let used_space = new_indent.width() + 2; // account for `(` and `)` let max_space = self.config.ideal_width + self.config.leeway; if used_space > max_space { @@ -480,14 +479,13 @@ impl<'a> FmtVisitor<'a> { let generics_str = self.format_generics(generics, " {", self.block_indent, - self.block_indent - .block_indent(self.config.tab_spaces), + self.block_indent.block_indent(self.config), codemap::mk_sp(span.lo, body_start)) .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; - self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_indent(self.config); for (i, f) in enum_def.variants.iter().enumerate() { let next_span_start: BytePos = if i == enum_def.variants.len() - 1 { span.hi @@ -497,7 +495,7 @@ impl<'a> FmtVisitor<'a> { self.visit_variant(f, i == enum_def.variants.len() - 1, next_span_start); } - self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_unindent(self.config); self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32), self.config); @@ -530,7 +528,7 @@ impl<'a> FmtVisitor<'a> { arg.ty .rewrite(&self.get_context(), 1000, - Indent::new(0, 0)) + Indent::empty()) .unwrap() }, span_after(field.span, "(", self.codemap), @@ -672,7 +670,7 @@ impl<'a> FmtVisitor<'a> { single_line_cost as usize + used_budget > self.config.max_width; let tactic = if break_line { - let indentation = make_indent(offset.block_indent(self.config.tab_spaces), self.config); + let indentation = offset.block_indent(self.config).to_string(self.config); result.push('\n'); result.push_str(&indentation); @@ -687,7 +685,7 @@ impl<'a> FmtVisitor<'a> { tactic: tactic, separator: ",", trailing_separator: self.config.struct_trailing_comma, - indent: offset.block_indent(self.config.tab_spaces), + indent: offset.block_indent(self.config), h_width: self.config.max_width, v_width: budget, ends_with_newline: true, @@ -699,7 +697,7 @@ impl<'a> FmtVisitor<'a> { if break_line { result.push('\n'); - result.push_str(&make_indent(offset, self.config)); + result.push_str(&offset.to_string(self.config)); } result.push_str(terminator); @@ -751,7 +749,7 @@ impl<'a> FmtVisitor<'a> { Density::Tall, span.hi)); result.push_str(&where_clause_str); - result.push_str(&make_indent(self.block_indent, self.config)); + result.push_str(&self.block_indent.to_string(self.config)); result.push('\n'); result.push_str(opener.trim()); } else { @@ -776,9 +774,9 @@ impl<'a> FmtVisitor<'a> { ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; // FIXME silly width, indent - let typ = field.node.ty.rewrite(&self.get_context(), 1000, Indent::new(0, 0)).unwrap(); + let typ = field.node.ty.rewrite(&self.get_context(), 1000, Indent::empty()).unwrap(); - let indent = self.block_indent + self.config.tab_spaces; + let indent = self.block_indent.block_indent(self.config); let mut attr_str = field.node .attrs .rewrite(&self.get_context(), @@ -787,7 +785,7 @@ impl<'a> FmtVisitor<'a> { .unwrap(); if !attr_str.is_empty() { attr_str.push('\n'); - attr_str.push_str(&make_indent(indent, self.config)); + attr_str.push_str(&indent.to_string(self.config)); } match name { @@ -812,7 +810,7 @@ impl<'a> FmtVisitor<'a> { let offset = match self.config.generics_indent { BlockIndentStyle::Inherit => offset, - BlockIndentStyle::Tabbed => offset.block_indent(self.config.tab_spaces), + BlockIndentStyle::Tabbed => offset.block_indent(self.config), // 1 = < BlockIndentStyle::Visual => generics_offset + 1, }; @@ -870,7 +868,7 @@ impl<'a> FmtVisitor<'a> { } let extra_indent = match self.config.where_indent { - BlockIndentStyle::Inherit => Indent::new(0, 0), + BlockIndentStyle::Inherit => Indent::empty(), BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => Indent::new(config.tab_spaces, 0), }; @@ -879,7 +877,7 @@ impl<'a> FmtVisitor<'a> { let offset = match self.config.where_pred_indent { BlockIndentStyle::Inherit => indent + extra_indent, - BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config.tab_spaces), + BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config), // 6 = "where ".len() BlockIndentStyle::Visual => indent + extra_indent + 6, }; @@ -915,9 +913,7 @@ impl<'a> FmtVisitor<'a> { // 9 = " where ".len() + " {".len() if density == Density::Tall || preds_str.contains('\n') || indent.width() + 9 + preds_str.len() > self.config.max_width { - Some(format!("\n{}where {}", - make_indent(indent + extra_indent, self.config), - preds_str)) + Some(format!("\n{}where {}", (indent + extra_indent).to_string(self.config), preds_str)) } else { Some(format!(" where {}", preds_str)) } diff --git a/src/lib.rs b/src/lib.rs index 2ca206665e2..30150537309 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,7 +83,10 @@ const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; #[derive(Copy, Clone, Debug)] pub struct Indent { + // Width of the block indent, in characters. Must be a multiple of + // Config::tab_spaces. block_indent: usize, + // Alignment in characters. alignment: usize, } @@ -92,13 +95,17 @@ impl Indent { Indent { block_indent: block_indent, alignment: alignment } } - pub fn block_indent(mut self, block_indent: usize) -> Indent { - self.block_indent += block_indent; + pub fn empty() -> Indent { + Indent::new(0, 0) + } + + pub fn block_indent(mut self, config: &Config) -> Indent { + self.block_indent += config.tab_spaces; self } - pub fn block_unindent(mut self, block_indent: usize) -> Indent { - self.block_indent -= block_indent; + pub fn block_unindent(mut self, config: &Config) -> Indent { + self.block_indent -= config.tab_spaces; self } @@ -139,10 +146,7 @@ impl Sub for Indent { type Output = Indent; fn sub(self, rhs: Indent) -> Indent { - Indent { - block_indent: self.block_indent - rhs.block_indent, - alignment: self.alignment - rhs.alignment, - } + Indent::new(self.block_indent - rhs.block_indent, self.alignment - rhs.alignment) } } @@ -150,7 +154,7 @@ impl Add for Indent { type Output = Indent; fn add(self, rhs: usize) -> Indent { - Indent { block_indent: self.block_indent, alignment: self.alignment + rhs } + Indent::new(self.block_indent, self.alignment + rhs) } } diff --git a/src/lists.rs b/src/lists.rs index 40da7af198e..e00e8b0ee37 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -14,7 +14,7 @@ use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; use Indent; -use utils::{round_up_to_power_of_two, make_indent, wrap_str}; +use utils::{round_up_to_power_of_two, wrap_str}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; use config::Config; @@ -155,7 +155,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let mut result = String::with_capacity(round_up_to_power_of_two(alloc_width)); let mut line_len = 0; - let indent_str = &make_indent(formatting.indent, formatting.config); + let indent_str = &formatting.indent.to_string(formatting.config); for (i, item) in items.iter().enumerate() { let first = i == 0; let last = i == items.len() - 1; @@ -221,7 +221,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let formatted_comment = rewrite_comment(comment, true, formatting.v_width, - Indent::new(0, 0), + Indent::empty(), formatting.config); result.push(' '); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index c8da3e76b63..f39480f5450 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -9,7 +9,6 @@ // except according to those terms. use config::Config; -use utils::make_indent; use visitor::FmtVisitor; use syntax::codemap::{self, BytePos}; @@ -29,7 +28,7 @@ impl<'a> FmtVisitor<'a> { // No new lines in the snippet. this.buffer.push_str("\n"); } - let indent = make_indent(this.block_indent, config); + let indent = this.block_indent.to_string(config); this.buffer.push_str(&indent); }) } diff --git a/src/rewrite.rs b/src/rewrite.rs index 2e0f5691d2e..6517bbdf37b 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -44,7 +44,7 @@ impl<'a> RewriteContext<'a> { RewriteContext { codemap: self.codemap, config: self.config, - block_indent: self.block_indent.block_indent(self.config.tab_spaces), + block_indent: self.block_indent.block_indent(self.config), overflow_indent: self.overflow_indent, } } diff --git a/src/string.rs b/src/string.rs index 3da0a5f4a25..4e40b8e9ede 100644 --- a/src/string.rs +++ b/src/string.rs @@ -15,7 +15,7 @@ use regex::Regex; use Indent; use config::Config; -use utils::{make_indent, round_up_to_power_of_two}; +use utils::round_up_to_power_of_two; use MIN_STRING; @@ -39,7 +39,7 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let indent = make_indent(fmt.offset, fmt.config); + let indent = fmt.offset.to_string(fmt.config); let indent = &indent; let mut cur_start = 0; diff --git a/src/utils.rs b/src/utils.rs index 3843e75973e..171572ccfbf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,7 +15,6 @@ use syntax::codemap::{CodeMap, Span, BytePos}; use Indent; use comment::FindUncommented; -use config::Config; use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; @@ -37,11 +36,6 @@ pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { original.lo + BytePos(snippet.find_uncommented(needle).unwrap() as u32 + 1) } -#[inline] -pub fn make_indent(indent: Indent, config: &Config) -> String { - indent.to_string(config) -} - #[inline] pub fn format_visibility(vis: Visibility) -> &'static str { match vis { diff --git a/src/visitor.rs b/src/visitor.rs index d0a5df12221..5426d9bae90 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -102,7 +102,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { }; self.last_pos = self.last_pos + brace_compensation; - self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_indent(self.config); self.buffer.push_str("{"); for stmt in &b.stmts { @@ -117,7 +117,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { None => {} } - self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_unindent(self.config); // TODO: we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - brace_compensation, self.config); self.buffer.push_str("}"); @@ -198,9 +198,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemImpl(..) | ast::Item_::ItemTrait(..) => { - self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_indent(self.config); visit::walk_item(self, item); - self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_unindent(self.config); } ast::Item_::ItemExternCrate(_) => { self.format_missing_with_indent(item.span.lo, self.config); @@ -330,17 +330,17 @@ impl<'a> FmtVisitor<'a> { if is_internal { debug!("FmtVisitor::format_mod: internal mod"); - self.block_indent = self.block_indent.block_indent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_indent(self.config); visit::walk_mod(self, m); debug!("... last_pos after: {:?}", self.last_pos); - self.block_indent = self.block_indent.block_unindent(self.config.tab_spaces); + self.block_indent = self.block_indent.block_unindent(self.config); } } pub fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) { let filemap = self.codemap.get_filemap(filename); self.last_pos = filemap.start_pos; - self.block_indent = Indent::new(0, 0); + self.block_indent = Indent::empty(); visit::walk_mod(self, m); self.format_missing(filemap.end_pos); } @@ -353,7 +353,7 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: Indent::new(0, 0), + overflow_indent: Indent::empty(), }; // 1 = ";" match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { @@ -385,7 +385,7 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: Indent::new(0, 0), + overflow_indent: Indent::empty(), } } } @@ -396,7 +396,7 @@ impl<'a> Rewrite for [ast::Attribute] { if self.is_empty() { return Some(result); } - let indent = utils::make_indent(offset, context.config); + let indent = offset.to_string(context.config); for (i, a) in self.iter().enumerate() { let a_str = context.snippet(a.span); -- cgit 1.4.1-3-g733a5 From 620650219e5c456a770a9ea9952a8afffe875ea4 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Fri, 18 Sep 2015 23:57:27 -0700 Subject: Use the block_indent inside visit_expr. This seems to pass all the tests and greatly improves the formatting output when using hard tabs. --- src/visitor.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 5426d9bae90..7c56bf675c7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -39,12 +39,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.codemap.lookup_char_pos(ex.span.hi)); self.format_missing(ex.span.lo); - let offset = self.buffer.cur_offset(); - // FIXME: We put the entire offset into the block_indent, which might not be correct in all - // situations. let rewrite = ex.rewrite(&self.get_context(), - self.config.max_width - offset, - Indent::new(offset, 0)); + self.config.max_width - self.block_indent.width(), + self.block_indent); if let Some(new_str) = rewrite { self.buffer.push_str(&new_str); -- cgit 1.4.1-3-g733a5 From 01bdcd001443d7639fc0127e31c61e5ff4e98464 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Sat, 19 Sep 2015 10:44:28 -0700 Subject: Remove unnecessary config parameter from format_missing_with_indent. --- src/items.rs | 7 +++---- src/missed_spans.rs | 4 ++-- src/visitor.rs | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e72251815cf..a61925798d3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -26,7 +26,7 @@ use syntax::parse::token; impl<'a> FmtVisitor<'a> { pub fn visit_let(&mut self, local: &ast::Local, span: Span) { - self.format_missing_with_indent(span.lo, self.config); + self.format_missing_with_indent(span.lo); // String that is placed within the assignment pattern and expression. let infix = { @@ -497,8 +497,7 @@ impl<'a> FmtVisitor<'a> { } self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32), - self.config); + self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32)); self.buffer.push_str("}"); } @@ -508,7 +507,7 @@ impl<'a> FmtVisitor<'a> { return; } - self.format_missing_with_indent(field.span.lo, self.config); + self.format_missing_with_indent(field.span.lo); let result = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index f39480f5450..db9599c1706 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::Config; use visitor::FmtVisitor; use syntax::codemap::{self, BytePos}; @@ -20,7 +19,8 @@ impl<'a> FmtVisitor<'a> { self.format_missing_inner(end, |this, last_snippet, _| this.buffer.push_str(last_snippet)) } - pub fn format_missing_with_indent(&mut self, end: BytePos, config: &Config) { + pub fn format_missing_with_indent(&mut self, end: BytePos) { + let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { this.buffer.push_str(last_snippet.trim_right()); diff --git a/src/visitor.rs b/src/visitor.rs index 7c56bf675c7..762eda2013a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -58,7 +58,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { - self.format_missing_with_indent(stmt.span.lo, self.config); + self.format_missing_with_indent(stmt.span.lo); let suffix = if let ast::Stmt_::StmtExpr(..) = stmt.node { "" } else { @@ -78,7 +78,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } ast::Stmt_::StmtMac(ref _mac, _macro_style) => { - self.format_missing_with_indent(stmt.span.lo, self.config); + self.format_missing_with_indent(stmt.span.lo); visit::walk_stmt(self, stmt); } } @@ -108,7 +108,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { match b.expr { Some(ref e) => { - self.format_missing_with_indent(e.span.lo, self.config); + self.format_missing_with_indent(e.span.lo); self.visit_expr(e); } None => {} @@ -116,7 +116,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent = self.block_indent.block_unindent(self.config); // TODO: we should compress any newlines here to just one - self.format_missing_with_indent(b.span.hi - brace_compensation, self.config); + self.format_missing_with_indent(b.span.hi - brace_compensation); self.buffer.push_str("}"); self.last_pos = b.span.hi; } @@ -165,7 +165,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { }; if let Some(fn_str) = rewrite { - self.format_missing_with_indent(s.lo, self.config); + self.format_missing_with_indent(s.lo); self.buffer.push_str(&fn_str); } else { self.format_missing(b.span.lo); @@ -200,26 +200,26 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.block_indent = self.block_indent.block_unindent(self.config); } ast::Item_::ItemExternCrate(_) => { - self.format_missing_with_indent(item.span.lo, self.config); + self.format_missing_with_indent(item.span.lo); let new_str = self.snippet(item.span); self.buffer.push_str(&new_str); self.last_pos = item.span.hi; } ast::Item_::ItemStruct(ref def, ref generics) => { - self.format_missing_with_indent(item.span.lo, self.config); + self.format_missing_with_indent(item.span.lo); self.visit_struct(item.ident, item.vis, def, generics, item.span); } ast::Item_::ItemEnum(ref def, ref generics) => { - self.format_missing_with_indent(item.span.lo, self.config); + self.format_missing_with_indent(item.span.lo); self.visit_enum(item.ident, item.vis, def, generics, item.span); self.last_pos = item.span.hi; } ast::Item_::ItemMod(ref module) => { - self.format_missing_with_indent(item.span.lo, self.config); + self.format_missing_with_indent(item.span.lo); self.format_mod(module, item.span, item.ident); } ast::Item_::ItemMac(..) => { - self.format_missing_with_indent(item.span.lo, self.config); + self.format_missing_with_indent(item.span.lo); // TODO: we cannot format these yet, because of a bad span. // See rust lang issue #28424. // visit::walk_item(self, item); @@ -236,7 +236,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } if let ast::TraitItem_::MethodTraitItem(ref sig, None) = ti.node { - self.format_missing_with_indent(ti.span.lo, self.config); + self.format_missing_with_indent(ti.span.lo); let indent = self.block_indent; let new_fn = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); @@ -300,7 +300,7 @@ impl<'a> FmtVisitor<'a> { } let first = &attrs[0]; - self.format_missing_with_indent(first.span.lo, self.config); + self.format_missing_with_indent(first.span.lo); if utils::contains_skip(attrs) { true @@ -366,12 +366,12 @@ impl<'a> FmtVisitor<'a> { } Some(ref s) => { let s = format!("{}use {};", vis, s); - self.format_missing_with_indent(span.lo, self.config); + self.format_missing_with_indent(span.lo); self.buffer.push_str(&s); self.last_pos = span.hi; } None => { - self.format_missing_with_indent(span.lo, self.config); + self.format_missing_with_indent(span.lo); self.format_missing(span.hi); } } -- cgit 1.4.1-3-g733a5 From f8e74bfa2c2d3917d9ed1607d57eabd9062a9759 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 20 Sep 2015 14:22:12 +0200 Subject: Place the closing brace of an inline mod on a new line --- src/visitor.rs | 6 ++++-- tests/source/mod-1.rs | 17 +++++++++++++++++ tests/target/mod-1.rs | 11 +++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/source/mod-1.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 762eda2013a..f15c2e07b82 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -326,11 +326,13 @@ impl<'a> FmtVisitor<'a> { // TODO: Should rewrite properly `mod X;` if is_internal { - debug!("FmtVisitor::format_mod: internal mod"); self.block_indent = self.block_indent.block_indent(self.config); visit::walk_mod(self, m); - debug!("... last_pos after: {:?}", self.last_pos); self.block_indent = self.block_indent.block_unindent(self.config); + + self.format_missing_with_indent(m.inner.hi - BytePos(1)); + self.buffer.push_str("}"); + self.last_pos = m.inner.hi; } } diff --git a/tests/source/mod-1.rs b/tests/source/mod-1.rs new file mode 100644 index 00000000000..2efb8f538e5 --- /dev/null +++ b/tests/source/mod-1.rs @@ -0,0 +1,17 @@ +// Deeply indented modules. + + mod foo { mod bar { mod baz {} } } + +mod foo { + mod bar { + mod baz { + fn foo() { bar() } + } + } + + mod qux { + + } +} + +mod boxed { pub use std::boxed::{Box, HEAP}; } diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs index c6d5f355f61..8916c972ad1 100644 --- a/tests/target/mod-1.rs +++ b/tests/target/mod-1.rs @@ -1,5 +1,12 @@ // Deeply indented modules. +mod foo { + mod bar { + mod baz { + } + } +} + mod foo { mod bar { mod baz { @@ -13,3 +20,7 @@ mod foo { } } + +mod boxed { + pub use std::boxed::{Box, HEAP}; +} -- cgit 1.4.1-3-g733a5 From 9bd502ad54a1ccea30d79e1cf5667fa9705fc221 Mon Sep 17 00:00:00 2001 From: Sebastian Ullrich Date: Sun, 20 Sep 2015 15:18:41 +0200 Subject: Fix negative overflow and missing '..' on struct lit base exprs --- src/expr.rs | 11 ++++++++--- tests/source/expr.rs | 8 ++++++++ tests/target/expr.rs | 7 +++++++ 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 74d5522cc59..155553a7615 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1108,9 +1108,14 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } StructLitField::Base(ref expr) => { // 2 = .. - expr.rewrite(inner_context, h_budget - 2, indent + 2) - .map(|s| format!("..{}", s)) - .unwrap_or(context.snippet(expr.span)) + format!("..{}", + h_budget.checked_sub(2) + .and_then(|h_budget| { + expr.rewrite(inner_context, + h_budget, + indent + 2) + }) + .unwrap_or(context.snippet(expr.span))) } } }, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index faa0d3775c7..4b5e262bd26 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -173,3 +173,11 @@ fn arrays() { [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] } + +fn struct_exprs() { + Foo + { a : 1, b:f( 2)}; + Foo{a:1,b:f(2),..g(3)}; + // FIXME: should be wrapped (#231) + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index bb629f12126..7b579960d53 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -183,3 +183,10 @@ fn arrays() { [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } + +fn struct_exprs() { + Foo { a: 1, b: f(2) }; + Foo { a: 1, b: f(2), ..g(3) }; + // FIXME: should be wrapped (#231) + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; +} -- cgit 1.4.1-3-g733a5 From 5ee6304d8d738d05debfcb712ee57b024f5e1b95 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 20 Sep 2015 18:44:49 +0200 Subject: Fix struct overflows --- src/expr.rs | 23 +++++++++++++---------- tests/source/expr.rs | 8 -------- tests/source/struct_lits.rs | 8 ++++++++ tests/target/expr.rs | 7 ------- tests/target/struct_lits.rs | 16 ++++++++++++---- 5 files changed, 33 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 155553a7615..95da7d3659f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1057,7 +1057,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let path_str = try_opt!(path.rewrite(context, path_budget, offset)); // Foo { a: Foo } - indent is +3, width is -5. - let h_budget = try_opt!(width.checked_sub(path_str.len() + 5)); + let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); let (indent, v_budget) = match context.config.struct_lit_style { StructLitStyle::Visual => { (offset + path_str.len() + 3, h_budget) @@ -1103,16 +1103,16 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| { match *item { StructLitField::Regular(ref field) => { - rewrite_field(inner_context, &field, h_budget, indent) + rewrite_field(inner_context, &field, v_budget, indent) .unwrap_or(context.snippet(field.span)) } StructLitField::Base(ref expr) => { // 2 = .. format!("..{}", - h_budget.checked_sub(2) - .and_then(|h_budget| { + v_budget.checked_sub(2) + .and_then(|v_budget| { expr.rewrite(inner_context, - h_budget, + v_budget, indent + 2) }) .unwrap_or(context.snippet(expr.span))) @@ -1122,11 +1122,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span_after(span, "{", context.codemap), span.hi); + let tactic = match (context.config.struct_lit_style, fields.len()) { + (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, + _ => context.config.struct_lit_multiline_style.to_list_tactic(), + }; + let fmt = ListFormatting { - tactic: match (context.config.struct_lit_style, fields.len()) { - (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => context.config.struct_lit_multiline_style.to_list_tactic(), - }, + tactic: tactic, separator: ",", trailing_separator: if base.is_some() { SeparatorTactic::Never @@ -1150,7 +1152,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }; match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { - (StructLitStyle::Block, _) if fields_str.contains('\n') => format_on_newline(), + (StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => + format_on_newline(), (StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(), _ => Some(format!("{} {{ {} }}", path_str, fields_str)), } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 4b5e262bd26..faa0d3775c7 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -173,11 +173,3 @@ fn arrays() { [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] } - -fn struct_exprs() { - Foo - { a : 1, b:f( 2)}; - Foo{a:1,b:f(2),..g(3)}; - // FIXME: should be wrapped (#231) - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; -} diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index ead7b749d5a..69f90879164 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -83,3 +83,11 @@ fn issue278() { b: 0, }; } + +fn struct_exprs() { + Foo + { a : 1, b:f( 2)}; + Foo{a:1,b:f(2),..g(3)}; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; + IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 7b579960d53..bb629f12126 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -183,10 +183,3 @@ fn arrays() { [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } - -fn struct_exprs() { - Foo { a: 1, b: f(2) }; - Foo { a: 1, b: f(2), ..g(3) }; - // FIXME: should be wrapped (#231) - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; -} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index b95772d41ec..ac7b8aaaeab 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -65,10 +65,7 @@ fn main() { fn matcher() { TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" Date: Mon, 21 Sep 2015 17:40:59 +0530 Subject: Handle comments in match better (fixes #344) --- src/expr.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 95da7d3659f..2c57bb5b64d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -117,7 +117,7 @@ impl Rewrite for ast::Expr { offset) } ast::Expr_::ExprMatch(ref cond, ref arms, _) => { - rewrite_match(context, cond, arms, width, offset) + rewrite_match(context, cond, arms, width, offset, self.span) } ast::Expr_::ExprPath(ref qself, ref path) => { rewrite_path(context, qself.as_ref(), path, width, offset) @@ -624,7 +624,8 @@ fn rewrite_match(context: &RewriteContext, cond: &ast::Expr, arms: &[ast::Arm], width: usize, - offset: Indent) + offset: Indent, + span: Span) -> Option { if arms.is_empty() { return None; @@ -666,7 +667,8 @@ fn rewrite_match(context: &RewriteContext, if !missed_str.is_empty() { result.push('\n'); result.push_str(&arm_indent_str); - result.push_str(missed_str); + result.push_str(&rewrite_comment(&missed_str, false, + width, arm_indent, context.config)); } result.push('\n'); result.push_str(&arm_indent_str); @@ -682,11 +684,23 @@ fn rewrite_match(context: &RewriteContext, result.push_str(&snippet); } } - - // We'll miss any comments etc. between the last arm and the end of the - // match expression, but meh. + let last_comment = context.snippet(mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi)); + let last_comment = match last_comment.find_uncommented(",") { + Some(n) => &last_comment[n+1..], + None => &last_comment[..], + }; + let last_comment = match last_comment.find_uncommented("}") { + Some(n) => &last_comment[..n-1], + None => &last_comment[..], + }; + let last_comment = last_comment.trim(); result.push('\n'); + if last_comment.len() > 0 { + result.push_str(&arm_indent_str); + result.push_str(&rewrite_comment(&last_comment, false, width, arm_indent, context.config)); + result.push('\n'); + } result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); result.push('}'); Some(result) -- cgit 1.4.1-3-g733a5 From 71faa8984d9b82b0e0a4d0e145fd541512697c7d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 21 Sep 2015 20:02:45 +0200 Subject: Format foreign functions and statics --- src/items.rs | 130 +++++++++++++++++++++++++++++++++++++++++++------ src/visitor.rs | 17 +++---- tests/source/extern.rs | 21 ++++++++ tests/target/extern.rs | 29 +++++++++++ 4 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 tests/source/extern.rs create mode 100644 tests/target/extern.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a61925798d3..33e0a2a11b4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -33,8 +33,18 @@ impl<'a> FmtVisitor<'a> { let mut infix = String::new(); if let Some(ref ty) = local.ty { - infix.push_str(": "); - infix.push_str(&ty.rewrite(&self.get_context(), 1000, Indent::empty()).unwrap()); + // 2 = ": ".len() + let offset = self.block_indent + 2; + let width = self.config.max_width - offset.width(); + let rewrite = ty.rewrite(&self.get_context(), width, offset); + + match rewrite { + Some(result) => { + infix.push_str(": "); + infix.push_str(&result); + } + None => return, + } } if local.init.is_some() { @@ -88,15 +98,103 @@ impl<'a> FmtVisitor<'a> { self.last_pos = span.hi; } + pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { + self.buffer.push_str("extern "); + + if fm.abi != abi::Abi::C { + self.buffer.push_str(&format!("{} ", fm.abi)); + } + + let snippet = self.snippet(span); + let brace_pos = snippet.find_uncommented("{").unwrap() as u32; + + // FIXME: this skips comments between the extern keyword and the opening + // brace. + self.last_pos = span.lo + BytePos(brace_pos); + self.block_indent = self.block_indent.block_indent(self.config); + + for item in &fm.items { + self.format_foreign_item(&*item); + } + + self.block_indent = self.block_indent.block_unindent(self.config); + self.format_missing_with_indent(span.hi - BytePos(1)); + self.buffer.push_str("}"); + self.last_pos = span.hi; + } + + fn format_foreign_item(&mut self, item: &ast::ForeignItem) { + self.format_missing_with_indent(item.span.lo); + // Drop semicolon or it will be interpreted as comment. + // FIXME: this may be a faulty span from libsyntax. + let span = codemap::mk_sp(item.span.lo, item.span.hi - BytePos(1)); + + match item.node { + ast::ForeignItem_::ForeignItemFn(ref fn_decl, ref generics) => { + let indent = self.block_indent; + let rewrite = self.rewrite_fn_base(indent, + item.ident, + fn_decl, + None, + generics, + ast::Unsafety::Normal, + ast::Constness::NotConst, + // These are not actually rust functions, + // but we format them as such. + abi::Abi::Rust, + ast::Visibility::Inherited, + span, + false); + + match rewrite { + Some(new_fn) => { + self.buffer.push_str(format_visibility(item.vis)); + self.buffer.push_str(&new_fn); + self.buffer.push_str(";"); + } + None => self.format_missing(item.span.hi), + } + } + ast::ForeignItem_::ForeignItemStatic(ref ty, is_mutable) => { + // FIXME(#21): we're dropping potential comments in between the + // function keywords here. + let mut_str = if is_mutable { + "mut " + } else { + "" + }; + let prefix = format!("{}static {}{}: ", + format_visibility(item.vis), + mut_str, + item.ident); + let offset = self.block_indent + prefix.len(); + // 1 = ; + let width = self.config.max_width - offset.width() - 1; + let rewrite = ty.rewrite(&self.get_context(), width, offset); + + match rewrite { + Some(result) => { + self.buffer.push_str(&prefix); + self.buffer.push_str(&result); + self.buffer.push_str(";"); + } + None => self.format_missing(item.span.hi), + } + } + } + + self.last_pos = item.span.hi; + } + pub fn rewrite_fn(&mut self, indent: Indent, ident: ast::Ident, fd: &ast::FnDecl, explicit_self: Option<&ast::ExplicitSelf>, generics: &ast::Generics, - unsafety: &ast::Unsafety, - constness: &ast::Constness, - abi: &abi::Abi, + unsafety: ast::Unsafety, + constness: ast::Constness, + abi: abi::Abi, vis: ast::Visibility, span: Span) -> Option { @@ -147,9 +245,9 @@ impl<'a> FmtVisitor<'a> { &sig.decl, Some(&sig.explicit_self), &sig.generics, - &sig.unsafety, - &sig.constness, - &sig.abi, + sig.unsafety, + sig.constness, + sig.abi, ast::Visibility::Inherited, span, false)); @@ -166,9 +264,9 @@ impl<'a> FmtVisitor<'a> { fd: &ast::FnDecl, explicit_self: Option<&ast::ExplicitSelf>, generics: &ast::Generics, - unsafety: &ast::Unsafety, - constness: &ast::Constness, - abi: &abi::Abi, + unsafety: ast::Unsafety, + constness: ast::Constness, + abi: abi::Abi, vis: ast::Visibility, span: Span, newline_brace: bool) @@ -182,13 +280,13 @@ impl<'a> FmtVisitor<'a> { // Vis unsafety abi. result.push_str(format_visibility(vis)); - if let &ast::Unsafety::Unsafe = unsafety { + if let ast::Unsafety::Unsafe = unsafety { result.push_str("unsafe "); } - if let &ast::Constness::Const = constness { + if let ast::Constness::Const = constness { result.push_str("const "); } - if *abi != abi::Rust { + if abi != abi::Rust { result.push_str("extern "); result.push_str(&abi.to_string()); result.push(' '); @@ -497,11 +595,11 @@ impl<'a> FmtVisitor<'a> { } self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(span.lo + BytePos(enum_snippet.rfind('}').unwrap() as u32)); + self.format_missing_with_indent(span.hi - BytePos(1)); self.buffer.push_str("}"); } - // Variant of an enum + // Variant of an enum. fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_start: BytePos) { if self.visit_attrs(&field.node.attrs) { return; diff --git a/src/visitor.rs b/src/visitor.rs index f15c2e07b82..8c46d69ebfc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -132,12 +132,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { let indent = self.block_indent; let rewrite = match fk { - visit::FnKind::ItemFn(ident, - ref generics, - ref unsafety, - ref constness, - ref abi, - vis) => { + visit::FnKind::ItemFn(ident, ref generics, unsafety, constness, abi, vis) => { self.rewrite_fn(indent, ident, fd, @@ -155,9 +150,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { fd, Some(&sig.explicit_self), &sig.generics, - &sig.unsafety, - &sig.constness, - &sig.abi, + sig.unsafety, + sig.constness, + sig.abi, vis.unwrap_or(ast::Visibility::Inherited), codemap::mk_sp(s.lo, b.span.lo)) } @@ -224,6 +219,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { // See rust lang issue #28424. // visit::walk_item(self, item); } + ast::Item_::ItemForeignMod(ref foreign_mod) => { + self.format_missing_with_indent(item.span.lo); + self.format_foreign_mod(foreign_mod, item.span); + } _ => { visit::walk_item(self, item); } diff --git a/tests/source/extern.rs b/tests/source/extern.rs new file mode 100644 index 00000000000..2e7b6c14646 --- /dev/null +++ b/tests/source/extern.rs @@ -0,0 +1,21 @@ + + extern "C" { + fn c_func(x: *mut *mut libc::c_void); + + fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); + + #[test123] + fn foo() -> uint64_t; + +pub fn bar() ; + } + +extern { + fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, devNr: c_uint, wildcard: c_char) -> TDMR_ERROR; + + fn quux() -> (); // Post comment +} + +extern "Rust" { static ext: u32; + // Some comment. + pub static mut var : SomeType ; } diff --git a/tests/target/extern.rs b/tests/target/extern.rs new file mode 100644 index 00000000000..2c6f4936bff --- /dev/null +++ b/tests/target/extern.rs @@ -0,0 +1,29 @@ + +extern { + fn c_func(x: *mut *mut libc::c_void); + + fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, + y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); + + #[test123] + fn foo() -> uint64_t; + + pub fn bar(); +} + +extern { + fn DMR_GetDevice(pHDev: *mut HDEV, + searchMode: DeviceSearchMode, + pSearchString: *const c_char, + devNr: c_uint, + wildcard: c_char) + -> TDMR_ERROR; + + fn quux() -> (); // Post comment +} + +extern "Rust" { + static ext: u32; + // Some comment. + pub static mut var: SomeType; +} -- cgit 1.4.1-3-g733a5 From 106f7251fbe68a2e4a2b483fc4793f6bcd5d49a5 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 22 Sep 2015 06:57:52 +0530 Subject: Add tests, reformat expr --- src/expr.rs | 13 ++++++++++--- tests/source/expr.rs | 10 ++++++++++ tests/target/expr.rs | 12 ++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2c57bb5b64d..7bcf613b2e5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -667,8 +667,11 @@ fn rewrite_match(context: &RewriteContext, if !missed_str.is_empty() { result.push('\n'); result.push_str(&arm_indent_str); - result.push_str(&rewrite_comment(&missed_str, false, - width, arm_indent, context.config)); + result.push_str(&rewrite_comment(&missed_str, + false, + width, + arm_indent, + context.config)); } result.push('\n'); result.push_str(&arm_indent_str); @@ -698,7 +701,11 @@ fn rewrite_match(context: &RewriteContext, result.push('\n'); if last_comment.len() > 0 { result.push_str(&arm_indent_str); - result.push_str(&rewrite_comment(&last_comment, false, width, arm_indent, context.config)); + result.push_str(&rewrite_comment(&last_comment, + false, + width, + arm_indent, + context.config)); result.push('\n'); } result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index faa0d3775c7..03265da7e1c 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -130,6 +130,16 @@ fn issue184(source: &str) { } } +fn matches() { + match 1 { + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0 // baz + } +} + fn arrays() { let x = [0, 1, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index bb629f12126..007d0ec7cb0 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -167,6 +167,18 @@ fn issue184(source: &str) { } } +fn matches() { + match 1 { + 1 => 1, + // foo + 2 => 2, + // bar + 3 => 3, + _ => 0, + // baz + } +} + fn arrays() { let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; -- cgit 1.4.1-3-g733a5 From 5e2633b7420b0363720e1770b6c308cfabd0a8dd Mon Sep 17 00:00:00 2001 From: Robin Gloster Date: Wed, 23 Sep 2015 18:31:31 +0000 Subject: adapt to rust sytax::ast::Mac changes --- src/macros.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 8c38326ee8a..3fe0c2b1552 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -49,13 +49,12 @@ pub fn rewrite_macro(mac: &ast::Mac, width: usize, offset: Indent) -> Option { - let ast::Mac_::MacInvocTT(ref path, ref tt_vec, _) = mac.node; let style = macro_style(mac, context); - let macro_name = format!("{}!", path); + let macro_name = format!("{}!", mac.node.path); if let MacroStyle::Braces = style { return None; - } else if tt_vec.is_empty() { + } else if mac.node.tts.is_empty() { return if let MacroStyle::Parens = style { Some(format!("{}()", macro_name)) } else { @@ -63,7 +62,7 @@ pub fn rewrite_macro(mac: &ast::Mac, }; } - let wrapped_tt_vec = ForceSend((*tt_vec).clone()); + let wrapped_tt_vec = ForceSend(mac.node.tts.clone()); // Wrap expression parsing logic in a thread since the libsyntax parser // panicks on failure, which we do not want to propagate. let expr_vec_result = thread::catch_panic(move || { -- cgit 1.4.1-3-g733a5 From 19d1ec1dec74b549761b5561e7b722a11fb66ecd Mon Sep 17 00:00:00 2001 From: Scyptnex Date: Thu, 24 Sep 2015 10:22:06 +1000 Subject: Fixes #339 and #272 --- src/expr.rs | 116 +++++++++++++++++++++++++++++++------------------- tests/source/expr.rs | 58 +++++++++++++++++++++++++ tests/target/expr.rs | 54 +++++++++++++++++++++-- tests/target/match.rs | 3 +- 4 files changed, 181 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7bcf613b2e5..c633f59f21b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -320,6 +320,17 @@ fn rewrite_closure(capture: ast::CaptureClause, Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } +fn nop_block_collapse(block_str: Option) -> Option { + block_str.map(|block_str| { + if block_str.starts_with("{") && + (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { + "{}".to_owned() + } else { + block_str.to_owned() + } + }) +} + impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let user_str = context.snippet(self.span); @@ -620,6 +631,51 @@ fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { !contains_comment(&snippet) } +// inter-match-arm-comment-rules: +// - all comments following a match arm before the start of the next arm +// are about the second arm +fn rewrite_match_arm_comment(context: &RewriteContext, + missed_str: &str, + width: usize, + arm_indent: Indent, + arm_indent_str: &str) + -> String { + // The leading "," is not part of the arm-comment + let missed_str = match missed_str.find_uncommented(",") { + Some(n) => &missed_str[n+1..], + None => &missed_str[..], + }; + // Nor the trailing "}" which closes the match + let missed_str = match missed_str.find_uncommented("}") { + Some(n) => &missed_str[..n-1], + None => &missed_str[..], + }; + + let mut result = String::new(); + // any text not preceeded by a newline is pushed unmodified to the block + let first_brk = missed_str.find(|c: char| c == '\n').unwrap_or(0); + result.push_str(&missed_str[..first_brk]); + let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it + + let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or(missed_str.len()); + if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { + // Excessive vertical whitespace before comment should be preserved + // TODO handle vertical whitespace better + result.push('\n'); + } + let missed_str = missed_str[first..].trim(); + if !missed_str.is_empty() { + result.push('\n'); + result.push_str(arm_indent_str); + result.push_str(&rewrite_comment(&missed_str, + false, + width, + arm_indent, + context.config)); + } + return result; +} + fn rewrite_match(context: &RewriteContext, cond: &ast::Expr, arms: &[ast::Arm], @@ -647,32 +703,15 @@ fn rewrite_match(context: &RewriteContext, for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. let missed_str = if i == 0 { - context.snippet(mk_sp(open_brace_pos + BytePos(1), arm_start_pos(arm))) + context.snippet(mk_sp(open_brace_pos, arm_start_pos(arm))) } else { context.snippet(mk_sp(arm_end_pos(&arms[i-1]), arm_start_pos(arm))) }; - let missed_str = match missed_str.find_uncommented(",") { - Some(n) => &missed_str[n+1..], - None => &missed_str[..], - }; - // first = first non-whitespace byte index. - let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or(missed_str.len()); - if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { - // There were multiple line breaks which got trimmed to nothing - // that means there should be some vertical white space. Lets - // replace that with just one blank line. - result.push('\n'); - } - let missed_str = missed_str.trim(); - if !missed_str.is_empty() { - result.push('\n'); - result.push_str(&arm_indent_str); - result.push_str(&rewrite_comment(&missed_str, - false, - width, - arm_indent, - context.config)); - } + result.push_str(&rewrite_match_arm_comment(context, + &missed_str, + width, + arm_indent, + &arm_indent_str)); result.push('\n'); result.push_str(&arm_indent_str); @@ -688,26 +727,11 @@ fn rewrite_match(context: &RewriteContext, } } let last_comment = context.snippet(mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi)); - let last_comment = match last_comment.find_uncommented(",") { - Some(n) => &last_comment[n+1..], - None => &last_comment[..], - }; - let last_comment = match last_comment.find_uncommented("}") { - Some(n) => &last_comment[..n-1], - None => &last_comment[..], - }; - let last_comment = last_comment.trim(); - + result.push_str(&rewrite_match_arm_comment(context, + &last_comment, + width, arm_indent, + &arm_indent_str)); result.push('\n'); - if last_comment.len() > 0 { - result.push_str(&arm_indent_str); - result.push_str(&rewrite_comment(&last_comment, - false, - width, - arm_indent, - context.config)); - result.push('\n'); - } result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); result.push('}'); Some(result) @@ -817,7 +841,9 @@ impl Rewrite for ast::Arm { // 4 = ` => `.len() if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; - if let Some(ref body_str) = body.rewrite(context, budget, line_indent + 4) { + if let Some(ref body_str) = nop_block_collapse(body.rewrite(context, + budget, + line_indent + 4)) { if first_line_width(body_str) <= budget { return Some(format!("{}{} => {}{}", attr_str.trim_left(), @@ -835,7 +861,9 @@ impl Rewrite for ast::Arm { } let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let body_str = try_opt!(body.rewrite(context, body_budget, context.block_indent)); + let body_str = try_opt!(nop_block_collapse(body.rewrite(context, + body_budget, + context.block_indent))); Some(format!("{}{} =>\n{}{},", attr_str.trim_left(), pats_str, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 03265da7e1c..565ab7213cf 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -140,6 +140,64 @@ fn matches() { } } +fn issue339() { + match a { + b => {} + c => { } + d => { + } + e => { + + + + } + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { + } + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { // comment above block + } + i => { + } // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => { + } n => { } o => + { + + } + p => { // Dont collapse me + } q => { } r => + { + + } + s => 0, // s comment + // t comment + t => 1, + u => 2, + // TODO uncomment when block-support exists + // v => { + // } /* funky block + // * comment */ + // final comment + } +} + fn arrays() { let x = [0, 1, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 007d0ec7cb0..f6d543ab1d9 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -169,13 +169,59 @@ fn issue184(source: &str) { fn matches() { match 1 { - 1 => 1, - // foo + 1 => 1, // foo 2 => 2, // bar 3 => 3, - _ => 0, - // baz + _ => 0, // baz + } +} + +fn issue339() { + match a { + b => {} + c => {} + d => {} + e => {} + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { // comment above block + } + i => {} // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => {} + n => {} + o => {} + p => { // Dont collapse me + } + q => {} + r => {} + s => 0, // s comment + // t comment + t => 1, + u => 2, + // TODO uncomment when block-support exists + // v => { + // } /* funky block + // * comment */ + // final comment } } diff --git a/tests/target/match.rs b/tests/target/match.rs index e18c04bf02a..36d91b785f4 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -38,8 +38,7 @@ fn foo() { _ => {} ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || data.types.len() > 0 || - data.bindings.len() > 0 => { - } + data.bindings.len() > 0 => {} } let whatever = match something { -- cgit 1.4.1-3-g733a5 From f1dfab5a29bb86690ae56ce07c928104b59ae2d0 Mon Sep 17 00:00:00 2001 From: Scyptnex Date: Thu, 24 Sep 2015 12:01:48 +1000 Subject: fix for #355 and test cases --- src/expr.rs | 6 +++++- tests/source/expr.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++ tests/target/expr.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c633f59f21b..e38476df6fd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -151,7 +151,11 @@ impl Rewrite for ast::Expr { rewrite_chain(self, context, width, offset) } ast::Expr_::ExprMac(ref mac) => { - rewrite_macro(mac, context, width, offset) + // Failure to rewrite a marco should not imply failure to rewrite the Expr + rewrite_macro(mac, context, width, offset).or(wrap_str(context.snippet(self.span), + context.config.max_width, + width, + offset)) } // We do not format these expressions yet, but they should still // satisfy our width restrictions. diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 565ab7213cf..61acdafd7b0 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -198,6 +198,57 @@ fn issue339() { } } +fn issue355() { + match mac { + a => println!("a", b), + b => vec!(1, 2), + c => vec!(3; 4), + d => { + println!("a", b) + } + e => { + vec!(1, 2) + } + f => { + vec!(3; 4) + } + h => println!("a", b), // h comment + i => vec!(1, 2), // i comment + j => vec!(3; 4), // j comment + // k comment + k => println!("a", b), + // l comment + l => vec!(1, 2), + // m comment + m => vec!(3; 4), + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), + // Macro support fails to recognise this macro as splitable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), + // Funky bracketing styles + t => println!{"a", b}, + u => vec!{1, 2}, + v => vec!{3; 4}, + w => println!["a", b], + x => vec![1, 2], + y =>vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec!{1, 2}, // comment + vc =>vec!{3; 4}, // comment + wc =>println!["a", b], // comment + xc => vec![1,2], // comment + yc => vec![3; 4], // comment + } +} + fn arrays() { let x = [0, 1, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index f6d543ab1d9..ec00c8a0285 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -225,6 +225,63 @@ fn issue339() { } } +fn issue355() { + match mac { + a => println!("a", b), + b => vec!(1, 2), + c => vec!(3; 4), + d => { + println!("a", b) + } + e => { + vec!(1, 2) + } + f => { + vec!(3; 4) + } + h => println!("a", b), // h comment + i => vec!(1, 2), // i comment + j => vec!(3; 4), // j comment + // k comment + k => println!("a", b), + // l comment + l => vec!(1, 2), + // m comment + m => vec!(3; 4), + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", + b), + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, + 2), + // Macro support fails to recognise this macro as splitable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => + vec!(3; 4), + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => + println!("a", b), + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => + vec!(1, 2), + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => + vec!(3; 4), + // Funky bracketing styles + t => println!{"a", b}, + u => vec!{1, 2}, + v => vec!{3; 4}, + w => println!["a", b], + x => vec![1, 2], + y => vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec!{1, 2}, // comment + vc => vec!{3; 4}, // comment + wc => println!["a", b], // comment + xc => vec![1, 2], // comment + yc => vec![3; 4], // comment + } +} + fn arrays() { let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; -- cgit 1.4.1-3-g733a5 From ed597a8059f4e04d2ab7caa9afd1b0ee8f66095c Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 23 Sep 2015 22:51:37 -0700 Subject: Exhaustively enumerate expressions in expression rewriting. --- src/expr.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7bcf613b2e5..c1749668c57 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -155,7 +155,15 @@ impl Rewrite for ast::Expr { } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - _ => wrap_str(context.snippet(self.span), context.config.max_width, width, offset), + ast::Expr_::ExprBox(..) | + ast::Expr_::ExprCast(..) | + ast::Expr_::ExprIndex(..) | + ast::Expr_::ExprAddrOf(..) | + ast::Expr_::ExprRet(..) | + ast::Expr_::ExprInlineAsm(..) | + ast::Expr_::ExprRepeat(..) => { + wrap_str(context.snippet(self.span), context.config.max_width, width, offset) + } } } } -- cgit 1.4.1-3-g733a5 From 69da1a78dede33a1b312158cebddeb8a84950e44 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 23 Sep 2015 22:51:37 -0700 Subject: Add support for formatting "return" expressions. Fixes #303. --- src/expr.rs | 22 +++++++++++++++++----- src/issues.rs | 8 ++++---- tests/source/expr.rs | 6 ++++++ tests/target/expr.rs | 8 ++++++++ 4 files changed, 35 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c1749668c57..2f59f67ac83 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -153,13 +153,18 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprMac(ref mac) => { rewrite_macro(mac, context, width, offset) } + ast::Expr_::ExprRet(None) => { + wrap_str("return".to_owned(), context.config.max_width, width, offset) + } + ast::Expr_::ExprRet(Some(ref expr)) => { + rewrite_unary_prefix(context, "return ", &expr, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::Expr_::ExprBox(..) | ast::Expr_::ExprCast(..) | ast::Expr_::ExprIndex(..) | ast::Expr_::ExprAddrOf(..) | - ast::Expr_::ExprRet(..) | ast::Expr_::ExprInlineAsm(..) | ast::Expr_::ExprRepeat(..) => { wrap_str(context.snippet(self.span), context.config.max_width, width, offset) @@ -1294,6 +1299,16 @@ fn rewrite_binary_op(context: &RewriteContext, rhs_result)) } +fn rewrite_unary_prefix(context: &RewriteContext, + prefix: &str, + expr: &ast::Expr, + width: usize, + offset: Indent) + -> Option { + expr.rewrite(context, try_opt!(width.checked_sub(prefix.len())), offset + prefix.len()) + .map(|r| format!("{}{}", prefix, r)) +} + fn rewrite_unary_op(context: &RewriteContext, op: &ast::UnOp, expr: &ast::Expr, @@ -1307,10 +1322,7 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::UnNot => "!", ast::UnOp::UnNeg => "-", }; - let operator_len = operator_str.len(); - - expr.rewrite(context, try_opt!(width.checked_sub(operator_len)), offset + operator_len) - .map(|r| format!("{}{}", operator_str, r)) + rewrite_unary_prefix(context, operator_str, expr, width, offset) } fn rewrite_assignment(context: &RewriteContext, diff --git a/src/issues.rs b/src/issues.rs index 6b35add20bf..1c4cf562f05 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -144,9 +144,9 @@ impl BadIssueSeeker { true } else { false - } + }, }, - part: NumberPart::OpenParen + part: NumberPart::OpenParen, }; } fixme_idx = 0; @@ -162,9 +162,9 @@ impl BadIssueSeeker { true } else { false - } + }, }, - part: NumberPart::OpenParen + part: NumberPart::OpenParen, }; } todo_idx = 0; diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 03265da7e1c..0aa64d3abb8 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -183,3 +183,9 @@ fn arrays() { [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] } + +fn returns() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && return; + + return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 007d0ec7cb0..3e4c1b9a536 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -195,3 +195,11 @@ fn arrays() { [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } + +fn returns() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + return; + + return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +} -- cgit 1.4.1-3-g733a5 From 19e887c3097488b8d4d911b9423ffba1dec99987 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 24 Sep 2015 01:13:57 -0700 Subject: Add support for formatting AddrOf (unary "&"). --- src/chains.rs | 5 +---- src/expr.rs | 26 +++++++++++++++++++------- src/lists.rs | 5 ++++- tests/source/expr.rs | 5 +++++ tests/target/expr.rs | 7 +++++++ 5 files changed, 36 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c59638d9e50..f385012dadd 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -150,10 +150,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, -> Option { match expr.node { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { - let inner = &RewriteContext { - block_indent: offset, - ..*context - }; + let inner = &RewriteContext { block_indent: offset, ..*context }; rewrite_method_call(method_name.node, types, expressions, span, inner, width, offset) } ast::Expr_::ExprField(_, ref field) => { diff --git a/src/expr.rs b/src/expr.rs index b98756612d2..a2be6ee8fd1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -163,12 +163,14 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprRet(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", &expr, width, offset) } + ast::Expr_::ExprAddrOf(mutability, ref expr) => { + rewrite_expr_addrof(context, mutability, &expr, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::Expr_::ExprBox(..) | ast::Expr_::ExprCast(..) | ast::Expr_::ExprIndex(..) | - ast::Expr_::ExprAddrOf(..) | ast::Expr_::ExprInlineAsm(..) | ast::Expr_::ExprRepeat(..) => { wrap_str(context.snippet(self.span), context.config.max_width, width, offset) @@ -684,11 +686,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, if !missed_str.is_empty() { result.push('\n'); result.push_str(arm_indent_str); - result.push_str(&rewrite_comment(&missed_str, - false, - width, - arm_indent, - context.config)); + result.push_str(&rewrite_comment(&missed_str, false, width, arm_indent, context.config)); } return result; } @@ -746,7 +744,8 @@ fn rewrite_match(context: &RewriteContext, let last_comment = context.snippet(mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi)); result.push_str(&rewrite_match_arm_comment(context, &last_comment, - width, arm_indent, + width, + arm_indent, &arm_indent_str)); result.push('\n'); result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); @@ -1414,3 +1413,16 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, Some(result) } + +fn rewrite_expr_addrof(context: &RewriteContext, + mutability: ast::Mutability, + expr: &ast::Expr, + width: usize, + offset: Indent) + -> Option { + let operator_str = match mutability { + ast::Mutability::MutImmutable => "&", + ast::Mutability::MutMutable => "&mut ", + }; + rewrite_unary_prefix(context, operator_str, expr, width, offset) +} diff --git a/src/lists.rs b/src/lists.rs index e00e8b0ee37..60e5c7e5b56 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -200,7 +200,10 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let block_mode = tactic != ListTactic::Vertical; // Width restriction is only relevant in vertical mode. let max_width = formatting.v_width; - result.push_str(&rewrite_comment(comment, block_mode, max_width, formatting.indent, + result.push_str(&rewrite_comment(comment, + block_mode, + max_width, + formatting.indent, formatting.config)); if tactic == ListTactic::Vertical { diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 5cfd661d080..fc34f799d7d 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -298,3 +298,8 @@ fn returns() { return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; } + +fn addrof() { + & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index dc9ab9d71ef..34205819f60 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -306,3 +306,10 @@ fn returns() { return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; } + +fn addrof() { + &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); +} -- cgit 1.4.1-3-g733a5 From a7690cb1e5853f8206eea66018ff08fe393c533a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 25 Sep 2015 12:53:25 +0200 Subject: Make rewrite_string return `Option` --- src/comment.rs | 104 ++++++++++++++++++++++++++++++--------------------------- src/expr.rs | 42 ++++++++++++++--------- src/lists.rs | 31 ++++++++--------- src/string.rs | 39 +++++++++++++++++----- src/visitor.rs | 11 +++--- 5 files changed, 134 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 765d61cfa11..1e22a578eb1 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -21,7 +21,7 @@ pub fn rewrite_comment(orig: &str, width: usize, offset: Indent, config: &Config) - -> String { + -> Option { let s = orig.trim(); // Edge case: block comments. Let's not trim their lines (for now). @@ -47,49 +47,53 @@ pub fn rewrite_comment(orig: &str, let indent_str = offset.to_string(config); let line_breaks = s.chars().filter(|&c| c == '\n').count(); - let (_, mut s) = s.lines() - .enumerate() - .map(|(i, mut line)| { - line = line.trim(); - // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = &line[..(line.len() - 2)]; - } - - line.trim_right() - }) - .map(left_trim_comment_line) - .map(|line| { - if line_breaks == 0 { - line.trim_left() - } else { - line - } - }) - .fold((true, opener.to_owned()), - |(first, mut acc), line| { - if !first { - acc.push('\n'); - acc.push_str(&indent_str); - acc.push_str(line_start); - } - - if line.len() > max_chars { - acc.push_str(&rewrite_string(line, &fmt)); - } else { - if line.len() == 0 { - acc.pop(); // Remove space if this is an empty comment. - } else { - acc.push_str(line); - } - } - - (false, acc) - }); - - s.push_str(closer); - - s + let lines = s.lines() + .enumerate() + .map(|(i, mut line)| { + line = line.trim(); + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = &line[..(line.len() - 2)]; + } + + line.trim_right() + }) + .map(left_trim_comment_line) + .map(|line| { + if line_breaks == 0 { + line.trim_left() + } else { + line + } + }); + + let mut result = opener.to_owned(); + let mut first = true; + + for line in lines { + if !first { + result.push('\n'); + result.push_str(&indent_str); + result.push_str(line_start); + } + + if line.len() > max_chars { + let rewrite = try_opt!(rewrite_string(line, &fmt)); + result.push_str(&rewrite); + } else { + if line.len() == 0 { + result.pop(); // Remove space if this is an empty comment. + } else { + result.push_str(line); + } + } + + first = false; + } + + result.push_str(closer); + + Some(result) } fn left_trim_comment_line(line: &str) -> &str { @@ -294,33 +298,33 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { #[cfg(test)] mod test { use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented}; - use Indent; + #[test] #[rustfmt_skip] fn format_comments() { let config = Default::default(); assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100), - &config)); + &config).unwrap()); assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, - Indent::empty(), &config)); + Indent::empty(), &config).unwrap()); assert_eq!("// A multi line comment\n // between args.", rewrite_comment("// A multi line comment\n // between args.", false, 60, Indent::new(0, 12), - &config)); + &config).unwrap()); let input = "// comment"; let expected = "/* com\n \ * men\n \ * t */"; - assert_eq!(expected, rewrite_comment(input, true, 9, Indent::new(0, 69), &config)); + assert_eq!(expected, rewrite_comment(input, true, 9, Indent::new(0, 69), &config).unwrap()); assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, - Indent::new(0, 100), &config)); + Indent::new(0, 100), &config).unwrap()); } // This is probably intended to be a non-test fn, but it is not used. I'm diff --git a/src/expr.rs b/src/expr.rs index a2be6ee8fd1..2e87bfbc19a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -374,7 +374,11 @@ impl Rewrite for ast::Block { // 9 = "unsafe {".len(), 7 = "unsafe ".len() let budget = try_opt!(width.checked_sub(9)); format!("unsafe {} ", - rewrite_comment(trimmed, true, budget, offset + 7, context.config)) + try_opt!(rewrite_comment(trimmed, + true, + budget, + offset + 7, + context.config))) } else { "unsafe ".to_owned() }; @@ -658,7 +662,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, width: usize, arm_indent: Indent, arm_indent_str: &str) - -> String { + -> Option { // The leading "," is not part of the arm-comment let missed_str = match missed_str.find_uncommented(",") { Some(n) => &missed_str[n+1..], @@ -684,11 +688,17 @@ fn rewrite_match_arm_comment(context: &RewriteContext, } let missed_str = missed_str[first..].trim(); if !missed_str.is_empty() { + let comment = try_opt!(rewrite_comment(&missed_str, + false, + width, + arm_indent, + context.config)); result.push('\n'); result.push_str(arm_indent_str); - result.push_str(&rewrite_comment(&missed_str, false, width, arm_indent, context.config)); + result.push_str(&comment); } - return result; + + Some(result) } fn rewrite_match(context: &RewriteContext, @@ -722,11 +732,12 @@ fn rewrite_match(context: &RewriteContext, } else { context.snippet(mk_sp(arm_end_pos(&arms[i-1]), arm_start_pos(arm))) }; - result.push_str(&rewrite_match_arm_comment(context, - &missed_str, - width, - arm_indent, - &arm_indent_str)); + let comment = try_opt!(rewrite_match_arm_comment(context, + &missed_str, + width, + arm_indent, + &arm_indent_str)); + result.push_str(&comment); result.push('\n'); result.push_str(&arm_indent_str); @@ -742,11 +753,12 @@ fn rewrite_match(context: &RewriteContext, } } let last_comment = context.snippet(mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi)); - result.push_str(&rewrite_match_arm_comment(context, - &last_comment, - width, - arm_indent, - &arm_indent_str)); + let comment = try_opt!(rewrite_match_arm_comment(context, + &last_comment, + width, + arm_indent, + &arm_indent_str)); + result.push_str(&comment); result.push('\n'); result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); result.push('}'); @@ -1004,7 +1016,7 @@ fn rewrite_string_lit(context: &RewriteContext, let string_lit = context.snippet(span); let str_lit = &string_lit[1..string_lit.len() - 1]; // Remove the quote characters. - Some(rewrite_string(str_lit, &fmt)) + rewrite_string(str_lit, &fmt) } pub fn rewrite_call(context: &RewriteContext, diff --git a/src/lists.rs b/src/lists.rs index 60e5c7e5b56..aa82ec47964 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -200,11 +200,12 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let block_mode = tactic != ListTactic::Vertical; // Width restriction is only relevant in vertical mode. let max_width = formatting.v_width; - result.push_str(&rewrite_comment(comment, - block_mode, - max_width, - formatting.indent, - formatting.config)); + let comment = try_opt!(rewrite_comment(comment, + block_mode, + max_width, + formatting.indent, + formatting.config)); + result.push_str(&comment); if tactic == ListTactic::Vertical { result.push('\n'); @@ -221,11 +222,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op // Post-comments if tactic != ListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = rewrite_comment(comment, - true, - formatting.v_width, - Indent::empty(), - formatting.config); + let formatted_comment = try_opt!(rewrite_comment(comment, + true, + formatting.v_width, + Indent::empty(), + formatting.config)); result.push(' '); result.push_str(&formatted_comment); @@ -246,11 +247,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op comment.trim().contains('\n') || comment.trim().len() > width; - let formatted_comment = rewrite_comment(comment, - block_style, - width, - offset, - formatting.config); + let formatted_comment = try_opt!(rewrite_comment(comment, + block_style, + width, + offset, + formatting.config)); result.push(' '); result.push_str(&formatted_comment); diff --git a/src/string.rs b/src/string.rs index 4e40b8e9ede..ffaf52d3380 100644 --- a/src/string.rs +++ b/src/string.rs @@ -31,23 +31,23 @@ pub struct StringFormat<'a> { } // TODO: simplify this! -pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { +pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) // Strip line breaks. let re = Regex::new(r"(\\[:space:]+)").unwrap(); let stripped_str = re.replace_all(s, ""); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let indent = fmt.offset.to_string(fmt.config); - let indent = &indent; let mut cur_start = 0; let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); - let max_chars = fmt.width.checked_sub(fmt.opener.len() + ender_length).unwrap_or(1); + // If we cannot put at least a single character per line, the rewrite won't + // succeed. + let max_chars = try_opt!(fmt.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; loop { let mut cur_end = cur_start + max_chars; @@ -57,8 +57,9 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { result.push_str(line); break; } + // Push cur_end left until we reach whitespace. - while !(graphemes[cur_end - 1].trim().len() == 0) { + while !graphemes[cur_end - 1].trim().is_empty() { cur_end -= 1; if cur_end - cur_start < MIN_STRING { // We can't break at whitespace, fall back to splitting @@ -71,7 +72,7 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { } } // Make sure there is no whitespace to the right of the break. - while cur_end < s.len() && graphemes[cur_end].trim().len() == 0 { + while cur_end < s.len() && graphemes[cur_end].trim().is_empty() { cur_end += 1; } let raw_line = graphemes[cur_start..cur_end].join(""); @@ -85,12 +86,34 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> String { result.push_str(line); result.push_str(fmt.line_end); result.push('\n'); - result.push_str(indent); + result.push_str(&indent); result.push_str(fmt.line_start); cur_start = cur_end; } result.push_str(fmt.closer); - result + Some(result) +} + +#[cfg(test)] +mod test { + use super::{StringFormat, rewrite_string}; + + #[test] + fn issue343() { + let config = Default::default(); + let fmt = StringFormat { + opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + width: 2, + offset: ::Indent::empty(), + trim_end: false, + config: &config, + }; + + rewrite_string("eq_", &fmt); + } } diff --git a/src/visitor.rs b/src/visitor.rs index 8c46d69ebfc..1a070a839f5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -407,11 +407,12 @@ impl<'a> Rewrite for [ast::Attribute] { let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; let comment = comment.trim(); if !comment.is_empty() { - let comment = rewrite_comment(comment, - false, - context.config.max_width - offset.width(), - offset, - context.config); + let comment = try_opt!(rewrite_comment(comment, + false, + context.config.max_width - + offset.width(), + offset, + context.config)); result.push_str(&indent); result.push_str(&comment); result.push('\n'); -- cgit 1.4.1-3-g733a5 From bc0dd2c68dd5adf4bd4b512b186d59b5112e0376 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 25 Sep 2015 13:25:52 +0200 Subject: Adjust for changed representation of box expressions in AST --- src/expr.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a2be6ee8fd1..ef6ef12b96d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -163,12 +163,15 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprRet(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", &expr, width, offset) } + ast::Expr_::ExprBox(ref expr) => { + rewrite_unary_prefix(context, "box ", &expr, width, offset) + } ast::Expr_::ExprAddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, &expr, width, offset) } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::Expr_::ExprBox(..) | + ast::Expr_::ExprInPlace(..) | ast::Expr_::ExprCast(..) | ast::Expr_::ExprIndex(..) | ast::Expr_::ExprInlineAsm(..) | @@ -1348,7 +1351,6 @@ fn rewrite_unary_op(context: &RewriteContext, -> Option { // For some reason, an UnOp is not spanned like BinOp! let operator_str = match *op { - ast::UnOp::UnUniq => "box ", ast::UnOp::UnDeref => "*", ast::UnOp::UnNot => "!", ast::UnOp::UnNeg => "-", -- cgit 1.4.1-3-g733a5 From 5db17ca703d19e96408fad992a758c072a6a3e82 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 25 Sep 2015 16:53:44 +0200 Subject: Use the maximum available width in struct formatting Previously, we'd use an approximation for the maximum width since the configuration wasn't available in `write_list`. --- src/expr.rs | 7 ++++--- src/items.rs | 11 ++++++----- src/lists.rs | 8 +++++--- tests/source/structs.rs | 3 +++ tests/target/structs.rs | 5 +++++ 5 files changed, 23 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ef6ef12b96d..c1f211dbf36 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1152,9 +1152,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => field.span.lo, StructLitField::Base(ref expr) => { - let last_field_hi = fields.last() - .map_or(span.lo, - |field| field.span.hi); + let last_field_hi = fields.last().map_or(span.lo, + |field| { + field.span.hi + }); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); diff --git a/src/items.rs b/src/items.rs index 33e0a2a11b4..c2a8f46b3db 100644 --- a/src/items.rs +++ b/src/items.rs @@ -788,8 +788,8 @@ impl<'a> FmtVisitor<'a> { ends_with_newline: true, config: self.config, }; - let list_str = write_list(&items.collect::>(), &fmt).unwrap(); + let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); result.push_str(&list_str); if break_line { @@ -819,11 +819,12 @@ impl<'a> FmtVisitor<'a> { struct_def, Some(generics), span, - indent) - .unwrap(); + indent); - self.buffer.push_str(&result); - self.last_pos = span.hi; + if let Some(rewrite) = result { + self.buffer.push_str(&rewrite); + self.last_pos = span.hi; + } } fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { diff --git a/src/lists.rs b/src/lists.rs index 60e5c7e5b56..a6c0e862cce 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -214,9 +214,11 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op } } - let max_width = formatting.indent.width() + formatting.v_width; - let item_str = wrap_str(&item.item[..], max_width, formatting.v_width, formatting.indent); - result.push_str(&&try_opt!(item_str)); + let item_str = try_opt!(wrap_str(&item.item[..], + formatting.config.max_width, + formatting.v_width, + formatting.indent)); + result.push_str(&item_str); // Post-comments if tactic != ListTactic::Vertical && item.post_comment.is_some() { diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 76602a7a561..bd9db77fec0 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -102,3 +102,6 @@ pub struct State time::Timespec> { now: F } pub struct State ()> { now: F } pub struct State { now: F } + +struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color + foo: i32} diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 31e32a51b42..67060ddf80e 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -95,3 +95,8 @@ pub struct State ()> { pub struct State { now: F, } + +struct Palette { + /// A map of indizes in the palette to a count of pixels in approximately that color + foo: i32, +} -- cgit 1.4.1-3-g733a5 From 92fbb80097bf172339b11a6387edacbc87c8dc07 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 24 Sep 2015 08:36:21 +1200 Subject: Formatting of some types Closes #341 --- src/types.rs | 36 +++++++++++++++++++++++++++++++++--- tests/source/multiple.rs | 2 ++ tests/target/multiple.rs | 3 +++ 3 files changed, 38 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 9ba50a59cd9..28465404988 100644 --- a/src/types.rs +++ b/src/types.rs @@ -15,7 +15,7 @@ use syntax::codemap::{self, Span, BytePos, CodeMap}; use Indent; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, span_after}; +use utils::{extra_offset, span_after, format_mutability}; impl Rewrite for ast::Path { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { @@ -437,9 +437,39 @@ impl Rewrite for ast::Ty { p.rewrite(context, width, offset) } ast::TyObjectSum(ref ty, ref bounds) => { + let ty_str = try_opt!(ty.rewrite(context, width, offset)); + let overhead = ty_str.len() + 3; Some(format!("{} + {}", - try_opt!(ty.rewrite(context, width, offset)), - try_opt!(bounds.rewrite(context, width, offset)))) + ty_str, + try_opt!(bounds.rewrite(context, + try_opt!(width.checked_sub(overhead)), + offset + overhead)))) + } + ast::TyRptr(ref lifetime, ref mt) => { + let mut_str = format_mutability(mt.mutbl); + let mut_len = mut_str.len(); + Some(match lifetime { + &Some(ref lifetime) => { + let lt_str = pprust::lifetime_to_string(lifetime); + let lt_len = lt_str.len(); + format!("&{} {}{}", + lt_str, + mut_str, + try_opt!(mt.ty.rewrite(context, + width - (2 + mut_len + lt_len), + offset + 2 + mut_len + lt_len))) + } + &None => { + format!("&{}{}", + mut_str, + try_opt!(mt.ty.rewrite(context, + width - (1 + mut_len), + offset + 1 + mut_len))) + } + }) + } + ast::TyParen(ref ty) => { + ty.rewrite(context, width - 2, offset + 1).map(|ty_str| format!("({})", ty_str)) } _ => Some(pprust::ty_to_string(self)), } diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index abc16035be2..a0a3f2599e8 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -92,6 +92,8 @@ pub struct Foo<'a, Y: Baz> f: SomeType, // Comment beside a field } +fn foo(ann: &'a (PpAnn+'a)) {} + fn main() { for i in 0i32..4 { println!("{}", i); diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 9ff3f2cf7a8..c2e2a471afc 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -117,6 +117,9 @@ pub struct Foo<'a, Y: Baz> f: SomeType, // Comment beside a field } +fn foo(ann: &'a (PpAnn + 'a)) { +} + fn main() { for i in 0i32..4 { println!("{}", i); -- cgit 1.4.1-3-g733a5 From ebf64ca35df03737e9850ab940125b21ba64ff16 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 24 Sep 2015 11:00:14 +1200 Subject: Heuristic max width for function calls --- src/config.rs | 7 +++++-- src/items.rs | 2 +- src/lists.rs | 22 ++++++++++++++++++++++ src/types.rs | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c5b777e1d81..4779d0e9b98 100644 --- a/src/config.rs +++ b/src/config.rs @@ -215,9 +215,11 @@ macro_rules! create_config { create_config! { max_width: usize, "Maximum width of each line", - ideal_width: usize, "Ideal width of each line", - leeway: usize, "Leeway of line width", + ideal_width: usize, "Ideal width of each line (only used for comments)", + leeway: usize, "Leeway of line width (deprecated)", tab_spaces: usize, "Number of spaces per tab", + list_width: usize, "Maximum width in a struct literal or function \ + call before faling back to vertical formatting", newline_style: NewlineStyle, "Unix or Windows line endings", fn_brace_style: BraceStyle, "Brace style for functions", fn_return_indent: ReturnIndent, "Location of return type in function declaration", @@ -256,6 +258,7 @@ impl Default for Config { ideal_width: 80, leeway: 5, tab_spaces: 4, + list_width: 50, newline_style: NewlineStyle::Unix, fn_brace_style: BraceStyle::SameLineWhere, fn_return_indent: ReturnIndent::WithArgs, diff --git a/src/items.rs b/src/items.rs index c2a8f46b3db..3656fcdf982 100644 --- a/src/items.rs +++ b/src/items.rs @@ -948,7 +948,7 @@ impl<'a> FmtVisitor<'a> { item.item = ty; } - let fmt = ListFormatting::for_fn(h_budget, offset, self.config); + let fmt = ListFormatting::for_item(h_budget, offset, self.config); let list_str = try_opt!(write_list(&items, &fmt)); Some(format!("<{}>", list_str)) diff --git a/src/lists.rs b/src/lists.rs index cccb8d37b08..cf1d433a25c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -26,6 +26,8 @@ pub enum ListTactic { Horizontal, // Try Horizontal layout, if that fails then vertical HorizontalVertical, + // HorizontalVertical with a soft limit. + LimitedHorizontalVertical(usize), // Pack as many items as possible per row over (possibly) many rows. Mixed, } @@ -59,6 +61,19 @@ pub struct ListFormatting<'a> { impl<'a> ListFormatting<'a> { pub fn for_fn(width: usize, offset: Indent, config: &'a Config) -> ListFormatting<'a> { + ListFormatting { + tactic: ListTactic::LimitedHorizontalVertical(config.list_width), + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + h_width: width, + v_width: width, + ends_with_newline: false, + config: config, + } + } + + pub fn for_item(width: usize, offset: Indent, config: &'a Config) -> ListFormatting<'a> { ListFormatting { tactic: ListTactic::HorizontalVertical, separator: ",", @@ -118,6 +133,13 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let fits_single = total_width + total_sep_len <= formatting.h_width; // Check if we need to fallback from horizontal listing, if possible. + if let ListTactic::LimitedHorizontalVertical(limit) = tactic { + if total_width > limit { + tactic = ListTactic::Vertical; + } else { + tactic = ListTactic::HorizontalVertical; + } + } if tactic == ListTactic::HorizontalVertical { debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", total_width, diff --git a/src/types.rs b/src/types.rs index 28465404988..b1af98afbda 100644 --- a/src/types.rs +++ b/src/types.rs @@ -230,7 +230,7 @@ fn rewrite_segment(segment: &ast::PathSegment, list_lo, span_hi); - let fmt = ListFormatting::for_fn(list_width, offset + extra_offset, context.config); + let fmt = ListFormatting::for_item(list_width, offset + extra_offset, context.config); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); // Update position of last bracket. -- cgit 1.4.1-3-g733a5 From 99d71a164aaed7817abe981d57b346fb2921c41d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 24 Sep 2015 11:01:01 +1200 Subject: Changes to source formatting --- src/chains.rs | 13 +++++++++++-- src/comment.rs | 10 +++++++--- src/expr.rs | 53 +++++++++++++++++++++++++++++++++++++++++------------ src/filemap.rs | 3 ++- src/issues.rs | 18 +++++++++++++----- src/items.rs | 13 ++++++++++--- src/lib.rs | 6 ++++-- src/macros.rs | 5 ++++- src/missed_spans.rs | 3 ++- src/modules.rs | 5 ++++- src/types.rs | 7 +++++-- src/visitor.rs | 8 ++++++-- 12 files changed, 109 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f385012dadd..6ad6123408a 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -126,7 +126,10 @@ pub fn rewrite_chain(mut expr: &ast::Expr, &connector[..] }; - Some(format!("{}{}{}", parent_rewrite, first_connector, rewrites.join(&connector))) + Some(format!("{}{}{}", + parent_rewrite, + first_connector, + rewrites.join(&connector))) } fn pop_expr_chain<'a>(expr: &'a ast::Expr) -> Option<&'a ast::Expr> { @@ -151,7 +154,13 @@ fn rewrite_chain_expr(expr: &ast::Expr, match expr.node { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { let inner = &RewriteContext { block_indent: offset, ..*context }; - rewrite_method_call(method_name.node, types, expressions, span, inner, width, offset) + rewrite_method_call(method_name.node, + types, + expressions, + span, + inner, + width, + offset) } ast::Expr_::ExprField(_, ref field) => { Some(format!(".{}", field.node)) diff --git a/src/comment.rs b/src/comment.rs index 1e22a578eb1..f5ba982ecc0 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -343,8 +343,10 @@ mod test { #[test] fn test_uncommented() { assert_eq!(&uncommented("abc/*...*/"), "abc"); - assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); - assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); + assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), + "..ac\n"); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), + "abc \" /* */\" qsdf"); } #[test] @@ -365,7 +367,9 @@ mod test { check("/*/ */test", "test", Some(6)); check("//test\ntest", "test", Some(7)); check("/* comment only */", "whatever", None); - check("/* comment */ some text /* more commentary */ result", "result", Some(46)); + check("/* comment */ some text /* more commentary */ result", + "result", + Some(46)); check("sup // sup", "p", Some(2)); check("sup", "x", None); check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); diff --git a/src/expr.rs b/src/expr.rs index b3e5fee176d..4d64efda4df 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -32,7 +32,11 @@ impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { ast::Expr_::ExprVec(ref expr_vec) => { - rewrite_array(expr_vec.iter().map(|e| &**e), self.span, context, width, offset) + rewrite_array(expr_vec.iter().map(|e| &**e), + self.span, + context, + width, + offset) } ast::Expr_::ExprLit(ref l) => { match l.node { @@ -176,7 +180,10 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprIndex(..) | ast::Expr_::ExprInlineAsm(..) | ast::Expr_::ExprRepeat(..) => { - wrap_str(context.snippet(self.span), context.config.max_width, width, offset) + wrap_str(context.snippet(self.span), + context.config.max_width, + width, + offset) } } } @@ -507,7 +514,13 @@ impl<'a> Rewrite for Loop<'a> { // FIXME: this drops any comment between "loop" and the block. self.block .rewrite(context, width, offset) - .map(|result| format!("{}{}{} {}", label_string, self.keyword, pat_expr_string, result)) + .map(|result| { + format!("{}{}{} {}", + label_string, + self.keyword, + pat_expr_string, + result) + }) } } @@ -1108,7 +1121,9 @@ fn rewrite_paren(context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("rewrite_paren, width: {}, offset: {:?}", width, offset); + debug!("rewrite_paren, width: {}, offset: {:?}", + width, + offset); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr. let subexpr_str = subexpr.rewrite(context, try_opt!(width.checked_sub(2)), offset + 1); @@ -1124,7 +1139,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("rewrite_struct_lit: width {}, offset {:?}", width, offset); + debug!("rewrite_struct_lit: width {}, offset {:?}", + width, + offset); assert!(!fields.is_empty() || base.is_some()); enum StructLitField<'a> { @@ -1229,10 +1246,15 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, .block_indent(context.config) .to_string(context.config); let outer_indent = context.block_indent.to_string(context.config); - Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) + Some(format!("{} {{\n{}{}\n{}}}", + path_str, + inner_indent, + fields_str, + outer_indent)) }; - match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { + match (context.config.struct_lit_style, + context.config.struct_lit_multiline_style) { (StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => format_on_newline(), (StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(), @@ -1250,8 +1272,9 @@ fn rewrite_field(context: &RewriteContext, -> Option { let name = &field.ident.node.to_string(); let overhead = name.len() + 2; - let expr = field.expr - .rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); + let expr = field.expr.rewrite(context, + try_opt!(width.checked_sub(overhead)), + offset + overhead); expr.map(|s| format!("{}: {}", name, s)) } @@ -1261,7 +1284,9 @@ fn rewrite_tuple_lit(context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset); + debug!("rewrite_tuple_lit: width: {}, offset: {:?}", + width, + offset); let indent = offset + 1; // In case of length 1, need a trailing comma if items.len() == 1 { @@ -1352,7 +1377,9 @@ fn rewrite_unary_prefix(context: &RewriteContext, width: usize, offset: Indent) -> Option { - expr.rewrite(context, try_opt!(width.checked_sub(prefix.len())), offset + prefix.len()) + expr.rewrite(context, + try_opt!(width.checked_sub(prefix.len())), + offset + prefix.len()) .map(|r| format!("{}{}", prefix, r)) } @@ -1385,7 +1412,9 @@ fn rewrite_assignment(context: &RewriteContext, // 1 = space between lhs and operator. let max_width = try_opt!(width.checked_sub(operator_str.len() + 1)); - let lhs_str = format!("{} {}", try_opt!(lhs.rewrite(context, max_width, offset)), operator_str); + let lhs_str = format!("{} {}", + try_opt!(lhs.rewrite(context, max_width, offset)), + operator_str); rewrite_assign_rhs(&context, lhs_str, rhs, width, offset) } diff --git a/src/filemap.rs b/src/filemap.rs index d94c1501734..f3f952bd00c 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -115,7 +115,8 @@ fn write_file(text: &StringBuffer, try!(write_system_newlines(&mut v, text, config)); let fmt_text = String::from_utf8(v).unwrap(); let diff = make_diff(&ori_text, &fmt_text, 3); - print_diff(diff, |line_num| format!("\nDiff at line {}:", line_num)); + print_diff(diff, + |line_num| format!("\nDiff at line {}:", line_num)); } WriteMode::Return => { // io::Write is not implemented for String, working around with diff --git a/src/issues.rs b/src/issues.rs index 1c4cf562f05..90123cf63e1 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -224,12 +224,14 @@ impl BadIssueSeeker { fn find_unnumbered_issue() { fn check_fail(text: &str, failing_pos: usize) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(Some(failing_pos), text.chars().position(|c| seeker.inspect(c).is_some())); + assert_eq!(Some(failing_pos), + text.chars().position(|c| seeker.inspect(c).is_some())); } fn check_pass(text: &str) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); + assert_eq!(None, + text.chars().position(|c| seeker.inspect(c).is_some())); } check_fail("TODO\n", 4); @@ -256,11 +258,17 @@ fn find_issue() { ReportTactic::Always, ReportTactic::Never)); - assert!(!is_bad_issue("TODO: no number\n", ReportTactic::Never, ReportTactic::Always)); + assert!(!is_bad_issue("TODO: no number\n", + ReportTactic::Never, + ReportTactic::Always)); - assert!(is_bad_issue("This is a FIXME(#1)\n", ReportTactic::Never, ReportTactic::Always)); + assert!(is_bad_issue("This is a FIXME(#1)\n", + ReportTactic::Never, + ReportTactic::Always)); - assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Always, ReportTactic::Never)); + assert!(!is_bad_issue("bad FIXME\n", + ReportTactic::Always, + ReportTactic::Never)); } #[test] diff --git a/src/items.rs b/src/items.rs index 3656fcdf982..efd2c852c3e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -307,7 +307,9 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let ret_str = fd.output - .rewrite(&context, self.config.max_width - indent.width(), indent) + .rewrite(&context, + self.config.max_width - indent.width(), + indent) .unwrap(); // Args. @@ -1011,7 +1013,9 @@ impl<'a> FmtVisitor<'a> { // 9 = " where ".len() + " {".len() if density == Density::Tall || preds_str.contains('\n') || indent.width() + 9 + preds_str.len() > self.config.max_width { - Some(format!("\n{}where {}", (indent + extra_indent).to_string(self.config), preds_str)) + Some(format!("\n{}where {}", + (indent + extra_indent).to_string(self.config), + preds_str)) } else { Some(format!(" where {}", preds_str)) } @@ -1041,7 +1045,10 @@ impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if is_named_arg(self) { if let ast::Ty_::TyInfer = self.ty.node { - wrap_str(pprust::pat_to_string(&self.pat), context.config.max_width, width, offset) + wrap_str(pprust::pat_to_string(&self.pat), + context.config.max_width, + width, + offset) } else { let mut result = pprust::pat_to_string(&self.pat); result.push_str(": "); diff --git a/src/lib.rs b/src/lib.rs index 30150537309..73184a0bdc1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,7 +115,8 @@ impl Indent { pub fn to_string(&self, config: &Config) -> String { let (num_tabs, num_spaces) = if config.hard_tabs { - (self.block_indent / config.tab_spaces, self.alignment) + (self.block_indent / config.tab_spaces, + self.alignment) } else { (0, self.block_indent + self.alignment) }; @@ -146,7 +147,8 @@ impl Sub for Indent { type Output = Indent; fn sub(self, rhs: Indent) -> Indent { - Indent::new(self.block_indent - rhs.block_indent, self.alignment - rhs.alignment) + Indent::new(self.block_indent - rhs.block_indent, + self.alignment - rhs.alignment) } } diff --git a/src/macros.rs b/src/macros.rs index 3fe0c2b1552..163a9f12f24 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -103,7 +103,10 @@ pub fn rewrite_macro(mac: &ast::Mac, } MacroStyle::Braces => { // Skip macro invocations with braces, for now. - wrap_str(context.snippet(mac.span), context.config.max_width, width, offset) + wrap_str(context.snippet(mac.span), + context.config.max_width, + width, + offset) } } } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index db9599c1706..135e6c3815b 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -16,7 +16,8 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| this.buffer.push_str(last_snippet)) + self.format_missing_inner(end, + |this, last_snippet, _| this.buffer.push_str(last_snippet)) } pub fn format_missing_with_indent(&mut self, end: BytePos) { diff --git a/src/modules.rs b/src/modules.rs index b50c9e26895..3f96bea9d44 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -25,7 +25,10 @@ pub fn list_files<'a>(krate: &'a ast::Crate, -> HashMap { let mut result = HashMap::new(); let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); - list_submodules(&krate.module, root_filename.parent().unwrap(), codemap, &mut result); + list_submodules(&krate.module, + root_filename.parent().unwrap(), + codemap, + &mut result); result.insert(root_filename, &krate.module); result } diff --git a/src/types.rs b/src/types.rs index b1af98afbda..33446765c8c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -205,7 +205,9 @@ fn rewrite_segment(segment: &ast::PathSegment, .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); - let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); + let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), + "<", + context.codemap); let separator = get_path_separator(context.codemap, *span_lo, list_lo); // 1 for < @@ -363,7 +365,8 @@ impl Rewrite for ast::TyParamBound { tref.rewrite(context, width, offset) } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { - Some(format!("?{}", try_opt!(tref.rewrite(context, width - 1, offset + 1)))) + Some(format!("?{}", + try_opt!(tref.rewrite(context, width - 1, offset + 1)))) } ast::TyParamBound::RegionTyParamBound(ref l) => { Some(pprust::lifetime_to_string(l)) diff --git a/src/visitor.rs b/src/visitor.rs index 1a070a839f5..5faff9e6d11 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -316,7 +316,9 @@ impl<'a> FmtVisitor<'a> { } fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { - debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); + debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", + ident, + s); // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); @@ -354,7 +356,9 @@ impl<'a> FmtVisitor<'a> { overflow_indent: Indent::empty(), }; // 1 = ";" - match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { + match vp.rewrite(&context, + self.config.max_width - offset.width() - 1, + offset) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, span.lo); -- cgit 1.4.1-3-g733a5 From d161b8df72877eae5f99f84bfe20b9efdda2cf73 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 26 Sep 2015 14:00:19 +1200 Subject: rebasing changes and address review comment --- src/expr.rs | 10 ++++++++-- src/lists.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4d64efda4df..79e03e644e4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -162,7 +162,10 @@ impl Rewrite for ast::Expr { offset)) } ast::Expr_::ExprRet(None) => { - wrap_str("return".to_owned(), context.config.max_width, width, offset) + wrap_str("return".to_owned(), + context.config.max_width, + width, + offset) } ast::Expr_::ExprRet(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", &expr, width, offset) @@ -652,7 +655,10 @@ fn single_line_if_else(context: &RewriteContext, let fits_line = fixed_cost + pat_expr_str.len() + if_str.len() + else_str.len() <= width; if fits_line && !if_str.contains('\n') && !else_str.contains('\n') { - return Some(format!("if {} {{ {} }} else {{ {} }}", pat_expr_str, if_str, else_str)); + return Some(format!("if {} {{ {} }} else {{ {} }}", + pat_expr_str, + if_str, + else_str)); } } diff --git a/src/lists.rs b/src/lists.rs index cf1d433a25c..ef3372bf0b6 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -26,7 +26,7 @@ pub enum ListTactic { Horizontal, // Try Horizontal layout, if that fails then vertical HorizontalVertical, - // HorizontalVertical with a soft limit. + // HorizontalVertical with a soft limit of n characters. LimitedHorizontalVertical(usize), // Pack as many items as possible per row over (possibly) many rows. Mixed, -- cgit 1.4.1-3-g733a5 From b2e7da0aa00297ff346fa15685995ee07e3b4c01 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 26 Sep 2015 18:12:25 +1200 Subject: Format imports with aliases. Closes #366 --- src/imports.rs | 44 +++++++++++++++++++++++++++++++------------- tests/source/imports.rs | 6 ++++++ tests/target/imports.rs | 6 ++++++ 3 files changed, 43 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index f5f81015efb..64633d2d4ff 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -48,14 +48,16 @@ impl Rewrite for ast::ViewPath { } } -fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { - if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { +fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { + let path_item_str = if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { + // A name. if path_str.is_empty() { name.to_string() } else { format!("{}::{}", path_str, name) } } else { + // `self`. if !path_str.is_empty() { path_str } else { @@ -63,6 +65,31 @@ fn rewrite_single_use_list(path_str: String, vpi: ast::PathListItem) -> String { // leave it alone. "{self}".to_owned() } + }; + + append_alias(path_item_str, vpi) +} + +fn rewrite_path_item(vpi: &&ast::PathListItem) -> String { + let path_item_str = match vpi.node { + ast::PathListItem_::PathListIdent{ name, .. } => { + name.to_string() + } + ast::PathListItem_::PathListMod{ .. } => { + "self".to_owned() + } + }; + + append_alias(path_item_str, vpi) +} + +fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { + match vpi.node { + ast::PathListItem_::PathListIdent{ rename: Some(rename), .. } | + ast::PathListItem_::PathListMod{ rename: Some(rename), .. } => { + format!("{} as {}", path_item_str, rename) + } + _ => path_item_str, } } @@ -80,7 +107,7 @@ pub fn rewrite_use_list(width: usize, match path_list.len() { 0 => unreachable!(), - 1 => return Some(rewrite_single_use_list(path_str, path_list[0])), + 1 => return Some(rewrite_single_use_list(path_str, &path_list[0])), _ => (), } @@ -117,16 +144,7 @@ pub fn rewrite_use_list(width: usize, "}", |vpi| vpi.span.lo, |vpi| vpi.span.hi, - |vpi| { - match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => { - name.to_string() - } - ast::PathListItem_::PathListMod{ .. } => { - "self".to_owned() - } - } - }, + rewrite_path_item, span_after(span, "{", context.codemap), span.hi); items.extend(iter); diff --git a/tests/source/imports.rs b/tests/source/imports.rs index 92380ea51b0..ab850f416fb 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -44,3 +44,9 @@ use Baz::*; use foo::bar::baz as baz ; use bar::quux as kaas; use foo; + +// With aliases. +use foo::{self as bar, baz}; +use foo::{self as bar}; +use foo::{qux as bar}; +use foo::{baz, qux as bar}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 07449a51982..948b6da7c2b 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -38,3 +38,9 @@ fn test() { use foo::bar::baz; use bar::quux as kaas; use foo; + +// With aliases. +use foo::{self as bar, baz}; +use foo as bar; +use foo::qux as bar; +use foo::{baz, qux as bar}; -- cgit 1.4.1-3-g733a5 From b894dd8abf93a56355437282c9eef2bda5b85f8c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 26 Sep 2015 18:25:41 +1200 Subject: Use a width heuristic for struct lits. Closes #123 --- src/config.rs | 9 ++++++--- src/expr.rs | 6 +++++- src/lists.rs | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 4779d0e9b98..02076174482 100644 --- a/src/config.rs +++ b/src/config.rs @@ -218,8 +218,10 @@ create_config! { ideal_width: usize, "Ideal width of each line (only used for comments)", leeway: usize, "Leeway of line width (deprecated)", tab_spaces: usize, "Number of spaces per tab", - list_width: usize, "Maximum width in a struct literal or function \ - call before faling back to vertical formatting", + fn_call_width: usize, "Maximum width of the args of a function call\ + before faling back to vertical formatting", + struct_lit_width: usize, "Maximum width in the body of a struct lit\ + before faling back to vertical formatting", newline_style: NewlineStyle, "Unix or Windows line endings", fn_brace_style: BraceStyle, "Brace style for functions", fn_return_indent: ReturnIndent, "Location of return type in function declaration", @@ -258,7 +260,8 @@ impl Default for Config { ideal_width: 80, leeway: 5, tab_spaces: 4, - list_width: 50, + fn_call_width: 50, + struct_lit_width: 12, newline_style: NewlineStyle::Unix, fn_brace_style: BraceStyle::SameLineWhere, fn_return_indent: ReturnIndent::WithArgs, diff --git a/src/expr.rs b/src/expr.rs index 79e03e644e4..f2e6b1e0dfa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1226,11 +1226,15 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span_after(span, "{", context.codemap), span.hi); - let tactic = match (context.config.struct_lit_style, fields.len()) { + let mut tactic = match (context.config.struct_lit_style, fields.len()) { (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style.to_list_tactic(), }; + if tactic == ListTactic::HorizontalVertical && fields.len() > 1 { + tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); + } + let fmt = ListFormatting { tactic: tactic, separator: ",", diff --git a/src/lists.rs b/src/lists.rs index ef3372bf0b6..c372be2fe8f 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -62,7 +62,7 @@ pub struct ListFormatting<'a> { impl<'a> ListFormatting<'a> { pub fn for_fn(width: usize, offset: Indent, config: &'a Config) -> ListFormatting<'a> { ListFormatting { - tactic: ListTactic::LimitedHorizontalVertical(config.list_width), + tactic: ListTactic::LimitedHorizontalVertical(config.fn_call_width), separator: ",", trailing_separator: SeparatorTactic::Never, indent: offset, -- cgit 1.4.1-3-g733a5 From 617eed353cd52007667df8cbd647634014ec0211 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 26 Sep 2015 18:29:48 +1200 Subject: Changes to rustfmt source --- src/comment.rs | 5 ++++- src/issues.rs | 30 ++++++++++++++++++++++++------ src/lib.rs | 25 ++++++++++++++++++++----- src/lists.rs | 7 ++++++- src/rustfmt_diff.rs | 5 ++++- src/visitor.rs | 5 ++++- 6 files changed, 62 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index f5ba982ecc0..b08e46681a7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -212,7 +212,10 @@ enum CodeCharKind { impl CharClasses where T: Iterator, T::Item: RichChar { fn new(base: T) -> CharClasses { - CharClasses { base: base.peekable(), status: CharClassesStatus::Normal } + CharClasses { + base: base.peekable(), + status: CharClassesStatus::Normal, + } } } diff --git a/src/issues.rs b/src/issues.rs index 90123cf63e1..2a5eaae287a 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -101,7 +101,10 @@ pub struct BadIssueSeeker { impl BadIssueSeeker { pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { BadIssueSeeker { - state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 }, + state: Seeking::Issue { + todo_idx: 0, + fixme_idx: 0, + }, report_todo: report_todo, report_fixme: report_fixme, } @@ -121,7 +124,10 @@ impl BadIssueSeeker { return None; } - self.state = Seeking::Issue { todo_idx: 0, fixme_idx: 0 }; + self.state = Seeking::Issue { + todo_idx: 0, + fixme_idx: 0, + }; if let IssueClassification::Bad(issue) = result { return Some(issue); @@ -173,7 +179,10 @@ impl BadIssueSeeker { fixme_idx = 0; } - Seeking::Issue { todo_idx: todo_idx, fixme_idx: fixme_idx } + Seeking::Issue { + todo_idx: todo_idx, + fixme_idx: fixme_idx, + } } fn inspect_number(&mut self, @@ -214,7 +223,10 @@ impl BadIssueSeeker { NumberPart::CloseParen => {} } - self.state = Seeking::Number { part: part, issue: issue }; + self.state = Seeking::Number { + part: part, + issue: issue, + }; IssueClassification::None } @@ -274,7 +286,10 @@ fn find_issue() { #[test] fn issue_type() { let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); - let expected = Some(Issue { issue_type: IssueType::Todo, missing_number: false }); + let expected = Some(Issue { + issue_type: IssueType::Todo, + missing_number: false, + }); assert_eq!(expected, "TODO(#100): more awesomeness" @@ -284,7 +299,10 @@ fn issue_type() { .unwrap()); let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); - let expected = Some(Issue { issue_type: IssueType::Fixme, missing_number: true }); + let expected = Some(Issue { + issue_type: IssueType::Fixme, + missing_number: true, + }); assert_eq!(expected, "Test. FIXME: bad, bad, not good" diff --git a/src/lib.rs b/src/lib.rs index 73184a0bdc1..19398208a77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,7 +92,10 @@ pub struct Indent { impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { - Indent { block_indent: block_indent, alignment: alignment } + Indent { + block_indent: block_indent, + alignment: alignment, + } } pub fn empty() -> Indent { @@ -304,7 +307,10 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { // Add warnings for bad todos/ fixmes if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { line: cur_line, kind: ErrorKind::BadIssue(issue) }); + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::BadIssue(issue), + }); } if c == '\n' { @@ -315,7 +321,10 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } // Check for any line width errors we couldn't correct. if line_len > config.max_width { - errors.push(FormattingError { line: cur_line, kind: ErrorKind::LineOverflow }); + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::LineOverflow, + }); } line_len = 0; cur_line += 1; @@ -340,7 +349,10 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } for &(l, _, _) in &trims { - errors.push(FormattingError { line: l, kind: ErrorKind::TrailingWhitespace }); + errors.push(FormattingError { + line: l, + kind: ErrorKind::TrailingWhitespace, + }); } report.file_error_map.insert(f.to_owned(), errors); @@ -395,7 +407,10 @@ pub fn format(args: Vec, config: &Config) -> FileMap { { let config = Rc::new(config.clone()); - let mut call_ctxt = RustFmtCalls { config: config, result: result.clone() }; + let mut call_ctxt = RustFmtCalls { + config: config, + result: result.clone(), + }; rustc_driver::run_compiler(&args, &mut call_ctxt); } diff --git a/src/lists.rs b/src/lists.rs index c372be2fe8f..12eebb7b691 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -107,7 +107,12 @@ impl ListItem { } pub fn from_str>(s: S) -> ListItem { - ListItem { pre_comment: None, item: s.into(), post_comment: None, new_lines: false } + ListItem { + pre_comment: None, + item: s.into(), + post_comment: None, + new_lines: false, + } } } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 375cfd661fa..8c20b8f5a0f 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -15,7 +15,10 @@ pub struct Mismatch { impl Mismatch { fn new(line_number: u32) -> Mismatch { - Mismatch { line_number: line_number, lines: Vec::new() } + Mismatch { + line_number: line_number, + lines: Vec::new(), + } } } diff --git a/src/visitor.rs b/src/visitor.rs index 5faff9e6d11..883d46a22d4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -275,7 +275,10 @@ impl<'a> FmtVisitor<'a> { codemap: codemap, buffer: StringBuffer::new(), last_pos: BytePos(0), - block_indent: Indent { block_indent: 0, alignment: 0 }, + block_indent: Indent { + block_indent: 0, + alignment: 0, + }, config: config, } } -- cgit 1.4.1-3-g733a5 From 078fff068a3d0e5401bd46214c112cb9276a6240 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 26 Sep 2015 18:16:07 +0200 Subject: Improve heuristics for match arm body placement --- src/expr.rs | 68 +++++++++++----- src/items.rs | 4 +- tests/source/expr.rs | 119 ---------------------------- tests/source/match.rs | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/target/expr.rs | 115 --------------------------- tests/target/match.rs | 142 +++++++++++++++++++++++++++++---- 6 files changed, 386 insertions(+), 273 deletions(-) create mode 100644 tests/source/match.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 79e03e644e4..29966d09da9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -15,7 +15,7 @@ use Indent; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; -use utils::{span_after, extra_offset, first_line_width, last_line_width, wrap_str, binary_search}; +use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search}; use visitor::FmtVisitor; use config::{StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; @@ -352,9 +352,9 @@ fn rewrite_closure(capture: ast::CaptureClause, Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } -fn nop_block_collapse(block_str: Option) -> Option { +fn nop_block_collapse(block_str: Option, budget: usize) -> Option { block_str.map(|block_str| { - if block_str.starts_with("{") && + if block_str.starts_with("{") && budget >= 2 && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { "{}".to_owned() } else { @@ -889,36 +889,64 @@ impl Rewrite for ast::Arm { // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() - if context.config.max_width > line_start + comma.len() + 4 { + let same_line_body = if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; - if let Some(ref body_str) = nop_block_collapse(body.rewrite(context, - budget, - line_indent + 4)) { - if first_line_width(body_str) <= budget { + let rewrite = nop_block_collapse(body.rewrite(context, budget, line_indent + 4), + budget); + + match rewrite { + Some(ref body_str) if body_str.len() <= budget || comma.is_empty() => return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, body_str, - comma)); - } + comma)), + _ => rewrite, } - } + } else { + None + }; // We have to push the body to the next line. - if comma.is_empty() { + if let ast::ExprBlock(_) = body.node { // We're trying to fit a block in, but it still failed, give up. return None; } let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let body_str = try_opt!(nop_block_collapse(body.rewrite(context, - body_budget, - context.block_indent))); - Some(format!("{}{} =>\n{}{},", - attr_str.trim_left(), - pats_str, - offset.block_indent(context.config).to_string(context.config), - body_str)) + let next_line_body = nop_block_collapse(body.rewrite(context, + body_budget, + context.block_indent + .block_indent(context.config)), + body_budget); + + let (body_str, break_line) = try_opt!(match_arm_heuristic(same_line_body.as_ref() + .map(|x| &x[..]), + next_line_body.as_ref() + .map(|x| &x[..]))); + + let spacer = if break_line { + format!("\n{}", offset.block_indent(context.config).to_string(context.config)) + } else { + " ".to_owned() + }; + + Some(format!("{}{} =>{}{},", attr_str.trim_left(), pats_str, spacer, body_str)) + } +} + +// Takes two possible rewrites for the match arm body and chooses the "nicest". +// Bool marks break line or no. +fn match_arm_heuristic<'a>(former: Option<&'a str>, + latter: Option<&'a str>) + -> Option<(&'a str, bool)> { + match (former, latter) { + (Some(f), None) => Some((f, false)), + (Some(f), Some(l)) if f.chars().filter(|&c| c == '\n').count() <= + l.chars().filter(|&c| c == '\n').count() => { + Some((f, false)) + } + (_, l) => l.map(|s| (s, true)), } } diff --git a/src/items.rs b/src/items.rs index efd2c852c3e..ec79040f59c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -969,8 +969,8 @@ impl<'a> FmtVisitor<'a> { let extra_indent = match self.config.where_indent { BlockIndentStyle::Inherit => Indent::empty(), - BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => Indent::new(config.tab_spaces, - 0), + BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => + Indent::new(config.tab_spaces, 0), }; let context = self.get_context(); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index fc34f799d7d..96ad42cd77d 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -130,125 +130,6 @@ fn issue184(source: &str) { } } -fn matches() { - match 1 { - 1 => 1, // foo - 2 => 2, - // bar - 3 => 3, - _ => 0 // baz - } -} - -fn issue339() { - match a { - b => {} - c => { } - d => { - } - e => { - - - - } - // collapsing here is safe - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { - } - // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } - h => { // comment above block - } - i => { - } // comment below block - j => { - // comment inside block - } - j2 => { - // comments inside... - } // ... and after - // TODO uncomment when vertical whitespace is handled better - // k => { - // - // // comment with WS above - // } - // l => { - // // comment with ws below - // - // } - m => { - } n => { } o => - { - - } - p => { // Dont collapse me - } q => { } r => - { - - } - s => 0, // s comment - // t comment - t => 1, - u => 2, - // TODO uncomment when block-support exists - // v => { - // } /* funky block - // * comment */ - // final comment - } -} - -fn issue355() { - match mac { - a => println!("a", b), - b => vec!(1, 2), - c => vec!(3; 4), - d => { - println!("a", b) - } - e => { - vec!(1, 2) - } - f => { - vec!(3; 4) - } - h => println!("a", b), // h comment - i => vec!(1, 2), // i comment - j => vec!(3; 4), // j comment - // k comment - k => println!("a", b), - // l comment - l => vec!(1, 2), - // m comment - m => vec!(3; 4), - // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), - // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), - // Macro support fails to recognise this macro as splitable - // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), - // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), - // Funky bracketing styles - t => println!{"a", b}, - u => vec!{1, 2}, - v => vec!{3; 4}, - w => println!["a", b], - x => vec![1, 2], - y =>vec![3; 4], - // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec!{1, 2}, // comment - vc =>vec!{3; 4}, // comment - wc =>println!["a", b], // comment - xc => vec![1,2], // comment - yc => vec![3; 4], // comment - } -} - fn arrays() { let x = [0, 1, diff --git a/tests/source/match.rs b/tests/source/match.rs new file mode 100644 index 00000000000..9fc32ef1904 --- /dev/null +++ b/tests/source/match.rs @@ -0,0 +1,211 @@ +// Match expressions. + +fn foo() { + // A match expression. + match x { + // Some comment. + a => foo(), + b if 0 < 42 => foo(), + c => { // Another comment. + // Comment. + an_expression; + foo() + } + // Perhaps this should introduce braces? + Foo(ref bar) => + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Pattern1 | Pattern2 | Pattern3 => false, + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + blah + } + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn => meh, + + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, + + Patternnnnnnnnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => + meh, + + // Test that earlier patterns can take the guard space + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} + + _ => {} + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => {} + } + + let whatever = match something { + /// DOC COMMENT! + Some(_) => 42, + // Comment on an attribute. + #[an_attribute] + // Comment after an attribute. + None => 0, + #[rustfmt_skip] + Blurb => { } + }; +} + +// Test that a match on an overflow line is laid out properly. +fn main() { + let sub_span = + match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; +} + +// Test that one-line bodies align. +fn main() { + match r { + Variableeeeeeeeeeeeeeeeee => ( "variable", + vec!("id", "name", "qualname", + "value", "type", "scopeid"), + true, + true), + Enummmmmmmmmmmmmmmmmmmmm => ("enum", + vec!("id","qualname","scopeid","value"), + true, + true), + Variantttttttttttttttttttttttt => ("variant", + vec!("id", + "name", + "qualname", + "type", + "value", + "scopeid"), + true, + true), + } +} + +fn matches() { + match 1 { + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0 // baz + } +} + +fn issue339() { + match a { + b => {} + c => { } + d => { + } + e => { + + + + } + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { + } + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { // comment above block + } + i => { + } // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => { + } n => { } o => + { + + } + p => { // Dont collapse me + } q => { } r => + { + + } + s => 0, // s comment + // t comment + t => 1, + u => 2, + // TODO uncomment when block-support exists + // v => { + // } /* funky block + // * comment */ + // final comment + } +} + +fn issue355() { + match mac { + a => println!("a", b), + b => vec!(1, 2), + c => vec!(3; 4), + d => { + println!("a", b) + } + e => { + vec!(1, 2) + } + f => { + vec!(3; 4) + } + h => println!("a", b), // h comment + i => vec!(1, 2), // i comment + j => vec!(3; 4), // j comment + // k comment + k => println!("a", b), + // l comment + l => vec!(1, 2), + // m comment + m => vec!(3; 4), + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), + // Macro support fails to recognise this macro as splitable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), + // Funky bracketing styles + t => println!{"a", b}, + u => vec!{1, 2}, + v => vec!{3; 4}, + w => println!["a", b], + x => vec![1, 2], + y =>vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec!{1, 2}, // comment + vc =>vec!{3; 4}, // comment + wc =>println!["a", b], // comment + xc => vec![1,2], // comment + yc => vec![3; 4], // comment + yd => + looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd), + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 34205819f60..f31f27f59d4 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -167,121 +167,6 @@ fn issue184(source: &str) { } } -fn matches() { - match 1 { - 1 => 1, // foo - 2 => 2, - // bar - 3 => 3, - _ => 0, // baz - } -} - -fn issue339() { - match a { - b => {} - c => {} - d => {} - e => {} - // collapsing here is safe - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} - // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } - h => { // comment above block - } - i => {} // comment below block - j => { - // comment inside block - } - j2 => { - // comments inside... - } // ... and after - // TODO uncomment when vertical whitespace is handled better - // k => { - // - // // comment with WS above - // } - // l => { - // // comment with ws below - // - // } - m => {} - n => {} - o => {} - p => { // Dont collapse me - } - q => {} - r => {} - s => 0, // s comment - // t comment - t => 1, - u => 2, - // TODO uncomment when block-support exists - // v => { - // } /* funky block - // * comment */ - // final comment - } -} - -fn issue355() { - match mac { - a => println!("a", b), - b => vec!(1, 2), - c => vec!(3; 4), - d => { - println!("a", b) - } - e => { - vec!(1, 2) - } - f => { - vec!(3; 4) - } - h => println!("a", b), // h comment - i => vec!(1, 2), // i comment - j => vec!(3; 4), // j comment - // k comment - k => println!("a", b), - // l comment - l => vec!(1, 2), - // m comment - m => vec!(3; 4), - // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", - b), - // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, - 2), - // Macro support fails to recognise this macro as splitable - // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => - vec!(3; 4), - // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => - println!("a", b), - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => - vec!(1, 2), - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => - vec!(3; 4), - // Funky bracketing styles - t => println!{"a", b}, - u => vec!{1, 2}, - v => vec!{3; 4}, - w => println!["a", b], - x => vec![1, 2], - y => vec![3; 4], - // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec!{1, 2}, // comment - vc => vec!{3; 4}, // comment - wc => println!["a", b], // comment - xc => vec![1, 2], // comment - yc => vec![3; 4], // comment - } -} - fn arrays() { let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; diff --git a/tests/target/match.rs b/tests/target/match.rs index 36d91b785f4..3a8bee35aac 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -65,22 +65,130 @@ fn main() { // Test that one-line bodies align. fn main() { match r { - Variableeeeeeeeeeeeeeeeee => ("variable", - vec!("id", "name", "qualname", "value", "type", "scopeid"), - true, - true), - Enummmmmmmmmmmmmmmmmmmmm => ("enum", - vec!("id", "qualname", "scopeid", "value"), - true, - true), - Variantttttttttttttttttttttttt => ("variant", - vec!("id", - "name", - "qualname", - "type", - "value", - "scopeid"), - true, - true), + Variableeeeeeeeeeeeeeeeee => + ("variable", vec!("id", "name", "qualname", "value", "type", "scopeid"), true, true), + Enummmmmmmmmmmmmmmmmmmmm => + ("enum", vec!("id", "qualname", "scopeid", "value"), true, true), + Variantttttttttttttttttttttttt => + ("variant", vec!("id", "name", "qualname", "type", "value", "scopeid"), true, true), + } +} + +fn matches() { + match 1 { + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0, // baz + } +} + +fn issue339() { + match a { + b => {} + c => {} + d => {} + e => {} + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { // comment above block + } + i => {} // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => {} + n => {} + o => {} + p => { // Dont collapse me + } + q => {} + r => {} + s => 0, // s comment + // t comment + t => 1, + u => 2, + // TODO uncomment when block-support exists + // v => { + // } /* funky block + // * comment */ + // final comment + } +} + +fn issue355() { + match mac { + a => println!("a", b), + b => vec!(1, 2), + c => vec!(3; 4), + d => { + println!("a", b) + } + e => { + vec!(1, 2) + } + f => { + vec!(3; 4) + } + h => println!("a", b), // h comment + i => vec!(1, 2), // i comment + j => vec!(3; 4), // j comment + // k comment + k => println!("a", b), + // l comment + l => vec!(1, 2), + // m comment + m => vec!(3; 4), + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => + println!("a", b), + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => + vec!(1, 2), + // Macro support fails to recognise this macro as splitable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => + vec!(3; 4), + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => + println!("a", b), + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => + vec!(1, 2), + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => + vec!(3; 4), + // Funky bracketing styles + t => println!{"a", b}, + u => vec!{1, 2}, + v => vec!{3; 4}, + w => println!["a", b], + x => vec![1, 2], + y => vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec!{1, 2}, // comment + vc => vec!{3; 4}, // comment + wc => println!["a", b], // comment + xc => vec![1, 2], // comment + yc => vec![3; 4], // comment + yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd), } } -- cgit 1.4.1-3-g733a5 From 2d4a0cbe3b7a4c8f94bb1d422993ff856d714dae Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 26 Sep 2015 23:16:11 +0200 Subject: Fix match arm indentation bug --- src/expr.rs | 39 +++++++++++++++++++++------------------ src/lib.rs | 4 ++-- tests/target/match.rs | 17 ++++++++++++----- 3 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 29966d09da9..b8a52a02cc7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -155,11 +155,14 @@ impl Rewrite for ast::Expr { rewrite_chain(self, context, width, offset) } ast::Expr_::ExprMac(ref mac) => { - // Failure to rewrite a marco should not imply failure to rewrite the Expr - rewrite_macro(mac, context, width, offset).or(wrap_str(context.snippet(self.span), - context.config.max_width, - width, - offset)) + // Failure to rewrite a marco should not imply failure to + // rewrite the expression. + rewrite_macro(mac, context, width, offset).or_else(|| { + wrap_str(context.snippet(self.span), + context.config.max_width, + width, + offset) + }) } ast::Expr_::ExprRet(None) => { wrap_str("return".to_owned(), @@ -168,10 +171,10 @@ impl Rewrite for ast::Expr { offset) } ast::Expr_::ExprRet(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &expr, width, offset) + rewrite_unary_prefix(context, "return ", expr, width, offset) } ast::Expr_::ExprBox(ref expr) => { - rewrite_unary_prefix(context, "box ", &expr, width, offset) + rewrite_unary_prefix(context, "box ", expr, width, offset) } ast::Expr_::ExprAddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, &expr, width, offset) @@ -872,15 +875,10 @@ impl Rewrite for ast::Arm { let pats_str = format!("{}{}", pats_str, guard_str); // Where the next text can start. let mut line_start = last_line_width(&pats_str); - if pats_str.find('\n').is_none() { + if !pats_str.contains('\n') { line_start += offset.width(); } - let mut line_indent = offset + pats_width; - if vertical { - line_indent = line_indent.block_indent(context.config); - } - let comma = if let ast::ExprBlock(_) = body.node { "" } else { @@ -891,8 +889,9 @@ impl Rewrite for ast::Arm { // 4 = ` => `.len() let same_line_body = if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; - let rewrite = nop_block_collapse(body.rewrite(context, budget, line_indent + 4), - budget); + let offset = Indent::new(offset.block_indent, + line_start + 4 - offset.block_indent); + let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); match rewrite { Some(ref body_str) if body_str.len() <= budget || comma.is_empty() => @@ -907,7 +906,6 @@ impl Rewrite for ast::Arm { None }; - // We have to push the body to the next line. if let ast::ExprBlock(_) = body.node { // We're trying to fit a block in, but it still failed, give up. return None; @@ -926,12 +924,17 @@ impl Rewrite for ast::Arm { .map(|x| &x[..]))); let spacer = if break_line { - format!("\n{}", offset.block_indent(context.config).to_string(context.config)) + format!("\n{}", + offset.block_indent(context.config).to_string(context.config)) } else { " ".to_owned() }; - Some(format!("{}{} =>{}{},", attr_str.trim_left(), pats_str, spacer, body_str)) + Some(format!("{}{} =>{}{},", + attr_str.trim_left(), + pats_str, + spacer, + body_str)) } } diff --git a/src/lib.rs b/src/lib.rs index 73184a0bdc1..b483cae60d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,9 +85,9 @@ const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; pub struct Indent { // Width of the block indent, in characters. Must be a multiple of // Config::tab_spaces. - block_indent: usize, + pub block_indent: usize, // Alignment in characters. - alignment: usize, + pub alignment: usize, } impl Indent { diff --git a/tests/target/match.rs b/tests/target/match.rs index 3a8bee35aac..d7227a0da59 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -65,12 +65,19 @@ fn main() { // Test that one-line bodies align. fn main() { match r { - Variableeeeeeeeeeeeeeeeee => - ("variable", vec!("id", "name", "qualname", "value", "type", "scopeid"), true, true), - Enummmmmmmmmmmmmmmmmmmmm => - ("enum", vec!("id", "qualname", "scopeid", "value"), true, true), + Variableeeeeeeeeeeeeeeeee => ("variable", + vec!("id", "name", "qualname", "value", "type", "scopeid"), + true, + true), + Enummmmmmmmmmmmmmmmmmmmm => ("enum", + vec!("id", "qualname", "scopeid", "value"), + true, + true), Variantttttttttttttttttttttttt => - ("variant", vec!("id", "name", "qualname", "type", "value", "scopeid"), true, true), + ("variant", + vec!("id", "name", "qualname", "type", "value", "scopeid"), + true, + true), } } -- cgit 1.4.1-3-g733a5 From 224eecce5078b54771906da85788b4b836deea0e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 27 Sep 2015 19:25:04 +1300 Subject: Minor refactoring in compute_budgets_for_args --- src/items.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index efd2c852c3e..3cf12b68a82 100644 --- a/src/items.rs +++ b/src/items.rs @@ -513,8 +513,6 @@ impl<'a> FmtVisitor<'a> { ret_str_len: usize, newline_brace: bool) -> (usize, usize, Indent) { - let mut budgets = None; - // Try keeping everything on the same line if !result.contains("\n") { // 3 = `() `, space is before ret_string @@ -535,26 +533,23 @@ impl<'a> FmtVisitor<'a> { used_space, max_space); if used_space < max_space { - budgets = Some((one_line_budget, - max_space - used_space, - indent + result.len() + 1)); + return (one_line_budget, + max_space - used_space, + indent + result.len() + 1); } } // Didn't work. we must force vertical layout and put args on a newline. - if let None = budgets { - let new_indent = indent.block_indent(self.config); - let used_space = new_indent.width() + 2; // account for `(` and `)` - let max_space = self.config.ideal_width + self.config.leeway; - if used_space > max_space { - // Whoops! bankrupt. - // TODO: take evasive action, perhaps kill the indent or something. - } else { - budgets = Some((0, max_space - used_space, new_indent)); - } + let new_indent = indent.block_indent(self.config); + let used_space = new_indent.width() + 2; // account for `(` and `)` + let max_space = self.config.ideal_width + self.config.leeway; + if used_space <= max_space { + (0, max_space - used_space, new_indent) + } else { + // Whoops! bankrupt. + // TODO: take evasive action, perhaps kill the indent or something. + panic!("in compute_budgets_for_args"); } - - budgets.unwrap() } fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { -- cgit 1.4.1-3-g733a5 From bc59f83f02d8350c84fed9ce47a910f651d8a48d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 27 Sep 2015 19:30:32 +1300 Subject: Use max width for function decls, etc. We were using ideal width + leeway before. This means we can remove leeway from the config. We could remove ideal_width too, but I want to use it for comments. --- src/config.rs | 2 -- src/items.rs | 10 +++++----- tests/config/small_tabs.toml | 1 - 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 02076174482..b21fe3d2a07 100644 --- a/src/config.rs +++ b/src/config.rs @@ -216,7 +216,6 @@ macro_rules! create_config { create_config! { max_width: usize, "Maximum width of each line", ideal_width: usize, "Ideal width of each line (only used for comments)", - leeway: usize, "Leeway of line width (deprecated)", tab_spaces: usize, "Number of spaces per tab", fn_call_width: usize, "Maximum width of the args of a function call\ before faling back to vertical formatting", @@ -258,7 +257,6 @@ impl Default for Config { Config { max_width: 100, ideal_width: 80, - leeway: 5, tab_spaces: 4, fn_call_width: 50, struct_lit_width: 12, diff --git a/src/items.rs b/src/items.rs index 3cf12b68a82..13e06d0b438 100644 --- a/src/items.rs +++ b/src/items.rs @@ -528,7 +528,7 @@ impl<'a> FmtVisitor<'a> { // 2 = `()` let used_space = indent.width() + result.len() + 2; - let max_space = self.config.ideal_width + self.config.leeway; + let max_space = self.config.max_width; debug!("compute_budgets_for_args: used_space: {}, max_space: {}", used_space, max_space); @@ -542,7 +542,7 @@ impl<'a> FmtVisitor<'a> { // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(self.config); let used_space = new_indent.width() + 2; // account for `(` and `)` - let max_space = self.config.ideal_width + self.config.leeway; + let max_space = self.config.max_width; if used_space <= max_space { (0, max_space - used_space, new_indent) } else { @@ -637,7 +637,7 @@ impl<'a> FmtVisitor<'a> { } else { 0 }; - let budget = self.config.ideal_width - indent.width() - comma_cost - 1; // 1 = ) + let budget = self.config.max_width - indent.width() - comma_cost - 1; // 1 = ) let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical, @@ -774,7 +774,7 @@ impl<'a> FmtVisitor<'a> { }; // 1 = , - let budget = self.config.ideal_width - offset.width() + self.config.tab_spaces - 1; + let budget = self.config.max_width - offset.width() + self.config.tab_spaces - 1; let fmt = ListFormatting { tactic: tactic, separator: ",", @@ -979,7 +979,7 @@ impl<'a> FmtVisitor<'a> { // FIXME: if where_pred_indent != Visual, then the budgets below might // be out by a char or two. - let budget = self.config.ideal_width + self.config.leeway - offset.width(); + let budget = self.config.max_width - offset.width(); let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; let items = itemize_list(self.codemap, where_clause.predicates.iter(), diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 754cde57cd9..1681aff77b4 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -1,6 +1,5 @@ max_width = 100 ideal_width = 80 -leeway = 5 tab_spaces = 2 newline_style = "Unix" fn_brace_style = "SameLineWhere" -- cgit 1.4.1-3-g733a5 From 2eb67827a7a34c9bb221710763f6d16fb4555a24 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Sep 2015 11:58:26 +0200 Subject: Add extra tests for match arm placement --- src/expr.rs | 28 +++++++++++----------------- tests/source/match.rs | 12 ++++++++++++ tests/target/match.rs | 11 +++++++++++ 3 files changed, 34 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b8a52a02cc7..38305fc7d62 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -918,16 +918,13 @@ impl Rewrite for ast::Arm { .block_indent(context.config)), body_budget); - let (body_str, break_line) = try_opt!(match_arm_heuristic(same_line_body.as_ref() - .map(|x| &x[..]), - next_line_body.as_ref() - .map(|x| &x[..]))); - - let spacer = if break_line { - format!("\n{}", - offset.block_indent(context.config).to_string(context.config)) - } else { - " ".to_owned() + let body_str = try_opt!(match_arm_heuristic(same_line_body.as_ref().map(|x| &x[..]), + next_line_body.as_ref().map(|x| &x[..]))); + + let spacer = match same_line_body { + Some(ref body) if body == body_str => " ".to_owned(), + _ => format!("\n{}", + offset.block_indent(context.config).to_string(context.config)), }; Some(format!("{}{} =>{}{},", @@ -939,17 +936,14 @@ impl Rewrite for ast::Arm { } // Takes two possible rewrites for the match arm body and chooses the "nicest". -// Bool marks break line or no. -fn match_arm_heuristic<'a>(former: Option<&'a str>, - latter: Option<&'a str>) - -> Option<(&'a str, bool)> { +fn match_arm_heuristic<'a>(former: Option<&'a str>, latter: Option<&'a str>) -> Option<&'a str> { match (former, latter) { - (Some(f), None) => Some((f, false)), + (f @ Some(..), None) => f, (Some(f), Some(l)) if f.chars().filter(|&c| c == '\n').count() <= l.chars().filter(|&c| c == '\n').count() => { - Some((f, false)) + Some(f) } - (_, l) => l.map(|s| (s, true)), + (_, l) => l, } } diff --git a/tests/source/match.rs b/tests/source/match.rs index 9fc32ef1904..49e66e4c0df 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -209,3 +209,15 @@ fn issue355() { dddddddddd), } } + +fn issue280() { + { + match x { + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == + '\n', + ast::ItemConst(ref typ, ref expr) => self.process_static_or_const_item(item, + &typ, + &expr), + } + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index d7227a0da59..6e330505a9b 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -199,3 +199,14 @@ fn issue355() { dddddddddd), } } + +fn issue280() { + { + match x { + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => + ch == '\n', + ast::ItemConst(ref typ, ref expr) => + self.process_static_or_const_item(item, &typ, &expr), + } + } +} -- cgit 1.4.1-3-g733a5 From a673fef844fdd8c5d1b1924ab1e823e1e7f9a360 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Sep 2015 17:23:37 +0200 Subject: Fix variant name duplication on rewrite failure --- src/items.rs | 10 +--------- tests/target/enum.rs | 6 ++++++ 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ec79040f59c..74a3e3a148d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -611,10 +611,7 @@ impl<'a> FmtVisitor<'a> { let result = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { - let name = field.node.name.to_string(); - self.buffer.push_str(&name); - - let mut result = String::new(); + let mut result = field.node.name.to_string(); if !types.is_empty() { let items = itemize_list(self.codemap, @@ -667,11 +664,6 @@ impl<'a> FmtVisitor<'a> { result.push_str(" = "); let expr_snippet = self.snippet(expr.span); result.push_str(&expr_snippet); - - // Make sure we do not exceed column limit - assert!(self.config.max_width >= - name.len() + expr_snippet.len() + " = ,".len(), - "Enum variant exceeded column limit"); } result diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 2e2e47e25c2..2d87c4e862b 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -45,3 +45,9 @@ enum StructLikeVariants { a: A, }, } + +enum X { + CreateWebGLPaintTask(Size2D, + GLContextAttributes, + IpcSender, usize), String>>), +} -- cgit 1.4.1-3-g733a5 From 431e8d9d2f4ae87b898624d7874fe19cc8ac0dc6 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Sep 2015 17:56:38 +0200 Subject: Remove a few unchecked subtractions, uses of ty_to_string --- src/imports.rs | 6 ++++-- src/types.rs | 67 ++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 64633d2d4ff..8c3545f2e12 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -36,7 +36,8 @@ impl Rewrite for ast::ViewPath { ast::ViewPath_::ViewPathSimple(ident, ref path) => { let ident_str = ident.to_string(); // 4 = " as ".len() - let path_str = try_opt!(path.rewrite(context, width - ident_str.len() - 4, offset)); + let budget = try_opt!(width.checked_sub(ident_str.len() + 4)); + let path_str = try_opt!(path.rewrite(context, budget, offset)); Some(if path.segments.last().unwrap().identifier == ident { path_str @@ -103,7 +104,8 @@ pub fn rewrite_use_list(width: usize, context: &RewriteContext) -> Option { // 1 = {} - let path_str = try_opt!(path.rewrite(context, width - 1, offset)); + let budget = try_opt!(width.checked_sub(1)); + let path_str = try_opt!(path.rewrite(context, budget, offset)); match path_list.len() { 0 => unreachable!(), diff --git a/src/types.rs b/src/types.rs index 33446765c8c..28980174314 100644 --- a/src/types.rs +++ b/src/types.rs @@ -15,7 +15,7 @@ use syntax::codemap::{self, Span, BytePos, CodeMap}; use Indent; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, span_after, format_mutability}; +use utils::{extra_offset, span_after, format_mutability, wrap_str}; impl Rewrite for ast::Path { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { @@ -49,7 +49,7 @@ pub fn rewrite_path(context: &RewriteContext, let extra_offset = extra_offset(&result, offset); // 3 = ">::".len() - let budget = try_opt!(width.checked_sub(extra_offset)) - 3; + let budget = try_opt!(width.checked_sub(extra_offset + 3)); result = try_opt!(rewrite_path_segments(result, path.segments.iter().take(skip_count), @@ -242,25 +242,28 @@ fn rewrite_segment(segment: &ast::PathSegment, } ast::PathParameters::ParenthesizedParameters(ref data) => { let output = match data.output { - Some(ref ty) => format!(" -> {}", pprust::ty_to_string(&*ty)), + Some(ref ty) => { + let type_str = try_opt!(ty.rewrite(context, width, offset)); + format!(" -> {}", type_str) + } None => String::new(), }; + // 2 for () + let budget = try_opt!(width.checked_sub(output.len() + 2)); + // 1 for ( + let offset = offset + 1; let list_lo = span_after(data.span, "(", context.codemap); let items = itemize_list(context.codemap, data.inputs.iter(), ")", |ty| ty.span.lo, |ty| ty.span.hi, - |ty| pprust::ty_to_string(ty), + |ty| ty.rewrite(context, budget, offset).unwrap(), list_lo, span_hi); - // 2 for () - let budget = try_opt!(width.checked_sub(output.len() + 2)); - - // 1 for ( - let fmt = ListFormatting::for_fn(budget, offset + 1, context.config); + let fmt = ListFormatting::for_fn(budget, offset, context.config); let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); format!("({}){}", list_str, output) @@ -280,6 +283,8 @@ impl Rewrite for ast::WherePredicate { ref bounded_ty, ref bounds, .. }) => { + let type_str = try_opt!(bounded_ty.rewrite(context, width, offset)); + if !bound_lifetimes.is_empty() { let lifetime_str = bound_lifetimes.iter() .map(|lt| { @@ -288,13 +293,13 @@ impl Rewrite for ast::WherePredicate { }) .collect::>() .join(", "); - let type_str = pprust::ty_to_string(bounded_ty); // 8 = "for<> : ".len() let used_width = lifetime_str.len() + type_str.len() + 8; + let budget = try_opt!(width.checked_sub(used_width)); let bounds_str = bounds.iter() .map(|ty_bound| { ty_bound.rewrite(context, - width - used_width, + budget, offset + used_width) .unwrap() }) @@ -303,13 +308,13 @@ impl Rewrite for ast::WherePredicate { format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { - let type_str = pprust::ty_to_string(bounded_ty); // 2 = ": ".len() let used_width = type_str.len() + 2; + let budget = try_opt!(width.checked_sub(used_width)); let bounds_str = bounds.iter() .map(|ty_bound| { ty_bound.rewrite(context, - width - used_width, + budget, offset + used_width) .unwrap() }) @@ -330,12 +335,11 @@ impl Rewrite for ast::WherePredicate { .join(" + ")) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref path, ref ty, .. }) => { - let ty_str = pprust::ty_to_string(ty); + let ty_str = try_opt!(ty.rewrite(context, width, offset)); // 3 = " = ".len() let used_width = 3 + ty_str.len(); - let path_str = try_opt!(path.rewrite(context, - width - used_width, - offset + used_width)); + let budget = try_opt!(width.checked_sub(used_width)); + let path_str = try_opt!(path.rewrite(context, budget, offset + used_width)); format!("{} = {}", path_str, ty_str) } }) @@ -365,8 +369,9 @@ impl Rewrite for ast::TyParamBound { tref.rewrite(context, width, offset) } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { + let budget = try_opt!(width.checked_sub(1)); Some(format!("?{}", - try_opt!(tref.rewrite(context, width - 1, offset + 1)))) + try_opt!(tref.rewrite(context, budget, offset + 1)))) } ast::TyParamBound::RegionTyParamBound(ref l) => { Some(pprust::lifetime_to_string(l)) @@ -402,7 +407,9 @@ impl Rewrite for ast::TyParam { } if let Some(ref def) = self.default { result.push_str(" = "); - result.push_str(&pprust::ty_to_string(&def)); + let budget = try_opt!(width.checked_sub(result.len())); + let rewrite = try_opt!(def.rewrite(context, budget, offset + result.len())); + result.push_str(&rewrite); } Some(result) @@ -451,30 +458,34 @@ impl Rewrite for ast::Ty { ast::TyRptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); - Some(match lifetime { - &Some(ref lifetime) => { + Some(match *lifetime { + Some(ref lifetime) => { let lt_str = pprust::lifetime_to_string(lifetime); let lt_len = lt_str.len(); + let budget = try_opt!(width.checked_sub(2 + mut_len + lt_len)); format!("&{} {}{}", lt_str, mut_str, try_opt!(mt.ty.rewrite(context, - width - (2 + mut_len + lt_len), + budget, offset + 2 + mut_len + lt_len))) } - &None => { + None => { + let budget = try_opt!(width.checked_sub(1 + mut_len)); format!("&{}{}", mut_str, - try_opt!(mt.ty.rewrite(context, - width - (1 + mut_len), - offset + 1 + mut_len))) + try_opt!(mt.ty.rewrite(context, budget, offset + 1 + mut_len))) } }) } ast::TyParen(ref ty) => { - ty.rewrite(context, width - 2, offset + 1).map(|ty_str| format!("({})", ty_str)) + let budget = try_opt!(width.checked_sub(2)); + ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) } - _ => Some(pprust::ty_to_string(self)), + _ => wrap_str(pprust::ty_to_string(self), + context.config.max_width, + width, + offset), } } } -- cgit 1.4.1-3-g733a5 From 840af4f84d32934d210f254a8d710aae972948b1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 28 Sep 2015 08:46:05 +1300 Subject: Option for putting the where clause on the same line as the function if the body is empty. --- src/config.rs | 6 ++++-- src/items.rs | 12 +++++++++--- tests/target/trait.rs | 3 +-- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b21fe3d2a07..7460f581205 100644 --- a/src/config.rs +++ b/src/config.rs @@ -74,6 +74,8 @@ pub enum Density { Compressed, // Use more lines. Tall, + // Try to compress if the body is empty. + CompressedIfEmpty, } impl_enum_decodable!(Density, Compressed, Tall); @@ -82,7 +84,7 @@ impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { Density::Compressed => ListTactic::Mixed, - Density::Tall => ListTactic::HorizontalVertical, + Density::Tall | Density::CompressedIfEmpty => ListTactic::HorizontalVertical, } } } @@ -267,7 +269,7 @@ impl Default for Config { fn_args_density: Density::Tall, fn_args_layout: StructLitStyle::Visual, fn_arg_indent: BlockIndentStyle::Visual, - where_density: Density::Tall, + where_density: Density::CompressedIfEmpty, where_indent: BlockIndentStyle::Tabbed, where_layout: ListTactic::Vertical, where_pred_indent: BlockIndentStyle::Visual, diff --git a/src/items.rs b/src/items.rs index 754d98793b9..e6a334d9ad3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -144,6 +144,7 @@ impl<'a> FmtVisitor<'a> { abi::Abi::Rust, ast::Visibility::Inherited, span, + false, false); match rewrite { @@ -210,7 +211,8 @@ impl<'a> FmtVisitor<'a> { abi, vis, span, - newline_brace)); + newline_brace, + true)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; @@ -250,6 +252,7 @@ impl<'a> FmtVisitor<'a> { sig.abi, ast::Visibility::Inherited, span, + false, false)); // Re-attach semicolon @@ -269,7 +272,8 @@ impl<'a> FmtVisitor<'a> { abi: abi::Abi, vis: ast::Visibility, span: Span, - newline_brace: bool) + newline_brace: bool, + has_body: bool) -> Option { // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. @@ -407,7 +411,9 @@ impl<'a> FmtVisitor<'a> { (!result.contains('\n') || self.config.fn_args_layout == StructLitStyle::Block)) || (self.config.fn_args_layout == StructLitStyle::Block && - ret_str.is_empty()) { + ret_str.is_empty()) || + (self.config.where_density == Density::CompressedIfEmpty && + !has_body) { Density::Compressed } else { Density::Tall diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 5b69c46b18d..3e0a7ed692a 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -15,8 +15,7 @@ trait Foo { fn increment(&mut self, x: i32); - fn read(&mut self, x: BufReader /* Used to be MemReader */) - where R: Read; + fn read(&mut self, x: BufReader /* Used to be MemReader */) where R: Read; } pub trait WriteMessage { -- cgit 1.4.1-3-g733a5 From 30aefa6dc7592943de8376dab69042988816aabe Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Sep 2015 22:11:17 +0200 Subject: Prevent arithmetic overflow handling match arm comments --- src/expr.rs | 10 ++++------ tests/source/match.rs | 4 ++++ tests/target/match.rs | 7 +++++++ 3 files changed, 15 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4076298cec8..f2c98129cd6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -693,11 +693,6 @@ fn rewrite_match_arm_comment(context: &RewriteContext, Some(n) => &missed_str[n+1..], None => &missed_str[..], }; - // Nor the trailing "}" which closes the match - let missed_str = match missed_str.find_uncommented("}") { - Some(n) => &missed_str[..n-1], - None => &missed_str[..], - }; let mut result = String::new(); // any text not preceeded by a newline is pushed unmodified to the block @@ -777,7 +772,10 @@ fn rewrite_match(context: &RewriteContext, result.push_str(&snippet); } } - let last_comment = context.snippet(mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi)); + // BytePos(1) = closing match brace. + let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), + span.hi - BytePos(1)); + let last_comment = context.snippet(last_span); let comment = try_opt!(rewrite_match_arm_comment(context, &last_comment, width, diff --git a/tests/source/match.rs b/tests/source/match.rs index 49e66e4c0df..b1c6449226f 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -221,3 +221,7 @@ fn issue280() { } } } + +fn issue383() { + match resolution.last_private {LastImport{..} => false, _ => true}; +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 6e330505a9b..e6b0b4099d3 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -210,3 +210,10 @@ fn issue280() { } } } + +fn issue383() { + match resolution.last_private { + LastImport{..} => false, + _ => true, + }; +} -- cgit 1.4.1-3-g733a5 From 220ecdaf713e48a9c7f264b11f2acb197f95bfe4 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Sun, 27 Sep 2015 16:32:07 -0400 Subject: Fix https://github.com/nrc/rustfmt/issues/377 --- src/types.rs | 21 +++++++++++++++++++++ tests/target/fn.rs | 3 +++ 2 files changed, 24 insertions(+) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 28980174314..333c0164d83 100644 --- a/src/types.rs +++ b/src/types.rs @@ -482,6 +482,27 @@ impl Rewrite for ast::Ty { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) } + ast::TyTup(ref tup_ret) => { + let inner = try_opt!(tup_ret.iter() + .map(|item| item.rewrite(context, width, offset)) + .fold(Some("".to_owned()), + |sum, x| { + match (sum, x) { + (Some(sum), Some(x)) => { + if sum == "" { + // First item. + Some(x) + } else { + Some(sum + ", " + &x) + } + } + _ => None, + } + })); + + let ret = format!("({})", inner); + wrap_str(ret, context.config.max_width, width, offset) + } _ => wrap_str(pprust::ty_to_string(self), context.config.max_width, width, diff --git a/tests/target/fn.rs b/tests/target/fn.rs index f9ea3f0c0c5..d8a705fb39b 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -79,6 +79,9 @@ fn homura>(_: T) { } +fn issue377() -> (Box, Box) { +} + fn main() { let _ = function(move || 5); let _ = move || 42; -- cgit 1.4.1-3-g733a5 From 00b314618d1b2418c4c42041ae4ab11b067a9bef Mon Sep 17 00:00:00 2001 From: Scyptnex Date: Tue, 29 Sep 2015 09:38:19 +1000 Subject: Refactoring configuration --- src/bin/rustfmt.rs | 8 +- src/config.rs | 307 +++++++++++++++++++++++++++-------------------------- src/issues.rs | 12 +-- src/utils.rs | 3 +- 4 files changed, 164 insertions(+), 166 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index af83cf13f85..01c292948df 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -85,13 +85,7 @@ fn print_usage>(reason: S) { println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] \ ", reason.into()); - - for option in Config::get_docs() { - println!("{}, {}, Possible values: {}", - option.option_name(), - option.doc_string(), - option.variant_names()); - } + Config::print_docs(); } fn determine_params(args: I) -> Option<(Vec, WriteMode)> diff --git a/src/config.rs b/src/config.rs index 7460f581205..3a73867f873 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,18 +11,24 @@ extern crate toml; use lists::{SeparatorTactic, ListTactic}; -pub use issues::ReportTactic; -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum NewlineStyle { +macro_rules! configuration_option_enum{ + ($e:ident: $( $x:ident ),+ $(,)*) => { + #[derive(Copy, Clone, Eq, PartialEq, Debug)] + pub enum $e { + $( $x ),+ + } + + impl_enum_decodable!($e, $( $x ),+); + } +} + +configuration_option_enum! { NewlineStyle: Windows, // \r\n Unix, // \n } -impl_enum_decodable!(NewlineStyle, Windows, Unix); - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum BraceStyle { +configuration_option_enum! { BraceStyle: AlwaysNextLine, PreferSameLine, // Prefer same line except where there is a where clause, in which case force @@ -30,22 +36,16 @@ pub enum BraceStyle { SameLineWhere, } -impl_enum_decodable!(BraceStyle, AlwaysNextLine, PreferSameLine, SameLineWhere); - // How to indent a function's return type. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum ReturnIndent { +configuration_option_enum! { ReturnIndent: // Aligned with the arguments WithArgs, // Aligned with the where clause WithWhereClause, } -impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); - // How to stle a struct literal. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum StructLitStyle { +configuration_option_enum! { StructLitStyle: // First line on the same line as the opening brace, all lines aligned with // the first line. Visual, @@ -54,10 +54,7 @@ pub enum StructLitStyle { // FIXME Maybe we should also have an option to align types. } -impl_enum_decodable!(StructLitStyle, Visual, Block); - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum BlockIndentStyle { +configuration_option_enum! { BlockIndentStyle: // Same level as parent. Inherit, // One level deeper than parent. @@ -66,10 +63,7 @@ pub enum BlockIndentStyle { Visual, } -impl_enum_decodable!(BlockIndentStyle, Inherit, Tabbed, Visual); - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum Density { +configuration_option_enum! { Density: // Fit as much on one line as possible. Compressed, // Use more lines. @@ -78,8 +72,6 @@ pub enum Density { CompressedIfEmpty, } -impl_enum_decodable!(Density, Compressed, Tall); - impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { @@ -89,17 +81,22 @@ impl Density { } } -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum MultilineStyle { +configuration_option_enum! { LicensePolicy: + // Do not place license text at top of files + NoLicense, + // Use the text in "license" field as the license + TextLicense, + // Use a text file as the license text + FileLicense, +} + +configuration_option_enum! { MultilineStyle: // Use horizontal layout if it fits in one line, fall back to vertical PreferSingle, // Use vertical layout ForceMulti, } - -impl_enum_decodable!(MultilineStyle, PreferSingle, ForceMulti); - impl MultilineStyle { pub fn to_list_tactic(self) -> ListTactic { match self { @@ -109,8 +106,63 @@ impl MultilineStyle { } } +configuration_option_enum! { ReportTactic: + Always, + Unnumbered, + Never, +} + +// This trait and the following impl blocks are there so that we an use +// UCFS inside the get_docs() function on types for configs. +pub trait ConfigType { + fn get_variant_names() -> String; +} + +impl ConfigType for bool { + fn get_variant_names() -> String { + String::from("") + } +} + +impl ConfigType for usize { + fn get_variant_names() -> String { + String::from("") + } +} + +impl ConfigType for String { + fn get_variant_names() -> String { + String::from("") + } +} + +pub struct ConfigHelpItem { + option_name: &'static str, + doc_string: &'static str, + variant_names: String, + default: &'static str, +} + +impl ConfigHelpItem { + pub fn option_name(&self) -> &'static str { + self.option_name + } + + pub fn doc_string(&self) -> &'static str { + self.doc_string + } + + pub fn variant_names(&self) -> &String { + &self.variant_names + } + + pub fn default(&self) -> &'static str { + self.default + } +} + macro_rules! create_config { - ($($i:ident: $ty:ty, $dstring: tt),+ $(,)*) => ( + ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[derive(RustcDecodable, Clone)] pub struct Config { $(pub $i: $ty),+ @@ -126,47 +178,9 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } - // This trait and the following impl blocks are there so that we an use - // UCFS inside the get_docs() function on types for configs. - pub trait ConfigType { - fn get_variant_names() -> String; - } - - impl ConfigType for bool { - fn get_variant_names() -> String { - String::from("") - } - } - - impl ConfigType for usize { - fn get_variant_names() -> String { - String::from("") - } - } - - pub struct ConfigHelpItem { - option_name: &'static str, - doc_string : &'static str, - variant_names: String, - } - - impl ConfigHelpItem { - pub fn option_name(&self) -> &'static str { - self.option_name - } - - pub fn doc_string(&self) -> &'static str { - self.doc_string - } - - pub fn variant_names(&self) -> &String { - &self.variant_names - } - } - impl Config { - fn fill_from_parsed_config(mut self, parsed: &ParsedConfig) -> Config { + fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config { $( if let Some(val) = parsed.$i { self.$i = val; @@ -186,7 +200,7 @@ macro_rules! create_config { panic!(); } }; - Config::default().fill_from_parsed_config(&parsed_config) + Config::default().fill_from_parsed_config(parsed_config) } pub fn override_value(&mut self, key: &str, val: &str) { @@ -200,93 +214,90 @@ macro_rules! create_config { } } - pub fn get_docs() -> Vec { - let mut options: Vec = Vec::new(); + pub fn print_docs() { + use std::cmp; + let max = 0; + $( let max = cmp::max(max, stringify!($i).len()+1); )+ + let mut space_str = String::with_capacity(max); + for _ in 0..max { + space_str.push(' '); + } + println!("\nConfiguration Options:"); $( - options.push(ConfigHelpItem { - option_name: stringify!($i), - doc_string: stringify!($dstring), - variant_names: <$ty>::get_variant_names(), - }); + let name_raw = stringify!($i); + let mut name_out = String::with_capacity(max); + for _ in name_raw.len()..max-1 { + name_out.push(' ') + } + name_out.push_str(name_raw); + name_out.push(' '); + println!("{}{} Default: {:?}", + name_out, + <$ty>::get_variant_names(), + $def); + $( + println!("{}{}", space_str, $dstring); + )+ + println!(""); )+ - options + } + } + + // Template for the default configuration + impl Default for Config { + fn default() -> Config { + Config { + $( + $i: $def, + )+ + } } } ) } create_config! { - max_width: usize, "Maximum width of each line", - ideal_width: usize, "Ideal width of each line (only used for comments)", - tab_spaces: usize, "Number of spaces per tab", - fn_call_width: usize, "Maximum width of the args of a function call\ - before faling back to vertical formatting", - struct_lit_width: usize, "Maximum width in the body of a struct lit\ - before faling back to vertical formatting", - newline_style: NewlineStyle, "Unix or Windows line endings", - fn_brace_style: BraceStyle, "Brace style for functions", - fn_return_indent: ReturnIndent, "Location of return type in function declaration", - fn_args_paren_newline: bool, "If function argument parenthases goes on a newline", - fn_args_density: Density, "Argument density in functions", - fn_args_layout: StructLitStyle, "Layout of function arguments", - fn_arg_indent: BlockIndentStyle, "Indent on function arguments", + max_width: usize, 100, "Maximum width of each line"; + ideal_width: usize, 80, "Ideal width of each line"; + tab_spaces: usize, 4, "Number of spaces per tab"; + fn_call_width: usize, 50, + "Maximum width of the args of a function call before faling back to vertical formatting"; + struct_lit_width: usize, 12, + "Maximum width in the body of a struct lit before faling back to vertical formatting"; + newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; + fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; + fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, + "Location of return type in function declaration"; + fn_args_paren_newline: bool, true, "If function argument parenthases goes on a newline"; + fn_args_density: Density, Density::Tall, "Argument density in functions"; + fn_args_layout: StructLitStyle, StructLitStyle::Visual, "Layout of function arguments"; + fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; // Should we at least try to put the where clause on the same line as the rest of the // function decl? - where_density: Density, "Density of a where clause", + where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; // Visual will be treated like Tabbed - where_indent: BlockIndentStyle, "Indentation of a where clause", - where_layout: ListTactic, "Element layout inside a where clause", - where_pred_indent: BlockIndentStyle, "Indentation style of a where predicate", - generics_indent: BlockIndentStyle, "Indentation of generics", - struct_trailing_comma: SeparatorTactic, "If there is a trailing comma on structs", - struct_lit_trailing_comma: SeparatorTactic, "If there is a trailing comma on literal structs", - struct_lit_style: StructLitStyle, "Style of struct definition", - struct_lit_multiline_style: MultilineStyle, "Multilline style on literal structs", - enum_trailing_comma: bool, "Put a trailing comma on enum declarations", - report_todo: ReportTactic, "Report all occurences of TODO in source file comments", - report_fixme: ReportTactic, "Report all occurences of FIXME in source file comments", + where_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of a where clause"; + where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; + where_pred_indent: BlockIndentStyle, BlockIndentStyle::Visual, + "Indentation style of a where predicate"; + generics_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of generics"; + struct_trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, + "If there is a trailing comma on structs"; + struct_lit_trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, + "If there is a trailing comma on literal structs"; + struct_lit_style: StructLitStyle, StructLitStyle::Block, "Style of struct definition"; + struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, + "Multilline style on literal structs"; + enum_trailing_comma: bool, true, "Put a trailing comma on enum declarations"; + report_todo: ReportTactic, ReportTactic::Always, + "Report all occurences of TODO in source file comments"; + report_fixme: ReportTactic, ReportTactic::Never, + "Report all occurences of FIXME in source file comments"; // Alphabetically, case sensitive. - reorder_imports: bool, "Reorder import statements alphabetically", - single_line_if_else: bool, "Put else on same line as closing brace for if statements", - format_strings: bool, "Format string literals, or leave as is", - chains_overflow_last: bool, "Allow last call in method chain to break the line", - take_source_hints: bool, "Retain some formatting characteristics from the source code", - hard_tabs: bool, "Use tab characters for indentation, spaces for alignment", -} - -impl Default for Config { - fn default() -> Config { - Config { - max_width: 100, - ideal_width: 80, - tab_spaces: 4, - fn_call_width: 50, - struct_lit_width: 12, - newline_style: NewlineStyle::Unix, - fn_brace_style: BraceStyle::SameLineWhere, - fn_return_indent: ReturnIndent::WithArgs, - fn_args_paren_newline: true, - fn_args_density: Density::Tall, - fn_args_layout: StructLitStyle::Visual, - fn_arg_indent: BlockIndentStyle::Visual, - where_density: Density::CompressedIfEmpty, - where_indent: BlockIndentStyle::Tabbed, - where_layout: ListTactic::Vertical, - where_pred_indent: BlockIndentStyle::Visual, - generics_indent: BlockIndentStyle::Visual, - struct_trailing_comma: SeparatorTactic::Vertical, - struct_lit_trailing_comma: SeparatorTactic::Vertical, - struct_lit_style: StructLitStyle::Block, - struct_lit_multiline_style: MultilineStyle::PreferSingle, - enum_trailing_comma: true, - report_todo: ReportTactic::Always, - report_fixme: ReportTactic::Never, - reorder_imports: false, - single_line_if_else: false, - format_strings: true, - chains_overflow_last: true, - take_source_hints: true, - hard_tabs: false, - } - } + reorder_imports: bool, false, "Reorder import statements alphabetically"; + single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; + format_strings: bool, true, "Format string literals, or leave as is"; + chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; + take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; + hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; } diff --git a/src/issues.rs b/src/issues.rs index 2a5eaae287a..6f64436bb52 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -13,17 +13,13 @@ // associated issue number. use std::fmt; +pub use config::ReportTactic; static TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O']; static FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; -#[derive(Clone, Copy)] -pub enum ReportTactic { - Always, - Unnumbered, - Never, -} - +// Enabled implementation detail is here because it is +// irrelevant outside the issues module impl ReportTactic { fn is_enabled(&self) -> bool { match *self { @@ -34,8 +30,6 @@ impl ReportTactic { } } -impl_enum_decodable!(ReportTactic, Always, Unnumbered, Never); - #[derive(Clone, Copy)] enum Seeking { Issue { diff --git a/src/utils.rs b/src/utils.rs index 171572ccfbf..b9da5b04c3b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -160,8 +160,7 @@ macro_rules! impl_enum_decodable { $( variants.push(stringify!($x)); )* - - variants.join(", ") + format!("[{}]", variants.join("|")) } } }; -- cgit 1.4.1-3-g733a5 From 11ed3c81d552028964c52270e0e423267085c985 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Sun, 27 Sep 2015 10:09:08 -0400 Subject: Fix https://github.com/nrc/rustfmt/issues/376 --- src/types.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 33446765c8c..5d8978ec554 100644 --- a/src/types.rs +++ b/src/types.rs @@ -42,7 +42,8 @@ pub fn rewrite_path(context: &RewriteContext, if let Some(ref qself) = qself { result.push('<'); - result.push_str(&pprust::ty_to_string(&qself.ty)); + let fmt_ty = try_opt!(qself.ty.rewrite(context, width, offset)); + result.push_str(&fmt_ty); if skip_count > 0 { result.push_str(" as "); -- cgit 1.4.1-3-g733a5 From 6c6e7194c20f057f5d30dbafda329e2d0ad99ac1 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Thu, 1 Oct 2015 01:58:44 -0700 Subject: Fix 1-tuple regression. Add test to prevent future regressions. --- src/lib.rs | 1 + src/types.rs | 26 ++++++++++---------------- tests/target/fn_once.rs | 8 ++++++++ 3 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 tests/target/fn_once.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index fdf08c001a3..c075589e99c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ #![feature(rustc_private)] #![feature(custom_attribute)] #![feature(slice_splits)] +#![feature(slice_patterns)] #![feature(catch_panic)] #![allow(unused_attributes)] diff --git a/src/types.rs b/src/types.rs index 333c0164d83..b67ded94299 100644 --- a/src/types.rs +++ b/src/types.rs @@ -483,22 +483,16 @@ impl Rewrite for ast::Ty { ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) } ast::TyTup(ref tup_ret) => { - let inner = try_opt!(tup_ret.iter() - .map(|item| item.rewrite(context, width, offset)) - .fold(Some("".to_owned()), - |sum, x| { - match (sum, x) { - (Some(sum), Some(x)) => { - if sum == "" { - // First item. - Some(x) - } else { - Some(sum + ", " + &x) - } - } - _ => None, - } - })); + let inner = if let [ref item] = &**tup_ret { + try_opt!(item.rewrite(context, width, offset)) + "," + } else { + let rewrites: Option>; + rewrites = tup_ret.iter() + .map(|item| item.rewrite(context, width, offset)) + .collect(); + + try_opt!(rewrites).join(", ") + }; let ret = format!("({})", inner); wrap_str(ret, context.config.max_width, width, offset) diff --git a/tests/target/fn_once.rs b/tests/target/fn_once.rs new file mode 100644 index 00000000000..42b8f98e78a --- /dev/null +++ b/tests/target/fn_once.rs @@ -0,0 +1,8 @@ +struct Add(usize); + +impl FnOnce<(usize,)> for Add { + type Output = Add; + extern "rust-call" fn call_once(self, to: (usize,)) -> Add { + Add(self.0 + to.0) + } +} -- cgit 1.4.1-3-g733a5 From 603f2034a512317c530473c8c229f8685ed18bd9 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 2 Oct 2015 11:31:40 +0200 Subject: Format type casts --- src/expr.rs | 38 ++++++++++++++++++++++++++++++++++++-- tests/source/expr.rs | 13 +++++++++++++ tests/target/expr.rs | 10 ++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f2c98129cd6..ecc94773211 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -177,12 +177,14 @@ impl Rewrite for ast::Expr { rewrite_unary_prefix(context, "box ", expr, width, offset) } ast::Expr_::ExprAddrOf(mutability, ref expr) => { - rewrite_expr_addrof(context, mutability, &expr, width, offset) + rewrite_expr_addrof(context, mutability, expr, width, offset) + } + ast::Expr_::ExprCast(ref expr, ref ty) => { + rewrite_cast(expr, ty, context, width, offset) } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::Expr_::ExprInPlace(..) | - ast::Expr_::ExprCast(..) | ast::Expr_::ExprIndex(..) | ast::Expr_::ExprInlineAsm(..) | ast::Expr_::ExprRepeat(..) => { @@ -195,6 +197,38 @@ impl Rewrite for ast::Expr { } } +fn rewrite_cast(expr: &ast::Expr, + ty: &ast::Ty, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let max_width = try_opt!(width.checked_sub(" as ".len())); + + binary_search(1, + max_width, + |expr_budget| { + let expr_str = match expr.rewrite(context, expr_budget, offset) { + Some(result) => result, + None => return Err(Ordering::Greater), + }; + + let last_line_width = last_line_width(&expr_str); + let ty_budget = match max_width.checked_sub(last_line_width) { + Some(b) => b, + None => return Err(Ordering::Less), + }; + let ty_indent = offset + last_line_width; + + let ty_str = match ty.rewrite(context, ty_budget, ty_indent) { + Some(result) => result, + None => return Err(Ordering::Less), + }; + + Ok(format!("{} as {}", expr_str, ty_str)) + }) +} + pub fn rewrite_array<'a, I>(expr_iter: I, span: Span, context: &RewriteContext, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 96ad42cd77d..544a566cee9 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -184,3 +184,16 @@ fn addrof() { & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); } + +fn casts() { + fn unpack(packed: u32) -> [u16; 2] { + [ + (packed >> 16) as u16, + (packed >> 0) as u16, + ] + } + + let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx + as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; + let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index f31f27f59d4..c23b0b050c8 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -198,3 +198,13 @@ fn addrof() { &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); } + +fn casts() { + fn unpack(packed: u32) -> [u16; 2] { + [(packed >> 16) as u16, (packed >> 0) as u16] + } + + let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; + let slightly_longer_trait = yyyyyyyyy + + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; +} -- cgit 1.4.1-3-g733a5 From ad2e3b8e2b58f016d61b33e17de52d6edb75ec0a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 2 Oct 2015 11:47:03 +0200 Subject: Format indices --- src/expr.rs | 40 ++++++++++++++++++++++++++++++++++++---- tests/source/expr.rs | 5 +++++ tests/target/expr.rs | 8 ++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ecc94773211..75630eb8301 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -111,8 +111,6 @@ impl Rewrite for ast::Expr { offset, true) } - // We reformat it ourselves because rustc gives us a bad span - // for ranges, see rust#27162 ast::Expr_::ExprRange(ref left, ref right) => { rewrite_range(context, left.as_ref().map(|e| &**e), @@ -182,10 +180,12 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprCast(ref expr, ref ty) => { rewrite_cast(expr, ty, context, width, offset) } + ast::Expr_::ExprIndex(ref expr, ref index) => { + rewrite_index(expr, index, context, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::Expr_::ExprInPlace(..) | - ast::Expr_::ExprIndex(..) | ast::Expr_::ExprInlineAsm(..) | ast::Expr_::ExprRepeat(..) => { wrap_str(context.snippet(self.span), @@ -197,6 +197,38 @@ impl Rewrite for ast::Expr { } } +fn rewrite_index(expr: &ast::Expr, + index: &ast::Expr, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let max_width = try_opt!(width.checked_sub("[]".len())); + + binary_search(1, + max_width, + |expr_budget| { + let expr_str = match expr.rewrite(context, expr_budget, offset) { + Some(result) => result, + None => return Err(Ordering::Greater), + }; + + let last_line_width = last_line_width(&expr_str); + let index_budget = match max_width.checked_sub(last_line_width) { + Some(b) => b, + None => return Err(Ordering::Less), + }; + let index_indent = offset + last_line_width + "[".len(); + + let index_str = match index.rewrite(context, index_budget, index_indent) { + Some(result) => result, + None => return Err(Ordering::Less), + }; + + Ok(format!("{}[{}]", expr_str, index_str)) + }) +} + fn rewrite_cast(expr: &ast::Expr, ty: &ast::Ty, context: &RewriteContext, @@ -218,7 +250,7 @@ fn rewrite_cast(expr: &ast::Expr, Some(b) => b, None => return Err(Ordering::Less), }; - let ty_indent = offset + last_line_width; + let ty_indent = offset + last_line_width + " as ".len(); let ty_str = match ty.rewrite(context, ty_budget, ty_indent) { Some(result) => result, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 544a566cee9..16b9047dcf1 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -197,3 +197,8 @@ fn casts() { as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; } + +fn indices() { + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index c23b0b050c8..ab25d489c1b 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -208,3 +208,11 @@ fn casts() { let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; } + +fn indices() { + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[x + + y + + z]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + cccccccccccccccc)[xxxxx + yyyyy + zzzzz]; +} -- cgit 1.4.1-3-g733a5 From 84718b5b90221597204de9f010d3079f91f7b9f3 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 2 Oct 2015 11:48:52 +0200 Subject: Format rustfmt's own indices --- src/expr.rs | 4 ++-- src/items.rs | 2 +- src/lists.rs | 2 +- src/missed_spans.rs | 2 +- src/visitor.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 75630eb8301..b68cbb87580 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -756,7 +756,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, -> Option { // The leading "," is not part of the arm-comment let missed_str = match missed_str.find_uncommented(",") { - Some(n) => &missed_str[n+1..], + Some(n) => &missed_str[n + 1..], None => &missed_str[..], }; @@ -816,7 +816,7 @@ fn rewrite_match(context: &RewriteContext, let missed_str = if i == 0 { context.snippet(mk_sp(open_brace_pos, arm_start_pos(arm))) } else { - context.snippet(mk_sp(arm_end_pos(&arms[i-1]), arm_start_pos(arm))) + context.snippet(mk_sp(arm_end_pos(&arms[i - 1]), arm_start_pos(arm))) }; let comment = try_opt!(rewrite_match_arm_comment(context, &missed_str, diff --git a/src/items.rs b/src/items.rs index e6a334d9ad3..827b528771e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -476,7 +476,7 @@ impl<'a> FmtVisitor<'a> { }; let more_items = itemize_list(self.codemap, - args[min_args-1..].iter(), + args[min_args - 1..].iter(), ")", |arg| span_lo_for_arg(arg), |arg| arg.ty.span.hi, diff --git a/src/lists.rs b/src/lists.rs index 12eebb7b691..9a169c15ce1 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -379,7 +379,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> // because of the way we divide pre- and post- comments. // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end-1..]; + let test_snippet = &post_snippet[comment_end - 1..]; let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 135e6c3815b..5c5565c6596 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -78,7 +78,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&snippet[line_start..lw]); self.buffer.push_str("\n"); } else { - self.buffer.push_str(&snippet[line_start..i+1]); + self.buffer.push_str(&snippet[line_start..i + 1]); } line_start = i + 1; diff --git a/src/visitor.rs b/src/visitor.rs index 883d46a22d4..21dc2cde2a5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -407,7 +407,7 @@ impl<'a> Rewrite for [ast::Attribute] { let a_str = context.snippet(a.span); if i > 0 { - let comment = context.snippet(codemap::mk_sp(self[i-1].span.hi, a.span.lo)); + let comment = context.snippet(codemap::mk_sp(self[i - 1].span.hi, a.span.lo)); // This particular horror show is to preserve line breaks in between doc // comments. An alternative would be to force such line breaks to start // with the usual doc comment token. -- cgit 1.4.1-3-g733a5 From ca0b8606882da76ac0a854c7e6d01ec085dae2e0 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 2 Oct 2015 12:00:28 +0200 Subject: Format repeated element array literals --- src/expr.rs | 38 ++++++++++++++++++++++++++++++++++++-- tests/source/expr.rs | 5 +++++ tests/target/expr.rs | 8 ++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b68cbb87580..8d375a8b586 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -183,11 +183,13 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprIndex(ref expr, ref index) => { rewrite_index(expr, index, context, width, offset) } + ast::Expr_::ExprRepeat(ref expr, ref repeats) => { + rewrite_repeats(expr, repeats, context, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::Expr_::ExprInPlace(..) | - ast::Expr_::ExprInlineAsm(..) | - ast::Expr_::ExprRepeat(..) => { + ast::Expr_::ExprInlineAsm(..) => { wrap_str(context.snippet(self.span), context.config.max_width, width, @@ -197,6 +199,38 @@ impl Rewrite for ast::Expr { } } +fn rewrite_repeats(expr: &ast::Expr, + index: &ast::Expr, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let max_width = try_opt!(width.checked_sub("[; ]".len())); + + binary_search(1, + max_width, + |expr_budget| { + let expr_str = match expr.rewrite(context, expr_budget, offset + "[".len()) { + Some(result) => result, + None => return Err(Ordering::Greater), + }; + + let last_line_width = last_line_width(&expr_str); + let index_budget = match max_width.checked_sub(last_line_width) { + Some(b) => b, + None => return Err(Ordering::Less), + }; + let index_indent = offset + last_line_width + "[; ".len(); + + let index_str = match index.rewrite(context, index_budget, index_indent) { + Some(result) => result, + None => return Err(Ordering::Less), + }; + + Ok(format!("[{}; {}]", expr_str, index_str)) + }) +} + fn rewrite_index(expr: &ast::Expr, index: &ast::Expr, context: &RewriteContext, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 16b9047dcf1..45f688693f6 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -202,3 +202,8 @@ fn indices() { let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; } + +fn repeats() { + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc; x + y + z ]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz ]; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index ab25d489c1b..6fe472c114e 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -216,3 +216,11 @@ fn indices() { let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[xxxxx + yyyyy + zzzzz]; } + +fn repeats() { + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; x + + y + + z]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + + cccccccccccccccc; xxxxx + yyyyy + zzzzz]; +} -- cgit 1.4.1-3-g733a5 From d0be26b383e052c47aff0507cbef99ec01e5ba8a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 2 Oct 2015 12:25:22 +0200 Subject: Unify pair formatting code --- src/expr.rs | 158 +++++++++++++++++------------------------------------------- 1 file changed, 43 insertions(+), 115 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8d375a8b586..fcb2ae1ff05 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -111,13 +111,6 @@ impl Rewrite for ast::Expr { offset, true) } - ast::Expr_::ExprRange(ref left, ref right) => { - rewrite_range(context, - left.as_ref().map(|e| &**e), - right.as_ref().map(|e| &**e), - width, - offset) - } ast::Expr_::ExprMatch(ref cond, ref arms, _) => { rewrite_match(context, cond, arms, width, offset, self.span) } @@ -178,13 +171,32 @@ impl Rewrite for ast::Expr { rewrite_expr_addrof(context, mutability, expr, width, offset) } ast::Expr_::ExprCast(ref expr, ref ty) => { - rewrite_cast(expr, ty, context, width, offset) + rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) } ast::Expr_::ExprIndex(ref expr, ref index) => { - rewrite_index(expr, index, context, width, offset) + rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) } ast::Expr_::ExprRepeat(ref expr, ref repeats) => { - rewrite_repeats(expr, repeats, context, width, offset) + rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) + } + ast::Expr_::ExprRange(Some(ref lhs), Some(ref rhs)) => { + rewrite_pair(&**lhs, &**rhs, "", "..", "", context, width, offset) + } + ast::Expr_::ExprRange(None, Some(ref rhs)) => { + rewrite_unary_prefix(context, "..", &**rhs, width, offset) + } + ast::Expr_::ExprRange(Some(ref lhs), None) => { + Some(format!("{}..", + try_opt!(lhs.rewrite(context, + try_opt!(width.checked_sub(2)), + offset)))) + } + ast::Expr_::ExprRange(None, None) => { + if width >= 2 { + Some("..".into()) + } else { + None + } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. @@ -199,99 +211,42 @@ impl Rewrite for ast::Expr { } } -fn rewrite_repeats(expr: &ast::Expr, - index: &ast::Expr, - context: &RewriteContext, - width: usize, - offset: Indent) - -> Option { - let max_width = try_opt!(width.checked_sub("[; ]".len())); - - binary_search(1, - max_width, - |expr_budget| { - let expr_str = match expr.rewrite(context, expr_budget, offset + "[".len()) { - Some(result) => result, - None => return Err(Ordering::Greater), - }; - - let last_line_width = last_line_width(&expr_str); - let index_budget = match max_width.checked_sub(last_line_width) { - Some(b) => b, - None => return Err(Ordering::Less), - }; - let index_indent = offset + last_line_width + "[; ".len(); - - let index_str = match index.rewrite(context, index_budget, index_indent) { - Some(result) => result, - None => return Err(Ordering::Less), - }; - - Ok(format!("[{}; {}]", expr_str, index_str)) - }) -} - -fn rewrite_index(expr: &ast::Expr, - index: &ast::Expr, - context: &RewriteContext, - width: usize, - offset: Indent) - -> Option { - let max_width = try_opt!(width.checked_sub("[]".len())); - - binary_search(1, - max_width, - |expr_budget| { - let expr_str = match expr.rewrite(context, expr_budget, offset) { - Some(result) => result, - None => return Err(Ordering::Greater), - }; - - let last_line_width = last_line_width(&expr_str); - let index_budget = match max_width.checked_sub(last_line_width) { - Some(b) => b, - None => return Err(Ordering::Less), - }; - let index_indent = offset + last_line_width + "[".len(); - - let index_str = match index.rewrite(context, index_budget, index_indent) { - Some(result) => result, - None => return Err(Ordering::Less), - }; - - Ok(format!("{}[{}]", expr_str, index_str)) - }) -} - -fn rewrite_cast(expr: &ast::Expr, - ty: &ast::Ty, - context: &RewriteContext, - width: usize, - offset: Indent) - -> Option { - let max_width = try_opt!(width.checked_sub(" as ".len())); +fn rewrite_pair(lhs: &LHS, + rhs: &RHS, + prefix: &str, + infix: &str, + suffix: &str, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option + where LHS: Rewrite, + RHS: Rewrite +{ + let max_width = try_opt!(width.checked_sub(prefix.len() + infix.len() + suffix.len())); binary_search(1, max_width, - |expr_budget| { - let expr_str = match expr.rewrite(context, expr_budget, offset) { + |lhs_budget| { + let lhs_offset = offset + prefix.len(); + let lhs_str = match lhs.rewrite(context, lhs_budget, lhs_offset) { Some(result) => result, None => return Err(Ordering::Greater), }; - let last_line_width = last_line_width(&expr_str); - let ty_budget = match max_width.checked_sub(last_line_width) { + let last_line_width = last_line_width(&lhs_str); + let rhs_budget = match max_width.checked_sub(last_line_width) { Some(b) => b, None => return Err(Ordering::Less), }; - let ty_indent = offset + last_line_width + " as ".len(); + let rhs_indent = offset + last_line_width + prefix.len() + infix.len(); - let ty_str = match ty.rewrite(context, ty_budget, ty_indent) { + let rhs_str = match rhs.rewrite(context, rhs_budget, rhs_indent) { Some(result) => result, None => return Err(Ordering::Less), }; - Ok(format!("{} as {}", expr_str, ty_str)) + Ok(format!("{}{}{}{}{}", prefix, lhs_str, infix, rhs_str, suffix)) }) } @@ -637,33 +592,6 @@ fn rewrite_label(label: Option) -> String { } } -// FIXME: this doesn't play well with line breaks -fn rewrite_range(context: &RewriteContext, - left: Option<&ast::Expr>, - right: Option<&ast::Expr>, - width: usize, - offset: Indent) - -> Option { - let left_string = match left { - Some(expr) => { - // 2 = .. - let max_width = try_opt!(width.checked_sub(2)); - try_opt!(expr.rewrite(context, max_width, offset)) - } - None => String::new(), - }; - - let right_string = match right { - Some(expr) => { - let max_width = try_opt!(width.checked_sub(left_string.len() + 2)); - try_opt!(expr.rewrite(context, max_width, offset + 2 + left_string.len())) - } - None => String::new(), - }; - - Some(format!("{}..{}", left_string, right_string)) -} - // Rewrites if-else blocks. If let Some(_) = pat, the expression is // treated as an if-let-else expression. fn rewrite_if_else(context: &RewriteContext, -- cgit 1.4.1-3-g733a5 From 2f7acf00e5d02ae795332c1fa83e41939d6361d7 Mon Sep 17 00:00:00 2001 From: sezna Date: Tue, 29 Sep 2015 09:38:52 -0500 Subject: Added punctuation preference Create test.rs Delete test.rs Fixed compile error. Trying a possible fix on an arithmetic overflow another try at the test failure... passed all tests. Added tests and cleaned up logic as per nrc's critiques Delete string.rs.old Delete string.rs.bk Made changes as per nrc's requests. Update string_punctuation.rs Update string_punctuation.rs fixed logical redundancy --- src/string.rs | 20 ++++++++++++++++---- tests/source/string_punctuation.rs | 5 +++++ tests/target/string_punctuation.rs | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 tests/source/string_punctuation.rs create mode 100644 tests/target/string_punctuation.rs (limited to 'src') diff --git a/src/string.rs b/src/string.rs index ffaf52d3380..59ba4992863 100644 --- a/src/string.rs +++ b/src/string.rs @@ -39,6 +39,7 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); let indent = fmt.offset.to_string(fmt.config); + let punctuation = ":,;."; let mut cur_start = 0; let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); @@ -62,11 +63,22 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { while !graphemes[cur_end - 1].trim().is_empty() { cur_end -= 1; if cur_end - cur_start < MIN_STRING { - // We can't break at whitespace, fall back to splitting - // anywhere that doesn't break an escape sequence. cur_end = cur_start + max_chars; - while graphemes[cur_end - 1] == "\\" { - cur_end -= 1; + // Look for punctuation to break on. + while (!punctuation.contains(graphemes[cur_end - 1])) && cur_end > 1 { + if cur_end > 1 { + cur_end -= 1; + } + } + // We can't break at whitespace or punctuation, fall back to splitting + // anywhere that doesn't break an escape sequence. + if cur_end < cur_start + MIN_STRING { + cur_end = cur_start + max_chars; + while graphemes[cur_end - 1] == "\\" { + if cur_end > 1 { + cur_end -= 1; + } + } } break; } diff --git a/tests/source/string_punctuation.rs b/tests/source/string_punctuation.rs new file mode 100644 index 00000000000..0a02077f7eb --- /dev/null +++ b/tests/source/string_punctuation.rs @@ -0,0 +1,5 @@ +fn main() { + println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); + println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); +} diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs new file mode 100644 index 00000000000..626bace0f5f --- /dev/null +++ b/tests/target/string_punctuation.rs @@ -0,0 +1,14 @@ +fn main() { + println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ + Likethisssssssssssss"); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColo\ + nsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}", + x, + y, + z, + a, + b); + println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ + adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ + ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); +} -- cgit 1.4.1-3-g733a5 From c726bcae80f4e0a11687034b740214d6ecb3b8a6 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 2 Oct 2015 11:13:07 -0500 Subject: infinite while loop fixed, redundancy removed --- src/string.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 59ba4992863..221b56aa4cb 100644 --- a/src/string.rs +++ b/src/string.rs @@ -66,18 +66,14 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { cur_end = cur_start + max_chars; // Look for punctuation to break on. while (!punctuation.contains(graphemes[cur_end - 1])) && cur_end > 1 { - if cur_end > 1 { - cur_end -= 1; - } + cur_end -= 1; } // We can't break at whitespace or punctuation, fall back to splitting // anywhere that doesn't break an escape sequence. if cur_end < cur_start + MIN_STRING { cur_end = cur_start + max_chars; - while graphemes[cur_end - 1] == "\\" { - if cur_end > 1 { - cur_end -= 1; - } + while graphemes[cur_end - 1] == "\\" && cur_end > 1 { + cur_end -= 1; } } break; -- cgit 1.4.1-3-g733a5 From 965ea09664c1649ac9bfbd128eda631a41d73dee Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 2 Oct 2015 13:50:24 +0200 Subject: Split ListTactic decision logic from write_list --- src/config.rs | 5 +- src/expr.rs | 85 +++++++++++++------- src/imports.rs | 31 ++++---- src/items.rs | 64 ++++++++------- src/lib.rs | 3 +- src/lists.rs | 239 +++++++++++++++++++++++++++++++-------------------------- src/macros.rs | 7 +- src/types.rs | 17 ++-- 8 files changed, 255 insertions(+), 196 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 3a73867f873..14d46a76834 100644 --- a/src/config.rs +++ b/src/config.rs @@ -90,6 +90,7 @@ configuration_option_enum! { LicensePolicy: FileLicense, } +// TODO: this is not necessary any more configuration_option_enum! { MultilineStyle: // Use horizontal layout if it fits in one line, fall back to vertical PreferSingle, @@ -260,9 +261,9 @@ create_config! { max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; - fn_call_width: usize, 50, + fn_call_width: usize, 55, "Maximum width of the args of a function call before faling back to vertical formatting"; - struct_lit_width: usize, 12, + struct_lit_width: usize, 16, "Maximum width in the body of a struct lit before faling back to vertical formatting"; newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; diff --git a/src/expr.rs b/src/expr.rs index f2c98129cd6..d51bd256caa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -13,7 +13,8 @@ use std::borrow::Borrow; use Indent; use rewrite::{Rewrite, RewriteContext}; -use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; +use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, + DefinitiveListTactic, definitive_tactic}; use string::{StringFormat, rewrite_string}; use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search}; use visitor::FmtVisitor; @@ -147,7 +148,13 @@ impl Rewrite for ast::Expr { Some(format!("break{}", id_str)) } ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { - rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) + rewrite_closure(capture, + fn_decl, + body, + self.span, + context, + width, + offset) } ast::Expr_::ExprField(..) | ast::Expr_::ExprTupField(..) | @@ -223,9 +230,9 @@ pub fn rewrite_array<'a, I>(expr_iter: I, .collect::>(); let tactic = if items.iter().any(|li| li.item.len() > 10 || li.is_multiline()) { - ListTactic::HorizontalVertical + definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width) } else { - ListTactic::Mixed + DefinitiveListTactic::Mixed }; let fmt = ListFormatting { @@ -233,8 +240,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, separator: ",", trailing_separator: SeparatorTactic::Never, indent: offset + 1, - h_width: max_item_width, - v_width: max_item_width, + width: max_item_width, ends_with_newline: false, config: context.config, }; @@ -285,18 +291,25 @@ fn rewrite_closure(capture: ast::CaptureClause, }, span_after(span, "|", context.codemap), body.span.lo); + let item_vec = arg_items.collect::>(); + let tactic = definitive_tactic(&item_vec, + ListTactic::HorizontalVertical, + horizontal_budget); + let budget = match tactic { + DefinitiveListTactic::Horizontal => horizontal_budget, + _ => budget, + }; let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, + tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, indent: argument_offset, - h_width: horizontal_budget, - v_width: budget, + width: budget, ends_with_newline: false, config: context.config, }; - let list_str = try_opt!(write_list(&arg_items.collect::>(), &fmt)); + let list_str = try_opt!(write_list(&item_vec, &fmt)); let mut prefix = format!("{}|{}|", mover, list_str); if !ret_str.is_empty() { @@ -586,7 +599,11 @@ fn rewrite_if_else(context: &RewriteContext, // Try to format if-else on single line. if allow_single_line && context.config.single_line_if_else { - let trial = single_line_if_else(context, &pat_expr_string, if_block, else_block_opt, width); + let trial = single_line_if_else(context, + &pat_expr_string, + if_block, + else_block_opt, + width); if trial.is_some() { return trial; @@ -1074,7 +1091,13 @@ pub fn rewrite_call(context: &RewriteContext, where R: Rewrite { let closure = |callee_max_width| { - rewrite_call_inner(context, callee, callee_max_width, args, span, width, offset) + rewrite_call_inner(context, + callee, + callee_max_width, + args, + span, + width, + offset) }; // 2 is for parens @@ -1136,8 +1159,7 @@ fn rewrite_call_inner(context: &RewriteContext, span.lo, span.hi); - let fmt = ListFormatting::for_fn(remaining_width, offset, context.config); - let list_str = match write_list(&items.collect::>(), &fmt) { + let list_str = match ::lists::format_fn_args(items, remaining_width, offset, context.config) { Some(str) => str, None => return Err(Ordering::Less), }; @@ -1150,9 +1172,7 @@ fn rewrite_paren(context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("rewrite_paren, width: {}, offset: {:?}", - width, - offset); + debug!("rewrite_paren, width: {}, offset: {:?}", width, offset); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr. let subexpr_str = subexpr.rewrite(context, try_opt!(width.checked_sub(2)), offset + 1); @@ -1248,15 +1268,25 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }, span_after(span, "{", context.codemap), span.hi); + let item_vec = items.collect::>(); + + let tactic = { + let mut prelim_tactic = match (context.config.struct_lit_style, fields.len()) { + (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, + _ => context.config.struct_lit_multiline_style.to_list_tactic(), + }; + + if prelim_tactic == ListTactic::HorizontalVertical && fields.len() > 1 { + prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); + }; - let mut tactic = match (context.config.struct_lit_style, fields.len()) { - (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => context.config.struct_lit_multiline_style.to_list_tactic(), + definitive_tactic(&item_vec, prelim_tactic, h_budget) }; - if tactic == ListTactic::HorizontalVertical && fields.len() > 1 { - tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); - } + let budget = match tactic { + DefinitiveListTactic::Horizontal => h_budget, + _ => v_budget, + }; let fmt = ListFormatting { tactic: tactic, @@ -1267,12 +1297,11 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, context.config.struct_lit_trailing_comma }, indent: indent, - h_width: h_budget, - v_width: v_budget, + width: budget, ends_with_newline: false, config: context.config, }; - let fields_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let fields_str = try_opt!(write_list(&item_vec, &fmt)); let format_on_newline = || { let inner_indent = context.block_indent @@ -1340,10 +1369,8 @@ fn rewrite_tuple_lit(context: &RewriteContext, }, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); - let budget = try_opt!(width.checked_sub(2)); - let fmt = ListFormatting::for_fn(budget, indent, context.config); - let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let list_str = try_opt!(::lists::format_fn_args(items, budget, indent, context.config)); Some(format!("({})", list_str)) } diff --git a/src/imports.rs b/src/imports.rs index 8c3545f2e12..9c29ece623f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -9,7 +9,7 @@ // except according to those terms. use Indent; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic}; use utils::span_after; use rewrite::{Rewrite, RewriteContext}; @@ -124,20 +124,6 @@ pub fn rewrite_use_list(width: usize, // 1 = } let remaining_width = width.checked_sub(supp_indent + 1).unwrap_or(0); - let fmt = ListFormatting { - tactic: ListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset + supp_indent, - h_width: remaining_width, - // FIXME This is too conservative, and will not use all width - // available - // (loose 1 column (";")) - v_width: remaining_width, - ends_with_newline: false, - config: context.config, - }; - let mut items = { // Dummy value, see explanation below. let mut items = vec![ListItem::from_str("")]; @@ -169,6 +155,21 @@ pub fn rewrite_use_list(width: usize, items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } + let tactic = ::lists::definitive_tactic(&items[first_index..], + ::lists::ListTactic::Mixed, + remaining_width); + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset + supp_indent, + // FIXME This is too conservative, and will not use all width + // available + // (loose 1 column (";")) + width: remaining_width, + ends_with_newline: false, + config: context.config, + }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); Some(if path_str.is_empty() { diff --git a/src/items.rs b/src/items.rs index e6a334d9ad3..c2f547162be 100644 --- a/src/items.rs +++ b/src/items.rs @@ -12,7 +12,8 @@ use Indent; use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, wrap_str}; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic, + DefinitiveListTactic, definitive_tactic}; use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; @@ -499,13 +500,20 @@ impl<'a> FmtVisitor<'a> { BlockIndentStyle::Visual => arg_indent, }; + let tactic = definitive_tactic(&arg_items, + self.config.fn_args_density.to_list_tactic(), + one_line_budget); + let budget = match tactic { + DefinitiveListTactic::Horizontal => one_line_budget, + _ => multi_line_budget, + }; + let fmt = ListFormatting { - tactic: self.config.fn_args_density.to_list_tactic(), + tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, indent: indent, - h_width: one_line_budget, - v_width: multi_line_budget, + width: budget, ends_with_newline: false, config: self.config, }; @@ -630,6 +638,7 @@ impl<'a> FmtVisitor<'a> { }, span_after(field.span, "(", self.codemap), next_span_start); + let item_vec = items.collect::>(); result.push('('); @@ -641,18 +650,20 @@ impl<'a> FmtVisitor<'a> { 0 }; let budget = self.config.max_width - indent.width() - comma_cost - 1; // 1 = ) + let tactic = definitive_tactic(&item_vec, + ListTactic::HorizontalVertical, + budget); let fmt = ListFormatting { - tactic: ListTactic::HorizontalVertical, + tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, indent: indent, - h_width: budget, - v_width: budget, + width: budget, ends_with_newline: true, config: self.config, }; - let list_str = match write_list(&items.collect::>(), &fmt) { + let list_str = match write_list(&item_vec, &fmt) { Some(list_str) => list_str, None => return, }; @@ -766,9 +777,9 @@ impl<'a> FmtVisitor<'a> { result.push('\n'); result.push_str(&indentation); - ListTactic::Vertical + DefinitiveListTactic::Vertical } else { - ListTactic::Horizontal + DefinitiveListTactic::Horizontal }; // 1 = , @@ -778,13 +789,12 @@ impl<'a> FmtVisitor<'a> { separator: ",", trailing_separator: self.config.struct_trailing_comma, indent: offset.block_indent(self.config), - h_width: self.config.max_width, - v_width: budget, + width: budget, ends_with_newline: true, config: self.config, }; - let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let list_str = try_opt!(write_list(items, &fmt)); result.push_str(&list_str); if break_line { @@ -930,21 +940,15 @@ impl<'a> FmtVisitor<'a> { let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(self.codemap, - lt_spans.chain(ty_spans), + lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), ">", - |sp| sp.lo, - |sp| sp.hi, - |_| String::new(), + |&(sp, _)| sp.lo, + |&(sp, _)| sp.hi, + // FIXME: don't clone + |&(_, ref str)| str.clone(), span_after(span, "<", self.codemap), span.hi); - let mut items = items.collect::>(); - - for (item, ty) in items.iter_mut().zip(lt_strs.chain(ty_strs)) { - item.item = ty; - } - - let fmt = ListFormatting::for_item(h_budget, offset, self.config); - let list_str = try_opt!(write_list(&items, &fmt)); + let list_str = try_opt!(::lists::format_item_list(items, h_budget, offset, self.config)); Some(format!("<{}>", list_str)) } @@ -990,18 +994,20 @@ impl<'a> FmtVisitor<'a> { |pred| pred.rewrite(&context, budget, offset).unwrap(), span_start, span_end); + let item_vec = items.collect::>(); + // FIXME: we don't need to collect here if the where_layout isnt horizontalVertical + let tactic = definitive_tactic(&item_vec, self.config.where_layout, budget); let fmt = ListFormatting { - tactic: self.config.where_layout, + tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, indent: offset, - h_width: budget, - v_width: budget, + width: budget, ends_with_newline: true, config: self.config, }; - let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let preds_str = try_opt!(write_list(&item_vec, &fmt)); // 9 = " where ".len() + " {".len() if density == Density::Tall || preds_str.contains('\n') || diff --git a/src/lib.rs b/src/lib.rs index c075589e99c..723c603ea3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,8 +119,7 @@ impl Indent { pub fn to_string(&self, config: &Config) -> String { let (num_tabs, num_spaces) = if config.hard_tabs { - (self.block_indent / config.tab_spaces, - self.alignment) + (self.block_indent / config.tab_spaces, self.alignment) } else { (0, self.block_indent + self.alignment) }; diff --git a/src/lists.rs b/src/lists.rs index 12eebb7b691..296df76e688 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -14,7 +14,7 @@ use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; use Indent; -use utils::{round_up_to_power_of_two, wrap_str}; +use utils::wrap_str; use comment::{FindUncommented, rewrite_comment, find_comment_end}; use config::Config; @@ -44,46 +44,69 @@ pub enum SeparatorTactic { impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical); // TODO having some helpful ctors for ListFormatting would be nice. +// FIXME: this should have only 1 width param pub struct ListFormatting<'a> { - pub tactic: ListTactic, + pub tactic: DefinitiveListTactic, pub separator: &'a str, pub trailing_separator: SeparatorTactic, pub indent: Indent, - // Available width if we layout horizontally. - pub h_width: usize, - // Available width if we layout vertically - pub v_width: usize, + pub width: usize, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. pub ends_with_newline: bool, pub config: &'a Config, } -impl<'a> ListFormatting<'a> { - pub fn for_fn(width: usize, offset: Indent, config: &'a Config) -> ListFormatting<'a> { - ListFormatting { - tactic: ListTactic::LimitedHorizontalVertical(config.fn_call_width), - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: width, - v_width: width, - ends_with_newline: false, - config: config, - } - } +pub fn format_fn_args(items: I, width: usize, offset: Indent, config: &Config) -> Option + where I: Iterator +{ + list_helper(items, + width, + offset, + config, + ListTactic::LimitedHorizontalVertical(config.fn_call_width)) +} - pub fn for_item(width: usize, offset: Indent, config: &'a Config) -> ListFormatting<'a> { - ListFormatting { - tactic: ListTactic::HorizontalVertical, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - h_width: width, - v_width: width, - ends_with_newline: false, - config: config, - } +pub fn format_item_list(items: I, + width: usize, + offset: Indent, + config: &Config) + -> Option + where I: Iterator +{ + list_helper(items, + width, + offset, + config, + ListTactic::HorizontalVertical) +} + +fn list_helper(items: I, + width: usize, + offset: Indent, + config: &Config, + tactic: ListTactic) + -> Option + where I: Iterator +{ + let item_vec: Vec<_> = items.collect(); + let tactic = definitive_tactic(&item_vec, tactic, width); + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + width: width, + ends_with_newline: false, + config: config, + }; + + write_list(&item_vec, &fmt) +} + +impl AsRef for ListItem { + fn as_ref(&self) -> &ListItem { + self } } @@ -116,76 +139,67 @@ impl ListItem { } } -// Format a list of commented items into a string. -// FIXME: this has grown into a monstrosity -// TODO: add unit tests -pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Option { - if items.is_empty() { - return Some(String::new()); - } - - let mut tactic = formatting.tactic; +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum DefinitiveListTactic { + Vertical, + Horizontal, + Mixed, +} - // Conservatively overestimates because of the changing separator tactic. - let sep_count = if formatting.trailing_separator == SeparatorTactic::Always { - items.len() - } else { - items.len() - 1 +pub fn definitive_tactic<'t, I, T>(items: I, + tactic: ListTactic, + width: usize) + -> DefinitiveListTactic + where I: IntoIterator + Clone, + T: AsRef +{ + let pre_line_comments = items.clone() + .into_iter() + .any(|item| item.as_ref().has_line_pre_comment()); + + let limit = match tactic { + _ if pre_line_comments => return DefinitiveListTactic::Vertical, + ListTactic::Mixed => return DefinitiveListTactic::Mixed, + ListTactic::Horizontal => return DefinitiveListTactic::Horizontal, + ListTactic::Vertical => return DefinitiveListTactic::Vertical, + ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit), + ListTactic::HorizontalVertical => width, }; - let sep_len = formatting.separator.len(); - let total_sep_len = (sep_len + 1) * sep_count; - let total_width = calculate_width(items); - let fits_single = total_width + total_sep_len <= formatting.h_width; - - // Check if we need to fallback from horizontal listing, if possible. - if let ListTactic::LimitedHorizontalVertical(limit) = tactic { - if total_width > limit { - tactic = ListTactic::Vertical; - } else { - tactic = ListTactic::HorizontalVertical; - } - } - if tactic == ListTactic::HorizontalVertical { - debug!("write_list: total_width: {}, total_sep_len: {}, h_width: {}", - total_width, - total_sep_len, - formatting.h_width); - tactic = if fits_single && !items.iter().any(ListItem::is_multiline) { - ListTactic::Horizontal - } else { - ListTactic::Vertical - }; - } - // Check if we can fit everything on a single line in mixed mode. - // The horizontal tactic does not break after v_width columns. - if tactic == ListTactic::Mixed && fits_single { - tactic = ListTactic::Horizontal; - } + let (sep_count, total_width) = calculate_width(items.clone()); + let sep_len = ", ".len(); // FIXME: make more generic? + let total_sep_len = sep_len * sep_count.checked_sub(1).unwrap_or(0); + let real_total = total_width + total_sep_len; - // Switch to vertical mode if we find non-block comments. - if items.iter().any(ListItem::has_line_pre_comment) { - tactic = ListTactic::Vertical; + if real_total <= limit && !pre_line_comments && + !items.into_iter().any(|item| item.as_ref().is_multiline()) { + DefinitiveListTactic::Horizontal + } else { + DefinitiveListTactic::Vertical } +} + +// Format a list of commented items into a string. +// TODO: add unit tests +pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option + where I: IntoIterator, + T: AsRef +{ + let tactic = formatting.tactic; + let sep_len = formatting.separator.len(); // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); - - // Create a buffer for the result. - // TODO could use a StringBuffer or rope for this - let alloc_width = if tactic == ListTactic::Horizontal { - total_width + total_sep_len - } else { - total_width + items.len() * (formatting.indent.width() + 1) - }; - let mut result = String::with_capacity(round_up_to_power_of_two(alloc_width)); + let mut result = String::new(); + let mut iter = items.into_iter().enumerate().peekable(); let mut line_len = 0; let indent_str = &formatting.indent.to_string(formatting.config); - for (i, item) in items.iter().enumerate() { + while let Some((i, item)) = iter.next() { + let item = item.as_ref(); let first = i == 0; - let last = i == items.len() - 1; + let last = iter.peek().is_none(); let separate = !last || trailing_separator; let item_sep_len = if separate { sep_len @@ -195,17 +209,17 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let item_width = item.item.len() + item_sep_len; match tactic { - ListTactic::Horizontal if !first => { + DefinitiveListTactic::Horizontal if !first => { result.push(' '); } - ListTactic::Vertical if !first => { + DefinitiveListTactic::Vertical if !first => { result.push('\n'); result.push_str(indent_str); } - ListTactic::Mixed => { + DefinitiveListTactic::Mixed => { let total_width = total_item_width(item) + item_sep_len; - if line_len > 0 && line_len + total_width > formatting.v_width { + if line_len > 0 && line_len + total_width > formatting.width { result.push('\n'); result.push_str(indent_str); line_len = 0; @@ -224,9 +238,9 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op // Pre-comments if let Some(ref comment) = item.pre_comment { // Block style in non-vertical mode. - let block_mode = tactic != ListTactic::Vertical; + let block_mode = tactic != DefinitiveListTactic::Vertical; // Width restriction is only relevant in vertical mode. - let max_width = formatting.v_width; + let max_width = formatting.width; let comment = try_opt!(rewrite_comment(comment, block_mode, max_width, @@ -234,7 +248,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op formatting.config)); result.push_str(&comment); - if tactic == ListTactic::Vertical { + if tactic == DefinitiveListTactic::Vertical { result.push('\n'); result.push_str(indent_str); } else { @@ -244,16 +258,16 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op let item_str = try_opt!(wrap_str(&item.item[..], formatting.config.max_width, - formatting.v_width, + formatting.width, formatting.indent)); result.push_str(&item_str); // Post-comments - if tactic != ListTactic::Vertical && item.post_comment.is_some() { + if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); let formatted_comment = try_opt!(rewrite_comment(comment, true, - formatting.v_width, + formatting.width, Indent::empty(), formatting.config)); @@ -265,9 +279,9 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op result.push_str(formatting.separator); } - if tactic == ListTactic::Vertical && item.post_comment.is_some() { + if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { // 1 = space between item and comment. - let width = formatting.v_width.checked_sub(item_width + 1).unwrap_or(1); + let width = formatting.width.checked_sub(item_width + 1).unwrap_or(1); let mut offset = formatting.indent; offset.alignment += item_width + 1; let comment = item.post_comment.as_ref().unwrap(); @@ -286,7 +300,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> Op result.push_str(&formatted_comment); } - if !last && tactic == ListTactic::Vertical && item.new_lines { + if !last && tactic == DefinitiveListTactic::Vertical && item.new_lines { result.push('\n'); } } @@ -449,25 +463,34 @@ pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap, } } -fn needs_trailing_separator(separator_tactic: SeparatorTactic, list_tactic: ListTactic) -> bool { +fn needs_trailing_separator(separator_tactic: SeparatorTactic, + list_tactic: DefinitiveListTactic) + -> bool { match separator_tactic { SeparatorTactic::Always => true, - SeparatorTactic::Vertical => list_tactic == ListTactic::Vertical, + SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical, SeparatorTactic::Never => false, } } -fn calculate_width(items: &[ListItem]) -> usize { - items.iter().map(total_item_width).fold(0, |a, l| a + l) +/// Returns the count and total width of the list items. +fn calculate_width<'li, I, T>(items: I) -> (usize, usize) + where I: IntoIterator, + T: AsRef +{ + items.into_iter() + .map(|item| total_item_width(item.as_ref())) + .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) } fn total_item_width(item: &ListItem) -> usize { - comment_len(&item.pre_comment) + comment_len(&item.post_comment) + item.item.len() + comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + item.item.len() } -fn comment_len(comment: &Option) -> usize { - match *comment { - Some(ref s) => { +fn comment_len(comment: Option<&str>) -> usize { + match comment { + Some(s) => { let text_len = s.trim().len(); if text_len > 0 { // We'll put " /*" before and " */" after inline comments. diff --git a/src/macros.rs b/src/macros.rs index 163a9f12f24..51fdd48a2ba 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -89,7 +89,12 @@ pub fn rewrite_macro(mac: &ast::Mac, match style { MacroStyle::Parens => { // Format macro invocation as function call. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, width, offset) + rewrite_call(context, + ¯o_name, + &expr_vec, + mac.span, + width, + offset) } MacroStyle::Brackets => { // Format macro invocation as array literal. diff --git a/src/types.rs b/src/types.rs index 2b757671a13..9fe837fced4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -13,7 +13,7 @@ use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; use Indent; -use lists::{itemize_list, write_list, ListFormatting}; +use lists::itemize_list; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; @@ -206,9 +206,7 @@ fn rewrite_segment(segment: &ast::PathSegment, .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); - let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), - "<", - context.codemap); + let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); let separator = get_path_separator(context.codemap, *span_lo, list_lo); // 1 for < @@ -232,9 +230,10 @@ fn rewrite_segment(segment: &ast::PathSegment, }, list_lo, span_hi); - - let fmt = ListFormatting::for_item(list_width, offset + extra_offset, context.config); - let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let list_str = try_opt!(::lists::format_item_list(items, + list_width, + offset + extra_offset, + context.config)); // Update position of last bracket. *span_lo = next_span_lo; @@ -263,9 +262,7 @@ fn rewrite_segment(segment: &ast::PathSegment, |ty| ty.rewrite(context, budget, offset).unwrap(), list_lo, span_hi); - - let fmt = ListFormatting::for_fn(budget, offset, context.config); - let list_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let list_str = try_opt!(::lists::format_fn_args(items, budget, offset, context.config)); format!("({}){}", list_str, output) } -- cgit 1.4.1-3-g733a5 From a76df6b4d9a67e67137cf0773d96f0027da827c7 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 4 Oct 2015 20:20:15 +0200 Subject: Make listItem contain option --- src/config.rs | 1 - src/expr.rs | 44 +++++++++------------------------ src/imports.rs | 8 +++--- src/items.rs | 49 ++++++++++++++++++------------------- src/lists.rs | 29 +++++++++++++--------- src/types.rs | 77 +++++++++++++++++++++++++++------------------------------- 6 files changed, 92 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 14d46a76834..1688b4b363e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -90,7 +90,6 @@ configuration_option_enum! { LicensePolicy: FileLicense, } -// TODO: this is not necessary any more configuration_option_enum! { MultilineStyle: // Use horizontal layout if it fits in one line, fall back to vertical PreferSingle, diff --git a/src/expr.rs b/src/expr.rs index d51bd256caa..53e24b70984 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -218,18 +218,16 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.span.lo, |item| item.span.hi, // 1 = [ - // FIXME(#133): itemize_list doesn't support - // rewrite failure. This may not be its - // responsibility, but that of write_list. - |item| { - item.rewrite(context, max_item_width, offset + 1) - .unwrap_or_else(|| context.snippet(item.span)) - }, + |item| item.rewrite(context, max_item_width, offset + 1), span_after(span, "[", context.codemap), span.hi) .collect::>(); - let tactic = if items.iter().any(|li| li.item.len() > 10 || li.is_multiline()) { + let has_long_item = try_opt!(items.iter() + .map(|li| li.item.as_ref().map(|s| s.len() > 10)) + .fold(Some(false), + |acc, x| acc.and_then(|y| x.map(|x| (x || y))))); + let tactic = if has_long_item || items.iter().any(|li| li.is_multiline()) { definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width) } else { DefinitiveListTactic::Mixed @@ -280,15 +278,7 @@ fn rewrite_closure(capture: ast::CaptureClause, "|", |arg| span_lo_for_arg(arg), |arg| span_hi_for_arg(arg), - |arg| { - // FIXME: we should just escalate failure - // here, but itemize_list doesn't allow it. - arg.rewrite(context, budget, argument_offset) - .unwrap_or_else(|| { - context.snippet(mk_sp(span_lo_for_arg(arg), - span_hi_for_arg(arg))) - }) - }, + |arg| arg.rewrite(context, budget, argument_offset), span_after(span, "|", context.codemap), body.span.lo); let item_vec = arg_items.collect::>(); @@ -1151,11 +1141,7 @@ fn rewrite_call_inner(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - // Take old span when rewrite fails. - |item| { - item.rewrite(&inner_context, remaining_width, offset) - .unwrap_or(context.snippet(item.span)) - }, + |item| item.rewrite(&inner_context, remaining_width, offset), span.lo, span.hi); @@ -1251,18 +1237,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(ref field) => { rewrite_field(inner_context, &field, v_budget, indent) - .unwrap_or(context.snippet(field.span)) } StructLitField::Base(ref expr) => { // 2 = .. - format!("..{}", - v_budget.checked_sub(2) - .and_then(|v_budget| { - expr.rewrite(inner_context, - v_budget, - indent + 2) - }) - .unwrap_or(context.snippet(expr.span))) + expr.rewrite(inner_context, + try_opt!(v_budget.checked_sub(2)), + indent + 2) + .map(|s| format!("..{}", s)) } } }, @@ -1365,7 +1346,6 @@ fn rewrite_tuple_lit(context: &RewriteContext, |item| { let inner_width = context.config.max_width - indent.width() - 1; item.rewrite(context, inner_width, indent) - .unwrap_or(context.snippet(item.span)) }, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); diff --git a/src/imports.rs b/src/imports.rs index 9c29ece623f..2c518378b36 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -71,7 +71,7 @@ fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String append_alias(path_item_str, vpi) } -fn rewrite_path_item(vpi: &&ast::PathListItem) -> String { +fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { let path_item_str = match vpi.node { ast::PathListItem_::PathListIdent{ name, .. } => { name.to_string() @@ -81,7 +81,7 @@ fn rewrite_path_item(vpi: &&ast::PathListItem) -> String { } }; - append_alias(path_item_str, vpi) + Some(append_alias(path_item_str, vpi)) } fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { @@ -142,8 +142,6 @@ pub fn rewrite_use_list(width: usize, // We prefixed the item list with a dummy value so that we can // potentially move "self" to the front of the vector without touching // the rest of the items. - // FIXME: Make more efficient by using a linked list? That would require - // changes to the signatures of write_list. let has_self = move_self_to_front(&mut items); let first_index = if has_self { 0 @@ -181,7 +179,7 @@ pub fn rewrite_use_list(width: usize, // Returns true when self item was found. fn move_self_to_front(items: &mut Vec) -> bool { - match items.iter().position(|item| item.item == "self") { + match items.iter().position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) { Some(pos) => { items[0] = items.remove(pos); true diff --git a/src/items.rs b/src/items.rs index c2f547162be..e2f59f0fb6a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -481,7 +481,7 @@ impl<'a> FmtVisitor<'a> { ")", |arg| span_lo_for_arg(arg), |arg| arg.ty.span.hi, - |_| String::new(), + |_| None, comment_span_start, span.hi); @@ -491,7 +491,7 @@ impl<'a> FmtVisitor<'a> { assert_eq!(arg_item_strs.len(), arg_items.len()); for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { - item.item = arg; + item.item = Some(arg); } let indent = match self.config.fn_arg_indent { @@ -630,11 +630,9 @@ impl<'a> FmtVisitor<'a> { |arg| arg.ty.span.hi, |arg| { // FIXME silly width, indent - arg.ty - .rewrite(&self.get_context(), - 1000, - Indent::empty()) - .unwrap() + arg.ty.rewrite(&self.get_context(), + 1000, + Indent::empty()) }, span_after(field.span, "(", self.codemap), next_span_start); @@ -863,9 +861,14 @@ impl<'a> FmtVisitor<'a> { } // Field of a struct - fn format_field(&self, field: &ast::StructField) -> String { + fn format_field(&self, field: &ast::StructField) -> Option { if contains_skip(&field.node.attrs) { - return self.snippet(codemap::mk_sp(field.node.attrs[0].span.lo, field.span.hi)); + // FIXME: silly width, indent + return wrap_str(self.snippet(codemap::mk_sp(field.node.attrs[0].span.lo, + field.span.hi)), + self.config.max_width, + 1000, + Indent::empty()); } let name = match field.node.kind { @@ -877,24 +880,23 @@ impl<'a> FmtVisitor<'a> { ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; // FIXME silly width, indent - let typ = field.node.ty.rewrite(&self.get_context(), 1000, Indent::empty()).unwrap(); + let typ = try_opt!(field.node.ty.rewrite(&self.get_context(), 1000, Indent::empty())); let indent = self.block_indent.block_indent(self.config); - let mut attr_str = field.node - .attrs - .rewrite(&self.get_context(), - self.config.max_width - indent.width(), - indent) - .unwrap(); + let mut attr_str = try_opt!(field.node + .attrs + .rewrite(&self.get_context(), + self.config.max_width - indent.width(), + indent)); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&indent.to_string(self.config)); } - match name { + Some(match name { Some(name) => format!("{}{}{}: {}", attr_str, vis, name, typ), None => format!("{}{}{}", attr_str, vis, typ), - } + }) } fn rewrite_generics(&self, @@ -923,10 +925,8 @@ impl<'a> FmtVisitor<'a> { // Strings for the generics. let context = self.get_context(); - // FIXME: don't unwrap - let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset).unwrap()); - let ty_strs = tys.iter() - .map(|ty_param| ty_param.rewrite(&context, h_budget, offset).unwrap()); + let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset)); + let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(&context, h_budget, offset)); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { @@ -988,10 +988,7 @@ impl<'a> FmtVisitor<'a> { "{", |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - // FIXME: we should handle failure better - // this will be taken care of when write_list - // takes Rewrite object: see issue #133 - |pred| pred.rewrite(&context, budget, offset).unwrap(), + |pred| pred.rewrite(&context, budget, offset), span_start, span_end); let item_vec = items.collect::>(); diff --git a/src/lists.rs b/src/lists.rs index 296df76e688..514acd13f53 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -43,8 +43,6 @@ pub enum SeparatorTactic { impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical); -// TODO having some helpful ctors for ListFormatting would be nice. -// FIXME: this should have only 1 width param pub struct ListFormatting<'a> { pub tactic: DefinitiveListTactic, pub separator: &'a str, @@ -111,9 +109,11 @@ impl AsRef for ListItem { } pub struct ListItem { + // None for comments mean that they are not present. pub pre_comment: Option, - // Item should include attributes and doc comments. - pub item: String, + // Item should include attributes and doc comments. None indicates failed + // rewrite. + pub item: Option, pub post_comment: Option, // Whether there is extra whitespace before this item. pub new_lines: bool, @@ -121,7 +121,9 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { - self.item.contains('\n') || self.pre_comment.is_some() || + // FIXME: fail earlier! + self.item.as_ref().map(|s| s.contains('\n')).unwrap_or(false) || + self.pre_comment.is_some() || self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false) } @@ -132,7 +134,7 @@ impl ListItem { pub fn from_str>(s: S) -> ListItem { ListItem { pre_comment: None, - item: s.into(), + item: Some(s.into()), post_comment: None, new_lines: false, } @@ -198,6 +200,7 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option let indent_str = &formatting.indent.to_string(formatting.config); while let Some((i, item)) = iter.next() { let item = item.as_ref(); + let inner_item = try_opt!(item.item.as_ref()); let first = i == 0; let last = iter.peek().is_none(); let separate = !last || trailing_separator; @@ -206,7 +209,7 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option } else { 0 }; - let item_width = item.item.len() + item_sep_len; + let item_width = inner_item.len() + item_sep_len; match tactic { DefinitiveListTactic::Horizontal if !first => { @@ -256,7 +259,8 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option } } - let item_str = try_opt!(wrap_str(&item.item[..], + // Make sure that string actually fits. + let item_str = try_opt!(wrap_str(&inner_item[..], formatting.config.max_width, formatting.width, formatting.indent)); @@ -325,7 +329,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> where I: Iterator, F1: Fn(&T) -> BytePos, F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> String + F3: Fn(&T) -> Option { type Item = ListItem; @@ -449,7 +453,7 @@ pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap, where I: Iterator, F1: Fn(&T) -> BytePos, F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> String + F3: Fn(&T) -> Option { ListItems { codemap: codemap, @@ -484,8 +488,11 @@ fn calculate_width<'li, I, T>(items: I) -> (usize, usize) } fn total_item_width(item: &ListItem) -> usize { + // FIXME: If the item has a `None` item, it may be better to fail earlier + // rather than later. comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + - comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + item.item.len() + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + + item.item.as_ref().map(|str| str.len()).unwrap_or(0) } fn comment_len(comment: Option<&str>) -> usize { diff --git a/src/types.rs b/src/types.rs index 9fe837fced4..6f6afbfc42e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -219,14 +219,10 @@ fn rewrite_segment(segment: &ast::PathSegment, ">", |param| param.get_span().lo, |param| param.get_span().hi, - // FIXME(#133): write_list should call - // rewrite itself, because it has a better - // context. |seg| { seg.rewrite(context, context.config.max_width, offset + extra_offset) - .unwrap() }, list_lo, span_hi); @@ -259,7 +255,7 @@ fn rewrite_segment(segment: &ast::PathSegment, ")", |ty| ty.span.lo, |ty| ty.span.hi, - |ty| ty.rewrite(context, budget, offset).unwrap(), + |ty| ty.rewrite(context, budget, offset), list_lo, span_hi); let list_str = try_opt!(::lists::format_fn_args(items, budget, offset, context.config)); @@ -284,40 +280,39 @@ impl Rewrite for ast::WherePredicate { let type_str = try_opt!(bounded_ty.rewrite(context, width, offset)); if !bound_lifetimes.is_empty() { - let lifetime_str = bound_lifetimes.iter() - .map(|lt| { - lt.rewrite(context, width, offset) - .unwrap() - }) - .collect::>() - .join(", "); + let lifetime_str = try_opt!(bound_lifetimes.iter() + .map(|lt| { + lt.rewrite(context, + width, + offset) + }) + .collect::>>()) + .join(", "); // 8 = "for<> : ".len() let used_width = lifetime_str.len() + type_str.len() + 8; let budget = try_opt!(width.checked_sub(used_width)); - let bounds_str = bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - budget, - offset + used_width) - .unwrap() - }) - .collect::>() - .join(" + "); + let bounds_str = try_opt!(bounds.iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + budget, + offset + used_width) + }) + .collect::>>()) + .join(" + "); format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { // 2 = ": ".len() let used_width = type_str.len() + 2; let budget = try_opt!(width.checked_sub(used_width)); - let bounds_str = bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - budget, - offset + used_width) - .unwrap() - }) - .collect::>() - .join(" + "); + let bounds_str = try_opt!(bounds.iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + budget, + offset + used_width) + }) + .collect::>>()) + .join(" + "); format!("{}: {}", type_str, bounds_str) } @@ -380,9 +375,9 @@ impl Rewrite for ast::TyParamBound { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - let strs: Vec<_> = self.iter() - .map(|b| b.rewrite(context, width, offset).unwrap()) - .collect(); + let strs: Vec<_> = try_opt!(self.iter() + .map(|b| b.rewrite(context, width, offset)) + .collect()); Some(strs.join(" + ")) } } @@ -395,10 +390,10 @@ impl Rewrite for ast::TyParam { if !self.bounds.is_empty() { result.push_str(": "); - let bounds = self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, width, offset).unwrap()) - .collect::>() + let bounds = try_opt!(self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, width, offset)) + .collect::>>()) .join(" + "); result.push_str(&bounds); @@ -418,10 +413,10 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if !self.bound_lifetimes.is_empty() { - let lifetime_str = self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, width, offset).unwrap()) - .collect::>() + let lifetime_str = try_opt!(self.bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, width, offset)) + .collect::>>()) .join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; -- cgit 1.4.1-3-g733a5 From 199d40fa5589bb0e74c4086e30825015277439c1 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 6 Oct 2015 22:13:14 +0200 Subject: Increase default function call width limit --- Cargo.lock | 16 ++++++++-------- src/comment.rs | 3 +-- src/config.rs | 2 +- src/expr.rs | 54 ++++++++++++++---------------------------------------- src/filemap.rs | 3 +-- src/imports.rs | 8 ++++---- src/issues.rs | 7 ++----- src/items.rs | 4 +--- src/lib.rs | 1 - src/lists.rs | 17 +++++++---------- src/macros.rs | 7 +------ src/types.rs | 15 +++++++-------- src/visitor.rs | 8 ++------ 13 files changed, 49 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b0f1f478df3..3648e5e5f67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,11 +2,11 @@ name = "rustfmt" version = "0.0.1" dependencies = [ - "diff 0.1.5 (git+https://github.com/utkarshkukreti/diff.rs.git)", + "diff 0.1.7 (git+https://github.com/utkarshkukreti/diff.rs.git)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", - "term 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -21,15 +21,15 @@ dependencies = [ [[package]] name = "diff" -version = "0.1.5" -source = "git+https://github.com/utkarshkukreti/diff.rs.git#1921576a73e1b50a0ecb26c8ce62eefb26d273b4" +version = "0.1.7" +source = "git+https://github.com/utkarshkukreti/diff.rs.git#6edb9454bf4127087aced0fe07ab3ea6894083cb" [[package]] name = "kernel32-sys" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -84,11 +84,11 @@ dependencies = [ [[package]] name = "term" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -106,7 +106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/src/comment.rs b/src/comment.rs index b08e46681a7..86d1a9aeb14 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -348,8 +348,7 @@ mod test { assert_eq!(&uncommented("abc/*...*/"), "abc"); assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), "..ac\n"); - assert_eq!(&uncommented("abc \" /* */\" qsdf"), - "abc \" /* */\" qsdf"); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); } #[test] diff --git a/src/config.rs b/src/config.rs index 1688b4b363e..b237ce4ddfc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -260,7 +260,7 @@ create_config! { max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; - fn_call_width: usize, 55, + fn_call_width: usize, 60, "Maximum width of the args of a function call before faling back to vertical formatting"; struct_lit_width: usize, 16, "Maximum width in the body of a struct lit before faling back to vertical formatting"; diff --git a/src/expr.rs b/src/expr.rs index 53e24b70984..ac966dc5118 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -14,7 +14,7 @@ use std::borrow::Borrow; use Indent; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic}; + DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; use string::{StringFormat, rewrite_string}; use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search}; use visitor::FmtVisitor; @@ -148,13 +148,7 @@ impl Rewrite for ast::Expr { Some(format!("break{}", id_str)) } ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { - rewrite_closure(capture, - fn_decl, - body, - self.span, - context, - width, - offset) + rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } ast::Expr_::ExprField(..) | ast::Expr_::ExprTupField(..) | @@ -172,10 +166,7 @@ impl Rewrite for ast::Expr { }) } ast::Expr_::ExprRet(None) => { - wrap_str("return".to_owned(), - context.config.max_width, - width, - offset) + wrap_str("return".to_owned(), context.config.max_width, width, offset) } ast::Expr_::ExprRet(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", expr, width, offset) @@ -227,7 +218,8 @@ pub fn rewrite_array<'a, I>(expr_iter: I, .map(|li| li.item.as_ref().map(|s| s.len() > 10)) .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| (x || y))))); - let tactic = if has_long_item || items.iter().any(|li| li.is_multiline()) { + + let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width) } else { DefinitiveListTactic::Mixed @@ -282,9 +274,7 @@ fn rewrite_closure(capture: ast::CaptureClause, span_after(span, "|", context.codemap), body.span.lo); let item_vec = arg_items.collect::>(); - let tactic = definitive_tactic(&item_vec, - ListTactic::HorizontalVertical, - horizontal_budget); + let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget); let budget = match tactic { DefinitiveListTactic::Horizontal => horizontal_budget, _ => budget, @@ -589,11 +579,7 @@ fn rewrite_if_else(context: &RewriteContext, // Try to format if-else on single line. if allow_single_line && context.config.single_line_if_else { - let trial = single_line_if_else(context, - &pat_expr_string, - if_block, - else_block_opt, - width); + let trial = single_line_if_else(context, &pat_expr_string, if_block, else_block_opt, width); if trial.is_some() { return trial; @@ -780,8 +766,7 @@ fn rewrite_match(context: &RewriteContext, } } // BytePos(1) = closing match brace. - let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), - span.hi - BytePos(1)); + let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi - BytePos(1)); let last_comment = context.snippet(last_span); let comment = try_opt!(rewrite_match_arm_comment(context, &last_comment, @@ -894,8 +879,7 @@ impl Rewrite for ast::Arm { // 4 = ` => `.len() let same_line_body = if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; - let offset = Indent::new(offset.block_indent, - line_start + 4 - offset.block_indent); + let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); match rewrite { @@ -1081,13 +1065,7 @@ pub fn rewrite_call(context: &RewriteContext, where R: Rewrite { let closure = |callee_max_width| { - rewrite_call_inner(context, - callee, - callee_max_width, - args, - span, - width, - offset) + rewrite_call_inner(context, callee, callee_max_width, args, span, width, offset) }; // 2 is for parens @@ -1145,7 +1123,7 @@ fn rewrite_call_inner(context: &RewriteContext, span.lo, span.hi); - let list_str = match ::lists::format_fn_args(items, remaining_width, offset, context.config) { + let list_str = match format_fn_args(items, remaining_width, offset, context.config) { Some(str) => str, None => return Err(Ordering::Less), }; @@ -1174,9 +1152,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("rewrite_struct_lit: width {}, offset {:?}", - width, - offset); + debug!("rewrite_struct_lit: width {}, offset {:?}", width, offset); assert!(!fields.is_empty() || base.is_some()); enum StructLitField<'a> { @@ -1327,9 +1303,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("rewrite_tuple_lit: width: {}, offset: {:?}", - width, - offset); + debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset); let indent = offset + 1; // In case of length 1, need a trailing comma if items.len() == 1 { @@ -1350,7 +1324,7 @@ fn rewrite_tuple_lit(context: &RewriteContext, span.lo + BytePos(1), // Remove parens span.hi - BytePos(1)); let budget = try_opt!(width.checked_sub(2)); - let list_str = try_opt!(::lists::format_fn_args(items, budget, indent, context.config)); + let list_str = try_opt!(format_fn_args(items, budget, indent, context.config)); Some(format!("({})", list_str)) } diff --git a/src/filemap.rs b/src/filemap.rs index f3f952bd00c..d94c1501734 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -115,8 +115,7 @@ fn write_file(text: &StringBuffer, try!(write_system_newlines(&mut v, text, config)); let fmt_text = String::from_utf8(v).unwrap(); let diff = make_diff(&ori_text, &fmt_text, 3); - print_diff(diff, - |line_num| format!("\nDiff at line {}:", line_num)); + print_diff(diff, |line_num| format!("\nDiff at line {}:", line_num)); } WriteMode::Return => { // io::Write is not implemented for String, working around with diff --git a/src/imports.rs b/src/imports.rs index 2c518378b36..aab5dd76799 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -9,7 +9,7 @@ // except according to those terms. use Indent; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; use utils::span_after; use rewrite::{Rewrite, RewriteContext}; @@ -153,9 +153,9 @@ pub fn rewrite_use_list(width: usize, items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } - let tactic = ::lists::definitive_tactic(&items[first_index..], - ::lists::ListTactic::Mixed, - remaining_width); + let tactic = definitive_tactic(&items[first_index..], + ::lists::ListTactic::Mixed, + remaining_width); let fmt = ListFormatting { tactic: tactic, separator: ",", diff --git a/src/issues.rs b/src/issues.rs index 6f64436bb52..04a61fff358 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -236,8 +236,7 @@ fn find_unnumbered_issue() { fn check_pass(text: &str) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, - text.chars().position(|c| seeker.inspect(c).is_some())); + assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); } check_fail("TODO\n", 4); @@ -272,9 +271,7 @@ fn find_issue() { ReportTactic::Never, ReportTactic::Always)); - assert!(!is_bad_issue("bad FIXME\n", - ReportTactic::Always, - ReportTactic::Never)); + assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Always, ReportTactic::Never)); } #[test] diff --git a/src/items.rs b/src/items.rs index e2f59f0fb6a..9cc228ae2c8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -312,9 +312,7 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let ret_str = fd.output - .rewrite(&context, - self.config.max_width - indent.width(), - indent) + .rewrite(&context, self.config.max_width - indent.width(), indent) .unwrap(); // Args. diff --git a/src/lib.rs b/src/lib.rs index 723c603ea3f..1dfb05c88b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,6 @@ // keeping some scratch mem for this and running our own StrPool? // TODO for lint violations of names, emit a refactor script - #[macro_use] extern crate log; diff --git a/src/lists.rs b/src/lists.rs index 514acd13f53..e7565851871 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -19,12 +19,15 @@ use comment::{FindUncommented, rewrite_comment, find_comment_end}; use config::Config; #[derive(Eq, PartialEq, Debug, Copy, Clone)] +/// Formatting tactic for lists. This will be cast down to a +/// DefinitiveListTactic depending on the number and length of the items and +/// their comments. pub enum ListTactic { // One item per row. Vertical, // All items on one row. Horizontal, - // Try Horizontal layout, if that fails then vertical + // Try Horizontal layout, if that fails then vertical. HorizontalVertical, // HorizontalVertical with a soft limit of n characters. LimitedHorizontalVertical(usize), @@ -72,11 +75,7 @@ pub fn format_item_list(items: I, -> Option where I: Iterator { - list_helper(items, - width, - offset, - config, - ListTactic::HorizontalVertical) + list_helper(items, width, offset, config, ListTactic::HorizontalVertical) } fn list_helper(items: I, @@ -111,7 +110,7 @@ impl AsRef for ListItem { pub struct ListItem { // None for comments mean that they are not present. pub pre_comment: Option, - // Item should include attributes and doc comments. None indicates failed + // Item should include attributes and doc comments. None indicates a failed // rewrite. pub item: Option, pub post_comment: Option, @@ -121,7 +120,6 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { - // FIXME: fail earlier! self.item.as_ref().map(|s| s.contains('\n')).unwrap_or(false) || self.pre_comment.is_some() || self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false) @@ -142,6 +140,7 @@ impl ListItem { } #[derive(Eq, PartialEq, Debug, Copy, Clone)] +/// The definitive formatting tactic for lists. pub enum DefinitiveListTactic { Vertical, Horizontal, @@ -488,8 +487,6 @@ fn calculate_width<'li, I, T>(items: I) -> (usize, usize) } fn total_item_width(item: &ListItem) -> usize { - // FIXME: If the item has a `None` item, it may be better to fail earlier - // rather than later. comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + item.item.as_ref().map(|str| str.len()).unwrap_or(0) diff --git a/src/macros.rs b/src/macros.rs index 51fdd48a2ba..163a9f12f24 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -89,12 +89,7 @@ pub fn rewrite_macro(mac: &ast::Mac, match style { MacroStyle::Parens => { // Format macro invocation as function call. - rewrite_call(context, - ¯o_name, - &expr_vec, - mac.span, - width, - offset) + rewrite_call(context, ¯o_name, &expr_vec, mac.span, width, offset) } MacroStyle::Brackets => { // Format macro invocation as array literal. diff --git a/src/types.rs b/src/types.rs index 6f6afbfc42e..2cbbed92fa5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -13,7 +13,7 @@ use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; use Indent; -use lists::itemize_list; +use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; @@ -226,10 +226,10 @@ fn rewrite_segment(segment: &ast::PathSegment, }, list_lo, span_hi); - let list_str = try_opt!(::lists::format_item_list(items, - list_width, - offset + extra_offset, - context.config)); + let list_str = try_opt!(format_item_list(items, + list_width, + offset + extra_offset, + context.config)); // Update position of last bracket. *span_lo = next_span_lo; @@ -258,7 +258,7 @@ fn rewrite_segment(segment: &ast::PathSegment, |ty| ty.rewrite(context, budget, offset), list_lo, span_hi); - let list_str = try_opt!(::lists::format_fn_args(items, budget, offset, context.config)); + let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); format!("({}){}", list_str, output) } @@ -363,8 +363,7 @@ impl Rewrite for ast::TyParamBound { } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { let budget = try_opt!(width.checked_sub(1)); - Some(format!("?{}", - try_opt!(tref.rewrite(context, budget, offset + 1)))) + Some(format!("?{}", try_opt!(tref.rewrite(context, budget, offset + 1)))) } ast::TyParamBound::RegionTyParamBound(ref l) => { Some(pprust::lifetime_to_string(l)) diff --git a/src/visitor.rs b/src/visitor.rs index 883d46a22d4..b02e8a72b8f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -319,9 +319,7 @@ impl<'a> FmtVisitor<'a> { } fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { - debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", - ident, - s); + debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); @@ -359,9 +357,7 @@ impl<'a> FmtVisitor<'a> { overflow_indent: Indent::empty(), }; // 1 = ";" - match vp.rewrite(&context, - self.config.max_width - offset.width() - 1, - offset) { + match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, span.lo); -- cgit 1.4.1-3-g733a5 From 6600cd341a4e0e2d14199c17e90b139ae641a619 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 8 Oct 2015 17:20:19 +1300 Subject: Format inner and outer attributes separately. Actually just skips inner attributes, because its a pain to track them, and lets missed spans handle them. Closes #413 --- src/visitor.rs | 36 ++++++++++++++++++++++-------------- tests/target/fn.rs | 6 ++++++ 2 files changed, 28 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 69217034d00..4827f68dafa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -270,7 +270,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } impl<'a> FmtVisitor<'a> { - pub fn from_codemap<'b>(codemap: &'b CodeMap, config: &'b Config) -> FmtVisitor<'b> { + pub fn from_codemap(codemap: &'a CodeMap, config: &'a Config) -> FmtVisitor<'a> { FmtVisitor { codemap: codemap, buffer: StringBuffer::new(), @@ -301,21 +301,29 @@ impl<'a> FmtVisitor<'a> { return false; } - let first = &attrs[0]; - self.format_missing_with_indent(first.span.lo); - if utils::contains_skip(attrs) { - true - } else { - let rewrite = attrs.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) - .unwrap(); - self.buffer.push_str(&rewrite); - let last = attrs.last().unwrap(); - self.last_pos = last.span.hi; - false + return true; } + + let outers: Vec<_> = attrs.iter() + .filter(|a| a.node.style == ast::AttrStyle::Outer) + .map(|a| a.clone()) + .collect(); + if outers.is_empty() { + return false; + } + + let first = &outers[0]; + self.format_missing_with_indent(first.span.lo); + + let rewrite = outers.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent) + .unwrap(); + self.buffer.push_str(&rewrite); + let last = outers.last().unwrap(); + self.last_pos = last.span.hi; + false } fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { diff --git a/tests/target/fn.rs b/tests/target/fn.rs index d8a705fb39b..da13a6f05dc 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -87,3 +87,9 @@ fn main() { let _ = move || 42; let _ = || unsafe { abort() }; } + +// With inner attributes. +fn inner() { + #![inline] + x +} -- cgit 1.4.1-3-g733a5 From e68cd089358b04e50d8a4e740d6f471a72ff3049 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 8 Oct 2015 16:13:10 +0200 Subject: Fix typos in config descriptions --- src/config.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b237ce4ddfc..6a7e686dc11 100644 --- a/src/config.rs +++ b/src/config.rs @@ -261,14 +261,14 @@ create_config! { ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; fn_call_width: usize, 60, - "Maximum width of the args of a function call before faling back to vertical formatting"; + "Maximum width of the args of a function call before falling back to vertical formatting"; struct_lit_width: usize, 16, - "Maximum width in the body of a struct lit before faling back to vertical formatting"; + "Maximum width in the body of a struct lit before falling back to vertical formatting"; newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, "Location of return type in function declaration"; - fn_args_paren_newline: bool, true, "If function argument parenthases goes on a newline"; + fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, "Argument density in functions"; fn_args_layout: StructLitStyle, StructLitStyle::Visual, "Layout of function arguments"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; @@ -287,12 +287,12 @@ create_config! { "If there is a trailing comma on literal structs"; struct_lit_style: StructLitStyle, StructLitStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, - "Multilline style on literal structs"; + "Multiline style on literal structs"; enum_trailing_comma: bool, true, "Put a trailing comma on enum declarations"; report_todo: ReportTactic, ReportTactic::Always, - "Report all occurences of TODO in source file comments"; + "Report all occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, - "Report all occurences of FIXME in source file comments"; + "Report all occurrences of FIXME in source file comments"; // Alphabetically, case sensitive. reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; -- cgit 1.4.1-3-g733a5 From 8daf4c3a31b6d9549cead4a0c076fc533eb9f38d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 8 Oct 2015 22:04:17 +0200 Subject: Prevent panics on list-like macro uses with trailing commas --- src/macros.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 163a9f12f24..58b2c5db25f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -64,7 +64,8 @@ pub fn rewrite_macro(mac: &ast::Mac, let wrapped_tt_vec = ForceSend(mac.node.tts.clone()); // Wrap expression parsing logic in a thread since the libsyntax parser - // panicks on failure, which we do not want to propagate. + // panics on failure, which we do not want to propagate. + // The expression vector is wrapped in an Option inside a Result. let expr_vec_result = thread::catch_panic(move || { let parse_session = ParseSess::new(); let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]); @@ -80,11 +81,15 @@ pub fn rewrite_macro(mac: &ast::Mac, } let _ = parser.bump(); + + if parser.token == Token::Eof { + return None; + } } - expr_vec + Some(expr_vec) }); - let expr_vec = try_opt!(expr_vec_result.ok()); + let expr_vec = try_opt!(try_opt!(expr_vec_result.ok())); match style { MacroStyle::Parens => { -- cgit 1.4.1-3-g733a5 From 5162282b6060349a672419fb86cdb2a46b59d113 Mon Sep 17 00:00:00 2001 From: mwiczer Date: Wed, 7 Oct 2015 19:23:07 -0400 Subject: Support pre- and post-comments for enums Use lists to format enum variants rather than special formatting. Add tests for enums mostly around block comments. --- src/items.rs | 125 +++++++++++++++++++++++++++++++++--------------- src/lists.rs | 19 ++++++-- tests/source/enum.rs | 94 ++++++++++++++++++++++++++++++++++++ tests/source/structs.rs | 10 ++++ tests/target/enum.rs | 91 ++++++++++++++++++++++++++++++++++- tests/target/structs.rs | 13 +++++ 6 files changed, 310 insertions(+), 42 deletions(-) create mode 100644 tests/source/enum.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3d9a0e56aa4..816bfac0fb3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -592,31 +592,88 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&generics_str); self.last_pos = body_start; - self.block_indent = self.block_indent.block_indent(self.config); - for (i, f) in enum_def.variants.iter().enumerate() { - let next_span_start: BytePos = if i == enum_def.variants.len() - 1 { - span.hi - } else { - enum_def.variants[i + 1].span.lo - }; - self.visit_variant(f, i == enum_def.variants.len() - 1, next_span_start); + self.block_indent = self.block_indent.block_indent(self.config); + let variant_list = self.format_variant_list(enum_def, body_start, span.hi - BytePos(1)); + match variant_list { + Some(ref body_str) => self.buffer.push_str(&body_str), + None => self.format_missing(span.hi - BytePos(1)), } self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(span.hi - BytePos(1)); + if variant_list.is_some() { + self.buffer.push_str(&self.block_indent.to_string(self.config)); + } self.buffer.push_str("}"); + self.last_pos = span.hi; + } + + // Format the body of an enum definition + fn format_variant_list(&self, + enum_def: &ast::EnumDef, + body_lo: BytePos, + body_hi: BytePos) + -> Option { + if enum_def.variants.is_empty() { + return None; + } + let mut result = String::with_capacity(1024); + result.push('\n'); + let indentation = self.block_indent.to_string(self.config); + result.push_str(&indentation); + + let items = itemize_list(self.codemap, + enum_def.variants.iter(), + "}", + |f| { + if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo + } else { + f.span.lo + } + }, + |f| f.span.hi, + |f| self.format_variant(f), + body_lo, + body_hi); + + let budget = self.config.max_width - self.block_indent.width() - 2; + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Always, + indent: self.block_indent, + width: budget, + ends_with_newline: true, + config: self.config, + }; + + let list = try_opt!(write_list(items, &fmt)); + result.push_str(&list); + result.push('\n'); + Some(result) } // Variant of an enum. - fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_start: BytePos) { - if self.visit_attrs(&field.node.attrs) { - return; + fn format_variant(&self, field: &ast::Variant) -> Option { + if contains_skip(&field.node.attrs) { + let lo = field.node.attrs[0].span.lo; + let span = codemap::mk_sp(lo, field.span.hi); + return Some(self.snippet(span)); } - self.format_missing_with_indent(field.span.lo); + let indent = self.block_indent; + let mut result = try_opt!(field.node + .attrs + .rewrite(&self.get_context(), + self.config.max_width - indent.width(), + indent)); + if !result.is_empty() { + result.push('\n'); + result.push_str(&indent.to_string(self.config)); + } - let result = match field.node.kind { + let variant_body = match field.node.kind { ast::VariantKind::TupleVariantKind(ref types) => { let mut result = field.node.name.to_string(); @@ -633,12 +690,12 @@ impl<'a> FmtVisitor<'a> { Indent::empty()) }, span_after(field.span, "(", self.codemap), - next_span_start); + field.span.hi); let item_vec = items.collect::>(); result.push('('); - let indent = self.block_indent + field.node.name.to_string().len() + "(".len(); + let indent = indent + field.node.name.to_string().len() + "(".len(); let comma_cost = if self.config.enum_trailing_comma { 1 @@ -659,10 +716,7 @@ impl<'a> FmtVisitor<'a> { ends_with_newline: true, config: self.config, }; - let list_str = match write_list(&item_vec, &fmt) { - Some(list_str) => list_str, - None => return, - }; + let list_str = try_opt!(write_list(&item_vec, &fmt)); result.push_str(&list_str); result.push(')'); @@ -674,31 +728,26 @@ impl<'a> FmtVisitor<'a> { result.push_str(&expr_snippet); } - result + Some(result) } ast::VariantKind::StructVariantKind(ref struct_def) => { // TODO: Should limit the width, as we have a trailing comma - let struct_rewrite = self.format_struct("", - field.node.name, - ast::Visibility::Inherited, - struct_def, - None, - field.span, - self.block_indent); - - match struct_rewrite { - Some(struct_str) => struct_str, - None => return, - } + self.format_struct("", + field.node.name, + ast::Visibility::Inherited, + struct_def, + None, + field.span, + indent) } }; - self.buffer.push_str(&result); - if !last_field || self.config.enum_trailing_comma { - self.buffer.push_str(","); + if let Some(variant_str) = variant_body { + result.push_str(&variant_str); + Some(result) + } else { + None } - - self.last_pos = field.span.hi + BytePos(1); } fn format_struct(&self, diff --git a/src/lists.rs b/src/lists.rs index 6f464805e4b..35705611f1e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -208,7 +208,18 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option } else { 0 }; - let item_width = inner_item.len() + item_sep_len; + + // Item string may be multi-line. Its length (used for block comment alignment) + // Should be only the length of the last line. + let item_last_line = if item.is_multiline() { + inner_item.lines().last().unwrap_or("") + } else { + inner_item.as_ref() + }; + let mut item_last_line_width = item_last_line.len() + item_sep_len; + if item_last_line.starts_with(indent_str) { + item_last_line_width -= indent_str.len(); + } match tactic { DefinitiveListTactic::Horizontal if !first => { @@ -284,10 +295,12 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { // 1 = space between item and comment. - let width = formatting.width.checked_sub(item_width + 1).unwrap_or(1); + let width = formatting.width.checked_sub(item_last_line_width + 1).unwrap_or(1); let mut offset = formatting.indent; - offset.alignment += item_width + 1; + offset.alignment += item_last_line_width + 1; let comment = item.post_comment.as_ref().unwrap(); + + debug!("Width = {}, offset = {:?}", width, offset); // Use block-style only for the last item or multiline comments. let block_style = !formatting.ends_with_newline && last || comment.trim().contains('\n') || diff --git a/tests/source/enum.rs b/tests/source/enum.rs new file mode 100644 index 00000000000..30b1ddadf3f --- /dev/null +++ b/tests/source/enum.rs @@ -0,0 +1,94 @@ +// Enums test + +#[atrr] +pub enum Test { + A, B(u32, + A /* comment */, + SomeType), + /// Doc comment + C, +} + +pub enum Foo<'a, Y: Baz> where X: Whatever +{ A, } + +enum EmtpyWithComment { + // Some comment +} + +// C-style enum +enum Bar { + A = 1, + #[someAttr(test)] + B = 2, // comment + C, +} + +enum LongVariants { +First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment +VARIANT), + // This is the second variant + Second +} + +enum StructLikeVariants { + Normal(u32, String, ), + StructLike { x: i32, // Test comment + // Pre-comment + #[Attr50] y: SomeType, // Aanother Comment + }, SL { a: A } +} + +enum X { + CreateWebGLPaintTask(Size2D, GLContextAttributes, IpcSender, usize), String>>), // This is a post comment +} + +pub enum EnumWithAttributes { + //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // Pre Comment + #[rustfmt_skip] + SkippedItem(String,String,), // Post-comment + #[another_attr] + #[attr2] + ItemStruct {x: usize, y: usize}, // Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // And another + ForcedPreflight // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +pub enum SingleTuple { + // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + Match(usize, usize, String) // Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +pub enum SingleStruct { + Match {name: String, loc: usize} // Post-comment +} + +pub enum GenericEnum +where I: Iterator { + // Pre Comment + Left {list: I, root: T}, // Post-comment + Right {list: I, root: T} // Post Comment +} + + +enum EmtpyWithComment { + // Some comment +} + +enum TestFormatFails { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +fn nested_enum_test() { + if true { + enum TestEnum { + One(usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize,), // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA + Two // AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA + } + enum TestNestedFormatFail { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + } +} diff --git a/tests/source/structs.rs b/tests/source/structs.rs index bd9db77fec0..26578bf8c23 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -105,3 +105,13 @@ pub struct State { now: F } struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index aca9ec42af4..72a0266b23c 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -49,5 +49,94 @@ enum StructLikeVariants { enum X { CreateWebGLPaintTask(Size2D, GLContextAttributes, - IpcSender, usize), String>>), + IpcSender, usize), String>>), /* This is + * a post c + * omment */ +} + +pub enum EnumWithAttributes { + // This is a pre comment + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + // Pre Comment + #[rustfmt_skip] + SkippedItem(String,String,), // Post-comment + #[another_attr] + #[attr2] + ItemStruct { + x: usize, + y: usize, + }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAA */ + // And another + ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ +} + +pub enum SingleTuple { + // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + Match(usize, usize, String), /* Post-comment + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * A */ +} + +pub enum SingleStruct { + Match { + name: String, + loc: usize, + }, // Post-comment +} + +pub enum GenericEnum + where I: Iterator +{ + // Pre Comment + Left { + list: I, + root: T, + }, // Post-comment + Right { + list: I, + root: T, + }, // Post Comment +} + + +enum EmtpyWithComment { + // Some comment +} + +enum TestFormatFails { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +fn nested_enum_test() { + if true { + enum TestEnum { + One(usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAA */ + Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAA */ + } + enum TestNestedFormatFail { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + } } diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 67060ddf80e..5ea4a21bad5 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -100,3 +100,16 @@ struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color foo: i32, } + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} -- cgit 1.4.1-3-g733a5 From ccd404ac6f5f8cd9ac1cbb11494b65e336294432 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 8 Oct 2015 23:07:19 +0200 Subject: Try "overflowing" the final function argument when it's a closure This means that we try formatting the last argument of a function call with block indentation instead of visual indentation when it is a closure and its first line fits on the same line as the first arguments. --- src/expr.rs | 109 +++++++++++++++++++++++++++++++++++----------- src/missed_spans.rs | 19 ++++---- tests/source/chains.rs | 14 ++++++ tests/target/chains.rs | 26 ++++++++--- tests/target/hard-tabs.rs | 11 +++-- 5 files changed, 131 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1d0621539e0..325841fbfd1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -10,13 +10,14 @@ use std::cmp::Ordering; use std::borrow::Borrow; +use std::mem::swap; use Indent; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; use string::{StringFormat, rewrite_string}; -use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search}; +use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search, first_line_width}; use visitor::FmtVisitor; use config::{StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; @@ -223,29 +224,27 @@ fn rewrite_pair(lhs: &LHS, { let max_width = try_opt!(width.checked_sub(prefix.len() + infix.len() + suffix.len())); - binary_search(1, - max_width, - |lhs_budget| { - let lhs_offset = offset + prefix.len(); - let lhs_str = match lhs.rewrite(context, lhs_budget, lhs_offset) { - Some(result) => result, - None => return Err(Ordering::Greater), - }; - - let last_line_width = last_line_width(&lhs_str); - let rhs_budget = match max_width.checked_sub(last_line_width) { - Some(b) => b, - None => return Err(Ordering::Less), - }; - let rhs_indent = offset + last_line_width + prefix.len() + infix.len(); - - let rhs_str = match rhs.rewrite(context, rhs_budget, rhs_indent) { - Some(result) => result, - None => return Err(Ordering::Less), - }; - - Ok(format!("{}{}{}{}{}", prefix, lhs_str, infix, rhs_str, suffix)) - }) + binary_search(1, max_width, |lhs_budget| { + let lhs_offset = offset + prefix.len(); + let lhs_str = match lhs.rewrite(context, lhs_budget, lhs_offset) { + Some(result) => result, + None => return Err(Ordering::Greater), + }; + + let last_line_width = last_line_width(&lhs_str); + let rhs_budget = match max_width.checked_sub(last_line_width) { + Some(b) => b, + None => return Err(Ordering::Less), + }; + let rhs_indent = offset + last_line_width + prefix.len() + infix.len(); + + let rhs_str = match rhs.rewrite(context, rhs_budget, rhs_indent) { + Some(result) => result, + None => return Err(Ordering::Less), + }; + + Ok(format!("{}{}{}{}{}", prefix, lhs_str, infix, rhs_str, suffix)) + }) } pub fn rewrite_array<'a, I>(expr_iter: I, @@ -1135,7 +1134,8 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Greater), }; let offset = offset + extra_offset + 1; - let block_indent = if args.len() == 1 { + let arg_count = args.len(); + let block_indent = if arg_count == 1 { context.block_indent } else { offset @@ -1150,8 +1150,65 @@ fn rewrite_call_inner(context: &RewriteContext, |item| item.rewrite(&inner_context, remaining_width, offset), span.lo, span.hi); + let mut item_vec: Vec<_> = items.collect(); + + // Try letting the last argument overflow to the next line with block + // indentation. If its first line fits on one line with the other arguments, + // we format the function arguments horizontally. + let overflow_last = match args.last().map(|x| &x.node) { + Some(&ast::Expr_::ExprClosure(..)) | + Some(&ast::Expr_::ExprBlock(..)) if arg_count > 1 => true, + _ => false, + } && context.config.chains_overflow_last; + + let mut orig_last = None; + let mut placeholder = None; + + // Replace the last item with its first line to see if it fits with + // first arguments. + if overflow_last { + let inner_context = &RewriteContext { block_indent: context.block_indent, ..*context }; + let rewrite = args.last().unwrap().rewrite(&inner_context, remaining_width, offset); + + if let Some(rewrite) = rewrite { + let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); + placeholder = Some(rewrite); + + swap(&mut item_vec[arg_count - 1].item, &mut orig_last); + item_vec[arg_count - 1].item = rewrite_first_line; + } + } + + let tactic = definitive_tactic(&item_vec, + ListTactic::LimitedHorizontalVertical(context.config + .fn_call_width), + remaining_width); + + // Replace the stub with the full overflowing last argument if the rewrite + // succeeded and its first line fits with the other arguments. + match (overflow_last, tactic, placeholder) { + (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { + item_vec[arg_count - 1].item = placeholder; + } + (true, _, _) => { + item_vec[arg_count - 1].item = orig_last; + } + (false, _, _) => {} + } + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + width: width, + ends_with_newline: false, + config: context.config, + }; + + // format_fn_args(items, remaining_width, offset, context.config) - let list_str = match format_fn_args(items, remaining_width, offset, context.config) { + let list_str = match write_list(&item_vec, &fmt) { Some(str) => str, None => return Err(Ordering::Less), }; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 5c5565c6596..f33b7a3014f 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -22,16 +22,15 @@ impl<'a> FmtVisitor<'a> { pub fn format_missing_with_indent(&mut self, end: BytePos) { let config = self.config; - self.format_missing_inner(end, - |this, last_snippet, snippet| { - this.buffer.push_str(last_snippet.trim_right()); - if last_snippet == snippet { - // No new lines in the snippet. - this.buffer.push_str("\n"); - } - let indent = this.block_indent.to_string(config); - this.buffer.push_str(&indent); - }) + self.format_missing_inner(end, |this, last_snippet, snippet| { + this.buffer.push_str(last_snippet.trim_right()); + if last_snippet == snippet { + // No new lines in the snippet. + this.buffer.push_str("\n"); + } + let indent = this.block_indent.to_string(config); + this.buffer.push_str(&indent); + }) } fn format_missing_inner(&mut self, diff --git a/tests/source/chains.rs b/tests/source/chains.rs index f53afaa0c28..2a400b306d2 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -23,6 +23,20 @@ fn main() { 2 }); + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }).method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 590f0a5b156..ea9b6867efe 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -30,12 +30,26 @@ fn main() { } }); - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }) + .method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) .map(|x| x / 2) diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index d8df0c2936a..e3160285c4d 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -76,12 +76,11 @@ fn main() { } }); - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); a.b .c .d(); -- cgit 1.4.1-3-g733a5 From f075fd01abf58d1a8b39a7326f9ed4279ad9c277 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Thu, 8 Oct 2015 22:49:16 -0700 Subject: Fix https://github.com/nrc/rustfmt/issues/430 --- src/lists.rs | 2 +- tests/source/multiple.rs | 5 ++++- tests/target/multiple.rs | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 35705611f1e..0f77ea6a750 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -395,7 +395,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> separator_index + 1) } // Potential *single* line comment. - (_, Some(j)) => j + 1, + (_, Some(j)) if j > separator_index => j + 1, _ => post_snippet.len(), } } diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index a0a3f2599e8..dc1fefb9019 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -108,4 +108,7 @@ fn main() { let rc = RefCell::new(42usize,remaining_width, remaining_width); // a comment let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; } + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; + let s = expand(a + , + b); } diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 0f7ddef007c..2ec281ae04e 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -139,4 +139,5 @@ fn main() { abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd"; + let s = expand(a, b); } -- cgit 1.4.1-3-g733a5 From aed558fce435924e6839f46c4cc0f021fe33f097 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 9 Oct 2015 16:07:14 +1300 Subject: Handle multi-line return types and multi-line tuples Closes #409 --- src/items.rs | 93 ++++++++++++++++++++++++++++++++++-------------- src/lists.rs | 12 +++---- src/types.rs | 34 +++++++++++------- tests/source/multiple.rs | 10 ++++++ tests/target/multiple.rs | 11 ++++++ 5 files changed, 114 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 816bfac0fb3..caf17257578 100644 --- a/src/items.rs +++ b/src/items.rs @@ -149,7 +149,7 @@ impl<'a> FmtVisitor<'a> { false); match rewrite { - Some(new_fn) => { + Some((new_fn, _)) => { self.buffer.push_str(format_visibility(item.vis)); self.buffer.push_str(&new_fn); self.buffer.push_str(";"); @@ -202,21 +202,23 @@ impl<'a> FmtVisitor<'a> { -> Option { let mut newline_brace = self.newline_for_brace(&generics.where_clause); - let mut result = try_opt!(self.rewrite_fn_base(indent, - ident, - fd, - explicit_self, - generics, - unsafety, - constness, - abi, - vis, - span, - newline_brace, - true)); + let (mut result, force_newline_brace) = try_opt!(self.rewrite_fn_base(indent, + ident, + fd, + explicit_self, + generics, + unsafety, + constness, + abi, + vis, + span, + newline_brace, + true)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; + } else if force_newline_brace { + newline_brace = true; } // Prepare for the function body by possibly adding a newline and @@ -243,6 +245,7 @@ impl<'a> FmtVisitor<'a> { // Drop semicolon or it will be interpreted as comment let span = codemap::mk_sp(span.lo, span.hi - BytePos(1)); + // FIXME: silly formatting of the `.0`. let mut result = try_opt!(self.rewrite_fn_base(indent, ident, &sig.decl, @@ -254,7 +257,8 @@ impl<'a> FmtVisitor<'a> { ast::Visibility::Inherited, span, false, - false)); + false)) + .0; // Re-attach semicolon result.push(';'); @@ -262,6 +266,7 @@ impl<'a> FmtVisitor<'a> { Some(result) } + // Return type is (result, force_new_line_for_brace) fn rewrite_fn_base(&mut self, indent: Indent, ident: ast::Ident, @@ -275,7 +280,8 @@ impl<'a> FmtVisitor<'a> { span: Span, newline_brace: bool, has_body: bool) - -> Option { + -> Option<(String, bool)> { + let mut force_new_line_for_brace = false; // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. @@ -311,13 +317,22 @@ impl<'a> FmtVisitor<'a> { result.push_str(&generics_str); let context = self.get_context(); + // Note that if the width and indent really matter, we'll re-layout the + // return type later anyway. let ret_str = fd.output .rewrite(&context, self.config.max_width - indent.width(), indent) .unwrap(); + let multi_line_ret_str = ret_str.contains('\n'); + let ret_str_len = if multi_line_ret_str { + 0 + } else { + ret_str.len() + }; + // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = - self.compute_budgets_for_args(&result, indent, ret_str.len(), newline_brace); + let (mut one_line_budget, multi_line_budget, mut arg_indent) = + self.compute_budgets_for_args(&result, indent, ret_str_len, newline_brace); debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", one_line_budget, @@ -343,6 +358,10 @@ impl<'a> FmtVisitor<'a> { result.push('('); } + if multi_line_ret_str { + one_line_budget = 0; + } + // A conservative estimation, to goal is to be over all parens in generics let args_start = generics.ty_params .last() @@ -371,12 +390,18 @@ impl<'a> FmtVisitor<'a> { // over the max width, then put the return type on a new line. // Unless we are formatting args like a block, in which case there // should always be room for the return type. - if (result.contains("\n") || - result.len() + indent.width() + ret_str.len() > self.config.max_width) && - self.config.fn_args_layout != StructLitStyle::Block { + let ret_indent = if (result.contains("\n") || multi_line_ret_str || + result.len() + indent.width() + ret_str_len > + self.config.max_width) && + self.config.fn_args_layout != StructLitStyle::Block { let indent = match self.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, - // TODO: we might want to check that using the arg indent + // Aligning with non-existent args looks silly. + _ if arg_str.len() == 0 => { + force_new_line_for_brace = true; + indent + 4 + } + // FIXME: we might want to check that using the arg indent // doesn't blow our budget, and if it does, then fallback to // the where clause indent. _ => arg_indent, @@ -384,10 +409,24 @@ impl<'a> FmtVisitor<'a> { result.push('\n'); result.push_str(&indent.to_string(self.config)); + indent } else { result.push(' '); + Indent::new(indent.width(), result.len()) + }; + + if multi_line_ret_str { + // Now that we know the proper indent and width, we need to + // re-layout the return type. + + let budget = try_opt!(self.config.max_width.checked_sub(ret_indent.width())); + let ret_str = fd.output + .rewrite(&context, budget, ret_indent) + .unwrap(); + result.push_str(&ret_str); + } else { + result.push_str(&ret_str); } - result.push_str(&ret_str); // Comment between return type and the end of the decl. let snippet_lo = fd.output.span().hi; @@ -426,7 +465,7 @@ impl<'a> FmtVisitor<'a> { span.hi)); result.push_str(&where_clause_str); - Some(result) + Some((result, force_new_line_for_brace)) } fn rewrite_args(&self, @@ -463,7 +502,7 @@ impl<'a> FmtVisitor<'a> { arg_items.push(ListItem::from_str("")); } - // TODO(#21): if there are no args, there might still be a comment, but + // FIXME(#21): if there are no args, there might still be a comment, but // without spans for the comment or parens, there is no chance of // getting it right. You also don't get to put a comment on self, unless // it is explicit. @@ -559,7 +598,7 @@ impl<'a> FmtVisitor<'a> { (0, max_space - used_space, new_indent) } else { // Whoops! bankrupt. - // TODO: take evasive action, perhaps kill the indent or something. + // FIXME: take evasive action, perhaps kill the indent or something. panic!("in compute_budgets_for_args"); } } @@ -731,7 +770,7 @@ impl<'a> FmtVisitor<'a> { Some(result) } ast::VariantKind::StructVariantKind(ref struct_def) => { - // TODO: Should limit the width, as we have a trailing comma + // FIXME: Should limit the width, as we have a trailing comma self.format_struct("", field.node.name, ast::Visibility::Inherited, @@ -968,7 +1007,7 @@ impl<'a> FmtVisitor<'a> { }; let h_budget = self.config.max_width - generics_offset.width() - 2; - // TODO: might need to insert a newline if the generics are really long. + // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. let context = self.get_context(); diff --git a/src/lists.rs b/src/lists.rs index 0f77ea6a750..c9cc24f18e1 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -78,12 +78,12 @@ pub fn format_item_list(items: I, list_helper(items, width, offset, config, ListTactic::HorizontalVertical) } -fn list_helper(items: I, - width: usize, - offset: Indent, - config: &Config, - tactic: ListTactic) - -> Option +pub fn list_helper(items: I, + width: usize, + offset: Indent, + config: &Config, + tactic: ListTactic) + -> Option where I: Iterator { let item_vec: Vec<_> = items.collect(); diff --git a/src/types.rs b/src/types.rs index 2cbbed92fa5..a706f7ec464 100644 --- a/src/types.rs +++ b/src/types.rs @@ -13,7 +13,7 @@ use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; use Indent; -use lists::{format_item_list, itemize_list, format_fn_args}; +use lists::{format_item_list, itemize_list, format_fn_args, list_helper, ListTactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; @@ -475,19 +475,27 @@ impl Rewrite for ast::Ty { ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) } ast::TyTup(ref tup_ret) => { - let inner = if let [ref item] = &**tup_ret { - try_opt!(item.rewrite(context, width, offset)) + "," + let budget = try_opt!(width.checked_sub(2)); + if tup_ret.is_empty() { + Some("()".to_string()) + } else if let [ref item] = &**tup_ret { + let inner = try_opt!(item.rewrite(context, budget, offset + 1)); + let ret = format!("({},)", inner); + wrap_str(ret, context.config.max_width, budget, offset + 1) } else { - let rewrites: Option>; - rewrites = tup_ret.iter() - .map(|item| item.rewrite(context, width, offset)) - .collect(); - - try_opt!(rewrites).join(", ") - }; - - let ret = format!("({})", inner); - wrap_str(ret, context.config.max_width, width, offset) + let items = itemize_list(context.codemap, + tup_ret.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, budget, offset + 1), + tup_ret[0].span.lo, + self.span.hi); + + + list_helper(items, budget, offset + 1, context.config, ListTactic::Mixed) + .map(|s| format!("({})", s)) + } } _ => wrap_str(pprust::ty_to_string(self), context.config.max_width, diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index dc1fefb9019..4f47aff0544 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -112,3 +112,13 @@ fn main() { let s = expand(a , b); } + +fn deconstruct() -> (SocketAddr, Method, Headers, + RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} + +fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, + RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 2ec281ae04e..d7f7a79f580 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -141,3 +141,14 @@ fn main() { abcd abcd"; let s = expand(a, b); } + +fn deconstruct() + -> (SocketAddr, Method, Headers, RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) +{ +} + +fn deconstruct(foo: Bar) + -> (SocketAddr, Method, Headers, RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} -- cgit 1.4.1-3-g733a5 From a5081c98324bf6eb5f4712afbf1db04f19a19f3d Mon Sep 17 00:00:00 2001 From: Will Speak Date: Sat, 10 Oct 2015 19:02:25 +0100 Subject: Fix Build to Compile with 1.5.0-nightly (87cd2c082) There was an extra, unused, paramter int he match arm which causes an error when compiling with the latest nightly. --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 325841fbfd1..7cc3e7fadf1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -113,7 +113,7 @@ impl Rewrite for ast::Expr { offset, true) } - ast::Expr_::ExprMatch(ref cond, ref arms, _) => { + ast::Expr_::ExprMatch(ref cond, ref arms) => { rewrite_match(context, cond, arms, width, offset, self.span) } ast::Expr_::ExprPath(ref qself, ref path) => { -- cgit 1.4.1-3-g733a5 From b768d27f039e186d863c0fce332d87b9e63167e3 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 10 Oct 2015 22:53:20 +0200 Subject: Format variadic arguments --- src/items.rs | 52 +++++++++++++++++++++++++++++++++++++++++--------- tests/source/extern.rs | 7 +++++++ tests/target/extern.rs | 9 +++++++++ 3 files changed, 59 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index caf17257578..35d34bbb558 100644 --- a/src/items.rs +++ b/src/items.rs @@ -377,7 +377,8 @@ impl<'a> FmtVisitor<'a> { multi_line_budget, indent, arg_indent, - args_span)); + args_span, + fd.variadic)); result.push_str(&arg_str); if self.config.fn_args_layout == StructLitStyle::Block { result.push('\n'); @@ -475,7 +476,8 @@ impl<'a> FmtVisitor<'a> { multi_line_budget: usize, indent: Indent, arg_indent: Indent, - span: Span) + span: Span, + variadic: bool) -> Option { let context = self.get_context(); let mut arg_item_strs = try_opt!(args.iter() @@ -506,27 +508,59 @@ impl<'a> FmtVisitor<'a> { // without spans for the comment or parens, there is no chance of // getting it right. You also don't get to put a comment on self, unless // it is explicit. - if args.len() >= min_args { + if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { span_after(span, ",", self.codemap) } else { span.lo }; + enum ArgumentKind<'a> { + Regular(&'a ast::Arg), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_span = codemap::mk_sp(args.last().unwrap().ty.span.hi, span.hi); + let variadic_start = span_after(variadic_span, "...", self.codemap) - BytePos(1); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + let more_items = itemize_list(self.codemap, - args[min_args - 1..].iter(), + args[min_args - 1..] + .iter() + .map(ArgumentKind::Regular) + .chain(variadic_arg), ")", - |arg| span_lo_for_arg(arg), - |arg| arg.ty.span.hi, - |_| None, + |arg| { + match *arg { + ArgumentKind::Regular(arg) => + span_lo_for_arg(arg), + ArgumentKind::Variadic(start) => start, + } + }, + |arg| { + match *arg { + ArgumentKind::Regular(arg) => arg.ty.span.hi, + ArgumentKind::Variadic(start) => + start + BytePos(3), + } + }, + |arg| { + match *arg { + ArgumentKind::Regular(..) => None, + ArgumentKind::Variadic(..) => + Some("...".to_owned()), + } + }, comment_span_start, span.hi); arg_items.extend(more_items); } - assert_eq!(arg_item_strs.len(), arg_items.len()); - for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { item.item = Some(arg); } diff --git a/tests/source/extern.rs b/tests/source/extern.rs index 2e7b6c14646..7d3d0de6200 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -19,3 +19,10 @@ extern { extern "Rust" { static ext: u32; // Some comment. pub static mut var : SomeType ; } + +extern "C" { + fn syscall(number: libc::c_long /* comment 1 */, /* comm 2 */ ... /* sup? */) -> libc::c_long; + + fn foo (x: *const c_char , ... ) -> +libc::c_long; + } diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 2c6f4936bff..164a6302bb4 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -27,3 +27,12 @@ extern "Rust" { // Some comment. pub static mut var: SomeType; } + +extern { + fn syscall(number: libc::c_long, // comment 1 + // comm 2 + ... /* sup? */) + -> libc::c_long; + + fn foo(x: *const c_char, ...) -> libc::c_long; +} -- cgit 1.4.1-3-g733a5 From e6af5d2c835ea1a4d84517218336fa718f297107 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 12 Oct 2015 21:14:12 +0200 Subject: Use visual block indentation for array literals --- src/expr.rs | 6 ++++-- tests/source/expr.rs | 19 +++++++++++++++++++ tests/target/expr.rs | 24 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7cc3e7fadf1..4a2b318c6ad 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -256,6 +256,8 @@ pub fn rewrite_array<'a, I>(expr_iter: I, where I: Iterator { // 2 for brackets; + let offset = offset + 1; + let inner_context = &RewriteContext { block_indent: offset, ..*context }; let max_item_width = try_opt!(width.checked_sub(2)); let items = itemize_list(context.codemap, expr_iter, @@ -263,7 +265,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.span.lo, |item| item.span.hi, // 1 = [ - |item| item.rewrite(context, max_item_width, offset + 1), + |item| item.rewrite(&inner_context, max_item_width, offset), span_after(span, "[", context.codemap), span.hi) .collect::>(); @@ -283,7 +285,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: offset + 1, + indent: offset, width: max_item_width, ends_with_newline: false, config: context.config, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 45f688693f6..c8bd6e5c859 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -169,6 +169,25 @@ fn arrays() { let y = [/* comment */ 1, 2 /* post comment */, 3]; + let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; + + let a =WeightedChoice::new(&mut [Weighted { + weight: x, + item: 0, + }, + Weighted { + weight: 1, + item: 1, + }, + Weighted { + weight: x, + item: 2, + }, + Weighted { + weight: 1, + item: 3, + }]); + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 6fe472c114e..991663effaa 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -176,6 +176,30 @@ fn arrays() { 2, // post comment 3]; + let xy = [strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + // comment + 1]; + + let a = WeightedChoice::new(&mut [Weighted { + weight: x, + item: 0, + }, + Weighted { + weight: 1, + item: 1, + }, + Weighted { + weight: x, + item: 2, + }, + Weighted { + weight: 1, + item: 3, + }]); + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, -- cgit 1.4.1-3-g733a5 From 7f1fbea8e9df0ff5f3ef77f797daf71fb9115527 Mon Sep 17 00:00:00 2001 From: Gaurav Saxena Date: Tue, 13 Oct 2015 02:22:35 -0400 Subject: added semicolons for return statements --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4a2b318c6ad..6be572f847b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -812,7 +812,7 @@ fn rewrite_match(context: &RewriteContext, fn arm_start_pos(arm: &ast::Arm) -> BytePos { let &ast::Arm { ref attrs, ref pats, .. } = arm; if !attrs.is_empty() { - return attrs[0].span.lo + return attrs[0].span.lo; } pats[0].span.lo -- cgit 1.4.1-3-g733a5 From dba08bf898c79a90527a2c7c00b66cc5e80f675a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 14 Oct 2015 19:41:29 +0200 Subject: Indent uncontinued chains to block level --- src/chains.rs | 6 +++--- tests/source/hard-tabs.rs | 2 ++ tests/target/hard-tabs.rs | 5 +++++ 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 6ad6123408a..6122aa14614 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -45,13 +45,13 @@ pub fn rewrite_chain(mut expr: &ast::Expr, let parent_rewrite = try_opt!(expr.rewrite(context, width, offset)); let (extra_indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || parent_rewrite.len() <= context.config.tab_spaces { - (parent_rewrite.len(), true) + (Indent::new(0, parent_rewrite.len()), true) } else { - (context.config.tab_spaces, false) + (Indent::new(context.config.tab_spaces, 0), false) }; let indent = offset + extra_indent; - let max_width = try_opt!(width.checked_sub(extra_indent)); + let max_width = try_opt!(width.checked_sub(extra_indent.width())); let mut rewrites = try_opt!(subexpr_list.iter() .rev() .map(|e| { diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs index 3fe38a5e42a..d9a46800246 100644 --- a/tests/source/hard-tabs.rs +++ b/tests/source/hard-tabs.rs @@ -31,6 +31,8 @@ unsafe // So this is a very long comment. { } +let chain = funktion_kall().go_to_next_line_with_tab().go_to_next_line_with_tab().go_to_next_line_with_tab(); + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; fn generic(arg: T) -> &SomeType diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index e3160285c4d..c101f0bbf3c 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -50,6 +50,11 @@ fn main() { * Will it still format correctly? */ { } + let chain = funktion_kall() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab(); + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, -- cgit 1.4.1-3-g733a5 From b039e3a8c31a1357c13034c7d1fc00cd2686fc37 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 14 Oct 2015 22:28:17 +0200 Subject: Force semicolons after break/continue/return. Remove after blocks. --- src/expr.rs | 2 +- src/visitor.rs | 45 ++++++++++++++++++++++++++++++++++++++------- tests/source/expr.rs | 8 +++++++- tests/target/expr.rs | 8 +++++++- tests/target/match.rs | 2 +- 5 files changed, 54 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6be572f847b..7d2ce3ea3af 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1322,7 +1322,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, if prelim_tactic == ListTactic::HorizontalVertical && fields.len() > 1 { prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); - }; + } definitive_tactic(&item_vec, prelim_tactic, h_budget) }; diff --git a/src/visitor.rs b/src/visitor.rs index 4827f68dafa..5f287ab5ee9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -59,13 +59,11 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { self.format_missing_with_indent(stmt.span.lo); - let suffix = if let ast::Stmt_::StmtExpr(..) = stmt.node { - "" - } else { + let suffix = if semicolon_for_stmt(stmt) { ";" + } else { + "" }; - - // 1 = trailing semicolon; let rewrite = ex.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width() - suffix.len(), @@ -110,6 +108,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { Some(ref e) => { self.format_missing_with_indent(e.span.lo); self.visit_expr(e); + + if semicolon_for_expr(e) { + self.buffer.push_str(";"); + } } None => {} } @@ -215,7 +217,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemMac(..) => { self.format_missing_with_indent(item.span.lo); - // TODO: we cannot format these yet, because of a bad span. + // FIXME: we cannot format these yet, because of a bad span. // See rust lang issue #28424. // visit::walk_item(self, item); } @@ -245,7 +247,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = ti.span.hi; } } - // TODO: format trait types. + // TODO(#78): format trait types. visit::walk_trait_item(self, ti) } @@ -399,6 +401,35 @@ impl<'a> FmtVisitor<'a> { } } +fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::Stmt_::StmtSemi(ref expr, _) => { + match expr.node { + ast::Expr_::ExprWhile(..) | + ast::Expr_::ExprWhileLet(..) | + ast::Expr_::ExprIf(..) | + ast::Expr_::ExprIfLet(..) | + ast::Expr_::ExprBlock(..) | + ast::Expr_::ExprLoop(..) | + ast::Expr_::ExprForLoop(..) | + ast::Expr_::ExprMatch(..) => false, + _ => true, + } + } + ast::Stmt_::StmtExpr(..) => false, + _ => true, + } +} + +fn semicolon_for_expr(expr: &ast::Expr) -> bool { + match expr.node { + ast::Expr_::ExprRet(..) | + ast::Expr_::ExprAgain(..) | + ast::Expr_::ExprBreak(..) => true, + _ => false, + } +} + impl<'a> Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option { let mut result = String::new(); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 689b2b22c32..b5a22479058 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -70,7 +70,7 @@ fn bar() { let bar = 5 ; let nonsense = (10 .. 0)..(0..10); - loop{if true {break;}} + loop{if true {break}} let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, @@ -226,3 +226,9 @@ fn repeats() { let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc; x + y + z ]; let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz ]; } + +fn blocks() { + if 1 + 1 == 2 { + println!("yay arithmetix!"); + }; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 4c12e6642cb..ed842289439 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -40,7 +40,7 @@ fn foo() -> bool { result } else { 4 - }; + } if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { // Nothing @@ -248,3 +248,9 @@ fn repeats() { let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz]; } + +fn blocks() { + if 1 + 1 == 2 { + println!("yay arithmetix!"); + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index e6b0b4099d3..e758cdd6f71 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -215,5 +215,5 @@ fn issue383() { match resolution.last_private { LastImport{..} => false, _ => true, - }; + } } -- cgit 1.4.1-3-g733a5 From 5ca9381d74234df30e5b165d45cf7cbdcad12539 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 15 Oct 2015 20:37:36 +0200 Subject: Adjust for unified enum variants and structs --- src/items.rs | 133 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 66 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 35d34bbb558..18b9118532c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -746,73 +746,74 @@ impl<'a> FmtVisitor<'a> { result.push_str(&indent.to_string(self.config)); } - let variant_body = match field.node.kind { - ast::VariantKind::TupleVariantKind(ref types) => { + let variant_body = match *field.node.data { + ast::VariantData::Tuple(ref types, _) => { let mut result = field.node.name.to_string(); + let items = itemize_list(self.codemap, + types.iter(), + ")", + |arg| arg.node.ty.span.lo, + |arg| arg.node.ty.span.hi, + |arg| { + // FIXME silly width, indent + arg.node + .ty + .rewrite(&self.get_context(), 1000, Indent::empty()) + }, + span_after(field.span, "(", self.codemap), + field.span.hi); + let item_vec = items.collect::>(); - if !types.is_empty() { - let items = itemize_list(self.codemap, - types.iter(), - ")", - |arg| arg.ty.span.lo, - |arg| arg.ty.span.hi, - |arg| { - // FIXME silly width, indent - arg.ty.rewrite(&self.get_context(), - 1000, - Indent::empty()) - }, - span_after(field.span, "(", self.codemap), - field.span.hi); - let item_vec = items.collect::>(); - - result.push('('); - - let indent = indent + field.node.name.to_string().len() + "(".len(); - - let comma_cost = if self.config.enum_trailing_comma { - 1 - } else { - 0 - }; - let budget = self.config.max_width - indent.width() - comma_cost - 1; // 1 = ) - let tactic = definitive_tactic(&item_vec, - ListTactic::HorizontalVertical, - budget); - - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - width: budget, - ends_with_newline: true, - config: self.config, - }; - let list_str = try_opt!(write_list(&item_vec, &fmt)); - - result.push_str(&list_str); - result.push(')'); - } + result.push('('); - if let Some(ref expr) = field.node.disr_expr { - result.push_str(" = "); - let expr_snippet = self.snippet(expr.span); - result.push_str(&expr_snippet); - } + let indent = indent + field.node.name.to_string().len() + "(".len(); + + let comma_cost = if self.config.enum_trailing_comma { + 1 + } else { + 0 + }; + let budget = self.config.max_width - indent.width() - comma_cost - 1; // 1 = ) + let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, budget); + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + width: budget, + ends_with_newline: true, + config: self.config, + }; + let list_str = try_opt!(write_list(&item_vec, &fmt)); + + result.push_str(&list_str); + result.push(')'); Some(result) } - ast::VariantKind::StructVariantKind(ref struct_def) => { + ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma self.format_struct("", field.node.name, ast::Visibility::Inherited, - struct_def, + &*field.node.data, None, field.span, indent) } + ast::VariantData::Unit(..) => { + let tag = if let Some(ref expr) = field.node.disr_expr { + format!("{} = {}", field.node.name, self.snippet(expr.span)) + } else { + field.node.name.to_string() + }; + + wrap_str(tag, + self.config.max_width, + self.config.max_width - indent.width(), + indent) + } }; if let Some(variant_str) = variant_body { @@ -827,7 +828,7 @@ impl<'a> FmtVisitor<'a> { item_name: &str, ident: ast::Ident, vis: ast::Visibility, - struct_def: &ast::StructDef, + struct_def: &ast::VariantData, generics: Option<&ast::Generics>, span: Span, offset: Indent) @@ -837,14 +838,13 @@ impl<'a> FmtVisitor<'a> { let header_str = self.format_header(item_name, ident, vis); result.push_str(&header_str); - if struct_def.fields.is_empty() { - result.push(';'); - return Some(result); - } - - let is_tuple = match struct_def.fields[0].node.kind { - ast::StructFieldKind::NamedField(..) => false, - ast::StructFieldKind::UnnamedField(..) => true, + let (is_tuple, fields) = match *struct_def { + ast::VariantData::Unit(..) => { + result.push(';'); + return Some(result); + } + ast::VariantData::Tuple(ref vec, _) => (true, vec), + ast::VariantData::Struct(ref vec, _) => (false, vec), }; let (opener, terminator) = if is_tuple { @@ -859,15 +859,14 @@ impl<'a> FmtVisitor<'a> { opener, offset, offset + header_str.len(), - codemap::mk_sp(span.lo, - struct_def.fields[0].span.lo))) + codemap::mk_sp(span.lo, fields[0].span.lo))) } None => opener.to_owned(), }; result.push_str(&generics_str); let items = itemize_list(self.codemap, - struct_def.fields.iter(), + fields.iter(), terminator, |field| { // Include attributes and doc comments, if present @@ -886,7 +885,7 @@ impl<'a> FmtVisitor<'a> { let used_budget = offset.width() + header_str.len() + generics_str.len() + 3; // Conservative approximation - let single_line_cost = (span.hi - struct_def.fields[0].span.lo).0; + let single_line_cost = (span.hi - fields[0].span.lo).0; let break_line = !is_tuple || generics_str.contains('\n') || single_line_cost as usize + used_budget > self.config.max_width; @@ -932,7 +931,7 @@ impl<'a> FmtVisitor<'a> { pub fn visit_struct(&mut self, ident: ast::Ident, vis: ast::Visibility, - struct_def: &ast::StructDef, + struct_def: &ast::VariantData, generics: &ast::Generics, span: Span) { let indent = self.block_indent; -- cgit 1.4.1-3-g733a5 From 5cc60dca976aa435f8897eaaeab4dd8bf57a829b Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 16 Oct 2015 18:11:46 +0200 Subject: Remove unsafe push and pop variants --- src/expr.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7d2ce3ea3af..db8e37c27e7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -426,7 +426,6 @@ impl Rewrite for ast::Block { visitor.block_indent = context.block_indent + context.overflow_indent; let prefix = match self.rules { - ast::BlockCheckMode::PushUnsafeBlock(..) | ast::BlockCheckMode::UnsafeBlock(..) => { let snippet = context.snippet(self.span); let open_pos = try_opt!(snippet.find_uncommented("{")); @@ -463,7 +462,6 @@ impl Rewrite for ast::Block { prefix } - ast::BlockCheckMode::PopUnsafeBlock(..) | ast::BlockCheckMode::DefaultBlock => { visitor.last_pos = self.span.lo; -- cgit 1.4.1-3-g733a5 From a9bd695723d22222b994ed6f2867cf587e79923f Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 16 Oct 2015 22:54:32 +0200 Subject: Format vec! macro using brackets --- src/expr.rs | 4 ++-- src/lists.rs | 3 ++- src/macros.rs | 29 ++++++++++++++++++++++++++--- tests/target/expr.rs | 4 ++-- tests/target/match.rs | 22 +++++++++++----------- 5 files changed, 43 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index db8e37c27e7..0b64ecf35ff 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -35,7 +35,7 @@ impl Rewrite for ast::Expr { match self.node { ast::Expr_::ExprVec(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), - self.span, + mk_sp(span_after(self.span, "[", context.codemap), self.span.hi), context, width, offset) @@ -266,7 +266,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.span.hi, // 1 = [ |item| item.rewrite(&inner_context, max_item_width, offset), - span_after(span, "[", context.codemap), + span.lo, span.hi) .collect::>(); diff --git a/src/lists.rs b/src/lists.rs index c9cc24f18e1..8182189178a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -232,7 +232,8 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option DefinitiveListTactic::Mixed => { let total_width = total_item_width(item) + item_sep_len; - if line_len > 0 && line_len + total_width > formatting.width { + // 1 is space between separator and item. + if line_len > 0 && line_len + 1 + total_width > formatting.width { result.push('\n'); result.push_str(indent_str); line_len = 0; diff --git a/src/macros.rs b/src/macros.rs index 58b2c5db25f..9035b0c7d8b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -24,12 +24,15 @@ use std::thread; use syntax::ast; use syntax::parse::token::{Eof, Comma, Token}; use syntax::parse::{ParseSess, tts_to_parser}; +use syntax::codemap::{mk_sp, BytePos}; use Indent; use rewrite::RewriteContext; use expr::{rewrite_call, rewrite_array}; use comment::FindUncommented; -use utils::wrap_str; +use utils::{wrap_str, span_after}; + +static FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; // We need to pass `TokenTree`s to our expression parsing thread, but they are // not `Send`. We wrap them in a `Send` container to force our will. @@ -38,19 +41,35 @@ struct ForceSend(pub T); unsafe impl Send for ForceSend {} // FIXME: use the enum from libsyntax? +#[derive(Clone, Copy)] enum MacroStyle { Parens, Brackets, Braces, } +impl MacroStyle { + fn opener(&self) -> &'static str { + match *self { + MacroStyle::Parens => "(", + MacroStyle::Brackets => "[", + MacroStyle::Braces => "{", + } + } +} + pub fn rewrite_macro(mac: &ast::Mac, context: &RewriteContext, width: usize, offset: Indent) -> Option { - let style = macro_style(mac, context); + let original_style = macro_style(mac, context); let macro_name = format!("{}!", mac.node.path); + let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + MacroStyle::Brackets + } else { + original_style + }; if let MacroStyle::Braces = style { return None; @@ -100,10 +119,14 @@ pub fn rewrite_macro(mac: &ast::Mac, // Format macro invocation as array literal. let extra_offset = macro_name.len(); let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mac.span, + mk_sp(span_after(mac.span, + original_style.opener(), + context.codemap), + mac.span.hi - BytePos(1)), context, try_opt!(width.checked_sub(extra_offset)), offset + extra_offset)); + Some(format!("{}{}", macro_name, rewrite)) } MacroStyle::Braces => { diff --git a/tests/target/expr.rs b/tests/target/expr.rs index ed842289439..555d8f37e01 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -168,8 +168,8 @@ fn issue184(source: &str) { } fn arrays() { - let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 0]; + let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0]; let y = [// comment 1, diff --git a/tests/target/match.rs b/tests/target/match.rs index e758cdd6f71..fe833dffb62 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -66,16 +66,16 @@ fn main() { fn main() { match r { Variableeeeeeeeeeeeeeeeee => ("variable", - vec!("id", "name", "qualname", "value", "type", "scopeid"), + vec!["id", "name", "qualname", "value", "type", "scopeid"], true, true), Enummmmmmmmmmmmmmmmmmmmm => ("enum", - vec!("id", "qualname", "scopeid", "value"), + vec!["id", "qualname", "scopeid", "value"], true, true), Variantttttttttttttttttttttttt => ("variant", - vec!("id", "name", "qualname", "type", "value", "scopeid"), + vec!["id", "name", "qualname", "type", "value", "scopeid"], true, true), } @@ -142,24 +142,24 @@ fn issue339() { fn issue355() { match mac { a => println!("a", b), - b => vec!(1, 2), + b => vec![1, 2], c => vec!(3; 4), d => { println!("a", b) } e => { - vec!(1, 2) + vec![1, 2] } f => { vec!(3; 4) } h => println!("a", b), // h comment - i => vec!(1, 2), // i comment + i => vec![1, 2], // i comment j => vec!(3; 4), // j comment // k comment k => println!("a", b), // l comment - l => vec!(1, 2), + l => vec![1, 2], // m comment m => vec!(3; 4), // Rewrite splits macro @@ -167,7 +167,7 @@ fn issue355() { println!("a", b), // Rewrite splits macro oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => - vec!(1, 2), + vec![1, 2], // Macro support fails to recognise this macro as splitable // We push the whole expr to a new line, TODO split this macro as well pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => @@ -176,19 +176,19 @@ fn issue355() { qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => - vec!(1, 2), + vec![1, 2], ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), // Funky bracketing styles t => println!{"a", b}, - u => vec!{1, 2}, + u => vec![1, 2], v => vec!{3; 4}, w => println!["a", b], x => vec![1, 2], y => vec![3; 4], // Brackets with comments tc => println!{"a", b}, // comment - uc => vec!{1, 2}, // comment + uc => vec![1, 2], // comment vc => vec!{3; 4}, // comment wc => println!["a", b], // comment xc => vec![1, 2], // comment -- cgit 1.4.1-3-g733a5 From 5407202fdf357e4acfe0d06c0ade9662d0eaad5f Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 16 Oct 2015 22:05:44 +0200 Subject: Properly indent pub fns in extern blocks --- src/expr.rs | 2 +- src/items.rs | 3 +-- tests/source/extern.rs | 8 ++++++++ tests/source/mod-1.rs | 9 +++++++++ tests/target/extern.rs | 9 +++++++++ tests/target/mod-1.rs | 10 ++++++++++ 6 files changed, 38 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index db8e37c27e7..0e2648fbe21 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -273,7 +273,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, let has_long_item = try_opt!(items.iter() .map(|li| li.item.as_ref().map(|s| s.len() > 10)) .fold(Some(false), - |acc, x| acc.and_then(|y| x.map(|x| (x || y))))); + |acc, x| acc.and_then(|y| x.map(|x| x || y)))); let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width) diff --git a/src/items.rs b/src/items.rs index 18b9118532c..49da3e5886f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -143,14 +143,13 @@ impl<'a> FmtVisitor<'a> { // These are not actually rust functions, // but we format them as such. abi::Abi::Rust, - ast::Visibility::Inherited, + item.vis, span, false, false); match rewrite { Some((new_fn, _)) => { - self.buffer.push_str(format_visibility(item.vis)); self.buffer.push_str(&new_fn); self.buffer.push_str(";"); } diff --git a/tests/source/extern.rs b/tests/source/extern.rs index 7d3d0de6200..e33b646b726 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -26,3 +26,11 @@ extern "C" { fn foo (x: *const c_char , ... ) -> libc::c_long; } + + extern { + pub fn freopen(filename: *const c_char, mode: *const c_char + , mode2: *const c_char + , mode3: *const c_char, + file: *mut FILE) + -> *mut FILE; + } diff --git a/tests/source/mod-1.rs b/tests/source/mod-1.rs index 2efb8f538e5..5eb73cb5d4c 100644 --- a/tests/source/mod-1.rs +++ b/tests/source/mod-1.rs @@ -15,3 +15,12 @@ mod foo { } mod boxed { pub use std::boxed::{Box, HEAP}; } + +mod x { + pub fn freopen(filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE) + -> *mut FILE{} +} diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 164a6302bb4..35475660bae 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -36,3 +36,12 @@ extern { fn foo(x: *const c_char, ...) -> libc::c_long; } + +extern { + pub fn freopen(filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE) + -> *mut FILE; +} diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs index 8916c972ad1..02ce208ed4e 100644 --- a/tests/target/mod-1.rs +++ b/tests/target/mod-1.rs @@ -24,3 +24,13 @@ mod foo { mod boxed { pub use std::boxed::{Box, HEAP}; } + +mod x { + pub fn freopen(filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE) + -> *mut FILE { + } +} -- cgit 1.4.1-3-g733a5 From 01937061a905d52d4893e31d64c5f8a7d2e5a044 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 17 Oct 2015 14:19:55 +0200 Subject: Format more type variants --- src/expr.rs | 42 +++++++++--------- src/items.rs | 2 +- src/types.rs | 120 +++++++++++++++++++++++++++++++++------------------ src/utils.rs | 3 +- tests/source/type.rs | 5 +++ tests/target/type.rs | 5 +++ 6 files changed, 111 insertions(+), 66 deletions(-) create mode 100644 tests/source/type.rs create mode 100644 tests/target/type.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index db8e37c27e7..bd03ee6838e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -161,10 +161,10 @@ impl Rewrite for ast::Expr { wrap_str("return".to_owned(), context.config.max_width, width, offset) } ast::Expr_::ExprRet(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", expr, width, offset) + rewrite_unary_prefix(context, "return ", &**expr, width, offset) } ast::Expr_::ExprBox(ref expr) => { - rewrite_unary_prefix(context, "box ", expr, width, offset) + rewrite_unary_prefix(context, "box ", &**expr, width, offset) } ast::Expr_::ExprAddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, expr, width, offset) @@ -210,15 +210,15 @@ impl Rewrite for ast::Expr { } } -fn rewrite_pair(lhs: &LHS, - rhs: &RHS, - prefix: &str, - infix: &str, - suffix: &str, - context: &RewriteContext, - width: usize, - offset: Indent) - -> Option +pub fn rewrite_pair(lhs: &LHS, + rhs: &RHS, + prefix: &str, + infix: &str, + suffix: &str, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option where LHS: Rewrite, RHS: Rewrite { @@ -1470,16 +1470,16 @@ fn rewrite_binary_op(context: &RewriteContext, rhs_result)) } -fn rewrite_unary_prefix(context: &RewriteContext, - prefix: &str, - expr: &ast::Expr, - width: usize, - offset: Indent) - -> Option { - expr.rewrite(context, - try_opt!(width.checked_sub(prefix.len())), - offset + prefix.len()) - .map(|r| format!("{}{}", prefix, r)) +pub fn rewrite_unary_prefix(context: &RewriteContext, + prefix: &str, + rewrite: &R, + width: usize, + offset: Indent) + -> Option { + rewrite.rewrite(context, + try_opt!(width.checked_sub(prefix.len())), + offset + prefix.len()) + .map(|r| format!("{}{}", prefix, r)) } fn rewrite_unary_op(context: &RewriteContext, diff --git a/src/items.rs b/src/items.rs index 18b9118532c..c49b507a37e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -522,7 +522,7 @@ impl<'a> FmtVisitor<'a> { let variadic_arg = if variadic { let variadic_span = codemap::mk_sp(args.last().unwrap().ty.span.hi, span.hi); - let variadic_start = span_after(variadic_span, "...", self.codemap) - BytePos(1); + let variadic_start = span_after(variadic_span, "...", self.codemap) - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { None diff --git a/src/types.rs b/src/types.rs index a706f7ec464..14c0c2669a9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast; +use syntax::ast::{self, Mutability}; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; @@ -16,6 +16,7 @@ use Indent; use lists::{format_item_list, itemize_list, format_fn_args, list_helper, ListTactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; +use expr::{rewrite_unary_prefix, rewrite_pair}; impl Rewrite for ast::Path { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { @@ -129,21 +130,25 @@ impl<'a> SegmentParam<'a> { } impl<'a> Rewrite for SegmentParam<'a> { - // FIXME: doesn't always use width, offset. fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - Some(match *self { + match *self { SegmentParam::LifeTime(ref lt) => { - pprust::lifetime_to_string(lt) + wrap_str(pprust::lifetime_to_string(lt), + context.config.max_width, + width, + offset) } SegmentParam::Type(ref ty) => { - try_opt!(ty.rewrite(context, width, offset)) + ty.rewrite(context, width, offset) } SegmentParam::Binding(ref binding) => { - format!("{} = {}", - binding.ident, - try_opt!(binding.ty.rewrite(context, width, offset))) + let mut result = format!("{} = ", binding.ident); + let budget = try_opt!(width.checked_sub(result.len())); + let rewrite = try_opt!(binding.ty.rewrite(context, budget, offset + result.len())); + result.push_str(&rewrite); + Some(result) } - }) + } } } @@ -163,9 +168,7 @@ fn get_path_separator(codemap: &CodeMap, for c in snippet.chars().rev() { if c == ':' { return "::"; - } else if c.is_whitespace() || c == '<' { - continue; - } else { + } else if !c.is_whitespace() && c != '<' { return ""; } } @@ -271,8 +274,7 @@ fn rewrite_segment(segment: &ast::PathSegment, impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { // TODO: dead spans? - // TODO: don't assume we'll always fit on one line... - Some(match *self { + let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ref bound_lifetimes, ref bounded_ty, ref bounds, @@ -335,23 +337,27 @@ impl Rewrite for ast::WherePredicate { let path_str = try_opt!(path.rewrite(context, budget, offset + used_width)); format!("{} = {}", path_str, ty_str) } - }) + }; + + wrap_str(result, context.config.max_width, width, offset) } } impl Rewrite for ast::LifetimeDef { - fn rewrite(&self, _: &RewriteContext, _: usize, _: Indent) -> Option { - if self.bounds.is_empty() { - Some(pprust::lifetime_to_string(&self.lifetime)) + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + let result = if self.bounds.is_empty() { + pprust::lifetime_to_string(&self.lifetime) } else { - Some(format!("{}: {}", - pprust::lifetime_to_string(&self.lifetime), - self.bounds - .iter() - .map(pprust::lifetime_to_string) - .collect::>() - .join(" + "))) - } + format!("{}: {}", + pprust::lifetime_to_string(&self.lifetime), + self.bounds + .iter() + .map(pprust::lifetime_to_string) + .collect::>() + .join(" + ")) + }; + + wrap_str(result, context.config.max_width, width, offset) } } @@ -366,7 +372,10 @@ impl Rewrite for ast::TyParamBound { Some(format!("?{}", try_opt!(tref.rewrite(context, budget, offset + 1)))) } ast::TyParamBound::RegionTyParamBound(ref l) => { - Some(pprust::lifetime_to_string(l)) + wrap_str(pprust::lifetime_to_string(l), + context.config.max_width, + width, + offset) } } } @@ -377,11 +386,10 @@ impl Rewrite for ast::TyParamBounds { let strs: Vec<_> = try_opt!(self.iter() .map(|b| b.rewrite(context, width, offset)) .collect()); - Some(strs.join(" + ")) + wrap_str(strs.join(" + "), context.config.max_width, width, offset) } } -// FIXME: this assumes everything will fit on one line impl Rewrite for ast::TyParam { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let mut result = String::with_capacity(128); @@ -404,11 +412,10 @@ impl Rewrite for ast::TyParam { result.push_str(&rewrite); } - Some(result) + wrap_str(result, context.config.max_width, width, offset) } } -// FIXME: this assumes everything will fit on one line impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if !self.bound_lifetimes.is_empty() { @@ -432,12 +439,8 @@ impl Rewrite for ast::PolyTraitRef { } impl Rewrite for ast::Ty { - // FIXME doesn't always use width, offset fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { - ast::TyPath(None, ref p) => { - p.rewrite(context, width, offset) - } ast::TyObjectSum(ref ty, ref bounds) => { let ty_str = try_opt!(ty.rewrite(context, width, offset)); let overhead = ty_str.len() + 3; @@ -447,6 +450,14 @@ impl Rewrite for ast::Ty { try_opt!(width.checked_sub(overhead)), offset + overhead)))) } + ast::TyPtr(ref mt) => { + let prefix = match mt.mutbl { + Mutability::MutMutable => "*mut ", + Mutability::MutImmutable => "*const ", + }; + + rewrite_unary_prefix(context, prefix, &*mt.ty, width, offset) + } ast::TyRptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); @@ -470,37 +481,60 @@ impl Rewrite for ast::Ty { } }) } + // FIXME: we drop any comments here, even though it's a silly place to put + // comments. ast::TyParen(ref ty) => { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) } - ast::TyTup(ref tup_ret) => { + ast::TyVec(ref ty) => { let budget = try_opt!(width.checked_sub(2)); + ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str)) + } + ast::TyTup(ref tup_ret) => { if tup_ret.is_empty() { - Some("()".to_string()) + Some("()".to_owned()) } else if let [ref item] = &**tup_ret { + let budget = try_opt!(width.checked_sub(3)); let inner = try_opt!(item.rewrite(context, budget, offset + 1)); let ret = format!("({},)", inner); wrap_str(ret, context.config.max_width, budget, offset + 1) } else { + let budget = try_opt!(width.checked_sub(2)); let items = itemize_list(context.codemap, tup_ret.iter(), ")", |item| item.span.lo, |item| item.span.hi, |item| item.rewrite(context, budget, offset + 1), - tup_ret[0].span.lo, + span_after(self.span, "(", context.codemap), self.span.hi); - list_helper(items, budget, offset + 1, context.config, ListTactic::Mixed) .map(|s| format!("({})", s)) } } - _ => wrap_str(pprust::ty_to_string(self), - context.config.max_width, - width, - offset), + ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), + ast::TyPath(ref q_self, ref path) => { + rewrite_path(context, q_self.as_ref(), path, width, offset) + } + ast::TyFixedLengthVec(ref ty, ref repeats) => { + rewrite_pair(&**ty, &**repeats, "[", "; ", "]", context, width, offset) + } + ast::TyInfer => { + if width >= 1 { + Some("_".to_owned()) + } else { + None + } + } + ast::TyBareFn(..) => { + wrap_str(pprust::ty_to_string(self), + context.config.max_width, + width, + offset) + } + ast::TyMac(..) | ast::TyTypeof(..) => unreachable!(), } } } diff --git a/src/utils.rs b/src/utils.rs index b9da5b04c3b..0fd749a5471 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -32,8 +32,9 @@ pub fn extra_offset(text: &str, offset: Indent) -> usize { #[inline] pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { let snippet = codemap.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); - original.lo + BytePos(snippet.find_uncommented(needle).unwrap() as u32 + 1) + original.lo + BytePos(offset as u32) } #[inline] diff --git a/tests/source/type.rs b/tests/source/type.rs new file mode 100644 index 00000000000..6059bc7a246 --- /dev/null +++ b/tests/source/type.rs @@ -0,0 +1,5 @@ +fn types() { + let x: [ Vec < _ > ] = []; + let y: * mut [ SomeType ; konst_funk() ] = expr(); + let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); +} diff --git a/tests/target/type.rs b/tests/target/type.rs new file mode 100644 index 00000000000..afcf86123ae --- /dev/null +++ b/tests/target/type.rs @@ -0,0 +1,5 @@ +fn types() { + let x: [Vec<_>] = []; + let y: *mut [SomeType; konst_funk()] = expr(); + let z: (/* #digits */ usize, /* exp */ i16) = funk(); +} -- cgit 1.4.1-3-g733a5 From 82a6cca010098faf08481a7449ef0d76230ae01a Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Sat, 17 Oct 2015 11:35:47 -0700 Subject: Refactor write_snippet --- src/missed_spans.rs | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index f33b7a3014f..57b63b56790 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -59,43 +59,22 @@ impl<'a> FmtVisitor<'a> { let span = codemap::mk_sp(start, end); let snippet = self.snippet(span); - self.write_snippet(&snippet, true, &process_last_snippet); + self.write_snippet(&snippet, &process_last_snippet); } fn write_snippet(&mut self, snippet: &str, - last_snippet: bool, process_last_snippet: F) { - // Trim whitespace from the right hand side of each line. - // Annoyingly, the library functions for splitting by lines etc. are not - // quite right, so we must do it ourselves. - let mut line_start = 0; - let mut last_wspace = None; - for (i, c) in snippet.char_indices() { - if c == '\n' { - if let Some(lw) = last_wspace { - self.buffer.push_str(&snippet[line_start..lw]); - self.buffer.push_str("\n"); - } else { - self.buffer.push_str(&snippet[line_start..i + 1]); - } - - line_start = i + 1; - last_wspace = None; - } else { - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(i); - } - } else { - last_wspace = None; - } - } - } - if last_snippet { - process_last_snippet(self, &snippet[line_start..], snippet); + let mut lines: Vec<&str> = snippet.lines().collect(); + let last_snippet = if snippet.ends_with("\n") { + "" } else { - self.buffer.push_str(&snippet[line_start..]); + lines.pop().unwrap() + }; + for line in lines.iter() { + self.buffer.push_str(line.trim_right()); + self.buffer.push_str("\n"); } + process_last_snippet(self, &last_snippet, snippet); } } -- cgit 1.4.1-3-g733a5 From 1a7d39041e13c45f5a60570240f3c9c5c0447bb6 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 18 Oct 2015 21:25:30 +0200 Subject: Format constants and static variables --- src/items.rs | 20 ++++++++++++++ src/visitor.rs | 72 +++++++++++++++++++++++++++++++------------------- tests/source/static.rs | 10 +++++++ tests/target/static.rs | 13 +++++++++ 4 files changed, 88 insertions(+), 27 deletions(-) create mode 100644 tests/source/static.rs create mode 100644 tests/target/static.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f2ce2106991..bd05d71eea7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1136,6 +1136,26 @@ impl<'a> FmtVisitor<'a> { } } +pub fn rewrite_static(prefix: &str, + ident: ast::Ident, + ty: &ast::Ty, + mutability: ast::Mutability, + expr: &ast::Expr, + context: &RewriteContext) + -> Option { + let prefix = format!("{} {}{}: ", prefix, format_mutability(mutability), ident); + // 2 = " =".len() + let ty_str = try_opt!(ty.rewrite(context, + context.config.max_width - context.block_indent.width() - + prefix.len() - 2, + context.block_indent)); + let lhs = format!("{}{} =", prefix, ty_str); + + // 1 = ; + let remaining_width = context.config.max_width - context.block_indent.width() - 1; + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") +} + impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { diff --git a/src/visitor.rs b/src/visitor.rs index 5f287ab5ee9..85ff28148c0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -20,6 +20,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; +use items::rewrite_static; pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, @@ -31,22 +32,8 @@ pub struct FmtVisitor<'a> { } impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { - // FIXME: We'd rather not format expressions here, as we have little - // context. How are we still reaching this? - fn visit_expr(&mut self, ex: &'v ast::Expr) { - debug!("visit_expr: {:?} {:?}", - self.codemap.lookup_char_pos(ex.span.lo), - self.codemap.lookup_char_pos(ex.span.hi)); - self.format_missing(ex.span.lo); - - let rewrite = ex.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent); - - if let Some(new_str) = rewrite { - self.buffer.push_str(&new_str); - self.last_pos = ex.span.hi; - } + fn visit_expr(&mut self, _: &'v ast::Expr) { + unreachable!() } fn visit_stmt(&mut self, stmt: &'v ast::Stmt) { @@ -104,16 +91,19 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.visit_stmt(&stmt) } - match b.expr { - Some(ref e) => { - self.format_missing_with_indent(e.span.lo); - self.visit_expr(e); + if let Some(ref e) = b.expr { + self.format_missing_with_indent(e.span.lo); + let rewrite = e.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent) + .unwrap_or_else(|| self.snippet(e.span)); - if semicolon_for_expr(e) { - self.buffer.push_str(";"); - } + self.buffer.push_str(&rewrite); + self.last_pos = e.span.hi; + + if semicolon_for_expr(e) { + self.buffer.push_str(";"); } - None => {} } self.block_indent = self.block_indent.block_unindent(self.config); @@ -131,7 +121,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { b: &'v ast::Block, s: Span, _: ast::NodeId) { - let indent = self.block_indent; let rewrite = match fk { visit::FnKind::ItemFn(ident, ref generics, unsafety, constness, abi, vis) => { @@ -190,6 +179,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { ast::Item_::ItemUse(ref vp) => { self.format_import(item.vis, vp, item.span); } + // TODO(#78): format traits and impl definitions. ast::Item_::ItemImpl(..) | ast::Item_::ItemTrait(..) => { self.block_indent = self.block_indent.block_indent(self.config); @@ -225,7 +215,36 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.format_missing_with_indent(item.span.lo); self.format_foreign_mod(foreign_mod, item.span); } - _ => { + ast::Item_::ItemStatic(ref ty, mutability, ref expr) => { + self.format_missing_with_indent(item.span.lo); + let rewrite = rewrite_static("static", + item.ident, + ty, + mutability, + expr, + &self.get_context()); + if let Some(s) = rewrite { + self.buffer.push_str(&s); + self.last_pos = item.span.hi; + } + } + ast::Item_::ItemConst(ref ty, ref expr) => { + self.format_missing_with_indent(item.span.lo); + let rewrite = rewrite_static("const", + item.ident, + ty, + ast::Mutability::MutImmutable, + expr, + &self.get_context()); + if let Some(s) = rewrite { + self.buffer.push_str(&s); + self.last_pos = item.span.hi; + } + } + // TODO(#486): format type aliases. + ast::Item_::ItemDefaultImpl(..) | + ast::Item_::ItemFn(..) | + ast::Item_::ItemTy(..) => { visit::walk_item(self, item); } } @@ -247,7 +266,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = ti.span.hi; } } - // TODO(#78): format trait types. visit::walk_trait_item(self, ti) } diff --git a/tests/source/static.rs b/tests/source/static.rs new file mode 100644 index 00000000000..00688732fe7 --- /dev/null +++ b/tests/source/static.rs @@ -0,0 +1,10 @@ +pub const FILE_GENERIC_READ: DWORD = + STANDARD_RIGHTS_READ | FILE_READ_DATA | + FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; + +pub static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", + "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", + "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", + "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; + +static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; diff --git a/tests/target/static.rs b/tests/target/static.rs new file mode 100644 index 00000000000..02223f59ca7 --- /dev/null +++ b/tests/target/static.rs @@ -0,0 +1,13 @@ +const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | + FILE_READ_EA | SYNCHRONIZE; + +static boolnames: &'static [&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", + "km", "hs", "in", "db", "da", "mir", "msgr", "os", + "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", + "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", + "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", + "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", + "OTNL", "OTpt", "OTxr"]; + +static mut name: SomeType = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -- cgit 1.4.1-3-g733a5 From 8e2a910021395baaea0a9edb15843b25516b57ea Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 18 Oct 2015 22:21:46 +0200 Subject: Fix indentation for function arguments --- src/items.rs | 4 +++- tests/source/fn-simple.rs | 5 +++++ tests/target/fn-simple.rs | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f2ce2106991..47ce0f8de20 100644 --- a/src/items.rs +++ b/src/items.rs @@ -481,7 +481,9 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let mut arg_item_strs = try_opt!(args.iter() .map(|arg| { - arg.rewrite(&context, multi_line_budget, indent) + arg.rewrite(&context, + multi_line_budget, + arg_indent) }) .collect::>>()); diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 5f41141b689..b9f6a1e64b1 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -24,3 +24,8 @@ pub fn http_fetch_async(listener:Box< AsyncCORSResponseListener+Send >, script_ } fn some_func>(val:T){} + +fn zzzzzzzzzzzzzzzzzzzz + (selff: Type, mut handle: node::Handle>, Type, NodeType>) + -> SearchStack<'a, K, V, Type, NodeType>{ +} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index e8b5635671d..9e635e31a3c 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -37,3 +37,10 @@ pub fn http_fetch_async(listener: Box, fn some_func>(val: T) { } + +fn zzzzzzzzzzzzzzzzzzzz(selff: Type, + mut handle: node::Handle>, + Type, + NodeType>) + -> SearchStack<'a, K, V, Type, NodeType> { +} -- cgit 1.4.1-3-g733a5 From 3ce425c9edf87258b9a498844307a5c23f14b893 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 18 Oct 2015 22:59:39 +0200 Subject: Factor out common item indentation idiom --- src/items.rs | 39 +++++++++------------------------------ src/visitor.rs | 57 +++++++++++++++++++++++++++------------------------------ 2 files changed, 36 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index bd05d71eea7..1010be2f19a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -823,15 +823,15 @@ impl<'a> FmtVisitor<'a> { } } - fn format_struct(&self, - item_name: &str, - ident: ast::Ident, - vis: ast::Visibility, - struct_def: &ast::VariantData, - generics: Option<&ast::Generics>, - span: Span, - offset: Indent) - -> Option { + pub fn format_struct(&self, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + struct_def: &ast::VariantData, + generics: Option<&ast::Generics>, + span: Span, + offset: Indent) + -> Option { let mut result = String::with_capacity(1024); let header_str = self.format_header(item_name, ident, vis); @@ -927,27 +927,6 @@ impl<'a> FmtVisitor<'a> { Some(result) } - pub fn visit_struct(&mut self, - ident: ast::Ident, - vis: ast::Visibility, - struct_def: &ast::VariantData, - generics: &ast::Generics, - span: Span) { - let indent = self.block_indent; - let result = self.format_struct("struct ", - ident, - vis, - struct_def, - Some(generics), - span, - indent); - - if let Some(rewrite) = result { - self.buffer.push_str(&rewrite); - self.last_pos = span.hi; - } - } - fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { format!("{}{}{}", format_visibility(vis), item_name, ident) } diff --git a/src/visitor.rs b/src/visitor.rs index 85ff28148c0..fb3b25eab22 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -45,7 +45,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { - self.format_missing_with_indent(stmt.span.lo); let suffix = if semicolon_for_stmt(stmt) { ";" } else { @@ -54,13 +53,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { let rewrite = ex.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width() - suffix.len(), - self.block_indent); - - if let Some(new_str) = rewrite { - self.buffer.push_str(&new_str); - self.buffer.push_str(suffix); - self.last_pos = stmt.span.hi; - } + self.block_indent) + .map(|s| s + suffix); + self.push_rewrite(stmt.span, rewrite); } ast::Stmt_::StmtMac(ref _mac, _macro_style) => { self.format_missing_with_indent(stmt.span.lo); @@ -179,7 +174,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { ast::Item_::ItemUse(ref vp) => { self.format_import(item.vis, vp, item.span); } - // TODO(#78): format traits and impl definitions. + // FIXME(#78): format traits and impl definitions. ast::Item_::ItemImpl(..) | ast::Item_::ItemTrait(..) => { self.block_indent = self.block_indent.block_indent(self.config); @@ -193,8 +188,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = item.span.hi; } ast::Item_::ItemStruct(ref def, ref generics) => { - self.format_missing_with_indent(item.span.lo); - self.visit_struct(item.ident, item.vis, def, generics, item.span); + let indent = self.block_indent; + let rewrite = self.format_struct("struct ", + item.ident, + item.vis, + def, + Some(generics), + item.span, + indent); + self.push_rewrite(item.span, rewrite); } ast::Item_::ItemEnum(ref def, ref generics) => { self.format_missing_with_indent(item.span.lo); @@ -216,32 +218,24 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.format_foreign_mod(foreign_mod, item.span); } ast::Item_::ItemStatic(ref ty, mutability, ref expr) => { - self.format_missing_with_indent(item.span.lo); let rewrite = rewrite_static("static", item.ident, ty, mutability, expr, &self.get_context()); - if let Some(s) = rewrite { - self.buffer.push_str(&s); - self.last_pos = item.span.hi; - } + self.push_rewrite(item.span, rewrite); } ast::Item_::ItemConst(ref ty, ref expr) => { - self.format_missing_with_indent(item.span.lo); let rewrite = rewrite_static("const", item.ident, ty, ast::Mutability::MutImmutable, expr, &self.get_context()); - if let Some(s) = rewrite { - self.buffer.push_str(&s); - self.last_pos = item.span.hi; - } + self.push_rewrite(item.span, rewrite); } - // TODO(#486): format type aliases. + // FIXME(#486): format type aliases. ast::Item_::ItemDefaultImpl(..) | ast::Item_::ItemFn(..) | ast::Item_::ItemTy(..) => { @@ -256,15 +250,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } if let ast::TraitItem_::MethodTraitItem(ref sig, None) = ti.node { - self.format_missing_with_indent(ti.span.lo); - let indent = self.block_indent; - let new_fn = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); - - if let Some(fn_str) = new_fn { - self.buffer.push_str(&fn_str); - self.last_pos = ti.span.hi; - } + let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); + self.push_rewrite(ti.span, rewrite); } visit::walk_trait_item(self, ti) @@ -290,6 +278,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } impl<'a> FmtVisitor<'a> { + fn push_rewrite(&mut self, span: Span, rewrite: Option) { + self.format_missing_with_indent(span.lo); + + if let Some(res) = rewrite { + self.buffer.push_str(&res); + self.last_pos = span.hi; + } + } + pub fn from_codemap(codemap: &'a CodeMap, config: &'a Config) -> FmtVisitor<'a> { FmtVisitor { codemap: codemap, -- cgit 1.4.1-3-g733a5 From 7e0456b852e33ce669141db1669b8c10a9afd987 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 19 Oct 2015 20:08:03 +0200 Subject: Format visibility for statics and consts --- src/items.rs | 7 ++++++- src/visitor.rs | 2 ++ tests/source/static.rs | 8 ++++++-- tests/target/static.rs | 4 ++++ 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 68715252ce9..92670947e71 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1118,13 +1118,18 @@ impl<'a> FmtVisitor<'a> { } pub fn rewrite_static(prefix: &str, + vis: ast::Visibility, ident: ast::Ident, ty: &ast::Ty, mutability: ast::Mutability, expr: &ast::Expr, context: &RewriteContext) -> Option { - let prefix = format!("{} {}{}: ", prefix, format_mutability(mutability), ident); + let prefix = format!("{}{} {}{}: ", + format_visibility(vis), + prefix, + format_mutability(mutability), + ident); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, context.config.max_width - context.block_indent.width() - diff --git a/src/visitor.rs b/src/visitor.rs index fb3b25eab22..2264aaa94af 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -219,6 +219,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemStatic(ref ty, mutability, ref expr) => { let rewrite = rewrite_static("static", + item.vis, item.ident, ty, mutability, @@ -228,6 +229,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemConst(ref ty, ref expr) => { let rewrite = rewrite_static("const", + item.vis, item.ident, ty, ast::Mutability::MutImmutable, diff --git a/tests/source/static.rs b/tests/source/static.rs index 00688732fe7..6315b489046 100644 --- a/tests/source/static.rs +++ b/tests/source/static.rs @@ -1,10 +1,14 @@ -pub const FILE_GENERIC_READ: DWORD = +const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; -pub static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", +static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + + pub static count : u8 = 10 ; + +pub const test: &Type = &val; diff --git a/tests/target/static.rs b/tests/target/static.rs index 02223f59ca7..ffaeb0890d3 100644 --- a/tests/target/static.rs +++ b/tests/target/static.rs @@ -11,3 +11,7 @@ static boolnames: &'static [&'static str] = &["bw", "am", "xsb", "xhp", "xenl", static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + +pub static count: u8 = 10; + +pub const test: &Type = &val; -- cgit 1.4.1-3-g733a5 From ca023ba9b702ec9d453e917ffac54263ab4ef965 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 17 Oct 2015 15:56:53 +0200 Subject: Format some patterns --- src/expr.rs | 41 ++++++++------------ src/items.rs | 65 +++++++++++++++++--------------- src/lib.rs | 25 ++++++++++++- src/patterns.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++ src/types.rs | 28 ++------------ tests/source/match.rs | 1 + tests/source/pattern.rs | 14 +++++++ tests/source/type.rs | 1 + tests/target/expr.rs | 4 +- tests/target/hard-tabs.rs | 4 +- tests/target/match.rs | 12 +++++- tests/target/multiple.rs | 12 +++++- tests/target/pattern.rs | 16 ++++++++ tests/target/type.rs | 6 ++- 14 files changed, 236 insertions(+), 88 deletions(-) create mode 100644 src/patterns.rs create mode 100644 tests/source/pattern.rs create mode 100644 tests/target/pattern.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2deaed9609a..b69989aa761 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,7 +12,7 @@ use std::cmp::Ordering; use std::borrow::Borrow; use std::mem::swap; -use Indent; +use {Indent, Spanned}; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; @@ -76,7 +76,7 @@ impl Rewrite for ast::Expr { offset) } ast::Expr_::ExprTup(ref items) => { - rewrite_tuple_lit(context, items, self.span, width, offset) + rewrite_tuple(context, items, self.span, width, offset) } ast::Expr_::ExprWhile(ref cond, ref block, label) => { Loop::new_while(None, cond, block, label).rewrite(context, width, offset) @@ -479,13 +479,6 @@ impl Rewrite for ast::Block { } } -// FIXME(#18): implement pattern formatting -impl Rewrite for ast::Pat { - fn rewrite(&self, context: &RewriteContext, _: usize, _: Indent) -> Option { - Some(context.snippet(self.span)) - } -} - // Abstraction over for, while and loop expressions struct Loop<'a> { cond: Option<&'a ast::Expr>, @@ -849,11 +842,7 @@ impl Rewrite for ast::Arm { // 5 = ` => {` let pat_budget = try_opt!(width.checked_sub(5)); let pat_strs = try_opt!(pats.iter() - .map(|p| { - p.rewrite(context, - pat_budget, - offset.block_indent(context.config)) - }) + .map(|p| p.rewrite(context, pat_budget, offset)) .collect::>>()); let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); @@ -1187,7 +1176,9 @@ fn rewrite_call_inner(context: &RewriteContext, // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. match (overflow_last, tactic, placeholder) { - (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { + (true, + DefinitiveListTactic::Horizontal, + placeholder @ Some(..)) => { item_vec[arg_count - 1].item = placeholder; } (true, _, _) => { @@ -1206,8 +1197,6 @@ fn rewrite_call_inner(context: &RewriteContext, config: context.config, }; - // format_fn_args(items, remaining_width, offset, context.config) - let list_str = match write_list(&item_vec, &fmt) { Some(str) => str, None => return Err(Ordering::Less), @@ -1382,12 +1371,14 @@ fn rewrite_field(context: &RewriteContext, expr.map(|s| format!("{}: {}", name, s)) } -fn rewrite_tuple_lit(context: &RewriteContext, - items: &[ptr::P], - span: Span, - width: usize, - offset: Indent) - -> Option { +pub fn rewrite_tuple<'a, R>(context: &RewriteContext, + items: &'a [ptr::P], + span: Span, + width: usize, + offset: Indent) + -> Option + where R: Rewrite + Spanned + 'a +{ debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset); let indent = offset + 1; // In case of length 1, need a trailing comma @@ -1400,8 +1391,8 @@ fn rewrite_tuple_lit(context: &RewriteContext, let items = itemize_list(context.codemap, items.iter(), ")", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span().lo, + |item| item.span().hi, |item| { let inner_width = context.config.max_width - indent.width() - 1; item.rewrite(context, inner_width, indent) diff --git a/src/items.rs b/src/items.rs index 68715252ce9..6d486bbbe51 100644 --- a/src/items.rs +++ b/src/items.rs @@ -29,41 +29,16 @@ impl<'a> FmtVisitor<'a> { pub fn visit_let(&mut self, local: &ast::Local, span: Span) { self.format_missing_with_indent(span.lo); - // String that is placed within the assignment pattern and expression. - let infix = { - let mut infix = String::new(); - - if let Some(ref ty) = local.ty { - // 2 = ": ".len() - let offset = self.block_indent + 2; - let width = self.config.max_width - offset.width(); - let rewrite = ty.rewrite(&self.get_context(), width, offset); - - match rewrite { - Some(result) => { - infix.push_str(": "); - infix.push_str(&result); - } - None => return, - } - } - - if local.init.is_some() { - infix.push_str(" ="); - } - - infix - }; - // New scope so we drop the borrow of self (context) in time to mutably // borrow self to mutate its buffer. let result = { let context = self.get_context(); let mut result = "let ".to_owned(); - let pattern_offset = self.block_indent + result.len() + infix.len(); + let pattern_offset = self.block_indent + result.len(); // 1 = ; - let pattern_width = self.config.max_width.checked_sub(pattern_offset.width() + 1); - let pattern_width = match pattern_width { + let pattern_width = match self.config + .max_width + .checked_sub(pattern_offset.width() + 1) { Some(width) => width, None => return, }; @@ -73,6 +48,36 @@ impl<'a> FmtVisitor<'a> { None => return, } + // String that is placed within the assignment pattern and expression. + let infix = { + let mut infix = String::new(); + + if let Some(ref ty) = local.ty { + // 2 = ": ".len() + // 1 = ; + let offset = self.block_indent + result.len() + 2; + let width = match self.config.max_width.checked_sub(offset.width() + 1) { + Some(w) => w, + None => return, + }; + let rewrite = ty.rewrite(&self.get_context(), width, offset); + + match rewrite { + Some(result) => { + infix.push_str(": "); + infix.push_str(&result); + } + None => return, + } + } + + if local.init.is_some() { + infix.push_str(" ="); + } + + infix + }; + result.push_str(&infix); if let Some(ref ex) = local.init { @@ -86,7 +91,7 @@ impl<'a> FmtVisitor<'a> { let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent); match rhs { - Some(result) => result, + Some(s) => s, None => return, } } else { diff --git a/src/lib.rs b/src/lib.rs index 1dfb05c88b6..03422a20c36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,7 @@ use rustc::session::config::Input; use rustc_driver::{driver, CompilerCalls, Compilation}; use syntax::ast; -use syntax::codemap::CodeMap; +use syntax::codemap::{CodeMap, Span}; use syntax::diagnostics; use std::ops::{Add, Sub}; @@ -76,11 +76,34 @@ mod modules; pub mod rustfmt_diff; mod chains; mod macros; +mod patterns; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; +pub trait Spanned { + fn span(&self) -> Span; +} + +impl Spanned for ast::Expr { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Pat { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Ty { + fn span(&self) -> Span { + self.span + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of diff --git a/src/patterns.rs b/src/patterns.rs new file mode 100644 index 00000000000..2e90f719853 --- /dev/null +++ b/src/patterns.rs @@ -0,0 +1,95 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use Indent; +use rewrite::{Rewrite, RewriteContext}; +use utils::{wrap_str, format_mutability, span_after}; +use lists::{format_item_list, itemize_list}; +use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; +use types::rewrite_path; + +use syntax::ast::{PatWildKind, BindingMode, Pat, Pat_}; + +// FIXME(#18): implement pattern formatting. +impl Rewrite for Pat { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + match self.node { + Pat_::PatBox(ref pat) => { + rewrite_unary_prefix(context, "box ", &**pat, width, offset) + } + Pat_::PatIdent(binding_mode, ident, None) => { + let (prefix, mutability) = match binding_mode { + BindingMode::BindByRef(mutability) => ("ref ", mutability), + BindingMode::BindByValue(mutability) => ("", mutability), + }; + let mut_infix = format_mutability(mutability); + let result = format!("{}{}{}", prefix, mut_infix, ident.node); + wrap_str(result, context.config.max_width, width, offset) + } + Pat_::PatWild(kind) => { + let result = match kind { + PatWildKind::PatWildSingle => "_", + PatWildKind::PatWildMulti => "..", + }; + if result.len() <= width { + Some(result.to_owned()) + } else { + None + } + } + Pat_::PatQPath(ref q_self, ref path) => { + rewrite_path(context, Some(q_self), path, width, offset) + } + Pat_::PatRange(ref lhs, ref rhs) => { + rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset) + } + Pat_::PatRegion(ref pat, mutability) => { + let prefix = format!("&{}", format_mutability(mutability)); + rewrite_unary_prefix(context, &prefix, &**pat, width, offset) + } + Pat_::PatTup(ref items) => { + rewrite_tuple(context, items, self.span, width, offset) + } + Pat_::PatEnum(ref path, Some(ref pat_vec)) => { + let path_str = try_opt!(::types::rewrite_path(context, None, path, width, offset)); + + if pat_vec.is_empty() { + Some(path_str) + } else { + let width = try_opt!(width.checked_sub(path_str.len())); + let offset = offset + path_str.len(); + let items = itemize_list(context.codemap, + pat_vec.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, width, offset), + span_after(self.span, "(", context.codemap), + self.span.hi); + Some(format!("{}({})", + path_str, + try_opt!(format_item_list(items, width, offset, context.config)))) + } + } + Pat_::PatLit(ref expr) => expr.rewrite(context, width, offset), + // FIXME(#8): format remaining pattern variants. + Pat_::PatIdent(_, _, Some(..)) | + Pat_::PatEnum(_, None) | + Pat_::PatStruct(..) | + Pat_::PatVec(..) | + Pat_::PatMac(..) => { + wrap_str(context.snippet(self.span), + context.config.max_width, + width, + offset) + } + } + } +} diff --git a/src/types.rs b/src/types.rs index 14c0c2669a9..d8170e2f917 100644 --- a/src/types.rs +++ b/src/types.rs @@ -13,10 +13,10 @@ use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos, CodeMap}; use Indent; -use lists::{format_item_list, itemize_list, format_fn_args, list_helper, ListTactic}; +use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; -use expr::{rewrite_unary_prefix, rewrite_pair}; +use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; impl Rewrite for ast::Path { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { @@ -491,28 +491,8 @@ impl Rewrite for ast::Ty { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str)) } - ast::TyTup(ref tup_ret) => { - if tup_ret.is_empty() { - Some("()".to_owned()) - } else if let [ref item] = &**tup_ret { - let budget = try_opt!(width.checked_sub(3)); - let inner = try_opt!(item.rewrite(context, budget, offset + 1)); - let ret = format!("({},)", inner); - wrap_str(ret, context.config.max_width, budget, offset + 1) - } else { - let budget = try_opt!(width.checked_sub(2)); - let items = itemize_list(context.codemap, - tup_ret.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, budget, offset + 1), - span_after(self.span, "(", context.codemap), - self.span.hi); - - list_helper(items, budget, offset + 1, context.config, ListTactic::Mixed) - .map(|s| format!("({})", s)) - } + ast::TyTup(ref items) => { + rewrite_tuple(context, items, self.span, width, offset) } ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), ast::TyPath(ref q_self, ref path) => { diff --git a/tests/source/match.rs b/tests/source/match.rs index b1c6449226f..992d0d98bf8 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -88,6 +88,7 @@ fn main() { fn matches() { match 1 { + -1 => 10, 1 => 1, // foo 2 => 2, // bar diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs new file mode 100644 index 00000000000..4192d521085 --- /dev/null +++ b/tests/source/pattern.rs @@ -0,0 +1,14 @@ +fn main() { + let z = match x { + "pat1" => 1, + ( ref x, ref mut y /*comment*/) => 2, + }; + + if let < T as Trait > :: CONST = ident { + do_smth(); + } + + let Some ( ref xyz /* comment! */) = opt; + + if let None = opt2 { panic!("oh noes"); } +} diff --git a/tests/source/type.rs b/tests/source/type.rs index 6059bc7a246..71822bd668d 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -2,4 +2,5 @@ fn types() { let x: [ Vec < _ > ] = []; let y: * mut [ SomeType ; konst_funk() ] = expr(); let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); + let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk(); } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 555d8f37e01..479a279e43b 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -57,8 +57,8 @@ fn foo() -> bool { tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} - if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = - 1 + 2 + 3 { + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { } let test = if true { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index c101f0bbf3c..21155218111 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -28,8 +28,8 @@ fn main() { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAA\ AAAAAAAAAAAAaAa"; - if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = - 1 + 2 + 3 { + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { } if cond() { diff --git a/tests/target/match.rs b/tests/target/match.rs index fe833dffb62..6c498014aa1 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -32,7 +32,16 @@ fn foo() { meh, // Test that earlier patterns can take the guard space - (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | + (aaaa, + bbbbb, + ccccccc, + aaaaa, + bbbbbbbb, + cccccc, + aaaa, + bbbbbbbb, + cccccc, + dddddd) | Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} _ => {} @@ -83,6 +92,7 @@ fn main() { fn matches() { match 1 { + -1 => 10, 1 => 1, // foo 2 => 2, // bar diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index d7f7a79f580..3c17eb77924 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -143,12 +143,20 @@ fn main() { } fn deconstruct() - -> (SocketAddr, Method, Headers, RequestUri, HttpVersion, + -> (SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } fn deconstruct(foo: Bar) - -> (SocketAddr, Method, Headers, RequestUri, HttpVersion, + -> (SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs new file mode 100644 index 00000000000..38ebe675a40 --- /dev/null +++ b/tests/target/pattern.rs @@ -0,0 +1,16 @@ +fn main() { + let z = match x { + "pat1" => 1, + (ref x, ref mut y /* comment */) => 2, + }; + + if let ::CONST = ident { + do_smth(); + } + + let Some(ref xyz /* comment! */) = opt; + + if let None = opt2 { + panic!("oh noes"); + } +} diff --git a/tests/target/type.rs b/tests/target/type.rs index afcf86123ae..a8a5e028aa5 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -1,5 +1,9 @@ fn types() { let x: [Vec<_>] = []; let y: *mut [SomeType; konst_funk()] = expr(); - let z: (/* #digits */ usize, /* exp */ i16) = funk(); + let z: (// #digits + usize, + // exp + i16) = funk(); + let z: (usize /* #digits */, i16 /* exp */) = funk(); } -- cgit 1.4.1-3-g733a5 From 11756d2ef8828e238bd7c9a1514332098a7c643d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 19 Oct 2015 00:25:38 +0200 Subject: Refactor enum formatting --- src/items.rs | 266 ++++++++++++++++++++---------------------------- src/visitor.rs | 8 +- tests/source/enum.rs | 4 + tests/source/structs.rs | 6 ++ tests/target/enum.rs | 4 + tests/target/structs.rs | 16 +-- 6 files changed, 139 insertions(+), 165 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6c1c6da2bbd..78d35427519 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,9 +11,10 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use Indent; -use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, wrap_str}; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic}; +use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, + wrap_str, last_line_width}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, + DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::rewrite_assign_rhs; use comment::FindUncommented; use visitor::FmtVisitor; @@ -21,7 +22,7 @@ use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; use syntax::{ast, abi}; -use syntax::codemap::{self, Span, BytePos}; +use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::print::pprust; use syntax::parse::token; @@ -133,7 +134,7 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(item.span.lo); // Drop semicolon or it will be interpreted as comment. // FIXME: this may be a faulty span from libsyntax. - let span = codemap::mk_sp(item.span.lo, item.span.hi - BytePos(1)); + let span = mk_sp(item.span.lo, item.span.hi - BytePos(1)); match item.node { ast::ForeignItem_::ForeignItemFn(ref fn_decl, ref generics) => { @@ -247,7 +248,7 @@ impl<'a> FmtVisitor<'a> { span: Span) -> Option { // Drop semicolon or it will be interpreted as comment - let span = codemap::mk_sp(span.lo, span.hi - BytePos(1)); + let span = mk_sp(span.lo, span.hi - BytePos(1)); // FIXME: silly formatting of the `.0`. let mut result = try_opt!(self.rewrite_fn_base(indent, @@ -313,7 +314,7 @@ impl<'a> FmtVisitor<'a> { // Generics. let generics_indent = indent + result.len(); - let generics_span = codemap::mk_sp(span.lo, span_for_return(&fd.output).lo); + let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); let generics_str = try_opt!(self.rewrite_generics(generics, indent, generics_indent, @@ -371,10 +372,8 @@ impl<'a> FmtVisitor<'a> { .last() .map(|tp| end_typaram(tp)) .unwrap_or(span.lo); - let args_span = codemap::mk_sp(span_after(codemap::mk_sp(args_start, span.hi), - "(", - self.codemap), - span_for_return(&fd.output).lo); + let args_span = mk_sp(span_after(mk_sp(args_start, span.hi), "(", self.codemap), + span_for_return(&fd.output).lo); let arg_str = try_opt!(self.rewrite_args(&fd.inputs, explicit_self, one_line_budget, @@ -437,7 +436,7 @@ impl<'a> FmtVisitor<'a> { let snippet_lo = fd.output.span().hi; if where_clause.predicates.is_empty() { let snippet_hi = span.hi; - let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); + let snippet = self.snippet(mk_sp(snippet_lo, snippet_hi)); let snippet = snippet.trim(); if !snippet.is_empty() { result.push(' '); @@ -527,7 +526,7 @@ impl<'a> FmtVisitor<'a> { } let variadic_arg = if variadic { - let variadic_span = codemap::mk_sp(args.last().unwrap().ty.span.hi, span.hi); + let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); let variadic_start = span_after(variadic_span, "...", self.codemap) - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { @@ -666,7 +665,7 @@ impl<'a> FmtVisitor<'a> { " {", self.block_indent, self.block_indent.block_indent(self.config), - codemap::mk_sp(span.lo, body_start)) + mk_sp(span.lo, body_start)) .unwrap(); self.buffer.push_str(&generics_str); @@ -737,7 +736,7 @@ impl<'a> FmtVisitor<'a> { fn format_variant(&self, field: &ast::Variant) -> Option { if contains_skip(&field.node.attrs) { let lo = field.node.attrs[0].span.lo; - let span = codemap::mk_sp(lo, field.span.hi); + let span = mk_sp(lo, field.span.hi); return Some(self.snippet(span)); } @@ -753,51 +752,7 @@ impl<'a> FmtVisitor<'a> { } let variant_body = match *field.node.data { - ast::VariantData::Tuple(ref types, _) => { - let mut result = field.node.name.to_string(); - let items = itemize_list(self.codemap, - types.iter(), - ")", - |arg| arg.node.ty.span.lo, - |arg| arg.node.ty.span.hi, - |arg| { - // FIXME silly width, indent - arg.node - .ty - .rewrite(&self.get_context(), 1000, Indent::empty()) - }, - span_after(field.span, "(", self.codemap), - field.span.hi); - let item_vec = items.collect::>(); - - result.push('('); - - let indent = indent + field.node.name.to_string().len() + "(".len(); - - let comma_cost = if self.config.enum_trailing_comma { - 1 - } else { - 0 - }; - let budget = self.config.max_width - indent.width() - comma_cost - 1; // 1 = ) - let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, budget); - - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - width: budget, - ends_with_newline: true, - config: self.config, - }; - let list_str = try_opt!(write_list(&item_vec, &fmt)); - - result.push_str(&list_str); - result.push(')'); - - Some(result) - } + ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma self.format_struct("", @@ -844,19 +799,17 @@ impl<'a> FmtVisitor<'a> { let header_str = self.format_header(item_name, ident, vis); result.push_str(&header_str); - let (is_tuple, fields) = match *struct_def { + let (fields, body_lo, opener, terminator) = match *struct_def { ast::VariantData::Unit(..) => { result.push(';'); return Some(result); } - ast::VariantData::Tuple(ref vec, _) => (true, vec), - ast::VariantData::Struct(ref vec, _) => (false, vec), - }; - - let (opener, terminator) = if is_tuple { - ("(", ")") - } else { - (" {", "}") + ast::VariantData::Tuple(ref vec, _) => { + (vec, vec[0].span.lo, "(", ")") + } + ast::VariantData::Struct(ref vec, _) => { + (vec, span_after(span, "{", self.codemap), " {", "}") + } }; let generics_str = match generics { @@ -865,12 +818,27 @@ impl<'a> FmtVisitor<'a> { opener, offset, offset + header_str.len(), - codemap::mk_sp(span.lo, fields[0].span.lo))) + mk_sp(span.lo, body_lo))) } None => opener.to_owned(), }; result.push_str(&generics_str); + // FIXME: properly format empty structs and their comments. + if fields.is_empty() { + result.push_str(&self.snippet(mk_sp(body_lo, span.hi))); + return Some(result); + } + + let item_indent = if let ast::VariantData::Tuple(..) = *struct_def { + self.block_indent + result.len() + } else { + offset.block_indent(self.config) + }; + // 2 = ");" or "," + let item_budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 2)); + + let context = self.get_context(); let items = itemize_list(self.codemap, fields.iter(), terminator, @@ -883,55 +851,38 @@ impl<'a> FmtVisitor<'a> { } }, |field| field.node.ty.span.hi, - |field| self.format_field(field), + |field| field.rewrite(&context, item_budget, item_indent), span_after(span, opener.trim(), self.codemap), span.hi); - - // 2 terminators and a semicolon - let used_budget = offset.width() + header_str.len() + generics_str.len() + 3; - - // Conservative approximation - let single_line_cost = (span.hi - fields[0].span.lo).0; - let break_line = !is_tuple || generics_str.contains('\n') || - single_line_cost as usize + used_budget > self.config.max_width; - - let tactic = if break_line { - let indentation = offset.block_indent(self.config).to_string(self.config); - result.push('\n'); - result.push_str(&indentation); - - DefinitiveListTactic::Vertical - } else { - DefinitiveListTactic::Horizontal - }; - - // 1 = , - let budget = self.config.max_width - offset.width() + self.config.tab_spaces - 1; - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: self.config.struct_trailing_comma, - indent: offset.block_indent(self.config), - width: budget, - ends_with_newline: true, - config: self.config, - }; - - let list_str = try_opt!(write_list(items, &fmt)); - result.push_str(&list_str); - - if break_line { - result.push('\n'); - result.push_str(&offset.to_string(self.config)); - } - - result.push_str(terminator); - - if is_tuple { - result.push(';'); + match *struct_def { + ast::VariantData::Tuple(..) => { + // 2 = ); + let budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 2)); + let rewrite = try_opt!(format_item_list(items, budget, item_indent, self.config)); + result.push_str(&rewrite); + result.push(')'); + Some(result) + } + ast::VariantData::Struct(..) => { + // 1 = , + let budget = self.config.max_width - offset.width() + self.config.tab_spaces - 1; + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: self.config.struct_trailing_comma, + indent: item_indent, + width: budget, + ends_with_newline: true, + config: self.config, + }; + Some(format!("{}\n{}{}\n{}}}", + result, + offset.block_indent(self.config).to_string(self.config), + try_opt!(write_list(items, &fmt)), + offset.to_string(self.config))) + } + _ => unreachable!(), } - - Some(result) } fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { @@ -964,45 +915,6 @@ impl<'a> FmtVisitor<'a> { Some(result) } - // Field of a struct - fn format_field(&self, field: &ast::StructField) -> Option { - if contains_skip(&field.node.attrs) { - // FIXME: silly width, indent - return wrap_str(self.snippet(codemap::mk_sp(field.node.attrs[0].span.lo, - field.span.hi)), - self.config.max_width, - 1000, - Indent::empty()); - } - - let name = match field.node.kind { - ast::StructFieldKind::NamedField(ident, _) => Some(ident.to_string()), - ast::StructFieldKind::UnnamedField(_) => None, - }; - let vis = match field.node.kind { - ast::StructFieldKind::NamedField(_, vis) | - ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), - }; - // FIXME silly width, indent - let typ = try_opt!(field.node.ty.rewrite(&self.get_context(), 1000, Indent::empty())); - - let indent = self.block_indent.block_indent(self.config); - let mut attr_str = try_opt!(field.node - .attrs - .rewrite(&self.get_context(), - self.config.max_width - indent.width(), - indent)); - if !attr_str.is_empty() { - attr_str.push('\n'); - attr_str.push_str(&indent.to_string(self.config)); - } - - Some(match name { - Some(name) => format!("{}{}{}: {}", attr_str, vis, name, typ), - None => format!("{}{}{}", attr_str, vis, typ), - }) - } - fn rewrite_generics(&self, generics: &ast::Generics, offset: Indent, @@ -1039,7 +951,7 @@ impl<'a> FmtVisitor<'a> { } else { l.bounds[l.bounds.len() - 1].span.hi }; - codemap::mk_sp(l.lifetime.span.lo, hi) + mk_sp(l.lifetime.span.lo, hi) }); let ty_spans = tys.iter().map(span_for_ty_param); @@ -1122,6 +1034,44 @@ impl<'a> FmtVisitor<'a> { } } +impl Rewrite for ast::StructField { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + if contains_skip(&self.node.attrs) { + let span = context.snippet(mk_sp(self.node.attrs[0].span.lo, self.span.hi)); + return wrap_str(span, context.config.max_width, width, offset); + } + + let name = match self.node.kind { + ast::StructFieldKind::NamedField(ident, _) => Some(ident.to_string()), + ast::StructFieldKind::UnnamedField(_) => None, + }; + let vis = match self.node.kind { + ast::StructFieldKind::NamedField(_, vis) | + ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), + }; + let indent = context.block_indent.block_indent(context.config); + let mut attr_str = try_opt!(self.node + .attrs + .rewrite(context, + context.config.max_width - indent.width(), + indent)); + if !attr_str.is_empty() { + attr_str.push('\n'); + attr_str.push_str(&indent.to_string(context.config)); + } + + let result = match name { + Some(name) => format!("{}{}{}: ", attr_str, vis, name), + None => format!("{}{}", attr_str, vis), + }; + + let last_line_width = last_line_width(&result); + let budget = try_opt!(width.checked_sub(last_line_width)); + let rewrite = try_opt!(self.node.ty.rewrite(context, budget, offset + last_line_width)); + Some(result + &rewrite) + } +} + pub fn rewrite_static(prefix: &str, vis: ast::Visibility, ident: ast::Ident, @@ -1254,7 +1204,7 @@ fn span_for_ty_param(ty: &ast::TyParam) -> Span { // Note that ty.span is the span for ty.ident, not the whole item. let lo = ty.span.lo; if let Some(ref def) = ty.default { - return codemap::mk_sp(lo, def.span.hi); + return mk_sp(lo, def.span.hi); } if ty.bounds.is_empty() { return ty.span; @@ -1263,7 +1213,7 @@ fn span_for_ty_param(ty: &ast::TyParam) -> Span { ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span.hi, ast::TyParamBound::RegionTyParamBound(ref l) => l.span.hi, }; - codemap::mk_sp(lo, hi) + mk_sp(lo, hi) } fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { diff --git a/src/visitor.rs b/src/visitor.rs index 2264aaa94af..6ea296a36b7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -195,7 +195,13 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { def, Some(generics), item.span, - indent); + indent) + .map(|s| { + match **def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + } + }); self.push_rewrite(item.span, rewrite); } ast::Item_::ItemEnum(ref def, ref generics) => { diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 30b1ddadf3f..eba75877277 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -92,3 +92,7 @@ fn nested_enum_test() { } } } + + pub struct EmtpyWithComment { + // FIXME: Implement this struct +} diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 26578bf8c23..2bdfe7325bc 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -115,3 +115,9 @@ struct FieldsWithAttributes { #[attr1] #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC } + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 72a0266b23c..04391d8f30c 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -140,3 +140,7 @@ fn nested_enum_test() { } } } + +pub struct EmtpyWithComment { + // FIXME: Implement this struct +} diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 5ea4a21bad5..4bc8c6bbe44 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -34,12 +34,10 @@ struct Qux<'a, pub W, ); -struct Tuple( - // Comment 1 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -); +struct Tuple(// Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); // With a where clause and generics. pub struct Foo<'a, Y: Baz> @@ -113,3 +111,9 @@ struct FieldsWithAttributes { pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC * CCCCCCCCCCCCCC CCCCCCCCCCCC */ } + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} -- cgit 1.4.1-3-g733a5 From cf0f5ca814a1cf3a5ae8830bbcbabea1e3a045af Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 19 Oct 2015 21:40:00 +0200 Subject: Implement CommentCodeSlices --- src/comment.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++++------ src/missed_spans.rs | 12 +++----- 2 files changed, 78 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 86d1a9aeb14..d9b2d1e111e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -162,7 +162,7 @@ pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment) } -struct CharClasses +pub struct CharClasses where T: Iterator, T::Item: RichChar { @@ -170,7 +170,7 @@ struct CharClasses status: CharClassesStatus, } -trait RichChar { +pub trait RichChar { fn get_char(&self) -> char; } @@ -195,23 +195,23 @@ enum CharClassesStatus { LitCharEscape, // The u32 is the nesting deepness of the comment BlockComment(u32), - // Status when the '/' has been consumed, but not yet the '*', deepness is the new deepness - // (after the comment opening). + // Status when the '/' has been consumed, but not yet the '*', deepness is + // the new deepness (after the comment opening). BlockCommentOpening(u32), - // Status when the '*' has been consumed, but not yet the '/', deepness is the new deepness - // (after the comment closing). + // Status when the '*' has been consumed, but not yet the '/', deepness is + // the new deepness (after the comment closing). BlockCommentClosing(u32), LineComment, } #[derive(PartialEq, Eq, Debug, Clone, Copy)] -enum CodeCharKind { +pub enum CodeCharKind { Normal, Comment, } impl CharClasses where T: Iterator, T::Item: RichChar { - fn new(base: T) -> CharClasses { + pub fn new(base: T) -> CharClasses { CharClasses { base: base.peekable(), status: CharClassesStatus::Normal, @@ -298,11 +298,76 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { } } +struct CommentCodeSlices<'a> { + slice: &'a str, + last_slice_type: CodeCharKind, + last_slice_end: usize, +} + +impl<'a> CommentCodeSlices<'a> { + fn new(slice: &'a str) -> CommentCodeSlices<'a> { + CommentCodeSlices { + slice: slice, + last_slice_type: CodeCharKind::Comment, + last_slice_end: 0, + } + } +} + +impl<'a> Iterator for CommentCodeSlices<'a> { + type Item = (CodeCharKind, &'a str); + + fn next(&mut self) -> Option { + if self.last_slice_end == self.slice.len() { + return None; + } + + let mut sub_slice_end = self.last_slice_end; + for (kind, (i, _)) in CharClasses::new(self.slice[self.last_slice_end..].char_indices()) { + if kind == self.last_slice_type { + sub_slice_end = self.last_slice_end + i; + break; + } + } + + let kind = match self.last_slice_type { + CodeCharKind::Comment => CodeCharKind::Normal, + CodeCharKind::Normal => CodeCharKind::Comment, + }; + self.last_slice_type = kind; + + // FIXME: be consistent in use of kind vs type. + if sub_slice_end == self.last_slice_end { + // This was the last subslice. + self.last_slice_end = self.slice.len(); + + Some((kind, &self.slice[sub_slice_end..])) + } else { + let res = &self.slice[self.last_slice_end..sub_slice_end]; + self.last_slice_end = sub_slice_end; + Some((kind, res)) + } + } +} + #[cfg(test)] mod test { - use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented}; + use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented, + CommentCodeSlices}; use Indent; + #[test] + fn comment_code_slices() { + let input = "code(); /* test */ 1 + 1"; + + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, "code(); "), iter.next().unwrap()); + assert_eq!((CodeCharKind::Comment, "/* test */"), iter.next().unwrap()); + assert_eq!((CodeCharKind::Normal, " 1 + 1"), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + #[test] #[rustfmt_skip] fn format_comments() { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 57b63b56790..6cb4a88d160 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -10,7 +10,8 @@ use visitor::FmtVisitor; -use syntax::codemap::{self, BytePos}; +use syntax::codemap::{self, BytePos, Span}; +use comment::{CharClasses, CodeCharKind}; impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests @@ -37,16 +38,12 @@ impl<'a> FmtVisitor<'a> { end: BytePos, process_last_snippet: F) { let start = self.last_pos; - debug!("format_missing_inner: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end)); if start == end { // Do nothing if this is the beginning of the file. - if start == self.codemap.lookup_char_pos(start).file.start_pos { - return; + if start != self.codemap.lookup_char_pos(start).file.start_pos { + process_last_snippet(self, "", ""); } - process_last_snippet(self, "", ""); return; } @@ -57,7 +54,6 @@ impl<'a> FmtVisitor<'a> { self.last_pos = end; let span = codemap::mk_sp(start, end); - let snippet = self.snippet(span); self.write_snippet(&snippet, &process_last_snippet); } -- cgit 1.4.1-3-g733a5 From 3970748f59376381f360e42d8f703b2f0f7bbde7 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 19 Oct 2015 21:41:18 +0200 Subject: Remove overflow indentation --- src/comment.rs | 25 ++++++++++++++++--------- src/expr.rs | 11 +++++------ src/missed_spans.rs | 2 +- src/rewrite.rs | 16 ---------------- src/visitor.rs | 2 -- 5 files changed, 22 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d9b2d1e111e..e0910ba093e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -291,6 +291,10 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { '\n' => CharClassesStatus::Normal, _ => CharClassesStatus::LineComment, }; + // let code_char_kind = match chr { + // '\n' => CodeCharKind::Normal, + // _ => CodeCharKind::Comment, + // }; return Some((CodeCharKind::Comment, item)); } }; @@ -298,14 +302,14 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { } } -struct CommentCodeSlices<'a> { +pub struct CommentCodeSlices<'a> { slice: &'a str, last_slice_type: CodeCharKind, last_slice_end: usize, } impl<'a> CommentCodeSlices<'a> { - fn new(slice: &'a str) -> CommentCodeSlices<'a> { + pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { CommentCodeSlices { slice: slice, last_slice_type: CodeCharKind::Comment, @@ -315,7 +319,7 @@ impl<'a> CommentCodeSlices<'a> { } impl<'a> Iterator for CommentCodeSlices<'a> { - type Item = (CodeCharKind, &'a str); + type Item = (CodeCharKind, usize, &'a str); fn next(&mut self) -> Option { if self.last_slice_end == self.slice.len() { @@ -341,11 +345,13 @@ impl<'a> Iterator for CommentCodeSlices<'a> { // This was the last subslice. self.last_slice_end = self.slice.len(); - Some((kind, &self.slice[sub_slice_end..])) + Some((kind, sub_slice_end, &self.slice[sub_slice_end..])) } else { - let res = &self.slice[self.last_slice_end..sub_slice_end]; + let res = (kind, + self.last_slice_end, + &self.slice[self.last_slice_end..sub_slice_end]); self.last_slice_end = sub_slice_end; - Some((kind, res)) + Some(res) } } } @@ -362,9 +368,10 @@ mod test { let mut iter = CommentCodeSlices::new(input); - assert_eq!((CodeCharKind::Normal, "code(); "), iter.next().unwrap()); - assert_eq!((CodeCharKind::Comment, "/* test */"), iter.next().unwrap()); - assert_eq!((CodeCharKind::Normal, " 1 + 1"), iter.next().unwrap()); + assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); + assert_eq!((CodeCharKind::Comment, 8, "/* test */"), + iter.next().unwrap()); + assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap()); assert_eq!(None, iter.next()); } diff --git a/src/expr.rs b/src/expr.rs index b69989aa761..8592ad47b9e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -423,7 +423,7 @@ impl Rewrite for ast::Block { } let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config); - visitor.block_indent = context.block_indent + context.overflow_indent; + visitor.block_indent = context.block_indent; let prefix = match self.rules { ast::BlockCheckMode::UnsafeBlock(..) => { @@ -751,7 +751,7 @@ fn rewrite_match(context: &RewriteContext, let mut result = format!("match {} {{", cond_str); let nested_context = context.nested_context(); - let arm_indent = nested_context.block_indent + context.overflow_indent; + let arm_indent = nested_context.block_indent; let arm_indent_str = arm_indent.to_string(context.config); let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), @@ -795,7 +795,7 @@ fn rewrite_match(context: &RewriteContext, &arm_indent_str)); result.push_str(&comment); result.push('\n'); - result.push_str(&(context.block_indent + context.overflow_indent).to_string(context.config)); + result.push_str(&context.block_indent.to_string(context.config)); result.push('}'); Some(result) } @@ -1537,9 +1537,8 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // FIXME: we probably should related max_width to width instead of config.max_width // where is the 1 coming from anyway? let max_width = try_opt!(context.config.max_width.checked_sub(new_offset.width() + 1)); - let rhs_indent = Indent::new(context.config.tab_spaces, 0); - let overflow_context = context.overflow_context(rhs_indent); - let rhs = ex.rewrite(&overflow_context, max_width, new_offset); + let inner_context = context.nested_context(); + let rhs = ex.rewrite(&inner_context, max_width, new_offset); result.push_str(&&try_opt!(rhs)); } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 6cb4a88d160..53819bfdd8f 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -11,7 +11,7 @@ use visitor::FmtVisitor; use syntax::codemap::{self, BytePos, Span}; -use comment::{CharClasses, CodeCharKind}; +use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests diff --git a/src/rewrite.rs b/src/rewrite.rs index 6517bbdf37b..cf8be8004e1 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -29,14 +29,8 @@ pub trait Rewrite { pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, pub config: &'a Config, - // Indentation due to nesting of blocks. pub block_indent: Indent, - // *Extra* indentation due to overflowing to the next line, e.g., - // let foo = - // bar(); - // The extra 4 spaces when formatting `bar()` is overflow_indent. - pub overflow_indent: Indent, } impl<'a> RewriteContext<'a> { @@ -45,16 +39,6 @@ impl<'a> RewriteContext<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent.block_indent(self.config), - overflow_indent: self.overflow_indent, - } - } - - pub fn overflow_context(&self, overflow: Indent) -> RewriteContext<'a> { - RewriteContext { - codemap: self.codemap, - config: self.config, - block_indent: self.block_indent, - overflow_indent: overflow, } } diff --git a/src/visitor.rs b/src/visitor.rs index 6ea296a36b7..17f197ec880 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -387,7 +387,6 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: Indent::empty(), }; // 1 = ";" match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { @@ -419,7 +418,6 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, block_indent: self.block_indent, - overflow_indent: Indent::empty(), } } } -- cgit 1.4.1-3-g733a5 From e8447a82104d5f9da2802af1e8530aba7ad6512a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 19 Oct 2015 21:41:47 +0200 Subject: Fix large block comments --- Cargo.lock | 4 +- src/comment.rs | 119 ++++++++++++++++++++++++++++++++------------- src/expr.rs | 8 +-- src/items.rs | 7 +-- src/missed_spans.rs | 124 +++++++++++++++++++++++++++++++++++++++++------ src/visitor.rs | 17 ++++++- tests/source/comment.rs | 39 +++++++++++++++ tests/target/closure.rs | 5 +- tests/target/comment.rs | 42 ++++++++++++++++ tests/target/doc.rs | 2 +- tests/target/expr.rs | 3 +- tests/target/match.rs | 9 ++-- tests/target/multiple.rs | 3 +- 13 files changed, 314 insertions(+), 68 deletions(-) create mode 100644 tests/source/comment.rs create mode 100644 tests/target/comment.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 3648e5e5f67..c00a673ebf6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "toml" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/comment.rs b/src/comment.rs index e0910ba093e..e4ce5a7ed35 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -81,11 +81,11 @@ pub fn rewrite_comment(orig: &str, let rewrite = try_opt!(rewrite_string(line, &fmt)); result.push_str(&rewrite); } else { - if line.len() == 0 { - result.pop(); // Remove space if this is an empty comment. - } else { - result.push_str(line); + if line.len() == 0 || line.starts_with('!') { + // Remove space if this is an empty comment or a doc comment. + result.pop(); } + result.push_str(line); } first = false; @@ -162,7 +162,7 @@ pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment) } -pub struct CharClasses +struct CharClasses where T: Iterator, T::Item: RichChar { @@ -170,7 +170,7 @@ pub struct CharClasses status: CharClassesStatus, } -pub trait RichChar { +trait RichChar { fn get_char(&self) -> char; } @@ -211,7 +211,7 @@ pub enum CodeCharKind { } impl CharClasses where T: Iterator, T::Item: RichChar { - pub fn new(base: T) -> CharClasses { + fn new(base: T) -> CharClasses { CharClasses { base: base.peekable(), status: CharClassesStatus::Normal, @@ -291,10 +291,6 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { '\n' => CharClassesStatus::Normal, _ => CharClassesStatus::LineComment, }; - // let code_char_kind = match chr { - // '\n' => CodeCharKind::Normal, - // _ => CodeCharKind::Comment, - // }; return Some((CodeCharKind::Comment, item)); } }; @@ -302,9 +298,12 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { } } +/// Iterator over an alternating sequence of functional and commented parts of +/// a string. The first item is always a, possibly zero length, subslice of +/// functional text. Line style comments contain their ending newlines. pub struct CommentCodeSlices<'a> { slice: &'a str, - last_slice_type: CodeCharKind, + last_slice_kind: CodeCharKind, last_slice_end: usize, } @@ -312,7 +311,7 @@ impl<'a> CommentCodeSlices<'a> { pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { CommentCodeSlices { slice: slice, - last_slice_type: CodeCharKind::Comment, + last_slice_kind: CodeCharKind::Comment, last_slice_end: 0, } } @@ -327,32 +326,52 @@ impl<'a> Iterator for CommentCodeSlices<'a> { } let mut sub_slice_end = self.last_slice_end; - for (kind, (i, _)) in CharClasses::new(self.slice[self.last_slice_end..].char_indices()) { - if kind == self.last_slice_type { - sub_slice_end = self.last_slice_end + i; + let mut first_whitespace = None; + let subslice = &self.slice[self.last_slice_end..]; + let mut iter = CharClasses::new(subslice.char_indices()); + + for (kind, (i, c)) in &mut iter { + let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal && + &subslice[..2] == "//" && + [' ', '\t'].contains(&c); + + if is_comment_connector && first_whitespace.is_none() { + first_whitespace = Some(i); + } + + if kind == self.last_slice_kind && !is_comment_connector { + let last_index = match first_whitespace { + Some(j) => j, + None => i, + }; + sub_slice_end = self.last_slice_end + last_index; break; } + + if !is_comment_connector { + first_whitespace = None; + } + } + + if let (None, true) = (iter.next(), sub_slice_end == self.last_slice_end) { + // This was the last subslice. + sub_slice_end = match first_whitespace { + Some(i) => self.last_slice_end + i, + None => self.slice.len(), + }; } - let kind = match self.last_slice_type { + let kind = match self.last_slice_kind { CodeCharKind::Comment => CodeCharKind::Normal, CodeCharKind::Normal => CodeCharKind::Comment, }; - self.last_slice_type = kind; - - // FIXME: be consistent in use of kind vs type. - if sub_slice_end == self.last_slice_end { - // This was the last subslice. - self.last_slice_end = self.slice.len(); + let res = (kind, + self.last_slice_end, + &self.slice[self.last_slice_end..sub_slice_end]); + self.last_slice_end = sub_slice_end; + self.last_slice_kind = kind; - Some((kind, sub_slice_end, &self.slice[sub_slice_end..])) - } else { - let res = (kind, - self.last_slice_end, - &self.slice[self.last_slice_end..sub_slice_end]); - self.last_slice_end = sub_slice_end; - Some(res) - } + Some(res) } } @@ -362,10 +381,20 @@ mod test { CommentCodeSlices}; use Indent; + #[test] + fn char_classes() { + let mut iter = CharClasses::new("//\n\n".chars()); + + assert_eq!((CodeCharKind::Comment, '/'), iter.next().unwrap()); + assert_eq!((CodeCharKind::Comment, '/'), iter.next().unwrap()); + assert_eq!((CodeCharKind::Comment, '\n'), iter.next().unwrap()); + assert_eq!((CodeCharKind::Normal, '\n'), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + #[test] fn comment_code_slices() { let input = "code(); /* test */ 1 + 1"; - let mut iter = CommentCodeSlices::new(input); assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); @@ -375,6 +404,31 @@ mod test { assert_eq!(None, iter.next()); } + #[test] + fn comment_code_slices_two() { + let input = "// comment\n test();"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap()); + assert_eq!((CodeCharKind::Comment, 0, "// comment\n"), + iter.next().unwrap()); + assert_eq!((CodeCharKind::Normal, 11, " test();"), + iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices_three() { + let input = "1 // comment\n // comment2\n\n"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap()); + assert_eq!((CodeCharKind::Comment, 2, "// comment\n // comment2\n"), + iter.next().unwrap()); + assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + #[test] #[rustfmt_skip] fn format_comments() { @@ -434,7 +488,6 @@ mod test { #[test] fn test_find_uncommented() { fn check(haystack: &str, needle: &str, expected: Option) { - println!("haystack {:?}, needle: {:?}", haystack, needle); assert_eq!(expected, haystack.find_uncommented(needle)); } diff --git a/src/expr.rs b/src/expr.rs index 8592ad47b9e..f0a877db215 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -471,10 +471,6 @@ impl Rewrite for ast::Block { visitor.visit_block(self); - // Push text between last block item and end of block - let snippet = visitor.snippet(mk_sp(visitor.last_pos, self.span.hi)); - visitor.buffer.push_str(&snippet); - Some(format!("{}{}", prefix, visitor.buffer)) } } @@ -1534,8 +1530,8 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let new_offset = offset.block_indent(context.config); result.push_str(&format!("\n{}", new_offset.to_string(context.config))); - // FIXME: we probably should related max_width to width instead of config.max_width - // where is the 1 coming from anyway? + // FIXME: we probably should related max_width to width instead of + // config.max_width where is the 1 coming from anyway? let max_width = try_opt!(context.config.max_width.checked_sub(new_offset.width() + 1)); let inner_context = context.nested_context(); let rhs = ex.rewrite(&inner_context, max_width, new_offset); diff --git a/src/items.rs b/src/items.rs index 78d35427519..c8054b8d01f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -287,8 +287,8 @@ impl<'a> FmtVisitor<'a> { has_body: bool) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; - // FIXME we'll lose any comments in between parts of the function decl, but anyone - // who comments there probably deserves what they get. + // FIXME we'll lose any comments in between parts of the function decl, but + // anyone who comments there probably deserves what they get. let where_clause = &generics.where_clause; @@ -1008,7 +1008,8 @@ impl<'a> FmtVisitor<'a> { span_start, span_end); let item_vec = items.collect::>(); - // FIXME: we don't need to collect here if the where_layout isnt horizontalVertical + // FIXME: we don't need to collect here if the where_layout isnt + // HorizontalVertical. let tactic = definitive_tactic(&item_vec, self.config.where_layout, budget); let fmt = ListFormatting { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 53819bfdd8f..04d3ac3366a 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -10,7 +10,7 @@ use visitor::FmtVisitor; -use syntax::codemap::{self, BytePos, Span}; +use syntax::codemap::{self, BytePos, Span, Pos}; use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; impl<'a> FmtVisitor<'a> { @@ -55,22 +55,116 @@ impl<'a> FmtVisitor<'a> { self.last_pos = end; let span = codemap::mk_sp(start, end); - self.write_snippet(&snippet, &process_last_snippet); + self.write_snippet(span, &process_last_snippet); } - fn write_snippet(&mut self, - snippet: &str, - process_last_snippet: F) { - let mut lines: Vec<&str> = snippet.lines().collect(); - let last_snippet = if snippet.ends_with("\n") { - "" - } else { - lines.pop().unwrap() - }; - for line in lines.iter() { - self.buffer.push_str(line.trim_right()); - self.buffer.push_str("\n"); + fn write_snippet(&mut self, span: Span, process_last_snippet: F) + where F: Fn(&mut FmtVisitor, &str, &str) + { + // Get a snippet from the file start to the span's hi without allocating. + // We need it to determine what precedes the current comment. If the comment + // follows code on the same line, we won't touch it. + let big_span_lo = self.codemap.lookup_char_pos(span.lo).file.start_pos; + let local_begin = self.codemap.lookup_byte_offset(big_span_lo); + let local_end = self.codemap.lookup_byte_offset(span.hi); + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; + + let big_diff = (span.lo - big_span_lo).to_usize(); + let snippet = self.snippet(span); + + self.write_snippet_inner(big_snippet, big_diff, &snippet, process_last_snippet); + } + + fn write_snippet_inner(&mut self, + big_snippet: &str, + big_diff: usize, + snippet: &str, + process_last_snippet: F) + where F: Fn(&mut FmtVisitor, &str, &str) + { + // Trim whitespace from the right hand side of each line. + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let mut line_start = 0; + let mut last_wspace = None; + let mut rewrite_next_comment = true; + + for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { + if let CodeCharKind::Comment = kind { + let last_char = big_snippet[..(offset + big_diff)] + .chars() + .rev() + .skip_while(|rev_c| [' ', '\t'].contains(&rev_c)) + .next(); + + let fix_indent = last_char.map(|rev_c| ['{', '\n'].contains(&rev_c)) + .unwrap_or(true); + + if rewrite_next_comment && fix_indent { + if let Some('{') = last_char { + self.buffer.push_str("\n"); + } + + let comment_width = ::std::cmp::min(self.config.ideal_width, + self.config.max_width - + self.block_indent.width()); + + self.buffer.push_str(&self.block_indent.to_string(self.config)); + self.buffer.push_str(&rewrite_comment(subslice, + false, + comment_width, + self.block_indent, + self.config) + .unwrap()); + + last_wspace = None; + line_start = offset + subslice.len(); + + if let Some('/') = subslice.chars().skip(1).next() { + self.buffer.push_str("\n"); + } else if line_start < snippet.len() { + let x = (&snippet[line_start..]).chars().next().unwrap() != '\n'; + + if x { + self.buffer.push_str("\n"); + } + } + + continue; + } else { + rewrite_next_comment = false; + } + } + + for (mut i, c) in subslice.char_indices() { + i += offset; + + if c == '\n' { + if let Some(lw) = last_wspace { + self.buffer.push_str(&snippet[line_start..lw]); + self.buffer.push_str("\n"); + } else { + self.buffer.push_str(&snippet[line_start..i + 1]); + } + + line_start = i + 1; + last_wspace = None; + rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + } else { + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(i); + } + } else { + rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + last_wspace = None; + } + } + } } - process_last_snippet(self, &last_snippet, snippet); + + process_last_snippet(self, &snippet[line_start..], &snippet); } } diff --git a/src/visitor.rs b/src/visitor.rs index 17f197ec880..b8de0fc7189 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -101,11 +101,22 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } } - self.block_indent = self.block_indent.block_unindent(self.config); // TODO: we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - brace_compensation); + // FIXME: this is a terrible hack to indent the comments between the last + // item in the block and the closing brace to the block's level. + // The closing brace itself, however, should be indented at a shallower + // level. + let total_len = self.buffer.len; + let chars_too_many = if self.config.hard_tabs { + 1 + } else { + self.config.tab_spaces + }; + self.buffer.truncate(total_len - chars_too_many); self.buffer.push_str("}"); self.last_pos = b.span.hi; + self.block_indent = self.block_indent.block_unindent(self.config); } // Note that this only gets called for function definitions. Required methods @@ -177,6 +188,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { // FIXME(#78): format traits and impl definitions. ast::Item_::ItemImpl(..) | ast::Item_::ItemTrait(..) => { + self.format_missing_with_indent(item.span.lo); self.block_indent = self.block_indent.block_indent(self.config); visit::walk_item(self, item); self.block_indent = self.block_indent.block_unindent(self.config); @@ -215,6 +227,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { } ast::Item_::ItemMac(..) => { self.format_missing_with_indent(item.span.lo); + let snippet = self.snippet(item.span); + self.buffer.push_str(&snippet); + self.last_pos = item.span.hi; // FIXME: we cannot format these yet, because of a bad span. // See rust lang issue #28424. // visit::walk_item(self, item); diff --git a/tests/source/comment.rs b/tests/source/comment.rs new file mode 100644 index 00000000000..34b5de79b75 --- /dev/null +++ b/tests/source/comment.rs @@ -0,0 +1,39 @@ +//! Doc comment +fn test() { +// comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + + /// test123 +fn doc_comment() { +} + +fn chains() { + foo.bar(|| { + let x = 10; + /* comment */ x }) +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 72acae8dbd9..6ab217ed6c4 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -19,7 +19,7 @@ fn main() { }; let loooooooooooooong_name = |field| { - // TODO(#27): format comments. + // TODO(#27): format comments. if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo } else { @@ -39,7 +39,8 @@ fn main() { let empty = |arg| {}; - let simple = |arg| { /* TODO(#27): comment formatting */ + let simple = |arg| { + // TODO(#27): comment formatting foo(arg) }; diff --git a/tests/target/comment.rs b/tests/target/comment.rs new file mode 100644 index 00000000000..575631cd3be --- /dev/null +++ b/tests/target/comment.rs @@ -0,0 +1,42 @@ +//! Doc comment +fn test() { + // comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + // viverra nec consectetur ante hendrerit. Donec et mollis dolor. + // Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + // tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + // libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + // amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + // felis, pulvinar a semper sed, adipiscing id dolor. + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment + // that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + +/// test123 +fn doc_comment() { +} + +fn chains() { + foo.bar(|| { + let x = 10; + // comment + x + }) +} diff --git a/tests/target/doc.rs b/tests/target/doc.rs index f325337c758..9e883c50afa 100644 --- a/tests/target/doc.rs +++ b/tests/target/doc.rs @@ -1,3 +1,3 @@ // sadfsdfa -//sdffsdfasdf +// sdffsdfasdf diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 479a279e43b..4b4afaa99e5 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -142,7 +142,8 @@ fn baz() { fn qux() { {} // FIXME this one could be done better. - { /* a block with a comment */ + { + // a block with a comment } { diff --git a/tests/target/match.rs b/tests/target/match.rs index 6c498014aa1..7202b0e0c80 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -6,7 +6,8 @@ fn foo() { // Some comment. a => foo(), b if 0 < 42 => foo(), - c => { // Another comment. + c => { + // Another comment. // Comment. an_expression; foo() @@ -112,7 +113,8 @@ fn issue339() { // collapsing here exceeds line length ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { } - h => { // comment above block + h => { + // comment above block } i => {} // comment below block j => { @@ -133,7 +135,8 @@ fn issue339() { m => {} n => {} o => {} - p => { // Dont collapse me + p => { + // Dont collapse me } q => {} r => {} diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 3c17eb77924..7d6513f70b7 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -22,7 +22,8 @@ mod doc; mod other; -// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff +// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff +// ffffffffffffffffffffffffffffffffffffffffff fn foo(a: isize, b: u32 /* blah blah */, c: f64) { -- cgit 1.4.1-3-g733a5 From 6b4ef7457a54103817e8afb3dba3828b60b1e286 Mon Sep 17 00:00:00 2001 From: Tim Kuehn Date: Tue, 20 Oct 2015 02:12:52 -0700 Subject: Fix doc comment regression and add tests. --- src/comment.rs | 11 +++++++++-- tests/source/comment2.rs | 2 ++ tests/source/comment3.rs | 3 +++ tests/target/comment2.rs | 4 ++++ tests/target/comment3.rs | 5 +++++ 5 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/source/comment2.rs create mode 100644 tests/source/comment3.rs create mode 100644 tests/target/comment2.rs create mode 100644 tests/target/comment3.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e4ce5a7ed35..045d1cb5047 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -27,6 +27,10 @@ pub fn rewrite_comment(orig: &str, // Edge case: block comments. Let's not trim their lines (for now). let (opener, closer, line_start) = if block_style { ("/* ", " */", " * ") + } else if orig.starts_with("///") { + ("/// ", "", "/// ") + } else if orig.starts_with("//!") { + ("//! ", "", "//! ") } else { ("// ", "", "// ") }; @@ -81,7 +85,7 @@ pub fn rewrite_comment(orig: &str, let rewrite = try_opt!(rewrite_string(line, &fmt)); result.push_str(&rewrite); } else { - if line.len() == 0 || line.starts_with('!') { + if line.len() == 0 { // Remove space if this is an empty comment or a doc comment. result.pop(); } @@ -97,7 +101,10 @@ pub fn rewrite_comment(orig: &str, } fn left_trim_comment_line(line: &str) -> &str { - if line.starts_with("/* ") || line.starts_with("// ") { + if line.starts_with("//! ") || line.starts_with("/// ") { + &line[4..] + } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || + line.starts_with("///") { &line[3..] } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") { &line[2..] diff --git a/tests/source/comment2.rs b/tests/source/comment2.rs new file mode 100644 index 00000000000..81478621bd9 --- /dev/null +++ b/tests/source/comment2.rs @@ -0,0 +1,2 @@ +/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. +pub mod foo {} diff --git a/tests/source/comment3.rs b/tests/source/comment3.rs new file mode 100644 index 00000000000..ed54605f727 --- /dev/null +++ b/tests/source/comment3.rs @@ -0,0 +1,3 @@ +//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. + +pub mod foo {} diff --git a/tests/target/comment2.rs b/tests/target/comment2.rs new file mode 100644 index 00000000000..885964afee2 --- /dev/null +++ b/tests/target/comment2.rs @@ -0,0 +1,4 @@ +/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly +/// and justly. +pub mod foo { +} diff --git a/tests/target/comment3.rs b/tests/target/comment3.rs new file mode 100644 index 00000000000..c9123d4e076 --- /dev/null +++ b/tests/target/comment3.rs @@ -0,0 +1,5 @@ +//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly +//! and justly. + +pub mod foo { +} -- cgit 1.4.1-3-g733a5 From be9e7dc68963db304533f3885ea6d27fddc81ae6 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 21 Oct 2015 13:21:14 -0700 Subject: Don't use `visit::walk_*`. Instead, recurse by hand. This is much more straightforward to understand given how rustfmt rewriting works, and it avoids walking into expressions in unexpected places. Fixes #513. Fixes #514. --- src/visitor.rs | 126 +++++++++++++++++++++++++++++++++++--------------- tests/source/trait.rs | 33 +++++++++++++ tests/target/impl.rs | 3 ++ tests/target/trait.rs | 4 ++ 4 files changed, 129 insertions(+), 37 deletions(-) create mode 100644 tests/source/trait.rs create mode 100644 tests/target/impl.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index b8de0fc7189..c58d16809aa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -31,17 +31,13 @@ pub struct FmtVisitor<'a> { pub config: &'a Config, } -impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { - fn visit_expr(&mut self, _: &'v ast::Expr) { - unreachable!() - } - - fn visit_stmt(&mut self, stmt: &'v ast::Stmt) { +impl<'a> FmtVisitor<'a> { + fn visit_stmt(&mut self, stmt: &ast::Stmt) { match stmt.node { ast::Stmt_::StmtDecl(ref decl, _) => { match decl.node { ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span), - ast::Decl_::DeclItem(..) => visit::walk_stmt(self, stmt), + ast::Decl_::DeclItem(ref item) => self.visit_item(item), } } ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { @@ -57,14 +53,14 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { .map(|s| s + suffix); self.push_rewrite(stmt.span, rewrite); } - ast::Stmt_::StmtMac(ref _mac, _macro_style) => { + ast::Stmt_::StmtMac(ref mac, _macro_style) => { self.format_missing_with_indent(stmt.span.lo); - visit::walk_stmt(self, stmt); + self.visit_mac(mac); } } } - fn visit_block(&mut self, b: &'v ast::Block) { + pub fn visit_block(&mut self, b: &ast::Block) { debug!("visit_block: {:?} {:?}", self.codemap.lookup_char_pos(b.span.lo), self.codemap.lookup_char_pos(b.span.hi)); @@ -122,9 +118,9 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. fn visit_fn(&mut self, - fk: visit::FnKind<'v>, - fd: &'v ast::FnDecl, - b: &'v ast::Block, + fk: visit::FnKind, + fd: &ast::FnDecl, + b: &ast::Block, s: Span, _: ast::NodeId) { let indent = self.block_indent; @@ -167,7 +163,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.visit_block(b) } - fn visit_item(&mut self, item: &'v ast::Item) { + fn visit_item(&mut self, item: &ast::Item) { // Don't look at attributes for modules. // We want to avoid looking at attributes in another file, which the AST // doesn't distinguish. FIXME This is overly conservative and means we miss @@ -185,12 +181,22 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { ast::Item_::ItemUse(ref vp) => { self.format_import(item.vis, vp, item.span); } - // FIXME(#78): format traits and impl definitions. - ast::Item_::ItemImpl(..) | - ast::Item_::ItemTrait(..) => { + // FIXME(#78): format impl definitions. + ast::Item_::ItemImpl(_, _, _, _, _, ref impl_items) => { + self.format_missing_with_indent(item.span.lo); + self.block_indent = self.block_indent.block_indent(self.config); + for item in impl_items { + self.visit_impl_item(&item); + } + self.block_indent = self.block_indent.block_unindent(self.config); + } + // FIXME(#78): format traits. + ast::Item_::ItemTrait(_, _, _, ref trait_items) => { self.format_missing_with_indent(item.span.lo); self.block_indent = self.block_indent.block_indent(self.config); - visit::walk_item(self, item); + for item in trait_items { + self.visit_trait_item(&item); + } self.block_indent = self.block_indent.block_unindent(self.config); } ast::Item_::ItemExternCrate(_) => { @@ -232,7 +238,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = item.span.hi; // FIXME: we cannot format these yet, because of a bad span. // See rust lang issue #28424. - // visit::walk_item(self, item); } ast::Item_::ItemForeignMod(ref foreign_mod) => { self.format_missing_with_indent(item.span.lo); @@ -258,37 +263,80 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &self.get_context()); self.push_rewrite(item.span, rewrite); } - // FIXME(#486): format type aliases. - ast::Item_::ItemDefaultImpl(..) | - ast::Item_::ItemFn(..) | + ast::Item_::ItemDefaultImpl(..) => { + // FIXME(#78): format impl definitions. + } + ast::ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { + self.visit_fn(visit::FnKind::ItemFn(item.ident, + generics, + unsafety, + constness, + abi, + item.vis), + declaration, + body, + item.span, + item.id) + } ast::Item_::ItemTy(..) => { - visit::walk_item(self, item); + // FIXME(#486): format type aliases. } } } - fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) { + fn visit_trait_item(&mut self, ti: &ast::TraitItem) { if self.visit_attrs(&ti.attrs) { return; } - if let ast::TraitItem_::MethodTraitItem(ref sig, None) = ti.node { - let indent = self.block_indent; - let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); - self.push_rewrite(ti.span, rewrite); + match ti.node { + ast::ConstTraitItem(..) => { + // FIXME: Implement + } + ast::MethodTraitItem(ref sig, None) => { + let indent = self.block_indent; + let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); + self.push_rewrite(ti.span, rewrite); + } + ast::MethodTraitItem(ref sig, Some(ref body)) => { + self.visit_fn(visit::FnKind::Method(ti.ident, sig, None), + &sig.decl, + &body, + ti.span, + ti.id); + } + ast::TypeTraitItem(..) => { + // FIXME: Implement + } } - - visit::walk_trait_item(self, ti) } - fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) { + fn visit_impl_item(&mut self, ii: &ast::ImplItem) { if self.visit_attrs(&ii.attrs) { return; } - visit::walk_impl_item(self, ii) + + match ii.node { + ast::MethodImplItem(ref sig, ref body) => { + self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(ii.vis)), + &sig.decl, + body, + ii.span, + ii.id); + } + ast::ConstImplItem(..) => { + // FIXME: Implement + } + ast::TypeImplItem(_) => { + // FIXME: Implement + } + ast::MacImplItem(ref mac) => { + self.visit_mac(mac); + } + } } - fn visit_mac(&mut self, mac: &'v ast::Mac) { + fn visit_mac(&mut self, mac: &ast::Mac) { // 1 = ; let width = self.config.max_width - self.block_indent.width() - 1; let rewrite = rewrite_macro(mac, &self.get_context(), width, self.block_indent); @@ -298,9 +346,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.last_pos = mac.span.hi; } } -} -impl<'a> FmtVisitor<'a> { fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(span.lo); @@ -366,6 +412,12 @@ impl<'a> FmtVisitor<'a> { false } + fn walk_mod_items(&mut self, m: &ast::Mod) { + for item in &m.items { + self.visit_item(&item); + } + } + fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); @@ -377,7 +429,7 @@ impl<'a> FmtVisitor<'a> { if is_internal { self.block_indent = self.block_indent.block_indent(self.config); - visit::walk_mod(self, m); + self.walk_mod_items(m); self.block_indent = self.block_indent.block_unindent(self.config); self.format_missing_with_indent(m.inner.hi - BytePos(1)); @@ -390,7 +442,7 @@ impl<'a> FmtVisitor<'a> { let filemap = self.codemap.get_filemap(filename); self.last_pos = filemap.start_pos; self.block_indent = Indent::empty(); - visit::walk_mod(self, m); + self.walk_mod_items(m); self.format_missing(filemap.end_pos); } diff --git a/tests/source/trait.rs b/tests/source/trait.rs new file mode 100644 index 00000000000..e04c7182421 --- /dev/null +++ b/tests/source/trait.rs @@ -0,0 +1,33 @@ +// Test traits + +trait Foo { + fn bar(x: i32 ) -> Baz< U> { Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, +b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) +-> RetType; + + fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment +b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType ; // Some comment + + fn baz(&mut self ) -> i32 ; + +fn increment(& mut self, x: i32 ); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where R: Read; +} + +pub trait WriteMessage { + fn write_message (&mut self, &FrontendMessage) -> io::Result<()>; +} + +trait Runnable { + fn handler(self: & Runnable ); +} + +trait TraitWithExpr { + fn fn_with_expr(x: [i32; 1]); +} diff --git a/tests/target/impl.rs b/tests/target/impl.rs new file mode 100644 index 00000000000..df44377a6bf --- /dev/null +++ b/tests/target/impl.rs @@ -0,0 +1,3 @@ +// Test impls + +impl JSTraceable for SmallVec<[T; 1]> {} diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 3e0a7ed692a..ffc5b87c6ea 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -25,3 +25,7 @@ pub trait WriteMessage { trait Runnable { fn handler(self: &Runnable); } + +trait TraitWithExpr { + fn fn_with_expr(x: [i32; 1]); +} -- cgit 1.4.1-3-g733a5 From e720218ffb6553764b516e074fee96eb0efb79e9 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 21 Oct 2015 14:35:45 -0700 Subject: Improve handling of commas after match arms. Fixes #507. Fixes #508. --- src/expr.rs | 19 ++++++++++++++----- tests/source/match.rs | 17 +++++++++++++++++ tests/target/match.rs | 17 +++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f0a877db215..c619376f276 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -779,6 +779,7 @@ fn rewrite_match(context: &RewriteContext, // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); + result.push_str(arm_comma(&arm.body)); } } // BytePos(1) = closing match brace. @@ -809,6 +810,18 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { arm.body.span.hi } +fn arm_comma(body: &ast::Expr) -> &'static str { + if let ast::ExprBlock(ref block) = body.node { + if let ast::DefaultBlock = block.rules { + "" + } else { + "," + } + } else { + "," + } +} + // Match arms. impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { @@ -881,11 +894,7 @@ impl Rewrite for ast::Arm { line_start += offset.width(); } - let comma = if let ast::ExprBlock(_) = body.node { - "" - } else { - "," - }; + let comma = arm_comma(body); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() diff --git a/tests/source/match.rs b/tests/source/match.rs index 992d0d98bf8..9ed25756d64 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -226,3 +226,20 @@ fn issue280() { fn issue383() { match resolution.last_private {LastImport{..} => false, _ => true}; } + +fn issue507() { + match 1 { + 1 => unsafe { std::intrinsics::abort() }, + _ => (), + } +} + +fn issue508() { + match s.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement))) => true, + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), + Some(NodeTypeId::Element(_)) => false, + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 7202b0e0c80..2e1a1b886ec 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -230,3 +230,20 @@ fn issue383() { _ => true, } } + +fn issue507() { + match 1 { + 1 => unsafe { std::intrinsics::abort() }, + _ => (), + } +} + +fn issue508() { + match s.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement))) => true, + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), + Some(NodeTypeId::Element(_)) => false, + } +} -- cgit 1.4.1-3-g733a5 From 2d267b16d1f28e7ab14cd1cc9953ae21fe1856c6 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 18 Oct 2015 17:56:13 +0200 Subject: Deal with floating links in chains --- src/chains.rs | 45 +++++++++++++++++---- src/config.rs | 5 ++- tests/source/chains-block-indented-base.rs | 30 ++++++++++++++ tests/source/chains.rs | 46 +++++++++++++++++++++ tests/target/chains-block-indented-base.rs | 31 +++++++++++++++ tests/target/chains.rs | 64 ++++++++++++++++++++++++++++++ 6 files changed, 211 insertions(+), 10 deletions(-) create mode 100644 tests/source/chains-block-indented-base.rs create mode 100644 tests/target/chains-block-indented-base.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 6122aa14614..4b6824a9073 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -23,6 +23,7 @@ use Indent; use rewrite::{Rewrite, RewriteContext}; use utils::first_line_width; use expr::rewrite_call; +use config::BlockIndentStyle; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; @@ -41,17 +42,24 @@ pub fn rewrite_chain(mut expr: &ast::Expr, expr = subexpr; } + let parent_block_indent = match context.config.chain_base_indent { + BlockIndentStyle::Visual => offset, + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + }; + let parent_context = &RewriteContext { block_indent: parent_block_indent, ..*context }; let parent = subexpr_list.pop().unwrap(); - let parent_rewrite = try_opt!(expr.rewrite(context, width, offset)); - let (extra_indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || - parent_rewrite.len() <= context.config.tab_spaces { - (Indent::new(0, parent_rewrite.len()), true) + let parent_rewrite = try_opt!(expr.rewrite(parent_context, width, offset)); + let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || + parent_rewrite.len() <= context.config.tab_spaces { + (offset + Indent::new(0, parent_rewrite.len()), true) + } else if is_block_expr(parent, &parent_rewrite) { + (parent_block_indent, false) } else { - (Indent::new(context.config.tab_spaces, 0), false) + (offset + Indent::new(context.config.tab_spaces, 0), false) }; - let indent = offset + extra_indent; - let max_width = try_opt!(width.checked_sub(extra_indent.width())); + let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); let mut rewrites = try_opt!(subexpr_list.iter() .rev() .map(|e| { @@ -114,7 +122,7 @@ pub fn rewrite_chain(mut expr: &ast::Expr, _ => total_width <= width && rewrites.iter().all(|s| !s.contains('\n')), }; - let connector = if fits_single_line { + let connector = if fits_single_line && !parent_rewrite.contains('\n') { String::new() } else { format!("\n{}", indent.to_string(context.config)) @@ -132,6 +140,27 @@ pub fn rewrite_chain(mut expr: &ast::Expr, rewrites.join(&connector))) } +// States whether an expression's last line exclusively consists of closing +// parens, braces and brackets in its idiomatic formatting. +fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { + match expr.node { + ast::Expr_::ExprStruct(..) | + ast::Expr_::ExprWhile(..) | + ast::Expr_::ExprWhileLet(..) | + ast::Expr_::ExprIf(..) | + ast::Expr_::ExprIfLet(..) | + ast::Expr_::ExprBlock(..) | + ast::Expr_::ExprLoop(..) | + ast::Expr_::ExprForLoop(..) | + ast::Expr_::ExprMatch(..) => repr.contains('\n'), + ast::Expr_::ExprParen(ref expr) | + ast::Expr_::ExprBinary(_, _, ref expr) | + ast::Expr_::ExprIndex(_, ref expr) | + ast::Expr_::ExprUnary(_, ref expr) => is_block_expr(expr, repr), + _ => false, + } +} + fn pop_expr_chain<'a>(expr: &'a ast::Expr) -> Option<&'a ast::Expr> { match expr.node { ast::Expr_::ExprMethodCall(_, _, ref expressions) => { diff --git a/src/config.rs b/src/config.rs index 6a7e686dc11..d788b17cfe7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -290,9 +290,10 @@ create_config! { "Multiline style on literal structs"; enum_trailing_comma: bool, true, "Put a trailing comma on enum declarations"; report_todo: ReportTactic, ReportTactic::Always, - "Report all occurrences of TODO in source file comments"; + "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, - "Report all occurrences of FIXME in source file comments"; + "Report all, none or unnumbered occurrences of FIXME in source file comments"; + chain_base_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on chain base"; // Alphabetically, case sensitive. reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; diff --git a/tests/source/chains-block-indented-base.rs b/tests/source/chains-block-indented-base.rs new file mode 100644 index 00000000000..05459dc6973 --- /dev/null +++ b/tests/source/chains-block-indented-base.rs @@ -0,0 +1,30 @@ +// rustfmt-chain_base_indent: Inherit +// Test chain formatting with block indented base + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 2a400b306d2..a50a9c51253 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -55,3 +55,49 @@ fn main() { x }).filter(some_mod::some_filter) } + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } + + if cond { some(); } else { none(); } + .bar() + .baz(); + + Foo { x: val } .baz(|| { /*force multiline */ }) .quux(); + + Foo { y: i_am_multi_line, z: ok } + .baz(|| { + // force multiline + }) + .quux(); + + a + match x { true => "yay!", false => "boo!" }.bar() +} diff --git a/tests/target/chains-block-indented-base.rs b/tests/target/chains-block-indented-base.rs new file mode 100644 index 00000000000..5b9863689de --- /dev/null +++ b/tests/target/chains-block-indented-base.rs @@ -0,0 +1,31 @@ +// rustfmt-chain_base_indent: Inherit +// Test chain formatting with block indented base + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index ea9b6867efe..9e195b42d6e 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -62,3 +62,67 @@ fn main() { }) .filter(some_mod::some_filter) } + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + } + .method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } + + if cond { + some(); + } else { + none(); + } + .bar() + .baz(); + + Foo { x: val } + .baz(|| { + // force multiline + }) + .quux(); + + Foo { + y: i_am_multi_line, + z: ok, + } + .baz(|| { + // force multiline + }) + .quux(); + + a + + match x { + true => "yay!", + false => "boo!", + } + .bar() +} -- cgit 1.4.1-3-g733a5 From 0bb979bb852ca8889492f595245ec9f55d1c94e8 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 23 Oct 2015 20:36:38 +0200 Subject: Restore idempotence for chain formatting --- src/chains.rs | 8 ++++---- tests/source/chains.rs | 5 +++++ tests/target/chains-no-overflow.rs | 3 ++- tests/target/chains.rs | 8 +++++++- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4b6824a9073..ebe7aacf7cc 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -82,11 +82,11 @@ pub fn rewrite_chain(mut expr: &ast::Expr, let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. - let first_line_no = context.codemap.lookup_char_pos(subexpr_list[0].span.lo).line; + let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); + let first_span = context.snippet(subexpr_list[1].span); + let last_iter = last_span.chars().take_while(|c| c.is_whitespace()); - subexpr_list[1..] - .iter() - .any(|ex| context.codemap.lookup_char_pos(ex.span.hi).line != first_line_no) + first_span.chars().chain(last_iter).any(|c| c == '\n') } else { false }; diff --git a/tests/source/chains.rs b/tests/source/chains.rs index a50a9c51253..bf1ed31afe7 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -101,3 +101,8 @@ fn floaters() { a + match x { true => "yay!", false => "boo!" }.bar() } + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained( + self.id, constraints)).unwrap(); +} diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs index 9b1f244637d..400db5f8df5 100644 --- a/tests/target/chains-no-overflow.rs +++ b/tests/target/chains-no-overflow.rs @@ -2,7 +2,8 @@ // Test chain formatting without overflowing the last item. fn main() { - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc .ddddddddddddddddddddddddddd diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 9e195b42d6e..2fb201011a5 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -7,7 +7,8 @@ fn main() { .1 .foo(|x| x + 1); - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc .ddddddddddddddddddddddddddd @@ -126,3 +127,8 @@ fn floaters() { } .bar() } + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) + .unwrap(); +} -- cgit 1.4.1-3-g733a5 From ae5d7e6ba43ce099ac9a810efdbd855367459e1b Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 23 Oct 2015 20:44:46 +0200 Subject: Fix indentation for enum-style patterns --- src/patterns.rs | 5 +++-- tests/source/pattern.rs | 11 +++++++++++ tests/target/pattern.rs | 9 +++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 2e90f719853..6bba3d4c6e2 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -63,8 +63,9 @@ impl Rewrite for Pat { if pat_vec.is_empty() { Some(path_str) } else { - let width = try_opt!(width.checked_sub(path_str.len())); - let offset = offset + path_str.len(); + // 1 = ( + let width = try_opt!(width.checked_sub(path_str.len() + 1)); + let offset = offset + path_str.len() + 1; let items = itemize_list(context.codemap, pat_vec.iter(), ")", diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 4192d521085..930ffe2258f 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -12,3 +12,14 @@ fn main() { if let None = opt2 { panic!("oh noes"); } } + +impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { + fn mutate_fragment(&mut self, fragment: &mut Fragment) { + match **info { + GeneratedContentInfo::ContentItem( + ContentItem::Counter( + ref counter_name, + counter_style + ) + ) => {}}} +} diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index 38ebe675a40..aa121268daf 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -14,3 +14,12 @@ fn main() { panic!("oh noes"); } } + +impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { + fn mutate_fragment(&mut self, fragment: &mut Fragment) { + match **info { + GeneratedContentInfo::ContentItem(ContentItem::Counter(ref counter_name, + counter_style)) => {} + } + } +} -- cgit 1.4.1-3-g733a5 From b41965539ab85e782f1d5059b02c1c744237d384 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 23 Oct 2015 21:20:43 +0200 Subject: Bump match inner block indent a level --- src/expr.rs | 9 ++++----- tests/source/match.rs | 20 ++++++++++++++++++++ tests/target/match.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c619376f276..00d8ea0e0e2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -863,7 +863,7 @@ impl Rewrite for ast::Arm { // If the patterns were previously stacked, keep them stacked. let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi); let pat_str = context.snippet(pat_span); - vertical = pat_str.find('\n').is_some(); + vertical = pat_str.contains('\n'); } let pats_width = if vertical { @@ -922,10 +922,9 @@ impl Rewrite for ast::Arm { } let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let next_line_body = nop_block_collapse(body.rewrite(context, - body_budget, - context.block_indent - .block_indent(context.config)), + let indent = context.block_indent.block_indent(context.config); + let inner_context = &RewriteContext { block_indent: indent, ..*context }; + let next_line_body = nop_block_collapse(body.rewrite(inner_context, body_budget, indent), body_budget); let body_str = try_opt!(match_arm_heuristic(same_line_body.as_ref().map(|x| &x[..]), diff --git a/tests/source/match.rs b/tests/source/match.rs index 9ed25756d64..9277319295e 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -243,3 +243,23 @@ fn issue508() { Some(NodeTypeId::Element(_)) => false, } } + +fn issue496() {{{{ + match def { + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => + match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + Some(const_expr) => { x }}}}}}} + +fn issue494() { + { + match stmt.node { + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => + result.push( + StmtRef::Mirror( + Box::new(Stmt { span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref() } }))), + } + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 2e1a1b886ec..4df098eb4d1 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -247,3 +247,35 @@ fn issue508() { Some(NodeTypeId::Element(_)) => false, } } + +fn issue496() { + { + { + { + match def { + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => + match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + Some(const_expr) => { + x + } + }, + } + } + } + } +} + +fn issue494() { + { + match stmt.node { + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => + result.push(StmtRef::Mirror(Box::new(Stmt { + span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref(), + }, + }))), + } + } +} -- cgit 1.4.1-3-g733a5 From cda463275ed9642e231c92614a986af4a815b351 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Oct 2015 14:34:05 -0700 Subject: Use the log/env_logger crates from crates.io --- Cargo.lock | 11 +++++++++++ Cargo.toml | 2 ++ src/bin/rustfmt.rs | 3 +++ 3 files changed, 16 insertions(+) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index c00a673ebf6..61a586da4f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,6 +3,8 @@ name = "rustfmt" version = "0.0.1" dependencies = [ "diff 0.1.7 (git+https://github.com/utkarshkukreti/diff.rs.git)", + "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", @@ -24,6 +26,15 @@ name = "diff" version = "0.1.7" source = "git+https://github.com/utkarshkukreti/diff.rs.git#6edb9454bf4127087aced0fe07ab3ea6894083cb" +[[package]] +name = "env_logger" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index e8b81eb8482..fc8f0aa6026 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,5 +16,7 @@ regex = "0.1.41" term = "0.2.11" strings = { version = "0.0.1", git = "https://github.com/nrc/strings.rs.git" } diff = { git = "https://github.com/utkarshkukreti/diff.rs.git" } +log = "0.3.2" +env_logger = "0.3.1" [dev-dependencies] diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 01c292948df..9d8596e5e13 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -15,6 +15,7 @@ extern crate log; extern crate rustfmt; extern crate toml; +extern crate env_logger; use rustfmt::{WriteMode, run}; use rustfmt::config::Config; @@ -71,6 +72,8 @@ fn execute() -> i32 { fn main() { use std::io::Write; + let _ = env_logger::init(); + let exit_code = execute(); // Make sure standard output is flushed before we exit std::io::stdout().flush().unwrap(); -- cgit 1.4.1-3-g733a5 From 36abfe5dc25cd0c34579f2f20a2201fd87496e4d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Oct 2015 14:35:42 -0700 Subject: Remove usage of many unstable features This removes usage of: * PathExt * split_last * split_last_mut * catch_panic The catch_panic one was a little tricky as the ident interner needed to be cloned across threads (a little unsafely), but it should otherwise be good to go. --- src/bin/rustfmt.rs | 7 +++---- src/chains.rs | 12 ++++++------ src/comment.rs | 2 +- src/lib.rs | 7 ------- src/macros.rs | 30 +++++++++++++++++++++++++++--- 5 files changed, 37 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9d8596e5e13..40f55d61154 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -7,8 +7,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(path_ext)] -#![feature(rustc_private)] + #![cfg(not(test))] #[macro_use] @@ -21,7 +20,7 @@ use rustfmt::{WriteMode, run}; use rustfmt::config::Config; use std::env; -use std::fs::{File, PathExt}; +use std::fs::{self, File}; use std::io::{self, Read}; use std::path::PathBuf; use std::str::FromStr; @@ -31,7 +30,7 @@ fn lookup_project_file() -> io::Result { let mut current = try!(env::current_dir()); loop { let config_file = current.join("rustfmt.toml"); - if config_file.exists() { + if fs::metadata(&config_file).is_ok() { return Ok(config_file); } else { current = match current.parent() { diff --git a/src/chains.rs b/src/chains.rs index 4b6824a9073..4716f545b3f 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -72,11 +72,9 @@ pub fn rewrite_chain(mut expr: &ast::Expr, .collect::>>()); // Total of all items excluding the last. - let almost_total = rewrites.split_last() - .unwrap() - .1 - .iter() - .fold(0, |a, b| a + first_line_width(b)) + + let almost_total = rewrites[..rewrites.len() - 1] + .iter() + .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let total_width = almost_total + first_line_width(rewrites.last().unwrap()); let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { @@ -95,7 +93,9 @@ pub fn rewrite_chain(mut expr: &ast::Expr, match subexpr_list[0].node { ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) if context.config.chains_overflow_last => { - let (last, init) = rewrites.split_last_mut().unwrap(); + let len = rewrites.len(); + let (init, last) = rewrites.split_at_mut(len - 1); + let last = &mut last[0]; if init.iter().all(|s| !s.contains('\n')) && total_width <= width { let last_rewrite = width.checked_sub(almost_total) diff --git a/src/comment.rs b/src/comment.rs index 045d1cb5047..091b4293ad3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -437,7 +437,7 @@ mod test { } #[test] - #[rustfmt_skip] + #[cfg_attr(rustfmt, rustfmt_skip)] fn format_comments() { let config = Default::default(); assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100), diff --git a/src/lib.rs b/src/lib.rs index 03422a20c36..0e3dff21b69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,13 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rustc_private)] -#![feature(custom_attribute)] -#![feature(slice_splits)] -#![feature(slice_patterns)] -#![feature(catch_panic)] -#![allow(unused_attributes)] - // TODO we're going to allocate a whole bunch of temp Strings, is it worth // keeping some scratch mem for this and running our own StrPool? // TODO for lint violations of names, emit a refactor script diff --git a/src/macros.rs b/src/macros.rs index 9035b0c7d8b..37ae0af3a0b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -20,11 +20,14 @@ // and those with brackets will be formatted as array literals. use std::thread; +use std::collections::hash_map::{HashMap, Entry}; use syntax::ast; use syntax::parse::token::{Eof, Comma, Token}; use syntax::parse::{ParseSess, tts_to_parser}; use syntax::codemap::{mk_sp, BytePos}; +use syntax::parse::token; +use syntax::util::interner::StrInterner; use Indent; use rewrite::RewriteContext; @@ -82,13 +85,16 @@ pub fn rewrite_macro(mac: &ast::Mac, } let wrapped_tt_vec = ForceSend(mac.node.tts.clone()); + let my_interner = ForceSend(clone_interner()); + // Wrap expression parsing logic in a thread since the libsyntax parser // panics on failure, which we do not want to propagate. // The expression vector is wrapped in an Option inside a Result. - let expr_vec_result = thread::catch_panic(move || { + let expr_vec_result = thread::spawn(move || { let parse_session = ParseSess::new(); let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]); let mut expr_vec = vec![]; + token::get_ident_interner().reset(my_interner.0); loop { expr_vec.push(parser.parse_expr()); @@ -106,9 +112,10 @@ pub fn rewrite_macro(mac: &ast::Mac, } } - Some(expr_vec) + Some(ForceSend((expr_vec, clone_interner()))) }); - let expr_vec = try_opt!(try_opt!(expr_vec_result.ok())); + let (expr_vec, interner) = try_opt!(try_opt!(expr_vec_result.join().ok())).0; + token::get_ident_interner().reset(interner); match style { MacroStyle::Parens => { @@ -139,6 +146,23 @@ pub fn rewrite_macro(mac: &ast::Mac, } } +fn clone_interner() -> StrInterner { + let old = token::get_ident_interner(); + let new = StrInterner::new(); + let mut map = HashMap::new(); + for name in (0..old.len()).map(|i| i as u32).map(ast::Name) { + match map.entry(old.get(name)) { + Entry::Occupied(e) => { + new.gensym_copy(*e.get()); + } + Entry::Vacant(e) => { + e.insert(new.intern(&old.get(name))); + } + } + } + return new +} + fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { let snippet = context.snippet(mac.span); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); -- cgit 1.4.1-3-g733a5 From 579fb34417844cf6242c62ba0b6f2f9c72772ba0 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Oct 2015 14:37:13 -0700 Subject: Remove dependence on rustc/rustc_driver, use syntex Instead just parse manually with the `syntex_syntax` crate which is a clone of libsyntax on crates.io which builds on stable Rust. --- Cargo.lock | 24 ++++++++++++++++++ Cargo.toml | 1 + src/lib.rs | 77 ++++++++++----------------------------------------------- src/macros.rs | 72 +++++++++++++---------------------------------------- tests/system.rs | 3 +-- 5 files changed, 56 insertions(+), 121 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 61a586da4f3..d3f20f8b759 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ dependencies = [ "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", + "syntex_syntax 0.18.0 (git+https://github.com/serde-rs/syntex)", "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -21,6 +22,11 @@ dependencies = [ "memchr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bitflags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "diff" version = "0.1.7" @@ -93,6 +99,19 @@ dependencies = [ "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syntex_syntax" +version = "0.18.0" +source = "git+https://github.com/serde-rs/syntex#176ca5d8add606fac8d503b10c89ddb82f02d92b" +dependencies = [ + "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "term" version = "0.2.12" @@ -115,6 +134,11 @@ name = "unicode-segmentation" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index fc8f0aa6026..60df8ac6904 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ regex = "0.1.41" term = "0.2.11" strings = { version = "0.0.1", git = "https://github.com/nrc/strings.rs.git" } diff = { git = "https://github.com/utkarshkukreti/diff.rs.git" } +syntex_syntax = { git = "https://github.com/serde-rs/syntex" } log = "0.3.2" env_logger = "0.3.1" diff --git a/src/lib.rs b/src/lib.rs index 0e3dff21b69..51497e3b1c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,10 +15,7 @@ #[macro_use] extern crate log; -extern crate getopts; -extern crate rustc; -extern crate rustc_driver; -extern crate syntax; +extern crate syntex_syntax as syntax; extern crate rustc_serialize; extern crate strings; @@ -28,22 +25,15 @@ extern crate regex; extern crate diff; extern crate term; -use rustc::session::Session; -use rustc::session::config as rustc_config; -use rustc::session::config::Input; -use rustc_driver::{driver, CompilerCalls, Compilation}; - use syntax::ast; use syntax::codemap::{CodeMap, Span}; -use syntax::diagnostics; +use syntax::parse::{self, ParseSess}; use std::ops::{Add, Sub}; -use std::path::PathBuf; +use std::path::Path; use std::collections::HashMap; use std::fmt; use std::str::FromStr; -use std::rc::Rc; -use std::cell::RefCell; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; @@ -380,65 +370,24 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -struct RustFmtCalls { - config: Rc, - result: Rc>>, -} - -impl<'a> CompilerCalls<'a> for RustFmtCalls { - fn no_input(&mut self, - _: &getopts::Matches, - _: &rustc_config::Options, - _: &Option, - _: &Option, - _: &diagnostics::registry::Registry) - -> Option<(Input, Option)> { - panic!("No input supplied to RustFmt"); - } - - fn build_controller(&mut self, _: &Session) -> driver::CompileController<'a> { - let result = self.result.clone(); - let config = self.config.clone(); - - let mut control = driver::CompileController::basic(); - control.after_parse.stop = Compilation::Stop; - control.after_parse.callback = Box::new(move |state| { - let krate = state.krate.unwrap(); - let codemap = state.session.codemap(); - let mut file_map = fmt_ast(krate, codemap, &*config); - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newlines(&mut file_map); - - *result.borrow_mut() = Some(file_map); - }); +pub fn format(file: &Path, config: &Config) -> FileMap { + let parse_session = ParseSess::new(); + let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); + let mut file_map = fmt_ast(&krate, parse_session.codemap(), config); - control - } -} - -pub fn format(args: Vec, config: &Config) -> FileMap { - let result = Rc::new(RefCell::new(None)); - - { - let config = Rc::new(config.clone()); - let mut call_ctxt = RustFmtCalls { - config: config, - result: result.clone(), - }; - rustc_driver::run_compiler(&args, &mut call_ctxt); - } + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newlines(&mut file_map); - // Peel the union. - Rc::try_unwrap(result).ok().unwrap().into_inner().unwrap() + return file_map; } // args are the arguments passed on the command line, generally passed through // to the compiler. // write_mode determines what happens to the result of running rustfmt, see // WriteMode. -pub fn run(args: Vec, write_mode: WriteMode, config: &Config) { - let mut result = format(args, config); +pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { + let mut result = format(file, config); println!("{}", fmt_lines(&mut result, config)); diff --git a/src/macros.rs b/src/macros.rs index 37ae0af3a0b..bede00d6e9e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -19,15 +19,10 @@ // List-like invocations with parentheses will be formatted as function calls, // and those with brackets will be formatted as array literals. -use std::thread; -use std::collections::hash_map::{HashMap, Entry}; - use syntax::ast; use syntax::parse::token::{Eof, Comma, Token}; use syntax::parse::{ParseSess, tts_to_parser}; use syntax::codemap::{mk_sp, BytePos}; -use syntax::parse::token; -use syntax::util::interner::StrInterner; use Indent; use rewrite::RewriteContext; @@ -37,12 +32,6 @@ use utils::{wrap_str, span_after}; static FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; -// We need to pass `TokenTree`s to our expression parsing thread, but they are -// not `Send`. We wrap them in a `Send` container to force our will. -// FIXME: this is a pretty terrible hack. Any other solution would be preferred. -struct ForceSend(pub T); -unsafe impl Send for ForceSend {} - // FIXME: use the enum from libsyntax? #[derive(Clone, Copy)] enum MacroStyle { @@ -84,38 +73,28 @@ pub fn rewrite_macro(mac: &ast::Mac, }; } - let wrapped_tt_vec = ForceSend(mac.node.tts.clone()); - let my_interner = ForceSend(clone_interner()); - - // Wrap expression parsing logic in a thread since the libsyntax parser - // panics on failure, which we do not want to propagate. - // The expression vector is wrapped in an Option inside a Result. - let expr_vec_result = thread::spawn(move || { - let parse_session = ParseSess::new(); - let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]); - let mut expr_vec = vec![]; - token::get_ident_interner().reset(my_interner.0); + let parse_session = ParseSess::new(); + let mut parser = tts_to_parser(&parse_session, mac.node.tts.clone(), Vec::new()); + let mut expr_vec = Vec::new(); - loop { - expr_vec.push(parser.parse_expr()); + loop { + expr_vec.push(match parser.parse_expr_nopanic() { + Ok(expr) => expr, + Err(..) => return None, + }); - match parser.token { - Token::Eof => break, - Token::Comma => (), - _ => panic!("Macro not list-like, skiping..."), - } + match parser.token { + Token::Eof => break, + Token::Comma => (), + _ => return None, + } - let _ = parser.bump(); + let _ = parser.bump(); - if parser.token == Token::Eof { - return None; - } + if parser.token == Token::Eof { + return None; } - - Some(ForceSend((expr_vec, clone_interner()))) - }); - let (expr_vec, interner) = try_opt!(try_opt!(expr_vec_result.join().ok())).0; - token::get_ident_interner().reset(interner); + } match style { MacroStyle::Parens => { @@ -146,23 +125,6 @@ pub fn rewrite_macro(mac: &ast::Mac, } } -fn clone_interner() -> StrInterner { - let old = token::get_ident_interner(); - let new = StrInterner::new(); - let mut map = HashMap::new(); - for name in (0..old.len()).map(|i| i as u32).map(ast::Name) { - match map.entry(old.get(name)) { - Entry::Occupied(e) => { - new.gensym_copy(*e.get()); - } - Entry::Vacant(e) => { - e.insert(new.intern(&old.get(name))); - } - } - } - return new -} - fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { let snippet = context.snippet(mac.span); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); diff --git a/tests/system.rs b/tests/system.rs index b6dee149ed1..649ccdf5647 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -135,7 +135,6 @@ fn print_mismatches(result: HashMap>) { pub fn idempotent_check(filename: String) -> Result>> { let sig_comments = read_significant_comments(&filename); let mut config = get_config(sig_comments.get("config").map(|x| &(*x)[..])); - let args = vec!["rustfmt".to_owned(), filename]; for (key, val) in &sig_comments { if key != "target" && key != "config" { @@ -146,7 +145,7 @@ pub fn idempotent_check(filename: String) -> Result Date: Thu, 22 Oct 2015 14:38:16 -0700 Subject: Move option parsing to crates.io-based getopts crate Should help adding more options in the future as well! --- Cargo.lock | 6 +++++ Cargo.toml | 1 + src/bin/rustfmt.rs | 76 ++++++++++++++++++++++++++++-------------------------- 3 files changed, 47 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d3f20f8b759..66061bd1e25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,6 +4,7 @@ version = "0.0.1" dependencies = [ "diff 0.1.7 (git+https://github.com/utkarshkukreti/diff.rs.git)", "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -41,6 +42,11 @@ dependencies = [ "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "getopts" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index 60df8ac6904..ebd4e8e7f1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,6 @@ diff = { git = "https://github.com/utkarshkukreti/diff.rs.git" } syntex_syntax = { git = "https://github.com/serde-rs/syntex" } log = "0.3.2" env_logger = "0.3.1" +getopts = "0.2" [dev-dependencies] diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 40f55d61154..6b3405aa936 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -15,6 +15,7 @@ extern crate log; extern crate rustfmt; extern crate toml; extern crate env_logger; +extern crate getopts; use rustfmt::{WriteMode, run}; use rustfmt::config::Config; @@ -23,7 +24,8 @@ use std::env; use std::fs::{self, File}; use std::io::{self, Read}; use std::path::PathBuf; -use std::str::FromStr; + +use getopts::Options; // Try to find a project file in the current directory and its parents. fn lookup_project_file() -> io::Result { @@ -52,7 +54,7 @@ fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> { } fn execute() -> i32 { - let (args, write_mode) = match determine_params(std::env::args()) { + let (file, write_mode) = match determine_params(std::env::args().skip(1)) { Some(params) => params, None => return 1, }; @@ -65,7 +67,7 @@ fn execute() -> i32 { Err(_) => Default::default(), }; - run(args, write_mode, &config); + run(&file, write_mode, &config); 0 } @@ -83,50 +85,52 @@ fn main() { std::process::exit(exit_code); } -fn print_usage>(reason: S) { - println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[replace|overwrite|display|diff]] \ - ", - reason.into()); +fn print_usage(opts: &Options, reason: &str) { + let reason = format!("{}\nusage: {} [options] ", + reason, + env::current_exe().unwrap().display()); + println!("{}", opts.usage(&reason)); Config::print_docs(); } -fn determine_params(args: I) -> Option<(Vec, WriteMode)> +fn determine_params(args: I) -> Option<(PathBuf, WriteMode)> where I: Iterator { - let arg_prefix = "-"; - let write_mode_prefix = "--write-mode="; - let help_mode = "-h"; - let long_help_mode = "--help"; - let mut write_mode = WriteMode::Replace; - let mut rustc_args = Vec::new(); - - // The NewFile option currently isn't supported because it requires another - // parameter, but it can be added later. - for arg in args { - if arg.starts_with(write_mode_prefix) { - match FromStr::from_str(&arg[write_mode_prefix.len()..]) { - Ok(mode) => write_mode = mode, - Err(_) => { - print_usage("Unrecognized write mode"); + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optopt("", + "write-mode", + "mode to write in", + "[replace|overwrite|display|diff]"); + let matches = match opts.parse(args) { + Ok(m) => m, + Err(e) => { + print_usage(&opts, &e.to_string()); + return None; + } + }; + + if matches.opt_present("h") { + print_usage(&opts, ""); + } + + let write_mode = match matches.opt_str("write-mode") { + Some(mode) => { + match mode.parse() { + Ok(mode) => mode, + Err(..) => { + print_usage(&opts, "Unrecognized write mode"); return None; } } - } else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) { - print_usage(""); - return None; - } else if arg.starts_with(arg_prefix) { - print_usage("Invalid argument"); - return None; - } else { - // Pass everything else to rustc - rustc_args.push(arg); } - } + None => WriteMode::Replace, + }; - if rustc_args.len() < 2 { - print_usage("Please provide a file to be formatted"); + if matches.free.len() != 1 { + print_usage(&opts, "Please provide one file to format"); return None; } - Some((rustc_args, write_mode)) + Some((PathBuf::from(&matches.free[0]), write_mode)) } -- cgit 1.4.1-3-g733a5 From e6b7ad3e39f36db3168fd750f7e7b50df40997a8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 22 Oct 2015 15:02:53 -0700 Subject: Ignore #[cfg_attr(rustfmt, rustfmt_skip)] functions This adds to #[rustfmt_skip] but is usable on stable Rust! --- src/utils.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 0fd749a5471..fea385532d0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -75,6 +75,9 @@ pub fn last_line_width(s: &str) -> usize { fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, + MetaItem_::MetaList(ref s, ref l) => { + *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1]) + } _ => false, } } -- cgit 1.4.1-3-g733a5 From 2ec769709f8bf334b115b1ecbcc0054b9ed351ab Mon Sep 17 00:00:00 2001 From: defuz Date: Fri, 16 Oct 2015 11:08:47 +0300 Subject: Lookup rustfmt.toml file is relative from input file, not from current directory --- src/bin/rustfmt.rs | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 6b3405aa936..da8d7e7bf03 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -23,30 +23,37 @@ use rustfmt::config::Config; use std::env; use std::fs::{self, File}; use std::io::{self, Read}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use getopts::Options; -// Try to find a project file in the current directory and its parents. -fn lookup_project_file() -> io::Result { - let mut current = try!(env::current_dir()); +// Try to find a project file in the input file directory and its parents. +fn lookup_project_file(input_file: &Path) -> io::Result { + let mut current = if input_file.is_relative() { + try!(env::current_dir()).join(input_file) + } else { + input_file.to_path_buf() + }; + + // TODO: We should canonize path to properly handle its parents, + // but `canonicalize` function is unstable now (recently added API) + // current = try!(fs::canonicalize(current)); + loop { + // if the current directory has no parent, we're done searching + if !current.pop() { + return Err(io::Error::new(io::ErrorKind::NotFound, "config not found")); + } let config_file = current.join("rustfmt.toml"); if fs::metadata(&config_file).is_ok() { return Ok(config_file); - } else { - current = match current.parent() { - // if the current directory has no parent, we're done searching - None => return Err(io::Error::new(io::ErrorKind::NotFound, "config not found")), - Some(path) => path.to_path_buf(), - }; } } } // Try to find a project file. If it's found, read it. -fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> { - let path = try!(lookup_project_file()); +fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, String)> { + let path = try!(lookup_project_file(input_file)); let mut file = try!(File::open(&path)); let mut toml = String::new(); try!(file.read_to_string(&mut toml)); @@ -59,7 +66,7 @@ fn execute() -> i32 { None => return 1, }; - let config = match lookup_and_read_project_file() { + let config = match lookup_and_read_project_file(&file) { Ok((path, toml)) => { println!("Project config file: {}", path.display()); Config::from_toml(&toml) -- cgit 1.4.1-3-g733a5 From d135217db26bd9a2643e57170c3f459aa42e08e4 Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Wed, 21 Oct 2015 12:56:24 +0530 Subject: show rustfmt coverage! --- src/bin/rustfmt.rs | 2 +- src/expr.rs | 4 ++-- src/filemap.rs | 2 +- src/lib.rs | 13 ++++++++----- src/missed_spans.rs | 24 ++++++++++++++++++++++-- src/visitor.rs | 9 +++++++-- tests/system.rs | 2 +- 7 files changed, 42 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index da8d7e7bf03..60c1312b6c6 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -108,7 +108,7 @@ fn determine_params(args: I) -> Option<(PathBuf, WriteMode)> opts.optopt("", "write-mode", "mode to write in", - "[replace|overwrite|display|diff]"); + "[replace|overwrite|display|diff|coverage]"); let matches = match opts.parse(args) { Ok(m) => m, Err(e) => { diff --git a/src/expr.rs b/src/expr.rs index 00d8ea0e0e2..20a637bffca 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -422,7 +422,7 @@ impl Rewrite for ast::Block { return Some(user_str); } - let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config); + let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config, None); visitor.block_indent = context.block_indent; let prefix = match self.rules { @@ -833,7 +833,7 @@ impl Rewrite for ast::Arm { let attr_str = if !attrs.is_empty() { // We only use this visitor for the attributes, should we use it for // more? - let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config); + let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config, None); attr_visitor.block_indent = context.block_indent; attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { diff --git a/src/filemap.rs b/src/filemap.rs index d94c1501734..72174679386 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -100,7 +100,7 @@ fn write_file(text: &StringBuffer, let file = try!(File::create(&filename)); try!(write_system_newlines(file, text, config)); } - WriteMode::Display => { + WriteMode::Display | WriteMode::Coverage => { println!("{}:\n", filename); let stdout = stdout(); let stdout_lock = stdout.lock(); diff --git a/src/lib.rs b/src/lib.rs index 51497e3b1c3..33753524348 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -182,6 +182,8 @@ pub enum WriteMode { Diff, // Return the result as a mapping from filenames to Strings. Return, + // Display how much of the input file was processed + Coverage, } impl FromStr for WriteMode { @@ -193,6 +195,7 @@ impl FromStr for WriteMode { "display" => Ok(WriteMode::Display), "overwrite" => Ok(WriteMode::Overwrite), "diff" => Ok(WriteMode::Diff), + "coverage" => Ok(WriteMode::Coverage), _ => Err(()), } } @@ -277,11 +280,11 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config) -> FileMap { +fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config, mode: WriteMode) -> FileMap { let mut file_map = FileMap::new(); for (path, module) in modules::list_files(krate, codemap) { let path = path.to_str().unwrap(); - let mut visitor = FmtVisitor::from_codemap(codemap, config); + let mut visitor = FmtVisitor::from_codemap(codemap, config, Some(mode)); visitor.format_separate_mod(module, path); file_map.insert(path.to_owned(), visitor.buffer); } @@ -370,10 +373,10 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -pub fn format(file: &Path, config: &Config) -> FileMap { +pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { let parse_session = ParseSess::new(); let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); - let mut file_map = fmt_ast(&krate, parse_session.codemap(), config); + let mut file_map = fmt_ast(&krate, parse_session.codemap(), config, mode); // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. @@ -387,7 +390,7 @@ pub fn format(file: &Path, config: &Config) -> FileMap { // write_mode determines what happens to the result of running rustfmt, see // WriteMode. pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { - let mut result = format(file, config); + let mut result = format(file, config, write_mode); println!("{}", fmt_lines(&mut result, config)); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 04d3ac3366a..b83f07e05d7 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use WriteMode; use visitor::FmtVisitor; - use syntax::codemap::{self, BytePos, Span, Pos}; use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; @@ -80,7 +80,7 @@ impl<'a> FmtVisitor<'a> { fn write_snippet_inner(&mut self, big_snippet: &str, big_diff: usize, - snippet: &str, + old_snippet: &str, process_last_snippet: F) where F: Fn(&mut FmtVisitor, &str, &str) { @@ -91,6 +91,26 @@ impl<'a> FmtVisitor<'a> { let mut last_wspace = None; let mut rewrite_next_comment = true; + fn replace_chars(string: &str) -> String { + string.chars() + .map(|ch| { + match ch.is_whitespace() { + true => ch, + false => 'X', + } + }) + .collect() + } + + let replaced = match self.write_mode { + Some(mode) => match mode { + WriteMode::Coverage => replace_chars(old_snippet), + _ => old_snippet.to_owned(), + }, + None => old_snippet.to_owned(), + }; + let snippet = &*replaced; + for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { if let CodeCharKind::Comment = kind { let last_char = big_snippet[..(offset + big_diff)] diff --git a/src/visitor.rs b/src/visitor.rs index c58d16809aa..9a33fdae024 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -14,7 +14,7 @@ use syntax::visit; use strings::string_buffer::StringBuffer; -use Indent; +use {Indent, WriteMode}; use utils; use config::Config; use rewrite::{Rewrite, RewriteContext}; @@ -29,6 +29,7 @@ pub struct FmtVisitor<'a> { // TODO: RAII util for indenting pub block_indent: Indent, pub config: &'a Config, + pub write_mode: Option, } impl<'a> FmtVisitor<'a> { @@ -356,7 +357,10 @@ impl<'a> FmtVisitor<'a> { } } - pub fn from_codemap(codemap: &'a CodeMap, config: &'a Config) -> FmtVisitor<'a> { + pub fn from_codemap(codemap: &'a CodeMap, + config: &'a Config, + mode: Option) + -> FmtVisitor<'a> { FmtVisitor { codemap: codemap, buffer: StringBuffer::new(), @@ -366,6 +370,7 @@ impl<'a> FmtVisitor<'a> { alignment: 0, }, config: config, + write_mode: mode, } } diff --git a/tests/system.rs b/tests/system.rs index 649ccdf5647..6e9a4efe406 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -145,7 +145,7 @@ pub fn idempotent_check(filename: String) -> Result Date: Sat, 24 Oct 2015 12:19:58 +0200 Subject: Address some issues with multiline patterns in let statements --- src/expr.rs | 16 +++++-- src/items.rs | 110 ++++++++++++++++++---------------------------- src/lib.rs | 8 ++++ src/visitor.rs | 8 +++- tests/source/issue-510.rs | 39 ++++++++++++++++ tests/target/issue-510.rs | 43 ++++++++++++++++++ 6 files changed, 151 insertions(+), 73 deletions(-) create mode 100644 tests/source/issue-510.rs create mode 100644 tests/target/issue-510.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 20a637bffca..16c46f6bef1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1398,7 +1398,10 @@ pub fn rewrite_tuple<'a, R>(context: &RewriteContext, |item| item.span().lo, |item| item.span().hi, |item| { - let inner_width = context.config.max_width - indent.width() - 1; + let inner_width = try_opt!(context.config + .max_width + .checked_sub(indent.width() + + 1)); item.rewrite(context, inner_width, indent) }, span.lo + BytePos(1), // Remove parens @@ -1522,10 +1525,15 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, offset: Indent) -> Option { let mut result = lhs.into(); - + let last_line_width = last_line_width(&result) - + if result.contains('\n') { + offset.width() + } else { + 0 + }; // 1 = space between operator and rhs. - let max_width = try_opt!(width.checked_sub(result.len() + 1)); - let rhs = ex.rewrite(&context, max_width, offset + result.len() + 1); + let max_width = try_opt!(width.checked_sub(last_line_width + 1)); + let rhs = ex.rewrite(&context, max_width, offset + last_line_width + 1); match rhs { Some(new_str) => { diff --git a/src/items.rs b/src/items.rs index c8054b8d01f..e6b401d2ff3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -26,85 +26,59 @@ use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::print::pprust; use syntax::parse::token; -impl<'a> FmtVisitor<'a> { - pub fn visit_let(&mut self, local: &ast::Local, span: Span) { - self.format_missing_with_indent(span.lo); - - // New scope so we drop the borrow of self (context) in time to mutably - // borrow self to mutate its buffer. - let result = { - let context = self.get_context(); - let mut result = "let ".to_owned(); - let pattern_offset = self.block_indent + result.len(); - // 1 = ; - let pattern_width = match self.config - .max_width - .checked_sub(pattern_offset.width() + 1) { - Some(width) => width, - None => return, - }; +// Statements of the form +// let pat: ty = init; +impl Rewrite for ast::Local { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + let mut result = "let ".to_owned(); + let pattern_offset = offset + result.len(); + // 1 = ; + let pattern_width = try_opt!(width.checked_sub(pattern_offset.width() + 1)); - match local.pat.rewrite(&context, pattern_width, pattern_offset) { - Some(ref pat_string) => result.push_str(pat_string), - None => return, - } + let pat_str = try_opt!(self.pat.rewrite(&context, pattern_width, pattern_offset)); + result.push_str(&pat_str); - // String that is placed within the assignment pattern and expression. - let infix = { - let mut infix = String::new(); - - if let Some(ref ty) = local.ty { - // 2 = ": ".len() - // 1 = ; - let offset = self.block_indent + result.len() + 2; - let width = match self.config.max_width.checked_sub(offset.width() + 1) { - Some(w) => w, - None => return, - }; - let rewrite = ty.rewrite(&self.get_context(), width, offset); - - match rewrite { - Some(result) => { - infix.push_str(": "); - infix.push_str(&result); - } - None => return, - } - } + // String that is placed within the assignment pattern and expression. + let infix = { + let mut infix = String::new(); - if local.init.is_some() { - infix.push_str(" ="); - } + if let Some(ref ty) = self.ty { + // 2 = ": ".len() + // 1 = ; + let indent = offset + last_line_width(&result) + 2; + let budget = try_opt!(width.checked_sub(indent.width() + 1)); + let rewrite = try_opt!(ty.rewrite(context, budget, indent)); - infix - }; + infix.push_str(": "); + infix.push_str(&rewrite); + } - result.push_str(&infix); + if self.init.is_some() { + infix.push_str(" ="); + } - if let Some(ref ex) = local.init { - let max_width = self.config.max_width.checked_sub(context.block_indent.width() + 1); - let max_width = match max_width { - Some(width) => width, - None => return, - }; + infix + }; - // 1 = trailing semicolon; - let rhs = rewrite_assign_rhs(&context, result, ex, max_width, context.block_indent); + result.push_str(&infix); - match rhs { - Some(s) => s, - None => return, - } - } else { - result - } - }; + if let Some(ref ex) = self.init { + let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1)); - self.buffer.push_str(&result); - self.buffer.push_str(";"); - self.last_pos = span.hi; + // 1 = trailing semicolon; + result = try_opt!(rewrite_assign_rhs(&context, + result, + ex, + budget, + context.block_indent)); + } + + result.push(';'); + Some(result) } +} +impl<'a> FmtVisitor<'a> { pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { self.buffer.push_str("extern "); diff --git a/src/lib.rs b/src/lib.rs index 33753524348..a22e797fb68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,6 +168,14 @@ impl Add for Indent { } } +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment - rhs) + } +} + #[derive(Copy, Clone)] pub enum WriteMode { // Backups the original file and overwrites the orignal. diff --git a/src/visitor.rs b/src/visitor.rs index 9a33fdae024..bd30e80e5a9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -37,7 +37,13 @@ impl<'a> FmtVisitor<'a> { match stmt.node { ast::Stmt_::StmtDecl(ref decl, _) => { match decl.node { - ast::Decl_::DeclLocal(ref local) => self.visit_let(local, stmt.span), + ast::Decl_::DeclLocal(ref local) => { + let rewrite = { + let context = self.get_context(); + local.rewrite(&context, self.config.max_width, self.block_indent) + }; + self.push_rewrite(stmt.span, rewrite); + } ast::Decl_::DeclItem(ref item) => self.visit_item(item), } } diff --git a/tests/source/issue-510.rs b/tests/source/issue-510.rs new file mode 100644 index 00000000000..faf3d657ada --- /dev/null +++ b/tests/source/issue-510.rs @@ -0,0 +1,39 @@ +impl ISizeAndMarginsComputer for AbsoluteNonReplaced { +fn solve_inline_size_constraints(&self, +block: &mut BlockFlow, +input: &ISizeConstraintInput) +-> ISizeConstraintSolution { + +let (inline_start,inline_size,margin_inline_start,margin_inline_end) = +match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { +(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { +let margin_start = inline_start_margin.specified_or_zero(); +let margin_end = inline_end_margin.specified_or_zero(); +// Now it is the same situation as inline-start Specified and inline-end +// and inline-size Auto. +// +// Set inline-end to zero to calculate inline-size. +let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - +(margin_start + margin_end)); +(Au(0), inline_size, margin_start, margin_end) +} +}; + +// FIXME(#501): tuple width heuristic may not be optimal for patterns. + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = + block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; +} +} diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs new file mode 100644 index 00000000000..5b427ef1402 --- /dev/null +++ b/tests/target/issue-510.rs @@ -0,0 +1,43 @@ +impl ISizeAndMarginsComputer for AbsoluteNonReplaced { + fn solve_inline_size_constraints(&self, + block: &mut BlockFlow, + input: &ISizeConstraintInput) + -> ISizeConstraintSolution { + + let (inline_start, + inline_size, + margin_inline_start, + margin_inline_end) = match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; + + // FIXME(#501): tuple width heuristic may not be optimal for patterns. + let (inline_start, + inline_size, + margin_inline_start, + margin_inline_end) = match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; + } +} -- cgit 1.4.1-3-g733a5 From 4fa0b0bc57ff017cc1be62e2f98c8584d6319938 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 24 Oct 2015 15:30:26 +0200 Subject: Print configuration options once in help message --- src/bin/rustfmt.rs | 93 +++++++++++++++++++++++++++++++----------------------- src/config.rs | 2 +- 2 files changed, 54 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 60c1312b6c6..517bda69a3a 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -22,12 +22,22 @@ use rustfmt::config::Config; use std::env; use std::fs::{self, File}; -use std::io::{self, Read}; +use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use getopts::Options; -// Try to find a project file in the input file directory and its parents. +/// Rustfmt operations. +enum Operation { + /// Format a file and its child modules. + Format(PathBuf, WriteMode), + /// Print the help message. + Help, + /// Invalid program input, including reason. + InvalidInput(String), +} + +/// Try to find a project file in the input file directory and its parents. fn lookup_project_file(input_file: &Path) -> io::Result { let mut current = if input_file.is_relative() { try!(env::current_dir()).join(input_file) @@ -35,14 +45,14 @@ fn lookup_project_file(input_file: &Path) -> io::Result { input_file.to_path_buf() }; - // TODO: We should canonize path to properly handle its parents, + // FIXME: We should canonize path to properly handle its parents, // but `canonicalize` function is unstable now (recently added API) // current = try!(fs::canonicalize(current)); loop { - // if the current directory has no parent, we're done searching + // If the current directory has no parent, we're done searching. if !current.pop() { - return Err(io::Error::new(io::ErrorKind::NotFound, "config not found")); + return Err(io::Error::new(io::ErrorKind::NotFound, "Config not found")); } let config_file = current.join("rustfmt.toml"); if fs::metadata(&config_file).is_ok() { @@ -51,7 +61,7 @@ fn lookup_project_file(input_file: &Path) -> io::Result { } } -// Try to find a project file. If it's found, read it. +/// Try to find a project file. If it's found, read it. fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, String)> { let path = try!(lookup_project_file(input_file)); let mut file = try!(File::open(&path)); @@ -61,30 +71,46 @@ fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, Strin } fn execute() -> i32 { - let (file, write_mode) = match determine_params(std::env::args().skip(1)) { - Some(params) => params, - None => return 1, - }; + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optopt("", + "write-mode", + "mode to write in", + "[replace|overwrite|display|diff|coverage]"); + + let operation = determine_operation(&opts, env::args().skip(1)); - let config = match lookup_and_read_project_file(&file) { - Ok((path, toml)) => { - println!("Project config file: {}", path.display()); - Config::from_toml(&toml) + match operation { + Operation::InvalidInput(reason) => { + print_usage(&opts, &reason); + 1 } - Err(_) => Default::default(), - }; + Operation::Help => { + print_usage(&opts, ""); + 0 + } + Operation::Format(file, write_mode) => { + let config = match lookup_and_read_project_file(&file) { + Ok((path, toml)) => { + println!("Using rustfmt config file: {}", path.display()); + Config::from_toml(&toml) + } + Err(_) => Default::default(), + }; - run(&file, write_mode, &config); - 0 + run(&file, write_mode, &config); + 0 + } + } } fn main() { - use std::io::Write; let _ = env_logger::init(); - let exit_code = execute(); - // Make sure standard output is flushed before we exit + + // Make sure standard output is flushed before we exit. std::io::stdout().flush().unwrap(); + // Exit with given exit code. // // NOTE: This immediately terminates the process without doing any cleanup, @@ -100,44 +126,31 @@ fn print_usage(opts: &Options, reason: &str) { Config::print_docs(); } -fn determine_params(args: I) -> Option<(PathBuf, WriteMode)> +fn determine_operation(opts: &Options, args: I) -> Operation where I: Iterator { - let mut opts = Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optopt("", - "write-mode", - "mode to write in", - "[replace|overwrite|display|diff|coverage]"); let matches = match opts.parse(args) { Ok(m) => m, - Err(e) => { - print_usage(&opts, &e.to_string()); - return None; - } + Err(e) => return Operation::InvalidInput(e.to_string()), }; if matches.opt_present("h") { - print_usage(&opts, ""); + return Operation::Help; } let write_mode = match matches.opt_str("write-mode") { Some(mode) => { match mode.parse() { Ok(mode) => mode, - Err(..) => { - print_usage(&opts, "Unrecognized write mode"); - return None; - } + Err(..) => return Operation::InvalidInput("Unrecognized write mode".into()), } } None => WriteMode::Replace, }; if matches.free.len() != 1 { - print_usage(&opts, "Please provide one file to format"); - return None; + return Operation::InvalidInput("Please provide one file to format".into()); } - Some((PathBuf::from(&matches.free[0]), write_mode)) + Operation::Format(PathBuf::from(&matches.free[0]), write_mode) } diff --git a/src/config.rs b/src/config.rs index d788b17cfe7..068ba136bb5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -222,7 +222,7 @@ macro_rules! create_config { for _ in 0..max { space_str.push(' '); } - println!("\nConfiguration Options:"); + println!("Configuration Options:"); $( let name_raw = stringify!($i); let mut name_out = String::with_capacity(max); -- cgit 1.4.1-3-g733a5 From 1c235de97dc6105a06b525bde126ab2704d41093 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 27 Oct 2015 23:41:32 -0700 Subject: Fix crash speculatively parsing macro arguments as expressions. The problem is essentially that if we try to parse a token tree using a CodeMap different from the one the tree was originally parsed with, spans become nonsense. Since CodeMaps can't be cloned, we're basically forced to use the original ParseSess for additional parsing. Ideally, rustfmt would be a bit more clever and figure out how to parse macro arguments based on the definition of the macro itself, rather than just guessing that a particular token sequence looks like an expression, but this is good enough for now. Fixes #538. --- src/expr.rs | 6 ++++-- src/lib.rs | 22 ++++++++++++++++------ src/macros.rs | 5 ++--- src/rewrite.rs | 3 +++ src/visitor.rs | 17 +++++++++-------- tests/source/macros.rs | 2 ++ tests/target/macros.rs | 2 ++ 7 files changed, 38 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 16c46f6bef1..951b407ef43 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -422,7 +422,7 @@ impl Rewrite for ast::Block { return Some(user_str); } - let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config, None); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); visitor.block_indent = context.block_indent; let prefix = match self.rules { @@ -833,7 +833,9 @@ impl Rewrite for ast::Arm { let attr_str = if !attrs.is_empty() { // We only use this visitor for the attributes, should we use it for // more? - let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config, None); + let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, + context.config, + None); attr_visitor.block_indent = context.block_indent; attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { diff --git a/src/lib.rs b/src/lib.rs index a22e797fb68..c7c2178e098 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,8 @@ extern crate diff; extern crate term; use syntax::ast; -use syntax::codemap::{CodeMap, Span}; +use syntax::codemap::Span; +use syntax::diagnostic::{EmitterWriter, Handler}; use syntax::parse::{self, ParseSess}; use std::ops::{Add, Sub}; @@ -288,11 +289,15 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config, mode: WriteMode) -> FileMap { +fn fmt_ast(krate: &ast::Crate, + parse_session: &ParseSess, + config: &Config, + mode: WriteMode) + -> FileMap { let mut file_map = FileMap::new(); - for (path, module) in modules::list_files(krate, codemap) { + for (path, module) in modules::list_files(krate, parse_session.codemap()) { let path = path.to_str().unwrap(); - let mut visitor = FmtVisitor::from_codemap(codemap, config, Some(mode)); + let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode)); visitor.format_separate_mod(module, path); file_map.insert(path.to_owned(), visitor.buffer); } @@ -382,9 +387,14 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { - let parse_session = ParseSess::new(); + let mut parse_session = ParseSess::new(); let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); - let mut file_map = fmt_ast(&krate, parse_session.codemap(), config, mode); + + // Suppress error output after parsing. + let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); + parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); + + let mut file_map = fmt_ast(&krate, &parse_session, config, mode); // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. diff --git a/src/macros.rs b/src/macros.rs index bede00d6e9e..389e29014f0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -21,7 +21,7 @@ use syntax::ast; use syntax::parse::token::{Eof, Comma, Token}; -use syntax::parse::{ParseSess, tts_to_parser}; +use syntax::parse::tts_to_parser; use syntax::codemap::{mk_sp, BytePos}; use Indent; @@ -73,8 +73,7 @@ pub fn rewrite_macro(mac: &ast::Mac, }; } - let parse_session = ParseSess::new(); - let mut parser = tts_to_parser(&parse_session, mac.node.tts.clone(), Vec::new()); + let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new()); let mut expr_vec = Vec::new(); loop { diff --git a/src/rewrite.rs b/src/rewrite.rs index cf8be8004e1..5ca8d2e8241 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -11,6 +11,7 @@ // A generic trait to abstract the rewriting of an element (of the AST). use syntax::codemap::{CodeMap, Span}; +use syntax::parse::ParseSess; use Indent; use config::Config; @@ -27,6 +28,7 @@ pub trait Rewrite { } pub struct RewriteContext<'a> { + pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, pub config: &'a Config, // Indentation due to nesting of blocks. @@ -36,6 +38,7 @@ pub struct RewriteContext<'a> { impl<'a> RewriteContext<'a> { pub fn nested_context(&self) -> RewriteContext<'a> { RewriteContext { + parse_session: self.parse_session, codemap: self.codemap, config: self.config, block_indent: self.block_indent.block_indent(self.config), diff --git a/src/visitor.rs b/src/visitor.rs index bd30e80e5a9..534b2c877fd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -10,6 +10,7 @@ use syntax::ast; use syntax::codemap::{self, CodeMap, Span, BytePos}; +use syntax::parse::ParseSess; use syntax::visit; use strings::string_buffer::StringBuffer; @@ -23,6 +24,7 @@ use macros::rewrite_macro; use items::rewrite_static; pub struct FmtVisitor<'a> { + pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, pub buffer: StringBuffer, pub last_pos: BytePos, @@ -363,12 +365,13 @@ impl<'a> FmtVisitor<'a> { } } - pub fn from_codemap(codemap: &'a CodeMap, + pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config, mode: Option) -> FmtVisitor<'a> { FmtVisitor { - codemap: codemap, + parse_session: parse_session, + codemap: parse_session.codemap(), buffer: StringBuffer::new(), last_pos: BytePos(0), block_indent: Indent { @@ -461,13 +464,10 @@ impl<'a> FmtVisitor<'a> { let vis = utils::format_visibility(vis); let mut offset = self.block_indent; offset.alignment += vis.len() + "use ".len(); - let context = RewriteContext { - codemap: self.codemap, - config: self.config, - block_indent: self.block_indent, - }; // 1 = ";" - match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { + match vp.rewrite(&self.get_context(), + self.config.max_width - offset.width() - 1, + offset) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, span.lo); @@ -493,6 +493,7 @@ impl<'a> FmtVisitor<'a> { pub fn get_context(&self) -> RewriteContext { RewriteContext { + parse_session: self.parse_session, codemap: self.codemap, config: self.config, block_indent: self.block_indent, diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 8487e0c5deb..5b07596fdf9 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -27,4 +27,6 @@ fn main() { hamkaas!{ () }; macrowithbraces! {dont, format, me} + + x!(fn); } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index ac87b693246..2bcc6f9a339 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -30,4 +30,6 @@ fn main() { hamkaas!{ () }; macrowithbraces! {dont, format, me} + + x!(fn); } -- cgit 1.4.1-3-g733a5 From fcc62cbbe0b7b5f3ba0b5e5f206d84b0ebb6c5b7 Mon Sep 17 00:00:00 2001 From: Johann Date: Mon, 2 Nov 2015 20:45:45 +0100 Subject: Stdin support Adds support for receiving input from stdin in case no file was specified. This is useful for editor/IDE integrations and other tooling. To achieve clean output a new write-mode option called plain was added, this option is mandatory when using stdin. --- src/bin/rustfmt.rs | 48 ++++++++++++++++++++++++++++++++++++++++++------ src/filemap.rs | 15 ++++++++++----- src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 517bda69a3a..f1dda3b1a79 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,7 +17,7 @@ extern crate toml; extern crate env_logger; extern crate getopts; -use rustfmt::{WriteMode, run}; +use rustfmt::{WriteMode, run, run_from_stdin}; use rustfmt::config::Config; use std::env; @@ -35,6 +35,8 @@ enum Operation { Help, /// Invalid program input, including reason. InvalidInput(String), + /// No file specified, read from stdin + Stdin(String, WriteMode), } /// Try to find a project file in the input file directory and its parents. @@ -76,7 +78,7 @@ fn execute() -> i32 { opts.optopt("", "write-mode", "mode to write in", - "[replace|overwrite|display|diff|coverage]"); + "[replace|overwrite|display|plain|diff|coverage]"); let operation = determine_operation(&opts, env::args().skip(1)); @@ -89,6 +91,18 @@ fn execute() -> i32 { print_usage(&opts, ""); 0 } + Operation::Stdin(input, write_mode) => { + // try to read config from local directory + let config = match lookup_and_read_project_file(&Path::new(".")) { + Ok((path, toml)) => { + Config::from_toml(&toml) + } + Err(_) => Default::default(), + }; + + run_from_stdin(input, write_mode, &config); + 0 + } Operation::Format(file, write_mode) => { let config = match lookup_and_read_project_file(&file) { Ok((path, toml)) => { @@ -138,6 +152,32 @@ fn determine_operation(opts: &Options, args: I) -> Operation return Operation::Help; } + // if no file argument is supplied, read from stdin + if matches.free.len() != 1 { + + // make sure the write mode is plain or not set + // (the other options would require a file) + match matches.opt_str("write-mode") { + Some(mode) => { + match mode.parse() { + Ok(WriteMode::Plain) => (), + _ => return Operation::InvalidInput("Using stdin requires write-mode to be \ + plain" + .into()), + } + } + _ => (), + } + + let mut buffer = String::new(); + match io::stdin().read_to_string(&mut buffer) { + Ok(..) => (), + Err(e) => return Operation::InvalidInput(e.to_string()), + } + + return Operation::Stdin(buffer, WriteMode::Plain); + } + let write_mode = match matches.opt_str("write-mode") { Some(mode) => { match mode.parse() { @@ -148,9 +188,5 @@ fn determine_operation(opts: &Options, args: I) -> Operation None => WriteMode::Replace, }; - if matches.free.len() != 1 { - return Operation::InvalidInput("Please provide one file to format".into()); - } - Operation::Format(PathBuf::from(&matches.free[0]), write_mode) } diff --git a/src/filemap.rs b/src/filemap.rs index 72174679386..a11b89bc54b 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -46,11 +46,11 @@ pub fn write_all_files(file_map: &FileMap, Ok(result) } -fn write_file(text: &StringBuffer, - filename: &str, - mode: WriteMode, - config: &Config) - -> Result, io::Error> { +pub fn write_file(text: &StringBuffer, + filename: &str, + mode: WriteMode, + config: &Config) + -> Result, io::Error> { // prints all newlines either as `\n` or as `\r\n` fn write_system_newlines(mut writer: T, @@ -100,6 +100,11 @@ fn write_file(text: &StringBuffer, let file = try!(File::create(&filename)); try!(write_system_newlines(file, text, config)); } + WriteMode::Plain => { + let stdout = stdout(); + let stdout_lock = stdout.lock(); + try!(write_system_newlines(stdout_lock, text, config)); + } WriteMode::Display | WriteMode::Coverage => { println!("{}:\n", filename); let stdout = stdout(); diff --git a/src/lib.rs b/src/lib.rs index c7c2178e098..4c7b3cbd249 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -193,6 +193,8 @@ pub enum WriteMode { Return, // Display how much of the input file was processed Coverage, + // Unfancy stdout + Plain, } impl FromStr for WriteMode { @@ -205,6 +207,7 @@ impl FromStr for WriteMode { "overwrite" => Ok(WriteMode::Overwrite), "diff" => Ok(WriteMode::Diff), "coverage" => Ok(WriteMode::Coverage), + "plain" => Ok(WriteMode::Plain), _ => Err(()), } } @@ -386,6 +389,33 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } +pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap { + let path = "stdin"; + let mut parse_session = ParseSess::new(); + let krate = parse::parse_crate_from_source_str(path.to_owned(), + input, + Vec::new(), + &parse_session); + + // Suppress error output after parsing. + let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); + parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); + + // FIXME: we still use a FileMap even though we only have + // one file, because fmt_lines requires a FileMap + let mut file_map = FileMap::new(); + + // do the actual formatting + let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode)); + visitor.format_separate_mod(&krate.module, path); + + // append final newline + visitor.buffer.push_str("\n"); + file_map.insert(path.to_owned(), visitor.buffer); + + return file_map; +} + pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { let mut parse_session = ParseSess::new(); let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); @@ -418,3 +448,15 @@ pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { println!("Error writing files: {}", msg); } } + +// Similar to run, but takes an input String instead of a file to format +pub fn run_from_stdin(input: String, mode: WriteMode, config: &Config) { + let mut result = format_string(input, config, mode); + fmt_lines(&mut result, config); + + let write_result = filemap::write_file(&result["stdin"], "stdin", mode, config); + + if let Err(msg) = write_result { + panic!("Error writing to stdout: {}", msg); + } +} -- cgit 1.4.1-3-g733a5 From 154e20a04f7b3261c2d94e18f9abd39a056f6bef Mon Sep 17 00:00:00 2001 From: Johann Date: Tue, 3 Nov 2015 09:16:33 +0100 Subject: Address review concerns --- src/bin/rustfmt.rs | 21 ++++----------------- src/filemap.rs | 8 ++++---- 2 files changed, 8 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index f1dda3b1a79..b8eacc2bcd0 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -77,8 +77,8 @@ fn execute() -> i32 { opts.optflag("h", "help", "show this message"); opts.optopt("", "write-mode", - "mode to write in", - "[replace|overwrite|display|plain|diff|coverage]"); + "mode to write in (not usable when piping from stdin)", + "[replace|overwrite|display|diff|coverage]"); let operation = determine_operation(&opts, env::args().skip(1)); @@ -153,21 +153,7 @@ fn determine_operation(opts: &Options, args: I) -> Operation } // if no file argument is supplied, read from stdin - if matches.free.len() != 1 { - - // make sure the write mode is plain or not set - // (the other options would require a file) - match matches.opt_str("write-mode") { - Some(mode) => { - match mode.parse() { - Ok(WriteMode::Plain) => (), - _ => return Operation::InvalidInput("Using stdin requires write-mode to be \ - plain" - .into()), - } - } - _ => (), - } + if matches.free.len() == 0 { let mut buffer = String::new(); match io::stdin().read_to_string(&mut buffer) { @@ -175,6 +161,7 @@ fn determine_operation(opts: &Options, args: I) -> Operation Err(e) => return Operation::InvalidInput(e.to_string()), } + // WriteMode is always plain for Stdin return Operation::Stdin(buffer, WriteMode::Plain); } diff --git a/src/filemap.rs b/src/filemap.rs index a11b89bc54b..3f1a867f385 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -102,14 +102,14 @@ pub fn write_file(text: &StringBuffer, } WriteMode::Plain => { let stdout = stdout(); - let stdout_lock = stdout.lock(); - try!(write_system_newlines(stdout_lock, text, config)); + let stdout = stdout.lock(); + try!(write_system_newlines(stdout, text, config)); } WriteMode::Display | WriteMode::Coverage => { println!("{}:\n", filename); let stdout = stdout(); - let stdout_lock = stdout.lock(); - try!(write_system_newlines(stdout_lock, text, config)); + let stdout = stdout.lock(); + try!(write_system_newlines(stdout, text, config)); } WriteMode::Diff => { println!("Diff of {}:\n", filename); -- cgit 1.4.1-3-g733a5 From 2aa35f0f6deb1f24c508077e877d1bf95bcc282b Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Tue, 3 Nov 2015 23:14:37 +0100 Subject: Honor "enum_trailing_comma" option. Fixes #556 --- src/items.rs | 2 +- src/lists.rs | 10 +++++++++ tests/source/enum-no_trailing_comma.rs | 41 ++++++++++++++++++++++++++++++++++ tests/target/enum-no_trailing_comma.rs | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/source/enum-no_trailing_comma.rs create mode 100644 tests/target/enum-no_trailing_comma.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e6b401d2ff3..fa15eeca3ac 100644 --- a/src/items.rs +++ b/src/items.rs @@ -693,7 +693,7 @@ impl<'a> FmtVisitor<'a> { let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", - trailing_separator: SeparatorTactic::Always, + trailing_separator: SeparatorTactic::from_bool(self.config.enum_trailing_comma), indent: self.block_indent, width: budget, ends_with_newline: true, diff --git a/src/lists.rs b/src/lists.rs index 8182189178a..b05e4d46066 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -46,6 +46,16 @@ pub enum SeparatorTactic { impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical); +impl SeparatorTactic { + pub fn from_bool(b: bool) -> SeparatorTactic { + if b { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } +} + pub struct ListFormatting<'a> { pub tactic: DefinitiveListTactic, pub separator: &'a str, diff --git a/tests/source/enum-no_trailing_comma.rs b/tests/source/enum-no_trailing_comma.rs new file mode 100644 index 00000000000..4b0347ab526 --- /dev/null +++ b/tests/source/enum-no_trailing_comma.rs @@ -0,0 +1,41 @@ +// rustfmt-enum_trailing_comma: false + +enum X { + A, + B, +} + +enum Y { + A, + B +} + +enum TupX { + A(u32), + B(i32, u16), +} + +enum TupY { + A(u32), + B(i32, u16) +} + +enum StructX { + A { + s: u16, + }, + B { + u: u32, + i: i32, + }, +} + +enum StructY { + A { + s: u16, + }, + B { + u: u32, + i: i32, + } +} diff --git a/tests/target/enum-no_trailing_comma.rs b/tests/target/enum-no_trailing_comma.rs new file mode 100644 index 00000000000..4ad7d1f12d7 --- /dev/null +++ b/tests/target/enum-no_trailing_comma.rs @@ -0,0 +1,41 @@ +// rustfmt-enum_trailing_comma: false + +enum X { + A, + B +} + +enum Y { + A, + B +} + +enum TupX { + A(u32), + B(i32, u16) +} + +enum TupY { + A(u32), + B(i32, u16) +} + +enum StructX { + A { + s: u16, + }, + B { + u: u32, + i: i32, + } +} + +enum StructY { + A { + s: u16, + }, + B { + u: u32, + i: i32, + } +} -- cgit 1.4.1-3-g733a5 From 67f0b00112f6f9fc55e740bc36928016603f6342 Mon Sep 17 00:00:00 2001 From: Mitsutaka Mimura Date: Thu, 5 Nov 2015 08:14:55 +0900 Subject: fix unused variable `path` warning --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index b8eacc2bcd0..9528105124f 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -94,7 +94,7 @@ fn execute() -> i32 { Operation::Stdin(input, write_mode) => { // try to read config from local directory let config = match lookup_and_read_project_file(&Path::new(".")) { - Ok((path, toml)) => { + Ok((_, toml)) => { Config::from_toml(&toml) } Err(_) => Default::default(), -- cgit 1.4.1-3-g733a5 From ae13bbcc98af5040aac39f4237ce3ff363a19974 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sat, 7 Nov 2015 19:03:25 -0500 Subject: Move config help to dedicated --config-help flag The existing help output is very verbose, overflowing a 50+ line terminal. This moves the configuration options to a separate help flag to make a mistyped command less annoying! --- src/bin/rustfmt.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9528105124f..2789b5f6cdd 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -33,6 +33,8 @@ enum Operation { Format(PathBuf, WriteMode), /// Print the help message. Help, + /// Print detailed configuration help. + ConfigHelp, /// Invalid program input, including reason. InvalidInput(String), /// No file specified, read from stdin @@ -80,6 +82,10 @@ fn execute() -> i32 { "mode to write in (not usable when piping from stdin)", "[replace|overwrite|display|diff|coverage]"); + opts.optflag("", + "config-help", + "show details of rustfmt configuration options"); + let operation = determine_operation(&opts, env::args().skip(1)); match operation { @@ -91,6 +97,10 @@ fn execute() -> i32 { print_usage(&opts, ""); 0 } + Operation::ConfigHelp => { + Config::print_docs(); + 0 + } Operation::Stdin(input, write_mode) => { // try to read config from local directory let config = match lookup_and_read_project_file(&Path::new(".")) { @@ -137,7 +147,6 @@ fn print_usage(opts: &Options, reason: &str) { reason, env::current_exe().unwrap().display()); println!("{}", opts.usage(&reason)); - Config::print_docs(); } fn determine_operation(opts: &Options, args: I) -> Operation @@ -152,6 +161,10 @@ fn determine_operation(opts: &Options, args: I) -> Operation return Operation::Help; } + if matches.opt_present("config-help") { + return Operation::ConfigHelp; + } + // if no file argument is supplied, read from stdin if matches.free.len() == 0 { -- cgit 1.4.1-3-g733a5 From 3dc0b804f1a50871d2a5187492ba92421727799c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Nov 2015 13:23:19 +1300 Subject: Don't strip semi-colons from expressions with non-void type since it can change semantics --- src/visitor.rs | 6 +----- tests/target/expr.rs | 4 ++-- tests/target/match.rs | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 534b2c877fd..6114dfff077 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -507,12 +507,8 @@ fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { match expr.node { ast::Expr_::ExprWhile(..) | ast::Expr_::ExprWhileLet(..) | - ast::Expr_::ExprIf(..) | - ast::Expr_::ExprIfLet(..) | - ast::Expr_::ExprBlock(..) | ast::Expr_::ExprLoop(..) | - ast::Expr_::ExprForLoop(..) | - ast::Expr_::ExprMatch(..) => false, + ast::Expr_::ExprForLoop(..) => false, _ => true, } } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 4b4afaa99e5..3bda26e745f 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -40,7 +40,7 @@ fn foo() -> bool { result } else { 4 - } + }; if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { // Nothing @@ -253,5 +253,5 @@ fn repeats() { fn blocks() { if 1 + 1 == 2 { println!("yay arithmetix!"); - } + }; } diff --git a/tests/target/match.rs b/tests/target/match.rs index 4df098eb4d1..1d6842d358a 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -228,7 +228,7 @@ fn issue383() { match resolution.last_private { LastImport{..} => false, _ => true, - } + }; } fn issue507() { -- cgit 1.4.1-3-g733a5 From bcda2824a2a798b2a9b6065c67171811d7b7bc5b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Nov 2015 19:00:04 +1300 Subject: Format tuple structs better closes #546 --- src/items.rs | 210 +++++++++++++++++++++++++++++++++++------------- tests/source/structs.rs | 13 +++ tests/target/structs.rs | 23 ++++++ 3 files changed, 189 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index fa15eeca3ac..e2484f8298e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -440,7 +440,8 @@ impl<'a> FmtVisitor<'a> { self.config, indent, where_density, - span.hi)); + "{", + Some(span.hi))); result.push_str(&where_clause_str); Some((result, force_new_line_for_brace)) @@ -636,7 +637,8 @@ impl<'a> FmtVisitor<'a> { let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); let generics_str = self.format_generics(generics, - " {", + "{", + "{", self.block_indent, self.block_indent.block_indent(self.config), mk_sp(span.lo, body_start)) @@ -768,33 +770,58 @@ impl<'a> FmtVisitor<'a> { span: Span, offset: Indent) -> Option { + match *struct_def { + ast::VariantData::Unit(..) => { + self.format_unit_struct(item_name, ident, vis) + } + ast::VariantData::Tuple(ref fields, _) => { + self.format_tuple_struct(item_name, ident, vis, fields, generics, span, offset) + } + ast::VariantData::Struct(ref fields, _) => { + self.format_struct_struct(item_name, ident, vis, fields, generics, span, offset) + } + } + } + + fn format_unit_struct(&self, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility) + -> Option { let mut result = String::with_capacity(1024); let header_str = self.format_header(item_name, ident, vis); result.push_str(&header_str); + result.push(';'); + return Some(result); + } - let (fields, body_lo, opener, terminator) = match *struct_def { - ast::VariantData::Unit(..) => { - result.push(';'); - return Some(result); - } - ast::VariantData::Tuple(ref vec, _) => { - (vec, vec[0].span.lo, "(", ")") - } - ast::VariantData::Struct(ref vec, _) => { - (vec, span_after(span, "{", self.codemap), " {", "}") - } - }; + fn format_struct_struct(&self, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + fields: &[ast::StructField], + generics: Option<&ast::Generics>, + span: Span, + offset: Indent) + -> Option { + let mut result = String::with_capacity(1024); + + let header_str = self.format_header(item_name, ident, vis); + result.push_str(&header_str); + + let body_lo = span_after(span, "{", self.codemap); let generics_str = match generics { Some(g) => { try_opt!(self.format_generics(g, - opener, + "{", + "{", offset, offset + header_str.len(), mk_sp(span.lo, body_lo))) } - None => opener.to_owned(), + None => " {".to_owned(), }; result.push_str(&generics_str); @@ -804,18 +831,90 @@ impl<'a> FmtVisitor<'a> { return Some(result); } - let item_indent = if let ast::VariantData::Tuple(..) = *struct_def { - self.block_indent + result.len() - } else { - offset.block_indent(self.config) + let item_indent = offset.block_indent(self.config); + // 2 = "," + let item_budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 1)); + + let context = self.get_context(); + let items = itemize_list(self.codemap, + fields.iter(), + "}", + |field| { + // Include attributes and doc comments, if present + if !field.node.attrs.is_empty() { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.node.ty.span.hi, + |field| field.rewrite(&context, item_budget, item_indent), + span_after(span, "{", self.codemap), + span.hi); + // 1 = , + let budget = self.config.max_width - offset.width() + self.config.tab_spaces - 1; + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: self.config.struct_trailing_comma, + indent: item_indent, + width: budget, + ends_with_newline: true, + config: self.config, + }; + Some(format!("{}\n{}{}\n{}}}", + result, + offset.block_indent(self.config).to_string(self.config), + try_opt!(write_list(items, &fmt)), + offset.to_string(self.config))) + } + + fn format_tuple_struct(&self, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + fields: &[ast::StructField], + generics: Option<&ast::Generics>, + span: Span, + offset: Indent) + -> Option { + assert!(!fields.is_empty(), "Tuple struct with no fields?"); + let mut result = String::with_capacity(1024); + + let header_str = self.format_header(item_name, ident, vis); + result.push_str(&header_str); + + let body_lo = fields[0].span.lo; + + let (generics_str, where_clause_str) = match generics { + Some(ref generics) => { + let generics_str = try_opt!(self.rewrite_generics(generics, + offset, + offset + header_str.len(), + mk_sp(span.lo, body_lo))); + + let where_clause_str = try_opt!(self.rewrite_where_clause(&generics.where_clause, + self.config, + self.block_indent, + Density::Compressed, + ";", + None)); + + (generics_str, where_clause_str) + } + None => ("".to_owned(), "".to_owned()), }; - // 2 = ");" or "," + result.push_str(&generics_str); + result.push('('); + + let item_indent = self.block_indent + result.len(); + // 2 = ");" let item_budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 2)); let context = self.get_context(); let items = itemize_list(self.codemap, fields.iter(), - terminator, + ")", |field| { // Include attributes and doc comments, if present if !field.node.attrs.is_empty() { @@ -826,37 +925,25 @@ impl<'a> FmtVisitor<'a> { }, |field| field.node.ty.span.hi, |field| field.rewrite(&context, item_budget, item_indent), - span_after(span, opener.trim(), self.codemap), + span_after(span, "(", self.codemap), span.hi); - match *struct_def { - ast::VariantData::Tuple(..) => { - // 2 = ); - let budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 2)); - let rewrite = try_opt!(format_item_list(items, budget, item_indent, self.config)); - result.push_str(&rewrite); - result.push(')'); - Some(result) - } - ast::VariantData::Struct(..) => { - // 1 = , - let budget = self.config.max_width - offset.width() + self.config.tab_spaces - 1; - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: ",", - trailing_separator: self.config.struct_trailing_comma, - indent: item_indent, - width: budget, - ends_with_newline: true, - config: self.config, - }; - Some(format!("{}\n{}{}\n{}}}", - result, - offset.block_indent(self.config).to_string(self.config), - try_opt!(write_list(items, &fmt)), - offset.to_string(self.config))) - } - _ => unreachable!(), + let body = try_opt!(format_item_list(items, item_budget, item_indent, self.config)); + result.push_str(&body); + result.push(')'); + + if where_clause_str.len() > 0 && !where_clause_str.contains('\n') && + (result.contains('\n') || + self.block_indent.width() + result.len() + where_clause_str.len() + 1 > + self.config.max_width) { + // We need to put the where clause on a new line, but we didn'to_string + // know that earlier, so the where clause will not be indented properly. + result.push('\n'); + result.push_str(&(self.block_indent + (self.config.tab_spaces - 1)) + .to_string(self.config)); } + result.push_str(&where_clause_str); + + Some(result) } fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { @@ -866,6 +953,7 @@ impl<'a> FmtVisitor<'a> { fn format_generics(&self, generics: &ast::Generics, opener: &str, + terminator: &str, offset: Indent, generics_offset: Indent, span: Span) @@ -877,12 +965,14 @@ impl<'a> FmtVisitor<'a> { self.config, self.block_indent, Density::Tall, - span.hi)); + terminator, + Some(span.hi))); result.push_str(&where_clause_str); result.push_str(&self.block_indent.to_string(self.config)); result.push('\n'); - result.push_str(opener.trim()); + result.push_str(opener); } else { + result.push(' '); result.push_str(opener); } @@ -938,7 +1028,7 @@ impl<'a> FmtVisitor<'a> { |&(_, ref str)| str.clone(), span_after(span, "<", self.codemap), span.hi); - let list_str = try_opt!(::lists::format_item_list(items, h_budget, offset, self.config)); + let list_str = try_opt!(format_item_list(items, h_budget, offset, self.config)); Some(format!("<{}>", list_str)) } @@ -948,7 +1038,8 @@ impl<'a> FmtVisitor<'a> { config: &Config, indent: Indent, density: Density, - span_end: BytePos) + terminator: &str, + span_end: Option) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); @@ -973,16 +1064,21 @@ impl<'a> FmtVisitor<'a> { let budget = self.config.max_width - offset.width(); let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; + let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list(self.codemap, where_clause.predicates.iter(), - "{", + terminator, |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, |pred| pred.rewrite(&context, budget, offset), span_start, span_end); let item_vec = items.collect::>(); - // FIXME: we don't need to collect here if the where_layout isnt + // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. let tactic = definitive_tactic(&item_vec, self.config.where_layout, budget); diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 2bdfe7325bc..ccf0b42b8ad 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -121,3 +121,16 @@ struct Deep { Type, NodeType>, } + +struct Foo(T); +struct Foo(T) where T: Copy, T: Eq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU); diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 4bc8c6bbe44..d8a8a921e4c 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -117,3 +117,26 @@ struct Deep { Type, NodeType>, } + +struct Foo(T); +struct Foo(T) + where T: Copy, + T: Eq; +struct Foo(TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) + where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU) + where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU, // Bar + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU); -- cgit 1.4.1-3-g733a5 From b7d61254a7c2b5fa9a03acc6b91445e72d7ee280 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 10 Nov 2015 08:03:01 +1300 Subject: Option to disable line breaking in comments Set to false by default for now, since we are having a lot of problems with comments. We should set to true once we have a better algorithm. --- src/comment.rs | 5 +++-- src/config.rs | 2 +- tests/source/attrib.rs | 1 + tests/source/comment.rs | 2 ++ tests/source/comment2.rs | 2 ++ tests/source/comment3.rs | 2 ++ tests/source/enum.rs | 1 + tests/source/expr.rs | 1 + tests/source/hard-tabs.rs | 1 + tests/source/multiple.rs | 1 + tests/source/struct_lits.rs | 1 + tests/source/struct_lits_multiline.rs | 1 + tests/source/struct_lits_visual.rs | 1 + tests/source/struct_lits_visual_multiline.rs | 1 + tests/source/structs.rs | 1 + tests/target/attrib.rs | 1 + tests/target/comment.rs | 2 ++ tests/target/comment2.rs | 2 ++ tests/target/comment3.rs | 2 ++ tests/target/enum.rs | 1 + tests/target/expr.rs | 1 + tests/target/hard-tabs.rs | 1 + tests/target/multiple.rs | 1 + tests/target/struct_lits.rs | 1 + tests/target/struct_lits_multiline.rs | 1 + tests/target/struct_lits_visual.rs | 1 + tests/target/struct_lits_visual_multiline.rs | 1 + tests/target/structs.rs | 1 + 28 files changed, 36 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 091b4293ad3..eb6c5fc75ec 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -81,7 +81,7 @@ pub fn rewrite_comment(orig: &str, result.push_str(line_start); } - if line.len() > max_chars { + if config.wrap_comments && line.len() > max_chars { let rewrite = try_opt!(rewrite_string(line, &fmt)); result.push_str(&rewrite); } else { @@ -439,7 +439,8 @@ mod test { #[test] #[cfg_attr(rustfmt, rustfmt_skip)] fn format_comments() { - let config = Default::default(); + let mut config: ::config::Config = Default::default(); + config.wrap_comments = true; assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100), &config).unwrap()); assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, diff --git a/src/config.rs b/src/config.rs index 068ba136bb5..9f260f93ab8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -294,11 +294,11 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_base_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on chain base"; - // Alphabetically, case sensitive. reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; format_strings: bool, true, "Format string literals, or leave as is"; chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; + wrap_comments: bool, false, "Break comments to fit on the line"; } diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index ac44a6504fd..a47c2507156 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Test attributes and doc comments are preserved. /// Blah blah blah. diff --git a/tests/source/comment.rs b/tests/source/comment.rs index 34b5de79b75..8de3c2ed1cd 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -1,3 +1,5 @@ +// rustfmt-wrap_comments: true + //! Doc comment fn test() { // comment diff --git a/tests/source/comment2.rs b/tests/source/comment2.rs index 81478621bd9..d68bb5483dc 100644 --- a/tests/source/comment2.rs +++ b/tests/source/comment2.rs @@ -1,2 +1,4 @@ +// rustfmt-wrap_comments: true + /// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. pub mod foo {} diff --git a/tests/source/comment3.rs b/tests/source/comment3.rs index ed54605f727..f19a8586334 100644 --- a/tests/source/comment3.rs +++ b/tests/source/comment3.rs @@ -1,3 +1,5 @@ +// rustfmt-wrap_comments: true + //! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. pub mod foo {} diff --git a/tests/source/enum.rs b/tests/source/enum.rs index eba75877277..e55da640d98 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Enums test #[atrr] diff --git a/tests/source/expr.rs b/tests/source/expr.rs index b5a22479058..26b22ed29be 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Test expressions fn foo() -> bool { diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs index d9a46800246..290dbfc616d 100644 --- a/tests/source/hard-tabs.rs +++ b/tests/source/hard-tabs.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-hard_tabs: true fn main() { diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 4f47aff0544..38d7d8ca941 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Test of lots of random stuff. // FIXME split this into multiple, self-contained tests. diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index aecbc285fc6..216ce08099d 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Struct literal expressions. fn main() { diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs index d0cf7d4069f..b6395884713 100644 --- a/tests/source/struct_lits_multiline.rs +++ b/tests/source/struct_lits_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-struct_lit_multiline_style: ForceMulti // Struct literal expressions. diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index 6b78df7e0f3..f483b08b625 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual // Struct literal expressions. diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs index 192d88a3903..58be4da68ad 100644 --- a/tests/source/struct_lits_visual_multiline.rs +++ b/tests/source/struct_lits_visual_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual // rustfmt-struct_lit_multiline_style: ForceMulti diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 2bdfe7325bc..94c58b2996c 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true /// A Doc comment #[AnAttribute] diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 62657ad3b5d..0789efc2b63 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Test attributes and doc comments are preserved. /// Blah blah blah. diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 575631cd3be..c3191381653 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -1,3 +1,5 @@ +// rustfmt-wrap_comments: true + //! Doc comment fn test() { // comment diff --git a/tests/target/comment2.rs b/tests/target/comment2.rs index 885964afee2..cecb7b0d95f 100644 --- a/tests/target/comment2.rs +++ b/tests/target/comment2.rs @@ -1,3 +1,5 @@ +// rustfmt-wrap_comments: true + /// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly /// and justly. pub mod foo { diff --git a/tests/target/comment3.rs b/tests/target/comment3.rs index c9123d4e076..24598931ed1 100644 --- a/tests/target/comment3.rs +++ b/tests/target/comment3.rs @@ -1,3 +1,5 @@ +// rustfmt-wrap_comments: true + //! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly //! and justly. diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 04391d8f30c..9278488fecf 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Enums test #[atrr] diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 4b4afaa99e5..bfd6161e4d8 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Test expressions fn foo() -> bool { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 21155218111..19a0182fdaa 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-hard_tabs: true fn main() { diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 7d6513f70b7..a806f62705e 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Test of lots of random stuff. // FIXME split this into multiple, self-contained tests. diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 66fb4925042..e0b29184162 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // Struct literal expressions. fn main() { diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index 2670ef6de1d..893c9dba888 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-struct_lit_multiline_style: ForceMulti // Struct literal expressions. diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 86812c147a1..5ebc3a8684f 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual // Struct literal expressions. diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs index 94aa121b7a4..3433b01ff50 100644 --- a/tests/target/struct_lits_visual_multiline.rs +++ b/tests/target/struct_lits_visual_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual // rustfmt-struct_lit_multiline_style: ForceMulti diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 4bc8c6bbe44..bb7cc9d5b7d 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -1,3 +1,4 @@ +// rustfmt-wrap_comments: true /// A Doc comment #[AnAttribute] -- cgit 1.4.1-3-g733a5 From 5d07b63ce59a3bbe27e3c8b370fdfb1934e831af Mon Sep 17 00:00:00 2001 From: Jørn Lode Date: Mon, 9 Nov 2015 21:41:25 +0100 Subject: Check if the CWD contains a config (previously it only checked parents) --- src/bin/rustfmt.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2789b5f6cdd..de906729b31 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -54,14 +54,15 @@ fn lookup_project_file(input_file: &Path) -> io::Result { // current = try!(fs::canonicalize(current)); loop { - // If the current directory has no parent, we're done searching. - if !current.pop() { - return Err(io::Error::new(io::ErrorKind::NotFound, "Config not found")); - } let config_file = current.join("rustfmt.toml"); if fs::metadata(&config_file).is_ok() { return Ok(config_file); } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + return Err(io::Error::new(io::ErrorKind::NotFound, "Config not found")); + } } } -- cgit 1.4.1-3-g733a5 From cb64ab22ecd24823b175db309a695420eab86746 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Fri, 13 Nov 2015 01:13:25 +0100 Subject: Enable rustfmt to format a list of files Fix #580 by allowing rustfmt to accept a list of files. This also enables usage of shell wildcard expansion, although notably this does not work with cmd.exe on Windows. For example: 'rustfmt *.rs' will format all rust files in the current working directory. - Change usage text to show rustfmt will accept a list of files - Change "Using rustfmt config file: {}" message to "Using rustfmt config file {} for {}" - Change Operation::Format(PathBuf, WriteMode) to Operation::Format(Vec, WriteMode) - Loop through Vec, load config and call 'run' for each path --- src/bin/rustfmt.rs | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index de906729b31..d9f4d46ec30 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -29,8 +29,8 @@ use getopts::Options; /// Rustfmt operations. enum Operation { - /// Format a file and its child modules. - Format(PathBuf, WriteMode), + /// Format files and its child modules. + Format(Vec, WriteMode), /// Print the help message. Help, /// Print detailed configuration help. @@ -114,16 +114,20 @@ fn execute() -> i32 { run_from_stdin(input, write_mode, &config); 0 } - Operation::Format(file, write_mode) => { - let config = match lookup_and_read_project_file(&file) { - Ok((path, toml)) => { - println!("Using rustfmt config file: {}", path.display()); - Config::from_toml(&toml) - } - Err(_) => Default::default(), - }; - - run(&file, write_mode, &config); + Operation::Format(files, write_mode) => { + for file in files { + let config = match lookup_and_read_project_file(&file) { + Ok((path, toml)) => { + println!("Using rustfmt config file {} for {}", + path.display(), + file.display()); + Config::from_toml(&toml) + } + Err(_) => Default::default(), + }; + + run(&file, write_mode, &config); + } 0 } } @@ -144,7 +148,7 @@ fn main() { } fn print_usage(opts: &Options, reason: &str) { - let reason = format!("{}\nusage: {} [options] ", + let reason = format!("{}\nusage: {} [options] ...", reason, env::current_exe().unwrap().display()); println!("{}", opts.usage(&reason)); @@ -189,5 +193,11 @@ fn determine_operation(opts: &Options, args: I) -> Operation None => WriteMode::Replace, }; - Operation::Format(PathBuf::from(&matches.free[0]), write_mode) + let mut files = Vec::with_capacity(matches.free.len()); + + for arg in matches.free { + files.push(PathBuf::from(arg)); + } + + Operation::Format(files, write_mode) } -- cgit 1.4.1-3-g733a5 From 4443c4b7ccc0f53b94bf2d47c1907047ba42d0bf Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Fri, 13 Nov 2015 02:08:57 +0100 Subject: Correct some non-idiomatic code --- src/bin/rustfmt.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index d9f4d46ec30..b90cdb3d3ca 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -29,7 +29,7 @@ use getopts::Options; /// Rustfmt operations. enum Operation { - /// Format files and its child modules. + /// Format files and their child modules. Format(Vec, WriteMode), /// Print the help message. Help, @@ -193,11 +193,7 @@ fn determine_operation(opts: &Options, args: I) -> Operation None => WriteMode::Replace, }; - let mut files = Vec::with_capacity(matches.free.len()); - - for arg in matches.free { - files.push(PathBuf::from(arg)); - } + let files: Vec<_> = matches.free.iter().map(|a| PathBuf::from(a)).collect(); Operation::Format(files, write_mode) } -- cgit 1.4.1-3-g733a5 From d32245a13d368b26173989e84d6309c9605aed6c Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 13 Nov 2015 14:31:20 +0100 Subject: Fix brace indentation after where clause --- src/items.rs | 5 +++-- tests/source/structs.rs | 6 ++++++ tests/target/structs.rs | 8 ++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e2484f8298e..19a2a118e8b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -793,7 +793,8 @@ impl<'a> FmtVisitor<'a> { let header_str = self.format_header(item_name, ident, vis); result.push_str(&header_str); result.push(';'); - return Some(result); + + Some(result) } fn format_struct_struct(&self, @@ -968,8 +969,8 @@ impl<'a> FmtVisitor<'a> { terminator, Some(span.hi))); result.push_str(&where_clause_str); - result.push_str(&self.block_indent.to_string(self.config)); result.push('\n'); + result.push_str(&self.block_indent.to_string(self.config)); result.push_str(opener); } else { result.push(' '); diff --git a/tests/source/structs.rs b/tests/source/structs.rs index a4e377f154e..9a559e029db 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -135,3 +135,9 @@ struct Foo(TTTTTTTTTTTTTTTTT, // Foo TTTTTTTTTTTTTTTTTTT, // Qux (FIXME #572 - doc comment) UUUUUUUUUUUUUUUUUUU); + +mod m { + struct X where T: Sized { + a: T, + } +} diff --git a/tests/target/structs.rs b/tests/target/structs.rs index a79663b0fed..50090b7a5f4 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -141,3 +141,11 @@ struct Foo(TTTTTTTTTTTTTTTTT, // Foo TTTTTTTTTTTTTTTTTTT, // Qux (FIXME #572 - doc comment) UUUUUUUUUUUUUUUUUUU); + +mod m { + struct X + where T: Sized + { + a: T, + } +} -- cgit 1.4.1-3-g733a5 From c93c771e71ca96a94ab7d13b37103cb57be22df5 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 13 Nov 2015 14:53:34 +0100 Subject: Fix span issue with generic method calls --- src/chains.rs | 10 ++++++---- tests/source/chains.rs | 6 ++++++ tests/target/chains.rs | 6 ++++++ 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f004a5798c2..9c5b37d35cb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -217,15 +217,17 @@ fn rewrite_method_call(method_name: ast::Ident, width: usize, offset: Indent) -> Option { - let type_str = if types.is_empty() { - String::new() + let (lo, type_str) = if types.is_empty() { + (args[0].span.hi, String::new()) } else { let type_list = types.iter().map(|ty| pprust::ty_to_string(ty)).collect::>(); - format!("::<{}>", type_list.join(", ")) + + (types.last().unwrap().span.hi, + format!("::<{}>", type_list.join(", "))) }; let callee_str = format!(".{}{}", method_name, type_str); - let span = mk_sp(args[0].span.hi, span.hi); + let span = mk_sp(lo, span.hi); rewrite_call(context, &callee_str, &args[1..], span, width, offset) } diff --git a/tests/source/chains.rs b/tests/source/chains.rs index bf1ed31afe7..e7d9783a51c 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -106,3 +106,9 @@ fn is_replaced_content() -> bool { constellat.send(ConstellationMsg::ViewportConstrained( self.id, constraints)).unwrap(); } + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 2fb201011a5..d8fca6d40fe 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -132,3 +132,9 @@ fn is_replaced_content() -> bool { constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) .unwrap(); } + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} -- cgit 1.4.1-3-g733a5 From 5b06ed6817c84ed05f1e1e3c7be68afbc7bde4e8 Mon Sep 17 00:00:00 2001 From: Mika Attila Date: Sat, 14 Nov 2015 19:01:28 +0100 Subject: Don't print an unnecessary newline after printing format report The Display implementation for FormatReport already prints a newline after every error. However, if the format report does not contain errors, we don't want to print an empty newline. This behavior clutters up the console output with empty lines when rustfmt is invoked multiple times (from .e.g a script or cargo-fmt). So instead of using println! to print the report, we just use print!. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 4c7b3cbd249..e73ed86599d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -440,7 +440,7 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { let mut result = format(file, config, write_mode); - println!("{}", fmt_lines(&mut result, config)); + print!("{}", fmt_lines(&mut result, config)); let write_result = filemap::write_all_files(&result, write_mode, config); -- cgit 1.4.1-3-g733a5 From d4be6a43e98883c04d38b101c663ddf990e247f3 Mon Sep 17 00:00:00 2001 From: Thorben Kroeger Date: Sat, 14 Nov 2015 17:47:59 +0100 Subject: new config 'chain_indent' --- src/chains.rs | 10 +++++++++- src/config.rs | 1 + tests/source/chains-indent-inherit.rs | 5 +++++ tests/source/chains-indent-tabbed.rs | 5 +++++ tests/source/chains-indent-visual.rs | 5 +++++ tests/target/chains-indent-inherit.rs | 10 ++++++++++ tests/target/chains-indent-tabbed.rs | 10 ++++++++++ tests/target/chains-indent-visual.rs | 10 ++++++++++ 8 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/source/chains-indent-inherit.rs create mode 100644 tests/source/chains-indent-tabbed.rs create mode 100644 tests/source/chains-indent-visual.rs create mode 100644 tests/target/chains-indent-inherit.rs create mode 100644 tests/target/chains-indent-tabbed.rs create mode 100644 tests/target/chains-indent-visual.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9c5b37d35cb..31cd9624016 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -56,7 +56,15 @@ pub fn rewrite_chain(mut expr: &ast::Expr, } else if is_block_expr(parent, &parent_rewrite) { (parent_block_indent, false) } else { - (offset + Indent::new(context.config.tab_spaces, 0), false) + match context.config.chain_indent { + BlockIndentStyle::Inherit => (context.block_indent, false), + BlockIndentStyle::Tabbed => { + (context.block_indent.block_indent(context.config), false) + } + BlockIndentStyle::Visual => { + (offset + Indent::new(context.config.tab_spaces, 0), false) + } + } }; let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); diff --git a/src/config.rs b/src/config.rs index 9f260f93ab8..dcf0816335b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -294,6 +294,7 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_base_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on chain base"; + chain_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of chain"; reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; format_strings: bool, true, "Format string literals, or leave as is"; diff --git a/tests/source/chains-indent-inherit.rs b/tests/source/chains-indent-inherit.rs new file mode 100644 index 00000000000..67272a656c6 --- /dev/null +++ b/tests/source/chains-indent-inherit.rs @@ -0,0 +1,5 @@ +// rustfmt-chain_indent: Inherit + +fn test() { + let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); +} diff --git a/tests/source/chains-indent-tabbed.rs b/tests/source/chains-indent-tabbed.rs new file mode 100644 index 00000000000..89bf5bb1a69 --- /dev/null +++ b/tests/source/chains-indent-tabbed.rs @@ -0,0 +1,5 @@ +// rustfmt-chain_indent: Tabbed + +fn test() { + let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); +} diff --git a/tests/source/chains-indent-visual.rs b/tests/source/chains-indent-visual.rs new file mode 100644 index 00000000000..7e7f0558ffe --- /dev/null +++ b/tests/source/chains-indent-visual.rs @@ -0,0 +1,5 @@ +// rustfmt-chain_indent: Visual + +fn test() { + let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); +} diff --git a/tests/target/chains-indent-inherit.rs b/tests/target/chains-indent-inherit.rs new file mode 100644 index 00000000000..76d3ef8204b --- /dev/null +++ b/tests/target/chains-indent-inherit.rs @@ -0,0 +1,10 @@ +// rustfmt-chain_indent: Inherit + +fn test() { + let x = my_long_function() + .my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); +} diff --git a/tests/target/chains-indent-tabbed.rs b/tests/target/chains-indent-tabbed.rs new file mode 100644 index 00000000000..4611b0587ff --- /dev/null +++ b/tests/target/chains-indent-tabbed.rs @@ -0,0 +1,10 @@ +// rustfmt-chain_indent: Tabbed + +fn test() { + let x = my_long_function() + .my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); +} diff --git a/tests/target/chains-indent-visual.rs b/tests/target/chains-indent-visual.rs new file mode 100644 index 00000000000..e91317bd5de --- /dev/null +++ b/tests/target/chains-indent-visual.rs @@ -0,0 +1,10 @@ +// rustfmt-chain_indent: Visual + +fn test() { + let x = my_long_function() + .my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); +} -- cgit 1.4.1-3-g733a5 From 2fff041b433a972fbc7604b16341b232e221350a Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 14 Nov 2015 13:52:43 -0800 Subject: Pass in whether an ast::Path is in an expression context. This gets rid of a slightly nasty hack involving scanning the source expression for a ":". --- src/expr.rs | 4 +-- src/imports.rs | 5 ++-- src/patterns.rs | 9 +++++-- src/types.rs | 74 +++++++++++++++++++++------------------------------ tests/source/paths.rs | 2 ++ tests/target/paths.rs | 2 ++ 6 files changed, 47 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 951b407ef43..c4b01e38b42 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -117,7 +117,7 @@ impl Rewrite for ast::Expr { rewrite_match(context, cond, arms, width, offset, self.span) } ast::Expr_::ExprPath(ref qself, ref path) => { - rewrite_path(context, qself.as_ref(), path, width, offset) + rewrite_path(context, true, qself.as_ref(), path, width, offset) } ast::Expr_::ExprAssign(ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, None, width, offset) @@ -1242,7 +1242,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // 2 = " {".len() let path_budget = try_opt!(width.checked_sub(2)); - let path_str = try_opt!(path.rewrite(context, path_budget, offset)); + let path_str = try_opt!(rewrite_path(context, true, None, path, path_budget, offset)); // Foo { a: Foo } - indent is +3, width is -5. let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); diff --git a/src/imports.rs b/src/imports.rs index aab5dd76799..6917b1ff403 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -10,6 +10,7 @@ use Indent; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; +use types::rewrite_path; use utils::span_after; use rewrite::{Rewrite, RewriteContext}; @@ -37,7 +38,7 @@ impl Rewrite for ast::ViewPath { let ident_str = ident.to_string(); // 4 = " as ".len() let budget = try_opt!(width.checked_sub(ident_str.len() + 4)); - let path_str = try_opt!(path.rewrite(context, budget, offset)); + let path_str = try_opt!(rewrite_path(context, false, None, path, budget, offset)); Some(if path.segments.last().unwrap().identifier == ident { path_str @@ -105,7 +106,7 @@ pub fn rewrite_use_list(width: usize, -> Option { // 1 = {} let budget = try_opt!(width.checked_sub(1)); - let path_str = try_opt!(path.rewrite(context, budget, offset)); + let path_str = try_opt!(rewrite_path(context, false, None, path, budget, offset)); match path_list.len() { 0 => unreachable!(), diff --git a/src/patterns.rs b/src/patterns.rs index 6bba3d4c6e2..bac69e4d126 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -45,7 +45,7 @@ impl Rewrite for Pat { } } Pat_::PatQPath(ref q_self, ref path) => { - rewrite_path(context, Some(q_self), path, width, offset) + rewrite_path(context, true, Some(q_self), path, width, offset) } Pat_::PatRange(ref lhs, ref rhs) => { rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset) @@ -58,7 +58,12 @@ impl Rewrite for Pat { rewrite_tuple(context, items, self.span, width, offset) } Pat_::PatEnum(ref path, Some(ref pat_vec)) => { - let path_str = try_opt!(::types::rewrite_path(context, None, path, width, offset)); + let path_str = try_opt!(::types::rewrite_path(context, + true, + None, + path, + width, + offset)); if pat_vec.is_empty() { Some(path_str) diff --git a/src/types.rs b/src/types.rs index d8170e2f917..9b50333e043 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,7 +10,7 @@ use syntax::ast::{self, Mutability}; use syntax::print::pprust; -use syntax::codemap::{self, Span, BytePos, CodeMap}; +use syntax::codemap::{self, Span, BytePos}; use Indent; use lists::{format_item_list, itemize_list, format_fn_args}; @@ -18,14 +18,9 @@ use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; -impl Rewrite for ast::Path { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - rewrite_path(context, None, self, width, offset) - } -} - // Does not wrap on simple segments. pub fn rewrite_path(context: &RewriteContext, + expr_context: bool, qself: Option<&ast::QSelf>, path: &ast::Path, width: usize, @@ -53,7 +48,8 @@ pub fn rewrite_path(context: &RewriteContext, // 3 = ">::".len() let budget = try_opt!(width.checked_sub(extra_offset + 3)); - result = try_opt!(rewrite_path_segments(result, + result = try_opt!(rewrite_path_segments(expr_context, + result, path.segments.iter().take(skip_count), span_lo, path.span.hi, @@ -68,7 +64,8 @@ pub fn rewrite_path(context: &RewriteContext, let extra_offset = extra_offset(&result, offset); let budget = try_opt!(width.checked_sub(extra_offset)); - rewrite_path_segments(result, + rewrite_path_segments(expr_context, + result, path.segments.iter().skip(skip_count), span_lo, path.span.hi, @@ -77,7 +74,8 @@ pub fn rewrite_path(context: &RewriteContext, offset + extra_offset) } -fn rewrite_path_segments<'a, I>(mut buffer: String, +fn rewrite_path_segments<'a, I>(expr_context: bool, + mut buffer: String, iter: I, mut span_lo: BytePos, span_hi: BytePos, @@ -99,7 +97,8 @@ fn rewrite_path_segments<'a, I>(mut buffer: String, let extra_offset = extra_offset(&buffer, offset); let remaining_width = try_opt!(width.checked_sub(extra_offset)); let new_offset = offset + extra_offset; - let segment_string = try_opt!(rewrite_segment(segment, + let segment_string = try_opt!(rewrite_segment(expr_context, + segment, &mut span_lo, span_hi, context, @@ -152,30 +151,6 @@ impl<'a> Rewrite for SegmentParam<'a> { } } -// This is a dirty hack to determine if we're in an expression or not. Generic -// parameters are passed differently in expressions and items. We'd declare -// a struct with Foo, but call its functions with Foo::::f(). -// We'd really rather not do this, but there doesn't seem to be an alternative -// at this point. -// FIXME: fails with spans containing comments with the characters < or : -fn get_path_separator(codemap: &CodeMap, - path_start: BytePos, - segment_start: BytePos) - -> &'static str { - let span = codemap::mk_sp(path_start, segment_start); - let snippet = codemap.span_to_snippet(span).unwrap(); - - for c in snippet.chars().rev() { - if c == ':' { - return "::"; - } else if !c.is_whitespace() && c != '<' { - return ""; - } - } - - unreachable!(); -} - // Formats a path segment. There are some hacks involved to correctly determine // the segment's associated span since it's not part of the AST. // @@ -186,7 +161,8 @@ fn get_path_separator(codemap: &CodeMap, // // When the segment contains a positive number of parameters, we update span_lo // so that invariants described above will hold for the next segment. -fn rewrite_segment(segment: &ast::PathSegment, +fn rewrite_segment(expr_context: bool, + segment: &ast::PathSegment, span_lo: &mut BytePos, span_hi: BytePos, context: &RewriteContext, @@ -210,7 +186,11 @@ fn rewrite_segment(segment: &ast::PathSegment, let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); - let separator = get_path_separator(context.codemap, *span_lo, list_lo); + let separator = if expr_context { + "::" + } else { + "" + }; // 1 for < let extra_offset = 1 + separator.len(); @@ -334,7 +314,12 @@ impl Rewrite for ast::WherePredicate { // 3 = " = ".len() let used_width = 3 + ty_str.len(); let budget = try_opt!(width.checked_sub(used_width)); - let path_str = try_opt!(path.rewrite(context, budget, offset + used_width)); + let path_str = try_opt!(rewrite_path(context, + false, + None, + path, + budget, + offset + used_width)); format!("{} = {}", path_str, ty_str) } }; @@ -427,13 +412,16 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref - .path - .rewrite(context, max_path_width, offset + extra_offset)); + let path_str = try_opt!(rewrite_path(context, + false, + None, + &self.trait_ref.path, + max_path_width, + offset + extra_offset)); Some(format!("for<{}> {}", lifetime_str, path_str)) } else { - self.trait_ref.path.rewrite(context, width, offset) + rewrite_path(context, false, None, &self.trait_ref.path, width, offset) } } } @@ -496,7 +484,7 @@ impl Rewrite for ast::Ty { } ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), ast::TyPath(ref q_self, ref path) => { - rewrite_path(context, q_self.as_ref(), path, width, offset) + rewrite_path(context, false, q_self.as_ref(), path, width, offset) } ast::TyFixedLengthVec(ref ty, ref repeats) => { rewrite_pair(&**ty, &**repeats, "[", "; ", "]", context, width, offset) diff --git a/tests/source/paths.rs b/tests/source/paths.rs index 9a5513e1589..8a4ab769ba3 100644 --- a/tests/source/paths.rs +++ b/tests/source/paths.rs @@ -16,6 +16,8 @@ fn main() { >::some_func(); < *mut JSObject >:: relocate(entry); + + let x: Foo/*::*/; } fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/target/paths.rs b/tests/target/paths.rs index fd97bb4d71c..15cc35e69f1 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -15,6 +15,8 @@ fn main() { Quux::::some_func(); <*mut JSObject>::relocate(entry); + + let x: Foo; } fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { -- cgit 1.4.1-3-g733a5 From faff4bc9e83e795c5d94ce7cfee9893459abd439 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Sun, 15 Nov 2015 15:41:41 +0900 Subject: Add verbose mode --- src/bin/rustfmt.rs | 29 ++++++++++++++++++----------- src/config.rs | 1 + src/lib.rs | 3 +++ 3 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index b90cdb3d3ca..789f8773345 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -25,7 +25,7 @@ use std::fs::{self, File}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; -use getopts::Options; +use getopts::{Matches, Options}; /// Rustfmt operations. enum Operation { @@ -75,9 +75,14 @@ fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, Strin Ok((path, toml)) } +fn update_config(config: &mut Config, matches: &Matches) { + config.verbose = matches.opt_present("verbose"); +} + fn execute() -> i32 { let mut opts = Options::new(); opts.optflag("h", "help", "show this message"); + opts.optflag("v", "verbose", "show progress"); opts.optopt("", "write-mode", "mode to write in (not usable when piping from stdin)", @@ -87,7 +92,15 @@ fn execute() -> i32 { "config-help", "show details of rustfmt configuration options"); - let operation = determine_operation(&opts, env::args().skip(1)); + let matches = match opts.parse(env::args().skip(1)) { + Ok(m) => m, + Err(e) => { + print_usage(&opts, &e.to_string()); + return 1; + } + }; + + let operation = determine_operation(&matches); match operation { Operation::InvalidInput(reason) => { @@ -116,7 +129,7 @@ fn execute() -> i32 { } Operation::Format(files, write_mode) => { for file in files { - let config = match lookup_and_read_project_file(&file) { + let mut config = match lookup_and_read_project_file(&file) { Ok((path, toml)) => { println!("Using rustfmt config file {} for {}", path.display(), @@ -126,6 +139,7 @@ fn execute() -> i32 { Err(_) => Default::default(), }; + update_config(&mut config, &matches); run(&file, write_mode, &config); } 0 @@ -154,14 +168,7 @@ fn print_usage(opts: &Options, reason: &str) { println!("{}", opts.usage(&reason)); } -fn determine_operation(opts: &Options, args: I) -> Operation - where I: Iterator -{ - let matches = match opts.parse(args) { - Ok(m) => m, - Err(e) => return Operation::InvalidInput(e.to_string()), - }; - +fn determine_operation(matches: &Matches) -> Operation { if matches.opt_present("h") { return Operation::Help; } diff --git a/src/config.rs b/src/config.rs index dcf0816335b..6d1c863bea8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -257,6 +257,7 @@ macro_rules! create_config { } create_config! { + verbose: bool, false, "Use verbose output"; max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; diff --git a/src/lib.rs b/src/lib.rs index e73ed86599d..bf1a0164f68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -300,6 +300,9 @@ fn fmt_ast(krate: &ast::Crate, let mut file_map = FileMap::new(); for (path, module) in modules::list_files(krate, parse_session.codemap()) { let path = path.to_str().unwrap(); + if config.verbose { + println!("Formatting {}", path); + } let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode)); visitor.format_separate_mod(module, path); file_map.insert(path.to_owned(), visitor.buffer); -- cgit 1.4.1-3-g733a5 From add37b9c4991d7ce9bdd58bb4f8c66ac8a9c7244 Mon Sep 17 00:00:00 2001 From: Johan Sköld Date: Sun, 15 Nov 2015 03:34:04 -0800 Subject: Adds a "Native" option to newline_style. By using it one will get \r\n line endings on Windows, and \n line endings on other platforms. --- src/config.rs | 1 + src/filemap.rs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index dcf0816335b..713d3aefd3c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,6 +26,7 @@ macro_rules! configuration_option_enum{ configuration_option_enum! { NewlineStyle: Windows, // \r\n Unix, // \n + Native, // \r\n in Windows, \n on other platforms } configuration_option_enum! { BraceStyle: diff --git a/src/filemap.rs b/src/filemap.rs index 3f1a867f385..5b997b55c25 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -59,7 +59,17 @@ pub fn write_file(text: &StringBuffer, -> Result<(), io::Error> where T: Write { - match config.newline_style { + let style = if config.newline_style == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + config.newline_style + }; + + match style { NewlineStyle::Unix => write!(writer, "{}", text), NewlineStyle::Windows => { for (c, _) in text.chars() { @@ -71,6 +81,7 @@ pub fn write_file(text: &StringBuffer, } Ok(()) } + NewlineStyle::Native => unreachable!(), } } -- cgit 1.4.1-3-g733a5 From 8658774ad2252f00559d88f1fd8884197041f307 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Sun, 15 Nov 2015 11:55:18 -0800 Subject: Implement initial option for brace style for non-fn items. --- src/config.rs | 1 + src/items.rs | 20 ++++++++++++++++++-- tests/source/item-brace-style.rs | 16 ++++++++++++++++ tests/target/item-brace-style.rs | 18 ++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/source/item-brace-style.rs create mode 100644 tests/target/item-brace-style.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index dcf0816335b..7a64ab15916 100644 --- a/src/config.rs +++ b/src/config.rs @@ -302,4 +302,5 @@ create_config! { take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; + item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; } diff --git a/src/items.rs b/src/items.rs index 19a2a118e8b..c4c55c841a6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -634,10 +634,17 @@ impl<'a> FmtVisitor<'a> { let header_str = self.format_header("enum ", ident, vis); self.buffer.push_str(&header_str); + let separator = if self.config.item_brace_style == BraceStyle::AlwaysNextLine && + !enum_def.variants.is_empty() { + format!("\n{}", self.block_indent.to_string(self.config)) + } else { + " ".to_owned() + }; let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); let generics_str = self.format_generics(generics, "{", + &separator, "{", self.block_indent, self.block_indent.block_indent(self.config), @@ -813,16 +820,24 @@ impl<'a> FmtVisitor<'a> { let body_lo = span_after(span, "{", self.codemap); + let separator = if self.config.item_brace_style == BraceStyle::AlwaysNextLine && + !fields.is_empty() { + format!("\n{}", self.block_indent.to_string(self.config)) + } else { + " ".to_owned() + }; + let generics_str = match generics { Some(g) => { try_opt!(self.format_generics(g, "{", + &separator, "{", offset, offset + header_str.len(), mk_sp(span.lo, body_lo))) } - None => " {".to_owned(), + None => format!("{}{{", separator), }; result.push_str(&generics_str); @@ -954,6 +969,7 @@ impl<'a> FmtVisitor<'a> { fn format_generics(&self, generics: &ast::Generics, opener: &str, + separator: &str, terminator: &str, offset: Indent, generics_offset: Indent, @@ -973,7 +989,7 @@ impl<'a> FmtVisitor<'a> { result.push_str(&self.block_indent.to_string(self.config)); result.push_str(opener); } else { - result.push(' '); + result.push_str(separator); result.push_str(opener); } diff --git a/tests/source/item-brace-style.rs b/tests/source/item-brace-style.rs new file mode 100644 index 00000000000..37b02f0940a --- /dev/null +++ b/tests/source/item-brace-style.rs @@ -0,0 +1,16 @@ +// rustfmt-item_brace_style: AlwaysNextLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} +} diff --git a/tests/target/item-brace-style.rs b/tests/target/item-brace-style.rs new file mode 100644 index 00000000000..006d6b4d3bf --- /dev/null +++ b/tests/target/item-brace-style.rs @@ -0,0 +1,18 @@ +// rustfmt-item_brace_style: AlwaysNextLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} +} -- cgit 1.4.1-3-g733a5 From 56a765ef0547b9eec3e82f5ec15e4501854f1757 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 13 Nov 2015 09:38:41 +1300 Subject: Rustup --- Cargo.lock | 61 +++++++++++++++++++++++++++++++-------------------------- src/items.rs | 4 ++-- src/macros.rs | 2 +- src/patterns.rs | 12 ++++-------- src/visitor.rs | 2 +- 5 files changed, 41 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 66061bd1e25..23a75bfb547 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,24 +3,24 @@ name = "rustfmt" version = "0.0.1" dependencies = [ "diff 0.1.7 (git+https://github.com/utkarshkukreti/diff.rs.git)", - "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", - "syntex_syntax 0.18.0 (git+https://github.com/serde-rs/syntex)", - "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.21.0 (git+https://github.com/serde-rs/syntex)", + "term 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -35,10 +35,10 @@ source = "git+https://github.com/utkarshkukreti/diff.rs.git#6edb9454bf4127087ace [[package]] name = "env_logger" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -49,32 +49,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "kernel32-sys" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.1.10" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -82,8 +87,8 @@ name = "regex" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -100,31 +105,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strings" version = "0.0.1" -source = "git+https://github.com/nrc/strings.rs.git#78ba5d802102e4f46f03c5eb835a53106a4d35f7" +source = "git+https://github.com/nrc/strings.rs.git#d33d75a7c22522c76f2306b16b238e363de45af4" dependencies = [ - "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.18.0" -source = "git+https://github.com/serde-rs/syntex#176ca5d8add606fac8d503b10c89ddb82f02d92b" +version = "0.21.0" +source = "git+https://github.com/serde-rs/syntex#069fe5d5e8cc8132dc3cb97099511240b9d4facc" dependencies = [ "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -147,7 +152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/src/items.rs b/src/items.rs index 19a2a118e8b..cbe8af541f3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -727,14 +727,14 @@ impl<'a> FmtVisitor<'a> { result.push_str(&indent.to_string(self.config)); } - let variant_body = match *field.node.data { + let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma self.format_struct("", field.node.name, ast::Visibility::Inherited, - &*field.node.data, + &field.node.data, None, field.span, indent) diff --git a/src/macros.rs b/src/macros.rs index 389e29014f0..4e28fd393f4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -77,7 +77,7 @@ pub fn rewrite_macro(mac: &ast::Mac, let mut expr_vec = Vec::new(); loop { - expr_vec.push(match parser.parse_expr_nopanic() { + expr_vec.push(match parser.parse_expr() { Ok(expr) => expr, Err(..) => return None, }); diff --git a/src/patterns.rs b/src/patterns.rs index bac69e4d126..3e7a11bad41 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,7 +15,7 @@ use lists::{format_item_list, itemize_list}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use types::rewrite_path; -use syntax::ast::{PatWildKind, BindingMode, Pat, Pat_}; +use syntax::ast::{BindingMode, Pat, Pat_}; // FIXME(#18): implement pattern formatting. impl Rewrite for Pat { @@ -33,13 +33,9 @@ impl Rewrite for Pat { let result = format!("{}{}{}", prefix, mut_infix, ident.node); wrap_str(result, context.config.max_width, width, offset) } - Pat_::PatWild(kind) => { - let result = match kind { - PatWildKind::PatWildSingle => "_", - PatWildKind::PatWildMulti => "..", - }; - if result.len() <= width { - Some(result.to_owned()) + Pat_::PatWild => { + if 1 <= width { + Some("_".to_owned()) } else { None } diff --git a/src/visitor.rs b/src/visitor.rs index 6114dfff077..f19ff1f7e8b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -224,7 +224,7 @@ impl<'a> FmtVisitor<'a> { item.span, indent) .map(|s| { - match **def { + match *def { ast::VariantData::Tuple(..) => s + ";", _ => s, } -- cgit 1.4.1-3-g733a5 From 6e063a14307a8bbcaa902b1ee91debeaa4c18b53 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Mon, 16 Nov 2015 04:37:08 +0100 Subject: Add --version switch Add --version switch, which prints a short hash of the current commit. Fix #612 --- src/bin/rustfmt.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 789f8773345..bc9c3445aad 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -23,6 +23,7 @@ use rustfmt::config::Config; use std::env; use std::fs::{self, File}; use std::io::{self, Read, Write}; +use std::process::Command; use std::path::{Path, PathBuf}; use getopts::{Matches, Options}; @@ -33,6 +34,8 @@ enum Operation { Format(Vec, WriteMode), /// Print the help message. Help, + // Print version information + Version, /// Print detailed configuration help. ConfigHelp, /// Invalid program input, including reason. @@ -82,6 +85,7 @@ fn update_config(config: &mut Config, matches: &Matches) { fn execute() -> i32 { let mut opts = Options::new(); opts.optflag("h", "help", "show this message"); + opts.optflag("", "version", "show version information"); opts.optflag("v", "verbose", "show progress"); opts.optopt("", "write-mode", @@ -111,6 +115,10 @@ fn execute() -> i32 { print_usage(&opts, ""); 0 } + Operation::Version => { + print_version(); + 0 + } Operation::ConfigHelp => { Config::print_docs(); 0 @@ -168,6 +176,18 @@ fn print_usage(opts: &Options, reason: &str) { println!("{}", opts.usage(&reason)); } +fn print_version() { + let cmd = Command::new("git") + .arg("rev-parse") + .arg("--short") + .arg("HEAD") + .output(); + match cmd { + Ok(output) => print!("{}", String::from_utf8(output.stdout).unwrap()), + Err(e) => panic!("Unable te get version: {}", e), + } +} + fn determine_operation(matches: &Matches) -> Operation { if matches.opt_present("h") { return Operation::Help; @@ -177,6 +197,10 @@ fn determine_operation(matches: &Matches) -> Operation { return Operation::ConfigHelp; } + if matches.opt_present("version") { + return Operation::Version; + } + // if no file argument is supplied, read from stdin if matches.free.len() == 0 { -- cgit 1.4.1-3-g733a5 From 1eb38c461e61045983e9a8160a7af965039b163b Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Mon, 16 Nov 2015 14:52:14 +0100 Subject: Add `-V` as a shorthand for `--version` --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index bc9c3445aad..4e8be851c16 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -85,7 +85,7 @@ fn update_config(config: &mut Config, matches: &Matches) { fn execute() -> i32 { let mut opts = Options::new(); opts.optflag("h", "help", "show this message"); - opts.optflag("", "version", "show version information"); + opts.optflag("V", "version", "show version information"); opts.optflag("v", "verbose", "show progress"); opts.optopt("", "write-mode", -- cgit 1.4.1-3-g733a5 From 30aec386f407ae440b386758e7e12432b9334885 Mon Sep 17 00:00:00 2001 From: David Barnett Date: Tue, 17 Nov 2015 11:57:49 +1300 Subject: Comments in structs use appropriate style Fixes #491 --- src/expr.rs | 5 ++++- tests/source/struct_lits_multiline.rs | 7 +++++++ tests/target/struct_lits.rs | 2 +- tests/target/struct_lits_multiline.rs | 9 ++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c4b01e38b42..5a281f2df83 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1335,7 +1335,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }, indent: indent, width: budget, - ends_with_newline: false, + ends_with_newline: match context.config.struct_lit_style { + StructLitStyle::Block => true, + StructLitStyle::Visual => false, + }, config: context.config, }; let fields_str = try_opt!(write_list(&item_vec, &fmt)); diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs index b6395884713..dc0470b1447 100644 --- a/tests/source/struct_lits_multiline.rs +++ b/tests/source/struct_lits_multiline.rs @@ -71,3 +71,10 @@ fn issue201() { fn issue201_2() { let s = S{a: S2{ .. c}, .. b}; } + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index e0b29184162..445b8028340 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -25,7 +25,7 @@ fn main() { // Comment a: foo(), // Comment // Comment - b: bar(), /* Comment */ + b: bar(), // Comment }; Foo { a: Bar, b: f() }; diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index 893c9dba888..91ead9e764a 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -32,7 +32,7 @@ fn main() { // Comment a: foo(), // Comment // Comment - b: bar(), /* Comment */ + b: bar(), // Comment }; Foo { @@ -107,3 +107,10 @@ fn issue201_2() { ..b }; } + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; +} -- cgit 1.4.1-3-g733a5 From a96a69b708dd2dae12d87ea36c545003009c9416 Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Mon, 16 Nov 2015 23:18:07 -0800 Subject: Comments. - Move the option - Add some more tests (don't pass yet) --- src/config.rs | 2 +- tests/source/item-brace-style-next-line.rs | 29 ++++++++++++++++++++++ tests/source/item-brace-style-same-line.rs | 29 ++++++++++++++++++++++ tests/source/item-brace-style.rs | 16 ------------ tests/target/item-brace-style-next-line.rs | 39 ++++++++++++++++++++++++++++++ tests/target/item-brace-style-same-line.rs | 31 ++++++++++++++++++++++++ tests/target/item-brace-style.rs | 18 -------------- 7 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 tests/source/item-brace-style-next-line.rs create mode 100644 tests/source/item-brace-style-same-line.rs delete mode 100644 tests/source/item-brace-style.rs create mode 100644 tests/target/item-brace-style-next-line.rs create mode 100644 tests/target/item-brace-style-same-line.rs delete mode 100644 tests/target/item-brace-style.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7a64ab15916..3990e1af6ad 100644 --- a/src/config.rs +++ b/src/config.rs @@ -266,6 +266,7 @@ create_config! { "Maximum width in the body of a struct lit before falling back to vertical formatting"; newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; + item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, "Location of return type in function declaration"; fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; @@ -302,5 +303,4 @@ create_config! { take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; - item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; } diff --git a/tests/source/item-brace-style-next-line.rs b/tests/source/item-brace-style-next-line.rs new file mode 100644 index 00000000000..96a628349ea --- /dev/null +++ b/tests/source/item-brace-style-next-line.rs @@ -0,0 +1,29 @@ +// rustfmt-item_brace_style: AlwaysNextLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style-same-line.rs b/tests/source/item-brace-style-same-line.rs new file mode 100644 index 00000000000..636a584ff68 --- /dev/null +++ b/tests/source/item-brace-style-same-line.rs @@ -0,0 +1,29 @@ +// rustfmt-item_brace_style: PreferSameLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style.rs b/tests/source/item-brace-style.rs deleted file mode 100644 index 37b02f0940a..00000000000 --- a/tests/source/item-brace-style.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-item_brace_style: AlwaysNextLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} -} diff --git a/tests/target/item-brace-style-next-line.rs b/tests/target/item-brace-style-next-line.rs new file mode 100644 index 00000000000..a5c24102d92 --- /dev/null +++ b/tests/target/item-brace-style-next-line.rs @@ -0,0 +1,39 @@ +// rustfmt-item_brace_style: AlwaysNextLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where T: Copy + { + A, + } + + struct B + where T: Copy + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where T: Copy + {} + + struct D + where T: Copy + {} +} diff --git a/tests/target/item-brace-style-same-line.rs b/tests/target/item-brace-style-same-line.rs new file mode 100644 index 00000000000..b38bd2e1a19 --- /dev/null +++ b/tests/target/item-brace-style-same-line.rs @@ -0,0 +1,31 @@ +// rustfmt-item_brace_style: PreferSameLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + enum C {} + + struct D {} + + enum A + where T: Copy { + A, + } + + struct B + where T: Copy { + b: i32, + } + + enum C + where T: Copy {} + + struct D + where T: Copy {} +} diff --git a/tests/target/item-brace-style.rs b/tests/target/item-brace-style.rs deleted file mode 100644 index 006d6b4d3bf..00000000000 --- a/tests/target/item-brace-style.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-item_brace_style: AlwaysNextLine - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} -} -- cgit 1.4.1-3-g733a5 From f85ff8d0e5e0149807c3f83b3554bf70ddf70831 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Wed, 18 Nov 2015 00:51:15 +0100 Subject: Print version of the crate Print version acquired from Cargo when building. If built using rustc directly, print X.X.X --- src/bin/rustfmt.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 4e8be851c16..126f893130f 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -23,7 +23,6 @@ use rustfmt::config::Config; use std::env; use std::fs::{self, File}; use std::io::{self, Read, Write}; -use std::process::Command; use std::path::{Path, PathBuf}; use getopts::{Matches, Options}; @@ -177,15 +176,11 @@ fn print_usage(opts: &Options, reason: &str) { } fn print_version() { - let cmd = Command::new("git") - .arg("rev-parse") - .arg("--short") - .arg("HEAD") - .output(); - match cmd { - Ok(output) => print!("{}", String::from_utf8(output.stdout).unwrap()), - Err(e) => panic!("Unable te get version: {}", e), - } + println!("{}.{}.{}{}", + option_env!("CARGO_PKG_VERSION_MAJOR").unwrap_or("X"), + option_env!("CARGO_PKG_VERSION_MINOR").unwrap_or("X"), + option_env!("CARGO_PKG_VERSION_PATCH").unwrap_or("X"), + option_env!("CARGO_PKG_VERSION_PRE").unwrap_or("")); } fn determine_operation(matches: &Matches) -> Operation { -- cgit 1.4.1-3-g733a5 From 10560067905331adc158b5613fa8460a3122be1f Mon Sep 17 00:00:00 2001 From: Pavel Sountsov Date: Wed, 18 Nov 2015 22:34:14 -0800 Subject: Properly follow the brace styles. --- src/items.rs | 46 +++++++++++++---------- tests/source/item-brace-style-always-next-line.rs | 29 ++++++++++++++ tests/source/item-brace-style-next-line.rs | 29 -------------- tests/source/item-brace-style-prefer-same-line.rs | 29 ++++++++++++++ tests/source/item-brace-style-same-line-where.rs | 31 +++++++++++++++ tests/source/item-brace-style-same-line.rs | 29 -------------- tests/target/item-brace-style-always-next-line.rs | 37 ++++++++++++++++++ tests/target/item-brace-style-next-line.rs | 39 ------------------- tests/target/item-brace-style-prefer-same-line.rs | 31 +++++++++++++++ tests/target/item-brace-style-same-line-where.rs | 35 +++++++++++++++++ tests/target/item-brace-style-same-line.rs | 31 --------------- 11 files changed, 218 insertions(+), 148 deletions(-) create mode 100644 tests/source/item-brace-style-always-next-line.rs delete mode 100644 tests/source/item-brace-style-next-line.rs create mode 100644 tests/source/item-brace-style-prefer-same-line.rs create mode 100644 tests/source/item-brace-style-same-line-where.rs delete mode 100644 tests/source/item-brace-style-same-line.rs create mode 100644 tests/target/item-brace-style-always-next-line.rs delete mode 100644 tests/target/item-brace-style-next-line.rs create mode 100644 tests/target/item-brace-style-prefer-same-line.rs create mode 100644 tests/target/item-brace-style-same-line-where.rs delete mode 100644 tests/target/item-brace-style-same-line.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c4c55c841a6..5595b41607b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -634,18 +634,13 @@ impl<'a> FmtVisitor<'a> { let header_str = self.format_header("enum ", ident, vis); self.buffer.push_str(&header_str); - let separator = if self.config.item_brace_style == BraceStyle::AlwaysNextLine && - !enum_def.variants.is_empty() { - format!("\n{}", self.block_indent.to_string(self.config)) - } else { - " ".to_owned() - }; let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); let generics_str = self.format_generics(generics, "{", - &separator, "{", + self.config.item_brace_style, + enum_def.variants.is_empty(), self.block_indent, self.block_indent.block_indent(self.config), mk_sp(span.lo, body_start)) @@ -820,24 +815,23 @@ impl<'a> FmtVisitor<'a> { let body_lo = span_after(span, "{", self.codemap); - let separator = if self.config.item_brace_style == BraceStyle::AlwaysNextLine && - !fields.is_empty() { - format!("\n{}", self.block_indent.to_string(self.config)) - } else { - " ".to_owned() - }; - let generics_str = match generics { Some(g) => { try_opt!(self.format_generics(g, "{", - &separator, "{", + self.config.item_brace_style, + fields.is_empty(), offset, offset + header_str.len(), mk_sp(span.lo, body_lo))) } - None => format!("{}{{", separator), + None => if self.config.item_brace_style == BraceStyle::AlwaysNextLine && + !fields.is_empty() { + format!("\n{}{{", self.block_indent.to_string(self.config)) + } else { + " {".to_owned() + }, }; result.push_str(&generics_str); @@ -969,8 +963,9 @@ impl<'a> FmtVisitor<'a> { fn format_generics(&self, generics: &ast::Generics, opener: &str, - separator: &str, terminator: &str, + brace_style: BraceStyle, + force_same_line_brace: bool, offset: Indent, generics_offset: Indent, span: Span) @@ -985,11 +980,22 @@ impl<'a> FmtVisitor<'a> { terminator, Some(span.hi))); result.push_str(&where_clause_str); - result.push('\n'); - result.push_str(&self.block_indent.to_string(self.config)); + if !force_same_line_brace && + (brace_style == BraceStyle::SameLineWhere || + brace_style == BraceStyle::AlwaysNextLine) { + result.push('\n'); + result.push_str(&self.block_indent.to_string(self.config)); + } else { + result.push(' '); + } result.push_str(opener); } else { - result.push_str(separator); + if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine { + result.push('\n'); + result.push_str(&self.block_indent.to_string(self.config)); + } else { + result.push(' '); + } result.push_str(opener); } diff --git a/tests/source/item-brace-style-always-next-line.rs b/tests/source/item-brace-style-always-next-line.rs new file mode 100644 index 00000000000..96a628349ea --- /dev/null +++ b/tests/source/item-brace-style-always-next-line.rs @@ -0,0 +1,29 @@ +// rustfmt-item_brace_style: AlwaysNextLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style-next-line.rs b/tests/source/item-brace-style-next-line.rs deleted file mode 100644 index 96a628349ea..00000000000 --- a/tests/source/item-brace-style-next-line.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-item_brace_style: AlwaysNextLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/tests/source/item-brace-style-prefer-same-line.rs b/tests/source/item-brace-style-prefer-same-line.rs new file mode 100644 index 00000000000..636a584ff68 --- /dev/null +++ b/tests/source/item-brace-style-prefer-same-line.rs @@ -0,0 +1,29 @@ +// rustfmt-item_brace_style: PreferSameLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style-same-line-where.rs b/tests/source/item-brace-style-same-line-where.rs new file mode 100644 index 00000000000..7b2a95d3245 --- /dev/null +++ b/tests/source/item-brace-style-same-line-where.rs @@ -0,0 +1,31 @@ +// rustfmt-item_brace_style: SameLineWhere + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style-same-line.rs b/tests/source/item-brace-style-same-line.rs deleted file mode 100644 index 636a584ff68..00000000000 --- a/tests/source/item-brace-style-same-line.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-item_brace_style: PreferSameLine - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/tests/target/item-brace-style-always-next-line.rs b/tests/target/item-brace-style-always-next-line.rs new file mode 100644 index 00000000000..48dcebc0263 --- /dev/null +++ b/tests/target/item-brace-style-always-next-line.rs @@ -0,0 +1,37 @@ +// rustfmt-item_brace_style: AlwaysNextLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where T: Copy + { + A, + } + + struct B + where T: Copy + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where T: Copy {} + + struct D + where T: Copy {} +} diff --git a/tests/target/item-brace-style-next-line.rs b/tests/target/item-brace-style-next-line.rs deleted file mode 100644 index a5c24102d92..00000000000 --- a/tests/target/item-brace-style-next-line.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-item_brace_style: AlwaysNextLine - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A - where T: Copy - { - A, - } - - struct B - where T: Copy - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C - where T: Copy - {} - - struct D - where T: Copy - {} -} diff --git a/tests/target/item-brace-style-prefer-same-line.rs b/tests/target/item-brace-style-prefer-same-line.rs new file mode 100644 index 00000000000..b38bd2e1a19 --- /dev/null +++ b/tests/target/item-brace-style-prefer-same-line.rs @@ -0,0 +1,31 @@ +// rustfmt-item_brace_style: PreferSameLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + enum C {} + + struct D {} + + enum A + where T: Copy { + A, + } + + struct B + where T: Copy { + b: i32, + } + + enum C + where T: Copy {} + + struct D + where T: Copy {} +} diff --git a/tests/target/item-brace-style-same-line-where.rs b/tests/target/item-brace-style-same-line-where.rs new file mode 100644 index 00000000000..cdcd813fda4 --- /dev/null +++ b/tests/target/item-brace-style-same-line-where.rs @@ -0,0 +1,35 @@ +// rustfmt-item_brace_style: SameLineWhere + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where T: Copy + { + A, + } + + struct B + where T: Copy + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where T: Copy {} + + struct D + where T: Copy {} +} diff --git a/tests/target/item-brace-style-same-line.rs b/tests/target/item-brace-style-same-line.rs deleted file mode 100644 index b38bd2e1a19..00000000000 --- a/tests/target/item-brace-style-same-line.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-item_brace_style: PreferSameLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - enum C {} - - struct D {} - - enum A - where T: Copy { - A, - } - - struct B - where T: Copy { - b: i32, - } - - enum C - where T: Copy {} - - struct D - where T: Copy {} -} -- cgit 1.4.1-3-g733a5 From 4d7de5a16e230d8cf533c1cafee574862f06b968 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Tue, 17 Nov 2015 22:53:06 -0600 Subject: Support single-line functions By default, places functions with empty bodies on one line. If the function has only one expression or statement that fits on one line, the 'fn_single_line' option can be used. --- src/config.rs | 1 + src/items.rs | 101 ++++++++++++++++++++++++++++++++- src/utils.rs | 27 +++++++++ src/visitor.rs | 61 +++++--------------- tests/source/fn-single-line.rs | 74 ++++++++++++++++++++++++ tests/target/attrib.rs | 9 +-- tests/target/comment.rs | 3 +- tests/target/comments-fn.rs | 6 +- tests/target/fn-simple.rs | 6 +- tests/target/fn-single-line.rs | 61 ++++++++++++++++++++ tests/target/fn.rs | 20 ++----- tests/target/multiple.rs | 10 +--- tests/target/nestedmod/mod2c.rs | 3 +- tests/target/nestedmod/mymod1/mod3a.rs | 3 +- tests/target/nestedmod/submod2/a.rs | 3 +- tests/target/no_new_line_beginning.rs | 3 +- tests/target/paths.rs | 3 +- 17 files changed, 298 insertions(+), 96 deletions(-) create mode 100644 tests/source/fn-single-line.rs create mode 100644 tests/target/fn-single-line.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 5407ad8e8b8..7d56e3e8a80 100644 --- a/src/config.rs +++ b/src/config.rs @@ -269,6 +269,7 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; + fn_single_line: bool, false, "Put single-expression functions on a single line"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, "Location of return type in function declaration"; fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; diff --git a/src/items.rs b/src/items.rs index bc57a3e5ed6..58ddea0c483 100644 --- a/src/items.rs +++ b/src/items.rs @@ -12,17 +12,17 @@ use Indent; use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, - wrap_str, last_line_width}; + wrap_str, last_line_width, semicolon_for_expr, semicolon_for_stmt}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::rewrite_assign_rhs; -use comment::FindUncommented; +use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; use syntax::{ast, abi}; -use syntax::codemap::{Span, BytePos, mk_sp}; +use syntax::codemap::{Span, BytePos, CodeMap, mk_sp}; use syntax::print::pprust; use syntax::parse::token; @@ -447,6 +447,81 @@ impl<'a> FmtVisitor<'a> { Some((result, force_new_line_for_brace)) } + pub fn rewrite_single_line_fn(&self, + fn_rewrite: &Option, + block: &ast::Block) + -> Option { + + let fn_str = match *fn_rewrite { + Some(ref s) if !s.contains('\n') => s, + _ => return None, + }; + + let codemap = self.get_context().codemap; + + if is_empty_block(block, codemap) && + self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width { + return Some(format!("{}{{ }}", fn_str)); + } + + if self.config.fn_single_line && is_simple_block_stmt(block, codemap) { + let rewrite = { + if let Some(ref e) = block.expr { + let suffix = if semicolon_for_expr(e) { + ";" + } else { + "" + }; + + e.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent) + .map(|s| s + suffix) + .or_else(|| Some(self.snippet(e.span))) + } else if let Some(ref stmt) = block.stmts.first() { + self.rewrite_stmt(stmt) + } else { + None + } + }; + + if let Some(res) = rewrite { + let width = self.block_indent.width() + fn_str.len() + res.len() + 3; + if !res.contains('\n') && width <= self.config.max_width { + return Some(format!("{}{{ {} }}", fn_str, res)); + } + } + } + + None + } + + pub fn rewrite_stmt(&self, stmt: &ast::Stmt) -> Option { + match stmt.node { + ast::Stmt_::StmtDecl(ref decl, _) => { + if let ast::Decl_::DeclLocal(ref local) = decl.node { + let context = self.get_context(); + local.rewrite(&context, self.config.max_width, self.block_indent) + } else { + None + } + } + ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { + let suffix = if semicolon_for_stmt(stmt) { + ";" + } else { + "" + }; + + ex.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width() - suffix.len(), + self.block_indent) + .map(|s| s + suffix) + } + ast::Stmt_::StmtMac(..) => None, + } + } + fn rewrite_args(&self, args: &[ast::Arg], explicit_self: Option<&ast::ExplicitSelf>, @@ -1317,3 +1392,23 @@ fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { ast::WherePredicate::EqPredicate(ref p) => p.span, } } + +// Checks whether a block contains at most one statement or expression, and no comments. +fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { + if (!block.stmts.is_empty() && block.expr.is_some()) || + (block.stmts.len() != 1 && block.expr.is_none()) { + return false; + } + + let snippet = codemap.span_to_snippet(block.span).unwrap(); + !contains_comment(&snippet) +} + +fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { + if !block.stmts.is_empty() || block.expr.is_some() { + return false; + } + + let snippet = codemap.span_to_snippet(block.span).unwrap(); + !contains_comment(&snippet) +} diff --git a/src/utils.rs b/src/utils.rs index fea385532d0..3965fc93c57 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -102,6 +102,33 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { .hi } +#[inline] +pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { + match expr.node { + ast::Expr_::ExprRet(..) | + ast::Expr_::ExprAgain(..) | + ast::Expr_::ExprBreak(..) => true, + _ => false, + } +} + +#[inline] +pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::Stmt_::StmtSemi(ref expr, _) => { + match expr.node { + ast::Expr_::ExprWhile(..) | + ast::Expr_::ExprWhileLet(..) | + ast::Expr_::ExprLoop(..) | + ast::Expr_::ExprForLoop(..) => false, + _ => true, + } + } + ast::Stmt_::StmtExpr(..) => false, + _ => true, + } +} + #[inline] #[cfg(target_pointer_width="64")] // Based on the trick layed out at diff --git a/src/visitor.rs b/src/visitor.rs index f19ff1f7e8b..534e8b112e4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -38,28 +38,15 @@ impl<'a> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { match stmt.node { ast::Stmt_::StmtDecl(ref decl, _) => { - match decl.node { - ast::Decl_::DeclLocal(ref local) => { - let rewrite = { - let context = self.get_context(); - local.rewrite(&context, self.config.max_width, self.block_indent) - }; - self.push_rewrite(stmt.span, rewrite); - } - ast::Decl_::DeclItem(ref item) => self.visit_item(item), + if let ast::Decl_::DeclItem(ref item) = decl.node { + self.visit_item(item); + } else { + let rewrite = self.rewrite_stmt(stmt); + self.push_rewrite(stmt.span, rewrite); } } - ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { - let suffix = if semicolon_for_stmt(stmt) { - ";" - } else { - "" - }; - let rewrite = ex.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width() - - suffix.len(), - self.block_indent) - .map(|s| s + suffix); + ast::Stmt_::StmtExpr(..) | ast::Stmt_::StmtSemi(..) => { + let rewrite = self.rewrite_stmt(stmt); self.push_rewrite(stmt.span, rewrite); } ast::Stmt_::StmtMac(ref mac, _macro_style) => { @@ -101,7 +88,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&rewrite); self.last_pos = e.span.hi; - if semicolon_for_expr(e) { + if utils::semicolon_for_expr(e) { self.buffer.push_str(";"); } } @@ -161,6 +148,13 @@ impl<'a> FmtVisitor<'a> { visit::FnKind::Closure => None, }; + if let Some(ref single_line_fn) = self.rewrite_single_line_fn(&rewrite, &b) { + self.format_missing_with_indent(s.lo); + self.buffer.push_str(single_line_fn); + self.last_pos = b.span.hi; + return; + } + if let Some(fn_str) = rewrite { self.format_missing_with_indent(s.lo); self.buffer.push_str(&fn_str); @@ -501,31 +495,6 @@ impl<'a> FmtVisitor<'a> { } } -fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::Stmt_::StmtSemi(ref expr, _) => { - match expr.node { - ast::Expr_::ExprWhile(..) | - ast::Expr_::ExprWhileLet(..) | - ast::Expr_::ExprLoop(..) | - ast::Expr_::ExprForLoop(..) => false, - _ => true, - } - } - ast::Stmt_::StmtExpr(..) => false, - _ => true, - } -} - -fn semicolon_for_expr(expr: &ast::Expr) -> bool { - match expr.node { - ast::Expr_::ExprRet(..) | - ast::Expr_::ExprAgain(..) | - ast::Expr_::ExprBreak(..) => true, - _ => false, - } -} - impl<'a> Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option { let mut result = String::new(); diff --git a/tests/source/fn-single-line.rs b/tests/source/fn-single-line.rs new file mode 100644 index 00000000000..b928de40de4 --- /dev/null +++ b/tests/source/fn-single-line.rs @@ -0,0 +1,74 @@ +// rustfmt-fn_single_line: true +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 0789efc2b63..8b793c9a925 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -13,8 +13,7 @@ impl Bar { /// Blah blah blooo. /// Blah blah blooo. #[an_attribute] - fn foo(&mut self) -> isize { - } + fn foo(&mut self) -> isize { } /// Blah blah bing. /// Blah blah bing. @@ -28,8 +27,7 @@ impl Bar { } #[another_attribute] - fn f3(self) -> Dog { - } + fn f3(self) -> Dog { } /// Blah blah bing. #[attrib1] @@ -38,6 +36,5 @@ impl Bar { // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo // loooooooooooong. /// Blah blah bing. - fn f4(self) -> Cat { - } + fn f4(self) -> Cat { } } diff --git a/tests/target/comment.rs b/tests/target/comment.rs index c3191381653..04053bd804a 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -32,8 +32,7 @@ fn test() { } /// test123 -fn doc_comment() { -} +fn doc_comment() { } fn chains() { foo.bar(|| { diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 57b6ae63381..c96489b0817 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -16,8 +16,6 @@ fn foo(a: aaaaaaaaaaaaa, // A comment } -fn bar() { -} +fn bar() { } -fn baz() -> Baz /* Comment after return type */ { -} +fn baz() -> Baz /* Comment after return type */ { } diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 9e635e31a3c..0f46b6d1318 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -28,15 +28,13 @@ fn generic(arg: T) -> &SomeType arg(a, b, c, d, e) } -fn foo() -> ! { -} +fn foo() -> ! { } pub fn http_fetch_async(listener: Box, script_chan: Box) { } -fn some_func>(val: T) { -} +fn some_func>(val: T) { } fn zzzzzzzzzzzzzzzzzzzz(selff: Type, mut handle: node::Handle>, diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs new file mode 100644 index 00000000000..205ab897207 --- /dev/null +++ b/tests/target/fn-single-line.rs @@ -0,0 +1,61 @@ +// rustfmt-fn_single_line: true +// Test single-line functions. + +fn foo_expr() { 1 } + +fn foo_stmt() { foo(); } + +fn foo_decl_local() { let z = 5; } + +fn foo_decl_item(x: &mut i32) { x = 3; } + +fn empty() { } + +fn foo_return() -> String { "yay" } + +fn foo_where() -> T + where T: Sync +{ + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space() { 1 } + +trait CoolTypes { + fn dummy(&self) { } +} + +trait CoolerTypes { + fn dummy(&self) { } +} diff --git a/tests/target/fn.rs b/tests/target/fn.rs index da13a6f05dc..97e1172470f 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -1,8 +1,6 @@ // Tests different fns -fn foo(a: AAAA, b: BBB, c: CCC) -> RetType { - -} +fn foo(a: AAAA, b: BBB, c: CCC) -> RetType { } fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType where T: Blah @@ -34,8 +32,7 @@ fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, } -fn foo B /* paren inside generics */>() { -} +fn foo B /* paren inside generics */>() { } impl Foo { fn with_no_errors(&mut self, f: F) -> T @@ -43,11 +40,9 @@ impl Foo { { } - fn foo(mut self, mut bar: u32) { - } + fn foo(mut self, mut bar: u32) { } - fn bar(self, mut bazz: u32) { - } + fn bar(self, mut bazz: u32) { } } pub fn render<'a, @@ -75,12 +70,9 @@ impl Foo { } } -fn homura>(_: T) { - -} +fn homura>(_: T) { } -fn issue377() -> (Box, Box) { -} +fn issue377() -> (Box, Box) { } fn main() { let _ = function(move || 5); diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index a806f62705e..f39a7bcd53d 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -26,9 +26,7 @@ mod other; // sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff // ffffffffffffffffffffffffffffffffffffffffff -fn foo(a: isize, b: u32 /* blah blah */, c: f64) { - -} +fn foo(a: isize, b: u32 /* blah blah */, c: f64) { } fn foo() -> Box where 'a: 'b, @@ -77,8 +75,7 @@ impl Bar { } #[an_attribute] - fn f3(self) -> Dog { - } + fn f3(self) -> Dog { } } /// The `nodes` and `edges` method each return instantiations of @@ -118,8 +115,7 @@ pub struct Foo<'a, Y: Baz> f: SomeType, // Comment beside a field } -fn foo(ann: &'a (PpAnn + 'a)) { -} +fn foo(ann: &'a (PpAnn + 'a)) { } fn main() { for i in 0i32..4 { diff --git a/tests/target/nestedmod/mod2c.rs b/tests/target/nestedmod/mod2c.rs index 9027adeb212..0a03d2b3994 100644 --- a/tests/target/nestedmod/mod2c.rs +++ b/tests/target/nestedmod/mod2c.rs @@ -1,4 +1,3 @@ // A standard mod -fn a() { -} +fn a() { } diff --git a/tests/target/nestedmod/mymod1/mod3a.rs b/tests/target/nestedmod/mymod1/mod3a.rs index a6399f5565d..febe1ff7b25 100644 --- a/tests/target/nestedmod/mymod1/mod3a.rs +++ b/tests/target/nestedmod/mymod1/mod3a.rs @@ -1,3 +1,2 @@ // Another mod -fn a() { -} +fn a() { } diff --git a/tests/target/nestedmod/submod2/a.rs b/tests/target/nestedmod/submod2/a.rs index 078a1d99f2c..53540b8b659 100644 --- a/tests/target/nestedmod/submod2/a.rs +++ b/tests/target/nestedmod/submod2/a.rs @@ -3,5 +3,4 @@ use c::a; -fn foo() { -} +fn foo() { } diff --git a/tests/target/no_new_line_beginning.rs b/tests/target/no_new_line_beginning.rs index f79c691f085..45590d86ba6 100644 --- a/tests/target/no_new_line_beginning.rs +++ b/tests/target/no_new_line_beginning.rs @@ -1,2 +1 @@ -fn main() { -} +fn main() { } diff --git a/tests/target/paths.rs b/tests/target/paths.rs index 15cc35e69f1..303a4df4a9d 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -19,5 +19,4 @@ fn main() { let x: Foo; } -fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { -} +fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { } -- cgit 1.4.1-3-g733a5 From 22837b07483c91f8fbda2bd1df3e2bb83af5c48d Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Thu, 19 Nov 2015 01:53:25 -0600 Subject: Combine block utilities --- src/expr.rs | 21 +++++++++++++++++++++ src/items.rs | 26 +++----------------------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c4b01e38b42..7616ef0c328 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -688,6 +688,27 @@ fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { !contains_comment(&snippet) } +/// Checks whether a block contains at most one statement or expression, and no comments. +pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { + if (!block.stmts.is_empty() && block.expr.is_some()) || + (block.stmts.len() != 1 && block.expr.is_none()) { + return false; + } + + let snippet = codemap.span_to_snippet(block.span).unwrap(); + !contains_comment(&snippet) +} + +/// Checks whether a block contains no statements, expressions, or comments. +pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { + if !block.stmts.is_empty() || block.expr.is_some() { + return false; + } + + let snippet = codemap.span_to_snippet(block.span).unwrap(); + !contains_comment(&snippet) +} + // inter-match-arm-comment-rules: // - all comments following a match arm before the start of the next arm // are about the second arm diff --git a/src/items.rs b/src/items.rs index 58ddea0c483..f16f5b50e6d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,14 +15,14 @@ use utils::{format_mutability, format_visibility, contains_skip, span_after, end wrap_str, last_line_width, semicolon_for_expr, semicolon_for_stmt}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; -use expr::rewrite_assign_rhs; -use comment::{FindUncommented, contains_comment}; +use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; +use comment::FindUncommented; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; use syntax::{ast, abi}; -use syntax::codemap::{Span, BytePos, CodeMap, mk_sp}; +use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::print::pprust; use syntax::parse::token; @@ -1392,23 +1392,3 @@ fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { ast::WherePredicate::EqPredicate(ref p) => p.span, } } - -// Checks whether a block contains at most one statement or expression, and no comments. -fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { - if (!block.stmts.is_empty() && block.expr.is_some()) || - (block.stmts.len() != 1 && block.expr.is_none()) { - return false; - } - - let snippet = codemap.span_to_snippet(block.span).unwrap(); - !contains_comment(&snippet) -} - -fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { - if !block.stmts.is_empty() || block.expr.is_some() { - return false; - } - - let snippet = codemap.span_to_snippet(block.span).unwrap(); - !contains_comment(&snippet) -} -- cgit 1.4.1-3-g733a5 From fbd1398c925fb51d72c3764133e1d35679cb53c2 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Thu, 19 Nov 2015 02:08:17 -0600 Subject: Implement Rewrite for ast::Stmt --- src/expr.rs | 30 +++++++++++++++++++++++++++++- src/items.rs | 32 ++++---------------------------- src/visitor.rs | 10 ++++++++-- tests/source/fn-single-line.rs | 2 ++ tests/target/fn-single-line.rs | 2 ++ 5 files changed, 45 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7616ef0c328..5ec12876c4b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -17,7 +17,8 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; use string::{StringFormat, rewrite_string}; -use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search, first_line_width}; +use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, + semicolon_for_stmt}; use visitor::FmtVisitor; use config::{StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; @@ -475,6 +476,33 @@ impl Rewrite for ast::Block { } } +impl Rewrite for ast::Stmt { + fn rewrite(&self, context: &RewriteContext, _width: usize, offset: Indent) -> Option { + match self.node { + ast::Stmt_::StmtDecl(ref decl, _) => { + if let ast::Decl_::DeclLocal(ref local) = decl.node { + local.rewrite(context, context.config.max_width, offset) + } else { + None + } + } + ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { + let suffix = if semicolon_for_stmt(self) { + ";" + } else { + "" + }; + + ex.rewrite(context, + context.config.max_width - offset.width() - suffix.len(), + offset) + .map(|s| s + suffix) + } + ast::Stmt_::StmtMac(..) => None, + } + } +} + // Abstraction over for, while and loop expressions struct Loop<'a> { cond: Option<&'a ast::Expr>, diff --git a/src/items.rs b/src/items.rs index f16f5b50e6d..eac01242737 100644 --- a/src/items.rs +++ b/src/items.rs @@ -12,7 +12,7 @@ use Indent; use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, - wrap_str, last_line_width, semicolon_for_expr, semicolon_for_stmt}; + wrap_str, last_line_width, semicolon_for_expr}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; @@ -479,7 +479,9 @@ impl<'a> FmtVisitor<'a> { .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } else if let Some(ref stmt) = block.stmts.first() { - self.rewrite_stmt(stmt) + stmt.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent) } else { None } @@ -496,32 +498,6 @@ impl<'a> FmtVisitor<'a> { None } - pub fn rewrite_stmt(&self, stmt: &ast::Stmt) -> Option { - match stmt.node { - ast::Stmt_::StmtDecl(ref decl, _) => { - if let ast::Decl_::DeclLocal(ref local) = decl.node { - let context = self.get_context(); - local.rewrite(&context, self.config.max_width, self.block_indent) - } else { - None - } - } - ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { - let suffix = if semicolon_for_stmt(stmt) { - ";" - } else { - "" - }; - - ex.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width() - suffix.len(), - self.block_indent) - .map(|s| s + suffix) - } - ast::Stmt_::StmtMac(..) => None, - } - } - fn rewrite_args(&self, args: &[ast::Arg], explicit_self: Option<&ast::ExplicitSelf>, diff --git a/src/visitor.rs b/src/visitor.rs index 534e8b112e4..6b98fd276b6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -41,12 +41,18 @@ impl<'a> FmtVisitor<'a> { if let ast::Decl_::DeclItem(ref item) = decl.node { self.visit_item(item); } else { - let rewrite = self.rewrite_stmt(stmt); + let rewrite = stmt.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent); + self.push_rewrite(stmt.span, rewrite); } } ast::Stmt_::StmtExpr(..) | ast::Stmt_::StmtSemi(..) => { - let rewrite = self.rewrite_stmt(stmt); + let rewrite = stmt.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent); + self.push_rewrite(stmt.span, rewrite); } ast::Stmt_::StmtMac(ref mac, _macro_style) => { diff --git a/tests/source/fn-single-line.rs b/tests/source/fn-single-line.rs index b928de40de4..a34371f55ad 100644 --- a/tests/source/fn-single-line.rs +++ b/tests/source/fn-single-line.rs @@ -64,6 +64,8 @@ fn lots_of_space () 1 } +fn mac() -> Vec { vec![] } + trait CoolTypes { fn dummy(&self) { } diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs index 205ab897207..57c926e83e4 100644 --- a/tests/target/fn-single-line.rs +++ b/tests/target/fn-single-line.rs @@ -52,6 +52,8 @@ fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { fn lots_of_space() { 1 } +fn mac() -> Vec { vec![] } + trait CoolTypes { fn dummy(&self) { } } -- cgit 1.4.1-3-g733a5 From b3f41e82fcf9423beaf938308f2034f5dfa508cb Mon Sep 17 00:00:00 2001 From: David Barnett Date: Fri, 20 Nov 2015 10:37:00 +1300 Subject: Use tactic instead of config Add mixed test Mixed is unreachable as there is no input combination that could get to this value --- src/expr.rs | 7 ++++--- tests/source/struct_lits.rs | 3 +++ tests/target/struct_lits.rs | 8 ++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5a281f2df83..7e0407465b9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1335,9 +1335,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }, indent: indent, width: budget, - ends_with_newline: match context.config.struct_lit_style { - StructLitStyle::Block => true, - StructLitStyle::Visual => false, + ends_with_newline: match tactic { + DefinitiveListTactic::Horizontal => false, + DefinitiveListTactic::Vertical => true, + DefinitiveListTactic::Mixed => unreachable!(), }, config: context.config, }; diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 98ac6fab799..0c30d721c4d 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -110,4 +110,7 @@ fn issue491() { Foo { arm: 0, // Comment }; + + Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ + e: eeeeeeeee }; } diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 3ece0cb23a3..a08222f8f13 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -140,4 +140,12 @@ fn issue491() { }; Foo { arm: 0 /* Comment */ }; + + Foo { + a: aaaaaaaaaa, + b: bbbbbbbb, + c: cccccccccc, + d: dddddddddd, // a comment + e: eeeeeeeee, + }; } -- cgit 1.4.1-3-g733a5 From d7b331bea79361642e016b61ba2cd174410d450b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 19 Nov 2015 17:56:37 -0800 Subject: Use argv[0] for usage output Usage messages traditionally use this as it contains the path that the user provided to run the executable (e.g. `rustfmt` instead of `/usr/local/bin/rustfmt`). --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 789f8773345..d5b34d98b2d 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -164,7 +164,7 @@ fn main() { fn print_usage(opts: &Options, reason: &str) { let reason = format!("{}\nusage: {} [options] ...", reason, - env::current_exe().unwrap().display()); + env::args_os().next().unwrap().to_string_lossy()); println!("{}", opts.usage(&reason)); } -- cgit 1.4.1-3-g733a5 From 15ec5b291292f87697b32f30cc31f863538959a2 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Thu, 19 Nov 2015 20:11:32 -0600 Subject: Fix empty body format, add fn_empty_single_line option, refactor block tests --- src/config.rs | 1 + src/expr.rs | 29 +++++++++-------------------- src/items.rs | 17 ++++++++--------- src/visitor.rs | 15 +++++++-------- tests/target/attrib.rs | 6 +++--- tests/target/comment.rs | 2 +- tests/target/comments-fn.rs | 4 ++-- tests/target/fn-simple.rs | 4 ++-- tests/target/fn-single-line.rs | 6 +++--- tests/target/fn.rs | 12 ++++++------ tests/target/multiple.rs | 6 +++--- tests/target/nestedmod/mod2c.rs | 2 +- tests/target/nestedmod/mymod1/mod3a.rs | 2 +- tests/target/nestedmod/submod2/a.rs | 2 +- tests/target/no_new_line_beginning.rs | 2 +- tests/target/paths.rs | 2 +- 16 files changed, 50 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7d56e3e8a80..295c1076b5f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -269,6 +269,7 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; + fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, "Location of return type in function declaration"; diff --git a/src/expr.rs b/src/expr.rs index 5ec12876c4b..b494cb08fcc 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -705,36 +705,25 @@ fn single_line_if_else(context: &RewriteContext, None } -// Checks that a block contains no statements, an expression and no comments. -fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { - if !block.stmts.is_empty() || block.expr.is_none() { - return false; - } - +fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { let snippet = codemap.span_to_snippet(block.span).unwrap(); + contains_comment(&snippet) +} - !contains_comment(&snippet) +// Checks that a block contains no statements, an expression and no comments. +pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { + block.stmts.is_empty() && block.expr.is_some() && !block_contains_comment(block, codemap) } /// Checks whether a block contains at most one statement or expression, and no comments. pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { - if (!block.stmts.is_empty() && block.expr.is_some()) || - (block.stmts.len() != 1 && block.expr.is_none()) { - return false; - } - - let snippet = codemap.span_to_snippet(block.span).unwrap(); - !contains_comment(&snippet) + (block.stmts.is_empty() || (block.stmts.len() == 1 && block.expr.is_none())) && + !block_contains_comment(block, codemap) } /// Checks whether a block contains no statements, expressions, or comments. pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { - if !block.stmts.is_empty() || block.expr.is_some() { - return false; - } - - let snippet = codemap.span_to_snippet(block.span).unwrap(); - !contains_comment(&snippet) + block.stmts.is_empty() && block.expr.is_none() && !block_contains_comment(block, codemap) } // inter-match-arm-comment-rules: diff --git a/src/items.rs b/src/items.rs index eac01242737..01418a08a9a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -448,20 +448,19 @@ impl<'a> FmtVisitor<'a> { } pub fn rewrite_single_line_fn(&self, - fn_rewrite: &Option, + fn_str: &str, block: &ast::Block) -> Option { - let fn_str = match *fn_rewrite { - Some(ref s) if !s.contains('\n') => s, - _ => return None, - }; + if fn_str.contains('\n') { + return None; + } let codemap = self.get_context().codemap; - if is_empty_block(block, codemap) && - self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width { - return Some(format!("{}{{ }}", fn_str)); + if self.config.fn_empty_single_line && is_empty_block(block, codemap) && + self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width { + return Some(format!("{}{{}}", fn_str)); } if self.config.fn_single_line && is_simple_block_stmt(block, codemap) { @@ -488,7 +487,7 @@ impl<'a> FmtVisitor<'a> { }; if let Some(res) = rewrite { - let width = self.block_indent.width() + fn_str.len() + res.len() + 3; + let width = self.block_indent.width() + fn_str.len() + res.len() + 4; if !res.contains('\n') && width <= self.config.max_width { return Some(format!("{}{{ {} }}", fn_str, res)); } diff --git a/src/visitor.rs b/src/visitor.rs index 6b98fd276b6..b51274b4d8d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -154,16 +154,15 @@ impl<'a> FmtVisitor<'a> { visit::FnKind::Closure => None, }; - if let Some(ref single_line_fn) = self.rewrite_single_line_fn(&rewrite, &b) { - self.format_missing_with_indent(s.lo); - self.buffer.push_str(single_line_fn); - self.last_pos = b.span.hi; - return; - } - if let Some(fn_str) = rewrite { self.format_missing_with_indent(s.lo); - self.buffer.push_str(&fn_str); + if let Some(ref single_line_fn) = self.rewrite_single_line_fn(&fn_str, &b) { + self.buffer.push_str(single_line_fn); + self.last_pos = b.span.hi; + return; + } else { + self.buffer.push_str(&fn_str); + } } else { self.format_missing(b.span.lo); } diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 8b793c9a925..9317a837065 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -13,7 +13,7 @@ impl Bar { /// Blah blah blooo. /// Blah blah blooo. #[an_attribute] - fn foo(&mut self) -> isize { } + fn foo(&mut self) -> isize {} /// Blah blah bing. /// Blah blah bing. @@ -27,7 +27,7 @@ impl Bar { } #[another_attribute] - fn f3(self) -> Dog { } + fn f3(self) -> Dog {} /// Blah blah bing. #[attrib1] @@ -36,5 +36,5 @@ impl Bar { // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo // loooooooooooong. /// Blah blah bing. - fn f4(self) -> Cat { } + fn f4(self) -> Cat {} } diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 04053bd804a..2d90d83edb6 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -32,7 +32,7 @@ fn test() { } /// test123 -fn doc_comment() { } +fn doc_comment() {} fn chains() { foo.bar(|| { diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index c96489b0817..fa607e131ea 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -16,6 +16,6 @@ fn foo(a: aaaaaaaaaaaaa, // A comment } -fn bar() { } +fn bar() {} -fn baz() -> Baz /* Comment after return type */ { } +fn baz() -> Baz /* Comment after return type */ {} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 0f46b6d1318..9db1c8831b6 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -28,13 +28,13 @@ fn generic(arg: T) -> &SomeType arg(a, b, c, d, e) } -fn foo() -> ! { } +fn foo() -> ! {} pub fn http_fetch_async(listener: Box, script_chan: Box) { } -fn some_func>(val: T) { } +fn some_func>(val: T) {} fn zzzzzzzzzzzzzzzzzzzz(selff: Type, mut handle: node::Handle>, diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs index 57c926e83e4..674ce1c89f9 100644 --- a/tests/target/fn-single-line.rs +++ b/tests/target/fn-single-line.rs @@ -9,7 +9,7 @@ fn foo_decl_local() { let z = 5; } fn foo_decl_item(x: &mut i32) { x = 3; } -fn empty() { } +fn empty() {} fn foo_return() -> String { "yay" } @@ -55,9 +55,9 @@ fn lots_of_space() { 1 } fn mac() -> Vec { vec![] } trait CoolTypes { - fn dummy(&self) { } + fn dummy(&self) {} } trait CoolerTypes { - fn dummy(&self) { } + fn dummy(&self) {} } diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 97e1172470f..0ae9fd7ef1f 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -1,6 +1,6 @@ // Tests different fns -fn foo(a: AAAA, b: BBB, c: CCC) -> RetType { } +fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType where T: Blah @@ -32,7 +32,7 @@ fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, } -fn foo B /* paren inside generics */>() { } +fn foo B /* paren inside generics */>() {} impl Foo { fn with_no_errors(&mut self, f: F) -> T @@ -40,9 +40,9 @@ impl Foo { { } - fn foo(mut self, mut bar: u32) { } + fn foo(mut self, mut bar: u32) {} - fn bar(self, mut bazz: u32) { } + fn bar(self, mut bazz: u32) {} } pub fn render<'a, @@ -70,9 +70,9 @@ impl Foo { } } -fn homura>(_: T) { } +fn homura>(_: T) {} -fn issue377() -> (Box, Box) { } +fn issue377() -> (Box, Box) {} fn main() { let _ = function(move || 5); diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index f39a7bcd53d..7b371409fba 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -26,7 +26,7 @@ mod other; // sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff // ffffffffffffffffffffffffffffffffffffffffff -fn foo(a: isize, b: u32 /* blah blah */, c: f64) { } +fn foo(a: isize, b: u32 /* blah blah */, c: f64) {} fn foo() -> Box where 'a: 'b, @@ -75,7 +75,7 @@ impl Bar { } #[an_attribute] - fn f3(self) -> Dog { } + fn f3(self) -> Dog {} } /// The `nodes` and `edges` method each return instantiations of @@ -115,7 +115,7 @@ pub struct Foo<'a, Y: Baz> f: SomeType, // Comment beside a field } -fn foo(ann: &'a (PpAnn + 'a)) { } +fn foo(ann: &'a (PpAnn + 'a)) {} fn main() { for i in 0i32..4 { diff --git a/tests/target/nestedmod/mod2c.rs b/tests/target/nestedmod/mod2c.rs index 0a03d2b3994..7db4572e777 100644 --- a/tests/target/nestedmod/mod2c.rs +++ b/tests/target/nestedmod/mod2c.rs @@ -1,3 +1,3 @@ // A standard mod -fn a() { } +fn a() {} diff --git a/tests/target/nestedmod/mymod1/mod3a.rs b/tests/target/nestedmod/mymod1/mod3a.rs index febe1ff7b25..ae09d8ddac0 100644 --- a/tests/target/nestedmod/mymod1/mod3a.rs +++ b/tests/target/nestedmod/mymod1/mod3a.rs @@ -1,2 +1,2 @@ // Another mod -fn a() { } +fn a() {} diff --git a/tests/target/nestedmod/submod2/a.rs b/tests/target/nestedmod/submod2/a.rs index 53540b8b659..120b17145e3 100644 --- a/tests/target/nestedmod/submod2/a.rs +++ b/tests/target/nestedmod/submod2/a.rs @@ -3,4 +3,4 @@ use c::a; -fn foo() { } +fn foo() {} diff --git a/tests/target/no_new_line_beginning.rs b/tests/target/no_new_line_beginning.rs index 45590d86ba6..f328e4d9d04 100644 --- a/tests/target/no_new_line_beginning.rs +++ b/tests/target/no_new_line_beginning.rs @@ -1 +1 @@ -fn main() { } +fn main() {} diff --git a/tests/target/paths.rs b/tests/target/paths.rs index 303a4df4a9d..f1b142b3a5c 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -19,4 +19,4 @@ fn main() { let x: Foo; } -fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult { } +fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {} -- cgit 1.4.1-3-g733a5 From 2e9b6dfab49411fd9a043f03c5f74fb32a0ed272 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Thu, 19 Nov 2015 20:49:24 -0600 Subject: Combine rewrite_single_line_fn and rewrite_fn --- src/items.rs | 10 ++++------ src/visitor.rs | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 01418a08a9a..c7cfc732fc1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -177,7 +177,8 @@ impl<'a> FmtVisitor<'a> { constness: ast::Constness, abi: abi::Abi, vis: ast::Visibility, - span: Span) + span: Span, + block: &ast::Block) -> Option { let mut newline_brace = self.newline_for_brace(&generics.where_clause); @@ -212,7 +213,7 @@ impl<'a> FmtVisitor<'a> { result.push(' '); } - Some(result) + self.single_line_fn(&result, block).or_else(|| Some(result)) } pub fn rewrite_required_fn(&mut self, @@ -447,10 +448,7 @@ impl<'a> FmtVisitor<'a> { Some((result, force_new_line_for_brace)) } - pub fn rewrite_single_line_fn(&self, - fn_str: &str, - block: &ast::Block) - -> Option { + fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { if fn_str.contains('\n') { return None; diff --git a/src/visitor.rs b/src/visitor.rs index b51274b4d8d..fa51d70a853 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -137,7 +137,8 @@ impl<'a> FmtVisitor<'a> { constness, abi, vis, - codemap::mk_sp(s.lo, b.span.lo)) + codemap::mk_sp(s.lo, b.span.lo), + &b) } visit::FnKind::Method(ident, ref sig, vis) => { self.rewrite_fn(indent, @@ -149,19 +150,20 @@ impl<'a> FmtVisitor<'a> { sig.constness, sig.abi, vis.unwrap_or(ast::Visibility::Inherited), - codemap::mk_sp(s.lo, b.span.lo)) + codemap::mk_sp(s.lo, b.span.lo), + &b) } visit::FnKind::Closure => None, }; if let Some(fn_str) = rewrite { self.format_missing_with_indent(s.lo); - if let Some(ref single_line_fn) = self.rewrite_single_line_fn(&fn_str, &b) { - self.buffer.push_str(single_line_fn); - self.last_pos = b.span.hi; - return; - } else { - self.buffer.push_str(&fn_str); + self.buffer.push_str(&fn_str); + if let Some(c) = fn_str.chars().last() { + if c == '}' { + self.last_pos = b.span.hi; + return; + } } } else { self.format_missing(b.span.lo); -- cgit 1.4.1-3-g733a5 From 8f3a29d1a74c1c8b8499426d640b7a866f03fabf Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 20 Nov 2015 21:05:10 +0100 Subject: Blockify multiline match arms --- src/comment.rs | 68 ++++++++++++++++++++---------------- src/expr.rs | 75 +++++++++++++++++++++++++--------------- src/items.rs | 20 ++++++----- src/missed_spans.rs | 10 +++--- tests/system.rs | 6 ++-- tests/target/match.rs | 95 ++++++++++++++++++++++++++++++--------------------- 6 files changed, 165 insertions(+), 109 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index eb6c5fc75ec..0f118ca5d29 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -127,12 +127,14 @@ impl FindUncommented for str { None => { return Some(i - pat.len()); } - Some(c) => match kind { - CodeCharKind::Normal if b == c => {} - _ => { - needle_iter = pat.chars(); + Some(c) => { + match kind { + CodeCharKind::Normal if b == c => {} + _ => { + needle_iter = pat.chars(); + } } - }, + } } } @@ -233,33 +235,39 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { let item = try_opt!(self.base.next()); let chr = item.get_char(); self.status = match self.status { - CharClassesStatus::LitString => match chr { - '"' => CharClassesStatus::Normal, - '\\' => CharClassesStatus::LitStringEscape, - _ => CharClassesStatus::LitString, - }, + CharClassesStatus::LitString => { + match chr { + '"' => CharClassesStatus::Normal, + '\\' => CharClassesStatus::LitStringEscape, + _ => CharClassesStatus::LitString, + } + } CharClassesStatus::LitStringEscape => CharClassesStatus::LitString, - CharClassesStatus::LitChar => match chr { - '\\' => CharClassesStatus::LitCharEscape, - '\'' => CharClassesStatus::Normal, - _ => CharClassesStatus::LitChar, - }, + CharClassesStatus::LitChar => { + match chr { + '\\' => CharClassesStatus::LitCharEscape, + '\'' => CharClassesStatus::Normal, + _ => CharClassesStatus::LitChar, + } + } CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, CharClassesStatus::Normal => { match chr { '"' => CharClassesStatus::LitString, '\'' => CharClassesStatus::LitChar, - '/' => match self.base.peek() { - Some(next) if next.get_char() == '*' => { - self.status = CharClassesStatus::BlockCommentOpening(1); - return Some((CodeCharKind::Comment, item)); - } - Some(next) if next.get_char() == '/' => { - self.status = CharClassesStatus::LineComment; - return Some((CodeCharKind::Comment, item)); + '/' => { + match self.base.peek() { + Some(next) if next.get_char() == '*' => { + self.status = CharClassesStatus::BlockCommentOpening(1); + return Some((CodeCharKind::Comment, item)); + } + Some(next) if next.get_char() == '/' => { + self.status = CharClassesStatus::LineComment; + return Some((CodeCharKind::Comment, item)); + } + _ => CharClassesStatus::Normal, } - _ => CharClassesStatus::Normal, - }, + } _ => CharClassesStatus::Normal, } } @@ -271,10 +279,12 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { return Some((CodeCharKind::Comment, item)); } self.status = match self.base.peek() { - Some(next) if next.get_char() == '/' && chr == '*' => - CharClassesStatus::BlockCommentClosing(deepness - 1), - Some(next) if next.get_char() == '*' && chr == '/' => - CharClassesStatus::BlockCommentOpening(deepness + 1), + Some(next) if next.get_char() == '/' && chr == '*' => { + CharClassesStatus::BlockCommentClosing(deepness - 1) + } + Some(next) if next.get_char() == '*' && chr == '/' => { + CharClassesStatus::BlockCommentOpening(deepness + 1) + } _ => CharClassesStatus::BlockComment(deepness), }; return Some((CodeCharKind::Comment, item)); diff --git a/src/expr.rs b/src/expr.rs index 8b5fa9fa787..3247e98c13a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -571,13 +571,15 @@ impl<'a> Rewrite for Loop<'a> { let inner_offset = offset + self.keyword.len() + label_string.len(); let pat_expr_string = match self.cond { - Some(cond) => try_opt!(rewrite_pat_expr(context, - self.pat, - cond, - self.matcher, - self.connector, - inner_width, - inner_offset)), + Some(cond) => { + try_opt!(rewrite_pat_expr(context, + self.pat, + cond, + self.matcher, + self.connector, + inner_width, + inner_offset)) + } None => String::new(), }; @@ -711,6 +713,8 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { } // Checks that a block contains no statements, an expression and no comments. +// FIXME: incorrectly returns false when comment is contained completely within +// the expression. pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { block.stmts.is_empty() && block.expr.is_some() && !block_contains_comment(block, codemap) } @@ -936,6 +940,11 @@ impl Rewrite for ast::Arm { let comma = arm_comma(body); + // let body = match *body { + // ast::ExprBlock(ref b) if is_simple_block(b, context.codemap) => b.expr, + // ref x => x, + // }; + // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() let same_line_body = if context.config.max_width > line_start + comma.len() + 4 { @@ -944,12 +953,13 @@ impl Rewrite for ast::Arm { let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); match rewrite { - Some(ref body_str) if body_str.len() <= budget || comma.is_empty() => + Some(ref body_str) if body_str.len() <= budget || comma.is_empty() => { return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, body_str, - comma)), + comma)); + } _ => rewrite, } } else { @@ -961,26 +971,34 @@ impl Rewrite for ast::Arm { return None; } - let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let indent = context.block_indent.block_indent(context.config); - let inner_context = &RewriteContext { block_indent: indent, ..*context }; - let next_line_body = nop_block_collapse(body.rewrite(inner_context, body_budget, indent), - body_budget); + let mut result = format!("{}{} =>", attr_str.trim_left(), pats_str); - let body_str = try_opt!(match_arm_heuristic(same_line_body.as_ref().map(|x| &x[..]), - next_line_body.as_ref().map(|x| &x[..]))); - - let spacer = match same_line_body { - Some(ref body) if body == body_str => " ".to_owned(), - _ => format!("\n{}", - offset.block_indent(context.config).to_string(context.config)), + match same_line_body { + // FIXME: also take this branch is expr is block + Some(ref body) if !body.contains('\n') => { + result.push(' '); + result.push_str(&body); + } + _ => { + let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); + let indent = context.block_indent.block_indent(context.config); + let inner_context = &RewriteContext { block_indent: indent, ..*context }; + let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context, + body_budget, + indent), + body_budget)); + + result.push_str(" {\n"); + let indent_str = offset.block_indent(context.config).to_string(context.config); + result.push_str(&indent_str); + result.push_str(&next_line_body); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + result.push('}'); + } }; - Some(format!("{}{} =>{}{},", - attr_str.trim_left(), - pats_str, - spacer, - body_str)) + Some(result) } } @@ -1396,8 +1414,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { - (StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => - format_on_newline(), + (StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => { + format_on_newline() + } (StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(), _ => Some(format!("{} {{ {} }}", path_str, fields_str)), } diff --git a/src/items.rs b/src/items.rs index c7cfc732fc1..60d08743a95 100644 --- a/src/items.rs +++ b/src/items.rs @@ -564,23 +564,26 @@ impl<'a> FmtVisitor<'a> { ")", |arg| { match *arg { - ArgumentKind::Regular(arg) => - span_lo_for_arg(arg), + ArgumentKind::Regular(arg) => { + span_lo_for_arg(arg) + } ArgumentKind::Variadic(start) => start, } }, |arg| { match *arg { ArgumentKind::Regular(arg) => arg.ty.span.hi, - ArgumentKind::Variadic(start) => - start + BytePos(3), + ArgumentKind::Variadic(start) => { + start + BytePos(3) + } } }, |arg| { match *arg { ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => - Some("...".to_owned()), + ArgumentKind::Variadic(..) => { + Some("...".to_owned()) + } } }, comment_span_start, @@ -1118,8 +1121,9 @@ impl<'a> FmtVisitor<'a> { let extra_indent = match self.config.where_indent { BlockIndentStyle::Inherit => Indent::empty(), - BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => - Indent::new(config.tab_spaces, 0), + BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => { + Indent::new(config.tab_spaces, 0) + } }; let context = self.get_context(); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b83f07e05d7..727bc49a742 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -103,10 +103,12 @@ impl<'a> FmtVisitor<'a> { } let replaced = match self.write_mode { - Some(mode) => match mode { - WriteMode::Coverage => replace_chars(old_snippet), - _ => old_snippet.to_owned(), - }, + Some(mode) => { + match mode { + WriteMode::Coverage => replace_chars(old_snippet), + _ => old_snippet.to_owned(), + } + } None => old_snippet.to_owned(), }; let snippet = &*replaced; diff --git a/tests/system.rs b/tests/system.rs index 4a924c57833..6d3c817256c 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -249,8 +249,10 @@ fn handle_result(result: HashMap, fn get_target(file_name: &str, target: Option<&str>, write_mode: WriteMode) -> String { let file_path = Path::new(file_name); let (source_path_prefix, target_path_prefix) = match write_mode { - WriteMode::Coverage => (Path::new("tests/coverage-source/"), - "tests/coverage-target/"), + WriteMode::Coverage => { + (Path::new("tests/coverage-source/"), + "tests/coverage-target/") + } _ => (Path::new("tests/source/"), "tests/target/"), }; diff --git a/tests/target/match.rs b/tests/target/match.rs index 1d6842d358a..28a5ce2d98c 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -13,8 +13,9 @@ fn foo() { foo() } // Perhaps this should introduce braces? - Foo(ref bar) => - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Foo(ref bar) => { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } Pattern1 | Pattern2 | Pattern3 => false, Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { @@ -29,8 +30,9 @@ fn foo() { Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, Patternnnnnnnnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => - meh, + Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => { + meh + } // Test that earlier patterns can take the guard space (aaaa, @@ -75,19 +77,24 @@ fn main() { // Test that one-line bodies align. fn main() { match r { - Variableeeeeeeeeeeeeeeeee => ("variable", - vec!["id", "name", "qualname", "value", "type", "scopeid"], - true, - true), - Enummmmmmmmmmmmmmmmmmmmm => ("enum", - vec!["id", "qualname", "scopeid", "value"], - true, - true), - Variantttttttttttttttttttttttt => + Variableeeeeeeeeeeeeeeeee => { + ("variable", + vec!["id", "name", "qualname", "value", "type", "scopeid"], + true, + true) + } + Enummmmmmmmmmmmmmmmmmmmm => { + ("enum", + vec!["id", "qualname", "scopeid", "value"], + true, + true) + } + Variantttttttttttttttttttttttt => { ("variant", vec!["id", "name", "qualname", "type", "value", "scopeid"], true, - true), + true) + } } } @@ -176,22 +183,28 @@ fn issue355() { // m comment m => vec!(3; 4), // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => - println!("a", b), + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + println!("a", b) + } // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => - vec![1, 2], + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => { + vec![1, 2] + } // Macro support fails to recognise this macro as splitable // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => - vec!(3; 4), + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { + vec!(3; 4) + } // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => - println!("a", b), - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => - vec![1, 2], - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => - vec!(3; 4), + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { + println!("a", b) + } + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => { + vec![1, 2] + } + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { + vec!(3; 4) + } // Funky bracketing styles t => println!{"a", b}, u => vec![1, 2], @@ -206,20 +219,24 @@ fn issue355() { wc => println!["a", b], // comment xc => vec![1, 2], // comment yc => vec![3; 4], // comment - yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd), + yd => { + looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd) + } } } fn issue280() { { match x { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => - ch == '\n', - ast::ItemConst(ref typ, ref expr) => - self.process_static_or_const_item(item, &typ, &expr), + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => { + ch == '\n' + } + ast::ItemConst(ref typ, ref expr) => { + self.process_static_or_const_item(item, &typ, &expr) + } } } } @@ -253,12 +270,13 @@ fn issue496() { { { match def { - def::DefConst(def_id) | def::DefAssociatedConst(def_id) => + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { Some(const_expr) => { x } - }, + } + } } } } @@ -268,14 +286,15 @@ fn issue496() { fn issue494() { { match stmt.node { - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Expr { scope: cx.tcx.region_maps.node_extent(id), expr: expr.to_ref(), }, - }))), + }))) + } } } } -- cgit 1.4.1-3-g733a5 From 6e1f77664df56e3ebf21c35a5a8abb77e68d079c Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 14 Nov 2015 21:57:31 +0100 Subject: Unwrap match arms that are simple blocks --- src/bin/rustfmt.rs | 4 +- src/chains.rs | 16 ++------ src/expr.rs | 110 +++++++++++++++++++------------------------------- src/imports.rs | 8 +--- src/items.rs | 4 +- src/lib.rs | 12 ++---- src/lists.rs | 4 +- src/patterns.rs | 8 +--- src/types.rs | 8 +--- src/utils.rs | 4 +- tests/target/match.rs | 20 +++------ 11 files changed, 64 insertions(+), 134 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index d5b34d98b2d..04251d09c74 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -118,9 +118,7 @@ fn execute() -> i32 { Operation::Stdin(input, write_mode) => { // try to read config from local directory let config = match lookup_and_read_project_file(&Path::new(".")) { - Ok((_, toml)) => { - Config::from_toml(&toml) - } + Ok((_, toml)) => Config::from_toml(&toml), Err(_) => Default::default(), }; diff --git a/src/chains.rs b/src/chains.rs index 31cd9624016..a011ad2ffef 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -171,13 +171,9 @@ fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { fn pop_expr_chain<'a>(expr: &'a ast::Expr) -> Option<&'a ast::Expr> { match expr.node { - ast::Expr_::ExprMethodCall(_, _, ref expressions) => { - Some(&expressions[0]) - } + ast::Expr_::ExprMethodCall(_, _, ref expressions) => Some(&expressions[0]), ast::Expr_::ExprTupField(ref subexpr, _) | - ast::Expr_::ExprField(ref subexpr, _) => { - Some(subexpr) - } + ast::Expr_::ExprField(ref subexpr, _) => Some(subexpr), _ => None, } } @@ -199,12 +195,8 @@ fn rewrite_chain_expr(expr: &ast::Expr, width, offset) } - ast::Expr_::ExprField(_, ref field) => { - Some(format!(".{}", field.node)) - } - ast::Expr_::ExprTupField(_, ref field) => { - Some(format!(".{}", field.node)) - } + ast::Expr_::ExprField(_, ref field) => Some(format!(".{}", field.node)), + ast::Expr_::ExprTupField(_, ref field) => Some(format!(".{}", field.node)), _ => unreachable!(), } } diff --git a/src/expr.rs b/src/expr.rs index 3247e98c13a..a0d7e08878f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -58,9 +58,7 @@ impl Rewrite for ast::Expr { let inner_span = mk_sp(callee.span.hi, self.span.hi); rewrite_call(context, &**callee, args, inner_span, width, offset) } - ast::Expr_::ExprParen(ref subexpr) => { - rewrite_paren(context, subexpr, width, offset) - } + ast::Expr_::ExprParen(ref subexpr) => rewrite_paren(context, subexpr, width, offset), ast::Expr_::ExprBinary(ref op, ref lhs, ref rhs) => { rewrite_binary_op(context, op, lhs, rhs, width, offset) } @@ -91,9 +89,7 @@ impl Rewrite for ast::Expr { ast::Expr_::ExprLoop(ref block, label) => { Loop::new_loop(block, label).rewrite(context, width, offset) } - ast::Expr_::ExprBlock(ref block) => { - block.rewrite(context, width, offset) - } + ast::Expr_::ExprBlock(ref block) => block.rewrite(context, width, offset), ast::Expr_::ExprIf(ref cond, ref if_block, ref else_block) => { rewrite_if_else(context, cond, @@ -145,9 +141,7 @@ impl Rewrite for ast::Expr { } ast::Expr_::ExprField(..) | ast::Expr_::ExprTupField(..) | - ast::Expr_::ExprMethodCall(..) => { - rewrite_chain(self, context, width, offset) - } + ast::Expr_::ExprMethodCall(..) => rewrite_chain(self, context, width, offset), ast::Expr_::ExprMac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. @@ -730,6 +724,14 @@ pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { block.stmts.is_empty() && block.expr.is_none() && !block_contains_comment(block, codemap) } +fn is_unsafe_block(block: &ast::Block) -> bool { + if let ast::BlockCheckMode::UnsafeBlock(..) = block.rules { + true + } else { + false + } +} + // inter-match-arm-comment-rules: // - all comments following a match arm before the start of the next arm // are about the second arm @@ -911,7 +913,7 @@ impl Rewrite for ast::Arm { } let pats_width = if vertical { - pat_strs[pat_strs.len() - 1].len() + pat_strs.last().unwrap().len() } else { total_width }; @@ -938,79 +940,53 @@ impl Rewrite for ast::Arm { line_start += offset.width(); } - let comma = arm_comma(body); + let body = match **body { + ast::Expr { node: ast::ExprBlock(ref b), .. } if !is_unsafe_block(b) && + is_simple_block(b, + context.codemap) => { + b.expr.as_ref().map(|e| &**e).unwrap() + } + ref x => x, + }; - // let body = match *body { - // ast::ExprBlock(ref b) if is_simple_block(b, context.codemap) => b.expr, - // ref x => x, - // }; + let comma = arm_comma(body); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() - let same_line_body = if context.config.max_width > line_start + comma.len() + 4 { + if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); match rewrite { - Some(ref body_str) if body_str.len() <= budget || comma.is_empty() => { + Some(ref body_str) if !body_str.contains('\n') || comma.is_empty() => { return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, body_str, comma)); } - _ => rewrite, + _ => {} } - } else { - None - }; - - if let ast::ExprBlock(_) = body.node { - // We're trying to fit a block in, but it still failed, give up. - return None; } - let mut result = format!("{}{} =>", attr_str.trim_left(), pats_str); - - match same_line_body { - // FIXME: also take this branch is expr is block - Some(ref body) if !body.contains('\n') => { - result.push(' '); - result.push_str(&body); - } - _ => { - let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); - let indent = context.block_indent.block_indent(context.config); - let inner_context = &RewriteContext { block_indent: indent, ..*context }; - let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context, - body_budget, - indent), - body_budget)); - - result.push_str(" {\n"); - let indent_str = offset.block_indent(context.config).to_string(context.config); - result.push_str(&indent_str); - result.push_str(&next_line_body); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - result.push('}'); - } - }; - - Some(result) - } -} - -// Takes two possible rewrites for the match arm body and chooses the "nicest". -fn match_arm_heuristic<'a>(former: Option<&'a str>, latter: Option<&'a str>) -> Option<&'a str> { - match (former, latter) { - (f @ Some(..), None) => f, - (Some(f), Some(l)) if f.chars().filter(|&c| c == '\n').count() <= - l.chars().filter(|&c| c == '\n').count() => { - Some(f) - } - (_, l) => l, + // FIXME: we're doing a second rewrite of the expr -- this may not be + // necessary. + let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); + let indent = context.block_indent.block_indent(context.config); + let inner_context = &RewriteContext { block_indent: indent, ..*context }; + let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context, + body_budget, + indent), + body_budget)); + let indent_str = offset.block_indent(context.config).to_string(context.config); + + Some(format!("{}{} => {{\n{}{}\n{}}}", + attr_str.trim_left(), + pats_str, + indent_str, + next_line_body, + offset.to_string(context.config))) } } @@ -1303,9 +1279,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // Foo { a: Foo } - indent is +3, width is -5. let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); let (indent, v_budget) = match context.config.struct_lit_style { - StructLitStyle::Visual => { - (offset + path_str.len() + 3, h_budget) - } + StructLitStyle::Visual => (offset + path_str.len() + 3, h_budget), StructLitStyle::Block => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. diff --git a/src/imports.rs b/src/imports.rs index 6917b1ff403..42d152fc6ac 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -74,12 +74,8 @@ fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { let path_item_str = match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => { - name.to_string() - } - ast::PathListItem_::PathListMod{ .. } => { - "self".to_owned() - } + ast::PathListItem_::PathListIdent{ name, .. } => name.to_string(), + ast::PathListItem_::PathListMod{ .. } => "self".to_owned(), }; Some(append_alias(path_item_str, vpi)) diff --git a/src/items.rs b/src/items.rs index 60d08743a95..4f3c82ee0ab 100644 --- a/src/items.rs +++ b/src/items.rs @@ -824,9 +824,7 @@ impl<'a> FmtVisitor<'a> { offset: Indent) -> Option { match *struct_def { - ast::VariantData::Unit(..) => { - self.format_unit_struct(item_name, ident, vis) - } + ast::VariantData::Unit(..) => self.format_unit_struct(item_name, ident, vis), ast::VariantData::Tuple(ref fields, _) => { self.format_tuple_struct(item_name, ident, vis, fields, generics, span, offset) } diff --git a/src/lib.rs b/src/lib.rs index bf1a0164f68..3923f6b742d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -225,15 +225,9 @@ pub enum ErrorKind { impl fmt::Display for ErrorKind { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - ErrorKind::LineOverflow => { - write!(fmt, "line exceeded maximum length") - } - ErrorKind::TrailingWhitespace => { - write!(fmt, "left behind trailing whitespace") - } - ErrorKind::BadIssue(issue) => { - write!(fmt, "found {}", issue) - } + ErrorKind::LineOverflow => write!(fmt, "line exceeded maximum length"), + ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), + ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), } } } diff --git a/src/lists.rs b/src/lists.rs index b05e4d46066..ecde4f19fe4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -392,9 +392,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> match (block_open_index, newline_index) { // Separator before comment, with the next item on same line. // Comment belongs to next item. - (Some(i), None) if i > separator_index => { - separator_index + 1 - } + (Some(i), None) if i > separator_index => separator_index + 1, // Block-style post-comment before the separator. (Some(i), None) => { cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, diff --git a/src/patterns.rs b/src/patterns.rs index 3e7a11bad41..af0bd827751 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -21,9 +21,7 @@ use syntax::ast::{BindingMode, Pat, Pat_}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { - Pat_::PatBox(ref pat) => { - rewrite_unary_prefix(context, "box ", &**pat, width, offset) - } + Pat_::PatBox(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, width, offset), Pat_::PatIdent(binding_mode, ident, None) => { let (prefix, mutability) = match binding_mode { BindingMode::BindByRef(mutability) => ("ref ", mutability), @@ -50,9 +48,7 @@ impl Rewrite for Pat { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, width, offset) } - Pat_::PatTup(ref items) => { - rewrite_tuple(context, items, self.span, width, offset) - } + Pat_::PatTup(ref items) => rewrite_tuple(context, items, self.span, width, offset), Pat_::PatEnum(ref path, Some(ref pat_vec)) => { let path_str = try_opt!(::types::rewrite_path(context, true, diff --git a/src/types.rs b/src/types.rs index 9b50333e043..9e693e9cff6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -137,9 +137,7 @@ impl<'a> Rewrite for SegmentParam<'a> { width, offset) } - SegmentParam::Type(ref ty) => { - ty.rewrite(context, width, offset) - } + SegmentParam::Type(ref ty) => ty.rewrite(context, width, offset), SegmentParam::Binding(ref binding) => { let mut result = format!("{} = ", binding.ident); let budget = try_opt!(width.checked_sub(result.len())); @@ -479,9 +477,7 @@ impl Rewrite for ast::Ty { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str)) } - ast::TyTup(ref items) => { - rewrite_tuple(context, items, self.span, width, offset) - } + ast::TyTup(ref items) => rewrite_tuple(context, items, self.span, width, offset), ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), ast::TyPath(ref q_self, ref path) => { rewrite_path(context, false, q_self.as_ref(), path, width, offset) diff --git a/src/utils.rs b/src/utils.rs index 3965fc93c57..37dfb756972 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -75,9 +75,7 @@ pub fn last_line_width(s: &str) -> usize { fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, - MetaItem_::MetaList(ref s, ref l) => { - *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1]) - } + MetaItem_::MetaList(ref s, ref l) => *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1]), _ => false, } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 28a5ce2d98c..b7f41c1dd6b 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -18,9 +18,7 @@ fn foo() { } Pattern1 | Pattern2 | Pattern3 => false, Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { - blah - } + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => blah, Patternnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnn | @@ -164,15 +162,9 @@ fn issue355() { a => println!("a", b), b => vec![1, 2], c => vec!(3; 4), - d => { - println!("a", b) - } - e => { - vec![1, 2] - } - f => { - vec!(3; 4) - } + d => println!("a", b), + e => vec![1, 2], + f => vec!(3; 4), h => println!("a", b), // h comment i => vec![1, 2], // i comment j => vec!(3; 4), // j comment @@ -272,9 +264,7 @@ fn issue496() { match def { def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { - Some(const_expr) => { - x - } + Some(const_expr) => x, } } } -- cgit 1.4.1-3-g733a5 From 7b0cceafeea2b722a941cc5456534cede9053334 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 14 Nov 2015 21:59:04 +0100 Subject: Force chains to adhere to restrictions --- src/chains.rs | 21 ++++++++++----------- src/items.rs | 14 ++++++++------ tests/source/match.rs | 7 +++++-- tests/target/match.rs | 10 +++++++++- 4 files changed, 32 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index a011ad2ffef..665fb5ac073 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -21,7 +21,7 @@ use Indent; use rewrite::{Rewrite, RewriteContext}; -use utils::first_line_width; +use utils::{wrap_str, first_line_width}; use expr::rewrite_call; use config::BlockIndentStyle; @@ -58,12 +58,8 @@ pub fn rewrite_chain(mut expr: &ast::Expr, } else { match context.config.chain_indent { BlockIndentStyle::Inherit => (context.block_indent, false), - BlockIndentStyle::Tabbed => { - (context.block_indent.block_indent(context.config), false) - } - BlockIndentStyle::Visual => { - (offset + Indent::new(context.config.tab_spaces, 0), false) - } + BlockIndentStyle::Tabbed => (context.block_indent.block_indent(context.config), false), + BlockIndentStyle::Visual => (offset + Indent::new(context.config.tab_spaces, 0), false), } }; @@ -142,10 +138,13 @@ pub fn rewrite_chain(mut expr: &ast::Expr, &connector[..] }; - Some(format!("{}{}{}", - parent_rewrite, - first_connector, - rewrites.join(&connector))) + wrap_str(format!("{}{}{}", + parent_rewrite, + first_connector, + rewrites.join(&connector)), + context.config.max_width, + width, + offset) } // States whether an expression's last line exclusively consists of closing diff --git a/src/items.rs b/src/items.rs index 4f3c82ee0ab..19aec73f116 100644 --- a/src/items.rs +++ b/src/items.rs @@ -875,12 +875,14 @@ impl<'a> FmtVisitor<'a> { offset + header_str.len(), mk_sp(span.lo, body_lo))) } - None => if self.config.item_brace_style == BraceStyle::AlwaysNextLine && - !fields.is_empty() { - format!("\n{}{{", self.block_indent.to_string(self.config)) - } else { - " {".to_owned() - }, + None => { + if self.config.item_brace_style == BraceStyle::AlwaysNextLine && + !fields.is_empty() { + format!("\n{}{{", self.block_indent.to_string(self.config)) + } else { + " {".to_owned() + } + } }; result.push_str(&generics_str); diff --git a/tests/source/match.rs b/tests/source/match.rs index 9277319295e..b4d35cb3815 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -11,7 +11,6 @@ fn foo() { an_expression; foo() } - // Perhaps this should introduce braces? Foo(ref bar) => aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, Pattern1 | Pattern2 | Pattern3 => false, @@ -83,7 +82,11 @@ fn main() { "scopeid"), true, true), - } + }; + + match x{ + y=>{/*Block with comment. Preserve me.*/ } + z=>{stmt();} } } fn matches() { diff --git a/tests/target/match.rs b/tests/target/match.rs index b7f41c1dd6b..2c238ea8a68 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -12,7 +12,6 @@ fn foo() { an_expression; foo() } - // Perhaps this should introduce braces? Foo(ref bar) => { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } @@ -93,6 +92,15 @@ fn main() { true, true) } + }; + + match x { + y => { + // Block with comment. Preserve me. + } + z => { + stmt(); + } } } -- cgit 1.4.1-3-g733a5 From 9fe3c08abcd4c1817525ef9fc49d0d9b0a052908 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 20 Nov 2015 21:50:25 +0100 Subject: Add option to disable (un)wrapping of match arms --- src/config.rs | 1 + src/expr.rs | 25 +++++++++++++++++-------- tests/source/match-nowrap.rs | 12 ++++++++++++ tests/target/match-nowrap.rs | 13 +++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 tests/source/match-nowrap.rs create mode 100644 tests/target/match-nowrap.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 295c1076b5f..c02d618437f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -307,4 +307,5 @@ create_config! { take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; + wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; } diff --git a/src/expr.rs b/src/expr.rs index a0d7e08878f..29d6d32c0dd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -941,10 +941,11 @@ impl Rewrite for ast::Arm { } let body = match **body { - ast::Expr { node: ast::ExprBlock(ref b), .. } if !is_unsafe_block(b) && - is_simple_block(b, - context.codemap) => { - b.expr.as_ref().map(|e| &**e).unwrap() + ast::Expr { node: ast::ExprBlock(ref block), .. } if !is_unsafe_block(block) && + is_simple_block(block, + context.codemap) && + context.config.wrap_match_arms => { + block.expr.as_ref().map(|e| &**e).unwrap() } ref x => x, }; @@ -959,7 +960,8 @@ impl Rewrite for ast::Arm { let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); match rewrite { - Some(ref body_str) if !body_str.contains('\n') || comma.is_empty() => { + Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || + comma.is_empty() => { return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, @@ -970,7 +972,7 @@ impl Rewrite for ast::Arm { } } - // FIXME: we're doing a second rewrite of the expr -- this may not be + // FIXME: we're doing a second rewrite of the expr; This may not be // necessary. let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); let indent = context.block_indent.block_indent(context.config); @@ -980,13 +982,20 @@ impl Rewrite for ast::Arm { indent), body_budget)); let indent_str = offset.block_indent(context.config).to_string(context.config); + let (body_prefix, body_suffix) = if context.config.wrap_match_arms { + (" {", "}") + } else { + ("", "") + }; - Some(format!("{}{} => {{\n{}{}\n{}}}", + Some(format!("{}{} =>{}\n{}{}\n{}{}", attr_str.trim_left(), pats_str, + body_prefix, indent_str, next_line_body, - offset.to_string(context.config))) + offset.to_string(context.config), + body_suffix)) } } diff --git a/tests/source/match-nowrap.rs b/tests/source/match-nowrap.rs new file mode 100644 index 00000000000..83e0fbbd450 --- /dev/null +++ b/tests/source/match-nowrap.rs @@ -0,0 +1,12 @@ +// rustfmt-wrap_match_arms: false +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { foo() } + b => + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/tests/target/match-nowrap.rs b/tests/target/match-nowrap.rs new file mode 100644 index 00000000000..db2a874c838 --- /dev/null +++ b/tests/target/match-nowrap.rs @@ -0,0 +1,13 @@ +// rustfmt-wrap_match_arms: false +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + foo() + } + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} -- cgit 1.4.1-3-g733a5 From ad7dc420cdfe22c8295c36c4e3a66cc9cf1cbe2b Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 20 Nov 2015 23:31:05 +0100 Subject: Avoid adding an extra newline after block comments When block comments were rewritten to line comments they check if a new line needs to be added and adds one if needed. It only checked for '\n' however which would cause a newline to be added even if the comment was ended by "\r\n" --- src/missed_spans.rs | 7 ++++--- tests/source/comment_crlf_newline.rs | 3 +++ tests/target/comment_crlf_newline.rs | 3 +++ 3 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 tests/source/comment_crlf_newline.rs create mode 100644 tests/target/comment_crlf_newline.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b83f07e05d7..99c1510da65 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -143,11 +143,12 @@ impl<'a> FmtVisitor<'a> { line_start = offset + subslice.len(); if let Some('/') = subslice.chars().skip(1).next() { + // Add a newline after line comments self.buffer.push_str("\n"); } else if line_start < snippet.len() { - let x = (&snippet[line_start..]).chars().next().unwrap() != '\n'; - - if x { + // For other comments add a newline if there isn't one at the end already + let c = snippet[line_start..].chars().next().unwrap(); + if c != '\n' && c != '\r' { self.buffer.push_str("\n"); } } diff --git a/tests/source/comment_crlf_newline.rs b/tests/source/comment_crlf_newline.rs new file mode 100644 index 00000000000..189a7053179 --- /dev/null +++ b/tests/source/comment_crlf_newline.rs @@ -0,0 +1,3 @@ +/* Block comments followed by CRLF newlines should not an extra newline at the end */ + +/* Something else */ diff --git a/tests/target/comment_crlf_newline.rs b/tests/target/comment_crlf_newline.rs new file mode 100644 index 00000000000..3b19b01a7eb --- /dev/null +++ b/tests/target/comment_crlf_newline.rs @@ -0,0 +1,3 @@ +// Block comments followed by CRLF newlines should not an extra newline at the end + +// Something else -- cgit 1.4.1-3-g733a5 From 465662a69187f89a48700c746ec63200bbb21942 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 21 Nov 2015 01:04:23 +0100 Subject: Fix long field accesses not being broken onto separate lines Fixes #512 --- src/chains.rs | 18 ++++++++++++++++-- tests/source/long_field_access.rs | 3 +++ tests/target/long_field_access.rs | 4 ++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/source/long_field_access.rs create mode 100644 tests/target/long_field_access.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 665fb5ac073..9e85b22da02 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -194,8 +194,22 @@ fn rewrite_chain_expr(expr: &ast::Expr, width, offset) } - ast::Expr_::ExprField(_, ref field) => Some(format!(".{}", field.node)), - ast::Expr_::ExprTupField(_, ref field) => Some(format!(".{}", field.node)), + ast::Expr_::ExprField(_, ref field) => { + let s = format!(".{}", field.node); + if s.len() <= width { + Some(s) + } else { + None + } + } + ast::Expr_::ExprTupField(_, ref field) => { + let s = format!(".{}", field.node); + if s.len() <= width { + Some(s) + } else { + None + } + } _ => unreachable!(), } } diff --git a/tests/source/long_field_access.rs b/tests/source/long_field_access.rs new file mode 100644 index 00000000000..7aa626221ae --- /dev/null +++ b/tests/source/long_field_access.rs @@ -0,0 +1,3 @@ +fn f() { + block_flow.base.stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; +} diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs new file mode 100644 index 00000000000..349d2c2f639 --- /dev/null +++ b/tests/target/long_field_access.rs @@ -0,0 +1,4 @@ +fn f() { + block_flow.base.stacking_relative_position_of_display_port = + self.base.stacking_relative_position_of_display_port; +} -- cgit 1.4.1-3-g733a5 From 49e2a146b17a631925c7cd7be00c5cc60d0b5b85 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 20 Nov 2015 22:44:15 +0100 Subject: Rewrite module declarations --- src/visitor.rs | 33 ++++++++++++++++++++------------- tests/source/mod-1.rs | 5 ++++- tests/source/mod-2.rs | 4 ++-- tests/target/mod-1.rs | 6 +++++- tests/target/mod-2.rs | 2 +- 5 files changed, 32 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index fa51d70a853..bf6e99e17c3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -101,10 +101,15 @@ impl<'a> FmtVisitor<'a> { // TODO: we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - brace_compensation); - // FIXME: this is a terrible hack to indent the comments between the last - // item in the block and the closing brace to the block's level. - // The closing brace itself, however, should be indented at a shallower - // level. + self.close_block(); + self.last_pos = b.span.hi; + } + + // FIXME: this is a terrible hack to indent the comments between the last + // item in the block and the closing brace to the block's level. + // The closing brace itself, however, should be indented at a shallower + // level. + fn close_block(&mut self) { let total_len = self.buffer.len; let chars_too_many = if self.config.hard_tabs { 1 @@ -113,7 +118,6 @@ impl<'a> FmtVisitor<'a> { }; self.buffer.truncate(total_len - chars_too_many); self.buffer.push_str("}"); - self.last_pos = b.span.hi; self.block_indent = self.block_indent.block_unindent(self.config); } @@ -239,7 +243,7 @@ impl<'a> FmtVisitor<'a> { } ast::Item_::ItemMod(ref module) => { self.format_missing_with_indent(item.span.lo); - self.format_mod(module, item.span, item.ident); + self.format_mod(module, item.vis, item.span, item.ident); } ast::Item_::ItemMac(..) => { self.format_missing_with_indent(item.span.lo); @@ -433,23 +437,26 @@ impl<'a> FmtVisitor<'a> { } } - fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident) { - debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s); - + fn format_mod(&mut self, m: &ast::Mod, vis: ast::Visibility, s: Span, ident: ast::Ident) { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); let is_internal = local_file_name == self.codemap.span_to_filename(m.inner); - // TODO: Should rewrite properly `mod X;` + self.buffer.push_str(utils::format_visibility(vis)); + self.buffer.push_str("mod "); + self.buffer.push_str(&ident.to_string()); if is_internal { + self.buffer.push_str(" {"); + self.last_pos = ::utils::span_after(s, "{", self.codemap); self.block_indent = self.block_indent.block_indent(self.config); self.walk_mod_items(m); - self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(m.inner.hi - BytePos(1)); - self.buffer.push_str("}"); + self.close_block(); self.last_pos = m.inner.hi; + } else { + self.buffer.push_str(";"); + self.last_pos = s.hi; } } diff --git a/tests/source/mod-1.rs b/tests/source/mod-1.rs index 5eb73cb5d4c..427a355b6be 100644 --- a/tests/source/mod-1.rs +++ b/tests/source/mod-1.rs @@ -16,7 +16,7 @@ mod foo { mod boxed { pub use std::boxed::{Box, HEAP}; } -mod x { +pub mod x { pub fn freopen(filename: *const c_char, mode: *const c_char, mode2: *const c_char, @@ -24,3 +24,6 @@ mod x { file: *mut FILE) -> *mut FILE{} } + + mod y { // sup boooooiiii + } diff --git a/tests/source/mod-2.rs b/tests/source/mod-2.rs index c4a148a616e..00b70e972cd 100644 --- a/tests/source/mod-2.rs +++ b/tests/source/mod-2.rs @@ -1,4 +1,4 @@ // Some nested mods -mod nestedmod; -mod no_new_line_beginning; + mod nestedmod ; +pub mod no_new_line_beginning; diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs index 02ce208ed4e..6fe2e65c565 100644 --- a/tests/target/mod-1.rs +++ b/tests/target/mod-1.rs @@ -25,7 +25,7 @@ mod boxed { pub use std::boxed::{Box, HEAP}; } -mod x { +pub mod x { pub fn freopen(filename: *const c_char, mode: *const c_char, mode2: *const c_char, @@ -34,3 +34,7 @@ mod x { -> *mut FILE { } } + +mod y { + // sup boooooiiii +} diff --git a/tests/target/mod-2.rs b/tests/target/mod-2.rs index c4a148a616e..426c266cecf 100644 --- a/tests/target/mod-2.rs +++ b/tests/target/mod-2.rs @@ -1,4 +1,4 @@ // Some nested mods mod nestedmod; -mod no_new_line_beginning; +pub mod no_new_line_beginning; -- cgit 1.4.1-3-g733a5 From 1b0ae00488616a93ffd015d97b65624cf47da818 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 22 Nov 2015 13:45:51 +0100 Subject: Extract fn rewrite methods from RewriteVisitor --- src/items.rs | 1582 ++++++++++++++++++++++++++++---------------------------- src/types.rs | 13 +- src/visitor.rs | 32 +- 3 files changed, 820 insertions(+), 807 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 19aec73f116..48cb212e76d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -113,20 +113,21 @@ impl<'a> FmtVisitor<'a> { match item.node { ast::ForeignItem_::ForeignItemFn(ref fn_decl, ref generics) => { let indent = self.block_indent; - let rewrite = self.rewrite_fn_base(indent, - item.ident, - fn_decl, - None, - generics, - ast::Unsafety::Normal, - ast::Constness::NotConst, - // These are not actually rust functions, - // but we format them as such. - abi::Abi::Rust, - item.vis, - span, - false, - false); + let rewrite = rewrite_fn_base(&self.get_context(), + indent, + item.ident, + fn_decl, + None, + generics, + ast::Unsafety::Normal, + ast::Constness::NotConst, + // These are not actually rust functions, + // but we format them as such. + abi::Abi::Rust, + item.vis, + span, + false, + false); match rewrite { Some((new_fn, _)) => { @@ -180,20 +181,22 @@ impl<'a> FmtVisitor<'a> { span: Span, block: &ast::Block) -> Option { - let mut newline_brace = self.newline_for_brace(&generics.where_clause); - - let (mut result, force_newline_brace) = try_opt!(self.rewrite_fn_base(indent, - ident, - fd, - explicit_self, - generics, - unsafety, - constness, - abi, - vis, - span, - newline_brace, - true)); + let mut newline_brace = newline_for_brace(self.config, &generics.where_clause); + let context = self.get_context(); + + let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, + indent, + ident, + fd, + explicit_self, + generics, + unsafety, + constness, + abi, + vis, + span, + newline_brace, + true)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; @@ -224,20 +227,22 @@ impl<'a> FmtVisitor<'a> { -> Option { // Drop semicolon or it will be interpreted as comment let span = mk_sp(span.lo, span.hi - BytePos(1)); + let context = self.get_context(); // FIXME: silly formatting of the `.0`. - let mut result = try_opt!(self.rewrite_fn_base(indent, - ident, - &sig.decl, - Some(&sig.explicit_self), - &sig.generics, - sig.unsafety, - sig.constness, - sig.abi, - ast::Visibility::Inherited, - span, - false, - false)) + let mut result = try_opt!(rewrite_fn_base(&context, + indent, + ident, + &sig.decl, + Some(&sig.explicit_self), + &sig.generics, + sig.unsafety, + sig.constness, + sig.abi, + ast::Visibility::Inherited, + span, + false, + false)) .0; // Re-attach semicolon @@ -246,210 +251,7 @@ impl<'a> FmtVisitor<'a> { Some(result) } - // Return type is (result, force_new_line_for_brace) - fn rewrite_fn_base(&mut self, - indent: Indent, - ident: ast::Ident, - fd: &ast::FnDecl, - explicit_self: Option<&ast::ExplicitSelf>, - generics: &ast::Generics, - unsafety: ast::Unsafety, - constness: ast::Constness, - abi: abi::Abi, - vis: ast::Visibility, - span: Span, - newline_brace: bool, - has_body: bool) - -> Option<(String, bool)> { - let mut force_new_line_for_brace = false; - // FIXME we'll lose any comments in between parts of the function decl, but - // anyone who comments there probably deserves what they get. - - let where_clause = &generics.where_clause; - - let mut result = String::with_capacity(1024); - // Vis unsafety abi. - result.push_str(format_visibility(vis)); - - if let ast::Unsafety::Unsafe = unsafety { - result.push_str("unsafe "); - } - if let ast::Constness::Const = constness { - result.push_str("const "); - } - if abi != abi::Rust { - result.push_str("extern "); - result.push_str(&abi.to_string()); - result.push(' '); - } - - // fn foo - result.push_str("fn "); - result.push_str(&ident.to_string()); - - // Generics. - let generics_indent = indent + result.len(); - let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); - let generics_str = try_opt!(self.rewrite_generics(generics, - indent, - generics_indent, - generics_span)); - result.push_str(&generics_str); - - let context = self.get_context(); - // Note that if the width and indent really matter, we'll re-layout the - // return type later anyway. - let ret_str = fd.output - .rewrite(&context, self.config.max_width - indent.width(), indent) - .unwrap(); - - let multi_line_ret_str = ret_str.contains('\n'); - let ret_str_len = if multi_line_ret_str { - 0 - } else { - ret_str.len() - }; - - // Args. - let (mut one_line_budget, multi_line_budget, mut arg_indent) = - self.compute_budgets_for_args(&result, indent, ret_str_len, newline_brace); - - debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", - one_line_budget, - multi_line_budget, - arg_indent); - - // Check if vertical layout was forced by compute_budget_for_args. - if one_line_budget <= 0 { - if self.config.fn_args_paren_newline { - result.push('\n'); - result.push_str(&arg_indent.to_string(self.config)); - arg_indent = arg_indent + 1; // extra space for `(` - result.push('('); - } else { - result.push_str("(\n"); - result.push_str(&arg_indent.to_string(self.config)); - } - } else if self.config.fn_args_layout == StructLitStyle::Block { - arg_indent = indent.block_indent(self.config); - result.push_str("(\n"); - result.push_str(&arg_indent.to_string(self.config)); - } else { - result.push('('); - } - - if multi_line_ret_str { - one_line_budget = 0; - } - - // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics.ty_params - .last() - .map(|tp| end_typaram(tp)) - .unwrap_or(span.lo); - let args_span = mk_sp(span_after(mk_sp(args_start, span.hi), "(", self.codemap), - span_for_return(&fd.output).lo); - let arg_str = try_opt!(self.rewrite_args(&fd.inputs, - explicit_self, - one_line_budget, - multi_line_budget, - indent, - arg_indent, - args_span, - fd.variadic)); - result.push_str(&arg_str); - if self.config.fn_args_layout == StructLitStyle::Block { - result.push('\n'); - } - result.push(')'); - - // Return type. - if !ret_str.is_empty() { - // If we've already gone multi-line, or the return type would push - // over the max width, then put the return type on a new line. - // Unless we are formatting args like a block, in which case there - // should always be room for the return type. - let ret_indent = if (result.contains("\n") || multi_line_ret_str || - result.len() + indent.width() + ret_str_len > - self.config.max_width) && - self.config.fn_args_layout != StructLitStyle::Block { - let indent = match self.config.fn_return_indent { - ReturnIndent::WithWhereClause => indent + 4, - // Aligning with non-existent args looks silly. - _ if arg_str.len() == 0 => { - force_new_line_for_brace = true; - indent + 4 - } - // FIXME: we might want to check that using the arg indent - // doesn't blow our budget, and if it does, then fallback to - // the where clause indent. - _ => arg_indent, - }; - - result.push('\n'); - result.push_str(&indent.to_string(self.config)); - indent - } else { - result.push(' '); - Indent::new(indent.width(), result.len()) - }; - - if multi_line_ret_str { - // Now that we know the proper indent and width, we need to - // re-layout the return type. - - let budget = try_opt!(self.config.max_width.checked_sub(ret_indent.width())); - let ret_str = fd.output - .rewrite(&context, budget, ret_indent) - .unwrap(); - result.push_str(&ret_str); - } else { - result.push_str(&ret_str); - } - - // Comment between return type and the end of the decl. - let snippet_lo = fd.output.span().hi; - if where_clause.predicates.is_empty() { - let snippet_hi = span.hi; - let snippet = self.snippet(mk_sp(snippet_lo, snippet_hi)); - let snippet = snippet.trim(); - if !snippet.is_empty() { - result.push(' '); - result.push_str(snippet); - } - } else { - // FIXME it would be nice to catch comments between the return type - // and the where clause, but we don't have a span for the where - // clause. - } - } - - let where_density = if (self.config.where_density == Density::Compressed && - (!result.contains('\n') || - self.config.fn_args_layout == StructLitStyle::Block)) || - (self.config.fn_args_layout == StructLitStyle::Block && - ret_str.is_empty()) || - (self.config.where_density == Density::CompressedIfEmpty && - !has_body) { - Density::Compressed - } else { - Density::Tall - }; - - // Where clause. - let where_clause_str = try_opt!(self.rewrite_where_clause(where_clause, - self.config, - indent, - where_density, - "{", - Some(span.hi))); - result.push_str(&where_clause_str); - - Some((result, force_new_line_for_brace)) - } - fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { - if fn_str.contains('\n') { return None; } @@ -495,206 +297,26 @@ impl<'a> FmtVisitor<'a> { None } - fn rewrite_args(&self, - args: &[ast::Arg], - explicit_self: Option<&ast::ExplicitSelf>, - one_line_budget: usize, - multi_line_budget: usize, - indent: Indent, - arg_indent: Indent, - span: Span, - variadic: bool) - -> Option { - let context = self.get_context(); - let mut arg_item_strs = try_opt!(args.iter() - .map(|arg| { - arg.rewrite(&context, - multi_line_budget, - arg_indent) - }) - .collect::>>()); - - // Account for sugary self. - // FIXME: the comment for the self argument is dropped. This is blocked - // on rust issue #27522. - let min_args = explicit_self.and_then(|explicit_self| { - rewrite_explicit_self(explicit_self, args) - }) - .map(|self_str| { - arg_item_strs[0] = self_str; - 2 - }) - .unwrap_or(1); - - // Comments between args. - let mut arg_items = Vec::new(); - if min_args == 2 { - arg_items.push(ListItem::from_str("")); - } - - // FIXME(#21): if there are no args, there might still be a comment, but - // without spans for the comment or parens, there is no chance of - // getting it right. You also don't get to put a comment on self, unless - // it is explicit. - if args.len() >= min_args || variadic { - let comment_span_start = if min_args == 2 { - span_after(span, ",", self.codemap) - } else { - span.lo - }; - - enum ArgumentKind<'a> { - Regular(&'a ast::Arg), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); - let variadic_start = span_after(variadic_span, "...", self.codemap) - BytePos(3); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - - let more_items = itemize_list(self.codemap, - args[min_args - 1..] - .iter() - .map(ArgumentKind::Regular) - .chain(variadic_arg), - ")", - |arg| { - match *arg { - ArgumentKind::Regular(arg) => { - span_lo_for_arg(arg) - } - ArgumentKind::Variadic(start) => start, - } - }, - |arg| { - match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi, - ArgumentKind::Variadic(start) => { - start + BytePos(3) - } - } - }, - |arg| { - match *arg { - ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => { - Some("...".to_owned()) - } - } - }, - comment_span_start, - span.hi); - - arg_items.extend(more_items); - } - - for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { - item.item = Some(arg); - } - - let indent = match self.config.fn_arg_indent { - BlockIndentStyle::Inherit => indent, - BlockIndentStyle::Tabbed => indent.block_indent(self.config), - BlockIndentStyle::Visual => arg_indent, - }; - - let tactic = definitive_tactic(&arg_items, - self.config.fn_args_density.to_list_tactic(), - one_line_budget); - let budget = match tactic { - DefinitiveListTactic::Horizontal => one_line_budget, - _ => multi_line_budget, - }; - - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: indent, - width: budget, - ends_with_newline: false, - config: self.config, - }; - - write_list(&arg_items, &fmt) - } - - fn compute_budgets_for_args(&self, - result: &str, - indent: Indent, - ret_str_len: usize, - newline_brace: bool) - -> (usize, usize, Indent) { - // Try keeping everything on the same line - if !result.contains("\n") { - // 3 = `() `, space is before ret_string - let mut used_space = indent.width() + result.len() + ret_str_len + 3; - if !newline_brace { - used_space += 2; - } - let one_line_budget = if used_space > self.config.max_width { - 0 - } else { - self.config.max_width - used_space - }; - - // 2 = `()` - let used_space = indent.width() + result.len() + 2; - let max_space = self.config.max_width; - debug!("compute_budgets_for_args: used_space: {}, max_space: {}", - used_space, - max_space); - if used_space < max_space { - return (one_line_budget, - max_space - used_space, - indent + result.len() + 1); - } - } - - // Didn't work. we must force vertical layout and put args on a newline. - let new_indent = indent.block_indent(self.config); - let used_space = new_indent.width() + 2; // account for `(` and `)` - let max_space = self.config.max_width; - if used_space <= max_space { - (0, max_space - used_space, new_indent) - } else { - // Whoops! bankrupt. - // FIXME: take evasive action, perhaps kill the indent or something. - panic!("in compute_budgets_for_args"); - } - } - - fn newline_for_brace(&self, where_clause: &ast::WhereClause) -> bool { - match self.config.fn_brace_style { - BraceStyle::AlwaysNextLine => true, - BraceStyle::SameLineWhere if !where_clause.predicates.is_empty() => true, - _ => false, - } - } - pub fn visit_enum(&mut self, ident: ast::Ident, vis: ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span) { - let header_str = self.format_header("enum ", ident, vis); + let header_str = format_header("enum ", ident, vis); self.buffer.push_str(&header_str); let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); - let generics_str = self.format_generics(generics, - "{", - "{", - self.config.item_brace_style, - enum_def.variants.is_empty(), - self.block_indent, - self.block_indent.block_indent(self.config), - mk_sp(span.lo, body_start)) + let generics_str = format_generics(&self.get_context(), + generics, + "{", + "{", + self.config.item_brace_style, + enum_def.variants.is_empty(), + self.block_indent, + self.block_indent.block_indent(self.config), + mk_sp(span.lo, body_start)) .unwrap(); self.buffer.push_str(&generics_str); @@ -780,17 +402,19 @@ impl<'a> FmtVisitor<'a> { result.push_str(&indent.to_string(self.config)); } + let context = self.get_context(); let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma - self.format_struct("", - field.node.name, - ast::Visibility::Inherited, - &field.node.data, - None, - field.span, - indent) + format_struct(&context, + "", + field.node.name, + ast::Visibility::Inherited, + &field.node.data, + None, + field.span, + indent) } ast::VariantData::Unit(..) => { let tag = if let Some(ref expr) = field.node.disr_expr { @@ -813,371 +437,212 @@ impl<'a> FmtVisitor<'a> { None } } +} - pub fn format_struct(&self, - item_name: &str, - ident: ast::Ident, - vis: ast::Visibility, - struct_def: &ast::VariantData, - generics: Option<&ast::Generics>, - span: Span, - offset: Indent) - -> Option { - match *struct_def { - ast::VariantData::Unit(..) => self.format_unit_struct(item_name, ident, vis), - ast::VariantData::Tuple(ref fields, _) => { - self.format_tuple_struct(item_name, ident, vis, fields, generics, span, offset) - } - ast::VariantData::Struct(ref fields, _) => { - self.format_struct_struct(item_name, ident, vis, fields, generics, span, offset) - } +pub fn format_struct(context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + struct_def: &ast::VariantData, + generics: Option<&ast::Generics>, + span: Span, + offset: Indent) + -> Option { + match *struct_def { + ast::VariantData::Unit(..) => format_unit_struct(item_name, ident, vis), + ast::VariantData::Tuple(ref fields, _) => { + format_tuple_struct(context, + item_name, + ident, + vis, + fields, + generics, + span, + offset) } - } - - fn format_unit_struct(&self, - item_name: &str, - ident: ast::Ident, - vis: ast::Visibility) - -> Option { - let mut result = String::with_capacity(1024); - - let header_str = self.format_header(item_name, ident, vis); - result.push_str(&header_str); - result.push(';'); - - Some(result) - } - - fn format_struct_struct(&self, - item_name: &str, - ident: ast::Ident, - vis: ast::Visibility, - fields: &[ast::StructField], - generics: Option<&ast::Generics>, - span: Span, - offset: Indent) - -> Option { - let mut result = String::with_capacity(1024); - - let header_str = self.format_header(item_name, ident, vis); - result.push_str(&header_str); - - let body_lo = span_after(span, "{", self.codemap); - - let generics_str = match generics { - Some(g) => { - try_opt!(self.format_generics(g, - "{", - "{", - self.config.item_brace_style, - fields.is_empty(), - offset, - offset + header_str.len(), - mk_sp(span.lo, body_lo))) - } - None => { - if self.config.item_brace_style == BraceStyle::AlwaysNextLine && - !fields.is_empty() { - format!("\n{}{{", self.block_indent.to_string(self.config)) - } else { - " {".to_owned() - } - } - }; - result.push_str(&generics_str); - - // FIXME: properly format empty structs and their comments. - if fields.is_empty() { - result.push_str(&self.snippet(mk_sp(body_lo, span.hi))); - return Some(result); + ast::VariantData::Struct(ref fields, _) => { + format_struct_struct(context, + item_name, + ident, + vis, + fields, + generics, + span, + offset) } - - let item_indent = offset.block_indent(self.config); - // 2 = "," - let item_budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 1)); - - let context = self.get_context(); - let items = itemize_list(self.codemap, - fields.iter(), - "}", - |field| { - // Include attributes and doc comments, if present - if !field.node.attrs.is_empty() { - field.node.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.node.ty.span.hi, - |field| field.rewrite(&context, item_budget, item_indent), - span_after(span, "{", self.codemap), - span.hi); - // 1 = , - let budget = self.config.max_width - offset.width() + self.config.tab_spaces - 1; - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: ",", - trailing_separator: self.config.struct_trailing_comma, - indent: item_indent, - width: budget, - ends_with_newline: true, - config: self.config, - }; - Some(format!("{}\n{}{}\n{}}}", - result, - offset.block_indent(self.config).to_string(self.config), - try_opt!(write_list(items, &fmt)), - offset.to_string(self.config))) } +} - fn format_tuple_struct(&self, - item_name: &str, - ident: ast::Ident, - vis: ast::Visibility, - fields: &[ast::StructField], - generics: Option<&ast::Generics>, - span: Span, - offset: Indent) - -> Option { - assert!(!fields.is_empty(), "Tuple struct with no fields?"); - let mut result = String::with_capacity(1024); - - let header_str = self.format_header(item_name, ident, vis); - result.push_str(&header_str); - - let body_lo = fields[0].span.lo; - - let (generics_str, where_clause_str) = match generics { - Some(ref generics) => { - let generics_str = try_opt!(self.rewrite_generics(generics, - offset, - offset + header_str.len(), - mk_sp(span.lo, body_lo))); - - let where_clause_str = try_opt!(self.rewrite_where_clause(&generics.where_clause, - self.config, - self.block_indent, - Density::Compressed, - ";", - None)); +fn format_unit_struct(item_name: &str, + ident: ast::Ident, + vis: ast::Visibility) + -> Option { + let mut result = String::with_capacity(1024); - (generics_str, where_clause_str) - } - None => ("".to_owned(), "".to_owned()), - }; - result.push_str(&generics_str); - result.push('('); + let header_str = format_header(item_name, ident, vis); + result.push_str(&header_str); + result.push(';'); - let item_indent = self.block_indent + result.len(); - // 2 = ");" - let item_budget = try_opt!(self.config.max_width.checked_sub(item_indent.width() + 2)); + Some(result) +} - let context = self.get_context(); - let items = itemize_list(self.codemap, - fields.iter(), - ")", - |field| { - // Include attributes and doc comments, if present - if !field.node.attrs.is_empty() { - field.node.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.node.ty.span.hi, - |field| field.rewrite(&context, item_budget, item_indent), - span_after(span, "(", self.codemap), - span.hi); - let body = try_opt!(format_item_list(items, item_budget, item_indent, self.config)); - result.push_str(&body); - result.push(')'); - - if where_clause_str.len() > 0 && !where_clause_str.contains('\n') && - (result.contains('\n') || - self.block_indent.width() + result.len() + where_clause_str.len() + 1 > - self.config.max_width) { - // We need to put the where clause on a new line, but we didn'to_string - // know that earlier, so the where clause will not be indented properly. - result.push('\n'); - result.push_str(&(self.block_indent + (self.config.tab_spaces - 1)) - .to_string(self.config)); +fn format_struct_struct(context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + fields: &[ast::StructField], + generics: Option<&ast::Generics>, + span: Span, + offset: Indent) + -> Option { + let mut result = String::with_capacity(1024); + + let header_str = format_header(item_name, ident, vis); + result.push_str(&header_str); + + let body_lo = span_after(span, "{", context.codemap); + + let generics_str = match generics { + Some(g) => { + try_opt!(format_generics(context, + g, + "{", + "{", + context.config.item_brace_style, + fields.is_empty(), + offset, + offset + header_str.len(), + mk_sp(span.lo, body_lo))) } - result.push_str(&where_clause_str); - - Some(result) - } - - fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, ident) - } - - fn format_generics(&self, - generics: &ast::Generics, - opener: &str, - terminator: &str, - brace_style: BraceStyle, - force_same_line_brace: bool, - offset: Indent, - generics_offset: Indent, - span: Span) - -> Option { - let mut result = try_opt!(self.rewrite_generics(generics, offset, generics_offset, span)); - - if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let where_clause_str = try_opt!(self.rewrite_where_clause(&generics.where_clause, - self.config, - self.block_indent, - Density::Tall, - terminator, - Some(span.hi))); - result.push_str(&where_clause_str); - if !force_same_line_brace && - (brace_style == BraceStyle::SameLineWhere || - brace_style == BraceStyle::AlwaysNextLine) { - result.push('\n'); - result.push_str(&self.block_indent.to_string(self.config)); - } else { - result.push(' '); - } - result.push_str(opener); - } else { - if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine { - result.push('\n'); - result.push_str(&self.block_indent.to_string(self.config)); + None => { + if context.config.item_brace_style == BraceStyle::AlwaysNextLine && !fields.is_empty() { + format!("\n{}{{", context.block_indent.to_string(context.config)) } else { - result.push(' '); + " {".to_owned() } - result.push_str(opener); } + }; + result.push_str(&generics_str); - Some(result) - } - - fn rewrite_generics(&self, - generics: &ast::Generics, - offset: Indent, - generics_offset: Indent, - span: Span) - -> Option { - // FIXME: convert bounds to where clauses where they get too big or if - // there is a where clause at all. - let lifetimes: &[_] = &generics.lifetimes; - let tys: &[_] = &generics.ty_params; - if lifetimes.is_empty() && tys.is_empty() { - return Some(String::new()); - } - - let offset = match self.config.generics_indent { - BlockIndentStyle::Inherit => offset, - BlockIndentStyle::Tabbed => offset.block_indent(self.config), - // 1 = < - BlockIndentStyle::Visual => generics_offset + 1, - }; - - let h_budget = self.config.max_width - generics_offset.width() - 2; - // FIXME: might need to insert a newline if the generics are really long. - - // Strings for the generics. - let context = self.get_context(); - let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset)); - let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(&context, h_budget, offset)); - - // Extract comments between generics. - let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - mk_sp(l.lifetime.span.lo, hi) - }); - let ty_spans = tys.iter().map(span_for_ty_param); - - let items = itemize_list(self.codemap, - lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), - ">", - |&(sp, _)| sp.lo, - |&(sp, _)| sp.hi, - // FIXME: don't clone - |&(_, ref str)| str.clone(), - span_after(span, "<", self.codemap), - span.hi); - let list_str = try_opt!(format_item_list(items, h_budget, offset, self.config)); - - Some(format!("<{}>", list_str)) + // FIXME: properly format empty structs and their comments. + if fields.is_empty() { + result.push_str(&context.snippet(mk_sp(body_lo, span.hi))); + return Some(result); } - fn rewrite_where_clause(&self, - where_clause: &ast::WhereClause, - config: &Config, - indent: Indent, - density: Density, - terminator: &str, - span_end: Option) - -> Option { - if where_clause.predicates.is_empty() { - return Some(String::new()); - } - - let extra_indent = match self.config.where_indent { - BlockIndentStyle::Inherit => Indent::empty(), - BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => { - Indent::new(config.tab_spaces, 0) - } - }; - - let context = self.get_context(); - - let offset = match self.config.where_pred_indent { - BlockIndentStyle::Inherit => indent + extra_indent, - BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config), - // 6 = "where ".len() - BlockIndentStyle::Visual => indent + extra_indent + 6, - }; - // FIXME: if where_pred_indent != Visual, then the budgets below might - // be out by a char or two. - - let budget = self.config.max_width - offset.width(); - let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; - // If we don't have the start of the next span, then use the end of the - // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; - let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list(self.codemap, - where_clause.predicates.iter(), - terminator, - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(&context, budget, offset), - span_start, - span_end); - let item_vec = items.collect::>(); - // FIXME: we don't need to collect here if the where_layout isn't - // HorizontalVertical. - let tactic = definitive_tactic(&item_vec, self.config.where_layout, budget); + let item_indent = offset.block_indent(context.config); + // 2 = "," + let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 1)); + + let items = itemize_list(context.codemap, + fields.iter(), + "}", + |field| { + // Include attributes and doc comments, if present + if !field.node.attrs.is_empty() { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.node.ty.span.hi, + |field| field.rewrite(context, item_budget, item_indent), + span_after(span, "{", context.codemap), + span.hi); + // 1 = , + let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1; + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: context.config.struct_trailing_comma, + indent: item_indent, + width: budget, + ends_with_newline: true, + config: context.config, + }; + Some(format!("{}\n{}{}\n{}}}", + result, + offset.block_indent(context.config).to_string(context.config), + try_opt!(write_list(items, &fmt)), + offset.to_string(context.config))) +} - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - indent: offset, - width: budget, - ends_with_newline: true, - config: self.config, - }; - let preds_str = try_opt!(write_list(&item_vec, &fmt)); - - // 9 = " where ".len() + " {".len() - if density == Density::Tall || preds_str.contains('\n') || - indent.width() + 9 + preds_str.len() > self.config.max_width { - Some(format!("\n{}where {}", - (indent + extra_indent).to_string(self.config), - preds_str)) - } else { - Some(format!(" where {}", preds_str)) +fn format_tuple_struct(context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: ast::Visibility, + fields: &[ast::StructField], + generics: Option<&ast::Generics>, + span: Span, + offset: Indent) + -> Option { + assert!(!fields.is_empty(), "Tuple struct with no fields?"); + let mut result = String::with_capacity(1024); + + let header_str = format_header(item_name, ident, vis); + result.push_str(&header_str); + + let body_lo = fields[0].span.lo; + + let (generics_str, where_clause_str) = match generics { + Some(ref generics) => { + let generics_str = try_opt!(rewrite_generics(context, + generics, + offset, + offset + header_str.len(), + mk_sp(span.lo, body_lo))); + + let where_clause_str = try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.block_indent, + Density::Compressed, + ";", + None)); + + (generics_str, where_clause_str) } + None => ("".to_owned(), "".to_owned()), + }; + result.push_str(&generics_str); + result.push('('); + + let item_indent = context.block_indent + result.len(); + // 2 = ");" + let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2)); + + let items = itemize_list(context.codemap, + fields.iter(), + ")", + |field| { + // Include attributes and doc comments, if present + if !field.node.attrs.is_empty() { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.node.ty.span.hi, + |field| field.rewrite(context, item_budget, item_indent), + span_after(span, "(", context.codemap), + span.hi); + let body = try_opt!(format_item_list(items, item_budget, item_indent, context.config)); + result.push_str(&body); + result.push(')'); + + if where_clause_str.len() > 0 && !where_clause_str.contains('\n') && + (result.contains('\n') || + context.block_indent.width() + result.len() + where_clause_str.len() + 1 > + context.config.max_width) { + // We need to put the where clause on a new line, but we didn'to_string + // know that earlier, so the where clause will not be indented properly. + result.push('\n'); + result.push_str(&(context.block_indent + (context.config.tab_spaces - 1)) + .to_string(context.config)); } + result.push_str(&where_clause_str); + + Some(result) } impl Rewrite for ast::StructField { @@ -1369,3 +834,546 @@ fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { ast::WherePredicate::EqPredicate(ref p) => p.span, } } + +// Return type is (result, force_new_line_for_brace) +fn rewrite_fn_base(context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: ast::Unsafety, + constness: ast::Constness, + abi: abi::Abi, + vis: ast::Visibility, + span: Span, + newline_brace: bool, + has_body: bool) + -> Option<(String, bool)> { + let mut force_new_line_for_brace = false; + // FIXME we'll lose any comments in between parts of the function decl, but + // anyone who comments there probably deserves what they get. + + let where_clause = &generics.where_clause; + + let mut result = String::with_capacity(1024); + // Vis unsafety abi. + result.push_str(format_visibility(vis)); + + if let ast::Unsafety::Unsafe = unsafety { + result.push_str("unsafe "); + } + if let ast::Constness::Const = constness { + result.push_str("const "); + } + if abi != abi::Rust { + result.push_str("extern "); + result.push_str(&abi.to_string()); + result.push(' '); + } + + // fn foo + result.push_str("fn "); + result.push_str(&ident.to_string()); + + // Generics. + let generics_indent = indent + result.len(); + let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); + let generics_str = try_opt!(rewrite_generics(context, + generics, + indent, + generics_indent, + generics_span)); + result.push_str(&generics_str); + + // Note that if the width and indent really matter, we'll re-layout the + // return type later anyway. + let ret_str = fd.output + .rewrite(&context, context.config.max_width - indent.width(), indent) + .unwrap(); + + let multi_line_ret_str = ret_str.contains('\n'); + let ret_str_len = if multi_line_ret_str { + 0 + } else { + ret_str.len() + }; + + // Args. + let (mut one_line_budget, multi_line_budget, mut arg_indent) = + compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace); + + debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", + one_line_budget, + multi_line_budget, + arg_indent); + + // Check if vertical layout was forced by compute_budget_for_args. + if one_line_budget <= 0 { + if context.config.fn_args_paren_newline { + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + arg_indent = arg_indent + 1; // extra space for `(` + result.push('('); + } else { + result.push_str("(\n"); + result.push_str(&arg_indent.to_string(context.config)); + } + } else if context.config.fn_args_layout == StructLitStyle::Block { + arg_indent = indent.block_indent(context.config); + result.push_str("(\n"); + result.push_str(&arg_indent.to_string(context.config)); + } else { + result.push('('); + } + + if multi_line_ret_str { + one_line_budget = 0; + } + + // A conservative estimation, to goal is to be over all parens in generics + let args_start = generics.ty_params + .last() + .map(|tp| end_typaram(tp)) + .unwrap_or(span.lo); + let args_span = mk_sp(span_after(mk_sp(args_start, span.hi), "(", context.codemap), + span_for_return(&fd.output).lo); + let arg_str = try_opt!(rewrite_args(context, + &fd.inputs, + explicit_self, + one_line_budget, + multi_line_budget, + indent, + arg_indent, + args_span, + fd.variadic)); + result.push_str(&arg_str); + if context.config.fn_args_layout == StructLitStyle::Block { + result.push('\n'); + } + result.push(')'); + + // Return type. + if !ret_str.is_empty() { + // If we've already gone multi-line, or the return type would push + // over the max width, then put the return type on a new line. + // Unless we are formatting args like a block, in which case there + // should always be room for the return type. + let ret_indent = if (result.contains("\n") || multi_line_ret_str || + result.len() + indent.width() + ret_str_len > + context.config.max_width) && + context.config.fn_args_layout != StructLitStyle::Block { + let indent = match context.config.fn_return_indent { + ReturnIndent::WithWhereClause => indent + 4, + // Aligning with non-existent args looks silly. + _ if arg_str.len() == 0 => { + force_new_line_for_brace = true; + indent + 4 + } + // FIXME: we might want to check that using the arg indent + // doesn't blow our budget, and if it does, then fallback to + // the where clause indent. + _ => arg_indent, + }; + + result.push('\n'); + result.push_str(&indent.to_string(context.config)); + indent + } else { + result.push(' '); + Indent::new(indent.width(), result.len()) + }; + + if multi_line_ret_str { + // Now that we know the proper indent and width, we need to + // re-layout the return type. + + let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); + let ret_str = fd.output + .rewrite(context, budget, ret_indent) + .unwrap(); + result.push_str(&ret_str); + } else { + result.push_str(&ret_str); + } + + // Comment between return type and the end of the decl. + let snippet_lo = fd.output.span().hi; + if where_clause.predicates.is_empty() { + let snippet_hi = span.hi; + let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); + let snippet = snippet.trim(); + if !snippet.is_empty() { + result.push(' '); + result.push_str(snippet); + } + } else { + // FIXME it would be nice to catch comments between the return type + // and the where clause, but we don't have a span for the where + // clause. + } + } + + let where_density = if (context.config.where_density == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout == StructLitStyle::Block)) || + (context.config.fn_args_layout == StructLitStyle::Block && + ret_str.is_empty()) || + (context.config.where_density == Density::CompressedIfEmpty && + !has_body) { + Density::Compressed + } else { + Density::Tall + }; + + // Where clause. + let where_clause_str = try_opt!(rewrite_where_clause(context, + where_clause, + context.config, + indent, + where_density, + "{", + Some(span.hi))); + result.push_str(&where_clause_str); + + Some((result, force_new_line_for_brace)) +} + +fn rewrite_args(context: &RewriteContext, + args: &[ast::Arg], + explicit_self: Option<&ast::ExplicitSelf>, + one_line_budget: usize, + multi_line_budget: usize, + indent: Indent, + arg_indent: Indent, + span: Span, + variadic: bool) + -> Option { + let mut arg_item_strs = try_opt!(args.iter() + .map(|arg| { + arg.rewrite(&context, multi_line_budget, arg_indent) + }) + .collect::>>()); + + // Account for sugary self. + // FIXME: the comment for the self argument is dropped. This is blocked + // on rust issue #27522. + let min_args = explicit_self.and_then(|explicit_self| { + rewrite_explicit_self(explicit_self, args) + }) + .map(|self_str| { + arg_item_strs[0] = self_str; + 2 + }) + .unwrap_or(1); + + // Comments between args. + let mut arg_items = Vec::new(); + if min_args == 2 { + arg_items.push(ListItem::from_str("")); + } + + // FIXME(#21): if there are no args, there might still be a comment, but + // without spans for the comment or parens, there is no chance of + // getting it right. You also don't get to put a comment on self, unless + // it is explicit. + if args.len() >= min_args || variadic { + let comment_span_start = if min_args == 2 { + span_after(span, ",", context.codemap) + } else { + span.lo + }; + + enum ArgumentKind<'a> { + Regular(&'a ast::Arg), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); + let variadic_start = span_after(variadic_span, "...", context.codemap) - BytePos(3); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + + let more_items = itemize_list(context.codemap, + args[min_args - 1..] + .iter() + .map(ArgumentKind::Regular) + .chain(variadic_arg), + ")", + |arg| { + match *arg { + ArgumentKind::Regular(arg) => span_lo_for_arg(arg), + ArgumentKind::Variadic(start) => start, + } + }, + |arg| { + match *arg { + ArgumentKind::Regular(arg) => arg.ty.span.hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + } + }, + |arg| { + match *arg { + ArgumentKind::Regular(..) => None, + ArgumentKind::Variadic(..) => Some("...".to_owned()), + } + }, + comment_span_start, + span.hi); + + arg_items.extend(more_items); + } + + for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { + item.item = Some(arg); + } + + let indent = match context.config.fn_arg_indent { + BlockIndentStyle::Inherit => indent, + BlockIndentStyle::Tabbed => indent.block_indent(context.config), + BlockIndentStyle::Visual => arg_indent, + }; + + let tactic = definitive_tactic(&arg_items, + context.config.fn_args_density.to_list_tactic(), + one_line_budget); + let budget = match tactic { + DefinitiveListTactic::Horizontal => one_line_budget, + _ => multi_line_budget, + }; + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: indent, + width: budget, + ends_with_newline: false, + config: context.config, + }; + + write_list(&arg_items, &fmt) +} + +fn compute_budgets_for_args(context: &RewriteContext, + result: &str, + indent: Indent, + ret_str_len: usize, + newline_brace: bool) + -> (usize, usize, Indent) { + // Try keeping everything on the same line + if !result.contains("\n") { + // 3 = `() `, space is before ret_string + let mut used_space = indent.width() + result.len() + ret_str_len + 3; + if !newline_brace { + used_space += 2; + } + let one_line_budget = if used_space > context.config.max_width { + 0 + } else { + context.config.max_width - used_space + }; + + // 2 = `()` + let used_space = indent.width() + result.len() + 2; + let max_space = context.config.max_width; + debug!("compute_budgets_for_args: used_space: {}, max_space: {}", + used_space, + max_space); + if used_space < max_space { + return (one_line_budget, + max_space - used_space, + indent + result.len() + 1); + } + } + + // Didn't work. we must force vertical layout and put args on a newline. + let new_indent = indent.block_indent(context.config); + let used_space = new_indent.width() + 2; // account for `(` and `)` + let max_space = context.config.max_width; + if used_space <= max_space { + (0, max_space - used_space, new_indent) + } else { + // Whoops! bankrupt. + // FIXME: take evasive action, perhaps kill the indent or something. + panic!("in compute_budgets_for_args"); + } +} + +fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { + match config.fn_brace_style { + BraceStyle::AlwaysNextLine => true, + BraceStyle::SameLineWhere if !where_clause.predicates.is_empty() => true, + _ => false, + } +} + +fn rewrite_generics(context: &RewriteContext, + generics: &ast::Generics, + offset: Indent, + generics_offset: Indent, + span: Span) + -> Option { + // FIXME: convert bounds to where clauses where they get too big or if + // there is a where clause at all. + let lifetimes: &[_] = &generics.lifetimes; + let tys: &[_] = &generics.ty_params; + if lifetimes.is_empty() && tys.is_empty() { + return Some(String::new()); + } + + let offset = match context.config.generics_indent { + BlockIndentStyle::Inherit => offset, + BlockIndentStyle::Tabbed => offset.block_indent(context.config), + // 1 = < + BlockIndentStyle::Visual => generics_offset + 1, + }; + + let h_budget = context.config.max_width - generics_offset.width() - 2; + // FIXME: might need to insert a newline if the generics are really long. + + // Strings for the generics. + let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset)); + let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(&context, h_budget, offset)); + + // Extract comments between generics. + let lt_spans = lifetimes.iter().map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + mk_sp(l.lifetime.span.lo, hi) + }); + let ty_spans = tys.iter().map(span_for_ty_param); + + let items = itemize_list(context.codemap, + lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), + ">", + |&(sp, _)| sp.lo, + |&(sp, _)| sp.hi, + // FIXME: don't clone + |&(_, ref str)| str.clone(), + span_after(span, "<", context.codemap), + span.hi); + let list_str = try_opt!(format_item_list(items, h_budget, offset, context.config)); + + Some(format!("<{}>", list_str)) +} + +fn rewrite_where_clause(context: &RewriteContext, + where_clause: &ast::WhereClause, + config: &Config, + indent: Indent, + density: Density, + terminator: &str, + span_end: Option) + -> Option { + if where_clause.predicates.is_empty() { + return Some(String::new()); + } + + let extra_indent = match context.config.where_indent { + BlockIndentStyle::Inherit => Indent::empty(), + BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => Indent::new(config.tab_spaces, 0), + }; + + let offset = match context.config.where_pred_indent { + BlockIndentStyle::Inherit => indent + extra_indent, + BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config), + // 6 = "where ".len() + BlockIndentStyle::Visual => indent + extra_indent + 6, + }; + // FIXME: if where_pred_indent != Visual, then the budgets below might + // be out by a char or two. + + let budget = context.config.max_width - offset.width(); + let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; + let span_end = span_end.unwrap_or(end_of_preds); + let items = itemize_list(context.codemap, + where_clause.predicates.iter(), + terminator, + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + |pred| pred.rewrite(&context, budget, offset), + span_start, + span_end); + let item_vec = items.collect::>(); + // FIXME: we don't need to collect here if the where_layout isn't + // HorizontalVertical. + let tactic = definitive_tactic(&item_vec, context.config.where_layout, budget); + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + indent: offset, + width: budget, + ends_with_newline: true, + config: context.config, + }; + let preds_str = try_opt!(write_list(&item_vec, &fmt)); + + // 9 = " where ".len() + " {".len() + if density == Density::Tall || preds_str.contains('\n') || + indent.width() + 9 + preds_str.len() > context.config.max_width { + Some(format!("\n{}where {}", + (indent + extra_indent).to_string(context.config), + preds_str)) + } else { + Some(format!(" where {}", preds_str)) + } +} + +fn format_header(item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { + format!("{}{}{}", format_visibility(vis), item_name, ident) +} + +fn format_generics(context: &RewriteContext, + generics: &ast::Generics, + opener: &str, + terminator: &str, + brace_style: BraceStyle, + force_same_line_brace: bool, + offset: Indent, + generics_offset: Indent, + span: Span) + -> Option { + let mut result = try_opt!(rewrite_generics(context, generics, offset, generics_offset, span)); + + if !generics.where_clause.predicates.is_empty() || result.contains('\n') { + let where_clause_str = try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.block_indent, + Density::Tall, + terminator, + Some(span.hi))); + result.push_str(&where_clause_str); + if !force_same_line_brace && + (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) { + result.push('\n'); + result.push_str(&context.block_indent.to_string(context.config)); + } else { + result.push(' '); + } + result.push_str(opener); + } else { + if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine { + result.push('\n'); + result.push_str(&context.block_indent.to_string(context.config)); + } else { + result.push(' '); + } + result.push_str(opener); + } + + Some(result) +} diff --git a/src/types.rs b/src/types.rs index 9e693e9cff6..1d991bb81da 100644 --- a/src/types.rs +++ b/src/types.rs @@ -492,13 +492,14 @@ impl Rewrite for ast::Ty { None } } - ast::TyBareFn(..) => { - wrap_str(pprust::ty_to_string(self), - context.config.max_width, - width, - offset) - } + ast::TyBareFn(ref bare_fn) => bare_fn.rewrite(context, width, offset), ast::TyMac(..) | ast::TyTypeof(..) => unreachable!(), } } } + +impl Rewrite for ast::BareFnTy { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + None + } +} diff --git a/src/visitor.rs b/src/visitor.rs index bf6e99e17c3..6448ccbabbc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -220,20 +220,24 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.hi; } ast::Item_::ItemStruct(ref def, ref generics) => { - let indent = self.block_indent; - let rewrite = self.format_struct("struct ", - item.ident, - item.vis, - def, - Some(generics), - item.span, - indent) - .map(|s| { - match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - } - }); + let rewrite = { + let indent = self.block_indent; + let context = self.get_context(); + ::items::format_struct(&context, + "struct ", + item.ident, + item.vis, + def, + Some(generics), + item.span, + indent) + .map(|s| { + match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + } + }) + }; self.push_rewrite(item.span, rewrite); } ast::Item_::ItemEnum(ref def, ref generics) => { -- cgit 1.4.1-3-g733a5 From 559f00ba9951b29c73339d94bcaeb5efa94b332a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 22 Nov 2015 14:48:30 +0100 Subject: Fix up indentation of function style paths Fixes https://github.com/rust-lang-nursery/rustfmt/issues/105. --- src/items.rs | 5 +---- src/types.rs | 39 ++++++++++++++++++++++++--------------- tests/source/fn-simple.rs | 5 ++++- tests/target/fn-simple.rs | 10 +++++++++- tests/target/hard-tabs.rs | 3 ++- 5 files changed, 40 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 48cb212e76d..d1502d173da 100644 --- a/src/items.rs +++ b/src/items.rs @@ -473,10 +473,7 @@ pub fn format_struct(context: &RewriteContext, } } -fn format_unit_struct(item_name: &str, - ident: ast::Ident, - vis: ast::Visibility) - -> Option { +fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> Option { let mut result = String::with_capacity(1024); let header_str = format_header(item_name, ident, vis); diff --git a/src/types.rs b/src/types.rs index 1d991bb81da..6d8ee483b14 100644 --- a/src/types.rs +++ b/src/types.rs @@ -200,11 +200,7 @@ fn rewrite_segment(expr_context: bool, ">", |param| param.get_span().lo, |param| param.get_span().hi, - |seg| { - seg.rewrite(context, - context.config.max_width, - offset + extra_offset) - }, + |seg| seg.rewrite(context, list_width, offset + extra_offset), list_lo, span_hi); let list_str = try_opt!(format_item_list(items, @@ -218,16 +214,8 @@ fn rewrite_segment(expr_context: bool, format!("{}<{}>", separator, list_str) } ast::PathParameters::ParenthesizedParameters(ref data) => { - let output = match data.output { - Some(ref ty) => { - let type_str = try_opt!(ty.rewrite(context, width, offset)); - format!(" -> {}", type_str) - } - None => String::new(), - }; - // 2 for () - let budget = try_opt!(width.checked_sub(output.len() + 2)); + let budget = try_opt!(width.checked_sub(2)); // 1 for ( let offset = offset + 1; let list_lo = span_after(data.span, "(", context.codemap); @@ -239,9 +227,30 @@ fn rewrite_segment(expr_context: bool, |ty| ty.rewrite(context, budget, offset), list_lo, span_hi); + println!("got here"); + let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); - format!("({}){}", list_str, output) + println!("got here 2"); + let output = match data.output { + Some(ref ty) => { + let budget = try_opt!(width.checked_sub(4)); + let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); + format!(" -> {}", type_str) + } + None => String::new(), + }; + + println!("got here 3"); + + let infix = if output.len() + list_str.len() > width { + format!("\n{}", (offset - 1).to_string(context.config)) + } else { + String::new() + }; + println!("({}){}{}", &list_str, &infix, &output); + + format!("({}){}{}", list_str, infix, output) } _ => String::new(), }; diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index b9f6a1e64b1..4c216ec26b8 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -1,6 +1,9 @@ fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ - ,response: NoWay /* hose */) {"cool"} + ,response: NoWay /* hose */) { +fn op(x: Typ, key : &[u8], upd : Box) -> (memcache::Status, Result>)>) -> MapResult {} + + "cool"} fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* tripple, even */*/*/, diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 9db1c8831b6..6acb1a3e582 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -2,6 +2,13 @@ fn simple(// pre-comment on a function!? i: i32, // yes, it's possible! response: NoWay /* hose */) { + fn op(x: Typ, + key: &[u8], + upd: Box) + -> (memcache::Status, Result>)>) + -> MapResult { + } + "cool" } @@ -23,7 +30,8 @@ fn generic(arg: T) -> &SomeType C, D, // pre comment - E /* last comment */) -> &SomeType + E /* last comment */) + -> &SomeType { arg(a, b, c, d, e) } diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 19a0182fdaa..cf96392036b 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -69,7 +69,8 @@ fn main() { C, D, // pre comment - E /* last comment */) -> &SomeType + E /* last comment */) + -> &SomeType { arg(a, b, c, d, e) } -- cgit 1.4.1-3-g733a5 From 840012b5e02db35a121bc69b91c77cde05f63ae7 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 22 Nov 2015 16:07:38 +0100 Subject: Format bare function types Fix https://github.com/rust-lang-nursery/rustfmt/issues/616. Fix https://github.com/rust-lang-nursery/rustfmt/issues/276. Close https://github.com/rust-lang-nursery/rustfmt/issues/350. --- src/items.rs | 15 ++---- src/types.rs | 130 +++++++++++++++++++++++++++++++--------------- src/utils.rs | 15 ++++++ tests/source/fn-simple.rs | 9 ++++ tests/target/extern.rs | 8 +-- tests/target/fn-simple.rs | 14 +++++ 6 files changed, 134 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d1502d173da..bbe51c73c40 100644 --- a/src/items.rs +++ b/src/items.rs @@ -80,11 +80,7 @@ impl Rewrite for ast::Local { impl<'a> FmtVisitor<'a> { pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { - self.buffer.push_str("extern "); - - if fm.abi != abi::Abi::C { - self.buffer.push_str(&format!("{} ", fm.abi)); - } + self.buffer.push_str(&::utils::format_abi(fm.abi)); let snippet = self.snippet(span); let brace_pos = snippet.find_uncommented("{").unwrap() as u32; @@ -856,17 +852,14 @@ fn rewrite_fn_base(context: &RewriteContext, let mut result = String::with_capacity(1024); // Vis unsafety abi. result.push_str(format_visibility(vis)); + result.push_str(::utils::format_unsafety(unsafety)); - if let ast::Unsafety::Unsafe = unsafety { - result.push_str("unsafe "); - } if let ast::Constness::Const = constness { result.push_str("const "); } + if abi != abi::Rust { - result.push_str("extern "); - result.push_str(&abi.to_string()); - result.push(' '); + result.push_str(&::utils::format_abi(abi)); } // fn foo diff --git a/src/types.rs b/src/types.rs index 6d8ee483b14..807f0f17a43 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::{self, Mutability}; +use syntax::ast::{self, Mutability, FunctionRetTy}; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos}; +use syntax::abi; use Indent; use lists::{format_item_list, itemize_list, format_fn_args}; @@ -214,43 +215,12 @@ fn rewrite_segment(expr_context: bool, format!("{}<{}>", separator, list_str) } ast::PathParameters::ParenthesizedParameters(ref data) => { - // 2 for () - let budget = try_opt!(width.checked_sub(2)); - // 1 for ( - let offset = offset + 1; - let list_lo = span_after(data.span, "(", context.codemap); - let items = itemize_list(context.codemap, - data.inputs.iter(), - ")", - |ty| ty.span.lo, - |ty| ty.span.hi, - |ty| ty.rewrite(context, budget, offset), - list_lo, - span_hi); - println!("got here"); - - let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); - - println!("got here 2"); - let output = match data.output { - Some(ref ty) => { - let budget = try_opt!(width.checked_sub(4)); - let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); - format!(" -> {}", type_str) - } - None => String::new(), - }; - - println!("got here 3"); - - let infix = if output.len() + list_str.len() > width { - format!("\n{}", (offset - 1).to_string(context.config)) - } else { - String::new() - }; - println!("({}){}{}", &list_str, &infix, &output); - - format!("({}){}{}", list_str, infix, output) + try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), + data.output.as_ref().map(|x| &**x), + data.span, + context, + width, + offset)) } _ => String::new(), }; @@ -258,6 +228,49 @@ fn rewrite_segment(expr_context: bool, Some(format!("{}{}", segment.identifier, params)) } +fn format_function_type<'a, I>(inputs: I, + output: Option<&ast::Ty>, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option + where I: Iterator +{ + // 2 for () + let budget = try_opt!(width.checked_sub(2)); + // 1 for ( + let offset = offset + 1; + let list_lo = span_after(span, "(", context.codemap); + let items = itemize_list(context.codemap, + inputs, + ")", + |ty| ty.span.lo, + |ty| ty.span.hi, + |ty| ty.rewrite(context, budget, offset), + list_lo, + span.hi); + + let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); + + let output = match output { + Some(ref ty) => { + let budget = try_opt!(width.checked_sub(4)); + let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); + format!(" -> {}", type_str) + } + None => String::new(), + }; + + let infix = if output.len() + list_str.len() > width { + format!("\n{}", (offset - 1).to_string(context.config)) + } else { + String::new() + }; + + Some(format!("({}){}{}", list_str, infix, output)) +} + impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { // TODO: dead spans? @@ -501,14 +514,47 @@ impl Rewrite for ast::Ty { None } } - ast::TyBareFn(ref bare_fn) => bare_fn.rewrite(context, width, offset), + ast::TyBareFn(ref bare_fn) => { + rewrite_bare_fn(bare_fn, self.span, context, width, offset) + } ast::TyMac(..) | ast::TyTypeof(..) => unreachable!(), } } } -impl Rewrite for ast::BareFnTy { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - None +fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let mut result = String::with_capacity(128); + + result.push_str(&::utils::format_unsafety(bare_fn.unsafety)); + + if bare_fn.abi != abi::Rust { + result.push_str(&::utils::format_abi(bare_fn.abi)); } + + result.push_str("fn"); + + let output = match bare_fn.decl.output { + FunctionRetTy::Return(ref ty) => Some(&**ty), + FunctionRetTy::NoReturn(..) => None, + FunctionRetTy::DefaultReturn(..) => unreachable!(), + }; + + let budget = try_opt!(width.checked_sub(result.len())); + let indent = offset + result.len(); + + let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter().map(|x| &*(x.ty)), + output, + span, + context, + budget, + indent)); + + result.push_str(&rewrite); + + Some(result) } diff --git a/src/utils.rs b/src/utils.rs index 37dfb756972..6170b0c5ee0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -12,6 +12,7 @@ use std::cmp::Ordering; use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::abi; use Indent; use comment::FindUncommented; @@ -45,6 +46,14 @@ pub fn format_visibility(vis: Visibility) -> &'static str { } } +#[inline] +pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { + match unsafety { + ast::Unsafety::Unsafe => "unsafe ", + ast::Unsafety::Normal => "", + } +} + #[inline] pub fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { @@ -53,6 +62,12 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } } +#[inline] +// FIXME(#451): include "C"? +pub fn format_abi(abi: abi::Abi) -> String { + format!("extern {} ", abi) +} + // The width of the first line in s. #[inline] pub fn first_line_width(s: &str) -> usize { diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 4c216ec26b8..93c43224417 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -32,3 +32,12 @@ fn zzzzzzzzzzzzzzzzzzzz (selff: Type, mut handle: node::Handle>, Type, NodeType>) -> SearchStack<'a, K, V, Type, NodeType>{ } + +unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8) { + let f: fn ( _ , _ ) -> _ = panic!() ; +} diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 35475660bae..ca8c43d8b2c 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,5 +1,5 @@ -extern { +extern "C" { fn c_func(x: *mut *mut libc::c_void); fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, @@ -11,7 +11,7 @@ extern { pub fn bar(); } -extern { +extern "C" { fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, @@ -28,7 +28,7 @@ extern "Rust" { pub static mut var: SomeType; } -extern { +extern "C" { fn syscall(number: libc::c_long, // comment 1 // comm 2 ... /* sup? */) @@ -37,7 +37,7 @@ extern { fn foo(x: *const c_char, ...) -> libc::c_long; } -extern { +extern "C" { pub fn freopen(filename: *const c_char, mode: *const c_char, mode2: *const c_char, diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 6acb1a3e582..e5de6b0f00d 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -50,3 +50,17 @@ fn zzzzzzzzzzzzzzzzzzzz(selff: Type, NodeType>) -> SearchStack<'a, K, V, Type, NodeType> { } + +unsafe fn generic_call(cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern "C" fn(*const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal) + -> u8) { + let f: fn(_, _) -> _ = panic!(); +} -- cgit 1.4.1-3-g733a5 From 2b0a25a5390d32b50697f414ff80a17c44b7307d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 22 Nov 2015 17:41:54 +0100 Subject: Fix last comment for visually formatted struct lits --- src/expr.rs | 9 ++++----- tests/source/struct_lits_visual.rs | 3 +++ tests/target/struct_lits_visual.rs | 3 +++ 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 29d6d32c0dd..6a34257eca3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1364,6 +1364,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, _ => v_budget, }; + let ends_with_newline = context.config.struct_lit_style != StructLitStyle::Visual && + tactic == DefinitiveListTactic::Vertical; + let fmt = ListFormatting { tactic: tactic, separator: ",", @@ -1374,11 +1377,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }, indent: indent, width: budget, - ends_with_newline: match tactic { - DefinitiveListTactic::Horizontal => false, - DefinitiveListTactic::Vertical => true, - DefinitiveListTactic::Mixed => unreachable!(), - }, + ends_with_newline: ends_with_newline, config: context.config, }; let fields_str = try_opt!(write_list(&item_vec, &fmt)); diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index f483b08b625..c7534eff7cb 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -25,6 +25,9 @@ fn main() { Quux { x: if cond { bar(); }, y: baz() }; + Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, z: zzzzz // test + }; + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. first: item(), diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 5ebc3a8684f..d5978c3debb 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -42,6 +42,9 @@ fn main() { }, y: baz(), }; + Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + z: zzzzz, /* test */ }; + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante // hendrerit. Donec et mollis dolor. -- cgit 1.4.1-3-g733a5 From ba936766c6182fa5bb15c85243d070b326b690dc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Nov 2015 09:20:53 +1300 Subject: Take rustfmt_skip attribute into account on modules Closes #632 --- src/visitor.rs | 21 +++++++++++---------- tests/source/multiple.rs | 7 +++++++ tests/target/multiple.rs | 7 +++++++ 3 files changed, 25 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 6448ccbabbc..6cbac8592dd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -28,7 +28,7 @@ pub struct FmtVisitor<'a> { pub codemap: &'a CodeMap, pub buffer: StringBuffer, pub last_pos: BytePos, - // TODO: RAII util for indenting + // FIXME: use an RAII util or closure for indenting pub block_indent: Indent, pub config: &'a Config, pub write_mode: Option, @@ -99,7 +99,7 @@ impl<'a> FmtVisitor<'a> { } } - // TODO: we should compress any newlines here to just one + // FIXME: we should compress any newlines here to just one self.format_missing_with_indent(b.span.hi - brace_compensation); self.close_block(); self.last_pos = b.span.hi; @@ -178,12 +178,17 @@ impl<'a> FmtVisitor<'a> { } fn visit_item(&mut self, item: &ast::Item) { - // Don't look at attributes for modules. + // Don't look at attributes for modules (except for rustfmt_skip). // We want to avoid looking at attributes in another file, which the AST - // doesn't distinguish. FIXME This is overly conservative and means we miss - // attributes on inline modules. + // doesn't distinguish. + // FIXME This is overly conservative and means we miss attributes on + // inline modules. match item.node { - ast::Item_::ItemMod(_) => {} + ast::Item_::ItemMod(_) => { + if utils::contains_skip(&item.attrs) { + return; + } + } _ => { if self.visit_attrs(&item.attrs) { return; @@ -406,10 +411,6 @@ impl<'a> FmtVisitor<'a> { // Returns true if we should skip the following item. pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { - if attrs.is_empty() { - return false; - } - if utils::contains_skip(attrs) { return true; } diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 38d7d8ca941..863d20f50ea 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -123,3 +123,10 @@ fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, RequestUri, HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } + +#[rustfmt_skip] +mod a{ +fn foo(x: T) { + let x: T = dfasdf; +} +} diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 7b371409fba..e29bb259ece 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -158,3 +158,10 @@ fn deconstruct(foo: Bar) HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } + +#[rustfmt_skip] +mod a{ +fn foo(x: T) { + let x: T = dfasdf; +} +} -- cgit 1.4.1-3-g733a5 From 4b4dd170d809c24fb308ea1bf81b91541a5b8b01 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 22 Nov 2015 22:55:57 +0100 Subject: Correct doc comment indentation for struct fields Fix https://github.com/rust-lang-nursery/rustfmt/issues/572. --- src/items.rs | 7 +++---- src/lists.rs | 8 +------- tests/source/structs.rs | 4 ++++ tests/target/imports.rs | 3 ++- tests/target/structs.rs | 4 ++++ 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 19aec73f116..d69e1866654 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1195,15 +1195,14 @@ impl Rewrite for ast::StructField { ast::StructFieldKind::NamedField(_, vis) | ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; - let indent = context.block_indent.block_indent(context.config); let mut attr_str = try_opt!(self.node .attrs .rewrite(context, - context.config.max_width - indent.width(), - indent)); + context.config.max_width - offset.width(), + offset)); if !attr_str.is_empty() { attr_str.push('\n'); - attr_str.push_str(&indent.to_string(context.config)); + attr_str.push_str(&offset.to_string(context.config)); } let result = match name { diff --git a/src/lists.rs b/src/lists.rs index ecde4f19fe4..5bd2845c0e5 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -14,7 +14,6 @@ use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; use Indent; -use utils::wrap_str; use comment::{FindUncommented, rewrite_comment, find_comment_end}; use config::Config; @@ -280,12 +279,7 @@ pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option } } - // Make sure that string actually fits. - let item_str = try_opt!(wrap_str(&inner_item[..], - formatting.config.max_width, - formatting.width, - formatting.indent)); - result.push_str(&item_str); + result.push_str(&inner_item[..]); // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 9a559e029db..6d7f6213eca 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -141,3 +141,7 @@ mod m { a: T, } } + +struct Foo(TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU); diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 948b6da7c2b..296230ef8ba 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -2,7 +2,8 @@ // Long import. use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 50090b7a5f4..9e17dec1411 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -149,3 +149,7 @@ mod m { a: T, } } + +struct Foo(TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU); -- cgit 1.4.1-3-g733a5 From 9cf8529e335995d54b178194d00172f7f7dd15d5 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Nov 2015 12:00:22 +1300 Subject: Implement formatting for impls Fixes #614 --- src/items.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/types.rs | 16 +++++---- src/utils.rs | 7 ++++ src/visitor.rs | 14 ++++---- 4 files changed, 121 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index bbe51c73c40..b4bd89ebb91 100644 --- a/src/items.rs +++ b/src/items.rs @@ -12,7 +12,7 @@ use Indent; use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, - wrap_str, last_line_width, semicolon_for_expr}; + wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; @@ -435,6 +435,104 @@ impl<'a> FmtVisitor<'a> { } } +pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { + if let ast::Item_::ItemImpl(unsafety, + polarity, + ref generics, + ref trait_ref, + ref self_ty, + ref items) = item.node { + let mut result = String::new(); + result.push_str(format_visibility(item.vis)); + result.push_str(format_unsafety(unsafety)); + result.push_str("impl"); + + let lo = span_after(item.span, "impl", context.codemap); + let hi = match *trait_ref { + Some(ref tr) => tr.path.span.lo, + None => self_ty.span.lo, + }; + let generics_str = try_opt!(rewrite_generics(context, + generics, + offset, + offset + result.len(), + mk_sp(lo, hi))); + result.push_str(&generics_str); + + // FIXME might need to linebreak in the impl header, here would be a + // good place. + result.push(' '); + if polarity == ast::ImplPolarity::Negative { + result.push_str("!"); + } + if let &Some(ref trait_ref) = trait_ref { + let budget = try_opt!(context.config.max_width.checked_sub(result.len())); + let indent = offset + result.len(); + result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent))); + result.push_str(" for "); + } + + let budget = try_opt!(context.config.max_width.checked_sub(result.len())); + let indent = offset + result.len(); + result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); + + let where_clause_str = try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.block_indent, + context.config.where_density, + "{", + None)); + if !where_clause_str.contains('\n') && + result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + result.push('\n'); + let width = context.block_indent.width() + context.config.tab_spaces - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string(context.config)); + } + result.push_str(&where_clause_str); + + match context.config.item_brace_style { + BraceStyle::AlwaysNextLine => result.push('\n'), + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if where_clause_str.len() > 0 { + result.push('\n') + } else { + result.push(' ') + } + } + } + result.push('{'); + + if !items.is_empty() { + result.push('\n'); + let indent_str = context.block_indent.to_string(context.config); + result.push_str(&indent_str); + + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + visitor.block_indent = context.block_indent.block_indent(context.config); + + let snippet = context.snippet(item.span); + let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + + for item in items { + visitor.visit_impl_item(&item); + } + + result.push_str(trim_newlines(&visitor.buffer.to_string())); + result.push('\n'); + result.push_str(&indent_str); + } + result.push('}'); + + Some(result) + } else { + unreachable!(); + } +} + pub fn format_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, diff --git a/src/types.rs b/src/types.rs index 807f0f17a43..4faa0a05f91 100644 --- a/src/types.rs +++ b/src/types.rs @@ -432,20 +432,22 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); - let path_str = try_opt!(rewrite_path(context, - false, - None, - &self.trait_ref.path, - max_path_width, - offset + extra_offset)); + let path_str = try_opt!(self.trait_ref + .rewrite(context, max_path_width, offset + extra_offset)); Some(format!("for<{}> {}", lifetime_str, path_str)) } else { - rewrite_path(context, false, None, &self.trait_ref.path, width, offset) + self.trait_ref.rewrite(context, width, offset) } } } +impl Rewrite for ast::TraitRef { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + rewrite_path(context, false, None, &self.path, width, offset) + } +} + impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { diff --git a/src/utils.rs b/src/utils.rs index 6170b0c5ee0..195ca265c1f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -142,6 +142,13 @@ pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { } } +#[inline] +pub fn trim_newlines(input: &str) -> &str { + let start = input.find(|c| c != '\n' && c != '\r').unwrap_or(0); + let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; + &input[start..end] +} + #[inline] #[cfg(target_pointer_width="64")] // Based on the trick layed out at diff --git a/src/visitor.rs b/src/visitor.rs index 6cbac8592dd..fcc017c98f2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::rewrite_static; +use items::{rewrite_static, format_impl}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -200,14 +200,12 @@ impl<'a> FmtVisitor<'a> { ast::Item_::ItemUse(ref vp) => { self.format_import(item.vis, vp, item.span); } - // FIXME(#78): format impl definitions. - ast::Item_::ItemImpl(_, _, _, _, _, ref impl_items) => { + ast::Item_::ItemImpl(..) => { self.format_missing_with_indent(item.span.lo); - self.block_indent = self.block_indent.block_indent(self.config); - for item in impl_items { - self.visit_impl_item(&item); + if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent) { + self.buffer.push_str(&impl_str); + self.last_pos = item.span.hi; } - self.block_indent = self.block_indent.block_unindent(self.config); } // FIXME(#78): format traits. ast::Item_::ItemTrait(_, _, _, ref trait_items) => { @@ -334,7 +332,7 @@ impl<'a> FmtVisitor<'a> { } } - fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { if self.visit_attrs(&ii.attrs) { return; } -- cgit 1.4.1-3-g733a5 From b577f95e3c10b6b39443b7e2542ee046304b4153 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Nov 2015 12:02:54 +1300 Subject: Reformatting due to changes --- src/comment.rs | 10 ++++++++-- tests/target/pattern.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0f118ca5d29..cb3b4b5f4d7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -219,7 +219,10 @@ pub enum CodeCharKind { Comment, } -impl CharClasses where T: Iterator, T::Item: RichChar { +impl CharClasses + where T: Iterator, + T::Item: RichChar +{ fn new(base: T) -> CharClasses { CharClasses { base: base.peekable(), @@ -228,7 +231,10 @@ impl CharClasses where T: Iterator, T::Item: RichChar { } } -impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { +impl Iterator for CharClasses + where T: Iterator, + T::Item: RichChar +{ type Item = (CodeCharKind, T::Item); fn next(&mut self) -> Option<(CodeCharKind, T::Item)> { diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index aa121268daf..eb42f9fde73 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -15,7 +15,7 @@ fn main() { } } -impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { +impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { fn mutate_fragment(&mut self, fragment: &mut Fragment) { match **info { GeneratedContentInfo::ContentItem(ContentItem::Counter(ref counter_name, -- cgit 1.4.1-3-g733a5 From e3f39941de464a4110ccf11b974ed86a53ec2555 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Nov 2015 13:23:41 +1300 Subject: Types which can be return types for function types Fixes #643 --- src/types.rs | 23 +++++++++++------------ tests/target/fn-ty.rs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 tests/target/fn-ty.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 4faa0a05f91..c483032b451 100644 --- a/src/types.rs +++ b/src/types.rs @@ -215,8 +215,12 @@ fn rewrite_segment(expr_context: bool, format!("{}<{}>", separator, list_str) } ast::PathParameters::ParenthesizedParameters(ref data) => { + let output = match data.output { + Some(ref ty) => FunctionRetTy::Return(ty.clone()), + None => FunctionRetTy::DefaultReturn(codemap::DUMMY_SP), + }; try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), - data.output.as_ref().map(|x| &**x), + &output, data.span, context, width, @@ -229,7 +233,7 @@ fn rewrite_segment(expr_context: bool, } fn format_function_type<'a, I>(inputs: I, - output: Option<&ast::Ty>, + output: &FunctionRetTy, span: Span, context: &RewriteContext, width: usize, @@ -253,13 +257,14 @@ fn format_function_type<'a, I>(inputs: I, let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); - let output = match output { - Some(ref ty) => { + let output = match *output { + FunctionRetTy::Return(ref ty) => { let budget = try_opt!(width.checked_sub(4)); let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); format!(" -> {}", type_str) } - None => String::new(), + FunctionRetTy::NoReturn(..) => " -> !".to_owned(), + FunctionRetTy::DefaultReturn(..) => String::new(), }; let infix = if output.len() + list_str.len() > width { @@ -540,17 +545,11 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str("fn"); - let output = match bare_fn.decl.output { - FunctionRetTy::Return(ref ty) => Some(&**ty), - FunctionRetTy::NoReturn(..) => None, - FunctionRetTy::DefaultReturn(..) => unreachable!(), - }; - let budget = try_opt!(width.checked_sub(result.len())); let indent = offset + result.len(); let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter().map(|x| &*(x.ty)), - output, + &bare_fn.decl.output, span, context, budget, diff --git a/tests/target/fn-ty.rs b/tests/target/fn-ty.rs new file mode 100644 index 00000000000..7432fcded34 --- /dev/null +++ b/tests/target/fn-ty.rs @@ -0,0 +1,12 @@ +fn f(xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, + xxxxxxxxxxxxxxxxxx: fn() -> a, + xxxxxxxxxxxxxxxxxx: fn(a, b, b), + xxxxxxxxxxxxxxxxxx: fn(), + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, + xxxxxxxxxxxxxxxxxx: fn() -> !) + where F1: Fn(a, b, b) -> a, + F2: Fn(a, b, b), + F3: Fn(), + F4: Fn() -> u32 +{ +} -- cgit 1.4.1-3-g733a5 From 2661592d59a30a175f71667a9ad751f52e58b3eb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Nov 2015 15:22:00 +1300 Subject: Handle multiply-referenced files Fixes #645 --- src/lib.rs | 4 ++-- src/visitor.rs | 4 ++-- tests/target/mulit-file.rs | 10 ++++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tests/target/mulit-file.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3923f6b742d..dd065a9939c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -298,7 +298,7 @@ fn fmt_ast(krate: &ast::Crate, println!("Formatting {}", path); } let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode)); - visitor.format_separate_mod(module, path); + visitor.format_separate_mod(module); file_map.insert(path.to_owned(), visitor.buffer); } file_map @@ -404,7 +404,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap // do the actual formatting let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode)); - visitor.format_separate_mod(&krate.module, path); + visitor.format_separate_mod(&krate.module); // append final newline visitor.buffer.push_str("\n"); diff --git a/src/visitor.rs b/src/visitor.rs index fcc017c98f2..15db08f7942 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -463,8 +463,8 @@ impl<'a> FmtVisitor<'a> { } } - pub fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) { - let filemap = self.codemap.get_filemap(filename); + pub fn format_separate_mod(&mut self, m: &ast::Mod) { + let filemap = self.codemap.lookup_char_pos(m.inner.lo).file; self.last_pos = filemap.start_pos; self.block_indent = Indent::empty(); self.walk_mod_items(m); diff --git a/tests/target/mulit-file.rs b/tests/target/mulit-file.rs new file mode 100644 index 00000000000..1f829b36f3f --- /dev/null +++ b/tests/target/mulit-file.rs @@ -0,0 +1,10 @@ +// Tests that where a single file is referred to in multiple places, we don't +// crash. + +#[cfg(all(foo))] +#[path = "closure.rs"] +pub mod imp; + +#[cfg(all(bar))] +#[path = "closure.rs"] +pub mod imp; -- cgit 1.4.1-3-g733a5 From 411fa40988ca4bbeea498db3afbf3db8785d7c09 Mon Sep 17 00:00:00 2001 From: Jakko Sikkar Date: Mon, 23 Nov 2015 20:54:33 +0200 Subject: update dependencies and fix compile errors --- Cargo.lock | 10 +++++----- src/visitor.rs | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 23a75bfb547..87e4c64ce2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", - "syntex_syntax 0.21.0 (git+https://github.com/serde-rs/syntex)", + "syntex_syntax 0.22.0 (git+https://github.com/serde-rs/syntex)", "term 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -25,7 +25,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -112,10 +112,10 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.21.0" -source = "git+https://github.com/serde-rs/syntex#069fe5d5e8cc8132dc3cb97099511240b9d4facc" +version = "0.22.0" +source = "git+https://github.com/serde-rs/syntex#7913a15053ef5f2526aeff8b318f49d010582efd" dependencies = [ - "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/visitor.rs b/src/visitor.rs index 6cbac8592dd..18128f1226c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -340,20 +340,20 @@ impl<'a> FmtVisitor<'a> { } match ii.node { - ast::MethodImplItem(ref sig, ref body) => { + ast::ImplItemKind::Method(ref sig, ref body) => { self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(ii.vis)), &sig.decl, body, ii.span, ii.id); } - ast::ConstImplItem(..) => { + ast::ImplItemKind::Const(..) => { // FIXME: Implement } - ast::TypeImplItem(_) => { + ast::ImplItemKind::Type(_) => { // FIXME: Implement } - ast::MacImplItem(ref mac) => { + ast::ImplItemKind::Macro(ref mac) => { self.visit_mac(mac); } } -- cgit 1.4.1-3-g733a5 From d405fdc2363486173b56deef1dc05ef7ea53c04b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Nov 2015 15:49:21 +1300 Subject: Fix a bug with nested impls --- src/items.rs | 7 +++---- tests/source/impls.rs | 20 ++++++++++++++++++++ tests/target/impls.rs | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c75fe9a942f..6ca82721689 100644 --- a/src/items.rs +++ b/src/items.rs @@ -506,10 +506,6 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - result.push('{'); if !items.is_empty() { - result.push('\n'); - let indent_str = context.block_indent.to_string(context.config); - result.push_str(&indent_str); - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); visitor.block_indent = context.block_indent.block_indent(context.config); @@ -521,8 +517,11 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - visitor.visit_impl_item(&item); } + result.push('\n'); result.push_str(trim_newlines(&visitor.buffer.to_string())); result.push('\n'); + + let indent_str = context.block_indent.to_string(context.config); result.push_str(&indent_str); } result.push('}'); diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 8e7b561ae4a..499b07afd27 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -21,3 +21,23 @@ impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooo { fn foo() { "hi" } } + +impl Foo { + fn foo() {} +} + +mod a { + impl Foo { + // Hello! + fn foo() {} + } +} + + +mod b { + mod a { + impl Foo { + fn foo() {} + } + } +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 7530bf16ede..d491dbfcea8 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -36,3 +36,23 @@ impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooo "hi" } } + +impl Foo { + fn foo() {} +} + +mod a { + impl Foo { + // Hello! + fn foo() {} + } +} + + +mod b { + mod a { + impl Foo { + fn foo() {} + } + } +} -- cgit 1.4.1-3-g733a5 From b6dc8a3f764e2fec67268c5611ca15fc2c005380 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Mon, 23 Nov 2015 22:54:44 -0600 Subject: Keep comments in empty impl bodies --- src/items.rs | 24 ++++++++++++++---------- tests/target/impl.rs | 4 ++++ tests/target/impls.rs | 1 + 3 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6ca82721689..51f064d92a1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,7 +16,7 @@ use utils::{format_mutability, format_visibility, contains_skip, span_after, end use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; -use comment::FindUncommented; +use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; @@ -505,27 +505,31 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - } result.push('{'); - if !items.is_empty() { + let snippet = context.snippet(item.span); + let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + + if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); visitor.block_indent = context.block_indent.block_indent(context.config); - - let snippet = context.snippet(item.span); - let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in items { visitor.visit_impl_item(&item); } + visitor.format_missing(item.span.hi - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string(context.config); + let outer_indent_str = context.block_indent.to_string(context.config); + result.push('\n'); - result.push_str(trim_newlines(&visitor.buffer.to_string())); + result.push_str(&inner_indent_str); + result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); result.push('\n'); - - let indent_str = context.block_indent.to_string(context.config); - result.push_str(&indent_str); + result.push_str(&outer_indent_str); } - result.push('}'); + result.push('}'); Some(result) } else { unreachable!(); diff --git a/tests/target/impl.rs b/tests/target/impl.rs index df44377a6bf..5dde5ee7382 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -1,3 +1,7 @@ // Test impls impl JSTraceable for SmallVec<[T; 1]> {} + +impl>> Handle { + // Keep this. +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index d491dbfcea8..cc60b822794 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -13,6 +13,7 @@ pub impl Foo for Bar { fn foo() { "hi" } + // Comment 3 } pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> -- cgit 1.4.1-3-g733a5 From f5fac4c54fda910c33dad2a22cb6d4d59784b00c Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Tue, 24 Nov 2015 14:37:31 -0600 Subject: Fix empty trim_newline panic, add impl macro test --- src/utils.rs | 6 +++++- tests/source/impls.rs | 7 +++++++ tests/target/impls.rs | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 195ca265c1f..aaa838bf043 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -146,7 +146,11 @@ pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { pub fn trim_newlines(input: &str) -> &str { let start = input.find(|c| c != '\n' && c != '\r').unwrap_or(0); let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; - &input[start..end] + if start == 0 && end == 1 { + input + } else { + &input[start..end] + } } #[inline] diff --git a/tests/source/impls.rs b/tests/source/impls.rs index c15ae12325e..4382c4fd0e6 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -51,3 +51,10 @@ mod b { } } } + +impl Foo { add_fun!(); } + +impl Blah { + fn boop() {} + add_fun!(); +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 972991572a5..35ddc23a20a 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -63,3 +63,12 @@ mod b { } } } + +impl Foo { + add_fun!(); +} + +impl Blah { + fn boop() {} + add_fun!(); +} -- cgit 1.4.1-3-g733a5 From 2b11d84119d78d92af8bcbd2688770c9d530c830 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Wed, 25 Nov 2015 15:39:15 +0900 Subject: Apply Clippy --- src/chains.rs | 2 +- src/expr.rs | 2 +- src/items.rs | 8 ++++---- src/lib.rs | 4 ++-- src/lists.rs | 2 +- src/missed_spans.rs | 7 ++++--- src/visitor.rs | 2 +- 7 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9e85b22da02..952c7f1e08e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -168,7 +168,7 @@ fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { } } -fn pop_expr_chain<'a>(expr: &'a ast::Expr) -> Option<&'a ast::Expr> { +fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { match expr.node { ast::Expr_::ExprMethodCall(_, _, ref expressions) => Some(&expressions[0]), ast::Expr_::ExprTupField(ref subexpr, _) | diff --git a/src/expr.rs b/src/expr.rs index 6a34257eca3..040c83488a7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1008,7 +1008,7 @@ fn rewrite_guard(context: &RewriteContext, // the arm (excludes offset). pattern_width: usize) -> Option { - if let &Some(ref guard) = guard { + if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; diff --git a/src/items.rs b/src/items.rs index 6ca82721689..01847f80d38 100644 --- a/src/items.rs +++ b/src/items.rs @@ -465,7 +465,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if polarity == ast::ImplPolarity::Negative { result.push_str("!"); } - if let &Some(ref trait_ref) = trait_ref { + if let Some(ref trait_ref) = *trait_ref { let budget = try_opt!(context.config.max_width.checked_sub(result.len())); let indent = offset + result.len(); result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent))); @@ -496,7 +496,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - BraceStyle::AlwaysNextLine => result.push('\n'), BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { - if where_clause_str.len() > 0 { + if !where_clause_str.is_empty() { result.push('\n') } else { result.push(' ') @@ -720,7 +720,7 @@ fn format_tuple_struct(context: &RewriteContext, result.push_str(&body); result.push(')'); - if where_clause_str.len() > 0 && !where_clause_str.contains('\n') && + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && (result.contains('\n') || context.block_indent.width() + result.len() + where_clause_str.len() + 1 > context.config.max_width) { @@ -1052,7 +1052,7 @@ fn rewrite_fn_base(context: &RewriteContext, let indent = match context.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, // Aligning with non-existent args looks silly. - _ if arg_str.len() == 0 => { + _ if arg_str.is_empty() => { force_new_line_for_brace = true; indent + 4 } diff --git a/src/lib.rs b/src/lib.rs index dd065a9939c..ad3e3b27e2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -410,7 +410,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap visitor.buffer.push_str("\n"); file_map.insert(path.to_owned(), visitor.buffer); - return file_map; + file_map } pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { @@ -427,7 +427,7 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { // newlines so we must add one on for each file. This is sad. filemap::append_newlines(&mut file_map); - return file_map; + file_map } // args are the arguments passed on the command line, generally passed through diff --git a/src/lists.rs b/src/lists.rs index 5bd2845c0e5..4dd2e5d1dce 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -191,7 +191,7 @@ pub fn definitive_tactic<'t, I, T>(items: I, // Format a list of commented items into a string. // TODO: add unit tests -pub fn write_list<'b, I, T>(items: I, formatting: &ListFormatting<'b>) -> Option +pub fn write_list(items: I, formatting: &ListFormatting) -> Option where I: IntoIterator, T: AsRef { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 0da0f3ebb33..c123a9bc81b 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -94,9 +94,10 @@ impl<'a> FmtVisitor<'a> { fn replace_chars(string: &str) -> String { string.chars() .map(|ch| { - match ch.is_whitespace() { - true => ch, - false => 'X', + if ch.is_whitespace() { + ch + } else { + 'X' } }) .collect() diff --git a/src/visitor.rs b/src/visitor.rs index 7d50a6da61b..98a706adc41 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -415,7 +415,7 @@ impl<'a> FmtVisitor<'a> { let outers: Vec<_> = attrs.iter() .filter(|a| a.node.style == ast::AttrStyle::Outer) - .map(|a| a.clone()) + .cloned() .collect(); if outers.is_empty() { return false; -- cgit 1.4.1-3-g733a5 From 314aff1a33c2174e8b52a7a80fc9104dd0686237 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Wed, 25 Nov 2015 22:25:02 -0600 Subject: Reformat trim_newlines --- src/utils.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index aaa838bf043..b1bbb860edb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -144,12 +144,12 @@ pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { #[inline] pub fn trim_newlines(input: &str) -> &str { - let start = input.find(|c| c != '\n' && c != '\r').unwrap_or(0); - let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; - if start == 0 && end == 1 { - input - } else { - &input[start..end] + match input.find(|c| c != '\n' && c != '\r') { + Some(start) => { + let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; + &input[start..end] + } + None => "", } } -- cgit 1.4.1-3-g733a5 From c61d6d4c3a2bbaba4728e840bb29d5590a528075 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sun, 22 Nov 2015 19:21:01 +0100 Subject: Format type aliases Fixes #486 --- src/items.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++ src/visitor.rs | 13 ++++++++--- tests/source/type_alias.rs | 16 ++++++++++++++ tests/target/type_alias.rs | 27 +++++++++++++++++++++++ 4 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 tests/source/type_alias.rs create mode 100644 tests/target/type_alias.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9de91307b27..9ba2985c2a0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -739,6 +739,61 @@ fn format_tuple_struct(context: &RewriteContext, Some(result) } +pub fn rewrite_type_alias(context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + ty: &ast::Ty, + generics: &ast::Generics, + vis: ast::Visibility, + span: Span) + -> Option { + let mut result = String::new(); + + result.push_str(&format_visibility(vis)); + result.push_str("type "); + result.push_str(&ident.to_string()); + + let generics_indent = indent + result.len(); + let generics_span = mk_sp(span_after(span, "type", context.codemap), ty.span.lo); + let generics_str = try_opt!(rewrite_generics(context, + generics, + indent, + generics_indent, + generics_span)); + + result.push_str(&generics_str); + result.push_str(" = "); + + let last_line_length = match generics_str.rfind("\n") { + Some(index) => " = ".len() + generics_str.len() - index, + None => result.len(), + }; + + let budget = try_opt!(context.config + .max_width + .checked_sub(indent.width() + last_line_length + ";".len())); + let type_indent = indent + last_line_length; + // Try to fit the type on the same line + let ty_str = try_opt!(ty.rewrite(context, budget, type_indent) + .or_else(|| { + // The line was to short try and put the type on the next line + + // Remove the space after '=' + result.pop(); + let type_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&type_indent.to_string(context.config)); + let budget = try_opt!(context.config + .max_width + .checked_sub(type_indent.width() + + ";".len())); + ty.rewrite(context, budget, type_indent) + })); + result.push_str(&ty_str); + result.push_str(";"); + Some(result) +} + impl Rewrite for ast::StructField { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if contains_skip(&self.node.attrs) { diff --git a/src/visitor.rs b/src/visitor.rs index 98a706adc41..7b694de4535 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, format_impl}; +use items::{rewrite_static, rewrite_type_alias, format_impl}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -299,8 +299,15 @@ impl<'a> FmtVisitor<'a> { item.span, item.id) } - ast::Item_::ItemTy(..) => { - // FIXME(#486): format type aliases. + ast::Item_::ItemTy(ref ty, ref generics) => { + let rewrite = rewrite_type_alias(&self.get_context(), + self.block_indent, + item.ident, + ty, + generics, + item.vis, + item.span); + self.push_rewrite(item.span, rewrite); } } } diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs new file mode 100644 index 00000000000..3f8a6ccfe3e --- /dev/null +++ b/tests/source/type_alias.rs @@ -0,0 +1,16 @@ + +type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); + +pub type PublicTest<'a, I, O> = Result, Box + 'a>, Box + 'a>>; + +pub type LongGenericListTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Option>; + +pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type CommentTest< /* Lifetime */ 'a + , + // Type + T + > = (); diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs new file mode 100644 index 00000000000..a468f7920e3 --- /dev/null +++ b/tests/target/type_alias.rs @@ -0,0 +1,27 @@ + +type PrivateTest<'a, I> = (Box + 'a>, + Box + 'a>); + +pub type PublicTest<'a, I, O> = Result, + Box + 'a>, + Box + 'a>>; + +pub type LongGenericListTest<'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A, + B, + C> = Option>; + +pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = + Vec; + +pub type CommentTest = (); -- cgit 1.4.1-3-g733a5 From 0021001a077b082947ea1ed1386ef2954a11d813 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 26 Nov 2015 21:20:04 +0100 Subject: Use utils::last_line_width in rewrite_type_alias --- src/items.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9ba2985c2a0..0f5fa1b655f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -764,19 +764,15 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&generics_str); result.push_str(" = "); - let last_line_length = match generics_str.rfind("\n") { - Some(index) => " = ".len() + generics_str.len() - index, - None => result.len(), - }; - + let line_width = last_line_width(&result); let budget = try_opt!(context.config .max_width - .checked_sub(indent.width() + last_line_length + ";".len())); - let type_indent = indent + last_line_length; + .checked_sub(indent.width() + line_width + ";".len())); + let type_indent = indent + line_width; // Try to fit the type on the same line let ty_str = try_opt!(ty.rewrite(context, budget, type_indent) .or_else(|| { - // The line was to short try and put the type on the next line + // The line was too short, try to put the type on the next line // Remove the space after '=' result.pop(); -- cgit 1.4.1-3-g733a5 From 937467c35820031f3803962675b3a5304d0f5c48 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 27 Nov 2015 09:25:31 +0100 Subject: Fix where clauses not taking the width of the line into account Fixes #630 --- src/items.rs | 29 +++++++++++++++++++++++------ tests/source/where-clause.rs | 16 ++++++++++++++++ tests/target/where-clause.rs | 21 +++++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 tests/source/where-clause.rs create mode 100644 tests/target/where-clause.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0f5fa1b655f..f1be0ed76a1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -476,10 +476,12 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let indent = offset + result.len(); result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); + let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, context.block_indent, + where_budget, context.config.where_density, "{", None)); @@ -678,27 +680,31 @@ fn format_tuple_struct(context: &RewriteContext, let body_lo = fields[0].span.lo; - let (generics_str, where_clause_str) = match generics { + let where_clause_str = match generics { Some(ref generics) => { let generics_str = try_opt!(rewrite_generics(context, generics, offset, offset + header_str.len(), mk_sp(span.lo, body_lo))); + result.push_str(&generics_str); + let where_budget = try_opt!(context.config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, context.block_indent, + where_budget, Density::Compressed, ";", None)); - (generics_str, where_clause_str) + where_clause_str } - None => ("".to_owned(), "".to_owned()), + None => "".to_owned(), }; - result.push_str(&generics_str); result.push('('); let item_indent = context.block_indent + result.len(); @@ -1168,10 +1174,12 @@ fn rewrite_fn_base(context: &RewriteContext, }; // Where clause. + let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, context.config, indent, + where_budget, where_density, "{", Some(span.hi))); @@ -1409,6 +1417,7 @@ fn rewrite_where_clause(context: &RewriteContext, where_clause: &ast::WhereClause, config: &Config, indent: Indent, + width: usize, density: Density, terminator: &str, span_end: Option) @@ -1462,9 +1471,15 @@ fn rewrite_where_clause(context: &RewriteContext, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); - // 9 = " where ".len() + " {".len() + // When '{' is the terminator just assume that it is put on the next line for single line where + // clauses + let end_length = if terminator == ";" { + 1 + } else { + 0 + }; if density == Density::Tall || preds_str.contains('\n') || - indent.width() + 9 + preds_str.len() > context.config.max_width { + indent.width() + " where ".len() + preds_str.len() + end_length > width { Some(format!("\n{}where {}", (indent + extra_indent).to_string(context.config), preds_str)) @@ -1490,10 +1505,12 @@ fn format_generics(context: &RewriteContext, let mut result = try_opt!(rewrite_generics(context, generics, offset, generics_offset, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { + let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, context.block_indent, + budget, Density::Tall, terminator, Some(span.hi))); diff --git a/tests/source/where-clause.rs b/tests/source/where-clause.rs new file mode 100644 index 00000000000..9e4a2f65698 --- /dev/null +++ b/tests/source/where-clause.rs @@ -0,0 +1,16 @@ +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; + +struct Exactly100CharsToSemicolon + (LongLongTypename, i32, i32) + where A: LongTrait1234; + +struct AlwaysOnNextLine where A: LongTrait { + x: i32 +} diff --git a/tests/target/where-clause.rs b/tests/target/where-clause.rs new file mode 100644 index 00000000000..cf225cab350 --- /dev/null +++ b/tests/target/where-clause.rs @@ -0,0 +1,21 @@ +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType + where F: FnMut(Self::Item) -> bool; + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType + where F: FnMut(Self::Item) -> bool +{ +} + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) + where A: LongTrait; + +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) where A: LongTrait1234; + +struct AlwaysOnNextLine + where A: LongTrait +{ + x: i32, +} -- cgit 1.4.1-3-g733a5 From 17c8fb10ea94ab77784b52096a66670323734b0d Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 27 Nov 2015 23:38:05 +0900 Subject: Remove unused imports --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 4e28fd393f4..8739d234fd2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -20,7 +20,7 @@ // and those with brackets will be formatted as array literals. use syntax::ast; -use syntax::parse::token::{Eof, Comma, Token}; +use syntax::parse::token::Token; use syntax::parse::tts_to_parser; use syntax::codemap::{mk_sp, BytePos}; -- cgit 1.4.1-3-g733a5 From 052fddd4ddd64d3b1a54aa50cb57e95b7d6cbdcc Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 28 Nov 2015 13:59:14 +0100 Subject: Use the BraceStyle config to calculate the width for braces in where clasues --- src/items.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f1be0ed76a1..a3eb7f7a4c9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1471,12 +1471,16 @@ fn rewrite_where_clause(context: &RewriteContext, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); - // When '{' is the terminator just assume that it is put on the next line for single line where - // clauses - let end_length = if terminator == ";" { - 1 + let end_length = if terminator == "{" { + // If the brace is on the next line we don't need to count it otherwise it needs two + // characters " {" + match context.config.item_brace_style { + BraceStyle::AlwaysNextLine => 0, + BraceStyle::PreferSameLine => 2, + BraceStyle::SameLineWhere => 0, + } } else { - 0 + terminator.len() }; if density == Density::Tall || preds_str.contains('\n') || indent.width() + " where ".len() + preds_str.len() + end_length > width { -- cgit 1.4.1-3-g733a5 From 2a430a8947ceebd6a181084969f169490db05dd1 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Mon, 30 Nov 2015 21:51:20 +1300 Subject: Trailing commas for match block arms Attempt to implement an option for trailing commas for block based match arms (issue 173). Put in place test files to verify this behaviour. --- src/config.rs | 2 ++ src/expr.rs | 13 ++++++++----- tests/source/match-block-trailing-comma.rs | 13 +++++++++++++ tests/target/match-block-trailing-comma.rs | 13 +++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 tests/source/match-block-trailing-comma.rs create mode 100644 tests/target/match-block-trailing-comma.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c02d618437f..2ea175c385f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -308,4 +308,6 @@ create_config! { hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; + match_block_trailing_comma: bool, false, + "Put a trailing comma after a block based match arm (non-block arms are not affected)"; } diff --git a/src/expr.rs b/src/expr.rs index 040c83488a7..9338160d98f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -823,7 +823,7 @@ fn rewrite_match(context: &RewriteContext, // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); - result.push_str(arm_comma(&arm.body)); + result.push_str(arm_comma(context, &arm.body)); } } // BytePos(1) = closing match brace. @@ -854,8 +854,10 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { arm.body.span.hi } -fn arm_comma(body: &ast::Expr) -> &'static str { - if let ast::ExprBlock(ref block) = body.node { +fn arm_comma(context: &RewriteContext, body: &ast::Expr) -> &'static str { + if context.config.match_block_trailing_comma { + "," + } else if let ast::ExprBlock(ref block) = body.node { if let ast::DefaultBlock = block.rules { "" } else { @@ -950,7 +952,7 @@ impl Rewrite for ast::Arm { ref x => x, }; - let comma = arm_comma(body); + let comma = arm_comma(context, body); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() @@ -961,7 +963,8 @@ impl Rewrite for ast::Arm { match rewrite { Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || - comma.is_empty() => { + comma.is_empty() || + context.config.match_block_trailing_comma => { return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, diff --git a/tests/source/match-block-trailing-comma.rs b/tests/source/match-block-trailing-comma.rs new file mode 100644 index 00000000000..7f7ddd0a6b4 --- /dev/null +++ b/tests/source/match-block-trailing-comma.rs @@ -0,0 +1,13 @@ +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + } + b => "bar", + } +} diff --git a/tests/target/match-block-trailing-comma.rs b/tests/target/match-block-trailing-comma.rs new file mode 100644 index 00000000000..c845baed376 --- /dev/null +++ b/tests/target/match-block-trailing-comma.rs @@ -0,0 +1,13 @@ +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + }, + b => "bar", + } +} -- cgit 1.4.1-3-g733a5 From 0fb96117868a4ce1e98056b317f76025c3c8db41 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 30 Nov 2015 23:12:50 +0100 Subject: Don't include failed item rewrites in missed spans --- src/visitor.rs | 9 ++++----- tests/source/structs.rs | 2 +- tests/target/fn.rs | 6 ++++++ 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 7b694de4535..295fbef6c07 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -191,6 +191,7 @@ impl<'a> FmtVisitor<'a> { } _ => { if self.visit_attrs(&item.attrs) { + self.push_rewrite(item.span, None); return; } } @@ -377,11 +378,9 @@ impl<'a> FmtVisitor<'a> { fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(span.lo); - - if let Some(res) = rewrite { - self.buffer.push_str(&res); - self.last_pos = span.hi; - } + let result = rewrite.unwrap_or_else(|| self.snippet(span)); + self.buffer.push_str(&result); + self.last_pos = span.hi; } pub fn from_codemap(parse_session: &'a ParseSess, diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 6d7f6213eca..924fbad1961 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -32,7 +32,7 @@ struct Qux<'a, ( AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] + #[AnAttr] // Comment /// Testdoc G, diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 0ae9fd7ef1f..3157c2f9881 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -85,3 +85,9 @@ fn inner() { #![inline] x } + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn foo(a: i32) -> i32 { + // comment + if a > 0 { 1 } else { 2 } +} -- cgit 1.4.1-3-g733a5 From 7ce887abcff3d9254ae7f152f9d8becb42964ff2 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Tue, 1 Dec 2015 20:10:57 +1300 Subject: Update trailing comma match logic, add tests Updates the traling comma code to attempt to handle multiline non-block bodies when adding traling commas to blocks. Also add and update tests to cover better the interactions between trailing commas and wrapping match arms. --- src/expr.rs | 23 +++++++++++++++-------- tests/source/match-block-trailing-comma.rs | 3 ++- tests/source/match-nowrap-trailing-comma.rs | 15 +++++++++++++++ tests/target/match-block-trailing-comma.rs | 5 ++++- tests/target/match-nowrap-trailing-comma.rs | 15 +++++++++++++++ 5 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 tests/source/match-nowrap-trailing-comma.rs create mode 100644 tests/target/match-nowrap-trailing-comma.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9338160d98f..cc518003e88 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,7 @@ use string::{StringFormat, rewrite_string}; use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt}; use visitor::FmtVisitor; -use config::{StructLitStyle, MultilineStyle}; +use config::{Config, StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -823,7 +823,7 @@ fn rewrite_match(context: &RewriteContext, // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); - result.push_str(arm_comma(context, &arm.body)); + result.push_str(arm_comma(&context.config, &arm.body)); } } // BytePos(1) = closing match brace. @@ -854,8 +854,8 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { arm.body.span.hi } -fn arm_comma(context: &RewriteContext, body: &ast::Expr) -> &'static str { - if context.config.match_block_trailing_comma { +fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { + if config.match_block_trailing_comma { "," } else if let ast::ExprBlock(ref block) = body.node { if let ast::DefaultBlock = block.rules { @@ -952,7 +952,7 @@ impl Rewrite for ast::Arm { ref x => x, }; - let comma = arm_comma(context, body); + let comma = arm_comma(&context.config, body); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() @@ -960,11 +960,14 @@ impl Rewrite for ast::Arm { let budget = context.config.max_width - line_start - comma.len() - 4; let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); + let is_body_str_block = match rewrite { + Some(ref s) => s.trim().starts_with("{") && s.trim().ends_with("}"), + None => false, + }; match rewrite { Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || - comma.is_empty() || - context.config.match_block_trailing_comma => { + is_body_str_block => { return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, @@ -986,7 +989,11 @@ impl Rewrite for ast::Arm { body_budget)); let indent_str = offset.block_indent(context.config).to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms { - (" {", "}") + if context.config.match_block_trailing_comma { + (" {", "},") + } else { + (" {", "}") + } } else { ("", "") }; diff --git a/tests/source/match-block-trailing-comma.rs b/tests/source/match-block-trailing-comma.rs index 7f7ddd0a6b4..e9daac13bf9 100644 --- a/tests/source/match-block-trailing-comma.rs +++ b/tests/source/match-block-trailing-comma.rs @@ -8,6 +8,7 @@ fn foo() { "line1"; "line2" } - b => "bar", + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), } } diff --git a/tests/source/match-nowrap-trailing-comma.rs b/tests/source/match-nowrap-trailing-comma.rs new file mode 100644 index 00000000000..f6e88406bb4 --- /dev/null +++ b/tests/source/match-nowrap-trailing-comma.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_match_arms: false +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + } + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/tests/target/match-block-trailing-comma.rs b/tests/target/match-block-trailing-comma.rs index c845baed376..b00def007e8 100644 --- a/tests/target/match-block-trailing-comma.rs +++ b/tests/target/match-block-trailing-comma.rs @@ -8,6 +8,9 @@ fn foo() { "line1"; "line2" }, - b => "bar", + b => { + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) + }, } } diff --git a/tests/target/match-nowrap-trailing-comma.rs b/tests/target/match-nowrap-trailing-comma.rs new file mode 100644 index 00000000000..6b2e430123d --- /dev/null +++ b/tests/target/match-nowrap-trailing-comma.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_match_arms: false +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + }, + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} -- cgit 1.4.1-3-g733a5 From 17fd2d073bf9c1a5e59b68c2f412f24456c9a39c Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 1 Dec 2015 19:51:49 +0100 Subject: Add a BraceStyle parameter to rewrite_where_clause This allow it to exactly calculate if it needs to break the where clause into multiple lines --- src/items.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a3eb7f7a4c9..3088c21ad09 100644 --- a/src/items.rs +++ b/src/items.rs @@ -480,6 +480,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, + context.config.item_brace_style, context.block_indent, where_budget, context.config.where_density, @@ -695,6 +696,7 @@ fn format_tuple_struct(context: &RewriteContext, let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, + context.config.item_brace_style, context.block_indent, where_budget, Density::Compressed, @@ -1178,6 +1180,7 @@ fn rewrite_fn_base(context: &RewriteContext, let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, context.config, + context.config.fn_brace_style, indent, where_budget, where_density, @@ -1416,6 +1419,7 @@ fn rewrite_generics(context: &RewriteContext, fn rewrite_where_clause(context: &RewriteContext, where_clause: &ast::WhereClause, config: &Config, + brace_style: BraceStyle, indent: Indent, width: usize, density: Density, @@ -1474,7 +1478,7 @@ fn rewrite_where_clause(context: &RewriteContext, let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two // characters " {" - match context.config.item_brace_style { + match brace_style { BraceStyle::AlwaysNextLine => 0, BraceStyle::PreferSameLine => 2, BraceStyle::SameLineWhere => 0, @@ -1513,6 +1517,7 @@ fn format_generics(context: &RewriteContext, let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, + brace_style, context.block_indent, budget, Density::Tall, -- cgit 1.4.1-3-g733a5 From 76f303f369d38878c6f9f5321c2db0e41b97d96b Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 1 Dec 2015 22:09:37 +0100 Subject: Break function headers earlier Closes rustfmt#295. --- src/items.rs | 55 ++++++++++++++++++++--------------------------- tests/source/fn-simple.rs | 2 ++ tests/target/fn-simple.rs | 8 +++++++ 3 files changed, 33 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0f5fa1b655f..e655d99cf20 100644 --- a/src/items.rs +++ b/src/items.rs @@ -221,25 +221,23 @@ impl<'a> FmtVisitor<'a> { sig: &ast::MethodSig, span: Span) -> Option { - // Drop semicolon or it will be interpreted as comment + // Drop semicolon or it will be interpreted as comment. let span = mk_sp(span.lo, span.hi - BytePos(1)); let context = self.get_context(); - // FIXME: silly formatting of the `.0`. - let mut result = try_opt!(rewrite_fn_base(&context, - indent, - ident, - &sig.decl, - Some(&sig.explicit_self), - &sig.generics, - sig.unsafety, - sig.constness, - sig.abi, - ast::Visibility::Inherited, - span, - false, - false)) - .0; + let (mut result, _) = try_opt!(rewrite_fn_base(&context, + indent, + ident, + &sig.decl, + Some(&sig.explicit_self), + &sig.generics, + sig.unsafety, + sig.constness, + sig.abi, + ast::Visibility::Inherited, + span, + false, + false)); // Re-attach semicolon result.push(';'); @@ -1050,7 +1048,7 @@ fn rewrite_fn_base(context: &RewriteContext, arg_indent); // Check if vertical layout was forced by compute_budget_for_args. - if one_line_budget <= 0 { + if one_line_budget == 0 { if context.config.fn_args_paren_newline { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); @@ -1305,28 +1303,21 @@ fn compute_budgets_for_args(context: &RewriteContext, ret_str_len: usize, newline_brace: bool) -> (usize, usize, Indent) { - // Try keeping everything on the same line + // Try keeping everything on the same line. if !result.contains("\n") { - // 3 = `() `, space is before ret_string + // 3 = `() `, space is before ret_string. let mut used_space = indent.width() + result.len() + ret_str_len + 3; if !newline_brace { used_space += 2; } - let one_line_budget = if used_space > context.config.max_width { - 0 - } else { - context.config.max_width - used_space - }; + let one_line_budget = context.config.max_width.checked_sub(used_space).unwrap_or(0); + + if one_line_budget > 0 { + let multi_line_budget = context.config.max_width - + (indent.width() + result.len() + "()".len()); - // 2 = `()` - let used_space = indent.width() + result.len() + 2; - let max_space = context.config.max_width; - debug!("compute_budgets_for_args: used_space: {}, max_space: {}", - used_space, - max_space); - if used_space < max_space { return (one_line_budget, - max_space - used_space, + multi_line_budget, indent + result.len() + 1); } } diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 93c43224417..044d494bd37 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -41,3 +41,5 @@ unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, -> u8) { let f: fn ( _ , _ ) -> _ = panic!() ; } + +pub fn start_export_thread(database: &Database, crypto_scheme: &C, block_size: usize, source_path: &Path) -> BonzoResult> {} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index e5de6b0f00d..17a3ac0fe15 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -64,3 +64,11 @@ unsafe fn generic_call(cx: *mut JSContext, -> u8) { let f: fn(_, _) -> _ = panic!(); } + +pub fn start_export_thread + (database: &Database, + crypto_scheme: &C, + block_size: usize, + source_path: &Path) + -> BonzoResult> { +} -- cgit 1.4.1-3-g733a5 From 74d40c042f9f2d6d39881465aca91a4daf1ea7a9 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Wed, 2 Dec 2015 16:44:40 +1300 Subject: Update block checking code --- src/expr.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index cc518003e88..78c3a82e223 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -960,14 +960,15 @@ impl Rewrite for ast::Arm { let budget = context.config.max_width - line_start - comma.len() - 4; let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); - let is_body_str_block = match rewrite { - Some(ref s) => s.trim().starts_with("{") && s.trim().ends_with("}"), - None => false, + let is_block = if let ast::ExprBlock(ref block) = body.node { + true + } else { + false }; match rewrite { Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || - is_body_str_block => { + is_block => { return Some(format!("{}{} => {}{}", attr_str.trim_left(), pats_str, -- cgit 1.4.1-3-g733a5 From ae9ad7b2884a5775c94d3a9e1295110f989b6417 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Wed, 2 Dec 2015 19:38:05 +0100 Subject: Fix formatting of type aliases where '=' is at or close to the max width --- src/items.rs | 26 +++++++++++++++++++++----- tests/source/type_alias.rs | 4 ++++ tests/target/type_alias.rs | 13 +++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3088c21ad09..d4ed6ad670e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -455,6 +455,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let generics_str = try_opt!(rewrite_generics(context, generics, offset, + context.config.max_width, offset + result.len(), mk_sp(lo, hi))); result.push_str(&generics_str); @@ -686,6 +687,7 @@ fn format_tuple_struct(context: &RewriteContext, let generics_str = try_opt!(rewrite_generics(context, generics, offset, + context.config.max_width, offset + header_str.len(), mk_sp(span.lo, body_lo))); result.push_str(&generics_str); @@ -763,9 +765,11 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(span_after(span, "type", context.codemap), ty.span.lo); + let generics_width = context.config.max_width - " =".len(); let generics_str = try_opt!(rewrite_generics(context, generics, indent, + generics_width, generics_indent, generics_span)); @@ -773,9 +777,12 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(" = "); let line_width = last_line_width(&result); - let budget = try_opt!(context.config - .max_width - .checked_sub(indent.width() + line_width + ";".len())); + // This checked_sub may fail as the extra space after '=' is not taken into account + // In that case the budget is set to 0 which will make ty.rewrite retry on a new line + let budget = context.config + .max_width + .checked_sub(indent.width() + line_width + ";".len()) + .unwrap_or(0); let type_indent = indent + line_width; // Try to fit the type on the same line let ty_str = try_opt!(ty.rewrite(context, budget, type_indent) @@ -1031,6 +1038,7 @@ fn rewrite_fn_base(context: &RewriteContext, let generics_str = try_opt!(rewrite_generics(context, generics, indent, + context.config.max_width, generics_indent, generics_span)); result.push_str(&generics_str); @@ -1366,6 +1374,7 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { fn rewrite_generics(context: &RewriteContext, generics: &ast::Generics, offset: Indent, + width: usize, generics_offset: Indent, span: Span) -> Option { @@ -1384,7 +1393,7 @@ fn rewrite_generics(context: &RewriteContext, BlockIndentStyle::Visual => generics_offset + 1, }; - let h_budget = context.config.max_width - generics_offset.width() - 2; + let h_budget = try_opt!(width.checked_sub(generics_offset.width() + 2)); // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. @@ -1483,6 +1492,8 @@ fn rewrite_where_clause(context: &RewriteContext, BraceStyle::PreferSameLine => 2, BraceStyle::SameLineWhere => 0, } + } else if terminator == "=" { + 2 } else { terminator.len() }; @@ -1510,7 +1521,12 @@ fn format_generics(context: &RewriteContext, generics_offset: Indent, span: Span) -> Option { - let mut result = try_opt!(rewrite_generics(context, generics, offset, generics_offset, span)); + let mut result = try_opt!(rewrite_generics(context, + generics, + offset, + context.config.max_width, + generics_offset, + span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs index 3f8a6ccfe3e..d69375144e7 100644 --- a/tests/source/type_alias.rs +++ b/tests/source/type_alias.rs @@ -9,6 +9,10 @@ pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAM pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; +pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; + +pub type GenericsFitButNotEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A1, B, C> = Vec; + pub type CommentTest< /* Lifetime */ 'a , // Type diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index a468f7920e3..d2d6bf4404d 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -22,6 +22,19 @@ pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAM pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; +pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = + Vec; + +pub type GenericsFitButNotEqualTest<'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A1, + B, + C> = Vec; + pub type CommentTest = (); -- cgit 1.4.1-3-g733a5 From a6b0d475f4c7c52c097dd62b48395798b38ef4cd Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Wed, 2 Dec 2015 19:39:45 +0100 Subject: Don't remove where clauses in type aliases --- src/items.rs | 14 ++++++++++++++ tests/source/type_alias.rs | 7 +++++++ tests/target/type_alias.rs | 11 +++++++++++ 3 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d4ed6ad670e..6af01bd1af1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -774,6 +774,20 @@ pub fn rewrite_type_alias(context: &RewriteContext, generics_span)); result.push_str(&generics_str); + + let where_budget = try_opt!(context.config + .max_width + .checked_sub(last_line_width(&result))); + let where_clause_str = try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.config.item_brace_style, + indent, + where_budget, + context.config.where_density, + "=", + Some(span.hi))); + result.push_str(&where_clause_str); result.push_str(" = "); let line_width = last_line_width(&result); diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs index d69375144e7..e4429bb8ddf 100644 --- a/tests/source/type_alias.rs +++ b/tests/source/type_alias.rs @@ -18,3 +18,10 @@ pub type CommentTest< /* Lifetime */ 'a // Type T > = (); + + +pub type WithWhereClause where T: Clone, LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; + +pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index d2d6bf4404d..d175aa60a67 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -38,3 +38,14 @@ pub type GenericsFitButNotEqualTest<'a, pub type CommentTest = (); + + +pub type WithWhereClause + where T: Clone, + LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; + +pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = + Option; + +pub type Exactly101CharstoEqualWhereTest + where T: Clone + Ord + Eq + SomeOtherTrait = Option; -- cgit 1.4.1-3-g733a5 From f61ba91c2da589553ef3207134955768c26c00b3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 4 Dec 2015 18:02:19 +0530 Subject: Minor clippy fixes --- src/bin/rustfmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 04251d09c74..f3ffccfbf7b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -176,7 +176,7 @@ fn determine_operation(matches: &Matches) -> Operation { } // if no file argument is supplied, read from stdin - if matches.free.len() == 0 { + if matches.free.is_empty() { let mut buffer = String::new(); match io::stdin().read_to_string(&mut buffer) { @@ -198,7 +198,7 @@ fn determine_operation(matches: &Matches) -> Operation { None => WriteMode::Replace, }; - let files: Vec<_> = matches.free.iter().map(|a| PathBuf::from(a)).collect(); + let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); Operation::Format(files, write_mode) } -- cgit 1.4.1-3-g733a5 From 1ed36a3a6bfb4b66cf29ad41e472657148452b79 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 4 Dec 2015 16:10:14 +0100 Subject: Use starts_with to avoid panics. --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 7b694de4535..ef422ca5924 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -69,7 +69,7 @@ impl<'a> FmtVisitor<'a> { // Check if this block has braces. let snippet = self.snippet(b.span); - let has_braces = &snippet[..1] == "{" || &snippet[..6] == "unsafe"; + let has_braces = snippet.starts_with("{") || snippet.starts_with("unsafe"); let brace_compensation = if has_braces { BytePos(1) } else { -- cgit 1.4.1-3-g733a5 From 97e4e7e5ba2010fe98c1775e96c6444a68e3cb80 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 6 Dec 2015 01:11:26 +0100 Subject: Fixed named arguments in bare function types --- src/expr.rs | 26 +++++++++++++++++--------- src/items.rs | 2 +- src/lib.rs | 12 +++++++++++- src/patterns.rs | 8 +++++++- src/types.rs | 23 +++++++++++++++++------ tests/source/structs.rs | 6 ++++++ tests/target/structs.rs | 5 +++++ 7 files changed, 64 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 78c3a82e223..350b9c53a25 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -11,6 +11,8 @@ use std::cmp::Ordering; use std::borrow::Borrow; use std::mem::swap; +use std::ops::Deref; +use std::iter::ExactSizeIterator; use {Indent, Spanned}; use rewrite::{Rewrite, RewriteContext}; @@ -75,7 +77,11 @@ impl Rewrite for ast::Expr { offset) } ast::Expr_::ExprTup(ref items) => { - rewrite_tuple(context, items, self.span, width, offset) + rewrite_tuple(context, + items.iter().map(|x| &**x), + self.span, + width, + offset) } ast::Expr_::ExprWhile(ref cond, ref block, label) => { Loop::new_while(None, cond, block, label).rewrite(context, width, offset) @@ -960,7 +966,7 @@ impl Rewrite for ast::Arm { let budget = context.config.max_width - line_start - comma.len() - 4; let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); - let is_block = if let ast::ExprBlock(ref block) = body.node { + let is_block = if let ast::ExprBlock(..) = body.node { true } else { false @@ -1431,25 +1437,27 @@ fn rewrite_field(context: &RewriteContext, expr.map(|s| format!("{}: {}", name, s)) } -pub fn rewrite_tuple<'a, R>(context: &RewriteContext, - items: &'a [ptr::P], +pub fn rewrite_tuple<'a, I>(context: &RewriteContext, + mut items: I, span: Span, width: usize, offset: Indent) -> Option - where R: Rewrite + Spanned + 'a + where I: ExactSizeIterator, + ::Item: Deref, + ::Target: Rewrite + Spanned + 'a { - debug!("rewrite_tuple_lit: width: {}, offset: {:?}", width, offset); let indent = offset + 1; // In case of length 1, need a trailing comma if items.len() == 1 { // 3 = "(" + ",)" let budget = try_opt!(width.checked_sub(3)); - return items[0].rewrite(context, budget, indent).map(|s| format!("({},)", s)); + return items.next().unwrap().rewrite(context, budget, indent).map(|s| format!("({},)", s)); } + let list_lo = span_after(span, "(", context.codemap); let items = itemize_list(context.codemap, - items.iter(), + items, ")", |item| item.span().lo, |item| item.span().hi, @@ -1460,7 +1468,7 @@ pub fn rewrite_tuple<'a, R>(context: &RewriteContext, 1)); item.rewrite(context, inner_width, indent) }, - span.lo + BytePos(1), // Remove parens + list_lo, span.hi - BytePos(1)); let budget = try_opt!(width.checked_sub(2)); let list_str = try_opt!(format_fn_args(items, budget, indent, context.config)); diff --git a/src/items.rs b/src/items.rs index 6af01bd1af1..3e08abd461a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -968,7 +968,7 @@ pub fn span_hi_for_arg(arg: &ast::Arg) -> BytePos { } } -fn is_named_arg(arg: &ast::Arg) -> bool { +pub fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::Pat_::PatIdent(_, ident, _) = arg.pat.node { ident.node != token::special_idents::invalid } else { diff --git a/src/lib.rs b/src/lib.rs index ad3e3b27e2e..86ab1a73022 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,7 +26,7 @@ extern crate diff; extern crate term; use syntax::ast; -use syntax::codemap::Span; +use syntax::codemap::{mk_sp, Span}; use syntax::diagnostic::{EmitterWriter, Handler}; use syntax::parse::{self, ParseSess}; @@ -88,6 +88,16 @@ impl Spanned for ast::Ty { } } +impl Spanned for ast::Arg { + fn span(&self) -> Span { + if items::is_named_arg(self) { + mk_sp(self.pat.span.lo, self.ty.span.hi) + } else { + self.ty.span + } + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of diff --git a/src/patterns.rs b/src/patterns.rs index af0bd827751..fdc418733fb 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -48,7 +48,13 @@ impl Rewrite for Pat { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, width, offset) } - Pat_::PatTup(ref items) => rewrite_tuple(context, items, self.span, width, offset), + Pat_::PatTup(ref items) => { + rewrite_tuple(context, + items.iter().map(|x| &**x), + self.span, + width, + offset) + } Pat_::PatEnum(ref path, Some(ref pat_vec)) => { let path_str = try_opt!(::types::rewrite_path(context, true, diff --git a/src/types.rs b/src/types.rs index c483032b451..1d9522d0f90 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ops::Deref; +use std::iter::ExactSizeIterator; + use syntax::ast::{self, Mutability, FunctionRetTy}; use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos}; use syntax::abi; -use Indent; +use {Indent, Spanned}; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; @@ -239,7 +242,9 @@ fn format_function_type<'a, I>(inputs: I, width: usize, offset: Indent) -> Option - where I: Iterator + where I: ExactSizeIterator, + ::Item: Deref, + ::Target: Rewrite + Spanned + 'a { // 2 for () let budget = try_opt!(width.checked_sub(2)); @@ -249,8 +254,8 @@ fn format_function_type<'a, I>(inputs: I, let items = itemize_list(context.codemap, inputs, ")", - |ty| ty.span.lo, - |ty| ty.span.hi, + |ty| ty.span().lo, + |ty| ty.span().hi, |ty| ty.rewrite(context, budget, offset), list_lo, span.hi); @@ -506,7 +511,13 @@ impl Rewrite for ast::Ty { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str)) } - ast::TyTup(ref items) => rewrite_tuple(context, items, self.span, width, offset), + ast::TyTup(ref items) => { + rewrite_tuple(context, + items.iter().map(|x| &**x), + self.span, + width, + offset) + } ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), ast::TyPath(ref q_self, ref path) => { rewrite_path(context, false, q_self.as_ref(), path, width, offset) @@ -548,7 +559,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, let budget = try_opt!(width.checked_sub(result.len())); let indent = offset + result.len(); - let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter().map(|x| &*(x.ty)), + let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(), &bare_fn.decl.output, span, context, diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 6d7f6213eca..d87d90db111 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -145,3 +145,9 @@ mod m { struct Foo(TTTTTTTTTTTTTTTTTTT, /// Qux UUUUUUUUUUUUUUUUUUU); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 9e17dec1411..adaa626c096 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -153,3 +153,8 @@ mod m { struct Foo(TTTTTTTTTTTTTTTTTTT, /// Qux UUUUUUUUUUUUUUUUUUU); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} -- cgit 1.4.1-3-g733a5 From e94bd34a06d878a41bb8be409f173a8824dda63f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 8 Dec 2015 16:19:23 +1300 Subject: cargo upgrade, bug fix, and prepare for packaging --- Cargo.lock | 43 +++++++++++++++++++------------------------ Cargo.toml | 9 ++++----- src/visitor.rs | 3 ++- 3 files changed, 25 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 87e4c64ce2c..ea9f07ad1ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,23 +1,23 @@ [root] name = "rustfmt" -version = "0.0.1" +version = "0.0.2" dependencies = [ "diff 0.1.7 (git+https://github.com/utkarshkukreti/diff.rs.git)", "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)", - "syntex_syntax 0.22.0 (git+https://github.com/serde-rs/syntex)", - "term 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.23.0 (git+https://github.com/serde-rs/syntex)", + "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.3.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -31,15 +31,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "diff" version = "0.1.7" -source = "git+https://github.com/utkarshkukreti/diff.rs.git#6edb9454bf4127087aced0fe07ab3ea6894083cb" +source = "git+https://github.com/utkarshkukreti/diff.rs.git#05c701a379f7eaa9b386af79f0a17b87d814f9bd" [[package]] name = "env_logger" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -56,11 +56,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "libc" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libc" version = "0.2.2" @@ -68,10 +63,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -84,10 +79,10 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.41" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -107,25 +102,25 @@ name = "strings" version = "0.0.1" source = "git+https://github.com/nrc/strings.rs.git#d33d75a7c22522c76f2306b16b238e363de45af4" dependencies = [ - "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.22.0" -source = "git+https://github.com/serde-rs/syntex#7913a15053ef5f2526aeff8b318f49d010582efd" +version = "0.23.0" +source = "git+https://github.com/serde-rs/syntex#f1e67d25ae320d6c7707bf0aef1ac072f63cf9c4" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index ebd4e8e7f1e..4a976cbe997 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "rustfmt" -version = "0.0.1" -authors = ["Nicholas Cameron "] +version = "0.0.2" +authors = ["Nicholas Cameron ", "Marcus Klaas ", "The Rustfmt contributors"] description = "Tool to find and fix Rust formatting issues" -repository = "https://github.com/nick29581/rustfmt" +repository = "https://github.com/rust-lang-nursery/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" +include = ["src/*.rs", "Cargo.toml"] [dependencies] toml = "0.1.20" @@ -20,5 +21,3 @@ syntex_syntax = { git = "https://github.com/serde-rs/syntex" } log = "0.3.2" env_logger = "0.3.1" getopts = "0.2" - -[dev-dependencies] diff --git a/src/visitor.rs b/src/visitor.rs index 012760ec9fb..8a0e1c9b847 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -55,7 +55,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(stmt.span, rewrite); } - ast::Stmt_::StmtMac(ref mac, _macro_style) => { + ast::Stmt_::StmtMac(ref mac, _macro_style, _) => { self.format_missing_with_indent(stmt.span.lo); self.visit_mac(mac); } @@ -360,6 +360,7 @@ impl<'a> FmtVisitor<'a> { // FIXME: Implement } ast::ImplItemKind::Macro(ref mac) => { + self.format_missing_with_indent(ii.span.lo); self.visit_mac(mac); } } -- cgit 1.4.1-3-g733a5 From f8cb1baadd0c5ebd621b79c45eafb99eeba1b4b7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 8 Dec 2015 17:04:40 +1300 Subject: Add normalise_comments option. So block comments are not converted to line comments --- src/comment.rs | 41 +++++++++++++++++++++++++++++++---------- src/config.rs | 1 + src/visitor.rs | 2 ++ tests/source/comment.rs | 6 ++++++ tests/source/comment4.rs | 35 +++++++++++++++++++++++++++++++++++ tests/target/comment.rs | 5 +++++ tests/target/comment4.rs | 34 ++++++++++++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 tests/source/comment4.rs create mode 100644 tests/target/comment4.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index cb3b4b5f4d7..c111259979c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -27,9 +27,23 @@ pub fn rewrite_comment(orig: &str, // Edge case: block comments. Let's not trim their lines (for now). let (opener, closer, line_start) = if block_style { ("/* ", " */", " * ") - } else if orig.starts_with("///") { + } else if !config.normalise_comments { + if orig.starts_with("/**") { + ("/** ", " **/", " ** ") + } else if orig.starts_with("/*!") { + ("/*! ", " */", " * ") + } else if orig.starts_with("/*") { + ("/* ", " */", " * ") + } else if orig.starts_with("///") { + ("/// ", "", "/// ") + } else if orig.starts_with("//!") { + ("//! ", "", "//! ") + } else { + ("// ", "", "// ") + } + } else if orig.starts_with("///") || orig.starts_with("/**") { ("/// ", "", "/// ") - } else if orig.starts_with("//!") { + } else if orig.starts_with("//!") || orig.starts_with("/*!") { ("//! ", "", "//! ") } else { ("// ", "", "// ") @@ -72,10 +86,12 @@ pub fn rewrite_comment(orig: &str, }); let mut result = opener.to_owned(); - let mut first = true; - for line in lines { - if !first { + if result == opener { + if line.len() == 0 { + continue; + } + } else { result.push('\n'); result.push_str(&indent_str); result.push_str(line_start); @@ -91,22 +107,27 @@ pub fn rewrite_comment(orig: &str, } result.push_str(line); } - - first = false; } result.push_str(closer); + if result == opener { + // Trailing space. + result.pop(); + } Some(result) } fn left_trim_comment_line(line: &str) -> &str { - if line.starts_with("//! ") || line.starts_with("/// ") { + if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || + line.starts_with("/** ") { &line[4..] } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || - line.starts_with("///") { + line.starts_with("///") || line.starts_with("** ") || line.starts_with("/*!") || + line.starts_with("/**") { &line[3..] - } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") { + } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || + line.starts_with("**") { &line[2..] } else if line.starts_with("*") { &line[1..] diff --git a/src/config.rs b/src/config.rs index 2ea175c385f..4c919191dbd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -307,6 +307,7 @@ create_config! { take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; + normalise_comments: bool, true, "Convert /* */ comments to // comments where possible"; wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; diff --git a/src/visitor.rs b/src/visitor.rs index 8a0e1c9b847..f0efde9de64 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -530,6 +530,7 @@ impl<'a> Rewrite for [ast::Attribute] { for (i, a) in self.iter().enumerate() { let a_str = context.snippet(a.span); + // Write comments and blank lines between attributes. if i > 0 { let comment = context.snippet(codemap::mk_sp(self[i - 1].span.hi, a.span.lo)); // This particular horror show is to preserve line breaks in between doc @@ -553,6 +554,7 @@ impl<'a> Rewrite for [ast::Attribute] { result.push_str(&indent); } + // Write the attribute itself. result.push_str(&a_str); if i < self.len() - 1 { diff --git a/tests/source/comment.rs b/tests/source/comment.rs index 8de3c2ed1cd..714b77b081c 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -2,6 +2,9 @@ //! Doc comment fn test() { + /*! + * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam */ + // comment // comment2 @@ -39,3 +42,6 @@ fn chains() { let x = 10; /* comment */ x }) } + +/* + * random comment */ diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs new file mode 100644 index 00000000000..7fef084fc7b --- /dev/null +++ b/tests/source/comment4.rs @@ -0,0 +1,35 @@ +// rustfmt-normalise_comments: false + +//! Doc comment +fn test() { +// comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + + /// test123 +fn doc_comment() { +} diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 2d90d83edb6..28740749c5d 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -2,6 +2,9 @@ //! Doc comment fn test() { + //! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam + //! lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + // comment // comment2 @@ -41,3 +44,5 @@ fn chains() { x }) } + +// random comment diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs new file mode 100644 index 00000000000..85edc7f06d4 --- /dev/null +++ b/tests/target/comment4.rs @@ -0,0 +1,34 @@ +// rustfmt-normalise_comments: false + +//! Doc comment +fn test() { + // comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + +/// test123 +fn doc_comment() {} -- cgit 1.4.1-3-g733a5 From 2636fed5f3ca01d0b5cf3637d635e4727ae24199 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 12 Dec 2015 15:41:10 +0100 Subject: Don't panic on function return type rewrite failure --- src/items.rs | 10 ++++------ tests/target/fn.rs | 8 ++++++++ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0229a1321fb..197f5403e7c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1057,9 +1057,8 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that if the width and indent really matter, we'll re-layout the // return type later anyway. - let ret_str = fd.output - .rewrite(&context, context.config.max_width - indent.width(), indent) - .unwrap(); + let ret_str = try_opt!(fd.output + .rewrite(&context, context.config.max_width - indent.width(), indent)); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { @@ -1158,9 +1157,8 @@ fn rewrite_fn_base(context: &RewriteContext, // re-layout the return type. let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); - let ret_str = fd.output - .rewrite(context, budget, ret_indent) - .unwrap(); + let ret_str = try_opt!(fd.output + .rewrite(context, budget, ret_indent)); result.push_str(&ret_str); } else { result.push_str(&ret_str); diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 3157c2f9881..eb4c3e1c8c1 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -91,3 +91,11 @@ fn foo(a: i32) -> i32 { // comment if a > 0 { 1 } else { 2 } } + +fn ______________________baz(a: i32) + -> + *mut ::std::option::Option ()> { +} -- cgit 1.4.1-3-g733a5 From 8cccf45d4339180b5788e7cb180917d7d1793501 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 12 Dec 2015 16:20:53 +0100 Subject: Prevent backslash stripping in string literals --- src/string.rs | 7 +++---- tests/source/string-lit.rs | 5 +++++ tests/target/string-lit.rs | 5 +++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 221b56aa4cb..47ba79d927b 100644 --- a/src/string.rs +++ b/src/string.rs @@ -30,11 +30,10 @@ pub struct StringFormat<'a> { pub config: &'a Config, } -// TODO: simplify this! +// FIXME: simplify this! pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { - // TODO if lo.col > IDEAL - 10, start a new line (need cur indent for that) // Strip line breaks. - let re = Regex::new(r"(\\[:space:]+)").unwrap(); + let re = Regex::new(r"(\\[\n\r][:space:]*)").unwrap(); let stripped_str = re.replace_all(s, ""); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); @@ -87,7 +86,7 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { let line = if fmt.trim_end { raw_line.trim() } else { - // TODO: use as_str once it's stable. + // FIXME: use as_str once it's stable. &*raw_line }; diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index 9ea2aad3c5c..c0bbee4f617 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -34,3 +34,8 @@ formatting"#; "stuffin'" } + +fn issue682() { + let a = "hello \\ o/"; + let b = a.replace("\\ ", "\\"); +} diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index e83c905ae63..0b5b5105b9b 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -40,3 +40,8 @@ formatting"#; "stuffin'" } + +fn issue682() { + let a = "hello \\ o/"; + let b = a.replace("\\ ", "\\"); +} -- cgit 1.4.1-3-g733a5 From 623277e7e0583ad413a7fa0c886c65ebb5b4adc9 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Mon, 14 Dec 2015 15:50:19 +0100 Subject: Add cargo-fmt binary Add a new utility, which formats all readable .rs files in the src directory of the crate using rustfmt. Both binaries can be installed using cargo install rustfmt. cargo-fmt can be used as a Cargo subcommand - cargo fmt. --- src/bin/cargo-fmt.rs | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/bin/cargo-fmt.rs (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs new file mode 100644 index 00000000000..9c7d8370548 --- /dev/null +++ b/src/bin/cargo-fmt.rs @@ -0,0 +1,116 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) + +#![cfg(not(test))] +#![cfg(feature="cargo-fmt")] + +extern crate getopts; +extern crate walkdir; +extern crate rustc_serialize; + +use std::path::PathBuf; +use std::process::Command; +use std::env; +use std::str; + +use getopts::Options; +use walkdir::{WalkDir, DirEntry}; +use rustc_serialize::json::Json; + +fn main() { + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + + let matches = match opts.parse(env::args().skip(1)) { + Ok(m) => m, + Err(e) => { + print_usage(&opts, &e.to_string()); + return; + } + }; + + if matches.opt_present("h") { + print_usage(&opts, ""); + } else { + format_crate(&opts); + } +} + +fn print_usage(opts: &Options, reason: &str) { + let msg = format!("{}\nusage: cargo fmt [options]", reason); + println!("{}\nThis utility formats all readable .rs files in the src directory of the \ + current crate using rustfmt.", + opts.usage(&msg)); +} + +fn format_crate(opts: &Options) { + let mut root = match locate_root() { + Ok(r) => r, + Err(e) => { + print_usage(opts, &e.to_string()); + return; + } + }; + + // Currently only files in [root]/src can be formatted + root.push("src"); + // All unreadable or non .rs files are skipped + let files: Vec<_> = WalkDir::new(root) + .into_iter() + .filter(is_rs_file) + .filter_map(|f| f.ok()) + .map(|e| e.path().to_owned()) + .collect(); + + format_files(&files).unwrap_or_else(|e| print_usage(opts, &e.to_string())); +} + +fn locate_root() -> Result { + // This seems adequate, as cargo-fmt can only be used systems that have Cargo installed + let output = try!(Command::new("cargo").arg("locate-project").output()); + if output.status.success() { + // We assume cargo locate-project is not broken and + // it will output a valid json document + let data = &String::from_utf8(output.stdout).unwrap(); + let json = Json::from_str(data).unwrap(); + let root = PathBuf::from(json.find("root").unwrap().as_string().unwrap()); + + // root.parent() should never fail if locate-project's output is correct + Ok(root.parent().unwrap().to_owned()) + } else { + // This happens when cargo-fmt is not used inside a crate + Err(std::io::Error::new(std::io::ErrorKind::NotFound, + str::from_utf8(&output.stderr).unwrap())) + } +} + +fn is_rs_file(entry: &Result) -> bool { + match *entry { + Ok(ref file) => { + match file.path().extension() { + Some(ext) => ext == "rs", + None => false, + } + } + Err(_) => false, + } +} + +fn format_files(files: &Vec) -> Result<(), std::io::Error> { + let mut command = try!(Command::new("rustfmt") + .arg("--write-mode=overwrite") + .args(files) + .spawn()); + try!(command.wait()); + + Ok(()) +} -- cgit 1.4.1-3-g733a5 From 360f3efce8743d1eee6395881591cec52edb6934 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Wed, 16 Dec 2015 02:21:43 +0100 Subject: Replace `locate-project` with `read-manifest` Use `cargo read-manifest` instead of `cargo locate-project` to get a list of files to be formatted. --- Cargo.lock | 10 ------ src/bin/cargo-fmt.rs | 92 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 73a16a22419..14afd091248 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,7 +13,6 @@ dependencies = [ "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -146,15 +145,6 @@ name = "unicode-xid" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "walkdir" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "winapi" version = "0.2.5" diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 9c7d8370548..af6c6b059a0 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -14,7 +14,6 @@ #![cfg(feature="cargo-fmt")] extern crate getopts; -extern crate walkdir; extern crate rustc_serialize; use std::path::PathBuf; @@ -23,7 +22,6 @@ use std::env; use std::str; use getopts::Options; -use walkdir::{WalkDir, DirEntry}; use rustc_serialize::json::Json; fn main() { @@ -47,45 +45,71 @@ fn main() { fn print_usage(opts: &Options, reason: &str) { let msg = format!("{}\nusage: cargo fmt [options]", reason); - println!("{}\nThis utility formats all readable .rs files in the src directory of the \ - current crate using rustfmt.", + println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt.", opts.usage(&msg)); } fn format_crate(opts: &Options) { - let mut root = match locate_root() { - Ok(r) => r, + let targets = match get_targets() { + Ok(t) => t, Err(e) => { print_usage(opts, &e.to_string()); return; } }; - // Currently only files in [root]/src can be formatted - root.push("src"); - // All unreadable or non .rs files are skipped - let files: Vec<_> = WalkDir::new(root) - .into_iter() - .filter(is_rs_file) - .filter_map(|f| f.ok()) - .map(|e| e.path().to_owned()) - .collect(); + // Currently only bin and lib files get formatted + let files: Vec<_> = targets.into_iter() + .filter(|t| t.kind.is_lib() | t.kind.is_bin()) + .map(|t| t.path) + .collect(); format_files(&files).unwrap_or_else(|e| print_usage(opts, &e.to_string())); } -fn locate_root() -> Result { - // This seems adequate, as cargo-fmt can only be used systems that have Cargo installed - let output = try!(Command::new("cargo").arg("locate-project").output()); +#[derive(Debug)] +enum TargetKind { + Lib, // dylib, staticlib, lib + Bin, // bin + Other, // test, plugin,... +} + +impl TargetKind { + fn is_lib(&self) -> bool { + match self { + &TargetKind::Lib => true, + _ => false, + } + } + + fn is_bin(&self) -> bool { + match self { + &TargetKind::Bin => true, + _ => false, + } + } +} + +#[derive(Debug)] +struct Target { + path: PathBuf, + kind: TargetKind, +} + +// Returns a vector of all compile targets of a crate +fn get_targets() -> Result, std::io::Error> { + let mut targets: Vec = vec![]; + let output = try!(Command::new("cargo").arg("read-manifest").output()); if output.status.success() { - // We assume cargo locate-project is not broken and - // it will output a valid json document + // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); let json = Json::from_str(data).unwrap(); - let root = PathBuf::from(json.find("root").unwrap().as_string().unwrap()); + let jtargets = json.find("targets").unwrap().as_array().unwrap(); + for jtarget in jtargets { + targets.push(target_from_json(jtarget)); + } - // root.parent() should never fail if locate-project's output is correct - Ok(root.parent().unwrap().to_owned()) + Ok(targets) } else { // This happens when cargo-fmt is not used inside a crate Err(std::io::Error::new(std::io::ErrorKind::NotFound, @@ -93,15 +117,19 @@ fn locate_root() -> Result { } } -fn is_rs_file(entry: &Result) -> bool { - match *entry { - Ok(ref file) => { - match file.path().extension() { - Some(ext) => ext == "rs", - None => false, - } - } - Err(_) => false, +fn target_from_json(jtarget: &Json) -> Target { + let jtarget = jtarget.as_object().unwrap(); + let path = PathBuf::from(jtarget.get("src_path").unwrap().as_string().unwrap()); + let kinds = jtarget.get("kind").unwrap().as_array().unwrap(); + let kind = match kinds[0].as_string().unwrap() { + "bin" => TargetKind::Bin, + "lib" | "dylib" | "staticlib" => TargetKind::Lib, + _ => TargetKind::Other, + }; + + Target { + path: path, + kind: kind, } } -- cgit 1.4.1-3-g733a5 From 1e5e290e392adbf3e16f964bacb47a853cff3bdf Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Wed, 16 Dec 2015 04:48:49 +0100 Subject: Allow to pass arguments to rustfmt --- src/bin/cargo-fmt.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index af6c6b059a0..f79899ff5b1 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -28,7 +28,7 @@ fn main() { let mut opts = getopts::Options::new(); opts.optflag("h", "help", "show this message"); - let matches = match opts.parse(env::args().skip(1)) { + let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { Ok(m) => m, Err(e) => { print_usage(&opts, &e.to_string()); @@ -45,7 +45,8 @@ fn main() { fn print_usage(opts: &Options, reason: &str) { let msg = format!("{}\nusage: cargo fmt [options]", reason); - println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt.", + println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ + Arguments after `--` are passes to rustfmt.", opts.usage(&msg)); } @@ -64,7 +65,15 @@ fn format_crate(opts: &Options) { .map(|t| t.path) .collect(); - format_files(&files).unwrap_or_else(|e| print_usage(opts, &e.to_string())); + format_files(&files, &get_fmt_args()).unwrap_or_else(|e| print_usage(opts, &e.to_string())); +} + +fn get_fmt_args() -> Vec { + let mut args = vec!["--write-mode=overwrite".to_string()]; + // All arguments after -- are passed to rustfmt + args.extend(env::args().skip_while(|a| a != "--").skip(1)); + + args } #[derive(Debug)] @@ -133,10 +142,10 @@ fn target_from_json(jtarget: &Json) -> Target { } } -fn format_files(files: &Vec) -> Result<(), std::io::Error> { +fn format_files(files: &Vec, fmt_args: &Vec) -> Result<(), std::io::Error> { let mut command = try!(Command::new("rustfmt") - .arg("--write-mode=overwrite") .args(files) + .args(fmt_args) .spawn()); try!(command.wait()); -- cgit 1.4.1-3-g733a5 From ecf12778fbfbb2bcf028eb2440084edd23067f99 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 16 Dec 2015 18:07:59 +1300 Subject: Use replace rather than overwrite for cargo fmt --- Cargo.toml | 2 +- README.md | 3 ++- src/bin/cargo-fmt.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index bcba2f66818..17bd20a0561 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt" -version = "0.2.0" +version = "0.2.1" authors = ["Nicholas Cameron ", "Marcus Klaas ", "The Rustfmt contributors"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/README.md b/README.md index 88d332de2fd..3e58da373dd 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,8 @@ screen, for example. You can run `rustfmt --help` for more information. -`cargo fmt` uses `--write-mode=overwrite` by default. +`cargo fmt` uses `--write-mode=replace` by default. + ## Running Rustfmt from your editor diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index f79899ff5b1..96d7566330e 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -69,7 +69,7 @@ fn format_crate(opts: &Options) { } fn get_fmt_args() -> Vec { - let mut args = vec!["--write-mode=overwrite".to_string()]; + let mut args = vec!["--write-mode=replace".to_string()]; // All arguments after -- are passed to rustfmt args.extend(env::args().skip_while(|a| a != "--").skip(1)); diff --git a/src/lib.rs b/src/lib.rs index 86ab1a73022..0ee5f71a355 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -189,7 +189,7 @@ impl Sub for Indent { #[derive(Copy, Clone)] pub enum WriteMode { - // Backups the original file and overwrites the orignal. + // Backsup the original file and overwrites the orignal. Replace, // Overwrites original file without backup. Overwrite, -- cgit 1.4.1-3-g733a5 From 7f21569351f2ab0f9417387d6275dac3a7fb2f9b Mon Sep 17 00:00:00 2001 From: Sean Marshallsay Date: Wed, 16 Dec 2015 12:18:18 +0000 Subject: Fix spelling mistake in cargo-fmt usage string. --- src/bin/cargo-fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 96d7566330e..95f88b04ef3 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -46,7 +46,7 @@ fn main() { fn print_usage(opts: &Options, reason: &str) { let msg = format!("{}\nusage: cargo fmt [options]", reason); println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ - Arguments after `--` are passes to rustfmt.", + Arguments after `--` are passed to rustfmt.", opts.usage(&msg)); } -- cgit 1.4.1-3-g733a5 From c578ad8df55a9daea96ef11de8c4d1f7d4c8a40c Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Thu, 17 Dec 2015 17:17:43 +0100 Subject: Remove `--write-mode=replace` from cargo-fmt Since replace is the default rustfmt write mode, there's no need to call rustfmt with `--write-mode=replace`. As a bonus, it is now also possible to override the write-mode. --- src/bin/cargo-fmt.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 96d7566330e..dfcb15ee4c1 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -69,11 +69,8 @@ fn format_crate(opts: &Options) { } fn get_fmt_args() -> Vec { - let mut args = vec!["--write-mode=replace".to_string()]; // All arguments after -- are passed to rustfmt - args.extend(env::args().skip_while(|a| a != "--").skip(1)); - - args + env::args().skip_while(|a| a != "--").skip(1).collect() } #[derive(Debug)] -- cgit 1.4.1-3-g733a5 From a5da67f4c4040a169e91bdb93a69361d420903e5 Mon Sep 17 00:00:00 2001 From: Jan Likar Date: Sun, 20 Dec 2015 04:19:08 +0100 Subject: Add verbose and quiet flags to cargo-fmt Quiet mode supresses rustfmt's stdout, verbose mode prints targets that are going to be formatted. --- src/bin/cargo-fmt.rs | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 58d5e4d8d0f..9c5e4bf9567 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -27,6 +27,8 @@ use rustc_serialize::json::Json; fn main() { let mut opts = getopts::Options::new(); opts.optflag("h", "help", "show this message"); + opts.optflag("q", "quiet", "no output printed to stdout"); + opts.optflag("v", "verbose", "use verbose output"); let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { Ok(m) => m, @@ -36,10 +38,17 @@ fn main() { } }; + let (verbose, quiet) = (matches.opt_present("v"), matches.opt_present("q")); + + if verbose && quiet { + print_usage(&opts, "quiet mode and verbose mode are not compatible"); + return; + } + if matches.opt_present("h") { print_usage(&opts, ""); } else { - format_crate(&opts); + format_crate(&opts, verbose, quiet); } } @@ -50,7 +59,7 @@ fn print_usage(opts: &Options, reason: &str) { opts.usage(&msg)); } -fn format_crate(opts: &Options) { +fn format_crate(opts: &Options, verbose: bool, quiet: bool) { let targets = match get_targets() { Ok(t) => t, Err(e) => { @@ -62,10 +71,16 @@ fn format_crate(opts: &Options) { // Currently only bin and lib files get formatted let files: Vec<_> = targets.into_iter() .filter(|t| t.kind.is_lib() | t.kind.is_bin()) + .inspect(|t| { + if verbose { + println!("[{:?}] {:?}", t.kind, t.path) + } + }) .map(|t| t.path) .collect(); - format_files(&files, &get_fmt_args()).unwrap_or_else(|e| print_usage(opts, &e.to_string())); + format_files(&files, &get_fmt_args(), verbose, quiet) + .unwrap_or_else(|e| print_usage(opts, &e.to_string())); } fn get_fmt_args() -> Vec { @@ -97,7 +112,7 @@ impl TargetKind { } #[derive(Debug)] -struct Target { +pub struct Target { path: PathBuf, kind: TargetKind, } @@ -139,8 +154,28 @@ fn target_from_json(jtarget: &Json) -> Target { } } -fn format_files(files: &Vec, fmt_args: &Vec) -> Result<(), std::io::Error> { +fn format_files(files: &Vec, + fmt_args: &Vec, + verbose: bool, + quiet: bool) + -> Result<(), std::io::Error> { + let stdout = if quiet { + std::process::Stdio::null() + } else { + std::process::Stdio::inherit() + }; + if verbose { + print!("rustfmt"); + for a in fmt_args.iter() { + print!(" {}", a); + } + for f in files.iter() { + print!(" {}", f.display()); + } + println!(""); + } let mut command = try!(Command::new("rustfmt") + .stdout(stdout) .args(files) .args(fmt_args) .spawn()); -- cgit 1.4.1-3-g733a5 From a70b621607d62f11f9e9daa51e795bf26d6a6531 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 23 Dec 2015 17:25:49 +0300 Subject: add option to ignore out of line modules --- src/bin/rustfmt.rs | 2 ++ src/config.rs | 1 + src/lib.rs | 6 +++++- 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 1b54d0d4d06..3e369e1ef23 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -79,6 +79,7 @@ fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, Strin fn update_config(config: &mut Config, matches: &Matches) { config.verbose = matches.opt_present("verbose"); + config.skip_children = matches.opt_present("skip-children"); } fn execute() -> i32 { @@ -90,6 +91,7 @@ fn execute() -> i32 { "write-mode", "mode to write in (not usable when piping from stdin)", "[replace|overwrite|display|diff|coverage]"); + opts.optflag("", "skip-children", "don't reformat child modules"); opts.optflag("", "config-help", diff --git a/src/config.rs b/src/config.rs index 4c919191dbd..804ace83c6d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -259,6 +259,7 @@ macro_rules! create_config { create_config! { verbose: bool, false, "Use verbose output"; + skip_children: bool, false, "Don't reformat out of line modules"; max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; diff --git a/src/lib.rs b/src/lib.rs index 0ee5f71a355..bae42ed44fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -298,11 +298,15 @@ impl fmt::Display for FormatReport { // Formatting which depends on the AST. fn fmt_ast(krate: &ast::Crate, parse_session: &ParseSess, + main_file: &Path, config: &Config, mode: WriteMode) -> FileMap { let mut file_map = FileMap::new(); for (path, module) in modules::list_files(krate, parse_session.codemap()) { + if config.skip_children && path.as_path() != main_file { + continue; + } let path = path.to_str().unwrap(); if config.verbose { println!("Formatting {}", path); @@ -431,7 +435,7 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); - let mut file_map = fmt_ast(&krate, &parse_session, config, mode); + let mut file_map = fmt_ast(&krate, &parse_session, file, config, mode); // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. -- cgit 1.4.1-3-g733a5 From 1e80fd2dcd251e9d1b545728b96f04fc8f361213 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 25 Dec 2015 18:50:40 +0100 Subject: Prevent incorrect backslash removal in strings --- src/string.rs | 10 +++++----- tests/source/string-lit.rs | 5 +++++ tests/target/string-lit.rs | 5 +++++ 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 47ba79d927b..5961254cd9a 100644 --- a/src/string.rs +++ b/src/string.rs @@ -31,17 +31,17 @@ pub struct StringFormat<'a> { } // FIXME: simplify this! -pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { +pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { // Strip line breaks. - let re = Regex::new(r"(\\[\n\r][:space:]*)").unwrap(); - let stripped_str = re.replace_all(s, ""); + let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][:space:]*").unwrap(); + let stripped_str = re.replace_all(orig, "$1"); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); let indent = fmt.offset.to_string(fmt.config); let punctuation = ":,;."; let mut cur_start = 0; - let mut result = String::with_capacity(round_up_to_power_of_two(s.len())); + let mut result = String::with_capacity(round_up_to_power_of_two(stripped_str.len())); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); @@ -79,7 +79,7 @@ pub fn rewrite_string<'a>(s: &str, fmt: &StringFormat<'a>) -> Option { } } // Make sure there is no whitespace to the right of the break. - while cur_end < s.len() && graphemes[cur_end].trim().is_empty() { + while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { cur_end += 1; } let raw_line = graphemes[cur_start..cur_end].join(""); diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index c0bbee4f617..c89b798a0ea 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -39,3 +39,8 @@ fn issue682() { let a = "hello \\ o/"; let b = a.replace("\\ ", "\\"); } + +fn issue716() { + println!("forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()"); +} diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 0b5b5105b9b..b9a676c49ea 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -45,3 +45,8 @@ fn issue682() { let a = "hello \\ o/"; let b = a.replace("\\ ", "\\"); } + +fn issue716() { + println!("forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()"); +} -- cgit 1.4.1-3-g733a5 From 954dd0869e96336c3366886d9b87c7d0d90841ac Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 25 Dec 2015 19:07:51 +0100 Subject: Preserve mutability for typed self arguments --- src/items.rs | 32 ++++++++++++++++++++------------ tests/source/impls.rs | 2 ++ tests/target/impls.rs | 4 ++++ 3 files changed, 26 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 197f5403e7c..2224d9a5cb6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -930,27 +930,35 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) - } } ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { - Some(format!("self: {}", pprust::ty_to_string(ty))) + assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); + + let mutability = explicit_self_mutability(&args[0]); + + Some(format!("{}self: {}", + format_mutability(mutability), + pprust::ty_to_string(ty))) } ast::ExplicitSelf_::SelfValue(_) => { - assert!(args.len() >= 1, "&[ast::Arg] shouldn't be empty."); + assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - // this hacky solution caused by absence of `Mutability` in `SelfValue`. - let mut_str = { - if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = - args[0].pat.node { - format_mutability(mutability) - } else { - panic!("there is a bug or change in structure of AST, aborting."); - } - }; + let mutability = explicit_self_mutability(&args[0]); - Some(format!("{}self", mut_str)) + Some(format!("{}self", format_mutability(mutability))) } _ => None, } } +// Hacky solution caused by absence of `Mutability` in `SelfValue` and +// `SelfExplicit` variants of `ast::ExplicitSelf_`. +fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { + if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = arg.pat.node { + mutability + } else { + unreachable!() + } +} + pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { if is_named_arg(arg) { arg.pat.span.lo diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 4382c4fd0e6..016350ca6d6 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -58,3 +58,5 @@ impl Blah { fn boop() {} add_fun!(); } + +impl X { fn do_parse( mut self : X ) {} } diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 35ddc23a20a..9f12a6fd7ff 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -72,3 +72,7 @@ impl Blah { fn boop() {} add_fun!(); } + +impl X { + fn do_parse(mut self: X) {} +} -- cgit 1.4.1-3-g733a5 From 2069abcca4e4d07e1b17e35584d1917cc704cded Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 25 Dec 2015 20:59:46 +0100 Subject: Reduce dependency on pprust --- src/chains.rs | 5 +++-- src/items.rs | 33 ++++++++++++++++-------------- src/types.rs | 66 ++++++++++++++++++++++++++++++++--------------------------- 3 files changed, 57 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 952c7f1e08e..12f879eb59c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -27,7 +27,6 @@ use config::BlockIndentStyle; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; -use syntax::print::pprust; pub fn rewrite_chain(mut expr: &ast::Expr, context: &RewriteContext, @@ -233,7 +232,9 @@ fn rewrite_method_call(method_name: ast::Ident, let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { - let type_list = types.iter().map(|ty| pprust::ty_to_string(ty)).collect::>(); + let type_list: Vec<_> = try_opt!(types.iter() + .map(|ty| ty.rewrite(context, width, offset)) + .collect()); (types.last().unwrap().span.hi, format!("::<{}>", type_list.join(", "))) diff --git a/src/items.rs b/src/items.rs index 2224d9a5cb6..9882278c543 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,7 +23,6 @@ use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, Struct use syntax::{ast, abi}; use syntax::codemap::{Span, BytePos, mk_sp}; -use syntax::print::pprust; use syntax::parse::token; // Statements of the form @@ -901,31 +900,36 @@ impl Rewrite for ast::FunctionRetTy { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if is_named_arg(self) { - if let ast::Ty_::TyInfer = self.ty.node { - wrap_str(pprust::pat_to_string(&self.pat), - context.config.max_width, - width, - offset) - } else { - let mut result = pprust::pat_to_string(&self.pat); + let mut result = try_opt!(self.pat.rewrite(context, width, offset)); + + if self.ty.node != ast::Ty_::TyInfer { result.push_str(": "); let max_width = try_opt!(width.checked_sub(result.len())); let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len())); result.push_str(&ty_str); - Some(result) } + + Some(result) } else { self.ty.rewrite(context, width, offset) } } } -fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) -> Option { +fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, + args: &[ast::Arg], + context: &RewriteContext) + -> Option { match explicit_self.node { ast::ExplicitSelf_::SelfRegion(lt, m, _) => { let mut_str = format_mutability(m); match lt { - Some(ref l) => Some(format!("&{} {}self", pprust::lifetime_to_string(l), mut_str)), + Some(ref l) => { + let lifetime_str = try_opt!(l.rewrite(context, + usize::max_value(), + Indent::empty())); + Some(format!("&{} {}self", lifetime_str, mut_str)) + } None => Some(format!("&{}self", mut_str)), } } @@ -933,10 +937,9 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, args: &[ast::Arg]) - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); + let type_str = try_opt!(ty.rewrite(context, usize::max_value(), Indent::empty())); - Some(format!("{}self: {}", - format_mutability(mutability), - pprust::ty_to_string(ty))) + Some(format!("{}self: {}", format_mutability(mutability), type_str)) } ast::ExplicitSelf_::SelfValue(_) => { assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); @@ -1237,7 +1240,7 @@ fn rewrite_args(context: &RewriteContext, // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. let min_args = explicit_self.and_then(|explicit_self| { - rewrite_explicit_self(explicit_self, args) + rewrite_explicit_self(explicit_self, args, context) }) .map(|self_str| { arg_item_strs[0] = self_str; diff --git a/src/types.rs b/src/types.rs index 1d9522d0f90..911bf925293 100644 --- a/src/types.rs +++ b/src/types.rs @@ -135,12 +135,7 @@ impl<'a> SegmentParam<'a> { impl<'a> Rewrite for SegmentParam<'a> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { - SegmentParam::LifeTime(ref lt) => { - wrap_str(pprust::lifetime_to_string(lt), - context.config.max_width, - width, - offset) - } + SegmentParam::LifeTime(ref lt) => lt.rewrite(context, width, offset), SegmentParam::Type(ref ty) => ty.rewrite(context, width, offset), SegmentParam::Binding(ref binding) => { let mut result = format!("{} = ", binding.ident); @@ -332,12 +327,7 @@ impl Rewrite for ast::WherePredicate { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, .. }) => { - format!("{}: {}", - pprust::lifetime_to_string(lifetime), - bounds.iter() - .map(pprust::lifetime_to_string) - .collect::>() - .join(" + ")) + try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, width, offset)) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref path, ref ty, .. }) => { let ty_str = try_opt!(ty.rewrite(context, width, offset)); @@ -360,18 +350,27 @@ impl Rewrite for ast::WherePredicate { impl Rewrite for ast::LifetimeDef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - let result = if self.bounds.is_empty() { - pprust::lifetime_to_string(&self.lifetime) - } else { - format!("{}: {}", - pprust::lifetime_to_string(&self.lifetime), - self.bounds - .iter() - .map(pprust::lifetime_to_string) - .collect::>() - .join(" + ")) - }; + rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, width, offset) + } +} + +fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, + bounds: I, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option + where I: ExactSizeIterator +{ + let result = try_opt!(lt.rewrite(context, width, offset)); + if bounds.len() == 0 { + Some(result) + } else { + let appendix: Vec<_> = try_opt!(bounds.into_iter() + .map(|b| b.rewrite(context, width, offset)) + .collect()); + let result = format!("{}: {}", result, appendix.join(" + ")); wrap_str(result, context.config.max_width, width, offset) } } @@ -386,16 +385,20 @@ impl Rewrite for ast::TyParamBound { let budget = try_opt!(width.checked_sub(1)); Some(format!("?{}", try_opt!(tref.rewrite(context, budget, offset + 1)))) } - ast::TyParamBound::RegionTyParamBound(ref l) => { - wrap_str(pprust::lifetime_to_string(l), - context.config.max_width, - width, - offset) - } + ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, width, offset), } } } +impl Rewrite for ast::Lifetime { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + wrap_str(pprust::lifetime_to_string(self), + context.config.max_width, + width, + offset) + } +} + impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let strs: Vec<_> = try_opt!(self.iter() @@ -483,7 +486,10 @@ impl Rewrite for ast::Ty { let mut_len = mut_str.len(); Some(match *lifetime { Some(ref lifetime) => { - let lt_str = pprust::lifetime_to_string(lifetime); + let lt_budget = try_opt!(width.checked_sub(2 + mut_len)); + let lt_str = try_opt!(lifetime.rewrite(context, + lt_budget, + offset + 2 + mut_len)); let lt_len = lt_str.len(); let budget = try_opt!(width.checked_sub(2 + mut_len + lt_len)); format!("&{} {}{}", -- cgit 1.4.1-3-g733a5 From 291aa1b22800020ae2ee7fdd5e094c170589b8b8 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Dec 2015 14:25:37 +0100 Subject: Make fn argument formatting more resilient for complex self types --- src/items.rs | 6 ++++-- src/utils.rs | 12 ++++++++++++ tests/source/impls.rs | 4 ++++ tests/target/impls.rs | 4 ++++ 4 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9882278c543..ed59d41fd4a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -12,7 +12,8 @@ use Indent; use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, - wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; + wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines, + span_after_last}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; @@ -1260,7 +1261,8 @@ fn rewrite_args(context: &RewriteContext, // it is explicit. if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { - span_after(span, ",", context.codemap) + let reduced_span = mk_sp(span.lo, args[1].ty.span.lo); + span_after_last(reduced_span, ",", context.codemap) } else { span.lo }; diff --git a/src/utils.rs b/src/utils.rs index b1bbb860edb..a13ca247964 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -38,6 +38,18 @@ pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { original.lo + BytePos(offset as u32) } +#[inline] +pub fn span_after_last(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { + let snippet = codemap.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo + BytePos(offset as u32) +} + #[inline] pub fn format_visibility(vis: Visibility) -> &'static str { match vis { diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 016350ca6d6..c3c3ab8ad3a 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -60,3 +60,7 @@ impl Blah { } impl X { fn do_parse( mut self : X ) {} } + +impl Y5000 { + fn bar(self: X< 'a , 'b >, y: Y) {} +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 9f12a6fd7ff..b6c1193a77d 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -76,3 +76,7 @@ impl Blah { impl X { fn do_parse(mut self: X) {} } + +impl Y5000 { + fn bar(self: X<'a, 'b>, y: Y) {} +} -- cgit 1.4.1-3-g733a5 From 15e6b7d335c0c66b72961a2243a3af701f7476f5 Mon Sep 17 00:00:00 2001 From: Utkarsh Kukreti Date: Mon, 28 Dec 2015 17:23:34 +0530 Subject: Add tests for #606. --- src/rustfmt_diff.rs | 2 ++ tests/system.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 8c20b8f5a0f..4bb858a6b30 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -2,12 +2,14 @@ use std::collections::VecDeque; use diff; use term; +#[derive(Debug, PartialEq)] pub enum DiffLine { Context(String), Expected(String), Resulting(String), } +#[derive(Debug, PartialEq)] pub struct Mismatch { pub line_number: u32, pub lines: Vec, diff --git a/tests/system.rs b/tests/system.rs index 6d3c817256c..d6f1ba806f5 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -273,3 +273,17 @@ fn get_target(file_name: &str, target: Option<&str>, write_mode: WriteMode) -> S file_name.to_owned() } } + +#[test] +fn rustfmt_diff_make_diff_tests() { + let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); + assert_eq!(diff, + vec![Mismatch { + line_number: 1, + lines: vec![DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into())], + }]); +} -- cgit 1.4.1-3-g733a5 From 122fc4bc654ff80fa4e58f6a3ee26284fd822213 Mon Sep 17 00:00:00 2001 From: Sinh Pham Date: Thu, 31 Dec 2015 15:02:44 -0800 Subject: Fixed #700, use default color for titles and context in write-mode=diff --- src/rustfmt_diff.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 4bb858a6b30..9f529276df1 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -88,15 +88,15 @@ pub fn print_diff(diff: Vec, get_section_title: F) where F: Fn(u32) -> String { let mut t = term::stdout().unwrap(); + for mismatch in diff { - t.fg(term::color::BRIGHT_WHITE).unwrap(); let title = get_section_title(mismatch.line_number); writeln!(t, "{}", title).unwrap(); for line in mismatch.lines { match line { DiffLine::Context(ref str) => { - t.fg(term::color::WHITE).unwrap(); + t.reset().unwrap(); writeln!(t, " {}⏎", str).unwrap(); } DiffLine::Expected(ref str) => { @@ -109,6 +109,6 @@ pub fn print_diff(diff: Vec, get_section_title: F) } } } + t.reset().unwrap(); } - t.reset().unwrap(); } -- cgit 1.4.1-3-g733a5 From f6497ca3fbec4474084b8d13b39bd1bd1a87208d Mon Sep 17 00:00:00 2001 From: "Victor M. Suarez" Date: Sat, 2 Jan 2016 20:47:10 -0500 Subject: ignore case for config enums. Fixes #738 --- src/utils.rs | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index a13ca247964..83018a25ebb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -198,13 +198,14 @@ macro_rules! impl_enum_decodable { ( $e:ident, $( $x:ident ),* ) => { impl ::rustc_serialize::Decodable for $e { fn decode(d: &mut D) -> Result { + use std::ascii::AsciiExt; let s = try!(d.read_str()); - match &*s { - $( - stringify!($x) => Ok($e::$x), - )* - _ => Err(d.error("Bad variant")), - } + $( + if stringify!($x).eq_ignore_ascii_case(&s) { + return Ok($e::$x); + } + )* + Err(d.error("Bad variant")) } } @@ -212,12 +213,13 @@ macro_rules! impl_enum_decodable { type Err = &'static str; fn from_str(s: &str) -> Result { - match &*s { - $( - stringify!($x) => Ok($e::$x), - )* - _ => Err("Bad variant"), - } + use std::ascii::AsciiExt; + $( + if stringify!($x).eq_ignore_ascii_case(s) { + return Ok($e::$x); + } + )* + Err("Bad variant") } } -- cgit 1.4.1-3-g733a5 From f9f7235c1b8422e0fa1d05a8ab39144fabe10870 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Wed, 6 Jan 2016 11:02:01 +0900 Subject: Trailing commas for wildcard arms --- src/config.rs | 1 + src/expr.rs | 12 +++++++++--- tests/source/match-wildcard-trailing-comma.rs | 10 ++++++++++ tests/target/match-wildcard-trailing-comma.rs | 10 ++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/source/match-wildcard-trailing-comma.rs create mode 100644 tests/target/match-wildcard-trailing-comma.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 804ace83c6d..7e1172e1b9a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -312,4 +312,5 @@ create_config! { wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; } diff --git a/src/expr.rs b/src/expr.rs index 350b9c53a25..e3b7dc84204 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -829,7 +829,7 @@ fn rewrite_match(context: &RewriteContext, // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); - result.push_str(arm_comma(&context.config, &arm.body)); + result.push_str(arm_comma(&context.config, &arm, &arm.body)); } } // BytePos(1) = closing match brace. @@ -860,7 +860,13 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { arm.body.span.hi } -fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { +fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str { + if !config.match_wildcard_trailing_comma { + if arm.pats.len() == 1 && arm.pats[0].node == ast::PatWild && arm.guard.is_none() { + return ""; + } + } + if config.match_block_trailing_comma { "," } else if let ast::ExprBlock(ref block) = body.node { @@ -958,7 +964,7 @@ impl Rewrite for ast::Arm { ref x => x, }; - let comma = arm_comma(&context.config, body); + let comma = arm_comma(&context.config, self, body); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() diff --git a/tests/source/match-wildcard-trailing-comma.rs b/tests/source/match-wildcard-trailing-comma.rs new file mode 100644 index 00000000000..b13e85c2d90 --- /dev/null +++ b/tests/source/match-wildcard-trailing-comma.rs @@ -0,0 +1,10 @@ +// rustfmt-match_wildcard_trailing_comma: false + +fn match_wild(x: i32) -> i32 { + match x { + 1 => 1, + 2 => 2, + 3 => 3, + _ => 0, + } +} diff --git a/tests/target/match-wildcard-trailing-comma.rs b/tests/target/match-wildcard-trailing-comma.rs new file mode 100644 index 00000000000..e0fbf81e045 --- /dev/null +++ b/tests/target/match-wildcard-trailing-comma.rs @@ -0,0 +1,10 @@ +// rustfmt-match_wildcard_trailing_comma: false + +fn match_wild(x: i32) -> i32 { + match x { + 1 => 1, + 2 => 2, + 3 => 3, + _ => 0 + } +} -- cgit 1.4.1-3-g733a5 From ffe9c9d834469e583a623f64b5a778402109c80a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 7 Jan 2016 12:13:45 +0530 Subject: Clippy rustfmt --- src/expr.rs | 2 +- src/items.rs | 28 ++++++++++++---------------- src/lists.rs | 14 +++++--------- src/missed_spans.rs | 3 +-- src/types.rs | 2 +- src/utils.rs | 3 +-- 6 files changed, 21 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 350b9c53a25..0e05f506d9b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -382,7 +382,7 @@ fn rewrite_closure(capture: ast::CaptureClause, let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); // Checks if rewrite succeeded and fits on a single line. - let accept_rewrite = rewrite.as_ref().map(|result| !result.contains('\n')).unwrap_or(false); + let accept_rewrite = rewrite.as_ref().map_or(false, |result| !result.contains('\n')); if accept_rewrite { return Some(format!("{}{}{}{}", prefix, spacer, rewrite.unwrap(), closer)); diff --git a/src/items.rs b/src/items.rs index ed59d41fd4a..d9c21c339cb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -693,17 +693,15 @@ fn format_tuple_struct(context: &RewriteContext, let where_budget = try_opt!(context.config .max_width .checked_sub(last_line_width(&result))); - let where_clause_str = try_opt!(rewrite_where_clause(context, - &generics.where_clause, - context.config, - context.config.item_brace_style, - context.block_indent, - where_budget, - Density::Compressed, - ";", - None)); - - where_clause_str + try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.config.item_brace_style, + context.block_indent, + where_budget, + Density::Compressed, + ";", + None)) } None => "".to_owned(), }; @@ -1114,8 +1112,7 @@ fn rewrite_fn_base(context: &RewriteContext, // A conservative estimation, to goal is to be over all parens in generics let args_start = generics.ty_params .last() - .map(|tp| end_typaram(tp)) - .unwrap_or(span.lo); + .map_or(span.lo, |tp| end_typaram(tp)); let args_span = mk_sp(span_after(mk_sp(args_start, span.hi), "(", context.codemap), span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, @@ -1243,11 +1240,10 @@ fn rewrite_args(context: &RewriteContext, let min_args = explicit_self.and_then(|explicit_self| { rewrite_explicit_self(explicit_self, args, context) }) - .map(|self_str| { + .map_or(1, |self_str| { arg_item_strs[0] = self_str; 2 - }) - .unwrap_or(1); + }); // Comments between args. let mut arg_items = Vec::new(); diff --git a/src/lists.rs b/src/lists.rs index 4dd2e5d1dce..b251a8ee255 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -129,9 +129,8 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { - self.item.as_ref().map(|s| s.contains('\n')).unwrap_or(false) || - self.pre_comment.is_some() || - self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false) + self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || + self.post_comment.as_ref().map_or(false, |s| s.contains('\n')) } pub fn has_line_pre_comment(&self) -> bool { @@ -156,10 +155,7 @@ pub enum DefinitiveListTactic { Mixed, } -pub fn definitive_tactic<'t, I, T>(items: I, - tactic: ListTactic, - width: usize) - -> DefinitiveListTactic +pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic where I: IntoIterator + Clone, T: AsRef { @@ -493,7 +489,7 @@ fn needs_trailing_separator(separator_tactic: SeparatorTactic, } /// Returns the count and total width of the list items. -fn calculate_width<'li, I, T>(items: I) -> (usize, usize) +fn calculate_width(items: I) -> (usize, usize) where I: IntoIterator, T: AsRef { @@ -505,7 +501,7 @@ fn calculate_width<'li, I, T>(items: I) -> (usize, usize) fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + - item.item.as_ref().map(|str| str.len()).unwrap_or(0) + item.item.as_ref().map_or(0, |str| str.len()) } fn comment_len(comment: Option<&str>) -> usize { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index c123a9bc81b..67661143ddf 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -122,8 +122,7 @@ impl<'a> FmtVisitor<'a> { .skip_while(|rev_c| [' ', '\t'].contains(&rev_c)) .next(); - let fix_indent = last_char.map(|rev_c| ['{', '\n'].contains(&rev_c)) - .unwrap_or(true); + let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); if rewrite_next_comment && fix_indent { if let Some('{') = last_char { diff --git a/src/types.rs b/src/types.rs index 911bf925293..82a335c3012 100644 --- a/src/types.rs +++ b/src/types.rs @@ -30,7 +30,7 @@ pub fn rewrite_path(context: &RewriteContext, width: usize, offset: Indent) -> Option { - let skip_count = qself.map(|x| x.position).unwrap_or(0); + let skip_count = qself.map_or(0, |x| x.position); let mut result = if path.global { "::".to_owned() diff --git a/src/utils.rs b/src/utils.rs index a13ca247964..78677495a91 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -117,13 +117,12 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { typaram.bounds .last() - .map(|bound| { + .map_or(typaram.span, |bound| { match *bound { ast::RegionTyParamBound(ref lt) => lt.span, ast::TraitTyParamBound(ref prt, _) => prt.span, } }) - .unwrap_or(typaram.span) .hi } -- cgit 1.4.1-3-g733a5 From 16b348dd9c615d54db2dadfc388ee1160870b9d2 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Fri, 8 Jan 2016 17:03:41 +0900 Subject: Add commas after skipped arms when needed --- src/expr.rs | 3 +-- tests/source/match.rs | 8 ++++++++ tests/target/match.rs | 8 ++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4a6888e951e..c9f684c6c10 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -898,8 +898,7 @@ impl Rewrite for ast::Arm { attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { // Attributes included a skip instruction. - let snippet = context.snippet(mk_sp(attrs[0].span.lo, body.span.hi)); - return Some(snippet); + return None; } attr_visitor.format_missing(pats[0].span.lo); attr_visitor.buffer.to_string() diff --git a/tests/source/match.rs b/tests/source/match.rs index b4d35cb3815..3723424317b 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -100,6 +100,14 @@ fn matches() { } } +fn match_skip() { + let _ = match Some(1) { + #[rustfmt_skip] + Some( n ) => n, + None => 1, + }; +} + fn issue339() { match a { b => {} diff --git a/tests/target/match.rs b/tests/target/match.rs index 2c238ea8a68..94f9bf8ae5e 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -115,6 +115,14 @@ fn matches() { } } +fn match_skip() { + let _ = match Some(1) { + #[rustfmt_skip] + Some( n ) => n, + None => 1, + }; +} + fn issue339() { match a { b => {} -- cgit 1.4.1-3-g733a5 From 9f98f725cb9ff3a31c330a4117ea1962d91d18f6 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 10 Jan 2016 15:12:15 +0100 Subject: Detect when comments disappear When the reformatted code doesn't contain the same quantity of comments as the original code, use the original code instead of the reformatted code. This is done for all expressions and `let` statements. This should be used at the finest grained level possible, to avoid that a small disappearing comment prevents a big chunk of code to be reformatted. Kind of fixes (avoid disappearing comments, but prevents a good formatting is such case) #285 #225 #563 #743 --- src/comment.rs | 262 +++++++++++++++++++++++++++++----- src/expr.rs | 12 +- tests/source/paths.rs | 3 +- tests/target/comment-not-disappear.rs | 42 ++++++ tests/target/paths.rs | 1 + 5 files changed, 277 insertions(+), 43 deletions(-) create mode 100644 tests/target/comment-not-disappear.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index c111259979c..3f716d9039c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Format comments. +// Formatting and tools for comments. -use std::iter; +use std::{self, iter}; + +use syntax::codemap::Span; use Indent; use config::Config; +use rewrite::RewriteContext; use string::{StringFormat, rewrite_string}; +use utils::wrap_str; pub fn rewrite_comment(orig: &str, block_style: bool, @@ -150,7 +154,7 @@ impl FindUncommented for str { } Some(c) => { match kind { - CodeCharKind::Normal if b == c => {} + FullCodeCharKind::Normal if b == c => {} _ => { needle_iter = pat.chars(); } @@ -174,7 +178,7 @@ impl FindUncommented for str { pub fn find_comment_end(s: &str) -> Option { let mut iter = CharClasses::new(s.char_indices()); for (kind, (i, _c)) in &mut iter { - if kind == CodeCharKind::Normal { + if kind == FullCodeCharKind::Normal { return Some(i); } } @@ -189,7 +193,7 @@ pub fn find_comment_end(s: &str) -> Option { /// Returns true if text contains any comment. pub fn contains_comment(text: &str) -> bool { - CharClasses::new(text.chars()).any(|(kind, _)| kind == CodeCharKind::Comment) + CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) } struct CharClasses @@ -240,6 +244,33 @@ pub enum CodeCharKind { Comment, } +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum FullCodeCharKind { + Normal, + StartComment, + InComment, + EndComment, +} + +impl FullCodeCharKind { + fn is_comment(&self) -> bool { + match *self { + FullCodeCharKind::Normal => false, + FullCodeCharKind::StartComment | + FullCodeCharKind::InComment | + FullCodeCharKind::EndComment => true, + } + } + + fn to_codecharkind(&self) -> CodeCharKind { + if self.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + } + } +} + impl CharClasses where T: Iterator, T::Item: RichChar @@ -256,9 +287,9 @@ impl Iterator for CharClasses where T: Iterator, T::Item: RichChar { - type Item = (CodeCharKind, T::Item); + type Item = (FullCodeCharKind, T::Item); - fn next(&mut self) -> Option<(CodeCharKind, T::Item)> { + fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { let item = try_opt!(self.base.next()); let chr = item.get_char(); self.status = match self.status { @@ -286,11 +317,11 @@ impl Iterator for CharClasses match self.base.peek() { Some(next) if next.get_char() == '*' => { self.status = CharClassesStatus::BlockCommentOpening(1); - return Some((CodeCharKind::Comment, item)); + return Some((FullCodeCharKind::StartComment, item)); } Some(next) if next.get_char() == '/' => { self.status = CharClassesStatus::LineComment; - return Some((CodeCharKind::Comment, item)); + return Some((FullCodeCharKind::StartComment, item)); } _ => CharClassesStatus::Normal, } @@ -299,12 +330,7 @@ impl Iterator for CharClasses } } CharClassesStatus::BlockComment(deepness) => { - if deepness == 0 { - // This is the closing '/' - assert_eq!(chr, '/'); - self.status = CharClassesStatus::Normal; - return Some((CodeCharKind::Comment, item)); - } + assert!(deepness != 0); self.status = match self.base.peek() { Some(next) if next.get_char() == '/' && chr == '*' => { CharClassesStatus::BlockCommentClosing(deepness - 1) @@ -314,34 +340,92 @@ impl Iterator for CharClasses } _ => CharClassesStatus::BlockComment(deepness), }; - return Some((CodeCharKind::Comment, item)); + return Some((FullCodeCharKind::InComment, item)); } CharClassesStatus::BlockCommentOpening(deepness) => { assert_eq!(chr, '*'); self.status = CharClassesStatus::BlockComment(deepness); - return Some((CodeCharKind::Comment, item)); + return Some((FullCodeCharKind::InComment, item)); } CharClassesStatus::BlockCommentClosing(deepness) => { assert_eq!(chr, '/'); - self.status = if deepness == 0 { - CharClassesStatus::Normal + if deepness == 0 { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); } else { - CharClassesStatus::BlockComment(deepness) - }; - return Some((CodeCharKind::Comment, item)); + self.status = CharClassesStatus::BlockComment(deepness); + return Some((FullCodeCharKind::InComment, item)); + } } CharClassesStatus::LineComment => { - self.status = match chr { - '\n' => CharClassesStatus::Normal, - _ => CharClassesStatus::LineComment, - }; - return Some((CodeCharKind::Comment, item)); + match chr { + '\n' => { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); + } + _ => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::InComment, item)); + } + } + } + }; + Some((FullCodeCharKind::Normal, item)) + } +} + +/// Iterator over functional and commented parts of a string. Any part of a string is either +/// functional code, either *one* block comment, either *one* line comment. Whitespace between +/// comments is functional code. Line comments contain their ending newlines. +struct UngroupedCommentCodeSlices<'a> { + slice: &'a str, + iter: iter::Peekable>>, +} + +impl<'a> UngroupedCommentCodeSlices<'a> { + fn new(code: &'a str) -> UngroupedCommentCodeSlices<'a> { + UngroupedCommentCodeSlices { + slice: code, + iter: CharClasses::new(code.char_indices()).peekable(), + } + } +} + +impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { + type Item = (CodeCharKind, usize, &'a str); + + fn next(&mut self) -> Option { + let (kind, (start_idx, _)) = try_opt!(self.iter.next()); + match kind { + FullCodeCharKind::Normal => { + // Consume all the Normal code + while let Some(&(FullCodeCharKind::Normal, (_, _))) = self.iter.peek() { + let _ = self.iter.next(); + } } + FullCodeCharKind::StartComment => { + // Consume the whole comment + while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {} + } + _ => panic!(), + } + let slice = match self.iter.peek() { + Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx], + None => &self.slice[start_idx..], }; - Some((CodeCharKind::Normal, item)) + Some((if kind.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + }, + start_idx, + slice)) } } + + + /// Iterator over an alternating sequence of functional and commented parts of /// a string. The first item is always a, possibly zero length, subslice of /// functional text. Line style comments contain their ending newlines. @@ -383,7 +467,7 @@ impl<'a> Iterator for CommentCodeSlices<'a> { first_whitespace = Some(i); } - if kind == self.last_slice_kind && !is_comment_connector { + if kind.to_codecharkind() == self.last_slice_kind && !is_comment_connector { let last_index = match first_whitespace { Some(j) => j, None => i, @@ -419,20 +503,124 @@ impl<'a> Iterator for CommentCodeSlices<'a> { } } +/// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text +/// (if it fits in the width/offset, else return None), else return `new` +pub fn recover_comment_removed(new: String, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let snippet = context.snippet(span); + if changed_comment_content(&snippet, &new) { + // We missed some comments + // Keep previous formatting if it satisfies the constrains + return wrap_str(snippet, context.config.max_width, width, offset); + } else { + Some(new) + } +} + +/// Return true if the two strings of code have the same payload of comments. +/// The payload of comments is everything in the string except: +/// - actual code (not comments) +/// - comment start/end marks +/// - whitespace +/// - '*' at the beginning of lines in block comments +fn changed_comment_content(orig: &str, new: &str) -> bool { + // Cannot write this as a fn since we cannot return types containing closures + let code_comment_content = |code| { + let slices = UngroupedCommentCodeSlices::new(code); + slices.filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) + .flat_map(|(_, _, s)| CommentReducer::new(s)) + }; + let res = code_comment_content(orig).ne(code_comment_content(new)); + debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", + res, + orig, + new, + code_comment_content(orig).collect::(), + code_comment_content(new).collect::()); + res +} + + +/// Iterator over the 'payload' characters of a comment. +/// It skips whitespace, comment start/end marks, and '*' at the beginning of lines. +/// The comment must be one comment, ie not more than one start mark (no multiple line comments, +/// for example). +struct CommentReducer<'a> { + is_block: bool, + at_start_line: bool, + iter: std::str::Chars<'a>, +} + +impl<'a> CommentReducer<'a> { + fn new(comment: &'a str) -> CommentReducer<'a> { + let is_block = comment.starts_with("/*"); + let comment = remove_comment_header(comment); + CommentReducer { + is_block: is_block, + at_start_line: false, // There are no supplementary '*' on the first line + iter: comment.chars(), + } + } +} + +impl<'a> Iterator for CommentReducer<'a> { + type Item = char; + fn next(&mut self) -> Option { + loop { + let mut c = try_opt!(self.iter.next()); + if self.is_block && self.at_start_line { + while c.is_whitespace() { + c = try_opt!(self.iter.next()); + } + // Ignore leading '*' + if c == '*' { + c = try_opt!(self.iter.next()); + } + } else { + if c == '\n' { + self.at_start_line = true; + } + } + if !c.is_whitespace() { + return Some(c); + } + } + } +} + + +fn remove_comment_header(comment: &str) -> &str { + if comment.starts_with("///") || comment.starts_with("//!") { + &comment[3..] + } else if comment.starts_with("//") { + &comment[2..] + } else if comment.starts_with("/**") || comment.starts_with("/*!") { + &comment[3..comment.len() - 2] + } else { + assert!(comment.starts_with("/*"), + format!("string '{}' is not a comment", comment)); + &comment[2..comment.len() - 2] + } +} + #[cfg(test)] mod test { - use super::{CharClasses, CodeCharKind, contains_comment, rewrite_comment, FindUncommented, - CommentCodeSlices}; + use super::{CharClasses, CodeCharKind, FullCodeCharKind, contains_comment, rewrite_comment, + FindUncommented, CommentCodeSlices}; use Indent; #[test] fn char_classes() { let mut iter = CharClasses::new("//\n\n".chars()); - assert_eq!((CodeCharKind::Comment, '/'), iter.next().unwrap()); - assert_eq!((CodeCharKind::Comment, '/'), iter.next().unwrap()); - assert_eq!((CodeCharKind::Comment, '\n'), iter.next().unwrap()); - assert_eq!((CodeCharKind::Normal, '\n'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::StartComment, '/'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::InComment, '/'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::EndComment, '\n'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::Normal, '\n'), iter.next().unwrap()); assert_eq!(None, iter.next()); } @@ -507,8 +695,8 @@ mod test { CharClasses::new(text.chars()) .filter_map(|(s, c)| { match s { - CodeCharKind::Normal => Some(c), - CodeCharKind::Comment => None, + FullCodeCharKind::Normal => Some(c), + _ => None, } }) .collect() diff --git a/src/expr.rs b/src/expr.rs index c9f684c6c10..269e45f9e9f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,7 +23,7 @@ use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search, semicolon_for_stmt}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle}; -use comment::{FindUncommented, rewrite_comment, contains_comment}; +use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; @@ -35,7 +35,7 @@ use syntax::visit::Visitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - match self.node { + let result = match self.node { ast::Expr_::ExprVec(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), mk_sp(span_after(self.span, "[", context.codemap), self.span.hi), @@ -207,7 +207,8 @@ impl Rewrite for ast::Expr { width, offset) } - } + }; + result.and_then(|res| recover_comment_removed(res, self.span, context, width, offset)) } } @@ -478,7 +479,7 @@ impl Rewrite for ast::Block { impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, _width: usize, offset: Indent) -> Option { - match self.node { + let result = match self.node { ast::Stmt_::StmtDecl(ref decl, _) => { if let ast::Decl_::DeclLocal(ref local) = decl.node { local.rewrite(context, context.config.max_width, offset) @@ -499,7 +500,8 @@ impl Rewrite for ast::Stmt { .map(|s| s + suffix) } ast::Stmt_::StmtMac(..) => None, - } + }; + result.and_then(|res| recover_comment_removed(res, self.span, context, _width, offset)) } } diff --git a/tests/source/paths.rs b/tests/source/paths.rs index 8a4ab769ba3..af61ba89b1c 100644 --- a/tests/source/paths.rs +++ b/tests/source/paths.rs @@ -17,7 +17,8 @@ fn main() { < *mut JSObject >:: relocate(entry); - let x: Foo/*::*/; + let x: Foo; + let x: Foo/*::*/; } fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/target/comment-not-disappear.rs b/tests/target/comment-not-disappear.rs new file mode 100644 index 00000000000..23c00c418be --- /dev/null +++ b/tests/target/comment-not-disappear.rs @@ -0,0 +1,42 @@ +// All the comments here should not disappear. + +fn a() { + match x { + X | + // A comment + Y => {} + }; +} + +fn b() { + match x { + X => + // A comment + y + } +} + +fn c() { + a() /* ... */; +} + +fn foo() -> Vec { + (0..11) + .map(|x| + // This comment disappears. + if x % 2 == 0 { x } else { x * 2 }) + .collect() +} + +fn d() { + if true /* and ... */ { + a(); + } +} + +fn calc_page_len(prefix_len: usize, sofar: usize) -> usize { + 2 // page type and flags + + 1 // stored depth + + 2 // stored count + + prefix_len + sofar // sum of size of all the actual items +} diff --git a/tests/target/paths.rs b/tests/target/paths.rs index f1b142b3a5c..adae879e647 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -17,6 +17,7 @@ fn main() { <*mut JSObject>::relocate(entry); let x: Foo; + let x: Foo/*::*/; } fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {} -- cgit 1.4.1-3-g733a5 From 598fcdddc39fb9ca088e21191e35aeae51ed626e Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 10 Jan 2016 16:25:31 +0100 Subject: Fix issue with windows line endings (#717). The '\r' character wasn't counted in the line length. --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index bae42ed44fd..3ed7c3cad8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -337,6 +337,7 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { for (c, b) in text.chars() { if c == '\r' { + line_len += c.len_utf8(); continue; } @@ -367,7 +368,7 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { last_wspace = None; } else { newline_count = 0; - line_len += 1; + line_len += c.len_utf8(); if c.is_whitespace() { if last_wspace.is_none() { last_wspace = Some(b); -- cgit 1.4.1-3-g733a5 From b117d7b2b845fad5d5bb30a620a13b4810e7ffe3 Mon Sep 17 00:00:00 2001 From: Gaëtan Cassiers Date: Sun, 10 Jan 2016 22:04:30 +0100 Subject: Document comment::*CodeCharKind --- src/comment.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 3f716d9039c..3382ab53276 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -238,17 +238,25 @@ enum CharClassesStatus { LineComment, } +/// Distinguish between functionnal part of code and comments #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum CodeCharKind { Normal, Comment, } +/// Distinguish between functionnal part of code and comments, +/// describing opening and closing of comments for ease when chunking +/// code from tagged characters #[derive(PartialEq, Eq, Debug, Clone, Copy)] enum FullCodeCharKind { Normal, + /// The first character of a comment, there is only one for a comment (always '/') StartComment, + /// Any character inside a comment including the second character of comment + /// marks ("//", "/*") InComment, + /// Last character of a comment, '\n' for a line comment, '/' for a block comment. EndComment, } -- cgit 1.4.1-3-g733a5 From 56a3aac2b57168016031b33ae10984619a7cabf3 Mon Sep 17 00:00:00 2001 From: "Victor M. Suarez" Date: Sat, 2 Jan 2016 23:21:55 -0500 Subject: stop creating bk files if there are no changes. Fixes #733 --- src/filemap.rs | 53 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 5b997b55c25..95ae95e66bc 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -85,21 +85,38 @@ pub fn write_file(text: &StringBuffer, } } + fn source_and_formatted_text(text: &StringBuffer, + filename: &str, + config: &Config) + -> Result<(String, String), io::Error> { + let mut f = try!(File::open(filename)); + let mut ori_text = String::new(); + try!(f.read_to_string(&mut ori_text)); + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text, config)); + let fmt_text = String::from_utf8(v).unwrap(); + Ok((ori_text, fmt_text)) + } + match mode { WriteMode::Replace => { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.to_owned() + ".tmp"; - let bk_name = filename.to_owned() + ".bk"; - { - // Write text to temp file - let tmp_file = try!(File::create(&tmp_name)); - try!(write_system_newlines(tmp_file, text, config)); - } + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + if fmt != ori { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.to_owned() + ".tmp"; + let bk_name = filename.to_owned() + ".bk"; + { + // Write text to temp file + let tmp_file = try!(File::create(&tmp_name)); + try!(write_system_newlines(tmp_file, text, config)); + } - try!(fs::rename(filename, bk_name)); - try!(fs::rename(tmp_name, filename)); + try!(fs::rename(filename, bk_name)); + try!(fs::rename(tmp_name, filename)); + } + } } WriteMode::Overwrite => { // Write text directly over original file. @@ -124,14 +141,10 @@ pub fn write_file(text: &StringBuffer, } WriteMode::Diff => { println!("Diff of {}:\n", filename); - let mut f = try!(File::open(filename)); - let mut ori_text = String::new(); - try!(f.read_to_string(&mut ori_text)); - let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); - let fmt_text = String::from_utf8(v).unwrap(); - let diff = make_diff(&ori_text, &fmt_text, 3); - print_diff(diff, |line_num| format!("\nDiff at line {}:", line_num)); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + print_diff(make_diff(&ori, &fmt, 3), + |line_num| format!("\nDiff at line {}:", line_num)); + } } WriteMode::Return => { // io::Write is not implemented for String, working around with -- cgit 1.4.1-3-g733a5 From 6b741a7194c4de975083743f3d49fd3ab24ff74c Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Sun, 10 Jan 2016 22:06:06 -0700 Subject: Where clause is on same line as fn if fn is empty fix-#760 only applies if fn_empty_single_line is set to true --- src/items.rs | 15 +++++++++++++-- tests/source/fn-single-line.rs | 3 +++ tests/target/fn-single-line.rs | 2 ++ tests/target/fn.rs | 17 +++-------------- 4 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d9c21c339cb..efe3a86e3a5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -21,6 +21,7 @@ use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; +use syntax::codemap; use syntax::{ast, abi}; use syntax::codemap::{Span, BytePos, mk_sp}; @@ -180,6 +181,10 @@ impl<'a> FmtVisitor<'a> { let mut newline_brace = newline_for_brace(self.config, &generics.where_clause); let context = self.get_context(); + let block_snippet = self.snippet(codemap::mk_sp(block.span.lo, block.span.hi)); + let is_block_empty = block_snippet[1..block_snippet.len() - 1].trim().is_empty() && + context.config.fn_empty_single_line; + let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, indent, ident, @@ -192,7 +197,7 @@ impl<'a> FmtVisitor<'a> { vis, span, newline_brace, - true)); + !is_block_empty)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; @@ -1196,7 +1201,7 @@ fn rewrite_fn_base(context: &RewriteContext, (context.config.fn_args_layout == StructLitStyle::Block && ret_str.is_empty()) || (context.config.where_density == Density::CompressedIfEmpty && - !has_body) { + !has_body && !result.contains('\n')) { Density::Compressed } else { Density::Tall @@ -1213,6 +1218,12 @@ fn rewrite_fn_base(context: &RewriteContext, where_density, "{", Some(span.hi))); + + if last_line_width(&result) + where_clause_str.len() > context.config.max_width && + !where_clause_str.contains('\n') { + result.push('\n'); + } + result.push_str(&where_clause_str); Some((result, force_new_line_for_brace)) diff --git a/tests/source/fn-single-line.rs b/tests/source/fn-single-line.rs index a34371f55ad..6d7f764d280 100644 --- a/tests/source/fn-single-line.rs +++ b/tests/source/fn-single-line.rs @@ -74,3 +74,6 @@ trait CoolTypes { trait CoolerTypes { fn dummy(&self) { } } + +fn Foo() where T: Bar { +} diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs index 674ce1c89f9..049206b60c8 100644 --- a/tests/target/fn-single-line.rs +++ b/tests/target/fn-single-line.rs @@ -61,3 +61,5 @@ trait CoolTypes { trait CoolerTypes { fn dummy(&self) {} } + +fn Foo() where T: Bar {} diff --git a/tests/target/fn.rs b/tests/target/fn.rs index eb4c3e1c8c1..02600f43f2a 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -2,17 +2,9 @@ fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} -fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType - where T: Blah -{ +fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType where T: Blah {} -} - -fn foo(a: AAA /* (comment) */) - where T: Blah -{ - -} +fn foo(a: AAA /* (comment) */) where T: Blah {} fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) @@ -35,10 +27,7 @@ fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, fn foo B /* paren inside generics */>() {} impl Foo { - fn with_no_errors(&mut self, f: F) -> T - where F: FnOnce(&mut Resolver) -> T - { - } + fn with_no_errors(&mut self, f: F) -> T where F: FnOnce(&mut Resolver) -> T {} fn foo(mut self, mut bar: u32) {} -- cgit 1.4.1-3-g733a5 From dba2d8afd553bd18806c4f674b0d6bcd925cb78e Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 11 Jan 2016 12:26:57 -0700 Subject: Added option for tighter punctuation in types. fixes #489 --- src/config.rs | 9 +++++++++ src/types.rs | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7e1172e1b9a..63fb4f760ef 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,6 +73,13 @@ configuration_option_enum! { Density: CompressedIfEmpty, } +configuration_option_enum! { TypeDensity: + // No spaces around "=" and "+" + Compressed, + // Spaces around " = " and " + " + WhiteSpace, +} + impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { @@ -278,6 +285,8 @@ create_config! { fn_args_density: Density, Density::Tall, "Argument density in functions"; fn_args_layout: StructLitStyle, StructLitStyle::Visual, "Layout of function arguments"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; + type_punctuation_density: TypeDensity, TypeDensity::WhiteSpace, + "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; // Should we at least try to put the where clause on the same line as the rest of the // function decl? where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; diff --git a/src/types.rs b/src/types.rs index 82a335c3012..5500cdecfc0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -21,6 +21,7 @@ use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, span_after, format_mutability, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; +use config::TypeDensity; // Does not wrap on simple segments. pub fn rewrite_path(context: &RewriteContext, @@ -424,7 +425,12 @@ impl Rewrite for ast::TyParam { result.push_str(&bounds); } if let Some(ref def) = self.default { - result.push_str(" = "); + let eq_str = if context.config.type_punctuation_density == TypeDensity::Compressed { + "=" + } else { + " = " + }; + result.push_str(eq_str); let budget = try_opt!(width.checked_sub(result.len())); let rewrite = try_opt!(def.rewrite(context, budget, offset + result.len())); result.push_str(&rewrite); @@ -467,8 +473,15 @@ impl Rewrite for ast::Ty { ast::TyObjectSum(ref ty, ref bounds) => { let ty_str = try_opt!(ty.rewrite(context, width, offset)); let overhead = ty_str.len() + 3; - Some(format!("{} + {}", + let plus_str = if context.config.type_punctuation_density == + TypeDensity::Compressed { + "+" + } else { + " + " + }; + Some(format!("{}{}{}", ty_str, + plus_str, try_opt!(bounds.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead)))) -- cgit 1.4.1-3-g733a5 From 749697d84594c78650f34dada25ee0c012a6b418 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 11 Jan 2016 14:47:56 -0700 Subject: Changed is_block_empty to has_body --- src/items.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index efe3a86e3a5..d81ff776126 100644 --- a/src/items.rs +++ b/src/items.rs @@ -182,8 +182,8 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let block_snippet = self.snippet(codemap::mk_sp(block.span.lo, block.span.hi)); - let is_block_empty = block_snippet[1..block_snippet.len() - 1].trim().is_empty() && - context.config.fn_empty_single_line; + let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || + !context.config.fn_empty_single_line; let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, indent, @@ -197,7 +197,7 @@ impl<'a> FmtVisitor<'a> { vis, span, newline_brace, - !is_block_empty)); + has_body)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; -- cgit 1.4.1-3-g733a5 From b0eb0f5daa9582387c4935d86e6077b7eb89a34b Mon Sep 17 00:00:00 2001 From: DarkDrek Date: Sun, 10 Jan 2016 05:20:35 +0100 Subject: Keep comments between if and else blocks. Fixes #447 --- src/expr.rs | 25 ++++++++++++++++++++++++- tests/target/issue-447.rs | 7 +++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-447.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 269e45f9e9f..096a934a788 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -664,7 +664,30 @@ fn rewrite_if_else(context: &RewriteContext, _ => else_block.rewrite(context, width, offset), }; - result.push_str(" else "); + let snippet = context.codemap + .span_to_snippet(mk_sp(if_block.span.hi, else_block.span.lo)) + .unwrap(); + // Preserve comments that are between the if and else block + if contains_comment(&snippet) { + let close_pos = try_opt!(snippet.find_uncommented("else")); + let trimmed = &snippet[..close_pos].trim(); + let comment_str = format!("{}{}", + offset.to_string(context.config), + try_opt!(rewrite_comment(trimmed, + false, + width, + offset, + context.config)), + ); + let else_str = format!("{}else ", offset.to_string(context.config)); + + result.push('\n'); + result.push_str(&comment_str); + result.push('\n'); + result.push_str(&else_str); + } else { + result.push_str(" else "); + } result.push_str(&&try_opt!(rewrite)); } diff --git a/tests/target/issue-447.rs b/tests/target/issue-447.rs new file mode 100644 index 00000000000..56e6c333aac --- /dev/null +++ b/tests/target/issue-447.rs @@ -0,0 +1,7 @@ +fn main() { + if cond { + } + // This shouldn't be dropped + else { + } +} -- cgit 1.4.1-3-g733a5 From 4da91e7df24e833a5800631319f300a304d2f981 Mon Sep 17 00:00:00 2001 From: DarkDrek Date: Tue, 12 Jan 2016 01:09:08 +0100 Subject: Handle more possible comment position for if else Extended the test with the new possiblecomment positions --- src/expr.rs | 91 +++++++++++++++++++++++++++++++++-------------- src/utils.rs | 8 +++++ tests/source/issue-447.rs | 37 +++++++++++++++++++ tests/target/issue-447.rs | 38 ++++++++++++++++++-- 4 files changed, 144 insertions(+), 30 deletions(-) create mode 100644 tests/source/issue-447.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 096a934a788..54a6fb20fa8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -13,14 +13,15 @@ use std::borrow::Borrow; use std::mem::swap; use std::ops::Deref; use std::iter::ExactSizeIterator; +use std::fmt::Write; use {Indent, Spanned}; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; use string::{StringFormat, rewrite_string}; -use utils::{span_after, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, - semicolon_for_stmt}; +use utils::{span_after, span_before, extra_offset, last_line_width, wrap_str, binary_search, + first_line_width, semicolon_for_stmt}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -101,6 +102,7 @@ impl Rewrite for ast::Expr { cond, if_block, else_block.as_ref().map(|e| &**e), + self.span, None, width, offset, @@ -111,6 +113,7 @@ impl Rewrite for ast::Expr { cond, if_block, else_block.as_ref().map(|e| &**e), + self.span, Some(pat), width, offset, @@ -605,12 +608,33 @@ fn rewrite_label(label: Option) -> String { } } +fn extract_comment(span: Span, + context: &RewriteContext, + offset: Indent, + width: usize) + -> Option { + let comment_str = context.snippet(span); + if contains_comment(&comment_str) { + let comment = try_opt!(rewrite_comment(comment_str.trim(), + false, + width, + offset, + context.config)); + Some(format!("\n{indent}{}\n{indent}", + comment, + indent = offset.to_string(context.config))) + } else { + None + } +} + // Rewrites if-else blocks. If let Some(_) = pat, the expression is // treated as an if-let-else expression. fn rewrite_if_else(context: &RewriteContext, cond: &ast::Expr, if_block: &ast::Block, else_block_opt: Option<&ast::Expr>, + span: Span, pat: Option<&ast::Pat>, width: usize, offset: Indent, @@ -635,7 +659,22 @@ fn rewrite_if_else(context: &RewriteContext, } let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); - let mut result = format!("if {} {}", pat_expr_string, if_block_string); + + let between_if_cond = mk_sp(span_after(span, "if", context.codemap), + pat.map_or(cond.span.lo, + |_| span_before(span, "let", context.codemap))); + let between_if_cond_comment = extract_comment(between_if_cond, &context, offset, width); + + let after_cond_comment = extract_comment(mk_sp(cond.span.hi, if_block.span.lo), + context, + offset, + width); + + let mut result = format!("if{}{}{}{}", + between_if_cond_comment.as_ref().map_or(" ", |str| &**str), + pat_expr_string, + after_cond_comment.as_ref().map_or(" ", |str| &**str), + if_block_string); if let Some(else_block) = else_block_opt { let rewrite = match else_block.node { @@ -646,6 +685,7 @@ fn rewrite_if_else(context: &RewriteContext, cond, if_block, else_block.as_ref().map(|e| &**e), + mk_sp(span_after(span, "else", context.codemap), span.hi), Some(pat), width, offset, @@ -656,6 +696,7 @@ fn rewrite_if_else(context: &RewriteContext, cond, if_block, else_block.as_ref().map(|e| &**e), + mk_sp(span_after(span, "else", context.codemap), span.hi), None, width, offset, @@ -664,30 +705,26 @@ fn rewrite_if_else(context: &RewriteContext, _ => else_block.rewrite(context, width, offset), }; - let snippet = context.codemap - .span_to_snippet(mk_sp(if_block.span.hi, else_block.span.lo)) - .unwrap(); - // Preserve comments that are between the if and else block - if contains_comment(&snippet) { - let close_pos = try_opt!(snippet.find_uncommented("else")); - let trimmed = &snippet[..close_pos].trim(); - let comment_str = format!("{}{}", - offset.to_string(context.config), - try_opt!(rewrite_comment(trimmed, - false, - width, - offset, - context.config)), - ); - let else_str = format!("{}else ", offset.to_string(context.config)); - - result.push('\n'); - result.push_str(&comment_str); - result.push('\n'); - result.push_str(&else_str); - } else { - result.push_str(" else "); - } + let between_if_else_block = mk_sp(if_block.span.hi, + span_before(mk_sp(if_block.span.hi, else_block.span.lo), + "else", + context.codemap)); + let between_if_else_block_comment = extract_comment(between_if_else_block, + &context, + offset, + width); + + let after_else = mk_sp(span_after(mk_sp(if_block.span.hi, else_block.span.lo), + "else", + context.codemap), + else_block.span.lo); + let after_else_comment = extract_comment(after_else, &context, offset, width); + + try_opt!(write!(&mut result, + "{}else{}", + between_if_else_block_comment.as_ref().map_or(" ", |str| &**str), + after_else_comment.as_ref().map_or(" ", |str| &**str)) + .ok()); result.push_str(&&try_opt!(rewrite)); } diff --git a/src/utils.rs b/src/utils.rs index 7014605ec81..3b03ede2be3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -38,6 +38,14 @@ pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { original.lo + BytePos(offset as u32) } +#[inline] +pub fn span_before(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { + let snippet = codemap.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap(); + + original.lo + BytePos(offset as u32) +} + #[inline] pub fn span_after_last(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { let snippet = codemap.span_to_snippet(original).unwrap(); diff --git a/tests/source/issue-447.rs b/tests/source/issue-447.rs new file mode 100644 index 00000000000..cc713af3f18 --- /dev/null +++ b/tests/source/issue-447.rs @@ -0,0 +1,37 @@ +fn main() { + if /* shouldn't be dropped + shouldn't be dropped */ + + cond /* shouldn't be dropped + shouldn't be dropped */ + + { + } /* shouldn't be dropped + shouldn't be dropped */ + + else /* shouldn't be dropped + shouldn't be dropped */ + + if /* shouldn't be dropped + shouldn't be dropped */ + + cond /* shouldn't be dropped + shouldn't be dropped */ + + { + } /* shouldn't be dropped + shouldn't be dropped */ + + else /* shouldn't be dropped + shouldn't be dropped */ + + { + } + + if /* shouldn't be dropped + shouldn't be dropped */ + let Some(x) = y/* shouldn't be dropped + shouldn't be dropped */ + { + } +} diff --git a/tests/target/issue-447.rs b/tests/target/issue-447.rs index 56e6c333aac..7e69c708eb7 100644 --- a/tests/target/issue-447.rs +++ b/tests/target/issue-447.rs @@ -1,7 +1,39 @@ fn main() { - if cond { + if + // shouldn't be dropped + // shouldn't be dropped + cond + // shouldn't be dropped + // shouldn't be dropped + { } - // This shouldn't be dropped - else { + // shouldn't be dropped + // shouldn't be dropped + else + // shouldn't be dropped + // shouldn't be dropped + if + // shouldn't be dropped + // shouldn't be dropped + cond + // shouldn't be dropped + // shouldn't be dropped + { + } + // shouldn't be dropped + // shouldn't be dropped + else + // shouldn't be dropped + // shouldn't be dropped + { + } + + if + // shouldn't be dropped + // shouldn't be dropped + let Some(x) = y + // shouldn't be dropped + // shouldn't be dropped + { } } -- cgit 1.4.1-3-g733a5 From d7a3256d4080ce4f125443f6894a3dfaf108e15b Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Sat, 9 Jan 2016 22:45:58 -0700 Subject: If where is on the same line as the impl, { is put on the same line fixes #650 factored if clause into a separate function --- src/config.rs | 1 + src/items.rs | 35 +++++++++++++++++++++++++++++++++-- tests/source/impls.rs | 13 +++++++++++++ tests/target/impls.rs | 28 ++++++++++++++++++++++++++-- 4 files changed, 73 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7e1172e1b9a..3e251ad1e39 100644 --- a/src/config.rs +++ b/src/config.rs @@ -270,6 +270,7 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; + impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, diff --git a/src/items.rs b/src/items.rs index d9c21c339cb..75eda01c870 100644 --- a/src/items.rs +++ b/src/items.rs @@ -25,6 +25,8 @@ use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, Struct use syntax::{ast, abi}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; +use syntax::ast::ImplItem; +use syntax::ptr::P; // Statements of the form // let pat: ty = init; @@ -485,8 +487,18 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - context.config.where_density, "{", None)); - if !where_clause_str.contains('\n') && - result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + + if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { + result.push_str(&where_clause_str); + if where_clause_str.contains('\n') { + result.push_str("\n{\n}"); + } else { + result.push_str(" {}"); + } + return Some(result); + } + + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); @@ -505,6 +517,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - } } } + result.push('{'); let snippet = context.snippet(item.span); @@ -531,13 +544,31 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - result.push_str(&outer_indent_str); } + if result.chars().last().unwrap() == '{' { + result.push('\n'); + } result.push('}'); + Some(result) } else { unreachable!(); } } +fn is_impl_single_line(context: &RewriteContext, + items: &Vec>, + result: &str, + where_clause_str: &str, + item: &ast::Item) + -> Option { + let snippet = context.snippet(item.span); + let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + + Some(context.config.impl_empty_single_line && items.is_empty() && + result.len() + where_clause_str.len() <= context.config.max_width && + !contains_comment(&snippet[open_pos..])) +} + pub fn format_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, diff --git a/tests/source/impls.rs b/tests/source/impls.rs index c3c3ab8ad3a..d04b5ce1eeb 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -22,6 +22,12 @@ impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooo fn foo() { "hi" } } +impl Foo for Bar where T: Baz +{ +} + +impl Foo for Bar where T: Baz { /* Comment */ } + impl Foo { fn foo() {} } @@ -64,3 +70,10 @@ impl X { fn do_parse( mut self : X ) {} } impl Y5000 { fn bar(self: X< 'a , 'b >, y: Y) {} } + +pub impl Foo for Bar where T: Foo +{ + fn foo() { "hi" } +} + +pub impl Foo for Bar where T: Foo, Z: Baz {} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index b6c1193a77d..33bc7481905 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -16,7 +16,8 @@ pub impl Foo for Bar { // Comment 3 } -pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> +pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> + where X: Foo<'a, Z> { fn foo() { "hi" @@ -31,13 +32,22 @@ impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> } } -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> + where X: Foooooooooooooooooooooooooooo<'a, Z> { fn foo() { "hi" } } +impl Foo for Bar where T: Baz {} + +impl Foo for Bar + where T: Baz +{ + // Comment +} + impl Foo { fn foo() {} } @@ -80,3 +90,17 @@ impl X { impl Y5000 { fn bar(self: X<'a, 'b>, y: Y) {} } + +pub impl Foo for Bar + where T: Foo +{ + fn foo() { + "hi" + } +} + +pub impl Foo for Bar + where T: Foo, + Z: Baz +{ +} -- cgit 1.4.1-3-g733a5 From 937e26d4e1b28a2b4609ccc76b14a7c873333c02 Mon Sep 17 00:00:00 2001 From: DarkDrek Date: Tue, 12 Jan 2016 21:13:59 +0100 Subject: fixes parsing issue #767 --- src/expr.rs | 13 +++++++------ tests/source/expr.rs | 11 +++++++++++ tests/target/expr.rs | 11 +++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 54a6fb20fa8..25c86363921 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -663,6 +663,7 @@ fn rewrite_if_else(context: &RewriteContext, let between_if_cond = mk_sp(span_after(span, "if", context.codemap), pat.map_or(cond.span.lo, |_| span_before(span, "let", context.codemap))); + let between_if_cond_comment = extract_comment(between_if_cond, &context, offset, width); let after_cond_comment = extract_comment(mk_sp(cond.span.hi, if_block.span.lo), @@ -680,23 +681,23 @@ fn rewrite_if_else(context: &RewriteContext, let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it // from being formatted on a single line. - ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref else_block) => { + ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, if_block, - else_block.as_ref().map(|e| &**e), - mk_sp(span_after(span, "else", context.codemap), span.hi), + next_else_block.as_ref().map(|e| &**e), + mk_sp(else_block.span.lo, span.hi), Some(pat), width, offset, false) } - ast::Expr_::ExprIf(ref cond, ref if_block, ref else_block) => { + ast::Expr_::ExprIf(ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, if_block, - else_block.as_ref().map(|e| &**e), - mk_sp(span_after(span, "else", context.codemap), span.hi), + next_else_block.as_ref().map(|e| &**e), + mk_sp(else_block.span.lo, span.hi), None, width, offset, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 26b22ed29be..c5002f5ec15 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -233,3 +233,14 @@ fn blocks() { println!("yay arithmetix!"); }; } + +fn issue767() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index d39309258b0..9c9c65a690c 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -256,3 +256,14 @@ fn blocks() { println!("yay arithmetix!"); }; } + +fn issue767() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} -- cgit 1.4.1-3-g733a5 From 479b69266be59ad1723d986b32c0d156f7772b9f Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Tue, 12 Jan 2016 13:42:53 -0700 Subject: Changed TypeDensity::WhiteSpace to TypeDensity::Wide Changed eq_str and plus_str assignments to use a match --- src/config.rs | 4 ++-- src/types.rs | 16 +++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 63fb4f760ef..b2d6cad25b6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -77,7 +77,7 @@ configuration_option_enum! { TypeDensity: // No spaces around "=" and "+" Compressed, // Spaces around " = " and " + " - WhiteSpace, + Wide, } impl Density { @@ -285,7 +285,7 @@ create_config! { fn_args_density: Density, Density::Tall, "Argument density in functions"; fn_args_layout: StructLitStyle, StructLitStyle::Visual, "Layout of function arguments"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; - type_punctuation_density: TypeDensity, TypeDensity::WhiteSpace, + type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; // Should we at least try to put the where clause on the same line as the rest of the // function decl? diff --git a/src/types.rs b/src/types.rs index 5500cdecfc0..32ae4689414 100644 --- a/src/types.rs +++ b/src/types.rs @@ -425,10 +425,10 @@ impl Rewrite for ast::TyParam { result.push_str(&bounds); } if let Some(ref def) = self.default { - let eq_str = if context.config.type_punctuation_density == TypeDensity::Compressed { - "=" - } else { - " = " + + let eq_str = match context.config.type_punctuation_density { + TypeDensity::Compressed => "=", + TypeDensity::Wide => " = ", }; result.push_str(eq_str); let budget = try_opt!(width.checked_sub(result.len())); @@ -473,11 +473,9 @@ impl Rewrite for ast::Ty { ast::TyObjectSum(ref ty, ref bounds) => { let ty_str = try_opt!(ty.rewrite(context, width, offset)); let overhead = ty_str.len() + 3; - let plus_str = if context.config.type_punctuation_density == - TypeDensity::Compressed { - "+" - } else { - " + " + let plus_str = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", }; Some(format!("{}{}{}", ty_str, -- cgit 1.4.1-3-g733a5 From 4f8938c616af167e47a05abafdfa67eed5f13533 Mon Sep 17 00:00:00 2001 From: "Victor M. Suarez" Date: Tue, 12 Jan 2016 18:12:48 -0500 Subject: Allow for setting of write-mode via config file. FIxes #215 Also from @marcusklaas: Refactor code output functions Specifically, `write_all_files` no longer returns a HashMap. It would sometimes contain items, and sometimes be empty. When "fixed" newlines are required, this must now be done with a separate call. The tests use this strategy and should now pass! --- src/bin/rustfmt.rs | 6 ++-- src/config.rs | 20 ++++++++++++ src/filemap.rs | 92 +++++++++++++++++++++++------------------------------ src/lib.rs | 57 ++++++++++----------------------- src/missed_spans.rs | 2 +- src/visitor.rs | 4 +-- tests/system.rs | 21 ++++++++---- 7 files changed, 97 insertions(+), 105 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 3e369e1ef23..c795d529409 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,8 +17,8 @@ extern crate toml; extern crate env_logger; extern crate getopts; -use rustfmt::{WriteMode, run, run_from_stdin}; -use rustfmt::config::Config; +use rustfmt::{run, run_from_stdin}; +use rustfmt::config::{Config, WriteMode}; use std::env; use std::fs::{self, File}; @@ -216,7 +216,7 @@ fn determine_operation(matches: &Matches) -> Operation { Err(..) => return Operation::InvalidInput("Unrecognized write mode".into()), } } - None => WriteMode::Replace, + None => WriteMode::Default, }; let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); diff --git a/src/config.rs b/src/config.rs index 7c8505e5e09..4576ecc5d2a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -120,6 +120,24 @@ configuration_option_enum! { ReportTactic: Never, } +configuration_option_enum! { WriteMode: + // Used internally to represent when no option is given + // Treated as Replace. + Default, + // Backsup the original file and overwrites the orignal. + Replace, + // Overwrites original file without backup. + Overwrite, + // Write the output to stdout. + Display, + // Write the diff to stdout. + Diff, + // Display how much of the input file was processed + Coverage, + // Unfancy stdout + Plain, +} + // This trait and the following impl blocks are there so that we an use // UCFS inside the get_docs() function on types for configs. pub trait ConfigType { @@ -323,4 +341,6 @@ create_config! { match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; + write_mode: WriteMode, WriteMode::Default, + "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; } diff --git a/src/filemap.rs b/src/filemap.rs index 95ae95e66bc..b518eaaa344 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -15,10 +15,9 @@ use strings::string_buffer::StringBuffer; use std::collections::HashMap; use std::fs::{self, File}; -use std::io::{self, Write, Read, stdout}; +use std::io::{self, Write, Read, stdout, BufWriter}; -use WriteMode; -use config::{NewlineStyle, Config}; +use config::{NewlineStyle, Config, WriteMode}; use rustfmt_diff::{make_diff, print_diff}; // A map of the files of a crate, with their new content @@ -34,56 +33,55 @@ pub fn append_newlines(file_map: &mut FileMap) { pub fn write_all_files(file_map: &FileMap, mode: WriteMode, config: &Config) - -> Result<(HashMap), io::Error> { - let mut result = HashMap::new(); + -> Result<(), io::Error> { for filename in file_map.keys() { - let one_result = try!(write_file(&file_map[filename], filename, mode, config)); - if let Some(r) = one_result { - result.insert(filename.clone(), r); - } + try!(write_file(&file_map[filename], filename, mode, config)); } - Ok(result) + Ok(()) } -pub fn write_file(text: &StringBuffer, - filename: &str, - mode: WriteMode, - config: &Config) - -> Result, io::Error> { - - // prints all newlines either as `\n` or as `\r\n` - fn write_system_newlines(mut writer: T, +// Prints all newlines either as `\n` or as `\r\n`. +pub fn write_system_newlines(writer: T, text: &StringBuffer, config: &Config) -> Result<(), io::Error> - where T: Write - { - let style = if config.newline_style == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } + where T: Write +{ + // Buffer output, since we're writing a since char at a time. + let mut writer = BufWriter::new(writer); + + let style = if config.newline_style == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows } else { - config.newline_style - }; - - match style { - NewlineStyle::Unix => write!(writer, "{}", text), - NewlineStyle::Windows => { - for (c, _) in text.chars() { - match c { - '\n' => try!(write!(writer, "\r\n")), - '\r' => continue, - c => try!(write!(writer, "{}", c)), - } + NewlineStyle::Unix + } + } else { + config.newline_style + }; + + match style { + NewlineStyle::Unix => write!(writer, "{}", text), + NewlineStyle::Windows => { + for (c, _) in text.chars() { + match c { + '\n' => try!(write!(writer, "\r\n")), + '\r' => continue, + c => try!(write!(writer, "{}", c)), } - Ok(()) } - NewlineStyle::Native => unreachable!(), + Ok(()) } + NewlineStyle::Native => unreachable!(), } +} + +pub fn write_file(text: &StringBuffer, + filename: &str, + mode: WriteMode, + config: &Config) + -> Result, io::Error> { fn source_and_formatted_text(text: &StringBuffer, filename: &str, @@ -123,11 +121,6 @@ pub fn write_file(text: &StringBuffer, let file = try!(File::create(filename)); try!(write_system_newlines(file, text, config)); } - WriteMode::NewFile(extn) => { - let filename = filename.to_owned() + "." + extn; - let file = try!(File::create(&filename)); - try!(write_system_newlines(file, text, config)); - } WriteMode::Plain => { let stdout = stdout(); let stdout = stdout.lock(); @@ -146,13 +139,8 @@ pub fn write_file(text: &StringBuffer, |line_num| format!("\nDiff at line {}:", line_num)); } } - WriteMode::Return => { - // io::Write is not implemented for String, working around with - // Vec - let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); - // won't panic, we are writing correct utf8 - return Ok(Some(String::from_utf8(v).unwrap())); + WriteMode::Default => { + unreachable!("The WriteMode should NEVER Be default at this point!"); } } diff --git a/src/lib.rs b/src/lib.rs index 3ed7c3cad8c..fccc0f0934c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,12 +34,11 @@ use std::ops::{Add, Sub}; use std::path::Path; use std::collections::HashMap; use std::fmt; -use std::str::FromStr; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; use visitor::FmtVisitor; -use config::Config; +use config::{Config, WriteMode}; #[macro_use] mod utils; @@ -187,42 +186,6 @@ impl Sub for Indent { } } -#[derive(Copy, Clone)] -pub enum WriteMode { - // Backsup the original file and overwrites the orignal. - Replace, - // Overwrites original file without backup. - Overwrite, - // str is the extension of the new file. - NewFile(&'static str), - // Write the output to stdout. - Display, - // Write the diff to stdout. - Diff, - // Return the result as a mapping from filenames to Strings. - Return, - // Display how much of the input file was processed - Coverage, - // Unfancy stdout - Plain, -} - -impl FromStr for WriteMode { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "replace" => Ok(WriteMode::Replace), - "display" => Ok(WriteMode::Display), - "overwrite" => Ok(WriteMode::Overwrite), - "diff" => Ok(WriteMode::Diff), - "coverage" => Ok(WriteMode::Coverage), - "plain" => Ok(WriteMode::Plain), - _ => Err(()), - } - } -} - pub enum ErrorKind { // Line has exceeded character limit LineOverflow, @@ -445,16 +408,27 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { file_map } +// Make sure that we are using the correct WriteMode, +// preferring what is passed as an argument +fn check_write_mode(arg: WriteMode, config: WriteMode) -> WriteMode { + match (arg, config) { + (WriteMode::Default, WriteMode::Default) => WriteMode::Replace, + (WriteMode::Default, mode) => mode, + (mode, _) => mode, + } +} + // args are the arguments passed on the command line, generally passed through // to the compiler. // write_mode determines what happens to the result of running rustfmt, see // WriteMode. pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { - let mut result = format(file, config, write_mode); + let mode = check_write_mode(write_mode, config.write_mode); + let mut result = format(file, config, mode); print!("{}", fmt_lines(&mut result, config)); - let write_result = filemap::write_all_files(&result, write_mode, config); + let write_result = filemap::write_all_files(&result, mode, config); if let Err(msg) = write_result { println!("Error writing files: {}", msg); @@ -462,7 +436,8 @@ pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { } // Similar to run, but takes an input String instead of a file to format -pub fn run_from_stdin(input: String, mode: WriteMode, config: &Config) { +pub fn run_from_stdin(input: String, write_mode: WriteMode, config: &Config) { + let mode = check_write_mode(write_mode, config.write_mode); let mut result = format_string(input, config, mode); fmt_lines(&mut result, config); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 67661143ddf..cd69b6dcc80 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use WriteMode; +use config::WriteMode; use visitor::FmtVisitor; use syntax::codemap::{self, BytePos, Span, Pos}; use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; diff --git a/src/visitor.rs b/src/visitor.rs index f0efde9de64..1f7de66f91c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -15,9 +15,9 @@ use syntax::visit; use strings::string_buffer::StringBuffer; -use {Indent, WriteMode}; +use Indent; use utils; -use config::Config; +use config::{Config, WriteMode}; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; diff --git a/tests/system.rs b/tests/system.rs index d6f1ba806f5..378998e30a9 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -19,7 +19,8 @@ use std::io::{self, Read, BufRead, BufReader}; use std::path::Path; use rustfmt::*; -use rustfmt::config::{Config, ReportTactic}; +use rustfmt::filemap::write_system_newlines; +use rustfmt::config::{Config, ReportTactic, WriteMode}; use rustfmt::rustfmt_diff::*; static DIFF_CONTEXT_SIZE: usize = 3; @@ -43,7 +44,7 @@ fn system_tests() { // Turn a DirEntry into a String that represents the relative path to the // file. let files = files.map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Return); + let (_reports, count, fails) = check_files(files, WriteMode::Default); // Display results. println!("Ran {} system tests.", count); @@ -71,7 +72,7 @@ fn idempotence_tests() { .ok() .expect("Couldn't read target dir.") .map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Return); + let (_reports, count, fails) = check_files(files, WriteMode::Default); // Display results. println!("Ran {} idempotent tests.", count); @@ -90,7 +91,7 @@ fn self_tests() { // Hack because there's no `IntoIterator` impl for `[T; N]`. let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); - let (reports, count, fails) = check_files(files, WriteMode::Return); + let (reports, count, fails) = check_files(files, WriteMode::Default); let mut warnings = 0; // Display results. @@ -162,8 +163,16 @@ pub fn idempotent_check(filename: String, let mut file_map = format(Path::new(&filename), &config, write_mode); let format_report = fmt_lines(&mut file_map, &config); - // Won't panic, as we're not doing any IO. - let write_result = filemap::write_all_files(&file_map, WriteMode::Return, &config).unwrap(); + let mut write_result = HashMap::new(); + for (filename, text) in file_map.iter() { + let mut v = Vec::new(); + // Won't panic, as we're not doing any IO. + write_system_newlines(&mut v, text, &config).unwrap(); + // Won't panic, we are writing correct utf8. + let one_result = String::from_utf8(v).unwrap(); + write_result.insert(filename.clone(), one_result); + } + let target = sig_comments.get("target").map(|x| &(*x)[..]); handle_result(write_result, target, write_mode).map(|_| format_report) -- cgit 1.4.1-3-g733a5 From 0c9f27fe5ec8d80bbbd939a3fb30070f993d7044 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 27 Dec 2015 23:13:32 -0500 Subject: Start hacking checkstyle output in. checkstyle now shows up on the option parser, and the code still compiles/passes tests. Next up will be outputing the XML to stdout. --- src/bin/rustfmt.rs | 2 +- src/config.rs | 2 ++ src/filemap.rs | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index c795d529409..a8a19d96bc7 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -90,7 +90,7 @@ fn execute() -> i32 { opts.optopt("", "write-mode", "mode to write in (not usable when piping from stdin)", - "[replace|overwrite|display|diff|coverage]"); + "[replace|overwrite|display|diff|coverage|checkstyle]"); opts.optflag("", "skip-children", "don't reformat child modules"); opts.optflag("", diff --git a/src/config.rs b/src/config.rs index 4576ecc5d2a..5b6a5e05cf5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -136,6 +136,8 @@ configuration_option_enum! { WriteMode: Coverage, // Unfancy stdout Plain, + // Output a checkstyle XML file. + Checkstyle, } // This trait and the following impl blocks are there so that we an use diff --git a/src/filemap.rs b/src/filemap.rs index b518eaaa344..b22ca7b9b80 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -38,6 +38,7 @@ pub fn write_all_files(file_map: &FileMap, try!(write_file(&file_map[filename], filename, mode, config)); } + // Output trailers for write mode. Ok(()) } @@ -142,6 +143,19 @@ pub fn write_file(text: &StringBuffer, WriteMode::Default => { unreachable!("The WriteMode should NEVER Be default at this point!"); } + WriteMode::Checkstyle => { + // Generate the diff for the current file. + // Output the XML tags for the lines that are different. + // Use the new text as 'should be X'. + } + WriteMode::Return => { + // io::Write is not implemented for String, working around with + // Vec + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text, config)); + // won't panic, we are writing correct utf8 + return Ok(Some(String::from_utf8(v).unwrap())); + } } Ok(None) -- cgit 1.4.1-3-g733a5 From d188854e133ab704b4c122d43c4c3621cf12caf5 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 29 Dec 2015 23:54:35 -0500 Subject: Hack together checkstyle output that compiles. I'm not sure it does something useful yet though. --- src/filemap.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index b22ca7b9b80..cecad3f8477 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -18,7 +18,7 @@ use std::fs::{self, File}; use std::io::{self, Write, Read, stdout, BufWriter}; use config::{NewlineStyle, Config, WriteMode}; -use rustfmt_diff::{make_diff, print_diff}; +use rustfmt_diff::{make_diff, print_diff, Mismatch, DiffLine}; // A map of the files of a crate, with their new content pub type FileMap = HashMap; @@ -34,11 +34,70 @@ pub fn write_all_files(file_map: &FileMap, mode: WriteMode, config: &Config) -> Result<(), io::Error> { + output_heading(&file_map, mode).ok(); for filename in file_map.keys() { try!(write_file(&file_map[filename], filename, mode, config)); } + output_trailing(&file_map, mode).ok(); - // Output trailers for write mode. + Ok(()) +} + +pub fn output_heading(file_map: &FileMap, + mode: WriteMode) -> Result<(), io::Error> { + let stdout = stdout(); + let mut stdout = stdout.lock(); + match mode { + WriteMode::Checkstyle => { + let mut xml_heading = String::new(); + xml_heading.push_str(""); + xml_heading.push_str("\n"); + xml_heading.push_str(""); + try!(write!(stdout, "{}", xml_heading)); + Ok(()) + } + _ => { + Ok(()) + } + } +} + +pub fn output_trailing(file_map: &FileMap, + mode: WriteMode) -> Result<(), io::Error> { + let stdout = stdout(); + let mut stdout = stdout.lock(); + match mode { + WriteMode::Checkstyle => { + let mut xml_tail = String::new(); + xml_tail.push_str(""); + try!(write!(stdout, "{}", xml_tail)); + Ok(()) + } + _ => { + Ok(()) + } + } +} + +pub fn output_checkstyle_file(mut writer: T, + filename: &str, + diff: Vec) -> Result<(), io::Error> + where T: Write +{ + try!(write!(writer, "", filename)); + for mismatch in diff { + for line in mismatch.lines { + match line { + DiffLine::Expected(ref str) => { + try!(write!(writer, "", mismatch.line_number, str)); + } + _ => { + // Do nothing with context and expected. + } + } + } + } + try!(write!(writer, "")); Ok(()) } @@ -144,9 +203,18 @@ pub fn write_file(text: &StringBuffer, unreachable!("The WriteMode should NEVER Be default at this point!"); } WriteMode::Checkstyle => { + let stdout = stdout(); + let stdout = stdout.lock(); // Generate the diff for the current file. + let mut f = try!(File::open(filename)); + let mut ori_text = String::new(); + try!(f.read_to_string(&mut ori_text)); + let mut v = Vec::new(); + try!(write_system_newlines(&mut v, text, config)); + let fmt_text = String::from_utf8(v).unwrap(); + let diff = make_diff(&ori_text, &fmt_text, 3); // Output the XML tags for the lines that are different. - // Use the new text as 'should be X'. + output_checkstyle_file(stdout, filename, diff).unwrap(); } WriteMode::Return => { // io::Write is not implemented for String, working around with -- cgit 1.4.1-3-g733a5 From 309f284dfbd15d3d6a019e8c81b74ac8b3a5c862 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 31 Dec 2015 00:33:07 -0500 Subject: Fix formatting errors. --- src/filemap.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index cecad3f8477..56e40e73c78 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -43,8 +43,7 @@ pub fn write_all_files(file_map: &FileMap, Ok(()) } -pub fn output_heading(file_map: &FileMap, - mode: WriteMode) -> Result<(), io::Error> { +pub fn output_heading(file_map: &FileMap, mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); match mode { @@ -56,14 +55,11 @@ pub fn output_heading(file_map: &FileMap, try!(write!(stdout, "{}", xml_heading)); Ok(()) } - _ => { - Ok(()) - } + _ => Ok(()), } } -pub fn output_trailing(file_map: &FileMap, - mode: WriteMode) -> Result<(), io::Error> { +pub fn output_trailing(file_map: &FileMap, mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); match mode { @@ -73,15 +69,14 @@ pub fn output_trailing(file_map: &FileMap, try!(write!(stdout, "{}", xml_tail)); Ok(()) } - _ => { - Ok(()) - } + _ => Ok(()), } } pub fn output_checkstyle_file(mut writer: T, filename: &str, - diff: Vec) -> Result<(), io::Error> + diff: Vec) + -> Result<(), io::Error> where T: Write { try!(write!(writer, "", filename)); @@ -89,7 +84,11 @@ pub fn output_checkstyle_file(mut writer: T, for line in mismatch.lines { match line { DiffLine::Expected(ref str) => { - try!(write!(writer, "", mismatch.line_number, str)); + try!(write!(writer, + "", + mismatch.line_number, + str)); } _ => { // Do nothing with context and expected. -- cgit 1.4.1-3-g733a5 From c3632befb5f733a1a0cd8f42c6d0b8dbca100680 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 31 Dec 2015 00:33:51 -0500 Subject: Remove unused argument. --- src/filemap.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 56e40e73c78..f9e927f03b2 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -34,16 +34,16 @@ pub fn write_all_files(file_map: &FileMap, mode: WriteMode, config: &Config) -> Result<(), io::Error> { - output_heading(&file_map, mode).ok(); + output_heading(mode).ok(); for filename in file_map.keys() { try!(write_file(&file_map[filename], filename, mode, config)); } - output_trailing(&file_map, mode).ok(); + output_trailing(mode).ok(); Ok(()) } -pub fn output_heading(file_map: &FileMap, mode: WriteMode) -> Result<(), io::Error> { +pub fn output_heading(mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); match mode { @@ -59,7 +59,7 @@ pub fn output_heading(file_map: &FileMap, mode: WriteMode) -> Result<(), io::Err } } -pub fn output_trailing(file_map: &FileMap, mode: WriteMode) -> Result<(), io::Error> { +pub fn output_trailing(mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); match mode { -- cgit 1.4.1-3-g733a5 From de10545906899084162b6511f15771db491551cc Mon Sep 17 00:00:00 2001 From: Mark Story Date: Sun, 3 Jan 2016 23:17:49 -0500 Subject: Encode XML entities. --- src/filemap.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index f9e927f03b2..212b95dd25b 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -84,11 +84,13 @@ pub fn output_checkstyle_file(mut writer: T, for line in mismatch.lines { match line { DiffLine::Expected(ref str) => { + let message = xml_escape_str(&str); + // TODO XML encode str here. try!(write!(writer, "", mismatch.line_number, - str)); + message)); } _ => { // Do nothing with context and expected. @@ -100,6 +102,23 @@ pub fn output_checkstyle_file(mut writer: T, Ok(()) } +// Convert special characters into XML entities. +// This is needed for checkstyle output. +fn xml_escape_str(string: &str) -> String { + let mut out = String::new(); + for c in string.chars() { + match c { + '<' => out.push_str("<"), + '>' => out.push_str(">"), + '"' => out.push_str("""), + '\'' => out.push_str("'"), + '&' => out.push_str("&"), + _ => out.push(c), + } + } + out +} + // Prints all newlines either as `\n` or as `\r\n`. pub fn write_system_newlines(writer: T, text: &StringBuffer, -- cgit 1.4.1-3-g733a5 From 3c968e1e38781001b2023ea6921287a16a3e7b02 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Fri, 8 Jan 2016 22:38:27 -0500 Subject: Update based on pull request feedback. * Extract duplicated logic. * Make checkstyle errors into warnings. --- src/filemap.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 212b95dd25b..436f5501882 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -87,7 +87,7 @@ pub fn output_checkstyle_file(mut writer: T, let message = xml_escape_str(&str); // TODO XML encode str here. try!(write!(writer, - "", mismatch.line_number, message)); @@ -174,6 +174,14 @@ pub fn write_file(text: &StringBuffer, Ok((ori_text, fmt_text)) } + fn create_diff(filename: &str, + text: &StringBuffer, + config: &Config) + -> Result, io::Error> { + let ori_text, fmt_text = try!(source_and_formatted_text(text, filename, config)); + Ok(make_diff(&ori_text, &fmt_text, 3)) + } + match mode { WriteMode::Replace => { if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { @@ -223,16 +231,9 @@ pub fn write_file(text: &StringBuffer, WriteMode::Checkstyle => { let stdout = stdout(); let stdout = stdout.lock(); - // Generate the diff for the current file. - let mut f = try!(File::open(filename)); - let mut ori_text = String::new(); - try!(f.read_to_string(&mut ori_text)); - let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); - let fmt_text = String::from_utf8(v).unwrap(); - let diff = make_diff(&ori_text, &fmt_text, 3); + let diff = try!(create_diff(filename, text, config)); // Output the XML tags for the lines that are different. - output_checkstyle_file(stdout, filename, diff).unwrap(); + try!(output_checkstyle_file(stdout, filename, diff)); } WriteMode::Return => { // io::Write is not implemented for String, working around with -- cgit 1.4.1-3-g733a5 From 58410ddd9385b9570ba65744096ea6bedbb1e040 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 13 Jan 2016 00:22:30 -0500 Subject: Extract checkstyle output into a separate module. Rename functions a bit now that they are specific to checkstyle output. --- src/checkstyle.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/filemap.rs | 84 ++++------------------------------------------------ src/lib.rs | 1 + 3 files changed, 94 insertions(+), 79 deletions(-) create mode 100644 src/checkstyle.rs (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs new file mode 100644 index 00000000000..1eb74a99bbf --- /dev/null +++ b/src/checkstyle.rs @@ -0,0 +1,88 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +use rustfmt_diff::{Mismatch, DiffLine}; +use std::io::{self, Write, Read, stdout}; +use WriteMode; + + +pub fn output_heading(mode: WriteMode) -> Result<(), io::Error> { + let stdout = stdout(); + let mut stdout = stdout.lock(); + match mode { + WriteMode::Checkstyle => { + let mut xml_heading = String::new(); + xml_heading.push_str(""); + xml_heading.push_str("\n"); + xml_heading.push_str(""); + try!(write!(stdout, "{}", xml_heading)); + Ok(()) + } + _ => Ok(()), + } +} + +pub fn output_footing(mode: WriteMode) -> Result<(), io::Error> { + let stdout = stdout(); + let mut stdout = stdout.lock(); + match mode { + WriteMode::Checkstyle => { + let mut xml_tail = String::new(); + xml_tail.push_str(""); + try!(write!(stdout, "{}", xml_tail)); + Ok(()) + } + _ => Ok(()), + } +} + +pub fn output_checkstyle_file(mut writer: T, + filename: &str, + diff: Vec) + -> Result<(), io::Error> + where T: Write +{ + try!(write!(writer, "", filename)); + for mismatch in diff { + for line in mismatch.lines { + match line { + DiffLine::Expected(ref str) => { + let message = xml_escape_str(&str); + try!(write!(writer, + "", + mismatch.line_number, + message)); + } + _ => { + // Do nothing with context and expected. + } + } + } + } + try!(write!(writer, "")); + Ok(()) +} + +// Convert special characters into XML entities. +// This is needed for checkstyle output. +fn xml_escape_str(string: &str) -> String { + let mut out = String::new(); + for c in string.chars() { + match c { + '<' => out.push_str("<"), + '>' => out.push_str(">"), + '"' => out.push_str("""), + '\'' => out.push_str("'"), + '&' => out.push_str("&"), + _ => out.push(c), + } + } + out +} diff --git a/src/filemap.rs b/src/filemap.rs index 436f5501882..92d4267f6e1 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -18,7 +18,8 @@ use std::fs::{self, File}; use std::io::{self, Write, Read, stdout, BufWriter}; use config::{NewlineStyle, Config, WriteMode}; -use rustfmt_diff::{make_diff, print_diff, Mismatch, DiffLine}; +use rustfmt_diff::{make_diff, print_diff, Mismatch}; +use checkstyle::{output_heading, output_footing, output_checkstyle_file}; // A map of the files of a crate, with their new content pub type FileMap = HashMap; @@ -38,86 +39,11 @@ pub fn write_all_files(file_map: &FileMap, for filename in file_map.keys() { try!(write_file(&file_map[filename], filename, mode, config)); } - output_trailing(mode).ok(); + output_footing(mode).ok(); Ok(()) } -pub fn output_heading(mode: WriteMode) -> Result<(), io::Error> { - let stdout = stdout(); - let mut stdout = stdout.lock(); - match mode { - WriteMode::Checkstyle => { - let mut xml_heading = String::new(); - xml_heading.push_str(""); - xml_heading.push_str("\n"); - xml_heading.push_str(""); - try!(write!(stdout, "{}", xml_heading)); - Ok(()) - } - _ => Ok(()), - } -} - -pub fn output_trailing(mode: WriteMode) -> Result<(), io::Error> { - let stdout = stdout(); - let mut stdout = stdout.lock(); - match mode { - WriteMode::Checkstyle => { - let mut xml_tail = String::new(); - xml_tail.push_str(""); - try!(write!(stdout, "{}", xml_tail)); - Ok(()) - } - _ => Ok(()), - } -} - -pub fn output_checkstyle_file(mut writer: T, - filename: &str, - diff: Vec) - -> Result<(), io::Error> - where T: Write -{ - try!(write!(writer, "", filename)); - for mismatch in diff { - for line in mismatch.lines { - match line { - DiffLine::Expected(ref str) => { - let message = xml_escape_str(&str); - // TODO XML encode str here. - try!(write!(writer, - "", - mismatch.line_number, - message)); - } - _ => { - // Do nothing with context and expected. - } - } - } - } - try!(write!(writer, "")); - Ok(()) -} - -// Convert special characters into XML entities. -// This is needed for checkstyle output. -fn xml_escape_str(string: &str) -> String { - let mut out = String::new(); - for c in string.chars() { - match c { - '<' => out.push_str("<"), - '>' => out.push_str(">"), - '"' => out.push_str("""), - '\'' => out.push_str("'"), - '&' => out.push_str("&"), - _ => out.push(c), - } - } - out -} // Prints all newlines either as `\n` or as `\r\n`. pub fn write_system_newlines(writer: T, @@ -178,8 +104,8 @@ pub fn write_file(text: &StringBuffer, text: &StringBuffer, config: &Config) -> Result, io::Error> { - let ori_text, fmt_text = try!(source_and_formatted_text(text, filename, config)); - Ok(make_diff(&ori_text, &fmt_text, 3)) + let (ori, fmt) = try!(source_and_formatted_text(text, filename, config)); + Ok(make_diff(&ori, &fmt, 3)) } match mode { diff --git a/src/lib.rs b/src/lib.rs index fccc0f0934c..6d60c0f278d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,6 +45,7 @@ mod utils; pub mod config; pub mod filemap; mod visitor; +mod checkstyle; mod items; mod missed_spans; mod lists; -- cgit 1.4.1-3-g733a5 From add80569ff1a701304bf3b3ef58feb2d76976113 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Wed, 13 Jan 2016 20:56:35 -0500 Subject: Use PartialEq/Eq implementation instead of match. Also cleanup from rebasing onto master. --- src/checkstyle.rs | 32 +++++++++++++------------------- src/filemap.rs | 8 -------- 2 files changed, 13 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 1eb74a99bbf..2a276dce120 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -9,37 +9,31 @@ // except according to those terms. use rustfmt_diff::{Mismatch, DiffLine}; use std::io::{self, Write, Read, stdout}; -use WriteMode; +use config::WriteMode; pub fn output_heading(mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); - match mode { - WriteMode::Checkstyle => { - let mut xml_heading = String::new(); - xml_heading.push_str(""); - xml_heading.push_str("\n"); - xml_heading.push_str(""); - try!(write!(stdout, "{}", xml_heading)); - Ok(()) - } - _ => Ok(()), + if mode == WriteMode::Checkstyle { + let mut xml_heading = String::new(); + xml_heading.push_str(""); + xml_heading.push_str("\n"); + xml_heading.push_str(""); + try!(write!(stdout, "{}", xml_heading)); } + Ok(()) } pub fn output_footing(mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); - match mode { - WriteMode::Checkstyle => { - let mut xml_tail = String::new(); - xml_tail.push_str(""); - try!(write!(stdout, "{}", xml_tail)); - Ok(()) - } - _ => Ok(()), + if mode == WriteMode::Checkstyle { + let mut xml_tail = String::new(); + xml_tail.push_str(""); + try!(write!(stdout, "{}", xml_tail)); } + Ok(()) } pub fn output_checkstyle_file(mut writer: T, diff --git a/src/filemap.rs b/src/filemap.rs index 92d4267f6e1..a2cba78ae96 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -161,14 +161,6 @@ pub fn write_file(text: &StringBuffer, // Output the XML tags for the lines that are different. try!(output_checkstyle_file(stdout, filename, diff)); } - WriteMode::Return => { - // io::Write is not implemented for String, working around with - // Vec - let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); - // won't panic, we are writing correct utf8 - return Ok(Some(String::from_utf8(v).unwrap())); - } } Ok(None) -- cgit 1.4.1-3-g733a5 From f0ca7aec24639eb9856472f4be66d5b21c78d618 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 14 Jan 2016 20:26:15 +1300 Subject: Fix an off-by-one error due to the comma in a struct lit field Also allows splitting the field expression on a new line after the field name. Fixes #698 --- src/expr.rs | 20 ++++++++++++++++++-- src/items.rs | 2 +- tests/source/struct_lits.rs | 9 +++++++++ tests/target/struct_lits.rs | 10 ++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 25c86363921..8e76001e731 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1372,6 +1372,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // Foo { a: Foo } - indent is +3, width is -5. let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); + // The 1 taken from the v_budget is for the comma. let (indent, v_budget) = match context.config.struct_lit_style { StructLitStyle::Visual => (offset + path_str.len() + 3, h_budget), StructLitStyle::Block => { @@ -1416,7 +1417,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| { match *item { StructLitField::Regular(ref field) => { - rewrite_field(inner_context, &field, v_budget, indent) + rewrite_field(inner_context, + &field, + v_budget.checked_sub(1).unwrap_or(0), + indent) } StructLitField::Base(ref expr) => { // 2 = .. @@ -1502,7 +1506,19 @@ fn rewrite_field(context: &RewriteContext, let expr = field.expr.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); - expr.map(|s| format!("{}: {}", name, s)) + + match expr { + Some(e) => Some(format!("{}: {}", name, e)), + None => { + let expr_offset = offset.block_indent(&context.config); + let expr = field.expr.rewrite(context, + try_opt!(context.config + .max_width + .checked_sub(expr_offset.width())), + expr_offset); + expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) + } + } } pub fn rewrite_tuple<'a, I>(context: &RewriteContext, diff --git a/src/items.rs b/src/items.rs index 85fcb2bf7b1..1e1b6ca8076 100644 --- a/src/items.rs +++ b/src/items.rs @@ -663,7 +663,7 @@ fn format_struct_struct(context: &RewriteContext, } let item_indent = offset.block_indent(context.config); - // 2 = "," + // 1 = "," let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 1)); let items = itemize_list(context.codemap, diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 0c30d721c4d..c62a355c5dd 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -114,3 +114,12 @@ fn issue491() { Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ e: eeeeeeeee }; } + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index a08222f8f13..299afb422ec 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -149,3 +149,13 @@ fn issue491() { e: eeeeeeeee, }; } + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} -- cgit 1.4.1-3-g733a5 From 5632831bd17ca662a61af090a12f17461ca5fe05 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Thu, 14 Jan 2016 22:04:24 -0500 Subject: Clean up function names for checkstyle output. --- src/checkstyle.rs | 4 ++-- src/filemap.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 2a276dce120..e25bfc03ba4 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -12,7 +12,7 @@ use std::io::{self, Write, Read, stdout}; use config::WriteMode; -pub fn output_heading(mode: WriteMode) -> Result<(), io::Error> { +pub fn output_header(mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); if mode == WriteMode::Checkstyle { @@ -25,7 +25,7 @@ pub fn output_heading(mode: WriteMode) -> Result<(), io::Error> { Ok(()) } -pub fn output_footing(mode: WriteMode) -> Result<(), io::Error> { +pub fn output_footer(mode: WriteMode) -> Result<(), io::Error> { let stdout = stdout(); let mut stdout = stdout.lock(); if mode == WriteMode::Checkstyle { diff --git a/src/filemap.rs b/src/filemap.rs index a2cba78ae96..dabf7ade3e1 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -19,7 +19,7 @@ use std::io::{self, Write, Read, stdout, BufWriter}; use config::{NewlineStyle, Config, WriteMode}; use rustfmt_diff::{make_diff, print_diff, Mismatch}; -use checkstyle::{output_heading, output_footing, output_checkstyle_file}; +use checkstyle::{output_header, output_footer, output_checkstyle_file}; // A map of the files of a crate, with their new content pub type FileMap = HashMap; @@ -35,11 +35,11 @@ pub fn write_all_files(file_map: &FileMap, mode: WriteMode, config: &Config) -> Result<(), io::Error> { - output_heading(mode).ok(); + output_header(mode).ok(); for filename in file_map.keys() { try!(write_file(&file_map[filename], filename, mode, config)); } - output_footing(mode).ok(); + output_footer(mode).ok(); Ok(()) } -- cgit 1.4.1-3-g733a5 From d8c6f5954ace9890bcdbe46bb618c9465dd1fd71 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Tue, 19 Jan 2016 00:02:21 -0500 Subject: Update checkstyle write mode to take Write arguments. By accepting Write traits we can write tests using StringBuffer. --- src/checkstyle.rs | 18 +++++++++--------- src/filemap.rs | 35 +++++++++++++++++++---------------- src/lib.rs | 8 +++++--- 3 files changed, 33 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index e25bfc03ba4..02e214864fa 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -8,30 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use rustfmt_diff::{Mismatch, DiffLine}; -use std::io::{self, Write, Read, stdout}; +use std::io::{self, Write, Read}; use config::WriteMode; -pub fn output_header(mode: WriteMode) -> Result<(), io::Error> { - let stdout = stdout(); - let mut stdout = stdout.lock(); +pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> + where T: Write +{ if mode == WriteMode::Checkstyle { let mut xml_heading = String::new(); xml_heading.push_str(""); xml_heading.push_str("\n"); xml_heading.push_str(""); - try!(write!(stdout, "{}", xml_heading)); + try!(write!(out, "{}", xml_heading)); } Ok(()) } -pub fn output_footer(mode: WriteMode) -> Result<(), io::Error> { - let stdout = stdout(); - let mut stdout = stdout.lock(); +pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> + where T: Write +{ if mode == WriteMode::Checkstyle { let mut xml_tail = String::new(); xml_tail.push_str(""); - try!(write!(stdout, "{}", xml_tail)); + try!(write!(out, "{}", xml_tail)); } Ok(()) } diff --git a/src/filemap.rs b/src/filemap.rs index dabf7ade3e1..61ad573f702 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -31,15 +31,18 @@ pub fn append_newlines(file_map: &mut FileMap) { } } -pub fn write_all_files(file_map: &FileMap, - mode: WriteMode, - config: &Config) - -> Result<(), io::Error> { - output_header(mode).ok(); +pub fn write_all_files(file_map: &FileMap, + mut out: T, + mode: WriteMode, + config: &Config) + -> Result<(), io::Error> + where T: Write +{ + output_header(&mut out, mode).ok(); for filename in file_map.keys() { - try!(write_file(&file_map[filename], filename, mode, config)); + try!(write_file(&file_map[filename], filename, &mut out, mode, config)); } - output_footer(mode).ok(); + output_footer(&mut out, mode).ok(); Ok(()) } @@ -81,11 +84,14 @@ pub fn write_system_newlines(writer: T, } } -pub fn write_file(text: &StringBuffer, - filename: &str, - mode: WriteMode, - config: &Config) - -> Result, io::Error> { +pub fn write_file(text: &StringBuffer, + filename: &str, + out: &mut T, + mode: WriteMode, + config: &Config) + -> Result, io::Error> + where T: Write +{ fn source_and_formatted_text(text: &StringBuffer, filename: &str, @@ -155,11 +161,8 @@ pub fn write_file(text: &StringBuffer, unreachable!("The WriteMode should NEVER Be default at this point!"); } WriteMode::Checkstyle => { - let stdout = stdout(); - let stdout = stdout.lock(); let diff = try!(create_diff(filename, text, config)); - // Output the XML tags for the lines that are different. - try!(output_checkstyle_file(stdout, filename, diff)); + try!(output_checkstyle_file(out, filename, diff)); } } diff --git a/src/lib.rs b/src/lib.rs index 6d60c0f278d..ad9322ab649 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ use syntax::codemap::{mk_sp, Span}; use syntax::diagnostic::{EmitterWriter, Handler}; use syntax::parse::{self, ParseSess}; +use std::io::stdout; use std::ops::{Add, Sub}; use std::path::Path; use std::collections::HashMap; @@ -428,8 +429,8 @@ pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { let mut result = format(file, config, mode); print!("{}", fmt_lines(&mut result, config)); - - let write_result = filemap::write_all_files(&result, mode, config); + let out = stdout(); + let write_result = filemap::write_all_files(&result, out, mode, config); if let Err(msg) = write_result { println!("Error writing files: {}", msg); @@ -442,7 +443,8 @@ pub fn run_from_stdin(input: String, write_mode: WriteMode, config: &Config) { let mut result = format_string(input, config, mode); fmt_lines(&mut result, config); - let write_result = filemap::write_file(&result["stdin"], "stdin", mode, config); + let mut out = stdout(); + let write_result = filemap::write_file(&result["stdin"], "stdin", &mut out, mode, config); if let Err(msg) = write_result { panic!("Error writing to stdout: {}", msg); -- cgit 1.4.1-3-g733a5 From f01ed6f507849a699c5ff3f3370264e3f234c734 Mon Sep 17 00:00:00 2001 From: Kevin Yeh Date: Fri, 22 Jan 2016 13:40:26 -0600 Subject: Format item macros --- src/macros.rs | 34 +++++++++++++++++----------------- src/visitor.rs | 8 ++------ tests/source/macros.rs | 2 +- tests/target/macros.rs | 2 +- 4 files changed, 21 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 8739d234fd2..84a7e18bd85 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,7 @@ use utils::{wrap_str, span_after}; static FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; // FIXME: use the enum from libsyntax? -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq, Eq)] enum MacroStyle { Parens, Brackets, @@ -63,9 +63,7 @@ pub fn rewrite_macro(mac: &ast::Mac, original_style }; - if let MacroStyle::Braces = style { - return None; - } else if mac.node.tts.is_empty() { + if mac.node.tts.is_empty() { return if let MacroStyle::Parens = style { Some(format!("{}()", macro_name)) } else { @@ -76,22 +74,24 @@ pub fn rewrite_macro(mac: &ast::Mac, let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new()); let mut expr_vec = Vec::new(); - loop { - expr_vec.push(match parser.parse_expr() { - Ok(expr) => expr, - Err(..) => return None, - }); + if MacroStyle::Braces != style { + loop { + expr_vec.push(match parser.parse_expr() { + Ok(expr) => expr, + Err(..) => return None, + }); - match parser.token { - Token::Eof => break, - Token::Comma => (), - _ => return None, - } + match parser.token { + Token::Eof => break, + Token::Comma => (), + _ => return None, + } - let _ = parser.bump(); + let _ = parser.bump(); - if parser.token == Token::Eof { - return None; + if parser.token == Token::Eof { + return None; + } } } diff --git a/src/visitor.rs b/src/visitor.rs index 1f7de66f91c..569bacc1300 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -253,13 +253,9 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(item.span.lo); self.format_mod(module, item.vis, item.span, item.ident); } - ast::Item_::ItemMac(..) => { + ast::Item_::ItemMac(ref mac) => { self.format_missing_with_indent(item.span.lo); - let snippet = self.snippet(item.span); - self.buffer.push_str(&snippet); - self.last_pos = item.span.hi; - // FIXME: we cannot format these yet, because of a bad span. - // See rust lang issue #28424. + self.visit_mac(mac); } ast::Item_::ItemForeignMod(ref foreign_mod) => { self.format_missing_with_indent(item.span.lo); diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 5b07596fdf9..a16038ccabb 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -1,4 +1,4 @@ -itemmacro!(this, is.not() .formatted(yet)); +itemmacro!(this, is.now() .formatted(yay)); fn main() { foo! ( ); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 2bcc6f9a339..9307c8720cd 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1,4 +1,4 @@ -itemmacro!(this, is.not() .formatted(yet)); +itemmacro!(this, is.now().formatted(yay)); fn main() { foo!(); -- cgit 1.4.1-3-g733a5 From d82d3b2cd1d06bd455979512c8be06dbcf88e36f Mon Sep 17 00:00:00 2001 From: Jeremy Wazny Date: Tue, 26 Jan 2016 12:42:11 +1100 Subject: Added where_trailing_comma option. The default is 'false', since a lot of the time there's only a single predicate. --- src/config.rs | 1 + src/items.rs | 2 +- tests/config/small_tabs.toml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 5b6a5e05cf5..48b7a06e538 100644 --- a/src/config.rs +++ b/src/config.rs @@ -316,6 +316,7 @@ create_config! { where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation style of a where predicate"; + where_trailing_comma: bool, false, "Put a trailing comma on where clauses"; generics_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of generics"; struct_trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, "If there is a trailing comma on structs"; diff --git a/src/items.rs b/src/items.rs index 1e1b6ca8076..f725ccf0153 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1530,7 +1530,7 @@ fn rewrite_where_clause(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::Never, + trailing_separator: SeparatorTactic::from_bool(context.config.where_trailing_comma), indent: offset, width: budget, ends_with_newline: true, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 1681aff77b4..cb4d5da5274 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -12,6 +12,7 @@ where_density = "Tall" where_indent = "Tabbed" where_layout = "Vertical" where_pred_indent = "Visual" +where_trailing_comma = false generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" -- cgit 1.4.1-3-g733a5 From 7297bc320fa148773f1615c211429ca7dfe3332e Mon Sep 17 00:00:00 2001 From: Jeremy Wazny Date: Tue, 26 Jan 2016 15:53:04 +1100 Subject: Limit when we emit a trailing where clause comma. --- src/items.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f725ccf0153..2ff52148f6a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -491,6 +491,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - where_budget, context.config.where_density, "{", + true, None)); if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { @@ -737,6 +738,7 @@ fn format_tuple_struct(context: &RewriteContext, where_budget, Density::Compressed, ";", + false, None)) } None => "".to_owned(), @@ -818,6 +820,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, where_budget, context.config.where_density, "=", + false, Some(span.hi))); result.push_str(&where_clause_str); result.push_str(" = "); @@ -1248,6 +1251,7 @@ fn rewrite_fn_base(context: &RewriteContext, where_budget, where_density, "{", + has_body, Some(span.hi))); if last_line_width(&result) + where_clause_str.len() > context.config.max_width && @@ -1487,6 +1491,7 @@ fn rewrite_where_clause(context: &RewriteContext, width: usize, density: Density, terminator: &str, + allow_trailing_comma: bool, span_end: Option) -> Option { if where_clause.predicates.is_empty() { @@ -1526,11 +1531,12 @@ fn rewrite_where_clause(context: &RewriteContext, // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. let tactic = definitive_tactic(&item_vec, context.config.where_layout, budget); + let use_trailing_comma = allow_trailing_comma && context.config.where_trailing_comma; let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::from_bool(context.config.where_trailing_comma), + trailing_separator: SeparatorTactic::from_bool(use_trailing_comma), indent: offset, width: budget, ends_with_newline: true, @@ -1592,6 +1598,7 @@ fn format_generics(context: &RewriteContext, budget, Density::Tall, terminator, + true, Some(span.hi))); result.push_str(&where_clause_str); if !force_same_line_brace && -- cgit 1.4.1-3-g733a5 From feb09a42f508e1c9b47089f4b017c6de447e62cb Mon Sep 17 00:00:00 2001 From: DarkDrek Date: Wed, 27 Jan 2016 02:18:05 +0100 Subject: Fix #784 --- src/missed_spans.rs | 8 ++++---- tests/source/comment.rs | 2 ++ tests/target/comment.rs | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index cd69b6dcc80..c86cd62a900 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -147,11 +147,11 @@ impl<'a> FmtVisitor<'a> { if let Some('/') = subslice.chars().skip(1).next() { // Add a newline after line comments self.buffer.push_str("\n"); - } else if line_start < snippet.len() { + } else if line_start <= snippet.len() { // For other comments add a newline if there isn't one at the end already - let c = snippet[line_start..].chars().next().unwrap(); - if c != '\n' && c != '\r' { - self.buffer.push_str("\n"); + match snippet[line_start..].chars().next() { + Some('\n') | Some('\r') => (), + _ => self.buffer.push_str("\n"), } } diff --git a/tests/source/comment.rs b/tests/source/comment.rs index 714b77b081c..8cfde87f8c4 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -45,3 +45,5 @@ fn chains() { /* * random comment */ + +fn main() {/* Test */} diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 28740749c5d..98815ac5403 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -46,3 +46,7 @@ fn chains() { } // random comment + +fn main() { + // Test +} -- cgit 1.4.1-3-g733a5 From 02302d2800fe33579013a02eb7f1e7188d9a0769 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Jan 2016 19:14:08 +1300 Subject: Don't reformat strings if we don't have to. Specifically if no line exceeds the allowed width and we aren't moving the string to a new offset --- src/config.rs | 3 ++- src/expr.rs | 40 ++++++++++++++++++++++++++++++++++++---- tests/source/string-lit-2.rs | 14 ++++++++++++++ tests/source/string-lit.rs | 1 + tests/target/string-lit-2.rs | 15 +++++++++++++++ tests/target/string-lit.rs | 1 + 6 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 tests/source/string-lit-2.rs create mode 100644 tests/target/string-lit-2.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 48b7a06e538..01fc86bdbf4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -334,7 +334,8 @@ create_config! { chain_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of chain"; reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; - format_strings: bool, true, "Format string literals, or leave as is"; + format_strings: bool, true, "Format string literals where necessary"; + force_format_strings: bool, false, "Always format string literals"; chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; diff --git a/src/expr.rs b/src/expr.rs index 8e76001e731..b299f82a883 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1182,8 +1182,15 @@ fn rewrite_string_lit(context: &RewriteContext, width: usize, offset: Indent) -> Option { - if !context.config.format_strings { - return Some(context.snippet(span)); + let string_lit = context.snippet(span); + + if !context.config.format_strings && !context.config.force_format_strings { + return Some(string_lit); + } + + if !context.config.force_format_strings && + !string_requires_rewrite(context, span, &string_lit, width, offset) { + return Some(string_lit); } let fmt = StringFormat { @@ -1197,12 +1204,37 @@ fn rewrite_string_lit(context: &RewriteContext, config: context.config, }; - let string_lit = context.snippet(span); - let str_lit = &string_lit[1..string_lit.len() - 1]; // Remove the quote characters. + // Remove the quote characters. + let str_lit = &string_lit[1..string_lit.len() - 1]; rewrite_string(str_lit, &fmt) } +fn string_requires_rewrite(context: &RewriteContext, + span: Span, + string: &str, + width: usize, + offset: Indent) + -> bool { + if context.codemap.lookup_char_pos(span.lo).col.0 != offset.width() { + return true; + } + + for (i, line) in string.lines().enumerate() { + if i == 0 { + if line.len() > width { + return true; + } + } else { + if line.len() > width + offset.width() { + return true; + } + } + } + + false +} + pub fn rewrite_call(context: &RewriteContext, callee: &R, args: &[ptr::P], diff --git a/tests/source/string-lit-2.rs b/tests/source/string-lit-2.rs new file mode 100644 index 00000000000..8ba60ccac1d --- /dev/null +++ b/tests/source/string-lit-2.rs @@ -0,0 +1,14 @@ +fn main() -> &'static str { + let too_many_lines = "H\ + e\ + l\ + l\ + o"; + let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; + // Crappy formatting :-( + let change_me = "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index c89b798a0ea..ca8aa36a90d 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -1,3 +1,4 @@ +// rustfmt-force_format_strings: true // Long string literals fn main() -> &'static str { diff --git a/tests/target/string-lit-2.rs b/tests/target/string-lit-2.rs new file mode 100644 index 00000000000..08e8be8186c --- /dev/null +++ b/tests/target/string-lit-2.rs @@ -0,0 +1,15 @@ +fn main() -> &'static str { + let too_many_lines = "H\ + e\ + l\ + l\ + o"; + let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; + // Crappy formatting :-( + let change_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss + \ + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\ + j"; +} diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index b9a676c49ea..e7146a84f9e 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -1,3 +1,4 @@ +// rustfmt-force_format_strings: true // Long string literals fn main() -> &'static str { -- cgit 1.4.1-3-g733a5 From a0e85f9a5fe01b510142147e798803ac0a3c92cc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Jan 2016 19:53:41 +1300 Subject: Put empty modules on one line Fixes #463 --- src/visitor.rs | 18 +++++++++++++----- tests/target/comment2.rs | 3 +-- tests/target/comment3.rs | 3 +-- tests/target/mod-1.rs | 7 ++----- 4 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 569bacc1300..073a05ef2bc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -454,11 +454,19 @@ impl<'a> FmtVisitor<'a> { if is_internal { self.buffer.push_str(" {"); - self.last_pos = ::utils::span_after(s, "{", self.codemap); - self.block_indent = self.block_indent.block_indent(self.config); - self.walk_mod_items(m); - self.format_missing_with_indent(m.inner.hi - BytePos(1)); - self.close_block(); + // Hackery to account for the closing }. + let mod_lo = ::utils::span_after(s, "{", self.codemap); + let body_snippet = self.snippet(codemap::mk_sp(mod_lo, m.inner.hi - BytePos(1))); + let body_snippet = body_snippet.trim(); + if body_snippet.is_empty() { + self.buffer.push_str("}"); + } else { + self.last_pos = mod_lo; + self.block_indent = self.block_indent.block_indent(self.config); + self.walk_mod_items(m); + self.format_missing_with_indent(m.inner.hi - BytePos(1)); + self.close_block(); + } self.last_pos = m.inner.hi; } else { self.buffer.push_str(";"); diff --git a/tests/target/comment2.rs b/tests/target/comment2.rs index cecb7b0d95f..04f84a15c95 100644 --- a/tests/target/comment2.rs +++ b/tests/target/comment2.rs @@ -2,5 +2,4 @@ /// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly /// and justly. -pub mod foo { -} +pub mod foo {} diff --git a/tests/target/comment3.rs b/tests/target/comment3.rs index 24598931ed1..3a810590d7b 100644 --- a/tests/target/comment3.rs +++ b/tests/target/comment3.rs @@ -3,5 +3,4 @@ //! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly //! and justly. -pub mod foo { -} +pub mod foo {} diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs index 6fe2e65c565..abf25b5e649 100644 --- a/tests/target/mod-1.rs +++ b/tests/target/mod-1.rs @@ -2,8 +2,7 @@ mod foo { mod bar { - mod baz { - } + mod baz {} } } @@ -16,9 +15,7 @@ mod foo { } } - mod qux { - - } + mod qux {} } mod boxed { -- cgit 1.4.1-3-g733a5 From bd9ad6b0a0f8cf691c469846b9ee4a30be339a52 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 31 Jan 2016 01:48:14 -0500 Subject: bin: Properly handle a directories named rustfmt.toml `lookup_project_file` could erroneously find a *directory* named `rustmfmt.toml` if there was one in its lookup path, and so ignore any configuration file it should have found further up. The error handling resulted in this silently using the default configuration. --- src/bin/rustfmt.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index a8a19d96bc7..3e31c4b5f23 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -57,8 +57,11 @@ fn lookup_project_file(input_file: &Path) -> io::Result { loop { let config_file = current.join("rustfmt.toml"); - if fs::metadata(&config_file).is_ok() { - return Ok(config_file); + if let Ok(md) = fs::metadata(&config_file) { + // Properly handle unlikely situation of a directory named `rustfmt.toml`. + if md.is_file() { + return Ok(config_file); + } } // If the current directory has no parent, we're done searching. -- cgit 1.4.1-3-g733a5 From 7a0d8be405f8d949cba1eedb27af90bbc452d481 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 31 Jan 2016 02:01:54 -0500 Subject: bin: Canonicalize path before looking for project file --- src/bin/rustfmt.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index a8a19d96bc7..187b48ec196 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -51,9 +51,7 @@ fn lookup_project_file(input_file: &Path) -> io::Result { input_file.to_path_buf() }; - // FIXME: We should canonize path to properly handle its parents, - // but `canonicalize` function is unstable now (recently added API) - // current = try!(fs::canonicalize(current)); + current = try!(fs::canonicalize(current)); loop { let config_file = current.join("rustfmt.toml"); -- cgit 1.4.1-3-g733a5 From 98726d0a5347a038e8b5200db0b4e1edb1c31a27 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 31 Jan 2016 10:21:48 -0500 Subject: bin: Improve error handling in project file lookup Previously errors were being silently ignored. Eg, if `rustfmt` did not have permission to read a `rustfmt.toml` file, the default configuration was used without informing the user. --- src/bin/rustfmt.rs | 69 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 1bea4430c30..3bd575bfe87 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -22,7 +22,7 @@ use rustfmt::config::{Config, WriteMode}; use std::env; use std::fs::{self, File}; -use std::io::{self, Read, Write}; +use std::io::{self, ErrorKind, Read, Write}; use std::path::{Path, PathBuf}; use getopts::{Matches, Options}; @@ -43,39 +43,55 @@ enum Operation { Stdin(String, WriteMode), } -/// Try to find a project file in the input file directory and its parents. -fn lookup_project_file(input_file: &Path) -> io::Result { - let mut current = if input_file.is_relative() { - try!(env::current_dir()).join(input_file) +/// Try to find a project file in the given directory and its parents. +fn lookup_project_file(dir: &Path) -> io::Result> { + let mut current = if dir.is_relative() { + try!(env::current_dir()).join(dir) } else { - input_file.to_path_buf() + dir.to_path_buf() }; current = try!(fs::canonicalize(current)); loop { let config_file = current.join("rustfmt.toml"); - if let Ok(md) = fs::metadata(&config_file) { - // Properly handle unlikely situation of a directory named `rustfmt.toml`. - if md.is_file() { - return Ok(config_file); + match fs::metadata(&config_file) { + Ok(md) => { + // Properly handle unlikely situation of a directory named `rustfmt.toml`. + if md.is_file() { + return Ok(Some(config_file)); + } + } + // If it's not found, we continue searching; otherwise something went wrong and we + // return the error. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e); + } } } // If the current directory has no parent, we're done searching. if !current.pop() { - return Err(io::Error::new(io::ErrorKind::NotFound, "Config not found")); + return Ok(None); } } } -/// Try to find a project file. If it's found, read it. -fn lookup_and_read_project_file(input_file: &Path) -> io::Result<(PathBuf, String)> { - let path = try!(lookup_project_file(input_file)); +/// Resolve the config for input in `dir`. +/// +/// Returns the `Config` to use, and the path of the project file if there was +/// one. +fn resolve_config(dir: &Path) -> io::Result<(Config, Option)> { + let path = try!(lookup_project_file(dir)); + if path.is_none() { + return Ok((Config::default(), None)); + } + let path = path.unwrap(); let mut file = try!(File::open(&path)); let mut toml = String::new(); try!(file.read_to_string(&mut toml)); - Ok((path, toml)) + Ok((Config::from_toml(&toml), Some(path))) } fn update_config(config: &mut Config, matches: &Matches) { @@ -127,25 +143,22 @@ fn execute() -> i32 { } Operation::Stdin(input, write_mode) => { // try to read config from local directory - let config = match lookup_and_read_project_file(&Path::new(".")) { - Ok((_, toml)) => Config::from_toml(&toml), - Err(_) => Default::default(), - }; + let (config, _) = resolve_config(&env::current_dir().unwrap()) + .expect("Error resolving config"); run_from_stdin(input, write_mode, &config); 0 } Operation::Format(files, write_mode) => { for file in files { - let mut config = match lookup_and_read_project_file(&file) { - Ok((path, toml)) => { - println!("Using rustfmt config file {} for {}", - path.display(), - file.display()); - Config::from_toml(&toml) - } - Err(_) => Default::default(), - }; + let (mut config, path) = resolve_config(file.parent().unwrap()) + .expect(&format!("Error resolving config for {}", + file.display())); + if let Some(path) = path { + println!("Using rustfmt config file {} for {}", + path.display(), + file.display()); + } update_config(&mut config, &matches); run(&file, write_mode, &config); -- cgit 1.4.1-3-g733a5 From 0f254bb343074ae69b3e14963ffe1cc4c23ceae7 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 1 Feb 2016 12:55:12 -0500 Subject: docs: Clarify return type of lookup_project_file --- src/bin/rustfmt.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 3bd575bfe87..14cb63db7d5 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -43,7 +43,8 @@ enum Operation { Stdin(String, WriteMode), } -/// Try to find a project file in the given directory and its parents. +/// Try to find a project file in the given directory and its parents. Returns the path of a the +/// nearest project file if one exists, or `None` if no project file was found. fn lookup_project_file(dir: &Path) -> io::Result> { let mut current = if dir.is_relative() { try!(env::current_dir()).join(dir) -- cgit 1.4.1-3-g733a5 From 85d14617ce989a840feacfef321b2a1f380877be Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 1 Feb 2016 18:40:32 -0500 Subject: config: Make panic messages more useful --- src/config.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 48b7a06e538..b2b40a23385 100644 --- a/src/config.rs +++ b/src/config.rs @@ -218,12 +218,12 @@ macro_rules! create_config { } pub fn from_toml(toml: &str) -> Config { - let parsed = toml.parse().unwrap(); + let parsed = toml.parse().expect("Could not parse TOML"); let parsed_config:ParsedConfig = match toml::decode(parsed) { Some(decoded) => decoded, None => { println!("Decoding config file failed. Config:\n{}", toml); - let parsed: toml::Value = toml.parse().unwrap(); + let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); println!("\n\nParsed:\n{:?}", parsed); panic!(); } @@ -235,10 +235,14 @@ macro_rules! create_config { match key { $( stringify!($i) => { - self.$i = val.parse::<$ty>().unwrap(); + self.$i = val.parse::<$ty>() + .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", + stringify!($i), + val, + stringify!($ty))); } )+ - _ => panic!("Bad config key!") + _ => panic!("Unknown config key in override: {}", key) } } -- cgit 1.4.1-3-g733a5 From 52f98c763b5e9c8517ee76e3232c48a2ffd366d1 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 1 Feb 2016 20:29:44 -0500 Subject: config: Disable report_todo by default --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 48b7a06e538..14e58919a87 100644 --- a/src/config.rs +++ b/src/config.rs @@ -326,7 +326,7 @@ create_config! { struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, "Multiline style on literal structs"; enum_trailing_comma: bool, true, "Put a trailing comma on enum declarations"; - report_todo: ReportTactic, ReportTactic::Always, + report_todo: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; -- cgit 1.4.1-3-g733a5 From 8b601812a6d4d8a26628be12bf2244440e935b52 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 1 Feb 2016 23:40:45 -0500 Subject: cleanup: Use const instead of static --- src/issues.rs | 4 ++-- src/macros.rs | 2 +- tests/system.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/issues.rs b/src/issues.rs index 04a61fff358..40b09fdfca5 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -15,8 +15,8 @@ use std::fmt; pub use config::ReportTactic; -static TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O']; -static FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; +const TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O']; +const FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; // Enabled implementation detail is here because it is // irrelevant outside the issues module diff --git a/src/macros.rs b/src/macros.rs index 84a7e18bd85..a8da45c6408 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,7 @@ use expr::{rewrite_call, rewrite_array}; use comment::FindUncommented; use utils::{wrap_str, span_after}; -static FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; +const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; // FIXME: use the enum from libsyntax? #[derive(Clone, Copy, PartialEq, Eq)] diff --git a/tests/system.rs b/tests/system.rs index 29f34e88c01..8c7ea6c5fe5 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -23,7 +23,7 @@ use rustfmt::filemap::{write_system_newlines, FileMap}; use rustfmt::config::{Config, ReportTactic, WriteMode}; use rustfmt::rustfmt_diff::*; -static DIFF_CONTEXT_SIZE: usize = 3; +const DIFF_CONTEXT_SIZE: usize = 3; fn get_path_string(dir_entry: io::Result) -> String { let path = dir_entry.expect("Couldn't get DirEntry").path(); -- cgit 1.4.1-3-g733a5 From 46242ed10e2430add4ecdaa44ed195cddbee3197 Mon Sep 17 00:00:00 2001 From: sid Date: Fri, 22 Jan 2016 16:13:54 +0530 Subject: Add support for the config-path option Adds a config-path option for rustfmt. If this argument is provided, it recursively searches the config-path for a rustfmt.toml file. If file is not found, reverts to searching the file input path for the config file or uses default options. --- src/bin/rustfmt.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 14cb63db7d5..fed74868f6a 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -30,7 +30,7 @@ use getopts::{Matches, Options}; /// Rustfmt operations. enum Operation { /// Format files and their child modules. - Format(Vec, WriteMode), + Format(Vec, WriteMode, Option), /// Print the help message. Help, // Print version information @@ -40,7 +40,7 @@ enum Operation { /// Invalid program input, including reason. InvalidInput(String), /// No file specified, read from stdin - Stdin(String, WriteMode), + Stdin(String, WriteMode, Option), } /// Try to find a project file in the given directory and its parents. Returns the path of a the @@ -95,6 +95,20 @@ fn resolve_config(dir: &Path) -> io::Result<(Config, Option)> { Ok((Config::from_toml(&toml), Some(path))) } +/// read the given config file path recursively if present else read the project file path +fn match_cli_path_or_file(config_path: Option, + input_file: &Path) + -> io::Result<(Config, Option)> { + + if let Some(config_file) = config_path { + let (toml, path) = try!(resolve_config(config_file.as_ref())); + if path.is_some() { + return Ok((toml, path)); + } + } + resolve_config(input_file) +} + fn update_config(config: &mut Config, matches: &Matches) { config.verbose = matches.opt_present("verbose"); config.skip_children = matches.opt_present("skip-children"); @@ -114,6 +128,11 @@ fn execute() -> i32 { opts.optflag("", "config-help", "show details of rustfmt configuration options"); + opts.optopt("", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ + found reverts to the input file path", + "[Path for the configuration file]"); let matches = match opts.parse(env::args().skip(1)) { Ok(m) => m, @@ -142,23 +161,41 @@ fn execute() -> i32 { Config::print_docs(); 0 } - Operation::Stdin(input, write_mode) => { + Operation::Stdin(input, write_mode, config_path) => { // try to read config from local directory - let (config, _) = resolve_config(&env::current_dir().unwrap()) + let (config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap()) .expect("Error resolving config"); run_from_stdin(input, write_mode, &config); 0 } - Operation::Format(files, write_mode) => { + Operation::Format(files, write_mode, config_path) => { + let mut config = Config::default(); + let mut path = None; + // Load the config path file if provided + if let Some(config_file) = config_path { + let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref()) + .expect(&format!("Error resolving config for {:?}", + config_file)); + config = cfg_tmp; + path = path_tmp; + }; + if let Some(path) = path.as_ref() { + println!("Using rustfmt config file {}", path.display()); + } for file in files { - let (mut config, path) = resolve_config(file.parent().unwrap()) - .expect(&format!("Error resolving config for {}", - file.display())); - if let Some(path) = path { - println!("Using rustfmt config file {} for {}", - path.display(), - file.display()); + // Check the file directory if the config-path could not be read or not provided + if path.is_none() { + let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap()) + .expect(&format!("Error resolving config \ + for {}", + file.display())); + if let Some(path) = path_tmp.as_ref() { + println!("Using rustfmt config file {} for {}", + path.display(), + file.display()); + } + config = config_tmp; } update_config(&mut config, &matches); @@ -211,6 +248,16 @@ fn determine_operation(matches: &Matches) -> Operation { return Operation::Version; } + // Read the config_path and convert to parent dir if a file is provided. + let config_path: Option = matches.opt_str("config-path") + .map(PathBuf::from) + .and_then(|dir| { + if dir.is_file() { + return dir.parent().map(|v| v.into()); + } + Some(dir) + }); + // if no file argument is supplied, read from stdin if matches.free.is_empty() { @@ -221,7 +268,7 @@ fn determine_operation(matches: &Matches) -> Operation { } // WriteMode is always plain for Stdin - return Operation::Stdin(buffer, WriteMode::Plain); + return Operation::Stdin(buffer, WriteMode::Plain, config_path); } let write_mode = match matches.opt_str("write-mode") { @@ -236,5 +283,5 @@ fn determine_operation(matches: &Matches) -> Operation { let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); - Operation::Format(files, write_mode) + Operation::Format(files, write_mode, config_path) } -- cgit 1.4.1-3-g733a5 From 70c9b55ecbdcd0d70b68b2175fc64d6bb14c30be Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Tue, 2 Feb 2016 12:37:38 -0500 Subject: cleanup: Remove documentation of deleted parameter The `args` parameter was removed in 579fb34. --- src/lib.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index ad9322ab649..2f49ed4f5e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -420,8 +420,6 @@ fn check_write_mode(arg: WriteMode, config: WriteMode) -> WriteMode { } } -// args are the arguments passed on the command line, generally passed through -// to the compiler. // write_mode determines what happens to the result of running rustfmt, see // WriteMode. pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { -- cgit 1.4.1-3-g733a5 From 14dbac5fd78a76592bcf4b9fbb71da3ba102e1ec Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Fri, 5 Feb 2016 15:59:41 -0500 Subject: config: Use write_mode from config This commit tidies up handling of `write_mode` by setting it in the config at the start, and removing the `write_mode` parameter threaded throughout the formatting process. --- src/bin/rustfmt.rs | 52 +++++++++++++++++++++++++++++----------------------- src/config.rs | 5 +---- src/expr.rs | 6 ++---- src/filemap.rs | 18 +++++------------- src/items.rs | 2 +- src/lib.rs | 41 +++++++++++++---------------------------- src/missed_spans.rs | 11 +++-------- src/visitor.rs | 9 ++------- tests/system.rs | 39 +++++++++++++++++++++++---------------- 9 files changed, 79 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index fed74868f6a..8a393ba399d 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -24,13 +24,14 @@ use std::env; use std::fs::{self, File}; use std::io::{self, ErrorKind, Read, Write}; use std::path::{Path, PathBuf}; +use std::str::FromStr; use getopts::{Matches, Options}; /// Rustfmt operations. enum Operation { /// Format files and their child modules. - Format(Vec, WriteMode, Option), + Format(Vec, Option), /// Print the help message. Help, // Print version information @@ -40,7 +41,7 @@ enum Operation { /// Invalid program input, including reason. InvalidInput(String), /// No file specified, read from stdin - Stdin(String, WriteMode, Option), + Stdin(String, Option), } /// Try to find a project file in the given directory and its parents. Returns the path of a the @@ -109,9 +110,19 @@ fn match_cli_path_or_file(config_path: Option, resolve_config(input_file) } -fn update_config(config: &mut Config, matches: &Matches) { +fn update_config(config: &mut Config, matches: &Matches) -> Result<(), String> { config.verbose = matches.opt_present("verbose"); config.skip_children = matches.opt_present("skip-children"); + + let write_mode = matches.opt_str("write-mode"); + match matches.opt_str("write-mode").map(|wm| WriteMode::from_str(&wm)) { + None => Ok(()), + Some(Ok(write_mode)) => { + config.write_mode = write_mode; + Ok(()) + } + Some(Err(_)) => Err(format!("Invalid write-mode: {}", write_mode.expect("cannot happen"))), + } } fn execute() -> i32 { @@ -161,15 +172,18 @@ fn execute() -> i32 { Config::print_docs(); 0 } - Operation::Stdin(input, write_mode, config_path) => { + Operation::Stdin(input, config_path) => { // try to read config from local directory - let (config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap()) - .expect("Error resolving config"); + let (mut config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap()) + .expect("Error resolving config"); - run_from_stdin(input, write_mode, &config); + // write_mode is always Plain for Stdin. + config.write_mode = WriteMode::Plain; + + run_from_stdin(input, &config); 0 } - Operation::Format(files, write_mode, config_path) => { + Operation::Format(files, config_path) => { let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -198,8 +212,11 @@ fn execute() -> i32 { config = config_tmp; } - update_config(&mut config, &matches); - run(&file, write_mode, &config); + if let Err(e) = update_config(&mut config, &matches) { + print_usage(&opts, &e); + return 1; + } + run(&file, &config); } 0 } @@ -267,21 +284,10 @@ fn determine_operation(matches: &Matches) -> Operation { Err(e) => return Operation::InvalidInput(e.to_string()), } - // WriteMode is always plain for Stdin - return Operation::Stdin(buffer, WriteMode::Plain, config_path); + return Operation::Stdin(buffer, config_path); } - let write_mode = match matches.opt_str("write-mode") { - Some(mode) => { - match mode.parse() { - Ok(mode) => mode, - Err(..) => return Operation::InvalidInput("Unrecognized write mode".into()), - } - } - None => WriteMode::Default, - }; - let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); - Operation::Format(files, write_mode, config_path) + Operation::Format(files, config_path) } diff --git a/src/config.rs b/src/config.rs index 59b301eebf1..da686ffac95 100644 --- a/src/config.rs +++ b/src/config.rs @@ -121,9 +121,6 @@ configuration_option_enum! { ReportTactic: } configuration_option_enum! { WriteMode: - // Used internally to represent when no option is given - // Treated as Replace. - Default, // Backsup the original file and overwrites the orignal. Replace, // Overwrites original file without backup. @@ -349,6 +346,6 @@ create_config! { match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; - write_mode: WriteMode, WriteMode::Default, + write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; } diff --git a/src/expr.rs b/src/expr.rs index b299f82a883..34a30e94899 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -427,7 +427,7 @@ impl Rewrite for ast::Block { return Some(user_str); } - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = context.block_indent; let prefix = match self.rules { @@ -954,9 +954,7 @@ impl Rewrite for ast::Arm { let attr_str = if !attrs.is_empty() { // We only use this visitor for the attributes, should we use it for // more? - let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, - context.config, - None); + let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, context.config); attr_visitor.block_indent = context.block_indent; attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { diff --git a/src/filemap.rs b/src/filemap.rs index 61ad573f702..f41915b8cff 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -31,18 +31,14 @@ pub fn append_newlines(file_map: &mut FileMap) { } } -pub fn write_all_files(file_map: &FileMap, - mut out: T, - mode: WriteMode, - config: &Config) - -> Result<(), io::Error> +pub fn write_all_files(file_map: &FileMap, mut out: T, config: &Config) -> Result<(), io::Error> where T: Write { - output_header(&mut out, mode).ok(); + output_header(&mut out, config.write_mode).ok(); for filename in file_map.keys() { - try!(write_file(&file_map[filename], filename, &mut out, mode, config)); + try!(write_file(&file_map[filename], filename, &mut out, config)); } - output_footer(&mut out, mode).ok(); + output_footer(&mut out, config.write_mode).ok(); Ok(()) } @@ -87,7 +83,6 @@ pub fn write_system_newlines(writer: T, pub fn write_file(text: &StringBuffer, filename: &str, out: &mut T, - mode: WriteMode, config: &Config) -> Result, io::Error> where T: Write @@ -114,7 +109,7 @@ pub fn write_file(text: &StringBuffer, Ok(make_diff(&ori, &fmt, 3)) } - match mode { + match config.write_mode { WriteMode::Replace => { if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { if fmt != ori { @@ -157,9 +152,6 @@ pub fn write_file(text: &StringBuffer, |line_num| format!("\nDiff at line {}:", line_num)); } } - WriteMode::Default => { - unreachable!("The WriteMode should NEVER Be default at this point!"); - } WriteMode::Checkstyle => { let diff = try!(create_diff(filename, text, config)); try!(output_checkstyle_file(out, filename, diff)); diff --git a/src/items.rs b/src/items.rs index 2ff52148f6a..d7c16c4561c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -530,7 +530,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = context.block_indent.block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); diff --git a/src/lib.rs b/src/lib.rs index 2f49ed4f5e5..ee671cf0baa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ use std::fmt; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; use visitor::FmtVisitor; -use config::{Config, WriteMode}; +use config::Config; #[macro_use] mod utils; @@ -264,8 +264,7 @@ impl fmt::Display for FormatReport { fn fmt_ast(krate: &ast::Crate, parse_session: &ParseSess, main_file: &Path, - config: &Config, - mode: WriteMode) + config: &Config) -> FileMap { let mut file_map = FileMap::new(); for (path, module) in modules::list_files(krate, parse_session.codemap()) { @@ -276,7 +275,7 @@ fn fmt_ast(krate: &ast::Crate, if config.verbose { println!("Formatting {}", path); } - let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode)); + let mut visitor = FmtVisitor::from_codemap(parse_session, config); visitor.format_separate_mod(module); file_map.insert(path.to_owned(), visitor.buffer); } @@ -366,7 +365,7 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap { +pub fn format_string(input: String, config: &Config) -> FileMap { let path = "stdin"; let mut parse_session = ParseSess::new(); let krate = parse::parse_crate_from_source_str(path.to_owned(), @@ -383,7 +382,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap let mut file_map = FileMap::new(); // do the actual formatting - let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode)); + let mut visitor = FmtVisitor::from_codemap(&parse_session, config); visitor.format_separate_mod(&krate.module); // append final newline @@ -393,7 +392,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap file_map } -pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { +pub fn format(file: &Path, config: &Config) -> FileMap { let mut parse_session = ParseSess::new(); let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); @@ -401,7 +400,7 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); - let mut file_map = fmt_ast(&krate, &parse_session, file, config, mode); + let mut file_map = fmt_ast(&krate, &parse_session, file, config); // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. @@ -410,25 +409,12 @@ pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { file_map } -// Make sure that we are using the correct WriteMode, -// preferring what is passed as an argument -fn check_write_mode(arg: WriteMode, config: WriteMode) -> WriteMode { - match (arg, config) { - (WriteMode::Default, WriteMode::Default) => WriteMode::Replace, - (WriteMode::Default, mode) => mode, - (mode, _) => mode, - } -} - -// write_mode determines what happens to the result of running rustfmt, see -// WriteMode. -pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { - let mode = check_write_mode(write_mode, config.write_mode); - let mut result = format(file, config, mode); +pub fn run(file: &Path, config: &Config) { + let mut result = format(file, config); print!("{}", fmt_lines(&mut result, config)); let out = stdout(); - let write_result = filemap::write_all_files(&result, out, mode, config); + let write_result = filemap::write_all_files(&result, out, config); if let Err(msg) = write_result { println!("Error writing files: {}", msg); @@ -436,13 +422,12 @@ pub fn run(file: &Path, write_mode: WriteMode, config: &Config) { } // Similar to run, but takes an input String instead of a file to format -pub fn run_from_stdin(input: String, write_mode: WriteMode, config: &Config) { - let mode = check_write_mode(write_mode, config.write_mode); - let mut result = format_string(input, config, mode); +pub fn run_from_stdin(input: String, config: &Config) { + let mut result = format_string(input, config); fmt_lines(&mut result, config); let mut out = stdout(); - let write_result = filemap::write_file(&result["stdin"], "stdin", &mut out, mode, config); + let write_result = filemap::write_file(&result["stdin"], "stdin", &mut out, config); if let Err(msg) = write_result { panic!("Error writing to stdout: {}", msg); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index c86cd62a900..092cc0093f1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -103,14 +103,9 @@ impl<'a> FmtVisitor<'a> { .collect() } - let replaced = match self.write_mode { - Some(mode) => { - match mode { - WriteMode::Coverage => replace_chars(old_snippet), - _ => old_snippet.to_owned(), - } - } - None => old_snippet.to_owned(), + let replaced = match self.config.write_mode { + WriteMode::Coverage => replace_chars(old_snippet), + _ => old_snippet.to_owned(), }; let snippet = &*replaced; diff --git a/src/visitor.rs b/src/visitor.rs index 073a05ef2bc..f53ed2246d5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,7 +17,7 @@ use strings::string_buffer::StringBuffer; use Indent; use utils; -use config::{Config, WriteMode}; +use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; @@ -31,7 +31,6 @@ pub struct FmtVisitor<'a> { // FIXME: use an RAII util or closure for indenting pub block_indent: Indent, pub config: &'a Config, - pub write_mode: Option, } impl<'a> FmtVisitor<'a> { @@ -380,10 +379,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = span.hi; } - pub fn from_codemap(parse_session: &'a ParseSess, - config: &'a Config, - mode: Option) - -> FmtVisitor<'a> { + pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> { FmtVisitor { parse_session: parse_session, codemap: parse_session.codemap(), @@ -394,7 +390,6 @@ impl<'a> FmtVisitor<'a> { alignment: 0, }, config: config, - write_mode: mode, } } diff --git a/tests/system.rs b/tests/system.rs index 8c7ea6c5fe5..497583f9d67 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -44,7 +44,7 @@ fn system_tests() { // Turn a DirEntry into a String that represents the relative path to the // file. let files = files.map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Default); + let (_reports, count, fails) = check_files(files, None); // Display results. println!("Ran {} system tests.", count); @@ -57,7 +57,7 @@ fn system_tests() { fn coverage_tests() { let files = fs::read_dir("tests/coverage-source").expect("Couldn't read source dir"); let files = files.map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Coverage); + let (_reports, count, fails) = check_files(files, Some(WriteMode::Coverage)); println!("Ran {} tests in coverage mode.", count); assert!(fails == 0, "{} tests failed", fails); @@ -67,19 +67,23 @@ fn coverage_tests() { fn checkstyle_test() { let filename = "tests/source/fn-single-line.rs"; let expected_filename = "tests/writemode/checkstyle.xml"; - assert_output(filename, expected_filename, WriteMode::Checkstyle); + assert_output(filename, expected_filename, Some(WriteMode::Checkstyle)); } // Helper function for comparing the results of rustfmt // to a known output file generated by one of the write modes. -fn assert_output(source: &str, expected_filename: &str, write_mode: WriteMode) { - let config = read_config(&source); +fn assert_output(source: &str, expected_filename: &str, write_mode: Option) { let file_map = run_rustfmt(source.to_string(), write_mode); + let mut config = read_config(&source); + if let Some(write_mode) = write_mode { + config.write_mode = write_mode; + } + // Populate output by writing to a vec. let mut out = vec![]; - let _ = filemap::write_all_files(&file_map, &mut out, write_mode, &config); + let _ = filemap::write_all_files(&file_map, &mut out, &config); let output = String::from_utf8(out).unwrap(); let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); @@ -104,7 +108,7 @@ fn idempotence_tests() { let files = fs::read_dir("tests/target") .expect("Couldn't read target dir") .map(get_path_string); - let (_reports, count, fails) = check_files(files, WriteMode::Default); + let (_reports, count, fails) = check_files(files, None); // Display results. println!("Ran {} idempotent tests.", count); @@ -122,7 +126,7 @@ fn self_tests() { // Hack because there's no `IntoIterator` impl for `[T; N]`. let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); - let (reports, count, fails) = check_files(files, WriteMode::Default); + let (reports, count, fails) = check_files(files, None); let mut warnings = 0; // Display results. @@ -141,7 +145,7 @@ fn self_tests() { // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. -fn check_files(files: I, write_mode: WriteMode) -> (Vec, u32, u32) +fn check_files(files: I, write_mode: Option) -> (Vec, u32, u32) where I: Iterator { let mut count = 0; @@ -192,13 +196,16 @@ fn read_config(filename: &str) -> Config { } // Simulate run() -fn run_rustfmt(filename: String, write_mode: WriteMode) -> FileMap { - let config = read_config(&filename); - format(Path::new(&filename), &config, write_mode) +fn run_rustfmt(filename: String, write_mode: Option) -> FileMap { + let mut config = read_config(&filename); + if let Some(write_mode) = write_mode { + config.write_mode = write_mode; + } + format(Path::new(&filename), &config) } pub fn idempotent_check(filename: String, - write_mode: WriteMode) + write_mode: Option) -> Result>> { let sig_comments = read_significant_comments(&filename); let config = read_config(&filename); @@ -266,7 +273,7 @@ fn read_significant_comments(file_name: &str) -> HashMap { // TODO: needs a better name, more explanation. fn handle_result(result: HashMap, target: Option<&str>, - write_mode: WriteMode) + write_mode: Option) -> Result<(), HashMap>> { let mut failures = HashMap::new(); @@ -292,10 +299,10 @@ fn handle_result(result: HashMap, } // Map source file paths to their target paths. -fn get_target(file_name: &str, target: Option<&str>, write_mode: WriteMode) -> String { +fn get_target(file_name: &str, target: Option<&str>, write_mode: Option) -> String { let file_path = Path::new(file_name); let (source_path_prefix, target_path_prefix) = match write_mode { - WriteMode::Coverage => { + Some(WriteMode::Coverage) => { (Path::new("tests/coverage-source/"), "tests/coverage-target/") } -- cgit 1.4.1-3-g733a5 From d86cfb357aef2d70e67e616f60ca587bd12def62 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 12 Feb 2016 14:59:13 +1300 Subject: Format all patterns (well, except macros) Fixes #18 Fixes #672 --- src/imports.rs | 10 ++-- src/patterns.rs | 153 +++++++++++++++++++++++++++++++++++++----------- tests/source/pattern.rs | 14 +++++ tests/system.rs | 2 + tests/target/match.rs | 2 +- tests/target/pattern.rs | 17 ++++++ 6 files changed, 159 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 42d152fc6ac..70351ca8d79 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -51,7 +51,7 @@ impl Rewrite for ast::ViewPath { } fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { - let path_item_str = if let ast::PathListItem_::PathListIdent{ name, .. } = vpi.node { + let path_item_str = if let ast::PathListItem_::PathListIdent { name, .. } = vpi.node { // A name. if path_str.is_empty() { name.to_string() @@ -74,8 +74,8 @@ fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { let path_item_str = match vpi.node { - ast::PathListItem_::PathListIdent{ name, .. } => name.to_string(), - ast::PathListItem_::PathListMod{ .. } => "self".to_owned(), + ast::PathListItem_::PathListIdent { name, .. } => name.to_string(), + ast::PathListItem_::PathListMod { .. } => "self".to_owned(), }; Some(append_alias(path_item_str, vpi)) @@ -83,8 +83,8 @@ fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { match vpi.node { - ast::PathListItem_::PathListIdent{ rename: Some(rename), .. } | - ast::PathListItem_::PathListMod{ rename: Some(rename), .. } => { + ast::PathListItem_::PathListIdent { rename: Some(rename), .. } | + ast::PathListItem_::PathListMod { rename: Some(rename), .. } => { format!("{} as {}", path_item_str, rename) } _ => path_item_str, diff --git a/src/patterns.rs b/src/patterns.rs index fdc418733fb..1aee4ae7a21 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,20 +15,30 @@ use lists::{format_item_list, itemize_list}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use types::rewrite_path; -use syntax::ast::{BindingMode, Pat, Pat_}; +use syntax::ast::{BindingMode, Pat, Pat_, FieldPat}; -// FIXME(#18): implement pattern formatting. impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { Pat_::PatBox(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, width, offset), - Pat_::PatIdent(binding_mode, ident, None) => { + Pat_::PatIdent(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { BindingMode::BindByRef(mutability) => ("ref ", mutability), BindingMode::BindByValue(mutability) => ("", mutability), }; let mut_infix = format_mutability(mutability); - let result = format!("{}{}{}", prefix, mut_infix, ident.node); + let id_str = ident.node.to_string(); + + let sub_pat = match *sub_pat { + Some(ref p) => { + let width = try_opt!(width.checked_sub(prefix.len() + mut_infix.len() + + id_str.len())); + format!(" @ {}", try_opt!(p.rewrite(context, width, offset))) + } + None => "".to_owned(), + }; + + let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); wrap_str(result, context.config.max_width, width, offset) } Pat_::PatWild => { @@ -55,39 +65,105 @@ impl Rewrite for Pat { width, offset) } - Pat_::PatEnum(ref path, Some(ref pat_vec)) => { - let path_str = try_opt!(::types::rewrite_path(context, - true, - None, - path, - width, - offset)); + Pat_::PatEnum(ref path, ref pat_vec) => { + let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); - if pat_vec.is_empty() { - Some(path_str) - } else { - // 1 = ( - let width = try_opt!(width.checked_sub(path_str.len() + 1)); - let offset = offset + path_str.len() + 1; - let items = itemize_list(context.codemap, - pat_vec.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, width, offset), - span_after(self.span, "(", context.codemap), - self.span.hi); - Some(format!("{}({})", - path_str, - try_opt!(format_item_list(items, width, offset, context.config)))) + match *pat_vec { + Some(ref pat_vec) => { + if pat_vec.is_empty() { + Some(path_str) + } else { + // 1 = ( + let width = try_opt!(width.checked_sub(path_str.len() + 1)); + let offset = offset + path_str.len() + 1; + let items = itemize_list(context.codemap, + pat_vec.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, width, offset), + span_after(self.span, "(", context.codemap), + self.span.hi); + Some(format!("{}({})", + path_str, + try_opt!(format_item_list(items, + width, + offset, + context.config)))) + } + } + None => Some(format!("{}(..)", path_str)), } } Pat_::PatLit(ref expr) => expr.rewrite(context, width, offset), - // FIXME(#8): format remaining pattern variants. - Pat_::PatIdent(_, _, Some(..)) | - Pat_::PatEnum(_, None) | - Pat_::PatStruct(..) | - Pat_::PatVec(..) | + Pat_::PatVec(ref prefix, ref slice_pat, ref suffix) => { + // Rewrite all the sub-patterns. + let prefix = prefix.iter().map(|p| p.rewrite(context, width, offset)); + let slice_pat = slice_pat.as_ref().map(|p| { + Some(format!("{}..", try_opt!(p.rewrite(context, width, offset)))) + }); + let suffix = suffix.iter().map(|p| p.rewrite(context, width, offset)); + + // Munge them together. + let pats = prefix.chain(slice_pat.into_iter()).chain(suffix); + + // Check that all the rewrites succeeded, and if not return None. + let (somes, nones) = pats.partition::>, _>(Option::is_some); + if nones.len() > 0 { + return None; + } + + // Unwrap all the sub-strings and join them with commas. + let pats = somes.into_iter().map(|p| p.unwrap()).collect::>().join(", "); + Some(format!("[{}]", pats)) + } + Pat_::PatStruct(ref path, ref fields, elipses) => { + let path = try_opt!(rewrite_path(context, true, None, path, width, offset)); + + let (elipses_str, terminator) = if elipses { + (", ..", "..") + } else { + ("", "}") + }; + + let budget = try_opt!(width.checked_sub(path.len() + 5 + elipses_str.len())); + // FIXME Using visual indenting, should use block or visual to match + // struct lit preference (however, in practice I think it is rare + // for struct patterns to be multi-line). + let offset = offset + path.len() + 3; + + let items = itemize_list(context.codemap, + fields.iter(), + terminator, + |f| f.span.lo, + |f| f.span.hi, + |f| f.node.rewrite(context, budget, offset), + span_after(self.span, "{", context.codemap), + self.span.hi); + let mut field_string = try_opt!(format_item_list(items, + budget, + offset, + context.config)); + if elipses { + if field_string.contains('\n') { + field_string.push_str(",\n"); + field_string.push_str(&offset.to_string(context.config)); + field_string.push_str(".."); + } else { + if field_string.len() > 0 { + field_string.push_str(", "); + } + field_string.push_str(".."); + } + } + + if field_string.len() == 0 { + Some(format!("{} {{}}", path)) + } else { + Some(format!("{} {{ {} }}", path, field_string)) + } + } + // FIXME(#819) format pattern macros. Pat_::PatMac(..) => { wrap_str(context.snippet(self.span), context.config.max_width, @@ -97,3 +173,14 @@ impl Rewrite for Pat { } } } + +impl Rewrite for FieldPat { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + let pat = self.pat.rewrite(context, width, offset); + if self.is_shorthand { + pat + } else { + Some(format!("{}: {}", self.ident.to_string(), try_opt!(pat))) + } + } +} diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 930ffe2258f..75f65806167 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -11,6 +11,20 @@ fn main() { let Some ( ref xyz /* comment! */) = opt; if let None = opt2 { panic!("oh noes"); } + + let foo@bar (f) = 42; + let a::foo ( ..) = 42; + let [ ] = 42; + let [a.., b,c ] = 42; + let [ a,b,c.. ] = 42; + let [a, b, c, d..,e,f, g] = 42; + let foo { } = 42; + let foo {..} = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; } impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { diff --git a/tests/system.rs b/tests/system.rs index 497583f9d67..bc5298ae22d 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -287,6 +287,8 @@ fn handle_result(result: HashMap, if fmt_text != text { let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); + assert!(!diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?"); failures.insert(file_name, diff); } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 94f9bf8ae5e..defcc13ef51 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -251,7 +251,7 @@ fn issue280() { fn issue383() { match resolution.last_private { - LastImport{..} => false, + LastImport { .. } => false, _ => true, }; } diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index eb42f9fde73..d77cb59f498 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -13,6 +13,23 @@ fn main() { if let None = opt2 { panic!("oh noes"); } + + let foo @ bar(f) = 42; + let a::foo(..) = 42; + let [] = 42; + let [a.., b, c] = 42; + let [a, b, c..] = 42; + let [a, b, c, d.., e, f, g] = 42; + let foo {} = 42; + let foo { .. } = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo } = 42; + let foo { x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. }; + let foo { x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo }; } impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { -- cgit 1.4.1-3-g733a5 From 160eb73baab57cbe0dbb221f5220fc4475ccd1da Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 15 Feb 2016 10:07:19 +1300 Subject: reviewer changes --- src/patterns.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 1aee4ae7a21..a5f09823212 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -31,8 +31,10 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { + // 3 - ` @ `. let width = try_opt!(width.checked_sub(prefix.len() + mut_infix.len() + - id_str.len())); + id_str.len() + + 3)); format!(" @ {}", try_opt!(p.rewrite(context, width, offset))) } None => "".to_owned(), @@ -105,17 +107,16 @@ impl Rewrite for Pat { let suffix = suffix.iter().map(|p| p.rewrite(context, width, offset)); // Munge them together. - let pats = prefix.chain(slice_pat.into_iter()).chain(suffix); + let pats: Option> = prefix.chain(slice_pat.into_iter()) + .chain(suffix) + .collect(); // Check that all the rewrites succeeded, and if not return None. - let (somes, nones) = pats.partition::>, _>(Option::is_some); - if nones.len() > 0 { - return None; - } + let pats = try_opt!(pats); // Unwrap all the sub-strings and join them with commas. - let pats = somes.into_iter().map(|p| p.unwrap()).collect::>().join(", "); - Some(format!("[{}]", pats)) + let result = format!("[{}]", pats.join(", ")); + wrap_str(result, context.config.max_width, width, offset) } Pat_::PatStruct(ref path, ref fields, elipses) => { let path = try_opt!(rewrite_path(context, true, None, path, width, offset)); @@ -126,10 +127,12 @@ impl Rewrite for Pat { ("", "}") }; + // 5 = `{` plus space before and after plus `}` plus space before. let budget = try_opt!(width.checked_sub(path.len() + 5 + elipses_str.len())); // FIXME Using visual indenting, should use block or visual to match // struct lit preference (however, in practice I think it is rare // for struct patterns to be multi-line). + // 3 = `{` plus space before and after. let offset = offset + path.len() + 3; let items = itemize_list(context.codemap, @@ -157,7 +160,7 @@ impl Rewrite for Pat { } } - if field_string.len() == 0 { + if field_string.is_empty() { Some(format!("{} {{}}", path)) } else { Some(format!("{} {{ {} }}", path, field_string)) @@ -180,7 +183,10 @@ impl Rewrite for FieldPat { if self.is_shorthand { pat } else { - Some(format!("{}: {}", self.ident.to_string(), try_opt!(pat))) + wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)), + context.config.max_width, + width, + offset) } } } -- cgit 1.4.1-3-g733a5 From a0567d4063bf092d7ca8f6375507d4bb897b7804 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Tue, 1 Mar 2016 16:39:43 +0100 Subject: Fix for issue #811 (falsely inserted "::" in paths with parameterized trait cast). --- src/types.rs | 2 +- tests/source/issue-811.rs | 19 +++++++++++++++++++ tests/target/issue-811.rs | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-811.rs create mode 100644 tests/target/issue-811.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 32ae4689414..4f930f22cad 100644 --- a/src/types.rs +++ b/src/types.rs @@ -53,7 +53,7 @@ pub fn rewrite_path(context: &RewriteContext, // 3 = ">::".len() let budget = try_opt!(width.checked_sub(extra_offset + 3)); - result = try_opt!(rewrite_path_segments(expr_context, + result = try_opt!(rewrite_path_segments(false, result, path.segments.iter().take(skip_count), span_lo, diff --git a/tests/source/issue-811.rs b/tests/source/issue-811.rs new file mode 100644 index 00000000000..b7a89b5d0f9 --- /dev/null +++ b/tests/source/issue-811.rs @@ -0,0 +1,19 @@ +trait FooTrait: Sized { + type Bar: BarTrait; +} + +trait BarTrait: Sized { + type Baz; + fn foo(); +} + +type Foo = <>::Bar as BarTrait>::Baz; +type Bar = >::Baz; + +fn some_func, U>() { + <>::Bar as BarTrait>::foo(); +} + +fn some_func>() { + >::foo(); +} diff --git a/tests/target/issue-811.rs b/tests/target/issue-811.rs new file mode 100644 index 00000000000..2b58c06941d --- /dev/null +++ b/tests/target/issue-811.rs @@ -0,0 +1,20 @@ +trait FooTrait: Sized { + type Bar: BarTrait; +} + +trait BarTrait: Sized { + type Baz; + fn foo(); +} + +type Foo = + <>::Bar as BarTrait>::Baz; +type Bar = >::Baz; + +fn some_func, U>() { + <>::Bar as BarTrait>::foo(); +} + +fn some_func>() { + >::foo(); +} -- cgit 1.4.1-3-g733a5 From de1fc319c122c1d1f59d7a4f913ed28d0163667f Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Thu, 25 Feb 2016 16:27:37 -0500 Subject: rustfmt: Use struct-like enum variants for Operation --- src/bin/rustfmt.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 8a393ba399d..1524384fc12 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -31,17 +31,25 @@ use getopts::{Matches, Options}; /// Rustfmt operations. enum Operation { /// Format files and their child modules. - Format(Vec, Option), + Format { + files: Vec, + config_path: Option, + }, /// Print the help message. Help, // Print version information Version, /// Print detailed configuration help. ConfigHelp, - /// Invalid program input, including reason. - InvalidInput(String), + /// Invalid program input. + InvalidInput { + reason: String, + }, /// No file specified, read from stdin - Stdin(String, Option), + Stdin { + input: String, + config_path: Option, + }, } /// Try to find a project file in the given directory and its parents. Returns the path of a the @@ -156,7 +164,7 @@ fn execute() -> i32 { let operation = determine_operation(&matches); match operation { - Operation::InvalidInput(reason) => { + Operation::InvalidInput { reason } => { print_usage(&opts, &reason); 1 } @@ -172,7 +180,7 @@ fn execute() -> i32 { Config::print_docs(); 0 } - Operation::Stdin(input, config_path) => { + Operation::Stdin { input, config_path } => { // try to read config from local directory let (mut config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap()) .expect("Error resolving config"); @@ -183,7 +191,7 @@ fn execute() -> i32 { run_from_stdin(input, &config); 0 } - Operation::Format(files, config_path) => { + Operation::Format { files, config_path } => { let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -281,13 +289,19 @@ fn determine_operation(matches: &Matches) -> Operation { let mut buffer = String::new(); match io::stdin().read_to_string(&mut buffer) { Ok(..) => (), - Err(e) => return Operation::InvalidInput(e.to_string()), + Err(e) => return Operation::InvalidInput { reason: e.to_string() }, } - return Operation::Stdin(buffer, config_path); + return Operation::Stdin { + input: buffer, + config_path: config_path, + }; } let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); - Operation::Format(files, config_path) + Operation::Format { + files: files, + config_path: config_path, + } } -- cgit 1.4.1-3-g733a5 From 589dabda2f212d8ae231ed6aab2bbf851eaed90c Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Tue, 1 Mar 2016 17:27:19 -0500 Subject: deps: Update syntex_syntax to 0.29.1 --- Cargo.lock | 4 +- Cargo.toml | 2 +- src/chains.rs | 42 ++++++++-------- src/expr.rs | 145 ++++++++++++++++++++++++++++---------------------------- src/imports.rs | 10 ++-- src/items.rs | 47 +++++++++--------- src/lib.rs | 34 +++++++++---- src/modules.rs | 2 +- src/patterns.rs | 31 ++++++------ src/types.rs | 48 +++++++++---------- src/utils.rs | 28 +++++------ src/visitor.rs | 50 +++++++++---------- 12 files changed, 230 insertions(+), 213 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 40b04c3ef16..9ebeff7bb25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "regex 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -108,7 +108,7 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.23.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 94ff9ce1ec6..49bd30a73ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ regex = "0.1.41" term = "0.2.11" strings = "0.0.1" diff = "0.1.8" -syntex_syntax = "0.23.0" +syntex_syntax = "0.29.1" log = "0.3.2" env_logger = "0.3.1" getopts = "0.2" diff --git a/src/chains.rs b/src/chains.rs index 12f879eb59c..191b4a2ea4c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -94,7 +94,7 @@ pub fn rewrite_chain(mut expr: &ast::Expr, let fits_single_line = !veto_single_line && match subexpr_list[0].node { - ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) + ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) if context.config.chains_overflow_last => { let len = rewrites.len(); let (init, last) = rewrites.split_at_mut(len - 1); @@ -150,28 +150,28 @@ pub fn rewrite_chain(mut expr: &ast::Expr, // parens, braces and brackets in its idiomatic formatting. fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { match expr.node { - ast::Expr_::ExprStruct(..) | - ast::Expr_::ExprWhile(..) | - ast::Expr_::ExprWhileLet(..) | - ast::Expr_::ExprIf(..) | - ast::Expr_::ExprIfLet(..) | - ast::Expr_::ExprBlock(..) | - ast::Expr_::ExprLoop(..) | - ast::Expr_::ExprForLoop(..) | - ast::Expr_::ExprMatch(..) => repr.contains('\n'), - ast::Expr_::ExprParen(ref expr) | - ast::Expr_::ExprBinary(_, _, ref expr) | - ast::Expr_::ExprIndex(_, ref expr) | - ast::Expr_::ExprUnary(_, ref expr) => is_block_expr(expr, repr), + ast::ExprKind::Struct(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) | + ast::ExprKind::If(..) | + ast::ExprKind::IfLet(..) | + ast::ExprKind::Block(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::ForLoop(..) | + ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) | + ast::ExprKind::Binary(_, _, ref expr) | + ast::ExprKind::Index(_, ref expr) | + ast::ExprKind::Unary(_, ref expr) => is_block_expr(expr, repr), _ => false, } } fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { match expr.node { - ast::Expr_::ExprMethodCall(_, _, ref expressions) => Some(&expressions[0]), - ast::Expr_::ExprTupField(ref subexpr, _) | - ast::Expr_::ExprField(ref subexpr, _) => Some(subexpr), + ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]), + ast::ExprKind::TupField(ref subexpr, _) | + ast::ExprKind::Field(ref subexpr, _) => Some(subexpr), _ => None, } } @@ -183,7 +183,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, offset: Indent) -> Option { match expr.node { - ast::Expr_::ExprMethodCall(ref method_name, ref types, ref expressions) => { + ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => { let inner = &RewriteContext { block_indent: offset, ..*context }; rewrite_method_call(method_name.node, types, @@ -193,7 +193,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, width, offset) } - ast::Expr_::ExprField(_, ref field) => { + ast::ExprKind::Field(_, ref field) => { let s = format!(".{}", field.node); if s.len() <= width { Some(s) @@ -201,7 +201,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, None } } - ast::Expr_::ExprTupField(_, ref field) => { + ast::ExprKind::TupField(_, ref field) => { let s = format!(".{}", field.node); if s.len() <= width { Some(s) @@ -216,7 +216,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, // Determines we can continue formatting a given expression on the same line. fn is_continuable(expr: &ast::Expr) -> bool { match expr.node { - ast::Expr_::ExprPath(..) => true, + ast::ExprKind::Path(..) => true, _ => false, } } diff --git a/src/expr.rs b/src/expr.rs index 34a30e94899..6409ab8fdac 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -37,16 +37,16 @@ use syntax::visit::Visitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let result = match self.node { - ast::Expr_::ExprVec(ref expr_vec) => { + ast::ExprKind::Vec(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), mk_sp(span_after(self.span, "[", context.codemap), self.span.hi), context, width, offset) } - ast::Expr_::ExprLit(ref l) => { + ast::ExprKind::Lit(ref l) => { match l.node { - ast::Lit_::LitStr(_, ast::StrStyle::CookedStr) => { + ast::LitKind::Str(_, ast::StrStyle::Cooked) => { rewrite_string_lit(context, l.span, width, offset) } _ => { @@ -57,18 +57,18 @@ impl Rewrite for ast::Expr { } } } - ast::Expr_::ExprCall(ref callee, ref args) => { + ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, self.span.hi); rewrite_call(context, &**callee, args, inner_span, width, offset) } - ast::Expr_::ExprParen(ref subexpr) => rewrite_paren(context, subexpr, width, offset), - ast::Expr_::ExprBinary(ref op, ref lhs, ref rhs) => { + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, width, offset), + ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { rewrite_binary_op(context, op, lhs, rhs, width, offset) } - ast::Expr_::ExprUnary(ref op, ref subexpr) => { + ast::ExprKind::Unary(ref op, ref subexpr) => { rewrite_unary_op(context, op, subexpr, width, offset) } - ast::Expr_::ExprStruct(ref path, ref fields, ref base) => { + ast::ExprKind::Struct(ref path, ref fields, ref base) => { rewrite_struct_lit(context, path, fields, @@ -77,27 +77,27 @@ impl Rewrite for ast::Expr { width, offset) } - ast::Expr_::ExprTup(ref items) => { + ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, items.iter().map(|x| &**x), self.span, width, offset) } - ast::Expr_::ExprWhile(ref cond, ref block, label) => { + ast::ExprKind::While(ref cond, ref block, label) => { Loop::new_while(None, cond, block, label).rewrite(context, width, offset) } - ast::Expr_::ExprWhileLet(ref pat, ref cond, ref block, label) => { + ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { Loop::new_while(Some(pat), cond, block, label).rewrite(context, width, offset) } - ast::Expr_::ExprForLoop(ref pat, ref cond, ref block, label) => { + ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { Loop::new_for(pat, cond, block, label).rewrite(context, width, offset) } - ast::Expr_::ExprLoop(ref block, label) => { + ast::ExprKind::Loop(ref block, label) => { Loop::new_loop(block, label).rewrite(context, width, offset) } - ast::Expr_::ExprBlock(ref block) => block.rewrite(context, width, offset), - ast::Expr_::ExprIf(ref cond, ref if_block, ref else_block) => { + ast::ExprKind::Block(ref block) => block.rewrite(context, width, offset), + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { rewrite_if_else(context, cond, if_block, @@ -108,7 +108,7 @@ impl Rewrite for ast::Expr { offset, true) } - ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref else_block) => { + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { rewrite_if_else(context, cond, if_block, @@ -119,39 +119,39 @@ impl Rewrite for ast::Expr { offset, true) } - ast::Expr_::ExprMatch(ref cond, ref arms) => { + ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, width, offset, self.span) } - ast::Expr_::ExprPath(ref qself, ref path) => { + ast::ExprKind::Path(ref qself, ref path) => { rewrite_path(context, true, qself.as_ref(), path, width, offset) } - ast::Expr_::ExprAssign(ref lhs, ref rhs) => { + ast::ExprKind::Assign(ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, None, width, offset) } - ast::Expr_::ExprAssignOp(ref op, ref lhs, ref rhs) => { + ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, Some(op), width, offset) } - ast::Expr_::ExprAgain(ref opt_ident) => { + ast::ExprKind::Again(ref opt_ident) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), None => String::new(), }; Some(format!("continue{}", id_str)) } - ast::Expr_::ExprBreak(ref opt_ident) => { + ast::ExprKind::Break(ref opt_ident) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), None => String::new(), }; Some(format!("break{}", id_str)) } - ast::Expr_::ExprClosure(capture, ref fn_decl, ref body) => { + ast::ExprKind::Closure(capture, ref fn_decl, ref body) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } - ast::Expr_::ExprField(..) | - ast::Expr_::ExprTupField(..) | - ast::Expr_::ExprMethodCall(..) => rewrite_chain(self, context, width, offset), - ast::Expr_::ExprMac(ref mac) => { + ast::ExprKind::Field(..) | + ast::ExprKind::TupField(..) | + ast::ExprKind::MethodCall(..) => rewrite_chain(self, context, width, offset), + ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. rewrite_macro(mac, context, width, offset).or_else(|| { @@ -161,40 +161,43 @@ impl Rewrite for ast::Expr { offset) }) } - ast::Expr_::ExprRet(None) => { + ast::ExprKind::Ret(None) => { wrap_str("return".to_owned(), context.config.max_width, width, offset) } - ast::Expr_::ExprRet(Some(ref expr)) => { + ast::ExprKind::Ret(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", &**expr, width, offset) } - ast::Expr_::ExprBox(ref expr) => { + ast::ExprKind::Box(ref expr) => { rewrite_unary_prefix(context, "box ", &**expr, width, offset) } - ast::Expr_::ExprAddrOf(mutability, ref expr) => { + ast::ExprKind::AddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, expr, width, offset) } - ast::Expr_::ExprCast(ref expr, ref ty) => { + ast::ExprKind::Cast(ref expr, ref ty) => { rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) } - ast::Expr_::ExprIndex(ref expr, ref index) => { + // TODO(#848): Handle type ascription; rust tracking issue + // https://github.com/rust-lang/rust/issues/23416 + ast::ExprKind::Type(_, _) => unimplemented!(), + ast::ExprKind::Index(ref expr, ref index) => { rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) } - ast::Expr_::ExprRepeat(ref expr, ref repeats) => { + ast::ExprKind::Repeat(ref expr, ref repeats) => { rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) } - ast::Expr_::ExprRange(Some(ref lhs), Some(ref rhs)) => { + ast::ExprKind::Range(Some(ref lhs), Some(ref rhs)) => { rewrite_pair(&**lhs, &**rhs, "", "..", "", context, width, offset) } - ast::Expr_::ExprRange(None, Some(ref rhs)) => { + ast::ExprKind::Range(None, Some(ref rhs)) => { rewrite_unary_prefix(context, "..", &**rhs, width, offset) } - ast::Expr_::ExprRange(Some(ref lhs), None) => { + ast::ExprKind::Range(Some(ref lhs), None) => { Some(format!("{}..", try_opt!(lhs.rewrite(context, try_opt!(width.checked_sub(2)), offset)))) } - ast::Expr_::ExprRange(None, None) => { + ast::ExprKind::Range(None, None) => { if width >= 2 { Some("..".into()) } else { @@ -203,8 +206,8 @@ impl Rewrite for ast::Expr { } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::Expr_::ExprInPlace(..) | - ast::Expr_::ExprInlineAsm(..) => { + ast::ExprKind::InPlace(..) | + ast::ExprKind::InlineAsm(..) => { wrap_str(context.snippet(self.span), context.config.max_width, width, @@ -302,7 +305,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, // This functions is pretty messy because of the wrapping and unwrapping of // expressions into and from blocks. See rust issue #27872. -fn rewrite_closure(capture: ast::CaptureClause, +fn rewrite_closure(capture: ast::CaptureBy, fn_decl: &ast::FnDecl, body: &ast::Block, span: Span, @@ -310,7 +313,7 @@ fn rewrite_closure(capture: ast::CaptureClause, width: usize, offset: Indent) -> Option { - let mover = if capture == ast::CaptureClause::CaptureByValue { + let mover = if capture == ast::CaptureBy::Value { "move " } else { "" @@ -374,9 +377,8 @@ fn rewrite_closure(capture: ast::CaptureClause, // All closure bodies are blocks in the eyes of the AST, but we may not // want to unwrap them when they only contain a single expression. let inner_expr = match expr.node { - ast::Expr_::ExprBlock(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() && - inner.rules == - ast::BlockCheckMode::DefaultBlock => { + ast::ExprKind::Block(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() && + inner.rules == ast::BlockCheckMode::Default => { inner.expr.as_ref().unwrap() } _ => expr, @@ -398,7 +400,7 @@ fn rewrite_closure(capture: ast::CaptureClause, let body_rewrite = body.expr .as_ref() .and_then(|body_expr| { - if let ast::Expr_::ExprBlock(ref inner) = body_expr.node { + if let ast::ExprKind::Block(ref inner) = body_expr.node { Some(inner.rewrite(&context, 2, Indent::empty())) } else { None @@ -431,7 +433,7 @@ impl Rewrite for ast::Block { visitor.block_indent = context.block_indent; let prefix = match self.rules { - ast::BlockCheckMode::UnsafeBlock(..) => { + ast::BlockCheckMode::Unsafe(..) => { let snippet = context.snippet(self.span); let open_pos = try_opt!(snippet.find_uncommented("{")); visitor.last_pos = self.span.lo + BytePos(open_pos as u32); @@ -467,7 +469,7 @@ impl Rewrite for ast::Block { prefix } - ast::BlockCheckMode::DefaultBlock => { + ast::BlockCheckMode::Default => { visitor.last_pos = self.span.lo; String::new() @@ -483,14 +485,14 @@ impl Rewrite for ast::Block { impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, _width: usize, offset: Indent) -> Option { let result = match self.node { - ast::Stmt_::StmtDecl(ref decl, _) => { - if let ast::Decl_::DeclLocal(ref local) = decl.node { + ast::StmtKind::Decl(ref decl, _) => { + if let ast::DeclKind::Local(ref local) = decl.node { local.rewrite(context, context.config.max_width, offset) } else { None } } - ast::Stmt_::StmtExpr(ref ex, _) | ast::Stmt_::StmtSemi(ref ex, _) => { + ast::StmtKind::Expr(ref ex, _) | ast::StmtKind::Semi(ref ex, _) => { let suffix = if semicolon_for_stmt(self) { ";" } else { @@ -502,7 +504,7 @@ impl Rewrite for ast::Stmt { offset) .map(|s| s + suffix) } - ast::Stmt_::StmtMac(..) => None, + ast::StmtKind::Mac(..) => None, }; result.and_then(|res| recover_comment_removed(res, self.span, context, _width, offset)) } @@ -681,7 +683,7 @@ fn rewrite_if_else(context: &RewriteContext, let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it // from being formatted on a single line. - ast::Expr_::ExprIfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, if_block, @@ -692,7 +694,7 @@ fn rewrite_if_else(context: &RewriteContext, offset, false) } - ast::Expr_::ExprIf(ref cond, ref if_block, ref next_else_block) => { + ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, if_block, @@ -741,7 +743,7 @@ fn single_line_if_else(context: &RewriteContext, let else_block = try_opt!(else_block_opt); let fixed_cost = "if { } else { }".len(); - if let ast::ExprBlock(ref else_node) = else_block.node { + if let ast::ExprKind::Block(ref else_node) = else_block.node { if !is_simple_block(if_node, context.codemap) || !is_simple_block(else_node, context.codemap) || pat_expr_str.contains('\n') { return None; @@ -794,7 +796,7 @@ pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { } fn is_unsafe_block(block: &ast::Block) -> bool { - if let ast::BlockCheckMode::UnsafeBlock(..) = block.rules { + if let ast::BlockCheckMode::Unsafe(..) = block.rules { true } else { false @@ -925,15 +927,15 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str { if !config.match_wildcard_trailing_comma { - if arm.pats.len() == 1 && arm.pats[0].node == ast::PatWild && arm.guard.is_none() { + if arm.pats.len() == 1 && arm.pats[0].node == ast::PatKind::Wild && arm.guard.is_none() { return ""; } } if config.match_block_trailing_comma { "," - } else if let ast::ExprBlock(ref block) = body.node { - if let ast::DefaultBlock = block.rules { + } else if let ast::ExprKind::Block(ref block) = body.node { + if let ast::BlockCheckMode::Default = block.rules { "" } else { "," @@ -1015,12 +1017,9 @@ impl Rewrite for ast::Arm { } let body = match **body { - ast::Expr { node: ast::ExprBlock(ref block), .. } if !is_unsafe_block(block) && - is_simple_block(block, - context.codemap) && - context.config.wrap_match_arms => { - block.expr.as_ref().map(|e| &**e).unwrap() - } + ast::Expr { node: ast::ExprKind::Block(ref block), .. } + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && + context.config.wrap_match_arms => block.expr.as_ref().map(|e| &**e).unwrap(), ref x => x, }; @@ -1032,7 +1031,7 @@ impl Rewrite for ast::Arm { let budget = context.config.max_width - line_start - comma.len() - 4; let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); - let is_block = if let ast::ExprBlock(..) = body.node { + let is_block = if let ast::ExprKind::Block(..) = body.node { true } else { false @@ -1307,8 +1306,8 @@ fn rewrite_call_inner(context: &RewriteContext, // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. let overflow_last = match args.last().map(|x| &x.node) { - Some(&ast::Expr_::ExprClosure(..)) | - Some(&ast::Expr_::ExprBlock(..)) if arg_count > 1 => true, + Some(&ast::ExprKind::Closure(..)) | + Some(&ast::ExprKind::Block(..)) if arg_count > 1 => true, _ => false, } && context.config.chains_overflow_last; @@ -1666,9 +1665,9 @@ fn rewrite_unary_op(context: &RewriteContext, -> Option { // For some reason, an UnOp is not spanned like BinOp! let operator_str = match *op { - ast::UnOp::UnDeref => "*", - ast::UnOp::UnNot => "!", - ast::UnOp::UnNeg => "-", + ast::UnOp::Deref => "*", + ast::UnOp::Not => "!", + ast::UnOp::Neg => "-", }; rewrite_unary_prefix(context, operator_str, expr, width, offset) } @@ -1744,8 +1743,8 @@ fn rewrite_expr_addrof(context: &RewriteContext, offset: Indent) -> Option { let operator_str = match mutability { - ast::Mutability::MutImmutable => "&", - ast::Mutability::MutMutable => "&mut ", + ast::Mutability::Immutable => "&", + ast::Mutability::Mutable => "&mut ", }; rewrite_unary_prefix(context, operator_str, expr, width, offset) } diff --git a/src/imports.rs b/src/imports.rs index 70351ca8d79..38720d84cce 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -51,7 +51,7 @@ impl Rewrite for ast::ViewPath { } fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { - let path_item_str = if let ast::PathListItem_::PathListIdent { name, .. } = vpi.node { + let path_item_str = if let ast::PathListItemKind::Ident { name, .. } = vpi.node { // A name. if path_str.is_empty() { name.to_string() @@ -74,8 +74,8 @@ fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { let path_item_str = match vpi.node { - ast::PathListItem_::PathListIdent { name, .. } => name.to_string(), - ast::PathListItem_::PathListMod { .. } => "self".to_owned(), + ast::PathListItemKind::Ident { name, .. } => name.to_string(), + ast::PathListItemKind::Mod { .. } => "self".to_owned(), }; Some(append_alias(path_item_str, vpi)) @@ -83,8 +83,8 @@ fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { match vpi.node { - ast::PathListItem_::PathListIdent { rename: Some(rename), .. } | - ast::PathListItem_::PathListMod { rename: Some(rename), .. } => { + ast::PathListItemKind::Ident { rename: Some(rename), .. } | + ast::PathListItemKind::Mod { rename: Some(rename), .. } => { format!("{} as {}", path_item_str, rename) } _ => path_item_str, diff --git a/src/items.rs b/src/items.rs index d7c16c4561c..c013733f37f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -27,7 +27,6 @@ use syntax::{ast, abi}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; use syntax::ast::ImplItem; -use syntax::ptr::P; // Statements of the form // let pat: ty = init; @@ -110,7 +109,7 @@ impl<'a> FmtVisitor<'a> { let span = mk_sp(item.span.lo, item.span.hi - BytePos(1)); match item.node { - ast::ForeignItem_::ForeignItemFn(ref fn_decl, ref generics) => { + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { let indent = self.block_indent; let rewrite = rewrite_fn_base(&self.get_context(), indent, @@ -136,7 +135,7 @@ impl<'a> FmtVisitor<'a> { None => self.format_missing(item.span.hi), } } - ast::ForeignItem_::ForeignItemStatic(ref ty, is_mutable) => { + ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. let mut_str = if is_mutable { @@ -441,12 +440,12 @@ impl<'a> FmtVisitor<'a> { } pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { - if let ast::Item_::ItemImpl(unsafety, - polarity, - ref generics, - ref trait_ref, - ref self_ty, - ref items) = item.node { + if let ast::ItemKind::Impl(unsafety, + polarity, + ref generics, + ref trait_ref, + ref self_ty, + ref items) = item.node { let mut result = String::new(); result.push_str(format_visibility(item.vis)); result.push_str(format_unsafety(unsafety)); @@ -562,7 +561,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - } fn is_impl_single_line(context: &RewriteContext, - items: &Vec>, + items: &Vec, result: &str, where_clause_str: &str, item: &ast::Item) @@ -919,15 +918,15 @@ pub fn rewrite_static(prefix: &str, impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { - ast::FunctionRetTy::DefaultReturn(_) => Some(String::new()), - ast::FunctionRetTy::NoReturn(_) => { + ast::FunctionRetTy::Default(_) => Some(String::new()), + ast::FunctionRetTy::None(_) => { if width >= 4 { Some("-> !".to_owned()) } else { None } } - ast::FunctionRetTy::Return(ref ty) => { + ast::FunctionRetTy::Ty(ref ty) => { let inner_width = try_opt!(width.checked_sub(3)); ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r)) } @@ -940,7 +939,7 @@ impl Rewrite for ast::Arg { if is_named_arg(self) { let mut result = try_opt!(self.pat.rewrite(context, width, offset)); - if self.ty.node != ast::Ty_::TyInfer { + if self.ty.node != ast::TyKind::Infer { result.push_str(": "); let max_width = try_opt!(width.checked_sub(result.len())); let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len())); @@ -959,7 +958,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, context: &RewriteContext) -> Option { match explicit_self.node { - ast::ExplicitSelf_::SelfRegion(lt, m, _) => { + ast::SelfKind::Region(lt, m, _) => { let mut_str = format_mutability(m); match lt { Some(ref l) => { @@ -971,7 +970,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, None => Some(format!("&{}self", mut_str)), } } - ast::ExplicitSelf_::SelfExplicit(ref ty, _) => { + ast::SelfKind::Explicit(ref ty, _) => { assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); @@ -979,7 +978,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, Some(format!("{}self: {}", format_mutability(mutability), type_str)) } - ast::ExplicitSelf_::SelfValue(_) => { + ast::SelfKind::Value(_) => { assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); @@ -993,7 +992,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, // Hacky solution caused by absence of `Mutability` in `SelfValue` and // `SelfExplicit` variants of `ast::ExplicitSelf_`. fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { - if let ast::Pat_::PatIdent(ast::BindingMode::BindByValue(mutability), _, _) = arg.pat.node { + if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node { mutability } else { unreachable!() @@ -1010,13 +1009,13 @@ pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { pub fn span_hi_for_arg(arg: &ast::Arg) -> BytePos { match arg.ty.node { - ast::Ty_::TyInfer if is_named_arg(arg) => arg.pat.span.hi, + ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi, _ => arg.ty.span.hi, } } pub fn is_named_arg(arg: &ast::Arg) -> bool { - if let ast::Pat_::PatIdent(_, ident, _) = arg.pat.node { + if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { ident.node != token::special_idents::invalid } else { true @@ -1025,9 +1024,9 @@ pub fn is_named_arg(arg: &ast::Arg) -> bool { fn span_for_return(ret: &ast::FunctionRetTy) -> Span { match *ret { - ast::FunctionRetTy::NoReturn(ref span) | - ast::FunctionRetTy::DefaultReturn(ref span) => span.clone(), - ast::FunctionRetTy::Return(ref ty) => ty.span, + ast::FunctionRetTy::None(ref span) | + ast::FunctionRetTy::Default(ref span) => span.clone(), + ast::FunctionRetTy::Ty(ref ty) => ty.span, } } @@ -1085,7 +1084,7 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str("const "); } - if abi != abi::Rust { + if abi != abi::Abi::Rust { result.push_str(&::utils::format_abi(abi)); } diff --git a/src/lib.rs b/src/lib.rs index ee671cf0baa..7e074f05124 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,13 +26,15 @@ extern crate diff; extern crate term; use syntax::ast; -use syntax::codemap::{mk_sp, Span}; -use syntax::diagnostic::{EmitterWriter, Handler}; +use syntax::codemap::{mk_sp, CodeMap, Span}; +use syntax::errors::Handler; +use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; use std::io::stdout; use std::ops::{Add, Sub}; use std::path::Path; +use std::rc::Rc; use std::collections::HashMap; use std::fmt; @@ -367,15 +369,23 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { pub fn format_string(input: String, config: &Config) -> FileMap { let path = "stdin"; - let mut parse_session = ParseSess::new(); + let codemap = Rc::new(CodeMap::new()); + + let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, + None, + true, + false, + codemap.clone()); + let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + let krate = parse::parse_crate_from_source_str(path.to_owned(), input, Vec::new(), &parse_session); // Suppress error output after parsing. - let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); - parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); + let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); // FIXME: we still use a FileMap even though we only have // one file, because fmt_lines requires a FileMap @@ -393,12 +403,20 @@ pub fn format_string(input: String, config: &Config) -> FileMap { } pub fn format(file: &Path, config: &Config) -> FileMap { - let mut parse_session = ParseSess::new(); + let codemap = Rc::new(CodeMap::new()); + + let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, + None, + true, + false, + codemap.clone()); + let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); // Suppress error output after parsing. - let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None)); - parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter); + let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); let mut file_map = fmt_ast(&krate, &parse_session, file, config); diff --git a/src/modules.rs b/src/modules.rs index 3f96bea9d44..e56fa57ac7b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -40,7 +40,7 @@ fn list_submodules<'a>(module: &'a ast::Mod, result: &mut HashMap) { debug!("list_submodules: search_dir: {:?}", search_dir); for item in &module.items { - if let ast::ItemMod(ref sub_mod) = item.node { + if let ast::ItemKind::Mod(ref sub_mod) = item.node { if !utils::contains_skip(&item.attrs) { let is_internal = codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); diff --git a/src/patterns.rs b/src/patterns.rs index a5f09823212..a761ad538f5 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,16 +15,16 @@ use lists::{format_item_list, itemize_list}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use types::rewrite_path; -use syntax::ast::{BindingMode, Pat, Pat_, FieldPat}; +use syntax::ast::{BindingMode, Pat, PatKind, FieldPat}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { - Pat_::PatBox(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, width, offset), - Pat_::PatIdent(binding_mode, ident, ref sub_pat) => { + PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, width, offset), + PatKind::Ident(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { - BindingMode::BindByRef(mutability) => ("ref ", mutability), - BindingMode::BindByValue(mutability) => ("", mutability), + BindingMode::ByRef(mutability) => ("ref ", mutability), + BindingMode::ByValue(mutability) => ("", mutability), }; let mut_infix = format_mutability(mutability); let id_str = ident.node.to_string(); @@ -43,31 +43,32 @@ impl Rewrite for Pat { let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); wrap_str(result, context.config.max_width, width, offset) } - Pat_::PatWild => { + PatKind::Wild => { if 1 <= width { Some("_".to_owned()) } else { None } } - Pat_::PatQPath(ref q_self, ref path) => { + PatKind::QPath(ref q_self, ref path) => { rewrite_path(context, true, Some(q_self), path, width, offset) } - Pat_::PatRange(ref lhs, ref rhs) => { + PatKind::Range(ref lhs, ref rhs) => { rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset) } - Pat_::PatRegion(ref pat, mutability) => { + PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, width, offset) } - Pat_::PatTup(ref items) => { + PatKind::Tup(ref items) => { rewrite_tuple(context, items.iter().map(|x| &**x), self.span, width, offset) } - Pat_::PatEnum(ref path, ref pat_vec) => { + PatKind::Path(ref path) => rewrite_path(context, true, None, path, width, offset), + PatKind::TupleStruct(ref path, ref pat_vec) => { let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); match *pat_vec { @@ -97,8 +98,8 @@ impl Rewrite for Pat { None => Some(format!("{}(..)", path_str)), } } - Pat_::PatLit(ref expr) => expr.rewrite(context, width, offset), - Pat_::PatVec(ref prefix, ref slice_pat, ref suffix) => { + PatKind::Lit(ref expr) => expr.rewrite(context, width, offset), + PatKind::Vec(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, width, offset)); let slice_pat = slice_pat.as_ref().map(|p| { @@ -118,7 +119,7 @@ impl Rewrite for Pat { let result = format!("[{}]", pats.join(", ")); wrap_str(result, context.config.max_width, width, offset) } - Pat_::PatStruct(ref path, ref fields, elipses) => { + PatKind::Struct(ref path, ref fields, elipses) => { let path = try_opt!(rewrite_path(context, true, None, path, width, offset)); let (elipses_str, terminator) = if elipses { @@ -167,7 +168,7 @@ impl Rewrite for Pat { } } // FIXME(#819) format pattern macros. - Pat_::PatMac(..) => { + PatKind::Mac(..) => { wrap_str(context.snippet(self.span), context.config.max_width, width, diff --git a/src/types.rs b/src/types.rs index 4f930f22cad..5a08e176618 100644 --- a/src/types.rs +++ b/src/types.rs @@ -172,9 +172,9 @@ fn rewrite_segment(expr_context: bool, let offset = offset + ident_len; let params = match segment.parameters { - ast::PathParameters::AngleBracketedParameters(ref data) if !data.lifetimes.is_empty() || - !data.types.is_empty() || - !data.bindings.is_empty() => { + ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() || + !data.types.is_empty() || + !data.bindings.is_empty() => { let param_list = data.lifetimes .iter() .map(SegmentParam::LifeTime) @@ -213,10 +213,10 @@ fn rewrite_segment(expr_context: bool, format!("{}<{}>", separator, list_str) } - ast::PathParameters::ParenthesizedParameters(ref data) => { + ast::PathParameters::Parenthesized(ref data) => { let output = match data.output { - Some(ref ty) => FunctionRetTy::Return(ty.clone()), - None => FunctionRetTy::DefaultReturn(codemap::DUMMY_SP), + Some(ref ty) => FunctionRetTy::Ty(ty.clone()), + None => FunctionRetTy::Default(codemap::DUMMY_SP), }; try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), &output, @@ -259,13 +259,13 @@ fn format_function_type<'a, I>(inputs: I, let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); let output = match *output { - FunctionRetTy::Return(ref ty) => { + FunctionRetTy::Ty(ref ty) => { let budget = try_opt!(width.checked_sub(4)); let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); format!(" -> {}", type_str) } - FunctionRetTy::NoReturn(..) => " -> !".to_owned(), - FunctionRetTy::DefaultReturn(..) => String::new(), + FunctionRetTy::None(..) => " -> !".to_owned(), + FunctionRetTy::Default(..) => String::new(), }; let infix = if output.len() + list_str.len() > width { @@ -470,7 +470,7 @@ impl Rewrite for ast::TraitRef { impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { - ast::TyObjectSum(ref ty, ref bounds) => { + ast::TyKind::ObjectSum(ref ty, ref bounds) => { let ty_str = try_opt!(ty.rewrite(context, width, offset)); let overhead = ty_str.len() + 3; let plus_str = match context.config.type_punctuation_density { @@ -484,15 +484,15 @@ impl Rewrite for ast::Ty { try_opt!(width.checked_sub(overhead)), offset + overhead)))) } - ast::TyPtr(ref mt) => { + ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { - Mutability::MutMutable => "*mut ", - Mutability::MutImmutable => "*const ", + Mutability::Mutable => "*mut ", + Mutability::Immutable => "*const ", }; rewrite_unary_prefix(context, prefix, &*mt.ty, width, offset) } - ast::TyRptr(ref lifetime, ref mt) => { + ast::TyKind::Rptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); Some(match *lifetime { @@ -520,39 +520,39 @@ impl Rewrite for ast::Ty { } // FIXME: we drop any comments here, even though it's a silly place to put // comments. - ast::TyParen(ref ty) => { + ast::TyKind::Paren(ref ty) => { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) } - ast::TyVec(ref ty) => { + ast::TyKind::Vec(ref ty) => { let budget = try_opt!(width.checked_sub(2)); ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str)) } - ast::TyTup(ref items) => { + ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter().map(|x| &**x), self.span, width, offset) } - ast::TyPolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), - ast::TyPath(ref q_self, ref path) => { + ast::TyKind::PolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), + ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, false, q_self.as_ref(), path, width, offset) } - ast::TyFixedLengthVec(ref ty, ref repeats) => { + ast::TyKind::FixedLengthVec(ref ty, ref repeats) => { rewrite_pair(&**ty, &**repeats, "[", "; ", "]", context, width, offset) } - ast::TyInfer => { + ast::TyKind::Infer => { if width >= 1 { Some("_".to_owned()) } else { None } } - ast::TyBareFn(ref bare_fn) => { + ast::TyKind::BareFn(ref bare_fn) => { rewrite_bare_fn(bare_fn, self.span, context, width, offset) } - ast::TyMac(..) | ast::TyTypeof(..) => unreachable!(), + ast::TyKind::Mac(..) | ast::TyKind::Typeof(..) => unreachable!(), } } } @@ -567,7 +567,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str(&::utils::format_unsafety(bare_fn.unsafety)); - if bare_fn.abi != abi::Rust { + if bare_fn.abi != abi::Abi::Rust { result.push_str(&::utils::format_abi(bare_fn.abi)); } diff --git a/src/utils.rs b/src/utils.rs index 3b03ede2be3..acf758087d4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,7 +10,7 @@ use std::cmp::Ordering; -use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_}; +use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind}; use syntax::codemap::{CodeMap, Span, BytePos}; use syntax::abi; @@ -77,8 +77,8 @@ pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { #[inline] pub fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { - ast::Mutability::MutMutable => "mut ", - ast::Mutability::MutImmutable => "", + ast::Mutability::Mutable => "mut ", + ast::Mutability::Immutable => "", } } @@ -109,8 +109,8 @@ pub fn last_line_width(s: &str) -> usize { #[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { - MetaItem_::MetaWord(ref s) => *s == SKIP_ANNOTATION, - MetaItem_::MetaList(ref s, ref l) => *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1]), + MetaItemKind::Word(ref s) => *s == SKIP_ANNOTATION, + MetaItemKind::List(ref s, ref l) => *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1]), _ => false, } } @@ -137,9 +137,9 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { #[inline] pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { match expr.node { - ast::Expr_::ExprRet(..) | - ast::Expr_::ExprAgain(..) | - ast::Expr_::ExprBreak(..) => true, + ast::ExprKind::Ret(..) | + ast::ExprKind::Again(..) | + ast::ExprKind::Break(..) => true, _ => false, } } @@ -147,16 +147,16 @@ pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { #[inline] pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { match stmt.node { - ast::Stmt_::StmtSemi(ref expr, _) => { + ast::StmtKind::Semi(ref expr, _) => { match expr.node { - ast::Expr_::ExprWhile(..) | - ast::Expr_::ExprWhileLet(..) | - ast::Expr_::ExprLoop(..) | - ast::Expr_::ExprForLoop(..) => false, + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::ForLoop(..) => false, _ => true, } } - ast::Stmt_::StmtExpr(..) => false, + ast::StmtKind::Expr(..) => false, _ => true, } } diff --git a/src/visitor.rs b/src/visitor.rs index f53ed2246d5..ae93ee52aab 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -36,8 +36,8 @@ pub struct FmtVisitor<'a> { impl<'a> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { match stmt.node { - ast::Stmt_::StmtDecl(ref decl, _) => { - if let ast::Decl_::DeclItem(ref item) = decl.node { + ast::StmtKind::Decl(ref decl, _) => { + if let ast::DeclKind::Item(ref item) = decl.node { self.visit_item(item); } else { let rewrite = stmt.rewrite(&self.get_context(), @@ -47,14 +47,14 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(stmt.span, rewrite); } } - ast::Stmt_::StmtExpr(..) | ast::Stmt_::StmtSemi(..) => { + ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let rewrite = stmt.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), self.block_indent); self.push_rewrite(stmt.span, rewrite); } - ast::Stmt_::StmtMac(ref mac, _macro_style, _) => { + ast::StmtKind::Mac(ref mac, _macro_style, _) => { self.format_missing_with_indent(stmt.span.lo); self.visit_mac(mac); } @@ -183,7 +183,7 @@ impl<'a> FmtVisitor<'a> { // FIXME This is overly conservative and means we miss attributes on // inline modules. match item.node { - ast::Item_::ItemMod(_) => { + ast::ItemKind::Mod(_) => { if utils::contains_skip(&item.attrs) { return; } @@ -197,10 +197,10 @@ impl<'a> FmtVisitor<'a> { } match item.node { - ast::Item_::ItemUse(ref vp) => { + ast::ItemKind::Use(ref vp) => { self.format_import(item.vis, vp, item.span); } - ast::Item_::ItemImpl(..) => { + ast::ItemKind::Impl(..) => { self.format_missing_with_indent(item.span.lo); if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent) { self.buffer.push_str(&impl_str); @@ -208,7 +208,7 @@ impl<'a> FmtVisitor<'a> { } } // FIXME(#78): format traits. - ast::Item_::ItemTrait(_, _, _, ref trait_items) => { + ast::ItemKind::Trait(_, _, _, ref trait_items) => { self.format_missing_with_indent(item.span.lo); self.block_indent = self.block_indent.block_indent(self.config); for item in trait_items { @@ -216,13 +216,13 @@ impl<'a> FmtVisitor<'a> { } self.block_indent = self.block_indent.block_unindent(self.config); } - ast::Item_::ItemExternCrate(_) => { + ast::ItemKind::ExternCrate(_) => { self.format_missing_with_indent(item.span.lo); let new_str = self.snippet(item.span); self.buffer.push_str(&new_str); self.last_pos = item.span.hi; } - ast::Item_::ItemStruct(ref def, ref generics) => { + ast::ItemKind::Struct(ref def, ref generics) => { let rewrite = { let indent = self.block_indent; let context = self.get_context(); @@ -243,24 +243,24 @@ impl<'a> FmtVisitor<'a> { }; self.push_rewrite(item.span, rewrite); } - ast::Item_::ItemEnum(ref def, ref generics) => { + ast::ItemKind::Enum(ref def, ref generics) => { self.format_missing_with_indent(item.span.lo); self.visit_enum(item.ident, item.vis, def, generics, item.span); self.last_pos = item.span.hi; } - ast::Item_::ItemMod(ref module) => { + ast::ItemKind::Mod(ref module) => { self.format_missing_with_indent(item.span.lo); self.format_mod(module, item.vis, item.span, item.ident); } - ast::Item_::ItemMac(ref mac) => { + ast::ItemKind::Mac(ref mac) => { self.format_missing_with_indent(item.span.lo); self.visit_mac(mac); } - ast::Item_::ItemForeignMod(ref foreign_mod) => { + ast::ItemKind::ForeignMod(ref foreign_mod) => { self.format_missing_with_indent(item.span.lo); self.format_foreign_mod(foreign_mod, item.span); } - ast::Item_::ItemStatic(ref ty, mutability, ref expr) => { + ast::ItemKind::Static(ref ty, mutability, ref expr) => { let rewrite = rewrite_static("static", item.vis, item.ident, @@ -270,32 +270,32 @@ impl<'a> FmtVisitor<'a> { &self.get_context()); self.push_rewrite(item.span, rewrite); } - ast::Item_::ItemConst(ref ty, ref expr) => { + ast::ItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static("const", item.vis, item.ident, ty, - ast::Mutability::MutImmutable, + ast::Mutability::Immutable, expr, &self.get_context()); self.push_rewrite(item.span, rewrite); } - ast::Item_::ItemDefaultImpl(..) => { + ast::ItemKind::DefaultImpl(..) => { // FIXME(#78): format impl definitions. } - ast::ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { + ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { self.visit_fn(visit::FnKind::ItemFn(item.ident, generics, unsafety, constness, abi, item.vis), - declaration, + decl, body, item.span, item.id) } - ast::Item_::ItemTy(ref ty, ref generics) => { + ast::ItemKind::Ty(ref ty, ref generics) => { let rewrite = rewrite_type_alias(&self.get_context(), self.block_indent, item.ident, @@ -314,22 +314,22 @@ impl<'a> FmtVisitor<'a> { } match ti.node { - ast::ConstTraitItem(..) => { + ast::TraitItemKind::Const(..) => { // FIXME: Implement } - ast::MethodTraitItem(ref sig, None) => { + ast::TraitItemKind::Method(ref sig, None) => { let indent = self.block_indent; let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); self.push_rewrite(ti.span, rewrite); } - ast::MethodTraitItem(ref sig, Some(ref body)) => { + ast::TraitItemKind::Method(ref sig, Some(ref body)) => { self.visit_fn(visit::FnKind::Method(ti.ident, sig, None), &sig.decl, &body, ti.span, ti.id); } - ast::TypeTraitItem(..) => { + ast::TraitItemKind::Type(..) => { // FIXME: Implement } } -- cgit 1.4.1-3-g733a5 From 698027c4c423ca5cd5696a2a0b72a443abefb429 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 2 Mar 2016 15:37:20 +0000 Subject: Fix ordering of "const unsafe fn" --- src/items.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c013733f37f..9e5b964429e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1078,12 +1078,13 @@ fn rewrite_fn_base(context: &RewriteContext, let mut result = String::with_capacity(1024); // Vis unsafety abi. result.push_str(format_visibility(vis)); - result.push_str(::utils::format_unsafety(unsafety)); if let ast::Constness::Const = constness { result.push_str("const "); } + result.push_str(::utils::format_unsafety(unsafety)); + if abi != abi::Abi::Rust { result.push_str(&::utils::format_abi(abi)); } -- cgit 1.4.1-3-g733a5 From d216c358ef6fe626af6bfe1657291b093d920da2 Mon Sep 17 00:00:00 2001 From: Jason Dusek Date: Tue, 8 Mar 2016 21:52:58 -0800 Subject: Write non-output to stderr when there is output --- src/bin/rustfmt.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 1524384fc12..b7492fdc2fe 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -28,6 +28,15 @@ use std::str::FromStr; use getopts::{Matches, Options}; +macro_rules! msg( + ($($arg:tt)*) => ( + match writeln!(&mut ::std::io::stderr(), $($arg)* ) { + Ok(_) => {}, + Err(x) => panic!("Unable to write to stderr: {}", x), + } + ) +); + /// Rustfmt operations. enum Operation { /// Format files and their child modules. @@ -203,7 +212,7 @@ fn execute() -> i32 { path = path_tmp; }; if let Some(path) = path.as_ref() { - println!("Using rustfmt config file {}", path.display()); + msg!("Using rustfmt config file {}", path.display()); } for file in files { // Check the file directory if the config-path could not be read or not provided @@ -213,7 +222,7 @@ fn execute() -> i32 { for {}", file.display())); if let Some(path) = path_tmp.as_ref() { - println!("Using rustfmt config file {} for {}", + msg!("Using rustfmt config file {} for {}", path.display(), file.display()); } -- cgit 1.4.1-3-g733a5 From 223df90c81d5e94796797067fe4176cd2e00a93c Mon Sep 17 00:00:00 2001 From: Jason Dusek Date: Wed, 9 Mar 2016 11:03:57 -0800 Subject: Align arguments --- src/bin/rustfmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index b7492fdc2fe..ee5877e25ca 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -223,8 +223,8 @@ fn execute() -> i32 { file.display())); if let Some(path) = path_tmp.as_ref() { msg!("Using rustfmt config file {} for {}", - path.display(), - file.display()); + path.display(), + file.display()); } config = config_tmp; } -- cgit 1.4.1-3-g733a5 From 867b5074aa2d01ba72a2de89865fb7a7aa25a76a Mon Sep 17 00:00:00 2001 From: Jason Dusek Date: Fri, 11 Mar 2016 00:41:11 -0800 Subject: Use braces, not parens, for macro def --- src/bin/rustfmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index ee5877e25ca..062c60e1065 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -28,14 +28,14 @@ use std::str::FromStr; use getopts::{Matches, Options}; -macro_rules! msg( +macro_rules! msg { ($($arg:tt)*) => ( match writeln!(&mut ::std::io::stderr(), $($arg)* ) { Ok(_) => {}, Err(x) => panic!("Unable to write to stderr: {}", x), } ) -); +} /// Rustfmt operations. enum Operation { -- cgit 1.4.1-3-g733a5 From 35dfcc007868e3fe1118c677efc1594bfce9c575 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 14:18:30 -0700 Subject: Adding trait formatting trait header formatting finished generic formatting finished added basic trait bounds formatting --- src/items.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/missed_spans.rs | 8 +++--- src/visitor.rs | 10 ++++++-- tests/source/trait.rs | 2 ++ tests/target/trait.rs | 2 ++ 5 files changed, 83 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d9c21c339cb..5586ad16564 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; -use syntax::{ast, abi}; +use syntax::{ast, abi, ptr}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; @@ -572,6 +572,50 @@ pub fn format_struct(context: &RewriteContext, } } +pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { + if let ast::Item_::ItemTrait(unsafety, ref generics, ref type_param_bounds, ref trait_items) = + item.node { + let mut result = String::new(); + let header = format!("{}{}trait {}", + format_visibility(item.vis), + format_unsafety(unsafety), + item.ident); + + result.push_str(&header); + + // TODO: Add max_width checking + // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); + // let indent = offset + result.len(); + + let body_lo = span_after(item.span, "{", context.codemap); + + let generics_str = try_opt!(rewrite_generics(context, + generics, + offset, + context.config.max_width, + offset + result.len(), + mk_sp(item.span.lo, body_lo))); + result.push_str(&generics_str); + + let trait_bound_str = try_opt!(rewrite_trait_bounds(context, + type_param_bounds, + offset, + 0)); + + result.push_str(&trait_bound_str); + + if trait_items.len() > 0 { + result.push_str(" {"); + } else { + result.push_str(" {}"); + } + + Some(result) + } else { + unreachable!(); + } +} + fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> Option { let mut result = String::with_capacity(1024); @@ -1437,6 +1481,28 @@ fn rewrite_generics(context: &RewriteContext, Some(format!("<{}>", list_str)) } +fn rewrite_trait_bounds(context: &RewriteContext, + param_bounds: &ast::TyParamBounds, + indent: Indent, + width: usize) + -> Option { + let bounds: &[_] = ¶m_bounds.as_slice(); + + if bounds.is_empty() { + return Some(String::new()); + } + + let bound_str = bounds.iter() + .filter_map(|ty_bound| ty_bound.rewrite(&context, 100, indent)) + .collect::>() + .join(" + "); + + let mut result = String::new(); + result.push_str(" : "); + result.push_str(&bound_str); + Some(result) +} + fn rewrite_where_clause(context: &RewriteContext, where_clause: &ast::WhereClause, config: &Config, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 67661143ddf..8e4c2281442 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -47,10 +47,10 @@ impl<'a> FmtVisitor<'a> { return; } - assert!(start < end, - "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end)); + // assert!(start < end, + // "Request to format inverted span: {:?} to {:?}", + // self.codemap.lookup_char_pos(start), + // self.codemap.lookup_char_pos(end)); self.last_pos = end; let span = codemap::mk_sp(start, end); diff --git a/src/visitor.rs b/src/visitor.rs index f0efde9de64..3a8bb0bae8f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_type_alias, format_impl}; +use items::{rewrite_static, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -209,8 +209,14 @@ impl<'a> FmtVisitor<'a> { } } // FIXME(#78): format traits. - ast::Item_::ItemTrait(_, _, _, ref trait_items) => { + ast::Item_::ItemTrait(unsafety, ref generics, ref param_bounds, ref trait_items) => { self.format_missing_with_indent(item.span.lo); + if let Some(trait_str) = format_trait(&self.get_context(), + item, + self.block_indent) { + self.buffer.push_str(&trait_str); + self.last_pos = item.span.hi; + } self.block_indent = self.block_indent.block_indent(self.config); for item in trait_items { self.visit_trait_item(&item); diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 5e7a0c78ba7..49b314358f2 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -35,3 +35,5 @@ trait TraitWithExpr { trait Test { fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; } + +trait T<> {} diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 241f5d05b7c..32389431284 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -34,3 +34,5 @@ trait Test { fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; } + +trait T {} -- cgit 1.4.1-3-g733a5 From 9e583ce7a7bda498ed256216a040b8c660eb15b4 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 14:49:11 -0700 Subject: Added where clause formatting --- src/items.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5586ad16564..85e25c0b95a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -604,6 +604,25 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&trait_bound_str); + let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let where_clause_str = try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.config.item_brace_style, + context.block_indent, + where_budget, + context.config.where_density, + "{", + None)); + if !where_clause_str.contains('\n') && + result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + result.push('\n'); + let width = context.block_indent.width() + context.config.tab_spaces - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string(context.config)); + } + result.push_str(&where_clause_str); + if trait_items.len() > 0 { result.push_str(" {"); } else { -- cgit 1.4.1-3-g733a5 From d24c31f74ca9f7c51576ce7151c99de0e2ffcb0a Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 22:32:08 -0700 Subject: Added support for associated type rewriting --- src/items.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++--------- src/visitor.rs | 30 +++++++++++++++++++++-------- 2 files changed, 73 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 85e25c0b95a..38ae285197e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; -use syntax::{ast, abi, ptr}; +use syntax::{ast, abi}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; @@ -600,8 +600,14 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let trait_bound_str = try_opt!(rewrite_trait_bounds(context, type_param_bounds, offset, - 0)); + context.config.max_width)); + if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { + result.push('\n'); + let width = context.block_indent.width() + context.config.tab_spaces - 1; + let trait_indent = Indent::new(0, width); + result.push_str(&trait_indent.to_string(context.config)); + } result.push_str(&trait_bound_str); let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); @@ -623,12 +629,48 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&where_clause_str); - if trait_items.len() > 0 { - result.push_str(" {"); - } else { - result.push_str(" {}"); + match context.config.item_brace_style { + BraceStyle::AlwaysNextLine => { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + }, + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push(' '); + } + } + } + result.push('{'); + + let snippet = context.snippet(item.span); + let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + + if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + visitor.block_indent = context.block_indent.block_indent(context.config); + visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + + for item in trait_items { + visitor.visit_trait_item(&item); + } + + visitor.format_missing(item.span.hi - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string(context.config); + let outer_indent_str = context.block_indent.to_string(context.config); + + result.push('\n'); + result.push_str(&inner_indent_str); + result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); + result.push('\n'); + result.push_str(&outer_indent_str); } + result.push('}'); Some(result) } else { unreachable!(); @@ -1501,18 +1543,18 @@ fn rewrite_generics(context: &RewriteContext, } fn rewrite_trait_bounds(context: &RewriteContext, - param_bounds: &ast::TyParamBounds, + type_param_bounds: &ast::TyParamBounds, indent: Indent, width: usize) -> Option { - let bounds: &[_] = ¶m_bounds.as_slice(); + let bounds: &[_] = &type_param_bounds.as_slice(); if bounds.is_empty() { return Some(String::new()); } let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&context, 100, indent)) + .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) .collect::>() .join(" + "); diff --git a/src/visitor.rs b/src/visitor.rs index 3a8bb0bae8f..22f9807b8c5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -217,11 +217,11 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&trait_str); self.last_pos = item.span.hi; } - self.block_indent = self.block_indent.block_indent(self.config); - for item in trait_items { - self.visit_trait_item(&item); - } - self.block_indent = self.block_indent.block_unindent(self.config); + // self.block_indent = self.block_indent.block_indent(self.config); + // for item in trait_items { + // self.visit_trait_item(&item); + // } + // self.block_indent = self.block_indent.block_unindent(self.config); } ast::Item_::ItemExternCrate(_) => { self.format_missing_with_indent(item.span.lo); @@ -319,7 +319,7 @@ impl<'a> FmtVisitor<'a> { } } - fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { if self.visit_attrs(&ti.attrs) { return; } @@ -340,8 +340,22 @@ impl<'a> FmtVisitor<'a> { ti.span, ti.id); } - ast::TypeTraitItem(..) => { - // FIXME: Implement + ast::TypeTraitItem(ref type_param_bounds, _) => { + let indent = self.block_indent; + let mut result = String::new(); + result.push_str(&format!("type {}", ti.ident)); + + let bounds: &[_] = &type_param_bounds.as_slice(); + let bound_str = bounds.iter() + .filter_map(|ty_bound| ty_bound.rewrite(&self.get_context(), self.config.max_width, indent)) + .collect::>() + .join(" + "); + if bounds.len() > 0 { + result.push_str(&format!(": {}", bound_str)); + } + + result.push(';'); + self.push_rewrite(ti.span, Some(result)); } } } -- cgit 1.4.1-3-g733a5 From 34651c4f78d811e01a87d6705c85c978d2ed452d Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 22:41:22 -0700 Subject: Fixed formatting --- src/items.rs | 16 ++++++++-------- src/visitor.rs | 10 +++++++--- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 38ae285197e..145c5ee1756 100644 --- a/src/items.rs +++ b/src/items.rs @@ -633,7 +633,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) BraceStyle::AlwaysNextLine => { result.push('\n'); result.push_str(&offset.to_string(context.config)); - }, + } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if !where_clause_str.is_empty() { @@ -1543,10 +1543,10 @@ fn rewrite_generics(context: &RewriteContext, } fn rewrite_trait_bounds(context: &RewriteContext, - type_param_bounds: &ast::TyParamBounds, - indent: Indent, - width: usize) - -> Option { + type_param_bounds: &ast::TyParamBounds, + indent: Indent, + width: usize) + -> Option { let bounds: &[_] = &type_param_bounds.as_slice(); if bounds.is_empty() { @@ -1554,9 +1554,9 @@ fn rewrite_trait_bounds(context: &RewriteContext, } let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) - .collect::>() - .join(" + "); + .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) + .collect::>() + .join(" + "); let mut result = String::new(); result.push_str(" : "); diff --git a/src/visitor.rs b/src/visitor.rs index 22f9807b8c5..31e5fb9a27a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -347,9 +347,13 @@ impl<'a> FmtVisitor<'a> { let bounds: &[_] = &type_param_bounds.as_slice(); let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&self.get_context(), self.config.max_width, indent)) - .collect::>() - .join(" + "); + .filter_map(|ty_bound| { + ty_bound.rewrite(&self.get_context(), + self.config.max_width, + indent) + }) + .collect::>() + .join(" + "); if bounds.len() > 0 { result.push_str(&format!(": {}", bound_str)); } -- cgit 1.4.1-3-g733a5 From de95b4cefb5acb9bad4048551575b2b3a33d437b Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 22:50:30 -0700 Subject: Removed unneeded pattern matching --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 31e5fb9a27a..2eb4afa22fb 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -209,7 +209,7 @@ impl<'a> FmtVisitor<'a> { } } // FIXME(#78): format traits. - ast::Item_::ItemTrait(unsafety, ref generics, ref param_bounds, ref trait_items) => { + ast::Item_::ItemTrait(..) => { self.format_missing_with_indent(item.span.lo); if let Some(trait_str) = format_trait(&self.get_context(), item, -- cgit 1.4.1-3-g733a5 From 87a5d88aeb0cda9fcd82c8e24080ed85c85a465f Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Sat, 12 Mar 2016 10:53:47 -0700 Subject: Uncommented missed spans check --- src/missed_spans.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 8e4c2281442..67661143ddf 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -47,10 +47,10 @@ impl<'a> FmtVisitor<'a> { return; } - // assert!(start < end, - // "Request to format inverted span: {:?} to {:?}", - // self.codemap.lookup_char_pos(start), - // self.codemap.lookup_char_pos(end)); + assert!(start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end)); self.last_pos = end; let span = codemap::mk_sp(start, end); -- cgit 1.4.1-3-g733a5 From d82d9fc808bfa3f99844ed40f622c8a53e2d267e Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 7 Mar 2016 13:41:32 -0500 Subject: utils: Add CodeMapSpanUtils trait for span_* methods This commit adds a CodeMapSpanUtils extension trait on CodeMap, and moves some functions to methods there: - span_after - span_after_last - span_before This better reflects them being lookup methods on the codemap. --- src/expr.rs | 33 +++++++++++++++--------------- src/imports.rs | 4 ++-- src/items.rs | 23 ++++++++++----------- src/macros.rs | 7 +++---- src/patterns.rs | 6 +++--- src/types.rs | 6 +++--- src/utils.rs | 62 ++++++++++++++++++++++++++++++++------------------------- src/visitor.rs | 4 ++-- 8 files changed, 75 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 34a30e94899..10d8330f51a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,7 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; use string::{StringFormat, rewrite_string}; -use utils::{span_after, span_before, extra_offset, last_line_width, wrap_str, binary_search, +use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle}; @@ -39,7 +39,7 @@ impl Rewrite for ast::Expr { let result = match self.node { ast::Expr_::ExprVec(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), - mk_sp(span_after(self.span, "[", context.codemap), self.span.hi), + mk_sp(context.codemap.span_after(self.span, "["), self.span.hi), context, width, offset) @@ -332,7 +332,7 @@ fn rewrite_closure(capture: ast::CaptureClause, |arg| span_lo_for_arg(arg), |arg| span_hi_for_arg(arg), |arg| arg.rewrite(context, budget, argument_offset), - span_after(span, "|", context.codemap), + context.codemap.span_after(span, "|"), body.span.lo); let item_vec = arg_items.collect::>(); let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget); @@ -660,9 +660,9 @@ fn rewrite_if_else(context: &RewriteContext, let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); - let between_if_cond = mk_sp(span_after(span, "if", context.codemap), + let between_if_cond = mk_sp(context.codemap.span_after(span, "if"), pat.map_or(cond.span.lo, - |_| span_before(span, "let", context.codemap))); + |_| context.codemap.span_before(span, "let"))); let between_if_cond_comment = extract_comment(between_if_cond, &context, offset, width); @@ -707,17 +707,17 @@ fn rewrite_if_else(context: &RewriteContext, }; let between_if_else_block = mk_sp(if_block.span.hi, - span_before(mk_sp(if_block.span.hi, else_block.span.lo), - "else", - context.codemap)); + context.codemap.span_before(mk_sp(if_block.span.hi, + else_block.span.lo), + "else")); let between_if_else_block_comment = extract_comment(between_if_else_block, &context, offset, width); - let after_else = mk_sp(span_after(mk_sp(if_block.span.hi, else_block.span.lo), - "else", - context.codemap), + let after_else = mk_sp(context.codemap + .span_after(mk_sp(if_block.span.hi, else_block.span.lo), + "else"), else_block.span.lo); let after_else_comment = extract_comment(after_else, &context, offset, width); @@ -863,9 +863,8 @@ fn rewrite_match(context: &RewriteContext, let arm_indent = nested_context.block_indent; let arm_indent_str = arm_indent.to_string(context.config); - let open_brace_pos = span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), - "{", - context.codemap); + let open_brace_pos = context.codemap + .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. @@ -1275,7 +1274,7 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Greater), }; - let span_lo = span_after(span, "(", context.codemap); + let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); let extra_offset = extra_offset(&callee_str, offset); @@ -1461,7 +1460,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } } }, - span_after(span, "{", context.codemap), + context.codemap.span_after(span, "{"), span.hi); let item_vec = items.collect::>(); @@ -1569,7 +1568,7 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, return items.next().unwrap().rewrite(context, budget, indent).map(|s| format!("({},)", s)); } - let list_lo = span_after(span, "(", context.codemap); + let list_lo = context.codemap.span_after(span, "("); let items = itemize_list(context.codemap, items, ")", diff --git a/src/imports.rs b/src/imports.rs index 70351ca8d79..8fa0347329c 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -11,7 +11,7 @@ use Indent; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; use types::rewrite_path; -use utils::span_after; +use utils::CodeMapSpanUtils; use rewrite::{Rewrite, RewriteContext}; use syntax::ast; @@ -130,7 +130,7 @@ pub fn rewrite_use_list(width: usize, |vpi| vpi.span.lo, |vpi| vpi.span.hi, rewrite_path_item, - span_after(span, "{", context.codemap), + context.codemap.span_after(span, "{"), span.hi); items.extend(iter); items diff --git a/src/items.rs b/src/items.rs index d7c16c4561c..4ba0897ef62 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,9 +11,8 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use Indent; -use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram, - wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines, - span_after_last}; +use utils::{CodeMapSpanUtils, format_mutability, format_visibility, contains_skip, end_typaram, + wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; @@ -452,7 +451,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - result.push_str(format_unsafety(unsafety)); result.push_str("impl"); - let lo = span_after(item.span, "impl", context.codemap); + let lo = context.codemap.span_after(item.span, "impl"); let hi = match *trait_ref { Some(ref tr) => tr.path.span.lo, None => self_ty.span.lo, @@ -633,7 +632,7 @@ fn format_struct_struct(context: &RewriteContext, let header_str = format_header(item_name, ident, vis); result.push_str(&header_str); - let body_lo = span_after(span, "{", context.codemap); + let body_lo = context.codemap.span_after(span, "{"); let generics_str = match generics { Some(g) => { @@ -680,7 +679,7 @@ fn format_struct_struct(context: &RewriteContext, }, |field| field.node.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), - span_after(span, "{", context.codemap), + context.codemap.span_after(span, "{"), span.hi); // 1 = , let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1; @@ -762,7 +761,7 @@ fn format_tuple_struct(context: &RewriteContext, }, |field| field.node.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), - span_after(span, "(", context.codemap), + context.codemap.span_after(span, "("), span.hi); let body = try_opt!(format_item_list(items, item_budget, item_indent, context.config)); result.push_str(&body); @@ -798,7 +797,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&ident.to_string()); let generics_indent = indent + result.len(); - let generics_span = mk_sp(span_after(span, "type", context.codemap), ty.span.lo); + let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); let generics_width = context.config.max_width - " =".len(); let generics_str = try_opt!(rewrite_generics(context, generics, @@ -1152,7 +1151,7 @@ fn rewrite_fn_base(context: &RewriteContext, let args_start = generics.ty_params .last() .map_or(span.lo, |tp| end_typaram(tp)); - let args_span = mk_sp(span_after(mk_sp(args_start, span.hi), "(", context.codemap), + let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("), span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, &fd.inputs, @@ -1304,7 +1303,7 @@ fn rewrite_args(context: &RewriteContext, if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { let reduced_span = mk_sp(span.lo, args[1].ty.span.lo); - span_after_last(reduced_span, ",", context.codemap) + context.codemap.span_after_last(reduced_span, ",") } else { span.lo }; @@ -1316,7 +1315,7 @@ fn rewrite_args(context: &RewriteContext, let variadic_arg = if variadic { let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); - let variadic_start = span_after(variadic_span, "...", context.codemap) - BytePos(3); + let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { None @@ -1476,7 +1475,7 @@ fn rewrite_generics(context: &RewriteContext, |&(sp, _)| sp.hi, // FIXME: don't clone |&(_, ref str)| str.clone(), - span_after(span, "<", context.codemap), + context.codemap.span_after(span, "<"), span.hi); let list_str = try_opt!(format_item_list(items, h_budget, offset, context.config)); diff --git a/src/macros.rs b/src/macros.rs index a8da45c6408..324c68d750a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -28,7 +28,7 @@ use Indent; use rewrite::RewriteContext; use expr::{rewrite_call, rewrite_array}; use comment::FindUncommented; -use utils::{wrap_str, span_after}; +use utils::{CodeMapSpanUtils, wrap_str}; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; @@ -104,9 +104,8 @@ pub fn rewrite_macro(mac: &ast::Mac, // Format macro invocation as array literal. let extra_offset = macro_name.len(); let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(span_after(mac.span, - original_style.opener(), - context.codemap), + mk_sp(context.codemap.span_after(mac.span, + original_style.opener()), mac.span.hi - BytePos(1)), context, try_opt!(width.checked_sub(extra_offset)), diff --git a/src/patterns.rs b/src/patterns.rs index a5f09823212..b176327ab15 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -10,7 +10,7 @@ use Indent; use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, format_mutability, span_after}; +use utils::{CodeMapSpanUtils, wrap_str, format_mutability}; use lists::{format_item_list, itemize_list}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use types::rewrite_path; @@ -84,7 +84,7 @@ impl Rewrite for Pat { |item| item.span.lo, |item| item.span.hi, |item| item.rewrite(context, width, offset), - span_after(self.span, "(", context.codemap), + context.codemap.span_after(self.span, "("), self.span.hi); Some(format!("{}({})", path_str, @@ -141,7 +141,7 @@ impl Rewrite for Pat { |f| f.span.lo, |f| f.span.hi, |f| f.node.rewrite(context, budget, offset), - span_after(self.span, "{", context.codemap), + context.codemap.span_after(self.span, "{"), self.span.hi); let mut field_string = try_opt!(format_item_list(items, budget, diff --git a/src/types.rs b/src/types.rs index 4f930f22cad..917a3839d54 100644 --- a/src/types.rs +++ b/src/types.rs @@ -19,7 +19,7 @@ use syntax::abi; use {Indent, Spanned}; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, span_after, format_mutability, wrap_str}; +use utils::{CodeMapSpanUtils, extra_offset, format_mutability, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::TypeDensity; @@ -183,7 +183,7 @@ fn rewrite_segment(expr_context: bool, .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); - let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap); + let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); let separator = if expr_context { "::" } else { @@ -246,7 +246,7 @@ fn format_function_type<'a, I>(inputs: I, let budget = try_opt!(width.checked_sub(2)); // 1 for ( let offset = offset + 1; - let list_lo = span_after(span, "(", context.codemap); + let list_lo = context.codemap.span_after(span, "("); let items = itemize_list(context.codemap, inputs, ")", diff --git a/src/utils.rs b/src/utils.rs index 3b03ede2be3..5c2bca73432 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,42 +20,50 @@ use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; -// Computes the length of a string's last line, minus offset. -#[inline] -pub fn extra_offset(text: &str, offset: Indent) -> usize { - match text.rfind('\n') { - // 1 for newline character - Some(idx) => text.len() - idx - 1 - offset.width(), - None => text.len(), - } +pub trait CodeMapSpanUtils { + fn span_after(&self, original: Span, needle: &str) -> BytePos; + fn span_after_last(&self, original: Span, needle: &str) -> BytePos; + fn span_before(&self, original: Span, needle: &str) -> BytePos; } -#[inline] -pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { - let snippet = codemap.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); +impl CodeMapSpanUtils for CodeMap { + #[inline] + fn span_after(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); - original.lo + BytePos(offset as u32) -} + original.lo + BytePos(offset as u32) + } -#[inline] -pub fn span_before(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { - let snippet = codemap.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap(); + #[inline] + fn span_after_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; - original.lo + BytePos(offset as u32) -} + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } -#[inline] -pub fn span_after_last(original: Span, needle: &str, codemap: &CodeMap) -> BytePos { - let snippet = codemap.span_to_snippet(original).unwrap(); - let mut offset = 0; + original.lo + BytePos(offset as u32) + } + + #[inline] + fn span_before(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap(); - while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { - offset += additional_offset + needle.len(); + original.lo + BytePos(offset as u32) } +} - original.lo + BytePos(offset as u32) +// Computes the length of a string's last line, minus offset. +#[inline] +pub fn extra_offset(text: &str, offset: Indent) -> usize { + match text.rfind('\n') { + // 1 for newline character + Some(idx) => text.len() - idx - 1 - offset.width(), + None => text.len(), + } } #[inline] diff --git a/src/visitor.rs b/src/visitor.rs index f53ed2246d5..76cdf543946 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,7 +16,7 @@ use syntax::visit; use strings::string_buffer::StringBuffer; use Indent; -use utils; +use utils::{self, CodeMapSpanUtils}; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; @@ -450,7 +450,7 @@ impl<'a> FmtVisitor<'a> { if is_internal { self.buffer.push_str(" {"); // Hackery to account for the closing }. - let mod_lo = ::utils::span_after(s, "{", self.codemap); + let mod_lo = self.codemap.span_after(s, "{"); let body_snippet = self.snippet(codemap::mk_sp(mod_lo, m.inner.hi - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { -- cgit 1.4.1-3-g733a5 From db9d1290254c5703d67fcf4f277b23641fb92d60 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Sun, 13 Mar 2016 22:57:03 +0200 Subject: Add Vertical fn_args_density This adds new option Vertical to fn_args_density, which formats the list vertically no matter what. --- src/config.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 448ab3b8d51..32eb9af4b11 100644 --- a/src/config.rs +++ b/src/config.rs @@ -71,6 +71,8 @@ configuration_option_enum! { Density: Tall, // Try to compress if the body is empty. CompressedIfEmpty, + // Place every item on a separate line. + Vertical, } configuration_option_enum! { TypeDensity: @@ -85,6 +87,7 @@ impl Density { match self { Density::Compressed => ListTactic::Mixed, Density::Tall | Density::CompressedIfEmpty => ListTactic::HorizontalVertical, + Density::Vertical => ListTactic::Vertical, } } } -- cgit 1.4.1-3-g733a5 From 0c8640a84f0cf4ce01665aa482f4470edcf12410 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Sun, 13 Mar 2016 23:27:13 +0200 Subject: Fix last comment turning into block comment This fixes the comment after the last argument in an argument list being turned into a block comment when it's not necessary. --- src/items.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9e5b964429e..f0a7d94ebe7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1370,13 +1370,18 @@ fn rewrite_args(context: &RewriteContext, _ => multi_line_budget, }; + let end_with_newline = match context.config.fn_args_layout { + StructLitStyle::Block => true, + _ => false, + }; + let fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, indent: indent, width: budget, - ends_with_newline: false, + ends_with_newline: end_with_newline, config: context.config, }; -- cgit 1.4.1-3-g733a5 From 96a2f25788ebda721bdd52de9e6c178ed364a5aa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 Mar 2016 18:55:55 +1300 Subject: Keep empty extern blocks on one line Closes #462 --- src/items.rs | 23 ++++++++++++++--------- tests/source/extern.rs | 4 ++++ tests/target/extern.rs | 2 ++ 3 files changed, 20 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1c5eaa2a631..d70f780df5a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -84,19 +84,24 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&::utils::format_abi(fm.abi)); let snippet = self.snippet(span); - let brace_pos = snippet.find_uncommented("{").unwrap() as u32; + let brace_pos = snippet.find_uncommented("{").unwrap(); - // FIXME: this skips comments between the extern keyword and the opening - // brace. - self.last_pos = span.lo + BytePos(brace_pos); - self.block_indent = self.block_indent.block_indent(self.config); + if fm.items.is_empty() && !contains_comment(&snippet[brace_pos..]) { + self.buffer.push_str("{"); + } else { + // FIXME: this skips comments between the extern keyword and the opening + // brace. + self.last_pos = span.lo + BytePos(brace_pos as u32); + self.block_indent = self.block_indent.block_indent(self.config); - for item in &fm.items { - self.format_foreign_item(&*item); + for item in &fm.items { + self.format_foreign_item(&*item); + } + + self.block_indent = self.block_indent.block_unindent(self.config); + self.format_missing_with_indent(span.hi - BytePos(1)); } - self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(span.hi - BytePos(1)); self.buffer.push_str("}"); self.last_pos = span.hi; } diff --git a/tests/source/extern.rs b/tests/source/extern.rs index e33b646b726..347612dd8f1 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -34,3 +34,7 @@ libc::c_long; file: *mut FILE) -> *mut FILE; } + +extern { + +} diff --git a/tests/target/extern.rs b/tests/target/extern.rs index ca8c43d8b2c..e25e8b01cd4 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -45,3 +45,5 @@ extern "C" { file: *mut FILE) -> *mut FILE; } + +extern "C" {} -- cgit 1.4.1-3-g733a5 From 9d8ce544283fd18cf1bfd6285a9dcce19aabbfea Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 Mar 2016 20:51:06 +1300 Subject: Don't apply the function args heuristic to tuple lits. Closes #450 Closes #510 --- src/chains.rs | 3 +-- src/comment.rs | 4 +-- src/expr.rs | 11 +++----- src/items.rs | 4 +-- tests/source/issue-510.rs | 1 - tests/system.rs | 3 +-- tests/target/closure.rs | 3 +-- tests/target/issue-510.rs | 65 ++++++++++++++++++++++------------------------- tests/target/match.rs | 26 +++---------------- tests/target/tuple.rs | 7 ++--- 10 files changed, 46 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 191b4a2ea4c..c535287df24 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -236,8 +236,7 @@ fn rewrite_method_call(method_name: ast::Ident, .map(|ty| ty.rewrite(context, width, offset)) .collect()); - (types.last().unwrap().span.hi, - format!("::<{}>", type_list.join(", "))) + (types.last().unwrap().span.hi, format!("::<{}>", type_list.join(", "))) }; let callee_str = format!(".{}{}", method_name, type_str); diff --git a/src/comment.rs b/src/comment.rs index 3382ab53276..232e7691b82 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -501,9 +501,7 @@ impl<'a> Iterator for CommentCodeSlices<'a> { CodeCharKind::Comment => CodeCharKind::Normal, CodeCharKind::Normal => CodeCharKind::Comment, }; - let res = (kind, - self.last_slice_end, - &self.slice[self.last_slice_end..sub_slice_end]); + let res = (kind, self.last_slice_end, &self.slice[self.last_slice_end..sub_slice_end]); self.last_slice_end = sub_slice_end; self.last_slice_kind = kind; diff --git a/src/expr.rs b/src/expr.rs index 5fc0f370ab6..d933f68ce18 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -18,7 +18,7 @@ use std::fmt::Write; use {Indent, Spanned}; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic, ListItem, format_fn_args}; + DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; use string::{StringFormat, rewrite_string}; use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt}; @@ -1336,9 +1336,7 @@ fn rewrite_call_inner(context: &RewriteContext, // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. match (overflow_last, tactic, placeholder) { - (true, - DefinitiveListTactic::Horizontal, - placeholder @ Some(..)) => { + (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { item_vec[arg_count - 1].item = placeholder; } (true, _, _) => { @@ -1511,8 +1509,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, outer_indent)) }; - match (context.config.struct_lit_style, - context.config.struct_lit_multiline_style) { + match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { (StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => { format_on_newline() } @@ -1583,7 +1580,7 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, list_lo, span.hi - BytePos(1)); let budget = try_opt!(width.checked_sub(2)); - let list_str = try_opt!(format_fn_args(items, budget, indent, context.config)); + let list_str = try_opt!(format_item_list(items, budget, indent, context.config)); Some(format!("({})", list_str)) } diff --git a/src/items.rs b/src/items.rs index 1c5eaa2a631..4024b144de2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1401,9 +1401,7 @@ fn compute_budgets_for_args(context: &RewriteContext, let multi_line_budget = context.config.max_width - (indent.width() + result.len() + "()".len()); - return (one_line_budget, - multi_line_budget, - indent + result.len() + 1); + return (one_line_budget, multi_line_budget, indent + result.len() + 1); } } diff --git a/tests/source/issue-510.rs b/tests/source/issue-510.rs index faf3d657ada..8f56be02e32 100644 --- a/tests/source/issue-510.rs +++ b/tests/source/issue-510.rs @@ -19,7 +19,6 @@ let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - } }; -// FIXME(#501): tuple width heuristic may not be optimal for patterns. let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match (inline_start, inline_end, computed_inline_size) { (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { diff --git a/tests/system.rs b/tests/system.rs index bc5298ae22d..eac45b83ca0 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -305,8 +305,7 @@ fn get_target(file_name: &str, target: Option<&str>, write_mode: Option { - (Path::new("tests/coverage-source/"), - "tests/coverage-target/") + (Path::new("tests/coverage-source/"), "tests/coverage-target/") } _ => (Path::new("tests/source/"), "tests/target/"), }; diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 6ab217ed6c4..382919ce403 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -9,8 +9,7 @@ fn main() { b: WithType, // argument // ignored _| { - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) }; let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs index 5b427ef1402..5b5860998fa 100644 --- a/tests/target/issue-510.rs +++ b/tests/target/issue-510.rs @@ -4,40 +4,37 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { input: &ISizeConstraintInput) -> ISizeConstraintSolution { - let (inline_start, - inline_size, - margin_inline_start, - margin_inline_end) = match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - (Au(0), inline_size, margin_start, margin_end) - } - }; + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; - // FIXME(#501): tuple width heuristic may not be optimal for patterns. - let (inline_start, - inline_size, - margin_inline_start, - margin_inline_end) = match (inline_start, inline_end, computed_inline_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - (Au(0), inline_size, margin_start, margin_end) - } - }; + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; } } diff --git a/tests/target/match.rs b/tests/target/match.rs index defcc13ef51..ed571d32123 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -32,16 +32,7 @@ fn foo() { } // Test that earlier patterns can take the guard space - (aaaa, - bbbbb, - ccccccc, - aaaaa, - bbbbbbbb, - cccccc, - aaaa, - bbbbbbbb, - cccccc, - dddddd) | + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} _ => {} @@ -75,22 +66,13 @@ fn main() { fn main() { match r { Variableeeeeeeeeeeeeeeeee => { - ("variable", - vec!["id", "name", "qualname", "value", "type", "scopeid"], - true, - true) + ("variable", vec!["id", "name", "qualname", "value", "type", "scopeid"], true, true) } Enummmmmmmmmmmmmmmmmmmmm => { - ("enum", - vec!["id", "qualname", "scopeid", "value"], - true, - true) + ("enum", vec!["id", "qualname", "scopeid", "value"], true, true) } Variantttttttttttttttttttttttt => { - ("variant", - vec!["id", "name", "qualname", "type", "value", "scopeid"], - true, - true) + ("variant", vec!["id", "name", "qualname", "type", "value", "scopeid"], true, true) } }; diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index f2c929dde6d..a5bcc7f701a 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -2,9 +2,7 @@ fn foo() { let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaa); + let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa, @@ -26,7 +24,6 @@ fn a() { } fn b() { - ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), bbbbbbbbbbbbbbbbbb) } -- cgit 1.4.1-3-g733a5 From 7ba43ff06edfd4c3d578d9c4ff2a11885275cae1 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 19:52:07 -0600 Subject: Finished implementing impl and trait type/const --- src/items.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/visitor.rs | 68 +++++++++++++++++++++++++++-------------------------- 2 files changed, 107 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 550a6613241..ccf99c5dae7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,7 +23,7 @@ use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; use syntax::codemap; -use syntax::{ast, abi}; +use syntax::{ast, abi, ptr}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; use syntax::ast::ImplItem; @@ -640,7 +640,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { result.push('\n'); - let width = context.block_indent.width() + context.config.tab_spaces - 1; + let width = context.block_indent.width() + context.config.tab_spaces; let trait_indent = Indent::new(0, width); result.push_str(&trait_indent.to_string(context.config)); } @@ -1021,6 +1021,75 @@ pub fn rewrite_static(prefix: &str, rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") } +pub fn rewrite_associated_type(prefix: &str, + ident: ast::Ident, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent) + -> Option { + let prefix = format!("{} {}", prefix, ident); + + let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { + let bounds: &[_] = &ty_param_bounds.as_slice(); + let bound_str = bounds.iter() + .filter_map(|ty_bound| { + ty_bound.rewrite(context, + context.config.max_width, + indent) + }) + .collect::>() + .join(" + "); + if bounds.len() > 0 { + format!(": {}", bound_str) + } else { + String::new() + } + } else { + String::new() + }; + + if let Some(ty) = ty_opt { + let ty_str = try_opt!(ty.rewrite(context, + context.config.max_width - context.block_indent.width() - + prefix.len() - 2, + context.block_indent)); + Some(format!("{} = {};", prefix, ty_str)) + } else { + Some(format!("{}{};", prefix, type_bounds_str)) + } +} + +pub fn rewrite_associated_static(prefix: &str, + vis: ast::Visibility, + ident: ast::Ident, + ty: &ast::Ty, + mutability: ast::Mutability, + expr_opt: &Option>, + context: &RewriteContext) + -> Option { + let prefix = format!("{}{} {}{}: ", + format_visibility(vis), + prefix, + format_mutability(mutability), + ident); + // 2 = " =".len() + let ty_str = try_opt!(ty.rewrite(context, + context.config.max_width - context.block_indent.width() - + prefix.len() - 2, + context.block_indent)); + + if let &Some(ref expr) = expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.config.max_width - context.block_indent.width() - 1; + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + } else { + let lhs = format!("{}{};", prefix, ty_str); + Some(lhs) + } +} + impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { @@ -1671,6 +1740,7 @@ fn rewrite_where_clause(context: &RewriteContext, config: context.config, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); + println!("{:?}", preds_str); let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two diff --git a/src/visitor.rs b/src/visitor.rs index 02bc29e3269..2339a47dd21 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -207,7 +207,6 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.hi; } } - // FIXME(#78): format traits. ast::ItemKind::Trait(..) => { self.format_missing_with_indent(item.span.lo); if let Some(trait_str) = format_trait(&self.get_context(), @@ -216,11 +215,6 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&trait_str); self.last_pos = item.span.hi; } - // self.block_indent = self.block_indent.block_indent(self.config); - // for item in trait_items { - // self.visit_trait_item(&item); - // } - // self.block_indent = self.block_indent.block_unindent(self.config); } ast::ItemKind::ExternCrate(_) => { self.format_missing_with_indent(item.span.lo); @@ -320,8 +314,15 @@ impl<'a> FmtVisitor<'a> { } match ti.node { - ast::TraitItemKind::Const(..) => { - // FIXME: Implement + ast::TraitItemKind::Const(ref ty, ref expr) => { + let rewrite = rewrite_associated_static("const", + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr, + &self.get_context()); + self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { let indent = self.block_indent; @@ -336,25 +337,13 @@ impl<'a> FmtVisitor<'a> { ti.id); } ast::TraitItemKind::Type(ref type_param_bounds, _) => { - let indent = self.block_indent; - let mut result = String::new(); - result.push_str(&format!("type {}", ti.ident)); - - let bounds: &[_] = &type_param_bounds.as_slice(); - let bound_str = bounds.iter() - .filter_map(|ty_bound| { - ty_bound.rewrite(&self.get_context(), - self.config.max_width, - indent) - }) - .collect::>() - .join(" + "); - if bounds.len() > 0 { - result.push_str(&format!(": {}", bound_str)); - } - - result.push(';'); - self.push_rewrite(ti.span, Some(result)); + let rewrite = rewrite_associated_type("type", + ti.ident, + None, + Some(type_param_bounds), + &self.get_context(), + self.block_indent); + self.push_rewrite(ti.span, rewrite); } } } @@ -372,11 +361,24 @@ impl<'a> FmtVisitor<'a> { ii.span, ii.id); } - ast::ImplItemKind::Const(..) => { - // FIXME: Implement - } - ast::ImplItemKind::Type(_) => { - // FIXME: Implement + ast::ImplItemKind::Const(ref ty, ref expr) => { + let rewrite = rewrite_static("const", + ast::Visibility::Inherited, + ii.ident, + ty, + ast::Mutability::Immutable, + &expr, + &self.get_context()); + self.push_rewrite(ii.span, rewrite); + } + ast::ImplItemKind::Type(ref ty) => { + let rewrite = rewrite_associated_type("type", + ii.ident, + Some(ty), + None, + &self.get_context(), + self.block_indent); + self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { self.format_missing_with_indent(ii.span.lo); -- cgit 1.4.1-3-g733a5 From 2793b4090c2acef5380bfb6f972f79a3d338f968 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 20:05:20 -0600 Subject: Added tests --- src/items.rs | 11 +++++------ src/visitor.rs | 15 ++++++++------- tests/source/impls.rs | 16 ++++++++++------ tests/source/trait.rs | 6 ++++++ tests/source/where-trailing-comma.rs | 3 +-- tests/target/impls.rs | 4 ++++ tests/target/trait.rs | 9 +++++++++ tests/target/where-trailing-comma.rs | 5 +++-- 8 files changed, 46 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ccf99c5dae7..5f8345593ee 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1034,9 +1034,7 @@ pub fn rewrite_associated_type(prefix: &str, let bounds: &[_] = &ty_param_bounds.as_slice(); let bound_str = bounds.iter() .filter_map(|ty_bound| { - ty_bound.rewrite(context, - context.config.max_width, - indent) + ty_bound.rewrite(context, context.config.max_width, indent) }) .collect::>() .join(" + "); @@ -1052,7 +1050,8 @@ pub fn rewrite_associated_type(prefix: &str, if let Some(ty) = ty_opt { let ty_str = try_opt!(ty.rewrite(context, context.config.max_width - context.block_indent.width() - - prefix.len() - 2, + prefix.len() - + 2, context.block_indent)); Some(format!("{} = {};", prefix, ty_str)) } else { @@ -1083,7 +1082,8 @@ pub fn rewrite_associated_static(prefix: &str, let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) + .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); Some(lhs) @@ -1740,7 +1740,6 @@ fn rewrite_where_clause(context: &RewriteContext, config: context.config, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); - println!("{:?}", preds_str); let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two diff --git a/src/visitor.rs b/src/visitor.rs index 2339a47dd21..5db7b396032 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,8 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, + rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -316,12 +317,12 @@ impl<'a> FmtVisitor<'a> { match ti.node { ast::TraitItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_associated_static("const", - ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr, - &self.get_context()); + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr, + &self.get_context()); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { diff --git a/tests/source/impls.rs b/tests/source/impls.rs index d04b5ce1eeb..9f34db7ae07 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -1,6 +1,10 @@ impl Foo for Bar { fn foo() { "hi" } } pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; // Comment 1 fn foo() { "hi" } // Comment 2 @@ -9,20 +13,20 @@ pub impl Foo for Bar { } pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } -impl Foo for Bar where T: Baz +impl Foo for Bar where T: Baz { } @@ -38,8 +42,8 @@ impl Boo { fn boo() {} // FOO - - + + } mod a { diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 49b314358f2..3fb6a1b85e2 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -37,3 +37,9 @@ trait Test { } trait T<> {} + +trait Foo { type Bar: Baz;} + +trait ConstCheck:Foo where T: Baz { + const J: i32; +} diff --git a/tests/source/where-trailing-comma.rs b/tests/source/where-trailing-comma.rs index 8f951d199e4..c2c1a3185bc 100644 --- a/tests/source/where-trailing-comma.rs +++ b/tests/source/where-trailing-comma.rs @@ -20,7 +20,7 @@ struct Pair where T: P, S: P + Q { struct TupPair (S, T) where T: P, S: P + Q; -enum E where S: P, T: P { +enum E where S: P, T: P { A {a: T}, } @@ -30,7 +30,6 @@ extern "C" { fn f(x: T, y: S) -> T where T: P, S: Q; } -// Note: trait declarations are not fully formatted (issue #78) trait Q where T: P, S: R { fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 33bc7481905..c81de4d40fe 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -5,6 +5,10 @@ impl Foo for Bar { } pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; // Comment 1 fn foo() { "hi" diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 32389431284..f784fa14530 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -36,3 +36,12 @@ trait Test { } trait T {} + +trait Foo { + type Bar: Baz; +} + +trait ConstCheck: Foo where T: Baz +{ + const J: i32; +} diff --git a/tests/target/where-trailing-comma.rs b/tests/target/where-trailing-comma.rs index bd7108f992a..c8682237ae6 100644 --- a/tests/target/where-trailing-comma.rs +++ b/tests/target/where-trailing-comma.rs @@ -48,8 +48,9 @@ extern "C" { S: Q; } -// Note: trait declarations are not fully formatted (issue #78) -trait Q where T: P, S: R +trait Q + where T: P, + S: R, { fn f(self, x: T, y: S, z: U) -> Self where U: P, -- cgit 1.4.1-3-g733a5 From a0a53356341b9bd71e994713c266746b64105a74 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 20:51:41 -0600 Subject: Fixed span_after issue --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c2447aa8c16..0fb5520f6bd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -622,7 +622,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); // let indent = offset + result.len(); - let body_lo = span_after(item.span, "{", context.codemap); + let body_lo = context.codemap.span_after(item.span, "{"); let generics_str = try_opt!(rewrite_generics(context, generics, -- cgit 1.4.1-3-g733a5 From 0a665aacebd5b2b4fa579c49fbb16dbb67e9347e Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Tue, 15 Mar 2016 14:08:12 -0600 Subject: Fixed nitpicks Removed unneeded comment Commented line wrapping conditions Removed prefix param on `rewrite_associated_type` Merged `rewrite_associated_static` into `rewrite_static` Added extra tests --- src/items.rs | 95 ++++++++++++++++++++++++--------------------------- src/visitor.rs | 31 ++++++++--------- tests/source/trait.rs | 10 ++++++ tests/target/trait.rs | 23 ++++++++++++- 4 files changed, 91 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0fb5520f6bd..8435de62147 100644 --- a/src/items.rs +++ b/src/items.rs @@ -618,10 +618,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&header); - // TODO: Add max_width checking - // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); - // let indent = offset + result.len(); - let body_lo = context.codemap.span_after(item.span, "{"); let generics_str = try_opt!(rewrite_generics(context, @@ -636,8 +632,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) type_param_bounds, offset, context.config.max_width)); - - if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { + // If the trait, generics, and trait bound cannot fit on the same line, + // put the trait bounds on an indented new line + if offset.width() + last_line_width(&result) + trait_bound_str.len() > + context.config.ideal_width { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces; let trait_indent = Indent::new(0, width); @@ -645,19 +643,39 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&trait_bound_str); - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let has_body = !trait_items.is_empty(); + + let where_density = if (context.config.where_density == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout == StructLitStyle::Block)) || + (context.config.fn_args_layout == StructLitStyle::Block && + result.is_empty()) || + (context.config.where_density == Density::CompressedIfEmpty && + !has_body && + !result.contains('\n')) { + Density::Compressed + } else { + Density::Tall + }; + + let where_budget = try_opt!(context.config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, context.config.item_brace_style, context.block_indent, where_budget, - context.config.where_density, + where_density, "{", - context.config.where_trailing_comma, + has_body, None)); + // If the where clause cannot fit on the same line, + // put the where clause on a new line if !where_clause_str.contains('\n') && - result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + last_line_width(&result) + where_clause_str.len() + offset.width() > + context.config.ideal_width { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); @@ -672,7 +690,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { + if !where_clause_str.is_empty() && + (trait_items.len() > 0 || result.contains('\n')) { result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -704,6 +723,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); result.push('\n'); result.push_str(&outer_indent_str); + } else if result.contains('\n') { + result.push('\n'); } result.push('}'); @@ -1000,7 +1021,7 @@ pub fn rewrite_static(prefix: &str, ident: ast::Ident, ty: &ast::Ty, mutability: ast::Mutability, - expr: &ast::Expr, + expr_opt: Option<&ptr::P>, context: &RewriteContext) -> Option { let prefix = format!("{}{} {}{}: ", @@ -1013,21 +1034,26 @@ pub fn rewrite_static(prefix: &str, context.config.max_width - context.block_indent.width() - prefix.len() - 2, context.block_indent)); - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + if let Some(ref expr) = expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.config.max_width - context.block_indent.width() - 1; + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) + .map(|s| s + ";") + } else { + let lhs = format!("{}{};", prefix, ty_str); + Some(lhs) + } } -pub fn rewrite_associated_type(prefix: &str, - ident: ast::Ident, +pub fn rewrite_associated_type(ident: ast::Ident, ty_opt: Option<&ptr::P>, ty_param_bounds_opt: Option<&ast::TyParamBounds>, context: &RewriteContext, indent: Indent) -> Option { - let prefix = format!("{} {}", prefix, ident); + let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = &ty_param_bounds.as_slice(); @@ -1058,37 +1084,6 @@ pub fn rewrite_associated_type(prefix: &str, } } -pub fn rewrite_associated_static(prefix: &str, - vis: ast::Visibility, - ident: ast::Ident, - ty: &ast::Ty, - mutability: ast::Mutability, - expr_opt: &Option>, - context: &RewriteContext) - -> Option { - let prefix = format!("{}{} {}{}: ", - format_visibility(vis), - prefix, - format_mutability(mutability), - ident); - // 2 = " =".len() - let ty_str = try_opt!(ty.rewrite(context, - context.config.max_width - context.block_indent.width() - - prefix.len() - 2, - context.block_indent)); - - if let &Some(ref expr) = expr_opt { - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) - .map(|s| s + ";") - } else { - let lhs = format!("{}{};", prefix, ty_str); - Some(lhs) - } -} - impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { diff --git a/src/visitor.rs b/src/visitor.rs index f5774da7d64..62fbfd7613f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,8 +21,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, - rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -267,7 +266,7 @@ impl<'a> FmtVisitor<'a> { item.ident, ty, mutability, - expr, + Some(expr), &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -277,7 +276,7 @@ impl<'a> FmtVisitor<'a> { item.ident, ty, ast::Mutability::Immutable, - expr, + Some(expr), &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -315,14 +314,14 @@ impl<'a> FmtVisitor<'a> { } match ti.node { - ast::TraitItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_associated_static("const", - ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr, - &self.get_context()); + ast::TraitItemKind::Const(ref ty, ref expr_opt) => { + let rewrite = rewrite_static("const", + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr_opt.as_ref(), + &self.get_context()); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { @@ -338,8 +337,7 @@ impl<'a> FmtVisitor<'a> { ti.id); } ast::TraitItemKind::Type(ref type_param_bounds, _) => { - let rewrite = rewrite_associated_type("type", - ti.ident, + let rewrite = rewrite_associated_type(ti.ident, None, Some(type_param_bounds), &self.get_context(), @@ -368,13 +366,12 @@ impl<'a> FmtVisitor<'a> { ii.ident, ty, ast::Mutability::Immutable, - &expr, + Some(expr), &self.get_context()); self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_type("type", - ii.ident, + let rewrite = rewrite_associated_type(ii.ident, Some(ty), None, &self.get_context(), diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 3fb6a1b85e2..faac57179c2 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -43,3 +43,13 @@ trait Foo { type Bar: Baz;} trait ConstCheck:Foo where T: Baz { const J: i32; } + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } + +trait WhereList where T: Foo, J: Bar {} + diff --git a/tests/target/trait.rs b/tests/target/trait.rs index f784fa14530..d8acc1ba229 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -41,7 +41,28 @@ trait Foo { type Bar: Baz; } -trait ConstCheck: Foo where T: Baz +trait ConstCheck: Foo + where T: Baz { const J: i32; } + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo +{ +} + +trait FooBar + : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where J: Bar +{ + fn test(); +} + +trait WhereList + where T: Foo, + J: Bar +{ +} -- cgit 1.4.1-3-g733a5 From 03bf1ceeb9e015fb8a3aca88e49b33b73158f0d4 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Mar 2016 13:07:28 +0200 Subject: Fix tuple destructuring in impl fns --- Cargo.lock | 12 ++++++------ src/items.rs | 24 +++++++++++++++++++++--- tests/source/impls.rs | 6 ++++++ tests/target/impls.rs | 4 ++++ 4 files changed, 37 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 689ed8db10b..ce3e5701ad2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,7 @@ dependencies = [ "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -39,7 +39,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -52,7 +52,7 @@ name = "kernel32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -79,7 +79,7 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.56" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -125,7 +125,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -153,7 +153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/src/items.rs b/src/items.rs index 688e4759832..97f12df8187 100644 --- a/src/items.rs +++ b/src/items.rs @@ -20,9 +20,8 @@ use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; -use syntax::codemap; -use syntax::{ast, abi, ptr}; +use syntax::{ast, abi, ptr, codemap}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; use syntax::ast::ImplItem; @@ -1477,7 +1476,13 @@ fn rewrite_args(context: &RewriteContext, // it is explicit. if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { - let reduced_span = mk_sp(span.lo, args[1].ty.span.lo); + let second_arg_start = if arg_has_pattern(&args[1]) { + args[1].pat.span.lo + } else { + args[1].ty.span.lo + }; + let reduced_span = mk_sp(span.lo, second_arg_start); + context.codemap.span_after_last(reduced_span, ",") } else { span.lo @@ -1562,6 +1567,19 @@ fn rewrite_args(context: &RewriteContext, write_list(&arg_items, &fmt) } +fn arg_has_pattern(arg: &ast::Arg) -> bool { + if let ast::PatKind::Ident(_, + codemap::Spanned { + node: ast::Ident { name: ast::Name(0u32), .. }, + .. + }, + _) = arg.pat.node { + false + } else { + true + } +} + fn compute_budgets_for_args(context: &RewriteContext, result: &str, indent: Indent, diff --git a/tests/source/impls.rs b/tests/source/impls.rs index a3a8033b07f..e96baa91473 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -73,6 +73,12 @@ impl X { fn do_parse( mut self : X ) {} } impl Y5000 { fn bar(self: X< 'a , 'b >, y: Y) {} + + fn bad(&self, ( x, y): CoorT) {} + + fn turbo_bad(self: X< 'a , 'b > , ( x, y): CoorT) { + + } } pub impl Foo for Bar where T: Foo diff --git a/tests/target/impls.rs b/tests/target/impls.rs index c81de4d40fe..c592ab6f9f9 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -93,6 +93,10 @@ impl X { impl Y5000 { fn bar(self: X<'a, 'b>, y: Y) {} + + fn bad(&self, (x, y): CoorT) {} + + fn turbo_bad(self: X<'a, 'b>, (x, y): CoorT) {} } pub impl Foo for Bar -- cgit 1.4.1-3-g733a5 From 0e0cf976c9293627ea318eec6211e62326375abe Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Mar 2016 13:44:08 +0200 Subject: Fix issues with empty macros with curly braces --- src/macros.rs | 12 ++++++------ tests/source/macros.rs | 19 +++++++++++++++++++ tests/target/macros.rs | 16 ++++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 324c68d750a..620dd9d98f6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -27,7 +27,7 @@ use syntax::codemap::{mk_sp, BytePos}; use Indent; use rewrite::RewriteContext; use expr::{rewrite_call, rewrite_array}; -use comment::FindUncommented; +use comment::{FindUncommented, contains_comment}; use utils::{CodeMapSpanUtils, wrap_str}; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; @@ -63,11 +63,11 @@ pub fn rewrite_macro(mac: &ast::Mac, original_style }; - if mac.node.tts.is_empty() { - return if let MacroStyle::Parens = style { - Some(format!("{}()", macro_name)) - } else { - Some(format!("{}[]", macro_name)) + if mac.node.tts.is_empty() && !contains_comment(&context.snippet(mac.span)) { + return match style { + MacroStyle::Parens => Some(format!("{}()", macro_name)), + MacroStyle::Brackets => Some(format!("{}[]", macro_name)), + MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), }; } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 261f02e756f..cafc4522ef7 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -33,4 +33,23 @@ fn main() { macrowithbraces! {dont, format, me} x!(fn); + + some_macro!( + + ); + + some_macro![ + ]; + + some_macro!{ + // comment + }; + + some_macro!{ + // comment + }; +} + +impl X { + empty_invoc!{} } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 4d99ede9f50..a463947d985 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -39,4 +39,20 @@ fn main() { macrowithbraces! {dont, format, me} x!(fn); + + some_macro!(); + + some_macro![]; + + some_macro!{ + // comment + }; + + some_macro!{ + // comment + }; +} + +impl X { + empty_invoc!{} } -- cgit 1.4.1-3-g733a5 From 0142191e51386ede07e70f61e0b47631a86ff2a4 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Mar 2016 20:20:51 +0200 Subject: Remove trailing whitespace for fn types /w non-unit return --- src/types.rs | 2 +- tests/source/type_alias.rs | 2 ++ tests/target/type_alias.rs | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 7ac4bd1c674..5a8e456bedb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -268,7 +268,7 @@ fn format_function_type<'a, I>(inputs: I, FunctionRetTy::Default(..) => String::new(), }; - let infix = if output.len() + list_str.len() > width { + let infix = if output.len() > 0 && output.len() + list_str.len() > width { format!("\n{}", (offset - 1).to_string(context.config)) } else { String::new() diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs index e4429bb8ddf..93e155534ec 100644 --- a/tests/source/type_alias.rs +++ b/tests/source/type_alias.rs @@ -25,3 +25,5 @@ pub type WithWhereClause where T: Clone, LONGPARAMETERNAME pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index d175aa60a67..16c77b273c1 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -49,3 +49,7 @@ pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + E pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +type RegisterPlugin = unsafe fn(pt: *const c_char, + plugin: *mut c_void, + data: *mut CallbackData); -- cgit 1.4.1-3-g733a5 From ac7778cc51774a96d89f1a9244d41558d7698429 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 25 Mar 2016 16:11:33 +0300 Subject: cargo-fmt: don't return zero on failure --- src/bin/cargo-fmt.rs | 53 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 9c5e4bf9567..d267dc5e35d 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -12,19 +12,30 @@ #![cfg(not(test))] #![cfg(feature="cargo-fmt")] +#![deny(warnings)] extern crate getopts; extern crate rustc_serialize; -use std::path::PathBuf; -use std::process::Command; use std::env; +use std::io::Write; +use std::path::PathBuf; +use std::process::{Command, ExitStatus}; use std::str; use getopts::Options; use rustc_serialize::json::Json; fn main() { + let exit_status = execute(); + std::io::stdout().flush().unwrap(); + std::process::exit(exit_status); +} + +fn execute() -> i32 { + let success = 0; + let failure = 1; + let mut opts = getopts::Options::new(); opts.optflag("h", "help", "show this message"); opts.optflag("q", "quiet", "no output printed to stdout"); @@ -34,7 +45,7 @@ fn main() { Ok(m) => m, Err(e) => { print_usage(&opts, &e.to_string()); - return; + return failure; } }; @@ -42,13 +53,26 @@ fn main() { if verbose && quiet { print_usage(&opts, "quiet mode and verbose mode are not compatible"); - return; + return failure; } if matches.opt_present("h") { print_usage(&opts, ""); - } else { - format_crate(&opts, verbose, quiet); + return success; + } + + match format_crate(verbose, quiet) { + Err(e) => { + print_usage(&opts, &e.to_string()); + failure + } + Ok(status) => { + if status.success() { + success + } else { + status.code().unwrap_or(failure) + } + } } } @@ -59,14 +83,8 @@ fn print_usage(opts: &Options, reason: &str) { opts.usage(&msg)); } -fn format_crate(opts: &Options, verbose: bool, quiet: bool) { - let targets = match get_targets() { - Ok(t) => t, - Err(e) => { - print_usage(opts, &e.to_string()); - return; - } - }; +fn format_crate(verbose: bool, quiet: bool) -> Result { + let targets = try!(get_targets()); // Currently only bin and lib files get formatted let files: Vec<_> = targets.into_iter() @@ -80,7 +98,6 @@ fn format_crate(opts: &Options, verbose: bool, quiet: bool) { .collect(); format_files(&files, &get_fmt_args(), verbose, quiet) - .unwrap_or_else(|e| print_usage(opts, &e.to_string())); } fn get_fmt_args() -> Vec { @@ -158,7 +175,7 @@ fn format_files(files: &Vec, fmt_args: &Vec, verbose: bool, quiet: bool) - -> Result<(), std::io::Error> { + -> Result { let stdout = if quiet { std::process::Stdio::null() } else { @@ -179,7 +196,5 @@ fn format_files(files: &Vec, .args(files) .args(fmt_args) .spawn()); - try!(command.wait()); - - Ok(()) + command.wait() } -- cgit 1.4.1-3-g733a5 From c7e51d3994f3fc885bfb94b32232084ad6f94834 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 29 Mar 2016 02:37:43 +0300 Subject: minor: use enum instead of pair of booleans This is a bit more typing, but statically forbids using both verbose and quiet --- src/bin/cargo-fmt.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index d267dc5e35d..c033851f98a 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -49,19 +49,22 @@ fn execute() -> i32 { } }; - let (verbose, quiet) = (matches.opt_present("v"), matches.opt_present("q")); - - if verbose && quiet { - print_usage(&opts, "quiet mode and verbose mode are not compatible"); - return failure; - } + let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { + (false, false) => Verbosity::Normal, + (false, true) => Verbosity::Quiet, + (true, false) => Verbosity::Verbose, + (true, true) => { + print_usage(&opts, "quiet mode and verbose mode are not compatible"); + return failure; + } + }; if matches.opt_present("h") { print_usage(&opts, ""); return success; } - match format_crate(verbose, quiet) { + match format_crate(verbosity) { Err(e) => { print_usage(&opts, &e.to_string()); failure @@ -83,21 +86,28 @@ fn print_usage(opts: &Options, reason: &str) { opts.usage(&msg)); } -fn format_crate(verbose: bool, quiet: bool) -> Result { +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Verbosity { + Verbose, + Normal, + Quiet, +} + +fn format_crate(verbosity: Verbosity) -> Result { let targets = try!(get_targets()); // Currently only bin and lib files get formatted let files: Vec<_> = targets.into_iter() .filter(|t| t.kind.is_lib() | t.kind.is_bin()) .inspect(|t| { - if verbose { + if verbosity == Verbosity::Verbose { println!("[{:?}] {:?}", t.kind, t.path) } }) .map(|t| t.path) .collect(); - format_files(&files, &get_fmt_args(), verbose, quiet) + format_files(&files, &get_fmt_args(), verbosity) } fn get_fmt_args() -> Vec { @@ -173,15 +183,14 @@ fn target_from_json(jtarget: &Json) -> Target { fn format_files(files: &Vec, fmt_args: &Vec, - verbose: bool, - quiet: bool) + verbosity: Verbosity) -> Result { - let stdout = if quiet { + let stdout = if verbosity == Verbosity::Quiet { std::process::Stdio::null() } else { std::process::Stdio::inherit() }; - if verbose { + if verbosity == Verbosity::Verbose { print!("rustfmt"); for a in fmt_args.iter() { print!(" {}", a); -- cgit 1.4.1-3-g733a5 From 8168c7c44c855e69755fe5c09c86fc88e8c747ea Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 28 Mar 2016 23:30:08 -0400 Subject: Use checked_next_power_of_two from std instead of custom method NB The custom method returned 0 on an input of 0, which is arguably incorrect: 0 is not a power of two; the method in `std` returns 1 in that case. --- src/string.rs | 5 +++-- src/utils.rs | 35 ----------------------------------- 2 files changed, 3 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 5961254cd9a..d7e1fe763ef 100644 --- a/src/string.rs +++ b/src/string.rs @@ -15,7 +15,6 @@ use regex::Regex; use Indent; use config::Config; -use utils::round_up_to_power_of_two; use MIN_STRING; @@ -41,7 +40,9 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let punctuation = ":,;."; let mut cur_start = 0; - let mut result = String::with_capacity(round_up_to_power_of_two(stripped_str.len())); + let mut result = String::with_capacity(stripped_str.len() + .checked_next_power_of_two() + .unwrap_or(usize::max_value())); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); diff --git a/src/utils.rs b/src/utils.rs index 6b2b1e58f57..902969b9618 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -180,33 +180,6 @@ pub fn trim_newlines(input: &str) -> &str { } } -#[inline] -#[cfg(target_pointer_width="64")] -// Based on the trick layed out at -// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 -pub fn round_up_to_power_of_two(mut x: usize) -> usize { - x = x.wrapping_sub(1); - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x |= x >> 32; - x.wrapping_add(1) -} - -#[inline] -#[cfg(target_pointer_width="32")] -pub fn round_up_to_power_of_two(mut x: usize) -> usize { - x = x.wrapping_sub(1); - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x.wrapping_add(1) -} - // Macro for deriving implementations of Decodable for enums #[macro_export] macro_rules! impl_enum_decodable { @@ -344,11 +317,3 @@ fn bin_search_test() { assert_eq!(Some(()), binary_search(4, 125, &closure)); assert_eq!(None, binary_search(6, 100, &closure)); } - -#[test] -fn power_rounding() { - assert_eq!(0, round_up_to_power_of_two(0)); - assert_eq!(1, round_up_to_power_of_two(1)); - assert_eq!(64, round_up_to_power_of_two(33)); - assert_eq!(256, round_up_to_power_of_two(256)); -} -- cgit 1.4.1-3-g733a5 From f2b5931c6da8a6e2fa0a5c82f3ece74a1c95e093 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Tue, 29 Mar 2016 00:04:44 -0400 Subject: deps: Update syntex_syntax to 0.30.0 This bump includes ability to parse inclusive ranges (`a...b`) and the question mark operator. Refs #867, #890 --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/expr.rs | 13 +++++++++---- src/lib.rs | 5 +++-- 4 files changed, 17 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ce3e5701ad2..853b2f4481b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -25,7 +25,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -108,10 +108,10 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.29.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 49bd30a73ca..591e60ef239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ regex = "0.1.41" term = "0.2.11" strings = "0.0.1" diff = "0.1.8" -syntex_syntax = "0.29.1" +syntex_syntax = "0.30" log = "0.3.2" env_logger = "0.3.1" getopts = "0.2" diff --git a/src/expr.rs b/src/expr.rs index d933f68ce18..a1e8a17c091 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -185,19 +185,21 @@ impl Rewrite for ast::Expr { ast::ExprKind::Repeat(ref expr, ref repeats) => { rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) } - ast::ExprKind::Range(Some(ref lhs), Some(ref rhs)) => { + // TODO(#890): Handle closed ranges; rust tracking issue + // https://github.com/rust-lang/rust/issues/28237 + ast::ExprKind::Range(Some(ref lhs), Some(ref rhs), _range_limits) => { rewrite_pair(&**lhs, &**rhs, "", "..", "", context, width, offset) } - ast::ExprKind::Range(None, Some(ref rhs)) => { + ast::ExprKind::Range(None, Some(ref rhs), _range_limits) => { rewrite_unary_prefix(context, "..", &**rhs, width, offset) } - ast::ExprKind::Range(Some(ref lhs), None) => { + ast::ExprKind::Range(Some(ref lhs), None, _range_limits) => { Some(format!("{}..", try_opt!(lhs.rewrite(context, try_opt!(width.checked_sub(2)), offset)))) } - ast::ExprKind::Range(None, None) => { + ast::ExprKind::Range(None, None, _range_limits) => { if width >= 2 { Some("..".into()) } else { @@ -213,6 +215,9 @@ impl Rewrite for ast::Expr { width, offset) } + // TODO(#867): Handle type ascription; rust tracking issue + // https://github.com/rust-lang/rust/issues/31436 + ast::ExprKind::Try(_) => unimplemented!(), }; result.and_then(|res| recover_comment_removed(res, self.span, context, width, offset)) } diff --git a/src/lib.rs b/src/lib.rs index 7e074f05124..3443db338cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -381,7 +381,8 @@ pub fn format_string(input: String, config: &Config) -> FileMap { let krate = parse::parse_crate_from_source_str(path.to_owned(), input, Vec::new(), - &parse_session); + &parse_session) + .unwrap(); // Suppress error output after parsing. let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); @@ -412,7 +413,7 @@ pub fn format(file: &Path, config: &Config) -> FileMap { codemap.clone()); let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); + let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session).unwrap(); // Suppress error output after parsing. let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); -- cgit 1.4.1-3-g733a5 From 9e5c0390a04910027097c98217fb47d05a1b2ca9 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 27 Mar 2016 14:45:55 +0200 Subject: Properly format macro's with an extra ident --- src/expr.rs | 2 +- src/macros.rs | 6 +++++- src/visitor.rs | 13 ++++++------- tests/source/macros.rs | 2 ++ tests/target/macros.rs | 2 ++ 5 files changed, 16 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d933f68ce18..96079a29b26 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -154,7 +154,7 @@ impl Rewrite for ast::Expr { ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, context, width, offset).or_else(|| { + rewrite_macro(mac, None, context, width, offset).or_else(|| { wrap_str(context.snippet(self.span), context.config.max_width, width, diff --git a/src/macros.rs b/src/macros.rs index 324c68d750a..7e321366abf 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -51,12 +51,16 @@ impl MacroStyle { } pub fn rewrite_macro(mac: &ast::Mac, + extra_ident: Option, context: &RewriteContext, width: usize, offset: Indent) -> Option { let original_style = macro_style(mac, context); - let macro_name = format!("{}!", mac.node.path); + let macro_name = match extra_ident { + None | Some(ast::Ident { name: ast::Name(0), .. }) => format!("{}!", mac.node.path), + Some(ident) => format!("{}! {}", mac.node.path, ident), + }; let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { MacroStyle::Brackets } else { diff --git a/src/visitor.rs b/src/visitor.rs index 62fbfd7613f..6ef07e922c0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast; +use syntax::{ast, visit}; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::parse::ParseSess; -use syntax::visit; use strings::string_buffer::StringBuffer; @@ -56,7 +55,7 @@ impl<'a> FmtVisitor<'a> { } ast::StmtKind::Mac(ref mac, _macro_style, _) => { self.format_missing_with_indent(stmt.span.lo); - self.visit_mac(mac); + self.visit_mac(mac, None); } } } @@ -254,7 +253,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Mac(ref mac) => { self.format_missing_with_indent(item.span.lo); - self.visit_mac(mac); + self.visit_mac(mac, Some(item.ident)); } ast::ItemKind::ForeignMod(ref foreign_mod) => { self.format_missing_with_indent(item.span.lo); @@ -380,15 +379,15 @@ impl<'a> FmtVisitor<'a> { } ast::ImplItemKind::Macro(ref mac) => { self.format_missing_with_indent(ii.span.lo); - self.visit_mac(mac); + self.visit_mac(mac, Some(ii.ident)); } } } - fn visit_mac(&mut self, mac: &ast::Mac) { + fn visit_mac(&mut self, mac: &ast::Mac, ident: Option) { // 1 = ; let width = self.config.max_width - self.block_indent.width() - 1; - let rewrite = rewrite_macro(mac, &self.get_context(), width, self.block_indent); + let rewrite = rewrite_macro(mac, ident, &self.get_context(), width, self.block_indent); if let Some(res) = rewrite { self.buffer.push_str(&res); diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 261f02e756f..4d9e0d9ff73 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -4,6 +4,8 @@ itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa itemmacro!{this, is.bracket().formatted()} +peg_file! modname ("mygrammarfile.rustpeg"); + fn main() { foo! ( ); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 4d99ede9f50..ecc885ec337 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -7,6 +7,8 @@ itemmacro!(really, itemmacro!{this, is.bracket().formatted()} +peg_file! modname("mygrammarfile.rustpeg"); + fn main() { foo!(); -- cgit 1.4.1-3-g733a5 From 9eee93306a001ef7eb2ee74183e534e62e77d8e4 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 29 Mar 2016 23:46:55 +0200 Subject: Format closed ranges --- Cargo.lock | 16 +++++++++++----- src/expr.rs | 40 +++++++++++++++++++++------------------- tests/source/expr.rs | 12 ++++++++++++ tests/target/expr.rs | 13 +++++++++++++ 4 files changed, 57 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 853b2f4481b..813c5359c79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,7 @@ dependencies = [ "env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.60 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -39,7 +39,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -77,20 +77,26 @@ dependencies = [ "libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mempool" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "regex" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mempool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/src/expr.rs b/src/expr.rs index a1e8a17c091..968eac96806 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -185,25 +185,27 @@ impl Rewrite for ast::Expr { ast::ExprKind::Repeat(ref expr, ref repeats) => { rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) } - // TODO(#890): Handle closed ranges; rust tracking issue - // https://github.com/rust-lang/rust/issues/28237 - ast::ExprKind::Range(Some(ref lhs), Some(ref rhs), _range_limits) => { - rewrite_pair(&**lhs, &**rhs, "", "..", "", context, width, offset) - } - ast::ExprKind::Range(None, Some(ref rhs), _range_limits) => { - rewrite_unary_prefix(context, "..", &**rhs, width, offset) - } - ast::ExprKind::Range(Some(ref lhs), None, _range_limits) => { - Some(format!("{}..", - try_opt!(lhs.rewrite(context, - try_opt!(width.checked_sub(2)), - offset)))) - } - ast::ExprKind::Range(None, None, _range_limits) => { - if width >= 2 { - Some("..".into()) - } else { - None + ast::ExprKind::Range(ref lhs, ref rhs, limits) => { + let delim = match limits { + ast::RangeLimits::HalfOpen => "..", + ast::RangeLimits::Closed => "...", + }; + + match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { + (Some(ref lhs), Some(ref rhs)) => { + rewrite_pair(&**lhs, &**rhs, "", delim, "", context, width, offset) + } + (None, Some(ref rhs)) => { + rewrite_unary_prefix(context, delim, &**rhs, width, offset) + } + (Some(ref lhs), None) => { + Some(format!("{}{}", + try_opt!(lhs.rewrite(context, + try_opt!(width.checked_sub(delim.len())), + offset)), + delim)) + } + (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), } } // We do not format these expressions yet, but they should still diff --git a/tests/source/expr.rs b/tests/source/expr.rs index c5002f5ec15..16953a932a3 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -244,3 +244,15 @@ fn issue767() { } else if let false = false { } } + +fn ranges() { + let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let z = ... x ; + let infi_range_2 = ... ; + + a ... b + + // the expr below won't compile for some reason... + // let a = 0 ... ; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 9c9c65a690c..e9a051711f5 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -267,3 +267,16 @@ fn issue767() { } else if let false = false { } } + +fn ranges() { + let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let z = ...x; + let infi_range_2 = ...; + + a...b + + // the expr below won't compile for some reason... + // let a = 0 ... ; +} -- cgit 1.4.1-3-g733a5 From f94164611880d85f26accf8b422ee2e7609d81dd Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Wed, 30 Mar 2016 00:01:54 +0200 Subject: Do not panic on type ascription or try shorthand Instead, simply format expressions involving these unstable features as they were found. --- src/expr.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 968eac96806..5c4a236705f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -176,9 +176,6 @@ impl Rewrite for ast::Expr { ast::ExprKind::Cast(ref expr, ref ty) => { rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) } - // TODO(#848): Handle type ascription; rust tracking issue - // https://github.com/rust-lang/rust/issues/23416 - ast::ExprKind::Type(_, _) => unimplemented!(), ast::ExprKind::Index(ref expr, ref index) => { rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) } @@ -211,15 +208,16 @@ impl Rewrite for ast::Expr { // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | - ast::ExprKind::InlineAsm(..) => { + ast::ExprKind::InlineAsm(..) | + // TODO(#848): Handle type ascription + ast::ExprKind::Type(_, _) | + // TODO(#867): Handle try shorthand + ast::ExprKind::Try(_) => { wrap_str(context.snippet(self.span), context.config.max_width, width, offset) } - // TODO(#867): Handle type ascription; rust tracking issue - // https://github.com/rust-lang/rust/issues/31436 - ast::ExprKind::Try(_) => unimplemented!(), }; result.and_then(|res| recover_comment_removed(res, self.span, context, width, offset)) } -- cgit 1.4.1-3-g733a5 From 8219d15291e0474f196f03e9f2245ed0dc50e6f2 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 1 Apr 2016 22:59:35 +0100 Subject: Fix incorrect indent with fn_args_layout: Block The closing parenthesis for the arg list was written on a new line without first applying the appropriate indent. --- src/items.rs | 1 + tests/source/fn-custom-6.rs | 6 +++++ tests/source/fn-custom-7.rs | 6 +++++ tests/source/fn_args_layout-block.rs | 24 +++++++++++++++++++ tests/target/fn-custom-6.rs | 12 ++++++++++ tests/target/fn-custom-7.rs | 14 +++++++++++ tests/target/fn_args_layout-block.rs | 46 ++++++++++++++++++++++++++++++++++++ 7 files changed, 109 insertions(+) create mode 100644 tests/source/fn_args_layout-block.rs create mode 100644 tests/target/fn_args_layout-block.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 97f12df8187..2e0cac0df07 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1339,6 +1339,7 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(&arg_str); if context.config.fn_args_layout == StructLitStyle::Block { result.push('\n'); + result.push_str(&indent.to_string(context.config)); } result.push(')'); diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index 1042fa5bd88..7941d3a215e 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -34,3 +34,9 @@ fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { bar(); } + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index 6a56c440d33..98f457207e3 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -17,3 +17,9 @@ fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { fn foo(/* Comment 1 */ a: u8, /* Comment 2 */ b: u8) -> u8 { bar() } + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/source/fn_args_layout-block.rs b/tests/source/fn_args_layout-block.rs new file mode 100644 index 00000000000..07cc983d5a8 --- /dev/null +++ b/tests/source/fn_args_layout-block.rs @@ -0,0 +1,24 @@ +// rustfmt-fn_args_layout: Block + + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index bea50c6a3ce..8c1f89173d7 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -68,3 +68,15 @@ fn bar( where T: UUUUUUUUUUU { bar(); } + +trait Test { + fn foo( + a: u8 + ) { + } + + fn bar( + a: u8 + ) -> String { + } +} diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 1c4cbde24b8..c58678d45d9 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -30,3 +30,17 @@ fn foo( { bar() } + +trait Test { + fn foo( + a: u8 + ) + { + } + + fn bar( + a: u8 + ) -> String + { + } +} diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs new file mode 100644 index 00000000000..7e1318a7a3c --- /dev/null +++ b/tests/target/fn_args_layout-block.rs @@ -0,0 +1,46 @@ +// rustfmt-fn_args_layout: Block + + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String { + bar(); +} + +trait Test { + fn foo( + a: u8 + ) { + } + + fn bar( + a: u8 + ) -> String { + } +} -- cgit 1.4.1-3-g733a5 From 57847e451af3d0057f36f61c357f5c451b4ac7ed Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Sat, 2 Apr 2016 00:25:35 +0100 Subject: Add fn_arg_one_line option If set, arguments will be kept on one line if they fit. Currently only applies when `fn_args_layout` is set to `Block`. This commit also fixes a bug where newlines were inserted inbetween argument brackets when there were no arguments and `fn_args_layout` was set to `Block`. --- src/config.rs | 1 + src/items.rs | 27 +++++++++--- tests/source/fn_arg_one_line.rs | 48 ++++++++++++++++++++ tests/source/fn_args_layout-block.rs | 3 ++ tests/target/fn_arg_one_line.rs | 85 ++++++++++++++++++++++++++++++++++++ tests/target/fn_args_layout-block.rs | 3 ++ 6 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 tests/source/fn_arg_one_line.rs create mode 100644 tests/target/fn_arg_one_line.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 32eb9af4b11..02ee5741c45 100644 --- a/src/config.rs +++ b/src/config.rs @@ -310,6 +310,7 @@ create_config! { fn_args_density: Density, Density::Tall, "Argument density in functions"; fn_args_layout: StructLitStyle, StructLitStyle::Visual, "Layout of function arguments"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; + fn_arg_one_line: bool, false, "Keep arguments on one line if they fit"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; // Should we at least try to put the where clause on the same line as the rest of the diff --git a/src/items.rs b/src/items.rs index 2e0cac0df07..da6d77fca45 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1293,6 +1293,10 @@ fn rewrite_fn_base(context: &RewriteContext, let (mut one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace); + if context.config.fn_args_layout == StructLitStyle::Block { + arg_indent = indent.block_indent(context.config); + } + debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", one_line_budget, multi_line_budget, @@ -1309,10 +1313,6 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str("(\n"); result.push_str(&arg_indent.to_string(context.config)); } - } else if context.config.fn_args_layout == StructLitStyle::Block { - arg_indent = indent.block_indent(context.config); - result.push_str("(\n"); - result.push_str(&arg_indent.to_string(context.config)); } else { result.push('('); } @@ -1336,12 +1336,25 @@ fn rewrite_fn_base(context: &RewriteContext, arg_indent, args_span, fd.variadic)); - result.push_str(&arg_str); - if context.config.fn_args_layout == StructLitStyle::Block { + + let multi_line_arg_str = arg_str.contains('\n'); + + let should_put_args_in_block = context.config.fn_args_layout == StructLitStyle::Block && + (multi_line_arg_str || !context.config.fn_arg_one_line) && + fd.inputs.len() > 0; + + if should_put_args_in_block { + arg_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + result.push_str(&arg_str); result.push('\n'); result.push_str(&indent.to_string(context.config)); + result.push(')'); + } else { + result.push_str(&arg_str); + result.push(')'); } - result.push(')'); // Return type. if !ret_str.is_empty() { diff --git a/tests/source/fn_arg_one_line.rs b/tests/source/fn_arg_one_line.rs new file mode 100644 index 00000000000..23aea2b58f7 --- /dev/null +++ b/tests/source/fn_arg_one_line.rs @@ -0,0 +1,48 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-fn_arg_one_line: true + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { + bar() +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T where X: Foooo, Y: Baaar { + foo(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} +} diff --git a/tests/source/fn_args_layout-block.rs b/tests/source/fn_args_layout-block.rs index 07cc983d5a8..a5b8e66931f 100644 --- a/tests/source/fn_args_layout-block.rs +++ b/tests/source/fn_args_layout-block.rs @@ -1,5 +1,8 @@ // rustfmt-fn_args_layout: Block +fn foo() { + foo(); +} fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { foo(); diff --git a/tests/target/fn_arg_one_line.rs b/tests/target/fn_arg_one_line.rs new file mode 100644 index 00000000000..ef5eeea90bd --- /dev/null +++ b/tests/target/fn_arg_one_line.rs @@ -0,0 +1,85 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-fn_arg_one_line: true + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String { + bar(); +} + +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo( + a: u8, // Comment 1 + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee // Comment 2 +) -> u8 { + bar() +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String + where X: Fooooo, + Y: Baaar +{ + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T + where X: Foooo, + Y: Baaar +{ + foo(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee + ) -> String { + } +} diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index 7e1318a7a3c..f18cf2197d8 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -1,5 +1,8 @@ // rustfmt-fn_args_layout: Block +fn foo() { + foo(); +} fn foo( a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb -- cgit 1.4.1-3-g733a5 From 294b463b5d9755fe2138b1d7a8593aa263567bdf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 2 Apr 2016 19:36:56 +0300 Subject: minor: use &mut ref instead of by value argument This also unifies `write_all_files` and `write_file` functions --- src/filemap.rs | 8 ++++---- src/lib.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index f41915b8cff..64c892a0929 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -31,14 +31,14 @@ pub fn append_newlines(file_map: &mut FileMap) { } } -pub fn write_all_files(file_map: &FileMap, mut out: T, config: &Config) -> Result<(), io::Error> +pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error> where T: Write { - output_header(&mut out, config.write_mode).ok(); + output_header(out, config.write_mode).ok(); for filename in file_map.keys() { - try!(write_file(&file_map[filename], filename, &mut out, config)); + try!(write_file(&file_map[filename], filename, out, config)); } - output_footer(&mut out, config.write_mode).ok(); + output_footer(out, config.write_mode).ok(); Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 3443db338cf..a559c23006b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -432,8 +432,8 @@ pub fn run(file: &Path, config: &Config) { let mut result = format(file, config); print!("{}", fmt_lines(&mut result, config)); - let out = stdout(); - let write_result = filemap::write_all_files(&result, out, config); + let mut out = stdout(); + let write_result = filemap::write_all_files(&result, &mut out, config); if let Err(msg) = write_result { println!("Error writing files: {}", msg); -- cgit 1.4.1-3-g733a5 From 84fb2f402e92976c34c4a60cab5b918d377388fb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 2 Apr 2016 21:56:37 +0300 Subject: refactor: unify run and run_from_stdin --- src/bin/rustfmt.rs | 6 +++--- src/filemap.rs | 10 +++++----- src/lib.rs | 40 ++++++++++++++++++++++++---------------- 3 files changed, 32 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 062c60e1065..e3ead2a28a1 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,7 +17,7 @@ extern crate toml; extern crate env_logger; extern crate getopts; -use rustfmt::{run, run_from_stdin}; +use rustfmt::{run, Input}; use rustfmt::config::{Config, WriteMode}; use std::env; @@ -197,7 +197,7 @@ fn execute() -> i32 { // write_mode is always Plain for Stdin. config.write_mode = WriteMode::Plain; - run_from_stdin(input, &config); + run(Input::Text(input), &config); 0 } Operation::Format { files, config_path } => { @@ -233,7 +233,7 @@ fn execute() -> i32 { print_usage(&opts, &e); return 1; } - run(&file, &config); + run(Input::File(file), &config); } 0 } diff --git a/src/filemap.rs b/src/filemap.rs index 64c892a0929..c6af9a70184 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -80,11 +80,11 @@ pub fn write_system_newlines(writer: T, } } -pub fn write_file(text: &StringBuffer, - filename: &str, - out: &mut T, - config: &Config) - -> Result, io::Error> +fn write_file(text: &StringBuffer, + filename: &str, + out: &mut T, + config: &Config) + -> Result, io::Error> where T: Write { diff --git a/src/lib.rs b/src/lib.rs index a559c23006b..42c5c7a5895 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ use syntax::parse::{self, ParseSess}; use std::io::stdout; use std::ops::{Add, Sub}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::collections::HashMap; use std::fmt; @@ -41,7 +41,7 @@ use std::fmt; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; use visitor::FmtVisitor; -use config::Config; +use config::{Config, WriteMode}; #[macro_use] mod utils; @@ -428,27 +428,35 @@ pub fn format(file: &Path, config: &Config) -> FileMap { file_map } -pub fn run(file: &Path, config: &Config) { - let mut result = format(file, config); +fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { + let mut file_map = match input { + Input::File(ref file) => format(file, config), + Input::Text(text) => format_string(text, config), + }; - print!("{}", fmt_lines(&mut result, config)); - let mut out = stdout(); - let write_result = filemap::write_all_files(&result, &mut out, config); + let report = fmt_lines(&mut file_map, config); + (file_map, report) +} - if let Err(msg) = write_result { - println!("Error writing files: {}", msg); - } +pub enum Input { + File(PathBuf), + Text(String), } -// Similar to run, but takes an input String instead of a file to format -pub fn run_from_stdin(input: String, config: &Config) { - let mut result = format_string(input, config); - fmt_lines(&mut result, config); +pub fn run(input: Input, config: &Config) { + let (file_map, report) = format_input(input, config); + + let ignore_errors = config.write_mode == WriteMode::Plain; + if !ignore_errors { + print!("{}", report); + } let mut out = stdout(); - let write_result = filemap::write_file(&result["stdin"], "stdin", &mut out, config); + let write_result = filemap::write_all_files(&file_map, &mut out, config); if let Err(msg) = write_result { - panic!("Error writing to stdout: {}", msg); + if !ignore_errors { + println!("Error writing files: {}", msg); + } } } -- cgit 1.4.1-3-g733a5 From bee9682a494d9e59cf8fdb48c5b642d70f8b949f Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Sun, 3 Apr 2016 01:08:25 +0530 Subject: Correct spelling of 'style' --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 32eb9af4b11..0b4b16c328e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -45,7 +45,7 @@ configuration_option_enum! { ReturnIndent: WithWhereClause, } -// How to stle a struct literal. +// How to style a struct literal. configuration_option_enum! { StructLitStyle: // First line on the same line as the opening brace, all lines aligned with // the first line. -- cgit 1.4.1-3-g733a5 From ac4532e16117eff1ecd24597d2dd916196e4efd9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 3 Apr 2016 00:32:24 +0300 Subject: use format_input function in tests --- src/lib.rs | 4 ++-- tests/system.rs | 13 ++++++------- tests/writemode/checkstyle.xml | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 42c5c7a5895..396ec030f7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -403,7 +403,7 @@ pub fn format_string(input: String, config: &Config) -> FileMap { file_map } -pub fn format(file: &Path, config: &Config) -> FileMap { +fn format(file: &Path, config: &Config) -> FileMap { let codemap = Rc::new(CodeMap::new()); let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, @@ -428,7 +428,7 @@ pub fn format(file: &Path, config: &Config) -> FileMap { file_map } -fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { +pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { let mut file_map = match input { Input::File(ref file) => format(file, config), Input::Text(text) => format_string(text, config), diff --git a/tests/system.rs b/tests/system.rs index 7081d73f778..96a9d9b7f92 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -16,7 +16,7 @@ extern crate term; use std::collections::HashMap; use std::fs; use std::io::{self, Read, BufRead, BufReader}; -use std::path::Path; +use std::path::{Path, PathBuf}; use rustfmt::*; use rustfmt::filemap::{write_system_newlines, FileMap}; @@ -75,7 +75,7 @@ fn checkstyle_test() { // to a known output file generated by one of the write modes. fn assert_output(source: &str, expected_filename: &str, write_mode: Option) { let config = read_config(&source, write_mode); - let file_map = run_rustfmt(source.to_string(), &config); + let (file_map, _report) = format_file(source, &config); // Populate output by writing to a vec. let mut out = vec![]; @@ -196,9 +196,9 @@ fn read_config(filename: &str, write_mode: Option) -> Config { config } -// Simulate run() -fn run_rustfmt(filename: String, config: &Config) -> FileMap { - format(Path::new(&filename), &config) +fn format_file>(filename: P, config: &Config) -> (FileMap, FormatReport) { + let input = Input::File(filename.into()); + format_input(input, &config) } pub fn idempotent_check(filename: String, @@ -206,8 +206,7 @@ pub fn idempotent_check(filename: String, -> Result>> { let sig_comments = read_significant_comments(&filename); let config = read_config(&filename, write_mode); - let mut file_map = run_rustfmt(filename, &config); - let format_report = fmt_lines(&mut file_map, &config); + let (file_map, format_report) = format_file(filename, &config); let mut write_result = HashMap::new(); for (filename, text) in file_map.iter() { diff --git a/tests/writemode/checkstyle.xml b/tests/writemode/checkstyle.xml index f655cfb3b6b..12c7dd9fdf1 100644 --- a/tests/writemode/checkstyle.xml +++ b/tests/writemode/checkstyle.xml @@ -1,2 +1,2 @@ - + -- cgit 1.4.1-3-g733a5 From 63887ed4132dc362e4d5a271672f352c74154613 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 3 Apr 2016 00:45:04 +0300 Subject: make format_string and fmt_lines private --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 396ec030f7c..5121a034fa4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -287,7 +287,7 @@ fn fmt_ast(krate: &ast::Crate, // Formatting done on a char by char or line by line basis. // TODO(#209) warn on bad license // TODO(#20) other stuff for parity with make tidy -pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { +fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; @@ -367,7 +367,7 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -pub fn format_string(input: String, config: &Config) -> FileMap { +fn format_string(input: String, config: &Config) -> FileMap { let path = "stdin"; let codemap = Rc::new(CodeMap::new()); -- cgit 1.4.1-3-g733a5 From 6e393b3d53aba6f3d18b76fd820c148f9e4b62e7 Mon Sep 17 00:00:00 2001 From: 0x0G <0x0G@users.noreply.github.com> Date: Mon, 4 Apr 2016 13:49:16 +0300 Subject: Fix. rustfmt write to stderr instead stdout Fix. rustfmt write to stderr instead stdout --- src/bin/rustfmt.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 062c60e1065..666185f837e 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -212,7 +212,7 @@ fn execute() -> i32 { path = path_tmp; }; if let Some(path) = path.as_ref() { - msg!("Using rustfmt config file {}", path.display()); + println!("Using rustfmt config file {}", path.display()); } for file in files { // Check the file directory if the config-path could not be read or not provided @@ -222,9 +222,9 @@ fn execute() -> i32 { for {}", file.display())); if let Some(path) = path_tmp.as_ref() { - msg!("Using rustfmt config file {} for {}", - path.display(), - file.display()); + println!("Using rustfmt config file {} for {}", + path.display(), + file.display()); } config = config_tmp; } -- cgit 1.4.1-3-g733a5 From c29ee66b94fea672f459374942a4e311dc9cef5e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 5 Apr 2016 01:20:14 +0300 Subject: make naming more consistent --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 5121a034fa4..8c69710e359 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -287,7 +287,7 @@ fn fmt_ast(krate: &ast::Crate, // Formatting done on a char by char or line by line basis. // TODO(#209) warn on bad license // TODO(#20) other stuff for parity with make tidy -fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { +fn format_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); let mut report = FormatReport { file_error_map: HashMap::new() }; @@ -403,7 +403,7 @@ fn format_string(input: String, config: &Config) -> FileMap { file_map } -fn format(file: &Path, config: &Config) -> FileMap { +fn format_file(file: &Path, config: &Config) -> FileMap { let codemap = Rc::new(CodeMap::new()); let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, @@ -430,11 +430,11 @@ fn format(file: &Path, config: &Config) -> FileMap { pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { let mut file_map = match input { - Input::File(ref file) => format(file, config), + Input::File(ref file) => format_file(file, config), Input::Text(text) => format_string(text, config), }; - let report = fmt_lines(&mut file_map, config); + let report = format_lines(&mut file_map, config); (file_map, report) } -- cgit 1.4.1-3-g733a5 From 901c5b1a5d45be3b9fe449716f779e31520e5882 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 6 Apr 2016 10:04:29 +0530 Subject: use std::error instead std::out --- src/bin/rustfmt.rs | 10 +--------- src/config.rs | 5 +++-- src/lib.rs | 4 ++-- src/utils.rs | 10 ++++++++++ 4 files changed, 16 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index bce8ac7bc0f..b65cbaa7f59 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -10,7 +10,7 @@ #![cfg(not(test))] -#[macro_use] + extern crate log; extern crate rustfmt; extern crate toml; @@ -28,14 +28,6 @@ use std::str::FromStr; use getopts::{Matches, Options}; -macro_rules! msg { - ($($arg:tt)*) => ( - match writeln!(&mut ::std::io::stderr(), $($arg)* ) { - Ok(_) => {}, - Err(x) => panic!("Unable to write to stderr: {}", x), - } - ) -} /// Rustfmt operations. enum Operation { diff --git a/src/config.rs b/src/config.rs index 0b4b16c328e..46c28322c92 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,6 +11,7 @@ extern crate toml; use lists::{SeparatorTactic, ListTactic}; +use std::io::Write; macro_rules! configuration_option_enum{ ($e:ident: $( $x:ident ),+ $(,)*) => { @@ -222,9 +223,9 @@ macro_rules! create_config { let parsed_config:ParsedConfig = match toml::decode(parsed) { Some(decoded) => decoded, None => { - println!("Decoding config file failed. Config:\n{}", toml); + msg!("Decoding config file failed. Config:\n{}", toml); let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); - println!("\n\nParsed:\n{:?}", parsed); + msg!("\n\nParsed:\n{:?}", parsed); panic!(); } }; diff --git a/src/lib.rs b/src/lib.rs index 8c69710e359..b7af96ac5aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ use syntax::errors::Handler; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; -use std::io::stdout; +use std::io::{stdout, Write}; use std::ops::{Add, Sub}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -456,7 +456,7 @@ pub fn run(input: Input, config: &Config) { if let Err(msg) = write_result { if !ignore_errors { - println!("Error writing files: {}", msg); + msg!("Error writing files: {}", msg); } } } diff --git a/src/utils.rs b/src/utils.rs index 902969b9618..66b9880777f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -232,6 +232,16 @@ macro_rules! try_opt { }) } +macro_rules! msg { + ($($arg:tt)*) => ( + match writeln!(&mut ::std::io::stderr(), $($arg)* ) { + Ok(_) => {}, + Err(x) => panic!("Unable to write to stderr: {}", x), + } + ) +} + + // Wraps string-like values in an Option. Returns Some when the string adheres // to the Rewrite constraints defined for the Rewrite trait and else otherwise. pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: Indent) -> Option { -- cgit 1.4.1-3-g733a5 From 4edc6f1a4e069dcb46d1fc583dccefba7e4aae44 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 7 Apr 2016 20:01:16 +0100 Subject: Add variant to fn_args_layout --- src/config.rs | 14 ++++- src/items.rs | 50 +++++++++-------- tests/source/fn_arg_one_line.rs | 48 ---------------- tests/source/fn_args_layout-block.rs | 48 +++++++++++++++- tests/source/fn_args_layout-blockalways.rs | 27 +++++++++ tests/target/fn_arg_one_line.rs | 85 ---------------------------- tests/target/fn_args_layout-block.rs | 89 ++++++++++++++++++++++++++---- tests/target/fn_args_layout-blockalways.rs | 49 ++++++++++++++++ 8 files changed, 241 insertions(+), 169 deletions(-) delete mode 100644 tests/source/fn_arg_one_line.rs create mode 100644 tests/source/fn_args_layout-blockalways.rs delete mode 100644 tests/target/fn_arg_one_line.rs create mode 100644 tests/target/fn_args_layout-blockalways.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 3c426b88033..84a23b6425d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -56,6 +56,17 @@ configuration_option_enum! { StructLitStyle: // FIXME Maybe we should also have an option to align types. } +// How to style fn args. +configuration_option_enum! { FnArgLayoutStyle: + // First line on the same line as the opening brace, all lines aligned with + // the first line. + Visual, + // Put args on one line if they fit, or start a new line with block indent. + Block, + // First line is on a new line and all lines align with block indent. + BlockAlways, +} + configuration_option_enum! { BlockIndentStyle: // Same level as parent. Inherit, @@ -309,9 +320,8 @@ create_config! { "Location of return type in function declaration"; fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, "Argument density in functions"; - fn_args_layout: StructLitStyle, StructLitStyle::Visual, "Layout of function arguments"; + fn_args_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, "Layout of function arguments"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; - fn_arg_one_line: bool, false, "Keep arguments on one line if they fit"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; // Should we at least try to put the where clause on the same line as the rest of the diff --git a/src/items.rs b/src/items.rs index da6d77fca45..f3ba3872a91 100644 --- a/src/items.rs +++ b/src/items.rs @@ -19,7 +19,7 @@ use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; +use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle}; use syntax::{ast, abi, ptr, codemap}; use syntax::codemap::{Span, BytePos, mk_sp}; @@ -651,8 +651,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let where_density = if (context.config.where_density == Density::Compressed && (!result.contains('\n') || - context.config.fn_args_layout == StructLitStyle::Block)) || - (context.config.fn_args_layout == StructLitStyle::Block && + context.config.fn_args_layout == FnArgLayoutStyle::Block)) || + (context.config.fn_args_layout == FnArgLayoutStyle::Block && result.is_empty()) || (context.config.where_density == Density::CompressedIfEmpty && !has_body && @@ -1293,7 +1293,8 @@ fn rewrite_fn_base(context: &RewriteContext, let (mut one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace); - if context.config.fn_args_layout == StructLitStyle::Block { + if context.config.fn_args_layout == FnArgLayoutStyle::Block || + context.config.fn_args_layout == FnArgLayoutStyle::BlockAlways { arg_indent = indent.block_indent(context.config); } @@ -1339,11 +1340,13 @@ fn rewrite_fn_base(context: &RewriteContext, let multi_line_arg_str = arg_str.contains('\n'); - let should_put_args_in_block = context.config.fn_args_layout == StructLitStyle::Block && - (multi_line_arg_str || !context.config.fn_arg_one_line) && - fd.inputs.len() > 0; + let put_args_in_block = match context.config.fn_args_layout { + FnArgLayoutStyle::Block => multi_line_arg_str, + FnArgLayoutStyle::BlockAlways => true, + _ => false, + } && fd.inputs.len() > 0; - if should_put_args_in_block { + if put_args_in_block { arg_indent = indent.block_indent(context.config); result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); @@ -1358,14 +1361,17 @@ fn rewrite_fn_base(context: &RewriteContext, // Return type. if !ret_str.is_empty() { + let ret_should_indent = match context.config.fn_args_layout { + FnArgLayoutStyle::Block if put_args_in_block => false, + FnArgLayoutStyle::BlockAlways => false, + _ => { + result.contains("\n") || multi_line_ret_str || + result.len() + indent.width() + ret_str_len > context.config.max_width + } + }; // If we've already gone multi-line, or the return type would push // over the max width, then put the return type on a new line. - // Unless we are formatting args like a block, in which case there - // should always be room for the return type. - let ret_indent = if (result.contains("\n") || multi_line_ret_str || - result.len() + indent.width() + ret_str_len > - context.config.max_width) && - context.config.fn_args_layout != StructLitStyle::Block { + let ret_indent = if ret_should_indent { let indent = match context.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, // Aligning with non-existent args looks silly. @@ -1416,13 +1422,13 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let where_density = if (context.config.where_density == Density::Compressed && - (!result.contains('\n') || - context.config.fn_args_layout == StructLitStyle::Block)) || - (context.config.fn_args_layout == StructLitStyle::Block && - ret_str.is_empty()) || - (context.config.where_density == Density::CompressedIfEmpty && - !has_body && !result.contains('\n')) { + let where_compressed = match context.config.where_density { + Density::Compressed => !result.contains('\n') || put_args_in_block, + Density::CompressedIfEmpty => !has_body && !result.contains('\n'), + _ => false, + } || (put_args_in_block && ret_str.is_empty()); + + let where_density = if where_compressed { Density::Compressed } else { Density::Tall @@ -1564,7 +1570,7 @@ fn rewrite_args(context: &RewriteContext, }; let end_with_newline = match context.config.fn_args_layout { - StructLitStyle::Block => true, + FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => true, _ => false, }; diff --git a/tests/source/fn_arg_one_line.rs b/tests/source/fn_arg_one_line.rs deleted file mode 100644 index 23aea2b58f7..00000000000 --- a/tests/source/fn_arg_one_line.rs +++ /dev/null @@ -1,48 +0,0 @@ -// rustfmt-fn_args_layout: Block -// rustfmt-fn_arg_one_line: true - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { - bar() -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { - bar(); -} - -fn foo() -> T { - foo(); -} - -fn foo() -> T where X: Foooo, Y: Baaar { - foo(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} -} diff --git a/tests/source/fn_args_layout-block.rs b/tests/source/fn_args_layout-block.rs index a5b8e66931f..983ccc60d2b 100644 --- a/tests/source/fn_args_layout-block.rs +++ b/tests/source/fn_args_layout-block.rs @@ -20,8 +20,54 @@ fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Ddddddddd bar(); } +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { + bar() +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T where X: Foooo, Y: Baaar { + foo(); +} + +fn foo() where X: Foooo { +} + +fn foo() where X: Foooo, Y: Baaar { +} + +fn foo() -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) { + foo(); +} + +fn foo() { + foo(); +} + +fn foo() { + foo(); +} + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { + foo(); +} + trait Test { fn foo(a: u8) {} - fn bar(a: u8) -> String {} + fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} } diff --git a/tests/source/fn_args_layout-blockalways.rs b/tests/source/fn_args_layout-blockalways.rs new file mode 100644 index 00000000000..d4bb00b9142 --- /dev/null +++ b/tests/source/fn_args_layout-blockalways.rs @@ -0,0 +1,27 @@ +// rustfmt-fn_args_layout: BlockAlways + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/target/fn_arg_one_line.rs b/tests/target/fn_arg_one_line.rs deleted file mode 100644 index ef5eeea90bd..00000000000 --- a/tests/target/fn_arg_one_line.rs +++ /dev/null @@ -1,85 +0,0 @@ -// rustfmt-fn_args_layout: Block -// rustfmt-fn_arg_one_line: true - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee -) -> String { - bar(); -} - -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -fn foo( - a: u8, // Comment 1 - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee // Comment 2 -) -> u8 { - bar() -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee -) -> String - where X: Fooooo, - Y: Baaar -{ - bar(); -} - -fn foo() -> T { - foo(); -} - -fn foo() -> T - where X: Foooo, - Y: Baaar -{ - foo(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee - ) -> String { - } -} diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index f18cf2197d8..b2d30018abd 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -4,9 +4,7 @@ fn foo() { foo(); } -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb -) { +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { foo(); } @@ -20,9 +18,7 @@ fn bar( bar(); } -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb -) -> String { +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { foo(); } @@ -36,14 +32,85 @@ fn bar( bar(); } +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo( + a: u8, // Comment 1 + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee // Comment 2 +) -> u8 { + bar() +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String + where X: Fooooo, + Y: Baaar +{ + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T + where X: Foooo, + Y: Baaar +{ + foo(); +} + +fn foo() where X: Foooo {} + +fn foo() + where X: Foooo, + Y: Baaar +{ +} + +fn foo + () + -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) +{ + foo(); +} + +fn foo() { + foo(); +} + +fn foo + () { + foo(); +} + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { + foo(); +} + trait Test { - fn foo( - a: u8 - ) { - } + fn foo(a: u8) {} fn bar( - a: u8 + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee ) -> String { } } diff --git a/tests/target/fn_args_layout-blockalways.rs b/tests/target/fn_args_layout-blockalways.rs new file mode 100644 index 00000000000..11f04d13ce6 --- /dev/null +++ b/tests/target/fn_args_layout-blockalways.rs @@ -0,0 +1,49 @@ +// rustfmt-fn_args_layout: BlockAlways + +fn foo() { + foo(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String { + bar(); +} + +trait Test { + fn foo( + a: u8 + ) { + } + + fn bar( + a: u8 + ) -> String { + } +} -- cgit 1.4.1-3-g733a5 From 4c9dd747bf3e6f3b3502d75755fc083f466ed3d8 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 7 Apr 2016 20:24:30 +0100 Subject: Fix long generic indent --- src/items.rs | 5 ++- tests/source/fn-custom-6.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom-8.rs | 50 ++++++++++++++++++++++++ tests/source/fn_args_layout-block.rs | 12 ++++-- tests/target/fn-custom-6.rs | 2 +- tests/target/fn-custom-7.rs | 2 +- tests/target/fn-custom-8.rs | 74 ++++++++++++++++++++++++++++++++++++ tests/target/fn_args_layout-block.rs | 22 +++++++++-- 9 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 tests/source/fn-custom-8.rs create mode 100644 tests/target/fn-custom-8.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f3ba3872a91..04bb2ec4a4c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1290,12 +1290,13 @@ fn rewrite_fn_base(context: &RewriteContext, }; // Args. - let (mut one_line_budget, multi_line_budget, mut arg_indent) = + let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace); if context.config.fn_args_layout == FnArgLayoutStyle::Block || context.config.fn_args_layout == FnArgLayoutStyle::BlockAlways { arg_indent = indent.block_indent(context.config); + multi_line_budget = context.config.max_width - arg_indent.width(); } debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", @@ -1569,6 +1570,8 @@ fn rewrite_args(context: &RewriteContext, _ => multi_line_budget, }; + debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); + let end_with_newline = match context.config.fn_args_layout { FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => true, _ => false, diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index 7941d3a215e..1f2d740a075 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_layout: BlockAlways // rustfmt-where_indent: Inherit // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index 98f457207e3..27c97867d26 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_layout: BlockAlways // rustfmt-fn_args_density: Vertical // rustfmt-fn_arg_indent: Tabbed // rustfmt-fn_brace_style: AlwaysNextLine diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs new file mode 100644 index 00000000000..a1aebf1f38c --- /dev/null +++ b/tests/source/fn-custom-8.rs @@ -0,0 +1,50 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_indent: Inherit +// rustfmt-fn_brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} + +trait Test { + fn foo( + a: u8) { + + } + + fn bar(a: u8) + -> String { + + } + + fn bar(a: u8) -> String where Foo: foooo, Bar: barrr {} +} diff --git a/tests/source/fn_args_layout-block.rs b/tests/source/fn_args_layout-block.rs index 983ccc60d2b..b87158a4d7f 100644 --- a/tests/source/fn_args_layout-block.rs +++ b/tests/source/fn_args_layout-block.rs @@ -62,12 +62,16 @@ fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { - foo(); -} - trait Test { fn foo(a: u8) {} fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} } + +fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { + foo(); +} + +fn foo() -> (Looooooooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiiiiiiis, Loooooooooooooooooooooong) { + foo(); +} diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 8c1f89173d7..74e6765847e 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_layout: BlockAlways // rustfmt-where_indent: Inherit // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index c58678d45d9..82260d8c863 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_layout: BlockAlways // rustfmt-fn_args_density: Vertical // rustfmt-fn_arg_indent: Tabbed // rustfmt-fn_brace_style: AlwaysNextLine diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs new file mode 100644 index 00000000000..bd4a379969b --- /dev/null +++ b/tests/target/fn-custom-8.rs @@ -0,0 +1,74 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_indent: Inherit +// rustfmt-fn_brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) +where T: UUUUUUUUUUU { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String +where T: UUUUUUUUUUU { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String +where T: UUUUUUUUUUU { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} + + fn bar(a: u8) -> String + where Foo: foooo, + Bar: barrr { + } +} diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index b2d30018abd..cf380c649c8 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -98,10 +98,6 @@ fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { - foo(); -} - trait Test { fn foo(a: u8) {} @@ -114,3 +110,21 @@ trait Test { ) -> String { } } + +fn foo( + a: Aaaaaaaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd +) { + foo(); +} + +fn foo() + -> (Looooooooooooooooooooooooooong, + Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, + iiiiiiiiiiiiiis, + Loooooooooooooooooooooong) +{ + foo(); +} -- cgit 1.4.1-3-g733a5 From 6a82a5fb0eb523b8fda8058ddffa31fa6c25ca87 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 7 Apr 2016 20:47:43 +0100 Subject: Tidy up --- src/items.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 04bb2ec4a4c..5b901f2eafc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1363,15 +1363,16 @@ fn rewrite_fn_base(context: &RewriteContext, // Return type. if !ret_str.is_empty() { let ret_should_indent = match context.config.fn_args_layout { + // If our args are block layout then we surely must have space. FnArgLayoutStyle::Block if put_args_in_block => false, FnArgLayoutStyle::BlockAlways => false, _ => { + // If we've already gone multi-line, or the return type would push + // over the max width, then put the return type on a new line. result.contains("\n") || multi_line_ret_str || result.len() + indent.width() + ret_str_len > context.config.max_width } }; - // If we've already gone multi-line, or the return type would push - // over the max width, then put the return type on a new line. let ret_indent = if ret_should_indent { let indent = match context.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, @@ -1423,13 +1424,13 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let where_compressed = match context.config.where_density { + let should_compress_where = match context.config.where_density { Density::Compressed => !result.contains('\n') || put_args_in_block, Density::CompressedIfEmpty => !has_body && !result.contains('\n'), _ => false, } || (put_args_in_block && ret_str.is_empty()); - let where_density = if where_compressed { + let where_density = if should_compress_where { Density::Compressed } else { Density::Tall -- cgit 1.4.1-3-g733a5 From a8c27c70862cf8497ac1f48a8c950b30f46e906f Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Thu, 7 Apr 2016 16:29:05 -0400 Subject: macros: Cancel DiagnosticBuilder when not emitting error The error handling in libsyntax changed to use a `DiagnosticBuilder` type in the `Err` variant of `PResult`. This type has `emit()` and `cancel()` methods. Once created, errors must be emitted or canceled; if not, the `Drop` impl on `DiagnosticBuilder` will panic. The first syntex_syntax release to include this change was v0.25.0. The bump from v0.23.0 to v0.29.1 in #847 did not add any `cancel()` calls, even though at least one was required. There may be others not caught in this commit. --- src/macros.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index d2709bed809..a6cbd634dd9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -82,7 +82,10 @@ pub fn rewrite_macro(mac: &ast::Mac, loop { expr_vec.push(match parser.parse_expr() { Ok(expr) => expr, - Err(..) => return None, + Err(mut e) => { + e.cancel(); + return None; + } }); match parser.token { -- cgit 1.4.1-3-g733a5 From b55e50f3875f5b531f8180dcab3a260ad1f351a1 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 10 Apr 2016 17:57:44 -0400 Subject: rustfmt: Move getopts::Options creation to its own function --- src/bin/rustfmt.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index b65cbaa7f59..dba91612761 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -134,7 +134,7 @@ fn update_config(config: &mut Config, matches: &Matches) -> Result<(), String> { } } -fn execute() -> i32 { +fn make_opts() -> Options { let mut opts = Options::new(); opts.optflag("h", "help", "show this message"); opts.optflag("V", "version", "show version information"); @@ -154,6 +154,12 @@ fn execute() -> i32 { found reverts to the input file path", "[Path for the configuration file]"); + opts +} + +fn execute() -> i32 { + let opts = make_opts(); + let matches = match opts.parse(env::args().skip(1)) { Ok(m) => m, Err(e) => { -- cgit 1.4.1-3-g733a5 From fe5fa874da6ce1691add81a46f9bfd0a28d39076 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sat, 9 Apr 2016 16:15:36 -0400 Subject: rustfmt: Make error handling more idiomatic This commit replaces the `Operation::InvalidInput` variant with `Result`, and uses the `try!()` macro instead of explicit matching. --- src/bin/rustfmt.rs | 85 ++++++++++++++++++++++-------------------------------- 1 file changed, 35 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index dba91612761..a4067f40eda 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -20,7 +20,7 @@ extern crate getopts; use rustfmt::{run, Input}; use rustfmt::config::{Config, WriteMode}; -use std::env; +use std::{env, error}; use std::fs::{self, File}; use std::io::{self, ErrorKind, Read, Write}; use std::path::{Path, PathBuf}; @@ -28,6 +28,8 @@ use std::str::FromStr; use getopts::{Matches, Options}; +type FmtError = Box; +type FmtResult = std::result::Result; /// Rustfmt operations. enum Operation { @@ -42,10 +44,6 @@ enum Operation { Version, /// Print detailed configuration help. ConfigHelp, - /// Invalid program input. - InvalidInput { - reason: String, - }, /// No file specified, read from stdin Stdin { input: String, @@ -55,7 +53,7 @@ enum Operation { /// Try to find a project file in the given directory and its parents. Returns the path of a the /// nearest project file if one exists, or `None` if no project file was found. -fn lookup_project_file(dir: &Path) -> io::Result> { +fn lookup_project_file(dir: &Path) -> FmtResult> { let mut current = if dir.is_relative() { try!(env::current_dir()).join(dir) } else { @@ -77,7 +75,7 @@ fn lookup_project_file(dir: &Path) -> io::Result> { // return the error. Err(e) => { if e.kind() != ErrorKind::NotFound { - return Err(e); + return Err(FmtError::from(e)); } } } @@ -93,7 +91,7 @@ fn lookup_project_file(dir: &Path) -> io::Result> { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. -fn resolve_config(dir: &Path) -> io::Result<(Config, Option)> { +fn resolve_config(dir: &Path) -> FmtResult<(Config, Option)> { let path = try!(lookup_project_file(dir)); if path.is_none() { return Ok((Config::default(), None)); @@ -108,7 +106,7 @@ fn resolve_config(dir: &Path) -> io::Result<(Config, Option)> { /// read the given config file path recursively if present else read the project file path fn match_cli_path_or_file(config_path: Option, input_file: &Path) - -> io::Result<(Config, Option)> { + -> FmtResult<(Config, Option)> { if let Some(config_file) = config_path { let (toml, path) = try!(resolve_config(config_file.as_ref())); @@ -119,7 +117,7 @@ fn match_cli_path_or_file(config_path: Option, resolve_config(input_file) } -fn update_config(config: &mut Config, matches: &Matches) -> Result<(), String> { +fn update_config(config: &mut Config, matches: &Matches) -> FmtResult<()> { config.verbose = matches.opt_present("verbose"); config.skip_children = matches.opt_present("skip-children"); @@ -130,7 +128,10 @@ fn update_config(config: &mut Config, matches: &Matches) -> Result<(), String> { config.write_mode = write_mode; Ok(()) } - Some(Err(_)) => Err(format!("Invalid write-mode: {}", write_mode.expect("cannot happen"))), + Some(Err(_)) => { + Err(FmtError::from(format!("Invalid write-mode: {}", + write_mode.expect("cannot happen")))) + } } } @@ -157,35 +158,18 @@ fn make_opts() -> Options { opts } -fn execute() -> i32 { - let opts = make_opts(); +fn execute(opts: &Options) -> FmtResult<()> { + let matches = try!(opts.parse(env::args().skip(1))); - let matches = match opts.parse(env::args().skip(1)) { - Ok(m) => m, - Err(e) => { - print_usage(&opts, &e.to_string()); - return 1; - } - }; - - let operation = determine_operation(&matches); - - match operation { - Operation::InvalidInput { reason } => { - print_usage(&opts, &reason); - 1 - } + match try!(determine_operation(&matches)) { Operation::Help => { print_usage(&opts, ""); - 0 } Operation::Version => { print_version(); - 0 } Operation::ConfigHelp => { Config::print_docs(); - 0 } Operation::Stdin { input, config_path } => { // try to read config from local directory @@ -196,7 +180,6 @@ fn execute() -> i32 { config.write_mode = WriteMode::Plain; run(Input::Text(input), &config); - 0 } Operation::Format { files, config_path } => { let mut config = Config::default(); @@ -227,21 +210,26 @@ fn execute() -> i32 { config = config_tmp; } - if let Err(e) = update_config(&mut config, &matches) { - print_usage(&opts, &e); - return 1; - } + try!(update_config(&mut config, &matches)); run(Input::File(file), &config); } - 0 } } + Ok(()) } fn main() { let _ = env_logger::init(); - let exit_code = execute(); + let opts = make_opts(); + + let exit_code = match execute(&opts) { + Ok(..) => 0, + Err(e) => { + print_usage(&opts, &e.to_string()); + 1 + } + }; // Make sure standard output is flushed before we exit. std::io::stdout().flush().unwrap(); @@ -267,17 +255,17 @@ fn print_version() { option_env!("CARGO_PKG_VERSION_PRE").unwrap_or("")); } -fn determine_operation(matches: &Matches) -> Operation { +fn determine_operation(matches: &Matches) -> FmtResult { if matches.opt_present("h") { - return Operation::Help; + return Ok(Operation::Help); } if matches.opt_present("config-help") { - return Operation::ConfigHelp; + return Ok(Operation::ConfigHelp); } if matches.opt_present("version") { - return Operation::Version; + return Ok(Operation::Version); } // Read the config_path and convert to parent dir if a file is provided. @@ -294,21 +282,18 @@ fn determine_operation(matches: &Matches) -> Operation { if matches.free.is_empty() { let mut buffer = String::new(); - match io::stdin().read_to_string(&mut buffer) { - Ok(..) => (), - Err(e) => return Operation::InvalidInput { reason: e.to_string() }, - } + try!(io::stdin().read_to_string(&mut buffer)); - return Operation::Stdin { + return Ok(Operation::Stdin { input: buffer, config_path: config_path, - }; + }); } let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); - Operation::Format { + Ok(Operation::Format { files: files, config_path: config_path, - } + }) } -- cgit 1.4.1-3-g733a5 From 72427356eb6d99a26c6596742e96df5516a8adc1 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 10 Apr 2016 18:29:25 -0400 Subject: rustfmt: Simplify match in project file lookup loop This commit changes the match in `lookup_project_file` to use pattern guards. --- src/bin/rustfmt.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index a4067f40eda..e2a2a491848 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -65,19 +65,17 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { loop { let config_file = current.join("rustfmt.toml"); match fs::metadata(&config_file) { - Ok(md) => { - // Properly handle unlikely situation of a directory named `rustfmt.toml`. - if md.is_file() { - return Ok(Some(config_file)); - } - } - // If it's not found, we continue searching; otherwise something went wrong and we - // return the error. + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't find + // the project file yet, and continue searching. Err(e) => { if e.kind() != ErrorKind::NotFound { return Err(FmtError::from(e)); } } + _ => {} } // If the current directory has no parent, we're done searching. -- cgit 1.4.1-3-g733a5 From 7ac354fd0938a8bdcffb3b5521d5b109dfc1aa8e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 12 Apr 2016 06:45:47 +1200 Subject: Don't be so aggressie about line-breaking strings (#911) We will no longer break in the middle of words, only at whitespace or punctuation. This means we sometimes over-run, but that seems better than some of the bad splits we see. Closes #369 --- src/comment.rs | 47 ++++++++++++++++----------- src/string.rs | 48 ++++++++++++++++++---------- tests/target/enum.rs | 9 ++---- tests/target/hard-tabs.rs | 3 +- tests/target/string-lit-2.rs | 3 +- tests/target/string-lit.rs | 22 ++++--------- tests/target/string_punctuation.rs | 3 +- tests/target/struct_lits_visual.rs | 22 +++---------- tests/target/struct_lits_visual_multiline.rs | 22 +++---------- 9 files changed, 80 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 232e7691b82..9b64e3f1345 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -102,7 +102,7 @@ pub fn rewrite_comment(orig: &str, } if config.wrap_comments && line.len() > max_chars { - let rewrite = try_opt!(rewrite_string(line, &fmt)); + let rewrite = rewrite_string(line, &fmt).unwrap_or(line.to_owned()); result.push_str(&rewrite); } else { if line.len() == 0 { @@ -672,27 +672,36 @@ mod test { fn format_comments() { let mut config: ::config::Config = Default::default(); config.wrap_comments = true; - assert_eq!("/* test */", rewrite_comment(" //test", true, 100, Indent::new(0, 100), - &config).unwrap()); - assert_eq!("// comment\n// on a", rewrite_comment("// comment on a", false, 10, - Indent::empty(), &config).unwrap()); - - assert_eq!("// A multi line comment\n // between args.", - rewrite_comment("// A multi line comment\n // between args.", - false, - 60, - Indent::new(0, 12), - &config).unwrap()); + + let comment = rewrite_comment(" //test", true, 100, Indent::new(0, 100), &config).unwrap(); + assert_eq!("/* test */", comment); + + let comment = rewrite_comment("// comment on a", + false, + 10, + Indent::empty(), + &config).unwrap(); + assert_eq!("// comment\n// on a", comment); + + let comment = rewrite_comment("// A multi line comment\n // between args.", + false, + 60, + Indent::new(0, 12), + &config).unwrap(); + assert_eq!("// A multi line comment\n // between args.", comment); let input = "// comment"; let expected = - "/* com\n \ - * men\n \ - * t */"; - assert_eq!(expected, rewrite_comment(input, true, 9, Indent::new(0, 69), &config).unwrap()); - - assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, - Indent::new(0, 100), &config).unwrap()); + "/* comment */"; + let comment = rewrite_comment(input, true, 9, Indent::new(0, 69), &config).unwrap(); + assert_eq!(expected, comment); + + let comment = rewrite_comment("/* trimmed */", + true, + 100, + Indent::new(0, 100), + &config).unwrap(); + assert_eq!("/* trimmed */", comment); } // This is probably intended to be a non-test fn, but it is not used. I'm diff --git a/src/string.rs b/src/string.rs index d7e1fe763ef..bccf39deb92 100644 --- a/src/string.rs +++ b/src/string.rs @@ -39,6 +39,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let indent = fmt.offset.to_string(fmt.config); let punctuation = ":,;."; + // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; let mut result = String::with_capacity(stripped_str.len() .checked_next_power_of_two() @@ -50,30 +51,43 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // succeed. let max_chars = try_opt!(fmt.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; - loop { + // Snip a line at a time from `orig` until it is used up. Push the snippet + // onto result. + 'outer: loop { + // `cur_end` will be where we break the line, as an offset into `orig`. + // Initialised to the maximum it could be (which may be beyond `orig`). let mut cur_end = cur_start + max_chars; + // We can fit the rest of the string on this line, so we're done. if cur_end >= graphemes.len() { let line = &graphemes[cur_start..].join(""); result.push_str(line); - break; + break 'outer; } - // Push cur_end left until we reach whitespace. + // Push cur_end left until we reach whitespace (or the line is too small). while !graphemes[cur_end - 1].trim().is_empty() { cur_end -= 1; - if cur_end - cur_start < MIN_STRING { + if cur_end < cur_start + MIN_STRING { + // We couldn't find whitespace before the string got too small. + // So start again at the max length and look for punctuation. cur_end = cur_start + max_chars; - // Look for punctuation to break on. - while (!punctuation.contains(graphemes[cur_end - 1])) && cur_end > 1 { + while !punctuation.contains(graphemes[cur_end - 1]) { cur_end -= 1; - } - // We can't break at whitespace or punctuation, fall back to splitting - // anywhere that doesn't break an escape sequence. - if cur_end < cur_start + MIN_STRING { - cur_end = cur_start + max_chars; - while graphemes[cur_end - 1] == "\\" && cur_end > 1 { - cur_end -= 1; + + // If we can't break at whitespace or punctuation, grow the string instead. + if cur_end < cur_start + MIN_STRING { + cur_end = cur_start + max_chars; + while !(punctuation.contains(graphemes[cur_end - 1]) || + graphemes[cur_end - 1].trim().is_empty()) { + if cur_end >= graphemes.len() { + let line = &graphemes[cur_start..].join(""); + result.push_str(line); + break 'outer; + } + cur_end += 1; + } + break; } } break; @@ -83,12 +97,13 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { cur_end += 1; } + + // Make the current line and add it on to result. let raw_line = graphemes[cur_start..cur_end].join(""); let line = if fmt.trim_end { raw_line.trim() } else { - // FIXME: use as_str once it's stable. - &*raw_line + raw_line.as_str() }; result.push_str(line); @@ -97,10 +112,11 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option result.push_str(&indent); result.push_str(fmt.line_start); + // The next line starts where the current line ends. cur_start = cur_end; } - result.push_str(fmt.closer); + result.push_str(fmt.closer); Some(result) } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 9278488fecf..ae1bc4bc276 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -51,8 +51,7 @@ enum X { CreateWebGLPaintTask(Size2D, GLContextAttributes, IpcSender, usize), String>>), /* This is - * a post c - * omment */ + * a post comment */ } pub enum EnumWithAttributes { @@ -68,8 +67,7 @@ pub enum EnumWithAttributes { ItemStruct { x: usize, y: usize, - }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAA */ + }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ // And another ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ @@ -79,8 +77,7 @@ pub enum SingleTuple { // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Match(usize, usize, String), /* Post-comment - * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - * A */ + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ } pub enum SingleStruct { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index cf96392036b..cd694099d95 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -26,8 +26,7 @@ fn main() { a: i32) { } - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { diff --git a/tests/target/string-lit-2.rs b/tests/target/string-lit-2.rs index 08e8be8186c..c636f878ef1 100644 --- a/tests/target/string-lit-2.rs +++ b/tests/target/string-lit-2.rs @@ -10,6 +10,5 @@ fn main() -> &'static str { // Crappy formatting :-( let change_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss \ - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\ - j"; + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; } diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index e7146a84f9e..1d4d21ff73e 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -4,22 +4,16 @@ fn main() -> &'static str { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; let too_many_lines = "Hello"; // Make sure we don't break after an escape character. - let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ - \n\n\n"; - let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ - \n\n\n"; + let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ - AA"; + let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; let raw_string = r#"Do not @@ -28,16 +22,12 @@ formatting"#; filename.replace(" ", "\\"); - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion("yyyyyyyyyyyyyyyyyyyyy\ - yyyyyyyyyyyyyyyyyyyyy\ - yyyyyyyyyyyyyyyyyyyyy\ - yyyyyyyyyy"); + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); let unicode = "a̐éö̲\r\n"; let unicode2 = "Löwe 老虎 Léopard"; let unicode3 = "中华Việt Nam"; - let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃\ - ☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; "stuffin'" } diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs index 626bace0f5f..1acad404357 100644 --- a/tests/target/string_punctuation.rs +++ b/tests/target/string_punctuation.rs @@ -1,8 +1,7 @@ fn main() { println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ Likethisssssssssssss"); - format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColo\ - nsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}", + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}", x, y, z, diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index d5978c3debb..3a3aa35bb16 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -16,24 +16,10 @@ fn main() { Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Commen - // t - a: foo(), /* C - * o - * m - * m - * e - * n - * t */ - // Commen - // t - b: bar(), /* C - * o - * m - * m - * e - * n - * t */ }; + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* Comment */ + // Comment + b: bar(), /* Comment */ }; Foo { a: Bar, b: f() }; diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs index 3433b01ff50..f233b24c213 100644 --- a/tests/target/struct_lits_visual_multiline.rs +++ b/tests/target/struct_lits_visual_multiline.rs @@ -18,24 +18,10 @@ fn main() { Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Commen - // t - a: foo(), /* C - * o - * m - * m - * e - * n - * t */ - // Commen - // t - b: bar(), /* C - * o - * m - * m - * e - * n - * t */ }; + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* Comment */ + // Comment + b: bar(), /* Comment */ }; Foo { a: Bar, b: foo(), }; -- cgit 1.4.1-3-g733a5 From 492b26cf04b62ff372d5af4ba99e5d5f49079fba Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 12 Apr 2016 07:05:54 +1200 Subject: Empty structs and struct lits (#920) * Handle empty struct lits Closes #835 * Don't crash on empty struct defs. Not a great fix, but better than crashing. --- src/expr.rs | 5 ++++- src/items.rs | 10 +++++++--- tests/source/struct_lits.rs | 9 +++++++++ tests/source/structs.rs | 3 +++ tests/target/struct_lits.rs | 9 +++++++++ tests/target/structs.rs | 3 +++ 6 files changed, 35 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a0274e4db8a..696a626bee8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1390,7 +1390,6 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, offset: Indent) -> Option { debug!("rewrite_struct_lit: width {}, offset {:?}", width, offset); - assert!(!fields.is_empty() || base.is_some()); enum StructLitField<'a> { Regular(&'a ast::Field), @@ -1502,6 +1501,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }; let fields_str = try_opt!(write_list(&item_vec, &fmt)); + if fields_str.is_empty() { + return Some(format!("{} {{}}", path_str)); + } + let format_on_newline = || { let inner_indent = context.block_indent .block_indent(context.config) diff --git a/src/items.rs b/src/items.rs index 2e0cac0df07..82937e5a2ad 100644 --- a/src/items.rs +++ b/src/items.rs @@ -786,7 +786,7 @@ fn format_struct_struct(context: &RewriteContext, }; result.push_str(&generics_str); - // FIXME: properly format empty structs and their comments. + // FIXME(#919): properly format empty structs and their comments. if fields.is_empty() { result.push_str(&context.snippet(mk_sp(body_lo, span.hi))); return Some(result); @@ -838,13 +838,17 @@ fn format_tuple_struct(context: &RewriteContext, span: Span, offset: Indent) -> Option { - assert!(!fields.is_empty(), "Tuple struct with no fields?"); let mut result = String::with_capacity(1024); let header_str = format_header(item_name, ident, vis); result.push_str(&header_str); - let body_lo = fields[0].span.lo; + // FIXME(#919): don't lose comments on empty tuple structs. + let body_lo = if fields.is_empty() { + span.hi + } else { + fields[0].span.lo + }; let where_clause_str = match generics { Some(ref generics) => { diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index c62a355c5dd..1341983ed0f 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -123,3 +123,12 @@ fn issue698() { ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, } } + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 38469efa2d9..ff297655713 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -151,3 +151,6 @@ struct Issue677 { pub trace: fn( obj: *const libc::c_void, tracer : *mut JSTracer ), } + +struct Foo {} +struct Foo(); diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 299afb422ec..c8b475df24f 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -159,3 +159,12 @@ fn issue698() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, } } + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} diff --git a/tests/target/structs.rs b/tests/target/structs.rs index adaa626c096..428258c4f76 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -158,3 +158,6 @@ struct Issue677 { pub ptr: *const libc::c_void, pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), } + +struct Foo {} +struct Foo(); -- cgit 1.4.1-3-g733a5 From dc1fc4be0fe1903c4d14070e62f2aafe9a91bd98 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 11 Apr 2016 19:49:56 +0300 Subject: unify format_string and format_file --- src/lib.rs | 83 ++++++++++++++++++++------------------------------------- tests/system.rs | 8 ++++++ 2 files changed, 37 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index b7af96ac5aa..93267ef7af3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ extern crate term; use syntax::ast; use syntax::codemap::{mk_sp, CodeMap, Span}; -use syntax::errors::Handler; +use syntax::errors::{Handler, DiagnosticBuilder}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; @@ -263,11 +263,11 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn fmt_ast(krate: &ast::Crate, - parse_session: &ParseSess, - main_file: &Path, - config: &Config) - -> FileMap { +fn format_ast(krate: &ast::Crate, + parse_session: &ParseSess, + main_file: &Path, + config: &Config) + -> FileMap { let mut file_map = FileMap::new(); for (path, module) in modules::list_files(krate, parse_session.codemap()) { if config.skip_children && path.as_path() != main_file { @@ -367,43 +367,18 @@ fn format_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -fn format_string(input: String, config: &Config) -> FileMap { - let path = "stdin"; - let codemap = Rc::new(CodeMap::new()); - - let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, - None, - true, - false, - codemap.clone()); - let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - - let krate = parse::parse_crate_from_source_str(path.to_owned(), - input, - Vec::new(), - &parse_session) - .unwrap(); - - // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - - // FIXME: we still use a FileMap even though we only have - // one file, because fmt_lines requires a FileMap - let mut file_map = FileMap::new(); - - // do the actual formatting - let mut visitor = FmtVisitor::from_codemap(&parse_session, config); - visitor.format_separate_mod(&krate.module); - - // append final newline - visitor.buffer.push_str("\n"); - file_map.insert(path.to_owned(), visitor.buffer); +fn parse_input(input: Input, parse_session: &ParseSess) -> Result { + let krate = match input { + Input::File(file) => parse::parse_crate_from_file(&file, Vec::new(), &parse_session), + Input::Text(text) => { + parse::parse_crate_from_source_str("stdin".to_owned(), text, Vec::new(), &parse_session) + } + }; - file_map + krate } -fn format_file(file: &Path, config: &Config) -> FileMap { +pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { let codemap = Rc::new(CodeMap::new()); let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, @@ -413,27 +388,29 @@ fn format_file(file: &Path, config: &Config) -> FileMap { codemap.clone()); let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session).unwrap(); + let main_file = match input { + Input::File(ref file) => file.clone(), + Input::Text(..) => PathBuf::from("stdin"), + }; + + let krate = match parse_input(input, &parse_session) { + Ok(krate) => krate, + Err(mut diagnostic) => { + diagnostic.emit(); + panic!("Unrecoverable parse error"); + } + }; // Suppress error output after parsing. let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - let mut file_map = fmt_ast(&krate, &parse_session, file, config); + let mut file_map = format_ast(&krate, &parse_session, &main_file, config); // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. filemap::append_newlines(&mut file_map); - file_map -} - -pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { - let mut file_map = match input { - Input::File(ref file) => format_file(file, config), - Input::Text(text) => format_string(text, config), - }; - let report = format_lines(&mut file_map, config); (file_map, report) } @@ -455,8 +432,6 @@ pub fn run(input: Input, config: &Config) { let write_result = filemap::write_all_files(&file_map, &mut out, config); if let Err(msg) = write_result { - if !ignore_errors { - msg!("Error writing files: {}", msg); - } + msg!("Error writing files: {}", msg); } } diff --git a/tests/system.rs b/tests/system.rs index b6518a559b9..6b13e77a7be 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -139,6 +139,14 @@ fn self_tests() { warnings); } +#[test] +fn stdin_formatting_smoke_test() { + let input = Input::Text("fn main () {}".to_owned()); + let config = Config::default(); + let (file_map, _report) = format_input(input, &config); + assert_eq!(file_map["stdin"].to_string(), "fn main() {}\n") +} + // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: I) -> (Vec, u32, u32) -- cgit 1.4.1-3-g733a5 From afc8be1d798ad44a201a23df8135be4ce9c29612 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 9 Apr 2016 18:40:00 +1200 Subject: Change the logic around breaking multiple patterns in match arms Refactor to use the list code, don't preserve original stacking-ness, base vertical vs mixed formatting on complexity of the patterns. Closes #386 --- src/config.rs | 3 ++- src/expr.rs | 61 ++++++++++++++++++++++++++------------------------- src/macros.rs | 3 ++- src/types.rs | 3 ++- src/visitor.rs | 3 ++- tests/source/match.rs | 10 +++++++++ tests/target/match.rs | 19 +++++++++++----- 7 files changed, 63 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 46c28322c92..bd01492d74e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -87,7 +87,8 @@ impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { Density::Compressed => ListTactic::Mixed, - Density::Tall | Density::CompressedIfEmpty => ListTactic::HorizontalVertical, + Density::Tall | + Density::CompressedIfEmpty => ListTactic::HorizontalVertical, Density::Vertical => ListTactic::Vertical, } } diff --git a/src/expr.rs b/src/expr.rs index 696a626bee8..8befc1adbe1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -497,7 +497,8 @@ impl Rewrite for ast::Stmt { None } } - ast::StmtKind::Expr(ref ex, _) | ast::StmtKind::Semi(ref ex, _) => { + ast::StmtKind::Expr(ref ex, _) | + ast::StmtKind::Semi(ref ex, _) => { let suffix = if semicolon_for_stmt(self) { ";" } else { @@ -953,7 +954,6 @@ fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; - let indent_str = offset.to_string(context.config); // FIXME this is all a bit grotty, would be nice to abstract out the // treatment of attributes. @@ -980,38 +980,34 @@ impl Rewrite for ast::Arm { .map(|p| p.rewrite(context, pat_budget, offset)) .collect::>>()); - let mut total_width = pat_strs.iter().fold(0, |a, p| a + p.len()); - // Add ` | `.len(). - total_width += (pat_strs.len() - 1) * 3; - - let mut vertical = total_width > pat_budget || pat_strs.iter().any(|p| p.contains('\n')); - if !vertical && context.config.take_source_hints { - // If the patterns were previously stacked, keep them stacked. - let pat_span = mk_sp(pats[0].span.lo, pats[pats.len() - 1].span.hi); - let pat_str = context.snippet(pat_span); - vertical = pat_str.contains('\n'); - } + let all_simple = pat_strs.iter().all(|p| pat_is_simple(&p)); + let items: Vec<_> = pat_strs.into_iter().map(|s| ListItem::from_str(s)).collect(); + let fmt = ListFormatting { + tactic: if all_simple { + DefinitiveListTactic::Mixed + } else { + DefinitiveListTactic::Vertical + }, + separator: " |", + trailing_separator: SeparatorTactic::Never, + indent: offset, + width: pat_budget, + ends_with_newline: false, + config: context.config, + }; + let pats_str = try_opt!(write_list(items, &fmt)); - let pats_width = if vertical { - pat_strs.last().unwrap().len() + let budget = if pats_str.contains('\n') { + context.config.max_width } else { - total_width + width }; - let mut pats_str = String::new(); - for p in pat_strs { - if !pats_str.is_empty() { - if vertical { - pats_str.push_str(" |\n"); - pats_str.push_str(&indent_str); - } else { - pats_str.push_str(" | "); - } - } - pats_str.push_str(&p); - } - - let guard_str = try_opt!(rewrite_guard(context, guard, width, offset, pats_width)); + let guard_str = try_opt!(rewrite_guard(context, + guard, + budget, + offset, + last_line_width(&pats_str))); let pats_str = format!("{}{}", pats_str, guard_str); // Where the next text can start. @@ -1085,6 +1081,11 @@ impl Rewrite for ast::Arm { } } +fn pat_is_simple(pat_str: &str) -> bool { + pat_str.len() <= 16 || + (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) +} + // The `if ...` guard on a match arm. fn rewrite_guard(context: &RewriteContext, guard: &Option>, diff --git a/src/macros.rs b/src/macros.rs index a6cbd634dd9..2be271e140b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -58,7 +58,8 @@ pub fn rewrite_macro(mac: &ast::Mac, -> Option { let original_style = macro_style(mac, context); let macro_name = match extra_ident { - None | Some(ast::Ident { name: ast::Name(0), .. }) => format!("{}!", mac.node.path), + None | + Some(ast::Ident { name: ast::Name(0), .. }) => format!("{}!", mac.node.path), Some(ident) => format!("{}! {}", mac.node.path, ident), }; let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { diff --git a/src/types.rs b/src/types.rs index 5a8e456bedb..51bebc409e0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -552,7 +552,8 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => { rewrite_bare_fn(bare_fn, self.span, context, width, offset) } - ast::TyKind::Mac(..) | ast::TyKind::Typeof(..) => unreachable!(), + ast::TyKind::Mac(..) | + ast::TyKind::Typeof(..) => unreachable!(), } } } diff --git a/src/visitor.rs b/src/visitor.rs index 6ef07e922c0..cc97c2289f0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -46,7 +46,8 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(stmt.span, rewrite); } } - ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + ast::StmtKind::Expr(..) | + ast::StmtKind::Semi(..) => { let rewrite = stmt.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), self.block_indent); diff --git a/tests/source/match.rs b/tests/source/match.rs index 3723424317b..6e8418f66d2 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -274,3 +274,13 @@ fn issue494() { } } } + +fn issue386() { + match foo { + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => + true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => + false, + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index ed571d32123..3bc675aa3d9 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -221,9 +221,8 @@ fn issue355() { fn issue280() { { match x { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => { - ch == '\n' - } + CompressionMode::DiscardNewline | + CompressionMode::CompressWhitespaceNewline => ch == '\n', ast::ItemConst(ref typ, ref expr) => { self.process_static_or_const_item(item, &typ, &expr) } @@ -260,7 +259,8 @@ fn issue496() { { { match def { - def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { + def::DefConst(def_id) | + def::DefAssociatedConst(def_id) => { match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { Some(const_expr) => x, } @@ -274,7 +274,8 @@ fn issue496() { fn issue494() { { match stmt.node { - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { + hir::StmtExpr(ref expr, id) | + hir::StmtSemi(ref expr, id) => { result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Expr { @@ -286,3 +287,11 @@ fn issue494() { } } } + +fn issue386() { + match foo { + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | + BiShl | BiShr => false, + } +} -- cgit 1.4.1-3-g733a5 From 5dc3283e49cc739425a314c1b0837c72f0d6909d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 12 Apr 2016 10:30:57 +1200 Subject: Reviewer comments - mostly fix rewrite_guard --- src/expr.rs | 15 +++++++++------ src/utils.rs | 7 +++++++ tests/source/match.rs | 10 ++++++++++ tests/target/match.rs | 14 ++++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8befc1adbe1..7ee69885a42 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -21,7 +21,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; use string::{StringFormat, rewrite_string}; use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, - first_line_width, semicolon_for_stmt}; + first_line_width, semicolon_for_stmt, trimmed_last_line_width}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -998,7 +998,7 @@ impl Rewrite for ast::Arm { let pats_str = try_opt!(write_list(items, &fmt)); let budget = if pats_str.contains('\n') { - context.config.max_width + context.config.max_width - offset.width() } else { width }; @@ -1007,7 +1007,7 @@ impl Rewrite for ast::Arm { guard, budget, offset, - last_line_width(&pats_str))); + trimmed_last_line_width(&pats_str))); let pats_str = format!("{}{}", pats_str, guard_str); // Where the next text can start. @@ -1019,7 +1019,7 @@ impl Rewrite for ast::Arm { let body = match **body { ast::Expr { node: ast::ExprKind::Block(ref block), .. } if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && - context.config.wrap_match_arms => block.expr.as_ref().map(|e| &**e).unwrap(), + context.config.wrap_match_arms => block.expr.as_ref().map(|e| &**e).unwrap(), ref x => x, }; @@ -1081,6 +1081,8 @@ impl Rewrite for ast::Arm { } } +// A pattern is simple if it is very short or it is short-ish and just a path. +// E.g. `Foo::Bar` is simple, but `Foo(..)` is not. fn pat_is_simple(pat_str: &str) -> bool { pat_str.len() <= 16 || (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) @@ -1107,11 +1109,12 @@ fn rewrite_guard(context: &RewriteContext, } // Not enough space to put the guard after the pattern, try a newline. - let overhead = context.config.tab_spaces + 4 + 5; + let overhead = offset.block_indent(context.config).width() + 4 + 5; if overhead < width { let cond_str = guard.rewrite(context, width - overhead, - offset.block_indent(context.config)); + // 3 == `if ` + offset.block_indent(context.config) + 3); if let Some(cond_str) = cond_str { return Some(format!("\n{}if {}", offset.block_indent(context.config).to_string(context.config), diff --git a/src/utils.rs b/src/utils.rs index 66b9880777f..862ceb1e13e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -113,6 +113,13 @@ pub fn last_line_width(s: &str) -> usize { None => s.len(), } } +#[inline] +pub fn trimmed_last_line_width(s: &str) -> usize { + match s.rfind('\n') { + Some(n) => s[(n + 1)..].trim().len(), + None => s.trim().len(), + } +} #[inline] fn is_skip(meta_item: &MetaItem) -> bool { diff --git a/tests/source/match.rs b/tests/source/match.rs index 6e8418f66d2..a9fb5404047 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -284,3 +284,13 @@ fn issue386() { false, } } + +fn guards() { + match foo { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if fooooooooooooooooooooo && + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {} + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 3bc675aa3d9..bc5556283c3 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -295,3 +295,17 @@ fn issue386() { BiShl | BiShr => false, } } + +fn guards() { + match foo { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && + barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && + barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if fooooooooooooooooooooo && + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || + cccccccccccccccccccccccccccccccccccccccc) => {} + } +} -- cgit 1.4.1-3-g733a5 From eadc878de01b99347c8f6e627459e5d69a307b8b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 11 Apr 2016 21:20:03 +1200 Subject: Handle variadic function types Closes #842 --- src/expr.rs | 2 +- src/types.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++---- tests/source/type.rs | 8 ++++++++ tests/target/type.rs | 14 ++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7ee69885a42..0c30aaf3f6f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -981,7 +981,7 @@ impl Rewrite for ast::Arm { .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(&p)); - let items: Vec<_> = pat_strs.into_iter().map(|s| ListItem::from_str(s)).collect(); + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); let fmt = ListFormatting { tactic: if all_simple { DefinitiveListTactic::Mixed diff --git a/src/types.rs b/src/types.rs index 51bebc409e0..09cf7e12126 100644 --- a/src/types.rs +++ b/src/types.rs @@ -220,6 +220,7 @@ fn rewrite_segment(expr_context: bool, }; try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), &output, + false, data.span, context, width, @@ -233,6 +234,7 @@ fn rewrite_segment(expr_context: bool, fn format_function_type<'a, I>(inputs: I, output: &FunctionRetTy, + variadic: bool, span: Span, context: &RewriteContext, width: usize, @@ -242,17 +244,54 @@ fn format_function_type<'a, I>(inputs: I, ::Item: Deref, ::Target: Rewrite + Spanned + 'a { + // Code for handling variadics is somewhat duplicated for items, but they + // are different enough to need some serious refactoring to share code. + enum ArgumentKind + where T: Deref, + ::Target: Rewrite + Spanned + { + Regular(Box), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_start = context.codemap.span_before(span, "..."); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + // 2 for () let budget = try_opt!(width.checked_sub(2)); // 1 for ( let offset = offset + 1; let list_lo = context.codemap.span_after(span, "("); let items = itemize_list(context.codemap, - inputs, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs.map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), ")", - |ty| ty.span().lo, - |ty| ty.span().hi, - |ty| ty.rewrite(context, budget, offset), + |arg| { + match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Variadic(start) => start, + } + }, + |arg| { + match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + } + }, + |arg| { + match *arg { + ArgumentKind::Regular(ref ty) => { + ty.rewrite(context, budget, offset) + } + ArgumentKind::Variadic(_) => Some("...".to_owned()), + } + }, list_lo, span.hi); @@ -579,6 +618,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(), &bare_fn.decl.output, + bare_fn.decl.variadic, span, context, budget, diff --git a/tests/source/type.rs b/tests/source/type.rs index 71822bd668d..dcb8e0d0f31 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -4,3 +4,11 @@ fn types() { let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk(); } + +struct F { + f: extern "C" fn(x: u8, ... /* comment */), + g: extern "C" fn(x: u8,/* comment */ ...), + h: extern "C" fn(x: u8, ... ), + i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3 + z: Foo, /* comment */ .../* comment 2*/ ), +} diff --git a/tests/target/type.rs b/tests/target/type.rs index a8a5e028aa5..1ae1143bcca 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -7,3 +7,17 @@ fn types() { i16) = funk(); let z: (usize /* #digits */, i16 /* exp */) = funk(); } + +struct F { + f: extern "C" fn(x: u8, ... /* comment */), + g: extern "C" fn(x: u8, + // comment + ...), + h: extern "C" fn(x: u8, ...), + i: extern "C" fn(x: u8, + // comment 4 + y: String, // comment 3 + z: Foo, + // comment + ... /* comment 2 */), +} -- cgit 1.4.1-3-g733a5 From c6084cb29c13256d402bfec8f854420d0b240a1b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 12 Apr 2016 11:04:33 +1200 Subject: Fix the build --- src/items.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e2f41259cef..7eddf63dd62 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1578,7 +1578,8 @@ fn rewrite_args(context: &RewriteContext, debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); let end_with_newline = match context.config.fn_args_layout { - FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => true, + FnArgLayoutStyle::Block | + FnArgLayoutStyle::BlockAlways => true, _ => false, }; -- cgit 1.4.1-3-g733a5 From 58b022c56a51669e1e36b94eba864b8ca6d4c41b Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 14 Apr 2016 00:52:45 +0530 Subject: Change stdout to stderr (#925) --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 93267ef7af3..92b6ffb8527 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -425,7 +425,7 @@ pub fn run(input: Input, config: &Config) { let ignore_errors = config.write_mode == WriteMode::Plain; if !ignore_errors { - print!("{}", report); + msg!("{}", report); } let mut out = stdout(); -- cgit 1.4.1-3-g733a5 From c7780fdfd8c23cfbc49f537490dda65af3a6ad8b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 14 Apr 2016 08:36:59 +1200 Subject: Be careful about where we change braces in closures And some general refactoring of closure code. Fixes #863 --- src/expr.rs | 118 ++++++++++++++++++++++++++----------- src/utils.rs | 19 ++++++ tests/source/closure.rs | 7 +++ tests/target/chains-no-overflow.rs | 18 +++--- tests/target/chains.rs | 18 +++--- tests/target/closure.rs | 17 ++++-- 6 files changed, 134 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0c30aaf3f6f..6cc8c3aa4a9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -21,7 +21,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; use string::{StringFormat, rewrite_string}; use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, - first_line_width, semicolon_for_stmt, trimmed_last_line_width}; + first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -32,6 +32,7 @@ use macros::rewrite_macro; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; +use syntax::parse::classify; use syntax::visit::Visitor; impl Rewrite for ast::Expr { @@ -308,8 +309,13 @@ pub fn rewrite_array<'a, I>(expr_iter: I, Some(format!("[{}]", list_str)) } -// This functions is pretty messy because of the wrapping and unwrapping of -// expressions into and from blocks. See rust issue #27872. +// This functions is pretty messy because of the rules around closures and blocks: +// * the body of a closure is represented by an ast::Block, but that does not +// imply there are `{}` (unless the block is empty) (see rust issue #27872), +// * if there is a return type, then there must be braces, +// * if the first expression in the body ends with a block (i.e., is a +// statement without needing a semi-colon), then adding or removing braces +// can change whether it is treated as an expression or statement. fn rewrite_closure(capture: ast::CaptureBy, fn_decl: &ast::FnDecl, body: &ast::Block, @@ -331,6 +337,8 @@ fn rewrite_closure(capture: ast::CaptureBy, // 1 = | let argument_offset = offset + 1; let ret_str = try_opt!(fn_decl.output.rewrite(context, budget, argument_offset)); + let force_block = !ret_str.is_empty(); + // 1 = space between arguments and return type. let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0); @@ -371,51 +379,91 @@ fn rewrite_closure(capture: ast::CaptureBy, prefix.push_str(&ret_str); } - // Try to format closure body as a single line expression without braces. - if is_simple_block(body, context.codemap) && !prefix.contains('\n') { - let (spacer, closer) = if ret_str.is_empty() { - (" ", "") - } else { - (" { ", " }") - }; - let expr = body.expr.as_ref().unwrap(); - // All closure bodies are blocks in the eyes of the AST, but we may not - // want to unwrap them when they only contain a single expression. - let inner_expr = match expr.node { - ast::ExprKind::Block(ref inner) if inner.stmts.is_empty() && inner.expr.is_some() && - inner.rules == ast::BlockCheckMode::Default => { - inner.expr.as_ref().unwrap() + assert!(body.stmts.is_empty(), + "unexpected statements in closure: `{}`", + context.snippet(span)); + + if body.expr.is_none() { + return Some(format!("{} {{}}", prefix)); + } + + // 1 = space between `|...|` and body. + let extra_offset = extra_offset(&prefix, offset) + 1; + let budget = try_opt!(width.checked_sub(extra_offset)); + + // This is where we figure out whether to use braces or not. + let mut had_braces = false; + let mut inner_block = body; + if let ast::ExprKind::Block(ref inner) = inner_block.expr.as_ref().unwrap().node { + had_braces = true; + inner_block = inner; + }; + assert!(!force_block || !had_braces, + "Closure requires braces, but they weren't present. How did this parse? `{}`", + context.snippet(span)); + + let try_single_line = is_simple_block(inner_block, context.codemap) && + inner_block.rules == ast::BlockCheckMode::Default; + + if try_single_line && !force_block { + let must_preserve_braces = + !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(inner_block.expr + .as_ref() + .unwrap())); + if !(must_preserve_braces && had_braces) && + (must_preserve_braces || !prefix.contains('\n')) { + // If we got here, then we can try to format without braces. + + let inner_expr = inner_block.expr.as_ref().unwrap(); + let mut rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); + + if must_preserve_braces { + // If we are here, then failure to rewrite is unacceptable. + if rewrite.is_none() { + return None; + } + } else { + // Checks if rewrite succeeded and fits on a single line. + rewrite = and_one_line(rewrite); } - _ => expr, - }; - let extra_offset = extra_offset(&prefix, offset) + spacer.len(); - let budget = try_opt!(width.checked_sub(extra_offset + closer.len())); - let rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); + + if let Some(rewrite) = rewrite { + return Some(format!("{} {}", prefix, rewrite)); + } + } + } + + // If we fell through the above block, then we need braces, but we might + // still prefer a one-liner (we might also have fallen through because of + // lack of space). + if try_single_line && !prefix.contains('\n') { + let inner_expr = inner_block.expr.as_ref().unwrap(); + // 4 = braces and spaces. + let mut rewrite = inner_expr.rewrite(context, budget - 4, offset + extra_offset); // Checks if rewrite succeeded and fits on a single line. - let accept_rewrite = rewrite.as_ref().map_or(false, |result| !result.contains('\n')); + rewrite = and_one_line(rewrite); - if accept_rewrite { - return Some(format!("{}{}{}{}", prefix, spacer, rewrite.unwrap(), closer)); + if let Some(rewrite) = rewrite { + return Some(format!("{} {{ {} }}", prefix, rewrite)); } } // We couldn't format the closure body as a single line expression; fall // back to block formatting. - let body_rewrite = body.expr - .as_ref() - .and_then(|body_expr| { - if let ast::ExprKind::Block(ref inner) = body_expr.node { - Some(inner.rewrite(&context, 2, Indent::empty())) - } else { - None - } - }) - .unwrap_or_else(|| body.rewrite(&context, 2, Indent::empty())); + let body_rewrite = inner_block.rewrite(&context, budget, Indent::empty()); Some(format!("{} {}", prefix, try_opt!(body_rewrite))) } +fn and_one_line(x: Option) -> Option { + x.and_then(|x| if x.contains('\n') { + None + } else { + Some(x) + }) +} + fn nop_block_collapse(block_str: Option, budget: usize) -> Option { block_str.map(|block_str| { if block_str.starts_with("{") && budget >= 2 && diff --git a/src/utils.rs b/src/utils.rs index 862ceb1e13e..a3c7c036879 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -334,3 +334,22 @@ fn bin_search_test() { assert_eq!(Some(()), binary_search(4, 125, &closure)); assert_eq!(None, binary_search(6, 100, &closure)); } + +pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { + match e.node { + ast::ExprKind::InPlace(ref e, _) | + ast::ExprKind::Call(ref e, _) | + ast::ExprKind::Binary(_, ref e, _) | + ast::ExprKind::Cast(ref e, _) | + ast::ExprKind::Type(ref e, _) | + ast::ExprKind::Assign(ref e, _) | + ast::ExprKind::AssignOp(_, ref e, _) | + ast::ExprKind::Field(ref e, _) | + ast::ExprKind::TupField(ref e, _) | + ast::ExprKind::Index(ref e, _) | + ast::ExprKind::Range(Some(ref e), _, _) => left_most_sub_expr(e), + // FIXME needs Try in Syntex + // ast::ExprKind::Try(ref f) => left_most_sub_expr(e), + _ => e, + } +} diff --git a/tests/source/closure.rs b/tests/source/closure.rs index 6abd7f9c0a7..e125a683dc6 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -50,3 +50,10 @@ fn issue311() { (func)(0.0); } + +fn issue863() { + let closure = |x| match x { + 0 => true, + _ => false, + } == true; +} diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs index 400db5f8df5..2479157bb4f 100644 --- a/tests/target/chains-no-overflow.rs +++ b/tests/target/chains-no-overflow.rs @@ -9,20 +9,16 @@ fn main() { .ddddddddddddddddddddddddddd .eeeeeeee(); - x().y(|| { - match cond() { - true => (), - false => (), - } + x().y(|| match cond() { + true => (), + false => (), }); loong_func() - .quux(move || { - if true { - 1 - } else { - 2 - } + .quux(move || if true { + 1 + } else { + 2 }); fffffffffffffffffffffffffffffffffff(a, diff --git a/tests/target/chains.rs b/tests/target/chains.rs index d8fca6d40fe..392ff355b86 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -16,19 +16,15 @@ fn main() { // Test case where first chain element isn't a path, but is shorter than // the size of a tab. - x().y(|| { - match cond() { - true => (), - false => (), - } + x().y(|| match cond() { + true => (), + false => (), }); - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } + loong_func().quux(move || if true { + 1 + } else { + 2 }); some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 382919ce403..467b07b38ca 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -26,12 +26,10 @@ fn main() { } }; - let block_me = |field| { - if true_story() { - 1 - } else { - 2 - } + let block_me = |field| if true_story() { + 1 + } else { + 2 }; let unblock_me = |trivial| closure(); @@ -77,3 +75,10 @@ fn issue311() { (func)(0.0); } + +fn issue863() { + let closure = |x| match x { + 0 => true, + _ => false, + } == true; +} -- cgit 1.4.1-3-g733a5 From b1efb3a39e23b4ccbc4feef0a30c02441a2384e9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 14 Apr 2016 01:39:39 +0300 Subject: don't silence error unnecessary This `if` was used to separate error output from the formatting output, when they both used stdout. It was useful for integration with tools, which can submit input to stdin and read pretty printed result from stdout without worrying about errors intermingled with the actual result. But now we write errors to `stderr`, so the problem disappears and we can safely remove this `if`. Errors should never pass silently, unless explicitly silenced. --- src/lib.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 92b6ffb8527..d0ff4be7241 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -422,11 +422,7 @@ pub enum Input { pub fn run(input: Input, config: &Config) { let (file_map, report) = format_input(input, config); - - let ignore_errors = config.write_mode == WriteMode::Plain; - if !ignore_errors { - msg!("{}", report); - } + msg!("{}", report); let mut out = stdout(); let write_result = filemap::write_all_files(&file_map, &mut out, config); -- cgit 1.4.1-3-g733a5 From 320df84e96bcdb92dbb6ed83db4093106fa9ee0b Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Thu, 14 Apr 2016 20:42:38 +0200 Subject: Fix brace indentation for impl items (#927) --- src/items.rs | 8 +++++--- tests/source/impls.rs | 10 ++++++++++ tests/target/impls.rs | 12 ++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7eddf63dd62..cee1fc4f13e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -499,7 +499,8 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { result.push_str(&where_clause_str); if where_clause_str.contains('\n') { - result.push_str("\n{\n}"); + let white_space = offset.to_string(context.config); + result.push_str(&format!("\n{}{{\n{}}}", &white_space, &white_space)); } else { result.push_str(" {}"); } @@ -519,9 +520,10 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if !where_clause_str.is_empty() { - result.push('\n') + result.push('\n'); + result.push_str(&offset.to_string(context.config)); } else { - result.push(' ') + result.push(' '); } } } diff --git a/tests/source/impls.rs b/tests/source/impls.rs index e96baa91473..0eb084018bc 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -87,3 +87,13 @@ pub impl Foo for Bar where T: Foo } pub impl Foo for Bar where T: Foo, Z: Baz {} + +mod m { + impl PartialEq for S where T: PartialEq { + fn eq(&self, other: &Self) { + true + } + } + + impl PartialEq for S where T: PartialEq { } + } diff --git a/tests/target/impls.rs b/tests/target/impls.rs index c592ab6f9f9..38c972c0031 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -112,3 +112,15 @@ pub impl Foo for Bar Z: Baz { } + +mod m { + impl PartialEq for S + where T: PartialEq + { + fn eq(&self, other: &Self) { + true + } + } + + impl PartialEq for S where T: PartialEq {} +} -- cgit 1.4.1-3-g733a5 From 77350e49b5d4674085e306986c564fd99686cc67 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Apr 2016 02:51:50 +0300 Subject: return non-zero exit code if there were errors --- README.md | 12 ++++++++++-- src/bin/rustfmt.rs | 28 +++++++++++++++++++++------ src/lib.rs | 43 +++++++++++++++++++++++++++++++----------- src/summary.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/system.rs | 15 +++++++++++++-- 5 files changed, 132 insertions(+), 21 deletions(-) create mode 100644 src/summary.rs (limited to 'src') diff --git a/README.md b/README.md index fbe605fb430..b1bd8227b3d 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,18 @@ diff, replace, overwrite, display, coverage, and checkstyle. The write mode can be set by passing the `--write-mode` flag on the command line. For example `rustfmt --write-mode=display src/filename.rs` -You can run `rustfmt --help` for more information. - `cargo fmt` uses `--write-mode=replace` by default. +If `rustfmt` successfully reformatted the code it will exit with `0` exit +status. Exit status `1` signals some unexpected error, like an unknown option or +a failure to read a file. Exit status `2` is returned if there are syntax errors +in the input files. `rustfmt` can't format syntatically invalid code. Finally, +exit status `3` is returned if there are some issues which can't be resolved +automatically. For example, if you have a very long comment line `rustfmt` +doesn't split it. Instead it prints a warning and exits with `3`. + +You can run `rustfmt --help` for more information. + ## Running Rustfmt from your editor diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index e2a2a491848..778a96a3c1b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,7 +17,7 @@ extern crate toml; extern crate env_logger; extern crate getopts; -use rustfmt::{run, Input}; +use rustfmt::{run, Input, Summary}; use rustfmt::config::{Config, WriteMode}; use std::{env, error}; @@ -156,18 +156,21 @@ fn make_opts() -> Options { opts } -fn execute(opts: &Options) -> FmtResult<()> { +fn execute(opts: &Options) -> FmtResult { let matches = try!(opts.parse(env::args().skip(1))); match try!(determine_operation(&matches)) { Operation::Help => { print_usage(&opts, ""); + Ok(Summary::new()) } Operation::Version => { print_version(); + Ok(Summary::new()) } Operation::ConfigHelp => { Config::print_docs(); + Ok(Summary::new()) } Operation::Stdin { input, config_path } => { // try to read config from local directory @@ -177,7 +180,7 @@ fn execute(opts: &Options) -> FmtResult<()> { // write_mode is always Plain for Stdin. config.write_mode = WriteMode::Plain; - run(Input::Text(input), &config); + Ok(run(Input::Text(input), &config)) } Operation::Format { files, config_path } => { let mut config = Config::default(); @@ -193,6 +196,8 @@ fn execute(opts: &Options) -> FmtResult<()> { if let Some(path) = path.as_ref() { println!("Using rustfmt config file {}", path.display()); } + + let mut error_summary = Summary::new(); for file in files { // Check the file directory if the config-path could not be read or not provided if path.is_none() { @@ -209,11 +214,11 @@ fn execute(opts: &Options) -> FmtResult<()> { } try!(update_config(&mut config, &matches)); - run(Input::File(file), &config); + error_summary.add(run(Input::File(file), &config)); } + Ok(error_summary) } } - Ok(()) } fn main() { @@ -222,7 +227,18 @@ fn main() { let opts = make_opts(); let exit_code = match execute(&opts) { - Ok(..) => 0, + Ok(summary) => { + if summary.has_operational_errors() { + 1 + } else if summary.has_parsing_errors() { + 2 + } else if summary.has_formatting_errors() { + 3 + } else { + assert!(summary.has_no_errors()); + 0 + } + } Err(e) => { print_usage(&opts, &e.to_string()); 1 diff --git a/src/lib.rs b/src/lib.rs index d0ff4be7241..9d90c58bea5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,9 @@ use std::fmt; use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; use visitor::FmtVisitor; -use config::{Config, WriteMode}; +use config::Config; + +pub use self::summary::Summary; #[macro_use] mod utils; @@ -64,6 +66,7 @@ pub mod rustfmt_diff; mod chains; mod macros; mod patterns; +mod summary; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. @@ -239,9 +242,17 @@ pub struct FormatReport { } impl FormatReport { + fn new() -> FormatReport { + FormatReport { file_error_map: HashMap::new() } + } + pub fn warning_count(&self) -> usize { self.file_error_map.iter().map(|(_, ref errors)| errors.len()).fold(0, |acc, x| acc + x) } + + pub fn has_warnings(&self) -> bool { + self.warning_count() > 0 + } } impl fmt::Display for FormatReport { @@ -289,7 +300,7 @@ fn format_ast(krate: &ast::Crate, // TODO(#20) other stuff for parity with make tidy fn format_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { let mut truncate_todo = Vec::new(); - let mut report = FormatReport { file_error_map: HashMap::new() }; + let mut report = FormatReport::new(); // Iterate over the chars in the file map. for (f, text) in file_map.iter() { @@ -368,17 +379,16 @@ fn format_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { } fn parse_input(input: Input, parse_session: &ParseSess) -> Result { - let krate = match input { + match input { Input::File(file) => parse::parse_crate_from_file(&file, Vec::new(), &parse_session), Input::Text(text) => { parse::parse_crate_from_source_str("stdin".to_owned(), text, Vec::new(), &parse_session) } - }; - - krate + } } -pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { +pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatReport) { + let mut summary = Summary::new(); let codemap = Rc::new(CodeMap::new()); let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, @@ -397,10 +407,15 @@ pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { Ok(krate) => krate, Err(mut diagnostic) => { diagnostic.emit(); - panic!("Unrecoverable parse error"); + summary.add_parsing_error(); + return (summary, FileMap::new(), FormatReport::new()); } }; + if parse_session.span_diagnostic.has_errors() { + summary.add_parsing_error(); + } + // Suppress error output after parsing. let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); @@ -412,7 +427,10 @@ pub fn format_input(input: Input, config: &Config) -> (FileMap, FormatReport) { filemap::append_newlines(&mut file_map); let report = format_lines(&mut file_map, config); - (file_map, report) + if report.has_warnings() { + summary.add_formatting_error(); + } + (summary, file_map, report) } pub enum Input { @@ -420,8 +438,8 @@ pub enum Input { Text(String), } -pub fn run(input: Input, config: &Config) { - let (file_map, report) = format_input(input, config); +pub fn run(input: Input, config: &Config) -> Summary { + let (mut summary, file_map, report) = format_input(input, config); msg!("{}", report); let mut out = stdout(); @@ -429,5 +447,8 @@ pub fn run(input: Input, config: &Config) { if let Err(msg) = write_result { msg!("Error writing files: {}", msg); + summary.add_operational_error(); } + + summary } diff --git a/src/summary.rs b/src/summary.rs new file mode 100644 index 00000000000..5e5c0a579af --- /dev/null +++ b/src/summary.rs @@ -0,0 +1,55 @@ +#[must_use] +pub struct Summary { + // Encountered e.g. an IO error. + has_operational_errors: bool, + + // Failed to reformat code because of parsing errors. + has_parsing_errors: bool, + + // Code is valid, but it is impossible to format it properly. + has_formatting_errors: bool, +} + +impl Summary { + pub fn new() -> Summary { + Summary { + has_operational_errors: false, + has_parsing_errors: false, + has_formatting_errors: false, + } + } + + pub fn has_operational_errors(&self) -> bool { + self.has_operational_errors + } + + pub fn has_parsing_errors(&self) -> bool { + self.has_parsing_errors + } + + pub fn has_formatting_errors(&self) -> bool { + self.has_formatting_errors + } + + pub fn add_operational_error(&mut self) { + self.has_operational_errors = true; + } + + pub fn add_parsing_error(&mut self) { + self.has_parsing_errors = true; + } + + pub fn add_formatting_error(&mut self) { + self.has_formatting_errors = true; + } + + pub fn has_no_errors(&self) -> bool { + !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors) + } + + pub fn add(&mut self, other: Summary) { + self.has_operational_errors |= other.has_operational_errors; + self.has_formatting_errors |= other.has_formatting_errors; + self.has_parsing_errors |= other.has_parsing_errors; + } +} diff --git a/tests/system.rs b/tests/system.rs index 6b13e77a7be..2a6b1a9e19c 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -143,10 +143,20 @@ fn self_tests() { fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); let config = Config::default(); - let (file_map, _report) = format_input(input, &config); + let (error_summary, file_map, _report) = format_input(input, &config); + assert!(error_summary.has_no_errors()); assert_eq!(file_map["stdin"].to_string(), "fn main() {}\n") } +#[test] +fn format_lines_errors_are_reported() { + let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); + let input = Input::Text(format!("fn {}() {{}}", long_identifier)); + let config = Config::default(); + let (error_summary, _file_map, _report) = format_input(input, &config); + assert!(error_summary.has_formatting_errors()); +} + // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: I) -> (Vec, u32, u32) @@ -202,7 +212,8 @@ fn read_config(filename: &str) -> Config { fn format_file>(filename: P, config: &Config) -> (FileMap, FormatReport) { let input = Input::File(filename.into()); - format_input(input, &config) + let (_error_summary, file_map, report) = format_input(input, &config); + return (file_map, report); } pub fn idempotent_check(filename: String) -> Result>> { -- cgit 1.4.1-3-g733a5 From a2426a678d47c4dd7ecb891bf82c57b4201af702 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Fri, 15 Apr 2016 01:11:04 -0400 Subject: config: Rename get_variant_names to doc_hint The `ConfigType` trait is implemented for non-enum types, so the name no longer makes perfect sense. --- src/config.rs | 17 +++++++++-------- src/utils.rs | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 0fecdd49a08..3316984b861 100644 --- a/src/config.rs +++ b/src/config.rs @@ -153,26 +153,27 @@ configuration_option_enum! { WriteMode: Checkstyle, } -// This trait and the following impl blocks are there so that we an use -// UCFS inside the get_docs() function on types for configs. -pub trait ConfigType { - fn get_variant_names() -> String; +/// Trait for types that can be used in `Config`. +pub trait ConfigType: Sized { + /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a + /// pipe-separated list of variants; for other types it returns "". + fn doc_hint() -> String; } impl ConfigType for bool { - fn get_variant_names() -> String { + fn doc_hint() -> String { String::from("") } } impl ConfigType for usize { - fn get_variant_names() -> String { + fn doc_hint() -> String { String::from("") } } impl ConfigType for String { - fn get_variant_names() -> String { + fn doc_hint() -> String { String::from("") } } @@ -278,7 +279,7 @@ macro_rules! create_config { name_out.push(' '); println!("{}{} Default: {:?}", name_out, - <$ty>::get_variant_names(), + <$ty>::doc_hint(), $def); $( println!("{}{}", space_str, $dstring); diff --git a/src/utils.rs b/src/utils.rs index a3c7c036879..f9debdbcec3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -219,7 +219,7 @@ macro_rules! impl_enum_decodable { } impl ::config::ConfigType for $e { - fn get_variant_names() -> String { + fn doc_hint() -> String { let mut variants = Vec::new(); $( variants.push(stringify!($x)); -- cgit 1.4.1-3-g733a5 From 7a758ea20a7bfdc1dbbf8486691549e569bb303e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 15 Apr 2016 20:52:08 +1200 Subject: Fix closures again (#937) * Fix closures again Closes #934 Oh god, the rules for parsing closures are even more messed up than I thought - whether or not there is an inner block or depends not only on if there are braces, but also if there is a return type for the closure (!) and if there are statements in the block. * Fix overflow --- src/expr.rs | 31 +++++++++++++++++-------------- tests/source/closure.rs | 25 +++++++++++++++++++++++++ tests/target/closure.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6cc8c3aa4a9..a88e7ee6d19 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -313,6 +313,9 @@ pub fn rewrite_array<'a, I>(expr_iter: I, // * the body of a closure is represented by an ast::Block, but that does not // imply there are `{}` (unless the block is empty) (see rust issue #27872), // * if there is a return type, then there must be braces, +// * given a closure with braces, whether that is parsed to give an inner block +// or not depends on if there is a return type and if there are statements +// in that block, // * if the first expression in the body ends with a block (i.e., is a // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. @@ -379,11 +382,7 @@ fn rewrite_closure(capture: ast::CaptureBy, prefix.push_str(&ret_str); } - assert!(body.stmts.is_empty(), - "unexpected statements in closure: `{}`", - context.snippet(span)); - - if body.expr.is_none() { + if body.expr.is_none() && body.stmts.is_empty() { return Some(format!("{} {{}}", prefix)); } @@ -392,15 +391,17 @@ fn rewrite_closure(capture: ast::CaptureBy, let budget = try_opt!(width.checked_sub(extra_offset)); // This is where we figure out whether to use braces or not. - let mut had_braces = false; + let mut had_braces = true; let mut inner_block = body; - if let ast::ExprKind::Block(ref inner) = inner_block.expr.as_ref().unwrap().node { - had_braces = true; - inner_block = inner; - }; - assert!(!force_block || !had_braces, - "Closure requires braces, but they weren't present. How did this parse? `{}`", - context.snippet(span)); + + // If there is an inner block and we can ignore it, do so. + if body.stmts.is_empty() { + if let ast::ExprKind::Block(ref inner) = inner_block.expr.as_ref().unwrap().node { + inner_block = inner; + } else if !force_block { + had_braces = false; + } + } let try_single_line = is_simple_block(inner_block, context.codemap) && inner_block.rules == ast::BlockCheckMode::Default; @@ -439,7 +440,9 @@ fn rewrite_closure(capture: ast::CaptureBy, if try_single_line && !prefix.contains('\n') { let inner_expr = inner_block.expr.as_ref().unwrap(); // 4 = braces and spaces. - let mut rewrite = inner_expr.rewrite(context, budget - 4, offset + extra_offset); + let mut rewrite = inner_expr.rewrite(context, + try_opt!(budget.checked_sub(4)), + offset + extra_offset); // Checks if rewrite succeeded and fits on a single line. rewrite = and_one_line(rewrite); diff --git a/tests/source/closure.rs b/tests/source/closure.rs index e125a683dc6..4fd5465cca0 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -57,3 +57,28 @@ fn issue863() { _ => false, } == true; } + +fn issue934() { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) + } + } + } +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 467b07b38ca..5f40610d603 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -82,3 +82,30 @@ fn issue863() { _ => false, } == true; } + +fn issue934() { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) + } + } + } +} -- cgit 1.4.1-3-g733a5 From 847bad603ebba003044ddcfa286b1d3ea4e7f73e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Apr 2016 17:52:21 +0300 Subject: Don't print empty lines to stderr (#940) --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 9d90c58bea5..f63b2caaa94 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -440,7 +440,9 @@ pub enum Input { pub fn run(input: Input, config: &Config) -> Summary { let (mut summary, file_map, report) = format_input(input, config); - msg!("{}", report); + if report.has_warnings() { + msg!("{}", report); + } let mut out = stdout(); let write_result = filemap::write_all_files(&file_map, &mut out, config); -- cgit 1.4.1-3-g733a5 From 45a83d18cc71fa4d7972d38c9302253ddec1c6cb Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 15 Apr 2016 17:56:08 +0200 Subject: Format type ascription --- src/expr.rs | 5 +++-- tests/source/type-ascription.rs | 9 +++++++++ tests/target/type-ascription.rs | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/source/type-ascription.rs create mode 100644 tests/target/type-ascription.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a88e7ee6d19..b5be60cf052 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -177,6 +177,9 @@ impl Rewrite for ast::Expr { ast::ExprKind::Cast(ref expr, ref ty) => { rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) } + ast::ExprKind::Type(ref expr, ref ty) => { + rewrite_pair(&**expr, &**ty, "", ": ", "", context, width, offset) + } ast::ExprKind::Index(ref expr, ref index) => { rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) } @@ -210,8 +213,6 @@ impl Rewrite for ast::Expr { // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) | - // TODO(#848): Handle type ascription - ast::ExprKind::Type(_, _) | // TODO(#867): Handle try shorthand ast::ExprKind::Try(_) => { wrap_str(context.snippet(self.span), diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs new file mode 100644 index 00000000000..3b761f4fc78 --- /dev/null +++ b/tests/source/type-ascription.rs @@ -0,0 +1,9 @@ +fn main() { + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; + + let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + x : u32 - 1u32 / 10f32 : u32 +} diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs new file mode 100644 index 00000000000..22f03713388 --- /dev/null +++ b/tests/target/type-ascription.rs @@ -0,0 +1,14 @@ +fn main() { + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + + let xxxxxxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + let z = funk(yyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzz, + wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + x: u32 - 1u32 / 10f32: u32 +} -- cgit 1.4.1-3-g733a5 From d98e22c971fb328e28fca913cd18c5c5d1250d16 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 15 Apr 2016 18:11:20 +0200 Subject: Check length of break and continue expressions --- src/expr.rs | 4 ++-- tests/source/issue-855.rs | 20 ++++++++++++++++++++ tests/target/issue-855.rs | 23 +++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-855.rs create mode 100644 tests/target/issue-855.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a88e7ee6d19..057a0ef1056 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -137,14 +137,14 @@ impl Rewrite for ast::Expr { Some(ident) => format!(" {}", ident.node), None => String::new(), }; - Some(format!("continue{}", id_str)) + wrap_str(format!("continue{}", id_str), context.config.max_width, width, offset) } ast::ExprKind::Break(ref opt_ident) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), None => String::new(), }; - Some(format!("break{}", id_str)) + wrap_str(format!("break{}", id_str), context.config.max_width, width, offset) } ast::ExprKind::Closure(capture, ref fn_decl, ref body) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) diff --git a/tests/source/issue-855.rs b/tests/source/issue-855.rs new file mode 100644 index 00000000000..8f33fa685ae --- /dev/null +++ b/tests/source/issue-855.rs @@ -0,0 +1,20 @@ +fn main() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} + +fn main2() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | + Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} diff --git a/tests/target/issue-855.rs b/tests/target/issue-855.rs new file mode 100644 index 00000000000..3add3378ff7 --- /dev/null +++ b/tests/target/issue-855.rs @@ -0,0 +1,23 @@ +fn main() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } | + Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} + +fn main2() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } | + Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => { + break 'running + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 27c91ee35b6dd42bb20f1aef4216299ab19bdaff Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sat, 16 Apr 2016 16:34:15 -0400 Subject: rustfmt: Parse options once instead of once per file argument (#944) `update_config()` was parsing the `write-mode` option once for each file argument. This commit parses them once up front into a `CliOptions` struct, which is then applied to the config before calling `run()`. --- src/bin/rustfmt.rs | 55 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 778a96a3c1b..472098f59eb 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -51,6 +51,40 @@ enum Operation { }, } +/// Parsed command line options. +#[derive(Clone, Debug, Default)] +struct CliOptions { + skip_children: bool, + verbose: bool, + write_mode: Option, +} + +impl CliOptions { + fn from_matches(matches: &Matches) -> FmtResult { + let mut options = CliOptions::default(); + options.skip_children = matches.opt_present("skip-children"); + options.verbose = matches.opt_present("verbose"); + + if let Some(ref write_mode) = matches.opt_str("write-mode") { + if let Ok(write_mode) = WriteMode::from_str(write_mode) { + options.write_mode = Some(write_mode); + } else { + return Err(FmtError::from(format!("Invalid write-mode: {}", write_mode))); + } + } + + Ok(options) + } + + fn apply_to(&self, config: &mut Config) { + config.skip_children = self.skip_children; + config.verbose = self.verbose; + if let Some(write_mode) = self.write_mode { + config.write_mode = write_mode; + } + } +} + /// Try to find a project file in the given directory and its parents. Returns the path of a the /// nearest project file if one exists, or `None` if no project file was found. fn lookup_project_file(dir: &Path) -> FmtResult> { @@ -115,24 +149,6 @@ fn match_cli_path_or_file(config_path: Option, resolve_config(input_file) } -fn update_config(config: &mut Config, matches: &Matches) -> FmtResult<()> { - config.verbose = matches.opt_present("verbose"); - config.skip_children = matches.opt_present("skip-children"); - - let write_mode = matches.opt_str("write-mode"); - match matches.opt_str("write-mode").map(|wm| WriteMode::from_str(&wm)) { - None => Ok(()), - Some(Ok(write_mode)) => { - config.write_mode = write_mode; - Ok(()) - } - Some(Err(_)) => { - Err(FmtError::from(format!("Invalid write-mode: {}", - write_mode.expect("cannot happen")))) - } - } -} - fn make_opts() -> Options { let mut opts = Options::new(); opts.optflag("h", "help", "show this message"); @@ -183,6 +199,7 @@ fn execute(opts: &Options) -> FmtResult { Ok(run(Input::Text(input), &config)) } Operation::Format { files, config_path } => { + let options = try!(CliOptions::from_matches(&matches)); let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -213,7 +230,7 @@ fn execute(opts: &Options) -> FmtResult { config = config_tmp; } - try!(update_config(&mut config, &matches)); + options.apply_to(&mut config); error_summary.add(run(Input::File(file), &config)); } Ok(error_summary) -- cgit 1.4.1-3-g733a5 From 63f0fc964130f7710b8c2e5f045cabff761025da Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sat, 16 Apr 2016 22:42:15 +0200 Subject: Fix off-by-one error in pattern formatting --- src/patterns.rs | 5 +++-- tests/source/issue-913.rs | 20 ++++++++++++++++++++ tests/target/issue-913.rs | 20 ++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-913.rs create mode 100644 tests/target/issue-913.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 4285b592fbc..3cec98bb93a 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -76,8 +76,9 @@ impl Rewrite for Pat { if pat_vec.is_empty() { Some(path_str) } else { - // 1 = ( - let width = try_opt!(width.checked_sub(path_str.len() + 1)); + // 2 = "()".len() + let width = try_opt!(width.checked_sub(path_str.len() + 2)); + // 1 = "(".len() let offset = offset + path_str.len() + 1; let items = itemize_list(context.codemap, pat_vec.iter(), diff --git a/tests/source/issue-913.rs b/tests/source/issue-913.rs new file mode 100644 index 00000000000..f58a8b0663b --- /dev/null +++ b/tests/source/issue-913.rs @@ -0,0 +1,20 @@ +mod client { + impl Client { + fn test(self) -> Result<()> { + let next_state = match self.state { + State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { + let x = reformat . meeee() ; + } + }; + + let next_state = match self.state { + State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { + // The pattern cannot be formatted in a way that the match stays + // within the column limit. The rewrite should therefore be + // skipped. + let x = dont . reformat . meeee(); + } + }; + } + } +} diff --git a/tests/target/issue-913.rs b/tests/target/issue-913.rs new file mode 100644 index 00000000000..c7aee5fe3ab --- /dev/null +++ b/tests/target/issue-913.rs @@ -0,0 +1,20 @@ +mod client { + impl Client { + fn test(self) -> Result<()> { + let next_state = match self.state { + State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { + let x = reformat.meeee(); + } + }; + + let next_state = match self.state { + State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { + // The pattern cannot be formatted in a way that the match stays + // within the column limit. The rewrite should therefore be + // skipped. + let x = dont . reformat . meeee(); + } + }; + } + } +} -- cgit 1.4.1-3-g733a5 From 5bd6036218cbb0521b6c752ec7f8d757514ab900 Mon Sep 17 00:00:00 2001 From: Thia Wyrod Date: Sat, 16 Apr 2016 17:33:17 -0600 Subject: Added option to configure if/else brace style --- src/config.rs | 11 ++++ src/expr.rs | 35 +++++++++--- .../source/else-if-brace-style-always-next-line.rs | 54 +++++++++++++++++++ .../source/else-if-brace-style-always-same-line.rs | 54 +++++++++++++++++++ .../else-if-brace-style-closing-next-line.rs | 54 +++++++++++++++++++ .../target/else-if-brace-style-always-next-line.rs | 62 ++++++++++++++++++++++ .../target/else-if-brace-style-always-same-line.rs | 51 ++++++++++++++++++ .../else-if-brace-style-closing-next-line.rs | 56 +++++++++++++++++++ 8 files changed, 371 insertions(+), 6 deletions(-) create mode 100644 tests/source/else-if-brace-style-always-next-line.rs create mode 100644 tests/source/else-if-brace-style-always-same-line.rs create mode 100644 tests/source/else-if-brace-style-closing-next-line.rs create mode 100644 tests/target/else-if-brace-style-always-next-line.rs create mode 100644 tests/target/else-if-brace-style-always-same-line.rs create mode 100644 tests/target/else-if-brace-style-closing-next-line.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 3316984b861..176d40026d2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,15 @@ configuration_option_enum! { BraceStyle: SameLineWhere, } +configuration_option_enum! { ElseIfBraceStyle: + // K&R style, Rust community default + AlwaysSameLine, + // Stroustrup style + ClosingNextLine, + // Allman style + AlwaysNextLine, +} + // How to indent a function's return type. configuration_option_enum! { ReturnIndent: // Aligned with the arguments @@ -315,6 +324,8 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; + else_if_brace_style: ElseIfBraceStyle, ElseIfBraceStyle::AlwaysSameLine, + "Brace style for if, else if, and else constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; diff --git a/src/expr.rs b/src/expr.rs index 90ccb87e2d4..7b080760f38 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,7 +23,7 @@ use string::{StringFormat, rewrite_string}; use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; use visitor::FmtVisitor; -use config::{Config, StructLitStyle, MultilineStyle}; +use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -701,12 +701,16 @@ fn rewrite_if_else(context: &RewriteContext, allow_single_line: bool) -> Option { // 3 = "if ", 2 = " {" + let pat_penalty = match context.config.else_if_brace_style { + ElseIfBraceStyle::AlwaysNextLine => 3, + _ => 3 + 2, + }; let pat_expr_string = try_opt!(rewrite_pat_expr(context, pat, cond, "let ", " =", - try_opt!(width.checked_sub(3 + 2)), + try_opt!(width.checked_sub(pat_penalty)), offset + 3)); // Try to format if-else on single line. @@ -731,13 +735,19 @@ fn rewrite_if_else(context: &RewriteContext, offset, width); + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let after_sep = match context.config.else_if_brace_style { + ElseIfBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + _ => " ", + }; let mut result = format!("if{}{}{}{}", between_if_cond_comment.as_ref().map_or(" ", |str| &**str), pat_expr_string, - after_cond_comment.as_ref().map_or(" ", |str| &**str), + after_cond_comment.as_ref().map_or(after_sep, |str| &**str), if_block_string); if let Some(else_block) = else_block_opt { + let mut last_in_chain = false; let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it // from being formatted on a single line. @@ -763,7 +773,10 @@ fn rewrite_if_else(context: &RewriteContext, offset, false) } - _ => else_block.rewrite(context, width, offset), + _ => { + last_in_chain = true; + else_block.rewrite(context, width, offset) + } }; let between_if_else_block = mk_sp(if_block.span.hi, @@ -781,10 +794,20 @@ fn rewrite_if_else(context: &RewriteContext, else_block.span.lo); let after_else_comment = extract_comment(after_else, &context, offset, width); + let between_sep = match context.config.else_if_brace_style { + ElseIfBraceStyle::AlwaysNextLine | + ElseIfBraceStyle::ClosingNextLine => alt_block_sep.as_str(), + ElseIfBraceStyle::AlwaysSameLine => " ", + }; + let after_sep = match context.config.else_if_brace_style { + ElseIfBraceStyle::AlwaysNextLine if last_in_chain => alt_block_sep.as_str(), + _ => " ", + }; try_opt!(write!(&mut result, "{}else{}", - between_if_else_block_comment.as_ref().map_or(" ", |str| &**str), - after_else_comment.as_ref().map_or(" ", |str| &**str)) + between_if_else_block_comment.as_ref() + .map_or(between_sep, |str| &**str), + after_else_comment.as_ref().map_or(after_sep, |str| &**str)) .ok()); result.push_str(&&try_opt!(rewrite)); } diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/tests/source/else-if-brace-style-always-next-line.rs new file mode 100644 index 00000000000..18a8ace1f14 --- /dev/null +++ b/tests/source/else-if-brace-style-always-next-line.rs @@ -0,0 +1,54 @@ +// rustfmt-else_if_brace_style: AlwaysNextLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/tests/source/else-if-brace-style-always-same-line.rs new file mode 100644 index 00000000000..090b1e9a9db --- /dev/null +++ b/tests/source/else-if-brace-style-always-same-line.rs @@ -0,0 +1,54 @@ +// rustfmt-else_if_brace_style: AlwaysSameLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/tests/source/else-if-brace-style-closing-next-line.rs new file mode 100644 index 00000000000..755b95bd541 --- /dev/null +++ b/tests/source/else-if-brace-style-closing-next-line.rs @@ -0,0 +1,54 @@ +// rustfmt-else_if_brace_style: ClosingNextLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs new file mode 100644 index 00000000000..3fbd8b7af25 --- /dev/null +++ b/tests/target/else-if-brace-style-always-next-line.rs @@ -0,0 +1,62 @@ +// rustfmt-else_if_brace_style: AlwaysNextLine + +fn main() { + if false + { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + + let a = if 0 > 1 + { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } + else if false + { + (); + (); + } + else + { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } + else if false + // else-if-chain else-if comment + { + (); + (); + } + else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs new file mode 100644 index 00000000000..393944133f7 --- /dev/null +++ b/tests/target/else-if-brace-style-always-same-line.rs @@ -0,0 +1,51 @@ +// rustfmt-else_if_brace_style: AlwaysSameLine + +fn main() { + if false { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + + let a = if 0 > 1 { + unreachable!() + } else { + 0x0 + }; + + + if true { + (); + } else if false { + (); + (); + } else { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } else if false + // else-if-chain else-if comment + { + (); + (); + } else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs new file mode 100644 index 00000000000..e50f29d2921 --- /dev/null +++ b/tests/target/else-if-brace-style-closing-next-line.rs @@ -0,0 +1,56 @@ +// rustfmt-else_if_brace_style: ClosingNextLine + +fn main() { + if false { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + + let a = if 0 > 1 { + unreachable!() + } + else { + 0x0 + }; + + + if true { + (); + } + else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } + else if false + // else-if-chain else-if comment + { + (); + (); + } + else + // else-if-chain else comment + { + (); + (); + (); + } +} -- cgit 1.4.1-3-g733a5 From d773cc53276cf49236615834cd4902710f0cb58d Mon Sep 17 00:00:00 2001 From: Thia Wyrod Date: Sun, 17 Apr 2016 11:01:16 -0600 Subject: Added loop/match brace style control option This adds Allman style loop/match braces as an alternative to the current default style. --- src/config.rs | 9 ++++ src/expr.rs | 33 +++++++++++--- .../source/control-brace-style-always-next-line.rs | 44 ++++++++++++++++++ .../source/control-brace-style-always-same-line.rs | 44 ++++++++++++++++++ .../target/control-brace-style-always-next-line.rs | 52 ++++++++++++++++++++++ .../target/control-brace-style-always-same-line.rs | 43 ++++++++++++++++++ 6 files changed, 219 insertions(+), 6 deletions(-) create mode 100644 tests/source/control-brace-style-always-next-line.rs create mode 100644 tests/source/control-brace-style-always-same-line.rs create mode 100644 tests/target/control-brace-style-always-next-line.rs create mode 100644 tests/target/control-brace-style-always-same-line.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 176d40026d2..82715c2164a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,13 @@ configuration_option_enum! { BraceStyle: SameLineWhere, } +configuration_option_enum! { ControlBraceStyle: + // K&R/Stroustrup style, Rust community default + AlwaysSameLine, + // Allman style + AlwaysNextLine, +} + configuration_option_enum! { ElseIfBraceStyle: // K&R style, Rust community default AlwaysSameLine, @@ -326,6 +333,8 @@ create_config! { item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; else_if_brace_style: ElseIfBraceStyle, ElseIfBraceStyle::AlwaysSameLine, "Brace style for if, else if, and else constructs"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, + "Brace style for match, loop, for, and while constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; diff --git a/src/expr.rs b/src/expr.rs index 7b080760f38..248cc7e090a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,7 +23,7 @@ use string::{StringFormat, rewrite_string}; use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; use visitor::FmtVisitor; -use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle}; +use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -648,14 +648,20 @@ impl<'a> Rewrite for Loop<'a> { None => String::new(), }; + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + ControlBraceStyle::AlwaysSameLine => " ", + }; // FIXME: this drops any comment between "loop" and the block. self.block .rewrite(context, width, offset) .map(|result| { - format!("{}{}{} {}", + format!("{}{}{}{}{}", label_string, self.keyword, pat_expr_string, + block_sep, result) }) } @@ -940,7 +946,12 @@ fn rewrite_match(context: &RewriteContext, // `match `cond` {` let cond_budget = try_opt!(width.checked_sub(8)); let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6)); - let mut result = format!("match {} {{", cond_str); + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysSameLine => " ", + ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + }; + let mut result = format!("match {}{}{{", cond_str, block_sep); let nested_context = context.nested_context(); let arm_indent = nested_context.block_indent; @@ -1099,6 +1110,7 @@ impl Rewrite for ast::Arm { }; let comma = arm_comma(&context.config, self, body); + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() @@ -1112,12 +1124,17 @@ impl Rewrite for ast::Arm { false }; + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), + _ => " ", + }; match rewrite { Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || is_block => { - return Some(format!("{}{} => {}{}", + return Some(format!("{}{} =>{}{}{}", attr_str.trim_left(), pats_str, + block_sep, body_str, comma)); } @@ -1145,10 +1162,14 @@ impl Rewrite for ast::Arm { ("", "") }; - Some(format!("{}{} =>{}\n{}{}\n{}{}", + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine => alt_block_sep, + ControlBraceStyle::AlwaysSameLine => String::from(body_prefix) + "\n", + }; + Some(format!("{}{} =>{}{}{}\n{}{}", attr_str.trim_left(), pats_str, - body_prefix, + block_sep, indent_str, next_line_body, offset.to_string(context.config), diff --git a/tests/source/control-brace-style-always-next-line.rs b/tests/source/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..9a2ec04e300 --- /dev/null +++ b/tests/source/control-brace-style-always-next-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop { + (); + (); + } + + + 'loop_label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/tests/source/control-brace-style-always-same-line.rs b/tests/source/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..52b0c8fdc46 --- /dev/null +++ b/tests/source/control-brace-style-always-same-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + + 'loop_label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/tests/target/control-brace-style-always-next-line.rs b/tests/target/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..534dfb89969 --- /dev/null +++ b/tests/target/control-brace-style-always-next-line.rs @@ -0,0 +1,52 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop + { + (); + (); + } + + + 'loop_label: loop + { + (); + } + + + cond = true; + while cond + { + (); + } + + + 'while_label: while cond + { + // while comment + (); + } + + + for obj in iter + { + for sub_obj in obj + { + 'nested_while_label: while cond + { + (); + } + } + } + + match some_var + { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => + { + do_stuff(); + val2 + } + }; +} diff --git a/tests/target/control-brace-style-always-same-line.rs b/tests/target/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..60a07e46986 --- /dev/null +++ b/tests/target/control-brace-style-always-same-line.rs @@ -0,0 +1,43 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + + 'loop_label: loop { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { + // while comment + (); + } + + + for obj in iter { + for sub_obj in obj { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + } + }; +} -- cgit 1.4.1-3-g733a5 From f364a7ec43a0cd50c7fa1f663f1ec8c30c5f3131 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 18 Apr 2016 18:39:40 +0200 Subject: Add option to force explicit extern ABI's --- src/config.rs | 1 + src/items.rs | 5 +++-- src/types.rs | 2 +- src/utils.rs | 9 ++++++--- tests/source/extern_not_explicit.rs | 14 ++++++++++++++ tests/target/extern_not_explicit.rs | 15 +++++++++++++++ 6 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 tests/source/extern_not_explicit.rs create mode 100644 tests/target/extern_not_explicit.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 82715c2164a..5632e9a925c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -328,6 +328,7 @@ create_config! { "Maximum width of the args of a function call before falling back to vertical formatting"; struct_lit_width: usize, 16, "Maximum width in the body of a struct lit before falling back to vertical formatting"; + force_explicit_abi: bool, true, "Always print the abi for extern items"; newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; diff --git a/src/items.rs b/src/items.rs index cee1fc4f13e..2566d9a436b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -80,7 +80,8 @@ impl Rewrite for ast::Local { impl<'a> FmtVisitor<'a> { pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { - self.buffer.push_str(&::utils::format_abi(fm.abi)); + let abi_str = ::utils::format_abi(fm.abi, self.config.force_explicit_abi); + self.buffer.push_str(&abi_str); let snippet = self.snippet(span); let brace_pos = snippet.find_uncommented("{").unwrap(); @@ -1265,7 +1266,7 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(::utils::format_unsafety(unsafety)); if abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi(abi)); + result.push_str(&::utils::format_abi(abi, context.config.force_explicit_abi)); } // fn foo diff --git a/src/types.rs b/src/types.rs index 09cf7e12126..22b518d2463 100644 --- a/src/types.rs +++ b/src/types.rs @@ -608,7 +608,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str(&::utils::format_unsafety(bare_fn.unsafety)); if bare_fn.abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi(bare_fn.abi)); + result.push_str(&::utils::format_abi(bare_fn.abi, context.config.force_explicit_abi)); } result.push_str("fn"); diff --git a/src/utils.rs b/src/utils.rs index f9debdbcec3..667c9cd7efd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -91,9 +91,12 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } #[inline] -// FIXME(#451): include "C"? -pub fn format_abi(abi: abi::Abi) -> String { - format!("extern {} ", abi) +pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String { + if abi == abi::Abi::C && !explicit_abi { + "extern ".into() + } else { + format!("extern {} ", abi) + } } // The width of the first line in s. diff --git a/tests/source/extern_not_explicit.rs b/tests/source/extern_not_explicit.rs new file mode 100644 index 00000000000..9d6c4c2a1cd --- /dev/null +++ b/tests/source/extern_not_explicit.rs @@ -0,0 +1,14 @@ +// rustfmt-force_explicit_abi: false + + extern "C" { + fn some_fn() -> (); + } + + extern "C" fn sup() { + + } + +type funky_func = extern "C" fn (unsafe extern "rust-call" fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8); diff --git a/tests/target/extern_not_explicit.rs b/tests/target/extern_not_explicit.rs new file mode 100644 index 00000000000..b0f64c4f1cf --- /dev/null +++ b/tests/target/extern_not_explicit.rs @@ -0,0 +1,15 @@ +// rustfmt-force_explicit_abi: false + +extern { + fn some_fn() -> (); +} + +extern fn sup() {} + +type funky_func = extern fn(unsafe extern "rust-call" fn(*const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal) + -> u8); -- cgit 1.4.1-3-g733a5 From b0755581ca49d3c583d68956bad445ad382c7af9 Mon Sep 17 00:00:00 2001 From: mrBliss Date: Tue, 19 Apr 2016 20:19:14 +0200 Subject: Format visibility of associated consts (#953) Fixes #951. --- src/visitor.rs | 2 +- tests/source/static.rs | 4 ++++ tests/target/static.rs | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index cc97c2289f0..d52a167cb5e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -362,7 +362,7 @@ impl<'a> FmtVisitor<'a> { } ast::ImplItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static("const", - ast::Visibility::Inherited, + ii.vis, ii.ident, ty, ast::Mutability::Immutable, diff --git a/tests/source/static.rs b/tests/source/static.rs index 6315b489046..a571b5f11f6 100644 --- a/tests/source/static.rs +++ b/tests/source/static.rs @@ -12,3 +12,7 @@ static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa pub static count : u8 = 10 ; pub const test: &Type = &val; + +impl Color { + pub const WHITE: u32 = 10; +} diff --git a/tests/target/static.rs b/tests/target/static.rs index ffaeb0890d3..f3dbdad3e76 100644 --- a/tests/target/static.rs +++ b/tests/target/static.rs @@ -15,3 +15,7 @@ static mut name: SomeType = pub static count: u8 = 10; pub const test: &Type = &val; + +impl Color { + pub const WHITE: u32 = 10; +} -- cgit 1.4.1-3-g733a5 From 4c3228530f5b3fb62554b9db6755e2651908e589 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Apr 2016 11:29:01 +1200 Subject: block indent large closures somewhat rough around the edges --- src/config.rs | 8 ++++++++ src/expr.rs | 14 ++++++++++++-- src/rewrite.rs | 1 + 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 5632e9a925c..846b8a39135 100644 --- a/src/config.rs +++ b/src/config.rs @@ -188,6 +188,12 @@ impl ConfigType for usize { } } +impl ConfigType for isize { + fn doc_hint() -> String { + String::from("") + } +} + impl ConfigType for String { fn doc_hint() -> String { String::from("") @@ -384,6 +390,8 @@ create_config! { match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; + closure_block_indent_threshold: isize, 4, "How many lines a closure must have before it is \ + block indented. -1 means never use block indent."; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; } diff --git a/src/expr.rs b/src/expr.rs index 248cc7e090a..2a6144481ba 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -455,9 +455,19 @@ fn rewrite_closure(capture: ast::CaptureBy, // We couldn't format the closure body as a single line expression; fall // back to block formatting. - let body_rewrite = inner_block.rewrite(&context, budget, Indent::empty()); + let body_rewrite = try_opt!(inner_block.rewrite(&context, budget, Indent::empty())); - Some(format!("{} {}", prefix, try_opt!(body_rewrite))) + let block_threshold = context.config.closure_block_indent_threshold; + if block_threshold < 0 || body_rewrite.matches('\n').count() <= block_threshold as usize { + return Some(format!("{} {}", prefix, body_rewrite)); + } + + // The body of the closure is big enough to be block indented, that means we + // must re-format. + let mut context = context.clone(); + context.block_indent.alignment = 0; + let body_rewrite = try_opt!(inner_block.rewrite(&context, budget, Indent::empty())); + Some(format!("{} {}", prefix, body_rewrite)) } fn and_one_line(x: Option) -> Option { diff --git a/src/rewrite.rs b/src/rewrite.rs index 5ca8d2e8241..247b1df1c3f 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -27,6 +27,7 @@ pub trait Rewrite { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option; } +#[derive(Clone)] pub struct RewriteContext<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, -- cgit 1.4.1-3-g733a5 From 3d46532e72a693b0ca9100b7ba9f721e4daaff31 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Apr 2016 13:36:27 +1200 Subject: refactor and document the chain reformatting code --- src/chains.rs | 278 ++++++++++++++++++++++++++++++++++++++++++---------------- src/config.rs | 4 +- 2 files changed, 202 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c535287df24..5c097c83cb1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -8,16 +8,88 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Formatting of chained expressions, i.e. expressions which are chained by -// dots: struct and enum field access and method calls. -// -// Instead of walking these subexpressions one-by-one, as is our usual strategy -// for expression formatting, we collect maximal sequences of these expressions -// and handle them simultaneously. -// -// Whenever possible, the entire chain is put on a single line. If that fails, -// we put each subexpression on a separate, much like the (default) function -// argument function argument strategy. +/// Formatting of chained expressions, i.e. expressions which are chained by +/// dots: struct and enum field access and method calls. +/// +/// Instead of walking these subexpressions one-by-one, as is our usual strategy +/// for expression formatting, we collect maximal sequences of these expressions +/// and handle them simultaneously. +/// +/// Whenever possible, the entire chain is put on a single line. If that fails, +/// we put each subexpression on a separate, much like the (default) function +/// argument function argument strategy. +/// +/// Depends on config options: `chain_base_indent` is the indent to use for +/// blocks in the parent/root/base of the chain. +/// E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the +/// following values of `chain_base_indent`: +/// Visual: +/// ``` +/// let foo = { +/// aaaa; +/// bbb; +/// ccc +/// } +/// .bar +/// .baz(); +/// ``` +/// Inherit: +/// ``` +/// let foo = { +/// aaaa; +/// bbb; +/// ccc +/// } +/// .bar +/// .baz(); +/// ``` +/// Tabbed: +/// ``` +/// let foo = { +/// aaaa; +/// bbb; +/// ccc +/// } +/// .bar +/// .baz(); +/// ``` +/// +/// `chain_indent` dictates how the rest of the chain is aligned. This only seems +/// to have an effect if the first non-root part of the chain is put on a +/// newline, otherwise we align the dots: +/// ``` +/// foo.bar +/// .baz() +/// ``` +/// If the first item in the chain is a block expression, we align the dots with +/// the braces. +/// +/// Otherwise: +/// Visual: +/// ``` +/// let a = foo(aaa, bbb) +/// .bar +/// .baz() +/// ``` +/// Visual seems to be a tab indented from the indent of the whole expression. +/// Inherit: +/// ``` +/// let a = foo(aaa, bbb) +/// .bar +/// .baz() +/// ``` +/// Tabbed: +/// ``` +/// let a = foo(aaa, bbb) +/// .bar +/// .baz() +/// ``` +/// `chains_overflow_last` applies only to chains where the last item is a +/// method call. Usually, any line break in a chain sub-expression causes the +/// whole chain to be split with newlines at each `.`. With `chains_overflow_last` +/// true, then we allow the last method call to spill over multiple lines without +/// forcing the rest of the chain to be split. + use Indent; use rewrite::{Rewrite, RewriteContext}; @@ -28,49 +100,43 @@ use config::BlockIndentStyle; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; -pub fn rewrite_chain(mut expr: &ast::Expr, + +pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, width: usize, offset: Indent) -> Option { let total_span = expr.span; - let mut subexpr_list = vec![expr]; + let (parent, subexpr_list) = make_subexpr_list(expr); - while let Some(subexpr) = pop_expr_chain(expr) { - subexpr_list.push(subexpr); - expr = subexpr; - } - - let parent_block_indent = match context.config.chain_base_indent { - BlockIndentStyle::Visual => offset, - BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), - }; + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. + let parent_block_indent = chain_base_indent(context, offset); let parent_context = &RewriteContext { block_indent: parent_block_indent, ..*context }; - let parent = subexpr_list.pop().unwrap(); - let parent_rewrite = try_opt!(expr.rewrite(parent_context, width, offset)); + let parent_rewrite = try_opt!(parent.rewrite(parent_context, width, offset)); + + // Decide how to layout the rest of the chain. `extend` is true if we can + // put the first non-parent item on the same line as the parent. let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || parent_rewrite.len() <= context.config.tab_spaces { + // Try and put the whole chain on one line. (offset + Indent::new(0, parent_rewrite.len()), true) } else if is_block_expr(parent, &parent_rewrite) { + // The parent is a block, so align the rest of the chain with the closing + // brace. (parent_block_indent, false) } else { - match context.config.chain_indent { - BlockIndentStyle::Inherit => (context.block_indent, false), - BlockIndentStyle::Tabbed => (context.block_indent.block_indent(context.config), false), - BlockIndentStyle::Visual => (offset + Indent::new(context.config.tab_spaces, 0), false), - } + (chain_indent(context, offset), false) }; let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); let mut rewrites = try_opt!(subexpr_list.iter() .rev() .map(|e| { - rewrite_chain_expr(e, - total_span, - context, - max_width, - indent) + rewrite_chain_subexpr(e, + total_span, + context, + max_width, + indent) }) .collect::>>()); @@ -80,6 +146,7 @@ pub fn rewrite_chain(mut expr: &ast::Expr, .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let total_width = almost_total + first_line_width(rewrites.last().unwrap()); + let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. @@ -92,49 +159,40 @@ pub fn rewrite_chain(mut expr: &ast::Expr, false }; - let fits_single_line = !veto_single_line && - match subexpr_list[0].node { - ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) - if context.config.chains_overflow_last => { - let len = rewrites.len(); - let (init, last) = rewrites.split_at_mut(len - 1); - let last = &mut last[0]; - - if init.iter().all(|s| !s.contains('\n')) && total_width <= width { - let last_rewrite = width.checked_sub(almost_total) - .and_then(|inner_width| { - rewrite_method_call(method_name.node, - types, - expressions, - total_span, - context, - inner_width, - offset + almost_total) - }); - match last_rewrite { - Some(mut string) => { - ::std::mem::swap(&mut string, last); - true - } - None => false, + let mut fits_single_line = !veto_single_line && total_width <= width; + if fits_single_line { + let len = rewrites.len(); + let (init, last) = rewrites.split_at_mut(len - 1); + fits_single_line = init.iter().all(|s| !s.contains('\n')); + + if fits_single_line { + fits_single_line = match expr.node { + ref e @ ast::ExprKind::MethodCall(..) if context.config.chains_overflow_last => { + rewrite_method_call_with_overflow(e, + &mut last[0], + almost_total, + width, + total_span, + context, + offset) } - } else { - false + _ => !last[0].contains('\n'), } } - _ => total_width <= width && rewrites.iter().all(|s| !s.contains('\n')), - }; + } let connector = if fits_single_line && !parent_rewrite.contains('\n') { + // Yay, we can put everything on one line. String::new() } else { + // Use new lines. format!("\n{}", indent.to_string(context.config)) }; let first_connector = if extend { "" } else { - &connector[..] + &connector }; wrap_str(format!("{}{}{}", @@ -146,8 +204,40 @@ pub fn rewrite_chain(mut expr: &ast::Expr, offset) } +fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, + last: &mut String, + almost_total: usize, + width: usize, + total_span: Span, + context: &RewriteContext, + offset: Indent) + -> bool { + if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { + let budget = match width.checked_sub(almost_total) { + Some(b) => b, + None => return false, + }; + let mut last_rewrite = rewrite_method_call(method_name.node, + types, + expressions, + total_span, + context, + budget, + offset + almost_total); + + if let Some(ref mut s) = last_rewrite { + ::std::mem::swap(s, last); + true + } else { + false + } + } else { + unreachable!(); + } +} + // States whether an expression's last line exclusively consists of closing -// parens, braces and brackets in its idiomatic formatting. +// parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { match expr.node { ast::ExprKind::Struct(..) | @@ -167,21 +257,53 @@ fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { } } -fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { - match expr.node { - ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]), - ast::ExprKind::TupField(ref subexpr, _) | - ast::ExprKind::Field(ref subexpr, _) => Some(subexpr), - _ => None, +// Returns the root of the chain and a Vec of the prefixes of the rest of the chain. +// E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) +fn make_subexpr_list(mut expr: &ast::Expr) -> (&ast::Expr, Vec<&ast::Expr>) { + fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { + match expr.node { + ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]), + ast::ExprKind::TupField(ref subexpr, _) | + ast::ExprKind::Field(ref subexpr, _) => Some(subexpr), + _ => None, + } + } + + let mut subexpr_list = vec![expr]; + + while let Some(subexpr) = pop_expr_chain(expr) { + subexpr_list.push(subexpr); + expr = subexpr; + } + + let parent = subexpr_list.pop().unwrap(); + (parent, subexpr_list) +} + +fn chain_base_indent(context: &RewriteContext, offset: Indent) -> Indent { + match context.config.chain_base_indent { + BlockIndentStyle::Visual => offset, + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + } +} + +fn chain_indent(context: &RewriteContext, offset: Indent) -> Indent { + match context.config.chain_indent { + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + BlockIndentStyle::Visual => offset + Indent::new(context.config.tab_spaces, 0), } } -fn rewrite_chain_expr(expr: &ast::Expr, - span: Span, - context: &RewriteContext, - width: usize, - offset: Indent) - -> Option { +// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite +// `.c`. +fn rewrite_chain_subexpr(expr: &ast::Expr, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { match expr.node { ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => { let inner = &RewriteContext { block_indent: offset, ..*context }; @@ -213,7 +335,7 @@ fn rewrite_chain_expr(expr: &ast::Expr, } } -// Determines we can continue formatting a given expression on the same line. +// Determines if we can continue formatting a given expression on the same line. fn is_continuable(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Path(..) => true, diff --git a/src/config.rs b/src/config.rs index 846b8a39135..71edfe955bd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -377,11 +377,11 @@ create_config! { "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_base_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on chain base"; chain_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of chain"; + chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; format_strings: bool, true, "Format string literals where necessary"; force_format_strings: bool, false, "Always format string literals"; - chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; @@ -390,7 +390,7 @@ create_config! { match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; - closure_block_indent_threshold: isize, 4, "How many lines a closure must have before it is \ + closure_block_indent_threshold: isize, -1, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; -- cgit 1.4.1-3-g733a5 From 95ff52f06fce389f2d5634c8b15916419cd876a8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Apr 2016 15:35:16 +1200 Subject: Tabbed/Inherit indent for chains works even without a newline after first item. --- src/chains.rs | 84 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5c097c83cb1..5d2ce8fedf7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -118,14 +118,16 @@ pub fn rewrite_chain(expr: &ast::Expr, // put the first non-parent item on the same line as the parent. let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || parent_rewrite.len() <= context.config.tab_spaces { - // Try and put the whole chain on one line. - (offset + Indent::new(0, parent_rewrite.len()), true) + // Try and put at least the first two items on the same line. + (chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), true) } else if is_block_expr(parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. (parent_block_indent, false) + } else if parent_rewrite.contains('\n') { + (chain_indent(context, parent_block_indent.block_indent(context.config)), false) } else { - (chain_indent(context, offset), false) + (hacked_chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), false) }; let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); @@ -204,38 +206,6 @@ pub fn rewrite_chain(expr: &ast::Expr, offset) } -fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, - last: &mut String, - almost_total: usize, - width: usize, - total_span: Span, - context: &RewriteContext, - offset: Indent) - -> bool { - if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { - let budget = match width.checked_sub(almost_total) { - Some(b) => b, - None => return false, - }; - let mut last_rewrite = rewrite_method_call(method_name.node, - types, - expressions, - total_span, - context, - budget, - offset + almost_total); - - if let Some(ref mut s) = last_rewrite { - ::std::mem::swap(s, last); - true - } else { - false - } - } else { - unreachable!(); - } -} - // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { @@ -290,9 +260,51 @@ fn chain_base_indent(context: &RewriteContext, offset: Indent) -> Indent { fn chain_indent(context: &RewriteContext, offset: Indent) -> Indent { match context.config.chain_indent { + BlockIndentStyle::Visual => offset, BlockIndentStyle::Inherit => context.block_indent, BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), - BlockIndentStyle::Visual => offset + Indent::new(context.config.tab_spaces, 0), + } +} + +// Temporary hack - ignores visual indenting because this function should be +// called where it is not possible to use visual indentation. +fn hacked_chain_indent(context: &RewriteContext, _offset: Indent) -> Indent { + match context.config.chain_indent { + BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Visual | + BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + } +} + +fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, + last: &mut String, + almost_total: usize, + width: usize, + total_span: Span, + context: &RewriteContext, + offset: Indent) + -> bool { + if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { + let budget = match width.checked_sub(almost_total) { + Some(b) => b, + None => return false, + }; + let mut last_rewrite = rewrite_method_call(method_name.node, + types, + expressions, + total_span, + context, + budget, + offset + almost_total); + + if let Some(ref mut s) = last_rewrite { + ::std::mem::swap(s, last); + true + } else { + false + } + } else { + unreachable!(); } } -- cgit 1.4.1-3-g733a5 From 9761cf71d8384db2a75c7595b082dd7764575851 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Apr 2016 18:53:39 +1200 Subject: Tests --- src/bin/cargo-fmt.rs | 8 ++++---- src/bin/rustfmt.rs | 9 +++------ src/chains.rs | 10 +++++----- src/items.rs | 2 +- src/missed_spans.rs | 8 ++++---- tests/system.rs | 12 ++++++------ tests/target/chains-indent-visual.rs | 10 +++++----- tests/target/hard-tabs.rs | 6 +++--- 8 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index c033851f98a..575e25ed965 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -201,9 +201,9 @@ fn format_files(files: &Vec, println!(""); } let mut command = try!(Command::new("rustfmt") - .stdout(stdout) - .args(files) - .args(fmt_args) - .spawn()); + .stdout(stdout) + .args(files) + .args(fmt_args) + .spawn()); command.wait() } diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 472098f59eb..2472001c38b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -191,7 +191,7 @@ fn execute(opts: &Options) -> FmtResult { Operation::Stdin { input, config_path } => { // try to read config from local directory let (mut config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap()) - .expect("Error resolving config"); + .expect("Error resolving config"); // write_mode is always Plain for Stdin. config.write_mode = WriteMode::Plain; @@ -205,8 +205,7 @@ fn execute(opts: &Options) -> FmtResult { // Load the config path file if provided if let Some(config_file) = config_path { let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref()) - .expect(&format!("Error resolving config for {:?}", - config_file)); + .expect(&format!("Error resolving config for {:?}", config_file)); config = cfg_tmp; path = path_tmp; }; @@ -219,9 +218,7 @@ fn execute(opts: &Options) -> FmtResult { // Check the file directory if the config-path could not be read or not provided if path.is_none() { let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap()) - .expect(&format!("Error resolving config \ - for {}", - file.display())); + .expect(&format!("Error resolving config for {}", file.display())); if let Some(path) = path_tmp.as_ref() { println!("Using rustfmt config file {} for {}", path.display(), diff --git a/src/chains.rs b/src/chains.rs index 5d2ce8fedf7..ec9e6685878 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -144,9 +144,8 @@ pub fn rewrite_chain(expr: &ast::Expr, // Total of all items excluding the last. let almost_total = rewrites[..rewrites.len() - 1] - .iter() - .fold(0, |a, b| a + first_line_width(b)) + - parent_rewrite.len(); + .iter() + .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let total_width = almost_total + first_line_width(rewrites.last().unwrap()); let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { @@ -271,8 +270,9 @@ fn chain_indent(context: &RewriteContext, offset: Indent) -> Indent { fn hacked_chain_indent(context: &RewriteContext, _offset: Indent) -> Indent { match context.config.chain_indent { BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Visual | - BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + BlockIndentStyle::Visual | BlockIndentStyle::Tabbed => { + context.block_indent.block_indent(context.config) + } } } diff --git a/src/items.rs b/src/items.rs index 2566d9a436b..19dad7f866c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -912,7 +912,7 @@ fn format_tuple_struct(context: &RewriteContext, // know that earlier, so the where clause will not be indented properly. result.push('\n'); result.push_str(&(context.block_indent + (context.config.tab_spaces - 1)) - .to_string(context.config)); + .to_string(context.config)); } result.push_str(&where_clause_str); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 092cc0093f1..3d1ef21478e 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -112,10 +112,10 @@ impl<'a> FmtVisitor<'a> { for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { if let CodeCharKind::Comment = kind { let last_char = big_snippet[..(offset + big_diff)] - .chars() - .rev() - .skip_while(|rev_c| [' ', '\t'].contains(&rev_c)) - .next(); + .chars() + .rev() + .skip_while(|rev_c| [' ', '\t'].contains(&rev_c)) + .next(); let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); diff --git a/tests/system.rs b/tests/system.rs index 2a6b1a9e19c..9ec8404b1d8 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -102,8 +102,8 @@ fn assert_output(source: &str, expected_filename: &str) { fn idempotence_tests() { // Get all files in the tests/target directory. let files = fs::read_dir("tests/target") - .expect("Couldn't read target dir") - .map(get_path_string); + .expect("Couldn't read target dir") + .map(get_path_string); let (_reports, count, fails) = check_files(files); // Display results. @@ -116,9 +116,9 @@ fn idempotence_tests() { #[test] fn self_tests() { let files = fs::read_dir("src/bin") - .expect("Couldn't read src dir") - .chain(fs::read_dir("tests").expect("Couldn't read tests dir")) - .map(get_path_string); + .expect("Couldn't read src dir") + .chain(fs::read_dir("tests").expect("Couldn't read tests dir")) + .map(get_path_string); // Hack because there's no `IntoIterator` impl for `[T; N]`. let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); @@ -264,7 +264,7 @@ fn read_significant_comments(file_name: &str) -> HashMap { // Matches lines containing significant comments or whitespace. let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") - .expect("Failed creating pattern 2"); + .expect("Failed creating pattern 2"); reader.lines() .map(|line| line.expect("Failed getting line")) diff --git a/tests/target/chains-indent-visual.rs b/tests/target/chains-indent-visual.rs index e91317bd5de..e3ab320c6e1 100644 --- a/tests/target/chains-indent-visual.rs +++ b/tests/target/chains-indent-visual.rs @@ -2,9 +2,9 @@ fn test() { let x = my_long_function() - .my_even_longer_function() - .my_nested_function() - .some_random_name() - .another_function() - .do_it(); + .my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); } diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index cd694099d95..de8adcceccd 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -51,9 +51,9 @@ fn main() { } let chain = funktion_kall() - .go_to_next_line_with_tab() - .go_to_next_line_with_tab() - .go_to_next_line_with_tab(); + .go_to_next_line_with_tab() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab(); let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, -- cgit 1.4.1-3-g733a5 From a9c3108c9cd6267ebaf2489fb65a07b88a4f9d4e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Apr 2016 19:03:36 +1200 Subject: Change defaults and update tests and source New defaults are `Tabbed` for `chain_indent` and `chain_base_indent`, and `5` for `closure_block_indent_threshold`. --- src/bin/cargo-fmt.rs | 16 ++-- src/bin/rustfmt.rs | 14 ++-- src/chains.rs | 16 ++-- src/comment.rs | 38 ++++----- src/config.rs | 8 +- src/expr.rs | 120 ++++++++++++++--------------- src/items.rs | 150 +++++++++++++++++------------------- src/lists.rs | 20 +++-- src/macros.rs | 5 +- src/missed_spans.rs | 18 ++--- src/patterns.rs | 9 +-- src/string.rs | 4 +- src/types.rs | 55 +++++++------ src/utils.rs | 16 ++-- src/visitor.rs | 18 ++--- tests/system.rs | 20 ++--- tests/target/chains-no-overflow.rs | 30 ++++---- tests/target/chains-no-overlow-2.rs | 22 +++--- tests/target/chains.rs | 89 +++++++++++---------- tests/target/hard-tabs.rs | 4 +- tests/target/long_field_access.rs | 4 +- 21 files changed, 323 insertions(+), 353 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 575e25ed965..909d62b20f8 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -98,14 +98,14 @@ fn format_crate(verbosity: Verbosity) -> Result { // Currently only bin and lib files get formatted let files: Vec<_> = targets.into_iter() - .filter(|t| t.kind.is_lib() | t.kind.is_bin()) - .inspect(|t| { - if verbosity == Verbosity::Verbose { - println!("[{:?}] {:?}", t.kind, t.path) - } - }) - .map(|t| t.path) - .collect(); + .filter(|t| t.kind.is_lib() | t.kind.is_bin()) + .inspect(|t| { + if verbosity == Verbosity::Verbose { + println!("[{:?}] {:?}", t.kind, t.path) + } + }) + .map(|t| t.path) + .collect(); format_files(&files, &get_fmt_args(), verbosity) } diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2472001c38b..2105a962997 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -298,13 +298,13 @@ fn determine_operation(matches: &Matches) -> FmtResult { // Read the config_path and convert to parent dir if a file is provided. let config_path: Option = matches.opt_str("config-path") - .map(PathBuf::from) - .and_then(|dir| { - if dir.is_file() { - return dir.parent().map(|v| v.into()); - } - Some(dir) - }); + .map(PathBuf::from) + .and_then(|dir| { + if dir.is_file() { + return dir.parent().map(|v| v.into()); + } + Some(dir) + }); // if no file argument is supplied, read from stdin if matches.free.is_empty() { diff --git a/src/chains.rs b/src/chains.rs index ec9e6685878..255db49386c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -132,15 +132,9 @@ pub fn rewrite_chain(expr: &ast::Expr, let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); let mut rewrites = try_opt!(subexpr_list.iter() - .rev() - .map(|e| { - rewrite_chain_subexpr(e, - total_span, - context, - max_width, - indent) - }) - .collect::>>()); + .rev() + .map(|e| rewrite_chain_subexpr(e, total_span, context, max_width, indent)) + .collect::>>()); // Total of all items excluding the last. let almost_total = rewrites[..rewrites.len() - 1] @@ -367,8 +361,8 @@ fn rewrite_method_call(method_name: ast::Ident, (args[0].span.hi, String::new()) } else { let type_list: Vec<_> = try_opt!(types.iter() - .map(|ty| ty.rewrite(context, width, offset)) - .collect()); + .map(|ty| ty.rewrite(context, width, offset)) + .collect()); (types.last().unwrap().span.hi, format!("::<{}>", type_list.join(", "))) }; diff --git a/src/comment.rs b/src/comment.rs index 9b64e3f1345..991faa3c9c8 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -70,24 +70,24 @@ pub fn rewrite_comment(orig: &str, let line_breaks = s.chars().filter(|&c| c == '\n').count(); let lines = s.lines() - .enumerate() - .map(|(i, mut line)| { - line = line.trim(); - // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = &line[..(line.len() - 2)]; - } - - line.trim_right() - }) - .map(left_trim_comment_line) - .map(|line| { - if line_breaks == 0 { - line.trim_left() - } else { - line - } - }); + .enumerate() + .map(|(i, mut line)| { + line = line.trim(); + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = &line[..(line.len() - 2)]; + } + + line.trim_right() + }) + .map(left_trim_comment_line) + .map(|line| { + if line_breaks == 0 { + line.trim_left() + } else { + line + } + }); let mut result = opener.to_owned(); for line in lines { @@ -538,7 +538,7 @@ fn changed_comment_content(orig: &str, new: &str) -> bool { let code_comment_content = |code| { let slices = UngroupedCommentCodeSlices::new(code); slices.filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) - .flat_map(|(_, _, s)| CommentReducer::new(s)) + .flat_map(|(_, _, s)| CommentReducer::new(s)) }; let res = code_comment_content(orig).ne(code_comment_content(new)); debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", diff --git a/src/config.rs b/src/config.rs index 71edfe955bd..333835b66cd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -375,8 +375,8 @@ create_config! { "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; - chain_base_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on chain base"; - chain_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of chain"; + chain_base_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indent on chain base"; + chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain"; chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; @@ -390,8 +390,8 @@ create_config! { match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; - closure_block_indent_threshold: isize, -1, "How many lines a closure must have before it is \ - block indented. -1 means never use block indent."; + closure_block_indent_threshold: isize, 5, "How many lines a closure must have before it is \ + block indented. -1 means never use block indent."; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; } diff --git a/src/expr.rs b/src/expr.rs index 2a6144481ba..c2d5115ba75 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -283,12 +283,11 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.rewrite(&inner_context, max_item_width, offset), span.lo, span.hi) - .collect::>(); + .collect::>(); let has_long_item = try_opt!(items.iter() - .map(|li| li.item.as_ref().map(|s| s.len() > 10)) - .fold(Some(false), - |acc, x| acc.and_then(|y| x.map(|x| x || y)))); + .map(|li| li.item.as_ref().map(|s| s.len() > 10)) + .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y)))); let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width) @@ -410,8 +409,8 @@ fn rewrite_closure(capture: ast::CaptureBy, if try_single_line && !force_block { let must_preserve_braces = !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(inner_block.expr - .as_ref() - .unwrap())); + .as_ref() + .unwrap())); if !(must_preserve_braces && had_braces) && (must_preserve_braces || !prefix.contains('\n')) { // If we got here, then we can try to format without braces. @@ -523,9 +522,9 @@ impl Rewrite for ast::Block { if is_simple_block(self, context.codemap) && prefix.len() < width { let body = self.expr - .as_ref() - .unwrap() - .rewrite(context, width - prefix.len(), offset); + .as_ref() + .unwrap() + .rewrite(context, width - prefix.len(), offset); if let Some(ref expr_str) = body { let result = format!("{}{{ {} }}", prefix, expr_str); if result.len() <= width && !result.contains('\n') { @@ -568,9 +567,9 @@ impl Rewrite for ast::Stmt { }; ex.rewrite(context, - context.config.max_width - offset.width() - suffix.len(), - offset) - .map(|s| s + suffix) + context.config.max_width - offset.width() - suffix.len(), + offset) + .map(|s| s + suffix) } ast::StmtKind::Mac(..) => None, }; @@ -805,8 +804,8 @@ fn rewrite_if_else(context: &RewriteContext, width); let after_else = mk_sp(context.codemap - .span_after(mk_sp(if_block.span.hi, else_block.span.lo), - "else"), + .span_after(mk_sp(if_block.span.hi, else_block.span.lo), + "else"), else_block.span.lo); let after_else_comment = extract_comment(after_else, &context, offset, width); @@ -822,9 +821,9 @@ fn rewrite_if_else(context: &RewriteContext, try_opt!(write!(&mut result, "{}else{}", between_if_else_block_comment.as_ref() - .map_or(between_sep, |str| &**str), + .map_or(between_sep, |str| &**str), after_else_comment.as_ref().map_or(after_sep, |str| &**str)) - .ok()); + .ok()); result.push_str(&&try_opt!(rewrite)); } @@ -968,7 +967,7 @@ fn rewrite_match(context: &RewriteContext, let arm_indent_str = arm_indent.to_string(context.config); let open_brace_pos = context.codemap - .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); + .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. @@ -1073,8 +1072,8 @@ impl Rewrite for ast::Arm { // 5 = ` => {` let pat_budget = try_opt!(width.checked_sub(5)); let pat_strs = try_opt!(pats.iter() - .map(|p| p.rewrite(context, pat_budget, offset)) - .collect::>>()); + .map(|p| p.rewrite(context, pat_budget, offset)) + .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(&p)); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); @@ -1445,7 +1444,7 @@ fn rewrite_call_inner(context: &RewriteContext, let tactic = definitive_tactic(&item_vec, ListTactic::LimitedHorizontalVertical(context.config - .fn_call_width), + .fn_call_width), remaining_width); // Replace the stub with the full overflowing last argument if the rewrite @@ -1525,8 +1524,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }; let field_iter = fields.into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); let inner_context = &RewriteContext { block_indent: indent, ..*context }; @@ -1534,20 +1533,16 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, field_iter, "}", |item| { - match *item { - StructLitField::Regular(ref field) => field.span.lo, - StructLitField::Base(ref expr) => { - let last_field_hi = fields.last().map_or(span.lo, - |field| { - field.span.hi - }); - let snippet = context.snippet(mk_sp(last_field_hi, - expr.span.lo)); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - } - }, + match *item { + StructLitField::Regular(ref field) => field.span.lo, + StructLitField::Base(ref expr) => { + let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + } + }, |item| { match *item { StructLitField::Regular(ref field) => field.span.hi, @@ -1555,22 +1550,20 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } }, |item| { - match *item { - StructLitField::Regular(ref field) => { - rewrite_field(inner_context, - &field, - v_budget.checked_sub(1).unwrap_or(0), - indent) - } - StructLitField::Base(ref expr) => { - // 2 = .. - expr.rewrite(inner_context, - try_opt!(v_budget.checked_sub(2)), - indent + 2) - .map(|s| format!("..{}", s)) - } - } - }, + match *item { + StructLitField::Regular(ref field) => { + rewrite_field(inner_context, + &field, + v_budget.checked_sub(1).unwrap_or(0), + indent) + } + StructLitField::Base(ref expr) => { + // 2 = .. + expr.rewrite(inner_context, try_opt!(v_budget.checked_sub(2)), indent + 2) + .map(|s| format!("..{}", s)) + } + } + }, context.codemap.span_after(span, "{"), span.hi); let item_vec = items.collect::>(); @@ -1617,8 +1610,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let format_on_newline = || { let inner_indent = context.block_indent - .block_indent(context.config) - .to_string(context.config); + .block_indent(context.config) + .to_string(context.config); let outer_indent = context.block_indent.to_string(context.config); Some(format!("{} {{\n{}{}\n{}}}", path_str, @@ -1656,8 +1649,8 @@ fn rewrite_field(context: &RewriteContext, let expr_offset = offset.block_indent(&context.config); let expr = field.expr.rewrite(context, try_opt!(context.config - .max_width - .checked_sub(expr_offset.width())), + .max_width + .checked_sub(expr_offset.width())), expr_offset); expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) } @@ -1690,9 +1683,8 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, |item| item.span().hi, |item| { let inner_width = try_opt!(context.config - .max_width - .checked_sub(indent.width() + - 1)); + .max_width + .checked_sub(indent.width() + 1)); item.rewrite(context, inner_width, indent) }, list_lo, @@ -1750,8 +1742,8 @@ fn rewrite_binary_op(context: &RewriteContext, // Re-evaluate the lhs because we have more space now: let budget = try_opt!(context.config - .max_width - .checked_sub(offset.width() + 1 + operator_str.len())); + .max_width + .checked_sub(offset.width() + 1 + operator_str.len())); Some(format!("{} {}\n{}{}", try_opt!(lhs.rewrite(context, budget, offset)), operator_str, @@ -1766,9 +1758,9 @@ pub fn rewrite_unary_prefix(context: &RewriteContext, offset: Indent) -> Option { rewrite.rewrite(context, - try_opt!(width.checked_sub(prefix.len())), - offset + prefix.len()) - .map(|r| format!("{}{}", prefix, r)) + try_opt!(width.checked_sub(prefix.len())), + offset + prefix.len()) + .map(|r| format!("{}{}", prefix, r)) } fn rewrite_unary_op(context: &RewriteContext, diff --git a/src/items.rs b/src/items.rs index 19dad7f866c..5ded7c2c5e8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -277,10 +277,10 @@ impl<'a> FmtVisitor<'a> { }; e.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) - .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span))) + self.config.max_width - self.block_indent.width(), + self.block_indent) + .map(|s| s + suffix) + .or_else(|| Some(self.snippet(e.span))) } else if let Some(ref stmt) = block.stmts.first() { stmt.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), @@ -321,7 +321,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent, self.block_indent.block_indent(self.config), mk_sp(span.lo, body_start)) - .unwrap(); + .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; @@ -359,12 +359,12 @@ impl<'a> FmtVisitor<'a> { enum_def.variants.iter(), "}", |f| { - if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo - } else { - f.span.lo - } - }, + if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo + } else { + f.span.lo + } + }, |f| f.span.hi, |f| self.format_variant(f), body_lo, @@ -397,10 +397,10 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent; let mut result = try_opt!(field.node - .attrs - .rewrite(&self.get_context(), - self.config.max_width - indent.width(), - indent)); + .attrs + .rewrite(&self.get_context(), + self.config.max_width - indent.width(), + indent)); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -666,8 +666,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) }; let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -803,13 +803,13 @@ fn format_struct_struct(context: &RewriteContext, fields.iter(), "}", |field| { - // Include attributes and doc comments, if present - if !field.node.attrs.is_empty() { - field.node.attrs[0].span.lo - } else { - field.span.lo - } - }, + // Include attributes and doc comments, if present + if !field.node.attrs.is_empty() { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }, |field| field.node.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), context.codemap.span_after(span, "{"), @@ -864,8 +864,8 @@ fn format_tuple_struct(context: &RewriteContext, result.push_str(&generics_str); let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + .max_width + .checked_sub(last_line_width(&result))); try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -889,13 +889,13 @@ fn format_tuple_struct(context: &RewriteContext, fields.iter(), ")", |field| { - // Include attributes and doc comments, if present - if !field.node.attrs.is_empty() { - field.node.attrs[0].span.lo - } else { - field.span.lo - } - }, + // Include attributes and doc comments, if present + if !field.node.attrs.is_empty() { + field.node.attrs[0].span.lo + } else { + field.span.lo + } + }, |field| field.node.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), context.codemap.span_after(span, "("), @@ -946,8 +946,8 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&generics_str); let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -965,26 +965,25 @@ pub fn rewrite_type_alias(context: &RewriteContext, // This checked_sub may fail as the extra space after '=' is not taken into account // In that case the budget is set to 0 which will make ty.rewrite retry on a new line let budget = context.config - .max_width - .checked_sub(indent.width() + line_width + ";".len()) - .unwrap_or(0); + .max_width + .checked_sub(indent.width() + line_width + ";".len()) + .unwrap_or(0); let type_indent = indent + line_width; // Try to fit the type on the same line let ty_str = try_opt!(ty.rewrite(context, budget, type_indent) - .or_else(|| { - // The line was too short, try to put the type on the next line - - // Remove the space after '=' - result.pop(); - let type_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context.config - .max_width - .checked_sub(type_indent.width() + - ";".len())); - ty.rewrite(context, budget, type_indent) - })); + .or_else(|| { + // The line was too short, try to put the type on the next line + + // Remove the space after '=' + result.pop(); + let type_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&type_indent.to_string(context.config)); + let budget = try_opt!(context.config + .max_width + .checked_sub(type_indent.width() + ";".len())); + ty.rewrite(context, budget, type_indent) + })); result.push_str(&ty_str); result.push_str(";"); Some(result) @@ -1006,10 +1005,8 @@ impl Rewrite for ast::StructField { ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), }; let mut attr_str = try_opt!(self.node - .attrs - .rewrite(context, - context.config.max_width - offset.width(), - offset)); + .attrs + .rewrite(context, context.config.max_width - offset.width(), offset)); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&offset.to_string(context.config)); @@ -1069,11 +1066,9 @@ pub fn rewrite_associated_type(ident: ast::Ident, let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = &ty_param_bounds.as_slice(); let bound_str = bounds.iter() - .filter_map(|ty_bound| { - ty_bound.rewrite(context, context.config.max_width, indent) - }) - .collect::>() - .join(" + "); + .filter_map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) + .collect::>() + .join(" + "); if bounds.len() > 0 { format!(": {}", bound_str) } else { @@ -1287,7 +1282,7 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that if the width and indent really matter, we'll re-layout the // return type later anyway. let ret_str = try_opt!(fd.output - .rewrite(&context, context.config.max_width - indent.width(), indent)); + .rewrite(&context, context.config.max_width - indent.width(), indent)); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { @@ -1332,8 +1327,8 @@ fn rewrite_fn_base(context: &RewriteContext, // A conservative estimation, to goal is to be over all parens in generics let args_start = generics.ty_params - .last() - .map_or(span.lo, |tp| end_typaram(tp)); + .last() + .map_or(span.lo, |tp| end_typaram(tp)); let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("), span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, @@ -1408,7 +1403,7 @@ fn rewrite_fn_base(context: &RewriteContext, let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); let ret_str = try_opt!(fd.output - .rewrite(context, budget, ret_indent)); + .rewrite(context, budget, ret_indent)); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -1477,21 +1472,18 @@ fn rewrite_args(context: &RewriteContext, variadic: bool) -> Option { let mut arg_item_strs = try_opt!(args.iter() - .map(|arg| { - arg.rewrite(&context, multi_line_budget, arg_indent) - }) - .collect::>>()); + .map(|arg| arg.rewrite(&context, multi_line_budget, arg_indent)) + .collect::>>()); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. - let min_args = explicit_self.and_then(|explicit_self| { - rewrite_explicit_self(explicit_self, args, context) - }) - .map_or(1, |self_str| { - arg_item_strs[0] = self_str; - 2 - }); + let min_args = + explicit_self.and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) + .map_or(1, |self_str| { + arg_item_strs[0] = self_str; + 2 + }); // Comments between args. let mut arg_items = Vec::new(); @@ -1722,9 +1714,9 @@ fn rewrite_trait_bounds(context: &RewriteContext, } let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) - .collect::>() - .join(" + "); + .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) + .collect::>() + .join(" + "); let mut result = String::new(); result.push_str(": "); diff --git a/src/lists.rs b/src/lists.rs index b251a8ee255..f966e41ce99 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -160,8 +160,8 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De T: AsRef { let pre_line_comments = items.clone() - .into_iter() - .any(|item| item.as_ref().has_line_pre_comment()); + .into_iter() + .any(|item| item.as_ref().has_line_pre_comment()); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, @@ -353,9 +353,8 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let mut new_lines = false; // Pre-comment let pre_snippet = self.codemap - .span_to_snippet(codemap::mk_sp(self.prev_span_end, - (self.get_lo)(&item))) - .unwrap(); + .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) + .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); let pre_comment = if !trimmed_pre_snippet.is_empty() { Some(trimmed_pre_snippet.to_owned()) @@ -369,9 +368,8 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> None => self.next_span_start, }; let post_snippet = self.codemap - .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), - next_start)) - .unwrap(); + .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) + .unwrap(); let comment_end = match self.inner.peek() { Some(..) => { @@ -413,7 +411,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; let first = test_snippet.find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); + .unwrap_or(test_snippet.len()); // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; @@ -494,8 +492,8 @@ fn calculate_width(items: I) -> (usize, usize) T: AsRef { items.into_iter() - .map(|item| total_item_width(item.as_ref())) - .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) + .map(|item| total_item_width(item.as_ref())) + .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) } fn total_item_width(item: &ListItem) -> usize { diff --git a/src/macros.rs b/src/macros.rs index 2be271e140b..13e1164487a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -112,8 +112,9 @@ pub fn rewrite_macro(mac: &ast::Mac, // Format macro invocation as array literal. let extra_offset = macro_name.len(); let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context.codemap.span_after(mac.span, - original_style.opener()), + mk_sp(context.codemap + .span_after(mac.span, + original_style.opener()), mac.span.hi - BytePos(1)), context, try_opt!(width.checked_sub(extra_offset)), diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 3d1ef21478e..2191a7812b1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -93,14 +93,14 @@ impl<'a> FmtVisitor<'a> { fn replace_chars(string: &str) -> String { string.chars() - .map(|ch| { - if ch.is_whitespace() { - ch - } else { - 'X' - } - }) - .collect() + .map(|ch| { + if ch.is_whitespace() { + ch + } else { + 'X' + } + }) + .collect() } let replaced = match self.config.write_mode { @@ -134,7 +134,7 @@ impl<'a> FmtVisitor<'a> { comment_width, self.block_indent, self.config) - .unwrap()); + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); diff --git a/src/patterns.rs b/src/patterns.rs index 3cec98bb93a..ba3621fc6d5 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -103,15 +103,14 @@ impl Rewrite for Pat { PatKind::Vec(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, width, offset)); - let slice_pat = slice_pat.as_ref().map(|p| { - Some(format!("{}..", try_opt!(p.rewrite(context, width, offset)))) - }); + let slice_pat = slice_pat.as_ref() + .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, width, offset))))); let suffix = suffix.iter().map(|p| p.rewrite(context, width, offset)); // Munge them together. let pats: Option> = prefix.chain(slice_pat.into_iter()) - .chain(suffix) - .collect(); + .chain(suffix) + .collect(); // Check that all the rewrites succeeded, and if not return None. let pats = try_opt!(pats); diff --git a/src/string.rs b/src/string.rs index bccf39deb92..e90e24f7af2 100644 --- a/src/string.rs +++ b/src/string.rs @@ -42,8 +42,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; let mut result = String::with_capacity(stripped_str.len() - .checked_next_power_of_two() - .unwrap_or(usize::max_value())); + .checked_next_power_of_two() + .unwrap_or(usize::max_value())); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); diff --git a/src/types.rs b/src/types.rs index 22b518d2463..a1d449f3249 100644 --- a/src/types.rs +++ b/src/types.rs @@ -176,11 +176,11 @@ fn rewrite_segment(expr_context: bool, !data.types.is_empty() || !data.bindings.is_empty() => { let param_list = data.lifetimes - .iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) - .collect::>(); + .iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); @@ -270,7 +270,7 @@ fn format_function_type<'a, I>(inputs: I, // FIXME Would be nice to avoid this allocation, // but I couldn't get the types to work out. inputs.map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), + .chain(variadic_arg), ")", |arg| { match *arg { @@ -285,13 +285,11 @@ fn format_function_type<'a, I>(inputs: I, } }, |arg| { - match *arg { - ArgumentKind::Regular(ref ty) => { - ty.rewrite(context, budget, offset) - } - ArgumentKind::Variadic(_) => Some("...".to_owned()), - } - }, + match *arg { + ArgumentKind::Regular(ref ty) => ty.rewrite(context, budget, offset), + ArgumentKind::Variadic(_) => Some("...".to_owned()), + } + }, list_lo, span.hi); @@ -408,8 +406,8 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, Some(result) } else { let appendix: Vec<_> = try_opt!(bounds.into_iter() - .map(|b| b.rewrite(context, width, offset)) - .collect()); + .map(|b| b.rewrite(context, width, offset)) + .collect()); let result = format!("{}: {}", result, appendix.join(" + ")); wrap_str(result, context.config.max_width, width, offset) } @@ -442,8 +440,8 @@ impl Rewrite for ast::Lifetime { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { let strs: Vec<_> = try_opt!(self.iter() - .map(|b| b.rewrite(context, width, offset)) - .collect()); + .map(|b| b.rewrite(context, width, offset)) + .collect()); wrap_str(strs.join(" + "), context.config.max_width, width, offset) } } @@ -456,10 +454,10 @@ impl Rewrite for ast::TyParam { result.push_str(": "); let bounds = try_opt!(self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, width, offset)) - .collect::>>()) - .join(" + "); + .iter() + .map(|ty_bound| ty_bound.rewrite(context, width, offset)) + .collect::>>()) + .join(" + "); result.push_str(&bounds); } @@ -483,15 +481,15 @@ impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if !self.bound_lifetimes.is_empty() { let lifetime_str = try_opt!(self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, width, offset)) - .collect::>>()) - .join(", "); + .iter() + .map(|lt| lt.rewrite(context, width, offset)) + .collect::>>()) + .join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); let path_str = try_opt!(self.trait_ref - .rewrite(context, max_path_width, offset + extra_offset)); + .rewrite(context, max_path_width, offset + extra_offset)); Some(format!("for<{}> {}", lifetime_str, path_str)) } else { @@ -545,9 +543,8 @@ impl Rewrite for ast::Ty { format!("&{} {}{}", lt_str, mut_str, - try_opt!(mt.ty.rewrite(context, - budget, - offset + 2 + mut_len + lt_len))) + try_opt!(mt.ty + .rewrite(context, budget, offset + 2 + mut_len + lt_len))) } None => { let budget = try_opt!(width.checked_sub(1 + mut_len)); diff --git a/src/utils.rs b/src/utils.rs index 667c9cd7efd..da690f1e8ea 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -142,14 +142,14 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { #[inline] pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { typaram.bounds - .last() - .map_or(typaram.span, |bound| { - match *bound { - ast::RegionTyParamBound(ref lt) => lt.span, - ast::TraitTyParamBound(ref prt, _) => prt.span, - } - }) - .hi + .last() + .map_or(typaram.span, |bound| { + match *bound { + ast::RegionTyParamBound(ref lt) => lt.span, + ast::TraitTyParamBound(ref prt, _) => prt.span, + } + }) + .hi } #[inline] diff --git a/src/visitor.rs b/src/visitor.rs index d52a167cb5e..8fba02de2d1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -86,9 +86,9 @@ impl<'a> FmtVisitor<'a> { if let Some(ref e) = b.expr { self.format_missing_with_indent(e.span.lo); let rewrite = e.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) - .unwrap_or_else(|| self.snippet(e.span)); + self.config.max_width - self.block_indent.width(), + self.block_indent) + .unwrap_or_else(|| self.snippet(e.span)); self.buffer.push_str(&rewrite); self.last_pos = e.span.hi; @@ -436,9 +436,9 @@ impl<'a> FmtVisitor<'a> { } let outers: Vec<_> = attrs.iter() - .filter(|a| a.node.style == ast::AttrStyle::Outer) - .cloned() - .collect(); + .filter(|a| a.node.style == ast::AttrStyle::Outer) + .cloned() + .collect(); if outers.is_empty() { return false; } @@ -447,9 +447,9 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(first.span.lo); let rewrite = outers.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) - .unwrap(); + self.config.max_width - self.block_indent.width(), + self.block_indent) + .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); self.last_pos = last.span.hi; diff --git a/tests/system.rs b/tests/system.rs index 9ec8404b1d8..1af9c0f3462 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -85,7 +85,7 @@ fn assert_output(source: &str, expected_filename: &str) { let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); let mut expected_text = String::new(); expected_file.read_to_string(&mut expected_text) - .expect("Failed reading target"); + .expect("Failed reading target"); let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); if compare.len() > 0 { @@ -267,15 +267,15 @@ fn read_significant_comments(file_name: &str) -> HashMap { .expect("Failed creating pattern 2"); reader.lines() - .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(&line)) - .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { - (capture.at(1).expect("Couldn't unwrap capture").to_owned(), - capture.at(2).expect("Couldn't unwrap capture").to_owned()) - }) - }) - .collect() + .map(|line| line.expect("Failed getting line")) + .take_while(|line| line_regex.is_match(&line)) + .filter_map(|line| { + regex.captures_iter(&line).next().map(|capture| { + (capture.at(1).expect("Couldn't unwrap capture").to_owned(), + capture.at(2).expect("Couldn't unwrap capture").to_owned()) + }) + }) + .collect() } // Compare output to input. diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs index 2479157bb4f..2c78fbd9121 100644 --- a/tests/target/chains-no-overflow.rs +++ b/tests/target/chains-no-overflow.rs @@ -3,16 +3,16 @@ fn main() { bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); + .ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); + .ddddddddddddddddddddddddddd + .eeeeeeee(); x().y(|| match cond() { - true => (), - false => (), - }); + true => (), + false => (), + }); loong_func() .quux(move || if true { @@ -24,19 +24,17 @@ fn main() { fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = - Some(&script_task); - }); + *root.borrow_mut() = Some(&script_task); + }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, - |acc, x| acc + x); + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) + x += 1; + x + }) + .filter(some_mod::some_filter) } diff --git a/tests/target/chains-no-overlow-2.rs b/tests/target/chains-no-overlow-2.rs index 815620234b5..c11070913d9 100644 --- a/tests/target/chains-no-overlow-2.rs +++ b/tests/target/chains-no-overlow-2.rs @@ -2,15 +2,15 @@ fn main() { reader.lines() - .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(&line)) - .filter_map(|line| { - regex.captures_iter(&line) - .next() - .map(|capture| { - (capture.at(1).expect("Couldn\'t unwrap capture").to_owned(), - capture.at(2).expect("Couldn\'t unwrap capture").to_owned()) - }) - }) - .collect(); + .map(|line| line.expect("Failed getting line")) + .take_while(|line| line_regex.is_match(&line)) + .filter_map(|line| { + regex.captures_iter(&line) + .next() + .map(|capture| { + (capture.at(1).expect("Couldn\'t unwrap capture").to_owned(), + capture.at(2).expect("Couldn\'t unwrap capture").to_owned()) + }) + }) + .collect(); } diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 392ff355b86..aacdb8e93e1 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -3,16 +3,16 @@ fn main() { // Don't put chains on a single line if it wasn't so in source. let a = b.c - .d - .1 - .foo(|x| x + 1); + .d + .1 + .foo(|x| x + 1); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); + .ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); + .ddddddddddddddddddddddddddd + .eeeeeeee(); // Test case where first chain element isn't a path, but is shorter than // the size of a tab. @@ -49,15 +49,14 @@ fn main() { }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, - |acc, x| acc + x); + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) + x += 1; + x + }) + .filter(some_mod::some_filter) } fn floaters() { @@ -67,39 +66,39 @@ fn floaters() { }; let x = Foo { - field1: val1, - field2: val2, - } - .method_call() - .method_call(); + field1: val1, + field2: val2, + } + .method_call() + .method_call(); let y = if cond { - val1 - } else { - val2 - } - .method_call(); + val1 + } else { + val2 + } + .method_call(); { match x { PushParam => { // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); } } } if cond { - some(); - } else { - none(); - } - .bar() - .baz(); + some(); + } else { + none(); + } + .bar() + .baz(); Foo { x: val } .baz(|| { @@ -108,25 +107,25 @@ fn floaters() { .quux(); Foo { - y: i_am_multi_line, - z: ok, - } - .baz(|| { - // force multiline - }) - .quux(); + y: i_am_multi_line, + z: ok, + } + .baz(|| { + // force multiline + }) + .quux(); a + match x { - true => "yay!", - false => "boo!", - } - .bar() + true => "yay!", + false => "boo!", + } + .bar() } fn is_replaced_content() -> bool { constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) - .unwrap(); + .unwrap(); } fn issue587() { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index de8adcceccd..0914959ceb1 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -88,8 +88,8 @@ fn main() { }); }); a.b - .c - .d(); + .c + .d(); x().y(|| { match cond() { diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs index 349d2c2f639..e4efd86b7f9 100644 --- a/tests/target/long_field_access.rs +++ b/tests/target/long_field_access.rs @@ -1,4 +1,4 @@ fn f() { - block_flow.base.stacking_relative_position_of_display_port = - self.base.stacking_relative_position_of_display_port; + block_flow.base.stacking_relative_position_of_display_port = self.base + .stacking_relative_position_of_display_port; } -- cgit 1.4.1-3-g733a5 From 19fa5c9ebb85aa7643d5917c406f6bcc0dc0ff52 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Apr 2016 19:26:42 +1200 Subject: Update docs (and a function name) --- src/chains.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 255db49386c..d4faedca5c1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -54,35 +54,26 @@ /// .baz(); /// ``` /// -/// `chain_indent` dictates how the rest of the chain is aligned. This only seems -/// to have an effect if the first non-root part of the chain is put on a -/// newline, otherwise we align the dots: -/// ``` -/// foo.bar -/// .baz() -/// ``` +/// `chain_indent` dictates how the rest of the chain is aligned. /// If the first item in the chain is a block expression, we align the dots with /// the braces. -/// -/// Otherwise: /// Visual: /// ``` -/// let a = foo(aaa, bbb) -/// .bar -/// .baz() +/// let a = foo.bar +/// .baz() +/// .qux /// ``` -/// Visual seems to be a tab indented from the indent of the whole expression. /// Inherit: /// ``` -/// let a = foo(aaa, bbb) -/// .bar +/// let a = foo.bar /// .baz() +/// .qux /// ``` /// Tabbed: /// ``` -/// let a = foo(aaa, bbb) -/// .bar +/// let a = foo.bar /// .baz() +/// .qux /// ``` /// `chains_overflow_last` applies only to chains where the last item is a /// method call. Usually, any line break in a chain sub-expression causes the @@ -127,7 +118,7 @@ pub fn rewrite_chain(expr: &ast::Expr, } else if parent_rewrite.contains('\n') { (chain_indent(context, parent_block_indent.block_indent(context.config)), false) } else { - (hacked_chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), false) + (chain_indent_newline(context, offset + Indent::new(0, parent_rewrite.len())), false) }; let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); @@ -259,9 +250,9 @@ fn chain_indent(context: &RewriteContext, offset: Indent) -> Indent { } } -// Temporary hack - ignores visual indenting because this function should be -// called where it is not possible to use visual indentation. -fn hacked_chain_indent(context: &RewriteContext, _offset: Indent) -> Indent { +// Ignores visual indenting because this function should be called where it is +// not possible to use visual indentation because we are starting on a newline. +fn chain_indent_newline(context: &RewriteContext, _offset: Indent) -> Indent { match context.config.chain_indent { BlockIndentStyle::Inherit => context.block_indent, BlockIndentStyle::Visual | BlockIndentStyle::Tabbed => { -- cgit 1.4.1-3-g733a5 From f2105d382f64d9351e5b44a0cfb11af8f9abe618 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 26 Apr 2016 14:27:13 +1200 Subject: Fix for stable --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index d4faedca5c1..aa6034aa687 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -178,7 +178,7 @@ pub fn rewrite_chain(expr: &ast::Expr, let first_connector = if extend { "" } else { - &connector + &*connector }; wrap_str(format!("{}{}{}", -- cgit 1.4.1-3-g733a5 From 9188ec0f7fd068608c9446cce99944c4cc33ede3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Apr 2016 07:08:44 +1200 Subject: Bail out on recovered errors. (#965) Closes #915 Closes #930 Closes #931 --- src/lib.rs | 19 +++++++++++++++---- src/macros.rs | 15 ++++++++++++--- tests/source/macros.rs | 5 +++++ tests/target/macros.rs | 5 +++++ 4 files changed, 37 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index f63b2caaa94..0a222428fe1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -378,13 +378,22 @@ fn format_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { report } -fn parse_input(input: Input, parse_session: &ParseSess) -> Result { - match input { +fn parse_input(input: Input, + parse_session: &ParseSess) + -> Result> { + let result = match input { Input::File(file) => parse::parse_crate_from_file(&file, Vec::new(), &parse_session), Input::Text(text) => { parse::parse_crate_from_source_str("stdin".to_owned(), text, Vec::new(), &parse_session) } + }; + + // Bail out if the parser recovered from an error. + if parse_session.span_diagnostic.has_errors() { + return Err(None); } + + result.map_err(|e| Some(e)) } pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatReport) { @@ -405,8 +414,10 @@ pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatR let krate = match parse_input(input, &parse_session) { Ok(krate) => krate, - Err(mut diagnostic) => { - diagnostic.emit(); + Err(diagnostic) => { + if let Some(mut diagnostic) = diagnostic { + diagnostic.emit(); + } summary.add_parsing_error(); return (summary, FileMap::new(), FormatReport::new()); } diff --git a/src/macros.rs b/src/macros.rs index 2be271e140b..bd054474608 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -81,13 +81,22 @@ pub fn rewrite_macro(mac: &ast::Mac, if MacroStyle::Braces != style { loop { - expr_vec.push(match parser.parse_expr() { - Ok(expr) => expr, + let expr = match parser.parse_expr() { + Ok(expr) => { + // Recovered errors. + if context.parse_session.span_diagnostic.has_errors() { + return None; + } + + expr + } Err(mut e) => { e.cancel(); return None; } - }); + }; + + expr_vec.push(expr); match parser.token { Token::Eof => break, diff --git a/tests/source/macros.rs b/tests/source/macros.rs index aa0ba0b234e..d04c204186c 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -55,3 +55,8 @@ fn main() { impl X { empty_invoc!{} } + +gfx_pipeline!(pipe { + vbuf: gfx::VertexBuffer = (), + out: gfx::RenderTarget = "Target0", +}); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 7099f714144..902dd2e4d9a 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -58,3 +58,8 @@ fn main() { impl X { empty_invoc!{} } + +gfx_pipeline!(pipe { + vbuf: gfx::VertexBuffer = (), + out: gfx::RenderTarget = "Target0", +}); -- cgit 1.4.1-3-g733a5 From 70611bf9ac9f8103aa77ab1f91adb51327f681e4 Mon Sep 17 00:00:00 2001 From: Micah Chalmer Date: Thu, 28 Apr 2016 01:38:04 -0400 Subject: Always skip children when using Plain write mode Outputting child module contents in the "Plain" write mode does not make sense, since there is no way to differentiate code that came from a child module from that which came from the parent file. --- src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 0a222428fe1..942fdb06994 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -280,8 +280,11 @@ fn format_ast(krate: &ast::Crate, config: &Config) -> FileMap { let mut file_map = FileMap::new(); + // We always skip children for the "Plain" write mode, since there is + // nothing to distinguish the nested module contents. + let skip_children = config.skip_children || config.write_mode == config::WriteMode::Plain; for (path, module) in modules::list_files(krate, parse_session.codemap()) { - if config.skip_children && path.as_path() != main_file { + if skip_children && path.as_path() != main_file { continue; } let path = path.to_str().unwrap(); -- cgit 1.4.1-3-g733a5 From fd38acb86fa991f1272013d565992f2f68d76a5f Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 1 May 2016 23:01:46 -0400 Subject: deps: Update syntex_syntax to 0.31.0 Most of the churn on this bump comes from the `Visibility` enum changing from pub enum Visibility { Public, Inherited, } to pub enum Visibility { Public, Crate, Restricted { path: P, id: NodeId }, Inherited, } which require taking `Visibility` by reference in most places. The new variants are not handled at this point. Refs #970 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/items.rs | 65 ++++++++++++++++++++++++++-------------------------------- src/utils.rs | 7 +++++-- src/visitor.rs | 28 ++++++++++++------------- 5 files changed, 51 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 8c7661b832d..a31897dd455 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "regex 0.1.63 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -111,7 +111,7 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 6cc358ca199..bf719ce90ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.30" +syntex_syntax = "0.31" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/items.rs b/src/items.rs index 5ded7c2c5e8..486325faf5d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -126,7 +126,7 @@ impl<'a> FmtVisitor<'a> { // These are not actually rust functions, // but we format them as such. abi::Abi::Rust, - item.vis, + &item.vis, span, false, false); @@ -148,7 +148,7 @@ impl<'a> FmtVisitor<'a> { "" }; let prefix = format!("{}static {}{}: ", - format_visibility(item.vis), + format_visibility(&item.vis), mut_str, item.ident); let offset = self.block_indent + prefix.len(); @@ -179,7 +179,7 @@ impl<'a> FmtVisitor<'a> { unsafety: ast::Unsafety, constness: ast::Constness, abi: abi::Abi, - vis: ast::Visibility, + vis: &ast::Visibility, span: Span, block: &ast::Block) -> Option { @@ -244,7 +244,7 @@ impl<'a> FmtVisitor<'a> { sig.unsafety, sig.constness, sig.abi, - ast::Visibility::Inherited, + &ast::Visibility::Inherited, span, false, false)); @@ -303,7 +303,7 @@ impl<'a> FmtVisitor<'a> { pub fn visit_enum(&mut self, ident: ast::Ident, - vis: ast::Visibility, + vis: &ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span) { @@ -414,7 +414,7 @@ impl<'a> FmtVisitor<'a> { format_struct(&context, "", field.node.name, - ast::Visibility::Inherited, + &ast::Visibility::Inherited, &field.node.data, None, field.span, @@ -451,7 +451,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - ref self_ty, ref items) = item.node { let mut result = String::new(); - result.push_str(format_visibility(item.vis)); + result.push_str(format_visibility(&item.vis)); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); @@ -583,7 +583,7 @@ fn is_impl_single_line(context: &RewriteContext, pub fn format_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, - vis: ast::Visibility, + vis: &ast::Visibility, struct_def: &ast::VariantData, generics: Option<&ast::Generics>, span: Span, @@ -619,7 +619,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) item.node { let mut result = String::new(); let header = format!("{}{}trait {}", - format_visibility(item.vis), + format_visibility(&item.vis), format_unsafety(unsafety), item.ident); @@ -741,7 +741,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } -fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> Option { +fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> Option { let mut result = String::with_capacity(1024); let header_str = format_header(item_name, ident, vis); @@ -754,7 +754,7 @@ fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: ast::Visibility) fn format_struct_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, - vis: ast::Visibility, + vis: &ast::Visibility, fields: &[ast::StructField], generics: Option<&ast::Generics>, span: Span, @@ -804,13 +804,13 @@ fn format_struct_struct(context: &RewriteContext, "}", |field| { // Include attributes and doc comments, if present - if !field.node.attrs.is_empty() { - field.node.attrs[0].span.lo + if !field.attrs.is_empty() { + field.attrs[0].span.lo } else { field.span.lo } }, - |field| field.node.ty.span.hi, + |field| field.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), context.codemap.span_after(span, "{"), span.hi); @@ -835,7 +835,7 @@ fn format_struct_struct(context: &RewriteContext, fn format_tuple_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, - vis: ast::Visibility, + vis: &ast::Visibility, fields: &[ast::StructField], generics: Option<&ast::Generics>, span: Span, @@ -890,13 +890,13 @@ fn format_tuple_struct(context: &RewriteContext, ")", |field| { // Include attributes and doc comments, if present - if !field.node.attrs.is_empty() { - field.node.attrs[0].span.lo + if !field.attrs.is_empty() { + field.attrs[0].span.lo } else { field.span.lo } }, - |field| field.node.ty.span.hi, + |field| field.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), context.codemap.span_after(span, "("), span.hi); @@ -924,12 +924,12 @@ pub fn rewrite_type_alias(context: &RewriteContext, ident: ast::Ident, ty: &ast::Ty, generics: &ast::Generics, - vis: ast::Visibility, + vis: &ast::Visibility, span: Span) -> Option { let mut result = String::new(); - result.push_str(&format_visibility(vis)); + result.push_str(&format_visibility(&vis)); result.push_str("type "); result.push_str(&ident.to_string()); @@ -991,21 +991,14 @@ pub fn rewrite_type_alias(context: &RewriteContext, impl Rewrite for ast::StructField { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - if contains_skip(&self.node.attrs) { - let span = context.snippet(mk_sp(self.node.attrs[0].span.lo, self.span.hi)); + if contains_skip(&self.attrs) { + let span = context.snippet(mk_sp(self.attrs[0].span.lo, self.span.hi)); return wrap_str(span, context.config.max_width, width, offset); } - let name = match self.node.kind { - ast::StructFieldKind::NamedField(ident, _) => Some(ident.to_string()), - ast::StructFieldKind::UnnamedField(_) => None, - }; - let vis = match self.node.kind { - ast::StructFieldKind::NamedField(_, vis) | - ast::StructFieldKind::UnnamedField(vis) => format_visibility(vis), - }; - let mut attr_str = try_opt!(self.node - .attrs + let name = self.ident; + let vis = format_visibility(&self.vis); + let mut attr_str = try_opt!(self.attrs .rewrite(context, context.config.max_width - offset.width(), offset)); if !attr_str.is_empty() { attr_str.push('\n'); @@ -1019,13 +1012,13 @@ impl Rewrite for ast::StructField { let last_line_width = last_line_width(&result); let budget = try_opt!(width.checked_sub(last_line_width)); - let rewrite = try_opt!(self.node.ty.rewrite(context, budget, offset + last_line_width)); + let rewrite = try_opt!(self.ty.rewrite(context, budget, offset + last_line_width)); Some(result + &rewrite) } } pub fn rewrite_static(prefix: &str, - vis: ast::Visibility, + vis: &ast::Visibility, ident: ast::Ident, ty: &ast::Ty, mutability: ast::Mutability, @@ -1239,7 +1232,7 @@ fn rewrite_fn_base(context: &RewriteContext, unsafety: ast::Unsafety, constness: ast::Constness, abi: abi::Abi, - vis: ast::Visibility, + vis: &ast::Visibility, span: Span, newline_brace: bool, has_body: bool) @@ -1808,7 +1801,7 @@ fn rewrite_where_clause(context: &RewriteContext, } } -fn format_header(item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String { +fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { format!("{}{}{}", format_visibility(vis), item_name, ident) } diff --git a/src/utils.rs b/src/utils.rs index da690f1e8ea..e1f33832a3b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -67,10 +67,13 @@ pub fn extra_offset(text: &str, offset: Indent) -> usize { } #[inline] -pub fn format_visibility(vis: Visibility) -> &'static str { - match vis { +pub fn format_visibility(vis: &Visibility) -> &'static str { + match *vis { Visibility::Public => "pub ", Visibility::Inherited => "", + // TODO(#970): Handle new visibility types. + Visibility::Crate => unimplemented!(), + Visibility::Restricted { .. } => unimplemented!(), } } diff --git a/src/visitor.rs b/src/visitor.rs index 8fba02de2d1..1ae3578376b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -152,7 +152,7 @@ impl<'a> FmtVisitor<'a> { sig.unsafety, sig.constness, sig.abi, - vis.unwrap_or(ast::Visibility::Inherited), + vis.unwrap_or(&ast::Visibility::Inherited), codemap::mk_sp(s.lo, b.span.lo), &b) } @@ -198,7 +198,7 @@ impl<'a> FmtVisitor<'a> { match item.node { ast::ItemKind::Use(ref vp) => { - self.format_import(item.vis, vp, item.span); + self.format_import(&item.vis, vp, item.span); } ast::ItemKind::Impl(..) => { self.format_missing_with_indent(item.span.lo); @@ -229,7 +229,7 @@ impl<'a> FmtVisitor<'a> { ::items::format_struct(&context, "struct ", item.ident, - item.vis, + &item.vis, def, Some(generics), item.span, @@ -245,12 +245,12 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Enum(ref def, ref generics) => { self.format_missing_with_indent(item.span.lo); - self.visit_enum(item.ident, item.vis, def, generics, item.span); + self.visit_enum(item.ident, &item.vis, def, generics, item.span); self.last_pos = item.span.hi; } ast::ItemKind::Mod(ref module) => { self.format_missing_with_indent(item.span.lo); - self.format_mod(module, item.vis, item.span, item.ident); + self.format_mod(module, &item.vis, item.span, item.ident); } ast::ItemKind::Mac(ref mac) => { self.format_missing_with_indent(item.span.lo); @@ -262,7 +262,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Static(ref ty, mutability, ref expr) => { let rewrite = rewrite_static("static", - item.vis, + &item.vis, item.ident, ty, mutability, @@ -272,7 +272,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static("const", - item.vis, + &item.vis, item.ident, ty, ast::Mutability::Immutable, @@ -289,7 +289,7 @@ impl<'a> FmtVisitor<'a> { unsafety, constness, abi, - item.vis), + &item.vis), decl, body, item.span, @@ -301,7 +301,7 @@ impl<'a> FmtVisitor<'a> { item.ident, ty, generics, - item.vis, + &item.vis, item.span); self.push_rewrite(item.span, rewrite); } @@ -316,7 +316,7 @@ impl<'a> FmtVisitor<'a> { match ti.node { ast::TraitItemKind::Const(ref ty, ref expr_opt) => { let rewrite = rewrite_static("const", - ast::Visibility::Inherited, + &ast::Visibility::Inherited, ti.ident, ty, ast::Mutability::Immutable, @@ -354,7 +354,7 @@ impl<'a> FmtVisitor<'a> { match ii.node { ast::ImplItemKind::Method(ref sig, ref body) => { - self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(ii.vis)), + self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis)), &sig.decl, body, ii.span, @@ -362,7 +362,7 @@ impl<'a> FmtVisitor<'a> { } ast::ImplItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static("const", - ii.vis, + &ii.vis, ii.ident, ty, ast::Mutability::Immutable, @@ -462,7 +462,7 @@ impl<'a> FmtVisitor<'a> { } } - fn format_mod(&mut self, m: &ast::Mod, vis: ast::Visibility, s: Span, ident: ast::Ident) { + fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: ast::Ident) { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); let is_internal = local_file_name == self.codemap.span_to_filename(m.inner); @@ -501,7 +501,7 @@ impl<'a> FmtVisitor<'a> { self.format_missing(filemap.end_pos); } - fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span) { + fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { let vis = utils::format_visibility(vis); let mut offset = self.block_indent; offset.alignment += vis.len() + "use ".len(); -- cgit 1.4.1-3-g733a5 From 6285d538854239d62984ab6c72be4a85eb38f353 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 2 May 2016 01:05:23 -0400 Subject: Handle new visibility types more gracefully --- src/items.rs | 36 ++++++++++++++++++++---------------- src/utils.rs | 12 ++++++------ src/visitor.rs | 9 +++++++-- 3 files changed, 33 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 486325faf5d..b1dffebbc13 100644 --- a/src/items.rs +++ b/src/items.rs @@ -142,15 +142,16 @@ impl<'a> FmtVisitor<'a> { ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. + let vis = match format_visibility(&item.vis) { + Some(s) => s, + None => return, + }; let mut_str = if is_mutable { "mut " } else { "" }; - let prefix = format!("{}static {}{}: ", - format_visibility(&item.vis), - mut_str, - item.ident); + let prefix = format!("{}static {}{}: ", vis, mut_str, item.ident); let offset = self.block_indent + prefix.len(); // 1 = ; let width = self.config.max_width - offset.width() - 1; @@ -307,7 +308,10 @@ impl<'a> FmtVisitor<'a> { enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span) { - let header_str = format_header("enum ", ident, vis); + let header_str = match format_header("enum ", ident, vis) { + Some(s) => s, + None => return, + }; self.buffer.push_str(&header_str); let enum_snippet = self.snippet(span); @@ -451,7 +455,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - ref self_ty, ref items) = item.node { let mut result = String::new(); - result.push_str(format_visibility(&item.vis)); + result.push_str(try_opt!(format_visibility(&item.vis))); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); @@ -619,7 +623,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) item.node { let mut result = String::new(); let header = format!("{}{}trait {}", - format_visibility(&item.vis), + try_opt!(format_visibility(&item.vis)), format_unsafety(unsafety), item.ident); @@ -744,7 +748,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> Option { let mut result = String::with_capacity(1024); - let header_str = format_header(item_name, ident, vis); + let header_str = try_opt!(format_header(item_name, ident, vis)); result.push_str(&header_str); result.push(';'); @@ -762,7 +766,7 @@ fn format_struct_struct(context: &RewriteContext, -> Option { let mut result = String::with_capacity(1024); - let header_str = format_header(item_name, ident, vis); + let header_str = try_opt!(format_header(item_name, ident, vis)); result.push_str(&header_str); let body_lo = context.codemap.span_after(span, "{"); @@ -843,7 +847,7 @@ fn format_tuple_struct(context: &RewriteContext, -> Option { let mut result = String::with_capacity(1024); - let header_str = format_header(item_name, ident, vis); + let header_str = try_opt!(format_header(item_name, ident, vis)); result.push_str(&header_str); // FIXME(#919): don't lose comments on empty tuple structs. @@ -929,7 +933,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, -> Option { let mut result = String::new(); - result.push_str(&format_visibility(&vis)); + result.push_str(&try_opt!(format_visibility(&vis))); result.push_str("type "); result.push_str(&ident.to_string()); @@ -997,7 +1001,7 @@ impl Rewrite for ast::StructField { } let name = self.ident; - let vis = format_visibility(&self.vis); + let vis = try_opt!(format_visibility(&self.vis)); let mut attr_str = try_opt!(self.attrs .rewrite(context, context.config.max_width - offset.width(), offset)); if !attr_str.is_empty() { @@ -1026,7 +1030,7 @@ pub fn rewrite_static(prefix: &str, context: &RewriteContext) -> Option { let prefix = format!("{}{} {}{}: ", - format_visibility(vis), + try_opt!(format_visibility(vis)), prefix, format_mutability(mutability), ident); @@ -1245,7 +1249,7 @@ fn rewrite_fn_base(context: &RewriteContext, let mut result = String::with_capacity(1024); // Vis unsafety abi. - result.push_str(format_visibility(vis)); + result.push_str(try_opt!(format_visibility(vis))); if let ast::Constness::Const = constness { result.push_str("const "); @@ -1801,8 +1805,8 @@ fn rewrite_where_clause(context: &RewriteContext, } } -fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, ident) +fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> Option { + Some(format!("{}{}{}", try_opt!(format_visibility(vis)), item_name, ident)) } fn format_generics(context: &RewriteContext, diff --git a/src/utils.rs b/src/utils.rs index e1f33832a3b..b80a5783799 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -67,13 +67,13 @@ pub fn extra_offset(text: &str, offset: Indent) -> usize { } #[inline] -pub fn format_visibility(vis: &Visibility) -> &'static str { +pub fn format_visibility(vis: &Visibility) -> Option<&'static str> { match *vis { - Visibility::Public => "pub ", - Visibility::Inherited => "", - // TODO(#970): Handle new visibility types. - Visibility::Crate => unimplemented!(), - Visibility::Restricted { .. } => unimplemented!(), + Visibility::Public => Some("pub "), + Visibility::Inherited => Some(""), + // FIXME(#970): Handle new visibility types. + Visibility::Crate => None, + Visibility::Restricted { .. } => None, } } diff --git a/src/visitor.rs b/src/visitor.rs index 1ae3578376b..762f77a16e6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -467,7 +467,9 @@ impl<'a> FmtVisitor<'a> { let local_file_name = self.codemap.span_to_filename(s); let is_internal = local_file_name == self.codemap.span_to_filename(m.inner); - self.buffer.push_str(utils::format_visibility(vis)); + if let Some(vis) = utils::format_visibility(vis) { + self.buffer.push_str(vis); + } self.buffer.push_str("mod "); self.buffer.push_str(&ident.to_string()); @@ -502,7 +504,10 @@ impl<'a> FmtVisitor<'a> { } fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { - let vis = utils::format_visibility(vis); + let vis = match utils::format_visibility(vis) { + Some(s) => s, + None => return, + }; let mut offset = self.block_indent; offset.alignment += vis.len() + "use ".len(); // 1 = ";" -- cgit 1.4.1-3-g733a5 From c696dcf8dae0c34161d467b7fbc32b0d7b01bb61 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 2 May 2016 20:54:25 +1200 Subject: Handle attributes on modules (#968) * Handle attributes (including doc comments) on inline modules Closes #22 Closes #684 * Tweak the rules for changing indentation in comments (to do it less often). --- src/comment.rs | 10 +++++----- src/visitor.rs | 31 ++++++++++++++++++++++--------- tests/target/attrib.rs | 4 ++-- tests/target/structs.rs | 3 ++- 4 files changed, 31 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 991faa3c9c8..83ea21b91e8 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -82,7 +82,7 @@ pub fn rewrite_comment(orig: &str, }) .map(left_trim_comment_line) .map(|line| { - if line_breaks == 0 { + if orig.starts_with("/*") && line_breaks == 0 { line.trim_left() } else { line @@ -529,10 +529,10 @@ pub fn recover_comment_removed(new: String, /// Return true if the two strings of code have the same payload of comments. /// The payload of comments is everything in the string except: -/// - actual code (not comments) -/// - comment start/end marks -/// - whitespace -/// - '*' at the beginning of lines in block comments +/// - actual code (not comments) +/// - comment start/end marks +/// - whitespace +/// - '*' at the beginning of lines in block comments fn changed_comment_content(orig: &str, new: &str) -> bool { // Cannot write this as a fn since we cannot return types containing closures let code_comment_content = |code| { diff --git a/src/visitor.rs b/src/visitor.rs index 8fba02de2d1..260303f32ae 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -177,14 +177,19 @@ impl<'a> FmtVisitor<'a> { } fn visit_item(&mut self, item: &ast::Item) { - // Don't look at attributes for modules (except for rustfmt_skip). - // We want to avoid looking at attributes in another file, which the AST - // doesn't distinguish. - // FIXME This is overly conservative and means we miss attributes on - // inline modules. + // Only look at attributes for modules (except for rustfmt_skip) if the + // module is inline. We want to avoid looking at attributes in another + // file, which the AST doesn't distinguish. match item.node { - ast::ItemKind::Mod(_) => { - if utils::contains_skip(&item.attrs) { + ast::ItemKind::Mod(ref m) => { + let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; + let inner_file = self.codemap.lookup_char_pos(m.inner.lo).file; + if outer_file.name == inner_file.name { + if self.visit_attrs(&item.attrs) { + self.push_rewrite(item.span, None); + return; + } + } else if utils::contains_skip(&item.attrs) { return; } } @@ -551,7 +556,7 @@ impl<'a> Rewrite for [ast::Attribute] { let indent = offset.to_string(context.config); for (i, a) in self.iter().enumerate() { - let a_str = context.snippet(a.span); + let mut a_str = context.snippet(a.span); // Write comments and blank lines between attributes. if i > 0 { @@ -564,7 +569,7 @@ impl<'a> Rewrite for [ast::Attribute] { if !comment.is_empty() { let comment = try_opt!(rewrite_comment(comment, false, - context.config.max_width - + context.config.ideal_width - offset.width(), offset, context.config)); @@ -577,6 +582,14 @@ impl<'a> Rewrite for [ast::Attribute] { result.push_str(&indent); } + if a_str.starts_with("//") { + a_str = try_opt!(rewrite_comment(&a_str, + false, + context.config.ideal_width - offset.width(), + offset, + context.config)); + } + // Write the attribute itself. result.push_str(&a_str); diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 9317a837065..b861b971d9b 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -33,8 +33,8 @@ impl Bar { #[attrib1] /// Blah blah bing. #[attrib2] - // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo - // loooooooooooong. + // Another comment that needs rewrite because it's + // tooooooooooooooooooooooooooooooo loooooooooooong. /// Blah blah bing. fn f4(self) -> Cat {} } diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 428258c4f76..0af68686318 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -96,7 +96,8 @@ pub struct State { } struct Palette { - /// A map of indizes in the palette to a count of pixels in approximately that color + /// A map of indizes in the palette to a count of pixels in approximately + /// that color foo: i32, } -- cgit 1.4.1-3-g733a5 From 96d59366fc3bb0b99d9ec39fb651fc3a7334b009 Mon Sep 17 00:00:00 2001 From: Aaron Gallagher Date: Mon, 2 May 2016 17:11:22 -0700 Subject: Don't misplace the :: on associated items. The rewritten location of the :: on global paths for qpaths was wrong. --- src/types.rs | 5 ++++- tests/target/associated-items.rs | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/target/associated-items.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index a1d449f3249..cf65f4426b3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -33,7 +33,7 @@ pub fn rewrite_path(context: &RewriteContext, -> Option { let skip_count = qself.map_or(0, |x| x.position); - let mut result = if path.global { + let mut result = if path.global && qself.is_none() { "::".to_owned() } else { String::new() @@ -48,6 +48,9 @@ pub fn rewrite_path(context: &RewriteContext, if skip_count > 0 { result.push_str(" as "); + if path.global { + result.push_str("::"); + } let extra_offset = extra_offset(&result, offset); // 3 = ">::".len() diff --git a/tests/target/associated-items.rs b/tests/target/associated-items.rs new file mode 100644 index 00000000000..1b0a828d029 --- /dev/null +++ b/tests/target/associated-items.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", ::default()); +} -- cgit 1.4.1-3-g733a5 From f85c603c63d2b6d793fdfd415074255c4d1a28ca Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Tue, 3 May 2016 21:52:55 +0900 Subject: Remove unused trait imports --- src/checkstyle.rs | 2 +- src/expr.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 02e214864fa..c43a37cf813 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use rustfmt_diff::{Mismatch, DiffLine}; -use std::io::{self, Write, Read}; +use std::io::{self, Write}; use config::WriteMode; diff --git a/src/expr.rs b/src/expr.rs index c2d5115ba75..04941c179b3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -33,7 +33,6 @@ use macros::rewrite_macro; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; use syntax::parse::classify; -use syntax::visit::Visitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { -- cgit 1.4.1-3-g733a5 From 8309d1a74ca611c4879450d26b168f7c4b2638d8 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 1 May 2016 23:01:46 -0400 Subject: deps: Update syntex_syntax to 0.32.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/expr.rs | 2 +- src/items.rs | 6 +++--- src/utils.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index a31897dd455..71d4280ed93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ dependencies = [ "regex 0.1.63 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -111,7 +111,7 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index bf719ce90ef..69ed0a108c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.31" +syntex_syntax = "0.32" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/expr.rs b/src/expr.rs index 04941c179b3..32fd5f561c3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -145,7 +145,7 @@ impl Rewrite for ast::Expr { }; wrap_str(format!("break{}", id_str), context.config.max_width, width, offset) } - ast::ExprKind::Closure(capture, ref fn_decl, ref body) => { + ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } ast::ExprKind::Field(..) | diff --git a/src/items.rs b/src/items.rs index b1dffebbc13..f3b4d1859a1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1061,7 +1061,7 @@ pub fn rewrite_associated_type(ident: ast::Ident, let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let bounds: &[_] = &ty_param_bounds.as_slice(); + let bounds: &[_] = &ty_param_bounds; let bound_str = bounds.iter() .filter_map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) .collect::>() @@ -1188,7 +1188,7 @@ pub fn span_hi_for_arg(arg: &ast::Arg) -> BytePos { pub fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != token::special_idents::invalid + ident.node != token::keywords::Invalid.ident() } else { true } @@ -1704,7 +1704,7 @@ fn rewrite_trait_bounds(context: &RewriteContext, indent: Indent, width: usize) -> Option { - let bounds: &[_] = &type_param_bounds.as_slice(); + let bounds: &[_] = &type_param_bounds; if bounds.is_empty() { return Some(String::new()); diff --git a/src/utils.rs b/src/utils.rs index b80a5783799..c7d4dd55469 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -72,7 +72,7 @@ pub fn format_visibility(vis: &Visibility) -> Option<&'static str> { Visibility::Public => Some("pub "), Visibility::Inherited => Some(""), // FIXME(#970): Handle new visibility types. - Visibility::Crate => None, + Visibility::Crate(_) => None, Visibility::Restricted { .. } => None, } } -- cgit 1.4.1-3-g733a5 From 4a2db3ec6cb4e4a2a115e279c5df7fb48b62c80a Mon Sep 17 00:00:00 2001 From: Daniel Campbell Date: Fri, 6 May 2016 12:20:38 +1200 Subject: Changed modules & visitor mods to public, set filemap::write_file public --- src/filemap.rs | 10 +++++----- src/lib.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index c6af9a70184..64c892a0929 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -80,11 +80,11 @@ pub fn write_system_newlines(writer: T, } } -fn write_file(text: &StringBuffer, - filename: &str, - out: &mut T, - config: &Config) - -> Result, io::Error> +pub fn write_file(text: &StringBuffer, + filename: &str, + out: &mut T, + config: &Config) + -> Result, io::Error> where T: Write { diff --git a/src/lib.rs b/src/lib.rs index 942fdb06994..b825059ee20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ pub use self::summary::Summary; mod utils; pub mod config; pub mod filemap; -mod visitor; +pub mod visitor; mod checkstyle; mod items; mod missed_spans; @@ -61,7 +61,7 @@ mod issues; mod rewrite; mod string; mod comment; -mod modules; +pub mod modules; pub mod rustfmt_diff; mod chains; mod macros; -- cgit 1.4.1-3-g733a5 From 238fc500ae7425b183fe72e8a3aee4c9cb640d3a Mon Sep 17 00:00:00 2001 From: Daniel Campbell Date: Fri, 6 May 2016 13:02:42 +1200 Subject: Altered FmtVisitor to function correctly on generated code --- src/visitor.rs | 87 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index d6be7401074..83108897684 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -22,6 +22,14 @@ use comment::rewrite_comment; use macros::rewrite_macro; use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; +// For format_missing and last_pos, need to use the source callsite (if applicable). +// Required as generated code spans aren't guaranteed to follow on from the last span. +macro_rules! source { + ($this:ident, $sp: expr) => { + $this.codemap.source_callsite($sp) + } +} + pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, @@ -55,7 +63,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Mac(ref mac, _macro_style, _) => { - self.format_missing_with_indent(stmt.span.lo); + self.format_missing_with_indent(source!(self, stmt.span).lo); self.visit_mac(mac, None); } } @@ -84,14 +92,14 @@ impl<'a> FmtVisitor<'a> { } if let Some(ref e) = b.expr { - self.format_missing_with_indent(e.span.lo); + self.format_missing_with_indent(source!(self, e.span).lo); let rewrite = e.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), self.block_indent) .unwrap_or_else(|| self.snippet(e.span)); self.buffer.push_str(&rewrite); - self.last_pos = e.span.hi; + self.last_pos = source!(self, e.span).hi; if utils::semicolon_for_expr(e) { self.buffer.push_str(";"); @@ -99,9 +107,9 @@ impl<'a> FmtVisitor<'a> { } // FIXME: we should compress any newlines here to just one - self.format_missing_with_indent(b.span.hi - brace_compensation); + self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation); self.close_block(); - self.last_pos = b.span.hi; + self.last_pos = source!(self, b.span).hi; } // FIXME: this is a terrible hack to indent the comments between the last @@ -160,19 +168,19 @@ impl<'a> FmtVisitor<'a> { }; if let Some(fn_str) = rewrite { - self.format_missing_with_indent(s.lo); + self.format_missing_with_indent(source!(self, s).lo); self.buffer.push_str(&fn_str); if let Some(c) = fn_str.chars().last() { if c == '}' { - self.last_pos = b.span.hi; + self.last_pos = source!(self, b.span).hi; return; } } } else { - self.format_missing(b.span.lo); + self.format_missing(source!(self, b.span).lo); } - self.last_pos = b.span.lo; + self.last_pos = source!(self, b.span).lo; self.visit_block(b) } @@ -206,10 +214,10 @@ impl<'a> FmtVisitor<'a> { self.format_import(&item.vis, vp, item.span); } ast::ItemKind::Impl(..) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(source!(self, item.span).lo); if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent) { self.buffer.push_str(&impl_str); - self.last_pos = item.span.hi; + self.last_pos = source!(self, item.span).hi; } } ast::ItemKind::Trait(..) => { @@ -218,14 +226,14 @@ impl<'a> FmtVisitor<'a> { item, self.block_indent) { self.buffer.push_str(&trait_str); - self.last_pos = item.span.hi; + self.last_pos = source!(self, item.span).hi; } } ast::ItemKind::ExternCrate(_) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(source!(self, item.span).lo); let new_str = self.snippet(item.span); self.buffer.push_str(&new_str); - self.last_pos = item.span.hi; + self.last_pos = source!(self, item.span).hi; } ast::ItemKind::Struct(ref def, ref generics) => { let rewrite = { @@ -249,20 +257,20 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(item.span, rewrite); } ast::ItemKind::Enum(ref def, ref generics) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(source!(self, item.span).lo); self.visit_enum(item.ident, &item.vis, def, generics, item.span); - self.last_pos = item.span.hi; + self.last_pos = source!(self, item.span).hi; } ast::ItemKind::Mod(ref module) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(source!(self, item.span).lo); self.format_mod(module, &item.vis, item.span, item.ident); } ast::ItemKind::Mac(ref mac) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(source!(self, item.span).lo); self.visit_mac(mac, Some(item.ident)); } ast::ItemKind::ForeignMod(ref foreign_mod) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(source!(self, item.span).lo); self.format_foreign_mod(foreign_mod, item.span); } ast::ItemKind::Static(ref ty, mutability, ref expr) => { @@ -384,7 +392,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { - self.format_missing_with_indent(ii.span.lo); + self.format_missing_with_indent(source!(self, ii.span).lo); self.visit_mac(mac, Some(ii.ident)); } } @@ -397,15 +405,15 @@ impl<'a> FmtVisitor<'a> { if let Some(res) = rewrite { self.buffer.push_str(&res); - self.last_pos = mac.span.hi; + self.last_pos = source!(self, mac.span).hi; } } fn push_rewrite(&mut self, span: Span, rewrite: Option) { - self.format_missing_with_indent(span.lo); + self.format_missing_with_indent(source!(self, span).lo); let result = rewrite.unwrap_or_else(|| self.snippet(span)); self.buffer.push_str(&result); - self.last_pos = span.hi; + self.last_pos = source!(self, span).hi; } pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> { @@ -449,7 +457,7 @@ impl<'a> FmtVisitor<'a> { } let first = &outers[0]; - self.format_missing_with_indent(first.span.lo); + self.format_missing_with_indent(source!(self, first.span).lo); let rewrite = outers.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), @@ -457,7 +465,7 @@ impl<'a> FmtVisitor<'a> { .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); - self.last_pos = last.span.hi; + self.last_pos = source!(self, last.span).hi; false } @@ -470,7 +478,7 @@ impl<'a> FmtVisitor<'a> { fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: ast::Ident) { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); - let is_internal = local_file_name == self.codemap.span_to_filename(m.inner); + let is_internal = local_file_name == self.codemap.span_to_filename(source!(self, m.inner)); if let Some(vis) = utils::format_visibility(vis) { self.buffer.push_str(vis); @@ -481,8 +489,9 @@ impl<'a> FmtVisitor<'a> { if is_internal { self.buffer.push_str(" {"); // Hackery to account for the closing }. - let mod_lo = self.codemap.span_after(s, "{"); - let body_snippet = self.snippet(codemap::mk_sp(mod_lo, m.inner.hi - BytePos(1))); + let mod_lo = self.codemap.span_after(source!(self, s), "{"); + let body_snippet = + self.snippet(codemap::mk_sp(mod_lo, source!(self, m.inner).hi - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { self.buffer.push_str("}"); @@ -490,18 +499,18 @@ impl<'a> FmtVisitor<'a> { self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); self.walk_mod_items(m); - self.format_missing_with_indent(m.inner.hi - BytePos(1)); + self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1)); self.close_block(); } - self.last_pos = m.inner.hi; + self.last_pos = source!(self, m.inner).hi; } else { self.buffer.push_str(";"); - self.last_pos = s.hi; + self.last_pos = source!(self, s).hi; } } pub fn format_separate_mod(&mut self, m: &ast::Mod) { - let filemap = self.codemap.lookup_char_pos(m.inner.lo).file; + let filemap = self.codemap.lookup_char_pos(source!(self, m.inner).lo).file; self.last_pos = filemap.start_pos; self.block_indent = Indent::empty(); self.walk_mod_items(m); @@ -521,23 +530,23 @@ impl<'a> FmtVisitor<'a> { offset) { Some(ref s) if s.is_empty() => { // Format up to last newline - let prev_span = codemap::mk_sp(self.last_pos, span.lo); + let prev_span = codemap::mk_sp(self.last_pos, source!(self, span).lo); let span_end = match self.snippet(prev_span).rfind('\n') { Some(offset) => self.last_pos + BytePos(offset as u32), - None => span.lo, + None => source!(self, span).lo, }; self.format_missing(span_end); - self.last_pos = span.hi; + self.last_pos = source!(self, span).hi; } Some(ref s) => { let s = format!("{}use {};", vis, s); - self.format_missing_with_indent(span.lo); + self.format_missing_with_indent(source!(self, span).lo); self.buffer.push_str(&s); - self.last_pos = span.hi; + self.last_pos = source!(self, span).hi; } None => { - self.format_missing_with_indent(span.lo); - self.format_missing(span.hi); + self.format_missing_with_indent(source!(self, span).lo); + self.format_missing(source!(self, span).hi); } } } -- cgit 1.4.1-3-g733a5 From ee7b5805fcb1e4bc6334b7a6a814769d4606541d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 9 May 2016 20:07:59 +0200 Subject: Format try shorthand --- src/chains.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++----- src/expr.rs | 29 ++++++++++++++++++++++------- tests/source/chains.rs | 9 +++++++++ tests/target/chains.rs | 13 +++++++++++++ 4 files changed, 88 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index aa6034aa687..da2a7629bad 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -9,7 +9,7 @@ // except according to those terms. /// Formatting of chained expressions, i.e. expressions which are chained by -/// dots: struct and enum field access and method calls. +/// dots: struct and enum field access, method calls, and try shorthand (?). /// /// Instead of walking these subexpressions one-by-one, as is our usual strategy /// for expression formatting, we collect maximal sequences of these expressions @@ -81,7 +81,6 @@ /// true, then we allow the last method call to spill over multiple lines without /// forcing the rest of the chain to be split. - use Indent; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, first_line_width}; @@ -109,8 +108,16 @@ pub fn rewrite_chain(expr: &ast::Expr, // put the first non-parent item on the same line as the parent. let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || parent_rewrite.len() <= context.config.tab_spaces { - // Try and put at least the first two items on the same line. - (chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), true) +// <<<<<<< HEAD +// // Try and put at least the first two items on the same line. +// (chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), true) +// ======= + let indent = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node { + parent_block_indent.block_indent(context.config) + } else { + offset + Indent::new(0, parent_rewrite.len()) + }; + (indent, true) } else if is_block_expr(parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. @@ -184,12 +191,27 @@ pub fn rewrite_chain(expr: &ast::Expr, wrap_str(format!("{}{}{}", parent_rewrite, first_connector, - rewrites.join(&connector)), + join_rewrites(&rewrites, &subexpr_list, &connector)), context.config.max_width, width, offset) } +fn join_rewrites(rewrites: &[String], subexps: &[&ast::Expr], connector: &str) -> String { + let mut rewrite_iter = rewrites.iter(); + let mut result = rewrite_iter.next().unwrap().clone(); + + for (rewrite, expr) in rewrite_iter.zip(subexps.iter()) { + match expr.node { + ast::ExprKind::Try(_) => (), + _ => result.push_str(connector), + }; + result.push_str(&rewrite[..]); + } + + result +} + // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { @@ -293,6 +315,16 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, } } +fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { + match expr.node { + ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]), + ast::ExprKind::TupField(ref subexpr, _) | + ast::ExprKind::Field(ref subexpr, _) | + ast::ExprKind::Try(ref subexpr) => Some(subexpr), + _ => None, + } +} + // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite // `.c`. fn rewrite_chain_subexpr(expr: &ast::Expr, @@ -328,6 +360,13 @@ fn rewrite_chain_subexpr(expr: &ast::Expr, None } } + ast::ExprKind::Try(_) => { + if width >= 1 { + Some("?".into()) + } else { + None + } + } _ => unreachable!(), } } diff --git a/src/expr.rs b/src/expr.rs index 32fd5f561c3..ba2ed7aec09 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -148,6 +148,7 @@ impl Rewrite for ast::Expr { ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } + // ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::TupField(..) | ast::ExprKind::MethodCall(..) => rewrite_chain(self, context, width, offset), @@ -199,21 +200,20 @@ impl Rewrite for ast::Expr { rewrite_unary_prefix(context, delim, &**rhs, width, offset) } (Some(ref lhs), None) => { - Some(format!("{}{}", - try_opt!(lhs.rewrite(context, - try_opt!(width.checked_sub(delim.len())), - offset)), - delim)) + rewrite_unary_suffix(context, delim, &**lhs, width, offset) } (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), } } + ast::ExprKind::Try(ref expr) => { + rewrite_unary_suffix(context, "?", &**expr, width, offset) + } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) | - // TODO(#867): Handle try shorthand - ast::ExprKind::Try(_) => { + // TODO(#848): Handle type ascription + ast::ExprKind::Type(_, _) => { wrap_str(context.snippet(self.span), context.config.max_width, width, @@ -1762,6 +1762,21 @@ pub fn rewrite_unary_prefix(context: &RewriteContext, .map(|r| format!("{}{}", prefix, r)) } +// FIXME: this is probably not correct for multi-line Rewrites. we should +// subtract suffix.len() from the last line budget, not the first! +pub fn rewrite_unary_suffix(context: &RewriteContext, + suffix: &str, + rewrite: &R, + width: usize, + offset: Indent) + -> Option { + rewrite.rewrite(context, try_opt!(width.checked_sub(suffix.len())), offset) + .map(|mut r| { + r.push_str(suffix); + r + }) +} + fn rewrite_unary_op(context: &RewriteContext, op: &ast::UnOp, expr: &ast::Expr, diff --git a/tests/source/chains.rs b/tests/source/chains.rs index e7d9783a51c..8ec5cd191c5 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -112,3 +112,12 @@ fn issue587() { std::mem::transmute(dl.symbol::<()>("init").unwrap()) } + +fn try_shorthand() { + let x = expr?; + let y = expr.kaas()?.test(); + let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); + let zzzz = expr?.another?.another?.another?.another?; + let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??; +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index aacdb8e93e1..4c38ab7eb52 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -133,3 +133,16 @@ fn issue587() { std::mem::transmute(dl.symbol::<()>("init").unwrap()) } + +fn try_shorthand() { + let x = expr?; + let y = expr.kaas()?.test(); + let loooooooooooooooooooooooooooooooooooooooooong = does_this? + .look? + .good? + .should_we_break? + .after_the_first_question_mark?; + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); + let zzzz = expr?.another?.another?.another?.another?; + let aaa = x??????????????????????????????????????????????????????????????????????????; +} -- cgit 1.4.1-3-g733a5 From cd158cecc87cb2d4d63aecf8854952370cb9ea4b Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 9 May 2016 20:11:25 +0200 Subject: Add try macro to try shorthand conversion tests --- src/chains.rs | 62 +++++++++++++++++++++++------------------- src/config.rs | 1 + src/expr.rs | 52 +++++++++++++++++++++-------------- src/macros.rs | 26 +++++++++++++++++- tests/source/chains.rs | 4 +++ tests/source/try-conversion.rs | 11 ++++++++ tests/target/chains.rs | 9 ++++++ tests/target/try-conversion.rs | 18 ++++++++++++ 8 files changed, 134 insertions(+), 49 deletions(-) create mode 100644 tests/source/try-conversion.rs create mode 100644 tests/target/try-conversion.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index da2a7629bad..3f306abfdca 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -86,18 +86,18 @@ use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, first_line_width}; use expr::rewrite_call; use config::BlockIndentStyle; +use macros::convert_try_mac; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; - pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, width: usize, offset: Indent) -> Option { let total_span = expr.span; - let (parent, subexpr_list) = make_subexpr_list(expr); + let (parent, subexpr_list) = make_subexpr_list(expr, context); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_block_indent = chain_base_indent(context, offset); @@ -106,19 +106,16 @@ pub fn rewrite_chain(expr: &ast::Expr, // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(parent) || + let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(&parent) || parent_rewrite.len() <= context.config.tab_spaces { -// <<<<<<< HEAD -// // Try and put at least the first two items on the same line. -// (chain_indent(context, offset + Indent::new(0, parent_rewrite.len())), true) -// ======= + let indent = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node { parent_block_indent.block_indent(context.config) } else { - offset + Indent::new(0, parent_rewrite.len()) + chain_indent(context, offset + Indent::new(0, parent_rewrite.len())) }; (indent, true) - } else if is_block_expr(parent, &parent_rewrite) { + } else if is_block_expr(&parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. (parent_block_indent, false) @@ -197,11 +194,13 @@ pub fn rewrite_chain(expr: &ast::Expr, offset) } -fn join_rewrites(rewrites: &[String], subexps: &[&ast::Expr], connector: &str) -> String { +fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { let mut rewrite_iter = rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); + let mut subexpr_iter = subexps.iter().rev(); + subexpr_iter.next(); - for (rewrite, expr) in rewrite_iter.zip(subexps.iter()) { + for (rewrite, expr) in rewrite_iter.zip(subexpr_iter) { match expr.node { ast::ExprKind::Try(_) => (), _ => result.push_str(connector), @@ -235,21 +234,11 @@ fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { // Returns the root of the chain and a Vec of the prefixes of the rest of the chain. // E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) -fn make_subexpr_list(mut expr: &ast::Expr) -> (&ast::Expr, Vec<&ast::Expr>) { - fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { - match expr.node { - ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]), - ast::ExprKind::TupField(ref subexpr, _) | - ast::ExprKind::Field(ref subexpr, _) => Some(subexpr), - _ => None, - } - } - - let mut subexpr_list = vec![expr]; +fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { + let mut subexpr_list = vec![expr.clone()]; - while let Some(subexpr) = pop_expr_chain(expr) { - subexpr_list.push(subexpr); - expr = subexpr; + while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { + subexpr_list.push(subexpr.clone()); } let parent = subexpr_list.pop().unwrap(); @@ -315,16 +304,33 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, } } -fn pop_expr_chain(expr: &ast::Expr) -> Option<&ast::Expr> { +// Returns the expression's subexpression, if it exists. When the subexpr +// is a try! macro, we'll convert it to shorthand when the option is set. +fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { match expr.node { - ast::ExprKind::MethodCall(_, _, ref expressions) => Some(&expressions[0]), + ast::ExprKind::MethodCall(_, _, ref expressions) => { + Some(convert_try(&expressions[0], context)) + } ast::ExprKind::TupField(ref subexpr, _) | ast::ExprKind::Field(ref subexpr, _) | - ast::ExprKind::Try(ref subexpr) => Some(subexpr), + ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), _ => None, } } +fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { + match expr.node { + ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand => { + if let Some(subexpr) = convert_try_mac(mac, context) { + subexpr + } else { + expr.clone() + } + } + _ => expr.clone(), + } +} + // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite // `.c`. fn rewrite_chain_subexpr(expr: &ast::Expr, diff --git a/src/config.rs b/src/config.rs index 333835b66cd..5e4dbefad45 100644 --- a/src/config.rs +++ b/src/config.rs @@ -392,6 +392,7 @@ create_config! { match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; closure_block_indent_threshold: isize, 5, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; + use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; } diff --git a/src/expr.rs b/src/expr.rs index ba2ed7aec09..1edacbf765d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -148,7 +148,7 @@ impl Rewrite for ast::Expr { ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) } - // ast::ExprKind::Try(..) | + ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::TupField(..) | ast::ExprKind::MethodCall(..) => rewrite_chain(self, context, width, offset), @@ -205,15 +205,10 @@ impl Rewrite for ast::Expr { (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), } } - ast::ExprKind::Try(ref expr) => { - rewrite_unary_suffix(context, "?", &**expr, width, offset) - } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | - ast::ExprKind::InlineAsm(..) | - // TODO(#848): Handle type ascription - ast::ExprKind::Type(_, _) => { + ast::ExprKind::InlineAsm(..) => { wrap_str(context.snippet(self.span), context.config.max_width, width, @@ -1832,24 +1827,41 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let max_width = try_opt!(width.checked_sub(last_line_width + 1)); let rhs = ex.rewrite(&context, max_width, offset + last_line_width + 1); + fn count_line_breaks(src: &str) -> usize { + src.chars().filter(|&x| x == '\n').count() + } + match rhs { - Some(new_str) => { + Some(ref new_str) if count_line_breaks(new_str) < 2 => { result.push(' '); - result.push_str(&new_str) + result.push_str(new_str); } - None => { - // Expression did not fit on the same line as the identifier. Retry - // on the next line. + _ => { + // Expression did not fit on the same line as the identifier or is + // at least three lines big. Try splitting the line and see + // if that works better. let new_offset = offset.block_indent(context.config); - result.push_str(&format!("\n{}", new_offset.to_string(context.config))); - - // FIXME: we probably should related max_width to width instead of - // config.max_width where is the 1 coming from anyway? - let max_width = try_opt!(context.config.max_width.checked_sub(new_offset.width() + 1)); + let max_width = try_opt!((width + offset.width()).checked_sub(new_offset.width())); let inner_context = context.nested_context(); - let rhs = ex.rewrite(&inner_context, max_width, new_offset); - - result.push_str(&&try_opt!(rhs)); + let new_rhs = ex.rewrite(&inner_context, max_width, new_offset); + + // FIXME: DRY! + match (rhs, new_rhs) { + (Some(ref orig_rhs), Some(ref replacement_rhs)) + if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 => { + result.push_str(&format!("\n{}", new_offset.to_string(context.config))); + result.push_str(replacement_rhs); + } + (None, Some(ref final_rhs)) => { + result.push_str(&format!("\n{}", new_offset.to_string(context.config))); + result.push_str(final_rhs); + } + (None, None) => return None, + (Some(ref orig_rhs), _) => { + result.push(' '); + result.push_str(orig_rhs); + } + } } } diff --git a/src/macros.rs b/src/macros.rs index a0c7cd51bb7..e9992fb0eb0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -25,7 +25,7 @@ use syntax::parse::tts_to_parser; use syntax::codemap::{mk_sp, BytePos}; use Indent; -use rewrite::RewriteContext; +use rewrite::{Rewrite, RewriteContext}; use expr::{rewrite_call, rewrite_array}; use comment::{FindUncommented, contains_comment}; use utils::{CodeMapSpanUtils, wrap_str}; @@ -56,6 +56,12 @@ pub fn rewrite_macro(mac: &ast::Mac, width: usize, offset: Indent) -> Option { + if context.config.use_try_shorthand { + if let Some(expr) = convert_try_mac(mac, context) { + return expr.rewrite(context, width, offset); + } + } + let original_style = macro_style(mac, context); let macro_name = match extra_ident { None | @@ -141,6 +147,24 @@ pub fn rewrite_macro(mac: &ast::Mac, } } +/// Tries to convert a macro use into a short hand try expression. Returns None +/// when the macro is not an instance of try! (or parsing the inner expression +/// failed). +pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { + if &format!("{}", mac.node.path)[..] == "try" { + let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new()); + + Some(ast::Expr { + id: 0, // dummy value + node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())), + span: mac.span, // incorrect span, but shouldn't matter too much + attrs: None, + }) + } else { + None + } +} + fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { let snippet = context.snippet(mac.span); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 8ec5cd191c5..48de948865b 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -120,4 +120,8 @@ fn try_shorthand() { let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); let zzzz = expr?.another?.another?.another?.another?; let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??; + + let y = a.very .loooooooooooooooooooooooooooooooooooooong() .chain() + .inside() .weeeeeeeeeeeeeee()? .test() .0 + .x; } diff --git a/tests/source/try-conversion.rs b/tests/source/try-conversion.rs new file mode 100644 index 00000000000..addf2f5d5e8 --- /dev/null +++ b/tests/source/try-conversion.rs @@ -0,0 +1,11 @@ +// rustfmt-use_try_shorthand: true + +fn main() { + let x = try!(some_expr()); + + let y = try!(a.very.loooooooooooooooooooooooooooooooooooooong().chain().inside().weeeeeeeeeeeeeee()).test().0.x; +} + +fn test() { + a? +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 4c38ab7eb52..2298b5e1714 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -145,4 +145,13 @@ fn try_shorthand() { let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); let zzzz = expr?.another?.another?.another?.another?; let aaa = x??????????????????????????????????????????????????????????????????????????; + + let y = a.very + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; } diff --git a/tests/target/try-conversion.rs b/tests/target/try-conversion.rs new file mode 100644 index 00000000000..2daaba88490 --- /dev/null +++ b/tests/target/try-conversion.rs @@ -0,0 +1,18 @@ +// rustfmt-use_try_shorthand: true + +fn main() { + let x = some_expr()?; + + let y = a.very + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; +} + +fn test() { + a? +} -- cgit 1.4.1-3-g733a5 From eae2921e14d1cc71134ce9afcafd2cb3dc9543a2 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Thu, 12 May 2016 21:50:43 +0200 Subject: Bootstrap it. Hard. --- src/expr.rs | 55 ++++++++++++++++++------------------- src/items.rs | 35 ++++++++++------------- src/lib.rs | 7 ++--- src/lists.rs | 7 ++--- src/patterns.rs | 6 ++-- src/types.rs | 13 +++------ tests/source/expr.rs | 1 - tests/source/single-line-if-else.rs | 2 +- tests/source/string-lit-2.rs | 6 +--- tests/target/chains.rs | 21 ++++++-------- tests/target/closure.rs | 17 ++++-------- tests/target/expr.rs | 7 ++--- tests/target/hard-tabs.rs | 6 ++-- tests/target/single-line-if-else.rs | 2 +- tests/target/static.rs | 12 ++++---- tests/target/string-lit-2.rs | 6 +--- tests/target/try-conversion.rs | 14 +++++----- tests/target/type-ascription.rs | 5 ++-- 18 files changed, 88 insertions(+), 134 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1edacbf765d..ebe34400014 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -136,14 +136,20 @@ impl Rewrite for ast::Expr { Some(ident) => format!(" {}", ident.node), None => String::new(), }; - wrap_str(format!("continue{}", id_str), context.config.max_width, width, offset) + wrap_str(format!("continue{}", id_str), + context.config.max_width, + width, + offset) } ast::ExprKind::Break(ref opt_ident) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), None => String::new(), }; - wrap_str(format!("break{}", id_str), context.config.max_width, width, offset) + wrap_str(format!("break{}", id_str), + context.config.max_width, + width, + offset) } ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) @@ -684,11 +690,8 @@ fn extract_comment(span: Span, -> Option { let comment_str = context.snippet(span); if contains_comment(&comment_str) { - let comment = try_opt!(rewrite_comment(comment_str.trim(), - false, - width, - offset, - context.config)); + let comment = + try_opt!(rewrite_comment(comment_str.trim(), false, width, offset, context.config)); Some(format!("\n{indent}{}\n{indent}", comment, indent = offset.to_string(context.config))) @@ -788,14 +791,11 @@ fn rewrite_if_else(context: &RewriteContext, } }; - let between_if_else_block = mk_sp(if_block.span.hi, - context.codemap.span_before(mk_sp(if_block.span.hi, - else_block.span.lo), - "else")); - let between_if_else_block_comment = extract_comment(between_if_else_block, - &context, - offset, - width); + let between_if_else_block = + mk_sp(if_block.span.hi, + context.codemap.span_before(mk_sp(if_block.span.hi, else_block.span.lo), "else")); + let between_if_else_block_comment = + extract_comment(between_if_else_block, &context, offset, width); let after_else = mk_sp(context.codemap .span_after(mk_sp(if_block.span.hi, else_block.span.lo), @@ -922,11 +922,8 @@ fn rewrite_match_arm_comment(context: &RewriteContext, } let missed_str = missed_str[first..].trim(); if !missed_str.is_empty() { - let comment = try_opt!(rewrite_comment(&missed_str, - false, - width, - arm_indent, - context.config)); + let comment = + try_opt!(rewrite_comment(&missed_str, false, width, arm_indent, context.config)); result.push('\n'); result.push_str(arm_indent_str); result.push_str(&comment); @@ -1150,10 +1147,9 @@ impl Rewrite for ast::Arm { let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); let indent = context.block_indent.block_indent(context.config); let inner_context = &RewriteContext { block_indent: indent, ..*context }; - let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context, - body_budget, - indent), - body_budget)); + let next_line_body = + try_opt!(nop_block_collapse(body.rewrite(inner_context, body_budget, indent), + body_budget)); let indent_str = offset.block_indent(context.config).to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms { if context.config.match_block_trailing_comma { @@ -1766,10 +1762,10 @@ pub fn rewrite_unary_suffix(context: &RewriteContext, offset: Indent) -> Option { rewrite.rewrite(context, try_opt!(width.checked_sub(suffix.len())), offset) - .map(|mut r| { - r.push_str(suffix); - r - }) + .map(|mut r| { + r.push_str(suffix); + r + }) } fn rewrite_unary_op(context: &RewriteContext, @@ -1848,7 +1844,8 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // FIXME: DRY! match (rhs, new_rhs) { (Some(ref orig_rhs), Some(ref replacement_rhs)) - if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 => { + if count_line_breaks(orig_rhs) > + count_line_breaks(replacement_rhs) + 1 => { result.push_str(&format!("\n{}", new_offset.to_string(context.config))); result.push_str(replacement_rhs); } diff --git a/src/items.rs b/src/items.rs index f3b4d1859a1..b4b200e8b05 100644 --- a/src/items.rs +++ b/src/items.rs @@ -66,11 +66,8 @@ impl Rewrite for ast::Local { let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1)); // 1 = trailing semicolon; - result = try_opt!(rewrite_assign_rhs(&context, - result, - ex, - budget, - context.block_indent)); + result = + try_opt!(rewrite_assign_rhs(&context, result, ex, budget, context.block_indent)); } result.push(';'); @@ -656,18 +653,17 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); - let where_density = if (context.config.where_density == Density::Compressed && - (!result.contains('\n') || - context.config.fn_args_layout == FnArgLayoutStyle::Block)) || - (context.config.fn_args_layout == FnArgLayoutStyle::Block && - result.is_empty()) || - (context.config.where_density == Density::CompressedIfEmpty && - !has_body && - !result.contains('\n')) { - Density::Compressed - } else { - Density::Tall - }; + let where_density = + if (context.config.where_density == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout == FnArgLayoutStyle::Block)) || + (context.config.fn_args_layout == FnArgLayoutStyle::Block && result.is_empty()) || + (context.config.where_density == Density::CompressedIfEmpty && !has_body && + !result.contains('\n')) { + Density::Compressed + } else { + Density::Tall + }; let where_budget = try_opt!(context.config .max_width @@ -1134,9 +1130,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = try_opt!(l.rewrite(context, - usize::max_value(), - Indent::empty())); + let lifetime_str = + try_opt!(l.rewrite(context, usize::max_value(), Indent::empty())); Some(format!("&{} {}self", lifetime_str, mut_str)) } None => Some(format!("&{}self", mut_str)), diff --git a/src/lib.rs b/src/lib.rs index b825059ee20..61ac2626e02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -403,11 +403,8 @@ pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatR let mut summary = Summary::new(); let codemap = Rc::new(CodeMap::new()); - let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, - None, - true, - false, - codemap.clone()); + let tty_handler = + Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, codemap.clone()); let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); let main_file = match input { diff --git a/src/lists.rs b/src/lists.rs index f966e41ce99..b35ccfe3d69 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -307,11 +307,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option comment.trim().contains('\n') || comment.trim().len() > width; - let formatted_comment = try_opt!(rewrite_comment(comment, - block_style, - width, - offset, - formatting.config)); + let formatted_comment = + try_opt!(rewrite_comment(comment, block_style, width, offset, formatting.config)); result.push(' '); result.push_str(&formatted_comment); diff --git a/src/patterns.rs b/src/patterns.rs index ba3621fc6d5..4881ff76a99 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -144,10 +144,8 @@ impl Rewrite for Pat { |f| f.node.rewrite(context, budget, offset), context.codemap.span_after(self.span, "{"), self.span.hi); - let mut field_string = try_opt!(format_item_list(items, - budget, - offset, - context.config)); + let mut field_string = + try_opt!(format_item_list(items, budget, offset, context.config)); if elipses { if field_string.contains('\n') { field_string.push_str(",\n"); diff --git a/src/types.rs b/src/types.rs index cf65f4426b3..0ead12a9f98 100644 --- a/src/types.rs +++ b/src/types.rs @@ -375,12 +375,8 @@ impl Rewrite for ast::WherePredicate { // 3 = " = ".len() let used_width = 3 + ty_str.len(); let budget = try_opt!(width.checked_sub(used_width)); - let path_str = try_opt!(rewrite_path(context, - false, - None, - path, - budget, - offset + used_width)); + let path_str = + try_opt!(rewrite_path(context, false, None, path, budget, offset + used_width)); format!("{} = {}", path_str, ty_str) } }; @@ -538,9 +534,8 @@ impl Rewrite for ast::Ty { Some(match *lifetime { Some(ref lifetime) => { let lt_budget = try_opt!(width.checked_sub(2 + mut_len)); - let lt_str = try_opt!(lifetime.rewrite(context, - lt_budget, - offset + 2 + mut_len)); + let lt_str = + try_opt!(lifetime.rewrite(context, lt_budget, offset + 2 + mut_len)); let lt_len = lt_str.len(); let budget = try_opt!(width.checked_sub(2 + mut_len + lt_len)); format!("&{} {}{}", diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 16953a932a3..40fd3309a4c 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -249,7 +249,6 @@ fn ranges() { let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ... x ; - let infi_range_2 = ... ; a ... b diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs index 42629ab8e37..2f9c19086ff 100644 --- a/tests/source/single-line-if-else.rs +++ b/tests/source/single-line-if-else.rs @@ -36,7 +36,7 @@ fn main() { do_something() } - let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; diff --git a/tests/source/string-lit-2.rs b/tests/source/string-lit-2.rs index 8ba60ccac1d..c19df093176 100644 --- a/tests/source/string-lit-2.rs +++ b/tests/source/string-lit-2.rs @@ -1,9 +1,5 @@ fn main() -> &'static str { - let too_many_lines = "H\ - e\ - l\ - l\ - o"; + let too_many_lines = "Hello"; let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ s jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 2298b5e1714..7d25046279f 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -137,21 +137,18 @@ fn issue587() { fn try_shorthand() { let x = expr?; let y = expr.kaas()?.test(); - let loooooooooooooooooooooooooooooooooooooooooong = does_this? - .look? - .good? - .should_we_break? - .after_the_first_question_mark?; + let loooooooooooooooooooooooooooooooooooooooooong = + does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); let zzzz = expr?.another?.another?.another?.another?; let aaa = x??????????????????????????????????????????????????????????????????????????; let y = a.very - .loooooooooooooooooooooooooooooooooooooong() - .chain() - .inside() - .weeeeeeeeeeeeeee()? - .test() - .0 - .x; + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 5f40610d603..8fe290b955a 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -46,23 +46,18 @@ fn main() { do_something_else(); }; - let arg_test = |big_argument_name, test123| { - looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() - }; + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - let arg_test = |big_argument_name, test123| { - looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame() - }; + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); let simple_closure = move || -> () {}; let closure = |input: Ty| -> Option { foo() }; - let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, - aaaaaaaaaaaaaaaaaaaaaaarg2| - -> Strong { - "sup".to_owned() - }; + let closure_with_return_type = + |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; diff --git a/tests/target/expr.rs b/tests/target/expr.rs index e9a051711f5..1378b4bf8f8 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -202,10 +202,8 @@ fn arrays() { item: 3, }]); - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q]; + let z = + [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } @@ -273,7 +271,6 @@ fn ranges() { let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ...x; - let infi_range_2 = ...; a...b diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 0914959ceb1..1e00559b3f3 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -55,10 +55,8 @@ fn main() { .go_to_next_line_with_tab() .go_to_next_line_with_tab(); - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q]; + let z = + [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; fn generic(arg: T) -> &SomeType where T: Fn(// First arg diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs index 27b6d773da5..ec4daa727a6 100644 --- a/tests/target/single-line-if-else.rs +++ b/tests/target/single-line-if-else.rs @@ -41,7 +41,7 @@ fn main() { } let x = if veeeeeeeeery_loooooong_condition() { - aaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; diff --git a/tests/target/static.rs b/tests/target/static.rs index f3dbdad3e76..f2421c1444c 100644 --- a/tests/target/static.rs +++ b/tests/target/static.rs @@ -1,13 +1,11 @@ const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; -static boolnames: &'static [&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", - "km", "hs", "in", "db", "da", "mir", "msgr", "os", - "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", - "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", - "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", - "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", - "OTNL", "OTpt", "OTxr"]; +static boolnames: &'static [&'static str] = + &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", + "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", + "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", + "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; diff --git a/tests/target/string-lit-2.rs b/tests/target/string-lit-2.rs index c636f878ef1..7deb4215d2e 100644 --- a/tests/target/string-lit-2.rs +++ b/tests/target/string-lit-2.rs @@ -1,9 +1,5 @@ fn main() -> &'static str { - let too_many_lines = "H\ - e\ - l\ - l\ - o"; + let too_many_lines = "Hello"; let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ s jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; diff --git a/tests/target/try-conversion.rs b/tests/target/try-conversion.rs index 2daaba88490..d4422cf9621 100644 --- a/tests/target/try-conversion.rs +++ b/tests/target/try-conversion.rs @@ -4,13 +4,13 @@ fn main() { let x = some_expr()?; let y = a.very - .loooooooooooooooooooooooooooooooooooooong() - .chain() - .inside() - .weeeeeeeeeeeeeee()? - .test() - .0 - .x; + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; } fn test() { diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index 22f03713388..de8d97d7b67 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -1,7 +1,6 @@ fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + let xxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; -- cgit 1.4.1-3-g733a5 From 9b05461666273bd9d7d9da1fd7458b8c943d2298 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 15 May 2016 21:41:05 +1200 Subject: Write each file as it is formatted (#991) The old behaviour stored everything in memory until we were finished. Now we write as soon as we can. This gives better behaviour when formatting large programs, since there is some progress indication. It also opens the door to optimising memory use by not storing everything in memory unless it is required (which it still might be). That is left as future work though. --- Cargo.lock | 2 +- src/filemap.rs | 16 ++--- src/lib.rs | 216 +++++++++++++++++++++++++++++++------------------------- src/summary.rs | 1 + tests/system.rs | 19 +++-- 5 files changed, 143 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 71d4280ed93..162e9160f85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt" -version = "0.4.0" +version = "0.5.0" dependencies = [ "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/filemap.rs b/src/filemap.rs index 64c892a0929..17abc6f76e7 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -13,7 +13,6 @@ use strings::string_buffer::StringBuffer; -use std::collections::HashMap; use std::fs::{self, File}; use std::io::{self, Write, Read, stdout, BufWriter}; @@ -22,28 +21,27 @@ use rustfmt_diff::{make_diff, print_diff, Mismatch}; use checkstyle::{output_header, output_footer, output_checkstyle_file}; // A map of the files of a crate, with their new content -pub type FileMap = HashMap; +pub type FileMap = Vec; + +pub type FileRecord = (String, StringBuffer); // Append a newline to the end of each file. -pub fn append_newlines(file_map: &mut FileMap) { - for (_, s) in file_map.iter_mut() { - s.push_str("\n"); - } +pub fn append_newline(s: &mut StringBuffer) { + s.push_str("\n"); } pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error> where T: Write { output_header(out, config.write_mode).ok(); - for filename in file_map.keys() { - try!(write_file(&file_map[filename], filename, out, config)); + for &(ref filename, ref text) in file_map { + try!(write_file(text, filename, out, config)); } output_footer(out, config.write_mode).ok(); Ok(()) } - // Prints all newlines either as `\n` or as `\r\n`. pub fn write_system_newlines(writer: T, text: &StringBuffer, diff --git a/src/lib.rs b/src/lib.rs index 61ac2626e02..12258ada15c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,9 @@ use syntax::errors::{Handler, DiagnosticBuilder}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; -use std::io::{stdout, Write}; +use strings::string_buffer::StringBuffer; + +use std::io::{self, stdout, Write}; use std::ops::{Add, Sub}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -42,6 +44,7 @@ use issues::{BadIssueSeeker, Issue}; use filemap::FileMap; use visitor::FmtVisitor; use config::Config; +use checkstyle::{output_header, output_footer}; pub use self::summary::Summary; @@ -274,12 +277,16 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn format_ast(krate: &ast::Crate, - parse_session: &ParseSess, - main_file: &Path, - config: &Config) - -> FileMap { - let mut file_map = FileMap::new(); +fn format_ast(krate: &ast::Crate, + parse_session: &ParseSess, + main_file: &Path, + config: &Config, + mut after_file: F) + -> Result + where F: FnMut(&str, &mut StringBuffer) -> Result<(), io::Error> +{ + let mut result = FileMap::new(); + // We always skip children for the "Plain" write mode, since there is // nothing to distinguish the nested module contents. let skip_children = config.skip_children || config.write_mode == config::WriteMode::Plain; @@ -293,92 +300,86 @@ fn format_ast(krate: &ast::Crate, } let mut visitor = FmtVisitor::from_codemap(parse_session, config); visitor.format_separate_mod(module); - file_map.insert(path.to_owned(), visitor.buffer); + + try!(after_file(path, &mut visitor.buffer)); + + result.push((path.to_owned(), visitor.buffer)); } - file_map + + Ok(result) } // Formatting done on a char by char or line by line basis. -// TODO(#209) warn on bad license -// TODO(#20) other stuff for parity with make tidy -fn format_lines(file_map: &mut FileMap, config: &Config) -> FormatReport { - let mut truncate_todo = Vec::new(); - let mut report = FormatReport::new(); - +// FIXME(#209) warn on bad license +// FIXME(#20) other stuff for parity with make tidy +fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &mut FormatReport) { // Iterate over the chars in the file map. - for (f, text) in file_map.iter() { - let mut trims = vec![]; - let mut last_wspace: Option = None; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo, config.report_fixme); - - for (c, b) in text.chars() { - if c == '\r' { - line_len += c.len_utf8(); - continue; - } + let mut trims = vec![]; + let mut last_wspace: Option = None; + let mut line_len = 0; + let mut cur_line = 1; + let mut newline_count = 0; + let mut errors = vec![]; + let mut issue_seeker = BadIssueSeeker::new(config.report_todo, config.report_fixme); + + for (c, b) in text.chars() { + if c == '\r' { + line_len += c.len_utf8(); + continue; + } - // Add warnings for bad todos/ fixmes - if let Some(issue) = issue_seeker.inspect(c) { + // Add warnings for bad todos/ fixmes + if let Some(issue) = issue_seeker.inspect(c) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::BadIssue(issue), + }); + } + + if c == '\n' { + // Check for (and record) trailing whitespace. + if let Some(lw) = last_wspace { + trims.push((cur_line, lw, b)); + line_len -= b - lw; + } + // Check for any line width errors we couldn't correct. + if line_len > config.max_width { errors.push(FormattingError { line: cur_line, - kind: ErrorKind::BadIssue(issue), + kind: ErrorKind::LineOverflow, }); } - - if c == '\n' { - // Check for (and record) trailing whitespace. - if let Some(lw) = last_wspace { - trims.push((cur_line, lw, b)); - line_len -= b - lw; - } - // Check for any line width errors we couldn't correct. - if line_len > config.max_width { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LineOverflow, - }); + line_len = 0; + cur_line += 1; + newline_count += 1; + last_wspace = None; + } else { + newline_count = 0; + line_len += c.len_utf8(); + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(b); } - line_len = 0; - cur_line += 1; - newline_count += 1; - last_wspace = None; } else { - newline_count = 0; - line_len += c.len_utf8(); - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(b); - } - } else { - last_wspace = None; - } + last_wspace = None; } } + } - if newline_count > 1 { - debug!("track truncate: {} {} {}", f, text.len, newline_count); - truncate_todo.push((f.to_owned(), text.len - newline_count + 1)) - } - - for &(l, _, _) in &trims { - errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - }); - } - - report.file_error_map.insert(f.to_owned(), errors); + if newline_count > 1 { + debug!("track truncate: {} {}", text.len, newline_count); + let line = text.len - newline_count + 1; + text.truncate(line); } - for (f, l) in truncate_todo { - file_map.get_mut(&f).unwrap().truncate(l); + for &(l, _, _) in &trims { + errors.push(FormattingError { + line: l, + kind: ErrorKind::TrailingWhitespace, + }); } - report + report.file_error_map.insert(name.to_owned(), errors); } fn parse_input(input: Input, @@ -399,7 +400,10 @@ fn parse_input(input: Input, result.map_err(|e| Some(e)) } -pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatReport) { +pub fn format_input(input: Input, + config: &Config, + mut out: Option<&mut T>) + -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { let mut summary = Summary::new(); let codemap = Rc::new(CodeMap::new()); @@ -419,7 +423,7 @@ pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatR diagnostic.emit(); } summary.add_parsing_error(); - return (summary, FileMap::new(), FormatReport::new()); + return Ok((summary, FileMap::new(), FormatReport::new())); } }; @@ -431,17 +435,33 @@ pub fn format_input(input: Input, config: &Config) -> (Summary, FileMap, FormatR let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - let mut file_map = format_ast(&krate, &parse_session, &main_file, config); + let mut report = FormatReport::new(); + + match format_ast(&krate, + &parse_session, + &main_file, + config, + |file_name, file| { + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(file); + + format_lines(file, file_name, config, &mut report); - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newlines(&mut file_map); + if let Some(ref mut out) = out { + try!(filemap::write_file(file, file_name, out, config)); + } + Ok(()) + }) { + Ok(file_map) => { + if report.has_warnings() { + summary.add_formatting_error(); + } - let report = format_lines(&mut file_map, config); - if report.has_warnings() { - summary.add_formatting_error(); + Ok((summary, file_map, report)) + } + Err(e) => Err((e, summary)), } - (summary, file_map, report) } pub enum Input { @@ -450,18 +470,22 @@ pub enum Input { } pub fn run(input: Input, config: &Config) -> Summary { - let (mut summary, file_map, report) = format_input(input, config); - if report.has_warnings() { - msg!("{}", report); - } - - let mut out = stdout(); - let write_result = filemap::write_all_files(&file_map, &mut out, config); + let mut out = &mut stdout(); + output_header(out, config.write_mode).ok(); + match format_input(input, config, Some(out)) { + Ok((summary, _, report)) => { + output_footer(out, config.write_mode).ok(); + + if report.has_warnings() { + msg!("{}", report); + } - if let Err(msg) = write_result { - msg!("Error writing files: {}", msg); - summary.add_operational_error(); + summary + } + Err((msg, mut summary)) => { + msg!("Error writing files: {}", msg); + summary.add_operational_error(); + summary + } } - - summary } diff --git a/src/summary.rs b/src/summary.rs index 5e5c0a579af..87d20899a58 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -1,4 +1,5 @@ #[must_use] +#[derive(Debug, Clone)] pub struct Summary { // Encountered e.g. an IO error. has_operational_errors: bool, diff --git a/tests/system.rs b/tests/system.rs index 1af9c0f3462..38d1e8584a5 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -143,9 +143,16 @@ fn self_tests() { fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); let config = Config::default(); - let (error_summary, file_map, _report) = format_input(input, &config); + let (error_summary, file_map, _report) = format_input::(input, &config, None) + .unwrap(); assert!(error_summary.has_no_errors()); - assert_eq!(file_map["stdin"].to_string(), "fn main() {}\n") + for &(ref file_name, ref text) in &file_map { + if file_name == "stdin" { + assert!(text.to_string() == "fn main() {}\n"); + return; + } + } + panic!("no stdin"); } #[test] @@ -153,7 +160,8 @@ fn format_lines_errors_are_reported() { let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let config = Config::default(); - let (error_summary, _file_map, _report) = format_input(input, &config); + let (error_summary, _file_map, _report) = format_input::(input, &config, None) + .unwrap(); assert!(error_summary.has_formatting_errors()); } @@ -212,7 +220,8 @@ fn read_config(filename: &str) -> Config { fn format_file>(filename: P, config: &Config) -> (FileMap, FormatReport) { let input = Input::File(filename.into()); - let (_error_summary, file_map, report) = format_input(input, &config); + let (_error_summary, file_map, report) = format_input::(input, &config, None) + .unwrap(); return (file_map, report); } @@ -222,7 +231,7 @@ pub fn idempotent_check(filename: String) -> Result Date: Sun, 15 May 2016 22:19:44 +0530 Subject: change normalise spelling to American version - normalize as American english is more common across programming community --- src/comment.rs | 2 +- src/config.rs | 2 +- tests/source/comment4.rs | 2 +- tests/target/comment4.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 83ea21b91e8..e417e29936e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -31,7 +31,7 @@ pub fn rewrite_comment(orig: &str, // Edge case: block comments. Let's not trim their lines (for now). let (opener, closer, line_start) = if block_style { ("/* ", " */", " * ") - } else if !config.normalise_comments { + } else if !config.normalize_comments { if orig.starts_with("/**") { ("/** ", " **/", " ** ") } else if orig.starts_with("/*!") { diff --git a/src/config.rs b/src/config.rs index 5e4dbefad45..8e8f4bd2f3d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -385,7 +385,7 @@ create_config! { take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; - normalise_comments: bool, true, "Convert /* */ comments to // comments where possible"; + normalize_comments: bool, true, "Convert /* */ comments to // comments where possible"; wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index 7fef084fc7b..81754f93c4c 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -1,4 +1,4 @@ -// rustfmt-normalise_comments: false +// rustfmt-normalize_comments: false //! Doc comment fn test() { diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index 85edc7f06d4..c4d25ca1143 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -1,4 +1,4 @@ -// rustfmt-normalise_comments: false +// rustfmt-normalize_comments: false //! Doc comment fn test() { -- cgit 1.4.1-3-g733a5 From d0720a00a1f708bb495535d361a1a63f65234fc7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 May 2016 09:25:57 +1200 Subject: Fall back to basic stdout if we can't unwrap a fancy terminal (#995) fixes #978 --- src/rustfmt_diff.rs | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 9f529276df1..fe521029cb5 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -1,6 +1,7 @@ use std::collections::VecDeque; use diff; use term; +use std::io; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -87,8 +88,18 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F) where F: Fn(u32) -> String { - let mut t = term::stdout().unwrap(); + if let Some(t) = term::stdout() { + print_diff_fancy(diff, get_section_title, t); + } else { + print_diff_basic(diff, get_section_title); + } +} +fn print_diff_fancy(diff: Vec, + get_section_title: F, + mut t: Box>) + where F: Fn(u32) -> String +{ for mismatch in diff { let title = get_section_title(mismatch.line_number); writeln!(t, "{}", title).unwrap(); @@ -112,3 +123,26 @@ pub fn print_diff(diff: Vec, get_section_title: F) t.reset().unwrap(); } } + +pub fn print_diff_basic(diff: Vec, get_section_title: F) + where F: Fn(u32) -> String +{ + for mismatch in diff { + let title = get_section_title(mismatch.line_number); + println!("{}", title); + + for line in mismatch.lines { + match line { + DiffLine::Context(ref str) => { + println!(" {}⏎", str); + } + DiffLine::Expected(ref str) => { + println!("+{}⏎", str); + } + DiffLine::Resulting(ref str) => { + println!("-{}⏎", str); + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From ff3ff5aa873efdb113758d4f6d950c07786e5e72 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 May 2016 09:58:51 +1200 Subject: Handle parser errors better --- src/lib.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 12258ada15c..69f9aaebbb7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -392,12 +392,17 @@ fn parse_input(input: Input, } }; - // Bail out if the parser recovered from an error. - if parse_session.span_diagnostic.has_errors() { - return Err(None); + match result { + Ok(c) => { + if parse_session.span_diagnostic.has_errors() { + // Bail out if the parser recovered from an error. + Err(None) + } else { + Ok(c) + } + } + Err(e) => Err(Some(e)), } - - result.map_err(|e| Some(e)) } pub fn format_input(input: Input, -- cgit 1.4.1-3-g733a5 From 9589cac62d54fa199524b6110df67f626ed3bdfa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 19 May 2016 08:36:59 +1200 Subject: Format inline attributes on out-of-line modules (#996) Fixes #838 --- src/visitor.rs | 27 ++++++++++++++++++++++++--- tests/source/mod-2.rs | 2 +- tests/target/mod-2.rs | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 83108897684..48a1a778c20 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -185,20 +185,41 @@ impl<'a> FmtVisitor<'a> { } fn visit_item(&mut self, item: &ast::Item) { - // Only look at attributes for modules (except for rustfmt_skip) if the - // module is inline. We want to avoid looking at attributes in another - // file, which the AST doesn't distinguish. + // This is where we bail out if there is a skip attribute. This is only + // complex in the module case. It is complex because the module could be + // in a seperate file and there might be attributes in both files, but + // the AST lumps them all together. match item.node { ast::ItemKind::Mod(ref m) => { let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; let inner_file = self.codemap.lookup_char_pos(m.inner.lo).file; if outer_file.name == inner_file.name { + // Module is inline, in this case we treat modules like any + // other item. if self.visit_attrs(&item.attrs) { self.push_rewrite(item.span, None); return; } } else if utils::contains_skip(&item.attrs) { + // Module is not inline, but should be skipped. return; + } else { + // Module is not inline and should not be skipped. We want + // to process only the attributes in the current file. + let attrs = item.attrs + .iter() + .filter_map(|a| { + let attr_file = self.codemap.lookup_char_pos(a.span.lo).file; + if attr_file.name == outer_file.name { + Some(a.clone()) + } else { + None + } + }) + .collect::>(); + // Assert because if we should skip it should be caught by + // the above case. + assert!(!self.visit_attrs(&attrs)); } } _ => { diff --git a/tests/source/mod-2.rs b/tests/source/mod-2.rs index 00b70e972cd..7202e00203e 100644 --- a/tests/source/mod-2.rs +++ b/tests/source/mod-2.rs @@ -1,4 +1,4 @@ // Some nested mods - mod nestedmod ; +#[cfg(test)] mod nestedmod ; pub mod no_new_line_beginning; diff --git a/tests/target/mod-2.rs b/tests/target/mod-2.rs index 426c266cecf..1a093bd5201 100644 --- a/tests/target/mod-2.rs +++ b/tests/target/mod-2.rs @@ -1,4 +1,5 @@ // Some nested mods +#[cfg(test)] mod nestedmod; pub mod no_new_line_beginning; -- cgit 1.4.1-3-g733a5 From 775de8a62b3c19521543cb6b9130979eb6747c75 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 19 May 2016 08:38:49 +1200 Subject: Optionally put short struct variants on one line (#997) Closes #418 --- src/config.rs | 2 ++ src/issues.rs | 10 ++------- src/items.rs | 40 ++++++++++++++++++++++++---------- src/visitor.rs | 3 ++- tests/target/enum-no_trailing_comma.rs | 18 ++++----------- tests/target/enum.rs | 24 +++++--------------- tests/target/where-trailing-comma.rs | 4 +--- 7 files changed, 44 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 8e8f4bd2f3d..e4d0e4517c2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -334,6 +334,8 @@ create_config! { "Maximum width of the args of a function call before falling back to vertical formatting"; struct_lit_width: usize, 16, "Maximum width in the body of a struct lit before falling back to vertical formatting"; + struct_variant_width: usize, 35, + "Maximum width in the body of a struct variant before falling back to vertical formatting"; force_explicit_abi: bool, true, "Always print the abi for extern items"; newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; diff --git a/src/issues.rs b/src/issues.rs index 40b09fdfca5..64797de2fda 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -32,14 +32,8 @@ impl ReportTactic { #[derive(Clone, Copy)] enum Seeking { - Issue { - todo_idx: usize, - fixme_idx: usize, - }, - Number { - issue: Issue, - part: NumberPart, - }, + Issue { todo_idx: usize, fixme_idx: usize }, + Number { issue: Issue, part: NumberPart }, } #[derive(Clone, Copy)] diff --git a/src/items.rs b/src/items.rs index b4b200e8b05..5c5e9923b32 100644 --- a/src/items.rs +++ b/src/items.rs @@ -14,7 +14,7 @@ use Indent; use utils::{CodeMapSpanUtils, format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, - DefinitiveListTactic, definitive_tactic, format_item_list}; + DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; @@ -419,7 +419,8 @@ impl<'a> FmtVisitor<'a> { &field.node.data, None, field.span, - indent) + indent, + Some(self.config.struct_variant_width)) } ast::VariantData::Unit(..) => { let tag = if let Some(ref expr) = field.node.disr_expr { @@ -588,7 +589,8 @@ pub fn format_struct(context: &RewriteContext, struct_def: &ast::VariantData, generics: Option<&ast::Generics>, span: Span, - offset: Indent) + offset: Indent, + one_line_width: Option) -> Option { match *struct_def { ast::VariantData::Unit(..) => format_unit_struct(item_name, ident, vis), @@ -610,7 +612,8 @@ pub fn format_struct(context: &RewriteContext, fields, generics, span, - offset) + offset, + one_line_width) } } } @@ -758,7 +761,8 @@ fn format_struct_struct(context: &RewriteContext, fields: &[ast::StructField], generics: Option<&ast::Generics>, span: Span, - offset: Indent) + offset: Indent, + one_line_width: Option) -> Option { let mut result = String::with_capacity(1024); @@ -813,11 +817,18 @@ fn format_struct_struct(context: &RewriteContext, |field| field.ty.span.hi, |field| field.rewrite(context, item_budget, item_indent), context.codemap.span_after(span, "{"), - span.hi); + span.hi) + .collect::>(); // 1 = , let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1; + + let tactic = match one_line_width { + Some(w) => definitive_tactic(&items, ListTactic::LimitedHorizontalVertical(w), budget), + None => DefinitiveListTactic::Vertical, + }; + let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, + tactic: tactic, separator: ",", trailing_separator: context.config.struct_trailing_comma, indent: item_indent, @@ -825,11 +836,16 @@ fn format_struct_struct(context: &RewriteContext, ends_with_newline: true, config: context.config, }; - Some(format!("{}\n{}{}\n{}}}", - result, - offset.block_indent(context.config).to_string(context.config), - try_opt!(write_list(items, &fmt)), - offset.to_string(context.config))) + let items_str = try_opt!(write_list(&items, &fmt)); + if one_line_width.is_some() && !items_str.contains('\n') { + Some(format!("{} {} }}", result, items_str)) + } else { + Some(format!("{}\n{}{}\n{}}}", + result, + offset.block_indent(context.config).to_string(context.config), + items_str, + offset.to_string(context.config))) + } } fn format_tuple_struct(context: &RewriteContext, diff --git a/src/visitor.rs b/src/visitor.rs index 48a1a778c20..fb508f64164 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -267,7 +267,8 @@ impl<'a> FmtVisitor<'a> { def, Some(generics), item.span, - indent) + indent, + None) .map(|s| { match *def { ast::VariantData::Tuple(..) => s + ";", diff --git a/tests/target/enum-no_trailing_comma.rs b/tests/target/enum-no_trailing_comma.rs index 4ad7d1f12d7..2e5a5ad23e3 100644 --- a/tests/target/enum-no_trailing_comma.rs +++ b/tests/target/enum-no_trailing_comma.rs @@ -21,21 +21,11 @@ enum TupY { } enum StructX { - A { - s: u16, - }, - B { - u: u32, - i: i32, - } + A { s: u16 }, + B { u: u32, i: i32 } } enum StructY { - A { - s: u16, - }, - B { - u: u32, - i: i32, - } + A { s: u16 }, + B { u: u32, i: i32 } } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index ae1bc4bc276..aa51b90a79e 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -42,9 +42,7 @@ enum StructLikeVariants { #[Attr50] y: SomeType, // Aanother Comment }, - SL { - a: A, - }, + SL { a: A }, } enum X { @@ -64,10 +62,7 @@ pub enum EnumWithAttributes { SkippedItem(String,String,), // Post-comment #[another_attr] #[attr2] - ItemStruct { - x: usize, - y: usize, - }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + ItemStruct { x: usize, y: usize }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ // And another ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ @@ -81,24 +76,15 @@ pub enum SingleTuple { } pub enum SingleStruct { - Match { - name: String, - loc: usize, - }, // Post-comment + Match { name: String, loc: usize }, // Post-comment } pub enum GenericEnum where I: Iterator { // Pre Comment - Left { - list: I, - root: T, - }, // Post-comment - Right { - list: I, - root: T, - }, // Post Comment + Left { list: I, root: T }, // Post-comment + Right { list: I, root: T }, // Post Comment } diff --git a/tests/target/where-trailing-comma.rs b/tests/target/where-trailing-comma.rs index c8682237ae6..4d4d19cdef8 100644 --- a/tests/target/where-trailing-comma.rs +++ b/tests/target/where-trailing-comma.rs @@ -33,9 +33,7 @@ enum E where S: P, T: P, { - A { - a: T, - }, + A { a: T }, } type Double -- cgit 1.4.1-3-g733a5 From d6bcfceb7e122ab86009ea36ff01388e613ca353 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 May 2016 20:33:19 +1200 Subject: Don't put a newline before `?` when it is the second sub-expression in a chain (#1012) Fixes #1003 --- src/chains.rs | 4 +++- tests/source/chains.rs | 8 ++++++++ tests/target/chains.rs | 10 ++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3f306abfdca..faf368d41c1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -179,7 +179,9 @@ pub fn rewrite_chain(expr: &ast::Expr, format!("\n{}", indent.to_string(context.config)) }; - let first_connector = if extend { + let first_connector = if extend || subexpr_list.len() == 0 { + "" + } else if let ast::ExprKind::Try(_) = subexpr_list[0].node { "" } else { &*connector diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 48de948865b..66c982082e7 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -124,4 +124,12 @@ fn try_shorthand() { let y = a.very .loooooooooooooooooooooooooooooooooooooong() .chain() .inside() .weeeeeeeeeeeeeee()? .test() .0 .x; + + parameterized(f, + substs, + def_id, + Ns::Value, + &[], + |tcx| tcx.lookup_item_type(def_id).generics)?; + fooooooooooooooooooooooooooo()?.bar()?.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; } diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 7d25046279f..3004946fb56 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -151,4 +151,14 @@ fn try_shorthand() { .test() .0 .x; + + parameterized(f, + substs, + def_id, + Ns::Value, + &[], + |tcx| tcx.lookup_item_type(def_id).generics)?; + fooooooooooooooooooooooooooo()? + .bar()? + .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; } -- cgit 1.4.1-3-g733a5 From 882ef8cc8249430027c5cea8f5cc65a9d35e9210 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 May 2016 11:49:26 +1200 Subject: Fix off by 2 error in function sigs Fixes #1000 This is a little conservative in some cases, but better than being wrong in others. --- src/items.rs | 18 +++++++++--------- tests/target/fn-custom.rs | 4 ++-- tests/target/fn.rs | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5c5e9923b32..46446eda779 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1301,7 +1301,7 @@ fn rewrite_fn_base(context: &RewriteContext, // Args. let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = - compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace); + try_opt!(compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace)); if context.config.fn_args_layout == FnArgLayoutStyle::Block || context.config.fn_args_layout == FnArgLayoutStyle::BlockAlways { @@ -1617,7 +1617,7 @@ fn compute_budgets_for_args(context: &RewriteContext, indent: Indent, ret_str_len: usize, newline_brace: bool) - -> (usize, usize, Indent) { + -> Option<((usize, usize, Indent))> { // Try keeping everything on the same line. if !result.contains("\n") { // 3 = `() `, space is before ret_string. @@ -1628,23 +1628,23 @@ fn compute_budgets_for_args(context: &RewriteContext, let one_line_budget = context.config.max_width.checked_sub(used_space).unwrap_or(0); if one_line_budget > 0 { - let multi_line_budget = context.config.max_width - - (indent.width() + result.len() + "()".len()); + // 4 = "() {".len() + let multi_line_budget = + try_opt!(context.config.max_width.checked_sub(indent.width() + result.len() + 4)); - return (one_line_budget, multi_line_budget, indent + result.len() + 1); + return Some((one_line_budget, multi_line_budget, indent + result.len() + 1)); } } // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(context.config); - let used_space = new_indent.width() + 2; // account for `(` and `)` + let used_space = new_indent.width() + 4; // Account for `(` and `)` and possibly ` {`. let max_space = context.config.max_width; if used_space <= max_space { - (0, max_space - used_space, new_indent) + Some((0, max_space - used_space, new_indent)) } else { // Whoops! bankrupt. - // FIXME: take evasive action, perhaps kill the indent or something. - panic!("in compute_budgets_for_args"); + None } } diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index c991142fa6c..ad36de7a997 100644 --- a/tests/target/fn-custom.rs +++ b/tests/target/fn-custom.rs @@ -2,8 +2,8 @@ // Test some of the ways function signatures can be customised. // Test compressed layout of args. -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee) { +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { foo(); } diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 02600f43f2a..9ba150d6115 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -88,3 +88,18 @@ fn ______________________baz(a: i32) arg3: i32) -> ()> { } + +pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option)) { +} + +pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, + Span, + &Option<&Stability>, + &Option)) { +} -- cgit 1.4.1-3-g733a5 From 0fae34dfa1e969052782831e39c5eb111e92502f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 May 2016 10:39:28 +1200 Subject: Don't ignore universal quantification in function types Fixes #1006 --- Cargo.lock | 62 +++++++++++++++++++++++++++++++--------------------- src/patterns.rs | 1 - src/types.rs | 13 +++++++++++ tests/source/type.rs | 2 ++ tests/target/type.rs | 2 ++ 5 files changed, 54 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 162e9160f85..e1ca0e05ddd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,18 +6,18 @@ dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.63 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -39,7 +39,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.63 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -49,16 +49,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "kernel32-sys" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -71,29 +71,24 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "mempool" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex" -version = "0.1.63" +version = "0.1.71" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mempool 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -115,7 +110,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -127,8 +122,8 @@ name = "term" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -136,13 +131,30 @@ name = "term" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread-id" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -165,7 +177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] diff --git a/src/patterns.rs b/src/patterns.rs index 4881ff76a99..837fecd83ce 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -28,7 +28,6 @@ impl Rewrite for Pat { }; let mut_infix = format_mutability(mutability); let id_str = ident.node.to_string(); - let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. diff --git a/src/types.rs b/src/types.rs index 0ead12a9f98..8dd8c09959b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -600,6 +600,19 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, -> Option { let mut result = String::with_capacity(128); + if !bare_fn.lifetimes.is_empty() { + result.push_str("for<"); + // 6 = "for<> ".len(), 4 = "for<". + // This doesn't work out so nicely for mutliline situation with lots of + // rightward drift. If that is a problem, we could use the list stuff. + result.push_str(&try_opt!(bare_fn.lifetimes + .iter() + .map(|l| l.rewrite(context, try_opt!(width.checked_sub(6)), offset + 4)) + .collect::>>()) + .join(", ")); + result.push_str("> "); + } + result.push_str(&::utils::format_unsafety(bare_fn.unsafety)); if bare_fn.abi != abi::Abi::Rust { diff --git a/tests/source/type.rs b/tests/source/type.rs index dcb8e0d0f31..92da1010641 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -12,3 +12,5 @@ struct F { i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3 z: Foo, /* comment */ .../* comment 2*/ ), } + +fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} diff --git a/tests/target/type.rs b/tests/target/type.rs index 1ae1143bcca..75655c913ec 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -21,3 +21,5 @@ struct F { // comment ... /* comment 2 */), } + +fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} -- cgit 1.4.1-3-g733a5 From 66cac1f3e9c26a6ef85a0ebe6b2249631976b42b Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sat, 28 May 2016 00:58:25 +0200 Subject: Handle pub(restricted) (#1013) * Handle pub(restricted) This commit properly handles pub(restricted) as introduced in RFC 1422 [0]. The syntax support was added in #971, but they were not correctly formatted. [0] https://github.com/rust-lang/rfcs/blob/master/text/1422-pub-restricted.md Fixes #970 * Drop #[inline] attribute on format_visibility * Make newly non-failing functions return String The change to `format_visibiilty` means that `format_header` and `format_unit_struct` can no longer fail. Their return type is updated to reflect that. --- Cargo.lock | 6 +++++ Cargo.toml | 1 + src/items.rs | 43 +++++++++++++---------------------- src/lib.rs | 1 + src/utils.rs | 28 ++++++++++++++++------- src/visitor.rs | 9 ++------ tests/source/pub-restricted.rs | 51 ++++++++++++++++++++++++++++++++++++++++++ tests/target/pub-restricted.rs | 51 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 147 insertions(+), 43 deletions(-) create mode 100644 tests/source/pub-restricted.rs create mode 100644 tests/target/pub-restricted.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index e1ca0e05ddd..1999f6c811a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,6 +5,7 @@ dependencies = [ "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -47,6 +48,11 @@ name = "getopts" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "itertools" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index 6fe6bc05d56..b0964c03704 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,4 @@ syntex_syntax = "0.32" log = "0.3" env_logger = "0.3" getopts = "0.2" +itertools = "0.4.15" diff --git a/src/items.rs b/src/items.rs index 46446eda779..b55ecd5c0ef 100644 --- a/src/items.rs +++ b/src/items.rs @@ -139,10 +139,7 @@ impl<'a> FmtVisitor<'a> { ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. - let vis = match format_visibility(&item.vis) { - Some(s) => s, - None => return, - }; + let vis = format_visibility(&item.vis); let mut_str = if is_mutable { "mut " } else { @@ -305,11 +302,7 @@ impl<'a> FmtVisitor<'a> { enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span) { - let header_str = match format_header("enum ", ident, vis) { - Some(s) => s, - None => return, - }; - self.buffer.push_str(&header_str); + self.buffer.push_str(&format_header("enum ", ident, vis)); let enum_snippet = self.snippet(span); let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); @@ -453,7 +446,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - ref self_ty, ref items) = item.node { let mut result = String::new(); - result.push_str(try_opt!(format_visibility(&item.vis))); + result.push_str(&*format_visibility(&item.vis)); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); @@ -593,7 +586,7 @@ pub fn format_struct(context: &RewriteContext, one_line_width: Option) -> Option { match *struct_def { - ast::VariantData::Unit(..) => format_unit_struct(item_name, ident, vis), + ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)), ast::VariantData::Tuple(ref fields, _) => { format_tuple_struct(context, item_name, @@ -623,7 +616,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) item.node { let mut result = String::new(); let header = format!("{}{}trait {}", - try_opt!(format_visibility(&item.vis)), + format_visibility(&item.vis), format_unsafety(unsafety), item.ident); @@ -744,14 +737,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } -fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> Option { - let mut result = String::with_capacity(1024); - - let header_str = try_opt!(format_header(item_name, ident, vis)); - result.push_str(&header_str); - result.push(';'); - - Some(result) +fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { + format!("{};", format_header(item_name, ident, vis)) } fn format_struct_struct(context: &RewriteContext, @@ -766,7 +753,7 @@ fn format_struct_struct(context: &RewriteContext, -> Option { let mut result = String::with_capacity(1024); - let header_str = try_opt!(format_header(item_name, ident, vis)); + let header_str = format_header(item_name, ident, vis); result.push_str(&header_str); let body_lo = context.codemap.span_after(span, "{"); @@ -859,7 +846,7 @@ fn format_tuple_struct(context: &RewriteContext, -> Option { let mut result = String::with_capacity(1024); - let header_str = try_opt!(format_header(item_name, ident, vis)); + let header_str = format_header(item_name, ident, vis); result.push_str(&header_str); // FIXME(#919): don't lose comments on empty tuple structs. @@ -945,7 +932,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, -> Option { let mut result = String::new(); - result.push_str(&try_opt!(format_visibility(&vis))); + result.push_str(&format_visibility(&vis)); result.push_str("type "); result.push_str(&ident.to_string()); @@ -1013,7 +1000,7 @@ impl Rewrite for ast::StructField { } let name = self.ident; - let vis = try_opt!(format_visibility(&self.vis)); + let vis = format_visibility(&self.vis); let mut attr_str = try_opt!(self.attrs .rewrite(context, context.config.max_width - offset.width(), offset)); if !attr_str.is_empty() { @@ -1042,7 +1029,7 @@ pub fn rewrite_static(prefix: &str, context: &RewriteContext) -> Option { let prefix = format!("{}{} {}{}: ", - try_opt!(format_visibility(vis)), + format_visibility(vis), prefix, format_mutability(mutability), ident); @@ -1260,7 +1247,7 @@ fn rewrite_fn_base(context: &RewriteContext, let mut result = String::with_capacity(1024); // Vis unsafety abi. - result.push_str(try_opt!(format_visibility(vis))); + result.push_str(&*format_visibility(vis)); if let ast::Constness::Const = constness { result.push_str("const "); @@ -1816,8 +1803,8 @@ fn rewrite_where_clause(context: &RewriteContext, } } -fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> Option { - Some(format!("{}{}{}", try_opt!(format_visibility(vis)), item_name, ident)) +fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { + format!("{}{}{}", format_visibility(vis), item_name, ident) } fn format_generics(context: &RewriteContext, diff --git a/src/lib.rs b/src/lib.rs index 69f9aaebbb7..e672efb8fea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ extern crate unicode_segmentation; extern crate regex; extern crate diff; extern crate term; +extern crate itertools; use syntax::ast; use syntax::codemap::{mk_sp, CodeMap, Span}; diff --git a/src/utils.rs b/src/utils.rs index c7d4dd55469..cb286723cc9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; use std::cmp::Ordering; -use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind}; +use itertools::Itertools; + +use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, Path}; use syntax::codemap::{CodeMap, Span, BytePos}; use syntax::abi; @@ -66,14 +69,23 @@ pub fn extra_offset(text: &str, offset: Indent) -> usize { } } -#[inline] -pub fn format_visibility(vis: &Visibility) -> Option<&'static str> { +// Uses Cow to avoid allocating in the common cases. +pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { match *vis { - Visibility::Public => Some("pub "), - Visibility::Inherited => Some(""), - // FIXME(#970): Handle new visibility types. - Visibility::Crate(_) => None, - Visibility::Restricted { .. } => None, + Visibility::Public => Cow::from("pub "), + Visibility::Inherited => Cow::from(""), + Visibility::Crate(_) => Cow::from("pub(crate) "), + Visibility::Restricted { ref path, .. } => { + let Path { global, ref segments, .. } = **path; + let prefix = if global { + "::" + } else { + "" + }; + let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.as_str()); + + Cow::from(format!("pub({}{}) ", prefix, segments_iter.join("::"))) + } } } diff --git a/src/visitor.rs b/src/visitor.rs index fb508f64164..8473d1685da 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -502,9 +502,7 @@ impl<'a> FmtVisitor<'a> { let local_file_name = self.codemap.span_to_filename(s); let is_internal = local_file_name == self.codemap.span_to_filename(source!(self, m.inner)); - if let Some(vis) = utils::format_visibility(vis) { - self.buffer.push_str(vis); - } + self.buffer.push_str(&*utils::format_visibility(vis)); self.buffer.push_str("mod "); self.buffer.push_str(&ident.to_string()); @@ -540,10 +538,7 @@ impl<'a> FmtVisitor<'a> { } fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { - let vis = match utils::format_visibility(vis) { - Some(s) => s, - None => return, - }; + let vis = utils::format_visibility(vis); let mut offset = self.block_indent; offset.alignment += vis.len() + "use ".len(); // 1 = ";" diff --git a/tests/source/pub-restricted.rs b/tests/source/pub-restricted.rs new file mode 100644 index 00000000000..77b19b8e746 --- /dev/null +++ b/tests/source/pub-restricted.rs @@ -0,0 +1,51 @@ +pub( super ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( crate ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( ::global:: path :: to::some_mod ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( local:: path :: to::some_mod ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} diff --git a/tests/target/pub-restricted.rs b/tests/target/pub-restricted.rs new file mode 100644 index 00000000000..388228af814 --- /dev/null +++ b/tests/target/pub-restricted.rs @@ -0,0 +1,51 @@ +pub(super) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(crate) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(::global::path::to::some_mod) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(local::path::to::some_mod) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} -- cgit 1.4.1-3-g733a5 From bbb6038b92aa1ce17eebad96a904543e867f18b2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 28 May 2016 21:50:25 +0100 Subject: Treat chains with just expr? specially. Fixes #1004 --- src/chains.rs | 28 ++++++++++++++++++++++++++++ tests/source/chains.rs | 15 +++++++++++++++ tests/target/chains.rs | 13 +++++++++++++ 3 files changed, 56 insertions(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index faf368d41c1..00895561ded 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -88,6 +88,7 @@ use expr::rewrite_call; use config::BlockIndentStyle; use macros::convert_try_mac; +use std::iter; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; @@ -99,6 +100,12 @@ pub fn rewrite_chain(expr: &ast::Expr, let total_span = expr.span; let (parent, subexpr_list) = make_subexpr_list(expr, context); + // Bail out if the chain is just try sugar, i.e., an expression followed by + // any number of `?`s. + if chain_only_try(&subexpr_list) { + return rewrite_try(&parent, subexpr_list.len(), context, width, offset); + } + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_block_indent = chain_base_indent(context, offset); let parent_context = &RewriteContext { block_indent: parent_block_indent, ..*context }; @@ -196,6 +203,27 @@ pub fn rewrite_chain(expr: &ast::Expr, offset) } +// True if the chain is only `?`s. +fn chain_only_try(exprs: &[ast::Expr]) -> bool { + exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { + true + } else { + false + }) +} + +pub fn rewrite_try(expr: &ast::Expr, + try_count: usize, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let sub_expr = try_opt!(expr.rewrite(context, width - try_count, offset)); + Some(format!("{}{}", + sub_expr, + iter::repeat("?").take(try_count).collect::())) +} + fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { let mut rewrite_iter = rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 66c982082e7..deed8f6d8d8 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -133,3 +133,18 @@ fn try_shorthand() { |tcx| tcx.lookup_item_type(def_id).generics)?; fooooooooooooooooooooooooooo()?.bar()?.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; } + +fn issue_1004() { + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), + } + ?; + + ty::tls::with(|tcx| { + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + }) + ?; +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 3004946fb56..bdcb9fbd60e 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -162,3 +162,16 @@ fn try_shorthand() { .bar()? .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; } + +fn issue_1004() { + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), + }?; + + ty::tls::with(|tcx| { + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + })?; +} -- cgit 1.4.1-3-g733a5 From 98c0570a284c477285e59bb1928b582e7089a597 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Sun, 29 May 2016 17:58:38 +0200 Subject: Format non-statement if-else expressions on a single line --- src/chains.rs | 20 +- src/config.rs | 4 +- src/expr.rs | 406 +++++++++++---------- src/imports.rs | 12 +- src/items.rs | 18 +- src/lists.rs | 6 +- src/missed_spans.rs | 8 +- src/patterns.rs | 6 +- src/types.rs | 6 +- src/utils.rs | 6 +- src/visitor.rs | 6 +- tests/config/small_tabs.toml | 2 +- tests/source/chains-block-indented-base.rs | 1 + tests/source/chains-no-overflow.rs | 1 + tests/source/chains-visual.rs | 1 + tests/source/chains.rs | 1 + tests/source/closure.rs | 6 +- .../source/else-if-brace-style-always-next-line.rs | 1 + .../source/else-if-brace-style-always-same-line.rs | 1 + .../else-if-brace-style-closing-next-line.rs | 1 + tests/source/expr.rs | 17 + tests/source/hard-tabs.rs | 1 + tests/source/single-line-if-else.rs | 2 +- tests/target/chains-block-indented-base.rs | 1 + tests/target/chains-no-overflow.rs | 1 + tests/target/chains-visual.rs | 1 + tests/target/chains.rs | 1 + tests/target/closure.rs | 10 +- .../target/else-if-brace-style-always-next-line.rs | 1 + .../target/else-if-brace-style-always-same-line.rs | 1 + .../else-if-brace-style-closing-next-line.rs | 1 + tests/target/expr.rs | 18 +- tests/target/hard-tabs.rs | 1 + tests/target/single-line-if-else.rs | 2 +- 34 files changed, 274 insertions(+), 297 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index faf368d41c1..6b8c4e50246 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -354,27 +354,13 @@ fn rewrite_chain_subexpr(expr: &ast::Expr, } ast::ExprKind::Field(_, ref field) => { let s = format!(".{}", field.node); - if s.len() <= width { - Some(s) - } else { - None - } + if s.len() <= width { Some(s) } else { None } } ast::ExprKind::TupField(_, ref field) => { let s = format!(".{}", field.node); - if s.len() <= width { - Some(s) - } else { - None - } - } - ast::ExprKind::Try(_) => { - if width >= 1 { - Some("?".into()) - } else { - None - } + if s.len() <= width { Some(s) } else { None } } + ast::ExprKind::Try(_) => if width >= 1 { Some("?".into()) } else { None }, _ => unreachable!(), } } diff --git a/src/config.rs b/src/config.rs index e4d0e4517c2..8a51b3ecefa 100644 --- a/src/config.rs +++ b/src/config.rs @@ -381,7 +381,9 @@ create_config! { chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain"; chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; - single_line_if_else: bool, false, "Put else on same line as closing brace for if statements"; + single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ + expressions. A value of zero means always break \ + if-else expressions."; format_strings: bool, true, "Format string literals where necessary"; force_format_strings: bool, false, "Always format string literals"; take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; diff --git a/src/expr.rs b/src/expr.rs index ebe34400014..d57c8d294e1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -36,193 +36,210 @@ use syntax::parse::classify; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - let result = match self.node { - ast::ExprKind::Vec(ref expr_vec) => { - rewrite_array(expr_vec.iter().map(|e| &**e), - mk_sp(context.codemap.span_after(self.span, "["), self.span.hi), - context, - width, - offset) - } - ast::ExprKind::Lit(ref l) => { - match l.node { - ast::LitKind::Str(_, ast::StrStyle::Cooked) => { - rewrite_string_lit(context, l.span, width, offset) - } - _ => { - wrap_str(context.snippet(self.span), - context.config.max_width, - width, - offset) - } + format_expr(self, ExprType::SubExpression, context, width, offset) + } +} + +#[derive(PartialEq)] +enum ExprType { + Statement, + SubExpression, +} + +fn format_expr(expr: &ast::Expr, + expr_type: ExprType, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let result = match expr.node { + ast::ExprKind::Vec(ref expr_vec) => { + rewrite_array(expr_vec.iter().map(|e| &**e), + mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), + context, + width, + offset) + } + ast::ExprKind::Lit(ref l) => { + match l.node { + ast::LitKind::Str(_, ast::StrStyle::Cooked) => { + rewrite_string_lit(context, l.span, width, offset) } - } - ast::ExprKind::Call(ref callee, ref args) => { - let inner_span = mk_sp(callee.span.hi, self.span.hi); - rewrite_call(context, &**callee, args, inner_span, width, offset) - } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, width, offset), - ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { - rewrite_binary_op(context, op, lhs, rhs, width, offset) - } - ast::ExprKind::Unary(ref op, ref subexpr) => { - rewrite_unary_op(context, op, subexpr, width, offset) - } - ast::ExprKind::Struct(ref path, ref fields, ref base) => { - rewrite_struct_lit(context, - path, - fields, - base.as_ref().map(|e| &**e), - self.span, - width, - offset) - } - ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, - items.iter().map(|x| &**x), - self.span, - width, - offset) - } - ast::ExprKind::While(ref cond, ref block, label) => { - Loop::new_while(None, cond, block, label).rewrite(context, width, offset) - } - ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - Loop::new_while(Some(pat), cond, block, label).rewrite(context, width, offset) - } - ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - Loop::new_for(pat, cond, block, label).rewrite(context, width, offset) - } - ast::ExprKind::Loop(ref block, label) => { - Loop::new_loop(block, label).rewrite(context, width, offset) - } - ast::ExprKind::Block(ref block) => block.rewrite(context, width, offset), - ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { - rewrite_if_else(context, - cond, - if_block, - else_block.as_ref().map(|e| &**e), - self.span, - None, - width, - offset, - true) - } - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { - rewrite_if_else(context, - cond, - if_block, - else_block.as_ref().map(|e| &**e), - self.span, - Some(pat), - width, - offset, - true) - } - ast::ExprKind::Match(ref cond, ref arms) => { - rewrite_match(context, cond, arms, width, offset, self.span) - } - ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, true, qself.as_ref(), path, width, offset) - } - ast::ExprKind::Assign(ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, None, width, offset) - } - ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), width, offset) - } - ast::ExprKind::Again(ref opt_ident) => { - let id_str = match *opt_ident { - Some(ident) => format!(" {}", ident.node), - None => String::new(), - }; - wrap_str(format!("continue{}", id_str), - context.config.max_width, - width, - offset) - } - ast::ExprKind::Break(ref opt_ident) => { - let id_str = match *opt_ident { - Some(ident) => format!(" {}", ident.node), - None => String::new(), - }; - wrap_str(format!("break{}", id_str), - context.config.max_width, - width, - offset) - } - ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { - rewrite_closure(capture, fn_decl, body, self.span, context, width, offset) - } - ast::ExprKind::Try(..) | - ast::ExprKind::Field(..) | - ast::ExprKind::TupField(..) | - ast::ExprKind::MethodCall(..) => rewrite_chain(self, context, width, offset), - ast::ExprKind::Mac(ref mac) => { - // Failure to rewrite a marco should not imply failure to - // rewrite the expression. - rewrite_macro(mac, None, context, width, offset).or_else(|| { - wrap_str(context.snippet(self.span), + _ => { + wrap_str(context.snippet(expr.span), context.config.max_width, width, offset) - }) - } - ast::ExprKind::Ret(None) => { - wrap_str("return".to_owned(), context.config.max_width, width, offset) - } - ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, width, offset) - } - ast::ExprKind::Box(ref expr) => { - rewrite_unary_prefix(context, "box ", &**expr, width, offset) - } - ast::ExprKind::AddrOf(mutability, ref expr) => { - rewrite_expr_addrof(context, mutability, expr, width, offset) - } - ast::ExprKind::Cast(ref expr, ref ty) => { - rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) - } - ast::ExprKind::Type(ref expr, ref ty) => { - rewrite_pair(&**expr, &**ty, "", ": ", "", context, width, offset) - } - ast::ExprKind::Index(ref expr, ref index) => { - rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) - } - ast::ExprKind::Repeat(ref expr, ref repeats) => { - rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) - } - ast::ExprKind::Range(ref lhs, ref rhs, limits) => { - let delim = match limits { - ast::RangeLimits::HalfOpen => "..", - ast::RangeLimits::Closed => "...", - }; - - match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { - (Some(ref lhs), Some(ref rhs)) => { - rewrite_pair(&**lhs, &**rhs, "", delim, "", context, width, offset) - } - (None, Some(ref rhs)) => { - rewrite_unary_prefix(context, delim, &**rhs, width, offset) - } - (Some(ref lhs), None) => { - rewrite_unary_suffix(context, delim, &**lhs, width, offset) - } - (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), } } - // We do not format these expressions yet, but they should still - // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | - ast::ExprKind::InlineAsm(..) => { - wrap_str(context.snippet(self.span), + } + ast::ExprKind::Call(ref callee, ref args) => { + let inner_span = mk_sp(callee.span.hi, expr.span.hi); + rewrite_call(context, &**callee, args, inner_span, width, offset) + } + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, width, offset), + ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { + rewrite_binary_op(context, op, lhs, rhs, width, offset) + } + ast::ExprKind::Unary(ref op, ref subexpr) => { + rewrite_unary_op(context, op, subexpr, width, offset) + } + ast::ExprKind::Struct(ref path, ref fields, ref base) => { + rewrite_struct_lit(context, + path, + fields, + base.as_ref().map(|e| &**e), + expr.span, + width, + offset) + } + ast::ExprKind::Tup(ref items) => { + rewrite_tuple(context, + items.iter().map(|x| &**x), + expr.span, + width, + offset) + } + ast::ExprKind::While(ref cond, ref block, label) => { + Loop::new_while(None, cond, block, label).rewrite(context, width, offset) + } + ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { + Loop::new_while(Some(pat), cond, block, label).rewrite(context, width, offset) + } + ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { + Loop::new_for(pat, cond, block, label).rewrite(context, width, offset) + } + ast::ExprKind::Loop(ref block, label) => { + Loop::new_loop(block, label).rewrite(context, width, offset) + } + ast::ExprKind::Block(ref block) => block.rewrite(context, width, offset), + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { + rewrite_if_else(context, + cond, + expr_type, + if_block, + else_block.as_ref().map(|e| &**e), + expr.span, + None, + width, + offset, + true) + } + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { + rewrite_if_else(context, + cond, + expr_type, + if_block, + else_block.as_ref().map(|e| &**e), + expr.span, + Some(pat), + width, + offset, + true) + } + ast::ExprKind::Match(ref cond, ref arms) => { + rewrite_match(context, cond, arms, width, offset, expr.span) + } + ast::ExprKind::Path(ref qself, ref path) => { + rewrite_path(context, true, qself.as_ref(), path, width, offset) + } + ast::ExprKind::Assign(ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, None, width, offset) + } + ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, Some(op), width, offset) + } + ast::ExprKind::Again(ref opt_ident) => { + let id_str = match *opt_ident { + Some(ident) => format!(" {}", ident.node), + None => String::new(), + }; + wrap_str(format!("continue{}", id_str), + context.config.max_width, + width, + offset) + } + ast::ExprKind::Break(ref opt_ident) => { + let id_str = match *opt_ident { + Some(ident) => format!(" {}", ident.node), + None => String::new(), + }; + wrap_str(format!("break{}", id_str), + context.config.max_width, + width, + offset) + } + ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { + rewrite_closure(capture, fn_decl, body, expr.span, context, width, offset) + } + ast::ExprKind::Try(..) | + ast::ExprKind::Field(..) | + ast::ExprKind::TupField(..) | + ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, width, offset), + ast::ExprKind::Mac(ref mac) => { + // Failure to rewrite a marco should not imply failure to + // rewrite the expression. + rewrite_macro(mac, None, context, width, offset).or_else(|| { + wrap_str(context.snippet(expr.span), context.config.max_width, width, offset) + }) + } + ast::ExprKind::Ret(None) => { + wrap_str("return".to_owned(), context.config.max_width, width, offset) + } + ast::ExprKind::Ret(Some(ref expr)) => { + rewrite_unary_prefix(context, "return ", &**expr, width, offset) + } + ast::ExprKind::Box(ref expr) => { + rewrite_unary_prefix(context, "box ", &**expr, width, offset) + } + ast::ExprKind::AddrOf(mutability, ref expr) => { + rewrite_expr_addrof(context, mutability, expr, width, offset) + } + ast::ExprKind::Cast(ref expr, ref ty) => { + rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) + } + ast::ExprKind::Type(ref expr, ref ty) => { + rewrite_pair(&**expr, &**ty, "", ": ", "", context, width, offset) + } + ast::ExprKind::Index(ref expr, ref index) => { + rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) + } + ast::ExprKind::Repeat(ref expr, ref repeats) => { + rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) + } + ast::ExprKind::Range(ref lhs, ref rhs, limits) => { + let delim = match limits { + ast::RangeLimits::HalfOpen => "..", + ast::RangeLimits::Closed => "...", + }; + + match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { + (Some(ref lhs), Some(ref rhs)) => { + rewrite_pair(&**lhs, &**rhs, "", delim, "", context, width, offset) + } + (None, Some(ref rhs)) => { + rewrite_unary_prefix(context, delim, &**rhs, width, offset) + } + (Some(ref lhs), None) => { + rewrite_unary_suffix(context, delim, &**lhs, width, offset) + } + (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), } - }; - result.and_then(|res| recover_comment_removed(res, self.span, context, width, offset)) - } + } + // We do not format these expressions yet, but they should still + // satisfy our width restrictions. + ast::ExprKind::InPlace(..) | + ast::ExprKind::InlineAsm(..) => { + wrap_str(context.snippet(expr.span), + context.config.max_width, + width, + offset) + } + }; + result.and_then(|res| recover_comment_removed(res, expr.span, context, width, offset)) } pub fn rewrite_pair(lhs: &LHS, @@ -470,11 +487,7 @@ fn rewrite_closure(capture: ast::CaptureBy, } fn and_one_line(x: Option) -> Option { - x.and_then(|x| if x.contains('\n') { - None - } else { - Some(x) - }) + x.and_then(|x| if x.contains('\n') { None } else { Some(x) }) } fn nop_block_collapse(block_str: Option, budget: usize) -> Option { @@ -560,15 +573,13 @@ impl Rewrite for ast::Stmt { } ast::StmtKind::Expr(ref ex, _) | ast::StmtKind::Semi(ref ex, _) => { - let suffix = if semicolon_for_stmt(self) { - ";" - } else { - "" - }; + let suffix = if semicolon_for_stmt(self) { ";" } else { "" }; - ex.rewrite(context, - context.config.max_width - offset.width() - suffix.len(), - offset) + format_expr(ex, + ExprType::Statement, + context, + context.config.max_width - offset.width() - suffix.len(), + offset) .map(|s| s + suffix) } ast::StmtKind::Mac(..) => None, @@ -704,6 +715,7 @@ fn extract_comment(span: Span, // treated as an if-let-else expression. fn rewrite_if_else(context: &RewriteContext, cond: &ast::Expr, + expr_type: ExprType, if_block: &ast::Block, else_block_opt: Option<&ast::Expr>, span: Span, @@ -726,10 +738,12 @@ fn rewrite_if_else(context: &RewriteContext, offset + 3)); // Try to format if-else on single line. - if allow_single_line && context.config.single_line_if_else { + if expr_type == ExprType::SubExpression && allow_single_line && + context.config.single_line_if_else_max_width > 0 { let trial = single_line_if_else(context, &pat_expr_string, if_block, else_block_opt, width); - if trial.is_some() { + if trial.is_some() && + trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width { return trial; } } @@ -766,6 +780,7 @@ fn rewrite_if_else(context: &RewriteContext, ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, + expr_type, if_block, next_else_block.as_ref().map(|e| &**e), mk_sp(else_block.span.lo, span.hi), @@ -777,6 +792,7 @@ fn rewrite_if_else(context: &RewriteContext, ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, + expr_type, if_block, next_else_block.as_ref().map(|e| &**e), mk_sp(else_block.span.lo, span.hi), @@ -1248,11 +1264,7 @@ fn rewrite_pat_expr(context: &RewriteContext, // The expression may (partionally) fit on the current line. if width > extra_offset + 1 { - let spacer = if pat.is_some() { - " " - } else { - "" - }; + let spacer = if pat.is_some() { " " } else { "" }; let expr_rewrite = expr.rewrite(context, width - extra_offset - spacer.len(), diff --git a/src/imports.rs b/src/imports.rs index c7cedc63a98..cb644485199 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -111,11 +111,7 @@ pub fn rewrite_use_list(width: usize, } // 2 = :: - let path_separation_w = if !path_str.is_empty() { - 2 - } else { - 0 - }; + let path_separation_w = if !path_str.is_empty() { 2 } else { 0 }; // 1 = { let supp_indent = path_str.len() + path_separation_w + 1; // 1 = } @@ -140,11 +136,7 @@ pub fn rewrite_use_list(width: usize, // potentially move "self" to the front of the vector without touching // the rest of the items. let has_self = move_self_to_front(&mut items); - let first_index = if has_self { - 0 - } else { - 1 - }; + let first_index = if has_self { 0 } else { 1 }; if context.config.reorder_imports { items[1..].sort_by(|a, b| a.item.cmp(&b.item)); diff --git a/src/items.rs b/src/items.rs index b55ecd5c0ef..6cafe34a824 100644 --- a/src/items.rs +++ b/src/items.rs @@ -140,11 +140,7 @@ impl<'a> FmtVisitor<'a> { // FIXME(#21): we're dropping potential comments in between the // function keywords here. let vis = format_visibility(&item.vis); - let mut_str = if is_mutable { - "mut " - } else { - "" - }; + let mut_str = if is_mutable { "mut " } else { "" }; let prefix = format!("{}static {}{}: ", vis, mut_str, item.ident); let offset = self.block_indent + prefix.len(); // 1 = ; @@ -265,11 +261,7 @@ impl<'a> FmtVisitor<'a> { if self.config.fn_single_line && is_simple_block_stmt(block, codemap) { let rewrite = { if let Some(ref e) = block.expr { - let suffix = if semicolon_for_expr(e) { - ";" - } else { - "" - }; + let suffix = if semicolon_for_expr(e) { ";" } else { "" }; e.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), @@ -1280,11 +1272,7 @@ fn rewrite_fn_base(context: &RewriteContext, .rewrite(&context, context.config.max_width - indent.width(), indent)); let multi_line_ret_str = ret_str.contains('\n'); - let ret_str_len = if multi_line_ret_str { - 0 - } else { - ret_str.len() - }; + let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; // Args. let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = diff --git a/src/lists.rs b/src/lists.rs index b35ccfe3d69..2bd4becc57f 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -208,11 +208,7 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option let first = i == 0; let last = iter.peek().is_none(); let separate = !last || trailing_separator; - let item_sep_len = if separate { - sep_len - } else { - 0 - }; + let item_sep_len = if separate { sep_len } else { 0 }; // Item string may be multi-line. Its length (used for block comment alignment) // Should be only the length of the last line. diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2191a7812b1..7e6d1516636 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -93,13 +93,7 @@ impl<'a> FmtVisitor<'a> { fn replace_chars(string: &str) -> String { string.chars() - .map(|ch| { - if ch.is_whitespace() { - ch - } else { - 'X' - } - }) + .map(|ch| { if ch.is_whitespace() { ch } else { 'X' } }) .collect() } diff --git a/src/patterns.rs b/src/patterns.rs index 837fecd83ce..2fe16495b99 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -121,11 +121,7 @@ impl Rewrite for Pat { PatKind::Struct(ref path, ref fields, elipses) => { let path = try_opt!(rewrite_path(context, true, None, path, width, offset)); - let (elipses_str, terminator) = if elipses { - (", ..", "..") - } else { - ("", "}") - }; + let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; // 5 = `{` plus space before and after plus `}` plus space before. let budget = try_opt!(width.checked_sub(path.len() + 5 + elipses_str.len())); diff --git a/src/types.rs b/src/types.rs index 8dd8c09959b..f44a10a4a37 100644 --- a/src/types.rs +++ b/src/types.rs @@ -187,11 +187,7 @@ fn rewrite_segment(expr_context: bool, let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); - let separator = if expr_context { - "::" - } else { - "" - }; + let separator = if expr_context { "::" } else { "" }; // 1 for < let extra_offset = 1 + separator.len(); diff --git a/src/utils.rs b/src/utils.rs index cb286723cc9..188174e6021 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -77,11 +77,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { Visibility::Crate(_) => Cow::from("pub(crate) "), Visibility::Restricted { ref path, .. } => { let Path { global, ref segments, .. } = **path; - let prefix = if global { - "::" - } else { - "" - }; + let prefix = if global { "::" } else { "" }; let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.as_str()); Cow::from(format!("pub({}{}) ", prefix, segments_iter.join("::"))) diff --git a/src/visitor.rs b/src/visitor.rs index 8473d1685da..94ae85b4ecb 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -77,11 +77,7 @@ impl<'a> FmtVisitor<'a> { // Check if this block has braces. let snippet = self.snippet(b.span); let has_braces = snippet.starts_with("{") || snippet.starts_with("unsafe"); - let brace_compensation = if has_braces { - BytePos(1) - } else { - BytePos(0) - }; + let brace_compensation = if has_braces { BytePos(1) } else { BytePos(0) }; self.last_pos = self.last_pos + brace_compensation; self.block_indent = self.block_indent.block_indent(self.config); diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index cb4d5da5274..2a0af63eea5 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -21,7 +21,7 @@ enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = false -single_line_if_else = false +single_line_if_else_max_width = 0 format_strings = true chains_overflow_last = true take_source_hints = true diff --git a/tests/source/chains-block-indented-base.rs b/tests/source/chains-block-indented-base.rs index 05459dc6973..6646056690d 100644 --- a/tests/source/chains-block-indented-base.rs +++ b/tests/source/chains-block-indented-base.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_base_indent: Inherit // Test chain formatting with block indented base diff --git a/tests/source/chains-no-overflow.rs b/tests/source/chains-no-overflow.rs index b94ca21b258..29c092d9f1a 100644 --- a/tests/source/chains-no-overflow.rs +++ b/tests/source/chains-no-overflow.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-chains_overflow_last: false // Test chain formatting without overflowing the last item. diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs index a62ec4f492e..bd365ce9a4c 100644 --- a/tests/source/chains-visual.rs +++ b/tests/source/chains-visual.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_indent: Visual // rustfmt-chain_base_indent: Visual // Test chain formatting. diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 66c982082e7..d2df8c48da6 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // Test chain formatting. fn main() { diff --git a/tests/source/closure.rs b/tests/source/closure.rs index 4fd5465cca0..0a0dd717586 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -11,21 +11,19 @@ fn main() { }; let loooooooooooooong_name = |field| { - // TODO(#27): format comments. + // format comments. if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo } else { field.span.lo }}; - let block_me = |field| if true_story() { 1 } else { 2 }; - let unblock_me = |trivial| { closure() }; let empty = |arg| {}; - let simple = |arg| { /* TODO(#27): comment formatting */ foo(arg) }; + let simple = |arg| { /* comment formatting */ foo(arg) }; let test = | | { do_something(); do_something_else(); }; diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/tests/source/else-if-brace-style-always-next-line.rs index 18a8ace1f14..768aa1fe3c0 100644 --- a/tests/source/else-if-brace-style-always-next-line.rs +++ b/tests/source/else-if-brace-style-always-next-line.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-else_if_brace_style: AlwaysNextLine fn main() { diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/tests/source/else-if-brace-style-always-same-line.rs index 090b1e9a9db..7f8a3f1a3c4 100644 --- a/tests/source/else-if-brace-style-always-same-line.rs +++ b/tests/source/else-if-brace-style-always-same-line.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-else_if_brace_style: AlwaysSameLine fn main() { diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/tests/source/else-if-brace-style-closing-next-line.rs index 755b95bd541..8784d7c08d7 100644 --- a/tests/source/else-if-brace-style-closing-next-line.rs +++ b/tests/source/else-if-brace-style-closing-next-line.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-else_if_brace_style: ClosingNextLine fn main() { diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 40fd3309a4c..ee24e742641 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -255,3 +255,20 @@ fn ranges() { // the expr below won't compile for some reason... // let a = 0 ... ; } + +fn if_else() { + let exact = diff / + (if size == 0 { + 1 +} else { + size +}); + + let cx = tp1.x + + any * radius * + if anticlockwise { + 1.0 + } else { + -1.0 + }; +} diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs index 290dbfc616d..c19d5d4c01f 100644 --- a/tests/source/hard-tabs.rs +++ b/tests/source/hard-tabs.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-wrap_comments: true // rustfmt-hard_tabs: true diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs index 2f9c19086ff..3780ef7659f 100644 --- a/tests/source/single-line-if-else.rs +++ b/tests/source/single-line-if-else.rs @@ -1,4 +1,4 @@ -// rustfmt-single_line_if_else: true +// rustfmt-single_line_if_else_max_width: 100 // Format if-else expressions on a single line, when possible. diff --git a/tests/target/chains-block-indented-base.rs b/tests/target/chains-block-indented-base.rs index 5b9863689de..f737745b366 100644 --- a/tests/target/chains-block-indented-base.rs +++ b/tests/target/chains-block-indented-base.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_base_indent: Inherit // Test chain formatting with block indented base diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs index 2c78fbd9121..a6fd0f92a8d 100644 --- a/tests/target/chains-no-overflow.rs +++ b/tests/target/chains-no-overflow.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-chains_overflow_last: false // Test chain formatting without overflowing the last item. diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index d17a98e2ada..9a13d03d5a2 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_indent: Visual // rustfmt-chain_base_indent: Visual // Test chain formatting. diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 3004946fb56..46bf4eaf354 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // Test chain formatting. fn main() { diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 8fe290b955a..ed8a66e2d16 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -18,7 +18,7 @@ fn main() { }; let loooooooooooooong_name = |field| { - // TODO(#27): format comments. + // format comments. if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo } else { @@ -26,18 +26,12 @@ fn main() { } }; - let block_me = |field| if true_story() { - 1 - } else { - 2 - }; - let unblock_me = |trivial| closure(); let empty = |arg| {}; let simple = |arg| { - // TODO(#27): comment formatting + // comment formatting foo(arg) }; diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs index 3fbd8b7af25..e14bf7d0182 100644 --- a/tests/target/else-if-brace-style-always-next-line.rs +++ b/tests/target/else-if-brace-style-always-next-line.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-else_if_brace_style: AlwaysNextLine fn main() { diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs index 393944133f7..e98d9bfc811 100644 --- a/tests/target/else-if-brace-style-always-same-line.rs +++ b/tests/target/else-if-brace-style-always-same-line.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-else_if_brace_style: AlwaysSameLine fn main() { diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs index e50f29d2921..7978e372449 100644 --- a/tests/target/else-if-brace-style-closing-next-line.rs +++ b/tests/target/else-if-brace-style-closing-next-line.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-else_if_brace_style: ClosingNextLine fn main() { diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 1378b4bf8f8..87a45a98d49 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -62,11 +62,7 @@ fn foo() -> bool { tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { } - let test = if true { - 5 - } else { - 3 - }; + let test = if true { 5 } else { 3 }; if cond() { something(); @@ -92,11 +88,7 @@ fn bar() { syntactically_correct(loop { sup('?'); }, - if cond { - 0 - } else { - 1 - }); + if cond { 0 } else { 1 }); let third = ..10; let infi_range = ..; @@ -277,3 +269,9 @@ fn ranges() { // the expr below won't compile for some reason... // let a = 0 ... ; } + +fn if_else() { + let exact = diff / (if size == 0 { 1 } else { size }); + + let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; +} diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 1e00559b3f3..7fa076b888f 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -1,3 +1,4 @@ +// rustfmt-single_line_if_else_max_width: 0 // rustfmt-wrap_comments: true // rustfmt-hard_tabs: true diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs index ec4daa727a6..ac55d062134 100644 --- a/tests/target/single-line-if-else.rs +++ b/tests/target/single-line-if-else.rs @@ -1,4 +1,4 @@ -// rustfmt-single_line_if_else: true +// rustfmt-single_line_if_else_max_width: 100 // Format if-else expressions on a single line, when possible. -- cgit 1.4.1-3-g733a5 From 120e1a0b51224a4ec16095a6e322bdb0039946db Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 30 May 2016 14:53:04 +0200 Subject: deps: Update syntex_syntax to 0.33 This bump brings syntex_syntax support for `..` in tuple and tuple struct patterns, which come from RFC 1492: https://github.com/rust-lang/rfcs/blob/master/text/1492-dotdot-in-patterns.md These new patterns are not properly handled in this PR; instead #1021 tracks supporting them. Refs #1021 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/expr.rs | 12 ++++++------ src/items.rs | 10 ++-------- src/patterns.rs | 15 ++++++++++----- src/types.rs | 1 + src/visitor.rs | 2 -- 7 files changed, 22 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 1999f6c811a..621659c737f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ dependencies = [ "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -112,7 +112,7 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index b0964c03704..756fcc600e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.32" +syntex_syntax = "0.33" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/expr.rs b/src/expr.rs index ebe34400014..73b76534f75 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -581,7 +581,7 @@ impl Rewrite for ast::Stmt { struct Loop<'a> { cond: Option<&'a ast::Expr>, block: &'a ast::Block, - label: Option, + label: Option, pat: Option<&'a ast::Pat>, keyword: &'a str, matcher: &'a str, @@ -589,7 +589,7 @@ struct Loop<'a> { } impl<'a> Loop<'a> { - fn new_loop(block: &'a ast::Block, label: Option) -> Loop<'a> { + fn new_loop(block: &'a ast::Block, label: Option) -> Loop<'a> { Loop { cond: None, block: block, @@ -604,7 +604,7 @@ impl<'a> Loop<'a> { fn new_while(pat: Option<&'a ast::Pat>, cond: &'a ast::Expr, block: &'a ast::Block, - label: Option) + label: Option) -> Loop<'a> { Loop { cond: Some(cond), @@ -623,7 +623,7 @@ impl<'a> Loop<'a> { fn new_for(pat: &'a ast::Pat, cond: &'a ast::Expr, block: &'a ast::Block, - label: Option) + label: Option) -> Loop<'a> { Loop { cond: Some(cond), @@ -676,9 +676,9 @@ impl<'a> Rewrite for Loop<'a> { } } -fn rewrite_label(label: Option) -> String { +fn rewrite_label(label: Option) -> String { match label { - Some(ident) => format!("{}: ", ident), + Some(ident) => format!("{}: ", ident.node), None => "".to_owned(), } } diff --git a/src/items.rs b/src/items.rs index b55ecd5c0ef..6bbf0dd5044 100644 --- a/src/items.rs +++ b/src/items.rs @@ -116,7 +116,6 @@ impl<'a> FmtVisitor<'a> { indent, item.ident, fn_decl, - None, generics, ast::Unsafety::Normal, ast::Constness::NotConst, @@ -169,7 +168,6 @@ impl<'a> FmtVisitor<'a> { indent: Indent, ident: ast::Ident, fd: &ast::FnDecl, - explicit_self: Option<&ast::ExplicitSelf>, generics: &ast::Generics, unsafety: ast::Unsafety, constness: ast::Constness, @@ -189,7 +187,6 @@ impl<'a> FmtVisitor<'a> { indent, ident, fd, - explicit_self, generics, unsafety, constness, @@ -234,7 +231,6 @@ impl<'a> FmtVisitor<'a> { indent, ident, &sig.decl, - Some(&sig.explicit_self), &sig.generics, sig.unsafety, sig.constness, @@ -1129,7 +1125,7 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, context: &RewriteContext) -> Option { match explicit_self.node { - ast::SelfKind::Region(lt, m, _) => { + ast::SelfKind::Region(lt, m) => { let mut_str = format_mutability(m); match lt { Some(ref l) => { @@ -1155,7 +1151,6 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, Some(format!("{}self", format_mutability(mutability))) } - _ => None, } } @@ -1229,7 +1224,6 @@ fn rewrite_fn_base(context: &RewriteContext, indent: Indent, ident: ast::Ident, fd: &ast::FnDecl, - explicit_self: Option<&ast::ExplicitSelf>, generics: &ast::Generics, unsafety: ast::Unsafety, constness: ast::Constness, @@ -1328,7 +1322,7 @@ fn rewrite_fn_base(context: &RewriteContext, span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, &fd.inputs, - explicit_self, + fd.get_self().as_ref(), one_line_budget, multi_line_budget, indent, diff --git a/src/patterns.rs b/src/patterns.rs index 837fecd83ce..1c147a3e74b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -59,7 +59,11 @@ impl Rewrite for Pat { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, width, offset) } - PatKind::Tup(ref items) => { + // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492) + PatKind::Tuple(ref items, dotdot_pos) => { + if dotdot_pos.is_some() { + return None; + } rewrite_tuple(context, items.iter().map(|x| &**x), self.span, @@ -67,11 +71,13 @@ impl Rewrite for Pat { offset) } PatKind::Path(ref path) => rewrite_path(context, true, None, path, width, offset), - PatKind::TupleStruct(ref path, ref pat_vec) => { + PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); - match *pat_vec { - Some(ref pat_vec) => { + // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492) + match dotdot_pos { + Some(_) => Some(format!("{}(..)", path_str)), + None => { if pat_vec.is_empty() { Some(path_str) } else { @@ -95,7 +101,6 @@ impl Rewrite for Pat { context.config)))) } } - None => Some(format!("{}(..)", path_str)), } } PatKind::Lit(ref expr) => expr.rewrite(context, width, offset), diff --git a/src/types.rs b/src/types.rs index 8dd8c09959b..8b5be1b4191 100644 --- a/src/types.rs +++ b/src/types.rs @@ -588,6 +588,7 @@ impl Rewrite for ast::Ty { } ast::TyKind::Mac(..) | ast::TyKind::Typeof(..) => unreachable!(), + ast::TyKind::ImplicitSelf => Some(String::from("")), } } } diff --git a/src/visitor.rs b/src/visitor.rs index 8473d1685da..b70ae8bb240 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -142,7 +142,6 @@ impl<'a> FmtVisitor<'a> { self.rewrite_fn(indent, ident, fd, - None, generics, unsafety, constness, @@ -155,7 +154,6 @@ impl<'a> FmtVisitor<'a> { self.rewrite_fn(indent, ident, fd, - Some(&sig.explicit_self), &sig.generics, sig.unsafety, sig.constness, -- cgit 1.4.1-3-g733a5 From 7f0d87cc5162705b94a92c834d7b94cf0f02738f Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Wed, 25 May 2016 20:41:26 +0200 Subject: Derive Debug for the Input enum --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index e672efb8fea..9b6d69e2f16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -470,6 +470,7 @@ pub fn format_input(input: Input, } } +#[derive(Debug)] pub enum Input { File(PathBuf), Text(String), -- cgit 1.4.1-3-g733a5 From 80c56a01ff9722ab0e52a8bd73b50603bc5a9a96 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Wed, 25 May 2016 20:41:26 +0200 Subject: visitor: Add debug log for FmtVisitor::visit_stmt() --- src/visitor.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 503153463df..45c72e2fdf8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -42,6 +42,10 @@ pub struct FmtVisitor<'a> { impl<'a> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { + debug!("visit_stmt: {:?} {:?}", + self.codemap.lookup_char_pos(stmt.span.lo), + self.codemap.lookup_char_pos(stmt.span.hi)); + match stmt.node { ast::StmtKind::Decl(ref decl, _) => { if let ast::DeclKind::Item(ref item) = decl.node { -- cgit 1.4.1-3-g733a5 From bd10af127ee4acbc6cd9e3221f78620d4f1e83be Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Wed, 25 May 2016 20:41:26 +0200 Subject: utils: Move codemap related utilities to a dedicated module This commit adds a `codemap` module, and moves the `CodemapSpanUtils` added in #857 to it. This is preparation for adding more `Codemap` specific utilities. Refs #434 --- src/codemap.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/expr.rs | 5 +++-- src/imports.rs | 2 +- src/items.rs | 5 +++-- src/lib.rs | 1 + src/macros.rs | 3 ++- src/patterns.rs | 3 ++- src/types.rs | 3 ++- src/utils.rs | 39 +-------------------------------------- src/visitor.rs | 3 ++- 10 files changed, 56 insertions(+), 47 deletions(-) create mode 100644 src/codemap.rs (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs new file mode 100644 index 00000000000..c70decd8422 --- /dev/null +++ b/src/codemap.rs @@ -0,0 +1,39 @@ +use syntax::codemap::{BytePos, CodeMap, Span}; + +use comment::FindUncommented; + +pub trait SpanUtils { + fn span_after(&self, original: Span, needle: &str) -> BytePos; + fn span_after_last(&self, original: Span, needle: &str) -> BytePos; + fn span_before(&self, original: Span, needle: &str) -> BytePos; +} + +impl SpanUtils for CodeMap { + #[inline] + fn span_after(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); + + original.lo + BytePos(offset as u32) + } + + #[inline] + fn span_after_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo + BytePos(offset as u32) + } + + #[inline] + fn span_before(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap(); + + original.lo + BytePos(offset as u32) + } +} diff --git a/src/expr.rs b/src/expr.rs index fc7f9cc6ca3..af0492b2913 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -16,12 +16,13 @@ use std::iter::ExactSizeIterator; use std::fmt::Write; use {Indent, Spanned}; +use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; use string::{StringFormat, rewrite_string}; -use utils::{CodeMapSpanUtils, extra_offset, last_line_width, wrap_str, binary_search, - first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; +use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, + semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; diff --git a/src/imports.rs b/src/imports.rs index cb644485199..89030392774 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -9,9 +9,9 @@ // except according to those terms. use Indent; +use codemap::SpanUtils; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; use types::rewrite_path; -use utils::CodeMapSpanUtils; use rewrite::{Rewrite, RewriteContext}; use syntax::ast; diff --git a/src/items.rs b/src/items.rs index defd8e1a742..d83ad3c88ee 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,8 +11,9 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use Indent; -use utils::{CodeMapSpanUtils, format_mutability, format_visibility, contains_skip, end_typaram, - wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; +use codemap::SpanUtils; +use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, + last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; diff --git a/src/lib.rs b/src/lib.rs index 9b6d69e2f16..8df2c069bcc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,7 @@ pub use self::summary::Summary; #[macro_use] mod utils; pub mod config; +pub mod codemap; pub mod filemap; pub mod visitor; mod checkstyle; diff --git a/src/macros.rs b/src/macros.rs index e9992fb0eb0..9cb0f8619c0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -25,10 +25,11 @@ use syntax::parse::tts_to_parser; use syntax::codemap::{mk_sp, BytePos}; use Indent; +use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use expr::{rewrite_call, rewrite_array}; use comment::{FindUncommented, contains_comment}; -use utils::{CodeMapSpanUtils, wrap_str}; +use utils::wrap_str; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; diff --git a/src/patterns.rs b/src/patterns.rs index 08d9db85201..a0b15a0f8c9 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -9,8 +9,9 @@ // except according to those terms. use Indent; +use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; -use utils::{CodeMapSpanUtils, wrap_str, format_mutability}; +use utils::{wrap_str, format_mutability}; use lists::{format_item_list, itemize_list}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use types::rewrite_path; diff --git a/src/types.rs b/src/types.rs index 656701b6c78..b1b9b749dd8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,9 +17,10 @@ use syntax::codemap::{self, Span, BytePos}; use syntax::abi; use {Indent, Spanned}; +use codemap::SpanUtils; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; -use utils::{CodeMapSpanUtils, extra_offset, format_mutability, wrap_str}; +use utils::{extra_offset, format_mutability, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::TypeDensity; diff --git a/src/utils.rs b/src/utils.rs index 188174e6021..82fbb8d5925 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -14,51 +14,14 @@ use std::cmp::Ordering; use itertools::Itertools; use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, Path}; -use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::codemap::BytePos; use syntax::abi; use Indent; -use comment::FindUncommented; use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; -pub trait CodeMapSpanUtils { - fn span_after(&self, original: Span, needle: &str) -> BytePos; - fn span_after_last(&self, original: Span, needle: &str) -> BytePos; - fn span_before(&self, original: Span, needle: &str) -> BytePos; -} - -impl CodeMapSpanUtils for CodeMap { - #[inline] - fn span_after(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); - - original.lo + BytePos(offset as u32) - } - - #[inline] - fn span_after_last(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let mut offset = 0; - - while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { - offset += additional_offset + needle.len(); - } - - original.lo + BytePos(offset as u32) - } - - #[inline] - fn span_before(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap(); - - original.lo + BytePos(offset as u32) - } -} - // Computes the length of a string's last line, minus offset. #[inline] pub fn extra_offset(text: &str, offset: Indent) -> usize { diff --git a/src/visitor.rs b/src/visitor.rs index 45c72e2fdf8..c2ebcd17119 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -15,7 +15,8 @@ use syntax::parse::ParseSess; use strings::string_buffer::StringBuffer; use Indent; -use utils::{self, CodeMapSpanUtils}; +use utils; +use codemap::SpanUtils; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; -- cgit 1.4.1-3-g733a5 From ed27b4799a34607627ea9b2e3c73a693820e4bbf Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Thu, 26 May 2016 13:49:19 +0200 Subject: codemap: Add utilities for looking up line ranges of spans This commit adds extension methods to `Codemap` to allow looking up line ranges for spans. Refs #434 --- src/codemap.rs | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs index c70decd8422..43c269e40a9 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -1,13 +1,37 @@ -use syntax::codemap::{BytePos, CodeMap, Span}; +use std::rc::Rc; + +use syntax::codemap::{BytePos, CodeMap, FileMap, Span}; use comment::FindUncommented; +/// A range of lines in a file, inclusive of both ends. +pub struct LineRange { + pub file: Rc, + pub lo: usize, + pub hi: usize, +} + +impl LineRange { + pub fn file_name(&self) -> &str { + self.file.as_ref().name.as_str() + } +} + pub trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; fn span_after_last(&self, original: Span, needle: &str) -> BytePos; fn span_before(&self, original: Span, needle: &str) -> BytePos; } +pub trait LineRangeUtils { + /// Returns the `LineRange` that corresponds to `span` in `self`. + /// + /// # Panics + /// + /// Panics if `span` crosses a file boundary, which shouldn't happen. + fn lookup_line_range(&self, span: Span) -> LineRange; +} + impl SpanUtils for CodeMap { #[inline] fn span_after(&self, original: Span, needle: &str) -> BytePos { @@ -37,3 +61,21 @@ impl SpanUtils for CodeMap { original.lo + BytePos(offset as u32) } } + +impl LineRangeUtils for CodeMap { + fn lookup_line_range(&self, span: Span) -> LineRange { + let lo = self.lookup_char_pos(span.lo); + let hi = self.lookup_char_pos(span.hi); + + assert!(lo.file.name == hi.file.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, + hi); + + LineRange { + file: lo.file.clone(), + lo: lo.line, + hi: hi.line, + } + } +} -- cgit 1.4.1-3-g733a5 From c311b30cacf91e8bfc4b6fb586dc3ec843140e26 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Thu, 26 May 2016 14:17:20 +0200 Subject: Add type to represent collection of lines in files This commit adds a type to represent lines in files, and adds it to the `Config` struct. It will be used for restricting formatting to specific lines. Refs #434 --- Cargo.lock | 6 ++ Cargo.toml | 1 + src/config.rs | 9 +++ src/file_lines.rs | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 5 files changed, 239 insertions(+) create mode 100644 src/file_lines.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 621659c737f..fc8070979d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -80,6 +81,11 @@ dependencies = [ "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "multimap" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "regex" version = "0.1.71" diff --git a/Cargo.toml b/Cargo.toml index 756fcc600e9..9d8ad68ed8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,4 @@ log = "0.3" env_logger = "0.3" getopts = "0.2" itertools = "0.4.15" +multimap = "0.3" diff --git a/src/config.rs b/src/config.rs index 8a51b3ecefa..ecb63851417 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,7 @@ extern crate toml; +use file_lines::FileLines; use lists::{SeparatorTactic, ListTactic}; use std::io::Write; @@ -200,6 +201,12 @@ impl ConfigType for String { } } +impl ConfigType for FileLines { + fn doc_hint() -> String { + String::from("") + } +} + pub struct ConfigHelpItem { option_name: &'static str, doc_string: &'static str, @@ -327,6 +334,8 @@ macro_rules! create_config { create_config! { verbose: bool, false, "Use verbose output"; skip_children: bool, false, "Don't reformat out of line modules"; + file_lines: FileLines, FileLines::all(), + "Lines to format"; max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; diff --git a/src/file_lines.rs b/src/file_lines.rs new file mode 100644 index 00000000000..e437202360d --- /dev/null +++ b/src/file_lines.rs @@ -0,0 +1,221 @@ +//! This module contains types and functions to support formatting specific line ranges. +use std::{cmp, iter, str}; + +use itertools::Itertools; +use multimap::MultiMap; +use rustc_serialize::{self, json}; + +use codemap::LineRange; + +/// A range that is inclusive of both ends. +#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcDecodable)] +struct Range { + pub lo: usize, + pub hi: usize, +} + +impl<'a> From<&'a LineRange> for Range { + fn from(range: &'a LineRange) -> Range { + Range::new(range.lo, range.hi) + } +} + +impl Range { + fn new(lo: usize, hi: usize) -> Range { + Range { lo: lo, hi: hi } + } + + fn is_empty(self) -> bool { + self.lo > self.hi + } + + fn contains(self, other: Range) -> bool { + if other.is_empty() { + true + } else { + !self.is_empty() && self.lo <= other.lo && self.hi >= other.hi + } + } + + fn intersects(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + (self.lo <= other.hi && other.hi <= self.hi) || + (other.lo <= self.hi && self.hi <= other.hi) + } + } + + fn adjacent_to(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + self.hi + 1 == other.lo || other.hi + 1 == self.lo + } + } + + /// Returns a new `Range` with lines from `self` and `other` if they were adjacent or + /// intersect; returns `None` otherwise. + fn merge(self, other: Range) -> Option { + if self.adjacent_to(other) || self.intersects(other) { + Some(Range::new(cmp::min(self.lo, other.lo), cmp::max(self.hi, other.hi))) + } else { + None + } + } +} + +/// A set of lines in files. +/// +/// It is represented as a multimap keyed on file names, with values a collection of +/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all +/// lines in all files. +#[derive(Clone, Debug, Default)] +pub struct FileLines(Option>); + +/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, +/// and ordered by their start point. +fn normalize_ranges(map: &mut MultiMap) { + for (_, ranges) in map.iter_all_mut() { + ranges.sort_by_key(|x| x.lo); + let merged = ranges.drain(..).coalesce(|x, y| x.merge(y).ok_or((x, y))).collect(); + *ranges = merged; + } +} + +impl FileLines { + /// Creates a `FileLines` that contains all lines in all files. + pub fn all() -> FileLines { + FileLines(None) + } + + /// Creates a `FileLines` from a `MultiMap`, ensuring that the invariants hold. + fn from_multimap(map: MultiMap) -> FileLines { + let mut map = map; + normalize_ranges(&mut map); + FileLines(Some(map)) + } + + /// Returns an iterator over the files contained in `self`. + pub fn files(&self) -> Files { + Files(self.0.as_ref().map(MultiMap::keys)) + } + + /// Returns true if `range` is fully contained in `self`. + pub fn contains(&self, range: &LineRange) -> bool { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match map.get_vec(range.file_name()) { + None => false, + Some(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + } + } + + /// Returns true if any lines in `range` are in `self`. + pub fn intersects(&self, range: &LineRange) -> bool { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match map.get_vec(range.file_name()) { + None => false, + Some(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), + } + } +} + +/// FileLines files iterator. +pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, String, Vec>>); + +impl<'a> iter::Iterator for Files<'a> { + type Item = &'a String; + + fn next(&mut self) -> Option<&'a String> { + self.0.as_mut().and_then(Iterator::next) + } +} + +// This impl is needed for `Config::override_value` to work for use in tests. +impl str::FromStr for FileLines { + type Err = String; + + fn from_str(s: &str) -> Result { + let v: Vec = try!(json::decode(s).map_err(|e| e.to_string())); + let m = v.into_iter().map(JsonSpan::into_tuple).collect(); + Ok(FileLines::from_multimap(m)) + } +} + +// For JSON decoding. +#[derive(Clone, Debug, RustcDecodable)] +struct JsonSpan { + file: String, + range: (usize, usize), +} + +impl JsonSpan { + // To allow `collect()`ing into a `MultiMap`. + fn into_tuple(self) -> (String, Range) { + let (lo, hi) = self.range; + (self.file, Range::new(lo, hi)) + } +} + +// This impl is needed for inclusion in the `Config` struct. We don't have a toml representation +// for `FileLines`, so it will just panic instead. +impl rustc_serialize::Decodable for FileLines { + fn decode(_: &mut D) -> Result { + unimplemented!(); + } +} + +#[cfg(test)] +mod test { + use super::Range; + + #[test] + fn test_range_intersects() { + assert!(Range::new(1, 2).intersects(Range::new(1, 1))); + assert!(Range::new(1, 2).intersects(Range::new(2, 2))); + assert!(!Range::new(1, 2).intersects(Range::new(0, 0))); + assert!(!Range::new(1, 2).intersects(Range::new(3, 10))); + assert!(!Range::new(1, 3).intersects(Range::new(5, 5))); + } + + #[test] + fn test_range_adjacent_to() { + assert!(!Range::new(1, 2).adjacent_to(Range::new(1, 1))); + assert!(!Range::new(1, 2).adjacent_to(Range::new(2, 2))); + assert!(Range::new(1, 2).adjacent_to(Range::new(0, 0))); + assert!(Range::new(1, 2).adjacent_to(Range::new(3, 10))); + assert!(!Range::new(1, 3).adjacent_to(Range::new(5, 5))); + } + + #[test] + fn test_range_contains() { + assert!(Range::new(1, 2).contains(Range::new(1, 1))); + assert!(Range::new(1, 2).contains(Range::new(2, 2))); + assert!(!Range::new(1, 2).contains(Range::new(0, 0))); + assert!(!Range::new(1, 2).contains(Range::new(3, 10))); + } + + #[test] + fn test_range_merge() { + assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); + assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); + assert_eq!(Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(4, 7))); + assert_eq!(Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(5, 7))); + assert_eq!(Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(6, 7))); + assert_eq!(Some(Range::new(3, 7)), + Range::new(3, 7).merge(Range::new(4, 5))); + } +} diff --git a/src/lib.rs b/src/lib.rs index 8df2c069bcc..322eed374de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ extern crate regex; extern crate diff; extern crate term; extern crate itertools; +extern crate multimap; use syntax::ast; use syntax::codemap::{mk_sp, CodeMap, Span}; @@ -54,6 +55,7 @@ mod utils; pub mod config; pub mod codemap; pub mod filemap; +pub mod file_lines; pub mod visitor; mod checkstyle; mod items; -- cgit 1.4.1-3-g733a5 From 9fa5a91fc50a5b7a7c2980e36e1bf63df3179500 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Fri, 11 Mar 2016 19:19:16 -0500 Subject: visitor: Handle specified line ranges in visit_stmt This commit adds a very rough implementation of handling the specified line ranges in `config.file_lines_map` for statements. It reformats a statement if its span is fully contained in the set of lines specified for the file. The implementation here is intended as a proof of concept, and demonstration that the machinery added in the preceding commits is functional. A final implementation would likely hook in via the `Rewrite` trait. Refs #434 --- src/visitor.rs | 7 ++++++- tests/source/file-lines-1.rs | 29 +++++++++++++++++++++++++++++ tests/source/file-lines-2.rs | 29 +++++++++++++++++++++++++++++ tests/source/file-lines-3.rs | 29 +++++++++++++++++++++++++++++ tests/source/file-lines-4.rs | 30 ++++++++++++++++++++++++++++++ tests/target/file-lines-1.rs | 30 ++++++++++++++++++++++++++++++ tests/target/file-lines-2.rs | 24 ++++++++++++++++++++++++ tests/target/file-lines-3.rs | 25 +++++++++++++++++++++++++ tests/target/file-lines-4.rs | 30 ++++++++++++++++++++++++++++++ 9 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 tests/source/file-lines-1.rs create mode 100644 tests/source/file-lines-2.rs create mode 100644 tests/source/file-lines-3.rs create mode 100644 tests/source/file-lines-4.rs create mode 100644 tests/target/file-lines-1.rs create mode 100644 tests/target/file-lines-2.rs create mode 100644 tests/target/file-lines-3.rs create mode 100644 tests/target/file-lines-4.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index c2ebcd17119..48b5e0ff7d2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,7 +16,7 @@ use strings::string_buffer::StringBuffer; use Indent; use utils; -use codemap::SpanUtils; +use codemap::{LineRangeUtils, SpanUtils}; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; @@ -47,6 +47,11 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(stmt.span.lo), self.codemap.lookup_char_pos(stmt.span.hi)); + // FIXME(#434): Move this check to somewhere more central, eg Rewrite. + if !self.config.file_lines.contains(&self.codemap.lookup_line_range(stmt.span)) { + return; + } + match stmt.node { ast::StmtKind::Decl(ref decl, _) => { if let ast::DeclKind::Item(ref item) = decl.node { diff --git a/tests/source/file-lines-1.rs b/tests/source/file-lines-1.rs new file mode 100644 index 00000000000..43c18d8f46f --- /dev/null +++ b/tests/source/file-lines-1.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-2.rs b/tests/source/file-lines-2.rs new file mode 100644 index 00000000000..6f8e9e6db3a --- /dev/null +++ b/tests/source/file-lines-2.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-3.rs b/tests/source/file-lines-3.rs new file mode 100644 index 00000000000..73d482695d6 --- /dev/null +++ b/tests/source/file-lines-3.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[4,8]},{"file":"tests/source/file-lines-3.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-4.rs b/tests/source/file-lines-4.rs new file mode 100644 index 00000000000..381f021515f --- /dev/null +++ b/tests/source/file-lines-4.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [] +// (Test that nothing is formatted if an empty array is specified.) + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-1.rs b/tests/target/file-lines-1.rs new file mode 100644 index 00000000000..5b8478e0303 --- /dev/null +++ b/tests/target/file-lines-1.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-2.rs b/tests/target/file-lines-2.rs new file mode 100644 index 00000000000..db4902d49b7 --- /dev/null +++ b/tests/target/file-lines-2.rs @@ -0,0 +1,24 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-3.rs b/tests/target/file-lines-3.rs new file mode 100644 index 00000000000..19359b2ddf9 --- /dev/null +++ b/tests/target/file-lines-3.rs @@ -0,0 +1,25 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[4,8]},{"file":"tests/source/file-lines-3.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call() + .method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-4.rs b/tests/target/file-lines-4.rs new file mode 100644 index 00000000000..381f021515f --- /dev/null +++ b/tests/target/file-lines-4.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [] +// (Test that nothing is formatted if an empty array is specified.) + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} -- cgit 1.4.1-3-g733a5 From bef5d095a4c59577d1400d980b7da62519bbe473 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 10 Apr 2016 13:03:54 -0400 Subject: rustfmt: Add option to specify line ranges for formatting This commit adds the `--experimental-file-lines` option to rustfmt. This allows specifying line ranges to format from the command line. Refs #434 --- README.md | 19 +++++++++++++++++++ src/bin/rustfmt.rs | 26 +++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 60b29956218..4f0714a9997 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,25 @@ the command line. For example `rustfmt --write-mode=display src/filename.rs` `cargo fmt` uses `--write-mode=replace` by default. +If you want to restrict reformatting to specific sets of lines, you can +use the `--file-lines` option. Its argument is a JSON array of objects +with `file` and `range` properties, where `file` is a file name, and +`range` is an array representing a range of lines like `[7,13]`. Ranges +are inclusive of both end points. Specifying an empty array will result in +no files being formatted. For example, + +``` +rustfmt --file-lines '[ + {"file":"src/lib.rs","range":[7,13]}, + {"file":"src/lib.rs","range":[21,29]}, + {"file":"src/foo.rs","range":[10,11]}, + {"file":"src/foo.rs","range":[15,15]}]' +``` + +would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`, +and `15` of `src/foo.rs`. No other files would be formatted, even if they +are included as out of line modules from `src/lib.rs`. + If `rustfmt` successfully reformatted the code it will exit with `0` exit status. Exit status `1` signals some unexpected error, like an unknown option or a failure to read a file. Exit status `2` is returned if there are syntax errors diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2105a962997..5aa7cc4e080 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,6 +18,7 @@ extern crate env_logger; extern crate getopts; use rustfmt::{run, Input, Summary}; +use rustfmt::file_lines::FileLines; use rustfmt::config::{Config, WriteMode}; use std::{env, error}; @@ -57,6 +58,7 @@ struct CliOptions { skip_children: bool, verbose: bool, write_mode: Option, + file_lines: FileLines, // Default is all lines in all files. } impl CliOptions { @@ -73,12 +75,17 @@ impl CliOptions { } } + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = try!(file_lines.parse()); + } + Ok(options) } - fn apply_to(&self, config: &mut Config) { + fn apply_to(self, config: &mut Config) { config.skip_children = self.skip_children; config.verbose = self.verbose; + config.file_lines = self.file_lines; if let Some(write_mode) = self.write_mode { config.write_mode = write_mode; } @@ -168,6 +175,10 @@ fn make_opts() -> Options { "Recursively searches the given path for the rustfmt.toml config file. If not \ found reverts to the input file path", "[Path for the configuration file]"); + opts.optopt("", + "file-lines", + "Format specified line ranges. See README for more detail on the JSON format.", + "JSON"); opts } @@ -198,8 +209,12 @@ fn execute(opts: &Options) -> FmtResult { Ok(run(Input::Text(input), &config)) } - Operation::Format { files, config_path } => { + Operation::Format { mut files, config_path } => { let options = try!(CliOptions::from_matches(&matches)); + + // Add any additional files that were specified via `--file-lines`. + files.extend(options.file_lines.files().cloned().map(PathBuf::from)); + let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -227,7 +242,7 @@ fn execute(opts: &Options) -> FmtResult { config = config_tmp; } - options.apply_to(&mut config); + options.clone().apply_to(&mut config); error_summary.add(run(Input::File(file), &config)); } Ok(error_summary) @@ -306,8 +321,8 @@ fn determine_operation(matches: &Matches) -> FmtResult { Some(dir) }); - // if no file argument is supplied, read from stdin - if matches.free.is_empty() { + // if no file argument is supplied and `--file-lines` is not specified, read from stdin + if matches.free.is_empty() && !matches.opt_present("file-lines") { let mut buffer = String::new(); try!(io::stdin().read_to_string(&mut buffer)); @@ -318,6 +333,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { }); } + // We append files from `--file-lines` later in `execute()`. let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); Ok(Operation::Format { -- cgit 1.4.1-3-g733a5 From a83f1a197e852820f0587ed39bf66bb79bda4707 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 30 May 2016 16:10:12 +0200 Subject: Add copyright notices to added files --- src/codemap.rs | 10 ++++++++++ src/file_lines.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs index 43c269e40a9..666bc67944d 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use std::rc::Rc; use syntax::codemap::{BytePos, CodeMap, FileMap, Span}; diff --git a/src/file_lines.rs b/src/file_lines.rs index e437202360d..9c60821a3bb 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -1,3 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + //! This module contains types and functions to support formatting specific line ranges. use std::{cmp, iter, str}; -- cgit 1.4.1-3-g733a5 From 8775fe417280413f37f8a22377404d2c870d3e83 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 30 May 2016 16:10:26 +0200 Subject: codemap: Add module description --- src/codemap.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs index 666bc67944d..9ec5c663064 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! This module contains utilities that work with the `CodeMap` from libsyntax / syntex_syntax. +//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. + use std::rc::Rc; use syntax::codemap::{BytePos, CodeMap, FileMap, Span}; -- cgit 1.4.1-3-g733a5 From 66483017f66b37b2c585cdfae4df59e89df41e42 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Mon, 30 May 2016 16:41:43 +0200 Subject: Explain that FileLines cannot be given in rustfmt.toml This adds a note to both the `--config-help` output for `file_lines`, and to the panic message on attempting to deserialize a `FileLines` struct. --- src/config.rs | 3 ++- src/file_lines.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index ecb63851417..51daa7a505a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -335,7 +335,8 @@ create_config! { verbose: bool, false, "Use verbose output"; skip_children: bool, false, "Don't reformat out of line modules"; file_lines: FileLines, FileLines::all(), - "Lines to format"; + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; diff --git a/src/file_lines.rs b/src/file_lines.rs index 9c60821a3bb..28fedad4cfd 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -181,7 +181,8 @@ impl JsonSpan { // for `FileLines`, so it will just panic instead. impl rustc_serialize::Decodable for FileLines { fn decode(_: &mut D) -> Result { - unimplemented!(); + panic!("FileLines cannot be deserialized from a project rustfmt.toml file: please \ + specify it via the `--file-lines` option instead"); } } -- cgit 1.4.1-3-g733a5 From 9759068e6280c8958d8ef769337d015794fb605f Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Tue, 31 May 2016 15:15:33 +0200 Subject: print_diff: Don't print color codes if output is not a tty On unix, `term::stdout()` just reads the `TERM` environment variable to decide what features are available. It does not check if the output file descriptor is in fact a tty. This resulted in printing escape codes when redirecting output. --- Cargo.lock | 3 +++ Cargo.toml | 7 +++++++ src/rustfmt_diff.rs | 26 ++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index fc8070979d6..1835836ba35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,8 @@ dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", @@ -15,6 +17,7 @@ dependencies = [ "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9d8ad68ed8a..d00f651aad1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,10 @@ env_logger = "0.3" getopts = "0.2" itertools = "0.4.15" multimap = "0.3" + +[target.'cfg(unix)'.dependencies] +libc = "0.2.11" + +[target.'cfg(windows)'.dependencies] +kernel32-sys = "0.2.2" +winapi = "0.2.7" diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index fe521029cb5..d5129bd1bca 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -88,10 +88,28 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F) where F: Fn(u32) -> String { - if let Some(t) = term::stdout() { - print_diff_fancy(diff, get_section_title, t); - } else { - print_diff_basic(diff, get_section_title); + match term::stdout() { + Some(_) if isatty() => print_diff_fancy(diff, get_section_title, term::stdout().unwrap()), + _ => print_diff_basic(diff, get_section_title), + } + + // isatty shamelessly adapted from cargo. + #[cfg(unix)] + fn isatty() -> bool { + extern crate libc; + + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } + } + #[cfg(windows)] + fn isatty() -> bool { + extern crate kernel32; + extern crate winapi; + + unsafe { + let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); + let mut out = 0; + kernel32::GetConsoleMode(handle, &mut out) != 0 + } } } -- cgit 1.4.1-3-g733a5 From b6263735b101b353bfee883046116b6b0e377589 Mon Sep 17 00:00:00 2001 From: lqd Date: Tue, 31 May 2016 19:48:49 +0200 Subject: Add support for the `default` keyword (#1025) Adds support for Defaultness on impl methods. Fixes #945 --- src/items.rs | 9 +++++++++ src/visitor.rs | 14 ++++++++++---- tests/source/issue-945.rs | 5 +++++ tests/target/issue-945.rs | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 tests/source/issue-945.rs create mode 100644 tests/target/issue-945.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d83ad3c88ee..7c73d1a6787 100644 --- a/src/items.rs +++ b/src/items.rs @@ -120,6 +120,7 @@ impl<'a> FmtVisitor<'a> { generics, ast::Unsafety::Normal, ast::Constness::NotConst, + ast::Defaultness::Final, // These are not actually rust functions, // but we format them as such. abi::Abi::Rust, @@ -168,6 +169,7 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, unsafety: ast::Unsafety, constness: ast::Constness, + defaultness: ast::Defaultness, abi: abi::Abi, vis: &ast::Visibility, span: Span, @@ -187,6 +189,7 @@ impl<'a> FmtVisitor<'a> { generics, unsafety, constness, + defaultness, abi, vis, span, @@ -231,6 +234,7 @@ impl<'a> FmtVisitor<'a> { &sig.generics, sig.unsafety, sig.constness, + ast::Defaultness::Final, sig.abi, &ast::Visibility::Inherited, span, @@ -1220,6 +1224,7 @@ fn rewrite_fn_base(context: &RewriteContext, generics: &ast::Generics, unsafety: ast::Unsafety, constness: ast::Constness, + defaultness: ast::Defaultness, abi: abi::Abi, vis: &ast::Visibility, span: Span, @@ -1236,6 +1241,10 @@ fn rewrite_fn_base(context: &RewriteContext, // Vis unsafety abi. result.push_str(&*format_visibility(vis)); + if let ast::Defaultness::Default = defaultness { + result.push_str("default "); + } + if let ast::Constness::Const = constness { result.push_str("const "); } diff --git a/src/visitor.rs b/src/visitor.rs index 48b5e0ff7d2..c5962e986b5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -141,7 +141,8 @@ impl<'a> FmtVisitor<'a> { fd: &ast::FnDecl, b: &ast::Block, s: Span, - _: ast::NodeId) { + _: ast::NodeId, + defaultness: ast::Defaultness) { let indent = self.block_indent; let rewrite = match fk { visit::FnKind::ItemFn(ident, ref generics, unsafety, constness, abi, vis) => { @@ -151,6 +152,7 @@ impl<'a> FmtVisitor<'a> { generics, unsafety, constness, + defaultness, abi, vis, codemap::mk_sp(s.lo, b.span.lo), @@ -163,6 +165,7 @@ impl<'a> FmtVisitor<'a> { &sig.generics, sig.unsafety, sig.constness, + defaultness, sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), codemap::mk_sp(s.lo, b.span.lo), @@ -332,7 +335,8 @@ impl<'a> FmtVisitor<'a> { decl, body, item.span, - item.id) + item.id, + ast::Defaultness::Final) } ast::ItemKind::Ty(ref ty, ref generics) => { let rewrite = rewrite_type_alias(&self.get_context(), @@ -373,7 +377,8 @@ impl<'a> FmtVisitor<'a> { &sig.decl, &body, ti.span, - ti.id); + ti.id, + ast::Defaultness::Final); } ast::TraitItemKind::Type(ref type_param_bounds, _) => { let rewrite = rewrite_associated_type(ti.ident, @@ -397,7 +402,8 @@ impl<'a> FmtVisitor<'a> { &sig.decl, body, ii.span, - ii.id); + ii.id, + ii.defaultness); } ast::ImplItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static("const", diff --git a/tests/source/issue-945.rs b/tests/source/issue-945.rs new file mode 100644 index 00000000000..37d703c4679 --- /dev/null +++ b/tests/source/issue-945.rs @@ -0,0 +1,5 @@ +impl Bar { default const unsafe fn foo() { "hi" } } + +impl Baz { default unsafe extern "C" fn foo() { "hi" } } + +impl Foo for Bar { default fn foo() { "hi" } } diff --git a/tests/target/issue-945.rs b/tests/target/issue-945.rs new file mode 100644 index 00000000000..d46c69a4f09 --- /dev/null +++ b/tests/target/issue-945.rs @@ -0,0 +1,17 @@ +impl Bar { + default const unsafe fn foo() { + "hi" + } +} + +impl Baz { + default unsafe extern "C" fn foo() { + "hi" + } +} + +impl Foo for Bar { + default fn foo() { + "hi" + } +} -- cgit 1.4.1-3-g733a5 From b3488c618638c6e9288cbe9b2b34ca1109a06a1d Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 3 Jun 2016 23:18:19 +0200 Subject: Fix constraints on pattern formatting of else arms --- src/comment.rs | 44 +++++++++++++++++++++++--------------------- src/expr.rs | 14 ++++++++++++-- tests/source/expr.rs | 13 +++++++++++++ tests/target/expr.rs | 15 +++++++++++++++ 4 files changed, 63 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e417e29936e..66cc5e2fb6f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -29,29 +29,30 @@ pub fn rewrite_comment(orig: &str, let s = orig.trim(); // Edge case: block comments. Let's not trim their lines (for now). - let (opener, closer, line_start) = if block_style { - ("/* ", " */", " * ") - } else if !config.normalize_comments { - if orig.starts_with("/**") { - ("/** ", " **/", " ** ") - } else if orig.starts_with("/*!") { - ("/*! ", " */", " * ") - } else if orig.starts_with("/*") { + let (opener, closer, line_start) = + if block_style { ("/* ", " */", " * ") - } else if orig.starts_with("///") { + } else if !config.normalize_comments { + if orig.starts_with("/**") { + ("/** ", " **/", " ** ") + } else if orig.starts_with("/*!") { + ("/*! ", " */", " * ") + } else if orig.starts_with("/*") { + ("/* ", " */", " * ") + } else if orig.starts_with("///") { + ("/// ", "", "/// ") + } else if orig.starts_with("//!") { + ("//! ", "", "//! ") + } else { + ("// ", "", "// ") + } + } else if orig.starts_with("///") || orig.starts_with("/**") { ("/// ", "", "/// ") - } else if orig.starts_with("//!") { + } else if orig.starts_with("//!") || orig.starts_with("/*!") { ("//! ", "", "//! ") } else { ("// ", "", "// ") - } - } else if orig.starts_with("///") || orig.starts_with("/**") { - ("/// ", "", "/// ") - } else if orig.starts_with("//!") || orig.starts_with("/*!") { - ("//! ", "", "//! ") - } else { - ("// ", "", "// ") - }; + }; let max_chars = width.checked_sub(closer.len() + opener.len()).unwrap_or(1); @@ -127,11 +128,12 @@ fn left_trim_comment_line(line: &str) -> &str { line.starts_with("/** ") { &line[4..] } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || - line.starts_with("///") || line.starts_with("** ") || line.starts_with("/*!") || - line.starts_with("/**") { + line.starts_with("///") || + line.starts_with("** ") || line.starts_with("/*!") || + line.starts_with("/**") { &line[3..] } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || - line.starts_with("**") { + line.starts_with("**") { &line[2..] } else if line.starts_with("*") { &line[1..] diff --git a/src/expr.rs b/src/expr.rs index af0492b2913..509f790842f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -725,6 +725,14 @@ fn rewrite_if_else(context: &RewriteContext, offset: Indent, allow_single_line: bool) -> Option { + let (budget, indent) = if !allow_single_line { + // We are part of an if-elseif-else chain. Our constraints are tightened. + // 7 = "} else" .len() + (try_opt!(width.checked_sub(7)), offset + 7) + } else { + (width, offset) + }; + // 3 = "if ", 2 = " {" let pat_penalty = match context.config.else_if_brace_style { ElseIfBraceStyle::AlwaysNextLine => 3, @@ -735,8 +743,8 @@ fn rewrite_if_else(context: &RewriteContext, cond, "let ", " =", - try_opt!(width.checked_sub(pat_penalty)), - offset + 3)); + try_opt!(budget.checked_sub(pat_penalty)), + indent + 3)); // Try to format if-else on single line. if expr_type == ExprType::SubExpression && allow_single_line && @@ -778,6 +786,8 @@ fn rewrite_if_else(context: &RewriteContext, let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it // from being formatted on a single line. + // Note how we're passing the original width and offset, as the + // cost of "else" should not cascade. ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { rewrite_if_else(context, cond, diff --git a/tests/source/expr.rs b/tests/source/expr.rs index ee24e742641..cb3c59b10ce 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -272,3 +272,16 @@ fn if_else() { -1.0 }; } + +fn complex_if_else() { + if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { + yo(); + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { + yo(); + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 87a45a98d49..12ac778be69 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -275,3 +275,18 @@ fn if_else() { let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; } + +fn complex_if_else() { + if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { + yo(); + } else if let Some(x) = + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + xxxxxxxxx { + yo(); + } +} -- cgit 1.4.1-3-g733a5 From 2ea99869a7372c533c6289ec609b75a430d156ce Mon Sep 17 00:00:00 2001 From: Jacob Clark Date: Mon, 6 Jun 2016 22:30:40 +0100 Subject: Refactor string collects to itertools join --- src/items.rs | 3 +-- src/types.rs | 39 +++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7c73d1a6787..fd0dd9d6a67 100644 --- a/src/items.rs +++ b/src/items.rs @@ -21,6 +21,7 @@ use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle}; +use itertools::Itertools; use syntax::{ast, abi, ptr, codemap}; use syntax::codemap::{Span, BytePos, mk_sp}; @@ -1056,7 +1057,6 @@ pub fn rewrite_associated_type(ident: ast::Ident, let bounds: &[_] = &ty_param_bounds; let bound_str = bounds.iter() .filter_map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) - .collect::>() .join(" + "); if bounds.len() > 0 { format!(": {}", bound_str) @@ -1702,7 +1702,6 @@ fn rewrite_trait_bounds(context: &RewriteContext, let bound_str = bounds.iter() .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) - .collect::>() .join(" + "); let mut result = String::new(); diff --git a/src/types.rs b/src/types.rs index b1b9b749dd8..0c35c82791f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -23,6 +23,7 @@ use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::TypeDensity; +use itertools::Itertools; // Does not wrap on simple segments. pub fn rewrite_path(context: &RewriteContext, @@ -331,8 +332,9 @@ impl Rewrite for ast::WherePredicate { width, offset) }) - .collect::>>()) - .join(", "); + .intersperse(Some(", ".to_string())) + .collect::>()); + // 8 = "for<> : ".len() let used_width = lifetime_str.len() + type_str.len() + 8; let budget = try_opt!(width.checked_sub(used_width)); @@ -342,8 +344,8 @@ impl Rewrite for ast::WherePredicate { budget, offset + used_width) }) - .collect::>>()) - .join(" + "); + .intersperse(Some(" + ".to_string())) + .collect::>()); format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { @@ -356,8 +358,8 @@ impl Rewrite for ast::WherePredicate { budget, offset + used_width) }) - .collect::>>()) - .join(" + "); + .intersperse(Some(" + ".to_string())) + .collect::>()); format!("{}: {}", type_str, bounds_str) } @@ -450,10 +452,10 @@ impl Rewrite for ast::TyParam { result.push_str(": "); let bounds = try_opt!(self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, width, offset)) - .collect::>>()) - .join(" + "); + .iter() + .map(|ty_bound| ty_bound.rewrite(context, width, offset)) + .intersperse(Some(" + ".to_string())) + .collect::>()); result.push_str(&bounds); } @@ -477,10 +479,11 @@ impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if !self.bound_lifetimes.is_empty() { let lifetime_str = try_opt!(self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, width, offset)) - .collect::>>()) - .join(", "); + .iter() + .map(|lt| lt.rewrite(context, width, offset)) + .intersperse(Some(", ".to_string())) + .collect::>()); + // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(width.checked_sub(extra_offset)); @@ -604,10 +607,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. result.push_str(&try_opt!(bare_fn.lifetimes - .iter() - .map(|l| l.rewrite(context, try_opt!(width.checked_sub(6)), offset + 4)) - .collect::>>()) - .join(", ")); + .iter() + .map(|l| l.rewrite(context, try_opt!(width.checked_sub(6)), offset + 4)) + .intersperse(Some(", ".to_string())) + .collect::>())); result.push_str("> "); } -- cgit 1.4.1-3-g733a5 From 77edbb7defec2cbc011d9b86301dfa28094f1444 Mon Sep 17 00:00:00 2001 From: Jacob Clark Date: Tue, 7 Jun 2016 00:03:25 +0100 Subject: Refactoring exsisting filter_maps to maps --- src/items.rs | 14 ++++++++------ src/types.rs | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index fd0dd9d6a67..1de56220cf4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1055,9 +1055,10 @@ pub fn rewrite_associated_type(ident: ast::Ident, let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = &ty_param_bounds; - let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) - .join(" + "); + let bound_str = try_opt!(bounds.iter() + .map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) + .intersperse(Some(" + ".to_string())) + .collect::>()); if bounds.len() > 0 { format!(": {}", bound_str) } else { @@ -1700,9 +1701,10 @@ fn rewrite_trait_bounds(context: &RewriteContext, return Some(String::new()); } - let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) - .join(" + "); + let bound_str = try_opt!(bounds.iter() + .map(|ty_bound| ty_bound.rewrite(&context, width, indent)) + .intersperse(Some(" + ".to_string())) + .collect::>()); let mut result = String::new(); result.push_str(": "); diff --git a/src/types.rs b/src/types.rs index 0c35c82791f..8fa24df0caa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -326,40 +326,40 @@ impl Rewrite for ast::WherePredicate { let type_str = try_opt!(bounded_ty.rewrite(context, width, offset)); if !bound_lifetimes.is_empty() { - let lifetime_str = try_opt!(bound_lifetimes.iter() + let lifetime_str: String = try_opt!(bound_lifetimes.iter() .map(|lt| { lt.rewrite(context, width, offset) }) .intersperse(Some(", ".to_string())) - .collect::>()); + .collect()); // 8 = "for<> : ".len() let used_width = lifetime_str.len() + type_str.len() + 8; let budget = try_opt!(width.checked_sub(used_width)); - let bounds_str = try_opt!(bounds.iter() + let bounds_str: String = try_opt!(bounds.iter() .map(|ty_bound| { ty_bound.rewrite(context, budget, offset + used_width) }) .intersperse(Some(" + ".to_string())) - .collect::>()); + .collect()); format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) } else { // 2 = ": ".len() let used_width = type_str.len() + 2; let budget = try_opt!(width.checked_sub(used_width)); - let bounds_str = try_opt!(bounds.iter() + let bounds_str: String = try_opt!(bounds.iter() .map(|ty_bound| { ty_bound.rewrite(context, budget, offset + used_width) }) .intersperse(Some(" + ".to_string())) - .collect::>()); + .collect()); format!("{}: {}", type_str, bounds_str) } @@ -451,11 +451,11 @@ impl Rewrite for ast::TyParam { if !self.bounds.is_empty() { result.push_str(": "); - let bounds = try_opt!(self.bounds + let bounds: String = try_opt!(self.bounds .iter() .map(|ty_bound| ty_bound.rewrite(context, width, offset)) .intersperse(Some(" + ".to_string())) - .collect::>()); + .collect()); result.push_str(&bounds); } @@ -478,11 +478,11 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if !self.bound_lifetimes.is_empty() { - let lifetime_str = try_opt!(self.bound_lifetimes + let lifetime_str: String = try_opt!(self.bound_lifetimes .iter() .map(|lt| lt.rewrite(context, width, offset)) .intersperse(Some(", ".to_string())) - .collect::>()); + .collect()); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; -- cgit 1.4.1-3-g733a5 From 1b55aa9f10d7227c5677aa2002a1e859cd3abe14 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 10 Jun 2016 15:09:27 +0200 Subject: Fix integer underflow --- src/expr.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 509f790842f..478c312b36f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1278,7 +1278,7 @@ fn rewrite_pat_expr(context: &RewriteContext, let spacer = if pat.is_some() { " " } else { "" }; let expr_rewrite = expr.rewrite(context, - width - extra_offset - spacer.len(), + try_opt!(width.checked_sub(extra_offset + spacer.len())), offset + extra_offset + spacer.len()); if let Some(expr_string) = expr_rewrite { @@ -1292,9 +1292,10 @@ fn rewrite_pat_expr(context: &RewriteContext, result.push('\n'); result.push_str(&pat_offset.to_string(context.config)); - let expr_rewrite = expr.rewrite(context, - context.config.max_width - pat_offset.width(), - pat_offset); + let expr_rewrite = + expr.rewrite(context, + try_opt!(context.config.max_width.checked_sub(pat_offset.width())), + pat_offset); result.push_str(&&try_opt!(expr_rewrite)); Some(result) -- cgit 1.4.1-3-g733a5 From 88fdf9a6e3bf6a8064d195311f31656f4ab0da2a Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 10 Jun 2016 16:16:14 +0200 Subject: Fix integer underflow in extra_offset --- src/utils.rs | 3 +-- tests/target/issue-1055.rs | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-1055.rs (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 82fbb8d5925..5807d4c158c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -23,11 +23,10 @@ use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; // Computes the length of a string's last line, minus offset. -#[inline] pub fn extra_offset(text: &str, offset: Indent) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => text.len() - idx - 1 - offset.width(), + Some(idx) => text.len().checked_sub(idx + 1 + offset.width()).unwrap_or(0), None => text.len(), } } diff --git a/tests/target/issue-1055.rs b/tests/target/issue-1055.rs new file mode 100644 index 00000000000..fed7d7de393 --- /dev/null +++ b/tests/target/issue-1055.rs @@ -0,0 +1,4 @@ +fn issue_1055() { + let foo = (|| { + })(); +} -- cgit 1.4.1-3-g733a5 From 5361f611107bdaed67dfeffe3e20aad082556ef7 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 12 Jun 2016 10:38:03 +0200 Subject: Include git commit and worktree status in version output (#1060) This will help in debugging issues as rustfmt gets more users. If the working tree is clean, output looks like $ target/debug/rustfmt -V 0.5.0 (9f5ed3b) If the working tree is dirty, output looks like $ target/debug/rustfmt -V 0.5.0 (9f5ed3b worktree dirty) If git is unavailable, output looks like $ target/debug/rustfmt -V 0.5.0 (git commit unavailable) To avoid rebuilds on changing tests, the build script will only rerun if files under src/ are changed. This means the actual git status may show changed files and this would not show up in the version. This should not be an issue as files not in src/ should not affect the build output. --- Cargo.lock | 10 ++++++++++ Cargo.toml | 4 ++++ build.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/rustfmt.rs | 18 ++++++++++++----- tests/system.rs | 1 + 5 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 build.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 1835836ba35..84293a46205 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,7 @@ dependencies = [ "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -190,6 +191,15 @@ name = "utf8-ranges" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.7" diff --git a/Cargo.toml b/Cargo.toml index d00f651aad1..dbf3e1edee0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ repository = "https://github.com/rust-lang-nursery/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" include = ["src/*.rs", "Cargo.toml"] +build = "build.rs" [features] default = ["cargo-fmt"] @@ -28,6 +29,9 @@ getopts = "0.2" itertools = "0.4.15" multimap = "0.3" +[build-dependencies] +walkdir = "0.1.5" + [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/build.rs b/build.rs new file mode 100644 index 00000000000..9192426f99a --- /dev/null +++ b/build.rs @@ -0,0 +1,57 @@ +extern crate walkdir; + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::Path; +use std::process::Command; + +use walkdir::WalkDir; + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("git_info.rs"); + let mut f = File::create(&dest_path).unwrap(); + + writeln!(f, + "const COMMIT_HASH: Option<&'static str> = {:?};", + git_head_sha1()) + .unwrap(); + writeln!(f, + "const WORKTREE_CLEAN: Option = {:?};", + git_tree_is_clean()) + .unwrap(); + + // cargo:rerun-if-changed requires one entry per individual file. + for entry in WalkDir::new("src") { + let entry = entry.unwrap(); + println!("cargo:rerun-if-changed={}", entry.path().display()); + } +} + +// Returns `None` if git is not available. +fn git_head_sha1() -> Option { + Command::new("git") + .arg("rev-parse") + .arg("--short") + .arg("HEAD") + .output() + .ok() + .and_then(|o| String::from_utf8(o.stdout).ok()) + .map(|mut s| { + let len = s.trim_right().len(); + s.truncate(len); + s + }) +} + +// Returns `None` if git is not available. +fn git_tree_is_clean() -> Option { + Command::new("git") + .arg("status") + .arg("--porcelain") + .arg("--untracked-files=no") + .output() + .ok() + .map(|o| o.stdout.is_empty()) +} diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5aa7cc4e080..30894b9d03c 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -29,6 +29,12 @@ use std::str::FromStr; use getopts::{Matches, Options}; +// Include git commit hash and worktree status; contents are like +// const COMMIT_HASH: Option<&'static str> = Some("c31a366"); +// const WORKTREE_CLEAN: Option = Some(false); +// with `None` if running git failed, eg if it is not installed. +include!(concat!(env!("OUT_DIR"), "/git_info.rs")); + type FmtError = Box; type FmtResult = std::result::Result; @@ -291,11 +297,13 @@ fn print_usage(opts: &Options, reason: &str) { } fn print_version() { - println!("{}.{}.{}{}", - option_env!("CARGO_PKG_VERSION_MAJOR").unwrap_or("X"), - option_env!("CARGO_PKG_VERSION_MINOR").unwrap_or("X"), - option_env!("CARGO_PKG_VERSION_PATCH").unwrap_or("X"), - option_env!("CARGO_PKG_VERSION_PRE").unwrap_or("")); + println!("{} ({}{})", + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), + COMMIT_HASH.unwrap_or("git commit unavailable"), + match WORKTREE_CLEAN { + Some(false) => " worktree dirty", + _ => "", + }); } fn determine_operation(matches: &Matches) -> FmtResult { diff --git a/tests/system.rs b/tests/system.rs index 38d1e8584a5..08ec576f221 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -121,6 +121,7 @@ fn self_tests() { .map(get_path_string); // Hack because there's no `IntoIterator` impl for `[T; N]`. let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); + let files = files.chain(Some("build.rs".to_owned()).into_iter()); let (reports, count, fails) = check_files(files); let mut warnings = 0; -- cgit 1.4.1-3-g733a5 From 921b56384731e73c558f786629e103125b4a3438 Mon Sep 17 00:00:00 2001 From: Seo Sanghyeon Date: Thu, 9 Jun 2016 00:43:08 +0900 Subject: Fix width computation in Loop::rewrite --- src/expr.rs | 11 ++++++++++- tests/source/loop.rs | 2 ++ tests/target/loop.rs | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 509f790842f..826897a2b26 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -504,6 +504,9 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option Option { + // width is used only for the single line case: either the empty block `{}`, + // or an unsafe expression `unsafe { e }`. + let user_str = context.snippet(self.span); if user_str == "{}" && width >= 2 { return Some(user_str); @@ -674,9 +677,15 @@ impl<'a> Rewrite for Loop<'a> { ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), ControlBraceStyle::AlwaysSameLine => " ", }; + + // This is used only for the empty block case: `{}` + let block_width = try_opt!(width.checked_sub(label_string.len() + self.keyword.len() + + extra_offset(&pat_expr_string, inner_offset) + + 1)); + // FIXME: this drops any comment between "loop" and the block. self.block - .rewrite(context, width, offset) + .rewrite(context, block_width, offset) .map(|result| { format!("{}{}{}{}{}", label_string, diff --git a/tests/source/loop.rs b/tests/source/loop.rs index c7f7da71831..e1266197a1c 100644 --- a/tests/source/loop.rs +++ b/tests/source/loop.rs @@ -14,6 +14,8 @@ let x = loop { do_forever(); }; while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {} + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { // do smth } diff --git a/tests/target/loop.rs b/tests/target/loop.rs index 648fe826e8f..ea84c00c22b 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -18,6 +18,9 @@ fn main() { while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + } + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { // do smth -- cgit 1.4.1-3-g733a5 From 8260d277c88f18c708ed9ebb319ae59f6c0c109f Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Mon, 20 Jun 2016 20:42:29 +0200 Subject: Return failure exit code on found diffs (fix #906) This changes rustfmt to return exit code 4 when run with write mode diff and differences between the formatted code and the original code are found. Useful for CI to make sure your contributors actually ran rustfmt. --- src/bin/rustfmt.rs | 3 +++ src/filemap.rs | 11 +++++++---- src/lib.rs | 20 +++++++++++++------- src/summary.rs | 12 +++++++++++- 4 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 30894b9d03c..bf78bb39fe4 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -269,6 +269,9 @@ fn main() { 2 } else if summary.has_formatting_errors() { 3 + } else if summary.has_diff { + // should only happen in diff mode + 4 } else { assert!(summary.has_no_errors()); 0 diff --git a/src/filemap.rs b/src/filemap.rs index 17abc6f76e7..1fca0d5b012 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -82,7 +82,7 @@ pub fn write_file(text: &StringBuffer, filename: &str, out: &mut T, config: &Config) - -> Result, io::Error> + -> Result where T: Write { @@ -146,8 +146,10 @@ pub fn write_file(text: &StringBuffer, WriteMode::Diff => { println!("Diff of {}:\n", filename); if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - print_diff(make_diff(&ori, &fmt, 3), - |line_num| format!("\nDiff at line {}:", line_num)); + let mismatch = make_diff(&ori, &fmt, 3); + let has_diff = !mismatch.is_empty(); + print_diff(mismatch, |line_num| format!("\nDiff at line {}:", line_num)); + return Ok(has_diff); } } WriteMode::Checkstyle => { @@ -156,5 +158,6 @@ pub fn write_file(text: &StringBuffer, } } - Ok(None) + // when we are not in diff mode, don't indicate differing files + Ok(false) } diff --git a/src/lib.rs b/src/lib.rs index 322eed374de..17af40d9b37 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -286,10 +286,12 @@ fn format_ast(krate: &ast::Crate, main_file: &Path, config: &Config, mut after_file: F) - -> Result - where F: FnMut(&str, &mut StringBuffer) -> Result<(), io::Error> + -> Result<(FileMap, bool), io::Error> + where F: FnMut(&str, &mut StringBuffer) -> Result { let mut result = FileMap::new(); + // diff mode: check if any files are differing + let mut has_diff = false; // We always skip children for the "Plain" write mode, since there is // nothing to distinguish the nested module contents. @@ -305,12 +307,12 @@ fn format_ast(krate: &ast::Crate, let mut visitor = FmtVisitor::from_codemap(parse_session, config); visitor.format_separate_mod(module); - try!(after_file(path, &mut visitor.buffer)); + has_diff |= try!(after_file(path, &mut visitor.buffer)); result.push((path.to_owned(), visitor.buffer)); } - Ok(result) + Ok((result, has_diff)) } // Formatting done on a char by char or line by line basis. @@ -458,15 +460,19 @@ pub fn format_input(input: Input, format_lines(file, file_name, config, &mut report); if let Some(ref mut out) = out { - try!(filemap::write_file(file, file_name, out, config)); + return filemap::write_file(file, file_name, out, config); } - Ok(()) + Ok(false) }) { - Ok(file_map) => { + Ok((file_map, has_diff)) => { if report.has_warnings() { summary.add_formatting_error(); } + if has_diff { + summary.add_diff(); + } + Ok((summary, file_map, report)) } Err(e) => Err((e, summary)), diff --git a/src/summary.rs b/src/summary.rs index 87d20899a58..5846afde7fc 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -9,6 +9,9 @@ pub struct Summary { // Code is valid, but it is impossible to format it properly. has_formatting_errors: bool, + + // Formatted code differs from existing code (write-mode diff only). + pub has_diff: bool, } impl Summary { @@ -17,6 +20,7 @@ impl Summary { has_operational_errors: false, has_parsing_errors: false, has_formatting_errors: false, + has_diff: false, } } @@ -44,13 +48,19 @@ impl Summary { self.has_formatting_errors = true; } + pub fn add_diff(&mut self) { + self.has_diff = true; + } + pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors) + !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors || + self.has_diff) } pub fn add(&mut self, other: Summary) { self.has_operational_errors |= other.has_operational_errors; self.has_formatting_errors |= other.has_formatting_errors; self.has_parsing_errors |= other.has_parsing_errors; + self.has_diff |= other.has_diff; } } -- cgit 1.4.1-3-g733a5 From ddda46d265f0b629e042ebd8c858500971170de3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 4 Jul 2016 15:46:58 +1200 Subject: rustup --- Cargo.lock | 18 +++++++++--------- src/bin/cargo-fmt.rs | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 84293a46205..857940114fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,9 +5,9 @@ dependencies = [ "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)", @@ -55,7 +55,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -69,7 +69,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -82,7 +82,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -98,7 +98,7 @@ dependencies = [ "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -126,7 +126,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -157,12 +157,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 909d62b20f8..93a9326918c 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -11,7 +11,6 @@ // Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) #![cfg(not(test))] -#![cfg(feature="cargo-fmt")] #![deny(warnings)] extern crate getopts; -- cgit 1.4.1-3-g733a5 From 033741246cdb8c653cc3bf9a6cc12f23dac08e6e Mon Sep 17 00:00:00 2001 From: Johann Hofmann Date: Sat, 2 Jul 2016 22:19:04 +0200 Subject: Show more helpful error if rustfmt is not in PATH. This fixes #1071. --- src/bin/cargo-fmt.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 909d62b20f8..7bd61dd1661 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -204,6 +204,16 @@ fn format_files(files: &Vec, .stdout(stdout) .args(files) .args(fmt_args) - .spawn()); + .spawn() + .map_err(|e| { + match e.kind() { + std::io::ErrorKind::NotFound => { + std::io::Error::new(std::io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your \ + PATH.") + } + _ => e, + } + })); command.wait() } -- cgit 1.4.1-3-g733a5 From 0dc3fc7a2c0dd6ac5a4f4df1c83b4e8e41b042dd Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 9 Jul 2016 22:41:28 +0900 Subject: Fix formatting empty block comments (`/**/`) issue #1086 --- src/comment.rs | 10 ++++++---- tests/source/comment.rs | 4 ++++ tests/target/comment.rs | 4 ++++ 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 66cc5e2fb6f..062e4ba0ca7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -33,7 +33,7 @@ pub fn rewrite_comment(orig: &str, if block_style { ("/* ", " */", " * ") } else if !config.normalize_comments { - if orig.starts_with("/**") { + if orig.starts_with("/**") && !orig.starts_with("/**/") { ("/** ", " **/", " ** ") } else if orig.starts_with("/*!") { ("/*! ", " */", " * ") @@ -46,7 +46,8 @@ pub fn rewrite_comment(orig: &str, } else { ("// ", "", "// ") } - } else if orig.starts_with("///") || orig.starts_with("/**") { + } else if orig.starts_with("///") || + (orig.starts_with("/**") && !orig.starts_with("/**/")) { ("/// ", "", "/// ") } else if orig.starts_with("//!") || orig.starts_with("/*!") { ("//! ", "", "//! ") @@ -130,7 +131,7 @@ fn left_trim_comment_line(line: &str) -> &str { } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || line.starts_with("///") || line.starts_with("** ") || line.starts_with("/*!") || - line.starts_with("/**") { + (line.starts_with("/**") && !line.starts_with("/**/")) { &line[3..] } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || line.starts_with("**") { @@ -606,7 +607,8 @@ fn remove_comment_header(comment: &str) -> &str { &comment[3..] } else if comment.starts_with("//") { &comment[2..] - } else if comment.starts_with("/**") || comment.starts_with("/*!") { + } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) || + comment.starts_with("/*!") { &comment[3..comment.len() - 2] } else { assert!(comment.starts_with("/*"), diff --git a/tests/source/comment.rs b/tests/source/comment.rs index 8cfde87f8c4..e461a2041ff 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -43,6 +43,10 @@ fn chains() { /* comment */ x }) } +fn issue_1086() { + /**/ +} + /* * random comment */ diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 98815ac5403..9577ff22b60 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -45,6 +45,10 @@ fn chains() { }) } +fn issue_1086() { + // +} + // random comment fn main() { -- cgit 1.4.1-3-g733a5 From 9750fb7fca8dfc16752c79f1e0b5f4a2d73c4563 Mon Sep 17 00:00:00 2001 From: Stuart Dootson Date: Mon, 18 Jul 2016 22:05:01 +0100 Subject: Canonicalize file paths within the map of file line ranges (#1098) * Canonicalize file paths within the map of file line ranges * Forgot to run the tests - and of course, the formatting of the canonicalization change was off, but it's fixed now! * Move imports to the top of the file, as per @nrc. * Change `canonicalize_path_string` to return `Option`, `None` indicating an error rather than an empty string * `format!` is better than string concatenation... * Change `canonicalize_path_string` to return `Result` rather than `Option` --- src/file_lines.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index 28fedad4cfd..61b43375dda 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -9,7 +9,7 @@ // except according to those terms. //! This module contains types and functions to support formatting specific line ranges. -use std::{cmp, iter, str}; +use std::{cmp, iter, path, str}; use itertools::Itertools; use multimap::MultiMap; @@ -119,9 +119,10 @@ impl FileLines { Some(ref map) => map, }; - match map.get_vec(range.file_name()) { - None => false, - Some(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + match canonicalize_path_string(range.file_name()) + .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { + Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + Err(_) => false, } } @@ -151,13 +152,20 @@ impl<'a> iter::Iterator for Files<'a> { } } +fn canonicalize_path_string(s: &str) -> Result { + match path::PathBuf::from(s).canonicalize() { + Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()).ok_or(()), + _ => Err(()), + } +} + // This impl is needed for `Config::override_value` to work for use in tests. impl str::FromStr for FileLines { type Err = String; fn from_str(s: &str) -> Result { let v: Vec = try!(json::decode(s).map_err(|e| e.to_string())); - let m = v.into_iter().map(JsonSpan::into_tuple).collect(); + let m = try!(v.into_iter().map(JsonSpan::into_tuple).collect()); Ok(FileLines::from_multimap(m)) } } @@ -171,9 +179,11 @@ struct JsonSpan { impl JsonSpan { // To allow `collect()`ing into a `MultiMap`. - fn into_tuple(self) -> (String, Range) { + fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - (self.file, Range::new(lo, hi)) + let canonical = try!(canonicalize_path_string(&self.file) + .map_err(|_| format!("Can't canonicalize {}", &self.file))); + Ok((canonical, Range::new(lo, hi))) } } -- cgit 1.4.1-3-g733a5 From 78b52ec3e130c0ead70f3e902206b7b068c53b9c Mon Sep 17 00:00:00 2001 From: Stuart Dootson Date: Tue, 26 Jul 2016 06:20:01 +0100 Subject: Add `use` declaration re-ordering (#1104) * Add config options for combinations of lines and items * Reordering of import lines implemented. * Changed nested matches to tuple pattern matching * Added ordering of path list items to the ordering of use declarations * Move `format_imports` and `format_import` methods to `imports.rs` * Add comment to explain how `use` declarations are split off while walking through a module * Change `ImportReordering` config option to separate boolean options --- src/config.rs | 2 + src/imports.rs | 170 +++++++++++++++++++++++- src/utils.rs | 7 + src/visitor.rs | 64 ++++----- tests/source/imports-reorder-lines-and-items.rs | 9 ++ tests/source/imports-reorder-lines.rs | 34 +++++ tests/source/imports-reorder.rs | 2 +- tests/target/imports-reorder-lines-and-items.rs | 9 ++ tests/target/imports-reorder-lines.rs | 33 +++++ tests/target/imports-reorder.rs | 2 +- 10 files changed, 287 insertions(+), 45 deletions(-) create mode 100644 tests/source/imports-reorder-lines-and-items.rs create mode 100644 tests/source/imports-reorder-lines.rs create mode 100644 tests/target/imports-reorder-lines-and-items.rs create mode 100644 tests/target/imports-reorder-lines.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 51daa7a505a..9cd15bc0e33 100644 --- a/src/config.rs +++ b/src/config.rs @@ -391,6 +391,8 @@ create_config! { chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain"; chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; + reorder_imported_names: bool, false, + "Reorder lists of names in import statements alphabetically"; single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ expressions. A value of zero means always break \ if-else expressions."; diff --git a/src/imports.rs b/src/imports.rs index 89030392774..36953463d38 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -9,13 +9,120 @@ // except according to those terms. use Indent; +use utils; +use syntax::codemap::{self, BytePos, Span}; use codemap::SpanUtils; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; use types::rewrite_path; use rewrite::{Rewrite, RewriteContext}; +use visitor::FmtVisitor; +use std::cmp::Ordering; -use syntax::ast; -use syntax::codemap::Span; +use syntax::{ast, ptr}; + +fn path_of(a: &ast::ViewPath_) -> &ast::Path { + match a { + &ast::ViewPath_::ViewPathSimple(_, ref p) => p, + &ast::ViewPath_::ViewPathGlob(ref p) => p, + &ast::ViewPath_::ViewPathList(ref p, _) => p, + } +} + +fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { + a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) +} + +fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { + for segment in a.segments.iter().zip(b.segments.iter()) { + let ord = compare_path_segments(segment.0, segment.1); + if ord != Ordering::Equal { + return ord; + } + } + a.segments.len().cmp(&b.segments.len()) +} + +fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Ordering { + let name_ordering = match a.node.name() { + Some(a_name) => { + match b.node.name() { + Some(b_name) => a_name.name.as_str().cmp(&b_name.name.as_str()), + None => Ordering::Greater, + } + } + None => { + match b.node.name() { + Some(_) => Ordering::Less, + None => Ordering::Equal, + } + } + }; + if name_ordering == Ordering::Equal { + match a.node.rename() { + Some(a_rename) => { + match b.node.rename() { + Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), + None => Ordering::Greater, + } + } + None => { + match b.node.name() { + Some(_) => Ordering::Less, + None => Ordering::Equal, + } + } + } + } else { + name_ordering + } +} + +fn compare_path_list_item_lists(a_items: &Vec, + b_items: &Vec) + -> Ordering { + let mut a = a_items.clone(); + let mut b = b_items.clone(); + a.sort_by(|a, b| compare_path_list_items(a, b)); + b.sort_by(|a, b| compare_path_list_items(a, b)); + for comparison_pair in a.iter().zip(b.iter()) { + let ord = compare_path_list_items(comparison_pair.0, comparison_pair.1); + if ord != Ordering::Equal { + return ord; + } + } + a.len().cmp(&b.len()) +} + +fn compare_view_path_types(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering { + use syntax::ast::ViewPath_::*; + match (a, b) { + (&ViewPathSimple(..), &ViewPathSimple(..)) => Ordering::Equal, + (&ViewPathSimple(..), _) => Ordering::Less, + (&ViewPathGlob(_), &ViewPathSimple(..)) => Ordering::Greater, + (&ViewPathGlob(_), &ViewPathGlob(_)) => Ordering::Equal, + (&ViewPathGlob(_), &ViewPathList(..)) => Ordering::Less, + (&ViewPathList(_, ref a_items), &ViewPathList(_, ref b_items)) => { + compare_path_list_item_lists(a_items, b_items) + } + (&ViewPathList(..), _) => Ordering::Greater, + } +} + +fn compare_view_paths(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering { + match compare_paths(path_of(a), path_of(b)) { + Ordering::Equal => compare_view_path_types(a, b), + cmp => cmp, + } +} + +fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { + match (&a.node, &b.node) { + (&ast::ItemKind::Use(ref a_vp), &ast::ItemKind::Use(ref b_vp)) => { + Some(compare_view_paths(&a_vp.node, &b_vp.node)) + } + _ => None, + } +} // TODO (some day) remove unused imports, expand globs, compress many single // imports into a list import. @@ -50,6 +157,63 @@ impl Rewrite for ast::ViewPath { } } +impl<'a> FmtVisitor<'a> { + pub fn format_imports(&mut self, use_items: &[ptr::P]) { + let mut last_pos = + use_items.first().map(|p_i| p_i.span.lo - BytePos(1)).unwrap_or(self.last_pos); + let prefix = codemap::mk_sp(self.last_pos, last_pos); + let mut ordered_use_items = use_items.iter() + .map(|p_i| { + let new_item = (&*p_i, last_pos); + last_pos = p_i.span.hi; + new_item + }) + .collect::>(); + // Order the imports by view-path & other import path properties + ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap()); + // First, output the span before the first import + self.format_missing(prefix.hi); + for ordered in ordered_use_items { + // Fake out the formatter by setting `self.last_pos` to the appropriate location before + // each item before visiting it. + self.last_pos = ordered.1; + self.visit_item(&ordered.0); + } + self.last_pos = last_pos; + } + + pub fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { + let vis = utils::format_visibility(vis); + let mut offset = self.block_indent; + offset.alignment += vis.len() + "use ".len(); + // 1 = ";" + match vp.rewrite(&self.get_context(), + self.config.max_width - offset.width() - 1, + offset) { + Some(ref s) if s.is_empty() => { + // Format up to last newline + let prev_span = codemap::mk_sp(self.last_pos, source!(self, span).lo); + let span_end = match self.snippet(prev_span).rfind('\n') { + Some(offset) => self.last_pos + BytePos(offset as u32), + None => source!(self, span).lo, + }; + self.format_missing(span_end); + self.last_pos = source!(self, span).hi; + } + Some(ref s) => { + let s = format!("{}use {};", vis, s); + self.format_missing_with_indent(source!(self, span).lo); + self.buffer.push_str(&s); + self.last_pos = source!(self, span).hi; + } + None => { + self.format_missing_with_indent(source!(self, span).lo); + self.format_missing(source!(self, span).hi); + } + } + } +} + fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { let path_item_str = if let ast::PathListItemKind::Ident { name, .. } = vpi.node { // A name. @@ -138,7 +302,7 @@ pub fn rewrite_use_list(width: usize, let has_self = move_self_to_front(&mut items); let first_index = if has_self { 0 } else { 1 }; - if context.config.reorder_imports { + if context.config.reorder_imported_names { items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } diff --git a/src/utils.rs b/src/utils.rs index 5807d4c158c..0978e552837 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -224,6 +224,13 @@ macro_rules! msg { ) } +// For format_missing and last_pos, need to use the source callsite (if applicable). +// Required as generated code spans aren't guaranteed to follow on from the last span. +macro_rules! source { + ($this:ident, $sp: expr) => { + $this.codemap.source_callsite($sp) + } +} // Wraps string-like values in an Option. Returns Some when the string adheres // to the Rewrite constraints defined for the Rewrite trait and else otherwise. diff --git a/src/visitor.rs b/src/visitor.rs index c5962e986b5..b60c5156680 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::{ast, visit}; +use syntax::{ast, ptr, visit}; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::parse::ParseSess; @@ -23,11 +23,10 @@ use comment::rewrite_comment; use macros::rewrite_macro; use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; -// For format_missing and last_pos, need to use the source callsite (if applicable). -// Required as generated code spans aren't guaranteed to follow on from the last span. -macro_rules! source { - ($this:ident, $sp: expr) => { - $this.codemap.source_callsite($sp) +fn is_use_item(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Use(_) => true, + _ => false, } } @@ -191,7 +190,7 @@ impl<'a> FmtVisitor<'a> { self.visit_block(b) } - fn visit_item(&mut self, item: &ast::Item) { + pub fn visit_item(&mut self, item: &ast::Item) { // This is where we bail out if there is a skip attribute. This is only // complex in the module case. It is complex because the module could be // in a seperate file and there might be attributes in both files, but @@ -502,8 +501,24 @@ impl<'a> FmtVisitor<'a> { } fn walk_mod_items(&mut self, m: &ast::Mod) { - for item in &m.items { - self.visit_item(&item); + let mut items_left: &[ptr::P] = &m.items; + while !items_left.is_empty() { + // If the next item is a `use` declaration, then extract it and any subsequent `use`s + // to be potentially reordered within `format_imports`. Otherwise, just format the + // next item for output. + if self.config.reorder_imports && is_use_item(&*items_left[0]) { + let use_item_length = + items_left.iter().take_while(|ppi| is_use_item(&***ppi)).count(); + let (use_items, rest) = items_left.split_at(use_item_length); + self.format_imports(use_items); + items_left = rest; + } else { + // `unwrap()` is safe here because we know `items_left` + // has elements from the loop condition + let (item, rest) = items_left.split_first().unwrap(); + self.visit_item(&item); + items_left = rest; + } } } @@ -547,37 +562,6 @@ impl<'a> FmtVisitor<'a> { self.format_missing(filemap.end_pos); } - fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { - let vis = utils::format_visibility(vis); - let mut offset = self.block_indent; - offset.alignment += vis.len() + "use ".len(); - // 1 = ";" - match vp.rewrite(&self.get_context(), - self.config.max_width - offset.width() - 1, - offset) { - Some(ref s) if s.is_empty() => { - // Format up to last newline - let prev_span = codemap::mk_sp(self.last_pos, source!(self, span).lo); - let span_end = match self.snippet(prev_span).rfind('\n') { - Some(offset) => self.last_pos + BytePos(offset as u32), - None => source!(self, span).lo, - }; - self.format_missing(span_end); - self.last_pos = source!(self, span).hi; - } - Some(ref s) => { - let s = format!("{}use {};", vis, s); - self.format_missing_with_indent(source!(self, span).lo); - self.buffer.push_str(&s); - self.last_pos = source!(self, span).hi; - } - None => { - self.format_missing_with_indent(source!(self, span).lo); - self.format_missing(source!(self, span).hi); - } - } - } - pub fn get_context(&self) -> RewriteContext { RewriteContext { parse_session: self.parse_session, diff --git a/tests/source/imports-reorder-lines-and-items.rs b/tests/source/imports-reorder-lines-and-items.rs new file mode 100644 index 00000000000..b61f26771f6 --- /dev/null +++ b/tests/source/imports-reorder-lines-and-items.rs @@ -0,0 +1,9 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true + +use std::str; +use std::cmp::{d, c, b, a}; +use std::ddd::aaa; +use std::ddd::{d as p, c as g, b, a}; +// This comment should stay with `use std::ddd:bbb;` +use std::ddd::bbb; diff --git a/tests/source/imports-reorder-lines.rs b/tests/source/imports-reorder-lines.rs new file mode 100644 index 00000000000..a855a964235 --- /dev/null +++ b/tests/source/imports-reorder-lines.rs @@ -0,0 +1,34 @@ +// rustfmt-reorder_imports: true + +use std::str; +use std::cmp::{d, c, b, a}; +use std::cmp::{b, e, g, f}; +use std::ddd::aaa; +// This comment should stay with `use std::ddd;` +use std::ddd; +use std::ddd::bbb; + +mod test { +} + +use aaa::bbb; +use aaa; +use aaa::*; + +mod test {} +// If item names are equal, order by rename + +use test::{a as bb, b}; +use test::{a as aa, c}; + +mod test {} +// If item names are equal, order by rename - no rename comes before a rename + +use test::{a as bb, b}; +use test::{a, c}; + +mod test {} +// `self` always comes first + +use test::{a as aa, c}; +use test::{self as bb, b}; diff --git a/tests/source/imports-reorder.rs b/tests/source/imports-reorder.rs index 4feb8e90561..4ad9e4b08d3 100644 --- a/tests/source/imports-reorder.rs +++ b/tests/source/imports-reorder.rs @@ -1,4 +1,4 @@ -// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true use path::{C,/*A*/ A, B /* B */, self /* self */}; diff --git a/tests/target/imports-reorder-lines-and-items.rs b/tests/target/imports-reorder-lines-and-items.rs new file mode 100644 index 00000000000..fb2e0347aac --- /dev/null +++ b/tests/target/imports-reorder-lines-and-items.rs @@ -0,0 +1,9 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true + +use std::cmp::{a, b, c, d}; +use std::ddd::{a, b, c as g, d as p}; +use std::ddd::aaa; +// This comment should stay with `use std::ddd:bbb;` +use std::ddd::bbb; +use std::str; diff --git a/tests/target/imports-reorder-lines.rs b/tests/target/imports-reorder-lines.rs new file mode 100644 index 00000000000..7c8735c2dd5 --- /dev/null +++ b/tests/target/imports-reorder-lines.rs @@ -0,0 +1,33 @@ +// rustfmt-reorder_imports: true + +use std::cmp::{d, c, b, a}; +use std::cmp::{b, e, g, f}; +// This comment should stay with `use std::ddd;` +use std::ddd; +use std::ddd::aaa; +use std::ddd::bbb; +use std::str; + +mod test {} + +use aaa; +use aaa::*; +use aaa::bbb; + +mod test {} +// If item names are equal, order by rename + +use test::{a as aa, c}; +use test::{a as bb, b}; + +mod test {} +// If item names are equal, order by rename - no rename comes before a rename + +use test::{a, c}; +use test::{a as bb, b}; + +mod test {} +// `self` always comes first + +use test::{self as bb, b}; +use test::{a as aa, c}; diff --git a/tests/target/imports-reorder.rs b/tests/target/imports-reorder.rs index 63ebbf1ec7b..32b5ee156cc 100644 --- a/tests/target/imports-reorder.rs +++ b/tests/target/imports-reorder.rs @@ -1,4 +1,4 @@ -// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true use path::{self /* self */, /* A */ A, B /* B */, C}; -- cgit 1.4.1-3-g733a5 From e76cb6a907a66fa90b2e7e612df3ea72d43d3401 Mon Sep 17 00:00:00 2001 From: dawirstejeck Date: Tue, 26 Jul 2016 07:34:11 +0200 Subject: Fix overlong impl (#1091) * Fix issue-1048 * Take possible where-clause into account * Move test to existing test set * Fix wrong variable name --- src/items.rs | 14 +++++++++++++- tests/source/impls.rs | 3 +++ tests/target/impls.rs | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1de56220cf4..a0e5626b882 100644 --- a/src/items.rs +++ b/src/items.rs @@ -440,6 +440,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - ref self_ty, ref items) = item.node { let mut result = String::new(); + result.push_str(&*format_visibility(&item.vis)); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); @@ -470,7 +471,18 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - result.push_str(" for "); } - let budget = try_opt!(context.config.max_width.checked_sub(result.len())); + let mut used_space = result.len(); + if generics.where_clause.predicates.is_empty() { + // If there is no where clause adapt budget for type formatting to take space and curly + // brace into account. + match context.config.item_brace_style { + BraceStyle::AlwaysNextLine => {} + BraceStyle::PreferSameLine => used_space += 2, + BraceStyle::SameLineWhere => used_space += 2, + } + } + + let budget = try_opt!(context.config.max_width.checked_sub(used_space)); let indent = offset + result.len(); result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 0eb084018bc..5fbcecb9700 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -97,3 +97,6 @@ mod m { impl PartialEq for S where T: PartialEq { } } + +impl Handle, HandleType> { +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 38c972c0031..03045c21ac5 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -124,3 +124,7 @@ mod m { impl PartialEq for S where T: PartialEq {} } + +impl Handle, + HandleType> { +} -- cgit 1.4.1-3-g733a5 From 6380937b596d32da78dfc24ae6666b12a6dc59bd Mon Sep 17 00:00:00 2001 From: Daniel Campoverde Date: Sun, 31 Jul 2016 16:32:35 -0500 Subject: Multiple config file names feature (#1101) * Add multiple configuration file names feature * Add '.rustfmt.toml' in README file * Clean up configuration file code * Make config file names constant * Use only one blank line --- README.md | 12 +++++++----- src/bin/rustfmt.rs | 26 +++++++++++++++----------- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 8e5b40b8af8..c99ea26e7cf 100644 --- a/README.md +++ b/README.md @@ -124,9 +124,10 @@ notes above on running rustfmt. ## Configuring Rustfmt Rustfmt is designed to be very configurable. You can create a TOML file called -rustfmt.toml, place it in the project directory and it will apply the options -in that file. See `rustfmt --config-help` for the options which are available, -or if you prefer to see source code, [src/config.rs](src/config.rs). +`rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent +directory and it will apply the options in that file. See `rustfmt +--config-help` for the options which are available, or if you prefer to see +source code, [src/config.rs](src/config.rs). By default, Rustfmt uses a style which (mostly) conforms to the [Rust style guidelines](https://github.com/rust-lang/rust/tree/master/src/doc/style). @@ -148,8 +149,9 @@ options covering different styles. File an issue, or even better, submit a PR. #[rustfmt_skip] // requires nightly and #![feature(custom_attribute)] in crate root #[cfg_attr(rustfmt, rustfmt_skip)] // works in stable ``` -* When you run rustfmt, place a file named rustfmt.toml in target file - directory or its parents to override the default settings of rustfmt. +* When you run rustfmt, place a file named `rustfmt.toml` or `.rustfmt.toml` in + target file directory or its parents to override the default settings of + rustfmt. * After successful compilation, a `rustfmt` executable can be found in the target directory. * If you're having issues compiling Rustfmt (or compile errors when trying to diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index bf78bb39fe4..3434f01ac9f 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -109,20 +109,24 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { current = try!(fs::canonicalize(current)); + const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + loop { - let config_file = current.join("rustfmt.toml"); - match fs::metadata(&config_file) { - // Only return if it's a file to handle the unlikely situation of a directory named - // `rustfmt.toml`. - Ok(ref md) if md.is_file() => return Ok(Some(config_file)), - // Return the error if it's something other than `NotFound`; otherwise we didn't find - // the project file yet, and continue searching. - Err(e) => { - if e.kind() != ErrorKind::NotFound { - return Err(FmtError::from(e)); + for config_file_name in &CONFIG_FILE_NAMES { + let config_file = current.join(config_file_name); + match fs::metadata(&config_file) { + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't + // find the project file yet, and continue searching. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(FmtError::from(e)); + } } + _ => {} } - _ => {} } // If the current directory has no parent, we're done searching. -- cgit 1.4.1-3-g733a5 From 22de7ced28aa7bc68d1317a5529d6e0d69ef744e Mon Sep 17 00:00:00 2001 From: dawirstejeck Date: Mon, 1 Aug 2016 06:25:00 +0200 Subject: Fix overlong function signature (#1089) * Fix issue-1049 * Add testcase suggested by pepyakin * Fix last commit * Handle special case * Remove debugging println * Fix grammar in comment * Change word in comment * Add test for long func without ret type * Add one more test --- src/items.rs | 23 ++++++++++++++++------- tests/source/issue-1049.rs | 16 ++++++++++++++++ tests/target/issue-1049.rs | 21 +++++++++++++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 tests/source/issue-1049.rs create mode 100644 tests/target/issue-1049.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a0e5626b882..36d9d92eb16 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1369,10 +1369,21 @@ fn rewrite_fn_base(context: &RewriteContext, FnArgLayoutStyle::Block if put_args_in_block => false, FnArgLayoutStyle::BlockAlways => false, _ => { - // If we've already gone multi-line, or the return type would push - // over the max width, then put the return type on a new line. - result.contains("\n") || multi_line_ret_str || - result.len() + indent.width() + ret_str_len > context.config.max_width + // If we've already gone multi-line, or the return type would push over the max + // width, then put the return type on a new line. With the +1 for the signature + // length an additional space between the closing parenthesis of the argument and + // the arrow '->' is considered. + let mut sig_length = result.len() + indent.width() + ret_str_len + 1; + + // If there is no where clause, take into account the space after the return type + // and the brace. + if where_clause.predicates.is_empty() { + sig_length += 2; + } + + let overlong_sig = sig_length > context.config.max_width; + + result.contains("\n") || multi_line_ret_str || overlong_sig } }; let ret_indent = if ret_should_indent { @@ -1400,10 +1411,8 @@ fn rewrite_fn_base(context: &RewriteContext, if multi_line_ret_str { // Now that we know the proper indent and width, we need to // re-layout the return type. - let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); - let ret_str = try_opt!(fd.output - .rewrite(context, budget, ret_indent)); + let ret_str = try_opt!(fd.output.rewrite(context, budget, ret_indent)); result.push_str(&ret_str); } else { result.push_str(&ret_str); diff --git a/tests/source/issue-1049.rs b/tests/source/issue-1049.rs new file mode 100644 index 00000000000..a0240b83b63 --- /dev/null +++ b/tests/source/issue-1049.rs @@ -0,0 +1,16 @@ +// Test overlong function signature +pub unsafe fn reborrow_mut(&mut X: Abcde) -> Handle, HandleType> { +} + +pub fn merge(mut X: Abcdef) -> Handle, K, V, marker::Internal>, marker::Edge> { +} + +impl Handle { + pub fn merge(a: Abcd) -> Handle, K, V, marker::Internal>, marker::Edge> { + } +} + +// Long function without return type that should not be reformated. +fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} diff --git a/tests/target/issue-1049.rs b/tests/target/issue-1049.rs new file mode 100644 index 00000000000..fac49b80b51 --- /dev/null +++ b/tests/target/issue-1049.rs @@ -0,0 +1,21 @@ +// Test overlong function signature +pub unsafe fn reborrow_mut(&mut X: Abcde) + -> Handle, HandleType> { +} + +pub fn merge(mut X: Abcdef) + -> Handle, K, V, marker::Internal>, marker::Edge> { +} + +impl Handle { + pub fn merge(a: Abcd) + -> Handle, K, V, marker::Internal>, marker::Edge> { + } +} + +// Long function without return type that should not be reformated. +fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, + b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { +} -- cgit 1.4.1-3-g733a5 From b4e49ddbf526547d70ba659136cd56c6acc6f33f Mon Sep 17 00:00:00 2001 From: Julien Blanchard Date: Wed, 8 Jun 2016 13:00:11 +0200 Subject: Fix imports with absolute paths --- src/imports.rs | 41 ++++++++++++++++++++++------------------- tests/source/imports.rs | 7 +++++++ tests/target/imports.rs | 7 +++++++ 3 files changed, 36 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 36953463d38..a9d56878ea6 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -214,22 +214,20 @@ impl<'a> FmtVisitor<'a> { } } -fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { +fn rewrite_single_use_list(path_str: Option, vpi: &ast::PathListItem) -> String { let path_item_str = if let ast::PathListItemKind::Ident { name, .. } = vpi.node { // A name. - if path_str.is_empty() { - name.to_string() - } else { - format!("{}::{}", path_str, name) + match path_str { + Some(path_str) => format!("{}::{}", path_str, name), + None => name.to_string(), } } else { // `self`. - if !path_str.is_empty() { - path_str - } else { + match path_str { + Some(path_str) => path_str, // This catches the import: use {self}, which is a compiler error, so we just // leave it alone. - "{self}".to_owned() + None => "{self}".to_owned(), } }; @@ -264,20 +262,26 @@ pub fn rewrite_use_list(width: usize, span: Span, context: &RewriteContext) -> Option { - // 1 = {} - let budget = try_opt!(width.checked_sub(1)); - let path_str = try_opt!(rewrite_path(context, false, None, path, budget, offset)); + // Returns a different option to distinguish `::foo` and `foo` + let opt_path_str = if !path.to_string().is_empty() { + Some(path.to_string()) + } else if path.global { + // path is absolute, we return an empty String to avoid a double `::` + Some(String::new()) + } else { + None + }; match path_list.len() { 0 => unreachable!(), - 1 => return Some(rewrite_single_use_list(path_str, &path_list[0])), + 1 => return Some(rewrite_single_use_list(opt_path_str, &path_list[0])), _ => (), } // 2 = :: - let path_separation_w = if !path_str.is_empty() { 2 } else { 0 }; + let path_separation_w = if opt_path_str.is_some() { 2 } else { 0 }; // 1 = { - let supp_indent = path_str.len() + path_separation_w + 1; + let supp_indent = path.to_string().len() + path_separation_w + 1; // 1 = } let remaining_width = width.checked_sub(supp_indent + 1).unwrap_or(0); @@ -323,10 +327,9 @@ pub fn rewrite_use_list(width: usize, }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); - Some(if path_str.is_empty() { - format!("{{{}}}", list_str) - } else { - format!("{}::{{{}}}", path_str, list_str) + Some(match opt_path_str { + Some(opt_path_str) => format!("{}::{{{}}}", opt_path_str, list_str), + None => format!("{{{}}}", list_str), }) } diff --git a/tests/source/imports.rs b/tests/source/imports.rs index ab850f416fb..45ed1e03fe0 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -50,3 +50,10 @@ use foo::{self as bar, baz}; use foo::{self as bar}; use foo::{qux as bar}; use foo::{baz, qux as bar}; + +// With absolute paths +use ::foo; +use ::foo::{Bar}; +use ::foo::{Bar, Baz}; +use ::{Foo}; +use ::{Bar, Baz}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 296230ef8ba..4e2f6903644 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -45,3 +45,10 @@ use foo::{self as bar, baz}; use foo as bar; use foo::qux as bar; use foo::{baz, qux as bar}; + +// With absolute paths +use ::foo; +use ::foo::Bar; +use ::foo::{Bar, Baz}; +use ::Foo; +use ::{Bar, Baz}; -- cgit 1.4.1-3-g733a5 From 4b999a99c046b8ff366f93fb5bb8adf91103971e Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Tue, 2 Aug 2016 21:07:56 -0400 Subject: Add two new whitespace options (#1109) * An option to leave a space before the colon in a type annotation * An option to leave a space before the colon in a trait or lifetime bound --- src/config.rs | 3 +++ src/items.rs | 30 ++++++++++++++++++++++------ src/types.rs | 10 +++++++++- tests/source/space-before-bound.rs | 4 ++++ tests/source/space-before-type-annotation.rs | 10 ++++++++++ tests/target/space-before-bound.rs | 4 ++++ tests/target/space-before-type-annotation.rs | 10 ++++++++++ 7 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 tests/source/space-before-bound.rs create mode 100644 tests/source/space-before-type-annotation.rs create mode 100644 tests/target/space-before-bound.rs create mode 100644 tests/target/space-before-type-annotation.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 9cd15bc0e33..71adc24c09f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -408,6 +408,9 @@ create_config! { match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; closure_block_indent_threshold: isize, 5, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; + space_before_type_annotation: bool, false, + "Leave a space before the colon in a type annotation"; + space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound"; use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; diff --git a/src/items.rs b/src/items.rs index a0e5626b882..ce44d1be839 100644 --- a/src/items.rs +++ b/src/items.rs @@ -45,13 +45,17 @@ impl Rewrite for ast::Local { let mut infix = String::new(); if let Some(ref ty) = self.ty { - // 2 = ": ".len() + let separator = if context.config.space_before_type_annotation { + " : " + } else { + ": " + }; + let indent = offset + last_line_width(&result) + separator.len(); // 1 = ; - let indent = offset + last_line_width(&result) + 2; let budget = try_opt!(width.checked_sub(indent.width() + 1)); let rewrite = try_opt!(ty.rewrite(context, budget, indent)); - infix.push_str(": "); + infix.push_str(separator); infix.push_str(&rewrite); } @@ -998,6 +1002,14 @@ pub fn rewrite_type_alias(context: &RewriteContext, Some(result) } +fn type_annotation_spacing(config: &Config) -> &str { + if config.space_before_type_annotation { + " " + } else { + "" + } +} + impl Rewrite for ast::StructField { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { if contains_skip(&self.attrs) { @@ -1014,8 +1026,9 @@ impl Rewrite for ast::StructField { attr_str.push_str(&offset.to_string(context.config)); } + let type_annotation_spacing = type_annotation_spacing(context.config); let result = match name { - Some(name) => format!("{}{}{}: ", attr_str, vis, name), + Some(name) => format!("{}{}{}{}: ", attr_str, vis, name, type_annotation_spacing), None => format!("{}{}", attr_str, vis), }; @@ -1034,11 +1047,13 @@ pub fn rewrite_static(prefix: &str, expr_opt: Option<&ptr::P>, context: &RewriteContext) -> Option { - let prefix = format!("{}{} {}{}: ", + let type_annotation_spacing = type_annotation_spacing(context.config); + let prefix = format!("{}{} {}{}{}: ", format_visibility(vis), prefix, format_mutability(mutability), - ident); + ident, + type_annotation_spacing); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, context.config.max_width - context.block_indent.width() - @@ -1117,6 +1132,9 @@ impl Rewrite for ast::Arg { let mut result = try_opt!(self.pat.rewrite(context, width, offset)); if self.ty.node != ast::TyKind::Infer { + if context.config.space_before_type_annotation { + result.push_str(" "); + } result.push_str(": "); let max_width = try_opt!(width.checked_sub(result.len())); let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len())); diff --git a/src/types.rs b/src/types.rs index 8fa24df0caa..598ac3b6ac8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -406,7 +406,12 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, let appendix: Vec<_> = try_opt!(bounds.into_iter() .map(|b| b.rewrite(context, width, offset)) .collect()); - let result = format!("{}: {}", result, appendix.join(" + ")); + let bound_spacing = if context.config.space_before_bound { + " " + } else { + "" + }; + let result = format!("{}{}: {}", result, bound_spacing, appendix.join(" + ")); wrap_str(result, context.config.max_width, width, offset) } } @@ -449,6 +454,9 @@ impl Rewrite for ast::TyParam { let mut result = String::with_capacity(128); result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { + if context.config.space_before_bound { + result.push_str(" "); + } result.push_str(": "); let bounds: String = try_opt!(self.bounds diff --git a/tests/source/space-before-bound.rs b/tests/source/space-before-bound.rs new file mode 100644 index 00000000000..cb4cf8aafd6 --- /dev/null +++ b/tests/source/space-before-bound.rs @@ -0,0 +1,4 @@ +// rustfmt-space_before_bound: true + +trait Trait {} +fn f<'a, 'b: 'a, T: Trait>() {} diff --git a/tests/source/space-before-type-annotation.rs b/tests/source/space-before-type-annotation.rs new file mode 100644 index 00000000000..c1b0248d8aa --- /dev/null +++ b/tests/source/space-before-type-annotation.rs @@ -0,0 +1,10 @@ +// rustfmt-space_before_type_annotation: true + +static staticVar: i32 = 42; +const constVar: i32 = 42; +fn foo(paramVar: i32) { + let localVar: i32 = 42; +} +struct S { + fieldVar: i32, +} diff --git a/tests/target/space-before-bound.rs b/tests/target/space-before-bound.rs new file mode 100644 index 00000000000..7e1ef870315 --- /dev/null +++ b/tests/target/space-before-bound.rs @@ -0,0 +1,4 @@ +// rustfmt-space_before_bound: true + +trait Trait {} +fn f<'a, 'b : 'a, T : Trait>() {} diff --git a/tests/target/space-before-type-annotation.rs b/tests/target/space-before-type-annotation.rs new file mode 100644 index 00000000000..8bd16499b14 --- /dev/null +++ b/tests/target/space-before-type-annotation.rs @@ -0,0 +1,10 @@ +// rustfmt-space_before_type_annotation: true + +static staticVar : i32 = 42; +const constVar : i32 = 42; +fn foo(paramVar : i32) { + let localVar : i32 = 42; +} +struct S { + fieldVar : i32, +} -- cgit 1.4.1-3-g733a5 From f6959a4772b2eabba3d2f93ad9f46d367110dbb2 Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Wed, 3 Aug 2016 01:25:54 +0300 Subject: Fix issue-1116 --- src/imports.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index a9d56878ea6..d82e0934360 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -159,8 +159,10 @@ impl Rewrite for ast::ViewPath { impl<'a> FmtVisitor<'a> { pub fn format_imports(&mut self, use_items: &[ptr::P]) { - let mut last_pos = - use_items.first().map(|p_i| p_i.span.lo - BytePos(1)).unwrap_or(self.last_pos); + let mut last_pos = use_items.first() + .and_then(|p_i| p_i.span.lo.0.checked_sub(1)) + .map(|span_lo| BytePos(span_lo)) + .unwrap_or(self.last_pos); let prefix = codemap::mk_sp(self.last_pos, last_pos); let mut ordered_use_items = use_items.iter() .map(|p_i| { -- cgit 1.4.1-3-g733a5 From 899169a1d2f12e0495f302746f5ebd6c098b2537 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Thu, 4 Aug 2016 00:17:47 -0400 Subject: Apply space_before_type_annotation to struct ctors (#1109) --- src/expr.rs | 13 +++++++++++-- src/items.rs | 8 ++------ tests/source/space-before-type-annotation.rs | 3 +++ tests/target/space-before-type-annotation.rs | 3 +++ 4 files changed, 19 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a50aa9f2de9..1fea4f40e17 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1655,19 +1655,28 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // of space, we should fall back to BlockIndent. } +pub fn type_annotation_separator(config: &Config) -> &str { + if config.space_before_type_annotation { + " : " + } else { + ": " + } +} + fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, offset: Indent) -> Option { let name = &field.ident.node.to_string(); - let overhead = name.len() + 2; + let separator = type_annotation_separator(context.config); + let overhead = name.len() + separator.len(); let expr = field.expr.rewrite(context, try_opt!(width.checked_sub(overhead)), offset + overhead); match expr { - Some(e) => Some(format!("{}: {}", name, e)), + Some(e) => Some(format!("{}{}{}", name, separator, e)), None => { let expr_offset = offset.block_indent(&context.config); let expr = field.expr.rewrite(context, diff --git a/src/items.rs b/src/items.rs index 65aa7ebe62a..565abae217c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,7 +16,7 @@ use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wr last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; -use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; +use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; @@ -45,11 +45,7 @@ impl Rewrite for ast::Local { let mut infix = String::new(); if let Some(ref ty) = self.ty { - let separator = if context.config.space_before_type_annotation { - " : " - } else { - ": " - }; + let separator = type_annotation_separator(context.config); let indent = offset + last_line_width(&result) + separator.len(); // 1 = ; let budget = try_opt!(width.checked_sub(indent.width() + 1)); diff --git a/tests/source/space-before-type-annotation.rs b/tests/source/space-before-type-annotation.rs index c1b0248d8aa..15a75e4cf33 100644 --- a/tests/source/space-before-type-annotation.rs +++ b/tests/source/space-before-type-annotation.rs @@ -8,3 +8,6 @@ fn foo(paramVar: i32) { struct S { fieldVar: i32, } +fn f() { + S { fieldVar: 42 } +} diff --git a/tests/target/space-before-type-annotation.rs b/tests/target/space-before-type-annotation.rs index 8bd16499b14..54b9541eaae 100644 --- a/tests/target/space-before-type-annotation.rs +++ b/tests/target/space-before-type-annotation.rs @@ -8,3 +8,6 @@ fn foo(paramVar : i32) { struct S { fieldVar : i32, } +fn f() { + S { fieldVar : 42 } +} -- cgit 1.4.1-3-g733a5 From a0de408198d5f1e8e2d96b471450af3742dfdddc Mon Sep 17 00:00:00 2001 From: juicejitsu Date: Tue, 9 Aug 2016 18:21:04 -0700 Subject: Don't emit filename in diff mode, add filename to diff metadata --- src/filemap.rs | 4 ++-- tests/system.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 1fca0d5b012..5560e9aee85 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -144,11 +144,11 @@ pub fn write_file(text: &StringBuffer, try!(write_system_newlines(stdout, text, config)); } WriteMode::Diff => { - println!("Diff of {}:\n", filename); if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { let mismatch = make_diff(&ori, &fmt, 3); let has_diff = !mismatch.is_empty(); - print_diff(mismatch, |line_num| format!("\nDiff at line {}:", line_num)); + print_diff(mismatch, + |line_num| format!("Diff in {} at line {}:", filename, line_num)); return Ok(has_diff); } } diff --git a/tests/system.rs b/tests/system.rs index 08ec576f221..4e7257e60c8 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -350,3 +350,9 @@ fn rustfmt_diff_make_diff_tests() { DiffLine::Context("d".into())], }]); } + +#[test] +fn rustfmt_diff_no_diff_test() { + let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); + assert_eq!(diff, vec![]); +} -- cgit 1.4.1-3-g733a5 From 4029b0e704bbb8300158eb5857d516614ef4ee23 Mon Sep 17 00:00:00 2001 From: Stuart Dootson Date: Wed, 10 Aug 2016 08:13:27 +0200 Subject: Fix #1120 - rework how the use list prefix is determined. (#1121) * Fix #1120 - rework how the use list prefix is determined. * Added test commentary & another test case --- src/imports.rs | 35 ++++++++++++++++++++++++++--------- tests/source/issue-1120.rs | 9 +++++++++ tests/target/issue-1120.rs | 11 +++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 tests/source/issue-1120.rs create mode 100644 tests/target/issue-1120.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index d82e0934360..4ae40b7fc0b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -16,7 +16,7 @@ use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, use types::rewrite_path; use rewrite::{Rewrite, RewriteContext}; use visitor::FmtVisitor; -use std::cmp::Ordering; +use std::cmp::{self, Ordering}; use syntax::{ast, ptr}; @@ -159,29 +159,46 @@ impl Rewrite for ast::ViewPath { impl<'a> FmtVisitor<'a> { pub fn format_imports(&mut self, use_items: &[ptr::P]) { - let mut last_pos = use_items.first() - .and_then(|p_i| p_i.span.lo.0.checked_sub(1)) - .map(|span_lo| BytePos(span_lo)) + // Find the location immediately before the first use item in the run. This must not lie + // before the current `self.last_pos` + let pos_before_first_use_item = use_items.first() + .map(|p_i| cmp::max(self.last_pos, p_i.span.lo)) .unwrap_or(self.last_pos); - let prefix = codemap::mk_sp(self.last_pos, last_pos); + // Construct a list of pairs, each containing a `use` item and the start of span before + // that `use` item. + let mut last_pos_of_prev_use_item = pos_before_first_use_item; let mut ordered_use_items = use_items.iter() .map(|p_i| { - let new_item = (&*p_i, last_pos); - last_pos = p_i.span.hi; + let new_item = (&*p_i, last_pos_of_prev_use_item); + last_pos_of_prev_use_item = p_i.span.hi; new_item }) .collect::>(); + let pos_after_last_use_item = last_pos_of_prev_use_item; // Order the imports by view-path & other import path properties ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap()); // First, output the span before the first import - self.format_missing(prefix.hi); + // Look for indent (the line part preceding the use is all whitespace) and excise that + // from the prefix + let prev_span_str = self.snippet(codemap::mk_sp(self.last_pos, pos_before_first_use_item)); + let span_end = match prev_span_str.rfind('\n') { + Some(offset) => { + if prev_span_str[offset..].trim().is_empty() { + self.last_pos + BytePos(offset as u32) + } else { + pos_before_first_use_item + } + } + None => pos_before_first_use_item, + }; + self.format_missing(span_end); for ordered in ordered_use_items { // Fake out the formatter by setting `self.last_pos` to the appropriate location before // each item before visiting it. self.last_pos = ordered.1; self.visit_item(&ordered.0); } - self.last_pos = last_pos; + self.last_pos = pos_after_last_use_item; } pub fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { diff --git a/tests/source/issue-1120.rs b/tests/source/issue-1120.rs new file mode 100644 index 00000000000..e85c9af99d4 --- /dev/null +++ b/tests/source/issue-1120.rs @@ -0,0 +1,9 @@ +// rustfmt-reorder_imports: true + +// Ensure that a use at the start of an inline module is correctly formatted. +mod foo {use bar;} + +// Ensure that an indented `use` gets the correct indentation. +mod foo { + use bar; +} diff --git a/tests/target/issue-1120.rs b/tests/target/issue-1120.rs new file mode 100644 index 00000000000..f44597e7d1e --- /dev/null +++ b/tests/target/issue-1120.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_imports: true + +// Ensure that a use at the start of an inline module is correctly formatted. +mod foo { + use bar; +} + +// Ensure that an indented `use` gets the correct indentation. +mod foo { + use bar; +} -- cgit 1.4.1-3-g733a5 From 61042e6e4d6680bd7788c37086c56ef2cd764217 Mon Sep 17 00:00:00 2001 From: Stuart Dootson Date: Wed, 24 Aug 2016 21:32:04 +0100 Subject: Fix issue 1124 - detect start of output rather than start of input file when writing output source file (#1133) * Change required to prevent a trailing space at the end of a separate module being propagated * Detect the start of the output file rather than the start of the input file when deciding whether to output preceding snippets - this stops unnecessary whitespace and blank lines from being inserted when spans and statements are output in an order other than that from the input file. * Add code to prevent space from being added with the prefix snippet if a) the snippet is entirely horizontal whitespace, or b) the snippet contains whitespace followed by a newline. This prevents trailing spaces at the end of a line from being added. * Tests for this issue * Tidy up `match` statements * Add test with blank lines between `use` statements --- src/imports.rs | 23 +++++++++++++++-------- src/missed_spans.rs | 8 ++++++-- src/visitor.rs | 2 +- tests/config/issue-1124.toml | 1 + tests/source/issue-1124.rs | 13 +++++++++++++ tests/target/issue-1124.rs | 21 +++++++++++++++++++++ 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 tests/config/issue-1124.toml create mode 100644 tests/source/issue-1124.rs create mode 100644 tests/target/issue-1124.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 4ae40b7fc0b..bc343307272 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -178,19 +178,26 @@ impl<'a> FmtVisitor<'a> { // Order the imports by view-path & other import path properties ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap()); // First, output the span before the first import + let prev_span_str = self.snippet(codemap::mk_sp(self.last_pos, pos_before_first_use_item)); + // Look for purely trailing space at the start of the prefix snippet before a linefeed, or + // a prefix that's entirely horizontal whitespace. + let prefix_span_start = match prev_span_str.find('\n') { + Some(offset) if prev_span_str[..offset].trim().is_empty() => { + self.last_pos + BytePos(offset as u32) + } + None if prev_span_str.trim().is_empty() => pos_before_first_use_item, + _ => self.last_pos, + }; // Look for indent (the line part preceding the use is all whitespace) and excise that // from the prefix - let prev_span_str = self.snippet(codemap::mk_sp(self.last_pos, pos_before_first_use_item)); let span_end = match prev_span_str.rfind('\n') { - Some(offset) => { - if prev_span_str[offset..].trim().is_empty() { - self.last_pos + BytePos(offset as u32) - } else { - pos_before_first_use_item - } + Some(offset) if prev_span_str[offset..].trim().is_empty() => { + self.last_pos + BytePos(offset as u32) } - None => pos_before_first_use_item, + _ => pos_before_first_use_item, }; + + self.last_pos = prefix_span_start; self.format_missing(span_end); for ordered in ordered_use_items { // Fake out the formatter by setting `self.last_pos` to the appropriate location before diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7e6d1516636..0e7d1402fc5 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -14,6 +14,10 @@ use syntax::codemap::{self, BytePos, Span, Pos}; use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; impl<'a> FmtVisitor<'a> { + fn output_at_start(&self) -> bool { + self.buffer.len == 0 + } + // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { @@ -25,7 +29,7 @@ impl<'a> FmtVisitor<'a> { let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { this.buffer.push_str(last_snippet.trim_right()); - if last_snippet == snippet { + if last_snippet == snippet && !this.output_at_start() { // No new lines in the snippet. this.buffer.push_str("\n"); } @@ -41,7 +45,7 @@ impl<'a> FmtVisitor<'a> { if start == end { // Do nothing if this is the beginning of the file. - if start != self.codemap.lookup_char_pos(start).file.start_pos { + if !self.output_at_start() { process_last_snippet(self, "", ""); } return; diff --git a/src/visitor.rs b/src/visitor.rs index b60c5156680..b89b97487a5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -559,7 +559,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = filemap.start_pos; self.block_indent = Indent::empty(); self.walk_mod_items(m); - self.format_missing(filemap.end_pos); + self.format_missing_with_indent(filemap.end_pos); } pub fn get_context(&self) -> RewriteContext { diff --git a/tests/config/issue-1124.toml b/tests/config/issue-1124.toml new file mode 100644 index 00000000000..44148a2d3c3 --- /dev/null +++ b/tests/config/issue-1124.toml @@ -0,0 +1 @@ +reorder_imports = true diff --git a/tests/source/issue-1124.rs b/tests/source/issue-1124.rs new file mode 100644 index 00000000000..0b9d68f49b8 --- /dev/null +++ b/tests/source/issue-1124.rs @@ -0,0 +1,13 @@ +use d; use c; use b; use a; +// The previous line has a space after the `use a;` + +mod a { use d; use c; use b; use a; } + +use z; + +use y; + + + +use x; +use a; \ No newline at end of file diff --git a/tests/target/issue-1124.rs b/tests/target/issue-1124.rs new file mode 100644 index 00000000000..d30f29461d8 --- /dev/null +++ b/tests/target/issue-1124.rs @@ -0,0 +1,21 @@ +use a; +use b; +use c; +use d; +// The previous line has a space after the `use a;` + +mod a { + use a; + use b; + use c; + use d; +} + +use a; + + + +use x; + +use y; +use z; -- cgit 1.4.1-3-g733a5 From 05882314f5facdf4b7f7ffff3c4aecf747cdf176 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Fri, 26 Aug 2016 17:08:47 -0400 Subject: Check term supports colour before printing fancy diffs For a terminal like DUMB, we were still attempting to print colourful diffs, which failed with a `NotSupported` error. Fixes #1140 --- src/rustfmt_diff.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index d5129bd1bca..23cb3f21bf2 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -89,7 +89,9 @@ pub fn print_diff(diff: Vec, get_section_title: F) where F: Fn(u32) -> String { match term::stdout() { - Some(_) if isatty() => print_diff_fancy(diff, get_section_title, term::stdout().unwrap()), + Some(ref t) if isatty() && t.supports_color() => { + print_diff_fancy(diff, get_section_title, term::stdout().unwrap()) + } _ => print_diff_basic(diff, get_section_title), } -- cgit 1.4.1-3-g733a5 From 130c5935443dab5ff7cc0ba0fb2bf196b640f447 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 23 Aug 2016 21:00:43 +0900 Subject: Fix #977 --- src/items.rs | 37 +++++++++++++++++++++++++------------ src/missed_spans.rs | 6 ++++++ tests/source/issue-977.rs | 7 +++++++ tests/target/issue-977.rs | 15 +++++++++++++++ 4 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 tests/source/issue-977.rs create mode 100644 tests/target/issue-977.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 565abae217c..55b4f8b9dcd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -85,20 +85,26 @@ impl<'a> FmtVisitor<'a> { let snippet = self.snippet(span); let brace_pos = snippet.find_uncommented("{").unwrap(); - if fm.items.is_empty() && !contains_comment(&snippet[brace_pos..]) { - self.buffer.push_str("{"); - } else { + self.buffer.push_str("{"); + if !fm.items.is_empty() || contains_comment(&snippet[brace_pos..]) { // FIXME: this skips comments between the extern keyword and the opening // brace. - self.last_pos = span.lo + BytePos(brace_pos as u32); + self.last_pos = span.lo + BytePos(brace_pos as u32 + 1); self.block_indent = self.block_indent.block_indent(self.config); - for item in &fm.items { - self.format_foreign_item(&*item); - } + if fm.items.is_empty() { + self.format_missing_no_indent(span.hi - BytePos(1)); + self.block_indent = self.block_indent.block_unindent(self.config); + + self.buffer.push_str(&self.block_indent.to_string(self.config)); + } else { + for item in &fm.items { + self.format_foreign_item(&*item); + } - self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(span.hi - BytePos(1)); + self.block_indent = self.block_indent.block_unindent(self.config); + self.format_missing_with_indent(span.hi - BytePos(1)); + } } self.buffer.push_str("}"); @@ -299,7 +305,8 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&format_header("enum ", ident, vis)); let enum_snippet = self.snippet(span); - let body_start = span.lo + BytePos(enum_snippet.find_uncommented("{").unwrap() as u32 + 1); + let brace_pos = enum_snippet.find_uncommented("{").unwrap(); + let body_start = span.lo + BytePos(brace_pos as u32 + 1); let generics_str = format_generics(&self.get_context(), generics, "{", @@ -318,11 +325,17 @@ impl<'a> FmtVisitor<'a> { let variant_list = self.format_variant_list(enum_def, body_start, span.hi - BytePos(1)); match variant_list { Some(ref body_str) => self.buffer.push_str(&body_str), - None => self.format_missing(span.hi - BytePos(1)), + None => { + if contains_comment(&enum_snippet[brace_pos..]) { + self.format_missing_no_indent(span.hi - BytePos(1)) + } else { + self.format_missing(span.hi - BytePos(1)) + } + } } self.block_indent = self.block_indent.block_unindent(self.config); - if variant_list.is_some() { + if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { self.buffer.push_str(&self.block_indent.to_string(self.config)); } self.buffer.push_str("}"); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7e6d1516636..5a737ebdee8 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -34,6 +34,12 @@ impl<'a> FmtVisitor<'a> { }) } + pub fn format_missing_no_indent(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, _| { + this.buffer.push_str(last_snippet.trim_right()); + }) + } + fn format_missing_inner(&mut self, end: BytePos, process_last_snippet: F) { diff --git a/tests/source/issue-977.rs b/tests/source/issue-977.rs new file mode 100644 index 00000000000..dc2663d581b --- /dev/null +++ b/tests/source/issue-977.rs @@ -0,0 +1,7 @@ +// FIXME(#919) + +trait NameC { /* comment */ } +struct FooC { /* comment */ } +enum MooC { /* comment */ } +mod BarC { /* comment */ } +extern { /* comment */ } diff --git a/tests/target/issue-977.rs b/tests/target/issue-977.rs new file mode 100644 index 00000000000..ad7c2bd4e5c --- /dev/null +++ b/tests/target/issue-977.rs @@ -0,0 +1,15 @@ +// FIXME(#919) + +trait NameC { + // comment +} +struct FooC { /* comment */ } +enum MooC { + // comment +} +mod BarC { + // comment +} +extern "C" { + // comment +} -- cgit 1.4.1-3-g733a5 From a3c63fdef95e0be5f09b7479765e54830b4ae250 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 23 Aug 2016 23:14:45 +0900 Subject: Run clippy --- src/bin/cargo-fmt.rs | 12 ++++++------ src/bin/rustfmt.rs | 2 +- src/chains.rs | 2 +- src/checkstyle.rs | 20 ++++++++------------ src/comment.rs | 8 ++++---- src/expr.rs | 44 ++++++++++++++++++++++---------------------- src/imports.rs | 10 +++++----- src/issues.rs | 6 +----- src/items.rs | 42 +++++++++++++++++++++--------------------- src/lib.rs | 6 +++--- src/lists.rs | 4 ++-- src/macros.rs | 2 +- src/missed_spans.rs | 18 ++++++++---------- src/modules.rs | 4 ++-- src/patterns.rs | 2 +- src/types.rs | 18 +++++++++--------- src/utils.rs | 2 +- src/visitor.rs | 16 ++++++++-------- 18 files changed, 104 insertions(+), 114 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3c3ce223318..9d2733f5820 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -123,15 +123,15 @@ enum TargetKind { impl TargetKind { fn is_lib(&self) -> bool { - match self { - &TargetKind::Lib => true, + match *self { + TargetKind::Lib => true, _ => false, } } fn is_bin(&self) -> bool { - match self { - &TargetKind::Bin => true, + match *self { + TargetKind::Bin => true, _ => false, } } @@ -180,8 +180,8 @@ fn target_from_json(jtarget: &Json) -> Target { } } -fn format_files(files: &Vec, - fmt_args: &Vec, +fn format_files(files: &[PathBuf], + fmt_args: &[String], verbosity: Verbosity) -> Result { let stdout = if verbosity == Verbosity::Quiet { diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 3434f01ac9f..ab41fbb7de7 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -198,7 +198,7 @@ fn execute(opts: &Options) -> FmtResult { match try!(determine_operation(&matches)) { Operation::Help => { - print_usage(&opts, ""); + print_usage(opts, ""); Ok(Summary::new()) } Operation::Version => { diff --git a/src/chains.rs b/src/chains.rs index 4a0b21a01e2..77835d0414e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -186,7 +186,7 @@ pub fn rewrite_chain(expr: &ast::Expr, format!("\n{}", indent.to_string(context.config)) }; - let first_connector = if extend || subexpr_list.len() == 0 { + let first_connector = if extend || subexpr_list.is_empty() { "" } else if let ast::ExprKind::Try(_) = subexpr_list[0].node { "" diff --git a/src/checkstyle.rs b/src/checkstyle.rs index c43a37cf813..3fc117904c7 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -45,18 +45,14 @@ pub fn output_checkstyle_file(mut writer: T, try!(write!(writer, "", filename)); for mismatch in diff { for line in mismatch.lines { - match line { - DiffLine::Expected(ref str) => { - let message = xml_escape_str(&str); - try!(write!(writer, - "", - mismatch.line_number, - message)); - } - _ => { - // Do nothing with context and expected. - } + // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. + if let DiffLine::Expected(ref str) = line { + let message = xml_escape_str(str); + try!(write!(writer, + "", + mismatch.line_number, + message)); } } } diff --git a/src/comment.rs b/src/comment.rs index 062e4ba0ca7..979d3bef90e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -94,7 +94,7 @@ pub fn rewrite_comment(orig: &str, let mut result = opener.to_owned(); for line in lines { if result == opener { - if line.len() == 0 { + if line.is_empty() { continue; } } else { @@ -107,7 +107,7 @@ pub fn rewrite_comment(orig: &str, let rewrite = rewrite_string(line, &fmt).unwrap_or(line.to_owned()); result.push_str(&rewrite); } else { - if line.len() == 0 { + if line.is_empty() { // Remove space if this is an empty comment or a doc comment. result.pop(); } @@ -136,7 +136,7 @@ fn left_trim_comment_line(line: &str) -> &str { } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || line.starts_with("**") { &line[2..] - } else if line.starts_with("*") { + } else if line.starts_with('*') { &line[1..] } else { line @@ -524,7 +524,7 @@ pub fn recover_comment_removed(new: String, if changed_comment_content(&snippet, &new) { // We missed some comments // Keep previous formatting if it satisfies the constrains - return wrap_str(snippet, context.config.max_width, width, offset); + wrap_str(snippet, context.config.max_width, width, offset) } else { Some(new) } diff --git a/src/expr.rs b/src/expr.rs index 1fea4f40e17..0f0526dba6d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -298,7 +298,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.span.lo, |item| item.span.hi, // 1 = [ - |item| item.rewrite(&inner_context, max_item_width, offset), + |item| item.rewrite(inner_context, max_item_width, offset), span.lo, span.hi) .collect::>(); @@ -493,7 +493,7 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { block_str.map(|block_str| { - if block_str.starts_with("{") && budget >= 2 && + if block_str.starts_with('{') && budget >= 2 && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { "{}".to_owned() } else { @@ -772,7 +772,7 @@ fn rewrite_if_else(context: &RewriteContext, pat.map_or(cond.span.lo, |_| context.codemap.span_before(span, "let"))); - let between_if_cond_comment = extract_comment(between_if_cond, &context, offset, width); + let between_if_cond_comment = extract_comment(between_if_cond, context, offset, width); let after_cond_comment = extract_comment(mk_sp(cond.span.hi, if_block.span.lo), context, @@ -831,13 +831,13 @@ fn rewrite_if_else(context: &RewriteContext, mk_sp(if_block.span.hi, context.codemap.span_before(mk_sp(if_block.span.hi, else_block.span.lo), "else")); let between_if_else_block_comment = - extract_comment(between_if_else_block, &context, offset, width); + extract_comment(between_if_else_block, context, offset, width); let after_else = mk_sp(context.codemap .span_after(mk_sp(if_block.span.hi, else_block.span.lo), "else"), else_block.span.lo); - let after_else_comment = extract_comment(after_else, &context, offset, width); + let after_else_comment = extract_comment(after_else, context, offset, width); let between_sep = match context.config.else_if_brace_style { ElseIfBraceStyle::AlwaysNextLine | @@ -854,7 +854,7 @@ fn rewrite_if_else(context: &RewriteContext, .map_or(between_sep, |str| &**str), after_else_comment.as_ref().map_or(after_sep, |str| &**str)) .ok()); - result.push_str(&&try_opt!(rewrite)); + result.push_str(&try_opt!(rewrite)); } Some(result) @@ -1021,7 +1021,7 @@ fn rewrite_match(context: &RewriteContext, // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); - result.push_str(arm_comma(&context.config, &arm, &arm.body)); + result.push_str(arm_comma(context.config, arm, &arm.body)); } } // BytePos(1) = closing match brace. @@ -1102,7 +1102,7 @@ impl Rewrite for ast::Arm { .map(|p| p.rewrite(context, pat_budget, offset)) .collect::>>()); - let all_simple = pat_strs.iter().all(|p| pat_is_simple(&p)); + let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); let fmt = ListFormatting { tactic: if all_simple { @@ -1145,7 +1145,7 @@ impl Rewrite for ast::Arm { ref x => x, }; - let comma = arm_comma(&context.config, self, body); + let comma = arm_comma(context.config, self, body); let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); // Let's try and get the arm body on the same line as the condition. @@ -1305,7 +1305,7 @@ fn rewrite_pat_expr(context: &RewriteContext, expr.rewrite(context, try_opt!(context.config.max_width.checked_sub(pat_offset.width())), pat_offset); - result.push_str(&&try_opt!(expr_rewrite)); + result.push_str(&try_opt!(expr_rewrite)); Some(result) } @@ -1433,7 +1433,7 @@ fn rewrite_call_inner(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - |item| item.rewrite(&inner_context, remaining_width, offset), + |item| item.rewrite(inner_context, remaining_width, offset), span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1454,7 +1454,7 @@ fn rewrite_call_inner(context: &RewriteContext, // first arguments. if overflow_last { let inner_context = &RewriteContext { block_indent: context.block_indent, ..*context }; - let rewrite = args.last().unwrap().rewrite(&inner_context, remaining_width, offset); + let rewrite = args.last().unwrap().rewrite(inner_context, remaining_width, offset); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); @@ -1557,8 +1557,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, "}", |item| { match *item { - StructLitField::Regular(ref field) => field.span.lo, - StructLitField::Base(ref expr) => { + StructLitField::Regular(field) => field.span.lo, + StructLitField::Base(expr) => { let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); @@ -1568,19 +1568,19 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, }, |item| { match *item { - StructLitField::Regular(ref field) => field.span.hi, - StructLitField::Base(ref expr) => expr.span.hi, + StructLitField::Regular(field) => field.span.hi, + StructLitField::Base(expr) => expr.span.hi, } }, |item| { match *item { - StructLitField::Regular(ref field) => { + StructLitField::Regular(field) => { rewrite_field(inner_context, - &field, + field, v_budget.checked_sub(1).unwrap_or(0), indent) } - StructLitField::Base(ref expr) => { + StructLitField::Base(expr) => { // 2 = .. expr.rewrite(inner_context, try_opt!(v_budget.checked_sub(2)), indent + 2) .map(|s| format!("..{}", s)) @@ -1678,7 +1678,7 @@ fn rewrite_field(context: &RewriteContext, match expr { Some(e) => Some(format!("{}{}{}", name, separator, e)), None => { - let expr_offset = offset.block_indent(&context.config); + let expr_offset = offset.block_indent(context.config); let expr = field.expr.rewrite(context, try_opt!(context.config .max_width @@ -1843,7 +1843,7 @@ fn rewrite_assignment(context: &RewriteContext, try_opt!(lhs.rewrite(context, max_width, offset)), operator_str); - rewrite_assign_rhs(&context, lhs_str, rhs, width, offset) + rewrite_assign_rhs(context, lhs_str, rhs, width, offset) } // The left hand side must contain everything up to, and including, the @@ -1863,7 +1863,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, }; // 1 = space between operator and rhs. let max_width = try_opt!(width.checked_sub(last_line_width + 1)); - let rhs = ex.rewrite(&context, max_width, offset + last_line_width + 1); + let rhs = ex.rewrite(context, max_width, offset + last_line_width + 1); fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() diff --git a/src/imports.rs b/src/imports.rs index bc343307272..8ae3b06e28b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -21,10 +21,10 @@ use std::cmp::{self, Ordering}; use syntax::{ast, ptr}; fn path_of(a: &ast::ViewPath_) -> &ast::Path { - match a { - &ast::ViewPath_::ViewPathSimple(_, ref p) => p, - &ast::ViewPath_::ViewPathGlob(ref p) => p, - &ast::ViewPath_::ViewPathList(ref p, _) => p, + match *a { + ast::ViewPath_::ViewPathSimple(_, ref p) => p, + ast::ViewPath_::ViewPathGlob(ref p) => p, + ast::ViewPath_::ViewPathList(ref p, _) => p, } } @@ -203,7 +203,7 @@ impl<'a> FmtVisitor<'a> { // Fake out the formatter by setting `self.last_pos` to the appropriate location before // each item before visiting it. self.last_pos = ordered.1; - self.visit_item(&ordered.0); + self.visit_item(ordered.0); } self.last_pos = pos_after_last_use_item; } diff --git a/src/issues.rs b/src/issues.rs index 64797de2fda..5282ee603ac 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -22,11 +22,7 @@ const FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; // irrelevant outside the issues module impl ReportTactic { fn is_enabled(&self) -> bool { - match *self { - ReportTactic::Always => true, - ReportTactic::Unnumbered => true, - ReportTactic::Never => false, - } + *self != ReportTactic::Never } } diff --git a/src/items.rs b/src/items.rs index 55b4f8b9dcd..b8fde7fbb0b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -276,7 +276,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent) .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) - } else if let Some(ref stmt) = block.stmts.first() { + } else if let Some(stmt) = block.stmts.first() { stmt.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), self.block_indent) @@ -324,7 +324,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); let variant_list = self.format_variant_list(enum_def, body_start, span.hi - BytePos(1)); match variant_list { - Some(ref body_str) => self.buffer.push_str(&body_str), + Some(ref body_str) => self.buffer.push_str(body_str), None => { if contains_comment(&enum_snippet[brace_pos..]) { self.format_missing_no_indent(span.hi - BytePos(1)) @@ -554,7 +554,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in items { - visitor.visit_impl_item(&item); + visitor.visit_impl_item(item); } visitor.format_missing(item.span.hi - BytePos(1)); @@ -564,7 +564,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - result.push('\n'); result.push_str(&inner_indent_str); - result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); + result.push_str(trim_newlines(visitor.buffer.to_string().trim())); result.push('\n'); result.push_str(&outer_indent_str); } @@ -581,7 +581,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - } fn is_impl_single_line(context: &RewriteContext, - items: &Vec, + items: &[ImplItem], result: &str, where_clause_str: &str, item: &ast::Item) @@ -713,7 +713,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if !where_clause_str.is_empty() && - (trait_items.len() > 0 || result.contains('\n')) { + (!trait_items.is_empty() || result.contains('\n')) { result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -732,7 +732,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in trait_items { - visitor.visit_trait_item(&item); + visitor.visit_trait_item(item); } visitor.format_missing(item.span.hi - BytePos(1)); @@ -742,7 +742,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push('\n'); result.push_str(&inner_indent_str); - result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); + result.push_str(trim_newlines(visitor.buffer.to_string().trim())); result.push('\n'); result.push_str(&outer_indent_str); } else if result.contains('\n') { @@ -876,7 +876,7 @@ fn format_tuple_struct(context: &RewriteContext, }; let where_clause_str = match generics { - Some(ref generics) => { + Some(generics) => { let generics_str = try_opt!(rewrite_generics(context, generics, offset, @@ -951,7 +951,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, -> Option { let mut result = String::new(); - result.push_str(&format_visibility(&vis)); + result.push_str(&format_visibility(vis)); result.push_str("type "); result.push_str(&ident.to_string()); @@ -1069,7 +1069,7 @@ pub fn rewrite_static(prefix: &str, prefix.len() - 2, context.block_indent)); - if let Some(ref expr) = expr_opt { + if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; let remaining_width = context.config.max_width - context.block_indent.width() - 1; @@ -1090,7 +1090,7 @@ pub fn rewrite_associated_type(ident: ast::Ident, let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let bounds: &[_] = &ty_param_bounds; + let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!(bounds.iter() .map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) .intersperse(Some(" + ".to_string())) @@ -1374,7 +1374,7 @@ fn rewrite_fn_base(context: &RewriteContext, FnArgLayoutStyle::Block => multi_line_arg_str, FnArgLayoutStyle::BlockAlways => true, _ => false, - } && fd.inputs.len() > 0; + } && !fd.inputs.is_empty(); if put_args_in_block { arg_indent = indent.block_indent(context.config); @@ -1410,7 +1410,7 @@ fn rewrite_fn_base(context: &RewriteContext, let overlong_sig = sig_length > context.config.max_width; - result.contains("\n") || multi_line_ret_str || overlong_sig + result.contains('\n') || multi_line_ret_str || overlong_sig } }; let ret_indent = if ret_should_indent { @@ -1647,7 +1647,7 @@ fn compute_budgets_for_args(context: &RewriteContext, newline_brace: bool) -> Option<((usize, usize, Indent))> { // Try keeping everything on the same line. - if !result.contains("\n") { + if !result.contains('\n') { // 3 = `() `, space is before ret_string. let mut used_space = indent.width() + result.len() + ret_str_len + 3; if !newline_brace { @@ -1710,8 +1710,8 @@ fn rewrite_generics(context: &RewriteContext, // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. - let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(&context, h_budget, offset)); - let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(&context, h_budget, offset)); + let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, h_budget, offset)); + let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(context, h_budget, offset)); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { @@ -1743,7 +1743,7 @@ fn rewrite_trait_bounds(context: &RewriteContext, indent: Indent, width: usize) -> Option { - let bounds: &[_] = &type_param_bounds; + let bounds: &[_] = type_param_bounds; if bounds.is_empty() { return Some(String::new()); @@ -1801,7 +1801,7 @@ fn rewrite_where_clause(context: &RewriteContext, terminator, |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(&context, budget, offset), + |pred| pred.rewrite(context, budget, offset), span_start, span_end); let item_vec = items.collect::>(); @@ -1825,9 +1825,9 @@ fn rewrite_where_clause(context: &RewriteContext, // If the brace is on the next line we don't need to count it otherwise it needs two // characters " {" match brace_style { - BraceStyle::AlwaysNextLine => 0, - BraceStyle::PreferSameLine => 2, + BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0, + BraceStyle::PreferSameLine => 2, } } else if terminator == "=" { 2 diff --git a/src/lib.rs b/src/lib.rs index 17af40d9b37..dd6a2a5d079 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -254,7 +254,7 @@ impl FormatReport { } pub fn warning_count(&self) -> usize { - self.file_error_map.iter().map(|(_, ref errors)| errors.len()).fold(0, |acc, x| acc + x) + self.file_error_map.iter().map(|(_, errors)| errors.len()).fold(0, |acc, x| acc + x) } pub fn has_warnings(&self) -> bool { @@ -392,9 +392,9 @@ fn parse_input(input: Input, parse_session: &ParseSess) -> Result> { let result = match input { - Input::File(file) => parse::parse_crate_from_file(&file, Vec::new(), &parse_session), + Input::File(file) => parse::parse_crate_from_file(&file, Vec::new(), parse_session), Input::Text(text) => { - parse::parse_crate_from_source_str("stdin".to_owned(), text, Vec::new(), &parse_session) + parse::parse_crate_from_source_str("stdin".to_owned(), text, Vec::new(), parse_session) } }; diff --git a/src/lists.rs b/src/lists.rs index 2bd4becc57f..9607039e1d2 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -357,7 +357,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> // Post-comment let next_start = match self.inner.peek() { - Some(ref next_item) => (self.get_lo)(next_item), + Some(next_item) => (self.get_lo)(next_item), None => self.next_span_start, }; let post_snippet = self.codemap @@ -420,7 +420,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let post_snippet_trimmed = if post_snippet.starts_with(',') { post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(",") { + } else if post_snippet.ends_with(',') { post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) } else { post_snippet diff --git a/src/macros.rs b/src/macros.rs index 9cb0f8619c0..5b87f6cc7ec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -111,7 +111,7 @@ pub fn rewrite_macro(mac: &ast::Mac, _ => return None, } - let _ = parser.bump(); + parser.bump(); if parser.token == Token::Eof { return None; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 22f56ef5fe0..98d87ba4963 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -118,7 +118,7 @@ impl<'a> FmtVisitor<'a> { let last_char = big_snippet[..(offset + big_diff)] .chars() .rev() - .skip_while(|rev_c| [' ', '\t'].contains(&rev_c)) + .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) .next(); let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); @@ -174,19 +174,17 @@ impl<'a> FmtVisitor<'a> { line_start = i + 1; last_wspace = None; rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; - } else { - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(i); - } - } else { - rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; - last_wspace = None; + } else if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(i); } + } else { + rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + last_wspace = None; } } } - process_last_snippet(self, &snippet[line_start..], &snippet); + process_last_snippet(self, &snippet[line_start..], snippet); } } diff --git a/src/modules.rs b/src/modules.rs index e56fa57ac7b..6ea2248ed3c 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -64,11 +64,11 @@ fn module_file(id: ast::Ident, dir_path: &Path, codemap: &codemap::CodeMap) -> PathBuf { - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &dir_path) { + if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { return path; } - match parser::Parser::default_submod_path(id, &dir_path, codemap).result { + match parser::Parser::default_submod_path(id, dir_path, codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => path, Err(_) => panic!("Couldn't find module {}", id), } diff --git a/src/patterns.rs b/src/patterns.rs index a0b15a0f8c9..c35dd25672d 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -153,7 +153,7 @@ impl Rewrite for Pat { field_string.push_str(&offset.to_string(context.config)); field_string.push_str(".."); } else { - if field_string.len() > 0 { + if !field_string.is_empty() { field_string.push_str(", "); } field_string.push_str(".."); diff --git a/src/types.rs b/src/types.rs index 598ac3b6ac8..fff46b0750d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -43,7 +43,7 @@ pub fn rewrite_path(context: &RewriteContext, let mut span_lo = path.span.lo; - if let Some(ref qself) = qself { + if let Some(qself) = qself { result.push('<'); let fmt_ty = try_opt!(qself.ty.rewrite(context, width, offset)); result.push_str(&fmt_ty); @@ -131,9 +131,9 @@ enum SegmentParam<'a> { impl<'a> SegmentParam<'a> { fn get_span(&self) -> Span { match *self { - SegmentParam::LifeTime(ref lt) => lt.span, - SegmentParam::Type(ref ty) => ty.span, - SegmentParam::Binding(ref binding) => binding.span, + SegmentParam::LifeTime(lt) => lt.span, + SegmentParam::Type(ty) => ty.span, + SegmentParam::Binding(binding) => binding.span, } } } @@ -141,9 +141,9 @@ impl<'a> SegmentParam<'a> { impl<'a> Rewrite for SegmentParam<'a> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { - SegmentParam::LifeTime(ref lt) => lt.rewrite(context, width, offset), - SegmentParam::Type(ref ty) => ty.rewrite(context, width, offset), - SegmentParam::Binding(ref binding) => { + SegmentParam::LifeTime(lt) => lt.rewrite(context, width, offset), + SegmentParam::Type(ty) => ty.rewrite(context, width, offset), + SegmentParam::Binding(binding) => { let mut result = format!("{} = ", binding.ident); let budget = try_opt!(width.checked_sub(result.len())); let rewrite = try_opt!(binding.ty.rewrite(context, budget, offset + result.len())); @@ -306,7 +306,7 @@ fn format_function_type<'a, I>(inputs: I, FunctionRetTy::Default(..) => String::new(), }; - let infix = if output.len() > 0 && output.len() + list_str.len() > width { + let infix = if !output.is_empty() && output.len() + list_str.len() > width { format!("\n{}", (offset - 1).to_string(context.config)) } else { String::new() @@ -622,7 +622,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str("> "); } - result.push_str(&::utils::format_unsafety(bare_fn.unsafety)); + result.push_str(::utils::format_unsafety(bare_fn.unsafety)); if bare_fn.abi != abi::Abi::Rust { result.push_str(&::utils::format_abi(bare_fn.abi, context.config.force_explicit_abi)); diff --git a/src/utils.rs b/src/utils.rs index 0978e552837..70f16386ec2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -251,7 +251,7 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: Ind } // The other lines must fit within the maximum width. - if lines.find(|line| line.len() > max_width).is_some() { + if lines.any(|line| line.len() > max_width) { return None; } diff --git a/src/visitor.rs b/src/visitor.rs index b89b97487a5..237866ed9ec 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -85,7 +85,7 @@ impl<'a> FmtVisitor<'a> { // Check if this block has braces. let snippet = self.snippet(b.span); - let has_braces = snippet.starts_with("{") || snippet.starts_with("unsafe"); + let has_braces = snippet.starts_with('{') || snippet.starts_with("unsafe"); let brace_compensation = if has_braces { BytePos(1) } else { BytePos(0) }; self.last_pos = self.last_pos + brace_compensation; @@ -93,7 +93,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str("{"); for stmt in &b.stmts { - self.visit_stmt(&stmt) + self.visit_stmt(stmt) } if let Some(ref e) = b.expr { @@ -144,7 +144,7 @@ impl<'a> FmtVisitor<'a> { defaultness: ast::Defaultness) { let indent = self.block_indent; let rewrite = match fk { - visit::FnKind::ItemFn(ident, ref generics, unsafety, constness, abi, vis) => { + visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis) => { self.rewrite_fn(indent, ident, fd, @@ -155,9 +155,9 @@ impl<'a> FmtVisitor<'a> { abi, vis, codemap::mk_sp(s.lo, b.span.lo), - &b) + b) } - visit::FnKind::Method(ident, ref sig, vis) => { + visit::FnKind::Method(ident, sig, vis) => { self.rewrite_fn(indent, ident, fd, @@ -168,7 +168,7 @@ impl<'a> FmtVisitor<'a> { sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), codemap::mk_sp(s.lo, b.span.lo), - &b) + b) } visit::FnKind::Closure => None, }; @@ -374,7 +374,7 @@ impl<'a> FmtVisitor<'a> { ast::TraitItemKind::Method(ref sig, Some(ref body)) => { self.visit_fn(visit::FnKind::Method(ti.ident, sig, None), &sig.decl, - &body, + body, ti.span, ti.id, ast::Defaultness::Final); @@ -516,7 +516,7 @@ impl<'a> FmtVisitor<'a> { // `unwrap()` is safe here because we know `items_left` // has elements from the loop condition let (item, rest) = items_left.split_first().unwrap(); - self.visit_item(&item); + self.visit_item(item); items_left = rest; } } -- cgit 1.4.1-3-g733a5 From a5d7073bf51937508ba38c3745622ef31473c0e5 Mon Sep 17 00:00:00 2001 From: dawirstejeck Date: Tue, 6 Sep 2016 07:11:56 +0200 Subject: Split impl at 'for' if a line break is needed (#1148) * Split impl at 'for' if a line break is needed * Fix formatting * Improve comments * Skip second try if there is no 'for' * Restore intentional trailing whitespace * Change test source to be incorrectly formatted * Restore more missing trailing whitespace * Remove too much whitespace... Really should learn how to use git revert. --- src/items.rs | 127 +++++++++++++++++++++++++++++++------------------- tests/source/impls.rs | 3 ++ tests/target/impls.rs | 4 ++ 3 files changed, 87 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index b8fde7fbb0b..d06fc9b2b8c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -446,58 +446,21 @@ impl<'a> FmtVisitor<'a> { } pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { - if let ast::ItemKind::Impl(unsafety, - polarity, - ref generics, - ref trait_ref, - ref self_ty, - ref items) = item.node { + if let ast::ItemKind::Impl(_, _, ref generics, ref trait_ref, _, ref items) = item.node { let mut result = String::new(); - result.push_str(&*format_visibility(&item.vis)); - result.push_str(format_unsafety(unsafety)); - result.push_str("impl"); - - let lo = context.codemap.span_after(item.span, "impl"); - let hi = match *trait_ref { - Some(ref tr) => tr.path.span.lo, - None => self_ty.span.lo, - }; - let generics_str = try_opt!(rewrite_generics(context, - generics, - offset, - context.config.max_width, - offset + result.len(), - mk_sp(lo, hi))); - result.push_str(&generics_str); - - // FIXME might need to linebreak in the impl header, here would be a - // good place. - result.push(' '); - if polarity == ast::ImplPolarity::Negative { - result.push_str("!"); - } - if let Some(ref trait_ref) = *trait_ref { - let budget = try_opt!(context.config.max_width.checked_sub(result.len())); - let indent = offset + result.len(); - result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent))); - result.push_str(" for "); - } + // First try to format the ref and type without a split at the 'for'. + let mut ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, false)); - let mut used_space = result.len(); - if generics.where_clause.predicates.is_empty() { - // If there is no where clause adapt budget for type formatting to take space and curly - // brace into account. - match context.config.item_brace_style { - BraceStyle::AlwaysNextLine => {} - BraceStyle::PreferSameLine => used_space += 2, - BraceStyle::SameLineWhere => used_space += 2, + // If there is a line break present in the first result format it again + // with a split at the 'for'. Skip this if there is no trait ref and + // therefore no 'for'. + if let Some(_) = *trait_ref { + if ref_and_type.contains('\n') { + ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, true)); } } - - let budget = try_opt!(context.config.max_width.checked_sub(used_space)); - let indent = offset + result.len(); - result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); + result.push_str(&ref_and_type); let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, @@ -594,6 +557,76 @@ fn is_impl_single_line(context: &RewriteContext, !contains_comment(&snippet[open_pos..])) } +fn format_impl_ref_and_type(context: &RewriteContext, + item: &ast::Item, + offset: Indent, + split_at_for: bool) + -> Option { + if let ast::ItemKind::Impl(unsafety, polarity, ref generics, ref trait_ref, ref self_ty, _) = + item.node { + let mut result = String::new(); + + result.push_str(&*format_visibility(&item.vis)); + result.push_str(format_unsafety(unsafety)); + result.push_str("impl"); + + let lo = context.codemap.span_after(item.span, "impl"); + let hi = match *trait_ref { + Some(ref tr) => tr.path.span.lo, + None => self_ty.span.lo, + }; + let generics_str = try_opt!(rewrite_generics(context, + generics, + offset, + context.config.max_width, + offset + result.len(), + mk_sp(lo, hi))); + result.push_str(&generics_str); + + result.push(' '); + if polarity == ast::ImplPolarity::Negative { + result.push('!'); + } + if let Some(ref trait_ref) = *trait_ref { + let budget = try_opt!(context.config.max_width.checked_sub(result.len())); + let indent = offset + result.len(); + result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent))); + + if split_at_for { + result.push('\n'); + + // Add indentation of one additional tab. + let width = context.block_indent.width() + context.config.tab_spaces; + let for_indent = Indent::new(0, width); + result.push_str(&for_indent.to_string(context.config)); + + result.push_str("for "); + } else { + result.push_str(" for "); + } + } + + let mut used_space = last_line_width(&result); + if generics.where_clause.predicates.is_empty() { + // If there is no where clause adapt budget for type formatting to take space and curly + // brace into account. + match context.config.item_brace_style { + BraceStyle::AlwaysNextLine => {} + BraceStyle::PreferSameLine => used_space += 2, + BraceStyle::SameLineWhere => used_space += 2, + } + } + + let budget = try_opt!(context.config.max_width.checked_sub(used_space)); + let indent = offset + result.len(); + result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); + + Some(result) + } else { + unreachable!(); + } +} + pub fn format_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 5fbcecb9700..6d65b8b4a7a 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -100,3 +100,6 @@ mod m { impl Handle, HandleType> { } + +impl PartialEq for Handle, HandleType> { +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 03045c21ac5..87791d25648 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -128,3 +128,7 @@ mod m { impl Handle, HandleType> { } + +impl PartialEq + for Handle, HandleType> { +} -- cgit 1.4.1-3-g733a5 From bf078566d7aaf62f3dc9f9f6cc2a95c377e00a37 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 6 Sep 2016 18:03:47 +0900 Subject: Fix #1021: Handle `..` in tuple / tuple struct patterns --- src/patterns.rs | 133 +++++++++++++++++++++++++++++++-------------- tests/source/issue-1021.rs | 21 +++++++ tests/target/issue-1021.rs | 27 +++++++++ 3 files changed, 141 insertions(+), 40 deletions(-) create mode 100644 tests/source/issue-1021.rs create mode 100644 tests/target/issue-1021.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index c35dd25672d..b52eeb9c445 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -13,10 +13,14 @@ use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; use lists::{format_item_list, itemize_list}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; +use expr::{rewrite_unary_prefix, rewrite_pair}; use types::rewrite_path; +use super::Spanned; +use comment::FindUncommented; -use syntax::ast::{BindingMode, Pat, PatKind, FieldPat}; +use syntax::ast::{self, BindingMode, Pat, PatKind, FieldPat}; +use syntax::ptr; +use syntax::codemap::{self, BytePos, Span}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { @@ -60,49 +64,19 @@ impl Rewrite for Pat { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, width, offset) } - // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492) PatKind::Tuple(ref items, dotdot_pos) => { - if dotdot_pos.is_some() { - return None; - } - rewrite_tuple(context, - items.iter().map(|x| &**x), - self.span, - width, - offset) + rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, width, offset) } PatKind::Path(ref path) => rewrite_path(context, true, None, path, width, offset), PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); - - // FIXME(#1021): Handle `..` in tuple / tuple struct patterns (RFC 1492) - match dotdot_pos { - Some(_) => Some(format!("{}(..)", path_str)), - None => { - if pat_vec.is_empty() { - Some(path_str) - } else { - // 2 = "()".len() - let width = try_opt!(width.checked_sub(path_str.len() + 2)); - // 1 = "(".len() - let offset = offset + path_str.len() + 1; - let items = itemize_list(context.codemap, - pat_vec.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, width, offset), - context.codemap.span_after(self.span, "("), - self.span.hi); - Some(format!("{}({})", - path_str, - try_opt!(format_item_list(items, - width, - offset, - context.config)))) - } - } - } + rewrite_tuple_pat(pat_vec, + dotdot_pos, + Some(path_str), + self.span, + context, + width, + offset) } PatKind::Lit(ref expr) => expr.rewrite(context, width, offset), PatKind::Vec(ref prefix, ref slice_pat, ref suffix) => { @@ -190,3 +164,82 @@ impl Rewrite for FieldPat { } } } + + +enum TuplePatField<'a> { + Pat(&'a ptr::P), + Dotdot(Span), +} + +impl<'a> Rewrite for TuplePatField<'a> { + fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + match *self { + TuplePatField::Pat(ref p) => p.rewrite(context, width, offset), + TuplePatField::Dotdot(_) => Some("..".to_string()), + } + } +} + +impl<'a> Spanned for TuplePatField<'a> { + fn span(&self) -> Span { + match *self { + TuplePatField::Pat(ref p) => p.span(), + TuplePatField::Dotdot(span) => span, + } + } +} + +fn rewrite_tuple_pat(pats: &[ptr::P], + dotdot_pos: Option, + path_str: Option, + span: Span, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); + + if let Some(pos) = dotdot_pos { + let snippet = context.snippet(span); + let lo = span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); + let span = Span { + lo: lo, + // 2 == "..".len() + hi: lo + BytePos(2), + expn_id: codemap::NO_EXPANSION, + }; + let dotdot = TuplePatField::Dotdot(span); + pat_vec.insert(pos, dotdot); + } + + if pat_vec.is_empty() { + path_str + } else { + // add comma if `(x,)` + let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + + let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); + // 2 = "()".len(), 3 = "(,)".len() + let width = try_opt!(width.checked_sub(path_len + if add_comma { 3 } else { 2 })); + // 1 = "(".len() + let offset = offset + path_len + 1; + let items = itemize_list(context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, width, offset), + context.codemap.span_after(span, "("), + span.hi - BytePos(1)); + + let list = try_opt!(format_item_list(items, width, offset, context.config)); + + match path_str { + Some(path_str) => Some(format!("{}({})", path_str, list)), + None => { + let comma = if add_comma { "," } else { "" }; + Some(format!("({}{})", list, comma)) + } + } + } +} diff --git a/tests/source/issue-1021.rs b/tests/source/issue-1021.rs new file mode 100644 index 00000000000..2c1b4716f57 --- /dev/null +++ b/tests/source/issue-1021.rs @@ -0,0 +1,21 @@ +fn main() { + match x { + S(true , .., true ) => (), + S(true , .. ) => (), + S(.., true ) => (), + S( .. ) => (), + S(_) => (), + S(/* .. */ .. ) => (), + S(/* .. */ .., true ) => (), + } + + match y { + (true , .., true ) => (), + (true , .. ) => (), + (.., true ) => (), + ( .. ) => (), + (_,) => (), + (/* .. */ .. ) => (), + (/* .. */ .., true ) => (), + } +} diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs new file mode 100644 index 00000000000..e4379855642 --- /dev/null +++ b/tests/target/issue-1021.rs @@ -0,0 +1,27 @@ +fn main() { + match x { + S(true, .., true) => (), + S(true, ..) => (), + S(.., true) => (), + S(..) => (), + S(_) => (), + S(// .. + ..) => (), + S(// .. + .., + true) => (), + } + + match y { + (true, .., true) => (), + (true, ..) => (), + (.., true) => (), + (..) => (), + (_,) => (), + (// .. + ..) => (), + (// .. + .., + true) => (), + } +} -- cgit 1.4.1-3-g733a5 From b446e3173937f53a860c05db7dbfa8401fc9e81e Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 10 Sep 2016 13:08:32 +0900 Subject: Fix #1040 --- src/visitor.rs | 2 ++ tests/source/skip.rs | 18 ++++++++++++++++++ tests/target/skip.rs | 6 ++++++ 3 files changed, 26 insertions(+) create mode 100644 tests/source/skip.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 237866ed9ec..13a4f6ec8a5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -352,6 +352,7 @@ impl<'a> FmtVisitor<'a> { pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { if self.visit_attrs(&ti.attrs) { + self.push_rewrite(ti.span, None); return; } @@ -392,6 +393,7 @@ impl<'a> FmtVisitor<'a> { pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { if self.visit_attrs(&ii.attrs) { + self.push_rewrite(ii.span, None); return; } diff --git a/tests/source/skip.rs b/tests/source/skip.rs new file mode 100644 index 00000000000..21f080e9aba --- /dev/null +++ b/tests/source/skip.rs @@ -0,0 +1,18 @@ +// Test the skip attribute works + +#[rustfmt_skip] +fn foo() { badly; formatted; stuff +; } + +#[rustfmt_skip] +trait Foo +{ +fn foo( +); +} + +impl LateLintPass for UsedUnderscoreBinding { + #[cfg_attr(rustfmt, rustfmt_skip)] + fn check_expr() { // comment + } +} diff --git a/tests/target/skip.rs b/tests/target/skip.rs index bd5a132cced..21f080e9aba 100644 --- a/tests/target/skip.rs +++ b/tests/target/skip.rs @@ -10,3 +10,9 @@ trait Foo fn foo( ); } + +impl LateLintPass for UsedUnderscoreBinding { + #[cfg_attr(rustfmt, rustfmt_skip)] + fn check_expr() { // comment + } +} -- cgit 1.4.1-3-g733a5 From 4418fab4f24e6497aa2a1f71bb4cf963c2971a28 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 16 Sep 2016 15:19:18 +1200 Subject: Update to latest Syntex + Cargo update + 0.6.2 release --- Cargo.lock | 90 +++++++++++++++++++++++----------------- Cargo.toml | 5 ++- src/expr.rs | 98 ++++++++++++++++++++++++++------------------ src/file_lines.rs | 1 + src/imports.rs | 68 +++++++++++------------------- src/items.rs | 41 +++++++++--------- src/lib.rs | 9 ++-- src/macros.rs | 3 +- src/patterns.rs | 7 ++-- src/types.rs | 6 ++- src/utils.rs | 45 ++++++++++++++++---- src/visitor.rs | 43 ++++++++----------- tests/source/file-lines-1.rs | 1 - tests/source/file-lines-2.rs | 1 - tests/source/file-lines-3.rs | 1 - tests/source/file-lines-4.rs | 1 - tests/target/file-lines-1.rs | 1 - tests/target/file-lines-2.rs | 1 - tests/target/file-lines-3.rs | 1 - tests/target/file-lines-4.rs | 1 - 20 files changed, 227 insertions(+), 197 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ebc733eb85f..82405e5d319 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,29 +1,30 @@ [root] name = "rustfmt" -version = "0.6.0" +version = "0.6.2" dependencies = [ "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "aho-corasick" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -41,11 +42,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "env_logger" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -55,7 +56,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "itertools" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -69,7 +70,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -82,7 +83,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -92,19 +93,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "0.1.73" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -121,25 +122,39 @@ dependencies = [ ] [[package]] -name = "syntex_syntax" -version = "0.33.0" +name = "syntex_errors" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "term" -version = "0.2.14" +name = "syntex_pos" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syntex_syntax" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -157,7 +172,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -193,7 +208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -211,23 +226,24 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9" +"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e48977eec6d3b7707462c2dc2e1363ad91b5dd822cf942537ccdc2085dc87587" -"checksum env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82dcb9ceed3868a03b335657b85a159736c961900f7e7747d3b0b97b9ccb5ccb" +"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum itertools 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7ddb83e0e9730d830afba4e6839077948b4efa22075f7cd80a3867ec286c610f" +"checksum itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2" +"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" -"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2" -"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199" +"checksum regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)" = "64b03446c466d35b42f2a8b203c8e03ed8b91c0f17b56e1f84f7210a257aa665" +"checksum regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279401017ae31cf4e15344aa3f085d0e2e5c1e70067289ef906906fdbe92c8fd" "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" "checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" -"checksum syntex_syntax 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44bded3cabafc65c90b663b1071bd2d198a9ab7515e6ce729e4570aaf53c407e" -"checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" +"checksum syntex_errors 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cad40c64b27f251ee286cf18e157e40fe3586bd1ad89e2318d336829e4f6bb41" +"checksum syntex_pos 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e56b7e73e8826c0bdd111da685becee1d42a42200139f72687242b6c0394247" +"checksum syntex_syntax 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1590efa9a3862c1f812abb205e16e15c81a36a6c22cdaa28962c2eb80f1453e" "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d" @@ -235,6 +251,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b905d0fc2a1f0befd86b0e72e31d1787944efef9d38b9358a9e92a69757f7e3b" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" -"checksum walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7ad450634b9022aeb0e8e7f1c79c1ded92d0fc5bee831033d148479771bd218d" +"checksum walkdir 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d42144c31c9909882ce76e696b306b88a5b091721251137d5d522d1ef3da7cf9" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 9843fd2e34d..13265da20bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt" -version = "0.6.0" +version = "0.6.2" authors = ["Nicholas Cameron ", "Marcus Klaas ", "The Rustfmt contributors"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" @@ -22,7 +22,8 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.33" +syntex_syntax = "0.43" +syntex_errors = "0.43" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/expr.rs b/src/expr.rs index 0f0526dba6d..bece2ef91fe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -22,7 +22,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, - semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr}; + semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_block, stmt_expr}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -150,7 +150,7 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, Some(op), width, offset) } - ast::ExprKind::Again(ref opt_ident) => { + ast::ExprKind::Continue(ref opt_ident) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), None => String::new(), @@ -400,7 +400,7 @@ fn rewrite_closure(capture: ast::CaptureBy, prefix.push_str(&ret_str); } - if body.expr.is_none() && body.stmts.is_empty() { + if body.stmts.is_empty() { return Some(format!("{} {{}}", prefix)); } @@ -412,10 +412,17 @@ fn rewrite_closure(capture: ast::CaptureBy, let mut had_braces = true; let mut inner_block = body; + let mut trailing_expr = stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]); + // If there is an inner block and we can ignore it, do so. - if body.stmts.is_empty() { - if let ast::ExprKind::Block(ref inner) = inner_block.expr.as_ref().unwrap().node { + if body.stmts.len() == 1 && trailing_expr.is_some() { + if let Some(ref inner) = stmt_block(&inner_block.stmts[0]) { inner_block = inner; + trailing_expr = if inner_block.stmts.is_empty() { + None + } else { + stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]) + }; } else if !force_block { had_braces = false; } @@ -426,14 +433,13 @@ fn rewrite_closure(capture: ast::CaptureBy, if try_single_line && !force_block { let must_preserve_braces = - !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(inner_block.expr - .as_ref() - .unwrap())); + trailing_expr.is_none() || + !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(trailing_expr.unwrap())); if !(must_preserve_braces && had_braces) && (must_preserve_braces || !prefix.contains('\n')) { // If we got here, then we can try to format without braces. - let inner_expr = inner_block.expr.as_ref().unwrap(); + let inner_expr = &inner_block.stmts[0]; let mut rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); if must_preserve_braces { @@ -456,7 +462,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // still prefer a one-liner (we might also have fallen through because of // lack of space). if try_single_line && !prefix.contains('\n') { - let inner_expr = inner_block.expr.as_ref().unwrap(); + let inner_expr = &inner_block.stmts[0]; // 4 = braces and spaces. let mut rewrite = inner_expr.rewrite(context, try_opt!(budget.checked_sub(4)), @@ -538,15 +544,11 @@ impl Rewrite for ast::Block { }; if is_simple_block(self, context.codemap) && prefix.len() < width { - let body = self.expr - .as_ref() - .unwrap() - .rewrite(context, width - prefix.len(), offset); - if let Some(ref expr_str) = body { - let result = format!("{}{{ {} }}", prefix, expr_str); - if result.len() <= width && !result.contains('\n') { - return Some(result); - } + let expr_str = self.stmts[0].rewrite(context, width - prefix.len(), offset); + let expr_str = try_opt!(expr_str); + let result = format!("{}{{ {} }}", prefix, expr_str); + if result.len() <= width && !result.contains('\n') { + return Some(result); } } @@ -568,25 +570,26 @@ impl Rewrite for ast::Block { impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, _width: usize, offset: Indent) -> Option { let result = match self.node { - ast::StmtKind::Decl(ref decl, _) => { - if let ast::DeclKind::Local(ref local) = decl.node { - local.rewrite(context, context.config.max_width, offset) - } else { - None - } + ast::StmtKind::Local(ref local) => { + local.rewrite(context, context.config.max_width, offset) } - ast::StmtKind::Expr(ref ex, _) | - ast::StmtKind::Semi(ref ex, _) => { + ast::StmtKind::Expr(ref ex) | + ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(self) { ";" } else { "" }; format_expr(ex, - ExprType::Statement, + match self.node { + ast::StmtKind::Expr(_) => ExprType::SubExpression, + ast::StmtKind::Semi(_) => ExprType::Statement, + _ => unreachable!(), + }, context, context.config.max_width - offset.width() - suffix.len(), offset) .map(|s| s + suffix) } - ast::StmtKind::Mac(..) => None, + ast::StmtKind::Mac(..) | + ast::StmtKind::Item(..) => None, }; result.and_then(|res| recover_comment_removed(res, self.span, context, _width, offset)) } @@ -876,11 +879,11 @@ fn single_line_if_else(context: &RewriteContext, } let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); - let if_expr = if_node.expr.as_ref().unwrap(); + let if_expr = &if_node.stmts[0]; let if_str = try_opt!(if_expr.rewrite(context, new_width, Indent::empty())); let new_width = try_opt!(new_width.checked_sub(if_str.len())); - let else_expr = else_node.expr.as_ref().unwrap(); + let else_expr = &else_node.stmts[0]; let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::empty())); // FIXME: this check shouldn't be necessary. Rewrites should either fail @@ -907,18 +910,25 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { // FIXME: incorrectly returns false when comment is contained completely within // the expression. pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.is_empty() && block.expr.is_some() && !block_contains_comment(block, codemap) + block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && + !block_contains_comment(block, codemap) } /// Checks whether a block contains at most one statement or expression, and no comments. pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { - (block.stmts.is_empty() || (block.stmts.len() == 1 && block.expr.is_none())) && - !block_contains_comment(block, codemap) + block.stmts.len() <= 1 && !block_contains_comment(block, codemap) } /// Checks whether a block contains no statements, expressions, or comments. pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.is_empty() && block.expr.is_none() && !block_contains_comment(block, codemap) + block.stmts.is_empty() && !block_contains_comment(block, codemap) +} + +pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::StmtKind::Expr(..) => true, + _ => false, + } } fn is_unsafe_block(block: &ast::Block) -> bool { @@ -1138,14 +1148,20 @@ impl Rewrite for ast::Arm { line_start += offset.width(); } - let body = match **body { - ast::Expr { node: ast::ExprKind::Block(ref block), .. } - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && - context.config.wrap_match_arms => block.expr.as_ref().map(|e| &**e).unwrap(), - ref x => x, + let body = match body.node { + ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && + is_simple_block(block, context.codemap) && + context.config.wrap_match_arms => { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { + expr + } else { + &**body + } + } + _ => &**body, }; - let comma = arm_comma(context.config, self, body); + let comma = arm_comma(&context.config, self, body); let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); // Let's try and get the arm body on the same line as the condition. diff --git a/src/file_lines.rs b/src/file_lines.rs index 61b43375dda..66c937c37c9 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -9,6 +9,7 @@ // except according to those terms. //! This module contains types and functions to support formatting specific line ranges. + use std::{cmp, iter, path, str}; use itertools::Itertools; diff --git a/src/imports.rs b/src/imports.rs index 8ae3b06e28b..ed74d828a9c 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -43,34 +43,30 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { } fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Ordering { - let name_ordering = match a.node.name() { - Some(a_name) => { - match b.node.name() { - Some(b_name) => a_name.name.as_str().cmp(&b_name.name.as_str()), - None => Ordering::Greater, - } + let a_name_str = a.node.name.name.as_str(); + let b_name_str = b.node.name.name.as_str(); + let name_ordering = if a_name_str == "self" { + if b_name_str == "self" { + Ordering::Equal + } else { + Ordering::Less } - None => { - match b.node.name() { - Some(_) => Ordering::Less, - None => Ordering::Equal, - } + } else { + if b_name_str == "self" { + Ordering::Greater + } else { + a_name_str.cmp(&b_name_str) } }; if name_ordering == Ordering::Equal { - match a.node.rename() { + match a.node.rename { Some(a_rename) => { - match b.node.rename() { + match b.node.rename { Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), None => Ordering::Greater, } } - None => { - match b.node.name() { - Some(_) => Ordering::Less, - None => Ordering::Equal, - } - } + None => Ordering::Less, } } else { name_ordering @@ -241,41 +237,23 @@ impl<'a> FmtVisitor<'a> { } fn rewrite_single_use_list(path_str: Option, vpi: &ast::PathListItem) -> String { - let path_item_str = if let ast::PathListItemKind::Ident { name, .. } = vpi.node { - // A name. - match path_str { - Some(path_str) => format!("{}::{}", path_str, name), - None => name.to_string(), - } - } else { - // `self`. - match path_str { - Some(path_str) => path_str, - // This catches the import: use {self}, which is a compiler error, so we just - // leave it alone. - None => "{self}".to_owned(), - } + let path_item_str = match path_str { + Some(ref path_str) if vpi.node.name.to_string() == "self" => path_str.to_owned(), + Some(path_str) => format!("{}::{}", path_str, vpi.node.name), + None => vpi.node.name.to_string(), }; append_alias(path_item_str, vpi) } fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { - let path_item_str = match vpi.node { - ast::PathListItemKind::Ident { name, .. } => name.to_string(), - ast::PathListItemKind::Mod { .. } => "self".to_owned(), - }; - - Some(append_alias(path_item_str, vpi)) + Some(append_alias(vpi.node.name.to_string(), vpi)) } fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { - match vpi.node { - ast::PathListItemKind::Ident { rename: Some(rename), .. } | - ast::PathListItemKind::Mod { rename: Some(rename), .. } => { - format!("{} as {}", path_item_str, rename) - } - _ => path_item_str, + match vpi.node.rename { + Some(rename) => format!("{} as {}", path_item_str, rename), + None => path_item_str, } } diff --git a/src/items.rs b/src/items.rs index d06fc9b2b8c..1071a4017d4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -13,7 +13,7 @@ use Indent; use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, - last_line_width, semicolon_for_expr, format_unsafety, trim_newlines}; + last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; @@ -240,7 +240,7 @@ impl<'a> FmtVisitor<'a> { &sig.decl, &sig.generics, sig.unsafety, - sig.constness, + sig.constness.node, ast::Defaultness::Final, sig.abi, &ast::Visibility::Inherited, @@ -268,18 +268,23 @@ impl<'a> FmtVisitor<'a> { if self.config.fn_single_line && is_simple_block_stmt(block, codemap) { let rewrite = { - if let Some(ref e) = block.expr { - let suffix = if semicolon_for_expr(e) { ";" } else { "" }; - - e.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) - .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span))) - } else if let Some(stmt) = block.stmts.first() { - stmt.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) + if let Some(ref stmt) = block.stmts.first() { + match stmt_expr(stmt) { + Some(e) => { + let suffix = if semicolon_for_expr(e) { ";" } else { "" }; + + e.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent) + .map(|s| s + suffix) + .or_else(|| Some(self.snippet(e.span))) + } + None => { + stmt.rewrite(&self.get_context(), + self.config.max_width - self.block_indent.width(), + self.block_indent) + } + } } else { None } @@ -1153,13 +1158,6 @@ impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { ast::FunctionRetTy::Default(_) => Some(String::new()), - ast::FunctionRetTy::None(_) => { - if width >= 4 { - Some("-> !".to_owned()) - } else { - None - } - } ast::FunctionRetTy::Ty(ref ty) => { let inner_width = try_opt!(width.checked_sub(3)); ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r)) @@ -1259,7 +1257,6 @@ pub fn is_named_arg(arg: &ast::Arg) -> bool { fn span_for_return(ret: &ast::FunctionRetTy) -> Span { match *ret { - ast::FunctionRetTy::None(ref span) | ast::FunctionRetTy::Default(ref span) => span.clone(), ast::FunctionRetTy::Ty(ref ty) => ty.span, } diff --git a/src/lib.rs b/src/lib.rs index dd6a2a5d079..740e0584893 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ extern crate log; extern crate syntex_syntax as syntax; +extern crate syntex_errors as errors; extern crate rustc_serialize; extern crate strings; @@ -27,10 +28,10 @@ extern crate term; extern crate itertools; extern crate multimap; +use errors::{Handler, DiagnosticBuilder}; +use errors::emitter::{ColorConfig, EmitterWriter}; use syntax::ast; use syntax::codemap::{mk_sp, CodeMap, Span}; -use syntax::errors::{Handler, DiagnosticBuilder}; -use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; use strings::string_buffer::StringBuffer; @@ -419,7 +420,7 @@ pub fn format_input(input: Input, let codemap = Rc::new(CodeMap::new()); let tty_handler = - Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, codemap.clone()); + Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())); let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); let main_file = match input { @@ -443,7 +444,7 @@ pub fn format_input(input: Input, } // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None, codemap.clone())); + let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), Some(codemap.clone()))); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); let mut report = FormatReport::new(); diff --git a/src/macros.rs b/src/macros.rs index 5b87f6cc7ec..9c275716ad2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -23,6 +23,7 @@ use syntax::ast; use syntax::parse::token::Token; use syntax::parse::tts_to_parser; use syntax::codemap::{mk_sp, BytePos}; +use syntax::util::ThinVec; use Indent; use codemap::SpanUtils; @@ -159,7 +160,7 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { - rewrite_path(context, true, Some(q_self), path, width, offset) - } PatKind::Range(ref lhs, ref rhs) => { rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset) } @@ -67,7 +64,9 @@ impl Rewrite for Pat { PatKind::Tuple(ref items, dotdot_pos) => { rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, width, offset) } - PatKind::Path(ref path) => rewrite_path(context, true, None, path, width, offset), + PatKind::Path(ref q_self, ref path) => { + rewrite_path(context, true, q_self.as_ref(), path, width, offset) + } PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); rewrite_tuple_pat(pat_vec, diff --git a/src/types.rs b/src/types.rs index fff46b0750d..cb310e13c33 100644 --- a/src/types.rs +++ b/src/types.rs @@ -302,7 +302,6 @@ fn format_function_type<'a, I>(inputs: I, let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); format!(" -> {}", type_str) } - FunctionRetTy::None(..) => " -> !".to_owned(), FunctionRetTy::Default(..) => String::new(), }; @@ -594,9 +593,14 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => { rewrite_bare_fn(bare_fn, self.span, context, width, offset) } + ast::TyKind::Never => Some(String::from("!")), ast::TyKind::Mac(..) | ast::TyKind::Typeof(..) => unreachable!(), ast::TyKind::ImplicitSelf => Some(String::from("")), + ast::TyKind::ImplTrait(..) => { + // FIXME(#1154) Implement impl Trait + Some(String::from("impl TODO")) + } } } } diff --git a/src/utils.rs b/src/utils.rs index 70f16386ec2..49472bb10aa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -13,7 +13,8 @@ use std::cmp::Ordering; use itertools::Itertools; -use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, Path}; +use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMetaItem, + NestedMetaItemKind, Path}; use syntax::codemap::BytePos; use syntax::abi; @@ -101,11 +102,21 @@ pub fn trimmed_last_line_width(s: &str) -> usize { fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { MetaItemKind::Word(ref s) => *s == SKIP_ANNOTATION, - MetaItemKind::List(ref s, ref l) => *s == "cfg_attr" && l.len() == 2 && is_skip(&l[1]), + MetaItemKind::List(ref s, ref l) => { + *s == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + } _ => false, } } +#[inline] +fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { + match meta_item.node { + NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi), + NestedMetaItemKind::Literal(_) => false, + } +} + #[inline] pub fn contains_skip(attrs: &[Attribute]) -> bool { attrs.iter().any(|a| is_skip(&a.node.value)) @@ -129,7 +140,7 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Ret(..) | - ast::ExprKind::Again(..) | + ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => true, _ => false, } @@ -138,7 +149,7 @@ pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { #[inline] pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { match stmt.node { - ast::StmtKind::Semi(ref expr, _) => { + ast::StmtKind::Semi(ref expr) => { match expr.node { ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | @@ -152,6 +163,27 @@ pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { } } +#[inline] +pub fn stmt_block(stmt: &ast::Stmt) -> Option<&ast::Block> { + match stmt.node { + ast::StmtKind::Expr(ref expr) => { + match expr.node { + ast::ExprKind::Block(ref inner) => Some(inner), + _ => None, + } + } + _ => None, + } +} + +#[inline] +pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { + match stmt.node { + ast::StmtKind::Expr(ref expr) => Some(expr), + _ => None, + } +} + #[inline] pub fn trim_newlines(input: &str) -> &str { match input.find(|c| c != '\n' && c != '\r') { @@ -330,9 +362,8 @@ pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { ast::ExprKind::Field(ref e, _) | ast::ExprKind::TupField(ref e, _) | ast::ExprKind::Index(ref e, _) | - ast::ExprKind::Range(Some(ref e), _, _) => left_most_sub_expr(e), - // FIXME needs Try in Syntex - // ast::ExprKind::Try(ref f) => left_most_sub_expr(e), + ast::ExprKind::Range(Some(ref e), _, _) | + ast::ExprKind::Try(ref e) => left_most_sub_expr(e), _ => e, } } diff --git a/src/visitor.rs b/src/visitor.rs index 237866ed9ec..d37bf760a26 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -52,17 +52,10 @@ impl<'a> FmtVisitor<'a> { } match stmt.node { - ast::StmtKind::Decl(ref decl, _) => { - if let ast::DeclKind::Item(ref item) = decl.node { - self.visit_item(item); - } else { - let rewrite = stmt.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent); - - self.push_rewrite(stmt.span, rewrite); - } + ast::StmtKind::Item(ref item) => { + self.visit_item(item); } + ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let rewrite = stmt.rewrite(&self.get_context(), @@ -71,7 +64,8 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(stmt.span, rewrite); } - ast::StmtKind::Mac(ref mac, _macro_style, _) => { + ast::StmtKind::Mac(ref mac) => { + let (ref mac, _macro_style, _) = **mac; self.format_missing_with_indent(source!(self, stmt.span).lo); self.visit_mac(mac, None); } @@ -96,18 +90,11 @@ impl<'a> FmtVisitor<'a> { self.visit_stmt(stmt) } - if let Some(ref e) = b.expr { - self.format_missing_with_indent(source!(self, e.span).lo); - let rewrite = e.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) - .unwrap_or_else(|| self.snippet(e.span)); - - self.buffer.push_str(&rewrite); - self.last_pos = source!(self, e.span).hi; - - if utils::semicolon_for_expr(e) { - self.buffer.push_str(";"); + if !b.stmts.is_empty() { + if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { + if utils::semicolon_for_expr(expr) { + self.buffer.push_str(";"); + } } } @@ -150,7 +137,7 @@ impl<'a> FmtVisitor<'a> { fd, generics, unsafety, - constness, + constness.node, defaultness, abi, vis, @@ -163,7 +150,7 @@ impl<'a> FmtVisitor<'a> { fd, &sig.generics, sig.unsafety, - sig.constness, + sig.constness.node, defaultness, sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), @@ -347,6 +334,9 @@ impl<'a> FmtVisitor<'a> { item.span); self.push_rewrite(item.span, rewrite); } + ast::ItemKind::Union(..) => { + // FIXME(#1157): format union definitions. + } } } @@ -387,6 +377,9 @@ impl<'a> FmtVisitor<'a> { self.block_indent); self.push_rewrite(ti.span, rewrite); } + ast::TraitItemKind::Macro(..) => { + // FIXME(#1158) Macros in trait item position + } } } diff --git a/tests/source/file-lines-1.rs b/tests/source/file-lines-1.rs index 43c18d8f46f..fc13a9edd17 100644 --- a/tests/source/file-lines-1.rs +++ b/tests/source/file-lines-1.rs @@ -17,7 +17,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/source/file-lines-2.rs b/tests/source/file-lines-2.rs index 6f8e9e6db3a..7812c752239 100644 --- a/tests/source/file-lines-2.rs +++ b/tests/source/file-lines-2.rs @@ -17,7 +17,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/source/file-lines-3.rs b/tests/source/file-lines-3.rs index 73d482695d6..29a0e6bb20f 100644 --- a/tests/source/file-lines-3.rs +++ b/tests/source/file-lines-3.rs @@ -17,7 +17,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/source/file-lines-4.rs b/tests/source/file-lines-4.rs index 381f021515f..c6c0a5f82a0 100644 --- a/tests/source/file-lines-4.rs +++ b/tests/source/file-lines-4.rs @@ -18,7 +18,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/target/file-lines-1.rs b/tests/target/file-lines-1.rs index 5b8478e0303..250b25e6ea3 100644 --- a/tests/target/file-lines-1.rs +++ b/tests/target/file-lines-1.rs @@ -18,7 +18,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/target/file-lines-2.rs b/tests/target/file-lines-2.rs index db4902d49b7..c889fc3fd66 100644 --- a/tests/target/file-lines-2.rs +++ b/tests/target/file-lines-2.rs @@ -12,7 +12,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/target/file-lines-3.rs b/tests/target/file-lines-3.rs index 19359b2ddf9..d8096dccd67 100644 --- a/tests/target/file-lines-3.rs +++ b/tests/target/file-lines-3.rs @@ -13,7 +13,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), diff --git a/tests/target/file-lines-4.rs b/tests/target/file-lines-4.rs index 381f021515f..c6c0a5f82a0 100644 --- a/tests/target/file-lines-4.rs +++ b/tests/target/file-lines-4.rs @@ -18,7 +18,6 @@ fn floaters() { { match x { PushParam => { - // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), -- cgit 1.4.1-3-g733a5 From efd3e5c0914f0c8d401a504be4116bf947296218 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 17 Sep 2016 01:44:51 +0200 Subject: Add three new options for spaces --- src/config.rs | 5 ++++ src/expr.rs | 30 +++++++++++++++++----- src/items.rs | 30 +++++++++++++++++----- src/types.rs | 18 ++++++++++--- .../space-not-after-type-annotation-colon.rs | 14 ++++++++++ tests/source/space-not-before-bound-colon.rs | 5 ++++ tests/source/spaces-around-ranges.rs | 15 +++++++++++ .../space-not-after-type-annotation-colon.rs | 14 ++++++++++ tests/target/space-not-before-bound-colon.rs | 5 ++++ tests/target/spaces-around-ranges.rs | 15 +++++++++++ 10 files changed, 134 insertions(+), 17 deletions(-) create mode 100644 tests/source/space-not-after-type-annotation-colon.rs create mode 100644 tests/source/space-not-before-bound-colon.rs create mode 100644 tests/source/spaces-around-ranges.rs create mode 100644 tests/target/space-not-after-type-annotation-colon.rs create mode 100644 tests/target/space-not-before-bound-colon.rs create mode 100644 tests/target/spaces-around-ranges.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 71adc24c09f..f93a6e115a5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -410,7 +410,12 @@ create_config! { block indented. -1 means never use block indent."; space_before_type_annotation: bool, false, "Leave a space before the colon in a type annotation"; + space_after_type_annotation_colon: bool, true, + "Leave a space after the colon in a type annotation"; space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound"; + space_after_bound_colon: bool, true, + "Leave a space after the colon in a trait or lifetime bound"; + spaces_around_ranges: bool, false, "Put spaces around the .. and ... range operators"; use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; diff --git a/src/expr.rs b/src/expr.rs index bece2ef91fe..11e2ca88145 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -219,13 +219,28 @@ fn format_expr(expr: &ast::Expr, match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { (Some(ref lhs), Some(ref rhs)) => { - rewrite_pair(&**lhs, &**rhs, "", delim, "", context, width, offset) + let sp_delim = if context.config.spaces_around_ranges { + format!(" {} ", delim) + } else { + delim.into() + }; + rewrite_pair(&**lhs, &**rhs, "", &sp_delim, "", context, width, offset) } (None, Some(ref rhs)) => { - rewrite_unary_prefix(context, delim, &**rhs, width, offset) + let sp_delim = if context.config.spaces_around_ranges { + format!("{} ", delim) + } else { + delim.into() + }; + rewrite_unary_prefix(context, &sp_delim, &**rhs, width, offset) } (Some(ref lhs), None) => { - rewrite_unary_suffix(context, delim, &**lhs, width, offset) + let sp_delim = if context.config.spaces_around_ranges { + format!(" {}", delim) + } else { + delim.into() + }; + rewrite_unary_suffix(context, &sp_delim, &**lhs, width, offset) } (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), } @@ -1672,10 +1687,11 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } pub fn type_annotation_separator(config: &Config) -> &str { - if config.space_before_type_annotation { - " : " - } else { - ": " + match (config.space_before_type_annotation, config.space_after_type_annotation_colon) { + (true, true) => " : ", + (true, false) => " :", + (false, true) => ": ", + (false, false) => ":", } } diff --git a/src/items.rs b/src/items.rs index 1071a4017d4..b381ba8b7b2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1049,12 +1049,17 @@ pub fn rewrite_type_alias(context: &RewriteContext, Some(result) } -fn type_annotation_spacing(config: &Config) -> &str { - if config.space_before_type_annotation { +fn type_annotation_spacing(config: &Config) -> (&str, &str) { + (if config.space_before_type_annotation { " " } else { "" - } + }, + if config.space_after_type_annotation_colon { + " " + } else { + "" + }) } impl Rewrite for ast::StructField { @@ -1075,7 +1080,14 @@ impl Rewrite for ast::StructField { let type_annotation_spacing = type_annotation_spacing(context.config); let result = match name { - Some(name) => format!("{}{}{}{}: ", attr_str, vis, name, type_annotation_spacing), + Some(name) => { + format!("{}{}{}{}:{}", + attr_str, + vis, + name, + type_annotation_spacing.0, + type_annotation_spacing.1) + } None => format!("{}{}", attr_str, vis), }; @@ -1095,12 +1107,13 @@ pub fn rewrite_static(prefix: &str, context: &RewriteContext) -> Option { let type_annotation_spacing = type_annotation_spacing(context.config); - let prefix = format!("{}{} {}{}{}: ", + let prefix = format!("{}{} {}{}{}:{}", format_visibility(vis), prefix, format_mutability(mutability), ident, - type_annotation_spacing); + type_annotation_spacing.0, + type_annotation_spacing.1); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, context.config.max_width - context.block_indent.width() - @@ -1175,7 +1188,10 @@ impl Rewrite for ast::Arg { if context.config.space_before_type_annotation { result.push_str(" "); } - result.push_str(": "); + result.push_str(":"); + if context.config.space_after_type_annotation_colon { + result.push_str(" "); + } let max_width = try_opt!(width.checked_sub(result.len())); let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len())); result.push_str(&ty_str); diff --git a/src/types.rs b/src/types.rs index cb310e13c33..a718750db95 100644 --- a/src/types.rs +++ b/src/types.rs @@ -405,12 +405,21 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, let appendix: Vec<_> = try_opt!(bounds.into_iter() .map(|b| b.rewrite(context, width, offset)) .collect()); - let bound_spacing = if context.config.space_before_bound { + let bound_spacing_before = if context.config.space_before_bound { " " } else { "" }; - let result = format!("{}{}: {}", result, bound_spacing, appendix.join(" + ")); + let bound_spacing_after = if context.config.space_after_bound_colon { + " " + } else { + "" + }; + let result = format!("{}{}:{}{}", + result, + bound_spacing_before, + bound_spacing_after, + appendix.join(" + ")); wrap_str(result, context.config.max_width, width, offset) } } @@ -456,7 +465,10 @@ impl Rewrite for ast::TyParam { if context.config.space_before_bound { result.push_str(" "); } - result.push_str(": "); + result.push_str(":"); + if context.config.space_after_bound_colon { + result.push_str(" "); + } let bounds: String = try_opt!(self.bounds .iter() diff --git a/tests/source/space-not-after-type-annotation-colon.rs b/tests/source/space-not-after-type-annotation-colon.rs new file mode 100644 index 00000000000..86f829c8353 --- /dev/null +++ b/tests/source/space-not-after-type-annotation-colon.rs @@ -0,0 +1,14 @@ +// rustfmt-space_before_type_annotation: true +// rustfmt-space_after_type_annotation_colon: false + +static staticVar: i32 = 42; +const constVar: i32 = 42; +fn foo(paramVar: i32) { + let localVar: i32 = 42; +} +struct S { + fieldVar: i32, +} +fn f() { + S { fieldVar: 42 } +} diff --git a/tests/source/space-not-before-bound-colon.rs b/tests/source/space-not-before-bound-colon.rs new file mode 100644 index 00000000000..4ec569f7902 --- /dev/null +++ b/tests/source/space-not-before-bound-colon.rs @@ -0,0 +1,5 @@ +// rustfmt-space_before_bound: true +// rustfmt-space_after_bound_colon: false + +trait Trait {} +fn f<'a, 'b: 'a, T: Trait>() {} diff --git a/tests/source/spaces-around-ranges.rs b/tests/source/spaces-around-ranges.rs new file mode 100644 index 00000000000..188f8f9074f --- /dev/null +++ b/tests/source/spaces-around-ranges.rs @@ -0,0 +1,15 @@ +// rustfmt-spaces_around_ranges: true + +fn bar(v: &[u8]) {} + +fn foo() { + let a = vec![0; 20]; + for j in 0...20 { + for i in 0..3 { + bar(a[i..j]); + bar(a[i..]); + bar(a[..j]); + bar(a[...(j + 1)]); + } + } +} diff --git a/tests/target/space-not-after-type-annotation-colon.rs b/tests/target/space-not-after-type-annotation-colon.rs new file mode 100644 index 00000000000..3bdfa57fb73 --- /dev/null +++ b/tests/target/space-not-after-type-annotation-colon.rs @@ -0,0 +1,14 @@ +// rustfmt-space_before_type_annotation: true +// rustfmt-space_after_type_annotation_colon: false + +static staticVar :i32 = 42; +const constVar :i32 = 42; +fn foo(paramVar :i32) { + let localVar :i32 = 42; +} +struct S { + fieldVar :i32, +} +fn f() { + S { fieldVar :42 } +} diff --git a/tests/target/space-not-before-bound-colon.rs b/tests/target/space-not-before-bound-colon.rs new file mode 100644 index 00000000000..ef48eca1114 --- /dev/null +++ b/tests/target/space-not-before-bound-colon.rs @@ -0,0 +1,5 @@ +// rustfmt-space_before_bound: true +// rustfmt-space_after_bound_colon: false + +trait Trait {} +fn f<'a, 'b :'a, T :Trait>() {} diff --git a/tests/target/spaces-around-ranges.rs b/tests/target/spaces-around-ranges.rs new file mode 100644 index 00000000000..7b280f1439d --- /dev/null +++ b/tests/target/spaces-around-ranges.rs @@ -0,0 +1,15 @@ +// rustfmt-spaces_around_ranges: true + +fn bar(v: &[u8]) {} + +fn foo() { + let a = vec![0; 20]; + for j in 0 ... 20 { + for i in 0 .. 3 { + bar(a[i .. j]); + bar(a[i ..]); + bar(a[.. j]); + bar(a[... (j + 1)]); + } + } +} -- cgit 1.4.1-3-g733a5 From c6243c950ee3376f562cc2dd08a3d31c9c3818b2 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 17 Sep 2016 03:20:00 +0200 Subject: Improve comment rewriting with normalize_comments == false Only change multiline comments of the form ```rust /* * Text */ ``` while not affecting comments of the form ```rust /* Text */ ``` when normalize_comments is off. In the first case, we have a known character we can align against, while we don't have one in the second case. Before, we have converted the second form into the first, but this is against the spirit of normalize_comments being turned off. Fixes #956 --- src/comment.rs | 10 ++++++++++ tests/source/comment4.rs | 12 ++++++++++++ tests/target/comment4.rs | 12 ++++++++++++ 3 files changed, 34 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 979d3bef90e..5a525f1bb23 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -71,6 +71,16 @@ pub fn rewrite_comment(orig: &str, let indent_str = offset.to_string(config); let line_breaks = s.chars().filter(|&c| c == '\n').count(); + let num_bare_lines = s.lines() + .enumerate() + .map(|(_, line)| line.trim()) + .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) + .count(); + + if num_bare_lines > 0 && !config.normalize_comments { + return Some(orig.to_owned()); + } + let lines = s.lines() .enumerate() .map(|(i, mut line)| { diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index 81754f93c4c..0ed18ca8da1 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -33,3 +33,15 @@ fn test() { /// test123 fn doc_comment() { } + +/* +Regression test for issue #956 + +(some very important text) +*/ + +/* +fn debug_function() { + println!("hello"); +} +// */ diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index c4d25ca1143..910bade6c88 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -32,3 +32,15 @@ fn test() { /// test123 fn doc_comment() {} + +/* +Regression test for issue #956 + +(some very important text) +*/ + +/* +fn debug_function() { + println!("hello"); +} +// */ -- cgit 1.4.1-3-g733a5 From 079f39d07fd75e625a56c8a417bdc946cac389a6 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 10 Sep 2016 14:02:05 +0900 Subject: Fix #550: `if` nested in tuple is indented oddly --- src/comment.rs | 8 ++++---- src/expr.rs | 9 +++++++-- tests/source/tuple.rs | 34 ++++++++++++++++++++++++++++++++++ tests/target/tuple.rs | 10 ++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/source/tuple.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 979d3bef90e..e67a438cbcc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -425,10 +425,10 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { None => &self.slice[start_idx..], }; Some((if kind.is_comment() { - CodeCharKind::Comment - } else { - CodeCharKind::Normal - }, + CodeCharKind::Comment + } else { + CodeCharKind::Normal + }, start_idx, slice)) } diff --git a/src/expr.rs b/src/expr.rs index bece2ef91fe..a00baf21a84 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1716,11 +1716,16 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, ::Target: Rewrite + Spanned + 'a { let indent = offset + 1; + let aligned = RewriteContext { block_indent: indent, ..context.clone() }; + // In case of length 1, need a trailing comma if items.len() == 1 { // 3 = "(" + ",)" let budget = try_opt!(width.checked_sub(3)); - return items.next().unwrap().rewrite(context, budget, indent).map(|s| format!("({},)", s)); + return items.next() + .unwrap() + .rewrite(&aligned, budget, indent) + .map(|s| format!("({},)", s)); } let list_lo = context.codemap.span_after(span, "("); @@ -1733,7 +1738,7 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, let inner_width = try_opt!(context.config .max_width .checked_sub(indent.width() + 1)); - item.rewrite(context, inner_width, indent) + item.rewrite(&aligned, inner_width, indent) }, list_lo, span.hi - BytePos(1)); diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs new file mode 100644 index 00000000000..b28e83d2f08 --- /dev/null +++ b/tests/source/tuple.rs @@ -0,0 +1,34 @@ +// Test tuple litterals + +fn foo() { + let a = (a, a, a, a, a); + let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); + let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa); + let a = (a,); + + let b = (// This is a comment + b, // Comment + b /* Trailing comment */); +} + +fn a() { + ((aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa),) +} + +fn b() { + ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + bbbbbbbbbbbbbbbbbb) +} + +fn issue550() { + self.visitor.visit_volume(self.level.sector_id(sector), (floor_y, + if is_sky_flat(ceil_tex) {from_wad_height(self.height_range.1)} else {ceil_y})); +} diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index a5bcc7f701a..2d1d0b808d7 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -27,3 +27,13 @@ fn b() { ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), bbbbbbbbbbbbbbbbbb) } + +fn issue550() { + self.visitor.visit_volume(self.level.sector_id(sector), + (floor_y, + if is_sky_flat(ceil_tex) { + from_wad_height(self.height_range.1) + } else { + ceil_y + })); +} -- cgit 1.4.1-3-g733a5 From b6bffa65961c6e01cf6a24288a93c6a475980fdf Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 9 Sep 2016 23:20:16 +0900 Subject: Prevent line breaking at `=` or `in` after trivial patterns --- src/expr.rs | 22 +++++++++++++++------- src/items.rs | 4 ++-- tests/source/expr.rs | 13 +++++++++++++ tests/target/expr.rs | 19 ++++++++++++++++--- tests/target/loop.rs | 4 ++-- 5 files changed, 48 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bece2ef91fe..857231e3744 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1307,20 +1307,28 @@ fn rewrite_pat_expr(context: &RewriteContext, offset + extra_offset + spacer.len()); if let Some(expr_string) = expr_rewrite { - result.push_str(spacer); - result.push_str(&expr_string); - return Some(result); + let pat_simple = + pat.and_then(|p| p.rewrite(context, context.config.max_width, Indent::empty())) + .map(|s| pat_is_simple(&s)); + + if pat.is_none() || pat_simple.unwrap_or(false) || !expr_string.contains('\n') { + result.push_str(spacer); + result.push_str(&expr_string); + return Some(result); + } } } + let nested = context.nested_context(); + // The expression won't fit on the current line, jump to next. result.push('\n'); - result.push_str(&pat_offset.to_string(context.config)); + result.push_str(&nested.block_indent.to_string(context.config)); let expr_rewrite = - expr.rewrite(context, - try_opt!(context.config.max_width.checked_sub(pat_offset.width())), - pat_offset); + expr.rewrite(&nested, + try_opt!(context.config.max_width.checked_sub(nested.block_indent.width())), + nested.block_indent); result.push_str(&try_opt!(expr_rewrite)); Some(result) diff --git a/src/items.rs b/src/items.rs index 1071a4017d4..7bb775c77d3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -568,7 +568,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, split_at_for: bool) -> Option { if let ast::ItemKind::Impl(unsafety, polarity, ref generics, ref trait_ref, ref self_ty, _) = - item.node { + item.node { let mut result = String::new(); result.push_str(&*format_visibility(&item.vis)); @@ -670,7 +670,7 @@ pub fn format_struct(context: &RewriteContext, pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { if let ast::ItemKind::Trait(unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node { + item.node { let mut result = String::new(); let header = format!("{}{}trait {}", format_visibility(&item.vis), diff --git a/tests/source/expr.rs b/tests/source/expr.rs index cb3c59b10ce..f9a0251910c 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -285,3 +285,16 @@ fn complex_if_else() { yo(); } } + +fn issue1106() { + { + if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map.expect_item(enum_node_id).node { + } + } + + for entry in + WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) { + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 12ac778be69..48fa14d8a54 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -55,8 +55,8 @@ fn foo() -> bool { } if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + - 2222 {} + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = + 1111 + 2222 {} if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { @@ -283,10 +283,23 @@ fn complex_if_else() { } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { yo(); } else if let Some(x) = - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { ha(); } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { yo(); } } + +fn issue1106() { + { + if let hir::ItemEnum(ref enum_def, ref generics) = + self.ast_map.expect_item(enum_node_id).node { + } + } + + for entry in WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) { + } +} diff --git a/tests/target/loop.rs b/tests/target/loop.rs index ea84c00c22b..4cf18f0110a 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -21,8 +21,8 @@ fn main() { while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { } - 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, - arg2) { + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in + some_iter(arg1, arg2) { // do smth } -- cgit 1.4.1-3-g733a5 From 114a3e287a2a5fd9426e9c2cfb6b7574a4b2faa4 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Mon, 19 Sep 2016 11:48:56 +0900 Subject: Fix self test --- src/items.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index b381ba8b7b2..8e6845c64b6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1051,15 +1051,15 @@ pub fn rewrite_type_alias(context: &RewriteContext, fn type_annotation_spacing(config: &Config) -> (&str, &str) { (if config.space_before_type_annotation { - " " - } else { - "" - }, + " " + } else { + "" + }, if config.space_after_type_annotation_colon { - " " - } else { - "" - }) + " " + } else { + "" + }) } impl Rewrite for ast::StructField { -- cgit 1.4.1-3-g733a5 From 2dfa96bc9aaf02bcf69999e52ce4a229638504aa Mon Sep 17 00:00:00 2001 From: sinkuu Date: Tue, 20 Sep 2016 14:01:35 +0900 Subject: Fix #775 rewrite_tuple referring config.max_width where given width should be used --- src/expr.rs | 13 ++++--------- tests/source/tuple.rs | 10 ++++++++++ tests/target/tuple.rs | 11 +++++++++++ 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 55f8fa8ba92..ce1eb5dc053 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -303,16 +303,16 @@ pub fn rewrite_array<'a, I>(expr_iter: I, -> Option where I: Iterator { - // 2 for brackets; + // 1 = [ let offset = offset + 1; let inner_context = &RewriteContext { block_indent: offset, ..*context }; + // 2 for brackets let max_item_width = try_opt!(width.checked_sub(2)); let items = itemize_list(context.codemap, expr_iter, "]", |item| item.span.lo, |item| item.span.hi, - // 1 = [ |item| item.rewrite(inner_context, max_item_width, offset), span.lo, span.hi) @@ -1753,20 +1753,15 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, } let list_lo = context.codemap.span_after(span, "("); + let budget = try_opt!(width.checked_sub(2)); let items = itemize_list(context.codemap, items, ")", |item| item.span().lo, |item| item.span().hi, - |item| { - let inner_width = try_opt!(context.config - .max_width - .checked_sub(indent.width() + 1)); - item.rewrite(&aligned, inner_width, indent) - }, + |item| item.rewrite(&aligned, budget, indent), list_lo, span.hi - BytePos(1)); - let budget = try_opt!(width.checked_sub(2)); let list_str = try_opt!(format_item_list(items, budget, indent, context.config)); Some(format!("({})", list_str)) diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs index b28e83d2f08..d47777734bb 100644 --- a/tests/source/tuple.rs +++ b/tests/source/tuple.rs @@ -32,3 +32,13 @@ fn issue550() { self.visitor.visit_volume(self.level.sector_id(sector), (floor_y, if is_sky_flat(ceil_tex) {from_wad_height(self.height_range.1)} else {ceil_y})); } + +fn issue775() { + if indent { + let a = mk_object(&[("a".to_string(), Boolean(true)), + ("b".to_string(), + Array(vec![mk_object(&[("c".to_string(), + String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))])]))]); + } +} diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 2d1d0b808d7..2d3b52da72a 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -37,3 +37,14 @@ fn issue550() { ceil_y })); } + +fn issue775() { + if indent { + let a = mk_object(&[("a".to_string(), Boolean(true)), + ("b".to_string(), + Array(vec![mk_object(&[("c".to_string(), + String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), + String("".to_string()))])]))]); + } +} -- cgit 1.4.1-3-g733a5 From 77ceba2bc033a230f77d6ac96a277191ca73fff2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 27 Sep 2016 17:24:58 +1300 Subject: Write to the supplied buffer if one is supplied to format_input --- src/filemap.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 5560e9aee85..ea45defe55c 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -14,7 +14,7 @@ use strings::string_buffer::StringBuffer; use std::fs::{self, File}; -use std::io::{self, Write, Read, stdout, BufWriter}; +use std::io::{self, Write, Read, sBufWriter}; use config::{NewlineStyle, Config, WriteMode}; use rustfmt_diff::{make_diff, print_diff, Mismatch}; @@ -133,15 +133,11 @@ pub fn write_file(text: &StringBuffer, try!(write_system_newlines(file, text, config)); } WriteMode::Plain => { - let stdout = stdout(); - let stdout = stdout.lock(); - try!(write_system_newlines(stdout, text, config)); + try!(write_system_newlines(out, text, config)); } WriteMode::Display | WriteMode::Coverage => { println!("{}:\n", filename); - let stdout = stdout(); - let stdout = stdout.lock(); - try!(write_system_newlines(stdout, text, config)); + try!(write_system_newlines(out, text, config)); } WriteMode::Diff => { if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { -- cgit 1.4.1-3-g733a5 From 8a9dfc5ede0ac5b7574f7438e946b03ce1df83ba Mon Sep 17 00:00:00 2001 From: nokaa Date: Tue, 27 Sep 2016 12:38:17 -0500 Subject: Fix broken import --- src/filemap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index ea45defe55c..6c15d659d54 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -14,7 +14,7 @@ use strings::string_buffer::StringBuffer; use std::fs::{self, File}; -use std::io::{self, Write, Read, sBufWriter}; +use std::io::{self, Write, Read, BufWriter}; use config::{NewlineStyle, Config, WriteMode}; use rustfmt_diff::{make_diff, print_diff, Mismatch}; -- cgit 1.4.1-3-g733a5 From b8f7ec3dcc8a08c835eba577b64efa92913ad429 Mon Sep 17 00:00:00 2001 From: Florian Gilcher Date: Thu, 29 Sep 2016 21:34:46 +0200 Subject: Add custom comments (#1179) * Add custom comments This allows users to use custom comments such as ``` //@ this is a custom comment //@ with multiple lines ``` without having them destroyed by rustfmt. * Fix issues with empty lines * Check non-whitespace right after custom comments --- src/comment.rs | 24 ++++++++++++++++++++++++ tests/source/comment5.rs | 7 +++++++ tests/target/comment5.rs | 8 ++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/source/comment5.rs create mode 100644 tests/target/comment5.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4ced667ef78..23d7dab3de9 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -20,6 +20,18 @@ use rewrite::RewriteContext; use string::{StringFormat, rewrite_string}; use utils::wrap_str; +fn is_custom_comment(comment: &str) -> bool { + if !comment.starts_with("//") { + false + } else { + if let Some(c) = comment.chars().nth(2) { + !c.is_alphanumeric() && !c.is_whitespace() + } else { + false + } + } +} + pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, @@ -51,6 +63,12 @@ pub fn rewrite_comment(orig: &str, ("/// ", "", "/// ") } else if orig.starts_with("//!") || orig.starts_with("/*!") { ("//! ", "", "//! ") + } else if is_custom_comment(orig) { + if orig.chars().nth(3) == Some(' ') { + (&orig[0..4], "", &orig[0..4]) + } else { + (&orig[0..3], "", &orig[0..3]) + } } else { ("// ", "", "// ") }; @@ -138,6 +156,12 @@ fn left_trim_comment_line(line: &str) -> &str { if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || line.starts_with("/** ") { &line[4..] + } else if is_custom_comment(line) { + if line.len() > 3 && line.chars().nth(3) == Some(' ') { + &line[4..] + } else { + &line[3..] + } } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || line.starts_with("///") || line.starts_with("** ") || line.starts_with("/*!") || diff --git a/tests/source/comment5.rs b/tests/source/comment5.rs new file mode 100644 index 00000000000..87a26f353a7 --- /dev/null +++ b/tests/source/comment5.rs @@ -0,0 +1,7 @@ +// rustfmt-wrap_comments: true + +//@ special comment +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ +//@foo +fn test() {} \ No newline at end of file diff --git a/tests/target/comment5.rs b/tests/target/comment5.rs new file mode 100644 index 00000000000..7006b35efed --- /dev/null +++ b/tests/target/comment5.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: true + +//@ special comment +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam +//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ +//@ foo +fn test() {} -- cgit 1.4.1-3-g733a5 From c4a7a7108e155dfb3ada7b0e7def78962f5d6263 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Mon, 3 Oct 2016 14:11:49 +1000 Subject: Preserve macro formatting if we can't rewrite it --- src/macros.rs | 6 +----- src/visitor.rs | 9 +-------- tests/source/macros.rs | 5 +++++ tests/target/macros.rs | 5 +++++ 4 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 9c275716ad2..dd301ad9de7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,6 @@ use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use expr::{rewrite_call, rewrite_array}; use comment::{FindUncommented, contains_comment}; -use utils::wrap_str; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; @@ -141,10 +140,7 @@ pub fn rewrite_macro(mac: &ast::Mac, } MacroStyle::Braces => { // Skip macro invocations with braces, for now. - wrap_str(context.snippet(mac.span), - context.config.max_width, - width, - offset) + None } } } diff --git a/src/visitor.rs b/src/visitor.rs index b0d5a91f1d8..f05fcefdfe8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -66,7 +66,6 @@ impl<'a> FmtVisitor<'a> { } ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, _) = **mac; - self.format_missing_with_indent(source!(self, stmt.span).lo); self.visit_mac(mac, None); } } @@ -281,7 +280,6 @@ impl<'a> FmtVisitor<'a> { self.format_mod(module, &item.vis, item.span, item.ident); } ast::ItemKind::Mac(ref mac) => { - self.format_missing_with_indent(source!(self, item.span).lo); self.visit_mac(mac, Some(item.ident)); } ast::ItemKind::ForeignMod(ref foreign_mod) => { @@ -418,7 +416,6 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { - self.format_missing_with_indent(source!(self, ii.span).lo); self.visit_mac(mac, Some(ii.ident)); } } @@ -428,11 +425,7 @@ impl<'a> FmtVisitor<'a> { // 1 = ; let width = self.config.max_width - self.block_indent.width() - 1; let rewrite = rewrite_macro(mac, ident, &self.get_context(), width, self.block_indent); - - if let Some(res) = rewrite { - self.buffer.push_str(&res); - self.last_pos = source!(self, mac.span).hi; - } + self.push_rewrite(mac.span, rewrite); } fn push_rewrite(&mut self, span: Span, rewrite: Option) { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index d04c204186c..ca28d5c625b 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -50,6 +50,11 @@ fn main() { some_macro!{ // comment }; + + some_macro!( + // comment + not function like + ); } impl X { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 902dd2e4d9a..79a42524939 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -53,6 +53,11 @@ fn main() { some_macro!{ // comment }; + + some_macro!( + // comment + not function like + ); } impl X { -- cgit 1.4.1-3-g733a5 From 7be202fa3c53ab1d4e208245653fde033ec0131c Mon Sep 17 00:00:00 2001 From: Mikko Rantanen Date: Thu, 13 Oct 2016 04:34:08 +0300 Subject: Add support for spaces_within_parens config (#1187) * Add support for spaces_within_parens config * Changes based on review comments --- src/config.rs | 1 + src/expr.rs | 25 ++++++++++++++++---- src/items.rs | 19 +++++++++++++++ src/patterns.rs | 14 +++++++++-- src/types.rs | 13 ++++++++-- tests/source/spaces-within-parens.rs | 46 ++++++++++++++++++++++++++++++++++++ tests/target/spaces-within-parens.rs | 46 ++++++++++++++++++++++++++++++++++++ 7 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 tests/source/spaces-within-parens.rs create mode 100644 tests/target/spaces-within-parens.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index f93a6e115a5..ad14f81a819 100644 --- a/src/config.rs +++ b/src/config.rs @@ -416,6 +416,7 @@ create_config! { space_after_bound_colon: bool, true, "Leave a space after the colon in a trait or lifetime bound"; spaces_around_ranges: bool, false, "Put spaces around the .. and ... range operators"; + spaces_within_parens: bool, false, "Put spaces within non-empty parentheses"; use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; diff --git a/src/expr.rs b/src/expr.rs index ce1eb5dc053..e1d74a3cc79 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1536,7 +1536,11 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Less), }; - Ok(format!("{}({})", callee_str, list_str)) + Ok(if context.config.spaces_within_parens && list_str.len() > 0 { + format!("{}( {} )", callee_str, list_str) + } else { + format!("{}({})", callee_str, list_str) + }) } fn rewrite_paren(context: &RewriteContext, @@ -1549,7 +1553,12 @@ fn rewrite_paren(context: &RewriteContext, // paren on the same line as the subexpr. let subexpr_str = subexpr.rewrite(context, try_opt!(width.checked_sub(2)), offset + 1); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - subexpr_str.map(|s| format!("({})", s)) + + subexpr_str.map(|s| if context.config.spaces_within_parens && s.len() > 0 { + format!("( {} )", s) + } else { + format!("({})", s) + }) } fn rewrite_struct_lit<'a>(context: &RewriteContext, @@ -1749,7 +1758,11 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, return items.next() .unwrap() .rewrite(&aligned, budget, indent) - .map(|s| format!("({},)", s)); + .map(|s| if context.config.spaces_within_parens { + format!("( {}, )", s) + } else { + format!("({},)", s) + }); } let list_lo = context.codemap.span_after(span, "("); @@ -1764,7 +1777,11 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, span.hi - BytePos(1)); let list_str = try_opt!(format_item_list(items, budget, indent, context.config)); - Some(format!("({})", list_str)) + if context.config.spaces_within_parens && list_str.len() > 0 { + Some(format!("( {} )", list_str)) + } else { + Some(format!("({})", list_str)) + } } fn rewrite_binary_op(context: &RewriteContext, diff --git a/src/items.rs b/src/items.rs index 7e18f0a2f4d..c3e58cba835 100644 --- a/src/items.rs +++ b/src/items.rs @@ -961,7 +961,17 @@ fn format_tuple_struct(context: &RewriteContext, context.codemap.span_after(span, "("), span.hi); let body = try_opt!(format_item_list(items, item_budget, item_indent, context.config)); + + if context.config.spaces_within_parens && body.len() > 0 { + result.push(' '); + } + result.push_str(&body); + + if context.config.spaces_within_parens && body.len() > 0 { + result.push(' '); + } + result.push(')'); if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && @@ -1386,12 +1396,18 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(&arg_indent.to_string(context.config)); arg_indent = arg_indent + 1; // extra space for `(` result.push('('); + if context.config.spaces_within_parens && fd.inputs.len() > 0 { + result.push(' ') + } } else { result.push_str("(\n"); result.push_str(&arg_indent.to_string(context.config)); } } else { result.push('('); + if context.config.spaces_within_parens && fd.inputs.len() > 0 { + result.push(' ') + } } if multi_line_ret_str { @@ -1432,6 +1448,9 @@ fn rewrite_fn_base(context: &RewriteContext, result.push(')'); } else { result.push_str(&arg_str); + if context.config.spaces_within_parens && fd.inputs.len() > 0 { + result.push(' ') + } result.push(')'); } diff --git a/src/patterns.rs b/src/patterns.rs index 1aaa28b853a..149844cd196 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -234,10 +234,20 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let list = try_opt!(format_item_list(items, width, offset, context.config)); match path_str { - Some(path_str) => Some(format!("{}({})", path_str, list)), + Some(path_str) => { + Some(if context.config.spaces_within_parens { + format!("{}( {} )", path_str, list) + } else { + format!("{}({})", path_str, list) + }) + } None => { let comma = if add_comma { "," } else { "" }; - Some(format!("({}{})", list, comma)) + Some(if context.config.spaces_within_parens { + format!("( {}{} )", list, comma) + } else { + format!("({}{})", list, comma) + }) } } } diff --git a/src/types.rs b/src/types.rs index a718750db95..624f17f6be8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -311,7 +311,11 @@ fn format_function_type<'a, I>(inputs: I, String::new() }; - Some(format!("({}){}{}", list_str, infix, output)) + Some(if context.config.spaces_within_parens { + format!("( {} ){}{}", list_str, infix, output) + } else { + format!("({}){}{}", list_str, infix, output) + }) } impl Rewrite for ast::WherePredicate { @@ -575,7 +579,12 @@ impl Rewrite for ast::Ty { // comments. ast::TyKind::Paren(ref ty) => { let budget = try_opt!(width.checked_sub(2)); - ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("({})", ty_str)) + ty.rewrite(context, budget, offset + 1) + .map(|ty_str| if context.config.spaces_within_parens { + format!("( {} )", ty_str) + } else { + format!("({})", ty_str) + }) } ast::TyKind::Vec(ref ty) => { let budget = try_opt!(width.checked_sub(2)); diff --git a/tests/source/spaces-within-parens.rs b/tests/source/spaces-within-parens.rs new file mode 100644 index 00000000000..63978eaf854 --- /dev/null +++ b/tests/source/spaces-within-parens.rs @@ -0,0 +1,46 @@ +// rustfmt-spaces_within_parens: true + +enum E { + A(u32), + B(u32, u32), + C(u32, u32, u32), + D(), +} + +struct TupleStruct0(); +struct TupleStruct1(u32); +struct TupleStruct2(u32, u32); + +fn fooEmpty() {} + +fn foo(e: E, _: u32) -> (u32, u32) { + + // Tuples + let t1 = (); + let t2 = (1,); + let t3 = (1, 2); + + let ts0 = TupleStruct0(); + let ts1 = TupleStruct1(1); + let ts2 = TupleStruct2(1, 2); + + // Tuple pattern + let (a,b,c) = (1,2,3); + + // Expressions + let x = (1 + 2) * (3); + + // Function call + fooEmpty(); + foo(1, 2); + + // Pattern matching + match e { + A(_) => (), + B(_, _) => (), + C(..) => (), + D => (), + } + + (1,2) +} diff --git a/tests/target/spaces-within-parens.rs b/tests/target/spaces-within-parens.rs new file mode 100644 index 00000000000..2a0a566ddea --- /dev/null +++ b/tests/target/spaces-within-parens.rs @@ -0,0 +1,46 @@ +// rustfmt-spaces_within_parens: true + +enum E { + A( u32 ), + B( u32, u32 ), + C( u32, u32, u32 ), + D(), +} + +struct TupleStruct0(); +struct TupleStruct1( u32 ); +struct TupleStruct2( u32, u32 ); + +fn fooEmpty() {} + +fn foo( e: E, _: u32 ) -> ( u32, u32 ) { + + // Tuples + let t1 = (); + let t2 = ( 1, ); + let t3 = ( 1, 2 ); + + let ts0 = TupleStruct0(); + let ts1 = TupleStruct1( 1 ); + let ts2 = TupleStruct2( 1, 2 ); + + // Tuple pattern + let ( a, b, c ) = ( 1, 2, 3 ); + + // Expressions + let x = ( 1 + 2 ) * ( 3 ); + + // Function call + fooEmpty(); + foo( 1, 2 ); + + // Pattern matching + match e { + A( _ ) => (), + B( _, _ ) => (), + C( .. ) => (), + D => (), + } + + ( 1, 2 ) +} -- cgit 1.4.1-3-g733a5 From 636a8287725042bb0ff58d763352fca00efb1a1a Mon Sep 17 00:00:00 2001 From: Mikko Rantanen Date: Thu, 13 Oct 2016 18:48:22 +0300 Subject: Add support for spaces_within_angle_brackets Enabling the config adds spaces within type arguments: <> --- src/chains.rs | 8 +++- src/config.rs | 1 + src/items.rs | 6 ++- src/types.rs | 26 +++++++++++-- tests/source/spaces-within-angle-brackets.rs | 56 ++++++++++++++++++++++++++++ tests/target/spaces-within-angle-brackets.rs | 56 ++++++++++++++++++++++++++++ 6 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 tests/source/spaces-within-angle-brackets.rs create mode 100644 tests/target/spaces-within-angle-brackets.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 77835d0414e..1220d43356e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -416,7 +416,13 @@ fn rewrite_method_call(method_name: ast::Ident, .map(|ty| ty.rewrite(context, width, offset)) .collect()); - (types.last().unwrap().span.hi, format!("::<{}>", type_list.join(", "))) + let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { + format!("::< {} >", type_list.join(", ")) + } else { + format!("::<{}>", type_list.join(", ")) + }; + + (types.last().unwrap().span.hi, type_str) }; let callee_str = format!(".{}{}", method_name, type_str); diff --git a/src/config.rs b/src/config.rs index ad14f81a819..b02af269f04 100644 --- a/src/config.rs +++ b/src/config.rs @@ -416,6 +416,7 @@ create_config! { space_after_bound_colon: bool, true, "Leave a space after the colon in a trait or lifetime bound"; spaces_around_ranges: bool, false, "Put spaces around the .. and ... range operators"; + spaces_within_angle_brackets: bool, false, "Put spaces within non-empty generic arguments"; spaces_within_parens: bool, false, "Put spaces within non-empty parentheses"; use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, diff --git a/src/items.rs b/src/items.rs index c3e58cba835..c24dde55189 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1800,7 +1800,11 @@ fn rewrite_generics(context: &RewriteContext, span.hi); let list_str = try_opt!(format_item_list(items, h_budget, offset, context.config)); - Some(format!("<{}>", list_str)) + Some(if context.config.spaces_within_angle_brackets { + format!("< {} >", list_str) + } else { + format!("<{}>", list_str) + }) } fn rewrite_trait_bounds(context: &RewriteContext, diff --git a/src/types.rs b/src/types.rs index 624f17f6be8..c210ae4627f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -45,6 +45,10 @@ pub fn rewrite_path(context: &RewriteContext, if let Some(qself) = qself { result.push('<'); + if context.config.spaces_within_angle_brackets { + result.push_str(" ") + } + let fmt_ty = try_opt!(qself.ty.rewrite(context, width, offset)); result.push_str(&fmt_ty); @@ -68,6 +72,10 @@ pub fn rewrite_path(context: &RewriteContext, offset + extra_offset)); } + if context.config.spaces_within_angle_brackets { + result.push_str(" ") + } + result.push_str(">::"); span_lo = qself.ty.span.hi + BytePos(1); } @@ -212,7 +220,11 @@ fn rewrite_segment(expr_context: bool, // Update position of last bracket. *span_lo = next_span_lo; - format!("{}<{}>", separator, list_str) + if context.config.spaces_within_angle_brackets && list_str.len() > 0 { + format!("{}< {} >", separator, list_str) + } else { + format!("{}<{}>", separator, list_str) + } } ast::PathParameters::Parenthesized(ref data) => { let output = match data.output { @@ -350,7 +362,11 @@ impl Rewrite for ast::WherePredicate { .intersperse(Some(" + ".to_string())) .collect()); - format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) + if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { + format!("for< {} > {}: {}", lifetime_str, type_str, bounds_str) + } else { + format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) + } } else { // 2 = ": ".len() let used_width = type_str.len() + 2; @@ -513,7 +529,11 @@ impl Rewrite for ast::PolyTraitRef { let path_str = try_opt!(self.trait_ref .rewrite(context, max_path_width, offset + extra_offset)); - Some(format!("for<{}> {}", lifetime_str, path_str)) + Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }) } else { self.trait_ref.rewrite(context, width, offset) } diff --git a/tests/source/spaces-within-angle-brackets.rs b/tests/source/spaces-within-angle-brackets.rs new file mode 100644 index 00000000000..07640e11e0e --- /dev/null +++ b/tests/source/spaces-within-angle-brackets.rs @@ -0,0 +1,56 @@ +// rustfmt-spaces_within_angle_brackets: true + +struct Foo { + i: T, +} + +struct Bar { + i: T, + e: E, +} + +struct Foo<'a> { + i: &'a str, +} + +enum E { + T(T), +} + +enum E { + T(T), + S(S), +} + +fn foo(a: T) { + foo::(10); +} + +fn foo(a: T, b: E) { + foo::(10, "bar"); +} + +fn foo(a: T, b: E) { + + foo::(10, "bar"); + + let opt: Option; + let res: Result; +} + +fn foo<'a>(a: &'a str) { + foo("foo"); +} + +fn foo<'a, 'b>(a: &'a str, b: &'b str) { + foo("foo", "bar"); +} + +impl Foo { + fn bar() { + ::bar(); + } +} + +trait MyTrait {} +impl MyTrait for Foo {} diff --git a/tests/target/spaces-within-angle-brackets.rs b/tests/target/spaces-within-angle-brackets.rs new file mode 100644 index 00000000000..67cfc1fac7f --- /dev/null +++ b/tests/target/spaces-within-angle-brackets.rs @@ -0,0 +1,56 @@ +// rustfmt-spaces_within_angle_brackets: true + +struct Foo< T > { + i: T, +} + +struct Bar< T, E > { + i: T, + e: E, +} + +struct Foo< 'a > { + i: &'a str, +} + +enum E< T > { + T(T), +} + +enum E< T, S > { + T(T), + S(S), +} + +fn foo< T >(a: T) { + foo::< u32 >(10); +} + +fn foo< T, E >(a: T, b: E) { + foo::< u32, str >(10, "bar"); +} + +fn foo< T: Send, E: Send >(a: T, b: E) { + + foo::< u32, str >(10, "bar"); + + let opt: Option< u32 >; + let res: Result< u32, String >; +} + +fn foo< 'a >(a: &'a str) { + foo("foo"); +} + +fn foo< 'a, 'b >(a: &'a str, b: &'b str) { + foo("foo", "bar"); +} + +impl Foo { + fn bar() { + < Foo as Foo >::bar(); + } +} + +trait MyTrait< A, D > {} +impl< A: Send, D: Send > MyTrait< A, D > for Foo {} -- cgit 1.4.1-3-g733a5 From 903e30b50365ef18c047c4f552622dce2529a559 Mon Sep 17 00:00:00 2001 From: Josh Chase Date: Thu, 13 Oct 2016 12:15:06 -0700 Subject: Quick fix for "impl Trait" * Remove "TODO" conversion * Add a couple of simple test cases Fix courtesy of @signaraiona --- src/types.rs | 5 ++--- tests/source/type.rs | 4 ++++ tests/target/type.rs | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 624f17f6be8..cb5b71181a5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -618,9 +618,8 @@ impl Rewrite for ast::Ty { ast::TyKind::Mac(..) | ast::TyKind::Typeof(..) => unreachable!(), ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(..) => { - // FIXME(#1154) Implement impl Trait - Some(String::from("impl TODO")) + ast::TyKind::ImplTrait(ref it) => { + it.rewrite(context, width, offset).map(|it_str| format!("impl {}", it_str)) } } } diff --git a/tests/source/type.rs b/tests/source/type.rs index 92da1010641..148abc30885 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -14,3 +14,7 @@ struct F { } fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} + +fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} + +fn impl_trait_fn_2() -> impl Future {} diff --git a/tests/target/type.rs b/tests/target/type.rs index 75655c913ec..6101442e072 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -23,3 +23,7 @@ struct F { } fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} + +fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} + +fn impl_trait_fn_2() -> impl Future {} -- cgit 1.4.1-3-g733a5 From 4b1c6690377e1dcac2ffd6357f89192ae63f1822 Mon Sep 17 00:00:00 2001 From: Mikko Rantanen Date: Mon, 17 Oct 2016 23:09:49 +0300 Subject: Add spaces_within_square_brackets config option. (#1191) * Add spaces_within_square_brackets config option. Enabling the config enforces spaces within various array/slice brackets. * Fixed budget-calculations for [] spacing --- src/config.rs | 1 + src/expr.rs | 27 ++++++++++++++------ src/patterns.rs | 6 ++++- src/types.rs | 18 +++++++++++--- tests/source/spaces-within-square-brackets.rs | 28 +++++++++++++++++++++ tests/target/spaces-within-square-brackets.rs | 36 +++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 tests/source/spaces-within-square-brackets.rs create mode 100644 tests/target/spaces-within-square-brackets.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b02af269f04..38e8201c2c2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -417,6 +417,7 @@ create_config! { "Leave a space after the colon in a trait or lifetime bound"; spaces_around_ranges: bool, false, "Put spaces around the .. and ... range operators"; spaces_within_angle_brackets: bool, false, "Put spaces within non-empty generic arguments"; + spaces_within_square_brackets: bool, false, "Put spaces within non-empty square brackets"; spaces_within_parens: bool, false, "Put spaces within non-empty parentheses"; use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, diff --git a/src/expr.rs b/src/expr.rs index e1d74a3cc79..a43b1ceac3f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -206,10 +206,16 @@ fn format_expr(expr: &ast::Expr, rewrite_pair(&**expr, &**ty, "", ": ", "", context, width, offset) } ast::ExprKind::Index(ref expr, ref index) => { - rewrite_pair(&**expr, &**index, "", "[", "]", context, width, offset) + let use_spaces = context.config.spaces_within_square_brackets; + let lbr = if use_spaces { "[ " } else { "[" }; + let rbr = if use_spaces { " ]" } else { "]" }; + rewrite_pair(&**expr, &**index, "", lbr, rbr, context, width, offset) } ast::ExprKind::Repeat(ref expr, ref repeats) => { - rewrite_pair(&**expr, &**repeats, "[", "; ", "]", context, width, offset) + let use_spaces = context.config.spaces_within_square_brackets; + let lbr = if use_spaces { "[ " } else { "[" }; + let rbr = if use_spaces { " ]" } else { "]" }; + rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, width, offset) } ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { @@ -303,11 +309,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I, -> Option where I: Iterator { - // 1 = [ - let offset = offset + 1; + let bracket_size = if context.config.spaces_within_square_brackets { + 2 // "[ " + } else { + 1 // "[" + }; + let offset = offset + bracket_size; let inner_context = &RewriteContext { block_indent: offset, ..*context }; - // 2 for brackets - let max_item_width = try_opt!(width.checked_sub(2)); + let max_item_width = try_opt!(width.checked_sub(bracket_size * 2)); let items = itemize_list(context.codemap, expr_iter, "]", @@ -339,7 +348,11 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let list_str = try_opt!(write_list(&items, &fmt)); - Some(format!("[{}]", list_str)) + Some(if context.config.spaces_within_square_brackets && list_str.len() > 0 { + format!("[ {} ]", list_str) + } else { + format!("[{}]", list_str) + }) } // This functions is pretty messy because of the rules around closures and blocks: diff --git a/src/patterns.rs b/src/patterns.rs index 149844cd196..eb394dddd02 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -94,7 +94,11 @@ impl Rewrite for Pat { let pats = try_opt!(pats); // Unwrap all the sub-strings and join them with commas. - let result = format!("[{}]", pats.join(", ")); + let result = if context.config.spaces_within_square_brackets { + format!("[ {} ]", pats.join(", ")) + } else { + format!("[{}]", pats.join(", ")) + }; wrap_str(result, context.config.max_width, width, offset) } PatKind::Struct(ref path, ref fields, elipses) => { diff --git a/src/types.rs b/src/types.rs index 75be97cce56..af3bf94498f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -607,8 +607,17 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::Vec(ref ty) => { - let budget = try_opt!(width.checked_sub(2)); - ty.rewrite(context, budget, offset + 1).map(|ty_str| format!("[{}]", ty_str)) + let budget = if context.config.spaces_within_square_brackets { + try_opt!(width.checked_sub(4)) + } else { + try_opt!(width.checked_sub(2)) + }; + ty.rewrite(context, budget, offset + 1) + .map(|ty_str| if context.config.spaces_within_square_brackets { + format!("[ {} ]", ty_str) + } else { + format!("[{}]", ty_str) + }) } ast::TyKind::Tup(ref items) => { rewrite_tuple(context, @@ -622,7 +631,10 @@ impl Rewrite for ast::Ty { rewrite_path(context, false, q_self.as_ref(), path, width, offset) } ast::TyKind::FixedLengthVec(ref ty, ref repeats) => { - rewrite_pair(&**ty, &**repeats, "[", "; ", "]", context, width, offset) + let use_spaces = context.config.spaces_within_square_brackets; + let lbr = if use_spaces { "[ " } else { "[" }; + let rbr = if use_spaces { " ]" } else { "]" }; + rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, width, offset) } ast::TyKind::Infer => { if width >= 1 { diff --git a/tests/source/spaces-within-square-brackets.rs b/tests/source/spaces-within-square-brackets.rs new file mode 100644 index 00000000000..6988ce5ed1c --- /dev/null +++ b/tests/source/spaces-within-square-brackets.rs @@ -0,0 +1,28 @@ +// rustfmt-spaces_within_square_brackets: true + +fn main() { + + let arr: [i32; 5] = [1, 2, 3, 4, 5]; + let arr: [i32; 500] = [0; 500]; + + let v = vec![1, 2, 3]; + assert_eq!(arr, [1, 2, 3]); + + let i = arr[0]; + + let slice = &arr[1..2]; + + let line100_________________________________________________________________________ = [1, 2]; + let line101__________________________________________________________________________ = [1, 2]; + let line102___________________________________________________________________________ = [1, 2]; + let line103____________________________________________________________________________ = [1, 2]; + let line104_____________________________________________________________________________ = [1, 2]; + + let line100_____________________________________________________________________ = vec![1, 2]; + let line101______________________________________________________________________ = vec![1, 2]; + let line102_______________________________________________________________________ = vec![1, 2]; + let line103________________________________________________________________________ = vec![1, 2]; + let line104_________________________________________________________________________ = vec![1, 2]; +} + +fn f(slice: &[i32]) {} diff --git a/tests/target/spaces-within-square-brackets.rs b/tests/target/spaces-within-square-brackets.rs new file mode 100644 index 00000000000..eb58a683704 --- /dev/null +++ b/tests/target/spaces-within-square-brackets.rs @@ -0,0 +1,36 @@ +// rustfmt-spaces_within_square_brackets: true + +fn main() { + + let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; + let arr: [ i32; 500 ] = [ 0; 500 ]; + + let v = vec![ 1, 2, 3 ]; + assert_eq!(arr, [ 1, 2, 3 ]); + + let i = arr[ 0 ]; + + let slice = &arr[ 1..2 ]; + + let line100_________________________________________________________________________ = [ 1, 2 ]; + let line101__________________________________________________________________________ = [ 1, + 2 ]; + let line102___________________________________________________________________________ = [ 1, + 2 ]; + let line103____________________________________________________________________________ = [ 1, + 2 ]; + let line104_____________________________________________________________________________ = + [ 1, 2 ]; + + let line100_____________________________________________________________________ = vec![ 1, 2 ]; + let line101______________________________________________________________________ = vec![ 1, + 2 ]; + let line102_______________________________________________________________________ = vec![ 1, + 2 ]; + let line103________________________________________________________________________ = vec![ 1, + 2 ]; + let line104_________________________________________________________________________ = + vec![ 1, 2 ]; +} + +fn f(slice: &[ i32 ]) {} -- cgit 1.4.1-3-g733a5 From 1c83c76015a822adca38ddf9214546ebda71670f Mon Sep 17 00:00:00 2001 From: Edward Yang Date: Mon, 24 Oct 2016 14:45:15 -0500 Subject: Stop extra newlines from being added after block comments (#1185) --- src/missed_spans.rs | 9 +++++++-- tests/source/issue-1177.rs | 6 ++++++ tests/target/issue-1177.rs | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-1177.rs create mode 100644 tests/target/issue-1177.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 98d87ba4963..3372c05eb06 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -144,8 +144,13 @@ impl<'a> FmtVisitor<'a> { line_start = offset + subslice.len(); if let Some('/') = subslice.chars().skip(1).next() { - // Add a newline after line comments - self.buffer.push_str("\n"); + // check that there are no contained block comments + if !subslice.split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() > 2 && &s[0..2] == "/*") { + // Add a newline after line comments + self.buffer.push_str("\n"); + } } else if line_start <= snippet.len() { // For other comments add a newline if there isn't one at the end already match snippet[line_start..].chars().next() { diff --git a/tests/source/issue-1177.rs b/tests/source/issue-1177.rs new file mode 100644 index 00000000000..053c73267fc --- /dev/null +++ b/tests/source/issue-1177.rs @@ -0,0 +1,6 @@ +fn main() { + // Line Comment + /* Block Comment */ + + let d = 5; +} diff --git a/tests/target/issue-1177.rs b/tests/target/issue-1177.rs new file mode 100644 index 00000000000..377540e1bfe --- /dev/null +++ b/tests/target/issue-1177.rs @@ -0,0 +1,6 @@ +fn main() { + // Line Comment + // Block Comment + + let d = 5; +} -- cgit 1.4.1-3-g733a5 From 5ecdd072d6745cd70ec7c37eea8dbf1f3ee42f2e Mon Sep 17 00:00:00 2001 From: Edward Yang Date: Thu, 27 Oct 2016 02:40:08 -0500 Subject: Remove extra whitespace after macro calls --- src/missed_spans.rs | 7 +++++++ tests/source/issue-1192.rs | 3 +++ tests/target/issue-1192.rs | 3 +++ 3 files changed, 13 insertions(+) create mode 100644 tests/source/issue-1192.rs create mode 100644 tests/target/issue-1192.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 98d87ba4963..b49686d40a6 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -178,6 +178,13 @@ impl<'a> FmtVisitor<'a> { if last_wspace.is_none() { last_wspace = Some(i); } + } else if c == ';' { + if last_wspace.is_some() { + line_start = i; + } + + rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + last_wspace = None; } else { rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; last_wspace = None; diff --git a/tests/source/issue-1192.rs b/tests/source/issue-1192.rs new file mode 100644 index 00000000000..4e39fbf9a36 --- /dev/null +++ b/tests/source/issue-1192.rs @@ -0,0 +1,3 @@ +fn main() { + assert!(true) ; +} diff --git a/tests/target/issue-1192.rs b/tests/target/issue-1192.rs new file mode 100644 index 00000000000..432fe8cce7c --- /dev/null +++ b/tests/target/issue-1192.rs @@ -0,0 +1,3 @@ +fn main() { + assert!(true); +} -- cgit 1.4.1-3-g733a5 From 764100361e621329b5077bc530daf3bb5eceaf3b Mon Sep 17 00:00:00 2001 From: Mason Smith Date: Wed, 2 Nov 2016 02:28:06 -0700 Subject: cargo-fmt processes bench, test, example files --- src/bin/cargo-fmt.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 9d2733f5820..55b8bc63333 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -97,7 +97,7 @@ fn format_crate(verbosity: Verbosity) -> Result { // Currently only bin and lib files get formatted let files: Vec<_> = targets.into_iter() - .filter(|t| t.kind.is_lib() | t.kind.is_bin()) + .filter(|t| t.kind.should_format()) .inspect(|t| { if verbosity == Verbosity::Verbose { println!("[{:?}] {:?}", t.kind, t.path) @@ -118,20 +118,17 @@ fn get_fmt_args() -> Vec { enum TargetKind { Lib, // dylib, staticlib, lib Bin, // bin - Other, // test, plugin,... + Example, // example file + Test, // test file + Bench, // bench file + Other, // plugin,... } impl TargetKind { - fn is_lib(&self) -> bool { + fn should_format(&self) -> bool { match *self { - TargetKind::Lib => true, - _ => false, - } - } - - fn is_bin(&self) -> bool { - match *self { - TargetKind::Bin => true, + TargetKind::Lib | TargetKind::Bin | TargetKind::Example | TargetKind::Test | + TargetKind::Bench => true, _ => false, } } @@ -171,6 +168,9 @@ fn target_from_json(jtarget: &Json) -> Target { let kind = match kinds[0].as_string().unwrap() { "bin" => TargetKind::Bin, "lib" | "dylib" | "staticlib" => TargetKind::Lib, + "test" => TargetKind::Test, + "example" => TargetKind::Example, + "bench" => TargetKind::Bench, _ => TargetKind::Other, }; -- cgit 1.4.1-3-g733a5 From f933d311157b90cdcb4f2bc670cea4844e5ea92e Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Thu, 3 Nov 2016 04:21:47 +0000 Subject: Fixes #1184 where reordering import items could cause a panic. Also extends an existing test to avoid regression. --- src/imports.rs | 5 ++++- tests/source/imports-reorder-lines-and-items.rs | 1 + tests/target/imports-reorder-lines-and-items.rs | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index ed74d828a9c..a01db739973 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -158,7 +158,10 @@ impl<'a> FmtVisitor<'a> { // Find the location immediately before the first use item in the run. This must not lie // before the current `self.last_pos` let pos_before_first_use_item = use_items.first() - .map(|p_i| cmp::max(self.last_pos, p_i.span.lo)) + .map(|p_i| { + cmp::max(self.last_pos, + p_i.attrs.iter().map(|attr| attr.span.lo).min().unwrap_or(p_i.span.lo)) + }) .unwrap_or(self.last_pos); // Construct a list of pairs, each containing a `use` item and the start of span before // that `use` item. diff --git a/tests/source/imports-reorder-lines-and-items.rs b/tests/source/imports-reorder-lines-and-items.rs index b61f26771f6..3c71f9984fe 100644 --- a/tests/source/imports-reorder-lines-and-items.rs +++ b/tests/source/imports-reorder-lines-and-items.rs @@ -1,6 +1,7 @@ // rustfmt-reorder_imports: true // rustfmt-reorder_imported_names: true +/// This comment should stay with `use std::str;` use std::str; use std::cmp::{d, c, b, a}; use std::ddd::aaa; diff --git a/tests/target/imports-reorder-lines-and-items.rs b/tests/target/imports-reorder-lines-and-items.rs index fb2e0347aac..f395710b186 100644 --- a/tests/target/imports-reorder-lines-and-items.rs +++ b/tests/target/imports-reorder-lines-and-items.rs @@ -6,4 +6,5 @@ use std::ddd::{a, b, c as g, d as p}; use std::ddd::aaa; // This comment should stay with `use std::ddd:bbb;` use std::ddd::bbb; +/// This comment should stay with `use std::str;` use std::str; -- cgit 1.4.1-3-g733a5 From aef665aa21fa484fa5be3a779901fed9a95c5b89 Mon Sep 17 00:00:00 2001 From: Fraser Hutchison Date: Thu, 3 Nov 2016 04:22:16 +0000 Subject: Fixes a few doc typos. --- src/comment.rs | 4 ++-- src/visitor.rs | 2 +- tests/system.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 23d7dab3de9..cb7fdadd4a2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -275,14 +275,14 @@ enum CharClassesStatus { LineComment, } -/// Distinguish between functionnal part of code and comments +/// Distinguish between functional part of code and comments #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum CodeCharKind { Normal, Comment, } -/// Distinguish between functionnal part of code and comments, +/// Distinguish between functional part of code and comments, /// describing opening and closing of comments for ease when chunking /// code from tagged characters #[derive(PartialEq, Eq, Debug, Clone, Copy)] diff --git a/src/visitor.rs b/src/visitor.rs index f05fcefdfe8..1f5d7c5414f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -179,7 +179,7 @@ impl<'a> FmtVisitor<'a> { pub fn visit_item(&mut self, item: &ast::Item) { // This is where we bail out if there is a skip attribute. This is only // complex in the module case. It is complex because the module could be - // in a seperate file and there might be attributes in both files, but + // in a separate file and there might be attributes in both files, but // the AST lumps them all together. match item.node { ast::ItemKind::Mod(ref m) => { diff --git a/tests/system.rs b/tests/system.rs index 3534052a173..a2a4c0eeedf 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -33,7 +33,7 @@ fn get_path_string(dir_entry: io::Result) -> String { // Integration tests. The files in the tests/source are formatted and compared // to their equivalent in tests/target. The target file and config can be -// overriden by annotations in the source file. The input and output must match +// overridden by annotations in the source file. The input and output must match // exactly. // FIXME(#28) would be good to check for error messages and fail on them, or at // least report. -- cgit 1.4.1-3-g733a5 From 5fc9fa377043fccde46b939ee5561e510a2bb931 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Mon, 7 Nov 2016 21:38:20 +0100 Subject: Condense suffix strings of simple wildcards in patterns --- src/config.rs | 2 ++ src/patterns.rs | 49 ++++++++++++++++++++++++------ tests/source/pattern-condense-wildcards.rs | 11 +++++++ tests/target/pattern-condense-wildcards.rs | 15 +++++++++ 4 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 tests/source/pattern-condense-wildcards.rs create mode 100644 tests/target/pattern-condense-wildcards.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 38e8201c2c2..8fe9552c7f8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -422,4 +422,6 @@ create_config! { use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; + condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in + tuple patterns" } diff --git a/src/patterns.rs b/src/patterns.rs index eb394dddd02..c9a29681728 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -12,7 +12,7 @@ use Indent; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; -use lists::{format_item_list, itemize_list}; +use lists::{format_item_list, itemize_list, ListItem}; use expr::{rewrite_unary_prefix, rewrite_pair}; use types::rewrite_path; use super::Spanned; @@ -226,16 +226,28 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let width = try_opt!(width.checked_sub(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() let offset = offset + path_len + 1; - let items = itemize_list(context.codemap, - pat_vec.iter(), - if add_comma { ",)" } else { ")" }, - |item| item.span().lo, - |item| item.span().hi, - |item| item.rewrite(context, width, offset), - context.codemap.span_after(span, "("), - span.hi - BytePos(1)); + let mut items: Vec<_> = itemize_list(context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, width, offset), + context.codemap.span_after(span, "("), + span.hi - BytePos(1)) + .collect(); - let list = try_opt!(format_item_list(items, width, offset, context.config)); + // Condense wildcard string suffix into a single .. + let wildcard_suffix_len = count_wildcard_suffix_len(&items); + + let list = if context.config.condense_wildcard_suffices && wildcard_suffix_len >= 2 { + let new_item_count = 1 + pats.len() - wildcard_suffix_len; + items[new_item_count - 1].item = Some("..".to_owned()); + + let da_iter = items.into_iter().take(new_item_count); + try_opt!(format_item_list(da_iter, width, offset, context.config)) + } else { + try_opt!(format_item_list(items.into_iter(), width, offset, context.config)) + }; match path_str { Some(path_str) => { @@ -256,3 +268,20 @@ fn rewrite_tuple_pat(pats: &[ptr::P], } } } + +fn count_wildcard_suffix_len(items: &[ListItem]) -> usize { + let mut suffix_len = 0; + + for item in items.iter().rev().take_while(|i| match i.item { + Some(ref internal_string) if internal_string == "_" => true, + _ => false, + }) { + suffix_len += 1; + + if item.pre_comment.is_some() || item.post_comment.is_some() { + break; + } + } + + suffix_len +} diff --git a/tests/source/pattern-condense-wildcards.rs b/tests/source/pattern-condense-wildcards.rs new file mode 100644 index 00000000000..bac712528dc --- /dev/null +++ b/tests/source/pattern-condense-wildcards.rs @@ -0,0 +1,11 @@ +// rustfmt-condense_wildcard_suffices: true + +fn main() { + match x { + Butt (_,_) => "hah", + Tup (_) => "nah", + Quad (_,_, x,_) => " also no rewrite", + Quad (x, _, _, _) => "condense me pls", + Weird (x, _, _, /* dont condense before */ _, _, _) => "pls work", + } +} diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs new file mode 100644 index 00000000000..96519cf3d44 --- /dev/null +++ b/tests/target/pattern-condense-wildcards.rs @@ -0,0 +1,15 @@ +// rustfmt-condense_wildcard_suffices: true + +fn main() { + match x { + Butt(..) => "hah", + Tup(_) => "nah", + Quad(_, _, x, _) => " also no rewrite", + Quad(x, ..) => "condense me pls", + Weird(x, + _, + _, + // dont condense before + ..) => "pls work", + } +} -- cgit 1.4.1-3-g733a5 From 0dffec8a5ccd036622bbe16d8d725dc887241847 Mon Sep 17 00:00:00 2001 From: Sébastien Santoro Date: Fri, 11 Nov 2016 05:27:18 +0100 Subject: Improve config::WriteMode comments - Fix typo - Switch comments verbs to the the 3rd person to offer a better coherence among options --- src/config.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 8fe9552c7f8..22db4d648fc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -154,19 +154,19 @@ configuration_option_enum! { ReportTactic: } configuration_option_enum! { WriteMode: - // Backsup the original file and overwrites the orignal. + // Backs the original file up and overwrites the original. Replace, // Overwrites original file without backup. Overwrite, - // Write the output to stdout. + // Writes the output to stdout. Display, - // Write the diff to stdout. + // Writes the diff to stdout. Diff, - // Display how much of the input file was processed + // Displays how much of the input file was processed Coverage, // Unfancy stdout Plain, - // Output a checkstyle XML file. + // Outputs a checkstyle XML file. Checkstyle, } -- cgit 1.4.1-3-g733a5 From 6c32c02952925f6397d70b686346bbbf41682a53 Mon Sep 17 00:00:00 2001 From: Martin Wohli Date: Sun, 13 Nov 2016 09:36:43 +0100 Subject: fix #1216: panic on comment starting with //* --- src/lists.rs | 8 +++++++- tests/source/issue-1216.rs | 4 ++++ tests/target/issue-1216.rs | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-1216.rs create mode 100644 tests/target/issue-1216.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 9607039e1d2..9af4fc238d6 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -366,7 +366,13 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let comment_end = match self.inner.peek() { Some(..) => { - let block_open_index = post_snippet.find("/*"); + let mut block_open_index = post_snippet.find("/*"); + // check if it realy is a block comment (and not //*) + if let Some(i) = block_open_index { + if i > 0 && &post_snippet[i - 1..i] == "/" { + block_open_index = None; + } + } let newline_index = post_snippet.find('\n'); let separator_index = post_snippet.find_uncommented(",").unwrap(); diff --git a/tests/source/issue-1216.rs b/tests/source/issue-1216.rs new file mode 100644 index 00000000000..da5f3471f72 --- /dev/null +++ b/tests/source/issue-1216.rs @@ -0,0 +1,4 @@ +enum E { + A, //* I am not a block comment (caused panic) + B, +} diff --git a/tests/target/issue-1216.rs b/tests/target/issue-1216.rs new file mode 100644 index 00000000000..da5f3471f72 --- /dev/null +++ b/tests/target/issue-1216.rs @@ -0,0 +1,4 @@ +enum E { + A, //* I am not a block comment (caused panic) + B, +} -- cgit 1.4.1-3-g733a5 From 935286755cbe08ba6beea31b3b8a83cd166a85f2 Mon Sep 17 00:00:00 2001 From: Bekh-Ivanov Aleksey Date: Mon, 14 Nov 2016 07:42:15 +0300 Subject: Stripping trailing commas and spaces from `vec!` elements (#1219) * Stripping trailing commas and spaces from `vec!` elements * Stripping trailing commas and spaces ONLY from `vec!` elements * Added comment --- src/macros.rs | 7 ++++++- tests/source/macros.rs | 9 +++++++++ tests/target/macros.rs | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index dd301ad9de7..250fd81099c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -114,7 +114,12 @@ pub fn rewrite_macro(mac: &ast::Mac, parser.bump(); if parser.token == Token::Eof { - return None; + // vec! is a special case of bracket macro which should be formated as an array. + if macro_name == "vec!" { + break; + } else { + return None; + } } } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index ca28d5c625b..5b6eb53daec 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -28,6 +28,15 @@ fn main() { vec! [a /* comment */]; + // Trailing spaces after a comma + vec![ + a, + ]; + + unknown_bracket_macro__comma_should_not_be_stripped![ + a, + ]; + foo(makro!(1, 3)); hamkaas!{ () }; diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 79a42524939..e5a0fc9731c 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -34,6 +34,13 @@ fn main() { vec![a /* comment */]; + // Trailing spaces after a comma + vec![a]; + + unknown_bracket_macro__comma_should_not_be_stripped![ + a, + ]; + foo(makro!(1, 3)); hamkaas!{ () }; -- cgit 1.4.1-3-g733a5 From d3eba76e4d63c08fa0c4406745d1f0cc0e576758 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 Nov 2016 08:37:35 +1300 Subject: update Serde, etc. Lots of changes to how closures work --- Cargo.lock | 64 +++++----- Cargo.toml | 4 +- src/bin/cargo-fmt.rs | 19 +-- src/codemap.rs | 3 - src/comment.rs | 18 +-- src/expr.rs | 290 +++++++++++++++++++++++++++--------------- src/items.rs | 36 ++---- src/lib.rs | 4 +- src/macros.rs | 23 +++- src/missed_spans.rs | 2 +- src/patterns.rs | 2 +- src/types.rs | 51 ++++---- src/utils.rs | 33 ++--- src/visitor.rs | 61 +++++---- tests/target/chains-visual.rs | 4 +- tests/target/chains.rs | 4 +- tests/target/closure.rs | 15 +-- tests/target/hard-tabs.rs | 22 ++-- tests/target/issue-1055.rs | 3 +- 19 files changed, 352 insertions(+), 306 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 41643344716..b5edd5f14d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,14 +7,14 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -46,7 +46,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -70,7 +70,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -83,7 +83,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -93,24 +93,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.5" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.19" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -123,36 +123,36 @@ dependencies = [ [[package]] name = "syntex_errors" -version = "0.44.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.44.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.44.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -172,7 +172,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -188,7 +188,7 @@ name = "toml" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -233,17 +233,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d" +"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" -"checksum regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)" = "64b03446c466d35b42f2a8b203c8e03ed8b91c0f17b56e1f84f7210a257aa665" -"checksum regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279401017ae31cf4e15344aa3f085d0e2e5c1e70067289ef906906fdbe92c8fd" -"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" +"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "bff9fc1c79f2dec76b253273d07682e94a978bd8f132ded071188122b2af9818" "checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" -"checksum syntex_errors 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0d95d2141ae79f312a01c6934d9984f9d7f5cfaf0c74aae5fbbc234a6dcb77a" -"checksum syntex_pos 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2cbf0598c5970f2dca122a4e6f7e93bf42f2d0b2dd88c3ea112413152864df" -"checksum syntex_syntax 0.44.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5a89ee386d492cdd3855becec489c25797bb91bcbb3c2478c41969b24cb318a2" +"checksum syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84822a1178204a191239ad844599f8c85c128cf9f4173397def4eb46b55b0aa1" +"checksum syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43abded5057c75bac8555e46ec913ce502efb418267b1ab8e9783897470c7db" +"checksum syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef781e4b60f03431f1b5b59843546ce60ae029a787770cf8e0969ac1fd063a5" "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" diff --git a/Cargo.toml b/Cargo.toml index 8db262568fa..122c8196a63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.44" -syntex_errors = "0.44" +syntex_syntax = "0.50" +syntex_errors = "0.50" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 55b8bc63333..3bc25af6311 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -98,10 +98,8 @@ fn format_crate(verbosity: Verbosity) -> Result { // Currently only bin and lib files get formatted let files: Vec<_> = targets.into_iter() .filter(|t| t.kind.should_format()) - .inspect(|t| { - if verbosity == Verbosity::Verbose { - println!("[{:?}] {:?}", t.kind, t.path) - } + .inspect(|t| if verbosity == Verbosity::Verbose { + println!("[{:?}] {:?}", t.kind, t.path) }) .map(|t| t.path) .collect(); @@ -204,15 +202,12 @@ fn format_files(files: &[PathBuf], .args(files) .args(fmt_args) .spawn() - .map_err(|e| { - match e.kind() { - std::io::ErrorKind::NotFound => { - std::io::Error::new(std::io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your \ - PATH.") - } - _ => e, + .map_err(|e| match e.kind() { + std::io::ErrorKind::NotFound => { + std::io::Error::new(std::io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.") } + _ => e, })); command.wait() } diff --git a/src/codemap.rs b/src/codemap.rs index 9ec5c663064..d04169c936e 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -46,7 +46,6 @@ pub trait LineRangeUtils { } impl SpanUtils for CodeMap { - #[inline] fn span_after(&self, original: Span, needle: &str) -> BytePos { let snippet = self.span_to_snippet(original).unwrap(); let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); @@ -54,7 +53,6 @@ impl SpanUtils for CodeMap { original.lo + BytePos(offset as u32) } - #[inline] fn span_after_last(&self, original: Span, needle: &str) -> BytePos { let snippet = self.span_to_snippet(original).unwrap(); let mut offset = 0; @@ -66,7 +64,6 @@ impl SpanUtils for CodeMap { original.lo + BytePos(offset as u32) } - #[inline] fn span_before(&self, original: Span, needle: &str) -> BytePos { let snippet = self.span_to_snippet(original).unwrap(); let offset = snippet.find_uncommented(needle).unwrap(); diff --git a/src/comment.rs b/src/comment.rs index cb7fdadd4a2..f831a039b95 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -111,12 +111,10 @@ pub fn rewrite_comment(orig: &str, line.trim_right() }) .map(left_trim_comment_line) - .map(|line| { - if orig.starts_with("/*") && line_breaks == 0 { - line.trim_left() - } else { - line - } + .map(|line| if orig.starts_with("/*") && line_breaks == 0 { + line.trim_left() + } else { + line }); let mut result = opener.to_owned(); @@ -746,11 +744,9 @@ mod test { // keeping it around unless it helps us test stuff. fn uncommented(text: &str) -> String { CharClasses::new(text.chars()) - .filter_map(|(s, c)| { - match s { - FullCodeCharKind::Normal => Some(c), - _ => None, - } + .filter_map(|(s, c)| match s { + FullCodeCharKind::Normal => Some(c), + _ => None, }) .collect() } diff --git a/src/expr.rs b/src/expr.rs index a43b1ceac3f..13150015417 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -22,14 +22,14 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, - semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_block, stmt_expr}; + semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; -use macros::rewrite_macro; +use macros::{rewrite_macro, MacroPosition}; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; @@ -180,12 +180,13 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, width, offset).or_else(|| { - wrap_str(context.snippet(expr.span), - context.config.max_width, - width, - offset) - }) + rewrite_macro(mac, None, context, width, offset, MacroPosition::Expression) + .or_else(|| { + wrap_str(context.snippet(expr.span), + context.config.max_width, + width, + offset) + }) } ast::ExprKind::Ret(None) => { wrap_str("return".to_owned(), context.config.max_width, width, offset) @@ -356,8 +357,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } // This functions is pretty messy because of the rules around closures and blocks: -// * the body of a closure is represented by an ast::Block, but that does not -// imply there are `{}` (unless the block is empty) (see rust issue #27872), +// TODO // * if there is a return type, then there must be braces, // * given a closure with braces, whether that is parsed to give an inner block // or not depends on if there is a return type and if there are statements @@ -367,7 +367,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, // can change whether it is treated as an expression or statement. fn rewrite_closure(capture: ast::CaptureBy, fn_decl: &ast::FnDecl, - body: &ast::Block, + body: &ast::Expr, span: Span, context: &RewriteContext, width: usize, @@ -386,7 +386,6 @@ fn rewrite_closure(capture: ast::CaptureBy, // 1 = | let argument_offset = offset + 1; let ret_str = try_opt!(fn_decl.output.rewrite(context, budget, argument_offset)); - let force_block = !ret_str.is_empty(); // 1 = space between arguments and return type. let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0); @@ -428,97 +427,181 @@ fn rewrite_closure(capture: ast::CaptureBy, prefix.push_str(&ret_str); } - if body.stmts.is_empty() { - return Some(format!("{} {{}}", prefix)); - } - // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, offset) + 1; let budget = try_opt!(width.checked_sub(extra_offset)); - - // This is where we figure out whether to use braces or not. - let mut had_braces = true; - let mut inner_block = body; - - let mut trailing_expr = stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]); - - // If there is an inner block and we can ignore it, do so. - if body.stmts.len() == 1 && trailing_expr.is_some() { - if let Some(ref inner) = stmt_block(&inner_block.stmts[0]) { - inner_block = inner; - trailing_expr = if inner_block.stmts.is_empty() { - None - } else { - stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]) - }; - } else if !force_block { - had_braces = false; + let total_offset = offset + extra_offset; + + if let ast::ExprKind::Block(ref block) = body.node { + // The body of the closure is a block. + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + return Some(format!("{} {{}}", prefix)); + } + + // Figure out if the block is necessary. + let needs_block = block.rules != ast::BlockCheckMode::Default || block.stmts.len() > 1 || + block_contains_comment(block, context.codemap) || + prefix.contains('\n'); + + if ret_str.is_empty() && !needs_block { + // lock.stmts.len() == 1 + if let Some(ref expr) = stmt_expr(&block.stmts[0]) { + if let Some(rw) = rewrite_closure_expr(expr, + &prefix, + context, + budget, + total_offset) { + return Some(rw); + } + } } - } - let try_single_line = is_simple_block(inner_block, context.codemap) && - inner_block.rules == ast::BlockCheckMode::Default; + if !needs_block { + // We need braces, but we might still prefer a one-liner. + let stmt = &block.stmts[0]; + // 4 = braces and spaces. + let mut rewrite = stmt.rewrite(context, try_opt!(budget.checked_sub(4)), total_offset); - if try_single_line && !force_block { - let must_preserve_braces = - trailing_expr.is_none() || - !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(trailing_expr.unwrap())); - if !(must_preserve_braces && had_braces) && - (must_preserve_braces || !prefix.contains('\n')) { - // If we got here, then we can try to format without braces. - - let inner_expr = &inner_block.stmts[0]; - let mut rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); - - if must_preserve_braces { - // If we are here, then failure to rewrite is unacceptable. - if rewrite.is_none() { - return None; - } - } else { - // Checks if rewrite succeeded and fits on a single line. - rewrite = and_one_line(rewrite); - } + // Checks if rewrite succeeded and fits on a single line. + rewrite = and_one_line(rewrite); if let Some(rewrite) = rewrite { - return Some(format!("{} {}", prefix, rewrite)); + return Some(format!("{} {{ {} }}", prefix, rewrite)); } } + + // Either we require a block, or tried without and failed. + return rewrite_closure_block(&block, prefix, context, budget); } - // If we fell through the above block, then we need braces, but we might - // still prefer a one-liner (we might also have fallen through because of - // lack of space). - if try_single_line && !prefix.contains('\n') { - let inner_expr = &inner_block.stmts[0]; - // 4 = braces and spaces. - let mut rewrite = inner_expr.rewrite(context, - try_opt!(budget.checked_sub(4)), - offset + extra_offset); + if let Some(rw) = rewrite_closure_expr(body, &prefix, context, budget, total_offset) { + return Some(rw); + } - // Checks if rewrite succeeded and fits on a single line. - rewrite = and_one_line(rewrite); + // The closure originally had a non-block expression, but we can't fit on + // one line, so we'll insert a block. + let block = ast::Block { + stmts: vec![ast::Stmt { + id: ast::NodeId::new(0), + node: ast::StmtKind::Expr(ptr::P(body.clone())), + span: body.span, + }], + id: ast::NodeId::new(0), + rules: ast::BlockCheckMode::Default, + span: body.span, + }; + return rewrite_closure_block(&block, prefix, context, budget); - if let Some(rewrite) = rewrite { - return Some(format!("{} {{ {} }}", prefix, rewrite)); + fn rewrite_closure_expr(expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + budget: usize, + offset: Indent) + -> Option { + let mut rewrite = expr.rewrite(context, budget, offset); + if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { + rewrite = and_one_line(rewrite); } + rewrite.map(|rw| format!("{} {}", prefix, rw)) } - // We couldn't format the closure body as a single line expression; fall - // back to block formatting. - let body_rewrite = try_opt!(inner_block.rewrite(&context, budget, Indent::empty())); + fn rewrite_closure_block(block: &ast::Block, + prefix: String, + context: &RewriteContext, + budget: usize) + -> Option { + // Start with visual indent, then fall back to block indent if the + // closure is large. + let rewrite = try_opt!(block.rewrite(&context, budget, Indent::empty())); - let block_threshold = context.config.closure_block_indent_threshold; - if block_threshold < 0 || body_rewrite.matches('\n').count() <= block_threshold as usize { - return Some(format!("{} {}", prefix, body_rewrite)); + let block_threshold = context.config.closure_block_indent_threshold; + if block_threshold < 0 || rewrite.matches('\n').count() <= block_threshold as usize { + return Some(format!("{} {}", prefix, rewrite)); + } + + // The body of the closure is big enough to be block indented, that + // means we must re-format. + let mut context = context.clone(); + context.block_indent.alignment = 0; + let rewrite = try_opt!(block.rewrite(&context, budget, Indent::empty())); + Some(format!("{} {}", prefix, rewrite)) } - // The body of the closure is big enough to be block indented, that means we - // must re-format. - let mut context = context.clone(); - context.block_indent.alignment = 0; - let body_rewrite = try_opt!(inner_block.rewrite(&context, budget, Indent::empty())); - Some(format!("{} {}", prefix, body_rewrite)) + // // This is where we figure out whether to use braces or not. + // let mut had_braces = true; + // let mut inner_block = body; + + // let mut trailing_expr = stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]); + + // // If there is an inner block and we can ignore it, do so. + // if body.stmts.len() == 1 && trailing_expr.is_some() { + // if let Some(ref inner) = stmt_block(&inner_block.stmts[0]) { + // inner_block = inner; + // trailing_expr = if inner_block.stmts.is_empty() { + // None + // } else { + // stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]) + // }; + // } else if !force_block { + // had_braces = false; + // } + // } + + // let try_single_line = is_simple_block(inner_block, context.codemap) && + // inner_block.rules == ast::BlockCheckMode::Default; + + + // if try_single_line && !force_block { + // let must_preserve_braces = + // trailing_expr.is_none() || + // !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(trailing_expr.unwrap())); + // if !(must_preserve_braces && had_braces) && + // (must_preserve_braces || !prefix.contains('\n')) { + // // If we got here, then we can try to format without braces. + + // let inner_expr = &inner_block.stmts[0]; + // let mut rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); + + // if must_preserve_braces { + // // If we are here, then failure to rewrite is unacceptable. + // if rewrite.is_none() { + // return None; + // } + // } else { + // // Checks if rewrite succeeded and fits on a single line. + // rewrite = and_one_line(rewrite); + // } + + // if let Some(rewrite) = rewrite { + // return Some(format!("{} {}", prefix, rewrite)); + // } + // } + // } + + // // If we fell through the above block, then we need braces, but we might + // // still prefer a one-liner (we might also have fallen through because of + // // lack of space). + // if try_single_line && !prefix.contains('\n') { + // let inner_expr = &inner_block.stmts[0]; + // // 4 = braces and spaces. + // let mut rewrite = inner_expr.rewrite(context, + // try_opt!(budget.checked_sub(4)), + // offset + extra_offset); + + // // Checks if rewrite succeeded and fits on a single line. + // rewrite = and_one_line(rewrite); + + // if let Some(rewrite) = rewrite { + // return Some(format!("{} {{ {} }}", prefix, rewrite)); + // } + // } + + // // We couldn't format the closure body as a single line expression; fall + // // back to block formatting. + // let mut context = context.clone(); + // context.block_indent.alignment = 0; + // let body_rewrite = try_opt!(inner_block.rewrite(&context, budget, Indent::empty())); + // Some(format!("{} {}", prefix, body_rewrite)) } fn and_one_line(x: Option) -> Option { @@ -526,13 +609,12 @@ fn and_one_line(x: Option) -> Option { } fn nop_block_collapse(block_str: Option, budget: usize) -> Option { - block_str.map(|block_str| { - if block_str.starts_with('{') && budget >= 2 && - (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { - "{}".to_owned() - } else { - block_str.to_owned() - } + block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && + (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == + block_str.len() - 2) { + "{}".to_owned() + } else { + block_str.to_owned() }) } @@ -1616,23 +1698,21 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let items = itemize_list(context.codemap, field_iter, "}", - |item| { - match *item { - StructLitField::Regular(field) => field.span.lo, - StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - } - }, - |item| { - match *item { - StructLitField::Regular(field) => field.span.hi, - StructLitField::Base(expr) => expr.span.hi, + |item| match *item { + StructLitField::Regular(field) => field.span.lo, + StructLitField::Base(expr) => { + let last_field_hi = fields.last() + .map_or(span.lo, |field| field.span.hi); + let snippet = + context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) } }, + |item| match *item { + StructLitField::Regular(field) => field.span.hi, + StructLitField::Base(expr) => expr.span.hi, + }, |item| { match *item { StructLitField::Regular(field) => { diff --git a/src/items.rs b/src/items.rs index c24dde55189..ac8a96a0fe0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -364,13 +364,11 @@ impl<'a> FmtVisitor<'a> { let items = itemize_list(self.codemap, enum_def.variants.iter(), "}", - |f| { - if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo - } else { - f.span.lo - } - }, + |f| if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo + } else { + f.span.lo + }, |f| f.span.hi, |f| self.format_variant(f), body_lo, @@ -1629,23 +1627,17 @@ fn rewrite_args(context: &RewriteContext, .map(ArgumentKind::Regular) .chain(variadic_arg), ")", - |arg| { - match *arg { - ArgumentKind::Regular(arg) => span_lo_for_arg(arg), - ArgumentKind::Variadic(start) => start, - } + |arg| match *arg { + ArgumentKind::Regular(arg) => span_lo_for_arg(arg), + ArgumentKind::Variadic(start) => start, }, - |arg| { - match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - } + |arg| match *arg { + ArgumentKind::Regular(arg) => arg.ty.span.hi, + ArgumentKind::Variadic(start) => start + BytePos(3), }, - |arg| { - match *arg { - ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => Some("...".to_owned()), - } + |arg| match *arg { + ArgumentKind::Regular(..) => None, + ArgumentKind::Variadic(..) => Some("...".to_owned()), }, comment_span_start, span.hi); diff --git a/src/lib.rs b/src/lib.rs index 740e0584893..50f1ab31291 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -393,9 +393,9 @@ fn parse_input(input: Input, parse_session: &ParseSess) -> Result> { let result = match input { - Input::File(file) => parse::parse_crate_from_file(&file, Vec::new(), parse_session), + Input::File(file) => parse::parse_crate_from_file(&file, parse_session), Input::Text(text) => { - parse::parse_crate_from_source_str("stdin".to_owned(), text, Vec::new(), parse_session) + parse::parse_crate_from_source_str("stdin".to_owned(), text, parse_session) } }; diff --git a/src/macros.rs b/src/macros.rs index 250fd81099c..1d9eb3f1ea8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -41,6 +41,13 @@ enum MacroStyle { Braces, } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MacroPosition { + Item, + Statement, + Expression, +} + impl MacroStyle { fn opener(&self) -> &'static str { match *self { @@ -55,7 +62,8 @@ pub fn rewrite_macro(mac: &ast::Mac, extra_ident: Option, context: &RewriteContext, width: usize, - offset: Indent) + offset: Indent, + position: MacroPosition) -> Option { if context.config.use_try_shorthand { if let Some(expr) = convert_try_mac(mac, context) { @@ -77,13 +85,16 @@ pub fn rewrite_macro(mac: &ast::Mac, if mac.node.tts.is_empty() && !contains_comment(&context.snippet(mac.span)) { return match style { + MacroStyle::Parens if position == MacroPosition::Item => { + Some(format!("{}();", macro_name)) + } MacroStyle::Parens => Some(format!("{}()", macro_name)), MacroStyle::Brackets => Some(format!("{}[]", macro_name)), MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), }; } - let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new()); + let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); let mut expr_vec = Vec::new(); if MacroStyle::Braces != style { @@ -128,6 +139,10 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Parens => { // Format macro invocation as function call. rewrite_call(context, ¯o_name, &expr_vec, mac.span, width, offset) + .map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) } MacroStyle::Brackets => { // Format macro invocation as array literal. @@ -155,10 +170,10 @@ pub fn rewrite_macro(mac: &ast::Mac, /// failed). pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { if &format!("{}", mac.node.path)[..] == "try" { - let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new()); + let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); Some(ast::Expr { - id: 0, // dummy value + id: ast::NodeId::new(0), // dummy value node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())), span: mac.span, // incorrect span, but shouldn't matter too much attrs: ThinVec::new(), diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 0e6995322a5..9caea864641 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -103,7 +103,7 @@ impl<'a> FmtVisitor<'a> { fn replace_chars(string: &str) -> String { string.chars() - .map(|ch| { if ch.is_whitespace() { ch } else { 'X' } }) + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) .collect() } diff --git a/src/patterns.rs b/src/patterns.rs index c9a29681728..a4ae0b7595a 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -78,7 +78,7 @@ impl Rewrite for Pat { offset) } PatKind::Lit(ref expr) => expr.rewrite(context, width, offset), - PatKind::Vec(ref prefix, ref slice_pat, ref suffix) => { + PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, width, offset)); let slice_pat = slice_pat.as_ref() diff --git a/src/types.rs b/src/types.rs index af3bf94498f..f4f86f58815 100644 --- a/src/types.rs +++ b/src/types.rs @@ -279,32 +279,27 @@ fn format_function_type<'a, I>(inputs: I, // 1 for ( let offset = offset + 1; let list_lo = context.codemap.span_after(span, "("); - let items = itemize_list(context.codemap, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs.map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), - ")", - |arg| { - match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo, - ArgumentKind::Variadic(start) => start, - } - }, - |arg| { - match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - } - }, - |arg| { - match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, budget, offset), - ArgumentKind::Variadic(_) => Some("...".to_owned()), - } - }, - list_lo, - span.hi); + let items = + itemize_list(context.codemap, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs.map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), + ")", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.rewrite(context, budget, offset), + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi); let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); @@ -606,7 +601,7 @@ impl Rewrite for ast::Ty { format!("({})", ty_str) }) } - ast::TyKind::Vec(ref ty) => { + ast::TyKind::Slice(ref ty) => { let budget = if context.config.spaces_within_square_brackets { try_opt!(width.checked_sub(4)) } else { @@ -630,7 +625,7 @@ impl Rewrite for ast::Ty { ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, false, q_self.as_ref(), path, width, offset) } - ast::TyKind::FixedLengthVec(ref ty, ref repeats) => { + ast::TyKind::Array(ref ty, ref repeats) => { let use_spaces = context.config.spaces_within_square_brackets; let lbr = if use_spaces { "[ " } else { "[" }; let rbr = if use_spaces { " ]" } else { "]" }; diff --git a/src/utils.rs b/src/utils.rs index 49472bb10aa..befed42c6fa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -127,11 +127,9 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { typaram.bounds .last() - .map_or(typaram.span, |bound| { - match *bound { - ast::RegionTyParamBound(ref lt) => lt.span, - ast::TraitTyParamBound(ref prt, _) => prt.span, - } + .map_or(typaram.span, |bound| match *bound { + ast::RegionTyParamBound(ref lt) => lt.span, + ast::TraitTyParamBound(ref prt, _) => prt.span, }) .hi } @@ -163,19 +161,6 @@ pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { } } -#[inline] -pub fn stmt_block(stmt: &ast::Stmt) -> Option<&ast::Block> { - match stmt.node { - ast::StmtKind::Expr(ref expr) => { - match expr.node { - ast::ExprKind::Block(ref inner) => Some(inner), - _ => None, - } - } - _ => None, - } -} - #[inline] pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { match stmt.node { @@ -334,13 +319,11 @@ pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option< #[test] fn bin_search_test() { - let closure = |i| { - match i { - 4 => Ok(()), - j if j > 4 => Err(Ordering::Less), - j if j < 4 => Err(Ordering::Greater), - _ => unreachable!(), - } + let closure = |i| match i { + 4 => Ok(()), + j if j > 4 => Err(Ordering::Less), + j if j < 4 => Err(Ordering::Greater), + _ => unreachable!(), }; assert_eq!(Some(()), binary_search(1, 10, &closure)); diff --git a/src/visitor.rs b/src/visitor.rs index 1f5d7c5414f..9c019fdd2d1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -20,7 +20,7 @@ use codemap::{LineRangeUtils, SpanUtils}; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; -use macros::rewrite_macro; +use macros::{rewrite_macro, MacroPosition}; use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; fn is_use_item(item: &ast::Item) -> bool { @@ -66,7 +66,7 @@ impl<'a> FmtVisitor<'a> { } ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, _) = **mac; - self.visit_mac(mac, None); + self.visit_mac(mac, None, MacroPosition::Statement); } } } @@ -124,13 +124,14 @@ impl<'a> FmtVisitor<'a> { fn visit_fn(&mut self, fk: visit::FnKind, fd: &ast::FnDecl, - b: &ast::Block, s: Span, _: ast::NodeId, defaultness: ast::Defaultness) { let indent = self.block_indent; + let block; let rewrite = match fk { - visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis) => { + visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => { + block = b; self.rewrite_fn(indent, ident, fd, @@ -141,9 +142,10 @@ impl<'a> FmtVisitor<'a> { abi, vis, codemap::mk_sp(s.lo, b.span.lo), - b) + &b) } - visit::FnKind::Method(ident, sig, vis) => { + visit::FnKind::Method(ident, sig, vis, b) => { + block = b; self.rewrite_fn(indent, ident, fd, @@ -154,9 +156,9 @@ impl<'a> FmtVisitor<'a> { sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), codemap::mk_sp(s.lo, b.span.lo), - b) + &b) } - visit::FnKind::Closure => None, + visit::FnKind::Closure(_) => unreachable!(), }; if let Some(fn_str) = rewrite { @@ -164,16 +166,16 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&fn_str); if let Some(c) = fn_str.chars().last() { if c == '}' { - self.last_pos = source!(self, b.span).hi; + self.last_pos = source!(self, block.span).hi; return; } } } else { - self.format_missing(source!(self, b.span).lo); + self.format_missing(source!(self, block.span).lo); } - self.last_pos = source!(self, b.span).lo; - self.visit_block(b) + self.last_pos = source!(self, block.span).lo; + self.visit_block(block) } pub fn visit_item(&mut self, item: &ast::Item) { @@ -261,11 +263,9 @@ impl<'a> FmtVisitor<'a> { item.span, indent, None) - .map(|s| { - match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - } + .map(|s| match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, }) }; self.push_rewrite(item.span, rewrite); @@ -280,7 +280,7 @@ impl<'a> FmtVisitor<'a> { self.format_mod(module, &item.vis, item.span, item.ident); } ast::ItemKind::Mac(ref mac) => { - self.visit_mac(mac, Some(item.ident)); + self.visit_mac(mac, Some(item.ident), MacroPosition::Item); } ast::ItemKind::ForeignMod(ref foreign_mod) => { self.format_missing_with_indent(source!(self, item.span).lo); @@ -315,9 +315,9 @@ impl<'a> FmtVisitor<'a> { unsafety, constness, abi, - &item.vis), + &item.vis, + body), decl, - body, item.span, item.id, ast::Defaultness::Final) @@ -361,9 +361,8 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, Some(ref body)) => { - self.visit_fn(visit::FnKind::Method(ti.ident, sig, None), + self.visit_fn(visit::FnKind::Method(ti.ident, sig, None, body), &sig.decl, - body, ti.span, ti.id, ast::Defaultness::Final); @@ -390,9 +389,8 @@ impl<'a> FmtVisitor<'a> { match ii.node { ast::ImplItemKind::Method(ref sig, ref body) => { - self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis)), + self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), &sig.decl, - body, ii.span, ii.id, ii.defaultness); @@ -416,15 +414,20 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { - self.visit_mac(mac, Some(ii.ident)); + self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); } } } - fn visit_mac(&mut self, mac: &ast::Mac, ident: Option) { + fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { // 1 = ; let width = self.config.max_width - self.block_indent.width() - 1; - let rewrite = rewrite_macro(mac, ident, &self.get_context(), width, self.block_indent); + let rewrite = rewrite_macro(mac, + ident, + &self.get_context(), + width, + self.block_indent, + pos); self.push_rewrite(mac.span, rewrite); } @@ -513,7 +516,9 @@ impl<'a> FmtVisitor<'a> { fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: ast::Ident) { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); - let is_internal = local_file_name == self.codemap.span_to_filename(source!(self, m.inner)); + let inner_span = source!(self, m.inner); + let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) && + local_file_name == self.codemap.span_to_filename(inner_span); self.buffer.push_str(&*utils::format_visibility(vis)); self.buffer.push_str("mod "); diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 9a13d03d5a2..472532676c5 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -46,9 +46,7 @@ fn main() { }); fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); + SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 53a54e8522d..726dbac155f 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -44,9 +44,7 @@ fn main() { }); fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); + SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) diff --git a/tests/target/closure.rs b/tests/target/closure.rs index ed8a66e2d16..101f3ea961c 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -3,14 +3,13 @@ fn main() { let square = (|i: i32| i * i); - let commented = |// first - a, // argument - // second - b: WithType, // argument - // ignored - _| { - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) - }; + let commented = + |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 7fa076b888f..d3adae03481 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -73,27 +73,21 @@ fn main() { arg(a, b, c, d, e) } - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } + loong_func().quux(move || if true { + 1 + } else { + 2 }); fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); + SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); }); a.b .c .d(); - x().y(|| { - match cond() { - true => (), - false => (), - } + x().y(|| match cond() { + true => (), + false => (), }); } diff --git a/tests/target/issue-1055.rs b/tests/target/issue-1055.rs index fed7d7de393..ee143e792b0 100644 --- a/tests/target/issue-1055.rs +++ b/tests/target/issue-1055.rs @@ -1,4 +1,3 @@ fn issue_1055() { - let foo = (|| { - })(); + let foo = (|| {})(); } -- cgit 1.4.1-3-g733a5 From 2fc1a2d3ccc9273f976a840a9019c33f8ca2c521 Mon Sep 17 00:00:00 2001 From: Wieland Hoffmann Date: Sun, 27 Nov 2016 21:43:02 +0100 Subject: Prevent an ugly linebreak in --config-helps description of condense_wildcard_suffices --- src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 22db4d648fc..7ee8e4a9097 100644 --- a/src/config.rs +++ b/src/config.rs @@ -422,6 +422,6 @@ create_config! { use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; - condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in - tuple patterns" + condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in \ + tuple patterns" } -- cgit 1.4.1-3-g733a5 From 6bf1382927ffab929a2153d894f306d7c30a3e82 Mon Sep 17 00:00:00 2001 From: Luke Clifton Date: Mon, 28 Nov 2016 08:47:07 +0800 Subject: Indent open brace for impl when nested. (#1227) * Indent open brace for impl when nested. Fixes #1226 * Added test case for indented impl with brace on newline --- src/items.rs | 5 ++++- tests/target/indented-impl.rs | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/target/indented-impl.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ac8a96a0fe0..3e510421976 100644 --- a/src/items.rs +++ b/src/items.rs @@ -497,7 +497,10 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - result.push_str(&where_clause_str); match context.config.item_brace_style { - BraceStyle::AlwaysNextLine => result.push('\n'), + BraceStyle::AlwaysNextLine => { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if !where_clause_str.is_empty() { diff --git a/tests/target/indented-impl.rs b/tests/target/indented-impl.rs new file mode 100644 index 00000000000..9acab7d757e --- /dev/null +++ b/tests/target/indented-impl.rs @@ -0,0 +1,11 @@ +// rustfmt-item_brace_style: AlwaysNextLine +mod x { + struct X(i8); + + impl Y for X + { + fn y(self) -> () { + println!("ok"); + } + } +} -- cgit 1.4.1-3-g733a5 From 56469a87453e9c8e1b65787d763626442d5a6345 Mon Sep 17 00:00:00 2001 From: Luke Clifton Date: Mon, 28 Nov 2016 08:47:38 +0800 Subject: Don't drop opening brace on long line matches. (#1228) * Don't drop opening brace on long line matches. Fixes #1225 * Added a test case for long match arms with braces on newline. --- src/expr.rs | 8 ++++---- tests/source/long-match-arms-brace-newline.rs | 14 ++++++++++++++ tests/target/long-match-arms-brace-newline.rs | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 tests/source/long-match-arms-brace-newline.rs create mode 100644 tests/target/long-match-arms-brace-newline.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 13150015417..c1528fc6271 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1315,17 +1315,17 @@ impl Rewrite for ast::Arm { let indent_str = offset.block_indent(context.config).to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms { if context.config.match_block_trailing_comma { - (" {", "},") + ("{", "},") } else { - (" {", "}") + ("{", "}") } } else { ("", "") }; let block_sep = match context.config.control_brace_style { - ControlBraceStyle::AlwaysNextLine => alt_block_sep, - ControlBraceStyle::AlwaysSameLine => String::from(body_prefix) + "\n", + ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n", + ControlBraceStyle::AlwaysSameLine => String::from(" ") + body_prefix + "\n", }; Some(format!("{}{} =>{}{}{}\n{}{}", attr_str.trim_left(), diff --git a/tests/source/long-match-arms-brace-newline.rs b/tests/source/long-match-arms-brace-newline.rs new file mode 100644 index 00000000000..79cfb927b49 --- /dev/null +++ b/tests/source/long-match-arms-brace-newline.rs @@ -0,0 +1,14 @@ +// rustfmt-max_width: 80 +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + match x { + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == + "aaaaaaaaaaa \ + aaaaaaa \ + aaaaaa" => { + Ok(()) + } + _ => Err(x), + } +} diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs new file mode 100644 index 00000000000..36f0b75f6a1 --- /dev/null +++ b/tests/target/long-match-arms-brace-newline.rs @@ -0,0 +1,15 @@ +// rustfmt-max_width: 80 +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + match x + { + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == + "aaaaaaaaaaa \ + aaaaaaa aaaaaa" => + { + Ok(()) + } + _ => Err(x), + } +} -- cgit 1.4.1-3-g733a5 From 22ddc36b179fadd2a2e67990b46240f9551a7d9e Mon Sep 17 00:00:00 2001 From: Jason Dusek Date: Fri, 16 Dec 2016 10:56:15 -0800 Subject: Recognize "rlib" and "cdylib" crates (#1238) Addresses #828 and https://github.com/lunaryorn/emacs-module.rs/issues/4 and probably numerous others. --- src/bin/cargo-fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3bc25af6311..3a667472118 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -165,7 +165,7 @@ fn target_from_json(jtarget: &Json) -> Target { let kinds = jtarget.get("kind").unwrap().as_array().unwrap(); let kind = match kinds[0].as_string().unwrap() { "bin" => TargetKind::Bin, - "lib" | "dylib" | "staticlib" => TargetKind::Lib, + "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, "test" => TargetKind::Test, "example" => TargetKind::Example, "bench" => TargetKind::Bench, -- cgit 1.4.1-3-g733a5 From e67ffcfb21a1e2d5fd08e0a16924848c7b68afc7 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 23 Dec 2016 11:13:00 -0800 Subject: Update to the latest syntex module One notable feature is this this adds support for the experimental `let x = loop { ... break $expr; }` syntax. This also includes a test for formatting all the break and continue variations. --- Cargo.lock | 56 +++++++++++++++++++------------------- Cargo.toml | 4 +-- src/expr.rs | 19 +++++++++---- src/imports.rs | 4 +-- src/items.rs | 14 +++------- src/macros.rs | 16 ++++++++--- src/utils.rs | 8 +++--- src/visitor.rs | 2 +- tests/source/break-and-continue.rs | 23 ++++++++++++++++ tests/target/break-and-continue.rs | 23 ++++++++++++++++ 10 files changed, 113 insertions(+), 56 deletions(-) create mode 100644 tests/source/break-and-continue.rs create mode 100644 tests/target/break-and-continue.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b5edd5f14d2..692db512585 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,17 +7,17 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -70,7 +70,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -83,7 +83,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -110,7 +110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -123,36 +123,36 @@ dependencies = [ [[package]] name = "syntex_errors" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -172,7 +172,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -188,12 +188,12 @@ name = "toml" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-segmentation" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -233,22 +233,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c4a9b56eb56058f43dc66e58f40a214b2ccbc9f3df51861b63d51dec7b65bc3f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" +"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "bff9fc1c79f2dec76b253273d07682e94a978bd8f132ded071188122b2af9818" +"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" "checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" -"checksum syntex_errors 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84822a1178204a191239ad844599f8c85c128cf9f4173397def4eb46b55b0aa1" -"checksum syntex_pos 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43abded5057c75bac8555e46ec913ce502efb418267b1ab8e9783897470c7db" -"checksum syntex_syntax 0.50.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ef781e4b60f03431f1b5b59843546ce60ae029a787770cf8e0969ac1fd063a5" +"checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b" +"checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac" +"checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" -"checksum unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b905d0fc2a1f0befd86b0e72e31d1787944efef9d38b9358a9e92a69757f7e3b" +"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum walkdir 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c66c0b9792f0a765345452775f3adbd28dde9d33f30d13e5dcc5ae17cf6f3780" diff --git a/Cargo.toml b/Cargo.toml index 122c8196a63..d6ae64ec401 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.50" -syntex_errors = "0.50" +syntex_syntax = "0.52" +syntex_errors = "0.52" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/expr.rs b/src/expr.rs index c1528fc6271..3bbc3c1295b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -160,15 +160,24 @@ fn format_expr(expr: &ast::Expr, width, offset) } - ast::ExprKind::Break(ref opt_ident) => { + ast::ExprKind::Break(ref opt_ident, ref opt_expr) => { let id_str = match *opt_ident { Some(ident) => format!(" {}", ident.node), None => String::new(), }; - wrap_str(format!("break{}", id_str), - context.config.max_width, - width, - offset) + + if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, + &format!("break{} ", id_str), + &**expr, + width, + offset) + } else { + wrap_str(format!("break{}", id_str), + context.config.max_width, + width, + offset) + } } ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, expr.span, context, width, offset) diff --git a/src/imports.rs b/src/imports.rs index a01db739973..d1c36299454 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -43,8 +43,8 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { } fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Ordering { - let a_name_str = a.node.name.name.as_str(); - let b_name_str = b.node.name.name.as_str(); + let a_name_str = &*a.node.name.name.as_str(); + let b_name_str = &*b.node.name.name.as_str(); let name_ordering = if a_name_str == "self" { if b_name_str == "self" { Ordering::Equal diff --git a/src/items.rs b/src/items.rs index 3e510421976..665704ea20f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,9 +23,8 @@ use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle}; use itertools::Itertools; -use syntax::{ast, abi, ptr, codemap}; +use syntax::{ast, abi, codemap, ptr, symbol}; use syntax::codemap::{Span, BytePos, mk_sp}; -use syntax::parse::token; use syntax::ast::ImplItem; // Statements of the form @@ -1276,7 +1275,7 @@ pub fn span_hi_for_arg(arg: &ast::Arg) -> BytePos { pub fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != token::keywords::Invalid.ident() + ident.node != symbol::keywords::Invalid.ident() } else { true } @@ -1688,13 +1687,8 @@ fn rewrite_args(context: &RewriteContext, } fn arg_has_pattern(arg: &ast::Arg) -> bool { - if let ast::PatKind::Ident(_, - codemap::Spanned { - node: ast::Ident { name: ast::Name(0u32), .. }, - .. - }, - _) = arg.pat.node { - false + if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { + ident.node != symbol::keywords::Invalid.ident() } else { true } diff --git a/src/macros.rs b/src/macros.rs index 1d9eb3f1ea8..412fb15cede 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -20,9 +20,10 @@ // and those with brackets will be formatted as array literals. use syntax::ast; +use syntax::codemap::{mk_sp, BytePos}; use syntax::parse::token::Token; use syntax::parse::tts_to_parser; -use syntax::codemap::{mk_sp, BytePos}; +use syntax::symbol; use syntax::util::ThinVec; use Indent; @@ -72,11 +73,18 @@ pub fn rewrite_macro(mac: &ast::Mac, } let original_style = macro_style(mac, context); + let macro_name = match extra_ident { - None | - Some(ast::Ident { name: ast::Name(0), .. }) => format!("{}!", mac.node.path), - Some(ident) => format!("{}! {}", mac.node.path, ident), + None => format!("{}!", mac.node.path), + Some(ident) => { + if ident == symbol::keywords::Invalid.ident() { + format!("{}!", mac.node.path) + } else { + format!("{}! {}", mac.node.path, ident) + } + } }; + let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { MacroStyle::Brackets } else { diff --git a/src/utils.rs b/src/utils.rs index befed42c6fa..ab5de426571 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -101,9 +101,9 @@ pub fn trimmed_last_line_width(s: &str) -> usize { #[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { - MetaItemKind::Word(ref s) => *s == SKIP_ANNOTATION, - MetaItemKind::List(ref s, ref l) => { - *s == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION, + MetaItemKind::List(ref l) => { + meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) } _ => false, } @@ -119,7 +119,7 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { #[inline] pub fn contains_skip(attrs: &[Attribute]) -> bool { - attrs.iter().any(|a| is_skip(&a.node.value)) + attrs.iter().any(|a| is_skip(&a.value)) } // Find the end of a TyParam diff --git a/src/visitor.rs b/src/visitor.rs index 9c019fdd2d1..f568c63eb38 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -471,7 +471,7 @@ impl<'a> FmtVisitor<'a> { } let outers: Vec<_> = attrs.iter() - .filter(|a| a.node.style == ast::AttrStyle::Outer) + .filter(|a| a.style == ast::AttrStyle::Outer) .cloned() .collect(); if outers.is_empty() { diff --git a/tests/source/break-and-continue.rs b/tests/source/break-and-continue.rs new file mode 100644 index 00000000000..c01d8a07845 --- /dev/null +++ b/tests/source/break-and-continue.rs @@ -0,0 +1,23 @@ +// break and continue formatting + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} diff --git a/tests/target/break-and-continue.rs b/tests/target/break-and-continue.rs new file mode 100644 index 00000000000..c01d8a07845 --- /dev/null +++ b/tests/target/break-and-continue.rs @@ -0,0 +1,23 @@ +// break and continue formatting + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} -- cgit 1.4.1-3-g733a5 From 1358f1ac806f10c5dbd80dd02934bf98d01993f2 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Wed, 4 Jan 2017 05:20:02 +0900 Subject: Fix #1259 (#1263) * Use `Indent::block_indent` instead of adding `config.tab_spaces` * Fix #1259 impl block closing brace placement --- src/items.rs | 4 ++-- tests/source/impls.rs | 8 ++++++++ tests/target/impls.rs | 10 ++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 665704ea20f..dafb7095002 100644 --- a/src/items.rs +++ b/src/items.rs @@ -539,6 +539,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if result.chars().last().unwrap() == '{' { result.push('\n'); + result.push_str(&offset.to_string(context.config)); } result.push('}'); @@ -698,8 +699,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if offset.width() + last_line_width(&result) + trait_bound_str.len() > context.config.ideal_width { result.push('\n'); - let width = context.block_indent.width() + context.config.tab_spaces; - let trait_indent = Indent::new(0, width); + let trait_indent = context.block_indent.block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); } result.push_str(&trait_bound_str); diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 6d65b8b4a7a..978ac8cc313 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -103,3 +103,11 @@ impl Handle PartialEq for Handle, HandleType> { } + +mod x { + impl Foo + where A: 'static, + B: 'static, + C: 'static, + D: 'static { } +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 87791d25648..dee683d18b1 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -132,3 +132,13 @@ impl Handle PartialEq for Handle, HandleType> { } + +mod x { + impl Foo + where A: 'static, + B: 'static, + C: 'static, + D: 'static + { + } +} -- cgit 1.4.1-3-g733a5 From 32cb83985541ec78fc17185c0847facf2f5da2ec Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 Jan 2017 16:06:09 +1300 Subject: Macros in types are possible Fixes #1234 --- Cargo.lock | 20 ++++++++++---------- src/types.rs | 4 ++-- tests/source/type.rs | 4 ++++ tests/target/type.rs | 4 ++++ 4 files changed, 20 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index f46b7d90b2f..822dcdaa644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -17,7 +17,7 @@ dependencies = [ "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -91,7 +91,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -134,7 +134,7 @@ name = "syntex_errors" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -156,7 +156,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -180,7 +180,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -201,7 +201,7 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -242,7 +242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itertools 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c6946da472dbbcbd98c049050e8e587cc4ee26985992e582b1d74a35cb8a7020" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" +"checksum libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e030dc72013ed68994d1b2cbf36a94dd0e58418ba949c4b0db7eeb70a7a6352" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" @@ -257,7 +257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" -"checksum unicode-segmentation 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70fba625c17936d0b811ccacb19c4e31186c82db42d9b670bcab830b2ddcde08" +"checksum unicode-segmentation 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7baebdc1df1363fa66161fca2fe047e4f4209011cc7e045948298996afdf85df" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum walkdir 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd7c16466ecc507c7cb5988db03e6eab4aaeab89a5c37a29251fcfd3ac9b7afe" diff --git a/src/types.rs b/src/types.rs index f4f86f58815..c186e1ea324 100644 --- a/src/types.rs +++ b/src/types.rs @@ -642,12 +642,12 @@ impl Rewrite for ast::Ty { rewrite_bare_fn(bare_fn, self.span, context, width, offset) } ast::TyKind::Never => Some(String::from("!")), - ast::TyKind::Mac(..) | - ast::TyKind::Typeof(..) => unreachable!(), + ast::TyKind::Mac(..) => None, ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(ref it) => { it.rewrite(context, width, offset).map(|it_str| format!("impl {}", it_str)) } + ast::TyKind::Typeof(..) => unreachable!(), } } } diff --git a/tests/source/type.rs b/tests/source/type.rs index 148abc30885..75c156455f9 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -18,3 +18,7 @@ fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, De fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} fn impl_trait_fn_2() -> impl Future {} + +fn issue_1234() { + do_parse!(name: take_while1!(is_token) >> (Header)) +} diff --git a/tests/target/type.rs b/tests/target/type.rs index 6101442e072..f9afb8aed02 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -27,3 +27,7 @@ fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, De fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} fn impl_trait_fn_2() -> impl Future {} + +fn issue_1234() { + do_parse!(name: take_while1!(is_token) >> (Header)) +} -- cgit 1.4.1-3-g733a5 From 6ecf5b8e844e5d8a35a21b1901e461033da0b9fa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 Jan 2017 16:35:28 +1300 Subject: If a string goes over-width, give up formatting it Logic here is that the original might be better and at best we'll only make it a different kind of bad. Fixes #1237 --- src/expr.rs | 10 +++++----- src/string.rs | 3 ++- tests/source/string-lit-2.rs | 23 +++++++++++++++++++---- tests/target/enum.rs | 6 ++---- tests/target/string-lit-2.rs | 23 +++++++++++++++++++---- 5 files changed, 47 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 3bbc3c1295b..b2ddd1c5731 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -64,7 +64,7 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Lit(ref l) => { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => { - rewrite_string_lit(context, l.span, width, offset) + Some(rewrite_string_lit(context, l.span, width, offset)) } _ => { wrap_str(context.snippet(expr.span), @@ -1457,16 +1457,16 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, width: usize, offset: Indent) - -> Option { + -> String { let string_lit = context.snippet(span); if !context.config.format_strings && !context.config.force_format_strings { - return Some(string_lit); + return string_lit; } if !context.config.force_format_strings && !string_requires_rewrite(context, span, &string_lit, width, offset) { - return Some(string_lit); + return string_lit; } let fmt = StringFormat { @@ -1483,7 +1483,7 @@ fn rewrite_string_lit(context: &RewriteContext, // Remove the quote characters. let str_lit = &string_lit[1..string_lit.len() - 1]; - rewrite_string(str_lit, &fmt) + rewrite_string(str_lit, &fmt).unwrap_or_else(|| string_lit.to_owned()) } fn string_requires_rewrite(context: &RewriteContext, diff --git a/src/string.rs b/src/string.rs index e90e24f7af2..71d8f8415f0 100644 --- a/src/string.rs +++ b/src/string.rs @@ -15,6 +15,7 @@ use regex::Regex; use Indent; use config::Config; +use utils::wrap_str; use MIN_STRING; @@ -117,7 +118,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option } result.push_str(fmt.closer); - Some(result) + wrap_str(result, fmt.config.max_width, fmt.width, fmt.offset) } #[cfg(test)] diff --git a/tests/source/string-lit-2.rs b/tests/source/string-lit-2.rs index c19df093176..6b95e25a052 100644 --- a/tests/source/string-lit-2.rs +++ b/tests/source/string-lit-2.rs @@ -3,8 +3,23 @@ fn main() -> &'static str { let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ s jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; - // Crappy formatting :-( - let change_me = "ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ - s - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} + +fn issue_1237() { + let msg = "eedadn\n\ + drvtee\n\ + eandsr\n\ + raavrd\n\ + atevrs\n\ + tsrnev\n\ + sdttsa\n\ + rasrtv\n\ + nssdts\n\ + ntnada\n\ + svetve\n\ + tesnvt\n\ + vntsnd\n\ + vrdear\n\ + dvrsen\n\ + enarar"; } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index aa51b90a79e..5b3960014b6 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -48,8 +48,7 @@ enum StructLikeVariants { enum X { CreateWebGLPaintTask(Size2D, GLContextAttributes, - IpcSender, usize), String>>), /* This is - * a post comment */ + IpcSender, usize), String>>), /* This is a post comment */ } pub enum EnumWithAttributes { @@ -71,8 +70,7 @@ pub enum EnumWithAttributes { pub enum SingleTuple { // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - Match(usize, usize, String), /* Post-comment - * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + Match(usize, usize, String), /* Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ } pub enum SingleStruct { diff --git a/tests/target/string-lit-2.rs b/tests/target/string-lit-2.rs index 7deb4215d2e..6b95e25a052 100644 --- a/tests/target/string-lit-2.rs +++ b/tests/target/string-lit-2.rs @@ -3,8 +3,23 @@ fn main() -> &'static str { let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ s jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; - // Crappy formatting :-( - let change_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss - \ - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} + +fn issue_1237() { + let msg = "eedadn\n\ + drvtee\n\ + eandsr\n\ + raavrd\n\ + atevrs\n\ + tsrnev\n\ + sdttsa\n\ + rasrtv\n\ + nssdts\n\ + ntnada\n\ + svetve\n\ + tesnvt\n\ + vntsnd\n\ + vrdear\n\ + dvrsen\n\ + enarar"; } -- cgit 1.4.1-3-g733a5 From 21c085261b3fac745768b03b10f5acb6e25e2972 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 Jan 2017 17:02:56 +1300 Subject: Remove `self` from `use foo::bar::self;` Also adds the `normalize_imports` config option. Fixes #1252 --- src/config.rs | 1 + src/imports.rs | 29 +++++++++++++++++++++-------- tests/source/imports.rs | 4 ++++ tests/target/imports.rs | 4 ++++ 4 files changed, 30 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7ee8e4a9097..641b8993fc5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -393,6 +393,7 @@ create_config! { reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imported_names: bool, false, "Reorder lists of names in import statements alphabetically"; + normalize_imports: bool, true, "Allows removing braces from imports and reducing paths"; single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ expressions. A value of zero means always break \ if-else expressions."; diff --git a/src/imports.rs b/src/imports.rs index d1c36299454..b2909cfecd2 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -133,15 +133,24 @@ impl Rewrite for ast::ViewPath { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { rewrite_use_list(width, offset, path, path_list, self.span, context) } - ast::ViewPath_::ViewPathGlob(_) => { - // FIXME convert to list? - None - } + ast::ViewPath_::ViewPathGlob(_) => None, ast::ViewPath_::ViewPathSimple(ident, ref path) => { let ident_str = ident.to_string(); // 4 = " as ".len() let budget = try_opt!(width.checked_sub(ident_str.len() + 4)); - let path_str = try_opt!(rewrite_path(context, false, None, path, budget, offset)); + + let path_str = if context.config.normalize_imports && + path.segments.last().unwrap().identifier.to_string() == "self" && + path.segments.len() > 1 { + let path = &ast::Path { + span: path.span.clone(), + segments: path.segments[..path.segments.len() - 1].to_owned(), + global: path.global, + }; + try_opt!(rewrite_path(context, false, None, &path, budget, offset)) + } else { + try_opt!(rewrite_path(context, false, None, path, budget, offset)) + }; Some(if path.segments.last().unwrap().identifier == ident { path_str @@ -239,9 +248,13 @@ impl<'a> FmtVisitor<'a> { } } -fn rewrite_single_use_list(path_str: Option, vpi: &ast::PathListItem) -> String { +fn rewrite_single_use_list(path_str: Option, + vpi: &ast::PathListItem, + context: &RewriteContext) + -> String { let path_item_str = match path_str { - Some(ref path_str) if vpi.node.name.to_string() == "self" => path_str.to_owned(), + Some(ref path_str) if vpi.node.name.to_string() == "self" && + context.config.normalize_imports => path_str.to_owned(), Some(path_str) => format!("{}::{}", path_str, vpi.node.name), None => vpi.node.name.to_string(), }; @@ -281,7 +294,7 @@ pub fn rewrite_use_list(width: usize, match path_list.len() { 0 => unreachable!(), - 1 => return Some(rewrite_single_use_list(opt_path_str, &path_list[0])), + 1 => return Some(rewrite_single_use_list(opt_path_str, &path_list[0], context)), _ => (), } diff --git a/tests/source/imports.rs b/tests/source/imports.rs index 45ed1e03fe0..4296a152f4e 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -20,6 +20,10 @@ use Foo::{Bar, Baz}; pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; use syntax::some::{}; +use self; +use std::io::{self}; +use std::io::self; + mod Foo { pub use syntax::ast::{ ItemForeignMod, diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 4e2f6903644..0be8f2c35e0 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -21,6 +21,10 @@ use {/* Pre-comment! */ Foo, Bar /* comment */}; use Foo::{Bar, Baz}; pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; +use self; +use std::io; +use std::io; + mod Foo { pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; -- cgit 1.4.1-3-g733a5 From 1c22d85db5c25c4f8dc573cd08bd75330a564cdb Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 9 Jan 2017 06:57:11 +0400 Subject: Better message for LineOverflow error (#1268) (with current length and configured limit) --- src/lib.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 50f1ab31291..fc016d86666 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,8 +202,8 @@ impl Sub for Indent { } pub enum ErrorKind { - // Line has exceeded character limit - LineOverflow, + // Line has exceeded character limit (found, maximum) + LineOverflow(usize, usize), // Line ends in whitespace TrailingWhitespace, // TO-DO or FIX-ME item without an issue number @@ -213,7 +213,12 @@ pub enum ErrorKind { impl fmt::Display for ErrorKind { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - ErrorKind::LineOverflow => write!(fmt, "line exceeded maximum length"), + ErrorKind::LineOverflow(found, maximum) => { + write!(fmt, + "line exceeded maximum length (maximum: {}, found: {})", + maximum, + found) + } ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), } @@ -229,7 +234,7 @@ pub struct FormattingError { impl FormattingError { fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow | + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "Rustfmt failed at", ErrorKind::BadIssue(_) => "WARNING:", } @@ -237,7 +242,7 @@ impl FormattingError { fn msg_suffix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow | + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "(sorry)", ErrorKind::BadIssue(_) => "", } @@ -353,7 +358,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m if line_len > config.max_width { errors.push(FormattingError { line: cur_line, - kind: ErrorKind::LineOverflow, + kind: ErrorKind::LineOverflow(line_len, config.max_width), }); } line_len = 0; -- cgit 1.4.1-3-g733a5 From ad46f9af95e3eefdd0e0b46084aba50568642aea Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 9 Jan 2017 06:58:06 +0400 Subject: Do not ignore space_before_bound in where clause (#1267) --- src/types.rs | 41 ++++++++++++++++++-------------------- tests/source/space-before-bound.rs | 8 +++++++- tests/target/space-before-bound.rs | 9 ++++++++- 3 files changed, 34 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index c186e1ea324..950a63adafc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -325,6 +325,15 @@ fn format_function_type<'a, I>(inputs: I, }) } +fn type_bound_colon(context: &RewriteContext) -> &'static str { + match (context.config.space_before_bound, context.config.space_after_bound_colon) { + (true, true) => " : ", + (true, false) => " :", + (false, true) => ": ", + (false, false) => ":", + } +} + impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { // TODO: dead spans? @@ -335,6 +344,8 @@ impl Rewrite for ast::WherePredicate { .. }) => { let type_str = try_opt!(bounded_ty.rewrite(context, width, offset)); + let colon = type_bound_colon(context); + if !bound_lifetimes.is_empty() { let lifetime_str: String = try_opt!(bound_lifetimes.iter() .map(|lt| { @@ -345,8 +356,8 @@ impl Rewrite for ast::WherePredicate { .intersperse(Some(", ".to_string())) .collect()); - // 8 = "for<> : ".len() - let used_width = lifetime_str.len() + type_str.len() + 8; + // 6 = "for<> ".len() + let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds.iter() .map(|ty_bound| { @@ -358,13 +369,12 @@ impl Rewrite for ast::WherePredicate { .collect()); if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { - format!("for< {} > {}: {}", lifetime_str, type_str, bounds_str) + format!("for< {} > {}{}{}", lifetime_str, type_str, colon, bounds_str) } else { - format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str) + format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) } } else { - // 2 = ": ".len() - let used_width = type_str.len() + 2; + let used_width = type_str.len() + colon.len(); let budget = try_opt!(width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds.iter() .map(|ty_bound| { @@ -375,7 +385,7 @@ impl Rewrite for ast::WherePredicate { .intersperse(Some(" + ".to_string())) .collect()); - format!("{}: {}", type_str, bounds_str) + format!("{}{}{}", type_str, colon, bounds_str) } } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, @@ -420,21 +430,8 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, let appendix: Vec<_> = try_opt!(bounds.into_iter() .map(|b| b.rewrite(context, width, offset)) .collect()); - let bound_spacing_before = if context.config.space_before_bound { - " " - } else { - "" - }; - let bound_spacing_after = if context.config.space_after_bound_colon { - " " - } else { - "" - }; - let result = format!("{}{}:{}{}", - result, - bound_spacing_before, - bound_spacing_after, - appendix.join(" + ")); + let colon = type_bound_colon(context); + let result = format!("{}{}{}", result, colon, appendix.join(" + ")); wrap_str(result, context.config.max_width, width, offset) } } diff --git a/tests/source/space-before-bound.rs b/tests/source/space-before-bound.rs index cb4cf8aafd6..2a77eb2d2f9 100644 --- a/tests/source/space-before-bound.rs +++ b/tests/source/space-before-bound.rs @@ -1,4 +1,10 @@ // rustfmt-space_before_bound: true trait Trait {} -fn f<'a, 'b: 'a, T: Trait>() {} +trait Trait2 {} +fn f<'a, 'b: 'a, T: Trait, U>() where U: Trait2 {} + +// should fit on the line +fn f2<'a, 'b: 'a, Ttttttttttttttttttttttttttttttttttttttttttttttt: Trait, U>() where U: Trait2 {} +// should be wrapped +fn f2<'a, 'b: 'a, Tttttttttttttttttttttttttttttttttttttttttttttttt: Trait, U>() where U: Trait2 {} diff --git a/tests/target/space-before-bound.rs b/tests/target/space-before-bound.rs index 7e1ef870315..0a226e1d585 100644 --- a/tests/target/space-before-bound.rs +++ b/tests/target/space-before-bound.rs @@ -1,4 +1,11 @@ // rustfmt-space_before_bound: true trait Trait {} -fn f<'a, 'b : 'a, T : Trait>() {} +trait Trait2 {} +fn f<'a, 'b : 'a, T : Trait, U>() where U : Trait2 {} + +// should fit on the line +fn f2<'a, 'b : 'a, Ttttttttttttttttttttttttttttttttttttttttttttttt : Trait, U>() where U : Trait2 {} +// should be wrapped +fn f2<'a, 'b : 'a, Tttttttttttttttttttttttttttttttttttttttttttttttt : Trait, U>() where U : Trait2 { +} -- cgit 1.4.1-3-g733a5 From 7e2fcc27e1b359efbdcc16b0aaabe6f7e09d8b4a Mon Sep 17 00:00:00 2001 From: sinkuu Date: Mon, 9 Jan 2017 12:11:12 +0900 Subject: Fix #1258 (#1266) * Fix #1258 * Add test --- src/items.rs | 13 ++++++++++++- tests/source/structs.rs | 11 +++++++++++ tests/target/structs.rs | 8 ++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index dafb7095002..6a187bad7d5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -839,7 +839,18 @@ fn format_struct_struct(context: &RewriteContext, // FIXME(#919): properly format empty structs and their comments. if fields.is_empty() { - result.push_str(&context.snippet(mk_sp(body_lo, span.hi))); + let snippet = context.snippet(mk_sp(body_lo, span.hi - BytePos(1))); + if snippet.trim().is_empty() { + // `struct S {}` + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { + // fix indent + result.push_str(&snippet.trim_right()); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push_str(&snippet); + } + result.push('}'); return Some(result); } diff --git a/tests/source/structs.rs b/tests/source/structs.rs index ff297655713..5a13d59f572 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -153,4 +153,15 @@ struct Issue677 { } struct Foo {} +struct Foo { + } +struct Foo { + // comment + } +struct Foo { + // trailing space -> + + + } +struct Foo { /* comment */ } struct Foo(); diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 0af68686318..3d3b20a9ad6 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -161,4 +161,12 @@ struct Issue677 { } struct Foo {} +struct Foo {} +struct Foo { + // comment +} +struct Foo { + // trailing space -> +} +struct Foo { /* comment */ } struct Foo(); -- cgit 1.4.1-3-g733a5 From 9be29712748cf8d723d190f9e99442cebbe1fd94 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jan 2017 12:06:23 +1300 Subject: Refactor pairs/binops --- src/expr.rs | 257 +++++++++++++++------------------------- tests/target/expr.rs | 26 ++-- tests/target/type-ascription.rs | 13 +- 3 files changed, 116 insertions(+), 180 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b2ddd1c5731..3271cc3f299 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -80,7 +80,15 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, width, offset), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { - rewrite_binary_op(context, op, lhs, rhs, width, offset) + // FIXME: format comments between operands and operator + rewrite_pair(&**lhs, + &**rhs, + "", + &format!(" {} ", context.snippet(op.span)), + "", + context, + width, + offset) } ast::ExprKind::Unary(ref op, ref subexpr) => { rewrite_unary_op(context, op, subexpr, width, offset) @@ -216,15 +224,14 @@ fn format_expr(expr: &ast::Expr, rewrite_pair(&**expr, &**ty, "", ": ", "", context, width, offset) } ast::ExprKind::Index(ref expr, ref index) => { - let use_spaces = context.config.spaces_within_square_brackets; - let lbr = if use_spaces { "[ " } else { "[" }; - let rbr = if use_spaces { " ]" } else { "]" }; - rewrite_pair(&**expr, &**index, "", lbr, rbr, context, width, offset) + rewrite_index(&**expr, &**index, context, width, offset) } ast::ExprKind::Repeat(ref expr, ref repeats) => { - let use_spaces = context.config.spaces_within_square_brackets; - let lbr = if use_spaces { "[ " } else { "[" }; - let rbr = if use_spaces { " ]" } else { "]" }; + let (lbr, rbr) = if context.config.spaces_within_square_brackets { + ("[ ", " ]") + } else { + ("[", "]") + }; rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, width, offset) } ast::ExprKind::Range(ref lhs, ref rhs, limits) => { @@ -286,29 +293,63 @@ pub fn rewrite_pair(lhs: &LHS, where LHS: Rewrite, RHS: Rewrite { - let max_width = try_opt!(width.checked_sub(prefix.len() + infix.len() + suffix.len())); + let lhs_budget = try_opt!(width.checked_sub(prefix.len() + infix.len())); + let rhs_budget = try_opt!(width.checked_sub(suffix.len())); - binary_search(1, max_width, |lhs_budget| { - let lhs_offset = offset + prefix.len(); - let lhs_str = match lhs.rewrite(context, lhs_budget, lhs_offset) { - Some(result) => result, - None => return Err(Ordering::Greater), - }; + // Get "full width" rhs and see if it fits on the current line. This + // usually works fairly well since it tends to place operands of + // operations with high precendence close together. + // Note that this is non-conservative, but its just to see if it's even + // worth trying to put everything on one line. + let rhs_result = rhs.rewrite(context, rhs_budget, offset); - let last_line_width = last_line_width(&lhs_str); - let rhs_budget = match max_width.checked_sub(last_line_width) { - Some(b) => b, - None => return Err(Ordering::Less), - }; - let rhs_indent = offset + last_line_width + prefix.len() + infix.len(); + if let Some(rhs_result) = rhs_result { + // This is needed in case of line break not caused by a + // shortage of space, but by end-of-line comments, for example. + if !rhs_result.contains('\n') { + let lhs_result = lhs.rewrite(context, lhs_budget, offset); + if let Some(lhs_result) = lhs_result { + let mut result = format!("{}{}{}", prefix, lhs_result, infix); - let rhs_str = match rhs.rewrite(context, rhs_budget, rhs_indent) { - Some(result) => result, - None => return Err(Ordering::Less), - }; + let remaining_width = width.checked_sub(last_line_width(&result)).unwrap_or(0); - Ok(format!("{}{}{}{}{}", prefix, lhs_str, infix, rhs_str, suffix)) - }) + if rhs_result.len() <= remaining_width { + result.push_str(&rhs_result); + result.push_str(suffix); + return Some(result); + } + + // Try rewriting the rhs into the remaining space. + let rhs_budget = try_opt!(remaining_width.checked_sub(suffix.len())); + if let Some(rhs_result) = rhs.rewrite(context, rhs_budget, offset + result.len()) { + if rhs_result.len() <= remaining_width { + result.push_str(&rhs_result); + result.push_str(suffix); + return Some(result); + } + } + } + } + } + + // We have to use multiple lines. + + // Re-evaluate the rhs because we have more space now: + let infix = infix.trim_right(); + let lhs_budget = + try_opt!(context.config.max_width.checked_sub(offset.width() + prefix.len() + infix.len())); + let rhs_budget = try_opt!(rhs_budget.checked_sub(prefix.len())); + let rhs_offset = offset + prefix.len(); + + let rhs_result = try_opt!(rhs.rewrite(context, rhs_budget, rhs_offset)); + let lhs_result = try_opt!(lhs.rewrite(context, lhs_budget, offset)); + Some(format!("{}{}{}\n{}{}{}", + prefix, + lhs_result, + infix, + rhs_offset.to_string(context.config), + rhs_result, + suffix)) } pub fn rewrite_array<'a, I>(expr_iter: I, @@ -535,82 +576,6 @@ fn rewrite_closure(capture: ast::CaptureBy, let rewrite = try_opt!(block.rewrite(&context, budget, Indent::empty())); Some(format!("{} {}", prefix, rewrite)) } - - // // This is where we figure out whether to use braces or not. - // let mut had_braces = true; - // let mut inner_block = body; - - // let mut trailing_expr = stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]); - - // // If there is an inner block and we can ignore it, do so. - // if body.stmts.len() == 1 && trailing_expr.is_some() { - // if let Some(ref inner) = stmt_block(&inner_block.stmts[0]) { - // inner_block = inner; - // trailing_expr = if inner_block.stmts.is_empty() { - // None - // } else { - // stmt_expr(&inner_block.stmts[inner_block.stmts.len() - 1]) - // }; - // } else if !force_block { - // had_braces = false; - // } - // } - - // let try_single_line = is_simple_block(inner_block, context.codemap) && - // inner_block.rules == ast::BlockCheckMode::Default; - - - // if try_single_line && !force_block { - // let must_preserve_braces = - // trailing_expr.is_none() || - // !classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(trailing_expr.unwrap())); - // if !(must_preserve_braces && had_braces) && - // (must_preserve_braces || !prefix.contains('\n')) { - // // If we got here, then we can try to format without braces. - - // let inner_expr = &inner_block.stmts[0]; - // let mut rewrite = inner_expr.rewrite(context, budget, offset + extra_offset); - - // if must_preserve_braces { - // // If we are here, then failure to rewrite is unacceptable. - // if rewrite.is_none() { - // return None; - // } - // } else { - // // Checks if rewrite succeeded and fits on a single line. - // rewrite = and_one_line(rewrite); - // } - - // if let Some(rewrite) = rewrite { - // return Some(format!("{} {}", prefix, rewrite)); - // } - // } - // } - - // // If we fell through the above block, then we need braces, but we might - // // still prefer a one-liner (we might also have fallen through because of - // // lack of space). - // if try_single_line && !prefix.contains('\n') { - // let inner_expr = &inner_block.stmts[0]; - // // 4 = braces and spaces. - // let mut rewrite = inner_expr.rewrite(context, - // try_opt!(budget.checked_sub(4)), - // offset + extra_offset); - - // // Checks if rewrite succeeded and fits on a single line. - // rewrite = and_one_line(rewrite); - - // if let Some(rewrite) = rewrite { - // return Some(format!("{} {{ {} }}", prefix, rewrite)); - // } - // } - - // // We couldn't format the closure body as a single line expression; fall - // // back to block formatting. - // let mut context = context.clone(); - // context.block_indent.alignment = 0; - // let body_rewrite = try_opt!(inner_block.rewrite(&context, budget, Indent::empty())); - // Some(format!("{} {}", prefix, body_rewrite)) } fn and_one_line(x: Option) -> Option { @@ -1665,6 +1630,36 @@ fn rewrite_paren(context: &RewriteContext, }) } +fn rewrite_index(expr: &ast::Expr, + index: &ast::Expr, + context: &RewriteContext, + width: usize, + offset: Indent) + -> Option { + let expr_str = try_opt!(expr.rewrite(context, width, offset)); + + let (lbr, rbr) = if context.config.spaces_within_square_brackets { + ("[ ", " ]") + } else { + ("[", "]") + }; + + let budget = width.checked_sub(expr_str.len() + lbr.len() + rbr.len()).unwrap_or(0); + let index_str = index.rewrite(context, budget, offset); + if let Some(index_str) = index_str { + return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); + } + + let indent = offset.block_indent(&context.config); + let indent = indent.to_string(&context.config); + // FIXME this is not right, since we don't take into account that width + // might be reduced from max_width by something on the right. + let budget = + try_opt!(context.config.max_width.checked_sub(indent.len() + lbr.len() + rbr.len())); + let index_str = try_opt!(index.rewrite(context, budget, offset)); + Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr)) +} + fn rewrite_struct_lit<'a>(context: &RewriteContext, path: &ast::Path, fields: &'a [ast::Field], @@ -1886,62 +1881,6 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, } } -fn rewrite_binary_op(context: &RewriteContext, - op: &ast::BinOp, - lhs: &ast::Expr, - rhs: &ast::Expr, - width: usize, - offset: Indent) - -> Option { - // FIXME: format comments between operands and operator - - let operator_str = context.snippet(op.span); - - // Get "full width" rhs and see if it fits on the current line. This - // usually works fairly well since it tends to place operands of - // operations with high precendence close together. - let rhs_result = try_opt!(rhs.rewrite(context, width, offset)); - - // Second condition is needed in case of line break not caused by a - // shortage of space, but by end-of-line comments, for example. - // Note that this is non-conservative, but its just to see if it's even - // worth trying to put everything on one line. - if rhs_result.len() + 2 + operator_str.len() < width && !rhs_result.contains('\n') { - // 1 = space between lhs expr and operator - if let Some(mut result) = lhs.rewrite(context, width - 1 - operator_str.len(), offset) { - result.push(' '); - result.push_str(&operator_str); - result.push(' '); - - let remaining_width = width.checked_sub(last_line_width(&result)).unwrap_or(0); - - if rhs_result.len() <= remaining_width { - result.push_str(&rhs_result); - return Some(result); - } - - if let Some(rhs_result) = rhs.rewrite(context, remaining_width, offset + result.len()) { - if rhs_result.len() <= remaining_width { - result.push_str(&rhs_result); - return Some(result); - } - } - } - } - - // We have to use multiple lines. - - // Re-evaluate the lhs because we have more space now: - let budget = try_opt!(context.config - .max_width - .checked_sub(offset.width() + 1 + operator_str.len())); - Some(format!("{} {}\n{}{}", - try_opt!(lhs.rewrite(context, budget, offset)), - operator_str, - offset.to_string(context.config), - rhs_result)) -} - pub fn rewrite_unary_prefix(context: &RewriteContext, prefix: &str, rewrite: &R, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 48fa14d8a54..ec9c6f10f5f 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -76,8 +76,8 @@ fn foo() -> bool { } fn bar() { - let range = (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + - 2333333333333333); + let range = (111111111 + 333333333333333333 + 1111 + 400000000000000000).. + (2222 + 2333333333333333); let another_range = 5..some_func(a, b /* comment */); @@ -226,19 +226,17 @@ fn casts() { } fn indices() { - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[x + - y + - z]; - let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + - cccccccccccccccc)[xxxxx + yyyyy + zzzzz]; + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) + [x + y + z]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) + [xxxxx + yyyyy + zzzzz]; } fn repeats() { - let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; x + - y + - z]; - let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + - cccccccccccccccc; xxxxx + yyyyy + zzzzz]; + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; + x + y + z]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; + xxxxx + yyyyy + zzzzz]; } fn blocks() { @@ -260,8 +258,8 @@ fn issue767() { fn ranges() { let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let y = - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ...x; a...b diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index de8d97d7b67..121c7990f86 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -1,13 +1,12 @@ fn main() { - let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: + SomeTrait; - let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - let z = funk(yyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzz, - wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; x: u32 - 1u32 / 10f32: u32 } -- cgit 1.4.1-3-g733a5 From 53493361925a1eba9226ba3f33bb1871962be169 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jan 2017 14:34:42 +1300 Subject: Refactor if/else formatting Removes else_if_brace_style from config options. Use control_brace_style instead. --- src/config.rs | 11 +- src/expr.rs | 516 +++++++++++---------- .../source/control-brace-style-always-next-line.rs | 2 +- .../source/control-brace-style-always-same-line.rs | 2 +- .../source/else-if-brace-style-always-next-line.rs | 2 +- .../source/else-if-brace-style-always-same-line.rs | 2 +- .../else-if-brace-style-closing-next-line.rs | 2 +- .../target/control-brace-style-always-next-line.rs | 3 +- .../target/control-brace-style-always-same-line.rs | 4 +- .../target/else-if-brace-style-always-next-line.rs | 2 +- .../target/else-if-brace-style-always-same-line.rs | 2 +- .../else-if-brace-style-closing-next-line.rs | 2 +- 12 files changed, 288 insertions(+), 262 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 641b8993fc5..0095e714f69 100644 --- a/src/config.rs +++ b/src/config.rs @@ -40,13 +40,6 @@ configuration_option_enum! { BraceStyle: } configuration_option_enum! { ControlBraceStyle: - // K&R/Stroustrup style, Rust community default - AlwaysSameLine, - // Allman style - AlwaysNextLine, -} - -configuration_option_enum! { ElseIfBraceStyle: // K&R style, Rust community default AlwaysSameLine, // Stroustrup style @@ -350,10 +343,8 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; - else_if_brace_style: ElseIfBraceStyle, ElseIfBraceStyle::AlwaysSameLine, - "Brace style for if, else if, and else constructs"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, - "Brace style for match, loop, for, and while constructs"; + "Brace style for control flow constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; diff --git a/src/expr.rs b/src/expr.rs index 3271cc3f299..b0b2315f1fe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -24,7 +24,7 @@ use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; use visitor::FmtVisitor; -use config::{Config, StructLitStyle, MultilineStyle, ElseIfBraceStyle, ControlBraceStyle}; +use config::{Config, StructLitStyle, MultilineStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::rewrite_path; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -110,41 +110,39 @@ fn format_expr(expr: &ast::Expr, offset) } ast::ExprKind::While(ref cond, ref block, label) => { - Loop::new_while(None, cond, block, label).rewrite(context, width, offset) + ControlFlow::new_while(None, cond, block, label, expr.span) + .rewrite(context, width, offset) } ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - Loop::new_while(Some(pat), cond, block, label).rewrite(context, width, offset) + ControlFlow::new_while(Some(pat), cond, block, label, expr.span) + .rewrite(context, width, offset) } ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - Loop::new_for(pat, cond, block, label).rewrite(context, width, offset) + ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, width, offset) } ast::ExprKind::Loop(ref block, label) => { - Loop::new_loop(block, label).rewrite(context, width, offset) + ControlFlow::new_loop(block, label, expr.span).rewrite(context, width, offset) } ast::ExprKind::Block(ref block) => block.rewrite(context, width, offset), ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { - rewrite_if_else(context, - cond, - expr_type, - if_block, - else_block.as_ref().map(|e| &**e), - expr.span, - None, - width, - offset, - true) + ControlFlow::new_if(cond, + None, + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span) + .rewrite(context, width, offset) } ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { - rewrite_if_else(context, - cond, - expr_type, - if_block, - else_block.as_ref().map(|e| &**e), - expr.span, - Some(pat), - width, - offset, - true) + ControlFlow::new_if(cond, + Some(pat), + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span) + .rewrite(context, width, offset) } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, width, offset, expr.span) @@ -679,72 +677,175 @@ impl Rewrite for ast::Stmt { } } -// Abstraction over for, while and loop expressions -struct Loop<'a> { +// Abstraction over control flow expressions +struct ControlFlow<'a> { cond: Option<&'a ast::Expr>, block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, label: Option, pat: Option<&'a ast::Pat>, keyword: &'a str, matcher: &'a str, connector: &'a str, + allow_single_line: bool, + // True if this is an `if` expression in an `else if` :-( hacky + nested_if: bool, + span: Span, } -impl<'a> Loop<'a> { - fn new_loop(block: &'a ast::Block, label: Option) -> Loop<'a> { - Loop { +impl<'a> ControlFlow<'a> { + fn new_if(cond: &'a ast::Expr, + pat: Option<&'a ast::Pat>, + block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, + allow_single_line: bool, + nested_if: bool, + span: Span) + -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block: block, + else_block: else_block, + label: None, + pat: pat, + keyword: "if", + matcher: match pat { + Some(..) => "let", + None => "", + }, + connector: " =", + allow_single_line: allow_single_line, + nested_if: nested_if, + span: span, + } + } + + fn new_loop(block: &'a ast::Block, + label: Option, + span: Span) + -> ControlFlow<'a> { + ControlFlow { cond: None, block: block, + else_block: None, label: label, pat: None, keyword: "loop", matcher: "", connector: "", + allow_single_line: false, + nested_if: false, + span: span, } } fn new_while(pat: Option<&'a ast::Pat>, cond: &'a ast::Expr, block: &'a ast::Block, - label: Option) - -> Loop<'a> { - Loop { + label: Option, + span: Span) + -> ControlFlow<'a> { + ControlFlow { cond: Some(cond), block: block, + else_block: None, label: label, pat: pat, - keyword: "while ", + keyword: "while", matcher: match pat { - Some(..) => "let ", + Some(..) => "let", None => "", }, connector: " =", + allow_single_line: false, + nested_if: false, + span: span, } } fn new_for(pat: &'a ast::Pat, cond: &'a ast::Expr, block: &'a ast::Block, - label: Option) - -> Loop<'a> { - Loop { + label: Option, + span: Span) + -> ControlFlow<'a> { + ControlFlow { cond: Some(cond), block: block, + else_block: None, label: label, pat: Some(pat), - keyword: "for ", + keyword: "for", matcher: "", connector: " in", + allow_single_line: false, + nested_if: false, + span: span, + } + } + + fn rewrite_single_line(&self, + pat_expr_str: &str, + context: &RewriteContext, + width: usize) + -> Option { + assert!(self.allow_single_line); + let else_block = try_opt!(self.else_block); + let fixed_cost = self.keyword.len() + " { } else { }".len(); + + if let ast::ExprKind::Block(ref else_node) = else_block.node { + if !is_simple_block(self.block, context.codemap) || + !is_simple_block(else_node, context.codemap) || + pat_expr_str.contains('\n') { + return None; + } + + let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); + let expr = &self.block.stmts[0]; + let if_str = try_opt!(expr.rewrite(context, new_width, Indent::empty())); + + let new_width = try_opt!(new_width.checked_sub(if_str.len())); + let else_expr = &else_node.stmts[0]; + let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::empty())); + + if if_str.contains('\n') || else_str.contains('\n') { + return None; + } + + let result = format!("{} {} {{ {} }} else {{ {} }}", + self.keyword, + pat_expr_str, + if_str, + else_str); + + if result.len() <= width { + return Some(result); + } } + + None } } -impl<'a> Rewrite for Loop<'a> { +impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + let (budget, indent) = if self.nested_if { + // We are part of an if-elseif-else chain. Our constraints are tightened. + // 7 = "} else " .len() + (try_opt!(width.checked_sub(7)), offset + 7) + } else { + (width, offset) + }; + let label_string = rewrite_label(self.label); - // 2 = " {".len() - let inner_width = try_opt!(width.checked_sub(self.keyword.len() + 2 + label_string.len())); - let inner_offset = offset + self.keyword.len() + label_string.len(); + // 1 = space after keyword. + let inner_offset = indent + self.keyword.len() + label_string.len() + 1; + let mut inner_width = + try_opt!(budget.checked_sub(self.keyword.len() + label_string.len() + 1)); + if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine { + // 2 = " {".len() + inner_width = try_opt!(inner_width.checked_sub(2)); + } let pat_expr_string = match self.cond { Some(cond) => { @@ -759,28 +860,131 @@ impl<'a> Rewrite for Loop<'a> { None => String::new(), }; - let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); - let block_sep = match context.config.control_brace_style { - ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), - ControlBraceStyle::AlwaysSameLine => " ", - }; + // Try to format if-else on single line. + if self.allow_single_line && context.config.single_line_if_else_max_width > 0 { + let trial = self.rewrite_single_line(&pat_expr_string, context, width); - // This is used only for the empty block case: `{}` + if trial.is_some() && + trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width { + return trial; + } + } + + // This is used only for the empty block case: `{}`. + // 2 = spaces after keyword and condition. let block_width = try_opt!(width.checked_sub(label_string.len() + self.keyword.len() + extra_offset(&pat_expr_string, inner_offset) + - 1)); - - // FIXME: this drops any comment between "loop" and the block. - self.block - .rewrite(context, block_width, offset) - .map(|result| { - format!("{}{}{}{}{}", - label_string, - self.keyword, - pat_expr_string, - block_sep, - result) - }) + 2)); + + let block_str = try_opt!(self.block.rewrite(context, block_width, offset)); + + let cond_span = if let Some(cond) = self.cond { + cond.span + } else { + mk_sp(self.block.span.lo, self.block.span.lo) + }; + + // for event in event + let between_kwd_cond = + mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), + self.pat.map_or(cond_span.lo, |p| if self.matcher.is_empty() { + p.span.lo + } else { + context.codemap.span_before(self.span, self.matcher.trim()) + })); + + let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, offset, width); + + let after_cond_comment = extract_comment(mk_sp(cond_span.hi, self.block.span.lo), + context, + offset, + width); + + let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { + "" + } else if context.config.control_brace_style == + ControlBraceStyle::AlwaysNextLine { + alt_block_sep.as_str() + } else { + " " + }; + + let mut result = format!("{}{}{}{}{}{}", + label_string, + self.keyword, + between_kwd_cond_comment.as_ref() + .map_or(if pat_expr_string.is_empty() { "" } else { " " }, + |s| &**s), + pat_expr_string, + after_cond_comment.as_ref().map_or(block_sep, |s| &**s), + block_str); + + if let Some(else_block) = self.else_block { + let mut last_in_chain = false; + let rewrite = match else_block.node { + // If the else expression is another if-else expression, prevent it + // from being formatted on a single line. + // Note how we're passing the original width and offset, as the + // cost of "else" should not cascade. + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { + ControlFlow::new_if(cond, + Some(pat), + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo, self.span.hi)) + .rewrite(context, width, offset) + } + ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { + ControlFlow::new_if(cond, + None, + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo, self.span.hi)) + .rewrite(context, width, offset) + } + _ => { + last_in_chain = true; + else_block.rewrite(context, width, offset) + } + }; + + let between_kwd_else_block = + mk_sp(self.block.span.hi, + context.codemap + .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else")); + let between_kwd_else_block_comment = + extract_comment(between_kwd_else_block, context, offset, width); + + let after_else = mk_sp(context.codemap + .span_after(mk_sp(self.block.span.hi, else_block.span.lo), + "else"), + else_block.span.lo); + let after_else_comment = extract_comment(after_else, context, offset, width); + + let between_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine | + ControlBraceStyle::ClosingNextLine => &*alt_block_sep, + ControlBraceStyle::AlwaysSameLine => " ", + }; + let after_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, + _ => " ", + }; + try_opt!(write!(&mut result, + "{}else{}", + between_kwd_else_block_comment.as_ref() + .map_or(between_sep, |s| &**s), + after_else_comment.as_ref().map_or(after_sep, |s| &**s)) + .ok()); + result.push_str(&try_opt!(rewrite)); + } + + Some(result) } } @@ -808,183 +1012,6 @@ fn extract_comment(span: Span, } } -// Rewrites if-else blocks. If let Some(_) = pat, the expression is -// treated as an if-let-else expression. -fn rewrite_if_else(context: &RewriteContext, - cond: &ast::Expr, - expr_type: ExprType, - if_block: &ast::Block, - else_block_opt: Option<&ast::Expr>, - span: Span, - pat: Option<&ast::Pat>, - width: usize, - offset: Indent, - allow_single_line: bool) - -> Option { - let (budget, indent) = if !allow_single_line { - // We are part of an if-elseif-else chain. Our constraints are tightened. - // 7 = "} else" .len() - (try_opt!(width.checked_sub(7)), offset + 7) - } else { - (width, offset) - }; - - // 3 = "if ", 2 = " {" - let pat_penalty = match context.config.else_if_brace_style { - ElseIfBraceStyle::AlwaysNextLine => 3, - _ => 3 + 2, - }; - let pat_expr_string = try_opt!(rewrite_pat_expr(context, - pat, - cond, - "let ", - " =", - try_opt!(budget.checked_sub(pat_penalty)), - indent + 3)); - - // Try to format if-else on single line. - if expr_type == ExprType::SubExpression && allow_single_line && - context.config.single_line_if_else_max_width > 0 { - let trial = single_line_if_else(context, &pat_expr_string, if_block, else_block_opt, width); - - if trial.is_some() && - trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width { - return trial; - } - } - - let if_block_string = try_opt!(if_block.rewrite(context, width, offset)); - - let between_if_cond = mk_sp(context.codemap.span_after(span, "if"), - pat.map_or(cond.span.lo, - |_| context.codemap.span_before(span, "let"))); - - let between_if_cond_comment = extract_comment(between_if_cond, context, offset, width); - - let after_cond_comment = extract_comment(mk_sp(cond.span.hi, if_block.span.lo), - context, - offset, - width); - - let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); - let after_sep = match context.config.else_if_brace_style { - ElseIfBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), - _ => " ", - }; - let mut result = format!("if{}{}{}{}", - between_if_cond_comment.as_ref().map_or(" ", |str| &**str), - pat_expr_string, - after_cond_comment.as_ref().map_or(after_sep, |str| &**str), - if_block_string); - - if let Some(else_block) = else_block_opt { - let mut last_in_chain = false; - let rewrite = match else_block.node { - // If the else expression is another if-else expression, prevent it - // from being formatted on a single line. - // Note how we're passing the original width and offset, as the - // cost of "else" should not cascade. - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { - rewrite_if_else(context, - cond, - expr_type, - if_block, - next_else_block.as_ref().map(|e| &**e), - mk_sp(else_block.span.lo, span.hi), - Some(pat), - width, - offset, - false) - } - ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { - rewrite_if_else(context, - cond, - expr_type, - if_block, - next_else_block.as_ref().map(|e| &**e), - mk_sp(else_block.span.lo, span.hi), - None, - width, - offset, - false) - } - _ => { - last_in_chain = true; - else_block.rewrite(context, width, offset) - } - }; - - let between_if_else_block = - mk_sp(if_block.span.hi, - context.codemap.span_before(mk_sp(if_block.span.hi, else_block.span.lo), "else")); - let between_if_else_block_comment = - extract_comment(between_if_else_block, context, offset, width); - - let after_else = mk_sp(context.codemap - .span_after(mk_sp(if_block.span.hi, else_block.span.lo), - "else"), - else_block.span.lo); - let after_else_comment = extract_comment(after_else, context, offset, width); - - let between_sep = match context.config.else_if_brace_style { - ElseIfBraceStyle::AlwaysNextLine | - ElseIfBraceStyle::ClosingNextLine => alt_block_sep.as_str(), - ElseIfBraceStyle::AlwaysSameLine => " ", - }; - let after_sep = match context.config.else_if_brace_style { - ElseIfBraceStyle::AlwaysNextLine if last_in_chain => alt_block_sep.as_str(), - _ => " ", - }; - try_opt!(write!(&mut result, - "{}else{}", - between_if_else_block_comment.as_ref() - .map_or(between_sep, |str| &**str), - after_else_comment.as_ref().map_or(after_sep, |str| &**str)) - .ok()); - result.push_str(&try_opt!(rewrite)); - } - - Some(result) -} - -fn single_line_if_else(context: &RewriteContext, - pat_expr_str: &str, - if_node: &ast::Block, - else_block_opt: Option<&ast::Expr>, - width: usize) - -> Option { - let else_block = try_opt!(else_block_opt); - let fixed_cost = "if { } else { }".len(); - - if let ast::ExprKind::Block(ref else_node) = else_block.node { - if !is_simple_block(if_node, context.codemap) || - !is_simple_block(else_node, context.codemap) || pat_expr_str.contains('\n') { - return None; - } - - let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); - let if_expr = &if_node.stmts[0]; - let if_str = try_opt!(if_expr.rewrite(context, new_width, Indent::empty())); - - let new_width = try_opt!(new_width.checked_sub(if_str.len())); - let else_expr = &else_node.stmts[0]; - let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::empty())); - - // FIXME: this check shouldn't be necessary. Rewrites should either fail - // or wrap to a newline when the object does not fit the width. - let fits_line = fixed_cost + pat_expr_str.len() + if_str.len() + else_str.len() <= width; - - if fits_line && !if_str.contains('\n') && !else_str.contains('\n') { - return Some(format!("if {} {{ {} }} else {{ {} }}", - pat_expr_str, - if_str, - else_str)); - } - } - - None -} - fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { let snippet = codemap.span_to_snippet(block.span).unwrap(); contains_comment(&snippet) @@ -1079,7 +1106,7 @@ fn rewrite_match(context: &RewriteContext, let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysSameLine => " ", - ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + _ => alt_block_sep.as_str(), }; let mut result = format!("match {}{}{{", cond_str, block_sep); @@ -1299,7 +1326,7 @@ impl Rewrite for ast::Arm { let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n", - ControlBraceStyle::AlwaysSameLine => String::from(" ") + body_prefix + "\n", + _ => String::from(" ") + body_prefix + "\n", }; Some(format!("{}{} =>{}{}{}\n{}{}", attr_str.trim_left(), @@ -1369,10 +1396,15 @@ fn rewrite_pat_expr(context: &RewriteContext, width: usize, offset: Indent) -> Option { - let pat_offset = offset + matcher.len(); let mut result = match pat { Some(pat) => { + let matcher = if matcher.is_empty() { + matcher.to_owned() + } else { + format!("{} ", matcher) + }; let pat_budget = try_opt!(width.checked_sub(connector.len() + matcher.len())); + let pat_offset = offset + matcher.len(); let pat_string = try_opt!(pat.rewrite(context, pat_budget, pat_offset)); format!("{}{}{}", matcher, pat_string, connector) } diff --git a/tests/source/control-brace-style-always-next-line.rs b/tests/source/control-brace-style-always-next-line.rs index 9a2ec04e300..9079fb46c0c 100644 --- a/tests/source/control-brace-style-always-next-line.rs +++ b/tests/source/control-brace-style-always-next-line.rs @@ -7,7 +7,7 @@ fn main() { } - 'loop_label: loop // loop comment + 'label: loop // loop comment { (); } diff --git a/tests/source/control-brace-style-always-same-line.rs b/tests/source/control-brace-style-always-same-line.rs index 52b0c8fdc46..1c8f487e7cd 100644 --- a/tests/source/control-brace-style-always-same-line.rs +++ b/tests/source/control-brace-style-always-same-line.rs @@ -7,7 +7,7 @@ fn main() { } - 'loop_label: loop // loop comment + 'label: loop // loop comment { (); } diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/tests/source/else-if-brace-style-always-next-line.rs index 768aa1fe3c0..12208dd7c8b 100644 --- a/tests/source/else-if-brace-style-always-next-line.rs +++ b/tests/source/else-if-brace-style-always-next-line.rs @@ -1,5 +1,5 @@ // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-else_if_brace_style: AlwaysNextLine +// rustfmt-control_brace_style: AlwaysNextLine fn main() { if false diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/tests/source/else-if-brace-style-always-same-line.rs index 7f8a3f1a3c4..c844275ef5b 100644 --- a/tests/source/else-if-brace-style-always-same-line.rs +++ b/tests/source/else-if-brace-style-always-same-line.rs @@ -1,5 +1,5 @@ // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-else_if_brace_style: AlwaysSameLine +// rustfmt-control_brace_style: AlwaysSameLine fn main() { if false diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/tests/source/else-if-brace-style-closing-next-line.rs index 8784d7c08d7..ccc8d7b0f3f 100644 --- a/tests/source/else-if-brace-style-closing-next-line.rs +++ b/tests/source/else-if-brace-style-closing-next-line.rs @@ -1,5 +1,5 @@ // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-else_if_brace_style: ClosingNextLine +// rustfmt-control_brace_style: ClosingNextLine fn main() { if false diff --git a/tests/target/control-brace-style-always-next-line.rs b/tests/target/control-brace-style-always-next-line.rs index 534dfb89969..07f46fa6163 100644 --- a/tests/target/control-brace-style-always-next-line.rs +++ b/tests/target/control-brace-style-always-next-line.rs @@ -8,7 +8,8 @@ fn main() { } - 'loop_label: loop + 'label: loop + // loop comment { (); } diff --git a/tests/target/control-brace-style-always-same-line.rs b/tests/target/control-brace-style-always-same-line.rs index 60a07e46986..d88ae5a2c2d 100644 --- a/tests/target/control-brace-style-always-same-line.rs +++ b/tests/target/control-brace-style-always-same-line.rs @@ -7,7 +7,9 @@ fn main() { } - 'loop_label: loop { + 'label: loop + // loop comment + { (); } diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs index e14bf7d0182..4a2ef877b85 100644 --- a/tests/target/else-if-brace-style-always-next-line.rs +++ b/tests/target/else-if-brace-style-always-next-line.rs @@ -1,5 +1,5 @@ // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-else_if_brace_style: AlwaysNextLine +// rustfmt-control_brace_style: AlwaysNextLine fn main() { if false diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs index e98d9bfc811..9baaa3f9b36 100644 --- a/tests/target/else-if-brace-style-always-same-line.rs +++ b/tests/target/else-if-brace-style-always-same-line.rs @@ -1,5 +1,5 @@ // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-else_if_brace_style: AlwaysSameLine +// rustfmt-control_brace_style: AlwaysSameLine fn main() { if false { diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs index 7978e372449..f1af1943431 100644 --- a/tests/target/else-if-brace-style-closing-next-line.rs +++ b/tests/target/else-if-brace-style-closing-next-line.rs @@ -1,5 +1,5 @@ // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-else_if_brace_style: ClosingNextLine +// rustfmt-control_brace_style: ClosingNextLine fn main() { if false { -- cgit 1.4.1-3-g733a5 From 846d7ad387f6866571da305c84d31bc5c0bf4818 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 16 Jan 2017 14:50:27 +1300 Subject: make rustfmt-normalize_comments false by default --- src/config.rs | 2 +- tests/source/chains-visual.rs | 1 + tests/source/chains.rs | 1 + tests/source/closure.rs | 1 + tests/source/comment.rs | 1 + tests/source/comment4.rs | 2 -- tests/source/comment5.rs | 1 + tests/source/comment_crlf_newline.rs | 1 + tests/source/expr.rs | 1 + tests/source/extern.rs | 1 + tests/source/fn-custom-7.rs | 1 + tests/source/fn-simple.rs | 1 + tests/source/fn_args_layout-block.rs | 1 + tests/source/hard-tabs.rs | 1 + tests/source/impls.rs | 1 + tests/source/imports.rs | 2 ++ tests/source/issue-1021.rs | 1 + tests/source/issue-1216.rs | 1 + tests/source/issue-447.rs | 2 ++ tests/source/issue-977.rs | 1 + tests/source/macros.rs | 1 + tests/source/match.rs | 1 + tests/source/multiple.rs | 1 + tests/source/pattern-condense-wildcards.rs | 1 + tests/source/struct_lits.rs | 1 + tests/source/struct_lits_multiline.rs | 1 + tests/source/struct_lits_visual.rs | 1 + tests/source/struct_lits_visual_multiline.rs | 1 + tests/source/structs.rs | 1 + tests/source/type.rs | 1 + tests/source/type_alias.rs | 1 + tests/target/chains-visual.rs | 1 + tests/target/chains.rs | 1 + tests/target/closure.rs | 1 + tests/target/comment.rs | 1 + tests/target/comment4.rs | 2 -- tests/target/comment5.rs | 1 + tests/target/comment_crlf_newline.rs | 1 + tests/target/expr.rs | 1 + tests/target/extern.rs | 1 + tests/target/fn-custom-7.rs | 1 + tests/target/fn-simple.rs | 1 + tests/target/fn_args_layout-block.rs | 1 + tests/target/hard-tabs.rs | 1 + tests/target/impls.rs | 1 + tests/target/imports.rs | 2 ++ tests/target/issue-1021.rs | 1 + tests/target/issue-1216.rs | 1 + tests/target/issue-447.rs | 2 ++ tests/target/issue-977.rs | 1 + tests/target/macros.rs | 1 + tests/target/match.rs | 1 + tests/target/multiple.rs | 1 + tests/target/pattern-condense-wildcards.rs | 1 + tests/target/struct_lits.rs | 1 + tests/target/struct_lits_multiline.rs | 1 + tests/target/struct_lits_visual.rs | 1 + tests/target/struct_lits_visual_multiline.rs | 1 + tests/target/structs.rs | 1 + tests/target/type.rs | 1 + tests/target/type_alias.rs | 1 + 61 files changed, 63 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 0095e714f69..b974de703bb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -393,7 +393,7 @@ create_config! { take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; - normalize_comments: bool, true, "Convert /* */ comments to // comments where possible"; + normalize_comments: bool, false, "Convert /* */ comments to // comments where possible"; wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs index bd365ce9a4c..cc9899fcc60 100644 --- a/tests/source/chains-visual.rs +++ b/tests/source/chains-visual.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_indent: Visual // rustfmt-chain_base_indent: Visual diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 39d3c65d9b7..de5c3e6e823 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // Test chain formatting. diff --git a/tests/source/closure.rs b/tests/source/closure.rs index 0a0dd717586..b95f961405a 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // Closures fn main() { diff --git a/tests/source/comment.rs b/tests/source/comment.rs index e461a2041ff..0f76f220582 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true //! Doc comment diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index 0ed18ca8da1..38442a79360 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -1,5 +1,3 @@ -// rustfmt-normalize_comments: false - //! Doc comment fn test() { // comment diff --git a/tests/source/comment5.rs b/tests/source/comment5.rs index 87a26f353a7..02dbac8e4f4 100644 --- a/tests/source/comment5.rs +++ b/tests/source/comment5.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true //@ special comment diff --git a/tests/source/comment_crlf_newline.rs b/tests/source/comment_crlf_newline.rs index 189a7053179..7a65f762f6c 100644 --- a/tests/source/comment_crlf_newline.rs +++ b/tests/source/comment_crlf_newline.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true /* Block comments followed by CRLF newlines should not an extra newline at the end */ /* Something else */ diff --git a/tests/source/expr.rs b/tests/source/expr.rs index f9a0251910c..c0d1e3477e0 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // Test expressions diff --git a/tests/source/extern.rs b/tests/source/extern.rs index 347612dd8f1..1dd1df2b74e 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true extern "C" { fn c_func(x: *mut *mut libc::c_void); diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index 27c97867d26..1cbcd211808 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-fn_args_layout: BlockAlways // rustfmt-fn_args_density: Vertical // rustfmt-fn_arg_indent: Tabbed diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 044d494bd37..1764266718e 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ ,response: NoWay /* hose */) { diff --git a/tests/source/fn_args_layout-block.rs b/tests/source/fn_args_layout-block.rs index b87158a4d7f..be22369ab8c 100644 --- a/tests/source/fn_args_layout-block.rs +++ b/tests/source/fn_args_layout-block.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-fn_args_layout: Block fn foo() { diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs index c19d5d4c01f..8374b1e70ed 100644 --- a/tests/source/hard-tabs.rs +++ b/tests/source/hard-tabs.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // rustfmt-wrap_comments: true // rustfmt-hard_tabs: true diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 978ac8cc313..aac87a1227f 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true impl Foo for Bar { fn foo() { "hi" } } pub impl Foo for Bar { diff --git a/tests/source/imports.rs b/tests/source/imports.rs index 4296a152f4e..adeeba02338 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -1,3 +1,5 @@ +// rustfmt-normalize_comments: true + // Imports. // Long import. diff --git a/tests/source/issue-1021.rs b/tests/source/issue-1021.rs index 2c1b4716f57..380e24cc0b0 100644 --- a/tests/source/issue-1021.rs +++ b/tests/source/issue-1021.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { match x { S(true , .., true ) => (), diff --git a/tests/source/issue-1216.rs b/tests/source/issue-1216.rs index da5f3471f72..d727c158ab8 100644 --- a/tests/source/issue-1216.rs +++ b/tests/source/issue-1216.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true enum E { A, //* I am not a block comment (caused panic) B, diff --git a/tests/source/issue-447.rs b/tests/source/issue-447.rs index cc713af3f18..7c542cb58c2 100644 --- a/tests/source/issue-447.rs +++ b/tests/source/issue-447.rs @@ -1,3 +1,5 @@ +// rustfmt-normalize_comments: true + fn main() { if /* shouldn't be dropped shouldn't be dropped */ diff --git a/tests/source/issue-977.rs b/tests/source/issue-977.rs index dc2663d581b..b028b36a055 100644 --- a/tests/source/issue-977.rs +++ b/tests/source/issue-977.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // FIXME(#919) trait NameC { /* comment */ } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 5b6eb53daec..1c4fd138820 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true itemmacro!(this, is.now() .formatted(yay)); itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); diff --git a/tests/source/match.rs b/tests/source/match.rs index a9fb5404047..2fb584c322c 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // Match expressions. fn foo() { diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 863d20f50ea..fe8cc1787f2 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // Test of lots of random stuff. // FIXME split this into multiple, self-contained tests. diff --git a/tests/source/pattern-condense-wildcards.rs b/tests/source/pattern-condense-wildcards.rs index bac712528dc..5f84aea0a6b 100644 --- a/tests/source/pattern-condense-wildcards.rs +++ b/tests/source/pattern-condense-wildcards.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-condense_wildcard_suffices: true fn main() { diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 1341983ed0f..8d762eed980 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // Struct literal expressions. diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs index dc0470b1447..120cc93471a 100644 --- a/tests/source/struct_lits_multiline.rs +++ b/tests/source/struct_lits_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-struct_lit_multiline_style: ForceMulti diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index c7534eff7cb..1ea26522ea7 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs index 58be4da68ad..57714ed989b 100644 --- a/tests/source/struct_lits_visual_multiline.rs +++ b/tests/source/struct_lits_visual_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual // rustfmt-struct_lit_multiline_style: ForceMulti diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 5a13d59f572..cdcccda39a5 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true /// A Doc comment diff --git a/tests/source/type.rs b/tests/source/type.rs index 75c156455f9..0a46ffb2ee4 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn types() { let x: [ Vec < _ > ] = []; let y: * mut [ SomeType ; konst_funk() ] = expr(); diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs index 93e155534ec..7c0b500c753 100644 --- a/tests/source/type_alias.rs +++ b/tests/source/type_alias.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 472532676c5..3ece67291da 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_indent: Visual // rustfmt-chain_base_indent: Visual diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 726dbac155f..488d64afacd 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // Test chain formatting. diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 101f3ea961c..bc4d03981d5 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // Closures fn main() { diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 9577ff22b60..71ef6acf99a 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true //! Doc comment diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index 910bade6c88..ff71124f464 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -1,5 +1,3 @@ -// rustfmt-normalize_comments: false - //! Doc comment fn test() { // comment diff --git a/tests/target/comment5.rs b/tests/target/comment5.rs index 7006b35efed..2ca371060d5 100644 --- a/tests/target/comment5.rs +++ b/tests/target/comment5.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true //@ special comment diff --git a/tests/target/comment_crlf_newline.rs b/tests/target/comment_crlf_newline.rs index 3b19b01a7eb..aab9e94d9e6 100644 --- a/tests/target/comment_crlf_newline.rs +++ b/tests/target/comment_crlf_newline.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // Block comments followed by CRLF newlines should not an extra newline at the end // Something else diff --git a/tests/target/expr.rs b/tests/target/expr.rs index ec9c6f10f5f..38007e31f1e 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // Test expressions diff --git a/tests/target/extern.rs b/tests/target/extern.rs index e25e8b01cd4..06d9d771e79 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true extern "C" { fn c_func(x: *mut *mut libc::c_void); diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 82260d8c863..1ae9f4ea896 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-fn_args_layout: BlockAlways // rustfmt-fn_args_density: Vertical // rustfmt-fn_arg_indent: Tabbed diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 17a3ac0fe15..4bcbbd6613f 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn simple(// pre-comment on a function!? i: i32, // yes, it's possible! diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index cf380c649c8..728dc0b1598 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-fn_args_layout: Block fn foo() { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index d3adae03481..c48f43581f9 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // rustfmt-wrap_comments: true // rustfmt-hard_tabs: true diff --git a/tests/target/impls.rs b/tests/target/impls.rs index dee683d18b1..6f7990926fd 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true impl Foo for Bar { fn foo() { "hi" diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 0be8f2c35e0..4e7627dd1b9 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -1,3 +1,5 @@ +// rustfmt-normalize_comments: true + // Imports. // Long import. diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs index e4379855642..cc85aa73cae 100644 --- a/tests/target/issue-1021.rs +++ b/tests/target/issue-1021.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { match x { S(true, .., true) => (), diff --git a/tests/target/issue-1216.rs b/tests/target/issue-1216.rs index da5f3471f72..d727c158ab8 100644 --- a/tests/target/issue-1216.rs +++ b/tests/target/issue-1216.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true enum E { A, //* I am not a block comment (caused panic) B, diff --git a/tests/target/issue-447.rs b/tests/target/issue-447.rs index 7e69c708eb7..7c1d370d0e8 100644 --- a/tests/target/issue-447.rs +++ b/tests/target/issue-447.rs @@ -1,3 +1,5 @@ +// rustfmt-normalize_comments: true + fn main() { if // shouldn't be dropped diff --git a/tests/target/issue-977.rs b/tests/target/issue-977.rs index ad7c2bd4e5c..9420054449d 100644 --- a/tests/target/issue-977.rs +++ b/tests/target/issue-977.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // FIXME(#919) trait NameC { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index e5a0fc9731c..66bf4d33a98 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true itemmacro!(this, is.now().formatted(yay)); itemmacro!(really, diff --git a/tests/target/match.rs b/tests/target/match.rs index bc5556283c3..e6c680f3cb7 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // Match expressions. fn foo() { diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index e29bb259ece..d2a736330f7 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // Test of lots of random stuff. // FIXME split this into multiple, self-contained tests. diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs index 96519cf3d44..ebf89c582ff 100644 --- a/tests/target/pattern-condense-wildcards.rs +++ b/tests/target/pattern-condense-wildcards.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-condense_wildcard_suffices: true fn main() { diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index c8b475df24f..5ab8de3f235 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // Struct literal expressions. diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index 91ead9e764a..0eb7b8b759f 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-struct_lit_multiline_style: ForceMulti diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 3a3aa35bb16..a9c682af15b 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs index f233b24c213..30d8815514b 100644 --- a/tests/target/struct_lits_visual_multiline.rs +++ b/tests/target/struct_lits_visual_multiline.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-struct_lit_style: Visual // rustfmt-struct_lit_multiline_style: ForceMulti diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 3d3b20a9ad6..40b410c072b 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-wrap_comments: true /// A Doc comment diff --git a/tests/target/type.rs b/tests/target/type.rs index f9afb8aed02..c002d3c2c67 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn types() { let x: [Vec<_>] = []; let y: *mut [SomeType; konst_funk()] = expr(); diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index 16c77b273c1..42600aa3ae5 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); -- cgit 1.4.1-3-g733a5 From d9484853711132c56528afb91221fe04af529e35 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 16 Jan 2017 16:37:58 +1300 Subject: Allow empty blocks on one line in more places In particular if they contain only a single-line comment. Fixes #493 --- src/expr.rs | 32 +++++++++++++++++++++++++------- tests/source/chains-visual.rs | 4 ++-- tests/source/chains.rs | 4 ++-- tests/target/chains-visual.rs | 6 ++++-- tests/target/chains.rs | 6 ++++-- tests/target/expr.rs | 17 +++++------------ tests/target/hard-tabs.rs | 3 +-- tests/target/issue-447.rs | 3 +-- tests/target/match.rs | 4 +--- 9 files changed, 45 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b0b2315f1fe..9794ff78093 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cmp::Ordering; +use std::cmp::{Ordering, min}; use std::borrow::Borrow; use std::mem::swap; use std::ops::Deref; @@ -595,9 +595,19 @@ impl Rewrite for ast::Block { // width is used only for the single line case: either the empty block `{}`, // or an unsafe expression `unsafe { e }`. + if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) && width >= 2 { + return Some("{}".to_owned()); + } + + // If a block contains only a single-line comment, then leave it on one line. let user_str = context.snippet(self.span); - if user_str == "{}" && width >= 2 { - return Some(user_str); + let user_str = user_str.trim(); + if user_str.starts_with('{') && user_str.ends_with('}') { + let comment_str = user_str[1..user_str.len() - 1].trim(); + if self.stmts.is_empty() && !comment_str.contains('\n') && + !comment_str.starts_with("//") && comment_str.len() + 4 <= width { + return Some(format!("{{ {} }}", comment_str)); + } } let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); @@ -870,11 +880,17 @@ impl<'a> Rewrite for ControlFlow<'a> { } } - // This is used only for the empty block case: `{}`. + // This is used only for the empty block case: `{}`. So, we use 1 if we know + // we should avoid the single line case. // 2 = spaces after keyword and condition. let block_width = try_opt!(width.checked_sub(label_string.len() + self.keyword.len() + extra_offset(&pat_expr_string, inner_offset) + 2)); + let block_width = if self.else_block.is_some() || self.nested_if { + min(1, block_width) + } else { + block_width + }; let block_str = try_opt!(self.block.rewrite(context, block_width, offset)); @@ -949,7 +965,9 @@ impl<'a> Rewrite for ControlFlow<'a> { } _ => { last_in_chain = true; - else_block.rewrite(context, width, offset) + // When rewriting a block, the width is only used for single line + // blocks, passing 1 lets us avoid that. + else_block.rewrite(context, min(1, width), offset) } }; @@ -1021,8 +1039,8 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { // FIXME: incorrectly returns false when comment is contained completely within // the expression. pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && - !block_contains_comment(block, codemap) + (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && + !block_contains_comment(block, codemap)) } /// Checks whether a block contains at most one statement or expression, and no comments. diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs index cc9899fcc60..ea7eeb60524 100644 --- a/tests/source/chains-visual.rs +++ b/tests/source/chains-visual.rs @@ -95,11 +95,11 @@ fn floaters() { .bar() .baz(); - Foo { x: val } .baz(|| { /*force multiline */ }) .quux(); + Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); Foo { y: i_am_multi_line, z: ok } .baz(|| { - // force multiline + force(); multiline(); }) .quux(); diff --git a/tests/source/chains.rs b/tests/source/chains.rs index de5c3e6e823..7fcda72d83d 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -93,11 +93,11 @@ fn floaters() { .bar() .baz(); - Foo { x: val } .baz(|| { /*force multiline */ }) .quux(); + Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); Foo { y: i_am_multi_line, z: ok } .baz(|| { - // force multiline + force(); multiline(); }) .quux(); diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 3ece67291da..aff6f170529 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -105,7 +105,8 @@ fn floaters() { Foo { x: val } .baz(|| { - // force multiline + force(); + multiline(); }) .quux(); @@ -114,7 +115,8 @@ fn floaters() { z: ok, } .baz(|| { - // force multiline + force(); + multiline(); }) .quux(); diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 488d64afacd..d9e7d3a58fe 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -102,7 +102,8 @@ fn floaters() { Foo { x: val } .baz(|| { - // force multiline + force(); + multiline(); }) .quux(); @@ -111,7 +112,8 @@ fn floaters() { z: ok, } .baz(|| { - // force multiline + force(); + multiline(); }) .quux(); diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 38007e31f1e..6b1ae7ec555 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -60,8 +60,7 @@ fn foo() -> bool { 1111 + 2222 {} if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { - } + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {} let test = if true { 5 } else { 3 }; @@ -136,12 +135,8 @@ fn baz() { fn qux() { {} // FIXME this one could be done better. - { - // a block with a comment - } - { - - } + { /* a block with a comment */ } + {} { // A block with a comment. } @@ -293,12 +288,10 @@ fn complex_if_else() { fn issue1106() { { if let hir::ItemEnum(ref enum_def, ref generics) = - self.ast_map.expect_item(enum_node_id).node { - } + self.ast_map.expect_item(enum_node_id).node {} } for entry in WalkDir::new(path) .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) { - } + .filter_entry(|entry| exclusions.filter_entry(entry)) {} } diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index c48f43581f9..43b00774a22 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -31,8 +31,7 @@ fn main() { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { - } + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {} if cond() { something(); diff --git a/tests/target/issue-447.rs b/tests/target/issue-447.rs index 7c1d370d0e8..d41cdb65cd0 100644 --- a/tests/target/issue-447.rs +++ b/tests/target/issue-447.rs @@ -36,6 +36,5 @@ fn main() { let Some(x) = y // shouldn't be dropped // shouldn't be dropped - { - } + {} } diff --git a/tests/target/match.rs b/tests/target/match.rs index e6c680f3cb7..7ebffdc2889 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -78,9 +78,7 @@ fn main() { }; match x { - y => { - // Block with comment. Preserve me. - } + y => { /*Block with comment. Preserve me.*/ } z => { stmt(); } -- cgit 1.4.1-3-g733a5 From 0218a41d73f3fa0be4f2952c4a903f91072823c4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 16 Jan 2017 17:58:51 +1300 Subject: Add a more lightweight method for rewriting comments when we are not normalising Fixes #652 --- src/comment.rs | 64 +++++++++++++++++++++++++++++------------ tests/config/issue-1124.toml | 1 + tests/source/doc.rs | 1 + tests/source/imports-reorder.rs | 1 + tests/source/issue-1177.rs | 1 + tests/source/paths.rs | 1 + tests/source/pattern.rs | 1 + tests/target/doc.rs | 1 + tests/target/imports-reorder.rs | 1 + tests/target/issue-1177.rs | 1 + tests/target/paths.rs | 1 + tests/target/pattern.rs | 1 + 12 files changed, 56 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index f831a039b95..8eaf2b2fb4f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -38,9 +38,21 @@ pub fn rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option { - let s = orig.trim(); + // If there are lines without a starting sigil, we won't format them correctly + // so in that case we won't even re-align (if !config.normalize_comments) and + // we should stop now. + let num_bare_lines = orig.lines() + .map(|line| line.trim()) + .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) + .count(); + if num_bare_lines > 0 && !config.normalize_comments { + return Some(orig.to_owned()); + } + + if !config.normalize_comments && !config.wrap_comments { + return light_rewrite_comment(orig, offset, config); + } - // Edge case: block comments. Let's not trim their lines (for now). let (opener, closer, line_start) = if block_style { ("/* ", " */", " * ") @@ -74,7 +86,7 @@ pub fn rewrite_comment(orig: &str, }; let max_chars = width.checked_sub(closer.len() + opener.len()).unwrap_or(1); - + let indent_str = offset.to_string(config); let fmt = StringFormat { opener: "", closer: "", @@ -86,29 +98,17 @@ pub fn rewrite_comment(orig: &str, config: config, }; - let indent_str = offset.to_string(config); - let line_breaks = s.chars().filter(|&c| c == '\n').count(); - - let num_bare_lines = s.lines() - .enumerate() - .map(|(_, line)| line.trim()) - .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) - .count(); - - if num_bare_lines > 0 && !config.normalize_comments { - return Some(orig.to_owned()); - } - - let lines = s.lines() + let line_breaks = orig.trim_right().chars().filter(|&c| c == '\n').count(); + let lines = orig.lines() .enumerate() .map(|(i, mut line)| { line = line.trim(); // Drop old closer. if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = &line[..(line.len() - 2)]; + line = &line[..(line.len() - 2)].trim_right(); } - line.trim_right() + line }) .map(left_trim_comment_line) .map(|line| if orig.starts_with("/*") && line_breaks == 0 { @@ -150,6 +150,31 @@ pub fn rewrite_comment(orig: &str, Some(result) } +/// Trims whitespace and aligns to indent, but otherwise does not change comments. +fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option { + let lines: Vec<&str> = orig.lines() + .map(|l| { + // This is basically just l.trim(), but in the case that a line starts + // with `*` we want to leave one space before it, so it aligns with the + // `*` in `/*`. + let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); + if let Some(fnw) = first_non_whitespace { + if l.as_bytes()[fnw] == '*' as u8 && fnw > 0 { + &l[fnw - 1..] + } else { + &l[fnw..] + } + } else { + "" + } + .trim_right() + }) + .collect(); + Some(lines.join(&format!("\n{}", offset.to_string(config)))) +} + +/// Trims comment characters and possibly a single space from the left of a string. +/// Does not trim all whitespace. fn left_trim_comment_line(line: &str) -> &str { if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || line.starts_with("/** ") { @@ -708,6 +733,7 @@ mod test { fn format_comments() { let mut config: ::config::Config = Default::default(); config.wrap_comments = true; + config.normalize_comments = true; let comment = rewrite_comment(" //test", true, 100, Indent::new(0, 100), &config).unwrap(); assert_eq!("/* test */", comment); diff --git a/tests/config/issue-1124.toml b/tests/config/issue-1124.toml index 44148a2d3c3..ca318207235 100644 --- a/tests/config/issue-1124.toml +++ b/tests/config/issue-1124.toml @@ -1 +1,2 @@ reorder_imports = true +normalize_comments = true diff --git a/tests/source/doc.rs b/tests/source/doc.rs index f325337c758..e03933e4516 100644 --- a/tests/source/doc.rs +++ b/tests/source/doc.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // sadfsdfa //sdffsdfasdf diff --git a/tests/source/imports-reorder.rs b/tests/source/imports-reorder.rs index 4ad9e4b08d3..200cad2d13c 100644 --- a/tests/source/imports-reorder.rs +++ b/tests/source/imports-reorder.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-reorder_imported_names: true use path::{C,/*A*/ A, B /* B */, self /* self */}; diff --git a/tests/source/issue-1177.rs b/tests/source/issue-1177.rs index 053c73267fc..3ac423c5aef 100644 --- a/tests/source/issue-1177.rs +++ b/tests/source/issue-1177.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { // Line Comment /* Block Comment */ diff --git a/tests/source/paths.rs b/tests/source/paths.rs index af61ba89b1c..ebc26f146e4 100644 --- a/tests/source/paths.rs +++ b/tests/source/paths.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { let constellation_chan = Constellation:: ::start( diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 75f65806167..a6c25225db2 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { let z = match x { "pat1" => 1, diff --git a/tests/target/doc.rs b/tests/target/doc.rs index 9e883c50afa..99d2ae7873f 100644 --- a/tests/target/doc.rs +++ b/tests/target/doc.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // sadfsdfa // sdffsdfasdf diff --git a/tests/target/imports-reorder.rs b/tests/target/imports-reorder.rs index 32b5ee156cc..fbdef3630e8 100644 --- a/tests/target/imports-reorder.rs +++ b/tests/target/imports-reorder.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true // rustfmt-reorder_imported_names: true use path::{self /* self */, /* A */ A, B /* B */, C}; diff --git a/tests/target/issue-1177.rs b/tests/target/issue-1177.rs index 377540e1bfe..dcda3972814 100644 --- a/tests/target/issue-1177.rs +++ b/tests/target/issue-1177.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { // Line Comment // Block Comment diff --git a/tests/target/paths.rs b/tests/target/paths.rs index adae879e647..6535463ebe3 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { let constellation_chan = diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index d77cb59f498..b809253aa85 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -1,3 +1,4 @@ +// rustfmt-normalize_comments: true fn main() { let z = match x { "pat1" => 1, -- cgit 1.4.1-3-g733a5 From 29e89136957b9eedf54255c8059f8a51fbd82a68 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 17 Jan 2017 12:01:10 +1300 Subject: Fix bug in identifying comments Fixes 1233 --- src/expr.rs | 4 ++-- src/missed_spans.rs | 12 ++++++++---- tests/source/comment.rs | 1 + tests/source/comment4.rs | 1 + tests/target/comment.rs | 9 +++++---- tests/target/comment4.rs | 5 +++-- tests/target/multiple.rs | 2 +- 7 files changed, 21 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9794ff78093..2fc6b8b86d2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -359,9 +359,9 @@ pub fn rewrite_array<'a, I>(expr_iter: I, where I: Iterator { let bracket_size = if context.config.spaces_within_square_brackets { - 2 // "[ " + 2 // "[ " } else { - 1 // "[" + 1 // "[" }; let offset = offset + bracket_size; let inner_context = &RewriteContext { block_indent: offset, ..*context }; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 9caea864641..d9c2a771414 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -123,16 +123,20 @@ impl<'a> FmtVisitor<'a> { let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - if rewrite_next_comment && fix_indent { - if let Some('{') = last_char { - self.buffer.push_str("\n"); + if rewrite_next_comment { + if fix_indent { + if let Some('{') = last_char { + self.buffer.push_str("\n"); + } + self.buffer.push_str(&self.block_indent.to_string(self.config)); + } else { + self.buffer.push_str(" "); } let comment_width = ::std::cmp::min(self.config.ideal_width, self.config.max_width - self.block_indent.width()); - self.buffer.push_str(&self.block_indent.to_string(self.config)); self.buffer.push_str(&rewrite_comment(subslice, false, comment_width, diff --git a/tests/source/comment.rs b/tests/source/comment.rs index 0f76f220582..bce05ff7a2a 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -9,6 +9,7 @@ fn test() { // comment // comment2 + // FIXME(1275) code(); /* leave this comment alone! * ok? */ diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index 38442a79360..6d8da3e5445 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -3,6 +3,7 @@ fn test() { // comment // comment2 + // FIXME(1275) code(); /* leave this comment alone! * ok? */ diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 71ef6acf99a..9de4366b1c4 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -9,8 +9,9 @@ fn test() { // comment // comment2 - code(); /* leave this comment alone! - * ok? */ + // FIXME(1275) + code(); // leave this comment alone! + // ok? // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam @@ -31,8 +32,8 @@ fn test() { // self.config) // .unwrap()); - funk(); //dontchangeme - // or me + funk(); // dontchangeme + // or me } /// test123 diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index ff71124f464..fd91b5462f5 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -3,8 +3,9 @@ fn test() { // comment // comment2 + // FIXME(1275) code(); /* leave this comment alone! - * ok? */ + * ok? */ /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam @@ -25,7 +26,7 @@ fn test() { // .unwrap()); funk(); //dontchangeme - // or me + // or me } /// test123 diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index d2a736330f7..84f3cf89ba4 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -133,7 +133,7 @@ fn main() { Cell::new(42usize, remaining_widthremaining_widthremaining_widthremaining_width), 42usize); - let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment + let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ -- cgit 1.4.1-3-g733a5 From 0b1d78bae1a83bf6805b65670f7232822b3740c3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 17 Jan 2017 13:08:36 +1300 Subject: Try hard to format impl signatures Fixes #1249 --- src/items.rs | 34 ++++++++++++++++++++++------------ tests/source/impls.rs | 5 +++++ tests/target/impls.rs | 6 ++++++ 3 files changed, 33 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6a187bad7d5..09802242332 100644 --- a/src/items.rs +++ b/src/items.rs @@ -450,17 +450,14 @@ impl<'a> FmtVisitor<'a> { pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { if let ast::ItemKind::Impl(_, _, ref generics, ref trait_ref, _, ref items) = item.node { let mut result = String::new(); - // First try to format the ref and type without a split at the 'for'. let mut ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, false)); // If there is a line break present in the first result format it again // with a split at the 'for'. Skip this if there is no trait ref and // therefore no 'for'. - if let Some(_) = *trait_ref { - if ref_and_type.contains('\n') { - ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, true)); - } + if ref_and_type.contains('\n') && trait_ref.is_some() { + ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, true)); } result.push_str(&ref_and_type); @@ -589,11 +586,13 @@ fn format_impl_ref_and_type(context: &RewriteContext, mk_sp(lo, hi))); result.push_str(&generics_str); - result.push(' '); if polarity == ast::ImplPolarity::Negative { - result.push('!'); + result.push_str(" !"); } if let Some(ref trait_ref) = *trait_ref { + if polarity != ast::ImplPolarity::Negative { + result.push_str(" "); + } let budget = try_opt!(context.config.max_width.checked_sub(result.len())); let indent = offset + result.len(); result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent))); @@ -606,9 +605,9 @@ fn format_impl_ref_and_type(context: &RewriteContext, let for_indent = Indent::new(0, width); result.push_str(&for_indent.to_string(context.config)); - result.push_str("for "); + result.push_str("for"); } else { - result.push_str(" for "); + result.push_str(" for"); } } @@ -623,10 +622,21 @@ fn format_impl_ref_and_type(context: &RewriteContext, } } - let budget = try_opt!(context.config.max_width.checked_sub(used_space)); - let indent = offset + result.len(); - result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); + // 1 = space before the type. + let budget = try_opt!(context.config.max_width.checked_sub(used_space + 1)); + let indent = offset + result.len() + 1; + let self_ty_str = self_ty.rewrite(context, budget, indent); + if let Some(self_ty_str) = self_ty_str { + result.push_str(" "); + result.push_str(&self_ty_str); + return Some(result); + } + // Can't fit the self type on what's left of the line, so start a new one. + let indent = offset.block_indent(context.config); + result.push_str(&format!("\n{}", indent.to_string(context.config))); + let budget = try_opt!(context.config.max_width.checked_sub(indent.width())); + result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); Some(result) } else { unreachable!(); diff --git a/tests/source/impls.rs b/tests/source/impls.rs index aac87a1227f..060376b113e 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -112,3 +112,8 @@ mod x { C: 'static, D: 'static { } } + +impl Issue1249 { + // Creates a new flow constructor. + fn foo() {} +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 6f7990926fd..dacaa1f5601 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -143,3 +143,9 @@ mod x { { } } + +impl + Issue1249 { + // Creates a new flow constructor. + fn foo() {} +} -- cgit 1.4.1-3-g733a5 From 49e86a1e6501b261e6fef530d478ad0ea5ff3814 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 Jan 2017 10:38:46 +1300 Subject: Handle semicolons in macro statements Fixes #1279 --- src/visitor.rs | 2 +- tests/source/macros.rs | 4 ++++ tests/target/macros.rs | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index f568c63eb38..bea976523bb 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -61,12 +61,12 @@ impl<'a> FmtVisitor<'a> { let rewrite = stmt.rewrite(&self.get_context(), self.config.max_width - self.block_indent.width(), self.block_indent); - self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, _) = **mac; self.visit_mac(mac, None, MacroPosition::Statement); + self.format_missing(stmt.span.hi); } } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 1c4fd138820..c8f625b935b 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -75,3 +75,7 @@ gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", }); + +fn issue_1279() { + println!("dsfs"); // a comment +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 66bf4d33a98..c4f40cfe55b 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -76,3 +76,7 @@ gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", }); + +fn issue_1279() { + println!("dsfs"); // a comment +} -- cgit 1.4.1-3-g733a5 From 6572874965b43abfacf292143ae85213e0b5927c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 19 Jan 2017 10:47:07 +1300 Subject: Update to latest Syntex As a side-effect of the Path changes, we are now a bit more aggressive about normalising paths. --- Cargo.lock | 46 +++++----- Cargo.toml | 4 +- src/config.rs | 1 - src/expr.rs | 14 ++- src/imports.rs | 70 +++++++-------- src/patterns.rs | 15 +++- src/types.rs | 194 ++++++++++++++++++++++------------------- src/utils.rs | 8 +- tests/target/imports.rs | 10 +-- tests/target/pub-restricted.rs | 2 +- 10 files changed, 198 insertions(+), 166 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ed12a19fd69..d4d4b4b4962 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,14 +7,14 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.56.2 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -91,7 +91,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -127,7 +127,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -141,20 +141,20 @@ dependencies = [ [[package]] name = "syntex_errors" -version = "0.52.0" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.52.0" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -162,17 +162,17 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.52.0" +version = "0.56.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -190,7 +190,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -216,7 +216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-xid" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -253,7 +253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itertools 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c6946da472dbbcbd98c049050e8e587cc4ee26985992e582b1d74a35cb8a7020" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e030dc72013ed68994d1b2cbf36a94dd0e58418ba949c4b0db7eeb70a7a6352" +"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" @@ -262,15 +262,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" "checksum same-file 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c722bde68d432ad7982a6431b13264cc558af1707c0f321820e238c5671856ea" "checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" -"checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b" -"checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac" -"checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde" +"checksum syntex_errors 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13596c6a30ecd9d73d5f03167b7cc98f1e3e65063b046ac10b411dc9b2a8c600" +"checksum syntex_pos 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d55810cf983ad75bcc52ec97a777b619b00d821219df7883d40f2aed7416966a" +"checksum syntex_syntax 0.56.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ca00794c3556cadbcec14036c8bce354d92de33bd5ffbbc5bc090a4c595b27dc" "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum unicode-segmentation 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7baebdc1df1363fa66161fca2fe047e4f4209011cc7e045948298996afdf85df" -"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/Cargo.toml b/Cargo.toml index c471b91eea6..3dc8e8c0ff0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ regex = "0.1" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.52" -syntex_errors = "0.52" +syntex_syntax = "0.56" +syntex_errors = "0.56" log = "0.3" env_logger = "0.3" getopts = "0.2" diff --git a/src/config.rs b/src/config.rs index b974de703bb..1971f2061f5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -384,7 +384,6 @@ create_config! { reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imported_names: bool, false, "Reorder lists of names in import statements alphabetically"; - normalize_imports: bool, true, "Allows removing braces from imports and reducing paths"; single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ expressions. A value of zero means always break \ if-else expressions."; diff --git a/src/expr.rs b/src/expr.rs index 2fc6b8b86d2..c7d1ee3b680 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -26,7 +26,7 @@ use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_w use visitor::FmtVisitor; use config::{Config, StructLitStyle, MultilineStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; -use types::rewrite_path; +use types::{rewrite_path, PathContext}; use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; use macros::{rewrite_macro, MacroPosition}; @@ -54,7 +54,7 @@ fn format_expr(expr: &ast::Expr, offset: Indent) -> Option { let result = match expr.node { - ast::ExprKind::Vec(ref expr_vec) => { + ast::ExprKind::Array(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), context, @@ -148,7 +148,12 @@ fn format_expr(expr: &ast::Expr, rewrite_match(context, cond, arms, width, offset, expr.span) } ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, true, qself.as_ref(), path, width, offset) + rewrite_path(context, + PathContext::Expr, + qself.as_ref(), + path, + width, + offset) } ast::ExprKind::Assign(ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, None, width, offset) @@ -1727,7 +1732,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // 2 = " {".len() let path_budget = try_opt!(width.checked_sub(2)); - let path_str = try_opt!(rewrite_path(context, true, None, path, path_budget, offset)); + let path_str = + try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_budget, offset)); // Foo { a: Foo } - indent is +3, width is -5. let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); diff --git a/src/imports.rs b/src/imports.rs index b2909cfecd2..a75a571c553 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -13,7 +13,7 @@ use utils; use syntax::codemap::{self, BytePos, Span}; use codemap::SpanUtils; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; -use types::rewrite_path; +use types::{rewrite_path, PathContext}; use rewrite::{Rewrite, RewriteContext}; use visitor::FmtVisitor; use std::cmp::{self, Ordering}; @@ -139,17 +139,20 @@ impl Rewrite for ast::ViewPath { // 4 = " as ".len() let budget = try_opt!(width.checked_sub(ident_str.len() + 4)); - let path_str = if context.config.normalize_imports && - path.segments.last().unwrap().identifier.to_string() == "self" && + let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && path.segments.len() > 1 { let path = &ast::Path { span: path.span.clone(), segments: path.segments[..path.segments.len() - 1].to_owned(), - global: path.global, }; - try_opt!(rewrite_path(context, false, None, &path, budget, offset)) + try_opt!(rewrite_path(context, + PathContext::Import, + None, + &path, + budget, + offset)) } else { - try_opt!(rewrite_path(context, false, None, path, budget, offset)) + try_opt!(rewrite_path(context, PathContext::Import, None, path, budget, offset)) }; Some(if path.segments.last().unwrap().identifier == ident { @@ -248,17 +251,22 @@ impl<'a> FmtVisitor<'a> { } } -fn rewrite_single_use_list(path_str: Option, - vpi: &ast::PathListItem, - context: &RewriteContext) - -> String { - let path_item_str = match path_str { - Some(ref path_str) if vpi.node.name.to_string() == "self" && - context.config.normalize_imports => path_str.to_owned(), - Some(path_str) => format!("{}::{}", path_str, vpi.node.name), - None => vpi.node.name.to_string(), +fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { + let mut item_str = vpi.node.name.to_string(); + if item_str == "self" { + item_str = "".to_owned(); + } + let path_item_str = if path_str.is_empty() { + if item_str.is_empty() { + "self".to_owned() + } else { + item_str + } + } else if item_str.is_empty() { + path_str + } else { + format!("{}::{}", path_str, item_str) }; - append_alias(path_item_str, vpi) } @@ -283,27 +291,16 @@ pub fn rewrite_use_list(width: usize, context: &RewriteContext) -> Option { // Returns a different option to distinguish `::foo` and `foo` - let opt_path_str = if !path.to_string().is_empty() { - Some(path.to_string()) - } else if path.global { - // path is absolute, we return an empty String to avoid a double `::` - Some(String::new()) - } else { - None - }; + let path_str = try_opt!(rewrite_path(context, PathContext::Import, None, path, width, offset)); match path_list.len() { 0 => unreachable!(), - 1 => return Some(rewrite_single_use_list(opt_path_str, &path_list[0], context)), + 1 => return Some(rewrite_single_use_list(path_str, &path_list[0])), _ => (), } - // 2 = :: - let path_separation_w = if opt_path_str.is_some() { 2 } else { 0 }; - // 1 = { - let supp_indent = path.to_string().len() + path_separation_w + 1; - // 1 = } - let remaining_width = width.checked_sub(supp_indent + 1).unwrap_or(0); + // 2 = {} + let remaining_width = width.checked_sub(path_str.len() + 2).unwrap_or(0); let mut items = { // Dummy value, see explanation below. @@ -330,6 +327,8 @@ pub fn rewrite_use_list(width: usize, items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } + let colons_offset = if path_str.is_empty() { 0 } else { 2 }; + let tactic = definitive_tactic(&items[first_index..], ::lists::ListTactic::Mixed, remaining_width); @@ -337,7 +336,7 @@ pub fn rewrite_use_list(width: usize, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: offset + supp_indent, + indent: offset + path_str.len() + 1 + colons_offset, // FIXME This is too conservative, and will not use all width // available // (loose 1 column (";")) @@ -347,9 +346,10 @@ pub fn rewrite_use_list(width: usize, }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); - Some(match opt_path_str { - Some(opt_path_str) => format!("{}::{{{}}}", opt_path_str, list_str), - None => format!("{{{}}}", list_str), + Some(if path_str.is_empty() { + format!("{{{}}}", list_str) + } else { + format!("{}::{{{}}}", path_str, list_str) }) } diff --git a/src/patterns.rs b/src/patterns.rs index a4ae0b7595a..03598a1971b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -14,7 +14,7 @@ use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; use lists::{format_item_list, itemize_list, ListItem}; use expr::{rewrite_unary_prefix, rewrite_pair}; -use types::rewrite_path; +use types::{rewrite_path, PathContext}; use super::Spanned; use comment::FindUncommented; @@ -65,10 +65,16 @@ impl Rewrite for Pat { rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, width, offset) } PatKind::Path(ref q_self, ref path) => { - rewrite_path(context, true, q_self.as_ref(), path, width, offset) + rewrite_path(context, + PathContext::Expr, + q_self.as_ref(), + path, + width, + offset) } PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { - let path_str = try_opt!(rewrite_path(context, true, None, path, width, offset)); + let path_str = + try_opt!(rewrite_path(context, PathContext::Expr, None, path, width, offset)); rewrite_tuple_pat(pat_vec, dotdot_pos, Some(path_str), @@ -102,7 +108,8 @@ impl Rewrite for Pat { wrap_str(result, context.config.max_width, width, offset) } PatKind::Struct(ref path, ref fields, elipses) => { - let path = try_opt!(rewrite_path(context, true, None, path, width, offset)); + let path = + try_opt!(rewrite_path(context, PathContext::Expr, None, path, width, offset)); let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; diff --git a/src/types.rs b/src/types.rs index 950a63adafc..acc9c7c6cb5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -11,10 +11,11 @@ use std::ops::Deref; use std::iter::ExactSizeIterator; +use syntax::abi; use syntax::ast::{self, Mutability, FunctionRetTy}; -use syntax::print::pprust; use syntax::codemap::{self, Span, BytePos}; -use syntax::abi; +use syntax::print::pprust; +use syntax::symbol::keywords; use {Indent, Spanned}; use codemap::SpanUtils; @@ -25,9 +26,16 @@ use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::TypeDensity; use itertools::Itertools; +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum PathContext { + Expr, + Type, + Import, +} + // Does not wrap on simple segments. pub fn rewrite_path(context: &RewriteContext, - expr_context: bool, + path_context: PathContext, qself: Option<&ast::QSelf>, path: &ast::Path, width: usize, @@ -35,7 +43,8 @@ pub fn rewrite_path(context: &RewriteContext, -> Option { let skip_count = qself.map_or(0, |x| x.position); - let mut result = if path.global && qself.is_none() { + let mut result = if path.is_global() && qself.is_none() && + path_context != PathContext::Import { "::".to_owned() } else { String::new() @@ -54,7 +63,7 @@ pub fn rewrite_path(context: &RewriteContext, if skip_count > 0 { result.push_str(" as "); - if path.global { + if path.is_global() && path_context != PathContext::Import { result.push_str("::"); } @@ -62,7 +71,7 @@ pub fn rewrite_path(context: &RewriteContext, // 3 = ">::".len() let budget = try_opt!(width.checked_sub(extra_offset + 3)); - result = try_opt!(rewrite_path_segments(false, + result = try_opt!(rewrite_path_segments(PathContext::Type, result, path.segments.iter().take(skip_count), span_lo, @@ -82,7 +91,7 @@ pub fn rewrite_path(context: &RewriteContext, let extra_offset = extra_offset(&result, offset); let budget = try_opt!(width.checked_sub(extra_offset)); - rewrite_path_segments(expr_context, + rewrite_path_segments(path_context, result, path.segments.iter().skip(skip_count), span_lo, @@ -92,7 +101,7 @@ pub fn rewrite_path(context: &RewriteContext, offset + extra_offset) } -fn rewrite_path_segments<'a, I>(expr_context: bool, +fn rewrite_path_segments<'a, I>(path_context: PathContext, mut buffer: String, iter: I, mut span_lo: BytePos, @@ -106,6 +115,10 @@ fn rewrite_path_segments<'a, I>(expr_context: bool, let mut first = true; for segment in iter { + // Indicates a global path, shouldn't be rendered. + if segment.identifier.name == keywords::CrateRoot.name() { + continue; + } if first { first = false; } else { @@ -115,7 +128,7 @@ fn rewrite_path_segments<'a, I>(expr_context: bool, let extra_offset = extra_offset(&buffer, offset); let remaining_width = try_opt!(width.checked_sub(extra_offset)); let new_offset = offset + extra_offset; - let segment_string = try_opt!(rewrite_segment(expr_context, + let segment_string = try_opt!(rewrite_segment(path_context, segment, &mut span_lo, span_hi, @@ -172,7 +185,7 @@ impl<'a> Rewrite for SegmentParam<'a> { // // When the segment contains a positive number of parameters, we update span_lo // so that invariants described above will hold for the next segment. -fn rewrite_segment(expr_context: bool, +fn rewrite_segment(path_context: PathContext, segment: &ast::PathSegment, span_lo: &mut BytePos, span_hi: BytePos, @@ -184,62 +197,71 @@ fn rewrite_segment(expr_context: bool, let width = try_opt!(width.checked_sub(ident_len)); let offset = offset + ident_len; - let params = match segment.parameters { - ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() || - !data.types.is_empty() || - !data.bindings.is_empty() => { - let param_list = data.lifetimes - .iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) - .collect::>(); - - let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); - let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); - let separator = if expr_context { "::" } else { "" }; - - // 1 for < - let extra_offset = 1 + separator.len(); - // 1 for > - let list_width = try_opt!(width.checked_sub(extra_offset + 1)); - - let items = itemize_list(context.codemap, - param_list.into_iter(), - ">", - |param| param.get_span().lo, - |param| param.get_span().hi, - |seg| seg.rewrite(context, list_width, offset + extra_offset), - list_lo, - span_hi); - let list_str = try_opt!(format_item_list(items, - list_width, - offset + extra_offset, - context.config)); - - // Update position of last bracket. - *span_lo = next_span_lo; - - if context.config.spaces_within_angle_brackets && list_str.len() > 0 { - format!("{}< {} >", separator, list_str) - } else { - format!("{}<{}>", separator, list_str) + let params = if let Some(ref params) = segment.parameters { + match **params { + ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() || + !data.types.is_empty() || + !data.bindings.is_empty() => { + let param_list = data.lifetimes + .iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .collect::>(); + + let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); + let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); + let separator = if path_context == PathContext::Expr { + "::" + } else { + "" + }; + + // 1 for < + let extra_offset = 1 + separator.len(); + // 1 for > + let list_width = try_opt!(width.checked_sub(extra_offset + 1)); + + let items = + itemize_list(context.codemap, + param_list.into_iter(), + ">", + |param| param.get_span().lo, + |param| param.get_span().hi, + |seg| seg.rewrite(context, list_width, offset + extra_offset), + list_lo, + span_hi); + let list_str = try_opt!(format_item_list(items, + list_width, + offset + extra_offset, + context.config)); + + // Update position of last bracket. + *span_lo = next_span_lo; + + if context.config.spaces_within_angle_brackets && list_str.len() > 0 { + format!("{}< {} >", separator, list_str) + } else { + format!("{}<{}>", separator, list_str) + } } + ast::PathParameters::Parenthesized(ref data) => { + let output = match data.output { + Some(ref ty) => FunctionRetTy::Ty(ty.clone()), + None => FunctionRetTy::Default(codemap::DUMMY_SP), + }; + try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), + &output, + false, + data.span, + context, + width, + offset)) + } + _ => String::new(), } - ast::PathParameters::Parenthesized(ref data) => { - let output = match data.output { - Some(ref ty) => FunctionRetTy::Ty(ty.clone()), - None => FunctionRetTy::Default(codemap::DUMMY_SP), - }; - try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), - &output, - false, - data.span, - context, - width, - offset)) - } - _ => String::new(), + } else { + String::new() }; Some(format!("{}{}", segment.identifier, params)) @@ -393,14 +415,15 @@ impl Rewrite for ast::WherePredicate { .. }) => { try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, width, offset)) } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref path, ref ty, .. }) => { - let ty_str = try_opt!(ty.rewrite(context, width, offset)); + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, + ref rhs_ty, + .. }) => { + let lhs_ty_str = try_opt!(lhs_ty.rewrite(context, width, offset)); // 3 = " = ".len() - let used_width = 3 + ty_str.len(); + let used_width = 3 + lhs_ty_str.len(); let budget = try_opt!(width.checked_sub(used_width)); - let path_str = - try_opt!(rewrite_path(context, false, None, path, budget, offset + used_width)); - format!("{} = {}", path_str, ty_str) + let rhs_ty_str = try_opt!(rhs_ty.rewrite(context, budget, offset + used_width)); + format!("{} = {}", lhs_ty_str, rhs_ty_str) } }; @@ -462,10 +485,14 @@ impl Rewrite for ast::Lifetime { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; let strs: Vec<_> = try_opt!(self.iter() .map(|b| b.rewrite(context, width, offset)) .collect()); - wrap_str(strs.join(" + "), context.config.max_width, width, offset) + wrap_str(strs.join(joiner), context.config.max_width, width, offset) } } @@ -534,27 +561,14 @@ impl Rewrite for ast::PolyTraitRef { impl Rewrite for ast::TraitRef { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - rewrite_path(context, false, None, &self.path, width, offset) + rewrite_path(context, PathContext::Type, None, &self.path, width, offset) } } impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match self.node { - ast::TyKind::ObjectSum(ref ty, ref bounds) => { - let ty_str = try_opt!(ty.rewrite(context, width, offset)); - let overhead = ty_str.len() + 3; - let plus_str = match context.config.type_punctuation_density { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - Some(format!("{}{}{}", - ty_str, - plus_str, - try_opt!(bounds.rewrite(context, - try_opt!(width.checked_sub(overhead)), - offset + overhead)))) - } + ast::TyKind::TraitObject(ref bounds) => bounds.rewrite(context, width, offset), ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { Mutability::Mutable => "*mut ", @@ -618,9 +632,13 @@ impl Rewrite for ast::Ty { width, offset) } - ast::TyKind::PolyTraitRef(ref trait_ref) => trait_ref.rewrite(context, width, offset), ast::TyKind::Path(ref q_self, ref path) => { - rewrite_path(context, false, q_self.as_ref(), path, width, offset) + rewrite_path(context, + PathContext::Type, + q_self.as_ref(), + path, + width, + offset) } ast::TyKind::Array(ref ty, ref repeats) => { let use_spaces = context.config.spaces_within_square_brackets; diff --git a/src/utils.rs b/src/utils.rs index ab5de426571..2f8c5db82e1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -39,11 +39,13 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { Visibility::Inherited => Cow::from(""), Visibility::Crate(_) => Cow::from("pub(crate) "), Visibility::Restricted { ref path, .. } => { - let Path { global, ref segments, .. } = **path; - let prefix = if global { "::" } else { "" }; + let Path { ref segments, .. } = **path; let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.as_str()); + if path.is_global() { + segments_iter.next().expect("Non-global path in pub(restricted)?"); + } - Cow::from(format!("pub({}{}) ", prefix, segments_iter.join("::"))) + Cow::from(format!("pub({}) ", segments_iter.join("::"))) } } } diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 4e7627dd1b9..6b1d75d7f20 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -53,8 +53,8 @@ use foo::qux as bar; use foo::{baz, qux as bar}; // With absolute paths -use ::foo; -use ::foo::Bar; -use ::foo::{Bar, Baz}; -use ::Foo; -use ::{Bar, Baz}; +use foo; +use foo::Bar; +use foo::{Bar, Baz}; +use Foo; +use {Bar, Baz}; diff --git a/tests/target/pub-restricted.rs b/tests/target/pub-restricted.rs index 388228af814..88053173704 100644 --- a/tests/target/pub-restricted.rs +++ b/tests/target/pub-restricted.rs @@ -24,7 +24,7 @@ pub(crate) enum WriteState { WriteData(Writer), } -pub(::global::path::to::some_mod) enum WriteState { +pub(global::path::to::some_mod) enum WriteState { WriteId { id: U64Writer, size: U64Writer, -- cgit 1.4.1-3-g733a5 From e018712612c270744ebbb1f87f2221551785e0ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 Jan 2017 17:22:01 +1300 Subject: process cfg'ed off modules Fixes #1229 Fixes #1277 --- src/lib.rs | 11 +++++++++-- src/visitor.rs | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index fc016d86666..9e80e8f1b6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -398,9 +398,16 @@ fn parse_input(input: Input, parse_session: &ParseSess) -> Result> { let result = match input { - Input::File(file) => parse::parse_crate_from_file(&file, parse_session), + Input::File(file) => { + let mut parser = parse::new_parser_from_file(parse_session, &file); + parser.cfg_mods = false; + parser.parse_crate_mod() + } Input::Text(text) => { - parse::parse_crate_from_source_str("stdin".to_owned(), text, parse_session) + let mut parser = + parse::new_parser_from_source_str(parse_session, "stdin".to_owned(), text); + parser.cfg_mods = false; + parser.parse_crate_mod() } }; diff --git a/src/visitor.rs b/src/visitor.rs index bea976523bb..95ec54e89ee 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -548,7 +548,7 @@ impl<'a> FmtVisitor<'a> { } pub fn format_separate_mod(&mut self, m: &ast::Mod) { - let filemap = self.codemap.lookup_char_pos(source!(self, m.inner).lo).file; + let filemap = self.codemap.lookup_char_pos(m.inner.lo).file; self.last_pos = filemap.start_pos; self.block_indent = Indent::empty(); self.walk_mod_items(m); -- cgit 1.4.1-3-g733a5 From 56e0c463d580ee23a908abab27817b6a66a43f1b Mon Sep 17 00:00:00 2001 From: Ivan Ukhov Date: Wed, 25 Jan 2017 08:29:48 +0100 Subject: Process build scripts --- src/bin/cargo-fmt.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3a667472118..683c2d433a7 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -119,6 +119,7 @@ enum TargetKind { Example, // example file Test, // test file Bench, // bench file + CustomBuild, // build script Other, // plugin,... } @@ -126,7 +127,7 @@ impl TargetKind { fn should_format(&self) -> bool { match *self { TargetKind::Lib | TargetKind::Bin | TargetKind::Example | TargetKind::Test | - TargetKind::Bench => true, + TargetKind::Bench | TargetKind::CustomBuild => true, _ => false, } } @@ -169,6 +170,7 @@ fn target_from_json(jtarget: &Json) -> Target { "test" => TargetKind::Test, "example" => TargetKind::Example, "bench" => TargetKind::Bench, + "custom-build" => TargetKind::CustomBuild, _ => TargetKind::Other, }; -- cgit 1.4.1-3-g733a5 From 2261947f6ea31e8f2063a2ec7e2f26545acf2201 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 26 Jan 2017 15:10:47 +1300 Subject: Catch attributes before comments Closes #1280 Closes #1284 --- Cargo.lock | 2 +- src/missed_spans.rs | 11 +++++++++++ tests/source/comment4.rs | 7 +++++++ tests/target/comment4.rs | 7 +++++++ tests/target/fn.rs | 2 +- 5 files changed, 27 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d4d4b4b4962..7034d91d1df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt" -version = "0.7.0" +version = "0.7.1" dependencies = [ "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/missed_spans.rs b/src/missed_spans.rs index d9c2a771414..eff3fd6c573 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -84,6 +84,8 @@ impl<'a> FmtVisitor<'a> { let big_diff = (span.lo - big_span_lo).to_usize(); let snippet = self.snippet(span); + debug!("write_snippet `{}`", snippet); + self.write_snippet_inner(big_snippet, big_diff, &snippet, process_last_snippet); } @@ -114,6 +116,8 @@ impl<'a> FmtVisitor<'a> { let snippet = &*replaced; for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { + debug!("{:?}: {:?}", kind, subslice); + if let CodeCharKind::Comment = kind { let last_char = big_snippet[..(offset + big_diff)] .chars() @@ -199,6 +203,13 @@ impl<'a> FmtVisitor<'a> { last_wspace = None; } } + + let remaining = snippet[line_start..subslice.len() + offset].trim(); + if !remaining.is_empty() { + self.buffer.push_str(remaining); + line_start = subslice.len() + offset; + rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + } } process_last_snippet(self, &snippet[line_start..], snippet); diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index 6d8da3e5445..69eaa7a681f 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] // bar + //! Doc comment fn test() { // comment @@ -44,3 +46,8 @@ fn debug_function() { println!("hello"); } // */ + +#[link_section=".vectors"] +#[no_mangle] // Test this attribute is preserved. +#[cfg_attr(rustfmt, rustfmt_skip)] +pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index fd91b5462f5..08f84bb861d 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] // bar + //! Doc comment fn test() { // comment @@ -43,3 +45,8 @@ fn debug_function() { println!("hello"); } // */ + +#[link_section=".vectors"] +#[no_mangle] // Test this attribute is preserved. +#[cfg_attr(rustfmt, rustfmt_skip)] +pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 9ba150d6115..db51610d64e 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -86,7 +86,7 @@ fn ______________________baz(a: i32) *mut ::std::option::Option ()> { +-> ()>{ } pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -- cgit 1.4.1-3-g733a5 From 3d3b6784d11b7b3cb96a29795945b742f7a6be1c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 26 Jan 2017 15:44:54 +1300 Subject: Nits --- src/items.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 09802242332..57f237d8dae 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1349,8 +1349,6 @@ fn rewrite_fn_base(context: &RewriteContext, has_body: bool) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; - // FIXME we'll lose any comments in between parts of the function decl, but - // anyone who comments there probably deserves what they get. let where_clause = &generics.where_clause; @@ -1410,7 +1408,7 @@ fn rewrite_fn_base(context: &RewriteContext, multi_line_budget, arg_indent); - // Check if vertical layout was forced by compute_budget_for_args. + // Check if vertical layout was forced. if one_line_budget == 0 { if context.config.fn_args_paren_newline { result.push('\n'); @@ -1721,6 +1719,11 @@ fn compute_budgets_for_args(context: &RewriteContext, ret_str_len: usize, newline_brace: bool) -> Option<((usize, usize, Indent))> { + debug!("compute_budgets_for_args {} {:?}, {}, {}", + result.len(), + indent, + ret_str_len, + newline_brace); // Try keeping everything on the same line. if !result.contains('\n') { // 3 = `() `, space is before ret_string. -- cgit 1.4.1-3-g733a5 From 6747cd721ccbc6fbd69541aa6eb7f84d39a61923 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 13 Jan 2017 14:07:42 +1300 Subject: Start factoring out an abstract `Item` --- src/items.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 57f237d8dae..e8e5dfbc7f5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -76,38 +76,84 @@ impl Rewrite for ast::Local { } } +// TODO convert to using rewrite style rather than visitor +// TODO format modules in this style +struct Item<'a> { + keyword: &'static str, + abi: String, + vis: Option<&'a ast::Visibility>, + body: Vec>, + span: Span, +} + +impl<'a> Item<'a> { + fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { + let abi = if fm.abi == abi::Abi::C && !config.force_explicit_abi { + "extern".into() + } else { + format!("extern {}", fm.abi) + }; + Item { + keyword: "", + abi: abi, + vis: None, + body: fm.items.iter().map(|i| BodyElement::ForeignItem(i)).collect(), + span: span, + } + } +} + +enum BodyElement<'a> { + // Stmt(&'a ast::Stmt), + // Field(&'a ast::Field), + // Variant(&'a ast::Variant), + // Item(&'a ast::Item), + ForeignItem(&'a ast::ForeignItem), +} + impl<'a> FmtVisitor<'a> { - pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { - let abi_str = ::utils::format_abi(fm.abi, self.config.force_explicit_abi); - self.buffer.push_str(&abi_str); + fn format_item(&mut self, item: Item) { + self.buffer.push_str(&item.abi); + self.buffer.push_str(" "); - let snippet = self.snippet(span); + let snippet = self.snippet(item.span); let brace_pos = snippet.find_uncommented("{").unwrap(); self.buffer.push_str("{"); - if !fm.items.is_empty() || contains_comment(&snippet[brace_pos..]) { + if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { // FIXME: this skips comments between the extern keyword and the opening // brace. - self.last_pos = span.lo + BytePos(brace_pos as u32 + 1); + self.last_pos = item.span.lo + BytePos(brace_pos as u32 + 1); self.block_indent = self.block_indent.block_indent(self.config); - if fm.items.is_empty() { - self.format_missing_no_indent(span.hi - BytePos(1)); + if item.body.is_empty() { + self.format_missing_no_indent(item.span.hi - BytePos(1)); self.block_indent = self.block_indent.block_unindent(self.config); self.buffer.push_str(&self.block_indent.to_string(self.config)); } else { - for item in &fm.items { - self.format_foreign_item(&*item); + for item in &item.body { + self.format_body_element(item); } self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(span.hi - BytePos(1)); + self.format_missing_with_indent(item.span.hi - BytePos(1)); } } self.buffer.push_str("}"); - self.last_pos = span.hi; + self.last_pos = item.span.hi; + } + + fn format_body_element(&mut self, element: &BodyElement) { + match *element { + BodyElement::ForeignItem(ref item) => self.format_foreign_item(item), + } + } + + pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { + let item = Item::from_foreign_mod(fm, span, self.config); + self.format_item(item); } fn format_foreign_item(&mut self, item: &ast::ForeignItem) { -- cgit 1.4.1-3-g733a5 From 309fb37f23f1ca0f73d5b3a86b7522ae06f95bc4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 Jan 2017 07:42:34 +1300 Subject: Allow some unused fields --- src/items.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e8e5dfbc7f5..3a1c70ccb3f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -78,6 +78,7 @@ impl Rewrite for ast::Local { // TODO convert to using rewrite style rather than visitor // TODO format modules in this style +#[allow(dead_code)] struct Item<'a> { keyword: &'static str, abi: String, -- cgit 1.4.1-3-g733a5 From 1f3100d7bb2e4889ec243d2781b77e252fb29c5c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 Jan 2017 08:04:13 +1300 Subject: Make string lit formatting fallible This allows expressions containing string lits to wrap their content Fixes #1282 --- src/expr.rs | 21 ++++++++++++--------- tests/source/string-lit.rs | 10 ++++++++++ tests/target/string-lit.rs | 19 ++++++++++++++++--- tests/target/string_punctuation.rs | 7 +------ 4 files changed, 39 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c7d1ee3b680..435155de28f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -64,7 +64,7 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Lit(ref l) => { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => { - Some(rewrite_string_lit(context, l.span, width, offset)) + rewrite_string_lit(context, l.span, width, offset) } _ => { wrap_str(context.snippet(expr.span), @@ -586,6 +586,7 @@ fn and_one_line(x: Option) -> Option { } fn nop_block_collapse(block_str: Option, budget: usize) -> Option { + debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { @@ -1219,6 +1220,7 @@ fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str // Match arms. impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + debug!("Arm::rewrite {:?} {} {:?}", self, width, offset); let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; // FIXME this is all a bit grotty, would be nice to abstract out the @@ -1310,13 +1312,14 @@ impl Rewrite for ast::Arm { false }; - let block_sep = match context.config.control_brace_style { - ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), - _ => " ", - }; match rewrite { Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || is_block => { + let block_sep = match context.config.control_brace_style { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), + _ => " ", + }; + return Some(format!("{}{} =>{}{}{}", attr_str.trim_left(), pats_str, @@ -1477,16 +1480,16 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, width: usize, offset: Indent) - -> String { + -> Option { let string_lit = context.snippet(span); if !context.config.format_strings && !context.config.force_format_strings { - return string_lit; + return Some(string_lit); } if !context.config.force_format_strings && !string_requires_rewrite(context, span, &string_lit, width, offset) { - return string_lit; + return Some(string_lit); } let fmt = StringFormat { @@ -1503,7 +1506,7 @@ fn rewrite_string_lit(context: &RewriteContext, // Remove the quote characters. let str_lit = &string_lit[1..string_lit.len() - 1]; - rewrite_string(str_lit, &fmt).unwrap_or_else(|| string_lit.to_owned()) + rewrite_string(str_lit, &fmt) } fn string_requires_rewrite(context: &RewriteContext, diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index ca8aa36a90d..59547cbe62f 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -45,3 +45,13 @@ fn issue716() { println!("forall x. mult(e(), x) = x /\\ forall x. mult(x, x) = e()"); } + +fn issue_1282() { + { + match foo { + Permission::AndroidPermissionAccessLocationExtraCommands => { + "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" + } + } + } +} diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 1d4d21ff73e..4fba80e1c51 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -10,8 +10,10 @@ fn main() -> &'static str { let too_many_lines = "Hello"; // Make sure we don't break after an escape character. - let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let odd_length_name = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let even_length_name = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; @@ -22,7 +24,8 @@ formatting"#; filename.replace(" ", "\\"); - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); let unicode = "a̐éö̲\r\n"; let unicode2 = "Löwe 老虎 Léopard"; @@ -41,3 +44,13 @@ fn issue716() { println!("forall x. mult(e(), x) = x /\\ forall x. mult(x, x) = e()"); } + +fn issue_1282() { + { + match foo { + Permission::AndroidPermissionAccessLocationExtraCommands => { + "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" + } + } + } +} diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs index 1acad404357..ba5a478a5e7 100644 --- a/tests/target/string_punctuation.rs +++ b/tests/target/string_punctuation.rs @@ -1,12 +1,7 @@ fn main() { println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ Likethisssssssssssss"); - format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}", - x, - y, - z, - a, - b); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); -- cgit 1.4.1-3-g733a5 From e56ef44a3a27d1f609a20aacbdd2919f225175a9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 Jan 2017 08:11:59 +1300 Subject: Do not format string lits by default --- src/config.rs | 2 +- tests/source/long-match-arms-brace-newline.rs | 1 + tests/source/multiple.rs | 1 + tests/source/string_punctuation.rs | 2 ++ tests/target/long-match-arms-brace-newline.rs | 1 + tests/target/multiple.rs | 1 + tests/target/string_punctuation.rs | 2 ++ 7 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 1971f2061f5..f5d563197c3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -387,7 +387,7 @@ create_config! { single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ expressions. A value of zero means always break \ if-else expressions."; - format_strings: bool, true, "Format string literals where necessary"; + format_strings: bool, false, "Format string literals where necessary"; force_format_strings: bool, false, "Always format string literals"; take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; diff --git a/tests/source/long-match-arms-brace-newline.rs b/tests/source/long-match-arms-brace-newline.rs index 79cfb927b49..927ada0ffb2 100644 --- a/tests/source/long-match-arms-brace-newline.rs +++ b/tests/source/long-match-arms-brace-newline.rs @@ -1,3 +1,4 @@ +// rustfmt-format_strings: true // rustfmt-max_width: 80 // rustfmt-control_brace_style: AlwaysNextLine diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index fe8cc1787f2..68cfacfcb4b 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -1,5 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true +// rustfmt-format_strings: true // Test of lots of random stuff. // FIXME split this into multiple, self-contained tests. diff --git a/tests/source/string_punctuation.rs b/tests/source/string_punctuation.rs index 0a02077f7eb..efbadebb083 100644 --- a/tests/source/string_punctuation.rs +++ b/tests/source/string_punctuation.rs @@ -1,3 +1,5 @@ +// rustfmt-format_strings: true + fn main() { println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index 36f0b75f6a1..7cf094906cc 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -1,3 +1,4 @@ +// rustfmt-format_strings: true // rustfmt-max_width: 80 // rustfmt-control_brace_style: AlwaysNextLine diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 84f3cf89ba4..716b77a2d30 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -1,5 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true +// rustfmt-format_strings: true // Test of lots of random stuff. // FIXME split this into multiple, self-contained tests. diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs index ba5a478a5e7..d82e1143bc9 100644 --- a/tests/target/string_punctuation.rs +++ b/tests/target/string_punctuation.rs @@ -1,3 +1,5 @@ +// rustfmt-format_strings: true + fn main() { println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ Likethisssssssssssss"); -- cgit 1.4.1-3-g733a5 From 6054f28bd2c2b617d4d494c5e27e09b4b16db1d2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 Jan 2017 09:14:26 +1300 Subject: Some debugging stuff --- src/expr.rs | 2 ++ src/items.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 435155de28f..80937d76da7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -694,6 +694,7 @@ impl Rewrite for ast::Stmt { } // Abstraction over control flow expressions +#[derive(Debug)] struct ControlFlow<'a> { cond: Option<&'a ast::Expr>, block: &'a ast::Block, @@ -845,6 +846,7 @@ impl<'a> ControlFlow<'a> { impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + debug!("ControlFlow::rewrite {:?} {} {:?}", self, width, offset); let (budget, indent) = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() diff --git a/src/items.rs b/src/items.rs index 3a1c70ccb3f..8270a52ce76 100644 --- a/src/items.rs +++ b/src/items.rs @@ -31,6 +31,7 @@ use syntax::ast::ImplItem; // let pat: ty = init; impl Rewrite for ast::Local { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + debug!("Local::rewrite {:?} {} {:?}", self, width, offset); let mut result = "let ".to_owned(); let pattern_offset = offset + result.len(); // 1 = ; @@ -64,9 +65,9 @@ impl Rewrite for ast::Local { result.push_str(&infix); if let Some(ref ex) = self.init { + // 1 = trailing semicolon; let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1)); - // 1 = trailing semicolon; result = try_opt!(rewrite_assign_rhs(&context, result, ex, budget, context.block_indent)); } -- cgit 1.4.1-3-g733a5 From 428339fdc3c572b0b4a4e86ce1fc2ab048cccac0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 31 Jan 2017 08:28:48 +1300 Subject: Refactor indent and width into Shape struct --- src/chains.rs | 84 ++++--- src/comment.rs | 40 ++-- src/expr.rs | 663 ++++++++++++++++++++++++---------------------------- src/imports.rs | 31 +-- src/items.rs | 302 +++++++++++++----------- src/lib.rs | 44 ++++ src/lists.rs | 62 ++--- src/macros.rs | 19 +- src/missed_spans.rs | 5 +- src/patterns.rs | 123 +++++----- src/rewrite.rs | 12 +- src/string.rs | 14 +- src/types.rs | 307 ++++++++++++------------ src/utils.rs | 16 +- src/visitor.rs | 30 +-- 15 files changed, 866 insertions(+), 886 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1220d43356e..38f6fad1166 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -81,7 +81,7 @@ /// true, then we allow the last method call to spill over multiple lines without /// forcing the rest of the chain to be split. -use Indent; +use {Indent, Shape}; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, first_line_width}; use expr::rewrite_call; @@ -92,24 +92,20 @@ use std::iter; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; -pub fn rewrite_chain(expr: &ast::Expr, - context: &RewriteContext, - width: usize, - offset: Indent) - -> Option { +pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { let total_span = expr.span; let (parent, subexpr_list) = make_subexpr_list(expr, context); // Bail out if the chain is just try sugar, i.e., an expression followed by // any number of `?`s. if chain_only_try(&subexpr_list) { - return rewrite_try(&parent, subexpr_list.len(), context, width, offset); + return rewrite_try(&parent, subexpr_list.len(), context, shape); } // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_block_indent = chain_base_indent(context, offset); + let parent_block_indent = chain_base_indent(context, shape.indent); let parent_context = &RewriteContext { block_indent: parent_block_indent, ..*context }; - let parent_rewrite = try_opt!(parent.rewrite(parent_context, width, offset)); + let parent_rewrite = try_opt!(parent.rewrite(parent_context, shape)); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. @@ -119,7 +115,7 @@ pub fn rewrite_chain(expr: &ast::Expr, let indent = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node { parent_block_indent.block_indent(context.config) } else { - chain_indent(context, offset + Indent::new(0, parent_rewrite.len())) + chain_indent(context, shape.indent + Indent::new(0, parent_rewrite.len())) }; (indent, true) } else if is_block_expr(&parent, &parent_rewrite) { @@ -129,13 +125,13 @@ pub fn rewrite_chain(expr: &ast::Expr, } else if parent_rewrite.contains('\n') { (chain_indent(context, parent_block_indent.block_indent(context.config)), false) } else { - (chain_indent_newline(context, offset + Indent::new(0, parent_rewrite.len())), false) + (chain_indent_newline(context, shape.indent + Indent::new(0, parent_rewrite.len())), false) }; - let max_width = try_opt!((width + offset.width()).checked_sub(indent.width())); + let max_width = try_opt!((shape.width + shape.indent.width()).checked_sub(indent.width())); let mut rewrites = try_opt!(subexpr_list.iter() .rev() - .map(|e| rewrite_chain_subexpr(e, total_span, context, max_width, indent)) + .map(|e| rewrite_chain_subexpr(e, total_span, context, Shape::legacy(max_width, indent))) .collect::>>()); // Total of all items excluding the last. @@ -156,7 +152,7 @@ pub fn rewrite_chain(expr: &ast::Expr, false }; - let mut fits_single_line = !veto_single_line && total_width <= width; + let mut fits_single_line = !veto_single_line && total_width <= shape.width; if fits_single_line { let len = rewrites.len(); let (init, last) = rewrites.split_at_mut(len - 1); @@ -168,10 +164,9 @@ pub fn rewrite_chain(expr: &ast::Expr, rewrite_method_call_with_overflow(e, &mut last[0], almost_total, - width, total_span, context, - offset) + shape) } _ => !last[0].contains('\n'), } @@ -199,8 +194,7 @@ pub fn rewrite_chain(expr: &ast::Expr, first_connector, join_rewrites(&rewrites, &subexpr_list, &connector)), context.config.max_width, - width, - offset) + shape) } // True if the chain is only `?`s. @@ -215,10 +209,9 @@ fn chain_only_try(exprs: &[ast::Expr]) -> bool { pub fn rewrite_try(expr: &ast::Expr, try_count: usize, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { - let sub_expr = try_opt!(expr.rewrite(context, width - try_count, offset)); + let sub_expr = try_opt!(expr.rewrite(context, shape.sub_width(try_count))); Some(format!("{}{}", sub_expr, iter::repeat("?").take(try_count).collect::())) @@ -305,13 +298,12 @@ fn chain_indent_newline(context: &RewriteContext, _offset: Indent) -> Indent { fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, last: &mut String, almost_total: usize, - width: usize, total_span: Span, context: &RewriteContext, - offset: Indent) + shape: Shape) -> bool { if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { - let budget = match width.checked_sub(almost_total) { + let budget = match shape.width.checked_sub(almost_total) { Some(b) => b, None => return false, }; @@ -320,8 +312,8 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, expressions, total_span, context, - budget, - offset + almost_total); + Shape::legacy(budget, + shape.indent + almost_total)); if let Some(ref mut s) = last_rewrite { ::std::mem::swap(s, last); @@ -366,29 +358,36 @@ fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { fn rewrite_chain_subexpr(expr: &ast::Expr, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { match expr.node { ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => { - let inner = &RewriteContext { block_indent: offset, ..*context }; - rewrite_method_call(method_name.node, - types, - expressions, - span, - inner, - width, - offset) + let inner = &RewriteContext { block_indent: shape.indent, ..*context }; + rewrite_method_call(method_name.node, types, expressions, span, inner, shape) } ast::ExprKind::Field(_, ref field) => { let s = format!(".{}", field.node); - if s.len() <= width { Some(s) } else { None } + if s.len() <= shape.width { + Some(s) + } else { + None + } } ast::ExprKind::TupField(_, ref field) => { let s = format!(".{}", field.node); - if s.len() <= width { Some(s) } else { None } + if s.len() <= shape.width { + Some(s) + } else { + None + } + } + ast::ExprKind::Try(_) => { + if shape.width >= 1 { + Some("?".into()) + } else { + None + } } - ast::ExprKind::Try(_) => if width >= 1 { Some("?".into()) } else { None }, _ => unreachable!(), } } @@ -406,14 +405,13 @@ fn rewrite_method_call(method_name: ast::Ident, args: &[ptr::P], span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { let type_list: Vec<_> = try_opt!(types.iter() - .map(|ty| ty.rewrite(context, width, offset)) + .map(|ty| ty.rewrite(context, shape)) .collect()); let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { @@ -428,5 +426,5 @@ fn rewrite_method_call(method_name: ast::Ident, let callee_str = format!(".{}{}", method_name, type_str); let span = mk_sp(lo, span.hi); - rewrite_call(context, &callee_str, &args[1..], span, width, offset) + rewrite_call(context, &callee_str, &args[1..], span, shape) } diff --git a/src/comment.rs b/src/comment.rs index 8eaf2b2fb4f..b7549f10c2d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -14,7 +14,7 @@ use std::{self, iter}; use syntax::codemap::Span; -use Indent; +use {Indent, Shape}; use config::Config; use rewrite::RewriteContext; use string::{StringFormat, rewrite_string}; @@ -34,8 +34,7 @@ fn is_custom_comment(comment: &str) -> bool { pub fn rewrite_comment(orig: &str, block_style: bool, - width: usize, - offset: Indent, + shape: Shape, config: &Config) -> Option { // If there are lines without a starting sigil, we won't format them correctly @@ -50,7 +49,7 @@ pub fn rewrite_comment(orig: &str, } if !config.normalize_comments && !config.wrap_comments { - return light_rewrite_comment(orig, offset, config); + return light_rewrite_comment(orig, shape.indent, config); } let (opener, closer, line_start) = @@ -85,15 +84,14 @@ pub fn rewrite_comment(orig: &str, ("// ", "", "// ") }; - let max_chars = width.checked_sub(closer.len() + opener.len()).unwrap_or(1); - let indent_str = offset.to_string(config); + let max_chars = shape.width.checked_sub(closer.len() + opener.len()).unwrap_or(1); + let indent_str = shape.indent.to_string(config); let fmt = StringFormat { opener: "", closer: "", line_start: line_start, line_end: "", - width: max_chars, - offset: offset + (opener.len() - line_start.len()), + shape: Shape::legacy(max_chars, shape.indent + (opener.len() - line_start.len())), trim_end: true, config: config, }; @@ -574,14 +572,13 @@ impl<'a> Iterator for CommentCodeSlices<'a> { pub fn recover_comment_removed(new: String, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let snippet = context.snippet(span); if changed_comment_content(&snippet, &new) { // We missed some comments // Keep previous formatting if it satisfies the constrains - wrap_str(snippet, context.config.max_width, width, offset) + wrap_str(snippet, context.config.max_width, shape) } else { Some(new) } @@ -678,7 +675,7 @@ fn remove_comment_header(comment: &str) -> &str { mod test { use super::{CharClasses, CodeCharKind, FullCodeCharKind, contains_comment, rewrite_comment, FindUncommented, CommentCodeSlices}; - use Indent; + use {Indent, Shape}; #[test] fn char_classes() { @@ -735,33 +732,36 @@ mod test { config.wrap_comments = true; config.normalize_comments = true; - let comment = rewrite_comment(" //test", true, 100, Indent::new(0, 100), &config).unwrap(); + let comment = rewrite_comment(" //test", + true, + Shape::legacy(100, Indent::new(0, 100)), + &config).unwrap(); assert_eq!("/* test */", comment); let comment = rewrite_comment("// comment on a", false, - 10, - Indent::empty(), + Shape::legacy(10, Indent::empty()), &config).unwrap(); assert_eq!("// comment\n// on a", comment); let comment = rewrite_comment("// A multi line comment\n // between args.", false, - 60, - Indent::new(0, 12), + Shape::legacy(60, Indent::new(0, 12)), &config).unwrap(); assert_eq!("// A multi line comment\n // between args.", comment); let input = "// comment"; let expected = "/* comment */"; - let comment = rewrite_comment(input, true, 9, Indent::new(0, 69), &config).unwrap(); + let comment = rewrite_comment(input, + true, + Shape::legacy(9, Indent::new(0, 69)), + &config).unwrap(); assert_eq!(expected, comment); let comment = rewrite_comment("/* trimmed */", true, - 100, - Indent::new(0, 100), + Shape::legacy(100, Indent::new(0, 100)), &config).unwrap(); assert_eq!("/* trimmed */", comment); } diff --git a/src/expr.rs b/src/expr.rs index 80937d76da7..ba7c05b6528 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -15,7 +15,7 @@ use std::ops::Deref; use std::iter::ExactSizeIterator; use std::fmt::Write; -use {Indent, Spanned}; +use {Indent, Shape, Spanned}; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, @@ -36,8 +36,8 @@ use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; use syntax::parse::classify; impl Rewrite for ast::Expr { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - format_expr(self, ExprType::SubExpression, context, width, offset) + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + format_expr(self, ExprType::SubExpression, context, shape) } } @@ -50,35 +50,28 @@ enum ExprType { fn format_expr(expr: &ast::Expr, expr_type: ExprType, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let result = match expr.node { ast::ExprKind::Array(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), context, - width, - offset) + shape) } ast::ExprKind::Lit(ref l) => { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => { - rewrite_string_lit(context, l.span, width, offset) - } - _ => { - wrap_str(context.snippet(expr.span), - context.config.max_width, - width, - offset) + rewrite_string_lit(context, l.span, shape) } + _ => wrap_str(context.snippet(expr.span), context.config.max_width, shape), } } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, expr.span.hi); - rewrite_call(context, &**callee, args, inner_span, width, offset) + rewrite_call(context, &**callee, args, inner_span, shape) } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, width, offset), + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator rewrite_pair(&**lhs, @@ -87,43 +80,33 @@ fn format_expr(expr: &ast::Expr, &format!(" {} ", context.snippet(op.span)), "", context, - width, - offset) - } - ast::ExprKind::Unary(ref op, ref subexpr) => { - rewrite_unary_op(context, op, subexpr, width, offset) + shape) } + ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref path, ref fields, ref base) => { rewrite_struct_lit(context, path, fields, base.as_ref().map(|e| &**e), expr.span, - width, - offset) + shape) } ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, - items.iter().map(|x| &**x), - expr.span, - width, - offset) + rewrite_tuple(context, items.iter().map(|x| &**x), expr.span, shape) } ast::ExprKind::While(ref cond, ref block, label) => { - ControlFlow::new_while(None, cond, block, label, expr.span) - .rewrite(context, width, offset) + ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape) } ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - ControlFlow::new_while(Some(pat), cond, block, label, expr.span) - .rewrite(context, width, offset) + ControlFlow::new_while(Some(pat), cond, block, label, expr.span).rewrite(context, shape) } ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, width, offset) + ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, shape) } ast::ExprKind::Loop(ref block, label) => { - ControlFlow::new_loop(block, label, expr.span).rewrite(context, width, offset) + ControlFlow::new_loop(block, label, expr.span).rewrite(context, shape) } - ast::ExprKind::Block(ref block) => block.rewrite(context, width, offset), + ast::ExprKind::Block(ref block) => block.rewrite(context, shape), ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { ControlFlow::new_if(cond, None, @@ -132,7 +115,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, width, offset) + .rewrite(context, shape) } ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { ControlFlow::new_if(cond, @@ -142,24 +125,19 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, width, offset) + .rewrite(context, shape) } ast::ExprKind::Match(ref cond, ref arms) => { - rewrite_match(context, cond, arms, width, offset, expr.span) + rewrite_match(context, cond, arms, shape, expr.span) } ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, - PathContext::Expr, - qself.as_ref(), - path, - width, - offset) + rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) } ast::ExprKind::Assign(ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, None, width, offset) + rewrite_assignment(context, lhs, rhs, None, shape) } ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), width, offset) + rewrite_assignment(context, lhs, rhs, Some(op), shape) } ast::ExprKind::Continue(ref opt_ident) => { let id_str = match *opt_ident { @@ -168,8 +146,7 @@ fn format_expr(expr: &ast::Expr, }; wrap_str(format!("continue{}", id_str), context.config.max_width, - width, - offset) + shape) } ast::ExprKind::Break(ref opt_ident, ref opt_expr) => { let id_str = match *opt_ident { @@ -178,56 +155,40 @@ fn format_expr(expr: &ast::Expr, }; if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, - &format!("break{} ", id_str), - &**expr, - width, - offset) + rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) } else { - wrap_str(format!("break{}", id_str), - context.config.max_width, - width, - offset) + wrap_str(format!("break{}", id_str), context.config.max_width, shape) } } ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { - rewrite_closure(capture, fn_decl, body, expr.span, context, width, offset) + rewrite_closure(capture, fn_decl, body, expr.span, context, shape) } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::TupField(..) | - ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, width, offset), + ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, width, offset, MacroPosition::Expression) - .or_else(|| { - wrap_str(context.snippet(expr.span), - context.config.max_width, - width, - offset) - }) - } - ast::ExprKind::Ret(None) => { - wrap_str("return".to_owned(), context.config.max_width, width, offset) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + .or_else(|| wrap_str(context.snippet(expr.span), context.config.max_width, shape)) } + ast::ExprKind::Ret(None) => wrap_str("return".to_owned(), context.config.max_width, shape), ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, width, offset) - } - ast::ExprKind::Box(ref expr) => { - rewrite_unary_prefix(context, "box ", &**expr, width, offset) + rewrite_unary_prefix(context, "return ", &**expr, shape) } + ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), ast::ExprKind::AddrOf(mutability, ref expr) => { - rewrite_expr_addrof(context, mutability, expr, width, offset) + rewrite_expr_addrof(context, mutability, expr, shape) } ast::ExprKind::Cast(ref expr, ref ty) => { - rewrite_pair(&**expr, &**ty, "", " as ", "", context, width, offset) + rewrite_pair(&**expr, &**ty, "", " as ", "", context, shape) } ast::ExprKind::Type(ref expr, ref ty) => { - rewrite_pair(&**expr, &**ty, "", ": ", "", context, width, offset) + rewrite_pair(&**expr, &**ty, "", ": ", "", context, shape) } ast::ExprKind::Index(ref expr, ref index) => { - rewrite_index(&**expr, &**index, context, width, offset) + rewrite_index(&**expr, &**index, context, shape) } ast::ExprKind::Repeat(ref expr, ref repeats) => { let (lbr, rbr) = if context.config.spaces_within_square_brackets { @@ -235,7 +196,7 @@ fn format_expr(expr: &ast::Expr, } else { ("[", "]") }; - rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, width, offset) + rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, shape) } ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { @@ -250,7 +211,7 @@ fn format_expr(expr: &ast::Expr, } else { delim.into() }; - rewrite_pair(&**lhs, &**rhs, "", &sp_delim, "", context, width, offset) + rewrite_pair(&**lhs, &**rhs, "", &sp_delim, "", context, shape) } (None, Some(ref rhs)) => { let sp_delim = if context.config.spaces_around_ranges { @@ -258,7 +219,7 @@ fn format_expr(expr: &ast::Expr, } else { delim.into() }; - rewrite_unary_prefix(context, &sp_delim, &**rhs, width, offset) + rewrite_unary_prefix(context, &sp_delim, &**rhs, shape) } (Some(ref lhs), None) => { let sp_delim = if context.config.spaces_around_ranges { @@ -266,22 +227,19 @@ fn format_expr(expr: &ast::Expr, } else { delim.into() }; - rewrite_unary_suffix(context, &sp_delim, &**lhs, width, offset) + rewrite_unary_suffix(context, &sp_delim, &**lhs, shape) } - (None, None) => wrap_str(delim.into(), context.config.max_width, width, offset), + (None, None) => wrap_str(delim.into(), context.config.max_width, shape), } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - wrap_str(context.snippet(expr.span), - context.config.max_width, - width, - offset) + wrap_str(context.snippet(expr.span), context.config.max_width, shape) } }; - result.and_then(|res| recover_comment_removed(res, expr.span, context, width, offset)) + result.and_then(|res| recover_comment_removed(res, expr.span, context, shape)) } pub fn rewrite_pair(lhs: &LHS, @@ -290,31 +248,31 @@ pub fn rewrite_pair(lhs: &LHS, infix: &str, suffix: &str, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option where LHS: Rewrite, RHS: Rewrite { - let lhs_budget = try_opt!(width.checked_sub(prefix.len() + infix.len())); - let rhs_budget = try_opt!(width.checked_sub(suffix.len())); + let lhs_budget = try_opt!(shape.width.checked_sub(prefix.len() + infix.len())); + let rhs_budget = try_opt!(shape.width.checked_sub(suffix.len())); // Get "full width" rhs and see if it fits on the current line. This // usually works fairly well since it tends to place operands of // operations with high precendence close together. // Note that this is non-conservative, but its just to see if it's even // worth trying to put everything on one line. - let rhs_result = rhs.rewrite(context, rhs_budget, offset); + let rhs_result = rhs.rewrite(context, Shape::legacy(rhs_budget, shape.indent)); if let Some(rhs_result) = rhs_result { // This is needed in case of line break not caused by a // shortage of space, but by end-of-line comments, for example. if !rhs_result.contains('\n') { - let lhs_result = lhs.rewrite(context, lhs_budget, offset); + let lhs_result = lhs.rewrite(context, Shape::legacy(lhs_budget, shape.indent)); if let Some(lhs_result) = lhs_result { let mut result = format!("{}{}{}", prefix, lhs_result, infix); - let remaining_width = width.checked_sub(last_line_width(&result)).unwrap_or(0); + let remaining_width = + shape.width.checked_sub(last_line_width(&result)).unwrap_or(0); if rhs_result.len() <= remaining_width { result.push_str(&rhs_result); @@ -324,7 +282,9 @@ pub fn rewrite_pair(lhs: &LHS, // Try rewriting the rhs into the remaining space. let rhs_budget = try_opt!(remaining_width.checked_sub(suffix.len())); - if let Some(rhs_result) = rhs.rewrite(context, rhs_budget, offset + result.len()) { + if let Some(rhs_result) = rhs.rewrite(context, + Shape::legacy(rhs_budget, + shape.indent + result.len())) { if rhs_result.len() <= remaining_width { result.push_str(&rhs_result); result.push_str(suffix); @@ -339,13 +299,14 @@ pub fn rewrite_pair(lhs: &LHS, // Re-evaluate the rhs because we have more space now: let infix = infix.trim_right(); - let lhs_budget = - try_opt!(context.config.max_width.checked_sub(offset.width() + prefix.len() + infix.len())); + let lhs_budget = try_opt!(context.config + .max_width + .checked_sub(shape.indent.width() + prefix.len() + infix.len())); let rhs_budget = try_opt!(rhs_budget.checked_sub(prefix.len())); - let rhs_offset = offset + prefix.len(); + let rhs_offset = shape.indent + prefix.len(); - let rhs_result = try_opt!(rhs.rewrite(context, rhs_budget, rhs_offset)); - let lhs_result = try_opt!(lhs.rewrite(context, lhs_budget, offset)); + let rhs_result = try_opt!(rhs.rewrite(context, Shape::legacy(rhs_budget, rhs_offset))); + let lhs_result = try_opt!(lhs.rewrite(context, Shape::legacy(lhs_budget, shape.indent))); Some(format!("{}{}{}\n{}{}{}", prefix, lhs_result, @@ -358,8 +319,7 @@ pub fn rewrite_pair(lhs: &LHS, pub fn rewrite_array<'a, I>(expr_iter: I, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option where I: Iterator { @@ -368,18 +328,19 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } else { 1 // "[" }; - let offset = offset + bracket_size; + let offset = shape.indent + bracket_size; let inner_context = &RewriteContext { block_indent: offset, ..*context }; - let max_item_width = try_opt!(width.checked_sub(bracket_size * 2)); - let items = itemize_list(context.codemap, - expr_iter, - "]", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(inner_context, max_item_width, offset), - span.lo, - span.hi) - .collect::>(); + let max_item_width = try_opt!(shape.width.checked_sub(bracket_size * 2)); + let items = + itemize_list(context.codemap, + expr_iter, + "]", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(inner_context, Shape::legacy(max_item_width, offset)), + span.lo, + span.hi) + .collect::>(); let has_long_item = try_opt!(items.iter() .map(|li| li.item.as_ref().map(|s| s.len() > 10)) @@ -395,8 +356,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: offset, - width: max_item_width, + shape: Shape::legacy(max_item_width, offset), ends_with_newline: false, config: context.config, }; @@ -410,7 +370,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } // This functions is pretty messy because of the rules around closures and blocks: -// TODO +// FIXME - the below is probably no longer true in full. // * if there is a return type, then there must be braces, // * given a closure with braces, whether that is parsed to give an inner block // or not depends on if there is a return type and if there are statements @@ -423,34 +383,34 @@ fn rewrite_closure(capture: ast::CaptureBy, body: &ast::Expr, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let mover = if capture == ast::CaptureBy::Value { "move " } else { "" }; - let offset = offset + mover.len(); + let offset = shape.indent + mover.len(); // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. - let budget = try_opt!(width.checked_sub(4 + mover.len())); + let budget = try_opt!(shape.width.checked_sub(4 + mover.len())); // 1 = | let argument_offset = offset + 1; - let ret_str = try_opt!(fn_decl.output.rewrite(context, budget, argument_offset)); + let ret_str = try_opt!(fn_decl.output.rewrite(context, Shape::legacy(budget, argument_offset))); // 1 = space between arguments and return type. let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0); - let arg_items = itemize_list(context.codemap, - fn_decl.inputs.iter(), - "|", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(arg), - |arg| arg.rewrite(context, budget, argument_offset), - context.codemap.span_after(span, "|"), - body.span.lo); + let arg_items = + itemize_list(context.codemap, + fn_decl.inputs.iter(), + "|", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(arg), + |arg| arg.rewrite(context, Shape::legacy(budget, argument_offset)), + context.codemap.span_after(span, "|"), + body.span.lo); let item_vec = arg_items.collect::>(); let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget); let budget = match tactic { @@ -462,8 +422,7 @@ fn rewrite_closure(capture: ast::CaptureBy, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: argument_offset, - width: budget, + shape: Shape::legacy(budget, argument_offset), ends_with_newline: false, config: context.config, }; @@ -482,7 +441,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, offset) + 1; - let budget = try_opt!(width.checked_sub(extra_offset)); + let budget = try_opt!(shape.width.checked_sub(extra_offset)); let total_offset = offset + extra_offset; if let ast::ExprKind::Block(ref block) = body.node { @@ -502,8 +461,7 @@ fn rewrite_closure(capture: ast::CaptureBy, if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, - budget, - total_offset) { + Shape::legacy(budget, total_offset)) { return Some(rw); } } @@ -513,7 +471,9 @@ fn rewrite_closure(capture: ast::CaptureBy, // We need braces, but we might still prefer a one-liner. let stmt = &block.stmts[0]; // 4 = braces and spaces. - let mut rewrite = stmt.rewrite(context, try_opt!(budget.checked_sub(4)), total_offset); + let mut rewrite = stmt.rewrite(context, + Shape::legacy(try_opt!(budget.checked_sub(4)), + total_offset)); // Checks if rewrite succeeded and fits on a single line. rewrite = and_one_line(rewrite); @@ -527,7 +487,10 @@ fn rewrite_closure(capture: ast::CaptureBy, return rewrite_closure_block(&block, prefix, context, budget); } - if let Some(rw) = rewrite_closure_expr(body, &prefix, context, budget, total_offset) { + if let Some(rw) = rewrite_closure_expr(body, + &prefix, + context, + Shape::legacy(budget, total_offset)) { return Some(rw); } @@ -548,10 +511,9 @@ fn rewrite_closure(capture: ast::CaptureBy, fn rewrite_closure_expr(expr: &ast::Expr, prefix: &str, context: &RewriteContext, - budget: usize, - offset: Indent) + shape: Shape) -> Option { - let mut rewrite = expr.rewrite(context, budget, offset); + let mut rewrite = expr.rewrite(context, shape); if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { rewrite = and_one_line(rewrite); } @@ -565,7 +527,7 @@ fn rewrite_closure(capture: ast::CaptureBy, -> Option { // Start with visual indent, then fall back to block indent if the // closure is large. - let rewrite = try_opt!(block.rewrite(&context, budget, Indent::empty())); + let rewrite = try_opt!(block.rewrite(&context, Shape::legacy(budget, Indent::empty()))); let block_threshold = context.config.closure_block_indent_threshold; if block_threshold < 0 || rewrite.matches('\n').count() <= block_threshold as usize { @@ -576,7 +538,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // means we must re-format. let mut context = context.clone(); context.block_indent.alignment = 0; - let rewrite = try_opt!(block.rewrite(&context, budget, Indent::empty())); + let rewrite = try_opt!(block.rewrite(&context, Shape::legacy(budget, Indent::empty()))); Some(format!("{} {}", prefix, rewrite)) } } @@ -597,11 +559,12 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option Option { - // width is used only for the single line case: either the empty block `{}`, + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + // shape.width is used only for the single line case: either the empty block `{}`, // or an unsafe expression `unsafe { e }`. - if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) && width >= 2 { + if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) && + shape.width >= 2 { return Some("{}".to_owned()); } @@ -611,7 +574,8 @@ impl Rewrite for ast::Block { if user_str.starts_with('{') && user_str.ends_with('}') { let comment_str = user_str[1..user_str.len() - 1].trim(); if self.stmts.is_empty() && !comment_str.contains('\n') && - !comment_str.starts_with("//") && comment_str.len() + 4 <= width { + !comment_str.starts_with("//") && + comment_str.len() + 4 <= shape.width { return Some(format!("{{ {} }}", comment_str)); } } @@ -630,22 +594,23 @@ impl Rewrite for ast::Block { let prefix = if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() - let budget = try_opt!(width.checked_sub(9)); + let budget = try_opt!(shape.width.checked_sub(9)); format!("unsafe {} ", try_opt!(rewrite_comment(trimmed, true, - budget, - offset + 7, + Shape::legacy(budget, shape.indent + 7), context.config))) } else { "unsafe ".to_owned() }; - if is_simple_block(self, context.codemap) && prefix.len() < width { - let expr_str = self.stmts[0].rewrite(context, width - prefix.len(), offset); + if is_simple_block(self, context.codemap) && prefix.len() < shape.width { + let expr_str = self.stmts[0].rewrite(context, + Shape::legacy(shape.width - prefix.len(), + shape.indent)); let expr_str = try_opt!(expr_str); let result = format!("{}{{ {} }}", prefix, expr_str); - if result.len() <= width && !result.contains('\n') { + if result.len() <= shape.width && !result.contains('\n') { return Some(result); } } @@ -666,10 +631,11 @@ impl Rewrite for ast::Block { } impl Rewrite for ast::Stmt { - fn rewrite(&self, context: &RewriteContext, _width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let result = match self.node { ast::StmtKind::Local(ref local) => { - local.rewrite(context, context.config.max_width, offset) + local.rewrite(context, + Shape::legacy(context.config.max_width, shape.indent)) } ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { @@ -682,14 +648,15 @@ impl Rewrite for ast::Stmt { _ => unreachable!(), }, context, - context.config.max_width - offset.width() - suffix.len(), - offset) + Shape::legacy(context.config.max_width - shape.indent.width() - + suffix.len(), + shape.indent)) .map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; - result.and_then(|res| recover_comment_removed(res, self.span, context, _width, offset)) + result.and_then(|res| recover_comment_removed(res, self.span, context, shape)) } } @@ -819,11 +786,12 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); let expr = &self.block.stmts[0]; - let if_str = try_opt!(expr.rewrite(context, new_width, Indent::empty())); + let if_str = try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = try_opt!(else_expr.rewrite(context, new_width, Indent::empty())); + let else_str = + try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); if if_str.contains('\n') || else_str.contains('\n') { return None; @@ -845,14 +813,14 @@ impl<'a> ControlFlow<'a> { } impl<'a> Rewrite for ControlFlow<'a> { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("ControlFlow::rewrite {:?} {} {:?}", self, width, offset); + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("ControlFlow::rewrite {:?} {:?}", self, shape); let (budget, indent) = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - (try_opt!(width.checked_sub(7)), offset + 7) + (try_opt!(shape.width.checked_sub(7)), shape.indent + 7) } else { - (width, offset) + (shape.width, shape.indent) }; let label_string = rewrite_label(self.label); @@ -872,15 +840,14 @@ impl<'a> Rewrite for ControlFlow<'a> { cond, self.matcher, self.connector, - inner_width, - inner_offset)) + Shape::legacy(inner_width, inner_offset))) } None => String::new(), }; // Try to format if-else on single line. if self.allow_single_line && context.config.single_line_if_else_max_width > 0 { - let trial = self.rewrite_single_line(&pat_expr_string, context, width); + let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if trial.is_some() && trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width { @@ -891,16 +858,18 @@ impl<'a> Rewrite for ControlFlow<'a> { // This is used only for the empty block case: `{}`. So, we use 1 if we know // we should avoid the single line case. // 2 = spaces after keyword and condition. - let block_width = try_opt!(width.checked_sub(label_string.len() + self.keyword.len() + - extra_offset(&pat_expr_string, inner_offset) + - 2)); + let block_width = try_opt!(shape.width + .checked_sub(label_string.len() + self.keyword.len() + + extra_offset(&pat_expr_string, inner_offset) + + 2)); let block_width = if self.else_block.is_some() || self.nested_if { min(1, block_width) } else { block_width }; - let block_str = try_opt!(self.block.rewrite(context, block_width, offset)); + let block_str = try_opt!(self.block + .rewrite(context, Shape::legacy(block_width, shape.indent))); let cond_span = if let Some(cond) = self.cond { cond.span @@ -917,12 +886,10 @@ impl<'a> Rewrite for ControlFlow<'a> { context.codemap.span_before(self.span, self.matcher.trim()) })); - let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, offset, width); + let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); - let after_cond_comment = extract_comment(mk_sp(cond_span.hi, self.block.span.lo), - context, - offset, - width); + let after_cond_comment = + extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { @@ -949,7 +916,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it // from being formatted on a single line. - // Note how we're passing the original width and offset, as the + // Note how we're passing the original shape, as the // cost of "else" should not cascade. ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -959,7 +926,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, width, offset) + .rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -969,13 +936,13 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, width, offset) + .rewrite(context, shape) } _ => { last_in_chain = true; // When rewriting a block, the width is only used for single line // blocks, passing 1 lets us avoid that. - else_block.rewrite(context, min(1, width), offset) + else_block.rewrite(context, Shape::legacy(min(1, shape.width), shape.indent)) } }; @@ -984,13 +951,13 @@ impl<'a> Rewrite for ControlFlow<'a> { context.codemap .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else")); let between_kwd_else_block_comment = - extract_comment(between_kwd_else_block, context, offset, width); + extract_comment(between_kwd_else_block, context, shape); let after_else = mk_sp(context.codemap .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), else_block.span.lo); - let after_else_comment = extract_comment(after_else, context, offset, width); + let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysNextLine | @@ -1021,18 +988,13 @@ fn rewrite_label(label: Option) -> String { } } -fn extract_comment(span: Span, - context: &RewriteContext, - offset: Indent, - width: usize) - -> Option { +fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { let comment_str = context.snippet(span); if contains_comment(&comment_str) { - let comment = - try_opt!(rewrite_comment(comment_str.trim(), false, width, offset, context.config)); + let comment = try_opt!(rewrite_comment(comment_str.trim(), false, shape, context.config)); Some(format!("\n{indent}{}\n{indent}", comment, - indent = offset.to_string(context.config))) + indent = shape.indent.to_string(context.config))) } else { None } @@ -1081,8 +1043,7 @@ fn is_unsafe_block(block: &ast::Block) -> bool { // are about the second arm fn rewrite_match_arm_comment(context: &RewriteContext, missed_str: &str, - width: usize, - arm_indent: Indent, + shape: Shape, arm_indent_str: &str) -> Option { // The leading "," is not part of the arm-comment @@ -1105,8 +1066,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, } let missed_str = missed_str[first..].trim(); if !missed_str.is_empty() { - let comment = - try_opt!(rewrite_comment(&missed_str, false, width, arm_indent, context.config)); + let comment = try_opt!(rewrite_comment(&missed_str, false, shape, context.config)); result.push('\n'); result.push_str(arm_indent_str); result.push_str(&comment); @@ -1118,8 +1078,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, fn rewrite_match(context: &RewriteContext, cond: &ast::Expr, arms: &[ast::Arm], - width: usize, - offset: Indent, + shape: Shape, span: Span) -> Option { if arms.is_empty() { @@ -1127,8 +1086,8 @@ fn rewrite_match(context: &RewriteContext, } // `match `cond` {` - let cond_budget = try_opt!(width.checked_sub(8)); - let cond_str = try_opt!(cond.rewrite(context, cond_budget, offset + 6)); + let cond_budget = try_opt!(shape.width.checked_sub(8)); + let cond_str = try_opt!(cond.rewrite(context, Shape::legacy(cond_budget, shape.indent + 6))); let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysSameLine => " ", @@ -1152,16 +1111,15 @@ fn rewrite_match(context: &RewriteContext, }; let comment = try_opt!(rewrite_match_arm_comment(context, &missed_str, - width, - arm_indent, + Shape::legacy(shape.width, arm_indent), &arm_indent_str)); result.push_str(&comment); result.push('\n'); result.push_str(&arm_indent_str); let arm_str = arm.rewrite(&nested_context, - context.config.max_width - arm_indent.width(), - arm_indent); + Shape::legacy(context.config.max_width - arm_indent.width(), + arm_indent)); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); } else { @@ -1176,8 +1134,7 @@ fn rewrite_match(context: &RewriteContext, let last_comment = context.snippet(last_span); let comment = try_opt!(rewrite_match_arm_comment(context, &last_comment, - width, - arm_indent, + Shape::legacy(shape.width, arm_indent), &arm_indent_str)); result.push_str(&comment); result.push('\n'); @@ -1221,8 +1178,8 @@ fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str // Match arms. impl Rewrite for ast::Arm { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("Arm::rewrite {:?} {} {:?}", self, width, offset); + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("Arm::rewrite {:?} {:?}", self, shape); let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; // FIXME this is all a bit grotty, would be nice to abstract out the @@ -1245,9 +1202,9 @@ impl Rewrite for ast::Arm { // Patterns // 5 = ` => {` - let pat_budget = try_opt!(width.checked_sub(5)); + let pat_budget = try_opt!(shape.width.checked_sub(5)); let pat_strs = try_opt!(pats.iter() - .map(|p| p.rewrite(context, pat_budget, offset)) + .map(|p| p.rewrite(context, Shape::legacy(pat_budget, shape.indent))) .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); @@ -1260,30 +1217,28 @@ impl Rewrite for ast::Arm { }, separator: " |", trailing_separator: SeparatorTactic::Never, - indent: offset, - width: pat_budget, + shape: Shape::legacy(pat_budget, shape.indent), ends_with_newline: false, config: context.config, }; let pats_str = try_opt!(write_list(items, &fmt)); let budget = if pats_str.contains('\n') { - context.config.max_width - offset.width() + context.config.max_width - shape.indent.width() } else { - width + shape.width }; let guard_str = try_opt!(rewrite_guard(context, guard, - budget, - offset, + Shape::legacy(budget, shape.indent), trimmed_last_line_width(&pats_str))); let pats_str = format!("{}{}", pats_str, guard_str); // Where the next text can start. let mut line_start = last_line_width(&pats_str); if !pats_str.contains('\n') { - line_start += offset.width(); + line_start += shape.indent.width(); } let body = match body.node { @@ -1306,8 +1261,10 @@ impl Rewrite for ast::Arm { // 4 = ` => `.len() if context.config.max_width > line_start + comma.len() + 4 { let budget = context.config.max_width - line_start - comma.len() - 4; - let offset = Indent::new(offset.block_indent, line_start + 4 - offset.block_indent); - let rewrite = nop_block_collapse(body.rewrite(context, budget, offset), budget); + let offset = Indent::new(shape.indent.block_indent, + line_start + 4 - shape.indent.block_indent); + let rewrite = nop_block_collapse(body.rewrite(context, Shape::legacy(budget, offset)), + budget); let is_block = if let ast::ExprKind::Block(..) = body.node { true } else { @@ -1335,13 +1292,14 @@ impl Rewrite for ast::Arm { // FIXME: we're doing a second rewrite of the expr; This may not be // necessary. - let body_budget = try_opt!(width.checked_sub(context.config.tab_spaces)); + let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces)); let indent = context.block_indent.block_indent(context.config); let inner_context = &RewriteContext { block_indent: indent, ..*context }; - let next_line_body = - try_opt!(nop_block_collapse(body.rewrite(inner_context, body_budget, indent), - body_budget)); - let indent_str = offset.block_indent(context.config).to_string(context.config); + let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context, + Shape::legacy(body_budget, + indent)), + body_budget)); + let indent_str = shape.indent.block_indent(context.config).to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms { if context.config.match_block_trailing_comma { ("{", "},") @@ -1362,7 +1320,7 @@ impl Rewrite for ast::Arm { block_sep, indent_str, next_line_body, - offset.to_string(context.config), + shape.indent.to_string(context.config), body_suffix)) } } @@ -1377,8 +1335,7 @@ fn pat_is_simple(pat_str: &str) -> bool { // The `if ...` guard on a match arm. fn rewrite_guard(context: &RewriteContext, guard: &Option>, - width: usize, - offset: Indent, + shape: Shape, // The amount of space used up on this line for the pattern in // the arm (excludes offset). pattern_width: usize) @@ -1387,23 +1344,28 @@ fn rewrite_guard(context: &RewriteContext, // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; - if overhead < width { - let cond_str = guard.rewrite(context, width - overhead, offset + pattern_width + 4); + if overhead < shape.width { + let cond_str = guard.rewrite(context, + Shape::legacy(shape.width - overhead, + shape.indent + pattern_width + 4)); if let Some(cond_str) = cond_str { return Some(format!(" if {}", cond_str)); } } // Not enough space to put the guard after the pattern, try a newline. - let overhead = offset.block_indent(context.config).width() + 4 + 5; - if overhead < width { + let overhead = shape.indent.block_indent(context.config).width() + 4 + 5; + if overhead < shape.width { let cond_str = guard.rewrite(context, - width - overhead, - // 3 == `if ` - offset.block_indent(context.config) + 3); + Shape::legacy(shape.width - overhead, + // 3 == `if ` + shape.indent.block_indent(context.config) + + 3)); if let Some(cond_str) = cond_str { return Some(format!("\n{}if {}", - offset.block_indent(context.config).to_string(context.config), + shape.indent + .block_indent(context.config) + .to_string(context.config), cond_str)); } } @@ -1421,8 +1383,7 @@ fn rewrite_pat_expr(context: &RewriteContext, // Connecting piece between pattern and expression, // *without* trailing space. connector: &str, - width: usize, - offset: Indent) + shape: Shape) -> Option { let mut result = match pat { Some(pat) => { @@ -1431,29 +1392,33 @@ fn rewrite_pat_expr(context: &RewriteContext, } else { format!("{} ", matcher) }; - let pat_budget = try_opt!(width.checked_sub(connector.len() + matcher.len())); - let pat_offset = offset + matcher.len(); - let pat_string = try_opt!(pat.rewrite(context, pat_budget, pat_offset)); + let pat_budget = try_opt!(shape.width.checked_sub(connector.len() + matcher.len())); + let pat_offset = shape.indent + matcher.len(); + let pat_string = try_opt!(pat.rewrite(context, Shape::legacy(pat_budget, pat_offset))); format!("{}{}{}", matcher, pat_string, connector) } None => String::new(), }; // Consider only the last line of the pat string. - let extra_offset = extra_offset(&result, offset); + let extra_offset = extra_offset(&result, shape.indent); // The expression may (partionally) fit on the current line. - if width > extra_offset + 1 { + if shape.width > extra_offset + 1 { let spacer = if pat.is_some() { " " } else { "" }; let expr_rewrite = expr.rewrite(context, - try_opt!(width.checked_sub(extra_offset + spacer.len())), - offset + extra_offset + spacer.len()); + Shape::legacy(try_opt!(shape.width + .checked_sub(extra_offset + + spacer.len())), + shape.indent + extra_offset + spacer.len())); if let Some(expr_string) = expr_rewrite { - let pat_simple = - pat.and_then(|p| p.rewrite(context, context.config.max_width, Indent::empty())) - .map(|s| pat_is_simple(&s)); + let pat_simple = pat.and_then(|p| { + p.rewrite(context, + Shape::legacy(context.config.max_width, Indent::empty())) + }) + .map(|s| pat_is_simple(&s)); if pat.is_none() || pat_simple.unwrap_or(false) || !expr_string.contains('\n') { result.push_str(spacer); @@ -1469,20 +1434,17 @@ fn rewrite_pat_expr(context: &RewriteContext, result.push('\n'); result.push_str(&nested.block_indent.to_string(context.config)); - let expr_rewrite = - expr.rewrite(&nested, - try_opt!(context.config.max_width.checked_sub(nested.block_indent.width())), - nested.block_indent); + let expr_rewrite = expr.rewrite(&nested, + Shape::legacy(try_opt!(context.config + .max_width + .checked_sub(nested.block_indent.width())), + nested.block_indent)); result.push_str(&try_opt!(expr_rewrite)); Some(result) } -fn rewrite_string_lit(context: &RewriteContext, - span: Span, - width: usize, - offset: Indent) - -> Option { +fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { let string_lit = context.snippet(span); if !context.config.format_strings && !context.config.force_format_strings { @@ -1490,7 +1452,7 @@ fn rewrite_string_lit(context: &RewriteContext, } if !context.config.force_format_strings && - !string_requires_rewrite(context, span, &string_lit, width, offset) { + !string_requires_rewrite(context, span, &string_lit, shape) { return Some(string_lit); } @@ -1499,8 +1461,7 @@ fn rewrite_string_lit(context: &RewriteContext, closer: "\"", line_start: " ", line_end: "\\", - width: width, - offset: offset, + shape: shape, trim_end: false, config: context.config, }; @@ -1514,20 +1475,19 @@ fn rewrite_string_lit(context: &RewriteContext, fn string_requires_rewrite(context: &RewriteContext, span: Span, string: &str, - width: usize, - offset: Indent) + shape: Shape) -> bool { - if context.codemap.lookup_char_pos(span.lo).col.0 != offset.width() { + if context.codemap.lookup_char_pos(span.lo).col.0 != shape.indent.width() { return true; } for (i, line) in string.lines().enumerate() { if i == 0 { - if line.len() > width { + if line.len() > shape.width { return true; } } else { - if line.len() > width + offset.width() { + if line.len() > shape.width + shape.indent.width() { return true; } } @@ -1540,17 +1500,15 @@ pub fn rewrite_call(context: &RewriteContext, callee: &R, args: &[ptr::P], span: Span, - width: usize, - offset: Indent) + shape: Shape) -> Option where R: Rewrite { - let closure = |callee_max_width| { - rewrite_call_inner(context, callee, callee_max_width, args, span, width, offset) - }; + let closure = + |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape); // 2 is for parens - let max_width = try_opt!(width.checked_sub(2)); + let max_width = try_opt!(shape.width.checked_sub(2)); binary_search(1, max_width, closure) } @@ -1559,15 +1517,14 @@ fn rewrite_call_inner(context: &RewriteContext, max_callee_width: usize, args: &[ptr::P], span: Span, - width: usize, - offset: Indent) + shape: Shape) -> Result where R: Rewrite { let callee = callee.borrow(); // FIXME using byte lens instead of char lens (and probably all over the // place too) - let callee_str = match callee.rewrite(context, max_callee_width, offset) { + let callee_str = match callee.rewrite(context, Shape::legacy(max_callee_width, shape.indent)) { Some(string) => { if !string.contains('\n') && string.len() > max_callee_width { panic!("{:?} {}", string, max_callee_width); @@ -1581,13 +1538,13 @@ fn rewrite_call_inner(context: &RewriteContext, let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); - let extra_offset = extra_offset(&callee_str, offset); + let extra_offset = extra_offset(&callee_str, shape.indent); // 2 is for parens. - let remaining_width = match width.checked_sub(extra_offset + 2) { + let remaining_width = match shape.width.checked_sub(extra_offset + 2) { Some(str) => str, None => return Err(Ordering::Greater), }; - let offset = offset + extra_offset + 1; + let offset = shape.indent + extra_offset + 1; let arg_count = args.len(); let block_indent = if arg_count == 1 { context.block_indent @@ -1596,14 +1553,15 @@ fn rewrite_call_inner(context: &RewriteContext, }; let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; - let items = itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(inner_context, remaining_width, offset), - span.lo, - span.hi); + let items = + itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(inner_context, Shape::legacy(remaining_width, offset)), + span.lo, + span.hi); let mut item_vec: Vec<_> = items.collect(); // Try letting the last argument overflow to the next line with block @@ -1622,7 +1580,8 @@ fn rewrite_call_inner(context: &RewriteContext, // first arguments. if overflow_last { let inner_context = &RewriteContext { block_indent: context.block_indent, ..*context }; - let rewrite = args.last().unwrap().rewrite(inner_context, remaining_width, offset); + let rewrite = + args.last().unwrap().rewrite(inner_context, Shape::legacy(remaining_width, offset)); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); @@ -1654,8 +1613,7 @@ fn rewrite_call_inner(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: offset, - width: width, + shape: Shape::legacy(shape.width, offset), ends_with_newline: false, config: context.config, }; @@ -1672,15 +1630,13 @@ fn rewrite_call_inner(context: &RewriteContext, }) } -fn rewrite_paren(context: &RewriteContext, - subexpr: &ast::Expr, - width: usize, - offset: Indent) - -> Option { - debug!("rewrite_paren, width: {}, offset: {:?}", width, offset); +fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { + debug!("rewrite_paren, shape: {:?}", shape); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr. - let subexpr_str = subexpr.rewrite(context, try_opt!(width.checked_sub(2)), offset + 1); + let subexpr_str = subexpr.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(2)), + shape.indent + 1)); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); subexpr_str.map(|s| if context.config.spaces_within_parens && s.len() > 0 { @@ -1693,10 +1649,9 @@ fn rewrite_paren(context: &RewriteContext, fn rewrite_index(expr: &ast::Expr, index: &ast::Expr, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { - let expr_str = try_opt!(expr.rewrite(context, width, offset)); + let expr_str = try_opt!(expr.rewrite(context, shape)); let (lbr, rbr) = if context.config.spaces_within_square_brackets { ("[ ", " ]") @@ -1704,19 +1659,19 @@ fn rewrite_index(expr: &ast::Expr, ("[", "]") }; - let budget = width.checked_sub(expr_str.len() + lbr.len() + rbr.len()).unwrap_or(0); - let index_str = index.rewrite(context, budget, offset); + let budget = shape.width.checked_sub(expr_str.len() + lbr.len() + rbr.len()).unwrap_or(0); + let index_str = index.rewrite(context, Shape::legacy(budget, shape.indent)); if let Some(index_str) = index_str { return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); } - let indent = offset.block_indent(&context.config); + let indent = shape.indent.block_indent(&context.config); let indent = indent.to_string(&context.config); - // FIXME this is not right, since we don't take into account that width + // FIXME this is not right, since we don't take into account that shape.width // might be reduced from max_width by something on the right. let budget = try_opt!(context.config.max_width.checked_sub(indent.len() + lbr.len() + rbr.len())); - let index_str = try_opt!(index.rewrite(context, budget, offset)); + let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr)) } @@ -1725,10 +1680,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, fields: &'a [ast::Field], base: Option<&'a ast::Expr>, span: Span, - width: usize, - offset: Indent) + shape: Shape) -> Option { - debug!("rewrite_struct_lit: width {}, offset {:?}", width, offset); + debug!("rewrite_struct_lit: shape {:?}", shape); enum StructLitField<'a> { Regular(&'a ast::Field), @@ -1736,15 +1690,18 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } // 2 = " {".len() - let path_budget = try_opt!(width.checked_sub(2)); - let path_str = - try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_budget, offset)); + let path_budget = try_opt!(shape.width.checked_sub(2)); + let path_str = try_opt!(rewrite_path(context, + PathContext::Expr, + None, + path, + Shape::legacy(path_budget, shape.indent))); // Foo { a: Foo } - indent is +3, width is -5. - let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0); + let h_budget = shape.width.checked_sub(path_str.len() + 5).unwrap_or(0); // The 1 taken from the v_budget is for the comma. let (indent, v_budget) = match context.config.struct_lit_style { - StructLitStyle::Visual => (offset + path_str.len() + 3, h_budget), + StructLitStyle::Visual => (shape.indent + path_str.len() + 3, h_budget), StructLitStyle::Block => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. @@ -1783,12 +1740,12 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, StructLitField::Regular(field) => { rewrite_field(inner_context, field, - v_budget.checked_sub(1).unwrap_or(0), - indent) + Shape::legacy(v_budget.checked_sub(1).unwrap_or(0), indent)) } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(inner_context, try_opt!(v_budget.checked_sub(2)), indent + 2) + expr.rewrite(inner_context, + Shape::legacy(try_opt!(v_budget.checked_sub(2)), indent + 2)) .map(|s| format!("..{}", s)) } } @@ -1826,8 +1783,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } else { context.config.struct_lit_trailing_comma }, - indent: indent, - width: budget, + shape: Shape::legacy(budget, indent), ends_with_newline: ends_with_newline, config: context.config, }; @@ -1870,27 +1826,23 @@ pub fn type_annotation_separator(config: &Config) -> &str { } } -fn rewrite_field(context: &RewriteContext, - field: &ast::Field, - width: usize, - offset: Indent) - -> Option { +fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { let name = &field.ident.node.to_string(); let separator = type_annotation_separator(context.config); let overhead = name.len() + separator.len(); let expr = field.expr.rewrite(context, - try_opt!(width.checked_sub(overhead)), - offset + overhead); + Shape::legacy(try_opt!(shape.width.checked_sub(overhead)), + shape.indent + overhead)); match expr { Some(e) => Some(format!("{}{}{}", name, separator, e)), None => { - let expr_offset = offset.block_indent(context.config); + let expr_offset = shape.indent.block_indent(context.config); let expr = field.expr.rewrite(context, - try_opt!(context.config - .max_width - .checked_sub(expr_offset.width())), - expr_offset); + Shape::legacy(try_opt!(context.config + .max_width + .checked_sub(expr_offset.width())), + expr_offset)); expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) } } @@ -1899,23 +1851,22 @@ fn rewrite_field(context: &RewriteContext, pub fn rewrite_tuple<'a, I>(context: &RewriteContext, mut items: I, span: Span, - width: usize, - offset: Indent) + shape: Shape) -> Option where I: ExactSizeIterator, ::Item: Deref, ::Target: Rewrite + Spanned + 'a { - let indent = offset + 1; + let indent = shape.indent + 1; let aligned = RewriteContext { block_indent: indent, ..context.clone() }; // In case of length 1, need a trailing comma if items.len() == 1 { // 3 = "(" + ",)" - let budget = try_opt!(width.checked_sub(3)); + let budget = try_opt!(shape.width.checked_sub(3)); return items.next() .unwrap() - .rewrite(&aligned, budget, indent) + .rewrite(&aligned, Shape::legacy(budget, indent)) .map(|s| if context.config.spaces_within_parens { format!("( {}, )", s) } else { @@ -1924,16 +1875,16 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, } let list_lo = context.codemap.span_after(span, "("); - let budget = try_opt!(width.checked_sub(2)); + let budget = try_opt!(shape.width.checked_sub(2)); let items = itemize_list(context.codemap, items, ")", |item| item.span().lo, |item| item.span().hi, - |item| item.rewrite(&aligned, budget, indent), + |item| item.rewrite(&aligned, Shape::legacy(budget, indent)), list_lo, span.hi - BytePos(1)); - let list_str = try_opt!(format_item_list(items, budget, indent, context.config)); + let list_str = try_opt!(format_item_list(items, Shape::legacy(budget, indent), context.config)); if context.config.spaces_within_parens && list_str.len() > 0 { Some(format!("( {} )", list_str)) @@ -1945,12 +1896,11 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, pub fn rewrite_unary_prefix(context: &RewriteContext, prefix: &str, rewrite: &R, - width: usize, - offset: Indent) + shape: Shape) -> Option { rewrite.rewrite(context, - try_opt!(width.checked_sub(prefix.len())), - offset + prefix.len()) + Shape::legacy(try_opt!(shape.width.checked_sub(prefix.len())), + shape.indent + prefix.len())) .map(|r| format!("{}{}", prefix, r)) } @@ -1959,10 +1909,11 @@ pub fn rewrite_unary_prefix(context: &RewriteContext, pub fn rewrite_unary_suffix(context: &RewriteContext, suffix: &str, rewrite: &R, - width: usize, - offset: Indent) + shape: Shape) -> Option { - rewrite.rewrite(context, try_opt!(width.checked_sub(suffix.len())), offset) + rewrite.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(suffix.len())), + shape.indent)) .map(|mut r| { r.push_str(suffix); r @@ -1972,8 +1923,7 @@ pub fn rewrite_unary_suffix(context: &RewriteContext, fn rewrite_unary_op(context: &RewriteContext, op: &ast::UnOp, expr: &ast::Expr, - width: usize, - offset: Indent) + shape: Shape) -> Option { // For some reason, an UnOp is not spanned like BinOp! let operator_str = match *op { @@ -1981,15 +1931,14 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::Not => "!", ast::UnOp::Neg => "-", }; - rewrite_unary_prefix(context, operator_str, expr, width, offset) + rewrite_unary_prefix(context, operator_str, expr, shape) } fn rewrite_assignment(context: &RewriteContext, lhs: &ast::Expr, rhs: &ast::Expr, op: Option<&ast::BinOp>, - width: usize, - offset: Indent) + shape: Shape) -> Option { let operator_str = match op { Some(op) => context.snippet(op.span), @@ -1997,12 +1946,12 @@ fn rewrite_assignment(context: &RewriteContext, }; // 1 = space between lhs and operator. - let max_width = try_opt!(width.checked_sub(operator_str.len() + 1)); + let max_width = try_opt!(shape.width.checked_sub(operator_str.len() + 1)); let lhs_str = format!("{} {}", - try_opt!(lhs.rewrite(context, max_width, offset)), + try_opt!(lhs.rewrite(context, Shape::legacy(max_width, shape.indent))), operator_str); - rewrite_assign_rhs(context, lhs_str, rhs, width, offset) + rewrite_assign_rhs(context, lhs_str, rhs, shape) } // The left hand side must contain everything up to, and including, the @@ -2010,19 +1959,19 @@ fn rewrite_assignment(context: &RewriteContext, pub fn rewrite_assign_rhs>(context: &RewriteContext, lhs: S, ex: &ast::Expr, - width: usize, - offset: Indent) + shape: Shape) -> Option { let mut result = lhs.into(); let last_line_width = last_line_width(&result) - if result.contains('\n') { - offset.width() + shape.indent.width() } else { 0 }; // 1 = space between operator and rhs. - let max_width = try_opt!(width.checked_sub(last_line_width + 1)); - let rhs = ex.rewrite(context, max_width, offset + last_line_width + 1); + let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1)); + let rhs = ex.rewrite(context, + Shape::legacy(max_width, shape.indent + last_line_width + 1)); fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() @@ -2037,10 +1986,11 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // Expression did not fit on the same line as the identifier or is // at least three lines big. Try splitting the line and see // if that works better. - let new_offset = offset.block_indent(context.config); - let max_width = try_opt!((width + offset.width()).checked_sub(new_offset.width())); + let new_offset = shape.indent.block_indent(context.config); + let max_width = try_opt!((shape.width + shape.indent.width()) + .checked_sub(new_offset.width())); let inner_context = context.nested_context(); - let new_rhs = ex.rewrite(&inner_context, max_width, new_offset); + let new_rhs = ex.rewrite(&inner_context, Shape::legacy(max_width, new_offset)); // FIXME: DRY! match (rhs, new_rhs) { @@ -2069,12 +2019,11 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, fn rewrite_expr_addrof(context: &RewriteContext, mutability: ast::Mutability, expr: &ast::Expr, - width: usize, - offset: Indent) + shape: Shape) -> Option { let operator_str = match mutability { ast::Mutability::Immutable => "&", ast::Mutability::Mutable => "&mut ", }; - rewrite_unary_prefix(context, operator_str, expr, width, offset) + rewrite_unary_prefix(context, operator_str, expr, shape) } diff --git a/src/imports.rs b/src/imports.rs index a75a571c553..6e7c2d0f7e2 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Indent; +use Shape; use utils; use syntax::codemap::{self, BytePos, Span}; use codemap::SpanUtils; @@ -125,19 +125,19 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => { Some(String::new()) } ast::ViewPath_::ViewPathList(ref path, ref path_list) => { - rewrite_use_list(width, offset, path, path_list, self.span, context) + rewrite_use_list(shape, path, path_list, self.span, context) } ast::ViewPath_::ViewPathGlob(_) => None, ast::ViewPath_::ViewPathSimple(ident, ref path) => { let ident_str = ident.to_string(); // 4 = " as ".len() - let budget = try_opt!(width.checked_sub(ident_str.len() + 4)); + let budget = try_opt!(shape.width.checked_sub(ident_str.len() + 4)); let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && path.segments.len() > 1 { @@ -149,10 +149,13 @@ impl Rewrite for ast::ViewPath { PathContext::Import, None, &path, - budget, - offset)) + Shape::legacy(budget, shape.indent))) } else { - try_opt!(rewrite_path(context, PathContext::Import, None, path, budget, offset)) + try_opt!(rewrite_path(context, + PathContext::Import, + None, + path, + Shape::legacy(budget, shape.indent))) }; Some(if path.segments.last().unwrap().identifier == ident { @@ -225,8 +228,7 @@ impl<'a> FmtVisitor<'a> { offset.alignment += vis.len() + "use ".len(); // 1 = ";" match vp.rewrite(&self.get_context(), - self.config.max_width - offset.width() - 1, - offset) { + Shape::legacy(self.config.max_width - offset.width() - 1, offset)) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, source!(self, span).lo); @@ -283,15 +285,14 @@ fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { // Pretty prints a multi-item import. // Assumes that path_list.len() > 0. -pub fn rewrite_use_list(width: usize, - offset: Indent, +pub fn rewrite_use_list(shape: Shape, path: &ast::Path, path_list: &[ast::PathListItem], span: Span, context: &RewriteContext) -> Option { // Returns a different option to distinguish `::foo` and `foo` - let path_str = try_opt!(rewrite_path(context, PathContext::Import, None, path, width, offset)); + let path_str = try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)); match path_list.len() { 0 => unreachable!(), @@ -300,7 +301,7 @@ pub fn rewrite_use_list(width: usize, } // 2 = {} - let remaining_width = width.checked_sub(path_str.len() + 2).unwrap_or(0); + let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); let mut items = { // Dummy value, see explanation below. @@ -336,11 +337,11 @@ pub fn rewrite_use_list(width: usize, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: offset + path_str.len() + 1 + colons_offset, // FIXME This is too conservative, and will not use all width // available // (loose 1 column (";")) - width: remaining_width, + shape: Shape::legacy(remaining_width, + shape.indent + path_str.len() + 1 + colons_offset), ends_with_newline: false, config: context.config, }; diff --git a/src/items.rs b/src/items.rs index 8270a52ce76..3c5bf3ce6ce 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,7 +10,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. -use Indent; +use {Indent, Shape}; use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr}; @@ -30,14 +30,18 @@ use syntax::ast::ImplItem; // Statements of the form // let pat: ty = init; impl Rewrite for ast::Local { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - debug!("Local::rewrite {:?} {} {:?}", self, width, offset); + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("Local::rewrite {:?} {} {:?}", + self, + shape.width, + shape.indent); let mut result = "let ".to_owned(); - let pattern_offset = offset + result.len(); + let pattern_offset = shape.indent + result.len(); // 1 = ; - let pattern_width = try_opt!(width.checked_sub(pattern_offset.width() + 1)); + let pattern_width = try_opt!(shape.width.checked_sub(pattern_offset.width() + 1)); - let pat_str = try_opt!(self.pat.rewrite(&context, pattern_width, pattern_offset)); + let pat_str = try_opt!(self.pat + .rewrite(&context, Shape::legacy(pattern_width, pattern_offset))); result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -46,10 +50,10 @@ impl Rewrite for ast::Local { if let Some(ref ty) = self.ty { let separator = type_annotation_separator(context.config); - let indent = offset + last_line_width(&result) + separator.len(); + let indent = shape.indent + last_line_width(&result) + separator.len(); // 1 = ; - let budget = try_opt!(width.checked_sub(indent.width() + 1)); - let rewrite = try_opt!(ty.rewrite(context, budget, indent)); + let budget = try_opt!(shape.width.checked_sub(indent.width() + 1)); + let rewrite = try_opt!(ty.rewrite(context, Shape::legacy(budget, indent))); infix.push_str(separator); infix.push_str(&rewrite); @@ -66,10 +70,12 @@ impl Rewrite for ast::Local { if let Some(ref ex) = self.init { // 1 = trailing semicolon; - let budget = try_opt!(width.checked_sub(context.block_indent.width() + 1)); + let budget = try_opt!(shape.width.checked_sub(context.block_indent.width() + 1)); - result = - try_opt!(rewrite_assign_rhs(&context, result, ex, budget, context.block_indent)); + result = try_opt!(rewrite_assign_rhs(&context, + result, + ex, + Shape::legacy(budget, context.block_indent))); } result.push(';'); @@ -200,7 +206,7 @@ impl<'a> FmtVisitor<'a> { let offset = self.block_indent + prefix.len(); // 1 = ; let width = self.config.max_width - offset.width() - 1; - let rewrite = ty.rewrite(&self.get_context(), width, offset); + let rewrite = ty.rewrite(&self.get_context(), Shape::legacy(width, offset)); match rewrite { Some(result) => { @@ -321,15 +327,17 @@ impl<'a> FmtVisitor<'a> { let suffix = if semicolon_for_expr(e) { ";" } else { "" }; e.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) + Shape::legacy(self.config.max_width - + self.block_indent.width(), + self.block_indent)) .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } None => { stmt.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) + Shape::legacy(self.config.max_width - + self.block_indent.width(), + self.block_indent)) } } } else { @@ -426,8 +434,7 @@ impl<'a> FmtVisitor<'a> { tactic: DefinitiveListTactic::Vertical, separator: ",", trailing_separator: SeparatorTactic::from_bool(self.config.enum_trailing_comma), - indent: self.block_indent, - width: budget, + shape: Shape::legacy(budget, self.block_indent), ends_with_newline: true, config: self.config, }; @@ -450,8 +457,7 @@ impl<'a> FmtVisitor<'a> { let mut result = try_opt!(field.node .attrs .rewrite(&self.get_context(), - self.config.max_width - indent.width(), - indent)); + Shape::legacy(self.config.max_width - indent.width(), indent))); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -481,8 +487,7 @@ impl<'a> FmtVisitor<'a> { wrap_str(tag, self.config.max_width, - self.config.max_width - indent.width(), - indent) + Shape::legacy(self.config.max_width - indent.width(), indent)) } }; @@ -514,8 +519,8 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - &generics.where_clause, context.config, context.config.item_brace_style, - context.block_indent, - where_budget, + Shape::legacy(where_budget, + context.block_indent), context.config.where_density, "{", true, @@ -628,8 +633,8 @@ fn format_impl_ref_and_type(context: &RewriteContext, }; let generics_str = try_opt!(rewrite_generics(context, generics, - offset, - context.config.max_width, + Shape::legacy(context.config.max_width, + offset), offset + result.len(), mk_sp(lo, hi))); result.push_str(&generics_str); @@ -643,7 +648,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, } let budget = try_opt!(context.config.max_width.checked_sub(result.len())); let indent = offset + result.len(); - result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent))); + result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent)))); if split_at_for { result.push('\n'); @@ -673,7 +678,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, // 1 = space before the type. let budget = try_opt!(context.config.max_width.checked_sub(used_space + 1)); let indent = offset + result.len() + 1; - let self_ty_str = self_ty.rewrite(context, budget, indent); + let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent)); if let Some(self_ty_str) = self_ty_str { result.push_str(" "); result.push_str(&self_ty_str); @@ -684,7 +689,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, let indent = offset.block_indent(context.config); result.push_str(&format!("\n{}", indent.to_string(context.config))); let budget = try_opt!(context.config.max_width.checked_sub(indent.width())); - result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent))); + result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, indent)))); Some(result) } else { unreachable!(); @@ -742,16 +747,16 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let generics_str = try_opt!(rewrite_generics(context, generics, - offset, - context.config.max_width, + Shape::legacy(context.config.max_width, + offset), offset + result.len(), mk_sp(item.span.lo, body_lo))); result.push_str(&generics_str); - let trait_bound_str = try_opt!(rewrite_trait_bounds(context, - type_param_bounds, - offset, - context.config.max_width)); + let trait_bound_str = + try_opt!(rewrite_trait_bounds(context, + type_param_bounds, + Shape::legacy(context.config.max_width, offset))); // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line if offset.width() + last_line_width(&result) + trait_bound_str.len() > @@ -783,8 +788,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) &generics.where_clause, context.config, context.config.item_brace_style, - context.block_indent, - where_budget, + Shape::legacy(where_budget, + context.block_indent), where_density, "{", has_body, @@ -916,22 +921,23 @@ fn format_struct_struct(context: &RewriteContext, // 1 = "," let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 1)); - let items = itemize_list(context.codemap, - fields.iter(), - "}", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, item_budget, item_indent), - context.codemap.span_after(span, "{"), - span.hi) - .collect::>(); + let items = + itemize_list(context.codemap, + fields.iter(), + "}", + |field| { + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.ty.span.hi, + |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), + context.codemap.span_after(span, "{"), + span.hi) + .collect::>(); // 1 = , let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1; @@ -944,8 +950,7 @@ fn format_struct_struct(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: context.config.struct_trailing_comma, - indent: item_indent, - width: budget, + shape: Shape::legacy(budget, item_indent), ends_with_newline: true, config: context.config, }; @@ -986,8 +991,8 @@ fn format_tuple_struct(context: &RewriteContext, Some(generics) => { let generics_str = try_opt!(rewrite_generics(context, generics, - offset, - context.config.max_width, + Shape::legacy(context.config.max_width, + offset), offset + header_str.len(), mk_sp(span.lo, body_lo))); result.push_str(&generics_str); @@ -999,8 +1004,7 @@ fn format_tuple_struct(context: &RewriteContext, &generics.where_clause, context.config, context.config.item_brace_style, - context.block_indent, - where_budget, + Shape::legacy(where_budget, context.block_indent), Density::Compressed, ";", false, @@ -1014,22 +1018,25 @@ fn format_tuple_struct(context: &RewriteContext, // 2 = ");" let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2)); - let items = itemize_list(context.codemap, - fields.iter(), - ")", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, item_budget, item_indent), - context.codemap.span_after(span, "("), - span.hi); - let body = try_opt!(format_item_list(items, item_budget, item_indent, context.config)); + let items = + itemize_list(context.codemap, + fields.iter(), + ")", + |field| { + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.ty.span.hi, + |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), + context.codemap.span_after(span, "("), + span.hi); + let body = try_opt!(format_item_list(items, + Shape::legacy(item_budget, item_indent), + context.config)); if context.config.spaces_within_parens && body.len() > 0 { result.push(' '); @@ -1077,8 +1084,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_width = context.config.max_width - " =".len(); let generics_str = try_opt!(rewrite_generics(context, generics, - indent, - generics_width, + Shape::legacy(generics_width, indent), generics_indent, generics_span)); @@ -1091,8 +1097,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, &generics.where_clause, context.config, context.config.item_brace_style, - indent, - where_budget, + Shape::legacy(where_budget, indent), context.config.where_density, "=", false, @@ -1109,7 +1114,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, .unwrap_or(0); let type_indent = indent + line_width; // Try to fit the type on the same line - let ty_str = try_opt!(ty.rewrite(context, budget, type_indent) + let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)) .or_else(|| { // The line was too short, try to put the type on the next line @@ -1121,7 +1126,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, let budget = try_opt!(context.config .max_width .checked_sub(type_indent.width() + ";".len())); - ty.rewrite(context, budget, type_indent) + ty.rewrite(context, Shape::legacy(budget, type_indent)) })); result.push_str(&ty_str); result.push_str(";"); @@ -1142,19 +1147,21 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { } impl Rewrite for ast::StructField { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if contains_skip(&self.attrs) { let span = context.snippet(mk_sp(self.attrs[0].span.lo, self.span.hi)); - return wrap_str(span, context.config.max_width, width, offset); + return wrap_str(span, context.config.max_width, shape); } let name = self.ident; let vis = format_visibility(&self.vis); let mut attr_str = try_opt!(self.attrs - .rewrite(context, context.config.max_width - offset.width(), offset)); + .rewrite(context, + Shape::legacy(context.config.max_width - shape.indent.width(), + shape.indent))); if !attr_str.is_empty() { attr_str.push('\n'); - attr_str.push_str(&offset.to_string(context.config)); + attr_str.push_str(&shape.indent.to_string(context.config)); } let type_annotation_spacing = type_annotation_spacing(context.config); @@ -1171,8 +1178,10 @@ impl Rewrite for ast::StructField { }; let last_line_width = last_line_width(&result); - let budget = try_opt!(width.checked_sub(last_line_width)); - let rewrite = try_opt!(self.ty.rewrite(context, budget, offset + last_line_width)); + let budget = try_opt!(shape.width.checked_sub(last_line_width)); + let rewrite = try_opt!(self.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + last_line_width))); Some(result + &rewrite) } } @@ -1195,15 +1204,20 @@ pub fn rewrite_static(prefix: &str, type_annotation_spacing.1); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, - context.config.max_width - context.block_indent.width() - - prefix.len() - 2, - context.block_indent)); + Shape::legacy(context.config.max_width - + context.block_indent.width() - + prefix.len() - + 2, + context.block_indent))); if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) + rewrite_assign_rhs(context, + lhs, + expr, + Shape::legacy(remaining_width, context.block_indent)) .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); @@ -1222,7 +1236,9 @@ pub fn rewrite_associated_type(ident: ast::Ident, let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!(bounds.iter() - .map(|ty_bound| ty_bound.rewrite(context, context.config.max_width, indent)) + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) + }) .intersperse(Some(" + ".to_string())) .collect::>()); if bounds.len() > 0 { @@ -1236,10 +1252,11 @@ pub fn rewrite_associated_type(ident: ast::Ident, if let Some(ty) = ty_opt { let ty_str = try_opt!(ty.rewrite(context, - context.config.max_width - context.block_indent.width() - - prefix.len() - - 2, - context.block_indent)); + Shape::legacy(context.config.max_width - + context.block_indent.width() - + prefix.len() - + 2, + context.block_indent))); Some(format!("{} = {};", prefix, ty_str)) } else { Some(format!("{}{};", prefix, type_bounds_str)) @@ -1247,21 +1264,23 @@ pub fn rewrite_associated_type(ident: ast::Ident, } impl Rewrite for ast::FunctionRetTy { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { ast::FunctionRetTy::Default(_) => Some(String::new()), ast::FunctionRetTy::Ty(ref ty) => { - let inner_width = try_opt!(width.checked_sub(3)); - ty.rewrite(context, inner_width, offset + 3).map(|r| format!("-> {}", r)) + let inner_width = try_opt!(shape.width.checked_sub(3)); + ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) + .map(|r| format!("-> {}", r)) } } } } impl Rewrite for ast::Arg { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!(self.pat.rewrite(context, width, offset)); + let mut result = try_opt!(self.pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))); if self.ty.node != ast::TyKind::Infer { if context.config.space_before_type_annotation { @@ -1271,14 +1290,16 @@ impl Rewrite for ast::Arg { if context.config.space_after_type_annotation_colon { result.push_str(" "); } - let max_width = try_opt!(width.checked_sub(result.len())); - let ty_str = try_opt!(self.ty.rewrite(context, max_width, offset + result.len())); + let max_width = try_opt!(shape.width.checked_sub(result.len())); + let ty_str = try_opt!(self.ty.rewrite(context, + Shape::legacy(max_width, + shape.indent + result.len()))); result.push_str(&ty_str); } Some(result) } else { - self.ty.rewrite(context, width, offset) + self.ty.rewrite(context, shape) } } } @@ -1292,8 +1313,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = - try_opt!(l.rewrite(context, usize::max_value(), Indent::empty())); + let lifetime_str = try_opt!(l.rewrite(context, + Shape::legacy(usize::max_value(), Indent::empty()))); Some(format!("&{} {}self", lifetime_str, mut_str)) } None => Some(format!("&{}self", mut_str)), @@ -1303,7 +1324,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); - let type_str = try_opt!(ty.rewrite(context, usize::max_value(), Indent::empty())); + let type_str = + try_opt!(ty.rewrite(context, Shape::legacy(usize::max_value(), Indent::empty()))); Some(format!("{}self: {}", format_mutability(mutability), type_str)) } @@ -1427,8 +1449,7 @@ fn rewrite_fn_base(context: &RewriteContext, let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); let generics_str = try_opt!(rewrite_generics(context, generics, - indent, - context.config.max_width, + Shape::legacy(context.config.max_width, indent), generics_indent, generics_span)); result.push_str(&generics_str); @@ -1436,7 +1457,8 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that if the width and indent really matter, we'll re-layout the // return type later anyway. let ret_str = try_opt!(fd.output - .rewrite(&context, context.config.max_width - indent.width(), indent)); + .rewrite(&context, + Shape::legacy(context.config.max_width - indent.width(), indent))); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -1571,7 +1593,7 @@ fn rewrite_fn_base(context: &RewriteContext, // Now that we know the proper indent and width, we need to // re-layout the return type. let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); - let ret_str = try_opt!(fd.output.rewrite(context, budget, ret_indent)); + let ret_str = try_opt!(fd.output.rewrite(context, Shape::legacy(budget, ret_indent))); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -1612,8 +1634,7 @@ fn rewrite_fn_base(context: &RewriteContext, where_clause, context.config, context.config.fn_brace_style, - indent, - where_budget, + Shape::legacy(where_budget, indent), where_density, "{", has_body, @@ -1640,7 +1661,7 @@ fn rewrite_args(context: &RewriteContext, variadic: bool) -> Option { let mut arg_item_strs = try_opt!(args.iter() - .map(|arg| arg.rewrite(&context, multi_line_budget, arg_indent)) + .map(|arg| arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent))) .collect::>>()); // Account for sugary self. @@ -1744,8 +1765,7 @@ fn rewrite_args(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: indent, - width: budget, + shape: Shape::legacy(budget, indent), ends_with_newline: end_with_newline, config: context.config, }; @@ -1812,8 +1832,8 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { fn rewrite_generics(context: &RewriteContext, generics: &ast::Generics, - offset: Indent, - width: usize, + shape: Shape, + // TODO shouldn't need this generics_offset: Indent, span: Span) -> Option { @@ -1826,18 +1846,19 @@ fn rewrite_generics(context: &RewriteContext, } let offset = match context.config.generics_indent { - BlockIndentStyle::Inherit => offset, - BlockIndentStyle::Tabbed => offset.block_indent(context.config), + BlockIndentStyle::Inherit => shape.indent, + BlockIndentStyle::Tabbed => shape.indent.block_indent(context.config), // 1 = < BlockIndentStyle::Visual => generics_offset + 1, }; - let h_budget = try_opt!(width.checked_sub(generics_offset.width() + 2)); + let h_budget = try_opt!(shape.width.checked_sub(generics_offset.width() + 2)); // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. - let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, h_budget, offset)); - let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(context, h_budget, offset)); + let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, Shape::legacy(h_budget, offset))); + let ty_strs = tys.iter() + .map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { @@ -1859,7 +1880,8 @@ fn rewrite_generics(context: &RewriteContext, |&(_, ref str)| str.clone(), context.codemap.span_after(span, "<"), span.hi); - let list_str = try_opt!(format_item_list(items, h_budget, offset, context.config)); + let list_str = + try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); Some(if context.config.spaces_within_angle_brackets { format!("< {} >", list_str) @@ -1870,8 +1892,7 @@ fn rewrite_generics(context: &RewriteContext, fn rewrite_trait_bounds(context: &RewriteContext, type_param_bounds: &ast::TyParamBounds, - indent: Indent, - width: usize) + shape: Shape) -> Option { let bounds: &[_] = type_param_bounds; @@ -1880,7 +1901,7 @@ fn rewrite_trait_bounds(context: &RewriteContext, } let bound_str = try_opt!(bounds.iter() - .map(|ty_bound| ty_bound.rewrite(&context, width, indent)) + .map(|ty_bound| ty_bound.rewrite(&context, shape)) .intersperse(Some(" + ".to_string())) .collect::>()); @@ -1894,8 +1915,7 @@ fn rewrite_where_clause(context: &RewriteContext, where_clause: &ast::WhereClause, config: &Config, brace_style: BraceStyle, - indent: Indent, - width: usize, + shape: Shape, density: Density, terminator: &str, allow_trailing_comma: bool, @@ -1911,10 +1931,10 @@ fn rewrite_where_clause(context: &RewriteContext, }; let offset = match context.config.where_pred_indent { - BlockIndentStyle::Inherit => indent + extra_indent, - BlockIndentStyle::Tabbed => indent + extra_indent.block_indent(config), + BlockIndentStyle::Inherit => shape.indent + extra_indent, + BlockIndentStyle::Tabbed => shape.indent + extra_indent.block_indent(config), // 6 = "where ".len() - BlockIndentStyle::Visual => indent + extra_indent + 6, + BlockIndentStyle::Visual => shape.indent + extra_indent + 6, }; // FIXME: if where_pred_indent != Visual, then the budgets below might // be out by a char or two. @@ -1931,7 +1951,7 @@ fn rewrite_where_clause(context: &RewriteContext, terminator, |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(context, budget, offset), + |pred| pred.rewrite(context, Shape::legacy(budget, offset)), span_start, span_end); let item_vec = items.collect::>(); @@ -1944,8 +1964,7 @@ fn rewrite_where_clause(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::from_bool(use_trailing_comma), - indent: offset, - width: budget, + shape: Shape::legacy(budget, offset), ends_with_newline: true, config: context.config, }; @@ -1965,9 +1984,9 @@ fn rewrite_where_clause(context: &RewriteContext, terminator.len() }; if density == Density::Tall || preds_str.contains('\n') || - indent.width() + " where ".len() + preds_str.len() + end_length > width { + shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { Some(format!("\n{}where {}", - (indent + extra_indent).to_string(context.config), + (shape.indent + extra_indent).to_string(context.config), preds_str)) } else { Some(format!(" where {}", preds_str)) @@ -1990,8 +2009,7 @@ fn format_generics(context: &RewriteContext, -> Option { let mut result = try_opt!(rewrite_generics(context, generics, - offset, - context.config.max_width, + Shape::legacy(context.config.max_width, offset), generics_offset, span)); @@ -2001,8 +2019,8 @@ fn format_generics(context: &RewriteContext, &generics.where_clause, context.config, brace_style, - context.block_indent, - budget, + Shape::legacy(budget, + context.block_indent), Density::Tall, terminator, true, diff --git a/src/lib.rs b/src/lib.rs index 9e80e8f1b6b..3caeaf92ebb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,6 +201,50 @@ impl Sub for Indent { } } +#[derive(Copy, Clone, Debug)] +pub struct Shape { + pub width: usize, + pub indent: Indent, +} + +impl Shape { + pub fn indented(indent: Indent, config: &Config) -> Shape { + Shape { + width: config.max_width, + indent: indent, + } + } + + /// `indent` is the indentation of the first line. The next lines + /// should begin with at least `indent` spaces (except backwards + /// indentation). The first line should not begin with indentation. + /// `width` is the maximum number of characters on the last line + /// (excluding `indent`). The width of other lines is not limited by + /// `width`. + /// Note that in reality, we sometimes use width for lines other than the + /// last (i.e., we are conservative). + // .......*-------* + // | | + // | *-* + // *-----| + // |<------------>| max width + // |<---->| indent + // |<--->| width + pub fn legacy(width: usize, indent: Indent) -> Shape { + Shape { + width: width, + indent: indent, + } + } + + pub fn sub_width(self, width: usize) -> Shape { + Shape { + width: self.width - width, + indent: self.indent, + } + } +} + pub enum ErrorKind { // Line has exceeded character limit (found, maximum) LineOverflow(usize, usize), diff --git a/src/lists.rs b/src/lists.rs index 9af4fc238d6..2c78a1040c8 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -13,7 +13,7 @@ use std::iter::Peekable; use syntax::codemap::{self, CodeMap, BytePos}; -use Indent; +use {Indent, Shape}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; use config::Config; @@ -59,50 +59,38 @@ pub struct ListFormatting<'a> { pub tactic: DefinitiveListTactic, pub separator: &'a str, pub trailing_separator: SeparatorTactic, - pub indent: Indent, - pub width: usize, + pub shape: Shape, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. pub ends_with_newline: bool, pub config: &'a Config, } -pub fn format_fn_args(items: I, width: usize, offset: Indent, config: &Config) -> Option +pub fn format_fn_args(items: I, shape: Shape, config: &Config) -> Option where I: Iterator { list_helper(items, - width, - offset, + shape, config, ListTactic::LimitedHorizontalVertical(config.fn_call_width)) } -pub fn format_item_list(items: I, - width: usize, - offset: Indent, - config: &Config) - -> Option +pub fn format_item_list(items: I, shape: Shape, config: &Config) -> Option where I: Iterator { - list_helper(items, width, offset, config, ListTactic::HorizontalVertical) + list_helper(items, shape, config, ListTactic::HorizontalVertical) } -pub fn list_helper(items: I, - width: usize, - offset: Indent, - config: &Config, - tactic: ListTactic) - -> Option +pub fn list_helper(items: I, shape: Shape, config: &Config, tactic: ListTactic) -> Option where I: Iterator { let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic(&item_vec, tactic, width); + let tactic = definitive_tactic(&item_vec, tactic, shape.width); let fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - indent: offset, - width: width, + shape: shape, ends_with_newline: false, config: config, }; @@ -201,7 +189,7 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option let mut iter = items.into_iter().enumerate().peekable(); let mut line_len = 0; - let indent_str = &formatting.indent.to_string(formatting.config); + let indent_str = &formatting.shape.indent.to_string(formatting.config); while let Some((i, item)) = iter.next() { let item = item.as_ref(); let inner_item = try_opt!(item.item.as_ref()); @@ -234,7 +222,7 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option let total_width = total_item_width(item) + item_sep_len; // 1 is space between separator and item. - if line_len > 0 && line_len + 1 + total_width > formatting.width { + if line_len > 0 && line_len + 1 + total_width > formatting.shape.width { result.push('\n'); result.push_str(indent_str); line_len = 0; @@ -255,12 +243,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Block style in non-vertical mode. let block_mode = tactic != DefinitiveListTactic::Vertical; // Width restriction is only relevant in vertical mode. - let max_width = formatting.width; - let comment = try_opt!(rewrite_comment(comment, - block_mode, - max_width, - formatting.indent, - formatting.config)); + let comment = + try_opt!(rewrite_comment(comment, block_mode, formatting.shape, formatting.config)); result.push_str(&comment); if tactic == DefinitiveListTactic::Vertical { @@ -276,11 +260,11 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = try_opt!(rewrite_comment(comment, - true, - formatting.width, - Indent::empty(), - formatting.config)); + let formatted_comment = + try_opt!(rewrite_comment(comment, + true, + Shape::legacy(formatting.shape.width, Indent::empty()), + formatting.config)); result.push(' '); result.push_str(&formatted_comment); @@ -292,8 +276,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { // 1 = space between item and comment. - let width = formatting.width.checked_sub(item_last_line_width + 1).unwrap_or(1); - let mut offset = formatting.indent; + let width = formatting.shape.width.checked_sub(item_last_line_width + 1).unwrap_or(1); + let mut offset = formatting.shape.indent; offset.alignment += item_last_line_width + 1; let comment = item.post_comment.as_ref().unwrap(); @@ -303,8 +287,10 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option comment.trim().contains('\n') || comment.trim().len() > width; - let formatted_comment = - try_opt!(rewrite_comment(comment, block_style, width, offset, formatting.config)); + let formatted_comment = try_opt!(rewrite_comment(comment, + block_style, + Shape::legacy(width, offset), + formatting.config)); result.push(' '); result.push_str(&formatted_comment); diff --git a/src/macros.rs b/src/macros.rs index 412fb15cede..3a184d242ef 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -26,7 +26,7 @@ use syntax::parse::tts_to_parser; use syntax::symbol; use syntax::util::ThinVec; -use Indent; +use Shape; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use expr::{rewrite_call, rewrite_array}; @@ -62,13 +62,12 @@ impl MacroStyle { pub fn rewrite_macro(mac: &ast::Mac, extra_ident: Option, context: &RewriteContext, - width: usize, - offset: Indent, + shape: Shape, position: MacroPosition) -> Option { if context.config.use_try_shorthand { if let Some(expr) = convert_try_mac(mac, context) { - return expr.rewrite(context, width, offset); + return expr.rewrite(context, shape); } } @@ -146,11 +145,12 @@ pub fn rewrite_macro(mac: &ast::Mac, match style { MacroStyle::Parens => { // Format macro invocation as function call. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, width, offset) - .map(|rw| match position { + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map(|rw| { + match position { MacroPosition::Item => format!("{};", rw), _ => rw, - }) + } + }) } MacroStyle::Brackets => { // Format macro invocation as array literal. @@ -161,8 +161,9 @@ pub fn rewrite_macro(mac: &ast::Mac, original_style.opener()), mac.span.hi - BytePos(1)), context, - try_opt!(width.checked_sub(extra_offset)), - offset + extra_offset)); + Shape::legacy(try_opt!(shape.width + .checked_sub(extra_offset)), + shape.indent + extra_offset))); Some(format!("{}{}", macro_name, rewrite)) } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index eff3fd6c573..9967a8a4ab8 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -12,6 +12,7 @@ use config::WriteMode; use visitor::FmtVisitor; use syntax::codemap::{self, BytePos, Span, Pos}; use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; +use Shape; impl<'a> FmtVisitor<'a> { fn output_at_start(&self) -> bool { @@ -143,8 +144,8 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&rewrite_comment(subslice, false, - comment_width, - self.block_indent, + Shape::legacy(comment_width, + self.block_indent), self.config) .unwrap()); diff --git a/src/patterns.rs b/src/patterns.rs index 03598a1971b..7346dc08010 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Indent; +use Shape; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; @@ -23,9 +23,9 @@ use syntax::ptr; use syntax::codemap::{self, BytePos, Span}; impl Rewrite for Pat { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, width, offset), + PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { BindingMode::ByRef(mutability) => ("ref ", mutability), @@ -36,60 +36,54 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!(width.checked_sub(prefix.len() + mut_infix.len() + - id_str.len() + - 3)); - format!(" @ {}", try_opt!(p.rewrite(context, width, offset))) + let width = try_opt!(shape.width + .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)); + format!(" @ {}", + try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) } None => "".to_owned(), }; let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); - wrap_str(result, context.config.max_width, width, offset) + wrap_str(result, context.config.max_width, shape) } PatKind::Wild => { - if 1 <= width { + if 1 <= shape.width { Some("_".to_owned()) } else { None } } PatKind::Range(ref lhs, ref rhs) => { - rewrite_pair(&**lhs, &**rhs, "", "...", "", context, width, offset) + rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape) } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); - rewrite_unary_prefix(context, &prefix, &**pat, width, offset) + rewrite_unary_prefix(context, &prefix, &**pat, shape) } PatKind::Tuple(ref items, dotdot_pos) => { - rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, width, offset) + rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) } PatKind::Path(ref q_self, ref path) => { - rewrite_path(context, - PathContext::Expr, - q_self.as_ref(), - path, - width, - offset) + rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { let path_str = - try_opt!(rewrite_path(context, PathContext::Expr, None, path, width, offset)); + try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); rewrite_tuple_pat(pat_vec, dotdot_pos, Some(path_str), self.span, context, - width, - offset) + shape) } - PatKind::Lit(ref expr) => expr.rewrite(context, width, offset), + PatKind::Lit(ref expr) => expr.rewrite(context, shape), PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. - let prefix = prefix.iter().map(|p| p.rewrite(context, width, offset)); + let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); let slice_pat = slice_pat.as_ref() - .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, width, offset))))); - let suffix = suffix.iter().map(|p| p.rewrite(context, width, offset)); + .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); + let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. let pats: Option> = prefix.chain(slice_pat.into_iter()) @@ -105,32 +99,33 @@ impl Rewrite for Pat { } else { format!("[{}]", pats.join(", ")) }; - wrap_str(result, context.config.max_width, width, offset) + wrap_str(result, context.config.max_width, shape) } PatKind::Struct(ref path, ref fields, elipses) => { - let path = - try_opt!(rewrite_path(context, PathContext::Expr, None, path, width, offset)); + let path = try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; // 5 = `{` plus space before and after plus `}` plus space before. - let budget = try_opt!(width.checked_sub(path.len() + 5 + elipses_str.len())); + let budget = try_opt!(shape.width.checked_sub(path.len() + 5 + elipses_str.len())); // FIXME Using visual indenting, should use block or visual to match // struct lit preference (however, in practice I think it is rare // for struct patterns to be multi-line). // 3 = `{` plus space before and after. - let offset = offset + path.len() + 3; + let offset = shape.indent + path.len() + 3; - let items = itemize_list(context.codemap, - fields.iter(), - terminator, - |f| f.span.lo, - |f| f.span.hi, - |f| f.node.rewrite(context, budget, offset), - context.codemap.span_after(self.span, "{"), - self.span.hi); - let mut field_string = - try_opt!(format_item_list(items, budget, offset, context.config)); + let items = + itemize_list(context.codemap, + fields.iter(), + terminator, + |f| f.span.lo, + |f| f.span.hi, + |f| f.node.rewrite(context, Shape::legacy(budget, offset)), + context.codemap.span_after(self.span, "{"), + self.span.hi); + let mut field_string = try_opt!(format_item_list(items, + Shape::legacy(budget, offset), + context.config)); if elipses { if field_string.contains('\n') { field_string.push_str(",\n"); @@ -152,25 +147,21 @@ impl Rewrite for Pat { } // FIXME(#819) format pattern macros. PatKind::Mac(..) => { - wrap_str(context.snippet(self.span), - context.config.max_width, - width, - offset) + wrap_str(context.snippet(self.span), context.config.max_width, shape) } } } } impl Rewrite for FieldPat { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - let pat = self.pat.rewrite(context, width, offset); + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let pat = self.pat.rewrite(context, shape); if self.is_shorthand { pat } else { wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)), context.config.max_width, - width, - offset) + shape) } } } @@ -182,9 +173,9 @@ enum TuplePatField<'a> { } impl<'a> Rewrite for TuplePatField<'a> { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { - TuplePatField::Pat(ref p) => p.rewrite(context, width, offset), + TuplePatField::Pat(ref p) => p.rewrite(context, shape), TuplePatField::Dotdot(_) => Some("..".to_string()), } } @@ -204,8 +195,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], path_str: Option, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); @@ -230,18 +220,19 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); // 2 = "()".len(), 3 = "(,)".len() - let width = try_opt!(width.checked_sub(path_len + if add_comma { 3 } else { 2 })); + let width = try_opt!(shape.width.checked_sub(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() - let offset = offset + path_len + 1; - let mut items: Vec<_> = itemize_list(context.codemap, - pat_vec.iter(), - if add_comma { ",)" } else { ")" }, - |item| item.span().lo, - |item| item.span().hi, - |item| item.rewrite(context, width, offset), - context.codemap.span_after(span, "("), - span.hi - BytePos(1)) - .collect(); + let offset = shape.indent + path_len + 1; + let mut items: Vec<_> = + itemize_list(context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, Shape::legacy(width, offset)), + context.codemap.span_after(span, "("), + span.hi - BytePos(1)) + .collect(); // Condense wildcard string suffix into a single .. let wildcard_suffix_len = count_wildcard_suffix_len(&items); @@ -251,9 +242,11 @@ fn rewrite_tuple_pat(pats: &[ptr::P], items[new_item_count - 1].item = Some("..".to_owned()); let da_iter = items.into_iter().take(new_item_count); - try_opt!(format_item_list(da_iter, width, offset, context.config)) + try_opt!(format_item_list(da_iter, Shape::legacy(width, offset), context.config)) } else { - try_opt!(format_item_list(items.into_iter(), width, offset, context.config)) + try_opt!(format_item_list(items.into_iter(), + Shape::legacy(width, offset), + context.config)) }; match path_str { diff --git a/src/rewrite.rs b/src/rewrite.rs index 247b1df1c3f..3c69e2c3c45 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -13,18 +13,12 @@ use syntax::codemap::{CodeMap, Span}; use syntax::parse::ParseSess; -use Indent; +use {Indent, Shape}; use config::Config; pub trait Rewrite { - /// Rewrite self into offset and width. - /// `offset` is the indentation of the first line. The next lines - /// should begin with a least `offset` spaces (except backwards - /// indentation). The first line should not begin with indentation. - /// `width` is the maximum number of characters on the last line - /// (excluding offset). The width of other lines is not limited by - /// `width`. - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option; + /// Rewrite self into shape. + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; } #[derive(Clone)] diff --git a/src/string.rs b/src/string.rs index 71d8f8415f0..014830a9155 100644 --- a/src/string.rs +++ b/src/string.rs @@ -13,7 +13,7 @@ use unicode_segmentation::UnicodeSegmentation; use regex::Regex; -use Indent; +use Shape; use config::Config; use utils::wrap_str; @@ -24,8 +24,7 @@ pub struct StringFormat<'a> { pub closer: &'a str, pub line_start: &'a str, pub line_end: &'a str, - pub width: usize, - pub offset: Indent, + pub shape: Shape, pub trim_end: bool, pub config: &'a Config, } @@ -37,7 +36,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let stripped_str = re.replace_all(orig, "$1"); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let indent = fmt.offset.to_string(fmt.config); + let indent = fmt.shape.indent.to_string(fmt.config); let punctuation = ":,;."; // `cur_start` is the position in `orig` of the start of the current line. @@ -50,7 +49,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = try_opt!(fmt.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; + let max_chars = try_opt!(fmt.shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. @@ -118,7 +117,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option } result.push_str(fmt.closer); - wrap_str(result, fmt.config.max_width, fmt.width, fmt.offset) + wrap_str(result, fmt.config.max_width, fmt.shape) } #[cfg(test)] @@ -133,8 +132,7 @@ mod test { closer: "\"", line_start: " ", line_end: "\\", - width: 2, - offset: ::Indent::empty(), + shape: ::Shape::legacy(2, ::Indent::empty()), trim_end: false, config: &config, }; diff --git a/src/types.rs b/src/types.rs index acc9c7c6cb5..cce487cb2ea 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,7 +17,7 @@ use syntax::codemap::{self, Span, BytePos}; use syntax::print::pprust; use syntax::symbol::keywords; -use {Indent, Spanned}; +use {Shape, Spanned}; use codemap::SpanUtils; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; @@ -38,8 +38,7 @@ pub fn rewrite_path(context: &RewriteContext, path_context: PathContext, qself: Option<&ast::QSelf>, path: &ast::Path, - width: usize, - offset: Indent) + shape: Shape) -> Option { let skip_count = qself.map_or(0, |x| x.position); @@ -58,7 +57,7 @@ pub fn rewrite_path(context: &RewriteContext, result.push_str(" ") } - let fmt_ty = try_opt!(qself.ty.rewrite(context, width, offset)); + let fmt_ty = try_opt!(qself.ty.rewrite(context, shape)); result.push_str(&fmt_ty); if skip_count > 0 { @@ -67,9 +66,9 @@ pub fn rewrite_path(context: &RewriteContext, result.push_str("::"); } - let extra_offset = extra_offset(&result, offset); + let extra_offset = extra_offset(&result, shape.indent); // 3 = ">::".len() - let budget = try_opt!(width.checked_sub(extra_offset + 3)); + let budget = try_opt!(shape.width.checked_sub(extra_offset + 3)); result = try_opt!(rewrite_path_segments(PathContext::Type, result, @@ -77,8 +76,8 @@ pub fn rewrite_path(context: &RewriteContext, span_lo, path.span.hi, context, - budget, - offset + extra_offset)); + Shape::legacy(budget, + shape.indent + extra_offset))); } if context.config.spaces_within_angle_brackets { @@ -89,16 +88,15 @@ pub fn rewrite_path(context: &RewriteContext, span_lo = qself.ty.span.hi + BytePos(1); } - let extra_offset = extra_offset(&result, offset); - let budget = try_opt!(width.checked_sub(extra_offset)); + let extra_offset = extra_offset(&result, shape.indent); + let budget = try_opt!(shape.width.checked_sub(extra_offset)); rewrite_path_segments(path_context, result, path.segments.iter().skip(skip_count), span_lo, path.span.hi, context, - budget, - offset + extra_offset) + Shape::legacy(budget, shape.indent + extra_offset)) } fn rewrite_path_segments<'a, I>(path_context: PathContext, @@ -107,8 +105,7 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext, mut span_lo: BytePos, span_hi: BytePos, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option where I: Iterator { @@ -125,16 +122,15 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext, buffer.push_str("::"); } - let extra_offset = extra_offset(&buffer, offset); - let remaining_width = try_opt!(width.checked_sub(extra_offset)); - let new_offset = offset + extra_offset; + let extra_offset = extra_offset(&buffer, shape.indent); + let remaining_width = try_opt!(shape.width.checked_sub(extra_offset)); + let new_offset = shape.indent + extra_offset; let segment_string = try_opt!(rewrite_segment(path_context, segment, &mut span_lo, span_hi, context, - remaining_width, - new_offset)); + Shape::legacy(remaining_width, new_offset))); buffer.push_str(&segment_string); } @@ -160,14 +156,15 @@ impl<'a> SegmentParam<'a> { } impl<'a> Rewrite for SegmentParam<'a> { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { - SegmentParam::LifeTime(lt) => lt.rewrite(context, width, offset), - SegmentParam::Type(ty) => ty.rewrite(context, width, offset), + SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), + SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(binding) => { let mut result = format!("{} = ", binding.ident); - let budget = try_opt!(width.checked_sub(result.len())); - let rewrite = try_opt!(binding.ty.rewrite(context, budget, offset + result.len())); + let budget = try_opt!(shape.width.checked_sub(result.len())); + let rewrite = try_opt!(binding.ty + .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); result.push_str(&rewrite); Some(result) } @@ -190,12 +187,11 @@ fn rewrite_segment(path_context: PathContext, span_lo: &mut BytePos, span_hi: BytePos, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let ident_len = segment.identifier.to_string().len(); - let width = try_opt!(width.checked_sub(ident_len)); - let offset = offset + ident_len; + let width = try_opt!(shape.width.checked_sub(ident_len)); + let offset = shape.indent + ident_len; let params = if let Some(ref params) = segment.parameters { match **params { @@ -222,18 +218,21 @@ fn rewrite_segment(path_context: PathContext, // 1 for > let list_width = try_opt!(width.checked_sub(extra_offset + 1)); - let items = - itemize_list(context.codemap, - param_list.into_iter(), - ">", - |param| param.get_span().lo, - |param| param.get_span().hi, - |seg| seg.rewrite(context, list_width, offset + extra_offset), - list_lo, - span_hi); + let items = itemize_list(context.codemap, + param_list.into_iter(), + ">", + |param| param.get_span().lo, + |param| param.get_span().hi, + |seg| { + seg.rewrite(context, + Shape::legacy(list_width, + offset + extra_offset)) + }, + list_lo, + span_hi); let list_str = try_opt!(format_item_list(items, - list_width, - offset + extra_offset, + Shape::legacy(list_width, + offset + extra_offset), context.config)); // Update position of last bracket. @@ -255,8 +254,7 @@ fn rewrite_segment(path_context: PathContext, false, data.span, context, - width, - offset)) + Shape::legacy(width, offset))) } _ => String::new(), } @@ -272,8 +270,7 @@ fn format_function_type<'a, I>(inputs: I, variadic: bool, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option where I: ExactSizeIterator, ::Item: Deref, @@ -297,44 +294,45 @@ fn format_function_type<'a, I>(inputs: I, }; // 2 for () - let budget = try_opt!(width.checked_sub(2)); + let budget = try_opt!(shape.width.checked_sub(2)); // 1 for ( - let offset = offset + 1; + let offset = shape.indent + 1; let list_lo = context.codemap.span_after(span, "("); - let items = - itemize_list(context.codemap, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs.map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), - ")", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo, - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, budget, offset), - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, - list_lo, - span.hi); - - let list_str = try_opt!(format_fn_args(items, budget, offset, context.config)); + let items = itemize_list(context.codemap, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs.map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), + ")", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => { + ty.rewrite(context, Shape::legacy(budget, offset)) + } + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi); + + let list_str = try_opt!(format_fn_args(items, Shape::legacy(budget, offset), context.config)); let output = match *output { FunctionRetTy::Ty(ref ty) => { - let budget = try_opt!(width.checked_sub(4)); - let type_str = try_opt!(ty.rewrite(context, budget, offset + 4)); + let budget = try_opt!(shape.width.checked_sub(4)); + let type_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, offset + 4))); format!(" -> {}", type_str) } FunctionRetTy::Default(..) => String::new(), }; - let infix = if !output.is_empty() && output.len() + list_str.len() > width { + let infix = if !output.is_empty() && output.len() + list_str.len() > shape.width { format!("\n{}", (offset - 1).to_string(context.config)) } else { String::new() @@ -357,35 +355,33 @@ fn type_bound_colon(context: &RewriteContext) -> &'static str { } impl Rewrite for ast::WherePredicate { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { // TODO: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ref bound_lifetimes, ref bounded_ty, ref bounds, .. }) => { - let type_str = try_opt!(bounded_ty.rewrite(context, width, offset)); + let type_str = try_opt!(bounded_ty.rewrite(context, shape)); let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { let lifetime_str: String = try_opt!(bound_lifetimes.iter() .map(|lt| { - lt.rewrite(context, - width, - offset) + lt.rewrite(context, shape) }) .intersperse(Some(", ".to_string())) .collect()); // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let budget = try_opt!(width.checked_sub(used_width)); + let budget = try_opt!(shape.width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds.iter() .map(|ty_bound| { ty_bound.rewrite(context, - budget, - offset + used_width) + Shape::legacy(budget, + shape.indent + used_width)) }) .intersperse(Some(" + ".to_string())) .collect()); @@ -397,12 +393,12 @@ impl Rewrite for ast::WherePredicate { } } else { let used_width = type_str.len() + colon.len(); - let budget = try_opt!(width.checked_sub(used_width)); + let budget = try_opt!(shape.width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds.iter() .map(|ty_bound| { ty_bound.rewrite(context, - budget, - offset + used_width) + Shape::legacy(budget, + shape.indent + used_width)) }) .intersperse(Some(" + ".to_string())) .collect()); @@ -413,91 +409,92 @@ impl Rewrite for ast::WherePredicate { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, .. }) => { - try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, width, offset)) + try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { - let lhs_ty_str = try_opt!(lhs_ty.rewrite(context, width, offset)); + let lhs_ty_str = try_opt!(lhs_ty.rewrite(context, shape)); // 3 = " = ".len() let used_width = 3 + lhs_ty_str.len(); - let budget = try_opt!(width.checked_sub(used_width)); - let rhs_ty_str = try_opt!(rhs_ty.rewrite(context, budget, offset + used_width)); + let budget = try_opt!(shape.width.checked_sub(used_width)); + let rhs_ty_str = try_opt!(rhs_ty.rewrite(context, + Shape::legacy(budget, shape.indent + used_width))); format!("{} = {}", lhs_ty_str, rhs_ty_str) } }; - wrap_str(result, context.config.max_width, width, offset) + wrap_str(result, context.config.max_width, shape) } } impl Rewrite for ast::LifetimeDef { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, width, offset) + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) } } fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, bounds: I, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option where I: ExactSizeIterator { - let result = try_opt!(lt.rewrite(context, width, offset)); + let result = try_opt!(lt.rewrite(context, shape)); if bounds.len() == 0 { Some(result) } else { let appendix: Vec<_> = try_opt!(bounds.into_iter() - .map(|b| b.rewrite(context, width, offset)) + .map(|b| b.rewrite(context, shape)) .collect()); let colon = type_bound_colon(context); let result = format!("{}{}{}", result, colon, appendix.join(" + ")); - wrap_str(result, context.config.max_width, width, offset) + wrap_str(result, context.config.max_width, shape) } } impl Rewrite for ast::TyParamBound { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { - tref.rewrite(context, width, offset) + tref.rewrite(context, shape) } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { - let budget = try_opt!(width.checked_sub(1)); - Some(format!("?{}", try_opt!(tref.rewrite(context, budget, offset + 1)))) + let budget = try_opt!(shape.width.checked_sub(1)); + Some(format!("?{}", + try_opt!(tref.rewrite(context, + Shape::legacy(budget, shape.indent + 1))))) } - ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, width, offset), + ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), } } } impl Rewrite for ast::Lifetime { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { wrap_str(pprust::lifetime_to_string(self), context.config.max_width, - width, - offset) + shape) } } impl Rewrite for ast::TyParamBounds { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let joiner = match context.config.type_punctuation_density { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; let strs: Vec<_> = try_opt!(self.iter() - .map(|b| b.rewrite(context, width, offset)) + .map(|b| b.rewrite(context, shape)) .collect()); - wrap_str(strs.join(joiner), context.config.max_width, width, offset) + wrap_str(strs.join(joiner), context.config.max_width, shape) } } impl Rewrite for ast::TyParam { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::with_capacity(128); result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { @@ -511,7 +508,7 @@ impl Rewrite for ast::TyParam { let bounds: String = try_opt!(self.bounds .iter() - .map(|ty_bound| ty_bound.rewrite(context, width, offset)) + .map(|ty_bound| ty_bound.rewrite(context, shape)) .intersperse(Some(" + ".to_string())) .collect()); @@ -524,29 +521,31 @@ impl Rewrite for ast::TyParam { TypeDensity::Wide => " = ", }; result.push_str(eq_str); - let budget = try_opt!(width.checked_sub(result.len())); - let rewrite = try_opt!(def.rewrite(context, budget, offset + result.len())); + let budget = try_opt!(shape.width.checked_sub(result.len())); + let rewrite = + try_opt!(def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); result.push_str(&rewrite); } - wrap_str(result, context.config.max_width, width, offset) + wrap_str(result, context.config.max_width, shape) } } impl Rewrite for ast::PolyTraitRef { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if !self.bound_lifetimes.is_empty() { let lifetime_str: String = try_opt!(self.bound_lifetimes .iter() - .map(|lt| lt.rewrite(context, width, offset)) + .map(|lt| lt.rewrite(context, shape)) .intersperse(Some(", ".to_string())) .collect()); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; - let max_path_width = try_opt!(width.checked_sub(extra_offset)); + let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); let path_str = try_opt!(self.trait_ref - .rewrite(context, max_path_width, offset + extra_offset)); + .rewrite(context, + Shape::legacy(max_path_width, shape.indent + extra_offset))); Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { format!("for< {} > {}", lifetime_str, path_str) @@ -554,58 +553,64 @@ impl Rewrite for ast::PolyTraitRef { format!("for<{}> {}", lifetime_str, path_str) }) } else { - self.trait_ref.rewrite(context, width, offset) + self.trait_ref.rewrite(context, shape) } } } impl Rewrite for ast::TraitRef { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - rewrite_path(context, PathContext::Type, None, &self.path, width, offset) + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_path(context, PathContext::Type, None, &self.path, shape) } } impl Rewrite for ast::Ty { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - ast::TyKind::TraitObject(ref bounds) => bounds.rewrite(context, width, offset), + ast::TyKind::TraitObject(ref bounds) => bounds.rewrite(context, shape), ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { Mutability::Mutable => "*mut ", Mutability::Immutable => "*const ", }; - rewrite_unary_prefix(context, prefix, &*mt.ty, width, offset) + rewrite_unary_prefix(context, prefix, &*mt.ty, shape) } ast::TyKind::Rptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); Some(match *lifetime { Some(ref lifetime) => { - let lt_budget = try_opt!(width.checked_sub(2 + mut_len)); - let lt_str = - try_opt!(lifetime.rewrite(context, lt_budget, offset + 2 + mut_len)); + let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); + let lt_str = try_opt!(lifetime.rewrite(context, + Shape::legacy(lt_budget, + shape.indent + 2 + + mut_len))); let lt_len = lt_str.len(); - let budget = try_opt!(width.checked_sub(2 + mut_len + lt_len)); + let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); format!("&{} {}{}", lt_str, mut_str, try_opt!(mt.ty - .rewrite(context, budget, offset + 2 + mut_len + lt_len))) + .rewrite(context, + Shape::legacy(budget, + shape.indent + 2 + mut_len + lt_len)))) } None => { - let budget = try_opt!(width.checked_sub(1 + mut_len)); + let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); format!("&{}{}", mut_str, - try_opt!(mt.ty.rewrite(context, budget, offset + 1 + mut_len))) + try_opt!(mt.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + 1 + mut_len)))) } }) } // FIXME: we drop any comments here, even though it's a silly place to put // comments. ast::TyKind::Paren(ref ty) => { - let budget = try_opt!(width.checked_sub(2)); - ty.rewrite(context, budget, offset + 1) + let budget = try_opt!(shape.width.checked_sub(2)); + ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_parens { format!("( {} )", ty_str) } else { @@ -614,11 +619,11 @@ impl Rewrite for ast::Ty { } ast::TyKind::Slice(ref ty) => { let budget = if context.config.spaces_within_square_brackets { - try_opt!(width.checked_sub(4)) + try_opt!(shape.width.checked_sub(4)) } else { - try_opt!(width.checked_sub(2)) + try_opt!(shape.width.checked_sub(2)) }; - ty.rewrite(context, budget, offset + 1) + ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_square_brackets { format!("[ {} ]", ty_str) } else { @@ -626,41 +631,30 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::Tup(ref items) => { - rewrite_tuple(context, - items.iter().map(|x| &**x), - self.span, - width, - offset) + rewrite_tuple(context, items.iter().map(|x| &**x), self.span, shape) } ast::TyKind::Path(ref q_self, ref path) => { - rewrite_path(context, - PathContext::Type, - q_self.as_ref(), - path, - width, - offset) + rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } ast::TyKind::Array(ref ty, ref repeats) => { let use_spaces = context.config.spaces_within_square_brackets; let lbr = if use_spaces { "[ " } else { "[" }; let rbr = if use_spaces { " ]" } else { "]" }; - rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, width, offset) + rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, shape) } ast::TyKind::Infer => { - if width >= 1 { + if shape.width >= 1 { Some("_".to_owned()) } else { None } } - ast::TyKind::BareFn(ref bare_fn) => { - rewrite_bare_fn(bare_fn, self.span, context, width, offset) - } + ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Some(String::from("!")), ast::TyKind::Mac(..) => None, ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(ref it) => { - it.rewrite(context, width, offset).map(|it_str| format!("impl {}", it_str)) + it.rewrite(context, shape).map(|it_str| format!("impl {}", it_str)) } ast::TyKind::Typeof(..) => unreachable!(), } @@ -670,8 +664,7 @@ impl Rewrite for ast::Ty { fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, span: Span, context: &RewriteContext, - width: usize, - offset: Indent) + shape: Shape) -> Option { let mut result = String::with_capacity(128); @@ -682,7 +675,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, // rightward drift. If that is a problem, we could use the list stuff. result.push_str(&try_opt!(bare_fn.lifetimes .iter() - .map(|l| l.rewrite(context, try_opt!(width.checked_sub(6)), offset + 4)) + .map(|l| { + l.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) + }) .intersperse(Some(", ".to_string())) .collect::>())); result.push_str("> "); @@ -696,16 +692,15 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str("fn"); - let budget = try_opt!(width.checked_sub(result.len())); - let indent = offset + result.len(); + let budget = try_opt!(shape.width.checked_sub(result.len())); + let indent = shape.indent + result.len(); let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(), &bare_fn.decl.output, bare_fn.decl.variadic, span, context, - budget, - indent)); + Shape::legacy(budget, indent))); result.push_str(&rewrite); diff --git a/src/utils.rs b/src/utils.rs index 2f8c5db82e1..c9017571025 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,7 +18,7 @@ use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMet use syntax::codemap::BytePos; use syntax::abi; -use Indent; +use {Indent, Shape}; use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; @@ -253,18 +253,18 @@ macro_rules! source { // Wraps string-like values in an Option. Returns Some when the string adheres // to the Rewrite constraints defined for the Rewrite trait and else otherwise. -pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: Indent) -> Option { +pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option { { let snippet = s.as_ref(); - if !snippet.contains('\n') && snippet.len() > width { + if !snippet.contains('\n') && snippet.len() > shape.width { return None; } else { let mut lines = snippet.lines(); - // The caller of this function has already placed `offset` + // The caller of this function has already placed `shape.offset` // characters on the first line. - let first_line_max_len = try_opt!(max_width.checked_sub(offset.width())); + let first_line_max_len = try_opt!(max_width.checked_sub(shape.indent.width())); if lines.next().unwrap().len() > first_line_max_len { return None; } @@ -278,7 +278,7 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: Ind // indentation. // A special check for the last line, since the caller may // place trailing characters on this line. - if snippet.lines().rev().next().unwrap().len() > offset.width() + width { + if snippet.lines().rev().next().unwrap().len() > shape.indent.width() + shape.width { return None; } } @@ -288,8 +288,8 @@ pub fn wrap_str>(s: S, max_width: usize, width: usize, offset: Ind } impl Rewrite for String { - fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { - wrap_str(self, context.config.max_width, width, offset).map(ToOwned::to_owned) + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + wrap_str(self, context.config.max_width, shape).map(ToOwned::to_owned) } } diff --git a/src/visitor.rs b/src/visitor.rs index 95ec54e89ee..fd0a1f1ed21 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -14,7 +14,7 @@ use syntax::parse::ParseSess; use strings::string_buffer::StringBuffer; -use Indent; +use {Indent, Shape}; use utils; use codemap::{LineRangeUtils, SpanUtils}; use config::Config; @@ -59,8 +59,9 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let rewrite = stmt.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent); + Shape::legacy(self.config.max_width - + self.block_indent.width(), + self.block_indent)); self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Mac(ref mac) => { @@ -425,8 +426,7 @@ impl<'a> FmtVisitor<'a> { let rewrite = rewrite_macro(mac, ident, &self.get_context(), - width, - self.block_indent, + Shape::legacy(width, self.block_indent), pos); self.push_rewrite(mac.span, rewrite); } @@ -482,8 +482,8 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(source!(self, first.span).lo); let rewrite = outers.rewrite(&self.get_context(), - self.config.max_width - self.block_indent.width(), - self.block_indent) + Shape::legacy(self.config.max_width - self.block_indent.width(), + self.block_indent)) .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); @@ -566,12 +566,12 @@ impl<'a> FmtVisitor<'a> { } impl<'a> Rewrite for [ast::Attribute] { - fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::new(); if self.is_empty() { return Some(result); } - let indent = offset.to_string(context.config); + let indent = shape.indent.to_string(context.config); for (i, a) in self.iter().enumerate() { let mut a_str = context.snippet(a.span); @@ -587,9 +587,10 @@ impl<'a> Rewrite for [ast::Attribute] { if !comment.is_empty() { let comment = try_opt!(rewrite_comment(comment, false, - context.config.ideal_width - - offset.width(), - offset, + Shape::legacy(context.config + .ideal_width - + shape.indent.width(), + shape.indent), context.config)); result.push_str(&indent); result.push_str(&comment); @@ -603,8 +604,9 @@ impl<'a> Rewrite for [ast::Attribute] { if a_str.starts_with("//") { a_str = try_opt!(rewrite_comment(&a_str, false, - context.config.ideal_width - offset.width(), - offset, + Shape::legacy(context.config.ideal_width - + shape.indent.width(), + shape.indent), context.config)); } -- cgit 1.4.1-3-g733a5 From 6810c762dff03b4a6ad1b64dadb1ac31896fdd34 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 31 Jan 2017 23:35:57 +0100 Subject: Handle multiline condition in let if else (fixes #1239) --- src/expr.rs | 11 ++++++++++- tests/source/issue-1239.rs | 9 +++++++++ tests/target/issue-1239.rs | 9 +++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-1239.rs create mode 100644 tests/target/issue-1239.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ba7c05b6528..4b7a76c733e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -895,7 +895,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style == - ControlBraceStyle::AlwaysNextLine { + ControlBraceStyle::AlwaysNextLine { alt_block_sep.as_str() } else { " " @@ -912,6 +912,15 @@ impl<'a> Rewrite for ControlFlow<'a> { block_str); if let Some(else_block) = self.else_block { + // Since this is an else block, we should not indent for the assignment preceding + // the original if, so set shape.indent.alignment to 0. + let shape = Shape { + width: shape.width, + indent: Indent { + block_indent: shape.indent.block_indent, + alignment: 0, + }, + }; let mut last_in_chain = false; let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it diff --git a/tests/source/issue-1239.rs b/tests/source/issue-1239.rs new file mode 100644 index 00000000000..913058257ed --- /dev/null +++ b/tests/source/issue-1239.rs @@ -0,0 +1,9 @@ +fn foo() { + let with_alignment = if condition__uses_alignment_for_first_if__0 || + condition__uses_alignment_for_first_if__1 || + condition__uses_alignment_for_first_if__2 { + } else if condition__no_alignment_for_later_else__0 || + condition__no_alignment_for_later_else__1 || + condition__no_alignment_for_later_else__2 { + }; +} diff --git a/tests/target/issue-1239.rs b/tests/target/issue-1239.rs new file mode 100644 index 00000000000..c8da3573e95 --- /dev/null +++ b/tests/target/issue-1239.rs @@ -0,0 +1,9 @@ +fn foo() { + let with_alignment = if condition__uses_alignment_for_first_if__0 || + condition__uses_alignment_for_first_if__1 || + condition__uses_alignment_for_first_if__2 { + } else if condition__no_alignment_for_later_else__0 || + condition__no_alignment_for_later_else__1 || + condition__no_alignment_for_later_else__2 { + }; +} -- cgit 1.4.1-3-g733a5 From f2c867d067eac285201e53672dcc5e42c2065785 Mon Sep 17 00:00:00 2001 From: "Craig M. Brandenburg" Date: Mon, 6 Feb 2017 21:11:47 -0700 Subject: New `disable_all_formatting` config option (#1297) * New `disable_all_formatting` config option * Resolve code review comments --- src/config.rs | 1 + src/lib.rs | 3 +++ tests/target/disable_all_formatting.rs | 4 ++++ 3 files changed, 8 insertions(+) create mode 100644 tests/target/disable_all_formatting.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index f5d563197c3..508b569232b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -326,6 +326,7 @@ macro_rules! create_config { create_config! { verbose: bool, false, "Use verbose output"; + disable_all_formatting: bool, false, "Don't reformat anything"; skip_children: bool, false, "Don't reformat out of line modules"; file_lines: FileLines, FileLines::all(), "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ diff --git a/src/lib.rs b/src/lib.rs index 3caeaf92ebb..abe9a6e8554 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -473,6 +473,9 @@ pub fn format_input(input: Input, mut out: Option<&mut T>) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { let mut summary = Summary::new(); + if config.disable_all_formatting { + return Ok((summary, FileMap::new(), FormatReport::new())); + } let codemap = Rc::new(CodeMap::new()); let tty_handler = diff --git a/tests/target/disable_all_formatting.rs b/tests/target/disable_all_formatting.rs new file mode 100644 index 00000000000..ef7e4ee9362 --- /dev/null +++ b/tests/target/disable_all_formatting.rs @@ -0,0 +1,4 @@ +// rustfmt-disable_all_formatting: true +// Don't format anything. + +fn main() { println!("This should not be formatted."); } -- cgit 1.4.1-3-g733a5 From fad74c8ac9dcf9cd0f9db5439a30e5cadf5d6542 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Mon, 13 Feb 2017 03:16:11 +0900 Subject: Support field-init-shorthand (#1308) --- src/expr.rs | 37 +++++++++++++++++++++---------------- tests/source/struct_lits.rs | 8 ++++++++ tests/target/struct_lits.rs | 15 +++++++++++++++ 3 files changed, 44 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4b7a76c733e..2498ee653af 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1837,22 +1837,27 @@ pub fn type_annotation_separator(config: &Config) -> &str { fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { let name = &field.ident.node.to_string(); - let separator = type_annotation_separator(context.config); - let overhead = name.len() + separator.len(); - let expr = field.expr.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(overhead)), - shape.indent + overhead)); - - match expr { - Some(e) => Some(format!("{}{}{}", name, separator, e)), - None => { - let expr_offset = shape.indent.block_indent(context.config); - let expr = field.expr.rewrite(context, - Shape::legacy(try_opt!(context.config - .max_width - .checked_sub(expr_offset.width())), - expr_offset)); - expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) + if field.is_shorthand { + Some(name.to_string()) + } else { + let separator = type_annotation_separator(context.config); + let overhead = name.len() + separator.len(); + let expr = field.expr.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(overhead)), + shape.indent + overhead)); + + match expr { + Some(e) => Some(format!("{}{}{}", name, separator, e)), + None => { + let expr_offset = shape.indent.block_indent(context.config); + let expr = field.expr + .rewrite(context, + Shape::legacy(try_opt!(context.config + .max_width + .checked_sub(expr_offset.width())), + expr_offset)); + expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) + } } } } diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs index 8d762eed980..c5aaf7ef881 100644 --- a/tests/source/struct_lits.rs +++ b/tests/source/struct_lits.rs @@ -133,3 +133,11 @@ fn issue835() { }; MyStruct {} } + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, .. base }; + Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ + eeeeeeeee }; + Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 5ab8de3f235..05840b703d3 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -169,3 +169,18 @@ fn issue835() { }; MyStruct {} } + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, ..base }; + Foo { + aaaaaaaaaa, + bbbbbbbb, + cccccccccc, + dddddddddd, // a comment + eeeeeeeee, + }; + Record { + ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; +} -- cgit 1.4.1-3-g733a5 From 4f939ddf0c9344da646367d46810eb1ac92c5780 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Sun, 12 Feb 2017 15:50:10 -0800 Subject: Don't print config file by default (#1313) Supress `Using rusftmt config file...` messages unless the --verbose flag is given. --- src/bin/rustfmt.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index ab41fbb7de7..9d66154a814 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -170,7 +170,7 @@ fn make_opts() -> Options { let mut opts = Options::new(); opts.optflag("h", "help", "show this message"); opts.optflag("V", "version", "show version information"); - opts.optflag("v", "verbose", "show progress"); + opts.optflag("v", "verbose", "print verbose output"); opts.optopt("", "write-mode", "mode to write in (not usable when piping from stdin)", @@ -234,8 +234,11 @@ fn execute(opts: &Options) -> FmtResult { config = cfg_tmp; path = path_tmp; }; - if let Some(path) = path.as_ref() { - println!("Using rustfmt config file {}", path.display()); + + if options.verbose { + if let Some(path) = path.as_ref() { + println!("Using rustfmt config file {}", path.display()); + } } let mut error_summary = Summary::new(); @@ -244,10 +247,12 @@ fn execute(opts: &Options) -> FmtResult { if path.is_none() { let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap()) .expect(&format!("Error resolving config for {}", file.display())); - if let Some(path) = path_tmp.as_ref() { - println!("Using rustfmt config file {} for {}", - path.display(), - file.display()); + if options.verbose { + if let Some(path) = path_tmp.as_ref() { + println!("Using rustfmt config file {} for {}", + path.display(), + file.display()); + } } config = config_tmp; } -- cgit 1.4.1-3-g733a5 From f6ccbd71c3f6264fd2c807a399dd64f5685f67d0 Mon Sep 17 00:00:00 2001 From: Sebastian Blunt Date: Sun, 19 Feb 2017 19:56:37 +0100 Subject: Add error_on_line_overflow option Makes it configurable whether to error if unable to get all lines within the max_width. --- src/config.rs | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 508b569232b..892b90b117e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -333,6 +333,7 @@ create_config! { via the --file-lines option"; max_width: usize, 100, "Maximum width of each line"; ideal_width: usize, 80, "Ideal width of each line"; + error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width"; tab_spaces: usize, 4, "Number of spaces per tab"; fn_call_width: usize, 60, "Maximum width of the args of a function call before falling back to vertical formatting"; diff --git a/src/lib.rs b/src/lib.rs index abe9a6e8554..4fdc9ff8675 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -399,7 +399,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m line_len -= b - lw; } // Check for any line width errors we couldn't correct. - if line_len > config.max_width { + if config.error_on_line_overflow && line_len > config.max_width { errors.push(FormattingError { line: cur_line, kind: ErrorKind::LineOverflow(line_len, config.max_width), -- cgit 1.4.1-3-g733a5 From b35906dbce47552c2ba6350f31c654bc77603fbd Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Feb 2017 14:43:43 +1300 Subject: WIP --- src/chains.rs | 72 +++++----- src/expr.rs | 411 ++++++++++++++++++++++++++------------------------------ src/items.rs | 55 ++++---- src/lib.rs | 96 ++++++++++++- src/macros.rs | 5 +- src/patterns.rs | 10 +- src/rewrite.rs | 13 +- src/string.rs | 5 +- src/types.rs | 40 +++--- src/utils.rs | 6 +- src/visitor.rs | 5 +- 11 files changed, 382 insertions(+), 336 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 38f6fad1166..f3cd2ab8f01 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -93,6 +93,7 @@ use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { + debug!("rewrite_chain {:?}", shape); let total_span = expr.span; let (parent, subexpr_list) = make_subexpr_list(expr, context); @@ -103,42 +104,45 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_block_indent = chain_base_indent(context, shape.indent); - let parent_context = &RewriteContext { block_indent: parent_block_indent, ..*context }; - let parent_rewrite = try_opt!(parent.rewrite(parent_context, shape)); + let mut parent_shape = shape; + if is_block_expr(&parent, "\n") { + parent_shape = chain_base_indent(context, shape); + } + let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape)); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let (indent, extend) = if !parent_rewrite.contains('\n') && is_continuable(&parent) || - parent_rewrite.len() <= context.config.tab_spaces { - - let indent = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node { - parent_block_indent.block_indent(context.config) + let (nested_shape, extend) = if !parent_rewrite.contains('\n') && is_continuable(&parent) { + let nested_shape = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node { + parent_shape.block_indent(context.config.tab_spaces) } else { - chain_indent(context, shape.indent + Indent::new(0, parent_rewrite.len())) + chain_indent(context, shape.add_offset(parent_rewrite.len())) }; - (indent, true) + (nested_shape, true) } else if is_block_expr(&parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. - (parent_block_indent, false) + (parent_shape, false) } else if parent_rewrite.contains('\n') { - (chain_indent(context, parent_block_indent.block_indent(context.config)), false) + (chain_indent(context, parent_shape.block_indent(context.config.tab_spaces)), false) } else { - (chain_indent_newline(context, shape.indent + Indent::new(0, parent_rewrite.len())), false) + (chain_indent_newline(context, shape.add_offset(parent_rewrite.len())), false) }; - let max_width = try_opt!((shape.width + shape.indent.width()).checked_sub(indent.width())); + let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset).checked_sub(nested_shape.indent.width() + nested_shape.offset)); + // The alignement in the shape is only used if we start the item on a new + // line, so we don't need to preserve the offset. + let child_shape = Shape { width: max_width, ..nested_shape }; + debug!("child_shape {:?}", child_shape); let mut rewrites = try_opt!(subexpr_list.iter() .rev() - .map(|e| rewrite_chain_subexpr(e, total_span, context, Shape::legacy(max_width, indent))) + .map(|e| rewrite_chain_subexpr(e, total_span, context, child_shape)) .collect::>>()); // Total of all items excluding the last. let almost_total = rewrites[..rewrites.len() - 1] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); - let total_width = almost_total + first_line_width(rewrites.last().unwrap()); let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same @@ -152,7 +156,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - false }; - let mut fits_single_line = !veto_single_line && total_width <= shape.width; + let mut fits_single_line = !veto_single_line && almost_total <= shape.width; if fits_single_line { let len = rewrites.len(); let (init, last) = rewrites.split_at_mut(len - 1); @@ -178,7 +182,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - String::new() } else { // Use new lines. - format!("\n{}", indent.to_string(context.config)) + format!("\n{}", nested_shape.indent.to_string(context.config)) }; let first_connector = if extend || subexpr_list.is_empty() { @@ -211,7 +215,7 @@ pub fn rewrite_try(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - let sub_expr = try_opt!(expr.rewrite(context, shape.sub_width(try_count))); + let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count)))); Some(format!("{}{}", sub_expr, iter::repeat("?").take(try_count).collect::())) @@ -268,29 +272,29 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, (parent, subexpr_list) } -fn chain_base_indent(context: &RewriteContext, offset: Indent) -> Indent { +fn chain_base_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_base_indent { - BlockIndentStyle::Visual => offset, - BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + BlockIndentStyle::Visual => shape, + BlockIndentStyle::Inherit => shape.block_indent(0), + BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces), } } -fn chain_indent(context: &RewriteContext, offset: Indent) -> Indent { +fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent { - BlockIndentStyle::Visual => offset, - BlockIndentStyle::Inherit => context.block_indent, - BlockIndentStyle::Tabbed => context.block_indent.block_indent(context.config), + BlockIndentStyle::Visual => shape, + BlockIndentStyle::Inherit => shape.block_indent(0), + BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces), } } // Ignores visual indenting because this function should be called where it is // not possible to use visual indentation because we are starting on a newline. -fn chain_indent_newline(context: &RewriteContext, _offset: Indent) -> Indent { +fn chain_indent_newline(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent { - BlockIndentStyle::Inherit => context.block_indent, + BlockIndentStyle::Inherit => shape.block_indent(0), BlockIndentStyle::Visual | BlockIndentStyle::Tabbed => { - context.block_indent.block_indent(context.config) + shape.block_indent(context.config.tab_spaces) } } } @@ -303,7 +307,7 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, shape: Shape) -> bool { if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { - let budget = match shape.width.checked_sub(almost_total) { + let shape = match shape.shrink_left(almost_total) { Some(b) => b, None => return false, }; @@ -312,8 +316,7 @@ fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, expressions, total_span, context, - Shape::legacy(budget, - shape.indent + almost_total)); + shape); if let Some(ref mut s) = last_rewrite { ::std::mem::swap(s, last); @@ -362,8 +365,7 @@ fn rewrite_chain_subexpr(expr: &ast::Expr, -> Option { match expr.node { ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => { - let inner = &RewriteContext { block_indent: shape.indent, ..*context }; - rewrite_method_call(method_name.node, types, expressions, span, inner, shape) + rewrite_method_call(method_name.node, types, expressions, span, context, shape) } ast::ExprKind::Field(_, ref field) => { let s = format!(".{}", field.node); diff --git a/src/expr.rs b/src/expr.rs index 2498ee653af..4f069ba7804 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -253,21 +253,20 @@ pub fn rewrite_pair(lhs: &LHS, where LHS: Rewrite, RHS: Rewrite { - let lhs_budget = try_opt!(shape.width.checked_sub(prefix.len() + infix.len())); - let rhs_budget = try_opt!(shape.width.checked_sub(suffix.len())); - // Get "full width" rhs and see if it fits on the current line. This // usually works fairly well since it tends to place operands of // operations with high precendence close together. // Note that this is non-conservative, but its just to see if it's even // worth trying to put everything on one line. - let rhs_result = rhs.rewrite(context, Shape::legacy(rhs_budget, shape.indent)); + let rhs_shape = try_opt!(shape.sub_width(suffix.len())); + let rhs_result = rhs.rewrite(context, rhs_shape); if let Some(rhs_result) = rhs_result { // This is needed in case of line break not caused by a // shortage of space, but by end-of-line comments, for example. if !rhs_result.contains('\n') { - let lhs_result = lhs.rewrite(context, Shape::legacy(lhs_budget, shape.indent)); + let lhs_shape = try_opt!(shape.sub_width(prefix.len() + infix.len())); + let lhs_result = lhs.rewrite(context, lhs_shape); if let Some(lhs_result) = lhs_result { let mut result = format!("{}{}{}", prefix, lhs_result, infix); @@ -281,14 +280,15 @@ pub fn rewrite_pair(lhs: &LHS, } // Try rewriting the rhs into the remaining space. - let rhs_budget = try_opt!(remaining_width.checked_sub(suffix.len())); - if let Some(rhs_result) = rhs.rewrite(context, - Shape::legacy(rhs_budget, - shape.indent + result.len())) { - if rhs_result.len() <= remaining_width { - result.push_str(&rhs_result); - result.push_str(suffix); - return Some(result); + let rhs_shape = shape.shrink_left(last_line_width(&result) + suffix.len()); + if let Some(rhs_shape) = rhs_shape { + if let Some(rhs_result) = rhs.rewrite(context, rhs_shape) { + // FIXME this should always hold. + if rhs_result.len() <= remaining_width { + result.push_str(&rhs_result); + result.push_str(suffix); + return Some(result); + } } } } @@ -301,17 +301,16 @@ pub fn rewrite_pair(lhs: &LHS, let infix = infix.trim_right(); let lhs_budget = try_opt!(context.config .max_width - .checked_sub(shape.indent.width() + prefix.len() + infix.len())); - let rhs_budget = try_opt!(rhs_budget.checked_sub(prefix.len())); - let rhs_offset = shape.indent + prefix.len(); + .checked_sub(shape.used_width() + prefix.len() + infix.len())); + let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()); - let rhs_result = try_opt!(rhs.rewrite(context, Shape::legacy(rhs_budget, rhs_offset))); - let lhs_result = try_opt!(lhs.rewrite(context, Shape::legacy(lhs_budget, shape.indent))); + let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); + let lhs_result = try_opt!(lhs.rewrite(context, Shape { width: lhs_budget, ..shape })); Some(format!("{}{}{}\n{}{}{}", prefix, lhs_result, infix, - rhs_offset.to_string(context.config), + rhs_shape.indent.to_string(context.config), rhs_result, suffix)) } @@ -328,16 +327,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } else { 1 // "[" }; - let offset = shape.indent + bracket_size; - let inner_context = &RewriteContext { block_indent: offset, ..*context }; - let max_item_width = try_opt!(shape.width.checked_sub(bracket_size * 2)); + let nested_shape = try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)); let items = itemize_list(context.codemap, expr_iter, "]", |item| item.span.lo, |item| item.span.hi, - |item| item.rewrite(inner_context, Shape::legacy(max_item_width, offset)), + |item| item.rewrite(context, nested_shape), span.lo, span.hi) .collect::>(); @@ -347,7 +344,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y)))); let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic(&items, ListTactic::HorizontalVertical, max_item_width) + definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) } else { DefinitiveListTactic::Mixed }; @@ -356,7 +353,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - shape: Shape::legacy(max_item_width, offset), + shape: nested_shape, ends_with_newline: false, config: context.config, }; @@ -390,17 +387,14 @@ fn rewrite_closure(capture: ast::CaptureBy, } else { "" }; - let offset = shape.indent + mover.len(); - // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. - let budget = try_opt!(shape.width.checked_sub(4 + mover.len())); - // 1 = | - let argument_offset = offset + 1; - let ret_str = try_opt!(fn_decl.output.rewrite(context, Shape::legacy(budget, argument_offset))); + let nested_shape = try_opt!(try_opt!(shape.shrink_left(mover.len())).sub_width(4)); - // 1 = space between arguments and return type. - let horizontal_budget = budget.checked_sub(ret_str.len() + 1).unwrap_or(0); + // 1 = | + let argument_offset = nested_shape.indent + 1; + let arg_shape = try_opt!(nested_shape.shrink_left(1)).visual_indent(0); + let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape)); let arg_items = itemize_list(context.codemap, @@ -408,21 +402,23 @@ fn rewrite_closure(capture: ast::CaptureBy, "|", |arg| span_lo_for_arg(arg), |arg| span_hi_for_arg(arg), - |arg| arg.rewrite(context, Shape::legacy(budget, argument_offset)), + |arg| arg.rewrite(context, arg_shape), context.codemap.span_after(span, "|"), body.span.lo); let item_vec = arg_items.collect::>(); + // 1 = space between arguments and return type. + let horizontal_budget = nested_shape.width.checked_sub(ret_str.len() + 1).unwrap_or(0); let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget); - let budget = match tactic { - DefinitiveListTactic::Horizontal => horizontal_budget, - _ => budget, + let arg_shape = match tactic { + DefinitiveListTactic::Horizontal => try_opt!(arg_shape.sub_width(ret_str.len() + 1)), + _ => arg_shape, }; let fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - shape: Shape::legacy(budget, argument_offset), + shape: arg_shape, ends_with_newline: false, config: context.config, }; @@ -440,12 +436,11 @@ fn rewrite_closure(capture: ast::CaptureBy, } // 1 = space between `|...|` and body. - let extra_offset = extra_offset(&prefix, offset) + 1; - let budget = try_opt!(shape.width.checked_sub(extra_offset)); - let total_offset = offset + extra_offset; + let extra_offset = extra_offset(&prefix, shape) + 1; + let body_shape = try_opt!(shape.sub_width(extra_offset)).add_offset(extra_offset); if let ast::ExprKind::Block(ref block) = body.node { - // The body of the closure is a block. + // The body of the closure is an empty block. if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { return Some(format!("{} {{}}", prefix)); } @@ -461,7 +456,7 @@ fn rewrite_closure(capture: ast::CaptureBy, if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, - Shape::legacy(budget, total_offset)) { + body_shape) { return Some(rw); } } @@ -472,8 +467,7 @@ fn rewrite_closure(capture: ast::CaptureBy, let stmt = &block.stmts[0]; // 4 = braces and spaces. let mut rewrite = stmt.rewrite(context, - Shape::legacy(try_opt!(budget.checked_sub(4)), - total_offset)); + try_opt!(body_shape.sub_width(4))); // Checks if rewrite succeeded and fits on a single line. rewrite = and_one_line(rewrite); @@ -484,13 +478,14 @@ fn rewrite_closure(capture: ast::CaptureBy, } // Either we require a block, or tried without and failed. - return rewrite_closure_block(&block, prefix, context, budget); + let body_shape = shape.block(); + return rewrite_closure_block(&block, prefix, context, body_shape); } if let Some(rw) = rewrite_closure_expr(body, &prefix, context, - Shape::legacy(budget, total_offset)) { + body_shape) { return Some(rw); } @@ -506,7 +501,7 @@ fn rewrite_closure(capture: ast::CaptureBy, rules: ast::BlockCheckMode::Default, span: body.span, }; - return rewrite_closure_block(&block, prefix, context, budget); + return rewrite_closure_block(&block, prefix, context, body_shape.block()); fn rewrite_closure_expr(expr: &ast::Expr, prefix: &str, @@ -523,11 +518,11 @@ fn rewrite_closure(capture: ast::CaptureBy, fn rewrite_closure_block(block: &ast::Block, prefix: String, context: &RewriteContext, - budget: usize) + shape: Shape) -> Option { // Start with visual indent, then fall back to block indent if the // closure is large. - let rewrite = try_opt!(block.rewrite(&context, Shape::legacy(budget, Indent::empty()))); + let rewrite = try_opt!(block.rewrite(&context, shape)); let block_threshold = context.config.closure_block_indent_threshold; if block_threshold < 0 || rewrite.matches('\n').count() <= block_threshold as usize { @@ -536,9 +531,8 @@ fn rewrite_closure(capture: ast::CaptureBy, // The body of the closure is big enough to be block indented, that // means we must re-format. - let mut context = context.clone(); - context.block_indent.alignment = 0; - let rewrite = try_opt!(block.rewrite(&context, Shape::legacy(budget, Indent::empty()))); + let block_shape = shape.block(); + let rewrite = try_opt!(block.rewrite(&context, block_shape)); Some(format!("{} {}", prefix, rewrite)) } } @@ -581,7 +575,7 @@ impl Rewrite for ast::Block { } let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = context.block_indent; + visitor.block_indent = shape.indent; let prefix = match self.rules { ast::BlockCheckMode::Unsafe(..) => { @@ -648,9 +642,7 @@ impl Rewrite for ast::Stmt { _ => unreachable!(), }, context, - Shape::legacy(context.config.max_width - shape.indent.width() - - suffix.len(), - shape.indent)) + try_opt!(shape.sub_width(suffix.len()))) .map(|s| s + suffix) } ast::StmtKind::Mac(..) | @@ -815,32 +807,32 @@ impl<'a> ControlFlow<'a> { impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { debug!("ControlFlow::rewrite {:?} {:?}", self, shape); - let (budget, indent) = if self.nested_if { + let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - (try_opt!(shape.width.checked_sub(7)), shape.indent + 7) + try_opt!(shape.shrink_left(7)) } else { - (shape.width, shape.indent) + shape }; let label_string = rewrite_label(self.label); // 1 = space after keyword. - let inner_offset = indent + self.keyword.len() + label_string.len() + 1; - let mut inner_width = - try_opt!(budget.checked_sub(self.keyword.len() + label_string.len() + 1)); - if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine { - // 2 = " {".len() - inner_width = try_opt!(inner_width.checked_sub(2)); - } + let add_offset = self.keyword.len() + label_string.len() + 1; let pat_expr_string = match self.cond { Some(cond) => { + let mut cond_shape = try_opt!(constr_shape.shrink_left(add_offset)); + if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine { + // 2 = " {".len() + cond_shape = try_opt!(cond_shape.sub_width(2)); + } + try_opt!(rewrite_pat_expr(context, self.pat, cond, self.matcher, self.connector, - Shape::legacy(inner_width, inner_offset))) + cond_shape)) } None => String::new(), }; @@ -855,21 +847,24 @@ impl<'a> Rewrite for ControlFlow<'a> { } } + let used_width = if pat_expr_string.contains('\n') { + last_line_width(&pat_expr_string) + } else { + // 2 = spaces after keyword and condition. + label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 + }; + let block_width = try_opt!(shape.width.checked_sub(used_width)); // This is used only for the empty block case: `{}`. So, we use 1 if we know // we should avoid the single line case. - // 2 = spaces after keyword and condition. - let block_width = try_opt!(shape.width - .checked_sub(label_string.len() + self.keyword.len() + - extra_offset(&pat_expr_string, inner_offset) + - 2)); let block_width = if self.else_block.is_some() || self.nested_if { min(1, block_width) } else { block_width }; - let block_str = try_opt!(self.block - .rewrite(context, Shape::legacy(block_width, shape.indent))); + // TODO this .block() - not what we want if we are actually visually indented + let block_shape = Shape { width: block_width, ..shape }; + let block_str = try_opt!(self.block.rewrite(context, block_shape)); let cond_span = if let Some(cond) = self.cond { cond.span @@ -891,7 +886,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let after_cond_comment = extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); - let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style == @@ -913,14 +908,8 @@ impl<'a> Rewrite for ControlFlow<'a> { if let Some(else_block) = self.else_block { // Since this is an else block, we should not indent for the assignment preceding - // the original if, so set shape.indent.alignment to 0. - let shape = Shape { - width: shape.width, - indent: Indent { - block_indent: shape.indent.block_indent, - alignment: 0, - }, - }; + // the original if, so set shape.offset to 0. + let shape = Shape { offset: 0, ..shape }; let mut last_in_chain = false; let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it @@ -935,7 +924,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + .rewrite(context, shape.visual_indent(0)) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -945,13 +934,14 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + .rewrite(context, shape.visual_indent(0)) } _ => { last_in_chain = true; // When rewriting a block, the width is only used for single line // blocks, passing 1 lets us avoid that. - else_block.rewrite(context, Shape::legacy(min(1, shape.width), shape.indent)) + let else_shape = Shape { width: min(1, shape.width), ..shape }; + else_block.rewrite(context, else_shape) } }; @@ -1097,16 +1087,15 @@ fn rewrite_match(context: &RewriteContext, // `match `cond` {` let cond_budget = try_opt!(shape.width.checked_sub(8)); let cond_str = try_opt!(cond.rewrite(context, Shape::legacy(cond_budget, shape.indent + 6))); - let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysSameLine => " ", _ => alt_block_sep.as_str(), }; let mut result = format!("match {}{}{{", cond_str, block_sep); - let nested_context = context.nested_context(); - let arm_indent = nested_context.block_indent; - let arm_indent_str = arm_indent.to_string(context.config); + let arm_shape = shape.block_indent(context.config.tab_spaces); + let arm_indent_str = arm_shape.indent.to_string(context.config); let open_brace_pos = context.codemap .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); @@ -1120,15 +1109,14 @@ fn rewrite_match(context: &RewriteContext, }; let comment = try_opt!(rewrite_match_arm_comment(context, &missed_str, - Shape::legacy(shape.width, arm_indent), + arm_shape, &arm_indent_str)); result.push_str(&comment); result.push('\n'); result.push_str(&arm_indent_str); - let arm_str = arm.rewrite(&nested_context, - Shape::legacy(context.config.max_width - arm_indent.width(), - arm_indent)); + let arm_str = arm.rewrite(&context, + Shape { width: context.config.max_width - arm_shape.indent.width(), .. arm_shape }); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); } else { @@ -1143,11 +1131,11 @@ fn rewrite_match(context: &RewriteContext, let last_comment = context.snippet(last_span); let comment = try_opt!(rewrite_match_arm_comment(context, &last_comment, - Shape::legacy(shape.width, arm_indent), + arm_shape, &arm_indent_str)); result.push_str(&comment); result.push('\n'); - result.push_str(&context.block_indent.to_string(context.config)); + result.push_str(&shape.indent.to_string(context.config)); result.push('}'); Some(result) } @@ -1197,7 +1185,7 @@ impl Rewrite for ast::Arm { // We only use this visitor for the attributes, should we use it for // more? let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - attr_visitor.block_indent = context.block_indent; + attr_visitor.block_indent = shape.indent.block_only(); attr_visitor.last_pos = attrs[0].span.lo; if attr_visitor.visit_attrs(attrs) { // Attributes included a skip instruction. @@ -1211,9 +1199,10 @@ impl Rewrite for ast::Arm { // Patterns // 5 = ` => {` - let pat_budget = try_opt!(shape.width.checked_sub(5)); + let pat_shape = try_opt!(shape.sub_width(5)); + let pat_strs = try_opt!(pats.iter() - .map(|p| p.rewrite(context, Shape::legacy(pat_budget, shape.indent))) + .map(|p| p.rewrite(context, pat_shape)) .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); @@ -1226,29 +1215,26 @@ impl Rewrite for ast::Arm { }, separator: " |", trailing_separator: SeparatorTactic::Never, - shape: Shape::legacy(pat_budget, shape.indent), + shape: pat_shape, ends_with_newline: false, config: context.config, }; let pats_str = try_opt!(write_list(items, &fmt)); - let budget = if pats_str.contains('\n') { - context.config.max_width - shape.indent.width() + let guard_shape = if pats_str.contains('\n') { + Shape { width: context.config.max_width - shape.indent.width(), ..shape } } else { - shape.width + shape }; let guard_str = try_opt!(rewrite_guard(context, guard, - Shape::legacy(budget, shape.indent), + guard_shape, trimmed_last_line_width(&pats_str))); let pats_str = format!("{}{}", pats_str, guard_str); // Where the next text can start. - let mut line_start = last_line_width(&pats_str); - if !pats_str.contains('\n') { - line_start += shape.indent.width(); - } + let mut line_start = trimmed_last_line_width(&pats_str); let body = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && @@ -1264,16 +1250,17 @@ impl Rewrite for ast::Arm { }; let comma = arm_comma(&context.config, self, body); - let alt_block_sep = String::from("\n") + &context.block_indent.to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() - if context.config.max_width > line_start + comma.len() + 4 { - let budget = context.config.max_width - line_start - comma.len() - 4; - let offset = Indent::new(shape.indent.block_indent, - line_start + 4 - shape.indent.block_indent); - let rewrite = nop_block_collapse(body.rewrite(context, Shape::legacy(budget, offset)), - budget); + if shape.width > line_start + comma.len() + 4 { + let arm_shape = shape.shrink_left(line_start + 4).unwrap().sub_width(comma.len()).unwrap().block(); + // TODO + // let offset = Indent::new(shape.indent.block_indent, + // line_start + 4 - shape.indent.block_indent); + let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), + arm_shape.width); let is_block = if let ast::ExprKind::Block(..) = body.node { true } else { @@ -1301,13 +1288,12 @@ impl Rewrite for ast::Arm { // FIXME: we're doing a second rewrite of the expr; This may not be // necessary. - let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces)); - let indent = context.block_indent.block_indent(context.config); - let inner_context = &RewriteContext { block_indent: indent, ..*context }; - let next_line_body = try_opt!(nop_block_collapse(body.rewrite(inner_context, - Shape::legacy(body_budget, - indent)), - body_budget)); + // TODO + // let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces)); + // let indent = shape.indent.block_only().block_indent(context.config); + let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces)).block_indent(context.config.tab_spaces); + let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape), + body_shape.width)); let indent_str = shape.indent.block_indent(context.config).to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms { if context.config.match_block_trailing_comma { @@ -1394,6 +1380,7 @@ fn rewrite_pat_expr(context: &RewriteContext, connector: &str, shape: Shape) -> Option { + debug!("rewrite_pat_expr {:?}", shape); let mut result = match pat { Some(pat) => { let matcher = if matcher.is_empty() { @@ -1401,26 +1388,22 @@ fn rewrite_pat_expr(context: &RewriteContext, } else { format!("{} ", matcher) }; - let pat_budget = try_opt!(shape.width.checked_sub(connector.len() + matcher.len())); - let pat_offset = shape.indent + matcher.len(); - let pat_string = try_opt!(pat.rewrite(context, Shape::legacy(pat_budget, pat_offset))); + let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())).sub_width(connector.len())); + let pat_string = try_opt!(pat.rewrite(context, pat_shape)); format!("{}{}{}", matcher, pat_string, connector) } None => String::new(), }; // Consider only the last line of the pat string. - let extra_offset = extra_offset(&result, shape.indent); + let extra_offset = extra_offset(&result, shape); - // The expression may (partionally) fit on the current line. + // The expression may (partially) fit on the current line. if shape.width > extra_offset + 1 { let spacer = if pat.is_some() { " " } else { "" }; - let expr_rewrite = expr.rewrite(context, - Shape::legacy(try_opt!(shape.width - .checked_sub(extra_offset + - spacer.len())), - shape.indent + extra_offset + spacer.len())); + let expr_shape = try_opt!(shape.sub_width(extra_offset + spacer.len())).add_offset(extra_offset + spacer.len()); + let expr_rewrite = expr.rewrite(context, expr_shape); if let Some(expr_string) = expr_rewrite { let pat_simple = pat.and_then(|p| { @@ -1437,17 +1420,17 @@ fn rewrite_pat_expr(context: &RewriteContext, } } - let nested = context.nested_context(); + let nested_indent = shape.indent.block_only().block_indent(context.config); // The expression won't fit on the current line, jump to next. result.push('\n'); - result.push_str(&nested.block_indent.to_string(context.config)); + result.push_str(&nested_indent.to_string(context.config)); - let expr_rewrite = expr.rewrite(&nested, + let expr_rewrite = expr.rewrite(&context, Shape::legacy(try_opt!(context.config .max_width - .checked_sub(nested.block_indent.width())), - nested.block_indent)); + .checked_sub(nested_indent.width())), + nested_indent)); result.push_str(&try_opt!(expr_rewrite)); Some(result) @@ -1533,7 +1516,7 @@ fn rewrite_call_inner(context: &RewriteContext, let callee = callee.borrow(); // FIXME using byte lens instead of char lens (and probably all over the // place too) - let callee_str = match callee.rewrite(context, Shape::legacy(max_callee_width, shape.indent)) { + let callee_str = match callee.rewrite(context, Shape { width: max_callee_width, ..shape }) { Some(string) => { if !string.contains('\n') && string.len() > max_callee_width { panic!("{:?} {}", string, max_callee_width); @@ -1547,20 +1530,15 @@ fn rewrite_call_inner(context: &RewriteContext, let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); - let extra_offset = extra_offset(&callee_str, shape.indent); + let used_width = extra_offset(&callee_str, shape); // 2 is for parens. - let remaining_width = match shape.width.checked_sub(extra_offset + 2) { - Some(str) => str, + let remaining_width = match shape.width.checked_sub(used_width + 2) { + Some(s) => s, None => return Err(Ordering::Greater), }; - let offset = shape.indent + extra_offset + 1; + // 1 = ( + let nested_shape = shape.visual_indent(used_width + 1); let arg_count = args.len(); - let block_indent = if arg_count == 1 { - context.block_indent - } else { - offset - }; - let inner_context = &RewriteContext { block_indent: block_indent, ..*context }; let items = itemize_list(context.codemap, @@ -1568,7 +1546,7 @@ fn rewrite_call_inner(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - |item| item.rewrite(inner_context, Shape::legacy(remaining_width, offset)), + |item| item.rewrite(context, Shape { width: remaining_width, ..nested_shape }), span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1588,9 +1566,12 @@ fn rewrite_call_inner(context: &RewriteContext, // Replace the last item with its first line to see if it fits with // first arguments. if overflow_last { - let inner_context = &RewriteContext { block_indent: context.block_indent, ..*context }; - let rewrite = - args.last().unwrap().rewrite(inner_context, Shape::legacy(remaining_width, offset)); + let nested_shape = Shape { + width: remaining_width, + indent: nested_shape.indent.block_only(), + ..nested_shape + }; + let rewrite = args.last().unwrap().rewrite(context, nested_shape); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); @@ -1622,7 +1603,7 @@ fn rewrite_call_inner(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - shape: Shape::legacy(shape.width, offset), + shape: nested_shape, ends_with_newline: false, config: context.config, }; @@ -1643,9 +1624,8 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> debug!("rewrite_paren, shape: {:?}", shape); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing // paren on the same line as the subexpr. - let subexpr_str = subexpr.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(2)), - shape.indent + 1)); + let sub_shape = try_opt!(shape.sub_width(2)).visual_indent(1); + let subexpr_str = subexpr.rewrite(context, sub_shape); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); subexpr_str.map(|s| if context.config.spaces_within_parens && s.len() > 0 { @@ -1699,24 +1679,20 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } // 2 = " {".len() - let path_budget = try_opt!(shape.width.checked_sub(2)); + let path_shape = try_opt!(shape.sub_width(2)); let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, - Shape::legacy(path_budget, shape.indent))); + path_shape)); // Foo { a: Foo } - indent is +3, width is -5. - let h_budget = shape.width.checked_sub(path_str.len() + 5).unwrap_or(0); - // The 1 taken from the v_budget is for the comma. - let (indent, v_budget) = match context.config.struct_lit_style { - StructLitStyle::Visual => (shape.indent + path_str.len() + 3, h_budget), + let h_shape = shape.sub_width(path_str.len() + 5); + let v_shape = match context.config.struct_lit_style { + StructLitStyle::Visual => try_opt!(try_opt!(shape.shrink_left(path_str.len() + 3)).sub_width(2)), StructLitStyle::Block => { - // If we are all on one line, then we'll ignore the indent, and we - // have a smaller budget. - let indent = context.block_indent.block_indent(context.config); - let v_budget = context.config.max_width.checked_sub(indent.width()).unwrap_or(0); - (indent, v_budget) + let shape = shape.block_indent(context.config.tab_spaces); + Shape { width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), ..shape } } }; @@ -1724,8 +1700,6 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, .map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); - let inner_context = &RewriteContext { block_indent: indent, ..*context }; - let items = itemize_list(context.codemap, field_iter, "}", @@ -1747,14 +1721,15 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| { match *item { StructLitField::Regular(field) => { - rewrite_field(inner_context, + // The 1 taken from the v_budget is for the comma. + rewrite_field(context, field, - Shape::legacy(v_budget.checked_sub(1).unwrap_or(0), indent)) + try_opt!(v_shape.sub_width(1))) } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(inner_context, - Shape::legacy(try_opt!(v_budget.checked_sub(2)), indent + 2)) + expr.rewrite(context, + try_opt!(v_shape.shrink_left(2))) .map(|s| format!("..{}", s)) } } @@ -1763,7 +1738,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, span.hi); let item_vec = items.collect::>(); - let tactic = { + let tactic = if let Some(h_shape) = h_shape { let mut prelim_tactic = match (context.config.struct_lit_style, fields.len()) { (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style.to_list_tactic(), @@ -1773,12 +1748,14 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); } - definitive_tactic(&item_vec, prelim_tactic, h_budget) + definitive_tactic(&item_vec, prelim_tactic, h_shape.width) + } else { + DefinitiveListTactic::Vertical }; - let budget = match tactic { - DefinitiveListTactic::Horizontal => h_budget, - _ => v_budget, + let nested_shape = match tactic { + DefinitiveListTactic::Horizontal => h_shape.unwrap(), + _ => v_shape, }; let ends_with_newline = context.config.struct_lit_style != StructLitStyle::Visual && @@ -1792,36 +1769,33 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } else { context.config.struct_lit_trailing_comma }, - shape: Shape::legacy(budget, indent), + shape: nested_shape, ends_with_newline: ends_with_newline, config: context.config, }; let fields_str = try_opt!(write_list(&item_vec, &fmt)); + // Empty struct. if fields_str.is_empty() { return Some(format!("{} {{}}", path_str)); } - let format_on_newline = || { - let inner_indent = context.block_indent - .block_indent(context.config) - .to_string(context.config); - let outer_indent = context.block_indent.to_string(context.config); - Some(format!("{} {{\n{}{}\n{}}}", - path_str, - inner_indent, - fields_str, - outer_indent)) - }; - - match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) { - (StructLitStyle::Block, _) if fields_str.contains('\n') || fields_str.len() > h_budget => { - format_on_newline() - } - (StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(), - _ => Some(format!("{} {{ {} }}", path_str, fields_str)), + // One liner or visual indent. + if context.config.struct_lit_style == StructLitStyle::Visual || + (context.config.struct_lit_multiline_style != MultilineStyle::ForceMulti && + !fields_str.contains('\n') && + fields_str.len() <= h_shape.map(|s| s.width).unwrap_or(0)) { + return Some(format!("{} {{ {} }}", path_str, fields_str)); } + // Multiple lines. + let inner_indent = v_shape.indent.to_string(context.config); + let outer_indent = shape.indent.to_string(context.config); + Some(format!("{} {{\n{}{}\n{}}}", + path_str, + inner_indent, + fields_str, + outer_indent)) // FIXME if context.config.struct_lit_style == Visual, but we run out // of space, we should fall back to BlockIndent. } @@ -1842,9 +1816,9 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> } else { let separator = type_annotation_separator(context.config); let overhead = name.len() + separator.len(); - let expr = field.expr.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(overhead)), - shape.indent + overhead)); + let mut expr_shape = try_opt!(shape.sub_width(overhead)); + expr_shape.offset += overhead; + let expr = field.expr.rewrite(context, expr_shape); match expr { Some(e) => Some(format!("{}{}{}", name, separator, e)), @@ -1871,16 +1845,14 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, ::Item: Deref, ::Target: Rewrite + Spanned + 'a { - let indent = shape.indent + 1; - let aligned = RewriteContext { block_indent: indent, ..context.clone() }; - + debug!("rewrite_tuple {:?}", shape); // In case of length 1, need a trailing comma if items.len() == 1 { // 3 = "(" + ",)" - let budget = try_opt!(shape.width.checked_sub(3)); + let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); return items.next() .unwrap() - .rewrite(&aligned, Shape::legacy(budget, indent)) + .rewrite(context, nested_shape) .map(|s| if context.config.spaces_within_parens { format!("( {}, )", s) } else { @@ -1889,16 +1861,16 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, } let list_lo = context.codemap.span_after(span, "("); - let budget = try_opt!(shape.width.checked_sub(2)); + let nested_shape = try_opt!(shape.sub_width(2)).visual_indent(1); let items = itemize_list(context.codemap, items, ")", |item| item.span().lo, |item| item.span().hi, - |item| item.rewrite(&aligned, Shape::legacy(budget, indent)), + |item| item.rewrite(context, nested_shape), list_lo, span.hi - BytePos(1)); - let list_str = try_opt!(format_item_list(items, Shape::legacy(budget, indent), context.config)); + let list_str = try_opt!(format_item_list(items, nested_shape, context.config)); if context.config.spaces_within_parens && list_str.len() > 0 { Some(format!("( {} )", list_str)) @@ -1912,10 +1884,8 @@ pub fn rewrite_unary_prefix(context: &RewriteContext, rewrite: &R, shape: Shape) -> Option { - rewrite.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(prefix.len())), - shape.indent + prefix.len())) - .map(|r| format!("{}{}", prefix, r)) + let shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); + rewrite.rewrite(context, shape).map(|r| format!("{}{}", prefix, r)) } // FIXME: this is probably not correct for multi-line Rewrites. we should @@ -1925,9 +1895,7 @@ pub fn rewrite_unary_suffix(context: &RewriteContext, rewrite: &R, shape: Shape) -> Option { - rewrite.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(suffix.len())), - shape.indent)) + rewrite.rewrite(context, try_opt!(shape.sub_width(suffix.len()))) .map(|mut r| { r.push_str(suffix); r @@ -1960,9 +1928,9 @@ fn rewrite_assignment(context: &RewriteContext, }; // 1 = space between lhs and operator. - let max_width = try_opt!(shape.width.checked_sub(operator_str.len() + 1)); + let lhs_shape = try_opt!(shape.sub_width(operator_str.len() + 1)); let lhs_str = format!("{} {}", - try_opt!(lhs.rewrite(context, Shape::legacy(max_width, shape.indent))), + try_opt!(lhs.rewrite(context, lhs_shape)), operator_str); rewrite_assign_rhs(context, lhs_str, rhs, shape) @@ -1985,7 +1953,9 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // 1 = space between operator and rhs. let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1)); let rhs = ex.rewrite(context, - Shape::legacy(max_width, shape.indent + last_line_width + 1)); + Shape::offset(max_width, + shape.indent.block_only(), + shape.indent.alignment + last_line_width + 1)); fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() @@ -2003,8 +1973,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let new_offset = shape.indent.block_indent(context.config); let max_width = try_opt!((shape.width + shape.indent.width()) .checked_sub(new_offset.width())); - let inner_context = context.nested_context(); - let new_rhs = ex.rewrite(&inner_context, Shape::legacy(max_width, new_offset)); + let new_rhs = ex.rewrite(context, Shape::legacy(max_width, new_offset)); // FIXME: DRY! match (rhs, new_rhs) { diff --git a/src/items.rs b/src/items.rs index 3c5bf3ce6ce..1a27b5bfbc9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -70,12 +70,12 @@ impl Rewrite for ast::Local { if let Some(ref ex) = self.init { // 1 = trailing semicolon; - let budget = try_opt!(shape.width.checked_sub(context.block_indent.width() + 1)); + let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1)); result = try_opt!(rewrite_assign_rhs(&context, result, ex, - Shape::legacy(budget, context.block_indent))); + Shape::legacy(budget, shape.indent.block_only()))); } result.push(';'); @@ -520,7 +520,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - context.config, context.config.item_brace_style, Shape::legacy(where_budget, - context.block_indent), + offset.block_only()), context.config.where_density, "{", true, @@ -539,7 +539,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { result.push('\n'); - let width = context.block_indent.width() + context.config.tab_spaces - 1; + let width = offset.block_indent + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); result.push_str(&where_indent.to_string(context.config)); } @@ -568,7 +568,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = context.block_indent.block_indent(context.config); + visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in items { @@ -578,7 +578,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - visitor.format_missing(item.span.hi - BytePos(1)); let inner_indent_str = visitor.block_indent.to_string(context.config); - let outer_indent_str = context.block_indent.to_string(context.config); + let outer_indent_str = offset.block_only().to_string(context.config); result.push('\n'); result.push_str(&inner_indent_str); @@ -654,7 +654,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, result.push('\n'); // Add indentation of one additional tab. - let width = context.block_indent.width() + context.config.tab_spaces; + let width = offset.block_indent + context.config.tab_spaces; let for_indent = Indent::new(0, width); result.push_str(&for_indent.to_string(context.config)); @@ -762,7 +762,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if offset.width() + last_line_width(&result) + trait_bound_str.len() > context.config.ideal_width { result.push('\n'); - let trait_indent = context.block_indent.block_indent(context.config); + let trait_indent = offset.block_only().block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); } result.push_str(&trait_bound_str); @@ -789,7 +789,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) context.config, context.config.item_brace_style, Shape::legacy(where_budget, - context.block_indent), + offset.block_only()), where_density, "{", has_body, @@ -800,7 +800,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) last_line_width(&result) + where_clause_str.len() + offset.width() > context.config.ideal_width { result.push('\n'); - let width = context.block_indent.width() + context.config.tab_spaces - 1; + let width = offset.block_indent + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); result.push_str(&where_indent.to_string(context.config)); } @@ -829,7 +829,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = context.block_indent.block_indent(context.config); + visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in trait_items { @@ -839,7 +839,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) visitor.format_missing(item.span.hi - BytePos(1)); let inner_indent_str = visitor.block_indent.to_string(context.config); - let outer_indent_str = context.block_indent.to_string(context.config); + let outer_indent_str = offset.block_only().to_string(context.config); result.push('\n'); result.push_str(&inner_indent_str); @@ -892,7 +892,7 @@ fn format_struct_struct(context: &RewriteContext, } None => { if context.config.item_brace_style == BraceStyle::AlwaysNextLine && !fields.is_empty() { - format!("\n{}{{", context.block_indent.to_string(context.config)) + format!("\n{}{{", offset.block_only().to_string(context.config)) } else { " {".to_owned() } @@ -1004,7 +1004,7 @@ fn format_tuple_struct(context: &RewriteContext, &generics.where_clause, context.config, context.config.item_brace_style, - Shape::legacy(where_budget, context.block_indent), + Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", false, @@ -1014,7 +1014,7 @@ fn format_tuple_struct(context: &RewriteContext, }; result.push('('); - let item_indent = context.block_indent + result.len(); + let item_indent = offset.block_only() + result.len(); // 2 = ");" let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2)); @@ -1052,12 +1052,12 @@ fn format_tuple_struct(context: &RewriteContext, if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && (result.contains('\n') || - context.block_indent.width() + result.len() + where_clause_str.len() + 1 > + offset.block_indent + result.len() + where_clause_str.len() + 1 > context.config.max_width) { // We need to put the where clause on a new line, but we didn'to_string // know that earlier, so the where clause will not be indented properly. result.push('\n'); - result.push_str(&(context.block_indent + (context.config.tab_spaces - 1)) + result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1)) .to_string(context.config)); } result.push_str(&where_clause_str); @@ -1192,6 +1192,7 @@ pub fn rewrite_static(prefix: &str, ty: &ast::Ty, mutability: ast::Mutability, expr_opt: Option<&ptr::P>, + offset: Indent, context: &RewriteContext) -> Option { let type_annotation_spacing = type_annotation_spacing(context.config); @@ -1205,19 +1206,19 @@ pub fn rewrite_static(prefix: &str, // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(context.config.max_width - - context.block_indent.width() - + offset.block_indent - prefix.len() - 2, - context.block_indent))); + offset.block_only()))); if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; + let remaining_width = context.config.max_width - offset.block_indent - 1; rewrite_assign_rhs(context, lhs, expr, - Shape::legacy(remaining_width, context.block_indent)) + Shape::legacy(remaining_width, offset.block_only())) .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); @@ -1253,10 +1254,10 @@ pub fn rewrite_associated_type(ident: ast::Ident, if let Some(ty) = ty_opt { let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(context.config.max_width - - context.block_indent.width() - + indent.block_indent - prefix.len() - 2, - context.block_indent))); + indent.block_only()))); Some(format!("{} = {};", prefix, ty_str)) } else { Some(format!("{}{};", prefix, type_bounds_str)) @@ -1473,7 +1474,7 @@ fn rewrite_fn_base(context: &RewriteContext, multi_line_budget = context.config.max_width - arg_indent.width(); } - debug!("rewrite_fn: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", + debug!("rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", one_line_budget, multi_line_budget, arg_indent); @@ -2020,7 +2021,7 @@ fn format_generics(context: &RewriteContext, context.config, brace_style, Shape::legacy(budget, - context.block_indent), + offset.block_only()), Density::Tall, terminator, true, @@ -2029,7 +2030,7 @@ fn format_generics(context: &RewriteContext, if !force_same_line_brace && (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) { result.push('\n'); - result.push_str(&context.block_indent.to_string(context.config)); + result.push_str(&offset.block_only().to_string(context.config)); } else { result.push(' '); } @@ -2037,7 +2038,7 @@ fn format_generics(context: &RewriteContext, } else { if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine { result.push('\n'); - result.push_str(&context.block_indent.to_string(context.config)); + result.push_str(&offset.block_only().to_string(context.config)); } else { result.push(' '); } diff --git a/src/lib.rs b/src/lib.rs index abe9a6e8554..43054698b2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,6 +133,13 @@ impl Indent { Indent::new(0, 0) } + pub fn block_only(&self) -> Indent { + Indent { + block_indent: self.block_indent, + alignment: 0, + } + } + pub fn block_indent(mut self, config: &Config) -> Indent { self.block_indent += config.tab_spaces; self @@ -204,7 +211,11 @@ impl Sub for Indent { #[derive(Copy, Clone, Debug)] pub struct Shape { pub width: usize, + // The current indentation of code. pub indent: Indent, + // Indentation + any already emitted text on the first line of the current + // statement. + pub offset: usize, } impl Shape { @@ -212,6 +223,7 @@ impl Shape { Shape { width: config.max_width, indent: indent, + offset: indent.width(), } } @@ -234,15 +246,93 @@ impl Shape { Shape { width: width, indent: indent, + offset: indent.alignment, } } - pub fn sub_width(self, width: usize) -> Shape { + pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { Shape { - width: self.width - width, - indent: self.indent, + width: width, + indent: indent, + offset: offset, + } + } + + pub fn visual_indent(&self, extra_width: usize) -> Shape { + let alignment = self.offset + extra_width; + Shape { + width: self.width, + indent: Indent { + block_indent: self.indent.block_indent, + alignment: alignment, + }, + offset: alignment, + } + } + + pub fn block_indent(&self, extra_width: usize) -> Shape { + if self.indent.alignment == 0 { + Shape { + width: self.width, + indent: Indent { + block_indent: self.indent.block_indent + extra_width, + alignment: 0, + }, + offset: 0, + } + } else { + Shape { + width: self.width, + indent: Indent { + block_indent: self.indent.block_indent, + alignment: self.indent.alignment + extra_width, + }, + offset: self.indent.alignment + extra_width, + } } } + + pub fn add_offset(&self, extra_width: usize) -> Shape { + Shape { + width: self.width, + indent: Indent { + block_indent: self.indent.block_indent, + alignment: self.indent.alignment, + }, + offset: self.offset + extra_width, + } + } + + pub fn block(&self) -> Shape { + Shape { + width: self.width, + indent: Indent { + block_indent: self.indent.block_indent, + alignment: 0, + }, + offset: self.offset, + } + } + + pub fn sub_width(&self, width: usize) -> Option { + Some(Shape { + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent, + offset: self.offset, + }) + } + + pub fn shrink_left(&self, width: usize) -> Option { + Some(Shape { + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent + width, + offset: self.offset + width, + }) + } + + pub fn used_width(&self) -> usize { + self.indent.block_indent + self.offset + } } pub enum ErrorKind { diff --git a/src/macros.rs b/src/macros.rs index 3a184d242ef..97c60adb684 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -155,15 +155,14 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Brackets => { // Format macro invocation as array literal. let extra_offset = macro_name.len(); + let shape = try_opt!(shape.shrink_left(extra_offset)); let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), mk_sp(context.codemap .span_after(mac.span, original_style.opener()), mac.span.hi - BytePos(1)), context, - Shape::legacy(try_opt!(shape.width - .checked_sub(extra_offset)), - shape.indent + extra_offset))); + shape)); Some(format!("{}{}", macro_name, rewrite)) } diff --git a/src/patterns.rs b/src/patterns.rs index 7346dc08010..73b54a66626 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -220,16 +220,16 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); // 2 = "()".len(), 3 = "(,)".len() - let width = try_opt!(shape.width.checked_sub(path_len + if add_comma { 3 } else { 2 })); + let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() - let offset = shape.indent + path_len + 1; + let nested_shape = nested_shape.visual_indent(path_len + 1); let mut items: Vec<_> = itemize_list(context.codemap, pat_vec.iter(), if add_comma { ",)" } else { ")" }, |item| item.span().lo, |item| item.span().hi, - |item| item.rewrite(context, Shape::legacy(width, offset)), + |item| item.rewrite(context, nested_shape), context.codemap.span_after(span, "("), span.hi - BytePos(1)) .collect(); @@ -242,10 +242,10 @@ fn rewrite_tuple_pat(pats: &[ptr::P], items[new_item_count - 1].item = Some("..".to_owned()); let da_iter = items.into_iter().take(new_item_count); - try_opt!(format_item_list(da_iter, Shape::legacy(width, offset), context.config)) + try_opt!(format_item_list(da_iter, nested_shape, context.config)) } else { try_opt!(format_item_list(items.into_iter(), - Shape::legacy(width, offset), + nested_shape, context.config)) }; diff --git a/src/rewrite.rs b/src/rewrite.rs index 3c69e2c3c45..bb75a6f4db7 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -13,7 +13,7 @@ use syntax::codemap::{CodeMap, Span}; use syntax::parse::ParseSess; -use {Indent, Shape}; +use Shape; use config::Config; pub trait Rewrite { @@ -26,20 +26,9 @@ pub struct RewriteContext<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, pub config: &'a Config, - // Indentation due to nesting of blocks. - pub block_indent: Indent, } impl<'a> RewriteContext<'a> { - pub fn nested_context(&self) -> RewriteContext<'a> { - RewriteContext { - parse_session: self.parse_session, - codemap: self.codemap, - config: self.config, - block_indent: self.block_indent.block_indent(self.config), - } - } - pub fn snippet(&self, span: Span) -> String { self.codemap.span_to_snippet(span).unwrap() } diff --git a/src/string.rs b/src/string.rs index 014830a9155..7fd6bb78e61 100644 --- a/src/string.rs +++ b/src/string.rs @@ -36,7 +36,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let stripped_str = re.replace_all(orig, "$1"); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let indent = fmt.shape.indent.to_string(fmt.config); + let shape = fmt.shape.visual_indent(0); + let indent = shape.indent.to_string(fmt.config); let punctuation = ":,;."; // `cur_start` is the position in `orig` of the start of the current line. @@ -49,7 +50,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = try_opt!(fmt.shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; + let max_chars = try_opt!(shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. diff --git a/src/types.rs b/src/types.rs index cce487cb2ea..d636f6e587a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -66,9 +66,9 @@ pub fn rewrite_path(context: &RewriteContext, result.push_str("::"); } - let extra_offset = extra_offset(&result, shape.indent); + let extra_offset = extra_offset(&result, shape); // 3 = ">::".len() - let budget = try_opt!(shape.width.checked_sub(extra_offset + 3)); + let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3)); result = try_opt!(rewrite_path_segments(PathContext::Type, result, @@ -76,8 +76,7 @@ pub fn rewrite_path(context: &RewriteContext, span_lo, path.span.hi, context, - Shape::legacy(budget, - shape.indent + extra_offset))); + shape)); } if context.config.spaces_within_angle_brackets { @@ -88,15 +87,15 @@ pub fn rewrite_path(context: &RewriteContext, span_lo = qself.ty.span.hi + BytePos(1); } - let extra_offset = extra_offset(&result, shape.indent); - let budget = try_opt!(shape.width.checked_sub(extra_offset)); + let extra_offset = extra_offset(&result, shape); + let shape = try_opt!(shape.shrink_left(extra_offset)); rewrite_path_segments(path_context, result, path.segments.iter().skip(skip_count), span_lo, path.span.hi, context, - Shape::legacy(budget, shape.indent + extra_offset)) + shape) } fn rewrite_path_segments<'a, I>(path_context: PathContext, @@ -110,6 +109,7 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext, where I: Iterator { let mut first = true; + let shape = shape.visual_indent(0); for segment in iter { // Indicates a global path, shouldn't be rendered. @@ -122,15 +122,14 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext, buffer.push_str("::"); } - let extra_offset = extra_offset(&buffer, shape.indent); - let remaining_width = try_opt!(shape.width.checked_sub(extra_offset)); - let new_offset = shape.indent + extra_offset; + let extra_offset = extra_offset(&buffer, shape); + let new_shape = try_opt!(shape.shrink_left(extra_offset)); let segment_string = try_opt!(rewrite_segment(path_context, segment, &mut span_lo, span_hi, context, - Shape::legacy(remaining_width, new_offset))); + new_shape)); buffer.push_str(&segment_string); } @@ -190,8 +189,7 @@ fn rewrite_segment(path_context: PathContext, shape: Shape) -> Option { let ident_len = segment.identifier.to_string().len(); - let width = try_opt!(shape.width.checked_sub(ident_len)); - let offset = shape.indent + ident_len; + let shape = try_opt!(shape.shrink_left(ident_len)); let params = if let Some(ref params) = segment.parameters { match **params { @@ -216,24 +214,18 @@ fn rewrite_segment(path_context: PathContext, // 1 for < let extra_offset = 1 + separator.len(); // 1 for > - let list_width = try_opt!(width.checked_sub(extra_offset + 1)); + // TODO bad visual indent + let list_shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(1)).visual_indent(0); let items = itemize_list(context.codemap, param_list.into_iter(), ">", |param| param.get_span().lo, |param| param.get_span().hi, - |seg| { - seg.rewrite(context, - Shape::legacy(list_width, - offset + extra_offset)) - }, + |seg| seg.rewrite(context, list_shape), list_lo, span_hi); - let list_str = try_opt!(format_item_list(items, - Shape::legacy(list_width, - offset + extra_offset), - context.config)); + let list_str = try_opt!(format_item_list(items, list_shape, context.config)); // Update position of last bracket. *span_lo = next_span_lo; @@ -254,7 +246,7 @@ fn rewrite_segment(path_context: PathContext, false, data.span, context, - Shape::legacy(width, offset))) + shape)) } _ => String::new(), } diff --git a/src/utils.rs b/src/utils.rs index c9017571025..da48831e672 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,16 +18,16 @@ use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMet use syntax::codemap::BytePos; use syntax::abi; -use {Indent, Shape}; +use Shape; use rewrite::{Rewrite, RewriteContext}; use SKIP_ANNOTATION; // Computes the length of a string's last line, minus offset. -pub fn extra_offset(text: &str, offset: Indent) -> usize { +pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => text.len().checked_sub(idx + 1 + offset.width()).unwrap_or(0), + Some(idx) => text.len().checked_sub(idx + 1 + shape.used_width()).unwrap_or(0), None => text.len(), } } diff --git a/src/visitor.rs b/src/visitor.rs index fd0a1f1ed21..e7fd3beda2f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -294,6 +294,7 @@ impl<'a> FmtVisitor<'a> { ty, mutability, Some(expr), + self.block_indent, &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -304,6 +305,7 @@ impl<'a> FmtVisitor<'a> { ty, ast::Mutability::Immutable, Some(expr), + self.block_indent, &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -353,6 +355,7 @@ impl<'a> FmtVisitor<'a> { ty, ast::Mutability::Immutable, expr_opt.as_ref(), + self.block_indent, &self.get_context()); self.push_rewrite(ti.span, rewrite); } @@ -403,6 +406,7 @@ impl<'a> FmtVisitor<'a> { ty, ast::Mutability::Immutable, Some(expr), + self.block_indent, &self.get_context()); self.push_rewrite(ii.span, rewrite); } @@ -560,7 +564,6 @@ impl<'a> FmtVisitor<'a> { parse_session: self.parse_session, codemap: self.codemap, config: self.config, - block_indent: self.block_indent, } } } -- cgit 1.4.1-3-g733a5 From 181cde9afbc36ed5578b0d71718aa32562f42324 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Wed, 22 Feb 2017 15:11:16 -0500 Subject: honor type_punctuation_density for assoc. types --- src/types.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index cce487cb2ea..b9404e7727b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -161,7 +161,10 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(binding) => { - let mut result = format!("{} = ", binding.ident); + let mut result = match context.config.type_punctuation_density { + TypeDensity::Wide => format!("{} = ", binding.ident), + TypeDensity::Compressed => format!("{}=", binding.ident), + }; let budget = try_opt!(shape.width.checked_sub(result.len())); let rewrite = try_opt!(binding.ty .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); -- cgit 1.4.1-3-g733a5 From 023b578c136df5ff96674feafbe619b72de6916f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 22 Feb 2017 10:54:51 +1300 Subject: Remove indent from context and only use Shape --- src/expr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4f069ba7804..8f6ccbd095e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -853,7 +853,8 @@ impl<'a> Rewrite for ControlFlow<'a> { // 2 = spaces after keyword and condition. label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 }; - let block_width = try_opt!(shape.width.checked_sub(used_width)); + + let block_width = shape.width.checked_sub(used_width).unwrap_or(0); // This is used only for the empty block case: `{}`. So, we use 1 if we know // we should avoid the single line case. let block_width = if self.else_block.is_some() || self.nested_if { @@ -1380,7 +1381,7 @@ fn rewrite_pat_expr(context: &RewriteContext, connector: &str, shape: Shape) -> Option { - debug!("rewrite_pat_expr {:?}", shape); + debug!("rewrite_pat_expr {:?} {:?}", shape, pat); let mut result = match pat { Some(pat) => { let matcher = if matcher.is_empty() { @@ -1407,8 +1408,7 @@ fn rewrite_pat_expr(context: &RewriteContext, if let Some(expr_string) = expr_rewrite { let pat_simple = pat.and_then(|p| { - p.rewrite(context, - Shape::legacy(context.config.max_width, Indent::empty())) + p.rewrite(context, Shape::legacy(context.config.max_width, Indent::empty())) }) .map(|s| pat_is_simple(&s)); -- cgit 1.4.1-3-g733a5 From 3bbdb0355e98978c5f57bd92fda6526762395558 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Feb 2017 16:43:22 +1300 Subject: remove some chain options --- src/chains.rs | 25 ++++++------------------- src/config.rs | 2 -- src/expr.rs | 2 +- 3 files changed, 7 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f3cd2ab8f01..f0a3f56822d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -19,10 +19,11 @@ /// we put each subexpression on a separate, much like the (default) function /// argument function argument strategy. /// -/// Depends on config options: `chain_base_indent` is the indent to use for -/// blocks in the parent/root/base of the chain. +/// Depends on config options: `chain_indent` is the indent to use for +/// blocks in the parent/root/base of the chain (and the rest of the chain's +/// alignment). /// E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the -/// following values of `chain_base_indent`: +/// following values of `chain_indent`: /// Visual: /// ``` /// let foo = { @@ -54,7 +55,6 @@ /// .baz(); /// ``` /// -/// `chain_indent` dictates how the rest of the chain is aligned. /// If the first item in the chain is a block expression, we align the dots with /// the braces. /// Visual: @@ -75,11 +75,6 @@ /// .baz() /// .qux /// ``` -/// `chains_overflow_last` applies only to chains where the last item is a -/// method call. Usually, any line break in a chain sub-expression causes the -/// whole chain to be split with newlines at each `.`. With `chains_overflow_last` -/// true, then we allow the last method call to spill over multiple lines without -/// forcing the rest of the chain to be split. use {Indent, Shape}; use rewrite::{Rewrite, RewriteContext}; @@ -106,7 +101,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let mut parent_shape = shape; if is_block_expr(&parent, "\n") { - parent_shape = chain_base_indent(context, shape); + parent_shape = chain_indent(context, shape); } let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape)); @@ -164,7 +159,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if fits_single_line { fits_single_line = match expr.node { - ref e @ ast::ExprKind::MethodCall(..) if context.config.chains_overflow_last => { + ref e @ ast::ExprKind::MethodCall(..) => { rewrite_method_call_with_overflow(e, &mut last[0], almost_total, @@ -272,14 +267,6 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, (parent, subexpr_list) } -fn chain_base_indent(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.chain_base_indent { - BlockIndentStyle::Visual => shape, - BlockIndentStyle::Inherit => shape.block_indent(0), - BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces), - } -} - fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent { BlockIndentStyle::Visual => shape, diff --git a/src/config.rs b/src/config.rs index 508b569232b..b34082fca3e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -379,9 +379,7 @@ create_config! { "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; - chain_base_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indent on chain base"; chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain"; - chains_overflow_last: bool, true, "Allow last call in method chain to break the line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imported_names: bool, false, "Reorder lists of names in import statements alphabetically"; diff --git a/src/expr.rs b/src/expr.rs index 8f6ccbd095e..f893f9cd12c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1558,7 +1558,7 @@ fn rewrite_call_inner(context: &RewriteContext, Some(&ast::ExprKind::Closure(..)) | Some(&ast::ExprKind::Block(..)) if arg_count > 1 => true, _ => false, - } && context.config.chains_overflow_last; + }; let mut orig_last = None; let mut placeholder = None; -- cgit 1.4.1-3-g733a5 From ba1202f6b3dfc634ed651e1b1f0994b613f7a85c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Feb 2017 16:59:14 +1300 Subject: test fallout --- src/bin/cargo-fmt.rs | 4 ++-- src/bin/rustfmt.rs | 12 ++++++------ src/chains.rs | 2 +- src/expr.rs | 2 +- tests/system.rs | 6 +++--- tests/target/expr.rs | 8 ++++---- 6 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 683c2d433a7..cf476edf7ca 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -99,8 +99,8 @@ fn format_crate(verbosity: Verbosity) -> Result { let files: Vec<_> = targets.into_iter() .filter(|t| t.kind.should_format()) .inspect(|t| if verbosity == Verbosity::Verbose { - println!("[{:?}] {:?}", t.kind, t.path) - }) + println!("[{:?}] {:?}", t.kind, t.path) + }) .map(|t| t.path) .collect(); diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9d66154a814..de12252df0e 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -348,16 +348,16 @@ fn determine_operation(matches: &Matches) -> FmtResult { try!(io::stdin().read_to_string(&mut buffer)); return Ok(Operation::Stdin { - input: buffer, - config_path: config_path, - }); + input: buffer, + config_path: config_path, + }); } // We append files from `--file-lines` later in `execute()`. let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); Ok(Operation::Format { - files: files, - config_path: config_path, - }) + files: files, + config_path: config_path, + }) } diff --git a/src/chains.rs b/src/chains.rs index f0a3f56822d..9a3c329d1c4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -76,7 +76,7 @@ /// .qux /// ``` -use {Indent, Shape}; +use Shape; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, first_line_width}; use expr::rewrite_call; diff --git a/src/expr.rs b/src/expr.rs index f893f9cd12c..7651d543e93 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1235,7 +1235,7 @@ impl Rewrite for ast::Arm { let pats_str = format!("{}{}", pats_str, guard_str); // Where the next text can start. - let mut line_start = trimmed_last_line_width(&pats_str); + let line_start = trimmed_last_line_width(&pats_str); let body = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && diff --git a/tests/system.rs b/tests/system.rs index a2a4c0eeedf..a0a8eefa277 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -212,9 +212,9 @@ fn read_config(filename: &str) -> Config { get_config(sig_comments.get("config").map(|x| &(*x)[..])) } else { get_config(Path::new(filename) - .with_extension("toml") - .file_name() - .and_then(std::ffi::OsStr::to_str)) + .with_extension("toml") + .file_name() + .and_then(std::ffi::OsStr::to_str)) }; for (key, val) in &sig_comments { diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 6b1ae7ec555..025afa4c38a 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -223,9 +223,9 @@ fn casts() { fn indices() { let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) - [x + y + z]; + [x + y + z]; let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) - [xxxxx + yyyyy + zzzzz]; + [xxxxx + yyyyy + zzzzz]; } fn repeats() { @@ -292,6 +292,6 @@ fn issue1106() { } for entry in WalkDir::new(path) - .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) {} + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) {} } -- cgit 1.4.1-3-g733a5 From 9eb78a33335b83073c90dd8b065c31f1fb958dcc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 22 Feb 2017 16:20:50 +1300 Subject: Fallout --- build.rs | 4 +- src/chains.rs | 29 +++--- src/comment.rs | 14 +-- src/expr.rs | 294 ++++++++++++++++++++++++++-------------------------- src/file_lines.rs | 10 +- src/imports.rs | 22 ++-- src/issues.rs | 61 +++++------ src/items.rs | 124 ++++++++++++---------- src/lib.rs | 36 +++---- src/lists.rs | 3 +- src/macros.rs | 24 ++--- src/missed_spans.rs | 6 +- src/patterns.rs | 53 +++++----- src/string.rs | 4 +- src/types.rs | 145 ++++++++++++++------------ src/visitor.rs | 8 +- 16 files changed, 431 insertions(+), 406 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index 9192426f99a..207d48eeb66 100644 --- a/build.rs +++ b/build.rs @@ -16,11 +16,11 @@ fn main() { writeln!(f, "const COMMIT_HASH: Option<&'static str> = {:?};", git_head_sha1()) - .unwrap(); + .unwrap(); writeln!(f, "const WORKTREE_CLEAN: Option = {:?};", git_tree_is_clean()) - .unwrap(); + .unwrap(); // cargo:rerun-if-changed requires one entry per individual file. for entry in WalkDir::new("src") { diff --git a/src/chains.rs b/src/chains.rs index 9a3c329d1c4..d64a51ac7d9 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -119,20 +119,25 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // brace. (parent_shape, false) } else if parent_rewrite.contains('\n') { - (chain_indent(context, parent_shape.block_indent(context.config.tab_spaces)), false) + (chain_indent(context, + parent_shape.block_indent(context.config.tab_spaces)), + false) } else { (chain_indent_newline(context, shape.add_offset(parent_rewrite.len())), false) }; - let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset).checked_sub(nested_shape.indent.width() + nested_shape.offset)); + let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset) + .checked_sub(nested_shape.indent.width() + + nested_shape.offset)); // The alignement in the shape is only used if we start the item on a new // line, so we don't need to preserve the offset. let child_shape = Shape { width: max_width, ..nested_shape }; debug!("child_shape {:?}", child_shape); - let mut rewrites = try_opt!(subexpr_list.iter() - .rev() - .map(|e| rewrite_chain_subexpr(e, total_span, context, child_shape)) - .collect::>>()); + let mut rewrites = + try_opt!(subexpr_list.iter() + .rev() + .map(|e| rewrite_chain_subexpr(e, total_span, context, child_shape)) + .collect::>>()); // Total of all items excluding the last. let almost_total = rewrites[..rewrites.len() - 1] @@ -199,10 +204,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // True if the chain is only `?`s. fn chain_only_try(exprs: &[ast::Expr]) -> bool { exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - }) + true + } else { + false + }) } pub fn rewrite_try(expr: &ast::Expr, @@ -400,8 +405,8 @@ fn rewrite_method_call(method_name: ast::Ident, (args[0].span.hi, String::new()) } else { let type_list: Vec<_> = try_opt!(types.iter() - .map(|ty| ty.rewrite(context, shape)) - .collect()); + .map(|ty| ty.rewrite(context, shape)) + .collect()); let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) diff --git a/src/comment.rs b/src/comment.rs index b7549f10c2d..3f85dd27ac9 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -110,10 +110,10 @@ pub fn rewrite_comment(orig: &str, }) .map(left_trim_comment_line) .map(|line| if orig.starts_with("/*") && line_breaks == 0 { - line.trim_left() - } else { - line - }); + line.trim_left() + } else { + line + }); let mut result = opener.to_owned(); for line in lines { @@ -771,9 +771,9 @@ mod test { fn uncommented(text: &str) -> String { CharClasses::new(text.chars()) .filter_map(|(s, c)| match s { - FullCodeCharKind::Normal => Some(c), - _ => None, - }) + FullCodeCharKind::Normal => Some(c), + _ => None, + }) .collect() } diff --git a/src/expr.rs b/src/expr.rs index 7651d543e93..d54a724b5e9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -115,7 +115,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { ControlFlow::new_if(cond, @@ -125,7 +125,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, shape, expr.span) @@ -170,8 +170,9 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - .or_else(|| wrap_str(context.snippet(expr.span), context.config.max_width, shape)) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str(context.snippet(expr.span), context.config.max_width, shape) + }) } ast::ExprKind::Ret(None) => wrap_str("return".to_owned(), context.config.max_width, shape), ast::ExprKind::Ret(Some(ref expr)) => { @@ -300,9 +301,11 @@ pub fn rewrite_pair(lhs: &LHS, // Re-evaluate the rhs because we have more space now: let infix = infix.trim_right(); let lhs_budget = try_opt!(context.config - .max_width - .checked_sub(shape.used_width() + prefix.len() + infix.len())); - let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()); + .max_width + .checked_sub(shape.used_width() + prefix.len() + + infix.len())); + let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())) + .visual_indent(prefix.len()); let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); let lhs_result = try_opt!(lhs.rewrite(context, Shape { width: lhs_budget, ..shape })); @@ -328,20 +331,20 @@ pub fn rewrite_array<'a, I>(expr_iter: I, 1 // "[" }; let nested_shape = try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)); - let items = - itemize_list(context.codemap, - expr_iter, - "]", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, nested_shape), - span.lo, - span.hi) + let items = itemize_list(context.codemap, + expr_iter, + "]", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, nested_shape), + span.lo, + span.hi) .collect::>(); let has_long_item = try_opt!(items.iter() - .map(|li| li.item.as_ref().map(|s| s.len() > 10)) - .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y)))); + .map(|li| li.item.as_ref().map(|s| s.len() > 10)) + .fold(Some(false), + |acc, x| acc.and_then(|y| x.map(|x| x || y)))); let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) @@ -360,10 +363,10 @@ pub fn rewrite_array<'a, I>(expr_iter: I, let list_str = try_opt!(write_list(&items, &fmt)); Some(if context.config.spaces_within_square_brackets && list_str.len() > 0 { - format!("[ {} ]", list_str) - } else { - format!("[{}]", list_str) - }) + format!("[ {} ]", list_str) + } else { + format!("[{}]", list_str) + }) } // This functions is pretty messy because of the rules around closures and blocks: @@ -396,15 +399,14 @@ fn rewrite_closure(capture: ast::CaptureBy, let arg_shape = try_opt!(nested_shape.shrink_left(1)).visual_indent(0); let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape)); - let arg_items = - itemize_list(context.codemap, - fn_decl.inputs.iter(), - "|", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(arg), - |arg| arg.rewrite(context, arg_shape), - context.codemap.span_after(span, "|"), - body.span.lo); + let arg_items = itemize_list(context.codemap, + fn_decl.inputs.iter(), + "|", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(arg), + |arg| arg.rewrite(context, arg_shape), + context.codemap.span_after(span, "|"), + body.span.lo); let item_vec = arg_items.collect::>(); // 1 = space between arguments and return type. let horizontal_budget = nested_shape.width.checked_sub(ret_str.len() + 1).unwrap_or(0); @@ -453,10 +455,7 @@ fn rewrite_closure(capture: ast::CaptureBy, if ret_str.is_empty() && !needs_block { // lock.stmts.len() == 1 if let Some(ref expr) = stmt_expr(&block.stmts[0]) { - if let Some(rw) = rewrite_closure_expr(expr, - &prefix, - context, - body_shape) { + if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, body_shape) { return Some(rw); } } @@ -466,8 +465,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // We need braces, but we might still prefer a one-liner. let stmt = &block.stmts[0]; // 4 = braces and spaces. - let mut rewrite = stmt.rewrite(context, - try_opt!(body_shape.sub_width(4))); + let mut rewrite = stmt.rewrite(context, try_opt!(body_shape.sub_width(4))); // Checks if rewrite succeeded and fits on a single line. rewrite = and_one_line(rewrite); @@ -482,10 +480,7 @@ fn rewrite_closure(capture: ast::CaptureBy, return rewrite_closure_block(&block, prefix, context, body_shape); } - if let Some(rw) = rewrite_closure_expr(body, - &prefix, - context, - body_shape) { + if let Some(rw) = rewrite_closure_expr(body, &prefix, context, body_shape) { return Some(rw); } @@ -546,10 +541,10 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option= 2 && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { - "{}".to_owned() - } else { - block_str.to_owned() - }) + "{}".to_owned() + } else { + block_str.to_owned() + }) } impl Rewrite for ast::Block { @@ -599,9 +594,10 @@ impl Rewrite for ast::Block { }; if is_simple_block(self, context.codemap) && prefix.len() < shape.width { - let expr_str = self.stmts[0].rewrite(context, - Shape::legacy(shape.width - prefix.len(), - shape.indent)); + let expr_str = + self.stmts[0].rewrite(context, + Shape::legacy(shape.width - prefix.len(), + shape.indent)); let expr_str = try_opt!(expr_str); let result = format!("{}{{ {} }}", prefix, expr_str); if result.len() <= shape.width && !result.contains('\n') { @@ -643,7 +639,7 @@ impl Rewrite for ast::Stmt { }, context, try_opt!(shape.sub_width(suffix.len()))) - .map(|s| s + suffix) + .map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, @@ -782,8 +778,8 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = - try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); + let else_str = try_opt!(else_expr.rewrite(context, + Shape::legacy(new_width, Indent::empty()))); if if_str.contains('\n') || else_str.contains('\n') { return None; @@ -877,17 +873,18 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_cond = mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), self.pat.map_or(cond_span.lo, |p| if self.matcher.is_empty() { - p.span.lo - } else { - context.codemap.span_before(self.span, self.matcher.trim()) - })); + p.span.lo + } else { + context.codemap.span_before(self.span, self.matcher.trim()) + })); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); let after_cond_comment = extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); - let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = String::from("\n") + + &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style == @@ -897,15 +894,15 @@ impl<'a> Rewrite for ControlFlow<'a> { " " }; - let mut result = format!("{}{}{}{}{}{}", - label_string, - self.keyword, - between_kwd_cond_comment.as_ref() - .map_or(if pat_expr_string.is_empty() { "" } else { " " }, - |s| &**s), - pat_expr_string, - after_cond_comment.as_ref().map_or(block_sep, |s| &**s), - block_str); + let mut result = + format!("{}{}{}{}{}{}", + label_string, + self.keyword, + between_kwd_cond_comment.as_ref() + .map_or(if pat_expr_string.is_empty() { "" } else { " " }, |s| &**s), + pat_expr_string, + after_cond_comment.as_ref().map_or(block_sep, |s| &**s), + block_str); if let Some(else_block) = self.else_block { // Since this is an else block, we should not indent for the assignment preceding @@ -925,7 +922,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape.visual_indent(0)) + .rewrite(context, shape.visual_indent(0)) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -935,7 +932,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape.visual_indent(0)) + .rewrite(context, shape.visual_indent(0)) } _ => { last_in_chain = true; @@ -953,10 +950,10 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); - let after_else = mk_sp(context.codemap - .span_after(mk_sp(self.block.span.hi, else_block.span.lo), - "else"), - else_block.span.lo); + let after_else = + mk_sp(context.codemap + .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), + else_block.span.lo); let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style { @@ -973,7 +970,7 @@ impl<'a> Rewrite for ControlFlow<'a> { between_kwd_else_block_comment.as_ref() .map_or(between_sep, |s| &**s), after_else_comment.as_ref().map_or(after_sep, |s| &**s)) - .ok()); + .ok()); result.push_str(&try_opt!(rewrite)); } @@ -1108,16 +1105,17 @@ fn rewrite_match(context: &RewriteContext, } else { context.snippet(mk_sp(arm_end_pos(&arms[i - 1]), arm_start_pos(arm))) }; - let comment = try_opt!(rewrite_match_arm_comment(context, - &missed_str, - arm_shape, - &arm_indent_str)); + let comment = + try_opt!(rewrite_match_arm_comment(context, &missed_str, arm_shape, &arm_indent_str)); result.push_str(&comment); result.push('\n'); result.push_str(&arm_indent_str); let arm_str = arm.rewrite(&context, - Shape { width: context.config.max_width - arm_shape.indent.width(), .. arm_shape }); + Shape { + width: context.config.max_width - arm_shape.indent.width(), + ..arm_shape + }); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); } else { @@ -1130,10 +1128,8 @@ fn rewrite_match(context: &RewriteContext, // BytePos(1) = closing match brace. let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi - BytePos(1)); let last_comment = context.snippet(last_span); - let comment = try_opt!(rewrite_match_arm_comment(context, - &last_comment, - arm_shape, - &arm_indent_str)); + let comment = + try_opt!(rewrite_match_arm_comment(context, &last_comment, arm_shape, &arm_indent_str)); result.push_str(&comment); result.push('\n'); result.push_str(&shape.indent.to_string(context.config)); @@ -1203,8 +1199,8 @@ impl Rewrite for ast::Arm { let pat_shape = try_opt!(shape.sub_width(5)); let pat_strs = try_opt!(pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>()); + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); @@ -1251,17 +1247,18 @@ impl Rewrite for ast::Arm { }; let comma = arm_comma(&context.config, self, body); - let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = String::from("\n") + + &shape.indent.block_only().to_string(context.config); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() if shape.width > line_start + comma.len() + 4 { - let arm_shape = shape.shrink_left(line_start + 4).unwrap().sub_width(comma.len()).unwrap().block(); + let arm_shape = + shape.shrink_left(line_start + 4).unwrap().sub_width(comma.len()).unwrap().block(); // TODO // let offset = Indent::new(shape.indent.block_indent, // line_start + 4 - shape.indent.block_indent); - let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), - arm_shape.width); + let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), arm_shape.width); let is_block = if let ast::ExprKind::Block(..) = body.node { true } else { @@ -1292,7 +1289,8 @@ impl Rewrite for ast::Arm { // TODO // let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces)); // let indent = shape.indent.block_only().block_indent(context.config); - let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces)).block_indent(context.config.tab_spaces); + let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces)) + .block_indent(context.config.tab_spaces); let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape), body_shape.width)); let indent_str = shape.indent.block_indent(context.config).to_string(context.config); @@ -1341,9 +1339,10 @@ fn rewrite_guard(context: &RewriteContext, // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; if overhead < shape.width { - let cond_str = guard.rewrite(context, - Shape::legacy(shape.width - overhead, - shape.indent + pattern_width + 4)); + let cond_str = + guard.rewrite(context, + Shape::legacy(shape.width - overhead, + shape.indent + pattern_width + 4)); if let Some(cond_str) = cond_str { return Some(format!(" if {}", cond_str)); } @@ -1389,7 +1388,8 @@ fn rewrite_pat_expr(context: &RewriteContext, } else { format!("{} ", matcher) }; - let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())).sub_width(connector.len())); + let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())) + .sub_width(connector.len())); let pat_string = try_opt!(pat.rewrite(context, pat_shape)); format!("{}{}{}", matcher, pat_string, connector) } @@ -1403,12 +1403,14 @@ fn rewrite_pat_expr(context: &RewriteContext, if shape.width > extra_offset + 1 { let spacer = if pat.is_some() { " " } else { "" }; - let expr_shape = try_opt!(shape.sub_width(extra_offset + spacer.len())).add_offset(extra_offset + spacer.len()); + let expr_shape = try_opt!(shape.sub_width(extra_offset + spacer.len())) + .add_offset(extra_offset + spacer.len()); let expr_rewrite = expr.rewrite(context, expr_shape); if let Some(expr_string) = expr_rewrite { let pat_simple = pat.and_then(|p| { - p.rewrite(context, Shape::legacy(context.config.max_width, Indent::empty())) + p.rewrite(context, + Shape::legacy(context.config.max_width, Indent::empty())) }) .map(|s| pat_is_simple(&s)); @@ -1540,15 +1542,16 @@ fn rewrite_call_inner(context: &RewriteContext, let nested_shape = shape.visual_indent(used_width + 1); let arg_count = args.len(); - let items = - itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, Shape { width: remaining_width, ..nested_shape }), - span.lo, - span.hi); + let items = itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite(context, Shape { width: remaining_width, ..nested_shape }) + }, + span.lo, + span.hi); let mut item_vec: Vec<_> = items.collect(); // Try letting the last argument overflow to the next line with block @@ -1584,7 +1587,7 @@ fn rewrite_call_inner(context: &RewriteContext, let tactic = definitive_tactic(&item_vec, ListTactic::LimitedHorizontalVertical(context.config - .fn_call_width), + .fn_call_width), remaining_width); // Replace the stub with the full overflowing last argument if the rewrite @@ -1614,10 +1617,10 @@ fn rewrite_call_inner(context: &RewriteContext, }; Ok(if context.config.spaces_within_parens && list_str.len() > 0 { - format!("{}( {} )", callee_str, list_str) - } else { - format!("{}({})", callee_str, list_str) - }) + format!("{}( {} )", callee_str, list_str) + } else { + format!("{}({})", callee_str, list_str) + }) } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { @@ -1629,10 +1632,10 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); subexpr_str.map(|s| if context.config.spaces_within_parens && s.len() > 0 { - format!("( {} )", s) - } else { - format!("({})", s) - }) + format!("( {} )", s) + } else { + format!("({})", s) + }) } fn rewrite_index(expr: &ast::Expr, @@ -1658,8 +1661,8 @@ fn rewrite_index(expr: &ast::Expr, let indent = indent.to_string(&context.config); // FIXME this is not right, since we don't take into account that shape.width // might be reduced from max_width by something on the right. - let budget = - try_opt!(context.config.max_width.checked_sub(indent.len() + lbr.len() + rbr.len())); + let budget = try_opt!(context.config.max_width.checked_sub(indent.len() + lbr.len() + + rbr.len())); let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr)) } @@ -1680,19 +1683,20 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // 2 = " {".len() let path_shape = try_opt!(shape.sub_width(2)); - let path_str = try_opt!(rewrite_path(context, - PathContext::Expr, - None, - path, - path_shape)); + let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape)); // Foo { a: Foo } - indent is +3, width is -5. let h_shape = shape.sub_width(path_str.len() + 5); let v_shape = match context.config.struct_lit_style { - StructLitStyle::Visual => try_opt!(try_opt!(shape.shrink_left(path_str.len() + 3)).sub_width(2)), + StructLitStyle::Visual => { + try_opt!(try_opt!(shape.shrink_left(path_str.len() + 3)).sub_width(2)) + } StructLitStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces); - Shape { width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), ..shape } + Shape { + width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), + ..shape + } } }; @@ -1706,13 +1710,12 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| match *item { StructLitField::Regular(field) => field.span.lo, StructLitField::Base(expr) => { - let last_field_hi = fields.last() - .map_or(span.lo, |field| field.span.hi); - let snippet = - context.snippet(mk_sp(last_field_hi, expr.span.lo)); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } + let last_field_hi = fields.last() + .map_or(span.lo, |field| field.span.hi); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } }, |item| match *item { StructLitField::Regular(field) => field.span.hi, @@ -1722,14 +1725,11 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, match *item { StructLitField::Regular(field) => { // The 1 taken from the v_budget is for the comma. - rewrite_field(context, - field, - try_opt!(v_shape.sub_width(1))) + rewrite_field(context, field, try_opt!(v_shape.sub_width(1))) } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(context, - try_opt!(v_shape.shrink_left(2))) + expr.rewrite(context, try_opt!(v_shape.shrink_left(2))) .map(|s| format!("..{}", s)) } } @@ -1827,8 +1827,8 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> let expr = field.expr .rewrite(context, Shape::legacy(try_opt!(context.config - .max_width - .checked_sub(expr_offset.width())), + .max_width + .checked_sub(expr_offset.width())), expr_offset)); expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) } @@ -1851,13 +1851,13 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); return items.next() - .unwrap() - .rewrite(context, nested_shape) - .map(|s| if context.config.spaces_within_parens { - format!("( {}, )", s) - } else { - format!("({},)", s) - }); + .unwrap() + .rewrite(context, nested_shape) + .map(|s| if context.config.spaces_within_parens { + format!("( {}, )", s) + } else { + format!("({},)", s) + }); } let list_lo = context.codemap.span_after(span, "("); @@ -1946,10 +1946,10 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let mut result = lhs.into(); let last_line_width = last_line_width(&result) - if result.contains('\n') { - shape.indent.width() - } else { - 0 - }; + shape.indent.width() + } else { + 0 + }; // 1 = space between operator and rhs. let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1)); let rhs = ex.rewrite(context, @@ -1972,7 +1972,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // if that works better. let new_offset = shape.indent.block_indent(context.config); let max_width = try_opt!((shape.width + shape.indent.width()) - .checked_sub(new_offset.width())); + .checked_sub(new_offset.width())); let new_rhs = ex.rewrite(context, Shape::legacy(max_width, new_offset)); // FIXME: DRY! diff --git a/src/file_lines.rs b/src/file_lines.rs index 66c937c37c9..2bf54556d27 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -120,8 +120,9 @@ impl FileLines { Some(ref map) => map, }; - match canonicalize_path_string(range.file_name()) - .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { + match canonicalize_path_string(range.file_name()).and_then(|canonical| { + map.get_vec(&canonical).ok_or(()) + }) { Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), Err(_) => false, } @@ -182,8 +183,9 @@ impl JsonSpan { // To allow `collect()`ing into a `MultiMap`. fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - let canonical = try!(canonicalize_path_string(&self.file) - .map_err(|_| format!("Can't canonicalize {}", &self.file))); + let canonical = try!(canonicalize_path_string(&self.file).map_err(|_| { + format!("Can't canonicalize {}", &self.file) + })); Ok((canonical, Range::new(lo, hi))) } } diff --git a/src/imports.rs b/src/imports.rs index 6e7c2d0f7e2..a2cfa34f1ab 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -142,9 +142,9 @@ impl Rewrite for ast::ViewPath { let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && path.segments.len() > 1 { let path = &ast::Path { - span: path.span.clone(), - segments: path.segments[..path.segments.len() - 1].to_owned(), - }; + span: path.span.clone(), + segments: path.segments[..path.segments.len() - 1].to_owned(), + }; try_opt!(rewrite_path(context, PathContext::Import, None, @@ -159,10 +159,10 @@ impl Rewrite for ast::ViewPath { }; Some(if path.segments.last().unwrap().identifier == ident { - path_str - } else { - format!("{} as {}", path_str, ident_str) - }) + path_str + } else { + format!("{} as {}", path_str, ident_str) + }) } } } @@ -348,10 +348,10 @@ pub fn rewrite_use_list(shape: Shape, let list_str = try_opt!(write_list(&items[first_index..], &fmt)); Some(if path_str.is_empty() { - format!("{{{}}}", list_str) - } else { - format!("{}::{{{}}}", path_str, list_str) - }) + format!("{{{}}}", list_str) + } else { + format!("{}::{{{}}}", path_str, list_str) + }) } // Returns true when self item was found. diff --git a/src/issues.rs b/src/issues.rs index 5282ee603ac..e247aad67a0 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -128,16 +128,16 @@ impl BadIssueSeeker { todo_idx += 1; if todo_idx == TO_DO_CHARS.len() { return Seeking::Number { - issue: Issue { - issue_type: IssueType::Todo, - missing_number: if let ReportTactic::Unnumbered = self.report_todo { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; + issue: Issue { + issue_type: IssueType::Todo, + missing_number: if let ReportTactic::Unnumbered = self.report_todo { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; } fixme_idx = 0; } else if self.report_fixme.is_enabled() && c == FIX_ME_CHARS[fixme_idx] { @@ -146,16 +146,17 @@ impl BadIssueSeeker { fixme_idx += 1; if fixme_idx == FIX_ME_CHARS.len() { return Seeking::Number { - issue: Issue { - issue_type: IssueType::Fixme, - missing_number: if let ReportTactic::Unnumbered = self.report_fixme { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; + issue: Issue { + issue_type: IssueType::Fixme, + missing_number: if let ReportTactic::Unnumbered = + self.report_fixme { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; } todo_idx = 0; } else { @@ -178,10 +179,10 @@ impl BadIssueSeeker { return IssueClassification::Bad(issue); } else if c == ')' { return if let NumberPart::CloseParen = part { - IssueClassification::Good - } else { - IssueClassification::Bad(issue) - }; + IssueClassification::Good + } else { + IssueClassification::Bad(issue) + }; } match part { @@ -268,9 +269,9 @@ fn find_issue() { fn issue_type() { let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); let expected = Some(Issue { - issue_type: IssueType::Todo, - missing_number: false, - }); + issue_type: IssueType::Todo, + missing_number: false, + }); assert_eq!(expected, "TODO(#100): more awesomeness" @@ -281,9 +282,9 @@ fn issue_type() { let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); let expected = Some(Issue { - issue_type: IssueType::Fixme, - missing_number: true, - }); + issue_type: IssueType::Fixme, + missing_number: true, + }); assert_eq!(expected, "Test. FIXME: bad, bad, not good" diff --git a/src/items.rs b/src/items.rs index 1a27b5bfbc9..6b66d9ef2c9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -41,7 +41,8 @@ impl Rewrite for ast::Local { let pattern_width = try_opt!(shape.width.checked_sub(pattern_offset.width() + 1)); let pat_str = try_opt!(self.pat - .rewrite(&context, Shape::legacy(pattern_width, pattern_offset))); + .rewrite(&context, + Shape::legacy(pattern_width, pattern_offset))); result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -376,7 +377,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent, self.block_indent.block_indent(self.config), mk_sp(span.lo, body_start)) - .unwrap(); + .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; @@ -455,9 +456,11 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent; let mut result = try_opt!(field.node - .attrs - .rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - indent.width(), indent))); + .attrs + .rewrite(&self.get_context(), + Shape::legacy(self.config.max_width - + indent.width(), + indent))); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -782,8 +785,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) }; let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -937,7 +940,7 @@ fn format_struct_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "{"), span.hi) - .collect::>(); + .collect::>(); // 1 = , let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1; @@ -998,8 +1001,8 @@ fn format_tuple_struct(context: &RewriteContext, result.push_str(&generics_str); let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + .max_width + .checked_sub(last_line_width(&result))); try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -1058,7 +1061,7 @@ fn format_tuple_struct(context: &RewriteContext, // know that earlier, so the where clause will not be indented properly. result.push('\n'); result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1)) - .to_string(context.config)); + .to_string(context.config)); } result.push_str(&where_clause_str); @@ -1091,8 +1094,8 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&generics_str); let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -1115,19 +1118,19 @@ pub fn rewrite_type_alias(context: &RewriteContext, let type_indent = indent + line_width; // Try to fit the type on the same line let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)) - .or_else(|| { - // The line was too short, try to put the type on the next line + .or_else(|| { + // The line was too short, try to put the type on the next line - // Remove the space after '=' - result.pop(); - let type_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context.config - .max_width - .checked_sub(type_indent.width() + ";".len())); - ty.rewrite(context, Shape::legacy(budget, type_indent)) - })); + // Remove the space after '=' + result.pop(); + let type_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&type_indent.to_string(context.config)); + let budget = try_opt!(context.config + .max_width + .checked_sub(type_indent.width() + ";".len())); + ty.rewrite(context, Shape::legacy(budget, type_indent)) + })); result.push_str(&ty_str); result.push_str(";"); Some(result) @@ -1156,9 +1159,10 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); let mut attr_str = try_opt!(self.attrs - .rewrite(context, - Shape::legacy(context.config.max_width - shape.indent.width(), - shape.indent))); + .rewrite(context, + Shape::legacy(context.config.max_width - + shape.indent.width(), + shape.indent))); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&shape.indent.to_string(context.config)); @@ -1205,8 +1209,7 @@ pub fn rewrite_static(prefix: &str, type_annotation_spacing.1); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, - Shape::legacy(context.config.max_width - - offset.block_indent - + Shape::legacy(context.config.max_width - offset.block_indent - prefix.len() - 2, offset.block_only()))); @@ -1219,7 +1222,7 @@ pub fn rewrite_static(prefix: &str, lhs, expr, Shape::legacy(remaining_width, offset.block_only())) - .map(|s| s + ";") + .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); Some(lhs) @@ -1237,11 +1240,11 @@ pub fn rewrite_associated_type(ident: ast::Ident, let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) - }) - .intersperse(Some(" + ".to_string())) - .collect::>()); + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) + }) + .intersperse(Some(" + ".to_string())) + .collect::>()); if bounds.len() > 0 { format!(": {}", bound_str) } else { @@ -1281,7 +1284,8 @@ impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { let mut result = try_opt!(self.pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))); + .rewrite(context, + Shape::legacy(shape.width, shape.indent))); if self.ty.node != ast::TyKind::Infer { if context.config.space_before_type_annotation { @@ -1314,7 +1318,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = try_opt!(l.rewrite(context, + let lifetime_str = + try_opt!(l.rewrite(context, Shape::legacy(usize::max_value(), Indent::empty()))); Some(format!("&{} {}self", lifetime_str, mut_str)) } @@ -1325,8 +1330,8 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); - let type_str = - try_opt!(ty.rewrite(context, Shape::legacy(usize::max_value(), Indent::empty()))); + let type_str = try_opt!(ty.rewrite(context, + Shape::legacy(usize::max_value(), Indent::empty()))); Some(format!("{}self: {}", format_mutability(mutability), type_str)) } @@ -1458,8 +1463,10 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that if the width and indent really matter, we'll re-layout the // return type later anyway. let ret_str = try_opt!(fd.output - .rewrite(&context, - Shape::legacy(context.config.max_width - indent.width(), indent))); + .rewrite(&context, + Shape::legacy(context.config.max_width - + indent.width(), + indent))); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -1662,18 +1669,21 @@ fn rewrite_args(context: &RewriteContext, variadic: bool) -> Option { let mut arg_item_strs = try_opt!(args.iter() - .map(|arg| arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent))) - .collect::>>()); + .map(|arg| { + arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)) + }) + .collect::>>()); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. - let min_args = - explicit_self.and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) - .map_or(1, |self_str| { - arg_item_strs[0] = self_str; - 2 - }); + let min_args = explicit_self.and_then(|explicit_self| { + rewrite_explicit_self(explicit_self, args, context) + }) + .map_or(1, |self_str| { + arg_item_strs[0] = self_str; + 2 + }); // Comments between args. let mut arg_items = Vec::new(); @@ -1885,10 +1895,10 @@ fn rewrite_generics(context: &RewriteContext, try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); Some(if context.config.spaces_within_angle_brackets { - format!("< {} >", list_str) - } else { - format!("<{}>", list_str) - }) + format!("< {} >", list_str) + } else { + format!("<{}>", list_str) + }) } fn rewrite_trait_bounds(context: &RewriteContext, @@ -1902,9 +1912,9 @@ fn rewrite_trait_bounds(context: &RewriteContext, } let bound_str = try_opt!(bounds.iter() - .map(|ty_bound| ty_bound.rewrite(&context, shape)) - .intersperse(Some(" + ".to_string())) - .collect::>()); + .map(|ty_bound| ty_bound.rewrite(&context, shape)) + .intersperse(Some(" + ".to_string())) + .collect::>()); let mut result = String::new(); result.push_str(": "); diff --git a/src/lib.rs b/src/lib.rs index 43054698b2d..b3f618395f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,7 +256,7 @@ impl Shape { indent: indent, offset: offset, } - } + } pub fn visual_indent(&self, extra_width: usize) -> Shape { let alignment = self.offset + extra_width; @@ -316,18 +316,18 @@ impl Shape { pub fn sub_width(&self, width: usize) -> Option { Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - indent: self.indent, - offset: self.offset, - }) + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent, + offset: self.offset, + }) } pub fn shrink_left(&self, width: usize) -> Option { Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - indent: self.indent + width, - offset: self.offset + width, - }) + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent + width, + offset: self.offset + width, + }) } pub fn used_width(&self) -> usize { @@ -477,9 +477,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m // Add warnings for bad todos/ fixmes if let Some(issue) = issue_seeker.inspect(c) { errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), - }); + line: cur_line, + kind: ErrorKind::BadIssue(issue), + }); } if c == '\n' { @@ -491,9 +491,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m // Check for any line width errors we couldn't correct. if line_len > config.max_width { errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LineOverflow(line_len, config.max_width), - }); + line: cur_line, + kind: ErrorKind::LineOverflow(line_len, config.max_width), + }); } line_len = 0; cur_line += 1; @@ -520,9 +520,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m for &(l, _, _) in &trims { errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - }); + line: l, + kind: ErrorKind::TrailingWhitespace, + }); } report.file_error_map.insert(name.to_owned(), errors); diff --git a/src/lists.rs b/src/lists.rs index 2c78a1040c8..8ba54ab4ccb 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -260,8 +260,7 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = - try_opt!(rewrite_comment(comment, + let formatted_comment = try_opt!(rewrite_comment(comment, true, Shape::legacy(formatting.shape.width, Indent::empty()), formatting.config)); diff --git a/src/macros.rs b/src/macros.rs index 97c60adb684..607e743380a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -92,13 +92,13 @@ pub fn rewrite_macro(mac: &ast::Mac, if mac.node.tts.is_empty() && !contains_comment(&context.snippet(mac.span)) { return match style { - MacroStyle::Parens if position == MacroPosition::Item => { - Some(format!("{}();", macro_name)) - } - MacroStyle::Parens => Some(format!("{}()", macro_name)), - MacroStyle::Brackets => Some(format!("{}[]", macro_name)), - MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), - }; + MacroStyle::Parens if position == MacroPosition::Item => { + Some(format!("{}();", macro_name)) + } + MacroStyle::Parens => Some(format!("{}()", macro_name)), + MacroStyle::Brackets => Some(format!("{}[]", macro_name)), + MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), + }; } let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); @@ -181,11 +181,11 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option FmtVisitor<'a> { Shape::legacy(comment_width, self.block_indent), self.config) - .unwrap()); + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); @@ -155,8 +155,8 @@ impl<'a> FmtVisitor<'a> { if let Some('/') = subslice.chars().skip(1).next() { // check that there are no contained block comments if !subslice.split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() > 2 && &s[0..2] == "/*") { + .map(|s| s.trim_left()) + .any(|s| s.len() > 2 && &s[0..2] == "/*") { // Add a newline after line comments self.buffer.push_str("\n"); } diff --git a/src/patterns.rs b/src/patterns.rs index 73b54a66626..ba642493bdd 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -37,7 +37,9 @@ impl Rewrite for Pat { Some(ref p) => { // 3 - ` @ `. let width = try_opt!(shape.width - .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)); + .checked_sub(prefix.len() + mut_infix.len() + + id_str.len() + + 3)); format!(" @ {}", try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) } @@ -81,8 +83,9 @@ impl Rewrite for Pat { PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = slice_pat.as_ref() - .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); + let slice_pat = + slice_pat.as_ref() + .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. @@ -223,15 +226,14 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() let nested_shape = nested_shape.visual_indent(path_len + 1); - let mut items: Vec<_> = - itemize_list(context.codemap, - pat_vec.iter(), - if add_comma { ",)" } else { ")" }, - |item| item.span().lo, - |item| item.span().hi, - |item| item.rewrite(context, nested_shape), - context.codemap.span_after(span, "("), - span.hi - BytePos(1)) + let mut items: Vec<_> = itemize_list(context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, nested_shape), + context.codemap.span_after(span, "("), + span.hi - BytePos(1)) .collect(); // Condense wildcard string suffix into a single .. @@ -244,26 +246,24 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let da_iter = items.into_iter().take(new_item_count); try_opt!(format_item_list(da_iter, nested_shape, context.config)) } else { - try_opt!(format_item_list(items.into_iter(), - nested_shape, - context.config)) + try_opt!(format_item_list(items.into_iter(), nested_shape, context.config)) }; match path_str { Some(path_str) => { Some(if context.config.spaces_within_parens { - format!("{}( {} )", path_str, list) - } else { - format!("{}({})", path_str, list) - }) + format!("{}( {} )", path_str, list) + } else { + format!("{}({})", path_str, list) + }) } None => { let comma = if add_comma { "," } else { "" }; Some(if context.config.spaces_within_parens { - format!("( {}{} )", list, comma) - } else { - format!("({}{})", list, comma) - }) + format!("( {}{} )", list, comma) + } else { + format!("({}{})", list, comma) + }) } } } @@ -273,9 +273,10 @@ fn count_wildcard_suffix_len(items: &[ListItem]) -> usize { let mut suffix_len = 0; for item in items.iter().rev().take_while(|i| match i.item { - Some(ref internal_string) if internal_string == "_" => true, - _ => false, - }) { + Some(ref internal_string) if internal_string == + "_" => true, + _ => false, + }) { suffix_len += 1; if item.pre_comment.is_some() || item.post_comment.is_some() { diff --git a/src/string.rs b/src/string.rs index 7fd6bb78e61..d8b3711040c 100644 --- a/src/string.rs +++ b/src/string.rs @@ -43,8 +43,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; let mut result = String::with_capacity(stripped_str.len() - .checked_next_power_of_two() - .unwrap_or(usize::max_value())); + .checked_next_power_of_two() + .unwrap_or(usize::max_value())); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); diff --git a/src/types.rs b/src/types.rs index d636f6e587a..574def6d7c4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -162,8 +162,10 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::Binding(binding) => { let mut result = format!("{} = ", binding.ident); let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!(binding.ty - .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); + let rewrite = + try_opt!(binding.ty + .rewrite(context, + Shape::legacy(budget, shape.indent + result.len()))); result.push_str(&rewrite); Some(result) } @@ -215,7 +217,8 @@ fn rewrite_segment(path_context: PathContext, let extra_offset = 1 + separator.len(); // 1 for > // TODO bad visual indent - let list_shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(1)).visual_indent(0); + let list_shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(1)) + .visual_indent(0); let items = itemize_list(context.codemap, param_list.into_iter(), @@ -331,10 +334,10 @@ fn format_function_type<'a, I>(inputs: I, }; Some(if context.config.spaces_within_parens { - format!("( {} ){}{}", list_str, infix, output) - } else { - format!("({}){}{}", list_str, infix, output) - }) + format!("( {} ){}{}", list_str, infix, output) + } else { + format!("({}){}{}", list_str, infix, output) + }) } fn type_bound_colon(context: &RewriteContext) -> &'static str { @@ -411,7 +414,8 @@ impl Rewrite for ast::WherePredicate { let used_width = 3 + lhs_ty_str.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); let rhs_ty_str = try_opt!(rhs_ty.rewrite(context, - Shape::legacy(budget, shape.indent + used_width))); + Shape::legacy(budget, + shape.indent + used_width))); format!("{} = {}", lhs_ty_str, rhs_ty_str) } }; @@ -439,8 +443,8 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, Some(result) } else { let appendix: Vec<_> = try_opt!(bounds.into_iter() - .map(|b| b.rewrite(context, shape)) - .collect()); + .map(|b| b.rewrite(context, shape)) + .collect()); let colon = type_bound_colon(context); let result = format!("{}{}{}", result, colon, appendix.join(" + ")); wrap_str(result, context.config.max_width, shape) @@ -479,8 +483,8 @@ impl Rewrite for ast::TyParamBounds { TypeDensity::Wide => " + ", }; let strs: Vec<_> = try_opt!(self.iter() - .map(|b| b.rewrite(context, shape)) - .collect()); + .map(|b| b.rewrite(context, shape)) + .collect()); wrap_str(strs.join(joiner), context.config.max_width, shape) } } @@ -498,11 +502,12 @@ impl Rewrite for ast::TyParam { result.push_str(" "); } - let bounds: String = try_opt!(self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .intersperse(Some(" + ".to_string())) - .collect()); + let bounds: String = + try_opt!(self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .intersperse(Some(" + ".to_string())) + .collect()); result.push_str(&bounds); } @@ -514,8 +519,8 @@ impl Rewrite for ast::TyParam { }; result.push_str(eq_str); let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = - try_opt!(def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); + let rewrite = try_opt!(def.rewrite(context, + Shape::legacy(budget, shape.indent + result.len()))); result.push_str(&rewrite); } @@ -527,23 +532,24 @@ impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if !self.bound_lifetimes.is_empty() { let lifetime_str: String = try_opt!(self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, shape)) - .intersperse(Some(", ".to_string())) - .collect()); + .iter() + .map(|lt| lt.rewrite(context, shape)) + .intersperse(Some(", ".to_string())) + .collect()); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); let path_str = try_opt!(self.trait_ref - .rewrite(context, - Shape::legacy(max_path_width, shape.indent + extra_offset))); + .rewrite(context, + Shape::legacy(max_path_width, + shape.indent + extra_offset))); Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }) + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }) } else { self.trait_ref.rewrite(context, shape) } @@ -572,31 +578,32 @@ impl Rewrite for ast::Ty { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); Some(match *lifetime { - Some(ref lifetime) => { - let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); - let lt_str = try_opt!(lifetime.rewrite(context, - Shape::legacy(lt_budget, - shape.indent + 2 + - mut_len))); - let lt_len = lt_str.len(); - let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); - format!("&{} {}{}", - lt_str, - mut_str, - try_opt!(mt.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + 2 + mut_len + lt_len)))) - } - None => { - let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); - format!("&{}{}", - mut_str, - try_opt!(mt.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + 1 + mut_len)))) - } - }) + Some(ref lifetime) => { + let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); + let lt_str = try_opt!(lifetime.rewrite(context, + Shape::legacy(lt_budget, + shape.indent + 2 + + mut_len))); + let lt_len = lt_str.len(); + let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); + format!("&{} {}{}", + lt_str, + mut_str, + try_opt!(mt.ty + .rewrite(context, + Shape::legacy(budget, + shape.indent + 2 + mut_len + + lt_len)))) + } + None => { + let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); + format!("&{}{}", + mut_str, + try_opt!(mt.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + 1 + mut_len)))) + } + }) } // FIXME: we drop any comments here, even though it's a silly place to put // comments. @@ -604,10 +611,10 @@ impl Rewrite for ast::Ty { let budget = try_opt!(shape.width.checked_sub(2)); ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_parens { - format!("( {} )", ty_str) - } else { - format!("({})", ty_str) - }) + format!("( {} )", ty_str) + } else { + format!("({})", ty_str) + }) } ast::TyKind::Slice(ref ty) => { let budget = if context.config.spaces_within_square_brackets { @@ -617,10 +624,10 @@ impl Rewrite for ast::Ty { }; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_square_brackets { - format!("[ {} ]", ty_str) - } else { - format!("[{}]", ty_str) - }) + format!("[ {} ]", ty_str) + } else { + format!("[{}]", ty_str) + }) } ast::TyKind::Tup(ref items) => { rewrite_tuple(context, items.iter().map(|x| &**x), self.span, shape) @@ -666,13 +673,13 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. result.push_str(&try_opt!(bare_fn.lifetimes - .iter() - .map(|l| { - l.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) - }) - .intersperse(Some(", ".to_string())) - .collect::>())); + .iter() + .map(|l| { + l.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) + }) + .intersperse(Some(", ".to_string())) + .collect::>())); result.push_str("> "); } diff --git a/src/visitor.rs b/src/visitor.rs index e7fd3beda2f..634248f1b65 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -264,10 +264,10 @@ impl<'a> FmtVisitor<'a> { item.span, indent, None) - .map(|s| match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - }) + .map(|s| match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + }) }; self.push_rewrite(item.span, rewrite); } -- cgit 1.4.1-3-g733a5 From d9d242376421654863a5dbb196d4311476839798 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Feb 2017 08:48:16 +1300 Subject: Tweak chain rules --- src/chains.rs | 28 ++++++++++++++++++++-------- src/items.rs | 19 +++++++++---------- src/visitor.rs | 5 +++-- 3 files changed, 32 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index d64a51ac7d9..218702cdbfd 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -78,7 +78,7 @@ use Shape; use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, first_line_width}; +use utils::{wrap_str, first_line_width, last_line_width}; use expr::rewrite_call; use config::BlockIndentStyle; use macros::convert_try_mac; @@ -129,14 +129,26 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset) .checked_sub(nested_shape.indent.width() + nested_shape.offset)); - // The alignement in the shape is only used if we start the item on a new - // line, so we don't need to preserve the offset. - let child_shape = Shape { width: max_width, ..nested_shape }; - debug!("child_shape {:?}", child_shape); + + let other_child_shape = Shape { width: max_width, ..nested_shape }; + let first_child_shape = if extend { + let mut shape = try_opt!(parent_shape.shrink_left(last_line_width(&parent_rewrite))); + shape.offset = shape.offset.checked_sub(context.config.tab_spaces).unwrap_or(0); + shape.indent.block_indent += context.config.tab_spaces; + shape + } else { + other_child_shape + }; + debug!("child_shapes {:?} {:?}", + first_child_shape, + other_child_shape); + + let child_shape_iter = + Some(first_child_shape).into_iter().chain(::std::iter::repeat(other_child_shape) + .take(subexpr_list.len() - 1)); + let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = - try_opt!(subexpr_list.iter() - .rev() - .map(|e| rewrite_chain_subexpr(e, total_span, context, child_shape)) + try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) .collect::>>()); // Total of all items excluding the last. diff --git a/src/items.rs b/src/items.rs index 6b66d9ef2c9..d0b2c1ee45f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1318,9 +1318,9 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = - try_opt!(l.rewrite(context, - Shape::legacy(usize::max_value(), Indent::empty()))); + let lifetime_str = try_opt!(l.rewrite(context, + Shape::legacy(usize::max_value(), + Indent::empty()))); Some(format!("&{} {}self", lifetime_str, mut_str)) } None => Some(format!("&{}self", mut_str)), @@ -1677,13 +1677,12 @@ fn rewrite_args(context: &RewriteContext, // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. - let min_args = explicit_self.and_then(|explicit_self| { - rewrite_explicit_self(explicit_self, args, context) - }) - .map_or(1, |self_str| { - arg_item_strs[0] = self_str; - 2 - }); + let min_args = + explicit_self.and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) + .map_or(1, |self_str| { + arg_item_strs[0] = self_str; + 2 + }); // Comments between args. let mut arg_items = Vec::new(); diff --git a/src/visitor.rs b/src/visitor.rs index 634248f1b65..1344121b5a6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -486,8 +486,9 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(source!(self, first.span).lo); let rewrite = outers.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - self.block_indent.width(), - self.block_indent)) + Shape::legacy(self.config.max_width - + self.block_indent.width(), + self.block_indent)) .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); -- cgit 1.4.1-3-g733a5 From a7612cc773e8f2ae9d1a3f77676eda3888221053 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 23 Feb 2017 08:52:52 +1300 Subject: more fallout --- build.rs | 8 ++--- src/bin/rustfmt.rs | 10 +++--- src/chains.rs | 14 +++++--- src/expr.rs | 19 +++++------ src/file_lines.rs | 5 +-- src/imports.rs | 8 ++--- src/items.rs | 11 ++++--- src/types.rs | 4 +-- tests/config/small_tabs.toml | 1 - tests/source/chains-block-indented-base.rs | 31 ------------------ tests/source/chains-no-overflow.rs | 38 ---------------------- tests/source/chains-visual.rs | 1 - tests/system.rs | 4 +-- tests/target/chains-block-indented-base.rs | 32 ------------------- tests/target/chains-no-overflow.rs | 41 ------------------------ tests/target/chains-no-overlow-2.rs | 16 ---------- tests/target/chains-visual.rs | 41 ++++++++++++------------ tests/target/chains.rs | 46 +++++++++++++-------------- tests/target/closure.rs | 16 +++++----- tests/target/comment.rs | 8 ++--- tests/target/hard-tabs.rs | 14 ++++---- tests/target/issue-510.rs | 12 +++---- tests/target/long-match-arms-brace-newline.rs | 5 +-- tests/target/long_field_access.rs | 4 +-- tests/target/match.rs | 14 ++++---- tests/target/struct_lits.rs | 10 +++--- tests/target/struct_lits_multiline.rs | 10 +++--- 27 files changed, 135 insertions(+), 288 deletions(-) delete mode 100644 tests/source/chains-block-indented-base.rs delete mode 100644 tests/source/chains-no-overflow.rs delete mode 100644 tests/target/chains-block-indented-base.rs delete mode 100644 tests/target/chains-no-overflow.rs delete mode 100644 tests/target/chains-no-overlow-2.rs (limited to 'src') diff --git a/build.rs b/build.rs index 207d48eeb66..4f4a63be436 100644 --- a/build.rs +++ b/build.rs @@ -39,10 +39,10 @@ fn git_head_sha1() -> Option { .ok() .and_then(|o| String::from_utf8(o.stdout).ok()) .map(|mut s| { - let len = s.trim_right().len(); - s.truncate(len); - s - }) + let len = s.trim_right().len(); + s.truncate(len); + s + }) } // Returns `None` if git is not available. diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index de12252df0e..52d1a8f9f15 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -335,11 +335,11 @@ fn determine_operation(matches: &Matches) -> FmtResult { let config_path: Option = matches.opt_str("config-path") .map(PathBuf::from) .and_then(|dir| { - if dir.is_file() { - return dir.parent().map(|v| v.into()); - } - Some(dir) - }); + if dir.is_file() { + return dir.parent().map(|v| v.into()); + } + Some(dir) + }); // if no file argument is supplied and `--file-lines` is not specified, read from stdin if matches.free.is_empty() && !matches.opt_present("file-lines") { diff --git a/src/chains.rs b/src/chains.rs index 218702cdbfd..e9bd220158f 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -133,9 +133,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let other_child_shape = Shape { width: max_width, ..nested_shape }; let first_child_shape = if extend { let mut shape = try_opt!(parent_shape.shrink_left(last_line_width(&parent_rewrite))); - shape.offset = shape.offset.checked_sub(context.config.tab_spaces).unwrap_or(0); - shape.indent.block_indent += context.config.tab_spaces; - shape + match context.config.chain_indent { + BlockIndentStyle::Visual => other_child_shape, + BlockIndentStyle::Inherit => shape, + BlockIndentStyle::Tabbed => { + shape.offset = shape.offset.checked_sub(context.config.tab_spaces).unwrap_or(0); + shape.indent.block_indent += context.config.tab_spaces; + shape + } + } } else { other_child_shape }; @@ -286,7 +292,7 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent { - BlockIndentStyle::Visual => shape, + BlockIndentStyle::Visual => shape.visual_indent(0), BlockIndentStyle::Inherit => shape.block_indent(0), BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces), } diff --git a/src/expr.rs b/src/expr.rs index d54a724b5e9..d4c34a054b3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -476,7 +476,6 @@ fn rewrite_closure(capture: ast::CaptureBy, } // Either we require a block, or tried without and failed. - let body_shape = shape.block(); return rewrite_closure_block(&block, prefix, context, body_shape); } @@ -1409,9 +1408,10 @@ fn rewrite_pat_expr(context: &RewriteContext, if let Some(expr_string) = expr_rewrite { let pat_simple = pat.and_then(|p| { - p.rewrite(context, - Shape::legacy(context.config.max_width, Indent::empty())) - }) + p.rewrite(context, + Shape::legacy(context.config.max_width, + Indent::empty())) + }) .map(|s| pat_is_simple(&s)); if pat.is_none() || pat_simple.unwrap_or(false) || !expr_string.contains('\n') { @@ -1548,8 +1548,9 @@ fn rewrite_call_inner(context: &RewriteContext, |item| item.span.lo, |item| item.span.hi, |item| { - item.rewrite(context, Shape { width: remaining_width, ..nested_shape }) - }, + item.rewrite(context, + Shape { width: remaining_width, ..nested_shape }) + }, span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1897,9 +1898,9 @@ pub fn rewrite_unary_suffix(context: &RewriteContext, -> Option { rewrite.rewrite(context, try_opt!(shape.sub_width(suffix.len()))) .map(|mut r| { - r.push_str(suffix); - r - }) + r.push_str(suffix); + r + }) } fn rewrite_unary_op(context: &RewriteContext, diff --git a/src/file_lines.rs b/src/file_lines.rs index 2bf54556d27..145713ee1ec 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -121,8 +121,9 @@ impl FileLines { }; match canonicalize_path_string(range.file_name()).and_then(|canonical| { - map.get_vec(&canonical).ok_or(()) - }) { + map.get_vec(&canonical) + .ok_or(()) + }) { Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), Err(_) => false, } diff --git a/src/imports.rs b/src/imports.rs index a2cfa34f1ab..0b432d072af 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -183,10 +183,10 @@ impl<'a> FmtVisitor<'a> { let mut last_pos_of_prev_use_item = pos_before_first_use_item; let mut ordered_use_items = use_items.iter() .map(|p_i| { - let new_item = (&*p_i, last_pos_of_prev_use_item); - last_pos_of_prev_use_item = p_i.span.hi; - new_item - }) + let new_item = (&*p_i, last_pos_of_prev_use_item); + last_pos_of_prev_use_item = p_i.span.hi; + new_item + }) .collect::>(); let pos_after_last_use_item = last_pos_of_prev_use_item; // Order the imports by view-path & other import path properties diff --git a/src/items.rs b/src/items.rs index d0b2c1ee45f..4e5dc9d5765 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1668,11 +1668,12 @@ fn rewrite_args(context: &RewriteContext, span: Span, variadic: bool) -> Option { - let mut arg_item_strs = try_opt!(args.iter() - .map(|arg| { - arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)) - }) - .collect::>>()); + let mut arg_item_strs = + try_opt!(args.iter() + .map(|arg| { + arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)) + }) + .collect::>>()); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked diff --git a/src/types.rs b/src/types.rs index 574def6d7c4..5fbf4a7e150 100644 --- a/src/types.rs +++ b/src/types.rs @@ -675,9 +675,9 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str(&try_opt!(bare_fn.lifetimes .iter() .map(|l| { - l.rewrite(context, + l.rewrite(context, Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) - }) + }) .intersperse(Some(", ".to_string())) .collect::>())); result.push_str("> "); diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 2a0af63eea5..820978b8c32 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -23,5 +23,4 @@ report_fixme = "Never" reorder_imports = false single_line_if_else_max_width = 0 format_strings = true -chains_overflow_last = true take_source_hints = true diff --git a/tests/source/chains-block-indented-base.rs b/tests/source/chains-block-indented-base.rs deleted file mode 100644 index 6646056690d..00000000000 --- a/tests/source/chains-block-indented-base.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chain_base_indent: Inherit -// Test chain formatting with block indented base - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/source/chains-no-overflow.rs b/tests/source/chains-no-overflow.rs deleted file mode 100644 index 29c092d9f1a..00000000000 --- a/tests/source/chains-no-overflow.rs +++ /dev/null @@ -1,38 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chains_overflow_last: false -// Test chain formatting without overflowing the last item. - -fn main() { - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); - - x() - .y(|| match cond() { true => (), false => () }); - - loong_func() - .quux(move || if true { - 1 - } else { - 2 - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx - .map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }).filter(some_mod::some_filter) -} diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs index ea7eeb60524..f0be8acdce9 100644 --- a/tests/source/chains-visual.rs +++ b/tests/source/chains-visual.rs @@ -1,7 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_indent: Visual -// rustfmt-chain_base_indent: Visual // Test chain formatting. fn main() { diff --git a/tests/system.rs b/tests/system.rs index a0a8eefa277..7ce7c55181f 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -295,11 +295,11 @@ fn read_significant_comments(file_name: &str) -> HashMap { .map(|line| line.expect("Failed getting line")) .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { + regex.captures_iter(&line).next().map(|capture| { (capture.at(1).expect("Couldn't unwrap capture").to_owned(), capture.at(2).expect("Couldn't unwrap capture").to_owned()) }) - }) + }) .collect() } diff --git a/tests/target/chains-block-indented-base.rs b/tests/target/chains-block-indented-base.rs deleted file mode 100644 index f737745b366..00000000000 --- a/tests/target/chains-block-indented-base.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chain_base_indent: Inherit -// Test chain formatting with block indented base - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call() - .method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/target/chains-no-overflow.rs b/tests/target/chains-no-overflow.rs deleted file mode 100644 index a6fd0f92a8d..00000000000 --- a/tests/target/chains-no-overflow.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chains_overflow_last: false -// Test chain formatting without overflowing the last item. - -fn main() { - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); - - x().y(|| match cond() { - true => (), - false => (), - }); - - loong_func() - .quux(move || if true { - 1 - } else { - 2 - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) -} diff --git a/tests/target/chains-no-overlow-2.rs b/tests/target/chains-no-overlow-2.rs deleted file mode 100644 index c11070913d9..00000000000 --- a/tests/target/chains-no-overlow-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-chains_overflow_last: false - -fn main() { - reader.lines() - .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(&line)) - .filter_map(|line| { - regex.captures_iter(&line) - .next() - .map(|capture| { - (capture.at(1).expect("Couldn\'t unwrap capture").to_owned(), - capture.at(2).expect("Couldn\'t unwrap capture").to_owned()) - }) - }) - .collect(); -} diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index aff6f170529..e88c08fb932 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -1,7 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 // rustfmt-chain_indent: Visual -// rustfmt-chain_base_indent: Visual // Test chain formatting. fn main() { @@ -21,15 +20,15 @@ fn main() { // Test case where first chain element isn't a path, but is shorter than // the size of a tab. x().y(|| match cond() { - true => (), - false => (), - }); + true => (), + false => (), + }); loong_func().quux(move || if true { - 1 - } else { - 2 - }); + 1 + } else { + 2 + }); some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { let x = c; @@ -50,15 +49,15 @@ fn main() { SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); }); - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, - |acc, x| acc + x); + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = + xxxxxxx.map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) + x += 1; + x + }) .filter(some_mod::some_filter) } @@ -105,9 +104,9 @@ fn floaters() { Foo { x: val } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); Foo { @@ -115,9 +114,9 @@ fn floaters() { z: ok, } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); a + diff --git a/tests/target/chains.rs b/tests/target/chains.rs index d9e7d3a58fe..c7fdd3076e4 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -19,15 +19,15 @@ fn main() { // Test case where first chain element isn't a path, but is shorter than // the size of a tab. x().y(|| match cond() { - true => (), - false => (), - }); + true => (), + false => (), + }); loong_func().quux(move || if true { - 1 - } else { - 2 - }); + 1 + } else { + 2 + }); some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { let x = c; @@ -53,9 +53,9 @@ fn main() { .fold(0, |acc, x| acc + x); aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) + x += 1; + x + }) .filter(some_mod::some_filter) } @@ -84,10 +84,10 @@ fn floaters() { PushParam => { // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); } } } @@ -102,9 +102,9 @@ fn floaters() { Foo { x: val } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); Foo { @@ -112,9 +112,9 @@ fn floaters() { z: ok, } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); a + @@ -173,7 +173,7 @@ fn issue_1004() { }?; ty::tls::with(|tcx| { - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - })?; + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + })?; } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index bc4d03981d5..a3d9cfe863b 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -74,16 +74,16 @@ fn issue863() { fn issue934() { let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish(); - }; + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; } impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 9de4366b1c4..3a973513987 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -41,10 +41,10 @@ fn doc_comment() {} fn chains() { foo.bar(|| { - let x = 10; - // comment - x - }) + let x = 10; + // comment + x + }) } fn issue_1086() { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 43b00774a22..db8c95ed951 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -74,10 +74,10 @@ fn main() { } loong_func().quux(move || if true { - 1 - } else { - 2 - }); + 1 + } else { + 2 + }); fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); @@ -87,7 +87,7 @@ fn main() { .d(); x().y(|| match cond() { - true => (), - false => (), - }); + true => (), + false => (), + }); } diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs index 5b5860998fa..21dca794e93 100644 --- a/tests/target/issue-510.rs +++ b/tests/target/issue-510.rs @@ -14,9 +14,9 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { // and inline-size Auto. // // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + - margin_end)); + let inline_size = + block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); (Au(0), inline_size, margin_start, margin_end) } }; @@ -30,9 +30,9 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { // and inline-size Auto. // // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + - margin_end)); + let inline_size = + block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); (Au(0), inline_size, margin_start, margin_end) } }; diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index 7cf094906cc..852fd4f2f14 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -7,10 +7,7 @@ fn main() { { aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == "aaaaaaaaaaa \ - aaaaaaa aaaaaa" => - { - Ok(()) - } + aaaaaaa aaaaaa" => Ok(()), _ => Err(x), } } diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs index e4efd86b7f9..349d2c2f639 100644 --- a/tests/target/long_field_access.rs +++ b/tests/target/long_field_access.rs @@ -1,4 +1,4 @@ fn f() { - block_flow.base.stacking_relative_position_of_display_port = self.base - .stacking_relative_position_of_display_port; + block_flow.base.stacking_relative_position_of_display_port = + self.base.stacking_relative_position_of_display_port; } diff --git a/tests/target/match.rs b/tests/target/match.rs index 7ebffdc2889..75156347978 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -276,12 +276,14 @@ fn issue494() { hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { result.push(StmtRef::Mirror(Box::new(Stmt { - span: stmt.span, - kind: StmtKind::Expr { - scope: cx.tcx.region_maps.node_extent(id), - expr: expr.to_ref(), - }, - }))) + span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx + .region_maps + .node_extent(id), + expr: expr.to_ref(), + }, + }))) } } } diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 05840b703d3..3fc817d64a6 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -49,11 +49,11 @@ fn main() { }; Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); Diagram { // o This graph demonstrates how diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index 0eb7b8b759f..7cd2acd958f 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -59,11 +59,11 @@ fn main() { }; Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); Diagram { // o This graph demonstrates how -- cgit 1.4.1-3-g733a5 From 7ad352239acbc5c2824ab97ab8881ea843496d0e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Feb 2017 07:52:46 +1300 Subject: Fix width bug for long patterns in match arms Fixes failing test --- src/expr.rs | 19 +++++-------------- tests/target/long-match-arms-brace-newline.rs | 5 ++++- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d4c34a054b3..52c0aee279d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1229,8 +1229,6 @@ impl Rewrite for ast::Arm { trimmed_last_line_width(&pats_str))); let pats_str = format!("{}{}", pats_str, guard_str); - // Where the next text can start. - let line_start = trimmed_last_line_width(&pats_str); let body = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && @@ -1249,14 +1247,12 @@ impl Rewrite for ast::Arm { let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let pat_width = extra_offset(&pats_str, shape); // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() - if shape.width > line_start + comma.len() + 4 { + if shape.width > pat_width + comma.len() + 4 { let arm_shape = - shape.shrink_left(line_start + 4).unwrap().sub_width(comma.len()).unwrap().block(); - // TODO - // let offset = Indent::new(shape.indent.block_indent, - // line_start + 4 - shape.indent.block_indent); + shape.shrink_left(pat_width + 4).unwrap().sub_width(comma.len()).unwrap().block(); let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), arm_shape.width); let is_block = if let ast::ExprKind::Block(..) = body.node { true @@ -1285,9 +1281,6 @@ impl Rewrite for ast::Arm { // FIXME: we're doing a second rewrite of the expr; This may not be // necessary. - // TODO - // let body_budget = try_opt!(shape.width.checked_sub(context.config.tab_spaces)); - // let indent = shape.indent.block_only().block_indent(context.config); let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces)) .block_indent(context.config.tab_spaces); let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape), @@ -1338,10 +1331,8 @@ fn rewrite_guard(context: &RewriteContext, // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; if overhead < shape.width { - let cond_str = - guard.rewrite(context, - Shape::legacy(shape.width - overhead, - shape.indent + pattern_width + 4)); + let cond_shape = shape.shrink_left(pattern_width + 4).unwrap().sub_width(5).unwrap(); + let cond_str = guard.rewrite(context, cond_shape); if let Some(cond_str) = cond_str { return Some(format!(" if {}", cond_str)); } diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index 852fd4f2f14..7cf094906cc 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -7,7 +7,10 @@ fn main() { { aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == "aaaaaaaaaaa \ - aaaaaaa aaaaaa" => Ok(()), + aaaaaaa aaaaaa" => + { + Ok(()) + } _ => Err(x), } } -- cgit 1.4.1-3-g733a5 From 6a58d9123952de104b1e02640261b7e90908bb0e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Feb 2017 10:31:23 +1300 Subject: Coalesce trailing comma options --- src/config.rs | 10 ++--- src/expr.rs | 8 +--- src/items.rs | 20 +++++----- tests/config/small_tabs.toml | 5 +-- tests/source/enum-no_trailing_comma.rs | 41 -------------------- tests/source/match-wildcard-trailing-comma.rs | 10 ----- tests/source/where-trailing-comma.rs | 36 ----------------- tests/target/enum-no_trailing_comma.rs | 31 --------------- tests/target/match-wildcard-trailing-comma.rs | 10 ----- tests/target/where-trailing-comma.rs | 56 --------------------------- 10 files changed, 14 insertions(+), 213 deletions(-) delete mode 100644 tests/source/enum-no_trailing_comma.rs delete mode 100644 tests/source/match-wildcard-trailing-comma.rs delete mode 100644 tests/source/where-trailing-comma.rs delete mode 100644 tests/target/enum-no_trailing_comma.rs delete mode 100644 tests/target/match-wildcard-trailing-comma.rs delete mode 100644 tests/target/where-trailing-comma.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c6c2beae56a..57b8ba190f8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -104,6 +104,7 @@ configuration_option_enum! { TypeDensity: Wide, } + impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { @@ -348,6 +349,8 @@ create_config! { control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, "Brace style for control flow constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, + "How to handle trailing commas for lists"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, @@ -366,16 +369,10 @@ create_config! { where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation style of a where predicate"; - where_trailing_comma: bool, false, "Put a trailing comma on where clauses"; generics_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of generics"; - struct_trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, - "If there is a trailing comma on structs"; - struct_lit_trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, - "If there is a trailing comma on literal structs"; struct_lit_style: StructLitStyle, StructLitStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, "Multiline style on literal structs"; - enum_trailing_comma: bool, true, "Put a trailing comma on enum declarations"; report_todo: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, @@ -396,7 +393,6 @@ create_config! { wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - match_wildcard_trailing_comma: bool, true, "Put a trailing comma after a wildcard arm"; closure_block_indent_threshold: isize, 5, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; space_before_type_annotation: bool, false, diff --git a/src/expr.rs b/src/expr.rs index 52c0aee279d..cbec7d0a8af 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1150,12 +1150,6 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { } fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str { - if !config.match_wildcard_trailing_comma { - if arm.pats.len() == 1 && arm.pats[0].node == ast::PatKind::Wild && arm.guard.is_none() { - return ""; - } - } - if config.match_block_trailing_comma { "," } else if let ast::ExprKind::Block(ref block) = body.node { @@ -1759,7 +1753,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, trailing_separator: if base.is_some() { SeparatorTactic::Never } else { - context.config.struct_lit_trailing_comma + context.config.trailing_comma }, shape: nested_shape, ends_with_newline: ends_with_newline, diff --git a/src/items.rs b/src/items.rs index 4e5dc9d5765..45e2175b801 100644 --- a/src/items.rs +++ b/src/items.rs @@ -434,7 +434,7 @@ impl<'a> FmtVisitor<'a> { let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", - trailing_separator: SeparatorTactic::from_bool(self.config.enum_trailing_comma), + trailing_separator: self.config.trailing_comma, shape: Shape::legacy(budget, self.block_indent), ends_with_newline: true, config: self.config, @@ -526,7 +526,6 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - offset.block_only()), context.config.where_density, "{", - true, None)); if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { @@ -795,7 +794,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) offset.block_only()), where_density, "{", - has_body, None)); // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -952,7 +950,7 @@ fn format_struct_struct(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: context.config.struct_trailing_comma, + trailing_separator: context.config.trailing_comma, shape: Shape::legacy(budget, item_indent), ends_with_newline: true, config: context.config, @@ -1010,7 +1008,6 @@ fn format_tuple_struct(context: &RewriteContext, Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", - false, None)) } None => "".to_owned(), @@ -1103,7 +1100,6 @@ pub fn rewrite_type_alias(context: &RewriteContext, Shape::legacy(where_budget, indent), context.config.where_density, "=", - false, Some(span.hi))); result.push_str(&where_clause_str); result.push_str(" = "); @@ -1645,7 +1641,6 @@ fn rewrite_fn_base(context: &RewriteContext, Shape::legacy(where_budget, indent), where_density, "{", - has_body, Some(span.hi))); if last_line_width(&result) + where_clause_str.len() > context.config.max_width && @@ -1929,7 +1924,6 @@ fn rewrite_where_clause(context: &RewriteContext, shape: Shape, density: Density, terminator: &str, - allow_trailing_comma: bool, span_end: Option) -> Option { if where_clause.predicates.is_empty() { @@ -1969,12 +1963,17 @@ fn rewrite_where_clause(context: &RewriteContext, // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. let tactic = definitive_tactic(&item_vec, context.config.where_layout, budget); - let use_trailing_comma = allow_trailing_comma && context.config.where_trailing_comma; + + let mut comma_tactic = context.config.trailing_comma; + // Kind of a hack because we don't usually have trailing commas in where clauses. + if comma_tactic == SeparatorTactic::Vertical { + comma_tactic = SeparatorTactic::Never; + } let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::from_bool(use_trailing_comma), + trailing_separator: comma_tactic, shape: Shape::legacy(budget, offset), ends_with_newline: true, config: context.config, @@ -2034,7 +2033,6 @@ fn format_generics(context: &RewriteContext, offset.block_only()), Density::Tall, terminator, - true, Some(span.hi))); result.push_str(&where_clause_str); if !force_same_line_brace && diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 820978b8c32..a8150020e56 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -12,12 +12,9 @@ where_density = "Tall" where_indent = "Tabbed" where_layout = "Vertical" where_pred_indent = "Visual" -where_trailing_comma = false generics_indent = "Visual" -struct_trailing_comma = "Vertical" -struct_lit_trailing_comma = "Vertical" +trailing_comma = "Vertical" struct_lit_style = "Block" -enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" reorder_imports = false diff --git a/tests/source/enum-no_trailing_comma.rs b/tests/source/enum-no_trailing_comma.rs deleted file mode 100644 index 4b0347ab526..00000000000 --- a/tests/source/enum-no_trailing_comma.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-enum_trailing_comma: false - -enum X { - A, - B, -} - -enum Y { - A, - B -} - -enum TupX { - A(u32), - B(i32, u16), -} - -enum TupY { - A(u32), - B(i32, u16) -} - -enum StructX { - A { - s: u16, - }, - B { - u: u32, - i: i32, - }, -} - -enum StructY { - A { - s: u16, - }, - B { - u: u32, - i: i32, - } -} diff --git a/tests/source/match-wildcard-trailing-comma.rs b/tests/source/match-wildcard-trailing-comma.rs deleted file mode 100644 index b13e85c2d90..00000000000 --- a/tests/source/match-wildcard-trailing-comma.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-match_wildcard_trailing_comma: false - -fn match_wild(x: i32) -> i32 { - match x { - 1 => 1, - 2 => 2, - 3 => 3, - _ => 0, - } -} diff --git a/tests/source/where-trailing-comma.rs b/tests/source/where-trailing-comma.rs deleted file mode 100644 index c2c1a3185bc..00000000000 --- a/tests/source/where-trailing-comma.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-where_trailing_comma: true - -fn f(x: T, y: S) -> T where T: P, S: Q -{ - x -} - -impl Trait for T where T: P -{ - fn f(x: T) -> T where T: Q + R - { - x - } -} - -struct Pair where T: P, S: P + Q { - a: T, - b: S -} - -struct TupPair (S, T) where T: P, S: P + Q; - -enum E where S: P, T: P { - A {a: T}, -} - -type Double where T: P, T: Q = Pair; - -extern "C" { - fn f(x: T, y: S) -> T where T: P, S: Q; -} - -trait Q where T: P, S: R -{ - fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; -} diff --git a/tests/target/enum-no_trailing_comma.rs b/tests/target/enum-no_trailing_comma.rs deleted file mode 100644 index 2e5a5ad23e3..00000000000 --- a/tests/target/enum-no_trailing_comma.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-enum_trailing_comma: false - -enum X { - A, - B -} - -enum Y { - A, - B -} - -enum TupX { - A(u32), - B(i32, u16) -} - -enum TupY { - A(u32), - B(i32, u16) -} - -enum StructX { - A { s: u16 }, - B { u: u32, i: i32 } -} - -enum StructY { - A { s: u16 }, - B { u: u32, i: i32 } -} diff --git a/tests/target/match-wildcard-trailing-comma.rs b/tests/target/match-wildcard-trailing-comma.rs deleted file mode 100644 index e0fbf81e045..00000000000 --- a/tests/target/match-wildcard-trailing-comma.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-match_wildcard_trailing_comma: false - -fn match_wild(x: i32) -> i32 { - match x { - 1 => 1, - 2 => 2, - 3 => 3, - _ => 0 - } -} diff --git a/tests/target/where-trailing-comma.rs b/tests/target/where-trailing-comma.rs deleted file mode 100644 index 4d4d19cdef8..00000000000 --- a/tests/target/where-trailing-comma.rs +++ /dev/null @@ -1,56 +0,0 @@ -// rustfmt-where_trailing_comma: true - -fn f(x: T, y: S) -> T - where T: P, - S: Q, -{ - x -} - -impl Trait for T - where T: P, -{ - fn f(x: T) -> T - where T: Q + R, - { - x - } -} - -struct Pair - where T: P, - S: P + Q, -{ - a: T, - b: S, -} - -struct TupPair(S, T) - where T: P, - S: P + Q; - -enum E - where S: P, - T: P, -{ - A { a: T }, -} - -type Double - where T: P, - T: Q = Pair; - -extern "C" { - fn f(x: T, y: S) -> T - where T: P, - S: Q; -} - -trait Q - where T: P, - S: R, -{ - fn f(self, x: T, y: S, z: U) -> Self - where U: P, - V: P; -} -- cgit 1.4.1-3-g733a5 From 3323056893a5437790d779d128e8eba3e1c1e5b2 Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Sun, 26 Feb 2017 15:09:09 +0100 Subject: bump regex to 0.2 Signed-off-by: Igor Gnatenko --- Cargo.toml | 2 +- src/string.rs | 2 +- tests/system.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 5f637fcaa52..049f85134d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ cargo-fmt = [] toml = "0.2.1" rustc-serialize = "0.3" unicode-segmentation = "1.0.0" -regex = "0.1" +regex = "0.2" term = "0.4" strings = "0.0.1" diff = "0.1" diff --git a/src/string.rs b/src/string.rs index d8b3711040c..8f51b09b6cc 100644 --- a/src/string.rs +++ b/src/string.rs @@ -32,7 +32,7 @@ pub struct StringFormat<'a> { // FIXME: simplify this! pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { // Strip line breaks. - let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][:space:]*").unwrap(); + let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); let stripped_str = re.replace_all(orig, "$1"); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); diff --git a/tests/system.rs b/tests/system.rs index b2537e80755..257b1ec46bf 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -300,8 +300,8 @@ fn read_significant_comments(file_name: &str) -> HashMap { .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { - (capture.at(1).expect("Couldn't unwrap capture").to_owned(), - capture.at(2).expect("Couldn't unwrap capture").to_owned()) + (capture.get(1).expect("Couldn't unwrap capture").as_str().to_owned(), + capture.get(2).expect("Couldn't unwrap capture").as_str().to_owned()) }) }) .collect() -- cgit 1.4.1-3-g733a5 From 106e011511bf216423a6f9bf91b54aeae28a0644 Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Sun, 26 Feb 2017 15:41:32 +0100 Subject: bump syntex_* to 0.58 Signed-off-by: Igor Gnatenko --- Cargo.toml | 4 ++-- src/patterns.rs | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 049f85134d6..3d076ad5763 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ regex = "0.2" term = "0.4" strings = "0.0.1" diff = "0.1" -syntex_syntax = "0.56" -syntex_errors = "0.56" +syntex_syntax = "0.58" +syntex_errors = "0.58" log = "0.3" env_logger = "0.4" getopts = "0.2" diff --git a/src/patterns.rs b/src/patterns.rs index ba642493bdd..cbaa29a4569 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -18,7 +18,7 @@ use types::{rewrite_path, PathContext}; use super::Spanned; use comment::FindUncommented; -use syntax::ast::{self, BindingMode, Pat, PatKind, FieldPat}; +use syntax::ast::{self, BindingMode, Pat, PatKind, FieldPat, RangeEnd}; use syntax::ptr; use syntax::codemap::{self, BytePos, Span}; @@ -56,8 +56,15 @@ impl Rewrite for Pat { None } } - PatKind::Range(ref lhs, ref rhs) => { - rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape) + PatKind::Range(ref lhs, ref rhs, ref end_kind) => { + match *end_kind { + RangeEnd::Included => { + rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape) + } + RangeEnd::Excluded => { + rewrite_pair(&**lhs, &**rhs, "", "..", "", context, shape) + } + } } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); -- cgit 1.4.1-3-g733a5 From 094c8898e11525d85b184cfe223e17508424c675 Mon Sep 17 00:00:00 2001 From: David Wickes Date: Sun, 26 Feb 2017 21:43:49 +0000 Subject: Fix for #1255 Default annotation incorrectly removed on associated types Fixed by adding a specific function to perform formatting on `ImplItems`. --- src/items.rs | 16 ++++++++++++++++ src/visitor.rs | 14 ++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 4e5dc9d5765..047855571c5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1267,6 +1267,22 @@ pub fn rewrite_associated_type(ident: ast::Ident, } } +pub fn rewrite_associated_impl_type(ident: ast::Ident, + defaultness: ast::Defaultness, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent) + -> Option { + let result = + try_opt!(rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)); + + match defaultness { + ast::Defaultness::Default => Some(format!("default {}", result)), + _ => Some(result), + } +} + impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { diff --git a/src/visitor.rs b/src/visitor.rs index 1344121b5a6..6cd00ffc1f4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,8 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::{rewrite_macro, MacroPosition}; -use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_type, rewrite_associated_impl_type, + rewrite_type_alias, format_impl, format_trait}; fn is_use_item(item: &ast::Item) -> bool { match item.node { @@ -411,11 +412,12 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_type(ii.ident, - Some(ty), - None, - &self.get_context(), - self.block_indent); + let rewrite = rewrite_associated_impl_type(ii.ident, + ii.defaultness, + Some(ty), + None, + &self.get_context(), + self.block_indent); self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { -- cgit 1.4.1-3-g733a5 From 371ffa4710e4babfe0f87d4929f15a8f0cb93ebb Mon Sep 17 00:00:00 2001 From: David Wickes Date: Sun, 26 Feb 2017 21:44:05 +0000 Subject: Small reformat --- src/items.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 047855571c5..457c6749520 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1240,11 +1240,11 @@ pub fn rewrite_associated_type(ident: ast::Ident, let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) - }) - .intersperse(Some(" + ".to_string())) - .collect::>()); + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) + }) + .intersperse(Some(" + ".to_string())) + .collect::>()); if bounds.len() > 0 { format!(": {}", bound_str) } else { -- cgit 1.4.1-3-g733a5 From b8da53ad7865a813e5862fb2de7e839d41af27b3 Mon Sep 17 00:00:00 2001 From: Marcus Ball Date: Tue, 28 Feb 2017 15:46:10 -0500 Subject: Fix wrap_match_arms resulting in a missing comma (#1307) * Fix match arms missing comma with "wrap_match_arms = false" * remove assert; use body_suffix for comma * basic test case for issue 1127 --- src/expr.rs | 30 +++++++++++++++++++++--------- tests/source/issue-1127.rs | 23 +++++++++++++++++++++++ tests/target/issue-1127.rs | 25 +++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 tests/source/issue-1127.rs create mode 100644 tests/target/issue-1127.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 52c0aee279d..edf48d6d7bb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1293,21 +1293,33 @@ impl Rewrite for ast::Arm { ("{", "}") } } else { - ("", "") + ("", ",") }; + let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n", _ => String::from(" ") + body_prefix + "\n", }; - Some(format!("{}{} =>{}{}{}\n{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - indent_str, - next_line_body, - shape.indent.to_string(context.config), - body_suffix)) + + if context.config.wrap_match_arms { + Some(format!("{}{} =>{}{}{}\n{}{}", + attr_str.trim_left(), + pats_str, + block_sep, + indent_str, + next_line_body, + shape.indent.to_string(context.config), + body_suffix)) + } else { + Some(format!("{}{} =>{}{}{}{}", + attr_str.trim_left(), + pats_str, + block_sep, + indent_str, + next_line_body, + body_suffix)) + } } } diff --git a/tests/source/issue-1127.rs b/tests/source/issue-1127.rs new file mode 100644 index 00000000000..4820f5ea229 --- /dev/null +++ b/tests/source/issue-1127.rs @@ -0,0 +1,23 @@ +// rustfmt-max_width:120 +// rustfmt-wrap_match_arms: false +// rustfmt-match_block_trailing_comma: true + +fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { + 42 +} + +enum TestEnum { + AVeryVeryLongEnumName, + AnotherVeryLongEnumName, + TheLastVeryLongEnumName, +} + +fn main() { + let var = TestEnum::AVeryVeryLongEnumName; + let num = match var { + TestEnum::AVeryVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::AnotherVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::TheLastVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + }; +} + diff --git a/tests/target/issue-1127.rs b/tests/target/issue-1127.rs new file mode 100644 index 00000000000..3d133f4ce9c --- /dev/null +++ b/tests/target/issue-1127.rs @@ -0,0 +1,25 @@ +// rustfmt-max_width:120 +// rustfmt-wrap_match_arms: false +// rustfmt-match_block_trailing_comma: true + +fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { + 42 +} + +enum TestEnum { + AVeryVeryLongEnumName, + AnotherVeryLongEnumName, + TheLastVeryLongEnumName, +} + +fn main() { + let var = TestEnum::AVeryVeryLongEnumName; + let num = match var { + TestEnum::AVeryVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::AnotherVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::TheLastVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + }; +} -- cgit 1.4.1-3-g733a5 From f2eac0513f985742b94c9c88fc0b82f474559326 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 2 Mar 2017 14:25:57 +1300 Subject: Fix trailing comma tests --- src/expr.rs | 6 +++--- src/items.rs | 9 ++++++++- tests/source/trailing_commas.rs | 1 + tests/target/trailing_commas.rs | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 83f6e1f22c7..ceba598b8af 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1121,7 +1121,7 @@ fn rewrite_match(context: &RewriteContext, // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); - result.push_str(arm_comma(context.config, arm, &arm.body)); + result.push_str(arm_comma(context.config, &arm.body)); } } // BytePos(1) = closing match brace. @@ -1149,7 +1149,7 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { arm.body.span.hi } -fn arm_comma(config: &Config, arm: &ast::Arm, body: &ast::Expr) -> &'static str { +fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { if config.match_block_trailing_comma { "," } else if let ast::ExprKind::Block(ref block) = body.node { @@ -1237,7 +1237,7 @@ impl Rewrite for ast::Arm { _ => &**body, }; - let comma = arm_comma(&context.config, self, body); + let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); diff --git a/src/items.rs b/src/items.rs index f232d5a8989..60a06f3dc5f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -526,6 +526,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - offset.block_only()), context.config.where_density, "{", + false, None)); if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { @@ -794,6 +795,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) offset.block_only()), where_density, "{", + !has_body, None)); // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -1008,6 +1010,7 @@ fn format_tuple_struct(context: &RewriteContext, Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", + true, None)) } None => "".to_owned(), @@ -1100,6 +1103,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, Shape::legacy(where_budget, indent), context.config.where_density, "=", + true, Some(span.hi))); result.push_str(&where_clause_str); result.push_str(" = "); @@ -1657,6 +1661,7 @@ fn rewrite_fn_base(context: &RewriteContext, Shape::legacy(where_budget, indent), where_density, "{", + !has_body, Some(span.hi))); if last_line_width(&result) + where_clause_str.len() > context.config.max_width && @@ -1940,6 +1945,7 @@ fn rewrite_where_clause(context: &RewriteContext, shape: Shape, density: Density, terminator: &str, + suppress_comma: bool, span_end: Option) -> Option { if where_clause.predicates.is_empty() { @@ -1982,7 +1988,7 @@ fn rewrite_where_clause(context: &RewriteContext, let mut comma_tactic = context.config.trailing_comma; // Kind of a hack because we don't usually have trailing commas in where clauses. - if comma_tactic == SeparatorTactic::Vertical { + if comma_tactic == SeparatorTactic::Vertical || suppress_comma { comma_tactic = SeparatorTactic::Never; } @@ -2049,6 +2055,7 @@ fn format_generics(context: &RewriteContext, offset.block_only()), Density::Tall, terminator, + false, Some(span.hi))); result.push_str(&where_clause_str); if !force_same_line_brace && diff --git a/tests/source/trailing_commas.rs b/tests/source/trailing_commas.rs index d1c53721652..3e5fcc8080f 100644 --- a/tests/source/trailing_commas.rs +++ b/tests/source/trailing_commas.rs @@ -1,3 +1,4 @@ +// rustfmt-match_block_trailing_comma: true // rustfmt-trailing_comma: Always fn main() { diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs index 3c707d07dba..9e74266b396 100644 --- a/tests/target/trailing_commas.rs +++ b/tests/target/trailing_commas.rs @@ -1,3 +1,4 @@ +// rustfmt-match_block_trailing_comma: true // rustfmt-trailing_comma: Always fn main() { -- cgit 1.4.1-3-g733a5 From c9ac3487595eb56339d57de33aa326ac9e762f9c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 2 Mar 2017 15:03:32 +1300 Subject: Fix failing test --- Cargo.lock | 99 ++++++++++++++++++++++++++-------------------- src/expr.rs | 3 +- tests/target/issue-1127.rs | 6 +-- 3 files changed, 61 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 7034d91d1df..64d07145a3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,18 +3,18 @@ name = "rustfmt" version = "0.7.1" dependencies = [ "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.56.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -24,15 +24,15 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -47,11 +47,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "env_logger" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -88,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "0.1.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", @@ -101,19 +101,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "0.1.80" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -141,20 +141,19 @@ dependencies = [ [[package]] name = "syntex_errors" -version = "0.56.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.56.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -162,16 +161,14 @@ dependencies = [ [[package]] name = "syntex_syntax" -version = "0.56.2" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -186,7 +183,7 @@ dependencies = [ [[package]] name = "thread-id" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -195,10 +192,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.2.7" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -219,9 +217,22 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unreachable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" -version = "0.1.3" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -245,33 +256,35 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2" +"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162" "checksum diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e48977eec6d3b7707462c2dc2e1363ad91b5dd822cf942537ccdc2085dc87587" "checksum either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2b503c86dad62aaf414ecf2b8c527439abedb3f8d812537f0b12bfd6f32a91" -"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" +"checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itertools 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c6946da472dbbcbd98c049050e8e587cc4ee26985992e582b1d74a35cb8a7020" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" +"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" "checksum same-file 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c722bde68d432ad7982a6431b13264cc558af1707c0f321820e238c5671856ea" "checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" -"checksum syntex_errors 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13596c6a30ecd9d73d5f03167b7cc98f1e3e65063b046ac10b411dc9b2a8c600" -"checksum syntex_pos 0.56.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d55810cf983ad75bcc52ec97a777b619b00d821219df7883d40f2aed7416966a" -"checksum syntex_syntax 0.56.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ca00794c3556cadbcec14036c8bce354d92de33bd5ffbbc5bc090a4c595b27dc" +"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" +"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" +"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" +"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" "checksum unicode-segmentation 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7baebdc1df1363fa66161fca2fe047e4f4209011cc7e045948298996afdf85df" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" +"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/expr.rs b/src/expr.rs index ceba598b8af..a64e1aafffd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1293,7 +1293,8 @@ impl Rewrite for ast::Arm { let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n", - _ => String::from(" ") + body_prefix + "\n", + _ if body_prefix.is_empty() => "\n".to_owned(), + _ => " ".to_owned() + body_prefix + "\n", }; if context.config.wrap_match_arms { diff --git a/tests/target/issue-1127.rs b/tests/target/issue-1127.rs index 3d133f4ce9c..afc79767cb7 100644 --- a/tests/target/issue-1127.rs +++ b/tests/target/issue-1127.rs @@ -15,11 +15,11 @@ enum TestEnum { fn main() { let var = TestEnum::AVeryVeryLongEnumName; let num = match var { - TestEnum::AVeryVeryLongEnumName => + TestEnum::AVeryVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::AnotherVeryLongEnumName => + TestEnum::AnotherVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::TheLastVeryLongEnumName => + TestEnum::TheLastVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), }; } -- cgit 1.4.1-3-g733a5 From 63114f3cace7d3866103975faef7bcb4c1e1f517 Mon Sep 17 00:00:00 2001 From: Andy Librian Date: Mon, 6 Mar 2017 01:50:04 +0700 Subject: added unit tests for Indent and Shape (#1353) --- src/lib.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cfad3dfdbbe..4c4c56bb2f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -655,3 +655,88 @@ pub fn run(input: Input, config: &Config) -> Summary { } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn indent_add_sub() { + let indent = Indent::new(4, 8) + Indent::new(8, 12); + assert_eq!(12, indent.block_indent); + assert_eq!(20, indent.alignment); + + let indent = indent - Indent::new(4, 4); + assert_eq!(8, indent.block_indent); + assert_eq!(16, indent.alignment); + } + + #[test] + fn indent_add_sub_alignment() { + let indent = Indent::new(4, 8) + 4; + assert_eq!(4, indent.block_indent); + assert_eq!(12, indent.alignment); + + let indent = indent - 4; + assert_eq!(4, indent.block_indent); + assert_eq!(8, indent.alignment); + } + + #[test] + fn indent_to_string_spaces() { + let config = Config::default(); + let indent = Indent::new(4, 8); + + // 12 spaces + assert_eq!(" ", indent.to_string(&config)); + } + + #[test] + fn indent_to_string_hard_tabs() { + let mut config = Config::default(); + config.hard_tabs = true; + let indent = Indent::new(8, 4); + + // 2 tabs + 4 spaces + assert_eq!("\t\t ", indent.to_string(&config)); + } + + #[test] + fn shape_visual_indent() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::indented(indent, &config); + let shape = shape.visual_indent(20); + + assert_eq!(config.max_width, shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(32, shape.indent.alignment); + assert_eq!(32, shape.offset); + } + + #[test] + fn shape_block_indent_without_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 0); + let shape = Shape::indented(indent, &config); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width, shape.width); + assert_eq!(24, shape.indent.block_indent); + assert_eq!(0, shape.indent.alignment); + assert_eq!(0, shape.offset); + } + + #[test] + fn shape_block_indent_with_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::indented(indent, &config); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width, shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } +} -- cgit 1.4.1-3-g733a5 From c7a33062e25e1d80545ae6094d3faa99348c79e1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 7 Mar 2017 09:34:28 +1300 Subject: Add a heuristic for maximum number of elements in a single-line chain And turn the source hints option to false by default. This should make formatting more deterministic. --- src/chains.rs | 5 ++++- src/config.rs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index e9bd220158f..a2c69b2cb42 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -162,7 +162,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); - let veto_single_line = if context.config.take_source_hints && subexpr_list.len() > 1 { + let veto_single_line = if subexpr_list.len() > context.config.chain_one_line_max - 1 { + // -1 above because subexpr_list does not include the parent. + true + } else if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); diff --git a/src/config.rs b/src/config.rs index 57b8ba190f8..8e0a839d29e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -378,6 +378,7 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain"; + chain_one_line_max: usize, 4, "Maximum number of elements in a chain to fit on a single line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imported_names: bool, false, "Reorder lists of names in import statements alphabetically"; @@ -386,7 +387,7 @@ create_config! { if-else expressions."; format_strings: bool, false, "Format string literals where necessary"; force_format_strings: bool, false, "Always format string literals"; - take_source_hints: bool, true, "Retain some formatting characteristics from the source code"; + take_source_hints: bool, false, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; normalize_comments: bool, false, "Convert /* */ comments to // comments where possible"; -- cgit 1.4.1-3-g733a5 From 33b83ae7dfb7f20825f666ecc78d5f7ad97597b1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 7 Mar 2017 09:40:08 +1300 Subject: Formatting fallout Also fixes a minor bug when we break a line after `if` and used to leave a trailing space --- src/bin/cargo-fmt.rs | 15 +++++++-- src/bin/rustfmt.rs | 10 ++++-- src/chains.rs | 17 ++++++---- src/codemap.rs | 5 ++- src/comment.rs | 10 ++++-- src/expr.rs | 95 ++++++++++++++++++++++++++++------------------------ src/imports.rs | 32 ++++++++++++++---- src/items.rs | 89 ++++++++++++++++++++++++------------------------ src/lib.rs | 5 ++- src/lists.rs | 16 +++++---- src/missed_spans.rs | 22 +++++++----- src/patterns.rs | 20 +++++------ src/types.rs | 39 +++++++++++---------- src/utils.rs | 6 +++- tests/system.rs | 8 ++--- 15 files changed, 225 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index cf476edf7ca..ceb6af93825 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -147,7 +147,10 @@ fn get_targets() -> Result, std::io::Error> { // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); let json = Json::from_str(data).unwrap(); - let jtargets = json.find("targets").unwrap().as_array().unwrap(); + let jtargets = json.find("targets") + .unwrap() + .as_array() + .unwrap(); for jtarget in jtargets { targets.push(target_from_json(jtarget)); } @@ -162,8 +165,14 @@ fn get_targets() -> Result, std::io::Error> { fn target_from_json(jtarget: &Json) -> Target { let jtarget = jtarget.as_object().unwrap(); - let path = PathBuf::from(jtarget.get("src_path").unwrap().as_string().unwrap()); - let kinds = jtarget.get("kind").unwrap().as_array().unwrap(); + let path = PathBuf::from(jtarget.get("src_path") + .unwrap() + .as_string() + .unwrap()); + let kinds = jtarget.get("kind") + .unwrap() + .as_array() + .unwrap(); let kind = match kinds[0].as_string().unwrap() { "bin" => TargetKind::Bin, "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 52d1a8f9f15..69a18d14cb5 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -223,7 +223,10 @@ fn execute(opts: &Options) -> FmtResult { let options = try!(CliOptions::from_matches(&matches)); // Add any additional files that were specified via `--file-lines`. - files.extend(options.file_lines.files().cloned().map(PathBuf::from)); + files.extend(options.file_lines + .files() + .cloned() + .map(PathBuf::from)); let mut config = Config::default(); let mut path = None; @@ -354,7 +357,10 @@ fn determine_operation(matches: &Matches) -> FmtResult { } // We append files from `--file-lines` later in `execute()`. - let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); + let files: Vec<_> = matches.free + .iter() + .map(PathBuf::from) + .collect(); Ok(Operation::Format { files: files, diff --git a/src/chains.rs b/src/chains.rs index a2c69b2cb42..4918ebd3cac 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -158,9 +158,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .collect::>>()); // Total of all items excluding the last. - let almost_total = rewrites[..rewrites.len() - 1] - .iter() - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); + let almost_total = rewrites[..rewrites.len() - 1].iter().fold(0, |a, b| { + a + first_line_width(b) + }) + parent_rewrite.len(); let veto_single_line = if subexpr_list.len() > context.config.chain_one_line_max - 1 { // -1 above because subexpr_list does not include the parent. @@ -425,9 +425,8 @@ fn rewrite_method_call(method_name: ast::Ident, let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { - let type_list: Vec<_> = try_opt!(types.iter() - .map(|ty| ty.rewrite(context, shape)) - .collect()); + let type_list: Vec<_> = + try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) @@ -435,7 +434,11 @@ fn rewrite_method_call(method_name: ast::Ident, format!("::<{}>", type_list.join(", ")) }; - (types.last().unwrap().span.hi, type_str) + (types.last() + .unwrap() + .span + .hi, + type_str) }; let callee_str = format!(".{}{}", method_name, type_str); diff --git a/src/codemap.rs b/src/codemap.rs index d04169c936e..602ab5c98be 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -26,7 +26,10 @@ pub struct LineRange { impl LineRange { pub fn file_name(&self) -> &str { - self.file.as_ref().name.as_str() + self.file + .as_ref() + .name + .as_str() } } diff --git a/src/comment.rs b/src/comment.rs index 3f85dd27ac9..e4f9db9f158 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -96,7 +96,10 @@ pub fn rewrite_comment(orig: &str, config: config, }; - let line_breaks = orig.trim_right().chars().filter(|&c| c == '\n').count(); + let line_breaks = orig.trim_right() + .chars() + .filter(|&c| c == '\n') + .count(); let lines = orig.lines() .enumerate() .map(|(i, mut line)| { @@ -594,8 +597,9 @@ fn changed_comment_content(orig: &str, new: &str) -> bool { // Cannot write this as a fn since we cannot return types containing closures let code_comment_content = |code| { let slices = UngroupedCommentCodeSlices::new(code); - slices.filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) - .flat_map(|(_, _, s)| CommentReducer::new(s)) + slices.filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment).flat_map(|(_, _, s)| { + CommentReducer::new(s) + }) }; let res = code_comment_content(orig).ne(code_comment_content(new)); debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", diff --git a/src/expr.rs b/src/expr.rs index a64e1aafffd..7f5d88d3f68 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -300,10 +300,9 @@ pub fn rewrite_pair(lhs: &LHS, // Re-evaluate the rhs because we have more space now: let infix = infix.trim_right(); - let lhs_budget = try_opt!(context.config - .max_width - .checked_sub(shape.used_width() + prefix.len() + - infix.len())); + let lhs_budget = try_opt!(context.config.max_width.checked_sub(shape.used_width() + + prefix.len() + + infix.len())); let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())) .visual_indent(prefix.len()); @@ -893,15 +892,19 @@ impl<'a> Rewrite for ControlFlow<'a> { " " }; - let mut result = - format!("{}{}{}{}{}{}", - label_string, - self.keyword, - between_kwd_cond_comment.as_ref() - .map_or(if pat_expr_string.is_empty() { "" } else { " " }, |s| &**s), - pat_expr_string, - after_cond_comment.as_ref().map_or(block_sep, |s| &**s), - block_str); + let mut result = format!("{}{}{}{}{}{}", + label_string, + self.keyword, + between_kwd_cond_comment.as_ref().map_or(if + pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { + "" + } else { + " " + }, + |s| &**s), + pat_expr_string, + after_cond_comment.as_ref().map_or(block_sep, |s| &**s), + block_str); if let Some(else_block) = self.else_block { // Since this is an else block, we should not indent for the assignment preceding @@ -944,15 +947,15 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_else_block = mk_sp(self.block.span.hi, - context.codemap - .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else")); + context.codemap.span_before(mk_sp(self.block.span.hi, else_block.span.lo), + "else")); let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); - let after_else = - mk_sp(context.codemap - .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), - else_block.span.lo); + let after_else = mk_sp(context.codemap.span_after(mk_sp(self.block.span.hi, + else_block.span.lo), + "else"), + else_block.span.lo); let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style { @@ -966,8 +969,7 @@ impl<'a> Rewrite for ControlFlow<'a> { }; try_opt!(write!(&mut result, "{}else{}", - between_kwd_else_block_comment.as_ref() - .map_or(between_sep, |s| &**s), + between_kwd_else_block_comment.as_ref().map_or(between_sep, |s| &**s), after_else_comment.as_ref().map_or(after_sep, |s| &**s)) .ok()); result.push_str(&try_opt!(rewrite)); @@ -1094,8 +1096,8 @@ fn rewrite_match(context: &RewriteContext, let arm_shape = shape.block_indent(context.config.tab_spaces); let arm_indent_str = arm_shape.indent.to_string(context.config); - let open_brace_pos = context.codemap - .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); + let open_brace_pos = context.codemap.span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), + "{"); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. @@ -1245,8 +1247,11 @@ impl Rewrite for ast::Arm { // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() if shape.width > pat_width + comma.len() + 4 { - let arm_shape = - shape.shrink_left(pat_width + 4).unwrap().sub_width(comma.len()).unwrap().block(); + let arm_shape = shape.shrink_left(pat_width + 4) + .unwrap() + .sub_width(comma.len()) + .unwrap() + .block(); let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), arm_shape.width); let is_block = if let ast::ExprKind::Block(..) = body.node { true @@ -1338,7 +1343,10 @@ fn rewrite_guard(context: &RewriteContext, // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; if overhead < shape.width { - let cond_shape = shape.shrink_left(pattern_width + 4).unwrap().sub_width(5).unwrap(); + let cond_shape = shape.shrink_left(pattern_width + 4) + .unwrap() + .sub_width(5) + .unwrap(); let cond_str = guard.rewrite(context, cond_shape); if let Some(cond_str) = cond_str { return Some(format!(" if {}", cond_str)); @@ -1469,7 +1477,10 @@ fn string_requires_rewrite(context: &RewriteContext, string: &str, shape: Shape) -> bool { - if context.codemap.lookup_char_pos(span.lo).col.0 != shape.indent.width() { + if context.codemap + .lookup_char_pos(span.lo) + .col + .0 != shape.indent.width() { return true; } @@ -1584,10 +1595,10 @@ fn rewrite_call_inner(context: &RewriteContext, } } - let tactic = definitive_tactic(&item_vec, - ListTactic::LimitedHorizontalVertical(context.config - .fn_call_width), - remaining_width); + let tactic = + definitive_tactic(&item_vec, + ListTactic::LimitedHorizontalVertical(context.config.fn_call_width), + remaining_width); // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. @@ -1709,8 +1720,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, |item| match *item { StructLitField::Regular(field) => field.span.lo, StructLitField::Base(expr) => { - let last_field_hi = fields.last() - .map_or(span.lo, |field| field.span.hi); + let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) @@ -1728,8 +1738,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(context, try_opt!(v_shape.shrink_left(2))) - .map(|s| format!("..{}", s)) + expr.rewrite(context, try_opt!(v_shape.shrink_left(2))).map(|s| format!("..{}", s)) } } }, @@ -1823,12 +1832,11 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Some(e) => Some(format!("{}{}{}", name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); - let expr = field.expr - .rewrite(context, - Shape::legacy(try_opt!(context.config + let expr = field.expr.rewrite(context, + Shape::legacy(try_opt!(context.config .max_width .checked_sub(expr_offset.width())), - expr_offset)); + expr_offset)); expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) } } @@ -1894,11 +1902,10 @@ pub fn rewrite_unary_suffix(context: &RewriteContext, rewrite: &R, shape: Shape) -> Option { - rewrite.rewrite(context, try_opt!(shape.sub_width(suffix.len()))) - .map(|mut r| { - r.push_str(suffix); - r - }) + rewrite.rewrite(context, try_opt!(shape.sub_width(suffix.len()))).map(|mut r| { + r.push_str(suffix); + r + }) } fn rewrite_unary_op(context: &RewriteContext, diff --git a/src/imports.rs b/src/imports.rs index 0b432d072af..65d8366ea22 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -29,7 +29,10 @@ fn path_of(a: &ast::ViewPath_) -> &ast::Path { } fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { - a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) + a.identifier + .name + .as_str() + .cmp(&b.identifier.name.as_str()) } fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { @@ -43,8 +46,14 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { } fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Ordering { - let a_name_str = &*a.node.name.name.as_str(); - let b_name_str = &*b.node.name.name.as_str(); + let a_name_str = &*a.node + .name + .name + .as_str(); + let b_name_str = &*b.node + .name + .name + .as_str(); let name_ordering = if a_name_str == "self" { if b_name_str == "self" { Ordering::Equal @@ -139,7 +148,11 @@ impl Rewrite for ast::ViewPath { // 4 = " as ".len() let budget = try_opt!(shape.width.checked_sub(ident_str.len() + 4)); - let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && + let path_str = if path.segments + .last() + .unwrap() + .identifier + .to_string() == "self" && path.segments.len() > 1 { let path = &ast::Path { span: path.span.clone(), @@ -158,7 +171,10 @@ impl Rewrite for ast::ViewPath { Shape::legacy(budget, shape.indent))) }; - Some(if path.segments.last().unwrap().identifier == ident { + Some(if path.segments + .last() + .unwrap() + .identifier == ident { path_str } else { format!("{} as {}", path_str, ident_str) @@ -175,7 +191,11 @@ impl<'a> FmtVisitor<'a> { let pos_before_first_use_item = use_items.first() .map(|p_i| { cmp::max(self.last_pos, - p_i.attrs.iter().map(|attr| attr.span.lo).min().unwrap_or(p_i.span.lo)) + p_i.attrs + .iter() + .map(|attr| attr.span.lo) + .min() + .unwrap_or(p_i.span.lo)) }) .unwrap_or(self.last_pos); // Construct a list of pairs, each containing a `use` item and the start of span before diff --git a/src/items.rs b/src/items.rs index 60a06f3dc5f..91fd91ef958 100644 --- a/src/items.rs +++ b/src/items.rs @@ -40,9 +40,8 @@ impl Rewrite for ast::Local { // 1 = ; let pattern_width = try_opt!(shape.width.checked_sub(pattern_offset.width() + 1)); - let pat_str = try_opt!(self.pat - .rewrite(&context, - Shape::legacy(pattern_width, pattern_offset))); + let pat_str = try_opt!(self.pat.rewrite(&context, + Shape::legacy(pattern_width, pattern_offset))); result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -106,7 +105,10 @@ impl<'a> Item<'a> { keyword: "", abi: abi, vis: None, - body: fm.items.iter().map(|i| BodyElement::ForeignItem(i)).collect(), + body: fm.items + .iter() + .map(|i| BodyElement::ForeignItem(i)) + .collect(), span: span, } } @@ -455,12 +457,10 @@ impl<'a> FmtVisitor<'a> { } let indent = self.block_indent; - let mut result = try_opt!(field.node - .attrs - .rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - indent.width(), - indent))); + let mut result = try_opt!(field.node.attrs.rewrite(&self.get_context(), + Shape::legacy(self.config.max_width - + indent.width(), + indent))); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -784,9 +784,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) Density::Tall }; - let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -1000,9 +998,8 @@ fn format_tuple_struct(context: &RewriteContext, mk_sp(span.lo, body_lo))); result.push_str(&generics_str); - let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + let where_budget = + try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -1093,9 +1090,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&generics_str); - let where_budget = try_opt!(context.config - .max_width - .checked_sub(last_line_width(&result))); + let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, @@ -1117,8 +1112,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, .unwrap_or(0); let type_indent = indent + line_width; // Try to fit the type on the same line - let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)) - .or_else(|| { + let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)).or_else(|| { // The line was too short, try to put the type on the next line // Remove the space after '=' @@ -1126,9 +1120,8 @@ pub fn rewrite_type_alias(context: &RewriteContext, let type_indent = indent.block_indent(context.config); result.push('\n'); result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context.config - .max_width - .checked_sub(type_indent.width() + ";".len())); + let budget = try_opt!(context.config.max_width.checked_sub(type_indent.width() + + ";".len())); ty.rewrite(context, Shape::legacy(budget, type_indent)) })); result.push_str(&ty_str); @@ -1158,11 +1151,10 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); - let mut attr_str = try_opt!(self.attrs - .rewrite(context, - Shape::legacy(context.config.max_width - - shape.indent.width(), - shape.indent))); + let mut attr_str = try_opt!(self.attrs.rewrite(context, + Shape::legacy(context.config.max_width - + shape.indent.width(), + shape.indent))); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&shape.indent.to_string(context.config)); @@ -1289,8 +1281,9 @@ impl Rewrite for ast::FunctionRetTy { ast::FunctionRetTy::Default(_) => Some(String::new()), ast::FunctionRetTy::Ty(ref ty) => { let inner_width = try_opt!(shape.width.checked_sub(3)); - ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) - .map(|r| format!("-> {}", r)) + ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)).map(|r| { + format!("-> {}", r) + }) } } } @@ -1299,9 +1292,8 @@ impl Rewrite for ast::FunctionRetTy { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!(self.pat - .rewrite(context, - Shape::legacy(shape.width, shape.indent))); + let mut result = try_opt!(self.pat.rewrite(context, + Shape::legacy(shape.width, shape.indent))); if self.ty.node != ast::TyKind::Infer { if context.config.space_before_type_annotation { @@ -1478,11 +1470,10 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that if the width and indent really matter, we'll re-layout the // return type later anyway. - let ret_str = try_opt!(fd.output - .rewrite(&context, - Shape::legacy(context.config.max_width - - indent.width(), - indent))); + let ret_str = try_opt!(fd.output.rewrite(&context, + Shape::legacy(context.config.max_width - + indent.width(), + indent))); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -1528,9 +1519,7 @@ fn rewrite_fn_base(context: &RewriteContext, } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics.ty_params - .last() - .map_or(span.lo, |tp| end_typaram(tp)); + let args_start = generics.ty_params.last().map_or(span.lo, |tp| end_typaram(tp)); let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("), span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, @@ -1731,7 +1720,12 @@ fn rewrite_args(context: &RewriteContext, } let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); + let variadic_span = mk_sp(args.last() + .unwrap() + .ty + .span + .hi, + span.hi); let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { @@ -1826,7 +1820,10 @@ fn compute_budgets_for_args(context: &RewriteContext, if !newline_brace { used_space += 2; } - let one_line_budget = context.config.max_width.checked_sub(used_space).unwrap_or(0); + let one_line_budget = context.config + .max_width + .checked_sub(used_space) + .unwrap_or(0); if one_line_budget > 0 { // 4 = "() {".len() @@ -1884,8 +1881,8 @@ fn rewrite_generics(context: &RewriteContext, // Strings for the generics. let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, Shape::legacy(h_budget, offset))); - let ty_strs = tys.iter() - .map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); + let ty_strs = + tys.iter().map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { diff --git a/src/lib.rs b/src/lib.rs index 4c4c56bb2f3..f37466bebfc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -394,7 +394,10 @@ impl FormatReport { } pub fn warning_count(&self) -> usize { - self.file_error_map.iter().map(|(_, errors)| errors.len()).fold(0, |acc, x| acc + x) + self.file_error_map + .iter() + .map(|(_, errors)| errors.len()) + .fold(0, |acc, x| acc + x) } pub fn has_warnings(&self) -> bool { diff --git a/src/lists.rs b/src/lists.rs index 8ba54ab4ccb..5c25c8b1cea 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -147,9 +147,8 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De where I: IntoIterator + Clone, T: AsRef { - let pre_line_comments = items.clone() - .into_iter() - .any(|item| item.as_ref().has_line_pre_comment()); + let pre_line_comments = + items.clone().into_iter().any(|item| item.as_ref().has_line_pre_comment()); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, @@ -275,7 +274,10 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { // 1 = space between item and comment. - let width = formatting.shape.width.checked_sub(item_last_line_width + 1).unwrap_or(1); + let width = formatting.shape + .width + .checked_sub(item_last_line_width + 1) + .unwrap_or(1); let mut offset = formatting.shape.indent; offset.alignment += item_last_line_width + 1; let comment = item.post_comment.as_ref().unwrap(); @@ -475,9 +477,9 @@ fn calculate_width(items: I) -> (usize, usize) where I: IntoIterator, T: AsRef { - items.into_iter() - .map(|item| total_item_width(item.as_ref())) - .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) + items.into_iter().map(|item| total_item_width(item.as_ref())).fold((0, 0), |acc, l| { + (acc.0 + 1, acc.1 + l) + }) } fn total_item_width(item: &ListItem) -> usize { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 61efbddeb1c..767a81120e5 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -75,12 +75,19 @@ impl<'a> FmtVisitor<'a> { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment // follows code on the same line, we won't touch it. - let big_span_lo = self.codemap.lookup_char_pos(span.lo).file.start_pos; + let big_span_lo = self.codemap + .lookup_char_pos(span.lo) + .file + .start_pos; let local_begin = self.codemap.lookup_byte_offset(big_span_lo); let local_end = self.codemap.lookup_byte_offset(span.hi); let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; + let big_snippet = &local_begin.fm + .src + .as_ref() + .unwrap() + [start_index..end_index]; let big_diff = (span.lo - big_span_lo).to_usize(); let snippet = self.snippet(span); @@ -105,9 +112,7 @@ impl<'a> FmtVisitor<'a> { let mut rewrite_next_comment = true; fn replace_chars(string: &str) -> String { - string.chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect() + string.chars().map(|ch| if ch.is_whitespace() { ch } else { 'X' }).collect() } let replaced = match self.config.write_mode { @@ -154,9 +159,10 @@ impl<'a> FmtVisitor<'a> { if let Some('/') = subslice.chars().skip(1).next() { // check that there are no contained block comments - if !subslice.split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() > 2 && &s[0..2] == "/*") { + if !subslice.split('\n').map(|s| s.trim_left()).any(|s| { + s.len() > 2 && + &s[0..2] == "/*" + }) { // Add a newline after line comments self.buffer.push_str("\n"); } diff --git a/src/patterns.rs b/src/patterns.rs index cbaa29a4569..601506b4954 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -36,10 +36,10 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!(shape.width - .checked_sub(prefix.len() + mut_infix.len() + - id_str.len() + - 3)); + let width = try_opt!(shape.width.checked_sub(prefix.len() + + mut_infix.len() + + id_str.len() + + 3)); format!(" @ {}", try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) } @@ -90,15 +90,15 @@ impl Rewrite for Pat { PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = - slice_pat.as_ref() - .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); + let slice_pat = slice_pat.as_ref().map(|p| { + Some(format!("{}..", + try_opt!(p.rewrite(context, shape)))) + }); let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. - let pats: Option> = prefix.chain(slice_pat.into_iter()) - .chain(suffix) - .collect(); + let pats: Option> = + prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); // Check that all the rewrites succeeded, and if not return None. let pats = try_opt!(pats); diff --git a/src/types.rs b/src/types.rs index 7f6e8e68576..39f9d40a627 100644 --- a/src/types.rs +++ b/src/types.rs @@ -165,10 +165,10 @@ impl<'a> Rewrite for SegmentParam<'a> { TypeDensity::Compressed => format!("{}=", binding.ident), }; let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = - try_opt!(binding.ty - .rewrite(context, - Shape::legacy(budget, shape.indent + result.len()))); + let rewrite = try_opt!(binding.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + + result.len()))); result.push_str(&rewrite); Some(result) } @@ -208,7 +208,10 @@ fn rewrite_segment(path_context: PathContext, .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); + let next_span_lo = param_list.last() + .unwrap() + .get_span() + .hi + BytePos(1); let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); let separator = if path_context == PathContext::Expr { "::" @@ -445,9 +448,8 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, if bounds.len() == 0 { Some(result) } else { - let appendix: Vec<_> = try_opt!(bounds.into_iter() - .map(|b| b.rewrite(context, shape)) - .collect()); + let appendix: Vec<_> = + try_opt!(bounds.into_iter().map(|b| b.rewrite(context, shape)).collect()); let colon = type_bound_colon(context); let result = format!("{}{}{}", result, colon, appendix.join(" + ")); wrap_str(result, context.config.max_width, shape) @@ -485,9 +487,7 @@ impl Rewrite for ast::TyParamBounds { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; - let strs: Vec<_> = try_opt!(self.iter() - .map(|b| b.rewrite(context, shape)) - .collect()); + let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect()); wrap_str(strs.join(joiner), context.config.max_width, shape) } } @@ -543,10 +543,10 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref - .rewrite(context, - Shape::legacy(max_path_width, - shape.indent + extra_offset))); + let path_str = try_opt!(self.trait_ref.rewrite(context, + Shape::legacy(max_path_width, + shape.indent + + extra_offset))); Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { format!("for< {} > {}", lifetime_str, path_str) @@ -592,11 +592,10 @@ impl Rewrite for ast::Ty { format!("&{} {}{}", lt_str, mut_str, - try_opt!(mt.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + 2 + mut_len + - lt_len)))) + try_opt!(mt.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + 2 + mut_len + + lt_len)))) } None => { let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); diff --git a/src/utils.rs b/src/utils.rs index da48831e672..999e1192b5d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -278,7 +278,11 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option shape.indent.width() + shape.width { + if snippet.lines() + .rev() + .next() + .unwrap() + .len() > shape.indent.width() + shape.width { return None; } } diff --git a/tests/system.rs b/tests/system.rs index 257b1ec46bf..2f5258df235 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -84,8 +84,7 @@ fn assert_output(source: &str, expected_filename: &str) { let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); let mut expected_text = String::new(); - expected_file.read_to_string(&mut expected_text) - .expect("Failed reading target"); + expected_file.read_to_string(&mut expected_text).expect("Failed reading target"); let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); if compare.len() > 0 { @@ -101,9 +100,8 @@ fn assert_output(source: &str, expected_filename: &str) { #[test] fn idempotence_tests() { // Get all files in the tests/target directory. - let files = fs::read_dir("tests/target") - .expect("Couldn't read target dir") - .map(get_path_string); + let files = + fs::read_dir("tests/target").expect("Couldn't read target dir").map(get_path_string); let (_reports, count, fails) = check_files(files); // Display results. -- cgit 1.4.1-3-g733a5 From 981b031c9fe695b169be79a7f53402d84f35ebee Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 7 Mar 2017 14:30:01 +1300 Subject: Treat new blocks like existing ones in closures Fixes #1355 --- src/expr.rs | 2 +- tests/target/expr.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7f5d88d3f68..e540965fd8c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -494,7 +494,7 @@ fn rewrite_closure(capture: ast::CaptureBy, rules: ast::BlockCheckMode::Default, span: body.span, }; - return rewrite_closure_block(&block, prefix, context, body_shape.block()); + return rewrite_closure_block(&block, prefix, context, body_shape); fn rewrite_closure_expr(expr: &ast::Expr, prefix: &str, diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 2d9f0e6ad10..d05870086e3 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -292,6 +292,6 @@ fn issue1106() { } for entry in WalkDir::new(path).into_iter().filter_entry(|entry| { - exclusions.filter_entry(entry) - }) {} + exclusions.filter_entry(entry) + }) {} } -- cgit 1.4.1-3-g733a5 From e5638e0cb5d967e18ffaa848797168e03bdc260a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 7 Mar 2017 14:53:10 +1300 Subject: More space for qself paths Fixes #1349 --- src/types.rs | 2 -- tests/target/issue-811.rs | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 39f9d40a627..0162ac851f3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -87,8 +87,6 @@ pub fn rewrite_path(context: &RewriteContext, span_lo = qself.ty.span.hi + BytePos(1); } - let extra_offset = extra_offset(&result, shape); - let shape = try_opt!(shape.shrink_left(extra_offset)); rewrite_path_segments(path_context, result, path.segments.iter().skip(skip_count), diff --git a/tests/target/issue-811.rs b/tests/target/issue-811.rs index 2b58c06941d..b7a89b5d0f9 100644 --- a/tests/target/issue-811.rs +++ b/tests/target/issue-811.rs @@ -7,8 +7,7 @@ trait BarTrait: Sized { fn foo(); } -type Foo = - <>::Bar as BarTrait>::Baz; +type Foo = <>::Bar as BarTrait>::Baz; type Bar = >::Baz; fn some_func, U>() { -- cgit 1.4.1-3-g733a5 From e7489356c6e9d83a6978a837d5309b4015f88519 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 8 Mar 2017 10:10:56 +1300 Subject: Format glob imports Fixes #1356 --- src/imports.rs | 53 ++++++++++++++++++++++++++----------------------- tests/source/imports.rs | 4 ++++ tests/target/imports.rs | 4 ++++ 3 files changed, 36 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 65d8366ea22..cafba0bb2c5 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -132,6 +132,26 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { // TODO (some day) remove unused imports, expand globs, compress many single // imports into a list import. +fn rewrite_view_path_prefix(path: &ast::Path, + context: &RewriteContext, + shape: Shape) + -> Option { + let path_str = if path.segments + .last() + .unwrap() + .identifier + .to_string() == "self" && path.segments.len() > 1 { + let path = &ast::Path { + span: path.span.clone(), + segments: path.segments[..path.segments.len() - 1].to_owned(), + }; + try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)) + } else { + try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)) + }; + Some(path_str) +} + impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { @@ -142,34 +162,17 @@ impl Rewrite for ast::ViewPath { ast::ViewPath_::ViewPathList(ref path, ref path_list) => { rewrite_use_list(shape, path, path_list, self.span, context) } - ast::ViewPath_::ViewPathGlob(_) => None, + ast::ViewPath_::ViewPathGlob(ref path) => { + // 4 = "::*".len() + let prefix_shape = try_opt!(shape.sub_width(3)); + let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); + Some(format!("{}::*", path_str)) + } ast::ViewPath_::ViewPathSimple(ident, ref path) => { let ident_str = ident.to_string(); // 4 = " as ".len() - let budget = try_opt!(shape.width.checked_sub(ident_str.len() + 4)); - - let path_str = if path.segments - .last() - .unwrap() - .identifier - .to_string() == "self" && - path.segments.len() > 1 { - let path = &ast::Path { - span: path.span.clone(), - segments: path.segments[..path.segments.len() - 1].to_owned(), - }; - try_opt!(rewrite_path(context, - PathContext::Import, - None, - &path, - Shape::legacy(budget, shape.indent))) - } else { - try_opt!(rewrite_path(context, - PathContext::Import, - None, - path, - Shape::legacy(budget, shape.indent))) - }; + let prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4)); + let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); Some(if path.segments .last() diff --git a/tests/source/imports.rs b/tests/source/imports.rs index 90cb78c2d1f..91016f8cb70 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -64,3 +64,7 @@ use ::foo::{Bar}; use ::foo::{Bar, Baz}; use ::{Foo}; use ::{Bar, Baz}; + +// spaces used to cause glob imports to disappear (#1356) +use super:: * ; +use foo::issue_1356:: * ; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 570b5225da7..1f4a692d0cc 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -59,3 +59,7 @@ use foo::Bar; use foo::{Bar, Baz}; use Foo; use {Bar, Baz}; + +// spaces used to cause glob imports to disappear (#1356) +use super::*; +use foo::issue_1356::*; -- cgit 1.4.1-3-g733a5 From b820d50ec06487eb5490b4a0048fdae76de11db8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 9 Mar 2017 13:16:14 +1300 Subject: Add style RFC conformant rustfmt toml Add a new `where` clause option, as yet unused. --- rfc-rustfmt.toml | 2 ++ src/config.rs | 6 ++++++ 2 files changed, 8 insertions(+) create mode 100644 rfc-rustfmt.toml (limited to 'src') diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml new file mode 100644 index 00000000000..7b6d3f0b3c4 --- /dev/null +++ b/rfc-rustfmt.toml @@ -0,0 +1,2 @@ +fn_args_layout = "Block" +where_style = "Rfc" diff --git a/src/config.rs b/src/config.rs index 8e0a839d29e..5cd28c5a492 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,6 +25,11 @@ macro_rules! configuration_option_enum{ } } +configuration_option_enum! { Style: + Rfc, // Follow the style RFCs style. + Default, // Follow the traditional Rustfmt style. +} + configuration_option_enum! { NewlineStyle: Windows, // \r\n Unix, // \n @@ -361,6 +366,7 @@ create_config! { fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; + where_style: Style, Style::Default, "Overall strategy for where clauses"; // Should we at least try to put the where clause on the same line as the rest of the // function decl? where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; -- cgit 1.4.1-3-g733a5 From 6025492245ec0028b09477261418176a197b3ebc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 9 Mar 2017 14:21:20 +1300 Subject: Implement where_style Rfc --- src/items.rs | 99 ++++++++++++++++++++++++++++++++++++---- tests/source/where-clause-rfc.rs | 44 ++++++++++++++++++ tests/target/where-clause-rfc.rs | 99 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 10 deletions(-) create mode 100644 tests/source/where-clause-rfc.rs create mode 100644 tests/target/where-clause-rfc.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 91fd91ef958..ea8ac6687a6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -20,7 +20,7 @@ use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annota use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle}; +use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle, Style}; use itertools::Itertools; use syntax::{ast, abi, codemap, ptr, symbol}; @@ -520,13 +520,13 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config, context.config.item_brace_style, Shape::legacy(where_budget, offset.block_only()), context.config.where_density, "{", false, + false, None)); if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { @@ -787,13 +787,13 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config, context.config.item_brace_style, Shape::legacy(where_budget, offset.block_only()), where_density, "{", !has_body, + false, None)); // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -1002,12 +1002,12 @@ fn format_tuple_struct(context: &RewriteContext, try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config, context.config.item_brace_style, Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", true, + false, None)) } None => "".to_owned(), @@ -1093,12 +1093,12 @@ pub fn rewrite_type_alias(context: &RewriteContext, let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config, context.config.item_brace_style, Shape::legacy(where_budget, indent), context.config.where_density, "=", true, + false, Some(span.hi))); result.push_str(&where_clause_str); result.push_str(" = "); @@ -1645,12 +1645,12 @@ fn rewrite_fn_base(context: &RewriteContext, let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, - context.config, context.config.fn_brace_style, Shape::legacy(where_budget, indent), where_density, "{", !has_body, + put_args_in_block && ret_str.is_empty(), Some(span.hi))); if last_line_width(&result) + where_clause_str.len() > context.config.max_width && @@ -1935,28 +1935,107 @@ fn rewrite_trait_bounds(context: &RewriteContext, Some(result) } +// fn reflow_list_node_with_rule( +// &self, +// node: &CompoundNode, +// rule: &Rule, +// args: &[Arg], +// shape: &Shape +// ) -> Result +// where +// T: Foo, +// { + + +fn rewrite_where_clause_rfc_style(context: &RewriteContext, + where_clause: &ast::WhereClause, + shape: Shape, + terminator: &str, + suppress_comma: bool, + // where clause can be kept on the current line. + snuggle: bool, + span_end: Option) + -> Option { + let block_shape = shape.block(); + + let starting_newline = if snuggle { + " ".to_owned() + } else { + "\n".to_owned() + &block_shape.indent.to_string(context.config) + }; + + let clause_shape = block_shape.block_indent(context.config.tab_spaces); + // each clause on one line, trailing comma (except if suppress_comma) + let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; + let span_end = span_end.unwrap_or(end_of_preds); + let items = itemize_list(context.codemap, + where_clause.predicates.iter(), + terminator, + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + |pred| pred.rewrite(context, clause_shape), + span_start, + span_end); + let comma_tactic = if suppress_comma { + SeparatorTactic::Never + } else { + SeparatorTactic::Always + }; + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: comma_tactic, + shape: clause_shape, + ends_with_newline: true, + config: context.config, + }; + let preds_str = try_opt!(write_list(items, &fmt)); + + Some(format!("{}where\n{}{}", + starting_newline, + clause_shape.indent.to_string(context.config), + preds_str)) +} + fn rewrite_where_clause(context: &RewriteContext, where_clause: &ast::WhereClause, - config: &Config, brace_style: BraceStyle, shape: Shape, density: Density, terminator: &str, suppress_comma: bool, + snuggle: bool, span_end: Option) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); } + if context.config.where_style == Style::Rfc { + return rewrite_where_clause_rfc_style(context, + where_clause, + shape, + terminator, + suppress_comma, + snuggle, + span_end); + } + let extra_indent = match context.config.where_indent { BlockIndentStyle::Inherit => Indent::empty(), - BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => Indent::new(config.tab_spaces, 0), + BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => { + Indent::new(context.config.tab_spaces, 0) + } }; let offset = match context.config.where_pred_indent { BlockIndentStyle::Inherit => shape.indent + extra_indent, - BlockIndentStyle::Tabbed => shape.indent + extra_indent.block_indent(config), + BlockIndentStyle::Tabbed => shape.indent + extra_indent.block_indent(context.config), // 6 = "where ".len() BlockIndentStyle::Visual => shape.indent + extra_indent + 6, }; @@ -2046,13 +2125,13 @@ fn format_generics(context: &RewriteContext, let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config, brace_style, Shape::legacy(budget, offset.block_only()), Density::Tall, terminator, false, + false, Some(span.hi))); result.push_str(&where_clause_str); if !force_same_line_brace && diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs new file mode 100644 index 00000000000..d8a014c4a91 --- /dev/null +++ b/tests/source/where-clause-rfc.rs @@ -0,0 +1,44 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_style: Rfc + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; + +struct Exactly100CharsToSemicolon + (LongLongTypename, i32, i32) + where A: LongTrait1234; + +struct AlwaysOnNextLine where A: LongTrait { + x: i32 +} diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs new file mode 100644 index 00000000000..fd912e794cc --- /dev/null +++ b/tests/target/where-clause-rfc.rs @@ -0,0 +1,99 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_style: Rfc + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) +where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) +where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape +) where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape +) where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape +) -> Option +where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape +) -> Option +where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType +where + F: FnMut(Self::Item) + -> bool +{ +} + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) +where + A: LongTrait; + +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) +where + A: LongTrait1234; + +struct AlwaysOnNextLine +where + A: LongTrait, +{ + x: i32, +} -- cgit 1.4.1-3-g733a5 From d107ca12b83b679ed7aab54a72fcd0d01b511ed8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 9 Mar 2017 14:47:29 +1300 Subject: Use trailing commas if block formatting fn args Fixes #1330 --- src/items.rs | 10 +++++----- tests/target/fn-custom-6.rs | 20 ++++++++++---------- tests/target/fn-custom-7.rs | 10 +++++----- tests/target/fn-custom-8.rs | 8 ++++---- tests/target/fn_args_layout-block.rs | 12 ++++++------ tests/target/fn_args_layout-blockalways.rs | 12 ++++++------ tests/target/where-clause-rfc.rs | 8 ++++---- 7 files changed, 40 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ea8ac6687a6..8f35d58e919 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1776,16 +1776,16 @@ fn rewrite_args(context: &RewriteContext, debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); - let end_with_newline = match context.config.fn_args_layout { - FnArgLayoutStyle::Block | - FnArgLayoutStyle::BlockAlways => true, - _ => false, + let (trailing_comma, end_with_newline) = match context.config.fn_args_layout { + FnArgLayoutStyle::Block => (SeparatorTactic::Vertical, true), + FnArgLayoutStyle::BlockAlways => (SeparatorTactic::Always, true), + _ => (SeparatorTactic::Never, false), }; let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::Never, + trailing_separator: trailing_comma, shape: Shape::legacy(budget, indent), ends_with_newline: end_with_newline, config: context.config, diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 74e6765847e..2da0d5c28d6 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -4,7 +4,7 @@ // Test different indents. fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, ) { foo(); } @@ -14,13 +14,13 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) { bar(); } fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, ) -> String { foo(); } @@ -30,13 +30,13 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String { bar(); } fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, ) where T: UUUUUUUUUUU { foo(); } @@ -46,13 +46,13 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) where T: UUUUUUUUUUU { bar(); } fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, ) -> String where T: UUUUUUUUUUU { foo(); @@ -63,7 +63,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String where T: UUUUUUUUUUU { bar(); @@ -71,12 +71,12 @@ where T: UUUUUUUUUUU { trait Test { fn foo( - a: u8 + a: u8, ) { } fn bar( - a: u8 + a: u8, ) -> String { } } diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 1ae9f4ea896..c0c1b9a8aa1 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -6,7 +6,7 @@ // Case with only one variable. fn foo( - a: u8 + a: u8, ) -> u8 { bar() @@ -15,7 +15,7 @@ fn foo( // Case with 2 variables and some pre-comments. fn foo( a: u8, // Comment 1 - b: u8 // Comment 2 + b: u8, // Comment 2 ) -> u8 { bar() @@ -26,7 +26,7 @@ fn foo( // Comment 1 a: u8, // Comment 2 - b: u8 + b: u8, ) -> u8 { bar() @@ -34,13 +34,13 @@ fn foo( trait Test { fn foo( - a: u8 + a: u8, ) { } fn bar( - a: u8 + a: u8, ) -> String { } diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index bd4a379969b..7ed0f801140 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -12,7 +12,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) { bar(); } @@ -26,7 +26,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String { bar(); } @@ -41,7 +41,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) where T: UUUUUUUUUUU { bar(); } @@ -56,7 +56,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String where T: UUUUUUUUUUU { bar(); diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index 728dc0b1598..27a98cfe7f9 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -14,7 +14,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) { bar(); } @@ -28,7 +28,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String { bar(); } @@ -42,7 +42,7 @@ fn foo( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee // Comment 2 + e: Eeeeeeeeeeeeeee, // Comment 2 ) -> u8 { bar() } @@ -52,7 +52,7 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String where X: Fooooo, Y: Baaar @@ -107,7 +107,7 @@ trait Test { b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String { } } @@ -116,7 +116,7 @@ fn foo String { foo(); } @@ -31,19 +31,19 @@ fn bar( b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeee, ) -> String { bar(); } trait Test { fn foo( - a: u8 + a: u8, ) { } fn bar( - a: u8 + a: u8, ) -> String { } } diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index fd912e794cc..5a589280887 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -21,7 +21,7 @@ fn reflow_list_node_with_rule( rule: &Rule, args: &[Arg], shape: &Shape, - shape: &Shape + shape: &Shape, ) where T: FOo, U: Bar, @@ -34,7 +34,7 @@ fn reflow_list_node_with_rule( rule: &Rule, args: &[Arg], shape: &Shape, - shape: &Shape + shape: &Shape, ) where T: FOo, { @@ -45,7 +45,7 @@ fn reflow_list_node_with_rule( node: &CompoundNode, rule: &Rule, args: &[Arg], - shape: &Shape + shape: &Shape, ) -> Option where T: FOo, @@ -58,7 +58,7 @@ fn reflow_list_node_with_rule( node: &CompoundNode, rule: &Rule, args: &[Arg], - shape: &Shape + shape: &Shape, ) -> Option where T: FOo, -- cgit 1.4.1-3-g733a5 From e3aad6ee83a73be49132b65ea8abc099ae8da027 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 9 Mar 2017 15:49:58 +1300 Subject: Be smarter about finding the span for `..` in patterns Fixes #1319 --- src/patterns.rs | 15 +++++++++++++-- tests/source/pattern.rs | 5 +++++ tests/target/pattern.rs | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 601506b4954..c1b3de56cfb 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -210,8 +210,19 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); if let Some(pos) = dotdot_pos { - let snippet = context.snippet(span); - let lo = span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); + let prev = if pos == 0 { + span.lo + } else { + pats[pos - 1].span().hi + }; + let next = if pos + 1 >= pats.len() { + span.hi + } else { + pats[pos + 1].span().lo + }; + let dot_span = codemap::mk_sp(prev, next); + let snippet = context.snippet(dot_span); + let lo = dot_span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); let span = Span { lo: lo, // 2 == "..".len() diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index a6c25225db2..468ff579710 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -38,3 +38,8 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { ) ) => {}}} } + +fn issue_1319() { + if let (Event { .. }, .. ) = ev_state {} +} + diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index b809253aa85..36d24170cee 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -41,3 +41,7 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { } } } + +fn issue_1319() { + if let (Event { .. }, ..) = ev_state {} +} -- cgit 1.4.1-3-g733a5 From 70085fca84064d4261d0e8ac8e598e102e326474 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 09:26:14 +1300 Subject: Try harder to format function sigs Fixes #1363 --- src/items.rs | 43 +++++++++++++++++++++++++++---------------- tests/source/pattern.rs | 1 - tests/target/fn.rs | 10 ++++------ 3 files changed, 31 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8f35d58e919..acddabd93fe 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1468,7 +1468,7 @@ fn rewrite_fn_base(context: &RewriteContext, generics_span)); result.push_str(&generics_str); - // Note that if the width and indent really matter, we'll re-layout the + // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. let ret_str = try_opt!(fd.output.rewrite(&context, Shape::legacy(context.config.max_width - @@ -1602,7 +1602,7 @@ fn rewrite_fn_base(context: &RewriteContext, Indent::new(indent.width(), result.len()) }; - if multi_line_ret_str { + if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); @@ -1635,29 +1635,40 @@ fn rewrite_fn_base(context: &RewriteContext, _ => false, } || (put_args_in_block && ret_str.is_empty()); - let where_density = if should_compress_where { - Density::Compressed - } else { - Density::Tall - }; + if where_clause.predicates.len() == 1 && should_compress_where { + let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + if let Some(where_clause_str) = + rewrite_where_clause(context, + where_clause, + context.config.fn_brace_style, + Shape::legacy(budget, indent), + Density::Compressed, + "{", + !has_body, + put_args_in_block && ret_str.is_empty(), + Some(span.hi)) { + if last_line_width(&result) + where_clause_str.len() > context.config.max_width && + !where_clause_str.contains('\n') { + result.push('\n'); + } - // Where clause. - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + result.push_str(&where_clause_str); + + return Some((result, force_new_line_for_brace)); + } + } + + let budget = try_opt!(context.config.max_width.checked_sub(indent.block_indent)); let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, context.config.fn_brace_style, - Shape::legacy(where_budget, indent), - where_density, + Shape::legacy(budget, indent), + Density::Tall, "{", !has_body, put_args_in_block && ret_str.is_empty(), Some(span.hi))); - if last_line_width(&result) + where_clause_str.len() > context.config.max_width && - !where_clause_str.contains('\n') { - result.push('\n'); - } - result.push_str(&where_clause_str); Some((result, force_new_line_for_brace)) diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 468ff579710..7e1787ca409 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -42,4 +42,3 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { fn issue_1319() { if let (Event { .. }, .. ) = ev_state {} } - diff --git a/tests/target/fn.rs b/tests/target/fn.rs index db51610d64e..01806ac3cd8 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -81,12 +81,10 @@ fn foo(a: i32) -> i32 { if a > 0 { 1 } else { 2 } } -fn ______________________baz(a: i32) - -> - *mut ::std::option::Option ()>{ +fn ______________________baz + (a: i32) + -> *mut ::std::option::Option ()> { } pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -- cgit 1.4.1-3-g733a5 From 4b60d94a9941f41787efacb59986563e31a05777 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 09:45:26 +1300 Subject: Check we can put the where clause on one line when we think we can Fixes #1362 --- src/items.rs | 14 ++++++++------ tests/target/where-clause-rfc.rs | 3 +-- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index acddabd93fe..ef9e049f725 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1636,6 +1636,7 @@ fn rewrite_fn_base(context: &RewriteContext, } || (put_args_in_block && ret_str.is_empty()); if where_clause.predicates.len() == 1 && should_compress_where { + // TODO hitting this path, but using a newline let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); if let Some(where_clause_str) = rewrite_where_clause(context, @@ -1647,14 +1648,15 @@ fn rewrite_fn_base(context: &RewriteContext, !has_body, put_args_in_block && ret_str.is_empty(), Some(span.hi)) { - if last_line_width(&result) + where_clause_str.len() > context.config.max_width && - !where_clause_str.contains('\n') { - result.push('\n'); - } + if !where_clause_str.contains('\n') { + if last_line_width(&result) + where_clause_str.len() > context.config.max_width { + result.push('\n'); + } - result.push_str(&where_clause_str); + result.push_str(&where_clause_str); - return Some((result, force_new_line_for_brace)); + return Some((result, force_new_line_for_brace)); + } } } diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index 5a589280887..ff63241f8c7 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -78,8 +78,7 @@ pub trait Test { fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where - F: FnMut(Self::Item) - -> bool + F: FnMut(Self::Item) -> bool { } -- cgit 1.4.1-3-g733a5 From 7b901130cb4718dcebfd5e361a9a045117222cbf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 14:29:45 +1300 Subject: Insert a newline before block-formatted generics Fixes #1359 --- rfc-rustfmt.toml | 1 + src/config.rs | 1 + src/items.rs | 37 +++++++++++++++++++++++-------------- 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml index 7b6d3f0b3c4..ec3076c9a3b 100644 --- a/rfc-rustfmt.toml +++ b/rfc-rustfmt.toml @@ -1,2 +1,3 @@ fn_args_layout = "Block" where_style = "Rfc" +generics_indent = "Tabbed" diff --git a/src/config.rs b/src/config.rs index 5cd28c5a492..67fa2256daa 100644 --- a/src/config.rs +++ b/src/config.rs @@ -375,6 +375,7 @@ create_config! { where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation style of a where predicate"; + generics_style: Style, Style::Default, "Overall strategy for generics"; generics_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of generics"; struct_lit_style: StructLitStyle, StructLitStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, diff --git a/src/items.rs b/src/items.rs index ef9e049f725..2a191815b7e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -13,7 +13,8 @@ use {Indent, Shape}; use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, - last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr}; + last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, + trimmed_last_line_width}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; @@ -1468,6 +1469,8 @@ fn rewrite_fn_base(context: &RewriteContext, generics_span)); result.push_str(&generics_str); + let snuggle_angle_bracket = last_line_width(&generics_str) == 1; + // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. let ret_str = try_opt!(fd.output.rewrite(&context, @@ -1495,7 +1498,9 @@ fn rewrite_fn_base(context: &RewriteContext, // Check if vertical layout was forced. if one_line_budget == 0 { - if context.config.fn_args_paren_newline { + if snuggle_angle_bracket { + result.push_str("("); + } else if context.config.fn_args_paren_newline { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); arg_indent = arg_indent + 1; // extra space for `(` @@ -1534,11 +1539,11 @@ fn rewrite_fn_base(context: &RewriteContext, let multi_line_arg_str = arg_str.contains('\n'); - let put_args_in_block = match context.config.fn_args_layout { + let put_args_in_block = (match context.config.fn_args_layout { FnArgLayoutStyle::Block => multi_line_arg_str, FnArgLayoutStyle::BlockAlways => true, _ => false, - } && !fd.inputs.is_empty(); + } || generics_str.contains('\n') )&& !fd.inputs.is_empty(); if put_args_in_block { arg_indent = indent.block_indent(context.config); @@ -1920,11 +1925,14 @@ fn rewrite_generics(context: &RewriteContext, let list_str = try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); - Some(if context.config.spaces_within_angle_brackets { - format!("< {} >", list_str) - } else { - format!("<{}>", list_str) - }) + let result = if context.config.generics_indent != BlockIndentStyle::Visual && list_str.contains('\n') { + format!("<\n{}{}\n{}>", offset.to_string(context.config), list_str, shape.indent.to_string(context.config)) + } else if context.config.spaces_within_angle_brackets { + format!("< {} >", list_str) + } else { + format!("<{}>", list_str) + }; + Some(result) } fn rewrite_trait_bounds(context: &RewriteContext, @@ -2144,10 +2152,11 @@ fn format_generics(context: &RewriteContext, Density::Tall, terminator, false, - false, + trimmed_last_line_width(&result) == 1, Some(span.hi))); result.push_str(&where_clause_str); - if !force_same_line_brace && + let same_line_brace = force_same_line_brace || (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1); + if !same_line_brace && (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) { result.push('\n'); result.push_str(&offset.block_only().to_string(context.config)); @@ -2156,11 +2165,11 @@ fn format_generics(context: &RewriteContext, } result.push_str(opener); } else { - if !force_same_line_brace && brace_style == BraceStyle::AlwaysNextLine { + if force_same_line_brace || trimmed_last_line_width(&result) == 1 || brace_style != BraceStyle::AlwaysNextLine { + result.push(' '); + } else { result.push('\n'); result.push_str(&offset.block_only().to_string(context.config)); - } else { - result.push(' '); } result.push_str(opener); } -- cgit 1.4.1-3-g733a5 From c8af03f4750f81069e9915643d771e4aebae1b80 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 15:30:47 +1300 Subject: Block formatting for tuple structs Follows the fn_args_layout option --- src/config.rs | 3 ++- src/items.rs | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 67fa2256daa..446bbab9e0e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -362,7 +362,8 @@ create_config! { "Location of return type in function declaration"; fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, "Argument density in functions"; - fn_args_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, "Layout of function arguments"; + fn_args_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, + "Layout of function arguments and tuple structs"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; diff --git a/src/items.rs b/src/items.rs index 2a191815b7e..5d1e034b389 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,7 +15,7 @@ use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, trimmed_last_line_width}; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; use comment::{FindUncommented, contains_comment}; @@ -1013,9 +1013,19 @@ fn format_tuple_struct(context: &RewriteContext, } None => "".to_owned(), }; - result.push('('); - let item_indent = offset.block_only() + result.len(); + let (tactic, item_indent) = match context.config.fn_args_layout { + FnArgLayoutStyle::Visual => { + result.push('('); + (ListTactic::HorizontalVertical, offset.block_only() + result.len()) + } + FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => { + let indent = offset.block_only().block_indent(&context.config); + result.push_str("(\n"); + result.push_str(&indent.to_string(&context.config)); + (ListTactic::Vertical, indent) + } + }; // 2 = ");" let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2)); @@ -1035,9 +1045,10 @@ fn format_tuple_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "("), span.hi); - let body = try_opt!(format_item_list(items, - Shape::legacy(item_budget, item_indent), - context.config)); + let body = try_opt!(list_helper(items, + Shape::legacy(item_budget, item_indent), + context.config, + tactic)); if context.config.spaces_within_parens && body.len() > 0 { result.push(' '); @@ -1049,13 +1060,22 @@ fn format_tuple_struct(context: &RewriteContext, result.push(' '); } - result.push(')'); + match context.config.fn_args_layout { + FnArgLayoutStyle::Visual => { + result.push(')'); + } + FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => { + result.push('\n'); + result.push_str(&offset.block_only().to_string(&context.config)); + result.push(')'); + } + } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && (result.contains('\n') || offset.block_indent + result.len() + where_clause_str.len() + 1 > context.config.max_width) { - // We need to put the where clause on a new line, but we didn'to_string + // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1)) -- cgit 1.4.1-3-g733a5 From a1d94e545cb070212f6a8d09ef584e87b0c4b35a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 15:58:35 +1300 Subject: Attempt to fixup impls with long generics --- src/items.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5d1e034b389..6bb30425073 100644 --- a/src/items.rs +++ b/src/items.rs @@ -527,7 +527,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - context.config.where_density, "{", false, - false, + last_line_width(&ref_and_type) == 1, None)); if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { @@ -626,7 +626,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, item.node { let mut result = String::new(); - result.push_str(&*format_visibility(&item.vis)); + result.push_str(&format_visibility(&item.vis)); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); @@ -650,8 +650,9 @@ fn format_impl_ref_and_type(context: &RewriteContext, if polarity != ast::ImplPolarity::Negative { result.push_str(" "); } - let budget = try_opt!(context.config.max_width.checked_sub(result.len())); - let indent = offset + result.len(); + let used_space = last_line_width(&result); + let budget = try_opt!(context.config.max_width.checked_sub(used_space)); + let indent = offset + used_space; result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent)))); if split_at_for { @@ -1119,7 +1120,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, context.config.where_density, "=", true, - false, + true, Some(span.hi))); result.push_str(&where_clause_str); result.push_str(" = "); -- cgit 1.4.1-3-g733a5 From 22be93780c870603bf789ffb5b941de9936256ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 16:04:08 +1300 Subject: block generics in traits --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6bb30425073..768a5f5abb3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -795,7 +795,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) where_density, "{", !has_body, - false, + trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, None)); // If the where clause cannot fit on the same line, // put the where clause on a new line -- cgit 1.4.1-3-g733a5 From d5478f7d455f30ba0edfa3a604f96704331f785e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 10 Mar 2017 16:06:05 +1300 Subject: Reformatting source code --- src/items.rs | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 768a5f5abb3..512b9dc5bb2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -795,7 +795,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) where_density, "{", !has_body, - trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, + trait_bound_str.is_empty() && + last_line_width(&generics_str) == 1, None)); // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -1020,7 +1021,8 @@ fn format_tuple_struct(context: &RewriteContext, result.push('('); (ListTactic::HorizontalVertical, offset.block_only() + result.len()) } - FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => { + FnArgLayoutStyle::Block | + FnArgLayoutStyle::BlockAlways => { let indent = offset.block_only().block_indent(&context.config); result.push_str("(\n"); result.push_str(&indent.to_string(&context.config)); @@ -1065,7 +1067,8 @@ fn format_tuple_struct(context: &RewriteContext, FnArgLayoutStyle::Visual => { result.push(')'); } - FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => { + FnArgLayoutStyle::Block | + FnArgLayoutStyle::BlockAlways => { result.push('\n'); result.push_str(&offset.block_only().to_string(&context.config)); result.push(')'); @@ -1561,10 +1564,11 @@ fn rewrite_fn_base(context: &RewriteContext, let multi_line_arg_str = arg_str.contains('\n'); let put_args_in_block = (match context.config.fn_args_layout { - FnArgLayoutStyle::Block => multi_line_arg_str, - FnArgLayoutStyle::BlockAlways => true, - _ => false, - } || generics_str.contains('\n') )&& !fd.inputs.is_empty(); + FnArgLayoutStyle::Block => multi_line_arg_str, + FnArgLayoutStyle::BlockAlways => true, + _ => false, + } || generics_str.contains('\n')) && + !fd.inputs.is_empty(); if put_args_in_block { arg_indent = indent.block_indent(context.config); @@ -1946,8 +1950,12 @@ fn rewrite_generics(context: &RewriteContext, let list_str = try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); - let result = if context.config.generics_indent != BlockIndentStyle::Visual && list_str.contains('\n') { - format!("<\n{}{}\n{}>", offset.to_string(context.config), list_str, shape.indent.to_string(context.config)) + let result = if context.config.generics_indent != BlockIndentStyle::Visual && + list_str.contains('\n') { + format!("<\n{}{}\n{}>", + offset.to_string(context.config), + list_str, + shape.indent.to_string(context.config)) } else if context.config.spaces_within_angle_brackets { format!("< {} >", list_str) } else { @@ -2165,18 +2173,20 @@ fn format_generics(context: &RewriteContext, if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); - let where_clause_str = try_opt!(rewrite_where_clause(context, - &generics.where_clause, - brace_style, - Shape::legacy(budget, - offset.block_only()), - Density::Tall, - terminator, - false, - trimmed_last_line_width(&result) == 1, - Some(span.hi))); + let where_clause_str = + try_opt!(rewrite_where_clause(context, + &generics.where_clause, + brace_style, + Shape::legacy(budget, offset.block_only()), + Density::Tall, + terminator, + false, + trimmed_last_line_width(&result) == 1, + Some(span.hi))); result.push_str(&where_clause_str); - let same_line_brace = force_same_line_brace || (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1); + let same_line_brace = force_same_line_brace || + (generics.where_clause.predicates.is_empty() && + trimmed_last_line_width(&result) == 1); if !same_line_brace && (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) { result.push('\n'); @@ -2186,7 +2196,8 @@ fn format_generics(context: &RewriteContext, } result.push_str(opener); } else { - if force_same_line_brace || trimmed_last_line_width(&result) == 1 || brace_style != BraceStyle::AlwaysNextLine { + if force_same_line_brace || trimmed_last_line_width(&result) == 1 || + brace_style != BraceStyle::AlwaysNextLine { result.push(' '); } else { result.push('\n'); -- cgit 1.4.1-3-g733a5 From ab832fa4bb4c756091f191a1674d32d1bfa22c66 Mon Sep 17 00:00:00 2001 From: C4K3 Date: Sun, 12 Mar 2017 21:07:33 +0100 Subject: config: Rename ideal_width -> comment_width (#1370) Since the config option only affects comment widths, and the previous name has led to some confusion (see #1321, #1152). --- Design.md | 2 +- src/config.rs | 2 +- src/items.rs | 4 ++-- src/missed_spans.rs | 2 +- src/visitor.rs | 4 ++-- tests/config/small_tabs.toml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/Design.md b/Design.md index 7e2f00aebdf..da52fb23e40 100644 --- a/Design.md +++ b/Design.md @@ -150,7 +150,7 @@ for its configuration. Our visitor keeps track of the desired current indent due to blocks ( `block_indent`). Each `visit_*` method reformats code according to this indent, -`config.ideal_width` and `config.max_width`. Most reformatting done in the +`config.comment_width` and `config.max_width`. Most reformatting done in the `visit_*` methods is a bit hackey and is meant to be temporary until it can be done properly. diff --git a/src/config.rs b/src/config.rs index 5cd28c5a492..fe597614a48 100644 --- a/src/config.rs +++ b/src/config.rs @@ -338,7 +338,6 @@ create_config! { "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; max_width: usize, 100, "Maximum width of each line"; - ideal_width: usize, 80, "Ideal width of each line"; error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width"; tab_spaces: usize, 4, "Number of spaces per tab"; fn_call_width: usize, 60, @@ -396,6 +395,7 @@ create_config! { take_source_hints: bool, false, "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, "Break comments to fit on the line"; + comment_width: usize, 80, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, "Convert /* */ comments to // comments where possible"; wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, diff --git a/src/items.rs b/src/items.rs index ef9e049f725..7e4df9031ae 100644 --- a/src/items.rs +++ b/src/items.rs @@ -763,7 +763,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line if offset.width() + last_line_width(&result) + trait_bound_str.len() > - context.config.ideal_width { + context.config.comment_width { result.push('\n'); let trait_indent = offset.block_only().block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); @@ -799,7 +799,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) // put the where clause on a new line if !where_clause_str.contains('\n') && last_line_width(&result) + where_clause_str.len() + offset.width() > - context.config.ideal_width { + context.config.comment_width { result.push('\n'); let width = offset.block_indent + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 767a81120e5..1a1371a19ce 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -143,7 +143,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(" "); } - let comment_width = ::std::cmp::min(self.config.ideal_width, + let comment_width = ::std::cmp::min(self.config.comment_width, self.config.max_width - self.block_indent.width()); diff --git a/src/visitor.rs b/src/visitor.rs index 6cd00ffc1f4..2700287608d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -594,7 +594,7 @@ impl<'a> Rewrite for [ast::Attribute] { let comment = try_opt!(rewrite_comment(comment, false, Shape::legacy(context.config - .ideal_width - + .comment_width - shape.indent.width(), shape.indent), context.config)); @@ -610,7 +610,7 @@ impl<'a> Rewrite for [ast::Attribute] { if a_str.starts_with("//") { a_str = try_opt!(rewrite_comment(&a_str, false, - Shape::legacy(context.config.ideal_width - + Shape::legacy(context.config.comment_width - shape.indent.width(), shape.indent), context.config)); diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index a8150020e56..69e9dfd5380 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -1,5 +1,5 @@ max_width = 100 -ideal_width = 80 +comment_width = 80 tab_spaces = 2 newline_style = "Unix" fn_brace_style = "SameLineWhere" -- cgit 1.4.1-3-g733a5 From 4df405a7680c99df325bec3849634f31442bce79 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Mar 2017 11:25:46 +1300 Subject: Line breaking around generics in tuple structs --- src/items.rs | 63 ++++++++++++++++++++++----------------------- tests/target/fn-custom-2.rs | 20 ++++++++------ tests/target/fn-custom-3.rs | 20 ++++++++------ 3 files changed, 55 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 512b9dc5bb2..e0912828f2d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1018,19 +1018,16 @@ fn format_tuple_struct(context: &RewriteContext, let (tactic, item_indent) = match context.config.fn_args_layout { FnArgLayoutStyle::Visual => { - result.push('('); - (ListTactic::HorizontalVertical, offset.block_only() + result.len()) + // 1 = `(` + (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) } FnArgLayoutStyle::Block | FnArgLayoutStyle::BlockAlways => { - let indent = offset.block_only().block_indent(&context.config); - result.push_str("(\n"); - result.push_str(&indent.to_string(&context.config)); - (ListTactic::Vertical, indent) + (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) } }; - // 2 = ");" - let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 2)); + // 3 = `();` + let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 3)); let items = itemize_list(context.codemap, @@ -1048,31 +1045,34 @@ fn format_tuple_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "("), span.hi); + let body_budget = try_opt!(context.config.max_width.checked_sub(offset.block_only().width() + + result.len() + + 3)); let body = try_opt!(list_helper(items, - Shape::legacy(item_budget, item_indent), + // TODO budget is wrong in block case + Shape::legacy(body_budget, item_indent), context.config, tactic)); - if context.config.spaces_within_parens && body.len() > 0 { - result.push(' '); - } - - result.push_str(&body); + if context.config.fn_args_layout == FnArgLayoutStyle::Visual || !body.contains('\n') { + result.push('('); + if context.config.spaces_within_parens && body.len() > 0 { + result.push(' '); + } - if context.config.spaces_within_parens && body.len() > 0 { - result.push(' '); - } + result.push_str(&body); - match context.config.fn_args_layout { - FnArgLayoutStyle::Visual => { - result.push(')'); - } - FnArgLayoutStyle::Block | - FnArgLayoutStyle::BlockAlways => { - result.push('\n'); - result.push_str(&offset.block_only().to_string(&context.config)); - result.push(')'); + if context.config.spaces_within_parens && body.len() > 0 { + result.push(' '); } + result.push(')'); + } else { + result.push_str("(\n"); + result.push_str(&item_indent.to_string(&context.config)); + result.push_str(&body); + result.push('\n'); + result.push_str(&offset.block_only().to_string(&context.config)); + result.push(')'); } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && @@ -1563,12 +1563,11 @@ fn rewrite_fn_base(context: &RewriteContext, let multi_line_arg_str = arg_str.contains('\n'); - let put_args_in_block = (match context.config.fn_args_layout { - FnArgLayoutStyle::Block => multi_line_arg_str, - FnArgLayoutStyle::BlockAlways => true, - _ => false, - } || generics_str.contains('\n')) && - !fd.inputs.is_empty(); + let put_args_in_block = match context.config.fn_args_layout { + FnArgLayoutStyle::Block => multi_line_arg_str || generics_str.contains('\n'), + FnArgLayoutStyle::BlockAlways => true, + _ => false, + } && !fd.inputs.is_empty(); if put_args_in_block { arg_indent = indent.block_indent(context.config); diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index acac301fa53..ff67084b202 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -12,10 +12,11 @@ e: Eeeeeeeeeeeeeeeeeee) { foo(); } -fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, +fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> - (a: Aaaaaaaaaaaaaaa) { + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW +>(a: Aaaaaaaaaaaaaaa) { bar(); } @@ -42,9 +43,11 @@ impl Foo { foo(); } - fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + > (a: Aaaaaaaaaaaaaaa) { bar(); } @@ -56,10 +59,11 @@ impl Foo { } } -struct Foo -{ + WWWWWWWWWWWWWWWWWWWWWWWW +> { foo: Foo, } diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 110fcf36714..f8de7f4a343 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -11,10 +11,11 @@ fn foo(a: Aaaaaaaaaaaaaaa, foo(); } -fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, +fn bar< +'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, -UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> - (a: Aaaaaaaaaaaaaaa) { +UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW +>(a: Aaaaaaaaaaaaaaa) { bar(); } @@ -43,18 +44,21 @@ impl Foo { foo(); } - fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW> + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + > (a: Aaaaaaaaaaaaaaa) { bar(); } } -struct Foo -{ +WWWWWWWWWWWWWWWWWWWWWWWW +> { foo: Foo, } -- cgit 1.4.1-3-g733a5 From ed10bf95322bbf436a9acd5bdd5d37b9f0386a92 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Mar 2017 11:42:41 +1300 Subject: Trailing comma for functions with empty bodies --- src/items.rs | 13 ++++++++----- tests/target/where-clause-rfc.rs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e0912828f2d..e21035e615f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -191,6 +191,7 @@ impl<'a> FmtVisitor<'a> { &item.vis, span, false, + false, false); match rewrite { @@ -258,7 +259,8 @@ impl<'a> FmtVisitor<'a> { vis, span, newline_brace, - has_body)); + has_body, + true)); if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; @@ -303,6 +305,7 @@ impl<'a> FmtVisitor<'a> { &ast::Visibility::Inherited, span, false, + false, false)); // Re-attach semicolon @@ -1455,7 +1458,8 @@ fn rewrite_fn_base(context: &RewriteContext, vis: &ast::Visibility, span: Span, newline_brace: bool, - has_body: bool) + has_body: bool, + has_braces: bool) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; @@ -1665,7 +1669,6 @@ fn rewrite_fn_base(context: &RewriteContext, } || (put_args_in_block && ret_str.is_empty()); if where_clause.predicates.len() == 1 && should_compress_where { - // TODO hitting this path, but using a newline let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); if let Some(where_clause_str) = rewrite_where_clause(context, @@ -1674,7 +1677,7 @@ fn rewrite_fn_base(context: &RewriteContext, Shape::legacy(budget, indent), Density::Compressed, "{", - !has_body, + !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi)) { if !where_clause_str.contains('\n') { @@ -1696,7 +1699,7 @@ fn rewrite_fn_base(context: &RewriteContext, Shape::legacy(budget, indent), Density::Tall, "{", - !has_body, + !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi))); diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index ff63241f8c7..6859690fa15 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -78,7 +78,7 @@ pub trait Test { fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where - F: FnMut(Self::Item) -> bool + F: FnMut(Self::Item) -> bool, { } -- cgit 1.4.1-3-g733a5 From 0cb6f56647192a10f99093e3c6e6aefc1e399539 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 20 Mar 2017 10:25:37 +1300 Subject: Block formatting for arrays Fixes #1331 --- src/config.rs | 1 + src/expr.rs | 60 ++++++++++++++++++----- tests/source/expr-block.rs | 78 +++++++++++++++++++++++++++++ tests/target/expr-block.rs | 120 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+), 11 deletions(-) create mode 100644 tests/source/expr-block.rs create mode 100644 tests/target/expr-block.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b4b7c3e13f4..4206392d7a7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -364,6 +364,7 @@ create_config! { fn_args_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, "Layout of function arguments and tuple structs"; fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; + array_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, "Indent on arrays"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; where_style: Style, Style::Default, "Overall strategy for where clauses"; diff --git a/src/expr.rs b/src/expr.rs index e540965fd8c..7e85ca4ee34 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -24,7 +24,7 @@ use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; use visitor::FmtVisitor; -use config::{Config, StructLitStyle, MultilineStyle, ControlBraceStyle}; +use config::{Config, StructLitStyle, MultilineStyle, ControlBraceStyle, FnArgLayoutStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::{rewrite_path, PathContext}; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -329,7 +329,15 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } else { 1 // "[" }; - let nested_shape = try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)); + + let nested_shape = match context.config.array_layout { + FnArgLayoutStyle::Block | + FnArgLayoutStyle::BlockAlways => shape.block().block_indent(context.config.tab_spaces), + FnArgLayoutStyle::Visual => { + try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)) + } + }; + let items = itemize_list(context.codemap, expr_iter, "]", @@ -340,15 +348,35 @@ pub fn rewrite_array<'a, I>(expr_iter: I, span.hi) .collect::>(); + if items.is_empty() { + if context.config.spaces_within_square_brackets { + return Some("[ ]".to_string()); + } else { + return Some("[]".to_string()); + } + } + let has_long_item = try_opt!(items.iter() .map(|li| li.item.as_ref().map(|s| s.len() > 10)) .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y)))); - let tactic = if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) - } else { - DefinitiveListTactic::Mixed + let tactic = match context.config.array_layout { + FnArgLayoutStyle::Block => { + // TODO wrong shape in one-line case + match shape.width.checked_sub(2 * bracket_size) { + Some(width) => definitive_tactic(&items, ListTactic::HorizontalVertical, width), + None => DefinitiveListTactic::Vertical, + } + } + FnArgLayoutStyle::BlockAlways => DefinitiveListTactic::Vertical, + FnArgLayoutStyle::Visual => { + if has_long_item || items.iter().any(ListItem::is_multiline) { + definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) + } else { + DefinitiveListTactic::Mixed + } + } }; let fmt = ListFormatting { @@ -361,11 +389,21 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let list_str = try_opt!(write_list(&items, &fmt)); - Some(if context.config.spaces_within_square_brackets && list_str.len() > 0 { - format!("[ {} ]", list_str) - } else { - format!("[{}]", list_str) - }) + let result = if context.config.array_layout == FnArgLayoutStyle::Visual || + tactic != DefinitiveListTactic::Vertical { + if context.config.spaces_within_square_brackets && list_str.len() > 0 { + format!("[ {} ]", list_str) + } else { + format!("[{}]", list_str) + } + } else { + format!("[\n{}{},\n{}]", + nested_shape.indent.to_string(context.config), + list_str, + shape.block().indent.to_string(context.config)) + }; + + Some(result) } // This functions is pretty messy because of the rules around closures and blocks: diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs new file mode 100644 index 00000000000..5e120b8604c --- /dev/null +++ b/tests/source/expr-block.rs @@ -0,0 +1,78 @@ +// rustfmt-array_layout: Block +// Test expressions with block formatting. + +fn arrays() { + [ ]; + let empty = []; + + let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name]; + + let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name]; + + vec![a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name]; + + [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name] +} + +fn arrays() { + let x = [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; + + let a =WeightedChoice::new(&mut [Weighted { + weight: x, + item: 0, + }, + Weighted { + weight: 1, + item: 1, + }, + Weighted { + weight: x, + item: 2, + }, + Weighted { + weight: 1, + item: 3, + }]); + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; + + [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs new file mode 100644 index 00000000000..0daa8ff91d6 --- /dev/null +++ b/tests/target/expr-block.rs @@ -0,0 +1,120 @@ +// rustfmt-array_layout: Block +// Test expressions with block formatting. + +fn arrays() { + []; + let empty = []; + + let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name]; + + let foo = [ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + ]; + + vec![ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_very_lng_name, + ]; + + [ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_very_lng_name, + ] +} + +fn arrays() { + let x = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + ]; + + let y = [ + /* comment */ + 1, + 2, /* post comment */ + 3, + ]; + + let xy = [ + strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + /* comment */ + 1, + ]; + + let a = WeightedChoice::new(&mut [ + Weighted { + weight: x, + item: 0, + }, + Weighted { + weight: 1, + item: 1, + }, + Weighted { + weight: x, + item: 2, + }, + Weighted { + weight: 1, + item: 3, + }, + ]); + + let z = + [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; + + [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] +} -- cgit 1.4.1-3-g733a5 From ce7b0aacd0d70145d9583e41c1ef65154d790823 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 20 Mar 2017 11:07:33 +1300 Subject: Remove BlockIndentStyle::Inherit --- src/chains.rs | 15 +-------------- src/config.rs | 2 -- src/items.rs | 10 +--------- tests/source/chains-indent-inherit.rs | 5 ----- tests/source/fn-custom-2.rs | 4 ++-- tests/source/fn-custom-3.rs | 2 +- tests/source/fn-custom-5.rs | 6 ------ tests/source/fn-custom-6.rs | 2 +- tests/source/fn-custom-8.rs | 2 +- tests/target/chains-indent-inherit.rs | 10 ---------- tests/target/fn-custom-2.rs | 30 +++++++++++++++--------------- tests/target/fn-custom-3.rs | 22 +++++++++++----------- tests/target/fn-custom-5.rs | 11 ----------- tests/target/fn-custom-6.rs | 6 +++--- tests/target/fn-custom-8.rs | 12 ++++++------ 15 files changed, 42 insertions(+), 97 deletions(-) delete mode 100644 tests/source/chains-indent-inherit.rs delete mode 100644 tests/source/fn-custom-5.rs delete mode 100644 tests/target/chains-indent-inherit.rs delete mode 100644 tests/target/fn-custom-5.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4918ebd3cac..32505138e65 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -123,7 +123,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - parent_shape.block_indent(context.config.tab_spaces)), false) } else { - (chain_indent_newline(context, shape.add_offset(parent_rewrite.len())), false) + (shape.block_indent(context.config.tab_spaces), false) }; let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset) @@ -135,7 +135,6 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let mut shape = try_opt!(parent_shape.shrink_left(last_line_width(&parent_rewrite))); match context.config.chain_indent { BlockIndentStyle::Visual => other_child_shape, - BlockIndentStyle::Inherit => shape, BlockIndentStyle::Tabbed => { shape.offset = shape.offset.checked_sub(context.config.tab_spaces).unwrap_or(0); shape.indent.block_indent += context.config.tab_spaces; @@ -296,22 +295,10 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent { BlockIndentStyle::Visual => shape.visual_indent(0), - BlockIndentStyle::Inherit => shape.block_indent(0), BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces), } } -// Ignores visual indenting because this function should be called where it is -// not possible to use visual indentation because we are starting on a newline. -fn chain_indent_newline(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.chain_indent { - BlockIndentStyle::Inherit => shape.block_indent(0), - BlockIndentStyle::Visual | BlockIndentStyle::Tabbed => { - shape.block_indent(context.config.tab_spaces) - } - } -} - fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, last: &mut String, almost_total: usize, diff --git a/src/config.rs b/src/config.rs index 4206392d7a7..ff9b7cd4d96 100644 --- a/src/config.rs +++ b/src/config.rs @@ -83,8 +83,6 @@ configuration_option_enum! { FnArgLayoutStyle: } configuration_option_enum! { BlockIndentStyle: - // Same level as parent. - Inherit, // One level deeper than parent. Tabbed, // Aligned with block open. diff --git a/src/items.rs b/src/items.rs index d20b2f77598..445959f63b0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1806,7 +1806,6 @@ fn rewrite_args(context: &RewriteContext, } let indent = match context.config.fn_arg_indent { - BlockIndentStyle::Inherit => indent, BlockIndentStyle::Tabbed => indent.block_indent(context.config), BlockIndentStyle::Visual => arg_indent, }; @@ -1915,7 +1914,6 @@ fn rewrite_generics(context: &RewriteContext, } let offset = match context.config.generics_indent { - BlockIndentStyle::Inherit => shape.indent, BlockIndentStyle::Tabbed => shape.indent.block_indent(context.config), // 1 = < BlockIndentStyle::Visual => generics_offset + 1, @@ -2078,15 +2076,9 @@ fn rewrite_where_clause(context: &RewriteContext, span_end); } - let extra_indent = match context.config.where_indent { - BlockIndentStyle::Inherit => Indent::empty(), - BlockIndentStyle::Tabbed | BlockIndentStyle::Visual => { - Indent::new(context.config.tab_spaces, 0) - } - }; + let extra_indent = Indent::new(context.config.tab_spaces, 0); let offset = match context.config.where_pred_indent { - BlockIndentStyle::Inherit => shape.indent + extra_indent, BlockIndentStyle::Tabbed => shape.indent + extra_indent.block_indent(context.config), // 6 = "where ".len() BlockIndentStyle::Visual => shape.indent + extra_indent + 6, diff --git a/tests/source/chains-indent-inherit.rs b/tests/source/chains-indent-inherit.rs deleted file mode 100644 index 67272a656c6..00000000000 --- a/tests/source/chains-indent-inherit.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-chain_indent: Inherit - -fn test() { - let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); -} diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index a45f5501ea7..ddd11949580 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,6 +1,6 @@ -// rustfmt-fn_arg_indent: Inherit +// rustfmt-fn_arg_indent: Tabbed // rustfmt-generics_indent: Tabbed -// rustfmt-where_indent: Inherit +// rustfmt-where_indent: Tabbed // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs index e63b642d19c..b5df5edddae 100644 --- a/tests/source/fn-custom-3.rs +++ b/tests/source/fn-custom-3.rs @@ -1,5 +1,5 @@ // rustfmt-fn_arg_indent: Tabbed -// rustfmt-generics_indent: Inherit +// rustfmt-generics_indent: Tabbed // rustfmt-where_layout: HorizontalVertical // Test different indents. diff --git a/tests/source/fn-custom-5.rs b/tests/source/fn-custom-5.rs deleted file mode 100644 index 98f11a72eab..00000000000 --- a/tests/source/fn-custom-5.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-where_pred_indent: Inherit -// Test different indents. - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index 1f2d740a075..5f464d93045 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: BlockAlways -// rustfmt-where_indent: Inherit +// rustfmt-where_indent: Tabbed // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs index a1aebf1f38c..26ab6a89443 100644 --- a/tests/source/fn-custom-8.rs +++ b/tests/source/fn-custom-8.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Inherit +// rustfmt-where_indent: Tabbed // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/chains-indent-inherit.rs b/tests/target/chains-indent-inherit.rs deleted file mode 100644 index 76d3ef8204b..00000000000 --- a/tests/target/chains-indent-inherit.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-chain_indent: Inherit - -fn test() { - let x = my_long_function() - .my_even_longer_function() - .my_nested_function() - .some_random_name() - .another_function() - .do_it(); -} diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index ff67084b202..71aecfeab4e 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,14 +1,14 @@ -// rustfmt-fn_arg_indent: Inherit +// rustfmt-fn_arg_indent: Tabbed // rustfmt-generics_indent: Tabbed -// rustfmt-where_indent: Inherit +// rustfmt-where_indent: Tabbed // rustfmt-where_layout: Mixed // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, -b: Bbbbbbbbbbbbbbbb, -c: Ccccccccccccccccc, -d: Ddddddddddddddddddddddddd, -e: Eeeeeeeeeeeeeeeeeee) { + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee) { foo(); } @@ -21,25 +21,25 @@ fn bar< } fn baz() -where X: TTTTTTTT + where X: TTTTTTTT { baz(); } fn qux() -where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT + where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { baz(); } impl Foo { fn foo(self, - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee) { + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee) { foo(); } @@ -53,7 +53,7 @@ impl Foo { } fn baz() - where X: TTTTTTTT + where X: TTTTTTTT { baz(); } diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index f8de7f4a343..96e82ac91f8 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -1,5 +1,5 @@ // rustfmt-fn_arg_indent: Tabbed -// rustfmt-generics_indent: Inherit +// rustfmt-generics_indent: Tabbed // rustfmt-where_layout: HorizontalVertical // Test different indents. @@ -12,9 +12,9 @@ fn foo(a: Aaaaaaaaaaaaaaa, } fn bar< -'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, -TTTTTTTTTTTTT, -UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW >(a: Aaaaaaaaaaaaaaa) { bar(); } @@ -45,9 +45,9 @@ impl Foo { } fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW > (a: Aaaaaaaaaaaaaaa) { bar(); @@ -55,10 +55,10 @@ impl Foo { } struct Foo< -TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -UUUUUUUUUUUUUUUUUUUUUU, -VVVVVVVVVVVVVVVVVVVVVVVVVVV, -WWWWWWWWWWWWWWWWWWWWWWWW + TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUU, + VVVVVVVVVVVVVVVVVVVVVVVVVVV, + WWWWWWWWWWWWWWWWWWWWWWWW > { foo: Foo, } diff --git a/tests/target/fn-custom-5.rs b/tests/target/fn-custom-5.rs deleted file mode 100644 index 08c717538f2..00000000000 --- a/tests/target/fn-custom-5.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-where_pred_indent: Inherit -// Test different indents. - -fn qux() - where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT -{ - baz(); -} diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 2da0d5c28d6..8cd8d20f360 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: BlockAlways -// rustfmt-where_indent: Inherit +// rustfmt-where_indent: Tabbed // rustfmt-fn_brace_style: PreferSameLine // Test different indents. @@ -54,7 +54,7 @@ fn bar( fn foo( a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, ) -> String -where T: UUUUUUUUUUU { + where T: UUUUUUUUUUU { foo(); } @@ -65,7 +65,7 @@ fn bar( d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, ) -> String -where T: UUUUUUUUUUU { + where T: UUUUUUUUUUU { bar(); } diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index 7ed0f801140..0c1c2aaf8f3 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Inherit +// rustfmt-where_indent: Tabbed // rustfmt-fn_brace_style: PreferSameLine // Test different indents. @@ -32,7 +32,7 @@ fn bar( } fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -where T: UUUUUUUUUUU { + where T: UUUUUUUUUUU { foo(); } @@ -47,7 +47,7 @@ fn bar( } fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String -where T: UUUUUUUUUUU { + where T: UUUUUUUUUUU { foo(); } @@ -58,7 +58,7 @@ fn bar( d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, ) -> String -where T: UUUUUUUUUUU { + where T: UUUUUUUUUUU { bar(); } @@ -68,7 +68,7 @@ trait Test { fn bar(a: u8) -> String {} fn bar(a: u8) -> String - where Foo: foooo, - Bar: barrr { + where Foo: foooo, + Bar: barrr { } } -- cgit 1.4.1-3-g733a5 From c986e895bbe856ffafd6999cc1d4418330e47f86 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 20 Mar 2017 11:35:53 +1300 Subject: Remove FnArgLayoutStyle::BlockAlways --- src/config.rs | 2 -- src/expr.rs | 4 +-- src/items.rs | 9 ++---- tests/source/fn-custom-6.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn_args_layout-blockalways.rs | 27 ---------------- tests/target/fn-custom-6.rs | 29 +++++------------- tests/target/fn-custom-7.rs | 14 +++------ tests/target/fn_args_layout-blockalways.rs | 49 ------------------------------ 9 files changed, 17 insertions(+), 121 deletions(-) delete mode 100644 tests/source/fn_args_layout-blockalways.rs delete mode 100644 tests/target/fn_args_layout-blockalways.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index ff9b7cd4d96..317cc9218c7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -78,8 +78,6 @@ configuration_option_enum! { FnArgLayoutStyle: Visual, // Put args on one line if they fit, or start a new line with block indent. Block, - // First line is on a new line and all lines align with block indent. - BlockAlways, } configuration_option_enum! { BlockIndentStyle: diff --git a/src/expr.rs b/src/expr.rs index 7e85ca4ee34..3d6ec44b8c8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -331,8 +331,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let nested_shape = match context.config.array_layout { - FnArgLayoutStyle::Block | - FnArgLayoutStyle::BlockAlways => shape.block().block_indent(context.config.tab_spaces), + FnArgLayoutStyle::Block => shape.block().block_indent(context.config.tab_spaces), FnArgLayoutStyle::Visual => { try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)) } @@ -369,7 +368,6 @@ pub fn rewrite_array<'a, I>(expr_iter: I, None => DefinitiveListTactic::Vertical, } } - FnArgLayoutStyle::BlockAlways => DefinitiveListTactic::Vertical, FnArgLayoutStyle::Visual => { if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) diff --git a/src/items.rs b/src/items.rs index 445959f63b0..f2650494a82 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1024,8 +1024,7 @@ fn format_tuple_struct(context: &RewriteContext, // 1 = `(` (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) } - FnArgLayoutStyle::Block | - FnArgLayoutStyle::BlockAlways => { + FnArgLayoutStyle::Block => { (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) } }; @@ -1513,8 +1512,7 @@ fn rewrite_fn_base(context: &RewriteContext, let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = try_opt!(compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace)); - if context.config.fn_args_layout == FnArgLayoutStyle::Block || - context.config.fn_args_layout == FnArgLayoutStyle::BlockAlways { + if context.config.fn_args_layout == FnArgLayoutStyle::Block { arg_indent = indent.block_indent(context.config); multi_line_budget = context.config.max_width - arg_indent.width(); } @@ -1569,7 +1567,6 @@ fn rewrite_fn_base(context: &RewriteContext, let put_args_in_block = match context.config.fn_args_layout { FnArgLayoutStyle::Block => multi_line_arg_str || generics_str.contains('\n'), - FnArgLayoutStyle::BlockAlways => true, _ => false, } && !fd.inputs.is_empty(); @@ -1594,7 +1591,6 @@ fn rewrite_fn_base(context: &RewriteContext, let ret_should_indent = match context.config.fn_args_layout { // If our args are block layout then we surely must have space. FnArgLayoutStyle::Block if put_args_in_block => false, - FnArgLayoutStyle::BlockAlways => false, _ => { // If we've already gone multi-line, or the return type would push over the max // width, then put the return type on a new line. With the +1 for the signature @@ -1822,7 +1818,6 @@ fn rewrite_args(context: &RewriteContext, let (trailing_comma, end_with_newline) = match context.config.fn_args_layout { FnArgLayoutStyle::Block => (SeparatorTactic::Vertical, true), - FnArgLayoutStyle::BlockAlways => (SeparatorTactic::Always, true), _ => (SeparatorTactic::Never, false), }; diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index 5f464d93045..f7079a3a9cd 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: BlockAlways +// rustfmt-fn_args_layout: Block // rustfmt-where_indent: Tabbed // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index 1cbcd211808..febe0c02db2 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: BlockAlways +// rustfmt-fn_args_layout: Block // rustfmt-fn_args_density: Vertical // rustfmt-fn_arg_indent: Tabbed // rustfmt-fn_brace_style: AlwaysNextLine diff --git a/tests/source/fn_args_layout-blockalways.rs b/tests/source/fn_args_layout-blockalways.rs deleted file mode 100644 index d4bb00b9142..00000000000 --- a/tests/source/fn_args_layout-blockalways.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-fn_args_layout: BlockAlways - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 8cd8d20f360..4340e7ac827 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,11 +1,9 @@ -// rustfmt-fn_args_layout: BlockAlways +// rustfmt-fn_args_layout: Block // rustfmt-where_indent: Tabbed // rustfmt-fn_brace_style: PreferSameLine // Test different indents. -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, -) { +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { foo(); } @@ -19,9 +17,7 @@ fn bar( bar(); } -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, -) -> String { +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { foo(); } @@ -35,9 +31,8 @@ fn bar( bar(); } -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, -) where T: UUUUUUUUUUU { +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) + where T: UUUUUUUUUUU { foo(); } @@ -51,9 +46,7 @@ fn bar( bar(); } -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, -) -> String +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { foo(); } @@ -70,13 +63,7 @@ fn bar( } trait Test { - fn foo( - a: u8, - ) { - } + fn foo(a: u8) {} - fn bar( - a: u8, - ) -> String { - } + fn bar(a: u8) -> String {} } diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index c0c1b9a8aa1..faa47a54060 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,13 +1,11 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: BlockAlways +// rustfmt-fn_args_layout: Block // rustfmt-fn_args_density: Vertical // rustfmt-fn_arg_indent: Tabbed // rustfmt-fn_brace_style: AlwaysNextLine // Case with only one variable. -fn foo( - a: u8, -) -> u8 +fn foo(a: u8,) -> u8 { bar() } @@ -33,15 +31,11 @@ fn foo( } trait Test { - fn foo( - a: u8, - ) + fn foo(a: u8,) { } - fn bar( - a: u8, - ) -> String + fn bar(a: u8,) -> String { } } diff --git a/tests/target/fn_args_layout-blockalways.rs b/tests/target/fn_args_layout-blockalways.rs deleted file mode 100644 index eb5caec6520..00000000000 --- a/tests/target/fn_args_layout-blockalways.rs +++ /dev/null @@ -1,49 +0,0 @@ -// rustfmt-fn_args_layout: BlockAlways - -fn foo() { - foo(); -} - -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, -) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo( - a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, -) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -trait Test { - fn foo( - a: u8, - ) { - } - - fn bar( - a: u8, - ) -> String { - } -} -- cgit 1.4.1-3-g733a5 From 21ff1d43ba2dd2a6e9011b393d94599b04effc2f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 20 Mar 2017 11:42:20 +1300 Subject: Unify a bunch of option types into IndentStyle --- src/chains.rs | 10 +++++----- src/config.rs | 36 +++++++++--------------------------- src/expr.rs | 22 +++++++++++----------- src/items.rs | 35 +++++++++++++++++------------------ tests/config/small_tabs.toml | 2 +- tests/source/chains-indent-tabbed.rs | 2 +- tests/source/fn-custom-2.rs | 6 +++--- tests/source/fn-custom-3.rs | 4 ++-- tests/source/fn-custom-4.rs | 2 +- tests/source/fn-custom-6.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom-8.rs | 2 +- tests/target/chains-indent-tabbed.rs | 2 +- tests/target/fn-custom-2.rs | 6 +++--- tests/target/fn-custom-3.rs | 4 ++-- tests/target/fn-custom-4.rs | 2 +- tests/target/fn-custom-6.rs | 2 +- tests/target/fn-custom-7.rs | 2 +- tests/target/fn-custom-8.rs | 2 +- 19 files changed, 63 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 32505138e65..3a3ce74bbb6 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -80,7 +80,7 @@ use Shape; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, first_line_width, last_line_width}; use expr::rewrite_call; -use config::BlockIndentStyle; +use config::IndentStyle; use macros::convert_try_mac; use std::iter; @@ -134,8 +134,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_child_shape = if extend { let mut shape = try_opt!(parent_shape.shrink_left(last_line_width(&parent_rewrite))); match context.config.chain_indent { - BlockIndentStyle::Visual => other_child_shape, - BlockIndentStyle::Tabbed => { + IndentStyle::Visual => other_child_shape, + IndentStyle::Block => { shape.offset = shape.offset.checked_sub(context.config.tab_spaces).unwrap_or(0); shape.indent.block_indent += context.config.tab_spaces; shape @@ -294,8 +294,8 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent { - BlockIndentStyle::Visual => shape.visual_indent(0), - BlockIndentStyle::Tabbed => shape.block_indent(context.config.tab_spaces), + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape.block_indent(context.config.tab_spaces), } } diff --git a/src/config.rs b/src/config.rs index 317cc9218c7..0ff5a45e57a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -61,30 +61,12 @@ configuration_option_enum! { ReturnIndent: WithWhereClause, } -// How to style a struct literal. -configuration_option_enum! { StructLitStyle: +configuration_option_enum! { IndentStyle: // First line on the same line as the opening brace, all lines aligned with // the first line. Visual, // First line is on a new line and all lines align with block indent. Block, - // FIXME Maybe we should also have an option to align types. -} - -// How to style fn args. -configuration_option_enum! { FnArgLayoutStyle: - // First line on the same line as the opening brace, all lines aligned with - // the first line. - Visual, - // Put args on one line if they fit, or start a new line with block indent. - Block, -} - -configuration_option_enum! { BlockIndentStyle: - // One level deeper than parent. - Tabbed, - // Aligned with block open. - Visual, } configuration_option_enum! { Density: @@ -357,10 +339,10 @@ create_config! { "Location of return type in function declaration"; fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, "Argument density in functions"; - fn_args_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, + fn_args_layout: IndentStyle, IndentStyle::Visual, "Layout of function arguments and tuple structs"; - fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments"; - array_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, "Indent on arrays"; + fn_arg_indent: IndentStyle, IndentStyle::Visual, "Indent on function arguments"; + array_layout: IndentStyle, IndentStyle::Visual, "Indent on arrays"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; where_style: Style, Style::Default, "Overall strategy for where clauses"; @@ -368,20 +350,20 @@ create_config! { // function decl? where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; // Visual will be treated like Tabbed - where_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of a where clause"; + where_indent: IndentStyle, IndentStyle::Block, "Indentation of a where clause"; where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; - where_pred_indent: BlockIndentStyle, BlockIndentStyle::Visual, + where_pred_indent: IndentStyle, IndentStyle::Visual, "Indentation style of a where predicate"; generics_style: Style, Style::Default, "Overall strategy for generics"; - generics_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of generics"; - struct_lit_style: StructLitStyle, StructLitStyle::Block, "Style of struct definition"; + generics_indent: IndentStyle, IndentStyle::Visual, "Indentation of generics"; + struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, "Multiline style on literal structs"; report_todo: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; - chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain"; + chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain"; chain_one_line_max: usize, 4, "Maximum number of elements in a chain to fit on a single line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imported_names: bool, false, diff --git a/src/expr.rs b/src/expr.rs index 3d6ec44b8c8..9e1237bd7c2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -24,7 +24,7 @@ use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; use visitor::FmtVisitor; -use config::{Config, StructLitStyle, MultilineStyle, ControlBraceStyle, FnArgLayoutStyle}; +use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::{rewrite_path, PathContext}; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -331,8 +331,8 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let nested_shape = match context.config.array_layout { - FnArgLayoutStyle::Block => shape.block().block_indent(context.config.tab_spaces), - FnArgLayoutStyle::Visual => { + IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces), + IndentStyle::Visual => { try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)) } }; @@ -361,14 +361,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |acc, x| acc.and_then(|y| x.map(|x| x || y)))); let tactic = match context.config.array_layout { - FnArgLayoutStyle::Block => { + IndentStyle::Block => { // TODO wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { Some(width) => definitive_tactic(&items, ListTactic::HorizontalVertical, width), None => DefinitiveListTactic::Vertical, } } - FnArgLayoutStyle::Visual => { + IndentStyle::Visual => { if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) } else { @@ -387,7 +387,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let list_str = try_opt!(write_list(&items, &fmt)); - let result = if context.config.array_layout == FnArgLayoutStyle::Visual || + let result = if context.config.array_layout == IndentStyle::Visual || tactic != DefinitiveListTactic::Vertical { if context.config.spaces_within_square_brackets && list_str.len() > 0 { format!("[ {} ]", list_str) @@ -1734,10 +1734,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // Foo { a: Foo } - indent is +3, width is -5. let h_shape = shape.sub_width(path_str.len() + 5); let v_shape = match context.config.struct_lit_style { - StructLitStyle::Visual => { + IndentStyle::Visual => { try_opt!(try_opt!(shape.shrink_left(path_str.len() + 3)).sub_width(2)) } - StructLitStyle::Block => { + IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces); Shape { width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), @@ -1784,7 +1784,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let tactic = if let Some(h_shape) = h_shape { let mut prelim_tactic = match (context.config.struct_lit_style, fields.len()) { - (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical, + (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style.to_list_tactic(), }; @@ -1802,7 +1802,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, _ => v_shape, }; - let ends_with_newline = context.config.struct_lit_style != StructLitStyle::Visual && + let ends_with_newline = context.config.struct_lit_style != IndentStyle::Visual && tactic == DefinitiveListTactic::Vertical; let fmt = ListFormatting { @@ -1825,7 +1825,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } // One liner or visual indent. - if context.config.struct_lit_style == StructLitStyle::Visual || + if context.config.struct_lit_style == IndentStyle::Visual || (context.config.struct_lit_multiline_style != MultilineStyle::ForceMulti && !fields_str.contains('\n') && fields_str.len() <= h_shape.map(|s| s.width).unwrap_or(0)) { diff --git a/src/items.rs b/src/items.rs index f2650494a82..70063af2694 100644 --- a/src/items.rs +++ b/src/items.rs @@ -21,7 +21,7 @@ use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annota use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, FnArgLayoutStyle, Style}; +use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style}; use itertools::Itertools; use syntax::{ast, abi, codemap, ptr, symbol}; @@ -779,9 +779,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let where_density = if (context.config.where_density == Density::Compressed && - (!result.contains('\n') || - context.config.fn_args_layout == FnArgLayoutStyle::Block)) || - (context.config.fn_args_layout == FnArgLayoutStyle::Block && result.is_empty()) || + (!result.contains('\n') || context.config.fn_args_layout == IndentStyle::Block)) || + (context.config.fn_args_layout == IndentStyle::Block && result.is_empty()) || (context.config.where_density == Density::CompressedIfEmpty && !has_body && !result.contains('\n')) { Density::Compressed @@ -1020,11 +1019,11 @@ fn format_tuple_struct(context: &RewriteContext, }; let (tactic, item_indent) = match context.config.fn_args_layout { - FnArgLayoutStyle::Visual => { + IndentStyle::Visual => { // 1 = `(` (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) } - FnArgLayoutStyle::Block => { + IndentStyle::Block => { (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) } }; @@ -1056,7 +1055,7 @@ fn format_tuple_struct(context: &RewriteContext, context.config, tactic)); - if context.config.fn_args_layout == FnArgLayoutStyle::Visual || !body.contains('\n') { + if context.config.fn_args_layout == IndentStyle::Visual || !body.contains('\n') { result.push('('); if context.config.spaces_within_parens && body.len() > 0 { result.push(' '); @@ -1512,7 +1511,7 @@ fn rewrite_fn_base(context: &RewriteContext, let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = try_opt!(compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace)); - if context.config.fn_args_layout == FnArgLayoutStyle::Block { + if context.config.fn_args_layout == IndentStyle::Block { arg_indent = indent.block_indent(context.config); multi_line_budget = context.config.max_width - arg_indent.width(); } @@ -1566,7 +1565,7 @@ fn rewrite_fn_base(context: &RewriteContext, let multi_line_arg_str = arg_str.contains('\n'); let put_args_in_block = match context.config.fn_args_layout { - FnArgLayoutStyle::Block => multi_line_arg_str || generics_str.contains('\n'), + IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'), _ => false, } && !fd.inputs.is_empty(); @@ -1590,7 +1589,7 @@ fn rewrite_fn_base(context: &RewriteContext, if !ret_str.is_empty() { let ret_should_indent = match context.config.fn_args_layout { // If our args are block layout then we surely must have space. - FnArgLayoutStyle::Block if put_args_in_block => false, + IndentStyle::Block if put_args_in_block => false, _ => { // If we've already gone multi-line, or the return type would push over the max // width, then put the return type on a new line. With the +1 for the signature @@ -1802,8 +1801,8 @@ fn rewrite_args(context: &RewriteContext, } let indent = match context.config.fn_arg_indent { - BlockIndentStyle::Tabbed => indent.block_indent(context.config), - BlockIndentStyle::Visual => arg_indent, + IndentStyle::Block => indent.block_indent(context.config), + IndentStyle::Visual => arg_indent, }; let tactic = definitive_tactic(&arg_items, @@ -1817,7 +1816,7 @@ fn rewrite_args(context: &RewriteContext, debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); let (trailing_comma, end_with_newline) = match context.config.fn_args_layout { - FnArgLayoutStyle::Block => (SeparatorTactic::Vertical, true), + IndentStyle::Block => (SeparatorTactic::Vertical, true), _ => (SeparatorTactic::Never, false), }; @@ -1909,9 +1908,9 @@ fn rewrite_generics(context: &RewriteContext, } let offset = match context.config.generics_indent { - BlockIndentStyle::Tabbed => shape.indent.block_indent(context.config), + IndentStyle::Block => shape.indent.block_indent(context.config), // 1 = < - BlockIndentStyle::Visual => generics_offset + 1, + IndentStyle::Visual => generics_offset + 1, }; let h_budget = try_opt!(shape.width.checked_sub(generics_offset.width() + 2)); @@ -1945,7 +1944,7 @@ fn rewrite_generics(context: &RewriteContext, let list_str = try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); - let result = if context.config.generics_indent != BlockIndentStyle::Visual && + let result = if context.config.generics_indent != IndentStyle::Visual && list_str.contains('\n') { format!("<\n{}{}\n{}>", offset.to_string(context.config), @@ -2074,9 +2073,9 @@ fn rewrite_where_clause(context: &RewriteContext, let extra_indent = Indent::new(context.config.tab_spaces, 0); let offset = match context.config.where_pred_indent { - BlockIndentStyle::Tabbed => shape.indent + extra_indent.block_indent(context.config), + IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), // 6 = "where ".len() - BlockIndentStyle::Visual => shape.indent + extra_indent + 6, + IndentStyle::Visual => shape.indent + extra_indent + 6, }; // FIXME: if where_pred_indent != Visual, then the budgets below might // be out by a char or two. diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 69e9dfd5380..25b2dcf7383 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -9,7 +9,7 @@ fn_args_density = "Tall" fn_args_layout = "Visual" fn_arg_indent = "Visual" where_density = "Tall" -where_indent = "Tabbed" +where_indent = "Block" where_layout = "Vertical" where_pred_indent = "Visual" generics_indent = "Visual" diff --git a/tests/source/chains-indent-tabbed.rs b/tests/source/chains-indent-tabbed.rs index 89bf5bb1a69..7a5afdfc9ef 100644 --- a/tests/source/chains-indent-tabbed.rs +++ b/tests/source/chains-indent-tabbed.rs @@ -1,4 +1,4 @@ -// rustfmt-chain_indent: Tabbed +// rustfmt-chain_indent: Block fn test() { let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index ddd11949580..588a4f25c7b 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,6 +1,6 @@ -// rustfmt-fn_arg_indent: Tabbed -// rustfmt-generics_indent: Tabbed -// rustfmt-where_indent: Tabbed +// rustfmt-fn_arg_indent: Block +// rustfmt-generics_indent: Block +// rustfmt-where_indent: Block // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs index b5df5edddae..e9deff6c327 100644 --- a/tests/source/fn-custom-3.rs +++ b/tests/source/fn-custom-3.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_arg_indent: Tabbed -// rustfmt-generics_indent: Tabbed +// rustfmt-fn_arg_indent: Block +// rustfmt-generics_indent: Block // rustfmt-where_layout: HorizontalVertical // Test different indents. diff --git a/tests/source/fn-custom-4.rs b/tests/source/fn-custom-4.rs index 7b3e4c4a163..009ceb87c2b 100644 --- a/tests/source/fn-custom-4.rs +++ b/tests/source/fn-custom-4.rs @@ -1,4 +1,4 @@ -// rustfmt-where_pred_indent: Tabbed +// rustfmt-where_pred_indent: Block // rustfmt-where_density: Compressed // Test different indents. diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index f7079a3a9cd..fbac1bb1807 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Tabbed +// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index febe0c02db2..e5072b178f2 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-fn_args_layout: Block // rustfmt-fn_args_density: Vertical -// rustfmt-fn_arg_indent: Tabbed +// rustfmt-fn_arg_indent: Block // rustfmt-fn_brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs index 26ab6a89443..5c4d51c0387 100644 --- a/tests/source/fn-custom-8.rs +++ b/tests/source/fn-custom-8.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Tabbed +// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/chains-indent-tabbed.rs b/tests/target/chains-indent-tabbed.rs index 4611b0587ff..8222b1c6ac7 100644 --- a/tests/target/chains-indent-tabbed.rs +++ b/tests/target/chains-indent-tabbed.rs @@ -1,4 +1,4 @@ -// rustfmt-chain_indent: Tabbed +// rustfmt-chain_indent: Block fn test() { let x = my_long_function() diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index 71aecfeab4e..3740cf2a490 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,6 +1,6 @@ -// rustfmt-fn_arg_indent: Tabbed -// rustfmt-generics_indent: Tabbed -// rustfmt-where_indent: Tabbed +// rustfmt-fn_arg_indent: Block +// rustfmt-generics_indent: Block +// rustfmt-where_indent: Block // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 96e82ac91f8..24a8db358e7 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -1,5 +1,5 @@ -// rustfmt-fn_arg_indent: Tabbed -// rustfmt-generics_indent: Tabbed +// rustfmt-fn_arg_indent: Block +// rustfmt-generics_indent: Block // rustfmt-where_layout: HorizontalVertical // Test different indents. diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs index 70ec49f34bc..d2ba91b7632 100644 --- a/tests/target/fn-custom-4.rs +++ b/tests/target/fn-custom-4.rs @@ -1,4 +1,4 @@ -// rustfmt-where_pred_indent: Tabbed +// rustfmt-where_pred_indent: Block // rustfmt-where_density: Compressed // Test different indents. diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 4340e7ac827..af58492497c 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Tabbed +// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index faa47a54060..f29a6b933ca 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-fn_args_layout: Block // rustfmt-fn_args_density: Vertical -// rustfmt-fn_arg_indent: Tabbed +// rustfmt-fn_arg_indent: Block // rustfmt-fn_brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index 0c1c2aaf8f3..d029982728f 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Tabbed +// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. -- cgit 1.4.1-3-g733a5 From d4c5d572c8b02849c194c13cc41366e07d32c9ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 20 Mar 2017 11:59:08 +1300 Subject: Unify fn_args_layout and fn_arg_indent Closes #1390 --- src/config.rs | 1 - src/items.rs | 13 +++++-------- tests/source/fn-custom-2.rs | 2 +- tests/source/fn-custom-3.rs | 2 +- tests/source/fn-custom-7.rs | 1 - tests/target/fn-custom-2.rs | 22 +++++++++++++++------- tests/target/fn-custom-3.rs | 22 +++++++++++++++------- tests/target/fn-custom-7.rs | 1 - 8 files changed, 37 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 0ff5a45e57a..91438a00f08 100644 --- a/src/config.rs +++ b/src/config.rs @@ -341,7 +341,6 @@ create_config! { fn_args_density: Density, Density::Tall, "Argument density in functions"; fn_args_layout: IndentStyle, IndentStyle::Visual, "Layout of function arguments and tuple structs"; - fn_arg_indent: IndentStyle, IndentStyle::Visual, "Indent on function arguments"; array_layout: IndentStyle, IndentStyle::Visual, "Indent on arrays"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; diff --git a/src/items.rs b/src/items.rs index 70063af2694..69acab70f34 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1800,9 +1800,11 @@ fn rewrite_args(context: &RewriteContext, item.item = Some(arg); } - let indent = match context.config.fn_arg_indent { - IndentStyle::Block => indent.block_indent(context.config), - IndentStyle::Visual => arg_indent, + let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout { + IndentStyle::Block => { + (indent.block_indent(context.config), SeparatorTactic::Vertical, true) + } + IndentStyle::Visual => (arg_indent, SeparatorTactic::Never, false), }; let tactic = definitive_tactic(&arg_items, @@ -1815,11 +1817,6 @@ fn rewrite_args(context: &RewriteContext, debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); - let (trailing_comma, end_with_newline) = match context.config.fn_args_layout { - IndentStyle::Block => (SeparatorTactic::Vertical, true), - _ => (SeparatorTactic::Never, false), - }; - let fmt = ListFormatting { tactic: tactic, separator: ",", diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index 588a4f25c7b..4a86f8c2d28 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_arg_indent: Block +// rustfmt-fn_args_layout: Block // rustfmt-generics_indent: Block // rustfmt-where_indent: Block // rustfmt-where_layout: Mixed diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs index e9deff6c327..38c7839a49a 100644 --- a/tests/source/fn-custom-3.rs +++ b/tests/source/fn-custom-3.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_arg_indent: Block +// rustfmt-fn_args_layout: Block // rustfmt-generics_indent: Block // rustfmt-where_layout: HorizontalVertical // Test different indents. diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index e5072b178f2..6ebf4236423 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,7 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-fn_args_layout: Block // rustfmt-fn_args_density: Vertical -// rustfmt-fn_arg_indent: Block // rustfmt-fn_brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index 3740cf2a490..f0251b70b58 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,14 +1,16 @@ -// rustfmt-fn_arg_indent: Block +// rustfmt-fn_args_layout: Block // rustfmt-generics_indent: Block // rustfmt-where_indent: Block // rustfmt-where_layout: Mixed // Test different indents. -fn foo(a: Aaaaaaaaaaaaaaa, +fn foo( + a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee) { + e: Eeeeeeeeeeeeeeeeeee, +) { foo(); } @@ -16,7 +18,9 @@ fn bar< 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW ->(a: Aaaaaaaaaaaaaaa) { +>( + a: Aaaaaaaaaaaaaaa, +) { bar(); } @@ -34,12 +38,14 @@ fn qux() } impl Foo { - fn foo(self, + fn foo( + self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee) { + e: Eeeeeeeeeeeeeeeeeee, + ) { foo(); } @@ -48,7 +54,9 @@ impl Foo { TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW > - (a: Aaaaaaaaaaaaaaa) { + ( + a: Aaaaaaaaaaaaaaa, + ) { bar(); } diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 24a8db358e7..309b1cd7eea 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -1,13 +1,15 @@ -// rustfmt-fn_arg_indent: Block +// rustfmt-fn_args_layout: Block // rustfmt-generics_indent: Block // rustfmt-where_layout: HorizontalVertical // Test different indents. -fn foo(a: Aaaaaaaaaaaaaaa, +fn foo( + a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee) { + e: Eeeeeeeeeeeeeeeeeee, +) { foo(); } @@ -15,7 +17,9 @@ fn bar< 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW ->(a: Aaaaaaaaaaaaaaa) { +>( + a: Aaaaaaaaaaaaaaa, +) { bar(); } @@ -35,12 +39,14 @@ fn qux() } impl Foo { - fn foo(self, + fn foo( + self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee) { + e: Eeeeeeeeeeeeeeeeeee, + ) { foo(); } @@ -49,7 +55,9 @@ impl Foo { TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW > - (a: Aaaaaaaaaaaaaaa) { + ( + a: Aaaaaaaaaaaaaaa, + ) { bar(); } } diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index f29a6b933ca..0f5297e33ed 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,7 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-fn_args_layout: Block // rustfmt-fn_args_density: Vertical -// rustfmt-fn_arg_indent: Block // rustfmt-fn_brace_style: AlwaysNextLine // Case with only one variable. -- cgit 1.4.1-3-g733a5 From bfb1c277a8e5b836b7b2a413bce6b8a056b70d43 Mon Sep 17 00:00:00 2001 From: Robert Gawdzik Date: Tue, 21 Mar 2017 16:00:33 -0400 Subject: Make list_files deterministic (Closes #1141) (#1393) - Use BTreeMap instead --- src/modules.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 6ea2248ed3c..3d2c3b0ac9f 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -11,7 +11,7 @@ use utils; use std::path::{Path, PathBuf}; -use std::collections::HashMap; +use std::collections::BTreeMap; use syntax::ast; use syntax::codemap; @@ -22,8 +22,8 @@ use syntax::parse::parser; /// If a file is used twice in a crate, it appears only once. pub fn list_files<'a>(krate: &'a ast::Crate, codemap: &codemap::CodeMap) - -> HashMap { - let mut result = HashMap::new(); + -> BTreeMap { + let mut result = BTreeMap::new(); // Enforce file order determinism let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); list_submodules(&krate.module, root_filename.parent().unwrap(), @@ -37,7 +37,7 @@ pub fn list_files<'a>(krate: &'a ast::Crate, fn list_submodules<'a>(module: &'a ast::Mod, search_dir: &Path, codemap: &codemap::CodeMap, - result: &mut HashMap) { + result: &mut BTreeMap) { debug!("list_submodules: search_dir: {:?}", search_dir); for item in &module.items { if let ast::ItemKind::Mod(ref sub_mod) = item.node { -- cgit 1.4.1-3-g733a5 From 4bb31a72315806e2a71dab0874132b988d303e60 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 21 Mar 2017 11:23:59 +1300 Subject: Block indenting for struct lit patterns Now follows struct_lit_style (and most other struct_lit_ options). Required a fair bit of refactoring and bug fixes. Fixes #1311 --- rfc-rustfmt.toml | 2 +- src/config.rs | 4 +- src/expr.rs | 160 ++++++++++++++++++------------------------------ src/items.rs | 14 ++--- src/lib.rs | 8 +++ src/lists.rs | 81 +++++++++++++++++++++++- src/patterns.rs | 114 +++++++++++++++++++++------------- tests/source/closure.rs | 8 +++ tests/target/closure.rs | 8 +++ 9 files changed, 244 insertions(+), 155 deletions(-) (limited to 'src') diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml index 11bfda45956..a46692917b8 100644 --- a/rfc-rustfmt.toml +++ b/rfc-rustfmt.toml @@ -1,4 +1,4 @@ fn_args_layout = "Block" array_layout = "Block" where_style = "Rfc" -generics_indent = "Tabbed" +generics_indent = "Block" diff --git a/src/config.rs b/src/config.rs index 91438a00f08..92a5aa7611e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -320,7 +320,7 @@ create_config! { tab_spaces: usize, 4, "Number of spaces per tab"; fn_call_width: usize, 60, "Maximum width of the args of a function call before falling back to vertical formatting"; - struct_lit_width: usize, 16, + struct_lit_width: usize, 18, "Maximum width in the body of a struct lit before falling back to vertical formatting"; struct_variant_width: usize, 35, "Maximum width in the body of a struct variant before falling back to vertical formatting"; @@ -380,7 +380,7 @@ create_config! { wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - closure_block_indent_threshold: isize, 5, "How many lines a closure must have before it is \ + closure_block_indent_threshold: isize, 7, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; space_before_type_annotation: bool, false, "Leave a space before the colon in a type annotation"; diff --git a/src/expr.rs b/src/expr.rs index 9e1237bd7c2..aa4988740dc 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -19,7 +19,8 @@ use {Indent, Shape, Spanned}; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic, ListItem, format_item_list}; + DefinitiveListTactic, definitive_tactic, ListItem, format_item_list, + struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting}; use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; @@ -658,8 +659,7 @@ impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let result = match self.node { ast::StmtKind::Local(ref local) => { - local.rewrite(context, - Shape::legacy(context.config.max_width, shape.indent)) + local.rewrite(context, shape) } ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { @@ -893,7 +893,6 @@ impl<'a> Rewrite for ControlFlow<'a> { block_width }; - // TODO this .block() - not what we want if we are actually visually indented let block_shape = Shape { width: block_width, ..shape }; let block_str = try_opt!(self.block.rewrite(context, block_shape)); @@ -1120,8 +1119,9 @@ fn rewrite_match(context: &RewriteContext, } // `match `cond` {` - let cond_budget = try_opt!(shape.width.checked_sub(8)); - let cond_str = try_opt!(cond.rewrite(context, Shape::legacy(cond_budget, shape.indent + 6))); + let cond_shape = try_opt!(shape.shrink_left(6)); + let cond_shape = try_opt!(cond_shape.sub_width(2)); + let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysSameLine => " ", @@ -1563,7 +1563,11 @@ fn rewrite_call_inner(context: &RewriteContext, let callee = callee.borrow(); // FIXME using byte lens instead of char lens (and probably all over the // place too) - let callee_str = match callee.rewrite(context, Shape { width: max_callee_width, ..shape }) { + let callee_str = match callee.rewrite(context, + Shape { + width: max_callee_width, + ..shape + }) { Some(string) => { if !string.contains('\n') && string.len() > max_callee_width { panic!("{:?} {}", string, max_callee_width); @@ -1731,115 +1735,71 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let path_shape = try_opt!(shape.sub_width(2)); let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape)); - // Foo { a: Foo } - indent is +3, width is -5. - let h_shape = shape.sub_width(path_str.len() + 5); - let v_shape = match context.config.struct_lit_style { - IndentStyle::Visual => { - try_opt!(try_opt!(shape.shrink_left(path_str.len() + 3)).sub_width(2)) - } - IndentStyle::Block => { - let shape = shape.block_indent(context.config.tab_spaces); - Shape { - width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), - ..shape - } - } - }; + if fields.len() == 0 && base.is_none() { + return Some(format!("{} {{}}", path_str)); + } let field_iter = fields.into_iter() .map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); + // Foo { a: Foo } - indent is +3, width is -5. + let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); + + let span_lo = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span.lo, + StructLitField::Base(expr) => { + let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }; + let span_hi = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span.hi, + StructLitField::Base(expr) => expr.span.hi, + }; + let rewrite = |item: &StructLitField| match *item { + StructLitField::Regular(field) => { + // The 1 taken from the v_budget is for the comma. + rewrite_field(context, field, try_opt!(v_shape.sub_width(1))) + } + StructLitField::Base(expr) => { + // 2 = .. + expr.rewrite(context, try_opt!(v_shape.shrink_left(2))).map(|s| format!("..{}", s)) + } + }; + let items = itemize_list(context.codemap, field_iter, "}", - |item| match *item { - StructLitField::Regular(field) => field.span.lo, - StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - }, - |item| match *item { - StructLitField::Regular(field) => field.span.hi, - StructLitField::Base(expr) => expr.span.hi, - }, - |item| { - match *item { - StructLitField::Regular(field) => { - // The 1 taken from the v_budget is for the comma. - rewrite_field(context, field, try_opt!(v_shape.sub_width(1))) - } - StructLitField::Base(expr) => { - // 2 = .. - expr.rewrite(context, try_opt!(v_shape.shrink_left(2))).map(|s| format!("..{}", s)) - } - } - }, + span_lo, + span_hi, + rewrite, context.codemap.span_after(span, "{"), span.hi); let item_vec = items.collect::>(); - let tactic = if let Some(h_shape) = h_shape { - let mut prelim_tactic = match (context.config.struct_lit_style, fields.len()) { - (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => context.config.struct_lit_multiline_style.to_list_tactic(), - }; - - if prelim_tactic == ListTactic::HorizontalVertical && fields.len() > 1 { - prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); - } + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); - definitive_tactic(&item_vec, prelim_tactic, h_shape.width) + let fields_str = try_opt!(write_list(&item_vec, &fmt)); + let fields_str = if context.config.struct_lit_style == IndentStyle::Block && + (fields_str.contains('\n') || + context.config.struct_lit_multiline_style == MultilineStyle::ForceMulti || + fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) { + format!("\n{}{}\n{}", + v_shape.indent.to_string(context.config), + fields_str, + shape.indent.to_string(context.config)) } else { - DefinitiveListTactic::Vertical - }; - - let nested_shape = match tactic { - DefinitiveListTactic::Horizontal => h_shape.unwrap(), - _ => v_shape, - }; - - let ends_with_newline = context.config.struct_lit_style != IndentStyle::Visual && - tactic == DefinitiveListTactic::Vertical; - - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: if base.is_some() { - SeparatorTactic::Never - } else { - context.config.trailing_comma - }, - shape: nested_shape, - ends_with_newline: ends_with_newline, - config: context.config, + // One liner or visual indent. + format!(" {} ", fields_str) }; - let fields_str = try_opt!(write_list(&item_vec, &fmt)); - // Empty struct. - if fields_str.is_empty() { - return Some(format!("{} {{}}", path_str)); - } - - // One liner or visual indent. - if context.config.struct_lit_style == IndentStyle::Visual || - (context.config.struct_lit_multiline_style != MultilineStyle::ForceMulti && - !fields_str.contains('\n') && - fields_str.len() <= h_shape.map(|s| s.width).unwrap_or(0)) { - return Some(format!("{} {{ {} }}", path_str, fields_str)); - } + Some(format!("{} {{{}}}", path_str, fields_str)) - // Multiple lines. - let inner_indent = v_shape.indent.to_string(context.config); - let outer_indent = shape.indent.to_string(context.config); - Some(format!("{} {{\n{}{}\n{}}}", - path_str, - inner_indent, - fields_str, - outer_indent)) // FIXME if context.config.struct_lit_style == Visual, but we run out // of space, we should fall back to BlockIndent. } @@ -1996,7 +1956,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1)); let rhs = ex.rewrite(context, Shape::offset(max_width, - shape.indent.block_only(), + shape.indent, shape.indent.alignment + last_line_width + 1)); fn count_line_breaks(src: &str) -> usize { diff --git a/src/items.rs b/src/items.rs index 69acab70f34..06c5552121f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -37,12 +37,11 @@ impl Rewrite for ast::Local { shape.width, shape.indent); let mut result = "let ".to_owned(); - let pattern_offset = shape.indent + result.len(); - // 1 = ; - let pattern_width = try_opt!(shape.width.checked_sub(pattern_offset.width() + 1)); - let pat_str = try_opt!(self.pat.rewrite(&context, - Shape::legacy(pattern_width, pattern_offset))); + let pat_shape = try_opt!(shape.offset_left(result.len())); + // 1 = ; + let pat_shape = try_opt!(pat_shape.sub_width(1)); + let pat_str = try_opt!(self.pat.rewrite(&context, pat_shape)); result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -71,12 +70,13 @@ impl Rewrite for ast::Local { if let Some(ref ex) = self.init { // 1 = trailing semicolon; - let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1)); + //let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1)); + let nested_shape = try_opt!(shape.sub_width(1)); result = try_opt!(rewrite_assign_rhs(&context, result, ex, - Shape::legacy(budget, shape.indent.block_only()))); + nested_shape)); } result.push(';'); diff --git a/src/lib.rs b/src/lib.rs index f37466bebfc..aa93061602e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -330,6 +330,14 @@ impl Shape { }) } + pub fn offset_left(&self, width: usize) -> Option { + Some(Shape { + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent, + offset: self.offset + width, + }) + } + pub fn used_width(&self) -> usize { self.indent.block_indent + self.offset } diff --git a/src/lists.rs b/src/lists.rs index 5c25c8b1cea..2bdb9cee695 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -15,7 +15,8 @@ use syntax::codemap::{self, CodeMap, BytePos}; use {Indent, Shape}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; -use config::Config; +use config::{Config, IndentStyle}; +use rewrite::RewriteContext; #[derive(Eq, PartialEq, Debug, Copy, Clone)] /// Formatting tactic for lists. This will be cast down to a @@ -502,3 +503,81 @@ fn comment_len(comment: Option<&str>) -> usize { None => 0, } } + +// Compute horizontal and vertical shapes for a struct-lit-like thing. +pub fn struct_lit_shape(shape: Shape, + context: &RewriteContext, + prefix_width: usize, + suffix_width: usize) + -> Option<(Option, Shape)> { + let v_shape = match context.config.struct_lit_style { + IndentStyle::Visual => { + try_opt!(try_opt!(shape.shrink_left(prefix_width)).sub_width(suffix_width)) + } + IndentStyle::Block => { + let shape = shape.block_indent(context.config.tab_spaces); + Shape { + width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), + ..shape + } + } + }; + let h_shape = shape.sub_width(prefix_width + suffix_width); + Some((h_shape, v_shape)) +} + +// Compute the tactic for the internals of a struct-lit-like thing. +pub fn struct_lit_tactic(h_shape: Option, + context: &RewriteContext, + items: &[ListItem]) + -> DefinitiveListTactic { + if let Some(h_shape) = h_shape { + let mut prelim_tactic = match (context.config.struct_lit_style, items.len()) { + (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, + _ => context.config.struct_lit_multiline_style.to_list_tactic(), + }; + + if prelim_tactic == ListTactic::HorizontalVertical && items.len() > 1 { + prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); + } + + definitive_tactic(items, prelim_tactic, h_shape.width) + } else { + DefinitiveListTactic::Vertical + } +} + +// Given a tactic and possible shapes for horizontal and vertical layout, +// come up with the actual shape to use. +pub fn shape_for_tactic(tactic: DefinitiveListTactic, + h_shape: Option, + v_shape: Shape) + -> Shape { + match tactic { + DefinitiveListTactic::Horizontal => h_shape.unwrap(), + _ => v_shape, + } +} + +// Create a ListFormatting object for formatting the internals of a +// struct-lit-like thing, that is a series of fields. +pub fn struct_lit_formatting<'a>(shape: Shape, + tactic: DefinitiveListTactic, + context: &'a RewriteContext, + force_no_trailing_comma: bool) + -> ListFormatting<'a> { + let ends_with_newline = context.config.struct_lit_style != IndentStyle::Visual && + tactic == DefinitiveListTactic::Vertical; + ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: if force_no_trailing_comma { + SeparatorTactic::Never + } else { + context.config.trailing_comma + }, + shape: shape, + ends_with_newline: ends_with_newline, + config: context.config, + } +} diff --git a/src/patterns.rs b/src/patterns.rs index c1b3de56cfb..18def6bfb64 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -10,9 +10,11 @@ use Shape; use codemap::SpanUtils; +use config::{IndentStyle, MultilineStyle}; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; -use lists::{format_item_list, itemize_list, ListItem}; +use lists::{format_item_list, itemize_list, ListItem, struct_lit_shape, struct_lit_tactic, + shape_for_tactic, struct_lit_formatting, write_list}; use expr::{rewrite_unary_prefix, rewrite_pair}; use types::{rewrite_path, PathContext}; use super::Spanned; @@ -112,48 +114,7 @@ impl Rewrite for Pat { wrap_str(result, context.config.max_width, shape) } PatKind::Struct(ref path, ref fields, elipses) => { - let path = try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); - - let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; - - // 5 = `{` plus space before and after plus `}` plus space before. - let budget = try_opt!(shape.width.checked_sub(path.len() + 5 + elipses_str.len())); - // FIXME Using visual indenting, should use block or visual to match - // struct lit preference (however, in practice I think it is rare - // for struct patterns to be multi-line). - // 3 = `{` plus space before and after. - let offset = shape.indent + path.len() + 3; - - let items = - itemize_list(context.codemap, - fields.iter(), - terminator, - |f| f.span.lo, - |f| f.span.hi, - |f| f.node.rewrite(context, Shape::legacy(budget, offset)), - context.codemap.span_after(self.span, "{"), - self.span.hi); - let mut field_string = try_opt!(format_item_list(items, - Shape::legacy(budget, offset), - context.config)); - if elipses { - if field_string.contains('\n') { - field_string.push_str(",\n"); - field_string.push_str(&offset.to_string(context.config)); - field_string.push_str(".."); - } else { - if !field_string.is_empty() { - field_string.push_str(", "); - } - field_string.push_str(".."); - } - } - - if field_string.is_empty() { - Some(format!("{} {{}}", path)) - } else { - Some(format!("{} {{ {} }}", path, field_string)) - } + rewrite_struct_pat(path, fields, elipses, self.span, context, shape) } // FIXME(#819) format pattern macros. PatKind::Mac(..) => { @@ -163,6 +124,72 @@ impl Rewrite for Pat { } } +fn rewrite_struct_pat(path: &ast::Path, + fields: &[codemap::Spanned], + elipses: bool, + span: Span, + context: &RewriteContext, + shape: Shape) + -> Option { + let path_shape = try_opt!(shape.sub_width(2)); + let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape)); + + if fields.len() == 0 && !elipses { + return Some(format!("{} {{}}", path_str)); + } + + let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; + + // 3 = ` { `, 2 = ` }`. + let (h_shape, v_shape) = + try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, elipses_str.len() + 2)); + + let items = itemize_list(context.codemap, + fields.iter(), + terminator, + |f| f.span.lo, + |f| f.span.hi, + |f| f.node.rewrite(context, v_shape), + context.codemap.span_after(span, "{"), + span.hi); + let item_vec = items.collect::>(); + + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, false); + + let mut fields_str = try_opt!(write_list(&item_vec, &fmt)); + + if elipses { + if fields_str.contains('\n') { + fields_str.push_str("\n"); + fields_str.push_str(&nested_shape.indent.to_string(context.config)); + fields_str.push_str(".."); + } else { + if !fields_str.is_empty() { + fields_str.push_str(", "); + } + fields_str.push_str(".."); + } + } + + + let fields_str = if context.config.struct_lit_style == IndentStyle::Block && + (fields_str.contains('\n') || + context.config.struct_lit_multiline_style == MultilineStyle::ForceMulti || + fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) { + format!("\n{}{}\n{}", + v_shape.indent.to_string(context.config), + fields_str, + shape.indent.to_string(context.config)) + } else { + // One liner or visual indent. + format!(" {} ", fields_str) + }; + + Some(format!("{} {{{}}}", path_str, fields_str)) +} + impl Rewrite for FieldPat { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let pat = self.pat.rewrite(context, shape); @@ -176,7 +203,6 @@ impl Rewrite for FieldPat { } } - enum TuplePatField<'a> { Pat(&'a ptr::P), Dotdot(Span), diff --git a/tests/source/closure.rs b/tests/source/closure.rs index b95f961405a..c9968a996f4 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -81,3 +81,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } } + +fn foo() { + lifetimes_iter___map(|lasdfasfd| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + }; + }); +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index a3d9cfe863b..ad6b48aeac9 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -98,3 +98,11 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } } + +fn foo() { + lifetimes_iter___map(|lasdfasfd| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + }; + }); +} -- cgit 1.4.1-3-g733a5 From 488c0b9546ff32234ae5b4d3463ec579e337020b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 22 Mar 2017 09:05:50 +1300 Subject: Test and source fallout --- src/bin/rustfmt.rs | 5 ++++- src/chains.rs | 5 ++++- src/expr.rs | 47 ++++++++++++++++++++++++++++++++++------------ src/imports.rs | 14 +++++++------- src/issues.rs | 5 ++++- src/items.rs | 47 ++++++++++++++++++++++------------------------ src/types.rs | 40 +++++++++++++++++++++++---------------- tests/source/expr.rs | 8 ++++---- tests/target/expr-block.rs | 20 ++++---------------- tests/target/expr.rs | 8 ++++---- tests/target/pattern.rs | 25 +++++++++++++++++------- 11 files changed, 130 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 69a18d14cb5..e97d0219aad 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -219,7 +219,10 @@ fn execute(opts: &Options) -> FmtResult { Ok(run(Input::Text(input), &config)) } - Operation::Format { mut files, config_path } => { + Operation::Format { + mut files, + config_path, + } => { let options = try!(CliOptions::from_matches(&matches)); // Add any additional files that were specified via `--file-lines`. diff --git a/src/chains.rs b/src/chains.rs index 3a3ce74bbb6..4eda33d9647 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -130,7 +130,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .checked_sub(nested_shape.indent.width() + nested_shape.offset)); - let other_child_shape = Shape { width: max_width, ..nested_shape }; + let other_child_shape = Shape { + width: max_width, + ..nested_shape + }; let first_child_shape = if extend { let mut shape = try_opt!(parent_shape.shrink_left(last_line_width(&parent_rewrite))); match context.config.chain_indent { diff --git a/src/expr.rs b/src/expr.rs index aa4988740dc..1df0f2a96d0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -19,8 +19,8 @@ use {Indent, Shape, Spanned}; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic, ListItem, format_item_list, - struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting}; + DefinitiveListTactic, definitive_tactic, ListItem, format_item_list, struct_lit_shape, + struct_lit_tactic, shape_for_tactic, struct_lit_formatting}; use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; @@ -308,7 +308,11 @@ pub fn rewrite_pair(lhs: &LHS, .visual_indent(prefix.len()); let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); - let lhs_result = try_opt!(lhs.rewrite(context, Shape { width: lhs_budget, ..shape })); + let lhs_result = try_opt!(lhs.rewrite(context, + Shape { + width: lhs_budget, + ..shape + })); Some(format!("{}{}{}\n{}{}{}", prefix, lhs_result, @@ -658,9 +662,7 @@ impl Rewrite for ast::Block { impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let result = match self.node { - ast::StmtKind::Local(ref local) => { - local.rewrite(context, shape) - } + ast::StmtKind::Local(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(self) { ";" } else { "" }; @@ -893,7 +895,10 @@ impl<'a> Rewrite for ControlFlow<'a> { block_width }; - let block_shape = Shape { width: block_width, ..shape }; + let block_shape = Shape { + width: block_width, + ..shape + }; let block_str = try_opt!(self.block.rewrite(context, block_shape)); let cond_span = if let Some(cond) = self.cond { @@ -975,7 +980,10 @@ impl<'a> Rewrite for ControlFlow<'a> { last_in_chain = true; // When rewriting a block, the width is only used for single line // blocks, passing 1 lets us avoid that. - let else_shape = Shape { width: min(1, shape.width), ..shape }; + let else_shape = Shape { + width: min(1, shape.width), + ..shape + }; else_block.rewrite(context, else_shape) } }; @@ -1175,7 +1183,11 @@ fn rewrite_match(context: &RewriteContext, } fn arm_start_pos(arm: &ast::Arm) -> BytePos { - let &ast::Arm { ref attrs, ref pats, .. } = arm; + let &ast::Arm { + ref attrs, + ref pats, + .. + } = arm; if !attrs.is_empty() { return attrs[0].span.lo; } @@ -1205,7 +1217,12 @@ fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { debug!("Arm::rewrite {:?} {:?}", self, shape); - let &ast::Arm { ref attrs, ref pats, ref guard, ref body } = self; + let &ast::Arm { + ref attrs, + ref pats, + ref guard, + ref body, + } = self; // FIXME this is all a bit grotty, would be nice to abstract out the // treatment of attributes. @@ -1250,7 +1267,10 @@ impl Rewrite for ast::Arm { let pats_str = try_opt!(write_list(items, &fmt)); let guard_shape = if pats_str.contains('\n') { - Shape { width: context.config.max_width - shape.indent.width(), ..shape } + Shape { + width: context.config.max_width - shape.indent.width(), + ..shape + } } else { shape }; @@ -1598,7 +1618,10 @@ fn rewrite_call_inner(context: &RewriteContext, |item| item.span.hi, |item| { item.rewrite(context, - Shape { width: remaining_width, ..nested_shape }) + Shape { + width: remaining_width, + ..nested_shape + }) }, span.lo, span.hi); diff --git a/src/imports.rs b/src/imports.rs index cafba0bb2c5..4b8f4e9762a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -193,13 +193,13 @@ impl<'a> FmtVisitor<'a> { // before the current `self.last_pos` let pos_before_first_use_item = use_items.first() .map(|p_i| { - cmp::max(self.last_pos, - p_i.attrs - .iter() - .map(|attr| attr.span.lo) - .min() - .unwrap_or(p_i.span.lo)) - }) + cmp::max(self.last_pos, + p_i.attrs + .iter() + .map(|attr| attr.span.lo) + .min() + .unwrap_or(p_i.span.lo)) + }) .unwrap_or(self.last_pos); // Construct a list of pairs, each containing a `use` item and the start of span before // that `use` item. diff --git a/src/issues.rs b/src/issues.rs index e247aad67a0..4819816c4eb 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -98,7 +98,10 @@ impl BadIssueSeeker { // unnumbered TO-DO or FIX-ME. pub fn inspect(&mut self, c: char) -> Option { match self.state { - Seeking::Issue { todo_idx, fixme_idx } => { + Seeking::Issue { + todo_idx, + fixme_idx, + } => { self.state = self.inspect_issue(c, todo_idx, fixme_idx); } Seeking::Number { issue, part } => { diff --git a/src/items.rs b/src/items.rs index 06c5552121f..f5118625822 100644 --- a/src/items.rs +++ b/src/items.rs @@ -73,10 +73,7 @@ impl Rewrite for ast::Local { //let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1)); let nested_shape = try_opt!(shape.sub_width(1)); - result = try_opt!(rewrite_assign_rhs(&context, - result, - ex, - nested_shape)); + result = try_opt!(rewrite_assign_rhs(&context, result, ex, nested_shape)); } result.push(';'); @@ -932,13 +929,13 @@ fn format_struct_struct(context: &RewriteContext, fields.iter(), "}", |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, |field| field.ty.span.hi, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "{"), @@ -1035,13 +1032,13 @@ fn format_tuple_struct(context: &RewriteContext, fields.iter(), ")", |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, |field| field.ty.span.hi, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "("), @@ -1920,13 +1917,13 @@ fn rewrite_generics(context: &RewriteContext, // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - mk_sp(l.lifetime.span.lo, hi) - }); + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(context.codemap, diff --git a/src/types.rs b/src/types.rs index 0162ac851f3..ba6852dbe84 100644 --- a/src/types.rs +++ b/src/types.rs @@ -357,21 +357,21 @@ impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { // TODO: dead spans? let result = match *self { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ref bound_lifetimes, - ref bounded_ty, - ref bounds, - .. }) => { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + ref bound_lifetimes, + ref bounded_ty, + ref bounds, + .. + }) => { let type_str = try_opt!(bounded_ty.rewrite(context, shape)); let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { let lifetime_str: String = try_opt!(bound_lifetimes.iter() - .map(|lt| { - lt.rewrite(context, shape) - }) - .intersperse(Some(", ".to_string())) - .collect()); + .map(|lt| lt.rewrite(context, shape)) + .intersperse(Some(", ".to_string())) + .collect()); // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; @@ -386,7 +386,11 @@ impl Rewrite for ast::WherePredicate { .collect()); if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { - format!("for< {} > {}{}{}", lifetime_str, type_str, colon, bounds_str) + format!("for< {} > {}{}{}", + lifetime_str, + type_str, + colon, + bounds_str) } else { format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) } @@ -405,14 +409,18 @@ impl Rewrite for ast::WherePredicate { format!("{}{}{}", type_str, colon, bounds_str) } } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, - ref bounds, - .. }) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + ref lifetime, + ref bounds, + .. + }) => { try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)) } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, - ref rhs_ty, - .. }) => { + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + ref lhs_ty, + ref rhs_ty, + .. + }) => { let lhs_ty_str = try_opt!(lhs_ty.rewrite(context, shape)); // 3 = " = ".len() let used_width = 3 + lhs_ty_str.len(); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index c0d1e3477e0..11d3fa98f9d 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -174,19 +174,19 @@ fn arrays() { let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; let a =WeightedChoice::new(&mut [Weighted { - weight: x, + weightweight: x, item: 0, }, Weighted { - weight: 1, + weightweight: 1, item: 1, }, Weighted { - weight: x, + weightweight: x, item: 2, }, Weighted { - weight: 1, + weightweight: 1, item: 3, }]); diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 0daa8ff91d6..6f0bbeb3212 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -95,22 +95,10 @@ fn arrays() { ]; let a = WeightedChoice::new(&mut [ - Weighted { - weight: x, - item: 0, - }, - Weighted { - weight: 1, - item: 1, - }, - Weighted { - weight: x, - item: 2, - }, - Weighted { - weight: 1, - item: 3, - }, + Weighted { weight: x, item: 0 }, + Weighted { weight: 1, item: 1 }, + Weighted { weight: x, item: 2 }, + Weighted { weight: 1, item: 3 }, ]); let z = diff --git a/tests/target/expr.rs b/tests/target/expr.rs index d05870086e3..f0788628538 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -174,19 +174,19 @@ fn arrays() { 1]; let a = WeightedChoice::new(&mut [Weighted { - weight: x, + weightweight: x, item: 0, }, Weighted { - weight: 1, + weightweight: 1, item: 1, }, Weighted { - weight: x, + weightweight: x, item: 2, }, Weighted { - weight: 1, + weightweight: 1, item: 3, }]); diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index 36d24170cee..f0cc1c16e14 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -24,13 +24,24 @@ fn main() { let foo {} = 42; let foo { .. } = 42; let foo { x, y: ref foo, .. } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo } = 42; - let foo { x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - .. }; - let foo { x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo }; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. + } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. + }; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + }; } impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { -- cgit 1.4.1-3-g733a5 From 6be61bcdd6252b529f5a14765fb7cb01be943f66 Mon Sep 17 00:00:00 2001 From: C4K3 Date: Sun, 26 Mar 2017 07:12:56 +0200 Subject: Warn on unused config options (#1402) This will make it clear if a user has misspelled a config option, or if an option has been changed/removed. --- src/config.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 92a5aa7611e..78c6b91526f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -238,7 +238,15 @@ macro_rules! create_config { } pub fn from_toml(toml: &str) -> Config { - let parsed = toml.parse().expect("Could not parse TOML"); + let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); + for (key, _) in parsed.as_table().expect("Parsed config was not table") { + match &**key { + $( + stringify!($i) => (), + )+ + _ => msg!("Warning: Unused configuration option {}", key), + } + } let parsed_config:ParsedConfig = match toml::decode(parsed) { Some(decoded) => decoded, None => { -- cgit 1.4.1-3-g733a5 From f96e56c3a024fd6b8e5545e21299cdefe17c5965 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Sun, 26 Mar 2017 01:16:45 -0400 Subject: Avoid extra comma in vertical single-field struct patterns (#1403) * Add (failing) test for #1397 * Fix for #1397 Specifically, we end up double-adding a trailing comma for single-member struct patterns that are arranged vertically. One is added by write_list (since such structs return true for needs_trailing_separator), and another is added by the if in the old code. --- src/patterns.rs | 12 +++++++++--- tests/target/issue-1397.rs | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 tests/target/issue-1397.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 18def6bfb64..8c81a5ef990 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -13,8 +13,8 @@ use codemap::SpanUtils; use config::{IndentStyle, MultilineStyle}; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; -use lists::{format_item_list, itemize_list, ListItem, struct_lit_shape, struct_lit_tactic, - shape_for_tactic, struct_lit_formatting, write_list}; +use lists::{DefinitiveListTactic, format_item_list, itemize_list, ListItem, struct_lit_shape, + struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list}; use expr::{rewrite_unary_prefix, rewrite_pair}; use types::{rewrite_path, PathContext}; use super::Spanned; @@ -167,7 +167,13 @@ fn rewrite_struct_pat(path: &ast::Path, fields_str.push_str(".."); } else { if !fields_str.is_empty() { - fields_str.push_str(", "); + // there are preceeding struct fields being matched on + if fmt.tactic == DefinitiveListTactic::Vertical { + // if the tactic is Vertical, write_list already added a trailing , + fields_str.push_str(" "); + } else { + fields_str.push_str(", "); + } } fields_str.push_str(".."); } diff --git a/tests/target/issue-1397.rs b/tests/target/issue-1397.rs new file mode 100644 index 00000000000..d8cacd61b58 --- /dev/null +++ b/tests/target/issue-1397.rs @@ -0,0 +1,23 @@ +pub enum TransactionState { + Committed(i64), +} + +pub enum Packet { + Transaction { state: TransactionState }, +} + +fn baz(p: Packet) { + loop { + loop { + loop { + loop { + if let Packet::Transaction { + state: TransactionState::Committed(ts, ..), .. + } = p { + unreachable!() + } + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 0dd0cc1941d5ef8222e36d54b0efd38628d589ee Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Sat, 25 Mar 2017 22:21:43 -0700 Subject: Break `use` statements into multiple lines (#1407) This fixes how line lengths for use statements with multiple items don't extend beyond the maximum line length. Fixes #1400 --- src/imports.rs | 14 +++++++------- tests/target/import-fencepost-length.rs | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 tests/target/import-fencepost-length.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 4b8f4e9762a..c83f821d4a8 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -323,8 +323,10 @@ pub fn rewrite_use_list(shape: Shape, _ => (), } - // 2 = {} - let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); + let colons_offset = if path_str.is_empty() { 0 } else { 2 }; + + // 2 = "{}" + let remaining_width = shape.width.checked_sub(path_str.len() + 2 + colons_offset).unwrap_or(0); let mut items = { // Dummy value, see explanation below. @@ -351,20 +353,18 @@ pub fn rewrite_use_list(shape: Shape, items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } - let colons_offset = if path_str.is_empty() { 0 } else { 2 }; let tactic = definitive_tactic(&items[first_index..], ::lists::ListTactic::Mixed, remaining_width); + let fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, - // FIXME This is too conservative, and will not use all width - // available - // (loose 1 column (";")) + // Add one to the indent to account for "{" shape: Shape::legacy(remaining_width, - shape.indent + path_str.len() + 1 + colons_offset), + shape.indent + path_str.len() + colons_offset + 1), ends_with_newline: false, config: context.config, }; diff --git a/tests/target/import-fencepost-length.rs b/tests/target/import-fencepost-length.rs new file mode 100644 index 00000000000..e4f885c09b1 --- /dev/null +++ b/tests/target/import-fencepost-length.rs @@ -0,0 +1,4 @@ +use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; +use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; +use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, + ddddddddd}; -- cgit 1.4.1-3-g733a5 From abca1dededc504eeff7fb31fb2f92e54c7ddae0e Mon Sep 17 00:00:00 2001 From: C4K3 Date: Sun, 26 Mar 2017 07:32:29 +0200 Subject: Add indent_match_arms option (#1404) Makes it optional whether to indent arms in match expressions. Setting this to false may be desirable for people wishing to avoid double-indents, in that if the match arm is a block, the block will cause an extra indentation level, and if it isn't a block but just a single line, it's still easy to see the logic at a glance. This style is preferred in certain other languages with switch statements, e.g. Linux style C and the most common Java style. --- src/config.rs | 2 ++ src/expr.rs | 7 ++++++- tests/source/indent_match_arms.rs | 27 +++++++++++++++++++++++++++ tests/target/indent_match_arms.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/source/indent_match_arms.rs create mode 100644 tests/target/indent_match_arms.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 78c6b91526f..3793e1fd290 100644 --- a/src/config.rs +++ b/src/config.rs @@ -388,6 +388,8 @@ create_config! { wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \ + indentation level as the match keyword"; closure_block_indent_threshold: isize, 7, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; space_before_type_annotation: bool, false, diff --git a/src/expr.rs b/src/expr.rs index 1df0f2a96d0..6ab9e1c3393 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1137,7 +1137,12 @@ fn rewrite_match(context: &RewriteContext, }; let mut result = format!("match {}{}{{", cond_str, block_sep); - let arm_shape = shape.block_indent(context.config.tab_spaces); + let arm_shape = if context.config.indent_match_arms { + shape.block_indent(context.config.tab_spaces) + } else { + shape.block_indent(0) + }; + let arm_indent_str = arm_shape.indent.to_string(context.config); let open_brace_pos = context.codemap.span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), diff --git a/tests/source/indent_match_arms.rs b/tests/source/indent_match_arms.rs new file mode 100644 index 00000000000..ecadbe705ff --- /dev/null +++ b/tests/source/indent_match_arms.rs @@ -0,0 +1,27 @@ +// rustfmt-indent_match_arms: false + +fn main() { + match x { + 1 => "one", + 2 => "two", + 3 => "three", + 4 => "four", + 5 => "five", + _ => "something else", + } + + match x { + 1 => "one", + 2 => "two", + 3 => "three", + 4 => "four", + 5 => match y { + 'a' => 'A', + 'b' => 'B', + 'c' => 'C', + _ => "Nope", + }, + _ => "something else", + } + +} diff --git a/tests/target/indent_match_arms.rs b/tests/target/indent_match_arms.rs new file mode 100644 index 00000000000..60e7b67ceb4 --- /dev/null +++ b/tests/target/indent_match_arms.rs @@ -0,0 +1,29 @@ +// rustfmt-indent_match_arms: false + +fn main() { + match x { + 1 => "one", + 2 => "two", + 3 => "three", + 4 => "four", + 5 => "five", + _ => "something else", + } + + match x { + 1 => "one", + 2 => "two", + 3 => "three", + 4 => "four", + 5 => { + match y { + 'a' => 'A', + 'b' => 'B', + 'c' => 'C', + _ => "Nope", + } + } + _ => "something else", + } + +} -- cgit 1.4.1-3-g733a5 From 548de69d2d767730f15244a66ec4b595efe07786 Mon Sep 17 00:00:00 2001 From: Aaron Lobb Date: Fri, 24 Mar 2017 23:58:34 -0700 Subject: Prevent conversion of empty tuples to unit structs Fixes #1408 --- src/patterns.rs | 93 +++++++++++----------- .../empty-tuple-no-conversion-to-unit-struct.rs | 13 +++ 2 files changed, 59 insertions(+), 47 deletions(-) create mode 100644 tests/target/empty-tuple-no-conversion-to-unit-struct.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 18def6bfb64..7ece118f872 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -260,55 +260,54 @@ fn rewrite_tuple_pat(pats: &[ptr::P], } if pat_vec.is_empty() { - path_str + return Some(format!("{}()", try_opt!(path_str))); + } + // add comma if `(x,)` + let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + + let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); + // 2 = "()".len(), 3 = "(,)".len() + let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); + // 1 = "(".len() + let nested_shape = nested_shape.visual_indent(path_len + 1); + let mut items: Vec<_> = itemize_list(context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, nested_shape), + context.codemap.span_after(span, "("), + span.hi - BytePos(1)) + .collect(); + + // Condense wildcard string suffix into a single .. + let wildcard_suffix_len = count_wildcard_suffix_len(&items); + + let list = if context.config.condense_wildcard_suffices && wildcard_suffix_len >= 2 { + let new_item_count = 1 + pats.len() - wildcard_suffix_len; + items[new_item_count - 1].item = Some("..".to_owned()); + + let da_iter = items.into_iter().take(new_item_count); + try_opt!(format_item_list(da_iter, nested_shape, context.config)) } else { - // add comma if `(x,)` - let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); - - let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); - // 2 = "()".len(), 3 = "(,)".len() - let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); - // 1 = "(".len() - let nested_shape = nested_shape.visual_indent(path_len + 1); - let mut items: Vec<_> = itemize_list(context.codemap, - pat_vec.iter(), - if add_comma { ",)" } else { ")" }, - |item| item.span().lo, - |item| item.span().hi, - |item| item.rewrite(context, nested_shape), - context.codemap.span_after(span, "("), - span.hi - BytePos(1)) - .collect(); - - // Condense wildcard string suffix into a single .. - let wildcard_suffix_len = count_wildcard_suffix_len(&items); - - let list = if context.config.condense_wildcard_suffices && wildcard_suffix_len >= 2 { - let new_item_count = 1 + pats.len() - wildcard_suffix_len; - items[new_item_count - 1].item = Some("..".to_owned()); - - let da_iter = items.into_iter().take(new_item_count); - try_opt!(format_item_list(da_iter, nested_shape, context.config)) - } else { - try_opt!(format_item_list(items.into_iter(), nested_shape, context.config)) - }; + try_opt!(format_item_list(items.into_iter(), nested_shape, context.config)) + }; - match path_str { - Some(path_str) => { - Some(if context.config.spaces_within_parens { - format!("{}( {} )", path_str, list) - } else { - format!("{}({})", path_str, list) - }) - } - None => { - let comma = if add_comma { "," } else { "" }; - Some(if context.config.spaces_within_parens { - format!("( {}{} )", list, comma) - } else { - format!("({}{})", list, comma) - }) - } + match path_str { + Some(path_str) => { + Some(if context.config.spaces_within_parens { + format!("{}( {} )", path_str, list) + } else { + format!("{}({})", path_str, list) + }) + } + None => { + let comma = if add_comma { "," } else { "" }; + Some(if context.config.spaces_within_parens { + format!("( {}{} )", list, comma) + } else { + format!("({}{})", list, comma) + }) } } } diff --git a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs new file mode 100644 index 00000000000..778937b0d56 --- /dev/null +++ b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs @@ -0,0 +1,13 @@ +enum TestEnum { + Arm1(), + Arm2, +} + + +fn foo() { + let test = TestEnum::Arm1; + match test { + TestEnum::Arm1() => {} + TestEnum::Arm2 => {} + } +} -- cgit 1.4.1-3-g733a5 From 8bca85c4b6203dbbb3524dd2139d07621a7a449e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 10:43:46 +1300 Subject: Support block indent for function calls Uses the `fn_call_style` option. Fixes #1358 --- rfc-rustfmt.toml | 1 + src/config.rs | 1 + src/expr.rs | 56 +++++++++++++++++++++++++++----------------- tests/config/small_tabs.toml | 1 - tests/source/expr-block.rs | 33 ++++++++++++++++++++++++++ tests/target/expr-block.rs | 55 ++++++++++++++++++++++++++++++++++++++----- 6 files changed, 119 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml index a46692917b8..914d19d6cb2 100644 --- a/rfc-rustfmt.toml +++ b/rfc-rustfmt.toml @@ -2,3 +2,4 @@ fn_args_layout = "Block" array_layout = "Block" where_style = "Rfc" generics_indent = "Block" +fn_call_style = "Block" diff --git a/src/config.rs b/src/config.rs index 3793e1fd290..11816945f71 100644 --- a/src/config.rs +++ b/src/config.rs @@ -366,6 +366,7 @@ create_config! { struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, "Multiline style on literal structs"; + fn_call_style: IndentStyle, IndentStyle::Visual, "Indentation for function calls, etc."; report_todo: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, diff --git a/src/expr.rs b/src/expr.rs index 6ab9e1c3393..5af8742c3b2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -367,7 +367,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, let tactic = match context.config.array_layout { IndentStyle::Block => { - // TODO wrong shape in one-line case + // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { Some(width) => definitive_tactic(&items, ListTactic::HorizontalVertical, width), None => DefinitiveListTactic::Vertical, @@ -1102,7 +1102,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or(missed_str.len()); if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { // Excessive vertical whitespace before comment should be preserved - // TODO handle vertical whitespace better + // FIXME handle vertical whitespace better result.push('\n'); } let missed_str = missed_str[first..].trim(); @@ -1607,13 +1607,20 @@ fn rewrite_call_inner(context: &RewriteContext, let span = mk_sp(span_lo, span.hi); let used_width = extra_offset(&callee_str, shape); - // 2 is for parens. - let remaining_width = match shape.width.checked_sub(used_width + 2) { + + let nested_shape = match context.config.fn_call_style { + IndentStyle::Block => { + shape.block() + .block_indent(context.config.tab_spaces) + .sub_width(context.config.tab_spaces) + } + // 1 = (, 2 = (). + IndentStyle::Visual => shape.visual_indent(used_width + 1).sub_width(used_width + 2), + }; + let nested_shape = match nested_shape { Some(s) => s, None => return Err(Ordering::Greater), }; - // 1 = ( - let nested_shape = shape.visual_indent(used_width + 1); let arg_count = args.len(); let items = itemize_list(context.codemap, @@ -1621,13 +1628,7 @@ fn rewrite_call_inner(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - |item| { - item.rewrite(context, - Shape { - width: remaining_width, - ..nested_shape - }) - }, + |item| item.rewrite(context, nested_shape), span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1648,7 +1649,6 @@ fn rewrite_call_inner(context: &RewriteContext, // first arguments. if overflow_last { let nested_shape = Shape { - width: remaining_width, indent: nested_shape.indent.block_only(), ..nested_shape }; @@ -1666,7 +1666,7 @@ fn rewrite_call_inner(context: &RewriteContext, let tactic = definitive_tactic(&item_vec, ListTactic::LimitedHorizontalVertical(context.config.fn_call_width), - remaining_width); + nested_shape.width); // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. @@ -1683,7 +1683,10 @@ fn rewrite_call_inner(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::Never, + trailing_separator: match context.config.fn_call_style { + IndentStyle::Visual => SeparatorTactic::Never, + IndentStyle::Block => context.config.trailing_comma, + }, shape: nested_shape, ends_with_newline: false, config: context.config, @@ -1694,11 +1697,22 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Less), }; - Ok(if context.config.spaces_within_parens && list_str.len() > 0 { - format!("{}( {} )", callee_str, list_str) - } else { - format!("{}({})", callee_str, list_str) - }) + let result = if context.config.fn_call_style == IndentStyle::Visual || + !list_str.contains('\n') { + if context.config.spaces_within_parens && list_str.len() > 0 { + format!("{}( {} )", callee_str, list_str) + } else { + format!("{}({})", callee_str, list_str) + } + } else { + format!("{}(\n{}{}\n{})", + callee_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.block().indent.to_string(context.config)) + }; + + Ok(result) } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 25b2dcf7383..57319012bc3 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -7,7 +7,6 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" fn_args_layout = "Visual" -fn_arg_indent = "Visual" where_density = "Tall" where_indent = "Block" where_layout = "Vertical" diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 5e120b8604c..54132ea862a 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -1,4 +1,5 @@ // rustfmt-array_layout: Block +// rustfmt-fn_call_style: Block // Test expressions with block formatting. fn arrays() { @@ -76,3 +77,35 @@ fn arrays() { [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] } + +fn function_calls() { + let items = itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo, + span.hi); + + itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo, + span.hi) +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 6f0bbeb3212..fe393dcad73 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -1,4 +1,5 @@ // rustfmt-array_layout: Block +// rustfmt-fn_call_style: Block // Test expressions with block formatting. fn arrays() { @@ -94,15 +95,57 @@ fn arrays() { 1, ]; - let a = WeightedChoice::new(&mut [ - Weighted { weight: x, item: 0 }, - Weighted { weight: 1, item: 1 }, - Weighted { weight: x, item: 2 }, - Weighted { weight: 1, item: 3 }, - ]); + let a = WeightedChoice::new( + &mut [ + Weighted { weight: x, item: 0 }, + Weighted { weight: 1, item: 1 }, + Weighted { weight: x, item: 2 }, + Weighted { weight: 1, item: 3 }, + ], + ); let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } + +fn function_calls() { + let items = itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo, + span.hi, + ); + + itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo, + span.hi, + ) +} -- cgit 1.4.1-3-g733a5 From 038436919d762bf6fbdd87ce4e824f8c8c0c8822 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 10:50:58 +1300 Subject: Put the second element of a chain on its own line when block formatting. --- src/chains.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4eda33d9647..70e6d951c2d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -113,7 +113,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) }; - (nested_shape, true) + (nested_shape, context.config.chain_indent == IndentStyle::Visual || + parent_rewrite.len() <= context.config.tab_spaces) } else if is_block_expr(&parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. -- cgit 1.4.1-3-g733a5 From e4efa22983a676fc78dafc3d39ff81f062e72120 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 10:58:41 +1300 Subject: Source formatting fallout --- src/bin/cargo-fmt.rs | 9 ++++++--- src/bin/rustfmt.rs | 9 ++++++--- src/chains.rs | 8 +++++--- src/expr.rs | 27 +++++++++++++++++---------- src/imports.rs | 6 ++++-- src/items.rs | 21 ++++++++++++--------- src/lists.rs | 7 ++++--- src/macros.rs | 14 +++++++------- src/missed_spans.rs | 3 ++- src/string.rs | 3 ++- src/types.rs | 50 ++++++++++++++++++++++++++------------------------ src/utils.rs | 6 ++++-- src/visitor.rs | 11 ++++++----- 13 files changed, 101 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index ceb6af93825..bd52f11bbef 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -96,7 +96,8 @@ fn format_crate(verbosity: Verbosity) -> Result { let targets = try!(get_targets()); // Currently only bin and lib files get formatted - let files: Vec<_> = targets.into_iter() + let files: Vec<_> = targets + .into_iter() .filter(|t| t.kind.should_format()) .inspect(|t| if verbosity == Verbosity::Verbose { println!("[{:?}] {:?}", t.kind, t.path) @@ -165,11 +166,13 @@ fn get_targets() -> Result, std::io::Error> { fn target_from_json(jtarget: &Json) -> Target { let jtarget = jtarget.as_object().unwrap(); - let path = PathBuf::from(jtarget.get("src_path") + let path = PathBuf::from(jtarget + .get("src_path") .unwrap() .as_string() .unwrap()); - let kinds = jtarget.get("kind") + let kinds = jtarget + .get("kind") .unwrap() .as_array() .unwrap(); diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index e97d0219aad..1a1c0c99de3 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -226,7 +226,8 @@ fn execute(opts: &Options) -> FmtResult { let options = try!(CliOptions::from_matches(&matches)); // Add any additional files that were specified via `--file-lines`. - files.extend(options.file_lines + files.extend(options + .file_lines .files() .cloned() .map(PathBuf::from)); @@ -338,7 +339,8 @@ fn determine_operation(matches: &Matches) -> FmtResult { } // Read the config_path and convert to parent dir if a file is provided. - let config_path: Option = matches.opt_str("config-path") + let config_path: Option = matches + .opt_str("config-path") .map(PathBuf::from) .and_then(|dir| { if dir.is_file() { @@ -360,7 +362,8 @@ fn determine_operation(matches: &Matches) -> FmtResult { } // We append files from `--file-lines` later in `execute()`. - let files: Vec<_> = matches.free + let files: Vec<_> = matches + .free .iter() .map(PathBuf::from) .collect(); diff --git a/src/chains.rs b/src/chains.rs index 70e6d951c2d..965187c5e07 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -113,8 +113,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) }; - (nested_shape, context.config.chain_indent == IndentStyle::Visual || - parent_rewrite.len() <= context.config.tab_spaces) + (nested_shape, + context.config.chain_indent == IndentStyle::Visual || + parent_rewrite.len() <= context.config.tab_spaces) } else if is_block_expr(&parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. @@ -425,7 +426,8 @@ fn rewrite_method_call(method_name: ast::Ident, format!("::<{}>", type_list.join(", ")) }; - (types.last() + (types + .last() .unwrap() .span .hi, diff --git a/src/expr.rs b/src/expr.rs index 5af8742c3b2..9568842e925 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -360,7 +360,8 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } } - let has_long_item = try_opt!(items.iter() + let has_long_item = try_opt!(items + .iter() .map(|li| li.item.as_ref().map(|s| s.len() > 10)) .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y)))); @@ -1308,7 +1309,8 @@ impl Rewrite for ast::Arm { // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() if shape.width > pat_width + comma.len() + 4 { - let arm_shape = shape.shrink_left(pat_width + 4) + let arm_shape = shape + .shrink_left(pat_width + 4) .unwrap() .sub_width(comma.len()) .unwrap() @@ -1404,7 +1406,8 @@ fn rewrite_guard(context: &RewriteContext, // 4 = ` if `, 5 = ` => {` let overhead = pattern_width + 4 + 5; if overhead < shape.width { - let cond_shape = shape.shrink_left(pattern_width + 4) + let cond_shape = shape + .shrink_left(pattern_width + 4) .unwrap() .sub_width(5) .unwrap(); @@ -1424,7 +1427,8 @@ fn rewrite_guard(context: &RewriteContext, 3)); if let Some(cond_str) = cond_str { return Some(format!("\n{}if {}", - shape.indent + shape + .indent .block_indent(context.config) .to_string(context.config), cond_str)); @@ -1538,7 +1542,8 @@ fn string_requires_rewrite(context: &RewriteContext, string: &str, shape: Shape) -> bool { - if context.codemap + if context + .codemap .lookup_char_pos(span.lo) .col .0 != shape.indent.width() { @@ -1610,7 +1615,8 @@ fn rewrite_call_inner(context: &RewriteContext, let nested_shape = match context.config.fn_call_style { IndentStyle::Block => { - shape.block() + shape + .block() .block_indent(context.config.tab_spaces) .sub_width(context.config.tab_spaces) } @@ -1781,9 +1787,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, return Some(format!("{} {{}}", path_str)); } - let field_iter = fields.into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + let field_iter = + fields.into_iter().map(StructLitField::Regular).chain(base.into_iter() + .map(StructLitField::Base)); // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); @@ -1895,7 +1901,8 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, if items.len() == 1 { // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); - return items.next() + return items + .next() .unwrap() .rewrite(context, nested_shape) .map(|s| if context.config.spaces_within_parens { diff --git a/src/imports.rs b/src/imports.rs index c83f821d4a8..1e9226bd56f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -191,7 +191,8 @@ impl<'a> FmtVisitor<'a> { pub fn format_imports(&mut self, use_items: &[ptr::P]) { // Find the location immediately before the first use item in the run. This must not lie // before the current `self.last_pos` - let pos_before_first_use_item = use_items.first() + let pos_before_first_use_item = use_items + .first() .map(|p_i| { cmp::max(self.last_pos, p_i.attrs @@ -204,7 +205,8 @@ impl<'a> FmtVisitor<'a> { // Construct a list of pairs, each containing a `use` item and the start of span before // that `use` item. let mut last_pos_of_prev_use_item = pos_before_first_use_item; - let mut ordered_use_items = use_items.iter() + let mut ordered_use_items = use_items + .iter() .map(|p_i| { let new_item = (&*p_i, last_pos_of_prev_use_item); last_pos_of_prev_use_item = p_i.span.hi; diff --git a/src/items.rs b/src/items.rs index f5118625822..506db369806 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1129,7 +1129,8 @@ pub fn rewrite_type_alias(context: &RewriteContext, let line_width = last_line_width(&result); // This checked_sub may fail as the extra space after '=' is not taken into account // In that case the budget is set to 0 which will make ty.rewrite retry on a new line - let budget = context.config + let budget = context + .config .max_width .checked_sub(indent.width() + line_width + ";".len()) .unwrap_or(0); @@ -1720,12 +1721,12 @@ fn rewrite_args(context: &RewriteContext, // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. - let min_args = - explicit_self.and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) - .map_or(1, |self_str| { - arg_item_strs[0] = self_str; - 2 - }); + let min_args = explicit_self + .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) + .map_or(1, |self_str| { + arg_item_strs[0] = self_str; + 2 + }); // Comments between args. let mut arg_items = Vec::new(); @@ -1852,7 +1853,8 @@ fn compute_budgets_for_args(context: &RewriteContext, if !newline_brace { used_space += 2; } - let one_line_budget = context.config + let one_line_budget = context + .config .max_width .checked_sub(used_space) .unwrap_or(0); @@ -1962,7 +1964,8 @@ fn rewrite_trait_bounds(context: &RewriteContext, return Some(String::new()); } - let bound_str = try_opt!(bounds.iter() + let bound_str = try_opt!(bounds + .iter() .map(|ty_bound| ty_bound.rewrite(&context, shape)) .intersperse(Some(" + ".to_string())) .collect::>()); diff --git a/src/lists.rs b/src/lists.rs index 2bdb9cee695..1ec1f00073d 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -275,7 +275,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { // 1 = space between item and comment. - let width = formatting.shape + let width = formatting + .shape .width .checked_sub(item_last_line_width + 1) .unwrap_or(1); @@ -397,8 +398,8 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet.find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); + let first = + test_snippet.find(|c: char| !c.is_whitespace()).unwrap_or(test_snippet.len()); // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; diff --git a/src/macros.rs b/src/macros.rs index 607e743380a..f0ddf029aef 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -156,13 +156,13 @@ pub fn rewrite_macro(mac: &ast::Mac, // Format macro invocation as array literal. let extra_offset = macro_name.len(); let shape = try_opt!(shape.shrink_left(extra_offset)); - let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context.codemap - .span_after(mac.span, - original_style.opener()), - mac.span.hi - BytePos(1)), - context, - shape)); + let rewrite = + try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mk_sp(context.codemap.span_after(mac.span, + original_style.opener()), + mac.span.hi - BytePos(1)), + context, + shape)); Some(format!("{}{}", macro_name, rewrite)) } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 1a1371a19ce..3f2d78f35cc 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -83,7 +83,8 @@ impl<'a> FmtVisitor<'a> { let local_end = self.codemap.lookup_byte_offset(span.hi); let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.fm + let big_snippet = &local_begin + .fm .src .as_ref() .unwrap() diff --git a/src/string.rs b/src/string.rs index 8f51b09b6cc..37a569ce67d 100644 --- a/src/string.rs +++ b/src/string.rs @@ -42,7 +42,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; - let mut result = String::with_capacity(stripped_str.len() + let mut result = String::with_capacity(stripped_str + .len() .checked_next_power_of_two() .unwrap_or(usize::max_value())); result.push_str(fmt.opener); diff --git a/src/types.rs b/src/types.rs index ba6852dbe84..9cac8b4a0e0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -206,7 +206,8 @@ fn rewrite_segment(path_context: PathContext, .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let next_span_lo = param_list.last() + let next_span_lo = param_list + .last() .unwrap() .get_span() .hi + BytePos(1); @@ -297,28 +298,28 @@ fn format_function_type<'a, I>(inputs: I, // 1 for ( let offset = shape.indent + 1; let list_lo = context.codemap.span_after(span, "("); - let items = itemize_list(context.codemap, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs.map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), - ")", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo, - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => { - ty.rewrite(context, Shape::legacy(budget, offset)) - } - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, - list_lo, - span.hi); + let items = + itemize_list(context.codemap, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs.map(|i| ArgumentKind::Regular(Box::new(i))).chain(variadic_arg), + ")", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => { + ty.rewrite(context, Shape::legacy(budget, offset)) + } + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi); let list_str = try_opt!(format_fn_args(items, Shape::legacy(budget, offset), context.config)); @@ -680,7 +681,8 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. - result.push_str(&try_opt!(bare_fn.lifetimes + result.push_str(&try_opt!(bare_fn + .lifetimes .iter() .map(|l| { l.rewrite(context, diff --git a/src/utils.rs b/src/utils.rs index 999e1192b5d..1d836d8dc67 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -127,7 +127,8 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { // Find the end of a TyParam #[inline] pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { - typaram.bounds + typaram + .bounds .last() .map_or(typaram.span, |bound| match *bound { ast::RegionTyParamBound(ref lt) => lt.span, @@ -278,7 +279,8 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option FmtVisitor<'a> { return true; } - let outers: Vec<_> = attrs.iter() + let outers: Vec<_> = attrs + .iter() .filter(|a| a.style == ast::AttrStyle::Outer) .cloned() .collect(); @@ -487,10 +488,10 @@ impl<'a> FmtVisitor<'a> { let first = &outers[0]; self.format_missing_with_indent(source!(self, first.span).lo); - let rewrite = outers.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - self.block_indent.width(), - self.block_indent)) + let rewrite = outers + .rewrite(&self.get_context(), + Shape::legacy(self.config.max_width - self.block_indent.width(), + self.block_indent)) .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); -- cgit 1.4.1-3-g733a5 From a079b87e7c7a937bd689e51af5c2c2b4ba690ca7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 11:12:15 +1300 Subject: Use a char len heuristic rather than item count for chain_one_line_max --- src/chains.rs | 4 ++-- src/config.rs | 2 +- tests/source/chains.rs | 1 + tests/target/chains.rs | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 965187c5e07..82b80e963cf 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -165,9 +165,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let almost_total = rewrites[..rewrites.len() - 1].iter().fold(0, |a, b| { a + first_line_width(b) }) + parent_rewrite.len(); + let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len() + 1) + parent_rewrite.len(); - let veto_single_line = if subexpr_list.len() > context.config.chain_one_line_max - 1 { - // -1 above because subexpr_list does not include the parent. + let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 && rewrites.len() > 1 { true } else if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same diff --git a/src/config.rs b/src/config.rs index 11816945f71..9a554659e83 100644 --- a/src/config.rs +++ b/src/config.rs @@ -372,7 +372,7 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain"; - chain_one_line_max: usize, 4, "Maximum number of elements in a chain to fit on a single line"; + chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imported_names: bool, false, "Reorder lists of names in import statements alphabetically"; diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 7fcda72d83d..f0c096faf2b 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,5 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 +// rustfmt-chain_one_line_max: 100 // Test chain formatting. fn main() { diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 8a1b7bfa8fd..2b4a31bf2a3 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,5 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 +// rustfmt-chain_one_line_max: 100 // Test chain formatting. fn main() { -- cgit 1.4.1-3-g733a5 From 5fb1140688ae9e8a0cfc9d90a00f7dad4935e029 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 11:14:47 +1300 Subject: fallout - source reformatting --- src/bin/cargo-fmt.rs | 9 +- src/bin/rustfmt.rs | 5 +- src/chains.rs | 64 ++++++++----- src/codemap.rs | 5 +- src/comment.rs | 11 ++- src/expr.rs | 208 +++++++++++++++++++++++++++++------------ src/file_lines.rs | 28 +++++- src/imports.rs | 31 ++++--- src/issues.rs | 10 +- src/items.rs | 254 ++++++++++++++++++++++++++++++++++----------------- src/lib.rs | 4 +- src/lists.rs | 252 ++++++++++++++++++++++++++++---------------------- src/macros.rs | 33 ++++--- src/missed_spans.rs | 39 ++++---- src/patterns.rs | 52 +++++++---- src/rustfmt_diff.rs | 20 +++- src/string.rs | 5 +- src/types.rs | 109 ++++++++++++---------- src/utils.rs | 25 +++-- src/visitor.rs | 20 ++-- 20 files changed, 752 insertions(+), 432 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index bd52f11bbef..ae40ffc16c9 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -110,7 +110,10 @@ fn format_crate(verbosity: Verbosity) -> Result { fn get_fmt_args() -> Vec { // All arguments after -- are passed to rustfmt - env::args().skip_while(|a| a != "--").skip(1).collect() + env::args() + .skip_while(|a| a != "--") + .skip(1) + .collect() } #[derive(Debug)] @@ -143,7 +146,9 @@ pub struct Target { // Returns a vector of all compile targets of a crate fn get_targets() -> Result, std::io::Error> { let mut targets: Vec = vec![]; - let output = try!(Command::new("cargo").arg("read-manifest").output()); + let output = try!(Command::new("cargo") + .arg("read-manifest") + .output()); if output.status.success() { // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 1a1c0c99de3..a108f9ba8d0 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -311,7 +311,10 @@ fn main() { fn print_usage(opts: &Options, reason: &str) { let reason = format!("{}\nusage: {} [options] ...", reason, - env::args_os().next().unwrap().to_string_lossy()); + env::args_os() + .next() + .unwrap() + .to_string_lossy()); println!("{}", opts.usage(&reason)); } diff --git a/src/chains.rs b/src/chains.rs index 82b80e963cf..568f23e5d72 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -141,7 +141,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - match context.config.chain_indent { IndentStyle::Visual => other_child_shape, IndentStyle::Block => { - shape.offset = shape.offset.checked_sub(context.config.tab_spaces).unwrap_or(0); + shape.offset = shape + .offset + .checked_sub(context.config.tab_spaces) + .unwrap_or(0); shape.indent.block_indent += context.config.tab_spaces; shape } @@ -154,29 +157,39 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - other_child_shape); let child_shape_iter = - Some(first_child_shape).into_iter().chain(::std::iter::repeat(other_child_shape) - .take(subexpr_list.len() - 1)); - let iter = subexpr_list.iter().rev().zip(child_shape_iter); + Some(first_child_shape) + .into_iter() + .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); + let iter = subexpr_list + .iter() + .rev() + .zip(child_shape_iter); let mut rewrites = try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) .collect::>>()); // Total of all items excluding the last. - let almost_total = rewrites[..rewrites.len() - 1].iter().fold(0, |a, b| { - a + first_line_width(b) - }) + parent_rewrite.len(); + let almost_total = rewrites[..rewrites.len() - 1] + .iter() + .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len() + 1) + parent_rewrite.len(); - let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 && rewrites.len() > 1 { + let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 && + rewrites.len() > 1 { true } else if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); let first_span = context.snippet(subexpr_list[1].span); - let last_iter = last_span.chars().take_while(|c| c.is_whitespace()); - - first_span.chars().chain(last_iter).any(|c| c == '\n') + let last_iter = last_span + .chars() + .take_while(|c| c.is_whitespace()); + + first_span + .chars() + .chain(last_iter) + .any(|c| c == '\n') } else { false }; @@ -228,11 +241,13 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // True if the chain is only `?`s. fn chain_only_try(exprs: &[ast::Expr]) -> bool { - exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - }) + exprs + .iter() + .all(|e| if let ast::ExprKind::Try(_) = e.node { + true + } else { + false + }) } pub fn rewrite_try(expr: &ast::Expr, @@ -243,7 +258,9 @@ pub fn rewrite_try(expr: &ast::Expr, let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count)))); Some(format!("{}{}", sub_expr, - iter::repeat("?").take(try_count).collect::())) + iter::repeat("?") + .take(try_count) + .collect::())) } fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { @@ -417,8 +434,10 @@ fn rewrite_method_call(method_name: ast::Ident, let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { - let type_list: Vec<_> = - try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + let type_list: Vec<_> = try_opt!(types + .iter() + .map(|ty| ty.rewrite(context, shape)) + .collect()); let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) @@ -426,12 +445,7 @@ fn rewrite_method_call(method_name: ast::Ident, format!("::<{}>", type_list.join(", ")) }; - (types - .last() - .unwrap() - .span - .hi, - type_str) + (types.last().unwrap().span.hi, type_str) }; let callee_str = format!(".{}{}", method_name, type_str); diff --git a/src/codemap.rs b/src/codemap.rs index 602ab5c98be..d04169c936e 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -26,10 +26,7 @@ pub struct LineRange { impl LineRange { pub fn file_name(&self) -> &str { - self.file - .as_ref() - .name - .as_str() + self.file.as_ref().name.as_str() } } diff --git a/src/comment.rs b/src/comment.rs index e4f9db9f158..3973c7fc048 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -84,7 +84,10 @@ pub fn rewrite_comment(orig: &str, ("// ", "", "// ") }; - let max_chars = shape.width.checked_sub(closer.len() + opener.len()).unwrap_or(1); + let max_chars = shape + .width + .checked_sub(closer.len() + opener.len()) + .unwrap_or(1); let indent_str = shape.indent.to_string(config); let fmt = StringFormat { opener: "", @@ -597,9 +600,9 @@ fn changed_comment_content(orig: &str, new: &str) -> bool { // Cannot write this as a fn since we cannot return types containing closures let code_comment_content = |code| { let slices = UngroupedCommentCodeSlices::new(code); - slices.filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment).flat_map(|(_, _, s)| { - CommentReducer::new(s) - }) + slices + .filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) + .flat_map(|(_, _, s)| CommentReducer::new(s)) }; let res = code_comment_content(orig).ne(code_comment_content(new)); debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", diff --git a/src/expr.rs b/src/expr.rs index 9568842e925..6d05b757d06 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -272,8 +272,10 @@ pub fn rewrite_pair(lhs: &LHS, if let Some(lhs_result) = lhs_result { let mut result = format!("{}{}{}", prefix, lhs_result, infix); - let remaining_width = - shape.width.checked_sub(last_line_width(&result)).unwrap_or(0); + let remaining_width = shape + .width + .checked_sub(last_line_width(&result)) + .unwrap_or(0); if rhs_result.len() <= remaining_width { result.push_str(&rhs_result); @@ -301,9 +303,11 @@ pub fn rewrite_pair(lhs: &LHS, // Re-evaluate the rhs because we have more space now: let infix = infix.trim_right(); - let lhs_budget = try_opt!(context.config.max_width.checked_sub(shape.used_width() + - prefix.len() + - infix.len())); + let lhs_budget = try_opt!(context + .config + .max_width + .checked_sub(shape.used_width() + prefix.len() + + infix.len())); let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())) .visual_indent(prefix.len()); @@ -336,9 +340,15 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let nested_shape = match context.config.array_layout { - IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces), + IndentStyle::Block => { + shape + .block() + .block_indent(context.config.tab_spaces) + } IndentStyle::Visual => { - try_opt!(shape.visual_indent(bracket_size).sub_width(bracket_size * 2)) + try_opt!(shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2)) } }; @@ -450,7 +460,10 @@ fn rewrite_closure(capture: ast::CaptureBy, body.span.lo); let item_vec = arg_items.collect::>(); // 1 = space between arguments and return type. - let horizontal_budget = nested_shape.width.checked_sub(ret_str.len() + 1).unwrap_or(0); + let horizontal_budget = nested_shape + .width + .checked_sub(ret_str.len() + 1) + .unwrap_or(0); let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget); let arg_shape = match tactic { DefinitiveListTactic::Horizontal => try_opt!(arg_shape.sub_width(ret_str.len() + 1)), @@ -579,7 +592,9 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && - (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == + (block_str[1..] + .find(|c: char| !c.is_whitespace()) + .unwrap() == block_str.len() - 2) { "{}".to_owned() } else { @@ -887,7 +902,10 @@ impl<'a> Rewrite for ControlFlow<'a> { label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 }; - let block_width = shape.width.checked_sub(used_width).unwrap_or(0); + let block_width = shape + .width + .checked_sub(used_width) + .unwrap_or(0); // This is used only for the empty block case: `{}`. So, we use 1 if we know // we should avoid the single line case. let block_width = if self.else_block.is_some() || self.nested_if { @@ -910,11 +928,16 @@ impl<'a> Rewrite for ControlFlow<'a> { // for event in event let between_kwd_cond = - mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), - self.pat.map_or(cond_span.lo, |p| if self.matcher.is_empty() { + mk_sp(context + .codemap + .span_after(self.span, self.keyword.trim()), + self.pat + .map_or(cond_span.lo, |p| if self.matcher.is_empty() { p.span.lo } else { - context.codemap.span_before(self.span, self.matcher.trim()) + context + .codemap + .span_before(self.span, self.matcher.trim()) })); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -923,7 +946,10 @@ impl<'a> Rewrite for ControlFlow<'a> { extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + &shape + .indent + .block_only() + .to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style == @@ -936,15 +962,19 @@ impl<'a> Rewrite for ControlFlow<'a> { let mut result = format!("{}{}{}{}{}{}", label_string, self.keyword, - between_kwd_cond_comment.as_ref().map_or(if - pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { - "" - } else { - " " - }, - |s| &**s), + between_kwd_cond_comment + .as_ref() + .map_or(if pat_expr_string.is_empty() || + pat_expr_string.starts_with('\n') { + "" + } else { + " " + }, + |s| &**s), pat_expr_string, - after_cond_comment.as_ref().map_or(block_sep, |s| &**s), + after_cond_comment + .as_ref() + .map_or(block_sep, |s| &**s), block_str); if let Some(else_block) = self.else_block { @@ -991,15 +1021,17 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_else_block = mk_sp(self.block.span.hi, - context.codemap.span_before(mk_sp(self.block.span.hi, else_block.span.lo), - "else")); + context + .codemap + .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else")); let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); - let after_else = mk_sp(context.codemap.span_after(mk_sp(self.block.span.hi, - else_block.span.lo), - "else"), - else_block.span.lo); + let after_else = + mk_sp(context + .codemap + .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), + else_block.span.lo); let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style { @@ -1013,8 +1045,12 @@ impl<'a> Rewrite for ControlFlow<'a> { }; try_opt!(write!(&mut result, "{}else{}", - between_kwd_else_block_comment.as_ref().map_or(between_sep, |s| &**s), - after_else_comment.as_ref().map_or(after_sep, |s| &**s)) + between_kwd_else_block_comment + .as_ref() + .map_or(between_sep, |s| &**s), + after_else_comment + .as_ref() + .map_or(after_sep, |s| &**s)) .ok()); result.push_str(&try_opt!(rewrite)); } @@ -1096,12 +1132,19 @@ fn rewrite_match_arm_comment(context: &RewriteContext, let mut result = String::new(); // any text not preceeded by a newline is pushed unmodified to the block - let first_brk = missed_str.find(|c: char| c == '\n').unwrap_or(0); + let first_brk = missed_str + .find(|c: char| c == '\n') + .unwrap_or(0); result.push_str(&missed_str[..first_brk]); let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it - let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or(missed_str.len()); - if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { + let first = missed_str + .find(|c: char| !c.is_whitespace()) + .unwrap_or(missed_str.len()); + if missed_str[..first] + .chars() + .filter(|c| c == &'\n') + .count() >= 2 { // Excessive vertical whitespace before comment should be preserved // FIXME handle vertical whitespace better result.push('\n'); @@ -1131,7 +1174,11 @@ fn rewrite_match(context: &RewriteContext, let cond_shape = try_opt!(shape.shrink_left(6)); let cond_shape = try_opt!(cond_shape.sub_width(2)); let cond_str = try_opt!(cond.rewrite(context, cond_shape)); - let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = String::from("\n") + + &shape + .indent + .block_only() + .to_string(context.config); let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysSameLine => " ", _ => alt_block_sep.as_str(), @@ -1146,8 +1193,9 @@ fn rewrite_match(context: &RewriteContext, let arm_indent_str = arm_shape.indent.to_string(context.config); - let open_brace_pos = context.codemap.span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), - "{"); + let open_brace_pos = context + .codemap + .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. @@ -1257,7 +1305,10 @@ impl Rewrite for ast::Arm { .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let items: Vec<_> = pat_strs + .into_iter() + .map(ListItem::from_str) + .collect(); let fmt = ListFormatting { tactic: if all_simple { DefinitiveListTactic::Mixed @@ -1303,7 +1354,10 @@ impl Rewrite for ast::Arm { let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + &shape + .indent + .block_only() + .to_string(context.config); let pat_width = extra_offset(&pats_str, shape); // Let's try and get the arm body on the same line as the condition. @@ -1347,7 +1401,10 @@ impl Rewrite for ast::Arm { .block_indent(context.config.tab_spaces); let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape), body_shape.width)); - let indent_str = shape.indent.block_indent(context.config).to_string(context.config); + let indent_str = shape + .indent + .block_indent(context.config) + .to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms { if context.config.match_block_trailing_comma { ("{", "},") @@ -1390,7 +1447,10 @@ impl Rewrite for ast::Arm { // E.g. `Foo::Bar` is simple, but `Foo(..)` is not. fn pat_is_simple(pat_str: &str) -> bool { pat_str.len() <= 16 || - (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) + (pat_str.len() <= 24 && + pat_str + .chars() + .all(|c| c.is_alphabetic() || c == ':')) } // The `if ...` guard on a match arm. @@ -1418,7 +1478,10 @@ fn rewrite_guard(context: &RewriteContext, } // Not enough space to put the guard after the pattern, try a newline. - let overhead = shape.indent.block_indent(context.config).width() + 4 + 5; + let overhead = shape + .indent + .block_indent(context.config) + .width() + 4 + 5; if overhead < shape.width { let cond_str = guard.rewrite(context, Shape::legacy(shape.width - overhead, @@ -1493,7 +1556,10 @@ fn rewrite_pat_expr(context: &RewriteContext, } } - let nested_indent = shape.indent.block_only().block_indent(context.config); + let nested_indent = shape + .indent + .block_only() + .block_indent(context.config); // The expression won't fit on the current line, jump to next. result.push('\n'); @@ -1621,7 +1687,11 @@ fn rewrite_call_inner(context: &RewriteContext, .sub_width(context.config.tab_spaces) } // 1 = (, 2 = (). - IndentStyle::Visual => shape.visual_indent(used_width + 1).sub_width(used_width + 2), + IndentStyle::Visual => { + shape + .visual_indent(used_width + 1) + .sub_width(used_width + 2) + } }; let nested_shape = match nested_shape { Some(s) => s, @@ -1658,7 +1728,9 @@ fn rewrite_call_inner(context: &RewriteContext, indent: nested_shape.indent.block_only(), ..nested_shape }; - let rewrite = args.last().unwrap().rewrite(context, nested_shape); + let rewrite = args.last() + .unwrap() + .rewrite(context, nested_shape); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); @@ -1749,7 +1821,10 @@ fn rewrite_index(expr: &ast::Expr, ("[", "]") }; - let budget = shape.width.checked_sub(expr_str.len() + lbr.len() + rbr.len()).unwrap_or(0); + let budget = shape + .width + .checked_sub(expr_str.len() + lbr.len() + rbr.len()) + .unwrap_or(0); let index_str = index.rewrite(context, Shape::legacy(budget, shape.indent)); if let Some(index_str) = index_str { return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); @@ -1759,8 +1834,10 @@ fn rewrite_index(expr: &ast::Expr, let indent = indent.to_string(&context.config); // FIXME this is not right, since we don't take into account that shape.width // might be reduced from max_width by something on the right. - let budget = try_opt!(context.config.max_width.checked_sub(indent.len() + lbr.len() + - rbr.len())); + let budget = try_opt!(context + .config + .max_width + .checked_sub(indent.len() + lbr.len() + rbr.len())); let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr)) } @@ -1787,9 +1864,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, return Some(format!("{} {{}}", path_str)); } - let field_iter = - fields.into_iter().map(StructLitField::Regular).chain(base.into_iter() - .map(StructLitField::Base)); + let field_iter = fields + .into_iter() + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); @@ -1797,7 +1875,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let span_lo = |item: &StructLitField| match *item { StructLitField::Regular(field) => field.span.lo, StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); + let last_field_hi = fields + .last() + .map_or(span.lo, |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) @@ -1814,7 +1894,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(context, try_opt!(v_shape.shrink_left(2))).map(|s| format!("..{}", s)) + expr.rewrite(context, try_opt!(v_shape.shrink_left(2))) + .map(|s| format!("..{}", s)) } }; @@ -1876,11 +1957,14 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Some(e) => Some(format!("{}{}{}", name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); - let expr = field.expr.rewrite(context, - Shape::legacy(try_opt!(context.config + let expr = field + .expr + .rewrite(context, + Shape::legacy(try_opt!(context + .config .max_width .checked_sub(expr_offset.width())), - expr_offset)); + expr_offset)); expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) } } @@ -1937,7 +2021,9 @@ pub fn rewrite_unary_prefix(context: &RewriteContext, shape: Shape) -> Option { let shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); - rewrite.rewrite(context, shape).map(|r| format!("{}{}", prefix, r)) + rewrite + .rewrite(context, shape) + .map(|r| format!("{}{}", prefix, r)) } // FIXME: this is probably not correct for multi-line Rewrites. we should @@ -1947,10 +2033,12 @@ pub fn rewrite_unary_suffix(context: &RewriteContext, rewrite: &R, shape: Shape) -> Option { - rewrite.rewrite(context, try_opt!(shape.sub_width(suffix.len()))).map(|mut r| { - r.push_str(suffix); - r - }) + rewrite + .rewrite(context, try_opt!(shape.sub_width(suffix.len()))) + .map(|mut r| { + r.push_str(suffix); + r + }) } fn rewrite_unary_op(context: &RewriteContext, diff --git a/src/file_lines.rs b/src/file_lines.rs index 145713ee1ec..664d101a483 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -89,7 +89,10 @@ pub struct FileLines(Option>); fn normalize_ranges(map: &mut MultiMap) { for (_, ranges) in map.iter_all_mut() { ranges.sort_by_key(|x| x.lo); - let merged = ranges.drain(..).coalesce(|x, y| x.merge(y).ok_or((x, y))).collect(); + let merged = ranges + .drain(..) + .coalesce(|x, y| x.merge(y).ok_or((x, y))) + .collect(); *ranges = merged; } } @@ -124,7 +127,11 @@ impl FileLines { map.get_vec(&canonical) .ok_or(()) }) { - Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + Ok(ranges) => { + ranges + .iter() + .any(|r| r.contains(Range::from(range))) + } Err(_) => false, } } @@ -139,7 +146,11 @@ impl FileLines { match map.get_vec(range.file_name()) { None => false, - Some(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), + Some(ranges) => { + ranges + .iter() + .any(|r| r.intersects(Range::from(range))) + } } } } @@ -157,7 +168,12 @@ impl<'a> iter::Iterator for Files<'a> { fn canonicalize_path_string(s: &str) -> Result { match path::PathBuf::from(s).canonicalize() { - Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()).ok_or(()), + Ok(canonicalized) => { + canonicalized + .to_str() + .map(|s| s.to_string()) + .ok_or(()) + } _ => Err(()), } } @@ -168,7 +184,9 @@ impl str::FromStr for FileLines { fn from_str(s: &str) -> Result { let v: Vec = try!(json::decode(s).map_err(|e| e.to_string())); - let m = try!(v.into_iter().map(JsonSpan::into_tuple).collect()); + let m = try!(v.into_iter() + .map(JsonSpan::into_tuple) + .collect()); Ok(FileLines::from_multimap(m)) } } diff --git a/src/imports.rs b/src/imports.rs index 1e9226bd56f..e99afea9c6f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -46,14 +46,8 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { } fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Ordering { - let a_name_str = &*a.node - .name - .name - .as_str(); - let b_name_str = &*b.node - .name - .name - .as_str(); + let a_name_str = &*a.node.name.name.as_str(); + let b_name_str = &*b.node.name.name.as_str(); let name_ordering = if a_name_str == "self" { if b_name_str == "self" { Ordering::Equal @@ -71,7 +65,12 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde match a.node.rename { Some(a_rename) => { match b.node.rename { - Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), + Some(b_rename) => { + a_rename + .name + .as_str() + .cmp(&b_rename.name.as_str()) + } None => Ordering::Greater, } } @@ -174,10 +173,7 @@ impl Rewrite for ast::ViewPath { let prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4)); let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); - Some(if path.segments - .last() - .unwrap() - .identifier == ident { + Some(if path.segments.last().unwrap().identifier == ident { path_str } else { format!("{} as {}", path_str, ident_str) @@ -328,7 +324,10 @@ pub fn rewrite_use_list(shape: Shape, let colons_offset = if path_str.is_empty() { 0 } else { 2 }; // 2 = "{}" - let remaining_width = shape.width.checked_sub(path_str.len() + 2 + colons_offset).unwrap_or(0); + let remaining_width = shape + .width + .checked_sub(path_str.len() + 2 + colons_offset) + .unwrap_or(0); let mut items = { // Dummy value, see explanation below. @@ -381,7 +380,9 @@ pub fn rewrite_use_list(shape: Shape, // Returns true when self item was found. fn move_self_to_front(items: &mut Vec) -> bool { - match items.iter().position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) { + match items + .iter() + .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) { Some(pos) => { items[0] = items.remove(pos); true diff --git a/src/issues.rs b/src/issues.rs index 4819816c4eb..968faedd7c4 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -225,12 +225,15 @@ fn find_unnumbered_issue() { fn check_fail(text: &str, failing_pos: usize) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); assert_eq!(Some(failing_pos), - text.chars().position(|c| seeker.inspect(c).is_some())); + text.chars() + .position(|c| seeker.inspect(c).is_some())); } fn check_pass(text: &str) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); + assert_eq!(None, + text.chars() + .position(|c| seeker.inspect(c).is_some())); } check_fail("TODO\n", 4); @@ -250,7 +253,8 @@ fn find_unnumbered_issue() { fn find_issue() { fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); - text.chars().any(|c| seeker.inspect(c).is_some()) + text.chars() + .any(|c| seeker.inspect(c).is_some()) } assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n", diff --git a/src/items.rs b/src/items.rs index 506db369806..cd5e4b485d3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -139,7 +139,8 @@ impl<'a> FmtVisitor<'a> { self.format_missing_no_indent(item.span.hi - BytePos(1)); self.block_indent = self.block_indent.block_unindent(self.config); - self.buffer.push_str(&self.block_indent.to_string(self.config)); + self.buffer + .push_str(&self.block_indent.to_string(self.config)); } else { for item in &item.body { self.format_body_element(item); @@ -241,7 +242,9 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let block_snippet = self.snippet(codemap::mk_sp(block.span.lo, block.span.hi)); - let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || + let has_body = !block_snippet[1..block_snippet.len() - 1] + .trim() + .is_empty() || !context.config.fn_empty_single_line; let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, @@ -277,7 +280,8 @@ impl<'a> FmtVisitor<'a> { result.push(' '); } - self.single_line_fn(&result, block).or_else(|| Some(result)) + self.single_line_fn(&result, block) + .or_else(|| Some(result)) } pub fn rewrite_required_fn(&mut self, @@ -366,7 +370,8 @@ impl<'a> FmtVisitor<'a> { enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span) { - self.buffer.push_str(&format_header("enum ", ident, vis)); + self.buffer + .push_str(&format_header("enum ", ident, vis)); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); @@ -400,7 +405,8 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_unindent(self.config); if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - self.buffer.push_str(&self.block_indent.to_string(self.config)); + self.buffer + .push_str(&self.block_indent.to_string(self.config)); } self.buffer.push_str("}"); self.last_pos = span.hi; @@ -458,10 +464,13 @@ impl<'a> FmtVisitor<'a> { } let indent = self.block_indent; - let mut result = try_opt!(field.node.attrs.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - indent.width(), - indent))); + let mut result = try_opt!(field + .node + .attrs + .rewrite(&self.get_context(), + Shape::legacy(self.config.max_width - + indent.width(), + indent))); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -518,7 +527,10 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - } result.push_str(&ref_and_type); - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let where_budget = try_opt!(context + .config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config.item_brace_style, @@ -572,7 +584,9 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = offset.block_only().block_indent(context.config); + visitor.block_indent = offset + .block_only() + .block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in items { @@ -651,7 +665,10 @@ fn format_impl_ref_and_type(context: &RewriteContext, result.push_str(" "); } let used_space = last_line_width(&result); - let budget = try_opt!(context.config.max_width.checked_sub(used_space)); + let budget = try_opt!(context + .config + .max_width + .checked_sub(used_space)); let indent = offset + used_space; result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent)))); @@ -681,7 +698,10 @@ fn format_impl_ref_and_type(context: &RewriteContext, } // 1 = space before the type. - let budget = try_opt!(context.config.max_width.checked_sub(used_space + 1)); + let budget = try_opt!(context + .config + .max_width + .checked_sub(used_space + 1)); let indent = offset + result.len() + 1; let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent)); if let Some(self_ty_str) = self_ty_str { @@ -693,7 +713,10 @@ fn format_impl_ref_and_type(context: &RewriteContext, // Can't fit the self type on what's left of the line, so start a new one. let indent = offset.block_indent(context.config); result.push_str(&format!("\n{}", indent.to_string(context.config))); - let budget = try_opt!(context.config.max_width.checked_sub(indent.width())); + let budget = try_opt!(context + .config + .max_width + .checked_sub(indent.width())); result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, indent)))); Some(result) } else { @@ -767,7 +790,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if offset.width() + last_line_width(&result) + trait_bound_str.len() > context.config.comment_width { result.push('\n'); - let trait_indent = offset.block_only().block_indent(context.config); + let trait_indent = offset + .block_only() + .block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); } result.push_str(&trait_bound_str); @@ -785,7 +810,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) Density::Tall }; - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let where_budget = try_opt!(context + .config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config.item_brace_style, @@ -832,7 +860,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = offset.block_only().block_indent(context.config); + visitor.block_indent = offset + .block_only() + .block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in trait_items { @@ -908,7 +938,9 @@ fn format_struct_struct(context: &RewriteContext, let snippet = context.snippet(mk_sp(body_lo, span.hi - BytePos(1))); if snippet.trim().is_empty() { // `struct S {}` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { + } else if snippet + .trim_right_matches(&[' ', '\t'][..]) + .ends_with('\n') { // fix indent result.push_str(&snippet.trim_right()); result.push('\n'); @@ -922,7 +954,10 @@ fn format_struct_struct(context: &RewriteContext, let item_indent = offset.block_indent(context.config); // 1 = "," - let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 1)); + let item_budget = try_opt!(context + .config + .max_width + .checked_sub(item_indent.width() + 1)); let items = itemize_list(context.codemap, @@ -963,7 +998,9 @@ fn format_struct_struct(context: &RewriteContext, } else { Some(format!("{}\n{}{}\n{}}}", result, - offset.block_indent(context.config).to_string(context.config), + offset + .block_indent(context.config) + .to_string(context.config), items_str, offset.to_string(context.config))) } @@ -1000,8 +1037,10 @@ fn format_tuple_struct(context: &RewriteContext, mk_sp(span.lo, body_lo))); result.push_str(&generics_str); - let where_budget = - try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let where_budget = try_opt!(context + .config + .max_width + .checked_sub(last_line_width(&result))); try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config.item_brace_style, @@ -1021,11 +1060,17 @@ fn format_tuple_struct(context: &RewriteContext, (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) } IndentStyle::Block => { - (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) + (ListTactic::HorizontalVertical, + offset + .block_only() + .block_indent(&context.config)) } }; // 3 = `();` - let item_budget = try_opt!(context.config.max_width.checked_sub(item_indent.width() + 3)); + let item_budget = try_opt!(context + .config + .max_width + .checked_sub(item_indent.width() + 3)); let items = itemize_list(context.codemap, @@ -1043,9 +1088,11 @@ fn format_tuple_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "("), span.hi); - let body_budget = try_opt!(context.config.max_width.checked_sub(offset.block_only().width() + - result.len() + - 3)); + let body_budget = try_opt!(context + .config + .max_width + .checked_sub(offset.block_only().width() + result.len() + + 3)); let body = try_opt!(list_helper(items, // TODO budget is wrong in block case Shape::legacy(body_budget, item_indent), @@ -1113,7 +1160,10 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&generics_str); - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let where_budget = try_opt!(context + .config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config.item_brace_style, @@ -1136,7 +1186,8 @@ pub fn rewrite_type_alias(context: &RewriteContext, .unwrap_or(0); let type_indent = indent + line_width; // Try to fit the type on the same line - let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)).or_else(|| { + let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)) + .or_else(|| { // The line was too short, try to put the type on the next line // Remove the space after '=' @@ -1144,8 +1195,10 @@ pub fn rewrite_type_alias(context: &RewriteContext, let type_indent = indent.block_indent(context.config); result.push('\n'); result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context.config.max_width.checked_sub(type_indent.width() + - ";".len())); + let budget = try_opt!(context + .config + .max_width + .checked_sub(type_indent.width() + ";".len())); ty.rewrite(context, Shape::legacy(budget, type_indent)) })); result.push_str(&ty_str); @@ -1175,10 +1228,11 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); - let mut attr_str = try_opt!(self.attrs.rewrite(context, - Shape::legacy(context.config.max_width - - shape.indent.width(), - shape.indent))); + let mut attr_str = try_opt!(self.attrs + .rewrite(context, + Shape::legacy(context.config.max_width - + shape.indent.width(), + shape.indent))); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&shape.indent.to_string(context.config)); @@ -1199,9 +1253,10 @@ impl Rewrite for ast::StructField { let last_line_width = last_line_width(&result); let budget = try_opt!(shape.width.checked_sub(last_line_width)); - let rewrite = try_opt!(self.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + last_line_width))); + let rewrite = try_opt!(self.ty + .rewrite(context, + Shape::legacy(budget, + shape.indent + last_line_width))); Some(result + &rewrite) } } @@ -1305,9 +1360,8 @@ impl Rewrite for ast::FunctionRetTy { ast::FunctionRetTy::Default(_) => Some(String::new()), ast::FunctionRetTy::Ty(ref ty) => { let inner_width = try_opt!(shape.width.checked_sub(3)); - ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)).map(|r| { - format!("-> {}", r) - }) + ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) + .map(|r| format!("-> {}", r)) } } } @@ -1316,21 +1370,25 @@ impl Rewrite for ast::FunctionRetTy { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!(self.pat.rewrite(context, - Shape::legacy(shape.width, shape.indent))); + let mut result = try_opt!(self.pat + .rewrite(context, + Shape::legacy(shape.width, shape.indent))); if self.ty.node != ast::TyKind::Infer { if context.config.space_before_type_annotation { result.push_str(" "); } result.push_str(":"); - if context.config.space_after_type_annotation_colon { + if context + .config + .space_after_type_annotation_colon { result.push_str(" "); } let max_width = try_opt!(shape.width.checked_sub(result.len())); - let ty_str = try_opt!(self.ty.rewrite(context, - Shape::legacy(max_width, - shape.indent + result.len()))); + let ty_str = try_opt!(self.ty + .rewrite(context, + Shape::legacy(max_width, + shape.indent + result.len()))); result.push_str(&ty_str); } @@ -1497,10 +1555,11 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. - let ret_str = try_opt!(fd.output.rewrite(&context, - Shape::legacy(context.config.max_width - - indent.width(), - indent))); + let ret_str = try_opt!(fd.output + .rewrite(&context, + Shape::legacy(context.config.max_width - + indent.width(), + indent))); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -1547,8 +1606,13 @@ fn rewrite_fn_base(context: &RewriteContext, } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics.ty_params.last().map_or(span.lo, |tp| end_typaram(tp)); - let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("), + let args_start = generics + .ty_params + .last() + .map_or(span.lo, |tp| end_typaram(tp)); + let args_span = mk_sp(context + .codemap + .span_after(mk_sp(args_start, span.hi), "("), span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, &fd.inputs, @@ -1631,8 +1695,12 @@ fn rewrite_fn_base(context: &RewriteContext, if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); - let ret_str = try_opt!(fd.output.rewrite(context, Shape::legacy(budget, ret_indent))); + let budget = try_opt!(context + .config + .max_width + .checked_sub(ret_indent.width())); + let ret_str = try_opt!(fd.output + .rewrite(context, Shape::legacy(budget, ret_indent))); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -1662,7 +1730,10 @@ fn rewrite_fn_base(context: &RewriteContext, } || (put_args_in_block && ret_str.is_empty()); if where_clause.predicates.len() == 1 && should_compress_where { - let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let budget = try_opt!(context + .config + .max_width + .checked_sub(last_line_width(&result))); if let Some(where_clause_str) = rewrite_where_clause(context, where_clause, @@ -1685,7 +1756,10 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let budget = try_opt!(context.config.max_width.checked_sub(indent.block_indent)); + let budget = try_opt!(context + .config + .max_width + .checked_sub(indent.block_indent)); let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, context.config.fn_brace_style, @@ -1747,7 +1821,9 @@ fn rewrite_args(context: &RewriteContext, }; let reduced_span = mk_sp(span.lo, second_arg_start); - context.codemap.span_after_last(reduced_span, ",") + context + .codemap + .span_after_last(reduced_span, ",") } else { span.lo }; @@ -1758,13 +1834,10 @@ fn rewrite_args(context: &RewriteContext, } let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last() - .unwrap() - .ty - .span - .hi, - span.hi); - let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); + let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); + let variadic_start = context + .codemap + .span_after(variadic_span, "...") - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { None @@ -1806,7 +1879,10 @@ fn rewrite_args(context: &RewriteContext, }; let tactic = definitive_tactic(&arg_items, - context.config.fn_args_density.to_list_tactic(), + context + .config + .fn_args_density + .to_list_tactic(), one_line_budget); let budget = match tactic { DefinitiveListTactic::Horizontal => one_line_budget, @@ -1861,8 +1937,11 @@ fn compute_budgets_for_args(context: &RewriteContext, if one_line_budget > 0 { // 4 = "() {".len() - let multi_line_budget = - try_opt!(context.config.max_width.checked_sub(indent.width() + result.len() + 4)); + let multi_line_budget = try_opt!(context + .config + .max_width + .checked_sub(indent.width() + result.len() + + 4)); return Some((one_line_budget, multi_line_budget, indent + result.len() + 1)); } @@ -1909,27 +1988,35 @@ fn rewrite_generics(context: &RewriteContext, IndentStyle::Visual => generics_offset + 1, }; - let h_budget = try_opt!(shape.width.checked_sub(generics_offset.width() + 2)); + let h_budget = try_opt!(shape + .width + .checked_sub(generics_offset.width() + 2)); // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. - let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, Shape::legacy(h_budget, offset))); - let ty_strs = - tys.iter().map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); + let lt_strs = lifetimes + .iter() + .map(|lt| lt.rewrite(context, Shape::legacy(h_budget, offset))); + let ty_strs = tys.iter() + .map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); // Extract comments between generics. - let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - mk_sp(l.lifetime.span.lo, hi) - }); + let lt_spans = lifetimes + .iter() + .map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(context.codemap, - lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), + lt_spans + .chain(ty_spans) + .zip(lt_strs.chain(ty_strs)), ">", |&(sp, _)| sp.lo, |&(sp, _)| sp.hi, @@ -2157,7 +2244,10 @@ fn format_generics(context: &RewriteContext, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let budget = try_opt!(context + .config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, diff --git a/src/lib.rs b/src/lib.rs index aa93061602e..f63829c9199 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -536,7 +536,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m }); } - report.file_error_map.insert(name.to_owned(), errors); + report + .file_error_map + .insert(name.to_owned(), errors); } fn parse_input(input: Input, diff --git a/src/lists.rs b/src/lists.rs index 1ec1f00073d..a5c5d2c0aad 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -118,12 +118,18 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { - self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || - self.post_comment.as_ref().map_or(false, |s| s.contains('\n')) + self.item + .as_ref() + .map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || + self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) } pub fn has_line_pre_comment(&self) -> bool { - self.pre_comment.as_ref().map_or(false, |comment| comment.starts_with("//")) + self.pre_comment + .as_ref() + .map_or(false, |comment| comment.starts_with("//")) } pub fn from_str>(s: S) -> ListItem { @@ -148,8 +154,10 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De where I: IntoIterator + Clone, T: AsRef { - let pre_line_comments = - items.clone().into_iter().any(|item| item.as_ref().has_line_pre_comment()); + let pre_line_comments = items + .clone() + .into_iter() + .any(|item| item.as_ref().has_line_pre_comment()); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, @@ -166,7 +174,9 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De let real_total = total_width + total_sep_len; if real_total <= limit && !pre_line_comments && - !items.into_iter().any(|item| item.as_ref().is_multiline()) { + !items + .into_iter() + .any(|item| item.as_ref().is_multiline()) { DefinitiveListTactic::Horizontal } else { DefinitiveListTactic::Vertical @@ -189,7 +199,10 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option let mut iter = items.into_iter().enumerate().peekable(); let mut line_len = 0; - let indent_str = &formatting.shape.indent.to_string(formatting.config); + let indent_str = &formatting + .shape + .indent + .to_string(formatting.config); while let Some((i, item)) = iter.next() { let item = item.as_ref(); let inner_item = try_opt!(item.item.as_ref()); @@ -331,109 +344,119 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> fn next(&mut self) -> Option { let white_space: &[_] = &[' ', '\t']; - self.inner.next().map(|item| { - let mut new_lines = false; - // Pre-comment - let pre_snippet = self.codemap - .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) - .unwrap(); - let trimmed_pre_snippet = pre_snippet.trim(); - let pre_comment = if !trimmed_pre_snippet.is_empty() { - Some(trimmed_pre_snippet.to_owned()) - } else { - None - }; - - // Post-comment - let next_start = match self.inner.peek() { - Some(next_item) => (self.get_lo)(next_item), - None => self.next_span_start, - }; - let post_snippet = self.codemap - .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let mut block_open_index = post_snippet.find("/*"); - // check if it realy is a block comment (and not //*) - if let Some(i) = block_open_index { - if i > 0 && &post_snippet[i - 1..i] == "/" { - block_open_index = None; - } - } - let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(",").unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => separator_index + 1, - // Block-style post-comment before the separator. - (Some(i), None) => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) + self.inner + .next() + .map(|item| { + let mut new_lines = false; + // Pre-comment + let pre_snippet = self.codemap + .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) + .unwrap(); + let trimmed_pre_snippet = pre_snippet.trim(); + let pre_comment = if !trimmed_pre_snippet.is_empty() { + Some(trimmed_pre_snippet.to_owned()) + } else { + None + }; + + // Post-comment + let next_start = match self.inner.peek() { + Some(next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.codemap + .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let mut block_open_index = post_snippet.find("/*"); + // check if it realy is a block comment (and not //*) + if let Some(i) = block_open_index { + if i > 0 && &post_snippet[i - 1..i] == "/" { + block_open_index = None; + } } - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(",").unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => separator_index + 1, + // Block-style post-comment before the separator. + (Some(i), None) => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Potential *single* line comment. + (_, Some(j)) if j > separator_index => j + 1, + _ => post_snippet.len(), } - // Potential *single* line comment. - (_, Some(j)) if j > separator_index => j + 1, - _ => post_snippet.len(), + } + None => { + post_snippet + .find_uncommented(self.terminator) + .unwrap_or(post_snippet.len()) + } + }; + + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end - 1..]; + let first_newline = test_snippet + .find('\n') + .unwrap_or(test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet + .find(|c: char| !c.is_whitespace()) + .unwrap_or(test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if test_snippet + .chars() + .filter(|c| c == &'\n') + .count() > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; } } - None => { - post_snippet.find_uncommented(self.terminator).unwrap_or(post_snippet.len()) - } - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = - test_snippet.find(|c: char| !c.is_whitespace()).unwrap_or(test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; - } - } - // Cleanup post-comment: strip separators and whitespace. - self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); - - let post_snippet_trimmed = if post_snippet.starts_with(',') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { - post_snippet - }; - - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; - - ListItem { - pre_comment: pre_comment, - item: (self.get_item_string)(&item), - post_comment: post_comment, - new_lines: new_lines, - } - }) + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let post_snippet = post_snippet[..comment_end].trim(); + + let post_snippet_trimmed = if post_snippet.starts_with(',') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.ends_with(',') { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; + + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + }; + + ListItem { + pre_comment: pre_comment, + item: (self.get_item_string)(&item), + post_comment: post_comment, + new_lines: new_lines, + } + }) } } @@ -479,9 +502,10 @@ fn calculate_width(items: I) -> (usize, usize) where I: IntoIterator, T: AsRef { - items.into_iter().map(|item| total_item_width(item.as_ref())).fold((0, 0), |acc, l| { - (acc.0 + 1, acc.1 + l) - }) + items + .into_iter() + .map(|item| total_item_width(item.as_ref())) + .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) } fn total_item_width(item: &ListItem) -> usize { @@ -518,7 +542,10 @@ pub fn struct_lit_shape(shape: Shape, IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces); Shape { - width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), + width: try_opt!(context + .config + .max_width + .checked_sub(shape.indent.width())), ..shape } } @@ -535,7 +562,12 @@ pub fn struct_lit_tactic(h_shape: Option, if let Some(h_shape) = h_shape { let mut prelim_tactic = match (context.config.struct_lit_style, items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => context.config.struct_lit_multiline_style.to_list_tactic(), + _ => { + context + .config + .struct_lit_multiline_style + .to_list_tactic() + } }; if prelim_tactic == ListTactic::HorizontalVertical && items.len() > 1 { diff --git a/src/macros.rs b/src/macros.rs index f0ddf029aef..034ddc15d15 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -109,7 +109,10 @@ pub fn rewrite_macro(mac: &ast::Mac, let expr = match parser.parse_expr() { Ok(expr) => { // Recovered errors. - if context.parse_session.span_diagnostic.has_errors() { + if context + .parse_session + .span_diagnostic + .has_errors() { return None; } @@ -156,13 +159,15 @@ pub fn rewrite_macro(mac: &ast::Mac, // Format macro invocation as array literal. let extra_offset = macro_name.len(); let shape = try_opt!(shape.shrink_left(extra_offset)); - let rewrite = - try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context.codemap.span_after(mac.span, - original_style.opener()), - mac.span.hi - BytePos(1)), - context, - shape)); + let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mk_sp(context + .codemap + .span_after(mac.span, + original_style + .opener()), + mac.span.hi - BytePos(1)), + context, + shape)); Some(format!("{}{}", macro_name, rewrite)) } @@ -193,9 +198,15 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option MacroStyle { let snippet = context.snippet(mac.span); - let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); - let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); - let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); + let paren_pos = snippet + .find_uncommented("(") + .unwrap_or(usize::max_value()); + let bracket_pos = snippet + .find_uncommented("[") + .unwrap_or(usize::max_value()); + let brace_pos = snippet + .find_uncommented("{") + .unwrap_or(usize::max_value()); if paren_pos < bracket_pos && paren_pos < brace_pos { MacroStyle::Parens diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 3f2d78f35cc..8b8a3424008 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -83,12 +83,7 @@ impl<'a> FmtVisitor<'a> { let local_end = self.codemap.lookup_byte_offset(span.hi); let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin - .fm - .src - .as_ref() - .unwrap() - [start_index..end_index]; + let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; let big_diff = (span.lo - big_span_lo).to_usize(); let snippet = self.snippet(span); @@ -113,7 +108,10 @@ impl<'a> FmtVisitor<'a> { let mut rewrite_next_comment = true; fn replace_chars(string: &str) -> String { - string.chars().map(|ch| if ch.is_whitespace() { ch } else { 'X' }).collect() + string + .chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect() } let replaced = match self.config.write_mode { @@ -139,7 +137,8 @@ impl<'a> FmtVisitor<'a> { if let Some('{') = last_char { self.buffer.push_str("\n"); } - self.buffer.push_str(&self.block_indent.to_string(self.config)); + self.buffer + .push_str(&self.block_indent.to_string(self.config)); } else { self.buffer.push_str(" "); } @@ -148,22 +147,23 @@ impl<'a> FmtVisitor<'a> { self.config.max_width - self.block_indent.width()); - self.buffer.push_str(&rewrite_comment(subslice, - false, - Shape::legacy(comment_width, - self.block_indent), - self.config) - .unwrap()); + self.buffer + .push_str(&rewrite_comment(subslice, + false, + Shape::legacy(comment_width, + self.block_indent), + self.config) + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); if let Some('/') = subslice.chars().skip(1).next() { // check that there are no contained block comments - if !subslice.split('\n').map(|s| s.trim_left()).any(|s| { - s.len() > 2 && - &s[0..2] == "/*" - }) { + if !subslice + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() > 2 && &s[0..2] == "/*") { // Add a newline after line comments self.buffer.push_str("\n"); } @@ -189,7 +189,8 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&snippet[line_start..lw]); self.buffer.push_str("\n"); } else { - self.buffer.push_str(&snippet[line_start..i + 1]); + self.buffer + .push_str(&snippet[line_start..i + 1]); } line_start = i + 1; diff --git a/src/patterns.rs b/src/patterns.rs index 222ad6a9323..ebbb84a895e 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -38,10 +38,11 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!(shape.width.checked_sub(prefix.len() + - mut_infix.len() + - id_str.len() + - 3)); + let width = try_opt!(shape + .width + .checked_sub(prefix.len() + mut_infix.len() + + id_str.len() + + 3)); format!(" @ {}", try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) } @@ -91,16 +92,22 @@ impl Rewrite for Pat { PatKind::Lit(ref expr) => expr.rewrite(context, shape), PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. - let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = slice_pat.as_ref().map(|p| { - Some(format!("{}..", - try_opt!(p.rewrite(context, shape)))) - }); - let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); + let prefix = prefix + .iter() + .map(|p| p.rewrite(context, shape)); + let slice_pat = + slice_pat + .as_ref() + .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); + let suffix = suffix + .iter() + .map(|p| p.rewrite(context, shape)); // Munge them together. - let pats: Option> = - prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); + let pats: Option> = prefix + .chain(slice_pat.into_iter()) + .chain(suffix) + .collect(); // Check that all the rewrites succeeded, and if not return None. let pats = try_opt!(pats); @@ -239,7 +246,9 @@ fn rewrite_tuple_pat(pats: &[ptr::P], context: &RewriteContext, shape: Shape) -> Option { - let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); + let mut pat_vec: Vec<_> = pats.into_iter() + .map(|x| TuplePatField::Pat(x)) + .collect(); if let Some(pos) = dotdot_pos { let prev = if pos == 0 { @@ -271,7 +280,10 @@ fn rewrite_tuple_pat(pats: &[ptr::P], // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); - let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); + let path_len = path_str + .as_ref() + .map(|p| p.len()) + .unwrap_or(0); // 2 = "()".len(), 3 = "(,)".len() let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() @@ -321,11 +333,13 @@ fn rewrite_tuple_pat(pats: &[ptr::P], fn count_wildcard_suffix_len(items: &[ListItem]) -> usize { let mut suffix_len = 0; - for item in items.iter().rev().take_while(|i| match i.item { - Some(ref internal_string) if internal_string == - "_" => true, - _ => false, - }) { + for item in items + .iter() + .rev() + .take_while(|i| match i.item { + Some(ref internal_string) if internal_string == "_" => true, + _ => false, + }) { suffix_len += 1; if item.pre_comment.is_some() || item.post_comment.is_some() { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 23cb3f21bf2..4d05f544290 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -42,10 +42,14 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { @@ -55,10 +59,14 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec Vec(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = try_opt!(shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; + let max_chars = try_opt!(shape + .width + .checked_sub(fmt.opener.len() + ender_length + 1)) + + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. diff --git a/src/types.rs b/src/types.rs index 9cac8b4a0e0..3a9335f39e5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -163,10 +163,11 @@ impl<'a> Rewrite for SegmentParam<'a> { TypeDensity::Compressed => format!("{}=", binding.ident), }; let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!(binding.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + - result.len()))); + let rewrite = + try_opt!(binding + .ty + .rewrite(context, + Shape::legacy(budget, shape.indent + result.len()))); result.push_str(&rewrite); Some(result) } @@ -202,16 +203,18 @@ fn rewrite_segment(path_context: PathContext, let param_list = data.lifetimes .iter() .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .chain(data.types + .iter() + .map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings + .iter() + .map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let next_span_lo = param_list - .last() - .unwrap() - .get_span() - .hi + BytePos(1); - let list_lo = context.codemap.span_after(codemap::mk_sp(*span_lo, span_hi), "<"); + let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); + let list_lo = context + .codemap + .span_after(codemap::mk_sp(*span_lo, span_hi), "<"); let separator = if path_context == PathContext::Expr { "::" } else { @@ -298,28 +301,29 @@ fn format_function_type<'a, I>(inputs: I, // 1 for ( let offset = shape.indent + 1; let list_lo = context.codemap.span_after(span, "("); - let items = - itemize_list(context.codemap, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs.map(|i| ArgumentKind::Regular(Box::new(i))).chain(variadic_arg), - ")", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo, - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => { - ty.rewrite(context, Shape::legacy(budget, offset)) - } - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, - list_lo, - span.hi); + let items = itemize_list(context.codemap, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs + .map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), + ")", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => { + ty.rewrite(context, Shape::legacy(budget, offset)) + } + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi); let list_str = try_opt!(format_fn_args(items, Shape::legacy(budget, offset), context.config)); @@ -455,8 +459,10 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, if bounds.len() == 0 { Some(result) } else { - let appendix: Vec<_> = - try_opt!(bounds.into_iter().map(|b| b.rewrite(context, shape)).collect()); + let appendix: Vec<_> = try_opt!(bounds + .into_iter() + .map(|b| b.rewrite(context, shape)) + .collect()); let colon = type_bound_colon(context); let result = format!("{}{}{}", result, colon, appendix.join(" + ")); wrap_str(result, context.config.max_width, shape) @@ -494,7 +500,9 @@ impl Rewrite for ast::TyParamBounds { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; - let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect()); + let strs: Vec<_> = try_opt!(self.iter() + .map(|b| b.rewrite(context, shape)) + .collect()); wrap_str(strs.join(joiner), context.config.max_width, shape) } } @@ -550,10 +558,10 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref.rewrite(context, - Shape::legacy(max_path_width, - shape.indent + - extra_offset))); + let path_str = try_opt!(self.trait_ref + .rewrite(context, + Shape::legacy(max_path_width, + shape.indent + extra_offset))); Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { format!("for< {} > {}", lifetime_str, path_str) @@ -599,18 +607,20 @@ impl Rewrite for ast::Ty { format!("&{} {}{}", lt_str, mut_str, - try_opt!(mt.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + 2 + mut_len + - lt_len)))) + try_opt!(mt.ty + .rewrite(context, + Shape::legacy(budget, + shape.indent + 2 + mut_len + + lt_len)))) } None => { let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); format!("&{}{}", mut_str, - try_opt!(mt.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + 1 + mut_len)))) + try_opt!(mt.ty + .rewrite(context, + Shape::legacy(budget, + shape.indent + 1 + mut_len)))) } }) } @@ -662,7 +672,8 @@ impl Rewrite for ast::Ty { ast::TyKind::Mac(..) => None, ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(ref it) => { - it.rewrite(context, shape).map(|it_str| format!("impl {}", it_str)) + it.rewrite(context, shape) + .map(|it_str| format!("impl {}", it_str)) } ast::TyKind::Typeof(..) => unreachable!(), } diff --git a/src/utils.rs b/src/utils.rs index 1d836d8dc67..84722cc9b32 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -27,7 +27,11 @@ use SKIP_ANNOTATION; pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => text.len().checked_sub(idx + 1 + shape.used_width()).unwrap_or(0), + Some(idx) => { + text.len() + .checked_sub(idx + 1 + shape.used_width()) + .unwrap_or(0) + } None => text.len(), } } @@ -40,9 +44,13 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { Visibility::Crate(_) => Cow::from("pub(crate) "), Visibility::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.as_str()); + let mut segments_iter = segments + .iter() + .map(|seg| seg.identifier.name.as_str()); if path.is_global() { - segments_iter.next().expect("Non-global path in pub(restricted)?"); + segments_iter + .next() + .expect("Non-global path in pub(restricted)?"); } Cow::from(format!("pub({}) ", segments_iter.join("::"))) @@ -176,7 +184,9 @@ pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { pub fn trim_newlines(input: &str) -> &str { match input.find(|c| c != '\n' && c != '\r') { Some(start) => { - let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; + let end = input + .rfind(|c| c != '\n' && c != '\r') + .unwrap_or(0) + 1; &input[start..end] } None => "", @@ -279,12 +289,7 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option shape.indent.width() + shape.width { + if snippet.lines().rev().next().unwrap().len() > shape.indent.width() + shape.width { return None; } } diff --git a/src/visitor.rs b/src/visitor.rs index f78b781feff..e3d1505fd1e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -48,7 +48,9 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(stmt.span.hi)); // FIXME(#434): Move this check to somewhere more central, eg Rewrite. - if !self.config.file_lines.contains(&self.codemap.lookup_line_range(stmt.span)) { + if !self.config + .file_lines + .contains(&self.codemap.lookup_line_range(stmt.span)) { return; } @@ -116,7 +118,8 @@ impl<'a> FmtVisitor<'a> { } else { self.config.tab_spaces }; - self.buffer.truncate(total_len - chars_too_many); + self.buffer + .truncate(total_len - chars_too_many); self.buffer.push_str("}"); self.block_indent = self.block_indent.block_unindent(self.config); } @@ -187,7 +190,9 @@ impl<'a> FmtVisitor<'a> { // the AST lumps them all together. match item.node { ast::ItemKind::Mod(ref m) => { - let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; + let outer_file = self.codemap + .lookup_char_pos(item.span.lo) + .file; let inner_file = self.codemap.lookup_char_pos(m.inner.lo).file; if outer_file.name == inner_file.name { // Module is inline, in this case we treat modules like any @@ -506,8 +511,10 @@ impl<'a> FmtVisitor<'a> { // to be potentially reordered within `format_imports`. Otherwise, just format the // next item for output. if self.config.reorder_imports && is_use_item(&*items_left[0]) { - let use_item_length = - items_left.iter().take_while(|ppi| is_use_item(&***ppi)).count(); + let use_item_length = items_left + .iter() + .take_while(|ppi| is_use_item(&***ppi)) + .count(); let (use_items, rest) = items_left.split_at(use_item_length); self.format_imports(use_items); items_left = rest; @@ -528,7 +535,8 @@ impl<'a> FmtVisitor<'a> { let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) && local_file_name == self.codemap.span_to_filename(inner_span); - self.buffer.push_str(&*utils::format_visibility(vis)); + self.buffer + .push_str(&*utils::format_visibility(vis)); self.buffer.push_str("mod "); self.buffer.push_str(&ident.to_string()); -- cgit 1.4.1-3-g733a5 From 5305bc8436eaca7112744e84149ac2024e9da7b9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 11:25:59 +1300 Subject: test fallout --- src/bin/cargo-fmt.rs | 26 +++----------- src/bin/rustfmt.rs | 17 ++------- src/chains.rs | 20 +++-------- src/expr.rs | 73 ++++++++------------------------------- src/file_lines.rs | 23 +++--------- src/imports.rs | 14 ++------ src/issues.rs | 10 ++---- src/items.rs | 65 ++++++++-------------------------- src/lib.rs | 4 +-- src/lists.rs | 18 +++------- src/macros.rs | 5 +-- src/missed_spans.rs | 8 ++--- src/patterns.rs | 13 ++----- src/rustfmt_diff.rs | 20 +++-------- src/types.rs | 12 ++----- src/utils.rs | 8 ++--- src/visitor.rs | 10 ++---- tests/source/chains.rs | 1 - tests/system.rs | 41 ++++++++++++++++------ tests/target/chains-visual.rs | 15 ++++---- tests/target/chains.rs | 19 +++------- tests/target/expr.rs | 6 ++-- tests/target/long_field_access.rs | 4 ++- tests/target/tuple.rs | 15 ++++---- 24 files changed, 133 insertions(+), 314 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index ae40ffc16c9..d234a96fd12 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -110,10 +110,7 @@ fn format_crate(verbosity: Verbosity) -> Result { fn get_fmt_args() -> Vec { // All arguments after -- are passed to rustfmt - env::args() - .skip_while(|a| a != "--") - .skip(1) - .collect() + env::args().skip_while(|a| a != "--").skip(1).collect() } #[derive(Debug)] @@ -146,17 +143,12 @@ pub struct Target { // Returns a vector of all compile targets of a crate fn get_targets() -> Result, std::io::Error> { let mut targets: Vec = vec![]; - let output = try!(Command::new("cargo") - .arg("read-manifest") - .output()); + let output = try!(Command::new("cargo").arg("read-manifest").output()); if output.status.success() { // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); let json = Json::from_str(data).unwrap(); - let jtargets = json.find("targets") - .unwrap() - .as_array() - .unwrap(); + let jtargets = json.find("targets").unwrap().as_array().unwrap(); for jtarget in jtargets { targets.push(target_from_json(jtarget)); } @@ -171,16 +163,8 @@ fn get_targets() -> Result, std::io::Error> { fn target_from_json(jtarget: &Json) -> Target { let jtarget = jtarget.as_object().unwrap(); - let path = PathBuf::from(jtarget - .get("src_path") - .unwrap() - .as_string() - .unwrap()); - let kinds = jtarget - .get("kind") - .unwrap() - .as_array() - .unwrap(); + let path = PathBuf::from(jtarget.get("src_path").unwrap().as_string().unwrap()); + let kinds = jtarget.get("kind").unwrap().as_array().unwrap(); let kind = match kinds[0].as_string().unwrap() { "bin" => TargetKind::Bin, "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index a108f9ba8d0..af6996613bf 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -226,11 +226,7 @@ fn execute(opts: &Options) -> FmtResult { let options = try!(CliOptions::from_matches(&matches)); // Add any additional files that were specified via `--file-lines`. - files.extend(options - .file_lines - .files() - .cloned() - .map(PathBuf::from)); + files.extend(options.file_lines.files().cloned().map(PathBuf::from)); let mut config = Config::default(); let mut path = None; @@ -311,10 +307,7 @@ fn main() { fn print_usage(opts: &Options, reason: &str) { let reason = format!("{}\nusage: {} [options] ...", reason, - env::args_os() - .next() - .unwrap() - .to_string_lossy()); + env::args_os().next().unwrap().to_string_lossy()); println!("{}", opts.usage(&reason)); } @@ -365,11 +358,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { } // We append files from `--file-lines` later in `execute()`. - let files: Vec<_> = matches - .free - .iter() - .map(PathBuf::from) - .collect(); + let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); Ok(Operation::Format { files: files, diff --git a/src/chains.rs b/src/chains.rs index 568f23e5d72..23085bb66e2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -160,10 +160,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - Some(first_child_shape) .into_iter() .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); - let iter = subexpr_list - .iter() - .rev() - .zip(child_shape_iter); + let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) .collect::>>()); @@ -182,14 +179,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // line, we won't consider putting them on a single line either. let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); let first_span = context.snippet(subexpr_list[1].span); - let last_iter = last_span - .chars() - .take_while(|c| c.is_whitespace()); - - first_span - .chars() - .chain(last_iter) - .any(|c| c == '\n') + let last_iter = last_span.chars().take_while(|c| c.is_whitespace()); + + first_span.chars().chain(last_iter).any(|c| c == '\n') } else { false }; @@ -258,9 +250,7 @@ pub fn rewrite_try(expr: &ast::Expr, let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count)))); Some(format!("{}{}", sub_expr, - iter::repeat("?") - .take(try_count) - .collect::())) + iter::repeat("?").take(try_count).collect::())) } fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { diff --git a/src/expr.rs b/src/expr.rs index 6d05b757d06..69d0495a07c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -340,11 +340,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let nested_shape = match context.config.array_layout { - IndentStyle::Block => { - shape - .block() - .block_indent(context.config.tab_spaces) - } + IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces), IndentStyle::Visual => { try_opt!(shape .visual_indent(bracket_size) @@ -902,10 +898,7 @@ impl<'a> Rewrite for ControlFlow<'a> { label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 }; - let block_width = shape - .width - .checked_sub(used_width) - .unwrap_or(0); + let block_width = shape.width.checked_sub(used_width).unwrap_or(0); // This is used only for the empty block case: `{}`. So, we use 1 if we know // we should avoid the single line case. let block_width = if self.else_block.is_some() || self.nested_if { @@ -946,10 +939,7 @@ impl<'a> Rewrite for ControlFlow<'a> { extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); let alt_block_sep = String::from("\n") + - &shape - .indent - .block_only() - .to_string(context.config); + &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style == @@ -972,9 +962,7 @@ impl<'a> Rewrite for ControlFlow<'a> { }, |s| &**s), pat_expr_string, - after_cond_comment - .as_ref() - .map_or(block_sep, |s| &**s), + after_cond_comment.as_ref().map_or(block_sep, |s| &**s), block_str); if let Some(else_block) = self.else_block { @@ -1048,9 +1036,7 @@ impl<'a> Rewrite for ControlFlow<'a> { between_kwd_else_block_comment .as_ref() .map_or(between_sep, |s| &**s), - after_else_comment - .as_ref() - .map_or(after_sep, |s| &**s)) + after_else_comment.as_ref().map_or(after_sep, |s| &**s)) .ok()); result.push_str(&try_opt!(rewrite)); } @@ -1132,9 +1118,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, let mut result = String::new(); // any text not preceeded by a newline is pushed unmodified to the block - let first_brk = missed_str - .find(|c: char| c == '\n') - .unwrap_or(0); + let first_brk = missed_str.find(|c: char| c == '\n').unwrap_or(0); result.push_str(&missed_str[..first_brk]); let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it @@ -1174,11 +1158,7 @@ fn rewrite_match(context: &RewriteContext, let cond_shape = try_opt!(shape.shrink_left(6)); let cond_shape = try_opt!(cond_shape.sub_width(2)); let cond_str = try_opt!(cond.rewrite(context, cond_shape)); - let alt_block_sep = String::from("\n") + - &shape - .indent - .block_only() - .to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysSameLine => " ", _ => alt_block_sep.as_str(), @@ -1305,10 +1285,7 @@ impl Rewrite for ast::Arm { .collect::>>()); let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); - let items: Vec<_> = pat_strs - .into_iter() - .map(ListItem::from_str) - .collect(); + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); let fmt = ListFormatting { tactic: if all_simple { DefinitiveListTactic::Mixed @@ -1354,10 +1331,7 @@ impl Rewrite for ast::Arm { let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + - &shape - .indent - .block_only() - .to_string(context.config); + &shape.indent.block_only().to_string(context.config); let pat_width = extra_offset(&pats_str, shape); // Let's try and get the arm body on the same line as the condition. @@ -1447,10 +1421,7 @@ impl Rewrite for ast::Arm { // E.g. `Foo::Bar` is simple, but `Foo(..)` is not. fn pat_is_simple(pat_str: &str) -> bool { pat_str.len() <= 16 || - (pat_str.len() <= 24 && - pat_str - .chars() - .all(|c| c.is_alphabetic() || c == ':')) + (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) } // The `if ...` guard on a match arm. @@ -1478,10 +1449,7 @@ fn rewrite_guard(context: &RewriteContext, } // Not enough space to put the guard after the pattern, try a newline. - let overhead = shape - .indent - .block_indent(context.config) - .width() + 4 + 5; + let overhead = shape.indent.block_indent(context.config).width() + 4 + 5; if overhead < shape.width { let cond_str = guard.rewrite(context, Shape::legacy(shape.width - overhead, @@ -1556,10 +1524,7 @@ fn rewrite_pat_expr(context: &RewriteContext, } } - let nested_indent = shape - .indent - .block_only() - .block_indent(context.config); + let nested_indent = shape.indent.block_only().block_indent(context.config); // The expression won't fit on the current line, jump to next. result.push('\n'); @@ -1608,11 +1573,7 @@ fn string_requires_rewrite(context: &RewriteContext, string: &str, shape: Shape) -> bool { - if context - .codemap - .lookup_char_pos(span.lo) - .col - .0 != shape.indent.width() { + if context.codemap.lookup_char_pos(span.lo).col.0 != shape.indent.width() { return true; } @@ -1728,9 +1689,7 @@ fn rewrite_call_inner(context: &RewriteContext, indent: nested_shape.indent.block_only(), ..nested_shape }; - let rewrite = args.last() - .unwrap() - .rewrite(context, nested_shape); + let rewrite = args.last().unwrap().rewrite(context, nested_shape); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); @@ -1875,9 +1834,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let span_lo = |item: &StructLitField| match *item { StructLitField::Regular(field) => field.span.lo, StructLitField::Base(expr) => { - let last_field_hi = fields - .last() - .map_or(span.lo, |field| field.span.hi); + let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) diff --git a/src/file_lines.rs b/src/file_lines.rs index 664d101a483..9ae5f190ede 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -127,11 +127,7 @@ impl FileLines { map.get_vec(&canonical) .ok_or(()) }) { - Ok(ranges) => { - ranges - .iter() - .any(|r| r.contains(Range::from(range))) - } + Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), Err(_) => false, } } @@ -146,11 +142,7 @@ impl FileLines { match map.get_vec(range.file_name()) { None => false, - Some(ranges) => { - ranges - .iter() - .any(|r| r.intersects(Range::from(range))) - } + Some(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), } } } @@ -168,12 +160,7 @@ impl<'a> iter::Iterator for Files<'a> { fn canonicalize_path_string(s: &str) -> Result { match path::PathBuf::from(s).canonicalize() { - Ok(canonicalized) => { - canonicalized - .to_str() - .map(|s| s.to_string()) - .ok_or(()) - } + Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()).ok_or(()), _ => Err(()), } } @@ -184,9 +171,7 @@ impl str::FromStr for FileLines { fn from_str(s: &str) -> Result { let v: Vec = try!(json::decode(s).map_err(|e| e.to_string())); - let m = try!(v.into_iter() - .map(JsonSpan::into_tuple) - .collect()); + let m = try!(v.into_iter().map(JsonSpan::into_tuple).collect()); Ok(FileLines::from_multimap(m)) } } diff --git a/src/imports.rs b/src/imports.rs index e99afea9c6f..791ff0ee387 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -65,12 +65,7 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde match a.node.rename { Some(a_rename) => { match b.node.rename { - Some(b_rename) => { - a_rename - .name - .as_str() - .cmp(&b_rename.name.as_str()) - } + Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), None => Ordering::Greater, } } @@ -135,11 +130,8 @@ fn rewrite_view_path_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { - let path_str = if path.segments - .last() - .unwrap() - .identifier - .to_string() == "self" && path.segments.len() > 1 { + let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && + path.segments.len() > 1 { let path = &ast::Path { span: path.span.clone(), segments: path.segments[..path.segments.len() - 1].to_owned(), diff --git a/src/issues.rs b/src/issues.rs index 968faedd7c4..4819816c4eb 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -225,15 +225,12 @@ fn find_unnumbered_issue() { fn check_fail(text: &str, failing_pos: usize) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); assert_eq!(Some(failing_pos), - text.chars() - .position(|c| seeker.inspect(c).is_some())); + text.chars().position(|c| seeker.inspect(c).is_some())); } fn check_pass(text: &str) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, - text.chars() - .position(|c| seeker.inspect(c).is_some())); + assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); } check_fail("TODO\n", 4); @@ -253,8 +250,7 @@ fn find_unnumbered_issue() { fn find_issue() { fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); - text.chars() - .any(|c| seeker.inspect(c).is_some()) + text.chars().any(|c| seeker.inspect(c).is_some()) } assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n", diff --git a/src/items.rs b/src/items.rs index cd5e4b485d3..c218d629d19 100644 --- a/src/items.rs +++ b/src/items.rs @@ -370,8 +370,7 @@ impl<'a> FmtVisitor<'a> { enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span) { - self.buffer - .push_str(&format_header("enum ", ident, vis)); + self.buffer.push_str(&format_header("enum ", ident, vis)); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); @@ -584,9 +583,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = offset - .block_only() - .block_indent(context.config); + visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in items { @@ -665,10 +662,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, result.push_str(" "); } let used_space = last_line_width(&result); - let budget = try_opt!(context - .config - .max_width - .checked_sub(used_space)); + let budget = try_opt!(context.config.max_width.checked_sub(used_space)); let indent = offset + used_space; result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent)))); @@ -698,10 +692,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, } // 1 = space before the type. - let budget = try_opt!(context - .config - .max_width - .checked_sub(used_space + 1)); + let budget = try_opt!(context.config.max_width.checked_sub(used_space + 1)); let indent = offset + result.len() + 1; let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent)); if let Some(self_ty_str) = self_ty_str { @@ -713,10 +704,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, // Can't fit the self type on what's left of the line, so start a new one. let indent = offset.block_indent(context.config); result.push_str(&format!("\n{}", indent.to_string(context.config))); - let budget = try_opt!(context - .config - .max_width - .checked_sub(indent.width())); + let budget = try_opt!(context.config.max_width.checked_sub(indent.width())); result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, indent)))); Some(result) } else { @@ -790,9 +778,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if offset.width() + last_line_width(&result) + trait_bound_str.len() > context.config.comment_width { result.push('\n'); - let trait_indent = offset - .block_only() - .block_indent(context.config); + let trait_indent = offset.block_only().block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); } result.push_str(&trait_bound_str); @@ -860,9 +846,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = offset - .block_only() - .block_indent(context.config); + visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); for item in trait_items { @@ -1060,10 +1044,7 @@ fn format_tuple_struct(context: &RewriteContext, (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) } IndentStyle::Block => { - (ListTactic::HorizontalVertical, - offset - .block_only() - .block_indent(&context.config)) + (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) } }; // 3 = `();` @@ -1379,9 +1360,7 @@ impl Rewrite for ast::Arg { result.push_str(" "); } result.push_str(":"); - if context - .config - .space_after_type_annotation_colon { + if context.config.space_after_type_annotation_colon { result.push_str(" "); } let max_width = try_opt!(shape.width.checked_sub(result.len())); @@ -1695,10 +1674,7 @@ fn rewrite_fn_base(context: &RewriteContext, if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let budget = try_opt!(context - .config - .max_width - .checked_sub(ret_indent.width())); + let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); let ret_str = try_opt!(fd.output .rewrite(context, Shape::legacy(budget, ret_indent))); result.push_str(&ret_str); @@ -1821,9 +1797,7 @@ fn rewrite_args(context: &RewriteContext, }; let reduced_span = mk_sp(span.lo, second_arg_start); - context - .codemap - .span_after_last(reduced_span, ",") + context.codemap.span_after_last(reduced_span, ",") } else { span.lo }; @@ -1835,9 +1809,7 @@ fn rewrite_args(context: &RewriteContext, let variadic_arg = if variadic { let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); - let variadic_start = context - .codemap - .span_after(variadic_span, "...") - BytePos(3); + let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { None @@ -1879,10 +1851,7 @@ fn rewrite_args(context: &RewriteContext, }; let tactic = definitive_tactic(&arg_items, - context - .config - .fn_args_density - .to_list_tactic(), + context.config.fn_args_density.to_list_tactic(), one_line_budget); let budget = match tactic { DefinitiveListTactic::Horizontal => one_line_budget, @@ -1988,9 +1957,7 @@ fn rewrite_generics(context: &RewriteContext, IndentStyle::Visual => generics_offset + 1, }; - let h_budget = try_opt!(shape - .width - .checked_sub(generics_offset.width() + 2)); + let h_budget = try_opt!(shape.width.checked_sub(generics_offset.width() + 2)); // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. @@ -2014,9 +1981,7 @@ fn rewrite_generics(context: &RewriteContext, let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(context.codemap, - lt_spans - .chain(ty_spans) - .zip(lt_strs.chain(ty_strs)), + lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), ">", |&(sp, _)| sp.lo, |&(sp, _)| sp.hi, diff --git a/src/lib.rs b/src/lib.rs index f63829c9199..aa93061602e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -536,9 +536,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m }); } - report - .file_error_map - .insert(name.to_owned(), errors); + report.file_error_map.insert(name.to_owned(), errors); } fn parse_input(input: Input, diff --git a/src/lists.rs b/src/lists.rs index a5c5d2c0aad..62ad48971d5 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -118,9 +118,7 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { - self.item - .as_ref() - .map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || + self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || self.post_comment .as_ref() .map_or(false, |s| s.contains('\n')) @@ -199,10 +197,7 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option let mut iter = items.into_iter().enumerate().peekable(); let mut line_len = 0; - let indent_str = &formatting - .shape - .indent - .to_string(formatting.config); + let indent_str = &formatting.shape.indent.to_string(formatting.config); while let Some((i, item)) = iter.next() { let item = item.as_ref(); let inner_item = try_opt!(item.item.as_ref()); @@ -412,9 +407,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> // Everything from the separator to the next item. let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet - .find('\n') - .unwrap_or(test_snippet.len()); + let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; let first = test_snippet @@ -423,10 +416,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; - if test_snippet - .chars() - .filter(|c| c == &'\n') - .count() > 1 { + if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { // There were multiple line breaks which got trimmed to nothing. new_lines = true; } diff --git a/src/macros.rs b/src/macros.rs index 034ddc15d15..9d1367ebadc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -109,10 +109,7 @@ pub fn rewrite_macro(mac: &ast::Mac, let expr = match parser.parse_expr() { Ok(expr) => { // Recovered errors. - if context - .parse_session - .span_diagnostic - .has_errors() { + if context.parse_session.span_diagnostic.has_errors() { return None; } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 8b8a3424008..c0f04f56e15 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -75,10 +75,7 @@ impl<'a> FmtVisitor<'a> { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment // follows code on the same line, we won't touch it. - let big_span_lo = self.codemap - .lookup_char_pos(span.lo) - .file - .start_pos; + let big_span_lo = self.codemap.lookup_char_pos(span.lo).file.start_pos; let local_begin = self.codemap.lookup_byte_offset(big_span_lo); let local_end = self.codemap.lookup_byte_offset(span.hi); let start_index = local_begin.pos.to_usize(); @@ -189,8 +186,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&snippet[line_start..lw]); self.buffer.push_str("\n"); } else { - self.buffer - .push_str(&snippet[line_start..i + 1]); + self.buffer.push_str(&snippet[line_start..i + 1]); } line_start = i + 1; diff --git a/src/patterns.rs b/src/patterns.rs index ebbb84a895e..bc5c917dc00 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -92,16 +92,12 @@ impl Rewrite for Pat { PatKind::Lit(ref expr) => expr.rewrite(context, shape), PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. - let prefix = prefix - .iter() - .map(|p| p.rewrite(context, shape)); + let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); let slice_pat = slice_pat .as_ref() .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); - let suffix = suffix - .iter() - .map(|p| p.rewrite(context, shape)); + let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. let pats: Option> = prefix @@ -280,10 +276,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); - let path_len = path_str - .as_ref() - .map(|p| p.len()) - .unwrap_or(0); + let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); // 2 = "()".len(), 3 = "(,)".len() let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 4d05f544290..23cb3f21bf2 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -42,14 +42,10 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { @@ -59,14 +55,10 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec Vec>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); @@ -500,9 +496,7 @@ impl Rewrite for ast::TyParamBounds { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; - let strs: Vec<_> = try_opt!(self.iter() - .map(|b| b.rewrite(context, shape)) - .collect()); + let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect()); wrap_str(strs.join(joiner), context.config.max_width, shape) } } diff --git a/src/utils.rs b/src/utils.rs index 84722cc9b32..2a5b868f546 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -44,9 +44,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { Visibility::Crate(_) => Cow::from("pub(crate) "), Visibility::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; - let mut segments_iter = segments - .iter() - .map(|seg| seg.identifier.name.as_str()); + let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.as_str()); if path.is_global() { segments_iter .next() @@ -184,9 +182,7 @@ pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { pub fn trim_newlines(input: &str) -> &str { match input.find(|c| c != '\n' && c != '\r') { Some(start) => { - let end = input - .rfind(|c| c != '\n' && c != '\r') - .unwrap_or(0) + 1; + let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; &input[start..end] } None => "", diff --git a/src/visitor.rs b/src/visitor.rs index e3d1505fd1e..caf67c0683f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -118,8 +118,7 @@ impl<'a> FmtVisitor<'a> { } else { self.config.tab_spaces }; - self.buffer - .truncate(total_len - chars_too_many); + self.buffer.truncate(total_len - chars_too_many); self.buffer.push_str("}"); self.block_indent = self.block_indent.block_unindent(self.config); } @@ -190,9 +189,7 @@ impl<'a> FmtVisitor<'a> { // the AST lumps them all together. match item.node { ast::ItemKind::Mod(ref m) => { - let outer_file = self.codemap - .lookup_char_pos(item.span.lo) - .file; + let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; let inner_file = self.codemap.lookup_char_pos(m.inner.lo).file; if outer_file.name == inner_file.name { // Module is inline, in this case we treat modules like any @@ -535,8 +532,7 @@ impl<'a> FmtVisitor<'a> { let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) && local_file_name == self.codemap.span_to_filename(inner_span); - self.buffer - .push_str(&*utils::format_visibility(vis)); + self.buffer.push_str(&*utils::format_visibility(vis)); self.buffer.push_str("mod "); self.buffer.push_str(&ident.to_string()); diff --git a/tests/source/chains.rs b/tests/source/chains.rs index f0c096faf2b..5987195e031 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -4,7 +4,6 @@ // Test chain formatting. fn main() { - // Don't put chains on a single line if it wasn't so in source. let a = b .c .d.1 .foo(|x| x + 1); diff --git a/tests/system.rs b/tests/system.rs index c7ba5db1589..7eeea235679 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -28,7 +28,9 @@ const DIFF_CONTEXT_SIZE: usize = 3; fn get_path_string(dir_entry: io::Result) -> String { let path = dir_entry.expect("Couldn't get DirEntry").path(); - path.to_str().expect("Couldn't stringify path").to_owned() + path.to_str() + .expect("Couldn't stringify path") + .to_owned() } // Integration tests. The files in the tests/source are formatted and compared @@ -84,7 +86,9 @@ fn assert_output(source: &str, expected_filename: &str) { let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); let mut expected_text = String::new(); - expected_file.read_to_string(&mut expected_text).expect("Failed reading target"); + expected_file + .read_to_string(&mut expected_text) + .expect("Failed reading target"); let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); if compare.len() > 0 { @@ -100,8 +104,9 @@ fn assert_output(source: &str, expected_filename: &str) { #[test] fn idempotence_tests() { // Get all files in the tests/target directory. - let files = - fs::read_dir("tests/target").expect("Couldn't read target dir").map(get_path_string); + let files = fs::read_dir("tests/target") + .expect("Couldn't read target dir") + .map(get_path_string); let (_reports, count, fails) = check_files(files); // Display results. @@ -276,7 +281,9 @@ fn get_config(config_file: Option<&str>) -> Config { let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); let mut def_config = String::new(); - def_config_file.read_to_string(&mut def_config).expect("Couldn't read config"); + def_config_file + .read_to_string(&mut def_config) + .expect("Couldn't read config"); Config::from_toml(&def_config) } @@ -298,11 +305,22 @@ fn read_significant_comments(file_name: &str) -> HashMap { .map(|line| line.expect("Failed getting line")) .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { - (capture.get(1).expect("Couldn't unwrap capture").as_str().to_owned(), - capture.get(2).expect("Couldn't unwrap capture").as_str().to_owned()) - }) - }) + regex + .captures_iter(&line) + .next() + .map(|capture| { + (capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned()) + }) + }) .collect() } @@ -319,7 +337,8 @@ fn handle_result(result: HashMap, let mut f = fs::File::open(&target).expect("Couldn't open target"); let mut text = String::new(); - f.read_to_string(&mut text).expect("Failed reading target"); + f.read_to_string(&mut text) + .expect("Failed reading target"); if fmt_text != text { let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index d2cf993b10c..2795237d51b 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -5,12 +5,10 @@ fn main() { // Don't put chains on a single line if it wasn't so in source. - let a = b.c - .d - .1 - .foo(|x| x + 1); + let a = b.c.d.1.foo(|x| x + 1); - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc .ddddddddddddddddddddddddddd @@ -49,7 +47,9 @@ fn main() { }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = - xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x); + xxxxxxx.map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); aaaaaaaaaaaaaaaa.map(|x| { x += 1; @@ -125,7 +125,8 @@ fn floaters() { } fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); + constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) + .unwrap(); } fn issue587() { diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 2b4a31bf2a3..1d9b8a08622 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -4,11 +4,7 @@ // Test chain formatting. fn main() { - // Don't put chains on a single line if it wasn't so in source. - let a = b.c - .d - .1 - .foo(|x| x + 1); + let a = b.c.d.1.foo(|x| x + 1); bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); @@ -139,11 +135,8 @@ fn issue587() { fn try_shorthand() { let x = expr?; let y = expr.kaas()?.test(); - let loooooooooooooooooooooooooooooooooooooooooong = does_this? - .look? - .good? - .should_we_break? - .after_the_first_question_mark?; + let loooooooooooooooooooooooooooooooooooooooooong = + does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; let yyyy = expr? .another? .another? @@ -154,11 +147,7 @@ fn try_shorthand() { .another? .another? .test(); - let zzzz = expr? - .another? - .another? - .another? - .another?; + let zzzz = expr?.another?.another?.another?.another?; let aaa = x??????????????????????????????????????????????????????????????????????????; let y = a.very diff --git a/tests/target/expr.rs b/tests/target/expr.rs index f0788628538..c2a39cc5bbc 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -291,7 +291,7 @@ fn issue1106() { self.ast_map.expect_item(enum_node_id).node {} } - for entry in WalkDir::new(path).into_iter().filter_entry(|entry| { - exclusions.filter_entry(entry) - }) {} + for entry in WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) {} } diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs index 349d2c2f639..d47a7d5a13e 100644 --- a/tests/target/long_field_access.rs +++ b/tests/target/long_field_access.rs @@ -1,4 +1,6 @@ fn f() { - block_flow.base.stacking_relative_position_of_display_port = + block_flow + .base + .stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; } diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 2d3b52da72a..b7cbf82f411 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -29,13 +29,14 @@ fn b() { } fn issue550() { - self.visitor.visit_volume(self.level.sector_id(sector), - (floor_y, - if is_sky_flat(ceil_tex) { - from_wad_height(self.height_range.1) - } else { - ceil_y - })); + self.visitor + .visit_volume(self.level.sector_id(sector), + (floor_y, + if is_sky_flat(ceil_tex) { + from_wad_height(self.height_range.1) + } else { + ceil_y + })); } fn issue775() { -- cgit 1.4.1-3-g733a5 From a2d57e956a0d2021d3909b9ca676ec4eeb86c5c5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 28 Mar 2017 23:14:48 +0900 Subject: Remove duplicate definitions This commit removes duplicated definitions of `type_annotation_separator` and `type_bound_colon`. --- src/expr.rs | 12 ++++-------- src/types.rs | 9 ++------- src/utils.rs | 10 ++++++++++ 3 files changed, 16 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 69d0495a07c..3c0cf9b06ae 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,7 +23,8 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti struct_lit_tactic, shape_for_tactic, struct_lit_formatting}; use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, - semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr}; + semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, + place_spaces}; use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -1890,13 +1891,8 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // of space, we should fall back to BlockIndent. } -pub fn type_annotation_separator(config: &Config) -> &str { - match (config.space_before_type_annotation, config.space_after_type_annotation_colon) { - (true, true) => " : ", - (true, false) => " :", - (false, true) => ": ", - (false, false) => ":", - } +pub fn type_annotation_separator(config: &Config) -> & str { + place_spaces (config.space_before_type_annotation, config.space_after_type_annotation_colon) } fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { diff --git a/src/types.rs b/src/types.rs index c76031e3f5e..9c7ba2c7bd3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -21,7 +21,7 @@ use {Shape, Spanned}; use codemap::SpanUtils; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, format_mutability, wrap_str}; +use utils::{extra_offset, format_mutability, place_spaces, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::TypeDensity; use itertools::Itertools; @@ -346,12 +346,7 @@ fn format_function_type<'a, I>(inputs: I, } fn type_bound_colon(context: &RewriteContext) -> &'static str { - match (context.config.space_before_bound, context.config.space_after_bound_colon) { - (true, true) => " : ", - (true, false) => " :", - (false, true) => ": ", - (false, false) => ":", - } + place_spaces(context.config.space_before_bound, context.config.space_after_bound_colon) } impl Rewrite for ast::WherePredicate { diff --git a/src/utils.rs b/src/utils.rs index 2a5b868f546..f7f4b0ba789 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -326,6 +326,16 @@ pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option< None } +#[inline] +pub fn place_spaces(before: bool, after: bool) -> &'static str { + match (before, after) { + (true, true) => " : ", + (true, false) => " :", + (false, true) => ": ", + (false, false) => ":", + } +} + #[test] fn bin_search_test() { let closure = |i| match i { -- cgit 1.4.1-3-g733a5 From 6ecc18c7decb7c5b3a42ce196a0187544c8f1f62 Mon Sep 17 00:00:00 2001 From: Fabian Zaiser Date: Tue, 28 Mar 2017 16:32:12 +0200 Subject: Omit space before '\n' + comment (fixes #457) --- src/lists.rs | 4 +++- tests/source/space-not-before-newline.rs | 8 ++++++++ tests/target/space-not-before-newline.rs | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/source/space-not-before-newline.rs create mode 100644 tests/target/space-not-before-newline.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 62ad48971d5..b5a8ba5ae8d 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -303,7 +303,9 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option Shape::legacy(width, offset), formatting.config)); - result.push(' '); + if !formatted_comment.starts_with('\n') { + result.push(' '); + } result.push_str(&formatted_comment); } diff --git a/tests/source/space-not-before-newline.rs b/tests/source/space-not-before-newline.rs new file mode 100644 index 00000000000..2a1e1856908 --- /dev/null +++ b/tests/source/space-not-before-newline.rs @@ -0,0 +1,8 @@ +struct Foo { + a: (), + // spaces ^^^ to be removed +} +enum Foo { + Bar, + // spaces ^^^ to be removed +} diff --git a/tests/target/space-not-before-newline.rs b/tests/target/space-not-before-newline.rs new file mode 100644 index 00000000000..9d75b726aa0 --- /dev/null +++ b/tests/target/space-not-before-newline.rs @@ -0,0 +1,8 @@ +struct Foo { + a: (), + // spaces ^^^ to be removed +} +enum Foo { + Bar, + // spaces ^^^ to be removed +} -- cgit 1.4.1-3-g733a5 From 78826e67839d3d58e420dbeff9c793a43675a0a7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 28 Mar 2017 23:16:52 +0900 Subject: Fix a typo --- src/expr.rs | 7 ++++--- src/lists.rs | 2 +- src/types.rs | 5 +++-- src/utils.rs | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 3c0cf9b06ae..91b17db5d23 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -24,7 +24,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, - place_spaces}; + colon_spaces}; use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -1891,8 +1891,9 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // of space, we should fall back to BlockIndent. } -pub fn type_annotation_separator(config: &Config) -> & str { - place_spaces (config.space_before_type_annotation, config.space_after_type_annotation_colon) +pub fn type_annotation_separator(config: &Config) -> &str { + colon_spaces(config.space_before_type_annotation, + config.space_after_type_annotation_colon) } fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { diff --git a/src/lists.rs b/src/lists.rs index 62ad48971d5..3fb49b67c1c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -207,7 +207,7 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option let item_sep_len = if separate { sep_len } else { 0 }; // Item string may be multi-line. Its length (used for block comment alignment) - // Should be only the length of the last line. + // should be only the length of the last line. let item_last_line = if item.is_multiline() { inner_item.lines().last().unwrap_or("") } else { diff --git a/src/types.rs b/src/types.rs index 9c7ba2c7bd3..d766b9770de 100644 --- a/src/types.rs +++ b/src/types.rs @@ -21,7 +21,7 @@ use {Shape, Spanned}; use codemap::SpanUtils; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, format_mutability, place_spaces, wrap_str}; +use utils::{extra_offset, format_mutability, colon_spaces, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::TypeDensity; use itertools::Itertools; @@ -346,7 +346,8 @@ fn format_function_type<'a, I>(inputs: I, } fn type_bound_colon(context: &RewriteContext) -> &'static str { - place_spaces(context.config.space_before_bound, context.config.space_after_bound_colon) + colon_spaces(context.config.space_before_bound, + context.config.space_after_bound_colon) } impl Rewrite for ast::WherePredicate { diff --git a/src/utils.rs b/src/utils.rs index f7f4b0ba789..1b1ef99955e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -327,7 +327,7 @@ pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option< } #[inline] -pub fn place_spaces(before: bool, after: bool) -> &'static str { +pub fn colon_spaces(before: bool, after: bool) -> &'static str { match (before, after) { (true, true) => " : ", (true, false) => " :", -- cgit 1.4.1-3-g733a5 From b6f1b516d9d5673d1d5379e6dd18236e7b759713 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 29 Mar 2017 01:33:14 -0400 Subject: Format any statement whose span intersects file_lines --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index caf67c0683f..86fb1bce9d9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -50,7 +50,7 @@ impl<'a> FmtVisitor<'a> { // FIXME(#434): Move this check to somewhere more central, eg Rewrite. if !self.config .file_lines - .contains(&self.codemap.lookup_line_range(stmt.span)) { + .intersects(&self.codemap.lookup_line_range(stmt.span)) { return; } -- cgit 1.4.1-3-g733a5 From 36f0402bac2464910b261d08de54e37a0dce5601 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 29 Mar 2017 18:50:39 -0400 Subject: Canonicalize range path in FileLines::intersects() --- src/file_lines.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index 9ae5f190ede..7e2ba13c8b0 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -140,9 +140,12 @@ impl FileLines { Some(ref map) => map, }; - match map.get_vec(range.file_name()) { - None => false, - Some(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), + match canonicalize_path_string(range.file_name()).and_then(|canonical| { + map.get_vec(&canonical) + .ok_or(()) + }) { + Ok(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), + Err(_) => false, } } } -- cgit 1.4.1-3-g733a5 From 6971b4b5c9450d191a684b2d94b2ff810c6984e8 Mon Sep 17 00:00:00 2001 From: Emil Gardström Date: Mon, 27 Mar 2017 15:36:43 +0200 Subject: Implemented support for workspaces closes rust-lang-nursery/rustfmt#1244 --- src/bin/cargo-fmt.rs | 112 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 96 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index d234a96fd12..0fcd0fd3f2d 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -21,8 +21,10 @@ use std::io::Write; use std::path::PathBuf; use std::process::{Command, ExitStatus}; use std::str; +use std::collections::HashSet; +use std::iter::FromIterator; -use getopts::Options; +use getopts::{Options, Matches}; use rustc_serialize::json::Json; fn main() { @@ -39,6 +41,11 @@ fn execute() -> i32 { opts.optflag("h", "help", "show this message"); opts.optflag("q", "quiet", "no output printed to stdout"); opts.optflag("v", "verbose", "use verbose output"); + opts.optmulti("p", + "package", + "specify package to format (only usable in workspaces)", + ""); + opts.optflag("", "all", "format all packages (only usable in workspaces)"); let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { Ok(m) => m, @@ -63,7 +70,9 @@ fn execute() -> i32 { return success; } - match format_crate(verbosity) { + let workspace_hitlist = WorkspaceHitlist::from_matches(&matches); + + match format_crate(verbosity, workspace_hitlist) { Err(e) => { print_usage(&opts, &e.to_string()); failure @@ -92,8 +101,10 @@ pub enum Verbosity { Quiet, } -fn format_crate(verbosity: Verbosity) -> Result { - let targets = try!(get_targets()); +fn format_crate(verbosity: Verbosity, + workspace_hitlist: WorkspaceHitlist) + -> Result { + let targets = try!(get_targets(workspace_hitlist)); // Currently only bin and lib files get formatted let files: Vec<_> = targets @@ -140,25 +151,94 @@ pub struct Target { kind: TargetKind, } +#[derive(Debug, PartialEq, Eq)] +pub enum WorkspaceHitlist { + All, + Some(Vec), + None, +} + +impl WorkspaceHitlist { + pub fn get_some<'a>(&'a self) -> Option<&'a [String]> { + if let &WorkspaceHitlist::Some(ref hitlist) = self { + Some(&hitlist) + } else { + None + } + } + + pub fn from_matches(matches: &Matches) -> WorkspaceHitlist { + match (matches.opt_present("all"), matches.opt_present("p")) { + (false, false) => WorkspaceHitlist::None, + (true, _) => WorkspaceHitlist::All, + (false, true) => WorkspaceHitlist::Some(matches.opt_strs("p")), + } + } +} + // Returns a vector of all compile targets of a crate -fn get_targets() -> Result, std::io::Error> { +fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std::io::Error> { let mut targets: Vec = vec![]; - let output = try!(Command::new("cargo").arg("read-manifest").output()); + if workspace_hitlist == WorkspaceHitlist::None { + let output = try!(Command::new("cargo").arg("read-manifest").output()); + if output.status.success() { + // None of the unwraps should fail if output of `cargo read-manifest` is correct + let data = &String::from_utf8(output.stdout).unwrap(); + let json = Json::from_str(data).unwrap(); + let jtargets = json.find("targets").unwrap().as_array().unwrap(); + for jtarget in jtargets { + targets.push(target_from_json(jtarget)); + } + + return Ok(targets); + } + return Err(std::io::Error::new(std::io::ErrorKind::NotFound, + str::from_utf8(&output.stderr).unwrap())); + } + // This happens when cargo-fmt is not used inside a crate or + // is used inside a workspace. + // To ensure backward compatability, we only use `cargo metadata` for workspaces. + // TODO: Is it possible only use metadata or read-manifest + let output = Command::new("cargo").arg("metadata") + .arg("--no-deps") + .output()?; if output.status.success() { - // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); let json = Json::from_str(data).unwrap(); - let jtargets = json.find("targets").unwrap().as_array().unwrap(); - for jtarget in jtargets { - targets.push(target_from_json(jtarget)); + let mut hitlist: HashSet<&String> = if workspace_hitlist != WorkspaceHitlist::All { + HashSet::from_iter(workspace_hitlist.get_some().unwrap()) + } else { + HashSet::new() // Unused + }; + let members: Vec<&Json> = json.find("packages") + .unwrap() + .as_array() + .unwrap() + .into_iter() + .filter(|member| if workspace_hitlist == WorkspaceHitlist::All { + true + } else { + let member_name = member.find("name").unwrap().as_string().unwrap(); + hitlist.take(&member_name.to_string()).is_some() + }) + .collect(); + if hitlist.len() != 0 { + // Mimick cargo of only outputting one spec. + return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, + format!("package `{}` is not a member of the workspace", + hitlist.iter().next().unwrap()))); } - - Ok(targets) - } else { - // This happens when cargo-fmt is not used inside a crate - Err(std::io::Error::new(std::io::ErrorKind::NotFound, - str::from_utf8(&output.stderr).unwrap())) + for member in members { + let jtargets = member.find("targets").unwrap().as_array().unwrap(); + for jtarget in jtargets { + targets.push(target_from_json(jtarget)); + } + } + return Ok(targets); } + Err(std::io::Error::new(std::io::ErrorKind::NotFound, + str::from_utf8(&output.stderr).unwrap())) + } fn target_from_json(jtarget: &Json) -> Target { -- cgit 1.4.1-3-g733a5 From 3a1ffa7db7c0a641cf2aa04171815a564317416a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 29 Mar 2017 20:15:27 +0900 Subject: Split long fields in structs This commit splits long fields in structs. Closes #1412. --- src/items.rs | 65 +++++++++++++++++++++++++++++++++++++------------ tests/source/structs.rs | 11 +++++++++ tests/target/structs.rs | 16 +++++++++--- 3 files changed, 74 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c218d629d19..2cb4e46ecb5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1220,25 +1220,60 @@ impl Rewrite for ast::StructField { } let type_annotation_spacing = type_annotation_spacing(context.config); - let result = match name { - Some(name) => { - format!("{}{}{}{}:{}", - attr_str, - vis, - name, - type_annotation_spacing.0, - type_annotation_spacing.1) - } + let mut result = match name { + Some(name) => format!("{}{}{}{}:", attr_str, vis, name, type_annotation_spacing.0), None => format!("{}{}", attr_str, vis), }; - let last_line_width = last_line_width(&result); + let type_offset = shape.indent.block_indent(context.config); + let rewrite_type_in_next_line = || { + let budget = try_opt!(context + .config + .max_width + .checked_sub(type_offset.width())); + self.ty + .rewrite(context, Shape::legacy(budget, type_offset)) + }; + + let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); let budget = try_opt!(shape.width.checked_sub(last_line_width)); - let rewrite = try_opt!(self.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + last_line_width))); - Some(result + &rewrite) + let ty_rewritten = self.ty + .rewrite(context, + Shape::legacy(budget, shape.indent + last_line_width)); + match ty_rewritten { + Some(ref ty) if ty.contains('\n') => { + let new_ty = rewrite_type_in_next_line(); + match new_ty { + Some(ref new_ty) if !new_ty.contains('\n') && + new_ty.len() + type_offset.width() <= + context.config.max_width => { + Some(format!("{}\n{}{}", + result, + type_offset.to_string(&context.config), + &new_ty)) + } + _ => { + if name.is_some() { + result.push_str(type_annotation_spacing.1); + } + Some(result + &ty) + } + } + } + Some(ty) => { + if name.is_some() { + result.push_str(type_annotation_spacing.1); + } + Some(result + &ty) + } + None => { + let ty = try_opt!(rewrite_type_in_next_line()); + Some(format!("{}\n{}{}", + result, + type_offset.to_string(&context.config), + &ty)) + } + } } } diff --git a/tests/source/structs.rs b/tests/source/structs.rs index d24b2ba1a77..d7cfe7ec548 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -167,3 +167,14 @@ struct Foo { } struct Foo { /* comment */ } struct Foo(); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 2969438eadd..7b4eb031f9f 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -117,9 +117,8 @@ struct FieldsWithAttributes { } struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, } struct Foo(T); @@ -172,3 +171,14 @@ struct Foo { } struct Foo { /* comment */ } struct Foo(); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} -- cgit 1.4.1-3-g733a5 From 56da223dc2129bd6623fa69f0b242b48329171aa Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Thu, 30 Mar 2017 19:16:06 -0400 Subject: --file_lines argument now supports "stdin" --- src/bin/rustfmt.rs | 19 ++++++++----------- src/file_lines.rs | 4 ++++ 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index af6996613bf..0b30a7f8798 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -217,17 +217,16 @@ fn execute(opts: &Options) -> FmtResult { // write_mode is always Plain for Stdin. config.write_mode = WriteMode::Plain; + // parse file_lines + if let Some(ref file_lines) = matches.opt_str("file-lines") { + config.file_lines = try!(file_lines.parse()); + } + Ok(run(Input::Text(input), &config)) } - Operation::Format { - mut files, - config_path, - } => { + Operation::Format { files, config_path } => { let options = try!(CliOptions::from_matches(&matches)); - // Add any additional files that were specified via `--file-lines`. - files.extend(options.file_lines.files().cloned().map(PathBuf::from)); - let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -345,9 +344,8 @@ fn determine_operation(matches: &Matches) -> FmtResult { Some(dir) }); - // if no file argument is supplied and `--file-lines` is not specified, read from stdin - if matches.free.is_empty() && !matches.opt_present("file-lines") { - + // if no file argument is supplied, read from stdin + if matches.free.is_empty() { let mut buffer = String::new(); try!(io::stdin().read_to_string(&mut buffer)); @@ -357,7 +355,6 @@ fn determine_operation(matches: &Matches) -> FmtResult { }); } - // We append files from `--file-lines` later in `execute()`. let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); Ok(Operation::Format { diff --git a/src/file_lines.rs b/src/file_lines.rs index 7e2ba13c8b0..e68751eb887 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -162,6 +162,10 @@ impl<'a> iter::Iterator for Files<'a> { } fn canonicalize_path_string(s: &str) -> Result { + if s == "stdin" { + return Ok(s.to_string()); + } + match path::PathBuf::from(s).canonicalize() { Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()).ok_or(()), _ => Err(()), -- cgit 1.4.1-3-g733a5 From 34b90d8716feedcfe5c5dcdd111d3490fa3b38e1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 31 Mar 2017 21:57:29 +0900 Subject: Check existence of pre comment explicitly This commit fixes #1428. --- src/lists.rs | 4 +++- tests/source/structs.rs | 2 ++ tests/target/structs.rs | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 34ad6b26ea8..6b917ff29e6 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -350,7 +350,9 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); - let pre_comment = if !trimmed_pre_snippet.is_empty() { + let has_pre_comment = trimmed_pre_snippet.contains("//") || + trimmed_pre_snippet.contains("/*"); + let pre_comment = if has_pre_comment { Some(trimmed_pre_snippet.to_owned()) } else { None diff --git a/tests/source/structs.rs b/tests/source/structs.rs index d7cfe7ec548..5786fef4839 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -178,3 +178,5 @@ struct Deep { Type, NodeType>, } + +struct Foo(String); diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 7b4eb031f9f..2906d39759b 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -182,3 +182,5 @@ struct Deep { deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, Type, NodeType>, } + +struct Foo(String); -- cgit 1.4.1-3-g733a5 From 6241469a69176b42291d5573d508ebeb2c5f39e9 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Fri, 31 Mar 2017 13:34:53 -0400 Subject: Warn about extra files listed in file_lines argument --- src/bin/rustfmt.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 0b30a7f8798..b5d731dbd69 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -220,6 +220,11 @@ fn execute(opts: &Options) -> FmtResult { // parse file_lines if let Some(ref file_lines) = matches.opt_str("file-lines") { config.file_lines = try!(file_lines.parse()); + for f in config.file_lines.files() { + if f != "stdin" { + println!("Warning: Extra file listed in file_lines option '{}'", f); + } + } } Ok(run(Input::Text(input), &config)) @@ -227,6 +232,12 @@ fn execute(opts: &Options) -> FmtResult { Operation::Format { files, config_path } => { let options = try!(CliOptions::from_matches(&matches)); + for f in options.file_lines.files() { + if !files.contains(&PathBuf::from(f)) { + println!("Warning: Extra file listed in file_lines option '{}'", f); + } + } + let mut config = Config::default(); let mut path = None; // Load the config path file if provided -- cgit 1.4.1-3-g733a5 From a0efdf2de9999c64c00b1e5cac86562e53e86128 Mon Sep 17 00:00:00 2001 From: Mike Boutin Date: Sun, 2 Apr 2017 11:05:21 -0400 Subject: Do not count `\r` as part of line width. Resolves #1335. Does not attempt to handle a `\r` not followed by a `\n` nor attempt to handle Unicode intricacies (#6) including zero-width or multi-byte characters. --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index aa93061602e..be4579faba2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -481,7 +481,6 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m for (c, b) in text.chars() { if c == '\r' { - line_len += c.len_utf8(); continue; } -- cgit 1.4.1-3-g733a5 From 6af096851124a515fa13e8cf07c646b70fce41d9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 1 Apr 2017 00:45:02 +0900 Subject: Change return type of 'from_toml' from 'Config' to 'Result' Closes #1426. --- src/bin/rustfmt.rs | 15 ++++++++------- src/config.rs | 24 +++++++++++++----------- tests/system.rs | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index af6996613bf..c60201bbb25 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -149,7 +149,10 @@ fn resolve_config(dir: &Path) -> FmtResult<(Config, Option)> { let mut file = try!(File::open(&path)); let mut toml = String::new(); try!(file.read_to_string(&mut toml)); - Ok((Config::from_toml(&toml), Some(path))) + match Config::from_toml(&toml) { + Ok(cfg) => Ok((cfg, Some(path))), + Err(err) => Err(FmtError::from(err)), + } } /// read the given config file path recursively if present else read the project file path @@ -211,8 +214,8 @@ fn execute(opts: &Options) -> FmtResult { } Operation::Stdin { input, config_path } => { // try to read config from local directory - let (mut config, _) = match_cli_path_or_file(config_path, &env::current_dir().unwrap()) - .expect("Error resolving config"); + let (mut config, _) = match_cli_path_or_file(config_path, + &env::current_dir().unwrap())?; // write_mode is always Plain for Stdin. config.write_mode = WriteMode::Plain; @@ -232,8 +235,7 @@ fn execute(opts: &Options) -> FmtResult { let mut path = None; // Load the config path file if provided if let Some(config_file) = config_path { - let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref()) - .expect(&format!("Error resolving config for {:?}", config_file)); + let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref())?; config = cfg_tmp; path = path_tmp; }; @@ -248,8 +250,7 @@ fn execute(opts: &Options) -> FmtResult { for file in files { // Check the file directory if the config-path could not be read or not provided if path.is_none() { - let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap()) - .expect(&format!("Error resolving config for {}", file.display())); + let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap())?; if options.verbose { if let Some(path) = path_tmp.as_ref() { println!("Using rustfmt config file {} for {}", diff --git a/src/config.rs b/src/config.rs index 9a554659e83..21ab6cd5447 100644 --- a/src/config.rs +++ b/src/config.rs @@ -12,7 +12,6 @@ extern crate toml; use file_lines::FileLines; use lists::{SeparatorTactic, ListTactic}; -use std::io::Write; macro_rules! configuration_option_enum{ ($e:ident: $( $x:ident ),+ $(,)*) => { @@ -237,26 +236,29 @@ macro_rules! create_config { self } - pub fn from_toml(toml: &str) -> Config { + pub fn from_toml(toml: &str) -> Result { let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); + let mut err: String = String::new(); for (key, _) in parsed.as_table().expect("Parsed config was not table") { match &**key { $( stringify!($i) => (), )+ - _ => msg!("Warning: Unused configuration option {}", key), + _ => { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } } } - let parsed_config:ParsedConfig = match toml::decode(parsed) { - Some(decoded) => decoded, + match toml::decode(parsed) { + Some(parsed_config) => + Ok(Config::default().fill_from_parsed_config(parsed_config)), None => { - msg!("Decoding config file failed. Config:\n{}", toml); - let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); - msg!("\n\nParsed:\n{:?}", parsed); - panic!(); + err.push_str("Error: Decoding config file failed. "); + err.push_str("Please check your config file.\n"); + Err(err) } - }; - Config::default().fill_from_parsed_config(parsed_config) + } } pub fn override_value(&mut self, key: &str, val: &str) { diff --git a/tests/system.rs b/tests/system.rs index 7eeea235679..0d7c47feb32 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -285,7 +285,7 @@ fn get_config(config_file: Option<&str>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config) + Config::from_toml(&def_config).expect("Invalid toml") } // Reads significant comments of the form: // rustfmt-key: value -- cgit 1.4.1-3-g733a5 From 4c4f70957bc40f9aae377ec67af62f6f3c4aa9f9 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 3 Apr 2017 17:39:14 -0600 Subject: fix bug by adding boolean argument Signed-off-by: Ryan1729 --- src/chains.rs | 2 +- src/expr.rs | 29 +++++++++++++++++++++-------- src/macros.rs | 5 +++-- 3 files changed, 25 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 23085bb66e2..2c2b4ef63ea 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -441,5 +441,5 @@ fn rewrite_method_call(method_name: ast::Ident, let callee_str = format!(".{}{}", method_name, type_str); let span = mk_sp(lo, span.hi); - rewrite_call(context, &callee_str, &args[1..], span, shape) + rewrite_call(context, &callee_str, &args[1..], span, shape, false) } diff --git a/src/expr.rs b/src/expr.rs index 91b17db5d23..6561d3faf62 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -71,7 +71,7 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, expr.span.hi); - rewrite_call(context, &**callee, args, inner_span, shape) + rewrite_call(context, &**callee, args, inner_span, shape, false) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { @@ -1597,12 +1597,20 @@ pub fn rewrite_call(context: &RewriteContext, callee: &R, args: &[ptr::P], span: Span, - shape: Shape) + shape: Shape, + force_no_trailing_comma: bool) -> Option where R: Rewrite { - let closure = - |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape); + let closure = |callee_max_width| { + rewrite_call_inner(context, + callee, + callee_max_width, + args, + span, + shape, + force_no_trailing_comma) + }; // 2 is for parens let max_width = try_opt!(shape.width.checked_sub(2)); @@ -1614,7 +1622,8 @@ fn rewrite_call_inner(context: &RewriteContext, max_callee_width: usize, args: &[ptr::P], span: Span, - shape: Shape) + shape: Shape, + force_no_trailing_comma: bool) -> Result where R: Rewrite { @@ -1721,9 +1730,13 @@ fn rewrite_call_inner(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: match context.config.fn_call_style { - IndentStyle::Visual => SeparatorTactic::Never, - IndentStyle::Block => context.config.trailing_comma, + trailing_separator: if force_no_trailing_comma { + SeparatorTactic::Never + } else { + match context.config.fn_call_style { + IndentStyle::Visual => SeparatorTactic::Never, + IndentStyle::Block => context.config.trailing_comma, + } }, shape: nested_shape, ends_with_newline: false, diff --git a/src/macros.rs b/src/macros.rs index 9d1367ebadc..fd5578e7f00 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -144,8 +144,9 @@ pub fn rewrite_macro(mac: &ast::Mac, match style { MacroStyle::Parens => { - // Format macro invocation as function call. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map(|rw| { + // Format macro invocation as function call, forcing no trailing + // comma because not all macros support them. + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape, true).map(|rw| { match position { MacroPosition::Item => format!("{};", rw), _ => rw, -- cgit 1.4.1-3-g733a5 From eb25ac5e11cc99713d512d2f5518f94d7de18eb0 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Tue, 4 Apr 2017 00:01:33 -0600 Subject: eliminate nested match --- src/expr.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6561d3faf62..b472f283c6c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1730,13 +1730,11 @@ fn rewrite_call_inner(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: if force_no_trailing_comma { + trailing_separator: if force_no_trailing_comma || + context.config.fn_call_style == IndentStyle::Visual { SeparatorTactic::Never } else { - match context.config.fn_call_style { - IndentStyle::Visual => SeparatorTactic::Never, - IndentStyle::Block => context.config.trailing_comma, - } + context.config.trailing_comma }, shape: nested_shape, ends_with_newline: false, -- cgit 1.4.1-3-g733a5 From 8d22e85e48bf46b3056b8e0173940a8bb4f69c31 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Apr 2017 06:28:47 +0900 Subject: Lookup the last element of 'subexpr_list' instead of the first one Closes #1217, #1236, #1389 and #1434. --- src/bin/cargo-fmt.rs | 3 ++- src/chains.rs | 2 +- tests/source/chains-visual.rs | 29 +++++++++++++++++++++++++++++ tests/target/chains-visual.rs | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 0fcd0fd3f2d..ea747aa4702 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -199,7 +199,8 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: // is used inside a workspace. // To ensure backward compatability, we only use `cargo metadata` for workspaces. // TODO: Is it possible only use metadata or read-manifest - let output = Command::new("cargo").arg("metadata") + let output = Command::new("cargo") + .arg("metadata") .arg("--no-deps") .output()?; if output.status.success() { diff --git a/src/chains.rs b/src/chains.rs index 23085bb66e2..970278d12a1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -217,7 +217,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_connector = if extend || subexpr_list.is_empty() { "" - } else if let ast::ExprKind::Try(_) = subexpr_list[0].node { + } else if let ast::ExprKind::Try(_) = subexpr_list.last().unwrap().node { "" } else { &*connector diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs index f0be8acdce9..198691d82b5 100644 --- a/tests/source/chains-visual.rs +++ b/tests/source/chains-visual.rs @@ -115,3 +115,32 @@ fn issue587() { std::mem::transmute(dl.symbol::<()>("init").unwrap()) } + +fn issue_1389() { + let names = String::from_utf8(names)?.split('|').map(str::to_owned).collect(); +} + +fn issue1217() -> Result { +let random_chars: String = OsRng::new()? + .gen_ascii_chars() + .take(self.bit_length) + .collect(); + + Ok(Mnemonic::new(&random_chars)) +} + +fn issue1236(options: Vec) -> Result> { +let process = Command::new("dmenu").stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; +} + +fn issue1434() { + for _ in 0..100 { + let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; + } +} diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 2795237d51b..2763b339084 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -134,3 +134,37 @@ fn issue587() { std::mem::transmute(dl.symbol::<()>("init").unwrap()) } + +fn issue_1389() { + let names = String::from_utf8(names)? + .split('|') + .map(str::to_owned) + .collect(); +} + +fn issue1217() -> Result { + let random_chars: String = OsRng::new()? + .gen_ascii_chars() + .take(self.bit_length) + .collect(); + + Ok(Mnemonic::new(&random_chars)) +} + +fn issue1236(options: Vec) -> Result> { + let process = Command::new("dmenu") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; +} + +fn issue1434() { + for _ in 0..100 { + let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor) + .chain_err(|| { + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; + } +} -- cgit 1.4.1-3-g733a5 From f4952d3780761c27cd686244aa490a1e64620e49 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 6 Apr 2017 13:01:19 +1200 Subject: Implement a max array width Fixes #1421 --- src/config.rs | 2 ++ src/expr.rs | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 21ab6cd5447..99d1d360a8a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -352,6 +352,8 @@ create_config! { fn_args_layout: IndentStyle, IndentStyle::Visual, "Layout of function arguments and tuple structs"; array_layout: IndentStyle, IndentStyle::Visual, "Indent on arrays"; + array_width: usize, 60, + "Maximum width of an array literal before falling back to vertical formatting"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; where_style: Style, Style::Default, "Overall strategy for where clauses"; diff --git a/src/expr.rs b/src/expr.rs index b472f283c6c..04634e2645e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -377,13 +377,18 @@ pub fn rewrite_array<'a, I>(expr_iter: I, IndentStyle::Block => { // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { - Some(width) => definitive_tactic(&items, ListTactic::HorizontalVertical, width), + Some(width) => { + let tactic = ListTactic::LimitedHorizontalVertical(context.config.array_width); + definitive_tactic(&items, tactic, width) + } None => DefinitiveListTactic::Vertical, } } IndentStyle::Visual => { if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic(&items, ListTactic::HorizontalVertical, nested_shape.width) + definitive_tactic(&items, + ListTactic::LimitedHorizontalVertical(context.config.array_width), + nested_shape.width) } else { DefinitiveListTactic::Mixed } -- cgit 1.4.1-3-g733a5 From ee9daade3597dc6e94855ab9e90fc9ebfbea6a1f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 6 Apr 2017 21:17:22 +1200 Subject: Fix a bug with overlong function calls --- src/expr.rs | 13 +++++++++++-- tests/source/fn-simple.rs | 9 +++++++++ tests/target/fn-simple.rs | 10 ++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 04634e2645e..2723c4099c1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1715,10 +1715,19 @@ fn rewrite_call_inner(context: &RewriteContext, } } + let one_line_width = shape.width.checked_sub(used_width + 2); + let one_line_width = match one_line_width { + Some(olw) => olw, + None => return Err(Ordering::Greater), + }; + let one_line_shape = Shape { + width: one_line_width, + ..nested_shape + }; let tactic = definitive_tactic(&item_vec, ListTactic::LimitedHorizontalVertical(context.config.fn_call_width), - nested_shape.width); + one_line_width); // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. @@ -1741,7 +1750,7 @@ fn rewrite_call_inner(context: &RewriteContext, } else { context.config.trailing_comma }, - shape: nested_shape, + shape: one_line_shape, ends_with_newline: false, config: context.config, }; diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 1764266718e..e11df34ad86 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -44,3 +44,12 @@ unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, } pub fn start_export_thread(database: &Database, crypto_scheme: &C, block_size: usize, source_path: &Path) -> BonzoResult> {} + +pub fn waltz(cwd: &Path) -> CliAssert { + { + { + formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig); + } + } + +} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 4bcbbd6613f..697fe21501c 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -73,3 +73,13 @@ pub fn start_export_thread source_path: &Path) -> BonzoResult> { } + +pub fn waltz(cwd: &Path) -> CliAssert { + { + { + formatted_comment = + rewrite_comment(comment, block_style, width, offset, formatting_fig); + } + } + +} -- cgit 1.4.1-3-g733a5 From c5f07eda4157aa34a9b882029ab7754f9a7a755f Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 10 Apr 2017 05:25:12 +0800 Subject: fix path check --- src/bin/rustfmt.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 400ee907021..227ab849b3c 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -367,7 +367,16 @@ fn determine_operation(matches: &Matches) -> FmtResult { }); } - let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); + let files: Vec<_> = matches + .free + .iter() + .map(|s| { + let p = PathBuf::from(s); + // we will do comparison later, so here tries to canonicalize first + // to get the expected behavior. + p.canonicalize().unwrap_or(p) + }) + .collect(); Ok(Operation::Format { files: files, -- cgit 1.4.1-3-g733a5 From 8a5038c8f59684d48d2e1d1cedca36dd7fcd77a2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 15 Apr 2017 16:22:26 +0900 Subject: Use offset instead of indent for match arm --- src/expr.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2723c4099c1..a8223fbc400 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1344,11 +1344,10 @@ impl Rewrite for ast::Arm { // 4 = ` => `.len() if shape.width > pat_width + comma.len() + 4 { let arm_shape = shape - .shrink_left(pat_width + 4) + .offset_left(pat_width + 4) .unwrap() .sub_width(comma.len()) - .unwrap() - .block(); + .unwrap(); let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), arm_shape.width); let is_block = if let ast::ExprKind::Block(..) = body.node { true -- cgit 1.4.1-3-g733a5 From 1c1ad525f6c23920cb264b1c9dd95742b700456a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 15 Apr 2017 16:22:54 +0900 Subject: Format source codes --- src/types.rs | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index d766b9770de..0001b5637ab 100644 --- a/src/types.rs +++ b/src/types.rs @@ -587,31 +587,34 @@ impl Rewrite for ast::Ty { let mut_len = mut_str.len(); Some(match *lifetime { Some(ref lifetime) => { - let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); - let lt_str = try_opt!(lifetime.rewrite(context, - Shape::legacy(lt_budget, + let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); + let lt_str = try_opt!(lifetime.rewrite(context, + Shape::legacy(lt_budget, + shape.indent + + 2 + + mut_len))); + let lt_len = lt_str.len(); + let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); + format!("&{} {}{}", + lt_str, + mut_str, + try_opt!(mt.ty + .rewrite(context, + Shape::legacy(budget, shape.indent + 2 + - mut_len))); - let lt_len = lt_str.len(); - let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); - format!("&{} {}{}", - lt_str, - mut_str, - try_opt!(mt.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + 2 + mut_len + - lt_len)))) - } + mut_len + + lt_len)))) + } None => { - let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); - format!("&{}{}", - mut_str, - try_opt!(mt.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + 1 + mut_len)))) - } + let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); + format!("&{}{}", + mut_str, + try_opt!(mt.ty + .rewrite(context, + Shape::legacy(budget, + shape.indent + 1 + + mut_len)))) + } }) } // FIXME: we drop any comments here, even though it's a silly place to put -- cgit 1.4.1-3-g733a5 From 8dc53d3750e3b683673b09785b2787543af19bb8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 15 Apr 2017 16:23:38 +0900 Subject: Check the length of the first line of the last method in the chain --- src/chains.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 0181cd3d099..9dabf2d0322 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -195,12 +195,19 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if fits_single_line { fits_single_line = match expr.node { ref e @ ast::ExprKind::MethodCall(..) => { - rewrite_method_call_with_overflow(e, - &mut last[0], - almost_total, - total_span, - context, - shape) + if rewrite_method_call_with_overflow(e, + &mut last[0], + almost_total, + total_span, + context, + shape) { + // If the first line of the last method does not fit into a single line + // after the others, allow new lines. + let first_line = try_opt!(last[0].lines().nth(0)); + almost_total + first_line.len() < context.config.max_width + } else { + false + } } _ => !last[0].contains('\n'), } -- cgit 1.4.1-3-g733a5 From a91fd699a012ae99bf36d12d88f98154e363979e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 15 Apr 2017 18:40:39 +0900 Subject: Add heuristic choosing block or visual indent for unary op based on span --- src/expr.rs | 35 +++++++++++++++++++++++++++-------- src/patterns.rs | 6 ++++-- src/types.rs | 2 +- 3 files changed, 32 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2723c4099c1..0a17bff9d01 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -157,7 +157,11 @@ fn format_expr(expr: &ast::Expr, }; if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) + rewrite_unary_prefix(context, + &format!("break{} ", id_str), + &**expr, + shape, + expr.span) } else { wrap_str(format!("break{}", id_str), context.config.max_width, shape) } @@ -178,9 +182,11 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Ret(None) => wrap_str("return".to_owned(), context.config.max_width, shape), ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, shape) + rewrite_unary_prefix(context, "return ", &**expr, shape, expr.span) + } + ast::ExprKind::Box(ref expr) => { + rewrite_unary_prefix(context, "box ", &**expr, shape, expr.span) } - ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), ast::ExprKind::AddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, expr, shape) } @@ -222,7 +228,7 @@ fn format_expr(expr: &ast::Expr, } else { delim.into() }; - rewrite_unary_prefix(context, &sp_delim, &**rhs, shape) + rewrite_unary_prefix(context, &sp_delim, &**rhs, shape, expr.span) } (Some(ref lhs), None) => { let sp_delim = if context.config.spaces_around_ranges { @@ -1997,9 +2003,22 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, pub fn rewrite_unary_prefix(context: &RewriteContext, prefix: &str, rewrite: &R, - shape: Shape) + mut shape: Shape, + span: Span) -> Option { - let shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); + // Heuristic: if unary is `&` and `rewrite` contains `{`, + // it is likely that block indent is preferred to visual indent. + if prefix == "&" { + let snippet = String::from(context.snippet(span).trim_left_matches('&')); + let first_line = try_opt!(snippet.lines().nth(0)); + if first_line.contains("{") { + shape = try_opt!(shape.sub_width(prefix.len())).block_indent(0); + } else { + shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); + } + } else { + shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); + } rewrite .rewrite(context, shape) .map(|r| format!("{}{}", prefix, r)) @@ -2031,7 +2050,7 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::Not => "!", ast::UnOp::Neg => "-", }; - rewrite_unary_prefix(context, operator_str, expr, shape) + rewrite_unary_prefix(context, operator_str, expr, shape, expr.span) } fn rewrite_assignment(context: &RewriteContext, @@ -2126,5 +2145,5 @@ fn rewrite_expr_addrof(context: &RewriteContext, ast::Mutability::Immutable => "&", ast::Mutability::Mutable => "&mut ", }; - rewrite_unary_prefix(context, operator_str, expr, shape) + rewrite_unary_prefix(context, operator_str, expr, shape, expr.span) } diff --git a/src/patterns.rs b/src/patterns.rs index bc5c917dc00..1ed13ab70b6 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -27,7 +27,9 @@ use syntax::codemap::{self, BytePos, Span}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), + PatKind::Box(ref pat) => { + rewrite_unary_prefix(context, "box ", &**pat, shape, self.span) + } PatKind::Ident(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { BindingMode::ByRef(mutability) => ("ref ", mutability), @@ -71,7 +73,7 @@ impl Rewrite for Pat { } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); - rewrite_unary_prefix(context, &prefix, &**pat, shape) + rewrite_unary_prefix(context, &prefix, &**pat, shape, self.span) } PatKind::Tuple(ref items, dotdot_pos) => { rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) diff --git a/src/types.rs b/src/types.rs index d766b9770de..b8038de709f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -580,7 +580,7 @@ impl Rewrite for ast::Ty { Mutability::Immutable => "*const ", }; - rewrite_unary_prefix(context, prefix, &*mt.ty, shape) + rewrite_unary_prefix(context, prefix, &*mt.ty, shape, self.span) } ast::TyKind::Rptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); -- cgit 1.4.1-3-g733a5 From 0614e94d0df2d50f7f16e93c469006a31294ec6d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 15 Apr 2017 18:42:45 +0900 Subject: Format source codes --- src/expr.rs | 18 +++++++++--------- src/imports.rs | 6 +++--- tests/target/closure.rs | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0a17bff9d01..7b4153083cb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1230,10 +1230,10 @@ fn rewrite_match(context: &RewriteContext, fn arm_start_pos(arm: &ast::Arm) -> BytePos { let &ast::Arm { - ref attrs, - ref pats, - .. - } = arm; + ref attrs, + ref pats, + .. + } = arm; if !attrs.is_empty() { return attrs[0].span.lo; } @@ -1264,11 +1264,11 @@ impl Rewrite for ast::Arm { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { debug!("Arm::rewrite {:?} {:?}", self, shape); let &ast::Arm { - ref attrs, - ref pats, - ref guard, - ref body, - } = self; + ref attrs, + ref pats, + ref guard, + ref body, + } = self; // FIXME this is all a bit grotty, would be nice to abstract out the // treatment of attributes. diff --git a/src/imports.rs b/src/imports.rs index 791ff0ee387..99651159b2a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -133,9 +133,9 @@ fn rewrite_view_path_prefix(path: &ast::Path, let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && path.segments.len() > 1 { let path = &ast::Path { - span: path.span.clone(), - segments: path.segments[..path.segments.len() - 1].to_owned(), - }; + span: path.span.clone(), + segments: path.segments[..path.segments.len() - 1].to_owned(), + }; try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)) } else { try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)) diff --git a/tests/target/closure.rs b/tests/target/closure.rs index ad6b48aeac9..c9edec799e2 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -74,16 +74,16 @@ fn issue863() { fn issue934() { let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish(); - }; + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; } impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { -- cgit 1.4.1-3-g733a5 From 02c9ac93be959272ffbb3fbbec79dbe9fc734140 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 17 Apr 2017 22:57:07 +0900 Subject: Prohibit long return val from 'rewrite_closure_block' --- src/expr.rs | 13 ++++++++----- src/file_lines.rs | 5 ++--- src/items.rs | 13 +++++++------ src/macros.rs | 11 +++++------ 4 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a8223fbc400..f282f7c0b57 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -172,9 +172,8 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str(context.snippet(expr.span), context.config.max_width, shape) - }) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + .or_else(|| wrap_str(context.snippet(expr.span), context.config.max_width, shape)) } ast::ExprKind::Ret(None) => wrap_str("return".to_owned(), context.config.max_width, shape), ast::ExprKind::Ret(Some(ref expr)) => { @@ -576,14 +575,18 @@ fn rewrite_closure(capture: ast::CaptureBy, let block_threshold = context.config.closure_block_indent_threshold; if block_threshold < 0 || rewrite.matches('\n').count() <= block_threshold as usize { - return Some(format!("{} {}", prefix, rewrite)); + if let Some(rewrite) = wrap_str(rewrite, context.config.max_width, shape) { + return Some(format!("{} {}", prefix, rewrite)); + } } // The body of the closure is big enough to be block indented, that // means we must re-format. let block_shape = shape.block(); let rewrite = try_opt!(block.rewrite(&context, block_shape)); - Some(format!("{} {}", prefix, rewrite)) + Some(format!("{} {}", + prefix, + try_opt!(wrap_str(rewrite, block_shape.width, block_shape)))) } } diff --git a/src/file_lines.rs b/src/file_lines.rs index e68751eb887..f11a0aaf6e2 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -194,9 +194,8 @@ impl JsonSpan { // To allow `collect()`ing into a `MultiMap`. fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - let canonical = try!(canonicalize_path_string(&self.file).map_err(|_| { - format!("Can't canonicalize {}", &self.file) - })); + let canonical = try!(canonicalize_path_string(&self.file) + .map_err(|_| format!("Can't canonicalize {}", &self.file))); Ok((canonical, Range::new(lo, hi))) } } diff --git a/src/items.rs b/src/items.rs index 2cb4e46ecb5..1909b0d2679 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1326,12 +1326,13 @@ pub fn rewrite_associated_type(ident: ast::Ident, let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = ty_param_bounds; - let bound_str = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) - }) - .intersperse(Some(" + ".to_string())) - .collect::>()); + let bound_str = try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) + }) + .intersperse(Some(" + ".to_string())) + .collect::>()); if bounds.len() > 0 { format!(": {}", bound_str) } else { diff --git a/src/macros.rs b/src/macros.rs index fd5578e7f00..0bdc7eb60e0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -146,12 +146,11 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape, true).map(|rw| { - match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - } - }) + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape, true) + .map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) } MacroStyle::Brackets => { // Format macro invocation as array literal. -- cgit 1.4.1-3-g733a5 From bb7b002b2372fbf43ab2f5a2f55784c8df1b767d Mon Sep 17 00:00:00 2001 From: Evgeny Duzhakov Date: Tue, 18 Apr 2017 14:31:53 +0300 Subject: format_lines: fix line_len for config.max_width --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index be4579faba2..8fddece4902 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -496,7 +496,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m // Check for (and record) trailing whitespace. if let Some(lw) = last_wspace { trims.push((cur_line, lw, b)); - line_len -= b - lw; + line_len -= 1; } // Check for any line width errors we couldn't correct. if config.error_on_line_overflow && line_len > config.max_width { @@ -511,7 +511,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m last_wspace = None; } else { newline_count = 0; - line_len += c.len_utf8(); + line_len += 1; if c.is_whitespace() { if last_wspace.is_none() { last_wspace = Some(b); -- cgit 1.4.1-3-g733a5 From 0653b8413e11ea0a75fc86ea3ea08d54762ea594 Mon Sep 17 00:00:00 2001 From: Sheng Hau Date: Wed, 19 Apr 2017 00:23:57 +0800 Subject: Show exit codes' meanings with the rustfmt help message --- Cargo.lock | 2 +- src/bin/rustfmt.rs | 1 + src/summary.rs | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 54a26e545be..99d7721d442 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt" -version = "0.8.2" +version = "0.8.3" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 227ab849b3c..a802c3360ff 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -202,6 +202,7 @@ fn execute(opts: &Options) -> FmtResult { match try!(determine_operation(&matches)) { Operation::Help => { print_usage(opts, ""); + Summary::print_exit_codes(); Ok(Summary::new()) } Operation::Version => { diff --git a/src/summary.rs b/src/summary.rs index 5846afde7fc..6fc1bbded1d 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -63,4 +63,14 @@ impl Summary { self.has_parsing_errors |= other.has_parsing_errors; self.has_diff |= other.has_diff; } + + pub fn print_exit_codes() { + let exit_codes = r#"Exit Codes: + 0 = No errors + 1 = Encountered operational errors e.g. an IO error + 2 = Failed to reformat code because of parsing errors + 3 = Code is valid, but it is impossible to format it properly + 4 = Formatted code differs from existing code (write-mode diff only)"#; + println!("{}", exit_codes); + } } -- cgit 1.4.1-3-g733a5 From b53aeebbcff40b91c1c19424db2393118a5ae335 Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Wed, 19 Apr 2017 17:49:03 +0300 Subject: Fix line length calculation (should be in chars, not bytes) --- src/lib.rs | 2 +- tests/source/max-line-length-in-chars.rs | 4 ++++ tests/target/max-line-length-in-chars.rs | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/source/max-line-length-in-chars.rs create mode 100644 tests/target/max-line-length-in-chars.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index be4579faba2..ddee0cdc286 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -511,7 +511,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m last_wspace = None; } else { newline_count = 0; - line_len += c.len_utf8(); + line_len += 1; if c.is_whitespace() { if last_wspace.is_none() { last_wspace = Some(b); diff --git a/tests/source/max-line-length-in-chars.rs b/tests/source/max-line-length-in-chars.rs new file mode 100644 index 00000000000..d49fbb7e30e --- /dev/null +++ b/tests/source/max-line-length-in-chars.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 25 + +// абвгдеёжзийклмнопрст +fn main() {} diff --git a/tests/target/max-line-length-in-chars.rs b/tests/target/max-line-length-in-chars.rs new file mode 100644 index 00000000000..d49fbb7e30e --- /dev/null +++ b/tests/target/max-line-length-in-chars.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 25 + +// абвгдеёжзийклмнопрст +fn main() {} -- cgit 1.4.1-3-g733a5 From cbd33e1983249a8edfd586d6f51c9c7a964a499c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 24 Apr 2017 16:48:05 +0900 Subject: Remove '+ 1' when counting the length of chains --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 0181cd3d099..27293175abb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -169,7 +169,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let almost_total = rewrites[..rewrites.len() - 1] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); - let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len() + 1) + parent_rewrite.len(); + let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len()) + parent_rewrite.len(); let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 && rewrites.len() > 1 { -- cgit 1.4.1-3-g733a5 From 02cf515be63600c1a2f59ba4ce77695e1ef60ceb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 24 Apr 2017 16:50:11 +0900 Subject: Format source codes --- src/chains.rs | 6 ++---- src/comment.rs | 5 +---- src/expr.rs | 17 ++++------------- src/imports.rs | 5 +---- src/items.rs | 18 ++++-------------- src/lists.rs | 16 +++------------- src/macros.rs | 12 +++--------- src/patterns.rs | 10 +++------- tests/system.rs | 7 ++----- tests/target/chains.rs | 11 +---------- tests/target/long_field_access.rs | 4 +--- 11 files changed, 25 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 27293175abb..1460c446352 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -424,10 +424,8 @@ fn rewrite_method_call(method_name: ast::Ident, let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { - let type_list: Vec<_> = try_opt!(types - .iter() - .map(|ty| ty.rewrite(context, shape)) - .collect()); + let type_list: Vec<_> = + try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) diff --git a/src/comment.rs b/src/comment.rs index 3973c7fc048..9df303c86b2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -99,10 +99,7 @@ pub fn rewrite_comment(orig: &str, config: config, }; - let line_breaks = orig.trim_right() - .chars() - .filter(|&c| c == '\n') - .count(); + let line_breaks = orig.trim_right().chars().filter(|&c| c == '\n').count(); let lines = orig.lines() .enumerate() .map(|(i, mut line)| { diff --git a/src/expr.rs b/src/expr.rs index 2723c4099c1..aa3ab1c41b5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -594,9 +594,7 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && - (block_str[1..] - .find(|c: char| !c.is_whitespace()) - .unwrap() == + (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { "{}".to_owned() } else { @@ -927,16 +925,12 @@ impl<'a> Rewrite for ControlFlow<'a> { // for event in event let between_kwd_cond = - mk_sp(context - .codemap - .span_after(self.span, self.keyword.trim()), + mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), self.pat .map_or(cond_span.lo, |p| if self.matcher.is_empty() { p.span.lo } else { - context - .codemap - .span_before(self.span, self.matcher.trim()) + context.codemap.span_before(self.span, self.matcher.trim()) })); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -1131,10 +1125,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, let first = missed_str .find(|c: char| !c.is_whitespace()) .unwrap_or(missed_str.len()); - if missed_str[..first] - .chars() - .filter(|c| c == &'\n') - .count() >= 2 { + if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { // Excessive vertical whitespace before comment should be preserved // FIXME handle vertical whitespace better result.push('\n'); diff --git a/src/imports.rs b/src/imports.rs index 791ff0ee387..f5ecab2a6a2 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -29,10 +29,7 @@ fn path_of(a: &ast::ViewPath_) -> &ast::Path { } fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { - a.identifier - .name - .as_str() - .cmp(&b.identifier.name.as_str()) + a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) } fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { diff --git a/src/items.rs b/src/items.rs index 2cb4e46ecb5..9ab551ddccc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -242,9 +242,7 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let block_snippet = self.snippet(codemap::mk_sp(block.span.lo, block.span.hi)); - let has_body = !block_snippet[1..block_snippet.len() - 1] - .trim() - .is_empty() || + let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || !context.config.fn_empty_single_line; let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, @@ -1227,10 +1225,7 @@ impl Rewrite for ast::StructField { let type_offset = shape.indent.block_indent(context.config); let rewrite_type_in_next_line = || { - let budget = try_opt!(context - .config - .max_width - .checked_sub(type_offset.width())); + let budget = try_opt!(context.config.max_width.checked_sub(type_offset.width())); self.ty .rewrite(context, Shape::legacy(budget, type_offset)) }; @@ -1624,9 +1619,7 @@ fn rewrite_fn_base(context: &RewriteContext, .ty_params .last() .map_or(span.lo, |tp| end_typaram(tp)); - let args_span = mk_sp(context - .codemap - .span_after(mk_sp(args_start, span.hi), "("), + let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("), span_for_return(&fd.output).lo); let arg_str = try_opt!(rewrite_args(context, &fd.inputs, @@ -1767,10 +1760,7 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let budget = try_opt!(context - .config - .max_width - .checked_sub(indent.block_indent)); + let budget = try_opt!(context.config.max_width.checked_sub(indent.block_indent)); let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, context.config.fn_brace_style, diff --git a/src/lists.rs b/src/lists.rs index 6b917ff29e6..7933ebab807 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -172,9 +172,7 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De let real_total = total_width + total_sep_len; if real_total <= limit && !pre_line_comments && - !items - .into_iter() - .any(|item| item.as_ref().is_multiline()) { + !items.into_iter().any(|item| item.as_ref().is_multiline()) { DefinitiveListTactic::Horizontal } else { DefinitiveListTactic::Vertical @@ -536,10 +534,7 @@ pub fn struct_lit_shape(shape: Shape, IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces); Shape { - width: try_opt!(context - .config - .max_width - .checked_sub(shape.indent.width())), + width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), ..shape } } @@ -556,12 +551,7 @@ pub fn struct_lit_tactic(h_shape: Option, if let Some(h_shape) = h_shape { let mut prelim_tactic = match (context.config.struct_lit_style, items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => { - context - .config - .struct_lit_multiline_style - .to_list_tactic() - } + _ => context.config.struct_lit_multiline_style.to_list_tactic(), }; if prelim_tactic == ListTactic::HorizontalVertical && items.len() > 1 { diff --git a/src/macros.rs b/src/macros.rs index fd5578e7f00..f7f6eb19727 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -196,15 +196,9 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option MacroStyle { let snippet = context.snippet(mac.span); - let paren_pos = snippet - .find_uncommented("(") - .unwrap_or(usize::max_value()); - let bracket_pos = snippet - .find_uncommented("[") - .unwrap_or(usize::max_value()); - let brace_pos = snippet - .find_uncommented("{") - .unwrap_or(usize::max_value()); + let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); + let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); + let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); if paren_pos < bracket_pos && paren_pos < brace_pos { MacroStyle::Parens diff --git a/src/patterns.rs b/src/patterns.rs index bc5c917dc00..8821b7c9146 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -100,10 +100,8 @@ impl Rewrite for Pat { let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. - let pats: Option> = prefix - .chain(slice_pat.into_iter()) - .chain(suffix) - .collect(); + let pats: Option> = + prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); // Check that all the rewrites succeeded, and if not return None. let pats = try_opt!(pats); @@ -242,9 +240,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], context: &RewriteContext, shape: Shape) -> Option { - let mut pat_vec: Vec<_> = pats.into_iter() - .map(|x| TuplePatField::Pat(x)) - .collect(); + let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); if let Some(pos) = dotdot_pos { let prev = if pos == 0 { diff --git a/tests/system.rs b/tests/system.rs index 0d7c47feb32..5b128aa6b35 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -28,9 +28,7 @@ const DIFF_CONTEXT_SIZE: usize = 3; fn get_path_string(dir_entry: io::Result) -> String { let path = dir_entry.expect("Couldn't get DirEntry").path(); - path.to_str() - .expect("Couldn't stringify path") - .to_owned() + path.to_str().expect("Couldn't stringify path").to_owned() } // Integration tests. The files in the tests/source are formatted and compared @@ -337,8 +335,7 @@ fn handle_result(result: HashMap, let mut f = fs::File::open(&target).expect("Couldn't open target"); let mut text = String::new(); - f.read_to_string(&mut text) - .expect("Failed reading target"); + f.read_to_string(&mut text).expect("Failed reading target"); if fmt_text != text { let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 1d9b8a08622..2b14ec147d4 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -137,16 +137,7 @@ fn try_shorthand() { let y = expr.kaas()?.test(); let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; - let yyyy = expr? - .another? - .another? - .another? - .another? - .another? - .another? - .another? - .another? - .test(); + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); let zzzz = expr?.another?.another?.another?.another?; let aaa = x??????????????????????????????????????????????????????????????????????????; diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs index d47a7d5a13e..349d2c2f639 100644 --- a/tests/target/long_field_access.rs +++ b/tests/target/long_field_access.rs @@ -1,6 +1,4 @@ fn f() { - block_flow - .base - .stacking_relative_position_of_display_port = + block_flow.base.stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; } -- cgit 1.4.1-3-g733a5 From 4cec3ab71d49d1971f58812a522ff3112d396796 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 26 Apr 2017 17:29:56 +0900 Subject: Prevent panicking against directories or non-existent files --- src/bin/rustfmt.rs | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 400ee907021..d5bc534bc02 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -258,21 +258,29 @@ fn execute(opts: &Options) -> FmtResult { let mut error_summary = Summary::new(); for file in files { - // Check the file directory if the config-path could not be read or not provided - if path.is_none() { - let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap())?; - if options.verbose { - if let Some(path) = path_tmp.as_ref() { - println!("Using rustfmt config file {} for {}", - path.display(), - file.display()); + if !file.exists() { + println!("Error: file `{}` does not exist", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else if file.is_dir() { + println!("Error: `{}` is a directory", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else { + // Check the file directory if the config-path could not be read or not provided + if path.is_none() { + let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap())?; + if options.verbose { + if let Some(path) = path_tmp.as_ref() { + println!("Using rustfmt config file {} for {}", + path.display(), + file.display()); + } } + config = config_tmp; } - config = config_tmp; - } - options.clone().apply_to(&mut config); - error_summary.add(run(Input::File(file), &config)); + options.clone().apply_to(&mut config); + error_summary.add(run(Input::File(file), &config)); + } } Ok(error_summary) } -- cgit 1.4.1-3-g733a5 From 5d9a35050d2b77613e95dbbfa890dd6bfd832812 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 1 May 2017 16:05:38 +1200 Subject: Remove where_indent option --- src/config.rs | 2 -- tests/config/small_tabs.toml | 1 - tests/source/fn-custom-2.rs | 1 - tests/source/fn-custom-6.rs | 1 - tests/source/fn-custom-8.rs | 1 - tests/target/fn-custom-2.rs | 1 - tests/target/fn-custom-6.rs | 1 - tests/target/fn-custom-8.rs | 1 - 8 files changed, 9 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 99d1d360a8a..d05f6c9ea48 100644 --- a/src/config.rs +++ b/src/config.rs @@ -360,8 +360,6 @@ create_config! { // Should we at least try to put the where clause on the same line as the rest of the // function decl? where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; - // Visual will be treated like Tabbed - where_indent: IndentStyle, IndentStyle::Block, "Indentation of a where clause"; where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: IndentStyle, IndentStyle::Visual, "Indentation style of a where predicate"; diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 57319012bc3..a682a88e811 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -8,7 +8,6 @@ fn_args_paren_newline = true fn_args_density = "Tall" fn_args_layout = "Visual" where_density = "Tall" -where_indent = "Block" where_layout = "Vertical" where_pred_indent = "Visual" generics_indent = "Visual" diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index 4a86f8c2d28..8c6813b054f 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,6 +1,5 @@ // rustfmt-fn_args_layout: Block // rustfmt-generics_indent: Block -// rustfmt-where_indent: Block // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index fbac1bb1807..c056985c796 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,5 +1,4 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs index 5c4d51c0387..0855ca1058f 100644 --- a/tests/source/fn-custom-8.rs +++ b/tests/source/fn-custom-8.rs @@ -1,5 +1,4 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index f0251b70b58..c2b012e52ab 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,6 +1,5 @@ // rustfmt-fn_args_layout: Block // rustfmt-generics_indent: Block -// rustfmt-where_indent: Block // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index af58492497c..487d1d8b7ea 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,5 +1,4 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index d029982728f..b32fc5d7cf2 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -1,5 +1,4 @@ // rustfmt-fn_args_layout: Block -// rustfmt-where_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. -- cgit 1.4.1-3-g733a5 From 3d2cd681ae76d0c1444238d54384e1d3cb3d35fc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 19 Apr 2017 10:14:27 +0900 Subject: Use 'first_line_width' --- src/chains.rs | 3 +- tests/source/match.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/target/match.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9dabf2d0322..a2485cab69f 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -203,8 +203,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - shape) { // If the first line of the last method does not fit into a single line // after the others, allow new lines. - let first_line = try_opt!(last[0].lines().nth(0)); - almost_total + first_line.len() < context.config.max_width + almost_total + first_line_width(&last[0]) < context.config.max_width } else { false } diff --git a/tests/source/match.rs b/tests/source/match.rs index 2fb584c322c..43b0b033ea6 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -295,3 +295,81 @@ fn guards() { (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {} } } + +fn issue1371() { + Some(match type_ { + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; + + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => { + TextEntered { + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + } + } + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; + + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; + + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) +} + +fn issue1395() { + let bar = Some(true); + let foo = Some(true); + let mut x = false; + bar.and_then(|_| { + match foo { + None => None, + Some(b) => { + x = true; + Some(b) + } + } + }); +} + +fn issue1456() { + Ok(Recording { + artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 75156347978..0da943d28f7 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -310,3 +310,82 @@ fn guards() { cccccccccccccccccccccccccccccccccccccccc) => {} } } + +fn issue1371() { + Some(match type_ { + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; + + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => { + TextEntered { + unicode: + unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + } + } + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; + + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; + + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) +} + +fn issue1395() { + let bar = Some(true); + let foo = Some(true); + let mut x = false; + bar.and_then(|_| match foo { + None => None, + Some(b) => { + x = true; + Some(b) + } + }); +} + +fn issue1456() { + Ok(Recording { + artists: match reader + .evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context) + .and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) +} -- cgit 1.4.1-3-g733a5 From af3f4c7f298f28965fee571945ecde1344b6908b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 14 Apr 2017 19:27:05 +0900 Subject: Remove duplicates --- src/chains.rs | 53 +++++++++++++++++++++-------------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1460c446352..8c405c1f6ef 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -104,11 +104,16 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - parent_shape = chain_indent(context, shape); } let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape)); + let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let (nested_shape, extend) = if !parent_rewrite.contains('\n') && is_continuable(&parent) { - let nested_shape = if let ast::ExprKind::Try(..) = subexpr_list.last().unwrap().node { + let first_subexpr_is_try = match subexpr_list.last().unwrap().node { + ast::ExprKind::Try(..) => true, + _ => false, + }; + let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + let nested_shape = if first_subexpr_is_try { parent_shape.block_indent(context.config.tab_spaces) } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) @@ -120,7 +125,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // The parent is a block, so align the rest of the chain with the closing // brace. (parent_shape, false) - } else if parent_rewrite.contains('\n') { + } else if parent_rewrite_contains_newline { (chain_indent(context, parent_shape.block_indent(context.config.tab_spaces)), false) @@ -137,9 +142,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ..nested_shape }; let first_child_shape = if extend { - let mut shape = try_opt!(parent_shape.shrink_left(last_line_width(&parent_rewrite))); + let mut shape = try_opt!(parent_shape.offset_left(last_line_width(&parent_rewrite))); match context.config.chain_indent { - IndentStyle::Visual => other_child_shape, + IndentStyle::Visual => shape, IndentStyle::Block => { shape.offset = shape .offset @@ -207,7 +212,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } } - let connector = if fits_single_line && !parent_rewrite.contains('\n') { + let connector = if fits_single_line && !parent_rewrite_contains_newline { // Yay, we can put everything on one line. String::new() } else { @@ -215,9 +220,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - format!("\n{}", nested_shape.indent.to_string(context.config)) }; - let first_connector = if extend || subexpr_list.is_empty() { - "" - } else if let ast::ExprKind::Try(_) = subexpr_list.last().unwrap().node { + let first_connector = if extend || subexpr_list.is_empty() || first_subexpr_is_try { "" } else { &*connector @@ -375,33 +378,19 @@ fn rewrite_chain_subexpr(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { + let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width { + Some(expr_str) + } else { + None + }; + match expr.node { ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => { rewrite_method_call(method_name.node, types, expressions, span, context, shape) } - ast::ExprKind::Field(_, ref field) => { - let s = format!(".{}", field.node); - if s.len() <= shape.width { - Some(s) - } else { - None - } - } - ast::ExprKind::TupField(_, ref field) => { - let s = format!(".{}", field.node); - if s.len() <= shape.width { - Some(s) - } else { - None - } - } - ast::ExprKind::Try(_) => { - if shape.width >= 1 { - Some("?".into()) - } else { - None - } - } + ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), + ast::ExprKind::TupField(_, ref field) => rewrite_element(format!(".{}", field.node)), + ast::ExprKind::Try(_) => rewrite_element(String::from("?")), _ => unreachable!(), } } -- cgit 1.4.1-3-g733a5 From 883db2f95268f24613ac50cf9aea7f8d24e10275 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 19 Apr 2017 18:52:56 +0900 Subject: Refactor Shape --- src/lib.rs | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 8fddece4902..cae298dbb62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -262,10 +262,7 @@ impl Shape { let alignment = self.offset + extra_width; Shape { width: self.width, - indent: Indent { - block_indent: self.indent.block_indent, - alignment: alignment, - }, + indent: Indent::new(self.indent.block_indent, alignment), offset: alignment, } } @@ -274,19 +271,13 @@ impl Shape { if self.indent.alignment == 0 { Shape { width: self.width, - indent: Indent { - block_indent: self.indent.block_indent + extra_width, - alignment: 0, - }, + indent: Indent::new(self.indent.block_indent + extra_width, 0), offset: 0, } } else { Shape { width: self.width, - indent: Indent { - block_indent: self.indent.block_indent, - alignment: self.indent.alignment + extra_width, - }, + indent: self.indent + extra_width, offset: self.indent.alignment + extra_width, } } @@ -295,10 +286,7 @@ impl Shape { pub fn add_offset(&self, extra_width: usize) -> Shape { Shape { width: self.width, - indent: Indent { - block_indent: self.indent.block_indent, - alignment: self.indent.alignment, - }, + indent: self.indent, offset: self.offset + extra_width, } } @@ -306,10 +294,7 @@ impl Shape { pub fn block(&self) -> Shape { Shape { width: self.width, - indent: Indent { - block_indent: self.indent.block_indent, - alignment: 0, - }, + indent: self.indent.block_only(), offset: self.offset, } } -- cgit 1.4.1-3-g733a5 From 68c5915176aa817644292064b865fb3adf23f745 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 19 Apr 2017 22:48:45 +0900 Subject: Remove TODO from 'rewrite_generics' --- src/items.rs | 76 ++++++++++++++++++++++++------------------------------------ 1 file changed, 30 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9ab551ddccc..01758bb9a75 100644 --- a/src/items.rs +++ b/src/items.rs @@ -38,7 +38,8 @@ impl Rewrite for ast::Local { shape.indent); let mut result = "let ".to_owned(); - let pat_shape = try_opt!(shape.offset_left(result.len())); + // 4 = "let ".len() + let pat_shape = try_opt!(shape.offset_left(4)); // 1 = ; let pat_shape = try_opt!(pat_shape.sub_width(1)); let pat_str = try_opt!(self.pat.rewrite(&context, pat_shape)); @@ -70,7 +71,6 @@ impl Rewrite for ast::Local { if let Some(ref ex) = self.init { // 1 = trailing semicolon; - //let budget = try_opt!(shape.width.checked_sub(shape.indent.block_only().width() + 1)); let nested_shape = try_opt!(shape.sub_width(1)); result = try_opt!(rewrite_assign_rhs(&context, result, ex, nested_shape)); @@ -380,7 +380,6 @@ impl<'a> FmtVisitor<'a> { self.config.item_brace_style, enum_def.variants.is_empty(), self.block_indent, - self.block_indent.block_indent(self.config), mk_sp(span.lo, body_start)) .unwrap(); self.buffer.push_str(&generics_str); @@ -644,12 +643,9 @@ fn format_impl_ref_and_type(context: &RewriteContext, Some(ref tr) => tr.path.span.lo, None => self_ty.span.lo, }; - let generics_str = try_opt!(rewrite_generics(context, - generics, - Shape::legacy(context.config.max_width, - offset), - offset + result.len(), - mk_sp(lo, hi))); + let generics_indent = offset + last_line_width(&result); + let shape = try_opt!(generics_shape(context.config, generics_indent)); + let generics_str = try_opt!(rewrite_generics(context, generics, shape, mk_sp(lo, hi))); result.push_str(&generics_str); if polarity == ast::ImplPolarity::Negative { @@ -759,12 +755,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); - let generics_str = try_opt!(rewrite_generics(context, - generics, - Shape::legacy(context.config.max_width, - offset), - offset + result.len(), - mk_sp(item.span.lo, body_lo))); + let generics_indent = offset + last_line_width(&result); + let shape = try_opt!(generics_shape(context.config, generics_indent)); + let generics_str = + try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo))); result.push_str(&generics_str); let trait_bound_str = @@ -902,7 +896,6 @@ fn format_struct_struct(context: &RewriteContext, context.config.item_brace_style, fields.is_empty(), offset, - offset + header_str.len(), mk_sp(span.lo, body_lo))) } None => { @@ -1011,12 +1004,10 @@ fn format_tuple_struct(context: &RewriteContext, let where_clause_str = match generics { Some(generics) => { - let generics_str = try_opt!(rewrite_generics(context, - generics, - Shape::legacy(context.config.max_width, - offset), - offset + header_str.len(), - mk_sp(span.lo, body_lo))); + let generics_indent = offset + last_line_width(&header_str); + let shape = try_opt!(generics_shape(context.config, generics_indent)); + let generics_str = + try_opt!(rewrite_generics(context, generics, shape, mk_sp(span.lo, body_lo))); result.push_str(&generics_str); let where_budget = try_opt!(context @@ -1130,12 +1121,9 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let generics_width = context.config.max_width - " =".len(); - let generics_str = try_opt!(rewrite_generics(context, - generics, - Shape::legacy(generics_width, indent), - generics_indent, - generics_span)); + let shape = try_opt!(try_opt!(generics_shape(context.config, generics_indent)) + .sub_width(" =".len())); + let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); @@ -1551,13 +1539,10 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(&ident.to_string()); // Generics. - let generics_indent = indent + result.len(); + let generics_indent = indent + last_line_width(&result); let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); - let generics_str = try_opt!(rewrite_generics(context, - generics, - Shape::legacy(context.config.max_width, indent), - generics_indent, - generics_span)); + let shape = try_opt!(generics_shape(context.config, generics_indent)); + let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); let snuggle_angle_bracket = last_line_width(&generics_str) == 1; @@ -1964,8 +1949,6 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { fn rewrite_generics(context: &RewriteContext, generics: &ast::Generics, shape: Shape, - // TODO shouldn't need this - generics_offset: Indent, span: Span) -> Option { // FIXME: convert bounds to where clauses where they get too big or if @@ -1977,12 +1960,12 @@ fn rewrite_generics(context: &RewriteContext, } let offset = match context.config.generics_indent { - IndentStyle::Block => shape.indent.block_indent(context.config), + IndentStyle::Block => shape.indent.block_only().block_indent(context.config), // 1 = < - IndentStyle::Visual => generics_offset + 1, + IndentStyle::Visual => shape.indent + 1, }; - let h_budget = try_opt!(shape.width.checked_sub(generics_offset.width() + 2)); + let h_budget = try_opt!(shape.width.checked_sub(2)); // FIXME: might need to insert a newline if the generics are really long. // Strings for the generics. @@ -2022,7 +2005,7 @@ fn rewrite_generics(context: &RewriteContext, format!("<\n{}{}\n{}>", offset.to_string(context.config), list_str, - shape.indent.to_string(context.config)) + shape.indent.block_only().to_string(context.config)) } else if context.config.spaces_within_angle_brackets { format!("< {} >", list_str) } else { @@ -2224,14 +2207,10 @@ fn format_generics(context: &RewriteContext, brace_style: BraceStyle, force_same_line_brace: bool, offset: Indent, - generics_offset: Indent, span: Span) -> Option { - let mut result = try_opt!(rewrite_generics(context, - generics, - Shape::legacy(context.config.max_width, offset), - generics_offset, - span)); + let shape = try_opt!(generics_shape(context.config, offset)); + let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = try_opt!(context @@ -2273,3 +2252,8 @@ fn format_generics(context: &RewriteContext, Some(result) } + +fn generics_shape(config: &Config, indent: Indent) -> Option { + Some(Shape::legacy(try_opt!(config.max_width.checked_sub(indent.width())), + indent)) +} -- cgit 1.4.1-3-g733a5 From 9dc643a6ae7e37c0b74e914d6e9835fd99d9b117 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 19 Apr 2017 23:33:03 +0900 Subject: Remove TODO from 'format_tuple_struct' --- src/items.rs | 43 +++++++++++++++++-------------------------- src/lib.rs | 2 +- 2 files changed, 18 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 01758bb9a75..7021f0c2ae5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1041,33 +1041,24 @@ fn format_tuple_struct(context: &RewriteContext, .config .max_width .checked_sub(item_indent.width() + 3)); + let shape = Shape::legacy(item_budget, item_indent); - let items = - itemize_list(context.codemap, - fields.iter(), - ")", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), - context.codemap.span_after(span, "("), - span.hi); - let body_budget = try_opt!(context - .config - .max_width - .checked_sub(offset.block_only().width() + result.len() + - 3)); - let body = try_opt!(list_helper(items, - // TODO budget is wrong in block case - Shape::legacy(body_budget, item_indent), - context.config, - tactic)); + let items = itemize_list(context.codemap, + fields.iter(), + ")", + |field| { + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.ty.span.hi, + |field| field.rewrite(context, shape), + context.codemap.span_after(span, "("), + span.hi); + let body = try_opt!(list_helper(items, shape, context.config, tactic)); if context.config.fn_args_layout == IndentStyle::Visual || !body.contains('\n') { result.push('('); diff --git a/src/lib.rs b/src/lib.rs index cae298dbb62..f7383fbc41e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -158,7 +158,7 @@ impl Indent { let (num_tabs, num_spaces) = if config.hard_tabs { (self.block_indent / config.tab_spaces, self.alignment) } else { - (0, self.block_indent + self.alignment) + (0, self.width()) }; let num_chars = num_tabs + num_spaces; let mut indent = String::with_capacity(num_chars); -- cgit 1.4.1-3-g733a5 From c7e9bcadaab1665b5e46797984c6a8ab3885718a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 1 May 2017 18:52:43 +0900 Subject: Use block indent when visual indent exceeds max_width --- src/expr.rs | 8 +++++--- tests/source/large_vec.rs | 29 +++++++++++++++++++++++++++++ tests/target/large_vec.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 tests/source/large_vec.rs create mode 100644 tests/target/large_vec.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2723c4099c1..f78dd7bbc5f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2091,13 +2091,15 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, let new_offset = shape.indent.block_indent(context.config); let max_width = try_opt!((shape.width + shape.indent.width()) .checked_sub(new_offset.width())); - let new_rhs = ex.rewrite(context, Shape::legacy(max_width, new_offset)); + let new_shape = Shape::legacy(max_width, new_offset); + let new_rhs = ex.rewrite(context, new_shape); // FIXME: DRY! match (rhs, new_rhs) { (Some(ref orig_rhs), Some(ref replacement_rhs)) - if count_line_breaks(orig_rhs) > - count_line_breaks(replacement_rhs) + 1 => { + if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 || + (orig_rhs.rewrite(context, shape).is_none() && + replacement_rhs.rewrite(context, new_shape).is_some()) => { result.push_str(&format!("\n{}", new_offset.to_string(context.config))); result.push_str(replacement_rhs); } diff --git a/tests/source/large_vec.rs b/tests/source/large_vec.rs new file mode 100644 index 00000000000..34d5bf39954 --- /dev/null +++ b/tests/source/large_vec.rs @@ -0,0 +1,29 @@ +// See #1470. + +impl Environment { + pub fn new_root() -> Rc> { + let mut env = Environment::new(); + let builtin_functions = &[("println", + Function::NativeVoid(CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println)), + ("run_http_server", + Function::NativeVoid(CallSign { + num_params: 1, + variadic: false, + param_types: + vec![Some(ConstraintType::Function)], + }, + native_run_http_server)), + ("len", + Function::NativeReturning(CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len))]; + } +} diff --git a/tests/target/large_vec.rs b/tests/target/large_vec.rs new file mode 100644 index 00000000000..44f6d52650c --- /dev/null +++ b/tests/target/large_vec.rs @@ -0,0 +1,29 @@ +// See #1470. + +impl Environment { + pub fn new_root() -> Rc> { + let mut env = Environment::new(); + let builtin_functions = + &[("println", + Function::NativeVoid(CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println)), + ("run_http_server", + Function::NativeVoid(CallSign { + num_params: 1, + variadic: false, + param_types: vec![Some(ConstraintType::Function)], + }, + native_run_http_server)), + ("len", + Function::NativeReturning(CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len))]; + } +} -- cgit 1.4.1-3-g733a5 From c6f1dd4fb5f3d503cb456cda8d3d476efaaa1dcf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 2 May 2017 07:56:46 +1200 Subject: Remove generics_style option --- src/config.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index d05f6c9ea48..31722fd9fc2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -363,7 +363,6 @@ create_config! { where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: IndentStyle, IndentStyle::Visual, "Indentation style of a where predicate"; - generics_style: Style, Style::Default, "Overall strategy for generics"; generics_indent: IndentStyle, IndentStyle::Visual, "Indentation of generics"; struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, -- cgit 1.4.1-3-g733a5 From 5ae74cab8ffe9a23ec36c16b8d05750def87a458 Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Mon, 1 May 2017 22:01:19 +0200 Subject: Add todo on equal output for `where_density = Tall` or `Vertical` --- src/config.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index d05f6c9ea48..bdea5303163 100644 --- a/src/config.rs +++ b/src/config.rs @@ -357,8 +357,10 @@ create_config! { type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; where_style: Style, Style::Default, "Overall strategy for where clauses"; - // Should we at least try to put the where clause on the same line as the rest of the + // TODO: + // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? + // 2. Currently options `Tall` and `Vertical` produce the same output. where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: IndentStyle, IndentStyle::Visual, -- cgit 1.4.1-3-g733a5 From 42dbe482e3c37ddab6a7138ae5372e1d4831293e Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Mon, 24 Apr 2017 19:59:21 +0200 Subject: Made `type_punctuation_density` apply too all `+` in types --- src/items.rs | 15 +++++++++++---- src/types.rs | 25 ++++++++++++++++++++----- tests/source/type-punctuation.rs | 27 +++++++++++++++++++++++++++ tests/target/type-punctuation.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 66040362d52..7a4aa781305 100644 --- a/src/items.rs +++ b/src/items.rs @@ -21,7 +21,7 @@ use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annota use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style}; +use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity}; use itertools::Itertools; use syntax::{ast, abi, codemap, ptr, symbol}; @@ -1299,13 +1299,17 @@ pub fn rewrite_associated_type(ident: ast::Ident, let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!(bounds .iter() .map(|ty_bound| { ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) }) - .intersperse(Some(" + ".to_string())) + .intersperse(Some(joiner.to_string())) .collect::>()); if bounds.len() > 0 { format!(": {}", bound_str) @@ -2015,11 +2019,14 @@ fn rewrite_trait_bounds(context: &RewriteContext, if bounds.is_empty() { return Some(String::new()); } - + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; let bound_str = try_opt!(bounds .iter() .map(|ty_bound| ty_bound.rewrite(&context, shape)) - .intersperse(Some(" + ".to_string())) + .intersperse(Some(joiner.to_string())) .collect::>()); let mut result = String::new(); diff --git a/src/types.rs b/src/types.rs index c0a40720fc3..ca98401db14 100644 --- a/src/types.rs +++ b/src/types.rs @@ -370,6 +370,10 @@ impl Rewrite for ast::WherePredicate { .intersperse(Some(", ".to_string())) .collect()); + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(shape.width.checked_sub(used_width)); @@ -379,7 +383,7 @@ impl Rewrite for ast::WherePredicate { Shape::legacy(budget, shape.indent + used_width)) }) - .intersperse(Some(" + ".to_string())) + .intersperse(Some(joiner.to_string())) .collect()); if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { @@ -392,6 +396,10 @@ impl Rewrite for ast::WherePredicate { format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) } } else { + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; let used_width = type_str.len() + colon.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds.iter() @@ -400,7 +408,7 @@ impl Rewrite for ast::WherePredicate { Shape::legacy(budget, shape.indent + used_width)) }) - .intersperse(Some(" + ".to_string())) + .intersperse(Some(joiner.to_string())) .collect()); format!("{}{}{}", type_str, colon, bounds_str) @@ -456,7 +464,11 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, .map(|b| b.rewrite(context, shape)) .collect()); let colon = type_bound_colon(context); - let result = format!("{}{}{}", result, colon, appendix.join(" + ")); + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let result = format!("{}{}{}", result, colon, appendix.join(joiner)); wrap_str(result, context.config.max_width, shape) } } @@ -509,12 +521,15 @@ impl Rewrite for ast::TyParam { if context.config.space_after_bound_colon { result.push_str(" "); } - + let joiner = match context.config.type_punctuation_density { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; let bounds: String = try_opt!(self.bounds .iter() .map(|ty_bound| ty_bound.rewrite(context, shape)) - .intersperse(Some(" + ".to_string())) + .intersperse(Some(joiner.to_string())) .collect()); result.push_str(&bounds); diff --git a/tests/source/type-punctuation.rs b/tests/source/type-punctuation.rs index 29c2f5a4e3b..0980e4a3732 100644 --- a/tests/source/type-punctuation.rs +++ b/tests/source/type-punctuation.rs @@ -1,5 +1,32 @@ // rustfmt-type_punctuation_density: Compressed +struct Foo + where U: Eq + Clone { + // body +} + +trait Foo<'a, T = usize> + where T: 'a + Eq + Clone +{ + type Bar: Eq + Clone; +} + +trait Foo: Eq + Clone { + // body +} + +impl Foo<'a> for Bar + where for<'a> T: 'a + Eq + Clone +{ + // body +} + +fn foo<'a, 'b, 'c>() + where 'a: 'b + 'c +{ + // body +} + fn Foo + Foo>() { let i = 6; } diff --git a/tests/target/type-punctuation.rs b/tests/target/type-punctuation.rs index 2e5725b3db9..e7021eca84f 100644 --- a/tests/target/type-punctuation.rs +++ b/tests/target/type-punctuation.rs @@ -1,5 +1,32 @@ // rustfmt-type_punctuation_density: Compressed +struct Foo + where U: Eq+Clone { + // body +} + +trait Foo<'a, T=usize> + where T: 'a+Eq+Clone +{ + type Bar: Eq+Clone; +} + +trait Foo: Eq+Clone { + // body +} + +impl Foo<'a> for Bar + where for<'a> T: 'a+Eq+Clone +{ + // body +} + +fn foo<'a, 'b, 'c>() + where 'a: 'b+'c +{ + // body +} + fn Foo+Foo>() { let i = 6; } -- cgit 1.4.1-3-g733a5 From 19599b9a018f3e0da6a75bf6a80a17523bab90e5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 1 May 2017 20:00:21 +0900 Subject: Use block when arm exceeds max_width --- src/expr.rs | 4 +++- tests/source/match.rs | 7 +++++++ tests/target/match.rs | 9 +++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d64a9a75ad3..25d9a1ed397 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1356,7 +1356,9 @@ impl Rewrite for ast::Arm { }; match rewrite { - Some(ref body_str) if !body_str.contains('\n') || !context.config.wrap_match_arms || + Some(ref body_str) if (!body_str.contains('\n') && + body_str.len() <= arm_shape.width) || + !context.config.wrap_match_arms || is_block => { let block_sep = match context.config.control_brace_style { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), diff --git a/tests/source/match.rs b/tests/source/match.rs index 43b0b033ea6..3ed0f89ad7c 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -373,3 +373,10 @@ fn issue1456() { }, }) } + +fn issue1460() { + let _ = match foo { + REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => "internal_spec_insert_internal_spec_insert_internal_spec_insert", + _ => "reorder_something", + }; +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 0da943d28f7..2d0194f5613 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -389,3 +389,12 @@ fn issue1456() { }, }) } + +fn issue1460() { + let _ = match foo { + REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => { + "internal_spec_insert_internal_spec_insert_internal_spec_insert" + } + _ => "reorder_something", + }; +} -- cgit 1.4.1-3-g733a5 From 2e00c117e553277428052edb5f8c52c6062676de Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 14 Apr 2017 20:25:47 +0900 Subject: Handle empty tuple struct def properly --- src/items.rs | 124 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7a4aa781305..ff24a87ec60 100644 --- a/src/items.rs +++ b/src/items.rs @@ -908,7 +908,6 @@ fn format_struct_struct(context: &RewriteContext, }; result.push_str(&generics_str); - // FIXME(#919): properly format empty structs and their comments. if fields.is_empty() { let snippet = context.snippet(mk_sp(body_lo, span.hi - BytePos(1))); if snippet.trim().is_empty() { @@ -995,9 +994,8 @@ fn format_tuple_struct(context: &RewriteContext, let header_str = format_header(item_name, ident, vis); result.push_str(&header_str); - // FIXME(#919): don't lose comments on empty tuple structs. let body_lo = if fields.is_empty() { - span.hi + context.codemap.span_after(span, "(") } else { fields[0].span.lo }; @@ -1027,58 +1025,84 @@ fn format_tuple_struct(context: &RewriteContext, None => "".to_owned(), }; - let (tactic, item_indent) = match context.config.fn_args_layout { - IndentStyle::Visual => { - // 1 = `(` - (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) - } - IndentStyle::Block => { - (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) - } - }; - // 3 = `();` - let item_budget = try_opt!(context - .config - .max_width - .checked_sub(item_indent.width() + 3)); - let shape = Shape::legacy(item_budget, item_indent); - - let items = itemize_list(context.codemap, - fields.iter(), - ")", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, shape), - context.codemap.span_after(span, "("), - span.hi); - let body = try_opt!(list_helper(items, shape, context.config, tactic)); - - if context.config.fn_args_layout == IndentStyle::Visual || !body.contains('\n') { + if fields.is_empty() { result.push('('); - if context.config.spaces_within_parens && body.len() > 0 { - result.push(' '); + let snippet = context.snippet(mk_sp(body_lo, context.codemap.span_before(span, ")"))); + if snippet.is_empty() { + // + } else if snippet + .trim_right_matches(&[' ', '\t'][..]) + .ends_with('\n') { + result.push_str(&snippet.trim_right()); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push_str(&snippet); } + result.push(')'); + } else { + let (tactic, item_indent) = match context.config.fn_args_layout { + IndentStyle::Visual => { + // 1 = `(` + (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) + } + IndentStyle::Block => { + (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) + } + }; + // 3 = `();` + let item_budget = try_opt!(context + .config + .max_width + .checked_sub(item_indent.width() + 3)); + + let items = + itemize_list(context.codemap, + fields.iter(), + ")", + |field| { + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.ty.span.hi, + |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), + context.codemap.span_after(span, "("), + span.hi); + let body_budget = try_opt!(context + .config + .max_width + .checked_sub(offset.block_only().width() + result.len() + + 3)); + let body = try_opt!(list_helper(items, + // TODO budget is wrong in block case + Shape::legacy(body_budget, item_indent), + context.config, + tactic)); + + if context.config.fn_args_layout == IndentStyle::Visual || !body.contains('\n') { + result.push('('); + if context.config.spaces_within_parens && body.len() > 0 { + result.push(' '); + } - result.push_str(&body); + result.push_str(&body); - if context.config.spaces_within_parens && body.len() > 0 { - result.push(' '); + if context.config.spaces_within_parens && body.len() > 0 { + result.push(' '); + } + result.push(')'); + } else { + result.push_str("(\n"); + result.push_str(&item_indent.to_string(&context.config)); + result.push_str(&body); + result.push('\n'); + result.push_str(&offset.block_only().to_string(&context.config)); + result.push(')'); } - result.push(')'); - } else { - result.push_str("(\n"); - result.push_str(&item_indent.to_string(&context.config)); - result.push_str(&body); - result.push('\n'); - result.push_str(&offset.block_only().to_string(&context.config)); - result.push(')'); } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && -- cgit 1.4.1-3-g733a5 From 93dae1a34d3e2d930b861fbf9f4818e3e0656ae2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 14 Apr 2017 22:39:20 +0900 Subject: Add test for empty tuple struct with comment --- src/items.rs | 2 +- tests/source/structs.rs | 2 +- tests/target/structs.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ff24a87ec60..8ea97b177e8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1029,7 +1029,7 @@ fn format_tuple_struct(context: &RewriteContext, result.push('('); let snippet = context.snippet(mk_sp(body_lo, context.codemap.span_before(span, ")"))); if snippet.is_empty() { - // + // `struct S ()` } else if snippet .trim_right_matches(&[' ', '\t'][..]) .ends_with('\n') { diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 5786fef4839..28bb95e1a2d 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -166,7 +166,7 @@ struct Foo { } struct Foo { /* comment */ } -struct Foo(); +struct Foo( /* comment */ ); struct LongStruct { a: A, diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 2906d39759b..358172ae838 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -170,7 +170,7 @@ struct Foo { // trailing space -> } struct Foo { /* comment */ } -struct Foo(); +struct Foo( /* comment */ ); struct LongStruct { a: A, -- cgit 1.4.1-3-g733a5 From 3f703fd33d8412fb870bd06fa14ffba087d33b3c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 3 May 2017 11:21:31 +0900 Subject: Use block indent when visual indent failed inside closure block --- src/expr.rs | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 25d9a1ed397..75a7ff21abe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -570,6 +570,19 @@ fn rewrite_closure(capture: ast::CaptureBy, rewrite.map(|rw| format!("{} {}", prefix, rw)) } + fn no_weird_visual_indent(block_str: &str, context: &RewriteContext) -> bool { + let mut prev_indent_width = 0; + for line in block_str.lines() { + let cur_indent_width = line.find(|c: char| !c.is_whitespace()).unwrap_or(0); + if prev_indent_width > cur_indent_width + context.config.tab_spaces && + line.find('}').unwrap_or(0) != cur_indent_width { + return false; + } + prev_indent_width = cur_indent_width; + } + true + } + fn rewrite_closure_block(block: &ast::Block, prefix: String, context: &RewriteContext, @@ -577,22 +590,27 @@ fn rewrite_closure(capture: ast::CaptureBy, -> Option { // Start with visual indent, then fall back to block indent if the // closure is large. - let rewrite = try_opt!(block.rewrite(&context, shape)); - - let block_threshold = context.config.closure_block_indent_threshold; - if block_threshold < 0 || rewrite.matches('\n').count() <= block_threshold as usize { - if let Some(rewrite) = wrap_str(rewrite, context.config.max_width, shape) { - return Some(format!("{} {}", prefix, rewrite)); + if let Some(block_str) = block.rewrite(&context, shape) { + let block_threshold = context.config.closure_block_indent_threshold; + if (block_threshold < 0 || + block_str.matches('\n').count() <= block_threshold as usize) && + no_weird_visual_indent(&block_str, context) { + if let Some(block_str) = block_str.rewrite(context, shape) { + return Some(format!("{} {}", prefix, block_str)); + } } } // The body of the closure is big enough to be block indented, that // means we must re-format. - let block_shape = shape.block(); - let rewrite = try_opt!(block.rewrite(&context, block_shape)); + let block_shape = Shape { + width: context.config.max_width - shape.block().indent.width(), + ..shape.block() + }; + let block_str = try_opt!(block.rewrite(&context, block_shape)); Some(format!("{} {}", prefix, - try_opt!(wrap_str(rewrite, block_shape.width, block_shape)))) + try_opt!(block_str.rewrite(context, block_shape)))) } } -- cgit 1.4.1-3-g733a5 From 2c1d896f6078521aedd9e153ad6940bb2917cf2f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 3 May 2017 11:22:36 +0900 Subject: Split a long chain with a single child --- src/chains.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 8e176fce724..8cb726bd4b4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -176,9 +176,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len()) + parent_rewrite.len(); - let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 && - rewrites.len() > 1 { - true + let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 { + if rewrites.len() > 1 { + true + } else if rewrites.len() == 1 { + let one_line_len = parent_rewrite.len() + first_line_width(&rewrites[0]); + one_line_len > shape.width + } else { + false + } } else if context.config.take_source_hints && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. -- cgit 1.4.1-3-g733a5 From e91d498b8f771ed9ddc1abbedf4d261883d4d505 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 3 May 2017 11:24:08 +0900 Subject: Keep a chain with length chain_one_line_max in a single line --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 8cb726bd4b4..3d148d19a55 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -176,7 +176,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len()) + parent_rewrite.len(); - let veto_single_line = if one_line_len > context.config.chain_one_line_max - 1 { + let veto_single_line = if one_line_len > context.config.chain_one_line_max { if rewrites.len() > 1 { true } else if rewrites.len() == 1 { -- cgit 1.4.1-3-g733a5 From f5da9d779fd0e72c97823eb808e13d44ebad86fb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 3 May 2017 11:26:25 +0900 Subject: Format source codes --- src/file_lines.rs | 12 ++++-------- src/items.rs | 14 ++++---------- src/string.rs | 5 +---- src/types.rs | 4 ++-- 4 files changed, 11 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index f11a0aaf6e2..b52d790ed37 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -123,10 +123,8 @@ impl FileLines { Some(ref map) => map, }; - match canonicalize_path_string(range.file_name()).and_then(|canonical| { - map.get_vec(&canonical) - .ok_or(()) - }) { + match canonicalize_path_string(range.file_name()) + .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), Err(_) => false, } @@ -140,10 +138,8 @@ impl FileLines { Some(ref map) => map, }; - match canonicalize_path_string(range.file_name()).and_then(|canonical| { - map.get_vec(&canonical) - .ok_or(()) - }) { + match canonicalize_path_string(range.file_name()) + .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { Ok(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), Err(_) => false, } diff --git a/src/items.rs b/src/items.rs index 8ea97b177e8..0b2ca5a52cb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -278,8 +278,7 @@ impl<'a> FmtVisitor<'a> { result.push(' '); } - self.single_line_fn(&result, block) - .or_else(|| Some(result)) + self.single_line_fn(&result, block).or_else(|| Some(result)) } pub fn rewrite_required_fn(&mut self, @@ -912,9 +911,7 @@ fn format_struct_struct(context: &RewriteContext, let snippet = context.snippet(mk_sp(body_lo, span.hi - BytePos(1))); if snippet.trim().is_empty() { // `struct S {}` - } else if snippet - .trim_right_matches(&[' ', '\t'][..]) - .ends_with('\n') { + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { // fix indent result.push_str(&snippet.trim_right()); result.push('\n'); @@ -1030,9 +1027,7 @@ fn format_tuple_struct(context: &RewriteContext, let snippet = context.snippet(mk_sp(body_lo, context.codemap.span_before(span, ")"))); if snippet.is_empty() { // `struct S ()` - } else if snippet - .trim_right_matches(&[' ', '\t'][..]) - .ends_with('\n') { + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { result.push_str(&snippet.trim_right()); result.push('\n'); result.push_str(&offset.to_string(context.config)); @@ -1229,8 +1224,7 @@ impl Rewrite for ast::StructField { let type_offset = shape.indent.block_indent(context.config); let rewrite_type_in_next_line = || { let budget = try_opt!(context.config.max_width.checked_sub(type_offset.width())); - self.ty - .rewrite(context, Shape::legacy(budget, type_offset)) + self.ty.rewrite(context, Shape::legacy(budget, type_offset)) }; let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); diff --git a/src/string.rs b/src/string.rs index e1e0681ba56..37a569ce67d 100644 --- a/src/string.rs +++ b/src/string.rs @@ -51,10 +51,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = try_opt!(shape - .width - .checked_sub(fmt.opener.len() + ender_length + 1)) + - 1; + let max_chars = try_opt!(shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. diff --git a/src/types.rs b/src/types.rs index ca98401db14..e2a95c66832 100644 --- a/src/types.rs +++ b/src/types.rs @@ -704,9 +704,9 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, .lifetimes .iter() .map(|l| { - l.rewrite(context, + l.rewrite(context, Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) - }) + }) .intersperse(Some(", ".to_string())) .collect::>())); result.push_str("> "); -- cgit 1.4.1-3-g733a5 From 78d4ef19921a9358a2888f00c4fd4c6053c7301d Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 3 May 2017 10:23:50 +0200 Subject: Drop rustc-serialize, use serde, update toml dependency --- Cargo.lock | 95 +++++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 6 ++-- src/bin/cargo-fmt.rs | 28 ++++++++++------ src/config.rs | 10 +++--- src/file_lines.rs | 14 ++++---- src/lib.rs | 6 +++- src/utils.rs | 24 ++++++++++--- 7 files changed, 149 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 9b6609a9c16..79467071cec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,12 +11,14 @@ dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -40,6 +42,11 @@ name = "diff" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dtoa" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "either" version = "1.1.0" @@ -67,6 +74,11 @@ dependencies = [ "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itoa" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -99,6 +111,16 @@ name = "multimap" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num-traits" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "regex" version = "0.2.1" @@ -130,6 +152,41 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strings" version = "0.0.1" @@ -138,6 +195,24 @@ dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syntex_errors" version = "0.58.1" @@ -200,10 +275,10 @@ dependencies = [ [[package]] name = "toml" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -258,27 +333,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" +"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" +"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" +"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" +"checksum serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3b46a59dd63931010fdb1d88538513f3279090d88b5c22ef4fe8440cfffcc6e3" +"checksum serde_derive 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c06b68790963518008b8ae0152d48be4bbbe77015d2c717f6282eea1824be9a" +"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" +"checksum serde_json 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c62115693d0a9ed8c32d1c760f0fdbe7d4b05cb13c135b9b54137ac0d59fccb" "checksum strings 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "54f86446ab480b4f60782188f4f78886465c5793aee248cbb48b7fdc0d022420" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" "checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" "checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" +"checksum toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3063405db158de3dce8efad5fc89cf1baffb9501a3647dc9505ba109694ce31f" "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" diff --git a/Cargo.toml b/Cargo.toml index 1629dd94522..568227869b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,10 @@ default = ["cargo-fmt"] cargo-fmt = [] [dependencies] -toml = "0.2.1" -rustc-serialize = "0.3" +toml = "0.4" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" unicode-segmentation = "1.0.0" regex = "0.2" term = "0.4" diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index ea747aa4702..442cb9e78f7 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -14,7 +14,7 @@ #![deny(warnings)] extern crate getopts; -extern crate rustc_serialize; +extern crate serde_json as json; use std::env; use std::io::Write; @@ -24,8 +24,9 @@ use std::str; use std::collections::HashSet; use std::iter::FromIterator; +use json::Value; + use getopts::{Options, Matches}; -use rustc_serialize::json::Json; fn main() { let exit_status = execute(); @@ -184,8 +185,9 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: if output.status.success() { // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); - let json = Json::from_str(data).unwrap(); - let jtargets = json.find("targets").unwrap().as_array().unwrap(); + let json: Value = json::from_str(data).unwrap(); + let json_obj = json.as_object().unwrap(); + let jtargets = json_obj.get("targets").unwrap().as_array().unwrap(); for jtarget in jtargets { targets.push(target_from_json(jtarget)); } @@ -205,13 +207,15 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: .output()?; if output.status.success() { let data = &String::from_utf8(output.stdout).unwrap(); - let json = Json::from_str(data).unwrap(); + let json: Value = json::from_str(data).unwrap(); + let json_obj = json.as_object().unwrap(); let mut hitlist: HashSet<&String> = if workspace_hitlist != WorkspaceHitlist::All { HashSet::from_iter(workspace_hitlist.get_some().unwrap()) } else { HashSet::new() // Unused }; - let members: Vec<&Json> = json.find("packages") + let members: Vec<&Value> = json_obj + .get("packages") .unwrap() .as_array() .unwrap() @@ -219,7 +223,8 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: .filter(|member| if workspace_hitlist == WorkspaceHitlist::All { true } else { - let member_name = member.find("name").unwrap().as_string().unwrap(); + let member_obj = member.as_object().unwrap(); + let member_name = member_obj.get("name").unwrap().as_str().unwrap(); hitlist.take(&member_name.to_string()).is_some() }) .collect(); @@ -230,7 +235,8 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: hitlist.iter().next().unwrap()))); } for member in members { - let jtargets = member.find("targets").unwrap().as_array().unwrap(); + let member_obj = member.as_object().unwrap(); + let jtargets = member_obj.get("targets").unwrap().as_array().unwrap(); for jtarget in jtargets { targets.push(target_from_json(jtarget)); } @@ -242,11 +248,11 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: } -fn target_from_json(jtarget: &Json) -> Target { +fn target_from_json(jtarget: &Value) -> Target { let jtarget = jtarget.as_object().unwrap(); - let path = PathBuf::from(jtarget.get("src_path").unwrap().as_string().unwrap()); + let path = PathBuf::from(jtarget.get("src_path").unwrap().as_str().unwrap()); let kinds = jtarget.get("kind").unwrap().as_array().unwrap(); - let kind = match kinds[0].as_string().unwrap() { + let kind = match kinds[0].as_str().unwrap() { "bin" => TargetKind::Bin, "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, "test" => TargetKind::Test, diff --git a/src/config.rs b/src/config.rs index bc62c9d3dac..f0f2d529308 100644 --- a/src/config.rs +++ b/src/config.rs @@ -210,7 +210,7 @@ impl ConfigHelpItem { macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => ( - #[derive(RustcDecodable, Clone)] + #[derive(Deserialize, Clone)] pub struct Config { $(pub $i: $ty),+ } @@ -220,7 +220,7 @@ macro_rules! create_config { // specity all properties of `Config`. // We first parse into `ParsedConfig`, then create a default `Config` // and overwrite the properties with corresponding values from `ParsedConfig` - #[derive(RustcDecodable, Clone)] + #[derive(Deserialize, Clone)] pub struct ParsedConfig { $(pub $i: Option<$ty>),+ } @@ -250,10 +250,10 @@ macro_rules! create_config { } } } - match toml::decode(parsed) { - Some(parsed_config) => + match parsed.try_into() { + Ok(parsed_config) => Ok(Config::default().fill_from_parsed_config(parsed_config)), - None => { + Err(_) => { err.push_str("Error: Decoding config file failed. "); err.push_str("Please check your config file.\n"); Err(err) diff --git a/src/file_lines.rs b/src/file_lines.rs index f11a0aaf6e2..2fad297a4df 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -14,12 +14,12 @@ use std::{cmp, iter, path, str}; use itertools::Itertools; use multimap::MultiMap; -use rustc_serialize::{self, json}; +use serde_json as json; use codemap::LineRange; /// A range that is inclusive of both ends. -#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcDecodable)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)] struct Range { pub lo: usize, pub hi: usize, @@ -177,14 +177,14 @@ impl str::FromStr for FileLines { type Err = String; fn from_str(s: &str) -> Result { - let v: Vec = try!(json::decode(s).map_err(|e| e.to_string())); + let v: Vec = try!(json::from_str(s).map_err(|e| e.to_string())); let m = try!(v.into_iter().map(JsonSpan::into_tuple).collect()); Ok(FileLines::from_multimap(m)) } } // For JSON decoding. -#[derive(Clone, Debug, RustcDecodable)] +#[derive(Clone, Debug, Deserialize)] struct JsonSpan { file: String, range: (usize, usize), @@ -202,8 +202,10 @@ impl JsonSpan { // This impl is needed for inclusion in the `Config` struct. We don't have a toml representation // for `FileLines`, so it will just panic instead. -impl rustc_serialize::Decodable for FileLines { - fn decode(_: &mut D) -> Result { +impl<'de> ::serde::de::Deserialize<'de> for FileLines { + fn deserialize(_: D) -> Result + where D: ::serde::de::Deserializer<'de> + { panic!("FileLines cannot be deserialized from a project rustfmt.toml file: please \ specify it via the `--file-lines` option instead"); } diff --git a/src/lib.rs b/src/lib.rs index f7383fbc41e..6935f0f7acd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,9 +15,13 @@ #[macro_use] extern crate log; +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; + extern crate syntex_syntax as syntax; extern crate syntex_errors as errors; -extern crate rustc_serialize; extern crate strings; diff --git a/src/utils.rs b/src/utils.rs index 1b1ef99955e..8648b8f2f57 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -193,16 +193,32 @@ pub fn trim_newlines(input: &str) -> &str { #[macro_export] macro_rules! impl_enum_decodable { ( $e:ident, $( $x:ident ),* ) => { - impl ::rustc_serialize::Decodable for $e { - fn decode(d: &mut D) -> Result { + impl<'de> ::serde::de::Deserialize<'de> for $e { + fn deserialize(d: D) -> Result + where D: ::serde::de::Deserializer<'de> { use std::ascii::AsciiExt; - let s = try!(d.read_str()); + use serde::{Deserializer}; + use serde::de::{Error, Visitor}; + use std::marker::PhantomData; + use std::fmt; + struct StringOnly(PhantomData); + impl<'de, T> Visitor<'de> for StringOnly + where T: Deserializer<'de> { + type Value = String; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("string") + } + fn visit_str(self, value :&str) -> Result { + Ok(String::from(value)) + } + } + let s = try!(d.deserialize_string(StringOnly::(PhantomData))); $( if stringify!($x).eq_ignore_ascii_case(&s) { return Ok($e::$x); } )* - Err(d.error("Bad variant")) + Err(>::Error::custom("Bad variant")) } } -- cgit 1.4.1-3-g733a5 From 6e46a827b63e8acade0fcb667dba29a9a46793f0 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 3 May 2017 17:11:34 +0200 Subject: Simplifications --- src/utils.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 8648b8f2f57..d177e01b42b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -195,15 +195,14 @@ macro_rules! impl_enum_decodable { ( $e:ident, $( $x:ident ),* ) => { impl<'de> ::serde::de::Deserialize<'de> for $e { fn deserialize(d: D) -> Result - where D: ::serde::de::Deserializer<'de> { + where D: ::serde::Deserializer<'de> { use std::ascii::AsciiExt; - use serde::{Deserializer}; use serde::de::{Error, Visitor}; use std::marker::PhantomData; use std::fmt; struct StringOnly(PhantomData); impl<'de, T> Visitor<'de> for StringOnly - where T: Deserializer<'de> { + where T: ::serde::Deserializer<'de> { type Value = String; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("string") @@ -218,7 +217,8 @@ macro_rules! impl_enum_decodable { return Ok($e::$x); } )* - Err(>::Error::custom("Bad variant")) + static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; + Err(D::Error::unknown_variant(&s, ALLOWED)) } } -- cgit 1.4.1-3-g733a5 From 11cc56b06b89d9141676e1fc27a2ce094600f270 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 3 May 2017 17:16:58 +0200 Subject: Format fix --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index d177e01b42b..efcf0f1b3e3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -207,7 +207,7 @@ macro_rules! impl_enum_decodable { fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("string") } - fn visit_str(self, value :&str) -> Result { + fn visit_str(self, value: &str) -> Result { Ok(String::from(value)) } } -- cgit 1.4.1-3-g733a5 From 58d957be3fd559787b7f489ee5f1089ce9a87f30 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 4 May 2017 00:21:51 +0900 Subject: Check format failures explicitly in visit_block --- src/expr.rs | 24 ++++++------------------ src/visitor.rs | 5 +++++ 2 files changed, 11 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 75a7ff21abe..5876409a9fa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -570,19 +570,6 @@ fn rewrite_closure(capture: ast::CaptureBy, rewrite.map(|rw| format!("{} {}", prefix, rw)) } - fn no_weird_visual_indent(block_str: &str, context: &RewriteContext) -> bool { - let mut prev_indent_width = 0; - for line in block_str.lines() { - let cur_indent_width = line.find(|c: char| !c.is_whitespace()).unwrap_or(0); - if prev_indent_width > cur_indent_width + context.config.tab_spaces && - line.find('}').unwrap_or(0) != cur_indent_width { - return false; - } - prev_indent_width = cur_indent_width; - } - true - } - fn rewrite_closure_block(block: &ast::Block, prefix: String, context: &RewriteContext, @@ -592,9 +579,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // closure is large. if let Some(block_str) = block.rewrite(&context, shape) { let block_threshold = context.config.closure_block_indent_threshold; - if (block_threshold < 0 || - block_str.matches('\n').count() <= block_threshold as usize) && - no_weird_visual_indent(&block_str, context) { + if block_threshold < 0 || block_str.matches('\n').count() <= block_threshold as usize { if let Some(block_str) = block_str.rewrite(context, shape) { return Some(format!("{} {}", prefix, block_str)); } @@ -697,8 +682,11 @@ impl Rewrite for ast::Block { }; visitor.visit_block(self); - - Some(format!("{}{}", prefix, visitor.buffer)) + if visitor.failed { + None + } else { + Some(format!("{}{}", prefix, visitor.buffer)) + } } } diff --git a/src/visitor.rs b/src/visitor.rs index 86fb1bce9d9..71013d085d5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -39,6 +39,7 @@ pub struct FmtVisitor<'a> { // FIXME: use an RAII util or closure for indenting pub block_indent: Indent, pub config: &'a Config, + pub failed: bool, } impl<'a> FmtVisitor<'a> { @@ -65,6 +66,9 @@ impl<'a> FmtVisitor<'a> { Shape::legacy(self.config.max_width - self.block_indent.width(), self.block_indent)); + if rewrite.is_none() { + self.failed = true; + } self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Mac(ref mac) => { @@ -457,6 +461,7 @@ impl<'a> FmtVisitor<'a> { alignment: 0, }, config: config, + failed: false, } } -- cgit 1.4.1-3-g733a5 From 51815effbef8777136c88ab146f3638c5fb4de23 Mon Sep 17 00:00:00 2001 From: Sheng Hau Date: Thu, 4 May 2017 00:10:03 +0800 Subject: Format macros in trait item position --- src/visitor.rs | 4 ++-- tests/source/issue-1158.rs | 3 +++ tests/target/issue-1158.rs | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-1158.rs create mode 100644 tests/target/issue-1158.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 86fb1bce9d9..00b2b6c2392 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -382,8 +382,8 @@ impl<'a> FmtVisitor<'a> { self.block_indent); self.push_rewrite(ti.span, rewrite); } - ast::TraitItemKind::Macro(..) => { - // FIXME(#1158) Macros in trait item position + ast::TraitItemKind::Macro(ref mac) => { + self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); } } } diff --git a/tests/source/issue-1158.rs b/tests/source/issue-1158.rs new file mode 100644 index 00000000000..6742e17459e --- /dev/null +++ b/tests/source/issue-1158.rs @@ -0,0 +1,3 @@ +trait T { + itemmacro!(this, is.now() .formatted(yay)); +} diff --git a/tests/target/issue-1158.rs b/tests/target/issue-1158.rs new file mode 100644 index 00000000000..2abfa5a29f2 --- /dev/null +++ b/tests/target/issue-1158.rs @@ -0,0 +1,3 @@ +trait T { + itemmacro!(this, is.now().formatted(yay)); +} -- cgit 1.4.1-3-g733a5 From e7c6d348541d19fc93350aef71e5bcbb4bb5ae23 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Apr 2017 16:53:49 +0900 Subject: Use SeperatorTactic::Never for a single argument --- src/expr.rs | 3 ++- src/items.rs | 9 +++++++-- tests/target/fn-custom-7.rs | 6 +++--- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5876409a9fa..f50b383b943 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1752,7 +1752,8 @@ fn rewrite_call_inner(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: if force_no_trailing_comma || - context.config.fn_call_style == IndentStyle::Visual { + context.config.fn_call_style == IndentStyle::Visual || + args.len() <= 1 { SeparatorTactic::Never } else { context.config.trailing_comma diff --git a/src/items.rs b/src/items.rs index 0b2ca5a52cb..6e5f4b0802a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1628,7 +1628,8 @@ fn rewrite_fn_base(context: &RewriteContext, indent, arg_indent, args_span, - fd.variadic)); + fd.variadic, + generics_str.contains('\n'))); let multi_line_arg_str = arg_str.contains('\n'); @@ -1783,7 +1784,8 @@ fn rewrite_args(context: &RewriteContext, indent: Indent, arg_indent: Indent, span: Span, - variadic: bool) + variadic: bool, + generics_str_contains_newline: bool) -> Option { let mut arg_item_strs = try_opt!(args.iter() @@ -1868,6 +1870,9 @@ fn rewrite_args(context: &RewriteContext, } let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout { + IndentStyle::Block if !generics_str_contains_newline && arg_items.len() <= 1 => { + (indent.block_indent(context.config), SeparatorTactic::Never, true) + } IndentStyle::Block => { (indent.block_indent(context.config), SeparatorTactic::Vertical, true) } diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 0f5297e33ed..1a134128d2b 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -4,7 +4,7 @@ // rustfmt-fn_brace_style: AlwaysNextLine // Case with only one variable. -fn foo(a: u8,) -> u8 +fn foo(a: u8) -> u8 { bar() } @@ -30,11 +30,11 @@ fn foo( } trait Test { - fn foo(a: u8,) + fn foo(a: u8) { } - fn bar(a: u8,) -> String + fn bar(a: u8) -> String { } } -- cgit 1.4.1-3-g733a5 From 75a13868dab681dfc31fbe31d76fff413bfe7c9e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 5 May 2017 14:29:18 +1200 Subject: Block format control flow discriminant expressions and binops Fixes #1450 Adds control_style option --- rfc-rustfmt.toml | 1 + src/config.rs | 1 + src/expr.rs | 24 +++++++++++++++++------- src/lib.rs | 8 ++++++++ tests/source/expr-block.rs | 23 +++++++++++++++++++++++ tests/target/expr-block.rs | 25 +++++++++++++++++++++++++ 6 files changed, 75 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml index 914d19d6cb2..0e622bdd943 100644 --- a/rfc-rustfmt.toml +++ b/rfc-rustfmt.toml @@ -1,5 +1,6 @@ fn_args_layout = "Block" array_layout = "Block" +control_style = "Rfc" where_style = "Rfc" generics_indent = "Block" fn_call_style = "Block" diff --git a/src/config.rs b/src/config.rs index f0f2d529308..805581abb4e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -338,6 +338,7 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; + control_style: Style, Style::Default, "Indent style for control flow statements"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, "Brace style for control flow constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; diff --git a/src/expr.rs b/src/expr.rs index 5876409a9fa..bb4caaa7b93 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -26,7 +26,7 @@ use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_w semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, colon_spaces}; use visitor::FmtVisitor; -use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle}; +use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; use types::{rewrite_path, PathContext}; use items::{span_lo_for_arg, span_hi_for_arg}; @@ -314,8 +314,12 @@ pub fn rewrite_pair(lhs: &LHS, .max_width .checked_sub(shape.used_width() + prefix.len() + infix.len())); - let rhs_shape = try_opt!(shape.sub_width(suffix.len() + prefix.len())) - .visual_indent(prefix.len()); + let rhs_shape = match context.config.control_style { + Style::Default => { + try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) + } + Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces)), + }; let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); let lhs_result = try_opt!(lhs.rewrite(context, @@ -884,7 +888,10 @@ impl<'a> Rewrite for ControlFlow<'a> { let pat_expr_string = match self.cond { Some(cond) => { - let mut cond_shape = try_opt!(constr_shape.shrink_left(add_offset)); + let mut cond_shape = match context.config.control_style { + Style::Default => try_opt!(constr_shape.shrink_left(add_offset)), + Style::Rfc => constr_shape, + }; if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine { // 2 = " {".len() cond_shape = try_opt!(cond_shape.sub_width(2)); @@ -900,6 +907,9 @@ impl<'a> Rewrite for ControlFlow<'a> { None => String::new(), }; + let force_newline_brace = context.config.control_style == Style::Rfc && + pat_expr_string.contains('\n'); + // Try to format if-else on single line. if self.allow_single_line && context.config.single_line_if_else_max_width > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); @@ -957,8 +967,8 @@ impl<'a> Rewrite for ControlFlow<'a> { &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" - } else if context.config.control_brace_style == - ControlBraceStyle::AlwaysNextLine { + } else if context.config.control_brace_style == ControlBraceStyle::AlwaysNextLine || + force_newline_brace { alt_block_sep.as_str() } else { " " @@ -1494,7 +1504,7 @@ fn rewrite_pat_expr(context: &RewriteContext, connector: &str, shape: Shape) -> Option { - debug!("rewrite_pat_expr {:?} {:?}", shape, pat); + debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); let mut result = match pat { Some(pat) => { let matcher = if matcher.is_empty() { diff --git a/src/lib.rs b/src/lib.rs index 6935f0f7acd..a3f1a93ca48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -287,6 +287,14 @@ impl Shape { } } + pub fn block_left(&self, width: usize) -> Option { + let block_shape = self.block_indent(width); + Some(Shape { + width: try_opt!(block_shape.width.checked_sub(width)), + ..block_shape + }) + } + pub fn add_offset(&self, extra_width: usize) -> Shape { Shape { width: self.width, diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index d7f7c610eb3..ad959f8ee01 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -1,5 +1,6 @@ // rustfmt-array_layout: Block // rustfmt-fn_call_style: Block +// rustfmt-control_style: Rfc // Test expressions with block formatting. fn arrays() { @@ -120,3 +121,25 @@ fn macros() { Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), }; } + +fn issue_1450() { + if selfstate + .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( + STATE_PARKED, + STATE_UNPARKED, + Release, + Relaxed, + Release, + Relaxed, + ) + .is_ok() { + return; + } +} + +fn foo() { + if real_total <= limit && !pre_line_comments && + !items.into_iter().any(|item| item.as_ref().is_multiline()) { + DefinitiveListTactic::Horizontal + } +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index f7a157cf3df..349f2a00c84 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -1,5 +1,6 @@ // rustfmt-array_layout: Block // rustfmt-fn_call_style: Block +// rustfmt-control_style: Rfc // Test expressions with block formatting. fn arrays() { @@ -188,3 +189,27 @@ fn macros() { Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), }; } + +fn issue_1450() { + if selfstate + .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( + STATE_PARKED, + STATE_UNPARKED, + Release, + Relaxed, + Release, + Relaxed, + ) + .is_ok() + { + return; + } +} + +fn foo() { + if real_total <= limit && !pre_line_comments && + !items.into_iter().any(|item| item.as_ref().is_multiline()) + { + DefinitiveListTactic::Horizontal + } +} -- cgit 1.4.1-3-g733a5 From 7c6479358bb562094de8a932c941254b5e31f210 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sat, 6 May 2017 15:14:44 -0400 Subject: Respect file_lines within format_lines() function --- src/file_lines.rs | 14 ++++++++++++++ src/lib.rs | 40 ++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index a20c8c4d3b3..3db75e1ce7e 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -144,6 +144,20 @@ impl FileLines { Err(_) => false, } } + + pub fn contains_line(&self, file_name: &str, line: usize) -> bool { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match canonicalize_path_string(file_name) + .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { + Ok(ranges) => ranges.iter().any(|r| r.lo <= line && r.hi >= line), + Err(_) => false, + } + } } /// FileLines files iterator. diff --git a/src/lib.rs b/src/lib.rs index a3f1a93ca48..ac736369f6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -481,27 +481,35 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m continue; } - // Add warnings for bad todos/ fixmes - if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), - }); - } + let format_line = config.file_lines.contains_line(name, cur_line as usize); - if c == '\n' { - // Check for (and record) trailing whitespace. - if let Some(lw) = last_wspace { - trims.push((cur_line, lw, b)); - line_len -= 1; - } - // Check for any line width errors we couldn't correct. - if config.error_on_line_overflow && line_len > config.max_width { + if format_line { + // Add warnings for bad todos/ fixmes + if let Some(issue) = issue_seeker.inspect(c) { errors.push(FormattingError { line: cur_line, - kind: ErrorKind::LineOverflow(line_len, config.max_width), + kind: ErrorKind::BadIssue(issue), }); } + } + + if c == '\n' { + if format_line { + // Check for (and record) trailing whitespace. + if let Some(lw) = last_wspace { + trims.push((cur_line, lw, b)); + line_len -= 1; + } + + // Check for any line width errors we couldn't correct. + if config.error_on_line_overflow && line_len > config.max_width { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::LineOverflow(line_len, config.max_width), + }); + } + } + line_len = 0; cur_line += 1; newline_count += 1; -- cgit 1.4.1-3-g733a5 From b1c9832c9b54e75141501b691844bdfd37cde7cb Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sat, 6 May 2017 17:59:51 -0400 Subject: Respect file_lines within write_snippet() function --- src/file_lines.rs | 14 ++++++++++++++ src/missed_spans.rs | 24 ++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index 3db75e1ce7e..ea3d63feb92 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -158,6 +158,20 @@ impl FileLines { Err(_) => false, } } + + pub fn intersects_range(&self, file_name: &str, lo: usize, hi: usize) -> bool { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match canonicalize_path_string(file_name) + .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { + Ok(ranges) => ranges.iter().any(|r| r.intersects(Range::new(lo, hi))), + Err(_) => false, + } + } } /// FileLines files iterator. diff --git a/src/missed_spans.rs b/src/missed_spans.rs index c0f04f56e15..aef158199ba 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -83,17 +83,18 @@ impl<'a> FmtVisitor<'a> { let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; let big_diff = (span.lo - big_span_lo).to_usize(); - let snippet = self.snippet(span); + let snippet = self.snippet(span.clone()); debug!("write_snippet `{}`", snippet); - self.write_snippet_inner(big_snippet, big_diff, &snippet, process_last_snippet); + self.write_snippet_inner(big_snippet, big_diff, &snippet, span, process_last_snippet); } fn write_snippet_inner(&mut self, big_snippet: &str, big_diff: usize, old_snippet: &str, + span: Span, process_last_snippet: F) where F: Fn(&mut FmtVisitor, &str, &str) { @@ -104,6 +105,10 @@ impl<'a> FmtVisitor<'a> { let mut last_wspace = None; let mut rewrite_next_comment = true; + let char_pos = self.codemap.lookup_char_pos(span.lo); + let file_name = &char_pos.file.name; + let mut cur_line = char_pos.line; + fn replace_chars(string: &str) -> String { string .chars() @@ -129,6 +134,15 @@ impl<'a> FmtVisitor<'a> { let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); + let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count(); + + if rewrite_next_comment && + !self.config + .file_lines + .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) { + rewrite_next_comment = false; + } + if rewrite_next_comment { if fix_indent { if let Some('{') = last_char { @@ -172,6 +186,7 @@ impl<'a> FmtVisitor<'a> { } } + cur_line += subslice_num_lines; continue; } else { rewrite_next_comment = false; @@ -182,6 +197,10 @@ impl<'a> FmtVisitor<'a> { i += offset; if c == '\n' { + if !self.config.file_lines.contains_line(file_name, cur_line) { + last_wspace = None; + } + if let Some(lw) = last_wspace { self.buffer.push_str(&snippet[line_start..lw]); self.buffer.push_str("\n"); @@ -189,6 +208,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&snippet[line_start..i + 1]); } + cur_line += 1; line_start = i + 1; last_wspace = None; rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; -- cgit 1.4.1-3-g733a5 From 2ee8e730a67de33bb57912d819bd617c70a7b922 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 7 May 2017 13:06:54 +0900 Subject: Add fallback path --- src/expr.rs | 12 +++++------- tests/source/closure.rs | 11 +++++++++++ tests/target/closure.rs | 11 +++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bb4caaa7b93..771e3ffcbb9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -530,13 +530,11 @@ fn rewrite_closure(capture: ast::CaptureBy, // We need braces, but we might still prefer a one-liner. let stmt = &block.stmts[0]; // 4 = braces and spaces. - let mut rewrite = stmt.rewrite(context, try_opt!(body_shape.sub_width(4))); - - // Checks if rewrite succeeded and fits on a single line. - rewrite = and_one_line(rewrite); - - if let Some(rewrite) = rewrite { - return Some(format!("{} {{ {} }}", prefix, rewrite)); + if let Some(body_shape) = body_shape.sub_width(4) { + // Checks if rewrite succeeded and fits on a single line. + if let Some(rewrite) = and_one_line(stmt.rewrite(context, body_shape)) { + return Some(format!("{} {{ {} }}", prefix, rewrite)); + } } } diff --git a/tests/source/closure.rs b/tests/source/closure.rs index b8d998f2e59..a4395d0286a 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -120,3 +120,14 @@ fn issue470() { }); }}} } + +// #1509 +impl Foo { + pub fn bar(&self) { + Some(SomeType { + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { + Ok(f) + })), + }) + } +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index c94d98b3dda..febbb0a46a2 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -139,3 +139,14 @@ fn issue470() { } } } + +// #1509 +impl Foo { + pub fn bar(&self) { + Some(SomeType { + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { + Ok(f) + })), + }) + } +} -- cgit 1.4.1-3-g733a5 From 5e832acdc49ecc717a27c5ab1ca1503374d930b7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 7 May 2017 16:44:03 +0900 Subject: Allow config-path to point to a file --- src/bin/rustfmt.rs | 62 +++++++++++++++++++++++++++++++++++------------------- src/config.rs | 26 +++++++++++++++-------- 2 files changed, 57 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 45f695c6477..2c741934a5e 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -98,6 +98,8 @@ impl CliOptions { } } +const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + /// Try to find a project file in the given directory and its parents. Returns the path of a the /// nearest project file if one exists, or `None` if no project file was found. fn lookup_project_file(dir: &Path) -> FmtResult> { @@ -109,8 +111,6 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { current = try!(fs::canonicalize(current)); - const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; - loop { for config_file_name in &CONFIG_FILE_NAMES { let config_file = current.join(config_file_name); @@ -136,6 +136,16 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { } } +fn open_config_file(file_path: &Path) -> FmtResult<(Config, Option)> { + let mut file = try!(File::open(&file_path)); + let mut toml = String::new(); + try!(file.read_to_string(&mut toml)); + match Config::from_toml(&toml) { + Ok(cfg) => Ok((cfg, Some(file_path.to_path_buf()))), + Err(err) => Err(FmtError::from(err)), + } +} + /// Resolve the config for input in `dir`. /// /// Returns the `Config` to use, and the path of the project file if there was @@ -145,14 +155,7 @@ fn resolve_config(dir: &Path) -> FmtResult<(Config, Option)> { if path.is_none() { return Ok((Config::default(), None)); } - let path = path.unwrap(); - let mut file = try!(File::open(&path)); - let mut toml = String::new(); - try!(file.read_to_string(&mut toml)); - match Config::from_toml(&toml) { - Ok(cfg) => Ok((cfg, Some(path))), - Err(err) => Err(FmtError::from(err)), - } + open_config_file(&path.unwrap()) } /// read the given config file path recursively if present else read the project file path @@ -161,7 +164,7 @@ fn match_cli_path_or_file(config_path: Option, -> FmtResult<(Config, Option)> { if let Some(config_file) = config_path { - let (toml, path) = try!(resolve_config(config_file.as_ref())); + let (toml, path) = try!(open_config_file(config_file.as_ref())); if path.is_some() { return Ok((toml, path)); } @@ -246,7 +249,7 @@ fn execute(opts: &Options) -> FmtResult { let mut path = None; // Load the config path file if provided if let Some(config_file) = config_path { - let (cfg_tmp, path_tmp) = resolve_config(config_file.as_ref())?; + let (cfg_tmp, path_tmp) = open_config_file(config_file.as_ref())?; config = cfg_tmp; path = path_tmp; }; @@ -325,7 +328,7 @@ fn main() { } fn print_usage(opts: &Options, reason: &str) { - let reason = format!("{}\nusage: {} [options] ...", + let reason = format!("{}\n\nusage: {} [options] ...", reason, env::args_os().next().unwrap().to_string_lossy()); println!("{}", opts.usage(&reason)); @@ -354,16 +357,31 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::Version); } + let config_path_not_found = |path: &str| -> FmtResult { + Err(FmtError::from(format!("Error: unable to find a config file for the given path: `{}`", + path))) + }; + // Read the config_path and convert to parent dir if a file is provided. - let config_path: Option = matches - .opt_str("config-path") - .map(PathBuf::from) - .and_then(|dir| { - if dir.is_file() { - return dir.parent().map(|v| v.into()); - } - Some(dir) - }); + // If a config file cannot be found from the given path, return error. + let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { + Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), + Some(ref path) if path.is_dir() => { + let mut config_file_path = None; + for config_file_name in &CONFIG_FILE_NAMES { + let temp_path = path.join(config_file_name); + if temp_path.is_file() { + config_file_path = Some(temp_path); + } + } + if config_file_path.is_some() { + config_file_path + } else { + return config_path_not_found(path.to_str().unwrap()); + } + } + path @ _ => path, + }; // if no file argument is supplied, read from stdin if matches.free.is_empty() { diff --git a/src/config.rs b/src/config.rs index 805581abb4e..441f86f48cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -237,16 +237,24 @@ macro_rules! create_config { } pub fn from_toml(toml: &str) -> Result { - let parsed: toml::Value = toml.parse().expect("Could not parse TOML"); + let parsed: toml::Value = + toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; let mut err: String = String::new(); - for (key, _) in parsed.as_table().expect("Parsed config was not table") { - match &**key { - $( - stringify!($i) => (), - )+ - _ => { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for (key, _) in table { + match &**key { + $( + stringify!($i) => (), + )+ + _ => { + let msg = + &format!("Warning: Unknown configuration option `{}`\n", + key); + err.push_str(msg) + } } } } -- cgit 1.4.1-3-g733a5 From e923df414678e957ff932d1c45b94e01e77d003b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 8 May 2017 07:24:12 +0900 Subject: Add indented and with_max_width --- src/expr.rs | 16 +++----------- src/items.rs | 69 +++++++++++++++++++++++----------------------------------- src/lib.rs | 36 +++++++++++++++++++----------- src/visitor.rs | 10 ++++----- 4 files changed, 57 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bb4caaa7b93..a188634f98f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -592,10 +592,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // The body of the closure is big enough to be block indented, that // means we must re-format. - let block_shape = Shape { - width: context.config.max_width - shape.block().indent.width(), - ..shape.block() - }; + let block_shape = shape.block().with_max_width(context.config); let block_str = try_opt!(block.rewrite(&context, block_shape)); Some(format!("{} {}", prefix, @@ -1212,11 +1209,7 @@ fn rewrite_match(context: &RewriteContext, result.push('\n'); result.push_str(&arm_indent_str); - let arm_str = arm.rewrite(&context, - Shape { - width: context.config.max_width - arm_shape.indent.width(), - ..arm_shape - }); + let arm_str = arm.rewrite(&context, arm_shape.with_max_width(context.config)); if let Some(ref arm_str) = arm_str { result.push_str(arm_str); } else { @@ -1323,10 +1316,7 @@ impl Rewrite for ast::Arm { let pats_str = try_opt!(write_list(items, &fmt)); let guard_shape = if pats_str.contains('\n') { - Shape { - width: context.config.max_width - shape.indent.width(), - ..shape - } + shape.with_max_width(context.config) } else { shape }; diff --git a/src/items.rs b/src/items.rs index 0b2ca5a52cb..4b49d0a93f9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -208,8 +208,8 @@ impl<'a> FmtVisitor<'a> { let prefix = format!("{}static {}{}: ", vis, mut_str, item.ident); let offset = self.block_indent + prefix.len(); // 1 = ; - let width = self.config.max_width - offset.width() - 1; - let rewrite = ty.rewrite(&self.get_context(), Shape::legacy(width, offset)); + let shape = Shape::indented(offset, self.config).sub_width(1).unwrap(); + let rewrite = ty.rewrite(&self.get_context(), shape); match rewrite { Some(result) => { @@ -332,17 +332,13 @@ impl<'a> FmtVisitor<'a> { let suffix = if semicolon_for_expr(e) { ";" } else { "" }; e.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - self.block_indent.width(), - self.block_indent)) + Shape::indented(self.block_indent, self.config)) .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } None => { stmt.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - self.block_indent.width(), - self.block_indent)) + Shape::indented(self.block_indent, self.config)) } } } else { @@ -434,12 +430,14 @@ impl<'a> FmtVisitor<'a> { body_lo, body_hi); - let budget = self.config.max_width - self.block_indent.width() - 2; + let shape = Shape::indented(self.block_indent, self.config) + .sub_width(2) + .unwrap(); let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", trailing_separator: self.config.trailing_comma, - shape: Shape::legacy(budget, self.block_indent), + shape: shape, ends_with_newline: true, config: self.config, }; @@ -463,9 +461,7 @@ impl<'a> FmtVisitor<'a> { .node .attrs .rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - indent.width(), - indent))); + Shape::indented(indent, self.config))); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -495,7 +491,7 @@ impl<'a> FmtVisitor<'a> { wrap_str(tag, self.config.max_width, - Shape::legacy(self.config.max_width - indent.width(), indent)) + Shape::indented(indent, self.config)) } }; @@ -643,7 +639,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, None => self_ty.span.lo, }; let generics_indent = offset + last_line_width(&result); - let shape = try_opt!(generics_shape(context.config, generics_indent)); + let shape = Shape::indented(generics_indent, context.config); let generics_str = try_opt!(rewrite_generics(context, generics, shape, mk_sp(lo, hi))); result.push_str(&generics_str); @@ -697,8 +693,8 @@ fn format_impl_ref_and_type(context: &RewriteContext, // Can't fit the self type on what's left of the line, so start a new one. let indent = offset.block_indent(context.config); result.push_str(&format!("\n{}", indent.to_string(context.config))); - let budget = try_opt!(context.config.max_width.checked_sub(indent.width())); - result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, indent)))); + result.push_str(&*try_opt!(self_ty.rewrite(context, + Shape::indented(indent, context.config)))); Some(result) } else { unreachable!(); @@ -755,7 +751,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); let generics_indent = offset + last_line_width(&result); - let shape = try_opt!(generics_shape(context.config, generics_indent)); + let shape = Shape::indented(generics_indent, context.config); let generics_str = try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo))); result.push_str(&generics_str); @@ -1000,7 +996,7 @@ fn format_tuple_struct(context: &RewriteContext, let where_clause_str = match generics { Some(generics) => { let generics_indent = offset + last_line_width(&header_str); - let shape = try_opt!(generics_shape(context.config, generics_indent)); + let shape = Shape::indented(generics_indent, context.config); let generics_str = try_opt!(rewrite_generics(context, generics, shape, mk_sp(span.lo, body_lo))); result.push_str(&generics_str); @@ -1131,7 +1127,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let shape = try_opt!(try_opt!(generics_shape(context.config, generics_indent)) + let shape = try_opt!(Shape::indented(generics_indent, context.config) .sub_width(" =".len())); let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); @@ -1205,11 +1201,9 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); - let mut attr_str = try_opt!(self.attrs - .rewrite(context, - Shape::legacy(context.config.max_width - - shape.indent.width(), - shape.indent))); + let mut attr_str = + try_opt!(self.attrs + .rewrite(context, Shape::indented(shape.indent, context.config))); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&shape.indent.to_string(context.config)); @@ -1223,8 +1217,8 @@ impl Rewrite for ast::StructField { let type_offset = shape.indent.block_indent(context.config); let rewrite_type_in_next_line = || { - let budget = try_opt!(context.config.max_width.checked_sub(type_offset.width())); - self.ty.rewrite(context, Shape::legacy(budget, type_offset)) + self.ty + .rewrite(context, Shape::indented(type_offset, context.config)) }; let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); @@ -1555,7 +1549,7 @@ fn rewrite_fn_base(context: &RewriteContext, // Generics. let generics_indent = indent + last_line_width(&result); let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); - let shape = try_opt!(generics_shape(context.config, generics_indent)); + let shape = Shape::indented(generics_indent, context.config); let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); @@ -1564,10 +1558,7 @@ fn rewrite_fn_base(context: &RewriteContext, // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. let ret_str = try_opt!(fd.output - .rewrite(&context, - Shape::legacy(context.config.max_width - - indent.width(), - indent))); + .rewrite(&context, Shape::indented(indent, context.config))); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -1701,9 +1692,9 @@ fn rewrite_fn_base(context: &RewriteContext, if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width())); let ret_str = try_opt!(fd.output - .rewrite(context, Shape::legacy(budget, ret_indent))); + .rewrite(context, + Shape::indented(ret_indent, context.config))); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -1759,11 +1750,10 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let budget = try_opt!(context.config.max_width.checked_sub(indent.block_indent)); let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, context.config.fn_brace_style, - Shape::legacy(budget, indent), + Shape::indented(indent, context.config), Density::Tall, "{", !has_braces, @@ -2226,7 +2216,7 @@ fn format_generics(context: &RewriteContext, offset: Indent, span: Span) -> Option { - let shape = try_opt!(generics_shape(context.config, offset)); + let shape = Shape::indented(offset, context.config); let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { @@ -2269,8 +2259,3 @@ fn format_generics(context: &RewriteContext, Some(result) } - -fn generics_shape(config: &Config, indent: Indent) -> Option { - Some(Shape::legacy(try_opt!(config.max_width.checked_sub(indent.width())), - indent)) -} diff --git a/src/lib.rs b/src/lib.rs index a3f1a93ca48..cd90f5fe931 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -223,14 +223,6 @@ pub struct Shape { } impl Shape { - pub fn indented(indent: Indent, config: &Config) -> Shape { - Shape { - width: config.max_width, - indent: indent, - offset: indent.width(), - } - } - /// `indent` is the indentation of the first line. The next lines /// should begin with at least `indent` spaces (except backwards /// indentation). The first line should not begin with indentation. @@ -254,6 +246,24 @@ impl Shape { } } + pub fn indented(indent: Indent, config: &Config) -> Shape { + Shape { + width: config.max_width.checked_sub(indent.width()).unwrap_or(0), + indent: indent, + offset: indent.alignment, + } + } + + pub fn with_max_width(&self, config: &Config) -> Shape { + Shape { + width: config + .max_width + .checked_sub(self.indent.width()) + .unwrap_or(0), + ..*self + } + } + pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { Shape { width: width, @@ -712,20 +722,20 @@ mod test { fn shape_visual_indent() { let config = Config::default(); let indent = Indent::new(4, 8); - let shape = Shape::indented(indent, &config); + let shape = Shape::legacy(config.max_width, indent); let shape = shape.visual_indent(20); assert_eq!(config.max_width, shape.width); assert_eq!(4, shape.indent.block_indent); - assert_eq!(32, shape.indent.alignment); - assert_eq!(32, shape.offset); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); } #[test] fn shape_block_indent_without_alignment() { let config = Config::default(); let indent = Indent::new(4, 0); - let shape = Shape::indented(indent, &config); + let shape = Shape::legacy(config.max_width, indent); let shape = shape.block_indent(20); assert_eq!(config.max_width, shape.width); @@ -738,7 +748,7 @@ mod test { fn shape_block_indent_with_alignment() { let config = Config::default(); let indent = Indent::new(4, 8); - let shape = Shape::indented(indent, &config); + let shape = Shape::legacy(config.max_width, indent); let shape = shape.block_indent(20); assert_eq!(config.max_width, shape.width); diff --git a/src/visitor.rs b/src/visitor.rs index e2003d1653a..48e65abb6a8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -62,10 +62,9 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - let rewrite = stmt.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - - self.block_indent.width(), - self.block_indent)); + let rewrite = + stmt.rewrite(&self.get_context(), + Shape::indented(self.block_indent, self.config)); if rewrite.is_none() { self.failed = true; } @@ -497,8 +496,7 @@ impl<'a> FmtVisitor<'a> { let rewrite = outers .rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - self.block_indent.width(), - self.block_indent)) + Shape::indented(self.block_indent, self.config)) .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); -- cgit 1.4.1-3-g733a5 From 4a28be486edd7255424ee7d84e5e565a838564ee Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 8 May 2017 07:24:32 +0900 Subject: Refactor Shape --- src/lib.rs | 21 +++++---------------- src/visitor.rs | 5 +---- 2 files changed, 6 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cd90f5fe931..13b2df06740 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -298,34 +298,27 @@ impl Shape { } pub fn block_left(&self, width: usize) -> Option { - let block_shape = self.block_indent(width); - Some(Shape { - width: try_opt!(block_shape.width.checked_sub(width)), - ..block_shape - }) + self.block_indent(width).sub_width(width) } pub fn add_offset(&self, extra_width: usize) -> Shape { Shape { - width: self.width, - indent: self.indent, offset: self.offset + extra_width, + ..*self } } pub fn block(&self) -> Shape { Shape { - width: self.width, indent: self.indent.block_only(), - offset: self.offset, + ..*self } } pub fn sub_width(&self, width: usize) -> Option { Some(Shape { width: try_opt!(self.width.checked_sub(width)), - indent: self.indent, - offset: self.offset, + ..*self }) } @@ -338,11 +331,7 @@ impl Shape { } pub fn offset_left(&self, width: usize) -> Option { - Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - indent: self.indent, - offset: self.offset + width, - }) + self.add_offset(width).sub_width(width) } pub fn used_width(&self) -> usize { diff --git a/src/visitor.rs b/src/visitor.rs index 48e65abb6a8..38185047b7e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -455,10 +455,7 @@ impl<'a> FmtVisitor<'a> { codemap: parse_session.codemap(), buffer: StringBuffer::new(), last_pos: BytePos(0), - block_indent: Indent { - block_indent: 0, - alignment: 0, - }, + block_indent: Indent::empty(), config: config, failed: false, } -- cgit 1.4.1-3-g733a5 From d062d79fb546245199c58a5a0b1ff2e7d9186172 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 8 May 2017 08:07:18 +0900 Subject: Use block indent when visual indent failed --- src/expr.rs | 5 +++-- src/visitor.rs | 20 +++++++++++--------- tests/source/large-block.rs | 5 +++++ tests/target/large-block.rs | 5 +++++ 4 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 tests/source/large-block.rs create mode 100644 tests/target/large-block.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ab831a37431..5aaaa2743f8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -681,8 +681,9 @@ impl Rewrite for ast::Block { }; visitor.visit_block(self); - if visitor.failed { - None + if visitor.failed && shape.indent.alignment != 0 { + self.rewrite(context, + Shape::indented(shape.indent.block_only(), context.config)) } else { Some(format!("{}{}", prefix, visitor.buffer)) } diff --git a/src/visitor.rs b/src/visitor.rs index 38185047b7e..86dd5c239cc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -65,9 +65,6 @@ impl<'a> FmtVisitor<'a> { let rewrite = stmt.rewrite(&self.get_context(), Shape::indented(self.block_indent, self.config)); - if rewrite.is_none() { - self.failed = true; - } self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Mac(ref mac) => { @@ -433,17 +430,22 @@ impl<'a> FmtVisitor<'a> { fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { // 1 = ; - let width = self.config.max_width - self.block_indent.width() - 1; - let rewrite = rewrite_macro(mac, - ident, - &self.get_context(), - Shape::legacy(width, self.block_indent), - pos); + let shape = Shape::indented(self.block_indent, self.config) + .sub_width(1) + .unwrap(); + let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); self.push_rewrite(mac.span, rewrite); } fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo); + self.failed = match rewrite { + Some(ref s) if s.rewrite(&self.get_context(), + Shape::indented(self.block_indent, self.config)) + .is_none() => true, + None => true, + _ => self.failed, + }; let result = rewrite.unwrap_or_else(|| self.snippet(span)); self.buffer.push_str(&result); self.last_pos = source!(self, span).hi; diff --git a/tests/source/large-block.rs b/tests/source/large-block.rs new file mode 100644 index 00000000000..09e9169f340 --- /dev/null +++ b/tests/source/large-block.rs @@ -0,0 +1,5 @@ +fn issue1351() { + std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ + static __STATIC_FMTSTR: &'static [&'static str] = &[]; + }); +} diff --git a/tests/target/large-block.rs b/tests/target/large-block.rs new file mode 100644 index 00000000000..09e9169f340 --- /dev/null +++ b/tests/target/large-block.rs @@ -0,0 +1,5 @@ +fn issue1351() { + std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ + static __STATIC_FMTSTR: &'static [&'static str] = &[]; + }); +} -- cgit 1.4.1-3-g733a5 From 2776615dc95715d197c2e757ae18b3285f06d80e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 8 May 2017 13:13:49 +0900 Subject: Replace 'try!' with '?' --- src/bin/cargo-fmt.rs | 8 ++++---- src/bin/rustfmt.rs | 24 ++++++++++++------------ src/checkstyle.rs | 16 ++++++++-------- src/file_lines.rs | 10 ++++++---- src/filemap.rs | 34 +++++++++++++++++----------------- src/lib.rs | 16 ++++++++-------- src/utils.rs | 2 +- 7 files changed, 56 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 442cb9e78f7..c55c283c654 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -105,7 +105,7 @@ pub enum Verbosity { fn format_crate(verbosity: Verbosity, workspace_hitlist: WorkspaceHitlist) -> Result { - let targets = try!(get_targets(workspace_hitlist)); + let targets = get_targets(workspace_hitlist)?; // Currently only bin and lib files get formatted let files: Vec<_> = targets @@ -181,7 +181,7 @@ impl WorkspaceHitlist { fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std::io::Error> { let mut targets: Vec = vec![]; if workspace_hitlist == WorkspaceHitlist::None { - let output = try!(Command::new("cargo").arg("read-manifest").output()); + let output = Command::new("cargo").arg("read-manifest").output()?; if output.status.success() { // None of the unwraps should fail if output of `cargo read-manifest` is correct let data = &String::from_utf8(output.stdout).unwrap(); @@ -287,7 +287,7 @@ fn format_files(files: &[PathBuf], } println!(""); } - let mut command = try!(Command::new("rustfmt") + let mut command = Command::new("rustfmt") .stdout(stdout) .args(files) .args(fmt_args) @@ -298,6 +298,6 @@ fn format_files(files: &[PathBuf], "Could not run rustfmt, please make sure it is in your PATH.") } _ => e, - })); + })?; command.wait() } diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2c741934a5e..2c5cf697362 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -82,7 +82,7 @@ impl CliOptions { } if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = try!(file_lines.parse()); + options.file_lines = file_lines.parse()?; } Ok(options) @@ -104,12 +104,12 @@ const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; /// nearest project file if one exists, or `None` if no project file was found. fn lookup_project_file(dir: &Path) -> FmtResult> { let mut current = if dir.is_relative() { - try!(env::current_dir()).join(dir) + env::current_dir()?.join(dir) } else { dir.to_path_buf() }; - current = try!(fs::canonicalize(current)); + current = fs::canonicalize(current)?; loop { for config_file_name in &CONFIG_FILE_NAMES { @@ -137,9 +137,9 @@ fn lookup_project_file(dir: &Path) -> FmtResult> { } fn open_config_file(file_path: &Path) -> FmtResult<(Config, Option)> { - let mut file = try!(File::open(&file_path)); + let mut file = File::open(&file_path)?; let mut toml = String::new(); - try!(file.read_to_string(&mut toml)); + file.read_to_string(&mut toml)?; match Config::from_toml(&toml) { Ok(cfg) => Ok((cfg, Some(file_path.to_path_buf()))), Err(err) => Err(FmtError::from(err)), @@ -151,7 +151,7 @@ fn open_config_file(file_path: &Path) -> FmtResult<(Config, Option)> { /// Returns the `Config` to use, and the path of the project file if there was /// one. fn resolve_config(dir: &Path) -> FmtResult<(Config, Option)> { - let path = try!(lookup_project_file(dir)); + let path = lookup_project_file(dir)?; if path.is_none() { return Ok((Config::default(), None)); } @@ -164,7 +164,7 @@ fn match_cli_path_or_file(config_path: Option, -> FmtResult<(Config, Option)> { if let Some(config_file) = config_path { - let (toml, path) = try!(open_config_file(config_file.as_ref())); + let (toml, path) = open_config_file(config_file.as_ref())?; if path.is_some() { return Ok((toml, path)); } @@ -200,9 +200,9 @@ fn make_opts() -> Options { } fn execute(opts: &Options) -> FmtResult { - let matches = try!(opts.parse(env::args().skip(1))); + let matches = opts.parse(env::args().skip(1))?; - match try!(determine_operation(&matches)) { + match determine_operation(&matches)? { Operation::Help => { print_usage(opts, ""); Summary::print_exit_codes(); @@ -226,7 +226,7 @@ fn execute(opts: &Options) -> FmtResult { // parse file_lines if let Some(ref file_lines) = matches.opt_str("file-lines") { - config.file_lines = try!(file_lines.parse()); + config.file_lines = file_lines.parse()?; for f in config.file_lines.files() { if f != "stdin" { println!("Warning: Extra file listed in file_lines option '{}'", f); @@ -237,7 +237,7 @@ fn execute(opts: &Options) -> FmtResult { Ok(run(Input::Text(input), &config)) } Operation::Format { files, config_path } => { - let options = try!(CliOptions::from_matches(&matches)); + let options = CliOptions::from_matches(&matches)?; for f in options.file_lines.files() { if !files.contains(&PathBuf::from(f)) { @@ -386,7 +386,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { // if no file argument is supplied, read from stdin if matches.free.is_empty() { let mut buffer = String::new(); - try!(io::stdin().read_to_string(&mut buffer)); + io::stdin().read_to_string(&mut buffer)?; return Ok(Operation::Stdin { input: buffer, diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 3fc117904c7..69c89a9c5fb 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -20,7 +20,7 @@ pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> xml_heading.push_str(""); xml_heading.push_str("\n"); xml_heading.push_str(""); - try!(write!(out, "{}", xml_heading)); + write!(out, "{}", xml_heading)?; } Ok(()) } @@ -31,7 +31,7 @@ pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> if mode == WriteMode::Checkstyle { let mut xml_tail = String::new(); xml_tail.push_str(""); - try!(write!(out, "{}", xml_tail)); + write!(out, "{}", xml_tail)?; } Ok(()) } @@ -42,21 +42,21 @@ pub fn output_checkstyle_file(mut writer: T, -> Result<(), io::Error> where T: Write { - try!(write!(writer, "", filename)); + write!(writer, "", filename)?; for mismatch in diff { for line in mismatch.lines { // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. if let DiffLine::Expected(ref str) = line { let message = xml_escape_str(str); - try!(write!(writer, - "", - mismatch.line_number, - message)); + mismatch.line_number, + message)?; } } } - try!(write!(writer, "")); + write!(writer, "")?; Ok(()) } diff --git a/src/file_lines.rs b/src/file_lines.rs index a20c8c4d3b3..0316ba277e2 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -173,8 +173,10 @@ impl str::FromStr for FileLines { type Err = String; fn from_str(s: &str) -> Result { - let v: Vec = try!(json::from_str(s).map_err(|e| e.to_string())); - let m = try!(v.into_iter().map(JsonSpan::into_tuple).collect()); + let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; + let m = v.into_iter() + .map(JsonSpan::into_tuple) + .collect::>()?; Ok(FileLines::from_multimap(m)) } } @@ -190,8 +192,8 @@ impl JsonSpan { // To allow `collect()`ing into a `MultiMap`. fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - let canonical = try!(canonicalize_path_string(&self.file) - .map_err(|_| format!("Can't canonicalize {}", &self.file))); + let canonical = canonicalize_path_string(&self.file) + .map_err(|_| format!("Can't canonicalize {}", &self.file))?; Ok((canonical, Range::new(lo, hi))) } } diff --git a/src/filemap.rs b/src/filemap.rs index 6c15d659d54..27f5b990201 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -35,7 +35,7 @@ pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> R { output_header(out, config.write_mode).ok(); for &(ref filename, ref text) in file_map { - try!(write_file(text, filename, out, config)); + write_file(text, filename, out, config)?; } output_footer(out, config.write_mode).ok(); @@ -67,9 +67,9 @@ pub fn write_system_newlines(writer: T, NewlineStyle::Windows => { for (c, _) in text.chars() { match c { - '\n' => try!(write!(writer, "\r\n")), + '\n' => write!(writer, "\r\n")?, '\r' => continue, - c => try!(write!(writer, "{}", c)), + c => write!(writer, "{}", c)?, } } Ok(()) @@ -90,11 +90,11 @@ pub fn write_file(text: &StringBuffer, filename: &str, config: &Config) -> Result<(String, String), io::Error> { - let mut f = try!(File::open(filename)); + let mut f = File::open(filename)?; let mut ori_text = String::new(); - try!(f.read_to_string(&mut ori_text)); + f.read_to_string(&mut ori_text)?; let mut v = Vec::new(); - try!(write_system_newlines(&mut v, text, config)); + write_system_newlines(&mut v, text, config)?; let fmt_text = String::from_utf8(v).unwrap(); Ok((ori_text, fmt_text)) } @@ -103,7 +103,7 @@ pub fn write_file(text: &StringBuffer, text: &StringBuffer, config: &Config) -> Result, io::Error> { - let (ori, fmt) = try!(source_and_formatted_text(text, filename, config)); + let (ori, fmt) = source_and_formatted_text(text, filename, config)?; Ok(make_diff(&ori, &fmt, 3)) } @@ -118,26 +118,26 @@ pub fn write_file(text: &StringBuffer, let bk_name = filename.to_owned() + ".bk"; { // Write text to temp file - let tmp_file = try!(File::create(&tmp_name)); - try!(write_system_newlines(tmp_file, text, config)); + let tmp_file = File::create(&tmp_name)?; + write_system_newlines(tmp_file, text, config)?; } - try!(fs::rename(filename, bk_name)); - try!(fs::rename(tmp_name, filename)); + fs::rename(filename, bk_name)?; + fs::rename(tmp_name, filename)?; } } } WriteMode::Overwrite => { // Write text directly over original file. - let file = try!(File::create(filename)); - try!(write_system_newlines(file, text, config)); + let file = File::create(filename)?; + write_system_newlines(file, text, config)?; } WriteMode::Plain => { - try!(write_system_newlines(out, text, config)); + write_system_newlines(out, text, config)?; } WriteMode::Display | WriteMode::Coverage => { println!("{}:\n", filename); - try!(write_system_newlines(out, text, config)); + write_system_newlines(out, text, config)?; } WriteMode::Diff => { if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { @@ -149,8 +149,8 @@ pub fn write_file(text: &StringBuffer, } } WriteMode::Checkstyle => { - let diff = try!(create_diff(filename, text, config)); - try!(output_checkstyle_file(out, filename, diff)); + let diff = create_diff(filename, text, config)?; + output_checkstyle_file(out, filename, diff)?; } } diff --git a/src/lib.rs b/src/lib.rs index 13b2df06740..e201c891dc2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -414,13 +414,13 @@ impl fmt::Display for FormatReport { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { for (file, errors) in &self.file_error_map { for error in errors { - try!(write!(fmt, - "{} {}:{}: {} {}\n", - error.msg_prefix(), - file, - error.line, - error.kind, - error.msg_suffix())); + write!(fmt, + "{} {}:{}: {} {}\n", + error.msg_prefix(), + file, + error.line, + error.kind, + error.msg_suffix())?; } } Ok(()) @@ -454,7 +454,7 @@ fn format_ast(krate: &ast::Crate, let mut visitor = FmtVisitor::from_codemap(parse_session, config); visitor.format_separate_mod(module); - has_diff |= try!(after_file(path, &mut visitor.buffer)); + has_diff |= after_file(path, &mut visitor.buffer)?; result.push((path.to_owned(), visitor.buffer)); } diff --git a/src/utils.rs b/src/utils.rs index efcf0f1b3e3..d7778448b86 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -211,7 +211,7 @@ macro_rules! impl_enum_decodable { Ok(String::from(value)) } } - let s = try!(d.deserialize_string(StringOnly::(PhantomData))); + let s = d.deserialize_string(StringOnly::(PhantomData))?; $( if stringify!($x).eq_ignore_ascii_case(&s) { return Ok($e::$x); -- cgit 1.4.1-3-g733a5 From f36411c33921bedfef87ee38c7f93340c1667bd7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 9 May 2017 08:11:05 +0900 Subject: Remove visual_indent when rewriting else block --- src/expr.rs | 4 ++-- tests/source/nested-if-else.rs | 11 +++++++++++ tests/target/nested-if-else.rs | 11 +++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/source/nested-if-else.rs create mode 100644 tests/target/nested-if-else.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5aaaa2743f8..61c6cea55e9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1004,7 +1004,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape.visual_indent(0)) + .rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -1014,7 +1014,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape.visual_indent(0)) + .rewrite(context, shape) } _ => { last_in_chain = true; diff --git a/tests/source/nested-if-else.rs b/tests/source/nested-if-else.rs new file mode 100644 index 00000000000..9a54789ddcd --- /dev/null +++ b/tests/source/nested-if-else.rs @@ -0,0 +1,11 @@ +fn issue1518() { + Some(Object { + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) +} diff --git a/tests/target/nested-if-else.rs b/tests/target/nested-if-else.rs new file mode 100644 index 00000000000..4d5bf1f702a --- /dev/null +++ b/tests/target/nested-if-else.rs @@ -0,0 +1,11 @@ +fn issue1518() { + Some(Object { + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) +} -- cgit 1.4.1-3-g733a5 From 0248e9869d9930c5fb8697e0508e00c983fe63f4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 9 May 2017 08:28:05 +0900 Subject: Apply closure exception to match in args --- src/expr.rs | 3 ++- tests/source/match.rs | 8 ++++++++ tests/target/match.rs | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5aaaa2743f8..66cb22127a5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1696,7 +1696,8 @@ fn rewrite_call_inner(context: &RewriteContext, // we format the function arguments horizontally. let overflow_last = match args.last().map(|x| &x.node) { Some(&ast::ExprKind::Closure(..)) | - Some(&ast::ExprKind::Block(..)) if arg_count > 1 => true, + Some(&ast::ExprKind::Block(..)) | + Some(&ast::ExprKind::Match(..)) if arg_count > 1 => true, _ => false, }; diff --git a/tests/source/match.rs b/tests/source/match.rs index 3ed0f89ad7c..bbd6d48827c 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -380,3 +380,11 @@ fn issue1460() { _ => "reorder_something", }; } + +fn issue525() { + foobar(f, "{}", match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }); +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 2d0194f5613..15b7889e476 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -398,3 +398,11 @@ fn issue1460() { _ => "reorder_something", }; } + +fn issue525() { + foobar(f, "{}", match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }); +} -- cgit 1.4.1-3-g733a5 From ac6e6dfd5d5ed5d98f1c4df0a935463c80b22987 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 9 May 2017 17:33:28 +0900 Subject: Refactor rewrite_pat_expr --- src/expr.rs | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6dc7af32ea1..8dfc29c38cc 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1494,6 +1494,7 @@ fn rewrite_pat_expr(context: &RewriteContext, shape: Shape) -> Option { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); + let mut pat_string = String::new(); let mut result = match pat { Some(pat) => { let matcher = if matcher.is_empty() { @@ -1503,7 +1504,7 @@ fn rewrite_pat_expr(context: &RewriteContext, }; let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())) .sub_width(connector.len())); - let pat_string = try_opt!(pat.rewrite(context, pat_shape)); + pat_string = try_opt!(pat.rewrite(context, pat_shape)); format!("{}{}{}", matcher, pat_string, connector) } None => String::new(), @@ -1516,19 +1517,11 @@ fn rewrite_pat_expr(context: &RewriteContext, if shape.width > extra_offset + 1 { let spacer = if pat.is_some() { " " } else { "" }; - let expr_shape = try_opt!(shape.sub_width(extra_offset + spacer.len())) - .add_offset(extra_offset + spacer.len()); + let expr_shape = try_opt!(shape.offset_left(extra_offset + spacer.len())); let expr_rewrite = expr.rewrite(context, expr_shape); if let Some(expr_string) = expr_rewrite { - let pat_simple = pat.and_then(|p| { - p.rewrite(context, - Shape::legacy(context.config.max_width, - Indent::empty())) - }) - .map(|s| pat_is_simple(&s)); - - if pat.is_none() || pat_simple.unwrap_or(false) || !expr_string.contains('\n') { + if pat.is_none() || pat_is_simple(&pat_string) || !expr_string.contains('\n') { result.push_str(spacer); result.push_str(&expr_string); return Some(result); @@ -1542,11 +1535,7 @@ fn rewrite_pat_expr(context: &RewriteContext, result.push('\n'); result.push_str(&nested_indent.to_string(context.config)); - let expr_rewrite = expr.rewrite(&context, - Shape::legacy(try_opt!(context.config - .max_width - .checked_sub(nested_indent.width())), - nested_indent)); + let expr_rewrite = expr.rewrite(&context, Shape::indented(nested_indent, context.config)); result.push_str(&try_opt!(expr_rewrite)); Some(result) -- cgit 1.4.1-3-g733a5 From 9d96c33d592732fb52055987be35b24e2929b616 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 9 May 2017 17:33:45 +0900 Subject: Inherit alignment to last else --- src/expr.rs | 7 +++++-- tests/source/issue-1468.rs | 27 +++++++++++++++++++++++++++ tests/target/issue-1468.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-1468.rs create mode 100644 tests/target/issue-1468.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8dfc29c38cc..6a63e1733d9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -988,8 +988,11 @@ impl<'a> Rewrite for ControlFlow<'a> { if let Some(else_block) = self.else_block { // Since this is an else block, we should not indent for the assignment preceding - // the original if, so set shape.offset to 0. - let shape = Shape { offset: 0, ..shape }; + // the original if, so set shape.offset to shape.indent.alignment. + let shape = Shape { + offset: shape.indent.alignment, + ..shape + }; let mut last_in_chain = false; let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it diff --git a/tests/source/issue-1468.rs b/tests/source/issue-1468.rs new file mode 100644 index 00000000000..1b45aa5d616 --- /dev/null +++ b/tests/source/issue-1468.rs @@ -0,0 +1,27 @@ +fn issue1468() { +euc_jp_decoder_functions!({ +let trail_minus_offset = byte.wrapping_sub(0xA1); +// Fast-track Hiragana (60% according to Lunde) +// and Katakana (10% acconding to Lunde). +if jis0208_lead_minus_offset == 0x03 && +trail_minus_offset < 0x53 { +// Hiragana +handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) +} else if jis0208_lead_minus_offset == 0x04 && +trail_minus_offset < 0x56 { +// Katakana +handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) +} else if trail_minus_offset > (0xFE - 0xA1) { +if byte < 0x80 { +return (DecoderResult::Malformed(1, 0), +unread_handle_trail.unread(), +handle.written()); +} +return (DecoderResult::Malformed(2, 0), +unread_handle_trail.consumed(), +handle.written()); +} else { +unreachable!(); +} +}); +} diff --git a/tests/target/issue-1468.rs b/tests/target/issue-1468.rs new file mode 100644 index 00000000000..518c31b625c --- /dev/null +++ b/tests/target/issue-1468.rs @@ -0,0 +1,27 @@ +fn issue1468() { + euc_jp_decoder_functions!({ + let trail_minus_offset = byte.wrapping_sub(0xA1); + // Fast-track Hiragana (60% according to Lunde) + // and Katakana (10% acconding to Lunde). + if jis0208_lead_minus_offset == 0x03 && + trail_minus_offset < 0x53 { + // Hiragana + handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) + } else if jis0208_lead_minus_offset == 0x04 && + trail_minus_offset < 0x56 { + // Katakana + handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) + } else if trail_minus_offset > (0xFE - 0xA1) { + if byte < 0x80 { + return (DecoderResult::Malformed(1, 0), + unread_handle_trail.unread(), + handle.written()); + } + return (DecoderResult::Malformed(2, 0), + unread_handle_trail.consumed(), + handle.written()); + } else { + unreachable!(); + } + }); +} -- cgit 1.4.1-3-g733a5 From 30a8050559533b1f1d9db2bd1081f97a2f635e6d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 10 May 2017 00:27:57 +0900 Subject: Use multiline when args exceeds max_width in fn_call_style = "block" --- src/expr.rs | 133 +++++++++++++++------------- tests/source/configs-fn_call_style-block.rs | 9 ++ tests/target/configs-fn_call_style-block.rs | 11 +++ 3 files changed, 91 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6dc7af32ea1..637244602de 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::cmp::{Ordering, min}; -use std::borrow::Borrow; use std::mem::swap; use std::ops::Deref; use std::iter::ExactSizeIterator; @@ -1638,47 +1637,75 @@ fn rewrite_call_inner(context: &RewriteContext, -> Result where R: Rewrite { - let callee = callee.borrow(); // FIXME using byte lens instead of char lens (and probably all over the // place too) - let callee_str = match callee.rewrite(context, - Shape { - width: max_callee_width, - ..shape - }) { - Some(string) => { - if !string.contains('\n') && string.len() > max_callee_width { - panic!("{:?} {}", string, max_callee_width); - } else { - string + let callee_shape = Shape { + width: max_callee_width, + ..shape + }; + let callee_str = callee + .rewrite(context, callee_shape) + .ok_or(Ordering::Greater)?; + + // 4 = `( )`, 2 = `()` + let paren_overhead = if context.config.spaces_within_parens { + 4 + } else { + 2 + }; + let used_width = extra_offset(&callee_str, shape); + let one_line_width = shape + .width + .checked_sub(used_width + paren_overhead) + .ok_or(Ordering::Greater)?; + + let nested_shape = match context.config.fn_call_style { + IndentStyle::Block => shape.block().block_left(context.config.tab_spaces), + // 1 = ( + IndentStyle::Visual => { + shape + .visual_indent(used_width + 1) + .sub_width(used_width + paren_overhead) } } - None => return Err(Ordering::Greater), - }; + .ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); - let used_width = extra_offset(&callee_str, shape); + let list_str = rewrite_call_args(context, + args, + span, + nested_shape, + one_line_width, + force_no_trailing_comma) + .ok_or(Ordering::Less)?; - let nested_shape = match context.config.fn_call_style { - IndentStyle::Block => { - shape - .block() - .block_indent(context.config.tab_spaces) - .sub_width(context.config.tab_spaces) - } - // 1 = (, 2 = (). - IndentStyle::Visual => { - shape - .visual_indent(used_width + 1) - .sub_width(used_width + 2) + let result = if context.config.fn_call_style == IndentStyle::Visual || + (!list_str.contains('\n') && list_str.chars().last().unwrap_or(' ') != ',') { + if context.config.spaces_within_parens && list_str.len() > 0 { + format!("{}( {} )", callee_str, list_str) + } else { + format!("{}({})", callee_str, list_str) } + } else { + format!("{}(\n{}{}\n{})", + callee_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.block().indent.to_string(context.config)) }; - let nested_shape = match nested_shape { - Some(s) => s, - None => return Err(Ordering::Greater), - }; + + Ok(result) +} + +fn rewrite_call_args(context: &RewriteContext, + args: &[ptr::P], + span: Span, + shape: Shape, + one_line_width: usize, + force_no_trailing_comma: bool) + -> Option { let arg_count = args.len(); let items = itemize_list(context.codemap, @@ -1686,7 +1713,7 @@ fn rewrite_call_inner(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - |item| item.rewrite(context, nested_shape), + |item| item.rewrite(context, shape), span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1708,8 +1735,8 @@ fn rewrite_call_inner(context: &RewriteContext, // first arguments. if overflow_last { let nested_shape = Shape { - indent: nested_shape.indent.block_only(), - ..nested_shape + indent: shape.indent.block_only(), + ..shape }; let rewrite = args.last().unwrap().rewrite(context, nested_shape); @@ -1722,15 +1749,11 @@ fn rewrite_call_inner(context: &RewriteContext, } } - let one_line_width = shape.width.checked_sub(used_width + 2); - let one_line_width = match one_line_width { - Some(olw) => olw, - None => return Err(Ordering::Greater), - }; let one_line_shape = Shape { width: one_line_width, - ..nested_shape + ..shape }; + let tactic = definitive_tactic(&item_vec, ListTactic::LimitedHorizontalVertical(context.config.fn_call_width), @@ -1748,12 +1771,12 @@ fn rewrite_call_inner(context: &RewriteContext, (false, _, _) => {} } - let fmt = ListFormatting { + let mut fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: if force_no_trailing_comma || context.config.fn_call_style == IndentStyle::Visual || - args.len() <= 1 { + arg_count <= 1 { SeparatorTactic::Never } else { context.config.trailing_comma @@ -1763,27 +1786,13 @@ fn rewrite_call_inner(context: &RewriteContext, config: context.config, }; - let list_str = match write_list(&item_vec, &fmt) { - Some(str) => str, - None => return Err(Ordering::Less), - }; - - let result = if context.config.fn_call_style == IndentStyle::Visual || - !list_str.contains('\n') { - if context.config.spaces_within_parens && list_str.len() > 0 { - format!("{}( {} )", callee_str, list_str) - } else { - format!("{}({})", callee_str, list_str) + match write_list(&item_vec, &fmt) { + Some(ref s) if !s.contains('\n') && s.len() > one_line_width => { + fmt.trailing_separator = SeparatorTactic::Vertical; + write_list(&item_vec, &fmt) } - } else { - format!("{}(\n{}{}\n{})", - callee_str, - nested_shape.indent.to_string(context.config), - list_str, - shape.block().indent.to_string(context.config)) - }; - - Ok(result) + rewrite @ _ => rewrite, + } } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 1d782670a20..4013b2d9b25 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -6,3 +6,12 @@ fn main() { // #1501 let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); } + +// #1521 +impl Foo { + fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { + unsafe { + Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw())) + } + } +} diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index dba4941adb0..d7cb12dd94c 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -15,3 +15,14 @@ fn main() { // #1501 let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); } + +// #1521 +impl Foo { + fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { + unsafe { + Vector2f::from_raw( + ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw()), + ) + } + } +} -- cgit 1.4.1-3-g733a5 From ba1a7b9e7f56c0c9fa8e6ef9d4b2ebec192ddc89 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 11 May 2017 13:38:26 +0900 Subject: Try multi-line only when fn_call_style is Block and rewriting function call --- src/expr.rs | 7 ++++++- tests/source/configs-fn_call_style-block-trailing-comma.rs | 7 +++++++ tests/source/configs-fn_call_style-visual-trailing-comma.rs | 7 +++++++ tests/target/configs-fn_call_style-block-trailing-comma.rs | 7 +++++++ tests/target/configs-fn_call_style-visual-trailing-comma.rs | 7 +++++++ 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/source/configs-fn_call_style-block-trailing-comma.rs create mode 100644 tests/source/configs-fn_call_style-visual-trailing-comma.rs create mode 100644 tests/target/configs-fn_call_style-block-trailing-comma.rs create mode 100644 tests/target/configs-fn_call_style-visual-trailing-comma.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index cf92b7ecc0e..da9a96bf19f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1779,7 +1779,12 @@ fn rewrite_call_args(context: &RewriteContext, }; match write_list(&item_vec, &fmt) { - Some(ref s) if !s.contains('\n') && s.len() > one_line_width => { + // If arguments do not fit in a single line and do not contain newline, + // try to put it on the next line. Try this only when we are in block mode + // and not rewriting macro. + Some(ref s) if context.config.fn_call_style == IndentStyle::Block && + !force_no_trailing_comma && + (!s.contains('\n') && s.len() > one_line_width) => { fmt.trailing_separator = SeparatorTactic::Vertical; write_list(&item_vec, &fmt) } diff --git a/tests/source/configs-fn_call_style-block-trailing-comma.rs b/tests/source/configs-fn_call_style-block-trailing-comma.rs new file mode 100644 index 00000000000..3f3d1dec2ea --- /dev/null +++ b/tests/source/configs-fn_call_style-block-trailing-comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-fn_call_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/tests/source/configs-fn_call_style-visual-trailing-comma.rs b/tests/source/configs-fn_call_style-visual-trailing-comma.rs new file mode 100644 index 00000000000..61be7c5ea93 --- /dev/null +++ b/tests/source/configs-fn_call_style-visual-trailing-comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-fn_call_style: Visual + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/tests/target/configs-fn_call_style-block-trailing-comma.rs b/tests/target/configs-fn_call_style-block-trailing-comma.rs new file mode 100644 index 00000000000..3f3d1dec2ea --- /dev/null +++ b/tests/target/configs-fn_call_style-block-trailing-comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-fn_call_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/tests/target/configs-fn_call_style-visual-trailing-comma.rs b/tests/target/configs-fn_call_style-visual-trailing-comma.rs new file mode 100644 index 00000000000..61be7c5ea93 --- /dev/null +++ b/tests/target/configs-fn_call_style-visual-trailing-comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-fn_call_style: Visual + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} -- cgit 1.4.1-3-g733a5 From 384ce46eef041fe03858428a0b21187717724773 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 12 May 2017 16:30:26 +0900 Subject: Use vertical layout when args len is larger than fn_call_width --- src/expr.rs | 3 ++- tests/source/configs-fn_call_width-zero.rs | 7 +++++++ tests/target/configs-fn_call_style-block.rs | 4 +++- tests/target/configs-fn_call_width-zero.rs | 9 +++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/source/configs-fn_call_width-zero.rs create mode 100644 tests/target/configs-fn_call_width-zero.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index da9a96bf19f..4b34fd8bf6d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1784,7 +1784,8 @@ fn rewrite_call_args(context: &RewriteContext, // and not rewriting macro. Some(ref s) if context.config.fn_call_style == IndentStyle::Block && !force_no_trailing_comma && - (!s.contains('\n') && s.len() > one_line_width) => { + (!s.contains('\n') && + (s.len() > one_line_width || s.len() > context.config.fn_call_width)) => { fmt.trailing_separator = SeparatorTactic::Vertical; write_list(&item_vec, &fmt) } diff --git a/tests/source/configs-fn_call_width-zero.rs b/tests/source/configs-fn_call_width-zero.rs new file mode 100644 index 00000000000..ee79c4ce805 --- /dev/null +++ b/tests/source/configs-fn_call_width-zero.rs @@ -0,0 +1,7 @@ +// rustfmt-fn_call_width: 0 +// rustfmt-fn_call_style: block + +// #1508 +fn a() { + let x = f(y); +} diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index d7cb12dd94c..c9a42cd4952 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -13,7 +13,9 @@ fn main() { "elit", ); // #1501 - let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); + let hyper = Arc::new( + Client::with_connector(HttpsConnector::new(TlsClient::new())), + ); } // #1521 diff --git a/tests/target/configs-fn_call_width-zero.rs b/tests/target/configs-fn_call_width-zero.rs new file mode 100644 index 00000000000..3193bc228f7 --- /dev/null +++ b/tests/target/configs-fn_call_width-zero.rs @@ -0,0 +1,9 @@ +// rustfmt-fn_call_width: 0 +// rustfmt-fn_call_style: block + +// #1508 +fn a() { + let x = f( + y, + ); +} -- cgit 1.4.1-3-g733a5 From 744fa427e2e62e074387392c567bc389d6c580e6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 12 May 2017 17:58:38 +0900 Subject: Support struct_field_attributes --- src/expr.rs | 22 ++++++++++++++-------- tests/source/struct-field-attributes.rs | 22 ++++++++++++++++++++++ tests/target/struct-field-attributes.rs | 22 ++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 tests/source/struct-field-attributes.rs create mode 100644 tests/target/struct-field-attributes.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index da9a96bf19f..e763b5b2be3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1946,19 +1946,25 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> expr_shape.offset += overhead; let expr = field.expr.rewrite(context, expr_shape); + let mut attrs_str = try_opt!((*field.attrs).rewrite(context, shape)); + if !attrs_str.is_empty() { + attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); + }; + match expr { - Some(e) => Some(format!("{}{}{}", name, separator, e)), + Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); let expr = field .expr - .rewrite(context, - Shape::legacy(try_opt!(context - .config - .max_width - .checked_sub(expr_offset.width())), - expr_offset)); - expr.map(|s| format!("{}:\n{}{}", name, expr_offset.to_string(&context.config), s)) + .rewrite(context, Shape::indented(expr_offset, context.config)); + expr.map(|s| { + format!("{}{}:\n{}{}", + attrs_str, + name, + expr_offset.to_string(&context.config), + s) + }) } } } diff --git a/tests/source/struct-field-attributes.rs b/tests/source/struct-field-attributes.rs new file mode 100644 index 00000000000..2e5381a7e41 --- /dev/null +++ b/tests/source/struct-field-attributes.rs @@ -0,0 +1,22 @@ +// #1535 +#![feature(struct_field_attributes)] + +struct Foo { + bar: u64, + + #[cfg(test)] + qux: u64, +} + +fn do_something() -> Foo { + Foo { + bar: 0, + + #[cfg(test)] + qux: 1, + } +} + +fn main() { + do_something(); +} diff --git a/tests/target/struct-field-attributes.rs b/tests/target/struct-field-attributes.rs new file mode 100644 index 00000000000..2e5381a7e41 --- /dev/null +++ b/tests/target/struct-field-attributes.rs @@ -0,0 +1,22 @@ +// #1535 +#![feature(struct_field_attributes)] + +struct Foo { + bar: u64, + + #[cfg(test)] + qux: u64, +} + +fn do_something() -> Foo { + Foo { + bar: 0, + + #[cfg(test)] + qux: 1, + } +} + +fn main() { + do_something(); +} -- cgit 1.4.1-3-g733a5 From 4aa64674c91880eebd047d520d755e9d849b2485 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 13 May 2017 06:44:57 +0900 Subject: Add a missing trailing comma before elipses --- src/patterns.rs | 10 ++++++++-- tests/source/configs-trailing_comma-never.rs | 6 ++++++ tests/target/configs-trailing_comma-never.rs | 10 ++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index a50fee040d6..8edfc1deea0 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -13,8 +13,9 @@ use codemap::SpanUtils; use config::{IndentStyle, MultilineStyle}; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability}; -use lists::{DefinitiveListTactic, format_item_list, itemize_list, ListItem, struct_lit_shape, - struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list}; +use lists::{DefinitiveListTactic, SeparatorTactic, format_item_list, itemize_list, ListItem, + struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting, + write_list}; use expr::{rewrite_unary_prefix, rewrite_pair}; use types::{rewrite_path, PathContext}; use super::Spanned; @@ -134,6 +135,7 @@ fn rewrite_struct_pat(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { + // 2 = ` {` let path_shape = try_opt!(shape.sub_width(2)); let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape)); @@ -165,6 +167,10 @@ fn rewrite_struct_pat(path: &ast::Path, if elipses { if fields_str.contains('\n') { + // Add a missing trailing comma. + if fmt.trailing_separator == SeparatorTactic::Never { + fields_str.push_str(","); + } fields_str.push_str("\n"); fields_str.push_str(&nested_shape.indent.to_string(context.config)); fields_str.push_str(".."); diff --git a/tests/source/configs-trailing_comma-never.rs b/tests/source/configs-trailing_comma-never.rs index 5d4dbef385a..0577f2e5aff 100644 --- a/tests/source/configs-trailing_comma-never.rs +++ b/tests/source/configs-trailing_comma-never.rs @@ -4,4 +4,10 @@ fn main() { let Lorem { ipsum, dolor, sit, } = amet; let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; + + // #1544 + if let VrMsg::ClientReply {request_num: reply_req_num, value, ..} = msg { + let _ = safe_assert_eq!(reply_req_num, request_num, op); + return Ok((request_num, op, value)); + } } diff --git a/tests/target/configs-trailing_comma-never.rs b/tests/target/configs-trailing_comma-never.rs index ca2da9136c7..949069cede8 100644 --- a/tests/target/configs-trailing_comma-never.rs +++ b/tests/target/configs-trailing_comma-never.rs @@ -11,4 +11,14 @@ fn main() { consectetur, adipiscing } = elit; + + // #1544 + if let VrMsg::ClientReply { + request_num: reply_req_num, + value, + .. + } = msg { + let _ = safe_assert_eq!(reply_req_num, request_num, op); + return Ok((request_num, op, value)); + } } -- cgit 1.4.1-3-g733a5 From 7ec78711f2f727baf3d10ca46f7dda35a2f0ffb4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 13 May 2017 18:20:18 +0900 Subject: Prevent rewriting closure block to expr inside macro --- src/chains.rs | 2 +- src/expr.rs | 38 ++++++++++-------------------- src/macros.rs | 13 ++++++---- src/rewrite.rs | 1 + src/visitor.rs | 1 + tests/target/closure-block-inside-macro.rs | 15 ++++++++++++ 6 files changed, 38 insertions(+), 32 deletions(-) create mode 100644 tests/target/closure-block-inside-macro.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3d148d19a55..858103489fd 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -440,5 +440,5 @@ fn rewrite_method_call(method_name: ast::Ident, let callee_str = format!(".{}{}", method_name, type_str); let span = mk_sp(lo, span.hi); - rewrite_call(context, &callee_str, &args[1..], span, shape, false) + rewrite_call(context, &callee_str, &args[1..], span, shape) } diff --git a/src/expr.rs b/src/expr.rs index 0a2fab9cd27..a52e163ac7a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -70,7 +70,7 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, expr.span.hi); - rewrite_call(context, &**callee, args, inner_span, shape, false) + rewrite_call(context, &**callee, args, inner_span, shape) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { @@ -512,7 +512,8 @@ fn rewrite_closure(capture: ast::CaptureBy, } // Figure out if the block is necessary. - let needs_block = block.rules != ast::BlockCheckMode::Default || block.stmts.len() > 1 || + let needs_block = block.rules != ast::BlockCheckMode::Default || + block.stmts.len() > 1 || context.inside_macro || block_contains_comment(block, context.codemap) || prefix.contains('\n'); @@ -1599,20 +1600,12 @@ pub fn rewrite_call(context: &RewriteContext, callee: &R, args: &[ptr::P], span: Span, - shape: Shape, - force_no_trailing_comma: bool) + shape: Shape) -> Option where R: Rewrite { - let closure = |callee_max_width| { - rewrite_call_inner(context, - callee, - callee_max_width, - args, - span, - shape, - force_no_trailing_comma) - }; + let closure = + |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape); // 2 is for parens let max_width = try_opt!(shape.width.checked_sub(2)); @@ -1624,8 +1617,7 @@ fn rewrite_call_inner(context: &RewriteContext, max_callee_width: usize, args: &[ptr::P], span: Span, - shape: Shape, - force_no_trailing_comma: bool) + shape: Shape) -> Result where R: Rewrite { @@ -1665,13 +1657,8 @@ fn rewrite_call_inner(context: &RewriteContext, let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); - let list_str = rewrite_call_args(context, - args, - span, - nested_shape, - one_line_width, - force_no_trailing_comma) - .ok_or(Ordering::Less)?; + let list_str = rewrite_call_args(context, args, span, nested_shape, one_line_width) + .ok_or(Ordering::Less)?; let result = if context.config.fn_call_style == IndentStyle::Visual || (!list_str.contains('\n') && list_str.chars().last().unwrap_or(' ') != ',') { @@ -1695,8 +1682,7 @@ fn rewrite_call_args(context: &RewriteContext, args: &[ptr::P], span: Span, shape: Shape, - one_line_width: usize, - force_no_trailing_comma: bool) + one_line_width: usize) -> Option { let arg_count = args.len(); @@ -1766,7 +1752,7 @@ fn rewrite_call_args(context: &RewriteContext, let mut fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: if force_no_trailing_comma || + trailing_separator: if context.inside_macro || context.config.fn_call_style == IndentStyle::Visual || arg_count <= 1 { SeparatorTactic::Never @@ -1783,7 +1769,7 @@ fn rewrite_call_args(context: &RewriteContext, // try to put it on the next line. Try this only when we are in block mode // and not rewriting macro. Some(ref s) if context.config.fn_call_style == IndentStyle::Block && - !force_no_trailing_comma && + !context.inside_macro && (!s.contains('\n') && (s.len() > one_line_width || s.len() > context.config.fn_call_width)) => { fmt.trailing_separator = SeparatorTactic::Vertical; diff --git a/src/macros.rs b/src/macros.rs index cd3e638d97c..d644e32bb6d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -65,6 +65,8 @@ pub fn rewrite_macro(mac: &ast::Mac, shape: Shape, position: MacroPosition) -> Option { + let mut context = &mut context.clone(); + context.inside_macro = true; if context.config.use_try_shorthand { if let Some(expr) = convert_try_mac(mac, context) { return expr.rewrite(context, shape); @@ -146,11 +148,12 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape, true) - .map(|rw| match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - }) + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map(|rw| { + match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + } + }) } MacroStyle::Brackets => { // Format macro invocation as array literal. diff --git a/src/rewrite.rs b/src/rewrite.rs index bb75a6f4db7..c1047e41b33 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -26,6 +26,7 @@ pub struct RewriteContext<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, pub config: &'a Config, + pub inside_macro: bool, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index 86dd5c239cc..e813f3a1813 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -574,6 +574,7 @@ impl<'a> FmtVisitor<'a> { parse_session: self.parse_session, codemap: self.codemap, config: self.config, + inside_macro: false, } } } diff --git a/tests/target/closure-block-inside-macro.rs b/tests/target/closure-block-inside-macro.rs new file mode 100644 index 00000000000..b58527eb8fb --- /dev/null +++ b/tests/target/closure-block-inside-macro.rs @@ -0,0 +1,15 @@ +// rustfmt-fn_call_style: Block + +// #1547 +fuzz_target!( + |data: &[u8]| { + if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; + } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); + } + } +); -- cgit 1.4.1-3-g733a5 From 819a13030f423849848520e9102c625d0cc1b722 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 13 May 2017 21:07:36 +0900 Subject: Use precise width when rewriting else if --- src/expr.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0a2fab9cd27..5f2b1f0353e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -986,12 +986,7 @@ impl<'a> Rewrite for ControlFlow<'a> { block_str); if let Some(else_block) = self.else_block { - // Since this is an else block, we should not indent for the assignment preceding - // the original if, so set shape.offset to shape.indent.alignment. - let shape = Shape { - offset: shape.indent.alignment, - ..shape - }; + let shape = Shape::indented(shape.indent, context.config); let mut last_in_chain = false; let rewrite = match else_block.node { // If the else expression is another if-else expression, prevent it -- cgit 1.4.1-3-g733a5 From 5383b6cc17210d0c2038e05d5f03a6abe13b38ea Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 13 May 2017 21:08:10 +0900 Subject: Format source code --- src/comment.rs | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 9df303c86b2..17b1700accd 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -52,37 +52,35 @@ pub fn rewrite_comment(orig: &str, return light_rewrite_comment(orig, shape.indent, config); } - let (opener, closer, line_start) = - if block_style { + let (opener, closer, line_start) = if block_style { + ("/* ", " */", " * ") + } else if !config.normalize_comments { + if orig.starts_with("/**") && !orig.starts_with("/**/") { + ("/** ", " **/", " ** ") + } else if orig.starts_with("/*!") { + ("/*! ", " */", " * ") + } else if orig.starts_with("/*") { ("/* ", " */", " * ") - } else if !config.normalize_comments { - if orig.starts_with("/**") && !orig.starts_with("/**/") { - ("/** ", " **/", " ** ") - } else if orig.starts_with("/*!") { - ("/*! ", " */", " * ") - } else if orig.starts_with("/*") { - ("/* ", " */", " * ") - } else if orig.starts_with("///") { - ("/// ", "", "/// ") - } else if orig.starts_with("//!") { - ("//! ", "", "//! ") - } else { - ("// ", "", "// ") - } - } else if orig.starts_with("///") || - (orig.starts_with("/**") && !orig.starts_with("/**/")) { + } else if orig.starts_with("///") { ("/// ", "", "/// ") - } else if orig.starts_with("//!") || orig.starts_with("/*!") { + } else if orig.starts_with("//!") { ("//! ", "", "//! ") - } else if is_custom_comment(orig) { - if orig.chars().nth(3) == Some(' ') { - (&orig[0..4], "", &orig[0..4]) - } else { - (&orig[0..3], "", &orig[0..3]) - } } else { ("// ", "", "// ") - }; + } + } else if orig.starts_with("///") || (orig.starts_with("/**") && !orig.starts_with("/**/")) { + ("/// ", "", "/// ") + } else if orig.starts_with("//!") || orig.starts_with("/*!") { + ("//! ", "", "//! ") + } else if is_custom_comment(orig) { + if orig.chars().nth(3) == Some(' ') { + (&orig[0..4], "", &orig[0..4]) + } else { + (&orig[0..3], "", &orig[0..3]) + } + } else { + ("// ", "", "// ") + }; let max_chars = shape .width -- cgit 1.4.1-3-g733a5 From 9f83f2918743bcce81e1e004daf512d4aaa605ce Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sat, 13 May 2017 13:14:24 -0400 Subject: Refactor file range checking --- src/file_lines.rs | 55 +++++++++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index ea3d63feb92..47497bde03d 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -115,62 +115,41 @@ impl FileLines { Files(self.0.as_ref().map(MultiMap::keys)) } - /// Returns true if `range` is fully contained in `self`. - pub fn contains(&self, range: &LineRange) -> bool { + /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in + /// the designated file (if any) and returns true if `f` ever does. + fn file_range_matches(&self, file_name: &str, f: F) -> bool + where F: FnMut(&Range) -> bool + { let map = match self.0 { // `None` means "all lines in all files". None => return true, Some(ref map) => map, }; - match canonicalize_path_string(range.file_name()) - .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { - Ok(ranges) => ranges.iter().any(|r| r.contains(Range::from(range))), + match canonicalize_path_string(file_name).and_then(|file| map.get_vec(&file).ok_or(())) { + Ok(ranges) => ranges.iter().any(f), Err(_) => false, } } + /// Returns true if `range` is fully contained in `self`. + pub fn contains(&self, range: &LineRange) -> bool { + self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) + } + /// Returns true if any lines in `range` are in `self`. pub fn intersects(&self, range: &LineRange) -> bool { - let map = match self.0 { - // `None` means "all lines in all files". - None => return true, - Some(ref map) => map, - }; - - match canonicalize_path_string(range.file_name()) - .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { - Ok(ranges) => ranges.iter().any(|r| r.intersects(Range::from(range))), - Err(_) => false, - } + self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) } + /// Returns true if `line` from `file_name` is in `self`. pub fn contains_line(&self, file_name: &str, line: usize) -> bool { - let map = match self.0 { - // `None` means "all lines in all files". - None => return true, - Some(ref map) => map, - }; - - match canonicalize_path_string(file_name) - .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { - Ok(ranges) => ranges.iter().any(|r| r.lo <= line && r.hi >= line), - Err(_) => false, - } + self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) } + /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. pub fn intersects_range(&self, file_name: &str, lo: usize, hi: usize) -> bool { - let map = match self.0 { - // `None` means "all lines in all files". - None => return true, - Some(ref map) => map, - }; - - match canonicalize_path_string(file_name) - .and_then(|canonical| map.get_vec(&canonical).ok_or(())) { - Ok(ranges) => ranges.iter().any(|r| r.intersects(Range::new(lo, hi))), - Err(_) => false, - } + self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) } } -- cgit 1.4.1-3-g733a5 From 7783b4c0b60506f1e1aef0ef4e4711d6fc5893e7 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sun, 14 May 2017 13:19:06 +0800 Subject: add more specific reason why it fails to parse --- src/config.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 441f86f48cb..632170e6812 100644 --- a/src/config.rs +++ b/src/config.rs @@ -261,8 +261,9 @@ macro_rules! create_config { match parsed.try_into() { Ok(parsed_config) => Ok(Config::default().fill_from_parsed_config(parsed_config)), - Err(_) => { - err.push_str("Error: Decoding config file failed. "); + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); err.push_str("Please check your config file.\n"); Err(err) } -- cgit 1.4.1-3-g733a5 From 79ba34c60758f02b3aded90bae3fb9983f550234 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 15 May 2017 22:55:01 +0900 Subject: Use offset_left for rewrite_unary_prefix --- src/expr.rs | 36 ++++++++---------------------------- src/patterns.rs | 6 ++---- tests/source/macros.rs | 6 ++++++ tests/target/macros.rs | 6 ++++++ 4 files changed, 22 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 585073c8f0c..729a98170af 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -156,11 +156,7 @@ fn format_expr(expr: &ast::Expr, }; if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, - &format!("break{} ", id_str), - &**expr, - shape, - expr.span) + rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) } else { wrap_str(format!("break{}", id_str), context.config.max_width, shape) } @@ -180,11 +176,9 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Ret(None) => wrap_str("return".to_owned(), context.config.max_width, shape), ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, shape, expr.span) - } - ast::ExprKind::Box(ref expr) => { - rewrite_unary_prefix(context, "box ", &**expr, shape, expr.span) + rewrite_unary_prefix(context, "return ", &**expr, shape) } + ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), ast::ExprKind::AddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, expr, shape) } @@ -226,7 +220,7 @@ fn format_expr(expr: &ast::Expr, } else { delim.into() }; - rewrite_unary_prefix(context, &sp_delim, &**rhs, shape, expr.span) + rewrite_unary_prefix(context, &sp_delim, &**rhs, shape) } (Some(ref lhs), None) => { let sp_delim = if context.config.spaces_around_ranges { @@ -1999,24 +1993,10 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, pub fn rewrite_unary_prefix(context: &RewriteContext, prefix: &str, rewrite: &R, - mut shape: Shape, - span: Span) + shape: Shape) -> Option { - // Heuristic: if unary is `&` and `rewrite` contains `{`, - // it is likely that block indent is preferred to visual indent. - if prefix == "&" { - let snippet = String::from(context.snippet(span).trim_left_matches('&')); - let first_line = try_opt!(snippet.lines().nth(0)); - if first_line.contains("{") { - shape = try_opt!(shape.sub_width(prefix.len())).block_indent(0); - } else { - shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); - } - } else { - shape = try_opt!(shape.shrink_left(prefix.len())).visual_indent(0); - } rewrite - .rewrite(context, shape) + .rewrite(context, try_opt!(shape.offset_left(prefix.len()))) .map(|r| format!("{}{}", prefix, r)) } @@ -2046,7 +2026,7 @@ fn rewrite_unary_op(context: &RewriteContext, ast::UnOp::Not => "!", ast::UnOp::Neg => "-", }; - rewrite_unary_prefix(context, operator_str, expr, shape, expr.span) + rewrite_unary_prefix(context, operator_str, expr, shape) } fn rewrite_assignment(context: &RewriteContext, @@ -2143,5 +2123,5 @@ fn rewrite_expr_addrof(context: &RewriteContext, ast::Mutability::Immutable => "&", ast::Mutability::Mutable => "&mut ", }; - rewrite_unary_prefix(context, operator_str, expr, shape, expr.span) + rewrite_unary_prefix(context, operator_str, expr, shape) } diff --git a/src/patterns.rs b/src/patterns.rs index 8edfc1deea0..75175cc7667 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -28,9 +28,7 @@ use syntax::codemap::{self, BytePos, Span}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - PatKind::Box(ref pat) => { - rewrite_unary_prefix(context, "box ", &**pat, shape, self.span) - } + PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { BindingMode::ByRef(mutability) => ("ref ", mutability), @@ -74,7 +72,7 @@ impl Rewrite for Pat { } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); - rewrite_unary_prefix(context, &prefix, &**pat, shape, self.span) + rewrite_unary_prefix(context, &prefix, &**pat, shape) } PatKind::Tuple(ref items, dotdot_pos) => { rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) diff --git a/tests/source/macros.rs b/tests/source/macros.rs index c8f625b935b..3eee8c543ba 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -79,3 +79,9 @@ gfx_pipeline!(pipe { fn issue_1279() { println!("dsfs"); // a comment } + +fn issue_1555() { + let hello = &format!("HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", + "65454654654654654654654655464", + "4"); +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index c4f40cfe55b..1fd8130f824 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -80,3 +80,9 @@ gfx_pipeline!(pipe { fn issue_1279() { println!("dsfs"); // a comment } + +fn issue_1555() { + let hello = &format!("HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", + "65454654654654654654654655464", + "4"); +} -- cgit 1.4.1-3-g733a5 From 762db5138e3c859f3dd736a46798615c561831a1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 15 May 2017 22:55:45 +0900 Subject: Format source codes --- src/expr.rs | 16 ++++++++-------- src/issues.rs | 49 ++++++++++++++++++++++++------------------------- src/items.rs | 2 +- src/macros.rs | 14 +++++++------- src/missed_spans.rs | 12 ++++++------ src/types.rs | 2 +- src/visitor.rs | 4 ++-- 7 files changed, 49 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 729a98170af..7fb71c2e8b4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1961,14 +1961,14 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); return items - .next() - .unwrap() - .rewrite(context, nested_shape) - .map(|s| if context.config.spaces_within_parens { - format!("( {}, )", s) - } else { - format!("({},)", s) - }); + .next() + .unwrap() + .rewrite(context, nested_shape) + .map(|s| if context.config.spaces_within_parens { + format!("( {}, )", s) + } else { + format!("({},)", s) + }); } let list_lo = context.codemap.span_after(span, "("); diff --git a/src/issues.rs b/src/issues.rs index 4819816c4eb..6e58784c1b8 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -131,16 +131,16 @@ impl BadIssueSeeker { todo_idx += 1; if todo_idx == TO_DO_CHARS.len() { return Seeking::Number { - issue: Issue { - issue_type: IssueType::Todo, - missing_number: if let ReportTactic::Unnumbered = self.report_todo { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; + issue: Issue { + issue_type: IssueType::Todo, + missing_number: if let ReportTactic::Unnumbered = self.report_todo { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; } fixme_idx = 0; } else if self.report_fixme.is_enabled() && c == FIX_ME_CHARS[fixme_idx] { @@ -149,17 +149,16 @@ impl BadIssueSeeker { fixme_idx += 1; if fixme_idx == FIX_ME_CHARS.len() { return Seeking::Number { - issue: Issue { - issue_type: IssueType::Fixme, - missing_number: if let ReportTactic::Unnumbered = - self.report_fixme { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; + issue: Issue { + issue_type: IssueType::Fixme, + missing_number: if let ReportTactic::Unnumbered = self.report_fixme { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; } todo_idx = 0; } else { @@ -182,10 +181,10 @@ impl BadIssueSeeker { return IssueClassification::Bad(issue); } else if c == ')' { return if let NumberPart::CloseParen = part { - IssueClassification::Good - } else { - IssueClassification::Bad(issue) - }; + IssueClassification::Good + } else { + IssueClassification::Bad(issue) + }; } match part { diff --git a/src/items.rs b/src/items.rs index a99797579c3..5eb1414c2e0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1104,7 +1104,7 @@ fn format_tuple_struct(context: &RewriteContext, // know that earlier, so the where clause will not be indented properly. result.push('\n'); result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1)) - .to_string(context.config)); + .to_string(context.config)); } result.push_str(&where_clause_str); diff --git a/src/macros.rs b/src/macros.rs index d644e32bb6d..8f998e42035 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -94,13 +94,13 @@ pub fn rewrite_macro(mac: &ast::Mac, if mac.node.tts.is_empty() && !contains_comment(&context.snippet(mac.span)) { return match style { - MacroStyle::Parens if position == MacroPosition::Item => { - Some(format!("{}();", macro_name)) - } - MacroStyle::Parens => Some(format!("{}()", macro_name)), - MacroStyle::Brackets => Some(format!("{}[]", macro_name)), - MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), - }; + MacroStyle::Parens if position == MacroPosition::Item => { + Some(format!("{}();", macro_name)) + } + MacroStyle::Parens => Some(format!("{}()", macro_name)), + MacroStyle::Brackets => Some(format!("{}[]", macro_name)), + MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), + }; } let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index aef158199ba..843556b9b38 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -138,8 +138,8 @@ impl<'a> FmtVisitor<'a> { if rewrite_next_comment && !self.config - .file_lines - .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) { + .file_lines + .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) { rewrite_next_comment = false; } @@ -164,7 +164,7 @@ impl<'a> FmtVisitor<'a> { Shape::legacy(comment_width, self.block_indent), self.config) - .unwrap()); + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); @@ -172,9 +172,9 @@ impl<'a> FmtVisitor<'a> { if let Some('/') = subslice.chars().skip(1).next() { // check that there are no contained block comments if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() > 2 && &s[0..2] == "/*") { + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() > 2 && &s[0..2] == "/*") { // Add a newline after line comments self.buffer.push_str("\n"); } diff --git a/src/types.rs b/src/types.rs index e2a95c66832..754db673013 100644 --- a/src/types.rs +++ b/src/types.rs @@ -595,7 +595,7 @@ impl Rewrite for ast::Ty { Mutability::Immutable => "*const ", }; - rewrite_unary_prefix(context, prefix, &*mt.ty, shape, self.span) + rewrite_unary_prefix(context, prefix, &*mt.ty, shape) } ast::TyKind::Rptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); diff --git a/src/visitor.rs b/src/visitor.rs index e813f3a1813..556b9912697 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -50,8 +50,8 @@ impl<'a> FmtVisitor<'a> { // FIXME(#434): Move this check to somewhere more central, eg Rewrite. if !self.config - .file_lines - .intersects(&self.codemap.lookup_line_range(stmt.span)) { + .file_lines + .intersects(&self.codemap.lookup_line_range(stmt.span)) { return; } -- cgit 1.4.1-3-g733a5 From c0bdbfa5315217741213d04329b02a4fb5e061e7 Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Tue, 16 May 2017 15:47:09 +0700 Subject: Switch to accessing config items via method. Preparation for #865, which proposes adding a flag which outputs which config options are used during formatting. This PR should not make any difference to functionality. A lot of this was search-and-replace. Some areas worthy of review/discussion: - The method for each config item returns a clone of the underlying value. We can't simply return an immutable reference, as lots of places in the code expect to be able to pass the returned value as `bool` (not `&bool). It would be nice if the `bool` items could return a copy, but the more complex types a borrowed reference... but unfortunately, I couldn't get the macro to do this. - A few places (mostly tests and `src/bin/rustfmt.rs`) were overriding config items by modifying the fields of the `Config` struct directly. They now use the existing `override_value()` method, which has been modified to return a `Result` for use by `src/bin/rustfmt.rs`. This benefits of this are that the complex `file_lines` and `write_mode` strings are now parsed in one place (`Config.override_value`) instead of multiple. The disadvantages are that it moves the compile-time checks for config names to become run-time checks. --- Contributing.md | 2 +- Design.md | 2 +- src/bin/rustfmt.rs | 58 ++++++------- src/chains.rs | 32 +++---- src/comment.rs | 18 ++-- src/config.rs | 24 ++++-- src/expr.rs | 153 +++++++++++++++++++--------------- src/filemap.rs | 10 +-- src/imports.rs | 4 +- src/items.rs | 234 ++++++++++++++++++++++++++-------------------------- src/lib.rs | 46 ++++++----- src/lists.rs | 19 +++-- src/macros.rs | 2 +- src/missed_spans.rs | 10 +-- src/patterns.rs | 23 +++--- src/string.rs | 2 +- src/types.rs | 54 ++++++------ src/utils.rs | 2 +- src/visitor.rs | 24 +++--- tests/system.rs | 10 ++- 20 files changed, 384 insertions(+), 345 deletions(-) (limited to 'src') diff --git a/Contributing.md b/Contributing.md index 7c66d27da41..730cefdca45 100644 --- a/Contributing.md +++ b/Contributing.md @@ -207,6 +207,6 @@ handling of configuration options is done in [src/config.rs](src/config.rs). Loo `create_config!` macro at the end of the file for all the options. The rest of the file defines a bunch of enums used for options, and the machinery to produce the config struct and parse a config file, etc. Checking an option is done by -accessing the correct field on the config struct, e.g., `config.max_width`. Most +accessing the correct field on the config struct, e.g., `config.max_width()`. Most functions have a `Config`, or one can be accessed via a visitor or context of some kind. diff --git a/Design.md b/Design.md index da52fb23e40..43caa7b81f8 100644 --- a/Design.md +++ b/Design.md @@ -150,7 +150,7 @@ for its configuration. Our visitor keeps track of the desired current indent due to blocks ( `block_indent`). Each `visit_*` method reformats code according to this indent, -`config.comment_width` and `config.max_width`. Most reformatting done in the +`config.comment_width()` and `config.max_width()`. Most reformatting done in the `visit_*` methods is a bit hackey and is meant to be temporary until it can be done properly. diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2c5cf697362..fac4f9f8714 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,14 +18,12 @@ extern crate env_logger; extern crate getopts; use rustfmt::{run, Input, Summary}; -use rustfmt::file_lines::FileLines; -use rustfmt::config::{Config, WriteMode}; +use rustfmt::config::Config; use std::{env, error}; use std::fs::{self, File}; use std::io::{self, ErrorKind, Read, Write}; use std::path::{Path, PathBuf}; -use std::str::FromStr; use getopts::{Matches, Options}; @@ -63,8 +61,8 @@ enum Operation { struct CliOptions { skip_children: bool, verbose: bool, - write_mode: Option, - file_lines: FileLines, // Default is all lines in all files. + write_mode: Option, + file_lines: Option, } impl CliOptions { @@ -73,28 +71,29 @@ impl CliOptions { options.skip_children = matches.opt_present("skip-children"); options.verbose = matches.opt_present("verbose"); - if let Some(ref write_mode) = matches.opt_str("write-mode") { - if let Ok(write_mode) = WriteMode::from_str(write_mode) { - options.write_mode = Some(write_mode); - } else { - return Err(FmtError::from(format!("Invalid write-mode: {}", write_mode))); - } + if let Some(write_mode) = matches.opt_str("write-mode") { + options.write_mode = Some(write_mode); } - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse()?; + if let Some(file_lines) = matches.opt_str("file-lines") { + options.file_lines = Some(file_lines); } Ok(options) } - fn apply_to(self, config: &mut Config) { - config.skip_children = self.skip_children; - config.verbose = self.verbose; - config.file_lines = self.file_lines; - if let Some(write_mode) = self.write_mode { - config.write_mode = write_mode; + fn apply_to(&self, config: &mut Config) -> FmtResult<()> { + let bool_to_str = |b| if b { "true" } else { "false" }; + config + .override_value("skip_children", bool_to_str(self.skip_children))?; + config.override_value("verbose", bool_to_str(self.verbose))?; + if let Some(ref write_mode) = self.write_mode { + config.override_value("write_mode", &write_mode)?; } + if let Some(ref file_lines) = self.file_lines { + config.override_value("file_lines", &file_lines)?; + } + Ok(()) } } @@ -222,12 +221,12 @@ fn execute(opts: &Options) -> FmtResult { &env::current_dir().unwrap())?; // write_mode is always Plain for Stdin. - config.write_mode = WriteMode::Plain; + config.override_value("write_mode", "Plain")?; // parse file_lines if let Some(ref file_lines) = matches.opt_str("file-lines") { - config.file_lines = file_lines.parse()?; - for f in config.file_lines.files() { + config.override_value("file-lines", file_lines)?; + for f in config.file_lines().files() { if f != "stdin" { println!("Warning: Extra file listed in file_lines option '{}'", f); } @@ -239,12 +238,6 @@ fn execute(opts: &Options) -> FmtResult { Operation::Format { files, config_path } => { let options = CliOptions::from_matches(&matches)?; - for f in options.file_lines.files() { - if !files.contains(&PathBuf::from(f)) { - println!("Warning: Extra file listed in file_lines option '{}'", f); - } - } - let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -253,6 +246,13 @@ fn execute(opts: &Options) -> FmtResult { config = cfg_tmp; path = path_tmp; }; + options.apply_to(&mut config)?; + + for f in config.file_lines().files() { + if !files.contains(&PathBuf::from(f)) { + println!("Warning: Extra file listed in file_lines option '{}'", f); + } + } if options.verbose { if let Some(path) = path.as_ref() { @@ -282,7 +282,7 @@ fn execute(opts: &Options) -> FmtResult { config = config_tmp; } - options.clone().apply_to(&mut config); + options.apply_to(&mut config)?; error_summary.add(run(Input::File(file), &config)); } } diff --git a/src/chains.rs b/src/chains.rs index 858103489fd..e8a334bb134 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -114,23 +114,23 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { let nested_shape = if first_subexpr_is_try { - parent_shape.block_indent(context.config.tab_spaces) + parent_shape.block_indent(context.config.tab_spaces()) } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) }; (nested_shape, - context.config.chain_indent == IndentStyle::Visual || - parent_rewrite.len() <= context.config.tab_spaces) + context.config.chain_indent() == IndentStyle::Visual || + parent_rewrite.len() <= context.config.tab_spaces()) } else if is_block_expr(&parent, &parent_rewrite) { // The parent is a block, so align the rest of the chain with the closing // brace. (parent_shape, false) } else if parent_rewrite_contains_newline { (chain_indent(context, - parent_shape.block_indent(context.config.tab_spaces)), + parent_shape.block_indent(context.config.tab_spaces())), false) } else { - (shape.block_indent(context.config.tab_spaces), false) + (shape.block_indent(context.config.tab_spaces()), false) }; let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset) @@ -143,14 +143,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; let first_child_shape = if extend { let mut shape = try_opt!(parent_shape.offset_left(last_line_width(&parent_rewrite))); - match context.config.chain_indent { + match context.config.chain_indent() { IndentStyle::Visual => shape, IndentStyle::Block => { shape.offset = shape .offset - .checked_sub(context.config.tab_spaces) + .checked_sub(context.config.tab_spaces()) .unwrap_or(0); - shape.indent.block_indent += context.config.tab_spaces; + shape.indent.block_indent += context.config.tab_spaces(); shape } } @@ -176,7 +176,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len()) + parent_rewrite.len(); - let veto_single_line = if one_line_len > context.config.chain_one_line_max { + let veto_single_line = if one_line_len > context.config.chain_one_line_max() { if rewrites.len() > 1 { true } else if rewrites.len() == 1 { @@ -185,7 +185,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { false } - } else if context.config.take_source_hints && subexpr_list.len() > 1 { + } else if context.config.take_source_hints() && subexpr_list.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); @@ -214,7 +214,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - shape) { // If the first line of the last method does not fit into a single line // after the others, allow new lines. - almost_total + first_line_width(&last[0]) < context.config.max_width + almost_total + first_line_width(&last[0]) < context.config.max_width() } else { false } @@ -242,7 +242,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - parent_rewrite, first_connector, join_rewrites(&rewrites, &subexpr_list, &connector)), - context.config.max_width, + context.config.max_width(), shape) } @@ -320,9 +320,9 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, } fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.chain_indent { + match context.config.chain_indent() { IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape.block_indent(context.config.tab_spaces), + IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), } } @@ -372,7 +372,7 @@ fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option ast::Expr { match expr.node { - ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand => { + ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { if let Some(subexpr) = convert_try_mac(mac, context) { subexpr } else { @@ -428,7 +428,7 @@ fn rewrite_method_call(method_name: ast::Ident, let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); - let type_str = if context.config.spaces_within_angle_brackets && type_list.len() > 0 { + let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) } else { format!("::<{}>", type_list.join(", ")) diff --git a/src/comment.rs b/src/comment.rs index 17b1700accd..ad52ec67f33 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -38,23 +38,23 @@ pub fn rewrite_comment(orig: &str, config: &Config) -> Option { // If there are lines without a starting sigil, we won't format them correctly - // so in that case we won't even re-align (if !config.normalize_comments) and + // so in that case we won't even re-align (if !config.normalize_comments()) and // we should stop now. let num_bare_lines = orig.lines() .map(|line| line.trim()) .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) .count(); - if num_bare_lines > 0 && !config.normalize_comments { + if num_bare_lines > 0 && !config.normalize_comments() { return Some(orig.to_owned()); } - if !config.normalize_comments && !config.wrap_comments { + if !config.normalize_comments() && !config.wrap_comments() { return light_rewrite_comment(orig, shape.indent, config); } let (opener, closer, line_start) = if block_style { ("/* ", " */", " * ") - } else if !config.normalize_comments { + } else if !config.normalize_comments() { if orig.starts_with("/**") && !orig.starts_with("/**/") { ("/** ", " **/", " ** ") } else if orig.starts_with("/*!") { @@ -128,7 +128,7 @@ pub fn rewrite_comment(orig: &str, result.push_str(line_start); } - if config.wrap_comments && line.len() > max_chars { + if config.wrap_comments() && line.len() > max_chars { let rewrite = rewrite_string(line, &fmt).unwrap_or(line.to_owned()); result.push_str(&rewrite); } else { @@ -579,7 +579,7 @@ pub fn recover_comment_removed(new: String, if changed_comment_content(&snippet, &new) { // We missed some comments // Keep previous formatting if it satisfies the constrains - wrap_str(snippet, context.config.max_width, shape) + wrap_str(snippet, context.config.max_width(), shape) } else { Some(new) } @@ -731,8 +731,10 @@ mod test { #[cfg_attr(rustfmt, rustfmt_skip)] fn format_comments() { let mut config: ::config::Config = Default::default(); - config.wrap_comments = true; - config.normalize_comments = true; + config.override_value("wrap_comments", "true") + .expect("Could not set wrap_comments to true"); + config.override_value("normalize_comments", "true") + .expect("Could not set normalize_comments to true"); let comment = rewrite_comment(" //test", true, diff --git a/src/config.rs b/src/config.rs index 632170e6812..63c33cdf6fc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,9 @@ extern crate toml; +use std::error; +use std::result; + use file_lines::FileLines; use lists::{SeparatorTactic, ListTactic}; @@ -212,7 +215,7 @@ macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[derive(Deserialize, Clone)] pub struct Config { - $(pub $i: $ty),+ + $($i: $ty),+ } // Just like the Config struct but with each property wrapped @@ -227,6 +230,12 @@ macro_rules! create_config { impl Config { + $( + pub fn $i(&self) -> $ty { + self.$i.clone() + } + )+ + fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config { $( if let Some(val) = parsed.$i { @@ -270,19 +279,16 @@ macro_rules! create_config { } } - pub fn override_value(&mut self, key: &str, val: &str) { + pub fn override_value(&mut self, key: &str, val: &str) + -> result::Result<(), Box> + { match key { $( - stringify!($i) => { - self.$i = val.parse::<$ty>() - .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", - stringify!($i), - val, - stringify!($ty))); - } + stringify!($i) => self.$i = val.parse::<$ty>()?, )+ _ => panic!("Unknown config key in override: {}", key) } + Ok(()) } pub fn print_docs() { diff --git a/src/expr.rs b/src/expr.rs index 7fb71c2e8b4..9d1f1093fa9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -65,7 +65,11 @@ fn format_expr(expr: &ast::Expr, ast::LitKind::Str(_, ast::StrStyle::Cooked) => { rewrite_string_lit(context, l.span, shape) } - _ => wrap_str(context.snippet(expr.span), context.config.max_width, shape), + _ => { + wrap_str(context.snippet(expr.span), + context.config.max_width(), + shape) + } } } ast::ExprKind::Call(ref callee, ref args) => { @@ -146,7 +150,7 @@ fn format_expr(expr: &ast::Expr, None => String::new(), }; wrap_str(format!("continue{}", id_str), - context.config.max_width, + context.config.max_width(), shape) } ast::ExprKind::Break(ref opt_ident, ref opt_expr) => { @@ -158,7 +162,9 @@ fn format_expr(expr: &ast::Expr, if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) } else { - wrap_str(format!("break{}", id_str), context.config.max_width, shape) + wrap_str(format!("break{}", id_str), + context.config.max_width(), + shape) } } ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { @@ -171,10 +177,15 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - .or_else(|| wrap_str(context.snippet(expr.span), context.config.max_width, shape)) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str(context.snippet(expr.span), + context.config.max_width(), + shape) + }) + } + ast::ExprKind::Ret(None) => { + wrap_str("return".to_owned(), context.config.max_width(), shape) } - ast::ExprKind::Ret(None) => wrap_str("return".to_owned(), context.config.max_width, shape), ast::ExprKind::Ret(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", &**expr, shape) } @@ -192,7 +203,7 @@ fn format_expr(expr: &ast::Expr, rewrite_index(&**expr, &**index, context, shape) } ast::ExprKind::Repeat(ref expr, ref repeats) => { - let (lbr, rbr) = if context.config.spaces_within_square_brackets { + let (lbr, rbr) = if context.config.spaces_within_square_brackets() { ("[ ", " ]") } else { ("[", "]") @@ -207,7 +218,7 @@ fn format_expr(expr: &ast::Expr, match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { (Some(ref lhs), Some(ref rhs)) => { - let sp_delim = if context.config.spaces_around_ranges { + let sp_delim = if context.config.spaces_around_ranges() { format!(" {} ", delim) } else { delim.into() @@ -215,7 +226,7 @@ fn format_expr(expr: &ast::Expr, rewrite_pair(&**lhs, &**rhs, "", &sp_delim, "", context, shape) } (None, Some(ref rhs)) => { - let sp_delim = if context.config.spaces_around_ranges { + let sp_delim = if context.config.spaces_around_ranges() { format!("{} ", delim) } else { delim.into() @@ -223,21 +234,23 @@ fn format_expr(expr: &ast::Expr, rewrite_unary_prefix(context, &sp_delim, &**rhs, shape) } (Some(ref lhs), None) => { - let sp_delim = if context.config.spaces_around_ranges { + let sp_delim = if context.config.spaces_around_ranges() { format!(" {}", delim) } else { delim.into() }; rewrite_unary_suffix(context, &sp_delim, &**lhs, shape) } - (None, None) => wrap_str(delim.into(), context.config.max_width, shape), + (None, None) => wrap_str(delim.into(), context.config.max_width(), shape), } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - wrap_str(context.snippet(expr.span), context.config.max_width, shape) + wrap_str(context.snippet(expr.span), + context.config.max_width(), + shape) } }; result.and_then(|res| recover_comment_removed(res, expr.span, context, shape)) @@ -304,14 +317,14 @@ pub fn rewrite_pair(lhs: &LHS, let infix = infix.trim_right(); let lhs_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(shape.used_width() + prefix.len() + infix.len())); - let rhs_shape = match context.config.control_style { + let rhs_shape = match context.config.control_style() { Style::Default => { try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) } - Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces)), + Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces())), }; let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); @@ -336,14 +349,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I, -> Option where I: Iterator { - let bracket_size = if context.config.spaces_within_square_brackets { + let bracket_size = if context.config.spaces_within_square_brackets() { 2 // "[ " } else { 1 // "[" }; - let nested_shape = match context.config.array_layout { - IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces), + let nested_shape = match context.config.array_layout() { + IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), IndentStyle::Visual => { try_opt!(shape .visual_indent(bracket_size) @@ -362,7 +375,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, .collect::>(); if items.is_empty() { - if context.config.spaces_within_square_brackets { + if context.config.spaces_within_square_brackets() { return Some("[ ]".to_string()); } else { return Some("[]".to_string()); @@ -375,12 +388,13 @@ pub fn rewrite_array<'a, I>(expr_iter: I, .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y)))); - let tactic = match context.config.array_layout { + let tactic = match context.config.array_layout() { IndentStyle::Block => { // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { Some(width) => { - let tactic = ListTactic::LimitedHorizontalVertical(context.config.array_width); + let tactic = + ListTactic::LimitedHorizontalVertical(context.config.array_width()); definitive_tactic(&items, tactic, width) } None => DefinitiveListTactic::Vertical, @@ -389,7 +403,9 @@ pub fn rewrite_array<'a, I>(expr_iter: I, IndentStyle::Visual => { if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic(&items, - ListTactic::LimitedHorizontalVertical(context.config.array_width), + ListTactic::LimitedHorizontalVertical(context + .config + .array_width()), nested_shape.width) } else { DefinitiveListTactic::Mixed @@ -407,9 +423,9 @@ pub fn rewrite_array<'a, I>(expr_iter: I, }; let list_str = try_opt!(write_list(&items, &fmt)); - let result = if context.config.array_layout == IndentStyle::Visual || + let result = if context.config.array_layout() == IndentStyle::Visual || tactic != DefinitiveListTactic::Vertical { - if context.config.spaces_within_square_brackets && list_str.len() > 0 { + if context.config.spaces_within_square_brackets() && list_str.len() > 0 { format!("[ {} ]", list_str) } else { format!("[{}]", list_str) @@ -574,7 +590,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // Start with visual indent, then fall back to block indent if the // closure is large. if let Some(block_str) = block.rewrite(&context, shape) { - let block_threshold = context.config.closure_block_indent_threshold; + let block_threshold = context.config.closure_block_indent_threshold(); if block_threshold < 0 || block_str.matches('\n').count() <= block_threshold as usize { if let Some(block_str) = block_str.rewrite(context, shape) { return Some(format!("{} {}", prefix, block_str)); @@ -878,11 +894,11 @@ impl<'a> Rewrite for ControlFlow<'a> { let pat_expr_string = match self.cond { Some(cond) => { - let mut cond_shape = match context.config.control_style { + let mut cond_shape = match context.config.control_style() { Style::Default => try_opt!(constr_shape.shrink_left(add_offset)), Style::Rfc => constr_shape, }; - if context.config.control_brace_style != ControlBraceStyle::AlwaysNextLine { + if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { // 2 = " {".len() cond_shape = try_opt!(cond_shape.sub_width(2)); } @@ -897,15 +913,15 @@ impl<'a> Rewrite for ControlFlow<'a> { None => String::new(), }; - let force_newline_brace = context.config.control_style == Style::Rfc && + let force_newline_brace = context.config.control_style() == Style::Rfc && pat_expr_string.contains('\n'); // Try to format if-else on single line. - if self.allow_single_line && context.config.single_line_if_else_max_width > 0 { + if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if trial.is_some() && - trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width { + trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width() { return trial; } } @@ -957,7 +973,7 @@ impl<'a> Rewrite for ControlFlow<'a> { &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" - } else if context.config.control_brace_style == ControlBraceStyle::AlwaysNextLine || + } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine || force_newline_brace { alt_block_sep.as_str() } else { @@ -1035,12 +1051,12 @@ impl<'a> Rewrite for ControlFlow<'a> { else_block.span.lo); let after_else_comment = extract_comment(after_else, context, shape); - let between_sep = match context.config.control_brace_style { + let between_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => &*alt_block_sep, ControlBraceStyle::AlwaysSameLine => " ", }; - let after_sep = match context.config.control_brace_style { + let after_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, _ => " ", }; @@ -1169,14 +1185,14 @@ fn rewrite_match(context: &RewriteContext, let cond_shape = try_opt!(cond_shape.sub_width(2)); let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); - let block_sep = match context.config.control_brace_style { + let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysSameLine => " ", _ => alt_block_sep.as_str(), }; let mut result = format!("match {}{}{{", cond_str, block_sep); - let arm_shape = if context.config.indent_match_arms { - shape.block_indent(context.config.tab_spaces) + let arm_shape = if context.config.indent_match_arms() { + shape.block_indent(context.config.tab_spaces()) } else { shape.block_indent(0) }; @@ -1240,7 +1256,7 @@ fn arm_end_pos(arm: &ast::Arm) -> BytePos { } fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { - if config.match_block_trailing_comma { + if config.match_block_trailing_comma() { "," } else if let ast::ExprKind::Block(ref block) = body.node { if let ast::BlockCheckMode::Default = block.rules { @@ -1322,7 +1338,7 @@ impl Rewrite for ast::Arm { let body = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && - context.config.wrap_match_arms => { + context.config.wrap_match_arms() => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { expr } else { @@ -1355,9 +1371,9 @@ impl Rewrite for ast::Arm { match rewrite { Some(ref body_str) if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) || - !context.config.wrap_match_arms || + !context.config.wrap_match_arms() || is_block => { - let block_sep = match context.config.control_brace_style { + let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), _ => " ", }; @@ -1375,16 +1391,16 @@ impl Rewrite for ast::Arm { // FIXME: we're doing a second rewrite of the expr; This may not be // necessary. - let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces)) - .block_indent(context.config.tab_spaces); + let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces())) + .block_indent(context.config.tab_spaces()); let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape), body_shape.width)); let indent_str = shape .indent .block_indent(context.config) .to_string(context.config); - let (body_prefix, body_suffix) = if context.config.wrap_match_arms { - if context.config.match_block_trailing_comma { + let (body_prefix, body_suffix) = if context.config.wrap_match_arms() { + if context.config.match_block_trailing_comma() { ("{", "},") } else { ("{", "}") @@ -1394,13 +1410,13 @@ impl Rewrite for ast::Arm { }; - let block_sep = match context.config.control_brace_style { + let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n", _ if body_prefix.is_empty() => "\n".to_owned(), _ => " ".to_owned() + body_prefix + "\n", }; - if context.config.wrap_match_arms { + if context.config.wrap_match_arms() { Some(format!("{}{} =>{}{}{}\n{}{}", attr_str.trim_left(), pats_str, @@ -1536,11 +1552,11 @@ fn rewrite_pat_expr(context: &RewriteContext, fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { let string_lit = context.snippet(span); - if !context.config.format_strings && !context.config.force_format_strings { + if !context.config.format_strings() && !context.config.force_format_strings() { return Some(string_lit); } - if !context.config.force_format_strings && + if !context.config.force_format_strings() && !string_requires_rewrite(context, span, &string_lit, shape) { return Some(string_lit); } @@ -1621,7 +1637,7 @@ fn rewrite_call_inner(context: &RewriteContext, .ok_or(Ordering::Greater)?; // 4 = `( )`, 2 = `()` - let paren_overhead = if context.config.spaces_within_parens { + let paren_overhead = if context.config.spaces_within_parens() { 4 } else { 2 @@ -1632,8 +1648,8 @@ fn rewrite_call_inner(context: &RewriteContext, .checked_sub(used_width + paren_overhead) .ok_or(Ordering::Greater)?; - let nested_shape = match context.config.fn_call_style { - IndentStyle::Block => shape.block().block_left(context.config.tab_spaces), + let nested_shape = match context.config.fn_call_style() { + IndentStyle::Block => shape.block().block_left(context.config.tab_spaces()), // 1 = ( IndentStyle::Visual => { shape @@ -1649,9 +1665,9 @@ fn rewrite_call_inner(context: &RewriteContext, let list_str = rewrite_call_args(context, args, span, nested_shape, one_line_width) .ok_or(Ordering::Less)?; - let result = if context.config.fn_call_style == IndentStyle::Visual || + let result = if context.config.fn_call_style() == IndentStyle::Visual || (!list_str.contains('\n') && list_str.chars().last().unwrap_or(' ') != ',') { - if context.config.spaces_within_parens && list_str.len() > 0 { + if context.config.spaces_within_parens() && list_str.len() > 0 { format!("{}( {} )", callee_str, list_str) } else { format!("{}({})", callee_str, list_str) @@ -1723,7 +1739,7 @@ fn rewrite_call_args(context: &RewriteContext, let tactic = definitive_tactic(&item_vec, - ListTactic::LimitedHorizontalVertical(context.config.fn_call_width), + ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()), one_line_width); // Replace the stub with the full overflowing last argument if the rewrite @@ -1742,11 +1758,11 @@ fn rewrite_call_args(context: &RewriteContext, tactic: tactic, separator: ",", trailing_separator: if context.inside_macro || - context.config.fn_call_style == IndentStyle::Visual || + context.config.fn_call_style() == IndentStyle::Visual || arg_count <= 1 { SeparatorTactic::Never } else { - context.config.trailing_comma + context.config.trailing_comma() }, shape: one_line_shape, ends_with_newline: false, @@ -1757,10 +1773,10 @@ fn rewrite_call_args(context: &RewriteContext, // If arguments do not fit in a single line and do not contain newline, // try to put it on the next line. Try this only when we are in block mode // and not rewriting macro. - Some(ref s) if context.config.fn_call_style == IndentStyle::Block && + Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && !context.inside_macro && (!s.contains('\n') && - (s.len() > one_line_width || s.len() > context.config.fn_call_width)) => { + (s.len() > one_line_width || s.len() > context.config.fn_call_width())) => { fmt.trailing_separator = SeparatorTactic::Vertical; write_list(&item_vec, &fmt) } @@ -1776,7 +1792,7 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> let subexpr_str = subexpr.rewrite(context, sub_shape); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - subexpr_str.map(|s| if context.config.spaces_within_parens && s.len() > 0 { + subexpr_str.map(|s| if context.config.spaces_within_parens() && s.len() > 0 { format!("( {} )", s) } else { format!("({})", s) @@ -1790,7 +1806,7 @@ fn rewrite_index(expr: &ast::Expr, -> Option { let expr_str = try_opt!(expr.rewrite(context, shape)); - let (lbr, rbr) = if context.config.spaces_within_square_brackets { + let (lbr, rbr) = if context.config.spaces_within_square_brackets() { ("[ ", " ]") } else { ("[", "]") @@ -1811,7 +1827,7 @@ fn rewrite_index(expr: &ast::Expr, // might be reduced from max_width by something on the right. let budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(indent.len() + lbr.len() + rbr.len())); let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr)) @@ -1887,9 +1903,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); let fields_str = try_opt!(write_list(&item_vec, &fmt)); - let fields_str = if context.config.struct_lit_style == IndentStyle::Block && + let fields_str = if context.config.struct_lit_style() == IndentStyle::Block && (fields_str.contains('\n') || - context.config.struct_lit_multiline_style == MultilineStyle::ForceMulti || + context.config.struct_lit_multiline_style() == + MultilineStyle::ForceMulti || fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) { format!("\n{}{}\n{}", v_shape.indent.to_string(context.config), @@ -1902,13 +1919,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, Some(format!("{} {{{}}}", path_str, fields_str)) - // FIXME if context.config.struct_lit_style == Visual, but we run out + // FIXME if context.config.struct_lit_style() == Visual, but we run out // of space, we should fall back to BlockIndent. } pub fn type_annotation_separator(config: &Config) -> &str { - colon_spaces(config.space_before_type_annotation, - config.space_after_type_annotation_colon) + colon_spaces(config.space_before_type_annotation(), + config.space_after_type_annotation_colon()) } fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { @@ -1964,7 +1981,7 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, .next() .unwrap() .rewrite(context, nested_shape) - .map(|s| if context.config.spaces_within_parens { + .map(|s| if context.config.spaces_within_parens() { format!("( {}, )", s) } else { format!("({},)", s) @@ -1983,7 +2000,7 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, span.hi - BytePos(1)); let list_str = try_opt!(format_item_list(items, nested_shape, context.config)); - if context.config.spaces_within_parens && list_str.len() > 0 { + if context.config.spaces_within_parens() && list_str.len() > 0 { Some(format!("( {} )", list_str)) } else { Some(format!("({})", list_str)) diff --git a/src/filemap.rs b/src/filemap.rs index 27f5b990201..d1486e94e39 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -33,11 +33,11 @@ pub fn append_newline(s: &mut StringBuffer) { pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error> where T: Write { - output_header(out, config.write_mode).ok(); + output_header(out, config.write_mode()).ok(); for &(ref filename, ref text) in file_map { write_file(text, filename, out, config)?; } - output_footer(out, config.write_mode).ok(); + output_footer(out, config.write_mode()).ok(); Ok(()) } @@ -52,14 +52,14 @@ pub fn write_system_newlines(writer: T, // Buffer output, since we're writing a since char at a time. let mut writer = BufWriter::new(writer); - let style = if config.newline_style == NewlineStyle::Native { + let style = if config.newline_style() == NewlineStyle::Native { if cfg!(windows) { NewlineStyle::Windows } else { NewlineStyle::Unix } } else { - config.newline_style + config.newline_style() }; match style { @@ -107,7 +107,7 @@ pub fn write_file(text: &StringBuffer, Ok(make_diff(&ori, &fmt, 3)) } - match config.write_mode { + match config.write_mode() { WriteMode::Replace => { if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { if fmt != ori { diff --git a/src/imports.rs b/src/imports.rs index 50c7b4dc938..46ce14f47b7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -238,7 +238,7 @@ impl<'a> FmtVisitor<'a> { offset.alignment += vis.len() + "use ".len(); // 1 = ";" match vp.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width - offset.width() - 1, offset)) { + Shape::legacy(self.config.max_width() - offset.width() - 1, offset)) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = codemap::mk_sp(self.last_pos, source!(self, span).lo); @@ -339,7 +339,7 @@ pub fn rewrite_use_list(shape: Shape, let has_self = move_self_to_front(&mut items); let first_index = if has_self { 0 } else { 1 }; - if context.config.reorder_imported_names { + if context.config.reorder_imported_names() { items[1..].sort_by(|a, b| a.item.cmp(&b.item)); } diff --git a/src/items.rs b/src/items.rs index 5eb1414c2e0..5fa7a05a142 100644 --- a/src/items.rs +++ b/src/items.rs @@ -94,7 +94,7 @@ struct Item<'a> { impl<'a> Item<'a> { fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { - let abi = if fm.abi == abi::Abi::C && !config.force_explicit_abi { + let abi = if fm.abi == abi::Abi::C && !config.force_explicit_abi() { "extern".into() } else { format!("extern {}", fm.abi) @@ -243,7 +243,7 @@ impl<'a> FmtVisitor<'a> { let block_snippet = self.snippet(codemap::mk_sp(block.span.lo, block.span.hi)); let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || - !context.config.fn_empty_single_line; + !context.config.fn_empty_single_line(); let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, indent, @@ -260,7 +260,7 @@ impl<'a> FmtVisitor<'a> { has_body, true)); - if self.config.fn_brace_style != BraceStyle::AlwaysNextLine && !result.contains('\n') { + if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine && !result.contains('\n') { newline_brace = false; } else if force_newline_brace { newline_brace = true; @@ -319,12 +319,12 @@ impl<'a> FmtVisitor<'a> { let codemap = self.get_context().codemap; - if self.config.fn_empty_single_line && is_empty_block(block, codemap) && - self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width { + if self.config.fn_empty_single_line() && is_empty_block(block, codemap) && + self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { return Some(format!("{}{{}}", fn_str)); } - if self.config.fn_single_line && is_simple_block_stmt(block, codemap) { + if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { let rewrite = { if let Some(ref stmt) = block.stmts.first() { match stmt_expr(stmt) { @@ -348,7 +348,7 @@ impl<'a> FmtVisitor<'a> { if let Some(res) = rewrite { let width = self.block_indent.width() + fn_str.len() + res.len() + 4; - if !res.contains('\n') && width <= self.config.max_width { + if !res.contains('\n') && width <= self.config.max_width() { return Some(format!("{}{{ {} }}", fn_str, res)); } } @@ -372,7 +372,7 @@ impl<'a> FmtVisitor<'a> { generics, "{", "{", - self.config.item_brace_style, + self.config.item_brace_style(), enum_def.variants.is_empty(), self.block_indent, mk_sp(span.lo, body_start)) @@ -436,7 +436,7 @@ impl<'a> FmtVisitor<'a> { let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", - trailing_separator: self.config.trailing_comma, + trailing_separator: self.config.trailing_comma(), shape: shape, ends_with_newline: true, config: self.config, @@ -480,7 +480,7 @@ impl<'a> FmtVisitor<'a> { None, field.span, indent, - Some(self.config.struct_variant_width)) + Some(self.config.struct_variant_width())) } ast::VariantData::Unit(..) => { let tag = if let Some(ref expr) = field.node.disr_expr { @@ -490,7 +490,7 @@ impl<'a> FmtVisitor<'a> { }; wrap_str(tag, - self.config.max_width, + self.config.max_width(), Shape::indented(indent, self.config)) } }; @@ -520,14 +520,14 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - let where_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config.item_brace_style, + context.config.item_brace_style(), Shape::legacy(where_budget, offset.block_only()), - context.config.where_density, + context.config.where_density(), "{", false, last_line_width(&ref_and_type) == 1, @@ -546,13 +546,13 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { result.push('\n'); - let width = offset.block_indent + context.config.tab_spaces - 1; + let width = offset.block_indent + context.config.tab_spaces() - 1; let where_indent = Indent::new(0, width); result.push_str(&where_indent.to_string(context.config)); } result.push_str(&where_clause_str); - match context.config.item_brace_style { + match context.config.item_brace_style() { BraceStyle::AlwaysNextLine => { result.push('\n'); result.push_str(&offset.to_string(context.config)); @@ -615,8 +615,8 @@ fn is_impl_single_line(context: &RewriteContext, let snippet = context.snippet(item.span); let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; - Some(context.config.impl_empty_single_line && items.is_empty() && - result.len() + where_clause_str.len() <= context.config.max_width && + Some(context.config.impl_empty_single_line() && items.is_empty() && + result.len() + where_clause_str.len() <= context.config.max_width() && !contains_comment(&snippet[open_pos..])) } @@ -651,7 +651,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, result.push_str(" "); } let used_space = last_line_width(&result); - let budget = try_opt!(context.config.max_width.checked_sub(used_space)); + let budget = try_opt!(context.config.max_width().checked_sub(used_space)); let indent = offset + used_space; result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent)))); @@ -659,7 +659,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, result.push('\n'); // Add indentation of one additional tab. - let width = offset.block_indent + context.config.tab_spaces; + let width = offset.block_indent + context.config.tab_spaces(); let for_indent = Indent::new(0, width); result.push_str(&for_indent.to_string(context.config)); @@ -673,7 +673,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, if generics.where_clause.predicates.is_empty() { // If there is no where clause adapt budget for type formatting to take space and curly // brace into account. - match context.config.item_brace_style { + match context.config.item_brace_style() { BraceStyle::AlwaysNextLine => {} BraceStyle::PreferSameLine => used_space += 2, BraceStyle::SameLineWhere => used_space += 2, @@ -681,7 +681,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, } // 1 = space before the type. - let budget = try_opt!(context.config.max_width.checked_sub(used_space + 1)); + let budget = try_opt!(context.config.max_width().checked_sub(used_space + 1)); let indent = offset + result.len() + 1; let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent)); if let Some(self_ty_str) = self_ty_str { @@ -759,11 +759,11 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let trait_bound_str = try_opt!(rewrite_trait_bounds(context, type_param_bounds, - Shape::legacy(context.config.max_width, offset))); + Shape::legacy(context.config.max_width(), offset))); // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line if offset.width() + last_line_width(&result) + trait_bound_str.len() > - context.config.comment_width { + context.config.comment_width() { result.push('\n'); let trait_indent = offset.block_only().block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); @@ -773,10 +773,11 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); let where_density = - if (context.config.where_density == Density::Compressed && - (!result.contains('\n') || context.config.fn_args_layout == IndentStyle::Block)) || - (context.config.fn_args_layout == IndentStyle::Block && result.is_empty()) || - (context.config.where_density == Density::CompressedIfEmpty && !has_body && + if (context.config.where_density() == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout() == IndentStyle::Block)) || + (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) || + (context.config.where_density() == Density::CompressedIfEmpty && !has_body && !result.contains('\n')) { Density::Compressed } else { @@ -785,11 +786,11 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let where_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config.item_brace_style, + context.config.item_brace_style(), Shape::legacy(where_budget, offset.block_only()), where_density, @@ -802,15 +803,15 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) // put the where clause on a new line if !where_clause_str.contains('\n') && last_line_width(&result) + where_clause_str.len() + offset.width() > - context.config.comment_width { + context.config.comment_width() { result.push('\n'); - let width = offset.block_indent + context.config.tab_spaces - 1; + let width = offset.block_indent + context.config.tab_spaces() - 1; let where_indent = Indent::new(0, width); result.push_str(&where_indent.to_string(context.config)); } result.push_str(&where_clause_str); - match context.config.item_brace_style { + match context.config.item_brace_style() { BraceStyle::AlwaysNextLine => { result.push('\n'); result.push_str(&offset.to_string(context.config)); @@ -888,13 +889,14 @@ fn format_struct_struct(context: &RewriteContext, g, "{", "{", - context.config.item_brace_style, + context.config.item_brace_style(), fields.is_empty(), offset, mk_sp(span.lo, body_lo))) } None => { - if context.config.item_brace_style == BraceStyle::AlwaysNextLine && !fields.is_empty() { + if context.config.item_brace_style() == BraceStyle::AlwaysNextLine && + !fields.is_empty() { format!("\n{}{{", offset.block_only().to_string(context.config)) } else { " {".to_owned() @@ -923,7 +925,7 @@ fn format_struct_struct(context: &RewriteContext, // 1 = "," let item_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(item_indent.width() + 1)); let items = @@ -944,7 +946,7 @@ fn format_struct_struct(context: &RewriteContext, span.hi) .collect::>(); // 1 = , - let budget = context.config.max_width - offset.width() + context.config.tab_spaces - 1; + let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1; let tactic = match one_line_width { Some(w) => definitive_tactic(&items, ListTactic::LimitedHorizontalVertical(w), budget), @@ -954,7 +956,7 @@ fn format_struct_struct(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: context.config.trailing_comma, + trailing_separator: context.config.trailing_comma(), shape: Shape::legacy(budget, item_indent), ends_with_newline: true, config: context.config, @@ -1003,11 +1005,11 @@ fn format_tuple_struct(context: &RewriteContext, let where_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(last_line_width(&result))); try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config.item_brace_style, + context.config.item_brace_style(), Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", @@ -1032,7 +1034,7 @@ fn format_tuple_struct(context: &RewriteContext, } result.push(')'); } else { - let (tactic, item_indent) = match context.config.fn_args_layout { + let (tactic, item_indent) = match context.config.fn_args_layout() { IndentStyle::Visual => { // 1 = `(` (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) @@ -1044,7 +1046,7 @@ fn format_tuple_struct(context: &RewriteContext, // 3 = `();` let item_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(item_indent.width() + 3)); let items = @@ -1065,7 +1067,7 @@ fn format_tuple_struct(context: &RewriteContext, span.hi); let body_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(offset.block_only().width() + result.len() + 3)); let body = try_opt!(list_helper(items, @@ -1074,15 +1076,15 @@ fn format_tuple_struct(context: &RewriteContext, context.config, tactic)); - if context.config.fn_args_layout == IndentStyle::Visual || !body.contains('\n') { + if context.config.fn_args_layout() == IndentStyle::Visual || !body.contains('\n') { result.push('('); - if context.config.spaces_within_parens && body.len() > 0 { + if context.config.spaces_within_parens() && body.len() > 0 { result.push(' '); } result.push_str(&body); - if context.config.spaces_within_parens && body.len() > 0 { + if context.config.spaces_within_parens() && body.len() > 0 { result.push(' '); } result.push(')'); @@ -1099,11 +1101,11 @@ fn format_tuple_struct(context: &RewriteContext, if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && (result.contains('\n') || offset.block_indent + result.len() + where_clause_str.len() + 1 > - context.config.max_width) { + context.config.max_width()) { // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); - result.push_str(&(offset.block_only() + (context.config.tab_spaces - 1)) + result.push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) .to_string(context.config)); } result.push_str(&where_clause_str); @@ -1135,13 +1137,13 @@ pub fn rewrite_type_alias(context: &RewriteContext, let where_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, - context.config.item_brace_style, + context.config.item_brace_style(), Shape::legacy(where_budget, indent), - context.config.where_density, + context.config.where_density(), "=", true, true, @@ -1154,7 +1156,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, // In that case the budget is set to 0 which will make ty.rewrite retry on a new line let budget = context .config - .max_width + .max_width() .checked_sub(indent.width() + line_width + ";".len()) .unwrap_or(0); let type_indent = indent + line_width; @@ -1170,7 +1172,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str(&type_indent.to_string(context.config)); let budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(type_indent.width() + ";".len())); ty.rewrite(context, Shape::legacy(budget, type_indent)) })); @@ -1180,12 +1182,12 @@ pub fn rewrite_type_alias(context: &RewriteContext, } fn type_annotation_spacing(config: &Config) -> (&str, &str) { - (if config.space_before_type_annotation { + (if config.space_before_type_annotation() { " " } else { "" }, - if config.space_after_type_annotation_colon { + if config.space_after_type_annotation_colon() { " " } else { "" @@ -1196,7 +1198,7 @@ impl Rewrite for ast::StructField { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if contains_skip(&self.attrs) { let span = context.snippet(mk_sp(self.attrs[0].span.lo, self.span.hi)); - return wrap_str(span, context.config.max_width, shape); + return wrap_str(span, context.config.max_width(), shape); } let name = self.ident; @@ -1232,7 +1234,7 @@ impl Rewrite for ast::StructField { match new_ty { Some(ref new_ty) if !new_ty.contains('\n') && new_ty.len() + type_offset.width() <= - context.config.max_width => { + context.config.max_width() => { Some(format!("{}\n{}{}", result, type_offset.to_string(&context.config), @@ -1282,7 +1284,8 @@ pub fn rewrite_static(prefix: &str, type_annotation_spacing.1); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite(context, - Shape::legacy(context.config.max_width - offset.block_indent - + Shape::legacy(context.config.max_width() - + offset.block_indent - prefix.len() - 2, offset.block_only()))); @@ -1290,7 +1293,7 @@ pub fn rewrite_static(prefix: &str, if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; - let remaining_width = context.config.max_width - offset.block_indent - 1; + let remaining_width = context.config.max_width() - offset.block_indent - 1; rewrite_assign_rhs(context, lhs, expr, @@ -1310,31 +1313,32 @@ pub fn rewrite_associated_type(ident: ast::Ident, -> Option { let prefix = format!("type {}", ident); - let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let joiner = match context.config.type_punctuation_density { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let bounds: &[_] = ty_param_bounds; - let bound_str = try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(context.config.max_width, indent)) - }) - .intersperse(Some(joiner.to_string())) - .collect::>()); - if bounds.len() > 0 { - format!(": {}", bound_str) + let type_bounds_str = + if let Some(ty_param_bounds) = ty_param_bounds_opt { + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let bounds: &[_] = ty_param_bounds; + let bound_str = try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(context.config.max_width(), indent)) + }) + .intersperse(Some(joiner.to_string())) + .collect::>()); + if bounds.len() > 0 { + format!(": {}", bound_str) + } else { + String::new() + } } else { String::new() - } - } else { - String::new() - }; + }; if let Some(ty) = ty_opt { let ty_str = try_opt!(ty.rewrite(context, - Shape::legacy(context.config.max_width - + Shape::legacy(context.config.max_width() - indent.block_indent - prefix.len() - 2, @@ -1382,11 +1386,11 @@ impl Rewrite for ast::Arg { Shape::legacy(shape.width, shape.indent))); if self.ty.node != ast::TyKind::Infer { - if context.config.space_before_type_annotation { + if context.config.space_before_type_annotation() { result.push_str(" "); } result.push_str(":"); - if context.config.space_after_type_annotation_colon { + if context.config.space_after_type_annotation_colon() { result.push_str(" "); } let max_width = try_opt!(shape.width.checked_sub(result.len())); @@ -1539,7 +1543,7 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(::utils::format_unsafety(unsafety)); if abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi(abi, context.config.force_explicit_abi)); + result.push_str(&::utils::format_abi(abi, context.config.force_explicit_abi())); } // fn foo @@ -1567,9 +1571,9 @@ fn rewrite_fn_base(context: &RewriteContext, let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = try_opt!(compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace)); - if context.config.fn_args_layout == IndentStyle::Block { + if context.config.fn_args_layout() == IndentStyle::Block { arg_indent = indent.block_indent(context.config); - multi_line_budget = context.config.max_width - arg_indent.width(); + multi_line_budget = context.config.max_width() - arg_indent.width(); } debug!("rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", @@ -1581,12 +1585,12 @@ fn rewrite_fn_base(context: &RewriteContext, if one_line_budget == 0 { if snuggle_angle_bracket { result.push_str("("); - } else if context.config.fn_args_paren_newline { + } else if context.config.fn_args_paren_newline() { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); arg_indent = arg_indent + 1; // extra space for `(` result.push('('); - if context.config.spaces_within_parens && fd.inputs.len() > 0 { + if context.config.spaces_within_parens() && fd.inputs.len() > 0 { result.push(' ') } } else { @@ -1595,7 +1599,7 @@ fn rewrite_fn_base(context: &RewriteContext, } } else { result.push('('); - if context.config.spaces_within_parens && fd.inputs.len() > 0 { + if context.config.spaces_within_parens() && fd.inputs.len() > 0 { result.push(' ') } } @@ -1624,7 +1628,7 @@ fn rewrite_fn_base(context: &RewriteContext, let multi_line_arg_str = arg_str.contains('\n'); - let put_args_in_block = match context.config.fn_args_layout { + let put_args_in_block = match context.config.fn_args_layout() { IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'), _ => false, } && !fd.inputs.is_empty(); @@ -1639,7 +1643,7 @@ fn rewrite_fn_base(context: &RewriteContext, result.push(')'); } else { result.push_str(&arg_str); - if context.config.spaces_within_parens && fd.inputs.len() > 0 { + if context.config.spaces_within_parens() && fd.inputs.len() > 0 { result.push(' ') } result.push(')'); @@ -1647,7 +1651,7 @@ fn rewrite_fn_base(context: &RewriteContext, // Return type. if !ret_str.is_empty() { - let ret_should_indent = match context.config.fn_args_layout { + let ret_should_indent = match context.config.fn_args_layout() { // If our args are block layout then we surely must have space. IndentStyle::Block if put_args_in_block => false, _ => { @@ -1663,13 +1667,13 @@ fn rewrite_fn_base(context: &RewriteContext, sig_length += 2; } - let overlong_sig = sig_length > context.config.max_width; + let overlong_sig = sig_length > context.config.max_width(); result.contains('\n') || multi_line_ret_str || overlong_sig } }; let ret_indent = if ret_should_indent { - let indent = match context.config.fn_return_indent { + let indent = match context.config.fn_return_indent() { ReturnIndent::WithWhereClause => indent + 4, // Aligning with non-existent args looks silly. _ if arg_str.is_empty() => { @@ -1718,7 +1722,7 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let should_compress_where = match context.config.where_density { + let should_compress_where = match context.config.where_density() { Density::Compressed => !result.contains('\n') || put_args_in_block, Density::CompressedIfEmpty => !has_body && !result.contains('\n'), _ => false, @@ -1727,12 +1731,12 @@ fn rewrite_fn_base(context: &RewriteContext, if where_clause.predicates.len() == 1 && should_compress_where { let budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(last_line_width(&result))); if let Some(where_clause_str) = rewrite_where_clause(context, where_clause, - context.config.fn_brace_style, + context.config.fn_brace_style(), Shape::legacy(budget, indent), Density::Compressed, "{", @@ -1740,7 +1744,7 @@ fn rewrite_fn_base(context: &RewriteContext, put_args_in_block && ret_str.is_empty(), Some(span.hi)) { if !where_clause_str.contains('\n') { - if last_line_width(&result) + where_clause_str.len() > context.config.max_width { + if last_line_width(&result) + where_clause_str.len() > context.config.max_width() { result.push('\n'); } @@ -1753,7 +1757,7 @@ fn rewrite_fn_base(context: &RewriteContext, let where_clause_str = try_opt!(rewrite_where_clause(context, where_clause, - context.config.fn_brace_style, + context.config.fn_brace_style(), Shape::indented(indent, context.config), Density::Tall, "{", @@ -1859,7 +1863,7 @@ fn rewrite_args(context: &RewriteContext, item.item = Some(arg); } - let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout { + let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout() { IndentStyle::Block if !generics_str_contains_newline && arg_items.len() <= 1 => { (indent.block_indent(context.config), SeparatorTactic::Never, true) } @@ -1870,7 +1874,7 @@ fn rewrite_args(context: &RewriteContext, }; let tactic = definitive_tactic(&arg_items, - context.config.fn_args_density.to_list_tactic(), + context.config.fn_args_density().to_list_tactic(), one_line_budget); let budget = match tactic { DefinitiveListTactic::Horizontal => one_line_budget, @@ -1919,7 +1923,7 @@ fn compute_budgets_for_args(context: &RewriteContext, } let one_line_budget = context .config - .max_width + .max_width() .checked_sub(used_space) .unwrap_or(0); @@ -1927,7 +1931,7 @@ fn compute_budgets_for_args(context: &RewriteContext, // 4 = "() {".len() let multi_line_budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(indent.width() + result.len() + 4)); @@ -1938,7 +1942,7 @@ fn compute_budgets_for_args(context: &RewriteContext, // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(context.config); let used_space = new_indent.width() + 4; // Account for `(` and `)` and possibly ` {`. - let max_space = context.config.max_width; + let max_space = context.config.max_width(); if used_space <= max_space { Some((0, max_space - used_space, new_indent)) } else { @@ -1948,7 +1952,7 @@ fn compute_budgets_for_args(context: &RewriteContext, } fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { - match config.fn_brace_style { + match config.fn_brace_style() { BraceStyle::AlwaysNextLine => true, BraceStyle::SameLineWhere if !where_clause.predicates.is_empty() => true, _ => false, @@ -1968,7 +1972,7 @@ fn rewrite_generics(context: &RewriteContext, return Some(String::new()); } - let offset = match context.config.generics_indent { + let offset = match context.config.generics_indent() { IndentStyle::Block => shape.indent.block_only().block_indent(context.config), // 1 = < IndentStyle::Visual => shape.indent + 1, @@ -2009,13 +2013,13 @@ fn rewrite_generics(context: &RewriteContext, let list_str = try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); - let result = if context.config.generics_indent != IndentStyle::Visual && + let result = if context.config.generics_indent() != IndentStyle::Visual && list_str.contains('\n') { format!("<\n{}{}\n{}>", offset.to_string(context.config), list_str, shape.indent.block_only().to_string(context.config)) - } else if context.config.spaces_within_angle_brackets { + } else if context.config.spaces_within_angle_brackets() { format!("< {} >", list_str) } else { format!("<{}>", list_str) @@ -2032,7 +2036,7 @@ fn rewrite_trait_bounds(context: &RewriteContext, if bounds.is_empty() { return Some(String::new()); } - let joiner = match context.config.type_punctuation_density { + let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; @@ -2077,7 +2081,7 @@ fn rewrite_where_clause_rfc_style(context: &RewriteContext, "\n".to_owned() + &block_shape.indent.to_string(context.config) }; - let clause_shape = block_shape.block_indent(context.config.tab_spaces); + let clause_shape = block_shape.block_indent(context.config.tab_spaces()); // each clause on one line, trailing comma (except if suppress_comma) let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; // If we don't have the start of the next span, then use the end of the @@ -2129,7 +2133,7 @@ fn rewrite_where_clause(context: &RewriteContext, return Some(String::new()); } - if context.config.where_style == Style::Rfc { + if context.config.where_style() == Style::Rfc { return rewrite_where_clause_rfc_style(context, where_clause, shape, @@ -2139,9 +2143,9 @@ fn rewrite_where_clause(context: &RewriteContext, span_end); } - let extra_indent = Indent::new(context.config.tab_spaces, 0); + let extra_indent = Indent::new(context.config.tab_spaces(), 0); - let offset = match context.config.where_pred_indent { + let offset = match context.config.where_pred_indent() { IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), // 6 = "where ".len() IndentStyle::Visual => shape.indent + extra_indent + 6, @@ -2149,7 +2153,7 @@ fn rewrite_where_clause(context: &RewriteContext, // FIXME: if where_pred_indent != Visual, then the budgets below might // be out by a char or two. - let budget = context.config.max_width - offset.width(); + let budget = context.config.max_width() - offset.width(); let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. @@ -2167,9 +2171,9 @@ fn rewrite_where_clause(context: &RewriteContext, let item_vec = items.collect::>(); // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. - let tactic = definitive_tactic(&item_vec, context.config.where_layout, budget); + let tactic = definitive_tactic(&item_vec, context.config.where_layout(), budget); - let mut comma_tactic = context.config.trailing_comma; + let mut comma_tactic = context.config.trailing_comma(); // Kind of a hack because we don't usually have trailing commas in where clauses. if comma_tactic == SeparatorTactic::Vertical || suppress_comma { comma_tactic = SeparatorTactic::Never; @@ -2227,7 +2231,7 @@ fn format_generics(context: &RewriteContext, if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = try_opt!(context .config - .max_width + .max_width() .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, diff --git a/src/lib.rs b/src/lib.rs index 99054b23712..8c112b5f8af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,12 +145,12 @@ impl Indent { } pub fn block_indent(mut self, config: &Config) -> Indent { - self.block_indent += config.tab_spaces; + self.block_indent += config.tab_spaces(); self } pub fn block_unindent(mut self, config: &Config) -> Indent { - self.block_indent -= config.tab_spaces; + self.block_indent -= config.tab_spaces(); self } @@ -159,8 +159,8 @@ impl Indent { } pub fn to_string(&self, config: &Config) -> String { - let (num_tabs, num_spaces) = if config.hard_tabs { - (self.block_indent / config.tab_spaces, self.alignment) + let (num_tabs, num_spaces) = if config.hard_tabs() { + (self.block_indent / config.tab_spaces(), self.alignment) } else { (0, self.width()) }; @@ -248,7 +248,7 @@ impl Shape { pub fn indented(indent: Indent, config: &Config) -> Shape { Shape { - width: config.max_width.checked_sub(indent.width()).unwrap_or(0), + width: config.max_width().checked_sub(indent.width()).unwrap_or(0), indent: indent, offset: indent.alignment, } @@ -257,7 +257,7 @@ impl Shape { pub fn with_max_width(&self, config: &Config) -> Shape { Shape { width: config - .max_width + .max_width() .checked_sub(self.indent.width()) .unwrap_or(0), ..*self @@ -442,13 +442,13 @@ fn format_ast(krate: &ast::Crate, // We always skip children for the "Plain" write mode, since there is // nothing to distinguish the nested module contents. - let skip_children = config.skip_children || config.write_mode == config::WriteMode::Plain; + let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; for (path, module) in modules::list_files(krate, parse_session.codemap()) { if skip_children && path.as_path() != main_file { continue; } let path = path.to_str().unwrap(); - if config.verbose { + if config.verbose() { println!("Formatting {}", path); } let mut visitor = FmtVisitor::from_codemap(parse_session, config); @@ -473,14 +473,14 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m let mut cur_line = 1; let mut newline_count = 0; let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo, config.report_fixme); + let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); for (c, b) in text.chars() { if c == '\r' { continue; } - let format_line = config.file_lines.contains_line(name, cur_line as usize); + let format_line = config.file_lines().contains_line(name, cur_line as usize); if format_line { // Add warnings for bad todos/ fixmes @@ -501,10 +501,10 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m } // Check for any line width errors we couldn't correct. - if config.error_on_line_overflow && line_len > config.max_width { + if config.error_on_line_overflow() && line_len > config.max_width() { errors.push(FormattingError { line: cur_line, - kind: ErrorKind::LineOverflow(line_len, config.max_width), + kind: ErrorKind::LineOverflow(line_len, config.max_width()), }); } } @@ -577,7 +577,7 @@ pub fn format_input(input: Input, mut out: Option<&mut T>) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { let mut summary = Summary::new(); - if config.disable_all_formatting { + if config.disable_all_formatting() { return Ok((summary, FileMap::new(), FormatReport::new())); } let codemap = Rc::new(CodeMap::new()); @@ -651,10 +651,10 @@ pub enum Input { pub fn run(input: Input, config: &Config) -> Summary { let mut out = &mut stdout(); - output_header(out, config.write_mode).ok(); + output_header(out, config.write_mode()).ok(); match format_input(input, config, Some(out)) { Ok((summary, _, report)) => { - output_footer(out, config.write_mode).ok(); + output_footer(out, config.write_mode()).ok(); if report.has_warnings() { msg!("{}", report); @@ -708,7 +708,9 @@ mod test { #[test] fn indent_to_string_hard_tabs() { let mut config = Config::default(); - config.hard_tabs = true; + config + .override_value("hard_tabs", "true") + .expect("Could not set hard_tabs to true"); let indent = Indent::new(8, 4); // 2 tabs + 4 spaces @@ -719,10 +721,10 @@ mod test { fn shape_visual_indent() { let config = Config::default(); let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width, indent); + let shape = Shape::legacy(config.max_width(), indent); let shape = shape.visual_indent(20); - assert_eq!(config.max_width, shape.width); + assert_eq!(config.max_width(), shape.width); assert_eq!(4, shape.indent.block_indent); assert_eq!(28, shape.indent.alignment); assert_eq!(28, shape.offset); @@ -732,10 +734,10 @@ mod test { fn shape_block_indent_without_alignment() { let config = Config::default(); let indent = Indent::new(4, 0); - let shape = Shape::legacy(config.max_width, indent); + let shape = Shape::legacy(config.max_width(), indent); let shape = shape.block_indent(20); - assert_eq!(config.max_width, shape.width); + assert_eq!(config.max_width(), shape.width); assert_eq!(24, shape.indent.block_indent); assert_eq!(0, shape.indent.alignment); assert_eq!(0, shape.offset); @@ -745,10 +747,10 @@ mod test { fn shape_block_indent_with_alignment() { let config = Config::default(); let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width, indent); + let shape = Shape::legacy(config.max_width(), indent); let shape = shape.block_indent(20); - assert_eq!(config.max_width, shape.width); + assert_eq!(config.max_width(), shape.width); assert_eq!(4, shape.indent.block_indent); assert_eq!(28, shape.indent.alignment); assert_eq!(28, shape.offset); diff --git a/src/lists.rs b/src/lists.rs index 7933ebab807..5e03afff6fd 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -73,7 +73,7 @@ pub fn format_fn_args(items: I, shape: Shape, config: &Config) -> Option(items: I, shape: Shape, config: &Config) -> Option @@ -527,14 +527,14 @@ pub fn struct_lit_shape(shape: Shape, prefix_width: usize, suffix_width: usize) -> Option<(Option, Shape)> { - let v_shape = match context.config.struct_lit_style { + let v_shape = match context.config.struct_lit_style() { IndentStyle::Visual => { try_opt!(try_opt!(shape.shrink_left(prefix_width)).sub_width(suffix_width)) } IndentStyle::Block => { - let shape = shape.block_indent(context.config.tab_spaces); + let shape = shape.block_indent(context.config.tab_spaces()); Shape { - width: try_opt!(context.config.max_width.checked_sub(shape.indent.width())), + width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())), ..shape } } @@ -549,13 +549,14 @@ pub fn struct_lit_tactic(h_shape: Option, items: &[ListItem]) -> DefinitiveListTactic { if let Some(h_shape) = h_shape { - let mut prelim_tactic = match (context.config.struct_lit_style, items.len()) { + let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => context.config.struct_lit_multiline_style.to_list_tactic(), + _ => context.config.struct_lit_multiline_style().to_list_tactic(), }; if prelim_tactic == ListTactic::HorizontalVertical && items.len() > 1 { - prelim_tactic = ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width); + prelim_tactic = + ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width()); } definitive_tactic(items, prelim_tactic, h_shape.width) @@ -583,7 +584,7 @@ pub fn struct_lit_formatting<'a>(shape: Shape, context: &'a RewriteContext, force_no_trailing_comma: bool) -> ListFormatting<'a> { - let ends_with_newline = context.config.struct_lit_style != IndentStyle::Visual && + let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual && tactic == DefinitiveListTactic::Vertical; ListFormatting { tactic: tactic, @@ -591,7 +592,7 @@ pub fn struct_lit_formatting<'a>(shape: Shape, trailing_separator: if force_no_trailing_comma { SeparatorTactic::Never } else { - context.config.trailing_comma + context.config.trailing_comma() }, shape: shape, ends_with_newline: ends_with_newline, diff --git a/src/macros.rs b/src/macros.rs index 8f998e42035..98472d67fa7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -67,7 +67,7 @@ pub fn rewrite_macro(mac: &ast::Mac, -> Option { let mut context = &mut context.clone(); context.inside_macro = true; - if context.config.use_try_shorthand { + if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { return expr.rewrite(context, shape); } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 843556b9b38..40b6bdd8ce9 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -116,7 +116,7 @@ impl<'a> FmtVisitor<'a> { .collect() } - let replaced = match self.config.write_mode { + let replaced = match self.config.write_mode() { WriteMode::Coverage => replace_chars(old_snippet), _ => old_snippet.to_owned(), }; @@ -138,7 +138,7 @@ impl<'a> FmtVisitor<'a> { if rewrite_next_comment && !self.config - .file_lines + .file_lines() .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) { rewrite_next_comment = false; } @@ -154,8 +154,8 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(" "); } - let comment_width = ::std::cmp::min(self.config.comment_width, - self.config.max_width - + let comment_width = ::std::cmp::min(self.config.comment_width(), + self.config.max_width() - self.block_indent.width()); self.buffer @@ -197,7 +197,7 @@ impl<'a> FmtVisitor<'a> { i += offset; if c == '\n' { - if !self.config.file_lines.contains_line(file_name, cur_line) { + if !self.config.file_lines().contains_line(file_name, cur_line) { last_wspace = None; } diff --git a/src/patterns.rs b/src/patterns.rs index 75175cc7667..7dd146efdf9 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -51,7 +51,7 @@ impl Rewrite for Pat { }; let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); - wrap_str(result, context.config.max_width, shape) + wrap_str(result, context.config.max_width(), shape) } PatKind::Wild => { if 1 <= shape.width { @@ -108,19 +108,21 @@ impl Rewrite for Pat { let pats = try_opt!(pats); // Unwrap all the sub-strings and join them with commas. - let result = if context.config.spaces_within_square_brackets { + let result = if context.config.spaces_within_square_brackets() { format!("[ {} ]", pats.join(", ")) } else { format!("[{}]", pats.join(", ")) }; - wrap_str(result, context.config.max_width, shape) + wrap_str(result, context.config.max_width(), shape) } PatKind::Struct(ref path, ref fields, elipses) => { rewrite_struct_pat(path, fields, elipses, self.span, context, shape) } // FIXME(#819) format pattern macros. PatKind::Mac(..) => { - wrap_str(context.snippet(self.span), context.config.max_width, shape) + wrap_str(context.snippet(self.span), + context.config.max_width(), + shape) } } } @@ -187,9 +189,10 @@ fn rewrite_struct_pat(path: &ast::Path, } - let fields_str = if context.config.struct_lit_style == IndentStyle::Block && + let fields_str = if context.config.struct_lit_style() == IndentStyle::Block && (fields_str.contains('\n') || - context.config.struct_lit_multiline_style == MultilineStyle::ForceMulti || + context.config.struct_lit_multiline_style() == + MultilineStyle::ForceMulti || fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) { format!("\n{}{}\n{}", v_shape.indent.to_string(context.config), @@ -210,7 +213,7 @@ impl Rewrite for FieldPat { pat } else { wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)), - context.config.max_width, + context.config.max_width(), shape) } } @@ -296,7 +299,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], // Condense wildcard string suffix into a single .. let wildcard_suffix_len = count_wildcard_suffix_len(&items); - let list = if context.config.condense_wildcard_suffices && wildcard_suffix_len >= 2 { + let list = if context.config.condense_wildcard_suffices() && wildcard_suffix_len >= 2 { let new_item_count = 1 + pats.len() - wildcard_suffix_len; items[new_item_count - 1].item = Some("..".to_owned()); @@ -308,7 +311,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], match path_str { Some(path_str) => { - Some(if context.config.spaces_within_parens { + Some(if context.config.spaces_within_parens() { format!("{}( {} )", path_str, list) } else { format!("{}({})", path_str, list) @@ -316,7 +319,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], } None => { let comma = if add_comma { "," } else { "" }; - Some(if context.config.spaces_within_parens { + Some(if context.config.spaces_within_parens() { format!("( {}{} )", list, comma) } else { format!("({}{})", list, comma) diff --git a/src/string.rs b/src/string.rs index 37a569ce67d..365d205aef1 100644 --- a/src/string.rs +++ b/src/string.rs @@ -119,7 +119,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option } result.push_str(fmt.closer); - wrap_str(result, fmt.config.max_width, fmt.shape) + wrap_str(result, fmt.config.max_width(), fmt.shape) } #[cfg(test)] diff --git a/src/types.rs b/src/types.rs index 754db673013..a0e7246e29d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -53,7 +53,7 @@ pub fn rewrite_path(context: &RewriteContext, if let Some(qself) = qself { result.push('<'); - if context.config.spaces_within_angle_brackets { + if context.config.spaces_within_angle_brackets() { result.push_str(" ") } @@ -79,7 +79,7 @@ pub fn rewrite_path(context: &RewriteContext, shape)); } - if context.config.spaces_within_angle_brackets { + if context.config.spaces_within_angle_brackets() { result.push_str(" ") } @@ -158,7 +158,7 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(binding) => { - let mut result = match context.config.type_punctuation_density { + let mut result = match context.config.type_punctuation_density() { TypeDensity::Wide => format!("{} = ", binding.ident), TypeDensity::Compressed => format!("{}=", binding.ident), }; @@ -237,7 +237,7 @@ fn rewrite_segment(path_context: PathContext, // Update position of last bracket. *span_lo = next_span_lo; - if context.config.spaces_within_angle_brackets && list_str.len() > 0 { + if context.config.spaces_within_angle_brackets() && list_str.len() > 0 { format!("{}< {} >", separator, list_str) } else { format!("{}<{}>", separator, list_str) @@ -338,7 +338,7 @@ fn format_function_type<'a, I>(inputs: I, String::new() }; - Some(if context.config.spaces_within_parens { + Some(if context.config.spaces_within_parens() { format!("( {} ){}{}", list_str, infix, output) } else { format!("({}){}{}", list_str, infix, output) @@ -346,8 +346,8 @@ fn format_function_type<'a, I>(inputs: I, } fn type_bound_colon(context: &RewriteContext) -> &'static str { - colon_spaces(context.config.space_before_bound, - context.config.space_after_bound_colon) + colon_spaces(context.config.space_before_bound(), + context.config.space_after_bound_colon()) } impl Rewrite for ast::WherePredicate { @@ -370,7 +370,7 @@ impl Rewrite for ast::WherePredicate { .intersperse(Some(", ".to_string())) .collect()); - let joiner = match context.config.type_punctuation_density { + let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; @@ -386,7 +386,7 @@ impl Rewrite for ast::WherePredicate { .intersperse(Some(joiner.to_string())) .collect()); - if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { + if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", lifetime_str, type_str, @@ -396,7 +396,7 @@ impl Rewrite for ast::WherePredicate { format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) } } else { - let joiner = match context.config.type_punctuation_density { + let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; @@ -437,7 +437,7 @@ impl Rewrite for ast::WherePredicate { } }; - wrap_str(result, context.config.max_width, shape) + wrap_str(result, context.config.max_width(), shape) } } @@ -464,12 +464,12 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, .map(|b| b.rewrite(context, shape)) .collect()); let colon = type_bound_colon(context); - let joiner = match context.config.type_punctuation_density { + let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; let result = format!("{}{}{}", result, colon, appendix.join(joiner)); - wrap_str(result, context.config.max_width, shape) + wrap_str(result, context.config.max_width(), shape) } } @@ -493,19 +493,19 @@ impl Rewrite for ast::TyParamBound { impl Rewrite for ast::Lifetime { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { wrap_str(pprust::lifetime_to_string(self), - context.config.max_width, + context.config.max_width(), shape) } } impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let joiner = match context.config.type_punctuation_density { + let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect()); - wrap_str(strs.join(joiner), context.config.max_width, shape) + wrap_str(strs.join(joiner), context.config.max_width(), shape) } } @@ -514,14 +514,14 @@ impl Rewrite for ast::TyParam { let mut result = String::with_capacity(128); result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { - if context.config.space_before_bound { + if context.config.space_before_bound() { result.push_str(" "); } result.push_str(":"); - if context.config.space_after_bound_colon { + if context.config.space_after_bound_colon() { result.push_str(" "); } - let joiner = match context.config.type_punctuation_density { + let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; @@ -536,7 +536,7 @@ impl Rewrite for ast::TyParam { } if let Some(ref def) = self.default { - let eq_str = match context.config.type_punctuation_density { + let eq_str = match context.config.type_punctuation_density() { TypeDensity::Compressed => "=", TypeDensity::Wide => " = ", }; @@ -547,7 +547,7 @@ impl Rewrite for ast::TyParam { result.push_str(&rewrite); } - wrap_str(result, context.config.max_width, shape) + wrap_str(result, context.config.max_width(), shape) } } @@ -568,7 +568,7 @@ impl Rewrite for ast::PolyTraitRef { Shape::legacy(max_path_width, shape.indent + extra_offset))); - Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { + Some(if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}", lifetime_str, path_str) } else { format!("for<{}> {}", lifetime_str, path_str) @@ -637,20 +637,20 @@ impl Rewrite for ast::Ty { ast::TyKind::Paren(ref ty) => { let budget = try_opt!(shape.width.checked_sub(2)); ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| if context.config.spaces_within_parens { + .map(|ty_str| if context.config.spaces_within_parens() { format!("( {} )", ty_str) } else { format!("({})", ty_str) }) } ast::TyKind::Slice(ref ty) => { - let budget = if context.config.spaces_within_square_brackets { + let budget = if context.config.spaces_within_square_brackets() { try_opt!(shape.width.checked_sub(4)) } else { try_opt!(shape.width.checked_sub(2)) }; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| if context.config.spaces_within_square_brackets { + .map(|ty_str| if context.config.spaces_within_square_brackets() { format!("[ {} ]", ty_str) } else { format!("[{}]", ty_str) @@ -663,7 +663,7 @@ impl Rewrite for ast::Ty { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } ast::TyKind::Array(ref ty, ref repeats) => { - let use_spaces = context.config.spaces_within_square_brackets; + let use_spaces = context.config.spaces_within_square_brackets(); let lbr = if use_spaces { "[ " } else { "[" }; let rbr = if use_spaces { " ]" } else { "]" }; rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, shape) @@ -715,7 +715,7 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str(::utils::format_unsafety(bare_fn.unsafety)); if bare_fn.abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi(bare_fn.abi, context.config.force_explicit_abi)); + result.push_str(&::utils::format_abi(bare_fn.abi, context.config.force_explicit_abi())); } result.push_str("fn"); diff --git a/src/utils.rs b/src/utils.rs index d7778448b86..059040c70a2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -312,7 +312,7 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option Option { - wrap_str(self, context.config.max_width, shape).map(ToOwned::to_owned) + wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned) } } diff --git a/src/visitor.rs b/src/visitor.rs index 556b9912697..c8d8cf52e7a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -50,7 +50,7 @@ impl<'a> FmtVisitor<'a> { // FIXME(#434): Move this check to somewhere more central, eg Rewrite. if !self.config - .file_lines + .file_lines() .intersects(&self.codemap.lookup_line_range(stmt.span)) { return; } @@ -113,10 +113,10 @@ impl<'a> FmtVisitor<'a> { // level. fn close_block(&mut self) { let total_len = self.buffer.len; - let chars_too_many = if self.config.hard_tabs { + let chars_too_many = if self.config.hard_tabs() { 1 } else { - self.config.tab_spaces + self.config.tab_spaces() }; self.buffer.truncate(total_len - chars_too_many); self.buffer.push_str("}"); @@ -509,7 +509,7 @@ impl<'a> FmtVisitor<'a> { // If the next item is a `use` declaration, then extract it and any subsequent `use`s // to be potentially reordered within `format_imports`. Otherwise, just format the // next item for output. - if self.config.reorder_imports && is_use_item(&*items_left[0]) { + if self.config.reorder_imports() && is_use_item(&*items_left[0]) { let use_item_length = items_left .iter() .take_while(|ppi| is_use_item(&***ppi)) @@ -599,13 +599,13 @@ impl<'a> Rewrite for [ast::Attribute] { let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; let comment = comment.trim(); if !comment.is_empty() { - let comment = try_opt!(rewrite_comment(comment, - false, - Shape::legacy(context.config - .comment_width - - shape.indent.width(), - shape.indent), - context.config)); + let comment = + try_opt!(rewrite_comment(comment, + false, + Shape::legacy(context.config.comment_width() - + shape.indent.width(), + shape.indent), + context.config)); result.push_str(&indent); result.push_str(&comment); result.push('\n'); @@ -618,7 +618,7 @@ impl<'a> Rewrite for [ast::Attribute] { if a_str.starts_with("//") { a_str = try_opt!(rewrite_comment(&a_str, false, - Shape::legacy(context.config.comment_width - + Shape::legacy(context.config.comment_width() - shape.indent.width(), shape.indent), context.config)); diff --git a/tests/system.rs b/tests/system.rs index 48531d321c8..91386a7f768 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -20,7 +20,7 @@ use std::path::{Path, PathBuf}; use rustfmt::*; use rustfmt::filemap::{write_system_newlines, FileMap}; -use rustfmt::config::{Config, ReportTactic}; +use rustfmt::config::Config; use rustfmt::rustfmt_diff::*; const DIFF_CONTEXT_SIZE: usize = 3; @@ -224,12 +224,16 @@ fn read_config(filename: &str) -> Config { for (key, val) in &sig_comments { if key != "target" && key != "config" { - config.override_value(key, val); + config + .override_value(key, val) + .expect(&format!("Failed to override config {} (\"{}\")", key, val)); } } // Don't generate warnings for to-do items. - config.report_todo = ReportTactic::Never; + config + .override_value("report_todo", "Never") + .expect("Could not set report-todo to Never"); config } -- cgit 1.4.1-3-g733a5 From 4d879662a9ef1184fa9f35d43bedd4b451e659c7 Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Tue, 16 May 2017 18:05:40 +0700 Subject: Track which config items are accessed. Required by #865. This doesn't introduce any method to view which parameters are accessed. We record which config items are accessed even if we don't intend to output them, as we assume it will be a relatively cheap operation. --- src/config.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 63c33cdf6fc..44c40f2ac6c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,8 @@ extern crate toml; +use std::cell::RefCell; +use std::collections::HashSet; use std::error; use std::result; @@ -211,10 +213,34 @@ impl ConfigHelpItem { } } +/// This is used by Config to track which config parameters are accessed during +/// formatting. It uses a RefCell for interior mutability, as we don't want to +/// require a mutable reference to Config in order to access configuration. +#[derive(Clone, Default)] +struct ConfigTracker { + set: RefCell>, +} + +impl ConfigTracker { + fn mark_accessed(&self, name: &'static str) { + // We don't ever expect borrowing to fail, as our use of RefCell is very + // simple. + let mut set = self.set.borrow_mut(); + set.insert(name); + } + + fn was_accessed(&self, name: &'static str) -> bool { + self.set.borrow().contains(name) + } +} + macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[derive(Deserialize, Clone)] pub struct Config { + #[serde(skip_deserializing)] + tracker: ConfigTracker, + $($i: $ty),+ } @@ -232,6 +258,7 @@ macro_rules! create_config { $( pub fn $i(&self) -> $ty { + self.tracker.mark_accessed(stringify!($i)); self.$i.clone() } )+ @@ -324,6 +351,7 @@ macro_rules! create_config { impl Default for Config { fn default() -> Config { Config { + tracker: ConfigTracker::default(), $( $i: $def, )+ -- cgit 1.4.1-3-g733a5 From 7a4955f705e123a3008f7d6993b71dc256cdd5b9 Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Tue, 16 May 2017 18:08:24 +0700 Subject: Add methods to serialize Config to TOML. Two different modes: - Serialize the full Config object. This is useful as `Config::default().to_toml()` to output a rustfmt.toml with defaults (#317). - Serialize only the options that have been accessed. This could be useful to output a minimal rustfmt.toml for a project. (If the default value of any unused config item changes, you'll then get the new default when you come to use it). This commit doesn't expose this anywhere - deciding a sensible CLI is a bit trickier. This commit also has very simple error reporting (Result) - once the CLI is decided, a more sensible method of reporting errors might become obvious. --- src/config.rs | 44 ++++++++++++++++++++++++++++++++++++++------ src/file_lines.rs | 10 ++++++++++ src/lists.rs | 4 ++-- src/utils.rs | 23 +++++++++++++++++++++-- 4 files changed, 71 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 44c40f2ac6c..e33c35f1054 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,7 +25,7 @@ macro_rules! configuration_option_enum{ $( $x ),+ } - impl_enum_decodable!($e, $( $x ),+); + impl_enum_serialize_and_deserialize!($e, $( $x ),+); } } @@ -247,10 +247,10 @@ macro_rules! create_config { // Just like the Config struct but with each property wrapped // as Option. This is used to parse a rustfmt.toml that doesn't // specity all properties of `Config`. - // We first parse into `ParsedConfig`, then create a default `Config` - // and overwrite the properties with corresponding values from `ParsedConfig` - #[derive(Deserialize, Clone)] - pub struct ParsedConfig { + // We first parse into `PartialConfig`, then create a default `Config` + // and overwrite the properties with corresponding values from `PartialConfig`. + #[derive(Deserialize, Serialize, Clone)] + struct PartialConfig { $(pub $i: Option<$ty>),+ } @@ -263,7 +263,7 @@ macro_rules! create_config { } )+ - fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config { + fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { self.$i = val; @@ -306,6 +306,38 @@ macro_rules! create_config { } } + pub fn used_to_toml(&self) -> Result { + let mut partial = PartialConfig { + $( + $i: if self.tracker.was_accessed(stringify!($i)) { + Some(self.$i.clone()) + } else { + None + }, + )+ + }; + + // file_lines is special and can't be specified in toml. + partial.file_lines = None; + + toml::to_string(&partial) + .map_err(|e| format!("Could not output config: {}", e.to_string())) + } + + pub fn to_toml(&self) -> Result { + let mut partial = PartialConfig { + $( + $i: Some(self.$i.clone()), + )+ + }; + + // file_lines is special and can't be specified in toml. + partial.file_lines = None; + + toml::to_string(&partial) + .map_err(|e| format!("Could not output config: {}", e.to_string())) + } + pub fn override_value(&mut self, key: &str, val: &str) -> result::Result<(), Box> { diff --git a/src/file_lines.rs b/src/file_lines.rs index a31fe72511c..c6c4cc3e597 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -216,6 +216,16 @@ impl<'de> ::serde::de::Deserialize<'de> for FileLines { } } +// We also want to avoid attempting to serialize a FileLines to toml. The +// `Config` struct should ensure this impl is never reached. +impl ::serde::ser::Serialize for FileLines { + fn serialize(&self, _: S) -> Result + where S: ::serde::ser::Serializer + { + panic!("FileLines cannot be serialized. This is a rustfmt bug."); + } +} + #[cfg(test)] mod test { use super::Range; diff --git a/src/lists.rs b/src/lists.rs index 5e03afff6fd..613f31412e0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -35,7 +35,7 @@ pub enum ListTactic { Mixed, } -impl_enum_decodable!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); +impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum SeparatorTactic { @@ -44,7 +44,7 @@ pub enum SeparatorTactic { Vertical, } -impl_enum_decodable!(SeparatorTactic, Always, Never, Vertical); +impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); impl SeparatorTactic { pub fn from_bool(b: bool) -> SeparatorTactic { diff --git a/src/utils.rs b/src/utils.rs index 059040c70a2..bb9d178b83f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -189,10 +189,29 @@ pub fn trim_newlines(input: &str) -> &str { } } -// Macro for deriving implementations of Decodable for enums +// Macro for deriving implementations of Serialize/Deserialize for enums #[macro_export] -macro_rules! impl_enum_decodable { +macro_rules! impl_enum_serialize_and_deserialize { ( $e:ident, $( $x:ident ),* ) => { + impl ::serde::ser::Serialize for $e { + fn serialize(&self, serializer: S) -> Result + where S: ::serde::ser::Serializer + { + use serde::ser::Error; + + // We don't know whether the user of the macro has given us all options. + #[allow(unreachable_patterns)] + match *self { + $( + $e::$x => serializer.serialize_str(stringify!($x)), + )* + _ => { + Err(S::Error::custom(format!("Cannot serialize {:?}", self))) + } + } + } + } + impl<'de> ::serde::de::Deserialize<'de> for $e { fn deserialize(d: D) -> Result where D: ::serde::Deserializer<'de> { -- cgit 1.4.1-3-g733a5 From feff6248c4130745d3d8ef9fe64c734d28874ac1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 16 May 2017 23:24:00 +0900 Subject: Allow last child in chain to go multiline --- src/chains.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 858103489fd..4ffb297e461 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -174,7 +174,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let almost_total = rewrites[..rewrites.len() - 1] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); - let one_line_len = rewrites.iter().fold(0, |a, r| a + r.len()) + parent_rewrite.len(); + let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + + parent_rewrite.len(); let veto_single_line = if one_line_len > context.config.chain_one_line_max { if rewrites.len() > 1 { -- cgit 1.4.1-3-g733a5 From d7b6f1199f25cde681eaa275290cac91066509a2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 16 May 2017 23:24:38 +0900 Subject: Format source codes --- src/chains.rs | 12 ++- src/expr.rs | 9 +-- src/items.rs | 54 ++++++------- src/lists.rs | 206 +++++++++++++++++++++++++------------------------- src/macros.rs | 16 ++-- src/missed_spans.rs | 13 ++-- src/patterns.rs | 21 +++-- src/types.rs | 37 +++++---- tests/system.rs | 27 +++---- tests/target/tuple.rs | 15 ++-- 10 files changed, 192 insertions(+), 218 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 4ffb297e461..3c5f174a0c2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -249,13 +249,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // True if the chain is only `?`s. fn chain_only_try(exprs: &[ast::Expr]) -> bool { - exprs - .iter() - .all(|e| if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - }) + exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { + true + } else { + false + }) } pub fn rewrite_try(expr: &ast::Expr, diff --git a/src/expr.rs b/src/expr.rs index 7fb71c2e8b4..dfe519782e1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1028,11 +1028,10 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); - let after_else = - mk_sp(context - .codemap - .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), - else_block.span.lo); + let after_else = mk_sp(context.codemap.span_after(mk_sp(self.block.span.hi, + else_block.span.lo), + "else"), + else_block.span.lo); let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style { diff --git a/src/items.rs b/src/items.rs index 5eb1414c2e0..b41b6166eca 100644 --- a/src/items.rs +++ b/src/items.rs @@ -457,11 +457,8 @@ impl<'a> FmtVisitor<'a> { } let indent = self.block_indent; - let mut result = try_opt!(field - .node - .attrs - .rewrite(&self.get_context(), - Shape::indented(indent, self.config))); + let mut result = try_opt!(field.node.attrs.rewrite(&self.get_context(), + Shape::indented(indent, self.config))); if !result.is_empty() { result.push('\n'); result.push_str(&indent.to_string(self.config)); @@ -1201,9 +1198,9 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); - let mut attr_str = - try_opt!(self.attrs - .rewrite(context, Shape::indented(shape.indent, context.config))); + let mut attr_str = try_opt!(self.attrs.rewrite(context, + Shape::indented(shape.indent, + context.config))); if !attr_str.is_empty() { attr_str.push('\n'); attr_str.push_str(&shape.indent.to_string(context.config)); @@ -1223,9 +1220,9 @@ impl Rewrite for ast::StructField { let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); let budget = try_opt!(shape.width.checked_sub(last_line_width)); - let ty_rewritten = self.ty - .rewrite(context, - Shape::legacy(budget, shape.indent + last_line_width)); + let ty_rewritten = + self.ty.rewrite(context, + Shape::legacy(budget, shape.indent + last_line_width)); match ty_rewritten { Some(ref ty) if ty.contains('\n') => { let new_ty = rewrite_type_in_next_line(); @@ -1377,9 +1374,8 @@ impl Rewrite for ast::FunctionRetTy { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!(self.pat - .rewrite(context, - Shape::legacy(shape.width, shape.indent))); + let mut result = try_opt!(self.pat.rewrite(context, + Shape::legacy(shape.width, shape.indent))); if self.ty.node != ast::TyKind::Infer { if context.config.space_before_type_annotation { @@ -1390,10 +1386,9 @@ impl Rewrite for ast::Arg { result.push_str(" "); } let max_width = try_opt!(shape.width.checked_sub(result.len())); - let ty_str = try_opt!(self.ty - .rewrite(context, - Shape::legacy(max_width, - shape.indent + result.len()))); + let ty_str = try_opt!(self.ty.rewrite(context, + Shape::legacy(max_width, + shape.indent + result.len()))); result.push_str(&ty_str); } @@ -1693,9 +1688,8 @@ fn rewrite_fn_base(context: &RewriteContext, if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = try_opt!(fd.output - .rewrite(context, - Shape::indented(ret_indent, context.config))); + let ret_str = try_opt!(fd.output.rewrite(context, + Shape::indented(ret_indent, context.config))); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -1985,16 +1979,14 @@ fn rewrite_generics(context: &RewriteContext, .map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); // Extract comments between generics. - let lt_spans = lifetimes - .iter() - .map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - mk_sp(l.lifetime.span.lo, hi) - }); + let lt_spans = lifetimes.iter().map(|l| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(context.codemap, diff --git a/src/lists.rs b/src/lists.rs index 7933ebab807..c2e98de55ed 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -339,116 +339,114 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> fn next(&mut self) -> Option { let white_space: &[_] = &[' ', '\t']; - self.inner - .next() - .map(|item| { - let mut new_lines = false; - // Pre-comment - let pre_snippet = self.codemap - .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) - .unwrap(); - let trimmed_pre_snippet = pre_snippet.trim(); - let has_pre_comment = trimmed_pre_snippet.contains("//") || - trimmed_pre_snippet.contains("/*"); - let pre_comment = if has_pre_comment { - Some(trimmed_pre_snippet.to_owned()) - } else { - None - }; - - // Post-comment - let next_start = match self.inner.peek() { - Some(next_item) => (self.get_lo)(next_item), - None => self.next_span_start, - }; - let post_snippet = self.codemap - .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let mut block_open_index = post_snippet.find("/*"); - // check if it realy is a block comment (and not //*) - if let Some(i) = block_open_index { - if i > 0 && &post_snippet[i - 1..i] == "/" { - block_open_index = None; - } - } - let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(",").unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => separator_index + 1, - // Block-style post-comment before the separator. - (Some(i), None) => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) - } - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) - } - // Potential *single* line comment. - (_, Some(j)) if j > separator_index => j + 1, - _ => post_snippet.len(), + self.inner.next().map(|item| { + let mut new_lines = false; + // Pre-comment + let pre_snippet = self.codemap + .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) + .unwrap(); + let trimmed_pre_snippet = pre_snippet.trim(); + let has_pre_comment = trimmed_pre_snippet.contains("//") || + trimmed_pre_snippet.contains("/*"); + let pre_comment = if has_pre_comment { + Some(trimmed_pre_snippet.to_owned()) + } else { + None + }; + + // Post-comment + let next_start = match self.inner.peek() { + Some(next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.codemap + .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let mut block_open_index = post_snippet.find("/*"); + // check if it realy is a block comment (and not //*) + if let Some(i) = block_open_index { + if i > 0 && &post_snippet[i - 1..i] == "/" { + block_open_index = None; } } - None => { - post_snippet - .find_uncommented(self.terminator) - .unwrap_or(post_snippet.len()) - } - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet - .find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; + let newline_index = post_snippet.find('\n'); + let separator_index = post_snippet.find_uncommented(",").unwrap(); + + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => separator_index + 1, + // Block-style post-comment before the separator. + (Some(i), None) => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => { + cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1) + } + // Potential *single* line comment. + (_, Some(j)) if j > separator_index => j + 1, + _ => post_snippet.len(), } } - - // Cleanup post-comment: strip separators and whitespace. - self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); - - let post_snippet_trimmed = if post_snippet.starts_with(',') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { + None => { post_snippet - }; - - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; - - ListItem { - pre_comment: pre_comment, - item: (self.get_item_string)(&item), - post_comment: post_comment, - new_lines: new_lines, + .find_uncommented(self.terminator) + .unwrap_or(post_snippet.len()) + } + }; + + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end - 1..]; + let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet + .find(|c: char| !c.is_whitespace()) + .unwrap_or(test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; } - }) + } + + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let post_snippet = post_snippet[..comment_end].trim(); + + let post_snippet_trimmed = if post_snippet.starts_with(',') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.ends_with(',') { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; + + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + }; + + ListItem { + pre_comment: pre_comment, + item: (self.get_item_string)(&item), + post_comment: post_comment, + new_lines: new_lines, + } + }) } } diff --git a/src/macros.rs b/src/macros.rs index 8f998e42035..70924b90d23 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -159,15 +159,13 @@ pub fn rewrite_macro(mac: &ast::Mac, // Format macro invocation as array literal. let extra_offset = macro_name.len(); let shape = try_opt!(shape.shrink_left(extra_offset)); - let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context - .codemap - .span_after(mac.span, - original_style - .opener()), - mac.span.hi - BytePos(1)), - context, - shape)); + let rewrite = + try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mk_sp(context.codemap.span_after(mac.span, + original_style.opener()), + mac.span.hi - BytePos(1)), + context, + shape)); Some(format!("{}{}", macro_name, rewrite)) } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 843556b9b38..e83cc4d462d 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -158,13 +158,12 @@ impl<'a> FmtVisitor<'a> { self.config.max_width - self.block_indent.width()); - self.buffer - .push_str(&rewrite_comment(subslice, - false, - Shape::legacy(comment_width, - self.block_indent), - self.config) - .unwrap()); + self.buffer.push_str(&rewrite_comment(subslice, + false, + Shape::legacy(comment_width, + self.block_indent), + self.config) + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); diff --git a/src/patterns.rs b/src/patterns.rs index 75175cc7667..a1628888622 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -39,11 +39,10 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!(shape - .width - .checked_sub(prefix.len() + mut_infix.len() + - id_str.len() + - 3)); + let width = try_opt!(shape.width.checked_sub(prefix.len() + + mut_infix.len() + + id_str.len() + + 3)); format!(" @ {}", try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) } @@ -328,13 +327,11 @@ fn rewrite_tuple_pat(pats: &[ptr::P], fn count_wildcard_suffix_len(items: &[ListItem]) -> usize { let mut suffix_len = 0; - for item in items - .iter() - .rev() - .take_while(|i| match i.item { - Some(ref internal_string) if internal_string == "_" => true, - _ => false, - }) { + for item in items.iter().rev().take_while(|i| match i.item { + Some(ref internal_string) if internal_string == + "_" => true, + _ => false, + }) { suffix_len += 1; if item.pre_comment.is_some() || item.post_comment.is_some() { diff --git a/src/types.rs b/src/types.rs index 754db673013..5cb0fc3f49d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -163,11 +163,10 @@ impl<'a> Rewrite for SegmentParam<'a> { TypeDensity::Compressed => format!("{}=", binding.ident), }; let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = - try_opt!(binding - .ty - .rewrite(context, - Shape::legacy(budget, shape.indent + result.len()))); + let rewrite = try_opt!(binding.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + + result.len()))); result.push_str(&rewrite); Some(result) } @@ -563,10 +562,10 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref - .rewrite(context, - Shape::legacy(max_path_width, - shape.indent + extra_offset))); + let path_str = try_opt!(self.trait_ref.rewrite(context, + Shape::legacy(max_path_width, + shape.indent + + extra_offset))); Some(if context.config.spaces_within_angle_brackets && lifetime_str.len() > 0 { format!("for< {} > {}", lifetime_str, path_str) @@ -613,22 +612,20 @@ impl Rewrite for ast::Ty { format!("&{} {}{}", lt_str, mut_str, - try_opt!(mt.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + 2 + - mut_len + - lt_len)))) + try_opt!(mt.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + 2 + + mut_len + + lt_len)))) } None => { let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); format!("&{}{}", mut_str, - try_opt!(mt.ty - .rewrite(context, - Shape::legacy(budget, - shape.indent + 1 + - mut_len)))) + try_opt!(mt.ty.rewrite(context, + Shape::legacy(budget, + shape.indent + 1 + + mut_len)))) } }) } diff --git a/tests/system.rs b/tests/system.rs index 48531d321c8..66f7fa19cfb 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -303,21 +303,18 @@ fn read_significant_comments(file_name: &str) -> HashMap { .map(|line| line.expect("Failed getting line")) .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { - regex - .captures_iter(&line) - .next() - .map(|capture| { - (capture - .get(1) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - capture - .get(2) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned()) - }) + regex.captures_iter(&line).next().map(|capture| { + (capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned()) + }) }) .collect() } diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index b7cbf82f411..2d3b52da72a 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -29,14 +29,13 @@ fn b() { } fn issue550() { - self.visitor - .visit_volume(self.level.sector_id(sector), - (floor_y, - if is_sky_flat(ceil_tex) { - from_wad_height(self.height_range.1) - } else { - ceil_y - })); + self.visitor.visit_volume(self.level.sector_id(sector), + (floor_y, + if is_sky_flat(ceil_tex) { + from_wad_height(self.height_range.1) + } else { + ceil_y + })); } fn issue775() { -- cgit 1.4.1-3-g733a5 From cfff3bd91ebe53176c32713be3028f25bf1307cc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 17 May 2017 16:31:09 +0900 Subject: Use multiline when signature does not fit single line --- src/items.rs | 9 +++++++-- tests/source/configs-fn_args_layout-block.rs | 6 ++++++ tests/target/configs-fn_args_layout-block.rs | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index b41b6166eca..118e8f96b96 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1617,7 +1617,8 @@ fn rewrite_fn_base(context: &RewriteContext, fd.variadic, generics_str.contains('\n'))); - let multi_line_arg_str = arg_str.contains('\n'); + let multi_line_arg_str = arg_str.contains('\n') || + arg_str.chars().last().map_or(false, |c| c == ','); let put_args_in_block = match context.config.fn_args_layout { IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'), @@ -1849,12 +1850,16 @@ fn rewrite_args(context: &RewriteContext, arg_items.extend(more_items); } + let fits_in_one_line = !generics_str_contains_newline && + (arg_items.len() == 0 || + arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { item.item = Some(arg); } let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout { - IndentStyle::Block if !generics_str_contains_newline && arg_items.len() <= 1 => { + IndentStyle::Block if fits_in_one_line => { (indent.block_indent(context.config), SeparatorTactic::Never, true) } IndentStyle::Block => { diff --git a/tests/source/configs-fn_args_layout-block.rs b/tests/source/configs-fn_args_layout-block.rs index bb36e9d34c5..eb09b941c33 100644 --- a/tests/source/configs-fn_args_layout-block.rs +++ b/tests/source/configs-fn_args_layout-block.rs @@ -8,3 +8,9 @@ fn lorem(ipsum: usize) {} fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { // body } + +// #1441 +extern "system" { + pub fn GetConsoleHistoryInfo(console_history_info: *mut ConsoleHistoryInfo) -> Boooooooooooooool; +} + diff --git a/tests/target/configs-fn_args_layout-block.rs b/tests/target/configs-fn_args_layout-block.rs index 2eab7d953a5..586d118b210 100644 --- a/tests/target/configs-fn_args_layout-block.rs +++ b/tests/target/configs-fn_args_layout-block.rs @@ -16,3 +16,10 @@ fn lorem( ) { // body } + +// #1441 +extern "system" { + pub fn GetConsoleHistoryInfo( + console_history_info: *mut ConsoleHistoryInfo, + ) -> Boooooooooooooool; +} -- cgit 1.4.1-3-g733a5 From 6098f7f9241035c2c36cc6fd1ab45309d2dc9c2a Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Wed, 17 May 2017 17:14:48 +0700 Subject: Remove ConfigTracker - inline in Config. Use an individual `Cell` on each config item, rather than maintaining a set of config names that were accessed. Add a simple unit test. --- src/config.rs | 66 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index e33c35f1054..9f74f2b69d6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,8 +10,7 @@ extern crate toml; -use std::cell::RefCell; -use std::collections::HashSet; +use std::cell::Cell; use std::error; use std::result; @@ -213,35 +212,13 @@ impl ConfigHelpItem { } } -/// This is used by Config to track which config parameters are accessed during -/// formatting. It uses a RefCell for interior mutability, as we don't want to -/// require a mutable reference to Config in order to access configuration. -#[derive(Clone, Default)] -struct ConfigTracker { - set: RefCell>, -} - -impl ConfigTracker { - fn mark_accessed(&self, name: &'static str) { - // We don't ever expect borrowing to fail, as our use of RefCell is very - // simple. - let mut set = self.set.borrow_mut(); - set.insert(name); - } - - fn was_accessed(&self, name: &'static str) -> bool { - self.set.borrow().contains(name) - } -} - macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => ( - #[derive(Deserialize, Clone)] + #[derive(Clone)] pub struct Config { - #[serde(skip_deserializing)] - tracker: ConfigTracker, - - $($i: $ty),+ + // For each config item, we store a bool indicating whether it has + // been accessed and the value. + $($i: (Cell, $ty)),+ } // Just like the Config struct but with each property wrapped @@ -258,15 +235,15 @@ macro_rules! create_config { $( pub fn $i(&self) -> $ty { - self.tracker.mark_accessed(stringify!($i)); - self.$i.clone() + self.$i.0.set(true); + self.$i.1.clone() } )+ fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { - self.$i = val; + self.$i.1 = val; } )+ self @@ -309,8 +286,8 @@ macro_rules! create_config { pub fn used_to_toml(&self) -> Result { let mut partial = PartialConfig { $( - $i: if self.tracker.was_accessed(stringify!($i)) { - Some(self.$i.clone()) + $i: if self.$i.0.get() { + Some(self.$i.1.clone()) } else { None }, @@ -327,7 +304,7 @@ macro_rules! create_config { pub fn to_toml(&self) -> Result { let mut partial = PartialConfig { $( - $i: Some(self.$i.clone()), + $i: Some(self.$i.1.clone()), )+ }; @@ -343,7 +320,7 @@ macro_rules! create_config { { match key { $( - stringify!($i) => self.$i = val.parse::<$ty>()?, + stringify!($i) => self.$i.1 = val.parse::<$ty>()?, )+ _ => panic!("Unknown config key in override: {}", key) } @@ -383,9 +360,8 @@ macro_rules! create_config { impl Default for Config { fn default() -> Config { Config { - tracker: ConfigTracker::default(), $( - $i: $def, + $i: (Cell::new(false), $def), )+ } } @@ -489,3 +465,19 @@ create_config! { condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns" } + +#[cfg(test)] +mod test { + use super::Config; + + #[test] + fn test_config_tracking() { + let config = Config::default(); + assert!(!config.verbose.0.get()); + config.verbose(); + config.skip_children(); + assert!(config.verbose.0.get()); + assert!(config.skip_children.0.get()); + assert!(!config.disable_all_formatting.0.get()); + } +} -- cgit 1.4.1-3-g733a5 From 9e26575ed8c8fc94278f97f68f478361fee9cc9c Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Wed, 17 May 2017 17:16:35 +0700 Subject: Use unreachable!() instead of panic!(). --- src/file_lines.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index c6c4cc3e597..1e151a57838 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -222,7 +222,7 @@ impl ::serde::ser::Serialize for FileLines { fn serialize(&self, _: S) -> Result where S: ::serde::ser::Serializer { - panic!("FileLines cannot be serialized. This is a rustfmt bug."); + unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); } } -- cgit 1.4.1-3-g733a5 From 222bac139743d63a653a198de287ec6b102270cd Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Thu, 18 May 2017 11:37:29 +0700 Subject: Provide `config.set().item(value)` API. This API isn't fantastic, but it's the best I can come up with without something like `concat_idents!()`. There are relatively few places where config is set, to hopefully the ugliness isn't disastrous. Change previous occurences of `config.item = value` to this new API, rather than using `config.override_value()`. Undo the changes to `override_value()`, as it's no longer important to propogate the error to the caller. Add a test for the new interface. --- src/bin/rustfmt.rs | 56 +++++++++++++++++++++++++++--------------------------- src/comment.rs | 6 ++---- src/config.rs | 40 +++++++++++++++++++++++++++++++++----- src/lib.rs | 4 +--- tests/system.rs | 10 +++------- 5 files changed, 69 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index fac4f9f8714..dc4087a066a 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,12 +18,14 @@ extern crate env_logger; extern crate getopts; use rustfmt::{run, Input, Summary}; -use rustfmt::config::Config; +use rustfmt::file_lines::FileLines; +use rustfmt::config::{Config, WriteMode}; use std::{env, error}; use std::fs::{self, File}; use std::io::{self, ErrorKind, Read, Write}; use std::path::{Path, PathBuf}; +use std::str::FromStr; use getopts::{Matches, Options}; @@ -61,8 +63,8 @@ enum Operation { struct CliOptions { skip_children: bool, verbose: bool, - write_mode: Option, - file_lines: Option, + write_mode: Option, + file_lines: FileLines, // Default is all lines in all files. } impl CliOptions { @@ -71,29 +73,28 @@ impl CliOptions { options.skip_children = matches.opt_present("skip-children"); options.verbose = matches.opt_present("verbose"); - if let Some(write_mode) = matches.opt_str("write-mode") { - options.write_mode = Some(write_mode); + if let Some(ref write_mode) = matches.opt_str("write-mode") { + if let Ok(write_mode) = WriteMode::from_str(write_mode) { + options.write_mode = Some(write_mode); + } else { + return Err(FmtError::from(format!("Invalid write-mode: {}", write_mode))); + } } - if let Some(file_lines) = matches.opt_str("file-lines") { - options.file_lines = Some(file_lines); + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse()?; } Ok(options) } - fn apply_to(&self, config: &mut Config) -> FmtResult<()> { - let bool_to_str = |b| if b { "true" } else { "false" }; - config - .override_value("skip_children", bool_to_str(self.skip_children))?; - config.override_value("verbose", bool_to_str(self.verbose))?; - if let Some(ref write_mode) = self.write_mode { - config.override_value("write_mode", &write_mode)?; + fn apply_to(self, config: &mut Config) { + config.set().skip_children(self.skip_children); + config.set().verbose(self.verbose); + config.set().file_lines(self.file_lines); + if let Some(write_mode) = self.write_mode { + config.set().write_mode(write_mode); } - if let Some(ref file_lines) = self.file_lines { - config.override_value("file_lines", &file_lines)?; - } - Ok(()) } } @@ -221,11 +222,11 @@ fn execute(opts: &Options) -> FmtResult { &env::current_dir().unwrap())?; // write_mode is always Plain for Stdin. - config.override_value("write_mode", "Plain")?; + config.set().write_mode(WriteMode::Plain); // parse file_lines if let Some(ref file_lines) = matches.opt_str("file-lines") { - config.override_value("file-lines", file_lines)?; + config.set().file_lines(file_lines.parse()?); for f in config.file_lines().files() { if f != "stdin" { println!("Warning: Extra file listed in file_lines option '{}'", f); @@ -238,6 +239,12 @@ fn execute(opts: &Options) -> FmtResult { Operation::Format { files, config_path } => { let options = CliOptions::from_matches(&matches)?; + for f in options.file_lines.files() { + if !files.contains(&PathBuf::from(f)) { + println!("Warning: Extra file listed in file_lines option '{}'", f); + } + } + let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -246,13 +253,6 @@ fn execute(opts: &Options) -> FmtResult { config = cfg_tmp; path = path_tmp; }; - options.apply_to(&mut config)?; - - for f in config.file_lines().files() { - if !files.contains(&PathBuf::from(f)) { - println!("Warning: Extra file listed in file_lines option '{}'", f); - } - } if options.verbose { if let Some(path) = path.as_ref() { @@ -282,7 +282,7 @@ fn execute(opts: &Options) -> FmtResult { config = config_tmp; } - options.apply_to(&mut config)?; + options.clone().apply_to(&mut config); error_summary.add(run(Input::File(file), &config)); } } diff --git a/src/comment.rs b/src/comment.rs index ad52ec67f33..22fa241677f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -731,10 +731,8 @@ mod test { #[cfg_attr(rustfmt, rustfmt_skip)] fn format_comments() { let mut config: ::config::Config = Default::default(); - config.override_value("wrap_comments", "true") - .expect("Could not set wrap_comments to true"); - config.override_value("normalize_comments", "true") - .expect("Could not set normalize_comments to true"); + config.set().wrap_comments(true); + config.set().normalize_comments(true); let comment = rewrite_comment(" //test", true, diff --git a/src/config.rs b/src/config.rs index 9f74f2b69d6..d629d4176ca 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,8 +11,6 @@ extern crate toml; use std::cell::Cell; -use std::error; -use std::result; use file_lines::FileLines; use lists::{SeparatorTactic, ListTactic}; @@ -231,6 +229,21 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } + // Macro hygiene won't allow us to make `set_$i()` methods on Config + // for each item, so this struct is used to give the API to set values: + // `config.get().option(false)`. It's pretty ugly. Consider replacing + // with `config.set_option(false)` if we ever get a stable/usable + // `concat_idents!()`. + pub struct ConfigSetter<'a>(&'a mut Config); + + impl<'a> ConfigSetter<'a> { + $( + pub fn $i(&mut self, value: $ty) { + (self.0).$i.1 = value; + } + )+ + } + impl Config { $( @@ -240,6 +253,10 @@ macro_rules! create_config { } )+ + pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { + ConfigSetter(self) + } + fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { @@ -316,15 +333,19 @@ macro_rules! create_config { } pub fn override_value(&mut self, key: &str, val: &str) - -> result::Result<(), Box> { match key { $( - stringify!($i) => self.$i.1 = val.parse::<$ty>()?, + stringify!($i) => { + self.$i.1 = val.parse::<$ty>() + .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", + stringify!($i), + val, + stringify!($ty))); + } )+ _ => panic!("Unknown config key in override: {}", key) } - Ok(()) } pub fn print_docs() { @@ -480,4 +501,13 @@ mod test { assert!(config.skip_children.0.get()); assert!(!config.disable_all_formatting.0.get()); } + + #[test] + fn test_config_set() { + let mut config = Config::default(); + config.set().verbose(false); + assert_eq!(config.verbose(), false); + config.set().verbose(true); + assert_eq!(config.verbose(), true); + } } diff --git a/src/lib.rs b/src/lib.rs index 8c112b5f8af..f31f3c0c3ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -708,9 +708,7 @@ mod test { #[test] fn indent_to_string_hard_tabs() { let mut config = Config::default(); - config - .override_value("hard_tabs", "true") - .expect("Could not set hard_tabs to true"); + config.set().hard_tabs(true); let indent = Indent::new(8, 4); // 2 tabs + 4 spaces diff --git a/tests/system.rs b/tests/system.rs index 91386a7f768..de4b1c46267 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -20,7 +20,7 @@ use std::path::{Path, PathBuf}; use rustfmt::*; use rustfmt::filemap::{write_system_newlines, FileMap}; -use rustfmt::config::Config; +use rustfmt::config::{Config, ReportTactic}; use rustfmt::rustfmt_diff::*; const DIFF_CONTEXT_SIZE: usize = 3; @@ -224,16 +224,12 @@ fn read_config(filename: &str) -> Config { for (key, val) in &sig_comments { if key != "target" && key != "config" { - config - .override_value(key, val) - .expect(&format!("Failed to override config {} (\"{}\")", key, val)); + config.override_value(key, val); } } // Don't generate warnings for to-do items. - config - .override_value("report_todo", "Never") - .expect("Could not set report-todo to Never"); + config.set().report_todo(ReportTactic::Never); config } -- cgit 1.4.1-3-g733a5 From 3f34ff82297a4f1d5f4052fff5ff44bd28504a3e Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Thu, 18 May 2017 12:09:14 +0700 Subject: Return `PartialConfig` from `Config` methods. Leave serialization to the caller, but provide a `PartialConfig.to_toml()` method, to deal with the fact that `file_lines` can't be serialized. Add a simple test. --- src/config.rs | 61 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index d629d4176ca..2d3077ed43d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -225,10 +225,21 @@ macro_rules! create_config { // We first parse into `PartialConfig`, then create a default `Config` // and overwrite the properties with corresponding values from `PartialConfig`. #[derive(Deserialize, Serialize, Clone)] - struct PartialConfig { + pub struct PartialConfig { $(pub $i: Option<$ty>),+ } + impl PartialConfig { + pub fn to_toml(&self) -> Result { + // file_lines can't be specified in TOML + let mut cloned = self.clone(); + cloned.file_lines = None; + + toml::to_string(&cloned) + .map_err(|e| format!("Could not output config: {}", e.to_string())) + } + } + // Macro hygiene won't allow us to make `set_$i()` methods on Config // for each item, so this struct is used to give the API to set values: // `config.get().option(false)`. It's pretty ugly. Consider replacing @@ -300,8 +311,8 @@ macro_rules! create_config { } } - pub fn used_to_toml(&self) -> Result { - let mut partial = PartialConfig { + pub fn used_options(&self) -> PartialConfig { + PartialConfig { $( $i: if self.$i.0.get() { Some(self.$i.1.clone()) @@ -309,27 +320,15 @@ macro_rules! create_config { None }, )+ - }; - - // file_lines is special and can't be specified in toml. - partial.file_lines = None; - - toml::to_string(&partial) - .map_err(|e| format!("Could not output config: {}", e.to_string())) + } } - pub fn to_toml(&self) -> Result { - let mut partial = PartialConfig { + pub fn all_options(&self) -> PartialConfig { + PartialConfig { $( $i: Some(self.$i.1.clone()), )+ - }; - - // file_lines is special and can't be specified in toml. - partial.file_lines = None; - - toml::to_string(&partial) - .map_err(|e| format!("Could not output config: {}", e.to_string())) + } } pub fn override_value(&mut self, key: &str, val: &str) @@ -491,17 +490,6 @@ create_config! { mod test { use super::Config; - #[test] - fn test_config_tracking() { - let config = Config::default(); - assert!(!config.verbose.0.get()); - config.verbose(); - config.skip_children(); - assert!(config.verbose.0.get()); - assert!(config.skip_children.0.get()); - assert!(!config.disable_all_formatting.0.get()); - } - #[test] fn test_config_set() { let mut config = Config::default(); @@ -510,4 +498,17 @@ mod test { config.set().verbose(true); assert_eq!(config.verbose(), true); } + + #[test] + fn test_config_used_to_toml() { + let config = Config::default(); + + let verbose = config.verbose(); + let skip_children = config.skip_children(); + + let used_options = config.used_options(); + let toml = used_options.to_toml().unwrap(); + assert_eq!(toml, + format!("verbose = {}\nskip_children = {}\n", verbose, skip_children)); + } } -- cgit 1.4.1-3-g733a5 From 1077a100a16e1ce6e33db6ca42c3f93b2ab9620f Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Wed, 17 May 2017 18:32:18 +0800 Subject: reorder imports in group --- Configurations.md | 37 +++++++++++++++++++++- src/config.rs | 1 + src/visitor.rs | 28 +++++++++++++++- .../configs-reorder_imports_in_group-false.rs | 13 ++++++++ .../configs-reorder_imports_in_group-true.rs | 13 ++++++++ .../configs-reorder_imports_in_group-false.rs | 13 ++++++++ .../configs-reorder_imports_in_group-true.rs | 13 ++++++++ 7 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 tests/source/configs-reorder_imports_in_group-false.rs create mode 100644 tests/source/configs-reorder_imports_in_group-true.rs create mode 100644 tests/target/configs-reorder_imports_in_group-false.rs create mode 100644 tests/target/configs-reorder_imports_in_group-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index d415047f7eb..1811c3aa5c6 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1007,7 +1007,42 @@ use lorem; use sit; ``` -See also [`reorder_imported_names`](#reorder_imported_names). +See also [`reorder_imported_names`](#reorder_imported_names), [`reorder_imports_in_group`](#reorder_imports_in_group). + +## `reorder_imports_in_group` + +Reorder import statements in group + +- **Default value**: `false` +- **Possible values**: `true`, `false` + +**Note:** This option takes effect only when [`reorder_imports`](#reorder_imports) is set to `true`. + +#### `false`: + +```rust +use std::mem; +use std::io; + +use lorem; +use ipsum; +use dolor; +use sit; +``` + +#### `true`: + +```rust +use std::io; +use std::mem; + +use dolor; +use ipsum; +use lorem; +use sit; +``` + +See also [`reorder_imports`](#reorder_imports). ## `single_line_if_else_max_width` diff --git a/src/config.rs b/src/config.rs index 632170e6812..e8ecfa0f8e5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -387,6 +387,7 @@ create_config! { chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain"; chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line"; reorder_imports: bool, false, "Reorder import statements alphabetically"; + reorder_imports_in_group: bool, false, "Reorder import statements in group"; reorder_imported_names: bool, false, "Reorder lists of names in import statements alphabetically"; single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ diff --git a/src/visitor.rs b/src/visitor.rs index 556b9912697..2321eee272a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp; + use syntax::{ast, ptr, visit}; use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::parse::ParseSess; @@ -31,6 +33,19 @@ fn is_use_item(item: &ast::Item) -> bool { } } +fn item_bound(item: &ast::Item) -> Span { + item.attrs + .iter() + .map(|attr| attr.span) + .fold(item.span, |bound, span| { + Span { + lo: cmp::min(bound.lo, span.lo), + hi: cmp::max(bound.hi, span.hi), + expn_id: span.expn_id, + } + }) +} + pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, @@ -510,9 +525,20 @@ impl<'a> FmtVisitor<'a> { // to be potentially reordered within `format_imports`. Otherwise, just format the // next item for output. if self.config.reorder_imports && is_use_item(&*items_left[0]) { + let reorder_imports_in_group = self.config.reorder_imports_in_group; + let mut last = self.codemap.lookup_line_range(item_bound(&items_left[0])); let use_item_length = items_left .iter() - .take_while(|ppi| is_use_item(&***ppi)) + .take_while(|ppi| { + is_use_item(&***ppi) && + (!reorder_imports_in_group || + { + let current = self.codemap.lookup_line_range(item_bound(&ppi)); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) + }) .count(); let (use_items, rest) = items_left.split_at(use_item_length); self.format_imports(use_items); diff --git a/tests/source/configs-reorder_imports_in_group-false.rs b/tests/source/configs-reorder_imports_in_group-false.rs new file mode 100644 index 00000000000..87711bb142b --- /dev/null +++ b/tests/source/configs-reorder_imports_in_group-false.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: false +// Reorder imports in group + +/// This comment should stay with `use std::mem;` +use std::mem; +use std::io; + +use lorem; +/// This comment should stay with `use ipsum;` +use ipsum; +use dolor; +use sit; diff --git a/tests/source/configs-reorder_imports_in_group-true.rs b/tests/source/configs-reorder_imports_in_group-true.rs new file mode 100644 index 00000000000..b5690b89cc0 --- /dev/null +++ b/tests/source/configs-reorder_imports_in_group-true.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: true +// Reorder imports in group + +/// This comment should stay with `use std::mem;` +use std::mem; +use std::io; + +use lorem; +/// This comment should stay with `use ipsum;` +use ipsum; +use dolor; +use sit; diff --git a/tests/target/configs-reorder_imports_in_group-false.rs b/tests/target/configs-reorder_imports_in_group-false.rs new file mode 100644 index 00000000000..42778d91dd8 --- /dev/null +++ b/tests/target/configs-reorder_imports_in_group-false.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: false +// Reorder imports in group + +use dolor; +/// This comment should stay with `use ipsum;` +use ipsum; + +use lorem; +use sit; +use std::io; +/// This comment should stay with `use std::mem;` +use std::mem; diff --git a/tests/target/configs-reorder_imports_in_group-true.rs b/tests/target/configs-reorder_imports_in_group-true.rs new file mode 100644 index 00000000000..c5e353662b5 --- /dev/null +++ b/tests/target/configs-reorder_imports_in_group-true.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: true +// Reorder imports in group + +use std::io; +/// This comment should stay with `use std::mem;` +use std::mem; + +use dolor; +/// This comment should stay with `use ipsum;` +use ipsum; +use lorem; +use sit; -- cgit 1.4.1-3-g733a5 From 31c8fb4e7663687d2822c5e6d41c47f1143aef0f Mon Sep 17 00:00:00 2001 From: Michael Killough Date: Thu, 18 May 2017 12:56:49 +0700 Subject: Add --dump-default-config and --dump-minimal-config. - `--dump-default-config` outputs the default configuration to the specified file as TOML and then exits. - `--dump-minimal-config` is checked after formatting files as normal. If present, any configuration options that were checked during formatting are written to the specified file as TOML. - These options were added only to `rustfmt`, not to `cargo fmt`. They can be specified when using `cargo fmt` by placing them after `--`. - It would have been nice if the filename was optional, so you could run just `rusfmt --dump-minimal-config build.rs` to have it output to `rustfmt.toml`. However, this doesn't do what you might expect: it outputs the config to `build.rs`! --- src/bin/rustfmt.rs | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index dc4087a066a..73c4439ba29 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -44,6 +44,7 @@ enum Operation { Format { files: Vec, config_path: Option, + minimal_config_path: Option, }, /// Print the help message. Help, @@ -51,6 +52,8 @@ enum Operation { Version, /// Print detailed configuration help. ConfigHelp, + /// Output default config to a file + ConfigOutputDefault { path: String }, /// No file specified, read from stdin Stdin { input: String, @@ -186,6 +189,14 @@ fn make_opts() -> Options { opts.optflag("", "config-help", "show details of rustfmt configuration options"); + opts.optopt("", + "dump-default-config", + "Dumps the default configuration to a file and exits.", + "PATH"); + opts.optopt("", + "dump-minimal-config", + "Dumps configuration options that were checked during formatting to a file.", + "PATH"); opts.optopt("", "config-path", "Recursively searches the given path for the rustfmt.toml config file. If not \ @@ -216,6 +227,12 @@ fn execute(opts: &Options) -> FmtResult { Config::print_docs(); Ok(Summary::new()) } + Operation::ConfigOutputDefault { path } => { + let mut file = File::create(path)?; + let toml = Config::default().all_options().to_toml()?; + file.write_all(toml.as_bytes())?; + Ok(Summary::new()) + } Operation::Stdin { input, config_path } => { // try to read config from local directory let (mut config, _) = match_cli_path_or_file(config_path, @@ -236,7 +253,11 @@ fn execute(opts: &Options) -> FmtResult { Ok(run(Input::Text(input), &config)) } - Operation::Format { files, config_path } => { + Operation::Format { + files, + config_path, + minimal_config_path, + } => { let options = CliOptions::from_matches(&matches)?; for f in options.file_lines.files() { @@ -286,6 +307,15 @@ fn execute(opts: &Options) -> FmtResult { error_summary.add(run(Input::File(file), &config)); } } + + // If we were given a path via dump-minimal-config, output any options + // that were used during formatting as TOML. + if let Some(path) = minimal_config_path { + let mut file = File::create(path)?; + let toml = config.used_options().to_toml()?; + file.write_all(toml.as_bytes())?; + } + Ok(error_summary) } } @@ -353,6 +383,10 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::ConfigHelp); } + if let Some(path) = matches.opt_str("dump-default-config") { + return Ok(Operation::ConfigOutputDefault { path }); + } + if matches.opt_present("version") { return Ok(Operation::Version); } @@ -383,6 +417,9 @@ fn determine_operation(matches: &Matches) -> FmtResult { path @ _ => path, }; + // If no path is given, we won't output a minimal config. + let minimal_config_path = matches.opt_str("dump-minimal-config"); + // if no file argument is supplied, read from stdin if matches.free.is_empty() { let mut buffer = String::new(); @@ -408,5 +445,6 @@ fn determine_operation(matches: &Matches) -> FmtResult { Ok(Operation::Format { files: files, config_path: config_path, + minimal_config_path: minimal_config_path, }) } -- cgit 1.4.1-3-g733a5 From 8ca699ce26bab2ec9a2ce5f8ab31581c6deb12bc Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 18 May 2017 08:03:47 -0400 Subject: config: fix `suffices` -> `suffixes` typo Fixes #1477. --- Configurations.md | 2 +- src/config.rs | 2 +- src/patterns.rs | 2 +- tests/source/configs-condense_wildcard_suffices-false.rs | 4 ++-- tests/source/configs-condense_wildcard_suffices-true.rs | 4 ++-- tests/source/pattern-condense-wildcards.rs | 2 +- tests/target/configs-condense_wildcard_suffices-false.rs | 4 ++-- tests/target/configs-condense_wildcard_suffices-true.rs | 4 ++-- tests/target/pattern-condense-wildcards.rs | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 1811c3aa5c6..1d8774b6c55 100644 --- a/Configurations.md +++ b/Configurations.md @@ -166,7 +166,7 @@ Maximum length of comments. No effect unless`wrap_comments = true`. See also [`wrap_comments`](#wrap_comments). -## `condense_wildcard_suffices` +## `condense_wildcard_suffixes` Replace strings of _ wildcards by a single .. in tuple patterns diff --git a/src/config.rs b/src/config.rs index e8ecfa0f8e5..fa12f16a3dd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -421,6 +421,6 @@ create_config! { use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; - condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in \ + condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns" } diff --git a/src/patterns.rs b/src/patterns.rs index a1628888622..2b65604e6a8 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -295,7 +295,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], // Condense wildcard string suffix into a single .. let wildcard_suffix_len = count_wildcard_suffix_len(&items); - let list = if context.config.condense_wildcard_suffices && wildcard_suffix_len >= 2 { + let list = if context.config.condense_wildcard_suffixes && wildcard_suffix_len >= 2 { let new_item_count = 1 + pats.len() - wildcard_suffix_len; items[new_item_count - 1].item = Some("..".to_owned()); diff --git a/tests/source/configs-condense_wildcard_suffices-false.rs b/tests/source/configs-condense_wildcard_suffices-false.rs index e4ad1f2f3cc..3b967f35a8e 100644 --- a/tests/source/configs-condense_wildcard_suffices-false.rs +++ b/tests/source/configs-condense_wildcard_suffices-false.rs @@ -1,5 +1,5 @@ -// rustfmt-condense_wildcard_suffices: false -// Condense wildcard suffices +// rustfmt-condense_wildcard_suffixes: false +// Condense wildcard suffixes fn main() { let (lorem, ipsum, _, _) = (1, 2, 3, 4); diff --git a/tests/source/configs-condense_wildcard_suffices-true.rs b/tests/source/configs-condense_wildcard_suffices-true.rs index 2c8457a88d3..3798a6b9902 100644 --- a/tests/source/configs-condense_wildcard_suffices-true.rs +++ b/tests/source/configs-condense_wildcard_suffices-true.rs @@ -1,5 +1,5 @@ -// rustfmt-condense_wildcard_suffices: true -// Condense wildcard suffices +// rustfmt-condense_wildcard_suffixes: true +// Condense wildcard suffixes fn main() { let (lorem, ipsum, _, _) = (1, 2, 3, 4); diff --git a/tests/source/pattern-condense-wildcards.rs b/tests/source/pattern-condense-wildcards.rs index 5f84aea0a6b..244e935639a 100644 --- a/tests/source/pattern-condense-wildcards.rs +++ b/tests/source/pattern-condense-wildcards.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-condense_wildcard_suffices: true +// rustfmt-condense_wildcard_suffixes: true fn main() { match x { diff --git a/tests/target/configs-condense_wildcard_suffices-false.rs b/tests/target/configs-condense_wildcard_suffices-false.rs index e4ad1f2f3cc..3b967f35a8e 100644 --- a/tests/target/configs-condense_wildcard_suffices-false.rs +++ b/tests/target/configs-condense_wildcard_suffices-false.rs @@ -1,5 +1,5 @@ -// rustfmt-condense_wildcard_suffices: false -// Condense wildcard suffices +// rustfmt-condense_wildcard_suffixes: false +// Condense wildcard suffixes fn main() { let (lorem, ipsum, _, _) = (1, 2, 3, 4); diff --git a/tests/target/configs-condense_wildcard_suffices-true.rs b/tests/target/configs-condense_wildcard_suffices-true.rs index 03bd0c4c6c8..4f880abe80e 100644 --- a/tests/target/configs-condense_wildcard_suffices-true.rs +++ b/tests/target/configs-condense_wildcard_suffices-true.rs @@ -1,5 +1,5 @@ -// rustfmt-condense_wildcard_suffices: true -// Condense wildcard suffices +// rustfmt-condense_wildcard_suffixes: true +// Condense wildcard suffixes fn main() { let (lorem, ipsum, ..) = (1, 2, 3, 4); diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs index ebf89c582ff..acc41b73e18 100644 --- a/tests/target/pattern-condense-wildcards.rs +++ b/tests/target/pattern-condense-wildcards.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-condense_wildcard_suffices: true +// rustfmt-condense_wildcard_suffixes: true fn main() { match x { -- cgit 1.4.1-3-g733a5 From d16a0a399e76b916cdde12c50a733d8eb59a31ef Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 19 May 2017 19:25:53 +0900 Subject: Implement 'vec![expr; expr]' --- src/macros.rs | 67 ++++++++++++++++++++++++++++++++++++++++---------- tests/source/macros.rs | 7 ++++++ tests/target/macros.rs | 7 ++++++ tests/target/match.rs | 16 ++++++------ 4 files changed, 76 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b5644fb014c..352c39f317c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,7 +29,7 @@ use syntax::util::ThinVec; use Shape; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; -use expr::{rewrite_call, rewrite_array}; +use expr::{rewrite_call, rewrite_array, rewrite_pair}; use comment::{FindUncommented, contains_comment}; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; @@ -105,6 +105,7 @@ pub fn rewrite_macro(mac: &ast::Mac, let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); let mut expr_vec = Vec::new(); + let mut vec_with_semi = false; if MacroStyle::Braces != style { loop { @@ -128,6 +129,29 @@ pub fn rewrite_macro(mac: &ast::Mac, match parser.token { Token::Eof => break, Token::Comma => (), + Token::Semi => { + // Try to parse `vec![expr; expr]` + if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + parser.bump(); + if parser.token != Token::Eof { + match parser.parse_expr() { + Ok(expr) => { + if context.parse_session.span_diagnostic.has_errors() { + return None; + } + expr_vec.push(expr); + parser.bump(); + if parser.token == Token::Eof && expr_vec.len() == 2 { + vec_with_semi = true; + break; + } + } + Err(mut e) => e.cancel(), + } + } + } + return None; + } _ => return None, } @@ -156,18 +180,35 @@ pub fn rewrite_macro(mac: &ast::Mac, }) } MacroStyle::Brackets => { - // Format macro invocation as array literal. - let extra_offset = macro_name.len(); - let shape = try_opt!(shape.shrink_left(extra_offset)); - let rewrite = - try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context.codemap.span_after(mac.span, - original_style.opener()), - mac.span.hi - BytePos(1)), - context, - shape)); - - Some(format!("{}{}", macro_name, rewrite)) + let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); + // Handle special case: `vec![expr; expr]` + if vec_with_semi { + let (lbr, rbr) = if context.config.spaces_within_square_brackets { + ("[ ", " ]") + } else { + ("[", "]") + }; + rewrite_pair(&*expr_vec[0], + &*expr_vec[1], + lbr, + "; ", + rbr, + context, + mac_shape) + .map(|s| format!("{}{}", macro_name, s)) + } else { + // Format macro invocation as array literal. + let rewrite = + try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mk_sp(context.codemap.span_after(mac.span, + original_style + .opener()), + mac.span.hi - BytePos(1)), + context, + mac_shape)); + + Some(format!("{}{}", macro_name, rewrite)) + } } MacroStyle::Braces => { // Skip macro invocations with braces, for now. diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 3eee8c543ba..afaf67359ed 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -34,6 +34,13 @@ fn main() { a, ]; + vec![a; b]; + vec!(a; b); + vec!{a; b}; + + vec![a, b; c]; + vec![a; b, c]; + unknown_bracket_macro__comma_should_not_be_stripped![ a, ]; diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 1fd8130f824..2f65b4e4f6e 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -38,6 +38,13 @@ fn main() { // Trailing spaces after a comma vec![a]; + vec![a; b]; + vec![a; b]; + vec![a; b]; + + vec![a, b; c]; + vec![a; b, c]; + unknown_bracket_macro__comma_should_not_be_stripped![ a, ]; diff --git a/tests/target/match.rs b/tests/target/match.rs index 15b7889e476..09df7ebd55f 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -158,19 +158,19 @@ fn issue355() { match mac { a => println!("a", b), b => vec![1, 2], - c => vec!(3; 4), + c => vec![3; 4], d => println!("a", b), e => vec![1, 2], - f => vec!(3; 4), + f => vec![3; 4], h => println!("a", b), // h comment i => vec![1, 2], // i comment - j => vec!(3; 4), // j comment + j => vec![3; 4], // j comment // k comment k => println!("a", b), // l comment l => vec![1, 2], // m comment - m => vec!(3; 4), + m => vec![3; 4], // Rewrite splits macro nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { println!("a", b) @@ -182,7 +182,7 @@ fn issue355() { // Macro support fails to recognise this macro as splitable // We push the whole expr to a new line, TODO split this macro as well pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { - vec!(3; 4) + vec![3; 4] } // q, r and s: Rewrite splits match arm qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { @@ -192,19 +192,19 @@ fn issue355() { vec![1, 2] } ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { - vec!(3; 4) + vec![3; 4] } // Funky bracketing styles t => println!{"a", b}, u => vec![1, 2], - v => vec!{3; 4}, + v => vec![3; 4], w => println!["a", b], x => vec![1, 2], y => vec![3; 4], // Brackets with comments tc => println!{"a", b}, // comment uc => vec![1, 2], // comment - vc => vec!{3; 4}, // comment + vc => vec![3; 4], // comment wc => println!["a", b], // comment xc => vec![1, 2], // comment yc => vec![3; 4], // comment -- cgit 1.4.1-3-g733a5 From 13af774e5596fc1e3ff5097efad74c8988b1282d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 19 May 2017 19:28:00 +0900 Subject: Fix weird indentaion in chain --- src/chains.rs | 18 +++++------------ src/macros.rs | 2 +- tests/source/configs-fn_call_style-block.rs | 30 +++++++++++++++++++++++++++++ tests/target/configs-fn_call_style-block.rs | 30 +++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 209c0eb1382..5da00d29330 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -126,9 +126,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // brace. (parent_shape, false) } else if parent_rewrite_contains_newline { - (chain_indent(context, - parent_shape.block_indent(context.config.tab_spaces())), - false) + (chain_indent(context, parent_shape), false) } else { (shape.block_indent(context.config.tab_spaces()), false) }; @@ -142,17 +140,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ..nested_shape }; let first_child_shape = if extend { - let mut shape = try_opt!(parent_shape.offset_left(last_line_width(&parent_rewrite))); + let first_child_shape = try_opt!(parent_shape + .offset_left(last_line_width(&parent_rewrite))); match context.config.chain_indent() { - IndentStyle::Visual => shape, - IndentStyle::Block => { - shape.offset = shape - .offset - .checked_sub(context.config.tab_spaces()) - .unwrap_or(0); - shape.indent.block_indent += context.config.tab_spaces(); - shape - } + IndentStyle::Visual => first_child_shape, + IndentStyle::Block => first_child_shape.block(), } } else { other_child_shape diff --git a/src/macros.rs b/src/macros.rs index 352c39f317c..a5ead34c9ec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -183,7 +183,7 @@ pub fn rewrite_macro(mac: &ast::Mac, let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); // Handle special case: `vec![expr; expr]` if vec_with_semi { - let (lbr, rbr) = if context.config.spaces_within_square_brackets { + let (lbr, rbr) = if context.config.spaces_within_square_brackets() { ("[ ", " ]") } else { ("[", "]") diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 4013b2d9b25..35030189b8b 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -15,3 +15,33 @@ impl Foo { } } } + +fn issue1420() { + given( + r#" + # Getting started + ... + "#, + ) + .running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| { + Post { + title: row.get(0), + date: row.get(1), + } + }, + )?; + + Ok(()) +} diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index c9a42cd4952..d7f65635379 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -28,3 +28,33 @@ impl Foo { } } } + +fn issue1420() { + given( + r#" + # Getting started + ... + "# + ) + .running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| { + Post { + title: row.get(0), + date: row.get(1), + } + }, + )?; + + Ok(()) +} -- cgit 1.4.1-3-g733a5 From 520340481d4238d63a4eef2555fba45405dc74b4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 19 May 2017 19:30:06 +0900 Subject: Allow macro rewrite to fail on rhs --- src/expr.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 066c7faa43e..a2c5f1c077c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2080,11 +2080,18 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, 0 }; // 1 = space between operator and rhs. - let max_width = try_opt!(shape.width.checked_sub(last_line_width + 1)); - let rhs = ex.rewrite(context, - Shape::offset(max_width, - shape.indent, - shape.indent.alignment + last_line_width + 1)); + let orig_shape = try_opt!(shape.block_indent(0).offset_left(last_line_width + 1)); + let rhs = match ex.node { + ast::ExprKind::Mac(ref mac) => { + match rewrite_macro(mac, None, context, orig_shape, MacroPosition::Expression) { + None if !context.snippet(ex.span).contains("\n") => { + context.snippet(ex.span).rewrite(context, orig_shape) + } + rhs @ _ => rhs, + } + } + _ => ex.rewrite(context, orig_shape), + }; fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() -- cgit 1.4.1-3-g733a5 From f2ec5a7bac3f8bdda148307c576f41f2ca005828 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 19 May 2017 19:31:01 +0900 Subject: Refactor source codes --- src/chains.rs | 1 - src/expr.rs | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5da00d29330..fbc42a5d84e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -173,7 +173,6 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if rewrites.len() > 1 { true } else if rewrites.len() == 1 { - let one_line_len = parent_rewrite.len() + first_line_width(&rewrites[0]); one_line_len > shape.width } else { false diff --git a/src/expr.rs b/src/expr.rs index a2c5f1c077c..7226357f7a3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -286,7 +286,7 @@ pub fn rewrite_pair(lhs: &LHS, let remaining_width = shape .width - .checked_sub(last_line_width(&result)) + .checked_sub(last_line_width(&result) + suffix.len()) .unwrap_or(0); if rhs_result.len() <= remaining_width { @@ -2106,10 +2106,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // Expression did not fit on the same line as the identifier or is // at least three lines big. Try splitting the line and see // if that works better. - let new_offset = shape.indent.block_indent(context.config); - let max_width = try_opt!((shape.width + shape.indent.width()) - .checked_sub(new_offset.width())); - let new_shape = Shape::legacy(max_width, new_offset); + let new_shape = try_opt!(shape.block_left(context.config.tab_spaces)); let new_rhs = ex.rewrite(context, new_shape); // FIXME: DRY! @@ -2118,11 +2115,11 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 || (orig_rhs.rewrite(context, shape).is_none() && replacement_rhs.rewrite(context, new_shape).is_some()) => { - result.push_str(&format!("\n{}", new_offset.to_string(context.config))); + result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(replacement_rhs); } (None, Some(ref final_rhs)) => { - result.push_str(&format!("\n{}", new_offset.to_string(context.config))); + result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(final_rhs); } (None, None) => return None, -- cgit 1.4.1-3-g733a5 From 77a2e9858b44598454aa6240475255cd5547d519 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 19 May 2017 19:31:29 +0900 Subject: Format source codes --- build.rs | 4 ++-- src/expr.rs | 14 +++++++------- src/items.rs | 8 ++++---- src/lists.rs | 3 ++- src/missed_spans.rs | 2 +- src/patterns.rs | 2 +- src/types.rs | 42 +++++++++++++++++++++++++----------------- src/visitor.rs | 8 ++++---- 8 files changed, 46 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index 4f4a63be436..aca96774d06 100644 --- a/build.rs +++ b/build.rs @@ -16,11 +16,11 @@ fn main() { writeln!(f, "const COMMIT_HASH: Option<&'static str> = {:?};", git_head_sha1()) - .unwrap(); + .unwrap(); writeln!(f, "const WORKTREE_CLEAN: Option = {:?};", git_tree_is_clean()) - .unwrap(); + .unwrap(); // cargo:rerun-if-changed requires one entry per individual file. for entry in WalkDir::new("src") { diff --git a/src/expr.rs b/src/expr.rs index 7226357f7a3..31953380a73 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -120,7 +120,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { ControlFlow::new_if(cond, @@ -130,7 +130,7 @@ fn format_expr(expr: &ast::Expr, expr_type == ExprType::SubExpression, false, expr.span) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, shape, expr.span) @@ -372,7 +372,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, |item| item.rewrite(context, nested_shape), span.lo, span.hi) - .collect::>(); + .collect::>(); if items.is_empty() { if context.config.spaces_within_square_brackets() { @@ -716,7 +716,7 @@ impl Rewrite for ast::Stmt { }, context, try_opt!(shape.sub_width(suffix.len()))) - .map(|s| s + suffix) + .map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, @@ -1012,7 +1012,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + .rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if(cond, @@ -1022,7 +1022,7 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + .rewrite(context, shape) } _ => { last_in_chain = true; @@ -1065,7 +1065,7 @@ impl<'a> Rewrite for ControlFlow<'a> { .as_ref() .map_or(between_sep, |s| &**s), after_else_comment.as_ref().map_or(after_sep, |s| &**s)) - .ok()); + .ok()); result.push_str(&try_opt!(rewrite)); } diff --git a/src/items.rs b/src/items.rs index 953aecb3305..f98cf9507e1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -332,7 +332,7 @@ impl<'a> FmtVisitor<'a> { let suffix = if semicolon_for_expr(e) { ";" } else { "" }; e.rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)) + Shape::indented(self.block_indent, self.config)) .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } @@ -376,7 +376,7 @@ impl<'a> FmtVisitor<'a> { enum_def.variants.is_empty(), self.block_indent, mk_sp(span.lo, body_start)) - .unwrap(); + .unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; @@ -941,7 +941,7 @@ fn format_struct_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "{"), span.hi) - .collect::>(); + .collect::>(); // 1 = , let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1; @@ -1295,7 +1295,7 @@ pub fn rewrite_static(prefix: &str, lhs, expr, Shape::legacy(remaining_width, offset.block_only())) - .map(|s| s + ";") + .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); Some(lhs) diff --git a/src/lists.rs b/src/lists.rs index a48f9a382e6..3448f8a446a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -266,7 +266,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = try_opt!(rewrite_comment(comment, + let formatted_comment = + try_opt!(rewrite_comment(comment, true, Shape::legacy(formatting.shape.width, Indent::empty()), formatting.config)); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2f4dda2a1b4..d6157cd6a29 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -163,7 +163,7 @@ impl<'a> FmtVisitor<'a> { Shape::legacy(comment_width, self.block_indent), self.config) - .unwrap()); + .unwrap()); last_wspace = None; line_start = offset + subslice.len(); diff --git a/src/patterns.rs b/src/patterns.rs index 5dc70f6d2d8..afea0ddb299 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -293,7 +293,7 @@ fn rewrite_tuple_pat(pats: &[ptr::P], |item| item.rewrite(context, nested_shape), context.codemap.span_after(span, "("), span.hi - BytePos(1)) - .collect(); + .collect(); // Condense wildcard string suffix into a single .. let wildcard_suffix_len = count_wildcard_suffix_len(&items); diff --git a/src/types.rs b/src/types.rs index ffa9639005a..570755d4441 100644 --- a/src/types.rs +++ b/src/types.rs @@ -364,7 +364,9 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { - let lifetime_str: String = try_opt!(bound_lifetimes.iter() + let lifetime_str: String = + try_opt!(bound_lifetimes + .iter() .map(|lt| lt.rewrite(context, shape)) .intersperse(Some(", ".to_string())) .collect()); @@ -376,14 +378,17 @@ impl Rewrite for ast::WherePredicate { // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, - shape.indent + used_width)) - }) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds_str: String = + try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(budget, + shape.indent + + used_width)) + }) + .intersperse(Some(joiner.to_string())) + .collect()); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", @@ -401,14 +406,17 @@ impl Rewrite for ast::WherePredicate { }; let used_width = type_str.len() + colon.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!(bounds.iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, - shape.indent + used_width)) - }) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds_str: String = + try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(budget, + shape.indent + + used_width)) + }) + .intersperse(Some(joiner.to_string())) + .collect()); format!("{}{}{}", type_str, colon, bounds_str) } diff --git a/src/visitor.rs b/src/visitor.rs index 0e6817be4f7..96327ef96a7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -282,10 +282,10 @@ impl<'a> FmtVisitor<'a> { item.span, indent, None) - .map(|s| match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - }) + .map(|s| match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + }) }; self.push_rewrite(item.span, rewrite); } -- cgit 1.4.1-3-g733a5 From dc8d3aa23a19e662c5a680f0be06561f5db3a714 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 22 May 2017 08:50:46 +0900 Subject: Update tests --- src/expr.rs | 2 +- tests/source/macros.rs | 6 ++++++ tests/target/macros.rs | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 31953380a73..9c4f48bbb7e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2106,7 +2106,7 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // Expression did not fit on the same line as the identifier or is // at least three lines big. Try splitting the line and see // if that works better. - let new_shape = try_opt!(shape.block_left(context.config.tab_spaces)); + let new_shape = try_opt!(shape.block_left(context.config.tab_spaces())); let new_rhs = ex.rewrite(context, new_shape); // FIXME: DRY! diff --git a/tests/source/macros.rs b/tests/source/macros.rs index afaf67359ed..b83f74c47d5 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -41,6 +41,12 @@ fn main() { vec![a, b; c]; vec![a; b, c]; + vec![a; (|x| { let y = x + 1; let z = y + 1; z })(2)]; + vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![a; unsafe { + x + 1 + }]; + unknown_bracket_macro__comma_should_not_be_stripped![ a, ]; diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 2f65b4e4f6e..c19bb242ca3 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -45,6 +45,16 @@ fn main() { vec![a, b; c]; vec![a; b, c]; + vec![a; + (|x| { + let y = x + 1; + let z = y + 1; + z + })(2)]; + vec![a; + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![a; unsafe { x + 1 }]; + unknown_bracket_macro__comma_should_not_be_stripped![ a, ]; -- cgit 1.4.1-3-g733a5 From 29c0ab77ba4e3a196227ee1d61a2ae57e35625c0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 21 May 2017 19:56:13 +0900 Subject: Implement combining openings and closings --- src/expr.rs | 83 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9c4f48bbb7e..f0db88ae566 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1334,18 +1334,21 @@ impl Rewrite for ast::Arm { let pats_str = format!("{}{}", pats_str, guard_str); - let body = match body.node { + let (mut extend, body) = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && context.config.wrap_match_arms() => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - expr + (false, &**expr) } else { - &**body + (false, &**body) } } - _ => &**body, + ast::ExprKind::Call(_, ref args) => (args.len() == 1, &**body), + ast::ExprKind::Closure(..) => (true, &**body), + _ => (false, &**body), }; + extend &= context.config.fn_call_style == IndentStyle::Block; let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + @@ -1371,6 +1374,7 @@ impl Rewrite for ast::Arm { Some(ref body_str) if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) || !context.config.wrap_match_arms() || + (extend && first_line_width(body_str) <= arm_shape.width) || is_block => { let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), @@ -1611,9 +1615,7 @@ pub fn rewrite_call(context: &RewriteContext, let closure = |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape); - // 2 is for parens - let max_width = try_opt!(shape.width.checked_sub(2)); - binary_search(1, max_width, closure) + binary_search(1, shape.width, closure) } fn rewrite_call_inner(context: &RewriteContext, @@ -1635,25 +1637,43 @@ fn rewrite_call_inner(context: &RewriteContext, .rewrite(context, callee_shape) .ok_or(Ordering::Greater)?; - // 4 = `( )`, 2 = `()` + // 2 = `( `, 1 = `(` let paren_overhead = if context.config.spaces_within_parens() { - 4 - } else { 2 + } else { + 1 }; let used_width = extra_offset(&callee_str, shape); let one_line_width = shape .width - .checked_sub(used_width + paren_overhead) + .checked_sub(used_width + 2 * paren_overhead) .ok_or(Ordering::Greater)?; + // Try combining openings and closings + if args.len() == 1 && context.config.fn_call_style() == IndentStyle::Block { + let expr = &*args[0]; + match expr.node { + ast::ExprKind::Struct(..) | + ast::ExprKind::Call(..) | + ast::ExprKind::Closure(..) => { + let max_width = min(one_line_width, context.config.fn_call_width()); + let shape = Shape::legacy(max_width, shape.block().indent); + if let Some(expr_str) = expr.rewrite(context, shape) { + if first_line_width(&expr_str) <= max_width { + return Ok(format!("{}({})", callee_str, expr_str)); + } + } + } + _ => (), + } + } + let nested_shape = match context.config.fn_call_style() { IndentStyle::Block => shape.block().block_left(context.config.tab_spaces()), - // 1 = ( IndentStyle::Visual => { shape - .visual_indent(used_width + 1) - .sub_width(used_width + paren_overhead) + .visual_indent(used_width + paren_overhead) + .sub_width(used_width + 2 * paren_overhead) } } .ok_or(Ordering::Greater)?; @@ -1664,8 +1684,12 @@ fn rewrite_call_inner(context: &RewriteContext, let list_str = rewrite_call_args(context, args, span, nested_shape, one_line_width) .ok_or(Ordering::Less)?; + let arg_one_line_budget = min(one_line_width, context.config.fn_call_width()); let result = if context.config.fn_call_style() == IndentStyle::Visual || - (!list_str.contains('\n') && list_str.chars().last().unwrap_or(' ') != ',') { + (((can_be_overflowed(args) && + first_line_width(&list_str) <= arg_one_line_budget) || + !list_str.contains('\n')) && + list_str.chars().last().unwrap_or(' ') != ',') { if context.config.spaces_within_parens() && list_str.len() > 0 { format!("{}( {} )", callee_str, list_str) } else { @@ -1682,6 +1706,15 @@ fn rewrite_call_inner(context: &RewriteContext, Ok(result) } +fn can_be_overflowed(args: &[ptr::P]) -> bool { + match args.last().map(|x| &x.node) { + Some(&ast::ExprKind::Closure(..)) | + Some(&ast::ExprKind::Block(..)) | + Some(&ast::ExprKind::Match(..)) if args.len() > 1 => true, + _ => false, + } +} + fn rewrite_call_args(context: &RewriteContext, args: &[ptr::P], span: Span, @@ -1703,12 +1736,7 @@ fn rewrite_call_args(context: &RewriteContext, // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. - let overflow_last = match args.last().map(|x| &x.node) { - Some(&ast::ExprKind::Closure(..)) | - Some(&ast::ExprKind::Block(..)) | - Some(&ast::ExprKind::Match(..)) if arg_count > 1 => true, - _ => false, - }; + let overflow_last = can_be_overflowed(args); let mut orig_last = None; let mut placeholder = None; @@ -1716,11 +1744,16 @@ fn rewrite_call_args(context: &RewriteContext, // Replace the last item with its first line to see if it fits with // first arguments. if overflow_last { - let nested_shape = Shape { - indent: shape.indent.block_only(), - ..shape + let last_arg = args.last().unwrap(); + let arg_shape = match last_arg.node { + ast::ExprKind::Closure(..) if context.config.fn_call_style == IndentStyle::Block => { + let mut arg_shape = shape.block(); + arg_shape.indent.block_indent -= context.config.tab_spaces; + arg_shape + } + _ => shape.block(), }; - let rewrite = args.last().unwrap().rewrite(context, nested_shape); + let rewrite = args.last().unwrap().rewrite(context, arg_shape); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); -- cgit 1.4.1-3-g733a5 From 2c15204f0c4a0b0d5f97460a23f10fa090f5aef9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 21 May 2017 19:56:37 +0900 Subject: Update tests --- src/expr.rs | 6 +- tests/source/configs-fn_call_style-block.rs | 51 +++++++++++++++++ tests/source/expr-block.rs | 85 +++++++++++++++++++++++++++++ tests/target/closure-block-inside-macro.rs | 18 +++--- tests/target/configs-fn_call_style-block.rs | 61 +++++++++++++++++++-- tests/target/expr-block.rs | 72 ++++++++++++++++++++++++ 6 files changed, 274 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f0db88ae566..c1b130fd8f3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1348,7 +1348,7 @@ impl Rewrite for ast::Arm { ast::ExprKind::Closure(..) => (true, &**body), _ => (false, &**body), }; - extend &= context.config.fn_call_style == IndentStyle::Block; + extend &= context.config.fn_call_style() == IndentStyle::Block; let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + @@ -1746,9 +1746,9 @@ fn rewrite_call_args(context: &RewriteContext, if overflow_last { let last_arg = args.last().unwrap(); let arg_shape = match last_arg.node { - ast::ExprKind::Closure(..) if context.config.fn_call_style == IndentStyle::Block => { + ast::ExprKind::Closure(..) if context.config.fn_call_style() == IndentStyle::Block => { let mut arg_shape = shape.block(); - arg_shape.indent.block_indent -= context.config.tab_spaces; + arg_shape.indent.block_indent -= context.config.tab_spaces(); arg_shape } _ => shape.block(), diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 35030189b8b..6708966fa69 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -45,3 +45,54 @@ fn query(conn: &Connection) -> Result<()> { Ok(()) } + +// #1449 +fn future_rayon_wait_1_thread() { + // run with only 1 worker thread; this would deadlock if we couldn't make progress + let mut result = None; + ThreadPool::new(Configuration::new().num_threads(1)) + .unwrap() + .install( + || { + scope( + |s| { + use std::sync::mpsc::channel; + let (tx, rx) = channel(); + let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); + // ^^^^ FIXME: why is this needed? + let b = s.spawn_future(a.map(|v| v + 1)); + let c = s.spawn_future(b.map(|v| v + 1)); + s.spawn(move |_| tx.send(20).unwrap()); + result = Some(c.rayon_wait().unwrap()); + }, + ); + }, + ); + assert_eq!(result, Some(22)); +} + +// #1494 +impl Cursor { + fn foo() { + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical != *self { + canonical.num_template_args() + } else { + None + } + }); + } +} diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index ad959f8ee01..bf5d23a7d9e 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -143,3 +143,88 @@ fn foo() { DefinitiveListTactic::Horizontal } } + +fn combine_block() { + foo( + Bar { + x: value, + y: value2, + }, + ); + + let opt = Some( + Struct( + long_argument_one, + long_argument_two, + long_argggggggg, + ), + ); + + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + Ok( + some_function( + lllllllllong_argument_one, + lllllllllong_argument_two, + lllllllllllllllllllllllllllllong_argument_three, + ), + ); + + foo( + thing, + bar( + param2, + pparam1param1param1param1param1param1param1param1param1param1aram1, + param3, + ), + ); + + foo.map_or( + || { + Ok( + SomeStruct { + f1: 0, + f2: 0, + f3: 0, + }, + ) + }, + ); + + match opt { + Some(x) => somefunc(anotherfunc( + long_argument_one, + long_argument_two, + long_argument_three, + )), + None => Ok(SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }), + }; + + match x { + y => func( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ), + _ => func( + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzz, + ), + } +} diff --git a/tests/target/closure-block-inside-macro.rs b/tests/target/closure-block-inside-macro.rs index b58527eb8fb..5d1e1de0f68 100644 --- a/tests/target/closure-block-inside-macro.rs +++ b/tests/target/closure-block-inside-macro.rs @@ -1,15 +1,13 @@ // rustfmt-fn_call_style: Block // #1547 -fuzz_target!( - |data: &[u8]| { - if let Some(first) = data.first() { - let index = *first as usize; - if index >= ENCODINGS.len() { - return; - } - let encoding = ENCODINGS[index]; - dispatch_test(encoding, &data[1..]); +fuzz_target!(|data: &[u8]| { + if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); } -); +}); diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index d7f65635379..ed3dd76c04d 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -13,18 +13,20 @@ fn main() { "elit", ); // #1501 - let hyper = Arc::new( - Client::with_connector(HttpsConnector::new(TlsClient::new())), - ); + let hyper = Arc::new(Client::with_connector(HttpsConnector::new( + TlsClient::new(), + ))); } // #1521 impl Foo { fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { unsafe { - Vector2f::from_raw( - ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw()), - ) + Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords( + self.render_texture, + point.raw(), + view.raw(), + )) } } } @@ -58,3 +60,50 @@ fn query(conn: &Connection) -> Result<()> { Ok(()) } + +// #1449 +fn future_rayon_wait_1_thread() { + // run with only 1 worker thread; this would deadlock if we couldn't make progress + let mut result = None; + ThreadPool::new(Configuration::new().num_threads(1)) + .unwrap() + .install(|| { + scope(|s| { + use std::sync::mpsc::channel; + let (tx, rx) = channel(); + let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); + // ^^^^ FIXME: why is this needed? + let b = s.spawn_future(a.map(|v| v + 1)); + let c = s.spawn_future(b.map(|v| v + 1)); + s.spawn(move |_| tx.send(20).unwrap()); + result = Some(c.rayon_wait().unwrap()); + }); + }); + assert_eq!(result, Some(22)); +} + +// #1494 +impl Cursor { + fn foo() { + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical != *self { + canonical.num_template_args() + } else { + None + } + }); + } +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index b6f35f65aec..1f3082f3068 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -213,3 +213,75 @@ fn foo() { DefinitiveListTactic::Horizontal } } + +fn combine_block() { + foo(Bar { + x: value, + y: value2, + }); + + let opt = Some(Struct( + long_argument_one, + long_argument_two, + long_argggggggg, + )); + + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + Ok(some_function( + lllllllllong_argument_one, + lllllllllong_argument_two, + lllllllllllllllllllllllllllllong_argument_three, + )); + + foo( + thing, + bar( + param2, + pparam1param1param1param1param1param1param1param1param1param1aram1, + param3, + ), + ); + + foo.map_or(|| { + Ok(SomeStruct { + f1: 0, + f2: 0, + f3: 0, + }) + }); + + match opt { + Some(x) => somefunc(anotherfunc( + long_argument_one, + long_argument_two, + long_argument_three, + )), + None => Ok(SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }), + }; + + match x { + y => func( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ), + _ => { + func( + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzz, + ) + } + } +} -- cgit 1.4.1-3-g733a5 From b4cd9584b380b196d9f599916180136c66694d71 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 May 2017 11:20:29 +0900 Subject: Implement combining for tuple and block --- src/expr.rs | 248 +++++++++++++++++----------- src/types.rs | 4 +- src/utils.rs | 43 ++--- tests/source/expr-block.rs | 16 ++ tests/target/configs-fn_call_style-block.rs | 6 +- tests/target/expr-block.rs | 21 +++ 6 files changed, 221 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c1b130fd8f3..bfd38f86c62 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -96,9 +96,7 @@ fn format_expr(expr: &ast::Expr, expr.span, shape) } - ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, items.iter().map(|x| &**x), expr.span, shape) - } + ast::ExprKind::Tup(ref items) => rewrite_tuple(context, items, expr.span, shape), ast::ExprKind::While(ref cond, ref block, label) => { ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape) } @@ -1345,7 +1343,9 @@ impl Rewrite for ast::Arm { } } ast::ExprKind::Call(_, ref args) => (args.len() == 1, &**body), - ast::ExprKind::Closure(..) => (true, &**body), + ast::ExprKind::Closure(..) | + ast::ExprKind::Struct(..) | + ast::ExprKind::Tup(..) => (true, &**body), _ => (false, &**body), }; extend &= context.config.fn_call_style() == IndentStyle::Block; @@ -1612,8 +1612,9 @@ pub fn rewrite_call(context: &RewriteContext, -> Option where R: Rewrite { - let closure = - |callee_max_width| rewrite_call_inner(context, callee, callee_max_width, args, span, shape); + let closure = |callee_max_width| { + rewrite_call_inner(context, callee, callee_max_width, args, span, shape, false) + }; binary_search(1, shape.width, closure) } @@ -1623,7 +1624,8 @@ fn rewrite_call_inner(context: &RewriteContext, max_callee_width: usize, args: &[ptr::P], span: Span, - shape: Shape) + shape: Shape, + force_trailing_comma: bool) -> Result where R: Rewrite { @@ -1649,80 +1651,40 @@ fn rewrite_call_inner(context: &RewriteContext, .checked_sub(used_width + 2 * paren_overhead) .ok_or(Ordering::Greater)?; - // Try combining openings and closings - if args.len() == 1 && context.config.fn_call_style() == IndentStyle::Block { - let expr = &*args[0]; - match expr.node { - ast::ExprKind::Struct(..) | - ast::ExprKind::Call(..) | - ast::ExprKind::Closure(..) => { - let max_width = min(one_line_width, context.config.fn_call_width()); - let shape = Shape::legacy(max_width, shape.block().indent); - if let Some(expr_str) = expr.rewrite(context, shape) { - if first_line_width(&expr_str) <= max_width { - return Ok(format!("{}({})", callee_str, expr_str)); - } - } - } - _ => (), - } - } - - let nested_shape = match context.config.fn_call_style() { - IndentStyle::Block => shape.block().block_left(context.config.tab_spaces()), - IndentStyle::Visual => { - shape - .visual_indent(used_width + paren_overhead) - .sub_width(used_width + 2 * paren_overhead) - } - } - .ok_or(Ordering::Greater)?; + let nested_shape = shape_from_fn_call_style(context, + shape, + used_width + 2 * paren_overhead, + used_width + paren_overhead) + .ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); - let list_str = rewrite_call_args(context, args, span, nested_shape, one_line_width) - .ok_or(Ordering::Less)?; - + let list_str = rewrite_call_args(context, + args, + span, + nested_shape, + one_line_width, + force_trailing_comma) + .ok_or(Ordering::Less)?; let arg_one_line_budget = min(one_line_width, context.config.fn_call_width()); - let result = if context.config.fn_call_style() == IndentStyle::Visual || - (((can_be_overflowed(args) && - first_line_width(&list_str) <= arg_one_line_budget) || - !list_str.contains('\n')) && - list_str.chars().last().unwrap_or(' ') != ',') { - if context.config.spaces_within_parens() && list_str.len() > 0 { - format!("{}( {} )", callee_str, list_str) - } else { - format!("{}({})", callee_str, list_str) - } - } else { - format!("{}(\n{}{}\n{})", - callee_str, - nested_shape.indent.to_string(context.config), - list_str, - shape.block().indent.to_string(context.config)) - }; - - Ok(result) -} - -fn can_be_overflowed(args: &[ptr::P]) -> bool { - match args.last().map(|x| &x.node) { - Some(&ast::ExprKind::Closure(..)) | - Some(&ast::ExprKind::Block(..)) | - Some(&ast::ExprKind::Match(..)) if args.len() > 1 => true, - _ => false, - } + Ok(format!("{}{}", + callee_str, + wrap_args_with_parens(context, + &list_str, + is_extendable(args), + arg_one_line_budget, + shape, + nested_shape))) } fn rewrite_call_args(context: &RewriteContext, args: &[ptr::P], span: Span, shape: Shape, - one_line_width: usize) + one_line_width: usize, + force_trailing_comma: bool) -> Option { - let arg_count = args.len(); - let items = itemize_list(context.codemap, args.iter(), ")", @@ -1736,7 +1698,7 @@ fn rewrite_call_args(context: &RewriteContext, // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. - let overflow_last = can_be_overflowed(args); + let overflow_last = can_be_overflowed(context, args); let mut orig_last = None; let mut placeholder = None; @@ -1744,14 +1706,15 @@ fn rewrite_call_args(context: &RewriteContext, // Replace the last item with its first line to see if it fits with // first arguments. if overflow_last { - let last_arg = args.last().unwrap(); - let arg_shape = match last_arg.node { - ast::ExprKind::Closure(..) if context.config.fn_call_style() == IndentStyle::Block => { - let mut arg_shape = shape.block(); - arg_shape.indent.block_indent -= context.config.tab_spaces(); - arg_shape + let arg_shape = if context.config.fn_call_style() == IndentStyle::Block && + is_extendable(args) { + Shape { + width: context.config.fn_call_width(), + indent: shape.block().indent.block_unindent(context.config), + offset: 0, } - _ => shape.block(), + } else { + shape.block() }; let rewrite = args.last().unwrap().rewrite(context, arg_shape); @@ -1759,8 +1722,8 @@ fn rewrite_call_args(context: &RewriteContext, let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); placeholder = Some(rewrite); - swap(&mut item_vec[arg_count - 1].item, &mut orig_last); - item_vec[arg_count - 1].item = rewrite_first_line; + swap(&mut item_vec[args.len() - 1].item, &mut orig_last); + item_vec[args.len() - 1].item = rewrite_first_line; } } @@ -1778,10 +1741,10 @@ fn rewrite_call_args(context: &RewriteContext, // succeeded and its first line fits with the other arguments. match (overflow_last, tactic, placeholder) { (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { - item_vec[arg_count - 1].item = placeholder; + item_vec[args.len() - 1].item = placeholder; } (true, _, _) => { - item_vec[arg_count - 1].item = orig_last; + item_vec[args.len() - 1].item = orig_last; } (false, _, _) => {} } @@ -1789,9 +1752,10 @@ fn rewrite_call_args(context: &RewriteContext, let mut fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: if context.inside_macro || - context.config.fn_call_style() == IndentStyle::Visual || - arg_count <= 1 { + trailing_separator: if force_trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro || context.config.fn_call_style() == IndentStyle::Visual || + args.len() <= 1 { SeparatorTactic::Never } else { context.config.trailing_comma() @@ -1807,8 +1771,8 @@ fn rewrite_call_args(context: &RewriteContext, // and not rewriting macro. Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && !context.inside_macro && - (!s.contains('\n') && - (s.len() > one_line_width || s.len() > context.config.fn_call_width())) => { + (first_line_width(s) > one_line_width || + first_line_width(s) > context.config.fn_call_width()) => { fmt.trailing_separator = SeparatorTactic::Vertical; write_list(&item_vec, &fmt) } @@ -1816,6 +1780,72 @@ fn rewrite_call_args(context: &RewriteContext, } } +fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bool { + match args.last().map(|x| &x.node) { + Some(&ast::ExprKind::Block(..)) | + Some(&ast::ExprKind::Match(..)) => { + (context.config.fn_call_style() == IndentStyle::Block && args.len() == 1) || + (context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1) + } + Some(&ast::ExprKind::Closure(..)) => { + context.config.fn_call_style() == IndentStyle::Block || + context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1 + } + Some(&ast::ExprKind::Call(..)) | + Some(&ast::ExprKind::Struct(..)) => { + context.config.fn_call_style() == IndentStyle::Block && args.len() == 1 + } + Some(&ast::ExprKind::Tup(..)) => context.config.fn_call_style() == IndentStyle::Block, + _ => false, + } +} + +fn is_extendable(args: &[ptr::P]) -> bool { + if args.len() == 1 { + match args[0].node { + ast::ExprKind::Block(..) | + ast::ExprKind::Call(..) | + ast::ExprKind::Closure(..) | + ast::ExprKind::Match(..) | + ast::ExprKind::Struct(..) | + ast::ExprKind::Tup(..) => true, + _ => false, + } + } else if args.len() > 1 { + match args[args.len() - 1].node { + ast::ExprKind::Closure(..) | + ast::ExprKind::Tup(..) => true, + _ => false, + } + } else { + false + } +} + +fn wrap_args_with_parens(context: &RewriteContext, + args_str: &str, + is_extendable: bool, + one_line_budget: usize, + shape: Shape, + nested_shape: Shape) + -> String { + if context.config.fn_call_style() == IndentStyle::Visual || + (context.inside_macro && !args_str.contains('\n')) || + ((is_extendable || !args_str.contains('\n')) && + first_line_width(&args_str) <= one_line_budget) { + if context.config.spaces_within_parens() && args_str.len() > 0 { + format!("( {} )", args_str) + } else { + format!("({})", args_str) + } + } else { + format!("(\n{}{}\n{})", + nested_shape.indent.to_string(context.config), + args_str, + shape.block().indent.to_string(context.config)) + } +} + fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { debug!("rewrite_paren, shape: {:?}", shape); // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing @@ -1995,17 +2025,28 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> } } -pub fn rewrite_tuple<'a, I>(context: &RewriteContext, - mut items: I, - span: Span, - shape: Shape) - -> Option +fn shape_from_fn_call_style(context: &RewriteContext, + shape: Shape, + overhead: usize, + offset: usize) + -> Option { + match context.config.fn_call_style() { + IndentStyle::Block => Some(shape.block().block_indent(context.config.tab_spaces())), + IndentStyle::Visual => shape.visual_indent(offset).sub_width(overhead), + } +} + +pub fn rewrite_tuple_type<'a, I>(context: &RewriteContext, + mut items: I, + span: Span, + shape: Shape) + -> Option where I: ExactSizeIterator, ::Item: Deref, ::Target: Rewrite + Spanned + 'a { - debug!("rewrite_tuple {:?}", shape); // In case of length 1, need a trailing comma + debug!("rewrite_tuple_type {:?}", shape); if items.len() == 1 { // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); @@ -2039,6 +2080,29 @@ pub fn rewrite_tuple<'a, I>(context: &RewriteContext, } } +pub fn rewrite_tuple(context: &RewriteContext, + items: &[ptr::P], + span: Span, + shape: Shape) + -> Option { + debug!("rewrite_tuple {:?}", shape); + // Use old `rewrite_tuple` + if context.config.fn_call_style() == IndentStyle::Visual { + return rewrite_tuple_type(context, items.iter().map(|x| &**x), span, shape); + } + + // We use the same rule as funcation call for rewriting tuple with multiple expressions. + // 1 = "," + rewrite_call_inner(context, + &String::new(), + shape.width.checked_sub(1).unwrap_or(0), + items, + span, + shape, + items.len() == 1) + .ok() +} + pub fn rewrite_unary_prefix(context: &RewriteContext, prefix: &str, rewrite: &R, diff --git a/src/types.rs b/src/types.rs index 570755d4441..8f99be11d1a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -22,7 +22,7 @@ use codemap::SpanUtils; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; +use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; use config::TypeDensity; use itertools::Itertools; @@ -662,7 +662,7 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::Tup(ref items) => { - rewrite_tuple(context, items.iter().map(|x| &**x), self.span, shape) + rewrite_tuple_type(context, items.iter().map(|x| &**x), self.span, shape) } ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) diff --git a/src/utils.rs b/src/utils.rs index bb9d178b83f..664d538fbb9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -299,29 +299,32 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option shape.width { - return None; - } else { - let mut lines = snippet.lines(); - - // The caller of this function has already placed `shape.offset` - // characters on the first line. - let first_line_max_len = try_opt!(max_width.checked_sub(shape.indent.width())); - if lines.next().unwrap().len() > first_line_max_len { + if !snippet.is_empty() { + if !snippet.contains('\n') && snippet.len() > shape.width { return None; - } + } else { + let mut lines = snippet.lines(); + + // The caller of this function has already placed `shape.offset` + // characters on the first line. + let first_line_max_len = try_opt!(max_width.checked_sub(shape.indent.width())); + if lines.next().unwrap().len() > first_line_max_len { + return None; + } - // The other lines must fit within the maximum width. - if lines.any(|line| line.len() > max_width) { - return None; - } + // The other lines must fit within the maximum width. + if lines.any(|line| line.len() > max_width) { + return None; + } - // `width` is the maximum length of the last line, excluding - // indentation. - // A special check for the last line, since the caller may - // place trailing characters on this line. - if snippet.lines().rev().next().unwrap().len() > shape.indent.width() + shape.width { - return None; + // `width` is the maximum length of the last line, excluding + // indentation. + // A special check for the last line, since the caller may + // place trailing characters on this line. + if snippet.lines().rev().next().unwrap().len() > + shape.indent.width() + shape.width { + return None; + } } } } diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index bf5d23a7d9e..14207b5adb9 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -152,6 +152,22 @@ fn combine_block() { }, ); + foo((Bar { + x: value, + y: value2, + },)); + + foo((1, 2, 3, Bar { + x: value, + y: value2, + })); + + foo((1, 2, 3, |x| { + let y = x + 1; + let z = y + 1; + z + })); + let opt = Some( Struct( long_argument_one, diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index ed3dd76c04d..af8238defe6 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -13,9 +13,9 @@ fn main() { "elit", ); // #1501 - let hyper = Arc::new(Client::with_connector(HttpsConnector::new( - TlsClient::new(), - ))); + let hyper = Arc::new(Client::with_connector( + HttpsConnector::new(TlsClient::new()), + )); } // #1521 diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 1f3082f3068..6e4d2f109ac 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -220,6 +220,27 @@ fn combine_block() { y: value2, }); + foo((Bar { + x: value, + y: value2, + },)); + + foo(( + 1, + 2, + 3, + Bar { + x: value, + y: value2, + }, + )); + + foo((1, 2, 3, |x| { + let y = x + 1; + let z = y + 1; + z + })); + let opt = Some(Struct( long_argument_one, long_argument_two, -- cgit 1.4.1-3-g733a5 From f83c22f24f2f497c454531e101cf63bf825e3bd5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 May 2017 12:03:04 +0900 Subject: Add trailing comma to a single arg in multiline --- src/expr.rs | 41 +++++++++++++--------- .../configs-fn_call_style-block-trailing-comma.rs | 1 + tests/source/expr-block.rs | 28 +++++++++++++++ .../configs-fn_call_style-block-trailing-comma.rs | 3 ++ tests/target/configs-fn_call_style-block.rs | 2 +- tests/target/expr-block.rs | 22 +++++++++++- 6 files changed, 79 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bfd38f86c62..ad0d654175d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1655,24 +1655,24 @@ fn rewrite_call_inner(context: &RewriteContext, shape, used_width + 2 * paren_overhead, used_width + paren_overhead) - .ok_or(Ordering::Greater)?; + .ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); let span = mk_sp(span_lo, span.hi); - let list_str = rewrite_call_args(context, - args, - span, - nested_shape, - one_line_width, - force_trailing_comma) - .ok_or(Ordering::Less)?; + let (extendable, list_str) = rewrite_call_args(context, + args, + span, + nested_shape, + one_line_width, + force_trailing_comma) + .ok_or(Ordering::Less)?; let arg_one_line_budget = min(one_line_width, context.config.fn_call_width()); Ok(format!("{}{}", callee_str, wrap_args_with_parens(context, &list_str, - is_extendable(args), + extendable, arg_one_line_budget, shape, nested_shape))) @@ -1684,7 +1684,7 @@ fn rewrite_call_args(context: &RewriteContext, shape: Shape, one_line_width: usize, force_trailing_comma: bool) - -> Option { + -> Option<(bool, String)> { let items = itemize_list(context.codemap, args.iter(), ")", @@ -1717,12 +1717,12 @@ fn rewrite_call_args(context: &RewriteContext, shape.block() }; let rewrite = args.last().unwrap().rewrite(context, arg_shape); + swap(&mut item_vec[args.len() - 1].item, &mut orig_last); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); placeholder = Some(rewrite); - swap(&mut item_vec[args.len() - 1].item, &mut orig_last); item_vec[args.len() - 1].item = rewrite_first_line; } } @@ -1765,18 +1765,27 @@ fn rewrite_call_args(context: &RewriteContext, config: context.config, }; + let args_in_single_line = + item_vec + .iter() + .rev() + .skip(1) + .all(|item| item.item.as_ref().map_or(false, |s| !s.contains('\n'))); + match write_list(&item_vec, &fmt) { // If arguments do not fit in a single line and do not contain newline, // try to put it on the next line. Try this only when we are in block mode // and not rewriting macro. Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && !context.inside_macro && - (first_line_width(s) > one_line_width || + (!can_be_overflowed(context, args) && args.len() == 1 && s.contains('\n') || + first_line_width(s) > one_line_width || first_line_width(s) > context.config.fn_call_width()) => { fmt.trailing_separator = SeparatorTactic::Vertical; - write_list(&item_vec, &fmt) + fmt.tactic = DefinitiveListTactic::Vertical; + write_list(&item_vec, &fmt).map(|rw| (false, rw)) } - rewrite @ _ => rewrite, + rewrite @ _ => rewrite.map(|rw| (args_in_single_line && is_extendable(args), rw)), } } @@ -2091,7 +2100,7 @@ pub fn rewrite_tuple(context: &RewriteContext, return rewrite_tuple_type(context, items.iter().map(|x| &**x), span, shape); } - // We use the same rule as funcation call for rewriting tuple with multiple expressions. + // We use the same rule as funcation call for rewriting tuple. // 1 = "," rewrite_call_inner(context, &String::new(), @@ -2100,7 +2109,7 @@ pub fn rewrite_tuple(context: &RewriteContext, span, shape, items.len() == 1) - .ok() + .ok() } pub fn rewrite_unary_prefix(context: &RewriteContext, diff --git a/tests/source/configs-fn_call_style-block-trailing-comma.rs b/tests/source/configs-fn_call_style-block-trailing-comma.rs index 3f3d1dec2ea..6f613fb10bb 100644 --- a/tests/source/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/source/configs-fn_call_style-block-trailing-comma.rs @@ -4,4 +4,5 @@ // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo(oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); } diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 14207b5adb9..27f7ff67da9 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -191,6 +191,19 @@ fn combine_block() { }, ); + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); + Ok( some_function( lllllllllong_argument_one, @@ -226,6 +239,21 @@ fn combine_block() { long_argument_two, long_argument_three, )), + Some(x) => |x| { + let y = x + 1; + let z = y + 1; + z + }, + Some(x) => (1, 2, |x| { + let y = x + 1; + let z = y + 1; + z + }), + Some(x) => SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }, None => Ok(SomeStruct { f1: long_argument_one, f2: long_argument_two, diff --git a/tests/target/configs-fn_call_style-block-trailing-comma.rs b/tests/target/configs-fn_call_style-block-trailing-comma.rs index 3f3d1dec2ea..ebdf41d0e3b 100644 --- a/tests/target/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/target/configs-fn_call_style-block-trailing-comma.rs @@ -4,4 +4,7 @@ // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo( + oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), + ); } diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index af8238defe6..cd19d8bb838 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -36,7 +36,7 @@ fn issue1420() { r#" # Getting started ... - "# + "#, ) .running(waltz) } diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 6e4d2f109ac..b4d86ed82f5 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -102,7 +102,7 @@ fn arrays() { Weighted { weight: 1, item: 1 }, Weighted { weight: x, item: 2 }, Weighted { weight: 1, item: 3 }, - ] + ], ); let z = [ @@ -257,6 +257,11 @@ fn combine_block() { foo(param) }); + do_thing(x, (1, 2, 3, |param| { + action(); + foo(param) + })); + Ok(some_function( lllllllllong_argument_one, lllllllllong_argument_two, @@ -286,6 +291,21 @@ fn combine_block() { long_argument_two, long_argument_three, )), + Some(x) => |x| { + let y = x + 1; + let z = y + 1; + z + }, + Some(x) => (1, 2, |x| { + let y = x + 1; + let z = y + 1; + z + }), + Some(x) => SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }, None => Ok(SomeStruct { f1: long_argument_one, f2: long_argument_two, -- cgit 1.4.1-3-g733a5 From a83d4876e735a795b5f1eaec4687d55c079be6df Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 May 2017 22:12:37 +0900 Subject: Allow first child to stay on the same line with block parent --- src/chains.rs | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index fbc42a5d84e..92f4aa212a2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -99,10 +99,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let mut parent_shape = shape; - if is_block_expr(&parent, "\n") { - parent_shape = chain_indent(context, shape); - } + let parent_shape = if is_block_expr(context, &parent, "\n") { + match context.config.chain_indent() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape.block(), + } + } else { + shape + }; let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape)); let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); @@ -121,10 +125,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - (nested_shape, context.config.chain_indent() == IndentStyle::Visual || parent_rewrite.len() <= context.config.tab_spaces()) - } else if is_block_expr(&parent, &parent_rewrite) { - // The parent is a block, so align the rest of the chain with the closing - // brace. - (parent_shape, false) + } else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.chain_indent() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } } else if parent_rewrite_contains_newline { (chain_indent(context, parent_shape), false) } else { @@ -140,11 +148,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ..nested_shape }; let first_child_shape = if extend { - let first_child_shape = try_opt!(parent_shape - .offset_left(last_line_width(&parent_rewrite))); + let overhead = last_line_width(&parent_rewrite); + let offset = parent_rewrite.lines().rev().next().unwrap().trim().len(); match context.config.chain_indent() { - IndentStyle::Visual => first_child_shape, - IndentStyle::Block => first_child_shape.block(), + IndentStyle::Visual => try_opt!(parent_shape.offset_left(overhead)), + IndentStyle::Block => try_opt!(parent_shape.block().offset_left(offset)), } } else { other_child_shape @@ -224,8 +232,16 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - format!("\n{}", nested_shape.indent.to_string(context.config)) }; - let first_connector = if extend || subexpr_list.is_empty() || first_subexpr_is_try { + let first_connector = if subexpr_list.is_empty() { "" + } else if extend || first_subexpr_is_try { + // 1 = ";", being conservative here. + if last_line_width(&parent_rewrite) + first_line_width(&rewrites[0]) + 1 <= + context.config.max_width() { + "" + } else { + &*connector + } } else { &*connector }; @@ -277,8 +293,11 @@ fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. -fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { +fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { match expr.node { + ast::ExprKind::Call(..) => { + context.config.fn_call_style() == IndentStyle::Block && repr.contains('\n') + } ast::ExprKind::Struct(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | @@ -291,7 +310,7 @@ fn is_block_expr(expr: &ast::Expr, repr: &str) -> bool { ast::ExprKind::Paren(ref expr) | ast::ExprKind::Binary(_, _, ref expr) | ast::ExprKind::Index(_, ref expr) | - ast::ExprKind::Unary(_, ref expr) => is_block_expr(expr, repr), + ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), _ => false, } } -- cgit 1.4.1-3-g733a5 From cb4a6a24191f1a5535a6694b2310be5ac9d60bfe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 May 2017 22:12:52 +0900 Subject: Use correct width when rewriting chain --- src/chains.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 92f4aa212a2..7ab81aa7197 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -139,14 +139,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - (shape.block_indent(context.config.tab_spaces()), false) }; - let max_width = try_opt!((shape.width + shape.indent.width() + shape.offset) - .checked_sub(nested_shape.indent.width() + - nested_shape.offset)); + let other_child_shape = nested_shape.with_max_width(context.config); - let other_child_shape = Shape { - width: max_width, - ..nested_shape - }; let first_child_shape = if extend { let overhead = last_line_width(&parent_rewrite); let offset = parent_rewrite.lines().rev().next().unwrap().trim().len(); -- cgit 1.4.1-3-g733a5 From ec33121aafb081f33c78f062492cd61b77cef565 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 May 2017 22:13:29 +0900 Subject: Format source codes --- src/comment.rs | 13 +++--- src/expr.rs | 29 +++++++------- src/items.rs | 58 +++++++++++++-------------- src/types.rs | 61 ++++++++++++----------------- tests/target/chains.rs | 52 +++++++++++------------- tests/target/configs-fn_call_style-block.rs | 3 +- tests/target/file-lines-1.rs | 7 ++-- tests/target/file-lines-3.rs | 7 ++-- 8 files changed, 104 insertions(+), 126 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 22fa241677f..9591ffc4427 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -158,15 +158,14 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< // `*` in `/*`. let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); if let Some(fnw) = first_non_whitespace { - if l.as_bytes()[fnw] == '*' as u8 && fnw > 0 { - &l[fnw - 1..] - } else { - &l[fnw..] - } + if l.as_bytes()[fnw] == '*' as u8 && fnw > 0 { + &l[fnw - 1..] } else { - "" + &l[fnw..] } - .trim_right() + } else { + "" + }.trim_right() }) .collect(); Some(lines.join(&format!("\n{}", offset.to_string(config)))) diff --git a/src/expr.rs b/src/expr.rs index ad0d654175d..885577b304e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -316,8 +316,7 @@ pub fn rewrite_pair(lhs: &LHS, let lhs_budget = try_opt!(context .config .max_width() - .checked_sub(shape.used_width() + prefix.len() + - infix.len())); + .checked_sub(shape.used_width() + prefix.len() + infix.len())); let rhs_shape = match context.config.control_style() { Style::Default => { try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) @@ -853,8 +852,8 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = try_opt!(else_expr.rewrite(context, - Shape::legacy(new_width, Indent::empty()))); + let else_str = + try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); if if_str.contains('\n') || else_str.contains('\n') { return None; @@ -953,14 +952,13 @@ impl<'a> Rewrite for ControlFlow<'a> { }; // for event in event - let between_kwd_cond = - mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), - self.pat - .map_or(cond_span.lo, |p| if self.matcher.is_empty() { - p.span.lo - } else { - context.codemap.span_before(self.span, self.matcher.trim()) - })); + let between_kwd_cond = mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), + self.pat + .map_or(cond_span.lo, |p| if self.matcher.is_empty() { + p.span.lo + } else { + context.codemap.span_before(self.span, self.matcher.trim()) + })); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -1042,9 +1040,10 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); - let after_else = mk_sp(context.codemap.span_after(mk_sp(self.block.span.hi, - else_block.span.lo), - "else"), + let after_else = mk_sp(context + .codemap + .span_after(mk_sp(self.block.span.hi, else_block.span.lo), + "else"), else_block.span.lo); let after_else_comment = extract_comment(after_else, context, shape); diff --git a/src/items.rs b/src/items.rs index f98cf9507e1..bddb07263b8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1062,11 +1062,11 @@ fn format_tuple_struct(context: &RewriteContext, |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), context.codemap.span_after(span, "("), span.hi); - let body_budget = try_opt!(context - .config - .max_width() - .checked_sub(offset.block_only().width() + result.len() + - 3)); + let body_budget = + try_opt!(context + .config + .max_width() + .checked_sub(offset.block_only().width() + result.len() + 3)); let body = try_opt!(list_helper(items, // TODO budget is wrong in block case Shape::legacy(body_budget, item_indent), @@ -1126,8 +1126,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let shape = try_opt!(Shape::indented(generics_indent, context.config) - .sub_width(" =".len())); + let shape = try_opt!(Shape::indented(generics_indent, context.config).sub_width(" =".len())); let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); @@ -1310,28 +1309,30 @@ pub fn rewrite_associated_type(ident: ast::Ident, -> Option { let prefix = format!("type {}", ident); - let type_bounds_str = - if let Some(ty_param_bounds) = ty_param_bounds_opt { - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let bounds: &[_] = ty_param_bounds; - let bound_str = try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(context.config.max_width(), indent)) - }) - .intersperse(Some(joiner.to_string())) - .collect::>()); - if bounds.len() > 0 { - format!(": {}", bound_str) - } else { - String::new() - } + let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let bounds: &[_] = ty_param_bounds; + let bound_str = + try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(context.config.max_width(), + indent)) + }) + .intersperse(Some(joiner.to_string())) + .collect::>()); + if bounds.len() > 0 { + format!(": {}", bound_str) } else { String::new() - }; + } + } else { + String::new() + }; if let Some(ty) = ty_opt { let ty_str = try_opt!(ty.rewrite(context, @@ -1931,8 +1932,7 @@ fn compute_budgets_for_args(context: &RewriteContext, let multi_line_budget = try_opt!(context .config .max_width() - .checked_sub(indent.width() + result.len() + - 4)); + .checked_sub(indent.width() + result.len() + 4)); return Some((one_line_budget, multi_line_budget, indent + result.len() + 1)); } diff --git a/src/types.rs b/src/types.rs index 8f99be11d1a..688d6719441 100644 --- a/src/types.rs +++ b/src/types.rs @@ -364,12 +364,11 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { - let lifetime_str: String = - try_opt!(bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, shape)) - .intersperse(Some(", ".to_string())) - .collect()); + let lifetime_str: String = try_opt!(bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, shape)) + .intersperse(Some(", ".to_string())) + .collect()); let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", @@ -378,17 +377,13 @@ impl Rewrite for ast::WherePredicate { // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = - try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, - shape.indent + - used_width)) - }) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds_str: String = try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) + }) + .intersperse(Some(joiner.to_string())) + .collect()); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", @@ -406,17 +401,13 @@ impl Rewrite for ast::WherePredicate { }; let used_width = type_str.len() + colon.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = - try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, - shape.indent + - used_width)) - }) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds_str: String = try_opt!(bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) + }) + .intersperse(Some(joiner.to_string())) + .collect()); format!("{}{}{}", type_str, colon, bounds_str) } @@ -532,12 +523,11 @@ impl Rewrite for ast::TyParam { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; - let bounds: String = - try_opt!(self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .intersperse(Some(joiner.to_string())) - .collect()); + let bounds: String = try_opt!(self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .intersperse(Some(joiner.to_string())) + .collect()); result.push_str(&bounds); } @@ -612,8 +602,7 @@ impl Rewrite for ast::Ty { let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); let lt_str = try_opt!(lifetime.rewrite(context, Shape::legacy(lt_budget, - shape.indent + - 2 + + shape.indent + 2 + mut_len))); let lt_len = lt_str.len(); let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); diff --git a/tests/target/chains.rs b/tests/target/chains.rs index b8e47607b83..80b02482991 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -66,38 +66,34 @@ fn floaters() { }; let x = Foo { - field1: val1, - field2: val2, - } - .method_call() + field1: val1, + field2: val2, + }.method_call() .method_call(); let y = if cond { - val1 - } else { - val2 - } - .method_call(); + val1 + } else { + val2 + }.method_call(); { match x { PushParam => { // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone()); } } } if cond { - some(); - } else { - none(); - } - .bar() + some(); + } else { + none(); + }.bar() .baz(); Foo { x: val } @@ -108,21 +104,19 @@ fn floaters() { .quux(); Foo { - y: i_am_multi_line, - z: ok, - } - .baz(|| { - force(); - multiline(); - }) + y: i_am_multi_line, + z: ok, + }.baz(|| { + force(); + multiline(); + }) .quux(); a + match x { - true => "yay!", - false => "boo!", - } - .bar() + true => "yay!", + false => "boo!", + }.bar() } fn is_replaced_content() -> bool { diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index cd19d8bb838..8149269158c 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -37,8 +37,7 @@ fn issue1420() { # Getting started ... "#, - ) - .running(waltz) + ).running(waltz) } // #1563 diff --git a/tests/target/file-lines-1.rs b/tests/target/file-lines-1.rs index 250b25e6ea3..a43f314a242 100644 --- a/tests/target/file-lines-1.rs +++ b/tests/target/file-lines-1.rs @@ -2,10 +2,9 @@ fn floaters() { let x = Foo { - field1: val1, - field2: val2, - } - .method_call() + field1: val1, + field2: val2, + }.method_call() .method_call(); let y = if cond { diff --git a/tests/target/file-lines-3.rs b/tests/target/file-lines-3.rs index 6652d9c92cd..754c7c879b0 100644 --- a/tests/target/file-lines-3.rs +++ b/tests/target/file-lines-3.rs @@ -3,10 +3,9 @@ fn floaters() { let x = Foo { - field1: val1, - field2: val2, - } - .method_call() + field1: val1, + field2: val2, + }.method_call() .method_call(); let y = if cond { val1 } else { val2 }.method_call(); -- cgit 1.4.1-3-g733a5 From 92b54d6490fc638a136c07b42921ba7ff67743fa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 24 May 2017 00:06:23 +0900 Subject: Add heuristic when rewriting chain with a single child rustfmt splits chain into multiline when the length of chain exceeds `chain_one_line_max`. However, currenly this rule only applies when the chain has more than one child. This can lead to unexpected long chain if the parent is long. This commit adds heuristic that if the length of parent is longer than the half of `chain_one_line_max` we use multiline even if there is only a single child. --- src/chains.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 7ab81aa7197..5ea43708af3 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -155,10 +155,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - first_child_shape, other_child_shape); - let child_shape_iter = - Some(first_child_shape) - .into_iter() - .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); + let child_shape_iter = Some(first_child_shape) + .into_iter() + .chain(::std::iter::repeat(other_child_shape) + .take(subexpr_list.len() - 1)); let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) @@ -175,7 +175,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if rewrites.len() > 1 { true } else if rewrites.len() == 1 { - one_line_len > shape.width + parent_rewrite.len() > context.config.chain_one_line_max() / 2 } else { false } -- cgit 1.4.1-3-g733a5 From 04bb5d892978b868a953bce4153dde66e583c7f4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 24 May 2017 00:07:02 +0900 Subject: Format source codes --- src/expr.rs | 36 ++++++++++++++++++++++-------------- src/file_lines.rs | 3 ++- src/items.rs | 3 ++- src/lists.rs | 6 ++++-- src/macros.rs | 11 +++++------ src/modules.rs | 3 ++- src/string.rs | 3 ++- src/utils.rs | 3 ++- tests/system.rs | 9 ++++++--- 9 files changed, 47 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 885577b304e..29edb0a3e3f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -98,16 +98,20 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Tup(ref items) => rewrite_tuple(context, items, expr.span, shape), ast::ExprKind::While(ref cond, ref block, label) => { - ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape) + ControlFlow::new_while(None, cond, block, label, expr.span) + .rewrite(context, shape) } ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - ControlFlow::new_while(Some(pat), cond, block, label, expr.span).rewrite(context, shape) + ControlFlow::new_while(Some(pat), cond, block, label, expr.span) + .rewrite(context, shape) } ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, shape) + ControlFlow::new_for(pat, cond, block, label, expr.span) + .rewrite(context, shape) } ast::ExprKind::Loop(ref block, label) => { - ControlFlow::new_loop(block, label, expr.span).rewrite(context, shape) + ControlFlow::new_loop(block, label, expr.span) + .rewrite(context, shape) } ast::ExprKind::Block(ref block) => block.rewrite(context, shape), ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { @@ -175,11 +179,12 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str(context.snippet(expr.span), - context.config.max_width(), - shape) - }) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + .or_else(|| { + wrap_str(context.snippet(expr.span), + context.config.max_width(), + shape) + }) } ast::ExprKind::Ret(None) => { wrap_str("return".to_owned(), context.config.max_width(), shape) @@ -319,7 +324,8 @@ pub fn rewrite_pair(lhs: &LHS, .checked_sub(shape.used_width() + prefix.len() + infix.len())); let rhs_shape = match context.config.control_style() { Style::Default => { - try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) + try_opt!(shape.sub_width(suffix.len() + prefix.len())) + .visual_indent(prefix.len()) } Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces())), }; @@ -510,7 +516,8 @@ fn rewrite_closure(capture: ast::CaptureBy, // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, shape) + 1; - let body_shape = try_opt!(shape.sub_width(extra_offset)).add_offset(extra_offset); + let body_shape = try_opt!(shape.sub_width(extra_offset)) + .add_offset(extra_offset); if let ast::ExprKind::Block(ref block) = body.node { // The body of the closure is an empty block. @@ -852,8 +859,8 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = - try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); + let else_str = try_opt!(else_expr.rewrite(context, + Shape::legacy(new_width, Indent::empty()))); if if_str.contains('\n') || else_str.contains('\n') { return None; @@ -1790,11 +1797,11 @@ fn rewrite_call_args(context: &RewriteContext, fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bool { match args.last().map(|x| &x.node) { - Some(&ast::ExprKind::Block(..)) | Some(&ast::ExprKind::Match(..)) => { (context.config.fn_call_style() == IndentStyle::Block && args.len() == 1) || (context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1) } + Some(&ast::ExprKind::Block(..)) | Some(&ast::ExprKind::Closure(..)) => { context.config.fn_call_style() == IndentStyle::Block || context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1 @@ -1821,6 +1828,7 @@ fn is_extendable(args: &[ptr::P]) -> bool { } } else if args.len() > 1 { match args[args.len() - 1].node { + ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) | ast::ExprKind::Tup(..) => true, _ => false, diff --git a/src/file_lines.rs b/src/file_lines.rs index 1e151a57838..9256f853f80 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -126,7 +126,8 @@ impl FileLines { Some(ref map) => map, }; - match canonicalize_path_string(file_name).and_then(|file| map.get_vec(&file).ok_or(())) { + match canonicalize_path_string(file_name) + .and_then(|file| map.get_vec(&file).ok_or(())) { Ok(ranges) => ranges.iter().any(f), Err(_) => false, } diff --git a/src/items.rs b/src/items.rs index bddb07263b8..e21abb9117f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1126,7 +1126,8 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let shape = try_opt!(Shape::indented(generics_indent, context.config).sub_width(" =".len())); + let shape = try_opt!(Shape::indented(generics_indent, context.config) + .sub_width(" =".len())); let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); diff --git a/src/lists.rs b/src/lists.rs index 3448f8a446a..adc18c14581 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -430,7 +430,8 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let post_snippet_trimmed = if post_snippet.starts_with(',') { post_snippet[1..].trim_matches(white_space) } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + post_snippet[..(post_snippet.len() - 1)] + .trim_matches(white_space) } else { post_snippet }; @@ -528,7 +529,8 @@ pub fn struct_lit_shape(shape: Shape, -> Option<(Option, Shape)> { let v_shape = match context.config.struct_lit_style() { IndentStyle::Visual => { - try_opt!(try_opt!(shape.shrink_left(prefix_width)).sub_width(suffix_width)) + try_opt!(try_opt!(shape.shrink_left(prefix_width)) + .sub_width(suffix_width)) } IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); diff --git a/src/macros.rs b/src/macros.rs index a5ead34c9ec..30786de6d59 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -172,12 +172,11 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map(|rw| { - match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - } - }) + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape) + .map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) } MacroStyle::Brackets => { let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); diff --git a/src/modules.rs b/src/modules.rs index 3d2c3b0ac9f..5e09a311dcb 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -68,7 +68,8 @@ fn module_file(id: ast::Ident, return path; } - match parser::Parser::default_submod_path(id, dir_path, codemap).result { + match parser::Parser::default_submod_path(id, dir_path, codemap) + .result { Ok(parser::ModulePathSuccess { path, .. }) => path, Err(_) => panic!("Couldn't find module {}", id), } diff --git a/src/string.rs b/src/string.rs index 365d205aef1..17c6533f7a0 100644 --- a/src/string.rs +++ b/src/string.rs @@ -35,7 +35,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); let stripped_str = re.replace_all(orig, "$1"); - let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); + let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false) + .collect::>(); let shape = fmt.shape.visual_indent(0); let indent = shape.indent.to_string(fmt.config); let punctuation = ":,;."; diff --git a/src/utils.rs b/src/utils.rs index 664d538fbb9..ded35d04196 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -334,7 +334,8 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option Option { - wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned) + wrap_str(self, context.config.max_width(), shape) + .map(ToOwned::to_owned) } } diff --git a/tests/system.rs b/tests/system.rs index 58e44ee5381..70c8033da6c 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -55,7 +55,8 @@ fn system_tests() { // the only difference is the coverage mode #[test] fn coverage_tests() { - let files = fs::read_dir("tests/coverage/source").expect("Couldn't read source dir"); + let files = fs::read_dir("tests/coverage/source") + .expect("Couldn't read source dir"); let files = files.map(get_path_string); let (_reports, count, fails) = check_files(files); @@ -82,7 +83,8 @@ fn assert_output(source: &str, expected_filename: &str) { let _ = filemap::write_all_files(&file_map, &mut out, &config); let output = String::from_utf8(out).unwrap(); - let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); + let mut expected_file = fs::File::open(&expected_filename) + .expect("Couldn't open target"); let mut expected_text = String::new(); expected_file .read_to_string(&mut expected_text) @@ -277,7 +279,8 @@ fn get_config(config_file: Option<&str>) -> Config { } }; - let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); + let mut def_config_file = fs::File::open(config_file_name) + .expect("Couldn't open config"); let mut def_config = String::new(); def_config_file .read_to_string(&mut def_config) -- cgit 1.4.1-3-g733a5 From e3eec4469092b553a2c27db0a2e80856369e4d01 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 24 May 2017 01:18:15 +0900 Subject: Return original snippet when macro contains invalid syntax --- src/macros.rs | 4 ++-- tests/source/macros.rs | 5 +++++ tests/target/macros.rs | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index a5ead34c9ec..49fd142095f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -113,14 +113,14 @@ pub fn rewrite_macro(mac: &ast::Mac, Ok(expr) => { // Recovered errors. if context.parse_session.span_diagnostic.has_errors() { - return None; + return Some(context.snippet(mac.span)); } expr } Err(mut e) => { e.cancel(); - return None; + return Some(context.snippet(mac.span)); } }; diff --git a/tests/source/macros.rs b/tests/source/macros.rs index b83f74c47d5..85ec41ddb0f 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -78,6 +78,11 @@ fn main() { // comment not function like ); + + // #1577 + let json = json!({ + "foo": "bar", + }); } impl X { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index c19bb242ca3..a1fa3f74368 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -83,6 +83,11 @@ fn main() { // comment not function like ); + + // #1577 + let json = json!({ + "foo": "bar", + }); } impl X { -- cgit 1.4.1-3-g733a5 From c8ad521c9f4d45935cc24c87772f00f6df360152 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 06:10:00 +0900 Subject: Decide whether args fit in a single line inside rewrite_call_args --- src/expr.rs | 29 ++++++++++++++++------------- tests/source/configs-fn_call_style-block.rs | 14 ++++++++++++++ tests/target/configs-fn_call_style-block.rs | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 29edb0a3e3f..bb9e55e4f16 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1673,15 +1673,9 @@ fn rewrite_call_inner(context: &RewriteContext, one_line_width, force_trailing_comma) .ok_or(Ordering::Less)?; - let arg_one_line_budget = min(one_line_width, context.config.fn_call_width()); Ok(format!("{}{}", callee_str, - wrap_args_with_parens(context, - &list_str, - extendable, - arg_one_line_budget, - shape, - nested_shape))) + wrap_args_with_parens(context, &list_str, extendable, shape, nested_shape))) } fn rewrite_call_args(context: &RewriteContext, @@ -1771,12 +1765,16 @@ fn rewrite_call_args(context: &RewriteContext, config: context.config, }; - let args_in_single_line = + let almost_no_newline = item_vec .iter() .rev() .skip(1) .all(|item| item.item.as_ref().map_or(false, |s| !s.contains('\n'))); + let extendable = almost_no_newline && + item_vec.iter().fold(0, |acc, item| { + acc + item.item.as_ref().map_or(0, |s| 2 + first_line_width(s)) + }) <= min(one_line_width, context.config.fn_call_width()) + 2; match write_list(&item_vec, &fmt) { // If arguments do not fit in a single line and do not contain newline, @@ -1791,7 +1789,15 @@ fn rewrite_call_args(context: &RewriteContext, fmt.tactic = DefinitiveListTactic::Vertical; write_list(&item_vec, &fmt).map(|rw| (false, rw)) } - rewrite @ _ => rewrite.map(|rw| (args_in_single_line && is_extendable(args), rw)), + rewrite @ _ => { + rewrite.map(|rw| { + (extendable && + rw.chars() + .last() + .map_or(true, |c| force_trailing_comma || c != ','), + rw) + }) + } } } @@ -1841,14 +1847,11 @@ fn is_extendable(args: &[ptr::P]) -> bool { fn wrap_args_with_parens(context: &RewriteContext, args_str: &str, is_extendable: bool, - one_line_budget: usize, shape: Shape, nested_shape: Shape) -> String { if context.config.fn_call_style() == IndentStyle::Visual || - (context.inside_macro && !args_str.contains('\n')) || - ((is_extendable || !args_str.contains('\n')) && - first_line_width(&args_str) <= one_line_budget) { + (context.inside_macro && !args_str.contains('\n')) || is_extendable { if context.config.spaces_within_parens() && args_str.len() > 0 { format!("( {} )", args_str) } else { diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 6708966fa69..6b5f00a9241 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -96,3 +96,17 @@ impl Cursor { }); } } + +fn issue1581() { + bootstrap.checks.register( + "PERSISTED_LOCATIONS", + move || if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + }, + ); +} diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index 8149269158c..c50eb5bc8da 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -106,3 +106,17 @@ impl Cursor { }); } } + +fn issue1581() { + bootstrap.checks.register( + "PERSISTED_LOCATIONS", + move || if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + }, + ); +} -- cgit 1.4.1-3-g733a5 From 80f3b3c9c415d55b01446476d2ef2e02ce15ae0d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 25 May 2017 15:59:06 +1200 Subject: Remove multimap dep --- Cargo.lock | 49 +++++++++++++++-------------------- Cargo.toml | 1 - src/file_lines.rs | 76 +++++++++++++++++++++++++++++++------------------------ src/lib.rs | 1 - 4 files changed, 64 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index fc82d6570ab..688c29db4b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,12 +7,11 @@ dependencies = [ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -58,7 +57,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -90,7 +89,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -103,14 +102,9 @@ name = "memchr" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "multimap" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num-traits" version = "0.1.37" @@ -123,19 +117,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -154,12 +148,12 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -184,7 +178,7 @@ dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -218,7 +212,7 @@ name = "syntex_errors" version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -261,7 +255,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -278,7 +272,7 @@ name = "toml" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -340,18 +334,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" +"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" +"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" -"checksum serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "38a3db3a5757f68069aba764b793823ea9fb9717c42c016f8903f8add50f508a" -"checksum serde_derive 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e46ef71ee001a4279a4513e79a6ebbb59da3a4987bf77a6df2e5534cd6f21d82" +"checksum serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c0c3d79316a6051231925504f6ef893d45088e8823c77a8331a3dcf427ee9087" +"checksum serde_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0019cd5b9f0529a1a0e145a912e9a2d60c325c58f7f260fc36c71976e9d76aee" "checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" diff --git a/Cargo.toml b/Cargo.toml index 1dd674204c8..414c45c887a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,6 @@ log = "0.3" env_logger = "0.4" getopts = "0.2" itertools = "0.5.8" -multimap = "0.3" [build-dependencies] walkdir = "1.0.3" diff --git a/src/file_lines.rs b/src/file_lines.rs index 9256f853f80..9de427781fe 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -11,18 +11,17 @@ //! This module contains types and functions to support formatting specific line ranges. use std::{cmp, iter, path, str}; +use std::collections::HashMap; -use itertools::Itertools; -use multimap::MultiMap; use serde_json as json; use codemap::LineRange; /// A range that is inclusive of both ends. -#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] struct Range { - pub lo: usize, - pub hi: usize, + lo: usize, + hi: usize, } impl<'a> From<&'a LineRange> for Range { @@ -82,18 +81,30 @@ impl Range { /// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all /// lines in all files. #[derive(Clone, Debug, Default)] -pub struct FileLines(Option>); +pub struct FileLines(Option>>); /// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, /// and ordered by their start point. -fn normalize_ranges(map: &mut MultiMap) { - for (_, ranges) in map.iter_all_mut() { - ranges.sort_by_key(|x| x.lo); - let merged = ranges - .drain(..) - .coalesce(|x, y| x.merge(y).ok_or((x, y))) - .collect(); - *ranges = merged; +fn normalize_ranges(ranges: &mut HashMap>) { + for ranges in ranges.values_mut() { + ranges.sort(); + let mut result = vec![]; + { + let mut iter = ranges.into_iter().peekable(); + while let Some(next) = iter.next() { + let mut next = next.clone(); + while let Some(&&mut peek) = iter.peek() { + if let Some(merged) = next.merge(peek) { + iter.next().unwrap(); + next = merged; + } else { + break; + } + } + result.push(next) + } + } + *ranges = result; } } @@ -103,16 +114,14 @@ impl FileLines { FileLines(None) } - /// Creates a `FileLines` from a `MultiMap`, ensuring that the invariants hold. - fn from_multimap(map: MultiMap) -> FileLines { - let mut map = map; - normalize_ranges(&mut map); - FileLines(Some(map)) + fn from_ranges(mut ranges: HashMap>) -> FileLines { + normalize_ranges(&mut ranges); + FileLines(Some(ranges)) } /// Returns an iterator over the files contained in `self`. pub fn files(&self) -> Files { - Files(self.0.as_ref().map(MultiMap::keys)) + Files(self.0.as_ref().map(|m| m.keys())) } /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in @@ -127,9 +136,9 @@ impl FileLines { }; match canonicalize_path_string(file_name) - .and_then(|file| map.get_vec(&file).ok_or(())) { - Ok(ranges) => ranges.iter().any(f), - Err(_) => false, + .and_then(|file| map.get(&file)) { + Some(ranges) => ranges.iter().any(f), + None => false, } } @@ -165,14 +174,14 @@ impl<'a> iter::Iterator for Files<'a> { } } -fn canonicalize_path_string(s: &str) -> Result { +fn canonicalize_path_string(s: &str) -> Option { if s == "stdin" { - return Ok(s.to_string()); + return Some(s.to_string()); } match path::PathBuf::from(s).canonicalize() { - Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()).ok_or(()), - _ => Err(()), + Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()), + _ => None, } } @@ -182,10 +191,12 @@ impl str::FromStr for FileLines { fn from_str(s: &str) -> Result { let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; - let m = v.into_iter() - .map(JsonSpan::into_tuple) - .collect::>()?; - Ok(FileLines::from_multimap(m)) + let mut m = HashMap::new(); + for js in v.into_iter() { + let (s, r) = JsonSpan::into_tuple(js)?; + m.entry(s).or_insert(vec![]).push(r); + } + Ok(FileLines::from_ranges(m)) } } @@ -197,11 +208,10 @@ struct JsonSpan { } impl JsonSpan { - // To allow `collect()`ing into a `MultiMap`. fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; let canonical = canonicalize_path_string(&self.file) - .map_err(|_| format!("Can't canonicalize {}", &self.file))?; + .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; Ok((canonical, Range::new(lo, hi))) } } diff --git a/src/lib.rs b/src/lib.rs index f31f3c0c3ee..477474df148 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,6 @@ extern crate regex; extern crate diff; extern crate term; extern crate itertools; -extern crate multimap; use errors::{Handler, DiagnosticBuilder}; use errors::emitter::{ColorConfig, EmitterWriter}; -- cgit 1.4.1-3-g733a5 From 393ba2731168a22d947edb6f1fadc0644e1a424d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 25 May 2017 16:23:07 +1200 Subject: Remove dependency on Itertools --- Cargo.lock | 16 ---------------- Cargo.toml | 1 - src/chains.rs | 7 ++++--- src/items.rs | 21 ++++----------------- src/lib.rs | 1 - src/macros.rs | 18 +++++++++++------- src/types.rs | 25 ++++++++++++------------- src/utils.rs | 6 ++---- 8 files changed, 33 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 688c29db4b8..4a2e7a3b843 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,6 @@ dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -46,11 +45,6 @@ name = "dtoa" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "either" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "env_logger" version = "0.4.2" @@ -65,14 +59,6 @@ name = "getopts" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "itertools" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.3.1" @@ -328,10 +314,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" diff --git a/Cargo.toml b/Cargo.toml index 414c45c887a..d3016fbc490 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,6 @@ syntex_errors = "0.58" log = "0.3" env_logger = "0.4" getopts = "0.2" -itertools = "0.5.8" [build-dependencies] walkdir = "1.0.3" diff --git a/src/chains.rs b/src/chains.rs index 5ea43708af3..285263932d3 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -160,9 +160,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .chain(::std::iter::repeat(other_child_shape) .take(subexpr_list.len() - 1)); let iter = subexpr_list.iter().rev().zip(child_shape_iter); - let mut rewrites = - try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) - .collect::>>()); + let mut rewrites = try_opt!(iter.map(|(e, shape)| { + rewrite_chain_subexpr(e, total_span, context, shape) + }) + .collect::>>()); // Total of all items excluding the last. let almost_total = rewrites[..rewrites.len() - 1] diff --git a/src/items.rs b/src/items.rs index e21abb9117f..88e663403d6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,6 @@ use comment::{FindUncommented, contains_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity}; -use itertools::Itertools; use syntax::{ast, abi, codemap, ptr, symbol}; use syntax::codemap::{Span, BytePos, mk_sp}; @@ -1324,8 +1323,8 @@ pub fn rewrite_associated_type(ident: ast::Ident, Shape::legacy(context.config.max_width(), indent)) }) - .intersperse(Some(joiner.to_string())) - .collect::>()); + .collect::>>()) + .join(joiner); if bounds.len() > 0 { format!(": {}", bound_str) } else { @@ -2041,8 +2040,8 @@ fn rewrite_trait_bounds(context: &RewriteContext, let bound_str = try_opt!(bounds .iter() .map(|ty_bound| ty_bound.rewrite(&context, shape)) - .intersperse(Some(joiner.to_string())) - .collect::>()); + .collect::>>()) + .join(joiner); let mut result = String::new(); result.push_str(": "); @@ -2050,18 +2049,6 @@ fn rewrite_trait_bounds(context: &RewriteContext, Some(result) } -// fn reflow_list_node_with_rule( -// &self, -// node: &CompoundNode, -// rule: &Rule, -// args: &[Arg], -// shape: &Shape -// ) -> Result -// where -// T: Foo, -// { - - fn rewrite_where_clause_rfc_style(context: &RewriteContext, where_clause: &ast::WhereClause, shape: Shape, diff --git a/src/lib.rs b/src/lib.rs index 477474df148..49125e6ff9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,6 @@ extern crate unicode_segmentation; extern crate regex; extern crate diff; extern crate term; -extern crate itertools; use errors::{Handler, DiagnosticBuilder}; use errors::emitter::{ColorConfig, EmitterWriter}; diff --git a/src/macros.rs b/src/macros.rs index 0f72f180c51..c46ed3d88c7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -198,13 +198,17 @@ pub fn rewrite_macro(mac: &ast::Mac, } else { // Format macro invocation as array literal. let rewrite = - try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context.codemap.span_after(mac.span, - original_style - .opener()), - mac.span.hi - BytePos(1)), - context, - mac_shape)); + try_opt!(rewrite_array( + expr_vec.iter().map(|x| &**x), + mk_sp( + context + .codemap + .span_after(mac.span, original_style.opener()), + mac.span.hi - BytePos(1) + ), + context, + mac_shape + )); Some(format!("{}{}", macro_name, rewrite)) } diff --git a/src/types.rs b/src/types.rs index 688d6719441..82f68976225 100644 --- a/src/types.rs +++ b/src/types.rs @@ -24,7 +24,6 @@ use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; use config::TypeDensity; -use itertools::Itertools; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -367,8 +366,8 @@ impl Rewrite for ast::WherePredicate { let lifetime_str: String = try_opt!(bound_lifetimes .iter() .map(|lt| lt.rewrite(context, shape)) - .intersperse(Some(", ".to_string())) - .collect()); + .collect::>>()) + .join(", "); let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", @@ -382,8 +381,8 @@ impl Rewrite for ast::WherePredicate { .map(|ty_bound| { ty_bound.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) }) - .intersperse(Some(joiner.to_string())) - .collect()); + .collect::>>()) + .join(joiner); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", @@ -406,8 +405,8 @@ impl Rewrite for ast::WherePredicate { .map(|ty_bound| { ty_bound.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) }) - .intersperse(Some(joiner.to_string())) - .collect()); + .collect::>>()) + .join(joiner); format!("{}{}{}", type_str, colon, bounds_str) } @@ -526,8 +525,8 @@ impl Rewrite for ast::TyParam { let bounds: String = try_opt!(self.bounds .iter() .map(|ty_bound| ty_bound.rewrite(context, shape)) - .intersperse(Some(joiner.to_string())) - .collect()); + .collect::>>()) + .join(joiner); result.push_str(&bounds); } @@ -554,8 +553,8 @@ impl Rewrite for ast::PolyTraitRef { let lifetime_str: String = try_opt!(self.bound_lifetimes .iter() .map(|lt| lt.rewrite(context, shape)) - .intersperse(Some(", ".to_string())) - .collect()); + .collect::>>()) + .join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; @@ -701,8 +700,8 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, l.rewrite(context, Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) }) - .intersperse(Some(", ".to_string())) - .collect::>())); + .collect::>>()) + .join(", ")); result.push_str("> "); } diff --git a/src/utils.rs b/src/utils.rs index ded35d04196..1192608c24a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -11,8 +11,6 @@ use std::borrow::Cow; use std::cmp::Ordering; -use itertools::Itertools; - use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path}; use syntax::codemap::BytePos; @@ -44,14 +42,14 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { Visibility::Crate(_) => Cow::from("pub(crate) "), Visibility::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.as_str()); + let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); if path.is_global() { segments_iter .next() .expect("Non-global path in pub(restricted)?"); } - Cow::from(format!("pub({}) ", segments_iter.join("::"))) + Cow::from(format!("pub({}) ", segments_iter.collect::>().join("::"))) } } } -- cgit 1.4.1-3-g733a5 From a7b8dcc60d50f9be0785ec5a572f813691af2032 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 25 May 2017 16:39:44 +1200 Subject: Simplify --version info --- Cargo.lock | 22 -------------------- Cargo.toml | 3 --- build.rs | 61 ++++++++++++++++++++++++------------------------------ src/bin/rustfmt.rs | 16 +++----------- 4 files changed, 30 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 4a2e7a3b843..2d34a8f7cea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,6 @@ dependencies = [ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -123,15 +122,6 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "same-file" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "serde" version = "1.0.7" @@ -289,16 +279,6 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "walkdir" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "winapi" version = "0.2.8" @@ -326,7 +306,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c0c3d79316a6051231925504f6ef893d45088e8823c77a8331a3dcf427ee9087" "checksum serde_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0019cd5b9f0529a1a0e145a912e9a2d60c325c58f7f260fc36c71976e9d76aee" "checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" @@ -346,6 +325,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index d3016fbc490..4f5eaa7f018 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,9 +34,6 @@ log = "0.3" env_logger = "0.4" getopts = "0.2" -[build-dependencies] -walkdir = "1.0.3" - [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/build.rs b/build.rs index aca96774d06..42d9330f75d 100644 --- a/build.rs +++ b/build.rs @@ -1,57 +1,50 @@ -extern crate walkdir; +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. use std::env; use std::fs::File; use std::io::Write; -use std::path::Path; +use std::path::PathBuf; use std::process::Command; -use walkdir::WalkDir; fn main() { - let out_dir = env::var("OUT_DIR").unwrap(); - let dest_path = Path::new(&out_dir).join("git_info.rs"); - let mut f = File::create(&dest_path).unwrap(); + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - writeln!(f, - "const COMMIT_HASH: Option<&'static str> = {:?};", - git_head_sha1()) - .unwrap(); - writeln!(f, - "const WORKTREE_CLEAN: Option = {:?};", - git_tree_is_clean()) + File::create(out_dir.join("commit-info.txt")) + .unwrap() + .write_all(commit_info().as_bytes()) .unwrap(); +} - // cargo:rerun-if-changed requires one entry per individual file. - for entry in WalkDir::new("src") { - let entry = entry.unwrap(); - println!("cargo:rerun-if-changed={}", entry.path().display()); +// Try to get hash and date of the last commit on a best effort basis. If anything goes wrong +// (git not installed or if this is not a git repository) just return an empty string. +fn commit_info() -> String { + match (commit_hash(), commit_date()) { + (Some(hash), Some(date)) => format!(" ({} {})", hash.trim_right(), date), + _ => String::new(), } } -// Returns `None` if git is not available. -fn git_head_sha1() -> Option { +fn commit_hash() -> Option { Command::new("git") - .arg("rev-parse") - .arg("--short") - .arg("HEAD") + .args(&["rev-parse", "--short", "HEAD"]) .output() .ok() - .and_then(|o| String::from_utf8(o.stdout).ok()) - .map(|mut s| { - let len = s.trim_right().len(); - s.truncate(len); - s - }) + .and_then(|r| String::from_utf8(r.stdout).ok()) } -// Returns `None` if git is not available. -fn git_tree_is_clean() -> Option { +fn commit_date() -> Option { Command::new("git") - .arg("status") - .arg("--porcelain") - .arg("--untracked-files=no") + .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) .output() .ok() - .map(|o| o.stdout.is_empty()) + .and_then(|r| String::from_utf8(r.stdout).ok()) } diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 73c4439ba29..72946b8374a 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -29,12 +29,6 @@ use std::str::FromStr; use getopts::{Matches, Options}; -// Include git commit hash and worktree status; contents are like -// const COMMIT_HASH: Option<&'static str> = Some("c31a366"); -// const WORKTREE_CLEAN: Option = Some(false); -// with `None` if running git failed, eg if it is not installed. -include!(concat!(env!("OUT_DIR"), "/git_info.rs")); - type FmtError = Box; type FmtResult = std::result::Result; @@ -365,13 +359,9 @@ fn print_usage(opts: &Options, reason: &str) { } fn print_version() { - println!("{} ({}{})", - option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), - COMMIT_HASH.unwrap_or("git commit unavailable"), - match WORKTREE_CLEAN { - Some(false) => " worktree dirty", - _ => "", - }); + println!("{}-nightly{}", + env!("CARGO_PKG_VERSION"), + include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))) } fn determine_operation(matches: &Matches) -> FmtResult { -- cgit 1.4.1-3-g733a5 From 857747c9caa561c83ee32b598a172bcccdd134b2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 09:24:04 +0900 Subject: Consider trailing try operations when counting almost_total --- src/chains.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 285263932d3..c61ee2267e8 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -97,6 +97,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if chain_only_try(&subexpr_list) { return rewrite_try(&parent, subexpr_list.len(), context, shape); } + let trailing_try_num = subexpr_list + .iter() + .take_while(|e| { + match e.node { + ast::ExprKind::Try(..) => true, + _ => false, + } + }) + .count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent, "\n") { @@ -166,7 +175,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .collect::>>()); // Total of all items excluding the last. - let almost_total = rewrites[..rewrites.len() - 1] + let almost_total = rewrites[..rewrites.len() - (1 + trailing_try_num)] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + @@ -195,7 +204,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let mut fits_single_line = !veto_single_line && almost_total <= shape.width; if fits_single_line { let len = rewrites.len(); - let (init, last) = rewrites.split_at_mut(len - 1); + let (init, last) = rewrites.split_at_mut(len - (1 + trailing_try_num)); fits_single_line = init.iter().all(|s| !s.contains('\n')); if fits_single_line { -- cgit 1.4.1-3-g733a5 From 6aed4177387f7c376059c42268801b64915c8316 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 09:32:14 +0900 Subject: Disallow single line chain when the line exceeds the given budget --- src/chains.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c61ee2267e8..cacc0624882 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -181,7 +181,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); - let veto_single_line = if one_line_len > context.config.chain_one_line_max() { + let veto_single_line = if one_line_len > context.config.chain_one_line_max() || + one_line_len > shape.width { if rewrites.len() > 1 { true } else if rewrites.len() == 1 { -- cgit 1.4.1-3-g733a5 From 635fdc662a376ba98a25e15056b27319ac97628d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 09:34:10 +0900 Subject: Format source codes --- src/chains.rs | 8 +++----- src/patterns.rs | 8 ++++---- tests/target/closure.rs | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index cacc0624882..e69731c5dc4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -99,11 +99,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } let trailing_try_num = subexpr_list .iter() - .take_while(|e| { - match e.node { - ast::ExprKind::Try(..) => true, - _ => false, - } + .take_while(|e| match e.node { + ast::ExprKind::Try(..) => true, + _ => false, }) .count(); diff --git a/src/patterns.rs b/src/patterns.rs index afea0ddb299..312f2b0ace9 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -39,10 +39,10 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!(shape.width.checked_sub(prefix.len() + - mut_infix.len() + - id_str.len() + - 3)); + let width = + try_opt!(shape.width.checked_sub(prefix.len() + mut_infix.len() + + id_str.len() + + 3)); format!(" @ {}", try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index febbb0a46a2..143f59b5962 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -144,9 +144,9 @@ fn issue470() { impl Foo { pub fn bar(&self) { Some(SomeType { - push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { - Ok(f) - })), + push_closure_out_to_100_chars: iter(otherwise_it_works_ok + .into_iter() + .map(|f| Ok(f))), }) } } -- cgit 1.4.1-3-g733a5 From 4d6e385f098930a572fd6ddfae972f2ada076002 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 13:35:09 +0900 Subject: Refactoring: introduce one_line_budget --- src/expr.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bb9e55e4f16..07f1c80fc3d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1765,6 +1765,7 @@ fn rewrite_call_args(context: &RewriteContext, config: context.config, }; + let one_line_budget = min(one_line_width, context.config.fn_call_width()); let almost_no_newline = item_vec .iter() @@ -1774,7 +1775,7 @@ fn rewrite_call_args(context: &RewriteContext, let extendable = almost_no_newline && item_vec.iter().fold(0, |acc, item| { acc + item.item.as_ref().map_or(0, |s| 2 + first_line_width(s)) - }) <= min(one_line_width, context.config.fn_call_width()) + 2; + }) <= one_line_budget + 2; match write_list(&item_vec, &fmt) { // If arguments do not fit in a single line and do not contain newline, @@ -1782,9 +1783,9 @@ fn rewrite_call_args(context: &RewriteContext, // and not rewriting macro. Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && !context.inside_macro && - (!can_be_overflowed(context, args) && args.len() == 1 && s.contains('\n') || - first_line_width(s) > one_line_width || - first_line_width(s) > context.config.fn_call_width()) => { + ((!can_be_overflowed(context, args) && args.len() == 1 && + s.contains('\n')) || + first_line_width(s) > one_line_budget) => { fmt.trailing_separator = SeparatorTactic::Vertical; fmt.tactic = DefinitiveListTactic::Vertical; write_list(&item_vec, &fmt).map(|rw| (false, rw)) -- cgit 1.4.1-3-g733a5 From c69608a7e05eef2da99081118bf20da87733b746 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 15:47:50 +0900 Subject: Allow the last elem in chain to overflow --- src/chains.rs | 48 +++++++++++++++++++++++++++-- tests/source/configs-fn_call_style-block.rs | 3 ++ tests/target/configs-fn_call_style-block.rs | 6 ++++ 3 files changed, 54 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index e69731c5dc4..e5450aa687e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -83,6 +83,7 @@ use expr::rewrite_call; use config::IndentStyle; use macros::convert_try_mac; +use std::cmp::min; use std::iter; use syntax::{ast, ptr}; use syntax::codemap::{mk_sp, Span}; @@ -173,14 +174,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .collect::>>()); // Total of all items excluding the last. - let almost_total = rewrites[..rewrites.len() - (1 + trailing_try_num)] + let last_non_try_index = rewrites.len() - (1 + trailing_try_num); + let almost_total = rewrites[..last_non_try_index] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); - let veto_single_line = if one_line_len > context.config.chain_one_line_max() || - one_line_len > shape.width { + let one_line_budget = min(shape.width, context.config.chain_one_line_max()); + let veto_single_line = if one_line_len > one_line_budget { if rewrites.len() > 1 { true } else if rewrites.len() == 1 { @@ -227,6 +229,25 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } } + // Try overflowing the last element if we are using block indent. + if !fits_single_line && context.config.fn_call_style() == IndentStyle::Block { + let (init, last) = rewrites.split_at_mut(last_non_try_index); + let almost_single_line = init.iter().all(|s| !s.contains('\n')); + if almost_single_line { + let overflow_shape = Shape { + width: one_line_budget, + ..parent_shape + }; + fits_single_line = rewrite_last_child_with_overflow(context, + &subexpr_list[trailing_try_num], + overflow_shape, + total_span, + almost_total, + one_line_budget, + &mut last[0]); + } + } + let connector = if fits_single_line && !parent_rewrite_contains_newline { // Yay, we can put everything on one line. String::new() @@ -266,6 +287,27 @@ fn chain_only_try(exprs: &[ast::Expr]) -> bool { }) } +// Try to rewrite and replace the last non-try child. Return `true` if +// replacing succeeds. +fn rewrite_last_child_with_overflow(context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, + span: Span, + almost_total: usize, + one_line_budget: usize, + last_child: &mut String) + -> bool { + if let Some(shape) = shape.shrink_left(almost_total) { + if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) { + if almost_total + first_line_width(rw) <= one_line_budget { + ::std::mem::swap(last_child, rw); + return true; + } + } + } + false +} + pub fn rewrite_try(expr: &ast::Expr, try_count: usize, context: &RewriteContext, diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 6b5f00a9241..c4fa4aa5f4c 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -5,6 +5,9 @@ fn main() { lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); // #1501 let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); + + // chain + let x = yooooooooooooo.fooooooooooooooo.baaaaaaaaaaaaar(hello, world); } // #1521 diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index c50eb5bc8da..2b2dbef7c61 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -16,6 +16,12 @@ fn main() { let hyper = Arc::new(Client::with_connector( HttpsConnector::new(TlsClient::new()), )); + + // chain + let x = yooooooooooooo.fooooooooooooooo.baaaaaaaaaaaaar( + hello, + world, + ); } // #1521 -- cgit 1.4.1-3-g733a5 From 2580d7a3107b99fb7cc43dd19d833396f2522e9f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 16:07:56 +0900 Subject: Add chain_split_single_child option --- Configurations.md | 22 ++++++++++++++++++++++ src/chains.rs | 10 +++++----- .../configs-chain_split_single_child-false.rs | 5 +++++ .../configs-chain_split_single_child-true.rs | 6 ++++++ 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 tests/target/configs-chain_split_single_child-false.rs create mode 100644 tests/target/configs-chain_split_single_child-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 0e644f4509d..a0c6ba407d9 100644 --- a/Configurations.md +++ b/Configurations.md @@ -112,6 +112,28 @@ let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); #### Lines longer than `chain_one_line_max`: See [`chain_indent`](#chain_indent). +## `chain_split_single_child` + +Split a chain with a single child if its length exceeds [`chain_one_line_max`](#chain_one_line_max). + +- **Default value**: `false` +- **Possible values**: `false`, `true` + +#### `false` + +```rust +let files = fs::read_dir("tests/coverage/source").expect("Couldn't read source dir"); +``` + +#### `true` + +```rust +let files = fs::read_dir("tests/coverage/source") + .expect("Couldn't read source dir"); +``` + +See also [`chain_one_line_max`](#chain_one_line_max). + ## `closure_block_indent_threshold` How many lines a closure must have before it is block indented. -1 means never use block indent. diff --git a/src/chains.rs b/src/chains.rs index e5450aa687e..9a8a6914440 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -163,10 +163,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - first_child_shape, other_child_shape); - let child_shape_iter = Some(first_child_shape) - .into_iter() - .chain(::std::iter::repeat(other_child_shape) - .take(subexpr_list.len() - 1)); + let child_shape_iter = + Some(first_child_shape) + .into_iter() + .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = try_opt!(iter.map(|(e, shape)| { rewrite_chain_subexpr(e, total_span, context, shape) @@ -186,7 +186,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if rewrites.len() > 1 { true } else if rewrites.len() == 1 { - parent_rewrite.len() > context.config.chain_one_line_max() / 2 + context.config.chain_split_single_child() || one_line_len > shape.width } else { false } diff --git a/tests/target/configs-chain_split_single_child-false.rs b/tests/target/configs-chain_split_single_child-false.rs new file mode 100644 index 00000000000..1863c6ac33f --- /dev/null +++ b/tests/target/configs-chain_split_single_child-false.rs @@ -0,0 +1,5 @@ +// rustfmt-chain_split_single_child: false + +fn main() { + let files = fs::read_dir("tests/source").expect("Couldn't read source dir"); +} diff --git a/tests/target/configs-chain_split_single_child-true.rs b/tests/target/configs-chain_split_single_child-true.rs new file mode 100644 index 00000000000..154fa0bfa2e --- /dev/null +++ b/tests/target/configs-chain_split_single_child-true.rs @@ -0,0 +1,6 @@ +// rustfmt-chain_split_single_child: true + +fn main() { + let files = fs::read_dir("tests/source") + .expect("Couldn't read source dir"); +} -- cgit 1.4.1-3-g733a5 From 86856491bc3457bd2abe66359a4f63cc6cbd0769 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 25 May 2017 16:08:08 +0900 Subject: Format source codes --- src/config.rs | 2 ++ src/expr.rs | 33 +++++++++++++-------------------- src/file_lines.rs | 3 +-- src/items.rs | 3 +-- src/lists.rs | 6 ++---- src/macros.rs | 11 ++++++----- src/modules.rs | 3 +-- src/string.rs | 3 +-- src/utils.rs | 3 +-- tests/system.rs | 9 +++------ 10 files changed, 31 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c64d2c0647d..0c73b64c6b2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -448,6 +448,8 @@ create_config! { "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain"; chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line"; + chain_split_single_child: bool, false, "Split a chain with a single child if its length \ + exceeds `chain_one_line_max`"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, false, "Reorder import statements in group"; reorder_imported_names: bool, false, diff --git a/src/expr.rs b/src/expr.rs index 07f1c80fc3d..4a415a5cc82 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -98,20 +98,16 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Tup(ref items) => rewrite_tuple(context, items, expr.span, shape), ast::ExprKind::While(ref cond, ref block, label) => { - ControlFlow::new_while(None, cond, block, label, expr.span) - .rewrite(context, shape) + ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape) } ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - ControlFlow::new_while(Some(pat), cond, block, label, expr.span) - .rewrite(context, shape) + ControlFlow::new_while(Some(pat), cond, block, label, expr.span).rewrite(context, shape) } ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - ControlFlow::new_for(pat, cond, block, label, expr.span) - .rewrite(context, shape) + ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, shape) } ast::ExprKind::Loop(ref block, label) => { - ControlFlow::new_loop(block, label, expr.span) - .rewrite(context, shape) + ControlFlow::new_loop(block, label, expr.span).rewrite(context, shape) } ast::ExprKind::Block(ref block) => block.rewrite(context, shape), ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { @@ -179,12 +175,11 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - .or_else(|| { - wrap_str(context.snippet(expr.span), - context.config.max_width(), - shape) - }) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str(context.snippet(expr.span), + context.config.max_width(), + shape) + }) } ast::ExprKind::Ret(None) => { wrap_str("return".to_owned(), context.config.max_width(), shape) @@ -324,8 +319,7 @@ pub fn rewrite_pair(lhs: &LHS, .checked_sub(shape.used_width() + prefix.len() + infix.len())); let rhs_shape = match context.config.control_style() { Style::Default => { - try_opt!(shape.sub_width(suffix.len() + prefix.len())) - .visual_indent(prefix.len()) + try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) } Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces())), }; @@ -516,8 +510,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, shape) + 1; - let body_shape = try_opt!(shape.sub_width(extra_offset)) - .add_offset(extra_offset); + let body_shape = try_opt!(shape.sub_width(extra_offset)).add_offset(extra_offset); if let ast::ExprKind::Block(ref block) = body.node { // The body of the closure is an empty block. @@ -859,8 +852,8 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = try_opt!(else_expr.rewrite(context, - Shape::legacy(new_width, Indent::empty()))); + let else_str = + try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); if if_str.contains('\n') || else_str.contains('\n') { return None; diff --git a/src/file_lines.rs b/src/file_lines.rs index 9de427781fe..2d1fa33a90e 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -135,8 +135,7 @@ impl FileLines { Some(ref map) => map, }; - match canonicalize_path_string(file_name) - .and_then(|file| map.get(&file)) { + match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) { Some(ranges) => ranges.iter().any(f), None => false, } diff --git a/src/items.rs b/src/items.rs index 88e663403d6..37ffb4792eb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1125,8 +1125,7 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let shape = try_opt!(Shape::indented(generics_indent, context.config) - .sub_width(" =".len())); + let shape = try_opt!(Shape::indented(generics_indent, context.config).sub_width(" =".len())); let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); diff --git a/src/lists.rs b/src/lists.rs index adc18c14581..3448f8a446a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -430,8 +430,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let post_snippet_trimmed = if post_snippet.starts_with(',') { post_snippet[1..].trim_matches(white_space) } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)] - .trim_matches(white_space) + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) } else { post_snippet }; @@ -529,8 +528,7 @@ pub fn struct_lit_shape(shape: Shape, -> Option<(Option, Shape)> { let v_shape = match context.config.struct_lit_style() { IndentStyle::Visual => { - try_opt!(try_opt!(shape.shrink_left(prefix_width)) - .sub_width(suffix_width)) + try_opt!(try_opt!(shape.shrink_left(prefix_width)).sub_width(suffix_width)) } IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); diff --git a/src/macros.rs b/src/macros.rs index c46ed3d88c7..3c6c54f42cf 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -172,11 +172,12 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape) - .map(|rw| match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - }) + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map(|rw| { + match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + } + }) } MacroStyle::Brackets => { let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); diff --git a/src/modules.rs b/src/modules.rs index 5e09a311dcb..3d2c3b0ac9f 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -68,8 +68,7 @@ fn module_file(id: ast::Ident, return path; } - match parser::Parser::default_submod_path(id, dir_path, codemap) - .result { + match parser::Parser::default_submod_path(id, dir_path, codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => path, Err(_) => panic!("Couldn't find module {}", id), } diff --git a/src/string.rs b/src/string.rs index 17c6533f7a0..365d205aef1 100644 --- a/src/string.rs +++ b/src/string.rs @@ -35,8 +35,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); let stripped_str = re.replace_all(orig, "$1"); - let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false) - .collect::>(); + let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); let shape = fmt.shape.visual_indent(0); let indent = shape.indent.to_string(fmt.config); let punctuation = ":,;."; diff --git a/src/utils.rs b/src/utils.rs index 1192608c24a..e80c558e51e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -332,8 +332,7 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option Option { - wrap_str(self, context.config.max_width(), shape) - .map(ToOwned::to_owned) + wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned) } } diff --git a/tests/system.rs b/tests/system.rs index 70c8033da6c..58e44ee5381 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -55,8 +55,7 @@ fn system_tests() { // the only difference is the coverage mode #[test] fn coverage_tests() { - let files = fs::read_dir("tests/coverage/source") - .expect("Couldn't read source dir"); + let files = fs::read_dir("tests/coverage/source").expect("Couldn't read source dir"); let files = files.map(get_path_string); let (_reports, count, fails) = check_files(files); @@ -83,8 +82,7 @@ fn assert_output(source: &str, expected_filename: &str) { let _ = filemap::write_all_files(&file_map, &mut out, &config); let output = String::from_utf8(out).unwrap(); - let mut expected_file = fs::File::open(&expected_filename) - .expect("Couldn't open target"); + let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); let mut expected_text = String::new(); expected_file .read_to_string(&mut expected_text) @@ -279,8 +277,7 @@ fn get_config(config_file: Option<&str>) -> Config { } }; - let mut def_config_file = fs::File::open(config_file_name) - .expect("Couldn't open config"); + let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); let mut def_config = String::new(); def_config_file .read_to_string(&mut def_config) -- cgit 1.4.1-3-g733a5 From 10c79347009ded8f03e4988f016659ff2a3713e1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 25 May 2017 22:55:11 +0900 Subject: Be precise with one_line_budget for fn_base --- src/items.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 88e663403d6..7b20d0b20c5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1565,7 +1565,12 @@ fn rewrite_fn_base(context: &RewriteContext, // Args. let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = - try_opt!(compute_budgets_for_args(context, &result, indent, ret_str_len, newline_brace)); + try_opt!(compute_budgets_for_args(context, + &result, + indent, + ret_str_len, + newline_brace, + has_braces)); if context.config.fn_args_layout() == IndentStyle::Block { arg_indent = indent.block_indent(context.config); @@ -1907,7 +1912,8 @@ fn compute_budgets_for_args(context: &RewriteContext, result: &str, indent: Indent, ret_str_len: usize, - newline_brace: bool) + newline_brace: bool, + has_braces: bool) -> Option<((usize, usize, Indent))> { debug!("compute_budgets_for_args {} {:?}, {}, {}", result.len(), @@ -1916,10 +1922,17 @@ fn compute_budgets_for_args(context: &RewriteContext, newline_brace); // Try keeping everything on the same line. if !result.contains('\n') { - // 3 = `() `, space is before ret_string. - let mut used_space = indent.width() + result.len() + ret_str_len + 3; - if !newline_brace { - used_space += 2; + // 2 = `()`, 3 = `() `, space is before ret_string. + let overhead = if ret_str_len == 0 { 2 } else { 3 }; + let mut used_space = indent.width() + result.len() + ret_str_len + overhead; + if has_braces { + if !newline_brace { + // 2 = `{}` + used_space += 2; + } + } else { + // 1 = `;` + used_space += 1; } let one_line_budget = context .config -- cgit 1.4.1-3-g733a5 From 92270ba191e53fa3d9a5dbdc8cc36b5f8749cbd7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 25 May 2017 23:01:41 +0900 Subject: Add offset when rewriting index --- src/expr.rs | 12 +++++------- tests/target/chains-visual.rs | 6 +++--- tests/target/chains.rs | 6 +++--- tests/target/issue-1247.rs | 7 +++++++ 4 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 tests/target/issue-1247.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bb9e55e4f16..4102f4f7ad3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1893,13 +1893,11 @@ fn rewrite_index(expr: &ast::Expr, ("[", "]") }; - let budget = shape - .width - .checked_sub(expr_str.len() + lbr.len() + rbr.len()) - .unwrap_or(0); - let index_str = index.rewrite(context, Shape::legacy(budget, shape.indent)); - if let Some(index_str) = index_str { - return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); + let offset = expr_str.len() + lbr.len(); + if let Some(index_shape) = shape.visual_indent(offset).sub_width(offset + rbr.len()) { + if let Some(index_str) = index.rewrite(context, index_shape) { + return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); + } } let indent = shape.indent.block_indent(&context.config); diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 2763b339084..52d271a4469 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -83,9 +83,9 @@ fn floaters() { PushParam => { // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] .clone()); } } diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 80b02482991..fb6ee2f885f 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -82,9 +82,9 @@ fn floaters() { PushParam => { // params are 1-indexed stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }].clone()); + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone()); } } } diff --git a/tests/target/issue-1247.rs b/tests/target/issue-1247.rs new file mode 100644 index 00000000000..427a8076ad5 --- /dev/null +++ b/tests/target/issue-1247.rs @@ -0,0 +1,7 @@ +// rustfmt-max_width: 80 + +fn foo() { + polyfill::slice::fill(&mut self.pending[padding_pos.. + (self.algorithm.block_len - 8)], + 0); +} -- cgit 1.4.1-3-g733a5 From 0869bca85abefa73ee4c1998378cb0b5c50b783e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 26 May 2017 13:14:36 +0900 Subject: Put closing paren on the next line when the last arg contains comment --- src/items.rs | 14 +++++++++++++- tests/target/issue-1587.rs | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-1587.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 34d2b6ea530..a23e69d6881 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1634,6 +1634,7 @@ fn rewrite_fn_base(context: &RewriteContext, _ => false, } && !fd.inputs.is_empty(); + let mut args_last_line_contains_comment = false; if put_args_in_block { arg_indent = indent.block_indent(context.config); result.push('\n'); @@ -1647,6 +1648,16 @@ fn rewrite_fn_base(context: &RewriteContext, if context.config.spaces_within_parens() && fd.inputs.len() > 0 { result.push(' ') } + // If the last line of args contains comment, we cannot put the closing paren + // on the same line. + if arg_str + .lines() + .last() + .map_or(false, |last_line| last_line.contains("//")) { + args_last_line_contains_comment = true; + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + } result.push(')'); } @@ -1670,7 +1681,8 @@ fn rewrite_fn_base(context: &RewriteContext, let overlong_sig = sig_length > context.config.max_width(); - result.contains('\n') || multi_line_ret_str || overlong_sig + (!args_last_line_contains_comment) && + (result.contains('\n') || multi_line_ret_str || overlong_sig) } }; let ret_indent = if ret_should_indent { diff --git a/tests/target/issue-1587.rs b/tests/target/issue-1587.rs new file mode 100644 index 00000000000..b2796ef6f3b --- /dev/null +++ b/tests/target/issue-1587.rs @@ -0,0 +1,8 @@ +pub trait X { + fn a(&self) -> &'static str; + fn bcd(&self, + c: &str, // comment on this arg + d: u16, // comment on this arg + e: &Vec // comment on this arg + ) -> Box; +} -- cgit 1.4.1-3-g733a5 From b748fe8bec300afb4eb6b7923c74152c588a5eb8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 26 May 2017 16:34:58 +0900 Subject: Set inside_macro to false when rewriting args of macro --- src/expr.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 318ec8e59b5..808cd06c2d2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1678,12 +1678,14 @@ fn rewrite_call_args(context: &RewriteContext, one_line_width: usize, force_trailing_comma: bool) -> Option<(bool, String)> { + let mut item_context = context.clone(); + item_context.inside_macro = false; let items = itemize_list(context.codemap, args.iter(), ")", |item| item.span.lo, |item| item.span.hi, - |item| item.rewrite(context, shape), + |item| item.rewrite(&item_context, shape), span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1691,7 +1693,7 @@ fn rewrite_call_args(context: &RewriteContext, // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. - let overflow_last = can_be_overflowed(context, args); + let overflow_last = can_be_overflowed(&item_context, args); let mut orig_last = None; let mut placeholder = None; @@ -1709,7 +1711,7 @@ fn rewrite_call_args(context: &RewriteContext, } else { shape.block() }; - let rewrite = args.last().unwrap().rewrite(context, arg_shape); + let rewrite = args.last().unwrap().rewrite(&item_context, arg_shape); swap(&mut item_vec[args.len() - 1].item, &mut orig_last); if let Some(rewrite) = rewrite { -- cgit 1.4.1-3-g733a5 From 15b988aed3d2d4ec761452840ed96b84080c2abc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 26 May 2017 16:35:34 +0900 Subject: Allow macro to nested and overflowed like function call --- src/expr.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 808cd06c2d2..0abeafaefc2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1772,13 +1772,17 @@ fn rewrite_call_args(context: &RewriteContext, acc + item.item.as_ref().map_or(0, |s| 2 + first_line_width(s)) }) <= one_line_budget + 2; - match write_list(&item_vec, &fmt) { + let result = write_list(&item_vec, &fmt); + let last_char_is_not_comma = result + .as_ref() + .map_or(false, |r| r.chars().last().unwrap_or(' ') != ','); + match result { // If arguments do not fit in a single line and do not contain newline, // try to put it on the next line. Try this only when we are in block mode // and not rewriting macro. Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && !context.inside_macro && - ((!can_be_overflowed(context, args) && args.len() == 1 && + ((!can_be_overflowed(&context, args) && last_char_is_not_comma && s.contains('\n')) || first_line_width(s) > one_line_budget) => { fmt.trailing_separator = SeparatorTactic::Vertical; @@ -1786,13 +1790,7 @@ fn rewrite_call_args(context: &RewriteContext, write_list(&item_vec, &fmt).map(|rw| (false, rw)) } rewrite @ _ => { - rewrite.map(|rw| { - (extendable && - rw.chars() - .last() - .map_or(true, |c| force_trailing_comma || c != ','), - rw) - }) + rewrite.map(|rw| (extendable && (last_char_is_not_comma || force_trailing_comma), rw)) } } } @@ -1809,6 +1807,7 @@ fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bo context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1 } Some(&ast::ExprKind::Call(..)) | + Some(&ast::ExprKind::Mac(..)) | Some(&ast::ExprKind::Struct(..)) => { context.config.fn_call_style() == IndentStyle::Block && args.len() == 1 } @@ -1824,6 +1823,7 @@ fn is_extendable(args: &[ptr::P]) -> bool { ast::ExprKind::Call(..) | ast::ExprKind::Closure(..) | ast::ExprKind::Match(..) | + ast::ExprKind::Mac(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => true, _ => false, -- cgit 1.4.1-3-g733a5 From 554605d47cc2546f32871de5f41ef4008f5d5ecf Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 26 May 2017 16:36:15 +0900 Subject: Format source codes and add tests --- src/chains.rs | 7 +++---- src/expr.rs | 2 +- src/items.rs | 4 +--- tests/source/configs-fn_call_style-block.rs | 4 ++++ tests/target/closure-block-inside-macro.rs | 14 ++++++-------- tests/target/configs-fn_call_style-block.rs | 10 ++++++++++ 6 files changed, 25 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9a8a6914440..1c66306022d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -168,10 +168,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .into_iter() .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); let iter = subexpr_list.iter().rev().zip(child_shape_iter); - let mut rewrites = try_opt!(iter.map(|(e, shape)| { - rewrite_chain_subexpr(e, total_span, context, shape) - }) - .collect::>>()); + let mut rewrites = + try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) + .collect::>>()); // Total of all items excluding the last. let last_non_try_index = rewrites.len() - (1 + trailing_try_num); diff --git a/src/expr.rs b/src/expr.rs index 0abeafaefc2..21a872489d8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1782,7 +1782,7 @@ fn rewrite_call_args(context: &RewriteContext, // and not rewriting macro. Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && !context.inside_macro && - ((!can_be_overflowed(&context, args) && last_char_is_not_comma && + ((!can_be_overflowed(context, args) && last_char_is_not_comma && s.contains('\n')) || first_line_width(s) > one_line_budget) => { fmt.trailing_separator = SeparatorTactic::Vertical; diff --git a/src/items.rs b/src/items.rs index 34d2b6ea530..2d9499445cc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1783,9 +1783,7 @@ fn rewrite_args(context: &RewriteContext, -> Option { let mut arg_item_strs = try_opt!(args.iter() - .map(|arg| { - arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)) - }) + .map(|arg| arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent))) .collect::>>()); // Account for sugary self. diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index aae6693f43f..2068216d18e 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -16,6 +16,10 @@ fn main() { .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; } } + + // nesting macro and function call + try!(foo(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)); + try!(foo(try!(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx))); } // #1521 diff --git a/tests/target/closure-block-inside-macro.rs b/tests/target/closure-block-inside-macro.rs index 5d1e1de0f68..d567008c2ad 100644 --- a/tests/target/closure-block-inside-macro.rs +++ b/tests/target/closure-block-inside-macro.rs @@ -1,13 +1,11 @@ // rustfmt-fn_call_style: Block // #1547 -fuzz_target!(|data: &[u8]| { - if let Some(first) = data.first() { - let index = *first as usize; - if index >= ENCODINGS.len() { - return; - } - let encoding = ENCODINGS[index]; - dispatch_test(encoding, &data[1..]); +fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); }); diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index 2ac5340059c..3da4f648527 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -32,6 +32,16 @@ fn main() { )?; } } + + // nesting macro and function call + try!(foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + )); + try!(foo(try!( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ))); } // #1521 -- cgit 1.4.1-3-g733a5 From fcffe854b8084e4ef0abfa06ce3d3db2f8c57586 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 26 May 2017 17:17:12 +0900 Subject: Allow default associated types --- src/visitor.rs | 4 ++-- tests/target/associated_type_defaults.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 tests/target/associated_type_defaults.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 96327ef96a7..650bb40ca17 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -389,9 +389,9 @@ impl<'a> FmtVisitor<'a> { ti.id, ast::Defaultness::Final); } - ast::TraitItemKind::Type(ref type_param_bounds, _) => { + ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { let rewrite = rewrite_associated_type(ti.ident, - None, + type_default.as_ref(), Some(type_param_bounds), &self.get_context(), self.block_indent); diff --git a/tests/target/associated_type_defaults.rs b/tests/target/associated_type_defaults.rs new file mode 100644 index 00000000000..d0a08133725 --- /dev/null +++ b/tests/target/associated_type_defaults.rs @@ -0,0 +1,4 @@ +#![feature(associated_type_defaults)] +trait Foo { + type Bar = (); +} -- cgit 1.4.1-3-g733a5 From dab14b4485b95ee36510bdae14c34f9afa81032f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 27 May 2017 02:03:22 +0900 Subject: Allow comments after where clause --- src/items.rs | 8 ++++++-- src/visitor.rs | 11 ++++++++++- tests/target/impl.rs | 11 +++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a23e69d6881..01178e8e53a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -500,7 +500,11 @@ impl<'a> FmtVisitor<'a> { } } -pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { +pub fn format_impl(context: &RewriteContext, + item: &ast::Item, + offset: Indent, + where_span_end: Option) + -> Option { if let ast::ItemKind::Impl(_, _, ref generics, ref trait_ref, _, ref items) = item.node { let mut result = String::new(); // First try to format the ref and type without a split at the 'for'. @@ -527,7 +531,7 @@ pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) - "{", false, last_line_width(&ref_and_type) == 1, - None)); + where_span_end)); if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { result.push_str(&where_clause_str); diff --git a/src/visitor.rs b/src/visitor.rs index 96327ef96a7..c40c0fcc87e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -19,6 +19,7 @@ use strings::string_buffer::StringBuffer; use {Indent, Shape}; use utils; use codemap::{LineRangeUtils, SpanUtils}; +use comment::FindUncommented; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; @@ -249,7 +250,15 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo); - if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent) { + let snippet = self.get_context().snippet(item.span); + let where_span_end = + snippet + .find_uncommented("{") + .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); + if let Some(impl_str) = format_impl(&self.get_context(), + item, + self.block_indent, + where_span_end) { self.buffer.push_str(&impl_str); self.last_pos = source!(self, item.span).hi; } diff --git a/tests/target/impl.rs b/tests/target/impl.rs index 5dde5ee7382..c51693afd22 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -5,3 +5,14 @@ impl JSTraceable for SmallVec<[T; 1]> {} impl>> Handle { // Keep this. } + +impl Test + where V: Clone // This comment is NOT removed by formating! +{ + pub fn new(value: V) -> Self { + Test { + cloned_value: value.clone(), + value: value, + } + } +} -- cgit 1.4.1-3-g733a5 From 67e8a690ff3aa0c3d1962449c4b8d0556a3770f8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 27 May 2017 07:33:06 +0900 Subject: Add a trailing comma if the last arg ends with comment --- src/items.rs | 9 +++++++++ tests/target/fn-args-with-last-line-comment.rs | 22 ++++++++++++++++++++++ tests/target/issue-1587.rs | 8 -------- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 tests/target/fn-args-with-last-line-comment.rs delete mode 100644 tests/target/issue-1587.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a23e69d6881..8d72c2a3a23 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1879,6 +1879,12 @@ fn rewrite_args(context: &RewriteContext, item.item = Some(arg); } + let last_line_ends_with_comment = arg_items + .iter() + .last() + .and_then(|item| item.post_comment.as_ref()) + .map_or(false, |s| s.trim().starts_with("//")); + let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout() { IndentStyle::Block if fits_in_one_line => { (indent.block_indent(context.config), SeparatorTactic::Never, true) @@ -1886,6 +1892,9 @@ fn rewrite_args(context: &RewriteContext, IndentStyle::Block => { (indent.block_indent(context.config), SeparatorTactic::Vertical, true) } + IndentStyle::Visual if last_line_ends_with_comment => { + (arg_indent, SeparatorTactic::Vertical, true) + } IndentStyle::Visual => (arg_indent, SeparatorTactic::Never, false), }; diff --git a/tests/target/fn-args-with-last-line-comment.rs b/tests/target/fn-args-with-last-line-comment.rs new file mode 100644 index 00000000000..2e310747cc4 --- /dev/null +++ b/tests/target/fn-args-with-last-line-comment.rs @@ -0,0 +1,22 @@ +// #1587 +pub trait X { + fn a(&self) -> &'static str; + fn bcd(&self, + c: &str, // comment on this arg + d: u16, // comment on this arg + e: &Vec, // comment on this arg + ) -> Box; +} + +// #1595 +fn foo(arg1: LongTypeName, + arg2: LongTypeName, + arg3: LongTypeName, + arg4: LongTypeName, + arg5: LongTypeName, + arg6: LongTypeName, + arg7: LongTypeName, + //arg8: LongTypeName, + ) { + // do stuff +} diff --git a/tests/target/issue-1587.rs b/tests/target/issue-1587.rs deleted file mode 100644 index b2796ef6f3b..00000000000 --- a/tests/target/issue-1587.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub trait X { - fn a(&self) -> &'static str; - fn bcd(&self, - c: &str, // comment on this arg - d: u16, // comment on this arg - e: &Vec // comment on this arg - ) -> Box; -} -- cgit 1.4.1-3-g733a5 From b6c503ac32511008ec59cb4a3ad1876a8b94fdb8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 27 May 2017 09:36:25 +0900 Subject: Allow comments after attributes of struct fields --- src/items.rs | 41 ++++++++++++++++++++++++++++++++++------- tests/source/structs.rs | 22 ++++++++++++++++++++++ tests/target/structs.rs | 22 ++++++++++++++++++++++ 3 files changed, 78 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a23e69d6881..86d2aeb07a5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,7 +18,7 @@ use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wr use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; -use comment::{FindUncommented, contains_comment}; +use comment::{FindUncommented, contains_comment, rewrite_comment}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity}; @@ -1201,15 +1201,42 @@ impl Rewrite for ast::StructField { let mut attr_str = try_opt!(self.attrs.rewrite(context, Shape::indented(shape.indent, context.config))); - if !attr_str.is_empty() { - attr_str.push('\n'); - attr_str.push_str(&shape.indent.to_string(context.config)); - } + // Try format missing comments after attributes + let missing_comment = if !self.attrs.is_empty() { + let possibly_comment_snippet = + context.snippet(mk_sp(self.attrs[self.attrs.len() - 1].span.hi, self.span.lo)); + let newline_index = possibly_comment_snippet.find('\n'); + let comment_index = possibly_comment_snippet.find('/'); + match (newline_index, comment_index) { + (Some(i), Some(j)) if i > j => attr_str.push(' '), + _ => { + attr_str.push('\n'); + attr_str.push_str(&shape.indent.to_string(context.config)); + } + } + let trimmed = possibly_comment_snippet.trim(); + if trimmed.is_empty() { + String::new() + } else { + rewrite_comment(trimmed, false, shape, context.config).map_or(String::new(), |s| { + format!("{}\n{}", s, shape.indent.to_string(context.config)) + }) + } + } else { + String::new() + }; let type_annotation_spacing = type_annotation_spacing(context.config); let mut result = match name { - Some(name) => format!("{}{}{}{}:", attr_str, vis, name, type_annotation_spacing.0), - None => format!("{}{}", attr_str, vis), + Some(name) => { + format!("{}{}{}{}{}:", + attr_str, + missing_comment, + vis, + name, + type_annotation_spacing.0) + } + None => format!("{}{}{}", attr_str, missing_comment, vis), }; let type_offset = shape.indent.block_indent(context.config); diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 5dd9087682c..03847ec883f 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -16,6 +16,28 @@ pub struct Foo { pub i: TypeForPublicField } +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + struct Bar; struct NewType(Type, OtherType); diff --git a/tests/target/structs.rs b/tests/target/structs.rs index a89df16376f..2872750c20a 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -16,6 +16,28 @@ pub struct Foo { pub i: TypeForPublicField, } +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + struct Bar; struct NewType(Type, OtherType); -- cgit 1.4.1-3-g733a5 From a22228aceea355098745a314b4177a800a623e97 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 27 May 2017 18:48:42 +0900 Subject: Avoid unnecessary binary search in rewrite_call --- src/expr.rs | 61 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 21a872489d8..4c9a55f28c0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -74,7 +74,7 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, expr.span.hi); - rewrite_call(context, &**callee, args, inner_span, shape) + rewrite_call_with_binary_search(context, &**callee, args, inner_span, shape) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { @@ -1603,41 +1603,47 @@ fn string_requires_rewrite(context: &RewriteContext, false } -pub fn rewrite_call(context: &RewriteContext, - callee: &R, - args: &[ptr::P], - span: Span, - shape: Shape) - -> Option +pub fn rewrite_call_with_binary_search(context: &RewriteContext, + callee: &R, + args: &[ptr::P], + span: Span, + shape: Shape) + -> Option where R: Rewrite { let closure = |callee_max_width| { - rewrite_call_inner(context, callee, callee_max_width, args, span, shape, false) + // FIXME using byte lens instead of char lens (and probably all over the + // place too) + let callee_shape = Shape { + width: callee_max_width, + ..shape + }; + let callee_str = callee + .rewrite(context, callee_shape) + .ok_or(Ordering::Greater)?; + + rewrite_call_inner(context, &callee_str, args, span, shape, false) }; binary_search(1, shape.width, closure) } -fn rewrite_call_inner(context: &RewriteContext, - callee: &R, - max_callee_width: usize, - args: &[ptr::P], - span: Span, - shape: Shape, - force_trailing_comma: bool) - -> Result - where R: Rewrite -{ - // FIXME using byte lens instead of char lens (and probably all over the - // place too) - let callee_shape = Shape { - width: max_callee_width, - ..shape - }; - let callee_str = callee - .rewrite(context, callee_shape) - .ok_or(Ordering::Greater)?; +pub fn rewrite_call(context: &RewriteContext, + callee: &str, + args: &[ptr::P], + span: Span, + shape: Shape) + -> Option { + rewrite_call_inner(context, &callee, args, span, shape, false).ok() +} +fn rewrite_call_inner(context: &RewriteContext, + callee_str: &str, + args: &[ptr::P], + span: Span, + shape: Shape, + force_trailing_comma: bool) + -> Result { // 2 = `( `, 1 = `(` let paren_overhead = if context.config.spaces_within_parens() { 2 @@ -2108,7 +2114,6 @@ pub fn rewrite_tuple(context: &RewriteContext, // 1 = "," rewrite_call_inner(context, &String::new(), - shape.width.checked_sub(1).unwrap_or(0), items, span, shape, -- cgit 1.4.1-3-g733a5 From 4402412b7838173c91cdfd26d066b40c02b981a7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 27 May 2017 23:59:29 +0900 Subject: Allow attributes in generics of impl --- src/items.rs | 8 ++++++-- src/types.rs | 6 ++++++ tests/source/impls.rs | 5 +++++ tests/target/impls.rs | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 31998c35d33..644837bd30b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1512,12 +1512,16 @@ fn span_for_return(ret: &ast::FunctionRetTy) -> Span { fn span_for_ty_param(ty: &ast::TyParam) -> Span { // Note that ty.span is the span for ty.ident, not the whole item. - let lo = ty.span.lo; + let lo = if ty.attrs.is_empty() { + ty.span.lo + } else { + ty.attrs[0].span.lo + }; if let Some(ref def) = ty.default { return mk_sp(lo, def.span.hi); } if ty.bounds.is_empty() { - return ty.span; + return mk_sp(lo, ty.span.hi); } let hi = match ty.bounds[ty.bounds.len() - 1] { ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span.hi, diff --git a/src/types.rs b/src/types.rs index 82f68976225..adade891075 100644 --- a/src/types.rs +++ b/src/types.rs @@ -509,6 +509,12 @@ impl Rewrite for ast::TyParamBounds { impl Rewrite for ast::TyParam { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::with_capacity(128); + // FIXME: If there are more than one attributes, this will force multiline. + let attr_str = match (&*self.attrs).rewrite(context, shape) { + Some(ref rw) if !rw.is_empty() => format!("{} ", rw), + _ => String::new(), + }; + result.push_str(&attr_str); result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { if context.config.space_before_bound() { diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 060376b113e..1c38a2ff284 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -117,3 +117,8 @@ impl Issue1249 Drop for RawTable { + fn drop() {} +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index dacaa1f5601..f8b9f43aeb0 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -149,3 +149,8 @@ impl // Creates a new flow constructor. fn foo() {} } + +// #1600 +impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { + fn drop() {} +} -- cgit 1.4.1-3-g733a5 From 99c2eab5aca190f4864f9966afe745b0ee365bfc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 28 May 2017 11:41:16 +0900 Subject: Allow attributes on expressions --- src/expr.rs | 19 ++++++++++++++++--- tests/source/macros.rs | 8 ++++++++ tests/source/skip.rs | 13 +++++++++++++ tests/target/macros.rs | 8 ++++++++ tests/target/skip.rs | 13 +++++++++++++ 5 files changed, 58 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 21a872489d8..b6dad6c5c23 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -23,7 +23,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, - colon_spaces}; + colon_spaces, contains_skip}; use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -53,7 +53,11 @@ fn format_expr(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - let result = match expr.node { + if contains_skip(&*expr.attrs) { + return Some(context.snippet(expr.span)); + } + let attr_rw = (&*expr.attrs).rewrite(context, shape); + let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => { rewrite_array(expr_vec.iter().map(|e| &**e), mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), @@ -251,7 +255,16 @@ fn format_expr(expr: &ast::Expr, shape) } }; - result.and_then(|res| recover_comment_removed(res, expr.span, context, shape)) + match (attr_rw, expr_rw) { + (Some(attr_str), Some(expr_str)) => { + let space = if attr_str.is_empty() { "" } else { " " }; + recover_comment_removed(format!("{}{}{}", attr_str, space, expr_str), + expr.span, + context, + shape) + } + _ => None, + } } pub fn rewrite_pair(lhs: &LHS, diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 85ec41ddb0f..26107fbff01 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -103,3 +103,11 @@ fn issue_1555() { "65454654654654654654654655464", "4"); } + +fn issue1178() { + macro_rules! foo { + (#[$attr:meta] $name:ident) => {} + } + + foo!(#[doc = "bar"] baz); +} diff --git a/tests/source/skip.rs b/tests/source/skip.rs index 21f080e9aba..d13c8159039 100644 --- a/tests/source/skip.rs +++ b/tests/source/skip.rs @@ -16,3 +16,16 @@ impl LateLintPass for UsedUnderscoreBinding { fn check_expr() { // comment } } + +fn issue1346() { + #[cfg_attr(rustfmt, rustfmt_skip)] + Box::new(self.inner.call(req).then(move |result| { + match result { + Ok(resp) => Box::new(future::done(Ok(resp))), + Err(e) => { + try_error!(clo_stderr, "{}", e); + Box::new(future::err(e)) + } + } + })) +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index a1fa3f74368..941ae46c6d5 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -108,3 +108,11 @@ fn issue_1555() { "65454654654654654654654655464", "4"); } + +fn issue1178() { + macro_rules! foo { + (#[$attr:meta] $name:ident) => {} + } + + foo!(#[doc = "bar"] baz); +} diff --git a/tests/target/skip.rs b/tests/target/skip.rs index 21f080e9aba..d13c8159039 100644 --- a/tests/target/skip.rs +++ b/tests/target/skip.rs @@ -16,3 +16,16 @@ impl LateLintPass for UsedUnderscoreBinding { fn check_expr() { // comment } } + +fn issue1346() { + #[cfg_attr(rustfmt, rustfmt_skip)] + Box::new(self.inner.call(req).then(move |result| { + match result { + Ok(resp) => Box::new(future::done(Ok(resp))), + Err(e) => { + try_error!(clo_stderr, "{}", e); + Box::new(future::err(e)) + } + } + })) +} -- cgit 1.4.1-3-g733a5 From bcebe9e7def08e987516fb59a46234acd7ef5d2c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 28 May 2017 19:10:05 +0900 Subject: Use different style when rewriting comment with different opener --- src/comment.rs | 183 +++++++++++++++++++++++++++++++++++++++------- tests/target/issue-691.rs | 9 +++ 2 files changed, 165 insertions(+), 27 deletions(-) create mode 100644 tests/target/issue-691.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 9591ffc4427..5b3ee179e2e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -32,6 +32,122 @@ fn is_custom_comment(comment: &str) -> bool { } } +#[derive(PartialEq, Eq)] +pub enum CommentStyle { + DoubleSlash, + TripleSlash, + Doc, + SingleBullet, + DoubleBullet, + Exclamation, + Custom, +} + +impl CommentStyle { + pub fn opener<'a>(&self, orig: &'a str) -> &'a str { + match *self { + CommentStyle::DoubleSlash => "// ", + CommentStyle::TripleSlash => "/// ", + CommentStyle::Doc => "//! ", + CommentStyle::SingleBullet => "/* ", + CommentStyle::DoubleBullet => "/** ", + CommentStyle::Exclamation => "/*! ", + CommentStyle::Custom => { + if orig.chars().nth(3) == Some(' ') { + &orig[0..4] + } else { + &orig[0..3] + } + } + } + } + + pub fn closer<'a>(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash | + CommentStyle::TripleSlash | + CommentStyle::Custom | + CommentStyle::Doc => "", + CommentStyle::DoubleBullet => " **/", + CommentStyle::SingleBullet | + CommentStyle::Exclamation => " */", + } + } + + pub fn line_start<'a>(&self, orig: &'a str) -> &'a str { + match *self { + CommentStyle::DoubleSlash => "// ", + CommentStyle::TripleSlash => "/// ", + CommentStyle::Doc => "//! ", + CommentStyle::SingleBullet | + CommentStyle::Exclamation => " * ", + CommentStyle::DoubleBullet => " ** ", + CommentStyle::Custom => { + if orig.chars().nth(3) == Some(' ') { + &orig[0..4] + } else { + &orig[0..3] + } + } + } + } + + pub fn to_str_tuplet<'a>(&self, orig: &'a str) -> (&'a str, &'a str, &'a str) { + (self.opener(orig), self.closer(), self.line_start(orig)) + } + + pub fn line_with_same_comment_style<'a>(&self, + line: &str, + orig: &'a str, + normalize_comments: bool) + -> bool { + match *self { + CommentStyle::DoubleSlash | + CommentStyle::TripleSlash | + CommentStyle::Custom | + CommentStyle::Doc => { + line.trim_left() + .starts_with(self.line_start(orig).trim_left()) || + comment_style(line, normalize_comments) == *self + } + CommentStyle::DoubleBullet | + CommentStyle::SingleBullet | + CommentStyle::Exclamation => { + line.trim_left().starts_with(self.closer().trim_left()) || + line.trim_left() + .starts_with(self.line_start(orig).trim_left()) || + comment_style(line, normalize_comments) == *self + } + } + } +} + +fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { + if !normalize_comments { + if orig.starts_with("/**") && !orig.starts_with("/**/") { + CommentStyle::DoubleBullet + } else if orig.starts_with("/*!") { + CommentStyle::Exclamation + } else if orig.starts_with("/*") { + CommentStyle::SingleBullet + } else if orig.starts_with("///") { + CommentStyle::TripleSlash + } else if orig.starts_with("//!") { + CommentStyle::Doc + } else { + CommentStyle::DoubleSlash + } + } else if orig.starts_with("///") || (orig.starts_with("/**") && !orig.starts_with("/**/")) { + CommentStyle::TripleSlash + } else if orig.starts_with("//!") || orig.starts_with("/*!") { + CommentStyle::Doc + } else if is_custom_comment(orig) { + CommentStyle::Custom + } else { + CommentStyle::DoubleSlash + } +} + pub fn rewrite_comment(orig: &str, block_style: bool, shape: Shape, @@ -47,39 +163,52 @@ pub fn rewrite_comment(orig: &str, if num_bare_lines > 0 && !config.normalize_comments() { return Some(orig.to_owned()); } - if !config.normalize_comments() && !config.wrap_comments() { return light_rewrite_comment(orig, shape.indent, config); } + identify_comment(orig, block_style, shape, config) +} + +fn identify_comment(orig: &str, + block_style: bool, + shape: Shape, + config: &Config) + -> Option { + let style = comment_style(orig, false); + let first_group = orig.lines() + .take_while(|l| style.line_with_same_comment_style(l, orig, false)) + .collect::>() + .join("\n"); + let rest = orig.lines() + .skip(first_group.lines().count()) + .collect::>() + .join("\n"); + + let first_group_str = try_opt!(rewrite_comment_inner(&first_group, block_style, shape, config)); + if rest.is_empty() { + Some(first_group_str) + } else { + identify_comment(&rest, block_style, shape, config).map(|rest_str| { + format!("{}\n{}{}", + first_group_str, + shape + .indent + .to_string(config), + rest_str) + }) + } +} + +fn rewrite_comment_inner(orig: &str, + block_style: bool, + shape: Shape, + config: &Config) + -> Option { let (opener, closer, line_start) = if block_style { - ("/* ", " */", " * ") - } else if !config.normalize_comments() { - if orig.starts_with("/**") && !orig.starts_with("/**/") { - ("/** ", " **/", " ** ") - } else if orig.starts_with("/*!") { - ("/*! ", " */", " * ") - } else if orig.starts_with("/*") { - ("/* ", " */", " * ") - } else if orig.starts_with("///") { - ("/// ", "", "/// ") - } else if orig.starts_with("//!") { - ("//! ", "", "//! ") - } else { - ("// ", "", "// ") - } - } else if orig.starts_with("///") || (orig.starts_with("/**") && !orig.starts_with("/**/")) { - ("/// ", "", "/// ") - } else if orig.starts_with("//!") || orig.starts_with("/*!") { - ("//! ", "", "//! ") - } else if is_custom_comment(orig) { - if orig.chars().nth(3) == Some(' ') { - (&orig[0..4], "", &orig[0..4]) - } else { - (&orig[0..3], "", &orig[0..3]) - } + CommentStyle::SingleBullet.to_str_tuplet("") } else { - ("// ", "", "// ") + comment_style(orig, config.normalize_comments()).to_str_tuplet(orig) }; let max_chars = shape diff --git a/tests/target/issue-691.rs b/tests/target/issue-691.rs new file mode 100644 index 00000000000..7473d070eff --- /dev/null +++ b/tests/target/issue-691.rs @@ -0,0 +1,9 @@ +// rustfmt-normalize_comments: true + +//! `std` or `core` and simply link to this library. In case the target +//! platform has no hardware +//! support for some operation, software implementations provided by this +//! library will be used automagically. +// TODO: provide instructions to override default libm link and how to link to +// this library. +fn foo() {} -- cgit 1.4.1-3-g733a5 From 924a9b5cb6af821ef8d763f2c7188bf9869066cf Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 30 May 2017 08:15:12 +0900 Subject: Allow longer custom comment --- src/comment.rs | 91 +++++++++++------------- tests/source/comment5.rs | 8 ++- tests/source/configs-normalize_comments-false.rs | 5 ++ tests/source/configs-normalize_comments-true.rs | 5 ++ tests/target/comment5.rs | 7 ++ tests/target/configs-normalize_comments-false.rs | 5 ++ tests/target/configs-normalize_comments-true.rs | 5 ++ 7 files changed, 77 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 5b3ee179e2e..ac4ec17bbbb 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -33,18 +33,26 @@ fn is_custom_comment(comment: &str) -> bool { } #[derive(PartialEq, Eq)] -pub enum CommentStyle { +pub enum CommentStyle<'a> { DoubleSlash, TripleSlash, Doc, SingleBullet, DoubleBullet, Exclamation, - Custom, + Custom(&'a str), } -impl CommentStyle { - pub fn opener<'a>(&self, orig: &'a str) -> &'a str { +fn custom_opener(s: &str) -> &str { + s.lines().next().map_or("", |first_line| { + first_line + .find(' ') + .map_or(first_line, |space_index| &first_line[0..space_index + 1]) + }) +} + +impl<'a> CommentStyle<'a> { + pub fn opener(&self) -> &'a str { match *self { CommentStyle::DoubleSlash => "// ", CommentStyle::TripleSlash => "/// ", @@ -52,21 +60,15 @@ impl CommentStyle { CommentStyle::SingleBullet => "/* ", CommentStyle::DoubleBullet => "/** ", CommentStyle::Exclamation => "/*! ", - CommentStyle::Custom => { - if orig.chars().nth(3) == Some(' ') { - &orig[0..4] - } else { - &orig[0..3] - } - } + CommentStyle::Custom(opener) => opener, } } - pub fn closer<'a>(&self) -> &'a str { + pub fn closer(&self) -> &'a str { match *self { CommentStyle::DoubleSlash | CommentStyle::TripleSlash | - CommentStyle::Custom | + CommentStyle::Custom(..) | CommentStyle::Doc => "", CommentStyle::DoubleBullet => " **/", CommentStyle::SingleBullet | @@ -74,7 +76,7 @@ impl CommentStyle { } } - pub fn line_start<'a>(&self, orig: &'a str) -> &'a str { + pub fn line_start(&self) -> &'a str { match *self { CommentStyle::DoubleSlash => "// ", CommentStyle::TripleSlash => "/// ", @@ -82,42 +84,30 @@ impl CommentStyle { CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", CommentStyle::DoubleBullet => " ** ", - CommentStyle::Custom => { - if orig.chars().nth(3) == Some(' ') { - &orig[0..4] - } else { - &orig[0..3] - } - } + CommentStyle::Custom(opener) => opener, } } - pub fn to_str_tuplet<'a>(&self, orig: &'a str) -> (&'a str, &'a str, &'a str) { - (self.opener(orig), self.closer(), self.line_start(orig)) + pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { + (self.opener(), self.closer(), self.line_start()) } - pub fn line_with_same_comment_style<'a>(&self, - line: &str, - orig: &'a str, - normalize_comments: bool) - -> bool { + pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { match *self { CommentStyle::DoubleSlash | CommentStyle::TripleSlash | - CommentStyle::Custom | CommentStyle::Doc => { - line.trim_left() - .starts_with(self.line_start(orig).trim_left()) || + line.trim_left().starts_with(self.line_start().trim_left()) || comment_style(line, normalize_comments) == *self } CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { line.trim_left().starts_with(self.closer().trim_left()) || - line.trim_left() - .starts_with(self.line_start(orig).trim_left()) || + line.trim_left().starts_with(self.line_start().trim_left()) || comment_style(line, normalize_comments) == *self } + CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), } } } @@ -130,19 +120,22 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { CommentStyle::Exclamation } else if orig.starts_with("/*") { CommentStyle::SingleBullet - } else if orig.starts_with("///") { + } else if orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/') { CommentStyle::TripleSlash } else if orig.starts_with("//!") { CommentStyle::Doc + } else if is_custom_comment(orig) { + CommentStyle::Custom(custom_opener(orig)) } else { CommentStyle::DoubleSlash } - } else if orig.starts_with("///") || (orig.starts_with("/**") && !orig.starts_with("/**/")) { + } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) || + (orig.starts_with("/**") && !orig.starts_with("/**/")) { CommentStyle::TripleSlash } else if orig.starts_with("//!") || orig.starts_with("/*!") { CommentStyle::Doc } else if is_custom_comment(orig) { - CommentStyle::Custom + CommentStyle::Custom(custom_opener(orig)) } else { CommentStyle::DoubleSlash } @@ -177,7 +170,7 @@ fn identify_comment(orig: &str, -> Option { let style = comment_style(orig, false); let first_group = orig.lines() - .take_while(|l| style.line_with_same_comment_style(l, orig, false)) + .take_while(|l| style.line_with_same_comment_style(l, false)) .collect::>() .join("\n"); let rest = orig.lines() @@ -185,7 +178,8 @@ fn identify_comment(orig: &str, .collect::>() .join("\n"); - let first_group_str = try_opt!(rewrite_comment_inner(&first_group, block_style, shape, config)); + let first_group_str = + try_opt!(rewrite_comment_inner(&first_group, block_style, style, shape, config)); if rest.is_empty() { Some(first_group_str) } else { @@ -202,13 +196,14 @@ fn identify_comment(orig: &str, fn rewrite_comment_inner(orig: &str, block_style: bool, + style: CommentStyle, shape: Shape, config: &Config) -> Option { let (opener, closer, line_start) = if block_style { - CommentStyle::SingleBullet.to_str_tuplet("") + CommentStyle::SingleBullet.to_str_tuplet() } else { - comment_style(orig, config.normalize_comments()).to_str_tuplet(orig) + comment_style(orig, config.normalize_comments()).to_str_tuplet() }; let max_chars = shape @@ -238,7 +233,7 @@ fn rewrite_comment_inner(orig: &str, line }) - .map(left_trim_comment_line) + .map(|s| left_trim_comment_line(s, &style)) .map(|line| if orig.starts_with("/*") && line_breaks == 0 { line.trim_left() } else { @@ -261,7 +256,7 @@ fn rewrite_comment_inner(orig: &str, let rewrite = rewrite_string(line, &fmt).unwrap_or(line.to_owned()); result.push_str(&rewrite); } else { - if line.is_empty() { + if line.is_empty() && result.ends_with(' ') { // Remove space if this is an empty comment or a doc comment. result.pop(); } @@ -270,7 +265,7 @@ fn rewrite_comment_inner(orig: &str, } result.push_str(closer); - if result == opener { + if result == opener && result.ends_with(' ') { // Trailing space. result.pop(); } @@ -302,15 +297,15 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< /// Trims comment characters and possibly a single space from the left of a string. /// Does not trim all whitespace. -fn left_trim_comment_line(line: &str) -> &str { +fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || line.starts_with("/** ") { &line[4..] - } else if is_custom_comment(line) { - if line.len() > 3 && line.chars().nth(3) == Some(' ') { - &line[4..] + } else if let &CommentStyle::Custom(opener) = style { + if line.starts_with(opener) { + &line[opener.len()..] } else { - &line[3..] + &line[opener.trim_right().len()..] } } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || line.starts_with("///") || diff --git a/tests/source/comment5.rs b/tests/source/comment5.rs index 02dbac8e4f4..2835d8b2578 100644 --- a/tests/source/comment5.rs +++ b/tests/source/comment5.rs @@ -5,4 +5,10 @@ //@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam //@ //@foo -fn test() {} \ No newline at end of file +fn test() {} + +//@@@ another special comment +//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@@@ +//@@@foo +fn bar() {} diff --git a/tests/source/configs-normalize_comments-false.rs b/tests/source/configs-normalize_comments-false.rs index 6bb214330a1..488962ed936 100644 --- a/tests/source/configs-normalize_comments-false.rs +++ b/tests/source/configs-normalize_comments-false.rs @@ -6,3 +6,8 @@ fn dolor() -> usize {} /* sit amet: */ fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/source/configs-normalize_comments-true.rs b/tests/source/configs-normalize_comments-true.rs index 3be75db88c2..c74a9808e61 100644 --- a/tests/source/configs-normalize_comments-true.rs +++ b/tests/source/configs-normalize_comments-true.rs @@ -6,3 +6,8 @@ fn dolor() -> usize {} /* sit amet: */ fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/target/comment5.rs b/tests/target/comment5.rs index 2ca371060d5..c52f9b38977 100644 --- a/tests/target/comment5.rs +++ b/tests/target/comment5.rs @@ -7,3 +7,10 @@ //@ //@ foo fn test() {} + +//@@@ another special comment +//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam +//@@@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@@@ +//@@@ foo +fn bar() {} diff --git a/tests/target/configs-normalize_comments-false.rs b/tests/target/configs-normalize_comments-false.rs index 6bb214330a1..488962ed936 100644 --- a/tests/target/configs-normalize_comments-false.rs +++ b/tests/target/configs-normalize_comments-false.rs @@ -6,3 +6,8 @@ fn dolor() -> usize {} /* sit amet: */ fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/target/configs-normalize_comments-true.rs b/tests/target/configs-normalize_comments-true.rs index e5f2d06fbe8..0bdbe08ab4f 100644 --- a/tests/target/configs-normalize_comments-true.rs +++ b/tests/target/configs-normalize_comments-true.rs @@ -6,3 +6,8 @@ fn dolor() -> usize {} // sit amet: fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// -- cgit 1.4.1-3-g733a5 From 33a735754308b35f1915d03648fa3251479fd70c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 30 May 2017 10:53:48 +0900 Subject: Fix index bug in write_snippet_inner --- src/missed_spans.rs | 2 +- tests/target/issue-1598.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-1598.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index d6157cd6a29..537e9eb7efe 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -173,7 +173,7 @@ impl<'a> FmtVisitor<'a> { if !subslice .split('\n') .map(|s| s.trim_left()) - .any(|s| s.len() > 2 && &s[0..2] == "/*") { + .any(|s| s.len() >= 2 && &s[0..2] == "/*") { // Add a newline after line comments self.buffer.push_str("\n"); } diff --git a/tests/target/issue-1598.rs b/tests/target/issue-1598.rs new file mode 100644 index 00000000000..c7e02c961a6 --- /dev/null +++ b/tests/target/issue-1598.rs @@ -0,0 +1,6 @@ +fn main() { + //foo + /* + */ + format!("hello"); +} -- cgit 1.4.1-3-g733a5 From b63e3aaa83e21ab78254d6bf8a1eb58b2bcccce2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 30 May 2017 20:40:05 +0900 Subject: Put a space between nested tuple field --- src/chains.rs | 8 +++++++- tests/source/tuple.rs | 3 +++ tests/target/tuple.rs | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1c66306022d..752e7110655 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -454,7 +454,13 @@ fn rewrite_chain_subexpr(expr: &ast::Expr, rewrite_method_call(method_name.node, types, expressions, span, context, shape) } ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), - ast::ExprKind::TupField(_, ref field) => rewrite_element(format!(".{}", field.node)), + ast::ExprKind::TupField(ref expr, ref field) => { + let space = match expr.node { + ast::ExprKind::TupField(..) => " ", + _ => "", + }; + rewrite_element(format!("{}.{}", space, field.node)) + } ast::ExprKind::Try(_) => rewrite_element(String::from("?")), _ => unreachable!(), } diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs index d47777734bb..fcfcff3a39b 100644 --- a/tests/source/tuple.rs +++ b/tests/source/tuple.rs @@ -12,6 +12,9 @@ fn foo() { let b = (// This is a comment b, // Comment b /* Trailing comment */); + + // #1063 + foo(x.0 .0); } fn a() { diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 2d3b52da72a..16fc3df020f 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -12,6 +12,9 @@ fn foo() { let b = (// This is a comment b, // Comment b /* Trailing comment */); + + // #1063 + foo(x.0 .0); } fn a() { -- cgit 1.4.1-3-g733a5 From 17995e15392168430208167d1987ede11bd32cc2 Mon Sep 17 00:00:00 2001 From: Ravi Khadiwala Date: Tue, 30 May 2017 19:55:26 -0500 Subject: Expose methods to locate and load config * Make method for searching parents for toml file public * Make method for loading config from path directly public, tweak the API since it was never returning None --- src/bin/rustfmt.rs | 96 ++++++++---------------------------------------------- src/config.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 72946b8374a..3a0a83f5fb1 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -19,11 +19,11 @@ extern crate getopts; use rustfmt::{run, Input, Summary}; use rustfmt::file_lines::FileLines; -use rustfmt::config::{Config, WriteMode}; +use rustfmt::config::{Config, WriteMode, get_toml_path}; use std::{env, error}; -use std::fs::{self, File}; -use std::io::{self, ErrorKind, Read, Write}; +use std::fs::File; +use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -95,78 +95,16 @@ impl CliOptions { } } -const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; - -/// Try to find a project file in the given directory and its parents. Returns the path of a the -/// nearest project file if one exists, or `None` if no project file was found. -fn lookup_project_file(dir: &Path) -> FmtResult> { - let mut current = if dir.is_relative() { - env::current_dir()?.join(dir) - } else { - dir.to_path_buf() - }; - - current = fs::canonicalize(current)?; - - loop { - for config_file_name in &CONFIG_FILE_NAMES { - let config_file = current.join(config_file_name); - match fs::metadata(&config_file) { - // Only return if it's a file to handle the unlikely situation of a directory named - // `rustfmt.toml`. - Ok(ref md) if md.is_file() => return Ok(Some(config_file)), - // Return the error if it's something other than `NotFound`; otherwise we didn't - // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != ErrorKind::NotFound { - return Err(FmtError::from(e)); - } - } - _ => {} - } - } - - // If the current directory has no parent, we're done searching. - if !current.pop() { - return Ok(None); - } - } -} - -fn open_config_file(file_path: &Path) -> FmtResult<(Config, Option)> { - let mut file = File::open(&file_path)?; - let mut toml = String::new(); - file.read_to_string(&mut toml)?; - match Config::from_toml(&toml) { - Ok(cfg) => Ok((cfg, Some(file_path.to_path_buf()))), - Err(err) => Err(FmtError::from(err)), - } -} - -/// Resolve the config for input in `dir`. -/// -/// Returns the `Config` to use, and the path of the project file if there was -/// one. -fn resolve_config(dir: &Path) -> FmtResult<(Config, Option)> { - let path = lookup_project_file(dir)?; - if path.is_none() { - return Ok((Config::default(), None)); - } - open_config_file(&path.unwrap()) -} - /// read the given config file path recursively if present else read the project file path fn match_cli_path_or_file(config_path: Option, input_file: &Path) -> FmtResult<(Config, Option)> { if let Some(config_file) = config_path { - let (toml, path) = open_config_file(config_file.as_ref())?; - if path.is_some() { - return Ok((toml, path)); - } + let toml = Config::from_toml_path(config_file.as_ref())?; + return Ok((toml, Some(config_file))); } - resolve_config(input_file) + Config::from_resolved_toml_path(input_file).map_err(|e| FmtError::from(e)) } fn make_opts() -> Options { @@ -261,16 +199,13 @@ fn execute(opts: &Options) -> FmtResult { } let mut config = Config::default(); - let mut path = None; // Load the config path file if provided - if let Some(config_file) = config_path { - let (cfg_tmp, path_tmp) = open_config_file(config_file.as_ref())?; - config = cfg_tmp; - path = path_tmp; + if let Some(config_file) = config_path.as_ref() { + config = Config::from_toml_path(config_file.as_ref())?; }; if options.verbose { - if let Some(path) = path.as_ref() { + if let Some(path) = config_path.as_ref() { println!("Using rustfmt config file {}", path.display()); } } @@ -285,8 +220,9 @@ fn execute(opts: &Options) -> FmtResult { error_summary.add_operational_error(); } else { // Check the file directory if the config-path could not be read or not provided - if path.is_none() { - let (config_tmp, path_tmp) = resolve_config(file.parent().unwrap())?; + if config_path.is_none() { + let (config_tmp, path_tmp) = + Config::from_resolved_toml_path(file.parent().unwrap())?; if options.verbose { if let Some(path) = path_tmp.as_ref() { println!("Using rustfmt config file {} for {}", @@ -391,13 +327,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), Some(ref path) if path.is_dir() => { - let mut config_file_path = None; - for config_file_name in &CONFIG_FILE_NAMES { - let temp_path = path.join(config_file_name); - if temp_path.is_file() { - config_file_path = Some(temp_path); - } - } + let config_file_path = get_toml_path(path)?; if config_file_path.is_some() { config_file_path } else { diff --git a/src/config.rs b/src/config.rs index 0c73b64c6b2..d0216b1de9f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,6 +11,11 @@ extern crate toml; use std::cell::Cell; +use std::fs; +use std::fs::File; +use std::env; +use std::io::{Error, ErrorKind, Read}; +use std::path::{Path, PathBuf}; use file_lines::FileLines; use lists::{SeparatorTactic, ListTactic}; @@ -347,6 +352,64 @@ macro_rules! create_config { } } + /// Construct a `Config` from the toml file specified at `file_path`. + /// + /// This method only looks at the provided path, for a method that + /// searches parents for an `rls.toml` see `resolve_config`. + /// + /// Return a `Config` if the config could be read and parsed from + /// the file, Error otherwise. + pub fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + /// Resolve the config for input in `dir`. + /// + /// Searches for `rustfmt.toml` beginning with `dir`, and + /// recursively checking parents of `dir` if no config file is found. + /// If no config file exists in `dir` or in any parent, a + /// default `Config` will be returned (and the returned path will be empty). + /// + /// Returns the `Config` to use, and the path of the project file if there was + /// one. + pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + + /// Try to find a project file in the given directory and its parents. + /// Returns the path of a the nearest project file if one exists, + /// or `None` if no project file was found. + fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => () + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + return Ok(None); + } + } + } + + match resolve_project_file(dir)? { + None => Ok((Config::default(), None)), + Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + } + } + + pub fn print_docs() { use std::cmp; let max = 0; @@ -389,6 +452,32 @@ macro_rules! create_config { ) } +/// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +/// +/// Return the path if a config file exists, empty if no file exists, and Error for IO errors +pub fn get_toml_path(dir: &Path) -> Result, Error> { + const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + for config_file_name in &CONFIG_FILE_NAMES { + let config_file = dir.join(config_file_name); + match fs::metadata(&config_file) { + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't + // find the project file yet, and continue searching. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e); + } + } + _ => {} + } + } + Ok(None) +} + + + create_config! { verbose: bool, false, "Use verbose output"; disable_all_formatting: bool, false, "Don't reformat anything"; -- cgit 1.4.1-3-g733a5 From 3d0ea5a099b411537098e36eb0ee06ec60d6f272 Mon Sep 17 00:00:00 2001 From: Ravi Khadiwala Date: Tue, 30 May 2017 22:24:12 -0500 Subject: Fix typo in from_toml_path --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index d0216b1de9f..c4f078c5536 100644 --- a/src/config.rs +++ b/src/config.rs @@ -355,7 +355,7 @@ macro_rules! create_config { /// Construct a `Config` from the toml file specified at `file_path`. /// /// This method only looks at the provided path, for a method that - /// searches parents for an `rls.toml` see `resolve_config`. + /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. /// /// Return a `Config` if the config could be read and parsed from /// the file, Error otherwise. -- cgit 1.4.1-3-g733a5 From 789abf063d04684cea85c8fe4adb3233249da7e8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 1 Jun 2017 12:07:10 +0900 Subject: Use block indent style when visual indent failed --- src/expr.rs | 68 +++++++++++++++++++++++++------------ src/rewrite.rs | 1 + src/visitor.rs | 1 + tests/target/nested-visual-block.rs | 57 +++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 tests/target/nested-visual-block.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a8f1c3a01b5..69f62319ade 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -599,11 +599,14 @@ fn rewrite_closure(capture: ast::CaptureBy, -> Option { // Start with visual indent, then fall back to block indent if the // closure is large. - if let Some(block_str) = block.rewrite(&context, shape) { - let block_threshold = context.config.closure_block_indent_threshold(); - if block_threshold < 0 || block_str.matches('\n').count() <= block_threshold as usize { - if let Some(block_str) = block_str.rewrite(context, shape) { - return Some(format!("{} {}", prefix, block_str)); + let block_threshold = context.config.closure_block_indent_threshold(); + if block_threshold >= 0 { + if let Some(block_str) = block.rewrite(&context, shape) { + if block_str.matches('\n').count() <= block_threshold as usize && + !need_block_indent(&block_str, shape) { + if let Some(block_str) = block_str.rewrite(context, shape) { + return Some(format!("{} {}", prefix, block_str)); + } } } } @@ -1676,20 +1679,40 @@ fn rewrite_call_inner(context: &RewriteContext, .ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); - let span = mk_sp(span_lo, span.hi); + let new_span = mk_sp(span_lo, span.hi); let (extendable, list_str) = rewrite_call_args(context, args, - span, + new_span, nested_shape, one_line_width, force_trailing_comma) .ok_or(Ordering::Less)?; + + if !use_block_indent(context) && need_block_indent(&list_str, nested_shape) && !extendable { + println!("here"); + let mut new_context = context.clone(); + new_context.use_block = true; + return rewrite_call_inner(&new_context, + callee_str, + args, + span, + shape, + force_trailing_comma); + } + Ok(format!("{}{}", callee_str, wrap_args_with_parens(context, &list_str, extendable, shape, nested_shape))) } +fn need_block_indent(s: &str, shape: Shape) -> bool { + s.lines().skip(1).any(|s| { + s.find(|c| !char::is_whitespace(c)) + .map_or(false, |w| w + 1 < shape.indent.width()) + }) +} + fn rewrite_call_args(context: &RewriteContext, args: &[ptr::P], span: Span, @@ -1720,8 +1743,7 @@ fn rewrite_call_args(context: &RewriteContext, // Replace the last item with its first line to see if it fits with // first arguments. if overflow_last { - let arg_shape = if context.config.fn_call_style() == IndentStyle::Block && - is_extendable(args) { + let arg_shape = if use_block_indent(context) && is_extendable(args) { Shape { width: context.config.fn_call_width(), indent: shape.block().indent.block_unindent(context.config), @@ -1799,8 +1821,7 @@ fn rewrite_call_args(context: &RewriteContext, // If arguments do not fit in a single line and do not contain newline, // try to put it on the next line. Try this only when we are in block mode // and not rewriting macro. - Some(ref s) if context.config.fn_call_style() == IndentStyle::Block && - !context.inside_macro && + Some(ref s) if use_block_indent(context) && !context.inside_macro && ((!can_be_overflowed(context, args) && last_char_is_not_comma && s.contains('\n')) || first_line_width(s) > one_line_budget) => { @@ -1814,23 +1835,25 @@ fn rewrite_call_args(context: &RewriteContext, } } +fn use_block_indent(context: &RewriteContext) -> bool { + context.config.fn_call_style() == IndentStyle::Block || context.use_block +} + fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bool { match args.last().map(|x| &x.node) { Some(&ast::ExprKind::Match(..)) => { - (context.config.fn_call_style() == IndentStyle::Block && args.len() == 1) || + (use_block_indent(context) && args.len() == 1) || (context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1) } Some(&ast::ExprKind::Block(..)) | Some(&ast::ExprKind::Closure(..)) => { - context.config.fn_call_style() == IndentStyle::Block || + use_block_indent(context) || context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1 } Some(&ast::ExprKind::Call(..)) | Some(&ast::ExprKind::Mac(..)) | - Some(&ast::ExprKind::Struct(..)) => { - context.config.fn_call_style() == IndentStyle::Block && args.len() == 1 - } - Some(&ast::ExprKind::Tup(..)) => context.config.fn_call_style() == IndentStyle::Block, + Some(&ast::ExprKind::Struct(..)) => use_block_indent(context) && args.len() == 1, + Some(&ast::ExprKind::Tup(..)) => use_block_indent(context), _ => false, } } @@ -1865,8 +1888,8 @@ fn wrap_args_with_parens(context: &RewriteContext, shape: Shape, nested_shape: Shape) -> String { - if context.config.fn_call_style() == IndentStyle::Visual || - (context.inside_macro && !args_str.contains('\n')) || is_extendable { + if !use_block_indent(context) || (context.inside_macro && !args_str.contains('\n')) || + is_extendable { if context.config.spaces_within_parens() && args_str.len() > 0 { format!("( {} )", args_str) } else { @@ -2062,9 +2085,10 @@ fn shape_from_fn_call_style(context: &RewriteContext, overhead: usize, offset: usize) -> Option { - match context.config.fn_call_style() { - IndentStyle::Block => Some(shape.block().block_indent(context.config.tab_spaces())), - IndentStyle::Visual => shape.visual_indent(offset).sub_width(overhead), + if use_block_indent(context) { + Some(shape.block().block_indent(context.config.tab_spaces())) + } else { + shape.visual_indent(offset).sub_width(overhead) } } diff --git a/src/rewrite.rs b/src/rewrite.rs index c1047e41b33..272e67756ab 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -27,6 +27,7 @@ pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, pub config: &'a Config, pub inside_macro: bool, + pub use_block: bool, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index 9ce200a915e..affcbf6b082 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -610,6 +610,7 @@ impl<'a> FmtVisitor<'a> { codemap: self.codemap, config: self.config, inside_macro: false, + use_block: false, } } } diff --git a/tests/target/nested-visual-block.rs b/tests/target/nested-visual-block.rs new file mode 100644 index 00000000000..7dd75c52891 --- /dev/null +++ b/tests/target/nested-visual-block.rs @@ -0,0 +1,57 @@ +fn main() { + // #1078 + let items = itemize_list( + context.codemap, + field_iter, + "}", + |item| match *item { + StructLitField::Regular(ref field) => field.span.lo, + StructLitField::Base(ref expr) => { + let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }, + |item| match *item { + StructLitField::Regular(ref field) => field.span.hi, + StructLitField::Base(ref expr) => expr.span.hi, + }, + |item| { + match *item { + StructLitField::Regular(ref field) => { + rewrite_field(inner_context, + &field, + &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent)) + } + StructLitField::Base(ref expr) => { + // 2 = .. + expr.rewrite(inner_context, + &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2)) + .map(|s| format!("..{}", s)) + } + } + }, + context.codemap.span_after(span, "{"), + span.hi, + ); + + // #1580 + self.0.pool.execute(move || { + let _timer = segments.0.rotate_timer.time(); + if let Err(e) = segments.rotate_async(wal) { + error!("error compacting segment storage WAL", unsafe { error: e.display() }); + } + }); + + // #1581 + bootstrap.checks.register( + "PERSISTED_LOCATIONS", + move || if locations2.0.inner_mut.lock().poisoned { + Check::new(State::Error, + "Persisted location storage is poisoned due to a write failure") + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + } + ); +} -- cgit 1.4.1-3-g733a5 From 10c3632078b986e1712f40ce5d39801a7e76b511 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 1 Jun 2017 12:08:09 +0900 Subject: Format source codes --- src/expr.rs | 16 +++++++++------- src/lib.rs | 32 +++++++++++++++++--------------- src/macros.rs | 4 ++-- 3 files changed, 28 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 69f62319ade..8e0a5aca984 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -968,13 +968,15 @@ impl<'a> Rewrite for ControlFlow<'a> { }; // for event in event - let between_kwd_cond = mk_sp(context.codemap.span_after(self.span, self.keyword.trim()), - self.pat - .map_or(cond_span.lo, |p| if self.matcher.is_empty() { - p.span.lo - } else { - context.codemap.span_before(self.span, self.matcher.trim()) - })); + let between_kwd_cond = mk_sp( + context.codemap.span_after(self.span, self.keyword.trim()), + self.pat + .map_or(cond_span.lo, |p| if self.matcher.is_empty() { + p.span.lo + } else { + context.codemap.span_before(self.span, self.matcher.trim()) + }), + ); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); diff --git a/src/lib.rs b/src/lib.rs index 49125e6ff9c..e89235631fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -610,22 +610,24 @@ pub fn format_input(input: Input, let mut report = FormatReport::new(); - match format_ast(&krate, - &parse_session, - &main_file, - config, - |file_name, file| { - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(file); - - format_lines(file, file_name, config, &mut report); - - if let Some(ref mut out) = out { - return filemap::write_file(file, file_name, out, config); + match format_ast( + &krate, + &parse_session, + &main_file, + config, + |file_name, file| { + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(file); + + format_lines(file, file_name, config, &mut report); + + if let Some(ref mut out) = out { + return filemap::write_file(file, file_name, out, config); + } + Ok(false) } - Ok(false) - }) { + ) { Ok((file_map, has_diff)) => { if report.has_warnings() { summary.add_formatting_error(); diff --git a/src/macros.rs b/src/macros.rs index 3c6c54f42cf..1193e4819eb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -205,10 +205,10 @@ pub fn rewrite_macro(mac: &ast::Mac, context .codemap .span_after(mac.span, original_style.opener()), - mac.span.hi - BytePos(1) + mac.span.hi - BytePos(1), ), context, - mac_shape + mac_shape, )); Some(format!("{}{}", macro_name, rewrite)) -- cgit 1.4.1-3-g733a5 From fbd4b87329324e3d53064601cccf7c8e4ced5b31 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 1 Jun 2017 19:59:50 +0900 Subject: Use correct one line budget when using Rfc control style --- src/expr.rs | 28 +++++++++++++++++----------- tests/target/configs-control_style-rfc.rs | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 tests/target/configs-control_style-rfc.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a8f1c3a01b5..b05c7ba6c97 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -326,23 +326,29 @@ pub fn rewrite_pair(lhs: &LHS, // Re-evaluate the rhs because we have more space now: let infix = infix.trim_right(); - let lhs_budget = try_opt!(context - .config - .max_width() - .checked_sub(shape.used_width() + prefix.len() + infix.len())); let rhs_shape = match context.config.control_style() { Style::Default => { try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) } - Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces())), + Style::Rfc => { + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + } }; let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); - let lhs_result = try_opt!(lhs.rewrite(context, - Shape { - width: lhs_budget, - ..shape - })); + let lhs_shape = match context.config.control_style() { + Style::Default => { + let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); + Shape { + width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), + ..shape + } + } + Style::Rfc => try_opt!(shape.sub_width(prefix.len() + infix.len())), + }; + let lhs_result = try_opt!(lhs.rewrite(context, lhs_shape)); Some(format!("{}{}{}\n{}{}{}", prefix, lhs_result, @@ -906,7 +912,7 @@ impl<'a> Rewrite for ControlFlow<'a> { Some(cond) => { let mut cond_shape = match context.config.control_style() { Style::Default => try_opt!(constr_shape.shrink_left(add_offset)), - Style::Rfc => constr_shape, + Style::Rfc => try_opt!(constr_shape.sub_width(add_offset)), }; if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { // 2 = " {".len() diff --git a/tests/target/configs-control_style-rfc.rs b/tests/target/configs-control_style-rfc.rs new file mode 100644 index 00000000000..a7213c34dfb --- /dev/null +++ b/tests/target/configs-control_style-rfc.rs @@ -0,0 +1,23 @@ +// rustfmt-control_style: Rfc + +// #1618 +fn main() { + loop { + if foo { + if ((right_paddle_speed < 0.) && + (right_paddle.position().y - paddle_size.y / 2. > 5.)) || + ((right_paddle_speed > 0.) && + (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) + { + foo + } + if ai_timer.elapsed_time().as_microseconds() > ai_time.as_microseconds() { + if ball.position().y + ball_radius > + right_paddle.position().y + paddle_size.y / 2. + { + foo + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From cdc3f9321cbb88bc336eb7a2ef76e7f8c5dabf06 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 2 Jun 2017 11:44:38 +1200 Subject: Rename the Style::Default option to Legacy --- src/config.rs | 6 +++--- src/expr.rs | 6 +++--- tests/source/configs-where_style-default.rs | 2 +- tests/target/configs-where_style-default.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c4f078c5536..1d912093c2e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -33,7 +33,7 @@ macro_rules! configuration_option_enum{ configuration_option_enum! { Style: Rfc, // Follow the style RFCs style. - Default, // Follow the traditional Rustfmt style. + Legacy, // Follow the traditional Rustfmt style. } configuration_option_enum! { NewlineStyle: @@ -498,7 +498,7 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; - control_style: Style, Style::Default, "Indent style for control flow statements"; + control_style: Style, Style::Legacy, "Indent style for control flow statements"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, "Brace style for control flow constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; @@ -517,7 +517,7 @@ create_config! { "Maximum width of an array literal before falling back to vertical formatting"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - where_style: Style, Style::Default, "Overall strategy for where clauses"; + where_style: Style, Style::Legacy, "Overall strategy for where clauses"; // TODO: // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? diff --git a/src/expr.rs b/src/expr.rs index ed896231ba9..c9b9284bb30 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -327,7 +327,7 @@ pub fn rewrite_pair(lhs: &LHS, // Re-evaluate the rhs because we have more space now: let infix = infix.trim_right(); let rhs_shape = match context.config.control_style() { - Style::Default => { + Style::Legacy => { try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) } Style::Rfc => { @@ -339,7 +339,7 @@ pub fn rewrite_pair(lhs: &LHS, let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); let lhs_shape = match context.config.control_style() { - Style::Default => { + Style::Legacy => { let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); Shape { width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), @@ -914,7 +914,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let pat_expr_string = match self.cond { Some(cond) => { let mut cond_shape = match context.config.control_style() { - Style::Default => try_opt!(constr_shape.shrink_left(add_offset)), + Style::Legacy => try_opt!(constr_shape.shrink_left(add_offset)), Style::Rfc => try_opt!(constr_shape.sub_width(add_offset)), }; if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { diff --git a/tests/source/configs-where_style-default.rs b/tests/source/configs-where_style-default.rs index 98f514b0c1e..e082f863f33 100644 --- a/tests/source/configs-where_style-default.rs +++ b/tests/source/configs-where_style-default.rs @@ -1,4 +1,4 @@ -// rustfmt-where_style: Default +// rustfmt-where_style: Legacy // Where style fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { diff --git a/tests/target/configs-where_style-default.rs b/tests/target/configs-where_style-default.rs index 3e1a3c93dfe..2971ac4c5e6 100644 --- a/tests/target/configs-where_style-default.rs +++ b/tests/target/configs-where_style-default.rs @@ -1,4 +1,4 @@ -// rustfmt-where_style: Default +// rustfmt-where_style: Legacy // Where style fn lorem() -> T -- cgit 1.4.1-3-g733a5 From 5650411d643d6ec3ec145d044ae549d73134e029 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 2 Jun 2017 11:20:49 +0900 Subject: Fix a typo --- src/expr.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c9b9284bb30..7e1e3922d6a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1698,7 +1698,6 @@ fn rewrite_call_inner(context: &RewriteContext, .ok_or(Ordering::Less)?; if !use_block_indent(context) && need_block_indent(&list_str, nested_shape) && !extendable { - println!("here"); let mut new_context = context.clone(); new_context.use_block = true; return rewrite_call_inner(&new_context, -- cgit 1.4.1-3-g733a5 From aadd3e11f40e41753c52781d73aa9b228461a303 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 2 Jun 2017 11:58:19 +0900 Subject: Unindent comment on top of `else` --- src/expr.rs | 6 +++++- src/rewrite.rs | 4 ++++ src/visitor.rs | 26 ++++++++++++++++++++++---- tests/target/unindent_if_else_cond_comment.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 tests/target/unindent_if_else_cond_comment.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7e1e3922d6a..16dfe6fcaa6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -666,6 +666,7 @@ impl Rewrite for ast::Block { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = shape.indent; + visitor.is_if_else_block = context.is_if_else_block; let prefix = match self.rules { ast::BlockCheckMode::Unsafe(..) => { @@ -965,7 +966,10 @@ impl<'a> Rewrite for ControlFlow<'a> { width: block_width, ..shape }; - let block_str = try_opt!(self.block.rewrite(context, block_shape)); + let mut block_context = context.clone(); + block_context.is_if_else_block = self.else_block.is_some(); + + let block_str = try_opt!(self.block.rewrite(&block_context, block_shape)); let cond_span = if let Some(cond) = self.cond { cond.span diff --git a/src/rewrite.rs b/src/rewrite.rs index 272e67756ab..9713871880e 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -27,7 +27,11 @@ pub struct RewriteContext<'a> { pub codemap: &'a CodeMap, pub config: &'a Config, pub inside_macro: bool, + // Force block indent style even if we are using visual indent style. pub use_block: bool, + // When `format_if_else_cond_comment` is true, unindent the comment on top + // of the `else` or `else if`. + pub is_if_else_block: bool, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index affcbf6b082..33e9812ee1f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -56,6 +56,7 @@ pub struct FmtVisitor<'a> { pub block_indent: Indent, pub config: &'a Config, pub failed: bool, + pub is_if_else_block: bool, } impl<'a> FmtVisitor<'a> { @@ -117,9 +118,22 @@ impl<'a> FmtVisitor<'a> { } } + let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); + if unindent_comment { + let end_pos = source!(self, b.span).hi - brace_compensation; + let snippet = self.get_context() + .snippet(codemap::mk_sp(self.last_pos, end_pos)); + unindent_comment = snippet.contains("//") || snippet.contains("/*"); + } // FIXME: we should compress any newlines here to just one + if unindent_comment { + self.block_indent = self.block_indent.block_unindent(self.config); + } self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation); - self.close_block(); + if unindent_comment { + self.block_indent = self.block_indent.block_indent(self.config); + } + self.close_block(unindent_comment); self.last_pos = source!(self, b.span).hi; } @@ -127,9 +141,11 @@ impl<'a> FmtVisitor<'a> { // item in the block and the closing brace to the block's level. // The closing brace itself, however, should be indented at a shallower // level. - fn close_block(&mut self) { + fn close_block(&mut self, unindent_comment: bool) { let total_len = self.buffer.len; - let chars_too_many = if self.config.hard_tabs() { + let chars_too_many = if unindent_comment { + 0 + } else if self.config.hard_tabs() { 1 } else { self.config.tab_spaces() @@ -484,6 +500,7 @@ impl<'a> FmtVisitor<'a> { block_indent: Indent::empty(), config: config, failed: false, + is_if_else_block: false, } } @@ -587,7 +604,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.walk_mod_items(m); self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1)); - self.close_block(); + self.close_block(false); } self.last_pos = source!(self, m.inner).hi; } else { @@ -611,6 +628,7 @@ impl<'a> FmtVisitor<'a> { config: self.config, inside_macro: false, use_block: false, + is_if_else_block: false, } } } diff --git a/tests/target/unindent_if_else_cond_comment.rs b/tests/target/unindent_if_else_cond_comment.rs new file mode 100644 index 00000000000..98621b1eed1 --- /dev/null +++ b/tests/target/unindent_if_else_cond_comment.rs @@ -0,0 +1,27 @@ +// Comments on else block. See #1575. + +fn example() { + // `if` comment + if x { + foo(); + // `else if` comment + } else if y { + foo(); + // Comment on `else if`. + // Comment on `else if`. + } else if z { + bar(); + /* + * Multi line comment on `else if` + */ + } else if xx { + bar(); + /* Single line comment on `else if` */ + } else if yy { + foo(); + // `else` comment + } else { + foo(); + // Comment at the end of `else` block + }; +} -- cgit 1.4.1-3-g733a5 From 08b53757762ef9fa4a510bd461bdc029e452eb2f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 3 Jun 2017 15:01:04 +0900 Subject: Forbid trailing comma at the end of args of variadic functions --- src/items.rs | 6 +++++- tests/source/configs-fn_args_layout-block.rs | 6 ++++++ tests/target/configs-fn_args_layout-block.rs | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 644837bd30b..c8cb3b6d262 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1944,7 +1944,11 @@ fn rewrite_args(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: trailing_comma, + trailing_separator: if variadic { + SeparatorTactic::Never + } else { + trailing_comma + }, shape: Shape::legacy(budget, indent), ends_with_newline: end_with_newline, config: context.config, diff --git a/tests/source/configs-fn_args_layout-block.rs b/tests/source/configs-fn_args_layout-block.rs index eb09b941c33..55b38101abc 100644 --- a/tests/source/configs-fn_args_layout-block.rs +++ b/tests/source/configs-fn_args_layout-block.rs @@ -14,3 +14,9 @@ extern "system" { pub fn GetConsoleHistoryInfo(console_history_info: *mut ConsoleHistoryInfo) -> Boooooooooooooool; } +// rustfmt should not add trailing comma for variadic function. See #1623. +extern "C" { + pub fn variadic_fn(first_parameter: FirstParameterType, + second_parameter: SecondParameterType, + ...); +} diff --git a/tests/target/configs-fn_args_layout-block.rs b/tests/target/configs-fn_args_layout-block.rs index 586d118b210..04a4d631ca4 100644 --- a/tests/target/configs-fn_args_layout-block.rs +++ b/tests/target/configs-fn_args_layout-block.rs @@ -23,3 +23,12 @@ extern "system" { console_history_info: *mut ConsoleHistoryInfo, ) -> Boooooooooooooool; } + +// rustfmt should not add trailing comma for variadic function. See #1623. +extern "C" { + pub fn variadic_fn( + first_parameter: FirstParameterType, + second_parameter: SecondParameterType, + ... + ); +} -- cgit 1.4.1-3-g733a5 From d21792a73086e3517545c56a5c620bf3dd414cdc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 3 Jun 2017 23:16:29 +0900 Subject: Put opening paren next to multi line generic --- src/items.rs | 5 ++++- tests/target/fn-custom-2.rs | 3 +-- tests/target/fn-custom-3.rs | 3 +-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 644837bd30b..46867f5b9de 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1587,7 +1587,10 @@ fn rewrite_fn_base(context: &RewriteContext, let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); result.push_str(&generics_str); - let snuggle_angle_bracket = last_line_width(&generics_str) == 1; + let snuggle_angle_bracket = generics_str + .lines() + .last() + .map_or(false, |l| l.trim_left().len() == 1); // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index c2b012e52ab..e9ba39f666c 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -52,8 +52,7 @@ impl Foo { 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW - > - ( + >( a: Aaaaaaaaaaaaaaa, ) { bar(); diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 309b1cd7eea..a29aac411ba 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -54,8 +54,7 @@ impl Foo { 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW - > - ( + >( a: Aaaaaaaaaaaaaaa, ) { bar(); -- cgit 1.4.1-3-g733a5 From 9b7ba980cf9b7f69a8c637aec9c7e2bb9d0fc931 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 3 Jun 2017 23:17:30 +0900 Subject: Use correct budget --- src/items.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 46867f5b9de..ac46c908a01 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1998,10 +1998,10 @@ fn compute_budgets_for_args(context: &RewriteContext, if one_line_budget > 0 { // 4 = "() {".len() - let multi_line_budget = try_opt!(context - .config - .max_width() - .checked_sub(indent.width() + result.len() + 4)); + let multi_line_overhead = indent.width() + result.len() + + if newline_brace { 2 } else { 4 }; + let multi_line_budget = + try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); return Some((one_line_budget, multi_line_budget, indent + result.len() + 1)); } @@ -2009,14 +2009,10 @@ fn compute_budgets_for_args(context: &RewriteContext, // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(context.config); - let used_space = new_indent.width() + 4; // Account for `(` and `)` and possibly ` {`. - let max_space = context.config.max_width(); - if used_space <= max_space { - Some((0, max_space - used_space, new_indent)) - } else { - // Whoops! bankrupt. - None - } + // Account for `)` and possibly ` {`. + let used_space = new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }; + let max_space = try_opt!(context.config.max_width().checked_sub(used_space)); + Some((0, max_space, new_indent)) } fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { -- cgit 1.4.1-3-g733a5 From dd13761f85f078160f22b947c95bd1461ed23d1b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 3 Jun 2017 23:18:39 +0900 Subject: Organize vertical layout of function definition --- src/items.rs | 30 +++++++++++++++++------------- tests/target/issue-1624.rs | 9 +++++++++ 2 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 tests/target/issue-1624.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ac46c908a01..051fb0617d9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1622,24 +1622,28 @@ fn rewrite_fn_base(context: &RewriteContext, // Check if vertical layout was forced. if one_line_budget == 0 { if snuggle_angle_bracket { - result.push_str("("); - } else if context.config.fn_args_paren_newline() { - result.push('\n'); - result.push_str(&arg_indent.to_string(context.config)); - arg_indent = arg_indent + 1; // extra space for `(` result.push('('); - if context.config.spaces_within_parens() && fd.inputs.len() > 0 { - result.push(' ') - } } else { - result.push_str("(\n"); - result.push_str(&arg_indent.to_string(context.config)); + if context.config.fn_args_paren_newline() { + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + if context.config.fn_args_layout() == IndentStyle::Visual { + arg_indent = arg_indent + 1; // extra space for `(` + } + result.push('('); + } else { + result.push_str("("); + if context.config.fn_args_layout() == IndentStyle::Visual { + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + } + } } } else { result.push('('); - if context.config.spaces_within_parens() && fd.inputs.len() > 0 { - result.push(' ') - } + } + if context.config.spaces_within_parens() && fd.inputs.len() > 0 && result.ends_with('(') { + result.push(' ') } if multi_line_ret_str { diff --git a/tests/target/issue-1624.rs b/tests/target/issue-1624.rs new file mode 100644 index 00000000000..dcdb18611a6 --- /dev/null +++ b/tests/target/issue-1624.rs @@ -0,0 +1,9 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_paren_newline: false + +// #1624 +pub unsafe fn some_long_function_name( + arg1: Type1, + arg2: Type2, +) -> (SomeLongTypeName, AnotherLongTypeName, AnotherLongTypeName) { +} -- cgit 1.4.1-3-g733a5 From 15e936bfc73c3c488512fd3dbce43625fa723c29 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 4 Jun 2017 06:29:08 +0900 Subject: Preserve the layout of comment after return type --- src/items.rs | 24 ++++++++++++++++++++---- tests/target/issue-1113.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 tests/target/issue-1113.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 644837bd30b..f76ae1c1a4b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -259,10 +259,11 @@ impl<'a> FmtVisitor<'a> { has_body, true)); - if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine && !result.contains('\n') { - newline_brace = false; - } else if force_newline_brace { + if force_newline_brace { newline_brace = true; + } else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine && + !result.contains('\n') { + newline_brace = false; } // Prepare for the function body by possibly adding a newline and @@ -1757,10 +1758,25 @@ fn rewrite_fn_base(context: &RewriteContext, if where_clause.predicates.is_empty() { let snippet_hi = span.hi; let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); + // Try to preserve the layout of the original snippet. + let original_starts_with_newline = + snippet + .find(|c| c != ' ') + .map_or(false, |i| snippet[i..].starts_with('\n')); + let original_ends_with_newline = snippet + .rfind(|c| c != ' ') + .map_or(false, |i| snippet[i..].ends_with('\n')); let snippet = snippet.trim(); if !snippet.is_empty() { - result.push(' '); + result.push(if original_starts_with_newline { + '\n' + } else { + ' ' + }); result.push_str(snippet); + if original_ends_with_newline { + force_new_line_for_brace = true; + } } } else { // FIXME it would be nice to catch comments between the return type diff --git a/tests/target/issue-1113.rs b/tests/target/issue-1113.rs new file mode 100644 index 00000000000..1245bcd057c --- /dev/null +++ b/tests/target/issue-1113.rs @@ -0,0 +1,33 @@ +pub fn foo() -> fmt::Result +//pub fn writeStringToken +{ + panic!() +} + +pub fn foo() -> fmt::Result // pub fn writeStringToken +{ + panic!() +} + +pub fn foo() -> fmt::Result /* pub fn writeStringToken */ { + panic!() +} + +pub fn foo() -> fmt::Result +/* pub fn writeStringToken */ { + panic!() +} + +pub fn foo() -> fmt::Result +/* pub fn writeStringToken */ +{ + panic!() +} + +pub fn foo() -> fmt::Result /* + * + * + */ +{ + panic!() +} -- cgit 1.4.1-3-g733a5 From d54634bd7cde07b276e431fc167119e13a8aef81 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 4 Jun 2017 18:35:17 +0900 Subject: Use recover_comment_removed in rewrite_static --- src/items.rs | 15 +++++++++++++-- src/visitor.rs | 4 ++++ tests/target/comment-inside-const.rs | 9 +++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/target/comment-inside-const.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 91221e1ccc6..10359f53bdd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,7 +18,7 @@ use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wr use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; -use comment::{FindUncommented, contains_comment, rewrite_comment}; +use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity}; @@ -1299,6 +1299,7 @@ pub fn rewrite_static(prefix: &str, mutability: ast::Mutability, expr_opt: Option<&ptr::P>, offset: Indent, + span: Span, context: &RewriteContext) -> Option { let type_annotation_spacing = type_annotation_spacing(context.config); @@ -1325,7 +1326,17 @@ pub fn rewrite_static(prefix: &str, lhs, expr, Shape::legacy(remaining_width, offset.block_only())) - .map(|s| s + ";") + .and_then(|res| { + recover_comment_removed(res, + span, + context, + Shape { + width: context.config.max_width(), + indent: offset, + offset: offset.alignment, + }) + }) + .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { let lhs = format!("{}{};", prefix, ty_str); Some(lhs) diff --git a/src/visitor.rs b/src/visitor.rs index affcbf6b082..5f594aad898 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -322,6 +322,7 @@ impl<'a> FmtVisitor<'a> { mutability, Some(expr), self.block_indent, + item.span, &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -333,6 +334,7 @@ impl<'a> FmtVisitor<'a> { ast::Mutability::Immutable, Some(expr), self.block_indent, + item.span, &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -383,6 +385,7 @@ impl<'a> FmtVisitor<'a> { ast::Mutability::Immutable, expr_opt.as_ref(), self.block_indent, + ti.span, &self.get_context()); self.push_rewrite(ti.span, rewrite); } @@ -434,6 +437,7 @@ impl<'a> FmtVisitor<'a> { ast::Mutability::Immutable, Some(expr), self.block_indent, + ii.span, &self.get_context()); self.push_rewrite(ii.span, rewrite); } diff --git a/tests/target/comment-inside-const.rs b/tests/target/comment-inside-const.rs new file mode 100644 index 00000000000..f847f2c69de --- /dev/null +++ b/tests/target/comment-inside-const.rs @@ -0,0 +1,9 @@ +fn issue982() { + const SOME_CONSTANT: u32 = + // Explanation why SOME_CONSTANT needs FLAG_A to be set. + FLAG_A | + // Explanation why SOME_CONSTANT needs FLAG_B to be set. + FLAG_B | + // Explanation why SOME_CONSTANT needs FLAG_C to be set. + FLAG_C; +} -- cgit 1.4.1-3-g733a5 From fef347cb9e9c1ee7b52b7076846f1397c00d1022 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 3 Jun 2017 22:43:12 +0900 Subject: Add `use_block_indent` method to RewriteContext --- src/chains.rs | 6 ++---- src/rewrite.rs | 7 ++++++- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 752e7110655..dca785593bb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -229,7 +229,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } // Try overflowing the last element if we are using block indent. - if !fits_single_line && context.config.fn_call_style() == IndentStyle::Block { + if !fits_single_line && context.use_block_indent() { let (init, last) = rewrites.split_at_mut(last_non_try_index); let almost_single_line = init.iter().all(|s| !s.contains('\n')); if almost_single_line { @@ -339,9 +339,7 @@ fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { match expr.node { - ast::ExprKind::Call(..) => { - context.config.fn_call_style() == IndentStyle::Block && repr.contains('\n') - } + ast::ExprKind::Call(..) => context.use_block_indent() && repr.contains('\n'), ast::ExprKind::Struct(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | diff --git a/src/rewrite.rs b/src/rewrite.rs index 9713871880e..28bb6fe6b59 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -14,7 +14,7 @@ use syntax::codemap::{CodeMap, Span}; use syntax::parse::ParseSess; use Shape; -use config::Config; +use config::{Config, IndentStyle}; pub trait Rewrite { /// Rewrite self into shape. @@ -38,4 +38,9 @@ impl<'a> RewriteContext<'a> { pub fn snippet(&self, span: Span) -> String { self.codemap.span_to_snippet(span).unwrap() } + + /// Return true if we should use block indent style for rewriting function call. + pub fn use_block_indent(&self) -> bool { + self.config.fn_call_style() == IndentStyle::Block || self.use_block + } } -- cgit 1.4.1-3-g733a5 From a01ad304596832ac0b546265200f85e69e8723da Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 3 Jun 2017 22:44:21 +0900 Subject: Forbid line break between if and pattern --- src/expr.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 16dfe6fcaa6..a1bdf995603 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -928,6 +928,7 @@ impl<'a> Rewrite for ControlFlow<'a> { cond, self.matcher, self.connector, + self.keyword, cond_shape)) } None => String::new(), @@ -1529,6 +1530,7 @@ fn rewrite_pat_expr(context: &RewriteContext, // Connecting piece between pattern and expression, // *without* trailing space. connector: &str, + keyword: &str, shape: Shape) -> Option { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); @@ -1567,6 +1569,10 @@ fn rewrite_pat_expr(context: &RewriteContext, } } + if pat.is_none() && keyword == "if" { + return None; + } + let nested_indent = shape.indent.block_only().block_indent(context.config); // The expression won't fit on the current line, jump to next. -- cgit 1.4.1-3-g733a5 From b548d8d77339eefb46ca6a0c38fa430ddb05017a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 3 Jun 2017 22:49:29 +0900 Subject: Refactor rewrite_call --- src/expr.rs | 225 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 105 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a1bdf995603..8ce2ea6d236 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::cmp::{Ordering, min}; -use std::mem::swap; use std::ops::Deref; use std::iter::ExactSizeIterator; use std::fmt::Write; @@ -1376,7 +1375,7 @@ impl Rewrite for ast::Arm { ast::ExprKind::Tup(..) => (true, &**body), _ => (false, &**body), }; - extend &= context.config.fn_call_style() == IndentStyle::Block; + extend &= context.use_block_indent(); let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + @@ -1697,17 +1696,17 @@ fn rewrite_call_inner(context: &RewriteContext, .ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); - let new_span = mk_sp(span_lo, span.hi); + let args_span = mk_sp(span_lo, span.hi); let (extendable, list_str) = rewrite_call_args(context, args, - new_span, + args_span, nested_shape, one_line_width, force_trailing_comma) .ok_or(Ordering::Less)?; - if !use_block_indent(context) && need_block_indent(&list_str, nested_shape) && !extendable { + if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { let mut new_context = context.clone(); new_context.use_block = true; return rewrite_call_inner(&new_context, @@ -1752,41 +1751,49 @@ fn rewrite_call_args(context: &RewriteContext, // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. - let overflow_last = can_be_overflowed(&item_context, args); + let tactic = try_overflow_last_arg(&item_context, &mut item_vec, args, shape, one_line_width); - let mut orig_last = None; - let mut placeholder = None; - - // Replace the last item with its first line to see if it fits with - // first arguments. - if overflow_last { - let arg_shape = if use_block_indent(context) && is_extendable(args) { - Shape { - width: context.config.fn_call_width(), - indent: shape.block().indent.block_unindent(context.config), - offset: 0, - } + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: if force_trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro || !context.use_block_indent() { + SeparatorTactic::Never } else { - shape.block() - }; - let rewrite = args.last().unwrap().rewrite(&item_context, arg_shape); - swap(&mut item_vec[args.len() - 1].item, &mut orig_last); + context.config.trailing_comma() + }, + shape: shape, + ends_with_newline: false, + config: context.config, + }; - if let Some(rewrite) = rewrite { - let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); - placeholder = Some(rewrite); + write_list(&item_vec, &fmt).map(|args_str| (tactic != DefinitiveListTactic::Vertical, args_str)) +} - item_vec[args.len() - 1].item = rewrite_first_line; - } - } +fn try_overflow_last_arg(context: &RewriteContext, + item_vec: &mut Vec, + args: &[ptr::P], + shape: Shape, + one_line_width: usize) + -> DefinitiveListTactic { + let overflow_last = can_be_overflowed(&context, args); - let one_line_shape = Shape { - width: one_line_width, - ..shape + // Replace the last item with its first line to see if it fits with + // first arguments. + let (orig_last, placeholder) = if overflow_last { + last_arg_shape(&context, &item_vec, shape).map_or((None, None), |arg_shape| { + rewrite_last_arg_with_overflow(&context, + &args[args.len() - 1], + &mut item_vec[args.len() - 1], + arg_shape) + }) + } else { + (None, None) }; let tactic = - definitive_tactic(&item_vec, + definitive_tactic(&*item_vec, ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()), one_line_width); @@ -1802,100 +1809,78 @@ fn rewrite_call_args(context: &RewriteContext, (false, _, _) => {} } - let mut fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: if force_trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro || context.config.fn_call_style() == IndentStyle::Visual || - args.len() <= 1 { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - shape: one_line_shape, - ends_with_newline: false, - config: context.config, - }; + tactic +} - let one_line_budget = min(one_line_width, context.config.fn_call_width()); - let almost_no_newline = - item_vec - .iter() - .rev() - .skip(1) - .all(|item| item.item.as_ref().map_or(false, |s| !s.contains('\n'))); - let extendable = almost_no_newline && - item_vec.iter().fold(0, |acc, item| { - acc + item.item.as_ref().map_or(0, |s| 2 + first_line_width(s)) - }) <= one_line_budget + 2; - - let result = write_list(&item_vec, &fmt); - let last_char_is_not_comma = result - .as_ref() - .map_or(false, |r| r.chars().last().unwrap_or(' ') != ','); - match result { - // If arguments do not fit in a single line and do not contain newline, - // try to put it on the next line. Try this only when we are in block mode - // and not rewriting macro. - Some(ref s) if use_block_indent(context) && !context.inside_macro && - ((!can_be_overflowed(context, args) && last_char_is_not_comma && - s.contains('\n')) || - first_line_width(s) > one_line_budget) => { - fmt.trailing_separator = SeparatorTactic::Vertical; - fmt.tactic = DefinitiveListTactic::Vertical; - write_list(&item_vec, &fmt).map(|rw| (false, rw)) - } - rewrite @ _ => { - rewrite.map(|rw| (extendable && (last_char_is_not_comma || force_trailing_comma), rw)) - } - } +fn last_arg_shape(context: &RewriteContext, items: &Vec, shape: Shape) -> Option { + let overhead = items.iter().rev().skip(1).fold(0, |acc, i| { + acc + i.item.as_ref().map_or(0, |s| first_line_width(&s)) + }); + let max_width = min(context.config.fn_call_width(), shape.width); + let arg_indent = if context.use_block_indent() { + shape.block().indent.block_unindent(context.config) + } else { + shape.block().indent + }; + Some(Shape { + width: try_opt!(max_width.checked_sub(overhead)), + indent: arg_indent, + offset: 0, + }) } -fn use_block_indent(context: &RewriteContext) -> bool { - context.config.fn_call_style() == IndentStyle::Block || context.use_block +fn rewrite_last_arg_with_overflow(context: &RewriteContext, + last_arg: &ptr::P, + last_item: &mut ListItem, + shape: Shape) + -> (Option, Option) { + let rewrite = last_arg.rewrite(context, shape); + let orig_last = last_item.item.clone(); + + if let Some(rewrite) = rewrite { + let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); + last_item.item = rewrite_first_line; + (orig_last, Some(rewrite)) + } else { + (orig_last, None) + } } fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bool { - match args.last().map(|x| &x.node) { - Some(&ast::ExprKind::Match(..)) => { - (use_block_indent(context) && args.len() == 1) || - (context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1) - } - Some(&ast::ExprKind::Block(..)) | - Some(&ast::ExprKind::Closure(..)) => { - use_block_indent(context) || - context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1 - } - Some(&ast::ExprKind::Call(..)) | - Some(&ast::ExprKind::Mac(..)) | - Some(&ast::ExprKind::Struct(..)) => use_block_indent(context) && args.len() == 1, - Some(&ast::ExprKind::Tup(..)) => use_block_indent(context), - _ => false, - } + args.last() + .map_or(false, |x| can_be_overflowed_expr(context, &x, args.len())) } -fn is_extendable(args: &[ptr::P]) -> bool { - if args.len() == 1 { - match args[0].node { - ast::ExprKind::Block(..) | - ast::ExprKind::Call(..) | - ast::ExprKind::Closure(..) | - ast::ExprKind::Match(..) | - ast::ExprKind::Mac(..) | - ast::ExprKind::Struct(..) | - ast::ExprKind::Tup(..) => true, - _ => false, - } - } else if args.len() > 1 { - match args[args.len() - 1].node { - ast::ExprKind::Block(..) | - ast::ExprKind::Closure(..) | - ast::ExprKind::Tup(..) => true, - _ => false, - } - } else { - false +fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { + match expr.node { + ast::ExprKind::Match(..) => { + (context.use_block_indent() && args_len == 1) || + (context.config.fn_call_style() == IndentStyle::Visual && args_len > 1) + } + ast::ExprKind::If(..) | + ast::ExprKind::IfLet(..) | + ast::ExprKind::ForLoop(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) => { + context.use_block_indent() && args_len == 1 + } + ast::ExprKind::Block(..) | + ast::ExprKind::Closure(..) => { + context.use_block_indent() || + context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 + } + ast::ExprKind::Call(..) | + ast::ExprKind::MethodCall(..) | + ast::ExprKind::Mac(..) | + ast::ExprKind::Struct(..) => context.use_block_indent() && args_len == 1, + ast::ExprKind::Tup(..) => context.use_block_indent(), + ast::ExprKind::AddrOf(_, ref expr) | + ast::ExprKind::Box(ref expr) | + ast::ExprKind::Try(ref expr) | + ast::ExprKind::Unary(_, ref expr) | + ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), + _ => false, } } @@ -1905,7 +1890,7 @@ fn wrap_args_with_parens(context: &RewriteContext, shape: Shape, nested_shape: Shape) -> String { - if !use_block_indent(context) || (context.inside_macro && !args_str.contains('\n')) || + if !context.use_block_indent() || (context.inside_macro && !args_str.contains('\n')) || is_extendable { if context.config.spaces_within_parens() && args_str.len() > 0 { format!("( {} )", args_str) @@ -2102,7 +2087,7 @@ fn shape_from_fn_call_style(context: &RewriteContext, overhead: usize, offset: usize) -> Option { - if use_block_indent(context) { + if context.use_block_indent() { Some(shape.block().block_indent(context.config.tab_spaces())) } else { shape.visual_indent(offset).sub_width(overhead) -- cgit 1.4.1-3-g733a5 From 4a0094f28f114333e1a1fe105c4dd57f3c838a7b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 3 Jun 2017 22:50:13 +0900 Subject: Add combine_control_expr option --- Configurations.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/config.rs | 3 ++- src/expr.rs | 10 ++++++---- 3 files changed, 64 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index a0c6ba407d9..605f5d63291 100644 --- a/Configurations.md +++ b/Configurations.md @@ -166,6 +166,62 @@ lorem_ipsum(|| { }); ``` +## `combine_control_expr` + +Combine control expressions with function calls. + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `true` + +```rust +fn example() { + // If + foo!(if x { + foo(); + } else { + bar(); + }); + + // IfLet + foo!(if let Some(..) = x { + foo(); + } else { + bar(); + }); + + // While + foo!(while x { + foo(); + bar(); + }); + + // WhileLet + foo!(while let Some(..) = x { + foo(); + bar(); + }); + + // ForLoop + foo!(for x in y { + foo(); + bar(); + }); + + // Loop + foo!(loop { + foo(); + bar(); + }); +} +``` + +#### `false` + +```rust +``` + ## `comment_width` Maximum length of comments. No effect unless`wrap_comments = true`. diff --git a/src/config.rs b/src/config.rs index 1d912093c2e..d4bff961e74 100644 --- a/src/config.rs +++ b/src/config.rs @@ -575,7 +575,8 @@ create_config! { write_mode: WriteMode, WriteMode::Replace, "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ - tuple patterns" + tuple patterns"; + combine_control_expr: bool, true, "Combine control expressions with funciton calls." } #[cfg(test)] diff --git a/src/expr.rs b/src/expr.rs index 8ce2ea6d236..0ec459f8e19 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -980,12 +980,14 @@ impl<'a> Rewrite for ControlFlow<'a> { // for event in event let between_kwd_cond = mk_sp( context.codemap.span_after(self.span, self.keyword.trim()), - self.pat - .map_or(cond_span.lo, |p| if self.matcher.is_empty() { + self.pat.map_or( + cond_span.lo, + |p| if self.matcher.is_empty() { p.span.lo } else { context.codemap.span_before(self.span, self.matcher.trim()) - }), + }, + ), ); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -1863,7 +1865,7 @@ fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: ast::ExprKind::Loop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => { - context.use_block_indent() && args_len == 1 + context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { -- cgit 1.4.1-3-g733a5 From a9f529cba4f30567d1ae96110dae235dc7a21348 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 3 Jun 2017 22:50:44 +0900 Subject: Format source codes --- src/filemap.rs | 5 +++-- src/items.rs | 26 +++++++++++++------------- src/lib.rs | 2 +- src/macros.rs | 26 +++++++++++--------------- src/missed_spans.rs | 5 +++-- src/types.rs | 38 ++++++++++++++++++++------------------ 6 files changed, 51 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index d1486e94e39..aa3ae8537af 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -143,8 +143,9 @@ pub fn write_file(text: &StringBuffer, if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { let mismatch = make_diff(&ori, &fmt, 3); let has_diff = !mismatch.is_empty(); - print_diff(mismatch, - |line_num| format!("Diff in {} at line {}:", filename, line_num)); + print_diff(mismatch, |line_num| { + format!("Diff in {} at line {}:", filename, line_num) + }); return Ok(has_diff); } } diff --git a/src/items.rs b/src/items.rs index 91221e1ccc6..3406b331c4d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1162,20 +1162,20 @@ pub fn rewrite_type_alias(context: &RewriteContext, let type_indent = indent + line_width; // Try to fit the type on the same line let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)) - .or_else(|| { - // The line was too short, try to put the type on the next line + .or_else(|| { + // The line was too short, try to put the type on the next line - // Remove the space after '=' - result.pop(); - let type_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context - .config - .max_width() - .checked_sub(type_indent.width() + ";".len())); - ty.rewrite(context, Shape::legacy(budget, type_indent)) - })); + // Remove the space after '=' + result.pop(); + let type_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&type_indent.to_string(context.config)); + let budget = try_opt!(context + .config + .max_width() + .checked_sub(type_indent.width() + ";".len())); + ty.rewrite(context, Shape::legacy(budget, type_indent)) + })); result.push_str(&ty_str); result.push_str(";"); Some(result) diff --git a/src/lib.rs b/src/lib.rs index e89235631fb..1635553eccd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -626,7 +626,7 @@ pub fn format_input(input: Input, return filemap::write_file(file, file_name, out, config); } Ok(false) - } + }, ) { Ok((file_map, has_diff)) => { if report.has_warnings() { diff --git a/src/macros.rs b/src/macros.rs index 1193e4819eb..f99e236ac88 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -172,12 +172,12 @@ pub fn rewrite_macro(mac: &ast::Mac, MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map(|rw| { - match position { + rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map( + |rw| match position { MacroPosition::Item => format!("{};", rw), _ => rw, - } - }) + }, + ) } MacroStyle::Brackets => { let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); @@ -199,17 +199,13 @@ pub fn rewrite_macro(mac: &ast::Mac, } else { // Format macro invocation as array literal. let rewrite = - try_opt!(rewrite_array( - expr_vec.iter().map(|x| &**x), - mk_sp( - context - .codemap - .span_after(mac.span, original_style.opener()), - mac.span.hi - BytePos(1), - ), - context, - mac_shape, - )); + try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), + mk_sp(context + .codemap + .span_after(mac.span, original_style.opener()), + mac.span.hi - BytePos(1)), + context, + mac_shape)); Some(format!("{}{}", macro_name, rewrite)) } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 537e9eb7efe..57ebc332ac4 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -22,8 +22,9 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, - |this, last_snippet, _| this.buffer.push_str(last_snippet)) + self.format_missing_inner(end, |this, last_snippet, _| { + this.buffer.push_str(last_snippet) + }) } pub fn format_missing_with_indent(&mut self, end: BytePos) { diff --git a/src/types.rs b/src/types.rs index adade891075..9ddfe8d6efe 100644 --- a/src/types.rs +++ b/src/types.rs @@ -377,11 +377,12 @@ impl Rewrite for ast::WherePredicate { let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(shape.width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) - }) - .collect::>>()) + .iter() + .map(|ty_bound| { + ty_bound + .rewrite(context, Shape::legacy(budget, shape.indent + used_width)) + }) + .collect::>>()) .join(joiner); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { @@ -401,11 +402,12 @@ impl Rewrite for ast::WherePredicate { let used_width = type_str.len() + colon.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); let bounds_str: String = try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) - }) - .collect::>>()) + .iter() + .map(|ty_bound| { + ty_bound + .rewrite(context, Shape::legacy(budget, shape.indent + used_width)) + }) + .collect::>>()) .join(joiner); format!("{}{}{}", type_str, colon, bounds_str) @@ -700,14 +702,14 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. result.push_str(&try_opt!(bare_fn - .lifetimes - .iter() - .map(|l| { - l.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) - }) - .collect::>>()) - .join(", ")); + .lifetimes + .iter() + .map(|l| { + l.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) + }) + .collect::>>()) + .join(", ")); result.push_str("> "); } -- cgit 1.4.1-3-g733a5 From fabbef2c3eaad7326e60cbb7c4c818bfaccb3178 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 4 Jun 2017 15:21:30 +0900 Subject: Add macro to block expr --- src/chains.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index dca785593bb..c7c0b82a64d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -339,6 +339,7 @@ fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { match expr.node { + ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => context.use_block_indent() && repr.contains('\n'), ast::ExprKind::Struct(..) | ast::ExprKind::While(..) | -- cgit 1.4.1-3-g733a5 From b49269ad399e33c5c5ea2cd9a01376221ea2c62e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 4 Jun 2017 15:23:00 +0900 Subject: Forbid method chain to get combined if it uses multi line. If the method chain goes multi line before the last element, disallow combining the method chain. --- src/chains.rs | 3 +++ src/expr.rs | 5 +++++ src/rewrite.rs | 2 ++ src/visitor.rs | 1 + 4 files changed, 11 insertions(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c7c0b82a64d..a56b8cf196d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -252,6 +252,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - String::new() } else { // Use new lines. + if context.force_one_line_chain { + return None; + } format!("\n{}", nested_shape.indent.to_string(context.config)) }; diff --git a/src/expr.rs b/src/expr.rs index 0ec459f8e19..46e030bd094 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1784,6 +1784,11 @@ fn try_overflow_last_arg(context: &RewriteContext, // Replace the last item with its first line to see if it fits with // first arguments. let (orig_last, placeholder) = if overflow_last { + let mut context = context.clone(); + match args[args.len() - 1].node { + ast::ExprKind::MethodCall(..) => context.force_one_line_chain = true, + _ => (), + } last_arg_shape(&context, &item_vec, shape).map_or((None, None), |arg_shape| { rewrite_last_arg_with_overflow(&context, &args[args.len() - 1], diff --git a/src/rewrite.rs b/src/rewrite.rs index 28bb6fe6b59..5c1236104b5 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -32,6 +32,8 @@ pub struct RewriteContext<'a> { // When `format_if_else_cond_comment` is true, unindent the comment on top // of the `else` or `else if`. pub is_if_else_block: bool, + // When rewriting chain, veto going multi line except the last element + pub force_one_line_chain: bool, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index 33e9812ee1f..d7d54a819e2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -629,6 +629,7 @@ impl<'a> FmtVisitor<'a> { inside_macro: false, use_block: false, is_if_else_block: false, + force_one_line_chain: false, } } } -- cgit 1.4.1-3-g733a5 From dcc7f32152f9469969460e0d45efd7742647fb6e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 4 Jun 2017 15:25:07 +0900 Subject: Format source codes --- src/items.rs | 32 +++++++++++++++++--------------- src/types.rs | 51 ++++++++++++++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3406b331c4d..015cb5b4eef 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1161,21 +1161,23 @@ pub fn rewrite_type_alias(context: &RewriteContext, .unwrap_or(0); let type_indent = indent + line_width; // Try to fit the type on the same line - let ty_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, type_indent)) - .or_else(|| { - // The line was too short, try to put the type on the next line - - // Remove the space after '=' - result.pop(); - let type_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context - .config - .max_width() - .checked_sub(type_indent.width() + ";".len())); - ty.rewrite(context, Shape::legacy(budget, type_indent)) - })); + let ty_str = try_opt!( + ty.rewrite(context, Shape::legacy(budget, type_indent)) + .or_else(|| { + // The line was too short, try to put the type on the next line + + // Remove the space after '=' + result.pop(); + let type_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&type_indent.to_string(context.config)); + let budget = try_opt!(context + .config + .max_width() + .checked_sub(type_indent.width() + ";".len())); + ty.rewrite(context, Shape::legacy(budget, type_indent)) + }) + ); result.push_str(&ty_str); result.push_str(";"); Some(result) diff --git a/src/types.rs b/src/types.rs index 9ddfe8d6efe..bec23579cda 100644 --- a/src/types.rs +++ b/src/types.rs @@ -376,13 +376,15 @@ impl Rewrite for ast::WherePredicate { // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound - .rewrite(context, Shape::legacy(budget, shape.indent + used_width)) - }) - .collect::>>()) + let bounds_str: String = try_opt!( + bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(budget, shape.indent + used_width)) + }) + .collect::>>() + ) .join(joiner); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { @@ -401,13 +403,15 @@ impl Rewrite for ast::WherePredicate { }; let used_width = type_str.len() + colon.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound - .rewrite(context, Shape::legacy(budget, shape.indent + used_width)) - }) - .collect::>>()) + let bounds_str: String = try_opt!( + bounds + .iter() + .map(|ty_bound| { + ty_bound.rewrite(context, + Shape::legacy(budget, shape.indent + used_width)) + }) + .collect::>>() + ) .join(joiner); format!("{}{}{}", type_str, colon, bounds_str) @@ -701,15 +705,16 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. - result.push_str(&try_opt!(bare_fn - .lifetimes - .iter() - .map(|l| { - l.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) - }) - .collect::>>()) - .join(", ")); + result.push_str(&try_opt!( + bare_fn + .lifetimes + .iter() + .map(|l| { + l.rewrite(context, + Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) + }) + .collect::>>() + ).join(", ")); result.push_str("> "); } -- cgit 1.4.1-3-g733a5 From d7de5b7656dcdca403b3560c7c9c2ebb335f8567 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 4 Jun 2017 23:27:21 +0900 Subject: Allow comments after attributes on enum fields --- src/items.rs | 75 +++++++++++++++++++++++++++++++++++----------------- tests/source/enum.rs | 11 ++++++++ tests/target/enum.rs | 12 +++++++++ 3 files changed, 74 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 91221e1ccc6..777b9df1f05 100644 --- a/src/items.rs +++ b/src/items.rs @@ -456,15 +456,30 @@ impl<'a> FmtVisitor<'a> { return Some(self.snippet(span)); } + let context = self.get_context(); let indent = self.block_indent; - let mut result = try_opt!(field.node.attrs.rewrite(&self.get_context(), - Shape::indented(indent, self.config))); + let mut result = try_opt!(field + .node + .attrs + .rewrite(&context, Shape::indented(indent, self.config))); if !result.is_empty() { - result.push('\n'); - result.push_str(&indent.to_string(self.config)); + let shape = Shape { + width: context.config.max_width(), + indent: self.block_indent, + offset: self.block_indent.alignment, + }; + let missing_comment = + rewrite_missing_comment_on_field(&context, + shape, + field.node.attrs[field.node.attrs.len() - 1] + .span + .hi, + field.span.lo, + &mut result) + .unwrap_or(String::new()); + result.push_str(&missing_comment); } - let context = self.get_context(); let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { @@ -1194,6 +1209,31 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { }) } +fn rewrite_missing_comment_on_field(context: &RewriteContext, + shape: Shape, + lo: BytePos, + hi: BytePos, + result: &mut String) + -> Option { + let possibly_comment_snippet = context.snippet(mk_sp(lo, hi)); + let newline_index = possibly_comment_snippet.find('\n'); + let comment_index = possibly_comment_snippet.find('/'); + match (newline_index, comment_index) { + (Some(i), Some(j)) if i > j => result.push(' '), + _ => { + result.push('\n'); + result.push_str(&shape.indent.to_string(context.config)); + } + } + let trimmed = possibly_comment_snippet.trim(); + if trimmed.is_empty() { + None + } else { + rewrite_comment(trimmed, false, shape, context.config) + .map(|s| format!("{}\n{}", s, shape.indent.to_string(context.config))) + } +} + impl Rewrite for ast::StructField { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if contains_skip(&self.attrs) { @@ -1208,25 +1248,12 @@ impl Rewrite for ast::StructField { context.config))); // Try format missing comments after attributes let missing_comment = if !self.attrs.is_empty() { - let possibly_comment_snippet = - context.snippet(mk_sp(self.attrs[self.attrs.len() - 1].span.hi, self.span.lo)); - let newline_index = possibly_comment_snippet.find('\n'); - let comment_index = possibly_comment_snippet.find('/'); - match (newline_index, comment_index) { - (Some(i), Some(j)) if i > j => attr_str.push(' '), - _ => { - attr_str.push('\n'); - attr_str.push_str(&shape.indent.to_string(context.config)); - } - } - let trimmed = possibly_comment_snippet.trim(); - if trimmed.is_empty() { - String::new() - } else { - rewrite_comment(trimmed, false, shape, context.config).map_or(String::new(), |s| { - format!("{}\n{}", s, shape.indent.to_string(context.config)) - }) - } + rewrite_missing_comment_on_field(context, + shape, + self.attrs[self.attrs.len() - 1].span.hi, + self.span.lo, + &mut attr_str) + .unwrap_or(String::new()) } else { String::new() }; diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 70a688428d2..0e2e2c066c3 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -98,3 +98,14 @@ fn nested_enum_test() { pub struct EmtpyWithComment { // FIXME: Implement this struct } + +// #1115 +pub enum Bencoding<'i> { + Str(&'i [u8]), + Int(i64), + List(Vec>), + /// A bencoded dict value. The first element the slice of bytes in the source that the dict is + /// composed of. The second is the dict, decoded into an ordered map. + // TODO make Dict "structlike" AKA name the two values. + Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 9121221c9c4..3e0e46d3fae 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -127,3 +127,15 @@ fn nested_enum_test() { pub struct EmtpyWithComment { // FIXME: Implement this struct } + +// #1115 +pub enum Bencoding<'i> { + Str(&'i [u8]), + Int(i64), + List(Vec>), + /// A bencoded dict value. The first element the slice of bytes in the + /// source that the dict is + /// composed of. The second is the dict, decoded into an ordered map. + // TODO make Dict "structlike" AKA name the two values. + Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), +} -- cgit 1.4.1-3-g733a5 From 0292640e147f0e9debb83f396b4304a2eb3bb4c2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 5 Jun 2017 15:31:05 +0900 Subject: Allow chain item to extend if the parent ends with closing parens and alike --- src/chains.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index a56b8cf196d..c48fdeb0b66 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -117,22 +117,18 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape)); let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); + let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let first_subexpr_is_try = match subexpr_list.last().unwrap().node { - ast::ExprKind::Try(..) => true, - _ => false, - }; + let first_subexpr_is_try = subexpr_list.last().map_or(false, is_try); let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { let nested_shape = if first_subexpr_is_try { parent_shape.block_indent(context.config.tab_spaces()) } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) }; - (nested_shape, - context.config.chain_indent() == IndentStyle::Visual || - parent_rewrite.len() <= context.config.tab_spaces()) + (nested_shape, context.config.chain_indent() == IndentStyle::Visual || is_small_parent) } else if is_block_expr(context, &parent, &parent_rewrite) { match context.config.chain_indent() { // Try to put the first child on the same line with parent's last line @@ -258,26 +254,47 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - format!("\n{}", nested_shape.indent.to_string(context.config)) }; - let first_connector = if subexpr_list.is_empty() { - "" - } else if extend || first_subexpr_is_try { - // 1 = ";", being conservative here. - if last_line_width(&parent_rewrite) + first_line_width(&rewrites[0]) + 1 <= - context.config.max_width() { - "" - } else { - &*connector - } + let first_connector = choose_first_connector(context, + &parent_rewrite, + &rewrites[0], + &connector, + &subexpr_list, + extend); + + if is_small_parent && rewrites.len() > 1 { + let second_connector = choose_first_connector(context, + &rewrites[0], + &rewrites[1], + &connector, + &subexpr_list[0..subexpr_list.len() - 1], + false); + wrap_str(format!("{}{}{}{}{}", + parent_rewrite, + first_connector, + rewrites[0], + second_connector, + join_rewrites(&rewrites[1..], + &subexpr_list[0..subexpr_list.len() - 1], + &connector)), + context.config.max_width(), + shape) } else { - &*connector - }; + wrap_str(format!("{}{}{}", + parent_rewrite, + first_connector, + join_rewrites(&rewrites, &subexpr_list, &connector)), + context.config.max_width(), + shape) + } +} - wrap_str(format!("{}{}{}", - parent_rewrite, - first_connector, - join_rewrites(&rewrites, &subexpr_list, &connector)), - context.config.max_width(), - shape) +fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { + context.config.chain_indent() == IndentStyle::Block && + parent_str.lines().last().map_or(false, |s| { + s.trim() + .chars() + .all(|c| c == ')' || c == ']' || c == '}' || c == '?') + }) } // True if the chain is only `?`s. @@ -476,6 +493,36 @@ fn is_continuable(expr: &ast::Expr) -> bool { } } +fn is_try(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Try(..) => true, + _ => false, + } +} + +fn choose_first_connector<'a>(context: &RewriteContext, + parent_str: &str, + first_child_str: &str, + connector: &'a str, + subexpr_list: &[ast::Expr], + extend: bool) + -> &'a str { + if subexpr_list.is_empty() { + "" + } else if extend || subexpr_list.last().map_or(false, is_try) || + is_extendable_parent(context, parent_str) { + // 1 = ";", being conservative here. + if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <= + context.config.max_width() { + "" + } else { + connector + } + } else { + connector + } +} + fn rewrite_method_call(method_name: ast::Ident, types: &[ptr::P], args: &[ptr::P], -- cgit 1.4.1-3-g733a5 From 41b7cc6a730f9c0b68a06df21a59467e6c7d0a4c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 5 Jun 2017 15:31:44 +0900 Subject: Set combine_control_expr to false by default and true in rfc-rustfmt --- rfc-rustfmt.toml | 1 + src/config.rs | 2 +- tests/target/combining.rs | 120 ------------------- tests/target/configs-combine_control_expr-false.rs | 133 +++++++++++++++++++++ tests/target/configs-combine_control_expr-true.rs | 121 +++++++++++++++++++ 5 files changed, 256 insertions(+), 121 deletions(-) delete mode 100644 tests/target/combining.rs create mode 100644 tests/target/configs-combine_control_expr-false.rs create mode 100644 tests/target/configs-combine_control_expr-true.rs (limited to 'src') diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml index 0e622bdd943..e286dcb4b7f 100644 --- a/rfc-rustfmt.toml +++ b/rfc-rustfmt.toml @@ -4,3 +4,4 @@ control_style = "Rfc" where_style = "Rfc" generics_indent = "Block" fn_call_style = "Block" +combine_control_expr = true diff --git a/src/config.rs b/src/config.rs index d4bff961e74..c61b03b88d7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -576,7 +576,7 @@ create_config! { "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns"; - combine_control_expr: bool, true, "Combine control expressions with funciton calls." + combine_control_expr: bool, false, "Combine control expressions with funciton calls." } #[cfg(test)] diff --git a/tests/target/combining.rs b/tests/target/combining.rs deleted file mode 100644 index de9ee656f68..00000000000 --- a/tests/target/combining.rs +++ /dev/null @@ -1,120 +0,0 @@ -// rustfmt-fn_call_style: Block -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. - -fn main() { - // Call - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Mac - foo(foo!( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // MethodCall - foo(x.foo::( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Block - foo!({ - foo(); - bar(); - }); - - // Closure - foo(|x| { - let y = x + 1; - y - }); - - // Match - foo(match opt { - Some(x) => x, - None => y, - }); - - // Struct - foo(Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // If - foo!(if x { - foo(); - } else { - bar(); - }); - - // IfLet - foo!(if let Some(..) = x { - foo(); - } else { - bar(); - }); - - // While - foo!(while x { - foo(); - bar(); - }); - - // WhileLet - foo!(while let Some(..) = x { - foo(); - bar(); - }); - - // ForLoop - foo!(for x in y { - foo(); - bar(); - }); - - // Loop - foo!(loop { - foo(); - bar(); - }); - - // Tuple - foo(( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // AddrOf - foo(&bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // Unary - foo(!bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Try - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )?); - - // Cast - foo(Bar { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - } as i64); -} diff --git a/tests/target/configs-combine_control_expr-false.rs b/tests/target/configs-combine_control_expr-false.rs new file mode 100644 index 00000000000..0d9ab24a6ed --- /dev/null +++ b/tests/target/configs-combine_control_expr-false.rs @@ -0,0 +1,133 @@ +// rustfmt-fn_call_style: Block +// rustfmt-combine_control_expr: false +// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. + +fn main() { + // Call + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Mac + foo(foo!( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // MethodCall + foo(x.foo::( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Block + foo!({ + foo(); + bar(); + }); + + // Closure + foo(|x| { + let y = x + 1; + y + }); + + // Match + foo(match opt { + Some(x) => x, + None => y, + }); + + // Struct + foo(Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // If + foo!( + if x { + foo(); + } else { + bar(); + } + ); + + // IfLet + foo!( + if let Some(..) = x { + foo(); + } else { + bar(); + } + ); + + // While + foo!( + while x { + foo(); + bar(); + } + ); + + // WhileLet + foo!( + while let Some(..) = x { + foo(); + bar(); + } + ); + + // ForLoop + foo!( + for x in y { + foo(); + bar(); + } + ); + + // Loop + foo!( + loop { + foo(); + bar(); + } + ); + + // Tuple + foo(( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // AddrOf + foo(&bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Box + foo(box Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // Unary + foo(!bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Try + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )?); + + // Cast + foo(Bar { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + } as i64); +} diff --git a/tests/target/configs-combine_control_expr-true.rs b/tests/target/configs-combine_control_expr-true.rs new file mode 100644 index 00000000000..925d2233539 --- /dev/null +++ b/tests/target/configs-combine_control_expr-true.rs @@ -0,0 +1,121 @@ +// rustfmt-fn_call_style: Block +// rustfmt-combine_control_expr: true +// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. + +fn main() { + // Call + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Mac + foo(foo!( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // MethodCall + foo(x.foo::( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Block + foo!({ + foo(); + bar(); + }); + + // Closure + foo(|x| { + let y = x + 1; + y + }); + + // Match + foo(match opt { + Some(x) => x, + None => y, + }); + + // Struct + foo(Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // If + foo!(if x { + foo(); + } else { + bar(); + }); + + // IfLet + foo!(if let Some(..) = x { + foo(); + } else { + bar(); + }); + + // While + foo!(while x { + foo(); + bar(); + }); + + // WhileLet + foo!(while let Some(..) = x { + foo(); + bar(); + }); + + // ForLoop + foo!(for x in y { + foo(); + bar(); + }); + + // Loop + foo!(loop { + foo(); + bar(); + }); + + // Tuple + foo(( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // AddrOf + foo(&bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Box + foo(box Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // Unary + foo(!bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Try + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )?); + + // Cast + foo(Bar { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + } as i64); +} -- cgit 1.4.1-3-g733a5 From 7250a468f978991e87e9f8dfd19ed74af903c21f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 5 Jun 2017 15:32:21 +0900 Subject: Format source codes --- src/chains.rs | 6 +++--- src/types.rs | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c48fdeb0b66..204f0b80423 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -164,9 +164,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .into_iter() .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); let iter = subexpr_list.iter().rev().zip(child_shape_iter); - let mut rewrites = - try_opt!(iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) - .collect::>>()); + let mut rewrites = try_opt!(iter.map(|(e, shape)| { + rewrite_chain_subexpr(e, total_span, context, shape) + }).collect::>>()); // Total of all items excluding the last. let last_non_try_index = rewrites.len() - (1 + trailing_try_num); diff --git a/src/types.rs b/src/types.rs index bec23579cda..17e9a467d1b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -384,8 +384,7 @@ impl Rewrite for ast::WherePredicate { Shape::legacy(budget, shape.indent + used_width)) }) .collect::>>() - ) - .join(joiner); + ).join(joiner); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", @@ -411,8 +410,7 @@ impl Rewrite for ast::WherePredicate { Shape::legacy(budget, shape.indent + used_width)) }) .collect::>>() - ) - .join(joiner); + ).join(joiner); format!("{}{}{}", type_str, colon, bounds_str) } -- cgit 1.4.1-3-g733a5 From 86be2e7bf85bd2c052b2d10c23fb6d4f5fe1424f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 5 Jun 2017 17:57:43 +0900 Subject: Do not add offset to match pattern when using Rfc style --- src/expr.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 16dfe6fcaa6..ebf5c519fac 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1205,8 +1205,10 @@ fn rewrite_match(context: &RewriteContext, } // `match `cond` {` - let cond_shape = try_opt!(shape.shrink_left(6)); - let cond_shape = try_opt!(cond_shape.sub_width(2)); + let cond_shape = match context.config.control_style() { + Style::Legacy => try_opt!(shape.shrink_left(6).and_then(|s| s.sub_width(2))), + Style::Rfc => try_opt!(shape.sub_width(8)), + }; let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style() { -- cgit 1.4.1-3-g733a5 From aa4cd311bb07ea25d89096e8fdd5d64b73666c28 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 6 Jun 2017 03:11:17 +0200 Subject: Add config options for spaces around the colon in struct literal fields In Rust, colons are used for three purposes: * Type annotations, including type ascription * Trait bounds * Struct literal fields This commit adds options for the last missing of the three purposes, struct literal fields. --- Configurations.md | 54 ++++++++++++++++++++++ src/config.rs | 4 ++ src/expr.rs | 10 ++-- src/items.rs | 10 +++- ...igs-space_after_struct_lit_field_colon-false.rs | 6 +++ ...figs-space_after_struct_lit_field_colon-true.rs | 6 +++ ...gs-space_before_struct_lit_field_colon-false.rs | 6 +++ ...igs-space_before_struct_lit_field_colon-true.rs | 6 +++ ...igs-space_after_struct_lit_field_colon-false.rs | 6 +++ ...figs-space_after_struct_lit_field_colon-true.rs | 6 +++ ...gs-space_before_struct_lit_field_colon-false.rs | 6 +++ ...igs-space_before_struct_lit_field_colon-true.rs | 6 +++ tests/target/space-before-type-annotation.rs | 2 +- .../space-not-after-type-annotation-colon.rs | 2 +- 14 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 tests/source/configs-space_after_struct_lit_field_colon-false.rs create mode 100644 tests/source/configs-space_after_struct_lit_field_colon-true.rs create mode 100644 tests/source/configs-space_before_struct_lit_field_colon-false.rs create mode 100644 tests/source/configs-space_before_struct_lit_field_colon-true.rs create mode 100644 tests/target/configs-space_after_struct_lit_field_colon-false.rs create mode 100644 tests/target/configs-space_after_struct_lit_field_colon-true.rs create mode 100644 tests/target/configs-space_before_struct_lit_field_colon-false.rs create mode 100644 tests/target/configs-space_before_struct_lit_field_colon-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index a0c6ba407d9..0b0a5570356 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1123,6 +1123,33 @@ fn lorem(t: T) { See also: [`space_before_bound`](#space_before_bound). +## `space_after_struct_lit_field_colon` + +Leave a space after the colon in a struct literal field + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `false`: + +```rust +let lorem = Lorem { + ipsum:dolor, + sit:amet, +}; +``` + +#### `true`: + +```rust +let lorem = Lorem { + ipsum: dolor, + sit: amet, +}; +``` + +See also: [`space_before_struct_lit_field_colon`](#space_before_struct_lit_field_colon). + ## `space_after_type_annotation_colon` Leave a space after the colon in a type annotation @@ -1173,6 +1200,33 @@ fn lorem(t: T) { See also: [`space_after_bound_colon`](#space_after_bound_colon). +## `space_before_struct_lit_field_colon` + +Leave a space before the colon in a struct literal field + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `false`: + +```rust +let lorem = Lorem { + ipsum: dolor, + sit: amet, +}; +``` + +#### `true`: + +```rust +let lorem = Lorem { + ipsum : dolor, + sit : amet, +}; +``` + +See also: [`space_after_struct_lit_field_colon`](#space_after_struct_lit_field_colon). + ## `space_before_type_annotation` Leave a space before the colon in a type annotation diff --git a/src/config.rs b/src/config.rs index 1d912093c2e..112d8e35d1d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -564,6 +564,10 @@ create_config! { "Leave a space before the colon in a type annotation"; space_after_type_annotation_colon: bool, true, "Leave a space after the colon in a type annotation"; + space_before_struct_lit_field_colon: bool, false, + "Leave a space before the colon in a struct literal field"; + space_after_struct_lit_field_colon: bool, true, + "Leave a space after the colon in a struct literal field"; space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound"; space_after_bound_colon: bool, true, "Leave a space after the colon in a trait or lifetime bound"; diff --git a/src/expr.rs b/src/expr.rs index 16dfe6fcaa6..8392ab438cd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2050,18 +2050,18 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // FIXME if context.config.struct_lit_style() == Visual, but we run out // of space, we should fall back to BlockIndent. } - -pub fn type_annotation_separator(config: &Config) -> &str { - colon_spaces(config.space_before_type_annotation(), - config.space_after_type_annotation_colon()) +pub fn struct_lit_field_separator(config: &Config) -> &str { + colon_spaces(config.space_before_struct_lit_field_colon(), + config.space_after_struct_lit_field_colon()) } + fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { let name = &field.ident.node.to_string(); if field.is_shorthand { Some(name.to_string()) } else { - let separator = type_annotation_separator(context.config); + let separator = struct_lit_field_separator(context.config); let overhead = name.len() + separator.len(); let mut expr_shape = try_opt!(shape.sub_width(overhead)); expr_shape.offset += overhead; diff --git a/src/items.rs b/src/items.rs index fdcf96454c7..bf7933b547c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -14,10 +14,10 @@ use {Indent, Shape}; use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, - trimmed_last_line_width}; + trimmed_last_line_width, colon_spaces}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; -use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, type_annotation_separator}; +use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; @@ -27,6 +27,12 @@ use syntax::{ast, abi, codemap, ptr, symbol}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::ast::ImplItem; +fn type_annotation_separator(config: &Config) -> &str { + colon_spaces(config.space_before_type_annotation(), + config.space_after_type_annotation_colon()) +} + + // Statements of the form // let pat: ty = init; impl Rewrite for ast::Local { diff --git a/tests/source/configs-space_after_struct_lit_field_colon-false.rs b/tests/source/configs-space_after_struct_lit_field_colon-false.rs new file mode 100644 index 00000000000..3ee99fa5d1d --- /dev/null +++ b/tests/source/configs-space_after_struct_lit_field_colon-false.rs @@ -0,0 +1,6 @@ +// rustfmt-space_after_struct_lit_field_colon: false + +const LOREM: Lorem = Lorem { + ipsum:dolor, + sit : amet, +}; diff --git a/tests/source/configs-space_after_struct_lit_field_colon-true.rs b/tests/source/configs-space_after_struct_lit_field_colon-true.rs new file mode 100644 index 00000000000..6105d4725d8 --- /dev/null +++ b/tests/source/configs-space_after_struct_lit_field_colon-true.rs @@ -0,0 +1,6 @@ +// rustfmt-space_after_struct_lit_field_colon: true + +const LOREM: Lorem = Lorem { + ipsum:dolor, + sit : amet, +}; diff --git a/tests/source/configs-space_before_struct_lit_field_colon-false.rs b/tests/source/configs-space_before_struct_lit_field_colon-false.rs new file mode 100644 index 00000000000..a2d71c8bf0b --- /dev/null +++ b/tests/source/configs-space_before_struct_lit_field_colon-false.rs @@ -0,0 +1,6 @@ +// rustfmt-space_before_struct_lit_field_colon: false + +const LOREM: Lorem = Lorem { + ipsum:dolor, + sit : amet, +}; diff --git a/tests/source/configs-space_before_struct_lit_field_colon-true.rs b/tests/source/configs-space_before_struct_lit_field_colon-true.rs new file mode 100644 index 00000000000..50e4ba12d82 --- /dev/null +++ b/tests/source/configs-space_before_struct_lit_field_colon-true.rs @@ -0,0 +1,6 @@ +// rustfmt-space_before_struct_lit_field_colon: true + +const LOREM: Lorem = Lorem { + ipsum:dolor, + sit : amet, +}; diff --git a/tests/target/configs-space_after_struct_lit_field_colon-false.rs b/tests/target/configs-space_after_struct_lit_field_colon-false.rs new file mode 100644 index 00000000000..8f475059464 --- /dev/null +++ b/tests/target/configs-space_after_struct_lit_field_colon-false.rs @@ -0,0 +1,6 @@ +// rustfmt-space_after_struct_lit_field_colon: false + +const LOREM: Lorem = Lorem { + ipsum:dolor, + sit:amet, +}; diff --git a/tests/target/configs-space_after_struct_lit_field_colon-true.rs b/tests/target/configs-space_after_struct_lit_field_colon-true.rs new file mode 100644 index 00000000000..34fb792dcb5 --- /dev/null +++ b/tests/target/configs-space_after_struct_lit_field_colon-true.rs @@ -0,0 +1,6 @@ +// rustfmt-space_after_struct_lit_field_colon: true + +const LOREM: Lorem = Lorem { + ipsum: dolor, + sit: amet, +}; diff --git a/tests/target/configs-space_before_struct_lit_field_colon-false.rs b/tests/target/configs-space_before_struct_lit_field_colon-false.rs new file mode 100644 index 00000000000..48336954786 --- /dev/null +++ b/tests/target/configs-space_before_struct_lit_field_colon-false.rs @@ -0,0 +1,6 @@ +// rustfmt-space_before_struct_lit_field_colon: false + +const LOREM: Lorem = Lorem { + ipsum: dolor, + sit: amet, +}; diff --git a/tests/target/configs-space_before_struct_lit_field_colon-true.rs b/tests/target/configs-space_before_struct_lit_field_colon-true.rs new file mode 100644 index 00000000000..e4f1cdb4575 --- /dev/null +++ b/tests/target/configs-space_before_struct_lit_field_colon-true.rs @@ -0,0 +1,6 @@ +// rustfmt-space_before_struct_lit_field_colon: true + +const LOREM: Lorem = Lorem { + ipsum : dolor, + sit : amet, +}; diff --git a/tests/target/space-before-type-annotation.rs b/tests/target/space-before-type-annotation.rs index 54b9541eaae..0ad06dbb70c 100644 --- a/tests/target/space-before-type-annotation.rs +++ b/tests/target/space-before-type-annotation.rs @@ -9,5 +9,5 @@ struct S { fieldVar : i32, } fn f() { - S { fieldVar : 42 } + S { fieldVar: 42 } } diff --git a/tests/target/space-not-after-type-annotation-colon.rs b/tests/target/space-not-after-type-annotation-colon.rs index 3bdfa57fb73..b07620fb4c1 100644 --- a/tests/target/space-not-after-type-annotation-colon.rs +++ b/tests/target/space-not-after-type-annotation-colon.rs @@ -10,5 +10,5 @@ struct S { fieldVar :i32, } fn f() { - S { fieldVar :42 } + S { fieldVar: 42 } } -- cgit 1.4.1-3-g733a5 From 7be703a6374527379a40d19ad10d868bde7167ad Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 5 Jun 2017 23:21:39 +0900 Subject: Implement Rewrite trait for syntax::ast::Attribute --- src/visitor.rs | 87 +++++++++++++++++++++++++++++---- tests/source/attrib.rs | 10 ++++ tests/source/enum.rs | 11 +++++ tests/source/struct-field-attributes.rs | 15 ++++++ tests/target/attrib.rs | 10 ++++ tests/target/enum.rs | 9 ++++ tests/target/nestedmod/mod.rs | 2 +- tests/target/nestedmod/mod2b.rs | 2 +- tests/target/struct-field-attributes.rs | 15 ++++++ 9 files changed, 149 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index a75b60a7bd7..a7198bf588b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -26,6 +26,7 @@ use comment::rewrite_comment; use macros::{rewrite_macro, MacroPosition}; use items::{rewrite_static, rewrite_associated_type, rewrite_associated_impl_type, rewrite_type_alias, format_impl, format_trait}; +use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorTactic}; fn is_use_item(item: &ast::Item) -> bool { match item.node { @@ -637,6 +638,81 @@ impl<'a> FmtVisitor<'a> { } } +impl Rewrite for ast::NestedMetaItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), + ast::NestedMetaItemKind::Literal(..) => Some(context.snippet(self.span)), + } + } +} + +impl Rewrite for ast::MetaItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + Some(match self.node { + ast::MetaItemKind::Word => String::from(&*self.name.as_str()), + ast::MetaItemKind::List(ref list) => { + let name = self.name.as_str(); + // 3 = `#[` and `(`, 2 = `]` and `)` + let item_shape = try_opt!(shape + .shrink_left(name.len() + 3) + .and_then(|s| s.sub_width(2))); + let items = itemize_list(context.codemap, + list.iter(), + ")", + |nested_meta_item| nested_meta_item.span.lo, + |nested_meta_item| nested_meta_item.span.hi, + |nested_meta_item| { + nested_meta_item.rewrite(context, item_shape) + }, + self.span.lo, + self.span.hi); + let item_vec = items.collect::>(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + shape: item_shape, + ends_with_newline: false, + config: context.config, + }; + format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt))) + } + ast::MetaItemKind::NameValue(ref literal) => { + let name = self.name.as_str(); + let value = context.snippet(literal.span); + if &*name == "doc" && value.starts_with("///") { + let doc_shape = Shape { + width: cmp::min(shape.width, context.config.comment_width()) + .checked_sub(shape.indent.width()) + .unwrap_or(0), + ..shape + }; + format!("{}", + try_opt!(rewrite_comment(&value, + false, + doc_shape, + context.config))) + } else { + format!("{} = {}", name, value) + } + } + }) + } +} + +impl Rewrite for ast::Attribute { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + self.value + .rewrite(context, shape) + .map(|rw| if rw.starts_with("///") { + rw + } else { + format!("#[{}]", rw) + }) + } +} + impl<'a> Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::new(); @@ -646,7 +722,7 @@ impl<'a> Rewrite for [ast::Attribute] { let indent = shape.indent.to_string(context.config); for (i, a) in self.iter().enumerate() { - let mut a_str = context.snippet(a.span); + let a_str = try_opt!(a.rewrite(context, shape)); // Write comments and blank lines between attributes. if i > 0 { @@ -673,15 +749,6 @@ impl<'a> Rewrite for [ast::Attribute] { result.push_str(&indent); } - if a_str.starts_with("//") { - a_str = try_opt!(rewrite_comment(&a_str, - false, - Shape::legacy(context.config.comment_width() - - shape.indent.width(), - shape.indent), - context.config)); - } - // Write the attribute itself. result.push_str(&a_str); diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index a47c2507156..593fb0ff57e 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -41,4 +41,14 @@ impl Bar { /// Blah blah bing. fn f4(self) -> Cat { } + + // We want spaces around `=` + #[cfg(feature="nightly")] + fn f5(self) -> Monkey {} +} + +// #984 +struct Foo { + # [ derive ( Clone , PartialEq , Debug , Deserialize , Serialize ) ] + foo: usize, } diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 0e2e2c066c3..6992ca53c1b 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -109,3 +109,14 @@ pub enum Bencoding<'i> { // TODO make Dict "structlike" AKA name the two values. Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), } + +// #1261 +pub enum CoreResourceMsg { + SetCookieForUrl( + ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource + ), +} diff --git a/tests/source/struct-field-attributes.rs b/tests/source/struct-field-attributes.rs index 2e5381a7e41..6fc69c2dfe4 100644 --- a/tests/source/struct-field-attributes.rs +++ b/tests/source/struct-field-attributes.rs @@ -20,3 +20,18 @@ fn do_something() -> Foo { fn main() { do_something(); } + +// #1462 +struct Foo { + foo: usize, + #[cfg(feature="include-bar")] + bar: usize, +} + +fn new_foo() -> Foo { + Foo { + foo: 0, + #[cfg(feature="include-bar")] + bar: 0, + } +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index b861b971d9b..fb70585bd21 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -37,4 +37,14 @@ impl Bar { // tooooooooooooooooooooooooooooooo loooooooooooong. /// Blah blah bing. fn f4(self) -> Cat {} + + // We want spaces around `=` + #[cfg(feature = "nightly")] + fn f5(self) -> Monkey {} +} + +// #984 +struct Foo { + #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] + foo: usize, } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 3e0e46d3fae..0bb18e2df67 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -139,3 +139,12 @@ pub enum Bencoding<'i> { // TODO make Dict "structlike" AKA name the two values. Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), } + +// #1261 +pub enum CoreResourceMsg { + SetCookieForUrl(ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource), +} diff --git a/tests/target/nestedmod/mod.rs b/tests/target/nestedmod/mod.rs index b3456bf0d0f..ff0d55b0175 100644 --- a/tests/target/nestedmod/mod.rs +++ b/tests/target/nestedmod/mod.rs @@ -7,7 +7,7 @@ mod mymod1 { mod mod3a; } -#[path="mod2c.rs"] +#[path = "mod2c.rs"] mod mymod2; mod submod2; diff --git a/tests/target/nestedmod/mod2b.rs b/tests/target/nestedmod/mod2b.rs index f128e2da6db..f06766f304f 100644 --- a/tests/target/nestedmod/mod2b.rs +++ b/tests/target/nestedmod/mod2b.rs @@ -1,3 +1,3 @@ -#[path="mod2a.rs"] +#[path = "mod2a.rs"] mod c; diff --git a/tests/target/struct-field-attributes.rs b/tests/target/struct-field-attributes.rs index 2e5381a7e41..8ae40ac9bdf 100644 --- a/tests/target/struct-field-attributes.rs +++ b/tests/target/struct-field-attributes.rs @@ -20,3 +20,18 @@ fn do_something() -> Foo { fn main() { do_something(); } + +// #1462 +struct Foo { + foo: usize, + #[cfg(feature = "include-bar")] + bar: usize, +} + +fn new_foo() -> Foo { + Foo { + foo: 0, + #[cfg(feature = "include-bar")] + bar: 0, + } +} -- cgit 1.4.1-3-g733a5 From 727963afe45b27f71b0fb4a8f82e5aab242db7f1 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 6 Jun 2017 06:54:22 +0200 Subject: Update syntex_syntax Bases on commit to switch to libsyntax by @nrc --- Cargo.lock | 133 +++++++++++++++++++++++++++++++++++----------------- Cargo.toml | 4 +- src/chains.rs | 4 +- src/expr.rs | 6 ++- src/imports.rs | 6 +-- src/items.rs | 19 +++++--- src/lib.rs | 6 +-- src/lists.rs | 7 +-- src/macros.rs | 14 ++++-- src/missed_spans.rs | 5 +- src/patterns.rs | 6 +-- src/types.rs | 7 ++- src/utils.rs | 16 +++++-- src/visitor.rs | 26 +++++----- 14 files changed, 167 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 2d34a8f7cea..161a26ad916 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,18 +3,18 @@ name = "rustfmt" version = "0.8.4" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -31,7 +31,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -46,13 +46,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "env_logger" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "extprim" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getopts" version = "0.2.14" @@ -79,7 +89,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -100,6 +110,14 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "0.2.2" @@ -118,28 +136,44 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rustc-serialize" -version = "0.3.24" +name = "rustc_version" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -154,7 +188,7 @@ dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -162,7 +196,7 @@ name = "strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -185,35 +219,40 @@ dependencies = [ [[package]] name = "syntex_errors" -version = "0.58.1" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.58.1" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.58.1" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "extprim 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -248,7 +287,7 @@ name = "toml" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -261,6 +300,11 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "0.1.1" @@ -291,37 +335,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum extprim 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9f92dbf3843b6b56a224bce6aacd734feea193013d6ee1e18f03dcb36a93911" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" -"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum serde 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c0c3d79316a6051231925504f6ef893d45088e8823c77a8331a3dcf427ee9087" -"checksum serde_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0019cd5b9f0529a1a0e145a912e9a2d60c325c58f7f260fc36c71976e9d76aee" -"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" +"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" +"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f530d36fb84ec48fb7146936881f026cdbf4892028835fd9398475f82c1bb4" +"checksum serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "10552fad5500771f3902d0c5ba187c5881942b811b7ba0d8fbbfbf84d80806d3" +"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" -"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" -"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" +"checksum syntex_errors 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f769b93e132914e999edb13018e192bd5f0296c2886fb6d5473ee6e055acb1c" +"checksum syntex_pos 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56c108cb745a38857097c1662a9d513594486acaf1d508831201fd122f83ba44" +"checksum syntex_syntax 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c815f257bdfb6f8b8876bb2937438a5365f2884f268c312f864cd002abace6" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" "checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 4f5eaa7f018..083dfd787fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,8 @@ regex = "0.2" term = "0.4" strings = "0.1" diff = "0.1" -syntex_syntax = "0.58" -syntex_errors = "0.58" +syntex_syntax = "0.59" +syntex_errors = "0.59" log = "0.3" env_logger = "0.4" getopts = "0.2" diff --git a/src/chains.rs b/src/chains.rs index 204f0b80423..b84a7e469f2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -78,7 +78,7 @@ use Shape; use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, first_line_width, last_line_width}; +use utils::{wrap_str, first_line_width, last_line_width, mk_sp}; use expr::rewrite_call; use config::IndentStyle; use macros::convert_try_mac; @@ -86,7 +86,7 @@ use macros::convert_try_mac; use std::cmp::min; use std::iter; use syntax::{ast, ptr}; -use syntax::codemap::{mk_sp, Span}; +use syntax::codemap::Span; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { debug!("rewrite_chain {:?}", shape); diff --git a/src/expr.rs b/src/expr.rs index 72c10619ea2..293acf1ea54 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -22,7 +22,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, - colon_spaces, contains_skip}; + colon_spaces, contains_skip, mk_sp}; use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -32,7 +32,7 @@ use chains::rewrite_chain; use macros::{rewrite_macro, MacroPosition}; use syntax::{ast, ptr}; -use syntax::codemap::{CodeMap, Span, BytePos, mk_sp}; +use syntax::codemap::{CodeMap, Span, BytePos}; use syntax::parse::classify; impl Rewrite for ast::Expr { @@ -253,6 +253,8 @@ fn format_expr(expr: &ast::Expr, context.config.max_width(), shape) } + // FIXME(#1537) + ast::ExprKind::Catch(..) => unimplemented!(), }; match (attr_rw, expr_rw) { (Some(attr_str), Some(expr_str)) => { diff --git a/src/imports.rs b/src/imports.rs index 46ce14f47b7..83e7661aad9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -10,7 +10,7 @@ use Shape; use utils; -use syntax::codemap::{self, BytePos, Span}; +use syntax::codemap::{BytePos, Span}; use codemap::SpanUtils; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; use types::{rewrite_path, PathContext}; @@ -202,7 +202,7 @@ impl<'a> FmtVisitor<'a> { // Order the imports by view-path & other import path properties ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap()); // First, output the span before the first import - let prev_span_str = self.snippet(codemap::mk_sp(self.last_pos, pos_before_first_use_item)); + let prev_span_str = self.snippet(utils::mk_sp(self.last_pos, pos_before_first_use_item)); // Look for purely trailing space at the start of the prefix snippet before a linefeed, or // a prefix that's entirely horizontal whitespace. let prefix_span_start = match prev_span_str.find('\n') { @@ -241,7 +241,7 @@ impl<'a> FmtVisitor<'a> { Shape::legacy(self.config.max_width() - offset.width() - 1, offset)) { Some(ref s) if s.is_empty() => { // Format up to last newline - let prev_span = codemap::mk_sp(self.last_pos, source!(self, span).lo); + let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo); let span_end = match self.snippet(prev_span).rfind('\n') { Some(offset) => self.last_pos + BytePos(offset as u32), None => source!(self, span).lo, diff --git a/src/items.rs b/src/items.rs index c9d9f7a12fc..bbbe75ddf78 100644 --- a/src/items.rs +++ b/src/items.rs @@ -14,7 +14,7 @@ use {Indent, Shape}; use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, - trimmed_last_line_width, colon_spaces}; + trimmed_last_line_width, colon_spaces, mk_sp}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; @@ -23,8 +23,8 @@ use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity}; -use syntax::{ast, abi, codemap, ptr, symbol}; -use syntax::codemap::{Span, BytePos, mk_sp}; +use syntax::{ast, abi, ptr, symbol}; +use syntax::codemap::{Span, BytePos}; use syntax::ast::ImplItem; fn type_annotation_separator(config: &Config) -> &str { @@ -246,7 +246,7 @@ impl<'a> FmtVisitor<'a> { let mut newline_brace = newline_for_brace(self.config, &generics.where_clause); let context = self.get_context(); - let block_snippet = self.snippet(codemap::mk_sp(block.span.lo, block.span.hi)); + let block_snippet = self.snippet(mk_sp(block.span.lo, block.span.hi)); let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || !context.config.fn_empty_single_line(); @@ -527,7 +527,7 @@ pub fn format_impl(context: &RewriteContext, offset: Indent, where_span_end: Option) -> Option { - if let ast::ItemKind::Impl(_, _, ref generics, ref trait_ref, _, ref items) = item.node { + if let ast::ItemKind::Impl(_, _, _, ref generics, ref trait_ref, _, ref items) = item.node { let mut result = String::new(); // First try to format the ref and type without a split at the 'for'. let mut ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, false)); @@ -647,8 +647,13 @@ fn format_impl_ref_and_type(context: &RewriteContext, offset: Indent, split_at_for: bool) -> Option { - if let ast::ItemKind::Impl(unsafety, polarity, ref generics, ref trait_ref, ref self_ty, _) = - item.node { + if let ast::ItemKind::Impl(unsafety, + polarity, + _, + ref generics, + ref trait_ref, + ref self_ty, + _) = item.node { let mut result = String::new(); result.push_str(&format_visibility(&item.vis)); diff --git a/src/lib.rs b/src/lib.rs index 1635553eccd..b7edc183618 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ extern crate term; use errors::{Handler, DiagnosticBuilder}; use errors::emitter::{ColorConfig, EmitterWriter}; use syntax::ast; -use syntax::codemap::{mk_sp, CodeMap, Span}; +use syntax::codemap::{CodeMap, Span, FilePathMapping}; use syntax::parse::{self, ParseSess}; use strings::string_buffer::StringBuffer; @@ -107,7 +107,7 @@ impl Spanned for ast::Ty { impl Spanned for ast::Arg { fn span(&self) -> Span { if items::is_named_arg(self) { - mk_sp(self.pat.span.lo, self.ty.span.hi) + utils::mk_sp(self.pat.span.lo, self.ty.span.hi) } else { self.ty.span } @@ -578,7 +578,7 @@ pub fn format_input(input: Input, if config.disable_all_formatting() { return Ok((summary, FileMap::new(), FormatReport::new())); } - let codemap = Rc::new(CodeMap::new()); + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); let tty_handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())); diff --git a/src/lists.rs b/src/lists.rs index 3448f8a446a..978d9dbaceb 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -11,12 +11,13 @@ use std::cmp; use std::iter::Peekable; -use syntax::codemap::{self, CodeMap, BytePos}; +use syntax::codemap::{CodeMap, BytePos}; use {Indent, Shape}; use comment::{FindUncommented, rewrite_comment, find_comment_end}; use config::{Config, IndentStyle}; use rewrite::RewriteContext; +use utils::mk_sp; #[derive(Eq, PartialEq, Debug, Copy, Clone)] /// Formatting tactic for lists. This will be cast down to a @@ -344,7 +345,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let mut new_lines = false; // Pre-comment let pre_snippet = self.codemap - .span_to_snippet(codemap::mk_sp(self.prev_span_end, (self.get_lo)(&item))) + .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); let has_pre_comment = trimmed_pre_snippet.contains("//") || @@ -361,7 +362,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> None => self.next_span_start, }; let post_snippet = self.codemap - .span_to_snippet(codemap::mk_sp((self.get_hi)(&item), next_start)) + .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) .unwrap(); let comment_end = match self.inner.peek() { diff --git a/src/macros.rs b/src/macros.rs index f99e236ac88..eca89a4b609 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -20,9 +20,10 @@ // and those with brackets will be formatted as array literals. use syntax::ast; -use syntax::codemap::{mk_sp, BytePos}; +use syntax::codemap::BytePos; use syntax::parse::token::Token; -use syntax::parse::tts_to_parser; +use syntax::parse::new_parser_from_tts; +use syntax::tokenstream::TokenStream; use syntax::symbol; use syntax::util::ThinVec; @@ -31,6 +32,7 @@ use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use expr::{rewrite_call, rewrite_array, rewrite_pair}; use comment::{FindUncommented, contains_comment}; +use utils::mk_sp; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; @@ -92,7 +94,8 @@ pub fn rewrite_macro(mac: &ast::Mac, original_style }; - if mac.node.tts.is_empty() && !contains_comment(&context.snippet(mac.span)) { + let ts: TokenStream = mac.node.tts.clone().into(); + if ts.is_empty() && !contains_comment(&context.snippet(mac.span)) { return match style { MacroStyle::Parens if position == MacroPosition::Item => { Some(format!("{}();", macro_name)) @@ -103,7 +106,7 @@ pub fn rewrite_macro(mac: &ast::Mac, }; } - let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); let mut expr_vec = Vec::new(); let mut vec_with_semi = false; @@ -222,7 +225,8 @@ pub fn rewrite_macro(mac: &ast::Mac, /// failed). pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { if &format!("{}", mac.node.path)[..] == "try" { - let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone()); + let ts: TokenStream = mac.node.tts.clone().into(); + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); Some(ast::Expr { id: ast::NodeId::new(0), // dummy value diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 57ebc332ac4..90a13277865 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -10,9 +10,10 @@ use config::WriteMode; use visitor::FmtVisitor; -use syntax::codemap::{self, BytePos, Span, Pos}; +use syntax::codemap::{BytePos, Span, Pos}; use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; use Shape; +use utils::mk_sp; impl<'a> FmtVisitor<'a> { fn output_at_start(&self) -> bool { @@ -65,7 +66,7 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(end)); self.last_pos = end; - let span = codemap::mk_sp(start, end); + let span = mk_sp(start, end); self.write_snippet(span, &process_last_snippet); } diff --git a/src/patterns.rs b/src/patterns.rs index 312f2b0ace9..eb100abd664 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -12,7 +12,7 @@ use Shape; use codemap::SpanUtils; use config::{IndentStyle, MultilineStyle}; use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, format_mutability}; +use utils::{wrap_str, format_mutability, mk_sp}; use lists::{DefinitiveListTactic, SeparatorTactic, format_item_list, itemize_list, ListItem, struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list}; @@ -261,14 +261,14 @@ fn rewrite_tuple_pat(pats: &[ptr::P], } else { pats[pos + 1].span().lo }; - let dot_span = codemap::mk_sp(prev, next); + let dot_span = mk_sp(prev, next); let snippet = context.snippet(dot_span); let lo = dot_span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); let span = Span { lo: lo, // 2 == "..".len() hi: lo + BytePos(2), - expn_id: codemap::NO_EXPANSION, + ctxt: codemap::NO_EXPANSION, }; let dotdot = TuplePatField::Dotdot(span); pat_vec.insert(pos, dotdot); diff --git a/src/types.rs b/src/types.rs index 17e9a467d1b..7dfc4337178 100644 --- a/src/types.rs +++ b/src/types.rs @@ -21,7 +21,7 @@ use {Shape, Spanned}; use codemap::SpanUtils; use lists::{format_item_list, itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, format_mutability, colon_spaces, wrap_str}; +use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; use config::TypeDensity; @@ -206,9 +206,7 @@ fn rewrite_segment(path_context: PathContext, .collect::>(); let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); - let list_lo = context - .codemap - .span_after(codemap::mk_sp(*span_lo, span_hi), "<"); + let list_lo = context.codemap.span_after(mk_sp(*span_lo, span_hi), "<"); let separator = if path_context == PathContext::Expr { "::" } else { @@ -686,6 +684,7 @@ impl Rewrite for ast::Ty { it.rewrite(context, shape) .map(|it_str| format!("impl {}", it_str)) } + ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), } } diff --git a/src/utils.rs b/src/utils.rs index e80c558e51e..c9bf00ee4c3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -13,7 +13,7 @@ use std::cmp::Ordering; use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path}; -use syntax::codemap::BytePos; +use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use syntax::abi; use Shape; @@ -125,7 +125,9 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { #[inline] pub fn contains_skip(attrs: &[Attribute]) -> bool { - attrs.iter().any(|a| is_skip(&a.value)) + attrs + .iter() + .any(|a| a.meta().map_or(false, |a| is_skip(&a))) } // Find the end of a TyParam @@ -287,7 +289,15 @@ macro_rules! msg { // Required as generated code spans aren't guaranteed to follow on from the last span. macro_rules! source { ($this:ident, $sp: expr) => { - $this.codemap.source_callsite($sp) + $sp.source_callsite() + } +} + +pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { + Span { + lo, + hi, + ctxt: NO_EXPANSION, } } diff --git a/src/visitor.rs b/src/visitor.rs index d3ab3d2d96d..f4ad95427c7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,13 +11,13 @@ use std::cmp; use syntax::{ast, ptr, visit}; -use syntax::codemap::{self, CodeMap, Span, BytePos}; +use syntax::codemap::{CodeMap, Span, BytePos}; use syntax::parse::ParseSess; use strings::string_buffer::StringBuffer; use {Indent, Shape}; -use utils; +use utils::{self, mk_sp}; use codemap::{LineRangeUtils, SpanUtils}; use comment::FindUncommented; use config::Config; @@ -43,7 +43,7 @@ fn item_bound(item: &ast::Item) -> Span { Span { lo: cmp::min(bound.lo, span.lo), hi: cmp::max(bound.hi, span.hi), - expn_id: span.expn_id, + ctxt: span.ctxt, } }) } @@ -122,8 +122,7 @@ impl<'a> FmtVisitor<'a> { let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); if unindent_comment { let end_pos = source!(self, b.span).hi - brace_compensation; - let snippet = self.get_context() - .snippet(codemap::mk_sp(self.last_pos, end_pos)); + let snippet = self.get_context().snippet(mk_sp(self.last_pos, end_pos)); unindent_comment = snippet.contains("//") || snippet.contains("/*"); } // FIXME: we should compress any newlines here to just one @@ -178,7 +177,7 @@ impl<'a> FmtVisitor<'a> { defaultness, abi, vis, - codemap::mk_sp(s.lo, b.span.lo), + mk_sp(s.lo, b.span.lo), &b) } visit::FnKind::Method(ident, sig, vis, b) => { @@ -192,7 +191,7 @@ impl<'a> FmtVisitor<'a> { defaultness, sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), - codemap::mk_sp(s.lo, b.span.lo), + mk_sp(s.lo, b.span.lo), &b) } visit::FnKind::Closure(_) => unreachable!(), @@ -384,6 +383,12 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::Union(..) => { // FIXME(#1157): format union definitions. } + ast::ItemKind::GlobalAsm(..) => { + // FIXME(#1538): format GlobalAsm + } + ast::ItemKind::MacroDef(..) => { + // FIXME(#1539): macros 2.0 + } } } @@ -599,8 +604,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(" {"); // Hackery to account for the closing }. let mod_lo = self.codemap.span_after(source!(self, s), "{"); - let body_snippet = - self.snippet(codemap::mk_sp(mod_lo, source!(self, m.inner).hi - BytePos(1))); + let body_snippet = self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { self.buffer.push_str("}"); @@ -704,7 +708,7 @@ impl Rewrite for ast::MetaItem { impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - self.value + try_opt!(self.meta()) .rewrite(context, shape) .map(|rw| if rw.starts_with("///") { rw @@ -727,7 +731,7 @@ impl<'a> Rewrite for [ast::Attribute] { // Write comments and blank lines between attributes. if i > 0 { - let comment = context.snippet(codemap::mk_sp(self[i - 1].span.hi, a.span.lo)); + let comment = context.snippet(mk_sp(self[i - 1].span.hi, a.span.lo)); // This particular horror show is to preserve line breaks in between doc // comments. An alternative would be to force such line breaks to start // with the usual doc comment token. -- cgit 1.4.1-3-g733a5 From e994eac3f1c6afb4458c621b991f0540f768c078 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 12 May 2017 22:25:26 +0900 Subject: Format pub(restricted) properly --- src/utils.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index c9bf00ee4c3..12f29253f2e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -48,8 +48,11 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { .next() .expect("Non-global path in pub(restricted)?"); } + let is_keyword = |s: &str| s == "self" || s == "super"; + let path = segments_iter.join("::"); + let in_str = if is_keyword(&path) { "" } else { "in " }; - Cow::from(format!("pub({}) ", segments_iter.collect::>().join("::"))) + Cow::from(format!("pub({}{}) ", in_str, path)) } } } -- cgit 1.4.1-3-g733a5 From 647fd4ff772bea43589359cd5fcf5a18c93d04b7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 13 May 2017 07:28:26 +0900 Subject: Leave GlobalAsm and MacroDef without formatting --- src/visitor.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index f4ad95427c7..d01e8e02ead 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -384,10 +384,13 @@ impl<'a> FmtVisitor<'a> { // FIXME(#1157): format union definitions. } ast::ItemKind::GlobalAsm(..) => { - // FIXME(#1538): format GlobalAsm + let snippet = Some(self.snippet(item.span)); + self.push_rewrite(item.span, snippet); } ast::ItemKind::MacroDef(..) => { // FIXME(#1539): macros 2.0 + let snippet = Some(self.snippet(item.span)); + self.push_rewrite(item.span, snippet); } } } -- cgit 1.4.1-3-g733a5 From 27da80324c45d6aac4b20b49d4e9d124d5416656 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 13 May 2017 07:28:48 +0900 Subject: Implement catch --- src/expr.rs | 47 +++++++++++++++++++++++++++++------------------ tests/source/catch.rs | 27 +++++++++++++++++++++++++++ tests/target/catch.rs | 21 +++++++++++++++++++++ tests/target/closure.rs | 6 ++++-- tests/target/match.rs | 9 ++++----- 5 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 tests/source/catch.rs create mode 100644 tests/target/catch.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 293acf1ea54..aa5913e5f0f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -253,8 +253,16 @@ fn format_expr(expr: &ast::Expr, context.config.max_width(), shape) } - // FIXME(#1537) - ast::ExprKind::Catch(..) => unimplemented!(), + ast::ExprKind::Catch(ref block) => { + if let rewrite @ Some(_) = try_one_line_block(context, shape, "do catch ", block) { + return rewrite; + } + // 9 = `do catch ` + let budget = shape.width.checked_sub(9).unwrap_or(0); + Some(format!("{}{}", + "do catch ", + try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))))) + } }; match (attr_rw, expr_rw) { (Some(attr_str), Some(expr_str)) => { @@ -268,6 +276,22 @@ fn format_expr(expr: &ast::Expr, } } +fn try_one_line_block(context: &RewriteContext, + shape: Shape, + prefix: &str, + block: &ast::Block) + -> Option { + if is_simple_block(block, context.codemap) { + let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent); + let expr_str = try_opt!(block.stmts[0].rewrite(context, expr_shape)); + let result = format!("{}{{ {} }}", prefix, expr_str); + if result.len() <= shape.width && !result.contains('\n') { + return Some(result); + } + } + None +} + pub fn rewrite_pair(lhs: &LHS, rhs: &RHS, prefix: &str, @@ -622,9 +646,7 @@ fn rewrite_closure(capture: ast::CaptureBy, // means we must re-format. let block_shape = shape.block().with_max_width(context.config); let block_str = try_opt!(block.rewrite(&context, block_shape)); - Some(format!("{} {}", - prefix, - try_opt!(block_str.rewrite(context, block_shape)))) + Some(format!("{} {}", prefix, block_str)) } } @@ -689,24 +711,13 @@ impl Rewrite for ast::Block { } else { "unsafe ".to_owned() }; - - if is_simple_block(self, context.codemap) && prefix.len() < shape.width { - let expr_str = - self.stmts[0].rewrite(context, - Shape::legacy(shape.width - prefix.len(), - shape.indent)); - let expr_str = try_opt!(expr_str); - let result = format!("{}{{ {} }}", prefix, expr_str); - if result.len() <= shape.width && !result.contains('\n') { - return Some(result); - } + if let result @ Some(_) = try_one_line_block(context, shape, &prefix, self) { + return result; } - prefix } ast::BlockCheckMode::Default => { visitor.last_pos = self.span.lo; - String::new() } }; diff --git a/tests/source/catch.rs b/tests/source/catch.rs new file mode 100644 index 00000000000..64cc9e7a207 --- /dev/null +++ b/tests/source/catch.rs @@ -0,0 +1,27 @@ +#![feature(catch_expr)] + +fn main() { + let x = do catch { + foo()? + }; + + let x = do catch /* Invisible comment */ { foo()? }; + + let x = do catch { + unsafe { foo()? } + }; + + let y = match (do catch { + foo()? + }) { + _ => (), + }; + + do catch { + foo()?; + }; + + do catch { + // Regular do catch block + }; +} diff --git a/tests/target/catch.rs b/tests/target/catch.rs new file mode 100644 index 00000000000..640f9bade49 --- /dev/null +++ b/tests/target/catch.rs @@ -0,0 +1,21 @@ +#![feature(catch_expr)] + +fn main() { + let x = do catch { foo()? }; + + let x = do catch /* Invisible comment */ { foo()? }; + + let x = do catch { unsafe { foo()? } }; + + let y = match (do catch { foo()? }) { + _ => (), + }; + + do catch { + foo()?; + }; + + do catch { + // Regular do catch block + }; +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index d51c76b9e48..3d20102bef0 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -109,8 +109,10 @@ fn foo() { fn issue1405() { open_raw_fd(fd, b'r').and_then(|file| { - Capture::new_raw(None, |_, err| unsafe { raw::pcap_fopen_offline(file, err) }) - }); + Capture::new_raw(None, |_, err| unsafe { + raw::pcap_fopen_offline(file, err) + }) + }); } fn issue1466() { diff --git a/tests/target/match.rs b/tests/target/match.rs index 09df7ebd55f..6acab043e67 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -326,11 +326,10 @@ fn issue1371() { sfEvtGainedFocus => GainedFocus, sfEvtTextEntered => { TextEntered { - unicode: - unsafe { - ::std::char::from_u32((*event.text.as_ref()).unicode) - .expect("Invalid unicode encountered on TextEntered event") - }, + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, } } sfEvtKeyPressed => { -- cgit 1.4.1-3-g733a5 From de6bfc4ad7850a4e2b980dad1811c1c035626352 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 17 May 2017 18:57:18 +1200 Subject: Rebasing --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 12f29253f2e..b4095978b8a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -49,7 +49,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { .expect("Non-global path in pub(restricted)?"); } let is_keyword = |s: &str| s == "self" || s == "super"; - let path = segments_iter.join("::"); + let path = segments_iter.collect::>().join("::"); let in_str = if is_keyword(&path) { "" } else { "in " }; Cow::from(format!("pub({}{}) ", in_str, path)) -- cgit 1.4.1-3-g733a5 From a64037d0f07f4ac6eeb284d6dcfa362542b07dae Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 6 Jun 2017 15:33:46 +0900 Subject: Do not overwrite files when there are no diffs in Overwrite mode --- src/filemap.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index aa3ae8537af..82e8c3e50ae 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -128,9 +128,12 @@ pub fn write_file(text: &StringBuffer, } } WriteMode::Overwrite => { - // Write text directly over original file. - let file = File::create(filename)?; - write_system_newlines(file, text, config)?; + // Write text directly over original file if there is a diff. + let (source, formatted) = source_and_formatted_text(text, filename, config)?; + if source != formatted { + let file = File::create(filename)?; + write_system_newlines(file, text, config)?; + } } WriteMode::Plain => { write_system_newlines(out, text, config)?; -- cgit 1.4.1-3-g733a5 From c92064c30acfd9748670c9d2d46525ef18bc8d1c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 9 Jun 2017 16:15:31 +0900 Subject: Force brace on new line if the signature ends with comment --- src/items.rs | 8 +++++++- tests/target/comments-fn.rs | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index bbbe75ddf78..ac2f36ad76a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1871,6 +1871,7 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(&where_clause_str); + force_new_line_for_brace |= last_line_contains_single_line_comment(&result); return Some((result, force_new_line_for_brace)); } } @@ -1888,7 +1889,12 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(&where_clause_str); - Some((result, force_new_line_for_brace)) + force_new_line_for_brace |= last_line_contains_single_line_comment(&result); + return Some((result, force_new_line_for_brace)); +} + +fn last_line_contains_single_line_comment(s: &str) -> bool { + s.lines().last().map_or(false, |l| l.contains("//")) } fn rewrite_args(context: &RewriteContext, diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index fa607e131ea..87b32f2915d 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -19,3 +19,7 @@ fn foo(a: aaaaaaaaaaaaa, // A comment fn bar() {} fn baz() -> Baz /* Comment after return type */ {} + +fn some_fn() where T: Eq // some comment +{ +} -- cgit 1.4.1-3-g733a5 From 762639e7fd968905d97599f9396568554c304f61 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 10 Jun 2017 14:16:12 +0900 Subject: Reset the error count of parser from the previous file --- src/lib.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index b7edc183618..6488c83e983 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -427,9 +427,10 @@ impl fmt::Display for FormatReport { // Formatting which depends on the AST. fn format_ast(krate: &ast::Crate, - parse_session: &ParseSess, + mut parse_session: &mut ParseSess, main_file: &Path, config: &Config, + codemap: &Rc, mut after_file: F) -> Result<(FileMap, bool), io::Error> where F: FnMut(&str, &mut StringBuffer) -> Result @@ -449,12 +450,19 @@ fn format_ast(krate: &ast::Crate, if config.verbose() { println!("Formatting {}", path); } - let mut visitor = FmtVisitor::from_codemap(parse_session, config); - visitor.format_separate_mod(module); + { + let mut visitor = FmtVisitor::from_codemap(parse_session, config); + visitor.format_separate_mod(module); - has_diff |= after_file(path, &mut visitor.buffer)?; + has_diff |= after_file(path, &mut visitor.buffer)?; - result.push((path.to_owned(), visitor.buffer)); + result.push((path.to_owned(), visitor.buffer)); + } + // Reset the error count. + if parse_session.span_diagnostic.has_errors() { + parse_session.span_diagnostic = + Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())); + } } Ok((result, has_diff)) @@ -612,9 +620,10 @@ pub fn format_input(input: Input, match format_ast( &krate, - &parse_session, + &mut parse_session, &main_file, config, + &codemap, |file_name, file| { // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. -- cgit 1.4.1-3-g733a5 From 9eefc6fc8d113e80f92de53ae756cb5203e173b1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 10 Jun 2017 18:24:23 +0900 Subject: Share codes when rewriting generics --- src/items.rs | 75 ++++++++++++++++++++------- src/types.rs | 25 ++++----- tests/target/configs-generics_indent-block.rs | 2 +- tests/target/fn-custom-2.rs | 6 +-- tests/target/fn-custom-3.rs | 6 +-- 5 files changed, 72 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index bbbe75ddf78..03ca6f60832 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,7 +16,7 @@ use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wr last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, trimmed_last_line_width, colon_spaces, mk_sp}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, - DefinitiveListTactic, ListTactic, definitive_tactic, format_item_list}; + DefinitiveListTactic, ListTactic, definitive_tactic}; use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; @@ -2111,21 +2111,13 @@ fn rewrite_generics(context: &RewriteContext, return Some(String::new()); } - let offset = match context.config.generics_indent() { - IndentStyle::Block => shape.indent.block_only().block_indent(context.config), - // 1 = < - IndentStyle::Visual => shape.indent + 1, - }; - - let h_budget = try_opt!(shape.width.checked_sub(2)); - // FIXME: might need to insert a newline if the generics are really long. - + let generics_shape = generics_shape_from_config(context.config, shape, 0); // Strings for the generics. let lt_strs = lifetimes .iter() - .map(|lt| lt.rewrite(context, Shape::legacy(h_budget, offset))); + .map(|lt| lt.rewrite(context, generics_shape)); let ty_strs = tys.iter() - .map(|ty_param| ty_param.rewrite(context, Shape::legacy(h_budget, offset))); + .map(|ty_param| ty_param.rewrite(context, generics_shape)); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { @@ -2147,21 +2139,64 @@ fn rewrite_generics(context: &RewriteContext, |&(_, ref str)| str.clone(), context.codemap.span_after(span, "<"), span.hi); - let list_str = - try_opt!(format_item_list(items, Shape::legacy(h_budget, offset), context.config)); + format_generics_item_list(context, items, generics_shape, generics_shape.width) +} + +pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Shape { + Shape { + // 2 = `<>` + width: shape.width.checked_sub(offset + 2).unwrap_or(0), + ..match config.generics_indent() { + IndentStyle::Visual => shape.visual_indent(1 + offset), + IndentStyle::Block => shape.block().block_indent(config.tab_spaces()), + } + } +} + +pub fn format_generics_item_list(context: &RewriteContext, + items: I, + shape: Shape, + one_line_budget: usize) + -> Option + where I: Iterator +{ + let item_vec = items.collect::>(); + + let fmt = ListFormatting { + tactic: definitive_tactic(&item_vec, ListTactic::HorizontalVertical, one_line_budget), + separator: ",", + trailing_separator: if context.config.generics_indent() == IndentStyle::Visual { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + shape: shape, + ends_with_newline: false, + config: context.config, + }; - let result = if context.config.generics_indent() != IndentStyle::Visual && - list_str.contains('\n') { + let list_str = try_opt!(write_list(&item_vec, &fmt)); + + Some(wrap_generics_with_angle_brackets(context, &list_str, shape.indent)) +} + +pub fn wrap_generics_with_angle_brackets(context: &RewriteContext, + list_str: &str, + list_offset: Indent) + -> String { + if context.config.generics_indent() == IndentStyle::Block && + (list_str.contains('\n') || list_str.ends_with(',')) { format!("<\n{}{}\n{}>", - offset.to_string(context.config), + list_offset.to_string(context.config), list_str, - shape.indent.block_only().to_string(context.config)) + list_offset + .block_unindent(context.config) + .to_string(context.config)) } else if context.config.spaces_within_angle_brackets() { format!("< {} >", list_str) } else { format!("<{}>", list_str) - }; - Some(result) + } } fn rewrite_trait_bounds(context: &RewriteContext, diff --git a/src/types.rs b/src/types.rs index 7dfc4337178..4e74ea8213f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -19,7 +19,8 @@ use syntax::symbol::keywords; use {Shape, Spanned}; use codemap::SpanUtils; -use lists::{format_item_list, itemize_list, format_fn_args}; +use items::{format_generics_item_list, generics_shape_from_config}; +use lists::{itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; @@ -213,31 +214,25 @@ fn rewrite_segment(path_context: PathContext, "" }; - // 1 for < - let extra_offset = 1 + separator.len(); - // 1 for > - // TODO bad visual indent - let list_shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(1)) - .visual_indent(0); - + let generics_shape = + generics_shape_from_config(context.config, shape, separator.len()); let items = itemize_list(context.codemap, param_list.into_iter(), ">", |param| param.get_span().lo, |param| param.get_span().hi, - |seg| seg.rewrite(context, list_shape), + |seg| seg.rewrite(context, generics_shape), list_lo, span_hi); - let list_str = try_opt!(format_item_list(items, list_shape, context.config)); + let generics_str = try_opt!(format_generics_item_list(context, + items, + generics_shape, + generics_shape.width)); // Update position of last bracket. *span_lo = next_span_lo; - if context.config.spaces_within_angle_brackets() && list_str.len() > 0 { - format!("{}< {} >", separator, list_str) - } else { - format!("{}<{}>", separator, list_str) - } + format!("{}{}", separator, generics_str) } ast::PathParameters::Parenthesized(ref data) => { let output = match data.output { diff --git a/tests/target/configs-generics_indent-block.rs b/tests/target/configs-generics_indent-block.rs index 789243c02c3..848e59c7c0a 100644 --- a/tests/target/configs-generics_indent-block.rs +++ b/tests/target/configs-generics_indent-block.rs @@ -8,7 +8,7 @@ fn lorem< Amet: Eq = usize, Adipiscing: Eq = usize, Consectetur: Eq = usize, - Elit: Eq = usize + Elit: Eq = usize, >(ipsum: Ipsum, dolor: Dolor, sit: Sit, diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index e9ba39f666c..f0923bd1a85 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -16,7 +16,7 @@ fn foo( fn bar< 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, >( a: Aaaaaaaaaaaaaaa, ) { @@ -51,7 +51,7 @@ impl Foo { fn bar< 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, >( a: Aaaaaaaaaaaaaaa, ) { @@ -69,7 +69,7 @@ struct Foo< TTTTTTTTTTTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUU, VVVVVVVVVVVVVVVVVVVVVVVVVVV, - WWWWWWWWWWWWWWWWWWWWWWWW + WWWWWWWWWWWWWWWWWWWWWWWW, > { foo: Foo, } diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index a29aac411ba..4d26c9b6951 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -16,7 +16,7 @@ fn foo( fn bar< 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, >( a: Aaaaaaaaaaaaaaa, ) { @@ -53,7 +53,7 @@ impl Foo { fn bar< 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, >( a: Aaaaaaaaaaaaaaa, ) { @@ -65,7 +65,7 @@ struct Foo< TTTTTTTTTTTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUU, VVVVVVVVVVVVVVVVVVVVVVVVVVV, - WWWWWWWWWWWWWWWWWWWWWWWW + WWWWWWWWWWWWWWWWWWWWWWWW, > { foo: Foo, } -- cgit 1.4.1-3-g733a5 From 88e522f921dad2f50b78f16dcd24ac256c8bf7c8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 10 Jun 2017 19:45:23 +0900 Subject: Use multiline in generics rather than fail --- src/items.rs | 169 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 124 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 03ca6f60832..f228bdf9d08 100644 --- a/src/items.rs +++ b/src/items.rs @@ -530,7 +530,9 @@ pub fn format_impl(context: &RewriteContext, if let ast::ItemKind::Impl(_, _, _, ref generics, ref trait_ref, _, ref items) = item.node { let mut result = String::new(); // First try to format the ref and type without a split at the 'for'. - let mut ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, false)); + let mut ref_and_type = + format_impl_ref_and_type(context, item, offset, false) + .unwrap_or(try_opt!(format_impl_ref_and_type(context, item, offset, true))); // If there is a line break present in the first result format it again // with a split at the 'for'. Skip this if there is no trait ref and @@ -540,10 +542,15 @@ pub fn format_impl(context: &RewriteContext, } result.push_str(&ref_and_type); - let where_budget = try_opt!(context - .config - .max_width() - .checked_sub(last_line_width(&result))); + let where_budget = if result.contains('\n') { + context.config.max_width() + } else { + context + .config + .max_width() + .checked_sub(last_line_width(&result)) + .unwrap_or(0) + }; let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config.item_brace_style(), @@ -666,34 +673,89 @@ fn format_impl_ref_and_type(context: &RewriteContext, None => self_ty.span.lo, }; let generics_indent = offset + last_line_width(&result); - let shape = Shape::indented(generics_indent, context.config); - let generics_str = try_opt!(rewrite_generics(context, generics, shape, mk_sp(lo, hi))); - result.push_str(&generics_str); + let shape = generics_shape_from_config(context.config, + Shape::indented(generics_indent, context.config), + 0); + let mut generics_str = + try_opt!(rewrite_generics(context, generics, shape, shape.width, mk_sp(lo, hi))); if polarity == ast::ImplPolarity::Negative { - result.push_str(" !"); + generics_str.push_str(" !"); } + + let mut retry_with_multiline = true; if let Some(ref trait_ref) = *trait_ref { if polarity != ast::ImplPolarity::Negative { - result.push_str(" "); + generics_str.push_str(" "); } - let used_space = last_line_width(&result); - let budget = try_opt!(context.config.max_width().checked_sub(used_space)); - let indent = offset + used_space; - result.push_str(&*try_opt!(trait_ref.rewrite(context, Shape::legacy(budget, indent)))); - - if split_at_for { - result.push('\n'); - - // Add indentation of one additional tab. - let width = offset.block_indent + context.config.tab_spaces(); - let for_indent = Indent::new(0, width); - result.push_str(&for_indent.to_string(context.config)); - - result.push_str("for"); + let used_space = if generics_str.contains('\n') { + last_line_width(&generics_str) } else { - result.push_str(" for"); + result.len() + generics_str.len() + }; + let budget = context + .config + .max_width() + .checked_sub(used_space) + .unwrap_or(0); + let indent = offset + used_space; + if let Some(trait_ref_str) = trait_ref.rewrite(context, Shape::legacy(budget, indent)) { + if !trait_ref_str.contains('\n') { + result.push_str(&generics_str); + result.push_str(&trait_ref_str); + if split_at_for { + result.push('\n'); + // Add indentation of one additional tab. + result.push_str(&offset + .block_indent(context.config) + .to_string(context.config)); + result.push_str("for"); + } else { + result.push_str(" for"); + } + retry_with_multiline = false; + } + } + if retry_with_multiline { + let mut generics_str = + try_opt!(rewrite_generics(context, generics, shape, 0, mk_sp(lo, hi))); + if polarity == ast::ImplPolarity::Negative { + generics_str.push_str(" !"); + } else { + generics_str.push_str(" "); + } + let used_space = if generics_str.contains('\n') { + last_line_width(&generics_str) + } else { + result.len() + generics_str.len() + }; + let budget = context + .config + .max_width() + .checked_sub(used_space) + .unwrap_or(0); + let indent = offset + used_space; + if let Some(trait_ref_str) = + trait_ref.rewrite(context, Shape::legacy(budget, indent)) { + result.push_str(&generics_str); + result.push_str(&trait_ref_str); + if split_at_for { + result.push('\n'); + // Add indentation of one additional tab. + result.push_str(&offset + .block_indent(context.config) + .to_string(context.config)); + result.push_str("for"); + } else { + result.push_str(" for"); + } + } } + } else { + if polarity == ast::ImplPolarity::Negative { + generics_str.push_str(" "); + } + result.push_str(&generics_str); } let mut used_space = last_line_width(&result); @@ -709,7 +771,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, // 1 = space before the type. let budget = try_opt!(context.config.max_width().checked_sub(used_space + 1)); - let indent = offset + result.len() + 1; + let indent = offset + last_line_width(&result) + 1; let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent)); if let Some(self_ty_str) = self_ty_str { result.push_str(" "); @@ -778,9 +840,14 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); let generics_indent = offset + last_line_width(&result); - let shape = Shape::indented(generics_indent, context.config); - let generics_str = - try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo))); + let shape = generics_shape_from_config(context.config, + Shape::indented(generics_indent, context.config), + 0); + let generics_str = try_opt!(rewrite_generics(context, + generics, + shape, + shape.width, + mk_sp(item.span.lo, body_lo))); result.push_str(&generics_str); let trait_bound_str = @@ -1025,9 +1092,15 @@ fn format_tuple_struct(context: &RewriteContext, let where_clause_str = match generics { Some(generics) => { let generics_indent = offset + last_line_width(&header_str); - let shape = Shape::indented(generics_indent, context.config); - let generics_str = - try_opt!(rewrite_generics(context, generics, shape, mk_sp(span.lo, body_lo))); + let shape = generics_shape_from_config(context.config, + Shape::indented(generics_indent, + context.config), + 0); + let generics_str = try_opt!(rewrite_generics(context, + generics, + shape, + shape.width, + mk_sp(span.lo, body_lo))); result.push_str(&generics_str); let where_budget = try_opt!(context @@ -1156,8 +1229,13 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_indent = indent + result.len(); let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let shape = try_opt!(Shape::indented(generics_indent, context.config).sub_width(" =".len())); - let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); + let shape = generics_shape_from_config(context.config, + try_opt!(Shape::indented(generics_indent, + context.config) + .sub_width(" =".len())), + 0); + let generics_str = + try_opt!(rewrite_generics(context, generics, shape, shape.width, generics_span)); result.push_str(&generics_str); @@ -1635,8 +1713,11 @@ fn rewrite_fn_base(context: &RewriteContext, // Generics. let generics_indent = indent + last_line_width(&result); let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); - let shape = Shape::indented(generics_indent, context.config); - let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span)); + let shape = generics_shape_from_config(context.config, + Shape::indented(generics_indent, context.config), + 0); + let generics_str = + try_opt!(rewrite_generics(context, generics, shape, shape.width, generics_span)); result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -2101,6 +2182,7 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { fn rewrite_generics(context: &RewriteContext, generics: &ast::Generics, shape: Shape, + one_line_width: usize, span: Span) -> Option { // FIXME: convert bounds to where clauses where they get too big or if @@ -2111,13 +2193,9 @@ fn rewrite_generics(context: &RewriteContext, return Some(String::new()); } - let generics_shape = generics_shape_from_config(context.config, shape, 0); // Strings for the generics. - let lt_strs = lifetimes - .iter() - .map(|lt| lt.rewrite(context, generics_shape)); - let ty_strs = tys.iter() - .map(|ty_param| ty_param.rewrite(context, generics_shape)); + let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, shape)); + let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(context, shape)); // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { @@ -2139,7 +2217,7 @@ fn rewrite_generics(context: &RewriteContext, |&(_, ref str)| str.clone(), context.codemap.span_after(span, "<"), span.hi); - format_generics_item_list(context, items, generics_shape, generics_shape.width) + format_generics_item_list(context, items, shape, one_line_width) } pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Shape { @@ -2385,8 +2463,9 @@ fn format_generics(context: &RewriteContext, offset: Indent, span: Span) -> Option { - let shape = Shape::indented(offset, context.config); - let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); + let shape = + generics_shape_from_config(context.config, Shape::indented(offset, context.config), 0); + let mut result = try_opt!(rewrite_generics(context, generics, shape, shape.width, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = try_opt!(context -- cgit 1.4.1-3-g733a5 From bd80077be89b3e8584d8c93af263e38c0e156d5b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 10 Jun 2017 20:37:34 +0900 Subject: Add format_trait_ref_then_update_result --- src/items.rs | 136 +++++++++++++++++++++---------------------- tests/source/big-impl-rfc.rs | 114 ++++++++++++++++++++++++++++++++++++ tests/target/big-impl-rfc.rs | 65 +++++++++++++++++++++ 3 files changed, 245 insertions(+), 70 deletions(-) create mode 100644 tests/source/big-impl-rfc.rs create mode 100644 tests/target/big-impl-rfc.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f228bdf9d08..a0b50bd50b7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -678,83 +678,30 @@ fn format_impl_ref_and_type(context: &RewriteContext, 0); let mut generics_str = try_opt!(rewrite_generics(context, generics, shape, shape.width, mk_sp(lo, hi))); + add_polarity(&mut generics_str, &polarity, trait_ref.is_some()); - if polarity == ast::ImplPolarity::Negative { - generics_str.push_str(" !"); - } - - let mut retry_with_multiline = true; if let Some(ref trait_ref) = *trait_ref { - if polarity != ast::ImplPolarity::Negative { - generics_str.push_str(" "); - } - let used_space = if generics_str.contains('\n') { - last_line_width(&generics_str) - } else { - result.len() + generics_str.len() - }; - let budget = context - .config - .max_width() - .checked_sub(used_space) - .unwrap_or(0); - let indent = offset + used_space; - if let Some(trait_ref_str) = trait_ref.rewrite(context, Shape::legacy(budget, indent)) { - if !trait_ref_str.contains('\n') { - result.push_str(&generics_str); - result.push_str(&trait_ref_str); - if split_at_for { - result.push('\n'); - // Add indentation of one additional tab. - result.push_str(&offset - .block_indent(context.config) - .to_string(context.config)); - result.push_str("for"); - } else { - result.push_str(" for"); - } - retry_with_multiline = false; - } - } - if retry_with_multiline { + let success = format_trait_ref_then_update_result(context, + &trait_ref, + offset, + &generics_str, + split_at_for, + &mut result); + if !success { let mut generics_str = try_opt!(rewrite_generics(context, generics, shape, 0, mk_sp(lo, hi))); - if polarity == ast::ImplPolarity::Negative { - generics_str.push_str(" !"); - } else { - generics_str.push_str(" "); - } - let used_space = if generics_str.contains('\n') { - last_line_width(&generics_str) - } else { - result.len() + generics_str.len() - }; - let budget = context - .config - .max_width() - .checked_sub(used_space) - .unwrap_or(0); - let indent = offset + used_space; - if let Some(trait_ref_str) = - trait_ref.rewrite(context, Shape::legacy(budget, indent)) { - result.push_str(&generics_str); - result.push_str(&trait_ref_str); - if split_at_for { - result.push('\n'); - // Add indentation of one additional tab. - result.push_str(&offset - .block_indent(context.config) - .to_string(context.config)); - result.push_str("for"); - } else { - result.push_str(" for"); - } + add_polarity(&mut generics_str, &polarity, true); + if !format_trait_ref_then_update_result(context, + &trait_ref, + offset, + &generics_str, + split_at_for, + &mut result) { + // FIXME: should be unreachable + return None; } } } else { - if polarity == ast::ImplPolarity::Negative { - generics_str.push_str(" "); - } result.push_str(&generics_str); } @@ -790,6 +737,55 @@ fn format_impl_ref_and_type(context: &RewriteContext, } } +// Returns false if failed to update result: then, try using multiline. +fn format_trait_ref_then_update_result(context: &RewriteContext, + trait_ref: &ast::TraitRef, + offset: Indent, + generics_str: &str, + split_at_for: bool, + result: &mut String) + -> bool { + let used_space = if generics_str.contains('\n') { + last_line_width(&generics_str) + } else { + result.len() + generics_str.len() + }; + let budget = context + .config + .max_width() + .checked_sub(used_space) + .unwrap_or(0); + let indent = offset + used_space; + if let Some(trait_ref_str) = trait_ref.rewrite(context, Shape::legacy(budget, indent)) { + if !trait_ref_str.contains('\n') { + result.push_str(&generics_str); + result.push_str(&trait_ref_str); + if split_at_for { + result.push('\n'); + // Add indentation of one additional tab. + let for_offset = match context.config.where_style() { + Style::Legacy => offset.block_indent(context.config), + Style::Rfc => offset, + }; + result.push_str(&for_offset.to_string(context.config)); + result.push_str("for"); + } else { + result.push_str(" for"); + } + return true; + } + } + false +} + +fn add_polarity(s: &mut String, polarity: &ast::ImplPolarity, has_trait_ref: bool) { + if polarity == &ast::ImplPolarity::Negative { + s.push_str(" !") + } else if has_trait_ref { + s.push(' ') + } +} + pub fn format_struct(context: &RewriteContext, item_name: &str, ident: ast::Ident, diff --git a/tests/source/big-impl-rfc.rs b/tests/source/big-impl-rfc.rs new file mode 100644 index 00000000000..167f654cc43 --- /dev/null +++ b/tests/source/big-impl-rfc.rs @@ -0,0 +1,114 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-fn_call_style: Block +// rustfmt-generics_indent: Block +// rustfmt-where_style: Rfc + +// #1357 +impl< + 'a, + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + Groupby, + DB, +> InternalBoxedDsl<'a, DB> + for SelectStatement< + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + GroupBy, + > where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} diff --git a/tests/target/big-impl-rfc.rs b/tests/target/big-impl-rfc.rs new file mode 100644 index 00000000000..18fa59cb5a0 --- /dev/null +++ b/tests/target/big-impl-rfc.rs @@ -0,0 +1,65 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-fn_call_style: Block +// rustfmt-generics_indent: Block +// rustfmt-where_style: Rfc + +// #1357 +impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> +for SelectStatement +where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl Foo +for Bar { + fn foo() {} +} +impl Foo +for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo +for Bar { + fn foo() {} +} +impl Foo +for Bar { + fn foo() {} +} +impl Foo +for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo +for Bar { + fn foo() {} +} -- cgit 1.4.1-3-g733a5 From f2838595d56124548f403a81715627872a4f93ba Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Jun 2017 22:20:11 +0900 Subject: Add visual offset when using struct_lit_style is Visual --- src/lists.rs | 3 ++- tests/target/configs-struct_lit_style-visual.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 978d9dbaceb..ec4427032e5 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -529,7 +529,8 @@ pub fn struct_lit_shape(shape: Shape, -> Option<(Option, Shape)> { let v_shape = match context.config.struct_lit_style() { IndentStyle::Visual => { - try_opt!(try_opt!(shape.shrink_left(prefix_width)).sub_width(suffix_width)) + try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width)) + .sub_width(suffix_width)) } IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); diff --git a/tests/target/configs-struct_lit_style-visual.rs b/tests/target/configs-struct_lit_style-visual.rs index 685ded59aad..eb470e1e29c 100644 --- a/tests/target/configs-struct_lit_style-visual.rs +++ b/tests/target/configs-struct_lit_style-visual.rs @@ -3,5 +3,5 @@ fn main() { let lorem = Lorem { ipsum: dolor, - sit: amet, }; + sit: amet, }; } -- cgit 1.4.1-3-g733a5 From 9b195ae228be1c74b2ccdc83697219e35439b01f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 11 Jun 2017 14:32:44 +0900 Subject: Refactor format_impl --- src/items.rs | 160 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 82 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a0b50bd50b7..10ab6fe72df 100644 --- a/src/items.rs +++ b/src/items.rs @@ -527,19 +527,9 @@ pub fn format_impl(context: &RewriteContext, offset: Indent, where_span_end: Option) -> Option { - if let ast::ItemKind::Impl(_, _, _, ref generics, ref trait_ref, _, ref items) = item.node { + if let ast::ItemKind::Impl(_, _, _, ref generics, _, _, ref items) = item.node { let mut result = String::new(); - // First try to format the ref and type without a split at the 'for'. - let mut ref_and_type = - format_impl_ref_and_type(context, item, offset, false) - .unwrap_or(try_opt!(format_impl_ref_and_type(context, item, offset, true))); - - // If there is a line break present in the first result format it again - // with a split at the 'for'. Skip this if there is no trait ref and - // therefore no 'for'. - if ref_and_type.contains('\n') && trait_ref.is_some() { - ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset, true)); - } + let ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset)); result.push_str(&ref_and_type); let where_budget = if result.contains('\n') { @@ -651,8 +641,7 @@ fn is_impl_single_line(context: &RewriteContext, fn format_impl_ref_and_type(context: &RewriteContext, item: &ast::Item, - offset: Indent, - split_at_for: bool) + offset: Indent) -> Option { if let ast::ItemKind::Impl(unsafety, polarity, @@ -672,32 +661,37 @@ fn format_impl_ref_and_type(context: &RewriteContext, Some(ref tr) => tr.path.span.lo, None => self_ty.span.lo, }; - let generics_indent = offset + last_line_width(&result); let shape = generics_shape_from_config(context.config, - Shape::indented(generics_indent, context.config), + Shape::indented(offset + last_line_width(&result), + context.config), 0); - let mut generics_str = + let generics_str = try_opt!(rewrite_generics(context, generics, shape, shape.width, mk_sp(lo, hi))); - add_polarity(&mut generics_str, &polarity, trait_ref.is_some()); + + let polarity_str = if polarity == ast::ImplPolarity::Negative { + "!" + } else { + "" + }; if let Some(ref trait_ref) = *trait_ref { let success = format_trait_ref_then_update_result(context, &trait_ref, offset, &generics_str, - split_at_for, + true, + polarity_str, &mut result); if !success { - let mut generics_str = + let generics_str = try_opt!(rewrite_generics(context, generics, shape, 0, mk_sp(lo, hi))); - add_polarity(&mut generics_str, &polarity, true); if !format_trait_ref_then_update_result(context, &trait_ref, offset, &generics_str, - split_at_for, + false, + polarity_str, &mut result) { - // FIXME: should be unreachable return None; } } @@ -705,32 +699,52 @@ fn format_impl_ref_and_type(context: &RewriteContext, result.push_str(&generics_str); } - let mut used_space = last_line_width(&result); - if generics.where_clause.predicates.is_empty() { + // Try to put the self type in a single line. + // ` for` + let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; + let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { // If there is no where clause adapt budget for type formatting to take space and curly // brace into account. match context.config.item_brace_style() { - BraceStyle::AlwaysNextLine => {} - BraceStyle::PreferSameLine => used_space += 2, - BraceStyle::SameLineWhere => used_space += 2, + BraceStyle::AlwaysNextLine => 0, + _ => 2, } - } - + } else { + 0 + }; + let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; // 1 = space before the type. - let budget = try_opt!(context.config.max_width().checked_sub(used_space + 1)); - let indent = offset + last_line_width(&result) + 1; - let self_ty_str = self_ty.rewrite(context, Shape::legacy(budget, indent)); - if let Some(self_ty_str) = self_ty_str { - result.push_str(" "); - result.push_str(&self_ty_str); - return Some(result); + let budget = context + .config + .max_width() + .checked_sub(used_space + 1) + .unwrap_or(0); + if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { + if !self_ty_str.contains('\n') { + if trait_ref.is_some() { + result.push_str(" for "); + } else { + result.push(' '); + } + result.push_str(&self_ty_str); + return Some(result); + } } - // Can't fit the self type on what's left of the line, so start a new one. - let indent = offset.block_indent(context.config); - result.push_str(&format!("\n{}", indent.to_string(context.config))); - result.push_str(&*try_opt!(self_ty.rewrite(context, - Shape::indented(indent, context.config)))); + // Couldn't fit the self type on a single line, put it on a new line. + result.push('\n'); + // Add indentation of one additional tab. + let new_line_offset = offset.block_indent(context.config); + result.push_str(&new_line_offset.to_string(context.config)); + if trait_ref.is_some() { + result.push_str("for "); + } + let budget = context.config.max_width() - last_line_width(&result); + let type_offset = match context.config.where_style() { + Style::Legacy => new_line_offset + trait_ref_overhead, + Style::Rfc => new_line_offset, + }; + result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, type_offset)))); Some(result) } else { unreachable!(); @@ -742,48 +756,38 @@ fn format_trait_ref_then_update_result(context: &RewriteContext, trait_ref: &ast::TraitRef, offset: Indent, generics_str: &str, - split_at_for: bool, + retry: bool, + polarity_str: &str, result: &mut String) -> bool { - let used_space = if generics_str.contains('\n') { - last_line_width(&generics_str) - } else { - result.len() + generics_str.len() - }; - let budget = context - .config - .max_width() - .checked_sub(used_space) - .unwrap_or(0); - let indent = offset + used_space; - if let Some(trait_ref_str) = trait_ref.rewrite(context, Shape::legacy(budget, indent)) { - if !trait_ref_str.contains('\n') { - result.push_str(&generics_str); - result.push_str(&trait_ref_str); - if split_at_for { - result.push('\n'); - // Add indentation of one additional tab. - let for_offset = match context.config.where_style() { - Style::Legacy => offset.block_indent(context.config), - Style::Rfc => offset, - }; - result.push_str(&for_offset.to_string(context.config)); - result.push_str("for"); - } else { - result.push_str(" for"); - } + // 1 = space between generics and trait_ref + let used_space = 1 + polarity_str.len() + + if generics_str.contains('\n') { + last_line_width(&generics_str) + } else { + result.len() + generics_str.len() + }; + let shape = Shape::indented(offset + used_space, context.config); + if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { + if !(retry && trait_ref_str.contains('\n')) { + result.push_str(&format!("{} {}{}", generics_str, polarity_str, &trait_ref_str)); return true; } } - false -} - -fn add_polarity(s: &mut String, polarity: &ast::ImplPolarity, has_trait_ref: bool) { - if polarity == &ast::ImplPolarity::Negative { - s.push_str(" !") - } else if has_trait_ref { - s.push(' ') + // We could not make enough space for trait_ref, so put it on new line. + if !retry { + let offset = offset.block_indent(context.config); + let shape = Shape::indented(offset, context.config); + if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { + result.push_str(&format!("{}\n{}{}{}", + generics_str, + &offset.to_string(context.config), + polarity_str, + &trait_ref_str)); + return true; + } } + false } pub fn format_struct(context: &RewriteContext, -- cgit 1.4.1-3-g733a5 From f135641cc873c21ea8768a78534efc9ff3f4bb82 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 11 Jun 2017 23:26:49 +0900 Subject: Use multi line when type bounds does not fit in a single line --- src/expr.rs | 2 +- src/items.rs | 107 +++++++++++++++++++++-------------------------------------- src/types.rs | 100 ++++++++++++++++++++++++------------------------------- 3 files changed, 82 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index aa5913e5f0f..04778b6ddca 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2063,12 +2063,12 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // FIXME if context.config.struct_lit_style() == Visual, but we run out // of space, we should fall back to BlockIndent. } + pub fn struct_lit_field_separator(config: &Config) -> &str { colon_spaces(config.space_before_struct_lit_field_colon(), config.space_after_struct_lit_field_colon()) } - fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { let name = &field.ident.node.to_string(); if field.is_shorthand { diff --git a/src/items.rs b/src/items.rs index 10ab6fe72df..78226624c4f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -21,7 +21,8 @@ use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style, TypeDensity}; +use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style}; +use types::join_bounds; use syntax::{ast, abi, ptr, symbol}; use syntax::codemap::{Span, BytePos}; @@ -666,7 +667,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, context.config), 0); let generics_str = - try_opt!(rewrite_generics(context, generics, shape, shape.width, mk_sp(lo, hi))); + try_opt!(rewrite_generics_inner(context, generics, shape, shape.width, mk_sp(lo, hi))); let polarity_str = if polarity == ast::ImplPolarity::Negative { "!" @@ -684,7 +685,7 @@ fn format_impl_ref_and_type(context: &RewriteContext, &mut result); if !success { let generics_str = - try_opt!(rewrite_generics(context, generics, shape, 0, mk_sp(lo, hi))); + try_opt!(rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))); if !format_trait_ref_then_update_result(context, &trait_ref, offset, @@ -839,15 +840,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); - let generics_indent = offset + last_line_width(&result); - let shape = generics_shape_from_config(context.config, - Shape::indented(generics_indent, context.config), - 0); - let generics_str = try_opt!(rewrite_generics(context, - generics, - shape, - shape.width, - mk_sp(item.span.lo, body_lo))); + let shape = Shape::indented(offset + last_line_width(&result), context.config); + let generics_str = + try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo))); result.push_str(&generics_str); let trait_bound_str = @@ -1091,16 +1086,9 @@ fn format_tuple_struct(context: &RewriteContext, let where_clause_str = match generics { Some(generics) => { - let generics_indent = offset + last_line_width(&header_str); - let shape = generics_shape_from_config(context.config, - Shape::indented(generics_indent, - context.config), - 0); - let generics_str = try_opt!(rewrite_generics(context, - generics, - shape, - shape.width, - mk_sp(span.lo, body_lo))); + let shape = Shape::indented(offset + last_line_width(&header_str), context.config); + let g_span = mk_sp(span.lo, body_lo); + let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); let where_budget = try_opt!(context @@ -1227,16 +1215,10 @@ pub fn rewrite_type_alias(context: &RewriteContext, result.push_str("type "); result.push_str(&ident.to_string()); - let generics_indent = indent + result.len(); - let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); - let shape = generics_shape_from_config(context.config, - try_opt!(Shape::indented(generics_indent, - context.config) - .sub_width(" =".len())), - 0); - let generics_str = - try_opt!(rewrite_generics(context, generics, shape, shape.width, generics_span)); - + // 2 = `= ` + let shape = try_opt!(Shape::indented(indent + result.len(), context.config).sub_width(2)); + let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); + let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); let where_budget = try_opt!(context @@ -1470,23 +1452,14 @@ pub fn rewrite_associated_type(ident: ast::Ident, let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; + let shape = Shape::legacy(context.config.max_width(), indent); let bounds: &[_] = ty_param_bounds; - let bound_str = - try_opt!(bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(context.config.max_width(), - indent)) - }) - .collect::>>()) - .join(joiner); + let bound_str = try_opt!(bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()); if bounds.len() > 0 { - format!(": {}", bound_str) + format!(": {}", join_bounds(context, shape, &bound_str)) } else { String::new() } @@ -1711,13 +1684,9 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(&ident.to_string()); // Generics. - let generics_indent = indent + last_line_width(&result); - let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo); - let shape = generics_shape_from_config(context.config, - Shape::indented(generics_indent, context.config), - 0); - let generics_str = - try_opt!(rewrite_generics(context, generics, shape, shape.width, generics_span)); + let shape = Shape::indented(indent + last_line_width(&result), context.config); + let g_span = mk_sp(span.lo, span_for_return(&fd.output).lo); + let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -2182,9 +2151,19 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { fn rewrite_generics(context: &RewriteContext, generics: &ast::Generics, shape: Shape, - one_line_width: usize, span: Span) -> Option { + let shape = generics_shape_from_config(context.config, shape, 0); + rewrite_generics_inner(context, generics, shape, shape.width, span) + .or_else(|| rewrite_generics_inner(context, generics, shape, 0, span)) +} + +fn rewrite_generics_inner(context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + one_line_width: usize, + span: Span) + -> Option { // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; @@ -2286,20 +2265,11 @@ fn rewrite_trait_bounds(context: &RewriteContext, if bounds.is_empty() { return Some(String::new()); } - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; let bound_str = try_opt!(bounds .iter() .map(|ty_bound| ty_bound.rewrite(&context, shape)) - .collect::>>()) - .join(joiner); - - let mut result = String::new(); - result.push_str(": "); - result.push_str(&bound_str); - Some(result) + .collect::>>()); + Some(format!(": {}", join_bounds(context, shape, &bound_str))) } fn rewrite_where_clause_rfc_style(context: &RewriteContext, @@ -2463,9 +2433,8 @@ fn format_generics(context: &RewriteContext, offset: Indent, span: Span) -> Option { - let shape = - generics_shape_from_config(context.config, Shape::indented(offset, context.config), 0); - let mut result = try_opt!(rewrite_generics(context, generics, shape, shape.width, span)); + let shape = Shape::indented(offset, context.config); + let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = try_opt!(context diff --git a/src/types.rs b/src/types.rs index 4e74ea8213f..d2405f390f1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -22,7 +22,7 @@ use codemap::SpanUtils; use items::{format_generics_item_list, generics_shape_from_config}; use lists::{itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp}; +use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; use config::TypeDensity; @@ -362,22 +362,15 @@ impl Rewrite for ast::WherePredicate { .collect::>>()) .join(", "); - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!( - bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, shape.indent + used_width)) - }) - .collect::>>() - ).join(joiner); + let ty_shape = try_opt!(shape.block_left(used_width)); + let bounds: Vec<_> = + try_opt!(bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect()); + let bounds_str = join_bounds(context, ty_shape, &bounds); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { format!("for< {} > {}{}{}", @@ -389,21 +382,14 @@ impl Rewrite for ast::WherePredicate { format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) } } else { - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; let used_width = type_str.len() + colon.len(); - let budget = try_opt!(shape.width.checked_sub(used_width)); - let bounds_str: String = try_opt!( - bounds - .iter() - .map(|ty_bound| { - ty_bound.rewrite(context, - Shape::legacy(budget, shape.indent + used_width)) - }) - .collect::>>() - ).join(joiner); + let ty_shape = try_opt!(shape.block_left(used_width)); + let bounds: Vec<_> = + try_opt!(bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect()); + let bounds_str = join_bounds(context, ty_shape, &bounds); format!("{}{}{}", type_str, colon, bounds_str) } @@ -458,11 +444,11 @@ fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, .map(|b| b.rewrite(context, shape)) .collect()); let colon = type_bound_colon(context); - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let result = format!("{}{}{}", result, colon, appendix.join(joiner)); + let overhead = last_line_width(&result) + colon.len(); + let result = format!("{}{}{}", + result, + colon, + join_bounds(context, try_opt!(shape.sub_width(overhead)), &appendix)); wrap_str(result, context.config.max_width(), shape) } } @@ -494,12 +480,8 @@ impl Rewrite for ast::Lifetime { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect()); - wrap_str(strs.join(joiner), context.config.max_width(), shape) + join_bounds(context, shape, &strs).rewrite(context, shape) } } @@ -514,24 +496,12 @@ impl Rewrite for ast::TyParam { result.push_str(&attr_str); result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { - if context.config.space_before_bound() { - result.push_str(" "); - } - result.push_str(":"); - if context.config.space_after_bound_colon() { - result.push_str(" "); - } - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let bounds: String = try_opt!(self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()) - .join(joiner); - - result.push_str(&bounds); + result.push_str(type_bound_colon(context)); + let strs: Vec<_> = try_opt!(self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect()); + result.push_str(&join_bounds(context, shape, &strs)); } if let Some(ref def) = self.default { @@ -732,3 +702,19 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, Some(result) } + +pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &Vec) -> String { + // Try to join types in a single line + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let result = type_strs.join(joiner); + if result.contains('\n') || result.len() > shape.width { + let joiner_indent = shape.indent.block_indent(context.config); + let joiner = format!("\n{}+ ", joiner_indent.to_string(context.config)); + type_strs.join(&joiner) + } else { + result + } +} -- cgit 1.4.1-3-g733a5 From 62e9473d07ec9a35e1c1e63140381055d86bb478 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Jun 2017 08:53:19 +0900 Subject: Update rewrite_trait_ref to return Option --- src/items.rs | 74 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 78226624c4f..6b9e1e411f1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -676,25 +676,26 @@ fn format_impl_ref_and_type(context: &RewriteContext, }; if let Some(ref trait_ref) = *trait_ref { - let success = format_trait_ref_then_update_result(context, - &trait_ref, - offset, - &generics_str, - true, - polarity_str, - &mut result); - if !success { + let result_len = result.len(); + if let Some(trait_ref_str) = + rewrite_trait_ref(context, + &trait_ref, + offset, + &generics_str, + true, + polarity_str, + result_len) { + result.push_str(&trait_ref_str); + } else { let generics_str = try_opt!(rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))); - if !format_trait_ref_then_update_result(context, - &trait_ref, - offset, - &generics_str, - false, - polarity_str, - &mut result) { - return None; - } + result.push_str(&try_opt!(rewrite_trait_ref(context, + &trait_ref, + offset, + &generics_str, + false, + polarity_str, + result_len))); } } else { result.push_str(&generics_str); @@ -752,43 +753,40 @@ fn format_impl_ref_and_type(context: &RewriteContext, } } -// Returns false if failed to update result: then, try using multiline. -fn format_trait_ref_then_update_result(context: &RewriteContext, - trait_ref: &ast::TraitRef, - offset: Indent, - generics_str: &str, - retry: bool, - polarity_str: &str, - result: &mut String) - -> bool { +fn rewrite_trait_ref(context: &RewriteContext, + trait_ref: &ast::TraitRef, + offset: Indent, + generics_str: &str, + retry: bool, + polarity_str: &str, + result_len: usize) + -> Option { // 1 = space between generics and trait_ref let used_space = 1 + polarity_str.len() + if generics_str.contains('\n') { last_line_width(&generics_str) } else { - result.len() + generics_str.len() + result_len + generics_str.len() }; let shape = Shape::indented(offset + used_space, context.config); if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { if !(retry && trait_ref_str.contains('\n')) { - result.push_str(&format!("{} {}{}", generics_str, polarity_str, &trait_ref_str)); - return true; + return Some(format!("{} {}{}", generics_str, polarity_str, &trait_ref_str)); } } // We could not make enough space for trait_ref, so put it on new line. if !retry { let offset = offset.block_indent(context.config); let shape = Shape::indented(offset, context.config); - if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { - result.push_str(&format!("{}\n{}{}{}", - generics_str, - &offset.to_string(context.config), - polarity_str, - &trait_ref_str)); - return true; - } + let trait_ref_str = try_opt!(trait_ref.rewrite(context, shape)); + Some(format!("{}\n{}{}{}", + generics_str, + &offset.to_string(context.config), + polarity_str, + &trait_ref_str)) + } else { + None } - false } pub fn format_struct(context: &RewriteContext, -- cgit 1.4.1-3-g733a5 From 9ad499786d1eb8008423d9d9810b47c4124e8d47 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Jun 2017 15:58:27 +0900 Subject: Use block indent for args if single line args exceeds max width --- src/expr.rs | 18 +++++++++++++++--- tests/source/configs-fn_call_style-block.rs | 6 ++++++ .../configs-fn_call_style-block-trailing-comma.rs | 4 +++- tests/target/configs-fn_call_style-block.rs | 7 +++++++ 4 files changed, 31 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index aa5913e5f0f..b47bf391ac1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1734,9 +1734,12 @@ fn rewrite_call_inner(context: &RewriteContext, force_trailing_comma); } + let args_shape = shape + .sub_width(last_line_width(&callee_str)) + .ok_or(Ordering::Less)?; Ok(format!("{}{}", callee_str, - wrap_args_with_parens(context, &list_str, extendable, shape, nested_shape))) + wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape))) } fn need_block_indent(s: &str, shape: Shape) -> bool { @@ -1906,14 +1909,23 @@ fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: } } +fn paren_overhead(context: &RewriteContext) -> usize { + if context.config.spaces_within_parens() { + 4 + } else { + 2 + } +} + fn wrap_args_with_parens(context: &RewriteContext, args_str: &str, is_extendable: bool, shape: Shape, nested_shape: Shape) -> String { - if !context.use_block_indent() || (context.inside_macro && !args_str.contains('\n')) || - is_extendable { + if !context.use_block_indent() || + (context.inside_macro && !args_str.contains('\n') && + args_str.len() + paren_overhead(context) <= shape.width) || is_extendable { if context.config.spaces_within_parens() && args_str.len() > 0 { format!("( {} )", args_str) } else { diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index 2068216d18e..ee6178c1902 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -125,3 +125,9 @@ fn issue1581() { }, ); } + +fn issue1651() { + { + let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + } +} diff --git a/tests/target/configs-fn_call_style-block-trailing-comma.rs b/tests/target/configs-fn_call_style-block-trailing-comma.rs index ebdf41d0e3b..b6eb94eb677 100644 --- a/tests/target/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/target/configs-fn_call_style-block-trailing-comma.rs @@ -3,7 +3,9 @@ // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + panic!( + "this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:" + ); foo( oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), ); diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index ddead8ce5a8..dfc8daef6d9 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -145,3 +145,10 @@ fn issue1581() { } }); } + +fn issue1651() { + { + let type_list: Vec<_> = + try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + } +} -- cgit 1.4.1-3-g733a5 From d269189f19f62de61564d9225cef18d9482bb55c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Jun 2017 16:23:10 +0900 Subject: Use correct indent for return type when it goes multi line --- src/items.rs | 2 +- tests/source/configs-fn_args_layout-block.rs | 4 ++++ tests/target/configs-fn_args_layout-block.rs | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ac2f36ad76a..43101d9187b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1798,7 +1798,7 @@ fn rewrite_fn_base(context: &RewriteContext, indent } else { result.push(' '); - Indent::new(indent.width(), result.len()) + Indent::new(indent.block_indent, last_line_width(&result)) }; if multi_line_ret_str || ret_should_indent { diff --git a/tests/source/configs-fn_args_layout-block.rs b/tests/source/configs-fn_args_layout-block.rs index 55b38101abc..28d1dffe6b3 100644 --- a/tests/source/configs-fn_args_layout-block.rs +++ b/tests/source/configs-fn_args_layout-block.rs @@ -20,3 +20,7 @@ extern "C" { second_parameter: SecondParameterType, ...); } + +// #1652 +fn deconstruct(foo: Bar) -> (SocketAddr, Header, Method, RequestUri, HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} diff --git a/tests/target/configs-fn_args_layout-block.rs b/tests/target/configs-fn_args_layout-block.rs index 04a4d631ca4..f93b84f2d4a 100644 --- a/tests/target/configs-fn_args_layout-block.rs +++ b/tests/target/configs-fn_args_layout-block.rs @@ -32,3 +32,14 @@ extern "C" { ... ); } + +// #1652 +fn deconstruct( + foo: Bar, +) -> (SocketAddr, + Header, + Method, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} -- cgit 1.4.1-3-g733a5 From 9df1509d1913865303844728de1b24d4495e9a4f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Jun 2017 17:25:07 +0900 Subject: Use rewrite instead of visitor for attributes --- src/expr.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index aa5913e5f0f..e6889991b07 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1321,20 +1321,13 @@ impl Rewrite for ast::Arm { ref body, } = self; - // FIXME this is all a bit grotty, would be nice to abstract out the - // treatment of attributes. let attr_str = if !attrs.is_empty() { - // We only use this visitor for the attributes, should we use it for - // more? - let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - attr_visitor.block_indent = shape.indent.block_only(); - attr_visitor.last_pos = attrs[0].span.lo; - if attr_visitor.visit_attrs(attrs) { - // Attributes included a skip instruction. + if contains_skip(attrs) { return None; } - attr_visitor.format_missing(pats[0].span.lo); - attr_visitor.buffer.to_string() + format!("{}\n{}", + try_opt!(attrs.rewrite(context, shape)), + shape.indent.to_string(context.config)) } else { String::new() }; -- cgit 1.4.1-3-g733a5 From 57fc39305dc765d4454869ab6a6b9667c17b6e57 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Jun 2017 17:25:38 +0900 Subject: Put guard on newline if it exceeds max width --- src/expr.rs | 28 +++++++++++----------------- tests/target/configs-control_style-rfc.rs | 17 +++++++++++++++++ tests/target/match.rs | 4 ++-- 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e6889991b07..06993c729b7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1495,28 +1495,22 @@ fn rewrite_guard(context: &RewriteContext, if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` - let overhead = pattern_width + 4 + 5; - if overhead < shape.width { - let cond_shape = shape - .shrink_left(pattern_width + 4) - .unwrap() - .sub_width(5) - .unwrap(); - let cond_str = guard.rewrite(context, cond_shape); - if let Some(cond_str) = cond_str { + if let Some(cond_shape) = shape + .shrink_left(pattern_width + 4) + .and_then(|s| s.sub_width(5)) { + if let Some(cond_str) = guard + .rewrite(context, cond_shape) + .and_then(|s| s.rewrite(context, cond_shape)) { return Some(format!(" if {}", cond_str)); } } // Not enough space to put the guard after the pattern, try a newline. - let overhead = shape.indent.block_indent(context.config).width() + 4 + 5; - if overhead < shape.width { - let cond_str = guard.rewrite(context, - Shape::legacy(shape.width - overhead, - // 3 == `if ` - shape.indent.block_indent(context.config) + - 3)); - if let Some(cond_str) = cond_str { + // 3 == `if ` + if let Some(cond_shape) = Shape::indented(shape.indent.block_indent(context.config) + 3, + context.config) + .sub_width(3) { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { return Some(format!("\n{}if {}", shape .indent diff --git a/tests/target/configs-control_style-rfc.rs b/tests/target/configs-control_style-rfc.rs index a7213c34dfb..43a10e92339 100644 --- a/tests/target/configs-control_style-rfc.rs +++ b/tests/target/configs-control_style-rfc.rs @@ -21,3 +21,20 @@ fn main() { } } } + +fn issue1656() { + { + { + match rewrite { + Some(ref body_str) + if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) || + !context.config.wrap_match_arms() || + (extend && first_line_width(body_str) <= arm_shape.width) || + is_block => { + return None; + } + _ => {} + } + } + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 6acab043e67..45f62ca6845 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -306,8 +306,8 @@ fn guards() { barrrrrrrrrrrr => {} aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if fooooooooooooooooooooo && - (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || - cccccccccccccccccccccccccccccccccccccccc) => {} + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => { + } } } -- cgit 1.4.1-3-g733a5 From ad628f6accd7024305c8a564fbdf177ba5068ba3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Jun 2017 18:34:38 +0900 Subject: Force multi line if the first attempt of rewriting args failed --- src/expr.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b47bf391ac1..cbe8671fd92 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1721,6 +1721,20 @@ fn rewrite_call_inner(context: &RewriteContext, nested_shape, one_line_width, force_trailing_comma) + .or_else(|| if context.use_block_indent() { + rewrite_call_args(context, + args, + args_span, + Shape::indented(shape + .block() + .indent + .block_indent(context.config), + context.config), + 0, + force_trailing_comma) + } else { + None + }) .ok_or(Ordering::Less)?; if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { -- cgit 1.4.1-3-g733a5 From 6e3394e6352ecb7dfdb7c248f4ceed9f9d11b763 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 13 Jun 2017 09:18:14 +0900 Subject: Use with_emitter instead of with_tty_emitter --- src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 6488c83e983..219e98ef1e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -460,8 +460,9 @@ fn format_ast(krate: &ast::Crate, } // Reset the error count. if parse_session.span_diagnostic.has_errors() { - parse_session.span_diagnostic = - Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())); + let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), + Some(codemap.clone()))); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); } } -- cgit 1.4.1-3-g733a5 From f084a8af963c2160c4832226d7c0003982f13204 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 13 Jun 2017 10:18:55 +0900 Subject: Fix excessive indentation in trait where clause when using Rfc style --- src/items.rs | 2 +- src/types.rs | 7 +++++-- tests/source/where-clause-rfc.rs | 6 ++++++ tests/target/where-clause-rfc.rs | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 18b58e57fe1..085b9eed812 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2306,7 +2306,7 @@ fn rewrite_where_clause_rfc_style(context: &RewriteContext, terminator, |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(context, clause_shape), + |pred| pred.rewrite(context, shape), span_start, span_end); let comma_tactic = if suppress_comma { diff --git a/src/types.rs b/src/types.rs index d2405f390f1..7e5daa12f81 100644 --- a/src/types.rs +++ b/src/types.rs @@ -24,7 +24,7 @@ use lists::{itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width}; use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; -use config::TypeDensity; +use config::{Style, TypeDensity}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -383,7 +383,10 @@ impl Rewrite for ast::WherePredicate { } } else { let used_width = type_str.len() + colon.len(); - let ty_shape = try_opt!(shape.block_left(used_width)); + let ty_shape = match context.config.where_style() { + Style::Legacy => try_opt!(shape.block_left(used_width)), + Style::Rfc => shape.block_indent(context.config.tab_spaces()), + }; let bounds: Vec<_> = try_opt!(bounds .iter() diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs index d8a014c4a91..ef822f6bea2 100644 --- a/tests/source/where-clause-rfc.rs +++ b/tests/source/where-clause-rfc.rs @@ -42,3 +42,9 @@ struct Exactly100CharsToSemicolon struct AlwaysOnNextLine where A: LongTrait { x: i32 } + +pub trait SomeTrait + where + T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr +{ +} diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index 6859690fa15..bdf1f9d2574 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -96,3 +96,20 @@ where { x: i32, } + +pub trait SomeTrait +where + T: Something + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read + + FromStr +{ +} -- cgit 1.4.1-3-g733a5 From 32e882789ba98cf6c02b1822beecacbcb8800269 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Jun 2017 15:50:43 +1200 Subject: Change defaults to RFC style --- Cargo.toml | 2 +- README.md | 5 +++++ legacy-rustfmt.toml | 8 ++++++++ rfc-rustfmt.toml | 8 -------- src/config.rs | 16 ++++++++-------- 5 files changed, 22 insertions(+), 17 deletions(-) create mode 100644 legacy-rustfmt.toml delete mode 100644 rfc-rustfmt.toml (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 75a8ce74974..a79c974b31d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt" -version = "0.8.6" +version = "0.9" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/README.md b/README.md index fa4e9d6c4e2..d60da4dec75 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,11 @@ A tool for formatting Rust code according to style guidelines. If you'd like to help out (and you should, it's a fun project!), see [Contributing.md](Contributing.md). +We are changing the default style used by rustfmt. There is an ongoing [RFC process](https://github.com/rust-lang-nursery/fmt-rfcs). +The last version using the old style was 0.8.5. From 0.9 onwards, the RFC style +is the default. If you want the old style back, you can use [legacy-rustfmt.toml](legacy-rustfmt.toml) +as your rustfmt.toml. + If you want latest and greatest, you should use the [libsyntax](https://github.com/rust-lang-nursery/rustfmt/tree/libsyntax) branch. It supports some newer Rust syntax which is missing from master and fixes some bugs. However, it links against libsyntax from the Rust compiler, so diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml new file mode 100644 index 00000000000..da1da764b2e --- /dev/null +++ b/legacy-rustfmt.toml @@ -0,0 +1,8 @@ +fn_args_layout = "Visual" +array_layout = "Visual" +control_style = "Legacy" +where_style = "Legacy" +generics_indent = "Visual" +fn_call_style = "Visual" +combine_control_expr = false +fn_args_paren_newline = true diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml deleted file mode 100644 index 893996bc7ff..00000000000 --- a/rfc-rustfmt.toml +++ /dev/null @@ -1,8 +0,0 @@ -fn_args_layout = "Block" -array_layout = "Block" -control_style = "Rfc" -where_style = "Rfc" -generics_indent = "Block" -fn_call_style = "Block" -combine_control_expr = true -fn_args_paren_newline = false diff --git a/src/config.rs b/src/config.rs index 082b731a002..55518ebad97 100644 --- a/src/config.rs +++ b/src/config.rs @@ -498,7 +498,7 @@ create_config! { newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; - control_style: Style, Style::Legacy, "Indent style for control flow statements"; + control_style: Style, Style::Rfc, "Indent style for control flow statements"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, "Brace style for control flow constructs"; impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; @@ -508,16 +508,16 @@ create_config! { fn_single_line: bool, false, "Put single-expression functions on a single line"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, "Location of return type in function declaration"; - fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline"; + fn_args_paren_newline: bool, false, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, "Argument density in functions"; - fn_args_layout: IndentStyle, IndentStyle::Visual, + fn_args_layout: IndentStyle, IndentStyle::Block, "Layout of function arguments and tuple structs"; - array_layout: IndentStyle, IndentStyle::Visual, "Indent on arrays"; + array_layout: IndentStyle, IndentStyle::Block, "Indent on arrays"; array_width: usize, 60, "Maximum width of an array literal before falling back to vertical formatting"; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - where_style: Style, Style::Legacy, "Overall strategy for where clauses"; + where_style: Style, Style::Rfc, "Overall strategy for where clauses"; // TODO: // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? @@ -526,11 +526,11 @@ create_config! { where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: IndentStyle, IndentStyle::Visual, "Indentation style of a where predicate"; - generics_indent: IndentStyle, IndentStyle::Visual, "Indentation of generics"; + generics_indent: IndentStyle, IndentStyle::Block, "Indentation of generics"; struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, "Multiline style on literal structs"; - fn_call_style: IndentStyle, IndentStyle::Visual, "Indentation for function calls, etc."; + fn_call_style: IndentStyle, IndentStyle::Block, "Indentation for function calls, etc."; report_todo: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, @@ -580,7 +580,7 @@ create_config! { "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns"; - combine_control_expr: bool, false, "Combine control expressions with funciton calls." + combine_control_expr: bool, true, "Combine control expressions with funciton calls." } #[cfg(test)] -- cgit 1.4.1-3-g733a5 From 1f512948a03cd24c2f8a056be0a2f53675802fd2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Jun 2017 15:58:58 +1200 Subject: Reformat source code using new defaults --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/bin/cargo-fmt.rs | 76 ++- src/bin/rustfmt.rs | 127 +++-- src/chains.rs | 282 +++++---- src/checkstyle.rs | 28 +- src/codemap.rs | 10 +- src/comment.rs | 225 +++++--- src/config.rs | 6 +- src/expr.rs | 1340 ++++++++++++++++++++++++------------------- src/file_lines.rs | 51 +- src/filemap.rs | 47 +- src/imports.rs | 146 +++-- src/issues.rs | 97 ++-- src/items.rs | 1547 ++++++++++++++++++++++++++++---------------------- src/lib.rs | 103 ++-- src/lists.rs | 234 ++++---- src/macros.rs | 60 +- src/missed_spans.rs | 78 +-- src/modules.rs | 40 +- src/patterns.rs | 194 ++++--- src/rustfmt_diff.rs | 16 +- src/string.rs | 13 +- src/summary.rs | 2 +- src/types.rs | 469 ++++++++------- src/utils.rs | 18 +- src/visitor.rs | 492 ++++++++-------- 27 files changed, 3241 insertions(+), 2464 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index bc456191d44..b7b906b5d40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt" -version = "0.8.5" +version = "0.9.0" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a79c974b31d..6bb598f0c0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt" -version = "0.9" +version = "0.9.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index c55c283c654..eeccae5c077 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -42,10 +42,12 @@ fn execute() -> i32 { opts.optflag("h", "help", "show this message"); opts.optflag("q", "quiet", "no output printed to stdout"); opts.optflag("v", "verbose", "use verbose output"); - opts.optmulti("p", - "package", - "specify package to format (only usable in workspaces)", - ""); + opts.optmulti( + "p", + "package", + "specify package to format (only usable in workspaces)", + "", + ); opts.optflag("", "all", "format all packages (only usable in workspaces)"); let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { @@ -90,9 +92,11 @@ fn execute() -> i32 { fn print_usage(opts: &Options, reason: &str) { let msg = format!("{}\nusage: cargo fmt [options]", reason); - println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ + println!( + "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ Arguments after `--` are passed to rustfmt.", - opts.usage(&msg)); + opts.usage(&msg) + ); } #[derive(Debug, Clone, Copy, PartialEq)] @@ -102,9 +106,10 @@ pub enum Verbosity { Quiet, } -fn format_crate(verbosity: Verbosity, - workspace_hitlist: WorkspaceHitlist) - -> Result { +fn format_crate( + verbosity: Verbosity, + workspace_hitlist: WorkspaceHitlist, +) -> Result { let targets = get_targets(workspace_hitlist)?; // Currently only bin and lib files get formatted @@ -112,8 +117,8 @@ fn format_crate(verbosity: Verbosity, .into_iter() .filter(|t| t.kind.should_format()) .inspect(|t| if verbosity == Verbosity::Verbose { - println!("[{:?}] {:?}", t.kind, t.path) - }) + println!("[{:?}] {:?}", t.kind, t.path) + }) .map(|t| t.path) .collect(); @@ -194,8 +199,10 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: return Ok(targets); } - return Err(std::io::Error::new(std::io::ErrorKind::NotFound, - str::from_utf8(&output.stderr).unwrap())); + return Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + str::from_utf8(&output.stderr).unwrap(), + )); } // This happens when cargo-fmt is not used inside a crate or // is used inside a workspace. @@ -221,18 +228,22 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: .unwrap() .into_iter() .filter(|member| if workspace_hitlist == WorkspaceHitlist::All { - true - } else { - let member_obj = member.as_object().unwrap(); - let member_name = member_obj.get("name").unwrap().as_str().unwrap(); - hitlist.take(&member_name.to_string()).is_some() - }) + true + } else { + let member_obj = member.as_object().unwrap(); + let member_name = member_obj.get("name").unwrap().as_str().unwrap(); + hitlist.take(&member_name.to_string()).is_some() + }) .collect(); if hitlist.len() != 0 { // Mimick cargo of only outputting one spec. - return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, - format!("package `{}` is not a member of the workspace", - hitlist.iter().next().unwrap()))); + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!( + "package `{}` is not a member of the workspace", + hitlist.iter().next().unwrap() + ), + )); } for member in members { let member_obj = member.as_object().unwrap(); @@ -243,8 +254,10 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: } return Ok(targets); } - Err(std::io::Error::new(std::io::ErrorKind::NotFound, - str::from_utf8(&output.stderr).unwrap())) + Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + str::from_utf8(&output.stderr).unwrap(), + )) } @@ -268,10 +281,11 @@ fn target_from_json(jtarget: &Value) -> Target { } } -fn format_files(files: &[PathBuf], - fmt_args: &[String], - verbosity: Verbosity) - -> Result { +fn format_files( + files: &[PathBuf], + fmt_args: &[String], + verbosity: Verbosity, +) -> Result { let stdout = if verbosity == Verbosity::Quiet { std::process::Stdio::null() } else { @@ -294,8 +308,10 @@ fn format_files(files: &[PathBuf], .spawn() .map_err(|e| match e.kind() { std::io::ErrorKind::NotFound => { - std::io::Error::new(std::io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your PATH.") + std::io::Error::new( + std::io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ) } _ => e, })?; diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 3a0a83f5fb1..1929285fdfe 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -74,7 +74,9 @@ impl CliOptions { if let Ok(write_mode) = WriteMode::from_str(write_mode) { options.write_mode = Some(write_mode); } else { - return Err(FmtError::from(format!("Invalid write-mode: {}", write_mode))); + return Err(FmtError::from( + format!("Invalid write-mode: {}", write_mode), + )); } } @@ -96,9 +98,10 @@ impl CliOptions { } /// read the given config file path recursively if present else read the project file path -fn match_cli_path_or_file(config_path: Option, - input_file: &Path) - -> FmtResult<(Config, Option)> { +fn match_cli_path_or_file( + config_path: Option, + input_file: &Path, +) -> FmtResult<(Config, Option)> { if let Some(config_file) = config_path { let toml = Config::from_toml_path(config_file.as_ref())?; @@ -112,32 +115,44 @@ fn make_opts() -> Options { opts.optflag("h", "help", "show this message"); opts.optflag("V", "version", "show version information"); opts.optflag("v", "verbose", "print verbose output"); - opts.optopt("", - "write-mode", - "mode to write in (not usable when piping from stdin)", - "[replace|overwrite|display|diff|coverage|checkstyle]"); + opts.optopt( + "", + "write-mode", + "mode to write in (not usable when piping from stdin)", + "[replace|overwrite|display|diff|coverage|checkstyle]", + ); opts.optflag("", "skip-children", "don't reformat child modules"); - opts.optflag("", - "config-help", - "show details of rustfmt configuration options"); - opts.optopt("", - "dump-default-config", - "Dumps the default configuration to a file and exits.", - "PATH"); - opts.optopt("", - "dump-minimal-config", - "Dumps configuration options that were checked during formatting to a file.", - "PATH"); - opts.optopt("", - "config-path", - "Recursively searches the given path for the rustfmt.toml config file. If not \ + opts.optflag( + "", + "config-help", + "show details of rustfmt configuration options", + ); + opts.optopt( + "", + "dump-default-config", + "Dumps the default configuration to a file and exits.", + "PATH", + ); + opts.optopt( + "", + "dump-minimal-config", + "Dumps configuration options that were checked during formatting to a file.", + "PATH", + ); + opts.optopt( + "", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ found reverts to the input file path", - "[Path for the configuration file]"); - opts.optopt("", - "file-lines", - "Format specified line ranges. See README for more detail on the JSON format.", - "JSON"); + "[Path for the configuration file]", + ); + opts.optopt( + "", + "file-lines", + "Format specified line ranges. See README for more detail on the JSON format.", + "JSON", + ); opts } @@ -167,8 +182,8 @@ fn execute(opts: &Options) -> FmtResult { } Operation::Stdin { input, config_path } => { // try to read config from local directory - let (mut config, _) = match_cli_path_or_file(config_path, - &env::current_dir().unwrap())?; + let (mut config, _) = + match_cli_path_or_file(config_path, &env::current_dir().unwrap())?; // write_mode is always Plain for Stdin. config.set().write_mode(WriteMode::Plain); @@ -225,9 +240,11 @@ fn execute(opts: &Options) -> FmtResult { Config::from_resolved_toml_path(file.parent().unwrap())?; if options.verbose { if let Some(path) = path_tmp.as_ref() { - println!("Using rustfmt config file {} for {}", - path.display(), - file.display()); + println!( + "Using rustfmt config file {} for {}", + path.display(), + file.display() + ); } } config = config_tmp; @@ -288,16 +305,20 @@ fn main() { } fn print_usage(opts: &Options, reason: &str) { - let reason = format!("{}\n\nusage: {} [options] ...", - reason, - env::args_os().next().unwrap().to_string_lossy()); + let reason = format!( + "{}\n\nusage: {} [options] ...", + reason, + env::args_os().next().unwrap().to_string_lossy() + ); println!("{}", opts.usage(&reason)); } fn print_version() { - println!("{}-nightly{}", - env!("CARGO_PKG_VERSION"), - include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))) + println!( + "{}-nightly{}", + env!("CARGO_PKG_VERSION"), + include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) + ) } fn determine_operation(matches: &Matches) -> FmtResult { @@ -318,8 +339,10 @@ fn determine_operation(matches: &Matches) -> FmtResult { } let config_path_not_found = |path: &str| -> FmtResult { - Err(FmtError::from(format!("Error: unable to find a config file for the given path: `{}`", - path))) + Err(FmtError::from(format!( + "Error: unable to find a config file for the given path: `{}`", + path + ))) }; // Read the config_path and convert to parent dir if a file is provided. @@ -346,25 +369,25 @@ fn determine_operation(matches: &Matches) -> FmtResult { io::stdin().read_to_string(&mut buffer)?; return Ok(Operation::Stdin { - input: buffer, - config_path: config_path, - }); + input: buffer, + config_path: config_path, + }); } let files: Vec<_> = matches .free .iter() .map(|s| { - let p = PathBuf::from(s); - // we will do comparison later, so here tries to canonicalize first - // to get the expected behavior. - p.canonicalize().unwrap_or(p) - }) + let p = PathBuf::from(s); + // we will do comparison later, so here tries to canonicalize first + // to get the expected behavior. + p.canonicalize().unwrap_or(p) + }) .collect(); Ok(Operation::Format { - files: files, - config_path: config_path, - minimal_config_path: minimal_config_path, - }) + files: files, + config_path: config_path, + minimal_config_path: minimal_config_path, + }) } diff --git a/src/chains.rs b/src/chains.rs index b84a7e469f2..eba79505e20 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -101,9 +101,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let trailing_try_num = subexpr_list .iter() .take_while(|e| match e.node { - ast::ExprKind::Try(..) => true, - _ => false, - }) + ast::ExprKind::Try(..) => true, + _ => false, + }) .count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. @@ -128,7 +128,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) }; - (nested_shape, context.config.chain_indent() == IndentStyle::Visual || is_small_parent) + ( + nested_shape, + context.config.chain_indent() == IndentStyle::Visual || is_small_parent, + ) } else if is_block_expr(context, &parent, &parent_rewrite) { match context.config.chain_indent() { // Try to put the first child on the same line with parent's last line @@ -155,26 +158,33 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { other_child_shape }; - debug!("child_shapes {:?} {:?}", - first_child_shape, - other_child_shape); - - let child_shape_iter = - Some(first_child_shape) - .into_iter() - .chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1)); + debug!( + "child_shapes {:?} {:?}", + first_child_shape, + other_child_shape + ); + + let child_shape_iter = Some(first_child_shape).into_iter().chain( + ::std::iter::repeat( + other_child_shape, + ).take( + subexpr_list.len() - 1, + ), + ); let iter = subexpr_list.iter().rev().zip(child_shape_iter); - let mut rewrites = try_opt!(iter.map(|(e, shape)| { - rewrite_chain_subexpr(e, total_span, context, shape) - }).collect::>>()); + let mut rewrites = try_opt!( + iter.map(|(e, shape)| { + rewrite_chain_subexpr(e, total_span, context, shape) + }).collect::>>() + ); // Total of all items excluding the last. let last_non_try_index = rewrites.len() - (1 + trailing_try_num); - let almost_total = rewrites[..last_non_try_index] - .iter() - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); + let almost_total = rewrites[..last_non_try_index].iter().fold(0, |a, b| { + a + first_line_width(b) + }) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + - parent_rewrite.len(); + parent_rewrite.len(); let one_line_budget = min(shape.width, context.config.chain_one_line_max()); let veto_single_line = if one_line_len > one_line_budget { @@ -206,12 +216,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if fits_single_line { fits_single_line = match expr.node { ref e @ ast::ExprKind::MethodCall(..) => { - if rewrite_method_call_with_overflow(e, - &mut last[0], - almost_total, - total_span, - context, - shape) { + if rewrite_method_call_with_overflow( + e, + &mut last[0], + almost_total, + total_span, + context, + shape, + ) + { // If the first line of the last method does not fit into a single line // after the others, allow new lines. almost_total + first_line_width(&last[0]) < context.config.max_width() @@ -233,13 +246,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - width: one_line_budget, ..parent_shape }; - fits_single_line = rewrite_last_child_with_overflow(context, - &subexpr_list[trailing_try_num], - overflow_shape, - total_span, - almost_total, - one_line_budget, - &mut last[0]); + fits_single_line = rewrite_last_child_with_overflow( + context, + &subexpr_list[trailing_try_num], + overflow_shape, + total_span, + almost_total, + one_line_budget, + &mut last[0], + ); } } @@ -254,68 +269,83 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - format!("\n{}", nested_shape.indent.to_string(context.config)) }; - let first_connector = choose_first_connector(context, - &parent_rewrite, - &rewrites[0], - &connector, - &subexpr_list, - extend); + let first_connector = choose_first_connector( + context, + &parent_rewrite, + &rewrites[0], + &connector, + &subexpr_list, + extend, + ); if is_small_parent && rewrites.len() > 1 { - let second_connector = choose_first_connector(context, - &rewrites[0], - &rewrites[1], - &connector, - &subexpr_list[0..subexpr_list.len() - 1], - false); - wrap_str(format!("{}{}{}{}{}", - parent_rewrite, - first_connector, - rewrites[0], - second_connector, - join_rewrites(&rewrites[1..], - &subexpr_list[0..subexpr_list.len() - 1], - &connector)), - context.config.max_width(), - shape) + let second_connector = choose_first_connector( + context, + &rewrites[0], + &rewrites[1], + &connector, + &subexpr_list[0..subexpr_list.len() - 1], + false, + ); + wrap_str( + format!( + "{}{}{}{}{}", + parent_rewrite, + first_connector, + rewrites[0], + second_connector, + join_rewrites( + &rewrites[1..], + &subexpr_list[0..subexpr_list.len() - 1], + &connector, + ) + ), + context.config.max_width(), + shape, + ) } else { - wrap_str(format!("{}{}{}", - parent_rewrite, - first_connector, - join_rewrites(&rewrites, &subexpr_list, &connector)), - context.config.max_width(), - shape) + wrap_str( + format!( + "{}{}{}", + parent_rewrite, + first_connector, + join_rewrites(&rewrites, &subexpr_list, &connector) + ), + context.config.max_width(), + shape, + ) } } fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { context.config.chain_indent() == IndentStyle::Block && - parent_str.lines().last().map_or(false, |s| { - s.trim() - .chars() - .all(|c| c == ')' || c == ']' || c == '}' || c == '?') - }) + parent_str.lines().last().map_or(false, |s| { + s.trim().chars().all(|c| { + c == ')' || c == ']' || c == '}' || c == '?' + }) + }) } // True if the chain is only `?`s. fn chain_only_try(exprs: &[ast::Expr]) -> bool { exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - }) + true + } else { + false + }) } // Try to rewrite and replace the last non-try child. Return `true` if // replacing succeeds. -fn rewrite_last_child_with_overflow(context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, - span: Span, - almost_total: usize, - one_line_budget: usize, - last_child: &mut String) - -> bool { +fn rewrite_last_child_with_overflow( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, + span: Span, + almost_total: usize, + one_line_budget: usize, + last_child: &mut String, +) -> bool { if let Some(shape) = shape.shrink_left(almost_total) { if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) { if almost_total + first_line_width(rw) <= one_line_budget { @@ -327,15 +357,18 @@ fn rewrite_last_child_with_overflow(context: &RewriteContext, false } -pub fn rewrite_try(expr: &ast::Expr, - try_count: usize, - context: &RewriteContext, - shape: Shape) - -> Option { +pub fn rewrite_try( + expr: &ast::Expr, + try_count: usize, + context: &RewriteContext, + shape: Shape, +) -> Option { let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count)))); - Some(format!("{}{}", - sub_expr, - iter::repeat("?").take(try_count).collect::())) + Some(format!( + "{}{}", + sub_expr, + iter::repeat("?").take(try_count).collect::() + )) } fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { @@ -398,24 +431,27 @@ fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { } } -fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind, - last: &mut String, - almost_total: usize, - total_span: Span, - context: &RewriteContext, - shape: Shape) - -> bool { +fn rewrite_method_call_with_overflow( + expr_kind: &ast::ExprKind, + last: &mut String, + almost_total: usize, + total_span: Span, + context: &RewriteContext, + shape: Shape, +) -> bool { if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { let shape = match shape.shrink_left(almost_total) { Some(b) => b, None => return false, }; - let mut last_rewrite = rewrite_method_call(method_name.node, - types, - expressions, - total_span, - context, - shape); + let mut last_rewrite = rewrite_method_call( + method_name.node, + types, + expressions, + total_span, + context, + shape, + ); if let Some(ref mut s) = last_rewrite { ::std::mem::swap(s, last); @@ -457,11 +493,12 @@ fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite // `.c`. -fn rewrite_chain_subexpr(expr: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_chain_subexpr( + expr: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width { Some(expr_str) } else { @@ -500,20 +537,23 @@ fn is_try(expr: &ast::Expr) -> bool { } } -fn choose_first_connector<'a>(context: &RewriteContext, - parent_str: &str, - first_child_str: &str, - connector: &'a str, - subexpr_list: &[ast::Expr], - extend: bool) - -> &'a str { +fn choose_first_connector<'a>( + context: &RewriteContext, + parent_str: &str, + first_child_str: &str, + connector: &'a str, + subexpr_list: &[ast::Expr], + extend: bool, +) -> &'a str { if subexpr_list.is_empty() { "" } else if extend || subexpr_list.last().map_or(false, is_try) || - is_extendable_parent(context, parent_str) { + is_extendable_parent(context, parent_str) + { // 1 = ";", being conservative here. if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <= - context.config.max_width() { + context.config.max_width() + { "" } else { connector @@ -523,18 +563,18 @@ fn choose_first_connector<'a>(context: &RewriteContext, } } -fn rewrite_method_call(method_name: ast::Ident, - types: &[ptr::P], - args: &[ptr::P], - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_method_call( + method_name: ast::Ident, + types: &[ptr::P], + args: &[ptr::P], + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { - let type_list: Vec<_> = - try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 69c89a9c5fb..90ba4561024 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -13,7 +13,8 @@ use config::WriteMode; pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> - where T: Write +where + T: Write, { if mode == WriteMode::Checkstyle { let mut xml_heading = String::new(); @@ -26,7 +27,8 @@ pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> } pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> - where T: Write +where + T: Write, { if mode == WriteMode::Checkstyle { let mut xml_tail = String::new(); @@ -36,11 +38,13 @@ pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> Ok(()) } -pub fn output_checkstyle_file(mut writer: T, - filename: &str, - diff: Vec) - -> Result<(), io::Error> - where T: Write +pub fn output_checkstyle_file( + mut writer: T, + filename: &str, + diff: Vec, +) -> Result<(), io::Error> +where + T: Write, { write!(writer, "", filename)?; for mismatch in diff { @@ -48,11 +52,13 @@ pub fn output_checkstyle_file(mut writer: T, // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. if let DiffLine::Expected(ref str) = line { let message = xml_escape_str(str); - write!(writer, - "", - mismatch.line_number, - message)?; + mismatch.line_number, + message + )?; } } } diff --git a/src/codemap.rs b/src/codemap.rs index d04169c936e..065c39f67c1 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -77,10 +77,12 @@ impl LineRangeUtils for CodeMap { let lo = self.lookup_char_pos(span.lo); let hi = self.lookup_char_pos(span.hi); - assert!(lo.file.name == hi.file.name, - "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, - hi); + assert!( + lo.file.name == hi.file.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, + hi + ); LineRange { file: lo.file.clone(), diff --git a/src/comment.rs b/src/comment.rs index ac4ec17bbbb..d31ba5f9f2d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -45,9 +45,9 @@ pub enum CommentStyle<'a> { fn custom_opener(s: &str) -> &str { s.lines().next().map_or("", |first_line| { - first_line - .find(' ') - .map_or(first_line, |space_index| &first_line[0..space_index + 1]) + first_line.find(' ').map_or(first_line, |space_index| { + &first_line[0..space_index + 1] + }) }) } @@ -98,14 +98,14 @@ impl<'a> CommentStyle<'a> { CommentStyle::TripleSlash | CommentStyle::Doc => { line.trim_left().starts_with(self.line_start().trim_left()) || - comment_style(line, normalize_comments) == *self + comment_style(line, normalize_comments) == *self } CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { line.trim_left().starts_with(self.closer().trim_left()) || - line.trim_left().starts_with(self.line_start().trim_left()) || - comment_style(line, normalize_comments) == *self + line.trim_left().starts_with(self.line_start().trim_left()) || + comment_style(line, normalize_comments) == *self } CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), } @@ -130,7 +130,8 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { CommentStyle::DoubleSlash } } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) || - (orig.starts_with("/**") && !orig.starts_with("/**/")) { + (orig.starts_with("/**") && !orig.starts_with("/**/")) + { CommentStyle::TripleSlash } else if orig.starts_with("//!") || orig.starts_with("/*!") { CommentStyle::Doc @@ -141,17 +142,20 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { } } -pub fn rewrite_comment(orig: &str, - block_style: bool, - shape: Shape, - config: &Config) - -> Option { +pub fn rewrite_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, +) -> Option { // If there are lines without a starting sigil, we won't format them correctly // so in that case we won't even re-align (if !config.normalize_comments()) and // we should stop now. let num_bare_lines = orig.lines() .map(|line| line.trim()) - .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) + .filter(|l| { + !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*")) + }) .count(); if num_bare_lines > 0 && !config.normalize_comments() { return Some(orig.to_owned()); @@ -163,11 +167,12 @@ pub fn rewrite_comment(orig: &str, identify_comment(orig, block_style, shape, config) } -fn identify_comment(orig: &str, - block_style: bool, - shape: Shape, - config: &Config) - -> Option { +fn identify_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, +) -> Option { let style = comment_style(orig, false); let first_group = orig.lines() .take_while(|l| style.line_with_same_comment_style(l, false)) @@ -178,28 +183,34 @@ fn identify_comment(orig: &str, .collect::>() .join("\n"); - let first_group_str = - try_opt!(rewrite_comment_inner(&first_group, block_style, style, shape, config)); + let first_group_str = try_opt!(rewrite_comment_inner( + &first_group, + block_style, + style, + shape, + config, + )); if rest.is_empty() { Some(first_group_str) } else { identify_comment(&rest, block_style, shape, config).map(|rest_str| { - format!("{}\n{}{}", - first_group_str, - shape - .indent - .to_string(config), - rest_str) - }) - } -} - -fn rewrite_comment_inner(orig: &str, - block_style: bool, - style: CommentStyle, - shape: Shape, - config: &Config) - -> Option { + format!( + "{}\n{}{}", + first_group_str, + shape.indent.to_string(config), + rest_str + ) + }) + } +} + +fn rewrite_comment_inner( + orig: &str, + block_style: bool, + style: CommentStyle, + shape: Shape, + config: &Config, +) -> Option { let (opener, closer, line_start) = if block_style { CommentStyle::SingleBullet.to_str_tuplet() } else { @@ -235,10 +246,10 @@ fn rewrite_comment_inner(orig: &str, }) .map(|s| left_trim_comment_line(s, &style)) .map(|line| if orig.starts_with("/*") && line_breaks == 0 { - line.trim_left() - } else { - line - }); + line.trim_left() + } else { + line + }); let mut result = opener.to_owned(); for line in lines { @@ -299,7 +310,8 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< /// Does not trim all whitespace. fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || - line.starts_with("/** ") { + line.starts_with("/** ") + { &line[4..] } else if let &CommentStyle::Custom(opener) = style { if line.starts_with(opener) { @@ -307,13 +319,15 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { } else { &line[opener.trim_right().len()..] } - } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || - line.starts_with("///") || - line.starts_with("** ") || line.starts_with("/*!") || - (line.starts_with("/**") && !line.starts_with("/**/")) { + } else if line.starts_with("/* ") || line.starts_with("// ") || + line.starts_with("//!") || line.starts_with("///") || + line.starts_with("** ") || line.starts_with("/*!") || + (line.starts_with("/**") && !line.starts_with("/**/")) + { &line[3..] } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || - line.starts_with("**") { + line.starts_with("**") + { &line[2..] } else if line.starts_with('*') { &line[1..] @@ -379,8 +393,9 @@ pub fn contains_comment(text: &str) -> bool { } struct CharClasses - where T: Iterator, - T::Item: RichChar +where + T: Iterator, + T::Item: RichChar, { base: iter::Peekable, status: CharClassesStatus, @@ -462,8 +477,9 @@ impl FullCodeCharKind { } impl CharClasses - where T: Iterator, - T::Item: RichChar +where + T: Iterator, + T::Item: RichChar, { fn new(base: T) -> CharClasses { CharClasses { @@ -474,8 +490,9 @@ impl CharClasses } impl Iterator for CharClasses - where T: Iterator, - T::Item: RichChar +where + T: Iterator, + T::Item: RichChar, { type Item = (FullCodeCharKind, T::Item); @@ -603,13 +620,15 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx], None => &self.slice[start_idx..], }; - Some((if kind.is_comment() { - CodeCharKind::Comment - } else { - CodeCharKind::Normal - }, - start_idx, - slice)) + Some(( + if kind.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + }, + start_idx, + slice, + )) } } @@ -650,8 +669,8 @@ impl<'a> Iterator for CommentCodeSlices<'a> { for (kind, (i, c)) in &mut iter { let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal && - &subslice[..2] == "//" && - [' ', '\t'].contains(&c); + &subslice[..2] == "//" && + [' ', '\t'].contains(&c); if is_comment_connector && first_whitespace.is_none() { first_whitespace = Some(i); @@ -683,7 +702,11 @@ impl<'a> Iterator for CommentCodeSlices<'a> { CodeCharKind::Comment => CodeCharKind::Normal, CodeCharKind::Normal => CodeCharKind::Comment, }; - let res = (kind, self.last_slice_end, &self.slice[self.last_slice_end..sub_slice_end]); + let res = ( + kind, + self.last_slice_end, + &self.slice[self.last_slice_end..sub_slice_end], + ); self.last_slice_end = sub_slice_end; self.last_slice_kind = kind; @@ -693,11 +716,12 @@ impl<'a> Iterator for CommentCodeSlices<'a> { /// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text /// (if it fits in the width/offset, else return None), else return `new` -pub fn recover_comment_removed(new: String, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +pub fn recover_comment_removed( + new: String, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { let snippet = context.snippet(span); if changed_comment_content(&snippet, &new) { // We missed some comments @@ -723,12 +747,14 @@ fn changed_comment_content(orig: &str, new: &str) -> bool { .flat_map(|(_, _, s)| CommentReducer::new(s)) }; let res = code_comment_content(orig).ne(code_comment_content(new)); - debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", - res, - orig, - new, - code_comment_content(orig).collect::(), - code_comment_content(new).collect::()); + debug!( + "comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", + res, + orig, + new, + code_comment_content(orig).collect::(), + code_comment_content(new).collect::() + ); res } @@ -787,11 +813,14 @@ fn remove_comment_header(comment: &str) -> &str { } else if comment.starts_with("//") { &comment[2..] } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) || - comment.starts_with("/*!") { + comment.starts_with("/*!") + { &comment[3..comment.len() - 2] } else { - assert!(comment.starts_with("/*"), - format!("string '{}' is not a comment", comment)); + assert!( + comment.starts_with("/*"), + format!("string '{}' is not a comment", comment) + ); &comment[2..comment.len() - 2] } } @@ -819,8 +848,10 @@ mod test { let mut iter = CommentCodeSlices::new(input); assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); - assert_eq!((CodeCharKind::Comment, 8, "/* test */"), - iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 8, "/* test */"), + iter.next().unwrap() + ); assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap()); assert_eq!(None, iter.next()); } @@ -831,10 +862,14 @@ mod test { let mut iter = CommentCodeSlices::new(input); assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap()); - assert_eq!((CodeCharKind::Comment, 0, "// comment\n"), - iter.next().unwrap()); - assert_eq!((CodeCharKind::Normal, 11, " test();"), - iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 0, "// comment\n"), + iter.next().unwrap() + ); + assert_eq!( + (CodeCharKind::Normal, 11, " test();"), + iter.next().unwrap() + ); assert_eq!(None, iter.next()); } @@ -844,8 +879,10 @@ mod test { let mut iter = CommentCodeSlices::new(input); assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap()); - assert_eq!((CodeCharKind::Comment, 2, "// comment\n // comment2\n"), - iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 2, "// comment\n // comment2\n"), + iter.next().unwrap() + ); assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap()); assert_eq!(None, iter.next()); } @@ -896,17 +933,19 @@ mod test { fn uncommented(text: &str) -> String { CharClasses::new(text.chars()) .filter_map(|(s, c)| match s { - FullCodeCharKind::Normal => Some(c), - _ => None, - }) + FullCodeCharKind::Normal => Some(c), + _ => None, + }) .collect() } #[test] fn test_uncommented() { assert_eq!(&uncommented("abc/*...*/"), "abc"); - assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), - "..ac\n"); + assert_eq!( + &uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), + "..ac\n" + ); assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); } @@ -927,9 +966,11 @@ mod test { check("/*/ */test", "test", Some(6)); check("//test\ntest", "test", Some(7)); check("/* comment only */", "whatever", None); - check("/* comment */ some text /* more commentary */ result", - "result", - Some(46)); + check( + "/* comment */ some text /* more commentary */ result", + "result", + Some(46), + ); check("sup // sup", "p", Some(2)); check("sup", "x", None); check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); diff --git a/src/config.rs b/src/config.rs index 55518ebad97..931b99bb5da 100644 --- a/src/config.rs +++ b/src/config.rs @@ -605,7 +605,9 @@ mod test { let used_options = config.used_options(); let toml = used_options.to_toml().unwrap(); - assert_eq!(toml, - format!("verbose = {}\nskip_children = {}\n", verbose, skip_children)); + assert_eq!( + toml, + format!("verbose = {}\nskip_children = {}\n", verbose, skip_children) + ); } } diff --git a/src/expr.rs b/src/expr.rs index ef47d0fd6c6..24432fb1dff 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -47,21 +47,24 @@ enum ExprType { SubExpression, } -fn format_expr(expr: &ast::Expr, - expr_type: ExprType, - context: &RewriteContext, - shape: Shape) - -> Option { +fn format_expr( + expr: &ast::Expr, + expr_type: ExprType, + context: &RewriteContext, + shape: Shape, +) -> Option { if contains_skip(&*expr.attrs) { return Some(context.snippet(expr.span)); } let attr_rw = (&*expr.attrs).rewrite(context, shape); let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => { - rewrite_array(expr_vec.iter().map(|e| &**e), - mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), - context, - shape) + rewrite_array( + expr_vec.iter().map(|e| &**e), + mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), + context, + shape, + ) } ast::ExprKind::Lit(ref l) => { match l.node { @@ -69,9 +72,11 @@ fn format_expr(expr: &ast::Expr, rewrite_string_lit(context, l.span, shape) } _ => { - wrap_str(context.snippet(expr.span), - context.config.max_width(), - shape) + wrap_str( + context.snippet(expr.span), + context.config.max_width(), + shape, + ) } } } @@ -82,22 +87,26 @@ fn format_expr(expr: &ast::Expr, ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator - rewrite_pair(&**lhs, - &**rhs, - "", - &format!(" {} ", context.snippet(op.span)), - "", - context, - shape) + rewrite_pair( + &**lhs, + &**rhs, + "", + &format!(" {} ", context.snippet(op.span)), + "", + context, + shape, + ) } ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref path, ref fields, ref base) => { - rewrite_struct_lit(context, - path, - fields, - base.as_ref().map(|e| &**e), - expr.span, - shape) + rewrite_struct_lit( + context, + path, + fields, + base.as_ref().map(|e| &**e), + expr.span, + shape, + ) } ast::ExprKind::Tup(ref items) => rewrite_tuple(context, items, expr.span, shape), ast::ExprKind::While(ref cond, ref block, label) => { @@ -114,24 +123,26 @@ fn format_expr(expr: &ast::Expr, } ast::ExprKind::Block(ref block) => block.rewrite(context, shape), ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { - ControlFlow::new_if(cond, - None, - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span) - .rewrite(context, shape) + ControlFlow::new_if( + cond, + None, + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + ).rewrite(context, shape) } ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { - ControlFlow::new_if(cond, - Some(pat), - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span) - .rewrite(context, shape) + ControlFlow::new_if( + cond, + Some(pat), + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + ).rewrite(context, shape) } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, shape, expr.span) @@ -150,9 +161,11 @@ fn format_expr(expr: &ast::Expr, Some(ident) => format!(" {}", ident.node), None => String::new(), }; - wrap_str(format!("continue{}", id_str), - context.config.max_width(), - shape) + wrap_str( + format!("continue{}", id_str), + context.config.max_width(), + shape, + ) } ast::ExprKind::Break(ref opt_ident, ref opt_expr) => { let id_str = match *opt_ident { @@ -163,9 +176,11 @@ fn format_expr(expr: &ast::Expr, if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) } else { - wrap_str(format!("break{}", id_str), - context.config.max_width(), - shape) + wrap_str( + format!("break{}", id_str), + context.config.max_width(), + shape, + ) } } ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { @@ -179,9 +194,11 @@ fn format_expr(expr: &ast::Expr, // Failure to rewrite a marco should not imply failure to // rewrite the expression. rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str(context.snippet(expr.span), - context.config.max_width(), - shape) + wrap_str( + context.snippet(expr.span), + context.config.max_width(), + shape, + ) }) } ast::ExprKind::Ret(None) => { @@ -249,9 +266,11 @@ fn format_expr(expr: &ast::Expr, // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - wrap_str(context.snippet(expr.span), - context.config.max_width(), - shape) + wrap_str( + context.snippet(expr.span), + context.config.max_width(), + shape, + ) } ast::ExprKind::Catch(ref block) => { if let rewrite @ Some(_) = try_one_line_block(context, shape, "do catch ", block) { @@ -259,28 +278,33 @@ fn format_expr(expr: &ast::Expr, } // 9 = `do catch ` let budget = shape.width.checked_sub(9).unwrap_or(0); - Some(format!("{}{}", - "do catch ", - try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))))) + Some(format!( + "{}{}", + "do catch ", + try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))) + )) } }; match (attr_rw, expr_rw) { (Some(attr_str), Some(expr_str)) => { let space = if attr_str.is_empty() { "" } else { " " }; - recover_comment_removed(format!("{}{}{}", attr_str, space, expr_str), - expr.span, - context, - shape) + recover_comment_removed( + format!("{}{}{}", attr_str, space, expr_str), + expr.span, + context, + shape, + ) } _ => None, } } -fn try_one_line_block(context: &RewriteContext, - shape: Shape, - prefix: &str, - block: &ast::Block) - -> Option { +fn try_one_line_block( + context: &RewriteContext, + shape: Shape, + prefix: &str, + block: &ast::Block, +) -> Option { if is_simple_block(block, context.codemap) { let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent); let expr_str = try_opt!(block.stmts[0].rewrite(context, expr_shape)); @@ -292,16 +316,18 @@ fn try_one_line_block(context: &RewriteContext, None } -pub fn rewrite_pair(lhs: &LHS, - rhs: &RHS, - prefix: &str, - infix: &str, - suffix: &str, - context: &RewriteContext, - shape: Shape) - -> Option - where LHS: Rewrite, - RHS: Rewrite +pub fn rewrite_pair( + lhs: &LHS, + rhs: &RHS, + prefix: &str, + infix: &str, + suffix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option +where + LHS: Rewrite, + RHS: Rewrite, { // Get "full width" rhs and see if it fits on the current line. This // usually works fairly well since it tends to place operands of @@ -374,21 +400,25 @@ pub fn rewrite_pair(lhs: &LHS, Style::Rfc => try_opt!(shape.sub_width(prefix.len() + infix.len())), }; let lhs_result = try_opt!(lhs.rewrite(context, lhs_shape)); - Some(format!("{}{}{}\n{}{}{}", - prefix, - lhs_result, - infix, - rhs_shape.indent.to_string(context.config), - rhs_result, - suffix)) + Some(format!( + "{}{}{}\n{}{}{}", + prefix, + lhs_result, + infix, + rhs_shape.indent.to_string(context.config), + rhs_result, + suffix + )) } -pub fn rewrite_array<'a, I>(expr_iter: I, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option - where I: Iterator +pub fn rewrite_array<'a, I>( + expr_iter: I, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: Iterator, { let bracket_size = if context.config.spaces_within_square_brackets() { 2 // "[ " @@ -399,21 +429,22 @@ pub fn rewrite_array<'a, I>(expr_iter: I, let nested_shape = match context.config.array_layout() { IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), IndentStyle::Visual => { - try_opt!(shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2)) + try_opt!(shape.visual_indent(bracket_size).sub_width( + bracket_size * 2, + )) } }; - let items = itemize_list(context.codemap, - expr_iter, - "]", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(context, nested_shape), - span.lo, - span.hi) - .collect::>(); + let items = itemize_list( + context.codemap, + expr_iter, + "]", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(context, nested_shape), + span.lo, + span.hi, + ).collect::>(); if items.is_empty() { if context.config.spaces_within_square_brackets() { @@ -423,11 +454,12 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } } - let has_long_item = try_opt!(items - .iter() - .map(|li| li.item.as_ref().map(|s| s.len() > 10)) - .fold(Some(false), - |acc, x| acc.and_then(|y| x.map(|x| x || y)))); + let has_long_item = try_opt!( + items + .iter() + .map(|li| li.item.as_ref().map(|s| s.len() > 10)) + .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y))) + ); let tactic = match context.config.array_layout() { IndentStyle::Block => { @@ -443,11 +475,11 @@ pub fn rewrite_array<'a, I>(expr_iter: I, } IndentStyle::Visual => { if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic(&items, - ListTactic::LimitedHorizontalVertical(context - .config - .array_width()), - nested_shape.width) + definitive_tactic( + &items, + ListTactic::LimitedHorizontalVertical(context.config.array_width()), + nested_shape.width, + ) } else { DefinitiveListTactic::Mixed } @@ -465,17 +497,20 @@ pub fn rewrite_array<'a, I>(expr_iter: I, let list_str = try_opt!(write_list(&items, &fmt)); let result = if context.config.array_layout() == IndentStyle::Visual || - tactic != DefinitiveListTactic::Vertical { + tactic != DefinitiveListTactic::Vertical + { if context.config.spaces_within_square_brackets() && list_str.len() > 0 { format!("[ {} ]", list_str) } else { format!("[{}]", list_str) } } else { - format!("[\n{}{},\n{}]", - nested_shape.indent.to_string(context.config), - list_str, - shape.block().indent.to_string(context.config)) + format!( + "[\n{}{},\n{}]", + nested_shape.indent.to_string(context.config), + list_str, + shape.block().indent.to_string(context.config) + ) }; Some(result) @@ -490,13 +525,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I, // * if the first expression in the body ends with a block (i.e., is a // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. -fn rewrite_closure(capture: ast::CaptureBy, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_closure( + capture: ast::CaptureBy, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { let mover = if capture == ast::CaptureBy::Value { "move " } else { @@ -511,14 +547,16 @@ fn rewrite_closure(capture: ast::CaptureBy, let arg_shape = try_opt!(nested_shape.shrink_left(1)).visual_indent(0); let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape)); - let arg_items = itemize_list(context.codemap, - fn_decl.inputs.iter(), - "|", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(arg), - |arg| arg.rewrite(context, arg_shape), - context.codemap.span_after(span, "|"), - body.span.lo); + let arg_items = itemize_list( + context.codemap, + fn_decl.inputs.iter(), + "|", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(arg), + |arg| arg.rewrite(context, arg_shape), + context.codemap.span_after(span, "|"), + body.span.lo, + ); let item_vec = arg_items.collect::>(); // 1 = space between arguments and return type. let horizontal_budget = nested_shape @@ -564,9 +602,9 @@ fn rewrite_closure(capture: ast::CaptureBy, // Figure out if the block is necessary. let needs_block = block.rules != ast::BlockCheckMode::Default || - block.stmts.len() > 1 || context.inside_macro || - block_contains_comment(block, context.codemap) || - prefix.contains('\n'); + block.stmts.len() > 1 || context.inside_macro || + block_contains_comment(block, context.codemap) || + prefix.contains('\n'); if ret_str.is_empty() && !needs_block { // lock.stmts.len() == 1 @@ -600,22 +638,25 @@ fn rewrite_closure(capture: ast::CaptureBy, // The closure originally had a non-block expression, but we can't fit on // one line, so we'll insert a block. let block = ast::Block { - stmts: vec![ast::Stmt { - id: ast::NodeId::new(0), - node: ast::StmtKind::Expr(ptr::P(body.clone())), - span: body.span, - }], + stmts: vec![ + ast::Stmt { + id: ast::NodeId::new(0), + node: ast::StmtKind::Expr(ptr::P(body.clone())), + span: body.span, + }, + ], id: ast::NodeId::new(0), rules: ast::BlockCheckMode::Default, span: body.span, }; return rewrite_closure_block(&block, prefix, context, body_shape); - fn rewrite_closure_expr(expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape) - -> Option { + fn rewrite_closure_expr( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, + ) -> Option { let mut rewrite = expr.rewrite(context, shape); if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { rewrite = and_one_line(rewrite); @@ -623,18 +664,20 @@ fn rewrite_closure(capture: ast::CaptureBy, rewrite.map(|rw| format!("{} {}", prefix, rw)) } - fn rewrite_closure_block(block: &ast::Block, - prefix: String, - context: &RewriteContext, - shape: Shape) - -> Option { + fn rewrite_closure_block( + block: &ast::Block, + prefix: String, + context: &RewriteContext, + shape: Shape, + ) -> Option { // Start with visual indent, then fall back to block indent if the // closure is large. let block_threshold = context.config.closure_block_indent_threshold(); if block_threshold >= 0 { if let Some(block_str) = block.rewrite(&context, shape) { if block_str.matches('\n').count() <= block_threshold as usize && - !need_block_indent(&block_str, shape) { + !need_block_indent(&block_str, shape) + { if let Some(block_str) = block_str.rewrite(context, shape) { return Some(format!("{} {}", prefix, block_str)); } @@ -656,13 +699,14 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); - block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && - (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == - block_str.len() - 2) { - "{}".to_owned() - } else { - block_str.to_owned() - }) + block_str.map(|block_str| if block_str.starts_with('{') && + budget >= 2 && + (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + { + "{}".to_owned() + } else { + block_str.to_owned() + }) } impl Rewrite for ast::Block { @@ -671,7 +715,8 @@ impl Rewrite for ast::Block { // or an unsafe expression `unsafe { e }`. if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) && - shape.width >= 2 { + shape.width >= 2 + { return Some("{}".to_owned()); } @@ -681,8 +726,9 @@ impl Rewrite for ast::Block { if user_str.starts_with('{') && user_str.ends_with('}') { let comment_str = user_str[1..user_str.len() - 1].trim(); if self.stmts.is_empty() && !comment_str.contains('\n') && - !comment_str.starts_with("//") && - comment_str.len() + 4 <= shape.width { + !comment_str.starts_with("//") && + comment_str.len() + 4 <= shape.width + { return Some(format!("{{ {} }}", comment_str)); } } @@ -703,11 +749,15 @@ impl Rewrite for ast::Block { let prefix = if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() let budget = try_opt!(shape.width.checked_sub(9)); - format!("unsafe {} ", - try_opt!(rewrite_comment(trimmed, - true, - Shape::legacy(budget, shape.indent + 7), - context.config))) + format!( + "unsafe {} ", + try_opt!(rewrite_comment( + trimmed, + true, + Shape::legacy(budget, shape.indent + 7), + context.config, + )) + ) } else { "unsafe ".to_owned() }; @@ -724,8 +774,10 @@ impl Rewrite for ast::Block { visitor.visit_block(self); if visitor.failed && shape.indent.alignment != 0 { - self.rewrite(context, - Shape::indented(shape.indent.block_only(), context.config)) + self.rewrite( + context, + Shape::indented(shape.indent.block_only(), context.config), + ) } else { Some(format!("{}{}", prefix, visitor.buffer)) } @@ -740,20 +792,23 @@ impl Rewrite for ast::Stmt { ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(self) { ";" } else { "" }; - format_expr(ex, - match self.node { - ast::StmtKind::Expr(_) => ExprType::SubExpression, - ast::StmtKind::Semi(_) => ExprType::Statement, - _ => unreachable!(), - }, - context, - try_opt!(shape.sub_width(suffix.len()))) - .map(|s| s + suffix) + format_expr( + ex, + match self.node { + ast::StmtKind::Expr(_) => ExprType::SubExpression, + ast::StmtKind::Semi(_) => ExprType::Statement, + _ => unreachable!(), + }, + context, + try_opt!(shape.sub_width(suffix.len())), + ).map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; - result.and_then(|res| recover_comment_removed(res, self.span, context, shape)) + result.and_then(|res| { + recover_comment_removed(res, self.span, context, shape) + }) } } @@ -775,14 +830,15 @@ struct ControlFlow<'a> { } impl<'a> ControlFlow<'a> { - fn new_if(cond: &'a ast::Expr, - pat: Option<&'a ast::Pat>, - block: &'a ast::Block, - else_block: Option<&'a ast::Expr>, - allow_single_line: bool, - nested_if: bool, - span: Span) - -> ControlFlow<'a> { + fn new_if( + cond: &'a ast::Expr, + pat: Option<&'a ast::Pat>, + block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, + allow_single_line: bool, + nested_if: bool, + span: Span, + ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), block: block, @@ -801,10 +857,11 @@ impl<'a> ControlFlow<'a> { } } - fn new_loop(block: &'a ast::Block, - label: Option, - span: Span) - -> ControlFlow<'a> { + fn new_loop( + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { ControlFlow { cond: None, block: block, @@ -820,12 +877,13 @@ impl<'a> ControlFlow<'a> { } } - fn new_while(pat: Option<&'a ast::Pat>, - cond: &'a ast::Expr, - block: &'a ast::Block, - label: Option, - span: Span) - -> ControlFlow<'a> { + fn new_while( + pat: Option<&'a ast::Pat>, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), block: block, @@ -844,12 +902,13 @@ impl<'a> ControlFlow<'a> { } } - fn new_for(pat: &'a ast::Pat, - cond: &'a ast::Expr, - block: &'a ast::Block, - label: Option, - span: Span) - -> ControlFlow<'a> { + fn new_for( + pat: &'a ast::Pat, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), block: block, @@ -865,40 +924,49 @@ impl<'a> ControlFlow<'a> { } } - fn rewrite_single_line(&self, - pat_expr_str: &str, - context: &RewriteContext, - width: usize) - -> Option { + fn rewrite_single_line( + &self, + pat_expr_str: &str, + context: &RewriteContext, + width: usize, + ) -> Option { assert!(self.allow_single_line); let else_block = try_opt!(self.else_block); let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node) = else_block.node { if !is_simple_block(self.block, context.codemap) || - !is_simple_block(else_node, context.codemap) || - pat_expr_str.contains('\n') { + !is_simple_block(else_node, context.codemap) || + pat_expr_str.contains('\n') + { return None; } let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); let expr = &self.block.stmts[0]; - let if_str = try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); + let if_str = try_opt!(expr.rewrite( + context, + Shape::legacy(new_width, Indent::empty()), + )); let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = - try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); + let else_str = try_opt!(else_expr.rewrite( + context, + Shape::legacy(new_width, Indent::empty()), + )); if if_str.contains('\n') || else_str.contains('\n') { return None; } - let result = format!("{} {} {{ {} }} else {{ {} }}", - self.keyword, - pat_expr_str, - if_str, - else_str); + let result = format!( + "{} {} {{ {} }} else {{ {} }}", + self.keyword, + pat_expr_str, + if_str, + else_str + ); if result.len() <= width { return Some(result); @@ -935,26 +1003,29 @@ impl<'a> Rewrite for ControlFlow<'a> { cond_shape = try_opt!(cond_shape.sub_width(2)); } - try_opt!(rewrite_pat_expr(context, - self.pat, - cond, - self.matcher, - self.connector, - self.keyword, - cond_shape)) + try_opt!(rewrite_pat_expr( + context, + self.pat, + cond, + self.matcher, + self.connector, + self.keyword, + cond_shape, + )) } None => String::new(), }; let force_newline_brace = context.config.control_style() == Style::Rfc && - pat_expr_string.contains('\n'); + pat_expr_string.contains('\n'); // Try to format if-else on single line. if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if trial.is_some() && - trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width() { + trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width() + { return trial; } } @@ -1009,17 +1080,19 @@ impl<'a> Rewrite for ControlFlow<'a> { extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine || - force_newline_brace { + force_newline_brace + { alt_block_sep.as_str() } else { " " }; - let mut result = format!("{}{}{}{}{}{}", + let mut result = + format!("{}{}{}{}{}{}", label_string, self.keyword, between_kwd_cond_comment @@ -1044,24 +1117,26 @@ impl<'a> Rewrite for ControlFlow<'a> { // Note how we're passing the original shape, as the // cost of "else" should not cascade. ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if(cond, - Some(pat), - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + ControlFlow::new_if( + cond, + Some(pat), + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo, self.span.hi), + ).rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if(cond, - None, - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo, self.span.hi)) - .rewrite(context, shape) + ControlFlow::new_if( + cond, + None, + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo, self.span.hi), + ).rewrite(context, shape) } _ => { last_in_chain = true; @@ -1076,18 +1151,23 @@ impl<'a> Rewrite for ControlFlow<'a> { }; let between_kwd_else_block = - mk_sp(self.block.span.hi, - context - .codemap - .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else")); + mk_sp( + self.block.span.hi, + context.codemap.span_before( + mk_sp(self.block.span.hi, else_block.span.lo), + "else", + ), + ); let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); - let after_else = mk_sp(context - .codemap - .span_after(mk_sp(self.block.span.hi, else_block.span.lo), - "else"), - else_block.span.lo); + let after_else = mk_sp( + context.codemap.span_after( + mk_sp(self.block.span.hi, else_block.span.lo), + "else", + ), + else_block.span.lo, + ); let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style() { @@ -1099,13 +1179,17 @@ impl<'a> Rewrite for ControlFlow<'a> { ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, _ => " ", }; - try_opt!(write!(&mut result, - "{}else{}", - between_kwd_else_block_comment - .as_ref() - .map_or(between_sep, |s| &**s), - after_else_comment.as_ref().map_or(after_sep, |s| &**s)) - .ok()); + try_opt!( + write!( + &mut result, + "{}else{}", + between_kwd_else_block_comment.as_ref().map_or( + between_sep, + |s| &**s, + ), + after_else_comment.as_ref().map_or(after_sep, |s| &**s) + ).ok() + ); result.push_str(&try_opt!(rewrite)); } @@ -1123,10 +1207,17 @@ fn rewrite_label(label: Option) -> String { fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { let comment_str = context.snippet(span); if contains_comment(&comment_str) { - let comment = try_opt!(rewrite_comment(comment_str.trim(), false, shape, context.config)); - Some(format!("\n{indent}{}\n{indent}", - comment, - indent = shape.indent.to_string(context.config))) + let comment = try_opt!(rewrite_comment( + comment_str.trim(), + false, + shape, + context.config, + )); + Some(format!( + "\n{indent}{}\n{indent}", + comment, + indent = shape.indent.to_string(context.config) + )) } else { None } @@ -1142,7 +1233,7 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { // the expression. pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && - !block_contains_comment(block, codemap)) + !block_contains_comment(block, codemap)) } /// Checks whether a block contains at most one statement or expression, and no comments. @@ -1173,11 +1264,12 @@ fn is_unsafe_block(block: &ast::Block) -> bool { // inter-match-arm-comment-rules: // - all comments following a match arm before the start of the next arm // are about the second arm -fn rewrite_match_arm_comment(context: &RewriteContext, - missed_str: &str, - shape: Shape, - arm_indent_str: &str) - -> Option { +fn rewrite_match_arm_comment( + context: &RewriteContext, + missed_str: &str, + shape: Shape, + arm_indent_str: &str, +) -> Option { // The leading "," is not part of the arm-comment let missed_str = match missed_str.find_uncommented(",") { Some(n) => &missed_str[n + 1..], @@ -1190,9 +1282,10 @@ fn rewrite_match_arm_comment(context: &RewriteContext, result.push_str(&missed_str[..first_brk]); let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it - let first = missed_str - .find(|c: char| !c.is_whitespace()) - .unwrap_or(missed_str.len()); + let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or( + missed_str + .len(), + ); if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { // Excessive vertical whitespace before comment should be preserved // FIXME handle vertical whitespace better @@ -1209,12 +1302,13 @@ fn rewrite_match_arm_comment(context: &RewriteContext, Some(result) } -fn rewrite_match(context: &RewriteContext, - cond: &ast::Expr, - arms: &[ast::Arm], - shape: Shape, - span: Span) - -> Option { +fn rewrite_match( + context: &RewriteContext, + cond: &ast::Expr, + arms: &[ast::Arm], + shape: Shape, + span: Span, +) -> Option { if arms.is_empty() { return None; } @@ -1240,9 +1334,10 @@ fn rewrite_match(context: &RewriteContext, let arm_indent_str = arm_shape.indent.to_string(context.config); - let open_brace_pos = context - .codemap - .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); + let open_brace_pos = context.codemap.span_after( + mk_sp(cond.span.hi, arm_start_pos(&arms[0])), + "{", + ); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. @@ -1251,8 +1346,12 @@ fn rewrite_match(context: &RewriteContext, } else { context.snippet(mk_sp(arm_end_pos(&arms[i - 1]), arm_start_pos(arm))) }; - let comment = - try_opt!(rewrite_match_arm_comment(context, &missed_str, arm_shape, &arm_indent_str)); + let comment = try_opt!(rewrite_match_arm_comment( + context, + &missed_str, + arm_shape, + &arm_indent_str, + )); result.push_str(&comment); result.push('\n'); result.push_str(&arm_indent_str); @@ -1270,8 +1369,12 @@ fn rewrite_match(context: &RewriteContext, // BytePos(1) = closing match brace. let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi - BytePos(1)); let last_comment = context.snippet(last_span); - let comment = - try_opt!(rewrite_match_arm_comment(context, &last_comment, arm_shape, &arm_indent_str)); + let comment = try_opt!(rewrite_match_arm_comment( + context, + &last_comment, + arm_shape, + &arm_indent_str, + )); result.push_str(&comment); result.push('\n'); result.push_str(&shape.indent.to_string(context.config)); @@ -1336,9 +1439,11 @@ impl Rewrite for ast::Arm { // 5 = ` => {` let pat_shape = try_opt!(shape.sub_width(5)); - let pat_strs = try_opt!(pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>()); + let pat_strs = try_opt!( + pats.iter() + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>() + ); let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); @@ -1362,17 +1467,19 @@ impl Rewrite for ast::Arm { shape }; - let guard_str = try_opt!(rewrite_guard(context, - guard, - guard_shape, - trimmed_last_line_width(&pats_str))); + let guard_str = try_opt!(rewrite_guard( + context, + guard, + guard_shape, + trimmed_last_line_width(&pats_str), + )); let pats_str = format!("{}{}", pats_str, guard_str); let (mut extend, body) = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && - is_simple_block(block, context.codemap) && - context.config.wrap_match_arms() => { + is_simple_block(block, context.codemap) && + context.config.wrap_match_arms() => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { (false, &**expr) } else { @@ -1389,7 +1496,7 @@ impl Rewrite for ast::Arm { let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + &shape.indent.block_only().to_string(context.config); let pat_width = extra_offset(&pats_str, shape); // Let's try and get the arm body on the same line as the condition. @@ -1409,21 +1516,23 @@ impl Rewrite for ast::Arm { match rewrite { Some(ref body_str) if (!body_str.contains('\n') && - body_str.len() <= arm_shape.width) || - !context.config.wrap_match_arms() || - (extend && first_line_width(body_str) <= arm_shape.width) || - is_block => { + body_str.len() <= arm_shape.width) || + !context.config.wrap_match_arms() || + (extend && first_line_width(body_str) <= arm_shape.width) || + is_block => { let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), _ => " ", }; - return Some(format!("{}{} =>{}{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - body_str, - comma)); + return Some(format!( + "{}{} =>{}{}{}", + attr_str.trim_left(), + pats_str, + block_sep, + body_str, + comma + )); } _ => {} } @@ -1433,12 +1542,13 @@ impl Rewrite for ast::Arm { // necessary. let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces())) .block_indent(context.config.tab_spaces()); - let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape), - body_shape.width)); - let indent_str = shape - .indent - .block_indent(context.config) - .to_string(context.config); + let next_line_body = try_opt!(nop_block_collapse( + body.rewrite(context, body_shape), + body_shape.width, + )); + let indent_str = shape.indent.block_indent(context.config).to_string( + context.config, + ); let (body_prefix, body_suffix) = if context.config.wrap_match_arms() { if context.config.match_block_trailing_comma() { ("{", "},") @@ -1457,22 +1567,26 @@ impl Rewrite for ast::Arm { }; if context.config.wrap_match_arms() { - Some(format!("{}{} =>{}{}{}\n{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - indent_str, - next_line_body, - shape.indent.to_string(context.config), - body_suffix)) + Some(format!( + "{}{} =>{}{}{}\n{}{}", + attr_str.trim_left(), + pats_str, + block_sep, + indent_str, + next_line_body, + shape.indent.to_string(context.config), + body_suffix + )) } else { - Some(format!("{}{} =>{}{}{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - indent_str, - next_line_body, - body_suffix)) + Some(format!( + "{}{} =>{}{}{}{}", + attr_str.trim_left(), + pats_str, + block_sep, + indent_str, + next_line_body, + body_suffix + )) } } } @@ -1481,17 +1595,18 @@ impl Rewrite for ast::Arm { // E.g. `Foo::Bar` is simple, but `Foo(..)` is not. fn pat_is_simple(pat_str: &str) -> bool { pat_str.len() <= 16 || - (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) + (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) } // The `if ...` guard on a match arm. -fn rewrite_guard(context: &RewriteContext, - guard: &Option>, - shape: Shape, - // The amount of space used up on this line for the pattern in - // the arm (excludes offset). - pattern_width: usize) - -> Option { +fn rewrite_guard( + context: &RewriteContext, + guard: &Option>, + shape: Shape, + // The amount of space used up on this line for the pattern in + // the arm (excludes offset). + pattern_width: usize, +) -> Option { if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` @@ -1526,16 +1641,17 @@ fn rewrite_guard(context: &RewriteContext, } } -fn rewrite_pat_expr(context: &RewriteContext, - pat: Option<&ast::Pat>, - expr: &ast::Expr, - matcher: &str, - // Connecting piece between pattern and expression, - // *without* trailing space. - connector: &str, - keyword: &str, - shape: Shape) - -> Option { +fn rewrite_pat_expr( + context: &RewriteContext, + pat: Option<&ast::Pat>, + expr: &ast::Expr, + matcher: &str, + // Connecting piece between pattern and expression, + // *without* trailing space. + connector: &str, + keyword: &str, + shape: Shape, +) -> Option { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); let mut pat_string = String::new(); let mut result = match pat { @@ -1545,8 +1661,9 @@ fn rewrite_pat_expr(context: &RewriteContext, } else { format!("{} ", matcher) }; - let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())) - .sub_width(connector.len())); + let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())).sub_width( + connector.len(), + )); pat_string = try_opt!(pat.rewrite(context, pat_shape)); format!("{}{}{}", matcher, pat_string, connector) } @@ -1596,7 +1713,8 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt } if !context.config.force_format_strings() && - !string_requires_rewrite(context, span, &string_lit, shape) { + !string_requires_rewrite(context, span, &string_lit, shape) + { return Some(string_lit); } @@ -1616,11 +1734,12 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt rewrite_string(str_lit, &fmt) } -fn string_requires_rewrite(context: &RewriteContext, - span: Span, - string: &str, - shape: Shape) - -> bool { +fn string_requires_rewrite( + context: &RewriteContext, + span: Span, + string: &str, + shape: Shape, +) -> bool { if context.codemap.lookup_char_pos(span.lo).col.0 != shape.indent.width() { return true; } @@ -1640,13 +1759,15 @@ fn string_requires_rewrite(context: &RewriteContext, false } -pub fn rewrite_call_with_binary_search(context: &RewriteContext, - callee: &R, - args: &[ptr::P], - span: Span, - shape: Shape) - -> Option - where R: Rewrite +pub fn rewrite_call_with_binary_search( + context: &RewriteContext, + callee: &R, + args: &[ptr::P], + span: Span, + shape: Shape, +) -> Option +where + R: Rewrite, { let closure = |callee_max_width| { // FIXME using byte lens instead of char lens (and probably all over the @@ -1655,9 +1776,9 @@ pub fn rewrite_call_with_binary_search(context: &RewriteContext, width: callee_max_width, ..shape }; - let callee_str = callee - .rewrite(context, callee_shape) - .ok_or(Ordering::Greater)?; + let callee_str = callee.rewrite(context, callee_shape).ok_or( + Ordering::Greater, + )?; rewrite_call_inner(context, &callee_str, args, span, shape, false) }; @@ -1665,22 +1786,24 @@ pub fn rewrite_call_with_binary_search(context: &RewriteContext, binary_search(1, shape.width, closure) } -pub fn rewrite_call(context: &RewriteContext, - callee: &str, - args: &[ptr::P], - span: Span, - shape: Shape) - -> Option { +pub fn rewrite_call( + context: &RewriteContext, + callee: &str, + args: &[ptr::P], + span: Span, + shape: Shape, +) -> Option { rewrite_call_inner(context, &callee, args, span, shape, false).ok() } -fn rewrite_call_inner(context: &RewriteContext, - callee_str: &str, - args: &[ptr::P], - span: Span, - shape: Shape, - force_trailing_comma: bool) - -> Result { +fn rewrite_call_inner( + context: &RewriteContext, + callee_str: &str, + args: &[ptr::P], + span: Span, + shape: Shape, + force_trailing_comma: bool, +) -> Result { // 2 = `( `, 1 = `(` let paren_overhead = if context.config.spaces_within_parens() { 2 @@ -1693,11 +1816,12 @@ fn rewrite_call_inner(context: &RewriteContext, .checked_sub(used_width + 2 * paren_overhead) .ok_or(Ordering::Greater)?; - let nested_shape = shape_from_fn_call_style(context, - shape, - used_width + 2 * paren_overhead, - used_width + paren_overhead) - .ok_or(Ordering::Greater)?; + let nested_shape = shape_from_fn_call_style( + context, + shape, + used_width + 2 * paren_overhead, + used_width + paren_overhead, + ).ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); let args_span = mk_sp(span_lo, span.hi); @@ -1727,12 +1851,14 @@ fn rewrite_call_inner(context: &RewriteContext, if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { let mut new_context = context.clone(); new_context.use_block = true; - return rewrite_call_inner(&new_context, - callee_str, - args, - span, - shape, - force_trailing_comma); + return rewrite_call_inner( + &new_context, + callee_str, + args, + span, + shape, + force_trailing_comma, + ); } let args_shape = shape @@ -1745,28 +1871,32 @@ fn rewrite_call_inner(context: &RewriteContext, fn need_block_indent(s: &str, shape: Shape) -> bool { s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)) - .map_or(false, |w| w + 1 < shape.indent.width()) - }) + s.find(|c| !char::is_whitespace(c)).map_or(false, |w| { + w + 1 < shape.indent.width() + }) + }) } -fn rewrite_call_args(context: &RewriteContext, - args: &[ptr::P], - span: Span, - shape: Shape, - one_line_width: usize, - force_trailing_comma: bool) - -> Option<(bool, String)> { +fn rewrite_call_args( + context: &RewriteContext, + args: &[ptr::P], + span: Span, + shape: Shape, + one_line_width: usize, + force_trailing_comma: bool, +) -> Option<(bool, String)> { let mut item_context = context.clone(); item_context.inside_macro = false; - let items = itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo, - |item| item.span.hi, - |item| item.rewrite(&item_context, shape), - span.lo, - span.hi); + let items = itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| item.rewrite(&item_context, shape), + span.lo, + span.hi, + ); let mut item_vec: Vec<_> = items.collect(); // Try letting the last argument overflow to the next line with block @@ -1789,15 +1919,18 @@ fn rewrite_call_args(context: &RewriteContext, config: context.config, }; - write_list(&item_vec, &fmt).map(|args_str| (tactic != DefinitiveListTactic::Vertical, args_str)) + write_list(&item_vec, &fmt).map(|args_str| { + (tactic != DefinitiveListTactic::Vertical, args_str) + }) } -fn try_overflow_last_arg(context: &RewriteContext, - item_vec: &mut Vec, - args: &[ptr::P], - shape: Shape, - one_line_width: usize) - -> DefinitiveListTactic { +fn try_overflow_last_arg( + context: &RewriteContext, + item_vec: &mut Vec, + args: &[ptr::P], + shape: Shape, + one_line_width: usize, +) -> DefinitiveListTactic { let overflow_last = can_be_overflowed(&context, args); // Replace the last item with its first line to see if it fits with @@ -1809,19 +1942,22 @@ fn try_overflow_last_arg(context: &RewriteContext, _ => (), } last_arg_shape(&context, &item_vec, shape).map_or((None, None), |arg_shape| { - rewrite_last_arg_with_overflow(&context, - &args[args.len() - 1], - &mut item_vec[args.len() - 1], - arg_shape) + rewrite_last_arg_with_overflow( + &context, + &args[args.len() - 1], + &mut item_vec[args.len() - 1], + arg_shape, + ) }) } else { (None, None) }; - let tactic = - definitive_tactic(&*item_vec, - ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()), - one_line_width); + let tactic = definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()), + one_line_width, + ); // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. @@ -1849,17 +1985,18 @@ fn last_arg_shape(context: &RewriteContext, items: &Vec, shape: Shape) shape.block().indent }; Some(Shape { - width: try_opt!(max_width.checked_sub(overhead)), - indent: arg_indent, - offset: 0, - }) + width: try_opt!(max_width.checked_sub(overhead)), + indent: arg_indent, + offset: 0, + }) } -fn rewrite_last_arg_with_overflow(context: &RewriteContext, - last_arg: &ptr::P, - last_item: &mut ListItem, - shape: Shape) - -> (Option, Option) { +fn rewrite_last_arg_with_overflow( + context: &RewriteContext, + last_arg: &ptr::P, + last_item: &mut ListItem, + shape: Shape, +) -> (Option, Option) { let rewrite = last_arg.rewrite(context, shape); let orig_last = last_item.item.clone(); @@ -1873,15 +2010,16 @@ fn rewrite_last_arg_with_overflow(context: &RewriteContext, } fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bool { - args.last() - .map_or(false, |x| can_be_overflowed_expr(context, &x, args.len())) + args.last().map_or(false, |x| { + can_be_overflowed_expr(context, &x, args.len()) + }) } fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { match expr.node { ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) || - (context.config.fn_call_style() == IndentStyle::Visual && args_len > 1) + (context.config.fn_call_style() == IndentStyle::Visual && args_len > 1) } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | @@ -1894,7 +2032,7 @@ fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { context.use_block_indent() || - context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 + context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 } ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) | @@ -1933,10 +2071,12 @@ fn wrap_args_with_parens(context: &RewriteContext, format!("({})", args_str) } } else { - format!("(\n{}{}\n{})", - nested_shape.indent.to_string(context.config), - args_str, - shape.block().indent.to_string(context.config)) + format!( + "(\n{}{}\n{})", + nested_shape.indent.to_string(context.config), + args_str, + shape.block().indent.to_string(context.config) + ) } } @@ -1948,18 +2088,21 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> let subexpr_str = subexpr.rewrite(context, sub_shape); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - subexpr_str.map(|s| if context.config.spaces_within_parens() && s.len() > 0 { - format!("( {} )", s) - } else { - format!("({})", s) - }) + subexpr_str.map(|s| if context.config.spaces_within_parens() && + s.len() > 0 + { + format!("( {} )", s) + } else { + format!("({})", s) + }) } -fn rewrite_index(expr: &ast::Expr, - index: &ast::Expr, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_index( + expr: &ast::Expr, + index: &ast::Expr, + context: &RewriteContext, + shape: Shape, +) -> Option { let expr_str = try_opt!(expr.rewrite(context, shape)); let (lbr, rbr) = if context.config.spaces_within_square_brackets() { @@ -1979,21 +2122,29 @@ fn rewrite_index(expr: &ast::Expr, let indent = indent.to_string(&context.config); // FIXME this is not right, since we don't take into account that shape.width // might be reduced from max_width by something on the right. - let budget = try_opt!(context - .config - .max_width() - .checked_sub(indent.len() + lbr.len() + rbr.len())); + let budget = try_opt!(context.config.max_width().checked_sub( + indent.len() + lbr.len() + + rbr.len(), + )); let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); - Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr)) + Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent, + lbr, + index_str, + rbr + )) } -fn rewrite_struct_lit<'a>(context: &RewriteContext, - path: &ast::Path, - fields: &'a [ast::Field], - base: Option<&'a ast::Expr>, - span: Span, - shape: Shape) - -> Option { +fn rewrite_struct_lit<'a>( + context: &RewriteContext, + path: &ast::Path, + fields: &'a [ast::Field], + base: Option<&'a ast::Expr>, + span: Span, + shape: Shape, +) -> Option { debug!("rewrite_struct_lit: shape {:?}", shape); enum StructLitField<'a> { @@ -2003,7 +2154,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // 2 = " {".len() let path_shape = try_opt!(shape.sub_width(2)); - let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape)); + let path_str = try_opt!(rewrite_path( + context, + PathContext::Expr, + None, + path, + path_shape, + )); if fields.len() == 0 && base.is_none() { return Some(format!("{} {{}}", path_str)); @@ -2042,14 +2199,16 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } }; - let items = itemize_list(context.codemap, - field_iter, - "}", - span_lo, - span_hi, - rewrite, - context.codemap.span_after(span, "{"), - span.hi); + let items = itemize_list( + context.codemap, + field_iter, + "}", + span_lo, + span_hi, + rewrite, + context.codemap.span_after(span, "{"), + span.hi, + ); let item_vec = items.collect::>(); let tactic = struct_lit_tactic(h_shape, context, &item_vec); @@ -2058,14 +2217,16 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let fields_str = try_opt!(write_list(&item_vec, &fmt)); let fields_str = if context.config.struct_lit_style() == IndentStyle::Block && - (fields_str.contains('\n') || - context.config.struct_lit_multiline_style() == - MultilineStyle::ForceMulti || - fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) { - format!("\n{}{}\n{}", - v_shape.indent.to_string(context.config), - fields_str, - shape.indent.to_string(context.config)) + (fields_str.contains('\n') || + context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || + fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) + { + format!( + "\n{}{}\n{}", + v_shape.indent.to_string(context.config), + fields_str, + shape.indent.to_string(context.config) + ) } else { // One liner or visual indent. format!(" {} ", fields_str) @@ -2078,8 +2239,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, } pub fn struct_lit_field_separator(config: &Config) -> &str { - colon_spaces(config.space_before_struct_lit_field_colon(), - config.space_after_struct_lit_field_colon()) + colon_spaces( + config.space_before_struct_lit_field_colon(), + config.space_after_struct_lit_field_colon(), + ) } fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { @@ -2102,26 +2265,30 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); - let expr = field - .expr - .rewrite(context, Shape::indented(expr_offset, context.config)); + let expr = field.expr.rewrite( + context, + Shape::indented(expr_offset, context.config), + ); expr.map(|s| { - format!("{}{}:\n{}{}", - attrs_str, - name, - expr_offset.to_string(&context.config), - s) - }) + format!( + "{}{}:\n{}{}", + attrs_str, + name, + expr_offset.to_string(&context.config), + s + ) + }) } } } } -fn shape_from_fn_call_style(context: &RewriteContext, - shape: Shape, - overhead: usize, - offset: usize) - -> Option { +fn shape_from_fn_call_style( + context: &RewriteContext, + shape: Shape, + overhead: usize, + offset: usize, +) -> Option { if context.use_block_indent() { Some(shape.block().block_indent(context.config.tab_spaces())) } else { @@ -2129,41 +2296,45 @@ fn shape_from_fn_call_style(context: &RewriteContext, } } -pub fn rewrite_tuple_type<'a, I>(context: &RewriteContext, - mut items: I, - span: Span, - shape: Shape) - -> Option - where I: ExactSizeIterator, - ::Item: Deref, - ::Target: Rewrite + Spanned + 'a +pub fn rewrite_tuple_type<'a, I>( + context: &RewriteContext, + mut items: I, + span: Span, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, + ::Item: Deref, + ::Target: Rewrite + Spanned + 'a, { // In case of length 1, need a trailing comma debug!("rewrite_tuple_type {:?}", shape); if items.len() == 1 { // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); - return items - .next() - .unwrap() - .rewrite(context, nested_shape) - .map(|s| if context.config.spaces_within_parens() { - format!("( {}, )", s) - } else { - format!("({},)", s) - }); + return items.next().unwrap().rewrite(context, nested_shape).map( + |s| { + if context.config.spaces_within_parens() { + format!("( {}, )", s) + } else { + format!("({},)", s) + } + }, + ); } let list_lo = context.codemap.span_after(span, "("); let nested_shape = try_opt!(shape.sub_width(2)).visual_indent(1); - let items = itemize_list(context.codemap, - items, - ")", - |item| item.span().lo, - |item| item.span().hi, - |item| item.rewrite(context, nested_shape), - list_lo, - span.hi - BytePos(1)); + let items = itemize_list( + context.codemap, + items, + ")", + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, nested_shape), + list_lo, + span.hi - BytePos(1), + ); let list_str = try_opt!(format_item_list(items, nested_shape, context.config)); if context.config.spaces_within_parens() && list_str.len() > 0 { @@ -2173,11 +2344,12 @@ pub fn rewrite_tuple_type<'a, I>(context: &RewriteContext, } } -pub fn rewrite_tuple(context: &RewriteContext, - items: &[ptr::P], - span: Span, - shape: Shape) - -> Option { +pub fn rewrite_tuple( + context: &RewriteContext, + items: &[ptr::P], + span: Span, + shape: Shape, +) -> Option { debug!("rewrite_tuple {:?}", shape); // Use old `rewrite_tuple` if context.config.fn_call_style() == IndentStyle::Visual { @@ -2186,20 +2358,22 @@ pub fn rewrite_tuple(context: &RewriteContext, // We use the same rule as funcation call for rewriting tuple. // 1 = "," - rewrite_call_inner(context, - &String::new(), - items, - span, - shape, - items.len() == 1) - .ok() + rewrite_call_inner( + context, + &String::new(), + items, + span, + shape, + items.len() == 1, + ).ok() } -pub fn rewrite_unary_prefix(context: &RewriteContext, - prefix: &str, - rewrite: &R, - shape: Shape) - -> Option { +pub fn rewrite_unary_prefix( + context: &RewriteContext, + prefix: &str, + rewrite: &R, + shape: Shape, +) -> Option { rewrite .rewrite(context, try_opt!(shape.offset_left(prefix.len()))) .map(|r| format!("{}{}", prefix, r)) @@ -2207,24 +2381,26 @@ pub fn rewrite_unary_prefix(context: &RewriteContext, // FIXME: this is probably not correct for multi-line Rewrites. we should // subtract suffix.len() from the last line budget, not the first! -pub fn rewrite_unary_suffix(context: &RewriteContext, - suffix: &str, - rewrite: &R, - shape: Shape) - -> Option { +pub fn rewrite_unary_suffix( + context: &RewriteContext, + suffix: &str, + rewrite: &R, + shape: Shape, +) -> Option { rewrite .rewrite(context, try_opt!(shape.sub_width(suffix.len()))) .map(|mut r| { - r.push_str(suffix); - r - }) + r.push_str(suffix); + r + }) } -fn rewrite_unary_op(context: &RewriteContext, - op: &ast::UnOp, - expr: &ast::Expr, - shape: Shape) - -> Option { +fn rewrite_unary_op( + context: &RewriteContext, + op: &ast::UnOp, + expr: &ast::Expr, + shape: Shape, +) -> Option { // For some reason, an UnOp is not spanned like BinOp! let operator_str = match *op { ast::UnOp::Deref => "*", @@ -2234,12 +2410,13 @@ fn rewrite_unary_op(context: &RewriteContext, rewrite_unary_prefix(context, operator_str, expr, shape) } -fn rewrite_assignment(context: &RewriteContext, - lhs: &ast::Expr, - rhs: &ast::Expr, - op: Option<&ast::BinOp>, - shape: Shape) - -> Option { +fn rewrite_assignment( + context: &RewriteContext, + lhs: &ast::Expr, + rhs: &ast::Expr, + op: Option<&ast::BinOp>, + shape: Shape, +) -> Option { let operator_str = match op { Some(op) => context.snippet(op.span), None => "=".to_owned(), @@ -2247,27 +2424,30 @@ fn rewrite_assignment(context: &RewriteContext, // 1 = space between lhs and operator. let lhs_shape = try_opt!(shape.sub_width(operator_str.len() + 1)); - let lhs_str = format!("{} {}", - try_opt!(lhs.rewrite(context, lhs_shape)), - operator_str); + let lhs_str = format!( + "{} {}", + try_opt!(lhs.rewrite(context, lhs_shape)), + operator_str + ); rewrite_assign_rhs(context, lhs_str, rhs, shape) } // The left hand side must contain everything up to, and including, the // assignment operator. -pub fn rewrite_assign_rhs>(context: &RewriteContext, - lhs: S, - ex: &ast::Expr, - shape: Shape) - -> Option { +pub fn rewrite_assign_rhs>( + context: &RewriteContext, + lhs: S, + ex: &ast::Expr, + shape: Shape, +) -> Option { let mut result = lhs.into(); let last_line_width = last_line_width(&result) - - if result.contains('\n') { - shape.indent.width() - } else { - 0 - }; + if result.contains('\n') { + shape.indent.width() + } else { + 0 + }; // 1 = space between operator and rhs. let orig_shape = try_opt!(shape.block_indent(0).offset_left(last_line_width + 1)); let rhs = match ex.node { @@ -2300,10 +2480,21 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, // FIXME: DRY! match (rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref replacement_rhs)) - if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 || - (orig_rhs.rewrite(context, shape).is_none() && - replacement_rhs.rewrite(context, new_shape).is_some()) => { + (Some(ref orig_rhs), Some(ref replacement_rhs)) if count_line_breaks( + orig_rhs, + ) > + count_line_breaks( + replacement_rhs, + ) + 1 || + (orig_rhs + .rewrite(context, shape) + .is_none() && + replacement_rhs + .rewrite( + context, + new_shape, + ) + .is_some()) => { result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(replacement_rhs); } @@ -2323,11 +2514,12 @@ pub fn rewrite_assign_rhs>(context: &RewriteContext, Some(result) } -fn rewrite_expr_addrof(context: &RewriteContext, - mutability: ast::Mutability, - expr: &ast::Expr, - shape: Shape) - -> Option { +fn rewrite_expr_addrof( + context: &RewriteContext, + mutability: ast::Mutability, + expr: &ast::Expr, + shape: Shape, +) -> Option { let operator_str = match mutability { ast::Mutability::Immutable => "&", ast::Mutability::Mutable => "&mut ", diff --git a/src/file_lines.rs b/src/file_lines.rs index 2d1fa33a90e..8a0ed4b5d7a 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -52,7 +52,7 @@ impl Range { false } else { (self.lo <= other.hi && other.hi <= self.hi) || - (other.lo <= self.hi && self.hi <= other.hi) + (other.lo <= self.hi && self.hi <= other.hi) } } @@ -68,7 +68,10 @@ impl Range { /// intersect; returns `None` otherwise. fn merge(self, other: Range) -> Option { if self.adjacent_to(other) || self.intersects(other) { - Some(Range::new(cmp::min(self.lo, other.lo), cmp::max(self.hi, other.hi))) + Some(Range::new( + cmp::min(self.lo, other.lo), + cmp::max(self.hi, other.hi), + )) } else { None } @@ -127,7 +130,8 @@ impl FileLines { /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in /// the designated file (if any) and returns true if `f` ever does. fn file_range_matches(&self, file_name: &str, f: F) -> bool - where F: FnMut(&Range) -> bool + where + F: FnMut(&Range) -> bool, { let map = match self.0 { // `None` means "all lines in all files". @@ -209,8 +213,9 @@ struct JsonSpan { impl JsonSpan { fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - let canonical = canonicalize_path_string(&self.file) - .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; + let canonical = canonicalize_path_string(&self.file).ok_or_else(|| { + format!("Can't canonicalize {}", &self.file) + })?; Ok((canonical, Range::new(lo, hi))) } } @@ -219,10 +224,13 @@ impl JsonSpan { // for `FileLines`, so it will just panic instead. impl<'de> ::serde::de::Deserialize<'de> for FileLines { fn deserialize(_: D) -> Result - where D: ::serde::de::Deserializer<'de> + where + D: ::serde::de::Deserializer<'de>, { - panic!("FileLines cannot be deserialized from a project rustfmt.toml file: please \ - specify it via the `--file-lines` option instead"); + panic!( + "FileLines cannot be deserialized from a project rustfmt.toml file: please \ + specify it via the `--file-lines` option instead" + ); } } @@ -230,7 +238,8 @@ impl<'de> ::serde::de::Deserialize<'de> for FileLines { // `Config` struct should ensure this impl is never reached. impl ::serde::ser::Serialize for FileLines { fn serialize(&self, _: S) -> Result - where S: ::serde::ser::Serializer + where + S: ::serde::ser::Serializer, { unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); } @@ -270,13 +279,21 @@ mod test { fn test_range_merge() { assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); - assert_eq!(Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(4, 7))); - assert_eq!(Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(5, 7))); - assert_eq!(Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(6, 7))); - assert_eq!(Some(Range::new(3, 7)), - Range::new(3, 7).merge(Range::new(4, 5))); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(4, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(5, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(6, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 7).merge(Range::new(4, 5)) + ); } } diff --git a/src/filemap.rs b/src/filemap.rs index 82e8c3e50ae..e9779edfe5c 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -31,7 +31,8 @@ pub fn append_newline(s: &mut StringBuffer) { } pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error> - where T: Write +where + T: Write, { output_header(out, config.write_mode()).ok(); for &(ref filename, ref text) in file_map { @@ -43,11 +44,13 @@ pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> R } // Prints all newlines either as `\n` or as `\r\n`. -pub fn write_system_newlines(writer: T, - text: &StringBuffer, - config: &Config) - -> Result<(), io::Error> - where T: Write +pub fn write_system_newlines( + writer: T, + text: &StringBuffer, + config: &Config, +) -> Result<(), io::Error> +where + T: Write, { // Buffer output, since we're writing a since char at a time. let mut writer = BufWriter::new(writer); @@ -78,18 +81,21 @@ pub fn write_system_newlines(writer: T, } } -pub fn write_file(text: &StringBuffer, - filename: &str, - out: &mut T, - config: &Config) - -> Result - where T: Write +pub fn write_file( + text: &StringBuffer, + filename: &str, + out: &mut T, + config: &Config, +) -> Result +where + T: Write, { - fn source_and_formatted_text(text: &StringBuffer, - filename: &str, - config: &Config) - -> Result<(String, String), io::Error> { + fn source_and_formatted_text( + text: &StringBuffer, + filename: &str, + config: &Config, + ) -> Result<(String, String), io::Error> { let mut f = File::open(filename)?; let mut ori_text = String::new(); f.read_to_string(&mut ori_text)?; @@ -99,10 +105,11 @@ pub fn write_file(text: &StringBuffer, Ok((ori_text, fmt_text)) } - fn create_diff(filename: &str, - text: &StringBuffer, - config: &Config) - -> Result, io::Error> { + fn create_diff( + filename: &str, + text: &StringBuffer, + config: &Config, + ) -> Result, io::Error> { let (ori, fmt) = source_and_formatted_text(text, filename, config)?; Ok(make_diff(&ori, &fmt, 3)) } diff --git a/src/imports.rs b/src/imports.rs index 83e7661aad9..8a327069c2f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -73,9 +73,10 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde } } -fn compare_path_list_item_lists(a_items: &Vec, - b_items: &Vec) - -> Ordering { +fn compare_path_list_item_lists( + a_items: &Vec, + b_items: &Vec, +) -> Ordering { let mut a = a_items.clone(); let mut b = b_items.clone(); a.sort_by(|a, b| compare_path_list_items(a, b)); @@ -123,19 +124,33 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { // TODO (some day) remove unused imports, expand globs, compress many single // imports into a list import. -fn rewrite_view_path_prefix(path: &ast::Path, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_view_path_prefix( + path: &ast::Path, + context: &RewriteContext, + shape: Shape, +) -> Option { let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && - path.segments.len() > 1 { + path.segments.len() > 1 + { let path = &ast::Path { span: path.span.clone(), segments: path.segments[..path.segments.len() - 1].to_owned(), }; - try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)) + try_opt!(rewrite_path( + context, + PathContext::Import, + None, + path, + shape, + )) } else { - try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)) + try_opt!(rewrite_path( + context, + PathContext::Import, + None, + path, + shape, + )) }; Some(path_str) } @@ -162,11 +177,13 @@ impl Rewrite for ast::ViewPath { let prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4)); let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); - Some(if path.segments.last().unwrap().identifier == ident { - path_str - } else { - format!("{} as {}", path_str, ident_str) - }) + Some( + if path.segments.last().unwrap().identifier == ident { + path_str + } else { + format!("{} as {}", path_str, ident_str) + }, + ) } } } @@ -179,13 +196,13 @@ impl<'a> FmtVisitor<'a> { let pos_before_first_use_item = use_items .first() .map(|p_i| { - cmp::max(self.last_pos, - p_i.attrs - .iter() - .map(|attr| attr.span.lo) - .min() - .unwrap_or(p_i.span.lo)) - }) + cmp::max( + self.last_pos, + p_i.attrs.iter().map(|attr| attr.span.lo).min().unwrap_or( + p_i.span.lo, + ), + ) + }) .unwrap_or(self.last_pos); // Construct a list of pairs, each containing a `use` item and the start of span before // that `use` item. @@ -193,10 +210,10 @@ impl<'a> FmtVisitor<'a> { let mut ordered_use_items = use_items .iter() .map(|p_i| { - let new_item = (&*p_i, last_pos_of_prev_use_item); - last_pos_of_prev_use_item = p_i.span.hi; - new_item - }) + let new_item = (&*p_i, last_pos_of_prev_use_item); + last_pos_of_prev_use_item = p_i.span.hi; + new_item + }) .collect::>(); let pos_after_last_use_item = last_pos_of_prev_use_item; // Order the imports by view-path & other import path properties @@ -237,8 +254,10 @@ impl<'a> FmtVisitor<'a> { let mut offset = self.block_indent; offset.alignment += vis.len() + "use ".len(); // 1 = ";" - match vp.rewrite(&self.get_context(), - Shape::legacy(self.config.max_width() - offset.width() - 1, offset)) { + match vp.rewrite( + &self.get_context(), + Shape::legacy(self.config.max_width() - offset.width() - 1, offset), + ) { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo); @@ -295,14 +314,21 @@ fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { // Pretty prints a multi-item import. // Assumes that path_list.len() > 0. -pub fn rewrite_use_list(shape: Shape, - path: &ast::Path, - path_list: &[ast::PathListItem], - span: Span, - context: &RewriteContext) - -> Option { +pub fn rewrite_use_list( + shape: Shape, + path: &ast::Path, + path_list: &[ast::PathListItem], + span: Span, + context: &RewriteContext, +) -> Option { // Returns a different option to distinguish `::foo` and `foo` - let path_str = try_opt!(rewrite_path(context, PathContext::Import, None, path, shape)); + let path_str = try_opt!(rewrite_path( + context, + PathContext::Import, + None, + path, + shape, + )); match path_list.len() { 0 => unreachable!(), @@ -321,14 +347,16 @@ pub fn rewrite_use_list(shape: Shape, let mut items = { // Dummy value, see explanation below. let mut items = vec![ListItem::from_str("")]; - let iter = itemize_list(context.codemap, - path_list.iter(), - "}", - |vpi| vpi.span.lo, - |vpi| vpi.span.hi, - rewrite_path_item, - context.codemap.span_after(span, "{"), - span.hi); + let iter = itemize_list( + context.codemap, + path_list.iter(), + "}", + |vpi| vpi.span.lo, + |vpi| vpi.span.hi, + rewrite_path_item, + context.codemap.span_after(span, "{"), + span.hi, + ); items.extend(iter); items }; @@ -344,34 +372,40 @@ pub fn rewrite_use_list(shape: Shape, } - let tactic = definitive_tactic(&items[first_index..], - ::lists::ListTactic::Mixed, - remaining_width); + let tactic = definitive_tactic( + &items[first_index..], + ::lists::ListTactic::Mixed, + remaining_width, + ); let fmt = ListFormatting { tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, // Add one to the indent to account for "{" - shape: Shape::legacy(remaining_width, - shape.indent + path_str.len() + colons_offset + 1), + shape: Shape::legacy( + remaining_width, + shape.indent + path_str.len() + colons_offset + 1, + ), ends_with_newline: false, config: context.config, }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); - Some(if path_str.is_empty() { - format!("{{{}}}", list_str) - } else { - format!("{}::{{{}}}", path_str, list_str) - }) + Some( + if path_str.is_empty() { + format!("{{{}}}", list_str) + } else { + format!("{}::{{{}}}", path_str, list_str) + }, + ) } // Returns true when self item was found. fn move_self_to_front(items: &mut Vec) -> bool { - match items - .iter() - .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) { + match items.iter().position(|item| { + item.item.as_ref().map(|x| &x[..]) == Some("self") + }) { Some(pos) => { items[0] = items.remove(pos); true diff --git a/src/issues.rs b/src/issues.rs index 6e58784c1b8..0211723e930 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -172,11 +172,12 @@ impl BadIssueSeeker { } } - fn inspect_number(&mut self, - c: char, - issue: Issue, - mut part: NumberPart) - -> IssueClassification { + fn inspect_number( + &mut self, + c: char, + issue: Issue, + mut part: NumberPart, + ) -> IssueClassification { if !issue.missing_number || c == '\n' { return IssueClassification::Bad(issue); } else if c == ')' { @@ -223,8 +224,10 @@ impl BadIssueSeeker { fn find_unnumbered_issue() { fn check_fail(text: &str, failing_pos: usize) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(Some(failing_pos), - text.chars().position(|c| seeker.inspect(c).is_some())); + assert_eq!( + Some(failing_pos), + text.chars().position(|c| seeker.inspect(c).is_some()) + ); } fn check_pass(text: &str) { @@ -252,46 +255,60 @@ fn find_issue() { text.chars().any(|c| seeker.inspect(c).is_some()) } - assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n", - ReportTactic::Always, - ReportTactic::Never)); - - assert!(!is_bad_issue("TODO: no number\n", - ReportTactic::Never, - ReportTactic::Always)); - - assert!(is_bad_issue("This is a FIXME(#1)\n", - ReportTactic::Never, - ReportTactic::Always)); - - assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Always, ReportTactic::Never)); + assert!(is_bad_issue( + "TODO(@maintainer, #1222, hello)\n", + ReportTactic::Always, + ReportTactic::Never, + )); + + assert!(!is_bad_issue( + "TODO: no number\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(is_bad_issue( + "This is a FIXME(#1)\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(!is_bad_issue( + "bad FIXME\n", + ReportTactic::Always, + ReportTactic::Never, + )); } #[test] fn issue_type() { let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); let expected = Some(Issue { - issue_type: IssueType::Todo, - missing_number: false, - }); - - assert_eq!(expected, - "TODO(#100): more awesomeness" - .chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap()); + issue_type: IssueType::Todo, + missing_number: false, + }); + + assert_eq!( + expected, + "TODO(#100): more awesomeness" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap() + ); let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); let expected = Some(Issue { - issue_type: IssueType::Fixme, - missing_number: true, - }); - - assert_eq!(expected, - "Test. FIXME: bad, bad, not good" - .chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap()); + issue_type: IssueType::Fixme, + missing_number: true, + }); + + assert_eq!( + expected, + "Test. FIXME: bad, bad, not good" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap() + ); } diff --git a/src/items.rs b/src/items.rs index 085b9eed812..3639e5ae0e5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -29,8 +29,10 @@ use syntax::codemap::{Span, BytePos}; use syntax::ast::ImplItem; fn type_annotation_separator(config: &Config) -> &str { - colon_spaces(config.space_before_type_annotation(), - config.space_after_type_annotation_colon()) + colon_spaces( + config.space_before_type_annotation(), + config.space_after_type_annotation_colon(), + ) } @@ -38,10 +40,12 @@ fn type_annotation_separator(config: &Config) -> &str { // let pat: ty = init; impl Rewrite for ast::Local { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!("Local::rewrite {:?} {} {:?}", - self, - shape.width, - shape.indent); + debug!( + "Local::rewrite {:?} {} {:?}", + self, + shape.width, + shape.indent + ); let mut result = "let ".to_owned(); // 4 = "let ".len() @@ -145,8 +149,9 @@ impl<'a> FmtVisitor<'a> { self.format_missing_no_indent(item.span.hi - BytePos(1)); self.block_indent = self.block_indent.block_unindent(self.config); - self.buffer - .push_str(&self.block_indent.to_string(self.config)); + self.buffer.push_str( + &self.block_indent.to_string(self.config), + ); } else { for item in &item.body { self.format_body_element(item); @@ -181,22 +186,24 @@ impl<'a> FmtVisitor<'a> { match item.node { ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { let indent = self.block_indent; - let rewrite = rewrite_fn_base(&self.get_context(), - indent, - item.ident, - fn_decl, - generics, - ast::Unsafety::Normal, - ast::Constness::NotConst, - ast::Defaultness::Final, - // These are not actually rust functions, - // but we format them as such. - abi::Abi::Rust, - &item.vis, - span, - false, - false, - false); + let rewrite = rewrite_fn_base( + &self.get_context(), + indent, + item.ident, + fn_decl, + generics, + ast::Unsafety::Normal, + ast::Constness::NotConst, + ast::Defaultness::Final, + // These are not actually rust functions, + // but we format them as such. + abi::Abi::Rust, + &item.vis, + span, + false, + false, + false, + ); match rewrite { Some((new_fn, _)) => { @@ -231,45 +238,49 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.hi; } - pub fn rewrite_fn(&mut self, - indent: Indent, - ident: ast::Ident, - fd: &ast::FnDecl, - generics: &ast::Generics, - unsafety: ast::Unsafety, - constness: ast::Constness, - defaultness: ast::Defaultness, - abi: abi::Abi, - vis: &ast::Visibility, - span: Span, - block: &ast::Block) - -> Option { + pub fn rewrite_fn( + &mut self, + indent: Indent, + ident: ast::Ident, + fd: &ast::FnDecl, + generics: &ast::Generics, + unsafety: ast::Unsafety, + constness: ast::Constness, + defaultness: ast::Defaultness, + abi: abi::Abi, + vis: &ast::Visibility, + span: Span, + block: &ast::Block, + ) -> Option { let mut newline_brace = newline_for_brace(self.config, &generics.where_clause); let context = self.get_context(); let block_snippet = self.snippet(mk_sp(block.span.lo, block.span.hi)); let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || - !context.config.fn_empty_single_line(); - - let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context, - indent, - ident, - fd, - generics, - unsafety, - constness, - defaultness, - abi, - vis, - span, - newline_brace, - has_body, - true)); + !context.config.fn_empty_single_line(); + + let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base( + &context, + indent, + ident, + fd, + generics, + unsafety, + constness, + defaultness, + abi, + vis, + span, + newline_brace, + has_body, + true, + )); if force_newline_brace { newline_brace = true; } else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine && - !result.contains('\n') { + !result.contains('\n') + { newline_brace = false; } @@ -288,30 +299,33 @@ impl<'a> FmtVisitor<'a> { self.single_line_fn(&result, block).or_else(|| Some(result)) } - pub fn rewrite_required_fn(&mut self, - indent: Indent, - ident: ast::Ident, - sig: &ast::MethodSig, - span: Span) - -> Option { + pub fn rewrite_required_fn( + &mut self, + indent: Indent, + ident: ast::Ident, + sig: &ast::MethodSig, + span: Span, + ) -> Option { // Drop semicolon or it will be interpreted as comment. let span = mk_sp(span.lo, span.hi - BytePos(1)); let context = self.get_context(); - let (mut result, _) = try_opt!(rewrite_fn_base(&context, - indent, - ident, - &sig.decl, - &sig.generics, - sig.unsafety, - sig.constness.node, - ast::Defaultness::Final, - sig.abi, - &ast::Visibility::Inherited, - span, - false, - false, - false)); + let (mut result, _) = try_opt!(rewrite_fn_base( + &context, + indent, + ident, + &sig.decl, + &sig.generics, + sig.unsafety, + sig.constness.node, + ast::Defaultness::Final, + sig.abi, + &ast::Visibility::Inherited, + span, + false, + false, + false, + )); // Re-attach semicolon result.push(';'); @@ -327,7 +341,8 @@ impl<'a> FmtVisitor<'a> { let codemap = self.get_context().codemap; if self.config.fn_empty_single_line() && is_empty_block(block, codemap) && - self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { + self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() + { return Some(format!("{}{{}}", fn_str)); } @@ -338,14 +353,17 @@ impl<'a> FmtVisitor<'a> { Some(e) => { let suffix = if semicolon_for_expr(e) { ";" } else { "" }; - e.rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)) - .map(|s| s + suffix) + e.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ).map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } None => { - stmt.rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)) + stmt.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ) } } } else { @@ -364,26 +382,29 @@ impl<'a> FmtVisitor<'a> { None } - pub fn visit_enum(&mut self, - ident: ast::Ident, - vis: &ast::Visibility, - enum_def: &ast::EnumDef, - generics: &ast::Generics, - span: Span) { + pub fn visit_enum( + &mut self, + ident: ast::Ident, + vis: &ast::Visibility, + enum_def: &ast::EnumDef, + generics: &ast::Generics, + span: Span, + ) { self.buffer.push_str(&format_header("enum ", ident, vis)); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); let body_start = span.lo + BytePos(brace_pos as u32 + 1); - let generics_str = format_generics(&self.get_context(), - generics, - "{", - "{", - self.config.item_brace_style(), - enum_def.variants.is_empty(), - self.block_indent, - mk_sp(span.lo, body_start)) - .unwrap(); + let generics_str = format_generics( + &self.get_context(), + generics, + "{", + "{", + self.config.item_brace_style(), + enum_def.variants.is_empty(), + self.block_indent, + mk_sp(span.lo, body_start), + ).unwrap(); self.buffer.push_str(&generics_str); self.last_pos = body_start; @@ -403,19 +424,21 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_unindent(self.config); if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - self.buffer - .push_str(&self.block_indent.to_string(self.config)); + self.buffer.push_str( + &self.block_indent.to_string(self.config), + ); } self.buffer.push_str("}"); self.last_pos = span.hi; } // Format the body of an enum definition - fn format_variant_list(&self, - enum_def: &ast::EnumDef, - body_lo: BytePos, - body_hi: BytePos) - -> Option { + fn format_variant_list( + &self, + enum_def: &ast::EnumDef, + body_lo: BytePos, + body_hi: BytePos, + ) -> Option { if enum_def.variants.is_empty() { return None; } @@ -424,18 +447,20 @@ impl<'a> FmtVisitor<'a> { let indentation = self.block_indent.to_string(self.config); result.push_str(&indentation); - let items = itemize_list(self.codemap, - enum_def.variants.iter(), - "}", - |f| if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo - } else { - f.span.lo - }, - |f| f.span.hi, - |f| self.format_variant(f), - body_lo, - body_hi); + let items = itemize_list( + self.codemap, + enum_def.variants.iter(), + "}", + |f| if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo + } else { + f.span.lo + }, + |f| f.span.hi, + |f| self.format_variant(f), + body_lo, + body_hi, + ); let shape = Shape::indented(self.block_indent, self.config) .sub_width(2) @@ -465,25 +490,23 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let indent = self.block_indent; - let mut result = try_opt!(field - .node - .attrs - .rewrite(&context, Shape::indented(indent, self.config))); + let mut result = try_opt!(field.node.attrs.rewrite( + &context, + Shape::indented(indent, self.config), + )); if !result.is_empty() { let shape = Shape { width: context.config.max_width(), indent: self.block_indent, offset: self.block_indent.alignment, }; - let missing_comment = - rewrite_missing_comment_on_field(&context, - shape, - field.node.attrs[field.node.attrs.len() - 1] - .span - .hi, - field.span.lo, - &mut result) - .unwrap_or(String::new()); + let missing_comment = rewrite_missing_comment_on_field( + &context, + shape, + field.node.attrs[field.node.attrs.len() - 1].span.hi, + field.span.lo, + &mut result, + ).unwrap_or(String::new()); result.push_str(&missing_comment); } @@ -491,15 +514,17 @@ impl<'a> FmtVisitor<'a> { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma - format_struct(&context, - "", - field.node.name, - &ast::Visibility::Inherited, - &field.node.data, - None, - field.span, - indent, - Some(self.config.struct_variant_width())) + format_struct( + &context, + "", + field.node.name, + &ast::Visibility::Inherited, + &field.node.data, + None, + field.span, + indent, + Some(self.config.struct_variant_width()), + ) } ast::VariantData::Unit(..) => { let tag = if let Some(ref expr) = field.node.disr_expr { @@ -508,9 +533,11 @@ impl<'a> FmtVisitor<'a> { field.node.name.to_string() }; - wrap_str(tag, - self.config.max_width(), - Shape::indented(indent, self.config)) + wrap_str( + tag, + self.config.max_width(), + Shape::indented(indent, self.config), + ) } }; @@ -626,18 +653,21 @@ pub fn format_impl(context: &RewriteContext, } } -fn is_impl_single_line(context: &RewriteContext, - items: &[ImplItem], - result: &str, - where_clause_str: &str, - item: &ast::Item) - -> Option { +fn is_impl_single_line( + context: &RewriteContext, + items: &[ImplItem], + result: &str, + where_clause_str: &str, + item: &ast::Item, +) -> Option { let snippet = context.snippet(item.span); let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; - Some(context.config.impl_empty_single_line() && items.is_empty() && - result.len() + where_clause_str.len() <= context.config.max_width() && - !contains_comment(&snippet[open_pos..])) + Some( + context.config.impl_empty_single_line() && items.is_empty() && + result.len() + where_clause_str.len() <= context.config.max_width() && + !contains_comment(&snippet[open_pos..]), + ) } fn format_impl_ref_and_type(context: &RewriteContext, @@ -645,12 +675,13 @@ fn format_impl_ref_and_type(context: &RewriteContext, offset: Indent) -> Option { if let ast::ItemKind::Impl(unsafety, - polarity, - _, - ref generics, - ref trait_ref, - ref self_ty, - _) = item.node { + polarity, + _, + ref generics, + ref trait_ref, + ref self_ty, + _) = item.node + { let mut result = String::new(); result.push_str(&format_visibility(&item.vis)); @@ -802,37 +833,44 @@ pub fn format_struct(context: &RewriteContext, match *struct_def { ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)), ast::VariantData::Tuple(ref fields, _) => { - format_tuple_struct(context, - item_name, - ident, - vis, - fields, - generics, - span, - offset) + format_tuple_struct( + context, + item_name, + ident, + vis, + fields, + generics, + span, + offset, + ) } ast::VariantData::Struct(ref fields, _) => { - format_struct_struct(context, - item_name, - ident, - vis, - fields, - generics, - span, - offset, - one_line_width) + format_struct_struct( + context, + item_name, + ident, + vis, + fields, + generics, + span, + offset, + one_line_width, + ) } } } pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { if let ast::ItemKind::Trait(unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node { + item.node + { let mut result = String::new(); - let header = format!("{}{}trait {}", - format_visibility(&item.vis), - format_unsafety(unsafety), - item.ident); + let header = format!( + "{}{}trait {}", + format_visibility(&item.vis), + format_unsafety(unsafety), + item.ident + ); result.push_str(&header); @@ -843,14 +881,16 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo))); result.push_str(&generics_str); - let trait_bound_str = - try_opt!(rewrite_trait_bounds(context, - type_param_bounds, - Shape::legacy(context.config.max_width(), offset))); + let trait_bound_str = try_opt!(rewrite_trait_bounds( + context, + type_param_bounds, + Shape::legacy(context.config.max_width(), offset), + )); // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line if offset.width() + last_line_width(&result) + trait_bound_str.len() > - context.config.comment_width() { + context.config.comment_width() + { result.push('\n'); let trait_indent = offset.block_only().block_indent(context.config); result.push_str(&trait_indent.to_string(context.config)); @@ -859,38 +899,39 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); - let where_density = - if (context.config.where_density() == Density::Compressed && - (!result.contains('\n') || - context.config.fn_args_layout() == IndentStyle::Block)) || - (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) || - (context.config.where_density() == Density::CompressedIfEmpty && !has_body && - !result.contains('\n')) { - Density::Compressed - } else { - Density::Tall - }; + let where_density = if (context.config.where_density() == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout() == IndentStyle::Block)) || + (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) || + (context.config.where_density() == Density::CompressedIfEmpty && !has_body && + !result.contains('\n')) + { + Density::Compressed + } else { + Density::Tall + }; - let where_budget = try_opt!(context - .config - .max_width() - .checked_sub(last_line_width(&result))); - let where_clause_str = try_opt!(rewrite_where_clause(context, - &generics.where_clause, - context.config.item_brace_style(), - Shape::legacy(where_budget, - offset.block_only()), - where_density, - "{", - !has_body, - trait_bound_str.is_empty() && - last_line_width(&generics_str) == 1, - None)); + let where_budget = try_opt!(context.config.max_width().checked_sub( + last_line_width(&result), + )); + let where_clause_str = try_opt!(rewrite_where_clause( + context, + &generics.where_clause, + context.config.item_brace_style(), + Shape::legacy(where_budget, offset.block_only()), + where_density, + "{", + !has_body, + trait_bound_str.is_empty() && + last_line_width(&generics_str) == 1, + None, + )); // If the where clause cannot fit on the same line, // put the where clause on a new line if !where_clause_str.contains('\n') && - last_line_width(&result) + where_clause_str.len() + offset.width() > - context.config.comment_width() { + last_line_width(&result) + where_clause_str.len() + offset.width() > + context.config.comment_width() + { result.push('\n'); let width = offset.block_indent + context.config.tab_spaces() - 1; let where_indent = Indent::new(0, width); @@ -906,7 +947,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if !where_clause_str.is_empty() && - (!trait_items.is_empty() || result.contains('\n')) { + (!trait_items.is_empty() || result.contains('\n')) + { result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -953,16 +995,17 @@ fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) format!("{};", format_header(item_name, ident, vis)) } -fn format_struct_struct(context: &RewriteContext, - item_name: &str, - ident: ast::Ident, - vis: &ast::Visibility, - fields: &[ast::StructField], - generics: Option<&ast::Generics>, - span: Span, - offset: Indent, - one_line_width: Option) - -> Option { +fn format_struct_struct( + context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: &ast::Visibility, + fields: &[ast::StructField], + generics: Option<&ast::Generics>, + span: Span, + offset: Indent, + one_line_width: Option, +) -> Option { let mut result = String::with_capacity(1024); let header_str = format_header(item_name, ident, vis); @@ -972,18 +1015,21 @@ fn format_struct_struct(context: &RewriteContext, let generics_str = match generics { Some(g) => { - try_opt!(format_generics(context, - g, - "{", - "{", - context.config.item_brace_style(), - fields.is_empty(), - offset, - mk_sp(span.lo, body_lo))) + try_opt!(format_generics( + context, + g, + "{", + "{", + context.config.item_brace_style(), + fields.is_empty(), + offset, + mk_sp(span.lo, body_lo), + )) } None => { if context.config.item_brace_style() == BraceStyle::AlwaysNextLine && - !fields.is_empty() { + !fields.is_empty() + { format!("\n{}{{", offset.block_only().to_string(context.config)) } else { " {".to_owned() @@ -1010,28 +1056,27 @@ fn format_struct_struct(context: &RewriteContext, let item_indent = offset.block_indent(context.config); // 1 = "," - let item_budget = try_opt!(context - .config - .max_width() - .checked_sub(item_indent.width() + 1)); - - let items = - itemize_list(context.codemap, - fields.iter(), - "}", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), - context.codemap.span_after(span, "{"), - span.hi) - .collect::>(); + let item_budget = try_opt!(context.config.max_width().checked_sub( + item_indent.width() + 1, + )); + + let items = itemize_list( + context.codemap, + fields.iter(), + "}", + |field| { + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.ty.span.hi, + |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), + context.codemap.span_after(span, "{"), + span.hi, + ).collect::>(); // 1 = , let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1; @@ -1052,25 +1097,28 @@ fn format_struct_struct(context: &RewriteContext, if one_line_width.is_some() && !items_str.contains('\n') { Some(format!("{} {} }}", result, items_str)) } else { - Some(format!("{}\n{}{}\n{}}}", - result, - offset - .block_indent(context.config) - .to_string(context.config), - items_str, - offset.to_string(context.config))) + Some(format!( + "{}\n{}{}\n{}}}", + result, + offset.block_indent(context.config).to_string( + context.config, + ), + items_str, + offset.to_string(context.config) + )) } } -fn format_tuple_struct(context: &RewriteContext, - item_name: &str, - ident: ast::Ident, - vis: &ast::Visibility, - fields: &[ast::StructField], - generics: Option<&ast::Generics>, - span: Span, - offset: Indent) - -> Option { +fn format_tuple_struct( + context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: &ast::Visibility, + fields: &[ast::StructField], + generics: Option<&ast::Generics>, + span: Span, + offset: Indent, +) -> Option { let mut result = String::with_capacity(1024); let header_str = format_header(item_name, ident, vis); @@ -1089,19 +1137,20 @@ fn format_tuple_struct(context: &RewriteContext, let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = try_opt!(context - .config - .max_width() - .checked_sub(last_line_width(&result))); - try_opt!(rewrite_where_clause(context, - &generics.where_clause, - context.config.item_brace_style(), - Shape::legacy(where_budget, offset.block_only()), - Density::Compressed, - ";", - true, - false, - None)) + let where_budget = try_opt!(context.config.max_width().checked_sub( + last_line_width(&result), + )); + try_opt!(rewrite_where_clause( + context, + &generics.where_clause, + context.config.item_brace_style(), + Shape::legacy(where_budget, offset.block_only()), + Density::Compressed, + ";", + true, + false, + None, + )) } None => "".to_owned(), }; @@ -1123,44 +1172,51 @@ fn format_tuple_struct(context: &RewriteContext, let (tactic, item_indent) = match context.config.fn_args_layout() { IndentStyle::Visual => { // 1 = `(` - (ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1) + ( + ListTactic::HorizontalVertical, + offset.block_only() + result.len() + 1, + ) } IndentStyle::Block => { - (ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config)) + ( + ListTactic::HorizontalVertical, + offset.block_only().block_indent(&context.config), + ) } }; // 3 = `();` - let item_budget = try_opt!(context - .config - .max_width() - .checked_sub(item_indent.width() + 3)); - - let items = - itemize_list(context.codemap, - fields.iter(), - ")", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), - context.codemap.span_after(span, "("), - span.hi); - let body_budget = - try_opt!(context - .config - .max_width() - .checked_sub(offset.block_only().width() + result.len() + 3)); - let body = try_opt!(list_helper(items, - // TODO budget is wrong in block case - Shape::legacy(body_budget, item_indent), - context.config, - tactic)); + let item_budget = try_opt!(context.config.max_width().checked_sub( + item_indent.width() + 3, + )); + + let items = itemize_list( + context.codemap, + fields.iter(), + ")", + |field| { + // Include attributes and doc comments, if present + if !field.attrs.is_empty() { + field.attrs[0].span.lo + } else { + field.span.lo + } + }, + |field| field.ty.span.hi, + |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), + context.codemap.span_after(span, "("), + span.hi, + ); + let body_budget = try_opt!(context.config.max_width().checked_sub( + offset.block_only().width() + + result.len() + 3, + )); + let body = try_opt!(list_helper( + items, + // TODO budget is wrong in block case + Shape::legacy(body_budget, item_indent), + context.config, + tactic, + )); if context.config.fn_args_layout() == IndentStyle::Visual || !body.contains('\n') { result.push('('); @@ -1185,28 +1241,30 @@ fn format_tuple_struct(context: &RewriteContext, } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && - (result.contains('\n') || - offset.block_indent + result.len() + where_clause_str.len() + 1 > - context.config.max_width()) { + (result.contains('\n') || + offset.block_indent + result.len() + where_clause_str.len() + 1 > + context.config.max_width()) + { // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); result.push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) - .to_string(context.config)); + .to_string(context.config)); } result.push_str(&where_clause_str); Some(result) } -pub fn rewrite_type_alias(context: &RewriteContext, - indent: Indent, - ident: ast::Ident, - ty: &ast::Ty, - generics: &ast::Generics, - vis: &ast::Visibility, - span: Span) - -> Option { +pub fn rewrite_type_alias( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + ty: &ast::Ty, + generics: &ast::Generics, + vis: &ast::Visibility, + span: Span, +) -> Option { let mut result = String::new(); result.push_str(&format_visibility(vis)); @@ -1219,19 +1277,20 @@ pub fn rewrite_type_alias(context: &RewriteContext, let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = try_opt!(context - .config - .max_width() - .checked_sub(last_line_width(&result))); - let where_clause_str = try_opt!(rewrite_where_clause(context, - &generics.where_clause, - context.config.item_brace_style(), - Shape::legacy(where_budget, indent), - context.config.where_density(), - "=", - true, - true, - Some(span.hi))); + let where_budget = try_opt!(context.config.max_width().checked_sub( + last_line_width(&result), + )); + let where_clause_str = try_opt!(rewrite_where_clause( + context, + &generics.where_clause, + context.config.item_brace_style(), + Shape::legacy(where_budget, indent), + context.config.where_density(), + "=", + true, + true, + Some(span.hi), + )); result.push_str(&where_clause_str); result.push_str(" = "); @@ -1255,10 +1314,9 @@ pub fn rewrite_type_alias(context: &RewriteContext, let type_indent = indent.block_indent(context.config); result.push('\n'); result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context - .config - .max_width() - .checked_sub(type_indent.width() + ";".len())); + let budget = try_opt!(context.config.max_width().checked_sub( + type_indent.width() + ";".len(), + )); ty.rewrite(context, Shape::legacy(budget, type_indent)) }) ); @@ -1268,24 +1326,27 @@ pub fn rewrite_type_alias(context: &RewriteContext, } fn type_annotation_spacing(config: &Config) -> (&str, &str) { - (if config.space_before_type_annotation() { - " " - } else { - "" - }, - if config.space_after_type_annotation_colon() { - " " - } else { - "" - }) + ( + if config.space_before_type_annotation() { + " " + } else { + "" + }, + if config.space_after_type_annotation_colon() { + " " + } else { + "" + }, + ) } -fn rewrite_missing_comment_on_field(context: &RewriteContext, - shape: Shape, - lo: BytePos, - hi: BytePos, - result: &mut String) - -> Option { +fn rewrite_missing_comment_on_field( + context: &RewriteContext, + shape: Shape, + lo: BytePos, + hi: BytePos, + result: &mut String, +) -> Option { let possibly_comment_snippet = context.snippet(mk_sp(lo, hi)); let newline_index = possibly_comment_snippet.find('\n'); let comment_index = possibly_comment_snippet.find('/'); @@ -1300,8 +1361,9 @@ fn rewrite_missing_comment_on_field(context: &RewriteContext, if trimmed.is_empty() { None } else { - rewrite_comment(trimmed, false, shape, context.config) - .map(|s| format!("{}\n{}", s, shape.indent.to_string(context.config))) + rewrite_comment(trimmed, false, shape, context.config).map(|s| { + format!("{}\n{}", s, shape.indent.to_string(context.config)) + }) } } @@ -1314,17 +1376,19 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); - let mut attr_str = try_opt!(self.attrs.rewrite(context, - Shape::indented(shape.indent, - context.config))); + let mut attr_str = try_opt!(self.attrs.rewrite( + context, + Shape::indented(shape.indent, context.config), + )); // Try format missing comments after attributes let missing_comment = if !self.attrs.is_empty() { - rewrite_missing_comment_on_field(context, - shape, - self.attrs[self.attrs.len() - 1].span.hi, - self.span.lo, - &mut attr_str) - .unwrap_or(String::new()) + rewrite_missing_comment_on_field( + context, + shape, + self.attrs[self.attrs.len() - 1].span.hi, + self.span.lo, + &mut attr_str, + ).unwrap_or(String::new()) } else { String::new() }; @@ -1332,38 +1396,45 @@ impl Rewrite for ast::StructField { let type_annotation_spacing = type_annotation_spacing(context.config); let mut result = match name { Some(name) => { - format!("{}{}{}{}{}:", - attr_str, - missing_comment, - vis, - name, - type_annotation_spacing.0) + format!( + "{}{}{}{}{}:", + attr_str, + missing_comment, + vis, + name, + type_annotation_spacing.0 + ) } None => format!("{}{}{}", attr_str, missing_comment, vis), }; let type_offset = shape.indent.block_indent(context.config); let rewrite_type_in_next_line = || { - self.ty - .rewrite(context, Shape::indented(type_offset, context.config)) + self.ty.rewrite( + context, + Shape::indented(type_offset, context.config), + ) }; let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); let budget = try_opt!(shape.width.checked_sub(last_line_width)); - let ty_rewritten = - self.ty.rewrite(context, - Shape::legacy(budget, shape.indent + last_line_width)); + let ty_rewritten = self.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + last_line_width), + ); match ty_rewritten { Some(ref ty) if ty.contains('\n') => { let new_ty = rewrite_type_in_next_line(); match new_ty { Some(ref new_ty) if !new_ty.contains('\n') && - new_ty.len() + type_offset.width() <= - context.config.max_width() => { - Some(format!("{}\n{}{}", - result, - type_offset.to_string(&context.config), - &new_ty)) + new_ty.len() + type_offset.width() <= + context.config.max_width() => { + Some(format!( + "{}\n{}{}", + result, + type_offset.to_string(&context.config), + &new_ty + )) } _ => { if name.is_some() { @@ -1381,59 +1452,69 @@ impl Rewrite for ast::StructField { } None => { let ty = try_opt!(rewrite_type_in_next_line()); - Some(format!("{}\n{}{}", - result, - type_offset.to_string(&context.config), - &ty)) + Some(format!( + "{}\n{}{}", + result, + type_offset.to_string(&context.config), + &ty + )) } } } } -pub fn rewrite_static(prefix: &str, - vis: &ast::Visibility, - ident: ast::Ident, - ty: &ast::Ty, - mutability: ast::Mutability, - expr_opt: Option<&ptr::P>, - offset: Indent, - span: Span, - context: &RewriteContext) - -> Option { +pub fn rewrite_static( + prefix: &str, + vis: &ast::Visibility, + ident: ast::Ident, + ty: &ast::Ty, + mutability: ast::Mutability, + expr_opt: Option<&ptr::P>, + offset: Indent, + span: Span, + context: &RewriteContext, +) -> Option { let type_annotation_spacing = type_annotation_spacing(context.config); - let prefix = format!("{}{} {}{}{}:{}", - format_visibility(vis), - prefix, - format_mutability(mutability), - ident, - type_annotation_spacing.0, - type_annotation_spacing.1); + let prefix = format!( + "{}{} {}{}{}:{}", + format_visibility(vis), + prefix, + format_mutability(mutability), + ident, + type_annotation_spacing.0, + type_annotation_spacing.1 + ); // 2 = " =".len() - let ty_str = try_opt!(ty.rewrite(context, - Shape::legacy(context.config.max_width() - - offset.block_indent - - prefix.len() - - 2, - offset.block_only()))); + let ty_str = try_opt!(ty.rewrite( + context, + Shape::legacy( + context.config.max_width() - offset.block_indent - + prefix.len() - 2, + offset.block_only(), + ), + )); if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; let remaining_width = context.config.max_width() - offset.block_indent - 1; - rewrite_assign_rhs(context, - lhs, - expr, - Shape::legacy(remaining_width, offset.block_only())) - .and_then(|res| { - recover_comment_removed(res, - span, - context, - Shape { - width: context.config.max_width(), - indent: offset, - offset: offset.alignment, - }) - }) + rewrite_assign_rhs( + context, + lhs, + expr, + Shape::legacy(remaining_width, offset.block_only()), + ).and_then(|res| { + recover_comment_removed( + res, + span, + context, + Shape { + width: context.config.max_width(), + indent: offset, + offset: offset.alignment, + }, + ) + }) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { let lhs = format!("{}{};", prefix, ty_str); @@ -1441,12 +1522,13 @@ pub fn rewrite_static(prefix: &str, } } -pub fn rewrite_associated_type(ident: ast::Ident, - ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, - context: &RewriteContext, - indent: Indent) - -> Option { +pub fn rewrite_associated_type( + ident: ast::Ident, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent, +) -> Option { let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { @@ -1466,27 +1548,35 @@ pub fn rewrite_associated_type(ident: ast::Ident, }; if let Some(ty) = ty_opt { - let ty_str = try_opt!(ty.rewrite(context, - Shape::legacy(context.config.max_width() - - indent.block_indent - - prefix.len() - - 2, - indent.block_only()))); + let ty_str = try_opt!(ty.rewrite( + context, + Shape::legacy( + context.config.max_width() - indent.block_indent - + prefix.len() - 2, + indent.block_only(), + ), + )); Some(format!("{} = {};", prefix, ty_str)) } else { Some(format!("{}{};", prefix, type_bounds_str)) } } -pub fn rewrite_associated_impl_type(ident: ast::Ident, - defaultness: ast::Defaultness, - ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, - context: &RewriteContext, - indent: Indent) - -> Option { - let result = - try_opt!(rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)); +pub fn rewrite_associated_impl_type( + ident: ast::Ident, + defaultness: ast::Defaultness, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent, +) -> Option { + let result = try_opt!(rewrite_associated_type( + ident, + ty_opt, + ty_param_bounds_opt, + context, + indent, + )); match defaultness { ast::Defaultness::Default => Some(format!("default {}", result)), @@ -1510,8 +1600,10 @@ impl Rewrite for ast::FunctionRetTy { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!(self.pat.rewrite(context, - Shape::legacy(shape.width, shape.indent))); + let mut result = try_opt!(self.pat.rewrite( + context, + Shape::legacy(shape.width, shape.indent), + )); if self.ty.node != ast::TyKind::Infer { if context.config.space_before_type_annotation() { @@ -1522,9 +1614,10 @@ impl Rewrite for ast::Arg { result.push_str(" "); } let max_width = try_opt!(shape.width.checked_sub(result.len())); - let ty_str = try_opt!(self.ty.rewrite(context, - Shape::legacy(max_width, - shape.indent + result.len()))); + let ty_str = try_opt!(self.ty.rewrite( + context, + Shape::legacy(max_width, shape.indent + result.len()), + )); result.push_str(&ty_str); } @@ -1535,18 +1628,20 @@ impl Rewrite for ast::Arg { } } -fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, - args: &[ast::Arg], - context: &RewriteContext) - -> Option { +fn rewrite_explicit_self( + explicit_self: &ast::ExplicitSelf, + args: &[ast::Arg], + context: &RewriteContext, +) -> Option { match explicit_self.node { ast::SelfKind::Region(lt, m) => { let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = try_opt!(l.rewrite(context, - Shape::legacy(usize::max_value(), - Indent::empty()))); + let lifetime_str = try_opt!(l.rewrite( + context, + Shape::legacy(usize::max_value(), Indent::empty()), + )); Some(format!("&{} {}self", lifetime_str, mut_str)) } None => Some(format!("&{}self", mut_str)), @@ -1556,10 +1651,16 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf, assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); - let type_str = try_opt!(ty.rewrite(context, - Shape::legacy(usize::max_value(), Indent::empty()))); - - Some(format!("{}self: {}", format_mutability(mutability), type_str)) + let type_str = try_opt!(ty.rewrite( + context, + Shape::legacy(usize::max_value(), Indent::empty()), + )); + + Some(format!( + "{}self: {}", + format_mutability(mutability), + type_str + )) } ast::SelfKind::Value(_) => { assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); @@ -1640,21 +1741,22 @@ fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { } // Return type is (result, force_new_line_for_brace) -fn rewrite_fn_base(context: &RewriteContext, - indent: Indent, - ident: ast::Ident, - fd: &ast::FnDecl, - generics: &ast::Generics, - unsafety: ast::Unsafety, - constness: ast::Constness, - defaultness: ast::Defaultness, - abi: abi::Abi, - vis: &ast::Visibility, - span: Span, - newline_brace: bool, - has_body: bool, - has_braces: bool) - -> Option<(String, bool)> { +fn rewrite_fn_base( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + fd: &ast::FnDecl, + generics: &ast::Generics, + unsafety: ast::Unsafety, + constness: ast::Constness, + defaultness: ast::Defaultness, + abi: abi::Abi, + vis: &ast::Visibility, + span: Span, + newline_brace: bool, + has_body: bool, + has_braces: bool, +) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; let where_clause = &generics.where_clause; @@ -1674,7 +1776,10 @@ fn rewrite_fn_base(context: &RewriteContext, result.push_str(::utils::format_unsafety(unsafety)); if abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi(abi, context.config.force_explicit_abi())); + result.push_str(&::utils::format_abi( + abi, + context.config.force_explicit_abi(), + )); } // fn foo @@ -1687,37 +1792,43 @@ fn rewrite_fn_base(context: &RewriteContext, let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let snuggle_angle_bracket = generics_str - .lines() - .last() - .map_or(false, |l| l.trim_left().len() == 1); + let snuggle_angle_bracket = generics_str.lines().last().map_or( + false, + |l| l.trim_left().len() == 1, + ); // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. - let ret_str = try_opt!(fd.output - .rewrite(&context, Shape::indented(indent, context.config))); + let ret_str = try_opt!(fd.output.rewrite( + &context, + Shape::indented(indent, context.config), + )); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; // Args. let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = - try_opt!(compute_budgets_for_args(context, - &result, - indent, - ret_str_len, - newline_brace, - has_braces)); + try_opt!(compute_budgets_for_args( + context, + &result, + indent, + ret_str_len, + newline_brace, + has_braces, + )); if context.config.fn_args_layout() == IndentStyle::Block { arg_indent = indent.block_indent(context.config); multi_line_budget = context.config.max_width() - arg_indent.width(); } - debug!("rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", - one_line_budget, - multi_line_budget, - arg_indent); + debug!( + "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", + one_line_budget, + multi_line_budget, + arg_indent + ); // Check if vertical layout was forced. if one_line_budget == 0 { @@ -1751,25 +1862,29 @@ fn rewrite_fn_base(context: &RewriteContext, } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics - .ty_params - .last() - .map_or(span.lo, |tp| end_typaram(tp)); - let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("), - span_for_return(&fd.output).lo); - let arg_str = try_opt!(rewrite_args(context, - &fd.inputs, - fd.get_self().as_ref(), - one_line_budget, - multi_line_budget, - indent, - arg_indent, - args_span, - fd.variadic, - generics_str.contains('\n'))); + let args_start = generics.ty_params.last().map_or( + span.lo, + |tp| end_typaram(tp), + ); + let args_span = mk_sp( + context.codemap.span_after(mk_sp(args_start, span.hi), "("), + span_for_return(&fd.output).lo, + ); + let arg_str = try_opt!(rewrite_args( + context, + &fd.inputs, + fd.get_self().as_ref(), + one_line_budget, + multi_line_budget, + indent, + arg_indent, + args_span, + fd.variadic, + generics_str.contains('\n'), + )); let multi_line_arg_str = arg_str.contains('\n') || - arg_str.chars().last().map_or(false, |c| c == ','); + arg_str.chars().last().map_or(false, |c| c == ','); let put_args_in_block = match context.config.fn_args_layout() { IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'), @@ -1792,10 +1907,10 @@ fn rewrite_fn_base(context: &RewriteContext, } // If the last line of args contains comment, we cannot put the closing paren // on the same line. - if arg_str - .lines() - .last() - .map_or(false, |last_line| last_line.contains("//")) { + if arg_str.lines().last().map_or(false, |last_line| { + last_line.contains("//") + }) + { args_last_line_contains_comment = true; result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); @@ -1824,7 +1939,7 @@ fn rewrite_fn_base(context: &RewriteContext, let overlong_sig = sig_length > context.config.max_width(); (!args_last_line_contains_comment) && - (result.contains('\n') || multi_line_ret_str || overlong_sig) + (result.contains('\n') || multi_line_ret_str || overlong_sig) } }; let ret_indent = if ret_should_indent { @@ -1852,8 +1967,10 @@ fn rewrite_fn_base(context: &RewriteContext, if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = try_opt!(fd.output.rewrite(context, - Shape::indented(ret_indent, context.config))); + let ret_str = try_opt!(fd.output.rewrite( + context, + Shape::indented(ret_indent, context.config), + )); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -1865,20 +1982,21 @@ fn rewrite_fn_base(context: &RewriteContext, let snippet_hi = span.hi; let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); // Try to preserve the layout of the original snippet. - let original_starts_with_newline = - snippet - .find(|c| c != ' ') - .map_or(false, |i| snippet[i..].starts_with('\n')); - let original_ends_with_newline = snippet - .rfind(|c| c != ' ') - .map_or(false, |i| snippet[i..].ends_with('\n')); + let original_starts_with_newline = snippet.find(|c| c != ' ').map_or(false, |i| { + snippet[i..].starts_with('\n') + }); + let original_ends_with_newline = snippet.rfind(|c| c != ' ').map_or(false, |i| { + snippet[i..].ends_with('\n') + }); let snippet = snippet.trim(); if !snippet.is_empty() { - result.push(if original_starts_with_newline { - '\n' - } else { - ' ' - }); + result.push( + if original_starts_with_newline { + '\n' + } else { + ' ' + }, + ); result.push_str(snippet); if original_ends_with_newline { force_new_line_for_brace = true; @@ -1898,20 +2016,22 @@ fn rewrite_fn_base(context: &RewriteContext, } || (put_args_in_block && ret_str.is_empty()); if where_clause.predicates.len() == 1 && should_compress_where { - let budget = try_opt!(context - .config - .max_width() - .checked_sub(last_line_width(&result))); + let budget = try_opt!(context.config.max_width().checked_sub( + last_line_width(&result), + )); if let Some(where_clause_str) = - rewrite_where_clause(context, - where_clause, - context.config.fn_brace_style(), - Shape::legacy(budget, indent), - Density::Compressed, - "{", - !has_braces, - put_args_in_block && ret_str.is_empty(), - Some(span.hi)) { + rewrite_where_clause( + context, + where_clause, + context.config.fn_brace_style(), + Shape::legacy(budget, indent), + Density::Compressed, + "{", + !has_braces, + put_args_in_block && ret_str.is_empty(), + Some(span.hi), + ) + { if !where_clause_str.contains('\n') { if last_line_width(&result) + where_clause_str.len() > context.config.max_width() { result.push('\n'); @@ -1925,15 +2045,17 @@ fn rewrite_fn_base(context: &RewriteContext, } } - let where_clause_str = try_opt!(rewrite_where_clause(context, - where_clause, - context.config.fn_brace_style(), - Shape::indented(indent, context.config), - Density::Tall, - "{", - !has_braces, - put_args_in_block && ret_str.is_empty(), - Some(span.hi))); + let where_clause_str = try_opt!(rewrite_where_clause( + context, + where_clause, + context.config.fn_brace_style(), + Shape::indented(indent, context.config), + Density::Tall, + "{", + !has_braces, + put_args_in_block && ret_str.is_empty(), + Some(span.hi), + )); result.push_str(&where_clause_str); @@ -1945,27 +2067,33 @@ fn last_line_contains_single_line_comment(s: &str) -> bool { s.lines().last().map_or(false, |l| l.contains("//")) } -fn rewrite_args(context: &RewriteContext, - args: &[ast::Arg], - explicit_self: Option<&ast::ExplicitSelf>, - one_line_budget: usize, - multi_line_budget: usize, - indent: Indent, - arg_indent: Indent, - span: Span, - variadic: bool, - generics_str_contains_newline: bool) - -> Option { - let mut arg_item_strs = - try_opt!(args.iter() - .map(|arg| arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent))) - .collect::>>()); +fn rewrite_args( + context: &RewriteContext, + args: &[ast::Arg], + explicit_self: Option<&ast::ExplicitSelf>, + one_line_budget: usize, + multi_line_budget: usize, + indent: Indent, + arg_indent: Indent, + span: Span, + variadic: bool, + generics_str_contains_newline: bool, +) -> Option { + let mut arg_item_strs = try_opt!( + args.iter() + .map(|arg| { + arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)) + }) + .collect::>>() + ); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. let min_args = explicit_self - .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) + .and_then(|explicit_self| { + rewrite_explicit_self(explicit_self, args, context) + }) .map_or(1, |self_str| { arg_item_strs[0] = self_str; 2 @@ -2008,33 +2136,34 @@ fn rewrite_args(context: &RewriteContext, None }; - let more_items = itemize_list(context.codemap, - args[min_args - 1..] - .iter() - .map(ArgumentKind::Regular) - .chain(variadic_arg), - ")", - |arg| match *arg { - ArgumentKind::Regular(arg) => span_lo_for_arg(arg), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => Some("...".to_owned()), - }, - comment_span_start, - span.hi); + let more_items = itemize_list( + context.codemap, + args[min_args - 1..] + .iter() + .map(ArgumentKind::Regular) + .chain(variadic_arg), + ")", + |arg| match *arg { + ArgumentKind::Regular(arg) => span_lo_for_arg(arg), + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(arg) => arg.ty.span.hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(..) => None, + ArgumentKind::Variadic(..) => Some("...".to_owned()), + }, + comment_span_start, + span.hi, + ); arg_items.extend(more_items); } let fits_in_one_line = !generics_str_contains_newline && - (arg_items.len() == 0 || - arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + (arg_items.len() == 0 || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { item.item = Some(arg); @@ -2048,10 +2177,18 @@ fn rewrite_args(context: &RewriteContext, let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout() { IndentStyle::Block if fits_in_one_line => { - (indent.block_indent(context.config), SeparatorTactic::Never, true) + ( + indent.block_indent(context.config), + SeparatorTactic::Never, + true, + ) } IndentStyle::Block => { - (indent.block_indent(context.config), SeparatorTactic::Vertical, true) + ( + indent.block_indent(context.config), + SeparatorTactic::Vertical, + true, + ) } IndentStyle::Visual if last_line_ends_with_comment => { (arg_indent, SeparatorTactic::Vertical, true) @@ -2059,9 +2196,11 @@ fn rewrite_args(context: &RewriteContext, IndentStyle::Visual => (arg_indent, SeparatorTactic::Never, false), }; - let tactic = definitive_tactic(&arg_items, - context.config.fn_args_density().to_list_tactic(), - one_line_budget); + let tactic = definitive_tactic( + &arg_items, + context.config.fn_args_density().to_list_tactic(), + one_line_budget, + ); let budget = match tactic { DefinitiveListTactic::Horizontal => one_line_budget, _ => multi_line_budget, @@ -2093,18 +2232,21 @@ fn arg_has_pattern(arg: &ast::Arg) -> bool { } } -fn compute_budgets_for_args(context: &RewriteContext, - result: &str, - indent: Indent, - ret_str_len: usize, - newline_brace: bool, - has_braces: bool) - -> Option<((usize, usize, Indent))> { - debug!("compute_budgets_for_args {} {:?}, {}, {}", - result.len(), - indent, - ret_str_len, - newline_brace); +fn compute_budgets_for_args( + context: &RewriteContext, + result: &str, + indent: Indent, + ret_str_len: usize, + newline_brace: bool, + has_braces: bool, +) -> Option<((usize, usize, Indent))> { + debug!( + "compute_budgets_for_args {} {:?}, {}, {}", + result.len(), + indent, + ret_str_len, + newline_brace + ); // Try keeping everything on the same line. if !result.contains('\n') { // 2 = `()`, 3 = `() `, space is before ret_string. @@ -2128,11 +2270,14 @@ fn compute_budgets_for_args(context: &RewriteContext, if one_line_budget > 0 { // 4 = "() {".len() let multi_line_overhead = indent.width() + result.len() + - if newline_brace { 2 } else { 4 }; - let multi_line_budget = - try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); - - return Some((one_line_budget, multi_line_budget, indent + result.len() + 1)); + if newline_brace { 2 } else { 4 }; + let multi_line_budget = try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); + + return Some(( + one_line_budget, + multi_line_budget, + indent + result.len() + 1, + )); } } @@ -2182,13 +2327,13 @@ fn rewrite_generics_inner(context: &RewriteContext, // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - } else { - l.bounds[l.bounds.len() - 1].span.hi - }; - mk_sp(l.lifetime.span.lo, hi) - }); + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + } else { + l.bounds[l.bounds.len() - 1].span.hi + }; + mk_sp(l.lifetime.span.lo, hi) + }); let ty_spans = tys.iter().map(span_for_ty_param); let items = itemize_list(context.codemap, @@ -2260,10 +2405,11 @@ pub fn wrap_generics_with_angle_brackets(context: &RewriteContext, } } -fn rewrite_trait_bounds(context: &RewriteContext, - type_param_bounds: &ast::TyParamBounds, - shape: Shape) - -> Option { +fn rewrite_trait_bounds( + context: &RewriteContext, + type_param_bounds: &ast::TyParamBounds, + shape: Shape, +) -> Option { let bounds: &[_] = type_param_bounds; if bounds.is_empty() { @@ -2276,15 +2422,16 @@ fn rewrite_trait_bounds(context: &RewriteContext, Some(format!(": {}", join_bounds(context, shape, &bound_str))) } -fn rewrite_where_clause_rfc_style(context: &RewriteContext, - where_clause: &ast::WhereClause, - shape: Shape, - terminator: &str, - suppress_comma: bool, - // where clause can be kept on the current line. - snuggle: bool, - span_end: Option) - -> Option { +fn rewrite_where_clause_rfc_style( + context: &RewriteContext, + where_clause: &ast::WhereClause, + shape: Shape, + terminator: &str, + suppress_comma: bool, + // where clause can be kept on the current line. + snuggle: bool, + span_end: Option, +) -> Option { let block_shape = shape.block(); let starting_newline = if snuggle { @@ -2325,34 +2472,39 @@ fn rewrite_where_clause_rfc_style(context: &RewriteContext, }; let preds_str = try_opt!(write_list(items, &fmt)); - Some(format!("{}where\n{}{}", - starting_newline, - clause_shape.indent.to_string(context.config), - preds_str)) + Some(format!( + "{}where\n{}{}", + starting_newline, + clause_shape.indent.to_string(context.config), + preds_str + )) } -fn rewrite_where_clause(context: &RewriteContext, - where_clause: &ast::WhereClause, - brace_style: BraceStyle, - shape: Shape, - density: Density, - terminator: &str, - suppress_comma: bool, - snuggle: bool, - span_end: Option) - -> Option { +fn rewrite_where_clause( + context: &RewriteContext, + where_clause: &ast::WhereClause, + brace_style: BraceStyle, + shape: Shape, + density: Density, + terminator: &str, + suppress_comma: bool, + snuggle: bool, + span_end: Option, +) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); } if context.config.where_style() == Style::Rfc { - return rewrite_where_clause_rfc_style(context, - where_clause, - shape, - terminator, - suppress_comma, - snuggle, - span_end); + return rewrite_where_clause_rfc_style( + context, + where_clause, + shape, + terminator, + suppress_comma, + snuggle, + span_end, + ); } let extra_indent = Indent::new(context.config.tab_spaces(), 0); @@ -2372,14 +2524,16 @@ fn rewrite_where_clause(context: &RewriteContext, let len = where_clause.predicates.len(); let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list(context.codemap, - where_clause.predicates.iter(), - terminator, - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(context, Shape::legacy(budget, offset)), - span_start, - span_end); + let items = itemize_list( + context.codemap, + where_clause.predicates.iter(), + terminator, + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + |pred| pred.rewrite(context, Shape::legacy(budget, offset)), + span_start, + span_end, + ); let item_vec = items.collect::>(); // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. @@ -2415,10 +2569,13 @@ fn rewrite_where_clause(context: &RewriteContext, terminator.len() }; if density == Density::Tall || preds_str.contains('\n') || - shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { - Some(format!("\n{}where {}", - (shape.indent + extra_indent).to_string(context.config), - preds_str)) + shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width + { + Some(format!( + "\n{}where {}", + (shape.indent + extra_indent).to_string(context.config), + preds_str + )) } else { Some(format!(" where {}", preds_str)) } @@ -2428,39 +2585,40 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S format!("{}{}{}", format_visibility(vis), item_name, ident) } -fn format_generics(context: &RewriteContext, - generics: &ast::Generics, - opener: &str, - terminator: &str, - brace_style: BraceStyle, - force_same_line_brace: bool, - offset: Indent, - span: Span) - -> Option { +fn format_generics( + context: &RewriteContext, + generics: &ast::Generics, + opener: &str, + terminator: &str, + brace_style: BraceStyle, + force_same_line_brace: bool, + offset: Indent, + span: Span, +) -> Option { let shape = Shape::indented(offset, context.config); let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = try_opt!(context - .config - .max_width() - .checked_sub(last_line_width(&result))); - let where_clause_str = - try_opt!(rewrite_where_clause(context, - &generics.where_clause, - brace_style, - Shape::legacy(budget, offset.block_only()), - Density::Tall, - terminator, - false, - trimmed_last_line_width(&result) == 1, - Some(span.hi))); + let budget = try_opt!(context.config.max_width().checked_sub( + last_line_width(&result), + )); + let where_clause_str = try_opt!(rewrite_where_clause( + context, + &generics.where_clause, + brace_style, + Shape::legacy(budget, offset.block_only()), + Density::Tall, + terminator, + false, + trimmed_last_line_width(&result) == 1, + Some(span.hi), + )); result.push_str(&where_clause_str); let same_line_brace = force_same_line_brace || - (generics.where_clause.predicates.is_empty() && - trimmed_last_line_width(&result) == 1); + (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1); if !same_line_brace && - (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) { + (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) + { result.push('\n'); result.push_str(&offset.block_only().to_string(context.config)); } else { @@ -2469,7 +2627,8 @@ fn format_generics(context: &RewriteContext, result.push_str(opener); } else { if force_same_line_brace || trimmed_last_line_width(&result) == 1 || - brace_style != BraceStyle::AlwaysNextLine { + brace_style != BraceStyle::AlwaysNextLine + { result.push(' '); } else { result.push('\n'); diff --git a/src/lib.rs b/src/lib.rs index 219e98ef1e6..2ede6d9a2f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -189,8 +189,10 @@ impl Sub for Indent { type Output = Indent; fn sub(self, rhs: Indent) -> Indent { - Indent::new(self.block_indent - rhs.block_indent, - self.alignment - rhs.alignment) + Indent::new( + self.block_indent - rhs.block_indent, + self.alignment - rhs.alignment, + ) } } @@ -315,17 +317,17 @@ impl Shape { pub fn sub_width(&self, width: usize) -> Option { Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - ..*self - }) + width: try_opt!(self.width.checked_sub(width)), + ..*self + }) } pub fn shrink_left(&self, width: usize) -> Option { Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - indent: self.indent + width, - offset: self.offset + width, - }) + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent + width, + offset: self.offset + width, + }) } pub fn offset_left(&self, width: usize) -> Option { @@ -350,10 +352,12 @@ impl fmt::Display for ErrorKind { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ErrorKind::LineOverflow(found, maximum) => { - write!(fmt, - "line exceeded maximum length (maximum: {}, found: {})", - maximum, - found) + write!( + fmt, + "line exceeded maximum length (maximum: {}, found: {})", + maximum, + found + ) } ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), @@ -412,13 +416,15 @@ impl fmt::Display for FormatReport { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { for (file, errors) in &self.file_error_map { for error in errors { - write!(fmt, - "{} {}:{}: {} {}\n", - error.msg_prefix(), - file, - error.line, - error.kind, - error.msg_suffix())?; + write!( + fmt, + "{} {}:{}: {} {}\n", + error.msg_prefix(), + file, + error.line, + error.kind, + error.msg_suffix() + )?; } } Ok(()) @@ -426,14 +432,16 @@ impl fmt::Display for FormatReport { } // Formatting which depends on the AST. -fn format_ast(krate: &ast::Crate, - mut parse_session: &mut ParseSess, - main_file: &Path, - config: &Config, - codemap: &Rc, - mut after_file: F) - -> Result<(FileMap, bool), io::Error> - where F: FnMut(&str, &mut StringBuffer) -> Result +fn format_ast( + krate: &ast::Crate, + mut parse_session: &mut ParseSess, + main_file: &Path, + config: &Config, + codemap: &Rc, + mut after_file: F, +) -> Result<(FileMap, bool), io::Error> +where + F: FnMut(&str, &mut StringBuffer) -> Result, { let mut result = FileMap::new(); // diff mode: check if any files are differing @@ -493,9 +501,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m // Add warnings for bad todos/ fixmes if let Some(issue) = issue_seeker.inspect(c) { errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), - }); + line: cur_line, + kind: ErrorKind::BadIssue(issue), + }); } } @@ -510,9 +518,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m // Check for any line width errors we couldn't correct. if config.error_on_line_overflow() && line_len > config.max_width() { errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LineOverflow(line_len, config.max_width()), - }); + line: cur_line, + kind: ErrorKind::LineOverflow(line_len, config.max_width()), + }); } } @@ -541,17 +549,18 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m for &(l, _, _) in &trims { errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - }); + line: l, + kind: ErrorKind::TrailingWhitespace, + }); } report.file_error_map.insert(name.to_owned(), errors); } -fn parse_input(input: Input, - parse_session: &ParseSess) - -> Result> { +fn parse_input( + input: Input, + parse_session: &ParseSess, +) -> Result> { let result = match input { Input::File(file) => { let mut parser = parse::new_parser_from_file(parse_session, &file); @@ -579,10 +588,11 @@ fn parse_input(input: Input, } } -pub fn format_input(input: Input, - config: &Config, - mut out: Option<&mut T>) - -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { +pub fn format_input( + input: Input, + config: &Config, + mut out: Option<&mut T>, +) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { let mut summary = Summary::new(); if config.disable_all_formatting() { return Ok((summary, FileMap::new(), FormatReport::new())); @@ -614,7 +624,10 @@ pub fn format_input(input: Input, } // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), Some(codemap.clone()))); + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + )); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); let mut report = FormatReport::new(); diff --git a/src/lists.rs b/src/lists.rs index ec4427032e5..37acff692a4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -69,22 +69,27 @@ pub struct ListFormatting<'a> { } pub fn format_fn_args(items: I, shape: Shape, config: &Config) -> Option - where I: Iterator +where + I: Iterator, { - list_helper(items, - shape, - config, - ListTactic::LimitedHorizontalVertical(config.fn_call_width())) + list_helper( + items, + shape, + config, + ListTactic::LimitedHorizontalVertical(config.fn_call_width()), + ) } pub fn format_item_list(items: I, shape: Shape, config: &Config) -> Option - where I: Iterator +where + I: Iterator, { list_helper(items, shape, config, ListTactic::HorizontalVertical) } pub fn list_helper(items: I, shape: Shape, config: &Config, tactic: ListTactic) -> Option - where I: Iterator +where + I: Iterator, { let item_vec: Vec<_> = items.collect(); let tactic = definitive_tactic(&item_vec, tactic, shape.width); @@ -120,15 +125,16 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || - self.post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) + self.post_comment.as_ref().map_or( + false, + |s| s.contains('\n'), + ) } pub fn has_line_pre_comment(&self) -> bool { - self.pre_comment - .as_ref() - .map_or(false, |comment| comment.starts_with("//")) + self.pre_comment.as_ref().map_or(false, |comment| { + comment.starts_with("//") + }) } pub fn from_str>(s: S) -> ListItem { @@ -150,13 +156,13 @@ pub enum DefinitiveListTactic { } pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic - where I: IntoIterator + Clone, - T: AsRef +where + I: IntoIterator + Clone, + T: AsRef, { - let pre_line_comments = items - .clone() - .into_iter() - .any(|item| item.as_ref().has_line_pre_comment()); + let pre_line_comments = items.clone().into_iter().any(|item| { + item.as_ref().has_line_pre_comment() + }); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, @@ -173,7 +179,8 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De let real_total = total_width + total_sep_len; if real_total <= limit && !pre_line_comments && - !items.into_iter().any(|item| item.as_ref().is_multiline()) { + !items.into_iter().any(|item| item.as_ref().is_multiline()) + { DefinitiveListTactic::Horizontal } else { DefinitiveListTactic::Vertical @@ -183,8 +190,9 @@ pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> De // Format a list of commented items into a string. // TODO: add unit tests pub fn write_list(items: I, formatting: &ListFormatting) -> Option - where I: IntoIterator, - T: AsRef +where + I: IntoIterator, + T: AsRef, { let tactic = formatting.tactic; let sep_len = formatting.separator.len(); @@ -250,8 +258,12 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Block style in non-vertical mode. let block_mode = tactic != DefinitiveListTactic::Vertical; // Width restriction is only relevant in vertical mode. - let comment = - try_opt!(rewrite_comment(comment, block_mode, formatting.shape, formatting.config)); + let comment = try_opt!(rewrite_comment( + comment, + block_mode, + formatting.shape, + formatting.config, + )); result.push_str(&comment); if tactic == DefinitiveListTactic::Vertical { @@ -267,11 +279,12 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = - try_opt!(rewrite_comment(comment, - true, - Shape::legacy(formatting.shape.width, Indent::empty()), - formatting.config)); + let formatted_comment = try_opt!(rewrite_comment( + comment, + true, + Shape::legacy(formatting.shape.width, Indent::empty()), + formatting.config, + )); result.push(' '); result.push_str(&formatted_comment); @@ -295,13 +308,15 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option debug!("Width = {}, offset = {:?}", width, offset); // Use block-style only for the last item or multiline comments. let block_style = !formatting.ends_with_newline && last || - comment.trim().contains('\n') || - comment.trim().len() > width; + comment.trim().contains('\n') || + comment.trim().len() > width; - let formatted_comment = try_opt!(rewrite_comment(comment, - block_style, - Shape::legacy(width, offset), - formatting.config)); + let formatted_comment = try_opt!(rewrite_comment( + comment, + block_style, + Shape::legacy(width, offset), + formatting.config, + )); if !formatted_comment.starts_with('\n') { result.push(' '); @@ -318,7 +333,8 @@ pub fn write_list(items: I, formatting: &ListFormatting) -> Option } pub struct ListItems<'a, I, F1, F2, F3> - where I: Iterator +where + I: Iterator, { codemap: &'a CodeMap, inner: Peekable, @@ -331,10 +347,11 @@ pub struct ListItems<'a, I, F1, F2, F3> } impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> - where I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, { type Item = ListItem; @@ -349,7 +366,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); let has_pre_comment = trimmed_pre_snippet.contains("//") || - trimmed_pre_snippet.contains("/*"); + trimmed_pre_snippet.contains("/*"); let pre_comment = if has_pre_comment { Some(trimmed_pre_snippet.to_owned()) } else { @@ -383,13 +400,17 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> (Some(i), None) if i > separator_index => separator_index + 1, // Block-style post-comment before the separator. (Some(i), None) => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) + cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ) } // Block-style post-comment. Either before or after the separator. (Some(i), Some(j)) if i < j => { - cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1) + cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ) } // Potential *single* line comment. (_, Some(j)) if j > separator_index => j + 1, @@ -397,9 +418,10 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> } } None => { - post_snippet - .find_uncommented(self.terminator) - .unwrap_or(post_snippet.len()) + post_snippet.find_uncommented(self.terminator).unwrap_or( + post_snippet + .len(), + ) } }; @@ -412,9 +434,10 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet - .find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); + let first = test_snippet.find(|c: char| !c.is_whitespace()).unwrap_or( + test_snippet + .len(), + ); // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; @@ -453,19 +476,21 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> } // Creates an iterator over a list's items with associated comments. -pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap, - inner: I, - terminator: &'a str, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - prev_span_end: BytePos, - next_span_start: BytePos) - -> ListItems<'a, I, F1, F2, F3> - where I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option +pub fn itemize_list<'a, T, I, F1, F2, F3>( + codemap: &'a CodeMap, + inner: I, + terminator: &'a str, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos, +) -> ListItems<'a, I, F1, F2, F3> +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, { ListItems { codemap: codemap, @@ -479,9 +504,10 @@ pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap, } } -fn needs_trailing_separator(separator_tactic: SeparatorTactic, - list_tactic: DefinitiveListTactic) - -> bool { +fn needs_trailing_separator( + separator_tactic: SeparatorTactic, + list_tactic: DefinitiveListTactic, +) -> bool { match separator_tactic { SeparatorTactic::Always => true, SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical, @@ -491,8 +517,9 @@ fn needs_trailing_separator(separator_tactic: SeparatorTactic, /// Returns the count and total width of the list items. fn calculate_width(items: I) -> (usize, usize) - where I: IntoIterator, - T: AsRef +where + I: IntoIterator, + T: AsRef, { items .into_iter() @@ -502,8 +529,8 @@ fn calculate_width(items: I) -> (usize, usize) fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + - comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + - item.item.as_ref().map_or(0, |str| str.len()) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + + item.item.as_ref().map_or(0, |str| str.len()) } fn comment_len(comment: Option<&str>) -> usize { @@ -522,33 +549,36 @@ fn comment_len(comment: Option<&str>) -> usize { } // Compute horizontal and vertical shapes for a struct-lit-like thing. -pub fn struct_lit_shape(shape: Shape, - context: &RewriteContext, - prefix_width: usize, - suffix_width: usize) - -> Option<(Option, Shape)> { - let v_shape = match context.config.struct_lit_style() { - IndentStyle::Visual => { - try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width)) +pub fn struct_lit_shape( + shape: Shape, + context: &RewriteContext, + prefix_width: usize, + suffix_width: usize, +) -> Option<(Option, Shape)> { + let v_shape = + match context.config.struct_lit_style() { + IndentStyle::Visual => { + try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width)) .sub_width(suffix_width)) - } - IndentStyle::Block => { - let shape = shape.block_indent(context.config.tab_spaces()); - Shape { - width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())), - ..shape } - } - }; + IndentStyle::Block => { + let shape = shape.block_indent(context.config.tab_spaces()); + Shape { + width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())), + ..shape + } + } + }; let h_shape = shape.sub_width(prefix_width + suffix_width); Some((h_shape, v_shape)) } // Compute the tactic for the internals of a struct-lit-like thing. -pub fn struct_lit_tactic(h_shape: Option, - context: &RewriteContext, - items: &[ListItem]) - -> DefinitiveListTactic { +pub fn struct_lit_tactic( + h_shape: Option, + context: &RewriteContext, + items: &[ListItem], +) -> DefinitiveListTactic { if let Some(h_shape) = h_shape { let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, @@ -568,10 +598,11 @@ pub fn struct_lit_tactic(h_shape: Option, // Given a tactic and possible shapes for horizontal and vertical layout, // come up with the actual shape to use. -pub fn shape_for_tactic(tactic: DefinitiveListTactic, - h_shape: Option, - v_shape: Shape) - -> Shape { +pub fn shape_for_tactic( + tactic: DefinitiveListTactic, + h_shape: Option, + v_shape: Shape, +) -> Shape { match tactic { DefinitiveListTactic::Horizontal => h_shape.unwrap(), _ => v_shape, @@ -580,13 +611,14 @@ pub fn shape_for_tactic(tactic: DefinitiveListTactic, // Create a ListFormatting object for formatting the internals of a // struct-lit-like thing, that is a series of fields. -pub fn struct_lit_formatting<'a>(shape: Shape, - tactic: DefinitiveListTactic, - context: &'a RewriteContext, - force_no_trailing_comma: bool) - -> ListFormatting<'a> { +pub fn struct_lit_formatting<'a>( + shape: Shape, + tactic: DefinitiveListTactic, + context: &'a RewriteContext, + force_no_trailing_comma: bool, +) -> ListFormatting<'a> { let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual && - tactic == DefinitiveListTactic::Vertical; + tactic == DefinitiveListTactic::Vertical; ListFormatting { tactic: tactic, separator: ",", diff --git a/src/macros.rs b/src/macros.rs index eca89a4b609..562e776f8d3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -61,12 +61,13 @@ impl MacroStyle { } } -pub fn rewrite_macro(mac: &ast::Mac, - extra_ident: Option, - context: &RewriteContext, - shape: Shape, - position: MacroPosition) - -> Option { +pub fn rewrite_macro( + mac: &ast::Mac, + extra_ident: Option, + context: &RewriteContext, + shape: Shape, + position: MacroPosition, +) -> Option { let mut context = &mut context.clone(); context.inside_macro = true; if context.config.use_try_shorthand() { @@ -191,24 +192,29 @@ pub fn rewrite_macro(mac: &ast::Mac, } else { ("[", "]") }; - rewrite_pair(&*expr_vec[0], - &*expr_vec[1], - lbr, - "; ", - rbr, - context, - mac_shape) - .map(|s| format!("{}{}", macro_name, s)) + rewrite_pair( + &*expr_vec[0], + &*expr_vec[1], + lbr, + "; ", + rbr, + context, + mac_shape, + ).map(|s| format!("{}{}", macro_name, s)) } else { // Format macro invocation as array literal. - let rewrite = - try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x), - mk_sp(context - .codemap - .span_after(mac.span, original_style.opener()), - mac.span.hi - BytePos(1)), - context, - mac_shape)); + let rewrite = try_opt!(rewrite_array( + expr_vec.iter().map(|x| &**x), + mk_sp( + context.codemap.span_after( + mac.span, + original_style.opener(), + ), + mac.span.hi - BytePos(1), + ), + context, + mac_shape, + )); Some(format!("{}{}", macro_name, rewrite)) } @@ -229,11 +235,11 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option FmtVisitor<'a> { }) } - fn format_missing_inner(&mut self, - end: BytePos, - process_last_snippet: F) { + fn format_missing_inner( + &mut self, + end: BytePos, + process_last_snippet: F, + ) { let start = self.last_pos; if start == end { @@ -60,10 +62,12 @@ impl<'a> FmtVisitor<'a> { return; } - assert!(start < end, - "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end)); + assert!( + start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end) + ); self.last_pos = end; let span = mk_sp(start, end); @@ -72,7 +76,8 @@ impl<'a> FmtVisitor<'a> { } fn write_snippet(&mut self, span: Span, process_last_snippet: F) - where F: Fn(&mut FmtVisitor, &str, &str) + where + F: Fn(&mut FmtVisitor, &str, &str), { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment @@ -92,13 +97,15 @@ impl<'a> FmtVisitor<'a> { self.write_snippet_inner(big_snippet, big_diff, &snippet, span, process_last_snippet); } - fn write_snippet_inner(&mut self, - big_snippet: &str, - big_diff: usize, - old_snippet: &str, - span: Span, - process_last_snippet: F) - where F: Fn(&mut FmtVisitor, &str, &str) + fn write_snippet_inner( + &mut self, + big_snippet: &str, + big_diff: usize, + old_snippet: &str, + span: Span, + process_last_snippet: F, + ) where + F: Fn(&mut FmtVisitor, &str, &str), { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not @@ -139,9 +146,12 @@ impl<'a> FmtVisitor<'a> { let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count(); if rewrite_next_comment && - !self.config - .file_lines() - .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) { + !self.config.file_lines().intersects_range( + file_name, + cur_line, + cur_line + subslice_num_lines, + ) + { rewrite_next_comment = false; } @@ -150,32 +160,34 @@ impl<'a> FmtVisitor<'a> { if let Some('{') = last_char { self.buffer.push_str("\n"); } - self.buffer - .push_str(&self.block_indent.to_string(self.config)); + self.buffer.push_str( + &self.block_indent.to_string(self.config), + ); } else { self.buffer.push_str(" "); } - let comment_width = ::std::cmp::min(self.config.comment_width(), - self.config.max_width() - - self.block_indent.width()); + let comment_width = ::std::cmp::min( + self.config.comment_width(), + self.config.max_width() - self.block_indent.width(), + ); - self.buffer.push_str(&rewrite_comment(subslice, - false, - Shape::legacy(comment_width, - self.block_indent), - self.config) - .unwrap()); + self.buffer.push_str(&rewrite_comment( + subslice, + false, + Shape::legacy(comment_width, self.block_indent), + self.config, + ).unwrap()); last_wspace = None; line_start = offset + subslice.len(); if let Some('/') = subslice.chars().skip(1).next() { // check that there are no contained block comments - if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() >= 2 && &s[0..2] == "/*") { + if !subslice.split('\n').map(|s| s.trim_left()).any(|s| { + s.len() >= 2 && &s[0..2] == "/*" + }) + { // Add a newline after line comments self.buffer.push_str("\n"); } diff --git a/src/modules.rs b/src/modules.rs index 3d2c3b0ac9f..5b5050d51c9 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -20,30 +20,35 @@ use syntax::parse::parser; /// List all the files containing modules of a crate. /// If a file is used twice in a crate, it appears only once. -pub fn list_files<'a>(krate: &'a ast::Crate, - codemap: &codemap::CodeMap) - -> BTreeMap { +pub fn list_files<'a>( + krate: &'a ast::Crate, + codemap: &codemap::CodeMap, +) -> BTreeMap { let mut result = BTreeMap::new(); // Enforce file order determinism let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); - list_submodules(&krate.module, - root_filename.parent().unwrap(), - codemap, - &mut result); + list_submodules( + &krate.module, + root_filename.parent().unwrap(), + codemap, + &mut result, + ); result.insert(root_filename, &krate.module); result } /// Recursively list all external modules included in a module. -fn list_submodules<'a>(module: &'a ast::Mod, - search_dir: &Path, - codemap: &codemap::CodeMap, - result: &mut BTreeMap) { +fn list_submodules<'a>( + module: &'a ast::Mod, + search_dir: &Path, + codemap: &codemap::CodeMap, + result: &mut BTreeMap, +) { debug!("list_submodules: search_dir: {:?}", search_dir); for item in &module.items { if let ast::ItemKind::Mod(ref sub_mod) = item.node { if !utils::contains_skip(&item.attrs) { let is_internal = codemap.span_to_filename(item.span) == - codemap.span_to_filename(sub_mod.inner); + codemap.span_to_filename(sub_mod.inner); let dir_path = if is_internal { search_dir.join(&item.ident.to_string()) } else { @@ -59,11 +64,12 @@ fn list_submodules<'a>(module: &'a ast::Mod, } /// Find the file corresponding to an external mod -fn module_file(id: ast::Ident, - attrs: &[ast::Attribute], - dir_path: &Path, - codemap: &codemap::CodeMap) - -> PathBuf { +fn module_file( + id: ast::Ident, + attrs: &[ast::Attribute], + dir_path: &Path, + codemap: &codemap::CodeMap, +) -> PathBuf { if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { return path; } diff --git a/src/patterns.rs b/src/patterns.rs index eb100abd664..67e4870f660 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -39,12 +39,13 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = - try_opt!(shape.width.checked_sub(prefix.len() + mut_infix.len() + - id_str.len() + - 3)); - format!(" @ {}", - try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))) + let width = try_opt!(shape.width.checked_sub( + prefix.len() + mut_infix.len() + id_str.len() + 3, + )); + format!( + " @ {}", + try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent))) + ) } None => "".to_owned(), }; @@ -80,23 +81,23 @@ impl Rewrite for Pat { rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { - let path_str = - try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); - rewrite_tuple_pat(pat_vec, - dotdot_pos, - Some(path_str), - self.span, - context, - shape) + let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); + rewrite_tuple_pat( + pat_vec, + dotdot_pos, + Some(path_str), + self.span, + context, + shape, + ) } PatKind::Lit(ref expr) => expr.rewrite(context, shape), PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = - slice_pat - .as_ref() - .map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape))))); + let slice_pat = slice_pat.as_ref().map(|p| { + Some(format!("{}..", try_opt!(p.rewrite(context, shape)))) + }); let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. @@ -119,24 +120,33 @@ impl Rewrite for Pat { } // FIXME(#819) format pattern macros. PatKind::Mac(..) => { - wrap_str(context.snippet(self.span), - context.config.max_width(), - shape) + wrap_str( + context.snippet(self.span), + context.config.max_width(), + shape, + ) } } } } -fn rewrite_struct_pat(path: &ast::Path, - fields: &[codemap::Spanned], - elipses: bool, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_struct_pat( + path: &ast::Path, + fields: &[codemap::Spanned], + elipses: bool, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { // 2 = ` {` let path_shape = try_opt!(shape.sub_width(2)); - let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape)); + let path_str = try_opt!(rewrite_path( + context, + PathContext::Expr, + None, + path, + path_shape, + )); if fields.len() == 0 && !elipses { return Some(format!("{} {{}}", path_str)); @@ -145,17 +155,23 @@ fn rewrite_struct_pat(path: &ast::Path, let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; // 3 = ` { `, 2 = ` }`. - let (h_shape, v_shape) = - try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, elipses_str.len() + 2)); - - let items = itemize_list(context.codemap, - fields.iter(), - terminator, - |f| f.span.lo, - |f| f.span.hi, - |f| f.node.rewrite(context, v_shape), - context.codemap.span_after(span, "{"), - span.hi); + let (h_shape, v_shape) = try_opt!(struct_lit_shape( + shape, + context, + path_str.len() + 3, + elipses_str.len() + 2, + )); + + let items = itemize_list( + context.codemap, + fields.iter(), + terminator, + |f| f.span.lo, + |f| f.span.hi, + |f| f.node.rewrite(context, v_shape), + context.codemap.span_after(span, "{"), + span.hi, + ); let item_vec = items.collect::>(); let tactic = struct_lit_tactic(h_shape, context, &item_vec); @@ -189,14 +205,16 @@ fn rewrite_struct_pat(path: &ast::Path, let fields_str = if context.config.struct_lit_style() == IndentStyle::Block && - (fields_str.contains('\n') || - context.config.struct_lit_multiline_style() == - MultilineStyle::ForceMulti || - fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) { - format!("\n{}{}\n{}", - v_shape.indent.to_string(context.config), - fields_str, - shape.indent.to_string(context.config)) + (fields_str.contains('\n') || + context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || + fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) + { + format!( + "\n{}{}\n{}", + v_shape.indent.to_string(context.config), + fields_str, + shape.indent.to_string(context.config) + ) } else { // One liner or visual indent. format!(" {} ", fields_str) @@ -211,9 +229,11 @@ impl Rewrite for FieldPat { if self.is_shorthand { pat } else { - wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)), - context.config.max_width(), - shape) + wrap_str( + format!("{}: {}", self.ident.to_string(), try_opt!(pat)), + context.config.max_width(), + shape, + ) } } } @@ -241,13 +261,14 @@ impl<'a> Spanned for TuplePatField<'a> { } } -fn rewrite_tuple_pat(pats: &[ptr::P], - dotdot_pos: Option, - path_str: Option, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_tuple_pat( + pats: &[ptr::P], + dotdot_pos: Option, + path_str: Option, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); if let Some(pos) = dotdot_pos { @@ -285,15 +306,16 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); // 1 = "(".len() let nested_shape = nested_shape.visual_indent(path_len + 1); - let mut items: Vec<_> = itemize_list(context.codemap, - pat_vec.iter(), - if add_comma { ",)" } else { ")" }, - |item| item.span().lo, - |item| item.span().hi, - |item| item.rewrite(context, nested_shape), - context.codemap.span_after(span, "("), - span.hi - BytePos(1)) - .collect(); + let mut items: Vec<_> = itemize_list( + context.codemap, + pat_vec.iter(), + if add_comma { ",)" } else { ")" }, + |item| item.span().lo, + |item| item.span().hi, + |item| item.rewrite(context, nested_shape), + context.codemap.span_after(span, "("), + span.hi - BytePos(1), + ).collect(); // Condense wildcard string suffix into a single .. let wildcard_suffix_len = count_wildcard_suffix_len(&items); @@ -305,24 +327,32 @@ fn rewrite_tuple_pat(pats: &[ptr::P], let da_iter = items.into_iter().take(new_item_count); try_opt!(format_item_list(da_iter, nested_shape, context.config)) } else { - try_opt!(format_item_list(items.into_iter(), nested_shape, context.config)) + try_opt!(format_item_list( + items.into_iter(), + nested_shape, + context.config, + )) }; match path_str { Some(path_str) => { - Some(if context.config.spaces_within_parens() { - format!("{}( {} )", path_str, list) - } else { - format!("{}({})", path_str, list) - }) + Some( + if context.config.spaces_within_parens() { + format!("{}( {} )", path_str, list) + } else { + format!("{}({})", path_str, list) + }, + ) } None => { let comma = if add_comma { "," } else { "" }; - Some(if context.config.spaces_within_parens() { - format!("( {}{} )", list, comma) - } else { - format!("({}{})", list, comma) - }) + Some( + if context.config.spaces_within_parens() { + format!("( {}{} )", list, comma) + } else { + format!("({}{})", list, comma) + }, + ) } } } @@ -331,10 +361,10 @@ fn count_wildcard_suffix_len(items: &[ListItem]) -> usize { let mut suffix_len = 0; for item in items.iter().rev().take_while(|i| match i.item { - Some(ref internal_string) if internal_string == - "_" => true, - _ => false, - }) { + Some(ref internal_string) if internal_string == "_" => true, + _ => false, + }) + { suffix_len += 1; if item.pre_comment.is_some() || item.post_comment.is_some() { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 23cb3f21bf2..ff35a83cc63 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -86,7 +86,8 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F) - where F: Fn(u32) -> String +where + F: Fn(u32) -> String, { match term::stdout() { Some(ref t) if isatty() && t.supports_color() => { @@ -115,10 +116,12 @@ pub fn print_diff(diff: Vec, get_section_title: F) } } -fn print_diff_fancy(diff: Vec, - get_section_title: F, - mut t: Box>) - where F: Fn(u32) -> String +fn print_diff_fancy( + diff: Vec, + get_section_title: F, + mut t: Box>, +) where + F: Fn(u32) -> String, { for mismatch in diff { let title = get_section_title(mismatch.line_number); @@ -145,7 +148,8 @@ fn print_diff_fancy(diff: Vec, } pub fn print_diff_basic(diff: Vec, get_section_title: F) - where F: Fn(u32) -> String +where + F: Fn(u32) -> String, { for mismatch in diff { let title = get_section_title(mismatch.line_number); diff --git a/src/string.rs b/src/string.rs index 365d205aef1..904260e8182 100644 --- a/src/string.rs +++ b/src/string.rs @@ -42,10 +42,12 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; - let mut result = String::with_capacity(stripped_str - .len() - .checked_next_power_of_two() - .unwrap_or(usize::max_value())); + let mut result = String::with_capacity( + stripped_str + .len() + .checked_next_power_of_two() + .unwrap_or(usize::max_value()), + ); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); @@ -81,7 +83,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option if cur_end < cur_start + MIN_STRING { cur_end = cur_start + max_chars; while !(punctuation.contains(graphemes[cur_end - 1]) || - graphemes[cur_end - 1].trim().is_empty()) { + graphemes[cur_end - 1].trim().is_empty()) + { if cur_end >= graphemes.len() { let line = &graphemes[cur_start..].join(""); result.push_str(line); diff --git a/src/summary.rs b/src/summary.rs index 6fc1bbded1d..5a169f8b80c 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -54,7 +54,7 @@ impl Summary { pub fn has_no_errors(&self) -> bool { !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors || - self.has_diff) + self.has_diff) } pub fn add(&mut self, other: Summary) { diff --git a/src/types.rs b/src/types.rs index 7e5daa12f81..f54e1c96eda 100644 --- a/src/types.rs +++ b/src/types.rs @@ -34,20 +34,21 @@ pub enum PathContext { } // Does not wrap on simple segments. -pub fn rewrite_path(context: &RewriteContext, - path_context: PathContext, - qself: Option<&ast::QSelf>, - path: &ast::Path, - shape: Shape) - -> Option { +pub fn rewrite_path( + context: &RewriteContext, + path_context: PathContext, + qself: Option<&ast::QSelf>, + path: &ast::Path, + shape: Shape, +) -> Option { let skip_count = qself.map_or(0, |x| x.position); - let mut result = if path.is_global() && qself.is_none() && - path_context != PathContext::Import { - "::".to_owned() - } else { - String::new() - }; + let mut result = + if path.is_global() && qself.is_none() && path_context != PathContext::Import { + "::".to_owned() + } else { + String::new() + }; let mut span_lo = path.span.lo; @@ -70,13 +71,15 @@ pub fn rewrite_path(context: &RewriteContext, // 3 = ">::".len() let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3)); - result = try_opt!(rewrite_path_segments(PathContext::Type, - result, - path.segments.iter().take(skip_count), - span_lo, - path.span.hi, - context, - shape)); + result = try_opt!(rewrite_path_segments( + PathContext::Type, + result, + path.segments.iter().take(skip_count), + span_lo, + path.span.hi, + context, + shape, + )); } if context.config.spaces_within_angle_brackets() { @@ -87,24 +90,28 @@ pub fn rewrite_path(context: &RewriteContext, span_lo = qself.ty.span.hi + BytePos(1); } - rewrite_path_segments(path_context, - result, - path.segments.iter().skip(skip_count), - span_lo, - path.span.hi, - context, - shape) + rewrite_path_segments( + path_context, + result, + path.segments.iter().skip(skip_count), + span_lo, + path.span.hi, + context, + shape, + ) } -fn rewrite_path_segments<'a, I>(path_context: PathContext, - mut buffer: String, - iter: I, - mut span_lo: BytePos, - span_hi: BytePos, - context: &RewriteContext, - shape: Shape) - -> Option - where I: Iterator +fn rewrite_path_segments<'a, I>( + path_context: PathContext, + mut buffer: String, + iter: I, + mut span_lo: BytePos, + span_hi: BytePos, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: Iterator, { let mut first = true; let shape = shape.visual_indent(0); @@ -122,12 +129,14 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext, let extra_offset = extra_offset(&buffer, shape); let new_shape = try_opt!(shape.shrink_left(extra_offset)); - let segment_string = try_opt!(rewrite_segment(path_context, - segment, - &mut span_lo, - span_hi, - context, - new_shape)); + let segment_string = try_opt!(rewrite_segment( + path_context, + segment, + &mut span_lo, + span_hi, + context, + new_shape, + )); buffer.push_str(&segment_string); } @@ -163,10 +172,10 @@ impl<'a> Rewrite for SegmentParam<'a> { TypeDensity::Compressed => format!("{}=", binding.ident), }; let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!(binding.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + - result.len()))); + let rewrite = try_opt!(binding.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + result.len()), + )); result.push_str(&rewrite); Some(result) } @@ -184,21 +193,22 @@ impl<'a> Rewrite for SegmentParam<'a> { // // When the segment contains a positive number of parameters, we update span_lo // so that invariants described above will hold for the next segment. -fn rewrite_segment(path_context: PathContext, - segment: &ast::PathSegment, - span_lo: &mut BytePos, - span_hi: BytePos, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_segment( + path_context: PathContext, + segment: &ast::PathSegment, + span_lo: &mut BytePos, + span_hi: BytePos, + context: &RewriteContext, + shape: Shape, +) -> Option { let ident_len = segment.identifier.to_string().len(); let shape = try_opt!(shape.shrink_left(ident_len)); let params = if let Some(ref params) = segment.parameters { match **params { ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() || - !data.types.is_empty() || - !data.bindings.is_empty() => { + !data.types.is_empty() || + !data.bindings.is_empty() => { let param_list = data.lifetimes .iter() .map(SegmentParam::LifeTime) @@ -239,12 +249,14 @@ fn rewrite_segment(path_context: PathContext, Some(ref ty) => FunctionRetTy::Ty(ty.clone()), None => FunctionRetTy::Default(codemap::DUMMY_SP), }; - try_opt!(format_function_type(data.inputs.iter().map(|x| &**x), - &output, - false, - data.span, - context, - shape)) + try_opt!(format_function_type( + data.inputs.iter().map(|x| &**x), + &output, + false, + data.span, + context, + shape, + )) } _ => String::new(), } @@ -255,22 +267,25 @@ fn rewrite_segment(path_context: PathContext, Some(format!("{}{}", segment.identifier, params)) } -fn format_function_type<'a, I>(inputs: I, - output: &FunctionRetTy, - variadic: bool, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option - where I: ExactSizeIterator, - ::Item: Deref, - ::Target: Rewrite + Spanned + 'a +fn format_function_type<'a, I>( + inputs: I, + output: &FunctionRetTy, + variadic: bool, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, + ::Item: Deref, + ::Target: Rewrite + Spanned + 'a, { // Code for handling variadics is somewhat duplicated for items, but they // are different enough to need some serious refactoring to share code. enum ArgumentKind - where T: Deref, - ::Target: Rewrite + Spanned + where + T: Deref, + ::Target: Rewrite + Spanned, { Regular(Box), Variadic(BytePos), @@ -288,31 +303,35 @@ fn format_function_type<'a, I>(inputs: I, // 1 for ( let offset = shape.indent + 1; let list_lo = context.codemap.span_after(span, "("); - let items = itemize_list(context.codemap, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs - .map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), - ")", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo, - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi, - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => { - ty.rewrite(context, Shape::legacy(budget, offset)) - } - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, - list_lo, - span.hi); - - let list_str = try_opt!(format_fn_args(items, Shape::legacy(budget, offset), context.config)); + let items = itemize_list( + context.codemap, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs + .map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), + ")", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.rewrite(context, Shape::legacy(budget, offset)), + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi, + ); + + let list_str = try_opt!(format_fn_args( + items, + Shape::legacy(budget, offset), + context.config, + )); let output = match *output { FunctionRetTy::Ty(ref ty) => { @@ -329,16 +348,20 @@ fn format_function_type<'a, I>(inputs: I, String::new() }; - Some(if context.config.spaces_within_parens() { - format!("( {} ){}{}", list_str, infix, output) - } else { - format!("({}){}{}", list_str, infix, output) - }) + Some( + if context.config.spaces_within_parens() { + format!("( {} ){}{}", list_str, infix, output) + } else { + format!("({}){}{}", list_str, infix, output) + }, + ) } fn type_bound_colon(context: &RewriteContext) -> &'static str { - colon_spaces(context.config.space_before_bound(), - context.config.space_after_bound_colon()) + colon_spaces( + context.config.space_before_bound(), + context.config.space_after_bound_colon(), + ) } impl Rewrite for ast::WherePredicate { @@ -356,11 +379,12 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { - let lifetime_str: String = try_opt!(bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, shape)) - .collect::>>()) - .join(", "); + let lifetime_str: String = try_opt!( + bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, shape)) + .collect::>>() + ).join(", "); // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; @@ -373,11 +397,13 @@ impl Rewrite for ast::WherePredicate { let bounds_str = join_bounds(context, ty_shape, &bounds); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { - format!("for< {} > {}{}{}", - lifetime_str, - type_str, - colon, - bounds_str) + format!( + "for< {} > {}{}{}", + lifetime_str, + type_str, + colon, + bounds_str + ) } else { format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) } @@ -402,7 +428,12 @@ impl Rewrite for ast::WherePredicate { ref bounds, .. }) => { - try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)) + try_opt!(rewrite_bounded_lifetime( + lifetime, + bounds.iter(), + context, + shape, + )) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, @@ -413,9 +444,10 @@ impl Rewrite for ast::WherePredicate { // 3 = " = ".len() let used_width = 3 + lhs_ty_str.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); - let rhs_ty_str = try_opt!(rhs_ty.rewrite(context, - Shape::legacy(budget, - shape.indent + used_width))); + let rhs_ty_str = try_opt!(rhs_ty.rewrite( + context, + Shape::legacy(budget, shape.indent + used_width), + )); format!("{} = {}", lhs_ty_str, rhs_ty_str) } }; @@ -430,22 +462,26 @@ impl Rewrite for ast::LifetimeDef { } } -fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime, - bounds: I, - context: &RewriteContext, - shape: Shape) - -> Option - where I: ExactSizeIterator +fn rewrite_bounded_lifetime<'b, I>( + lt: &ast::Lifetime, + bounds: I, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, { let result = try_opt!(lt.rewrite(context, shape)); if bounds.len() == 0 { Some(result) } else { - let appendix: Vec<_> = try_opt!(bounds - .into_iter() - .map(|b| b.rewrite(context, shape)) - .collect()); + let appendix: Vec<_> = try_opt!( + bounds + .into_iter() + .map(|b| b.rewrite(context, shape)) + .collect() + ); let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); let result = format!("{}{}{}", @@ -464,9 +500,13 @@ impl Rewrite for ast::TyParamBound { } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { let budget = try_opt!(shape.width.checked_sub(1)); - Some(format!("?{}", - try_opt!(tref.rewrite(context, - Shape::legacy(budget, shape.indent + 1))))) + Some(format!( + "?{}", + try_opt!(tref.rewrite( + context, + Shape::legacy(budget, shape.indent + 1), + )) + )) } ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), } @@ -475,9 +515,11 @@ impl Rewrite for ast::TyParamBound { impl Rewrite for ast::Lifetime { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - wrap_str(pprust::lifetime_to_string(self), - context.config.max_width(), - shape) + wrap_str( + pprust::lifetime_to_string(self), + context.config.max_width(), + shape, + ) } } @@ -514,8 +556,10 @@ impl Rewrite for ast::TyParam { }; result.push_str(eq_str); let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!(def.rewrite(context, - Shape::legacy(budget, shape.indent + result.len()))); + let rewrite = try_opt!(def.rewrite( + context, + Shape::legacy(budget, shape.indent + result.len()), + )); result.push_str(&rewrite); } @@ -526,25 +570,31 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if !self.bound_lifetimes.is_empty() { - let lifetime_str: String = try_opt!(self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, shape)) - .collect::>>()) - .join(", "); + let lifetime_str: String = try_opt!( + self.bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, shape)) + .collect::>>() + ).join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref.rewrite(context, - Shape::legacy(max_path_width, - shape.indent + - extra_offset))); - - Some(if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }) + let path_str = try_opt!(self.trait_ref.rewrite( + context, + Shape::legacy( + max_path_width, + shape.indent + extra_offset, + ), + )); + + Some( + if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }, + ) } else { self.trait_ref.rewrite(context, shape) } @@ -573,33 +623,39 @@ impl Rewrite for ast::Ty { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); Some(match *lifetime { - Some(ref lifetime) => { - let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); - let lt_str = try_opt!(lifetime.rewrite(context, - Shape::legacy(lt_budget, - shape.indent + 2 + - mut_len))); - let lt_len = lt_str.len(); - let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); - format!("&{} {}{}", - lt_str, - mut_str, - try_opt!(mt.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + 2 + - mut_len + - lt_len)))) - } - None => { - let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); - format!("&{}{}", - mut_str, - try_opt!(mt.ty.rewrite(context, - Shape::legacy(budget, - shape.indent + 1 + - mut_len)))) - } - }) + Some(ref lifetime) => { + let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); + let lt_str = try_opt!(lifetime.rewrite( + context, + Shape::legacy(lt_budget, shape.indent + 2 + mut_len), + )); + let lt_len = lt_str.len(); + let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); + format!( + "&{} {}{}", + lt_str, + mut_str, + try_opt!(mt.ty.rewrite( + context, + Shape::legacy( + budget, + shape.indent + 2 + mut_len + lt_len, + ), + )) + ) + } + None => { + let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); + format!( + "&{}{}", + mut_str, + try_opt!(mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 1 + mut_len), + )) + ) + } + }) } // FIXME: we drop any comments here, even though it's a silly place to put // comments. @@ -607,10 +663,10 @@ impl Rewrite for ast::Ty { let budget = try_opt!(shape.width.checked_sub(2)); ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_parens() { - format!("( {} )", ty_str) - } else { - format!("({})", ty_str) - }) + format!("( {} )", ty_str) + } else { + format!("({})", ty_str) + }) } ast::TyKind::Slice(ref ty) => { let budget = if context.config.spaces_within_square_brackets() { @@ -620,10 +676,10 @@ impl Rewrite for ast::Ty { }; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_square_brackets() { - format!("[ {} ]", ty_str) - } else { - format!("[{}]", ty_str) - }) + format!("[ {} ]", ty_str) + } else { + format!("[{}]", ty_str) + }) } ast::TyKind::Tup(ref items) => { rewrite_tuple_type(context, items.iter().map(|x| &**x), self.span, shape) @@ -649,8 +705,9 @@ impl Rewrite for ast::Ty { ast::TyKind::Mac(..) => None, ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(ref it) => { - it.rewrite(context, shape) - .map(|it_str| format!("impl {}", it_str)) + it.rewrite(context, shape).map(|it_str| { + format!("impl {}", it_str) + }) } ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), @@ -658,11 +715,12 @@ impl Rewrite for ast::Ty { } } -fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, - span: Span, - context: &RewriteContext, - shape: Shape) - -> Option { +fn rewrite_bare_fn( + bare_fn: &ast::BareFnTy, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { let mut result = String::with_capacity(128); if !bare_fn.lifetimes.is_empty() { @@ -675,8 +733,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, .lifetimes .iter() .map(|l| { - l.rewrite(context, - Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4)) + l.rewrite( + context, + Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4), + ) }) .collect::>>() ).join(", ")); @@ -686,7 +746,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, result.push_str(::utils::format_unsafety(bare_fn.unsafety)); if bare_fn.abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi(bare_fn.abi, context.config.force_explicit_abi())); + result.push_str(&::utils::format_abi( + bare_fn.abi, + context.config.force_explicit_abi(), + )); } result.push_str("fn"); @@ -694,12 +757,14 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy, let budget = try_opt!(shape.width.checked_sub(result.len())); let indent = shape.indent + result.len(); - let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(), - &bare_fn.decl.output, - bare_fn.decl.variadic, - span, - context, - Shape::legacy(budget, indent))); + let rewrite = try_opt!(format_function_type( + bare_fn.decl.inputs.iter(), + &bare_fn.decl.output, + bare_fn.decl.variadic, + span, + context, + Shape::legacy(budget, indent), + )); result.push_str(&rewrite); diff --git a/src/utils.rs b/src/utils.rs index b4095978b8a..0d1b32570c8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -44,9 +44,9 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { let Path { ref segments, .. } = **path; let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); if path.is_global() { - segments_iter - .next() - .expect("Non-global path in pub(restricted)?"); + segments_iter.next().expect( + "Non-global path in pub(restricted)?", + ); } let is_keyword = |s: &str| s == "self" || s == "super"; let path = segments_iter.collect::>().join("::"); @@ -128,9 +128,9 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { #[inline] pub fn contains_skip(attrs: &[Attribute]) -> bool { - attrs - .iter() - .any(|a| a.meta().map_or(false, |a| is_skip(&a))) + attrs.iter().any( + |a| a.meta().map_or(false, |a| is_skip(&a)), + ) } // Find the end of a TyParam @@ -333,7 +333,8 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option - shape.indent.width() + shape.width { + shape.indent.width() + shape.width + { return None; } } @@ -355,7 +356,8 @@ impl Rewrite for String { // whether the `guess' was too high (Ordering::Less), or too low. // This function is guaranteed to try to the hi value first. pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option - where C: Fn(usize) -> Result +where + C: Fn(usize) -> Result, { let mut middle = hi; diff --git a/src/visitor.rs b/src/visitor.rs index d01e8e02ead..6358cc7531f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -36,16 +36,16 @@ fn is_use_item(item: &ast::Item) -> bool { } fn item_bound(item: &ast::Item) -> Span { - item.attrs - .iter() - .map(|attr| attr.span) - .fold(item.span, |bound, span| { + item.attrs.iter().map(|attr| attr.span).fold( + item.span, + |bound, span| { Span { lo: cmp::min(bound.lo, span.lo), hi: cmp::max(bound.hi, span.hi), ctxt: span.ctxt, } - }) + }, + ) } pub struct FmtVisitor<'a> { @@ -62,14 +62,19 @@ pub struct FmtVisitor<'a> { impl<'a> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { - debug!("visit_stmt: {:?} {:?}", - self.codemap.lookup_char_pos(stmt.span.lo), - self.codemap.lookup_char_pos(stmt.span.hi)); + debug!( + "visit_stmt: {:?} {:?}", + self.codemap.lookup_char_pos(stmt.span.lo), + self.codemap.lookup_char_pos(stmt.span.hi) + ); // FIXME(#434): Move this check to somewhere more central, eg Rewrite. - if !self.config - .file_lines() - .intersects(&self.codemap.lookup_line_range(stmt.span)) { + if !self.config.file_lines().intersects( + &self.codemap.lookup_line_range( + stmt.span, + ), + ) + { return; } @@ -80,9 +85,10 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - let rewrite = - stmt.rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)); + let rewrite = stmt.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ); self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Mac(ref mac) => { @@ -94,9 +100,11 @@ impl<'a> FmtVisitor<'a> { } pub fn visit_block(&mut self, b: &ast::Block) { - debug!("visit_block: {:?} {:?}", - self.codemap.lookup_char_pos(b.span.lo), - self.codemap.lookup_char_pos(b.span.hi)); + debug!( + "visit_block: {:?} {:?}", + self.codemap.lookup_char_pos(b.span.lo), + self.codemap.lookup_char_pos(b.span.hi) + ); // Check if this block has braces. let snippet = self.snippet(b.span); @@ -157,42 +165,48 @@ impl<'a> FmtVisitor<'a> { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. - fn visit_fn(&mut self, - fk: visit::FnKind, - fd: &ast::FnDecl, - s: Span, - _: ast::NodeId, - defaultness: ast::Defaultness) { + fn visit_fn( + &mut self, + fk: visit::FnKind, + fd: &ast::FnDecl, + s: Span, + _: ast::NodeId, + defaultness: ast::Defaultness, + ) { let indent = self.block_indent; let block; let rewrite = match fk { visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => { block = b; - self.rewrite_fn(indent, - ident, - fd, - generics, - unsafety, - constness.node, - defaultness, - abi, - vis, - mk_sp(s.lo, b.span.lo), - &b) + self.rewrite_fn( + indent, + ident, + fd, + generics, + unsafety, + constness.node, + defaultness, + abi, + vis, + mk_sp(s.lo, b.span.lo), + &b, + ) } visit::FnKind::Method(ident, sig, vis, b) => { block = b; - self.rewrite_fn(indent, - ident, - fd, - &sig.generics, - sig.unsafety, - sig.constness.node, - defaultness, - sig.abi, - vis.unwrap_or(&ast::Visibility::Inherited), - mk_sp(s.lo, b.span.lo), - &b) + self.rewrite_fn( + indent, + ident, + fd, + &sig.generics, + sig.unsafety, + sig.constness.node, + defaultness, + sig.abi, + vis.unwrap_or(&ast::Visibility::Inherited), + mk_sp(s.lo, b.span.lo), + &b, + ) } visit::FnKind::Closure(_) => unreachable!(), }; @@ -267,23 +281,28 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo); let snippet = self.get_context().snippet(item.span); - let where_span_end = - snippet - .find_uncommented("{") - .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); - if let Some(impl_str) = format_impl(&self.get_context(), - item, - self.block_indent, - where_span_end) { + let where_span_end = snippet.find_uncommented("{").map(|x| { + (BytePos(x as u32)) + source!(self, item.span).lo + }); + if let Some(impl_str) = format_impl( + &self.get_context(), + item, + self.block_indent, + where_span_end, + ) + { self.buffer.push_str(&impl_str); self.last_pos = source!(self, item.span).hi; } } ast::ItemKind::Trait(..) => { self.format_missing_with_indent(item.span.lo); - if let Some(trait_str) = format_trait(&self.get_context(), - item, - self.block_indent) { + if let Some(trait_str) = format_trait( + &self.get_context(), + item, + self.block_indent, + ) + { self.buffer.push_str(&trait_str); self.last_pos = source!(self, item.span).hi; } @@ -298,19 +317,20 @@ impl<'a> FmtVisitor<'a> { let rewrite = { let indent = self.block_indent; let context = self.get_context(); - ::items::format_struct(&context, - "struct ", - item.ident, - &item.vis, - def, - Some(generics), - item.span, - indent, - None) - .map(|s| match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - }) + ::items::format_struct( + &context, + "struct ", + item.ident, + &item.vis, + def, + Some(generics), + item.span, + indent, + None, + ).map(|s| match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + }) }; self.push_rewrite(item.span, rewrite); } @@ -331,53 +351,63 @@ impl<'a> FmtVisitor<'a> { self.format_foreign_mod(foreign_mod, item.span); } ast::ItemKind::Static(ref ty, mutability, ref expr) => { - let rewrite = rewrite_static("static", - &item.vis, - item.ident, - ty, - mutability, - Some(expr), - self.block_indent, - item.span, - &self.get_context()); + let rewrite = rewrite_static( + "static", + &item.vis, + item.ident, + ty, + mutability, + Some(expr), + self.block_indent, + item.span, + &self.get_context(), + ); self.push_rewrite(item.span, rewrite); } ast::ItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_static("const", - &item.vis, - item.ident, - ty, - ast::Mutability::Immutable, - Some(expr), - self.block_indent, - item.span, - &self.get_context()); + let rewrite = rewrite_static( + "const", + &item.vis, + item.ident, + ty, + ast::Mutability::Immutable, + Some(expr), + self.block_indent, + item.span, + &self.get_context(), + ); self.push_rewrite(item.span, rewrite); } ast::ItemKind::DefaultImpl(..) => { // FIXME(#78): format impl definitions. } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { - self.visit_fn(visit::FnKind::ItemFn(item.ident, - generics, - unsafety, - constness, - abi, - &item.vis, - body), - decl, - item.span, - item.id, - ast::Defaultness::Final) + self.visit_fn( + visit::FnKind::ItemFn( + item.ident, + generics, + unsafety, + constness, + abi, + &item.vis, + body, + ), + decl, + item.span, + item.id, + ast::Defaultness::Final, + ) } ast::ItemKind::Ty(ref ty, ref generics) => { - let rewrite = rewrite_type_alias(&self.get_context(), - self.block_indent, - item.ident, - ty, - generics, - &item.vis, - item.span); + let rewrite = rewrite_type_alias( + &self.get_context(), + self.block_indent, + item.ident, + ty, + generics, + &item.vis, + item.span, + ); self.push_rewrite(item.span, rewrite); } ast::ItemKind::Union(..) => { @@ -403,15 +433,17 @@ impl<'a> FmtVisitor<'a> { match ti.node { ast::TraitItemKind::Const(ref ty, ref expr_opt) => { - let rewrite = rewrite_static("const", - &ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr_opt.as_ref(), - self.block_indent, - ti.span, - &self.get_context()); + let rewrite = rewrite_static( + "const", + &ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr_opt.as_ref(), + self.block_indent, + ti.span, + &self.get_context(), + ); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { @@ -420,18 +452,22 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, Some(ref body)) => { - self.visit_fn(visit::FnKind::Method(ti.ident, sig, None, body), - &sig.decl, - ti.span, - ti.id, - ast::Defaultness::Final); + self.visit_fn( + visit::FnKind::Method(ti.ident, sig, None, body), + &sig.decl, + ti.span, + ti.id, + ast::Defaultness::Final, + ); } ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { - let rewrite = rewrite_associated_type(ti.ident, - type_default.as_ref(), - Some(type_param_bounds), - &self.get_context(), - self.block_indent); + let rewrite = rewrite_associated_type( + ti.ident, + type_default.as_ref(), + Some(type_param_bounds), + &self.get_context(), + self.block_indent, + ); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Macro(ref mac) => { @@ -448,31 +484,37 @@ impl<'a> FmtVisitor<'a> { match ii.node { ast::ImplItemKind::Method(ref sig, ref body) => { - self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), - &sig.decl, - ii.span, - ii.id, - ii.defaultness); + self.visit_fn( + visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), + &sig.decl, + ii.span, + ii.id, + ii.defaultness, + ); } ast::ImplItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_static("const", - &ii.vis, - ii.ident, - ty, - ast::Mutability::Immutable, - Some(expr), - self.block_indent, - ii.span, - &self.get_context()); + let rewrite = rewrite_static( + "const", + &ii.vis, + ii.ident, + ty, + ast::Mutability::Immutable, + Some(expr), + self.block_indent, + ii.span, + &self.get_context(), + ); self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_impl_type(ii.ident, - ii.defaultness, - Some(ty), - None, - &self.get_context(), - self.block_indent); + let rewrite = rewrite_associated_impl_type( + ii.ident, + ii.defaultness, + Some(ty), + None, + &self.get_context(), + self.block_indent, + ); self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { @@ -493,9 +535,10 @@ impl<'a> FmtVisitor<'a> { fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo); self.failed = match rewrite { - Some(ref s) if s.rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)) - .is_none() => true, + Some(ref s) if s.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ).is_none() => true, None => true, _ => self.failed, }; @@ -521,9 +564,11 @@ impl<'a> FmtVisitor<'a> { match self.codemap.span_to_snippet(span) { Ok(s) => s, Err(_) => { - println!("Couldn't make snippet for span {:?}->{:?}", - self.codemap.lookup_char_pos(span.lo), - self.codemap.lookup_char_pos(span.hi)); + println!( + "Couldn't make snippet for span {:?}->{:?}", + self.codemap.lookup_char_pos(span.lo), + self.codemap.lookup_char_pos(span.hi) + ); "".to_owned() } } @@ -548,8 +593,10 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(source!(self, first.span).lo); let rewrite = outers - .rewrite(&self.get_context(), - Shape::indented(self.block_indent, self.config)) + .rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ) .unwrap(); self.buffer.push_str(&rewrite); let last = outers.last().unwrap(); @@ -570,13 +617,13 @@ impl<'a> FmtVisitor<'a> { .iter() .take_while(|ppi| { is_use_item(&***ppi) && - (!reorder_imports_in_group || - { - let current = self.codemap.lookup_line_range(item_bound(&ppi)); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) + (!reorder_imports_in_group || + { + let current = self.codemap.lookup_line_range(item_bound(&ppi)); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) }) .count(); let (use_items, rest) = items_left.split_at(use_item_length); @@ -597,7 +644,7 @@ impl<'a> FmtVisitor<'a> { let local_file_name = self.codemap.span_to_filename(s); let inner_span = source!(self, m.inner); let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) && - local_file_name == self.codemap.span_to_filename(inner_span); + local_file_name == self.codemap.span_to_filename(inner_span); self.buffer.push_str(&*utils::format_visibility(vis)); self.buffer.push_str("mod "); @@ -658,66 +705,65 @@ impl Rewrite for ast::NestedMetaItem { impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { - ast::MetaItemKind::Word => String::from(&*self.name.as_str()), - ast::MetaItemKind::List(ref list) => { - let name = self.name.as_str(); - // 3 = `#[` and `(`, 2 = `]` and `)` - let item_shape = try_opt!(shape - .shrink_left(name.len() + 3) - .and_then(|s| s.sub_width(2))); - let items = itemize_list(context.codemap, - list.iter(), - ")", - |nested_meta_item| nested_meta_item.span.lo, - |nested_meta_item| nested_meta_item.span.hi, - |nested_meta_item| { - nested_meta_item.rewrite(context, item_shape) - }, - self.span.lo, - self.span.hi); - let item_vec = items.collect::>(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - shape: item_shape, - ends_with_newline: false, - config: context.config, - }; - format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt))) - } - ast::MetaItemKind::NameValue(ref literal) => { - let name = self.name.as_str(); - let value = context.snippet(literal.span); - if &*name == "doc" && value.starts_with("///") { - let doc_shape = Shape { - width: cmp::min(shape.width, context.config.comment_width()) - .checked_sub(shape.indent.width()) - .unwrap_or(0), - ..shape - }; - format!("{}", - try_opt!(rewrite_comment(&value, - false, - doc_shape, - context.config))) - } else { - format!("{} = {}", name, value) - } - } - }) + ast::MetaItemKind::Word => String::from(&*self.name.as_str()), + ast::MetaItemKind::List(ref list) => { + let name = self.name.as_str(); + // 3 = `#[` and `(`, 2 = `]` and `)` + let item_shape = try_opt!(shape.shrink_left(name.len() + 3).and_then( + |s| s.sub_width(2), + )); + let items = itemize_list( + context.codemap, + list.iter(), + ")", + |nested_meta_item| nested_meta_item.span.lo, + |nested_meta_item| nested_meta_item.span.hi, + |nested_meta_item| nested_meta_item.rewrite(context, item_shape), + self.span.lo, + self.span.hi, + ); + let item_vec = items.collect::>(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + shape: item_shape, + ends_with_newline: false, + config: context.config, + }; + format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt))) + } + ast::MetaItemKind::NameValue(ref literal) => { + let name = self.name.as_str(); + let value = context.snippet(literal.span); + if &*name == "doc" && value.starts_with("///") { + let doc_shape = Shape { + width: cmp::min(shape.width, context.config.comment_width()) + .checked_sub(shape.indent.width()) + .unwrap_or(0), + ..shape + }; + format!( + "{}", + try_opt!(rewrite_comment(&value, false, doc_shape, context.config)) + ) + } else { + format!("{} = {}", name, value) + } + } + }) } } impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - try_opt!(self.meta()) - .rewrite(context, shape) - .map(|rw| if rw.starts_with("///") { - rw - } else { - format!("#[{}]", rw) - }) + try_opt!(self.meta()).rewrite(context, shape).map(|rw| { + if rw.starts_with("///") { + rw + } else { + format!("#[{}]", rw) + } + }) } } @@ -741,13 +787,15 @@ impl<'a> Rewrite for [ast::Attribute] { let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; let comment = comment.trim(); if !comment.is_empty() { - let comment = - try_opt!(rewrite_comment(comment, - false, - Shape::legacy(context.config.comment_width() - - shape.indent.width(), - shape.indent), - context.config)); + let comment = try_opt!(rewrite_comment( + comment, + false, + Shape::legacy( + context.config.comment_width() - shape.indent.width(), + shape.indent, + ), + context.config, + )); result.push_str(&indent); result.push_str(&comment); result.push('\n'); -- cgit 1.4.1-3-g733a5 From 6f30d9e7c973d7bee78f8d16aa623f679c37bcae Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Jun 2017 16:01:41 +1200 Subject: Reformat tests --- src/imports.rs | 24 +-- src/items.rs | 12 +- src/patterns.rs | 24 +-- src/types.rs | 26 ++- tests/system.rs | 92 +++++---- tests/target/assignment.rs | 14 +- tests/target/chains-visual.rs | 69 +++---- tests/target/chains.rs | 56 +++--- tests/target/closure.rs | 67 +++---- tests/target/comment.rs | 16 +- tests/target/comments-fn.rs | 28 +-- tests/target/configs-array_width-above.rs | 16 +- .../configs-chain_split_single_child-true.rs | 5 +- .../configs-closure_block_indent_threshold-10.rs | 12 +- tests/target/configs-fn_args_density-compressed.rs | 12 +- .../configs-fn_args_density-compressed_if_empty.rs | 32 ++-- tests/target/configs-fn_args_density-tall.rs | 32 ++-- tests/target/configs-fn_args_density-vertical.rs | 52 ++--- .../target/configs-fn_args_paren_newline-false.rs | 4 +- tests/target/configs-fn_args_paren_newline-true.rs | 11 +- .../configs-fn_brace_style-always_next_line.rs | 3 +- .../configs-fn_brace_style-prefer_same_line.rs | 3 +- .../configs-fn_brace_style-same_line_where.rs | 3 +- tests/target/configs-fn_call_width-above.rs | 18 +- tests/target/configs-fn_return_indent-with_args.rs | 18 +- .../configs-fn_return_indent-with_where_clause.rs | 18 +- tests/target/configs-generics_indent-block.rs | 4 +- tests/target/configs-generics_indent-visual.rs | 18 +- .../configs-item_brace_style-always_next_line.rs | 3 +- .../configs-item_brace_style-prefer_same_line.rs | 3 +- .../configs-item_brace_style-same_line_where.rs | 3 +- tests/target/configs-trailing_comma-never.rs | 9 +- tests/target/configs-where_density-compressed.rs | 9 +- .../configs-where_density-compressed_if_empty.rs | 7 +- tests/target/configs-where_density-tall.rs | 6 +- tests/target/configs-where_density-vertical.rs | 6 +- tests/target/configs-where_layout-horizontal.rs | 10 +- .../configs-where_layout-horizontal_vertical.rs | 13 +- tests/target/configs-where_layout-mixed.rs | 11 +- tests/target/configs-where_layout-vertical.rs | 14 +- tests/target/configs-where_pred_indent-block.rs | 9 +- tests/target/configs-where_pred_indent-visual.rs | 9 +- tests/target/enum.rs | 40 ++-- tests/target/expr.rs | 209 +++++++++++++-------- tests/target/extern.rs | 41 ++-- tests/target/fn-args-with-last-line-comment.rs | 28 +-- tests/target/fn-custom-2.rs | 13 +- tests/target/fn-custom-3.rs | 13 +- tests/target/fn-custom-4.rs | 19 +- tests/target/fn-custom-6.rs | 12 +- tests/target/fn-custom-8.rs | 17 +- tests/target/fn-custom.rs | 12 +- tests/target/fn-simple.rs | 107 ++++++----- tests/target/fn-single-line.rs | 9 +- tests/target/fn-ty.rs | 22 ++- tests/target/fn.rs | 88 +++++---- tests/target/fn_args_density-vertical.rs | 23 ++- tests/target/fn_args_layout-block.rs | 27 +-- tests/target/hard-tabs.rs | 34 ++-- tests/target/impl.rs | 3 +- tests/target/impls.rs | 44 +++-- tests/target/issue-1049.rs | 21 ++- tests/target/issue-1239.rs | 10 +- tests/target/issue-1247.rs | 7 +- tests/target/issue-1366.rs | 8 +- tests/target/issue-1397.rs | 5 +- tests/target/issue-1468.rs | 50 ++--- tests/target/issue-510.rs | 27 +-- tests/target/item-brace-style-always-next-line.rs | 12 +- tests/target/item-brace-style-prefer-same-line.rs | 12 +- tests/target/item-brace-style-same-line-where.rs | 12 +- tests/target/large_vec.rs | 57 +++--- tests/target/long-fn-1.rs | 9 +- tests/target/long-match-arms-brace-newline.rs | 4 +- tests/target/loop.rs | 6 +- tests/target/macros.rs | 57 ++++-- tests/target/match-block-trailing-comma.rs | 8 +- tests/target/match-nowrap-trailing-comma.rs | 6 +- tests/target/match-nowrap.rs | 6 +- tests/target/match.rs | 203 +++++++++++--------- tests/target/mod-1.rs | 13 +- tests/target/multiple.rs | 60 +++--- tests/target/nested-if-else.rs | 16 +- tests/target/nested-visual-block.rs | 33 ++-- tests/target/nested_skipped/mod.rs | 2 +- tests/target/paths.rs | 23 +-- tests/target/space-before-bound.rs | 17 +- tests/target/spaces-within-angle-brackets.rs | 6 +- tests/target/spaces-within-square-brackets.rs | 24 +-- tests/target/static.rs | 53 +++++- tests/target/string-lit.rs | 10 +- tests/target/string_punctuation.rs | 14 +- tests/target/struct_lits.rs | 10 +- tests/target/struct_lits_multiline.rs | 10 +- tests/target/struct_tuple_visual.rs | 62 +++--- tests/target/structs.rs | 73 ++++--- tests/target/trailing_commas.rs | 47 +++-- tests/target/trait.rs | 34 ++-- tests/target/try-conversion.rs | 11 +- tests/target/tuple.rs | 80 +++++--- tests/target/type-ascription.rs | 6 +- tests/target/type-punctuation.rs | 12 +- tests/target/type_alias.rs | 74 ++++---- tests/target/where-clause.rs | 20 +- tests/writemode/target/checkstyle.xml | 2 +- 105 files changed, 1651 insertions(+), 1143 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 8a327069c2f..3b7c47f0fca 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -177,13 +177,11 @@ impl Rewrite for ast::ViewPath { let prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4)); let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); - Some( - if path.segments.last().unwrap().identifier == ident { - path_str - } else { - format!("{} as {}", path_str, ident_str) - }, - ) + Some(if path.segments.last().unwrap().identifier == ident { + path_str + } else { + format!("{} as {}", path_str, ident_str) + }) } } } @@ -392,13 +390,11 @@ pub fn rewrite_use_list( }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); - Some( - if path_str.is_empty() { - format!("{{{}}}", list_str) - } else { - format!("{}::{{{}}}", path_str, list_str) - }, - ) + Some(if path_str.is_empty() { + format!("{{{}}}", list_str) + } else { + format!("{}::{{{}}}", path_str, list_str) + }) } // Returns true when self item was found. diff --git a/src/items.rs b/src/items.rs index 3639e5ae0e5..01aa7b389d5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1990,13 +1990,11 @@ fn rewrite_fn_base( }); let snippet = snippet.trim(); if !snippet.is_empty() { - result.push( - if original_starts_with_newline { - '\n' - } else { - ' ' - }, - ); + result.push(if original_starts_with_newline { + '\n' + } else { + ' ' + }); result.push_str(snippet); if original_ends_with_newline { force_new_line_for_brace = true; diff --git a/src/patterns.rs b/src/patterns.rs index 67e4870f660..a52f42157b8 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -336,23 +336,19 @@ fn rewrite_tuple_pat( match path_str { Some(path_str) => { - Some( - if context.config.spaces_within_parens() { - format!("{}( {} )", path_str, list) - } else { - format!("{}({})", path_str, list) - }, - ) + Some(if context.config.spaces_within_parens() { + format!("{}( {} )", path_str, list) + } else { + format!("{}({})", path_str, list) + }) } None => { let comma = if add_comma { "," } else { "" }; - Some( - if context.config.spaces_within_parens() { - format!("( {}{} )", list, comma) - } else { - format!("({}{})", list, comma) - }, - ) + Some(if context.config.spaces_within_parens() { + format!("( {}{} )", list, comma) + } else { + format!("({}{})", list, comma) + }) } } } diff --git a/src/types.rs b/src/types.rs index f54e1c96eda..b1cea7df864 100644 --- a/src/types.rs +++ b/src/types.rs @@ -348,13 +348,11 @@ where String::new() }; - Some( - if context.config.spaces_within_parens() { - format!("( {} ){}{}", list_str, infix, output) - } else { - format!("({}){}{}", list_str, infix, output) - }, - ) + Some(if context.config.spaces_within_parens() { + format!("( {} ){}{}", list_str, infix, output) + } else { + format!("({}){}{}", list_str, infix, output) + }) } fn type_bound_colon(context: &RewriteContext) -> &'static str { @@ -588,13 +586,13 @@ impl Rewrite for ast::PolyTraitRef { ), )); - Some( - if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }, - ) + Some(if context.config.spaces_within_angle_brackets() && + lifetime_str.len() > 0 + { + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }) } else { self.trait_ref.rewrite(context, shape) } diff --git a/tests/system.rs b/tests/system.rs index b36676e4c37..970d9f0e2eb 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -84,9 +84,9 @@ fn assert_output(source: &str, expected_filename: &str) { let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); let mut expected_text = String::new(); - expected_file - .read_to_string(&mut expected_text) - .expect("Failed reading target"); + expected_file.read_to_string(&mut expected_text).expect( + "Failed reading target", + ); let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); if compare.len() > 0 { @@ -136,9 +136,11 @@ fn self_tests() { warnings += format_report.warning_count(); } - assert!(warnings == 0, - "Rustfmt's code generated {} warnings", - warnings); + assert!( + warnings == 0, + "Rustfmt's code generated {} warnings", + warnings + ); } #[test] @@ -170,7 +172,8 @@ fn format_lines_errors_are_reported() { // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: I) -> (Vec, u32, u32) - where I: Iterator +where + I: Iterator, { let mut count = 0; let mut fails = 0; @@ -217,10 +220,12 @@ fn read_config(filename: &str) -> Config { let mut config = if !sig_comments.is_empty() { get_config(sig_comments.get("config").map(|x| &(*x)[..])) } else { - get_config(Path::new(filename) - .with_extension("toml") - .file_name() - .and_then(std::ffi::OsStr::to_str)) + get_config( + Path::new(filename) + .with_extension("toml") + .file_name() + .and_then(std::ffi::OsStr::to_str), + ) }; for (key, val) in &sig_comments { @@ -280,9 +285,9 @@ fn get_config(config_file: Option<&str>) -> Config { let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); let mut def_config = String::new(); - def_config_file - .read_to_string(&mut def_config) - .expect("Couldn't read config"); + def_config_file.read_to_string(&mut def_config).expect( + "Couldn't read config", + ); Config::from_toml(&def_config).expect("Invalid toml") } @@ -305,16 +310,18 @@ fn read_significant_comments(file_name: &str) -> HashMap { .take_while(|line| line_regex.is_match(&line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { - (capture - .get(1) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - capture - .get(2) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned()) + ( + capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + ) }) }) .collect() @@ -322,9 +329,10 @@ fn read_significant_comments(file_name: &str) -> HashMap { // Compare output to input. // TODO: needs a better name, more explanation. -fn handle_result(result: HashMap, - target: Option<&str>) - -> Result<(), HashMap>> { +fn handle_result( + result: HashMap, + target: Option<&str>, +) -> Result<(), HashMap>> { let mut failures = HashMap::new(); for (file_name, fmt_text) in result { @@ -339,8 +347,10 @@ fn handle_result(result: HashMap, if fmt_text != text { let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); - assert!(!diff.is_empty(), - "Empty diff? Maybe due to a missing a newline at the end of a file?"); + assert!( + !diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?" + ); failures.insert(file_name, diff); } } @@ -374,15 +384,21 @@ fn get_target(file_name: &str, target: Option<&str>) -> String { #[test] fn rustfmt_diff_make_diff_tests() { let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); - assert_eq!(diff, - vec![Mismatch { - line_number: 1, - lines: vec![DiffLine::Context("a".into()), - DiffLine::Resulting("b".into()), - DiffLine::Expected("e".into()), - DiffLine::Context("c".into()), - DiffLine::Context("d".into())], - }]); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 1, + lines: vec![ + DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into()), + ], + }, + ] + ); } #[test] diff --git a/tests/target/assignment.rs b/tests/target/assignment.rs index fe8f3baae1e..1bd7dbc1d91 100644 --- a/tests/target/assignment.rs +++ b/tests/target/assignment.rs @@ -19,10 +19,14 @@ fn main() { fn break_meee() { { - (block_start, block_size, margin_block_start, margin_block_end) = - match (block_start, block_end, block_size) { - x => 1, - _ => 2, - }; + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) = match (block_start, block_end, block_size) { + x => 1, + _ => 2, + }; } } diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 52d271a4469..48222b14e6e 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -17,15 +17,15 @@ fn main() { // Test case where first chain element isn't a path, but is shorter than // the size of a tab. x().y(|| match cond() { - true => (), - false => (), - }); + true => (), + false => (), + }); loong_func().quux(move || if true { - 1 - } else { - 2 - }); + 1 + } else { + 2 + }); some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { let x = c; @@ -47,14 +47,15 @@ fn main() { }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = - xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); + xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold( + 0, + |acc, x| acc + x, + ); aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) + x += 1; + x + }) .filter(some_mod::some_filter) } @@ -82,11 +83,13 @@ fn floaters() { match x { PushParam => { // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); + stack.push( + mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone(), + ); } } } @@ -101,9 +104,9 @@ fn floaters() { Foo { x: val } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); Foo { @@ -111,17 +114,17 @@ fn floaters() { z: ok, } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); a + - match x { - true => "yay!", - false => "boo!", - } - .bar() + match x { + true => "yay!", + false => "boo!", + } + .bar() } fn is_replaced_content() -> bool { @@ -163,8 +166,10 @@ fn issue1434() { for _ in 0..100 { let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor) .chain_err(|| { - format!("could not read prototype ID at offset {:#010x}", - current_offset) - })?; + format!( + "could not read prototype ID at offset {:#010x}", + current_offset + ) + })?; } } diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 298c79ae91a..52e65b420e7 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -19,15 +19,15 @@ fn main() { // Test case where first chain element isn't a path, but is shorter than // the size of a tab. x().y(|| match cond() { - true => (), - false => (), - }); + true => (), + false => (), + }); loong_func().quux(move || if true { - 1 - } else { - 2 - }); + 1 + } else { + 2 + }); some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { let x = c; @@ -53,9 +53,9 @@ fn main() { aaaaaaaaaaaaaaaa .map(|x| { - x += 1; - x - }) + x += 1; + x + }) .filter(some_mod::some_filter) } @@ -81,10 +81,12 @@ fn floaters() { match x { PushParam => { // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }].clone()); + stack.push( + mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone(), + ); } } } @@ -98,25 +100,25 @@ fn floaters() { Foo { x: val } .baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); Foo { y: i_am_multi_line, z: ok, }.baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); a + - match x { - true => "yay!", - false => "boo!", - }.bar() + match x { + true => "yay!", + false => "boo!", + }.bar() } fn is_replaced_content() -> bool { @@ -163,7 +165,7 @@ fn issue_1004() { }?; ty::tls::with(|tcx| { - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - })?; + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + })?; } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index d51c76b9e48..4f35a7b413a 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -4,13 +4,17 @@ fn main() { let square = (|i: i32| i * i); - let commented = - |// first - a, // argument - // second - b: WithType, // argument - // ignored - _| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| { + ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ) + }; let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { @@ -91,9 +95,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { - l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - }) + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) } } } @@ -101,10 +105,10 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn foo() { lifetimes_iter___map(|lasdfasfd| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi - }; - }); + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi + }; + }); } fn issue1405() { @@ -124,17 +128,18 @@ fn issue470() { { { { - let explicit_arg_decls = explicit_arguments - .into_iter() - .enumerate() - .map(|(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); - block = this.pattern(block, - argument_extent, - hair::PatternRef::Hair(pattern), - &lvalue); - ArgDecl { ty: ty } - }); + let explicit_arg_decls = explicit_arguments.into_iter().enumerate().map(|(index, + (ty, + pattern))| { + let lvalue = Lvalue::Arg(index as u32); + block = this.pattern( + block, + argument_extent, + hair::PatternRef::Hair(pattern), + &lvalue, + ); + ArgDecl { ty: ty } + }); } } } @@ -144,19 +149,17 @@ fn issue470() { impl Foo { pub fn bar(&self) { Some(SomeType { - push_closure_out_to_100_chars: iter(otherwise_it_works_ok - .into_iter() - .map(|f| Ok(f))), - }) + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| Ok(f))), + }) } } fn issue1329() { aaaaaaaaaaaaaaaa .map(|x| { - x += 1; - x - }) + x += 1; + x + }) .filter } diff --git a/tests/target/comment.rs b/tests/target/comment.rs index a2f8d6ba0b4..a50c147de30 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -37,9 +37,11 @@ fn test() { // #1388 const EXCEPTION_PATHS: &'static [&'static str] = - &[// std crates - "src/libstd/sys/", // Platform-specific code for std lives here. - "src/bootstrap"]; + &[ + // std crates + "src/libstd/sys/", // Platform-specific code for std lives here. + "src/bootstrap", + ]; } /// test123 @@ -47,10 +49,10 @@ fn doc_comment() {} fn chains() { foo.bar(|| { - let x = 10; - // comment - x - }) + let x = 10; + // comment + x + }) } fn issue_1086() { diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 87b32f2915d..9a28c81a39e 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -1,17 +1,19 @@ // Test comments on functions are preserved. // Comment on foo. -fn foo(a: aaaaaaaaaaaaa, // A comment - b: bbbbbbbbbbbbb, // a second comment - c: ccccccccccccc, - // Newline comment - d: ddddddddddddd, - // A multi line comment - // between args. - e: eeeeeeeeeeeee /* comment before paren */) - -> bar - where F: Foo, // COmment after where clause - G: Goo // final comment +fn foo( + a: aaaaaaaaaaaaa, // A comment + b: bbbbbbbbbbbbb, // a second comment + c: ccccccccccccc, + // Newline comment + d: ddddddddddddd, + // A multi line comment + // between args. + e: eeeeeeeeeeeee, /* comment before paren */ +) -> bar +where + F: Foo, // COmment after where clause + G: Goo, // final comment { } @@ -20,6 +22,8 @@ fn bar() {} fn baz() -> Baz /* Comment after return type */ {} -fn some_fn() where T: Eq // some comment +fn some_fn() +where + T: Eq, // some comment { } diff --git a/tests/target/configs-array_width-above.rs b/tests/target/configs-array_width-above.rs index 8da896c1549..1265ebe0d8b 100644 --- a/tests/target/configs-array_width-above.rs +++ b/tests/target/configs-array_width-above.rs @@ -2,11 +2,13 @@ // Array width fn main() { - let lorem = vec!["ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit"]; + let lorem = vec![ + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ]; } diff --git a/tests/target/configs-chain_split_single_child-true.rs b/tests/target/configs-chain_split_single_child-true.rs index 154fa0bfa2e..c417e28d99c 100644 --- a/tests/target/configs-chain_split_single_child-true.rs +++ b/tests/target/configs-chain_split_single_child-true.rs @@ -1,6 +1,7 @@ // rustfmt-chain_split_single_child: true fn main() { - let files = fs::read_dir("tests/source") - .expect("Couldn't read source dir"); + let files = fs::read_dir("tests/source").expect( + "Couldn't read source dir", + ); } diff --git a/tests/target/configs-closure_block_indent_threshold-10.rs b/tests/target/configs-closure_block_indent_threshold-10.rs index 1a0c79ab234..21b47a8d7ca 100644 --- a/tests/target/configs-closure_block_indent_threshold-10.rs +++ b/tests/target/configs-closure_block_indent_threshold-10.rs @@ -3,10 +3,10 @@ fn main() { lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - }); + println!("lorem"); + println!("ipsum"); + println!("dolor"); + println!("sit"); + println!("amet"); + }); } diff --git a/tests/target/configs-fn_args_density-compressed.rs b/tests/target/configs-fn_args_density-compressed.rs index 5a24766d3b9..7bc949e5518 100644 --- a/tests/target/configs-fn_args_density-compressed.rs +++ b/tests/target/configs-fn_args_density-compressed.rs @@ -8,11 +8,15 @@ trait Lorem { // body } - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit); + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit + ); - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit) { + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit + ) { // body } } diff --git a/tests/target/configs-fn_args_density-compressed_if_empty.rs b/tests/target/configs-fn_args_density-compressed_if_empty.rs index c2fea2badd6..1a0f127f59c 100644 --- a/tests/target/configs-fn_args_density-compressed_if_empty.rs +++ b/tests/target/configs-fn_args_density-compressed_if_empty.rs @@ -8,25 +8,29 @@ trait Lorem { // body } - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit); + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); // FIXME: Previous line should be formatted like this: // fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, // adipiscing: Adipiscing, elit: Elit); - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit) { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { // body } } diff --git a/tests/target/configs-fn_args_density-tall.rs b/tests/target/configs-fn_args_density-tall.rs index 856501382f3..6ee43b41a19 100644 --- a/tests/target/configs-fn_args_density-tall.rs +++ b/tests/target/configs-fn_args_density-tall.rs @@ -8,21 +8,25 @@ trait Lorem { // body } - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit); + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit) { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { // body } } diff --git a/tests/target/configs-fn_args_density-vertical.rs b/tests/target/configs-fn_args_density-vertical.rs index ac4ef01efda..d48b3492452 100644 --- a/tests/target/configs-fn_args_density-vertical.rs +++ b/tests/target/configs-fn_args_density-vertical.rs @@ -2,33 +2,41 @@ // Function arguments density trait Lorem { - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet); + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ); - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet) { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ) { // body } - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit); + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); - fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit) { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { // body } } diff --git a/tests/target/configs-fn_args_paren_newline-false.rs b/tests/target/configs-fn_args_paren_newline-false.rs index ad2aec11ea8..031d39014b3 100644 --- a/tests/target/configs-fn_args_paren_newline-false.rs +++ b/tests/target/configs-fn_args_paren_newline-false.rs @@ -5,7 +5,7 @@ fn lorem( ipsum: Ipsum, dolor: Dolor, sit: Sit, - amet: Amet) - -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { + amet: Amet, +) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { // body } diff --git a/tests/target/configs-fn_args_paren_newline-true.rs b/tests/target/configs-fn_args_paren_newline-true.rs index 19b9c342b9c..50e9e6484d8 100644 --- a/tests/target/configs-fn_args_paren_newline-true.rs +++ b/tests/target/configs-fn_args_paren_newline-true.rs @@ -2,10 +2,11 @@ // Function arguments parenthesis on a newline fn lorem - (ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet) - -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { + ( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, +) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { // body } diff --git a/tests/target/configs-fn_brace_style-always_next_line.rs b/tests/target/configs-fn_brace_style-always_next_line.rs index a249cdf87d9..543fc015cba 100644 --- a/tests/target/configs-fn_brace_style-always_next_line.rs +++ b/tests/target/configs-fn_brace_style-always_next_line.rs @@ -12,7 +12,8 @@ fn lorem(ipsum: usize) } fn lorem(ipsum: T) - where T: Add + Sub + Mul + Div +where + T: Add + Sub + Mul + Div, { // body } diff --git a/tests/target/configs-fn_brace_style-prefer_same_line.rs b/tests/target/configs-fn_brace_style-prefer_same_line.rs index 25d05f761e4..498ed9f2a99 100644 --- a/tests/target/configs-fn_brace_style-prefer_same_line.rs +++ b/tests/target/configs-fn_brace_style-prefer_same_line.rs @@ -10,6 +10,7 @@ fn lorem(ipsum: usize) { } fn lorem(ipsum: T) - where T: Add + Sub + Mul + Div { +where + T: Add + Sub + Mul + Div, { // body } diff --git a/tests/target/configs-fn_brace_style-same_line_where.rs b/tests/target/configs-fn_brace_style-same_line_where.rs index 664f256e122..4da07441eaa 100644 --- a/tests/target/configs-fn_brace_style-same_line_where.rs +++ b/tests/target/configs-fn_brace_style-same_line_where.rs @@ -10,7 +10,8 @@ fn lorem(ipsum: usize) { } fn lorem(ipsum: T) - where T: Add + Sub + Mul + Div +where + T: Add + Sub + Mul + Div, { // body } diff --git a/tests/target/configs-fn_call_width-above.rs b/tests/target/configs-fn_call_width-above.rs index 5e763106072..3f84928ed59 100644 --- a/tests/target/configs-fn_call_width-above.rs +++ b/tests/target/configs-fn_call_width-above.rs @@ -2,12 +2,14 @@ // Function call width fn main() { - lorem("lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit"); + lorem( + "lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ); } diff --git a/tests/target/configs-fn_return_indent-with_args.rs b/tests/target/configs-fn_return_indent-with_args.rs index ab08d0bfe0f..e1d49a65c25 100644 --- a/tests/target/configs-fn_return_indent-with_args.rs +++ b/tests/target/configs-fn_return_indent-with_args.rs @@ -1,14 +1,16 @@ // rustfmt-fn_return_indent: WithArgs // Function return type indent -fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing) - -> Elit - where Ipsum: Eq +fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: Consectetur, + adipiscing: Adipiscing, +) -> Elit +where + Ipsum: Eq, { // body } diff --git a/tests/target/configs-fn_return_indent-with_where_clause.rs b/tests/target/configs-fn_return_indent-with_where_clause.rs index 279949c982b..62a35af516b 100644 --- a/tests/target/configs-fn_return_indent-with_where_clause.rs +++ b/tests/target/configs-fn_return_indent-with_where_clause.rs @@ -1,14 +1,16 @@ // rustfmt-fn_return_indent: WithWhereClause // Function return type indent -fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing) - -> Elit - where Ipsum: Eq +fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: Consectetur, + adipiscing: Adipiscing, +) -> Elit +where + Ipsum: Eq, { // body } diff --git a/tests/target/configs-generics_indent-block.rs b/tests/target/configs-generics_indent-block.rs index 848e59c7c0a..53175fa362f 100644 --- a/tests/target/configs-generics_indent-block.rs +++ b/tests/target/configs-generics_indent-block.rs @@ -15,7 +15,7 @@ fn lorem< amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, - elit: Elit) - -> T { + elit: Elit, +) -> T { // body } diff --git a/tests/target/configs-generics_indent-visual.rs b/tests/target/configs-generics_indent-visual.rs index 6ae0f775c22..1160772f29f 100644 --- a/tests/target/configs-generics_indent-visual.rs +++ b/tests/target/configs-generics_indent-visual.rs @@ -7,14 +7,14 @@ fn lorem - (ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - adipiscing: Adipiscing, - consectetur: Consectetur, - elit: Elit) - -> T { + Elit: Eq = usize>( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + adipiscing: Adipiscing, + consectetur: Consectetur, + elit: Elit, +) -> T { // body } diff --git a/tests/target/configs-item_brace_style-always_next_line.rs b/tests/target/configs-item_brace_style-always_next_line.rs index 6095149a514..b9334677e1f 100644 --- a/tests/target/configs-item_brace_style-always_next_line.rs +++ b/tests/target/configs-item_brace_style-always_next_line.rs @@ -7,7 +7,8 @@ struct Lorem } struct Dolor - where T: Eq +where + T: Eq, { sit: T, } diff --git a/tests/target/configs-item_brace_style-prefer_same_line.rs b/tests/target/configs-item_brace_style-prefer_same_line.rs index 0b65ecc30c1..3d2e4fd537e 100644 --- a/tests/target/configs-item_brace_style-prefer_same_line.rs +++ b/tests/target/configs-item_brace_style-prefer_same_line.rs @@ -6,6 +6,7 @@ struct Lorem { } struct Dolor - where T: Eq { +where + T: Eq, { sit: T, } diff --git a/tests/target/configs-item_brace_style-same_line_where.rs b/tests/target/configs-item_brace_style-same_line_where.rs index 33d6501f424..21a10cb28a1 100644 --- a/tests/target/configs-item_brace_style-same_line_where.rs +++ b/tests/target/configs-item_brace_style-same_line_where.rs @@ -6,7 +6,8 @@ struct Lorem { } struct Dolor - where T: Eq +where + T: Eq, { sit: T, } diff --git a/tests/target/configs-trailing_comma-never.rs b/tests/target/configs-trailing_comma-never.rs index 949069cede8..f38d26d64db 100644 --- a/tests/target/configs-trailing_comma-never.rs +++ b/tests/target/configs-trailing_comma-never.rs @@ -14,10 +14,11 @@ fn main() { // #1544 if let VrMsg::ClientReply { - request_num: reply_req_num, - value, - .. - } = msg { + request_num: reply_req_num, + value, + .. + } = msg + { let _ = safe_assert_eq!(reply_req_num, request_num, op); return Ok((request_num, op, value)); } diff --git a/tests/target/configs-where_density-compressed.rs b/tests/target/configs-where_density-compressed.rs index d10c860db07..215c10c2d7a 100644 --- a/tests/target/configs-where_density-compressed.rs +++ b/tests/target/configs-where_density-compressed.rs @@ -2,9 +2,14 @@ // Where density trait Lorem { - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq; + fn ipsum(dolor: Dolor) -> Sit + where + Dolor: Eq; - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq { + fn ipsum(dolor: Dolor) -> Sit + where + Dolor: Eq, + { // body } } diff --git a/tests/target/configs-where_density-compressed_if_empty.rs b/tests/target/configs-where_density-compressed_if_empty.rs index 101a1c92575..2a5da551f37 100644 --- a/tests/target/configs-where_density-compressed_if_empty.rs +++ b/tests/target/configs-where_density-compressed_if_empty.rs @@ -2,10 +2,13 @@ // Where density trait Lorem { - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq; + fn ipsum(dolor: Dolor) -> Sit + where + Dolor: Eq; fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq + where + Dolor: Eq, { // body } diff --git a/tests/target/configs-where_density-tall.rs b/tests/target/configs-where_density-tall.rs index cdf84f37f5c..e256f1c221c 100644 --- a/tests/target/configs-where_density-tall.rs +++ b/tests/target/configs-where_density-tall.rs @@ -3,10 +3,12 @@ trait Lorem { fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq; + where + Dolor: Eq; fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq + where + Dolor: Eq, { // body } diff --git a/tests/target/configs-where_density-vertical.rs b/tests/target/configs-where_density-vertical.rs index 9fb9837710a..96ac111ba74 100644 --- a/tests/target/configs-where_density-vertical.rs +++ b/tests/target/configs-where_density-vertical.rs @@ -3,10 +3,12 @@ trait Lorem { fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq; + where + Dolor: Eq; fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq + where + Dolor: Eq, { // body } diff --git a/tests/target/configs-where_layout-horizontal.rs b/tests/target/configs-where_layout-horizontal.rs index 5778c0c66e5..062f62ff4e7 100644 --- a/tests/target/configs-where_layout-horizontal.rs +++ b/tests/target/configs-where_layout-horizontal.rs @@ -3,13 +3,19 @@ // Where layout fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, { // body } fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, + Sit: SitAmetConsecteturAdipiscing, + Amet: AmetConsecteturAdipiscingElit, { // body } diff --git a/tests/target/configs-where_layout-horizontal_vertical.rs b/tests/target/configs-where_layout-horizontal_vertical.rs index 8906056caa9..56d125e1cf7 100644 --- a/tests/target/configs-where_layout-horizontal_vertical.rs +++ b/tests/target/configs-where_layout-horizontal_vertical.rs @@ -2,16 +2,19 @@ // Where layout fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, { // body } fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, + Sit: SitAmetConsecteturAdipiscing, + Amet: AmetConsecteturAdipiscingElit, { // body } diff --git a/tests/target/configs-where_layout-mixed.rs b/tests/target/configs-where_layout-mixed.rs index 636e42ac6ac..fa896b77267 100644 --- a/tests/target/configs-where_layout-mixed.rs +++ b/tests/target/configs-where_layout-mixed.rs @@ -2,14 +2,19 @@ // Where layout fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, { // body } fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, + Sit: SitAmetConsecteturAdipiscing, + Amet: AmetConsecteturAdipiscingElit, { // body } diff --git a/tests/target/configs-where_layout-vertical.rs b/tests/target/configs-where_layout-vertical.rs index 9efe0cf04b8..024a74dd9ac 100644 --- a/tests/target/configs-where_layout-vertical.rs +++ b/tests/target/configs-where_layout-vertical.rs @@ -2,17 +2,19 @@ // Where layout fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, { // body } fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit +where + Ipsum: IpsumDolorSitAmet, + Dolor: DolorSitAmetConsectetur, + Sit: SitAmetConsecteturAdipiscing, + Amet: AmetConsecteturAdipiscingElit, { // body } diff --git a/tests/target/configs-where_pred_indent-block.rs b/tests/target/configs-where_pred_indent-block.rs index 7df9a3e7c22..b880995ccce 100644 --- a/tests/target/configs-where_pred_indent-block.rs +++ b/tests/target/configs-where_pred_indent-block.rs @@ -2,10 +2,11 @@ // Where predicate indent fn lorem() -> T - where Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq +where + Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq, { // body } diff --git a/tests/target/configs-where_pred_indent-visual.rs b/tests/target/configs-where_pred_indent-visual.rs index 5136470372e..11da3a3ba85 100644 --- a/tests/target/configs-where_pred_indent-visual.rs +++ b/tests/target/configs-where_pred_indent-visual.rs @@ -2,10 +2,11 @@ // Where predicate indent fn lorem() -> T - where Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq +where + Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq, { // body } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 0bb18e2df67..6ff1750ae01 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -11,7 +11,8 @@ pub enum Test { } pub enum Foo<'a, Y: Baz> - where X: Whatever +where + X: Whatever, { A, } @@ -29,8 +30,10 @@ enum Bar { } enum LongVariants { - First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment - VARIANT), + First( + LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment + VARIANT + ), // This is the second variant Second, } @@ -47,9 +50,11 @@ enum StructLikeVariants { } enum X { - CreateWebGLPaintTask(Size2D, - GLContextAttributes, - IpcSender, usize), String>>), /* This is a post comment */ + CreateWebGLPaintTask( + Size2D, + GLContextAttributes, + IpcSender, usize), String>> + ), // This is a post comment } pub enum EnumWithAttributes { @@ -79,7 +84,8 @@ pub enum SingleStruct { } pub enum GenericEnum - where I: Iterator +where + I: Iterator, { // Pre Comment Left { list: I, root: T }, // Post-comment @@ -98,7 +104,7 @@ enum TestFormatFails { fn nested_enum_test() { if true { enum TestEnum { - One(usize, + One( usize, usize, usize, @@ -113,8 +119,10 @@ fn nested_enum_test() { usize, usize, usize, - usize), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAA */ + usize, + usize + ), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAA */ Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAA */ } @@ -142,9 +150,11 @@ pub enum Bencoding<'i> { // #1261 pub enum CoreResourceMsg { - SetCookieForUrl(ServoUrl, - #[serde(deserialize_with = "::hyper_serde::deserialize", - serialize_with = "::hyper_serde::serialize")] - Cookie, - CookieSource), + SetCookieForUrl( + ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource + ), } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 5cd5452fd27..3932992af62 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -7,23 +7,21 @@ fn foo() -> bool { let referenced = &5; let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + - BBBBBBBBBBBBBBBBB + b + c); + let very_long_variable_name = + (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); let is_internalxxxx = self.codemap.span_to_filename(s) == - self.codemap.span_to_filename(m.inner); + self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / - (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; + (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; - some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + - 40000 / 1002200000000 - - 50000 * sqrt(-1), - trivial_value); - (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaa))))))))); + some_ridiculously_loooooooooooooooooooooong_function( + 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), + trivial_value, + ); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; { for _ in 0..10 {} @@ -49,18 +47,22 @@ fn foo() -> bool { } if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) + {} if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + { } if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = - 1111 + 2222 {} + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = + 1111 + 2222 + {} if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {} + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + {} let test = if true { 5 } else { 3 }; @@ -71,13 +73,13 @@ fn foo() -> bool { } else { // Check subformatting aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } } fn bar() { let range = (111111111 + 333333333333333333 + 1111 + 400000000000000000).. - (2222 + 2333333333333333); + (2222 + 2333333333333333); let another_range = 5..some_func(a, b /* comment */); @@ -85,10 +87,12 @@ fn bar() { call_forever(); } - syntactically_correct(loop { - sup('?'); - }, - if cond { 0 } else { 1 }); + syntactically_correct( + loop { + sup('?'); + }, + if cond { 0 } else { 1 }, + ); let third = ..10; let infi_range = ..; @@ -102,8 +106,10 @@ fn bar() { } } - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - a); + let x = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + a, + ); } fn baz() { @@ -144,8 +150,8 @@ fn qux() { fn issue227() { { - let handler = box DocumentProgressHandler::new(addr, - DocumentProgressTask::DOMContentLoaded); + let handler = + box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); } } @@ -158,59 +164,104 @@ fn issue184(source: &str) { } fn arrays() { - let x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 0]; - - let y = [// comment - 1, - 2, // post comment - 3]; - - let xy = [strukt { - test123: value_one_two_three_four, - turbo: coolio(), - }, - // comment - 1]; - - let a = WeightedChoice::new(&mut [Weighted { - weightweight: x, - item: 0, - }, - Weighted { - weightweight: 1, - item: 1, - }, - Weighted { - weightweight: x, - item: 2, - }, - Weighted { - weightweight: 1, - item: 3, - }]); - - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q]; + let x = [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + ]; + + let y = [ + // comment + 1, + 2, // post comment + 3, + ]; + + let xy = [ + strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + // comment + 1, + ]; + + let a = WeightedChoice::new( + &mut [ + Weighted { + weightweight: x, + item: 0, + }, + Weighted { + weightweight: 1, + item: 1, + }, + Weighted { + weightweight: x, + item: 2, + }, + Weighted { + weightweight: 1, + item: 3, + }, + ], + ); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q, + ]; [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } fn returns() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && - return; + return; return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; } fn addrof() { &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); } fn casts() { @@ -220,7 +271,7 @@ fn casts() { let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; let slightly_longer_trait = yyyyyyyyy + - yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; } fn indices() { @@ -232,9 +283,9 @@ fn indices() { fn repeats() { let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; - x + y + z]; + x + y + z]; let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; - xxxxx + yyyyy + zzzzz]; + xxxxx + yyyyy + zzzzz]; } fn blocks() { @@ -257,7 +308,7 @@ fn issue767() { fn ranges() { let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ...x; a...b @@ -279,10 +330,12 @@ fn complex_if_else() { } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { yo(); } else if let Some(x) = - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + { ha(); } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + - xxxxxxxxx { + xxxxxxxxx + { yo(); } } @@ -290,10 +343,12 @@ fn complex_if_else() { fn issue1106() { { if let hir::ItemEnum(ref enum_def, ref generics) = - self.ast_map.expect_item(enum_node_id).node {} + self.ast_map.expect_item(enum_node_id).node + {} } - for entry in WalkDir::new(path) - .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) {} + for entry in WalkDir::new(path).into_iter().filter_entry(|entry| { + exclusions.filter_entry(entry) + }) + {} } diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 06d9d771e79..efee6ab26bf 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -3,8 +3,10 @@ extern "C" { fn c_func(x: *mut *mut libc::c_void); - fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, - y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); + fn c_func( + x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, + y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY, + ); #[test123] fn foo() -> uint64_t; @@ -13,12 +15,13 @@ extern "C" { } extern "C" { - fn DMR_GetDevice(pHDev: *mut HDEV, - searchMode: DeviceSearchMode, - pSearchString: *const c_char, - devNr: c_uint, - wildcard: c_char) - -> TDMR_ERROR; + fn DMR_GetDevice( + pHDev: *mut HDEV, + searchMode: DeviceSearchMode, + pSearchString: *const c_char, + devNr: c_uint, + wildcard: c_char, + ) -> TDMR_ERROR; fn quux() -> (); // Post comment } @@ -30,21 +33,23 @@ extern "Rust" { } extern "C" { - fn syscall(number: libc::c_long, // comment 1 - // comm 2 - ... /* sup? */) - -> libc::c_long; + fn syscall( + number: libc::c_long, // comment 1 + // comm 2 + ... // sup? + ) -> libc::c_long; fn foo(x: *const c_char, ...) -> libc::c_long; } extern "C" { - pub fn freopen(filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE) - -> *mut FILE; + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE, + ) -> *mut FILE; } extern "C" {} diff --git a/tests/target/fn-args-with-last-line-comment.rs b/tests/target/fn-args-with-last-line-comment.rs index 2e310747cc4..2ffb3909b74 100644 --- a/tests/target/fn-args-with-last-line-comment.rs +++ b/tests/target/fn-args-with-last-line-comment.rs @@ -1,22 +1,24 @@ // #1587 pub trait X { fn a(&self) -> &'static str; - fn bcd(&self, - c: &str, // comment on this arg - d: u16, // comment on this arg - e: &Vec, // comment on this arg - ) -> Box; + fn bcd( + &self, + c: &str, // comment on this arg + d: u16, // comment on this arg + e: &Vec, // comment on this arg + ) -> Box; } // #1595 -fn foo(arg1: LongTypeName, - arg2: LongTypeName, - arg3: LongTypeName, - arg4: LongTypeName, - arg5: LongTypeName, - arg6: LongTypeName, - arg7: LongTypeName, +fn foo( + arg1: LongTypeName, + arg2: LongTypeName, + arg3: LongTypeName, + arg4: LongTypeName, + arg5: LongTypeName, + arg6: LongTypeName, + arg7: LongTypeName, //arg8: LongTypeName, - ) { +) { // do stuff } diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index f0923bd1a85..430ffeb9fb7 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -24,14 +24,18 @@ fn bar< } fn baz() - where X: TTTTTTTT +where + X: TTTTTTTT, { baz(); } fn qux() - where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, { baz(); } @@ -59,7 +63,8 @@ impl Foo { } fn baz() - where X: TTTTTTTT + where + X: TTTTTTTT, { baz(); } diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 4d26c9b6951..655f1f1dc5b 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -24,16 +24,19 @@ fn bar< } fn qux() - where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, { baz(); } fn qux() - where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, { baz(); } diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs index d2ba91b7632..c044becc782 100644 --- a/tests/target/fn-custom-4.rs +++ b/tests/target/fn-custom-4.rs @@ -3,21 +3,26 @@ // Test different indents. fn qux() - where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, { baz(); } -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ baz(); } fn qux(a: Aaaaaaaaaaaaaaaaa) - where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, { baz(); } diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 487d1d8b7ea..9a2d8d8981a 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -31,7 +31,8 @@ fn bar( } fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) - where T: UUUUUUUUUUU { +where + T: UUUUUUUUUUU, { foo(); } @@ -41,12 +42,14 @@ fn bar( c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, -) where T: UUUUUUUUUUU { +) where + T: UUUUUUUUUUU, { bar(); } fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String - where T: UUUUUUUUUUU { +where + T: UUUUUUUUUUU, { foo(); } @@ -57,7 +60,8 @@ fn bar( d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, ) -> String - where T: UUUUUUUUUUU { +where + T: UUUUUUUUUUU, { bar(); } diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index b32fc5d7cf2..854f4231480 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -31,7 +31,8 @@ fn bar( } fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) - where T: UUUUUUUUUUU { +where + T: UUUUUUUUUUU, { foo(); } @@ -41,12 +42,14 @@ fn bar( c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, -) where T: UUUUUUUUUUU { +) where + T: UUUUUUUUUUU, { bar(); } fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String - where T: UUUUUUUUUUU { +where + T: UUUUUUUUUUU, { foo(); } @@ -57,7 +60,8 @@ fn bar( d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, ) -> String - where T: UUUUUUUUUUU { +where + T: UUUUUUUUUUU, { bar(); } @@ -67,7 +71,8 @@ trait Test { fn bar(a: u8) -> String {} fn bar(a: u8) -> String - where Foo: foooo, - Bar: barrr { + where + Foo: foooo, + Bar: barrr, { } } diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index ad36de7a997..7a2ea722bfd 100644 --- a/tests/target/fn-custom.rs +++ b/tests/target/fn-custom.rs @@ -2,14 +2,18 @@ // Test some of the ways function signatures can be customised. // Test compressed layout of args. -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { +fn foo( + a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee +) { foo(); } impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + fn foo( + self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee + ) { foo(); } } diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 697fe21501c..d0c15c643f5 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -1,77 +1,88 @@ // rustfmt-normalize_comments: true -fn simple(// pre-comment on a function!? - i: i32, // yes, it's possible! - response: NoWay /* hose */) { - fn op(x: Typ, - key: &[u8], - upd: Box) - -> (memcache::Status, Result>)>) - -> MapResult { +fn simple( + // pre-comment on a function!? + i: i32, // yes, it's possible! + response: NoWay, // hose +) { + fn op( + x: Typ, + key: &[u8], + upd: Box) + -> (memcache::Status, Result>)>, + ) -> MapResult { } "cool" } -fn weird_comment(// /*/ double level */ comment - x: Hello, // /*/* tripple, even */*/ - // Does this work? - y: World) { - simple(// does this preserve comments now? - 42, - NoWay) +fn weird_comment( + // /*/ double level */ comment + x: Hello, // /*/* tripple, even */*/ + // Does this work? + y: World, +) { + simple( + // does this preserve comments now? + 42, + NoWay, + ) } fn generic(arg: T) -> &SomeType - where T: Fn(// First arg - A, - // Second argument - B, - C, - D, - // pre comment - E /* last comment */) - -> &SomeType +where + T: Fn(// First arg + A, + // Second argument + B, + C, + D, + // pre comment + E /* last comment */) + -> &SomeType, { arg(a, b, c, d, e) } fn foo() -> ! {} -pub fn http_fetch_async(listener: Box, - script_chan: Box) { +pub fn http_fetch_async( + listener: Box, + script_chan: Box, +) { } fn some_func>(val: T) {} -fn zzzzzzzzzzzzzzzzzzzz(selff: Type, - mut handle: node::Handle>, - Type, - NodeType>) - -> SearchStack<'a, K, V, Type, NodeType> { +fn zzzzzzzzzzzzzzzzzzzz( + selff: Type, + mut handle: node::Handle>, Type, NodeType>, +) -> SearchStack<'a, K, V, Type, NodeType> { } -unsafe fn generic_call(cx: *mut JSContext, - argc: libc::c_uint, - vp: *mut JSVal, - is_lenient: bool, - call: unsafe extern "C" fn(*const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal) - -> u8) { +unsafe fn generic_call( + cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern "C" fn(*const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal) + -> u8, +) { let f: fn(_, _) -> _ = panic!(); } -pub fn start_export_thread - (database: &Database, - crypto_scheme: &C, - block_size: usize, - source_path: &Path) - -> BonzoResult> { +pub fn start_export_thread( + database: &Database, + crypto_scheme: &C, + block_size: usize, + source_path: &Path, +) -> BonzoResult> { } pub fn waltz(cwd: &Path) -> CliAssert { diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs index 049206b60c8..3617506d89a 100644 --- a/tests/target/fn-single-line.rs +++ b/tests/target/fn-single-line.rs @@ -14,7 +14,8 @@ fn empty() {} fn foo_return() -> String { "yay" } fn foo_where() -> T - where T: Sync +where + T: Sync, { let x = 2; } @@ -62,4 +63,8 @@ trait CoolerTypes { fn dummy(&self) {} } -fn Foo() where T: Bar {} +fn Foo() +where + T: Bar, +{ +} diff --git a/tests/target/fn-ty.rs b/tests/target/fn-ty.rs index 7432fcded34..7d48f3b32db 100644 --- a/tests/target/fn-ty.rs +++ b/tests/target/fn-ty.rs @@ -1,12 +1,14 @@ -fn f(xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, - xxxxxxxxxxxxxxxxxx: fn() -> a, - xxxxxxxxxxxxxxxxxx: fn(a, b, b), - xxxxxxxxxxxxxxxxxx: fn(), - xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, - xxxxxxxxxxxxxxxxxx: fn() -> !) - where F1: Fn(a, b, b) -> a, - F2: Fn(a, b, b), - F3: Fn(), - F4: Fn() -> u32 +fn f( + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, + xxxxxxxxxxxxxxxxxx: fn() -> a, + xxxxxxxxxxxxxxxxxx: fn(a, b, b), + xxxxxxxxxxxxxxxxxx: fn(), + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, + xxxxxxxxxxxxxxxxxx: fn() -> !, +) where + F1: Fn(a, b, b) -> a, + F2: Fn(a, b, b), + F3: Fn(), + F4: Fn() -> u32, { } diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 01806ac3cd8..7a09ec6e83c 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -2,24 +2,36 @@ fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} -fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType where T: Blah {} +fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType +where + T: Blah, +{ +} -fn foo(a: AAA /* (comment) */) where T: Blah {} +fn foo(a: AAA /* (comment) */) +where + T: Blah, +{ +} -fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) - -> RetType - where T: Blah +fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +) -> RetType +where + T: Blah, { } -fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) - -> RetType - where T: Blah, - U: dsfasdfasdfasd +fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +) -> RetType +where + T: Blah, + U: dsfasdfasdfasd, { } @@ -27,21 +39,27 @@ fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, fn foo B /* paren inside generics */>() {} impl Foo { - fn with_no_errors(&mut self, f: F) -> T where F: FnOnce(&mut Resolver) -> T {} + fn with_no_errors(&mut self, f: F) -> T + where + F: FnOnce(&mut Resolver) -> T, + { + } fn foo(mut self, mut bar: u32) {} fn bar(self, mut bazz: u32) {} } -pub fn render<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write> - (g: &'a G, - w: &mut W) - -> io::Result<()> { +pub fn render< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write +>( + g: &'a G, + w: &mut W, +) -> io::Result<()> { render_opts(g, w, &[]) } @@ -81,23 +99,23 @@ fn foo(a: i32) -> i32 { if a > 0 { 1 } else { 2 } } -fn ______________________baz - (a: i32) - -> *mut ::std::option::Option ()> { +fn ______________________baz( + a: i32, +) -> *mut ::std::option::Option ()> { } -pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - path: &hir::Path, - id: ast::NodeId, - cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option)) { +pub fn check_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), +) { } -pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - path: &hir::Path, - id: ast::NodeId, - cb: &mut FnMut(DefId, - Span, - &Option<&Stability>, - &Option)) { +pub fn check_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), +) { } diff --git a/tests/target/fn_args_density-vertical.rs b/tests/target/fn_args_density-vertical.rs index 250d32654e5..dcc8478a138 100644 --- a/tests/target/fn_args_density-vertical.rs +++ b/tests/target/fn_args_density-vertical.rs @@ -11,12 +11,13 @@ fn do_bar(a: u8) -> u8 { } // Multiple arguments should each get their own line. -fn do_bar(a: u8, - mut b: u8, - c: &u8, - d: &mut u8, - closure: &Fn(i32) -> i32) - -> i32 { +fn do_bar( + a: u8, + mut b: u8, + c: &u8, + d: &mut u8, + closure: &Fn(i32) -> i32, +) -> i32 { // This feature should not affect closures. let bar = |x: i32, y: i32| -> i32 { x + y }; bar(a, b) @@ -26,10 +27,12 @@ fn do_bar(a: u8, // the whole list should probably be pushed to the next line with hanging // indent. That's not what happens though, so check current behaviour instead. // In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, - c: u8, - d: u8) { +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, + c: u8, + d: u8, +) { this(); that(); the_other_thing(); diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index 27a98cfe7f9..93f14c526bd 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -54,8 +54,9 @@ fn bar( d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee, ) -> String - where X: Fooooo, - Y: Baaar +where + X: Fooooo, + Y: Baaar, { bar(); } @@ -65,22 +66,27 @@ fn foo() -> T { } fn foo() -> T - where X: Foooo, - Y: Baaar +where + X: Foooo, + Y: Baaar, { foo(); } -fn foo() where X: Foooo {} +fn foo() +where + X: Foooo, +{ +} fn foo() - where X: Foooo, - Y: Baaar +where + X: Foooo, + Y: Baaar, { } -fn foo - () +fn foo() -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) { foo(); @@ -90,8 +96,7 @@ fn foo() { foo(); } -fn foo - () { +fn foo() { foo(); } diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index bdd07ffbd74..2781d54af88 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -22,7 +22,8 @@ fn main() { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {} + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + {} if cond() { something(); @@ -30,7 +31,7 @@ fn main() { something_else(); } else { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong @@ -47,21 +48,24 @@ fn main() { .go_to_next_line_with_tab() .go_to_next_line_with_tab(); - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q]; + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q, + ]; fn generic(arg: T) -> &SomeType - where T: Fn(// First arg - A, - // Second argument - B, - C, - D, - // pre comment - E /* last comment */) - -> &SomeType + where + T: Fn(// First arg + A, + // Second argument + B, + C, + D, + // pre comment + E /* last comment */) + -> &SomeType, { arg(a, b, c, d, e) } diff --git a/tests/target/impl.rs b/tests/target/impl.rs index c51693afd22..528d80fd5a5 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -7,7 +7,8 @@ impl>> Handle Test - where V: Clone // This comment is NOT removed by formating! +where + V: Clone, // This comment is NOT removed by formating! { pub fn new(value: V) -> Self { Test { diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 654d4be8967..216c9d5193d 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -22,7 +22,8 @@ pub impl Foo for Bar { } pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> - where X: Foo<'a, Z> +where + X: Foo<'a, Z>, { fn foo() { "hi" @@ -30,7 +31,8 @@ pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> - where X: Fooooooooooooooooooooooooooooo<'a, Z> +where + X: Fooooooooooooooooooooooooooooo<'a, Z>, { fn foo() { "hi" @@ -38,17 +40,23 @@ impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> - where X: Foooooooooooooooooooooooooooo<'a, Z> +where + X: Foooooooooooooooooooooooooooo<'a, Z>, { fn foo() { "hi" } } -impl Foo for Bar where T: Baz {} +impl Foo for Bar +where + T: Baz, +{ +} impl Foo for Bar - where T: Baz +where + T: Baz, { // Comment } @@ -101,7 +109,8 @@ impl Y5000 { } pub impl Foo for Bar - where T: Foo +where + T: Foo, { fn foo() { "hi" @@ -109,21 +118,27 @@ pub impl Foo for Bar } pub impl Foo for Bar - where T: Foo, - Z: Baz +where + T: Foo, + Z: Baz, { } mod m { impl PartialEq for S - where T: PartialEq + where + T: PartialEq, { fn eq(&self, other: &Self) { true } } - impl PartialEq for S where T: PartialEq {} + impl PartialEq for S + where + T: PartialEq, + { + } } impl @@ -136,10 +151,11 @@ impl PartialEq mod x { impl Foo - where A: 'static, - B: 'static, - C: 'static, - D: 'static + where + A: 'static, + B: 'static, + C: 'static, + D: 'static, { } } diff --git a/tests/target/issue-1049.rs b/tests/target/issue-1049.rs index 020ac6ff0d9..416db998065 100644 --- a/tests/target/issue-1049.rs +++ b/tests/target/issue-1049.rs @@ -1,15 +1,18 @@ // Test overlong function signature -pub unsafe fn reborrow_mut(&mut X: Abcde) - -> Handle, HandleType> { +pub unsafe fn reborrow_mut( + &mut X: Abcde, +) -> Handle, HandleType> { } -pub fn merge(mut X: Abcdef) - -> Handle, K, V, marker::Internal>, marker::Edge> { +pub fn merge( + mut X: Abcdef, +) -> Handle, K, V, marker::Internal>, marker::Edge> { } impl Handle { - pub fn merge(a: Abcd) - -> Handle, K, V, marker::Internal>, marker::Edge> { + pub fn merge( + a: Abcd, + ) -> Handle, K, V, marker::Internal>, marker::Edge> { } } @@ -19,6 +22,8 @@ fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeee fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { } -fn veeeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, - b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { +fn veeeeeeeeeeeeeeeeeeeeeeery_long_name( + a: FirstTypeeeeeeeeee, + b: SecondTypeeeeeeeeeeeeeeeeeeeeeee, +) { } diff --git a/tests/target/issue-1239.rs b/tests/target/issue-1239.rs index c8da3573e95..8db0d195ae6 100644 --- a/tests/target/issue-1239.rs +++ b/tests/target/issue-1239.rs @@ -1,9 +1,11 @@ fn foo() { let with_alignment = if condition__uses_alignment_for_first_if__0 || - condition__uses_alignment_for_first_if__1 || - condition__uses_alignment_for_first_if__2 { + condition__uses_alignment_for_first_if__1 || + condition__uses_alignment_for_first_if__2 + { } else if condition__no_alignment_for_later_else__0 || - condition__no_alignment_for_later_else__1 || - condition__no_alignment_for_later_else__2 { + condition__no_alignment_for_later_else__1 || + condition__no_alignment_for_later_else__2 + { }; } diff --git a/tests/target/issue-1247.rs b/tests/target/issue-1247.rs index 427a8076ad5..16c63e0f53d 100644 --- a/tests/target/issue-1247.rs +++ b/tests/target/issue-1247.rs @@ -1,7 +1,8 @@ // rustfmt-max_width: 80 fn foo() { - polyfill::slice::fill(&mut self.pending[padding_pos.. - (self.algorithm.block_len - 8)], - 0); + polyfill::slice::fill( + &mut self.pending[padding_pos..(self.algorithm.block_len - 8)], + 0, + ); } diff --git a/tests/target/issue-1366.rs b/tests/target/issue-1366.rs index 927aabc5018..eee147baab9 100644 --- a/tests/target/issue-1366.rs +++ b/tests/target/issue-1366.rs @@ -4,10 +4,10 @@ fn main() { .map(|s| s) .map(|s| s.to_string()) .map(|res| match Some(res) { - Some(ref s) if s == "" => 41, - Some(_) => 42, - _ => 43, - }) + Some(ref s) if s == "" => 41, + Some(_) => 42, + _ => 43, + }) } println!("{:?}", f()) } diff --git a/tests/target/issue-1397.rs b/tests/target/issue-1397.rs index d8cacd61b58..f267a91d3e1 100644 --- a/tests/target/issue-1397.rs +++ b/tests/target/issue-1397.rs @@ -12,8 +12,9 @@ fn baz(p: Packet) { loop { loop { if let Packet::Transaction { - state: TransactionState::Committed(ts, ..), .. - } = p { + state: TransactionState::Committed(ts, ..), .. + } = p + { unreachable!() } } diff --git a/tests/target/issue-1468.rs b/tests/target/issue-1468.rs index 518c31b625c..e10c83d45ac 100644 --- a/tests/target/issue-1468.rs +++ b/tests/target/issue-1468.rs @@ -1,27 +1,29 @@ fn issue1468() { euc_jp_decoder_functions!({ - let trail_minus_offset = byte.wrapping_sub(0xA1); - // Fast-track Hiragana (60% according to Lunde) - // and Katakana (10% acconding to Lunde). - if jis0208_lead_minus_offset == 0x03 && - trail_minus_offset < 0x53 { - // Hiragana - handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) - } else if jis0208_lead_minus_offset == 0x04 && - trail_minus_offset < 0x56 { - // Katakana - handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) - } else if trail_minus_offset > (0xFE - 0xA1) { - if byte < 0x80 { - return (DecoderResult::Malformed(1, 0), - unread_handle_trail.unread(), - handle.written()); - } - return (DecoderResult::Malformed(2, 0), - unread_handle_trail.consumed(), - handle.written()); - } else { - unreachable!(); - } - }); + let trail_minus_offset = byte.wrapping_sub(0xA1); + // Fast-track Hiragana (60% according to Lunde) + // and Katakana (10% acconding to Lunde). + if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { + // Hiragana + handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) + } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 { + // Katakana + handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) + } else if trail_minus_offset > (0xFE - 0xA1) { + if byte < 0x80 { + return ( + DecoderResult::Malformed(1, 0), + unread_handle_trail.unread(), + handle.written(), + ); + } + return ( + DecoderResult::Malformed(2, 0), + unread_handle_trail.consumed(), + handle.written(), + ); + } else { + unreachable!(); + } + }); } diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs index 21dca794e93..27eeacaa08a 100644 --- a/tests/target/issue-510.rs +++ b/tests/target/issue-510.rs @@ -1,12 +1,15 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { - fn solve_inline_size_constraints(&self, - block: &mut BlockFlow, - input: &ISizeConstraintInput) - -> ISizeConstraintSolution { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { + match ( + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + ) { (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { let margin_start = inline_start_margin.specified_or_zero(); let margin_end = inline_end_margin.specified_or_zero(); @@ -14,9 +17,9 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { // and inline-size Auto. // // Set inline-end to zero to calculate inline-size. - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); (Au(0), inline_size, margin_start, margin_end) } }; @@ -30,9 +33,9 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { // and inline-size Auto. // // Set inline-end to zero to calculate inline-size. - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); (Au(0), inline_size, margin_start, margin_end) } }; diff --git a/tests/target/item-brace-style-always-next-line.rs b/tests/target/item-brace-style-always-next-line.rs index 48dcebc0263..0c0f2163102 100644 --- a/tests/target/item-brace-style-always-next-line.rs +++ b/tests/target/item-brace-style-always-next-line.rs @@ -17,21 +17,25 @@ mod M { struct D {} enum A - where T: Copy + where + T: Copy, { A, } struct B - where T: Copy + where + T: Copy, { b: i32, } // For empty enums and structs, the brace remains on the same line. enum C - where T: Copy {} + where + T: Copy, {} struct D - where T: Copy {} + where + T: Copy, {} } diff --git a/tests/target/item-brace-style-prefer-same-line.rs b/tests/target/item-brace-style-prefer-same-line.rs index b38bd2e1a19..bb090479cab 100644 --- a/tests/target/item-brace-style-prefer-same-line.rs +++ b/tests/target/item-brace-style-prefer-same-line.rs @@ -14,18 +14,22 @@ mod M { struct D {} enum A - where T: Copy { + where + T: Copy, { A, } struct B - where T: Copy { + where + T: Copy, { b: i32, } enum C - where T: Copy {} + where + T: Copy, {} struct D - where T: Copy {} + where + T: Copy, {} } diff --git a/tests/target/item-brace-style-same-line-where.rs b/tests/target/item-brace-style-same-line-where.rs index cdcd813fda4..54ad69de42a 100644 --- a/tests/target/item-brace-style-same-line-where.rs +++ b/tests/target/item-brace-style-same-line-where.rs @@ -15,21 +15,25 @@ mod M { struct D {} enum A - where T: Copy + where + T: Copy, { A, } struct B - where T: Copy + where + T: Copy, { b: i32, } // For empty enums and structs, the brace remains on the same line. enum C - where T: Copy {} + where + T: Copy, {} struct D - where T: Copy {} + where + T: Copy, {} } diff --git a/tests/target/large_vec.rs b/tests/target/large_vec.rs index 44f6d52650c..95d1fc43c03 100644 --- a/tests/target/large_vec.rs +++ b/tests/target/large_vec.rs @@ -3,27 +3,40 @@ impl Environment { pub fn new_root() -> Rc> { let mut env = Environment::new(); - let builtin_functions = - &[("println", - Function::NativeVoid(CallSign { - num_params: 0, - variadic: true, - param_types: vec![], - }, - native_println)), - ("run_http_server", - Function::NativeVoid(CallSign { - num_params: 1, - variadic: false, - param_types: vec![Some(ConstraintType::Function)], - }, - native_run_http_server)), - ("len", - Function::NativeReturning(CallSign { - num_params: 1, - variadic: false, - param_types: vec![None], - }, - native_len))]; + let builtin_functions = &[ + ( + "println", + Function::NativeVoid( + CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println, + ), + ), + ( + "run_http_server", + Function::NativeVoid( + CallSign { + num_params: 1, + variadic: false, + param_types: vec![Some(ConstraintType::Function)], + }, + native_run_http_server, + ), + ), + ( + "len", + Function::NativeReturning( + CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len, + ), + ), + ]; } } diff --git a/tests/target/long-fn-1.rs b/tests/target/long-fn-1.rs index 0e299aaecc1..f94431965c2 100644 --- a/tests/target/long-fn-1.rs +++ b/tests/target/long-fn-1.rs @@ -2,10 +2,11 @@ // formatted correctly. impl Foo { - fn some_input(&mut self, - input: Input, - input_path: Option) - -> (Input, Option) { + fn some_input( + &mut self, + input: Input, + input_path: Option, + ) -> (Input, Option) { } fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index 7cf094906cc..95e6d3be3ed 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -6,8 +6,8 @@ fn main() { match x { aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == - "aaaaaaaaaaa \ - aaaaaaa aaaaaa" => + "aaaaaaaaaaa \ + aaaaaaa aaaaaa" => { Ok(()) } diff --git a/tests/target/loop.rs b/tests/target/loop.rs index 4cf18f0110a..2dfbff93a65 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -13,7 +13,8 @@ fn main() { } 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > - some_other_value {} + some_other_value + {} while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } @@ -22,7 +23,8 @@ fn main() { } 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in - some_iter(arg1, arg2) { + some_iter(arg1, arg2) + { // do smth } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 45b475a18f9..6185e21a835 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1,10 +1,12 @@ // rustfmt-normalize_comments: true itemmacro!(this, is.now().formatted(yay)); -itemmacro!(really, - long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() - .is - .formatted()); +itemmacro!( + really, + long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() + .is + .formatted() +); itemmacro!{this, is.bracket().formatted()} @@ -17,12 +19,16 @@ fn main() { baz!(1 + 2 + 3, quux.kaas()); - quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + quux!( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + ); - kaas!(// comments - a, // post macro - b /* another */); + kaas!( + // comments + a, // post macro + b /* another */ + ); trailingcomma!( a , b , c , ); @@ -30,8 +36,24 @@ fn main() { vec![a, b, c]; - vec![AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, BBBBB, 5, - 100 - 30, 1.33, b, b, b]; + vec![ + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + BBBBB, + 5, + 100 - 30, + 1.33, + b, + b, + b, + ]; vec![a /* comment */]; @@ -46,13 +68,12 @@ fn main() { vec![a; b, c]; vec![a; - (|x| { - let y = x + 1; - let z = y + 1; - z - })(2)]; - vec![a; - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + (|x| { + let y = x + 1; + let z = y + 1; + z + })(2)]; + vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; vec![a; unsafe { x + 1 }]; unknown_bracket_macro__comma_should_not_be_stripped![ diff --git a/tests/target/match-block-trailing-comma.rs b/tests/target/match-block-trailing-comma.rs index b00def007e8..44d1f289f8e 100644 --- a/tests/target/match-block-trailing-comma.rs +++ b/tests/target/match-block-trailing-comma.rs @@ -8,9 +8,9 @@ fn foo() { "line1"; "line2" }, - b => { - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) - }, + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), } } diff --git a/tests/target/match-nowrap-trailing-comma.rs b/tests/target/match-nowrap-trailing-comma.rs index 6b2e430123d..0abc358a340 100644 --- a/tests/target/match-nowrap-trailing-comma.rs +++ b/tests/target/match-nowrap-trailing-comma.rs @@ -9,7 +9,9 @@ fn foo() { "line1"; "line2" }, - b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), } } diff --git a/tests/target/match-nowrap.rs b/tests/target/match-nowrap.rs index db2a874c838..3849a8fb0e0 100644 --- a/tests/target/match-nowrap.rs +++ b/tests/target/match-nowrap.rs @@ -7,7 +7,9 @@ fn foo() { a => { foo() } - b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 45f62ca6845..f21fdb37dc5 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -37,9 +37,10 @@ fn foo() { Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} _ => {} - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || - data.types.len() > 0 || - data.bindings.len() > 0 => {} + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > + 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => {} } let whatever = match something { @@ -66,15 +67,31 @@ fn main() { // Test that one-line bodies align. fn main() { match r { - Variableeeeeeeeeeeeeeeeee => { - ("variable", vec!["id", "name", "qualname", "value", "type", "scopeid"], true, true) - } - Enummmmmmmmmmmmmmmmmmmmm => { - ("enum", vec!["id", "qualname", "scopeid", "value"], true, true) - } - Variantttttttttttttttttttttttt => { - ("variant", vec!["id", "name", "qualname", "type", "value", "scopeid"], true, true) - } + Variableeeeeeeeeeeeeeeeee => ( + "variable", + vec!["id", "name", "qualname", "value", "type", "scopeid"], + true, + true, + ), + Enummmmmmmmmmmmmmmmmmmmm => ( + "enum", + vec!["id", "qualname", "scopeid", "value"], + true, + true, + ), + Variantttttttttttttttttttttttt => ( + "variant", + vec![ + "id", + "name", + "qualname", + "type", + "value", + "scopeid", + ], + true, + true, + ), }; match x { @@ -209,10 +226,12 @@ fn issue355() { xc => vec![1, 2], // comment yc => vec![3; 4], // comment yd => { - looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd) + looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( + aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd, + ) } } } @@ -276,14 +295,12 @@ fn issue494() { hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { result.push(StmtRef::Mirror(Box::new(Stmt { - span: stmt.span, - kind: StmtKind::Expr { - scope: cx.tcx - .region_maps - .node_extent(id), - expr: expr.to_ref(), - }, - }))) + span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref(), + }, + }))) } } } @@ -300,10 +317,10 @@ fn issue386() { fn guards() { match foo { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && - barrrrrrrrrrrr => {} + barrrrrrrrrrrr => {} aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && - barrrrrrrrrrrr => {} + barrrrrrrrrrrr => {} aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if fooooooooooooooooooooo && (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => { @@ -313,48 +330,48 @@ fn guards() { fn issue1371() { Some(match type_ { - sfEvtClosed => Closed, - sfEvtResized => { - let e = unsafe { *event.size.as_ref() }; + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; - Resized { - width: e.width, - height: e.height, - } - } - sfEvtLostFocus => LostFocus, - sfEvtGainedFocus => GainedFocus, - sfEvtTextEntered => { - TextEntered { - unicode: unsafe { - ::std::char::from_u32((*event.text.as_ref()).unicode) - .expect("Invalid unicode encountered on TextEntered event") - }, - } - } - sfEvtKeyPressed => { - let e = unsafe { event.key.as_ref() }; + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => { + TextEntered { + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + } + } + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; - KeyPressed { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - sfEvtKeyReleased => { - let e = unsafe { event.key.as_ref() }; + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; - KeyReleased { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - }) + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) } fn issue1395() { @@ -362,31 +379,31 @@ fn issue1395() { let foo = Some(true); let mut x = false; bar.and_then(|_| match foo { - None => None, - Some(b) => { - x = true; - Some(b) - } - }); + None => None, + Some(b) => { + x = true; + Some(b) + } + }); } fn issue1456() { Ok(Recording { - artists: match reader - .evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { - Nodeset(nodeset) => { - let res: Result, ReadError> = nodeset - .iter() - .map(|node| { - XPathNodeReader::new(node, &context) - .and_then(|r| ArtistRef::from_xml(&r)) - }) - .collect(); - res? - } - _ => Vec::new(), - }, - }) + artists: match reader.evaluate( + ".//mb:recording/mb:artist-credit/mb:name-credit", + )? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) } fn issue1460() { @@ -399,9 +416,13 @@ fn issue1460() { } fn issue525() { - foobar(f, "{}", match *self { - TaskState::Started => "started", - TaskState::Success => "success", - TaskState::Failed => "failed", - }); + foobar( + f, + "{}", + match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }, + ); } diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs index abf25b5e649..a5d186c5df7 100644 --- a/tests/target/mod-1.rs +++ b/tests/target/mod-1.rs @@ -23,12 +23,13 @@ mod boxed { } pub mod x { - pub fn freopen(filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE) - -> *mut FILE { + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE, + ) -> *mut FILE { } } diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 716b77a2d30..8c1e2d9695d 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -31,18 +31,21 @@ mod other; fn foo(a: isize, b: u32 /* blah blah */, c: f64) {} fn foo() -> Box - where 'a: 'b, - for<'a> D<'b>: 'a +where + 'a: 'b, + for<'a> D<'b>: 'a, { hello!() } -fn baz<'a: 'b, // comment on 'a - T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */> - (a: A, - b: B, // comment on b - c: C) - -> Bob { +fn baz< + 'a: 'b, // comment on 'a + T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */ +>( + a: A, + b: B, // comment on b + c: C, +) -> Bob { #[attr1] extern crate foo; #[attr2] @@ -65,10 +68,11 @@ fn qux(a: dadsfa, // Comment 1 /// Blah blah blah. impl Bar { - fn foo(&mut self, - a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a - b: sdfasdfsdfasfs /* closing comment */) - -> isize { + fn foo( + &mut self, + a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a + b: sdfasdfsdfasfs, // closing comment + ) -> isize { } /// Blah blah blah. @@ -112,7 +116,8 @@ struct Bar; // With a where clause and generics. pub struct Foo<'a, Y: Baz> - where X: Whatever +where + X: Whatever, { f: SomeType, // Comment beside a field } @@ -129,11 +134,15 @@ fn main() { hello(); } - let rc = Cell::new(42usize, - 42usize, - Cell::new(42usize, - remaining_widthremaining_widthremaining_widthremaining_width), - 42usize); + let rc = Cell::new( + 42usize, + 42usize, + Cell::new( + 42usize, + remaining_widthremaining_widthremaining_widthremaining_width, + ), + 42usize, + ); let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ @@ -152,13 +161,14 @@ fn deconstruct() { } -fn deconstruct(foo: Bar) - -> (SocketAddr, - Method, - Headers, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +fn deconstruct( + foo: Bar, +) -> (SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } #[rustfmt_skip] diff --git a/tests/target/nested-if-else.rs b/tests/target/nested-if-else.rs index 4d5bf1f702a..9a54789ddcd 100644 --- a/tests/target/nested-if-else.rs +++ b/tests/target/nested-if-else.rs @@ -1,11 +1,11 @@ fn issue1518() { Some(Object { - field: if a { - a_thing - } else if b { - b_thing - } else { - c_thing - }, - }) + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) } diff --git a/tests/target/nested-visual-block.rs b/tests/target/nested-visual-block.rs index a2e3c30f3ac..0312d6ff101 100644 --- a/tests/target/nested-visual-block.rs +++ b/tests/target/nested-visual-block.rs @@ -20,15 +20,18 @@ fn main() { |item| { match *item { StructLitField::Regular(ref field) => { - rewrite_field(inner_context, - &field, - &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent)) + rewrite_field( + inner_context, + &field, + &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent), + ) } StructLitField::Base(ref expr) => { // 2 = .. - expr.rewrite(inner_context, - &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2)) - .map(|s| format!("..{}", s)) + expr.rewrite( + inner_context, + &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2), + ).map(|s| format!("..{}", s)) } } }, @@ -45,16 +48,14 @@ fn main() { }); // #1581 - bootstrap - .checks - .register("PERSISTED_LOCATIONS", move || if locations2 - .0 - .inner_mut - .lock() - .poisoned { - Check::new(State::Error, - "Persisted location storage is poisoned due to a write failure") + bootstrap.checks.register("PERSISTED_LOCATIONS", move || { + if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) } else { Check::new(State::Healthy, "Persisted location storage is healthy") - }); + } + }); } diff --git a/tests/target/nested_skipped/mod.rs b/tests/target/nested_skipped/mod.rs index 44b25ca8797..0ab6f081e44 100644 --- a/tests/target/nested_skipped/mod.rs +++ b/tests/target/nested_skipped/mod.rs @@ -1,3 +1,3 @@ fn ugly() { -92; + 92; } diff --git a/tests/target/paths.rs b/tests/target/paths.rs index 6535463ebe3..da266389b6b 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -1,17 +1,18 @@ // rustfmt-normalize_comments: true fn main() { - let constellation_chan = - Constellation::::start(compositor_proxy, - resource_task, - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard); + let constellation_chan = Constellation::::start( + compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard, + ); Quux::::some_func(); diff --git a/tests/target/space-before-bound.rs b/tests/target/space-before-bound.rs index 0a226e1d585..538d0d41a5e 100644 --- a/tests/target/space-before-bound.rs +++ b/tests/target/space-before-bound.rs @@ -2,10 +2,21 @@ trait Trait {} trait Trait2 {} -fn f<'a, 'b : 'a, T : Trait, U>() where U : Trait2 {} +fn f<'a, 'b : 'a, T : Trait, U>() +where + U : Trait2, +{ +} // should fit on the line -fn f2<'a, 'b : 'a, Ttttttttttttttttttttttttttttttttttttttttttttttt : Trait, U>() where U : Trait2 {} +fn f2<'a, 'b : 'a, Ttttttttttttttttttttttttttttttttttttttttttttttt : Trait, U>() +where + U : Trait2, +{ +} // should be wrapped -fn f2<'a, 'b : 'a, Tttttttttttttttttttttttttttttttttttttttttttttttt : Trait, U>() where U : Trait2 { +fn f2<'a, 'b : 'a, Tttttttttttttttttttttttttttttttttttttttttttttttt : Trait, U>() +where + U : Trait2, +{ } diff --git a/tests/target/spaces-within-angle-brackets.rs b/tests/target/spaces-within-angle-brackets.rs index bc662487369..3969327b8ec 100644 --- a/tests/target/spaces-within-angle-brackets.rs +++ b/tests/target/spaces-within-angle-brackets.rs @@ -55,4 +55,8 @@ impl Foo { trait MyTrait< A, D > {} impl< A: Send, D: Send > MyTrait< A, D > for Foo {} -fn foo() where for< 'a > u32: 'a {} +fn foo() +where + for< 'a > u32: 'a, +{ +} diff --git a/tests/target/spaces-within-square-brackets.rs b/tests/target/spaces-within-square-brackets.rs index eb58a683704..3a1b24d4def 100644 --- a/tests/target/spaces-within-square-brackets.rs +++ b/tests/target/spaces-within-square-brackets.rs @@ -13,22 +13,22 @@ fn main() { let slice = &arr[ 1..2 ]; let line100_________________________________________________________________________ = [ 1, 2 ]; - let line101__________________________________________________________________________ = [ 1, - 2 ]; - let line102___________________________________________________________________________ = [ 1, - 2 ]; - let line103____________________________________________________________________________ = [ 1, - 2 ]; + let line101__________________________________________________________________________ = + [ 1, 2 ]; + let line102___________________________________________________________________________ = + [ 1, 2 ]; + let line103____________________________________________________________________________ = + [ 1, 2 ]; let line104_____________________________________________________________________________ = [ 1, 2 ]; let line100_____________________________________________________________________ = vec![ 1, 2 ]; - let line101______________________________________________________________________ = vec![ 1, - 2 ]; - let line102_______________________________________________________________________ = vec![ 1, - 2 ]; - let line103________________________________________________________________________ = vec![ 1, - 2 ]; + let line101______________________________________________________________________ = + vec![ 1, 2 ]; + let line102_______________________________________________________________________ = + vec![ 1, 2 ]; + let line103________________________________________________________________________ = + vec![ 1, 2 ]; let line104_________________________________________________________________________ = vec![ 1, 2 ]; } diff --git a/tests/target/static.rs b/tests/target/static.rs index f2421c1444c..12a8eba111b 100644 --- a/tests/target/static.rs +++ b/tests/target/static.rs @@ -1,11 +1,52 @@ const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | - FILE_READ_EA | SYNCHRONIZE; + FILE_READ_EA | SYNCHRONIZE; -static boolnames: &'static [&'static str] = - &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", - "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", - "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", - "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; +static boolnames: &'static [&'static str] = &[ + "bw", + "am", + "xsb", + "xhp", + "xenl", + "eo", + "gn", + "hc", + "km", + "hs", + "in", + "db", + "da", + "mir", + "msgr", + "os", + "eslok", + "xt", + "hz", + "ul", + "xon", + "nxon", + "mc5i", + "chts", + "nrrmc", + "npc", + "ndscr", + "ccc", + "bce", + "hls", + "xhpa", + "crxm", + "daisy", + "xvpa", + "sam", + "cpix", + "lpix", + "OTbs", + "OTns", + "OTnc", + "OTMT", + "OTNL", + "OTpt", + "OTxr", +]; static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index bbca3fe097e..7ac75290f2e 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -26,7 +26,9 @@ formatting"#; filename.replace(" ", "\\"); let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = - funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + funktion( + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", + ); let unicode = "a̐éö̲\r\n"; let unicode2 = "Löwe 老虎 Léopard"; @@ -42,8 +44,10 @@ fn issue682() { } fn issue716() { - println!("forall x. mult(e(), x) = x /\\ - forall x. mult(x, x) = e()"); + println!( + "forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()" + ); } fn issue_1282() { diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs index f53e149b923..1cc73d14060 100644 --- a/tests/target/string_punctuation.rs +++ b/tests/target/string_punctuation.rs @@ -2,10 +2,14 @@ // rustfmt-error_on_line_overflow: false fn main() { - println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ - Likethisssssssssssss"); + println!( + "ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ + Likethisssssssssssss" + ); format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); - println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ - adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ - ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); + println!( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ + adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ + ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea" + ); } diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index 5befcb6cd7d..a42d8e7aada 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -50,11 +50,11 @@ fn main() { }; Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); Diagram { // o This graph demonstrates how diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index 7cd2acd958f..0eb7b8b759f 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -59,11 +59,11 @@ fn main() { }; Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); Diagram { // o This graph demonstrates how diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs index 8f935c1aa4d..fa49c4f61a4 100644 --- a/tests/target/struct_tuple_visual.rs +++ b/tests/target/struct_tuple_visual.rs @@ -6,34 +6,44 @@ fn foo() { Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment - foo(), /* Comment */ - // Comment - bar() /* Comment */); + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo( + // Comment + foo(), // Comment + // Comment + bar(), /* Comment */ + ); Foo(Bar, f()); - Quux(if cond { - bar(); - }, - baz()); - - Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - zzzzz /* test */); - - A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - Item); - - Diagram(// o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - G) + Quux( + if cond { + bar(); + }, + baz(), + ); + + Baz( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + zzzzz, /* test */ + ); + + A( + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + Item, + ); + + Diagram( + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + G, + ) } diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 2872750c20a..f6387fc2bf3 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -59,14 +59,17 @@ struct Qux<'a, pub W, ); -struct Tuple(// Comment 1 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); +struct Tuple( + // Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +); // With a where clause and generics. pub struct Foo<'a, Y: Baz> - where X: Whatever +where + X: Whatever, { f: SomeType, // Comment beside a field } @@ -145,38 +148,52 @@ struct Deep { struct Foo(T); struct Foo(T) - where T: Copy, - T: Eq; -struct Foo(TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +where + T: Copy, + T: Eq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU +); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) +where + T: PartialEq; struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) - where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU) - where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU, // Bar - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU); +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU, // Bar + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU +); mod m { struct X - where T: Sized + where + T: Sized, { a: T, } } -struct Foo(TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU); +struct Foo( + TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU +); struct Issue677 { pub ptr: *const libc::c_void, diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs index 9e74266b396..9ef4eecbcc5 100644 --- a/tests/target/trailing_commas.rs +++ b/tests/target/trailing_commas.rs @@ -12,56 +12,65 @@ fn main() { } fn f(x: T, y: S) -> T - where T: P, - S: Q, +where + T: P, + S: Q, { x } impl Trait for T - where T: P, +where + T: P, { fn f(x: T) -> T - where T: Q + R, + where + T: Q + R, { x } } struct Pair - where T: P, - S: P + Q, +where + T: P, + S: P + Q, { a: T, b: S, } struct TupPair(S, T) - where T: P, - S: P + Q; +where + T: P, + S: P + Q; enum E - where S: P, - T: P, +where + S: P, + T: P, { A { a: T, }, } -type Double - where T: P, - T: Q = Pair; +type Double where + T: P, + T: Q = Pair; extern "C" { fn f(x: T, y: S) -> T - where T: P, - S: Q; + where + T: P, + S: Q; } trait Q - where T: P, - S: R, +where + T: P, + S: R, { fn f(self, x: T, y: S, z: U) -> Self - where U: P, - V: P; + where + U: P, + V: P; } diff --git a/tests/target/trait.rs b/tests/target/trait.rs index d8acc1ba229..e4758e98b5e 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -7,15 +7,18 @@ trait Foo { fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; - fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) - -> RetType; // Some comment + fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + ) -> RetType; // Some comment fn baz(&mut self) -> i32; fn increment(&mut self, x: i32); - fn read(&mut self, x: BufReader /* Used to be MemReader */) where R: Read; + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where + R: Read; } pub trait WriteMessage { @@ -32,7 +35,8 @@ trait TraitWithExpr { trait Test { fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result - where F: FnOnce(&mut Self) -> Result; + where + F: FnOnce(&mut Self) -> Result; } trait T {} @@ -42,27 +46,35 @@ trait Foo { } trait ConstCheck: Foo - where T: Baz +where + T: Baz, { const J: i32; } -trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + T: Foo +{ +} trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt - where T: Foo +where + T: Foo { } trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt - where J: Bar +where + J: Bar, { fn test(); } trait WhereList - where T: Foo, - J: Bar +where + T: Foo, + J: Bar { } diff --git a/tests/target/try-conversion.rs b/tests/target/try-conversion.rs index 7198606d75b..e16fba278d2 100644 --- a/tests/target/try-conversion.rs +++ b/tests/target/try-conversion.rs @@ -18,9 +18,10 @@ fn test() { } fn issue1291() { - fs::create_dir_all(&gitfiledir) - .chain_err(|| { - format!("failed to create the {} submodule directory for the workarea", - name) - })?; + fs::create_dir_all(&gitfiledir).chain_err(|| { + format!( + "failed to create the {} submodule directory for the workarea", + name + ) + })?; } diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index 16fc3df020f..f398b7dffb7 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -2,52 +2,74 @@ fn foo() { let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); - let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaa, - aaaa); + let aaaaaaaaaaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + ); + let aaaaaaaaaaaaaaaaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa, + ); let a = (a,); - let b = (// This is a comment - b, // Comment - b /* Trailing comment */); + let b = ( + // This is a comment + b, // Comment + b, /* Trailing comment */ + ); // #1063 foo(x.0 .0); } fn a() { - ((aaaaaaaa, - aaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa),) + (( + aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + ),) } fn b() { - ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - bbbbbbbbbbbbbbbbbb) + ( + ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + bbbbbbbbbbbbbbbbbb, + ) } fn issue550() { - self.visitor.visit_volume(self.level.sector_id(sector), - (floor_y, - if is_sky_flat(ceil_tex) { - from_wad_height(self.height_range.1) - } else { - ceil_y - })); + self.visitor.visit_volume(self.level.sector_id(sector), ( + floor_y, + if is_sky_flat(ceil_tex) { + from_wad_height(self.height_range.1) + } else { + ceil_y + }, + )); } fn issue775() { if indent { - let a = mk_object(&[("a".to_string(), Boolean(true)), - ("b".to_string(), - Array(vec![mk_object(&[("c".to_string(), - String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), - String("".to_string()))])]))]); + let a = mk_object( + &[ + ("a".to_string(), Boolean(true)), + ( + "b".to_string(), + Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]), + ]), + ), + ], + ); } } diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index 121c7990f86..f99d524eb2e 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -1,12 +1,12 @@ fn main() { let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: - SomeTrait; + SomeTrait; let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; x: u32 - 1u32 / 10f32: u32 } diff --git a/tests/target/type-punctuation.rs b/tests/target/type-punctuation.rs index e7021eca84f..f35293de626 100644 --- a/tests/target/type-punctuation.rs +++ b/tests/target/type-punctuation.rs @@ -1,12 +1,14 @@ // rustfmt-type_punctuation_density: Compressed struct Foo - where U: Eq+Clone { +where + U: Eq+Clone, { // body } trait Foo<'a, T=usize> - where T: 'a+Eq+Clone +where + T: 'a+Eq+Clone, { type Bar: Eq+Clone; } @@ -16,13 +18,15 @@ trait Foo: Eq+Clone { } impl Foo<'a> for Bar - where for<'a> T: 'a+Eq+Clone +where + for<'a> T: 'a+Eq+Clone, { // body } fn foo<'a, 'b, 'c>() - where 'a: 'b+'c +where + 'a: 'b+'c, { // body } diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index 42600aa3ae5..86180149aac 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -7,16 +7,18 @@ pub type PublicTest<'a, I, O> = Result, Box + 'a>, Box + 'a>>; -pub type LongGenericListTest<'a, - 'b, - 'c, - 'd, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - A, - B, - C> = Option>; +pub type LongGenericListTest< + 'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A, + B, + C +> = Option>; pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; @@ -26,30 +28,34 @@ pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAM pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; -pub type GenericsFitButNotEqualTest<'a, - 'b, - 'c, - 'd, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - A1, - B, - C> = Vec; - -pub type CommentTest = (); - - -pub type WithWhereClause - where T: Clone, - LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; - -pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = - Option; - -pub type Exactly101CharstoEqualWhereTest - where T: Clone + Ord + Eq + SomeOtherTrait = Option; +pub type GenericsFitButNotEqualTest< + 'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A1, + B, + C +> = Vec; + +pub type CommentTest< + // Lifetime + 'a, // Type + T +> = (); + + +pub type WithWhereClause where + T: Clone, + LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; + +pub type Exactly100CharstoEqualWhereTest where + T: Clone + Ord + Eq + SomeOtherTrait = Option; + +pub type Exactly101CharstoEqualWhereTest where + T: Clone + Ord + Eq + SomeOtherTrait = Option; type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, diff --git a/tests/target/where-clause.rs b/tests/target/where-clause.rs index cf225cab350..724f3b34bf0 100644 --- a/tests/target/where-clause.rs +++ b/tests/target/where-clause.rs @@ -1,21 +1,29 @@ pub trait Test { fn very_long_method_name(self, f: F) -> MyVeryLongReturnType - where F: FnMut(Self::Item) -> bool; - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + where + F: FnMut(Self::Item) -> bool; + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; } fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType - where F: FnMut(Self::Item) -> bool +where + F: FnMut(Self::Item) -> bool, { } struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) - where A: LongTrait; +where + A: LongTrait; -struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) where A: LongTrait1234; +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) +where + A: LongTrait1234; struct AlwaysOnNextLine - where A: LongTrait +where + A: LongTrait, { x: i32, } diff --git a/tests/writemode/target/checkstyle.xml b/tests/writemode/target/checkstyle.xml index b59d81b29c8..30ab5ad7579 100644 --- a/tests/writemode/target/checkstyle.xml +++ b/tests/writemode/target/checkstyle.xml @@ -1,2 +1,2 @@ - + -- cgit 1.4.1-3-g733a5 From 18ccd0190ee6ef4a6e1bb9d737e515b872009711 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 13 Jun 2017 14:49:47 +1200 Subject: Rebasing --- src/chains.rs | 3 +- src/expr.rs | 144 +++++++----- src/items.rs | 323 +++++++++++++++----------- src/lib.rs | 6 +- src/lists.rs | 26 +-- src/patterns.rs | 3 +- src/string.rs | 10 +- src/types.rs | 76 +++--- tests/target/big-impl.rs | 76 +++--- tests/target/configs-generics_indent-block.rs | 3 +- tests/target/fn-simple.rs | 22 +- tests/target/fn.rs | 7 +- tests/target/hard-tabs.rs | 16 +- tests/target/issue-510.rs | 35 ++- tests/target/long-match-arms-brace-newline.rs | 8 +- tests/target/match.rs | 3 +- tests/target/multiple.rs | 12 +- tests/target/paths.rs | 24 +- tests/target/string-lit.rs | 7 +- tests/target/trailing_commas.rs | 50 +++- tests/target/tuple.rs | 4 +- tests/target/type_alias.rs | 14 +- 22 files changed, 504 insertions(+), 368 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index eba79505e20..890c39ebabb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -574,7 +574,8 @@ fn rewrite_method_call( let (lo, type_str) = if types.is_empty() { (args[0].span.hi, String::new()) } else { - let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + let type_list: Vec<_> = + try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 { format!("::< {} >", type_list.join(", ")) diff --git a/src/expr.rs b/src/expr.rs index 24432fb1dff..80c89a3a91b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -281,7 +281,9 @@ fn format_expr( Some(format!( "{}{}", "do catch ", - try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))) + try_opt!( + block.rewrite(&context, Shape::legacy(budget, shape.indent)) + ) )) } }; @@ -1428,9 +1430,11 @@ impl Rewrite for ast::Arm { if contains_skip(attrs) { return None; } - format!("{}\n{}", - try_opt!(attrs.rewrite(context, shape)), - shape.indent.to_string(context.config)) + format!( + "{}\n{}", + try_opt!(attrs.rewrite(context, shape)), + shape.indent.to_string(context.config) + ) } else { String::new() }; @@ -1515,11 +1519,11 @@ impl Rewrite for ast::Arm { }; match rewrite { - Some(ref body_str) if (!body_str.contains('\n') && - body_str.len() <= arm_shape.width) || - !context.config.wrap_match_arms() || - (extend && first_line_width(body_str) <= arm_shape.width) || - is_block => { + Some(ref body_str) + if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) || + !context.config.wrap_match_arms() || + (extend && first_line_width(body_str) <= arm_shape.width) || + is_block => { let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), _ => " ", @@ -1610,28 +1614,33 @@ fn rewrite_guard( if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` - if let Some(cond_shape) = shape - .shrink_left(pattern_width + 4) - .and_then(|s| s.sub_width(5)) { - if let Some(cond_str) = guard - .rewrite(context, cond_shape) - .and_then(|s| s.rewrite(context, cond_shape)) { + if let Some(cond_shape) = shape.shrink_left(pattern_width + 4).and_then( + |s| s.sub_width(5), + ) + { + if let Some(cond_str) = guard.rewrite(context, cond_shape).and_then(|s| { + s.rewrite(context, cond_shape) + }) + { return Some(format!(" if {}", cond_str)); } } // Not enough space to put the guard after the pattern, try a newline. // 3 == `if ` - if let Some(cond_shape) = Shape::indented(shape.indent.block_indent(context.config) + 3, - context.config) - .sub_width(3) { + if let Some(cond_shape) = Shape::indented( + shape.indent.block_indent(context.config) + 3, + context.config, + ).sub_width(3) + { if let Some(cond_str) = guard.rewrite(context, cond_shape) { - return Some(format!("\n{}if {}", - shape - .indent - .block_indent(context.config) - .to_string(context.config), - cond_str)); + return Some(format!( + "\n{}if {}", + shape.indent.block_indent(context.config).to_string( + context.config, + ), + cond_str + )); } } @@ -1826,26 +1835,28 @@ fn rewrite_call_inner( let span_lo = context.codemap.span_after(span, "("); let args_span = mk_sp(span_lo, span.hi); - let (extendable, list_str) = rewrite_call_args(context, - args, - args_span, - nested_shape, - one_line_width, - force_trailing_comma) - .or_else(|| if context.use_block_indent() { - rewrite_call_args(context, - args, - args_span, - Shape::indented(shape - .block() - .indent - .block_indent(context.config), - context.config), - 0, - force_trailing_comma) - } else { - None - }) + let (extendable, list_str) = rewrite_call_args( + context, + args, + args_span, + nested_shape, + one_line_width, + force_trailing_comma, + ).or_else(|| if context.use_block_indent() { + rewrite_call_args( + context, + args, + args_span, + Shape::indented( + shape.block().indent.block_indent(context.config), + context.config, + ), + 0, + force_trailing_comma, + ) + } else { + None + }) .ok_or(Ordering::Less)?; if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { @@ -1861,12 +1872,20 @@ fn rewrite_call_inner( ); } - let args_shape = shape - .sub_width(last_line_width(&callee_str)) - .ok_or(Ordering::Less)?; - Ok(format!("{}{}", - callee_str, - wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape))) + let args_shape = shape.sub_width(last_line_width(&callee_str)).ok_or( + Ordering::Less, + )?; + Ok(format!( + "{}{}", + callee_str, + wrap_args_with_parens( + context, + &list_str, + extendable, + args_shape, + nested_shape, + ) + )) } fn need_block_indent(s: &str, shape: Shape) -> bool { @@ -2056,15 +2075,17 @@ fn paren_overhead(context: &RewriteContext) -> usize { } } -fn wrap_args_with_parens(context: &RewriteContext, - args_str: &str, - is_extendable: bool, - shape: Shape, - nested_shape: Shape) - -> String { +fn wrap_args_with_parens( + context: &RewriteContext, + args_str: &str, + is_extendable: bool, + shape: Shape, + nested_shape: Shape, +) -> String { if !context.use_block_indent() || - (context.inside_macro && !args_str.contains('\n') && - args_str.len() + paren_overhead(context) <= shape.width) || is_extendable { + (context.inside_macro && !args_str.contains('\n') && + args_str.len() + paren_overhead(context) <= shape.width) || is_extendable + { if context.config.spaces_within_parens() && args_str.len() > 0 { format!("( {} )", args_str) } else { @@ -2166,10 +2187,9 @@ fn rewrite_struct_lit<'a>( return Some(format!("{} {{}}", path_str)); } - let field_iter = fields - .into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + let field_iter = fields.into_iter().map(StructLitField::Regular).chain( + base.into_iter().map(StructLitField::Base), + ); // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); diff --git a/src/items.rs b/src/items.rs index 01aa7b389d5..156528301be 100644 --- a/src/items.rs +++ b/src/items.rs @@ -550,11 +550,12 @@ impl<'a> FmtVisitor<'a> { } } -pub fn format_impl(context: &RewriteContext, - item: &ast::Item, - offset: Indent, - where_span_end: Option) - -> Option { +pub fn format_impl( + context: &RewriteContext, + item: &ast::Item, + offset: Indent, + where_span_end: Option, +) -> Option { if let ast::ItemKind::Impl(_, _, _, ref generics, _, _, ref items) = item.node { let mut result = String::new(); let ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset)); @@ -569,18 +570,26 @@ pub fn format_impl(context: &RewriteContext, .checked_sub(last_line_width(&result)) .unwrap_or(0) }; - let where_clause_str = try_opt!(rewrite_where_clause(context, - &generics.where_clause, - context.config.item_brace_style(), - Shape::legacy(where_budget, - offset.block_only()), - context.config.where_density(), - "{", - false, - last_line_width(&ref_and_type) == 1, - where_span_end)); - - if try_opt!(is_impl_single_line(context, &items, &result, &where_clause_str, &item)) { + let where_clause_str = try_opt!(rewrite_where_clause( + context, + &generics.where_clause, + context.config.item_brace_style(), + Shape::legacy(where_budget, offset.block_only()), + context.config.where_density(), + "{", + false, + last_line_width(&ref_and_type) == 1, + where_span_end, + )); + + if try_opt!(is_impl_single_line( + context, + &items, + &result, + &where_clause_str, + &item, + )) + { result.push_str(&where_clause_str); if where_clause_str.contains('\n') { let white_space = offset.to_string(context.config); @@ -670,10 +679,11 @@ fn is_impl_single_line( ) } -fn format_impl_ref_and_type(context: &RewriteContext, - item: &ast::Item, - offset: Indent) - -> Option { +fn format_impl_ref_and_type( + context: &RewriteContext, + item: &ast::Item, + offset: Indent, +) -> Option { if let ast::ItemKind::Impl(unsafety, polarity, _, @@ -693,12 +703,18 @@ fn format_impl_ref_and_type(context: &RewriteContext, Some(ref tr) => tr.path.span.lo, None => self_ty.span.lo, }; - let shape = generics_shape_from_config(context.config, - Shape::indented(offset + last_line_width(&result), - context.config), - 0); - let generics_str = - try_opt!(rewrite_generics_inner(context, generics, shape, shape.width, mk_sp(lo, hi))); + let shape = generics_shape_from_config( + context.config, + Shape::indented(offset + last_line_width(&result), context.config), + 0, + ); + let generics_str = try_opt!(rewrite_generics_inner( + context, + generics, + shape, + shape.width, + mk_sp(lo, hi), + )); let polarity_str = if polarity == ast::ImplPolarity::Negative { "!" @@ -709,24 +725,34 @@ fn format_impl_ref_and_type(context: &RewriteContext, if let Some(ref trait_ref) = *trait_ref { let result_len = result.len(); if let Some(trait_ref_str) = - rewrite_trait_ref(context, - &trait_ref, - offset, - &generics_str, - true, - polarity_str, - result_len) { + rewrite_trait_ref( + context, + &trait_ref, + offset, + &generics_str, + true, + polarity_str, + result_len, + ) + { result.push_str(&trait_ref_str); } else { - let generics_str = - try_opt!(rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))); - result.push_str(&try_opt!(rewrite_trait_ref(context, - &trait_ref, - offset, - &generics_str, - false, - polarity_str, - result_len))); + let generics_str = try_opt!(rewrite_generics_inner( + context, + generics, + shape, + 0, + mk_sp(lo, hi), + )); + result.push_str(&try_opt!(rewrite_trait_ref( + context, + &trait_ref, + offset, + &generics_str, + false, + polarity_str, + result_len, + ))); } } else { result.push_str(&generics_str); @@ -777,32 +803,41 @@ fn format_impl_ref_and_type(context: &RewriteContext, Style::Legacy => new_line_offset + trait_ref_overhead, Style::Rfc => new_line_offset, }; - result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, type_offset)))); + result.push_str(&*try_opt!(self_ty.rewrite( + context, + Shape::legacy(budget, type_offset), + ))); Some(result) } else { unreachable!(); } } -fn rewrite_trait_ref(context: &RewriteContext, - trait_ref: &ast::TraitRef, - offset: Indent, - generics_str: &str, - retry: bool, - polarity_str: &str, - result_len: usize) - -> Option { +fn rewrite_trait_ref( + context: &RewriteContext, + trait_ref: &ast::TraitRef, + offset: Indent, + generics_str: &str, + retry: bool, + polarity_str: &str, + result_len: usize, +) -> Option { // 1 = space between generics and trait_ref let used_space = 1 + polarity_str.len() + - if generics_str.contains('\n') { - last_line_width(&generics_str) - } else { - result_len + generics_str.len() - }; + if generics_str.contains('\n') { + last_line_width(&generics_str) + } else { + result_len + generics_str.len() + }; let shape = Shape::indented(offset + used_space, context.config); if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { if !(retry && trait_ref_str.contains('\n')) { - return Some(format!("{} {}{}", generics_str, polarity_str, &trait_ref_str)); + return Some(format!( + "{} {}{}", + generics_str, + polarity_str, + &trait_ref_str + )); } } // We could not make enough space for trait_ref, so put it on new line. @@ -810,26 +845,29 @@ fn rewrite_trait_ref(context: &RewriteContext, let offset = offset.block_indent(context.config); let shape = Shape::indented(offset, context.config); let trait_ref_str = try_opt!(trait_ref.rewrite(context, shape)); - Some(format!("{}\n{}{}{}", - generics_str, - &offset.to_string(context.config), - polarity_str, - &trait_ref_str)) + Some(format!( + "{}\n{}{}{}", + generics_str, + &offset.to_string(context.config), + polarity_str, + &trait_ref_str + )) } else { None } } -pub fn format_struct(context: &RewriteContext, - item_name: &str, - ident: ast::Ident, - vis: &ast::Visibility, - struct_def: &ast::VariantData, - generics: Option<&ast::Generics>, - span: Span, - offset: Indent, - one_line_width: Option) - -> Option { +pub fn format_struct( + context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: &ast::Visibility, + struct_def: &ast::VariantData, + generics: Option<&ast::Generics>, + span: Span, + offset: Indent, + one_line_width: Option, +) -> Option { match *struct_def { ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)), ast::VariantData::Tuple(ref fields, _) => { @@ -877,8 +915,12 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); let shape = Shape::indented(offset + last_line_width(&result), context.config); - let generics_str = - try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo))); + let generics_str = try_opt!(rewrite_generics( + context, + generics, + shape, + mk_sp(item.span.lo, body_lo), + )); result.push_str(&generics_str); let trait_bound_str = try_opt!(rewrite_trait_bounds( @@ -1534,10 +1576,12 @@ pub fn rewrite_associated_type( let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let shape = Shape::legacy(context.config.max_width(), indent); let bounds: &[_] = ty_param_bounds; - let bound_str = try_opt!(bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()); + let bound_str = try_opt!( + bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>() + ); if bounds.len() > 0 { format!(": {}", join_bounds(context, shape, &bound_str)) } else { @@ -2269,7 +2313,8 @@ fn compute_budgets_for_args( // 4 = "() {".len() let multi_line_overhead = indent.width() + result.len() + if newline_brace { 2 } else { 4 }; - let multi_line_budget = try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); + let multi_line_budget = + try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); return Some(( one_line_budget, @@ -2295,22 +2340,24 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { } } -fn rewrite_generics(context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - span: Span) - -> Option { +fn rewrite_generics( + context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + span: Span, +) -> Option { let shape = generics_shape_from_config(context.config, shape, 0); rewrite_generics_inner(context, generics, shape, shape.width, span) .or_else(|| rewrite_generics_inner(context, generics, shape, 0, span)) } -fn rewrite_generics_inner(context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - one_line_width: usize, - span: Span) - -> Option { +fn rewrite_generics_inner( + context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + one_line_width: usize, + span: Span, +) -> Option { // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. let lifetimes: &[_] = &generics.lifetimes; @@ -2334,15 +2381,17 @@ fn rewrite_generics_inner(context: &RewriteContext, }); let ty_spans = tys.iter().map(span_for_ty_param); - let items = itemize_list(context.codemap, - lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), - ">", - |&(sp, _)| sp.lo, - |&(sp, _)| sp.hi, - // FIXME: don't clone - |&(_, ref str)| str.clone(), - context.codemap.span_after(span, "<"), - span.hi); + let items = itemize_list( + context.codemap, + lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), + ">", + |&(sp, _)| sp.lo, + |&(sp, _)| sp.hi, + // FIXME: don't clone + |&(_, ref str)| str.clone(), + context.codemap.span_after(span, "<"), + span.hi, + ); format_generics_item_list(context, items, shape, one_line_width) } @@ -2357,12 +2406,14 @@ pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) } } -pub fn format_generics_item_list(context: &RewriteContext, - items: I, - shape: Shape, - one_line_budget: usize) - -> Option - where I: Iterator +pub fn format_generics_item_list( + context: &RewriteContext, + items: I, + shape: Shape, + one_line_budget: usize, +) -> Option +where + I: Iterator, { let item_vec = items.collect::>(); @@ -2381,21 +2432,29 @@ pub fn format_generics_item_list(context: &RewriteContext, let list_str = try_opt!(write_list(&item_vec, &fmt)); - Some(wrap_generics_with_angle_brackets(context, &list_str, shape.indent)) + Some(wrap_generics_with_angle_brackets( + context, + &list_str, + shape.indent, + )) } -pub fn wrap_generics_with_angle_brackets(context: &RewriteContext, - list_str: &str, - list_offset: Indent) - -> String { +pub fn wrap_generics_with_angle_brackets( + context: &RewriteContext, + list_str: &str, + list_offset: Indent, +) -> String { if context.config.generics_indent() == IndentStyle::Block && - (list_str.contains('\n') || list_str.ends_with(',')) { - format!("<\n{}{}\n{}>", - list_offset.to_string(context.config), - list_str, - list_offset - .block_unindent(context.config) - .to_string(context.config)) + (list_str.contains('\n') || list_str.ends_with(',')) + { + format!( + "<\n{}{}\n{}>", + list_offset.to_string(context.config), + list_str, + list_offset.block_unindent(context.config).to_string( + context.config, + ) + ) } else if context.config.spaces_within_angle_brackets() { format!("< {} >", list_str) } else { @@ -2413,10 +2472,12 @@ fn rewrite_trait_bounds( if bounds.is_empty() { return Some(String::new()); } - let bound_str = try_opt!(bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(&context, shape)) - .collect::>>()); + let bound_str = try_opt!( + bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(&context, shape)) + .collect::>>() + ); Some(format!(": {}", join_bounds(context, shape, &bound_str))) } @@ -2446,14 +2507,16 @@ fn rewrite_where_clause_rfc_style( let len = where_clause.predicates.len(); let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list(context.codemap, - where_clause.predicates.iter(), - terminator, - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(context, shape), - span_start, - span_end); + let items = itemize_list( + context.codemap, + where_clause.predicates.iter(), + terminator, + |pred| span_for_where_pred(pred).lo, + |pred| span_for_where_pred(pred).hi, + |pred| pred.rewrite(context, shape), + span_start, + span_end, + ); let comma_tactic = if suppress_comma { SeparatorTactic::Never } else { diff --git a/src/lib.rs b/src/lib.rs index 2ede6d9a2f0..2aa477ccafa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -468,8 +468,10 @@ where } // Reset the error count. if parse_session.span_diagnostic.has_errors() { - let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), - Some(codemap.clone()))); + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + )); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); } } diff --git a/src/lists.rs b/src/lists.rs index 37acff692a4..24bd10e24a0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -555,20 +555,20 @@ pub fn struct_lit_shape( prefix_width: usize, suffix_width: usize, ) -> Option<(Option, Shape)> { - let v_shape = - match context.config.struct_lit_style() { - IndentStyle::Visual => { - try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width)) - .sub_width(suffix_width)) - } - IndentStyle::Block => { - let shape = shape.block_indent(context.config.tab_spaces()); - Shape { - width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())), - ..shape - } + let v_shape = match context.config.struct_lit_style() { + IndentStyle::Visual => { + try_opt!( + try_opt!(shape.visual_indent(0).shrink_left(prefix_width)).sub_width(suffix_width) + ) + } + IndentStyle::Block => { + let shape = shape.block_indent(context.config.tab_spaces()); + Shape { + width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())), + ..shape } - }; + } + }; let h_shape = shape.sub_width(prefix_width + suffix_width); Some((h_shape, v_shape)) } diff --git a/src/patterns.rs b/src/patterns.rs index a52f42157b8..25290ceaf0e 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -81,7 +81,8 @@ impl Rewrite for Pat { rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { - let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); + let path_str = + try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); rewrite_tuple_pat( pat_vec, dotdot_pos, diff --git a/src/string.rs b/src/string.rs index 904260e8182..6c20c18ca47 100644 --- a/src/string.rs +++ b/src/string.rs @@ -42,12 +42,10 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; - let mut result = String::with_capacity( - stripped_str - .len() - .checked_next_power_of_two() - .unwrap_or(usize::max_value()), - ); + let mut result = + String::with_capacity(stripped_str.len().checked_next_power_of_two().unwrap_or( + usize::max_value(), + )); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); diff --git a/src/types.rs b/src/types.rs index b1cea7df864..5e57ce790a7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -226,18 +226,22 @@ fn rewrite_segment( let generics_shape = generics_shape_from_config(context.config, shape, separator.len()); - let items = itemize_list(context.codemap, - param_list.into_iter(), - ">", - |param| param.get_span().lo, - |param| param.get_span().hi, - |seg| seg.rewrite(context, generics_shape), - list_lo, - span_hi); - let generics_str = try_opt!(format_generics_item_list(context, - items, - generics_shape, - generics_shape.width)); + let items = itemize_list( + context.codemap, + param_list.into_iter(), + ">", + |param| param.get_span().lo, + |param| param.get_span().hi, + |seg| seg.rewrite(context, generics_shape), + list_lo, + span_hi, + ); + let generics_str = try_opt!(format_generics_item_list( + context, + items, + generics_shape, + generics_shape.width, + )); // Update position of last bracket. *span_lo = next_span_lo; @@ -307,9 +311,9 @@ where context.codemap, // FIXME Would be nice to avoid this allocation, // but I couldn't get the types to work out. - inputs - .map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), + inputs.map(|i| ArgumentKind::Regular(Box::new(i))).chain( + variadic_arg, + ), ")", |arg| match *arg { ArgumentKind::Regular(ref ty) => ty.span().lo, @@ -387,11 +391,12 @@ impl Rewrite for ast::WherePredicate { // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let ty_shape = try_opt!(shape.block_left(used_width)); - let bounds: Vec<_> = - try_opt!(bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect()); + let bounds: Vec<_> = try_opt!( + bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect() + ); let bounds_str = join_bounds(context, ty_shape, &bounds); if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { @@ -411,11 +416,12 @@ impl Rewrite for ast::WherePredicate { Style::Legacy => try_opt!(shape.block_left(used_width)), Style::Rfc => shape.block_indent(context.config.tab_spaces()), }; - let bounds: Vec<_> = - try_opt!(bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect()); + let bounds: Vec<_> = try_opt!( + bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect() + ); let bounds_str = join_bounds(context, ty_shape, &bounds); format!("{}{}{}", type_str, colon, bounds_str) @@ -482,10 +488,12 @@ where ); let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); - let result = format!("{}{}{}", - result, - colon, - join_bounds(context, try_opt!(shape.sub_width(overhead)), &appendix)); + let result = format!( + "{}{}{}", + result, + colon, + join_bounds(context, try_opt!(shape.sub_width(overhead)), &appendix) + ); wrap_str(result, context.config.max_width(), shape) } } @@ -540,10 +548,12 @@ impl Rewrite for ast::TyParam { result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); - let strs: Vec<_> = try_opt!(self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect()); + let strs: Vec<_> = try_opt!( + self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect() + ); result.push_str(&join_bounds(context, shape, &strs)); } if let Some(ref def) = self.default { diff --git a/tests/target/big-impl.rs b/tests/target/big-impl.rs index afe2571ec68..056ded71daa 100644 --- a/tests/target/big-impl.rs +++ b/tests/target/big-impl.rs @@ -1,24 +1,27 @@ // #1357 impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> for SelectStatement - where DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a +where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, { type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new(Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset)) + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) } } @@ -31,32 +34,39 @@ impl Foo Foo for Bar { +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar { fn foo() {} } impl Foo - for Bar { + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { fn foo() {} } impl Foo - for Bar { + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { fn foo() {} } -impl Foo - for Bar { +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { fn foo() {} } diff --git a/tests/target/configs-generics_indent-block.rs b/tests/target/configs-generics_indent-block.rs index 53175fa362f..0950a716fde 100644 --- a/tests/target/configs-generics_indent-block.rs +++ b/tests/target/configs-generics_indent-block.rs @@ -9,7 +9,8 @@ fn lorem< Adipiscing: Eq = usize, Consectetur: Eq = usize, Elit: Eq = usize, ->(ipsum: Ipsum, +>( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index d0c15c643f5..102c1449627 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -8,8 +8,10 @@ fn simple( fn op( x: Typ, key: &[u8], - upd: Box) - -> (memcache::Status, Result>)>, + upd: Box< + Fn(Option<&memcache::Item>) + -> (memcache::Status, Result>), + >, ) -> MapResult { } @@ -33,14 +35,14 @@ fn weird_comment( fn generic(arg: T) -> &SomeType where T: Fn(// First arg - A, - // Second argument - B, - C, - D, - // pre comment - E /* last comment */) - -> &SomeType, + A, + // Second argument + B, + C, + D, + // pre comment + E /* last comment */) + -> &SomeType, { arg(a, b, c, d, e) } diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 7a09ec6e83c..c8102fe3b54 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -55,7 +55,7 @@ pub fn render< N: Clone + 'a, E: Clone + 'a, G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + W: Write, >( g: &'a G, w: &mut W, @@ -101,7 +101,10 @@ fn foo(a: i32) -> i32 { fn ______________________baz( a: i32, -) -> *mut ::std::option::Option ()> { +) -> *mut ::std::option::Option< + extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) + -> (), +> { } pub fn check_path<'a, 'tcx>( diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 2781d54af88..42d3875ad19 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -58,14 +58,14 @@ fn main() { fn generic(arg: T) -> &SomeType where T: Fn(// First arg - A, - // Second argument - B, - C, - D, - // pre comment - E /* last comment */) - -> &SomeType, + A, + // Second argument + B, + C, + D, + // pre comment + E /* last comment */) + -> &SomeType, { arg(a, b, c, d, e) } diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs index 27eeacaa08a..54fe361bb4e 100644 --- a/tests/target/issue-510.rs +++ b/tests/target/issue-510.rs @@ -5,24 +5,23 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { input: &ISizeConstraintInput, ) -> ISizeConstraintSolution { - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match ( - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - ) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size( - available_inline_size - (margin_start + margin_end), - ); - (Au(0), inline_size, margin_start, margin_end) - } - }; + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match ( + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + ) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); + (Au(0), inline_size, margin_start, margin_end) + } + }; let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match (inline_start, inline_end, computed_inline_size) { diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index 95e6d3be3ed..6f4e3a8de21 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -5,12 +5,8 @@ fn main() { match x { - aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == - "aaaaaaaaaaa \ - aaaaaaa aaaaaa" => - { - Ok(()) - } + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) + if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => Ok(()), _ => Err(x), } } diff --git a/tests/target/match.rs b/tests/target/match.rs index f21fdb37dc5..35b97094535 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -323,7 +323,8 @@ fn guards() { barrrrrrrrrrrr => {} aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if fooooooooooooooooooooo && - (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => { + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => { + {} } } } diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 8c1e2d9695d..49d0520a5d1 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -40,7 +40,7 @@ where fn baz< 'a: 'b, // comment on 'a - T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */ + T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, /* comment on T */ >( a: A, b: B, // comment on b @@ -164,11 +164,11 @@ fn deconstruct() fn deconstruct( foo: Bar, ) -> (SocketAddr, - Method, - Headers, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { + Method, + Headers, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } #[rustfmt_skip] diff --git a/tests/target/paths.rs b/tests/target/paths.rs index da266389b6b..9b48dd9a470 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -1,18 +1,18 @@ // rustfmt-normalize_comments: true fn main() { - let constellation_chan = Constellation::::start( - compositor_proxy, - resource_task, - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard, - ); + let constellation_chan = + Constellation::::start( + compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard, + ); Quux::::some_func(); diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 7ac75290f2e..fc92d379a52 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -25,10 +25,9 @@ formatting"#; filename.replace(" ", "\\"); - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = - funktion( - "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", - ); + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion( + "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", + ); let unicode = "a̐éö̲\r\n"; let unicode2 = "Löwe 老虎 Léopard"; diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs index 9ef4eecbcc5..c5e6b9525b4 100644 --- a/tests/target/trailing_commas.rs +++ b/tests/target/trailing_commas.rs @@ -11,7 +11,12 @@ fn main() { } } -fn f(x: T, y: S) -> T +fn f< + S, T, +>( + x: T, + y: S, +) -> T where T: P, S: Q, @@ -31,8 +36,9 @@ where } } -struct Pair -where +struct Pair< + S, T, +> where T: P, S: P + Q, { @@ -40,36 +46,56 @@ where b: S, } -struct TupPair(S, T) +struct TupPair< + S, T, +>(S, T) where T: P, S: P + Q; -enum E -where +enum E< + S, T, +> where S: P, T: P, { A { a: T, }, } -type Double where +type Double< + T, +> where T: P, - T: Q = Pair; + T: Q = Pair< + T, T, +>; extern "C" { - fn f(x: T, y: S) -> T + fn f< + S, T, + >( + x: T, + y: S, + ) -> T where T: P, S: Q; } -trait Q -where +trait Q< + S, T, +> where T: P, S: R, { - fn f(self, x: T, y: S, z: U) -> Self + fn f< + U, V, + >( + self, + x: T, + y: S, + z: U, + ) -> Self where U: P, V: P; diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index f398b7dffb7..772cb251f57 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -65,7 +65,9 @@ fn issue775() { ( "b".to_string(), Array(vec![ - mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object( + &[("c".to_string(), String("\x0c\r".to_string()))] + ), mk_object(&[("d".to_string(), String("".to_string()))]), ]), ), diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index 86180149aac..cd40f65d6e1 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -3,9 +3,11 @@ type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); -pub type PublicTest<'a, I, O> = Result, - Box + 'a>, - Box + 'a>>; +pub type PublicTest<'a, I, O> = Result< + Vec, + Box + 'a>, + Box + 'a>, +>; pub type LongGenericListTest< 'a, @@ -17,7 +19,7 @@ pub type LongGenericListTest< LONGPARAMETERNAME, A, B, - C + C, > = Option>; pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; @@ -37,13 +39,13 @@ pub type GenericsFitButNotEqualTest< LONGPARAMETERNAME, A1, B, - C + C, > = Vec; pub type CommentTest< // Lifetime 'a, // Type - T + T, > = (); -- cgit 1.4.1-3-g733a5 From c4d84b44ba39560e453f5cf6a026c40b98836852 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 00:06:48 +0900 Subject: Avoid overflow --- src/items.rs | 4 ++-- src/lib.rs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 156528301be..5144feed474 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1684,7 +1684,7 @@ fn rewrite_explicit_self( Some(ref l) => { let lifetime_str = try_opt!(l.rewrite( context, - Shape::legacy(usize::max_value(), Indent::empty()), + Shape::legacy(context.config.max_width(), Indent::empty()), )); Some(format!("&{} {}self", lifetime_str, mut_str)) } @@ -1697,7 +1697,7 @@ fn rewrite_explicit_self( let mutability = explicit_self_mutability(&args[0]); let type_str = try_opt!(ty.rewrite( context, - Shape::legacy(usize::max_value(), Indent::empty()), + Shape::legacy(context.config.max_width(), Indent::empty()), )); Some(format!( diff --git a/src/lib.rs b/src/lib.rs index 2aa477ccafa..1775752efce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,8 +148,12 @@ impl Indent { } pub fn block_unindent(mut self, config: &Config) -> Indent { - self.block_indent -= config.tab_spaces(); - self + if self.block_indent < config.tab_spaces() { + Indent::new(self.block_indent, 0) + } else { + self.block_indent -= config.tab_spaces(); + self + } } pub fn width(&self) -> usize { -- cgit 1.4.1-3-g733a5 From 384d985df9648027e26125a5d2e38dfbd4a010a3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 00:08:31 +0900 Subject: Do not rely on format_missing for rewriting attributes --- src/expr.rs | 36 ++++++++++++++++++++++++++++++++---- src/visitor.rs | 17 ++++++++++++++--- 2 files changed, 46 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 80c89a3a91b..1e92b5b9368 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -47,16 +47,45 @@ enum ExprType { SubExpression, } +fn combine_attr_and_expr( + context: &RewriteContext, + shape: Shape, + attr_str: &str, + expr_str: &str, +) -> String { + let separator = if attr_str.is_empty() { + String::new() + } else { + if expr_str.contains('\n') || attr_str.contains('\n') || + attr_str.len() + expr_str.len() > shape.width + { + format!("\n{}", shape.indent.to_string(context.config)) + } else { + String::from(" ") + } + }; + format!("{}{}{}", attr_str, separator, expr_str) +} + fn format_expr( expr: &ast::Expr, expr_type: ExprType, context: &RewriteContext, shape: Shape, ) -> Option { + let attr_rw = (&*expr.attrs).rewrite(context, shape); if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span)); + if let Some(attr_str) = attr_rw { + return Some(combine_attr_and_expr( + context, + shape, + &attr_str, + &context.snippet(expr.span), + )); + } else { + return Some(context.snippet(expr.span)); + } } - let attr_rw = (&*expr.attrs).rewrite(context, shape); let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => { rewrite_array( @@ -289,9 +318,8 @@ fn format_expr( }; match (attr_rw, expr_rw) { (Some(attr_str), Some(expr_str)) => { - let space = if attr_str.is_empty() { "" } else { " " }; recover_comment_removed( - format!("{}{}{}", attr_str, space, expr_str), + combine_attr_and_expr(context, shape, &attr_str, &expr_str), expr.span, context, shape, diff --git a/src/visitor.rs b/src/visitor.rs index 6358cc7531f..08ff3cd4c61 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -82,15 +82,26 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Item(ref item) => { self.visit_item(item); } - ast::StmtKind::Local(..) | - ast::StmtKind::Expr(..) | - ast::StmtKind::Semi(..) => { + ast::StmtKind::Local(..) => { let rewrite = stmt.rewrite( &self.get_context(), Shape::indented(self.block_indent, self.config), ); self.push_rewrite(stmt.span, rewrite); } + ast::StmtKind::Expr(ref expr) | + ast::StmtKind::Semi(ref expr) => { + let rewrite = stmt.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ); + let span = if expr.attrs.is_empty() { + stmt.span + } else { + mk_sp(expr.attrs[0].span.lo, stmt.span.hi) + }; + self.push_rewrite(span, rewrite) + } ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, _) = **mac; self.visit_mac(mac, None, MacroPosition::Statement); -- cgit 1.4.1-3-g733a5 From e2d51aeb418391e89b9148ef5600df258fdb6e7f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 00:09:05 +0900 Subject: Use correct span for MetaItem --- src/visitor.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 08ff3cd4c61..7e3fed3faff 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -713,6 +713,12 @@ impl Rewrite for ast::NestedMetaItem { } } +fn count_missing_closing_parens(s: &str) -> u32 { + let op_parens = s.chars().filter(|c| *c == '(').count(); + let cl_parens = s.chars().filter(|c| *c == ')').count(); + op_parens.checked_sub(cl_parens).unwrap_or(0) as u32 +} + impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { @@ -723,15 +729,21 @@ impl Rewrite for ast::MetaItem { let item_shape = try_opt!(shape.shrink_left(name.len() + 3).and_then( |s| s.sub_width(2), )); + let hi = self.span.hi + + BytePos(count_missing_closing_parens(&context.snippet(self.span))); let items = itemize_list( context.codemap, list.iter(), ")", |nested_meta_item| nested_meta_item.span.lo, - |nested_meta_item| nested_meta_item.span.hi, + // FIXME: Span from MetaItem is missing closing parens. + |nested_meta_item| { + let snippet = context.snippet(nested_meta_item.span); + nested_meta_item.span.hi + BytePos(count_missing_closing_parens(&snippet)) + }, |nested_meta_item| nested_meta_item.rewrite(context, item_shape), self.span.lo, - self.span.hi, + hi, ); let item_vec = items.collect::>(); let fmt = ListFormatting { -- cgit 1.4.1-3-g733a5 From 18806321e60c631867f56d90a979686d59a3810d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 09:29:39 +0900 Subject: Use block indent style against tuple type --- src/expr.rs | 102 +++++++++++++++++++++++++++++++++++++---------------------- src/types.rs | 6 ++-- 2 files changed, 67 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1e92b5b9368..10e25bbc8c5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::cmp::{Ordering, min}; -use std::ops::Deref; use std::iter::ExactSizeIterator; use std::fmt::Write; @@ -1833,14 +1832,17 @@ pub fn rewrite_call( rewrite_call_inner(context, &callee, args, span, shape, false).ok() } -fn rewrite_call_inner( +fn rewrite_call_inner<'a, T>( context: &RewriteContext, callee_str: &str, - args: &[ptr::P], + args: &[ptr::P], span: Span, shape: Shape, force_trailing_comma: bool, -) -> Result { +) -> Result +where + T: Rewrite + Spanned + ToExpr + 'a, +{ // 2 = `( `, 1 = `(` let paren_overhead = if context.config.spaces_within_parens() { 2 @@ -1924,22 +1926,25 @@ fn need_block_indent(s: &str, shape: Shape) -> bool { }) } -fn rewrite_call_args( +fn rewrite_call_args<'a, T>( context: &RewriteContext, - args: &[ptr::P], + args: &[ptr::P], span: Span, shape: Shape, one_line_width: usize, force_trailing_comma: bool, -) -> Option<(bool, String)> { +) -> Option<(bool, String)> +where + T: Rewrite + Spanned + ToExpr + 'a, +{ let mut item_context = context.clone(); item_context.inside_macro = false; let items = itemize_list( context.codemap, args.iter(), ")", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span().lo, + |item| item.span().hi, |item| item.rewrite(&item_context, shape), span.lo, span.hi, @@ -1949,7 +1954,14 @@ fn rewrite_call_args( // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. - let tactic = try_overflow_last_arg(&item_context, &mut item_vec, args, shape, one_line_width); + let args = args.iter().filter_map(|e| e.to_expr()).collect::>(); + let tactic = try_overflow_last_arg( + &item_context, + &mut item_vec, + &args[..], + shape, + one_line_width, + ); let fmt = ListFormatting { tactic: tactic, @@ -1974,7 +1986,7 @@ fn rewrite_call_args( fn try_overflow_last_arg( context: &RewriteContext, item_vec: &mut Vec, - args: &[ptr::P], + args: &[&ast::Expr], shape: Shape, one_line_width: usize, ) -> DefinitiveListTactic { @@ -1991,7 +2003,7 @@ fn try_overflow_last_arg( last_arg_shape(&context, &item_vec, shape).map_or((None, None), |arg_shape| { rewrite_last_arg_with_overflow( &context, - &args[args.len() - 1], + args[args.len() - 1], &mut item_vec[args.len() - 1], arg_shape, ) @@ -2040,7 +2052,7 @@ fn last_arg_shape(context: &RewriteContext, items: &Vec, shape: Shape) fn rewrite_last_arg_with_overflow( context: &RewriteContext, - last_arg: &ptr::P, + last_arg: &ast::Expr, last_item: &mut ListItem, shape: Shape, ) -> (Option, Option) { @@ -2056,7 +2068,7 @@ fn rewrite_last_arg_with_overflow( } } -fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P]) -> bool { +fn can_be_overflowed(context: &RewriteContext, args: &[&ast::Expr]) -> bool { args.last().map_or(false, |x| { can_be_overflowed_expr(context, &x, args.len()) }) @@ -2344,19 +2356,18 @@ fn shape_from_fn_call_style( } } -pub fn rewrite_tuple_type<'a, I>( +fn rewrite_tuple_in_visual_indent_style<'a, T>( context: &RewriteContext, - mut items: I, + items: &[ptr::P], span: Span, shape: Shape, ) -> Option where - I: ExactSizeIterator, - ::Item: Deref, - ::Target: Rewrite + Spanned + 'a, + T: Rewrite + Spanned + ToExpr + 'a, { + let mut items = items.iter(); // In case of length 1, need a trailing comma - debug!("rewrite_tuple_type {:?}", shape); + debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); if items.len() == 1 { // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); @@ -2392,28 +2403,29 @@ where } } -pub fn rewrite_tuple( +pub fn rewrite_tuple<'a, T>( context: &RewriteContext, - items: &[ptr::P], + items: &[ptr::P], span: Span, shape: Shape, -) -> Option { +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ debug!("rewrite_tuple {:?}", shape); - // Use old `rewrite_tuple` - if context.config.fn_call_style() == IndentStyle::Visual { - return rewrite_tuple_type(context, items.iter().map(|x| &**x), span, shape); + if context.use_block_indent() { + // We use the same rule as funcation call for rewriting tuple. + rewrite_call_inner( + context, + &String::new(), + items, + span, + shape, + items.len() == 1, + ).ok() + } else { + rewrite_tuple_in_visual_indent_style(context, items, span, shape) } - - // We use the same rule as funcation call for rewriting tuple. - // 1 = "," - rewrite_call_inner( - context, - &String::new(), - items, - span, - shape, - items.len() == 1, - ).ok() } pub fn rewrite_unary_prefix( @@ -2574,3 +2586,19 @@ fn rewrite_expr_addrof( }; rewrite_unary_prefix(context, operator_str, expr, shape) } + +pub trait ToExpr { + fn to_expr(&self) -> Option<&ast::Expr>; +} + +impl ToExpr for ast::Expr { + fn to_expr(&self) -> Option<&ast::Expr> { + Some(self) + } +} + +impl ToExpr for ast::Ty { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } +} diff --git a/src/types.rs b/src/types.rs index 5e57ce790a7..f084aecaee6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -23,7 +23,7 @@ use items::{format_generics_item_list, generics_shape_from_config}; use lists::{itemize_list, format_fn_args}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple_type}; +use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; use config::{Style, TypeDensity}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -689,9 +689,7 @@ impl Rewrite for ast::Ty { format!("[{}]", ty_str) }) } - ast::TyKind::Tup(ref items) => { - rewrite_tuple_type(context, items.iter().map(|x| &**x), self.span, shape) - } + ast::TyKind::Tup(ref items) => rewrite_tuple(context, items, self.span, shape), ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } -- cgit 1.4.1-3-g733a5 From 5f1bab26c4bb95e91a90a9fb581e246a08df3d85 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 14 Jun 2017 13:57:31 +1200 Subject: Move to Libsyntax --- Cargo.lock | 103 ++--------------------------------------------------- Cargo.toml | 9 ++--- README.md | 8 +++++ src/bin/rustfmt.rs | 2 +- src/lib.rs | 8 ++--- 5 files changed, 19 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b7b906b5d40..26b055b5a4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] -name = "rustfmt" -version = "0.9.0" +name = "rustfmt-nightly" +version = "0.1.0" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -13,8 +13,6 @@ dependencies = [ "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -29,11 +27,6 @@ dependencies = [ "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "diff" version = "0.1.10" @@ -53,16 +46,6 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "extprim" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "getopts" version = "0.2.14" @@ -110,14 +93,6 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rand" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "0.2.2" @@ -135,27 +110,6 @@ name = "regex-syntax" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc_version" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde" version = "1.0.8" @@ -217,44 +171,6 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "syntex_errors" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_pos" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syntex_syntax" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "extprim 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "term" version = "0.4.5" @@ -300,11 +216,6 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unreachable" version = "0.1.1" @@ -335,11 +246,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum extprim 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d9f92dbf3843b6b56a224bce6aacd734feea193013d6ee1e18f03dcb36a93911" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -348,12 +257,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" -"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f530d36fb84ec48fb7146936881f026cdbf4892028835fd9398475f82c1bb4" "checksum serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "10552fad5500771f3902d0c5ba187c5881942b811b7ba0d8fbbfbf84d80806d3" "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" @@ -361,16 +266,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum syntex_errors 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f769b93e132914e999edb13018e192bd5f0296c2886fb6d5473ee6e055acb1c" -"checksum syntex_pos 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56c108cb745a38857097c1662a9d513594486acaf1d508831201fd122f83ba44" -"checksum syntex_syntax 0.59.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c815f257bdfb6f8b8876bb2937438a5365f2884f268c312f864cd002abace6" "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" "checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 6bb598f0c0e..a0da1d6b685 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "rustfmt" -version = "0.9.0" +name = "rustfmt-nightly" +version = "0.1.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" @@ -14,6 +14,9 @@ categories = ["development-tools"] [lib] doctest = false +[[bin]] +name = "rustfmt" + [features] default = ["cargo-fmt"] cargo-fmt = [] @@ -28,8 +31,6 @@ regex = "0.2" term = "0.4" strings = "0.1" diff = "0.1" -syntex_syntax = "0.59" -syntex_errors = "0.59" log = "0.3" env_logger = "0.4" getopts = "0.2" diff --git a/README.md b/README.md index 54ff09ef78b..1660c5e7622 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,14 @@ The last version using the old style was 0.8.6. From 0.9 onwards, the RFC style is the default. If you want the old style back, you can use [legacy-rustfmt.toml](legacy-rustfmt.toml) as your rustfmt.toml. +The current `master` branch uses libsyntax (part of the compiler). It is +published as `rustfmt-nightly`. The `syntex` branch uses Syntex instead of +libsyntax, it is published (for now) as `rustfmt`. Most development happens on +the `master` branch, however, this only supports nightly toolchains. If you use +stable or beta Rust toolchains, you must use the Syntex version (which is likely +to be a bit out of date). Version 0.1 of rustfmt-nightly is forked from version +0.9 of the syntex branch. + ## Quick start diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 1929285fdfe..58b7e3ac8fd 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -12,7 +12,7 @@ extern crate log; -extern crate rustfmt; +extern crate rustfmt_nightly as rustfmt; extern crate toml; extern crate env_logger; extern crate getopts; diff --git a/src/lib.rs b/src/lib.rs index 1775752efce..62d4df502d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// TODO we're going to allocate a whole bunch of temp Strings, is it worth -// keeping some scratch mem for this and running our own StrPool? -// TODO for lint violations of names, emit a refactor script +#![feature(rustc_private)] #[macro_use] extern crate log; @@ -20,8 +18,8 @@ extern crate serde; extern crate serde_derive; extern crate serde_json; -extern crate syntex_syntax as syntax; -extern crate syntex_errors as errors; +extern crate syntax; +extern crate rustc_errors as errors; extern crate strings; -- cgit 1.4.1-3-g733a5 From 8955eb86e621c0713a9adacad79965bd6eb9af94 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 20:33:54 +0900 Subject: Direct format vec! instead of using rewrite_pair --- src/macros.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 562e776f8d3..cfc14b53adb 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,7 @@ use syntax::util::ThinVec; use Shape; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; -use expr::{rewrite_call, rewrite_array, rewrite_pair}; +use expr::{rewrite_call, rewrite_array}; use comment::{FindUncommented, contains_comment}; use utils::mk_sp; @@ -192,15 +192,28 @@ pub fn rewrite_macro( } else { ("[", "]") }; - rewrite_pair( - &*expr_vec[0], - &*expr_vec[1], - lbr, - "; ", - rbr, - context, - mac_shape, - ).map(|s| format!("{}{}", macro_name, s)) + // 6 = `vec!` + `; ` + let total_overhead = lbr.len() + rbr.len() + 6; + let lhs = try_opt!(expr_vec[0].rewrite(context, mac_shape)); + let rhs = try_opt!(expr_vec[1].rewrite(context, mac_shape)); + if !lhs.contains('\n') && !rhs.contains('\n') && + lhs.len() + rhs.len() + total_overhead <= shape.width + { + Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) + } else { + let nested_indent = shape.indent.block_indent(context.config); + Some(format!( + "{}{}\n{}{};\n{}{}\n{}{}", + macro_name, + lbr, + nested_indent.to_string(context.config), + lhs, + nested_indent.to_string(context.config), + rhs, + shape.indent.to_string(context.config), + rbr + )) + } } else { // Format macro invocation as array literal. let rewrite = try_opt!(rewrite_array( -- cgit 1.4.1-3-g733a5 From 496e95846745aaa3f90c07cfd24bea1b6b24a0fa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 20:36:28 +0900 Subject: Put match arm guard on the next line if it contains new line --- src/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1e92b5b9368..e45aa20a68a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1650,7 +1650,9 @@ fn rewrite_guard( s.rewrite(context, cond_shape) }) { - return Some(format!(" if {}", cond_str)); + if !cond_str.contains('\n') { + return Some(format!(" if {}", cond_str)); + } } } -- cgit 1.4.1-3-g733a5 From c06d487712c309b1ff0197916e8148cad23cb0bd Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 20:37:54 +0900 Subject: Add offset wherever necessary --- src/expr.rs | 83 +++++++++++++++++++++++++++++++++--------------------------- src/items.rs | 12 ++++++++- 2 files changed, 57 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e45aa20a68a..7729ef5f10b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -371,7 +371,9 @@ where // This is needed in case of line break not caused by a // shortage of space, but by end-of-line comments, for example. if !rhs_result.contains('\n') { - let lhs_shape = try_opt!(shape.sub_width(prefix.len() + infix.len())); + let lhs_shape = try_opt!(try_opt!(shape.offset_left(prefix.len())).sub_width( + infix.len(), + )); let lhs_result = lhs.rewrite(context, lhs_shape); if let Some(lhs_result) = lhs_result { let mut result = format!("{}{}{}", prefix, lhs_result, infix); @@ -412,22 +414,23 @@ where try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) } Style::Rfc => { - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) + // Try to calculate the initial constraint on the right hand side. + let rhs_overhead = context + .config + .max_width() + .checked_sub(shape.used_width() + shape.width) + .unwrap_or(0); + try_opt!( + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(rhs_overhead) + ) } }; - let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); - let lhs_shape = match context.config.control_style() { - Style::Legacy => { - let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); - Shape { - width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), - ..shape - } - } - Style::Rfc => try_opt!(shape.sub_width(prefix.len() + infix.len())), + let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); + let lhs_shape = Shape { + width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), + ..shape }; let lhs_result = try_opt!(lhs.rewrite(context, lhs_shape)); Some(format!( @@ -484,12 +487,9 @@ where } } - let has_long_item = try_opt!( - items - .iter() - .map(|li| li.item.as_ref().map(|s| s.len() > 10)) - .fold(Some(false), |acc, x| acc.and_then(|y| x.map(|x| x || y))) - ); + let has_long_item = items.iter().any(|li| { + li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false) + }); let tactic = match context.config.array_layout() { IndentStyle::Block => { @@ -622,7 +622,7 @@ fn rewrite_closure( // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, shape) + 1; - let body_shape = try_opt!(shape.sub_width(extra_offset)).add_offset(extra_offset); + let body_shape = try_opt!(shape.offset_left(extra_offset)); if let ast::ExprKind::Block(ref block) = body.node { // The body of the closure is an empty block. @@ -1020,13 +1020,13 @@ impl<'a> Rewrite for ControlFlow<'a> { let label_string = rewrite_label(self.label); // 1 = space after keyword. - let add_offset = self.keyword.len() + label_string.len() + 1; + let offset = self.keyword.len() + label_string.len() + 1; let pat_expr_string = match self.cond { Some(cond) => { let mut cond_shape = match context.config.control_style() { - Style::Legacy => try_opt!(constr_shape.shrink_left(add_offset)), - Style::Rfc => try_opt!(constr_shape.sub_width(add_offset)), + Style::Legacy => try_opt!(constr_shape.shrink_left(offset)), + Style::Rfc => try_opt!(constr_shape.offset_left(offset)), }; if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { // 2 = " {".len() @@ -1346,7 +1346,7 @@ fn rewrite_match( // `match `cond` {` let cond_shape = match context.config.control_style() { Style::Legacy => try_opt!(shape.shrink_left(6).and_then(|s| s.sub_width(2))), - Style::Rfc => try_opt!(shape.sub_width(8)), + Style::Rfc => try_opt!(shape.offset_left(8)), }; let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); @@ -1572,8 +1572,7 @@ impl Rewrite for ast::Arm { // FIXME: we're doing a second rewrite of the expr; This may not be // necessary. - let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces())) - .block_indent(context.config.tab_spaces()); + let body_shape = try_opt!(shape.block_left(context.config.tab_spaces())); let next_line_body = try_opt!(nop_block_collapse( body.rewrite(context, body_shape), body_shape.width, @@ -1700,7 +1699,7 @@ fn rewrite_pat_expr( } else { format!("{} ", matcher) }; - let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len())).sub_width( + let pat_shape = try_opt!(try_opt!(shape.offset_left(matcher.len())).sub_width( connector.len(), )); pat_string = try_opt!(pat.rewrite(context, pat_shape)); @@ -2133,19 +2132,29 @@ fn wrap_args_with_parens( fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { debug!("rewrite_paren, shape: {:?}", shape); - // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing - // paren on the same line as the subexpr. - let sub_shape = try_opt!(shape.sub_width(2)).visual_indent(1); - let subexpr_str = subexpr.rewrite(context, sub_shape); - debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); + let paren_overhead = paren_overhead(context); + let sub_shape = try_opt!(shape.sub_width(paren_overhead / 2)).visual_indent(paren_overhead / 2); - subexpr_str.map(|s| if context.config.spaces_within_parens() && - s.len() > 0 - { + let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && s.len() > 0 { format!("( {} )", s) } else { format!("({})", s) - }) + }; + + let subexpr_str = try_opt!(subexpr.rewrite(context, sub_shape)); + debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); + + if subexpr_str.contains('\n') { + Some(paren_wrapper(&subexpr_str)) + } else { + if subexpr_str.len() + paren_overhead <= shape.width { + Some(paren_wrapper(&subexpr_str)) + } else { + let sub_shape = try_opt!(shape.offset_left(2)); + let subexpr_str = try_opt!(subexpr.rewrite(context, sub_shape)); + Some(paren_wrapper(&subexpr_str)) + } + } } fn rewrite_index( diff --git a/src/items.rs b/src/items.rs index 5144feed474..2e00bcbd10d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1831,7 +1831,17 @@ fn rewrite_fn_base( result.push_str(&ident.to_string()); // Generics. - let shape = Shape::indented(indent + last_line_width(&result), context.config); + let overhead = if has_braces && !newline_brace { + // 4 = `() {` + 4 + } else { + // 2 = `()` + 2 + }; + let shape = try_opt!( + Shape::indented(indent + last_line_width(&result), context.config) + .sub_width(overhead) + ); let g_span = mk_sp(span.lo, span_for_return(&fd.output).lo); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); -- cgit 1.4.1-3-g733a5 From b8f11a4e3c1c3a381daa19da28e3e9d686c25aa0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 14 Jun 2017 20:39:07 +0900 Subject: Format source codes --- src/comment.rs | 4 ++-- src/expr.rs | 32 ++++++++++------------------ src/items.rs | 25 +++++++++++----------- src/string.rs | 2 +- src/types.rs | 6 +++--- src/visitor.rs | 9 ++++---- tests/target/configs-control_style-rfc.rs | 2 +- tests/target/configs-trailing_comma-never.rs | 8 +++---- tests/target/expr.rs | 18 +++++++++------- tests/target/fn_args_layout-block.rs | 7 +++++- tests/target/hard-tabs.rs | 2 +- tests/target/issue-1397.rs | 4 ++-- tests/target/macros.rs | 19 +++++++++++------ tests/target/match.rs | 19 +++++++---------- 14 files changed, 79 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d31ba5f9f2d..e9f84b71e48 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -319,8 +319,8 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { } else { &line[opener.trim_right().len()..] } - } else if line.starts_with("/* ") || line.starts_with("// ") || - line.starts_with("//!") || line.starts_with("///") || + } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || + line.starts_with("///") || line.starts_with("** ") || line.starts_with("/*!") || (line.starts_with("/**") && !line.starts_with("/**/")) { diff --git a/src/expr.rs b/src/expr.rs index 7729ef5f10b..d236448caf5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -729,9 +729,10 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); - block_str.map(|block_str| if block_str.starts_with('{') && - budget >= 2 && - (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && + (block_str[1..] + .find(|c: char| !c.is_whitespace()) + .unwrap() == block_str.len() - 2) { "{}".to_owned() } else { @@ -1509,9 +1510,9 @@ impl Rewrite for ast::Arm { let pats_str = format!("{}{}", pats_str, guard_str); let (mut extend, body) = match body.node { - ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && - is_simple_block(block, context.codemap) && - context.config.wrap_match_arms() => { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && + context.config.wrap_match_arms() => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { (false, &**expr) } else { @@ -2539,21 +2540,10 @@ pub fn rewrite_assign_rhs>( // FIXME: DRY! match (rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref replacement_rhs)) if count_line_breaks( - orig_rhs, - ) > - count_line_breaks( - replacement_rhs, - ) + 1 || - (orig_rhs - .rewrite(context, shape) - .is_none() && - replacement_rhs - .rewrite( - context, - new_shape, - ) - .is_some()) => { + (Some(ref orig_rhs), Some(ref replacement_rhs)) + if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 || + (orig_rhs.rewrite(context, shape).is_none() && + replacement_rhs.rewrite(context, new_shape).is_some()) => { result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(replacement_rhs); } diff --git a/src/items.rs b/src/items.rs index 2e00bcbd10d..a660f287a5b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -685,12 +685,12 @@ fn format_impl_ref_and_type( offset: Indent, ) -> Option { if let ast::ItemKind::Impl(unsafety, - polarity, - _, - ref generics, - ref trait_ref, - ref self_ty, - _) = item.node + polarity, + _, + ref generics, + ref trait_ref, + ref self_ty, + _) = item.node { let mut result = String::new(); @@ -942,8 +942,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); let where_density = if (context.config.where_density() == Density::Compressed && - (!result.contains('\n') || - context.config.fn_args_layout() == IndentStyle::Block)) || + (!result.contains('\n') || + context.config.fn_args_layout() == IndentStyle::Block)) || (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) || (context.config.where_density() == Density::CompressedIfEmpty && !has_body && !result.contains('\n')) @@ -1468,9 +1468,9 @@ impl Rewrite for ast::StructField { Some(ref ty) if ty.contains('\n') => { let new_ty = rewrite_type_in_next_line(); match new_ty { - Some(ref new_ty) if !new_ty.contains('\n') && - new_ty.len() + type_offset.width() <= - context.config.max_width() => { + Some(ref new_ty) + if !new_ty.contains('\n') && + new_ty.len() + type_offset.width() <= context.config.max_width() => { Some(format!( "{}\n{}{}", result, @@ -2688,7 +2688,8 @@ fn format_generics( let same_line_brace = force_same_line_brace || (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1); if !same_line_brace && - (brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) + (brace_style == BraceStyle::SameLineWhere || + brace_style == BraceStyle::AlwaysNextLine) { result.push('\n'); result.push_str(&offset.block_only().to_string(context.config)); diff --git a/src/string.rs b/src/string.rs index 6c20c18ca47..5ba273ad272 100644 --- a/src/string.rs +++ b/src/string.rs @@ -81,7 +81,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option if cur_end < cur_start + MIN_STRING { cur_end = cur_start + max_chars; while !(punctuation.contains(graphemes[cur_end - 1]) || - graphemes[cur_end - 1].trim().is_empty()) + graphemes[cur_end - 1].trim().is_empty()) { if cur_end >= graphemes.len() { let line = &graphemes[cur_start..].join(""); diff --git a/src/types.rs b/src/types.rs index 5e57ce790a7..3774df70146 100644 --- a/src/types.rs +++ b/src/types.rs @@ -206,9 +206,9 @@ fn rewrite_segment( let params = if let Some(ref params) = segment.parameters { match **params { - ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() || - !data.types.is_empty() || - !data.bindings.is_empty() => { + ast::PathParameters::AngleBracketed(ref data) + if !data.lifetimes.is_empty() || !data.types.is_empty() || + !data.bindings.is_empty() => { let param_list = data.lifetimes .iter() .map(SegmentParam::LifeTime) diff --git a/src/visitor.rs b/src/visitor.rs index 7e3fed3faff..9ed40cc29ee 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -546,10 +546,11 @@ impl<'a> FmtVisitor<'a> { fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo); self.failed = match rewrite { - Some(ref s) if s.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ).is_none() => true, + Some(ref s) + if s.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ).is_none() => true, None => true, _ => self.failed, }; diff --git a/tests/target/configs-control_style-rfc.rs b/tests/target/configs-control_style-rfc.rs index 43a10e92339..20742da2195 100644 --- a/tests/target/configs-control_style-rfc.rs +++ b/tests/target/configs-control_style-rfc.rs @@ -5,7 +5,7 @@ fn main() { loop { if foo { if ((right_paddle_speed < 0.) && - (right_paddle.position().y - paddle_size.y / 2. > 5.)) || + (right_paddle.position().y - paddle_size.y / 2. > 5.)) || ((right_paddle_speed > 0.) && (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) { diff --git a/tests/target/configs-trailing_comma-never.rs b/tests/target/configs-trailing_comma-never.rs index f38d26d64db..8f351e8dfc2 100644 --- a/tests/target/configs-trailing_comma-never.rs +++ b/tests/target/configs-trailing_comma-never.rs @@ -14,10 +14,10 @@ fn main() { // #1544 if let VrMsg::ClientReply { - request_num: reply_req_num, - value, - .. - } = msg + request_num: reply_req_num, + value, + .. + } = msg { let _ = safe_assert_eq!(reply_req_num, request_num, op); return Ok((request_num, op, value)); diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 3932992af62..3b17aee5a78 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -7,8 +7,8 @@ fn foo() -> bool { let referenced = &5; let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = - (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + + BBBBBBBBBBBBBBBBB + b + c); let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); @@ -20,8 +20,10 @@ fn foo() -> bool { 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), trivial_value, ); - (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaa))))))))); { for _ in 0..10 {} @@ -47,21 +49,21 @@ fn foo() -> bool { } if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 { } if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {} let test = if true { 5 } else { 3 }; diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index 93f14c526bd..1d4a1fb6792 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -96,7 +96,12 @@ fn foo() { foo(); } -fn foo() { +fn foo< + L: Loooooooooooooooooooooong, + G: Geeeeeeeeeeeneric, + I: iiiiiiiiis, + L: Looooooooooooooooong, +>() { foo(); } diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 42d3875ad19..48c72afd055 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -22,7 +22,7 @@ fn main() { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 {} if cond() { diff --git a/tests/target/issue-1397.rs b/tests/target/issue-1397.rs index f267a91d3e1..21c3c9e38de 100644 --- a/tests/target/issue-1397.rs +++ b/tests/target/issue-1397.rs @@ -12,8 +12,8 @@ fn baz(p: Packet) { loop { loop { if let Packet::Transaction { - state: TransactionState::Committed(ts, ..), .. - } = p + state: TransactionState::Committed(ts, ..), .. + } = p { unreachable!() } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 6185e21a835..9cc3305ea39 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -67,13 +67,18 @@ fn main() { vec![a, b; c]; vec![a; b, c]; - vec![a; - (|x| { - let y = x + 1; - let z = y + 1; - z - })(2)]; - vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![ + a; + (|x| { + let y = x + 1; + let z = y + 1; + z + })(2) + ]; + vec![ + a; + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ]; vec![a; unsafe { x + 1 }]; unknown_bracket_macro__comma_should_not_be_stripped![ diff --git a/tests/target/match.rs b/tests/target/match.rs index 35b97094535..040fbf155a4 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -37,10 +37,8 @@ fn foo() { Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} _ => {} - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > - 0 || - data.types.len() > 0 || - data.bindings.len() > 0 => {} + ast::PathParameters::AngleBracketedParameters(ref data) + if data.lifetimes.len() > 0 || data.types.len() > 0 || data.bindings.len() > 0 => {} } let whatever = match something { @@ -316,16 +314,15 @@ fn issue386() { fn guards() { match foo { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && - barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if foooooooooooooo && barrrrrrrrrrrr => {} aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && - barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if foooooooooooooo && barrrrrrrrrrrr => {} aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if fooooooooooooooooooooo && - (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => { - {} - } + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || + cccccccccccccccccccccccccccccccccccccccc) => {} } } -- cgit 1.4.1-3-g733a5 From a5138b16768d2ceefee3deba995cd45fc1f52fdb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 16:25:40 +0900 Subject: Use block indent for tuple pattern when fn_call_style is Block --- src/expr.rs | 152 +++++++++++++++++++++++++++++++++++++++++--------------- src/patterns.rs | 125 +++++++++++++++++++++++++--------------------- src/types.rs | 16 +++++- 3 files changed, 197 insertions(+), 96 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index afa4aa851f3..6bba83b520c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -25,10 +25,11 @@ use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_w use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; -use types::{rewrite_path, PathContext}; +use types::{rewrite_path, PathContext, can_be_overflowed_type}; use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; use macros::{rewrite_macro, MacroPosition}; +use patterns::{TuplePatField, can_be_overflowed_pat}; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos}; @@ -110,7 +111,13 @@ fn format_expr( } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, expr.span.hi); - rewrite_call_with_binary_search(context, &**callee, args, inner_span, shape) + rewrite_call_with_binary_search( + context, + &**callee, + &args.iter().map(|x| &**x).collect::>()[..], + inner_span, + shape, + ) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { @@ -136,7 +143,14 @@ fn format_expr( shape, ) } - ast::ExprKind::Tup(ref items) => rewrite_tuple(context, items, expr.span, shape), + ast::ExprKind::Tup(ref items) => { + rewrite_tuple( + context, + &items.iter().map(|x| &**x).collect::>()[..], + expr.span, + shape, + ) + } ast::ExprKind::While(ref cond, ref block, label) => { ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape) } @@ -1800,7 +1814,7 @@ fn string_requires_rewrite( pub fn rewrite_call_with_binary_search( context: &RewriteContext, callee: &R, - args: &[ptr::P], + args: &[&ast::Expr], span: Span, shape: Shape, ) -> Option @@ -1818,7 +1832,15 @@ where Ordering::Greater, )?; - rewrite_call_inner(context, &callee_str, args, span, shape, false) + rewrite_call_inner( + context, + &callee_str, + args, + span, + shape, + context.config.fn_call_width(), + false, + ) }; binary_search(1, shape.width, closure) @@ -1831,15 +1853,24 @@ pub fn rewrite_call( span: Span, shape: Shape, ) -> Option { - rewrite_call_inner(context, &callee, args, span, shape, false).ok() + rewrite_call_inner( + context, + &callee, + &args.iter().map(|x| &**x).collect::>(), + span, + shape, + context.config.fn_call_width(), + false, + ).ok() } -fn rewrite_call_inner<'a, T>( +pub fn rewrite_call_inner<'a, T>( context: &RewriteContext, callee_str: &str, - args: &[ptr::P], + args: &[&T], span: Span, shape: Shape, + args_max_width: usize, force_trailing_comma: bool, ) -> Result where @@ -1873,6 +1904,7 @@ where args_span, nested_shape, one_line_width, + args_max_width, force_trailing_comma, ).or_else(|| if context.use_block_indent() { rewrite_call_args( @@ -1884,6 +1916,7 @@ where context.config, ), 0, + 0, force_trailing_comma, ) } else { @@ -1900,6 +1933,7 @@ where args, span, shape, + args_max_width, force_trailing_comma, ); } @@ -1930,10 +1964,11 @@ fn need_block_indent(s: &str, shape: Shape) -> bool { fn rewrite_call_args<'a, T>( context: &RewriteContext, - args: &[ptr::P], + args: &[&T], span: Span, shape: Shape, one_line_width: usize, + args_max_width: usize, force_trailing_comma: bool, ) -> Option<(bool, String)> where @@ -1956,13 +1991,13 @@ where // Try letting the last argument overflow to the next line with block // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. - let args = args.iter().filter_map(|e| e.to_expr()).collect::>(); let tactic = try_overflow_last_arg( &item_context, &mut item_vec, &args[..], shape, one_line_width, + args_max_width, ); let fmt = ListFormatting { @@ -1985,38 +2020,45 @@ where }) } -fn try_overflow_last_arg( +fn try_overflow_last_arg<'a, T>( context: &RewriteContext, item_vec: &mut Vec, - args: &[&ast::Expr], + args: &[&T], shape: Shape, one_line_width: usize, -) -> DefinitiveListTactic { + args_max_width: usize, +) -> DefinitiveListTactic +where + T: Rewrite + Spanned + ToExpr + 'a, +{ let overflow_last = can_be_overflowed(&context, args); // Replace the last item with its first line to see if it fits with // first arguments. let (orig_last, placeholder) = if overflow_last { let mut context = context.clone(); - match args[args.len() - 1].node { - ast::ExprKind::MethodCall(..) => context.force_one_line_chain = true, - _ => (), - } - last_arg_shape(&context, &item_vec, shape).map_or((None, None), |arg_shape| { - rewrite_last_arg_with_overflow( - &context, - args[args.len() - 1], - &mut item_vec[args.len() - 1], - arg_shape, - ) - }) + if let Some(expr) = args[args.len() - 1].to_expr() { + match expr.node { + ast::ExprKind::MethodCall(..) => context.force_one_line_chain = true, + _ => (), + } + } + last_arg_shape(&context, &item_vec, shape, args_max_width) + .map_or((None, None), |arg_shape| { + rewrite_last_arg_with_overflow( + &context, + args[args.len() - 1], + &mut item_vec[args.len() - 1], + arg_shape, + ) + }) } else { (None, None) }; let tactic = definitive_tactic( &*item_vec, - ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()), + ListTactic::LimitedHorizontalVertical(args_max_width), one_line_width, ); @@ -2035,11 +2077,16 @@ fn try_overflow_last_arg( tactic } -fn last_arg_shape(context: &RewriteContext, items: &Vec, shape: Shape) -> Option { +fn last_arg_shape( + context: &RewriteContext, + items: &Vec, + shape: Shape, + args_max_width: usize, +) -> Option { let overhead = items.iter().rev().skip(1).fold(0, |acc, i| { acc + i.item.as_ref().map_or(0, |s| first_line_width(&s)) }); - let max_width = min(context.config.fn_call_width(), shape.width); + let max_width = min(args_max_width, shape.width); let arg_indent = if context.use_block_indent() { shape.block().indent.block_unindent(context.config) } else { @@ -2052,12 +2099,15 @@ fn last_arg_shape(context: &RewriteContext, items: &Vec, shape: Shape) }) } -fn rewrite_last_arg_with_overflow( +fn rewrite_last_arg_with_overflow<'a, T>( context: &RewriteContext, - last_arg: &ast::Expr, + last_arg: &T, last_item: &mut ListItem, shape: Shape, -) -> (Option, Option) { +) -> (Option, Option) +where + T: Rewrite + Spanned + ToExpr + 'a, +{ let rewrite = last_arg.rewrite(context, shape); let orig_last = last_item.item.clone(); @@ -2070,13 +2120,17 @@ fn rewrite_last_arg_with_overflow( } } -fn can_be_overflowed(context: &RewriteContext, args: &[&ast::Expr]) -> bool { - args.last().map_or(false, |x| { - can_be_overflowed_expr(context, &x, args.len()) - }) +fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + args.last().map_or( + false, + |x| x.can_be_overflowed(context, args.len()), + ) } -fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { +pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { match expr.node { ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) || @@ -2117,7 +2171,7 @@ fn paren_overhead(context: &RewriteContext) -> usize { } } -fn wrap_args_with_parens( +pub fn wrap_args_with_parens( context: &RewriteContext, args_str: &str, is_extendable: bool, @@ -2370,7 +2424,7 @@ fn shape_from_fn_call_style( fn rewrite_tuple_in_visual_indent_style<'a, T>( context: &RewriteContext, - items: &[ptr::P], + items: &[&T], span: Span, shape: Shape, ) -> Option @@ -2417,7 +2471,7 @@ where pub fn rewrite_tuple<'a, T>( context: &RewriteContext, - items: &[ptr::P], + items: &[&T], span: Span, shape: Shape, ) -> Option @@ -2433,6 +2487,7 @@ where items, span, shape, + context.config.fn_call_width(), items.len() == 1, ).ok() } else { @@ -2590,16 +2645,35 @@ fn rewrite_expr_addrof( pub trait ToExpr { fn to_expr(&self) -> Option<&ast::Expr>; + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool; } impl ToExpr for ast::Expr { fn to_expr(&self) -> Option<&ast::Expr> { Some(self) } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_expr(context, self, len) + } } impl ToExpr for ast::Ty { fn to_expr(&self) -> Option<&ast::Expr> { None } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_type(context, self, len) + } +} + +impl<'a> ToExpr for TuplePatField<'a> { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_pat(context, self, len) + } } diff --git a/src/patterns.rs b/src/patterns.rs index 25290ceaf0e..88d63af2298 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -13,10 +13,9 @@ use codemap::SpanUtils; use config::{IndentStyle, MultilineStyle}; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability, mk_sp}; -use lists::{DefinitiveListTactic, SeparatorTactic, format_item_list, itemize_list, ListItem, - struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting, - write_list}; -use expr::{rewrite_unary_prefix, rewrite_pair}; +use lists::{DefinitiveListTactic, SeparatorTactic, itemize_list, struct_lit_shape, + struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list}; +use expr::{rewrite_call_inner, rewrite_unary_prefix, rewrite_pair, can_be_overflowed_expr}; use types::{rewrite_path, PathContext}; use super::Spanned; use comment::FindUncommented; @@ -239,7 +238,7 @@ impl Rewrite for FieldPat { } } -enum TuplePatField<'a> { +pub enum TuplePatField<'a> { Pat(&'a ptr::P), Dotdot(Span), } @@ -262,6 +261,24 @@ impl<'a> Spanned for TuplePatField<'a> { } } +pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { + match pat { + &TuplePatField::Pat(ref pat) => { + match pat.node { + ast::PatKind::Tuple(..) | + ast::PatKind::Struct(..) => context.use_block_indent() && len == 1, + ast::PatKind::Ref(ref p, _) | + ast::PatKind::Box(ref p) => { + can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) + } + ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), + _ => false, + } + } + &TuplePatField::Dotdot(..) => false, + } +} + fn rewrite_tuple_pat( pats: &[ptr::P], dotdot_pos: Option, @@ -286,77 +303,73 @@ fn rewrite_tuple_pat( let dot_span = mk_sp(prev, next); let snippet = context.snippet(dot_span); let lo = dot_span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); - let span = Span { + let dotdot = TuplePatField::Dotdot(Span { lo: lo, // 2 == "..".len() hi: lo + BytePos(2), ctxt: codemap::NO_EXPANSION, - }; - let dotdot = TuplePatField::Dotdot(span); + }); pat_vec.insert(pos, dotdot); } if pat_vec.is_empty() { return Some(format!("{}()", try_opt!(path_str))); } + + let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); + let (pat_vec, span) = + if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 { + let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; + let sp = pat_vec[new_item_count - 1].span(); + let snippet = context.snippet(sp); + let lo = sp.lo + BytePos(snippet.find_uncommented("_").unwrap() as u32); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + (&pat_vec[..new_item_count], mk_sp(span.lo, lo + BytePos(1))) + } else { + (&pat_vec[..], span) + }; + // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + let mut context = context.clone(); + if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { + context.inside_macro = true; + } + let path_str = path_str.unwrap_or(String::new()); + let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); + for pat in pat_vec { + pat_ref_vec.push(pat); + } + return rewrite_call_inner( + &context, + &path_str, + &pat_ref_vec[..], + span, + shape, + shape.width, + add_comma, + ).ok(); +} + +fn count_wildcard_suffix_len( + context: &RewriteContext, + patterns: &[TuplePatField], + span: Span, + shape: Shape, +) -> usize { + let mut suffix_len = 0; - let path_len = path_str.as_ref().map(|p| p.len()).unwrap_or(0); - // 2 = "()".len(), 3 = "(,)".len() - let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 })); - // 1 = "(".len() - let nested_shape = nested_shape.visual_indent(path_len + 1); - let mut items: Vec<_> = itemize_list( + let items: Vec<_> = itemize_list( context.codemap, - pat_vec.iter(), - if add_comma { ",)" } else { ")" }, + patterns.iter(), + ")", |item| item.span().lo, |item| item.span().hi, - |item| item.rewrite(context, nested_shape), + |item| item.rewrite(context, shape), context.codemap.span_after(span, "("), span.hi - BytePos(1), ).collect(); - // Condense wildcard string suffix into a single .. - let wildcard_suffix_len = count_wildcard_suffix_len(&items); - - let list = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 { - let new_item_count = 1 + pats.len() - wildcard_suffix_len; - items[new_item_count - 1].item = Some("..".to_owned()); - - let da_iter = items.into_iter().take(new_item_count); - try_opt!(format_item_list(da_iter, nested_shape, context.config)) - } else { - try_opt!(format_item_list( - items.into_iter(), - nested_shape, - context.config, - )) - }; - - match path_str { - Some(path_str) => { - Some(if context.config.spaces_within_parens() { - format!("{}( {} )", path_str, list) - } else { - format!("{}({})", path_str, list) - }) - } - None => { - let comma = if add_comma { "," } else { "" }; - Some(if context.config.spaces_within_parens() { - format!("( {}{} )", list, comma) - } else { - format!("({}{})", list, comma) - }) - } - } -} - -fn count_wildcard_suffix_len(items: &[ListItem]) -> usize { - let mut suffix_len = 0; - for item in items.iter().rev().take_while(|i| match i.item { Some(ref internal_string) if internal_string == "_" => true, _ => false, diff --git a/src/types.rs b/src/types.rs index 665eb2ce35e..d725b091983 100644 --- a/src/types.rs +++ b/src/types.rs @@ -689,7 +689,14 @@ impl Rewrite for ast::Ty { format!("[{}]", ty_str) }) } - ast::TyKind::Tup(ref items) => rewrite_tuple(context, items, self.span, shape), + ast::TyKind::Tup(ref items) => { + rewrite_tuple( + context, + &items.iter().map(|x| &**x).collect::>()[..], + self.span, + shape, + ) + } ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } @@ -792,3 +799,10 @@ pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &Vec bool { + match ty.node { + ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, + _ => false, + } +} -- cgit 1.4.1-3-g733a5 From 8a6e9f689b09421b281e0e9dc4f014001097def8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 16:26:41 +0900 Subject: Format source codes --- src/items.rs | 16 +++++++++------- src/types.rs | 26 +++++++++++++------------- src/utils.rs | 1 + 3 files changed, 23 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a660f287a5b..7a2d3048ff0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -684,13 +684,15 @@ fn format_impl_ref_and_type( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl(unsafety, - polarity, - _, - ref generics, - ref trait_ref, - ref self_ty, - _) = item.node + if let ast::ItemKind::Impl( + unsafety, + polarity, + _, + ref generics, + ref trait_ref, + ref self_ty, + _, + ) = item.node { let mut result = String::new(); diff --git a/src/types.rs b/src/types.rs index d725b091983..edeeb1e3b72 100644 --- a/src/types.rs +++ b/src/types.rs @@ -371,11 +371,11 @@ impl Rewrite for ast::WherePredicate { // TODO: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_lifetimes, - ref bounded_ty, - ref bounds, - .. - }) => { + ref bound_lifetimes, + ref bounded_ty, + ref bounds, + .. + }) => { let type_str = try_opt!(bounded_ty.rewrite(context, shape)); let colon = type_bound_colon(context); @@ -428,10 +428,10 @@ impl Rewrite for ast::WherePredicate { } } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - ref lifetime, - ref bounds, - .. - }) => { + ref lifetime, + ref bounds, + .. + }) => { try_opt!(rewrite_bounded_lifetime( lifetime, bounds.iter(), @@ -440,10 +440,10 @@ impl Rewrite for ast::WherePredicate { )) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { + ref lhs_ty, + ref rhs_ty, + .. + }) => { let lhs_ty_str = try_opt!(lhs_ty.rewrite(context, shape)); // 3 = " = ".len() let used_width = 3 + lhs_ty_str.len(); diff --git a/src/utils.rs b/src/utils.rs index 0d1b32570c8..c432df301df 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -99,6 +99,7 @@ pub fn last_line_width(s: &str) -> usize { None => s.len(), } } + #[inline] pub fn trimmed_last_line_width(s: &str) -> usize { match s.rfind('\n') { -- cgit 1.4.1-3-g733a5 From de10113c748825750b421e4ec5e0fe5aaf1d65ec Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 16:26:46 +0900 Subject: Update tests Add more patterns and types --- src/patterns.rs | 1 + src/types.rs | 3 +++ tests/target/closure.rs | 26 ++++++++++++++------------ tests/target/expr.rs | 22 +++++++++++++--------- tests/target/hard-tabs.rs | 6 ++++-- tests/target/issue-1021.rs | 28 ++++++++++++++++++---------- tests/target/issue-913.rs | 6 ++++-- tests/target/match.rs | 10 ++++++---- tests/target/pattern-condense-wildcards.rs | 12 +++++++----- tests/target/pattern.rs | 5 +++-- 10 files changed, 73 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 88d63af2298..3ca8aa52455 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -265,6 +265,7 @@ pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: match pat { &TuplePatField::Pat(ref pat) => { match pat.node { + ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => context.use_block_indent() && len == 1, ast::PatKind::Ref(ref p, _) | diff --git a/src/types.rs b/src/types.rs index edeeb1e3b72..57a7b301f54 100644 --- a/src/types.rs +++ b/src/types.rs @@ -802,7 +802,10 @@ pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &Vec bool { match ty.node { + ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, + ast::TyKind::Rptr(_, ref mutty) | + ast::TyKind::Ptr(ref mutty) => can_be_overflowed_type(context, &*mutty.ty, len), _ => false, } } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 4f35a7b413a..47d8c6bf166 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -128,18 +128,20 @@ fn issue470() { { { { - let explicit_arg_decls = explicit_arguments.into_iter().enumerate().map(|(index, - (ty, - pattern))| { - let lvalue = Lvalue::Arg(index as u32); - block = this.pattern( - block, - argument_extent, - hair::PatternRef::Hair(pattern), - &lvalue, - ); - ArgDecl { ty: ty } - }); + let explicit_arg_decls = + explicit_arguments.into_iter().enumerate().map(|( + index, + (ty, pattern), + )| { + let lvalue = Lvalue::Arg(index as u32); + block = this.pattern( + block, + argument_extent, + hair::PatternRef::Hair(pattern), + &lvalue, + ); + ArgDecl { ty: ty } + }); } } } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 3b17aee5a78..7741939df45 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -52,18 +52,22 @@ fn foo() -> bool { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 - { - } + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = - 1111 + 2222 + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1111 + 2222 {} - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 {} let test = if true { 5 } else { 3 }; diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 48c72afd055..68919b1039c 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -21,8 +21,10 @@ fn main() { let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + 2 + 3 + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 {} if cond() { diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs index cc85aa73cae..70347407346 100644 --- a/tests/target/issue-1021.rs +++ b/tests/target/issue-1021.rs @@ -6,11 +6,15 @@ fn main() { S(.., true) => (), S(..) => (), S(_) => (), - S(// .. - ..) => (), - S(// .. - .., - true) => (), + S( + // .. + .. + ) => (), + S( + // .. + .., + true, + ) => (), } match y { @@ -19,10 +23,14 @@ fn main() { (.., true) => (), (..) => (), (_,) => (), - (// .. - ..) => (), - (// .. - .., - true) => (), + ( + // .. + .. + ) => (), + ( + // .. + .., + true, + ) => (), } } diff --git a/tests/target/issue-913.rs b/tests/target/issue-913.rs index 98f766e7310..1bfd1cd0041 100644 --- a/tests/target/issue-913.rs +++ b/tests/target/issue-913.rs @@ -10,11 +10,13 @@ mod client { }; let next_state = match self.state { - State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { + State::V5( + v5::State::Command(v5::comand::State::WriteVersion(ref mut response)), + ) => { // The pattern cannot be formatted in a way that the match stays // within the column limit. The rewrite should therefore be // skipped. - let x = dont . reformat . meeee(); + let x = dont.reformat.meeee(); } }; } diff --git a/tests/target/match.rs b/tests/target/match.rs index 040fbf155a4..d47e94b6464 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -262,10 +262,12 @@ fn issue507() { fn issue508() { match s.type_id() { - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLCanvasElement))) => true, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), + Some( + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement)), + ) => true, + Some( + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement)), + ) => s.has_object_data(), Some(NodeTypeId::Element(_)) => false, } } diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs index acc41b73e18..9f630f6dada 100644 --- a/tests/target/pattern-condense-wildcards.rs +++ b/tests/target/pattern-condense-wildcards.rs @@ -7,10 +7,12 @@ fn main() { Tup(_) => "nah", Quad(_, _, x, _) => " also no rewrite", Quad(x, ..) => "condense me pls", - Weird(x, - _, - _, - // dont condense before - ..) => "pls work", + Weird( + x, + _, + _, + // dont condense before + .. + ) => "pls work", } } diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index f0cc1c16e14..39a8408a630 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -47,8 +47,9 @@ fn main() { impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { fn mutate_fragment(&mut self, fragment: &mut Fragment) { match **info { - GeneratedContentInfo::ContentItem(ContentItem::Counter(ref counter_name, - counter_style)) => {} + GeneratedContentInfo::ContentItem( + ContentItem::Counter(ref counter_name, counter_style), + ) => {} } } } -- cgit 1.4.1-3-g733a5 From 02f925100759256b87324ca07d7ff174330f60ad Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 23:26:32 +0900 Subject: Refactor rewrite for ConrtolFlow --- src/expr.rs | 240 +++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 156 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6bba83b520c..70e7e294aa3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -151,41 +151,17 @@ fn format_expr( shape, ) } - ast::ExprKind::While(ref cond, ref block, label) => { - ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape) - } - ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - ControlFlow::new_while(Some(pat), cond, block, label, expr.span).rewrite(context, shape) - } - ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, shape) - } - ast::ExprKind::Loop(ref block, label) => { - ControlFlow::new_loop(block, label, expr.span).rewrite(context, shape) + ast::ExprKind::If(..) | + ast::ExprKind::IfLet(..) | + ast::ExprKind::ForLoop(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) => { + to_control_flow(expr, expr_type).and_then(|control_flow| { + control_flow.rewrite(context, shape) + }) } ast::ExprKind::Block(ref block) => block.rewrite(context, shape), - ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { - ControlFlow::new_if( - cond, - None, - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - ).rewrite(context, shape) - } - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { - ControlFlow::new_if( - cond, - Some(pat), - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - ).rewrite(context, shape) - } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, shape, expr.span) } @@ -856,6 +832,32 @@ impl Rewrite for ast::Stmt { } } +// Rewrite condition if the given expression has one. +fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { + match expr.node { + ast::ExprKind::Match(ref cond, _) => { + // `match `cond` {` + let cond_shape = match context.config.control_style() { + Style::Legacy => try_opt!(shape.shrink_left(6).and_then(|s| s.sub_width(2))), + Style::Rfc => try_opt!(shape.offset_left(8)), + }; + cond.rewrite(context, cond_shape) + } + ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { + stmt_expr(&block.stmts[0]).and_then(|e| rewrite_cond(context, e, shape)) + } + _ => { + to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { + let alt_block_sep = String::from("\n") + + &shape.indent.block_only().to_string(context.config); + control_flow + .rewrite_cond(context, shape, &alt_block_sep) + .and_then(|rw| Some(rw.0)) + }) + } + } +} + // Abstraction over control flow expressions #[derive(Debug)] struct ControlFlow<'a> { @@ -873,6 +875,56 @@ struct ControlFlow<'a> { span: Span, } +fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option> { + match expr.node { + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { + Some(ControlFlow::new_if( + cond, + None, + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )) + } + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { + Some(ControlFlow::new_if( + cond, + Some(pat), + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )) + } + ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { + Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) + } + ast::ExprKind::Loop(ref block, label) => Some( + ControlFlow::new_loop(block, label, expr.span), + ), + ast::ExprKind::While(ref cond, ref block, label) => Some(ControlFlow::new_while( + None, + cond, + block, + label, + expr.span, + )), + ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { + Some(ControlFlow::new_while( + Some(pat), + cond, + block, + label, + expr.span, + )) + } + _ => None, + } +} + impl<'a> ControlFlow<'a> { fn new_if( cond: &'a ast::Expr, @@ -1021,9 +1073,13 @@ impl<'a> ControlFlow<'a> { } } -impl<'a> Rewrite for ControlFlow<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!("ControlFlow::rewrite {:?} {:?}", self, shape); +impl<'a> ControlFlow<'a> { + fn rewrite_cond( + &self, + context: &RewriteContext, + shape: Shape, + alt_block_sep: &str, + ) -> Option<(String, usize)> { let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() @@ -1067,38 +1123,13 @@ impl<'a> Rewrite for ControlFlow<'a> { if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); - if trial.is_some() && - trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width() - { - return trial; + if let Some(cond_str) = trial { + if cond_str.len() <= context.config.single_line_if_else_max_width() { + return Some((cond_str, 0)); + } } } - let used_width = if pat_expr_string.contains('\n') { - last_line_width(&pat_expr_string) - } else { - // 2 = spaces after keyword and condition. - label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 - }; - - let block_width = shape.width.checked_sub(used_width).unwrap_or(0); - // This is used only for the empty block case: `{}`. So, we use 1 if we know - // we should avoid the single line case. - let block_width = if self.else_block.is_some() || self.nested_if { - min(1, block_width) - } else { - block_width - }; - - let block_shape = Shape { - width: block_width, - ..shape - }; - let mut block_context = context.clone(); - block_context.is_if_else_block = self.else_block.is_some(); - - let block_str = try_opt!(self.block.rewrite(&block_context, block_shape)); - let cond_span = if let Some(cond) = self.cond { cond.span } else { @@ -1123,34 +1154,75 @@ impl<'a> Rewrite for ControlFlow<'a> { let after_cond_comment = extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); - let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine || force_newline_brace { - alt_block_sep.as_str() + alt_block_sep } else { " " }; - let mut result = - format!("{}{}{}{}{}{}", - label_string, - self.keyword, - between_kwd_cond_comment - .as_ref() - .map_or(if pat_expr_string.is_empty() || - pat_expr_string.starts_with('\n') { - "" - } else { - " " - }, - |s| &**s), - pat_expr_string, - after_cond_comment.as_ref().map_or(block_sep, |s| &**s), - block_str); + let used_width = if pat_expr_string.contains('\n') { + last_line_width(&pat_expr_string) + } else { + // 2 = spaces after keyword and condition. + label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 + }; + + Some(( + format!( + "{}{}{}{}{}", + label_string, + self.keyword, + between_kwd_cond_comment.as_ref().map_or( + if pat_expr_string.is_empty() || + pat_expr_string.starts_with('\n') + { + "" + } else { + " " + }, + |s| &**s, + ), + pat_expr_string, + after_cond_comment.as_ref().map_or(block_sep, |s| &**s) + ), + used_width, + )) + } +} + +impl<'a> Rewrite for ControlFlow<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("ControlFlow::rewrite {:?} {:?}", self, shape); + + let alt_block_sep = String::from("\n") + + &shape.indent.block_only().to_string(context.config); + let (cond_str, used_width) = try_opt!(self.rewrite_cond(context, shape, &alt_block_sep)); + // If `used_width` is 0, it indicates that whole control flow is written in a single line. + if used_width == 0 { + return Some(cond_str); + } + + let block_width = shape.width.checked_sub(used_width).unwrap_or(0); + // This is used only for the empty block case: `{}`. So, we use 1 if we know + // we should avoid the single line case. + let block_width = if self.else_block.is_some() || self.nested_if { + min(1, block_width) + } else { + block_width + }; + let block_shape = Shape { + width: block_width, + ..shape + }; + let mut block_context = context.clone(); + block_context.is_if_else_block = self.else_block.is_some(); + let block_str = try_opt!(self.block.rewrite(&block_context, block_shape)); + + let mut result = format!("{}{}", cond_str, block_str); if let Some(else_block) = self.else_block { let shape = Shape::indented(shape.indent, context.config); -- cgit 1.4.1-3-g733a5 From e22fd0ce594105aeb59594a4012cea2061719784 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 23:27:33 +0900 Subject: Refactor rewrite for closure --- src/expr.rs | 142 +++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 70e7e294aa3..de9ea598df7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -535,23 +535,15 @@ where Some(result) } -// This functions is pretty messy because of the rules around closures and blocks: -// FIXME - the below is probably no longer true in full. -// * if there is a return type, then there must be braces, -// * given a closure with braces, whether that is parsed to give an inner block -// or not depends on if there is a return type and if there are statements -// in that block, -// * if the first expression in the body ends with a block (i.e., is a -// statement without needing a semi-colon), then adding or removing braces -// can change whether it is treated as an expression or statement. -fn rewrite_closure( +// Return type is (prefix, extra_offset) +fn rewrite_closure_fn_decl( capture: ast::CaptureBy, fn_decl: &ast::FnDecl, body: &ast::Expr, span: Span, context: &RewriteContext, shape: Shape, -) -> Option { +) -> Option<(String, usize)> { let mover = if capture == ast::CaptureBy::Value { "move " } else { @@ -598,6 +590,7 @@ fn rewrite_closure( }; let list_str = try_opt!(write_list(&item_vec, &fmt)); let mut prefix = format!("{}|{}|", mover, list_str); + let extra_offset = extra_offset(&prefix, shape) + 1; if !ret_str.is_empty() { if prefix.contains('\n') { @@ -609,8 +602,35 @@ fn rewrite_closure( prefix.push_str(&ret_str); } + Some((prefix, extra_offset)) +} + +// This functions is pretty messy because of the rules around closures and blocks: +// FIXME - the below is probably no longer true in full. +// * if there is a return type, then there must be braces, +// * given a closure with braces, whether that is parsed to give an inner block +// or not depends on if there is a return type and if there are statements +// in that block, +// * if the first expression in the body ends with a block (i.e., is a +// statement without needing a semi-colon), then adding or removing braces +// can change whether it is treated as an expression or statement. +fn rewrite_closure( + capture: ast::CaptureBy, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let (prefix, extra_offset) = try_opt!(rewrite_closure_fn_decl( + capture, + fn_decl, + body, + span, + context, + shape, + )); // 1 = space between `|...|` and body. - let extra_offset = extra_offset(&prefix, shape) + 1; let body_shape = try_opt!(shape.offset_left(extra_offset)); if let ast::ExprKind::Block(ref block) = body.node { @@ -625,7 +645,12 @@ fn rewrite_closure( block_contains_comment(block, context.codemap) || prefix.contains('\n'); - if ret_str.is_empty() && !needs_block { + let no_return_type = if let ast::FunctionRetTy::Default(_) = fn_decl.output { + true + } else { + false + }; + if no_return_type && !needs_block { // lock.stmts.len() == 1 if let Some(ref expr) = stmt_expr(&block.stmts[0]) { if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, body_shape) { @@ -647,15 +672,22 @@ fn rewrite_closure( } // Either we require a block, or tried without and failed. - return rewrite_closure_block(&block, prefix, context, body_shape); - } - - if let Some(rw) = rewrite_closure_expr(body, &prefix, context, body_shape) { - return Some(rw); + rewrite_closure_block(&block, &prefix, context, body_shape) + } else { + rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { + // The closure originally had a non-block expression, but we can't fit on + // one line, so we'll insert a block. + rewrite_closure_with_block(context, body_shape, &prefix, body) + }) } +} - // The closure originally had a non-block expression, but we can't fit on - // one line, so we'll insert a block. +fn rewrite_closure_with_block( + context: &RewriteContext, + shape: Shape, + prefix: &str, + body: &ast::Expr, +) -> Option { let block = ast::Block { stmts: vec![ ast::Stmt { @@ -668,48 +700,48 @@ fn rewrite_closure( rules: ast::BlockCheckMode::Default, span: body.span, }; - return rewrite_closure_block(&block, prefix, context, body_shape); + rewrite_closure_block(&block, prefix, context, shape) +} - fn rewrite_closure_expr( - expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, - ) -> Option { - let mut rewrite = expr.rewrite(context, shape); - if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { - rewrite = and_one_line(rewrite); - } - rewrite.map(|rw| format!("{} {}", prefix, rw)) +fn rewrite_closure_expr( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut rewrite = expr.rewrite(context, shape); + if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { + rewrite = and_one_line(rewrite); } + rewrite.map(|rw| format!("{} {}", prefix, rw)) +} - fn rewrite_closure_block( - block: &ast::Block, - prefix: String, - context: &RewriteContext, - shape: Shape, - ) -> Option { - // Start with visual indent, then fall back to block indent if the - // closure is large. - let block_threshold = context.config.closure_block_indent_threshold(); - if block_threshold >= 0 { - if let Some(block_str) = block.rewrite(&context, shape) { - if block_str.matches('\n').count() <= block_threshold as usize && - !need_block_indent(&block_str, shape) - { - if let Some(block_str) = block_str.rewrite(context, shape) { - return Some(format!("{} {}", prefix, block_str)); - } +fn rewrite_closure_block( + block: &ast::Block, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + // Start with visual indent, then fall back to block indent if the + // closure is large. + let block_threshold = context.config.closure_block_indent_threshold(); + if block_threshold >= 0 { + if let Some(block_str) = block.rewrite(&context, shape) { + if block_str.matches('\n').count() <= block_threshold as usize && + !need_block_indent(&block_str, shape) + { + if let Some(block_str) = block_str.rewrite(context, shape) { + return Some(format!("{} {}", prefix, block_str)); } } } - - // The body of the closure is big enough to be block indented, that - // means we must re-format. - let block_shape = shape.block().with_max_width(context.config); - let block_str = try_opt!(block.rewrite(&context, block_shape)); - Some(format!("{} {}", prefix, block_str)) } + + // The body of the closure is big enough to be block indented, that + // means we must re-format. + let block_shape = shape.block().with_max_width(context.config); + let block_str = try_opt!(block.rewrite(&context, block_shape)); + Some(format!("{} {}", prefix, block_str)) } fn and_one_line(x: Option) -> Option { -- cgit 1.4.1-3-g733a5 From 2f17c31fa4c61172cb7cb3298509d973a58f6475 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 23:27:53 +0900 Subject: Wrap closure with a single control flow expr with multi line condition --- src/expr.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index de9ea598df7..61cd9ad0cfc 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2212,7 +2212,35 @@ fn rewrite_last_arg_with_overflow<'a, T>( where T: Rewrite + Spanned + ToExpr + 'a, { - let rewrite = last_arg.rewrite(context, shape); + let rewrite = if let Some(expr) = last_arg.to_expr() { + match expr.node { + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { + if rewrite_cond(context, body, shape).map_or(false, |cond| cond.contains('\n')) { + rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape) + .and_then(|(prefix, extra_offset)| { + // 1 = space between `|...|` and body. + shape.offset_left(extra_offset).and_then(|body_shape| { + let body = match body.node { + ast::ExprKind::Block(ref block) => { + stmt_expr(&block.stmts[0]).unwrap() + } + _ => body, + }; + rewrite_closure_with_block(context, body_shape, &prefix, body) + }) + }) + .or_else(|| expr.rewrite(context, shape)) + } else { + expr.rewrite(context, shape) + } + } + _ => expr.rewrite(context, shape), + } + } else { + last_arg.rewrite(context, shape) + }; let orig_last = last_item.item.clone(); if let Some(rewrite) = rewrite { -- cgit 1.4.1-3-g733a5 From 0d5768964b2571eb1d58f0766a2089729d5e770a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 15 Jun 2017 23:29:46 +0900 Subject: Format source codes and add a test --- src/expr.rs | 16 ++++++++-------- src/imports.rs | 6 +++--- tests/target/issue-1681.rs | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 tests/target/issue-1681.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 61cd9ad0cfc..22f963e0609 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -750,14 +750,14 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); - block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 && - (block_str[1..] - .find(|c: char| !c.is_whitespace()) - .unwrap() == block_str.len() - 2) - { - "{}".to_owned() - } else { - block_str.to_owned() + block_str.map(|block_str| { + if block_str.starts_with('{') && budget >= 2 && + (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + { + "{}".to_owned() + } else { + block_str.to_owned() + } }) } diff --git a/src/imports.rs b/src/imports.rs index 3b7c47f0fca..e3c06ae7956 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -159,9 +159,9 @@ impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => { - Some(String::new()) - } + ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => Some( + String::new(), + ), ast::ViewPath_::ViewPathList(ref path, ref path_list) => { rewrite_use_list(shape, path, path_list, self.span, context) } diff --git a/tests/target/issue-1681.rs b/tests/target/issue-1681.rs new file mode 100644 index 00000000000..a13f323e88f --- /dev/null +++ b/tests/target/issue-1681.rs @@ -0,0 +1,19 @@ +// rustfmt-max_width: 80 + +fn foo() { + // This is where it gets good + refmut_map_result(self.cache.borrow_mut(), |cache| { + match cache.entry(cache_key) { + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => { + let statement = { + let sql = try!(entry.key().sql(source)); + prepare_fn(&sql) + }; + + Ok(entry.insert(try!(statement))) + } + // and now, casually call a method on this + } + }).map(MaybeCached::Cached) +} -- cgit 1.4.1-3-g733a5 From e7240f5e24f083aebe3cb32964e943a618210b1e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 08:28:12 +0900 Subject: Add and remove comments --- src/expr.rs | 45 +++++++++++++++++++++++++++------------------ tests/target/issue-1681.rs | 5 +++-- 2 files changed, 30 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 22f963e0609..92c62b08125 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -590,6 +590,7 @@ fn rewrite_closure_fn_decl( }; let list_str = try_opt!(write_list(&item_vec, &fmt)); let mut prefix = format!("{}|{}|", mover, list_str); + // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, shape) + 1; if !ret_str.is_empty() { @@ -682,6 +683,7 @@ fn rewrite_closure( } } +// Rewrite closure with a single expression wrapping its body with block. fn rewrite_closure_with_block( context: &RewriteContext, shape: Shape, @@ -703,6 +705,7 @@ fn rewrite_closure_with_block( rewrite_closure_block(&block, prefix, context, shape) } +// Rewrite closure with a single expression without wrapping its body with block. fn rewrite_closure_expr( expr: &ast::Expr, prefix: &str, @@ -716,6 +719,7 @@ fn rewrite_closure_expr( rewrite.map(|rw| format!("{} {}", prefix, rw)) } +// Rewrite closure whose body is block. fn rewrite_closure_block( block: &ast::Block, prefix: &str, @@ -2217,24 +2221,29 @@ where // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { - if rewrite_cond(context, body, shape).map_or(false, |cond| cond.contains('\n')) { - rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape) - .and_then(|(prefix, extra_offset)| { - // 1 = space between `|...|` and body. - shape.offset_left(extra_offset).and_then(|body_shape| { - let body = match body.node { - ast::ExprKind::Block(ref block) => { - stmt_expr(&block.stmts[0]).unwrap() - } - _ => body, - }; - rewrite_closure_with_block(context, body_shape, &prefix, body) - }) - }) - .or_else(|| expr.rewrite(context, shape)) - } else { - expr.rewrite(context, shape) - } + let try_closure_with_block = || { + let body = match body.node { + ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { + try_opt!(stmt_expr(&block.stmts[0])) + } + _ => body, + }; + let (prefix, extra_offset) = try_opt!(rewrite_closure_fn_decl( + capture, + fn_decl, + body, + expr.span, + context, + shape, + )); + let shape = try_opt!(shape.offset_left(extra_offset)); + rewrite_cond(context, body, shape).map_or(None, |cond| if cond.contains('\n') { + rewrite_closure_with_block(context, shape, &prefix, body) + } else { + None + }) + }; + try_closure_with_block().or_else(|| expr.rewrite(context, shape)) } _ => expr.rewrite(context, shape), } diff --git a/tests/target/issue-1681.rs b/tests/target/issue-1681.rs index a13f323e88f..5734fd5502d 100644 --- a/tests/target/issue-1681.rs +++ b/tests/target/issue-1681.rs @@ -1,7 +1,9 @@ // rustfmt-max_width: 80 +// We would like to surround closure body with block when overflowing the last +// argument of function call if the last argument has condition and without +// block it may go multi lines. fn foo() { - // This is where it gets good refmut_map_result(self.cache.borrow_mut(), |cache| { match cache.entry(cache_key) { Occupied(entry) => Ok(entry.into_mut()), @@ -13,7 +15,6 @@ fn foo() { Ok(entry.insert(try!(statement))) } - // and now, casually call a method on this } }).map(MaybeCached::Cached) } -- cgit 1.4.1-3-g733a5 From d3d31a9f75c99fac12beb1341610d806f56c5d31 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 08:47:33 +0900 Subject: Allow overflowing the last item of chain only if it is multi-lined By multi-lined we mean if it has more than 3 lines. --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 890c39ebabb..7fcd1f3fb3e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -348,7 +348,7 @@ fn rewrite_last_child_with_overflow( ) -> bool { if let Some(shape) = shape.shrink_left(almost_total) { if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) { - if almost_total + first_line_width(rw) <= one_line_budget { + if almost_total + first_line_width(rw) <= one_line_budget && rw.lines().count() > 3 { ::std::mem::swap(last_child, rw); return true; } -- cgit 1.4.1-3-g733a5 From 208ff15954c76ee0a7908e20eecb35dac6a69f72 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 08:49:49 +0900 Subject: Format source codes --- src/chains.rs | 16 ++- src/comment.rs | 6 +- src/expr.rs | 74 ++++++------- src/file_lines.rs | 5 +- src/imports.rs | 14 +-- src/items.rs | 114 +++++++++++++-------- src/lists.rs | 13 +-- src/missed_spans.rs | 12 +-- src/patterns.rs | 8 +- src/string.rs | 10 +- src/types.rs | 11 +- src/utils.rs | 12 +-- src/visitor.rs | 23 +++-- tests/system.rs | 12 +-- .../configs-chain_split_single_child-true.rs | 5 +- tests/target/expr.rs | 6 +- tests/target/match.rs | 5 +- 17 files changed, 187 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 7fcd1f3fb3e..25c1c353915 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -167,9 +167,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let child_shape_iter = Some(first_child_shape).into_iter().chain( ::std::iter::repeat( other_child_shape, - ).take( - subexpr_list.len() - 1, - ), + ).take(subexpr_list.len() - 1), ); let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = try_opt!( @@ -180,9 +178,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Total of all items excluding the last. let last_non_try_index = rewrites.len() - (1 + trailing_try_num); - let almost_total = rewrites[..last_non_try_index].iter().fold(0, |a, b| { - a + first_line_width(b) - }) + parent_rewrite.len(); + let almost_total = rewrites[..last_non_try_index] + .iter() + .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); @@ -320,9 +318,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { context.config.chain_indent() == IndentStyle::Block && parent_str.lines().last().map_or(false, |s| { - s.trim().chars().all(|c| { - c == ')' || c == ']' || c == '}' || c == '?' - }) + s.trim() + .chars() + .all(|c| c == ')' || c == ']' || c == '}' || c == '?') }) } diff --git a/src/comment.rs b/src/comment.rs index e9f84b71e48..d8189df363c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -45,9 +45,9 @@ pub enum CommentStyle<'a> { fn custom_opener(s: &str) -> &str { s.lines().next().map_or("", |first_line| { - first_line.find(' ').map_or(first_line, |space_index| { - &first_line[0..space_index + 1] - }) + first_line + .find(' ') + .map_or(first_line, |space_index| &first_line[0..space_index + 1]) }) } diff --git a/src/expr.rs b/src/expr.rs index 6bba83b520c..080fdca0f04 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -384,9 +384,8 @@ where // This is needed in case of line break not caused by a // shortage of space, but by end-of-line comments, for example. if !rhs_result.contains('\n') { - let lhs_shape = try_opt!(try_opt!(shape.offset_left(prefix.len())).sub_width( - infix.len(), - )); + let lhs_shape = + try_opt!(try_opt!(shape.offset_left(prefix.len())).sub_width(infix.len())); let lhs_result = lhs.rewrite(context, lhs_shape); if let Some(lhs_result) = lhs_result { let mut result = format!("{}{}{}", prefix, lhs_result, infix); @@ -475,9 +474,11 @@ where let nested_shape = match context.config.array_layout() { IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), IndentStyle::Visual => { - try_opt!(shape.visual_indent(bracket_size).sub_width( - bracket_size * 2, - )) + try_opt!( + shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2) + ) } }; @@ -500,9 +501,9 @@ where } } - let has_long_item = items.iter().any(|li| { - li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false) - }); + let has_long_item = items + .iter() + .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); let tactic = match context.config.array_layout() { IndentStyle::Block => { @@ -1591,9 +1592,10 @@ impl Rewrite for ast::Arm { body.rewrite(context, body_shape), body_shape.width, )); - let indent_str = shape.indent.block_indent(context.config).to_string( - context.config, - ); + let indent_str = shape + .indent + .block_indent(context.config) + .to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms() { if context.config.match_block_trailing_comma() { ("{", "},") @@ -1655,13 +1657,13 @@ fn rewrite_guard( if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` - if let Some(cond_shape) = shape.shrink_left(pattern_width + 4).and_then( - |s| s.sub_width(5), - ) + if let Some(cond_shape) = shape + .shrink_left(pattern_width + 4) + .and_then(|s| s.sub_width(5)) { - if let Some(cond_str) = guard.rewrite(context, cond_shape).and_then(|s| { - s.rewrite(context, cond_shape) - }) + if let Some(cond_str) = guard + .rewrite(context, cond_shape) + .and_then(|s| s.rewrite(context, cond_shape)) { if !cond_str.contains('\n') { return Some(format!(" if {}", cond_str)); @@ -1679,9 +1681,10 @@ fn rewrite_guard( if let Some(cond_str) = guard.rewrite(context, cond_shape) { return Some(format!( "\n{}if {}", - shape.indent.block_indent(context.config).to_string( - context.config, - ), + shape + .indent + .block_indent(context.config) + .to_string(context.config), cond_str )); } @@ -1713,9 +1716,8 @@ fn rewrite_pat_expr( } else { format!("{} ", matcher) }; - let pat_shape = try_opt!(try_opt!(shape.offset_left(matcher.len())).sub_width( - connector.len(), - )); + let pat_shape = + try_opt!(try_opt!(shape.offset_left(matcher.len())).sub_width(connector.len())); pat_string = try_opt!(pat.rewrite(context, pat_shape)); format!("{}{}{}", matcher, pat_string, connector) } @@ -1828,9 +1830,9 @@ where width: callee_max_width, ..shape }; - let callee_str = callee.rewrite(context, callee_shape).ok_or( - Ordering::Greater, - )?; + let callee_str = callee + .rewrite(context, callee_shape) + .ok_or(Ordering::Greater)?; rewrite_call_inner( context, @@ -1938,9 +1940,9 @@ where ); } - let args_shape = shape.sub_width(last_line_width(&callee_str)).ok_or( - Ordering::Less, - )?; + let args_shape = shape + .sub_width(last_line_width(&callee_str)) + .ok_or(Ordering::Less)?; Ok(format!( "{}{}", callee_str, @@ -1956,9 +1958,8 @@ where fn need_block_indent(s: &str, shape: Shape) -> bool { s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)).map_or(false, |w| { - w + 1 < shape.indent.width() - }) + s.find(|c| !char::is_whitespace(c)) + .map_or(false, |w| w + 1 < shape.indent.width()) }) } @@ -2293,9 +2294,10 @@ fn rewrite_struct_lit<'a>( return Some(format!("{} {{}}", path_str)); } - let field_iter = fields.into_iter().map(StructLitField::Regular).chain( - base.into_iter().map(StructLitField::Base), - ); + let field_iter = fields + .into_iter() + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); diff --git a/src/file_lines.rs b/src/file_lines.rs index 8a0ed4b5d7a..81755eae805 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -213,9 +213,8 @@ struct JsonSpan { impl JsonSpan { fn into_tuple(self) -> Result<(String, Range), String> { let (lo, hi) = self.range; - let canonical = canonicalize_path_string(&self.file).ok_or_else(|| { - format!("Can't canonicalize {}", &self.file) - })?; + let canonical = canonicalize_path_string(&self.file) + .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; Ok((canonical, Range::new(lo, hi))) } } diff --git a/src/imports.rs b/src/imports.rs index 3b7c47f0fca..6a0f74f1e6a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -196,9 +196,11 @@ impl<'a> FmtVisitor<'a> { .map(|p_i| { cmp::max( self.last_pos, - p_i.attrs.iter().map(|attr| attr.span.lo).min().unwrap_or( - p_i.span.lo, - ), + p_i.attrs + .iter() + .map(|attr| attr.span.lo) + .min() + .unwrap_or(p_i.span.lo), ) }) .unwrap_or(self.last_pos); @@ -399,9 +401,9 @@ pub fn rewrite_use_list( // Returns true when self item was found. fn move_self_to_front(items: &mut Vec) -> bool { - match items.iter().position(|item| { - item.item.as_ref().map(|x| &x[..]) == Some("self") - }) { + match items + .iter() + .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) { Some(pos) => { items[0] = items.remove(pos); true diff --git a/src/items.rs b/src/items.rs index 7a2d3048ff0..1eb85771fd6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -149,9 +149,8 @@ impl<'a> FmtVisitor<'a> { self.format_missing_no_indent(item.span.hi - BytePos(1)); self.block_indent = self.block_indent.block_unindent(self.config); - self.buffer.push_str( - &self.block_indent.to_string(self.config), - ); + self.buffer + .push_str(&self.block_indent.to_string(self.config)); } else { for item in &item.body { self.format_body_element(item); @@ -424,9 +423,8 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_unindent(self.config); if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - self.buffer.push_str( - &self.block_indent.to_string(self.config), - ); + self.buffer + .push_str(&self.block_indent.to_string(self.config)); } self.buffer.push_str("}"); self.last_pos = span.hi; @@ -955,9 +953,12 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) Density::Tall }; - let where_budget = try_opt!(context.config.max_width().checked_sub( - last_line_width(&result), - )); + let where_budget = try_opt!( + context + .config + .max_width() + .checked_sub(last_line_width(&result)) + ); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1100,9 +1101,12 @@ fn format_struct_struct( let item_indent = offset.block_indent(context.config); // 1 = "," - let item_budget = try_opt!(context.config.max_width().checked_sub( - item_indent.width() + 1, - )); + let item_budget = try_opt!( + context + .config + .max_width() + .checked_sub(item_indent.width() + 1) + ); let items = itemize_list( context.codemap, @@ -1144,9 +1148,9 @@ fn format_struct_struct( Some(format!( "{}\n{}{}\n{}}}", result, - offset.block_indent(context.config).to_string( - context.config, - ), + offset + .block_indent(context.config) + .to_string(context.config), items_str, offset.to_string(context.config) )) @@ -1181,9 +1185,12 @@ fn format_tuple_struct( let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = try_opt!(context.config.max_width().checked_sub( - last_line_width(&result), - )); + let where_budget = try_opt!( + context + .config + .max_width() + .checked_sub(last_line_width(&result)) + ); try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1229,9 +1236,12 @@ fn format_tuple_struct( } }; // 3 = `();` - let item_budget = try_opt!(context.config.max_width().checked_sub( - item_indent.width() + 3, - )); + let item_budget = try_opt!( + context + .config + .max_width() + .checked_sub(item_indent.width() + 3) + ); let items = itemize_list( context.codemap, @@ -1321,9 +1331,12 @@ pub fn rewrite_type_alias( let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = try_opt!(context.config.max_width().checked_sub( - last_line_width(&result), - )); + let where_budget = try_opt!( + context + .config + .max_width() + .checked_sub(last_line_width(&result)) + ); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1358,9 +1371,12 @@ pub fn rewrite_type_alias( let type_indent = indent.block_indent(context.config); result.push('\n'); result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!(context.config.max_width().checked_sub( - type_indent.width() + ";".len(), - )); + let budget = try_opt!( + context + .config + .max_width() + .checked_sub(type_indent.width() + ";".len()) + ); ty.rewrite(context, Shape::legacy(budget, type_indent)) }) ); @@ -1963,9 +1979,10 @@ fn rewrite_fn_base( } // If the last line of args contains comment, we cannot put the closing paren // on the same line. - if arg_str.lines().last().map_or(false, |last_line| { - last_line.contains("//") - }) + if arg_str + .lines() + .last() + .map_or(false, |last_line| last_line.contains("//")) { args_last_line_contains_comment = true; result.push('\n'); @@ -2038,12 +2055,13 @@ fn rewrite_fn_base( let snippet_hi = span.hi; let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); // Try to preserve the layout of the original snippet. - let original_starts_with_newline = snippet.find(|c| c != ' ').map_or(false, |i| { - snippet[i..].starts_with('\n') - }); - let original_ends_with_newline = snippet.rfind(|c| c != ' ').map_or(false, |i| { - snippet[i..].ends_with('\n') - }); + let original_starts_with_newline = + snippet + .find(|c| c != ' ') + .map_or(false, |i| snippet[i..].starts_with('\n')); + let original_ends_with_newline = snippet + .rfind(|c| c != ' ') + .map_or(false, |i| snippet[i..].ends_with('\n')); let snippet = snippet.trim(); if !snippet.is_empty() { result.push(if original_starts_with_newline { @@ -2070,9 +2088,12 @@ fn rewrite_fn_base( } || (put_args_in_block && ret_str.is_empty()); if where_clause.predicates.len() == 1 && should_compress_where { - let budget = try_opt!(context.config.max_width().checked_sub( - last_line_width(&result), - )); + let budget = try_opt!( + context + .config + .max_width() + .checked_sub(last_line_width(&result)) + ); if let Some(where_clause_str) = rewrite_where_clause( context, @@ -2463,9 +2484,9 @@ pub fn wrap_generics_with_angle_brackets( "<\n{}{}\n{}>", list_offset.to_string(context.config), list_str, - list_offset.block_unindent(context.config).to_string( - context.config, - ) + list_offset + .block_unindent(context.config) + .to_string(context.config) ) } else if context.config.spaces_within_angle_brackets() { format!("< {} >", list_str) @@ -2672,9 +2693,12 @@ fn format_generics( let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = try_opt!(context.config.max_width().checked_sub( - last_line_width(&result), - )); + let budget = try_opt!( + context + .config + .max_width() + .checked_sub(last_line_width(&result)) + ); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, diff --git a/src/lists.rs b/src/lists.rs index 24bd10e24a0..c770d1bf953 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -132,9 +132,9 @@ impl ListItem { } pub fn has_line_pre_comment(&self) -> bool { - self.pre_comment.as_ref().map_or(false, |comment| { - comment.starts_with("//") - }) + self.pre_comment + .as_ref() + .map_or(false, |comment| comment.starts_with("//")) } pub fn from_str>(s: S) -> ListItem { @@ -160,9 +160,10 @@ where I: IntoIterator + Clone, T: AsRef, { - let pre_line_comments = items.clone().into_iter().any(|item| { - item.as_ref().has_line_pre_comment() - }); + let pre_line_comments = items + .clone() + .into_iter() + .any(|item| item.as_ref().has_line_pre_comment()); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 17b75a34427..45e4dc19dae 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -160,9 +160,8 @@ impl<'a> FmtVisitor<'a> { if let Some('{') = last_char { self.buffer.push_str("\n"); } - self.buffer.push_str( - &self.block_indent.to_string(self.config), - ); + self.buffer + .push_str(&self.block_indent.to_string(self.config)); } else { self.buffer.push_str(" "); } @@ -184,9 +183,10 @@ impl<'a> FmtVisitor<'a> { if let Some('/') = subslice.chars().skip(1).next() { // check that there are no contained block comments - if !subslice.split('\n').map(|s| s.trim_left()).any(|s| { - s.len() >= 2 && &s[0..2] == "/*" - }) + if !subslice + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() >= 2 && &s[0..2] == "/*") { // Add a newline after line comments self.buffer.push_str("\n"); diff --git a/src/patterns.rs b/src/patterns.rs index 3ca8aa52455..1899944bc10 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -38,9 +38,11 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!(shape.width.checked_sub( - prefix.len() + mut_infix.len() + id_str.len() + 3, - )); + let width = try_opt!( + shape + .width + .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3) + ); format!( " @ {}", try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent))) diff --git a/src/string.rs b/src/string.rs index 5ba273ad272..3efb406e796 100644 --- a/src/string.rs +++ b/src/string.rs @@ -42,10 +42,12 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; - let mut result = - String::with_capacity(stripped_str.len().checked_next_power_of_two().unwrap_or( - usize::max_value(), - )); + let mut result = String::with_capacity( + stripped_str + .len() + .checked_next_power_of_two() + .unwrap_or(usize::max_value()), + ); result.push_str(fmt.opener); let ender_length = fmt.line_end.len(); diff --git a/src/types.rs b/src/types.rs index 57a7b301f54..3cdf9096094 100644 --- a/src/types.rs +++ b/src/types.rs @@ -311,9 +311,9 @@ where context.codemap, // FIXME Would be nice to avoid this allocation, // but I couldn't get the types to work out. - inputs.map(|i| ArgumentKind::Regular(Box::new(i))).chain( - variadic_arg, - ), + inputs + .map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), ")", |arg| match *arg { ArgumentKind::Regular(ref ty) => ty.span().lo, @@ -718,9 +718,8 @@ impl Rewrite for ast::Ty { ast::TyKind::Mac(..) => None, ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(ref it) => { - it.rewrite(context, shape).map(|it_str| { - format!("impl {}", it_str) - }) + it.rewrite(context, shape) + .map(|it_str| format!("impl {}", it_str)) } ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), diff --git a/src/utils.rs b/src/utils.rs index c432df301df..dd18572575b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -44,9 +44,9 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { let Path { ref segments, .. } = **path; let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); if path.is_global() { - segments_iter.next().expect( - "Non-global path in pub(restricted)?", - ); + segments_iter + .next() + .expect("Non-global path in pub(restricted)?"); } let is_keyword = |s: &str| s == "self" || s == "super"; let path = segments_iter.collect::>().join("::"); @@ -129,9 +129,9 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { #[inline] pub fn contains_skip(attrs: &[Attribute]) -> bool { - attrs.iter().any( - |a| a.meta().map_or(false, |a| is_skip(&a)), - ) + attrs + .iter() + .any(|a| a.meta().map_or(false, |a| is_skip(&a))) } // Find the end of a TyParam diff --git a/src/visitor.rs b/src/visitor.rs index 9ed40cc29ee..f0aeb6bfa3f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -69,11 +69,9 @@ impl<'a> FmtVisitor<'a> { ); // FIXME(#434): Move this check to somewhere more central, eg Rewrite. - if !self.config.file_lines().intersects( - &self.codemap.lookup_line_range( - stmt.span, - ), - ) + if !self.config + .file_lines() + .intersects(&self.codemap.lookup_line_range(stmt.span)) { return; } @@ -292,9 +290,10 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo); let snippet = self.get_context().snippet(item.span); - let where_span_end = snippet.find_uncommented("{").map(|x| { - (BytePos(x as u32)) + source!(self, item.span).lo - }); + let where_span_end = + snippet + .find_uncommented("{") + .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); if let Some(impl_str) = format_impl( &self.get_context(), item, @@ -727,9 +726,11 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::List(ref list) => { let name = self.name.as_str(); // 3 = `#[` and `(`, 2 = `]` and `)` - let item_shape = try_opt!(shape.shrink_left(name.len() + 3).and_then( - |s| s.sub_width(2), - )); + let item_shape = try_opt!( + shape + .shrink_left(name.len() + 3) + .and_then(|s| s.sub_width(2)) + ); let hi = self.span.hi + BytePos(count_missing_closing_parens(&context.snippet(self.span))); let items = itemize_list( diff --git a/tests/system.rs b/tests/system.rs index a6b7536111f..26b1edaff5b 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -84,9 +84,9 @@ fn assert_output(source: &str, expected_filename: &str) { let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); let mut expected_text = String::new(); - expected_file.read_to_string(&mut expected_text).expect( - "Failed reading target", - ); + expected_file + .read_to_string(&mut expected_text) + .expect("Failed reading target"); let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); if compare.len() > 0 { @@ -285,9 +285,9 @@ fn get_config(config_file: Option<&str>) -> Config { let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); let mut def_config = String::new(); - def_config_file.read_to_string(&mut def_config).expect( - "Couldn't read config", - ); + def_config_file + .read_to_string(&mut def_config) + .expect("Couldn't read config"); Config::from_toml(&def_config).expect("Invalid toml") } diff --git a/tests/target/configs-chain_split_single_child-true.rs b/tests/target/configs-chain_split_single_child-true.rs index c417e28d99c..154fa0bfa2e 100644 --- a/tests/target/configs-chain_split_single_child-true.rs +++ b/tests/target/configs-chain_split_single_child-true.rs @@ -1,7 +1,6 @@ // rustfmt-chain_split_single_child: true fn main() { - let files = fs::read_dir("tests/source").expect( - "Couldn't read source dir", - ); + let files = fs::read_dir("tests/source") + .expect("Couldn't read source dir"); } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 7741939df45..55d023cb55d 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -353,8 +353,8 @@ fn issue1106() { {} } - for entry in WalkDir::new(path).into_iter().filter_entry(|entry| { - exclusions.filter_entry(entry) - }) + for entry in WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) {} } diff --git a/tests/target/match.rs b/tests/target/match.rs index d47e94b6464..bd51ac6f962 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -389,9 +389,8 @@ fn issue1395() { fn issue1456() { Ok(Recording { - artists: match reader.evaluate( - ".//mb:recording/mb:artist-credit/mb:name-credit", - )? { + artists: match reader + .evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { Nodeset(nodeset) => { let res: Result, ReadError> = nodeset .iter() -- cgit 1.4.1-3-g733a5 From 85ecaf99df29b33405783acd0a85653ae4094ddb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 16 Jun 2017 16:49:54 +1200 Subject: Config knows if an option was default or set --- src/config.rs | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 931b99bb5da..153fad178cc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -220,8 +220,9 @@ macro_rules! create_config { #[derive(Clone)] pub struct Config { // For each config item, we store a bool indicating whether it has - // been accessed and the value. - $($i: (Cell, $ty)),+ + // been accessed and the value, and a bool whether the option was + // manually initialised, or taken from the default, + $($i: (Cell, bool, $ty)),+ } // Just like the Config struct but with each property wrapped @@ -255,7 +256,19 @@ macro_rules! create_config { impl<'a> ConfigSetter<'a> { $( pub fn $i(&mut self, value: $ty) { - (self.0).$i.1 = value; + (self.0).$i.2 = value; + } + )+ + } + + // Query each option, returns true if the user set the option, false if + // a default was used. + pub struct ConfigWasSet<'a>(&'a Config); + + impl<'a> ConfigWasSet<'a> { + $( + pub fn $i(&self) -> bool { + (self.0).$i.1 } )+ } @@ -265,7 +278,7 @@ macro_rules! create_config { $( pub fn $i(&self) -> $ty { self.$i.0.set(true); - self.$i.1.clone() + self.$i.2.clone() } )+ @@ -273,10 +286,15 @@ macro_rules! create_config { ConfigSetter(self) } + pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { + ConfigWasSet(self) + } + fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { - self.$i.1 = val; + self.$i.1 = true; + self.$i.2 = val; } )+ self @@ -320,7 +338,7 @@ macro_rules! create_config { PartialConfig { $( $i: if self.$i.0.get() { - Some(self.$i.1.clone()) + Some(self.$i.2.clone()) } else { None }, @@ -331,7 +349,7 @@ macro_rules! create_config { pub fn all_options(&self) -> PartialConfig { PartialConfig { $( - $i: Some(self.$i.1.clone()), + $i: Some(self.$i.2.clone()), )+ } } @@ -341,7 +359,7 @@ macro_rules! create_config { match key { $( stringify!($i) => { - self.$i.1 = val.parse::<$ty>() + self.$i.2 = val.parse::<$ty>() .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", stringify!($i), val, @@ -444,7 +462,7 @@ macro_rules! create_config { fn default() -> Config { Config { $( - $i: (Cell::new(false), $def), + $i: (Cell::new(false), false, $def), )+ } } @@ -610,4 +628,12 @@ mod test { format!("verbose = {}\nskip_children = {}\n", verbose, skip_children) ); } + + #[test] + fn test_was_set() { + let config = Config::from_toml("hard_tabs = true").unwrap(); + + assert_eq!(config.was_set().hard_tabs(), true); + assert_eq!(config.was_set().verbose(), false); + } } -- cgit 1.4.1-3-g733a5 From 4a5871eccc5994366b76627c8f240167e7b12cd6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 13:57:37 +0900 Subject: Use correct indentaion for vec! with semicolon --- src/expr.rs | 5 ++--- src/macros.rs | 12 ++++++------ tests/source/issue-1693.rs | 3 +++ tests/target/issue-1693.rs | 10 ++++++++++ 4 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 tests/source/issue-1693.rs create mode 100644 tests/target/issue-1693.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 892e6ef905e..1b17ced8a42 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -157,9 +157,8 @@ fn format_expr( ast::ExprKind::Loop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => { - to_control_flow(expr, expr_type).and_then(|control_flow| { - control_flow.rewrite(context, shape) - }) + to_control_flow(expr, expr_type) + .and_then(|control_flow| control_flow.rewrite(context, shape)) } ast::ExprKind::Block(ref block) => block.rewrite(context, shape), ast::ExprKind::Match(ref cond, ref arms) => { diff --git a/src/macros.rs b/src/macros.rs index cfc14b53adb..88bfb96c5d6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -184,7 +184,7 @@ pub fn rewrite_macro( ) } MacroStyle::Brackets => { - let mac_shape = try_opt!(shape.shrink_left(macro_name.len())); + let mac_shape = try_opt!(shape.offset_left(macro_name.len())); // Handle special case: `vec![expr; expr]` if vec_with_semi { let (lbr, rbr) = if context.config.spaces_within_square_brackets() { @@ -194,21 +194,21 @@ pub fn rewrite_macro( }; // 6 = `vec!` + `; ` let total_overhead = lbr.len() + rbr.len() + 6; - let lhs = try_opt!(expr_vec[0].rewrite(context, mac_shape)); - let rhs = try_opt!(expr_vec[1].rewrite(context, mac_shape)); + let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); + let lhs = try_opt!(expr_vec[0].rewrite(context, nested_shape)); + let rhs = try_opt!(expr_vec[1].rewrite(context, nested_shape)); if !lhs.contains('\n') && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) } else { - let nested_indent = shape.indent.block_indent(context.config); Some(format!( "{}{}\n{}{};\n{}{}\n{}{}", macro_name, lbr, - nested_indent.to_string(context.config), + nested_shape.indent.to_string(context.config), lhs, - nested_indent.to_string(context.config), + nested_shape.indent.to_string(context.config), rhs, shape.indent.to_string(context.config), rbr diff --git a/tests/source/issue-1693.rs b/tests/source/issue-1693.rs new file mode 100644 index 00000000000..0622ce50235 --- /dev/null +++ b/tests/source/issue-1693.rs @@ -0,0 +1,3 @@ +fn issue1693() { + let pixel_data = vec![(f16::from_f32(0.82), f16::from_f32(1.78), f16::from_f32(0.21)); 256 * 256]; +} diff --git a/tests/target/issue-1693.rs b/tests/target/issue-1693.rs new file mode 100644 index 00000000000..85421a123bb --- /dev/null +++ b/tests/target/issue-1693.rs @@ -0,0 +1,10 @@ +fn issue1693() { + let pixel_data = vec![ + ( + f16::from_f32(0.82), + f16::from_f32(1.78), + f16::from_f32(0.21) + ); + 256 * 256 + ]; +} -- cgit 1.4.1-3-g733a5 From f60a810730aa684f1354d852719b1a3edd0cd2fe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 05:44:54 +0900 Subject: Preserve comments inside attributes --- src/expr.rs | 5 ++--- src/visitor.rs | 11 ++++++++--- tests/target/issue-1703.rs | 9 +++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tests/target/issue-1703.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 892e6ef905e..1b17ced8a42 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -157,9 +157,8 @@ fn format_expr( ast::ExprKind::Loop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => { - to_control_flow(expr, expr_type).and_then(|control_flow| { - control_flow.rewrite(context, shape) - }) + to_control_flow(expr, expr_type) + .and_then(|control_flow| control_flow.rewrite(context, shape)) } ast::ExprKind::Block(ref block) => block.rewrite(context, shape), ast::ExprKind::Match(ref cond, ref arms) => { diff --git a/src/visitor.rs b/src/visitor.rs index f0aeb6bfa3f..17f48933499 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -19,7 +19,7 @@ use strings::string_buffer::StringBuffer; use {Indent, Shape}; use utils::{self, mk_sp}; use codemap::{LineRangeUtils, SpanUtils}; -use comment::FindUncommented; +use comment::{contains_comment, FindUncommented}; use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; @@ -761,7 +761,7 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::NameValue(ref literal) => { let name = self.name.as_str(); let value = context.snippet(literal.span); - if &*name == "doc" && value.starts_with("///") { + if &*name == "doc" && contains_comment(&value) { let doc_shape = Shape { width: cmp::min(shape.width, context.config.comment_width()) .checked_sub(shape.indent.width()) @@ -786,7 +786,12 @@ impl Rewrite for ast::Attribute { if rw.starts_with("///") { rw } else { - format!("#[{}]", rw) + let original = context.snippet(self.span); + if contains_comment(&original) { + original + } else { + format!("#[{}]", rw) + } } }) } diff --git a/tests/target/issue-1703.rs b/tests/target/issue-1703.rs new file mode 100644 index 00000000000..4079ef4cfca --- /dev/null +++ b/tests/target/issue-1703.rs @@ -0,0 +1,9 @@ +// rustfmt should not remove doc comments or comments inside attributes. + +/** +This function has a block doc comment. + */ +fn test_function() {} + +#[foo /* do not remove this! */] +fn foo() {} -- cgit 1.4.1-3-g733a5 From af57d285aa17270b42108d9f59fa6f792b2b8577 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 18:52:46 +0900 Subject: Use correct budget for function call args --- src/expr.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1b17ced8a42..aaf54faf4e2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2558,7 +2558,12 @@ fn shape_from_fn_call_style( offset: usize, ) -> Option { if context.use_block_indent() { - Some(shape.block().block_indent(context.config.tab_spaces())) + // 1 = "," + shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1) } else { shape.visual_indent(offset).sub_width(overhead) } -- cgit 1.4.1-3-g733a5 From ee0e9aeaae127513e89885c1aa7361d2e250a093 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 18:53:21 +0900 Subject: Use special rules when overflowing the last argument When overflowing the last argument of function call, if it is a closure, we apply some special rules in order to avoid weird formatting. --- src/expr.rs | 68 ++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index aaf54faf4e2..092f64fbb3e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2207,6 +2207,48 @@ fn last_arg_shape( }) } +// Rewriting closure which is placed at the end of the function call's arg. +// Returns `None` if the reformatted closure 'looks bad'. +fn rewrite_last_closure( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, +) -> Option { + if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node { + let body = match body.node { + ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { + stmt_expr(&block.stmts[0]).unwrap_or(body) + } + _ => body, + }; + let (prefix, extra_offset) = try_opt!(rewrite_closure_fn_decl( + capture, + fn_decl, + body, + expr.span, + context, + shape, + )); + // If the closure goes multi line before its body, do not overflow the closure. + if prefix.contains('\n') { + return None; + } + let body_shape = try_opt!(shape.offset_left(extra_offset)); + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + if rewrite_cond(context, body, body_shape) + .map(|cond| cond.contains('\n')) + .unwrap_or(false) + { + return rewrite_closure_with_block(context, body_shape, &prefix, body); + } + + // Seems fine, just format the closure in usual manner. + return expr.rewrite(context, shape); + } + None +} + fn rewrite_last_arg_with_overflow<'a, T>( context: &RewriteContext, last_arg: &T, @@ -2220,31 +2262,7 @@ where match expr.node { // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. - ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { - let try_closure_with_block = || { - let body = match body.node { - ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { - try_opt!(stmt_expr(&block.stmts[0])) - } - _ => body, - }; - let (prefix, extra_offset) = try_opt!(rewrite_closure_fn_decl( - capture, - fn_decl, - body, - expr.span, - context, - shape, - )); - let shape = try_opt!(shape.offset_left(extra_offset)); - rewrite_cond(context, body, shape).map_or(None, |cond| if cond.contains('\n') { - rewrite_closure_with_block(context, shape, &prefix, body) - } else { - None - }) - }; - try_closure_with_block().or_else(|| expr.rewrite(context, shape)) - } + ast::ExprKind::Closure(..) => rewrite_last_closure(context, expr, shape), _ => expr.rewrite(context, shape), } } else { -- cgit 1.4.1-3-g733a5 From b048fe6b356934e7e3990037738b3dfe322cce0d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Jun 2017 18:56:32 +0900 Subject: Format source codes --- src/chains.rs | 11 +++++---- src/comment.rs | 7 +++--- src/expr.rs | 70 ++++++++++++++++++++++++---------------------------------- src/items.rs | 52 +++++++++++++++++++++---------------------- src/lists.rs | 21 +++++++++--------- src/types.rs | 10 ++------- src/visitor.rs | 6 ++--- 7 files changed, 78 insertions(+), 99 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 25c1c353915..5a4a404bfdb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -165,9 +165,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ); let child_shape_iter = Some(first_child_shape).into_iter().chain( - ::std::iter::repeat( - other_child_shape, - ).take(subexpr_list.len() - 1), + ::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1), ); let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = try_opt!( @@ -178,9 +176,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Total of all items excluding the last. let last_non_try_index = rewrites.len() - (1 + trailing_try_num); - let almost_total = rewrites[..last_non_try_index] - .iter() - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); + let almost_total = rewrites[..last_non_try_index].iter().fold( + 0, + |a, b| a + first_line_width(b), + ) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); diff --git a/src/comment.rs b/src/comment.rs index d8189df363c..ce4b45009a2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -45,9 +45,10 @@ pub enum CommentStyle<'a> { fn custom_opener(s: &str) -> &str { s.lines().next().map_or("", |first_line| { - first_line - .find(' ') - .map_or(first_line, |space_index| &first_line[0..space_index + 1]) + first_line.find(' ').map_or( + first_line, + |space_index| &first_line[0..space_index + 1], + ) }) } diff --git a/src/expr.rs b/src/expr.rs index 092f64fbb3e..6b4669a70e7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -298,9 +298,7 @@ fn format_expr( Some(format!( "{}{}", "do catch ", - try_opt!( - block.rewrite(&context, Shape::legacy(budget, shape.indent)) - ) + try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))) )) } }; @@ -941,13 +939,9 @@ fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option Some( ControlFlow::new_loop(block, label, expr.span), ), - ast::ExprKind::While(ref cond, ref block, label) => Some(ControlFlow::new_while( - None, - cond, - block, - label, - expr.span, - )), + ast::ExprKind::While(ref cond, ref block, label) => Some( + ControlFlow::new_while(None, cond, block, label, expr.span), + ), ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { Some(ControlFlow::new_while( Some(pat), @@ -1302,14 +1296,13 @@ impl<'a> Rewrite for ControlFlow<'a> { } }; - let between_kwd_else_block = - mk_sp( - self.block.span.hi, - context.codemap.span_before( - mk_sp(self.block.span.hi, else_block.span.lo), - "else", - ), - ); + let between_kwd_else_block = mk_sp( + self.block.span.hi, + context.codemap.span_before( + mk_sp(self.block.span.hi, else_block.span.lo), + "else", + ), + ); let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); @@ -1434,10 +1427,9 @@ fn rewrite_match_arm_comment( result.push_str(&missed_str[..first_brk]); let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it - let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or( - missed_str - .len(), - ); + let first = missed_str + .find(|c: char| !c.is_whitespace()) + .unwrap_or(missed_str.len()); if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { // Excessive vertical whitespace before comment should be preserved // FIXME handle vertical whitespace better @@ -2053,20 +2045,16 @@ where Ok(format!( "{}{}", callee_str, - wrap_args_with_parens( - context, - &list_str, - extendable, - args_shape, - nested_shape, - ) + wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) )) } fn need_block_indent(s: &str, shape: Shape) -> bool { s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)) - .map_or(false, |w| w + 1 < shape.indent.width()) + s.find(|c| !char::is_whitespace(c)).map_or( + false, + |w| w + 1 < shape.indent.width(), + ) }) } @@ -2408,10 +2396,12 @@ fn rewrite_index( let indent = indent.to_string(&context.config); // FIXME this is not right, since we don't take into account that shape.width // might be reduced from max_width by something on the right. - let budget = try_opt!(context.config.max_width().checked_sub( - indent.len() + lbr.len() + - rbr.len(), - )); + let budget = try_opt!( + context + .config + .max_width() + .checked_sub(indent.len() + lbr.len() + rbr.len()) + ); let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); Some(format!( "{}\n{}{}{}{}", @@ -2603,12 +2593,10 @@ where // 3 = "(" + ",)" let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); return items.next().unwrap().rewrite(context, nested_shape).map( - |s| { - if context.config.spaces_within_parens() { - format!("( {}, )", s) - } else { - format!("({},)", s) - } + |s| if context.config.spaces_within_parens() { + format!("( {}, )", s) + } else { + format!("({},)", s) }, ); } diff --git a/src/items.rs b/src/items.rs index 1eb85771fd6..02a35286117 100644 --- a/src/items.rs +++ b/src/items.rs @@ -803,10 +803,9 @@ fn format_impl_ref_and_type( Style::Legacy => new_line_offset + trait_ref_overhead, Style::Rfc => new_line_offset, }; - result.push_str(&*try_opt!(self_ty.rewrite( - context, - Shape::legacy(budget, type_offset), - ))); + result.push_str(&*try_opt!( + self_ty.rewrite(context, Shape::legacy(budget, type_offset)) + )); Some(result) } else { unreachable!(); @@ -967,8 +966,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) where_density, "{", !has_body, - trait_bound_str.is_empty() && - last_line_width(&generics_str) == 1, + trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, None, )); // If the where clause cannot fit on the same line, @@ -1260,10 +1258,12 @@ fn format_tuple_struct( context.codemap.span_after(span, "("), span.hi, ); - let body_budget = try_opt!(context.config.max_width().checked_sub( - offset.block_only().width() + - result.len() + 3, - )); + let body_budget = try_opt!( + context + .config + .max_width() + .checked_sub(offset.block_only().width() + result.len() + 3) + ); let body = try_opt!(list_helper( items, // TODO budget is wrong in block case @@ -1548,8 +1548,7 @@ pub fn rewrite_static( let ty_str = try_opt!(ty.rewrite( context, Shape::legacy( - context.config.max_width() - offset.block_indent - - prefix.len() - 2, + context.config.max_width() - offset.block_indent - prefix.len() - 2, offset.block_only(), ), )); @@ -1613,8 +1612,7 @@ pub fn rewrite_associated_type( let ty_str = try_opt!(ty.rewrite( context, Shape::legacy( - context.config.max_width() - indent.block_indent - - prefix.len() - 2, + context.config.max_width() - indent.block_indent - prefix.len() - 2, indent.block_only(), ), )); @@ -1857,8 +1855,7 @@ fn rewrite_fn_base( 2 }; let shape = try_opt!( - Shape::indented(indent + last_line_width(&result), context.config) - .sub_width(overhead) + Shape::indented(indent + last_line_width(&result), context.config).sub_width(overhead) ); let g_span = mk_sp(span.lo, span_for_return(&fd.output).lo); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); @@ -1979,10 +1976,10 @@ fn rewrite_fn_base( } // If the last line of args contains comment, we cannot put the closing paren // on the same line. - if arg_str - .lines() - .last() - .map_or(false, |last_line| last_line.contains("//")) + if arg_str.lines().last().map_or( + false, + |last_line| last_line.contains("//"), + ) { args_last_line_contains_comment = true; result.push('\n'); @@ -2055,13 +2052,14 @@ fn rewrite_fn_base( let snippet_hi = span.hi; let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); // Try to preserve the layout of the original snippet. - let original_starts_with_newline = - snippet - .find(|c| c != ' ') - .map_or(false, |i| snippet[i..].starts_with('\n')); - let original_ends_with_newline = snippet - .rfind(|c| c != ' ') - .map_or(false, |i| snippet[i..].ends_with('\n')); + let original_starts_with_newline = snippet.find(|c| c != ' ').map_or( + false, + |i| snippet[i..].starts_with('\n'), + ); + let original_ends_with_newline = snippet.rfind(|c| c != ' ').map_or( + false, + |i| snippet[i..].ends_with('\n'), + ); let snippet = snippet.trim(); if !snippet.is_empty() { result.push(if original_starts_with_newline { diff --git a/src/lists.rs b/src/lists.rs index c770d1bf953..da412211233 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -132,9 +132,10 @@ impl ListItem { } pub fn has_line_pre_comment(&self) -> bool { - self.pre_comment - .as_ref() - .map_or(false, |comment| comment.starts_with("//")) + self.pre_comment.as_ref().map_or( + false, + |comment| comment.starts_with("//"), + ) } pub fn from_str>(s: S) -> ListItem { @@ -419,10 +420,9 @@ where } } None => { - post_snippet.find_uncommented(self.terminator).unwrap_or( - post_snippet - .len(), - ) + post_snippet + .find_uncommented(self.terminator) + .unwrap_or(post_snippet.len()) } }; @@ -435,10 +435,9 @@ where let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet.find(|c: char| !c.is_whitespace()).unwrap_or( - test_snippet - .len(), - ); + let first = test_snippet + .find(|c: char| !c.is_whitespace()) + .unwrap_or(test_snippet.len()); // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; diff --git a/src/types.rs b/src/types.rs index 3cdf9096094..723317a1040 100644 --- a/src/types.rs +++ b/src/types.rs @@ -590,10 +590,7 @@ impl Rewrite for ast::PolyTraitRef { let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); let path_str = try_opt!(self.trait_ref.rewrite( context, - Shape::legacy( - max_path_width, - shape.indent + extra_offset, - ), + Shape::legacy(max_path_width, shape.indent + extra_offset), )); Some(if context.config.spaces_within_angle_brackets() && @@ -645,10 +642,7 @@ impl Rewrite for ast::Ty { mut_str, try_opt!(mt.ty.rewrite( context, - Shape::legacy( - budget, - shape.indent + 2 + mut_len + lt_len, - ), + Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len), )) ) } diff --git a/src/visitor.rs b/src/visitor.rs index 17f48933499..a303e099f7a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -782,8 +782,8 @@ impl Rewrite for ast::MetaItem { impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - try_opt!(self.meta()).rewrite(context, shape).map(|rw| { - if rw.starts_with("///") { + try_opt!(self.meta()).rewrite(context, shape).map( + |rw| if rw.starts_with("///") { rw } else { let original = context.snippet(self.span); @@ -793,7 +793,7 @@ impl Rewrite for ast::Attribute { format!("#[{}]", rw) } } - }) + ) } } -- cgit 1.4.1-3-g733a5 From e31f5eceac47f66779f95324c58abde73cb06a0d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 06:25:58 +0900 Subject: Use correct span for Infer type inside closure header --- src/expr.rs | 2 +- src/items.rs | 15 +++++++++++++-- src/visitor.rs | 2 +- tests/source/closure.rs | 4 ++++ tests/target/closure.rs | 8 ++++++++ 5 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6b4669a70e7..8e2fe782ce9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -561,7 +561,7 @@ fn rewrite_closure_fn_decl( fn_decl.inputs.iter(), "|", |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(arg), + |arg| span_hi_for_arg(context, arg), |arg| arg.rewrite(context, arg_shape), context.codemap.span_after(span, "|"), body.span.lo, diff --git a/src/items.rs b/src/items.rs index 02a35286117..9a6bb08d3b6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1657,6 +1657,16 @@ impl Rewrite for ast::FunctionRetTy { } } +fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { + match ty.node { + ast::TyKind::Infer => { + let original = context.snippet(ty.span); + original != "_" + } + _ => false, + } +} + impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { @@ -1665,7 +1675,7 @@ impl Rewrite for ast::Arg { Shape::legacy(shape.width, shape.indent), )); - if self.ty.node != ast::TyKind::Infer { + if !is_empty_infer(context, &*self.ty) { if context.config.space_before_type_annotation() { result.push_str(" "); } @@ -1750,8 +1760,9 @@ pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { } } -pub fn span_hi_for_arg(arg: &ast::Arg) -> BytePos { +pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { match arg.ty.node { + ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi, ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi, _ => arg.ty.span.hi, } diff --git a/src/visitor.rs b/src/visitor.rs index a303e099f7a..b8225aaed1c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -792,7 +792,7 @@ impl Rewrite for ast::Attribute { } else { format!("#[{}]", rw) } - } + }, ) } } diff --git a/tests/source/closure.rs b/tests/source/closure.rs index 2f695e771b6..b52643f2fb8 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -147,3 +147,7 @@ fn issue325() { fn issue1697() { Test.func_a(A_VERY_LONG_CONST_VARIABLE_NAME, move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4) } + +fn issue1694() { + foooooo(|_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| format!("refs/pull/{}/merge", pr_id)) +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 7f09b1d7f68..3d6d322a103 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -174,3 +174,11 @@ fn issue1697() { move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4, ) } + +fn issue1694() { + foooooo( + |_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| { + format!("refs/pull/{}/merge", pr_id) + }, + ) +} -- cgit 1.4.1-3-g733a5 From 53273b8547ce39912c016f6573389485b657b4da Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 15:33:29 +0900 Subject: Try overflowing the last element of chain only if it goes multi line --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5a4a404bfdb..899d01ac4c5 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -238,7 +238,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if !fits_single_line && context.use_block_indent() { let (init, last) = rewrites.split_at_mut(last_non_try_index); let almost_single_line = init.iter().all(|s| !s.contains('\n')); - if almost_single_line { + if almost_single_line && last[0].contains('\n') { let overflow_shape = Shape { width: one_line_budget, ..parent_shape -- cgit 1.4.1-3-g733a5 From 7132814a71199d47570253027bf9804d8f36b81d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 16:54:25 +0900 Subject: Fix wrap_str Use shape.width for the first line and shape.used_width() for the last line. --- src/utils.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index dd18572575b..9c3d023c2ed 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -317,10 +317,7 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option first_line_max_len { + if lines.next().unwrap().len() > shape.width { return None; } @@ -333,9 +330,7 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option - shape.indent.width() + shape.width - { + if snippet.lines().rev().next().unwrap().len() > shape.used_width() + shape.width { return None; } } -- cgit 1.4.1-3-g733a5 From 92634a8f69ed3d11c70ed0e0a0e406a0e5511149 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 16:56:37 +0900 Subject: Use correct budget for chain --- src/chains.rs | 14 +++++++++++--- src/expr.rs | 4 +--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 899d01ac4c5..ed5278e81fc 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -124,7 +124,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_subexpr_is_try = subexpr_list.last().map_or(false, is_try); let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { let nested_shape = if first_subexpr_is_try { - parent_shape.block_indent(context.config.tab_spaces()) + parent_shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) } else { chain_indent(context, shape.add_offset(parent_rewrite.len())) }; @@ -143,7 +145,12 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else if parent_rewrite_contains_newline { (chain_indent(context, parent_shape), false) } else { - (shape.block_indent(context.config.tab_spaces()), false) + ( + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), + false, + ) }; let other_child_shape = nested_shape.with_max_width(context.config); @@ -234,7 +241,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } } - // Try overflowing the last element if we are using block indent. + // Try overflowing the last element if we are using block indent and it goes multi line + // or it fits in a single line but goes over the max width. if !fits_single_line && context.use_block_indent() { let (init, last) = rewrites.split_at_mut(last_non_try_index); let almost_single_line = init.iter().all(|s| !s.contains('\n')); diff --git a/src/expr.rs b/src/expr.rs index 8e2fe782ce9..d22c3f21a77 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2761,9 +2761,7 @@ pub fn rewrite_assign_rhs>( // FIXME: DRY! match (rhs, new_rhs) { (Some(ref orig_rhs), Some(ref replacement_rhs)) - if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 || - (orig_rhs.rewrite(context, shape).is_none() && - replacement_rhs.rewrite(context, new_shape).is_some()) => { + if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 => { result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(replacement_rhs); } -- cgit 1.4.1-3-g733a5 From 54233acc8ebe62cf6bf0d1bbbf686b6437a4fe9e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 16:56:54 +0900 Subject: Format source codes --- src/chains.rs | 7 ++--- src/comment.rs | 7 ++--- src/expr.rs | 55 ++++++++++++++-------------------- src/items.rs | 86 ++++++++++++++++++++++++++--------------------------- src/lists.rs | 14 ++++----- src/macros.rs | 7 ++--- src/missed_spans.rs | 8 ++--- src/types.rs | 26 ++++++++-------- src/visitor.rs | 7 ++--- 9 files changed, 99 insertions(+), 118 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index ed5278e81fc..9b27c92c270 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -183,10 +183,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Total of all items excluding the last. let last_non_try_index = rewrites.len() - (1 + trailing_try_num); - let almost_total = rewrites[..last_non_try_index].iter().fold( - 0, - |a, b| a + first_line_width(b), - ) + parent_rewrite.len(); + let almost_total = rewrites[..last_non_try_index] + .iter() + .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); diff --git a/src/comment.rs b/src/comment.rs index ce4b45009a2..d8189df363c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -45,10 +45,9 @@ pub enum CommentStyle<'a> { fn custom_opener(s: &str) -> &str { s.lines().next().map_or("", |first_line| { - first_line.find(' ').map_or( - first_line, - |space_index| &first_line[0..space_index + 1], - ) + first_line + .find(' ') + .map_or(first_line, |space_index| &first_line[0..space_index + 1]) }) } diff --git a/src/expr.rs b/src/expr.rs index d22c3f21a77..b69e8bbd42e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1077,10 +1077,8 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; - let else_str = try_opt!(else_expr.rewrite( - context, - Shape::legacy(new_width, Indent::empty()), - )); + let else_str = + try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); if if_str.contains('\n') || else_str.contains('\n') { return None; @@ -1298,19 +1296,17 @@ impl<'a> Rewrite for ControlFlow<'a> { let between_kwd_else_block = mk_sp( self.block.span.hi, - context.codemap.span_before( - mk_sp(self.block.span.hi, else_block.span.lo), - "else", - ), + context + .codemap + .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else"), ); let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); let after_else = mk_sp( - context.codemap.span_after( - mk_sp(self.block.span.hi, else_block.span.lo), - "else", - ), + context + .codemap + .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), else_block.span.lo, ); let after_else_comment = extract_comment(after_else, context, shape); @@ -1328,10 +1324,9 @@ impl<'a> Rewrite for ControlFlow<'a> { write!( &mut result, "{}else{}", - between_kwd_else_block_comment.as_ref().map_or( - between_sep, - |s| &**s, - ), + between_kwd_else_block_comment + .as_ref() + .map_or(between_sep, |s| &**s), after_else_comment.as_ref().map_or(after_sep, |s| &**s) ).ok() ); @@ -1478,10 +1473,9 @@ fn rewrite_match( let arm_indent_str = arm_shape.indent.to_string(context.config); - let open_brace_pos = context.codemap.span_after( - mk_sp(cond.span.hi, arm_start_pos(&arms[0])), - "{", - ); + let open_brace_pos = context + .codemap + .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. @@ -2051,10 +2045,8 @@ where fn need_block_indent(s: &str, shape: Shape) -> bool { s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)).map_or( - false, - |w| w + 1 < shape.indent.width(), - ) + s.find(|c| !char::is_whitespace(c)) + .map_or(false, |w| w + 1 < shape.indent.width()) }) } @@ -2271,10 +2263,8 @@ fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool where T: Rewrite + Spanned + ToExpr + 'a, { - args.last().map_or( - false, - |x| x.can_be_overflowed(context, args.len()), - ) + args.last() + .map_or(false, |x| x.can_be_overflowed(context, args.len())) } pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { @@ -2541,10 +2531,9 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); - let expr = field.expr.rewrite( - context, - Shape::indented(expr_offset, context.config), - ); + let expr = field + .expr + .rewrite(context, Shape::indented(expr_offset, context.config)); expr.map(|s| { format!( "{}{}:\n{}{}", @@ -2729,7 +2718,7 @@ pub fn rewrite_assign_rhs>( 0 }; // 1 = space between operator and rhs. - let orig_shape = try_opt!(shape.block_indent(0).offset_left(last_line_width + 1)); + let orig_shape = try_opt!(shape.offset_left(last_line_width + 1)); let rhs = match ex.node { ast::ExprKind::Mac(ref mac) => { match rewrite_macro(mac, None, context, orig_shape, MacroPosition::Expression) { diff --git a/src/items.rs b/src/items.rs index 9a6bb08d3b6..40d57ac45d7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -488,10 +488,12 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let indent = self.block_indent; - let mut result = try_opt!(field.node.attrs.rewrite( - &context, - Shape::indented(indent, self.config), - )); + let mut result = try_opt!( + field + .node + .attrs + .rewrite(&context, Shape::indented(indent, self.config)) + ); if !result.is_empty() { let shape = Shape { width: context.config.max_width(), @@ -1436,10 +1438,10 @@ impl Rewrite for ast::StructField { let name = self.ident; let vis = format_visibility(&self.vis); - let mut attr_str = try_opt!(self.attrs.rewrite( - context, - Shape::indented(shape.indent, context.config), - )); + let mut attr_str = try_opt!( + self.attrs + .rewrite(context, Shape::indented(shape.indent, context.config)) + ); // Try format missing comments after attributes let missing_comment = if !self.attrs.is_empty() { rewrite_missing_comment_on_field( @@ -1470,10 +1472,8 @@ impl Rewrite for ast::StructField { let type_offset = shape.indent.block_indent(context.config); let rewrite_type_in_next_line = || { - self.ty.rewrite( - context, - Shape::indented(type_offset, context.config), - ) + self.ty + .rewrite(context, Shape::indented(type_offset, context.config)) }; let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); @@ -1670,10 +1670,10 @@ fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!(self.pat.rewrite( - context, - Shape::legacy(shape.width, shape.indent), - )); + let mut result = try_opt!( + self.pat + .rewrite(context, Shape::legacy(shape.width, shape.indent)) + ); if !is_empty_infer(context, &*self.ty) { if context.config.space_before_type_annotation() { @@ -1872,17 +1872,17 @@ fn rewrite_fn_base( let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let snuggle_angle_bracket = generics_str.lines().last().map_or( - false, - |l| l.trim_left().len() == 1, - ); + let snuggle_angle_bracket = generics_str + .lines() + .last() + .map_or(false, |l| l.trim_left().len() == 1); // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. - let ret_str = try_opt!(fd.output.rewrite( - &context, - Shape::indented(indent, context.config), - )); + let ret_str = try_opt!( + fd.output + .rewrite(&context, Shape::indented(indent, context.config)) + ); let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -1942,10 +1942,10 @@ fn rewrite_fn_base( } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics.ty_params.last().map_or( - span.lo, - |tp| end_typaram(tp), - ); + let args_start = generics + .ty_params + .last() + .map_or(span.lo, |tp| end_typaram(tp)); let args_span = mk_sp( context.codemap.span_after(mk_sp(args_start, span.hi), "("), span_for_return(&fd.output).lo, @@ -1987,10 +1987,10 @@ fn rewrite_fn_base( } // If the last line of args contains comment, we cannot put the closing paren // on the same line. - if arg_str.lines().last().map_or( - false, - |last_line| last_line.contains("//"), - ) + if arg_str + .lines() + .last() + .map_or(false, |last_line| last_line.contains("//")) { args_last_line_contains_comment = true; result.push('\n'); @@ -2048,10 +2048,10 @@ fn rewrite_fn_base( if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = try_opt!(fd.output.rewrite( - context, - Shape::indented(ret_indent, context.config), - )); + let ret_str = try_opt!( + fd.output + .rewrite(context, Shape::indented(ret_indent, context.config)) + ); result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -2063,14 +2063,12 @@ fn rewrite_fn_base( let snippet_hi = span.hi; let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); // Try to preserve the layout of the original snippet. - let original_starts_with_newline = snippet.find(|c| c != ' ').map_or( - false, - |i| snippet[i..].starts_with('\n'), - ); - let original_ends_with_newline = snippet.rfind(|c| c != ' ').map_or( - false, - |i| snippet[i..].ends_with('\n'), - ); + let original_starts_with_newline = snippet + .find(|c| c != ' ') + .map_or(false, |i| snippet[i..].starts_with('\n')); + let original_ends_with_newline = snippet + .rfind(|c| c != ' ') + .map_or(false, |i| snippet[i..].ends_with('\n')); let snippet = snippet.trim(); if !snippet.is_empty() { result.push(if original_starts_with_newline { diff --git a/src/lists.rs b/src/lists.rs index da412211233..d176ef01f9b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -125,17 +125,15 @@ pub struct ListItem { impl ListItem { pub fn is_multiline(&self) -> bool { self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || - self.post_comment.as_ref().map_or( - false, - |s| s.contains('\n'), - ) + self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) } pub fn has_line_pre_comment(&self) -> bool { - self.pre_comment.as_ref().map_or( - false, - |comment| comment.starts_with("//"), - ) + self.pre_comment + .as_ref() + .map_or(false, |comment| comment.starts_with("//")) } pub fn from_str>(s: S) -> ListItem { diff --git a/src/macros.rs b/src/macros.rs index 88bfb96c5d6..419dea87a33 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -219,10 +219,9 @@ pub fn rewrite_macro( let rewrite = try_opt!(rewrite_array( expr_vec.iter().map(|x| &**x), mk_sp( - context.codemap.span_after( - mac.span, - original_style.opener(), - ), + context + .codemap + .span_after(mac.span, original_style.opener()), mac.span.hi - BytePos(1), ), context, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 45e4dc19dae..fb0e298bbbf 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -146,11 +146,9 @@ impl<'a> FmtVisitor<'a> { let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count(); if rewrite_next_comment && - !self.config.file_lines().intersects_range( - file_name, - cur_line, - cur_line + subslice_num_lines, - ) + !self.config + .file_lines() + .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) { rewrite_next_comment = false; } diff --git a/src/types.rs b/src/types.rs index 723317a1040..39b35de20b2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -172,10 +172,11 @@ impl<'a> Rewrite for SegmentParam<'a> { TypeDensity::Compressed => format!("{}=", binding.ident), }; let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!(binding.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + result.len()), - )); + let rewrite = try_opt!( + binding + .ty + .rewrite(context, Shape::legacy(budget, shape.indent + result.len())) + ); result.push_str(&rewrite); Some(result) } @@ -448,10 +449,9 @@ impl Rewrite for ast::WherePredicate { // 3 = " = ".len() let used_width = 3 + lhs_ty_str.len(); let budget = try_opt!(shape.width.checked_sub(used_width)); - let rhs_ty_str = try_opt!(rhs_ty.rewrite( - context, - Shape::legacy(budget, shape.indent + used_width), - )); + let rhs_ty_str = try_opt!( + rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) + ); format!("{} = {}", lhs_ty_str, rhs_ty_str) } }; @@ -651,10 +651,12 @@ impl Rewrite for ast::Ty { format!( "&{}{}", mut_str, - try_opt!(mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 1 + mut_len), - )) + try_opt!( + mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 1 + mut_len), + ) + ) ) } }) diff --git a/src/visitor.rs b/src/visitor.rs index b8225aaed1c..d20b4e971b5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -290,10 +290,9 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo); let snippet = self.get_context().snippet(item.span); - let where_span_end = - snippet - .find_uncommented("{") - .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); + let where_span_end = snippet + .find_uncommented("{") + .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); if let Some(impl_str) = format_impl( &self.get_context(), item, -- cgit 1.4.1-3-g733a5 From 38c30a3e06cb11bb541b5a9ea5c5b4f167d8469b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Jun 2017 02:00:58 +0900 Subject: Refactor format against types and generics Previous implementation relied on the fact that rustfmt used visual indent style as a default. However, since now rustfmt uses block indent style against most part of the code, we need some refactorings. --- src/items.rs | 45 ++++++++++++++++------------ src/lists.rs | 12 -------- src/types.rs | 96 ++++++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 94 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9a6bb08d3b6..ede20f331a2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -703,16 +703,17 @@ fn format_impl_ref_and_type( Some(ref tr) => tr.path.span.lo, None => self_ty.span.lo, }; - let shape = generics_shape_from_config( + let shape = try_opt!(generics_shape_from_config( context.config, Shape::indented(offset + last_line_width(&result), context.config), 0, - ); + )); + let one_line_budget = try_opt!(shape.width.checked_sub(last_line_width(&result) + 2)); let generics_str = try_opt!(rewrite_generics_inner( context, generics, shape, - shape.width, + one_line_budget, mk_sp(lo, hi), )); @@ -925,7 +926,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let trait_bound_str = try_opt!(rewrite_trait_bounds( context, type_param_bounds, - Shape::legacy(context.config.max_width(), offset), + Shape::indented(offset, context.config), )); // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line @@ -1591,7 +1592,7 @@ pub fn rewrite_associated_type( let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let shape = Shape::legacy(context.config.max_width(), indent); + let shape = Shape::indented(indent, context.config); let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!( bounds @@ -1900,7 +1901,8 @@ fn rewrite_fn_base( if context.config.fn_args_layout() == IndentStyle::Block { arg_indent = indent.block_indent(context.config); - multi_line_budget = context.config.max_width() - arg_indent.width(); + // 1 = "," + multi_line_budget = context.config.max_width() - (arg_indent.width() + 1); } debug!( @@ -2388,9 +2390,11 @@ fn rewrite_generics( shape: Shape, span: Span, ) -> Option { - let shape = generics_shape_from_config(context.config, shape, 0); - rewrite_generics_inner(context, generics, shape, shape.width, span) - .or_else(|| rewrite_generics_inner(context, generics, shape, 0, span)) + let g_shape = try_opt!(generics_shape_from_config(context.config, shape, 0)); + let one_line_width = try_opt!(shape.width.checked_sub(2)); + rewrite_generics_inner(context, generics, g_shape, one_line_width, span).or_else(|| { + rewrite_generics_inner(context, generics, g_shape, 0, span) + }) } fn rewrite_generics_inner( @@ -2437,14 +2441,17 @@ fn rewrite_generics_inner( format_generics_item_list(context, items, shape, one_line_width) } -pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Shape { - Shape { - // 2 = `<>` - width: shape.width.checked_sub(offset + 2).unwrap_or(0), - ..match config.generics_indent() { - IndentStyle::Visual => shape.visual_indent(1 + offset), - IndentStyle::Block => shape.block().block_indent(config.tab_spaces()), - } +pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { + match config.generics_indent() { + IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), + IndentStyle::Block => { + // 1 = "," + shape + .block() + .block_indent(config.tab_spaces()) + .with_max_width(config) + .sub_width(1) + } } } @@ -2533,7 +2540,7 @@ fn rewrite_where_clause_rfc_style( snuggle: bool, span_end: Option, ) -> Option { - let block_shape = shape.block(); + let block_shape = shape.block().with_max_width(context.config); let starting_newline = if snuggle { " ".to_owned() @@ -2555,7 +2562,7 @@ fn rewrite_where_clause_rfc_style( terminator, |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - |pred| pred.rewrite(context, shape), + |pred| pred.rewrite(context, block_shape), span_start, span_end, ); diff --git a/src/lists.rs b/src/lists.rs index da412211233..ced56cc6de9 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -68,18 +68,6 @@ pub struct ListFormatting<'a> { pub config: &'a Config, } -pub fn format_fn_args(items: I, shape: Shape, config: &Config) -> Option -where - I: Iterator, -{ - list_helper( - items, - shape, - config, - ListTactic::LimitedHorizontalVertical(config.fn_call_width()), - ) -} - pub fn format_item_list(items: I, shape: Shape, config: &Config) -> Option where I: Iterator, diff --git a/src/types.rs b/src/types.rs index 723317a1040..5e815c73b5b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -20,11 +20,12 @@ use syntax::symbol::keywords; use {Shape, Spanned}; use codemap::SpanUtils; use items::{format_generics_item_list, generics_shape_from_config}; -use lists::{itemize_list, format_fn_args}; +use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, + definitive_tactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple}; -use config::{Style, TypeDensity}; +use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple, wrap_args_with_parens}; +use config::{IndentStyle, Style, TypeDensity}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -224,8 +225,12 @@ fn rewrite_segment( "" }; - let generics_shape = - generics_shape_from_config(context.config, shape, separator.len()); + let generics_shape = try_opt!(generics_shape_from_config( + context.config, + shape, + separator.len(), + )); + let one_line_width = try_opt!(shape.width.checked_sub(separator.len() + 2)); let items = itemize_list( context.codemap, param_list.into_iter(), @@ -240,7 +245,7 @@ fn rewrite_segment( context, items, generics_shape, - generics_shape.width, + one_line_width, )); // Update position of last bracket. @@ -305,7 +310,16 @@ where // 2 for () let budget = try_opt!(shape.width.checked_sub(2)); // 1 for ( - let offset = shape.indent + 1; + let offset = match context.config.fn_args_layout() { + IndentStyle::Block => { + shape + .block() + .block_indent(context.config.tab_spaces()) + .indent + } + IndentStyle::Visual => shape.indent + 1, + }; + let list_shape = Shape::legacy(budget, offset); let list_lo = context.codemap.span_after(span, "("); let items = itemize_list( context.codemap, @@ -324,39 +338,64 @@ where ArgumentKind::Variadic(start) => start + BytePos(3), }, |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, Shape::legacy(budget, offset)), + ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), ArgumentKind::Variadic(_) => Some("...".to_owned()), }, list_lo, span.hi, ); - let list_str = try_opt!(format_fn_args( - items, - Shape::legacy(budget, offset), - context.config, - )); + let item_vec: Vec<_> = items.collect(); + + let tactic = definitive_tactic(&*item_vec, ListTactic::HorizontalVertical, budget); + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: if !context.use_block_indent() || variadic { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + shape: list_shape, + ends_with_newline: false, + config: context.config, + }; + let list_str = try_opt!(write_list(&item_vec, &fmt)); + + let ty_shape = match context.config.fn_args_layout() { + IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), + IndentStyle::Visual => try_opt!(shape.block_left(4)), + }; let output = match *output { FunctionRetTy::Ty(ref ty) => { - let budget = try_opt!(shape.width.checked_sub(4)); - let type_str = try_opt!(ty.rewrite(context, Shape::legacy(budget, offset + 4))); + let type_str = try_opt!(ty.rewrite(context, ty_shape)); format!(" -> {}", type_str) } FunctionRetTy::Default(..) => String::new(), }; - let infix = if !output.is_empty() && output.len() + list_str.len() > shape.width { - format!("\n{}", (offset - 1).to_string(context.config)) + let shape = try_opt!(shape.sub_width(output.len())); + let extendable = !list_str.contains('\n') || list_str.is_empty(); + let args = wrap_args_with_parens( + context, + &list_str, + extendable, + shape, + Shape::indented(offset, context.config), + ); + if last_line_width(&args) + output.len() > shape.width { + Some(format!( + "{}\n{}{}", + args, + offset.to_string(context.config), + output.trim_left() + )) } else { - String::new() - }; + Some(format!("{}{}", args, output)) + } - Some(if context.config.spaces_within_parens() { - format!("( {} ){}{}", list_str, infix, output) - } else { - format!("({}){}{}", list_str, infix, output) - }) } fn type_bound_colon(context: &RewriteContext) -> &'static str { @@ -422,7 +461,9 @@ impl Rewrite for ast::WherePredicate { .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) .collect() ); - let bounds_str = join_bounds(context, ty_shape, &bounds); + let overhead = type_str.len() + colon.len(); + let bounds_str = + join_bounds(context, try_opt!(ty_shape.sub_width(overhead)), &bounds); format!("{}{}{}", type_str, colon, bounds_str) } @@ -760,8 +801,7 @@ fn rewrite_bare_fn( result.push_str("fn"); - let budget = try_opt!(shape.width.checked_sub(result.len())); - let indent = shape.indent + result.len(); + let func_ty_shape = try_opt!(shape.offset_left(result.len())); let rewrite = try_opt!(format_function_type( bare_fn.decl.inputs.iter(), @@ -769,7 +809,7 @@ fn rewrite_bare_fn( bare_fn.decl.variadic, span, context, - Shape::legacy(budget, indent), + func_ty_shape, )); result.push_str(&rewrite); -- cgit 1.4.1-3-g733a5 From 6afb0e856cd78fd932f3ee363757be0573c94098 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Jun 2017 02:35:18 +0900 Subject: Avoid line break when rhs of assignment is an invalid macro --- src/expr.rs | 12 +----------- tests/source/macros.rs | 6 ++++++ tests/target/macros.rs | 6 ++++++ 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b69e8bbd42e..5fdc03bcc8e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2719,17 +2719,7 @@ pub fn rewrite_assign_rhs>( }; // 1 = space between operator and rhs. let orig_shape = try_opt!(shape.offset_left(last_line_width + 1)); - let rhs = match ex.node { - ast::ExprKind::Mac(ref mac) => { - match rewrite_macro(mac, None, context, orig_shape, MacroPosition::Expression) { - None if !context.snippet(ex.span).contains("\n") => { - context.snippet(ex.span).rewrite(context, orig_shape) - } - rhs @ _ => rhs, - } - } - _ => ex.rewrite(context, orig_shape), - }; + let rhs = ex.rewrite(context, orig_shape); fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() diff --git a/tests/source/macros.rs b/tests/source/macros.rs index a890053359f..e9c87f3ccea 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -79,6 +79,12 @@ fn main() { not function like ); + // #1712 + let image = gray_image!( + 00, 01, 02; + 10, 11, 12; + 20, 21, 22); + // #1577 let json = json!({ "foo": "bar", diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 9cc3305ea39..a9522fc26ce 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -110,6 +110,12 @@ fn main() { not function like ); + // #1712 + let image = gray_image!( + 00, 01, 02; + 10, 11, 12; + 20, 21, 22); + // #1577 let json = json!({ "foo": "bar", -- cgit 1.4.1-3-g733a5 From 3dcd3d7fb0452403e050e3b01c5678b0403c41f8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 21:11:55 +0900 Subject: Combine condition and body of control flow If the condition of control flow expressions ends with closing parens and alike, put the opening bracket of the body on the same line with closing parens. --- src/chains.rs | 9 ++------- src/expr.rs | 5 +++-- src/utils.rs | 9 +++++++++ 3 files changed, 14 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9b27c92c270..1729505d63b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -78,7 +78,7 @@ use Shape; use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, first_line_width, last_line_width, mk_sp}; +use utils::{wrap_str, first_line_width, last_line_width, mk_sp, last_line_extendable}; use expr::rewrite_call; use config::IndentStyle; use macros::convert_try_mac; @@ -322,12 +322,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { - context.config.chain_indent() == IndentStyle::Block && - parent_str.lines().last().map_or(false, |s| { - s.trim() - .chars() - .all(|c| c == ')' || c == ']' || c == '}' || c == '?') - }) + context.config.chain_indent() == IndentStyle::Block && last_line_extendable(parent_str) } // True if the chain is only `?`s. diff --git a/src/expr.rs b/src/expr.rs index b69e8bbd42e..c299ffadad5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -21,7 +21,7 @@ use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTacti use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, - colon_spaces, contains_skip, mk_sp}; + colon_spaces, contains_skip, mk_sp, last_line_extendable}; use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -1145,7 +1145,8 @@ impl<'a> ControlFlow<'a> { }; let force_newline_brace = context.config.control_style() == Style::Rfc && - pat_expr_string.contains('\n'); + pat_expr_string.contains('\n') && + !last_line_extendable(&pat_expr_string); // Try to format if-else on single line. if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { diff --git a/src/utils.rs b/src/utils.rs index 9c3d023c2ed..1be83d01bab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -108,6 +108,15 @@ pub fn trimmed_last_line_width(s: &str) -> usize { } } +#[inline] +pub fn last_line_extendable(s: &str) -> bool { + s.lines().last().map_or(false, |s| { + s.trim() + .chars() + .all(|c| c == ')' || c == ']' || c == '}' || c == '?') + }) +} + #[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { -- cgit 1.4.1-3-g733a5 From 91bd1fdc86f9891d063b11c87cee28aa3728fac0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 17 Jun 2017 21:17:20 +0900 Subject: Format source codes --- src/chains.rs | 3 +-- src/items.rs | 9 +++------ src/patterns.rs | 3 +-- src/visitor.rs | 6 ++---- 4 files changed, 7 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1729505d63b..fb26fb2ff7d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -226,8 +226,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - total_span, context, shape, - ) - { + ) { // If the first line of the last method does not fit into a single line // after the others, allow new lines. almost_total + first_line_width(&last[0]) < context.config.max_width() diff --git a/src/items.rs b/src/items.rs index 09d866ccf8d..b7c26574838 100644 --- a/src/items.rs +++ b/src/items.rs @@ -588,8 +588,7 @@ pub fn format_impl( &result, &where_clause_str, &item, - )) - { + )) { result.push_str(&where_clause_str); if where_clause_str.contains('\n') { let white_space = offset.to_string(context.config); @@ -736,8 +735,7 @@ fn format_impl_ref_and_type( true, polarity_str, result_len, - ) - { + ) { result.push_str(&trait_ref_str); } else { let generics_str = try_opt!(rewrite_generics_inner( @@ -2114,8 +2112,7 @@ fn rewrite_fn_base( !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi), - ) - { + ) { if !where_clause_str.contains('\n') { if last_line_width(&result) + where_clause_str.len() > context.config.max_width() { result.push('\n'); diff --git a/src/patterns.rs b/src/patterns.rs index 1899944bc10..ed444210081 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -376,8 +376,7 @@ fn count_wildcard_suffix_len( for item in items.iter().rev().take_while(|i| match i.item { Some(ref internal_string) if internal_string == "_" => true, _ => false, - }) - { + }) { suffix_len += 1; if item.pre_comment.is_some() || item.post_comment.is_some() { diff --git a/src/visitor.rs b/src/visitor.rs index d20b4e971b5..b34108800e7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -298,8 +298,7 @@ impl<'a> FmtVisitor<'a> { item, self.block_indent, where_span_end, - ) - { + ) { self.buffer.push_str(&impl_str); self.last_pos = source!(self, item.span).hi; } @@ -310,8 +309,7 @@ impl<'a> FmtVisitor<'a> { &self.get_context(), item, self.block_indent, - ) - { + ) { self.buffer.push_str(&trait_str); self.last_pos = source!(self, item.span).hi; } -- cgit 1.4.1-3-g733a5 From ae9ce7bcd9e628e3a4df5a3da91e7dfc29dff9f2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Jun 2017 22:44:56 +0900 Subject: Align multiline string literal --- src/expr.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b69e8bbd42e..b667eae8b14 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1856,7 +1856,26 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt let string_lit = context.snippet(span); if !context.config.format_strings() && !context.config.force_format_strings() { - return Some(string_lit); + if string_lit + .lines() + .rev() + .skip(1) + .all(|line| line.ends_with('\\')) + { + let new_indent = shape.visual_indent(1).indent; + return Some(String::from( + string_lit + .lines() + .map(|line| { + new_indent.to_string(context.config) + line.trim_left() + }) + .collect::>() + .join("\n") + .trim_left(), + )); + } else { + return Some(string_lit); + } } if !context.config.force_format_strings() && -- cgit 1.4.1-3-g733a5 From 75d86eb1a04e1179cddf093da25082def9da570c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Jun 2017 22:45:08 +0900 Subject: Format source codes --- Cargo.lock | 2 +- src/bin/cargo-fmt.rs | 2 +- src/bin/rustfmt.rs | 2 +- src/checkstyle.rs | 2 +- src/file_lines.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d56da60ea21..c17aea72696 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt-nightly" -version = "0.1.2" +version = "0.1.3" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index eeccae5c077..93348b82996 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -94,7 +94,7 @@ fn print_usage(opts: &Options, reason: &str) { let msg = format!("{}\nusage: cargo fmt [options]", reason); println!( "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ - Arguments after `--` are passed to rustfmt.", + Arguments after `--` are passed to rustfmt.", opts.usage(&msg) ); } diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 58b7e3ac8fd..e819579db14 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -144,7 +144,7 @@ fn make_opts() -> Options { "", "config-path", "Recursively searches the given path for the rustfmt.toml config file. If not \ - found reverts to the input file path", + found reverts to the input file path", "[Path for the configuration file]", ); opts.optopt( diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 90ba4561024..7b7ab2e1b2d 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -55,7 +55,7 @@ where write!( writer, "", + />", mismatch.line_number, message )?; diff --git a/src/file_lines.rs b/src/file_lines.rs index 81755eae805..939a7bf09a4 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -228,7 +228,7 @@ impl<'de> ::serde::de::Deserialize<'de> for FileLines { { panic!( "FileLines cannot be deserialized from a project rustfmt.toml file: please \ - specify it via the `--file-lines` option instead" + specify it via the `--file-lines` option instead" ); } } -- cgit 1.4.1-3-g733a5 From 34fa428471e0401377ed59ce7d75b7a280f0582d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 19 Jun 2017 12:58:29 +1200 Subject: make file_lines::Range public --- Cargo.lock | 2 +- src/file_lines.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d56da60ea21..c17aea72696 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt-nightly" -version = "0.1.2" +version = "0.1.3" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/file_lines.rs b/src/file_lines.rs index 81755eae805..4eae2602908 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -19,7 +19,7 @@ use codemap::LineRange; /// A range that is inclusive of both ends. #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] -struct Range { +pub struct Range { lo: usize, hi: usize, } -- cgit 1.4.1-3-g733a5 From 0b1342094352a935c7f205e4dfed7bdfd5bb3b64 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 19 Jun 2017 11:24:36 +0900 Subject: Apply the same overflowing rule to tuple as function call --- src/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 3b78dc961c2..8ff06f650eb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2309,8 +2309,8 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) | ast::ExprKind::Mac(..) | - ast::ExprKind::Struct(..) => context.use_block_indent() && args_len == 1, - ast::ExprKind::Tup(..) => context.use_block_indent(), + ast::ExprKind::Struct(..) | + ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, ast::ExprKind::AddrOf(_, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | -- cgit 1.4.1-3-g733a5 From ec4b439484d293860103c266eb96afc9ccca6ad5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 19 Jun 2017 12:07:20 +0900 Subject: Disallow overflowing closure if there are multiple closures in args --- src/expr.rs | 23 ++++++++++++++++++++--- tests/source/closure.rs | 14 ++++++++++++++ tests/target/closure.rs | 14 ++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8ff06f650eb..6546afd2d63 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2155,7 +2155,7 @@ where .map_or((None, None), |arg_shape| { rewrite_last_arg_with_overflow( &context, - args[args.len() - 1], + args, &mut item_vec[args.len() - 1], arg_shape, ) @@ -2251,18 +2251,35 @@ fn rewrite_last_closure( fn rewrite_last_arg_with_overflow<'a, T>( context: &RewriteContext, - last_arg: &T, + args: &[&T], last_item: &mut ListItem, shape: Shape, ) -> (Option, Option) where T: Rewrite + Spanned + ToExpr + 'a, { + let last_arg = args[args.len() - 1]; let rewrite = if let Some(expr) = last_arg.to_expr() { match expr.node { // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. - ast::ExprKind::Closure(..) => rewrite_last_closure(context, expr, shape), + ast::ExprKind::Closure(..) => { + // If the argument consists of multiple closures, we do not overflow + // the last closure. + if args.len() > 1 && + args.iter() + .rev() + .skip(1) + .filter_map(|arg| arg.to_expr()) + .any(|expr| match expr.node { + ast::ExprKind::Closure(..) => true, + _ => false, + }) { + None + } else { + rewrite_last_closure(context, expr, shape) + } + } _ => expr.rewrite(context, shape), } } else { diff --git a/tests/source/closure.rs b/tests/source/closure.rs index b52643f2fb8..e1aa8fc345e 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -151,3 +151,17 @@ fn issue1697() { fn issue1694() { foooooo(|_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| format!("refs/pull/{}/merge", pr_id)) } + +fn issue1713() { + rayon::join( + || recurse(left, is_less, pred, limit), + || recurse(right, is_less, Some(pivot), limit), + ); + + rayon::join( + 1, + || recurse(left, is_less, pred, limit), + 2, + || recurse(right, is_less, Some(pivot), limit), + ); +} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 3d6d322a103..bb31cad792b 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -182,3 +182,17 @@ fn issue1694() { }, ) } + +fn issue1713() { + rayon::join( + || recurse(left, is_less, pred, limit), + || recurse(right, is_less, Some(pivot), limit), + ); + + rayon::join( + 1, + || recurse(left, is_less, pred, limit), + 2, + || recurse(right, is_less, Some(pivot), limit), + ); +} -- cgit 1.4.1-3-g733a5 From 512c8c1edfbc6f94313045d3d6bcadcd42751cd7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 19 Jun 2017 16:00:04 +0900 Subject: Apply config.trailing_comma wherever possible --- src/expr.rs | 14 ++++++++++++-- src/items.rs | 6 +++--- tests/source/configs-trailing_comma-never.rs | 10 ++++++++++ tests/target/configs-trailing_comma-never.rs | 10 ++++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8ff06f650eb..8abc607d662 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1478,6 +1478,7 @@ fn rewrite_match( .codemap .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); + let arm_num = arms.len(); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. let missed_str = if i == 0 { @@ -1497,12 +1498,21 @@ fn rewrite_match( let arm_str = arm.rewrite(&context, arm_shape.with_max_width(context.config)); if let Some(ref arm_str) = arm_str { - result.push_str(arm_str); + // Trim the trailing comma if necessary. + if i == arm_num - 1 && context.config.trailing_comma() == SeparatorTactic::Never && + arm_str.ends_with(',') + { + result.push_str(&arm_str[0..arm_str.len() - 1]) + } else { + result.push_str(arm_str) + } } else { // We couldn't format the arm, just reproduce the source. let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); result.push_str(&snippet); - result.push_str(arm_comma(context.config, &arm.body)); + if context.config.trailing_comma() != SeparatorTactic::Never { + result.push_str(arm_comma(context.config, &arm.body)) + } } } // BytePos(1) = closing match brace. diff --git a/src/items.rs b/src/items.rs index b7c26574838..9adecb9be94 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2267,12 +2267,12 @@ fn rewrite_args( IndentStyle::Block => { ( indent.block_indent(context.config), - SeparatorTactic::Vertical, + context.config.trailing_comma(), true, ) } IndentStyle::Visual if last_line_ends_with_comment => { - (arg_indent, SeparatorTactic::Vertical, true) + (arg_indent, context.config.trailing_comma(), true) } IndentStyle::Visual => (arg_indent, SeparatorTactic::Never, false), }; @@ -2564,7 +2564,7 @@ fn rewrite_where_clause_rfc_style( let comma_tactic = if suppress_comma { SeparatorTactic::Never } else { - SeparatorTactic::Always + context.config.trailing_comma() }; let fmt = ListFormatting { diff --git a/tests/source/configs-trailing_comma-never.rs b/tests/source/configs-trailing_comma-never.rs index 0577f2e5aff..4da3b996f29 100644 --- a/tests/source/configs-trailing_comma-never.rs +++ b/tests/source/configs-trailing_comma-never.rs @@ -10,4 +10,14 @@ fn main() { let _ = safe_assert_eq!(reply_req_num, request_num, op); return Ok((request_num, op, value)); } + + // #1710 + pub struct FileInput { + input: StringInput, + file_name: OsString, + } + match len { + Some(len) => Ok(new(self.input, self.pos + len)), + None => Err(self), + } } diff --git a/tests/target/configs-trailing_comma-never.rs b/tests/target/configs-trailing_comma-never.rs index 8f351e8dfc2..ae0e50f96d1 100644 --- a/tests/target/configs-trailing_comma-never.rs +++ b/tests/target/configs-trailing_comma-never.rs @@ -22,4 +22,14 @@ fn main() { let _ = safe_assert_eq!(reply_req_num, request_num, op); return Ok((request_num, op, value)); } + + // #1710 + pub struct FileInput { + input: StringInput, + file_name: OsString + } + match len { + Some(len) => Ok(new(self.input, self.pos + len)), + None => Err(self) + } } -- cgit 1.4.1-3-g733a5 From 325d02bcc7e3bb95796874f983a20a7a7ca9f4a3 Mon Sep 17 00:00:00 2001 From: shinichi kogai Date: Mon, 19 Jun 2017 21:14:33 +0900 Subject: Public file-lines constructor --- src/file_lines.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index 6fa243dc186..dad7d0b061a 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -31,7 +31,7 @@ impl<'a> From<&'a LineRange> for Range { } impl Range { - fn new(lo: usize, hi: usize) -> Range { + pub fn new(lo: usize, hi: usize) -> Range { Range { lo: lo, hi: hi } } @@ -117,7 +117,7 @@ impl FileLines { FileLines(None) } - fn from_ranges(mut ranges: HashMap>) -> FileLines { + pub fn from_ranges(mut ranges: HashMap>) -> FileLines { normalize_ranges(&mut ranges); FileLines(Some(ranges)) } -- cgit 1.4.1-3-g733a5 From b99f3cb447d0eb76afd5d6d3b19336f12e30cc3f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 19 Jun 2017 22:06:08 +0900 Subject: Allow extending a chain after raw string literal --- src/utils.rs | 7 ++++--- tests/source/chains.rs | 11 +++++++++++ tests/target/chains.rs | 13 +++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 1be83d01bab..dc5dee6ba0d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -111,9 +111,10 @@ pub fn trimmed_last_line_width(s: &str) -> usize { #[inline] pub fn last_line_extendable(s: &str) -> bool { s.lines().last().map_or(false, |s| { - s.trim() - .chars() - .all(|c| c == ')' || c == ']' || c == '}' || c == '?') + s.ends_with("\"#") || + s.trim() + .chars() + .all(|c| c == ')' || c == ']' || c == '}' || c == '?') }) } diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 20d320ccde8..99fe6176aa8 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -152,3 +152,14 @@ fn issue_1004() { }) ?; } + +fn issue1392() { + test_method(r#" + if foo { + a(); + } + else { + b(); + } + "#.trim()); +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 52e65b420e7..d930f0a49ba 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -169,3 +169,16 @@ fn issue_1004() { in_binder(f, tcx, &ty::Binder(""), Some(tap)) })?; } + +fn issue1392() { + test_method( + r#" + if foo { + a(); + } + else { + b(); + } + "#.trim(), + ); +} -- cgit 1.4.1-3-g733a5 From d7298fbd97bf638ffce4c00717b2cf94cc9a08f6 Mon Sep 17 00:00:00 2001 From: Sean Olson Date: Mon, 19 Jun 2017 07:14:51 -0700 Subject: Keep brace on same line as `match` when using `ClosingNextLine` for `control_brace_style`. --- src/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6546afd2d63..3c6e1ad52b9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1461,8 +1461,8 @@ fn rewrite_match( let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysSameLine => " ", - _ => alt_block_sep.as_str(), + ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + _ => " ", }; let mut result = format!("match {}{}{{", cond_str, block_sep); -- cgit 1.4.1-3-g733a5 From 53202b40296f198ff30f46444b1c12197f616eb5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 19 Jun 2017 23:39:59 +0900 Subject: Do not run cargo fmt if there are unnecessary arguments --- src/bin/cargo-fmt.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 93348b82996..c8202eb7e41 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -50,6 +50,16 @@ fn execute() -> i32 { ); opts.optflag("", "all", "format all packages (only usable in workspaces)"); + // If there is any invalid argument passed to `cargo fmt`, return without formatting. + if let Some(arg) = env::args() + .skip(2) + .take_while(|a| a != "--") + .find(|a| !a.starts_with('-')) + { + print_usage(&opts, &format!("Invalid argument: `{}`.", arg)); + return failure; + } + let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { Ok(m) => m, Err(e) => { -- cgit 1.4.1-3-g733a5 From 90251c32ff4b52e3f3ac466d1b16bb91366d21a3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 20 Jun 2017 18:47:32 +1200 Subject: Add warning about write-mode change --- src/bin/rustfmt.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index e819579db14..ba00f123d03 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -78,6 +78,8 @@ impl CliOptions { format!("Invalid write-mode: {}", write_mode), )); } + } else { + println!("Warning: the default write-mode for Rustfmt will soon change to overwrite - this will not leave backups of changed files."); } if let Some(ref file_lines) = matches.opt_str("file-lines") { -- cgit 1.4.1-3-g733a5 From eeb20e20333127add88aa712091a958a0539a604 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 20 Jun 2017 21:34:19 +0900 Subject: Refactor rewrite for ast::Block --- src/expr.rs | 187 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 109 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2be7987d7c6..ebf9d5c1baa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -290,7 +290,9 @@ fn format_expr( ) } ast::ExprKind::Catch(ref block) => { - if let rewrite @ Some(_) = try_one_line_block(context, shape, "do catch ", block) { + if let rewrite @ Some(_) = + rewrite_single_line_block(context, "do catch ", block, shape) + { return rewrite; } // 9 = `do catch ` @@ -315,23 +317,6 @@ fn format_expr( } } -fn try_one_line_block( - context: &RewriteContext, - shape: Shape, - prefix: &str, - block: &ast::Block, -) -> Option { - if is_simple_block(block, context.codemap) { - let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent); - let expr_str = try_opt!(block.stmts[0].rewrite(context, expr_shape)); - let result = format!("{}{{ {} }}", prefix, expr_str); - if result.len() <= shape.width && !result.contains('\n') { - return Some(result); - } - } - None -} - pub fn rewrite_pair( lhs: &LHS, rhs: &RHS, @@ -763,78 +748,124 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option Option { - // shape.width is used only for the single line case: either the empty block `{}`, - // or an unsafe expression `unsafe { e }`. +fn rewrite_empty_block( + context: &RewriteContext, + block: &ast::Block, + shape: Shape, +) -> Option { + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && + shape.width >= 2 + { + return Some("{}".to_owned()); + } - if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) && - shape.width >= 2 + // If a block contains only a single-line comment, then leave it on one line. + let user_str = context.snippet(block.span); + let user_str = user_str.trim(); + if user_str.starts_with('{') && user_str.ends_with('}') { + let comment_str = user_str[1..user_str.len() - 1].trim(); + if block.stmts.is_empty() && !comment_str.contains('\n') && + !comment_str.starts_with("//") && comment_str.len() + 4 <= shape.width { - return Some("{}".to_owned()); + return Some(format!("{{ {} }}", comment_str)); } + } - // If a block contains only a single-line comment, then leave it on one line. - let user_str = context.snippet(self.span); - let user_str = user_str.trim(); - if user_str.starts_with('{') && user_str.ends_with('}') { - let comment_str = user_str[1..user_str.len() - 1].trim(); - if self.stmts.is_empty() && !comment_str.contains('\n') && - !comment_str.starts_with("//") && - comment_str.len() + 4 <= shape.width - { - return Some(format!("{{ {} }}", comment_str)); + None +} + +fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> Option { + Some(match block.rules { + ast::BlockCheckMode::Unsafe(..) => { + let snippet = context.snippet(block.span); + let open_pos = try_opt!(snippet.find_uncommented("{")); + // Extract comment between unsafe and block start. + let trimmed = &snippet[6..open_pos].trim(); + + if !trimmed.is_empty() { + // 9 = "unsafe {".len(), 7 = "unsafe ".len() + let budget = try_opt!(shape.width.checked_sub(9)); + format!( + "unsafe {} ", + try_opt!(rewrite_comment( + trimmed, + true, + Shape::legacy(budget, shape.indent + 7), + context.config, + )) + ) + } else { + "unsafe ".to_owned() } } + ast::BlockCheckMode::Default => String::new(), + }) +} - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); - visitor.block_indent = shape.indent; - visitor.is_if_else_block = context.is_if_else_block; +fn rewrite_single_line_block( + context: &RewriteContext, + prefix: &str, + block: &ast::Block, + shape: Shape, +) -> Option { + if is_simple_block(block, context.codemap) { + let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent); + let expr_str = try_opt!(block.stmts[0].rewrite(context, expr_shape)); + let result = format!("{}{{ {} }}", prefix, expr_str); + if result.len() <= shape.width && !result.contains('\n') { + return Some(result); + } + } + None +} - let prefix = match self.rules { - ast::BlockCheckMode::Unsafe(..) => { - let snippet = context.snippet(self.span); - let open_pos = try_opt!(snippet.find_uncommented("{")); - visitor.last_pos = self.span.lo + BytePos(open_pos as u32); +fn rewrite_block_with_visitor( + context: &RewriteContext, + prefix: &str, + block: &ast::Block, + shape: Shape, +) -> Option { + if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + return rw; + } - // Extract comment between unsafe and block start. - let trimmed = &snippet[6..open_pos].trim(); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); + visitor.block_indent = shape.indent; + visitor.is_if_else_block = context.is_if_else_block; + match block.rules { + ast::BlockCheckMode::Unsafe(..) => { + let snippet = context.snippet(block.span); + let open_pos = try_opt!(snippet.find_uncommented("{")); + visitor.last_pos = block.span.lo + BytePos(open_pos as u32) + } + ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo, + } - let prefix = if !trimmed.is_empty() { - // 9 = "unsafe {".len(), 7 = "unsafe ".len() - let budget = try_opt!(shape.width.checked_sub(9)); - format!( - "unsafe {} ", - try_opt!(rewrite_comment( - trimmed, - true, - Shape::legacy(budget, shape.indent + 7), - context.config, - )) - ) - } else { - "unsafe ".to_owned() - }; - if let result @ Some(_) = try_one_line_block(context, shape, &prefix, self) { - return result; - } - prefix - } - ast::BlockCheckMode::Default => { - visitor.last_pos = self.span.lo; - String::new() - } - }; + visitor.visit_block(block); + if visitor.failed && shape.indent.alignment != 0 { + block.rewrite( + context, + Shape::indented(shape.indent.block_only(), context.config), + ) + } else { + Some(format!("{}{}", prefix, visitor.buffer)) + } +} - visitor.visit_block(self); - if visitor.failed && shape.indent.alignment != 0 { - self.rewrite( - context, - Shape::indented(shape.indent.block_only(), context.config), - ) - } else { - Some(format!("{}{}", prefix, visitor.buffer)) +impl Rewrite for ast::Block { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + // shape.width is used only for the single line case: either the empty block `{}`, + // or an unsafe expression `unsafe { e }`. + if let rw @ Some(_) = rewrite_empty_block(context, self, shape) { + return rw; } + + let prefix = try_opt!(block_prefix(context, self, shape)); + if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { + return rw; + } + + rewrite_block_with_visitor(context, &prefix, self, shape) } } -- cgit 1.4.1-3-g733a5 From fb1225a8af14567eaf21d5978f7e7a6498867381 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 20 Jun 2017 21:35:52 +0900 Subject: Use format_expr wherever single-lined block is not allowed --- src/expr.rs | 38 +++++++++++++++++++++++++++++++------- src/items.rs | 6 ++++-- src/visitor.rs | 16 +++++++++++++++- 3 files changed, 50 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ebf9d5c1baa..e3c80cd95ca 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -42,7 +42,7 @@ impl Rewrite for ast::Expr { } #[derive(PartialEq)] -enum ExprType { +pub enum ExprType { Statement, SubExpression, } @@ -67,7 +67,7 @@ fn combine_attr_and_expr( format!("{}{}{}", attr_str, separator, expr_str) } -fn format_expr( +pub fn format_expr( expr: &ast::Expr, expr_type: ExprType, context: &RewriteContext, @@ -160,7 +160,23 @@ fn format_expr( to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)) } - ast::ExprKind::Block(ref block) => block.rewrite(context, shape), + ast::ExprKind::Block(ref block) => { + match expr_type { + ExprType::Statement => { + if is_unsafe_block(block) { + block.rewrite(context, shape) + } else { + // Rewrite block without trying to put it in a single line. + if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + return rw; + } + let prefix = try_opt!(block_prefix(context, block, shape)); + rewrite_block_with_visitor(context, &prefix, block, shape) + } + } + ExprType::SubExpression => block.rewrite(context, shape), + } + } ast::ExprKind::Match(ref cond, ref arms) => { rewrite_match(context, cond, arms, shape, expr.span) } @@ -1280,7 +1296,12 @@ impl<'a> Rewrite for ControlFlow<'a> { }; let mut block_context = context.clone(); block_context.is_if_else_block = self.else_block.is_some(); - let block_str = try_opt!(self.block.rewrite(&block_context, block_shape)); + let block_str = try_opt!(rewrite_block_with_visitor( + &block_context, + "", + self.block, + block_shape, + )); let mut result = format!("{}{}", cond_str, block_str); @@ -1322,7 +1343,7 @@ impl<'a> Rewrite for ControlFlow<'a> { width: min(1, shape.width), ..shape }; - else_block.rewrite(context, else_shape) + format_expr(else_block, ExprType::Statement, context, else_shape) } }; @@ -1689,7 +1710,10 @@ impl Rewrite for ast::Arm { .unwrap() .sub_width(comma.len()) .unwrap(); - let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), arm_shape.width); + let rewrite = nop_block_collapse( + format_expr(body, ExprType::Statement, context, arm_shape), + arm_shape.width, + ); let is_block = if let ast::ExprKind::Block(..) = body.node { true } else { @@ -1724,7 +1748,7 @@ impl Rewrite for ast::Arm { // necessary. let body_shape = try_opt!(shape.block_left(context.config.tab_spaces())); let next_line_body = try_opt!(nop_block_collapse( - body.rewrite(context, body_shape), + format_expr(body, ExprType::Statement, context, body_shape), body_shape.width, )); let indent_str = shape diff --git a/src/items.rs b/src/items.rs index 9adecb9be94..cb68231733e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -17,7 +17,7 @@ use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wr trimmed_last_line_width, colon_spaces, mk_sp}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, DefinitiveListTactic, ListTactic, definitive_tactic}; -use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, ExprType}; use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; @@ -352,7 +352,9 @@ impl<'a> FmtVisitor<'a> { Some(e) => { let suffix = if semicolon_for_expr(e) { ";" } else { "" }; - e.rewrite( + format_expr( + &e, + ExprType::Statement, &self.get_context(), Shape::indented(self.block_indent, self.config), ).map(|s| s + suffix) diff --git a/src/visitor.rs b/src/visitor.rs index b34108800e7..0f574d433fd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,6 +17,7 @@ use syntax::parse::ParseSess; use strings::string_buffer::StringBuffer; use {Indent, Shape}; +use expr::{format_expr, ExprType}; use utils::{self, mk_sp}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, FindUncommented}; @@ -87,7 +88,20 @@ impl<'a> FmtVisitor<'a> { ); self.push_rewrite(stmt.span, rewrite); } - ast::StmtKind::Expr(ref expr) | + ast::StmtKind::Expr(ref expr) => { + let rewrite = format_expr( + expr, + ExprType::Statement, + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ); + let span = if expr.attrs.is_empty() { + stmt.span + } else { + mk_sp(expr.attrs[0].span.lo, stmt.span.hi) + }; + self.push_rewrite(span, rewrite) + } ast::StmtKind::Semi(ref expr) => { let rewrite = stmt.rewrite( &self.get_context(), -- cgit 1.4.1-3-g733a5 From 64fc9e31e7e102e15d3d6570ce855b8738f6ace9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 20 Jun 2017 22:35:56 +0900 Subject: Fix a typo --- src/bin/rustfmt.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index ba00f123d03..4d2f1cdc041 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -79,7 +79,10 @@ impl CliOptions { )); } } else { - println!("Warning: the default write-mode for Rustfmt will soon change to overwrite - this will not leave backups of changed files."); + println!( + "Warning: the default write-mode for Rustfmt will soon change to overwrite \ + - this will not leave backups of changed files." + ); } if let Some(ref file_lines) = matches.opt_str("file-lines") { -- cgit 1.4.1-3-g733a5 From b95666b20cf0b12c4396ec56e6bc04fc3555f268 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 21 Jun 2017 07:32:23 +0200 Subject: Handle proc-macro crates in cargo-fmt --- src/bin/cargo-fmt.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index c8202eb7e41..b4a1b3d5172 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -148,6 +148,7 @@ enum TargetKind { Test, // test file Bench, // bench file CustomBuild, // build script + ProcMacro, // a proc macro implementation Other, // plugin,... } @@ -155,7 +156,7 @@ impl TargetKind { fn should_format(&self) -> bool { match *self { TargetKind::Lib | TargetKind::Bin | TargetKind::Example | TargetKind::Test | - TargetKind::Bench | TargetKind::CustomBuild => true, + TargetKind::Bench | TargetKind::CustomBuild | TargetKind::ProcMacro => true, _ => false, } } @@ -282,6 +283,7 @@ fn target_from_json(jtarget: &Value) -> Target { "example" => TargetKind::Example, "bench" => TargetKind::Bench, "custom-build" => TargetKind::CustomBuild, + "proc-macro" => TargetKind::ProcMacro, _ => TargetKind::Other, }; -- cgit 1.4.1-3-g733a5 From 60f0c576c9d6227f493494fe3cc7ca3880ab6b2d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 23 Jun 2017 12:56:57 +0900 Subject: Preserve trailing comma of macro invocation --- src/expr.rs | 12 ++++++++++-- src/macros.rs | 39 +++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e3c80cd95ca..4eafd726807 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -93,6 +93,7 @@ pub fn format_expr( mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), context, shape, + false, ) } ast::ExprKind::Lit(ref l) => { @@ -435,6 +436,7 @@ pub fn rewrite_array<'a, I>( span: Span, context: &RewriteContext, shape: Shape, + trailing_comma: bool, ) -> Option where I: Iterator, @@ -507,7 +509,13 @@ where let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::Never, + trailing_separator: if trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro || context.config.array_layout() == IndentStyle::Visual { + SeparatorTactic::Never + } else { + SeparatorTactic::Vertical + }, shape: nested_shape, ends_with_newline: false, config: context.config, @@ -524,7 +532,7 @@ where } } else { format!( - "[\n{}{},\n{}]", + "[\n{}{}\n{}]", nested_shape.indent.to_string(context.config), list_str, shape.block().indent.to_string(context.config) diff --git a/src/macros.rs b/src/macros.rs index 419dea87a33..54a65087e12 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,7 @@ use syntax::util::ThinVec; use Shape; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; -use expr::{rewrite_call, rewrite_array}; +use expr::{rewrite_call_inner, rewrite_array}; use comment::{FindUncommented, contains_comment}; use utils::mk_sp; @@ -110,6 +110,7 @@ pub fn rewrite_macro( let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); let mut expr_vec = Vec::new(); let mut vec_with_semi = false; + let mut trailing_comma = false; if MacroStyle::Braces != style { loop { @@ -162,12 +163,8 @@ pub fn rewrite_macro( parser.bump(); if parser.token == Token::Eof { - // vec! is a special case of bracket macro which should be formated as an array. - if macro_name == "vec!" { - break; - } else { - return None; - } + trailing_comma = true; + break; } } } @@ -176,12 +173,19 @@ pub fn rewrite_macro( MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - rewrite_call(context, ¯o_name, &expr_vec, mac.span, shape).map( - |rw| match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - }, - ) + let rw = rewrite_call_inner( + context, + ¯o_name, + &expr_vec.iter().map(|e| &**e).collect::>()[..], + mac.span, + shape, + context.config.fn_call_width(), + trailing_comma, + ); + rw.ok().map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) } MacroStyle::Brackets => { let mac_shape = try_opt!(shape.offset_left(macro_name.len())); @@ -215,7 +219,13 @@ pub fn rewrite_macro( )) } } else { - // Format macro invocation as array literal. + // If we are rewriting `vec!` macro or other special macros, + // then we can rewrite this as an usual array literal. + // Otherwise, we must preserve the original existence of trailing comma. + if FORCED_BRACKET_MACROS.contains(&¯o_name.as_str()) { + context.inside_macro = false; + trailing_comma = false; + } let rewrite = try_opt!(rewrite_array( expr_vec.iter().map(|x| &**x), mk_sp( @@ -226,6 +236,7 @@ pub fn rewrite_macro( ), context, mac_shape, + trailing_comma, )); Some(format!("{}{}", macro_name, rewrite)) -- cgit 1.4.1-3-g733a5 From eeb5599b4b767762a3bdd9f6b9493b05faa34c84 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 23 Jun 2017 13:40:30 +0900 Subject: Do not add trailing comma inside macro invocation unless there already is --- src/expr.rs | 34 +++++++++++++++++++++++------ tests/target/configs-fn_call_style-block.rs | 2 +- tests/target/macros.rs | 2 +- 3 files changed, 29 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4eafd726807..35c028d24db 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2009,6 +2009,11 @@ pub fn rewrite_call_with_binary_search( where R: Rewrite, { + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + false + }; let closure = |callee_max_width| { // FIXME using byte lens instead of char lens (and probably all over the // place too) @@ -2027,7 +2032,7 @@ where span, shape, context.config.fn_call_width(), - false, + force_trailing_comma, ) }; @@ -2041,6 +2046,11 @@ pub fn rewrite_call( span: Span, shape: Shape, ) -> Option { + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + false + }; rewrite_call_inner( context, &callee, @@ -2048,7 +2058,7 @@ pub fn rewrite_call( span, shape, context.config.fn_call_width(), - false, + force_trailing_comma, ).ok() } @@ -2155,15 +2165,13 @@ fn rewrite_call_args<'a, T>( where T: Rewrite + Spanned + ToExpr + 'a, { - let mut item_context = context.clone(); - item_context.inside_macro = false; let items = itemize_list( context.codemap, args.iter(), ")", |item| item.span().lo, |item| item.span().hi, - |item| item.rewrite(&item_context, shape), + |item| item.rewrite(context, shape), span.lo, span.hi, ); @@ -2173,7 +2181,7 @@ where // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. let tactic = try_overflow_last_arg( - &item_context, + context, &mut item_vec, &args[..], shape, @@ -2444,6 +2452,13 @@ pub fn wrap_args_with_parens( } } +fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { + let snippet = context.snippet(span); + snippet + .trim_right_matches(|c: char| c == ')' || c.is_whitespace()) + .ends_with(',') +} + fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { debug!("rewrite_paren, shape: {:?}", shape); let paren_overhead = paren_overhead(context); @@ -2733,6 +2748,11 @@ where debug!("rewrite_tuple {:?}", shape); if context.use_block_indent() { // We use the same rule as funcation call for rewriting tuple. + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + items.len() == 1 + }; rewrite_call_inner( context, &String::new(), @@ -2740,7 +2760,7 @@ where span, shape, context.config.fn_call_width(), - items.len() == 1, + force_trailing_comma, ).ok() } else { rewrite_tuple_in_visual_indent_style(context, items, span, shape) diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index 55c5ecdf593..75d6b6765fb 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -33,7 +33,7 @@ fn main() { // nesting macro and function call try!(foo( xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx )); try!(foo(try!( xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, diff --git a/tests/target/macros.rs b/tests/target/macros.rs index bd1042638a1..eb95fe4758c 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -152,7 +152,7 @@ fn issue1739() { b: types::Timestamptz, c: types::Text, d: types::Text, - e: types::Text, + e: types::Text ) ); -- cgit 1.4.1-3-g733a5 From 5f775817637bcd65d9eddc91ac6272455b7db2f1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 26 Jun 2017 07:57:06 +0900 Subject: Put multi-lined index on the next line if it fits in one line --- src/expr.rs | 62 +++++++++++++++++++++++++++++++++++----------------- tests/source/expr.rs | 13 +++++++++++ tests/target/expr.rs | 15 +++++++++++++ 3 files changed, 70 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 35c028d24db..12846049406 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2501,31 +2501,53 @@ fn rewrite_index( }; let offset = expr_str.len() + lbr.len(); - if let Some(index_shape) = shape.visual_indent(offset).sub_width(offset + rbr.len()) { - if let Some(index_str) = index.rewrite(context, index_shape) { + let orig_index_rw = shape + .visual_indent(offset) + .sub_width(offset + rbr.len()) + .and_then(|index_shape| index.rewrite(context, index_shape)); + + // Return if everything fits in a single line. + match orig_index_rw { + Some(ref index_str) if !index_str.contains('\n') => { return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); } + _ => (), } + // Try putting index on the next line and see if it fits in a single line. let indent = shape.indent.block_indent(&context.config); - let indent = indent.to_string(&context.config); - // FIXME this is not right, since we don't take into account that shape.width - // might be reduced from max_width by something on the right. - let budget = try_opt!( - context - .config - .max_width() - .checked_sub(indent.len() + lbr.len() + rbr.len()) - ); - let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent))); - Some(format!( - "{}\n{}{}{}{}", - expr_str, - indent, - lbr, - index_str, - rbr - )) + let rhs_overhead = context + .config + .max_width() + .checked_sub(shape.used_width() + shape.width) + .unwrap_or(0); + let index_shape = try_opt!(Shape::indented(indent, context.config).offset_left(lbr.len())); + let index_shape = try_opt!(index_shape.sub_width(rbr.len() + rhs_overhead)); + let new_index_rw = index.rewrite(context, index_shape); + match (orig_index_rw, new_index_rw) { + (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => { + Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent.to_string(&context.config), + lbr, + new_index_str, + rbr + )) + } + (None, Some(ref new_index_str)) => { + Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent.to_string(&context.config), + lbr, + new_index_str, + rbr + )) + } + (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), + _ => None, + } } fn rewrite_struct_lit<'a>( diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 80e4f2b623f..3d54e68c409 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -308,3 +308,16 @@ fn issue1714() { v = &mut {v}[mid..]; let (left, right) = {v}.split_at_mut(mid); } + +// Multi-lined index should be put on the next line if it fits in one line. +fn issue1749() { + { + { + { + if self.shape[(r as f32 + self.x_offset) as usize][(c as f32 + self.y_offset) as usize] != 0 { + // hello + } + } + } + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index b6509040714..624a3c7eb94 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -367,3 +367,18 @@ fn issue1714() { v = &mut { v }[mid..]; let (left, right) = { v }.split_at_mut(mid); } + +// Multi-lined index should be put on the next line if it fits in one line. +fn issue1749() { + { + { + { + if self.shape[(r as f32 + self.x_offset) as usize] + [(c as f32 + self.y_offset) as usize] != 0 + { + // hello + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 747481068c4d33b82880dac61b25f530a6f31f3f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 26 Jun 2017 14:11:34 +0900 Subject: Add an option to inhibit warning on write-mode change --- src/bin/rustfmt.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 4d2f1cdc041..d2f2f3d761b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -78,7 +78,7 @@ impl CliOptions { format!("Invalid write-mode: {}", write_mode), )); } - } else { + } else if !matches.opt_present("no-warn-write-mode") { println!( "Warning: the default write-mode for Rustfmt will soon change to overwrite \ - this will not leave backups of changed files." @@ -120,6 +120,12 @@ fn make_opts() -> Options { opts.optflag("h", "help", "show this message"); opts.optflag("V", "version", "show version information"); opts.optflag("v", "verbose", "print verbose output"); + // Suppress warning. Remove this option after the default write mode changed to overwrite. + opts.optflag( + "w", + "no-warn-write-mode", + "inhibit warning about write-mode change", + ); opts.optopt( "", "write-mode", -- cgit 1.4.1-3-g733a5 From 0199e08367ab09d0e6194cd0c8f9dbfeab8b53a2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 28 Jun 2017 10:56:29 +0900 Subject: Use correct one line budget in rewrite_closure_block --- src/expr.rs | 2 +- tests/source/configs-closure_block_indent_threshold--1.rs | 5 +++++ tests/target/configs-closure_block_indent_threshold--1.rs | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/source/configs-closure_block_indent_threshold--1.rs create mode 100644 tests/target/configs-closure_block_indent_threshold--1.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 35c028d24db..471229b3f07 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -750,7 +750,7 @@ fn rewrite_closure_block( // The body of the closure is big enough to be block indented, that // means we must re-format. - let block_shape = shape.block().with_max_width(context.config); + let block_shape = shape.block(); let block_str = try_opt!(block.rewrite(&context, block_shape)); Some(format!("{} {}", prefix, block_str)) } diff --git a/tests/source/configs-closure_block_indent_threshold--1.rs b/tests/source/configs-closure_block_indent_threshold--1.rs new file mode 100644 index 00000000000..166f825b239 --- /dev/null +++ b/tests/source/configs-closure_block_indent_threshold--1.rs @@ -0,0 +1,5 @@ +// rustfmt-closure_block_indent_threshold: -1 + +fn issue1755() { + b.iter(|| dfkljdklgjdlkfgjdlkgjldkjfgkdjgldjfgkljdfklgjlkdjfgkljdflkgjlkdfjgdjfsas::expect("parse")); +} diff --git a/tests/target/configs-closure_block_indent_threshold--1.rs b/tests/target/configs-closure_block_indent_threshold--1.rs new file mode 100644 index 00000000000..3a62e6a27ed --- /dev/null +++ b/tests/target/configs-closure_block_indent_threshold--1.rs @@ -0,0 +1,7 @@ +// rustfmt-closure_block_indent_threshold: -1 + +fn issue1755() { + b.iter(|| { + dfkljdklgjdlkfgjdlkgjldkjfgkdjgldjfgkljdfklgjlkdjfgkljdflkgjlkdfjgdjfsas::expect("parse") + }); +} -- cgit 1.4.1-3-g733a5 From 4e0882ea67a785733ab54dbef195cea56211b0db Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 29 Jun 2017 11:00:51 +0900 Subject: Combine Array --- src/expr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 35c028d24db..e771216dee9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2404,9 +2404,10 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l context.use_block_indent() || context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 } + ast::ExprKind::Array(..) | ast::ExprKind::Call(..) | - ast::ExprKind::MethodCall(..) | ast::ExprKind::Mac(..) | + ast::ExprKind::MethodCall(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, ast::ExprKind::AddrOf(_, ref expr) | -- cgit 1.4.1-3-g733a5 From 7eafad96ad301f69eff104bc6f3e6b39fb29a9d2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 3 Jul 2017 18:48:21 +0900 Subject: Implement Spanned for ast::StructField and ast::Field --- src/lib.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 62d4df502d1..94aef6f5c48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,6 +48,7 @@ use filemap::FileMap; use visitor::FmtVisitor; use config::Config; use checkstyle::{output_header, output_footer}; +use utils::mk_sp; pub use self::summary::Summary; @@ -112,6 +113,28 @@ impl Spanned for ast::Arg { } } +impl Spanned for ast::StructField { + fn span(&self) -> Span { + if self.attrs.is_empty() { + mk_sp(self.span.lo, self.ty.span.hi) + } else { + // Include attributes and doc comments, if present + mk_sp(self.attrs[0].span.lo, self.ty.span.hi) + } + } +} + +impl Spanned for ast::Field { + fn span(&self) -> Span { + let lo = if self.attrs.is_empty() { + self.span.lo + } else { + self.attrs[0].span.lo + }; + mk_sp(lo, self.span.hi) + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of -- cgit 1.4.1-3-g733a5 From 89aaf3bf03b5c65b21be5bde0eb5063f2dc890b9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 3 Jul 2017 18:53:47 +0900 Subject: Use correct width and tactic for struct literal --- src/expr.rs | 29 ++++++++++++++++------------- src/lists.rs | 17 ++++++++--------- src/patterns.rs | 25 +++++-------------------- 3 files changed, 29 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 35c028d24db..e6b6c53fa2e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2601,32 +2601,35 @@ fn rewrite_struct_lit<'a>( span.hi, ); let item_vec = items.collect::>(); + let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + Some(format!("{} {{{}}}", path_str, fields_str)) - let tactic = struct_lit_tactic(h_shape, context, &item_vec); - let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); - let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); + // FIXME if context.config.struct_lit_style() == Visual, but we run out + // of space, we should fall back to BlockIndent. +} - let fields_str = try_opt!(write_list(&item_vec, &fmt)); - let fields_str = if context.config.struct_lit_style() == IndentStyle::Block && +pub fn wrap_struct_field( + context: &RewriteContext, + fields_str: &str, + shape: Shape, + nested_shape: Shape, + one_line_width: usize, +) -> String { + if context.config.struct_lit_style() == IndentStyle::Block && (fields_str.contains('\n') || context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || - fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) + fields_str.len() > one_line_width) { format!( "\n{}{}\n{}", - v_shape.indent.to_string(context.config), + nested_shape.indent.to_string(context.config), fields_str, shape.indent.to_string(context.config) ) } else { // One liner or visual indent. format!(" {} ", fields_str) - }; - - Some(format!("{} {{{}}}", path_str, fields_str)) - - // FIXME if context.config.struct_lit_style() == Visual, but we run out - // of space, we should fall back to BlockIndent. + } } pub fn struct_lit_field_separator(config: &Config) -> &str { diff --git a/src/lists.rs b/src/lists.rs index 1d3be8045e2..d6cb00b55cd 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -555,8 +555,13 @@ pub fn struct_lit_shape( } } }; - let h_shape = shape.sub_width(prefix_width + suffix_width); - Some((h_shape, v_shape)) + let shape_width = shape.width.checked_sub(prefix_width + suffix_width); + if let Some(w) = shape_width { + let shape_width = cmp::min(w, context.config.struct_lit_width()); + Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) + } else { + Some((None, v_shape)) + } } // Compute the tactic for the internals of a struct-lit-like thing. @@ -566,16 +571,10 @@ pub fn struct_lit_tactic( items: &[ListItem], ) -> DefinitiveListTactic { if let Some(h_shape) = h_shape { - let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) { + let prelim_tactic = match (context.config.struct_lit_style(), items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style().to_list_tactic(), }; - - if prelim_tactic == ListTactic::HorizontalVertical && items.len() > 1 { - prelim_tactic = - ListTactic::LimitedHorizontalVertical(context.config.struct_lit_width()); - } - definitive_tactic(items, prelim_tactic, h_shape.width) } else { DefinitiveListTactic::Vertical diff --git a/src/patterns.rs b/src/patterns.rs index ed444210081..cda7a108609 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -10,12 +10,12 @@ use Shape; use codemap::SpanUtils; -use config::{IndentStyle, MultilineStyle}; use rewrite::{Rewrite, RewriteContext}; use utils::{wrap_str, format_mutability, mk_sp}; use lists::{DefinitiveListTactic, SeparatorTactic, itemize_list, struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list}; -use expr::{rewrite_call_inner, rewrite_unary_prefix, rewrite_pair, can_be_overflowed_expr}; +use expr::{rewrite_call_inner, rewrite_unary_prefix, rewrite_pair, can_be_overflowed_expr, + wrap_struct_field}; use types::{rewrite_path, PathContext}; use super::Spanned; use comment::FindUncommented; @@ -181,9 +181,10 @@ fn rewrite_struct_pat( let fmt = struct_lit_formatting(nested_shape, tactic, context, false); let mut fields_str = try_opt!(write_list(&item_vec, &fmt)); + let one_line_width = h_shape.map_or(0, |shape| shape.width); if elipses { - if fields_str.contains('\n') { + if fields_str.contains('\n') || fields_str.len() > one_line_width { // Add a missing trailing comma. if fmt.trailing_separator == SeparatorTactic::Never { fields_str.push_str(","); @@ -205,23 +206,7 @@ fn rewrite_struct_pat( } } - - let fields_str = if context.config.struct_lit_style() == IndentStyle::Block && - (fields_str.contains('\n') || - context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || - fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) - { - format!( - "\n{}{}\n{}", - v_shape.indent.to_string(context.config), - fields_str, - shape.indent.to_string(context.config) - ) - } else { - // One liner or visual indent. - format!(" {} ", fields_str) - }; - + let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); Some(format!("{} {{{}}}", path_str, fields_str)) } -- cgit 1.4.1-3-g733a5 From bd991851c86c2475d703b08bed6742253d4bb8d9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 3 Jul 2017 18:54:26 +0900 Subject: Format source codes --- src/lib.rs | 4 +++- tests/target/attrib.rs | 8 ++++++-- tests/target/issue-1397.rs | 3 ++- tests/target/issue-855.rs | 12 ++++++++---- tests/target/struct_lits.rs | 8 ++++++-- 5 files changed, 25 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 94aef6f5c48..5e512b4fa89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -421,7 +421,9 @@ pub struct FormatReport { impl FormatReport { fn new() -> FormatReport { - FormatReport { file_error_map: HashMap::new() } + FormatReport { + file_error_map: HashMap::new(), + } } pub fn warning_count(&self) -> usize { diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index ed152a8124e..fa14f3c8647 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -56,8 +56,12 @@ struct Foo { fn foo() { #[cfg(target_os = "freertos")] match port_id { - 'a' | 'A' => GpioPort { port_address: GPIO_A }, - 'b' | 'B' => GpioPort { port_address: GPIO_B }, + 'a' | 'A' => GpioPort { + port_address: GPIO_A, + }, + 'b' | 'B' => GpioPort { + port_address: GPIO_B, + }, _ => panic!(), } diff --git a/tests/target/issue-1397.rs b/tests/target/issue-1397.rs index 21c3c9e38de..86b7a78411f 100644 --- a/tests/target/issue-1397.rs +++ b/tests/target/issue-1397.rs @@ -12,7 +12,8 @@ fn baz(p: Packet) { loop { loop { if let Packet::Transaction { - state: TransactionState::Committed(ts, ..), .. + state: TransactionState::Committed(ts, ..), + .. } = p { unreachable!() diff --git a/tests/target/issue-855.rs b/tests/target/issue-855.rs index 3add3378ff7..dc5600c7d5d 100644 --- a/tests/target/issue-855.rs +++ b/tests/target/issue-855.rs @@ -3,7 +3,10 @@ fn main() { for event in event_pump.poll_iter() { match event { Event::Quit { .. } | - Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, + Event::KeyDown { + keycode: Some(Keycode::Escape), + .. + } => break 'running, } } } @@ -14,9 +17,10 @@ fn main2() { for event in event_pump.poll_iter() { match event { Event::Quit { .. } | - Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => { - break 'running - } + Event::KeyDownXXXXXXXXXXXXX { + keycode: Some(Keycode::Escape), + .. + } => break 'running, } } } diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index a42d8e7aada..648c723d357 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -116,7 +116,9 @@ fn struct_exprs() { ..base }; IntrinsicISizesContribution { - content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0 }, + content_intrinsic_sizes: IntrinsicISizes { + minimum_inline_size: 0, + }, }; } @@ -141,7 +143,9 @@ fn issue491() { arm: 0, // Comment }; - Foo { arm: 0 /* Comment */ }; + Foo { + arm: 0, // Comment + }; Foo { a: aaaaaaaaaa, -- cgit 1.4.1-3-g733a5 From 34b4a9d3c4ccd47a6dbc676dd0825693a85b9b01 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 3 Jul 2017 18:54:41 +0900 Subject: Add struct_field_align_threshold for vertical alignment --- Configurations.md | 27 ++++++ src/config.rs | 4 +- src/expr.rs | 132 +++++++++++++++++--------- src/items.rs | 248 ++++++++++++++++++++++++------------------------- src/lib.rs | 1 + src/vertical.rs | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 512 insertions(+), 171 deletions(-) create mode 100644 src/vertical.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index a436e5159c5..5de757a9168 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1209,6 +1209,33 @@ fn lorem(t: T) { See also: [`space_before_bound`](#space_before_bound). +## `struct_field_align_threshold` + +The maximum diff of width between struct fields to be aligned with each other. + +- **Default value** : 0 +- **Possible values**: any positive integer + +#### `0`: + +```rust +struct Foo { + x: u32, + yy: u32, + zzz: u32, +} +``` + +#### `20`: + +```rust +struct Foo { + x: u32, + yy: u32, + zzz: u32, +} +``` + ## `space_after_struct_lit_field_colon` Leave a space after the colon in a struct literal field diff --git a/src/config.rs b/src/config.rs index 153fad178cc..bc00fd176cf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -598,7 +598,9 @@ create_config! { "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns"; - combine_control_expr: bool, true, "Combine control expressions with funciton calls." + combine_control_expr: bool, true, "Combine control expressions with funciton calls."; + struct_field_align_threshold: usize, 0, "Align struct fields if their diffs fits within \ + threshold." } #[cfg(test)] diff --git a/src/expr.rs b/src/expr.rs index e6b6c53fa2e..d9d20b1092c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -30,6 +30,7 @@ use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; use macros::{rewrite_macro, MacroPosition}; use patterns::{TuplePatField, can_be_overflowed_pat}; +use vertical::rewrite_with_alignment; use syntax::{ast, ptr}; use syntax::codemap::{CodeMap, Span, BytePos}; @@ -2528,6 +2529,14 @@ fn rewrite_index( )) } +fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { + if base.is_some() { + return false; + } + + fields.iter().all(|field| !field.is_shorthand) +} + fn rewrite_struct_lit<'a>( context: &RewriteContext, path: &ast::Path, @@ -2557,50 +2566,71 @@ fn rewrite_struct_lit<'a>( return Some(format!("{} {{}}", path_str)); } - let field_iter = fields - .into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); - // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); - let span_lo = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span.lo, - StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - }; - let span_hi = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span.hi, - StructLitField::Base(expr) => expr.span.hi, - }; - let rewrite = |item: &StructLitField| match *item { - StructLitField::Regular(field) => { - // The 1 taken from the v_budget is for the comma. - rewrite_field(context, field, try_opt!(v_shape.sub_width(1))) - } - StructLitField::Base(expr) => { - // 2 = .. - expr.rewrite(context, try_opt!(v_shape.shrink_left(2))) - .map(|s| format!("..{}", s)) - } + let one_line_width = h_shape.map_or(0, |shape| shape.width); + let body_lo = context.codemap.span_after(span, "{"); + let fields_str = if struct_lit_can_be_aligned(fields, &base) && + context.config.struct_field_align_threshold() > 0 + { + try_opt!(rewrite_with_alignment( + fields, + context, + shape, + mk_sp(body_lo, span.hi), + one_line_width, + )) + } else { + let field_iter = fields + .into_iter() + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); + + let span_lo = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span().lo, + StructLitField::Base(expr) => { + let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }; + let span_hi = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span().hi, + StructLitField::Base(expr) => expr.span.hi, + }; + let rewrite = |item: &StructLitField| match *item { + StructLitField::Regular(field) => { + // The 1 taken from the v_budget is for the comma. + rewrite_field(context, field, try_opt!(v_shape.sub_width(1)), 0) + } + StructLitField::Base(expr) => { + // 2 = .. + expr.rewrite(context, try_opt!(v_shape.shrink_left(2))) + .map(|s| format!("..{}", s)) + } + }; + + let items = itemize_list( + context.codemap, + field_iter, + "}", + span_lo, + span_hi, + rewrite, + body_lo, + span.hi, + ); + let item_vec = items.collect::>(); + + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); + + try_opt!(write_list(&item_vec, &fmt)) }; - let items = itemize_list( - context.codemap, - field_iter, - "}", - span_lo, - span_hi, - rewrite, - context.codemap.span_after(span, "{"), - span.hi, - ); - let item_vec = items.collect::>(); let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); Some(format!("{} {{{}}}", path_str, fields_str)) @@ -2639,18 +2669,32 @@ pub fn struct_lit_field_separator(config: &Config) -> &str { ) } -fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option { +pub fn rewrite_field( + context: &RewriteContext, + field: &ast::Field, + shape: Shape, + prefix_max_width: usize, +) -> Option { + if contains_skip(&field.attrs) { + return wrap_str( + context.snippet(field.span()), + context.config.max_width(), + shape, + ); + } let name = &field.ident.node.to_string(); if field.is_shorthand { Some(name.to_string()) } else { - let separator = struct_lit_field_separator(context.config); + let mut separator = String::from(struct_lit_field_separator(context.config)); + for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { + separator.push(' '); + } let overhead = name.len() + separator.len(); - let mut expr_shape = try_opt!(shape.sub_width(overhead)); - expr_shape.offset += overhead; + let expr_shape = try_opt!(shape.offset_left(overhead)); let expr = field.expr.rewrite(context, expr_shape); - let mut attrs_str = try_opt!((*field.attrs).rewrite(context, shape)); + let mut attrs_str = try_opt!(field.attrs.rewrite(context, shape)); if !attrs_str.is_empty() { attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); }; diff --git a/src/items.rs b/src/items.rs index cb68231733e..0e8c10ea181 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,6 +23,7 @@ use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style}; use types::join_bounds; +use vertical::rewrite_with_alignment; use syntax::{ast, abi, ptr, symbol}; use syntax::codemap::{Span, BytePos}; @@ -1100,49 +1101,14 @@ fn format_struct_struct( return Some(result); } - let item_indent = offset.block_indent(context.config); - // 1 = "," - let item_budget = try_opt!( - context - .config - .max_width() - .checked_sub(item_indent.width() + 1) - ); - - let items = itemize_list( - context.codemap, - fields.iter(), - "}", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), - context.codemap.span_after(span, "{"), - span.hi, - ).collect::>(); - // 1 = , - let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1; - - let tactic = match one_line_width { - Some(w) => definitive_tactic(&items, ListTactic::LimitedHorizontalVertical(w), budget), - None => DefinitiveListTactic::Vertical, - }; + let items_str = try_opt!(rewrite_with_alignment( + fields, + context, + Shape::indented(offset, context.config), + mk_sp(body_lo, span.hi), + one_line_width.unwrap_or(0), + )); - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: context.config.trailing_comma(), - shape: Shape::legacy(budget, item_indent), - ends_with_newline: true, - config: context.config, - }; - let items_str = try_opt!(write_list(&items, &fmt)); if one_line_width.is_some() && !items_str.contains('\n') { Some(format!("{} {} }}", result, items_str)) } else { @@ -1257,7 +1223,9 @@ fn format_tuple_struct( } }, |field| field.ty.span.hi, - |field| field.rewrite(context, Shape::legacy(item_budget, item_indent)), + |field| { + rewrite_struct_field(context, field, Shape::legacy(item_budget, item_indent), 0) + }, context.codemap.span_after(span, "("), span.hi, ); @@ -1430,97 +1398,125 @@ fn rewrite_missing_comment_on_field( } } -impl Rewrite for ast::StructField { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if contains_skip(&self.attrs) { - let span = context.snippet(mk_sp(self.attrs[0].span.lo, self.span.hi)); - return wrap_str(span, context.config.max_width(), shape); +pub fn rewrite_struct_field_prefix( + context: &RewriteContext, + field: &ast::StructField, + shape: Shape, +) -> Option { + let vis = format_visibility(&field.vis); + let mut attr_str = try_opt!( + field + .attrs + .rewrite(context, Shape::indented(shape.indent, context.config)) + ); + // Try format missing comments after attributes + let missing_comment = if !field.attrs.is_empty() { + rewrite_missing_comment_on_field( + context, + shape, + field.attrs[field.attrs.len() - 1].span.hi, + field.span.lo, + &mut attr_str, + ).unwrap_or(String::new()) + } else { + String::new() + }; + + let type_annotation_spacing = type_annotation_spacing(context.config); + Some(match field.ident { + Some(name) => { + format!( + "{}{}{}{}{}:", + attr_str, + missing_comment, + vis, + name, + type_annotation_spacing.0 + ) } + None => format!("{}{}{}", attr_str, missing_comment, vis), + }) +} - let name = self.ident; - let vis = format_visibility(&self.vis); - let mut attr_str = try_opt!( - self.attrs - .rewrite(context, Shape::indented(shape.indent, context.config)) - ); - // Try format missing comments after attributes - let missing_comment = if !self.attrs.is_empty() { - rewrite_missing_comment_on_field( - context, - shape, - self.attrs[self.attrs.len() - 1].span.hi, - self.span.lo, - &mut attr_str, - ).unwrap_or(String::new()) - } else { - String::new() - }; +fn rewrite_struct_field_type( + context: &RewriteContext, + last_line_width: usize, + field: &ast::StructField, + spacing: &str, + shape: Shape, +) -> Option { + let ty_shape = try_opt!(shape.offset_left(last_line_width + spacing.len())); + field + .ty + .rewrite(context, ty_shape) + .map(|ty| format!("{}{}", spacing, ty)) +} - let type_annotation_spacing = type_annotation_spacing(context.config); - let mut result = match name { - Some(name) => { - format!( - "{}{}{}{}{}:", - attr_str, - missing_comment, - vis, - name, - type_annotation_spacing.0 - ) - } - None => format!("{}{}{}", attr_str, missing_comment, vis), - }; - let type_offset = shape.indent.block_indent(context.config); - let rewrite_type_in_next_line = || { - self.ty - .rewrite(context, Shape::indented(type_offset, context.config)) - }; +pub fn rewrite_struct_field( + context: &RewriteContext, + field: &ast::StructField, + shape: Shape, + lhs_max_width: usize, +) -> Option { + if contains_skip(&field.attrs) { + let span = context.snippet(mk_sp(field.attrs[0].span.lo, field.span.hi)); + return wrap_str(span, context.config.max_width(), shape); + } - let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len(); - let budget = try_opt!(shape.width.checked_sub(last_line_width)); - let ty_rewritten = self.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + last_line_width), - ); - match ty_rewritten { - Some(ref ty) if ty.contains('\n') => { - let new_ty = rewrite_type_in_next_line(); - match new_ty { - Some(ref new_ty) - if !new_ty.contains('\n') && - new_ty.len() + type_offset.width() <= context.config.max_width() => { - Some(format!( - "{}\n{}{}", - result, - type_offset.to_string(&context.config), - &new_ty - )) - } - _ => { - if name.is_some() { - result.push_str(type_annotation_spacing.1); - } - Some(result + &ty) - } - } - } - Some(ty) => { - if name.is_some() { - result.push_str(type_annotation_spacing.1); + let type_annotation_spacing = type_annotation_spacing(context.config); + let prefix = try_opt!(rewrite_struct_field_prefix(context, field, shape)); + + // Try to put everything on a single line. + let last_line_width = last_line_width(&prefix); + let mut spacing = String::from(if field.ident.is_some() { + type_annotation_spacing.1 + } else { + "" + }); + let lhs_offset = lhs_max_width.checked_sub(last_line_width).unwrap_or(0); + for _ in 0..lhs_offset { + spacing.push(' '); + } + let ty_rewritten = rewrite_struct_field_type(context, last_line_width, field, &spacing, shape); + if let Some(ref ty) = ty_rewritten { + if !ty.contains('\n') { + return Some(prefix + &ty); + } + } + + // We must use multiline. + let type_offset = shape.indent.block_indent(context.config); + let rewrite_type_in_next_line = || { + field + .ty + .rewrite(context, Shape::indented(type_offset, context.config)) + }; + + match ty_rewritten { + // If we start from the next line and type fits in a single line, then do so. + Some(ref ty) => { + match rewrite_type_in_next_line() { + Some(ref new_ty) if !new_ty.contains('\n') => { + Some(format!( + "{}\n{}{}", + prefix, + type_offset.to_string(&context.config), + &new_ty + )) } - Some(result + &ty) - } - None => { - let ty = try_opt!(rewrite_type_in_next_line()); - Some(format!( - "{}\n{}{}", - result, - type_offset.to_string(&context.config), - &ty - )) + _ => Some(prefix + &ty), } } + _ => { + let ty = try_opt!(rewrite_type_in_next_line()); + Some(format!( + "{}\n{}{}", + prefix, + type_offset.to_string(&context.config), + &ty + )) + } } } diff --git a/src/lib.rs b/src/lib.rs index 5e512b4fa89..f0c3ebf49a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,7 @@ mod chains; mod macros; mod patterns; mod summary; +mod vertical; const MIN_STRING: usize = 10; // When we get scoped annotations, we should have rustfmt::skip. diff --git a/src/vertical.rs b/src/vertical.rs new file mode 100644 index 00000000000..d6b34443518 --- /dev/null +++ b/src/vertical.rs @@ -0,0 +1,271 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format with vertical alignment. + +use std::cmp; + +use {Indent, Shape, Spanned}; +use codemap::SpanUtils; +use comment::contains_comment; +use expr::rewrite_field; +use items::{rewrite_struct_field, rewrite_struct_field_prefix}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic}; +use rewrite::{Rewrite, RewriteContext}; +use utils::{contains_skip, mk_sp}; + +use syntax::ast; +use syntax::codemap::{Span, BytePos}; + +pub trait AlignedItem { + fn skip(&self) -> bool; + fn get_span(&self) -> Span; + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option; + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option; +} + +impl AlignedItem for ast::StructField { + fn skip(&self) -> bool { + contains_skip(&self.attrs) + } + + fn get_span(&self) -> Span { + self.span() + } + + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_struct_field_prefix(context, self, shape) + } + + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option { + rewrite_struct_field(context, self, shape, prefix_max_width) + } +} + +impl AlignedItem for ast::Field { + fn skip(&self) -> bool { + contains_skip(&self.attrs) + } + + fn get_span(&self) -> Span { + self.span() + } + + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + let mut attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + if !attrs_str.is_empty() { + attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); + }; + let name = &self.ident.node.to_string(); + Some(format!("{}{}", attrs_str, name)) + } + + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option { + rewrite_field(context, self, shape, prefix_max_width) + } +} + +pub fn rewrite_with_alignment( + fields: &[T], + context: &RewriteContext, + shape: Shape, + span: Span, + one_line_width: usize, +) -> Option { + let (spaces, group_index) = if context.config.struct_field_align_threshold() > 0 { + group_aligned_items(context, fields) + } else { + ("", fields.len() - 1) + }; + let init = &fields[0..group_index + 1]; + let rest = &fields[group_index + 1..]; + let init_last_pos = if rest.is_empty() { + span.hi + } else { + // Decide whether the missing comments should stick to init or rest. + let init_hi = init[init.len() - 1].get_span().hi; + let rest_lo = rest[0].get_span().lo; + let missing_span = mk_sp(init_hi, rest_lo); + let missing_span = mk_sp( + context.codemap.span_after(missing_span, ","), + missing_span.hi, + ); + + let snippet = context.snippet(missing_span); + if snippet.trim_left().starts_with("//") { + let offset = snippet.lines().next().map_or(0, |l| l.len()); + // 2 = "," + "\n" + init_hi + BytePos(offset as u32 + 2) + } else if snippet.trim_left().starts_with("/*") { + let comment_lines = snippet + .lines() + .position(|line| line.trim_right().ends_with("*/")) + .unwrap_or(0); + + let offset = snippet + .lines() + .take(comment_lines + 1) + .collect::>() + .join("\n") + .len(); + + init_hi + BytePos(offset as u32 + 2) + } else { + missing_span.lo + } + }; + let init_span = mk_sp(span.lo, init_last_pos); + let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; + let result = try_opt!(rewrite_aligned_items_inner( + context, + init, + init_span, + shape.indent, + one_line_width, + )); + if rest.is_empty() { + Some(result + spaces) + } else { + let rest_span = mk_sp(init_last_pos, span.hi); + let rest_str = try_opt!(rewrite_with_alignment( + rest, + context, + shape, + rest_span, + one_line_width, + )); + Some( + result + spaces + "\n" + + &shape + .indent + .block_indent(context.config) + .to_string(context.config) + &rest_str, + ) + } +} + +fn struct_field_preix_max_min_width( + context: &RewriteContext, + fields: &[T], + shape: Shape, +) -> (usize, usize) { + fields + .iter() + .map(|field| { + field.rewrite_prefix(context, shape).and_then( + |field_str| if field_str.contains('\n') { + None + } else { + Some(field_str.len()) + }, + ) + }) + .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { + (Some((max_len, min_len)), Some(len)) => { + Some((cmp::max(max_len, len), cmp::min(min_len, len))) + } + _ => None, + }) + .unwrap_or((0, 0)) +} + +fn rewrite_aligned_items_inner( + context: &RewriteContext, + fields: &[T], + span: Span, + offset: Indent, + one_line_width: usize, +) -> Option { + let item_indent = offset.block_indent(context.config); + // 1 = "," + let item_shape = try_opt!(Shape::indented(item_indent, context.config).sub_width(1)); + let (mut field_prefix_max_width, field_prefix_min_width) = + struct_field_preix_max_min_width(context, fields, item_shape); + let max_diff = field_prefix_max_width + .checked_sub(field_prefix_min_width) + .unwrap_or(0); + if max_diff > context.config.struct_field_align_threshold() { + field_prefix_max_width = 0; + } + + let items = itemize_list( + context.codemap, + fields.iter(), + "}", + |field| field.get_span().lo, + |field| field.get_span().hi, + |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), + span.lo, + span.hi, + ).collect::>(); + + let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, one_line_width); + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: context.config.trailing_comma(), + shape: item_shape, + ends_with_newline: true, + config: context.config, + }; + write_list(&items, &fmt) +} + +fn group_aligned_items( + context: &RewriteContext, + fields: &[T], +) -> (&'static str, usize) { + let mut index = 0; + for i in 0..fields.len() - 1 { + if fields[i].skip() { + return ("", index); + } + // See if there are comments or empty lines between fields. + let span = mk_sp(fields[i].get_span().hi, fields[i + 1].get_span().lo); + let snippet = context + .snippet(span) + .lines() + .skip(1) + .collect::>() + .join("\n"); + let spacings = if snippet + .lines() + .rev() + .skip(1) + .find(|l| l.trim().is_empty()) + .is_some() + { + "\n" + } else { + "" + }; + if contains_comment(&snippet) || snippet.lines().count() > 1 { + return (spacings, index); + } + index += 1; + } + ("", index) +} -- cgit 1.4.1-3-g733a5 From 183e3482e58d2cc107046386a816644c7b4f7b69 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 4 Jul 2017 20:21:49 +0900 Subject: Add a space before range if lhs ends with dot --- src/expr.rs | 16 ++++++++++++++++ tests/source/expr.rs | 4 ++++ tests/target/expr.rs | 4 ++++ 3 files changed, 24 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c5f7ccb857b..2b15ff53787 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -268,10 +268,26 @@ pub fn format_expr( ast::RangeLimits::Closed => "...", }; + fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { + match lhs.node { + ast::ExprKind::Lit(ref lit) => { + match lit.node { + ast::LitKind::FloatUnsuffixed(..) => { + context.snippet(lit.span).ends_with('.') + } + _ => false, + } + } + _ => false, + } + } + match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { (Some(ref lhs), Some(ref rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { format!(" {} ", delim) + } else if needs_space_before_range(context, lhs) { + format!(" {}", delim) } else { delim.into() }; diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 3d54e68c409..96e00174af8 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -251,6 +251,10 @@ fn ranges() { let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ... x ; + // #1766 + let x = [0. ..10.0]; + let x = [0. ...10.0]; + a ... b // the expr below won't compile for some reason... diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 3b275d30f4c..de4391d4056 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -315,6 +315,10 @@ fn ranges() { bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ...x; + // #1766 + let x = [0. ..10.0]; + let x = [0. ...10.0]; + a...b // the expr below won't compile for some reason... -- cgit 1.4.1-3-g733a5 From 332cc97986e37ec33ef8f21c75be9feb8470b70d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 24 Jun 2017 01:12:58 +0900 Subject: Use block indent style for struct tuple --- src/items.rs | 42 ++++++++++++++++++++++++----------------- tests/target/enum.rs | 8 ++++---- tests/target/structs.rs | 23 +++++++++++----------- tests/target/trailing_commas.rs | 5 ++++- 4 files changed, 45 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0e8c10ea181..f113dee2c0c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,8 +15,8 @@ use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, trimmed_last_line_width, colon_spaces, mk_sp}; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, list_helper, - DefinitiveListTactic, ListTactic, definitive_tactic}; +use lists::{write_list, itemize_list, definitive_tactic, ListItem, ListFormatting, + SeparatorTactic, DefinitiveListTactic, ListTactic}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, ExprType}; use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; @@ -1152,12 +1152,11 @@ fn format_tuple_struct( let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = try_opt!( - context - .config - .max_width() - .checked_sub(last_line_width(&result)) - ); + let where_budget = context + .config + .max_width() + .checked_sub(last_line_width(&result)) + .unwrap_or(0); try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1197,7 +1196,11 @@ fn format_tuple_struct( } IndentStyle::Block => { ( - ListTactic::HorizontalVertical, + if result.contains('\n') { + ListTactic::Vertical + } else { + ListTactic::HorizontalVertical + }, offset.block_only().block_indent(&context.config), ) } @@ -1233,15 +1236,20 @@ fn format_tuple_struct( context .config .max_width() - .checked_sub(offset.block_only().width() + result.len() + 3) + .checked_sub(offset.block_only().width() + last_line_width(&result) + 3) ); - let body = try_opt!(list_helper( - items, - // TODO budget is wrong in block case - Shape::legacy(body_budget, item_indent), - context.config, - tactic, - )); + + let item_vec: Vec<_> = items.collect(); + let tactic = definitive_tactic(&item_vec, tactic, body_budget); + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: context.config.trailing_comma(), + shape: Shape::indented(item_indent, context.config), + ends_with_newline: false, + config: context.config, + }; + let body = try_opt!(write_list(&item_vec, &fmt)); if context.config.fn_args_layout() == IndentStyle::Visual || !body.contains('\n') { result.push('('); diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 6ff1750ae01..14b9910687d 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -32,7 +32,7 @@ enum Bar { enum LongVariants { First( LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment - VARIANT + VARIANT, ), // This is the second variant Second, @@ -53,7 +53,7 @@ enum X { CreateWebGLPaintTask( Size2D, GLContextAttributes, - IpcSender, usize), String>> + IpcSender, usize), String>>, ), // This is a post comment } @@ -120,7 +120,7 @@ fn nested_enum_test() { usize, usize, usize, - usize + usize, ), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAA */ Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -155,6 +155,6 @@ pub enum CoreResourceMsg { #[serde(deserialize_with = "::hyper_serde::deserialize", serialize_with = "::hyper_serde::serialize")] Cookie, - CookieSource + CookieSource, ), } diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 541abd36c7c..c525c587845 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -43,12 +43,13 @@ struct NewType(Type, OtherType); struct NewInt(pub i32, SomeType /* inline comment */, T /* sup */); -struct Qux<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy> -( +struct Qux< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy, +>( AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, #[AnAttr] @@ -62,7 +63,7 @@ struct Tuple( // Comment 1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, ); // With a where clause and generics. @@ -154,7 +155,7 @@ struct Foo( TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ); struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where @@ -166,7 +167,7 @@ struct Foo( TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ) where T: PartialEq; @@ -176,7 +177,7 @@ struct Foo( // Baz TTTTTTTTTTTTTTTTTTT, // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ); mod m { @@ -191,7 +192,7 @@ mod m { struct Foo( TTTTTTTTTTTTTTTTTTT, /// Qux - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ); struct Issue677 { diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs index c5e6b9525b4..4c4dedd59a0 100644 --- a/tests/target/trailing_commas.rs +++ b/tests/target/trailing_commas.rs @@ -48,7 +48,10 @@ struct Pair< struct TupPair< S, T, ->(S, T) +>( + S, + T, +) where T: P, S: P + Q; -- cgit 1.4.1-3-g733a5 From be5c40cbb97aaa5da147fb3223fe412eb62b8dfb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 24 Jun 2017 19:45:22 +0900 Subject: Handle very long struct --- src/items.rs | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f113dee2c0c..844ebf7f13b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -392,7 +392,8 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span, ) { - self.buffer.push_str(&format_header("enum ", ident, vis)); + let enum_header = format_header("enum ", ident, vis); + self.buffer.push_str(&enum_header); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); @@ -406,6 +407,7 @@ impl<'a> FmtVisitor<'a> { enum_def.variants.is_empty(), self.block_indent, mk_sp(span.lo, body_start), + last_line_width(&enum_header), ).unwrap(); self.buffer.push_str(&generics_str); @@ -1071,11 +1073,19 @@ fn format_struct_struct( fields.is_empty(), offset, mk_sp(span.lo, body_lo), + last_line_width(&result), )) } None => { - if context.config.item_brace_style() == BraceStyle::AlwaysNextLine && - !fields.is_empty() + // 3 = ` {}`, 2 = ` {`. + let overhead = if fields.is_empty() { 3 } else { 2 }; + if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine && + !fields.is_empty()) || + context + .config + .max_width() + .checked_sub(result.len()) + .unwrap_or(0) < overhead { format!("\n{}{{", offset.block_only().to_string(context.config)) } else { @@ -1083,7 +1093,18 @@ fn format_struct_struct( } } }; - result.push_str(&generics_str); + // 1 = `}` + let overhead = if fields.is_empty() { 1 } else { 0 }; + let max_len = context.config.max_width() - offset.width(); + if !generics_str.contains('\n') && result.len() + generics_str.len() + overhead > max_len { + result.push('\n'); + result.push_str(&offset + .block_indent(context.config) + .to_string(context.config)); + result.push_str(&generics_str.trim_left()); + } else { + result.push_str(&generics_str); + } if fields.is_empty() { let snippet = context.snippet(mk_sp(body_lo, span.hi - BytePos(1))); @@ -1147,16 +1168,13 @@ fn format_tuple_struct( let where_clause_str = match generics { Some(generics) => { - let shape = Shape::indented(offset + last_line_width(&header_str), context.config); + let budget = context.budget(last_line_width(&header_str)); + let shape = Shape::legacy(budget, offset); let g_span = mk_sp(span.lo, body_lo); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = context - .config - .max_width() - .checked_sub(last_line_width(&result)) - .unwrap_or(0); + let where_budget = context.budget(last_line_width(&result)); try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1173,6 +1191,18 @@ fn format_tuple_struct( }; if fields.is_empty() { + // 3 = `();` + let used_width = if result.contains('\n') { + last_line_width(&result) + 3 + } else { + offset.width() + result.len() + 3 + }; + if used_width > context.config.max_width() { + result.push('\n'); + result.push_str(&offset + .block_indent(context.config) + .to_string(context.config)) + } result.push('('); let snippet = context.snippet(mk_sp(body_lo, context.codemap.span_before(span, ")"))); if snippet.is_empty() { -- cgit 1.4.1-3-g733a5 From f8586bac2ab83b41956fdb2a22c8a3ea25602a80 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 24 Jun 2017 19:46:36 +0900 Subject: Handle comment at the last element in write_list --- src/expr.rs | 41 +++++++++++++++------ src/items.rs | 113 ++++++++++++--------------------------------------------- src/lists.rs | 36 ++++-------------- src/rewrite.rs | 4 ++ src/utils.rs | 9 +++++ 5 files changed, 72 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dff1521f14a..4bea5f4c0e1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -16,12 +16,12 @@ use {Indent, Shape, Spanned}; use codemap::SpanUtils; use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic, ListItem, format_item_list, struct_lit_shape, + DefinitiveListTactic, definitive_tactic, ListItem, struct_lit_shape, struct_lit_tactic, shape_for_tactic, struct_lit_formatting}; use string::{StringFormat, rewrite_string}; use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, - colon_spaces, contains_skip, mk_sp, last_line_extendable}; + colon_spaces, contains_skip, mk_sp, last_line_extendable, paren_overhead}; use visitor::FmtVisitor; use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; @@ -2217,7 +2217,7 @@ where context.config.trailing_comma() }, shape: shape, - ends_with_newline: false, + ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, config: context.config, }; @@ -2436,14 +2436,6 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l } } -fn paren_overhead(context: &RewriteContext) -> usize { - if context.config.spaces_within_parens() { - 4 - } else { - 2 - } -} - pub fn wrap_args_with_parens( context: &RewriteContext, args_str: &str, @@ -2813,7 +2805,21 @@ where list_lo, span.hi - BytePos(1), ); - let list_str = try_opt!(format_item_list(items, nested_shape, context.config)); + let item_vec: Vec<_> = items.collect(); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + nested_shape.width, + ); + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + shape: shape, + ends_with_newline: false, + config: context.config, + }; + let list_str = try_opt!(write_list(&item_vec, &fmt)); if context.config.spaces_within_parens() && list_str.len() > 0 { Some(format!("( {} )", list_str)) @@ -3023,3 +3029,14 @@ impl<'a> ToExpr for TuplePatField<'a> { can_be_overflowed_pat(context, self, len) } } + +impl<'a> ToExpr for ast::StructField { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + #[allow(unused_variables)] + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + false + } +} diff --git a/src/items.rs b/src/items.rs index 844ebf7f13b..aa19e4238a5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,9 +15,10 @@ use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, trimmed_last_line_width, colon_spaces, mk_sp}; -use lists::{write_list, itemize_list, definitive_tactic, ListItem, ListFormatting, - SeparatorTactic, DefinitiveListTactic, ListTactic}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, ExprType}; +use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, + DefinitiveListTactic, ListTactic, definitive_tactic}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_call_inner, ExprType}; use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; use visitor::FmtVisitor; use rewrite::{Rewrite, RewriteContext}; @@ -1216,91 +1217,19 @@ fn format_tuple_struct( } result.push(')'); } else { - let (tactic, item_indent) = match context.config.fn_args_layout() { - IndentStyle::Visual => { - // 1 = `(` - ( - ListTactic::HorizontalVertical, - offset.block_only() + result.len() + 1, - ) - } - IndentStyle::Block => { - ( - if result.contains('\n') { - ListTactic::Vertical - } else { - ListTactic::HorizontalVertical - }, - offset.block_only().block_indent(&context.config), - ) - } - }; // 3 = `();` - let item_budget = try_opt!( - context - .config - .max_width() - .checked_sub(item_indent.width() + 3) - ); - - let items = itemize_list( - context.codemap, - fields.iter(), - ")", - |field| { - // Include attributes and doc comments, if present - if !field.attrs.is_empty() { - field.attrs[0].span.lo - } else { - field.span.lo - } - }, - |field| field.ty.span.hi, - |field| { - rewrite_struct_field(context, field, Shape::legacy(item_budget, item_indent), 0) - }, - context.codemap.span_after(span, "("), - span.hi, - ); - let body_budget = try_opt!( - context - .config - .max_width() - .checked_sub(offset.block_only().width() + last_line_width(&result) + 3) + let body = try_opt!( + rewrite_call_inner( + context, + "", + &fields.iter().map(|field| field).collect::>()[..], + span, + Shape::legacy(context.budget(last_line_width(&result) + 3), offset), + context.config.fn_call_width(), + false, + ).ok() ); - - let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic(&item_vec, tactic, body_budget); - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: context.config.trailing_comma(), - shape: Shape::indented(item_indent, context.config), - ends_with_newline: false, - config: context.config, - }; - let body = try_opt!(write_list(&item_vec, &fmt)); - - if context.config.fn_args_layout() == IndentStyle::Visual || !body.contains('\n') { - result.push('('); - if context.config.spaces_within_parens() && body.len() > 0 { - result.push(' '); - } - - result.push_str(&body); - - if context.config.spaces_within_parens() && body.len() > 0 { - result.push(' '); - } - result.push(')'); - } else { - result.push_str("(\n"); - result.push_str(&item_indent.to_string(&context.config)); - result.push_str(&body); - result.push('\n'); - result.push_str(&offset.block_only().to_string(&context.config)); - result.push(')'); - } + result.push_str(&body); } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && @@ -2422,7 +2351,7 @@ fn rewrite_generics( span: Span, ) -> Option { let g_shape = try_opt!(generics_shape_from_config(context.config, shape, 0)); - let one_line_width = try_opt!(shape.width.checked_sub(2)); + let one_line_width = shape.width.checked_sub(2).unwrap_or(0); rewrite_generics_inner(context, generics, g_shape, one_line_width, span).or_else(|| { rewrite_generics_inner(context, generics, g_shape, 0, span) }) @@ -2497,8 +2426,11 @@ where { let item_vec = items.collect::>(); + let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, one_line_budget); + let ends_with_newline = context.config.generics_indent() == IndentStyle::Block && + tactic == DefinitiveListTactic::Vertical; let fmt = ListFormatting { - tactic: definitive_tactic(&item_vec, ListTactic::HorizontalVertical, one_line_budget), + tactic: tactic, separator: ",", trailing_separator: if context.config.generics_indent() == IndentStyle::Visual { SeparatorTactic::Never @@ -2506,7 +2438,7 @@ where context.config.trailing_comma() }, shape: shape, - ends_with_newline: false, + ends_with_newline: ends_with_newline, config: context.config, }; @@ -2735,8 +2667,9 @@ fn format_generics( force_same_line_brace: bool, offset: Indent, span: Span, + used_width: usize, ) -> Option { - let shape = Shape::indented(offset, context.config); + let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); if !generics.where_clause.predicates.is_empty() || result.contains('\n') { diff --git a/src/lists.rs b/src/lists.rs index d6cb00b55cd..5e3d00076f7 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -14,7 +14,7 @@ use std::iter::Peekable; use syntax::codemap::{CodeMap, BytePos}; use {Indent, Shape}; -use comment::{FindUncommented, rewrite_comment, find_comment_end}; +use comment::{find_comment_end, rewrite_comment, FindUncommented}; use config::{Config, IndentStyle}; use rewrite::RewriteContext; use utils::mk_sp; @@ -68,31 +68,6 @@ pub struct ListFormatting<'a> { pub config: &'a Config, } -pub fn format_item_list(items: I, shape: Shape, config: &Config) -> Option -where - I: Iterator, -{ - list_helper(items, shape, config, ListTactic::HorizontalVertical) -} - -pub fn list_helper(items: I, shape: Shape, config: &Config, tactic: ListTactic) -> Option -where - I: Iterator, -{ - let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic(&item_vec, tactic, shape.width); - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - shape: shape, - ends_with_newline: false, - config: config, - }; - - write_list(&item_vec, &fmt) -} - impl AsRef for ListItem { fn as_ref(&self) -> &ListItem { self @@ -118,10 +93,13 @@ impl ListItem { .map_or(false, |s| s.contains('\n')) } - pub fn has_line_pre_comment(&self) -> bool { + pub fn has_comment(&self) -> bool { self.pre_comment .as_ref() - .map_or(false, |comment| comment.starts_with("//")) + .map_or(false, |comment| comment.starts_with("//")) || + self.post_comment + .as_ref() + .map_or(false, |comment| comment.starts_with("//")) } pub fn from_str>(s: S) -> ListItem { @@ -150,7 +128,7 @@ where let pre_line_comments = items .clone() .into_iter() - .any(|item| item.as_ref().has_line_pre_comment()); + .any(|item| item.as_ref().has_comment()); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, diff --git a/src/rewrite.rs b/src/rewrite.rs index 5c1236104b5..6a7167537c9 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -45,4 +45,8 @@ impl<'a> RewriteContext<'a> { pub fn use_block_indent(&self) -> bool { self.config.fn_call_style() == IndentStyle::Block || self.use_block } + + pub fn budget(&self, used_width: usize) -> usize { + self.config.max_width().checked_sub(used_width).unwrap_or(0) + } } diff --git a/src/utils.rs b/src/utils.rs index dc5dee6ba0d..bc46316d39b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -393,6 +393,15 @@ pub fn colon_spaces(before: bool, after: bool) -> &'static str { } } +#[inline] +pub fn paren_overhead(context: &RewriteContext) -> usize { + if context.config.spaces_within_parens() { + 4 + } else { + 2 + } +} + #[test] fn bin_search_test() { let closure = |i| match i { -- cgit 1.4.1-3-g733a5 From 6a7f866cfececbdb1aeea9d654e42aecfc8e4bca Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 24 Jun 2017 19:49:01 +0900 Subject: Format source codes --- src/expr.rs | 3 +- src/file_lines.rs | 4 +- src/items.rs | 5 +++ .../configs-struct_field_align_threshold-20.rs | 48 ++++++++++++++-------- tests/target/macros.rs | 2 +- tests/target/multiple.rs | 2 +- tests/target/paths.rs | 5 ++- tests/target/struct_tuple_visual.rs | 4 +- tests/target/structs.rs | 23 +++++++++-- tests/target/trailing_commas.rs | 5 +-- 10 files changed, 69 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4bea5f4c0e1..1696577f023 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -3035,8 +3035,7 @@ impl<'a> ToExpr for ast::StructField { None } - #[allow(unused_variables)] - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { false } } diff --git a/src/file_lines.rs b/src/file_lines.rs index dad7d0b061a..7df4dbb7399 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -167,7 +167,9 @@ impl FileLines { } /// FileLines files iterator. -pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, String, Vec>>); +pub struct Files<'a>( + Option<::std::collections::hash_map::Keys<'a, String, Vec>>, +); impl<'a> iter::Iterator for Files<'a> { type Item = &'a String; diff --git a/src/items.rs b/src/items.rs index aa19e4238a5..a70d72e7b26 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1419,6 +1419,11 @@ fn rewrite_struct_field_type( .map(|ty| format!("{}{}", spacing, ty)) } +impl Rewrite for ast::StructField { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_struct_field(context, self, shape, 0) + } +} pub fn rewrite_struct_field( context: &RewriteContext, diff --git a/tests/target/configs-struct_field_align_threshold-20.rs b/tests/target/configs-struct_field_align_threshold-20.rs index db3458bda15..509bcbf6d64 100644 --- a/tests/target/configs-struct_field_align_threshold-20.rs +++ b/tests/target/configs-struct_field_align_threshold-20.rs @@ -73,14 +73,19 @@ struct Bar; struct NewType(Type, OtherType); -struct NewInt(pub i32, SomeType /* inline comment */, T /* sup */); - -struct Qux<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy> -( +struct NewInt( + pub i32, + SomeType, // inline comment + T, // sup +); + +struct Qux< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy, +>( AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, #[AnAttr] @@ -94,7 +99,7 @@ struct Tuple( // Comment 1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, ); // With a where clause and generics. @@ -139,7 +144,10 @@ struct Baz { } // Will this be a one-liner? -struct Tuple(A /* Comment */, B); +struct Tuple( + A, // Comment + B, +); pub struct State time::Timespec> { now: F, @@ -186,19 +194,27 @@ struct Foo( TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) +struct Foo( + TTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, +) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTTTT, +) where T: PartialEq; struct Foo( TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ) where T: PartialEq; @@ -208,7 +224,7 @@ struct Foo( // Baz TTTTTTTTTTTTTTTTTTT, // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ); mod m { @@ -223,7 +239,7 @@ mod m { struct Foo( TTTTTTTTTTTTTTTTTTT, /// Qux - UUUUUUUUUUUUUUUUUUU + UUUUUUUUUUUUUUUUUUU, ); struct Issue677 { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index eb95fe4758c..1f482075df4 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -29,7 +29,7 @@ fn main() { kaas!( // comments a, // post macro - b /* another */ + b // another ); trailingcomma!(a, b, c,); diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 9e5785dc241..d8dea8896f2 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -40,7 +40,7 @@ where fn baz< 'a: 'b, // comment on 'a - T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, /* comment on T */ + T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, // comment on T >( a: A, b: B, // comment on b diff --git a/tests/target/paths.rs b/tests/target/paths.rs index 9b48dd9a470..0d2ba797eb7 100644 --- a/tests/target/paths.rs +++ b/tests/target/paths.rs @@ -14,7 +14,10 @@ fn main() { supports_clipboard, ); - Quux::::some_func(); + Quux::< + ParamOne, // Comment 1 + ParamTwo, // Comment 2 + >::some_func(); <*mut JSObject>::relocate(entry); diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs index fa49c4f61a4..e63bc2c47c2 100644 --- a/tests/target/struct_tuple_visual.rs +++ b/tests/target/struct_tuple_visual.rs @@ -10,7 +10,7 @@ fn foo() { // Comment foo(), // Comment // Comment - bar(), /* Comment */ + bar(), // Comment ); Foo(Bar, f()); @@ -24,7 +24,7 @@ fn foo() { Baz( xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - zzzzz, /* test */ + zzzzz, // test ); A( diff --git a/tests/target/structs.rs b/tests/target/structs.rs index c525c587845..dcb21bb195b 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -41,7 +41,11 @@ struct Bar; struct NewType(Type, OtherType); -struct NewInt(pub i32, SomeType /* inline comment */, T /* sup */); +struct NewInt( + pub i32, + SomeType, // inline comment + T, // sup +); struct Qux< 'a, @@ -108,7 +112,10 @@ struct Baz { } // Will this be a one-liner? -struct Tuple(A /* Comment */, B); +struct Tuple( + A, // Comment + B, +); pub struct State time::Timespec> { now: F, @@ -157,10 +164,18 @@ struct Foo( TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU, ); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) +struct Foo( + TTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, +) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTTTT, +) where T: PartialEq; struct Foo( diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs index 4c4dedd59a0..93fcc0f2cb1 100644 --- a/tests/target/trailing_commas.rs +++ b/tests/target/trailing_commas.rs @@ -48,10 +48,7 @@ struct Pair< struct TupPair< S, T, ->( - S, - T, -) +>(S, T,) where T: P, S: P + Q; -- cgit 1.4.1-3-g733a5 From 101df143cfd60fcf5132aeb579da43684b32c509 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Jul 2017 18:25:50 +0900 Subject: Refactor rewrite_static --- src/items.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0e8c10ea181..bbe5438a01f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1531,22 +1531,23 @@ pub fn rewrite_static( span: Span, context: &RewriteContext, ) -> Option { - let type_annotation_spacing = type_annotation_spacing(context.config); + let colon = colon_spaces( + context.config.space_before_type_annotation(), + context.config.space_after_type_annotation_colon(), + ); let prefix = format!( - "{}{} {}{}{}:{}", + "{}{} {}{}{}", format_visibility(vis), prefix, format_mutability(mutability), ident, - type_annotation_spacing.0, - type_annotation_spacing.1 + colon, ); // 2 = " =".len() let ty_str = try_opt!(ty.rewrite( context, - Shape::legacy( - context.config.max_width() - offset.block_indent - prefix.len() - 2, - offset.block_only(), + try_opt!( + Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2) ), )); @@ -1560,21 +1561,11 @@ pub fn rewrite_static( expr, Shape::legacy(remaining_width, offset.block_only()), ).and_then(|res| { - recover_comment_removed( - res, - span, - context, - Shape { - width: context.config.max_width(), - indent: offset, - offset: offset.alignment, - }, - ) + recover_comment_removed(res, span, context, Shape::indented(offset, context.config)) }) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { - let lhs = format!("{}{};", prefix, ty_str); - Some(lhs) + Some(format!("{}{};", prefix, ty_str)) } } -- cgit 1.4.1-3-g733a5 From 0237347abcdcb8a173fe144d91673952530c785c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Jul 2017 18:30:11 +0900 Subject: Update heuristic in rewrite_assign_rhs Put the rhs of assignement on the next line when putting next to `lhs = ` will cause rhs to go multi line, but putting on the next line makes it fits in a single line. --- src/expr.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dff1521f14a..90694226113 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2937,26 +2937,21 @@ pub fn rewrite_assign_rhs>( let orig_shape = try_opt!(shape.offset_left(last_line_width + 1)); let rhs = ex.rewrite(context, orig_shape); - fn count_line_breaks(src: &str) -> usize { - src.chars().filter(|&x| x == '\n').count() - } - match rhs { - Some(ref new_str) if count_line_breaks(new_str) < 2 => { + Some(ref new_str) if !new_str.contains('\n') => { result.push(' '); result.push_str(new_str); } _ => { - // Expression did not fit on the same line as the identifier or is - // at least three lines big. Try splitting the line and see - // if that works better. + // Expression did not fit on the same line as the identifier. + // Try splitting the line and see if that works better. let new_shape = try_opt!(shape.block_left(context.config.tab_spaces())); let new_rhs = ex.rewrite(context, new_shape); // FIXME: DRY! match (rhs, new_rhs) { (Some(ref orig_rhs), Some(ref replacement_rhs)) - if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 => { + if prefer_next_line(orig_rhs, replacement_rhs) => { result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); result.push_str(replacement_rhs); } @@ -2976,6 +2971,16 @@ pub fn rewrite_assign_rhs>( Some(result) } +fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { + + fn count_line_breaks(src: &str) -> usize { + src.chars().filter(|&x| x == '\n').count() + } + + !next_line_rhs.contains('\n') || + count_line_breaks(orig_rhs) > count_line_breaks(next_line_rhs) + 1 +} + fn rewrite_expr_addrof( context: &RewriteContext, mutability: ast::Mutability, -- cgit 1.4.1-3-g733a5 From cb48435ff372d6b7970b16b53a1e5a6d446fe7b5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Jul 2017 18:31:37 +0900 Subject: Format source codes --- src/chains.rs | 4 ++-- src/expr.rs | 12 ++++++------ src/items.rs | 8 ++++---- src/lists.rs | 4 ++-- src/modules.rs | 4 ++-- tests/source/static.rs | 3 +++ tests/system.rs | 12 ++++++------ tests/target/expr.rs | 20 ++++++++++---------- tests/target/long_field_access.rs | 4 ++-- tests/target/static.rs | 8 ++++++-- tests/target/type-ascription.rs | 8 ++++---- 11 files changed, 47 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index fb26fb2ff7d..e4ad0d82fd4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -186,8 +186,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let almost_total = rewrites[..last_non_try_index] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); - let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + - parent_rewrite.len(); + let one_line_len = + rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); let one_line_budget = min(shape.width, context.config.chain_one_line_max()); let veto_single_line = if one_line_len > one_line_budget { diff --git a/src/expr.rs b/src/expr.rs index 90694226113..1647cf5e357 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -954,8 +954,8 @@ fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Opt } _ => { to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { - let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + let alt_block_sep = + String::from("\n") + &shape.indent.block_only().to_string(context.config); control_flow .rewrite_cond(context, shape, &alt_block_sep) .and_then(|rw| Some(rw.0)) @@ -1299,8 +1299,8 @@ impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { debug!("ControlFlow::rewrite {:?} {:?}", self, shape); - let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + let alt_block_sep = + String::from("\n") + &shape.indent.block_only().to_string(context.config); let (cond_str, used_width) = try_opt!(self.rewrite_cond(context, shape, &alt_block_sep)); // If `used_width` is 0, it indicates that whole control flow is written in a single line. if used_width == 0 { @@ -1723,8 +1723,8 @@ impl Rewrite for ast::Arm { extend &= context.use_block_indent(); let comma = arm_comma(&context.config, body); - let alt_block_sep = String::from("\n") + - &shape.indent.block_only().to_string(context.config); + let alt_block_sep = + String::from("\n") + &shape.indent.block_only().to_string(context.config); let pat_width = extra_offset(&pats_str, shape); // Let's try and get the arm body on the same line as the condition. diff --git a/src/items.rs b/src/items.rs index bbe5438a01f..42526fc9b13 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1952,8 +1952,8 @@ fn rewrite_fn_base( generics_str.contains('\n'), )); - let multi_line_arg_str = arg_str.contains('\n') || - arg_str.chars().last().map_or(false, |c| c == ','); + let multi_line_arg_str = + arg_str.contains('\n') || arg_str.chars().last().map_or(false, |c| c == ','); let put_args_in_block = match context.config.fn_args_layout() { IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'), @@ -2339,8 +2339,8 @@ fn compute_budgets_for_args( if one_line_budget > 0 { // 4 = "() {".len() - let multi_line_overhead = indent.width() + result.len() + - if newline_brace { 2 } else { 4 }; + let multi_line_overhead = + indent.width() + result.len() + if newline_brace { 2 } else { 4 }; let multi_line_budget = try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); diff --git a/src/lists.rs b/src/lists.rs index d6cb00b55cd..63e9e360ade 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -353,8 +353,8 @@ where .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); - let has_pre_comment = trimmed_pre_snippet.contains("//") || - trimmed_pre_snippet.contains("/*"); + let has_pre_comment = + trimmed_pre_snippet.contains("//") || trimmed_pre_snippet.contains("/*"); let pre_comment = if has_pre_comment { Some(trimmed_pre_snippet.to_owned()) } else { diff --git a/src/modules.rs b/src/modules.rs index 5b5050d51c9..c8275520ca1 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -47,8 +47,8 @@ fn list_submodules<'a>( for item in &module.items { if let ast::ItemKind::Mod(ref sub_mod) = item.node { if !utils::contains_skip(&item.attrs) { - let is_internal = codemap.span_to_filename(item.span) == - codemap.span_to_filename(sub_mod.inner); + let is_internal = + codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); let dir_path = if is_internal { search_dir.join(&item.ident.to_string()) } else { diff --git a/tests/source/static.rs b/tests/source/static.rs index a571b5f11f6..b51c56d1205 100644 --- a/tests/source/static.rs +++ b/tests/source/static.rs @@ -16,3 +16,6 @@ pub const test: &Type = &val; impl Color { pub const WHITE: u32 = 10; } + +// #1391 +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; diff --git a/tests/system.rs b/tests/system.rs index 26b1edaff5b..b43bb081921 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -147,8 +147,8 @@ fn self_tests() { fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); let config = Config::default(); - let (error_summary, file_map, _report) = format_input::(input, &config, None) - .unwrap(); + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); assert!(error_summary.has_no_errors()); for &(ref file_name, ref text) in &file_map { if file_name == "stdin" { @@ -164,8 +164,8 @@ fn format_lines_errors_are_reported() { let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let config = Config::default(); - let (error_summary, _file_map, _report) = format_input::(input, &config, None) - .unwrap(); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); } @@ -242,8 +242,8 @@ fn read_config(filename: &str) -> Config { fn format_file>(filename: P, config: &Config) -> (FileMap, FormatReport) { let input = Input::File(filename.into()); - let (_error_summary, file_map, report) = format_input::(input, &config, None) - .unwrap(); + let (_error_summary, file_map, report) = + format_input::(input, &config, None).unwrap(); return (file_map, report); } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index de4391d4056..4d75239f357 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -7,11 +7,11 @@ fn foo() -> bool { let referenced = &5; let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + - BBBBBBBBBBBBBBBBB + b + c); + let very_long_variable_name = + (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - let is_internalxxxx = self.codemap.span_to_filename(s) == - self.codemap.span_to_filename(m.inner); + let is_internalxxxx = + self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; @@ -84,8 +84,8 @@ fn foo() -> bool { } fn bar() { - let range = (111111111 + 333333333333333333 + 1111 + 400000000000000000).. - (2222 + 2333333333333333); + let range = + (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + 2333333333333333); let another_range = 5..some_func(a, b /* comment */); @@ -274,8 +274,8 @@ fn casts() { } let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - let slightly_longer_trait = yyyyyyyyy + - yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; + let slightly_longer_trait = + yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; } fn indices() { @@ -311,8 +311,8 @@ fn issue767() { fn ranges() { let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; let z = ...x; // #1766 diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs index e4efd86b7f9..349d2c2f639 100644 --- a/tests/target/long_field_access.rs +++ b/tests/target/long_field_access.rs @@ -1,4 +1,4 @@ fn f() { - block_flow.base.stacking_relative_position_of_display_port = self.base - .stacking_relative_position_of_display_port; + block_flow.base.stacking_relative_position_of_display_port = + self.base.stacking_relative_position_of_display_port; } diff --git a/tests/target/static.rs b/tests/target/static.rs index 12a8eba111b..30a549cc732 100644 --- a/tests/target/static.rs +++ b/tests/target/static.rs @@ -1,5 +1,5 @@ -const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | - FILE_READ_EA | SYNCHRONIZE; +const FILE_GENERIC_READ: DWORD = + STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; static boolnames: &'static [&'static str] = &[ "bw", @@ -58,3 +58,7 @@ pub const test: &Type = &val; impl Color { pub const WHITE: u32 = 10; } + +// #1391 +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = + 0 as usize; diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index f99d524eb2e..a2f082ba4b4 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -1,9 +1,9 @@ fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: - SomeTrait; + let xxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let xxxxxxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; -- cgit 1.4.1-3-g733a5 From d613f75676d50acce7f65fc5e54c9903e6100c4d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Jul 2017 19:19:54 +0900 Subject: Use correct one line budget for array in Block indent style --- src/expr.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dff1521f14a..81168b3618c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -464,8 +464,16 @@ where 1 // "[" }; - let nested_shape = match context.config.array_layout() { - IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), + let mut nested_shape = match context.config.array_layout() { + IndentStyle::Block => { + try_opt!( + shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1) + ) + } IndentStyle::Visual => { try_opt!( shape -- cgit 1.4.1-3-g733a5 From 8e8e7a4215b0d76e661f8c79e41c84ef6a8029e5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Jul 2017 22:51:52 +0900 Subject: Add array_horizontal_layout_threshold option --- Configurations.md | 33 +++++++ src/config.rs | 2 + src/expr.rs | 14 ++- ...nfigs-array_horizontal_layout_threshold-1000.rs | 107 +++++++++++++++++++++ ...nfigs-array_horizontal_layout_threshold-1000.rs | 95 ++++++++++++++++++ 5 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 tests/source/configs-array_horizontal_layout_threshold-1000.rs create mode 100644 tests/target/configs-array_horizontal_layout_threshold-1000.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 5de757a9168..cbf41b0f537 100644 --- a/Configurations.md +++ b/Configurations.md @@ -14,6 +14,39 @@ reorder_imported_names = true Below you find a detailed visual guide on all the supported configuration options of rustfmt: +## `array_horizontal_layout_threshold` + +How many elements array must have before rustfmt uses horizontal layout. +Use this option to prevent a huge array from being vertically formatted. + +- **Default value**: `0` +- **Possible values**: any positive integer + +**Note:** A value of `0` results in [`array_layout`](#array_layout) being applied regardless of a line's width. + +#### `0`: + +```rust +// Each element will be placed on its own line. +let a = vec![ + 0, + 1, + 2, + 3, + 4, + ... + 999, + 1000, +]; +``` + +#### `1000`: +```rust +// Each element will be placed on the same line as much as possible. +let a = vec![0, 1, 2, 3, 4, ... + ..., 999, 1000]; +``` + ## `array_layout` Indent on arrays diff --git a/src/config.rs b/src/config.rs index bc00fd176cf..5b2f77ca668 100644 --- a/src/config.rs +++ b/src/config.rs @@ -533,6 +533,8 @@ create_config! { array_layout: IndentStyle, IndentStyle::Block, "Indent on arrays"; array_width: usize, 60, "Maximum width of an array literal before falling back to vertical formatting"; + array_horizontal_layout_threshold: usize, 0, + "How many elements array must have before rustfmt uses horizontal layout."; type_punctuation_density: TypeDensity, TypeDensity::Wide, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; where_style: Style, Style::Rfc, "Overall strategy for where clauses"; diff --git a/src/expr.rs b/src/expr.rs index 81168b3618c..8170f32728d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -506,7 +506,7 @@ where .iter() .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - let tactic = match context.config.array_layout() { + let mut tactic = match context.config.array_layout() { IndentStyle::Block => { // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { @@ -530,6 +530,18 @@ where } } }; + if context.config.array_horizontal_layout_threshold() > 0 && + items.len() > context.config.array_horizontal_layout_threshold() + { + tactic = DefinitiveListTactic::Mixed; + if context.config.array_layout() == IndentStyle::Block { + nested_shape = try_opt!( + shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2) + ); + } + } let fmt = ListFormatting { tactic: tactic, diff --git a/tests/source/configs-array_horizontal_layout_threshold-1000.rs b/tests/source/configs-array_horizontal_layout_threshold-1000.rs new file mode 100644 index 00000000000..c1fb8e92872 --- /dev/null +++ b/tests/source/configs-array_horizontal_layout_threshold-1000.rs @@ -0,0 +1,107 @@ +// rustfmt-array_horizontal_layout_threshold: 1000 + +const ARRAY: [u8; 2048] = + [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, + 21, 18, 37, 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, + 87, 69, 42, 38, 25, 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, + 29, 111, 120, 26, 0, 78, 36, 115, 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, + 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, 124, 124, 102, 74, 35, 9, 83, 22, 121, + 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, 54, 17, 58, 105, 13, 96, 61, 99, + 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, 56, 5, 114, 11, 25, 16, 97, + 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, 58, 103, 2, 88, + 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, 97, + 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, + 9, 21, 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, + 61, 8, 124, 110, 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, + 44, 73, 82, 10, 49, 95, 72, 89, 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, + 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, 31, 33, 84, 72, 128, 91, 3, 84, 92, + 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, 43, 66, 21, 90, 31, 102, 45, + 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, 54, 11, 103, 45, + 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, 93, + 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, + 92, 105, 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, + 52, 46, 81, 28, 46, 82, 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, + 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, + 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, 48, 51, 54, 56, 105, 90, 50, 67, + 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, 75, 29, 15, 15, 47, 33, + 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, 86, 101, + 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, + 36, 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, + 62, 86, 104, 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, + 23, 68, 115, 106, 15, 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, + 88, 8, 32, 3, 63, 77, 14, 86, 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, + 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, 67, 42, 109, 30, 93, 40, 113, 13, 85, + 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, 102, 25, 4, 113, 84, 63, + 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, 81, 38, 55, 82, + 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, 123, + 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, + 49, 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, + 83, 36, 38, 71, 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, + 49, 86, 7, 84, 40, 42, 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, + 50, 42, 34, 122, 116, 75, 31, 109, 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, + 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, 3, 18, 110, 84, 70, 23, 84, 23, + 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, 86, 67, 78, 126, 86, + 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, 86, 34, 91, + 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, 102, + 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, + 58, 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, + 115, 44, 4, 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, + 20, 44, 46, 4, 116, 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, + 10, 36, 68, 94, 40, 87, 74, 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, + 40, 97, 43, 58, 16, 120, 74, 52, 42, 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, + 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, 71, 92, 70, 57, 37, 42, 21, 83, 2, + 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, 52, 80, 94, 46, 18, 68, 72, + 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, 81, 45, 79, 121, + 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, 115, 29, + 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, + 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, + 101, 68, 26, 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, + 54, 69, 34, 22, 21, 54, 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, + 65, 40, 34, 12, 6, 127, 32, 90, 62, 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, + 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, 45, 85, 40, 3, 114, 36, 23, 109, 118, + 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, 47, 126, 118, 105, 10, 59, 12, + 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, 106, 110, 49, 50, 20, + 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, 79, 85, + 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, + 126, 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, + 116, 114, 119, 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, + 92, 70, 49, 59, 51, 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, + 2, 98, 47, 25, 100, 37, 42, 115, 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, + 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, 16, 113, 68, 20, 76, 99, 93, 121, 18, + 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, 6, 96, 12, 100, 33, 5, + 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, 114, 84, + 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, + 110, 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, + 115, 47, 80, 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, + 81, 76, 66, 17, 108, 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, + 12, 16, 114, 50, 49, 12, 3, 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, + 27, 28, 24, 46, 101, 10, 104, 51, 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, + 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, 56, 80, 20, 117, 65, 53, 58, 66, 5, + 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, 31, 80, 29, 12, 115, 75, + 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, 98, 118, 26, + 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, + 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, + 109, 109, 97, 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, + 81, 111, 6, 11, 28, 5, 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, + 29, 60, 91, 72, 94, 15, 31, 98, 47, 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, + 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, 103, 88, 22, 107, 38, 39, 100, + 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, 19, 59, 87, 128, 16, 46, + 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, 100, 41, 51, + 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, + 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, + 16, 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, + 91, 16, 46, 117, 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, + 5, 21, 81, 43, 58, 61, 59, 39, 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, + 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, + 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, 32, 3, 2, 117, 41, 80, 96, 122, + 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, 22, 68, 39, 119, + 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, 115, + 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, + 125, 1, 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, + 47, 21, 103, 63, 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, + 104, 43, 73, 17, 111, 36, 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, + 54, 71, 38, 58, 86, 124, 3, 103, 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, + 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, + 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, 45, 97, 8, 39, 125, 9, 22, 91, + 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, 106, 32, 105, 27, 0, 56, + 66, 51, 4, 94, 72, 117, 69]; diff --git a/tests/target/configs-array_horizontal_layout_threshold-1000.rs b/tests/target/configs-array_horizontal_layout_threshold-1000.rs new file mode 100644 index 00000000000..cadb9b09464 --- /dev/null +++ b/tests/target/configs-array_horizontal_layout_threshold-1000.rs @@ -0,0 +1,95 @@ +// rustfmt-array_horizontal_layout_threshold: 1000 + +const ARRAY: [u8; 2048] = + [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, + 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, 87, 69, 42, 38, 25, + 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, 29, 111, 120, 26, 0, 78, 36, 115, + 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, + 124, 124, 102, 74, 35, 9, 83, 22, 121, 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, + 54, 17, 58, 105, 13, 96, 61, 99, 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, + 56, 5, 114, 11, 25, 16, 97, 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, + 58, 103, 2, 88, 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, + 97, 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, 9, 21, + 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, 61, 8, 124, 110, + 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, 44, 73, 82, 10, 49, 95, 72, 89, + 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, + 31, 33, 84, 72, 128, 91, 3, 84, 92, 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, + 43, 66, 21, 90, 31, 102, 45, 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, + 54, 11, 103, 45, 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, + 93, 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, 92, 105, + 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, 52, 46, 81, 28, 46, 82, + 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, + 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, + 48, 51, 54, 56, 105, 90, 50, 67, 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, + 75, 29, 15, 15, 47, 33, 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, + 86, 101, 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, 36, + 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, 62, 86, 104, + 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, 23, 68, 115, 106, 15, + 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, 88, 8, 32, 3, 63, 77, 14, 86, + 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, + 67, 42, 109, 30, 93, 40, 113, 13, 85, 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, + 102, 25, 4, 113, 84, 63, 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, + 81, 38, 55, 82, 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, + 123, 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, 49, + 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, 83, 36, 38, 71, + 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, 49, 86, 7, 84, 40, 42, + 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, 50, 42, 34, 122, 116, 75, 31, 109, + 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, + 3, 18, 110, 84, 70, 23, 84, 23, 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, + 86, 67, 78, 126, 86, 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, + 86, 34, 91, 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, + 102, 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, 58, + 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, 115, 44, 4, + 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, 20, 44, 46, 4, 116, + 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, 10, 36, 68, 94, 40, 87, 74, + 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, 40, 97, 43, 58, 16, 120, 74, 52, 42, + 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, + 71, 92, 70, 57, 37, 42, 21, 83, 2, 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, + 52, 80, 94, 46, 18, 68, 72, 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, + 81, 45, 79, 121, 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, + 115, 29, 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, + 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, 101, 68, 26, + 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, 54, 69, 34, 22, 21, 54, + 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, 65, 40, 34, 12, 6, 127, 32, 90, 62, + 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, + 45, 85, 40, 3, 114, 36, 23, 109, 118, 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, + 47, 126, 118, 105, 10, 59, 12, 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, + 106, 110, 49, 50, 20, 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, + 79, 85, 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, 126, + 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, 116, 114, 119, + 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, 92, 70, 49, 59, 51, + 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, 2, 98, 47, 25, 100, 37, 42, 115, + 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, + 16, 113, 68, 20, 76, 99, 93, 121, 18, 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, + 6, 96, 12, 100, 33, 5, 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, + 114, 84, 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, 110, + 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, 115, 47, 80, + 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, 81, 76, 66, 17, 108, + 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, 12, 16, 114, 50, 49, 12, 3, + 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, 27, 28, 24, 46, 101, 10, 104, 51, + 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, + 56, 80, 20, 117, 65, 53, 58, 66, 5, 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, + 31, 80, 29, 12, 115, 75, 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, + 98, 118, 26, 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, + 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, 109, 109, 97, + 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, 81, 111, 6, 11, 28, 5, + 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, 29, 60, 91, 72, 94, 15, 31, 98, 47, + 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, + 103, 88, 22, 107, 38, 39, 100, 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, + 19, 59, 87, 128, 16, 46, 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, + 100, 41, 51, 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, + 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, 16, + 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, 91, 16, 46, 117, + 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, 5, 21, 81, 43, 58, 61, 59, 39, + 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, + 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, + 32, 3, 2, 117, 41, 80, 96, 122, 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, + 22, 68, 39, 119, 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, + 115, 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, 125, 1, + 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, 47, 21, 103, 63, + 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, 104, 43, 73, 17, 111, 36, + 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, 54, 71, 38, 58, 86, 124, 3, 103, + 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, + 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, + 45, 97, 8, 39, 125, 9, 22, 91, 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, + 106, 32, 105, 27, 0, 56, 66, 51, 4, 94, 72, 117, 69]; -- cgit 1.4.1-3-g733a5 From 2dd8d6d097b52a34991cc032f94be4f03583d0e1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 5 Jul 2017 23:12:58 +0900 Subject: Add Clone trait bound to write_list --- src/expr.rs | 2 +- src/items.rs | 4 ++-- src/lists.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 66813417631..1326d3c41b1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1707,7 +1707,7 @@ impl Rewrite for ast::Arm { ends_with_newline: false, config: context.config, }; - let pats_str = try_opt!(write_list(items, &fmt)); + let pats_str = try_opt!(write_list(&items, &fmt)); let guard_shape = if pats_str.contains('\n') { shape.with_max_width(context.config) diff --git a/src/items.rs b/src/items.rs index 4ae7bcc609a..91bba534924 100644 --- a/src/items.rs +++ b/src/items.rs @@ -478,7 +478,7 @@ impl<'a> FmtVisitor<'a> { config: self.config, }; - let list = try_opt!(write_list(items, &fmt)); + let list = try_opt!(write_list(&items.collect::>(), &fmt)); result.push_str(&list); result.push('\n'); Some(result) @@ -2539,7 +2539,7 @@ fn rewrite_where_clause_rfc_style( ends_with_newline: true, config: context.config, }; - let preds_str = try_opt!(write_list(items, &fmt)); + let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); Some(format!( "{}where\n{}{}", diff --git a/src/lists.rs b/src/lists.rs index bd4c6891c1b..de82f2cd624 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -157,7 +157,7 @@ where // TODO: add unit tests pub fn write_list(items: I, formatting: &ListFormatting) -> Option where - I: IntoIterator, + I: IntoIterator + Clone, T: AsRef, { let tactic = formatting.tactic; -- cgit 1.4.1-3-g733a5 From 1de786a79a4c7eb6b0a19f02271cb056e22c492b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 6 Jul 2017 01:02:37 +0900 Subject: Implement vertical alignment for comments after list structure --- src/lists.rs | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 117 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index de82f2cd624..b0598397517 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -17,7 +17,7 @@ use {Indent, Shape}; use comment::{find_comment_end, rewrite_comment, FindUncommented}; use config::{Config, IndentStyle}; use rewrite::RewriteContext; -use utils::mk_sp; +use utils::{first_line_width, last_line_width, mk_sp}; #[derive(Eq, PartialEq, Debug, Copy, Clone)] /// Formatting tactic for lists. This will be cast down to a @@ -86,8 +86,12 @@ pub struct ListItem { } impl ListItem { + pub fn inner_as_ref(&self) -> &str { + self.item.as_ref().map_or("", |s| &*s) + } + pub fn is_multiline(&self) -> bool { - self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() || + self.inner_as_ref().contains('\n') || self.pre_comment.is_some() || self.post_comment .as_ref() .map_or(false, |s| s.contains('\n')) @@ -167,7 +171,9 @@ where // will be a trailing separator. let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); let mut result = String::new(); + let cloned_items = items.clone(); let mut iter = items.into_iter().enumerate().peekable(); + let mut item_max_width: Option = None; let mut line_len = 0; let indent_str = &formatting.shape.indent.to_string(formatting.config); @@ -238,6 +244,7 @@ where } else { result.push(' '); } + item_max_width = None; } result.push_str(&inner_item[..]); @@ -261,36 +268,60 @@ where } if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { - // 1 = space between item and comment. - let width = formatting - .shape - .width - .checked_sub(item_last_line_width + 1) - .unwrap_or(1); - let mut offset = formatting.shape.indent; - offset.alignment += item_last_line_width + 1; let comment = item.post_comment.as_ref().unwrap(); - - debug!("Width = {}, offset = {:?}", width, offset); - // Use block-style only for the last item or multiline comments. - let block_style = !formatting.ends_with_newline && last || - comment.trim().contains('\n') || - comment.trim().len() > width; - - let formatted_comment = try_opt!(rewrite_comment( + let block_style = !formatting.ends_with_newline && last; + let mut formatted_comment = try_opt!(rewrite_post_comment( + formatting.config, + formatting.shape, comment, + &cloned_items, + inner_item, + i, + &mut item_max_width, + item_last_line_width, + last, block_style, - Shape::legacy(width, offset), - formatting.config, )); if !formatted_comment.starts_with('\n') { - result.push(' '); + let mut comment_alignment = + post_comment_alignment(item_max_width, inner_item.len()); + if first_line_width(&formatted_comment) + last_line_width(&result) + + comment_alignment + 1 > formatting.config.max_width() + { + item_max_width = None; + formatted_comment = try_opt!(rewrite_post_comment( + formatting.config, + formatting.shape, + comment, + &cloned_items, + inner_item, + i, + &mut item_max_width, + item_last_line_width, + last, + block_style, + )); + comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); + } + for _ in 0..(comment_alignment + 1) { + result.push(' '); + } + // An additional space for the missing trailing comma + if last && item_max_width.is_some() && !separate { + result.push(' '); + } + } + if formatted_comment.contains('\n') { + item_max_width = None; } result.push_str(&formatted_comment); + } else { + item_max_width = None; } if !last && tactic == DefinitiveListTactic::Vertical && item.new_lines { + item_max_width = None; result.push('\n'); } } @@ -298,6 +329,71 @@ where Some(result) } +fn rewrite_post_comment( + config: &Config, + shape: Shape, + comment: &str, + cloned_items: &I, + inner_item: &str, + i: usize, + mut item_max_width: &mut Option, + item_last_line_width: usize, + last: bool, + block_style: bool, +) -> Option +where + I: IntoIterator + Clone, + T: AsRef, +{ + if item_max_width.is_none() && !last && !inner_item.contains('\n') { + *item_max_width = Some(max_width_of_item_with_post_comment(cloned_items, i)); + } + let overhead = if let &mut Some(max_width) = item_max_width { + max_width + 2 + } else { + // 1 = space between item and comment. + item_last_line_width + 1 + }; + let width = shape.width.checked_sub(overhead).unwrap_or(1); + let offset = shape.indent + overhead; + + debug!("Width = {}, offset = {:?}", width, offset); + // Use block-style only for the last item or multiline comments. + let block_style = block_style || comment.trim().contains('\n') || comment.trim().len() > width; + + rewrite_comment(comment, block_style, Shape::legacy(width, offset), config) +} + +fn max_width_of_item_with_post_comment(items: &I, i: usize) -> usize +where + I: IntoIterator + Clone, + T: AsRef, +{ + let mut max_width = 0; + let mut first = true; + for item in items.clone().into_iter().skip(i) { + let item = item.as_ref(); + if !first && (item.is_multiline() || !item.post_comment.is_some()) { + return max_width; + } + let inner_item_width = item.inner_as_ref().len(); + if max_width < inner_item_width { + max_width = inner_item_width; + } + if item.new_lines { + return max_width; + } + first = false; + } + max_width +} + +fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { + item_max_width + .and_then(|max_line_width| max_line_width.checked_sub(inner_item_len)) + .unwrap_or(0) +} + pub struct ListItems<'a, I, F1, F2, F3> where I: Iterator, -- cgit 1.4.1-3-g733a5 From 57466dc68799f4c28bae5e7531555334052c3d65 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 6 Jul 2017 01:03:07 +0900 Subject: Format source codes --- src/bin/cargo-fmt.rs | 14 +++++++------- src/expr.rs | 4 +--- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index b4a1b3d5172..95ac1a25bb9 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -142,14 +142,14 @@ fn get_fmt_args() -> Vec { #[derive(Debug)] enum TargetKind { - Lib, // dylib, staticlib, lib - Bin, // bin - Example, // example file - Test, // test file - Bench, // bench file + Lib, // dylib, staticlib, lib + Bin, // bin + Example, // example file + Test, // test file + Bench, // bench file CustomBuild, // build script - ProcMacro, // a proc macro implementation - Other, // plugin,... + ProcMacro, // a proc macro implementation + Other, // plugin,... } impl TargetKind { diff --git a/src/expr.rs b/src/expr.rs index 1326d3c41b1..971bdc21aaa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1298,9 +1298,7 @@ impl<'a> ControlFlow<'a> { label_string, self.keyword, between_kwd_cond_comment.as_ref().map_or( - if pat_expr_string.is_empty() || - pat_expr_string.starts_with('\n') - { + if pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { "" } else { " " -- cgit 1.4.1-3-g733a5 From f7ec959c979b83f125ba9e8c274096c8838e5fa1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Jul 2017 08:51:19 +0900 Subject: Use closure instead of declaring function Take comment overhead into account --- src/lists.rs | 103 ++++++++++++++++++++++++----------------------------------- 1 file changed, 41 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index b0598397517..4f762ea1f37 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -269,19 +269,36 @@ where if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let block_style = !formatting.ends_with_newline && last; - let mut formatted_comment = try_opt!(rewrite_post_comment( - formatting.config, - formatting.shape, - comment, - &cloned_items, - inner_item, - i, - &mut item_max_width, - item_last_line_width, - last, - block_style, - )); + let overhead = last_line_width(&result) + first_line_width(comment.trim()); + + let rewrite_post_comment = |item_max_width: &mut Option| { + if item_max_width.is_none() && !last && !inner_item.contains('\n') { + *item_max_width = Some(max_width_of_item_with_post_comment( + &cloned_items, + i, + overhead, + formatting.config.max_width(), + )); + } + let overhead = if let &mut Some(max_width) = item_max_width { + max_width + 2 + } else { + // 1 = space between item and comment. + item_last_line_width + 1 + }; + let width = formatting.shape.width.checked_sub(overhead).unwrap_or(1); + let offset = formatting.shape.indent + overhead; + let comment_shape = Shape::legacy(width, offset); + + // Use block-style only for the last item or multiline comments. + let block_style = !formatting.ends_with_newline && last || + comment.trim().contains('\n') || + comment.trim().len() > width; + + rewrite_comment(comment, block_style, comment_shape, formatting.config) + }; + + let mut formatted_comment = try_opt!(rewrite_post_comment(&mut item_max_width)); if !formatted_comment.starts_with('\n') { let mut comment_alignment = @@ -290,18 +307,7 @@ where comment_alignment + 1 > formatting.config.max_width() { item_max_width = None; - formatted_comment = try_opt!(rewrite_post_comment( - formatting.config, - formatting.shape, - comment, - &cloned_items, - inner_item, - i, - &mut item_max_width, - item_last_line_width, - last, - block_style, - )); + formatted_comment = try_opt!(rewrite_post_comment(&mut item_max_width)); comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); } for _ in 0..(comment_alignment + 1) { @@ -329,42 +335,12 @@ where Some(result) } -fn rewrite_post_comment( - config: &Config, - shape: Shape, - comment: &str, - cloned_items: &I, - inner_item: &str, +fn max_width_of_item_with_post_comment( + items: &I, i: usize, - mut item_max_width: &mut Option, - item_last_line_width: usize, - last: bool, - block_style: bool, -) -> Option -where - I: IntoIterator + Clone, - T: AsRef, -{ - if item_max_width.is_none() && !last && !inner_item.contains('\n') { - *item_max_width = Some(max_width_of_item_with_post_comment(cloned_items, i)); - } - let overhead = if let &mut Some(max_width) = item_max_width { - max_width + 2 - } else { - // 1 = space between item and comment. - item_last_line_width + 1 - }; - let width = shape.width.checked_sub(overhead).unwrap_or(1); - let offset = shape.indent + overhead; - - debug!("Width = {}, offset = {:?}", width, offset); - // Use block-style only for the last item or multiline comments. - let block_style = block_style || comment.trim().contains('\n') || comment.trim().len() > width; - - rewrite_comment(comment, block_style, Shape::legacy(width, offset), config) -} - -fn max_width_of_item_with_post_comment(items: &I, i: usize) -> usize + overhead: usize, + max_budget: usize, +) -> usize where I: IntoIterator + Clone, T: AsRef, @@ -373,10 +349,13 @@ where let mut first = true; for item in items.clone().into_iter().skip(i) { let item = item.as_ref(); - if !first && (item.is_multiline() || !item.post_comment.is_some()) { + let inner_item_width = item.inner_as_ref().len(); + if !first && + (item.is_multiline() || !item.post_comment.is_some() || + inner_item_width + overhead > max_budget) + { return max_width; } - let inner_item_width = item.inner_as_ref().len(); if max_width < inner_item_width { max_width = inner_item_width; } -- cgit 1.4.1-3-g733a5 From d4c8a176657fcbeb038f86c470b808145bb62a29 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 7 Jul 2017 15:52:23 +0300 Subject: Update rustfmt for ast::ExprKind::MethodCall changes --- src/chains.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index fb26fb2ff7d..c4dbacb0421 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -437,13 +437,22 @@ fn rewrite_method_call_with_overflow( context: &RewriteContext, shape: Shape, ) -> bool { - if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind { + if let &ast::ExprKind::MethodCall(ref segment, ref expressions) = expr_kind { let shape = match shape.shrink_left(almost_total) { Some(b) => b, None => return false, }; + let types = match segment.parameters { + Some(ref params) => { + match **params { + ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + _ => &[], + } + } + _ => &[], + }; let mut last_rewrite = rewrite_method_call( - method_name.node, + segment.identifier, types, expressions, total_span, @@ -466,7 +475,7 @@ fn rewrite_method_call_with_overflow( // is a try! macro, we'll convert it to shorthand when the option is set. fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { match expr.node { - ast::ExprKind::MethodCall(_, _, ref expressions) => { + ast::ExprKind::MethodCall(_, ref expressions) => { Some(convert_try(&expressions[0], context)) } ast::ExprKind::TupField(ref subexpr, _) | @@ -504,8 +513,17 @@ fn rewrite_chain_subexpr( }; match expr.node { - ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) => { - rewrite_method_call(method_name.node, types, expressions, span, context, shape) + ast::ExprKind::MethodCall(ref segment, ref expressions) => { + let types = match segment.parameters { + Some(ref params) => { + match **params { + ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + _ => &[], + } + } + _ => &[], + }; + rewrite_method_call(segment.identifier, types, expressions, span, context, shape) } ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), ast::ExprKind::TupField(ref expr, ref field) => { -- cgit 1.4.1-3-g733a5 From 72b155a9e2798126e48ba441f759ee4166123361 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 02:16:57 +0900 Subject: Implement rhs_overhead method against Shape --- src/expr.rs | 14 +++----------- src/lib.rs | 7 +++++++ 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 971bdc21aaa..4b4596e59d7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -419,11 +419,7 @@ where } Style::Rfc => { // Try to calculate the initial constraint on the right hand side. - let rhs_overhead = context - .config - .max_width() - .checked_sub(shape.used_width() + shape.width) - .unwrap_or(0); + let rhs_overhead = shape.rhs_overhead(context.config); try_opt!( Shape::indented(shape.indent.block_indent(context.config), context.config) .sub_width(rhs_overhead) @@ -2543,12 +2539,8 @@ fn rewrite_index( } // Try putting index on the next line and see if it fits in a single line. - let indent = shape.indent.block_indent(&context.config); - let rhs_overhead = context - .config - .max_width() - .checked_sub(shape.used_width() + shape.width) - .unwrap_or(0); + let indent = shape.indent.block_indent(context.config); + let rhs_overhead = shape.rhs_overhead(context.config); let index_shape = try_opt!(Shape::indented(indent, context.config).offset_left(lbr.len())); let index_shape = try_opt!(index_shape.sub_width(rbr.len() + rhs_overhead)); let new_index_rw = index.rewrite(context, index_shape); diff --git a/src/lib.rs b/src/lib.rs index f0c3ebf49a1..b27a02a17a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -363,6 +363,13 @@ impl Shape { pub fn used_width(&self) -> usize { self.indent.block_indent + self.offset } + + pub fn rhs_overhead(&self, config: &Config) -> usize { + config + .max_width() + .checked_sub(self.used_width() + self.width) + .unwrap_or(0) + } } pub enum ErrorKind { -- cgit 1.4.1-3-g733a5 From b897310d7965455c3ac4d199915f3241d3c4d7d8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 02:18:53 +0900 Subject: Prefer to put the whole pattern of match arm on one line --- src/expr.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4b4596e59d7..b304af8e5cd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1687,14 +1687,14 @@ impl Rewrite for ast::Arm { .collect::>>() ); - let all_simple = pat_strs.iter().all(|p| pat_is_simple(p)); + let all_simple = pat_strs.iter().all(|p| !p.contains('\n')); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let mut tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, pat_shape.width); + if tactic == DefinitiveListTactic::Horizontal && all_simple { + tactic = DefinitiveListTactic::Mixed; + } let fmt = ListFormatting { - tactic: if all_simple { - DefinitiveListTactic::Mixed - } else { - DefinitiveListTactic::Vertical - }, + tactic: tactic, separator: " |", trailing_separator: SeparatorTactic::Never, shape: pat_shape, -- cgit 1.4.1-3-g733a5 From e355c85b424c906cf2e3d3ecda361a2c7d99aad6 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 02:22:15 +0900 Subject: Use rewrite_assign_rhs for rewriting pattern in condition --- src/expr.rs | 74 +++++++++++++++++++------------------------------------------ 1 file changed, 23 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b304af8e5cd..febbeaf09d5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1836,13 +1836,6 @@ impl Rewrite for ast::Arm { } } -// A pattern is simple if it is very short or it is short-ish and just a path. -// E.g. `Foo::Bar` is simple, but `Foo(..)` is not. -fn pat_is_simple(pat_str: &str) -> bool { - pat_str.len() <= 16 || - (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':')) -} - // The `if ...` guard on a match arm. fn rewrite_guard( context: &RewriteContext, @@ -1906,55 +1899,34 @@ fn rewrite_pat_expr( shape: Shape, ) -> Option { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); - let mut pat_string = String::new(); - let mut result = match pat { - Some(pat) => { - let matcher = if matcher.is_empty() { - matcher.to_owned() - } else { - format!("{} ", matcher) - }; - let pat_shape = - try_opt!(try_opt!(shape.offset_left(matcher.len())).sub_width(connector.len())); - pat_string = try_opt!(pat.rewrite(context, pat_shape)); - format!("{}{}{}", matcher, pat_string, connector) - } - None => String::new(), - }; - - // Consider only the last line of the pat string. - let extra_offset = extra_offset(&result, shape); - - // The expression may (partially) fit on the current line. - if shape.width > extra_offset + 1 { - let spacer = if pat.is_some() { " " } else { "" }; - - let expr_shape = try_opt!(shape.offset_left(extra_offset + spacer.len())); - let expr_rewrite = expr.rewrite(context, expr_shape); - - if let Some(expr_string) = expr_rewrite { - if pat.is_none() || pat_is_simple(&pat_string) || !expr_string.contains('\n') { - result.push_str(spacer); - result.push_str(&expr_string); - return Some(result); - } - } + if let Some(pat) = pat { + let matcher = if matcher.is_empty() { + matcher.to_owned() + } else { + format!("{} ", matcher) + }; + let pat_shape = + try_opt!(try_opt!(shape.offset_left(matcher.len())).sub_width(connector.len())); + let pat_string = try_opt!(pat.rewrite(context, pat_shape)); + let result = format!("{}{}{}", matcher, pat_string, connector); + return rewrite_assign_rhs(context, result, expr, shape); } - if pat.is_none() && keyword == "if" { - return None; + let expr_rw = expr.rewrite(context, shape); + // The expression may (partially) fit on the current line. + // We do not allow splitting between `if` and condition. + if keyword == "if" || expr_rw.is_some() { + return expr_rw; } - let nested_indent = shape.indent.block_only().block_indent(context.config); - // The expression won't fit on the current line, jump to next. - result.push('\n'); - result.push_str(&nested_indent.to_string(context.config)); - - let expr_rewrite = expr.rewrite(&context, Shape::indented(nested_indent, context.config)); - result.push_str(&try_opt!(expr_rewrite)); - - Some(result) + let nested_shape = shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let nested_indent_str = nested_shape.indent.to_string(context.config); + expr.rewrite(context, nested_shape) + .map(|expr_rw| format!("\n{}{}", nested_indent_str, expr_rw)) } fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { -- cgit 1.4.1-3-g733a5 From 588700c3dc7557b755b32e5e545845d20b158f4f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 02:22:59 +0900 Subject: Refactor rewrite_assign_rhs 1. Stop using mut var 2. Use block indent when breaking lines --- src/expr.rs | 63 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index febbeaf09d5..3b75f6c93db 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2914,49 +2914,54 @@ pub fn rewrite_assign_rhs>( ex: &ast::Expr, shape: Shape, ) -> Option { - let mut result = lhs.into(); - let last_line_width = last_line_width(&result) - - if result.contains('\n') { + let lhs = lhs.into(); + let last_line_width = last_line_width(&lhs) - + if lhs.contains('\n') { shape.indent.width() } else { 0 }; // 1 = space between operator and rhs. let orig_shape = try_opt!(shape.offset_left(last_line_width + 1)); - let rhs = ex.rewrite(context, orig_shape); + let rhs = try_opt!(choose_rhs( + context, + ex, + shape, + ex.rewrite(context, orig_shape) + )); + Some(lhs + &rhs) +} - match rhs { - Some(ref new_str) if !new_str.contains('\n') => { - result.push(' '); - result.push_str(new_str); - } +fn choose_rhs( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, + orig_rhs: Option, +) -> Option { + match orig_rhs { + Some(ref new_str) if !new_str.contains('\n') => Some(format!(" {}", new_str)), _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = try_opt!(shape.block_left(context.config.tab_spaces())); - let new_rhs = ex.rewrite(context, new_shape); - - // FIXME: DRY! - match (rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref replacement_rhs)) - if prefer_next_line(orig_rhs, replacement_rhs) => { - result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); - result.push_str(replacement_rhs); - } - (None, Some(ref final_rhs)) => { - result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config))); - result.push_str(final_rhs); - } - (None, None) => return None, - (Some(ref orig_rhs), _) => { - result.push(' '); - result.push_str(orig_rhs); + let new_shape = try_opt!( + Shape::indented( + shape.block().indent.block_indent(context.config), + context.config, + ).sub_width(shape.rhs_overhead(context.config)) + ); + let new_rhs = expr.rewrite(context, new_shape); + let new_indent_str = &new_shape.indent.to_string(context.config); + + match (orig_rhs, new_rhs) { + (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { + Some(format!("\n{}{}", new_indent_str, new_rhs)) } + (None, Some(ref new_rhs)) => Some(format!("\n{}{}", new_indent_str, new_rhs)), + (None, None) => None, + (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), } } } - - Some(result) } fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { -- cgit 1.4.1-3-g733a5 From bc63d69c3fde04404693aa685339ed9cac2dd0a4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 02:24:59 +0900 Subject: Format source codes --- src/bin/cargo-fmt.rs | 9 +++++++-- src/chains.rs | 5 +++-- src/comment.rs | 14 ++++---------- src/config.rs | 3 +-- src/expr.rs | 24 +++++++++++------------- src/items.rs | 48 ++++++++++++++++++++++-------------------------- src/lib.rs | 6 ++---- src/patterns.rs | 9 ++++----- src/types.rs | 11 +++++------ src/utils.rs | 4 +--- src/visitor.rs | 17 ++++++----------- 11 files changed, 66 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 95ac1a25bb9..9a7c9680a5c 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -155,8 +155,13 @@ enum TargetKind { impl TargetKind { fn should_format(&self) -> bool { match *self { - TargetKind::Lib | TargetKind::Bin | TargetKind::Example | TargetKind::Test | - TargetKind::Bench | TargetKind::CustomBuild | TargetKind::ProcMacro => true, + TargetKind::Lib | + TargetKind::Bin | + TargetKind::Example | + TargetKind::Test | + TargetKind::Bench | + TargetKind::CustomBuild | + TargetKind::ProcMacro => true, _ => false, } } diff --git a/src/chains.rs b/src/chains.rs index e4ad0d82fd4..9bce9c792f4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -390,8 +390,9 @@ fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { match expr.node { - ast::ExprKind::Mac(..) | - ast::ExprKind::Call(..) => context.use_block_indent() && repr.contains('\n'), + ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { + context.use_block_indent() && repr.contains('\n') + } ast::ExprKind::Struct(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | diff --git a/src/comment.rs b/src/comment.rs index d8189df363c..123df4927f4 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -71,8 +71,7 @@ impl<'a> CommentStyle<'a> { CommentStyle::Custom(..) | CommentStyle::Doc => "", CommentStyle::DoubleBullet => " **/", - CommentStyle::SingleBullet | - CommentStyle::Exclamation => " */", + CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", } } @@ -81,8 +80,7 @@ impl<'a> CommentStyle<'a> { CommentStyle::DoubleSlash => "// ", CommentStyle::TripleSlash => "/// ", CommentStyle::Doc => "//! ", - CommentStyle::SingleBullet | - CommentStyle::Exclamation => " * ", + CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", CommentStyle::DoubleBullet => " ** ", CommentStyle::Custom(opener) => opener, } @@ -94,15 +92,11 @@ impl<'a> CommentStyle<'a> { pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { match *self { - CommentStyle::DoubleSlash | - CommentStyle::TripleSlash | - CommentStyle::Doc => { + CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { line.trim_left().starts_with(self.line_start().trim_left()) || comment_style(line, normalize_comments) == *self } - CommentStyle::DoubleBullet | - CommentStyle::SingleBullet | - CommentStyle::Exclamation => { + CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { line.trim_left().starts_with(self.closer().trim_left()) || line.trim_left().starts_with(self.line_start().trim_left()) || comment_style(line, normalize_comments) == *self diff --git a/src/config.rs b/src/config.rs index 5b2f77ca668..fa72e2b85d5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -98,8 +98,7 @@ impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { Density::Compressed => ListTactic::Mixed, - Density::Tall | - Density::CompressedIfEmpty => ListTactic::HorizontalVertical, + Density::Tall | Density::CompressedIfEmpty => ListTactic::HorizontalVertical, Density::Vertical => ListTactic::Vertical, } } diff --git a/src/expr.rs b/src/expr.rs index 3b75f6c93db..b214a42a3db 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -315,8 +315,7 @@ pub fn format_expr( } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | - ast::ExprKind::InlineAsm(..) => { + ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { wrap_str( context.snippet(expr.span), context.config.max_width(), @@ -930,8 +929,7 @@ impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let result = match self.node { ast::StmtKind::Local(ref local) => local.rewrite(context, shape), - ast::StmtKind::Expr(ref ex) | - ast::StmtKind::Semi(ref ex) => { + ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(self) { ";" } else { "" }; format_expr( @@ -945,8 +943,7 @@ impl Rewrite for ast::Stmt { try_opt!(shape.sub_width(suffix.len())), ).map(|s| s + suffix) } - ast::StmtKind::Mac(..) | - ast::StmtKind::Item(..) => None, + ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; result.and_then(|res| { recover_comment_removed(res, self.span, context, shape) @@ -1404,8 +1401,9 @@ impl<'a> Rewrite for ControlFlow<'a> { let after_else_comment = extract_comment(after_else, context, shape); let between_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine | - ControlBraceStyle::ClosingNextLine => &*alt_block_sep, + ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => { + &*alt_block_sep + } ControlBraceStyle::AlwaysSameLine => " ", }; let after_sep = match context.config.control_brace_style() { @@ -1729,9 +1727,10 @@ impl Rewrite for ast::Arm { } } ast::ExprKind::Call(_, ref args) => (args.len() == 1, &**body), - ast::ExprKind::Closure(..) | - ast::ExprKind::Struct(..) | - ast::ExprKind::Tup(..) => (true, &**body), + ast::ExprKind::Closure(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => ( + true, + &**body, + ), _ => (false, &**body), }; extend &= context.use_block_indent(); @@ -2402,8 +2401,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l ast::ExprKind::WhileLet(..) => { context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } - ast::ExprKind::Block(..) | - ast::ExprKind::Closure(..) => { + ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { context.use_block_indent() || context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 } diff --git a/src/items.rs b/src/items.rs index 91bba534924..87299f01574 100644 --- a/src/items.rs +++ b/src/items.rs @@ -517,8 +517,7 @@ impl<'a> FmtVisitor<'a> { } let variant_body = match field.node.data { - ast::VariantData::Tuple(..) | - ast::VariantData::Struct(..) => { + ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma format_struct( &context, @@ -732,16 +731,15 @@ fn format_impl_ref_and_type( if let Some(ref trait_ref) = *trait_ref { let result_len = result.len(); - if let Some(trait_ref_str) = - rewrite_trait_ref( - context, - &trait_ref, - offset, - &generics_str, - true, - polarity_str, - result_len, - ) { + if let Some(trait_ref_str) = rewrite_trait_ref( + context, + &trait_ref, + offset, + &generics_str, + true, + polarity_str, + result_len, + ) { result.push_str(&trait_ref_str); } else { let generics_str = try_opt!(rewrite_generics_inner( @@ -2062,18 +2060,17 @@ fn rewrite_fn_base( .max_width() .checked_sub(last_line_width(&result)) ); - if let Some(where_clause_str) = - rewrite_where_clause( - context, - where_clause, - context.config.fn_brace_style(), - Shape::legacy(budget, indent), - Density::Compressed, - "{", - !has_braces, - put_args_in_block && ret_str.is_empty(), - Some(span.hi), - ) { + if let Some(where_clause_str) = rewrite_where_clause( + context, + where_clause, + context.config.fn_brace_style(), + Shape::legacy(budget, indent), + Density::Compressed, + "{", + !has_braces, + put_args_in_block && ret_str.is_empty(), + Some(span.hi), + ) { if !where_clause_str.contains('\n') { if last_line_width(&result) + where_clause_str.len() > context.config.max_width() { result.push('\n'); @@ -2628,8 +2625,7 @@ fn rewrite_where_clause( // If the brace is on the next line we don't need to count it otherwise it needs two // characters " {" match brace_style { - BraceStyle::AlwaysNextLine | - BraceStyle::SameLineWhere => 0, + BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0, BraceStyle::PreferSameLine => 2, } } else if terminator == "=" { diff --git a/src/lib.rs b/src/lib.rs index b27a02a17a9..a8bade23442 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -407,16 +407,14 @@ pub struct FormattingError { impl FormattingError { fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | - ErrorKind::TrailingWhitespace => "Rustfmt failed at", + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "Rustfmt failed at", ErrorKind::BadIssue(_) => "WARNING:", } } fn msg_suffix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | - ErrorKind::TrailingWhitespace => "(sorry)", + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "(sorry)", ErrorKind::BadIssue(_) => "", } } diff --git a/src/patterns.rs b/src/patterns.rs index cda7a108609..2fce2b7ccad 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -252,11 +252,10 @@ pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: match pat { &TuplePatField::Pat(ref pat) => { match pat.node { - ast::PatKind::Path(..) | - ast::PatKind::Tuple(..) | - ast::PatKind::Struct(..) => context.use_block_indent() && len == 1, - ast::PatKind::Ref(ref p, _) | - ast::PatKind::Box(ref p) => { + ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => { + context.use_block_indent() && len == 1 + } + ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) } ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), diff --git a/src/types.rs b/src/types.rs index 8ba0d64de9e..b617c433f10 100644 --- a/src/types.rs +++ b/src/types.rs @@ -758,8 +758,7 @@ impl Rewrite for ast::Ty { it.rewrite(context, shape) .map(|it_str| format!("impl {}", it_str)) } - ast::TyKind::Err | - ast::TyKind::Typeof(..) => unreachable!(), + ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), } } } @@ -837,10 +836,10 @@ pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &Vec bool { match ty.node { - ast::TyKind::Path(..) | - ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Rptr(_, ref mutty) | - ast::TyKind::Ptr(ref mutty) => can_be_overflowed_type(context, &*mutty.ty, len), + ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, + ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { + can_be_overflowed_type(context, &*mutty.ty, len) + } _ => false, } } diff --git a/src/utils.rs b/src/utils.rs index bc46316d39b..7873cd5d846 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -160,9 +160,7 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { #[inline] pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { match expr.node { - ast::ExprKind::Ret(..) | - ast::ExprKind::Continue(..) | - ast::ExprKind::Break(..) => true, + ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => true, _ => false, } } diff --git a/src/visitor.rs b/src/visitor.rs index 0f574d433fd..178f7c7691f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -307,23 +307,18 @@ impl<'a> FmtVisitor<'a> { let where_span_end = snippet .find_uncommented("{") .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); - if let Some(impl_str) = format_impl( - &self.get_context(), - item, - self.block_indent, - where_span_end, - ) { + if let Some(impl_str) = + format_impl(&self.get_context(), item, self.block_indent, where_span_end) + { self.buffer.push_str(&impl_str); self.last_pos = source!(self, item.span).hi; } } ast::ItemKind::Trait(..) => { self.format_missing_with_indent(item.span.lo); - if let Some(trait_str) = format_trait( - &self.get_context(), - item, - self.block_indent, - ) { + if let Some(trait_str) = + format_trait(&self.get_context(), item, self.block_indent) + { self.buffer.push_str(&trait_str); self.last_pos = source!(self, item.span).hi; } -- cgit 1.4.1-3-g733a5 From 7ab4bdfd85fe868e7aaabe1fe3192815787e5b29 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 10 Jul 2017 14:23:29 +0900 Subject: Use correct one line budget when rewriting index --- src/expr.rs | 18 +++++++++++------- tests/source/expr.rs | 2 ++ tests/target/expr.rs | 9 +++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b214a42a3db..d9524c46fa5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2494,13 +2494,18 @@ fn rewrite_index( ("[", "]") }; - let offset = expr_str.len() + lbr.len(); - let orig_index_rw = shape - .visual_indent(offset) - .sub_width(offset + rbr.len()) - .and_then(|index_shape| index.rewrite(context, index_shape)); + let offset = last_line_width(&expr_str) + lbr.len(); + let rhs_overhead = shape.rhs_overhead(context.config); + let index_shape = if expr_str.contains('\n') { + Shape::legacy(context.config.max_width(), shape.indent) + .offset_left(offset) + .and_then(|shape| shape.sub_width(rbr.len() + rhs_overhead)) + } else { + shape.visual_indent(offset).sub_width(offset + rbr.len()) + }; + let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); - // Return if everything fits in a single line. + // Return if index fits in a single line. match orig_index_rw { Some(ref index_str) if !index_str.contains('\n') => { return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); @@ -2510,7 +2515,6 @@ fn rewrite_index( // Try putting index on the next line and see if it fits in a single line. let indent = shape.indent.block_indent(context.config); - let rhs_overhead = shape.rhs_overhead(context.config); let index_shape = try_opt!(Shape::indented(indent, context.config).offset_left(lbr.len())); let index_shape = try_opt!(index_shape.sub_width(rbr.len() + rhs_overhead)); let new_index_rw = index.rewrite(context, index_shape); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 96e00174af8..fb0bd905d0a 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -222,6 +222,8 @@ fn casts() { fn indices() { let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; + let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; + let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; } fn repeats() { diff --git a/tests/target/expr.rs b/tests/target/expr.rs index c291eca34e2..26963540fcc 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -283,6 +283,15 @@ fn indices() { [x + y + z]; let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) [xxxxx + yyyyy + zzzzz]; + let z = xxxxxxxxxx + .x() + .y() + .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; + let z = xxxxxxxxxx + .x() + .y() + .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz() + [aaaaa]; } fn repeats() { -- cgit 1.4.1-3-g733a5 From 65790f2b2a1682ecce330587a2922d51d604c0b1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 10 Jul 2017 14:35:50 +0900 Subject: Cover missing comments before and after where --- src/items.rs | 185 ++++++++++++++++++++++++++++++++------------ src/lib.rs | 47 +++++++++++ tests/target/comments-fn.rs | 10 +++ tests/target/impl.rs | 9 +++ 4 files changed, 201 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 87299f01574..96ffffa7b60 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,7 +10,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. -use {Indent, Shape}; +use {Indent, Shape, Spanned}; use codemap::SpanUtils; use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, @@ -561,7 +561,7 @@ pub fn format_impl( offset: Indent, where_span_end: Option, ) -> Option { - if let ast::ItemKind::Impl(_, _, _, ref generics, _, _, ref items) = item.node { + if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { let mut result = String::new(); let ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset)); result.push_str(&ref_and_type); @@ -585,6 +585,8 @@ pub fn format_impl( false, last_line_width(&ref_and_type) == 1, where_span_end, + item.span, + self_ty.span.hi, )); if try_opt!(is_impl_single_line( @@ -963,6 +965,12 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) .max_width() .checked_sub(last_line_width(&result)) ); + let pos_before_where = if type_param_bounds.is_empty() { + // We do not use this, so it does not matter + generics.span.hi + } else { + type_param_bounds[type_param_bounds.len() - 1].span().hi + }; let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -973,6 +981,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) !has_body, trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, None, + item.span, + pos_before_where, )); // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -1164,6 +1174,19 @@ fn format_tuple_struct( } else { fields[0].span.lo }; + let body_hi = if fields.is_empty() { + context.codemap.span_after(span, ")") + } else { + // This is a dirty hack to work around a missing `)` from the span of the last field. + let last_arg_span = fields[fields.len() - 1].span; + if context.snippet(last_arg_span).ends_with(")") { + last_arg_span.hi + } else { + context + .codemap + .span_after(mk_sp(last_arg_span.hi, span.hi), ")") + } + }; let where_clause_str = match generics { Some(generics) => { @@ -1184,6 +1207,8 @@ fn format_tuple_struct( true, false, None, + span, + body_hi, )) } None => "".to_owned(), @@ -1283,6 +1308,8 @@ pub fn rewrite_type_alias( true, true, Some(span.hi), + span, + generics.span.hi, )); result.push_str(&where_clause_str); result.push_str(" = "); @@ -1734,41 +1761,6 @@ pub fn is_named_arg(arg: &ast::Arg) -> bool { } } -fn span_for_return(ret: &ast::FunctionRetTy) -> Span { - match *ret { - ast::FunctionRetTy::Default(ref span) => span.clone(), - ast::FunctionRetTy::Ty(ref ty) => ty.span, - } -} - -fn span_for_ty_param(ty: &ast::TyParam) -> Span { - // Note that ty.span is the span for ty.ident, not the whole item. - let lo = if ty.attrs.is_empty() { - ty.span.lo - } else { - ty.attrs[0].span.lo - }; - if let Some(ref def) = ty.default { - return mk_sp(lo, def.span.hi); - } - if ty.bounds.is_empty() { - return mk_sp(lo, ty.span.hi); - } - let hi = match ty.bounds[ty.bounds.len() - 1] { - ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span.hi, - ast::TyParamBound::RegionTyParamBound(ref l) => l.span.hi, - }; - mk_sp(lo, hi) -} - -fn span_for_where_pred(pred: &ast::WherePredicate) -> Span { - match *pred { - ast::WherePredicate::BoundPredicate(ref p) => p.span, - ast::WherePredicate::RegionPredicate(ref p) => p.span, - ast::WherePredicate::EqPredicate(ref p) => p.span, - } -} - // Return type is (result, force_new_line_for_brace) fn rewrite_fn_base( context: &RewriteContext, @@ -1826,7 +1818,7 @@ fn rewrite_fn_base( let shape = try_opt!( Shape::indented(indent + last_line_width(&result), context.config).sub_width(overhead) ); - let g_span = mk_sp(span.lo, span_for_return(&fd.output).lo); + let g_span = mk_sp(span.lo, fd.output.span().lo); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); @@ -1905,9 +1897,15 @@ fn rewrite_fn_base( .ty_params .last() .map_or(span.lo, |tp| end_typaram(tp)); + let args_end = if fd.inputs.is_empty() { + context.codemap.span_after(mk_sp(args_start, span.hi), ")") + } else { + let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi, span.hi); + context.codemap.span_after(last_span, ")") + }; let args_span = mk_sp( context.codemap.span_after(mk_sp(args_start, span.hi), "("), - span_for_return(&fd.output).lo, + args_end, ); let arg_str = try_opt!(rewrite_args( context, @@ -2053,6 +2051,10 @@ fn rewrite_fn_base( _ => false, } || (put_args_in_block && ret_str.is_empty()); + let pos_before_where = match fd.output { + ast::FunctionRetTy::Default(..) => args_span.hi, + ast::FunctionRetTy::Ty(ref ty) => ty.span.hi, + }; if where_clause.predicates.len() == 1 && should_compress_where { let budget = try_opt!( context @@ -2070,6 +2072,8 @@ fn rewrite_fn_base( !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi), + span, + pos_before_where, ) { if !where_clause_str.contains('\n') { if last_line_width(&result) + where_clause_str.len() > context.config.max_width() { @@ -2094,6 +2098,8 @@ fn rewrite_fn_base( !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi), + span, + pos_before_where, )); result.push_str(&where_clause_str); @@ -2378,7 +2384,7 @@ fn rewrite_generics_inner( }; mk_sp(l.lifetime.span.lo, hi) }); - let ty_spans = tys.iter().map(span_for_ty_param); + let ty_spans = tys.iter().map(|ty| ty.span()); let items = itemize_list( context.codemap, @@ -2495,10 +2501,21 @@ fn rewrite_where_clause_rfc_style( // where clause can be kept on the current line. snuggle: bool, span_end: Option, + span: Span, + span_end_before_where: BytePos, ) -> Option { let block_shape = shape.block().with_max_width(context.config); - let starting_newline = if snuggle { + let (span_before, span_after) = + missing_span_before_after_where(context, span.hi, span_end_before_where, where_clause); + let (comment_before, comment_after) = try_opt!(rewrite_comments_before_after_where( + context, + span_before, + span_after, + shape, + )); + + let starting_newline = if snuggle && comment_before.is_empty() { " ".to_owned() } else { "\n".to_owned() + &block_shape.indent.to_string(context.config) @@ -2506,18 +2523,18 @@ fn rewrite_where_clause_rfc_style( let clause_shape = block_shape.block_indent(context.config.tab_spaces()); // each clause on one line, trailing comma (except if suppress_comma) - let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; + let span_start = where_clause.predicates[0].span().lo; // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. let len = where_clause.predicates.len(); - let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; + let end_of_preds = where_clause.predicates[len - 1].span().hi; let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list( context.codemap, where_clause.predicates.iter(), terminator, - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, + |pred| pred.span().lo, + |pred| pred.span().hi, |pred| pred.rewrite(context, block_shape), span_start, span_end, @@ -2538,9 +2555,23 @@ fn rewrite_where_clause_rfc_style( }; let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let newline_before_where = if comment_before.is_empty() || comment_before.ends_with('\n') { + String::new() + } else { + "\n".to_owned() + &shape.indent.to_string(context.config) + }; + let newline_after_where = if comment_after.is_empty() { + String::new() + } else { + "\n".to_owned() + &clause_shape.indent.to_string(context.config) + }; Some(format!( - "{}where\n{}{}", + "{}{}{}where{}{}\n{}{}", starting_newline, + comment_before, + newline_before_where, + newline_after_where, + comment_after, clause_shape.indent.to_string(context.config), preds_str )) @@ -2556,6 +2587,8 @@ fn rewrite_where_clause( suppress_comma: bool, snuggle: bool, span_end: Option, + span: Span, + span_end_before_where: BytePos, ) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); @@ -2570,6 +2603,8 @@ fn rewrite_where_clause( suppress_comma, snuggle, span_end, + span, + span_end_before_where, ); } @@ -2584,18 +2619,18 @@ fn rewrite_where_clause( // be out by a char or two. let budget = context.config.max_width() - offset.width(); - let span_start = span_for_where_pred(&where_clause.predicates[0]).lo; + let span_start = where_clause.predicates[0].span().lo; // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. let len = where_clause.predicates.len(); - let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi; + let end_of_preds = where_clause.predicates[len - 1].span().hi; let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list( context.codemap, where_clause.predicates.iter(), terminator, - |pred| span_for_where_pred(pred).lo, - |pred| span_for_where_pred(pred).hi, + |pred| pred.span().lo, + |pred| pred.span().hi, |pred| pred.rewrite(context, Shape::legacy(budget, offset)), span_start, span_end, @@ -2646,6 +2681,54 @@ fn rewrite_where_clause( } } +fn missing_span_before_after_where( + context: &RewriteContext, + item_end: BytePos, + before_item_span_end: BytePos, + where_clause: &ast::WhereClause, +) -> (Span, Span) { + let snippet = context.snippet(mk_sp(before_item_span_end, item_end)); + let pos_before_where = + before_item_span_end + BytePos(snippet.find_uncommented("where").unwrap() as u32); + let missing_span_before = mk_sp(before_item_span_end, pos_before_where); + // 5 = `where` + let pos_after_where = pos_before_where + BytePos(5); + let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo); + (missing_span_before, missing_span_after) +} + +fn rewrite_missing_comment_in_where( + context: &RewriteContext, + comment: &str, + shape: Shape, +) -> Option { + let comment = comment.trim(); + if comment.is_empty() { + Some(String::new()) + } else { + rewrite_comment(comment, false, shape, context.config) + } +} + +fn rewrite_comments_before_after_where( + context: &RewriteContext, + span_before_where: Span, + span_after_where: Span, + shape: Shape, +) -> Option<(String, String)> { + let before_comment = try_opt!(rewrite_missing_comment_in_where( + context, + &context.snippet(span_before_where), + shape, + )); + let after_comment = try_opt!(rewrite_missing_comment_in_where( + context, + &context.snippet(span_after_where), + shape.block_indent(context.config.tab_spaces()), + )); + Some((before_comment, after_comment)) +} + fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { format!("{}{}{}", format_visibility(vis), item_name, ident) } @@ -2681,6 +2764,8 @@ fn format_generics( false, trimmed_last_line_width(&result) == 1, Some(span.hi), + span, + generics.span.hi, )); result.push_str(&where_clause_str); let same_line_brace = force_same_line_brace || diff --git a/src/lib.rs b/src/lib.rs index a8bade23442..3668e9cd30c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,6 +136,53 @@ impl Spanned for ast::Field { } } +impl Spanned for ast::WherePredicate { + fn span(&self) -> Span { + match *self { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } + } +} + +impl Spanned for ast::FunctionRetTy { + fn span(&self) -> Span { + match *self { + ast::FunctionRetTy::Default(span) => span, + ast::FunctionRetTy::Ty(ref ty) => ty.span, + } + } +} + +impl Spanned for ast::TyParam { + fn span(&self) -> Span { + // Note that ty.span is the span for ty.ident, not the whole item. + let lo = if self.attrs.is_empty() { + self.span.lo + } else { + self.attrs[0].span.lo + }; + if let Some(ref def) = self.default { + return mk_sp(lo, def.span.hi); + } + if self.bounds.is_empty() { + return mk_sp(lo, self.span.hi); + } + let hi = self.bounds[self.bounds.len() - 1].span().hi; + mk_sp(lo, hi) + } +} + +impl Spanned for ast::TyParamBound { + fn span(&self) -> Span { + match *self { + ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, + ast::TyParamBound::RegionTyParamBound(ref l) => l.span, + } + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 9a28c81a39e..39af3fd064e 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -27,3 +27,13 @@ where T: Eq, // some comment { } + +fn issue458(a: &str, f: F) +// comment1 +where + // comment2 + F: FnOnce(&str) -> bool, +{ + f(a); + () +} diff --git a/tests/target/impl.rs b/tests/target/impl.rs index 528d80fd5a5..ef8895580bd 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -17,3 +17,12 @@ where } } } + +impl Foo for T +// comment1 +where + // comment2 + // blah + T: Clone, +{ +} -- cgit 1.4.1-3-g733a5 From d1e124b03a93a6fa0a72ab79d73f83d96e9e0c1e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 10 Jul 2017 16:52:07 +0900 Subject: Fix up rewriting match arm pattern --- src/expr.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b214a42a3db..9fc4df80cff 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1701,19 +1701,14 @@ impl Rewrite for ast::Arm { }; let pats_str = try_opt!(write_list(&items, &fmt)); - let guard_shape = if pats_str.contains('\n') { - shape.with_max_width(context.config) - } else { - shape - }; - let guard_str = try_opt!(rewrite_guard( context, guard, - guard_shape, + shape, trimmed_last_line_width(&pats_str), )); + let pats_len = pats_str.len(); let pats_str = format!("{}{}", pats_str, guard_str); let (mut extend, body) = match body.node { @@ -1766,6 +1761,9 @@ impl Rewrite for ast::Arm { is_block => { let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), + _ if guard.is_some() && pats_str.contains('\n') && is_block && + body_str != "{}" && + pats_len > context.config.tab_spaces() => alt_block_sep.as_str(), _ => " ", }; @@ -1848,33 +1846,30 @@ fn rewrite_guard( // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` if let Some(cond_shape) = shape - .shrink_left(pattern_width + 4) + .offset_left(pattern_width + 4) .and_then(|s| s.sub_width(5)) { if let Some(cond_str) = guard .rewrite(context, cond_shape) .and_then(|s| s.rewrite(context, cond_shape)) { - if !cond_str.contains('\n') { + if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { return Some(format!(" if {}", cond_str)); } } } // Not enough space to put the guard after the pattern, try a newline. - // 3 == `if ` - if let Some(cond_shape) = Shape::indented( - shape.indent.block_indent(context.config) + 3, - context.config, - ).sub_width(3) + // 3 = `if `, 5 = ` => {` + if let Some(cond_shape) = + Shape::indented(shape.indent.block_indent(context.config), context.config) + .offset_left(3) + .and_then(|s| s.sub_width(5)) { if let Some(cond_str) = guard.rewrite(context, cond_shape) { return Some(format!( "\n{}if {}", - shape - .indent - .block_indent(context.config) - .to_string(context.config), + cond_shape.indent.to_string(context.config), cond_str )); } @@ -1920,7 +1915,6 @@ fn rewrite_pat_expr( // The expression won't fit on the current line, jump to next. let nested_shape = shape - .block() .block_indent(context.config.tab_spaces()) .with_max_width(context.config); let nested_indent_str = nested_shape.indent.to_string(context.config); -- cgit 1.4.1-3-g733a5 From 76228e81dea390a618b36ee46379e23c321a6676 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 10 Jul 2017 16:52:50 +0900 Subject: Format source codes --- src/expr.rs | 9 +++++---- src/types.rs | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9fc4df80cff..cb0f83732e9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1714,7 +1714,7 @@ impl Rewrite for ast::Arm { let (mut extend, body) = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && - context.config.wrap_match_arms() => { + context.config.wrap_match_arms() => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { (false, &**expr) } else { @@ -1756,9 +1756,10 @@ impl Rewrite for ast::Arm { match rewrite { Some(ref body_str) if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) || - !context.config.wrap_match_arms() || - (extend && first_line_width(body_str) <= arm_shape.width) || - is_block => { + !context.config.wrap_match_arms() || + (extend && first_line_width(body_str) <= arm_shape.width) || + is_block => + { let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), _ if guard.is_some() && pats_str.contains('\n') && is_block && diff --git a/src/types.rs b/src/types.rs index b617c433f10..6fd070291af 100644 --- a/src/types.rs +++ b/src/types.rs @@ -210,7 +210,8 @@ fn rewrite_segment( match **params { ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() || !data.types.is_empty() || - !data.bindings.is_empty() => { + !data.bindings.is_empty() => + { let param_list = data.lifetimes .iter() .map(SegmentParam::LifeTime) -- cgit 1.4.1-3-g733a5 From bc90a12b8deaa14b996174881790a2fb5bc2a7e9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 17:26:55 +0900 Subject: Format union --- src/items.rs | 2 +- src/visitor.rs | 15 +++- tests/source/unions.rs | 195 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/target/unions.rs | 196 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 405 insertions(+), 3 deletions(-) create mode 100644 tests/source/unions.rs create mode 100644 tests/target/unions.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 96ffffa7b60..a5e35e144fb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1053,7 +1053,7 @@ fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) format!("{};", format_header(item_name, ident, vis)) } -fn format_struct_struct( +pub fn format_struct_struct( context: &RewriteContext, item_name: &str, ident: ast::Ident, diff --git a/src/visitor.rs b/src/visitor.rs index 178f7c7691f..800f46374ec 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -426,8 +426,19 @@ impl<'a> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } - ast::ItemKind::Union(..) => { - // FIXME(#1157): format union definitions. + ast::ItemKind::Union(ref def, ref generics) => { + let rewrite = ::items::format_struct_struct( + &self.get_context(), + "union ", + item.ident, + &item.vis, + def.fields(), + Some(generics), + item.span, + self.block_indent, + None, + ); + self.push_rewrite(item.span, rewrite); } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span)); diff --git a/tests/source/unions.rs b/tests/source/unions.rs new file mode 100644 index 00000000000..107be79873c --- /dev/null +++ b/tests/source/unions.rs @@ -0,0 +1,195 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + + /// A Doc comment +#[AnAttribute] +pub union Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1029 +pub union Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +union X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub union Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +// With a where clause and generics. +pub union Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +union Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +union Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +union Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +union Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +pub union State time::Timespec> { now: F } + +pub union State ()> { now: F } + +pub union State { now: F } + +union Palette { /// A map of indizes in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +union FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +mod m { + union X where T: Sized { + a: T, + } +} + +union Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +union Foo {} +union Foo { + } +union Foo { + // comment + } +union Foo { + // trailing space -> + + + } +union Foo { /* comment */ } + +union LongUnion { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +union Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} diff --git a/tests/target/unions.rs b/tests/target/unions.rs new file mode 100644 index 00000000000..bd6328173b5 --- /dev/null +++ b/tests/target/unions.rs @@ -0,0 +1,196 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +/// A Doc comment +#[AnAttribute] +pub union Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1029 +pub union Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +union X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub union Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +// With a where clause and generics. +pub union Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +union Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +union Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +union Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +union Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +pub union State time::Timespec> { + now: F, +} + +pub union State ()> { + now: F, +} + +pub union State { + now: F, +} + +union Palette { + /// A map of indizes in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +union FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +mod m { + union X + where + T: Sized, + { + a: T, + } +} + +union Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +union Foo {} +union Foo {} +union Foo { + // comment +} +union Foo { + // trailing space -> +} +union Foo { /* comment */ } + +union LongUnion { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +union Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + * */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} -- cgit 1.4.1-3-g733a5 From 08f3f03353b88c3845ae67efbdb86b4669f94ca7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 11 Jul 2017 21:52:27 +0900 Subject: Implement combining against match arms --- src/expr.rs | 408 +++++++++++++++++++++++++++++------------------------------- src/lib.rs | 11 ++ 2 files changed, 209 insertions(+), 210 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 19b7f8b734e..d60377df65a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1553,27 +1553,96 @@ fn rewrite_match( ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), _ => " ", }; - let mut result = format!("match {}{}{{", cond_str, block_sep); + + Some(format!( + "match {}{}{{{}\n{}}}", + cond_str, + block_sep, + try_opt!(rewrite_match_arms(context, arms, shape, span, cond.span.hi)), + shape.indent.to_string(context.config), + )) +} + +fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { + if config.match_block_trailing_comma() { + "," + } else if let ast::ExprKind::Block(ref block) = body.node { + if let ast::BlockCheckMode::Default = block.rules { + "" + } else { + "," + } + } else { + "," + } +} + +fn rewrite_match_pattern( + context: &RewriteContext, + pats: &Vec>, + guard: &Option>, + shape: Shape, +) -> Option { + // Patterns + // 5 = ` => {` + let pat_shape = try_opt!(shape.sub_width(5)); + + let pat_strs = try_opt!( + pats.iter() + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>() + ); + + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, pat_shape.width); + let fmt = ListFormatting { + tactic: tactic, + separator: " |", + trailing_separator: SeparatorTactic::Never, + shape: pat_shape, + ends_with_newline: false, + config: context.config, + }; + let pats_str = try_opt!(write_list(&items, &fmt)); + + // Guard + let guard_str = try_opt!(rewrite_guard( + context, + guard, + shape, + trimmed_last_line_width(&pats_str), + )); + + Some(format!("{}{}", pats_str, guard_str)) +} + +fn rewrite_match_arms( + context: &RewriteContext, + arms: &[ast::Arm], + shape: Shape, + span: Span, + cond_end_pos: BytePos, +) -> Option { + let mut result = String::new(); let arm_shape = if context.config.indent_match_arms() { shape.block_indent(context.config.tab_spaces()) } else { shape.block_indent(0) - }; - + }.with_max_width(context.config); let arm_indent_str = arm_shape.indent.to_string(context.config); let open_brace_pos = context .codemap - .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{"); + .span_after(mk_sp(cond_end_pos, arms[0].span().lo), "{"); let arm_num = arms.len(); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. let missed_str = if i == 0 { - context.snippet(mk_sp(open_brace_pos, arm_start_pos(arm))) + context.snippet(mk_sp(open_brace_pos, arm.span().lo)) } else { - context.snippet(mk_sp(arm_end_pos(&arms[i - 1]), arm_start_pos(arm))) + context.snippet(mk_sp(arms[i - 1].span().hi, arm.span().lo)) }; let comment = try_opt!(rewrite_match_arm_comment( context, @@ -1585,7 +1654,7 @@ fn rewrite_match( result.push('\n'); result.push_str(&arm_indent_str); - let arm_str = arm.rewrite(&context, arm_shape.with_max_width(context.config)); + let arm_str = rewrite_match_arm(context, arm, arm_shape); if let Some(ref arm_str) = arm_str { // Trim the trailing comma if necessary. if i == arm_num - 1 && context.config.trailing_comma() == SeparatorTactic::Never && @@ -1597,7 +1666,7 @@ fn rewrite_match( } } else { // We couldn't format the arm, just reproduce the source. - let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm))); + let snippet = context.snippet(arm.span()); result.push_str(&snippet); if context.config.trailing_comma() != SeparatorTactic::Never { result.push_str(arm_comma(context.config, &arm.body)) @@ -1605,7 +1674,7 @@ fn rewrite_match( } } // BytePos(1) = closing match brace. - let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi - BytePos(1)); + let last_span = mk_sp(arms[arms.len() - 1].span().hi, span.hi - BytePos(1)); let last_comment = context.snippet(last_span); let comment = try_opt!(rewrite_match_arm_comment( context, @@ -1614,223 +1683,146 @@ fn rewrite_match( &arm_indent_str, )); result.push_str(&comment); - result.push('\n'); - result.push_str(&shape.indent.to_string(context.config)); - result.push('}'); - Some(result) -} - -fn arm_start_pos(arm: &ast::Arm) -> BytePos { - let &ast::Arm { - ref attrs, - ref pats, - .. - } = arm; - if !attrs.is_empty() { - return attrs[0].span.lo; - } - pats[0].span.lo -} - -fn arm_end_pos(arm: &ast::Arm) -> BytePos { - arm.body.span.hi + Some(result) } -fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { - if config.match_block_trailing_comma() { - "," - } else if let ast::ExprKind::Block(ref block) = body.node { - if let ast::BlockCheckMode::Default = block.rules { - "" - } else { - "," +fn rewrite_match_arm(context: &RewriteContext, arm: &ast::Arm, shape: Shape) -> Option { + let attr_str = if !arm.attrs.is_empty() { + if contains_skip(&arm.attrs) { + return None; } + format!( + "{}\n{}", + try_opt!(arm.attrs.rewrite(context, shape)), + shape.indent.to_string(context.config) + ) } else { - "," - } + String::new() + }; + let pats_str = try_opt!(rewrite_match_pattern(context, &arm.pats, &arm.guard, shape)); + let pats_str = attr_str + &pats_str; + rewrite_match_body(context, &arm.body, &pats_str, shape, arm.guard.is_some()) } -// Match arms. -impl Rewrite for ast::Arm { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!("Arm::rewrite {:?} {:?}", self, shape); - let &ast::Arm { - ref attrs, - ref pats, - ref guard, - ref body, - } = self; - - let attr_str = if !attrs.is_empty() { - if contains_skip(attrs) { - return None; +fn rewrite_match_body( + context: &RewriteContext, + body: &ptr::P, + pats_str: &str, + shape: Shape, + has_guard: bool, +) -> Option { + let (extend, body) = match body.node { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { + (expr.can_be_overflowed(context, 1), &**expr) + } else { + (false, &**body) } - format!( - "{}\n{}", - try_opt!(attrs.rewrite(context, shape)), - shape.indent.to_string(context.config) - ) - } else { - String::new() - }; - - // Patterns - // 5 = ` => {` - let pat_shape = try_opt!(shape.sub_width(5)); - - let pat_strs = try_opt!( - pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>() - ); - - let all_simple = pat_strs.iter().all(|p| !p.contains('\n')); - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let mut tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, pat_shape.width); - if tactic == DefinitiveListTactic::Horizontal && all_simple { - tactic = DefinitiveListTactic::Mixed; - } - let fmt = ListFormatting { - tactic: tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - shape: pat_shape, - ends_with_newline: false, - config: context.config, - }; - let pats_str = try_opt!(write_list(&items, &fmt)); - - let guard_str = try_opt!(rewrite_guard( - context, - guard, - shape, - trimmed_last_line_width(&pats_str), - )); + } + _ => (body.can_be_overflowed(context, 1), &**body), + }; - let pats_len = pats_str.len(); - let pats_str = format!("{}{}", pats_str, guard_str); + let comma = arm_comma(&context.config, body); + let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = alt_block_sep.as_str(); + let is_block = if let ast::ExprKind::Block(..) = body.node { + true + } else { + false + }; - let (mut extend, body) = match body.node { - ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) && - context.config.wrap_match_arms() => { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - (false, &**expr) - } else { - (false, &**body) - } + let combine_orig_body = |body_str: &str| { + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, + _ if has_guard && pats_str.contains('\n') && is_block && body_str != "{}" => { + alt_block_sep } - ast::ExprKind::Call(_, ref args) => (args.len() == 1, &**body), - ast::ExprKind::Closure(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => ( - true, - &**body, - ), - _ => (false, &**body), + _ => " ", }; - extend &= context.use_block_indent(); - - let comma = arm_comma(&context.config, body); - let alt_block_sep = - String::from("\n") + &shape.indent.block_only().to_string(context.config); - - let pat_width = extra_offset(&pats_str, shape); - // Let's try and get the arm body on the same line as the condition. - // 4 = ` => `.len() - if shape.width > pat_width + comma.len() + 4 { - let arm_shape = shape - .offset_left(pat_width + 4) - .unwrap() - .sub_width(comma.len()) - .unwrap(); - let rewrite = nop_block_collapse( - format_expr(body, ExprType::Statement, context, arm_shape), - arm_shape.width, - ); - let is_block = if let ast::ExprKind::Block(..) = body.node { - true - } else { - false - }; - match rewrite { - Some(ref body_str) - if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) || - !context.config.wrap_match_arms() || - (extend && first_line_width(body_str) <= arm_shape.width) || - is_block => - { - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(), - _ if guard.is_some() && pats_str.contains('\n') && is_block && - body_str != "{}" && - pats_len > context.config.tab_spaces() => alt_block_sep.as_str(), - _ => " ", - }; - - return Some(format!( - "{}{} =>{}{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - body_str, - comma - )); - } - _ => {} - } - } + Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) + }; - // FIXME: we're doing a second rewrite of the expr; This may not be - // necessary. - let body_shape = try_opt!(shape.block_left(context.config.tab_spaces())); - let next_line_body = try_opt!(nop_block_collapse( - format_expr(body, ExprType::Statement, context, body_shape), - body_shape.width, - )); + let combine_next_line_body = |body_str: &str| { let indent_str = shape .indent .block_indent(context.config) .to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms() { - if context.config.match_block_trailing_comma() { - ("{", "},") + let comma = if context.config.match_block_trailing_comma() { + "," } else { - ("{", "}") - } + "" + }; + ( + "{", + format!("\n{}}}{}", shape.indent.to_string(context.config), comma), + ) } else { - ("", ",") + ("", String::from(",")) }; - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n", + ControlBraceStyle::AlwaysNextLine => format!("{}{}\n", alt_block_sep, body_prefix), _ if body_prefix.is_empty() => "\n".to_owned(), _ => " ".to_owned() + body_prefix + "\n", - }; + } + &indent_str; - if context.config.wrap_match_arms() { - Some(format!( - "{}{} =>{}{}{}\n{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - indent_str, - next_line_body, - shape.indent.to_string(context.config), - body_suffix - )) - } else { - Some(format!( - "{}{} =>{}{}{}{}", - attr_str.trim_left(), - pats_str, - block_sep, - indent_str, - next_line_body, - body_suffix - )) + Some(format!( + "{} =>{}{}{}", + pats_str, + block_sep, + body_str, + body_suffix + )) + }; + + // Let's try and get the arm body on the same line as the condition. + // 4 = ` => `.len() + let orig_arm_shape = shape + .offset_left(extra_offset(&pats_str, shape) + 4) + .and_then(|shape| shape.sub_width(comma.len())); + let orig_body = if let Some(arm_shape) = orig_arm_shape { + let rewrite = nop_block_collapse( + format_expr(body, ExprType::Statement, context, arm_shape), + arm_shape.width, + ); + + match rewrite { + Some(ref body_str) + if ((!body_str.contains('\n')) && first_line_width(body_str) <= arm_shape.width) || + is_block => + { + return combine_orig_body(body_str); + } + _ => rewrite, } + } else { + None + }; + let orig_budget = orig_arm_shape.map_or(0, |shape| shape.width); + + // Try putting body on the next line and see if it looks better. + let next_line_body_shape = + Shape::indented(shape.indent.block_indent(context.config), context.config); + let next_line_body = nop_block_collapse( + format_expr(body, ExprType::Statement, context, next_line_body_shape), + next_line_body_shape.width, + ); + match (orig_body, next_line_body) { + (Some(ref orig_str), Some(ref next_line_str)) + if prefer_next_line(orig_str, next_line_str) => combine_next_line_body(next_line_str), + (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { + combine_orig_body(orig_str) + } + (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { + combine_next_line_body(next_line_str) + } + (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), + (None, None) => None, + (Some(ref orig_str), _) => combine_orig_body(orig_str), } } @@ -1846,14 +1838,11 @@ fn rewrite_guard( if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. // 4 = ` if `, 5 = ` => {` - if let Some(cond_shape) = shape + let cond_shape = shape .offset_left(pattern_width + 4) - .and_then(|s| s.sub_width(5)) - { - if let Some(cond_str) = guard - .rewrite(context, cond_shape) - .and_then(|s| s.rewrite(context, cond_shape)) - { + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { return Some(format!(" if {}", cond_str)); } @@ -1862,11 +1851,10 @@ fn rewrite_guard( // Not enough space to put the guard after the pattern, try a newline. // 3 = `if `, 5 = ` => {` - if let Some(cond_shape) = - Shape::indented(shape.indent.block_indent(context.config), context.config) - .offset_left(3) - .and_then(|s| s.sub_width(5)) - { + let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) + .offset_left(3) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { if let Some(cond_str) = guard.rewrite(context, cond_shape) { return Some(format!( "\n{}if {}", diff --git a/src/lib.rs b/src/lib.rs index 3668e9cd30c..899d168cee4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,17 @@ impl Spanned for ast::Ty { } } +impl Spanned for ast::Arm { + fn span(&self) -> Span { + let hi = self.body.span.hi; + if self.attrs.is_empty() { + mk_sp(self.pats[0].span.lo, hi) + } else { + mk_sp(self.attrs[0].span.lo, hi) + } + } +} + impl Spanned for ast::Arg { fn span(&self) -> Span { if items::is_named_arg(self) { -- cgit 1.4.1-3-g733a5 From e3310a6a18d83016209d758ca2694fa1909f74f3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 11 Jul 2017 21:53:10 +0900 Subject: Format source codes --- src/bin/cargo-fmt.rs | 22 ++--- src/chains.rs | 20 ++-- src/comment.rs | 88 ++++++++---------- src/config.rs | 8 +- src/expr.rs | 256 ++++++++++++++++++++++----------------------------- src/imports.rs | 16 ++-- src/issues.rs | 32 +++---- src/items.rs | 188 +++++++++++++++++-------------------- src/lib.rs | 14 ++- src/lists.rs | 36 +++----- src/macros.rs | 12 +-- src/patterns.rs | 58 +++++------- src/types.rs | 46 ++++----- src/utils.rs | 24 ++--- src/visitor.rs | 10 +- 15 files changed, 350 insertions(+), 480 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 9a7c9680a5c..3f7d11c0a97 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -90,13 +90,11 @@ fn execute() -> i32 { print_usage(&opts, &e.to_string()); failure } - Ok(status) => { - if status.success() { - success - } else { - status.code().unwrap_or(failure) - } - } + Ok(status) => if status.success() { + success + } else { + status.code().unwrap_or(failure) + }, } } @@ -324,12 +322,10 @@ fn format_files( .args(fmt_args) .spawn() .map_err(|e| match e.kind() { - std::io::ErrorKind::NotFound => { - std::io::Error::new( - std::io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your PATH.", - ) - } + std::io::ErrorKind::NotFound => std::io::Error::new( + std::io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), _ => e, })?; command.wait() diff --git a/src/chains.rs b/src/chains.rs index 4e606369eb9..1660e113dcd 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -444,12 +444,10 @@ fn rewrite_method_call_with_overflow( None => return false, }; let types = match segment.parameters { - Some(ref params) => { - match **params { - ast::PathParameters::AngleBracketed(ref data) => &data.types[..], - _ => &[], - } - } + Some(ref params) => match **params { + ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + _ => &[], + }, _ => &[], }; let mut last_rewrite = rewrite_method_call( @@ -516,12 +514,10 @@ fn rewrite_chain_subexpr( match expr.node { ast::ExprKind::MethodCall(ref segment, ref expressions) => { let types = match segment.parameters { - Some(ref params) => { - match **params { - ast::PathParameters::AngleBracketed(ref data) => &data.types[..], - _ => &[], - } - } + Some(ref params) => match **params { + ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + _ => &[], + }, _ => &[], }; rewrite_method_call(segment.identifier, types, expressions, span, context, shape) diff --git a/src/comment.rs b/src/comment.rs index 123df4927f4..df97c2bfef3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -342,14 +342,12 @@ impl FindUncommented for str { None => { return Some(i - pat.len()); } - Some(c) => { - match kind { - FullCodeCharKind::Normal if b == c => {} - _ => { - needle_iter = pat.chars(); - } + Some(c) => match kind { + FullCodeCharKind::Normal if b == c => {} + _ => { + needle_iter = pat.chars(); } - } + }, } } @@ -494,42 +492,34 @@ where let item = try_opt!(self.base.next()); let chr = item.get_char(); self.status = match self.status { - CharClassesStatus::LitString => { - match chr { - '"' => CharClassesStatus::Normal, - '\\' => CharClassesStatus::LitStringEscape, - _ => CharClassesStatus::LitString, - } - } + CharClassesStatus::LitString => match chr { + '"' => CharClassesStatus::Normal, + '\\' => CharClassesStatus::LitStringEscape, + _ => CharClassesStatus::LitString, + }, CharClassesStatus::LitStringEscape => CharClassesStatus::LitString, - CharClassesStatus::LitChar => { - match chr { - '\\' => CharClassesStatus::LitCharEscape, - '\'' => CharClassesStatus::Normal, - _ => CharClassesStatus::LitChar, - } - } + CharClassesStatus::LitChar => match chr { + '\\' => CharClassesStatus::LitCharEscape, + '\'' => CharClassesStatus::Normal, + _ => CharClassesStatus::LitChar, + }, CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, - CharClassesStatus::Normal => { - match chr { - '"' => CharClassesStatus::LitString, - '\'' => CharClassesStatus::LitChar, - '/' => { - match self.base.peek() { - Some(next) if next.get_char() == '*' => { - self.status = CharClassesStatus::BlockCommentOpening(1); - return Some((FullCodeCharKind::StartComment, item)); - } - Some(next) if next.get_char() == '/' => { - self.status = CharClassesStatus::LineComment; - return Some((FullCodeCharKind::StartComment, item)); - } - _ => CharClassesStatus::Normal, - } + CharClassesStatus::Normal => match chr { + '"' => CharClassesStatus::LitString, + '\'' => CharClassesStatus::LitChar, + '/' => match self.base.peek() { + Some(next) if next.get_char() == '*' => { + self.status = CharClassesStatus::BlockCommentOpening(1); + return Some((FullCodeCharKind::StartComment, item)); + } + Some(next) if next.get_char() == '/' => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::StartComment, item)); } _ => CharClassesStatus::Normal, - } - } + }, + _ => CharClassesStatus::Normal, + }, CharClassesStatus::BlockComment(deepness) => { assert!(deepness != 0); self.status = match self.base.peek() { @@ -558,18 +548,16 @@ where return Some((FullCodeCharKind::InComment, item)); } } - CharClassesStatus::LineComment => { - match chr { - '\n' => { - self.status = CharClassesStatus::Normal; - return Some((FullCodeCharKind::EndComment, item)); - } - _ => { - self.status = CharClassesStatus::LineComment; - return Some((FullCodeCharKind::InComment, item)); - } + CharClassesStatus::LineComment => match chr { + '\n' => { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); } - } + _ => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::InComment, item)); + } + }, }; Some((FullCodeCharKind::Normal, item)) } diff --git a/src/config.rs b/src/config.rs index fa72e2b85d5..510cdef6f1b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -482,11 +482,9 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { Ok(ref md) if md.is_file() => return Ok(Some(config_file)), // Return the error if it's something other than `NotFound`; otherwise we didn't // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != ErrorKind::NotFound { - return Err(e); - } - } + Err(e) => if e.kind() != ErrorKind::NotFound { + return Err(e); + }, _ => {} } } diff --git a/src/expr.rs b/src/expr.rs index d60377df65a..9adb601c9cb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -88,29 +88,23 @@ pub fn format_expr( } } let expr_rw = match expr.node { - ast::ExprKind::Array(ref expr_vec) => { - rewrite_array( - expr_vec.iter().map(|e| &**e), - mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), - context, - shape, - false, - ) - } - ast::ExprKind::Lit(ref l) => { - match l.node { - ast::LitKind::Str(_, ast::StrStyle::Cooked) => { - rewrite_string_lit(context, l.span, shape) - } - _ => { - wrap_str( - context.snippet(expr.span), - context.config.max_width(), - shape, - ) - } + ast::ExprKind::Array(ref expr_vec) => rewrite_array( + expr_vec.iter().map(|e| &**e), + mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), + context, + shape, + false, + ), + ast::ExprKind::Lit(ref l) => match l.node { + ast::LitKind::Str(_, ast::StrStyle::Cooked) => { + rewrite_string_lit(context, l.span, shape) } - } + _ => wrap_str( + context.snippet(expr.span), + context.config.max_width(), + shape, + ), + }, ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi, expr.span.hi); rewrite_call_with_binary_search( @@ -135,33 +129,27 @@ pub fn format_expr( ) } ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref base) => { - rewrite_struct_lit( - context, - path, - fields, - base.as_ref().map(|e| &**e), - expr.span, - shape, - ) - } - ast::ExprKind::Tup(ref items) => { - rewrite_tuple( - context, - &items.iter().map(|x| &**x).collect::>()[..], - expr.span, - shape, - ) - } + ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( + context, + path, + fields, + base.as_ref().map(|e| &**e), + expr.span, + shape, + ), + ast::ExprKind::Tup(ref items) => rewrite_tuple( + context, + &items.iter().map(|x| &**x).collect::>()[..], + expr.span, + shape, + ), ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) => { - to_control_flow(expr, expr_type) - .and_then(|control_flow| control_flow.rewrite(context, shape)) - } + ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) + .and_then(|control_flow| control_flow.rewrite(context, shape)), ast::ExprKind::Block(ref block) => { match expr_type { ExprType::Statement => { @@ -271,14 +259,12 @@ pub fn format_expr( fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { match lhs.node { - ast::ExprKind::Lit(ref lit) => { - match lit.node { - ast::LitKind::FloatUnsuffixed(..) => { - context.snippet(lit.span).ends_with('.') - } - _ => false, + ast::ExprKind::Lit(ref lit) => match lit.node { + ast::LitKind::FloatUnsuffixed(..) => { + context.snippet(lit.span).ends_with('.') } - } + _ => false, + }, _ => false, } } @@ -315,13 +301,11 @@ pub fn format_expr( } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - wrap_str( - context.snippet(expr.span), - context.config.max_width(), - shape, - ) - } + ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => wrap_str( + context.snippet(expr.span), + context.config.max_width(), + shape, + ), ast::ExprKind::Catch(ref block) => { if let rewrite @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) @@ -338,14 +322,12 @@ pub fn format_expr( } }; match (attr_rw, expr_rw) { - (Some(attr_str), Some(expr_str)) => { - recover_comment_removed( - combine_attr_and_expr(context, shape, &attr_str, &expr_str), - expr.span, - context, - shape, - ) - } + (Some(attr_str), Some(expr_str)) => recover_comment_removed( + combine_attr_and_expr(context, shape, &attr_str, &expr_str), + expr.span, + context, + shape, + ), _ => None, } } @@ -460,22 +442,18 @@ where }; let mut nested_shape = match context.config.array_layout() { - IndentStyle::Block => { - try_opt!( - shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1) - ) - } - IndentStyle::Visual => { - try_opt!( - shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2) - ) - } + IndentStyle::Block => try_opt!( + shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1) + ), + IndentStyle::Visual => try_opt!( + shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2) + ), }; let items = itemize_list( @@ -513,17 +491,15 @@ where None => DefinitiveListTactic::Vertical, } } - IndentStyle::Visual => { - if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic( - &items, - ListTactic::LimitedHorizontalVertical(context.config.array_width()), - nested_shape.width, - ) - } else { - DefinitiveListTactic::Mixed - } - } + IndentStyle::Visual => if has_long_item || items.iter().any(ListItem::is_multiline) { + definitive_tactic( + &items, + ListTactic::LimitedHorizontalVertical(context.config.array_width()), + nested_shape.width, + ) + } else { + DefinitiveListTactic::Mixed + }, }; if context.config.array_horizontal_layout_threshold() > 0 && items.len() > context.config.array_horizontal_layout_threshold() @@ -965,15 +941,13 @@ fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Opt ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { stmt_expr(&block.stmts[0]).and_then(|e| rewrite_cond(context, e, shape)) } - _ => { - to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { - let alt_block_sep = - String::from("\n") + &shape.indent.block_only().to_string(context.config); - control_flow - .rewrite_cond(context, shape, &alt_block_sep) - .and_then(|rw| Some(rw.0)) - }) - } + _ => to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { + let alt_block_sep = + String::from("\n") + &shape.indent.block_only().to_string(context.config); + control_flow + .rewrite_cond(context, shape, &alt_block_sep) + .and_then(|rw| Some(rw.0)) + }), } } @@ -996,17 +970,15 @@ struct ControlFlow<'a> { fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option> { match expr.node { - ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { - Some(ControlFlow::new_if( - cond, - None, - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - )) - } + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( + cond, + None, + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )), ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { Some(ControlFlow::new_if( cond, @@ -1021,21 +993,15 @@ fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option { Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) } - ast::ExprKind::Loop(ref block, label) => Some( - ControlFlow::new_loop(block, label, expr.span), - ), - ast::ExprKind::While(ref cond, ref block, label) => Some( - ControlFlow::new_while(None, cond, block, label, expr.span), - ), - ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => { - Some(ControlFlow::new_while( - Some(pat), - cond, - block, - label, - expr.span, - )) + ast::ExprKind::Loop(ref block, label) => { + Some(ControlFlow::new_loop(block, label, expr.span)) + } + ast::ExprKind::While(ref cond, ref block, label) => { + Some(ControlFlow::new_while(None, cond, block, label, expr.span)) } + ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( + ControlFlow::new_while(Some(pat), cond, block, label, expr.span), + ), _ => None, } } @@ -2502,26 +2468,22 @@ fn rewrite_index( let index_shape = try_opt!(index_shape.sub_width(rbr.len() + rhs_overhead)); let new_index_rw = index.rewrite(context, index_shape); match (orig_index_rw, new_index_rw) { - (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => { - Some(format!( - "{}\n{}{}{}{}", - expr_str, - indent.to_string(&context.config), - lbr, - new_index_str, - rbr - )) - } - (None, Some(ref new_index_str)) => { - Some(format!( - "{}\n{}{}{}{}", - expr_str, - indent.to_string(&context.config), - lbr, - new_index_str, - rbr - )) - } + (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent.to_string(&context.config), + lbr, + new_index_str, + rbr + )), + (None, Some(ref new_index_str)) => Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent.to_string(&context.config), + lbr, + new_index_str, + rbr + )), (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), _ => None, } diff --git a/src/imports.rs b/src/imports.rs index 8ded75a9576..d284b235c5e 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -60,12 +60,10 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde }; if name_ordering == Ordering::Equal { match a.node.rename { - Some(a_rename) => { - match b.node.rename { - Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), - None => Ordering::Greater, - } - } + Some(a_rename) => match b.node.rename { + Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), + None => Ordering::Greater, + }, None => Ordering::Less, } } else { @@ -159,9 +157,9 @@ impl Rewrite for ast::ViewPath { // Returns an empty string when the ViewPath is empty (like foo::bar::{}) fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => Some( - String::new(), - ), + ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => { + Some(String::new()) + } ast::ViewPath_::ViewPathList(ref path, ref path_list) => { rewrite_use_list(shape, path, path_list, self.span, context) } diff --git a/src/issues.rs b/src/issues.rs index 0211723e930..432fb797a6e 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -189,25 +189,19 @@ impl BadIssueSeeker { } match part { - NumberPart::OpenParen => { - if c != '(' { - return IssueClassification::Bad(issue); - } else { - part = NumberPart::Pound; - } - } - NumberPart::Pound => { - if c == '#' { - part = NumberPart::Number; - } - } - NumberPart::Number => { - if c >= '0' && c <= '9' { - part = NumberPart::CloseParen; - } else { - return IssueClassification::Bad(issue); - } - } + NumberPart::OpenParen => if c != '(' { + return IssueClassification::Bad(issue); + } else { + part = NumberPart::Pound; + }, + NumberPart::Pound => if c == '#' { + part = NumberPart::Number; + }, + NumberPart::Number => if c >= '0' && c <= '9' { + part = NumberPart::CloseParen; + } else { + return IssueClassification::Bad(issue); + }, NumberPart::CloseParen => {} } diff --git a/src/items.rs b/src/items.rs index a5e35e144fb..7e79e0a0b45 100644 --- a/src/items.rs +++ b/src/items.rs @@ -362,12 +362,10 @@ impl<'a> FmtVisitor<'a> { ).map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } - None => { - stmt.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ) - } + None => stmt.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ), } } else { None @@ -418,13 +416,11 @@ impl<'a> FmtVisitor<'a> { let variant_list = self.format_variant_list(enum_def, body_start, span.hi - BytePos(1)); match variant_list { Some(ref body_str) => self.buffer.push_str(body_str), - None => { - if contains_comment(&enum_snippet[brace_pos..]) { - self.format_missing_no_indent(span.hi - BytePos(1)) - } else { - self.format_missing(span.hi - BytePos(1)) - } - } + None => if contains_comment(&enum_snippet[brace_pos..]) { + self.format_missing_no_indent(span.hi - BytePos(1)) + } else { + self.format_missing(span.hi - BytePos(1)) + }, } self.block_indent = self.block_indent.block_unindent(self.config); @@ -620,14 +616,12 @@ pub fn format_impl( result.push_str(&offset.to_string(context.config)); } BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push(' '); - } - } + BraceStyle::SameLineWhere => if !where_clause_str.is_empty() { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push(' '); + }, } result.push('{'); @@ -876,31 +870,27 @@ pub fn format_struct( ) -> Option { match *struct_def { ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)), - ast::VariantData::Tuple(ref fields, _) => { - format_tuple_struct( - context, - item_name, - ident, - vis, - fields, - generics, - span, - offset, - ) - } - ast::VariantData::Struct(ref fields, _) => { - format_struct_struct( - context, - item_name, - ident, - vis, - fields, - generics, - span, - offset, - one_line_width, - ) - } + ast::VariantData::Tuple(ref fields, _) => format_tuple_struct( + context, + item_name, + ident, + vis, + fields, + generics, + span, + offset, + ), + ast::VariantData::Struct(ref fields, _) => format_struct_struct( + context, + item_name, + ident, + vis, + fields, + generics, + span, + offset, + one_line_width, + ), } } @@ -1003,16 +993,14 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&offset.to_string(context.config)); } BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() && - (!trait_items.is_empty() || result.contains('\n')) - { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push(' '); - } - } + BraceStyle::SameLineWhere => if !where_clause_str.is_empty() && + (!trait_items.is_empty() || result.contains('\n')) + { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push(' '); + }, } result.push('{'); @@ -1072,19 +1060,17 @@ pub fn format_struct_struct( let body_lo = context.codemap.span_after(span, "{"); let generics_str = match generics { - Some(g) => { - try_opt!(format_generics( - context, - g, - "{", - "{", - context.config.item_brace_style(), - fields.is_empty(), - offset, - mk_sp(span.lo, body_lo), - last_line_width(&result), - )) - } + Some(g) => try_opt!(format_generics( + context, + g, + "{", + "{", + context.config.item_brace_style(), + fields.is_empty(), + offset, + mk_sp(span.lo, body_lo), + last_line_width(&result), + )), None => { // 3 = ` {}`, 2 = ` {`. let overhead = if fields.is_empty() { 3 } else { 2 }; @@ -1416,16 +1402,14 @@ pub fn rewrite_struct_field_prefix( let type_annotation_spacing = type_annotation_spacing(context.config); Some(match field.ident { - Some(name) => { - format!( - "{}{}{}{}{}:", - attr_str, - missing_comment, - vis, - name, - type_annotation_spacing.0 - ) - } + Some(name) => format!( + "{}{}{}{}{}:", + attr_str, + missing_comment, + vis, + name, + type_annotation_spacing.0 + ), None => format!("{}{}{}", attr_str, missing_comment, vis), }) } @@ -1492,19 +1476,15 @@ pub fn rewrite_struct_field( match ty_rewritten { // If we start from the next line and type fits in a single line, then do so. - Some(ref ty) => { - match rewrite_type_in_next_line() { - Some(ref new_ty) if !new_ty.contains('\n') => { - Some(format!( - "{}\n{}{}", - prefix, - type_offset.to_string(&context.config), - &new_ty - )) - } - _ => Some(prefix + &ty), - } - } + Some(ref ty) => match rewrite_type_in_next_line() { + Some(ref new_ty) if !new_ty.contains('\n') => Some(format!( + "{}\n{}{}", + prefix, + type_offset.to_string(&context.config), + &new_ty + )), + _ => Some(prefix + &ty), + }, _ => { let ty = try_opt!(rewrite_type_in_next_line()); Some(format!( @@ -2221,20 +2201,16 @@ fn rewrite_args( .map_or(false, |s| s.trim().starts_with("//")); let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout() { - IndentStyle::Block if fits_in_one_line => { - ( - indent.block_indent(context.config), - SeparatorTactic::Never, - true, - ) - } - IndentStyle::Block => { - ( - indent.block_indent(context.config), - context.config.trailing_comma(), - true, - ) - } + IndentStyle::Block if fits_in_one_line => ( + indent.block_indent(context.config), + SeparatorTactic::Never, + true, + ), + IndentStyle::Block => ( + indent.block_indent(context.config), + context.config.trailing_comma(), + true, + ), IndentStyle::Visual if last_line_ends_with_comment => { (arg_indent, context.config.trailing_comma(), true) } diff --git a/src/lib.rs b/src/lib.rs index 899d168cee4..030d18c3000 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -442,14 +442,12 @@ pub enum ErrorKind { impl fmt::Display for ErrorKind { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - ErrorKind::LineOverflow(found, maximum) => { - write!( - fmt, - "line exceeded maximum length (maximum: {}, found: {})", - maximum, - found - ) - } + ErrorKind::LineOverflow(found, maximum) => write!( + fmt, + "line exceeded maximum length (maximum: {}, found: {})", + maximum, + found + ), ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), } diff --git a/src/lists.rs b/src/lists.rs index 4f762ea1f37..4bd7d76483a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -440,29 +440,23 @@ where // Comment belongs to next item. (Some(i), None) if i > separator_index => separator_index + 1, // Block-style post-comment before the separator. - (Some(i), None) => { - cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ) - } + (Some(i), None) => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => { - cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ) - } + (Some(i), Some(j)) if i < j => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), // Potential *single* line comment. (_, Some(j)) if j > separator_index => j + 1, _ => post_snippet.len(), } } - None => { - post_snippet - .find_uncommented(self.terminator) - .unwrap_or(post_snippet.len()) - } + None => post_snippet + .find_uncommented(self.terminator) + .unwrap_or(post_snippet.len()), }; if !post_snippet.is_empty() && comment_end > 0 { @@ -595,11 +589,9 @@ pub fn struct_lit_shape( suffix_width: usize, ) -> Option<(Option, Shape)> { let v_shape = match context.config.struct_lit_style() { - IndentStyle::Visual => { - try_opt!( - try_opt!(shape.visual_indent(0).shrink_left(prefix_width)).sub_width(suffix_width) - ) - } + IndentStyle::Visual => try_opt!( + try_opt!(shape.visual_indent(0).shrink_left(prefix_width)).sub_width(suffix_width) + ), IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); Shape { diff --git a/src/macros.rs b/src/macros.rs index 54a65087e12..3f4adf88120 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -80,13 +80,11 @@ pub fn rewrite_macro( let macro_name = match extra_ident { None => format!("{}!", mac.node.path), - Some(ident) => { - if ident == symbol::keywords::Invalid.ident() { - format!("{}!", mac.node.path) - } else { - format!("{}! {}", mac.node.path, ident) - } - } + Some(ident) => if ident == symbol::keywords::Invalid.ident() { + format!("{}!", mac.node.path) + } else { + format!("{}! {}", mac.node.path, ident) + }, }; let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { diff --git a/src/patterns.rs b/src/patterns.rs index 2fce2b7ccad..bcc57f93189 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -54,23 +54,15 @@ impl Rewrite for Pat { let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); wrap_str(result, context.config.max_width(), shape) } - PatKind::Wild => { - if 1 <= shape.width { - Some("_".to_owned()) - } else { - None - } - } - PatKind::Range(ref lhs, ref rhs, ref end_kind) => { - match *end_kind { - RangeEnd::Included => { - rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape) - } - RangeEnd::Excluded => { - rewrite_pair(&**lhs, &**rhs, "", "..", "", context, shape) - } - } - } + PatKind::Wild => if 1 <= shape.width { + Some("_".to_owned()) + } else { + None + }, + PatKind::Range(ref lhs, ref rhs, ref end_kind) => match *end_kind { + RangeEnd::Included => rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape), + RangeEnd::Excluded => rewrite_pair(&**lhs, &**rhs, "", "..", "", context, shape), + }, PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, shape) @@ -121,13 +113,11 @@ impl Rewrite for Pat { rewrite_struct_pat(path, fields, elipses, self.span, context, shape) } // FIXME(#819) format pattern macros. - PatKind::Mac(..) => { - wrap_str( - context.snippet(self.span), - context.config.max_width(), - shape, - ) - } + PatKind::Mac(..) => wrap_str( + context.snippet(self.span), + context.config.max_width(), + shape, + ), } } } @@ -250,18 +240,16 @@ impl<'a> Spanned for TuplePatField<'a> { pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { match pat { - &TuplePatField::Pat(ref pat) => { - match pat.node { - ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => { - context.use_block_indent() && len == 1 - } - ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { - can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) - } - ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), - _ => false, + &TuplePatField::Pat(ref pat) => match pat.node { + ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => { + context.use_block_indent() && len == 1 } - } + ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { + can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) + } + ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), + _ => false, + }, &TuplePatField::Dotdot(..) => false, } } diff --git a/src/types.rs b/src/types.rs index 6fd070291af..edab375b02d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -474,14 +474,12 @@ impl Rewrite for ast::WherePredicate { ref lifetime, ref bounds, .. - }) => { - try_opt!(rewrite_bounded_lifetime( - lifetime, - bounds.iter(), - context, - shape, - )) - } + }) => try_opt!(rewrite_bounded_lifetime( + lifetime, + bounds.iter(), + context, + shape, + )), ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, @@ -727,14 +725,12 @@ impl Rewrite for ast::Ty { format!("[{}]", ty_str) }) } - ast::TyKind::Tup(ref items) => { - rewrite_tuple( - context, - &items.iter().map(|x| &**x).collect::>()[..], - self.span, - shape, - ) - } + ast::TyKind::Tup(ref items) => rewrite_tuple( + context, + &items.iter().map(|x| &**x).collect::>()[..], + self.span, + shape, + ), ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } @@ -744,21 +740,17 @@ impl Rewrite for ast::Ty { let rbr = if use_spaces { " ]" } else { "]" }; rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, shape) } - ast::TyKind::Infer => { - if shape.width >= 1 { - Some("_".to_owned()) - } else { - None - } - } + ast::TyKind::Infer => if shape.width >= 1 { + Some("_".to_owned()) + } else { + None + }, ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Some(String::from("!")), ast::TyKind::Mac(..) => None, ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(ref it) => { - it.rewrite(context, shape) - .map(|it_str| format!("impl {}", it_str)) - } + ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) + .map(|it_str| format!("impl {}", it_str)), ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), } } diff --git a/src/utils.rs b/src/utils.rs index 7873cd5d846..2e0dce52e91 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -25,11 +25,9 @@ use SKIP_ANNOTATION; pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => { - text.len() - .checked_sub(idx + 1 + shape.used_width()) - .unwrap_or(0) - } + Some(idx) => text.len() + .checked_sub(idx + 1 + shape.used_width()) + .unwrap_or(0), None => text.len(), } } @@ -168,15 +166,13 @@ pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { #[inline] pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { match stmt.node { - ast::StmtKind::Semi(ref expr) => { - match expr.node { - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::ForLoop(..) => false, - _ => true, - } - } + ast::StmtKind::Semi(ref expr) => match expr.node { + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::ForLoop(..) => false, + _ => true, + }, ast::StmtKind::Expr(..) => false, _ => true, } diff --git a/src/visitor.rs b/src/visitor.rs index 800f46374ec..a1258092e8d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -289,12 +289,10 @@ impl<'a> FmtVisitor<'a> { assert!(!self.visit_attrs(&attrs)); } } - _ => { - if self.visit_attrs(&item.attrs) { - self.push_rewrite(item.span, None); - return; - } - } + _ => if self.visit_attrs(&item.attrs) { + self.push_rewrite(item.span, None); + return; + }, } match item.node { -- cgit 1.4.1-3-g733a5 From c11aac04a34b64fc90a5da5602a5b14a818fd71c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 11 Jul 2017 21:53:57 +0900 Subject: Update wrap_match_arms option tests and visual guide --- Configurations.md | 15 +++++---------- src/config.rs | 3 ++- tests/source/configs-wrap_match_arms-false.rs | 5 +---- tests/source/configs-wrap_match_arms-true.rs | 5 +---- tests/target/configs-wrap_match_arms-false.rs | 10 +++------- tests/target/configs-wrap_match_arms-true.rs | 3 +-- tests/target/match-nowrap.rs | 4 +--- 7 files changed, 14 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index cbf41b0f537..58124b8bc93 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1986,7 +1986,7 @@ Break comments to fit on the line ## `wrap_match_arms` -Wrap multiline match arms in blocks +Wrap the body of arms in blocks when it does not fit on the same line with the pattern of arms - **Default value**: `true` - **Possible values**: `true`, `false` @@ -1995,13 +1995,9 @@ Wrap multiline match arms in blocks ```rust match lorem { - true => { - let ipsum = dolor; - println!("{}", ipsum); - } - false => { - println!("{}", sit) - } + true => + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => println!("{}", sit), } ``` @@ -2010,8 +2006,7 @@ match lorem { ```rust match lorem { true => { - let ipsum = dolor; - println!("{}", ipsum); + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) } false => println!("{}", sit), } diff --git a/src/config.rs b/src/config.rs index 510cdef6f1b..2fe6d3ea6b6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -570,7 +570,8 @@ create_config! { wrap_comments: bool, false, "Break comments to fit on the line"; comment_width: usize, 80, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, "Convert /* */ comments to // comments where possible"; - wrap_match_arms: bool, true, "Wrap multiline match arms in blocks"; + wrap_match_arms: bool, true, "Wrap the body of arms in blocks when it does not fit on \ + the same line with the pattern of arms"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \ diff --git a/tests/source/configs-wrap_match_arms-false.rs b/tests/source/configs-wrap_match_arms-false.rs index 5d0337a0c7d..d1c05c27fd7 100644 --- a/tests/source/configs-wrap_match_arms-false.rs +++ b/tests/source/configs-wrap_match_arms-false.rs @@ -3,10 +3,7 @@ fn main() { match lorem { - true => { - let ipsum = dolor; - println!("{:?}", ipsum); - } + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), false => { println!("{}", sit) } diff --git a/tests/source/configs-wrap_match_arms-true.rs b/tests/source/configs-wrap_match_arms-true.rs index fb74fb4f620..8ddc5ebdc2e 100644 --- a/tests/source/configs-wrap_match_arms-true.rs +++ b/tests/source/configs-wrap_match_arms-true.rs @@ -3,10 +3,7 @@ fn main() { match lorem { - true => { - let ipsum = dolor; - println!("{}", ipsum); - } + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), false => { println!("{}", sit) } diff --git a/tests/target/configs-wrap_match_arms-false.rs b/tests/target/configs-wrap_match_arms-false.rs index 5d0337a0c7d..e4ca37bc6e5 100644 --- a/tests/target/configs-wrap_match_arms-false.rs +++ b/tests/target/configs-wrap_match_arms-false.rs @@ -3,12 +3,8 @@ fn main() { match lorem { - true => { - let ipsum = dolor; - println!("{:?}", ipsum); - } - false => { - println!("{}", sit) - } + true => + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => println!("{}", sit), } } diff --git a/tests/target/configs-wrap_match_arms-true.rs b/tests/target/configs-wrap_match_arms-true.rs index 3655a62f618..f6307e53e43 100644 --- a/tests/target/configs-wrap_match_arms-true.rs +++ b/tests/target/configs-wrap_match_arms-true.rs @@ -4,8 +4,7 @@ fn main() { match lorem { true => { - let ipsum = dolor; - println!("{}", ipsum); + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) } false => println!("{}", sit), } diff --git a/tests/target/match-nowrap.rs b/tests/target/match-nowrap.rs index 3849a8fb0e0..14571098218 100644 --- a/tests/target/match-nowrap.rs +++ b/tests/target/match-nowrap.rs @@ -4,9 +4,7 @@ fn foo() { match x { - a => { - foo() - } + a => foo(), b => ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, -- cgit 1.4.1-3-g733a5 From 2fb66cd1d3963dd66c536865a8413a677f6aa470 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 11 Jul 2017 22:41:38 +0900 Subject: Add trailing_semicolon config option trailing_semicolon controls whether to add a trailing semicolon after break, continue and return. --- Configurations.md | 21 ++++++++++++++++++ src/config.rs | 1 + src/expr.rs | 6 +++++- src/items.rs | 6 +++++- src/utils.rs | 11 +++++++--- src/visitor.rs | 2 +- tests/target/configs-trailing_semicolon-false.rs | 27 ++++++++++++++++++++++++ tests/target/configs-trailing_semicolon-true.rs | 27 ++++++++++++++++++++++++ 8 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 tests/target/configs-trailing_semicolon-false.rs create mode 100644 tests/target/configs-trailing_semicolon-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 58124b8bc93..2e1cdc9dccf 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1698,6 +1698,27 @@ let Lorem { See also: [`match_block_trailing_comma`](#match_block_trailing_comma). +## `trailing_semicolon` + +Add trailing semicolon after break, continue and return + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `true`: +```rust +fn foo() -> usize { + return 0; +} +``` + +#### `false`: +```rust +fn foo() -> usize { + return 0 +} +``` + ## `type_punctuation_density` Determines if `+` or `=` are wrapped in spaces in the punctuation of types diff --git a/src/config.rs b/src/config.rs index 2fe6d3ea6b6..1965675a83e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -519,6 +519,7 @@ create_config! { impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, "How to handle trailing commas for lists"; + trailing_semicolon: bool, true, "Add trailing semicolon after break, continue and return"; fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; fn_single_line: bool, false, "Put single-expression functions on a single line"; fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, diff --git a/src/expr.rs b/src/expr.rs index 9adb601c9cb..e1162521859 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -906,7 +906,11 @@ impl Rewrite for ast::Stmt { let result = match self.node { ast::StmtKind::Local(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { - let suffix = if semicolon_for_stmt(self) { ";" } else { "" }; + let suffix = if semicolon_for_stmt(context, self) { + ";" + } else { + "" + }; format_expr( ex, diff --git a/src/items.rs b/src/items.rs index 7e79e0a0b45..2f3018a2552 100644 --- a/src/items.rs +++ b/src/items.rs @@ -352,7 +352,11 @@ impl<'a> FmtVisitor<'a> { if let Some(ref stmt) = block.stmts.first() { match stmt_expr(stmt) { Some(e) => { - let suffix = if semicolon_for_expr(e) { ";" } else { "" }; + let suffix = if semicolon_for_expr(&self.get_context(), e) { + ";" + } else { + "" + }; format_expr( &e, diff --git a/src/utils.rs b/src/utils.rs index 2e0dce52e91..bdf5c2e4b5e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -156,21 +156,26 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { } #[inline] -pub fn semicolon_for_expr(expr: &ast::Expr) -> bool { +pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { match expr.node { - ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => true, + ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { + context.config.trailing_semicolon() + } _ => false, } } #[inline] -pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool { +pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { match stmt.node { ast::StmtKind::Semi(ref expr) => match expr.node { ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) => false, + ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { + context.config.trailing_semicolon() + } _ => true, }, ast::StmtKind::Expr(..) => false, diff --git a/src/visitor.rs b/src/visitor.rs index a1258092e8d..3bb533a00fd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -144,7 +144,7 @@ impl<'a> FmtVisitor<'a> { if !b.stmts.is_empty() { if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { - if utils::semicolon_for_expr(expr) { + if utils::semicolon_for_expr(&self.get_context(), expr) { self.buffer.push_str(";"); } } diff --git a/tests/target/configs-trailing_semicolon-false.rs b/tests/target/configs-trailing_semicolon-false.rs new file mode 100644 index 00000000000..9fa746e9c0f --- /dev/null +++ b/tests/target/configs-trailing_semicolon-false.rs @@ -0,0 +1,27 @@ +// rustfmt-trailing_semicolon: false + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b + } + + let x = loop { + break 5 + }; + + let x = 'c: loop { + break 'c 5 + }; +} + +fn foo() -> usize { + return 0 +} diff --git a/tests/target/configs-trailing_semicolon-true.rs b/tests/target/configs-trailing_semicolon-true.rs new file mode 100644 index 00000000000..61b6843d677 --- /dev/null +++ b/tests/target/configs-trailing_semicolon-true.rs @@ -0,0 +1,27 @@ +// rustfmt-trailing_semicolon: true + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} + +fn foo() -> usize { + return 0; +} -- cgit 1.4.1-3-g733a5 From 51641f167eef95b9d47f3ab61f63fb0aea0a7162 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 10 Jul 2017 16:45:21 +0900 Subject: Do not count the number of parens inside str or comment --- src/visitor.rs | 46 +++++++++++++++++++++++++++++++++++++++++++--- tests/source/attrib.rs | 13 +++++++++++++ tests/target/attrib.rs | 13 +++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 3bb533a00fd..6f81496856b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -729,9 +729,49 @@ impl Rewrite for ast::NestedMetaItem { } fn count_missing_closing_parens(s: &str) -> u32 { - let op_parens = s.chars().filter(|c| *c == '(').count(); - let cl_parens = s.chars().filter(|c| *c == ')').count(); - op_parens.checked_sub(cl_parens).unwrap_or(0) as u32 + let mut op_parens: u32 = 0; + let mut cl_parens: u32 = 0; + + #[derive(Eq, PartialEq)] + pub enum SnippetState { + Normal, + InsideStr, + InsideBulletComment, + InsideSingleLineComment, + } + + let mut state = SnippetState::Normal; + let mut iter = s.chars().peekable(); + let mut prev_char: Option = None; + while let Some(c) = iter.next() { + let next_char = iter.peek(); + match c { + '/' if state == SnippetState::Normal => match next_char { + Some(&'*') => state = SnippetState::InsideBulletComment, + Some(&'/') if prev_char.map_or(true, |c| c != '*') => { + state = SnippetState::InsideSingleLineComment; + } + _ => (), + }, + '*' if state == SnippetState::InsideBulletComment && + next_char.map_or(false, |c| *c == '/') => + { + state = SnippetState::Normal; + } + '\n' if state == SnippetState::InsideSingleLineComment => state = SnippetState::Normal, + '"' if state == SnippetState::InsideStr && prev_char.map_or(false, |c| c != '\\') => { + state = SnippetState::Normal; + } + '"' if state == SnippetState::Normal && prev_char.map_or(false, |c| c != '\\') => { + state = SnippetState::InsideStr + } + '(' if state == SnippetState::Normal => op_parens += 1, + ')' if state == SnippetState::Normal => cl_parens += 1, + _ => (), + } + prev_char = Some(c); + } + op_parens.checked_sub(cl_parens).unwrap_or(0) } impl Rewrite for ast::MetaItem { diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 313dbbb1276..324f0c69fc4 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -68,3 +68,16 @@ fn foo() { #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] let x = 3; } + +// #1777 +#[test] +#[should_panic(expected = "(")] +#[should_panic(expected = /* ( */ "(")] +#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] +#[should_panic( + /* (((((((( *//* + (((((((((()(((((((( */ + expected = "(" + // (((((((( +)] +fn foo() {} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index fa14f3c8647..2e08ec5cc34 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -68,3 +68,16 @@ fn foo() { #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] let x = 3; } + +// #1777 +#[test] +#[should_panic(expected = "(")] +#[should_panic(expected = /* ( */ "(")] +#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] +#[should_panic( + /* (((((((( *//* + (((((((((()(((((((( */ + expected = "(" + // (((((((( +)] +fn foo() {} -- cgit 1.4.1-3-g733a5 From 27b04fec1a05b4ebf034dcd466a04bb40fd06f4f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 13 Jul 2017 18:36:31 +0900 Subject: Sort items within import alphabetically in groups We group items in snake_case, CamelCase and SCREAMING_SNAKE_CASE --- src/imports.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index d284b235c5e..8c38f37f263 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -310,6 +310,78 @@ fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { } } +#[derive(Eq, PartialEq)] +enum ImportItem<'a> { + // `self` or `self as a` + SelfImport(&'a str), + // name_one, name_two, ... + SnakeCase(&'a str), + // NameOne, NameTwo, ... + CamelCase(&'a str), + // NAME_ONE, NAME_TWO, ... + AllCaps(&'a str), + // Failed to format the import item + Invalid, +} + +impl<'a> ImportItem<'a> { + fn from_str(s: &str) -> ImportItem { + if s == "self" || s.starts_with("self as") { + ImportItem::SelfImport(s) + } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') { + ImportItem::SnakeCase(s) + } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') { + ImportItem::AllCaps(s) + } else { + ImportItem::CamelCase(s) + } + } + + fn from_opt_str(s: Option<&String>) -> ImportItem { + s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s)) + } + + fn to_str(&self) -> Option<&str> { + match *self { + ImportItem::SelfImport(s) | + ImportItem::SnakeCase(s) | + ImportItem::CamelCase(s) | + ImportItem::AllCaps(s) => Some(s), + ImportItem::Invalid => None, + } + } + + fn to_u32(&self) -> u32 { + match *self { + ImportItem::SelfImport(..) => 0, + ImportItem::SnakeCase(..) => 1, + ImportItem::CamelCase(..) => 2, + ImportItem::AllCaps(..) => 3, + ImportItem::Invalid => 4, + } + } +} + +impl<'a> PartialOrd for ImportItem<'a> { + fn partial_cmp(&self, other: &ImportItem<'a>) -> Option { + Some(self.cmp(other)) + } +} + +impl<'a> Ord for ImportItem<'a> { + fn cmp(&self, other: &ImportItem<'a>) -> Ordering { + let res = self.to_u32().cmp(&other.to_u32()); + if res != Ordering::Equal { + return res; + } + self.to_str().map_or(Ordering::Greater, |self_str| { + other + .to_str() + .map_or(Ordering::Less, |other_str| self_str.cmp(other_str)) + }) + } +} + // Pretty prints a multi-item import. // Assumes that path_list.len() > 0. pub fn rewrite_use_list( @@ -366,7 +438,11 @@ pub fn rewrite_use_list( let first_index = if has_self { 0 } else { 1 }; if context.config.reorder_imported_names() { - items[1..].sort_by(|a, b| a.item.cmp(&b.item)); + items[1..].sort_by(|a, b| { + let a = ImportItem::from_opt_str(a.item.as_ref()); + let b = ImportItem::from_opt_str(b.item.as_ref()); + a.cmp(&b) + }); } -- cgit 1.4.1-3-g733a5 From 6fd291981e1bb7deba30644c09798087e84203ec Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 13 Jul 2017 18:42:14 +0900 Subject: Sort imports in alphabetical and consistent order --- src/bin/cargo-fmt.rs | 3 +-- src/bin/rustfmt.rs | 8 ++++---- src/chains.rs | 6 +++--- src/checkstyle.rs | 5 +++-- src/comment.rs | 6 +++--- src/config.rs | 5 ++--- src/expr.rs | 42 +++++++++++++++++++++--------------------- src/filemap.rs | 10 +++++----- src/imports.rs | 15 ++++++++------- src/issues.rs | 1 + src/items.rs | 24 ++++++++++++------------ src/lib.rs | 31 +++++++++++++------------------ src/lists.rs | 2 +- src/macros.rs | 8 ++++---- src/missed_spans.rs | 8 ++++---- src/modules.rs | 8 ++++---- src/patterns.rs | 23 +++++++++++------------ src/rustfmt_diff.rs | 14 ++++++++++++-- src/string.rs | 6 +++--- src/types.rs | 16 ++++++++-------- src/utils.rs | 9 +++++---- src/vertical.rs | 6 +++--- src/visitor.rs | 19 +++++++++---------- 23 files changed, 140 insertions(+), 135 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3f7d11c0a97..b07a40804dd 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -24,10 +24,9 @@ use std::str; use std::collections::HashSet; use std::iter::FromIterator; +use getopts::{Matches, Options}; use json::Value; -use getopts::{Options, Matches}; - fn main() { let exit_status = execute(); std::io::stdout().flush().unwrap(); diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index d2f2f3d761b..f0846b43ea8 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -17,10 +17,6 @@ extern crate toml; extern crate env_logger; extern crate getopts; -use rustfmt::{run, Input, Summary}; -use rustfmt::file_lines::FileLines; -use rustfmt::config::{Config, WriteMode, get_toml_path}; - use std::{env, error}; use std::fs::File; use std::io::{self, Read, Write}; @@ -29,6 +25,10 @@ use std::str::FromStr; use getopts::{Matches, Options}; +use rustfmt::{run, Input, Summary}; +use rustfmt::file_lines::FileLines; +use rustfmt::config::{get_toml_path, Config, WriteMode}; + type FmtError = Box; type FmtResult = std::result::Result; diff --git a/src/chains.rs b/src/chains.rs index 1660e113dcd..fdf0a80709b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -77,11 +77,11 @@ /// ``` use Shape; -use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, first_line_width, last_line_width, mk_sp, last_line_extendable}; -use expr::rewrite_call; use config::IndentStyle; +use expr::rewrite_call; use macros::convert_try_mac; +use rewrite::{Rewrite, RewriteContext}; +use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, wrap_str}; use std::cmp::min; use std::iter; diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 7b7ab2e1b2d..0934ed3f719 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -7,10 +7,11 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustfmt_diff::{Mismatch, DiffLine}; + use std::io::{self, Write}; -use config::WriteMode; +use config::WriteMode; +use rustfmt_diff::{DiffLine, Mismatch}; pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> where diff --git a/src/comment.rs b/src/comment.rs index df97c2bfef3..b3fd171b86f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -17,7 +17,7 @@ use syntax::codemap::Span; use {Indent, Shape}; use config::Config; use rewrite::RewriteContext; -use string::{StringFormat, rewrite_string}; +use string::{rewrite_string, StringFormat}; use utils::wrap_str; fn is_custom_comment(comment: &str) -> bool { @@ -809,8 +809,8 @@ fn remove_comment_header(comment: &str) -> &str { #[cfg(test)] mod test { - use super::{CharClasses, CodeCharKind, FullCodeCharKind, contains_comment, rewrite_comment, - FindUncommented, CommentCodeSlices}; + use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, + FindUncommented, FullCodeCharKind}; use {Indent, Shape}; #[test] diff --git a/src/config.rs b/src/config.rs index 1965675a83e..995e6164cf4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,15 +10,14 @@ extern crate toml; +use std::{env, fs}; use std::cell::Cell; -use std::fs; use std::fs::File; -use std::env; use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; use file_lines::FileLines; -use lists::{SeparatorTactic, ListTactic}; +use lists::{ListTactic, SeparatorTactic}; macro_rules! configuration_option_enum{ ($e:ident: $( $x:ident ),+ $(,)*) => { diff --git a/src/expr.rs b/src/expr.rs index e1162521859..88f56cfa25c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,33 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cmp::{Ordering, min}; -use std::iter::ExactSizeIterator; +use std::cmp::{min, Ordering}; use std::fmt::Write; +use std::iter::ExactSizeIterator; + +use syntax::{ast, ptr}; +use syntax::codemap::{BytePos, CodeMap, Span}; +use syntax::parse::classify; use {Indent, Shape, Spanned}; -use codemap::SpanUtils; -use rewrite::{Rewrite, RewriteContext}; -use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - DefinitiveListTactic, definitive_tactic, ListItem, struct_lit_shape, - struct_lit_tactic, shape_for_tactic, struct_lit_formatting}; -use string::{StringFormat, rewrite_string}; -use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width, - semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr, - colon_spaces, contains_skip, mk_sp, last_line_extendable, paren_overhead}; -use visitor::FmtVisitor; -use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style}; -use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed}; -use types::{rewrite_path, PathContext, can_be_overflowed_type}; -use items::{span_lo_for_arg, span_hi_for_arg}; use chains::rewrite_chain; +use codemap::SpanUtils; +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; +use items::{span_hi_for_arg, span_lo_for_arg}; +use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, + struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, + ListItem, ListTactic, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; -use patterns::{TuplePatField, can_be_overflowed_pat}; +use patterns::{can_be_overflowed_pat, TuplePatField}; +use rewrite::{Rewrite, RewriteContext}; +use string::{rewrite_string, StringFormat}; +use types::{can_be_overflowed_type, rewrite_path, PathContext}; +use utils::{binary_search, colon_spaces, contains_skip, extra_offset, first_line_width, + last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, paren_overhead, + semicolon_for_stmt, stmt_expr, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; - -use syntax::{ast, ptr}; -use syntax::codemap::{CodeMap, Span, BytePos}; -use syntax::parse::classify; +use visitor::FmtVisitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { diff --git a/src/filemap.rs b/src/filemap.rs index e9779edfe5c..ee0a21b39b1 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -11,14 +11,14 @@ // TODO: add tests -use strings::string_buffer::StringBuffer; - use std::fs::{self, File}; -use std::io::{self, Write, Read, BufWriter}; +use std::io::{self, BufWriter, Read, Write}; + +use strings::string_buffer::StringBuffer; -use config::{NewlineStyle, Config, WriteMode}; +use checkstyle::{output_checkstyle_file, output_footer, output_header}; +use config::{Config, NewlineStyle, WriteMode}; use rustfmt_diff::{make_diff, print_diff, Mismatch}; -use checkstyle::{output_header, output_footer, output_checkstyle_file}; // A map of the files of a crate, with their new content pub type FileMap = Vec; diff --git a/src/imports.rs b/src/imports.rs index 8c38f37f263..a43b281f3cf 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,17 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Shape; -use utils; +use std::cmp::{self, Ordering}; + +use syntax::{ast, ptr}; use syntax::codemap::{BytePos, Span}; + +use Shape; use codemap::SpanUtils; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, definitive_tactic}; -use types::{rewrite_path, PathContext}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; +use types::{rewrite_path, PathContext}; +use utils; use visitor::FmtVisitor; -use std::cmp::{self, Ordering}; - -use syntax::{ast, ptr}; fn path_of(a: &ast::ViewPath_) -> &ast::Path { match *a { diff --git a/src/issues.rs b/src/issues.rs index 432fb797a6e..b81f902d59f 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -13,6 +13,7 @@ // associated issue number. use std::fmt; + pub use config::ReportTactic; const TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O']; diff --git a/src/items.rs b/src/items.rs index 2f3018a2552..eb15e95fabb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,25 +10,25 @@ // Formatting top-level items - functions, structs, enums, traits, impls. +use syntax::{abi, ast, ptr, symbol}; +use syntax::ast::ImplItem; +use syntax::codemap::{BytePos, Span}; + use {Indent, Shape, Spanned}; use codemap::SpanUtils; -use utils::{format_mutability, format_visibility, contains_skip, end_typaram, wrap_str, - last_line_width, format_unsafety, trim_newlines, stmt_expr, semicolon_for_expr, - trimmed_last_line_width, colon_spaces, mk_sp}; -use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, - DefinitiveListTactic, ListTactic, definitive_tactic}; +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; -use comment::{FindUncommented, contains_comment, rewrite_comment, recover_comment_removed}; -use visitor::FmtVisitor; +use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, + ListItem, ListTactic, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; -use config::{Config, IndentStyle, Density, ReturnIndent, BraceStyle, Style}; use types::join_bounds; +use utils::{colon_spaces, contains_skip, end_typaram, format_mutability, format_unsafety, + format_visibility, last_line_width, mk_sp, semicolon_for_expr, stmt_expr, + trim_newlines, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; - -use syntax::{ast, abi, ptr, symbol}; -use syntax::codemap::{Span, BytePos}; -use syntax::ast::ImplItem; +use visitor::FmtVisitor; fn type_annotation_separator(config: &Config) -> &str { colon_spaces( diff --git a/src/lib.rs b/src/lib.rs index 030d18c3000..088f0950f10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,27 +28,26 @@ extern crate regex; extern crate diff; extern crate term; -use errors::{Handler, DiagnosticBuilder}; -use errors::emitter::{ColorConfig, EmitterWriter}; -use syntax::ast; -use syntax::codemap::{CodeMap, Span, FilePathMapping}; -use syntax::parse::{self, ParseSess}; - -use strings::string_buffer::StringBuffer; - +use std::collections::HashMap; +use std::fmt; use std::io::{self, stdout, Write}; use std::ops::{Add, Sub}; use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::collections::HashMap; -use std::fmt; -use issues::{BadIssueSeeker, Issue}; -use filemap::FileMap; -use visitor::FmtVisitor; +use errors::{DiagnosticBuilder, Handler}; +use errors::emitter::{ColorConfig, EmitterWriter}; +use strings::string_buffer::StringBuffer; +use syntax::ast; +use syntax::codemap::{CodeMap, FilePathMapping, Span}; +use syntax::parse::{self, ParseSess}; + +use checkstyle::{output_footer, output_header}; use config::Config; -use checkstyle::{output_header, output_footer}; +use filemap::FileMap; +use issues::{BadIssueSeeker, Issue}; use utils::mk_sp; +use visitor::FmtVisitor; pub use self::summary::Summary; @@ -78,10 +77,6 @@ mod patterns; mod summary; mod vertical; -const MIN_STRING: usize = 10; -// When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; - pub trait Spanned { fn span(&self) -> Span; } diff --git a/src/lists.rs b/src/lists.rs index 4bd7d76483a..e55103d0df8 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -11,7 +11,7 @@ use std::cmp; use std::iter::Peekable; -use syntax::codemap::{CodeMap, BytePos}; +use syntax::codemap::{BytePos, CodeMap}; use {Indent, Shape}; use comment::{find_comment_end, rewrite_comment, FindUncommented}; diff --git a/src/macros.rs b/src/macros.rs index 3f4adf88120..989aaaaa58c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -21,17 +21,17 @@ use syntax::ast; use syntax::codemap::BytePos; -use syntax::parse::token::Token; use syntax::parse::new_parser_from_tts; -use syntax::tokenstream::TokenStream; +use syntax::parse::token::Token; use syntax::symbol; +use syntax::tokenstream::TokenStream; use syntax::util::ThinVec; use Shape; use codemap::SpanUtils; +use comment::{contains_comment, FindUncommented}; +use expr::{rewrite_array, rewrite_call_inner}; use rewrite::{Rewrite, RewriteContext}; -use expr::{rewrite_call_inner, rewrite_array}; -use comment::{FindUncommented, contains_comment}; use utils::mk_sp; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index fb0e298bbbf..ac3ad906d17 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::WriteMode; -use visitor::FmtVisitor; -use syntax::codemap::{BytePos, Span, Pos}; -use comment::{CodeCharKind, CommentCodeSlices, rewrite_comment}; use Shape; +use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use config::WriteMode; +use syntax::codemap::{BytePos, Pos, Span}; use utils::mk_sp; +use visitor::FmtVisitor; impl<'a> FmtVisitor<'a> { fn output_at_start(&self) -> bool { diff --git a/src/modules.rs b/src/modules.rs index c8275520ca1..8e728f98cd1 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use utils; - -use std::path::{Path, PathBuf}; use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; use syntax::ast; use syntax::codemap; use syntax::parse::parser; +use utils::contains_skip; + /// List all the files containing modules of a crate. /// If a file is used twice in a crate, it appears only once. @@ -46,7 +46,7 @@ fn list_submodules<'a>( debug!("list_submodules: search_dir: {:?}", search_dir); for item in &module.items { if let ast::ItemKind::Mod(ref sub_mod) = item.node { - if !utils::contains_skip(&item.attrs) { + if !contains_skip(&item.attrs) { let is_internal = codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); let dir_path = if is_internal { diff --git a/src/patterns.rs b/src/patterns.rs index bcc57f93189..544285ec213 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -8,21 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Shape; +use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd}; +use syntax::codemap::{self, BytePos, Span}; +use syntax::ptr; + +use {Shape, Spanned}; use codemap::SpanUtils; -use rewrite::{Rewrite, RewriteContext}; -use utils::{wrap_str, format_mutability, mk_sp}; -use lists::{DefinitiveListTactic, SeparatorTactic, itemize_list, struct_lit_shape, - struct_lit_tactic, shape_for_tactic, struct_lit_formatting, write_list}; -use expr::{rewrite_call_inner, rewrite_unary_prefix, rewrite_pair, can_be_overflowed_expr, +use comment::FindUncommented; +use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, wrap_struct_field}; +use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorTactic}; +use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; -use super::Spanned; -use comment::FindUncommented; - -use syntax::ast::{self, BindingMode, Pat, PatKind, FieldPat, RangeEnd}; -use syntax::ptr; -use syntax::codemap::{self, BytePos, Span}; +use utils::{format_mutability, mk_sp, wrap_str}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index ff35a83cc63..3e9fd913d7c 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -1,7 +1,17 @@ -use std::collections::VecDeque; +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use diff; -use term; +use std::collections::VecDeque; use std::io; +use term; #[derive(Debug, PartialEq)] pub enum DiffLine { diff --git a/src/string.rs b/src/string.rs index 3efb406e796..00d8c0875e5 100644 --- a/src/string.rs +++ b/src/string.rs @@ -10,14 +10,14 @@ // Format string literals. -use unicode_segmentation::UnicodeSegmentation; use regex::Regex; +use unicode_segmentation::UnicodeSegmentation; use Shape; use config::Config; use utils::wrap_str; -use MIN_STRING; +const MIN_STRING: usize = 10; pub struct StringFormat<'a> { pub opener: &'a str, @@ -127,7 +127,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option #[cfg(test)] mod test { - use super::{StringFormat, rewrite_string}; + use super::{rewrite_string, StringFormat}; #[test] fn issue343() { diff --git a/src/types.rs b/src/types.rs index edab375b02d..877502f153c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,24 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::ops::Deref; use std::iter::ExactSizeIterator; +use std::ops::Deref; use syntax::abi; -use syntax::ast::{self, Mutability, FunctionRetTy}; -use syntax::codemap::{self, Span, BytePos}; +use syntax::ast::{self, FunctionRetTy, Mutability}; +use syntax::codemap::{self, BytePos, Span}; use syntax::print::pprust; use syntax::symbol::keywords; use {Shape, Spanned}; use codemap::SpanUtils; +use config::{IndentStyle, Style, TypeDensity}; +use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; use items::{format_generics_item_list, generics_shape_from_config}; -use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic, - definitive_tactic}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, + SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; -use utils::{extra_offset, format_mutability, colon_spaces, wrap_str, mk_sp, last_line_width}; -use expr::{rewrite_unary_prefix, rewrite_pair, rewrite_tuple, wrap_args_with_parens}; -use config::{IndentStyle, Style, TypeDensity}; +use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp, wrap_str}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { diff --git a/src/utils.rs b/src/utils.rs index bdf5c2e4b5e..dc511fc3101 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -11,15 +11,16 @@ use std::borrow::Cow; use std::cmp::Ordering; -use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItemKind, NestedMetaItem, - NestedMetaItemKind, Path}; -use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use syntax::abi; +use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, + Path, Visibility}; +use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use Shape; use rewrite::{Rewrite, RewriteContext}; -use SKIP_ANNOTATION; +// When we get scoped annotations, we should have rustfmt::skip. +const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; // Computes the length of a string's last line, minus offset. pub fn extra_offset(text: &str, shape: Shape) -> usize { diff --git a/src/vertical.rs b/src/vertical.rs index d6b34443518..04d9ac9d35b 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -12,6 +12,9 @@ use std::cmp; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; + use {Indent, Shape, Spanned}; use codemap::SpanUtils; use comment::contains_comment; @@ -21,9 +24,6 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTac use rewrite::{Rewrite, RewriteContext}; use utils::{contains_skip, mk_sp}; -use syntax::ast; -use syntax::codemap::{Span, BytePos}; - pub trait AlignedItem { fn skip(&self) -> bool; fn get_span(&self) -> Span; diff --git a/src/visitor.rs b/src/visitor.rs index 6f81496856b..97b6ce29269 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -10,24 +10,23 @@ use std::cmp; +use strings::string_buffer::StringBuffer; use syntax::{ast, ptr, visit}; -use syntax::codemap::{CodeMap, Span, BytePos}; +use syntax::codemap::{BytePos, CodeMap, Span}; use syntax::parse::ParseSess; -use strings::string_buffer::StringBuffer; - use {Indent, Shape}; -use expr::{format_expr, ExprType}; -use utils::{self, mk_sp}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, FindUncommented}; -use config::Config; -use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; -use macros::{rewrite_macro, MacroPosition}; -use items::{rewrite_static, rewrite_associated_type, rewrite_associated_impl_type, - rewrite_type_alias, format_impl, format_trait}; +use config::Config; +use expr::{format_expr, ExprType}; +use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, + rewrite_static, rewrite_type_alias}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorTactic}; +use macros::{rewrite_macro, MacroPosition}; +use rewrite::{Rewrite, RewriteContext}; +use utils::{self, mk_sp}; fn is_use_item(item: &ast::Item) -> bool { match item.node { -- cgit 1.4.1-3-g733a5 From d9dc13efe1db413c92fa460544d1282a285700a5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 13 Jul 2017 18:42:49 +0900 Subject: Set reorder_imported_names to true as default --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 995e6164cf4..58638899bd2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -558,7 +558,7 @@ create_config! { exceeds `chain_one_line_max`"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, false, "Reorder import statements in group"; - reorder_imported_names: bool, false, + reorder_imported_names: bool, true, "Reorder lists of names in import statements alphabetically"; single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ expressions. A value of zero means always break \ -- cgit 1.4.1-3-g733a5 From dcb953b901354bf89f7a9fbdfba8053e37e86894 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 13 Jul 2017 20:32:46 +0900 Subject: Add trailing comma when using Mixed indent style with newline --- src/expr.rs | 4 +++- src/items.rs | 23 +++++++++------------- src/lists.rs | 20 +++++++++++++++++-- src/types.rs | 2 +- tests/target/configs-fn_args_density-compressed.rs | 4 ++-- tests/target/fn-custom.rs | 4 ++-- tests/target/fn-simple.rs | 2 +- tests/target/hard-tabs.rs | 2 +- tests/target/type.rs | 2 +- 9 files changed, 38 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 88f56cfa25c..09220e9ac80 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -501,10 +501,12 @@ where DefinitiveListTactic::Mixed }, }; + let mut ends_with_newline = tactic.ends_with_newline(context.config.array_layout()); if context.config.array_horizontal_layout_threshold() > 0 && items.len() > context.config.array_horizontal_layout_threshold() { tactic = DefinitiveListTactic::Mixed; + ends_with_newline = false; if context.config.array_layout() == IndentStyle::Block { nested_shape = try_opt!( shape @@ -525,7 +527,7 @@ where SeparatorTactic::Vertical }, shape: nested_shape, - ends_with_newline: false, + ends_with_newline: ends_with_newline, config: context.config, }; let list_str = try_opt!(write_list(&items, &fmt)); diff --git a/src/items.rs b/src/items.rs index eb15e95fabb..aa83d9a2b0d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2204,21 +2204,18 @@ fn rewrite_args( .and_then(|item| item.post_comment.as_ref()) .map_or(false, |s| s.trim().starts_with("//")); - let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout() { - IndentStyle::Block if fits_in_one_line => ( - indent.block_indent(context.config), - SeparatorTactic::Never, - true, - ), + let (indent, trailing_comma) = match context.config.fn_args_layout() { + IndentStyle::Block if fits_in_one_line => { + (indent.block_indent(context.config), SeparatorTactic::Never) + } IndentStyle::Block => ( indent.block_indent(context.config), context.config.trailing_comma(), - true, ), IndentStyle::Visual if last_line_ends_with_comment => { - (arg_indent, context.config.trailing_comma(), true) + (arg_indent, context.config.trailing_comma()) } - IndentStyle::Visual => (arg_indent, SeparatorTactic::Never, false), + IndentStyle::Visual => (arg_indent, SeparatorTactic::Never), }; let tactic = definitive_tactic( @@ -2242,7 +2239,7 @@ fn rewrite_args( trailing_comma }, shape: Shape::legacy(budget, indent), - ends_with_newline: end_with_newline, + ends_with_newline: tactic.ends_with_newline(context.config.fn_args_layout()), config: context.config, }; @@ -2406,8 +2403,6 @@ where let item_vec = items.collect::>(); let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, one_line_budget); - let ends_with_newline = context.config.generics_indent() == IndentStyle::Block && - tactic == DefinitiveListTactic::Vertical; let fmt = ListFormatting { tactic: tactic, separator: ",", @@ -2417,7 +2412,7 @@ where context.config.trailing_comma() }, shape: shape, - ends_with_newline: ends_with_newline, + ends_with_newline: tactic.ends_with_newline(context.config.generics_indent()), config: context.config, }; @@ -2631,7 +2626,7 @@ fn rewrite_where_clause( separator: ",", trailing_separator: comma_tactic, shape: Shape::legacy(budget, offset), - ends_with_newline: true, + ends_with_newline: tactic.ends_with_newline(context.config.where_pred_indent()), config: context.config, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); diff --git a/src/lists.rs b/src/lists.rs index e55103d0df8..55db7cd9c00 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -124,6 +124,15 @@ pub enum DefinitiveListTactic { Mixed, } +impl DefinitiveListTactic { + pub fn ends_with_newline(&self, indent_style: IndentStyle) -> bool { + match indent_style { + IndentStyle::Block => *self != DefinitiveListTactic::Horizontal, + IndentStyle::Visual => false, + } + } +} + pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic where I: IntoIterator + Clone, @@ -169,7 +178,7 @@ where // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. - let trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); + let mut trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); let mut result = String::new(); let cloned_items = items.clone(); let mut iter = items.into_iter().enumerate().peekable(); @@ -182,7 +191,7 @@ where let inner_item = try_opt!(item.item.as_ref()); let first = i == 0; let last = iter.peek().is_none(); - let separate = !last || trailing_separator; + let mut separate = !last || trailing_separator; let item_sep_len = if separate { sep_len } else { 0 }; // Item string may be multi-line. Its length (used for block comment alignment) @@ -213,6 +222,13 @@ where result.push('\n'); result.push_str(indent_str); line_len = 0; + if tactic == DefinitiveListTactic::Mixed && formatting.ends_with_newline { + if last { + separate = true; + } else { + trailing_separator = true; + } + } } if line_len > 0 { diff --git a/src/types.rs b/src/types.rs index 877502f153c..c34a3bfaa6a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -360,7 +360,7 @@ where context.config.trailing_comma() }, shape: list_shape, - ends_with_newline: false, + ends_with_newline: tactic.ends_with_newline(context.config.fn_call_style()), config: context.config, }; diff --git a/tests/target/configs-fn_args_density-compressed.rs b/tests/target/configs-fn_args_density-compressed.rs index 7bc949e5518..99283722bee 100644 --- a/tests/target/configs-fn_args_density-compressed.rs +++ b/tests/target/configs-fn_args_density-compressed.rs @@ -10,12 +10,12 @@ trait Lorem { fn lorem( ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit + adipiscing: Adipiscing, elit: Elit, ); fn lorem( ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit + adipiscing: Adipiscing, elit: Elit, ) { // body } diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index 7a2ea722bfd..bf87553dedc 100644 --- a/tests/target/fn-custom.rs +++ b/tests/target/fn-custom.rs @@ -4,7 +4,7 @@ // Test compressed layout of args. fn foo( a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee + e: Eeeeeeeeeeeeeeeeeee, ) { foo(); } @@ -12,7 +12,7 @@ fn foo( impl Foo { fn foo( self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee, ) { foo(); } diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index e150973a67d..e381b6e6231 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -42,7 +42,7 @@ where C, D, // pre comment - E, /* last comment */ + E, // last comment ) -> &SomeType, { arg(a, b, c, d, e) diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index c2f8d252237..4ac6df5def8 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -67,7 +67,7 @@ fn main() { C, D, // pre comment - E, /* last comment */ + E, // last comment ) -> &SomeType, { arg(a, b, c, d, e) diff --git a/tests/target/type.rs b/tests/target/type.rs index 80855ee5732..5a12989c857 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -25,7 +25,7 @@ struct F { y: String, // comment 3 z: Foo, // comment - ... /* comment 2 */ + ... // comment 2 ), } -- cgit 1.4.1-3-g733a5 From 988e387132cf4137ecbba7f212ec37f52928d42b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 13 Jul 2017 20:40:49 +0900 Subject: Add imports_indent and imports_layout config options --- Configurations.md | 81 ++++++++++++++++++++++ src/config.rs | 2 + src/imports.rs | 79 +++++++++++++-------- tests/target/configs-imports_indent-block.rs | 7 ++ .../configs-imports_layout-horizontal_vertical.rs | 18 +++++ tests/target/configs-imports_layout-mixed.rs | 9 +++ 6 files changed, 168 insertions(+), 28 deletions(-) create mode 100644 tests/target/configs-imports_indent-block.rs create mode 100644 tests/target/configs-imports_layout-horizontal_vertical.rs create mode 100644 tests/target/configs-imports_layout-mixed.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 2e1cdc9dccf..f97214c1358 100644 --- a/Configurations.md +++ b/Configurations.md @@ -979,6 +979,87 @@ match lorem { See also: [`match_block_trailing_comma`](#match_block_trailing_comma), [`wrap_match_arms`](#wrap_match_arms). +## `imports_indent` + +Indent style of imports + +- **Default Value**: `"Visual"` +- **Possible values**: `"Block"`, `"Visual"` + +#### `"Block"` + +```rust +use foo::{ + xxx, + yyy, + zzz, +}; +``` + +#### `"Visual"` + +```rust +use foo::{xxx, + yyy, + zzz}; +``` + +See also: [`imports_layout`](#imports_layout). + +## `imports_layout` + +Item layout inside a imports block + +- **Default value**: "Mixed" +- **Possible values**: "Horizontal", "HorizontalVertical", "Mixed", "Vertical" + +#### `"Mixed"` + +```rust +use foo::{xxx, yyy, zzz}; + +use foo::{aaa, bbb, ccc, + ddd, eee, fff}; +``` + +#### `"Horizontal"` + +**Note**: This option forces to put everything on one line and may exceeds `max_width`. + +```rust +use foo::{xxx, yyy, zzz}; + +use foo::{aaa, bbb, ccc, ddd, eee, fff}; +``` + +#### `"HorizontalVertical"` + +```rust +use foo::{xxx, yyy, zzz}; + +use foo::{aaa, + bbb, + ccc, + ddd, + eee, + fff}; +``` + +#### `"Vertical"` + +```rust +use foo::{xxx, + yyy, + zzz}; + +use foo::{aaa, + bbb, + ccc, + ddd, + eee, + fff}; +``` + ## `item_brace_style` Brace style for structs and enums diff --git a/src/config.rs b/src/config.rs index 58638899bd2..173f076bebb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -556,6 +556,8 @@ create_config! { chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line"; chain_split_single_child: bool, false, "Split a chain with a single child if its length \ exceeds `chain_one_line_max`"; + imports_indent: IndentStyle, IndentStyle::Visual, "Indent of imports"; + imports_layout: ListTactic, ListTactic::Mixed, "Item layout inside a import block"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, false, "Reorder import statements in group"; reorder_imported_names: bool, true, diff --git a/src/imports.rs b/src/imports.rs index a43b281f3cf..1ce397f6c5a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -15,7 +15,9 @@ use syntax::codemap::{BytePos, Span}; use Shape; use codemap::SpanUtils; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, SeparatorTactic}; +use config::IndentStyle; +use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, + ListItem, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; use utils; @@ -250,13 +252,12 @@ impl<'a> FmtVisitor<'a> { pub fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { let vis = utils::format_visibility(vis); - let mut offset = self.block_indent; - offset.alignment += vis.len() + "use ".len(); - // 1 = ";" - match vp.rewrite( - &self.get_context(), - Shape::legacy(self.config.max_width() - offset.width() - 1, offset), - ) { + // 4 = `use `, 1 = `;` + let rw = Shape::indented(self.block_indent, self.config) + .offset_left(vis.len() + 4) + .and_then(|shape| shape.sub_width(1)) + .and_then(|shape| vp.rewrite(&self.get_context(), shape)); + match rw { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo); @@ -385,7 +386,7 @@ impl<'a> Ord for ImportItem<'a> { // Pretty prints a multi-item import. // Assumes that path_list.len() > 0. -pub fn rewrite_use_list( +fn rewrite_use_list( shape: Shape, path: &ast::Path, path_list: &[ast::PathListItem], @@ -407,13 +408,14 @@ pub fn rewrite_use_list( _ => (), } - let colons_offset = if path_str.is_empty() { 0 } else { 2 }; + let path_str = if path_str.is_empty() { + path_str + } else { + format!("{}::", path_str) + }; // 2 = "{}" - let remaining_width = shape - .width - .checked_sub(path_str.len() + 2 + colons_offset) - .unwrap_or(0); + let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); let mut items = { // Dummy value, see explanation below. @@ -446,32 +448,53 @@ pub fn rewrite_use_list( }); } - let tactic = definitive_tactic( &items[first_index..], - ::lists::ListTactic::Mixed, + context.config.imports_layout(), remaining_width, ); + let nested_indent = match context.config.imports_indent() { + IndentStyle::Block => shape.indent.block_indent(context.config), + // 1 = `{` + IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, + }; + + let nested_shape = match context.config.imports_indent() { + IndentStyle::Block => Shape::indented(nested_indent, context.config), + IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), + }; + + let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && + tactic != DefinitiveListTactic::Horizontal; + let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::Never, - // Add one to the indent to account for "{" - shape: Shape::legacy( - remaining_width, - shape.indent + path_str.len() + colons_offset + 1, - ), - ends_with_newline: false, + trailing_separator: if ends_with_newline { + context.config.trailing_comma() + } else { + SeparatorTactic::Never + }, + shape: nested_shape, + ends_with_newline: ends_with_newline, config: context.config, }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); - Some(if path_str.is_empty() { - format!("{{{}}}", list_str) - } else { - format!("{}::{{{}}}", path_str, list_str) - }) + let result = + if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block { + format!( + "{}{{\n{}{}\n{}}}", + path_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.indent.to_string(context.config) + ) + } else { + format!("{}{{{}}}", path_str, list_str) + }; + Some(result) } // Returns true when self item was found. diff --git a/tests/target/configs-imports_indent-block.rs b/tests/target/configs-imports_indent-block.rs new file mode 100644 index 00000000000..84c3b26bd6e --- /dev/null +++ b/tests/target/configs-imports_indent-block.rs @@ -0,0 +1,7 @@ +// rustfmt-imports_indent: Block + +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, + SeparatorTactic, +}; diff --git a/tests/target/configs-imports_layout-horizontal_vertical.rs b/tests/target/configs-imports_layout-horizontal_vertical.rs new file mode 100644 index 00000000000..4a63556d45b --- /dev/null +++ b/tests/target/configs-imports_layout-horizontal_vertical.rs @@ -0,0 +1,18 @@ +// rustfmt-imports_indent: Block +// rustfmt-imports_layout: HorizontalVertical + +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use lists::{ + definitive_tactic, + itemize_list, + shape_for_tactic, + struct_lit_formatting, + struct_lit_shape, + struct_lit_tactic, + write_list, + DefinitiveListTactic, + ListFormatting, + ListItem, + ListTactic, + SeparatorTactic, +}; diff --git a/tests/target/configs-imports_layout-mixed.rs b/tests/target/configs-imports_layout-mixed.rs new file mode 100644 index 00000000000..5d3349a01bb --- /dev/null +++ b/tests/target/configs-imports_layout-mixed.rs @@ -0,0 +1,9 @@ +// rustfmt-imports_indent: Block +// rustfmt-imports_layout: Mixed + +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, + SeparatorTactic, +}; -- cgit 1.4.1-3-g733a5 From de403f4f65e0c22de2ebab9b034154203a204940 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 19 Jul 2017 22:50:28 +0900 Subject: Use offset_left instead of shrink_left --- src/chains.rs | 2 +- src/comment.rs | 12 ++++++------ src/expr.rs | 10 +++++----- src/items.rs | 2 +- tests/target/expr.rs | 2 +- tests/target/issue-1239.rs | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index fdf0a80709b..5c98308e40c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -561,7 +561,7 @@ fn choose_first_connector<'a>( if subexpr_list.is_empty() { "" } else if extend || subexpr_list.last().map_or(false, is_try) || - is_extendable_parent(context, parent_str) + is_extendable_parent(context, parent_str) { // 1 = ";", being conservative here. if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <= diff --git a/src/comment.rs b/src/comment.rs index b3fd171b86f..35ff88d86d1 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -124,7 +124,7 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { CommentStyle::DoubleSlash } } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) || - (orig.starts_with("/**") && !orig.starts_with("/**/")) + (orig.starts_with("/**") && !orig.starts_with("/**/")) { CommentStyle::TripleSlash } else if orig.starts_with("//!") || orig.starts_with("/*!") { @@ -314,13 +314,13 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { &line[opener.trim_right().len()..] } } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || - line.starts_with("///") || - line.starts_with("** ") || line.starts_with("/*!") || - (line.starts_with("/**") && !line.starts_with("/**/")) + line.starts_with("///") || + line.starts_with("** ") || line.starts_with("/*!") || + (line.starts_with("/**") && !line.starts_with("/**/")) { &line[3..] } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || - line.starts_with("**") + line.starts_with("**") { &line[2..] } else if line.starts_with('*') { @@ -795,7 +795,7 @@ fn remove_comment_header(comment: &str) -> &str { } else if comment.starts_with("//") { &comment[2..] } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) || - comment.starts_with("/*!") + comment.starts_with("/*!") { &comment[3..comment.len() - 2] } else { diff --git a/src/expr.rs b/src/expr.rs index 09220e9ac80..896ecebb68e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -375,7 +375,7 @@ where } // Try rewriting the rhs into the remaining space. - let rhs_shape = shape.shrink_left(last_line_width(&result) + suffix.len()); + let rhs_shape = shape.offset_left(last_line_width(&result) + suffix.len()); if let Some(rhs_shape) = rhs_shape { if let Some(rhs_result) = rhs.rewrite(context, rhs_shape) { // FIXME this should always hold. @@ -572,7 +572,7 @@ fn rewrite_closure_fn_decl( // 1 = | let argument_offset = nested_shape.indent + 1; - let arg_shape = try_opt!(nested_shape.shrink_left(1)).visual_indent(0); + let arg_shape = try_opt!(nested_shape.offset_left(1)).visual_indent(0); let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape)); let arg_items = itemize_list( @@ -1168,7 +1168,7 @@ impl<'a> ControlFlow<'a> { let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - try_opt!(shape.shrink_left(7)) + try_opt!(shape.offset_left(7)) } else { shape }; @@ -1243,7 +1243,7 @@ impl<'a> ControlFlow<'a> { let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine || - force_newline_brace + force_newline_brace { alt_block_sep } else { @@ -2573,7 +2573,7 @@ fn rewrite_struct_lit<'a>( } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(context, try_opt!(v_shape.shrink_left(2))) + expr.rewrite(context, try_opt!(v_shape.offset_left(2))) .map(|s| format!("..{}", s)) } }; diff --git a/src/items.rs b/src/items.rs index aa83d9a2b0d..4e989fe64e2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -280,7 +280,7 @@ impl<'a> FmtVisitor<'a> { if force_newline_brace { newline_brace = true; } else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine && - !result.contains('\n') + !result.contains('\n') { newline_brace = false; } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 26963540fcc..4d8ab906789 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -351,7 +351,7 @@ fn complex_if_else() { { ha(); } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + - xxxxxxxxx + xxxxxxxxx { yo(); } diff --git a/tests/target/issue-1239.rs b/tests/target/issue-1239.rs index 8db0d195ae6..6b5163cf796 100644 --- a/tests/target/issue-1239.rs +++ b/tests/target/issue-1239.rs @@ -4,8 +4,8 @@ fn foo() { condition__uses_alignment_for_first_if__2 { } else if condition__no_alignment_for_later_else__0 || - condition__no_alignment_for_later_else__1 || - condition__no_alignment_for_later_else__2 + condition__no_alignment_for_later_else__1 || + condition__no_alignment_for_later_else__2 { }; } -- cgit 1.4.1-3-g733a5 From 0a2567db930478d58cd53e87623fe70a7eff27c2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:00:36 +0900 Subject: Implement RFC style for match Put the opening brace of match arm's body on the next line if the pattern has guard and consists of multi lines. --- src/expr.rs | 141 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 896ecebb68e..8aa82aa621d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1549,45 +1549,6 @@ fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { } } -fn rewrite_match_pattern( - context: &RewriteContext, - pats: &Vec>, - guard: &Option>, - shape: Shape, -) -> Option { - // Patterns - // 5 = ` => {` - let pat_shape = try_opt!(shape.sub_width(5)); - - let pat_strs = try_opt!( - pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>() - ); - - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, pat_shape.width); - let fmt = ListFormatting { - tactic: tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - shape: pat_shape, - ends_with_newline: false, - config: context.config, - }; - let pats_str = try_opt!(write_list(&items, &fmt)); - - // Guard - let guard_str = try_opt!(rewrite_guard( - context, - guard, - shape, - trimmed_last_line_width(&pats_str), - )); - - Some(format!("{}{}", pats_str, guard_str)) -} - fn rewrite_match_arms( context: &RewriteContext, arms: &[ast::Arm], @@ -1677,6 +1638,45 @@ fn rewrite_match_arm(context: &RewriteContext, arm: &ast::Arm, shape: Shape) -> rewrite_match_body(context, &arm.body, &pats_str, shape, arm.guard.is_some()) } +fn rewrite_match_pattern( + context: &RewriteContext, + pats: &Vec>, + guard: &Option>, + shape: Shape, +) -> Option { + // Patterns + // 5 = ` => {` + let pat_shape = try_opt!(shape.sub_width(5)); + + let pat_strs = try_opt!( + pats.iter() + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>() + ); + + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, pat_shape.width); + let fmt = ListFormatting { + tactic: tactic, + separator: " |", + trailing_separator: SeparatorTactic::Never, + shape: pat_shape, + ends_with_newline: false, + config: context.config, + }; + let pats_str = try_opt!(write_list(&items, &fmt)); + + // Guard + let guard_str = try_opt!(rewrite_guard( + context, + guard, + shape, + trimmed_last_line_width(&pats_str), + )); + + Some(format!("{}{}", pats_str, guard_str)) +} + fn rewrite_match_body( context: &RewriteContext, body: &ptr::P, @@ -1699,39 +1699,46 @@ fn rewrite_match_body( let comma = arm_comma(&context.config, body); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let alt_block_sep = alt_block_sep.as_str(); - let is_block = if let ast::ExprKind::Block(..) = body.node { - true + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { + (true, is_empty_block(block, context.codemap)) } else { - false + (false, false) }; let combine_orig_body = |body_str: &str| { let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, - _ if has_guard && pats_str.contains('\n') && is_block && body_str != "{}" => { - alt_block_sep - } _ => " ", }; Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) }; + let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; + let next_line_indent = if is_block { + shape.indent + } else { + shape.indent.block_indent(context.config) + }; let combine_next_line_body = |body_str: &str| { - let indent_str = shape - .indent - .block_indent(context.config) - .to_string(context.config); + if is_block { + return Some(format!( + "{} =>\n{}{}", + pats_str, + next_line_indent.to_string(context.config), + body_str + )); + } + + let indent_str = shape.indent.to_string(context.config); + let nested_indent_str = next_line_indent.to_string(context.config); let (body_prefix, body_suffix) = if context.config.wrap_match_arms() { let comma = if context.config.match_block_trailing_comma() { "," } else { "" }; - ( - "{", - format!("\n{}}}{}", shape.indent.to_string(context.config), comma), - ) + ("{", format!("\n{}}}{}", indent_str, comma)) } else { ("", String::from(",")) }; @@ -1739,8 +1746,9 @@ fn rewrite_match_body( let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => format!("{}{}\n", alt_block_sep, body_prefix), _ if body_prefix.is_empty() => "\n".to_owned(), - _ => " ".to_owned() + body_prefix + "\n", - } + &indent_str; + _ if forbid_same_line => format!("{}{}\n", alt_block_sep, body_prefix), + _ => format!(" {}\n", body_prefix), + } + &nested_indent_str; Some(format!( "{} =>{}{}{}", @@ -1753,19 +1761,20 @@ fn rewrite_match_body( // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() - let orig_arm_shape = shape + let orig_body_shape = shape .offset_left(extra_offset(&pats_str, shape) + 4) .and_then(|shape| shape.sub_width(comma.len())); - let orig_body = if let Some(arm_shape) = orig_arm_shape { + let orig_body = if let Some(body_shape) = orig_body_shape { let rewrite = nop_block_collapse( - format_expr(body, ExprType::Statement, context, arm_shape), - arm_shape.width, + format_expr(body, ExprType::Statement, context, body_shape), + body_shape.width, ); match rewrite { Some(ref body_str) - if ((!body_str.contains('\n')) && first_line_width(body_str) <= arm_shape.width) || - is_block => + if !forbid_same_line && + (is_block || + (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => { return combine_orig_body(body_str); } @@ -1774,18 +1783,20 @@ fn rewrite_match_body( } else { None }; - let orig_budget = orig_arm_shape.map_or(0, |shape| shape.width); + let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); // Try putting body on the next line and see if it looks better. - let next_line_body_shape = - Shape::indented(shape.indent.block_indent(context.config), context.config); + let next_line_body_shape = Shape::indented(next_line_indent, context.config); let next_line_body = nop_block_collapse( format_expr(body, ExprType::Statement, context, next_line_body_shape), next_line_body_shape.width, ); match (orig_body, next_line_body) { (Some(ref orig_str), Some(ref next_line_str)) - if prefer_next_line(orig_str, next_line_str) => combine_next_line_body(next_line_str), + if forbid_same_line || prefer_next_line(orig_str, next_line_str) => + { + combine_next_line_body(next_line_str) + } (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { combine_orig_body(orig_str) } -- cgit 1.4.1-3-g733a5 From b78b6e8b09179adde64780a22ce5b9d4a575967f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:01:38 +0900 Subject: Format source codes and update tests --- src/expr.rs | 3 ++- src/visitor.rs | 5 ++++- tests/target/long-match-arms-brace-newline.rs | 5 ++++- tests/target/match.rs | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8aa82aa621d..1b8cfbe8c04 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1686,7 +1686,8 @@ fn rewrite_match_body( ) -> Option { let (extend, body) = match body.node { ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => { + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { (expr.can_be_overflowed(context, 1), &**expr) } else { diff --git a/src/visitor.rs b/src/visitor.rs index 97b6ce29269..2a6a827c1a4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -563,7 +563,10 @@ impl<'a> FmtVisitor<'a> { if s.rewrite( &self.get_context(), Shape::indented(self.block_indent, self.config), - ).is_none() => true, + ).is_none() => + { + true + } None => true, _ => self.failed, }; diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index 2a956e5b4d0..da82d971593 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -7,7 +7,10 @@ fn main() { match x { aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) - if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => Ok(()), + if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => + { + Ok(()) + } _ => Err(x), } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 433eacb7ac6..29bc8516529 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -29,7 +29,10 @@ fn foo() { } Patternnnnnnnnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnnnnnnnn - if looooooooooooooooooooooooooooooooooooooooong_guard => meh, + if looooooooooooooooooooooooooooooooooooooooong_guard => + { + meh + } // Test that earlier patterns can take the guard space (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | -- cgit 1.4.1-3-g733a5 From cf8b191852ba63e0c1c645cfb1af9d832fc613ee Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:09:03 +0900 Subject: Put the brace of match on the next line if condition is multi-lined --- src/expr.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1b8cfbe8c04..14bf46e966f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1514,15 +1514,17 @@ fn rewrite_match( return None; } - // `match `cond` {` + // 6 = `match `, 2 = ` {` let cond_shape = match context.config.control_style() { Style::Legacy => try_opt!(shape.shrink_left(6).and_then(|s| s.sub_width(2))), - Style::Rfc => try_opt!(shape.offset_left(8)), + Style::Rfc => try_opt!(shape.offset_left(6).and_then(|s| s.sub_width(2))), }; let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => alt_block_sep.as_str(), + ControlBraceStyle::AlwaysNextLine => &alt_block_sep, + _ if last_line_extendable(&cond_str) => " ", + _ if cond_str.contains('\n') => &alt_block_sep, _ => " ", }; -- cgit 1.4.1-3-g733a5 From 9777c0de93d79485b93e276eb783fa2b5edd7905 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:09:43 +0900 Subject: Format source codes and update tests --- src/imports.rs | 3 ++- tests/target/match.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 1ce397f6c5a..d506fb583b4 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -501,7 +501,8 @@ fn rewrite_use_list( fn move_self_to_front(items: &mut Vec) -> bool { match items .iter() - .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) { + .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) + { Some(pos) => { items[0] = items.remove(pos); true diff --git a/tests/target/match.rs b/tests/target/match.rs index 29bc8516529..d0b7e665459 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -390,7 +390,8 @@ fn issue1395() { fn issue1456() { Ok(Recording { artists: match reader - .evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + .evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? + { Nodeset(nodeset) => { let res: Result, ReadError> = nodeset .iter() -- cgit 1.4.1-3-g733a5 From faf45b3a8028cf40d7bfeb073e3df7e2a48f8318 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:16:31 +0900 Subject: Remove old heuristics from legacy style --- src/expr.rs | 27 ++------------------------- src/visitor.rs | 14 -------------- 2 files changed, 2 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 14bf46e966f..c2205f4ea74 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -876,14 +876,7 @@ fn rewrite_block_with_visitor( } visitor.visit_block(block); - if visitor.failed && shape.indent.alignment != 0 { - block.rewrite( - context, - Shape::indented(shape.indent.block_only(), context.config), - ) - } else { - Some(format!("{}{}", prefix, visitor.buffer)) - } + Some(format!("{}{}", prefix, visitor.buffer)) } impl Rewrite for ast::Block { @@ -2075,23 +2068,7 @@ where one_line_width, args_max_width, force_trailing_comma, - ).or_else(|| if context.use_block_indent() { - rewrite_call_args( - context, - args, - args_span, - Shape::indented( - shape.block().indent.block_indent(context.config), - context.config, - ), - 0, - 0, - force_trailing_comma, - ) - } else { - None - }) - .ok_or(Ordering::Less)?; + ).ok_or(Ordering::Less)?; if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { let mut new_context = context.clone(); diff --git a/src/visitor.rs b/src/visitor.rs index 2a6a827c1a4..9ee7136bb63 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -56,7 +56,6 @@ pub struct FmtVisitor<'a> { // FIXME: use an RAII util or closure for indenting pub block_indent: Indent, pub config: &'a Config, - pub failed: bool, pub is_if_else_block: bool, } @@ -558,18 +557,6 @@ impl<'a> FmtVisitor<'a> { fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo); - self.failed = match rewrite { - Some(ref s) - if s.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ).is_none() => - { - true - } - None => true, - _ => self.failed, - }; let result = rewrite.unwrap_or_else(|| self.snippet(span)); self.buffer.push_str(&result); self.last_pos = source!(self, span).hi; @@ -583,7 +570,6 @@ impl<'a> FmtVisitor<'a> { last_pos: BytePos(0), block_indent: Indent::empty(), config: config, - failed: false, is_if_else_block: false, } } -- cgit 1.4.1-3-g733a5 From 28e32ce898f84131baa35a7db34a399727d8f15f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:30:42 +0900 Subject: Use block indent when rewriting parenthesised expressions --- src/expr.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c2205f4ea74..327737d671c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2401,8 +2401,13 @@ fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { debug!("rewrite_paren, shape: {:?}", shape); - let paren_overhead = paren_overhead(context); - let sub_shape = try_opt!(shape.sub_width(paren_overhead / 2)).visual_indent(paren_overhead / 2); + let total_paren_overhead = paren_overhead(context); + let paren_overhead = total_paren_overhead / 2; + let sub_shape = try_opt!( + shape + .offset_left(paren_overhead) + .and_then(|s| s.sub_width(paren_overhead)) + ); let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && s.len() > 0 { format!("( {} )", s) @@ -2413,16 +2418,12 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> let subexpr_str = try_opt!(subexpr.rewrite(context, sub_shape)); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - if subexpr_str.contains('\n') { + if subexpr_str.contains('\n') || + first_line_width(&subexpr_str) + total_paren_overhead <= shape.width + { Some(paren_wrapper(&subexpr_str)) } else { - if subexpr_str.len() + paren_overhead <= shape.width { - Some(paren_wrapper(&subexpr_str)) - } else { - let sub_shape = try_opt!(shape.offset_left(2)); - let subexpr_str = try_opt!(subexpr.rewrite(context, sub_shape)); - Some(paren_wrapper(&subexpr_str)) - } + None } } -- cgit 1.4.1-3-g733a5 From a8b0a6e4c5524460ff7f181ffc0ca45758a02545 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 20 Jul 2017 00:35:00 +0900 Subject: Format source codes and update tests --- src/expr.rs | 10 +++++----- src/items.rs | 11 +++++------ src/lists.rs | 2 +- src/string.rs | 2 +- src/summary.rs | 2 +- src/visitor.rs | 12 ++++++------ tests/system.rs | 8 +------- tests/target/configs-control_style-rfc.rs | 4 ++-- tests/target/expr.rs | 10 +++++----- tests/target/macros.rs | 8 ++++---- 10 files changed, 31 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 327737d671c..d99a73b87ec 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1428,7 +1428,7 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { // the expression. pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && - !block_contains_comment(block, codemap)) + !block_contains_comment(block, codemap)) } /// Checks whether a block contains at most one statement or expression, and no comments. @@ -1770,7 +1770,7 @@ fn rewrite_match_body( Some(ref body_str) if !forbid_same_line && (is_block || - (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => + (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => { return combine_orig_body(body_str); } @@ -2375,7 +2375,7 @@ pub fn wrap_args_with_parens( ) -> String { if !context.use_block_indent() || (context.inside_macro && !args_str.contains('\n') && - args_str.len() + paren_overhead(context) <= shape.width) || is_extendable + args_str.len() + paren_overhead(context) <= shape.width) || is_extendable { if context.config.spaces_within_parens() && args_str.len() > 0 { format!("( {} )", args_str) @@ -2605,8 +2605,8 @@ pub fn wrap_struct_field( ) -> String { if context.config.struct_lit_style() == IndentStyle::Block && (fields_str.contains('\n') || - context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || - fields_str.len() > one_line_width) + context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || + fields_str.len() > one_line_width) { format!( "\n{}{}\n{}", diff --git a/src/items.rs b/src/items.rs index 4e989fe64e2..1b9c4495761 100644 --- a/src/items.rs +++ b/src/items.rs @@ -942,11 +942,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); let where_density = if (context.config.where_density() == Density::Compressed && - (!result.contains('\n') || - context.config.fn_args_layout() == IndentStyle::Block)) || + (!result.contains('\n') || context.config.fn_args_layout() == IndentStyle::Block)) || (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) || (context.config.where_density() == Density::CompressedIfEmpty && !has_body && - !result.contains('\n')) + !result.contains('\n')) { Density::Compressed } else { @@ -1079,7 +1078,7 @@ pub fn format_struct_struct( // 3 = ` {}`, 2 = ` {`. let overhead = if fields.is_empty() { 3 } else { 2 }; if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine && - !fields.is_empty()) || + !fields.is_empty()) || context .config .max_width() @@ -1247,8 +1246,8 @@ fn format_tuple_struct( if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && (result.contains('\n') || - offset.block_indent + result.len() + where_clause_str.len() + 1 > - context.config.max_width()) + offset.block_indent + result.len() + where_clause_str.len() + 1 > + context.config.max_width()) { // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. diff --git a/src/lists.rs b/src/lists.rs index 55db7cd9c00..6dfab314d97 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -368,7 +368,7 @@ where let inner_item_width = item.inner_as_ref().len(); if !first && (item.is_multiline() || !item.post_comment.is_some() || - inner_item_width + overhead > max_budget) + inner_item_width + overhead > max_budget) { return max_width; } diff --git a/src/string.rs b/src/string.rs index 00d8c0875e5..6cb2fcddaef 100644 --- a/src/string.rs +++ b/src/string.rs @@ -83,7 +83,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option if cur_end < cur_start + MIN_STRING { cur_end = cur_start + max_chars; while !(punctuation.contains(graphemes[cur_end - 1]) || - graphemes[cur_end - 1].trim().is_empty()) + graphemes[cur_end - 1].trim().is_empty()) { if cur_end >= graphemes.len() { let line = &graphemes[cur_start..].join(""); diff --git a/src/summary.rs b/src/summary.rs index 5a169f8b80c..065e357ea95 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -54,7 +54,7 @@ impl Summary { pub fn has_no_errors(&self) -> bool { !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors || - self.has_diff) + self.has_diff) } pub fn add(&mut self, other: Summary) { diff --git a/src/visitor.rs b/src/visitor.rs index 9ee7136bb63..6461fa89d6c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -632,12 +632,12 @@ impl<'a> FmtVisitor<'a> { .take_while(|ppi| { is_use_item(&***ppi) && (!reorder_imports_in_group || - { - let current = self.codemap.lookup_line_range(item_bound(&ppi)); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) + { + let current = self.codemap.lookup_line_range(item_bound(&ppi)); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) }) .count(); let (use_items, rest) = items_left.split_at(use_item_length); diff --git a/tests/system.rs b/tests/system.rs index 18e389b0ba7..d915e11d534 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -240,15 +240,9 @@ fn read_config(filename: &str) -> Config { fn format_file>(filepath: P, config: &Config) -> (FileMap, FormatReport) { let filepath = filepath.into(); - let display_path = filepath.display().to_string(); let input = Input::File(filepath); - let (error_summary, file_map, report) = + let (_error_summary, file_map, report) = format_input::(input, &config, None).unwrap(); - assert!( - error_summary.has_no_errors(), - "Encountered errors formatting {}", - display_path - ); return (file_map, report); } diff --git a/tests/target/configs-control_style-rfc.rs b/tests/target/configs-control_style-rfc.rs index 417c33c59f8..8033aff208f 100644 --- a/tests/target/configs-control_style-rfc.rs +++ b/tests/target/configs-control_style-rfc.rs @@ -5,9 +5,9 @@ fn main() { loop { if foo { if ((right_paddle_speed < 0.) && - (right_paddle.position().y - paddle_size.y / 2. > 5.)) || + (right_paddle.position().y - paddle_size.y / 2. > 5.)) || ((right_paddle_speed > 0.) && - (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) + (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) { foo } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 4d8ab906789..dde596394a8 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -21,9 +21,9 @@ fn foo() -> bool { trivial_value, ); (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaa))))))))); + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaa))))))))); { for _ in 0..10 {} @@ -263,9 +263,9 @@ fn returns() { fn addrof() { &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); } fn casts() { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index d784c26ce1c..392a190ff0c 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -72,10 +72,10 @@ fn main() { vec![ a; (|x| { - let y = x + 1; - let z = y + 1; - z - })(2) + let y = x + 1; + let z = y + 1; + z + })(2) ]; vec![ a; -- cgit 1.4.1-3-g733a5 From b233653a222946e73b5c56a76e35d4c96e151aa1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 20 Jul 2017 23:58:00 +0900 Subject: Cover missing comments between attributes and expressions --- src/expr.rs | 80 +++++++++++++++++++++++++++++++++----------------- src/lib.rs | 18 +++++++++++- tests/source/attrib.rs | 10 +++++++ tests/target/attrib.rs | 10 +++++++ 4 files changed, 90 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d99a73b87ec..8225f0165dd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -51,21 +51,58 @@ pub enum ExprType { fn combine_attr_and_expr( context: &RewriteContext, shape: Shape, - attr_str: &str, + expr: &ast::Expr, expr_str: &str, -) -> String { +) -> Option { + let attr_str = try_opt!((&*expr.attrs).rewrite(context, shape)); let separator = if attr_str.is_empty() { String::new() } else { - if expr_str.contains('\n') || attr_str.contains('\n') || - attr_str.len() + expr_str.len() > shape.width + // Try to recover comments between the attributes and the expression if available. + let missing_snippet = context.snippet(mk_sp( + expr.attrs[expr.attrs.len() - 1].span.hi, + expr.span.lo, + )); + let comment_opening_pos = missing_snippet.chars().position(|c| c == '/'); + let prefer_same_line = if let Some(pos) = comment_opening_pos { + !missing_snippet[..pos].contains('\n') + } else { + !missing_snippet.contains('\n') + }; + + let trimmed = missing_snippet.trim(); + let missing_comment = if trimmed.is_empty() { + String::new() + } else { + try_opt!(rewrite_comment(&trimmed, false, shape, context.config)) + }; + + // 2 = ` ` + ` ` + let one_line_width = + attr_str.len() + missing_comment.len() + 2 + first_line_width(expr_str); + let attr_expr_separator = if prefer_same_line && !missing_comment.starts_with("//") && + one_line_width <= shape.width { + String::from(" ") + } else { format!("\n{}", shape.indent.to_string(context.config)) + }; + + if missing_comment.is_empty() { + attr_expr_separator } else { - String::from(" ") + // 1 = ` ` + let one_line_width = + last_line_width(&attr_str) + 1 + first_line_width(&missing_comment); + let attr_comment_separator = if prefer_same_line && one_line_width <= shape.width { + String::from(" ") + } else { + format!("\n{}", shape.indent.to_string(context.config)) + }; + attr_comment_separator + &missing_comment + &attr_expr_separator } }; - format!("{}{}{}", attr_str, separator, expr_str) + Some(format!("{}{}{}", attr_str, separator, expr_str)) } pub fn format_expr( @@ -74,18 +111,8 @@ pub fn format_expr( context: &RewriteContext, shape: Shape, ) -> Option { - let attr_rw = (&*expr.attrs).rewrite(context, shape); if contains_skip(&*expr.attrs) { - if let Some(attr_str) = attr_rw { - return Some(combine_attr_and_expr( - context, - shape, - &attr_str, - &context.snippet(expr.span), - )); - } else { - return Some(context.snippet(expr.span)); - } + return Some(context.snippet(expr.span())); } let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( @@ -321,15 +348,14 @@ pub fn format_expr( )) } }; - match (attr_rw, expr_rw) { - (Some(attr_str), Some(expr_str)) => recover_comment_removed( - combine_attr_and_expr(context, shape, &attr_str, &expr_str), - expr.span, - context, - shape, - ), - _ => None, - } + + expr_rw + .and_then(|expr_str| { + recover_comment_removed(expr_str, expr.span, context, shape) + }) + .and_then(|expr_str| { + combine_attr_and_expr(context, shape, expr, &expr_str) + }) } pub fn rewrite_pair( @@ -921,7 +947,7 @@ impl Rewrite for ast::Stmt { ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; result.and_then(|res| { - recover_comment_removed(res, self.span, context, shape) + recover_comment_removed(res, self.span(), context, shape) }) } } diff --git a/src/lib.rs b/src/lib.rs index 088f0950f10..bd611202fb7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,7 +83,23 @@ pub trait Spanned { impl Spanned for ast::Expr { fn span(&self) -> Span { - self.span + if self.attrs.is_empty() { + self.span + } else { + mk_sp(self.attrs[0].span.lo, self.span.hi) + } + } +} + +impl Spanned for ast::Stmt { + fn span(&self) -> Span { + match self.node { + // Cover attributes + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { + mk_sp(expr.span().lo, self.span.hi) + } + _ => self.span, + } } } diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 324f0c69fc4..361d9fb784c 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -81,3 +81,13 @@ fn foo() { // (((((((( )] fn foo() {} + +// #1799 +fn issue_1799() { + #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 + Some( Err(error) ) ; + + #[allow(unreachable_code)] + // https://github.com/rust-lang/rust/issues/43336 + Some( Err(error) ) ; +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 2e08ec5cc34..7ff79b16411 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -81,3 +81,13 @@ fn foo() { // (((((((( )] fn foo() {} + +// #1799 +fn issue_1799() { + #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 + Some(Err(error)); + + #[allow(unreachable_code)] + // https://github.com/rust-lang/rust/issues/43336 + Some(Err(error)); +} -- cgit 1.4.1-3-g733a5 From db5f77b7d0c8065e46c433d71a95c3e24ac53a5b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 21 Jul 2017 07:17:49 +0900 Subject: Consider max_width when rewriting struct in single-line --- src/items.rs | 13 +++++++++++-- tests/target/issue-1802.rs | 11 +++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-1802.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1b9c4495761..22ac1354e34 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,6 +10,8 @@ // Formatting top-level items - functions, structs, enums, traits, impls. +use std::cmp::min; + use syntax::{abi, ast, ptr, symbol}; use syntax::ast::ImplItem; use syntax::codemap::{BytePos, Span}; @@ -1120,15 +1122,22 @@ pub fn format_struct_struct( return Some(result); } + // 3 = ` ` and ` }` + let one_line_budget = context + .config + .max_width() + .checked_sub(result.len() + 3 + offset.width()) + .unwrap_or(0); + let items_str = try_opt!(rewrite_with_alignment( fields, context, Shape::indented(offset, context.config), mk_sp(body_lo, span.hi), - one_line_width.unwrap_or(0), + one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)), )); - if one_line_width.is_some() && !items_str.contains('\n') { + if one_line_width.is_some() && !items_str.contains('\n') && !result.contains('\n') { Some(format!("{} {} }}", result, items_str)) } else { Some(format!( diff --git a/tests/target/issue-1802.rs b/tests/target/issue-1802.rs new file mode 100644 index 00000000000..236a49f2ff3 --- /dev/null +++ b/tests/target/issue-1802.rs @@ -0,0 +1,11 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 10 +// rustfmt-struct_variant_width: 10 +// rustfmt-error_on_line_overflow: false + +enum F { + X { + a: d, + b: e, + }, +} -- cgit 1.4.1-3-g733a5 From 6984c05e6945e73a75b43c3e797462af1c06271f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 21 Jul 2017 09:10:27 +1200 Subject: Change the writemode to overwrite --- Cargo.lock | 2 +- Cargo.toml | 2 +- Configurations.md | 2 +- README.md | 9 +++++---- src/bin/rustfmt.rs | 15 ++------------- src/config.rs | 5 +++-- 6 files changed, 13 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 8dff7cbcff5..efad18d5abc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "rustfmt-nightly" -version = "0.1.9" +version = "0.2.0" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a82883b2d8b..5ac6bf54144 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.1.9" +version = "0.2.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/Configurations.md b/Configurations.md index f97214c1358..5c75030d480 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2120,5 +2120,5 @@ See also: [`indent_match_arms`](#indent_match_arms), [`match_block_trailing_comm What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage -- **Default value**: `"Replace"` +- **Default value**: `"Overwrite"` - **Possible values**: `"Checkstyle"`, `"Coverage"`, `"Diff"`, `"Display"`, `"Overwrite"`, `"Plain"`, `"Replace"` diff --git a/README.md b/README.md index 4b7210dd06e..f7efdfeb266 100644 --- a/README.md +++ b/README.md @@ -90,11 +90,12 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all binary and library targets of your crate. You'll probably want to specify the write mode. Currently, there are modes for -diff, replace, overwrite, display, coverage, and checkstyle. +`diff`, `replace`, `overwrite`, `display`, `coverage`, `checkstyle`, and `plain`. -* `replace` Is the default and overwrites the original files after creating backups of the files. -* `overwrite` Overwrites the original files _without_ creating backups. +* `overwrite` Is the default and overwrites the original files _without_ creating backups. +* `replace` Overwrites the original files after creating backups of the files. * `display` Will print the formatted files to stdout. +* `plain` Also writes to stdout, but with no metadata. * `diff` Will print a diff between the original files and formatted files to stdout. Will also exit with an error code if there are any differences. * `checkstyle` Will output the lines that need to be corrected as a checkstyle XML file, @@ -103,7 +104,7 @@ diff, replace, overwrite, display, coverage, and checkstyle. The write mode can be set by passing the `--write-mode` flag on the command line. For example `rustfmt --write-mode=display src/filename.rs` -`cargo fmt` uses `--write-mode=replace` by default. +`cargo fmt` uses `--write-mode=overwrite` by default. If you want to restrict reformatting to specific sets of lines, you can use the `--file-lines` option. Its argument is a JSON array of objects diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index f0846b43ea8..2de572f616e 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -78,11 +78,6 @@ impl CliOptions { format!("Invalid write-mode: {}", write_mode), )); } - } else if !matches.opt_present("no-warn-write-mode") { - println!( - "Warning: the default write-mode for Rustfmt will soon change to overwrite \ - - this will not leave backups of changed files." - ); } if let Some(ref file_lines) = matches.opt_str("file-lines") { @@ -120,17 +115,11 @@ fn make_opts() -> Options { opts.optflag("h", "help", "show this message"); opts.optflag("V", "version", "show version information"); opts.optflag("v", "verbose", "print verbose output"); - // Suppress warning. Remove this option after the default write mode changed to overwrite. - opts.optflag( - "w", - "no-warn-write-mode", - "inhibit warning about write-mode change", - ); opts.optopt( "", "write-mode", - "mode to write in (not usable when piping from stdin)", - "[replace|overwrite|display|diff|coverage|checkstyle]", + "how to write output (not usable when piping from stdin)", + "[replace|overwrite|display|plain|diff|coverage|checkstyle]", ); opts.optflag("", "skip-children", "don't reformat child modules"); diff --git a/src/config.rs b/src/config.rs index 173f076bebb..7ffe141e6c1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -596,8 +596,9 @@ create_config! { spaces_within_square_brackets: bool, false, "Put spaces within non-empty square brackets"; spaces_within_parens: bool, false, "Put spaces within non-empty parentheses"; use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; - write_mode: WriteMode, WriteMode::Replace, - "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage"; + write_mode: WriteMode, WriteMode::Overwrite, + "What Write Mode to use when none is supplied: \ + Replace, Overwrite, Display, Plain, Diff, Coverage"; condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns"; combine_control_expr: bool, true, "Combine control expressions with funciton calls."; -- cgit 1.4.1-3-g733a5 From 1e00a2833263104fb8e996135e0c49412e0e54ad Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 21 Jul 2017 13:55:15 +0900 Subject: Apply item_brace_style to mod --- src/visitor.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 6461fa89d6c..e6e7f038ce7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -19,7 +19,7 @@ use {Indent, Shape}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, FindUncommented}; use comment::rewrite_comment; -use config::Config; +use config::{BraceStyle, Config}; use expr::{format_expr, ExprType}; use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, rewrite_type_alias}; @@ -665,7 +665,11 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&ident.to_string()); if is_internal { - self.buffer.push_str(" {"); + match self.config.item_brace_style() { + BraceStyle::AlwaysNextLine => self.buffer + .push_str(&format!("\n{}{{", self.block_indent.to_string(self.config))), + _ => self.buffer.push_str(" {"), + } // Hackery to account for the closing }. let mod_lo = self.codemap.span_after(source!(self, s), "{"); let body_snippet = self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi - BytePos(1))); -- cgit 1.4.1-3-g733a5 From a16307a70f250708d31582b06584e084d5cd82cf Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 21 Jul 2017 17:53:03 +0900 Subject: Allow block-like rhs expression to stay on the same line as lhs --- src/expr.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8225f0165dd..2ba08cd3390 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -377,9 +377,9 @@ where // Note that this is non-conservative, but its just to see if it's even // worth trying to put everything on one line. let rhs_shape = try_opt!(shape.sub_width(suffix.len())); - let rhs_result = rhs.rewrite(context, rhs_shape); + let rhs_orig_result = rhs.rewrite(context, rhs_shape); - if let Some(rhs_result) = rhs_result { + if let Some(ref rhs_result) = rhs_orig_result { // This is needed in case of line break not caused by a // shortage of space, but by end-of-line comments, for example. if !rhs_result.contains('\n') { @@ -419,6 +419,7 @@ where // We have to use multiple lines. // Re-evaluate the rhs because we have more space now: + let sep = if infix.ends_with(' ') { " " } else { "" }; let infix = infix.trim_right(); let rhs_shape = match context.config.control_style() { Style::Legacy => { @@ -439,12 +440,24 @@ where width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), ..shape }; - let lhs_result = try_opt!(lhs.rewrite(context, lhs_shape)); + let lhs_result = try_opt!( + lhs.rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}{}", prefix, lhs_str, infix)) + ); + if let Some(ref rhs_str) = rhs_orig_result { + if rhs_str.lines().count() <= rhs_result.lines().count() && + rhs_str + .lines() + .next() + .map_or(false, |first_line| first_line.ends_with('{')) && + last_line_width(&lhs_result) + sep.len() + first_line_width(rhs_str) <= shape.width + { + return Some(format!("{}{}{}{}", lhs_result, sep, rhs_str, suffix)); + } + } Some(format!( - "{}{}{}\n{}{}{}", - prefix, + "{}\n{}{}{}", lhs_result, - infix, rhs_shape.indent.to_string(context.config), rhs_result, suffix -- cgit 1.4.1-3-g733a5 From 68c6fe70fdf441b46d5b88bc344e6d68f8f0068d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 21 Jul 2017 17:55:52 +0900 Subject: Format source codes and update tests --- src/expr.rs | 11 +++++------ src/items.rs | 11 +++++------ src/visitor.rs | 14 ++++++-------- tests/target/chains-visual.rs | 11 +++++------ tests/target/chains.rs | 9 ++++----- tests/target/issue-831.rs | 9 +++++++++ 6 files changed, 34 insertions(+), 31 deletions(-) create mode 100644 tests/target/issue-831.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2ba08cd3390..c1d5e8ccc39 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2899,12 +2899,11 @@ pub fn rewrite_assign_rhs>( shape: Shape, ) -> Option { let lhs = lhs.into(); - let last_line_width = last_line_width(&lhs) - - if lhs.contains('\n') { - shape.indent.width() - } else { - 0 - }; + let last_line_width = last_line_width(&lhs) - if lhs.contains('\n') { + shape.indent.width() + } else { + 0 + }; // 1 = space between operator and rhs. let orig_shape = try_opt!(shape.offset_left(last_line_width + 1)); let rhs = try_opt!(choose_rhs( diff --git a/src/items.rs b/src/items.rs index 22ac1354e34..087b5615f02 100644 --- a/src/items.rs +++ b/src/items.rs @@ -829,12 +829,11 @@ fn rewrite_trait_ref( result_len: usize, ) -> Option { // 1 = space between generics and trait_ref - let used_space = 1 + polarity_str.len() + - if generics_str.contains('\n') { - last_line_width(&generics_str) - } else { - result_len + generics_str.len() - }; + let used_space = 1 + polarity_str.len() + if generics_str.contains('\n') { + last_line_width(&generics_str) + } else { + result_len + generics_str.len() + }; let shape = Shape::indented(offset + used_space, context.config); if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { if !(retry && trait_ref_str.contains('\n')) { diff --git a/src/visitor.rs b/src/visitor.rs index e6e7f038ce7..e3233e1dba3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -630,14 +630,12 @@ impl<'a> FmtVisitor<'a> { let use_item_length = items_left .iter() .take_while(|ppi| { - is_use_item(&***ppi) && - (!reorder_imports_in_group || - { - let current = self.codemap.lookup_line_range(item_bound(&ppi)); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) + is_use_item(&***ppi) && (!reorder_imports_in_group || { + let current = self.codemap.lookup_line_range(item_bound(&ppi)); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) }) .count(); let (use_items, rest) = items_left.split_at(use_item_length); diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 3962bdcbbcd..c2aecd26105 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -118,12 +118,11 @@ fn floaters() { }) .quux(); - a + - match x { - true => "yay!", - false => "boo!", - } - .bar() + a + match x { + true => "yay!", + false => "boo!", + } + .bar() } fn is_replaced_content() -> bool { diff --git a/tests/target/chains.rs b/tests/target/chains.rs index d930f0a49ba..4955817da5c 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -114,11 +114,10 @@ fn floaters() { }) .quux(); - a + - match x { - true => "yay!", - false => "boo!", - }.bar() + a + match x { + true => "yay!", + false => "boo!", + }.bar() } fn is_replaced_content() -> bool { diff --git a/tests/target/issue-831.rs b/tests/target/issue-831.rs new file mode 100644 index 00000000000..1d6327c2158 --- /dev/null +++ b/tests/target/issue-831.rs @@ -0,0 +1,9 @@ +fn main() { + let y = a.iter().any(|x| { + println!("a"); + }) || b.iter().any(|x| { + println!("b"); + }) || c.iter().any(|x| { + println!("c"); + }); +} -- cgit 1.4.1-3-g733a5 From 0b38ac40d78dc40cd5bbebddb9be2b5b598d7a76 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 22 Jul 2017 11:18:47 +0900 Subject: Support rustfmt_skip on statements --- src/visitor.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index e6e7f038ce7..813f5422f2c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -26,7 +26,7 @@ use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_ass use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; -use utils::{self, mk_sp}; +use utils::{self, contains_skip, mk_sp}; fn is_use_item(item: &ast::Item) -> bool { match item.node { @@ -79,11 +79,15 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Item(ref item) => { self.visit_item(item); } - ast::StmtKind::Local(..) => { - let rewrite = stmt.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ); + ast::StmtKind::Local(ref local) => { + let rewrite = if contains_skip(&local.attrs) { + None + } else { + stmt.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ) + }; self.push_rewrite(stmt.span, rewrite); } ast::StmtKind::Expr(ref expr) => { @@ -113,8 +117,12 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(span, rewrite) } ast::StmtKind::Mac(ref mac) => { - let (ref mac, _macro_style, _) = **mac; - self.visit_mac(mac, None, MacroPosition::Statement); + let (ref mac, _macro_style, ref attrs) = **mac; + if contains_skip(attrs) { + self.push_rewrite(mac.span, None); + } else { + self.visit_mac(mac, None, MacroPosition::Statement); + } self.format_missing(stmt.span.hi); } } -- cgit 1.4.1-3-g733a5 From adce9545600d0e52e1cd09bb5632e5de697e8712 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 25 Jul 2017 00:55:29 +0900 Subject: Support inner attributes --- src/visitor.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 24802133593..77a39f9efc3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -597,31 +597,27 @@ impl<'a> FmtVisitor<'a> { } // Returns true if we should skip the following item. - pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { + pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { if utils::contains_skip(attrs) { return true; } - let outers: Vec<_> = attrs - .iter() - .filter(|a| a.style == ast::AttrStyle::Outer) - .cloned() - .collect(); - if outers.is_empty() { + let attrs: Vec<_> = attrs.iter().filter(|a| a.style == style).cloned().collect(); + if attrs.is_empty() { return false; } - let first = &outers[0]; + let first = &attrs[0]; self.format_missing_with_indent(source!(self, first.span).lo); - let rewrite = outers + let rewrite = attrs .rewrite( &self.get_context(), Shape::indented(self.block_indent, self.config), ) .unwrap(); self.buffer.push_str(&rewrite); - let last = outers.last().unwrap(); + let last = attrs.last().unwrap(); self.last_pos = source!(self, last.span).hi; false } @@ -836,14 +832,18 @@ impl Rewrite for ast::MetaItem { impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { try_opt!(self.meta()).rewrite(context, shape).map( - |rw| if rw.starts_with("///") { + |rw| if self.is_sugared_doc { rw } else { let original = context.snippet(self.span); + let prefix = match self.style { + ast::AttrStyle::Inner => "#!", + ast::AttrStyle::Outer => "#", + }; if contains_comment(&original) { original } else { - format!("#[{}]", rw) + format!("{}[{}]", prefix, rw) } }, ) -- cgit 1.4.1-3-g733a5 From 8b970fcc9f542d67cfee4a8815f3aa709c7f58f7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 25 Jul 2017 00:55:55 +0900 Subject: Format inner attributes wherever possible --- src/expr.rs | 2 +- src/items.rs | 1 + src/lib.rs | 17 ++++++++++++----- src/visitor.rs | 45 +++++++++++++++++++++++++++++++-------------- 4 files changed, 45 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c1d5e8ccc39..35e1e432733 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -914,7 +914,7 @@ fn rewrite_block_with_visitor( ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo, } - visitor.visit_block(block); + visitor.visit_block(block, None); Some(format!("{}{}", prefix, visitor.buffer)) } diff --git a/src/items.rs b/src/items.rs index 087b5615f02..9c3fb86f73e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -640,6 +640,7 @@ pub fn format_impl( visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); for item in items { visitor.visit_impl_item(item); } diff --git a/src/lib.rs b/src/lib.rs index bd611202fb7..5647e6df5e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -554,17 +554,24 @@ where if skip_children && path.as_path() != main_file { continue; } - let path = path.to_str().unwrap(); + let path_str = path.to_str().unwrap(); if config.verbose() { - println!("Formatting {}", path); + println!("Formatting {}", path_str); } { let mut visitor = FmtVisitor::from_codemap(parse_session, config); - visitor.format_separate_mod(module); + let filemap = visitor.codemap.lookup_char_pos(module.inner.lo).file; + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == main_file { + visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); + } else { + visitor.last_pos = filemap.start_pos; + } + visitor.format_separate_mod(module, &*filemap); - has_diff |= after_file(path, &mut visitor.buffer)?; + has_diff |= after_file(path_str, &mut visitor.buffer)?; - result.push((path.to_owned(), visitor.buffer)); + result.push((path_str.to_owned(), visitor.buffer)); } // Reset the error count. if parse_session.span_diagnostic.has_errors() { diff --git a/src/visitor.rs b/src/visitor.rs index 77a39f9efc3..0f7005e2856 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -12,7 +12,7 @@ use std::cmp; use strings::string_buffer::StringBuffer; use syntax::{ast, ptr, visit}; -use syntax::codemap::{BytePos, CodeMap, Span}; +use syntax::codemap::{self, BytePos, CodeMap, Span}; use syntax::parse::ParseSess; use {Indent, Shape}; @@ -128,7 +128,7 @@ impl<'a> FmtVisitor<'a> { } } - pub fn visit_block(&mut self, b: &ast::Block) { + pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>) { debug!( "visit_block: {:?} {:?}", self.codemap.lookup_char_pos(b.span.lo), @@ -144,6 +144,11 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.buffer.push_str("{"); + // Format inner attributes if available. + if let Some(attrs) = inner_attrs { + self.visit_attrs(attrs, ast::AttrStyle::Inner); + } + for stmt in &b.stmts { self.visit_stmt(stmt) } @@ -201,6 +206,7 @@ impl<'a> FmtVisitor<'a> { s: Span, _: ast::NodeId, defaultness: ast::Defaultness, + inner_attrs: Option<&[ast::Attribute]>, ) { let indent = self.block_indent; let block; @@ -254,7 +260,7 @@ impl<'a> FmtVisitor<'a> { } self.last_pos = source!(self, block.span).lo; - self.visit_block(block) + self.visit_block(block, inner_attrs) } pub fn visit_item(&mut self, item: &ast::Item) { @@ -262,6 +268,7 @@ impl<'a> FmtVisitor<'a> { // complex in the module case. It is complex because the module could be // in a separate file and there might be attributes in both files, but // the AST lumps them all together. + let mut attrs = item.attrs.clone(); match item.node { ast::ItemKind::Mod(ref m) => { let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; @@ -269,7 +276,7 @@ impl<'a> FmtVisitor<'a> { if outer_file.name == inner_file.name { // Module is inline, in this case we treat modules like any // other item. - if self.visit_attrs(&item.attrs) { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_rewrite(item.span, None); return; } @@ -279,7 +286,7 @@ impl<'a> FmtVisitor<'a> { } else { // Module is not inline and should not be skipped. We want // to process only the attributes in the current file. - let attrs = item.attrs + let filterd_attrs = item.attrs .iter() .filter_map(|a| { let attr_file = self.codemap.lookup_char_pos(a.span.lo).file; @@ -292,10 +299,11 @@ impl<'a> FmtVisitor<'a> { .collect::>(); // Assert because if we should skip it should be caught by // the above case. - assert!(!self.visit_attrs(&attrs)); + assert!(!self.visit_attrs(&filterd_attrs, ast::AttrStyle::Outer)); + attrs = filterd_attrs; } } - _ => if self.visit_attrs(&item.attrs) { + _ => if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_rewrite(item.span, None); return; }, @@ -361,7 +369,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Mod(ref module) => { self.format_missing_with_indent(source!(self, item.span).lo); - self.format_mod(module, &item.vis, item.span, item.ident); + self.format_mod(module, &item.vis, item.span, item.ident, &attrs); } ast::ItemKind::Mac(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -416,6 +424,7 @@ impl<'a> FmtVisitor<'a> { item.span, item.id, ast::Defaultness::Final, + Some(&item.attrs), ) } ast::ItemKind::Ty(ref ty, ref generics) => { @@ -457,7 +466,7 @@ impl<'a> FmtVisitor<'a> { } pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { - if self.visit_attrs(&ti.attrs) { + if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { self.push_rewrite(ti.span, None); return; } @@ -489,6 +498,7 @@ impl<'a> FmtVisitor<'a> { ti.span, ti.id, ast::Defaultness::Final, + Some(&ti.attrs), ); } ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { @@ -508,7 +518,7 @@ impl<'a> FmtVisitor<'a> { } pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { - if self.visit_attrs(&ii.attrs) { + if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { self.push_rewrite(ii.span, None); return; } @@ -521,6 +531,7 @@ impl<'a> FmtVisitor<'a> { ii.span, ii.id, ii.defaultness, + Some(&ii.attrs), ); } ast::ImplItemKind::Const(ref ty, ref expr) => { @@ -655,7 +666,14 @@ impl<'a> FmtVisitor<'a> { } } - fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: ast::Ident) { + fn format_mod( + &mut self, + m: &ast::Mod, + vis: &ast::Visibility, + s: Span, + ident: ast::Ident, + attrs: &[ast::Attribute], + ) { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); let inner_span = source!(self, m.inner); @@ -681,6 +699,7 @@ impl<'a> FmtVisitor<'a> { } else { self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); + self.visit_attrs(attrs, ast::AttrStyle::Inner); self.walk_mod_items(m); self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1)); self.close_block(false); @@ -692,9 +711,7 @@ impl<'a> FmtVisitor<'a> { } } - pub fn format_separate_mod(&mut self, m: &ast::Mod) { - let filemap = self.codemap.lookup_char_pos(m.inner.lo).file; - self.last_pos = filemap.start_pos; + pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { self.block_indent = Indent::empty(); self.walk_mod_items(m); self.format_missing_with_indent(filemap.end_pos); -- cgit 1.4.1-3-g733a5 From a17993c14ae2b9b001339af34c062edf498f6c40 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 25 Jul 2017 15:19:09 +0900 Subject: Force vertical layout when struct_variant_width is 0 --- src/items.rs | 6 ++++-- tests/target/configs-struct_variant_width-0.rs | 29 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/target/configs-struct_variant_width-0.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9c3fb86f73e..c92625511a7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1128,16 +1128,18 @@ pub fn format_struct_struct( .max_width() .checked_sub(result.len() + 3 + offset.width()) .unwrap_or(0); + let one_line_budget = + one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); let items_str = try_opt!(rewrite_with_alignment( fields, context, Shape::indented(offset, context.config), mk_sp(body_lo, span.hi), - one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)), + one_line_budget, )); - if one_line_width.is_some() && !items_str.contains('\n') && !result.contains('\n') { + if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget { Some(format!("{} {} }}", result, items_str)) } else { Some(format!( diff --git a/tests/target/configs-struct_variant_width-0.rs b/tests/target/configs-struct_variant_width-0.rs new file mode 100644 index 00000000000..54c93d48031 --- /dev/null +++ b/tests/target/configs-struct_variant_width-0.rs @@ -0,0 +1,29 @@ +// rustfmt-struct_variant_width: 0 + +// Force vertical layout when struct_variant_width is set to 0. + +enum State { + TryRecv { + pos: usize, + lap: u8, + closed_count: usize, + }, + Subscribe { + pos: usize, + }, + IsReady { + pos: usize, + ready: bool, + }, + Unsubscribe { + pos: usize, + lap: u8, + id_woken: usize, + }, + FinalTryRecv { + pos: usize, + id_woken: usize, + }, + TimedOut, + Disconnected, +} -- cgit 1.4.1-3-g733a5 From 65ad7d3bb0b9895cdd703c4b7d7e49ad4f7af6f5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 25 Jul 2017 18:51:14 +0900 Subject: Put braces on the next line if it exceeds max width --- src/items.rs | 74 +++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9c3fb86f73e..f5bf7cbb824 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1095,12 +1095,14 @@ pub fn format_struct_struct( }; // 1 = `}` let overhead = if fields.is_empty() { 1 } else { 0 }; - let max_len = context.config.max_width() - offset.width(); + let max_len = context + .config + .max_width() + .checked_sub(offset.width()) + .unwrap_or(0); if !generics_str.contains('\n') && result.len() + generics_str.len() + overhead > max_len { result.push('\n'); - result.push_str(&offset - .block_indent(context.config) - .to_string(context.config)); + result.push_str(&offset.to_string(context.config)); result.push_str(&generics_str.trim_left()); } else { result.push_str(&generics_str); @@ -2730,13 +2732,14 @@ fn format_generics( let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); - if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = try_opt!( - context - .config - .max_width() - .checked_sub(last_line_width(&result)) - ); + let same_line_brace = if !generics.where_clause.predicates.is_empty() || + result.contains('\n') + { + let budget = context + .config + .max_width() + .checked_sub(last_line_width(&result)) + .unwrap_or(0); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -2751,29 +2754,38 @@ fn format_generics( generics.span.hi, )); result.push_str(&where_clause_str); - let same_line_brace = force_same_line_brace || - (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1); - if !same_line_brace && - (brace_style == BraceStyle::SameLineWhere || - brace_style == BraceStyle::AlwaysNextLine) - { - result.push('\n'); - result.push_str(&offset.block_only().to_string(context.config)); - } else { - result.push(' '); - } - result.push_str(opener); + force_same_line_brace || brace_style == BraceStyle::PreferSameLine || + (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1) } else { - if force_same_line_brace || trimmed_last_line_width(&result) == 1 || + force_same_line_brace || trimmed_last_line_width(&result) == 1 || brace_style != BraceStyle::AlwaysNextLine - { - result.push(' '); - } else { - result.push('\n'); - result.push_str(&offset.block_only().to_string(context.config)); - } - result.push_str(opener); + }; + let total_used_width = if result.contains('\n') { + last_line_width(&result) + } else { + used_width + result.len() + }; + let remaining_budget = context + .config + .max_width() + .checked_sub(total_used_width) + .unwrap_or(0); + // If the same line brace if forced, it indicates that we are rewriting an item with empty body, + // and hence we take the closer into account as well for one line budget. + // We assume that the closer has the same length as the opener. + let overhead = if force_same_line_brace { + 1 + opener.len() + opener.len() + } else { + 1 + opener.len() + }; + let forbid_same_line_brace = overhead > remaining_budget; + if !forbid_same_line_brace && same_line_brace { + result.push(' '); + } else { + result.push('\n'); + result.push_str(&offset.block_only().to_string(context.config)); } + result.push_str(opener); Some(result) } -- cgit 1.4.1-3-g733a5 From 3884b532b9c6e8fb2a117a825cbb138eb241b802 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 26 Jul 2017 16:28:55 +0900 Subject: Avoid unnecessary line breaks in condition expression --- src/expr.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 35e1e432733..67214a96c60 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1211,15 +1211,10 @@ impl<'a> ControlFlow<'a> { let pat_expr_string = match self.cond { Some(cond) => { - let mut cond_shape = match context.config.control_style() { + let cond_shape = match context.config.control_style() { Style::Legacy => try_opt!(constr_shape.shrink_left(offset)), Style::Rfc => try_opt!(constr_shape.offset_left(offset)), }; - if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { - // 2 = " {".len() - cond_shape = try_opt!(cond_shape.sub_width(2)); - } - try_opt!(rewrite_pat_expr( context, self.pat, @@ -1233,8 +1228,20 @@ impl<'a> ControlFlow<'a> { None => String::new(), }; + let brace_overhead = + if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { + // 2 = ` {` + 2 + } else { + 0 + }; + let one_line_budget = context + .config + .max_width() + .checked_sub(constr_shape.used_width() + offset + brace_overhead) + .unwrap_or(0); let force_newline_brace = context.config.control_style() == Style::Rfc && - pat_expr_string.contains('\n') && + (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) && !last_line_extendable(&pat_expr_string); // Try to format if-else on single line. -- cgit 1.4.1-3-g733a5 From e523f053a3cd06453733f5543492d80e10bf8964 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 26 Jul 2017 16:30:58 +0900 Subject: Format source codes and update tests --- src/expr.rs | 6 ++---- src/items.rs | 4 +--- src/types.rs | 11 +++++------ src/visitor.rs | 3 +-- tests/target/configs-control_style-rfc.rs | 3 +-- tests/target/expr.rs | 6 ++---- tests/target/loop.rs | 9 ++++----- 7 files changed, 16 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 67214a96c60..8c8e245d202 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -334,8 +334,7 @@ pub fn format_expr( shape, ), ast::ExprKind::Catch(ref block) => { - if let rewrite @ Some(_) = - rewrite_single_line_block(context, "do catch ", block, shape) + if let rewrite @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { return rewrite; } @@ -826,8 +825,7 @@ fn rewrite_empty_block( block: &ast::Block, shape: Shape, ) -> Option { - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && - shape.width >= 2 + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 { return Some("{}".to_owned()); } diff --git a/src/items.rs b/src/items.rs index ac19e85a113..63e6eb7bc66 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2734,9 +2734,7 @@ fn format_generics( let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); - let same_line_brace = if !generics.where_clause.predicates.is_empty() || - result.contains('\n') - { + let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = context .config .max_width() diff --git a/src/types.rs b/src/types.rs index c34a3bfaa6a..5505966f818 100644 --- a/src/types.rs +++ b/src/types.rs @@ -44,12 +44,11 @@ pub fn rewrite_path( ) -> Option { let skip_count = qself.map_or(0, |x| x.position); - let mut result = - if path.is_global() && qself.is_none() && path_context != PathContext::Import { - "::".to_owned() - } else { - String::new() - }; + let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import { + "::".to_owned() + } else { + String::new() + }; let mut span_lo = path.span.lo; diff --git a/src/visitor.rs b/src/visitor.rs index 0f7005e2856..c657a4050e2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -328,8 +328,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Trait(..) => { self.format_missing_with_indent(item.span.lo); - if let Some(trait_str) = - format_trait(&self.get_context(), item, self.block_indent) + if let Some(trait_str) = format_trait(&self.get_context(), item, self.block_indent) { self.buffer.push_str(&trait_str); self.last_pos = source!(self, item.span).hi; diff --git a/tests/target/configs-control_style-rfc.rs b/tests/target/configs-control_style-rfc.rs index 8033aff208f..48aa7431736 100644 --- a/tests/target/configs-control_style-rfc.rs +++ b/tests/target/configs-control_style-rfc.rs @@ -12,8 +12,7 @@ fn main() { foo } if ai_timer.elapsed_time().as_microseconds() > ai_time.as_microseconds() { - if ball.position().y + ball_radius > - right_paddle.position().y + paddle_size.y / 2. + if ball.position().y + ball_radius > right_paddle.position().y + paddle_size.y / 2. { foo } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index dde596394a8..661637b743e 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -346,12 +346,10 @@ fn complex_if_else() { ha(); } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { yo(); - } else if let Some(x) = - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + - xxxxxxxxx + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { yo(); } diff --git a/tests/target/loop.rs b/tests/target/loop.rs index 2dfbff93a65..815f920a3c2 100644 --- a/tests/target/loop.rs +++ b/tests/target/loop.rs @@ -12,9 +12,9 @@ fn main() { // Just comments } - 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > - some_other_value - {} + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value + { + } while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { } @@ -22,8 +22,7 @@ fn main() { while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { } - 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in - some_iter(arg1, arg2) + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { // do smth } -- cgit 1.4.1-3-g733a5 From 2ffe4d05632ee09c73b948b47eb70d54d3fd95bc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 26 Jul 2017 17:40:57 +0900 Subject: Simplify rewrite_pair --- src/expr.rs | 87 +++++++++++++++++-------------------------------------------- 1 file changed, 24 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8c8e245d202..f6edc454a77 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -370,56 +370,37 @@ where LHS: Rewrite, RHS: Rewrite, { - // Get "full width" rhs and see if it fits on the current line. This - // usually works fairly well since it tends to place operands of - // operations with high precendence close together. - // Note that this is non-conservative, but its just to see if it's even - // worth trying to put everything on one line. - let rhs_shape = try_opt!(shape.sub_width(suffix.len())); - let rhs_orig_result = rhs.rewrite(context, rhs_shape); + let sep = if infix.ends_with(' ') { " " } else { "" }; + let infix = infix.trim_right(); + let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); + let lhs_shape = Shape { + width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), + ..shape + }; + let lhs_result = try_opt!( + lhs.rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}{}", prefix, lhs_str, infix)) + ); + // Try to the both lhs and rhs on the same line. + let rhs_orig_result = shape + .offset_left(last_line_width(&lhs_result) + suffix.len() + sep.len()) + .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); if let Some(ref rhs_result) = rhs_orig_result { - // This is needed in case of line break not caused by a - // shortage of space, but by end-of-line comments, for example. - if !rhs_result.contains('\n') { - let lhs_shape = - try_opt!(try_opt!(shape.offset_left(prefix.len())).sub_width(infix.len())); - let lhs_result = lhs.rewrite(context, lhs_shape); - if let Some(lhs_result) = lhs_result { - let mut result = format!("{}{}{}", prefix, lhs_result, infix); - - let remaining_width = shape - .width - .checked_sub(last_line_width(&result) + suffix.len()) - .unwrap_or(0); - - if rhs_result.len() <= remaining_width { - result.push_str(&rhs_result); - result.push_str(suffix); - return Some(result); - } - - // Try rewriting the rhs into the remaining space. - let rhs_shape = shape.offset_left(last_line_width(&result) + suffix.len()); - if let Some(rhs_shape) = rhs_shape { - if let Some(rhs_result) = rhs.rewrite(context, rhs_shape) { - // FIXME this should always hold. - if rhs_result.len() <= remaining_width { - result.push_str(&rhs_result); - result.push_str(suffix); - return Some(result); - } - } - } - } + // If the rhs looks like block expression, we allow it to stay on the same line + // with the lhs even if it is multi-lined. + let allow_same_line = rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); + if !rhs_result.contains('\n') || allow_same_line { + return Some(format!("{}{}{}{}", lhs_result, sep, rhs_result, suffix)); } } // We have to use multiple lines. - // Re-evaluate the rhs because we have more space now: - let sep = if infix.ends_with(' ') { " " } else { "" }; - let infix = infix.trim_right(); let rhs_shape = match context.config.control_style() { Style::Legacy => { try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) @@ -434,26 +415,6 @@ where } }; let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); - let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); - let lhs_shape = Shape { - width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), - ..shape - }; - let lhs_result = try_opt!( - lhs.rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}{}", prefix, lhs_str, infix)) - ); - if let Some(ref rhs_str) = rhs_orig_result { - if rhs_str.lines().count() <= rhs_result.lines().count() && - rhs_str - .lines() - .next() - .map_or(false, |first_line| first_line.ends_with('{')) && - last_line_width(&lhs_result) + sep.len() + first_line_width(rhs_str) <= shape.width - { - return Some(format!("{}{}{}{}", lhs_result, sep, rhs_str, suffix)); - } - } Some(format!( "{}\n{}{}{}", lhs_result, -- cgit 1.4.1-3-g733a5 From 760d6b85e2e8b837ee441e404b9eafd1c17be7c2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 26 Jul 2017 17:41:45 +0900 Subject: Ignore the last line overhead when rewriting condition --- src/expr.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f6edc454a77..99208b92134 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1156,12 +1156,23 @@ impl<'a> ControlFlow<'a> { shape: Shape, alt_block_sep: &str, ) -> Option<(String, usize)> { + // Do not take the rhs overhead from the upper expressions into account + // when rewriting pattern. + let new_width = context + .config + .max_width() + .checked_sub(shape.used_width()) + .unwrap_or(0); + let fresh_shape = Shape { + width: new_width, + ..shape + }; let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - try_opt!(shape.offset_left(7)) + try_opt!(fresh_shape.offset_left(7)) } else { - shape + fresh_shape }; let label_string = rewrite_label(self.label); -- cgit 1.4.1-3-g733a5 From 6b8f62fcc8467d4cf694727ef8fde8aefda264bc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 26 Jul 2017 17:42:52 +0900 Subject: Avoid regression --- src/expr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 99208b92134..7cebf793c60 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2281,10 +2281,10 @@ fn rewrite_last_closure( let body_shape = try_opt!(shape.offset_left(extra_offset)); // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. - if rewrite_cond(context, body, body_shape) - .map(|cond| cond.contains('\n')) - .unwrap_or(false) - { + let is_multi_lined_cond = rewrite_cond(context, body, body_shape) + .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) + .unwrap_or(false); + if is_multi_lined_cond { return rewrite_closure_with_block(context, body_shape, &prefix, body); } -- cgit 1.4.1-3-g733a5 From 38614e7af124c59c0d82d360af55b2eeed67bea3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 26 Jul 2017 17:43:17 +0900 Subject: Format source codes and update tests --- src/comment.rs | 4 ++-- src/expr.rs | 4 ++-- src/imports.rs | 24 ++++++++++++------------ src/patterns.rs | 22 +++++++++++----------- src/types.rs | 14 +++++++------- tests/target/chains-visual.rs | 8 ++++---- 6 files changed, 38 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 35ff88d86d1..d332c354b12 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -314,8 +314,8 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { &line[opener.trim_right().len()..] } } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || - line.starts_with("///") || - line.starts_with("** ") || line.starts_with("/*!") || + line.starts_with("///") || line.starts_with("** ") || + line.starts_with("/*!") || (line.starts_with("/**") && !line.starts_with("/**/")) { &line[3..] diff --git a/src/expr.rs b/src/expr.rs index 7cebf793c60..ab6bcb53e5a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -657,8 +657,8 @@ fn rewrite_closure( } // Figure out if the block is necessary. - let needs_block = block.rules != ast::BlockCheckMode::Default || - block.stmts.len() > 1 || context.inside_macro || + let needs_block = block.rules != ast::BlockCheckMode::Default || block.stmts.len() > 1 || + context.inside_macro || block_contains_comment(block, context.codemap) || prefix.contains('\n'); diff --git a/src/imports.rs b/src/imports.rs index d506fb583b4..69249a4522d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -482,18 +482,18 @@ fn rewrite_use_list( }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); - let result = - if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block { - format!( - "{}{{\n{}{}\n{}}}", - path_str, - nested_shape.indent.to_string(context.config), - list_str, - shape.indent.to_string(context.config) - ) - } else { - format!("{}{{{}}}", path_str, list_str) - }; + let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block + { + format!( + "{}{{\n{}{}\n{}}}", + path_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.indent.to_string(context.config) + ) + } else { + format!("{}{{{}}}", path_str, list_str) + }; Some(result) } diff --git a/src/patterns.rs b/src/patterns.rs index 544285ec213..03afe2d81b1 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -291,17 +291,17 @@ fn rewrite_tuple_pat( } let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); - let (pat_vec, span) = - if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 { - let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; - let sp = pat_vec[new_item_count - 1].span(); - let snippet = context.snippet(sp); - let lo = sp.lo + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); - (&pat_vec[..new_item_count], mk_sp(span.lo, lo + BytePos(1))) - } else { - (&pat_vec[..], span) - }; + let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 + { + let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; + let sp = pat_vec[new_item_count - 1].span(); + let snippet = context.snippet(sp); + let lo = sp.lo + BytePos(snippet.find_uncommented("_").unwrap() as u32); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + (&pat_vec[..new_item_count], mk_sp(span.lo, lo + BytePos(1))) + } else { + (&pat_vec[..], span) + }; // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); diff --git a/src/types.rs b/src/types.rs index 5505966f818..57a09a91501 100644 --- a/src/types.rs +++ b/src/types.rs @@ -632,13 +632,13 @@ impl Rewrite for ast::PolyTraitRef { Shape::legacy(max_path_width, shape.indent + extra_offset), )); - Some(if context.config.spaces_within_angle_brackets() && - lifetime_str.len() > 0 - { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }) + Some( + if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }, + ) } else { self.trait_ref.rewrite(context, shape) } diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index c2aecd26105..cfd7192b8b4 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -119,10 +119,10 @@ fn floaters() { .quux(); a + match x { - true => "yay!", - false => "boo!", - } - .bar() + true => "yay!", + false => "boo!", + } + .bar() } fn is_replaced_content() -> bool { -- cgit 1.4.1-3-g733a5 From 261865ecc9f83cec4264c534c4498942bfd3eb46 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 26 Jul 2017 22:43:36 +0900 Subject: Remove newlines between list elements for expressions --- src/expr.rs | 5 +++++ src/imports.rs | 1 + src/items.rs | 5 +++++ src/lists.rs | 7 ++++++- src/types.rs | 1 + src/vertical.rs | 1 + src/visitor.rs | 1 + 7 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 35e1e432733..06b32ab9ff5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -567,6 +567,7 @@ where }, shape: nested_shape, ends_with_newline: ends_with_newline, + preserve_newline: false, config: context.config, }; let list_str = try_opt!(write_list(&items, &fmt)); @@ -642,6 +643,7 @@ fn rewrite_closure_fn_decl( trailing_separator: SeparatorTactic::Never, shape: arg_shape, ends_with_newline: false, + preserve_newline: true, config: context.config, }; let list_str = try_opt!(write_list(&item_vec, &fmt)); @@ -1696,6 +1698,7 @@ fn rewrite_match_pattern( trailing_separator: SeparatorTactic::Never, shape: pat_shape, ends_with_newline: false, + preserve_newline: false, config: context.config, }; let pats_str = try_opt!(write_list(&items, &fmt)); @@ -2188,6 +2191,7 @@ where }, shape: shape, ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, + preserve_newline: false, config: context.config, }; @@ -2783,6 +2787,7 @@ where trailing_separator: SeparatorTactic::Never, shape: shape, ends_with_newline: false, + preserve_newline: false, config: context.config, }; let list_str = try_opt!(write_list(&item_vec, &fmt)); diff --git a/src/imports.rs b/src/imports.rs index d506fb583b4..a5ebb65c099 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -478,6 +478,7 @@ fn rewrite_use_list( }, shape: nested_shape, ends_with_newline: ends_with_newline, + preserve_newline: true, config: context.config, }; let list_str = try_opt!(write_list(&items[first_index..], &fmt)); diff --git a/src/items.rs b/src/items.rs index ac19e85a113..5f976d7283e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -477,6 +477,7 @@ impl<'a> FmtVisitor<'a> { trailing_separator: self.config.trailing_comma(), shape: shape, ends_with_newline: true, + preserve_newline: true, config: self.config, }; @@ -2252,6 +2253,7 @@ fn rewrite_args( }, shape: Shape::legacy(budget, indent), ends_with_newline: tactic.ends_with_newline(context.config.fn_args_layout()), + preserve_newline: true, config: context.config, }; @@ -2425,6 +2427,7 @@ where }, shape: shape, ends_with_newline: tactic.ends_with_newline(context.config.generics_indent()), + preserve_newline: true, config: context.config, }; @@ -2538,6 +2541,7 @@ fn rewrite_where_clause_rfc_style( trailing_separator: comma_tactic, shape: clause_shape, ends_with_newline: true, + preserve_newline: true, config: context.config, }; let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); @@ -2639,6 +2643,7 @@ fn rewrite_where_clause( trailing_separator: comma_tactic, shape: Shape::legacy(budget, offset), ends_with_newline: tactic.ends_with_newline(context.config.where_pred_indent()), + preserve_newline: true, config: context.config, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); diff --git a/src/lists.rs b/src/lists.rs index 6dfab314d97..5a6225a5903 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -65,6 +65,8 @@ pub struct ListFormatting<'a> { // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. pub ends_with_newline: bool, + // Remove newlines between list elements for expressions. + pub preserve_newline: bool, pub config: &'a Config, } @@ -342,7 +344,9 @@ where item_max_width = None; } - if !last && tactic == DefinitiveListTactic::Vertical && item.new_lines { + if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical && + item.new_lines + { item_max_width = None; result.push('\n'); } @@ -675,6 +679,7 @@ pub fn struct_lit_formatting<'a>( }, shape: shape, ends_with_newline: ends_with_newline, + preserve_newline: true, config: context.config, } } diff --git a/src/types.rs b/src/types.rs index c34a3bfaa6a..0439bf2cfac 100644 --- a/src/types.rs +++ b/src/types.rs @@ -361,6 +361,7 @@ where }, shape: list_shape, ends_with_newline: tactic.ends_with_newline(context.config.fn_call_style()), + preserve_newline: true, config: context.config, }; diff --git a/src/vertical.rs b/src/vertical.rs index 04d9ac9d35b..57876d644c2 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -229,6 +229,7 @@ fn rewrite_aligned_items_inner( trailing_separator: context.config.trailing_comma(), shape: item_shape, ends_with_newline: true, + preserve_newline: true, config: context.config, }; write_list(&items, &fmt) diff --git a/src/visitor.rs b/src/visitor.rs index 0f7005e2856..5daa9109cad 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -820,6 +820,7 @@ impl Rewrite for ast::MetaItem { trailing_separator: SeparatorTactic::Never, shape: item_shape, ends_with_newline: false, + preserve_newline: false, config: context.config, }; format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt))) -- cgit 1.4.1-3-g733a5 From c3cc8fcb13b6eac21721d1932b14b249d3d2c896 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 27 Jul 2017 09:43:35 +0900 Subject: Format defaultness --- src/items.rs | 9 +++++---- src/utils.rs | 8 ++++++++ tests/target/impl.rs | 5 +++++ 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cd2cdf28fe6..924c6b22969 100644 --- a/src/items.rs +++ b/src/items.rs @@ -26,9 +26,9 @@ use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, L ListItem, ListTactic, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::join_bounds; -use utils::{colon_spaces, contains_skip, end_typaram, format_mutability, format_unsafety, - format_visibility, last_line_width, mk_sp, semicolon_for_expr, stmt_expr, - trim_newlines, trimmed_last_line_width, wrap_str}; +use utils::{colon_spaces, contains_skip, end_typaram, format_defaultness, format_mutability, + format_unsafety, format_visibility, last_line_width, mk_sp, semicolon_for_expr, + stmt_expr, trim_newlines, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -695,7 +695,7 @@ fn format_impl_ref_and_type( if let ast::ItemKind::Impl( unsafety, polarity, - _, + defaultness, ref generics, ref trait_ref, ref self_ty, @@ -705,6 +705,7 @@ fn format_impl_ref_and_type( let mut result = String::new(); result.push_str(&format_visibility(&item.vis)); + result.push_str(&format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); diff --git a/src/utils.rs b/src/utils.rs index dc511fc3101..56dde6c247a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -56,6 +56,14 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { } } +#[inline] +pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { + match defaultness { + ast::Defaultness::Default => "default ", + ast::Defaultness::Final => "", + } +} + #[inline] pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { match unsafety { diff --git a/tests/target/impl.rs b/tests/target/impl.rs index ef8895580bd..c0db6769512 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -26,3 +26,8 @@ where T: Clone, { } + +// #1823 +default impl Trait for X {} +default unsafe impl Trait for Y {} +pub default unsafe impl Trait for Z {} -- cgit 1.4.1-3-g733a5 From 5a81c7d4b0bdbb82ef6018fe4200cf74479e12c6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 27 Jul 2017 11:09:38 +0900 Subject: Use correct BytePos for where when rewriting trait --- src/items.rs | 12 +++++++++--- tests/target/issue-1824.rs | 5 +++++ tests/target/trait.rs | 6 +++--- tests/target/where-clause-rfc.rs | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 tests/target/issue-1824.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cd2cdf28fe6..46361471206 100644 --- a/src/items.rs +++ b/src/items.rs @@ -962,8 +962,14 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) .checked_sub(last_line_width(&result)) ); let pos_before_where = if type_param_bounds.is_empty() { - // We do not use this, so it does not matter - generics.span.hi + if generics.where_clause.predicates.is_empty() { + // We do not use this, so it does not matter + item.span.lo + } else { + let snippet = context.snippet(item.span); + let where_pos = snippet.find_uncommented("where"); + item.span.lo + where_pos.map_or(BytePos(0), |p| BytePos(p as u32)) + } } else { type_param_bounds[type_param_bounds.len() - 1].span().hi }; @@ -974,7 +980,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) Shape::legacy(where_budget, offset.block_only()), where_density, "{", - !has_body, + false, trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, None, item.span, diff --git a/tests/target/issue-1824.rs b/tests/target/issue-1824.rs new file mode 100644 index 00000000000..1c4c2db46dc --- /dev/null +++ b/tests/target/issue-1824.rs @@ -0,0 +1,5 @@ +pub trait Ingredient +where + Self: Send, +{ +} diff --git a/tests/target/trait.rs b/tests/target/trait.rs index e4758e98b5e..cb1e0beb555 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -54,13 +54,13 @@ where trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where - T: Foo + T: Foo, { } trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where - T: Foo + T: Foo, { } @@ -75,6 +75,6 @@ where trait WhereList where T: Foo, - J: Bar + J: Bar, { } diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index bdf1f9d2574..ebfdc073eaa 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -110,6 +110,6 @@ where + Display + Write + Read - + FromStr + + FromStr, { } -- cgit 1.4.1-3-g733a5 From 462530cb7ec8e0ee74e8c606b78203db99122f5d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 28 Jul 2017 06:27:34 +0900 Subject: Fix a typo in rewrite_associated_type --- src/items.rs | 2 +- tests/source/trait.rs | 2 +- tests/target/trait.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cd2cdf28fe6..f7d193f0b57 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1598,7 +1598,7 @@ pub fn rewrite_associated_type( indent.block_only(), ), )); - Some(format!("{} = {};", prefix, ty_str)) + Some(format!("{}{} = {};", prefix, type_bounds_str, ty_str)) } else { Some(format!("{}{};", prefix, type_bounds_str)) } diff --git a/tests/source/trait.rs b/tests/source/trait.rs index faac57179c2..57cf4d79954 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -38,7 +38,7 @@ trait Test { trait T<> {} -trait Foo { type Bar: Baz;} +trait Foo { type Bar: Baz; type Inner: Foo = Box< Foo >; } trait ConstCheck:Foo where T: Baz { const J: i32; diff --git a/tests/target/trait.rs b/tests/target/trait.rs index e4758e98b5e..34a19d1f8af 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -43,6 +43,7 @@ trait T {} trait Foo { type Bar: Baz; + type Inner: Foo = Box; } trait ConstCheck: Foo -- cgit 1.4.1-3-g733a5 From 5aff5beb2a55ae380edd03c36db1f466c6b8644d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 29 Jul 2017 12:51:45 +0900 Subject: More fine-grained file-lines --- src/expr.rs | 7 ++++++- src/items.rs | 5 ++++- src/utils.rs | 25 +++++++++++++++++++++++++ src/visitor.rs | 16 ++++++++-------- tests/source/file-lines-item.rs | 12 ++++++++++++ tests/target/file-lines-item.rs | 12 ++++++++++++ 6 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 tests/source/file-lines-item.rs create mode 100644 tests/target/file-lines-item.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 68272f5af84..0d42582ff56 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -18,7 +18,7 @@ use syntax::parse::classify; use {Indent, Shape, Spanned}; use chains::rewrite_chain; -use codemap::SpanUtils; +use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; use items::{span_hi_for_arg, span_lo_for_arg}; @@ -111,9 +111,12 @@ pub fn format_expr( context: &RewriteContext, shape: Shape, ) -> Option { + skip_out_of_file_lines_range!(context, expr.span); + if contains_skip(&*expr.attrs) { return Some(context.snippet(expr.span())); } + let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( expr_vec.iter().map(|e| &**e), @@ -898,6 +901,8 @@ impl Rewrite for ast::Block { impl Rewrite for ast::Stmt { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + skip_out_of_file_lines_range!(context, self.span()); + let result = match self.node { ast::StmtKind::Local(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { diff --git a/src/items.rs b/src/items.rs index f21277e9e83..f4354549499 100644 --- a/src/items.rs +++ b/src/items.rs @@ -17,7 +17,7 @@ use syntax::ast::ImplItem; use syntax::codemap::{BytePos, Span}; use {Indent, Shape, Spanned}; -use codemap::SpanUtils; +use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, @@ -50,6 +50,9 @@ impl Rewrite for ast::Local { shape.width, shape.indent ); + + skip_out_of_file_lines_range!(context, self.span); + let mut result = "let ".to_owned(); // 4 = "let ".len() diff --git a/src/utils.rs b/src/utils.rs index 56dde6c247a..9c1717e8638 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -323,6 +323,31 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { } } +// Return true if the given span does not intersect with file lines. +macro_rules! out_of_file_lines_range { + ($self:ident, $span:expr) => { + !$self.config + .file_lines() + .intersects(&$self.codemap.lookup_line_range($span)) + } +} + +macro_rules! skip_out_of_file_lines_range { + ($self:ident, $span:expr) => { + if out_of_file_lines_range!($self, $span) { + return None; + } + } +} + +macro_rules! skip_out_of_file_lines_range_visitor { + ($self:ident, $span:expr) => { + if out_of_file_lines_range!($self, $span) { + return; + } + } +} + // Wraps string-like values in an Option. Returns Some when the string adheres // to the Rewrite constraints defined for the Rewrite trait and else otherwise. pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option { diff --git a/src/visitor.rs b/src/visitor.rs index cb94ea9a6dc..389c606c54b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -67,14 +67,6 @@ impl<'a> FmtVisitor<'a> { self.codemap.lookup_char_pos(stmt.span.hi) ); - // FIXME(#434): Move this check to somewhere more central, eg Rewrite. - if !self.config - .file_lines() - .intersects(&self.codemap.lookup_line_range(stmt.span)) - { - return; - } - match stmt.node { ast::StmtKind::Item(ref item) => { self.visit_item(item); @@ -264,6 +256,8 @@ impl<'a> FmtVisitor<'a> { } pub fn visit_item(&mut self, item: &ast::Item) { + skip_out_of_file_lines_range_visitor!(self, item.span); + // This is where we bail out if there is a skip attribute. This is only // complex in the module case. It is complex because the module could be // in a separate file and there might be attributes in both files, but @@ -465,6 +459,8 @@ impl<'a> FmtVisitor<'a> { } pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + skip_out_of_file_lines_range_visitor!(self, ti.span); + if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { self.push_rewrite(ti.span, None); return; @@ -517,6 +513,8 @@ impl<'a> FmtVisitor<'a> { } pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + skip_out_of_file_lines_range_visitor!(self, ii.span); + if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { self.push_rewrite(ii.span, None); return; @@ -565,6 +563,8 @@ impl<'a> FmtVisitor<'a> { } fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { + skip_out_of_file_lines_range_visitor!(self, mac.span); + // 1 = ; let shape = Shape::indented(self.block_indent, self.config) .sub_width(1) diff --git a/tests/source/file-lines-item.rs b/tests/source/file-lines-item.rs new file mode 100644 index 00000000000..41043d873ac --- /dev/null +++ b/tests/source/file-lines-item.rs @@ -0,0 +1,12 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[5,7]}] + +use foo::{c, b, a}; + +fn foo() { + bar ( ) ; +} + +impl Drop for Context { + fn drop(&mut self) { + } +} diff --git a/tests/target/file-lines-item.rs b/tests/target/file-lines-item.rs new file mode 100644 index 00000000000..b5561040ac6 --- /dev/null +++ b/tests/target/file-lines-item.rs @@ -0,0 +1,12 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[5,7]}] + +use foo::{c, b, a}; + +fn foo() { + bar(); +} + +impl Drop for Context { + fn drop(&mut self) { + } +} -- cgit 1.4.1-3-g733a5 From 3377ba4dd76d458bb7746379dad5df2c70ad1cd4 Mon Sep 17 00:00:00 2001 From: Fausto Núñez Alberro Date: Tue, 25 Jul 2017 19:46:09 +0200 Subject: Remove whitespace between extern crate declaration --- src/visitor.rs | 10 +++++++++- tests/source/extern.rs | 3 +++ tests/target/extern.rs | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 0f7005e2856..2326848ddd2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -25,6 +25,7 @@ use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_ass rewrite_static, rewrite_type_alias}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; +use regex::Regex; use rewrite::{Rewrite, RewriteContext}; use utils::{self, contains_skip, mk_sp}; @@ -338,7 +339,14 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::ExternCrate(_) => { self.format_missing_with_indent(source!(self, item.span).lo); let new_str = self.snippet(item.span); - self.buffer.push_str(&new_str); + if contains_comment(&new_str) { + self.buffer.push_str(&new_str) + } else { + let no_whitespace = + &new_str.split_whitespace().collect::>().join(" "); + self.buffer + .push_str(&Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")); + } self.last_pos = source!(self, item.span).hi; } ast::ItemKind::Struct(ref def, ref generics) => { diff --git a/tests/source/extern.rs b/tests/source/extern.rs index 1dd1df2b74e..7f14d27b779 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -1,5 +1,8 @@ // rustfmt-normalize_comments: true + extern crate foo ; + extern crate foo as bar ; + extern "C" { fn c_func(x: *mut *mut libc::c_void); diff --git a/tests/target/extern.rs b/tests/target/extern.rs index efee6ab26bf..1431c384db9 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,5 +1,8 @@ // rustfmt-normalize_comments: true +extern crate foo; +extern crate foo as bar; + extern "C" { fn c_func(x: *mut *mut libc::c_void); -- cgit 1.4.1-3-g733a5 From 570a3505b9dd0fcf61b4d9f6a8f2dd6b04cb7e54 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 29 Jul 2017 22:12:18 +0900 Subject: Make definitive_tactic more generic with separator length --- src/expr.rs | 14 +++++++++++--- src/imports.rs | 1 + src/items.rs | 10 ++++++++-- src/lists.rs | 10 +++++++--- src/types.rs | 2 +- src/vertical.rs | 2 +- 6 files changed, 29 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 68272f5af84..5621bcbf1b9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -485,7 +485,7 @@ where Some(width) => { let tactic = ListTactic::LimitedHorizontalVertical(context.config.array_width()); - definitive_tactic(&items, tactic, width) + definitive_tactic(&items, tactic, 2, width) } None => DefinitiveListTactic::Vertical, } @@ -494,6 +494,7 @@ where definitive_tactic( &items, ListTactic::LimitedHorizontalVertical(context.config.array_width()), + 2, nested_shape.width, ) } else { @@ -591,7 +592,12 @@ fn rewrite_closure_fn_decl( .width .checked_sub(ret_str.len() + 1) .unwrap_or(0); - let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + 2, + horizontal_budget, + ); let arg_shape = match tactic { DefinitiveListTactic::Horizontal => try_opt!(arg_shape.sub_width(ret_str.len() + 1)), _ => arg_shape, @@ -1668,7 +1674,7 @@ fn rewrite_match_pattern( ); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, pat_shape.width); + let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, 3, pat_shape.width); let fmt = ListFormatting { tactic: tactic, separator: " |", @@ -2216,6 +2222,7 @@ where let tactic = definitive_tactic( &*item_vec, ListTactic::LimitedHorizontalVertical(args_max_width), + 2, one_line_width, ); @@ -2756,6 +2763,7 @@ where let tactic = definitive_tactic( &item_vec, ListTactic::HorizontalVertical, + 2, nested_shape.width, ); let fmt = ListFormatting { diff --git a/src/imports.rs b/src/imports.rs index 00b6711cf9b..bc743649e84 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -451,6 +451,7 @@ fn rewrite_use_list( let tactic = definitive_tactic( &items[first_index..], context.config.imports_layout(), + 2, remaining_width, ); diff --git a/src/items.rs b/src/items.rs index f21277e9e83..8b4fd4c725e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2241,6 +2241,7 @@ fn rewrite_args( let tactic = definitive_tactic( &arg_items, context.config.fn_args_density().to_list_tactic(), + 2, one_line_budget, ); let budget = match tactic { @@ -2423,7 +2424,12 @@ where { let item_vec = items.collect::>(); - let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, one_line_budget); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + 2, + one_line_budget, + ); let fmt = ListFormatting { tactic: tactic, separator: ",", @@ -2636,7 +2642,7 @@ fn rewrite_where_clause( let item_vec = items.collect::>(); // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. - let tactic = definitive_tactic(&item_vec, context.config.where_layout(), budget); + let tactic = definitive_tactic(&item_vec, context.config.where_layout(), 2, budget); let mut comma_tactic = context.config.trailing_comma(); // Kind of a hack because we don't usually have trailing commas in where clauses. diff --git a/src/lists.rs b/src/lists.rs index 5a6225a5903..56ac10691de 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -135,7 +135,12 @@ impl DefinitiveListTactic { } } -pub fn definitive_tactic(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic +pub fn definitive_tactic( + items: I, + tactic: ListTactic, + sep_len: usize, + width: usize, +) -> DefinitiveListTactic where I: IntoIterator + Clone, T: AsRef, @@ -155,7 +160,6 @@ where }; let (sep_count, total_width) = calculate_width(items.clone()); - let sep_len = ", ".len(); // FIXME: make more generic? let total_sep_len = sep_len * sep_count.checked_sub(1).unwrap_or(0); let real_total = total_width + total_sep_len; @@ -640,7 +644,7 @@ pub fn struct_lit_tactic( (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style().to_list_tactic(), }; - definitive_tactic(items, prelim_tactic, h_shape.width) + definitive_tactic(items, prelim_tactic, 2, h_shape.width) } else { DefinitiveListTactic::Vertical } diff --git a/src/types.rs b/src/types.rs index 71e6bcdcd18..3144efe9db0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -348,7 +348,7 @@ where let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic(&*item_vec, ListTactic::HorizontalVertical, budget); + let tactic = definitive_tactic(&*item_vec, ListTactic::HorizontalVertical, 2, budget); let fmt = ListFormatting { tactic: tactic, diff --git a/src/vertical.rs b/src/vertical.rs index 57876d644c2..08ef6281baa 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -221,7 +221,7 @@ fn rewrite_aligned_items_inner( span.hi, ).collect::>(); - let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, one_line_width); + let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, 2, one_line_width); let fmt = ListFormatting { tactic: tactic, -- cgit 1.4.1-3-g733a5 From e588f2fd7b0445944f15341f9b45051f440b82b4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 31 Jul 2017 16:23:42 +0900 Subject: Make definitive_tactic more generic via enum Separator --- src/expr.rs | 19 ++++++++++++------- src/imports.rs | 4 ++-- src/items.rs | 13 +++++++++---- src/lists.rs | 24 +++++++++++++++++++++--- src/types.rs | 9 +++++++-- src/vertical.rs | 9 +++++++-- 6 files changed, 58 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5621bcbf1b9..cf2bc337247 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -24,7 +24,7 @@ use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, SeparatorTactic}; + ListItem, ListTactic, Separator, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; @@ -485,7 +485,7 @@ where Some(width) => { let tactic = ListTactic::LimitedHorizontalVertical(context.config.array_width()); - definitive_tactic(&items, tactic, 2, width) + definitive_tactic(&items, tactic, Separator::Comma, width) } None => DefinitiveListTactic::Vertical, } @@ -494,7 +494,7 @@ where definitive_tactic( &items, ListTactic::LimitedHorizontalVertical(context.config.array_width()), - 2, + Separator::Comma, nested_shape.width, ) } else { @@ -595,7 +595,7 @@ fn rewrite_closure_fn_decl( let tactic = definitive_tactic( &item_vec, ListTactic::HorizontalVertical, - 2, + Separator::Comma, horizontal_budget, ); let arg_shape = match tactic { @@ -1674,7 +1674,12 @@ fn rewrite_match_pattern( ); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, 3, pat_shape.width); + let tactic = definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + pat_shape.width, + ); let fmt = ListFormatting { tactic: tactic, separator: " |", @@ -2222,7 +2227,7 @@ where let tactic = definitive_tactic( &*item_vec, ListTactic::LimitedHorizontalVertical(args_max_width), - 2, + Separator::Comma, one_line_width, ); @@ -2763,7 +2768,7 @@ where let tactic = definitive_tactic( &item_vec, ListTactic::HorizontalVertical, - 2, + Separator::Comma, nested_shape.width, ); let fmt = ListFormatting { diff --git a/src/imports.rs b/src/imports.rs index bc743649e84..e0049698bfb 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -17,7 +17,7 @@ use Shape; use codemap::SpanUtils; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, SeparatorTactic}; + ListItem, Separator, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; use utils; @@ -451,7 +451,7 @@ fn rewrite_use_list( let tactic = definitive_tactic( &items[first_index..], context.config.imports_layout(), - 2, + Separator::Comma, remaining_width, ); diff --git a/src/items.rs b/src/items.rs index 8b4fd4c725e..89028afdc10 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,7 +23,7 @@ use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, SeparatorTactic}; + ListItem, ListTactic, Separator, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, format_defaultness, format_mutability, @@ -2241,7 +2241,7 @@ fn rewrite_args( let tactic = definitive_tactic( &arg_items, context.config.fn_args_density().to_list_tactic(), - 2, + Separator::Comma, one_line_budget, ); let budget = match tactic { @@ -2427,7 +2427,7 @@ where let tactic = definitive_tactic( &item_vec, ListTactic::HorizontalVertical, - 2, + Separator::Comma, one_line_budget, ); let fmt = ListFormatting { @@ -2642,7 +2642,12 @@ fn rewrite_where_clause( let item_vec = items.collect::>(); // FIXME: we don't need to collect here if the where_layout isn't // HorizontalVertical. - let tactic = definitive_tactic(&item_vec, context.config.where_layout(), 2, budget); + let tactic = definitive_tactic( + &item_vec, + context.config.where_layout(), + Separator::Comma, + budget, + ); let mut comma_tactic = context.config.trailing_comma(); // Kind of a hack because we don't usually have trailing commas in where clauses. diff --git a/src/lists.rs b/src/lists.rs index 56ac10691de..048f11a1856 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -135,10 +135,28 @@ impl DefinitiveListTactic { } } +/// The type of separator for lists. +#[derive(Eq, PartialEq, Debug)] +pub enum Separator { + Comma, + VerticalBar, +} + +impl Separator { + pub fn len(&self) -> usize { + match *self { + // 2 = `, ` + Separator::Comma => 2, + // 3 = ` | ` + Separator::VerticalBar => 3, + } + } +} + pub fn definitive_tactic( items: I, tactic: ListTactic, - sep_len: usize, + sep: Separator, width: usize, ) -> DefinitiveListTactic where @@ -160,7 +178,7 @@ where }; let (sep_count, total_width) = calculate_width(items.clone()); - let total_sep_len = sep_len * sep_count.checked_sub(1).unwrap_or(0); + let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); let real_total = total_width + total_sep_len; if real_total <= limit && !pre_line_comments && @@ -644,7 +662,7 @@ pub fn struct_lit_tactic( (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style().to_list_tactic(), }; - definitive_tactic(items, prelim_tactic, 2, h_shape.width) + definitive_tactic(items, prelim_tactic, Separator::Comma, h_shape.width) } else { DefinitiveListTactic::Vertical } diff --git a/src/types.rs b/src/types.rs index 3144efe9db0..8e0cf2436de 100644 --- a/src/types.rs +++ b/src/types.rs @@ -22,7 +22,7 @@ use codemap::SpanUtils; use config::{IndentStyle, Style, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; use items::{format_generics_item_list, generics_shape_from_config}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp, wrap_str}; @@ -348,7 +348,12 @@ where let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic(&*item_vec, ListTactic::HorizontalVertical, 2, budget); + let tactic = definitive_tactic( + &*item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + budget, + ); let fmt = ListFormatting { tactic: tactic, diff --git a/src/vertical.rs b/src/vertical.rs index 08ef6281baa..7f43fa8681a 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -20,7 +20,7 @@ use codemap::SpanUtils; use comment::contains_comment; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator}; use rewrite::{Rewrite, RewriteContext}; use utils::{contains_skip, mk_sp}; @@ -221,7 +221,12 @@ fn rewrite_aligned_items_inner( span.hi, ).collect::>(); - let tactic = definitive_tactic(&items, ListTactic::HorizontalVertical, 2, one_line_width); + let tactic = definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::Comma, + one_line_width, + ); let fmt = ListFormatting { tactic: tactic, -- cgit 1.4.1-3-g733a5 From 568a9adf8780c80b3301d25981a4926307d73e50 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 31 Jul 2017 16:24:07 +0900 Subject: Avoid early line breaks in match condition --- src/expr.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index cf2bc337247..0a1a4a58316 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1531,17 +1531,25 @@ fn rewrite_match( return None; } - // 6 = `match `, 2 = ` {` + // Do not take the rhs overhead from the upper expressions into account + // when rewriting match condition. + let new_width = try_opt!(context.config.max_width().checked_sub(shape.used_width())); + let cond_shape = Shape { + width: new_width, + ..shape + }; + // 6 = `match ` let cond_shape = match context.config.control_style() { - Style::Legacy => try_opt!(shape.shrink_left(6).and_then(|s| s.sub_width(2))), - Style::Rfc => try_opt!(shape.offset_left(6).and_then(|s| s.sub_width(2))), + Style::Legacy => try_opt!(cond_shape.shrink_left(6)), + Style::Rfc => try_opt!(cond_shape.offset_left(6)), }; let cond_str = try_opt!(cond.rewrite(context, cond_shape)); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => &alt_block_sep, _ if last_line_extendable(&cond_str) => " ", - _ if cond_str.contains('\n') => &alt_block_sep, + // 2 = ` {` + _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => &alt_block_sep, _ => " ", }; -- cgit 1.4.1-3-g733a5 From 6bf9124ace1f341176ee3996aa0cb3c013bf9d8c Mon Sep 17 00:00:00 2001 From: Emilio Cobos Álvarez Date: Sat, 29 Jul 2017 17:06:50 +0200 Subject: visitor: Make sure to don't eat or realign items when they should be skipped due to file-lines. Before this patch, stuff like the argument with the comment was realigned to column 0, even when being outside of the file_lines range. --- src/utils.rs | 1 + tests/source/file-lines-item.rs | 8 ++++++++ tests/target/file-lines-item.rs | 8 ++++++++ 3 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 9c1717e8638..47ce5e7fcbe 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -343,6 +343,7 @@ macro_rules! skip_out_of_file_lines_range { macro_rules! skip_out_of_file_lines_range_visitor { ($self:ident, $span:expr) => { if out_of_file_lines_range!($self, $span) { + $self.push_rewrite($span, None); return; } } diff --git a/tests/source/file-lines-item.rs b/tests/source/file-lines-item.rs index 41043d873ac..2f856c004e8 100644 --- a/tests/source/file-lines-item.rs +++ b/tests/source/file-lines-item.rs @@ -10,3 +10,11 @@ impl Drop for Context { fn drop(&mut self) { } } + +impl Bar for Baz { + fn foo() { + bar( + baz, // Who knows? + ) + } +} diff --git a/tests/target/file-lines-item.rs b/tests/target/file-lines-item.rs index b5561040ac6..f0908cba56a 100644 --- a/tests/target/file-lines-item.rs +++ b/tests/target/file-lines-item.rs @@ -10,3 +10,11 @@ impl Drop for Context { fn drop(&mut self) { } } + +impl Bar for Baz { + fn foo() { + bar( + baz, // Who knows? + ) + } +} -- cgit 1.4.1-3-g733a5 From 27a3bdb394f4adda57206d29591e716c7fd1e278 Mon Sep 17 00:00:00 2001 From: Emilio Cobos Álvarez Date: Sat, 29 Jul 2017 17:07:17 +0200 Subject: visitor: Only reorder imports if at least one of them is in file-lines. --- src/visitor.rs | 14 +++++++++++++- tests/source/file-lines-item.rs | 4 +++- tests/target/file-lines-item.rs | 4 +++- 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index cc178dc0a86..bc3126615d3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -661,7 +661,19 @@ impl<'a> FmtVisitor<'a> { }) .count(); let (use_items, rest) = items_left.split_at(use_item_length); - self.format_imports(use_items); + + let at_least_one_in_file_lines = use_items + .iter() + .any(|item| !out_of_file_lines_range!(self, item.span)); + + if at_least_one_in_file_lines { + self.format_imports(use_items); + } else { + for item in use_items { + self.push_rewrite(item.span, None); + } + } + items_left = rest; } else { // `unwrap()` is safe here because we know `items_left` diff --git a/tests/source/file-lines-item.rs b/tests/source/file-lines-item.rs index 2f856c004e8..0ed4b93df5f 100644 --- a/tests/source/file-lines-item.rs +++ b/tests/source/file-lines-item.rs @@ -1,6 +1,8 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[5,7]}] +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] +// rustfmt-reorder_imports: true use foo::{c, b, a}; +use bar; fn foo() { bar ( ) ; diff --git a/tests/target/file-lines-item.rs b/tests/target/file-lines-item.rs index f0908cba56a..e155e75f34c 100644 --- a/tests/target/file-lines-item.rs +++ b/tests/target/file-lines-item.rs @@ -1,6 +1,8 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[5,7]}] +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] +// rustfmt-reorder_imports: true use foo::{c, b, a}; +use bar; fn foo() { bar(); -- cgit 1.4.1-3-g733a5 From c12b4e90317c19182202acdc80615b5280dfb08b Mon Sep 17 00:00:00 2001 From: Emilio Cobos Álvarez Date: Sun, 30 Jul 2017 00:59:30 +0200 Subject: bin: Add a very simple rustfmt-format-diff. This patch introduces a super-simple format-diff tool, that allows you to do: ``` git diff | rustfmt-format-diff -p 1 ``` To format your current changes. For now it doesn't accept too much customisation, and it basically calls rustfmt with the default configuration, but more customisation can be added in the future if needed. --- Cargo.toml | 6 +- src/bin/rustfmt-format-diff.rs | 277 +++++++++++++++++++++++++++++++++++++++++ src/bin/test/bindgen.diff | 67 ++++++++++ 3 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 src/bin/rustfmt-format-diff.rs create mode 100644 src/bin/test/bindgen.diff (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 9af270a710b..0e0920f8755 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,13 @@ name = "rustfmt" [[bin]] name = "cargo-fmt" +[[bin]] +name = "rustfmt-format-diff" + [features] -default = ["cargo-fmt"] +default = ["cargo-fmt", "rustfmt-format-diff"] cargo-fmt = [] +rustfmt-format-diff = [] [dependencies] toml = "0.4" diff --git a/src/bin/rustfmt-format-diff.rs b/src/bin/rustfmt-format-diff.rs new file mode 100644 index 00000000000..23bac21f215 --- /dev/null +++ b/src/bin/rustfmt-format-diff.rs @@ -0,0 +1,277 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Clang's clang-format-diff: +// +// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py + +#![deny(warnings)] + +extern crate getopts; +extern crate regex; +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json as json; + +use std::{env, fmt, process}; +use std::collections::HashSet; +use std::error::Error; +use std::io::{self, BufRead}; + +use regex::Regex; + +/// The default pattern of files to format. +/// +/// We only want to format rust files by default. +const DEFAULT_PATTERN: &'static str = r".*\.rs"; + +#[derive(Debug)] +enum FormatDiffError { + IncorrectOptions(getopts::Fail), + IncorrectFilter(regex::Error), + IoError(io::Error), +} + +impl fmt::Display for FormatDiffError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fmt::Display::fmt(self.cause().unwrap(), f) + } +} + +impl Error for FormatDiffError { + fn description(&self) -> &str { + self.cause().unwrap().description() + } + + fn cause(&self) -> Option<&Error> { + Some(match *self { + FormatDiffError::IoError(ref e) => e, + FormatDiffError::IncorrectFilter(ref e) => e, + FormatDiffError::IncorrectOptions(ref e) => e, + }) + } +} + +impl From for FormatDiffError { + fn from(fail: getopts::Fail) -> Self { + FormatDiffError::IncorrectOptions(fail) + } +} + +impl From for FormatDiffError { + fn from(err: regex::Error) -> Self { + FormatDiffError::IncorrectFilter(err) + } +} + +impl From for FormatDiffError { + fn from(fail: io::Error) -> Self { + FormatDiffError::IoError(fail) + } +} + +fn main() { + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("v", "verbose", "use verbose output"); + opts.optopt( + "p", + "skip-prefix", + "skip the smallest prefix containing NUMBER slashes", + "NUMBER", + ); + opts.optopt( + "f", + "filter", + "custom pattern selecting file paths to reformat", + "PATTERN", + ); + + if let Err(e) = run(&opts) { + println!("{}", opts.usage(e.description())); + process::exit(1); + } +} + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +struct Range { + file: String, + range: [u32; 2], +} + +fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { + let matches = opts.parse(env::args().skip(1))?; + + if matches.opt_present("h") { + println!("{}", opts.usage("usage: ")); + return Ok(()); + } + + let verbose = matches.opt_present("v"); + + let filter = matches + .opt_str("f") + .unwrap_or_else(|| DEFAULT_PATTERN.into()); + + + let skip_prefix = matches + .opt_str("p") + .and_then(|p| p.parse::().ok()) + .unwrap_or(0); + + let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; + + run_rustfmt(&files, &ranges, verbose) +} + +fn run_rustfmt( + files: &HashSet, + ranges: &[Range], + verbose: bool, +) -> Result<(), FormatDiffError> { + if files.is_empty() || ranges.is_empty() { + if verbose { + println!("No files to format found"); + } + return Ok(()); + } + + let ranges_as_json = json::to_string(ranges).unwrap(); + if verbose { + print!("rustfmt"); + for file in files { + print!(" {:?}", file); + } + print!(" --file-lines {:?}", ranges_as_json); + } + + let exit_status = process::Command::new("rustfmt") + .args(files) + .arg("--file-lines") + .arg(ranges_as_json) + .status()?; + + if !exit_status.success() { + return Err(FormatDiffError::IoError(io::Error::new( + io::ErrorKind::Other, + format!("rustfmt failed with {}", exit_status), + ))); + } + Ok(()) +} + +/// Scans a diff from `from`, and returns the set of files found, and the ranges +/// in those files. +fn scan_diff( + from: R, + skip_prefix: u32, + file_filter: &str, +) -> Result<(HashSet, Vec), FormatDiffError> +where + R: io::Read, +{ + let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix); + let diff_pattern = Regex::new(&diff_pattern).unwrap(); + + let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap(); + + let file_filter = Regex::new(&format!("^{}$", file_filter))?; + + let mut current_file = None; + + let mut files = HashSet::new(); + let mut ranges = vec![]; + for line in io::BufReader::new(from).lines() { + let line = line.unwrap(); + + if let Some(captures) = diff_pattern.captures(&line) { + current_file = Some(captures.get(1).unwrap().as_str().to_owned()); + } + + let file = match current_file { + Some(ref f) => &**f, + None => continue, + }; + + // TODO(emilio): We could avoid this most of the time if needed, but + // it's not clear it's worth it. + if !file_filter.is_match(file) { + continue; + } + + let lines_captures = match lines_pattern.captures(&line) { + Some(captures) => captures, + None => continue, + }; + + let start_line = lines_captures + .get(1) + .unwrap() + .as_str() + .parse::() + .unwrap(); + let line_count = match lines_captures.get(3) { + Some(line_count) => line_count.as_str().parse::().unwrap(), + None => 1, + }; + + if line_count == 0 { + continue; + } + + let end_line = start_line + line_count - 1; + files.insert(file.to_owned()); + ranges.push(Range { + file: file.to_owned(), + range: [start_line, end_line], + }); + } + + Ok((files, ranges)) +} + +#[test] +fn scan_simple_git_diff() { + const DIFF: &'static str = include_str!("test/bindgen.diff"); + let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); + + assert!( + files.contains("src/ir/traversal.rs"), + "Should've matched the filter" + ); + + assert!( + !files.contains("tests/headers/anon_enum.hpp"), + "Shouldn't have matched the filter" + ); + + assert_eq!( + &ranges, + &[ + Range { + file: "src/ir/item.rs".into(), + range: [148, 158], + }, + Range { + file: "src/ir/item.rs".into(), + range: [160, 170], + }, + Range { + file: "src/ir/traversal.rs".into(), + range: [9, 16], + }, + Range { + file: "src/ir/traversal.rs".into(), + range: [35, 43], + } + ] + ); +} diff --git a/src/bin/test/bindgen.diff b/src/bin/test/bindgen.diff new file mode 100644 index 00000000000..d2fd379f471 --- /dev/null +++ b/src/bin/test/bindgen.diff @@ -0,0 +1,67 @@ +diff --git a/src/ir/item.rs b/src/ir/item.rs +index 7f3afefb..90d15e96 100644 +--- a/src/ir/item.rs ++++ b/src/ir/item.rs +@@ -148,7 +148,11 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> + impl AsTemplateParam for ItemId { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + ctx.resolve_item(*self).as_template_param(ctx, &()) + } + } +@@ -156,7 +160,11 @@ impl AsTemplateParam for ItemId { + impl AsTemplateParam for Item { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + self.kind.as_template_param(ctx, self) + } + } +diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs +index 762a3e2d..b9c9dd4e 100644 +--- a/src/ir/traversal.rs ++++ b/src/ir/traversal.rs +@@ -9,6 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; + /// + /// from --> to + /// ++/// Random content to generate a diff. ++/// + /// The `from` is left implicit: it is the concrete `Trace` implementer which + /// yielded this outgoing edge. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +@@ -33,7 +35,9 @@ impl Into for Edge { + } + } + +-/// The kind of edge reference. This is useful when we wish to only consider ++/// The kind of edge reference. ++/// ++/// This is useful when we wish to only consider + /// certain kinds of edges for a particular traversal or analysis. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum EdgeKind { +diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp +index 1961fe6c..34759df3 100644 +--- a/tests/headers/anon_enum.hpp ++++ b/tests/headers/anon_enum.hpp +@@ -1,7 +1,7 @@ + struct Test { + int foo; + float bar; +- enum { T_NONE }; ++ enum { T_NONE, T_SOME }; + }; + + typedef enum { -- cgit 1.4.1-3-g733a5 From 068bcad880b1e14d44ae7aef8709b8f60bea526e Mon Sep 17 00:00:00 2001 From: Emilio Cobos Álvarez Date: Mon, 31 Jul 2017 09:38:24 +0100 Subject: rustfmt-format-diff: Use logging macros instead of "-v" option. --- src/bin/rustfmt-format-diff.rs | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt-format-diff.rs b/src/bin/rustfmt-format-diff.rs index 23bac21f215..f7f3c1d8f7c 100644 --- a/src/bin/rustfmt-format-diff.rs +++ b/src/bin/rustfmt-format-diff.rs @@ -14,7 +14,10 @@ #![deny(warnings)] +extern crate env_logger; extern crate getopts; +#[macro_use] +extern crate log; extern crate regex; extern crate serde; #[macro_use] @@ -79,9 +82,10 @@ impl From for FormatDiffError { } fn main() { + let _ = env_logger::init(); + let mut opts = getopts::Options::new(); opts.optflag("h", "help", "show this message"); - opts.optflag("v", "verbose", "use verbose output"); opts.optopt( "p", "skip-prefix", @@ -115,13 +119,10 @@ fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { return Ok(()); } - let verbose = matches.opt_present("v"); - let filter = matches .opt_str("f") .unwrap_or_else(|| DEFAULT_PATTERN.into()); - let skip_prefix = matches .opt_str("p") .and_then(|p| p.parse::().ok()) @@ -129,29 +130,19 @@ fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; - run_rustfmt(&files, &ranges, verbose) + run_rustfmt(&files, &ranges) } -fn run_rustfmt( - files: &HashSet, - ranges: &[Range], - verbose: bool, -) -> Result<(), FormatDiffError> { +fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDiffError> { if files.is_empty() || ranges.is_empty() { - if verbose { - println!("No files to format found"); - } + debug!("No files to format found"); return Ok(()); } let ranges_as_json = json::to_string(ranges).unwrap(); - if verbose { - print!("rustfmt"); - for file in files { - print!(" {:?}", file); - } - print!(" --file-lines {:?}", ranges_as_json); - } + + debug!("Files: {:?}", files); + debug!("Ranges: {:?}", ranges); let exit_status = process::Command::new("rustfmt") .args(files) -- cgit 1.4.1-3-g733a5 From e636fe732edb760e4b201bae6456bbe04ea895bc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 1 Aug 2017 18:36:36 +0900 Subject: Use Span from ast::WhereClause --- src/items.rs | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d8afbe29b99..f05554905af 100644 --- a/src/items.rs +++ b/src/items.rs @@ -39,7 +39,6 @@ fn type_annotation_separator(config: &Config) -> &str { ) } - // Statements of the form // let pat: ty = init; impl Rewrite for ast::Local { @@ -591,7 +590,6 @@ pub fn format_impl( false, last_line_width(&ref_and_type) == 1, where_span_end, - item.span, self_ty.span.hi, )); @@ -987,7 +985,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) false, trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, None, - item.span, pos_before_where, )); // If the where clause cannot fit on the same line, @@ -1220,7 +1217,6 @@ fn format_tuple_struct( true, false, None, - span, body_hi, )) } @@ -1321,7 +1317,6 @@ pub fn rewrite_type_alias( true, true, Some(span.hi), - span, generics.span.hi, )); result.push_str(&where_clause_str); @@ -2045,10 +2040,6 @@ fn rewrite_fn_base( force_new_line_for_brace = true; } } - } else { - // FIXME it would be nice to catch comments between the return type - // and the where clause, but we don't have a span for the where - // clause. } } @@ -2079,7 +2070,6 @@ fn rewrite_fn_base( !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi), - span, pos_before_where, ) { if !where_clause_str.contains('\n') { @@ -2105,7 +2095,6 @@ fn rewrite_fn_base( !has_braces, put_args_in_block && ret_str.is_empty(), Some(span.hi), - span, pos_before_where, )); @@ -2507,13 +2496,12 @@ fn rewrite_where_clause_rfc_style( // where clause can be kept on the current line. snuggle: bool, span_end: Option, - span: Span, span_end_before_where: BytePos, ) -> Option { let block_shape = shape.block().with_max_width(context.config); let (span_before, span_after) = - missing_span_before_after_where(context, span.hi, span_end_before_where, where_clause); + missing_span_before_after_where(span_end_before_where, where_clause); let (comment_before, comment_after) = try_opt!(rewrite_comments_before_after_where( context, span_before, @@ -2594,7 +2582,6 @@ fn rewrite_where_clause( suppress_comma: bool, snuggle: bool, span_end: Option, - span: Span, span_end_before_where: BytePos, ) -> Option { if where_clause.predicates.is_empty() { @@ -2610,7 +2597,6 @@ fn rewrite_where_clause( suppress_comma, snuggle, span_end, - span, span_end_before_where, ); } @@ -2695,17 +2681,12 @@ fn rewrite_where_clause( } fn missing_span_before_after_where( - context: &RewriteContext, - item_end: BytePos, before_item_span_end: BytePos, where_clause: &ast::WhereClause, ) -> (Span, Span) { - let snippet = context.snippet(mk_sp(before_item_span_end, item_end)); - let pos_before_where = - before_item_span_end + BytePos(snippet.find_uncommented("where").unwrap() as u32); - let missing_span_before = mk_sp(before_item_span_end, pos_before_where); + let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo); // 5 = `where` - let pos_after_where = pos_before_where + BytePos(5); + let pos_after_where = where_clause.span.lo + BytePos(5); let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo); (missing_span_before, missing_span_after) } @@ -2776,7 +2757,6 @@ fn format_generics( false, trimmed_last_line_width(&result) == 1, Some(span.hi), - span, generics.span.hi, )); result.push_str(&where_clause_str); -- cgit 1.4.1-3-g733a5 From 14f416273b850e1551baed294388ff999748fee9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 1 Aug 2017 22:19:20 +0900 Subject: Add format_constness() and last_line_used_width() --- src/utils.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 47ce5e7fcbe..d0917721898 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -56,6 +56,14 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { } } +#[inline] +pub fn format_constness(constness: ast::Constness) -> &'static str { + match constness { + ast::Constness::Const => "const ", + ast::Constness::NotConst => "", + } +} + #[inline] pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { match defaultness { @@ -107,6 +115,16 @@ pub fn last_line_width(s: &str) -> usize { } } +// The total used width of the last line. +#[inline] +pub fn last_line_used_width(s: &str, offset: usize) -> usize { + if s.contains('\n') { + last_line_width(s) + } else { + offset + s.len() + } +} + #[inline] pub fn trimmed_last_line_width(s: &str) -> usize { match s.rfind('\n') { -- cgit 1.4.1-3-g733a5 From 6ab727e6fffc0e236932e4c55cd20f8f09f687b0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 1 Aug 2017 22:20:04 +0900 Subject: Set where_density default value to Density::Vertical --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7ffe141e6c1..65292d60b26 100644 --- a/src/config.rs +++ b/src/config.rs @@ -539,7 +539,7 @@ create_config! { // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? // 2. Currently options `Tall` and `Vertical` produce the same output. - where_density: Density, Density::CompressedIfEmpty, "Density of a where clause"; + where_density: Density, Density::Vertical, "Density of a where clause"; where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; where_pred_indent: IndentStyle, IndentStyle::Visual, "Indentation style of a where predicate"; -- cgit 1.4.1-3-g733a5 From c67f729205f4472cb688bf947041ccc98568e5d0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 1 Aug 2017 22:23:12 +0900 Subject: Refactoring --- src/items.rs | 60 +++++++++++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d8afbe29b99..5fb0cd8e2cb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -26,8 +26,9 @@ use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, L ListItem, ListTactic, Separator, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::join_bounds; -use utils::{colon_spaces, contains_skip, end_typaram, format_defaultness, format_mutability, - format_unsafety, format_visibility, last_line_width, mk_sp, semicolon_for_expr, +use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, + format_constness, format_defaultness, format_mutability, format_unsafety, + format_visibility, last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, stmt_expr, trim_newlines, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -835,11 +836,7 @@ fn rewrite_trait_ref( result_len: usize, ) -> Option { // 1 = space between generics and trait_ref - let used_space = 1 + polarity_str.len() + if generics_str.contains('\n') { - last_line_width(&generics_str) - } else { - result_len + generics_str.len() - }; + let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len); let shape = Shape::indented(offset + used_space, context.config); if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { if !(retry && trait_ref_str.contains('\n')) { @@ -1229,11 +1226,7 @@ fn format_tuple_struct( if fields.is_empty() { // 3 = `();` - let used_width = if result.contains('\n') { - last_line_width(&result) + 3 - } else { - offset.width() + result.len() + 3 - }; + let used_width = last_line_used_width(&result, offset.width()) + 3; if used_width > context.config.max_width() { result.push('\n'); result.push_str(&offset @@ -1790,24 +1783,13 @@ fn rewrite_fn_base( let where_clause = &generics.where_clause; let mut result = String::with_capacity(1024); - // Vis unsafety abi. + // Vis defaultness constness unsafety abi. result.push_str(&*format_visibility(vis)); - - if let ast::Defaultness::Default = defaultness { - result.push_str("default "); - } - - if let ast::Constness::Const = constness { - result.push_str("const "); - } - - result.push_str(::utils::format_unsafety(unsafety)); - + result.push_str(format_defaultness(defaultness)); + result.push_str(format_constness(constness)); + result.push_str(format_unsafety(unsafety)); if abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi( - abi, - context.config.force_explicit_abi(), - )); + result.push_str(&format_abi(abi, context.config.force_explicit_abi())); } // fn foo @@ -1822,9 +1804,17 @@ fn rewrite_fn_base( // 2 = `()` 2 }; - let shape = try_opt!( - Shape::indented(indent + last_line_width(&result), context.config).sub_width(overhead) - ); + let used_width = last_line_used_width(&result, indent.width()); + let one_line_budget = context + .config + .max_width() + .checked_sub(used_width + overhead) + .unwrap_or(0); + let shape = Shape { + width: one_line_budget, + indent: indent, + offset: used_width, + }; let g_span = mk_sp(span.lo, fd.output.span().lo); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); @@ -2764,7 +2754,7 @@ fn format_generics( let budget = context .config .max_width() - .checked_sub(last_line_width(&result)) + .checked_sub(last_line_used_width(&result, offset.width())) .unwrap_or(0); let where_clause_str = try_opt!(rewrite_where_clause( context, @@ -2786,11 +2776,7 @@ fn format_generics( force_same_line_brace || trimmed_last_line_width(&result) == 1 || brace_style != BraceStyle::AlwaysNextLine }; - let total_used_width = if result.contains('\n') { - last_line_width(&result) - } else { - used_width + result.len() - }; + let total_used_width = last_line_used_width(&result, used_width); let remaining_budget = context .config .max_width() -- cgit 1.4.1-3-g733a5 From ec6c2d6e997209a14bd954861fe1a35326d4251e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 1 Aug 2017 22:25:26 +0900 Subject: Refactor compute_budgets_for_args() --- src/items.rs | 106 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5fb0cd8e2cb..4c3e650c36a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1835,21 +1835,15 @@ fn rewrite_fn_base( let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; // Args. - let (mut one_line_budget, mut multi_line_budget, mut arg_indent) = - try_opt!(compute_budgets_for_args( - context, - &result, - indent, - ret_str_len, - newline_brace, - has_braces, - )); - - if context.config.fn_args_layout() == IndentStyle::Block { - arg_indent = indent.block_indent(context.config); - // 1 = "," - multi_line_budget = context.config.max_width() - (arg_indent.width() + 1); - } + let (one_line_budget, multi_line_budget, mut arg_indent) = try_opt!(compute_budgets_for_args( + context, + &result, + indent, + ret_str_len, + newline_brace, + has_braces, + multi_line_ret_str, + )); debug!( "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", @@ -1885,10 +1879,6 @@ fn rewrite_fn_base( result.push(' ') } - if multi_line_ret_str { - one_line_budget = 0; - } - // A conservative estimation, to goal is to be over all parens in generics let args_start = generics .ty_params @@ -1917,11 +1907,8 @@ fn rewrite_fn_base( generics_str.contains('\n'), )); - let multi_line_arg_str = - arg_str.contains('\n') || arg_str.chars().last().map_or(false, |c| c == ','); - let put_args_in_block = match context.config.fn_args_layout() { - IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'), + IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, _ => false, } && !fd.inputs.is_empty(); @@ -1936,6 +1923,12 @@ fn rewrite_fn_base( result.push(')'); } else { result.push_str(&arg_str); + let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); + // Put the closing brace on the next line if it overflows the max width. + // 1 = `)` + if fd.inputs.len() == 0 && used_width + 1 > context.config.max_width() { + result.push('\n'); + } if context.config.spaces_within_parens() && fd.inputs.len() > 0 { result.push(' ') } @@ -1954,15 +1947,16 @@ fn rewrite_fn_base( } // Return type. - if !ret_str.is_empty() { + if let ast::FunctionRetTy::Ty(..) = fd.output { let ret_should_indent = match context.config.fn_args_layout() { // If our args are block layout then we surely must have space. - IndentStyle::Block if put_args_in_block => false, + IndentStyle::Block if put_args_in_block || fd.inputs.len() == 0 => false, + _ if args_last_line_contains_comment => false, + _ if result.contains('\n') || multi_line_ret_str => true, _ => { - // If we've already gone multi-line, or the return type would push over the max - // width, then put the return type on a new line. With the +1 for the signature - // length an additional space between the closing parenthesis of the argument and - // the arrow '->' is considered. + // If the return type would push over the max width, then put the return type on + // a new line. With the +1 for the signature length an additional space between + // the closing parenthesis of the argument and the arrow '->' is considered. let mut sig_length = result.len() + indent.width() + ret_str_len + 1; // If there is no where clause, take into account the space after the return type @@ -1971,10 +1965,7 @@ fn rewrite_fn_base( sig_length += 2; } - let overlong_sig = sig_length > context.config.max_width(); - - (!args_last_line_contains_comment) && - (result.contains('\n') || multi_line_ret_str || overlong_sig) + sig_length > context.config.max_width() } }; let ret_indent = if ret_should_indent { @@ -2276,6 +2267,7 @@ fn compute_budgets_for_args( ret_str_len: usize, newline_brace: bool, has_braces: bool, + force_vertical_layout: bool, ) -> Option<((usize, usize, Indent))> { debug!( "compute_budgets_for_args {} {:?}, {}, {}", @@ -2285,7 +2277,7 @@ fn compute_budgets_for_args( newline_brace ); // Try keeping everything on the same line. - if !result.contains('\n') { + if !result.contains('\n') && !force_vertical_layout { // 2 = `()`, 3 = `() `, space is before ret_string. let overhead = if ret_str_len == 0 { 2 } else { 3 }; let mut used_space = indent.width() + result.len() + ret_str_len + overhead; @@ -2306,31 +2298,45 @@ fn compute_budgets_for_args( if one_line_budget > 0 { // 4 = "() {".len() - let multi_line_overhead = - indent.width() + result.len() + if newline_brace { 2 } else { 4 }; - let multi_line_budget = - try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); - - return Some(( - one_line_budget, - multi_line_budget, - indent + result.len() + 1, - )); + let (indent, multi_line_budget) = match context.config.fn_args_layout() { + IndentStyle::Block => { + let indent = indent.block_indent(context.config); + let budget = + try_opt!(context.config.max_width().checked_sub(indent.width() + 1)); + (indent, budget) + } + IndentStyle::Visual => { + let indent = indent + result.len() + 1; + let multi_line_overhead = + indent.width() + result.len() + if newline_brace { 2 } else { 4 }; + let budget = + try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); + (indent, budget) + } + }; + + return Some((one_line_budget, multi_line_budget, indent)); } } // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(context.config); - // Account for `)` and possibly ` {`. - let used_space = new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }; + let used_space = match context.config.fn_args_layout() { + // 1 = `,` + IndentStyle::Block => new_indent.width() + 1, + // Account for `)` and possibly ` {`. + IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, + }; let max_space = try_opt!(context.config.max_width().checked_sub(used_space)); Some((0, max_space, new_indent)) } -fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { - match config.fn_brace_style() { - BraceStyle::AlwaysNextLine => true, - BraceStyle::SameLineWhere if !where_clause.predicates.is_empty() => true, +fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: bool) -> bool { + match (config.fn_brace_style(), config.where_density()) { + (BraceStyle::AlwaysNextLine, _) => true, + (_, Density::Compressed) if where_clause.predicates.len() == 1 => false, + (_, Density::CompressedIfEmpty) if where_clause.predicates.len() == 1 && !has_body => false, + (BraceStyle::SameLineWhere, _) if !where_clause.predicates.is_empty() => true, _ => false, } } -- cgit 1.4.1-3-g733a5 From 659d325982c38346a57cd7a999b27b8f478092a0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 1 Aug 2017 22:26:22 +0900 Subject: Implement compressed where clause with Rfc style --- src/items.rs | 57 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 4c3e650c36a..f317081f586 100644 --- a/src/items.rs +++ b/src/items.rs @@ -259,12 +259,12 @@ impl<'a> FmtVisitor<'a> { span: Span, block: &ast::Block, ) -> Option { - let mut newline_brace = newline_for_brace(self.config, &generics.where_clause); let context = self.get_context(); let block_snippet = self.snippet(mk_sp(block.span.lo, block.span.hi)); let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || !context.config.fn_empty_single_line(); + let mut newline_brace = newline_for_brace(self.config, &generics.where_clause, has_body); let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base( &context, @@ -591,6 +591,7 @@ pub fn format_impl( "{", false, last_line_width(&ref_and_type) == 1, + false, where_span_end, item.span, self_ty.span.hi, @@ -983,6 +984,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) "{", false, trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, + false, None, item.span, pos_before_where, @@ -1216,6 +1218,7 @@ fn format_tuple_struct( ";", true, false, + false, None, span, body_hi, @@ -1313,6 +1316,7 @@ pub fn rewrite_type_alias( "=", true, true, + false, Some(span.hi), span, generics.span.hi, @@ -2034,22 +2038,22 @@ fn rewrite_fn_base( } let should_compress_where = match context.config.where_density() { - Density::Compressed => !result.contains('\n') || put_args_in_block, + Density::Compressed => !result.contains('\n'), Density::CompressedIfEmpty => !has_body && !result.contains('\n'), _ => false, - } || (put_args_in_block && ret_str.is_empty()); + }; let pos_before_where = match fd.output { ast::FunctionRetTy::Default(..) => args_span.hi, ast::FunctionRetTy::Ty(ref ty) => ty.span.hi, }; + if where_clause.predicates.len() == 1 && should_compress_where { - let budget = try_opt!( - context - .config - .max_width() - .checked_sub(last_line_width(&result)) - ); + let budget = context + .config + .max_width() + .checked_sub(last_line_used_width(&result, indent.width())) + .unwrap_or(0); if let Some(where_clause_str) = rewrite_where_clause( context, where_clause, @@ -2057,22 +2061,16 @@ fn rewrite_fn_base( Shape::legacy(budget, indent), Density::Compressed, "{", - !has_braces, - put_args_in_block && ret_str.is_empty(), + true, + false, // Force where clause on the next line + true, // Compress where Some(span.hi), span, pos_before_where, ) { - if !where_clause_str.contains('\n') { - if last_line_width(&result) + where_clause_str.len() > context.config.max_width() { - result.push('\n'); - } - - result.push_str(&where_clause_str); - - force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - return Some((result, force_new_line_for_brace)); - } + result.push_str(&where_clause_str); + force_new_line_for_brace |= last_line_contains_single_line_comment(&result); + return Some((result, force_new_line_for_brace)); } } @@ -2085,6 +2083,7 @@ fn rewrite_fn_base( "{", !has_braces, put_args_in_block && ret_str.is_empty(), + false, Some(span.hi), span, pos_before_where, @@ -2502,6 +2501,8 @@ fn rewrite_where_clause_rfc_style( suppress_comma: bool, // where clause can be kept on the current line. snuggle: bool, + // copmressed single where clause + compress_where: bool, span_end: Option, span: Span, span_end_before_where: BytePos, @@ -2568,14 +2569,21 @@ fn rewrite_where_clause_rfc_style( } else { "\n".to_owned() + &clause_shape.indent.to_string(context.config) }; + let clause_sep = if compress_where && comment_before.is_empty() && comment_after.is_empty() && + !preds_str.contains('\n') && 6 + preds_str.len() <= shape.width + { + String::from(" ") + } else { + format!("\n{}", clause_shape.indent.to_string(context.config)) + }; Some(format!( - "{}{}{}where{}{}\n{}{}", + "{}{}{}where{}{}{}{}", starting_newline, comment_before, newline_before_where, newline_after_where, comment_after, - clause_shape.indent.to_string(context.config), + clause_sep, preds_str )) } @@ -2589,6 +2597,7 @@ fn rewrite_where_clause( terminator: &str, suppress_comma: bool, snuggle: bool, + compress_where: bool, span_end: Option, span: Span, span_end_before_where: BytePos, @@ -2605,6 +2614,7 @@ fn rewrite_where_clause( terminator, suppress_comma, snuggle, + compress_where, span_end, span, span_end_before_where, @@ -2771,6 +2781,7 @@ fn format_generics( terminator, false, trimmed_last_line_width(&result) == 1, + false, Some(span.hi), span, generics.span.hi, -- cgit 1.4.1-3-g733a5 From d95549775143113816133145c82c420e7e782879 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 2 Aug 2017 23:26:35 +0900 Subject: Factor out boolean flags for rewrite_where_clause() --- src/items.rs | 92 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index dccae7342e6..172c56b81c7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -581,6 +581,7 @@ pub fn format_impl( .checked_sub(last_line_width(&result)) .unwrap_or(0) }; + let option = WhereClauseOption::snuggled(&ref_and_type); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -588,11 +589,9 @@ pub fn format_impl( Shape::legacy(where_budget, offset.block_only()), context.config.where_density(), "{", - false, - last_line_width(&ref_and_type) == 1, - false, where_span_end, self_ty.span.hi, + option, )); if try_opt!(is_impl_single_line( @@ -973,6 +972,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } else { type_param_bounds[type_param_bounds.len() - 1].span().hi }; + let option = WhereClauseOption::snuggled(&generics_str); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -980,11 +980,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) Shape::legacy(where_budget, offset.block_only()), where_density, "{", - false, - trait_bound_str.is_empty() && last_line_width(&generics_str) == 1, - false, None, pos_before_where, + option, )); // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -1206,6 +1204,7 @@ fn format_tuple_struct( result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); + let option = WhereClauseOption::new(true, false); try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1213,11 +1212,9 @@ fn format_tuple_struct( Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", - true, - false, - false, None, body_hi, + option, )) } None => "".to_owned(), @@ -1303,6 +1300,7 @@ pub fn rewrite_type_alias( .max_width() .checked_sub(last_line_width(&result)) ); + let option = WhereClauseOption::snuggled(&result); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -1310,11 +1308,9 @@ pub fn rewrite_type_alias( Shape::legacy(where_budget, indent), context.config.where_density(), "=", - true, - true, - false, Some(span.hi), generics.span.hi, + option, )); result.push_str(&where_clause_str); result.push_str(" = "); @@ -2052,11 +2048,9 @@ fn rewrite_fn_base( Shape::legacy(budget, indent), Density::Compressed, "{", - true, - false, // Force where clause on the next line - true, // Compress where Some(span.hi), pos_before_where, + WhereClauseOption::compressed(), ) { result.push_str(&where_clause_str); force_new_line_for_brace |= last_line_contains_single_line_comment(&result); @@ -2064,6 +2058,7 @@ fn rewrite_fn_base( } } + let option = WhereClauseOption::new(!has_braces, put_args_in_block && ret_str.is_empty()); let where_clause_str = try_opt!(rewrite_where_clause( context, where_clause, @@ -2071,11 +2066,9 @@ fn rewrite_fn_base( Shape::indented(indent, context.config), Density::Tall, "{", - !has_braces, - put_args_in_block && ret_str.is_empty(), - false, Some(span.hi), pos_before_where, + option, )); result.push_str(&where_clause_str); @@ -2084,6 +2077,38 @@ fn rewrite_fn_base( return Some((result, force_new_line_for_brace)); } +struct WhereClauseOption { + suppress_comma: bool, // Force no trailing comma + snuggle: bool, // Do not insert newline before `where` + compress_where: bool, // Try single line where clause instead of vertical layout +} + +impl WhereClauseOption { + pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { + WhereClauseOption { + suppress_comma: suppress_comma, + snuggle: snuggle, + compress_where: false, + } + } + + pub fn compressed() -> WhereClauseOption { + WhereClauseOption { + suppress_comma: true, + snuggle: false, + compress_where: true, + } + } + + pub fn snuggled(current: &str) -> WhereClauseOption { + WhereClauseOption { + suppress_comma: false, + snuggle: trimmed_last_line_width(current) == 1, + compress_where: false, + } + } +} + fn last_line_contains_single_line_comment(s: &str) -> bool { s.lines().last().map_or(false, |l| l.contains("//")) } @@ -2487,13 +2512,9 @@ fn rewrite_where_clause_rfc_style( where_clause: &ast::WhereClause, shape: Shape, terminator: &str, - suppress_comma: bool, - // where clause can be kept on the current line. - snuggle: bool, - // copmressed single where clause - compress_where: bool, span_end: Option, span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, ) -> Option { let block_shape = shape.block().with_max_width(context.config); @@ -2506,7 +2527,7 @@ fn rewrite_where_clause_rfc_style( shape, )); - let starting_newline = if snuggle && comment_before.is_empty() { + let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { " ".to_owned() } else { "\n".to_owned() + &block_shape.indent.to_string(context.config) @@ -2530,7 +2551,7 @@ fn rewrite_where_clause_rfc_style( span_start, span_end, ); - let comma_tactic = if suppress_comma { + let comma_tactic = if where_clause_option.suppress_comma { SeparatorTactic::Never } else { context.config.trailing_comma() @@ -2557,8 +2578,10 @@ fn rewrite_where_clause_rfc_style( } else { "\n".to_owned() + &clause_shape.indent.to_string(context.config) }; - let clause_sep = if compress_where && comment_before.is_empty() && comment_after.is_empty() && - !preds_str.contains('\n') && 6 + preds_str.len() <= shape.width + // 6 = `where ` + let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() && + comment_after.is_empty() && !preds_str.contains('\n') && + 6 + preds_str.len() <= shape.width { String::from(" ") } else { @@ -2583,11 +2606,9 @@ fn rewrite_where_clause( shape: Shape, density: Density, terminator: &str, - suppress_comma: bool, - snuggle: bool, - compress_where: bool, span_end: Option, span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, ) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); @@ -2599,11 +2620,9 @@ fn rewrite_where_clause( where_clause, shape, terminator, - suppress_comma, - snuggle, - compress_where, span_end, span_end_before_where, + where_clause_option, ); } @@ -2646,7 +2665,7 @@ fn rewrite_where_clause( let mut comma_tactic = context.config.trailing_comma(); // Kind of a hack because we don't usually have trailing commas in where clauses. - if comma_tactic == SeparatorTactic::Vertical || suppress_comma { + if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma { comma_tactic = SeparatorTactic::Never; } @@ -2753,6 +2772,7 @@ fn format_generics( .max_width() .checked_sub(last_line_used_width(&result, offset.width())) .unwrap_or(0); + let option = WhereClauseOption::snuggled(&result); let where_clause_str = try_opt!(rewrite_where_clause( context, &generics.where_clause, @@ -2760,11 +2780,9 @@ fn format_generics( Shape::legacy(budget, offset.block_only()), Density::Tall, terminator, - false, - trimmed_last_line_width(&result) == 1, - false, Some(span.hi), generics.span.hi, + option, )); result.push_str(&where_clause_str); force_same_line_brace || brace_style == BraceStyle::PreferSameLine || -- cgit 1.4.1-3-g733a5 From c0c27761b42ad41db707d00e1988ad060341498f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 2 Aug 2017 23:27:19 +0900 Subject: Simplify comments separator --- src/items.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 172c56b81c7..7b2c016aed0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2568,16 +2568,14 @@ fn rewrite_where_clause_rfc_style( }; let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); - let newline_before_where = if comment_before.is_empty() || comment_before.ends_with('\n') { + let comment_separator = |comment: &str, shape: Shape| if comment.is_empty() { String::new() } else { - "\n".to_owned() + &shape.indent.to_string(context.config) - }; - let newline_after_where = if comment_after.is_empty() { - String::new() - } else { - "\n".to_owned() + &clause_shape.indent.to_string(context.config) + format!("\n{}", shape.indent.to_string(context.config)) }; + let newline_before_where = comment_separator(&comment_before, shape); + let newline_after_where = comment_separator(&comment_after, clause_shape); + // 6 = `where ` let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() && comment_after.is_empty() && !preds_str.contains('\n') && -- cgit 1.4.1-3-g733a5 From a5a7cc764342eb67702a1fbb2a8a2d573f66fe2b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 2 Aug 2017 23:27:33 +0900 Subject: Insert newline between type alias with where clause --- src/items.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7b2c016aed0..dc40d1b5b8a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1313,7 +1313,11 @@ pub fn rewrite_type_alias( option, )); result.push_str(&where_clause_str); - result.push_str(" = "); + if where_clause_str.is_empty() { + result.push_str(" = "); + } else { + result.push_str(&format!("\n{}= ", indent.to_string(context.config))); + } let line_width = last_line_width(&result); // This checked_sub may fail as the extra space after '=' is not taken into account -- cgit 1.4.1-3-g733a5 From 60fb11e5ddc3d50efd2eda16ed8f85d46978bf8b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 5 Aug 2017 15:21:46 +0900 Subject: Do not take inner attributes into account for span --- src/lib.rs | 53 +++++++++++++++++++++++++++++------------------------ src/utils.rs | 19 +++++++++++++++++++ src/visitor.rs | 23 +++++------------------ 3 files changed, 53 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 5647e6df5e2..e1017fab959 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ use checkstyle::{output_footer, output_header}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; -use utils::mk_sp; +use utils::{mk_sp, outer_attributes}; use visitor::FmtVisitor; pub use self::summary::Summary; @@ -81,13 +81,33 @@ pub trait Spanned { fn span(&self) -> Span; } +macro_rules! span_with_attrs_lo_hi { + ($this:ident, $lo:expr, $hi:expr) => { + { + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo, $hi) + } + } + } +} +macro_rules! span_with_attrs { + ($this:ident) => { + span_with_attrs_lo_hi!($this, $this.span.lo, $this.span.hi) + } +} + impl Spanned for ast::Expr { fn span(&self) -> Span { - if self.attrs.is_empty() { - self.span - } else { - mk_sp(self.attrs[0].span.lo, self.span.hi) - } + span_with_attrs!(self) + } +} + +impl Spanned for ast::Item { + fn span(&self) -> Span { + span_with_attrs!(self) } } @@ -117,12 +137,7 @@ impl Spanned for ast::Ty { impl Spanned for ast::Arm { fn span(&self) -> Span { - let hi = self.body.span.hi; - if self.attrs.is_empty() { - mk_sp(self.pats[0].span.lo, hi) - } else { - mk_sp(self.attrs[0].span.lo, hi) - } + span_with_attrs_lo_hi!(self, self.pats[0].span.lo, self.body.span.hi) } } @@ -138,23 +153,13 @@ impl Spanned for ast::Arg { impl Spanned for ast::StructField { fn span(&self) -> Span { - if self.attrs.is_empty() { - mk_sp(self.span.lo, self.ty.span.hi) - } else { - // Include attributes and doc comments, if present - mk_sp(self.attrs[0].span.lo, self.ty.span.hi) - } + span_with_attrs_lo_hi!(self, self.span.lo, self.ty.span.hi) } } impl Spanned for ast::Field { fn span(&self) -> Span { - let lo = if self.attrs.is_empty() { - self.span.lo - } else { - self.attrs[0].span.lo - }; - mk_sp(lo, self.span.hi) + span_with_attrs!(self) } } diff --git a/src/utils.rs b/src/utils.rs index d0917721898..c0861b8da20 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -97,6 +97,25 @@ pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String { } } +#[inline] +pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { + attrs + .iter() + .filter(|a| a.style == style) + .cloned() + .collect::>() +} + +#[inline] +pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Inner) +} + +#[inline] +pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Outer) +} + // The width of the first line in s. #[inline] pub fn first_line_width(s: &str) -> usize { diff --git a/src/visitor.rs b/src/visitor.rs index bc3126615d3..ef0ff1d52db 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -15,7 +15,7 @@ use syntax::{ast, ptr, visit}; use syntax::codemap::{self, BytePos, CodeMap, Span}; use syntax::parse::ParseSess; -use {Indent, Shape}; +use {Indent, Shape, Spanned}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, FindUncommented}; use comment::rewrite_comment; @@ -36,19 +36,6 @@ fn is_use_item(item: &ast::Item) -> bool { } } -fn item_bound(item: &ast::Item) -> Span { - item.attrs.iter().map(|attr| attr.span).fold( - item.span, - |bound, span| { - Span { - lo: cmp::min(bound.lo, span.lo), - hi: cmp::max(bound.hi, span.hi), - ctxt: span.ctxt, - } - }, - ) -} - pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, @@ -93,7 +80,7 @@ impl<'a> FmtVisitor<'a> { let span = if expr.attrs.is_empty() { stmt.span } else { - mk_sp(expr.attrs[0].span.lo, stmt.span.hi) + mk_sp(expr.span().lo, stmt.span.hi) }; self.push_rewrite(span, rewrite) } @@ -105,7 +92,7 @@ impl<'a> FmtVisitor<'a> { let span = if expr.attrs.is_empty() { stmt.span } else { - mk_sp(expr.attrs[0].span.lo, stmt.span.hi) + mk_sp(expr.span().lo, stmt.span.hi) }; self.push_rewrite(span, rewrite) } @@ -648,12 +635,12 @@ impl<'a> FmtVisitor<'a> { // next item for output. if self.config.reorder_imports() && is_use_item(&*items_left[0]) { let reorder_imports_in_group = self.config.reorder_imports_in_group(); - let mut last = self.codemap.lookup_line_range(item_bound(&items_left[0])); + let mut last = self.codemap.lookup_line_range(items_left[0].span()); let use_item_length = items_left .iter() .take_while(|ppi| { is_use_item(&***ppi) && (!reorder_imports_in_group || { - let current = self.codemap.lookup_line_range(item_bound(&ppi)); + let current = self.codemap.lookup_line_range(ppi.span()); let in_same_group = current.lo < last.hi + 2; last = current; in_same_group -- cgit 1.4.1-3-g733a5 From d4bf413956c5e70dfe42cbca062fcb349ecdff5d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 5 Aug 2017 15:23:23 +0900 Subject: Do not add missing snippet between arms if it's just spaces --- src/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a847733e7bd..d276bcc2951 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1615,7 +1615,9 @@ fn rewrite_match_arms( arm_shape, &arm_indent_str, )); - result.push_str(&comment); + if !comment.chars().all(|c| c == ' ') { + result.push_str(&comment); + } result.push('\n'); result.push_str(&arm_indent_str); -- cgit 1.4.1-3-g733a5 From 6b85c4a6e76bc9dacf51ca40f237bb31f603ddf9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 5 Aug 2017 15:24:12 +0900 Subject: Format inner attributes in match expr --- src/expr.rs | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d276bcc2951..f56f3f8779e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,8 +31,9 @@ use rewrite::{Rewrite, RewriteContext}; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{binary_search, colon_spaces, contains_skip, extra_offset, first_line_width, - last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, paren_overhead, - semicolon_for_stmt, stmt_expr, trimmed_last_line_width, wrap_str}; + inner_attributes, last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, + outer_attributes, paren_overhead, semicolon_for_stmt, stmt_expr, + trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -54,15 +55,13 @@ fn combine_attr_and_expr( expr: &ast::Expr, expr_str: &str, ) -> Option { - let attr_str = try_opt!((&*expr.attrs).rewrite(context, shape)); + let attrs = outer_attributes(&expr.attrs); + let attr_str = try_opt!(attrs.rewrite(context, shape)); let separator = if attr_str.is_empty() { String::new() } else { // Try to recover comments between the attributes and the expression if available. - let missing_snippet = context.snippet(mk_sp( - expr.attrs[expr.attrs.len() - 1].span.hi, - expr.span.lo, - )); + let missing_snippet = context.snippet(mk_sp(attrs[attrs.len() - 1].span.hi, expr.span.lo)); let comment_opening_pos = missing_snippet.chars().position(|c| c == '/'); let prefer_same_line = if let Some(pos) = comment_opening_pos { !missing_snippet[..pos].contains('\n') @@ -198,7 +197,7 @@ pub fn format_expr( } } ast::ExprKind::Match(ref cond, ref arms) => { - rewrite_match(context, cond, arms, shape, expr.span) + rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs) } ast::ExprKind::Path(ref qself, ref path) => { rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) @@ -1531,6 +1530,7 @@ fn rewrite_match( arms: &[ast::Arm], shape: Shape, span: Span, + attrs: &[ast::Attribute], ) -> Option { if arms.is_empty() { return None; @@ -1558,11 +1558,42 @@ fn rewrite_match( _ => " ", }; + let nested_indent_str = shape + .indent + .block_indent(context.config) + .to_string(context.config); + // Inner attributes. + let inner_attrs = &inner_attributes(attrs); + let inner_attrs_str = if inner_attrs.is_empty() { + String::new() + } else { + try_opt!( + inner_attrs + .rewrite(context, shape) + .map(|s| format!("\n{}{}", nested_indent_str, s)) + ) + }; + + let open_brace_pos = if inner_attrs.is_empty() { + context + .codemap + .span_after(mk_sp(cond.span.hi, arms[0].span().lo), "{") + } else { + inner_attrs[inner_attrs.len() - 1].span().hi + }; + Some(format!( - "match {}{}{{{}\n{}}}", + "match {}{}{{{}{}\n{}}}", cond_str, block_sep, - try_opt!(rewrite_match_arms(context, arms, shape, span, cond.span.hi)), + inner_attrs_str, + try_opt!(rewrite_match_arms( + context, + arms, + shape, + span, + open_brace_pos, + )), shape.indent.to_string(context.config), )) } @@ -1586,7 +1617,7 @@ fn rewrite_match_arms( arms: &[ast::Arm], shape: Shape, span: Span, - cond_end_pos: BytePos, + open_brace_pos: BytePos, ) -> Option { let mut result = String::new(); @@ -1597,10 +1628,6 @@ fn rewrite_match_arms( }.with_max_width(context.config); let arm_indent_str = arm_shape.indent.to_string(context.config); - let open_brace_pos = context - .codemap - .span_after(mk_sp(cond_end_pos, arms[0].span().lo), "{"); - let arm_num = arms.len(); for (i, arm) in arms.iter().enumerate() { // Make sure we get the stuff between arms. -- cgit 1.4.1-3-g733a5 From fa242a5cd607f19531c73e4526f57a4a44b7b07f Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Sun, 6 Aug 2017 19:42:07 -0400 Subject: Fix #1858 - "Don't erase a use with attributes attached" This prevents code like #[cfg(unix)] pub use self::unix::{}; from becoming #[cfg(unix)] which would cause the attribute to be attached to the next item. --- src/imports.rs | 19 +++++++++++++++++-- src/visitor.rs | 2 +- tests/source/imports.rs | 4 ++++ tests/target/imports.rs | 4 ++++ 4 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index e0049698bfb..6b1a2f541ea 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -250,13 +250,28 @@ impl<'a> FmtVisitor<'a> { self.last_pos = pos_after_last_use_item; } - pub fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span: Span) { + pub fn format_import( + &mut self, + vis: &ast::Visibility, + vp: &ast::ViewPath, + span: Span, + attrs: &[ast::Attribute], + ) { let vis = utils::format_visibility(vis); // 4 = `use `, 1 = `;` let rw = Shape::indented(self.block_indent, self.config) .offset_left(vis.len() + 4) .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| vp.rewrite(&self.get_context(), shape)); + .and_then(|shape| match vp.node { + // If we have an empty path with attributes attached, we want to skip erasing it + ast::ViewPath_::ViewPathList(ref path, ref path_list) + if path_list.is_empty() && !attrs.is_empty() => + { + rewrite_path(&self.get_context(), PathContext::Import, None, path, shape) + .map(|path_str| format!("{}::{{}}", path_str)) + } + _ => vp.rewrite(&self.get_context(), shape), + }); match rw { Some(ref s) if s.is_empty() => { // Format up to last newline diff --git a/src/visitor.rs b/src/visitor.rs index ef0ff1d52db..c9fa7065511 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -293,7 +293,7 @@ impl<'a> FmtVisitor<'a> { match item.node { ast::ItemKind::Use(ref vp) => { - self.format_import(&item.vis, vp, item.span); + self.format_import(&item.vis, vp, item.span, &item.attrs); } ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo); diff --git a/tests/source/imports.rs b/tests/source/imports.rs index faa1334d466..debd851d7b7 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -72,3 +72,7 @@ use ::*; // spaces used to cause glob imports to disappear (#1356) use super:: * ; use foo::issue_1356:: * ; + +// We shouldn't remove imports which have attributes attached (#1858) +#[cfg(unix)] +use self::unix::{}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index ed176e43002..5a2494c50cf 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -67,3 +67,7 @@ use ::*; // spaces used to cause glob imports to disappear (#1356) use super::*; use foo::issue_1356::*; + +// We shouldn't remove imports which have attributes attached (#1858) +#[cfg(unix)] +use self::unix::{}; -- cgit 1.4.1-3-g733a5 From 94df4f8cca133c638ddd7f51eec7b349b0a12c5a Mon Sep 17 00:00:00 2001 From: Caleb Jones Date: Sun, 6 Aug 2017 23:04:33 -0400 Subject: Move the empty path_list handling into rewrite_use_list() --- src/imports.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 6b1a2f541ea..a65d8bb066a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -157,12 +157,8 @@ fn rewrite_view_path_prefix( } impl Rewrite for ast::ViewPath { - // Returns an empty string when the ViewPath is empty (like foo::bar::{}) fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - ast::ViewPath_::ViewPathList(_, ref path_list) if path_list.is_empty() => { - Some(String::new()) - } ast::ViewPath_::ViewPathList(ref path, ref path_list) => { rewrite_use_list(shape, path, path_list, self.span, context) } @@ -263,12 +259,11 @@ impl<'a> FmtVisitor<'a> { .offset_left(vis.len() + 4) .and_then(|shape| shape.sub_width(1)) .and_then(|shape| match vp.node { - // If we have an empty path with attributes attached, we want to skip erasing it - ast::ViewPath_::ViewPathList(ref path, ref path_list) - if path_list.is_empty() && !attrs.is_empty() => + // If we have an empty path list with no attributes, we erase it + ast::ViewPath_::ViewPathList(_, ref path_list) + if path_list.is_empty() && attrs.is_empty() => { - rewrite_path(&self.get_context(), PathContext::Import, None, path, shape) - .map(|path_str| format!("{}::{{}}", path_str)) + Some("".into()) } _ => vp.rewrite(&self.get_context(), shape), }); @@ -400,7 +395,7 @@ impl<'a> Ord for ImportItem<'a> { } // Pretty prints a multi-item import. -// Assumes that path_list.len() > 0. +// If the path list is empty, it leaves the braces empty. fn rewrite_use_list( shape: Shape, path: &ast::Path, @@ -418,7 +413,10 @@ fn rewrite_use_list( )); match path_list.len() { - 0 => unreachable!(), + 0 => { + return rewrite_path(context, PathContext::Import, None, path, shape) + .map(|path_str| format!("{}::{{}}", path_str)); + } 1 => return Some(rewrite_single_use_list(path_str, &path_list[0])), _ => (), } -- cgit 1.4.1-3-g733a5 From 021f922b9c48d455f80fe34ab38cff7fe25cbd63 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 8 Aug 2017 18:24:06 +0900 Subject: Keep the pre-comment on the same line with item if it fits max width --- src/lists.rs | 64 +++++++++++++++++++++++++++++++++++++++++----- tests/source/expr-block.rs | 10 ++++++++ tests/target/expr-block.rs | 18 ++++++++++--- 3 files changed, 81 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 048f11a1856..731d310a5d4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -76,9 +76,20 @@ impl AsRef for ListItem { } } +#[derive(PartialEq, Eq)] +pub enum ListItemCommentStyle { + // Try to keep the comment on the same line with the item. + SameLine, + // Put the comment on the previous or the next line of the item. + DifferentLine, + // No comment available. + None, +} + pub struct ListItem { // None for comments mean that they are not present. pub pre_comment: Option, + pub pre_comment_style: ListItemCommentStyle, // Item should include attributes and doc comments. None indicates a failed // rewrite. pub item: Option, @@ -111,6 +122,7 @@ impl ListItem { pub fn from_str>(s: S) -> ListItem { ListItem { pre_comment: None, + pre_comment_style: ListItemCommentStyle::None, item: Some(s.into()), post_comment: None, new_lines: false, @@ -279,8 +291,23 @@ where result.push_str(&comment); if tactic == DefinitiveListTactic::Vertical { - result.push('\n'); - result.push_str(indent_str); + // We cannot keep pre-comments on the same line if the comment if normalized. + let keep_comment = if formatting.config.normalize_comments() { + false + } else if item.pre_comment_style == ListItemCommentStyle::DifferentLine { + false + } else { + // We will try to keep the comment on the same line with the item here. + // 1 = ` ` + let total_width = total_item_width(item) + item_sep_len + 1; + total_width <= formatting.shape.width + }; + if keep_comment { + result.push(' '); + } else { + result.push('\n'); + result.push_str(indent_str); + } } else { result.push(' '); } @@ -448,12 +475,34 @@ where .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); - let has_pre_comment = - trimmed_pre_snippet.contains("//") || trimmed_pre_snippet.contains("/*"); - let pre_comment = if has_pre_comment { - Some(trimmed_pre_snippet.to_owned()) + let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); + let has_block_comment = trimmed_pre_snippet.starts_with("/*"); + let (pre_comment, pre_comment_style) = if has_single_line_comment { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else if has_block_comment { + let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); + if pre_snippet + .chars() + .rev() + .take(comment_end + 1) + .find(|c| *c == '\n') + .is_some() + { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::SameLine, + ) + } } else { - None + (None, ListItemCommentStyle::None) }; // Post-comment @@ -542,6 +591,7 @@ where ListItem { pre_comment: pre_comment, + pre_comment_style: pre_comment_style, item: (self.get_item_string)(&item), post_comment: post_comment, new_lines: new_lines, diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 27f7ff67da9..3b4e6356ff9 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -272,3 +272,13 @@ fn combine_block() { ), } } + +fn issue_1862() { + foo( + /* bar = */ None , + something_something, + /* baz = */ None , + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ None , + /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , + ) +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 5b68b374899..68c5421c3ca 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -81,8 +81,7 @@ fn arrays() { ]; let y = [ - /* comment */ - 1, + /* comment */ 1, 2, /* post comment */ 3, ]; @@ -92,8 +91,7 @@ fn arrays() { test123: value_one_two_three_four, turbo: coolio(), }, - /* comment */ - 1, + /* comment */ 1, ]; let a = WeightedChoice::new(&mut [ @@ -323,3 +321,15 @@ fn combine_block() { ), } } + +fn issue_1862() { + foo( + /* bar = */ None, + something_something, + /* baz = */ None, + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ + None, + /* com */ + this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, + ) +} -- cgit 1.4.1-3-g733a5 From 7bf9aa25be0dc15be1640e72780871adf61a3f4d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 9 Aug 2017 00:16:18 +0900 Subject: Add reorder_extern_crates and reorder_extern_crates_in_group config options --- src/config.rs | 2 ++ src/imports.rs | 9 ++++-- src/visitor.rs | 86 ++++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 65292d60b26..7b2fb9f629d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -558,6 +558,8 @@ create_config! { exceeds `chain_one_line_max`"; imports_indent: IndentStyle, IndentStyle::Visual, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, "Item layout inside a import block"; + reorder_extern_crates: bool, true, "Reorder extern crate statements alphabetically"; + reorder_extern_crates_in_group: bool, true, "Reorder extern crate statements in group"; reorder_imports: bool, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, false, "Reorder import statements in group"; reorder_imported_names: bool, true, diff --git a/src/imports.rs b/src/imports.rs index a65d8bb066a..b73c85ddb56 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -113,11 +113,14 @@ fn compare_view_paths(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering { } } -fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { +fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> Option { match (&a.node, &b.node) { (&ast::ItemKind::Use(ref a_vp), &ast::ItemKind::Use(ref b_vp)) => { Some(compare_view_paths(&a_vp.node, &b_vp.node)) } + (&ast::ItemKind::ExternCrate(..), &ast::ItemKind::ExternCrate(..)) => { + Some(context.snippet(a.span).cmp(&context.snippet(b.span))) + } _ => None, } } @@ -214,7 +217,9 @@ impl<'a> FmtVisitor<'a> { .collect::>(); let pos_after_last_use_item = last_pos_of_prev_use_item; // Order the imports by view-path & other import path properties - ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap()); + ordered_use_items.sort_by(|a, b| { + compare_use_items(&self.get_context(), a.0, b.0).unwrap() + }); // First, output the span before the first import let prev_span_str = self.snippet(utils::mk_sp(self.last_pos, pos_before_first_use_item)); // Look for purely trailing space at the start of the prefix snippet before a linefeed, or diff --git a/src/visitor.rs b/src/visitor.rs index c9fa7065511..3427867274a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -36,6 +36,13 @@ fn is_use_item(item: &ast::Item) -> bool { } } +fn is_extern_crate(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::ExternCrate(..) => true, + _ => false, + } +} + pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, @@ -627,6 +634,44 @@ impl<'a> FmtVisitor<'a> { false } + fn reorder_items( + &mut self, + items_left: &[ptr::P], + is_item: &F, + in_group: bool, + ) -> usize + where + F: Fn(&ast::Item) -> bool, + { + let mut last = self.codemap.lookup_line_range(items_left[0].span()); + let item_length = items_left + .iter() + .take_while(|ppi| { + is_item(&***ppi) && (!in_group || { + let current = self.codemap.lookup_line_range(ppi.span()); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) + }) + .count(); + let items = &items_left[..item_length]; + + let at_least_one_in_file_lines = items + .iter() + .any(|item| !out_of_file_lines_range!(self, item.span)); + + if at_least_one_in_file_lines { + self.format_imports(items); + } else { + for item in items { + self.push_rewrite(item.span, None); + } + } + + item_length + } + fn walk_mod_items(&mut self, m: &ast::Mod) { let mut items_left: &[ptr::P] = &m.items; while !items_left.is_empty() { @@ -634,33 +679,20 @@ impl<'a> FmtVisitor<'a> { // to be potentially reordered within `format_imports`. Otherwise, just format the // next item for output. if self.config.reorder_imports() && is_use_item(&*items_left[0]) { - let reorder_imports_in_group = self.config.reorder_imports_in_group(); - let mut last = self.codemap.lookup_line_range(items_left[0].span()); - let use_item_length = items_left - .iter() - .take_while(|ppi| { - is_use_item(&***ppi) && (!reorder_imports_in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) - }) - .count(); - let (use_items, rest) = items_left.split_at(use_item_length); - - let at_least_one_in_file_lines = use_items - .iter() - .any(|item| !out_of_file_lines_range!(self, item.span)); - - if at_least_one_in_file_lines { - self.format_imports(use_items); - } else { - for item in use_items { - self.push_rewrite(item.span, None); - } - } - + let used_items_len = self.reorder_items( + &items_left, + &is_use_item, + self.config.reorder_imports_in_group(), + ); + let (_, rest) = items_left.split_at(used_items_len); + items_left = rest; + } else if self.config.reorder_extern_crates() && is_extern_crate(&*items_left[0]) { + let used_items_len = self.reorder_items( + &items_left, + &is_extern_crate, + self.config.reorder_extern_crates_in_group(), + ); + let (_, rest) = items_left.split_at(used_items_len); items_left = rest; } else { // `unwrap()` is safe here because we know `items_left` -- cgit 1.4.1-3-g733a5 From c28df858c79521dde6571a6fe153ba8af92f79d4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 9 Aug 2017 00:16:35 +0900 Subject: Format source codes and update tests --- src/bin/rustfmt.rs | 4 ++-- src/lib.rs | 14 +++++--------- tests/source/extern.rs | 7 +++++++ tests/system.rs | 2 +- tests/target/attrib-extern-crate.rs | 4 ++-- tests/target/extern.rs | 9 ++++++++- 6 files changed, 25 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2de572f616e..d1f7a83187b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -11,11 +11,11 @@ #![cfg(not(test))] +extern crate env_logger; +extern crate getopts; extern crate log; extern crate rustfmt_nightly as rustfmt; extern crate toml; -extern crate env_logger; -extern crate getopts; use std::{env, error}; use std::fs::File; diff --git a/src/lib.rs b/src/lib.rs index e1017fab959..eaac371aa5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,23 +10,19 @@ #![feature(rustc_private)] +extern crate diff; #[macro_use] extern crate log; - +extern crate regex; +extern crate rustc_errors as errors; extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; - -extern crate syntax; -extern crate rustc_errors as errors; - extern crate strings; - -extern crate unicode_segmentation; -extern crate regex; -extern crate diff; +extern crate syntax; extern crate term; +extern crate unicode_segmentation; use std::collections::HashMap; use std::fmt; diff --git a/tests/source/extern.rs b/tests/source/extern.rs index 7f14d27b779..5546b217226 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -3,6 +3,13 @@ extern crate foo ; extern crate foo as bar ; +extern crate futures; +extern crate dotenv; +extern crate chrono; + +extern crate foo; +extern crate bar; + extern "C" { fn c_func(x: *mut *mut libc::c_void); diff --git a/tests/system.rs b/tests/system.rs index d915e11d534..6e148147a48 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate rustfmt_nightly as rustfmt; extern crate diff; extern crate regex; +extern crate rustfmt_nightly as rustfmt; extern crate term; use std::collections::HashMap; diff --git a/tests/target/attrib-extern-crate.rs b/tests/target/attrib-extern-crate.rs index fe06195b154..ed64a0aeb07 100644 --- a/tests/target/attrib-extern-crate.rs +++ b/tests/target/attrib-extern-crate.rs @@ -1,17 +1,17 @@ // Attributes on extern crate. -extern crate Foo; #[Attr1] extern crate Bar; #[Attr2] #[Attr2] extern crate Baz; +extern crate Foo; fn foo() { - extern crate Foo; #[Attr1] extern crate Bar; #[Attr2] #[Attr2] extern crate Baz; + extern crate Foo; } diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 1431c384db9..c0601a4d0e1 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,7 +1,14 @@ // rustfmt-normalize_comments: true -extern crate foo; extern crate foo as bar; +extern crate foo; + +extern crate chrono; +extern crate dotenv; +extern crate futures; + +extern crate bar; +extern crate foo; extern "C" { fn c_func(x: *mut *mut libc::c_void); -- cgit 1.4.1-3-g733a5 From 7268a50e36033b4f3026a142b69b1fca82130e88 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 6 Aug 2017 22:56:51 +0900 Subject: Handle prefix and suffix try operators differently --- src/chains.rs | 108 +++++++++++++++++++++++--------------------------- tests/target/match.rs | 4 +- 2 files changed, 50 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5c98308e40c..2e2ce293fdb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -98,13 +98,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if chain_only_try(&subexpr_list) { return rewrite_try(&parent, subexpr_list.len(), context, shape); } - let trailing_try_num = subexpr_list - .iter() - .take_while(|e| match e.node { - ast::ExprKind::Try(..) => true, - _ => false, - }) - .count(); + let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); + let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent, "\n") { @@ -115,23 +110,19 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { shape }; - let parent_rewrite = try_opt!(parent.rewrite(context, parent_shape)); + let parent_rewrite = try_opt!( + parent + .rewrite(context, parent_shape) + .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num)) + ); let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let first_subexpr_is_try = subexpr_list.last().map_or(false, is_try); let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - let nested_shape = if first_subexpr_is_try { - parent_shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - } else { - chain_indent(context, shape.add_offset(parent_rewrite.len())) - }; ( - nested_shape, + chain_indent(context, shape.add_offset(parent_rewrite.len())), context.config.chain_indent() == IndentStyle::Visual || is_small_parent, ) } else if is_block_expr(context, &parent, &parent_rewrite) { @@ -171,9 +162,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - other_child_shape ); - let child_shape_iter = Some(first_child_shape).into_iter().chain( - ::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1), - ); + let child_shape_iter = Some(first_child_shape) + .into_iter() + .chain(iter::repeat(other_child_shape)); + let subexpr_num = subexpr_list.len(); + let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; let iter = subexpr_list.iter().rev().zip(child_shape_iter); let mut rewrites = try_opt!( iter.map(|(e, shape)| { @@ -182,8 +175,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ); // Total of all items excluding the last. - let last_non_try_index = rewrites.len() - (1 + trailing_try_num); - let almost_total = rewrites[..last_non_try_index] + let rewrites_len = rewrites.len(); + let almost_total = rewrites[0..(rewrites_len - 1)] .iter() .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); let one_line_len = @@ -198,7 +191,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { false } - } else if context.config.take_source_hints() && subexpr_list.len() > 1 { + } else if context.config.take_source_hints() && rewrites.len() > 1 { // Look at the source code. Unless all chain elements start on the same // line, we won't consider putting them on a single line either. let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); @@ -213,7 +206,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let mut fits_single_line = !veto_single_line && almost_total <= shape.width; if fits_single_line { let len = rewrites.len(); - let (init, last) = rewrites.split_at_mut(len - (1 + trailing_try_num)); + let (init, last) = rewrites.split_at_mut(len - 1); fits_single_line = init.iter().all(|s| !s.contains('\n')); if fits_single_line { @@ -242,7 +235,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Try overflowing the last element if we are using block indent and it goes multi line // or it fits in a single line but goes over the max width. if !fits_single_line && context.use_block_indent() { - let (init, last) = rewrites.split_at_mut(last_non_try_index); + let last_expr_index = rewrites.len() - 1; + let (init, last) = rewrites.split_at_mut(last_expr_index); let almost_single_line = init.iter().all(|s| !s.contains('\n')); if almost_single_line && last[0].contains('\n') { let overflow_shape = Shape { @@ -251,7 +245,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; fits_single_line = rewrite_last_child_with_overflow( context, - &subexpr_list[trailing_try_num], + &subexpr_list[0], overflow_shape, total_span, almost_total, @@ -281,42 +275,36 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - extend, ); - if is_small_parent && rewrites.len() > 1 { + let result = if is_small_parent && rewrites.len() > 1 { let second_connector = choose_first_connector( context, &rewrites[0], &rewrites[1], &connector, - &subexpr_list[0..subexpr_list.len() - 1], + &subexpr_list[..subexpr_num - 1], false, ); - wrap_str( - format!( - "{}{}{}{}{}", - parent_rewrite, - first_connector, - rewrites[0], - second_connector, - join_rewrites( - &rewrites[1..], - &subexpr_list[0..subexpr_list.len() - 1], - &connector, - ) - ), - context.config.max_width(), - shape, + format!( + "{}{}{}{}{}", + parent_rewrite, + first_connector, + rewrites[0], + second_connector, + join_rewrites(&rewrites[1..], &subexpr_list[..subexpr_num - 1], &connector) ) } else { - wrap_str( - format!( - "{}{}{}", - parent_rewrite, - first_connector, - join_rewrites(&rewrites, &subexpr_list, &connector) - ), - context.config.max_width(), - shape, + format!( + "{}{}{}", + parent_rewrite, + first_connector, + join_rewrites(&rewrites, &subexpr_list, &connector) ) + }; + let result = format!("{}{}", result, repeat_try(suffix_try_num)); + if context.config.chain_indent() == IndentStyle::Block { + Some(result) + } else { + wrap_str(result, context.config.max_width(), shape) } } @@ -355,18 +343,18 @@ fn rewrite_last_child_with_overflow( false } -pub fn rewrite_try( +fn repeat_try(try_count: usize) -> String { + iter::repeat("?").take(try_count).collect::() +} + +fn rewrite_try( expr: &ast::Expr, try_count: usize, context: &RewriteContext, shape: Shape, ) -> Option { let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count)))); - Some(format!( - "{}{}", - sub_expr, - iter::repeat("?").take(try_count).collect::() - )) + Some(format!("{}{}", sub_expr, repeat_try(try_count))) } fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { @@ -426,7 +414,9 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { match context.config.chain_indent() { IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), + IndentStyle::Block => shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), } } diff --git a/tests/target/match.rs b/tests/target/match.rs index 219c6fdea13..7d29e1e2321 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -389,9 +389,7 @@ fn issue1395() { fn issue1456() { Ok(Recording { - artists: match reader - .evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? - { + artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { Nodeset(nodeset) => { let res: Result, ReadError> = nodeset .iter() -- cgit 1.4.1-3-g733a5 From 04a6d16c7b68587f8e9fa8a1e6715f80408b023b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 7 Aug 2017 15:17:35 +0900 Subject: Avoid trial and error in rewrite_chain whenever possible --- src/chains.rs | 202 ++++++++++++++-------------------------------------------- 1 file changed, 48 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 2e2ce293fdb..75dac5b3227 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -105,7 +105,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let parent_shape = if is_block_expr(context, &parent, "\n") { match context.config.chain_indent() { IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape.block(), + IndentStyle::Block => shape, } } else { shape @@ -133,13 +133,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // brace. IndentStyle::Visual => (parent_shape, false), } - } else if parent_rewrite_contains_newline { - (chain_indent(context, parent_shape), false) } else { ( - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), + chain_indent(context, shape.add_offset(parent_rewrite.len())), false, ) }; @@ -166,8 +162,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .into_iter() .chain(iter::repeat(other_child_shape)); let subexpr_num = subexpr_list.len(); + let last_subexpr = &subexpr_list[suffix_try_num]; let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; - let iter = subexpr_list.iter().rev().zip(child_shape_iter); + let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); let mut rewrites = try_opt!( iter.map(|(e, shape)| { rewrite_chain_subexpr(e, total_span, context, shape) @@ -175,85 +172,46 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ); // Total of all items excluding the last. - let rewrites_len = rewrites.len(); - let almost_total = rewrites[0..(rewrites_len - 1)] - .iter() - .fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len(); - let one_line_len = - rewrites.iter().fold(0, |a, r| a + first_line_width(r)) + parent_rewrite.len(); - - let one_line_budget = min(shape.width, context.config.chain_one_line_max()); - let veto_single_line = if one_line_len > one_line_budget { - if rewrites.len() > 1 { - true - } else if rewrites.len() == 1 { - context.config.chain_split_single_child() || one_line_len > shape.width - } else { - false - } - } else if context.config.take_source_hints() && rewrites.len() > 1 { - // Look at the source code. Unless all chain elements start on the same - // line, we won't consider putting them on a single line either. - let last_span = context.snippet(mk_sp(subexpr_list[1].span.hi, total_span.hi)); - let first_span = context.snippet(subexpr_list[1].span); - let last_iter = last_span.chars().take_while(|c| c.is_whitespace()); - - first_span.chars().chain(last_iter).any(|c| c == '\n') + let extend_last_subexr = last_line_extendable(&parent_rewrite) && rewrites.is_empty(); + let almost_total = if extend_last_subexr { + last_line_width(&parent_rewrite) } else { - false + rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() }; - - let mut fits_single_line = !veto_single_line && almost_total <= shape.width; - if fits_single_line { - let len = rewrites.len(); - let (init, last) = rewrites.split_at_mut(len - 1); - fits_single_line = init.iter().all(|s| !s.contains('\n')); - - if fits_single_line { - fits_single_line = match expr.node { - ref e @ ast::ExprKind::MethodCall(..) => { - if rewrite_method_call_with_overflow( - e, - &mut last[0], - almost_total, - total_span, - context, - shape, - ) { - // If the first line of the last method does not fit into a single line - // after the others, allow new lines. - almost_total + first_line_width(&last[0]) < context.config.max_width() - } else { - false + let one_line_budget = if rewrites.is_empty() && !context.config.chain_split_single_child() { + shape.width + } else { + min(shape.width, context.config.chain_one_line_max()) + }; + let all_in_one_line = !parent_rewrite_contains_newline && + rewrites.iter().all(|s| !s.contains('\n')) && + almost_total < one_line_budget; + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, nested_shape); + let (last_subexpr_str, fits_single_line) = try_opt!(if all_in_one_line || extend_last_subexr { + parent_shape.offset_left(almost_total).map(|shape| { + if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + let line_count = rw.lines().count(); + let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + if (line_count >= 5 && fits_single_line) || extend_last_subexr { + (Some(rw), true) + } else { + match rewrite_last() { + Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), + Some(ref new_rw) if new_rw.lines().count() >= line_count => { + (Some(rw), fits_single_line) + } + new_rw @ Some(..) => (new_rw, false), + _ => (Some(rw), fits_single_line), } } - _ => !last[0].contains('\n'), + } else { + (rewrite_last(), false) } - } - } - - // Try overflowing the last element if we are using block indent and it goes multi line - // or it fits in a single line but goes over the max width. - if !fits_single_line && context.use_block_indent() { - let last_expr_index = rewrites.len() - 1; - let (init, last) = rewrites.split_at_mut(last_expr_index); - let almost_single_line = init.iter().all(|s| !s.contains('\n')); - if almost_single_line && last[0].contains('\n') { - let overflow_shape = Shape { - width: one_line_budget, - ..parent_shape - }; - fits_single_line = rewrite_last_child_with_overflow( - context, - &subexpr_list[0], - overflow_shape, - total_span, - almost_total, - one_line_budget, - &mut last[0], - ); - } - } + }) + } else { + Some((rewrite_last(), false)) + }); + rewrites.push(try_opt!(last_subexpr_str)); let connector = if fits_single_line && !parent_rewrite_contains_newline { // Yay, we can put everything on one line. @@ -266,14 +224,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - format!("\n{}", nested_shape.indent.to_string(context.config)) }; - let first_connector = choose_first_connector( - context, - &parent_rewrite, - &rewrites[0], - &connector, - &subexpr_list, - extend, - ); + let first_connector = if is_small_parent || fits_single_line || + last_line_extendable(&parent_rewrite) || + context.config.chain_indent() == IndentStyle::Visual + { + "" + } else { + connector.as_str() + }; let result = if is_small_parent && rewrites.len() > 1 { let second_connector = choose_first_connector( @@ -301,11 +259,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ) }; let result = format!("{}{}", result, repeat_try(suffix_try_num)); - if context.config.chain_indent() == IndentStyle::Block { - Some(result) - } else { - wrap_str(result, context.config.max_width(), shape) - } + wrap_str(result, context.config.max_width(), shape) } fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { @@ -323,26 +277,6 @@ fn chain_only_try(exprs: &[ast::Expr]) -> bool { // Try to rewrite and replace the last non-try child. Return `true` if // replacing succeeds. -fn rewrite_last_child_with_overflow( - context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, - span: Span, - almost_total: usize, - one_line_budget: usize, - last_child: &mut String, -) -> bool { - if let Some(shape) = shape.shrink_left(almost_total) { - if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) { - if almost_total + first_line_width(rw) <= one_line_budget && rw.lines().count() > 3 { - ::std::mem::swap(last_child, rw); - return true; - } - } - } - false -} - fn repeat_try(try_count: usize) -> String { iter::repeat("?").take(try_count).collect::() } @@ -420,46 +354,6 @@ fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { } } -fn rewrite_method_call_with_overflow( - expr_kind: &ast::ExprKind, - last: &mut String, - almost_total: usize, - total_span: Span, - context: &RewriteContext, - shape: Shape, -) -> bool { - if let &ast::ExprKind::MethodCall(ref segment, ref expressions) = expr_kind { - let shape = match shape.shrink_left(almost_total) { - Some(b) => b, - None => return false, - }; - let types = match segment.parameters { - Some(ref params) => match **params { - ast::PathParameters::AngleBracketed(ref data) => &data.types[..], - _ => &[], - }, - _ => &[], - }; - let mut last_rewrite = rewrite_method_call( - segment.identifier, - types, - expressions, - total_span, - context, - shape, - ); - - if let Some(ref mut s) = last_rewrite { - ::std::mem::swap(s, last); - true - } else { - false - } - } else { - unreachable!(); - } -} - // Returns the expression's subexpression, if it exists. When the subexpr // is a try! macro, we'll convert it to shorthand when the option is set. fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { -- cgit 1.4.1-3-g733a5 From f9239dd630bb10fcff07cc834f18d4330dcf75c8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 7 Aug 2017 15:17:57 +0900 Subject: Format source codes and update tests --- src/expr.rs | 22 +++++------ src/missed_spans.rs | 9 +++-- src/types.rs | 11 ++---- src/vertical.rs | 8 ++-- src/visitor.rs | 8 ++-- tests/target/chains-indent-visual.rs | 11 +++--- tests/target/chains-visual.rs | 73 +++++++++++++++--------------------- 7 files changed, 62 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f56f3f8779e..e800ed0565f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1130,10 +1130,8 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); let expr = &self.block.stmts[0]; - let if_str = try_opt!(expr.rewrite( - context, - Shape::legacy(new_width, Indent::empty()), - )); + let if_str = + try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty()),)); let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; @@ -1246,14 +1244,12 @@ impl<'a> ControlFlow<'a> { // for event in event let between_kwd_cond = mk_sp( context.codemap.span_after(self.span, self.keyword.trim()), - self.pat.map_or( - cond_span.lo, - |p| if self.matcher.is_empty() { + self.pat + .map_or(cond_span.lo, |p| if self.matcher.is_empty() { p.span.lo } else { context.codemap.span_before(self.span, self.matcher.trim()) - }, - ), + }), ); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -2253,15 +2249,17 @@ where _ => (), } } - last_arg_shape(&context, &item_vec, shape, args_max_width) - .map_or((None, None), |arg_shape| { + last_arg_shape(&context, &item_vec, shape, args_max_width).map_or( + (None, None), + |arg_shape| { rewrite_last_arg_with_overflow( &context, args, &mut item_vec[args.len() - 1], arg_shape, ) - }) + }, + ) } else { (None, None) }; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index ac3ad906d17..b85bc44b162 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -146,10 +146,11 @@ impl<'a> FmtVisitor<'a> { let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count(); if rewrite_next_comment && - !self.config - .file_lines() - .intersects_range(file_name, cur_line, cur_line + subslice_num_lines) - { + !self.config.file_lines().intersects_range( + file_name, + cur_line, + cur_line + subslice_num_lines, + ) { rewrite_next_comment = false; } diff --git a/src/types.rs b/src/types.rs index 8e0cf2436de..2927aa7425b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -553,10 +553,7 @@ impl Rewrite for ast::TyParamBound { let budget = try_opt!(shape.width.checked_sub(1)); Some(format!( "?{}", - try_opt!(tref.rewrite( - context, - Shape::legacy(budget, shape.indent + 1), - )) + try_opt!(tref.rewrite(context, Shape::legacy(budget, shape.indent + 1))) )) } ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), @@ -609,10 +606,8 @@ impl Rewrite for ast::TyParam { }; result.push_str(eq_str); let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!(def.rewrite( - context, - Shape::legacy(budget, shape.indent + result.len()), - )); + let rewrite = + try_opt!(def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); result.push_str(&rewrite); } diff --git a/src/vertical.rs b/src/vertical.rs index 7f43fa8681a..521341702c5 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -174,13 +174,13 @@ fn struct_field_preix_max_min_width( fields .iter() .map(|field| { - field.rewrite_prefix(context, shape).and_then( - |field_str| if field_str.contains('\n') { + field + .rewrite_prefix(context, shape) + .and_then(|field_str| if field_str.contains('\n') { None } else { Some(field_str.len()) - }, - ) + }) }) .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { (Some((max_len, min_len)), Some(len)) => { diff --git a/src/visitor.rs b/src/visitor.rs index c9fa7065511..3e23f1a399d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -855,8 +855,9 @@ impl Rewrite for ast::MetaItem { impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - try_opt!(self.meta()).rewrite(context, shape).map( - |rw| if self.is_sugared_doc { + try_opt!(self.meta()) + .rewrite(context, shape) + .map(|rw| if self.is_sugared_doc { rw } else { let original = context.snippet(self.span); @@ -869,8 +870,7 @@ impl Rewrite for ast::Attribute { } else { format!("{}[{}]", prefix, rw) } - }, - ) + }) } } diff --git a/tests/target/chains-indent-visual.rs b/tests/target/chains-indent-visual.rs index e3ab320c6e1..66ef44fcd4a 100644 --- a/tests/target/chains-indent-visual.rs +++ b/tests/target/chains-indent-visual.rs @@ -1,10 +1,9 @@ // rustfmt-chain_indent: Visual fn test() { - let x = my_long_function() - .my_even_longer_function() - .my_nested_function() - .some_random_name() - .another_function() - .do_it(); + let x = my_long_function().my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); } diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index cfd7192b8b4..829a27867dd 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -32,15 +32,14 @@ fn main() { x }); - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }) - .method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }) + .method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); @@ -67,16 +66,14 @@ fn floaters() { let x = Foo { field1: val1, field2: val2, - } - .method_call() + }.method_call() .method_call(); let y = if cond { val1 } else { val2 - } - .method_call(); + }.method_call(); { match x { @@ -86,8 +83,7 @@ fn floaters() { mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err("bad param number".to_owned()), - }] - .clone(), + }].clone(), ); } } @@ -97,22 +93,19 @@ fn floaters() { some(); } else { none(); - } - .bar() + }.bar() .baz(); - Foo { x: val } - .baz(|| { - force(); - multiline(); - }) - .quux(); + Foo { x: val }.baz(|| { + force(); + multiline(); + }) + .quux(); Foo { y: i_am_multi_line, z: ok, - } - .baz(|| { + }.baz(|| { force(); multiline(); }) @@ -121,8 +114,7 @@ fn floaters() { a + match x { true => "yay!", false => "boo!", - } - .bar() + }.bar() } fn is_replaced_content() -> bool { @@ -137,33 +129,30 @@ fn issue587() { } fn issue_1389() { - let names = String::from_utf8(names)? - .split('|') - .map(str::to_owned) - .collect(); + let names = String::from_utf8(names)?.split('|') + .map(str::to_owned) + .collect(); } fn issue1217() -> Result { - let random_chars: String = OsRng::new()? - .gen_ascii_chars() - .take(self.bit_length) - .collect(); + let random_chars: String = OsRng::new()?.gen_ascii_chars() + .take(self.bit_length) + .collect(); Ok(Mnemonic::new(&random_chars)) } fn issue1236(options: Vec) -> Result> { - let process = Command::new("dmenu") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .chain_err(|| "failed to spawn dmenu")?; + let process = Command::new("dmenu").stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; } fn issue1434() { for _ in 0..100 { - let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor) - .chain_err(|| { + let prototype_id = + PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { format!( "could not read prototype ID at offset {:#010x}", current_offset -- cgit 1.4.1-3-g733a5 From be38606c7790c4ae92e4f9a368ede8dfcb2feec5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 7 Aug 2017 17:29:55 +0900 Subject: Add leave_last field to ListItems --- src/expr.rs | 5 +++++ src/imports.rs | 1 + src/items.rs | 5 +++++ src/lists.rs | 9 ++++++++- src/patterns.rs | 2 ++ src/types.rs | 2 ++ src/vertical.rs | 1 + src/visitor.rs | 1 + 8 files changed, 25 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e800ed0565f..1287b89ed63 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -466,6 +466,7 @@ where |item| item.rewrite(context, nested_shape), span.lo, span.hi, + false, ).collect::>(); if items.is_empty() { @@ -587,6 +588,7 @@ fn rewrite_closure_fn_decl( |arg| arg.rewrite(context, arg_shape), context.codemap.span_after(span, "|"), body.span.lo, + false, ); let item_vec = arg_items.collect::>(); // 1 = space between arguments and return type. @@ -2190,6 +2192,7 @@ where |item| item.rewrite(context, shape), span.lo, span.hi, + true, ); let mut item_vec: Vec<_> = items.collect(); @@ -2651,6 +2654,7 @@ fn rewrite_struct_lit<'a>( rewrite, body_lo, span.hi, + false, ); let item_vec = items.collect::>(); @@ -2803,6 +2807,7 @@ where |item| item.rewrite(context, nested_shape), list_lo, span.hi - BytePos(1), + false, ); let item_vec: Vec<_> = items.collect(); let tactic = definitive_tactic( diff --git a/src/imports.rs b/src/imports.rs index a65d8bb066a..80780b661f2 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -442,6 +442,7 @@ fn rewrite_use_list( rewrite_path_item, context.codemap.span_after(span, "{"), span.hi, + false, ); items.extend(iter); items diff --git a/src/items.rs b/src/items.rs index dc40d1b5b8a..09b5f7d9d30 100644 --- a/src/items.rs +++ b/src/items.rs @@ -469,6 +469,7 @@ impl<'a> FmtVisitor<'a> { |f| self.format_variant(f), body_lo, body_hi, + false, ); let shape = Shape::indented(self.block_indent, self.config) @@ -2207,6 +2208,7 @@ fn rewrite_args( }, comment_span_start, span.hi, + false, ); arg_items.extend(more_items); @@ -2411,6 +2413,7 @@ fn rewrite_generics_inner( |&(_, ref str)| str.clone(), context.codemap.span_after(span, "<"), span.hi, + false, ); format_generics_item_list(context, items, shape, one_line_width) } @@ -2554,6 +2557,7 @@ fn rewrite_where_clause_rfc_style( |pred| pred.rewrite(context, block_shape), span_start, span_end, + false, ); let comma_tactic = if where_clause_option.suppress_comma { SeparatorTactic::Never @@ -2654,6 +2658,7 @@ fn rewrite_where_clause( |pred| pred.rewrite(context, Shape::legacy(budget, offset)), span_start, span_end, + false, ); let item_vec = items.collect::>(); // FIXME: we don't need to collect here if the where_layout isn't diff --git a/src/lists.rs b/src/lists.rs index 731d310a5d4..e6ee8a7df44 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -454,6 +454,7 @@ where prev_span_end: BytePos, next_span_start: BytePos, terminator: &'a str, + leave_last: bool, } impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> @@ -592,7 +593,11 @@ where ListItem { pre_comment: pre_comment, pre_comment_style: pre_comment_style, - item: (self.get_item_string)(&item), + item: if self.inner.peek().is_none() && self.leave_last { + None + } else { + (self.get_item_string)(&item) + }, post_comment: post_comment, new_lines: new_lines, } @@ -610,6 +615,7 @@ pub fn itemize_list<'a, T, I, F1, F2, F3>( get_item_string: F3, prev_span_end: BytePos, next_span_start: BytePos, + leave_last: bool, ) -> ListItems<'a, I, F1, F2, F3> where I: Iterator, @@ -626,6 +632,7 @@ where prev_span_end: prev_span_end, next_span_start: next_span_start, terminator: terminator, + leave_last: leave_last, } } diff --git a/src/patterns.rs b/src/patterns.rs index 03afe2d81b1..628c207d750 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -162,6 +162,7 @@ fn rewrite_struct_pat( |f| f.node.rewrite(context, v_shape), context.codemap.span_after(span, "{"), span.hi, + false, ); let item_vec = items.collect::>(); @@ -342,6 +343,7 @@ fn count_wildcard_suffix_len( |item| item.rewrite(context, shape), context.codemap.span_after(span, "("), span.hi - BytePos(1), + false, ).collect(); for item in items.iter().rev().take_while(|i| match i.item { diff --git a/src/types.rs b/src/types.rs index 2927aa7425b..f7cb3c53656 100644 --- a/src/types.rs +++ b/src/types.rs @@ -241,6 +241,7 @@ fn rewrite_segment( |seg| seg.rewrite(context, generics_shape), list_lo, span_hi, + false, ); let generics_str = try_opt!(format_generics_item_list( context, @@ -344,6 +345,7 @@ where }, list_lo, span.hi, + false, ); let item_vec: Vec<_> = items.collect(); diff --git a/src/vertical.rs b/src/vertical.rs index 521341702c5..fbb4ddd3bc8 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -219,6 +219,7 @@ fn rewrite_aligned_items_inner( |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), span.lo, span.hi, + false, ).collect::>(); let tactic = definitive_tactic( diff --git a/src/visitor.rs b/src/visitor.rs index 3e23f1a399d..bcc219107f4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -818,6 +818,7 @@ impl Rewrite for ast::MetaItem { |nested_meta_item| nested_meta_item.rewrite(context, item_shape), self.span.lo, hi, + false, ); let item_vec = items.collect::>(); let fmt = ListFormatting { -- cgit 1.4.1-3-g733a5 From bb8afcb091a3a18454e46849238522e6b7556e94 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 7 Aug 2017 17:30:32 +0900 Subject: Avoid rewriting the last argument whenever possible --- src/expr.rs | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1287b89ed63..0fe6294d9ab 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2244,7 +2244,7 @@ where // Replace the last item with its first line to see if it fits with // first arguments. - let (orig_last, placeholder) = if overflow_last { + let placeholder = if overflow_last { let mut context = context.clone(); if let Some(expr) = args[args.len() - 1].to_expr() { match expr.node { @@ -2252,22 +2252,14 @@ where _ => (), } } - last_arg_shape(&context, &item_vec, shape, args_max_width).map_or( - (None, None), - |arg_shape| { - rewrite_last_arg_with_overflow( - &context, - args, - &mut item_vec[args.len() - 1], - arg_shape, - ) - }, - ) + last_arg_shape(&context, &item_vec, shape, args_max_width).and_then(|arg_shape| { + rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) + }) } else { - (None, None) + None }; - let tactic = definitive_tactic( + let mut tactic = definitive_tactic( &*item_vec, ListTactic::LimitedHorizontalVertical(args_max_width), Separator::Comma, @@ -2280,10 +2272,17 @@ where (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { item_vec[args.len() - 1].item = placeholder; } - (true, _, _) => { - item_vec[args.len() - 1].item = orig_last; + _ if args.len() >= 1 => { + item_vec[args.len() - 1].item = args.last() + .and_then(|last_arg| last_arg.rewrite(context, shape)); + tactic = definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ); } - (false, _, _) => {} + _ => (), } tactic @@ -2358,7 +2357,7 @@ fn rewrite_last_arg_with_overflow<'a, T>( args: &[&T], last_item: &mut ListItem, shape: Shape, -) -> (Option, Option) +) -> Option where T: Rewrite + Spanned + ToExpr + 'a, { @@ -2389,14 +2388,13 @@ where } else { last_arg.rewrite(context, shape) }; - let orig_last = last_item.item.clone(); if let Some(rewrite) = rewrite { let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); last_item.item = rewrite_first_line; - (orig_last, Some(rewrite)) + Some(rewrite) } else { - (orig_last, None) + None } } -- cgit 1.4.1-3-g733a5 From beeaf8d0659af90de92bc2f977241cb1d297167e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 7 Aug 2017 17:32:31 +0900 Subject: Fix a typo --- src/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0fe6294d9ab..d0e5df3abbb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1132,8 +1132,7 @@ impl<'a> ControlFlow<'a> { let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); let expr = &self.block.stmts[0]; - let if_str = - try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty()),)); + let if_str = try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); let new_width = try_opt!(new_width.checked_sub(if_str.len())); let else_expr = &else_node.stmts[0]; -- cgit 1.4.1-3-g733a5 From e69a2aba18f0da8e004c0417a574fe001489a0fc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 10 Aug 2017 08:13:20 +0900 Subject: Add error_on_line_overflow_comments config option --- src/config.rs | 1 + src/lib.rs | 15 ++++++++++++++- .../configs-error_on_line_overflow_comment-false.rs | 7 +++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/target/configs-error_on_line_overflow_comment-false.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 7b2fb9f629d..fbba5e19490 100644 --- a/src/config.rs +++ b/src/config.rs @@ -501,6 +501,7 @@ create_config! { via the --file-lines option"; max_width: usize, 100, "Maximum width of each line"; error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width"; + error_on_line_overflow_comments: bool, true, "Error if unable to get comments within max_width"; tab_spaces: usize, 4, "Number of spaces per tab"; fn_call_width: usize, 60, "Maximum width of the args of a function call before falling back to vertical formatting"; diff --git a/src/lib.rs b/src/lib.rs index eaac371aa5b..555aa66671a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -599,6 +599,8 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m let mut newline_count = 0; let mut errors = vec![]; let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); + let mut prev_char: Option = None; + let mut is_comment = false; for (c, b) in text.chars() { if c == '\r' { @@ -626,7 +628,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m } // Check for any line width errors we couldn't correct. - if config.error_on_line_overflow() && line_len > config.max_width() { + let report_error_on_line_overflow = config.error_on_line_overflow() && + (config.error_on_line_overflow_comments() || !is_comment); + if report_error_on_line_overflow && line_len > config.max_width() { errors.push(FormattingError { line: cur_line, kind: ErrorKind::LineOverflow(line_len, config.max_width()), @@ -638,6 +642,8 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m cur_line += 1; newline_count += 1; last_wspace = None; + prev_char = None; + is_comment = false; } else { newline_count = 0; line_len += 1; @@ -645,9 +651,16 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m if last_wspace.is_none() { last_wspace = Some(b); } + } else if c == '/' { + match prev_char { + Some('/') => is_comment = true, + _ => (), + } + last_wspace = None; } else { last_wspace = None; } + prev_char = Some(c); } } diff --git a/tests/target/configs-error_on_line_overflow_comment-false.rs b/tests/target/configs-error_on_line_overflow_comment-false.rs new file mode 100644 index 00000000000..9fd9e01e274 --- /dev/null +++ b/tests/target/configs-error_on_line_overflow_comment-false.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow_comments: false +// Error on line overflow comment + +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn main() { + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +} -- cgit 1.4.1-3-g733a5 From 0bb998685dc878f56121709d26a63ca93b947d5f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 10 Aug 2017 23:10:41 +0900 Subject: Cover comments between function args and the brace --- src/items.rs | 34 ++++++++++++++++++++++++++++++++++ tests/source/comment.rs | 23 +++++++++++++++++++++++ tests/target/comment.rs | 23 +++++++++++++++++++++++ 3 files changed, 80 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 09b5f7d9d30..06251ffaf76 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2075,6 +2075,40 @@ fn rewrite_fn_base( pos_before_where, option, )); + // If there are neither where clause nor return type, we may be missing comments between + // args and `{`. + if where_clause_str.is_empty() { + if let ast::FunctionRetTy::Default(ret_span) = fd.output { + let sp = mk_sp(args_span.hi, ret_span.hi); + let missing_snippet = context.snippet(sp); + let trimmed_snippet = missing_snippet.trim(); + let missing_comment = if trimmed_snippet.is_empty() { + String::new() + } else { + try_opt!(rewrite_comment( + trimmed_snippet, + false, + Shape::indented(indent, context.config), + context.config, + )) + }; + if !missing_comment.is_empty() { + let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); + // 1 = ` ` + let total_width = missing_comment.len() + last_line_width(&result) + 1; + let force_new_line_before_comment = missing_snippet[..pos].contains('\n') || + total_width > context.config.max_width(); + let sep = if force_new_line_before_comment { + format!("\n{}", indent.to_string(context.config)) + } else { + String::from(" ") + }; + result.push_str(&sep); + result.push_str(&missing_comment); + force_new_line_for_brace = true; + } + } + } result.push_str(&where_clause_str); diff --git a/tests/source/comment.rs b/tests/source/comment.rs index cf40e581b6e..61d7fc454aa 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -59,3 +59,26 @@ fn issue_1086() { * random comment */ fn main() {/* Test */} + +// #1643 +fn some_fn() /* some comment */ +{ +} + +fn some_fn1() +// some comment +{ +} + +fn some_fn2() // some comment +{ +} + +fn some_fn3() /* some comment some comment some comment some comment some comment some comment so */ +{ +} + +fn some_fn4() +/* some comment some comment some comment some comment some comment some comment some comment */ +{ +} diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 486dde72ff3..9b650dad51f 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -63,3 +63,26 @@ fn issue_1086() { fn main() { // Test } + +// #1643 +fn some_fn() // some comment +{ +} + +fn some_fn1() +// some comment +{ +} + +fn some_fn2() // some comment +{ +} + +fn some_fn3() // some comment some comment some comment some comment some comment some comment so +{ +} + +fn some_fn4() +// some comment some comment some comment some comment some comment some comment some comment +{ +} -- cgit 1.4.1-3-g733a5 From b433e63d2a952db18fd079cbf8ec1cf49b0d076b Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 11 Aug 2017 16:15:28 +0900 Subject: Remove unnecessary blank lines at the start and the end of a block --- src/config.rs | 4 +++- src/visitor.rs | 49 +++++++++++++++++++++++++++++++++++--- tests/source/remove_blank_lines.rs | 22 +++++++++++++++++ tests/target/remove_blank_lines.rs | 11 +++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 tests/source/remove_blank_lines.rs create mode 100644 tests/target/remove_blank_lines.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index fbba5e19490..11d64dc073f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -606,7 +606,9 @@ create_config! { tuple patterns"; combine_control_expr: bool, true, "Combine control expressions with funciton calls."; struct_field_align_threshold: usize, 0, "Align struct fields if their diffs fits within \ - threshold." + threshold."; + remove_blank_lines_at_start_or_end_of_block: bool, true, + "Remove blank lines at start or end of a block"; } #[cfg(test)] diff --git a/src/visitor.rs b/src/visitor.rs index 4ef89979c3f..b455e569e43 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,7 +17,7 @@ use syntax::parse::ParseSess; use {Indent, Shape, Spanned}; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{contains_comment, FindUncommented}; +use comment::{contains_comment, CodeCharKind, CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; use expr::{format_expr, ExprType}; @@ -131,6 +131,27 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.buffer.push_str("{"); + if self.config.remove_blank_lines_at_start_or_end_of_block() { + if let Some(stmt) = b.stmts.first() { + let snippet = self.snippet(mk_sp(self.last_pos, stmt.span.lo)); + let len = CommentCodeSlices::new(&snippet) + .nth(0) + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal { + // There may be inner attributes + let s = &s[..s.len() - + s.trim_left_matches(&[' ', '\t', '\r', '\n'][..]).len()]; + s.rfind('\n') + } else { + None + } + }); + if let Some(len) = len { + self.last_pos = self.last_pos + BytePos(len as u32); + } + } + } + // Format inner attributes if available. if let Some(attrs) = inner_attrs { self.visit_attrs(attrs, ast::AttrStyle::Inner); @@ -148,9 +169,31 @@ impl<'a> FmtVisitor<'a> { } } + let mut remove_len = BytePos(0); + if self.config.remove_blank_lines_at_start_or_end_of_block() { + if let Some(stmt) = b.stmts.last() { + let snippet = self.snippet(mk_sp( + stmt.span.hi, + source!(self, b.span).hi - brace_compensation, + )); + let len = CommentCodeSlices::new(&snippet) + .last() + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal && s.trim().is_empty() { + Some(s.len()) + } else { + None + } + }); + if let Some(len) = len { + remove_len = BytePos(len as u32); + } + } + } + let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); if unindent_comment { - let end_pos = source!(self, b.span).hi - brace_compensation; + let end_pos = source!(self, b.span).hi - brace_compensation - remove_len; let snippet = self.get_context().snippet(mk_sp(self.last_pos, end_pos)); unindent_comment = snippet.contains("//") || snippet.contains("/*"); } @@ -158,7 +201,7 @@ impl<'a> FmtVisitor<'a> { if unindent_comment { self.block_indent = self.block_indent.block_unindent(self.config); } - self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation); + self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation - remove_len); if unindent_comment { self.block_indent = self.block_indent.block_indent(self.config); } diff --git a/tests/source/remove_blank_lines.rs b/tests/source/remove_blank_lines.rs new file mode 100644 index 00000000000..377843cbc8b --- /dev/null +++ b/tests/source/remove_blank_lines.rs @@ -0,0 +1,22 @@ +fn main() { + + + + + let x = 1; + + + + +} + +fn foo() { + + #![attribute] + + let x = 1; + + // comment + + +} diff --git a/tests/target/remove_blank_lines.rs b/tests/target/remove_blank_lines.rs new file mode 100644 index 00000000000..00de4a829f2 --- /dev/null +++ b/tests/target/remove_blank_lines.rs @@ -0,0 +1,11 @@ +fn main() { + let x = 1; +} + +fn foo() { + #![attribute] + + let x = 1; + + // comment +} -- cgit 1.4.1-3-g733a5 From fea3080f915cbf75b100bbba1f0b99d2839ca5e0 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 11 Aug 2017 16:17:12 +0900 Subject: Format --- src/bin/cargo-fmt.rs | 1 - src/bin/rustfmt.rs | 1 - src/expr.rs | 1 - src/filemap.rs | 1 - src/types.rs | 2 -- tests/source/fn-simple.rs | 1 - tests/source/indent_match_arms.rs | 1 - tests/source/issue-510.rs | 1 - tests/source/spaces-within-angle-brackets.rs | 1 - tests/source/spaces-within-parens.rs | 1 - tests/source/spaces-within-square-brackets.rs | 1 - tests/source/struct_tuple_visual.rs | 2 -- tests/target/fn-simple.rs | 1 - tests/target/indent_match_arms.rs | 1 - tests/target/issue-510.rs | 1 - tests/target/spaces-within-angle-brackets.rs | 1 - tests/target/spaces-within-parens.rs | 1 - tests/target/spaces-within-square-brackets.rs | 1 - tests/target/struct_tuple_visual.rs | 2 -- 19 files changed, 22 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index b07a40804dd..2c0ec3a84dc 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -271,7 +271,6 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: std::io::ErrorKind::NotFound, str::from_utf8(&output.stderr).unwrap(), )) - } fn target_from_json(jtarget: &Value) -> Target { diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index d1f7a83187b..88bd3222fcb 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -102,7 +102,6 @@ fn match_cli_path_or_file( config_path: Option, input_file: &Path, ) -> FmtResult<(Config, Option)> { - if let Some(config_file) = config_path { let toml = Config::from_toml_path(config_file.as_ref())?; return Ok((toml, Some(config_file))); diff --git a/src/expr.rs b/src/expr.rs index d0e5df3abbb..298b8143b53 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2985,7 +2985,6 @@ fn choose_rhs( } fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - fn count_line_breaks(src: &str) -> usize { src.chars().filter(|&x| x == '\n').count() } diff --git a/src/filemap.rs b/src/filemap.rs index ee0a21b39b1..72724da1c11 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -90,7 +90,6 @@ pub fn write_file( where T: Write, { - fn source_and_formatted_text( text: &StringBuffer, filename: &str, diff --git a/src/types.rs b/src/types.rs index f7cb3c53656..61ef03b1687 100644 --- a/src/types.rs +++ b/src/types.rs @@ -404,7 +404,6 @@ where } else { Some(format!("{}{}", args, output)) } - } fn type_bound_colon(context: &RewriteContext) -> &'static str { @@ -601,7 +600,6 @@ impl Rewrite for ast::TyParam { result.push_str(&join_bounds(context, shape, &strs)); } if let Some(ref def) = self.default { - let eq_str = match context.config.type_punctuation_density() { TypeDensity::Compressed => "=", TypeDensity::Wide => " = ", diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index e11df34ad86..e3d489411ad 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -51,5 +51,4 @@ pub fn waltz(cwd: &Path) -> CliAssert { formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig); } } - } diff --git a/tests/source/indent_match_arms.rs b/tests/source/indent_match_arms.rs index ecadbe705ff..75cee57f10d 100644 --- a/tests/source/indent_match_arms.rs +++ b/tests/source/indent_match_arms.rs @@ -23,5 +23,4 @@ fn main() { }, _ => "something else", } - } diff --git a/tests/source/issue-510.rs b/tests/source/issue-510.rs index 8f56be02e32..4c60859e6cf 100644 --- a/tests/source/issue-510.rs +++ b/tests/source/issue-510.rs @@ -3,7 +3,6 @@ fn solve_inline_size_constraints(&self, block: &mut BlockFlow, input: &ISizeConstraintInput) -> ISizeConstraintSolution { - let (inline_start,inline_size,margin_inline_start,margin_inline_end) = match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { diff --git a/tests/source/spaces-within-angle-brackets.rs b/tests/source/spaces-within-angle-brackets.rs index fc8dcda4293..73cab841e2e 100644 --- a/tests/source/spaces-within-angle-brackets.rs +++ b/tests/source/spaces-within-angle-brackets.rs @@ -31,7 +31,6 @@ fn foo(a: T, b: E) { } fn foo(a: T, b: E) { - foo::(10, "bar"); let opt: Option; diff --git a/tests/source/spaces-within-parens.rs b/tests/source/spaces-within-parens.rs index 63978eaf854..dba8d7cf013 100644 --- a/tests/source/spaces-within-parens.rs +++ b/tests/source/spaces-within-parens.rs @@ -14,7 +14,6 @@ struct TupleStruct2(u32, u32); fn fooEmpty() {} fn foo(e: E, _: u32) -> (u32, u32) { - // Tuples let t1 = (); let t2 = (1,); diff --git a/tests/source/spaces-within-square-brackets.rs b/tests/source/spaces-within-square-brackets.rs index 6988ce5ed1c..d0466cacdd5 100644 --- a/tests/source/spaces-within-square-brackets.rs +++ b/tests/source/spaces-within-square-brackets.rs @@ -1,7 +1,6 @@ // rustfmt-spaces_within_square_brackets: true fn main() { - let arr: [i32; 5] = [1, 2, 3, 4, 5]; let arr: [i32; 500] = [0; 500]; diff --git a/tests/source/struct_tuple_visual.rs b/tests/source/struct_tuple_visual.rs index 8f935c1aa4d..d7d9e961bc4 100644 --- a/tests/source/struct_tuple_visual.rs +++ b/tests/source/struct_tuple_visual.rs @@ -3,7 +3,6 @@ // rustfmt-error_on_line_overflow: false // rustfmt-struct_lit_style: Visual fn foo() { - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment @@ -35,5 +34,4 @@ fn foo() { // /|\ \ // o o o o G) - } diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index e381b6e6231..a9640937f60 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -96,5 +96,4 @@ pub fn waltz(cwd: &Path) -> CliAssert { rewrite_comment(comment, block_style, width, offset, formatting_fig); } } - } diff --git a/tests/target/indent_match_arms.rs b/tests/target/indent_match_arms.rs index e0b34dbe03d..8d5e7ef7887 100644 --- a/tests/target/indent_match_arms.rs +++ b/tests/target/indent_match_arms.rs @@ -23,5 +23,4 @@ fn main() { }, _ => "something else", } - } diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs index 54fe361bb4e..a166b68498f 100644 --- a/tests/target/issue-510.rs +++ b/tests/target/issue-510.rs @@ -4,7 +4,6 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced { block: &mut BlockFlow, input: &ISizeConstraintInput, ) -> ISizeConstraintSolution { - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match ( inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, diff --git a/tests/target/spaces-within-angle-brackets.rs b/tests/target/spaces-within-angle-brackets.rs index 3969327b8ec..89335b602a4 100644 --- a/tests/target/spaces-within-angle-brackets.rs +++ b/tests/target/spaces-within-angle-brackets.rs @@ -31,7 +31,6 @@ fn foo< T, E >(a: T, b: E) { } fn foo< T: Send, E: Send >(a: T, b: E) { - foo::< u32, str >(10, "bar"); let opt: Option< u32 >; diff --git a/tests/target/spaces-within-parens.rs b/tests/target/spaces-within-parens.rs index 2a0a566ddea..651386c618b 100644 --- a/tests/target/spaces-within-parens.rs +++ b/tests/target/spaces-within-parens.rs @@ -14,7 +14,6 @@ struct TupleStruct2( u32, u32 ); fn fooEmpty() {} fn foo( e: E, _: u32 ) -> ( u32, u32 ) { - // Tuples let t1 = (); let t2 = ( 1, ); diff --git a/tests/target/spaces-within-square-brackets.rs b/tests/target/spaces-within-square-brackets.rs index 3a1b24d4def..cb468d6b59e 100644 --- a/tests/target/spaces-within-square-brackets.rs +++ b/tests/target/spaces-within-square-brackets.rs @@ -1,7 +1,6 @@ // rustfmt-spaces_within_square_brackets: true fn main() { - let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; let arr: [ i32; 500 ] = [ 0; 500 ]; diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs index e63bc2c47c2..02811668bcb 100644 --- a/tests/target/struct_tuple_visual.rs +++ b/tests/target/struct_tuple_visual.rs @@ -3,7 +3,6 @@ // rustfmt-error_on_line_overflow: false // rustfmt-struct_lit_style: Visual fn foo() { - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo( @@ -45,5 +44,4 @@ fn foo() { // o o o o G, ) - } -- cgit 1.4.1-3-g733a5 From 0af19985fcf9ac94079025ab116c804eff959d67 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 11 Aug 2017 17:52:13 +0900 Subject: Generalize combine_attr_and_expr --- src/comment.rs | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/expr.rs | 66 ++++++------------------------------------- src/utils.rs | 10 +++++++ 3 files changed, 107 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d332c354b12..0a716aa308c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -18,7 +18,7 @@ use {Indent, Shape}; use config::Config; use rewrite::RewriteContext; use string::{rewrite_string, StringFormat}; -use utils::wrap_str; +use utils::{first_line_width, last_line_width, wrap_str}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { @@ -136,6 +136,93 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { } } +pub fn combine_strs_with_missing_comments( + context: &RewriteContext, + prev_str: &str, + next_str: &str, + span: Span, + shape: Shape, + allow_extend: bool, +) -> Option { + let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); + let first_sep = if prev_str.is_empty() || next_str.is_empty() { + "" + } else { + " " + }; + let mut one_line_width = + last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); + + let original_snippet = context.snippet(span); + let trimmed_snippet = original_snippet.trim(); + let indent_str = shape.indent.to_string(context.config); + + if trimmed_snippet.is_empty() { + if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { + return Some(format!("{}{}{}", prev_str, first_sep, next_str)); + } else { + let sep = if prev_str.is_empty() { + String::new() + } else { + String::from("\n") + &indent_str + }; + return Some(format!("{}{}{}", prev_str, sep, next_str)); + } + } + + // We have a missing comment between the first expression and the second expression. + + // Peek the the original source code and find out whether there is a newline between the first + // expression and the second expression or the missing comment. We will preserve the orginal + // layout whenever possible. + let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { + !original_snippet[..pos].contains('\n') + } else { + !original_snippet.contains('\n') + }; + + let missing_comment = try_opt!(rewrite_comment( + trimmed_snippet, + false, + shape, + context.config + )); + one_line_width -= first_sep.len(); + let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { + String::new() + } else { + let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; + if prefer_same_line && one_line_width <= shape.width { + String::from(" ") + } else { + format!("\n{}", indent_str) + } + }; + let second_sep = if missing_comment.is_empty() || next_str.is_empty() { + String::new() + } else { + if missing_comment.starts_with("//") { + format!("\n{}", indent_str) + } else { + one_line_width += missing_comment.len() + first_sep.len() + 1; + allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); + if prefer_same_line && allow_one_line && one_line_width <= shape.width { + String::from(" ") + } else { + format!("\n{}", indent_str) + } + } + }; + Some(format!( + "{}{}{}{}{}", + prev_str, + first_sep, + missing_comment, + second_sep, + next_str, + )) +} + pub fn rewrite_comment( orig: &str, block_style: bool, diff --git a/src/expr.rs b/src/expr.rs index d0e5df3abbb..c785f4883c4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -19,7 +19,8 @@ use syntax::parse::classify; use {Indent, Shape, Spanned}; use chains::rewrite_chain; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + rewrite_comment, FindUncommented}; use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, @@ -49,61 +50,6 @@ pub enum ExprType { SubExpression, } -fn combine_attr_and_expr( - context: &RewriteContext, - shape: Shape, - expr: &ast::Expr, - expr_str: &str, -) -> Option { - let attrs = outer_attributes(&expr.attrs); - let attr_str = try_opt!(attrs.rewrite(context, shape)); - let separator = if attr_str.is_empty() { - String::new() - } else { - // Try to recover comments between the attributes and the expression if available. - let missing_snippet = context.snippet(mk_sp(attrs[attrs.len() - 1].span.hi, expr.span.lo)); - let comment_opening_pos = missing_snippet.chars().position(|c| c == '/'); - let prefer_same_line = if let Some(pos) = comment_opening_pos { - !missing_snippet[..pos].contains('\n') - } else { - !missing_snippet.contains('\n') - }; - - let trimmed = missing_snippet.trim(); - let missing_comment = if trimmed.is_empty() { - String::new() - } else { - try_opt!(rewrite_comment(&trimmed, false, shape, context.config)) - }; - - // 2 = ` ` + ` ` - let one_line_width = - attr_str.len() + missing_comment.len() + 2 + first_line_width(expr_str); - let attr_expr_separator = if prefer_same_line && !missing_comment.starts_with("//") && - one_line_width <= shape.width - { - String::from(" ") - } else { - format!("\n{}", shape.indent.to_string(context.config)) - }; - - if missing_comment.is_empty() { - attr_expr_separator - } else { - // 1 = ` ` - let one_line_width = - last_line_width(&attr_str) + 1 + first_line_width(&missing_comment); - let attr_comment_separator = if prefer_same_line && one_line_width <= shape.width { - String::from(" ") - } else { - format!("\n{}", shape.indent.to_string(context.config)) - }; - attr_comment_separator + &missing_comment + &attr_expr_separator - } - }; - Some(format!("{}{}{}", attr_str, separator, expr_str)) -} - pub fn format_expr( expr: &ast::Expr, expr_type: ExprType, @@ -355,7 +301,13 @@ pub fn format_expr( recover_comment_removed(expr_str, expr.span, context, shape) }) .and_then(|expr_str| { - combine_attr_and_expr(context, shape, expr, &expr_str) + let attrs = outer_attributes(&expr.attrs); + let attrs_str = try_opt!(attrs.rewrite(context, shape)); + let span = mk_sp( + attrs.last().map_or(expr.span.lo, |attr| attr.span.hi), + expr.span.lo, + ); + combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) }) } diff --git a/src/utils.rs b/src/utils.rs index c0861b8da20..9a31289e8eb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -116,6 +116,16 @@ pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { filter_attributes(attrs, ast::AttrStyle::Outer) } +#[inline] +pub fn last_line_contains_single_line_comment(s: &str) -> bool { + s.lines().last().map_or(false, |l| l.contains("//")) +} + +#[inline] +pub fn is_attributes_extendable(attrs_str: &str) -> bool { + !attrs_str.contains('\n') && !last_line_contains_single_line_comment(&attrs_str) +} + // The width of the first line in s. #[inline] pub fn first_line_width(s: &str) -> usize { -- cgit 1.4.1-3-g733a5 From a4e0fe2b02f76ef10d908d234fb48ad583e373c6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 11 Aug 2017 17:52:49 +0900 Subject: Allow attributes to stay on the same line with fields --- src/items.rs | 201 ++++++++++++++++++++++++-------------------------------- src/vertical.rs | 40 ++++++++--- 2 files changed, 118 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 06251ffaf76..302d15ee8aa 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,7 +18,8 @@ use syntax::codemap::{BytePos, Span}; use {Indent, Shape, Spanned}; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + rewrite_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; @@ -28,8 +29,9 @@ use rewrite::{Rewrite, RewriteContext}; use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, - format_visibility, last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, - stmt_expr, trim_newlines, trimmed_last_line_width, wrap_str}; + format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, + last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, stmt_expr, + trim_newlines, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -501,32 +503,19 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let indent = self.block_indent; - let mut result = try_opt!( - field - .node - .attrs - .rewrite(&context, Shape::indented(indent, self.config)) - ); - if !result.is_empty() { - let shape = Shape { - width: context.config.max_width(), - indent: self.block_indent, - offset: self.block_indent.alignment, - }; - let missing_comment = rewrite_missing_comment_on_field( - &context, - shape, - field.node.attrs[field.node.attrs.len() - 1].span.hi, - field.span.lo, - &mut result, - ).unwrap_or(String::new()); - result.push_str(&missing_comment); - } + let shape = Shape::indented(indent, self.config); + let attrs_str = try_opt!(field.node.attrs.rewrite(&context, shape)); + let lo = field + .node + .attrs + .last() + .map_or(field.span.lo, |attr| attr.span.hi); + let span = mk_sp(lo, field.span.lo); let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma - format_struct( + try_opt!(format_struct( &context, "", field.node.name, @@ -536,29 +525,37 @@ impl<'a> FmtVisitor<'a> { field.span, indent, Some(self.config.struct_variant_width()), - ) + )) } - ast::VariantData::Unit(..) => { - let tag = if let Some(ref expr) = field.node.disr_expr { + ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { + let one_line_width = + field.node.name.to_string().len() + self.snippet(expr.span).len() + 3; + if one_line_width <= shape.width { format!("{} = {}", field.node.name, self.snippet(expr.span)) } else { - field.node.name.to_string() - }; - - wrap_str( - tag, - self.config.max_width(), - Shape::indented(indent, self.config), - ) - } + format!( + "{}\n{}{}", + field.node.name, + shape + .indent + .block_indent(self.config) + .to_string(self.config), + self.snippet(expr.span) + ) + } + } else { + String::from(field.node.name.to_string()) + }, }; - if let Some(variant_str) = variant_body { - result.push_str(&variant_str); - Some(result) - } else { - None - } + combine_strs_with_missing_comments( + &context, + &attrs_str, + &variant_body, + span, + shape, + is_attributes_extendable(&attrs_str), + ) } } @@ -1369,68 +1366,15 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { ) } -fn rewrite_missing_comment_on_field( - context: &RewriteContext, - shape: Shape, - lo: BytePos, - hi: BytePos, - result: &mut String, -) -> Option { - let possibly_comment_snippet = context.snippet(mk_sp(lo, hi)); - let newline_index = possibly_comment_snippet.find('\n'); - let comment_index = possibly_comment_snippet.find('/'); - match (newline_index, comment_index) { - (Some(i), Some(j)) if i > j => result.push(' '), - _ => { - result.push('\n'); - result.push_str(&shape.indent.to_string(context.config)); - } - } - let trimmed = possibly_comment_snippet.trim(); - if trimmed.is_empty() { - None - } else { - rewrite_comment(trimmed, false, shape, context.config).map(|s| { - format!("{}\n{}", s, shape.indent.to_string(context.config)) - }) - } -} - pub fn rewrite_struct_field_prefix( context: &RewriteContext, field: &ast::StructField, - shape: Shape, ) -> Option { let vis = format_visibility(&field.vis); - let mut attr_str = try_opt!( - field - .attrs - .rewrite(context, Shape::indented(shape.indent, context.config)) - ); - // Try format missing comments after attributes - let missing_comment = if !field.attrs.is_empty() { - rewrite_missing_comment_on_field( - context, - shape, - field.attrs[field.attrs.len() - 1].span.hi, - field.span.lo, - &mut attr_str, - ).unwrap_or(String::new()) - } else { - String::new() - }; - let type_annotation_spacing = type_annotation_spacing(context.config); Some(match field.ident { - Some(name) => format!( - "{}{}{}{}{}:", - attr_str, - missing_comment, - vis, - name, - type_annotation_spacing.0 - ), - None => format!("{}{}{}", attr_str, missing_comment, vis), + Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), + None => format!("{}", vis), }) } @@ -1466,27 +1410,50 @@ pub fn rewrite_struct_field( } let type_annotation_spacing = type_annotation_spacing(context.config); - let prefix = try_opt!(rewrite_struct_field_prefix(context, field, shape)); + let prefix = try_opt!(rewrite_struct_field_prefix(context, field)); - // Try to put everything on a single line. - let last_line_width = last_line_width(&prefix); + let attrs_str = try_opt!(field.attrs.rewrite(context, shape)); + let missing_span = if field.attrs.is_empty() { + mk_sp(field.span.lo, field.span.lo) + } else { + mk_sp(field.attrs.last().unwrap().span.hi, field.span.lo) + }; let mut spacing = String::from(if field.ident.is_some() { type_annotation_spacing.1 } else { "" }); - let lhs_offset = lhs_max_width.checked_sub(last_line_width).unwrap_or(0); + // Try to put everything on a single line. + let attr_prefix = try_opt!(combine_strs_with_missing_comments( + context, + &attrs_str, + &prefix, + missing_span, + shape, + is_attributes_extendable(&attrs_str), + )); + let overhead = last_line_width(&attr_prefix); + let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); for _ in 0..lhs_offset { spacing.push(' '); } - let ty_rewritten = rewrite_struct_field_type(context, last_line_width, field, &spacing, shape); + // In this extreme case we will be missing a space betweeen an attribute and a field. + if prefix.is_empty() && !attrs_str.is_empty() && is_attributes_extendable(&attrs_str) && + spacing.is_empty() + { + spacing.push(' '); + } + let ty_rewritten = rewrite_struct_field_type(context, overhead, field, &spacing, shape); if let Some(ref ty) = ty_rewritten { if !ty.contains('\n') { - return Some(prefix + &ty); + return Some(attr_prefix + &ty); } } // We must use multiline. + let last_line_width = last_line_width(&prefix); + let ty_rewritten = rewrite_struct_field_type(context, last_line_width, field, &spacing, shape); + let type_offset = shape.indent.block_indent(context.config); let rewrite_type_in_next_line = || { field @@ -1494,27 +1461,35 @@ pub fn rewrite_struct_field( .rewrite(context, Shape::indented(type_offset, context.config)) }; - match ty_rewritten { + let field_str = match ty_rewritten { // If we start from the next line and type fits in a single line, then do so. Some(ref ty) => match rewrite_type_in_next_line() { - Some(ref new_ty) if !new_ty.contains('\n') => Some(format!( + Some(ref new_ty) if !new_ty.contains('\n') => format!( "{}\n{}{}", prefix, type_offset.to_string(&context.config), &new_ty - )), - _ => Some(prefix + &ty), + ), + _ => prefix + &ty, }, _ => { let ty = try_opt!(rewrite_type_in_next_line()); - Some(format!( + format!( "{}\n{}{}", prefix, type_offset.to_string(&context.config), &ty - )) + ) } - } + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + &field_str, + missing_span, + shape, + is_attributes_extendable(&attrs_str), + ) } pub fn rewrite_static( @@ -2148,10 +2123,6 @@ impl WhereClauseOption { } } -fn last_line_contains_single_line_comment(s: &str) -> bool { - s.lines().last().map_or(false, |l| l.contains("//")) -} - fn rewrite_args( context: &RewriteContext, args: &[ast::Arg], diff --git a/src/vertical.rs b/src/vertical.rs index fbb4ddd3bc8..1a62cad7757 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -17,12 +17,12 @@ use syntax::codemap::{BytePos, Span}; use {Indent, Shape, Spanned}; use codemap::SpanUtils; -use comment::contains_comment; +use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator}; use rewrite::{Rewrite, RewriteContext}; -use utils::{contains_skip, mk_sp}; +use utils::{contains_skip, is_attributes_extendable, mk_sp}; pub trait AlignedItem { fn skip(&self) -> bool; @@ -46,7 +46,22 @@ impl AlignedItem for ast::StructField { } fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_struct_field_prefix(context, self, shape) + let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo, self.span.lo) + } else { + mk_sp(self.attrs.last().unwrap().span.hi, self.span.lo) + }; + rewrite_struct_field_prefix(context, self).and_then(|field_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &field_str, + missing_span, + shape, + is_attributes_extendable(&attrs_str), + ) + }) } fn rewrite_aligned_item( @@ -69,12 +84,21 @@ impl AlignedItem for ast::Field { } fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let mut attrs_str = try_opt!(self.attrs.rewrite(context, shape)); - if !attrs_str.is_empty() { - attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); - }; + let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); let name = &self.ident.node.to_string(); - Some(format!("{}{}", attrs_str, name)) + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo, self.span.lo) + } else { + mk_sp(self.attrs.last().unwrap().span.hi, self.span.lo) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + name, + missing_span, + shape, + is_attributes_extendable(&attrs_str), + ) } fn rewrite_aligned_item( -- cgit 1.4.1-3-g733a5 From 840edb2c4f8fe4f74999c1a311461f86fae7cbae Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 11 Aug 2017 17:54:38 +0900 Subject: Remove 'mut' notation --- src/lib.rs | 4 ++-- src/macros.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 555aa66671a..d5d2db33fc5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -535,7 +535,7 @@ impl fmt::Display for FormatReport { // Formatting which depends on the AST. fn format_ast( krate: &ast::Crate, - mut parse_session: &mut ParseSess, + parse_session: &mut ParseSess, main_file: &Path, config: &Config, codemap: &Rc, @@ -796,7 +796,7 @@ pub enum Input { } pub fn run(input: Input, config: &Config) -> Summary { - let mut out = &mut stdout(); + let out = &mut stdout(); output_header(out, config.write_mode()).ok(); match format_input(input, config, Some(out)) { Ok((summary, _, report)) => { diff --git a/src/macros.rs b/src/macros.rs index 989aaaaa58c..ae2a16510b8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -68,7 +68,7 @@ pub fn rewrite_macro( shape: Shape, position: MacroPosition, ) -> Option { - let mut context = &mut context.clone(); + let context = &mut context.clone(); context.inside_macro = true; if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { -- cgit 1.4.1-3-g733a5 From 02d82f926e398b25a04d1b37603981963fa6ca7a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 12 Aug 2017 15:59:35 +0900 Subject: Allow empty tuple pattern --- src/patterns.rs | 2 +- tests/source/pattern.rs | 6 ++++++ tests/target/pattern.rs | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 628c207d750..aa163c2d4d8 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -288,7 +288,7 @@ fn rewrite_tuple_pat( } if pat_vec.is_empty() { - return Some(format!("{}()", try_opt!(path_str))); + return Some(format!("{}()", path_str.unwrap_or(String::new()))); } let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 7e1787ca409..b8781bd1d2e 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -42,3 +42,9 @@ impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { fn issue_1319() { if let (Event { .. }, .. ) = ev_state {} } + +fn issue_1874() { + if let Some(()) = x { +y + } +} diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index 39a8408a630..15fbef048c8 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -57,3 +57,9 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { fn issue_1319() { if let (Event { .. }, ..) = ev_state {} } + +fn issue_1874() { + if let Some(()) = x { + y + } +} -- cgit 1.4.1-3-g733a5 From 955b25625d2f925261661a8fd7abfc322186886b Mon Sep 17 00:00:00 2001 From: sinkuu Date: Fri, 11 Aug 2017 22:16:24 +0900 Subject: Use attribute span --- src/visitor.rs | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index b455e569e43..8c911465722 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -12,7 +12,8 @@ use std::cmp; use strings::string_buffer::StringBuffer; use syntax::{ast, ptr, visit}; -use syntax::codemap::{self, BytePos, CodeMap, Span}; +use syntax::attr::HasAttrs; +use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; use {Indent, Shape, Spanned}; @@ -132,22 +133,45 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str("{"); if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(stmt) = b.stmts.first() { - let snippet = self.snippet(mk_sp(self.last_pos, stmt.span.lo)); - let len = CommentCodeSlices::new(&snippet) - .nth(0) - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal { - // There may be inner attributes - let s = &s[..s.len() - - s.trim_left_matches(&[' ', '\t', '\r', '\n'][..]).len()]; - s.rfind('\n') + if let Some(first_stmt) = b.stmts.first() { + let attr_lo = inner_attrs + .and_then(|attrs| { + attrs + .iter() + .filter(|a| a.style == ast::AttrStyle::Inner) + .nth(0) + .map(|attr| attr.span.lo) + }) + .or_else(|| { + // Attributes for an item in a statement position + // do not belong to the statement. (rust-lang/rust#34459) + if let ast::StmtKind::Item(ref item) = first_stmt.node { + item.attrs.first() } else { - None - } + first_stmt.attrs().first() + }.and_then(|attr| { + // Some stmts can have embedded attributes. + // e.g. `match { #![attr] ... }` + let attr_lo = attr.span.lo; + if attr_lo < first_stmt.span.lo { + Some(attr_lo) + } else { + None + } + }) }); + + let snippet = + self.snippet(mk_sp(self.last_pos, attr_lo.unwrap_or(first_stmt.span.lo))); + let len = CommentCodeSlices::new(&snippet).nth(0).and_then( + |(kind, _, s)| if kind == CodeCharKind::Normal { + s.rfind('\n') + } else { + None + }, + ); if let Some(len) = len { - self.last_pos = self.last_pos + BytePos(len as u32); + self.last_pos = self.last_pos + BytePos::from_usize(len); } } } @@ -186,7 +210,7 @@ impl<'a> FmtVisitor<'a> { } }); if let Some(len) = len { - remove_len = BytePos(len as u32); + remove_len = BytePos::from_usize(len); } } } -- cgit 1.4.1-3-g733a5 From f9ee060eae6324a15f90e772b3db4d71f4141a6f Mon Sep 17 00:00:00 2001 From: sinkuu Date: Sat, 12 Aug 2017 17:01:46 +0900 Subject: Use utils::inner_attributes --- src/visitor.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 8c911465722..6faaf8805b3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -136,10 +136,8 @@ impl<'a> FmtVisitor<'a> { if let Some(first_stmt) = b.stmts.first() { let attr_lo = inner_attrs .and_then(|attrs| { - attrs - .iter() - .filter(|a| a.style == ast::AttrStyle::Inner) - .nth(0) + utils::inner_attributes(attrs) + .first() .map(|attr| attr.span.lo) }) .or_else(|| { -- cgit 1.4.1-3-g733a5 From 10f1257eb34d978ad230de503dc1df7a5d520d95 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 13 Aug 2017 10:17:52 +0900 Subject: Use correct width for subexpr_list --- src/chains.rs | 1 + tests/source/expr-block.rs | 4 ++++ tests/target/expr-block.rs | 5 +++++ 3 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 75dac5b3227..9c129ef99ee 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -233,6 +233,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - connector.as_str() }; + let subexpr_num = subexpr_list.len(); let result = if is_small_parent && rewrites.len() > 1 { let second_connector = choose_first_connector( context, diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 3b4e6356ff9..1d55bd0a0d9 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -282,3 +282,7 @@ fn issue_1862() { /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , ) } + +fn issue_1878() { + let channel: &str = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 68c5421c3ca..194798ff472 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -333,3 +333,8 @@ fn issue_1862() { this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, ) } + +fn issue_1878() { + let channel: &str = seq.next_element()? + .ok_or_else(|| de::Error::invalid_length(2, &self))?; +} -- cgit 1.4.1-3-g733a5 From 831db35a83f8577ae68cbd04d8674ba99632b9bf Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 15 Aug 2017 16:49:02 +0900 Subject: Move isatty() to utils.rs --- src/rustfmt_diff.rs | 20 +------------------- src/utils.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 3e9fd913d7c..3fb22865385 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -12,6 +12,7 @@ use diff; use std::collections::VecDeque; use std::io; use term; +use utils::isatty; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -105,25 +106,6 @@ where } _ => print_diff_basic(diff, get_section_title), } - - // isatty shamelessly adapted from cargo. - #[cfg(unix)] - fn isatty() -> bool { - extern crate libc; - - unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } - } - #[cfg(windows)] - fn isatty() -> bool { - extern crate kernel32; - extern crate winapi; - - unsafe { - let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); - let mut out = 0; - kernel32::GetConsoleMode(handle, &mut out) != 0 - } - } } fn print_diff_fancy( diff --git a/src/utils.rs b/src/utils.rs index 9a31289e8eb..bd46ef1bc6a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -516,3 +516,22 @@ pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { _ => e, } } + +// isatty shamelessly adapted from cargo. +#[cfg(unix)] +pub fn isatty() -> bool { + extern crate libc; + + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +pub fn isatty() -> bool { + extern crate kernel32; + extern crate winapi; + + unsafe { + let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); + let mut out = 0; + kernel32::GetConsoleMode(handle, &mut out) != 0 + } +} -- cgit 1.4.1-3-g733a5 From 222ae15c7beeaea774f771e4f19543e332b414b7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 15 Aug 2017 16:49:54 +0900 Subject: No more sorry --- src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index d5d2db33fc5..d98e764ad1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -482,8 +482,7 @@ impl FormattingError { fn msg_suffix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "(sorry)", - ErrorKind::BadIssue(_) => "", + _ => String::from(""), } } } -- cgit 1.4.1-3-g733a5 From 4c39e5aeb8f444e4cc258f91c6d07012a9e1424a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 15 Aug 2017 16:52:11 +0900 Subject: Add fields to FormattingError is_comment is set to true if the error happened inside comment. line_buffer is the line which overflowed. --- src/lib.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index d98e764ad1c..86d5191412e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -468,8 +468,10 @@ impl fmt::Display for ErrorKind { // Formatting errors that are identified *after* rustfmt has run. pub struct FormattingError { - line: u32, + line: usize, kind: ErrorKind, + is_comment: bool, + line_buffer: String, } impl FormattingError { @@ -600,6 +602,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); let mut prev_char: Option = None; let mut is_comment = false; + let mut line_buffer = String::with_capacity(config.max_width() * 2); for (c, b) in text.chars() { if c == '\r' { @@ -614,6 +617,8 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m errors.push(FormattingError { line: cur_line, kind: ErrorKind::BadIssue(issue), + is_comment: false, + line_buffer: String::new(), }); } } @@ -622,7 +627,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m if format_line { // Check for (and record) trailing whitespace. if let Some(lw) = last_wspace { - trims.push((cur_line, lw, b)); + trims.push((cur_line, lw, b, line_buffer.clone())); line_len -= 1; } @@ -633,6 +638,8 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m errors.push(FormattingError { line: cur_line, kind: ErrorKind::LineOverflow(line_len, config.max_width()), + is_comment: is_comment, + line_buffer: line_buffer.clone(), }); } } @@ -643,6 +650,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m last_wspace = None; prev_char = None; is_comment = false; + line_buffer.clear(); } else { newline_count = 0; line_len += 1; @@ -660,6 +668,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m last_wspace = None; } prev_char = Some(c); + line_buffer.push(c); } } @@ -669,10 +678,12 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m text.truncate(line); } - for &(l, _, _) in &trims { + for &(l, _, _, ref b) in &trims { errors.push(FormattingError { line: l, kind: ErrorKind::TrailingWhitespace, + is_comment: false, + line_buffer: b.clone(), }); } -- cgit 1.4.1-3-g733a5 From 67285f15eb64637abbb134b675e04fd9a842d2f4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 15 Aug 2017 16:54:07 +0900 Subject: Enhance error messages with rustc style --- src/lib.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 86d5191412e..5af8449cd0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,7 @@ extern crate unicode_segmentation; use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, Write}; +use std::iter::repeat; use std::ops::{Add, Sub}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -456,7 +457,7 @@ impl fmt::Display for ErrorKind { match *self { ErrorKind::LineOverflow(found, maximum) => write!( fmt, - "line exceeded maximum length (maximum: {}, found: {})", + "line exceeded maximum width (maximum: {}, found: {})", maximum, found ), @@ -477,16 +478,36 @@ pub struct FormattingError { impl FormattingError { fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "Rustfmt failed at", + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "error:", ErrorKind::BadIssue(_) => "WARNING:", } } - fn msg_suffix(&self) -> &str { + fn msg_suffix(&self) -> String { match self.kind { + ErrorKind::LineOverflow(..) if self.is_comment => format!( + "use `error_on_lineoverflow_comments = false` to suppress \ + the warning against line comments\n", + ), _ => String::from(""), } } + + // (space, target) + pub fn format_len(&self) -> (usize, usize) { + match self.kind { + ErrorKind::LineOverflow(found, max) => (max, found - max), + ErrorKind::TrailingWhitespace => { + let trailing_ws_len = self.line_buffer + .chars() + .rev() + .take_while(|c| c.is_whitespace()) + .count(); + (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) + } + _ => (0, 0), // unreachable + } + } } pub struct FormatReport { @@ -518,17 +539,50 @@ impl fmt::Display for FormatReport { fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { for (file, errors) in &self.file_error_map { for error in errors { + let prefix_space_len = error.line.to_string().len(); + let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + + let error_line_buffer = if error.line_buffer.is_empty() { + String::from(" ") + } else { + let (space_len, target_len) = error.format_len(); + format!( + "{}|\n{} | {}\n{}| {}", + prefix_spaces, + error.line, + error.line_buffer, + prefix_spaces, + target_str(space_len, target_len) + ) + }; + + let error_info = format!("{} {}", error.msg_prefix(), error.kind); + let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line); + let msg_suffix = error.msg_suffix(); + let note = if msg_suffix.is_empty() { + String::new() + } else { + format!("{}note= ", prefix_spaces) + }; + write!( fmt, - "{} {}:{}: {} {}\n", - error.msg_prefix(), - file, - error.line, - error.kind, + "{}\n{}\n{}\n{}{}\n", + error_info, + file_info, + error_line_buffer, + note, error.msg_suffix() )?; } } + if !self.file_error_map.is_empty() { + write!( + fmt, + "warning: rustfmt may have failed to format. See previous {} errors.\n", + self.warning_count(), + )?; + } Ok(()) } } -- cgit 1.4.1-3-g733a5 From 5c50766b361f54ab39b0726ed65164a5e13b666d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 15 Aug 2017 16:54:18 +0900 Subject: Print error messages with colors if possible --- src/lib.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 5af8449cd0a..3ac1c3e4cf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ use checkstyle::{output_footer, output_header}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; -use utils::{mk_sp, outer_attributes}; +use utils::{isatty, mk_sp, outer_attributes}; use visitor::FmtVisitor; pub use self::summary::Summary; @@ -532,6 +532,76 @@ impl FormatReport { pub fn has_warnings(&self) -> bool { self.warning_count() > 0 } + + pub fn print_warnings_fancy( + &self, + mut t: Box>, + ) -> Result<(), term::Error> { + for (file, errors) in &self.file_error_map { + for error in errors { + let prefix_space_len = error.line.to_string().len(); + let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + + // First line: the overview of error + t.fg(term::color::RED)?; + t.attr(term::Attr::Bold)?; + write!(t, "{} ", error.msg_prefix())?; + t.reset()?; + t.attr(term::Attr::Bold)?; + write!(t, "{}\n", error.kind)?; + + // Second line: file info + write!(t, "{}--> ", &prefix_spaces[1..])?; + t.reset()?; + write!(t, "{}:{}\n", file, error.line)?; + + // Third to fifth lines: show the line which triggered error, if available. + if !error.line_buffer.is_empty() { + let (space_len, target_len) = error.format_len(); + t.attr(term::Attr::Bold)?; + write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; + t.reset()?; + write!(t, "{}\n", error.line_buffer)?; + t.attr(term::Attr::Bold)?; + write!(t, "{}| ", prefix_spaces)?; + t.fg(term::color::RED)?; + write!(t, "{}\n", target_str(space_len, target_len))?; + t.reset()?; + } + + // The last line: show note if available. + let msg_suffix = error.msg_suffix(); + if !msg_suffix.is_empty() { + t.attr(term::Attr::Bold)?; + write!(t, "{}= note: ", prefix_spaces)?; + t.reset()?; + write!(t, "{}\n", error.msg_suffix())?; + } else { + write!(t, "\n")?; + } + t.reset()?; + } + } + + if !self.file_error_map.is_empty() { + t.attr(term::Attr::Bold)?; + write!(t, "warning: ")?; + t.reset()?; + write!( + t, + "rustfmt may have failed to format. See previous {} errors.\n\n", + self.warning_count(), + )?; + } + + Ok(()) + } +} + +fn target_str(space_len: usize, target_len: usize) -> String { + let empty_line: String = repeat(" ").take(space_len).collect(); + let overflowed: String = repeat("^").take(target_len).collect(); + empty_line + &overflowed } impl fmt::Display for FormatReport { @@ -867,7 +937,15 @@ pub fn run(input: Input, config: &Config) -> Summary { output_footer(out, config.write_mode()).ok(); if report.has_warnings() { - msg!("{}", report); + match term::stderr() { + Some(ref t) if isatty() && t.supports_color() => { + match report.print_warnings_fancy(term::stderr().unwrap()) { + Ok(..) => (), + Err(..) => panic!("Unable to write to stderr: {}", report), + } + } + _ => msg!("{}", report), + } } summary -- cgit 1.4.1-3-g733a5 From 4fd9920a2d6e5a8e9f8cb0b28bf50c50d92f52dc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 15 Aug 2017 22:10:39 +0900 Subject: Obey to array_layout when using mixed tactic for array --- src/expr.rs | 14 +- ...rray_horizontal_layout_threshold-1000-visual.rs | 108 ++++++++++++ ...rray_horizontal_layout_threshold-1000-visual.rs | 96 +++++++++++ ...nfigs-array_horizontal_layout_threshold-1000.rs | 185 ++++++++++----------- 4 files changed, 299 insertions(+), 104 deletions(-) create mode 100644 tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs create mode 100644 tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c785f4883c4..b9ea9461a5e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -394,7 +394,7 @@ where 1 // "[" }; - let mut nested_shape = match context.config.array_layout() { + let nested_shape = match context.config.array_layout() { IndentStyle::Block => try_opt!( shape .block() @@ -456,19 +456,11 @@ where DefinitiveListTactic::Mixed }, }; - let mut ends_with_newline = tactic.ends_with_newline(context.config.array_layout()); + let ends_with_newline = tactic.ends_with_newline(context.config.array_layout()); if context.config.array_horizontal_layout_threshold() > 0 && items.len() > context.config.array_horizontal_layout_threshold() { tactic = DefinitiveListTactic::Mixed; - ends_with_newline = false; - if context.config.array_layout() == IndentStyle::Block { - nested_shape = try_opt!( - shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2) - ); - } } let fmt = ListFormatting { @@ -489,7 +481,7 @@ where let list_str = try_opt!(write_list(&items, &fmt)); let result = if context.config.array_layout() == IndentStyle::Visual || - tactic != DefinitiveListTactic::Vertical + tactic == DefinitiveListTactic::Horizontal { if context.config.spaces_within_square_brackets() && list_str.len() > 0 { format!("[ {} ]", list_str) diff --git a/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs b/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs new file mode 100644 index 00000000000..877d63194e8 --- /dev/null +++ b/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs @@ -0,0 +1,108 @@ +// rustfmt-array_horizontal_layout_threshold: 1000 +// rustfmt-array_layout: Visual + +const ARRAY: [u8; 2048] = + [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, + 21, 18, 37, 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, + 87, 69, 42, 38, 25, 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, + 29, 111, 120, 26, 0, 78, 36, 115, 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, + 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, 124, 124, 102, 74, 35, 9, 83, 22, 121, + 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, 54, 17, 58, 105, 13, 96, 61, 99, + 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, 56, 5, 114, 11, 25, 16, 97, + 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, 58, 103, 2, 88, + 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, 97, + 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, + 9, 21, 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, + 61, 8, 124, 110, 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, + 44, 73, 82, 10, 49, 95, 72, 89, 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, + 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, 31, 33, 84, 72, 128, 91, 3, 84, 92, + 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, 43, 66, 21, 90, 31, 102, 45, + 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, 54, 11, 103, 45, + 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, 93, + 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, + 92, 105, 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, + 52, 46, 81, 28, 46, 82, 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, + 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, + 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, 48, 51, 54, 56, 105, 90, 50, 67, + 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, 75, 29, 15, 15, 47, 33, + 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, 86, 101, + 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, + 36, 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, + 62, 86, 104, 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, + 23, 68, 115, 106, 15, 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, + 88, 8, 32, 3, 63, 77, 14, 86, 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, + 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, 67, 42, 109, 30, 93, 40, 113, 13, 85, + 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, 102, 25, 4, 113, 84, 63, + 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, 81, 38, 55, 82, + 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, 123, + 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, + 49, 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, + 83, 36, 38, 71, 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, + 49, 86, 7, 84, 40, 42, 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, + 50, 42, 34, 122, 116, 75, 31, 109, 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, + 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, 3, 18, 110, 84, 70, 23, 84, 23, + 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, 86, 67, 78, 126, 86, + 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, 86, 34, 91, + 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, 102, + 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, + 58, 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, + 115, 44, 4, 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, + 20, 44, 46, 4, 116, 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, + 10, 36, 68, 94, 40, 87, 74, 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, + 40, 97, 43, 58, 16, 120, 74, 52, 42, 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, + 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, 71, 92, 70, 57, 37, 42, 21, 83, 2, + 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, 52, 80, 94, 46, 18, 68, 72, + 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, 81, 45, 79, 121, + 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, 115, 29, + 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, + 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, + 101, 68, 26, 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, + 54, 69, 34, 22, 21, 54, 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, + 65, 40, 34, 12, 6, 127, 32, 90, 62, 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, + 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, 45, 85, 40, 3, 114, 36, 23, 109, 118, + 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, 47, 126, 118, 105, 10, 59, 12, + 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, 106, 110, 49, 50, 20, + 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, 79, 85, + 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, + 126, 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, + 116, 114, 119, 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, + 92, 70, 49, 59, 51, 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, + 2, 98, 47, 25, 100, 37, 42, 115, 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, + 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, 16, 113, 68, 20, 76, 99, 93, 121, 18, + 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, 6, 96, 12, 100, 33, 5, + 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, 114, 84, + 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, + 110, 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, + 115, 47, 80, 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, + 81, 76, 66, 17, 108, 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, + 12, 16, 114, 50, 49, 12, 3, 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, + 27, 28, 24, 46, 101, 10, 104, 51, 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, + 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, 56, 80, 20, 117, 65, 53, 58, 66, 5, + 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, 31, 80, 29, 12, 115, 75, + 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, 98, 118, 26, + 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, + 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, + 109, 109, 97, 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, + 81, 111, 6, 11, 28, 5, 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, + 29, 60, 91, 72, 94, 15, 31, 98, 47, 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, + 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, 103, 88, 22, 107, 38, 39, 100, + 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, 19, 59, 87, 128, 16, 46, + 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, 100, 41, 51, + 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, + 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, + 16, 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, + 91, 16, 46, 117, 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, + 5, 21, 81, 43, 58, 61, 59, 39, 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, + 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, + 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, 32, 3, 2, 117, 41, 80, 96, 122, + 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, 22, 68, 39, 119, + 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, 115, + 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, + 125, 1, 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, + 47, 21, 103, 63, 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, + 104, 43, 73, 17, 111, 36, 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, + 54, 71, 38, 58, 86, 124, 3, 103, 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, + 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, + 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, 45, 97, 8, 39, 125, 9, 22, 91, + 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, 106, 32, 105, 27, 0, 56, + 66, 51, 4, 94, 72, 117, 69]; diff --git a/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs b/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs new file mode 100644 index 00000000000..1f3dced2943 --- /dev/null +++ b/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs @@ -0,0 +1,96 @@ +// rustfmt-array_horizontal_layout_threshold: 1000 +// rustfmt-array_layout: Visual + +const ARRAY: [u8; 2048] = + [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, + 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, 87, 69, 42, 38, 25, + 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, 29, 111, 120, 26, 0, 78, 36, 115, + 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, + 124, 124, 102, 74, 35, 9, 83, 22, 121, 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, + 54, 17, 58, 105, 13, 96, 61, 99, 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, + 56, 5, 114, 11, 25, 16, 97, 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, + 58, 103, 2, 88, 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, + 97, 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, 9, 21, + 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, 61, 8, 124, 110, + 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, 44, 73, 82, 10, 49, 95, 72, 89, + 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, + 31, 33, 84, 72, 128, 91, 3, 84, 92, 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, + 43, 66, 21, 90, 31, 102, 45, 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, + 54, 11, 103, 45, 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, + 93, 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, 92, 105, + 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, 52, 46, 81, 28, 46, 82, + 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, + 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, + 48, 51, 54, 56, 105, 90, 50, 67, 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, + 75, 29, 15, 15, 47, 33, 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, + 86, 101, 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, 36, + 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, 62, 86, 104, + 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, 23, 68, 115, 106, 15, + 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, 88, 8, 32, 3, 63, 77, 14, 86, + 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, + 67, 42, 109, 30, 93, 40, 113, 13, 85, 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, + 102, 25, 4, 113, 84, 63, 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, + 81, 38, 55, 82, 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, + 123, 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, 49, + 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, 83, 36, 38, 71, + 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, 49, 86, 7, 84, 40, 42, + 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, 50, 42, 34, 122, 116, 75, 31, 109, + 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, + 3, 18, 110, 84, 70, 23, 84, 23, 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, + 86, 67, 78, 126, 86, 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, + 86, 34, 91, 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, + 102, 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, 58, + 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, 115, 44, 4, + 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, 20, 44, 46, 4, 116, + 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, 10, 36, 68, 94, 40, 87, 74, + 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, 40, 97, 43, 58, 16, 120, 74, 52, 42, + 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, + 71, 92, 70, 57, 37, 42, 21, 83, 2, 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, + 52, 80, 94, 46, 18, 68, 72, 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, + 81, 45, 79, 121, 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, + 115, 29, 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, + 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, 101, 68, 26, + 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, 54, 69, 34, 22, 21, 54, + 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, 65, 40, 34, 12, 6, 127, 32, 90, 62, + 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, + 45, 85, 40, 3, 114, 36, 23, 109, 118, 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, + 47, 126, 118, 105, 10, 59, 12, 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, + 106, 110, 49, 50, 20, 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, + 79, 85, 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, 126, + 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, 116, 114, 119, + 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, 92, 70, 49, 59, 51, + 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, 2, 98, 47, 25, 100, 37, 42, 115, + 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, + 16, 113, 68, 20, 76, 99, 93, 121, 18, 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, + 6, 96, 12, 100, 33, 5, 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, + 114, 84, 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, 110, + 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, 115, 47, 80, + 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, 81, 76, 66, 17, 108, + 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, 12, 16, 114, 50, 49, 12, 3, + 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, 27, 28, 24, 46, 101, 10, 104, 51, + 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, + 56, 80, 20, 117, 65, 53, 58, 66, 5, 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, + 31, 80, 29, 12, 115, 75, 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, + 98, 118, 26, 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, + 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, 109, 109, 97, + 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, 81, 111, 6, 11, 28, 5, + 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, 29, 60, 91, 72, 94, 15, 31, 98, 47, + 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, + 103, 88, 22, 107, 38, 39, 100, 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, + 19, 59, 87, 128, 16, 46, 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, + 100, 41, 51, 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, + 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, 16, + 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, 91, 16, 46, 117, + 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, 5, 21, 81, 43, 58, 61, 59, 39, + 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, + 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, + 32, 3, 2, 117, 41, 80, 96, 122, 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, + 22, 68, 39, 119, 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, + 115, 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, 125, 1, + 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, 47, 21, 103, 63, + 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, 104, 43, 73, 17, 111, 36, + 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, 54, 71, 38, 58, 86, 124, 3, 103, + 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, + 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, + 45, 97, 8, 39, 125, 9, 22, 91, 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, + 106, 32, 105, 27, 0, 56, 66, 51, 4, 94, 72, 117, 69]; diff --git a/tests/target/configs-array_horizontal_layout_threshold-1000.rs b/tests/target/configs-array_horizontal_layout_threshold-1000.rs index cadb9b09464..7c4347f9519 100644 --- a/tests/target/configs-array_horizontal_layout_threshold-1000.rs +++ b/tests/target/configs-array_horizontal_layout_threshold-1000.rs @@ -1,95 +1,94 @@ // rustfmt-array_horizontal_layout_threshold: 1000 -const ARRAY: [u8; 2048] = - [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, - 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, 87, 69, 42, 38, 25, - 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, 29, 111, 120, 26, 0, 78, 36, 115, - 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, - 124, 124, 102, 74, 35, 9, 83, 22, 121, 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, - 54, 17, 58, 105, 13, 96, 61, 99, 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, - 56, 5, 114, 11, 25, 16, 97, 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, - 58, 103, 2, 88, 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, - 97, 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, 9, 21, - 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, 61, 8, 124, 110, - 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, 44, 73, 82, 10, 49, 95, 72, 89, - 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, - 31, 33, 84, 72, 128, 91, 3, 84, 92, 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, - 43, 66, 21, 90, 31, 102, 45, 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, - 54, 11, 103, 45, 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, - 93, 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, 92, 105, - 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, 52, 46, 81, 28, 46, 82, - 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, - 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, - 48, 51, 54, 56, 105, 90, 50, 67, 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, - 75, 29, 15, 15, 47, 33, 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, - 86, 101, 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, 36, - 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, 62, 86, 104, - 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, 23, 68, 115, 106, 15, - 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, 88, 8, 32, 3, 63, 77, 14, 86, - 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, - 67, 42, 109, 30, 93, 40, 113, 13, 85, 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, - 102, 25, 4, 113, 84, 63, 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, - 81, 38, 55, 82, 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, - 123, 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, 49, - 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, 83, 36, 38, 71, - 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, 49, 86, 7, 84, 40, 42, - 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, 50, 42, 34, 122, 116, 75, 31, 109, - 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, - 3, 18, 110, 84, 70, 23, 84, 23, 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, - 86, 67, 78, 126, 86, 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, - 86, 34, 91, 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, - 102, 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, 58, - 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, 115, 44, 4, - 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, 20, 44, 46, 4, 116, - 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, 10, 36, 68, 94, 40, 87, 74, - 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, 40, 97, 43, 58, 16, 120, 74, 52, 42, - 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, - 71, 92, 70, 57, 37, 42, 21, 83, 2, 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, - 52, 80, 94, 46, 18, 68, 72, 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, - 81, 45, 79, 121, 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, - 115, 29, 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, - 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, 101, 68, 26, - 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, 54, 69, 34, 22, 21, 54, - 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, 65, 40, 34, 12, 6, 127, 32, 90, 62, - 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, - 45, 85, 40, 3, 114, 36, 23, 109, 118, 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, - 47, 126, 118, 105, 10, 59, 12, 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, - 106, 110, 49, 50, 20, 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, - 79, 85, 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, 126, - 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, 116, 114, 119, - 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, 92, 70, 49, 59, 51, - 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, 2, 98, 47, 25, 100, 37, 42, 115, - 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, - 16, 113, 68, 20, 76, 99, 93, 121, 18, 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, - 6, 96, 12, 100, 33, 5, 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, - 114, 84, 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, 110, - 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, 115, 47, 80, - 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, 81, 76, 66, 17, 108, - 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, 12, 16, 114, 50, 49, 12, 3, - 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, 27, 28, 24, 46, 101, 10, 104, 51, - 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, - 56, 80, 20, 117, 65, 53, 58, 66, 5, 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, - 31, 80, 29, 12, 115, 75, 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, - 98, 118, 26, 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, - 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, 109, 109, 97, - 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, 81, 111, 6, 11, 28, 5, - 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, 29, 60, 91, 72, 94, 15, 31, 98, 47, - 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, - 103, 88, 22, 107, 38, 39, 100, 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, - 19, 59, 87, 128, 16, 46, 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, - 100, 41, 51, 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, - 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, 16, - 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, 91, 16, 46, 117, - 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, 5, 21, 81, 43, 58, 61, 59, 39, - 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, - 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, - 32, 3, 2, 117, 41, 80, 96, 122, 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, - 22, 68, 39, 119, 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, - 115, 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, 125, 1, - 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, 47, 21, 103, 63, - 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, 104, 43, 73, 17, 111, 36, - 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, 54, 71, 38, 58, 86, 124, 3, 103, - 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, - 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, - 45, 97, 8, 39, 125, 9, 22, 91, 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, - 106, 32, 105, 27, 0, 56, 66, 51, 4, 94, 72, 117, 69]; +const ARRAY: [u8; 2048] = [ + 99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, 61, + 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, 87, 69, 42, 38, 25, 105, 6, + 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, 29, 111, 120, 26, 0, 78, 36, 115, 86, 66, 10, + 52, 87, 27, 125, 122, 42, 126, 101, 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, 124, 124, 102, + 74, 35, 9, 83, 22, 121, 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, 54, 17, 58, 105, + 13, 96, 61, 99, 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, 56, 5, 114, 11, 25, + 16, 97, 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, 58, 103, 2, 88, 85, 9, + 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, 97, 59, 39, 37, 79, 110, + 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, 9, 21, 65, 119, 2, 20, 64, 56, 34, + 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, 61, 8, 124, 110, 87, 64, 99, 26, 122, 56, 127, + 94, 8, 121, 19, 24, 27, 61, 34, 44, 73, 82, 10, 49, 95, 72, 89, 27, 124, 75, 33, 64, 48, 73, + 21, 101, 34, 47, 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, 31, 33, 84, 72, 128, 91, 3, + 84, 92, 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, 43, 66, 21, 90, 31, 102, 45, 66, + 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, 54, 11, 103, 45, 44, 101, 106, 53, + 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, 93, 34, 101, 48, 114, 127, 65, 69, + 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, 92, 105, 119, 17, 32, 23, 37, 8, 127, 99, 71, + 54, 80, 109, 54, 51, 44, 20, 40, 52, 46, 81, 28, 46, 82, 39, 39, 70, 3, 90, 41, 40, 36, 127, + 48, 124, 26, 115, 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, 46, 16, 65, 114, 53, 51, 123, 16, 36, + 98, 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, 48, 51, 54, 56, 105, 90, 50, 67, 111, + 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, 75, 29, 15, 15, 47, 33, 119, 85, 11, + 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, 86, 101, 79, 103, 98, 70, 122, 110, 38, + 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, 36, 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, + 32, 96, 64, 71, 89, 108, 10, 106, 62, 86, 104, 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, + 111, 102, 4, 126, 95, 23, 68, 115, 106, 15, 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, + 7, 52, 77, 88, 8, 32, 3, 63, 77, 14, 86, 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, 74, + 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, 67, 42, 109, 30, 93, 40, 113, 13, 85, 17, 51, 63, 57, + 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, 102, 25, 4, 113, 84, 63, 64, 63, 73, 83, 39, 123, 113, + 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, 81, 38, 55, 82, 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, + 77, 74, 62, 126, 36, 110, 66, 4, 86, 123, 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, + 0, 59, 76, 47, 94, 6, 94, 86, 49, 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, + 18, 32, 69, 1, 83, 36, 38, 71, 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, + 79, 97, 49, 86, 7, 84, 40, 42, 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, 50, 42, + 34, 122, 116, 75, 31, 109, 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, 114, 105, 16, 79, 53, + 19, 78, 86, 110, 4, 43, 97, 3, 18, 110, 84, 70, 23, 84, 23, 48, 125, 36, 58, 25, 90, 111, 103, + 83, 38, 112, 127, 28, 53, 86, 67, 78, 126, 86, 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, + 90, 42, 108, 29, 72, 86, 34, 91, 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, + 52, 116, 65, 15, 102, 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, + 16, 31, 8, 58, 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, + 115, 44, 4, 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, 20, 44, + 46, 4, 116, 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, 10, 36, 68, 94, + 40, 87, 74, 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, 40, 97, 43, 58, 16, 120, 74, + 52, 42, 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, + 9, 71, 92, 70, 57, 37, 42, 21, 83, 2, 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, + 52, 80, 94, 46, 18, 68, 72, 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, + 81, 45, 79, 121, 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, + 115, 29, 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, + 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, 101, 68, 26, + 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, 54, 69, 34, 22, 21, 54, + 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, 65, 40, 34, 12, 6, 127, 32, 90, 62, 47, + 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, 45, + 85, 40, 3, 114, 36, 23, 109, 118, 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, 47, + 126, 118, 105, 10, 59, 12, 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, 106, + 110, 49, 50, 20, 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, 79, 85, + 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, 126, 104, 57, + 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, 116, 114, 119, 125, 61, 81, + 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, 92, 70, 49, 59, 51, 104, 103, 62, 96, + 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, 2, 98, 47, 25, 100, 37, 42, 115, 105, 42, 127, 65, + 24, 102, 122, 33, 79, 87, 22, 47, 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, 16, 113, 68, 20, 76, + 99, 93, 121, 18, 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, 6, 96, 12, 100, 33, 5, + 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, 114, 84, 125, 124, 113, + 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, 110, 96, 42, 4, 64, 41, 110, 97, + 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, 115, 47, 80, 55, 67, 92, 127, 120, 8, 42, + 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, 81, 76, 66, 17, 108, 55, 17, 50, 31, 64, 102, 88, 5, + 32, 12, 37, 120, 48, 46, 43, 99, 12, 16, 114, 50, 49, 12, 3, 63, 64, 27, 54, 53, 31, 73, 2, 15, + 39, 102, 12, 60, 100, 27, 28, 24, 46, 101, 10, 104, 51, 127, 101, 60, 55, 114, 25, 3, 29, 20, + 53, 108, 7, 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, 56, 80, 20, 117, 65, 53, 58, 66, 5, + 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, 31, 80, 29, 12, 115, 75, 84, 91, 91, + 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, 98, 118, 26, 19, 36, 35, 122, 29, 41, + 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, + 47, 2, 112, 2, 42, 126, 12, 15, 15, 109, 109, 97, 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, + 24, 21, 68, 42, 49, 69, 81, 111, 6, 11, 28, 5, 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, + 54, 25, 29, 60, 91, 72, 94, 15, 31, 98, 47, 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, 96, 65, + 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, 103, 88, 22, 107, 38, 39, 100, 102, 96, 1, 66, 44, + 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, 19, 59, 87, 128, 16, 46, 51, 34, 34, 71, 117, 113, 66, + 89, 126, 127, 35, 125, 11, 81, 120, 100, 41, 51, 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, + 95, 75, 31, 33, 84, 83, 22, 35, 99, 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, + 53, 57, 15, 82, 60, 101, 10, 16, 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, + 14, 35, 3, 51, 91, 16, 46, 117, 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, + 5, 21, 81, 43, 58, 61, 59, 39, 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, 23, 64, 28, + 32, 2, 119, 2, 55, 125, 57, 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, 100, 98, 53, 116, 22, 64, + 63, 112, 19, 60, 77, 95, 32, 3, 2, 117, 41, 80, 96, 122, 15, 45, 118, 102, 26, 89, 74, 2, 17, + 63, 21, 52, 23, 82, 97, 22, 68, 39, 119, 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, + 47, 59, 91, 46, 124, 115, 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, + 113, 45, 116, 125, 1, 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, + 47, 21, 103, 63, 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, 104, 43, 73, + 17, 111, 36, 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, 54, 71, 38, 58, 86, 124, + 3, 103, 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, 62, 48, 115, 30, 19, 80, 14, 7, 21, + 124, 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, + 58, 45, 97, 8, 39, 125, 9, 22, 91, 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, + 106, 32, 105, 27, 0, 56, 66, 51, 4, 94, 72, 117, 69, +]; -- cgit 1.4.1-3-g733a5 From 528200009a4778c0295f30282ed2d2ba7f3cd0c0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 16 Aug 2017 00:11:20 +0900 Subject: Do not panic against files with invalid attributes --- src/visitor.rs | 19 +++++++------------ tests/source/attrib.rs | 3 +++ tests/target/attrib.rs | 3 +++ 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 6faaf8805b3..c5d91fee5b3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -684,18 +684,13 @@ impl<'a> FmtVisitor<'a> { return false; } - let first = &attrs[0]; - self.format_missing_with_indent(source!(self, first.span).lo); - - let rewrite = attrs - .rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ) - .unwrap(); - self.buffer.push_str(&rewrite); - let last = attrs.last().unwrap(); - self.last_pos = source!(self, last.span).hi; + let rewrite = attrs.rewrite( + &self.get_context(), + Shape::indented(self.block_indent, self.config), + ); + let span = mk_sp(attrs[0].span.lo, attrs[attrs.len() - 1].span.hi); + self.push_rewrite(span, rewrite); + false } diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index beabed88510..55815371947 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -1,6 +1,9 @@ // rustfmt-wrap_comments: true // Test attributes and doc comments are preserved. +#[invalid attribute] +fn foo() {} + /// Blah blah blah. /// Blah blah blah. /// Blah blah blah. diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index fc2dfc11ad9..542ed3676f0 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -1,6 +1,9 @@ // rustfmt-wrap_comments: true // Test attributes and doc comments are preserved. +#[invalid attribute] +fn foo() {} + /// Blah blah blah. /// Blah blah blah. /// Blah blah blah. -- cgit 1.4.1-3-g733a5 From f9d279576f52ecf267758e2c3e1b921146fbfa7b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 18 Aug 2017 23:15:56 +0900 Subject: Use write_list() for rewriting match arms --- src/expr.rs | 230 +++++++++++++++++++++++++++++------------------------------ src/lists.rs | 48 +++++++------ 2 files changed, 142 insertions(+), 136 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0276b68ac9f..7953c344b40 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -10,7 +10,7 @@ use std::cmp::{min, Ordering}; use std::fmt::Write; -use std::iter::ExactSizeIterator; +use std::iter::{repeat, ExactSizeIterator}; use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; @@ -1425,44 +1425,24 @@ fn is_unsafe_block(block: &ast::Block) -> bool { } } -// inter-match-arm-comment-rules: -// - all comments following a match arm before the start of the next arm -// are about the second arm -fn rewrite_match_arm_comment( - context: &RewriteContext, - missed_str: &str, - shape: Shape, - arm_indent_str: &str, -) -> Option { - // The leading "," is not part of the arm-comment - let missed_str = match missed_str.find_uncommented(",") { - Some(n) => &missed_str[n + 1..], - None => &missed_str[..], - }; - - let mut result = String::new(); - // any text not preceeded by a newline is pushed unmodified to the block - let first_brk = missed_str.find(|c: char| c == '\n').unwrap_or(0); - result.push_str(&missed_str[..first_brk]); - let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it +// A simple wrapper type against ast::Arm. Used inside write_list(). +struct ArmWrapper<'a> { + pub arm: &'a ast::Arm, + // True if the arm is the last one in match expression. Used to decide on whether we should add + // trailing comma to the match arm when `config.trailing_comma() == Never`. + pub is_last: bool, +} - let first = missed_str - .find(|c: char| !c.is_whitespace()) - .unwrap_or(missed_str.len()); - if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { - // Excessive vertical whitespace before comment should be preserved - // FIXME handle vertical whitespace better - result.push('\n'); - } - let missed_str = missed_str[first..].trim(); - if !missed_str.is_empty() { - let comment = try_opt!(rewrite_comment(&missed_str, false, shape, context.config)); - result.push('\n'); - result.push_str(arm_indent_str); - result.push_str(&comment); +impl<'a> ArmWrapper<'a> { + pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> { + ArmWrapper { arm, is_last } } +} - Some(result) +impl<'a> Rewrite for ArmWrapper<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_match_arm(context, self.arm, shape, self.is_last) + } } fn rewrite_match( @@ -1511,7 +1491,7 @@ fn rewrite_match( try_opt!( inner_attrs .rewrite(context, shape) - .map(|s| format!("\n{}{}", nested_indent_str, s)) + .map(|s| format!("{}{}\n", nested_indent_str, s)) ) }; @@ -1523,11 +1503,18 @@ fn rewrite_match( inner_attrs[inner_attrs.len() - 1].span().hi }; + let arm_indent_str = if context.config.indent_match_arms() { + nested_indent_str + } else { + shape.indent.to_string(context.config) + }; + Some(format!( - "match {}{}{{{}{}\n{}}}", + "match {}{}{{\n{}{}{}\n{}}}", cond_str, block_sep, inner_attrs_str, + arm_indent_str, try_opt!(rewrite_match_arms( context, arms, @@ -1539,8 +1526,10 @@ fn rewrite_match( )) } -fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str { - if config.match_block_trailing_comma() { +fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { + if is_last && config.trailing_comma() == SeparatorTactic::Never { + "" + } else if config.match_block_trailing_comma() { "," } else if let ast::ExprKind::Block(ref block) = body.node { if let ast::BlockCheckMode::Default = block.rules { @@ -1560,84 +1549,87 @@ fn rewrite_match_arms( span: Span, open_brace_pos: BytePos, ) -> Option { - let mut result = String::new(); - let arm_shape = if context.config.indent_match_arms() { shape.block_indent(context.config.tab_spaces()) } else { shape.block_indent(0) }.with_max_width(context.config); - let arm_indent_str = arm_shape.indent.to_string(context.config); - - let arm_num = arms.len(); - for (i, arm) in arms.iter().enumerate() { - // Make sure we get the stuff between arms. - let missed_str = if i == 0 { - context.snippet(mk_sp(open_brace_pos, arm.span().lo)) - } else { - context.snippet(mk_sp(arms[i - 1].span().hi, arm.span().lo)) - }; - let comment = try_opt!(rewrite_match_arm_comment( - context, - &missed_str, - arm_shape, - &arm_indent_str, - )); - if !comment.chars().all(|c| c == ' ') { - result.push_str(&comment); - } - result.push('\n'); - result.push_str(&arm_indent_str); - let arm_str = rewrite_match_arm(context, arm, arm_shape); - if let Some(ref arm_str) = arm_str { - // Trim the trailing comma if necessary. - if i == arm_num - 1 && context.config.trailing_comma() == SeparatorTactic::Never && - arm_str.ends_with(',') - { - result.push_str(&arm_str[0..arm_str.len() - 1]) - } else { - result.push_str(arm_str) - } - } else { - // We couldn't format the arm, just reproduce the source. - let snippet = context.snippet(arm.span()); - result.push_str(&snippet); - if context.config.trailing_comma() != SeparatorTactic::Never { - result.push_str(arm_comma(context.config, &arm.body)) - } - } - } - // BytePos(1) = closing match brace. - let last_span = mk_sp(arms[arms.len() - 1].span().hi, span.hi - BytePos(1)); - let last_comment = context.snippet(last_span); - let comment = try_opt!(rewrite_match_arm_comment( - context, - &last_comment, - arm_shape, - &arm_indent_str, - )); - result.push_str(&comment); + let arm_len = arms.len(); + let is_last_iter = repeat(false) + .take(arm_len.checked_sub(1).unwrap_or(0)) + .chain(repeat(true)); + let items = itemize_list( + context.codemap, + arms.iter() + .zip(is_last_iter) + .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), + "}", + |arm| arm.arm.span().lo, + |arm| arm.arm.span().hi, + |arm| arm.rewrite(context, arm_shape), + open_brace_pos, + span.hi, + false, + ); + let arms_vec: Vec<_> = items.collect(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. + separator: "", + trailing_separator: SeparatorTactic::Never, + shape: arm_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; - Some(result) + write_list(&arms_vec, &fmt) } -fn rewrite_match_arm(context: &RewriteContext, arm: &ast::Arm, shape: Shape) -> Option { - let attr_str = if !arm.attrs.is_empty() { +fn rewrite_match_arm( + context: &RewriteContext, + arm: &ast::Arm, + shape: Shape, + is_last: bool, +) -> Option { + let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { - return None; + let (_, body) = flatten_arm_body(context, &arm.body); + // `arm.span()` does not include trailing comma, add it manually. + return Some(format!( + "{}{}", + context.snippet(arm.span()), + arm_comma(context.config, body, is_last), + )); } - format!( - "{}\n{}", + ( + mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi, arm.pats[0].span.lo), try_opt!(arm.attrs.rewrite(context, shape)), - shape.indent.to_string(context.config) ) } else { - String::new() + (mk_sp(arm.span().lo, arm.span().lo), String::new()) }; - let pats_str = try_opt!(rewrite_match_pattern(context, &arm.pats, &arm.guard, shape)); - let pats_str = attr_str + &pats_str; - rewrite_match_body(context, &arm.body, &pats_str, shape, arm.guard.is_some()) + let pats_str = try_opt!( + rewrite_match_pattern(context, &arm.pats, &arm.guard, shape).and_then(|pats_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &pats_str, + missing_span, + shape, + false, + ) + }) + ); + rewrite_match_body( + context, + &arm.body, + &pats_str, + shape, + arm.guard.is_some(), + is_last, + ) } fn rewrite_match_pattern( @@ -1685,27 +1677,35 @@ fn rewrite_match_pattern( Some(format!("{}{}", pats_str, guard_str)) } -fn rewrite_match_body( - context: &RewriteContext, - body: &ptr::P, - pats_str: &str, - shape: Shape, - has_guard: bool, -) -> Option { - let (extend, body) = match body.node { +// (extend, body) +// @extend: true if the arm body can be put next to `=>` +// @body: flattened body, if the body is block with a single expression +fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { + match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { (expr.can_be_overflowed(context, 1), &**expr) } else { - (false, &**body) + (false, &*body) } } - _ => (body.can_be_overflowed(context, 1), &**body), - }; + _ => (body.can_be_overflowed(context, 1), &*body), + } +} + +fn rewrite_match_body( + context: &RewriteContext, + body: &ptr::P, + pats_str: &str, + shape: Shape, + has_guard: bool, + is_last: bool, +) -> Option { + let (extend, body) = flatten_arm_body(context, &body); - let comma = arm_comma(&context.config, body); + let comma = arm_comma(&context.config, body, is_last); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let alt_block_sep = alt_block_sep.as_str(); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { diff --git a/src/lists.rs b/src/lists.rs index e6ee8a7df44..3fd9b1ab93c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -380,8 +380,9 @@ where for _ in 0..(comment_alignment + 1) { result.push(' '); } - // An additional space for the missing trailing comma - if last && item_max_width.is_some() && !separate { + // An additional space for the missing trailing separator. + if last && item_max_width.is_some() && !separate && !formatting.separator.is_empty() + { result.push(' '); } } @@ -525,25 +526,30 @@ where } } let newline_index = post_snippet.find('\n'); - let separator_index = post_snippet.find_uncommented(",").unwrap(); - - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => separator_index + 1, - // Block-style post-comment before the separator. - (Some(i), None) => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Potential *single* line comment. - (_, Some(j)) if j > separator_index => j + 1, - _ => post_snippet.len(), + if let Some(separator_index) = post_snippet.find_uncommented(",") { + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => separator_index + 1, + // Block-style post-comment before the separator. + (Some(i), None) => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Potential *single* line comment. + (_, Some(j)) if j > separator_index => j + 1, + _ => post_snippet.len(), + } + } else { + // Match arms may not have trailing comma. In any case, for match arms, + // we will assume that the post comment belongs to the next arm if they + // do not end with trailing comma. + 1 } } None => post_snippet -- cgit 1.4.1-3-g733a5 From a3567cec94620db57005e8511bb69f26ae389804 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 18 Aug 2017 23:19:11 +0900 Subject: Add mach_pattern_separator_break_point config option --- Configurations.md | 33 +++++++++++++++++++++++++++++++++ src/config.rs | 4 +++- 2 files changed, 36 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index a8d8c353c27..99740cb4b48 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1163,6 +1163,39 @@ match lorem { See also: [`indent_match_arms`](#indent_match_arms), [`trailing_comma`](#trailing_comma), [`wrap_match_arms`](#wrap_match_arms). +## `match_pattern_separator_break_point` + +Put a match sub-patterns' separator (`|`) in front or back. + +- **Default value**: `"Back"` +- **Possible values**: `"Back"`, `"Front"` + +#### `"Back"` + +```rust +match m { + Variant::Tag | + Variant::Tag2 | + Variant::Tag3 | + Variant::Tag4 | + Variant::Tag5 | + Variant::Tag6 => {} +} +``` + +#### `Front` + +```rust +match m { + Variant::Tag + | Variant::Tag2 + | Variant::Tag3 + | Variant::Tag4 + | Variant::Tag5 + | Variant::Tag6 => {} +} +``` + ## `max_width` Maximum width of each line diff --git a/src/config.rs b/src/config.rs index 11d64dc073f..3c1afe8ddfa 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,7 +17,7 @@ use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; use file_lines::FileLines; -use lists::{ListTactic, SeparatorTactic}; +use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; macro_rules! configuration_option_enum{ ($e:ident: $( $x:ident ),+ $(,)*) => { @@ -581,6 +581,8 @@ create_config! { "Put a trailing comma after a block based match arm (non-block arms are not affected)"; indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \ indentation level as the match keyword"; + match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, + "Put a match sub-patterns' separator in front or back."; closure_block_indent_threshold: isize, 7, "How many lines a closure must have before it is \ block indented. -1 means never use block indent."; space_before_type_annotation: bool, false, -- cgit 1.4.1-3-g733a5 From 63ac49638b32fd9daebb36e75ee213580503bf9e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 18 Aug 2017 23:19:47 +0900 Subject: Support match_pattern_separator_break_point config option --- src/expr.rs | 8 ++++++- src/imports.rs | 3 ++- src/items.rs | 7 +++++- src/lists.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++------------ src/types.rs | 3 ++- src/vertical.rs | 4 +++- src/visitor.rs | 4 +++- 7 files changed, 75 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7953c344b40..e49d8a99ad5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -25,7 +25,7 @@ use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, Separator, SeparatorTactic}; + ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; @@ -473,6 +473,7 @@ where } else { SeparatorTactic::Vertical }, + separator_place: SeparatorPlace::Back, shape: nested_shape, ends_with_newline: ends_with_newline, preserve_newline: false, @@ -555,6 +556,7 @@ fn rewrite_closure_fn_decl( tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: arg_shape, ends_with_newline: false, preserve_newline: true, @@ -1578,6 +1580,7 @@ fn rewrite_match_arms( // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. separator: "", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: arm_shape, ends_with_newline: true, preserve_newline: true, @@ -1659,6 +1662,7 @@ fn rewrite_match_pattern( tactic: tactic, separator: " |", trailing_separator: SeparatorTactic::Never, + separator_place: context.config.match_pattern_separator_break_point(), shape: pat_shape, ends_with_newline: false, preserve_newline: false, @@ -2161,6 +2165,7 @@ where } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, preserve_newline: false, @@ -2761,6 +2766,7 @@ where tactic: tactic, separator: ",", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: false, preserve_newline: false, diff --git a/src/imports.rs b/src/imports.rs index f42975ff919..e5dfb12f4c4 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -17,7 +17,7 @@ use Shape; use codemap::SpanUtils; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, Separator, SeparatorTactic}; + ListItem, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; use utils; @@ -496,6 +496,7 @@ fn rewrite_use_list( } else { SeparatorTactic::Never }, + separator_place: SeparatorPlace::Back, shape: nested_shape, ends_with_newline: ends_with_newline, preserve_newline: true, diff --git a/src/items.rs b/src/items.rs index 302d15ee8aa..99b189d341c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -24,7 +24,7 @@ use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, Separator, SeparatorTactic}; + ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, @@ -481,6 +481,7 @@ impl<'a> FmtVisitor<'a> { tactic: DefinitiveListTactic::Vertical, separator: ",", trailing_separator: self.config.trailing_comma(), + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: true, preserve_newline: true, @@ -2267,6 +2268,7 @@ fn rewrite_args( } else { trailing_comma }, + separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, indent), ends_with_newline: tactic.ends_with_newline(context.config.fn_args_layout()), preserve_newline: true, @@ -2462,6 +2464,7 @@ where } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: tactic.ends_with_newline(context.config.generics_indent()), preserve_newline: true, @@ -2574,6 +2577,7 @@ fn rewrite_where_clause_rfc_style( tactic: DefinitiveListTactic::Vertical, separator: ",", trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, shape: clause_shape, ends_with_newline: true, preserve_newline: true, @@ -2685,6 +2689,7 @@ fn rewrite_where_clause( tactic: tactic, separator: ",", trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, offset), ends_with_newline: tactic.ends_with_newline(context.config.where_pred_indent()), preserve_newline: true, diff --git a/src/lists.rs b/src/lists.rs index 3fd9b1ab93c..ea34cdfc480 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -61,6 +61,7 @@ pub struct ListFormatting<'a> { pub tactic: DefinitiveListTactic, pub separator: &'a str, pub trailing_separator: SeparatorTactic, + pub separator_place: SeparatorPlace, pub shape: Shape, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. @@ -70,6 +71,19 @@ pub struct ListFormatting<'a> { pub config: &'a Config, } +impl<'a> ListFormatting<'a> { + pub fn needs_trailing_separator(&self) -> bool { + match self.trailing_separator { + // We always put separator in front. + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => self.tactic == DefinitiveListTactic::Vertical, + SeparatorTactic::Never => { + self.tactic == DefinitiveListTactic::Vertical && self.separator_place.is_front() + } + } + } +} + impl AsRef for ListItem { fn as_ref(&self) -> &ListItem { self @@ -165,6 +179,32 @@ impl Separator { } } +/// Where to put separator. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorPlace { + Front, + Back, +} + +impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); + +impl SeparatorPlace { + pub fn is_front(&self) -> bool { + *self == SeparatorPlace::Front + } + + pub fn is_back(&self) -> bool { + *self == SeparatorPlace::Back + } + + pub fn from_tactic(default: SeparatorPlace, tactic: DefinitiveListTactic) -> SeparatorPlace { + match tactic { + DefinitiveListTactic::Vertical => default, + _ => SeparatorPlace::Back, + } + } +} + pub fn definitive_tactic( items: I, tactic: ListTactic, @@ -214,11 +254,12 @@ where // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. - let mut trailing_separator = needs_trailing_separator(formatting.trailing_separator, tactic); + let mut trailing_separator = formatting.needs_trailing_separator(); let mut result = String::new(); let cloned_items = items.clone(); let mut iter = items.into_iter().enumerate().peekable(); let mut item_max_width: Option = None; + let mut sep_place = SeparatorPlace::from_tactic(formatting.separator_place, tactic); let mut line_len = 0; let indent_str = &formatting.shape.indent.to_string(formatting.config); @@ -258,13 +299,16 @@ where result.push('\n'); result.push_str(indent_str); line_len = 0; - if tactic == DefinitiveListTactic::Mixed && formatting.ends_with_newline { + if formatting.ends_with_newline { if last { separate = true; } else { trailing_separator = true; } } + sep_place = formatting.separator_place; + } else { + sep_place = SeparatorPlace::Back; } if line_len > 0 { @@ -314,6 +358,10 @@ where item_max_width = None; } + if separate && sep_place.is_front() && !first { + result.push_str(formatting.separator.trim()); + result.push(' '); + } result.push_str(&inner_item[..]); // Post-comments @@ -330,7 +378,7 @@ where result.push_str(&formatted_comment); } - if separate { + if separate && sep_place.is_back() { result.push_str(formatting.separator); } @@ -642,17 +690,6 @@ where } } -fn needs_trailing_separator( - separator_tactic: SeparatorTactic, - list_tactic: DefinitiveListTactic, -) -> bool { - match separator_tactic { - SeparatorTactic::Always => true, - SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical, - SeparatorTactic::Never => false, - } -} - /// Returns the count and total width of the list items. fn calculate_width(items: I) -> (usize, usize) where @@ -762,6 +799,7 @@ pub fn struct_lit_formatting<'a>( } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: shape, ends_with_newline: ends_with_newline, preserve_newline: true, diff --git a/src/types.rs b/src/types.rs index 61ef03b1687..455c4ad5ae4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -23,7 +23,7 @@ use config::{IndentStyle, Style, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; use items::{format_generics_item_list, generics_shape_from_config}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, - SeparatorTactic}; + SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp, wrap_str}; @@ -365,6 +365,7 @@ where } else { context.config.trailing_comma() }, + separator_place: SeparatorPlace::Back, shape: list_shape, ends_with_newline: tactic.ends_with_newline(context.config.fn_call_style()), preserve_newline: true, diff --git a/src/vertical.rs b/src/vertical.rs index 1a62cad7757..5c48acbb9d0 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -20,7 +20,8 @@ use codemap::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, + SeparatorPlace}; use rewrite::{Rewrite, RewriteContext}; use utils::{contains_skip, is_attributes_extendable, mk_sp}; @@ -257,6 +258,7 @@ fn rewrite_aligned_items_inner( tactic: tactic, separator: ",", trailing_separator: context.config.trailing_comma(), + separator_place: SeparatorPlace::Back, shape: item_shape, ends_with_newline: true, preserve_newline: true, diff --git a/src/visitor.rs b/src/visitor.rs index c5d91fee5b3..5777a871d05 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -24,7 +24,8 @@ use config::{BraceStyle, Config}; use expr::{format_expr, ExprType}; use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, rewrite_type_alias}; -use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorTactic}; +use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, + SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; @@ -917,6 +918,7 @@ impl Rewrite for ast::MetaItem { tactic: DefinitiveListTactic::Mixed, separator: ",", trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, shape: item_shape, ends_with_newline: false, preserve_newline: false, -- cgit 1.4.1-3-g733a5 From 2471248370fc4183e5bf32ed56725682f170095c Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 18 Aug 2017 16:31:13 -0700 Subject: Fix typo in comment line overflow message s/error_on_lineoverflow_comments/error_on_line_overflow_comments --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3ac1c3e4cf7..1b19689b660 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -486,7 +486,7 @@ impl FormattingError { fn msg_suffix(&self) -> String { match self.kind { ErrorKind::LineOverflow(..) if self.is_comment => format!( - "use `error_on_lineoverflow_comments = false` to suppress \ + "use `error_on_line_overflow_comments = false` to suppress \ the warning against line comments\n", ), _ => String::from(""), -- cgit 1.4.1-3-g733a5 From b2d10e39b487bdff2f2f6899b7732e29270a47ed Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 18 Aug 2017 17:10:50 -0700 Subject: Fix typos in comment --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0276b68ac9f..b19e632b76e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2786,7 +2786,7 @@ where { debug!("rewrite_tuple {:?}", shape); if context.use_block_indent() { - // We use the same rule as funcation call for rewriting tuple. + // We use the same rule as function calls for rewriting tuples. let force_trailing_comma = if context.inside_macro { span_ends_with_comma(context, span) } else { -- cgit 1.4.1-3-g733a5 From 1c9d044c05d08f8d5d8bb7633329facc25aae0eb Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sat, 19 Aug 2017 11:51:24 -0700 Subject: Add attributes_on_same_line_as_{field,variant} --- Configurations.md | 60 ++++++++++++++++++++++ src/config.rs | 4 ++ src/items.rs | 15 +++--- ...nfigs-attributes_on_same_line_as_field-false.rs | 11 ++++ ...onfigs-attributes_on_same_line_as_field-true.rs | 11 ++++ ...igs-attributes_on_same_line_as_variant-false.rs | 11 ++++ ...figs-attributes_on_same_line_as_variant-true.rs | 11 ++++ ...nfigs-attributes_on_same_line_as_field-false.rs | 11 ++++ ...onfigs-attributes_on_same_line_as_field-true.rs | 8 +++ ...igs-attributes_on_same_line_as_variant-false.rs | 11 ++++ ...figs-attributes_on_same_line_as_variant-true.rs | 8 +++ 11 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 tests/source/configs-attributes_on_same_line_as_field-false.rs create mode 100644 tests/source/configs-attributes_on_same_line_as_field-true.rs create mode 100644 tests/source/configs-attributes_on_same_line_as_variant-false.rs create mode 100644 tests/source/configs-attributes_on_same_line_as_variant-true.rs create mode 100644 tests/target/configs-attributes_on_same_line_as_field-false.rs create mode 100644 tests/target/configs-attributes_on_same_line_as_field-true.rs create mode 100644 tests/target/configs-attributes_on_same_line_as_variant-false.rs create mode 100644 tests/target/configs-attributes_on_same_line_as_variant-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index a8d8c353c27..f7966357940 100644 --- a/Configurations.md +++ b/Configurations.md @@ -100,6 +100,66 @@ let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", " #### Lines longer than `array_width`: See [`array_layout`](#array_layout). +## `attributes_on_same_line_as_field` + +Try to put attributes on the same line as fields + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `true` + +```rust +struct Lorem { + #[serde(rename = "Ipsum")] ipsum: usize, + #[serde(rename = "Dolor")] dolor: usize, + #[serde(rename = "Amet")] amet: usize, +} +``` + +#### `false` + +```rust +struct Lorem { + #[serde(rename = "Ipsum")] + ipsum: usize, + #[serde(rename = "Dolor")] + dolor: usize, + #[serde(rename = "Amet")] + amet: usize, +} +``` + +## `attributes_on_same_line_as_variant` + +Try to put attributes on the same line as variants + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `true` + +```rust +enum Lorem { + #[serde(skip_serializing)] Ipsum, + #[serde(skip_serializing)] Dolor, + #[serde(skip_serializing)] Amet, +} +``` + +#### `false` + +```rust +enum Lorem { + #[serde(skip_serializing)] + Ipsum, + #[serde(skip_serializing)] + Dolor, + #[serde(skip_serializing)] + Amet, +} +``` + ## `chain_indent` Indentation of chain diff --git a/src/config.rs b/src/config.rs index 11d64dc073f..f3e4c462893 100644 --- a/src/config.rs +++ b/src/config.rs @@ -609,6 +609,10 @@ create_config! { threshold."; remove_blank_lines_at_start_or_end_of_block: bool, true, "Remove blank lines at start or end of a block"; + attributes_on_same_line_as_field: bool, true, + "Try to put attributes on the same line as fields."; + attributes_on_same_line_as_variant: bool, true, + "Try to put attributes on the same line as variants in enum declarations."; } #[cfg(test)] diff --git a/src/items.rs b/src/items.rs index 302d15ee8aa..156bab05c9c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -548,13 +548,16 @@ impl<'a> FmtVisitor<'a> { }, }; + let attrs_extendable = attrs_str.is_empty() || + (context.config.attributes_on_same_line_as_variant() && + is_attributes_extendable(&attrs_str)); combine_strs_with_missing_comments( &context, &attrs_str, &variant_body, span, shape, - is_attributes_extendable(&attrs_str), + attrs_extendable, ) } } @@ -1413,6 +1416,8 @@ pub fn rewrite_struct_field( let prefix = try_opt!(rewrite_struct_field_prefix(context, field)); let attrs_str = try_opt!(field.attrs.rewrite(context, shape)); + let attrs_extendable = attrs_str.is_empty() || + (context.config.attributes_on_same_line_as_field() && is_attributes_extendable(&attrs_str)); let missing_span = if field.attrs.is_empty() { mk_sp(field.span.lo, field.span.lo) } else { @@ -1430,7 +1435,7 @@ pub fn rewrite_struct_field( &prefix, missing_span, shape, - is_attributes_extendable(&attrs_str), + attrs_extendable, )); let overhead = last_line_width(&attr_prefix); let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); @@ -1438,9 +1443,7 @@ pub fn rewrite_struct_field( spacing.push(' '); } // In this extreme case we will be missing a space betweeen an attribute and a field. - if prefix.is_empty() && !attrs_str.is_empty() && is_attributes_extendable(&attrs_str) && - spacing.is_empty() - { + if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { spacing.push(' '); } let ty_rewritten = rewrite_struct_field_type(context, overhead, field, &spacing, shape); @@ -1488,7 +1491,7 @@ pub fn rewrite_struct_field( &field_str, missing_span, shape, - is_attributes_extendable(&attrs_str), + attrs_extendable, ) } diff --git a/tests/source/configs-attributes_on_same_line_as_field-false.rs b/tests/source/configs-attributes_on_same_line_as_field-false.rs new file mode 100644 index 00000000000..ba63fd5caa0 --- /dev/null +++ b/tests/source/configs-attributes_on_same_line_as_field-false.rs @@ -0,0 +1,11 @@ +// rustfmt-attributes_on_same_line_as_field: false +// Option to place attributes on the same line as fields where possible + +struct Lorem { + #[ serde(rename = "Ipsum") ] + ipsum: usize, + #[ serde(rename = "Dolor") ] + dolor: usize, + #[ serde(rename = "Amet") ] + amet: usize, +} diff --git a/tests/source/configs-attributes_on_same_line_as_field-true.rs b/tests/source/configs-attributes_on_same_line_as_field-true.rs new file mode 100644 index 00000000000..3258c754e50 --- /dev/null +++ b/tests/source/configs-attributes_on_same_line_as_field-true.rs @@ -0,0 +1,11 @@ +// rustfmt-attributes_on_same_line_as_field: true +// Option to place attributes on the same line as fields where possible + +struct Lorem { + #[ serde(rename = "Ipsum") ] + ipsum: usize, + #[ serde(rename = "Dolor") ] + dolor: usize, + #[ serde(rename = "Amet") ] + amet: usize, +} diff --git a/tests/source/configs-attributes_on_same_line_as_variant-false.rs b/tests/source/configs-attributes_on_same_line_as_variant-false.rs new file mode 100644 index 00000000000..d3456b7087c --- /dev/null +++ b/tests/source/configs-attributes_on_same_line_as_variant-false.rs @@ -0,0 +1,11 @@ +// rustfmt-attributes_on_same_line_as_variant: false +// Option to place attributes on the same line as variants where possible + +enum Lorem { + #[ serde(skip_serializing) ] + Ipsum, + #[ serde(skip_serializing) ] + Dolor, + #[ serde(skip_serializing) ] + Amet, +} diff --git a/tests/source/configs-attributes_on_same_line_as_variant-true.rs b/tests/source/configs-attributes_on_same_line_as_variant-true.rs new file mode 100644 index 00000000000..0f7d98f200a --- /dev/null +++ b/tests/source/configs-attributes_on_same_line_as_variant-true.rs @@ -0,0 +1,11 @@ +// rustfmt-attributes_on_same_line_as_variant: true +// Option to place attributes on the same line as variants where possible + +enum Lorem { + #[ serde(skip_serializing) ] + Ipsum, + #[ serde(skip_serializing) ] + Dolor, + #[ serde(skip_serializing) ] + Amet, +} diff --git a/tests/target/configs-attributes_on_same_line_as_field-false.rs b/tests/target/configs-attributes_on_same_line_as_field-false.rs new file mode 100644 index 00000000000..7cb074d13a9 --- /dev/null +++ b/tests/target/configs-attributes_on_same_line_as_field-false.rs @@ -0,0 +1,11 @@ +// rustfmt-attributes_on_same_line_as_field: false +// Option to place attributes on the same line as fields where possible + +struct Lorem { + #[serde(rename = "Ipsum")] + ipsum: usize, + #[serde(rename = "Dolor")] + dolor: usize, + #[serde(rename = "Amet")] + amet: usize, +} diff --git a/tests/target/configs-attributes_on_same_line_as_field-true.rs b/tests/target/configs-attributes_on_same_line_as_field-true.rs new file mode 100644 index 00000000000..3261fa24ea0 --- /dev/null +++ b/tests/target/configs-attributes_on_same_line_as_field-true.rs @@ -0,0 +1,8 @@ +// rustfmt-attributes_on_same_line_as_field: true +// Option to place attributes on the same line as fields where possible + +struct Lorem { + #[serde(rename = "Ipsum")] ipsum: usize, + #[serde(rename = "Dolor")] dolor: usize, + #[serde(rename = "Amet")] amet: usize, +} diff --git a/tests/target/configs-attributes_on_same_line_as_variant-false.rs b/tests/target/configs-attributes_on_same_line_as_variant-false.rs new file mode 100644 index 00000000000..3442a10915a --- /dev/null +++ b/tests/target/configs-attributes_on_same_line_as_variant-false.rs @@ -0,0 +1,11 @@ +// rustfmt-attributes_on_same_line_as_variant: false +// Option to place attributes on the same line as variants where possible + +enum Lorem { + #[serde(skip_serializing)] + Ipsum, + #[serde(skip_serializing)] + Dolor, + #[serde(skip_serializing)] + Amet, +} diff --git a/tests/target/configs-attributes_on_same_line_as_variant-true.rs b/tests/target/configs-attributes_on_same_line_as_variant-true.rs new file mode 100644 index 00000000000..0bced842c75 --- /dev/null +++ b/tests/target/configs-attributes_on_same_line_as_variant-true.rs @@ -0,0 +1,8 @@ +// rustfmt-attributes_on_same_line_as_variant: true +// Option to place attributes on the same line as variants where possible + +enum Lorem { + #[serde(skip_serializing)] Ipsum, + #[serde(skip_serializing)] Dolor, + #[serde(skip_serializing)] Amet, +} -- cgit 1.4.1-3-g733a5 From baafa4f011d6c50f51f9c1de718e37d23a533373 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sat, 19 Aug 2017 14:57:01 -0700 Subject: Fix wrapping of bounds in associated types Bounds were wrapped to the full width of the line rather then the width available after the "type ...: ", resulting in rustfmt unnecessarily producing lines that were longer than the maximum width. --- src/items.rs | 3 ++- tests/source/associated-types-bounds-wrapping.rs | 6 ++++++ tests/target/associated-types-bounds-wrapping.rs | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/source/associated-types-bounds-wrapping.rs create mode 100644 tests/target/associated-types-bounds-wrapping.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 302d15ee8aa..0eed4204d45 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1551,7 +1551,8 @@ pub fn rewrite_associated_type( let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { - let shape = Shape::indented(indent, context.config); + // 2 = ": ".len() + let shape = try_opt!(Shape::indented(indent, context.config).offset_left(prefix.len() + 2)); let bounds: &[_] = ty_param_bounds; let bound_str = try_opt!( bounds diff --git a/tests/source/associated-types-bounds-wrapping.rs b/tests/source/associated-types-bounds-wrapping.rs new file mode 100644 index 00000000000..8f5e2172569 --- /dev/null +++ b/tests/source/associated-types-bounds-wrapping.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 100 +// Test proper wrapping of long associated type bounds + +pub trait HttpService { + type WsService: 'static + Service; +} diff --git a/tests/target/associated-types-bounds-wrapping.rs b/tests/target/associated-types-bounds-wrapping.rs new file mode 100644 index 00000000000..d5b94a5e869 --- /dev/null +++ b/tests/target/associated-types-bounds-wrapping.rs @@ -0,0 +1,7 @@ +// rustfmt-max_width: 100 +// Test proper wrapping of long associated type bounds + +pub trait HttpService { + type WsService: 'static + + Service; +} -- cgit 1.4.1-3-g733a5 From 3d1b6fe1c604abc3ba3efb3274861b903e63f147 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 20 Aug 2017 23:23:13 +0900 Subject: Remove count_missing_closing_parens() --- src/visitor.rs | 56 ++------------------------------------------------------ 1 file changed, 2 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index c5d91fee5b3..309148d7c7b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -837,52 +837,6 @@ impl Rewrite for ast::NestedMetaItem { } } -fn count_missing_closing_parens(s: &str) -> u32 { - let mut op_parens: u32 = 0; - let mut cl_parens: u32 = 0; - - #[derive(Eq, PartialEq)] - pub enum SnippetState { - Normal, - InsideStr, - InsideBulletComment, - InsideSingleLineComment, - } - - let mut state = SnippetState::Normal; - let mut iter = s.chars().peekable(); - let mut prev_char: Option = None; - while let Some(c) = iter.next() { - let next_char = iter.peek(); - match c { - '/' if state == SnippetState::Normal => match next_char { - Some(&'*') => state = SnippetState::InsideBulletComment, - Some(&'/') if prev_char.map_or(true, |c| c != '*') => { - state = SnippetState::InsideSingleLineComment; - } - _ => (), - }, - '*' if state == SnippetState::InsideBulletComment && - next_char.map_or(false, |c| *c == '/') => - { - state = SnippetState::Normal; - } - '\n' if state == SnippetState::InsideSingleLineComment => state = SnippetState::Normal, - '"' if state == SnippetState::InsideStr && prev_char.map_or(false, |c| c != '\\') => { - state = SnippetState::Normal; - } - '"' if state == SnippetState::Normal && prev_char.map_or(false, |c| c != '\\') => { - state = SnippetState::InsideStr - } - '(' if state == SnippetState::Normal => op_parens += 1, - ')' if state == SnippetState::Normal => cl_parens += 1, - _ => (), - } - prev_char = Some(c); - } - op_parens.checked_sub(cl_parens).unwrap_or(0) -} - impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { @@ -895,21 +849,15 @@ impl Rewrite for ast::MetaItem { .shrink_left(name.len() + 3) .and_then(|s| s.sub_width(2)) ); - let hi = self.span.hi + - BytePos(count_missing_closing_parens(&context.snippet(self.span))); let items = itemize_list( context.codemap, list.iter(), ")", |nested_meta_item| nested_meta_item.span.lo, - // FIXME: Span from MetaItem is missing closing parens. - |nested_meta_item| { - let snippet = context.snippet(nested_meta_item.span); - nested_meta_item.span.hi + BytePos(count_missing_closing_parens(&snippet)) - }, + |nested_meta_item| nested_meta_item.span.hi, |nested_meta_item| nested_meta_item.rewrite(context, item_shape), self.span.lo, - hi, + self.span.hi, false, ); let item_vec = items.collect::>(); -- cgit 1.4.1-3-g733a5 From a18a40cbc141ad1437796a53b1d1a893c5cb5dff Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 21 Aug 2017 23:19:01 +0900 Subject: Add indent to macro we could not format --- src/macros.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++++---- tests/source/macros.rs | 9 +++++++ tests/target/macros.rs | 12 ++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index ae2a16510b8..b1f740e6a87 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -19,6 +19,8 @@ // List-like invocations with parentheses will be formatted as function calls, // and those with brackets will be formatted as array literals. +use std::iter::repeat; + use syntax::ast; use syntax::codemap::BytePos; use syntax::parse::new_parser_from_tts; @@ -27,7 +29,7 @@ use syntax::symbol; use syntax::tokenstream::TokenStream; use syntax::util::ThinVec; -use Shape; +use {Indent, Shape}; use codemap::SpanUtils; use comment::{contains_comment, FindUncommented}; use expr::{rewrite_array, rewrite_call_inner}; @@ -116,14 +118,14 @@ pub fn rewrite_macro( Ok(expr) => { // Recovered errors. if context.parse_session.span_diagnostic.has_errors() { - return Some(context.snippet(mac.span)); + return indent_macro_snippet(&context.snippet(mac.span), shape.indent); } expr } Err(mut e) => { e.cancel(); - return Some(context.snippet(mac.span)); + return indent_macro_snippet(&context.snippet(mac.span), shape.indent); } }; @@ -242,7 +244,7 @@ pub fn rewrite_macro( } MacroStyle::Braces => { // Skip macro invocations with braces, for now. - None + indent_macro_snippet(&context.snippet(mac.span), shape.indent) } } } @@ -280,3 +282,58 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { MacroStyle::Braces } } + +/// Indent each line according to the specified `indent`. +/// e.g. +/// ```rust +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +/// ), +/// } +/// ``` +/// will become +/// ```rust +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +// ), +/// } +/// ``` +fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option { + let min_prefix_space_width = + try_opt!(macro_str.lines().skip(1).map(get_prefix_space_width).min()); + + let mut lines = macro_str.lines(); + let first_line = try_opt!(lines.next()); + + Some( + String::from(first_line) + "\n" + + &lines + .map(|line| { + let new_indent_width = indent.width() + + get_prefix_space_width(line) + .checked_sub(min_prefix_space_width) + .unwrap_or(0); + repeat_white_space(new_indent_width) + line.trim() + }) + .collect::>() + .join("\n"), + ) +} + +fn get_prefix_space_width(s: &str) -> usize { + s.chars().position(|c| c != ' ').unwrap_or(0) +} + +fn repeat_white_space(ws_count: usize) -> String { + repeat(" ").take(ws_count).collect::() +} diff --git a/tests/source/macros.rs b/tests/source/macros.rs index e3d7229a0e1..d8e6efe9199 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -112,6 +112,7 @@ fn issue1178() { foo!(#[doc = "bar"] baz); } + fn issue1739() { sql_function!(add_rss_item, add_rss_item_t, @@ -125,6 +126,14 @@ fn issue1739() { .par_map_inplace(|el| *el = 0.); } +fn issue_1885() { + let threads = people.into_iter().map(|name| { + chan_select! { + rx.recv() => {} + } + }).collect::>(); +} + // Put the following tests with macro invocations whose arguments cannot be parsed as expressioins // at the end of the file for now. diff --git a/tests/target/macros.rs b/tests/target/macros.rs index f80f6843fe2..21c0b983ff9 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -146,6 +146,7 @@ fn issue1178() { baz ); } + fn issue1739() { sql_function!( add_rss_item, @@ -166,6 +167,17 @@ fn issue1739() { ]).par_map_inplace(|el| *el = 0.); } +fn issue_1885() { + let threads = people + .into_iter() + .map(|name| { + chan_select! { + rx.recv() => {} + } + }) + .collect::>(); +} + // Put the following tests with macro invocations whose arguments cannot be parsed as expressioins // at the end of the file for now. -- cgit 1.4.1-3-g733a5 From 411c73c12fa014c568c2ff0b0141042e500910d7 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 18 Aug 2017 16:50:39 -0700 Subject: Add multiline_{closure,match_arm}_forces_block multiline_closure_forces_block = false (default): result.and_then(|maybe_value| match maybe_value { None => ..., Some(value) => ..., }) multiline_closure_forces_block = true: result.and_then(|maybe_value| { match maybe_value { None => ..., Some(value) => ..., } }) multiline_match_arm_forces_block = false (default): match lorem { None => if ipsum { println!("Hello World"); }, Some(dolor) => ..., } multiline_match_arm_forces_block = true: match lorem { None => { if ipsum { println!("Hello World"); } } Some(dolor) => ..., } --- Configurations.md | 58 ++++++++++++++++++++++ src/config.rs | 4 ++ src/expr.rs | 19 ++++++- ...configs-multiline_closure_forces_block-false.rs | 11 ++++ .../configs-multiline_closure_forces_block-true.rs | 9 ++++ ...nfigs-multiline_match_arm_forces_block-false.rs | 13 +++++ ...onfigs-multiline_match_arm_forces_block-true.rs | 11 ++++ ...configs-multiline_closure_forces_block-false.rs | 9 ++++ .../configs-multiline_closure_forces_block-true.rs | 11 ++++ ...nfigs-multiline_match_arm_forces_block-false.rs | 11 ++++ ...onfigs-multiline_match_arm_forces_block-true.rs | 13 +++++ 11 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 tests/source/configs-multiline_closure_forces_block-false.rs create mode 100644 tests/source/configs-multiline_closure_forces_block-true.rs create mode 100644 tests/source/configs-multiline_match_arm_forces_block-false.rs create mode 100644 tests/source/configs-multiline_match_arm_forces_block-true.rs create mode 100644 tests/target/configs-multiline_closure_forces_block-false.rs create mode 100644 tests/target/configs-multiline_closure_forces_block-true.rs create mode 100644 tests/target/configs-multiline_match_arm_forces_block-false.rs create mode 100644 tests/target/configs-multiline_match_arm_forces_block-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 27c1c47280c..13a704240c3 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1265,6 +1265,64 @@ Maximum width of each line See also [`error_on_line_overflow`](#error_on_line_overflow). +## `multiline_closure_forces_block` + +Force multiline closure bodies to be wrapped in a block + +- **Default value**: `false` +- **Possible values**: `false`, `true` + +#### `false`: + +```rust +result.and_then(|maybe_value| match maybe_value { + None => ..., + Some(value) => ..., +}) +``` + +#### `true`: + +```rust +result.and_then(|maybe_value| { + match maybe_value { + None => ..., + Some(value) => ..., + } +}) +``` + +## `multiline_match_arm_forces_block` + +Force multiline match arm bodies to be wrapped in a block + +- **Default value**: `false` +- **Possible values**: `false`, `true` + +#### `false`: + +```rust +match lorem { + None => if ipsum { + println!("Hello World"); + }, + Some(dolor) => ..., +} +``` + +#### `true`: + +```rust +match lorem { + None => { + if ipsum { + println!("Hello World"); + } + } + Some(dolor) => ..., +} +``` + ## `newline_style` Unix or Windows line endings diff --git a/src/config.rs b/src/config.rs index 02fd111fd9a..9659f19377d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -615,6 +615,10 @@ create_config! { "Try to put attributes on the same line as fields."; attributes_on_same_line_as_variant: bool, true, "Try to put attributes on the same line as variants in enum declarations."; + multiline_closure_forces_block: bool, false, + "Force multiline closure bodies to be wrapped in a block"; + multiline_match_arm_forces_block: bool, false, + "Force multiline match arm bodies to be wrapped in a block"; } #[cfg(test)] diff --git a/src/expr.rs b/src/expr.rs index 5e8c66663c4..a42ab973e0d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -690,6 +690,13 @@ fn rewrite_closure_expr( if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { rewrite = and_one_line(rewrite); } + rewrite = rewrite.and_then(|rw| { + if context.config.multiline_closure_forces_block() && rw.contains('\n') { + None + } else { + Some(rw) + } + }); rewrite.map(|rw| format!("{} {}", prefix, rw)) } @@ -1690,12 +1697,20 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - (expr.can_be_overflowed(context, 1), &**expr) + ( + !context.config.multiline_match_arm_forces_block() && + expr.can_be_overflowed(context, 1), + &**expr, + ) } else { (false, &*body) } } - _ => (body.can_be_overflowed(context, 1), &*body), + _ => ( + !context.config.multiline_match_arm_forces_block() && + body.can_be_overflowed(context, 1), + &*body, + ), } } diff --git a/tests/source/configs-multiline_closure_forces_block-false.rs b/tests/source/configs-multiline_closure_forces_block-false.rs new file mode 100644 index 00000000000..e885dff5ee6 --- /dev/null +++ b/tests/source/configs-multiline_closure_forces_block-false.rs @@ -0,0 +1,11 @@ +// rustfmt-multiline_closure_forces_block: false +// Option forces multiline closure bodies to be wrapped in a block + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/tests/source/configs-multiline_closure_forces_block-true.rs b/tests/source/configs-multiline_closure_forces_block-true.rs new file mode 100644 index 00000000000..f267466ac66 --- /dev/null +++ b/tests/source/configs-multiline_closure_forces_block-true.rs @@ -0,0 +1,9 @@ +// rustfmt-multiline_closure_forces_block: true +// Option forces multiline closure bodies to be wrapped in a block + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/tests/source/configs-multiline_match_arm_forces_block-false.rs b/tests/source/configs-multiline_match_arm_forces_block-false.rs new file mode 100644 index 00000000000..4cbec0c7c1c --- /dev/null +++ b/tests/source/configs-multiline_match_arm_forces_block-false.rs @@ -0,0 +1,13 @@ +// rustfmt-multiline_match_arm_forces_block: false +// Option forces multiline match arm bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} diff --git a/tests/source/configs-multiline_match_arm_forces_block-true.rs b/tests/source/configs-multiline_match_arm_forces_block-true.rs new file mode 100644 index 00000000000..602076a4e74 --- /dev/null +++ b/tests/source/configs-multiline_match_arm_forces_block-true.rs @@ -0,0 +1,11 @@ +// rustfmt-multiline_match_arm_forces_block: true +// Option forces multiline match arm bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => if ipsum { + println!("dolor"); + }, + Lorem::Dolor => println!("amet"), + } +} diff --git a/tests/target/configs-multiline_closure_forces_block-false.rs b/tests/target/configs-multiline_closure_forces_block-false.rs new file mode 100644 index 00000000000..7fb3d597da1 --- /dev/null +++ b/tests/target/configs-multiline_closure_forces_block-false.rs @@ -0,0 +1,9 @@ +// rustfmt-multiline_closure_forces_block: false +// Option forces multiline closure bodies to be wrapped in a block + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/tests/target/configs-multiline_closure_forces_block-true.rs b/tests/target/configs-multiline_closure_forces_block-true.rs new file mode 100644 index 00000000000..01e2de43527 --- /dev/null +++ b/tests/target/configs-multiline_closure_forces_block-true.rs @@ -0,0 +1,11 @@ +// rustfmt-multiline_closure_forces_block: true +// Option forces multiline closure bodies to be wrapped in a block + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/tests/target/configs-multiline_match_arm_forces_block-false.rs b/tests/target/configs-multiline_match_arm_forces_block-false.rs new file mode 100644 index 00000000000..3c4c1470b0f --- /dev/null +++ b/tests/target/configs-multiline_match_arm_forces_block-false.rs @@ -0,0 +1,11 @@ +// rustfmt-multiline_match_arm_forces_block: false +// Option forces multiline match arm bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => if ipsum { + println!("dolor"); + }, + Lorem::Dolor => println!("amet"), + } +} diff --git a/tests/target/configs-multiline_match_arm_forces_block-true.rs b/tests/target/configs-multiline_match_arm_forces_block-true.rs new file mode 100644 index 00000000000..c36d59c315c --- /dev/null +++ b/tests/target/configs-multiline_match_arm_forces_block-true.rs @@ -0,0 +1,13 @@ +// rustfmt-multiline_match_arm_forces_block: true +// Option forces multiline match arm bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} -- cgit 1.4.1-3-g733a5 From 5dafcc24e46a05713c47235d51ac2d50c7899feb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 Aug 2017 23:20:32 +0900 Subject: Add merge_derives config option --- Configurations.md | 46 +++++++++++++++++++++++------- src/config.rs | 1 + src/lists.rs | 4 +-- src/visitor.rs | 44 ++++++++++++++++++++++++++-- tests/source/configs-merge_derives-true.rs | 10 +++++++ tests/target/configs-merge_derives-true.rs | 8 ++++++ 6 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 tests/source/configs-merge_derives-true.rs create mode 100644 tests/target/configs-merge_derives-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 13a704240c3..373447bf24f 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1230,7 +1230,7 @@ Put a match sub-patterns' separator (`|`) in front or back. - **Default value**: `"Back"` - **Possible values**: `"Back"`, `"Front"` -#### `"Back"` +#### `"Back"`: ```rust match m { @@ -1243,7 +1243,7 @@ match m { } ``` -#### `Front` +#### `Front`: ```rust match m { @@ -1265,25 +1265,42 @@ Maximum width of each line See also [`error_on_line_overflow`](#error_on_line_overflow). -## `multiline_closure_forces_block` +## `merge_derives` -Force multiline closure bodies to be wrapped in a block +Merge multiple derives into a single one. -- **Default value**: `false` -- **Possible values**: `false`, `true` +- **Default value**: `true` +- **Possible values**: `true`, `false` + +*Note*: The merged derives will be put after all other attributes or doc comments. + +#### `true`: + +```rust +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum Foo {} +``` #### `false`: ```rust -result.and_then(|maybe_value| match maybe_value { - None => ..., - Some(value) => ..., -}) +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum Foo {} ``` +## `multiline_closure_forces_block` + +Force multiline closure bodies to be wrapped in a block + +- **Default value**: `false` +- **Possible values**: `false`, `true` + #### `true`: ```rust + result.and_then(|maybe_value| { match maybe_value { None => ..., @@ -1292,6 +1309,15 @@ result.and_then(|maybe_value| { }) ``` +#### `false`: + +```rust +result.and_then(|maybe_value| match maybe_value { + None => ..., + Some(value) => ..., +}) +``` + ## `multiline_match_arm_forces_block` Force multiline match arm bodies to be wrapped in a block diff --git a/src/config.rs b/src/config.rs index 9659f19377d..31eccf24941 100644 --- a/src/config.rs +++ b/src/config.rs @@ -619,6 +619,7 @@ create_config! { "Force multiline closure bodies to be wrapped in a block"; multiline_match_arm_forces_block: bool, false, "Force multiline match arm bodies to be wrapped in a block"; + merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one"; } #[cfg(test)] diff --git a/src/lists.rs b/src/lists.rs index ea34cdfc480..8787850634e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -19,10 +19,10 @@ use config::{Config, IndentStyle}; use rewrite::RewriteContext; use utils::{first_line_width, last_line_width, mk_sp}; -#[derive(Eq, PartialEq, Debug, Copy, Clone)] /// Formatting tactic for lists. This will be cast down to a /// DefinitiveListTactic depending on the number and length of the items and /// their comments. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { // One item per row. Vertical, @@ -144,8 +144,8 @@ impl ListItem { } } -#[derive(Eq, PartialEq, Debug, Copy, Clone)] /// The definitive formatting tactic for lists. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum DefinitiveListTactic { Vertical, Horizontal, diff --git a/src/visitor.rs b/src/visitor.rs index 49772f97e2d..b0df0bcaf9b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -925,6 +925,8 @@ impl<'a> Rewrite for [ast::Attribute] { } let indent = shape.indent.to_string(context.config); + let mut derive_args = Vec::new(); + for (i, a) in self.iter().enumerate() { let a_str = try_opt!(a.rewrite(context, shape)); @@ -956,13 +958,51 @@ impl<'a> Rewrite for [ast::Attribute] { } // Write the attribute itself. - result.push_str(&a_str); + if context.config.merge_derives() { + if let Some(mut args) = get_derive_args(context, a) { + // If the attribute is `#[derive(...)]`, take the arguments and skip rewriting. + // We will merge the all arguments into a single `#[derive(...)]` at last. + derive_args.append(&mut args); + } else { + result.push_str(&a_str); + + if i < self.len() - 1 { + result.push('\n'); + } + } + } else { + result.push_str(&a_str); - if i < self.len() - 1 { + if i < self.len() - 1 { + result.push('\n'); + } + } + } + + // Add merged `#[derive(...)]` at last. + if context.config.merge_derives() && !derive_args.is_empty() { + if !result.is_empty() && !result.ends_with('\n') { + result.push_str(&indent); result.push('\n'); } + result.push_str(&format!("#[derive({})]", derive_args.join(", "))); } Some(result) } } + +/// Returns the arguments of `#[derive(...)]`. +fn get_derive_args(context: &RewriteContext, attr: &ast::Attribute) -> Option> { + attr.meta().and_then(|meta_item| match meta_item.node { + ast::MetaItemKind::List(ref args) if meta_item.name.as_str() == "derive" => { + // Every argument of `derive` should be `NestedMetaItemKind::Literal`. + Some( + args.iter() + .map(|a| context.snippet(a.span)) + .collect::>(), + ) + } + _ => None, + }) +} diff --git a/tests/source/configs-merge_derives-true.rs b/tests/source/configs-merge_derives-true.rs new file mode 100644 index 00000000000..804a48c43c0 --- /dev/null +++ b/tests/source/configs-merge_derives-true.rs @@ -0,0 +1,10 @@ +// rustfmt-merge_derives: true +// Merge multiple derives to a single one. + +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} diff --git a/tests/target/configs-merge_derives-true.rs b/tests/target/configs-merge_derives-true.rs new file mode 100644 index 00000000000..8cf7b9a346d --- /dev/null +++ b/tests/target/configs-merge_derives-true.rs @@ -0,0 +1,8 @@ +// rustfmt-merge_derives: true +// Merge multiple derives to a single one. + +#[bar] +#[foo] +#[foobar] +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum Foo {} -- cgit 1.4.1-3-g733a5 From 669a139956681edf13c9fa21f08fa27979d5c345 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 24 Aug 2017 23:46:22 +0900 Subject: Only merge consecutive derives --- Configurations.md | 2 -- src/visitor.rs | 46 ++++++++++++++++++------------ tests/source/configs-merge_derives-true.rs | 36 +++++++++++++++++++++++ tests/target/configs-merge_derives-true.rs | 34 +++++++++++++++++++++- 4 files changed, 96 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 373447bf24f..972c2e58241 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1272,8 +1272,6 @@ Merge multiple derives into a single one. - **Default value**: `true` - **Possible values**: `true`, `false` -*Note*: The merged derives will be put after all other attributes or doc comments. - #### `true`: ```rust diff --git a/src/visitor.rs b/src/visitor.rs index b0df0bcaf9b..2f6a503dc13 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -927,7 +927,8 @@ impl<'a> Rewrite for [ast::Attribute] { let mut derive_args = Vec::new(); - for (i, a) in self.iter().enumerate() { + let mut iter = self.iter().enumerate().peekable(); + while let Some((i, a)) = iter.next() { let a_str = try_opt!(a.rewrite(context, shape)); // Write comments and blank lines between attributes. @@ -954,44 +955,51 @@ impl<'a> Rewrite for [ast::Attribute] { } else if multi_line { result.push('\n'); } - result.push_str(&indent); + if derive_args.is_empty() { + result.push_str(&indent); + } } // Write the attribute itself. + let mut insert_new_line = true; if context.config.merge_derives() { + // If the attribute is `#[derive(...)]`, take the arguments. if let Some(mut args) = get_derive_args(context, a) { - // If the attribute is `#[derive(...)]`, take the arguments and skip rewriting. - // We will merge the all arguments into a single `#[derive(...)]` at last. derive_args.append(&mut args); + match iter.peek() { + // If the next attribute is `#[derive(...)]` as well, skip rewriting. + Some(&(_, next_attr)) if is_derive(next_attr) => insert_new_line = false, + // If not, rewrite the merged derives. + _ => { + result.push_str(&format!("#[derive({})]", derive_args.join(", "))); + derive_args.clear(); + } + } } else { result.push_str(&a_str); - - if i < self.len() - 1 { - result.push('\n'); - } } } else { result.push_str(&a_str); - - if i < self.len() - 1 { - result.push('\n'); - } } - } - // Add merged `#[derive(...)]` at last. - if context.config.merge_derives() && !derive_args.is_empty() { - if !result.is_empty() && !result.ends_with('\n') { - result.push_str(&indent); + if insert_new_line && i < self.len() - 1 { result.push('\n'); } - result.push_str(&format!("#[derive({})]", derive_args.join(", "))); } - Some(result) } } +fn is_derive(attr: &ast::Attribute) -> bool { + match attr.meta() { + Some(meta_item) => match meta_item.node { + ast::MetaItemKind::List(..) => meta_item.name.as_str() == "derive", + _ => false, + }, + _ => false, + } +} + /// Returns the arguments of `#[derive(...)]`. fn get_derive_args(context: &RewriteContext, attr: &ast::Attribute) -> Option> { attr.meta().and_then(|meta_item| match meta_item.node { diff --git a/tests/source/configs-merge_derives-true.rs b/tests/source/configs-merge_derives-true.rs index 804a48c43c0..18b8443f0d7 100644 --- a/tests/source/configs-merge_derives-true.rs +++ b/tests/source/configs-merge_derives-true.rs @@ -8,3 +8,39 @@ #[foobar] #[derive(Copy, Clone)] pub enum Foo {} + +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} + +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum FooBar {} + +mod foo { +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} +} + +mod bar { +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} +} + +mod foobar { +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum FooBar {} +} diff --git a/tests/target/configs-merge_derives-true.rs b/tests/target/configs-merge_derives-true.rs index 8cf7b9a346d..4d0148b1c6e 100644 --- a/tests/target/configs-merge_derives-true.rs +++ b/tests/target/configs-merge_derives-true.rs @@ -2,7 +2,39 @@ // Merge multiple derives to a single one. #[bar] +#[derive(Eq, PartialEq)] #[foo] +#[derive(Debug)] #[foobar] -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Copy, Clone)] pub enum Foo {} + +#[derive(Eq, PartialEq, Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum FooBar {} + +mod foo { + #[bar] + #[derive(Eq, PartialEq)] + #[foo] + #[derive(Debug)] + #[foobar] + #[derive(Copy, Clone)] + pub enum Foo {} +} + +mod bar { + #[derive(Eq, PartialEq, Debug)] + #[foobar] + #[derive(Copy, Clone)] + pub enum Bar {} +} + +mod foobar { + #[derive(Eq, PartialEq, Debug, Copy, Clone)] + pub enum FooBar {} +} -- cgit 1.4.1-3-g733a5 From 1f9e7c25c95b1cd267c0e54669021e0b56462d94 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 25 Aug 2017 08:19:51 +0900 Subject: Implement Rewrite trait for ast::ForeignItem --- src/items.rs | 126 +++++++++++++++++++++++++++++++-------------------------- src/lib.rs | 7 ++++ src/visitor.rs | 2 +- 3 files changed, 77 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c42ef7f971c..9dd1972670a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -185,64 +185,11 @@ impl<'a> FmtVisitor<'a> { self.format_item(item); } - fn format_foreign_item(&mut self, item: &ast::ForeignItem) { - self.format_missing_with_indent(item.span.lo); - // Drop semicolon or it will be interpreted as comment. - // FIXME: this may be a faulty span from libsyntax. - let span = mk_sp(item.span.lo, item.span.hi - BytePos(1)); - - match item.node { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { - let indent = self.block_indent; - let rewrite = rewrite_fn_base( - &self.get_context(), - indent, - item.ident, - fn_decl, - generics, - ast::Unsafety::Normal, - ast::Constness::NotConst, - ast::Defaultness::Final, - // These are not actually rust functions, - // but we format them as such. - abi::Abi::Rust, - &item.vis, - span, - false, - false, - false, - ); - - match rewrite { - Some((new_fn, _)) => { - self.buffer.push_str(&new_fn); - self.buffer.push_str(";"); - } - None => self.format_missing(item.span.hi), - } - } - ast::ForeignItemKind::Static(ref ty, is_mutable) => { - // FIXME(#21): we're dropping potential comments in between the - // function keywords here. - let vis = format_visibility(&item.vis); - let mut_str = if is_mutable { "mut " } else { "" }; - let prefix = format!("{}static {}{}: ", vis, mut_str, item.ident); - let offset = self.block_indent + prefix.len(); - // 1 = ; - let shape = Shape::indented(offset, self.config).sub_width(1).unwrap(); - let rewrite = ty.rewrite(&self.get_context(), shape); - - match rewrite { - Some(result) => { - self.buffer.push_str(&prefix); - self.buffer.push_str(&result); - self.buffer.push_str(";"); - } - None => self.format_missing(item.span.hi), - } - } - } + fn format_foreign_item(&mut self, item: &ast::ForeignItem) { + let shape = Shape::indented(self.block_indent, self.config); + let rewrite = item.rewrite(&self.get_context(), shape); + self.push_rewrite(item.span(), rewrite); self.last_pos = item.span.hi; } @@ -2837,3 +2784,68 @@ fn format_generics( Some(result) } + +impl Rewrite for ast::ForeignItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + // Drop semicolon or it will be interpreted as comment. + // FIXME: this may be a faulty span from libsyntax. + let span = mk_sp(self.span.lo, self.span.hi - BytePos(1)); + + let item_str = try_opt!(match self.node { + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { + rewrite_fn_base( + context, + shape.indent, + self.ident, + fn_decl, + generics, + ast::Unsafety::Normal, + ast::Constness::NotConst, + ast::Defaultness::Final, + // These are not actually rust functions, + // but we format them as such. + abi::Abi::Rust, + &self.vis, + span, + false, + false, + false, + ).map(|(s, _)| format!("{};", s)) + } + ast::ForeignItemKind::Static(ref ty, is_mutable) => { + // FIXME(#21): we're dropping potential comments in between the + // function keywords here. + let vis = format_visibility(&self.vis); + let mut_str = if is_mutable { "mut " } else { "" }; + let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); + // 1 = ; + let shape = try_opt!(shape.sub_width(1)); + ty.rewrite(context, shape).map(|ty_str| { + // 1 = space between prefix and type. + let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { + String::from(" ") + } else { + let nested_indent = shape.indent.block_indent(context.config); + format!("\n{}", nested_indent.to_string(context.config)) + }; + format!("{}{}{};", prefix, sep, ty_str) + }) + } + }); + + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo, self.span.lo) + } else { + mk_sp(self.attrs[self.attrs.len() - 1].span.hi, self.span.lo) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missing_span, + shape, + false, + ) + } +} diff --git a/src/lib.rs b/src/lib.rs index 1b19689b660..432e61e874b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,7 @@ mod patterns; mod summary; mod vertical; +/// Spanned returns a span including attributes, if available. pub trait Spanned { fn span(&self) -> Span; } @@ -207,6 +208,12 @@ impl Spanned for ast::TyParamBound { } } +impl Spanned for ast::ForeignItem { + fn span(&self) -> Span { + span_with_attrs!(self) + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of diff --git a/src/visitor.rs b/src/visitor.rs index 2f6a503dc13..bf1afb0c3f0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -641,7 +641,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(mac.span, rewrite); } - fn push_rewrite(&mut self, span: Span, rewrite: Option) { + pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo); let result = rewrite.unwrap_or_else(|| self.snippet(span)); self.buffer.push_str(&result); -- cgit 1.4.1-3-g733a5 From 24efc3a934abcc9f497929a0c799d105cae934aa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 25 Aug 2017 22:35:22 +0900 Subject: Ignore empty lines inside arguments of macro with brace --- src/macros.rs | 46 +++++++++++++++++++++++++++++++++------------- tests/source/macros.rs | 15 +++++++++++++++ tests/target/macros.rs | 15 +++++++++++++++ 3 files changed, 63 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b1f740e6a87..a841268ce07 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -309,31 +309,51 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { /// } /// ``` fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option { - let min_prefix_space_width = - try_opt!(macro_str.lines().skip(1).map(get_prefix_space_width).min()); - let mut lines = macro_str.lines(); - let first_line = try_opt!(lines.next()); + let first_line = try_opt!(lines.next().map(|s| s.trim_right())); + let mut trimmed_lines = Vec::with_capacity(16); + + let min_prefix_space_width = try_opt!( + lines + .filter_map(|line| { + let prefix_space_width = if is_empty_line(line) { + None + } else { + get_prefix_space_width(line) + }; + trimmed_lines.push((line.trim(), prefix_space_width)); + prefix_space_width + }) + .min() + ); Some( String::from(first_line) + "\n" + - &lines - .map(|line| { - let new_indent_width = indent.width() + - get_prefix_space_width(line) - .checked_sub(min_prefix_space_width) - .unwrap_or(0); - repeat_white_space(new_indent_width) + line.trim() + &trimmed_lines + .iter() + .map(|&(line, prefix_space_width)| match prefix_space_width { + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width + .checked_sub(min_prefix_space_width) + .unwrap_or(0); + repeat_white_space(new_indent_width) + line.trim() + } + None => String::new(), }) .collect::>() .join("\n"), ) } -fn get_prefix_space_width(s: &str) -> usize { - s.chars().position(|c| c != ' ').unwrap_or(0) +fn get_prefix_space_width(s: &str) -> Option { + s.chars().position(|c| c != ' ') } fn repeat_white_space(ws_count: usize) -> String { repeat(" ").take(ws_count).collect::() } + +fn is_empty_line(s: &str) -> bool { + s.is_empty() || s.chars().all(char::is_whitespace) +} diff --git a/tests/source/macros.rs b/tests/source/macros.rs index d8e6efe9199..aa2861ecd17 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -134,6 +134,21 @@ fn issue_1885() { }).collect::>(); } +fn issue_1917() { + mod x { + quickcheck! { + fn test(a: String, s: String, b: String) -> TestResult { + if a.find(&s).is_none() { + + TestResult::from_bool(true) + } else { + TestResult::discard() + } + } + } + } +} + // Put the following tests with macro invocations whose arguments cannot be parsed as expressioins // at the end of the file for now. diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 21c0b983ff9..cbe15f9f7f7 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -178,6 +178,21 @@ fn issue_1885() { .collect::>(); } +fn issue_1917() { + mod x { + quickcheck! { + fn test(a: String, s: String, b: String) -> TestResult { + if a.find(&s).is_none() { + + TestResult::from_bool(true) + } else { + TestResult::discard() + } + } + } + } +} + // Put the following tests with macro invocations whose arguments cannot be parsed as expressioins // at the end of the file for now. -- cgit 1.4.1-3-g733a5 From 343b3158304ef8af111e1e4923c598b99e7dc3b4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 27 Aug 2017 13:44:49 +0900 Subject: Handle macros with tabs --- src/lib.rs | 10 ++++++++++ src/macros.rs | 40 ++++++++++++++++++++++++++-------------- tests/source/macros.rs | 15 +++++++++++++++ tests/target/macros.rs | 15 +++++++++++++++ 4 files changed, 66 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 432e61e874b..97f60329421 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -231,6 +231,16 @@ impl Indent { } } + pub fn from_width(config: &Config, width: usize) -> Indent { + if config.hard_tabs() { + let tab_num = width / config.tab_spaces(); + let alignment = width % config.tab_spaces(); + Indent::new(config.tab_spaces() * tab_num, alignment) + } else { + Indent::new(width, 0) + } + } + pub fn empty() -> Indent { Indent::new(0, 0) } diff --git a/src/macros.rs b/src/macros.rs index a841268ce07..12965b61560 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -19,8 +19,6 @@ // List-like invocations with parentheses will be formatted as function calls, // and those with brackets will be formatted as array literals. -use std::iter::repeat; - use syntax::ast; use syntax::codemap::BytePos; use syntax::parse::new_parser_from_tts; @@ -118,14 +116,18 @@ pub fn rewrite_macro( Ok(expr) => { // Recovered errors. if context.parse_session.span_diagnostic.has_errors() { - return indent_macro_snippet(&context.snippet(mac.span), shape.indent); + return indent_macro_snippet( + context, + &context.snippet(mac.span), + shape.indent, + ); } expr } Err(mut e) => { e.cancel(); - return indent_macro_snippet(&context.snippet(mac.span), shape.indent); + return indent_macro_snippet(context, &context.snippet(mac.span), shape.indent); } }; @@ -244,7 +246,7 @@ pub fn rewrite_macro( } MacroStyle::Braces => { // Skip macro invocations with braces, for now. - indent_macro_snippet(&context.snippet(mac.span), shape.indent) + indent_macro_snippet(context, &context.snippet(mac.span), shape.indent) } } } @@ -308,7 +310,11 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { // ), /// } /// ``` -fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option { +fn indent_macro_snippet( + context: &RewriteContext, + macro_str: &str, + indent: Indent, +) -> Option { let mut lines = macro_str.lines(); let first_line = try_opt!(lines.next().map(|s| s.trim_right())); let mut trimmed_lines = Vec::with_capacity(16); @@ -319,7 +325,7 @@ fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option { let prefix_space_width = if is_empty_line(line) { None } else { - get_prefix_space_width(line) + Some(get_prefix_space_width(context, line)) }; trimmed_lines.push((line.trim(), prefix_space_width)); prefix_space_width @@ -337,7 +343,8 @@ fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option { original_indent_width .checked_sub(min_prefix_space_width) .unwrap_or(0); - repeat_white_space(new_indent_width) + line.trim() + let new_indent = Indent::from_width(context.config, new_indent_width); + new_indent.to_string(context.config) + line.trim() } None => String::new(), }) @@ -346,12 +353,17 @@ fn indent_macro_snippet(macro_str: &str, indent: Indent) -> Option { ) } -fn get_prefix_space_width(s: &str) -> Option { - s.chars().position(|c| c != ' ') -} - -fn repeat_white_space(ws_count: usize) -> String { - repeat(" ").take(ws_count).collect::() +fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { + let mut width = 0; + let mut iter = s.chars(); + while let Some(c) = iter.next() { + match c { + ' ' => width += 1, + '\t' => width += context.config.tab_spaces(), + _ => return width, + } + } + width } fn is_empty_line(s: &str) -> bool { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index aa2861ecd17..caccd75a700 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -149,6 +149,21 @@ fn issue_1917() { } } +fn issue_1921() { + // Macro with tabs. + lazy_static! { + static ref ONE: u32 = 1; + static ref TWO: u32 = 2; + static ref THREE: u32 = 3; + static ref FOUR: u32 = { + let mut acc = 1; + acc += 1; + acc += 2; + acc + } +} +} + // Put the following tests with macro invocations whose arguments cannot be parsed as expressioins // at the end of the file for now. diff --git a/tests/target/macros.rs b/tests/target/macros.rs index cbe15f9f7f7..0b651cc5445 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -193,6 +193,21 @@ fn issue_1917() { } } +fn issue_1921() { + // Macro with tabs. + lazy_static! { + static ref ONE: u32 = 1; + static ref TWO: u32 = 2; + static ref THREE: u32 = 3; + static ref FOUR: u32 = { + let mut acc = 1; + acc += 1; + acc += 2; + acc + } + } +} + // Put the following tests with macro invocations whose arguments cannot be parsed as expressioins // at the end of the file for now. -- cgit 1.4.1-3-g733a5 From fd10d256802e94c0cd7d1b6cfdb2c2924fdf8e99 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 27 Aug 2017 14:41:15 +0900 Subject: Allow pre-line single-lined comments to stay on the same line --- src/lists.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 8787850634e..a9d705b4c64 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -117,13 +117,23 @@ impl ListItem { self.item.as_ref().map_or("", |s| &*s) } - pub fn is_multiline(&self) -> bool { + pub fn is_different_group(&self) -> bool { self.inner_as_ref().contains('\n') || self.pre_comment.is_some() || self.post_comment .as_ref() .map_or(false, |s| s.contains('\n')) } + pub fn is_multiline(&self) -> bool { + self.inner_as_ref().contains('\n') || + self.pre_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) || + self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + } + pub fn has_comment(&self) -> bool { self.pre_comment .as_ref() @@ -469,7 +479,7 @@ where let item = item.as_ref(); let inner_item_width = item.inner_as_ref().len(); if !first && - (item.is_multiline() || !item.post_comment.is_some() || + (item.is_different_group() || !item.post_comment.is_some() || inner_item_width + overhead > max_budget) { return max_width; -- cgit 1.4.1-3-g733a5 From ef84319e47dfe899b7fe530248c15c1392ced8a3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 27 Aug 2017 14:57:21 +0900 Subject: Fix a typo in calculating overhead for fn args --- src/items.rs | 3 +-- tests/source/configs-fn_args_layout-visual.rs | 22 ++++++++++++++++++++++ tests/target/configs-fn_args_layout-visual.rs | 24 ++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9dd1972670a..b1636ef0123 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2284,8 +2284,7 @@ fn compute_budgets_for_args( } IndentStyle::Visual => { let indent = indent + result.len() + 1; - let multi_line_overhead = - indent.width() + result.len() + if newline_brace { 2 } else { 4 }; + let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; let budget = try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); (indent, budget) diff --git a/tests/source/configs-fn_args_layout-visual.rs b/tests/source/configs-fn_args_layout-visual.rs index b0d88fb0651..e0af153f982 100644 --- a/tests/source/configs-fn_args_layout-visual.rs +++ b/tests/source/configs-fn_args_layout-visual.rs @@ -8,3 +8,25 @@ fn lorem(ipsum: usize) {} fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { // body } + +// #1922 +extern "C" { + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + a: *const lapack_complex_float, + lda: lapack_int, ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int + )-> lapack_int; + + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + lda: lapack_int, ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int + ) -> lapack_int; +} diff --git a/tests/target/configs-fn_args_layout-visual.rs b/tests/target/configs-fn_args_layout-visual.rs index 834cac446a9..778d6d4fc03 100644 --- a/tests/target/configs-fn_args_layout-visual.rs +++ b/tests/target/configs-fn_args_layout-visual.rs @@ -14,3 +14,27 @@ fn lorem(ipsum: usize, elit: usize) { // body } + +// #1922 +extern "C" { + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + a: *const lapack_complex_float, + lda: lapack_int, + ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int) + -> lapack_int; + + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + lda: lapack_int, + ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int) + -> lapack_int; +} -- cgit 1.4.1-3-g733a5 From 66b16426243f6e9bae6404d453e6845893edcad6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 Aug 2017 00:10:46 +0900 Subject: Add recover_missing_comment_in_span() and rewrite_missing_comment() --- src/comment.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0a716aa308c..bb7ce14dcdd 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -365,6 +365,50 @@ fn rewrite_comment_inner( Some(result) } +/// Given the span, rewrite the missing comment inside it if available. +/// Note that the given span must only include comments (or leading/trailing whitespaces). +pub fn rewrite_missing_comment( + span: Span, + shape: Shape, + context: &RewriteContext, +) -> Option { + let missing_snippet = context.snippet(span); + let trimmed_snippet = missing_snippet.trim(); + if !trimmed_snippet.is_empty() { + rewrite_comment(trimmed_snippet, false, shape, context.config) + } else { + Some(String::new()) + } +} + +/// Recover the missing comments in the specified span, if available. +/// The layout of the comments will be preserved as long as it does not break the code +/// and its total width does not exceed the max width. +pub fn recover_missing_comment_in_span( + span: Span, + shape: Shape, + context: &RewriteContext, + used_width: usize, +) -> Option { + let missing_comment = try_opt!(rewrite_missing_comment(span, shape, context)); + if missing_comment.is_empty() { + Some(String::new()) + } else { + let missing_snippet = context.snippet(span); + let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); + // 1 = ` ` + let total_width = missing_comment.len() + used_width + 1; + let force_new_line_before_comment = + missing_snippet[..pos].contains('\n') || total_width > context.config.max_width(); + let sep = if force_new_line_before_comment { + format!("\n{}", shape.indent.to_string(context.config)) + } else { + String::from(" ") + }; + Some(format!("{}{}", sep, missing_comment)) + } +} + /// Trims whitespace and aligns to indent, but otherwise does not change comments. fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option { let lines: Vec<&str> = orig.lines() -- cgit 1.4.1-3-g733a5 From 6bbc6b54de37738ea8991b1dd928b9d49d53cd67 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 Aug 2017 00:13:42 +0900 Subject: Refactor - remove duplicates replacing some functions with recover_missing_comments() and rewrite_missing_comments(). --- src/comment.rs | 12 +++-------- src/expr.rs | 26 ++++++++++------------- src/items.rs | 65 +++++++++++++++------------------------------------------- 3 files changed, 30 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index bb7ce14dcdd..aa078f4dbf7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -153,11 +153,10 @@ pub fn combine_strs_with_missing_comments( let mut one_line_width = last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); - let original_snippet = context.snippet(span); - let trimmed_snippet = original_snippet.trim(); let indent_str = shape.indent.to_string(context.config); + let missing_comment = try_opt!(rewrite_missing_comment(span, shape, context)); - if trimmed_snippet.is_empty() { + if missing_comment.is_empty() { if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { return Some(format!("{}{}{}", prev_str, first_sep, next_str)); } else { @@ -175,18 +174,13 @@ pub fn combine_strs_with_missing_comments( // Peek the the original source code and find out whether there is a newline between the first // expression and the second expression or the missing comment. We will preserve the orginal // layout whenever possible. + let original_snippet = context.snippet(span); let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { !original_snippet[..pos].contains('\n') } else { !original_snippet.contains('\n') }; - let missing_comment = try_opt!(rewrite_comment( - trimmed_snippet, - false, - shape, - context.config - )); one_line_width -= first_sep.len(); let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { String::new() diff --git a/src/expr.rs b/src/expr.rs index a42ab973e0d..1bb910b61b3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,7 @@ use {Indent, Shape, Spanned}; use chains::rewrite_chain; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - rewrite_comment, FindUncommented}; + rewrite_comment, rewrite_missing_comment, FindUncommented}; use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, @@ -1195,9 +1195,13 @@ impl<'a> ControlFlow<'a> { mk_sp(self.block.span.lo, self.block.span.lo) }; - // for event in event + // `for event in event` + // Do not include label in the span. + let lo = self.label.map_or(self.span.lo, |label| label.span.hi); let between_kwd_cond = mk_sp( - context.codemap.span_after(self.span, self.keyword.trim()), + context + .codemap + .span_after(mk_sp(lo, self.span.hi), self.keyword.trim()), self.pat .map_or(cond_span.lo, |p| if self.matcher.is_empty() { p.span.lo @@ -1378,21 +1382,13 @@ fn rewrite_label(label: Option) -> String { } fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { - let comment_str = context.snippet(span); - if contains_comment(&comment_str) { - let comment = try_opt!(rewrite_comment( - comment_str.trim(), - false, - shape, - context.config, - )); - Some(format!( + match rewrite_missing_comment(span, shape, context) { + Some(ref comment) if !comment.is_empty() => Some(format!( "\n{indent}{}\n{indent}", comment, indent = shape.indent.to_string(context.config) - )) - } else { - None + )), + _ => None, } } diff --git a/src/items.rs b/src/items.rs index 9dd1972670a..c3092553b91 100644 --- a/src/items.rs +++ b/src/items.rs @@ -19,7 +19,7 @@ use syntax::codemap::{BytePos, Span}; use {Indent, Shape, Spanned}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - rewrite_comment, FindUncommented}; + recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; @@ -2006,33 +2006,17 @@ fn rewrite_fn_base( // args and `{`. if where_clause_str.is_empty() { if let ast::FunctionRetTy::Default(ret_span) = fd.output { - let sp = mk_sp(args_span.hi, ret_span.hi); - let missing_snippet = context.snippet(sp); - let trimmed_snippet = missing_snippet.trim(); - let missing_comment = if trimmed_snippet.is_empty() { - String::new() - } else { - try_opt!(rewrite_comment( - trimmed_snippet, - false, - Shape::indented(indent, context.config), - context.config, - )) - }; - if !missing_comment.is_empty() { - let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); - // 1 = ` ` - let total_width = missing_comment.len() + last_line_width(&result) + 1; - let force_new_line_before_comment = missing_snippet[..pos].contains('\n') || - total_width > context.config.max_width(); - let sep = if force_new_line_before_comment { - format!("\n{}", indent.to_string(context.config)) - } else { - String::from(" ") - }; - result.push_str(&sep); - result.push_str(&missing_comment); - force_new_line_for_brace = true; + match recover_missing_comment_in_span( + mk_sp(args_span.hi, ret_span.hi), + shape, + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + force_new_line_for_brace = true; + } + _ => (), } } } @@ -2684,34 +2668,17 @@ fn missing_span_before_after_where( (missing_span_before, missing_span_after) } -fn rewrite_missing_comment_in_where( - context: &RewriteContext, - comment: &str, - shape: Shape, -) -> Option { - let comment = comment.trim(); - if comment.is_empty() { - Some(String::new()) - } else { - rewrite_comment(comment, false, shape, context.config) - } -} - fn rewrite_comments_before_after_where( context: &RewriteContext, span_before_where: Span, span_after_where: Span, shape: Shape, ) -> Option<(String, String)> { - let before_comment = try_opt!(rewrite_missing_comment_in_where( - context, - &context.snippet(span_before_where), - shape, - )); - let after_comment = try_opt!(rewrite_missing_comment_in_where( - context, - &context.snippet(span_after_where), + let before_comment = try_opt!(rewrite_missing_comment(span_before_where, shape, context)); + let after_comment = try_opt!(rewrite_missing_comment( + span_after_where, shape.block_indent(context.config.tab_spaces()), + context, )); Some((before_comment, after_comment)) } -- cgit 1.4.1-3-g733a5 From fa7c4d503015638a9696a54432beca7af6999f10 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 Aug 2017 00:16:54 +0900 Subject: Recover comments between 'impl' and the opening brace --- src/items.rs | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c3092553b91..3217cc9b8f6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -517,8 +517,10 @@ pub fn format_impl( where_span_end: Option, ) -> Option { if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { - let mut result = String::new(); + let mut result = String::with_capacity(128); let ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset)); + let indent_str = offset.to_string(context.config); + let sep = format!("\n{}", &indent_str); result.push_str(&ref_and_type); let where_budget = if result.contains('\n') { @@ -543,6 +545,24 @@ pub fn format_impl( option, )); + // If there is no where clause, we may have missing comments between the trait name and + // the opening brace. + if generics.where_clause.predicates.is_empty() { + if let Some(hi) = where_span_end { + match recover_missing_comment_in_span( + mk_sp(self_ty.span.hi, hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + } + _ => (), + } + } + } + if try_opt!(is_impl_single_line( context, &items, @@ -551,9 +571,8 @@ pub fn format_impl( &item, )) { result.push_str(&where_clause_str); - if where_clause_str.contains('\n') { - let white_space = offset.to_string(context.config); - result.push_str(&format!("\n{}{{\n{}}}", &white_space, &white_space)); + if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { + result.push_str(&format!("{}{{{}}}", &sep, &sep)); } else { result.push_str(" {}"); } @@ -569,14 +588,11 @@ pub fn format_impl( result.push_str(&where_clause_str); match context.config.item_brace_style() { - BraceStyle::AlwaysNextLine => { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } + _ if last_line_contains_single_line_comment(&result) => result.push_str(&sep), + BraceStyle::AlwaysNextLine => result.push_str(&sep), BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => if !where_clause_str.is_empty() { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); + result.push_str(&sep); } else { result.push(' '); }, @@ -610,8 +626,7 @@ pub fn format_impl( } if result.chars().last().unwrap() == '{' { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); + result.push_str(&sep); } result.push('}'); @@ -632,7 +647,7 @@ fn is_impl_single_line( let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; Some( - context.config.impl_empty_single_line() && items.is_empty() && + context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n') && result.len() + where_clause_str.len() <= context.config.max_width() && !contains_comment(&snippet[open_pos..]), ) -- cgit 1.4.1-3-g733a5 From c4c55285daf803750ec21ecdb77b6a04eb464566 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 Aug 2017 00:17:19 +0900 Subject: Recover comments between 'trait' and the opening brace --- src/items.rs | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3217cc9b8f6..3c4aab69fcc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -868,7 +868,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if let ast::ItemKind::Trait(unsafety, ref generics, ref type_param_bounds, ref trait_items) = item.node { - let mut result = String::new(); + let mut result = String::with_capacity(128); let header = format!( "{}{}trait {}", format_visibility(&item.vis), @@ -925,14 +925,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) .checked_sub(last_line_width(&result)) ); let pos_before_where = if type_param_bounds.is_empty() { - if generics.where_clause.predicates.is_empty() { - // We do not use this, so it does not matter - item.span.lo - } else { - let snippet = context.snippet(item.span); - let where_pos = snippet.find_uncommented("where"); - item.span.lo + where_pos.map_or(BytePos(0), |p| BytePos(p as u32)) - } + generics.where_clause.span.lo } else { type_param_bounds[type_param_bounds.len() - 1].span().hi }; @@ -961,7 +954,33 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&where_clause_str); + if generics.where_clause.predicates.is_empty() { + let item_snippet = context.snippet(item.span); + if let Some(lo) = item_snippet.chars().position(|c| c == '/') { + // 1 = `{` + let comment_hi = body_lo - BytePos(1); + let comment_lo = item.span.lo + BytePos(lo as u32); + if comment_lo < comment_hi { + match recover_missing_comment_in_span( + mk_sp(comment_lo, comment_hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + } + _ => (), + } + } + } + } + match context.config.item_brace_style() { + _ if last_line_contains_single_line_comment(&result) => { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } BraceStyle::AlwaysNextLine => { result.push('\n'); result.push_str(&offset.to_string(context.config)); -- cgit 1.4.1-3-g733a5 From eb828ed9ff17eee767d72986d1cfc7516cbbf663 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 Aug 2017 00:17:38 +0900 Subject: Preserve blank line between doc comment and attribute --- src/visitor.rs | 67 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index bf1afb0c3f0..e6872078365 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -18,7 +18,8 @@ use syntax::parse::ParseSess; use {Indent, Shape, Spanned}; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{contains_comment, CodeCharKind, CommentCodeSlices, FindUncommented}; +use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, CommentCodeSlices, + FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; use expr::{format_expr, ExprType}; @@ -928,6 +929,8 @@ impl<'a> Rewrite for [ast::Attribute] { let mut derive_args = Vec::new(); let mut iter = self.iter().enumerate().peekable(); + let mut insert_new_line = true; + let mut is_prev_sugared_doc = false; while let Some((i, a)) = iter.next() { let a_str = try_opt!(a.rewrite(context, shape)); @@ -937,31 +940,61 @@ impl<'a> Rewrite for [ast::Attribute] { // This particular horror show is to preserve line breaks in between doc // comments. An alternative would be to force such line breaks to start // with the usual doc comment token. - let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1; - let comment = comment.trim(); + let (multi_line_before, multi_line_after) = if a.is_sugared_doc || + is_prev_sugared_doc + { + // Look at before and after comment and see if there are any empty lines. + let comment_begin = comment.chars().position(|c| c == '/'); + let len = comment_begin.unwrap_or(comment.len()); + let mlb = comment.chars().take(len).filter(|c| *c == '\n').count() > 1; + let mla = if comment_begin.is_none() { + mlb + } else { + let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); + let len = comment_end.unwrap(); + comment + .chars() + .rev() + .take(len) + .filter(|c| *c == '\n') + .count() > 1 + }; + (mlb, mla) + } else { + (false, false) + }; + + let comment = try_opt!(recover_missing_comment_in_span( + mk_sp(self[i - 1].span.hi, a.span.lo), + shape.with_max_width(context.config), + context, + 0, + )); + if !comment.is_empty() { - let comment = try_opt!(rewrite_comment( - comment, - false, - Shape::legacy( - context.config.comment_width() - shape.indent.width(), - shape.indent, - ), - context.config, - )); - result.push_str(&indent); + if multi_line_before { + result.push('\n'); + } result.push_str(&comment); result.push('\n'); - } else if multi_line { + if multi_line_after { + result.push('\n') + } + } else if insert_new_line { result.push('\n'); + if multi_line_after { + result.push('\n') + } } + if derive_args.is_empty() { result.push_str(&indent); } + + insert_new_line = true; } // Write the attribute itself. - let mut insert_new_line = true; if context.config.merge_derives() { // If the attribute is `#[derive(...)]`, take the arguments. if let Some(mut args) = get_derive_args(context, a) { @@ -982,9 +1015,7 @@ impl<'a> Rewrite for [ast::Attribute] { result.push_str(&a_str); } - if insert_new_line && i < self.len() - 1 { - result.push('\n'); - } + is_prev_sugared_doc = a.is_sugared_doc; } Some(result) } -- cgit 1.4.1-3-g733a5 From 1015dd8860b625b4d1d5c9462145044d26654c73 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 Aug 2017 00:24:10 +0900 Subject: Use String::with_capacity() instead of String::new() --- src/items.rs | 6 +++--- src/visitor.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3c4aab69fcc..6f4fce6a2d7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -66,7 +66,7 @@ impl Rewrite for ast::Local { // String that is placed within the assignment pattern and expression. let infix = { - let mut infix = String::new(); + let mut infix = String::with_capacity(32); if let Some(ref ty) = self.ty { let separator = type_annotation_separator(context.config); @@ -668,7 +668,7 @@ fn format_impl_ref_and_type( _, ) = item.node { - let mut result = String::new(); + let mut result = String::with_capacity(128); result.push_str(&format_visibility(&item.vis)); result.push_str(&format_defaultness(defaultness)); @@ -1265,7 +1265,7 @@ pub fn rewrite_type_alias( vis: &ast::Visibility, span: Span, ) -> Option { - let mut result = String::new(); + let mut result = String::with_capacity(128); result.push_str(&format_visibility(vis)); result.push_str("type "); diff --git a/src/visitor.rs b/src/visitor.rs index e6872078365..f07dad4a6ba 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -920,10 +920,10 @@ impl Rewrite for ast::Attribute { impl<'a> Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let mut result = String::new(); if self.is_empty() { - return Some(result); + return Some(String::new()); } + let mut result = String::with_capacity(128); let indent = shape.indent.to_string(context.config); let mut derive_args = Vec::new(); -- cgit 1.4.1-3-g733a5 From 404e2db046cbde04195939219984483e76b1a911 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 28 Aug 2017 23:40:01 +0900 Subject: Remove unused extern crate --- src/bin/rustfmt-format-diff.rs | 1 - src/bin/rustfmt.rs | 2 -- tests/system.rs | 1 - 3 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt-format-diff.rs b/src/bin/rustfmt-format-diff.rs index f7f3c1d8f7c..5bd0e5d18cc 100644 --- a/src/bin/rustfmt-format-diff.rs +++ b/src/bin/rustfmt-format-diff.rs @@ -19,7 +19,6 @@ extern crate getopts; #[macro_use] extern crate log; extern crate regex; -extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json as json; diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 88bd3222fcb..5bb5190e810 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -13,9 +13,7 @@ extern crate env_logger; extern crate getopts; -extern crate log; extern crate rustfmt_nightly as rustfmt; -extern crate toml; use std::{env, error}; use std::fs::File; diff --git a/tests/system.rs b/tests/system.rs index 6e148147a48..9559b545cc6 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate diff; extern crate regex; extern crate rustfmt_nightly as rustfmt; extern crate term; -- cgit 1.4.1-3-g733a5 From 1577cefad5066ab6efd4073231cd2bd9126d46d3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 27 Aug 2017 15:31:19 -0700 Subject: Add support for `Yield` --- src/expr.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1bb910b61b3..95300133775 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -181,6 +181,17 @@ pub fn format_expr( ) } } + ast::ExprKind::Yield(ref opt_expr) => { + if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, "yield ", &**expr, shape) + } else { + wrap_str( + "yield".to_string(), + context.config.max_width(), + shape, + ) + } + } ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, expr.span, context, shape) } -- cgit 1.4.1-3-g733a5 From e31a48b4d9f431635c67bb608d9a68729c798a35 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 30 Aug 2017 19:26:45 +0900 Subject: Refactoring: remove duplicates --- src/imports.rs | 2 +- src/items.rs | 22 ++++++---------------- src/visitor.rs | 25 +++++++++++-------------- 3 files changed, 18 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index e5dfb12f4c4..afa81693548 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -260,7 +260,7 @@ impl<'a> FmtVisitor<'a> { ) { let vis = utils::format_visibility(vis); // 4 = `use `, 1 = `;` - let rw = Shape::indented(self.block_indent, self.config) + let rw = self.shape() .offset_left(vis.len() + 4) .and_then(|shape| shape.sub_width(1)) .and_then(|shape| match vp.node { diff --git a/src/items.rs b/src/items.rs index 94a13a502eb..5908464c416 100644 --- a/src/items.rs +++ b/src/items.rs @@ -187,8 +187,7 @@ impl<'a> FmtVisitor<'a> { fn format_foreign_item(&mut self, item: &ast::ForeignItem) { - let shape = Shape::indented(self.block_indent, self.config); - let rewrite = item.rewrite(&self.get_context(), shape); + let rewrite = item.rewrite(&self.get_context(), self.shape()); self.push_rewrite(item.span(), rewrite); self.last_pos = item.span.hi; } @@ -312,18 +311,11 @@ impl<'a> FmtVisitor<'a> { "" }; - format_expr( - &e, - ExprType::Statement, - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ).map(|s| s + suffix) + format_expr(&e, ExprType::Statement, &self.get_context(), self.shape()) + .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } - None => stmt.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ), + None => stmt.rewrite(&self.get_context(), self.shape()), } } else { None @@ -421,9 +413,7 @@ impl<'a> FmtVisitor<'a> { false, ); - let shape = Shape::indented(self.block_indent, self.config) - .sub_width(2) - .unwrap(); + let shape = self.shape().sub_width(2).unwrap(); let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", @@ -451,7 +441,7 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let indent = self.block_indent; - let shape = Shape::indented(indent, self.config); + let shape = self.shape(); let attrs_str = try_opt!(field.node.attrs.rewrite(&context, shape)); let lo = field .node diff --git a/src/visitor.rs b/src/visitor.rs index f07dad4a6ba..fad14f19ce8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -58,6 +58,10 @@ pub struct FmtVisitor<'a> { } impl<'a> FmtVisitor<'a> { + pub fn shape(&self) -> Shape { + Shape::indented(self.block_indent, self.config) + } + fn visit_stmt(&mut self, stmt: &ast::Stmt) { debug!( "visit_stmt: {:?} {:?}", @@ -138,9 +142,7 @@ impl<'a> FmtVisitor<'a> { if let Some(first_stmt) = b.stmts.first() { let attr_lo = inner_attrs .and_then(|attrs| { - utils::inner_attributes(attrs) - .first() - .map(|attr| attr.span.lo) + inner_attributes(attrs).first().map(|attr| attr.span.lo) }) .or_else(|| { // Attributes for an item in a statement position @@ -218,7 +220,7 @@ impl<'a> FmtVisitor<'a> { let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); if unindent_comment { let end_pos = source!(self, b.span).hi - brace_compensation - remove_len; - let snippet = self.get_context().snippet(mk_sp(self.last_pos, end_pos)); + let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); unindent_comment = snippet.contains("//") || snippet.contains("/*"); } // FIXME: we should compress any newlines here to just one @@ -336,7 +338,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(item.span, None); return; } - } else if utils::contains_skip(&item.attrs) { + } else if contains_skip(&item.attrs) { // Module is not inline, but should be skipped. return; } else { @@ -371,7 +373,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo); - let snippet = self.get_context().snippet(item.span); + let snippet = self.snippet(item.span); let where_span_end = snippet .find_uncommented("{") .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); @@ -635,9 +637,7 @@ impl<'a> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, mac.span); // 1 = ; - let shape = Shape::indented(self.block_indent, self.config) - .sub_width(1) - .unwrap(); + let shape = self.shape().sub_width(1).unwrap(); let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); self.push_rewrite(mac.span, rewrite); } @@ -677,7 +677,7 @@ impl<'a> FmtVisitor<'a> { // Returns true if we should skip the following item. pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { - if utils::contains_skip(attrs) { + if contains_skip(attrs) { return true; } @@ -686,10 +686,7 @@ impl<'a> FmtVisitor<'a> { return false; } - let rewrite = attrs.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ); + let rewrite = attrs.rewrite(&self.get_context(), self.shape()); let span = mk_sp(attrs[0].span.lo, attrs[attrs.len() - 1].span.hi); self.push_rewrite(span, rewrite); -- cgit 1.4.1-3-g733a5 From 979d131c5d8354a80d21942bed7d78ab1e76d9f0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 30 Aug 2017 19:27:36 +0900 Subject: Format and preserve attributes on ast::Stmt --- src/expr.rs | 44 ++++++++++++++++++++------------------------ src/items.rs | 18 +++++++++++++++++- src/lib.rs | 46 ++++++++++++++++++++++++---------------------- src/visitor.rs | 48 ++++++++++++------------------------------------ tests/source/attrib.rs | 22 ++++++++++++++++++++++ tests/target/attrib.rs | 22 ++++++++++++++++++++++ 6 files changed, 117 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 95300133775..f00dc6457f9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -130,11 +130,10 @@ pub fn format_expr( ExprType::Statement => { if is_unsafe_block(block) { block.rewrite(context, shape) - } else { + } else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { // Rewrite block without trying to put it in a single line. - if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { - return rw; - } + rw + } else { let prefix = try_opt!(block_prefix(context, block, shape)); rewrite_block_with_visitor(context, &prefix, block, shape) } @@ -293,17 +292,17 @@ pub fn format_expr( shape, ), ast::ExprKind::Catch(ref block) => { - if let rewrite @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) - { - return rewrite; + if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { + rw + } else { + // 9 = `do catch ` + let budget = shape.width.checked_sub(9).unwrap_or(0); + Some(format!( + "{}{}", + "do catch ", + try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))) + )) } - // 9 = `do catch ` - let budget = shape.width.checked_sub(9).unwrap_or(0); - Some(format!( - "{}{}", - "do catch ", - try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))) - )) } }; @@ -883,16 +882,13 @@ impl Rewrite for ast::Stmt { "" }; - format_expr( - ex, - match self.node { - ast::StmtKind::Expr(_) => ExprType::SubExpression, - ast::StmtKind::Semi(_) => ExprType::Statement, - _ => unreachable!(), - }, - context, - try_opt!(shape.sub_width(suffix.len())), - ).map(|s| s + suffix) + let expr_type = match self.node { + ast::StmtKind::Expr(_) => ExprType::SubExpression, + ast::StmtKind::Semi(_) => ExprType::Statement, + _ => unreachable!(), + }; + let shape = try_opt!(shape.sub_width(suffix.len())); + format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; diff --git a/src/items.rs b/src/items.rs index 5908464c416..50efea4044e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -55,7 +55,23 @@ impl Rewrite for ast::Local { skip_out_of_file_lines_range!(context, self.span); - let mut result = "let ".to_owned(); + if contains_skip(&self.attrs) { + return None; + } + + let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + let mut result = if attrs_str.is_empty() { + "let ".to_owned() + } else { + try_opt!(combine_strs_with_missing_comments( + context, + &attrs_str, + "let ", + mk_sp(self.attrs.last().map(|a| a.span.hi).unwrap(), self.span.lo), + shape, + false, + )) + }; // 4 = "let ".len() let pat_shape = try_opt!(shape.offset_left(4)); diff --git a/src/lib.rs b/src/lib.rs index 97f60329421..c45110ea06b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,32 +91,46 @@ macro_rules! span_with_attrs_lo_hi { } } } + macro_rules! span_with_attrs { ($this:ident) => { span_with_attrs_lo_hi!($this, $this.span.lo, $this.span.hi) } } -impl Spanned for ast::Expr { - fn span(&self) -> Span { - span_with_attrs!(self) +macro_rules! implement_spanned { + ($this:ty) => { + impl Spanned for $this { + fn span(&self) -> Span { + span_with_attrs!(self) + } + } } } -impl Spanned for ast::Item { - fn span(&self) -> Span { - span_with_attrs!(self) - } -} +// Implement `Spanned` for structs with `attrs` field. +implement_spanned!(ast::Expr); +implement_spanned!(ast::Field); +implement_spanned!(ast::ForeignItem); +implement_spanned!(ast::Item); +implement_spanned!(ast::Local); impl Spanned for ast::Stmt { fn span(&self) -> Span { match self.node { - // Cover attributes + ast::StmtKind::Local(ref local) => mk_sp(local.span().lo, self.span.hi), + ast::StmtKind::Item(ref item) => mk_sp(item.span().lo, self.span.hi), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo, self.span.hi) } - _ => self.span, + ast::StmtKind::Mac(ref mac) => { + let (_, _, ref attrs) = **mac; + if attrs.is_empty() { + self.span + } else { + mk_sp(attrs[0].span.lo, self.span.hi) + } + } } } } @@ -155,12 +169,6 @@ impl Spanned for ast::StructField { } } -impl Spanned for ast::Field { - fn span(&self) -> Span { - span_with_attrs!(self) - } -} - impl Spanned for ast::WherePredicate { fn span(&self) -> Span { match *self { @@ -208,12 +216,6 @@ impl Spanned for ast::TyParamBound { } } -impl Spanned for ast::ForeignItem { - fn span(&self) -> Span { - span_with_attrs!(self) - } -} - #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of diff --git a/src/visitor.rs b/src/visitor.rs index fad14f19ce8..b4c4bf3553f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -30,7 +30,7 @@ use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, Sepa use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; -use utils::{self, contains_skip, mk_sp}; +use utils::{self, contains_skip, inner_attributes, mk_sp}; fn is_use_item(item: &ast::Item) -> bool { match item.node { @@ -73,47 +73,23 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Item(ref item) => { self.visit_item(item); } - ast::StmtKind::Local(ref local) => { - let rewrite = if contains_skip(&local.attrs) { - None - } else { - stmt.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ) - }; - self.push_rewrite(stmt.span, rewrite); + ast::StmtKind::Local(..) => { + let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(stmt.span(), rewrite); } ast::StmtKind::Expr(ref expr) => { - let rewrite = format_expr( - expr, - ExprType::Statement, - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ); - let span = if expr.attrs.is_empty() { - stmt.span - } else { - mk_sp(expr.span().lo, stmt.span.hi) - }; - self.push_rewrite(span, rewrite) + let rewrite = + format_expr(expr, ExprType::Statement, &self.get_context(), self.shape()); + self.push_rewrite(stmt.span(), rewrite) } - ast::StmtKind::Semi(ref expr) => { - let rewrite = stmt.rewrite( - &self.get_context(), - Shape::indented(self.block_indent, self.config), - ); - let span = if expr.attrs.is_empty() { - stmt.span - } else { - mk_sp(expr.span().lo, stmt.span.hi) - }; - self.push_rewrite(span, rewrite) + ast::StmtKind::Semi(..) => { + let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(stmt.span(), rewrite) } ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, ref attrs) = **mac; - if contains_skip(attrs) { - self.push_rewrite(mac.span, None); + if self.visit_attrs(attrs, ast::AttrStyle::Outer) { + self.push_rewrite(stmt.span(), None); } else { self.visit_mac(mac, None, MacroPosition::Statement); } diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index fe8a5e3615b..4d23d8b79d1 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -124,3 +124,25 @@ impl InnerAttributes() { mod InnerAttributes { #![ this_is_an_inner_attribute ( foo ) ] } + +fn attributes_on_statements() { + // Local + # [ attr ( on ( local ) ) ] + let x = 3; + + // Item + # [ attr ( on ( item ) ) ] + use foo; + + // Expr + # [ attr ( on ( expr ) ) ] + {} + + // Semi + # [ attr ( on ( semi ) ) ] + foo(); + + // Mac + # [ attr ( on ( mac ) ) ] + foo!(); +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 677c920ff1b..467d168ef4f 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -124,3 +124,25 @@ impl InnerAttributes() { mod InnerAttributes { #![this_is_an_inner_attribute(foo)] } + +fn attributes_on_statements() { + // Local + #[attr(on(local))] + let x = 3; + + // Item + #[attr(on(item))] + use foo; + + // Expr + #[attr(on(expr))] + {} + + // Semi + #[attr(on(semi))] + foo(); + + // Mac + #[attr(on(mac))] + foo!(); +} -- cgit 1.4.1-3-g733a5 From 52805833694ebe370f570467577afba23f034e34 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 30 Aug 2017 19:27:50 +0900 Subject: Format --- src/expr.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f00dc6457f9..f5275942425 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -180,17 +180,11 @@ pub fn format_expr( ) } } - ast::ExprKind::Yield(ref opt_expr) => { - if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape) - } else { - wrap_str( - "yield".to_string(), - context.config.max_width(), - shape, - ) - } - } + ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, "yield ", &**expr, shape) + } else { + wrap_str("yield".to_string(), context.config.max_width(), shape) + }, ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, expr.span, context, shape) } -- cgit 1.4.1-3-g733a5 From 6e5c6f5ba3f0da31a40066fe6c40ab22a4453839 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 19 Aug 2017 21:47:40 +0300 Subject: Use getters to access `Span` fields --- src/chains.rs | 6 +- src/codemap.rs | 10 +- src/expr.rs | 86 ++++++++--------- src/imports.rs | 26 +++--- src/items.rs | 182 ++++++++++++++++++------------------ src/lib.rs | 24 ++--- src/macros.rs | 2 +- src/missed_spans.rs | 8 +- src/patterns.rs | 39 ++++---- src/types.rs | 20 ++-- src/utils.rs | 8 +- src/vertical.rs | 32 +++---- src/visitor.rs | 99 ++++++++++---------- tests/source/closure.rs | 6 +- tests/source/expr-block.rs | 16 ++-- tests/target/closure.rs | 6 +- tests/target/expr-block.rs | 16 ++-- tests/target/nested-visual-block.rs | 12 +-- 18 files changed, 303 insertions(+), 295 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9c129ef99ee..27119dd6f0d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -470,7 +470,7 @@ fn rewrite_method_call( shape: Shape, ) -> Option { let (lo, type_str) = if types.is_empty() { - (args[0].span.hi, String::new()) + (args[0].span.hi(), String::new()) } else { let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); @@ -481,11 +481,11 @@ fn rewrite_method_call( format!("::<{}>", type_list.join(", ")) }; - (types.last().unwrap().span.hi, type_str) + (types.last().unwrap().span.hi(), type_str) }; let callee_str = format!(".{}{}", method_name, type_str); - let span = mk_sp(lo, span.hi); + let span = mk_sp(lo, span.hi()); rewrite_call(context, &callee_str, &args[1..], span, shape) } diff --git a/src/codemap.rs b/src/codemap.rs index 065c39f67c1..e156f34015b 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -50,7 +50,7 @@ impl SpanUtils for CodeMap { let snippet = self.span_to_snippet(original).unwrap(); let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); - original.lo + BytePos(offset as u32) + original.lo() + BytePos(offset as u32) } fn span_after_last(&self, original: Span, needle: &str) -> BytePos { @@ -61,21 +61,21 @@ impl SpanUtils for CodeMap { offset += additional_offset + needle.len(); } - original.lo + BytePos(offset as u32) + original.lo() + BytePos(offset as u32) } fn span_before(&self, original: Span, needle: &str) -> BytePos { let snippet = self.span_to_snippet(original).unwrap(); let offset = snippet.find_uncommented(needle).unwrap(); - original.lo + BytePos(offset as u32) + original.lo() + BytePos(offset as u32) } } impl LineRangeUtils for CodeMap { fn lookup_line_range(&self, span: Span) -> LineRange { - let lo = self.lookup_char_pos(span.lo); - let hi = self.lookup_char_pos(span.hi); + let lo = self.lookup_char_pos(span.lo()); + let hi = self.lookup_char_pos(span.hi()); assert!( lo.file.name == hi.file.name, diff --git a/src/expr.rs b/src/expr.rs index f5275942425..e1c32235386 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -65,7 +65,7 @@ pub fn format_expr( let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( expr_vec.iter().map(|e| &**e), - mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi), + mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi()), context, shape, false, @@ -81,7 +81,7 @@ pub fn format_expr( ), }, ast::ExprKind::Call(ref callee, ref args) => { - let inner_span = mk_sp(callee.span.hi, expr.span.hi); + let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); rewrite_call_with_binary_search( context, &**callee, @@ -308,8 +308,8 @@ pub fn format_expr( let attrs = outer_attributes(&expr.attrs); let attrs_str = try_opt!(attrs.rewrite(context, shape)); let span = mk_sp( - attrs.last().map_or(expr.span.lo, |attr| attr.span.hi), - expr.span.lo, + attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), + expr.span.lo(), ); combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) }) @@ -417,11 +417,11 @@ where context.codemap, expr_iter, "]", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span.lo(), + |item| item.span.hi(), |item| item.rewrite(context, nested_shape), - span.lo, - span.hi, + span.lo(), + span.hi(), false, ).collect::>(); @@ -536,7 +536,7 @@ fn rewrite_closure_fn_decl( |arg| span_hi_for_arg(context, arg), |arg| arg.rewrite(context, arg_shape), context.codemap.span_after(span, "|"), - body.span.lo, + body.span.lo(), false, ); let item_vec = arg_items.collect::>(); @@ -837,9 +837,9 @@ fn rewrite_block_with_visitor( ast::BlockCheckMode::Unsafe(..) => { let snippet = context.snippet(block.span); let open_pos = try_opt!(snippet.find_uncommented("{")); - visitor.last_pos = block.span.lo + BytePos(open_pos as u32) + visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) } - ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo, + ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), } visitor.visit_block(block, None); @@ -1193,7 +1193,7 @@ impl<'a> ControlFlow<'a> { let cond_span = if let Some(cond) = self.cond { cond.span } else { - mk_sp(self.block.span.lo, self.block.span.lo) + mk_sp(self.block.span.lo(), self.block.span.lo()) }; // `for event in event` @@ -1204,8 +1204,8 @@ impl<'a> ControlFlow<'a> { .codemap .span_after(mk_sp(lo, self.span.hi), self.keyword.trim()), self.pat - .map_or(cond_span.lo, |p| if self.matcher.is_empty() { - p.span.lo + .map_or(cond_span.lo(), |p| if self.matcher.is_empty() { + p.span.lo() } else { context.codemap.span_before(self.span, self.matcher.trim()) }), @@ -1214,7 +1214,7 @@ impl<'a> ControlFlow<'a> { let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); let after_cond_comment = - extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape); + extract_comment(mk_sp(cond_span.hi(), self.block.span.lo()), context, shape); let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" @@ -1305,7 +1305,7 @@ impl<'a> Rewrite for ControlFlow<'a> { next_else_block.as_ref().map(|e| &**e), false, true, - mk_sp(else_block.span.lo, self.span.hi), + mk_sp(else_block.span.lo(), self.span.hi()), ).rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { @@ -1316,7 +1316,7 @@ impl<'a> Rewrite for ControlFlow<'a> { next_else_block.as_ref().map(|e| &**e), false, true, - mk_sp(else_block.span.lo, self.span.hi), + mk_sp(else_block.span.lo(), self.span.hi()), ).rewrite(context, shape) } _ => { @@ -1332,10 +1332,10 @@ impl<'a> Rewrite for ControlFlow<'a> { }; let between_kwd_else_block = mk_sp( - self.block.span.hi, + self.block.span.hi(), context .codemap - .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else"), + .span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), ); let between_kwd_else_block_comment = extract_comment(between_kwd_else_block, context, shape); @@ -1343,8 +1343,8 @@ impl<'a> Rewrite for ControlFlow<'a> { let after_else = mk_sp( context .codemap - .span_after(mk_sp(self.block.span.hi, else_block.span.lo), "else"), - else_block.span.lo, + .span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), + else_block.span.lo(), ); let after_else_comment = extract_comment(after_else, context, shape); @@ -1504,9 +1504,9 @@ fn rewrite_match( let open_brace_pos = if inner_attrs.is_empty() { context .codemap - .span_after(mk_sp(cond.span.hi, arms[0].span().lo), "{") + .span_after(mk_sp(cond.span.hi(), arms[0].span().lo()), "{") } else { - inner_attrs[inner_attrs.len() - 1].span().hi + inner_attrs[inner_attrs.len() - 1].span().hi() }; let arm_indent_str = if context.config.indent_match_arms() { @@ -1571,11 +1571,11 @@ fn rewrite_match_arms( .zip(is_last_iter) .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), "}", - |arm| arm.arm.span().lo, - |arm| arm.arm.span().hi, + |arm| arm.arm.span().lo(), + |arm| arm.arm.span().hi(), |arm| arm.rewrite(context, arm_shape), open_brace_pos, - span.hi, + span.hi(), false, ); let arms_vec: Vec<_> = items.collect(); @@ -1611,7 +1611,7 @@ fn rewrite_match_arm( )); } ( - mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi, arm.pats[0].span.lo), + mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi(), arm.pats[0].span.lo()), try_opt!(arm.attrs.rewrite(context, shape)), ) } else { @@ -1973,7 +1973,7 @@ fn string_requires_rewrite( string: &str, shape: Shape, ) -> bool { - if context.codemap.lookup_char_pos(span.lo).col.0 != shape.indent.width() { + if context.codemap.lookup_char_pos(span.lo()).col.0 != shape.indent.width() { return true; } @@ -2087,7 +2087,7 @@ where ).ok_or(Ordering::Greater)?; let span_lo = context.codemap.span_after(span, "("); - let args_span = mk_sp(span_lo, span.hi); + let args_span = mk_sp(span_lo, span.hi()); let (extendable, list_str) = rewrite_call_args( context, @@ -2146,11 +2146,11 @@ where context.codemap, args.iter(), ")", - |item| item.span().lo, - |item| item.span().hi, + |item| item.span().lo(), + |item| item.span().hi(), |item| item.rewrite(context, shape), - span.lo, - span.hi, + span.lo(), + span.hi(), true, ); let mut item_vec: Vec<_> = items.collect(); @@ -2569,7 +2569,7 @@ fn rewrite_struct_lit<'a>( fields, context, shape, - mk_sp(body_lo, span.hi), + mk_sp(body_lo, span.hi()), one_line_width, )) } else { @@ -2579,17 +2579,17 @@ fn rewrite_struct_lit<'a>( .chain(base.into_iter().map(StructLitField::Base)); let span_lo = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span().lo, + StructLitField::Regular(field) => field.span().lo(), StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) } }; let span_hi = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span().hi, - StructLitField::Base(expr) => expr.span.hi, + StructLitField::Regular(field) => field.span().hi(), + StructLitField::Base(expr) => expr.span.hi(), }; let rewrite = |item: &StructLitField| match *item { StructLitField::Regular(field) => { @@ -2611,7 +2611,7 @@ fn rewrite_struct_lit<'a>( span_hi, rewrite, body_lo, - span.hi, + span.hi(), false, ); let item_vec = items.collect::>(); @@ -2760,11 +2760,11 @@ where context.codemap, items, ")", - |item| item.span().lo, - |item| item.span().hi, + |item| item.span().lo(), + |item| item.span().hi(), |item| item.rewrite(context, nested_shape), list_lo, - span.hi - BytePos(1), + span.hi() - BytePos(1), false, ); let item_vec: Vec<_> = items.collect(); diff --git a/src/imports.rs b/src/imports.rs index afa81693548..04492665d70 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -198,9 +198,9 @@ impl<'a> FmtVisitor<'a> { self.last_pos, p_i.attrs .iter() - .map(|attr| attr.span.lo) + .map(|attr| attr.span.lo()) .min() - .unwrap_or(p_i.span.lo), + .unwrap_or(p_i.span.lo()), ) }) .unwrap_or(self.last_pos); @@ -211,7 +211,7 @@ impl<'a> FmtVisitor<'a> { .iter() .map(|p_i| { let new_item = (&*p_i, last_pos_of_prev_use_item); - last_pos_of_prev_use_item = p_i.span.hi; + last_pos_of_prev_use_item = p_i.span.hi(); new_item }) .collect::>(); @@ -275,23 +275,23 @@ impl<'a> FmtVisitor<'a> { match rw { Some(ref s) if s.is_empty() => { // Format up to last newline - let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo); + let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo()); let span_end = match self.snippet(prev_span).rfind('\n') { Some(offset) => self.last_pos + BytePos(offset as u32), - None => source!(self, span).lo, + None => source!(self, span).lo(), }; self.format_missing(span_end); - self.last_pos = source!(self, span).hi; + self.last_pos = source!(self, span).hi(); } Some(ref s) => { let s = format!("{}use {};", vis, s); - self.format_missing_with_indent(source!(self, span).lo); + self.format_missing_with_indent(source!(self, span).lo()); self.buffer.push_str(&s); - self.last_pos = source!(self, span).hi; + self.last_pos = source!(self, span).hi(); } None => { - self.format_missing_with_indent(source!(self, span).lo); - self.format_missing(source!(self, span).hi); + self.format_missing_with_indent(source!(self, span).lo()); + self.format_missing(source!(self, span).hi()); } } } @@ -442,11 +442,11 @@ fn rewrite_use_list( context.codemap, path_list.iter(), "}", - |vpi| vpi.span.lo, - |vpi| vpi.span.hi, + |vpi| vpi.span.lo(), + |vpi| vpi.span.hi(), rewrite_path_item, context.codemap.span_after(span, "{"), - span.hi, + span.hi(), false, ); items.extend(iter); diff --git a/src/items.rs b/src/items.rs index 50efea4044e..500150d877a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -167,11 +167,11 @@ impl<'a> FmtVisitor<'a> { if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { // FIXME: this skips comments between the extern keyword and the opening // brace. - self.last_pos = item.span.lo + BytePos(brace_pos as u32 + 1); + self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1); self.block_indent = self.block_indent.block_indent(self.config); if item.body.is_empty() { - self.format_missing_no_indent(item.span.hi - BytePos(1)); + self.format_missing_no_indent(item.span.hi() - BytePos(1)); self.block_indent = self.block_indent.block_unindent(self.config); self.buffer @@ -182,12 +182,12 @@ impl<'a> FmtVisitor<'a> { } self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(item.span.hi - BytePos(1)); + self.format_missing_with_indent(item.span.hi() - BytePos(1)); } } self.buffer.push_str("}"); - self.last_pos = item.span.hi; + self.last_pos = item.span.hi(); } fn format_body_element(&mut self, element: &BodyElement) { @@ -205,7 +205,7 @@ impl<'a> FmtVisitor<'a> { fn format_foreign_item(&mut self, item: &ast::ForeignItem) { let rewrite = item.rewrite(&self.get_context(), self.shape()); self.push_rewrite(item.span(), rewrite); - self.last_pos = item.span.hi; + self.last_pos = item.span.hi(); } pub fn rewrite_fn( @@ -224,7 +224,7 @@ impl<'a> FmtVisitor<'a> { ) -> Option { let context = self.get_context(); - let block_snippet = self.snippet(mk_sp(block.span.lo, block.span.hi)); + let block_snippet = self.snippet(mk_sp(block.span.lo(), block.span.hi())); let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || !context.config.fn_empty_single_line(); let mut newline_brace = newline_for_brace(self.config, &generics.where_clause, has_body); @@ -277,7 +277,7 @@ impl<'a> FmtVisitor<'a> { span: Span, ) -> Option { // Drop semicolon or it will be interpreted as comment. - let span = mk_sp(span.lo, span.hi - BytePos(1)); + let span = mk_sp(span.lo(), span.hi() - BytePos(1)); let context = self.get_context(); let (mut result, _) = try_opt!(rewrite_fn_base( @@ -362,7 +362,7 @@ impl<'a> FmtVisitor<'a> { let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); - let body_start = span.lo + BytePos(brace_pos as u32 + 1); + let body_start = span.lo() + BytePos(brace_pos as u32 + 1); let generics_str = format_generics( &self.get_context(), generics, @@ -371,7 +371,7 @@ impl<'a> FmtVisitor<'a> { self.config.item_brace_style(), enum_def.variants.is_empty(), self.block_indent, - mk_sp(span.lo, body_start), + mk_sp(span.lo(), body_start), last_line_width(&enum_header), ).unwrap(); self.buffer.push_str(&generics_str); @@ -379,13 +379,13 @@ impl<'a> FmtVisitor<'a> { self.last_pos = body_start; self.block_indent = self.block_indent.block_indent(self.config); - let variant_list = self.format_variant_list(enum_def, body_start, span.hi - BytePos(1)); + let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); match variant_list { Some(ref body_str) => self.buffer.push_str(body_str), None => if contains_comment(&enum_snippet[brace_pos..]) { - self.format_missing_no_indent(span.hi - BytePos(1)) + self.format_missing_no_indent(span.hi() - BytePos(1)) } else { - self.format_missing(span.hi - BytePos(1)) + self.format_missing(span.hi() - BytePos(1)) }, } self.block_indent = self.block_indent.block_unindent(self.config); @@ -395,7 +395,7 @@ impl<'a> FmtVisitor<'a> { .push_str(&self.block_indent.to_string(self.config)); } self.buffer.push_str("}"); - self.last_pos = span.hi; + self.last_pos = span.hi(); } // Format the body of an enum definition @@ -418,11 +418,11 @@ impl<'a> FmtVisitor<'a> { enum_def.variants.iter(), "}", |f| if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo + f.node.attrs[0].span.lo() } else { - f.span.lo + f.span.lo() }, - |f| f.span.hi, + |f| f.span.hi(), |f| self.format_variant(f), body_lo, body_hi, @@ -450,8 +450,8 @@ impl<'a> FmtVisitor<'a> { // Variant of an enum. fn format_variant(&self, field: &ast::Variant) -> Option { if contains_skip(&field.node.attrs) { - let lo = field.node.attrs[0].span.lo; - let span = mk_sp(lo, field.span.hi); + let lo = field.node.attrs[0].span.lo(); + let span = mk_sp(lo, field.span.hi()); return Some(self.snippet(span)); } @@ -463,8 +463,8 @@ impl<'a> FmtVisitor<'a> { .node .attrs .last() - .map_or(field.span.lo, |attr| attr.span.hi); - let span = mk_sp(lo, field.span.lo); + .map_or(field.span.lo(), |attr| attr.span.hi()); + let span = mk_sp(lo, field.span.lo()); let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { @@ -547,7 +547,7 @@ pub fn format_impl( context.config.where_density(), "{", where_span_end, - self_ty.span.hi, + self_ty.span.hi(), option, )); @@ -612,14 +612,14 @@ pub fn format_impl( if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); for item in items { visitor.visit_impl_item(item); } - visitor.format_missing(item.span.hi - BytePos(1)); + visitor.format_missing(item.span.hi() - BytePos(1)); let inner_indent_str = visitor.block_indent.to_string(context.config); let outer_indent_str = offset.block_only().to_string(context.config); @@ -683,8 +683,8 @@ fn format_impl_ref_and_type( let lo = context.codemap.span_after(item.span, "impl"); let hi = match *trait_ref { - Some(ref tr) => tr.path.span.lo, - None => self_ty.span.lo, + Some(ref tr) => tr.path.span.lo(), + None => self_ty.span.lo(), }; let shape = try_opt!(generics_shape_from_config( context.config, @@ -891,7 +891,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) context, generics, shape, - mk_sp(item.span.lo, body_lo), + mk_sp(item.span.lo(), body_lo), )); result.push_str(&generics_str); @@ -931,9 +931,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) .checked_sub(last_line_width(&result)) ); let pos_before_where = if type_param_bounds.is_empty() { - generics.where_clause.span.lo + generics.where_clause.span.lo() } else { - type_param_bounds[type_param_bounds.len() - 1].span().hi + type_param_bounds[type_param_bounds.len() - 1].span().hi() }; let option = WhereClauseOption::snuggled(&generics_str); let where_clause_str = try_opt!(rewrite_where_clause( @@ -1009,13 +1009,13 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); for item in trait_items { visitor.visit_trait_item(item); } - visitor.format_missing(item.span.hi - BytePos(1)); + visitor.format_missing(item.span.hi() - BytePos(1)); let inner_indent_str = visitor.block_indent.to_string(context.config); let outer_indent_str = offset.block_only().to_string(context.config); @@ -1067,7 +1067,7 @@ pub fn format_struct_struct( context.config.item_brace_style(), fields.is_empty(), offset, - mk_sp(span.lo, body_lo), + mk_sp(span.lo(), body_lo), last_line_width(&result), )), None => { @@ -1103,7 +1103,7 @@ pub fn format_struct_struct( } if fields.is_empty() { - let snippet = context.snippet(mk_sp(body_lo, span.hi - BytePos(1))); + let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1))); if snippet.trim().is_empty() { // `struct S {}` } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { @@ -1131,7 +1131,7 @@ pub fn format_struct_struct( fields, context, Shape::indented(offset, context.config), - mk_sp(body_lo, span.hi), + mk_sp(body_lo, span.hi()), one_line_budget, )); @@ -1168,7 +1168,7 @@ fn format_tuple_struct( let body_lo = if fields.is_empty() { context.codemap.span_after(span, "(") } else { - fields[0].span.lo + fields[0].span.lo() }; let body_hi = if fields.is_empty() { context.codemap.span_after(span, ")") @@ -1176,11 +1176,11 @@ fn format_tuple_struct( // This is a dirty hack to work around a missing `)` from the span of the last field. let last_arg_span = fields[fields.len() - 1].span; if context.snippet(last_arg_span).ends_with(")") { - last_arg_span.hi + last_arg_span.hi() } else { context .codemap - .span_after(mk_sp(last_arg_span.hi, span.hi), ")") + .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") } }; @@ -1188,7 +1188,7 @@ fn format_tuple_struct( Some(generics) => { let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); - let g_span = mk_sp(span.lo, body_lo); + let g_span = mk_sp(span.lo(), body_lo); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); @@ -1279,7 +1279,7 @@ pub fn rewrite_type_alias( // 2 = `= ` let shape = try_opt!(Shape::indented(indent + result.len(), context.config).sub_width(2)); - let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo); + let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo()); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); @@ -1297,8 +1297,8 @@ pub fn rewrite_type_alias( Shape::legacy(where_budget, indent), context.config.where_density(), "=", - Some(span.hi), - generics.span.hi, + Some(span.hi()), + generics.span.hi(), option, )); result.push_str(&where_clause_str); @@ -1396,7 +1396,7 @@ pub fn rewrite_struct_field( lhs_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - let span = context.snippet(mk_sp(field.attrs[0].span.lo, field.span.hi)); + let span = context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi())); return wrap_str(span, context.config.max_width(), shape); } @@ -1407,9 +1407,9 @@ pub fn rewrite_struct_field( let attrs_extendable = attrs_str.is_empty() || (context.config.attributes_on_same_line_as_field() && is_attributes_extendable(&attrs_str)); let missing_span = if field.attrs.is_empty() { - mk_sp(field.span.lo, field.span.lo) + mk_sp(field.span.lo(), field.span.lo()) } else { - mk_sp(field.attrs.last().unwrap().span.hi, field.span.lo) + mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo()) }; let mut spacing = String::from(if field.ident.is_some() { type_annotation_spacing.1 @@ -1706,17 +1706,17 @@ fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { if is_named_arg(arg) { - arg.pat.span.lo + arg.pat.span.lo() } else { - arg.ty.span.lo + arg.ty.span.lo() } } pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { match arg.ty.node { - ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi, - ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi, - _ => arg.ty.span.hi, + ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), + ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), + _ => arg.ty.span.hi(), } } @@ -1782,7 +1782,7 @@ fn rewrite_fn_base( indent: indent, offset: used_width, }; - let g_span = mk_sp(span.lo, fd.output.span().lo); + let g_span = mk_sp(span.lo(), fd.output.span().lo()); let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); @@ -1850,15 +1850,19 @@ fn rewrite_fn_base( let args_start = generics .ty_params .last() - .map_or(span.lo, |tp| end_typaram(tp)); + .map_or(span.lo(), |tp| end_typaram(tp)); let args_end = if fd.inputs.is_empty() { - context.codemap.span_after(mk_sp(args_start, span.hi), ")") + context + .codemap + .span_after(mk_sp(args_start, span.hi()), ")") } else { - let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi, span.hi); + let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); context.codemap.span_after(last_span, ")") }; let args_span = mk_sp( - context.codemap.span_after(mk_sp(args_start, span.hi), "("), + context + .codemap + .span_after(mk_sp(args_start, span.hi()), "("), args_end, ); let arg_str = try_opt!(rewrite_args( @@ -1970,9 +1974,9 @@ fn rewrite_fn_base( } // Comment between return type and the end of the decl. - let snippet_lo = fd.output.span().hi; + let snippet_lo = fd.output.span().hi(); if where_clause.predicates.is_empty() { - let snippet_hi = span.hi; + let snippet_hi = span.hi(); let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); // Try to preserve the layout of the original snippet. let original_starts_with_newline = snippet @@ -2003,8 +2007,8 @@ fn rewrite_fn_base( }; let pos_before_where = match fd.output { - ast::FunctionRetTy::Default(..) => args_span.hi, - ast::FunctionRetTy::Ty(ref ty) => ty.span.hi, + ast::FunctionRetTy::Default(..) => args_span.hi(), + ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), }; if where_clause.predicates.len() == 1 && should_compress_where { @@ -2020,7 +2024,7 @@ fn rewrite_fn_base( Shape::legacy(budget, indent), Density::Compressed, "{", - Some(span.hi), + Some(span.hi()), pos_before_where, WhereClauseOption::compressed(), ) { @@ -2038,7 +2042,7 @@ fn rewrite_fn_base( Shape::indented(indent, context.config), Density::Tall, "{", - Some(span.hi), + Some(span.hi()), pos_before_where, option, )); @@ -2047,7 +2051,7 @@ fn rewrite_fn_base( if where_clause_str.is_empty() { if let ast::FunctionRetTy::Default(ret_span) = fd.output { match recover_missing_comment_in_span( - mk_sp(args_span.hi, ret_span.hi), + mk_sp(args_span.hi(), ret_span.hi()), shape, context, last_line_width(&result), @@ -2144,15 +2148,15 @@ fn rewrite_args( if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { let second_arg_start = if arg_has_pattern(&args[1]) { - args[1].pat.span.lo + args[1].pat.span.lo() } else { - args[1].ty.span.lo + args[1].ty.span.lo() }; - let reduced_span = mk_sp(span.lo, second_arg_start); + let reduced_span = mk_sp(span.lo(), second_arg_start); context.codemap.span_after_last(reduced_span, ",") } else { - span.lo + span.lo() }; enum ArgumentKind<'a> { @@ -2161,7 +2165,7 @@ fn rewrite_args( } let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last().unwrap().ty.span.hi, span.hi); + let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi()); let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); Some(ArgumentKind::Variadic(variadic_start)) } else { @@ -2180,7 +2184,7 @@ fn rewrite_args( ArgumentKind::Variadic(start) => start, }, |arg| match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi, + ArgumentKind::Regular(arg) => arg.ty.span.hi(), ArgumentKind::Variadic(start) => start + BytePos(3), }, |arg| match *arg { @@ -2188,7 +2192,7 @@ fn rewrite_args( ArgumentKind::Variadic(..) => Some("...".to_owned()), }, comment_span_start, - span.hi, + span.hi(), false, ); @@ -2376,11 +2380,11 @@ fn rewrite_generics_inner( // Extract comments between generics. let lt_spans = lifetimes.iter().map(|l| { let hi = if l.bounds.is_empty() { - l.lifetime.span.hi + l.lifetime.span.hi() } else { - l.bounds[l.bounds.len() - 1].span.hi + l.bounds[l.bounds.len() - 1].span.hi() }; - mk_sp(l.lifetime.span.lo, hi) + mk_sp(l.lifetime.span.lo(), hi) }); let ty_spans = tys.iter().map(|ty| ty.span()); @@ -2388,12 +2392,12 @@ fn rewrite_generics_inner( context.codemap, lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), ">", - |&(sp, _)| sp.lo, - |&(sp, _)| sp.hi, + |&(sp, _)| sp.lo(), + |&(sp, _)| sp.hi(), // FIXME: don't clone |&(_, ref str)| str.clone(), context.codemap.span_after(span, "<"), - span.hi, + span.hi(), false, ); format_generics_item_list(context, items, shape, one_line_width) @@ -2524,18 +2528,18 @@ fn rewrite_where_clause_rfc_style( let clause_shape = block_shape.block_indent(context.config.tab_spaces()); // each clause on one line, trailing comma (except if suppress_comma) - let span_start = where_clause.predicates[0].span().lo; + let span_start = where_clause.predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi; + let end_of_preds = where_clause.predicates[len - 1].span().hi(); let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list( context.codemap, where_clause.predicates.iter(), terminator, - |pred| pred.span().lo, - |pred| pred.span().hi, + |pred| pred.span().lo(), + |pred| pred.span().hi(), |pred| pred.rewrite(context, block_shape), span_start, span_end, @@ -2626,18 +2630,18 @@ fn rewrite_where_clause( // be out by a char or two. let budget = context.config.max_width() - offset.width(); - let span_start = where_clause.predicates[0].span().lo; + let span_start = where_clause.predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi; + let end_of_preds = where_clause.predicates[len - 1].span().hi(); let span_end = span_end.unwrap_or(end_of_preds); let items = itemize_list( context.codemap, where_clause.predicates.iter(), terminator, - |pred| pred.span().lo, - |pred| pred.span().hi, + |pred| pred.span().lo(), + |pred| pred.span().hi(), |pred| pred.rewrite(context, Shape::legacy(budget, offset)), span_start, span_end, @@ -2700,10 +2704,10 @@ fn missing_span_before_after_where( before_item_span_end: BytePos, where_clause: &ast::WhereClause, ) -> (Span, Span) { - let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo); + let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo()); // 5 = `where` - let pos_after_where = where_clause.span.lo + BytePos(5); - let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo); + let pos_after_where = where_clause.span.lo() + BytePos(5); + let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo()); (missing_span_before, missing_span_after) } @@ -2754,8 +2758,8 @@ fn format_generics( Shape::legacy(budget, offset.block_only()), Density::Tall, terminator, - Some(span.hi), - generics.span.hi, + Some(span.hi()), + generics.span.hi(), option, )); result.push_str(&where_clause_str); @@ -2796,7 +2800,7 @@ impl Rewrite for ast::ForeignItem { let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); // Drop semicolon or it will be interpreted as comment. // FIXME: this may be a faulty span from libsyntax. - let span = mk_sp(self.span.lo, self.span.hi - BytePos(1)); + let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = try_opt!(match self.node { ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { @@ -2841,9 +2845,9 @@ impl Rewrite for ast::ForeignItem { }); let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo, self.span.lo) + mk_sp(self.span.lo(), self.span.lo()) } else { - mk_sp(self.attrs[self.attrs.len() - 1].span.hi, self.span.lo) + mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo()) }; combine_strs_with_missing_comments( context, diff --git a/src/lib.rs b/src/lib.rs index c45110ea06b..da87ede7c60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,7 +86,7 @@ macro_rules! span_with_attrs_lo_hi { if attrs.is_empty() { mk_sp($lo, $hi) } else { - mk_sp(attrs[0].span.lo, $hi) + mk_sp(attrs[0].span.lo(), $hi) } } } @@ -94,7 +94,7 @@ macro_rules! span_with_attrs_lo_hi { macro_rules! span_with_attrs { ($this:ident) => { - span_with_attrs_lo_hi!($this, $this.span.lo, $this.span.hi) + span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) } } @@ -121,7 +121,7 @@ impl Spanned for ast::Stmt { ast::StmtKind::Local(ref local) => mk_sp(local.span().lo, self.span.hi), ast::StmtKind::Item(ref item) => mk_sp(item.span().lo, self.span.hi), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { - mk_sp(expr.span().lo, self.span.hi) + mk_sp(expr.span().lo(), self.span.hi()) } ast::StmtKind::Mac(ref mac) => { let (_, _, ref attrs) = **mac; @@ -149,14 +149,14 @@ impl Spanned for ast::Ty { impl Spanned for ast::Arm { fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.pats[0].span.lo, self.body.span.hi) + span_with_attrs_lo_hi!(self, self.pats[0].span.lo(), self.body.span.hi()) } } impl Spanned for ast::Arg { fn span(&self) -> Span { if items::is_named_arg(self) { - utils::mk_sp(self.pat.span.lo, self.ty.span.hi) + utils::mk_sp(self.pat.span.lo(), self.ty.span.hi()) } else { self.ty.span } @@ -165,7 +165,7 @@ impl Spanned for ast::Arg { impl Spanned for ast::StructField { fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.span.lo, self.ty.span.hi) + span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) } } @@ -192,17 +192,17 @@ impl Spanned for ast::TyParam { fn span(&self) -> Span { // Note that ty.span is the span for ty.ident, not the whole item. let lo = if self.attrs.is_empty() { - self.span.lo + self.span.lo() } else { - self.attrs[0].span.lo + self.attrs[0].span.lo() }; if let Some(ref def) = self.default { - return mk_sp(lo, def.span.hi); + return mk_sp(lo, def.span.hi()); } if self.bounds.is_empty() { - return mk_sp(lo, self.span.hi); + return mk_sp(lo, self.span.hi()); } - let hi = self.bounds[self.bounds.len() - 1].span().hi; + let hi = self.bounds[self.bounds.len() - 1].span().hi(); mk_sp(lo, hi) } } @@ -705,7 +705,7 @@ where } { let mut visitor = FmtVisitor::from_codemap(parse_session, config); - let filemap = visitor.codemap.lookup_char_pos(module.inner.lo).file; + let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; // Format inner attributes if available. if !krate.attrs.is_empty() && path == main_file { visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); diff --git a/src/macros.rs b/src/macros.rs index 12965b61560..d9156e08e85 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -234,7 +234,7 @@ pub fn rewrite_macro( context .codemap .span_after(mac.span, original_style.opener()), - mac.span.hi - BytePos(1), + mac.span.hi() - BytePos(1), ), context, mac_shape, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b85bc44b162..43e81e12f71 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -82,14 +82,14 @@ impl<'a> FmtVisitor<'a> { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment // follows code on the same line, we won't touch it. - let big_span_lo = self.codemap.lookup_char_pos(span.lo).file.start_pos; + let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos; let local_begin = self.codemap.lookup_byte_offset(big_span_lo); - let local_end = self.codemap.lookup_byte_offset(span.hi); + let local_end = self.codemap.lookup_byte_offset(span.hi()); let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; - let big_diff = (span.lo - big_span_lo).to_usize(); + let big_diff = (span.lo() - big_span_lo).to_usize(); let snippet = self.snippet(span.clone()); debug!("write_snippet `{}`", snippet); @@ -114,7 +114,7 @@ impl<'a> FmtVisitor<'a> { let mut last_wspace = None; let mut rewrite_next_comment = true; - let char_pos = self.codemap.lookup_char_pos(span.lo); + let char_pos = self.codemap.lookup_char_pos(span.lo()); let file_name = &char_pos.file.name; let mut cur_line = char_pos.line; diff --git a/src/patterns.rs b/src/patterns.rs index aa163c2d4d8..70d94f4bee7 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -157,11 +157,11 @@ fn rewrite_struct_pat( context.codemap, fields.iter(), terminator, - |f| f.span.lo, - |f| f.span.hi, + |f| f.span.lo(), + |f| f.span.hi(), |f| f.node.rewrite(context, v_shape), context.codemap.span_after(span, "{"), - span.hi, + span.hi(), false, ); let item_vec = items.collect::>(); @@ -266,24 +266,24 @@ fn rewrite_tuple_pat( if let Some(pos) = dotdot_pos { let prev = if pos == 0 { - span.lo + span.lo() } else { - pats[pos - 1].span().hi + pats[pos - 1].span().hi() }; let next = if pos + 1 >= pats.len() { - span.hi + span.hi() } else { - pats[pos + 1].span().lo + pats[pos + 1].span().lo() }; let dot_span = mk_sp(prev, next); let snippet = context.snippet(dot_span); - let lo = dot_span.lo + BytePos(snippet.find_uncommented("..").unwrap() as u32); - let dotdot = TuplePatField::Dotdot(Span { - lo: lo, + let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32); + let dotdot = TuplePatField::Dotdot(Span::new( + lo, // 2 == "..".len() - hi: lo + BytePos(2), - ctxt: codemap::NO_EXPANSION, - }); + lo + BytePos(2), + codemap::NO_EXPANSION, + )); pat_vec.insert(pos, dotdot); } @@ -297,9 +297,12 @@ fn rewrite_tuple_pat( let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; let sp = pat_vec[new_item_count - 1].span(); let snippet = context.snippet(sp); - let lo = sp.lo + BytePos(snippet.find_uncommented("_").unwrap() as u32); + let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); - (&pat_vec[..new_item_count], mk_sp(span.lo, lo + BytePos(1))) + ( + &pat_vec[..new_item_count], + mk_sp(span.lo(), lo + BytePos(1)), + ) } else { (&pat_vec[..], span) }; @@ -338,11 +341,11 @@ fn count_wildcard_suffix_len( context.codemap, patterns.iter(), ")", - |item| item.span().lo, - |item| item.span().hi, + |item| item.span().lo(), + |item| item.span().hi(), |item| item.rewrite(context, shape), context.codemap.span_after(span, "("), - span.hi - BytePos(1), + span.hi() - BytePos(1), false, ).collect(); diff --git a/src/types.rs b/src/types.rs index 455c4ad5ae4..86a6e4d3d72 100644 --- a/src/types.rs +++ b/src/types.rs @@ -50,7 +50,7 @@ pub fn rewrite_path( String::new() }; - let mut span_lo = path.span.lo; + let mut span_lo = path.span.lo(); if let Some(qself) = qself { result.push('<'); @@ -76,7 +76,7 @@ pub fn rewrite_path( result, path.segments.iter().take(skip_count), span_lo, - path.span.hi, + path.span.hi(), context, shape, )); @@ -87,7 +87,7 @@ pub fn rewrite_path( } result.push_str(">::"); - span_lo = qself.ty.span.hi + BytePos(1); + span_lo = qself.ty.span.hi() + BytePos(1); } rewrite_path_segments( @@ -95,7 +95,7 @@ pub fn rewrite_path( result, path.segments.iter().skip(skip_count), span_lo, - path.span.hi, + path.span.hi(), context, shape, ) @@ -218,7 +218,7 @@ fn rewrite_segment( .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1); + let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1); let list_lo = context.codemap.span_after(mk_sp(*span_lo, span_hi), "<"); let separator = if path_context == PathContext::Expr { "::" @@ -236,8 +236,8 @@ fn rewrite_segment( context.codemap, param_list.into_iter(), ">", - |param| param.get_span().lo, - |param| param.get_span().hi, + |param| param.get_span().lo(), + |param| param.get_span().hi(), |seg| seg.rewrite(context, generics_shape), list_lo, span_hi, @@ -332,11 +332,11 @@ where .chain(variadic_arg), ")", |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo, + ArgumentKind::Regular(ref ty) => ty.span().lo(), ArgumentKind::Variadic(start) => start, }, |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi, + ArgumentKind::Regular(ref ty) => ty.span().hi(), ArgumentKind::Variadic(start) => start + BytePos(3), }, |arg| match *arg { @@ -344,7 +344,7 @@ where ArgumentKind::Variadic(_) => Some("...".to_owned()), }, list_lo, - span.hi, + span.hi(), false, ); diff --git a/src/utils.rs b/src/utils.rs index bd46ef1bc6a..f99e1958f8c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -208,7 +208,7 @@ pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { ast::RegionTyParamBound(ref lt) => lt.span, ast::TraitTyParamBound(ref prt, _) => prt.span, }) - .hi + .hi() } #[inline] @@ -363,11 +363,7 @@ macro_rules! source { } pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { - Span { - lo, - hi, - ctxt: NO_EXPANSION, - } + Span::new(lo, hi, NO_EXPANSION) } // Return true if the given span does not intersect with file lines. diff --git a/src/vertical.rs b/src/vertical.rs index 5c48acbb9d0..600bdeaba3a 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -49,9 +49,9 @@ impl AlignedItem for ast::StructField { fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo, self.span.lo) + mk_sp(self.span.lo(), self.span.lo()) } else { - mk_sp(self.attrs.last().unwrap().span.hi, self.span.lo) + mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; rewrite_struct_field_prefix(context, self).and_then(|field_str| { combine_strs_with_missing_comments( @@ -88,9 +88,9 @@ impl AlignedItem for ast::Field { let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); let name = &self.ident.node.to_string(); let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo, self.span.lo) + mk_sp(self.span.lo(), self.span.lo()) } else { - mk_sp(self.attrs.last().unwrap().span.hi, self.span.lo) + mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; combine_strs_with_missing_comments( context, @@ -127,15 +127,15 @@ pub fn rewrite_with_alignment( let init = &fields[0..group_index + 1]; let rest = &fields[group_index + 1..]; let init_last_pos = if rest.is_empty() { - span.hi + span.hi() } else { // Decide whether the missing comments should stick to init or rest. - let init_hi = init[init.len() - 1].get_span().hi; - let rest_lo = rest[0].get_span().lo; + let init_hi = init[init.len() - 1].get_span().hi(); + let rest_lo = rest[0].get_span().lo(); let missing_span = mk_sp(init_hi, rest_lo); let missing_span = mk_sp( context.codemap.span_after(missing_span, ","), - missing_span.hi, + missing_span.hi(), ); let snippet = context.snippet(missing_span); @@ -158,10 +158,10 @@ pub fn rewrite_with_alignment( init_hi + BytePos(offset as u32 + 2) } else { - missing_span.lo + missing_span.lo() } }; - let init_span = mk_sp(span.lo, init_last_pos); + let init_span = mk_sp(span.lo(), init_last_pos); let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; let result = try_opt!(rewrite_aligned_items_inner( context, @@ -173,7 +173,7 @@ pub fn rewrite_with_alignment( if rest.is_empty() { Some(result + spaces) } else { - let rest_span = mk_sp(init_last_pos, span.hi); + let rest_span = mk_sp(init_last_pos, span.hi()); let rest_str = try_opt!(rewrite_with_alignment( rest, context, @@ -239,11 +239,11 @@ fn rewrite_aligned_items_inner( context.codemap, fields.iter(), "}", - |field| field.get_span().lo, - |field| field.get_span().hi, + |field| field.get_span().lo(), + |field| field.get_span().hi(), |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), - span.lo, - span.hi, + span.lo(), + span.hi(), false, ).collect::>(); @@ -277,7 +277,7 @@ fn group_aligned_items( return ("", index); } // See if there are comments or empty lines between fields. - let span = mk_sp(fields[i].get_span().hi, fields[i + 1].get_span().lo); + let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo()); let snippet = context .snippet(span) .lines() diff --git a/src/visitor.rs b/src/visitor.rs index b4c4bf3553f..057bd0ee7ee 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -65,8 +65,8 @@ impl<'a> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { debug!( "visit_stmt: {:?} {:?}", - self.codemap.lookup_char_pos(stmt.span.lo), - self.codemap.lookup_char_pos(stmt.span.hi) + self.codemap.lookup_char_pos(stmt.span.lo()), + self.codemap.lookup_char_pos(stmt.span.hi()) ); match stmt.node { @@ -93,7 +93,7 @@ impl<'a> FmtVisitor<'a> { } else { self.visit_mac(mac, None, MacroPosition::Statement); } - self.format_missing(stmt.span.hi); + self.format_missing(stmt.span.hi()); } } } @@ -101,8 +101,8 @@ impl<'a> FmtVisitor<'a> { pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>) { debug!( "visit_block: {:?} {:?}", - self.codemap.lookup_char_pos(b.span.lo), - self.codemap.lookup_char_pos(b.span.hi) + self.codemap.lookup_char_pos(b.span.lo()), + self.codemap.lookup_char_pos(b.span.hi()) ); // Check if this block has braces. @@ -118,7 +118,7 @@ impl<'a> FmtVisitor<'a> { if let Some(first_stmt) = b.stmts.first() { let attr_lo = inner_attrs .and_then(|attrs| { - inner_attributes(attrs).first().map(|attr| attr.span.lo) + inner_attributes(attrs).first().map(|attr| attr.span.lo()) }) .or_else(|| { // Attributes for an item in a statement position @@ -130,8 +130,8 @@ impl<'a> FmtVisitor<'a> { }.and_then(|attr| { // Some stmts can have embedded attributes. // e.g. `match { #![attr] ... }` - let attr_lo = attr.span.lo; - if attr_lo < first_stmt.span.lo { + let attr_lo = attr.span.lo(); + if attr_lo < first_stmt.span.lo() { Some(attr_lo) } else { None @@ -139,8 +139,10 @@ impl<'a> FmtVisitor<'a> { }) }); - let snippet = - self.snippet(mk_sp(self.last_pos, attr_lo.unwrap_or(first_stmt.span.lo))); + let snippet = self.snippet(mk_sp( + self.last_pos, + attr_lo.unwrap_or(first_stmt.span.lo()), + )); let len = CommentCodeSlices::new(&snippet).nth(0).and_then( |(kind, _, s)| if kind == CodeCharKind::Normal { s.rfind('\n') @@ -175,8 +177,8 @@ impl<'a> FmtVisitor<'a> { if self.config.remove_blank_lines_at_start_or_end_of_block() { if let Some(stmt) = b.stmts.last() { let snippet = self.snippet(mk_sp( - stmt.span.hi, - source!(self, b.span).hi - brace_compensation, + stmt.span.hi(), + source!(self, b.span).hi() - brace_compensation, )); let len = CommentCodeSlices::new(&snippet) .last() @@ -203,12 +205,14 @@ impl<'a> FmtVisitor<'a> { if unindent_comment { self.block_indent = self.block_indent.block_unindent(self.config); } - self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation - remove_len); + self.format_missing_with_indent( + source!(self, b.span).hi() - brace_compensation - remove_len, + ); if unindent_comment { self.block_indent = self.block_indent.block_indent(self.config); } self.close_block(unindent_comment); - self.last_pos = source!(self, b.span).hi; + self.last_pos = source!(self, b.span).hi(); } // FIXME: this is a terrible hack to indent the comments between the last @@ -255,7 +259,7 @@ impl<'a> FmtVisitor<'a> { defaultness, abi, vis, - mk_sp(s.lo, b.span.lo), + mk_sp(s.lo(), b.span.lo()), &b, ) } @@ -271,7 +275,7 @@ impl<'a> FmtVisitor<'a> { defaultness, sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), - mk_sp(s.lo, b.span.lo), + mk_sp(s.lo(), b.span.lo()), &b, ) } @@ -279,19 +283,19 @@ impl<'a> FmtVisitor<'a> { }; if let Some(fn_str) = rewrite { - self.format_missing_with_indent(source!(self, s).lo); + self.format_missing_with_indent(source!(self, s).lo()); self.buffer.push_str(&fn_str); if let Some(c) = fn_str.chars().last() { if c == '}' { - self.last_pos = source!(self, block.span).hi; + self.last_pos = source!(self, block.span).hi(); return; } } } else { - self.format_missing(source!(self, block.span).lo); + self.format_missing(source!(self, block.span).lo()); } - self.last_pos = source!(self, block.span).lo; + self.last_pos = source!(self, block.span).lo(); self.visit_block(block, inner_attrs) } @@ -305,8 +309,8 @@ impl<'a> FmtVisitor<'a> { let mut attrs = item.attrs.clone(); match item.node { ast::ItemKind::Mod(ref m) => { - let outer_file = self.codemap.lookup_char_pos(item.span.lo).file; - let inner_file = self.codemap.lookup_char_pos(m.inner.lo).file; + let outer_file = self.codemap.lookup_char_pos(item.span.lo()).file; + let inner_file = self.codemap.lookup_char_pos(m.inner.lo()).file; if outer_file.name == inner_file.name { // Module is inline, in this case we treat modules like any // other item. @@ -323,7 +327,7 @@ impl<'a> FmtVisitor<'a> { let filterd_attrs = item.attrs .iter() .filter_map(|a| { - let attr_file = self.codemap.lookup_char_pos(a.span.lo).file; + let attr_file = self.codemap.lookup_char_pos(a.span.lo()).file; if attr_file.name == outer_file.name { Some(a.clone()) } else { @@ -352,24 +356,24 @@ impl<'a> FmtVisitor<'a> { let snippet = self.snippet(item.span); let where_span_end = snippet .find_uncommented("{") - .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo); + .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent, where_span_end) { self.buffer.push_str(&impl_str); - self.last_pos = source!(self, item.span).hi; + self.last_pos = source!(self, item.span).hi(); } } ast::ItemKind::Trait(..) => { - self.format_missing_with_indent(item.span.lo); + self.format_missing_with_indent(item.span.lo()); if let Some(trait_str) = format_trait(&self.get_context(), item, self.block_indent) { self.buffer.push_str(&trait_str); - self.last_pos = source!(self, item.span).hi; + self.last_pos = source!(self, item.span).hi(); } } ast::ItemKind::ExternCrate(_) => { - self.format_missing_with_indent(source!(self, item.span).lo); + self.format_missing_with_indent(source!(self, item.span).lo()); let new_str = self.snippet(item.span); if contains_comment(&new_str) { self.buffer.push_str(&new_str) @@ -379,7 +383,7 @@ impl<'a> FmtVisitor<'a> { self.buffer .push_str(&Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")); } - self.last_pos = source!(self, item.span).hi; + self.last_pos = source!(self, item.span).hi(); } ast::ItemKind::Struct(ref def, ref generics) => { let rewrite = { @@ -403,19 +407,19 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(item.span, rewrite); } ast::ItemKind::Enum(ref def, ref generics) => { - self.format_missing_with_indent(source!(self, item.span).lo); + self.format_missing_with_indent(source!(self, item.span).lo()); self.visit_enum(item.ident, &item.vis, def, generics, item.span); - self.last_pos = source!(self, item.span).hi; + self.last_pos = source!(self, item.span).hi(); } ast::ItemKind::Mod(ref module) => { - self.format_missing_with_indent(source!(self, item.span).lo); + self.format_missing_with_indent(source!(self, item.span).lo()); self.format_mod(module, &item.vis, item.span, item.ident, &attrs); } ast::ItemKind::Mac(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); } ast::ItemKind::ForeignMod(ref foreign_mod) => { - self.format_missing_with_indent(source!(self, item.span).lo); + self.format_missing_with_indent(source!(self, item.span).lo()); self.format_foreign_mod(foreign_mod, item.span); } ast::ItemKind::Static(ref ty, mutability, ref expr) => { @@ -619,10 +623,10 @@ impl<'a> FmtVisitor<'a> { } pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { - self.format_missing_with_indent(source!(self, span).lo); + self.format_missing_with_indent(source!(self, span).lo()); let result = rewrite.unwrap_or_else(|| self.snippet(span)); self.buffer.push_str(&result); - self.last_pos = source!(self, span).hi; + self.last_pos = source!(self, span).hi(); } pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> { @@ -643,8 +647,8 @@ impl<'a> FmtVisitor<'a> { Err(_) => { println!( "Couldn't make snippet for span {:?}->{:?}", - self.codemap.lookup_char_pos(span.lo), - self.codemap.lookup_char_pos(span.hi) + self.codemap.lookup_char_pos(span.lo()), + self.codemap.lookup_char_pos(span.hi()) ); "".to_owned() } @@ -750,7 +754,7 @@ impl<'a> FmtVisitor<'a> { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); let inner_span = source!(self, m.inner); - let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) && + let is_internal = !(inner_span.lo().0 == 0 && inner_span.hi().0 == 0) && local_file_name == self.codemap.span_to_filename(inner_span); self.buffer.push_str(&*utils::format_visibility(vis)); @@ -765,7 +769,8 @@ impl<'a> FmtVisitor<'a> { } // Hackery to account for the closing }. let mod_lo = self.codemap.span_after(source!(self, s), "{"); - let body_snippet = self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi - BytePos(1))); + let body_snippet = + self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { self.buffer.push_str("}"); @@ -774,13 +779,13 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.visit_attrs(attrs, ast::AttrStyle::Inner); self.walk_mod_items(m); - self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1)); + self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); self.close_block(false); } - self.last_pos = source!(self, m.inner).hi; + self.last_pos = source!(self, m.inner).hi(); } else { self.buffer.push_str(";"); - self.last_pos = source!(self, s).hi; + self.last_pos = source!(self, s).hi(); } } @@ -828,11 +833,11 @@ impl Rewrite for ast::MetaItem { context.codemap, list.iter(), ")", - |nested_meta_item| nested_meta_item.span.lo, - |nested_meta_item| nested_meta_item.span.hi, + |nested_meta_item| nested_meta_item.span.lo(), + |nested_meta_item| nested_meta_item.span.hi(), |nested_meta_item| nested_meta_item.rewrite(context, item_shape), - self.span.lo, - self.span.hi, + self.span.lo(), + self.span.hi(), false, ); let item_vec = items.collect::>(); @@ -909,7 +914,7 @@ impl<'a> Rewrite for [ast::Attribute] { // Write comments and blank lines between attributes. if i > 0 { - let comment = context.snippet(mk_sp(self[i - 1].span.hi, a.span.lo)); + let comment = context.snippet(mk_sp(self[i - 1].span.hi(), a.span.lo())); // This particular horror show is to preserve line breaks in between doc // comments. An alternative would be to force such line breaks to start // with the usual doc comment token. diff --git a/tests/source/closure.rs b/tests/source/closure.rs index e1aa8fc345e..684c811f582 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure.rs @@ -13,9 +13,9 @@ fn main() { let loooooooooooooong_name = |field| { // format comments. - if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo + if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo() } else { - field.span.lo + field.span.lo() }}; let unblock_me = |trivial| { @@ -85,7 +85,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn foo() { lifetimes_iter___map(|lasdfasfd| { let hi = if l.bounds.is_empty() { - l.lifetime.span.hi + l.lifetime.span.hi() }; }); } diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 1d55bd0a0d9..18706783fb4 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -83,8 +83,8 @@ fn function_calls() { let items = itemize_list(context.codemap, args.iter(), ")", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span.lo(), + |item| item.span.hi(), |item| { item.rewrite(context, Shape { @@ -92,14 +92,14 @@ fn function_calls() { ..nested_shape }) }, - span.lo, - span.hi); + span.lo(), + span.hi()); itemize_list(context.codemap, args.iter(), ")", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span.lo(), + |item| item.span.hi(), |item| { item.rewrite(context, Shape { @@ -107,8 +107,8 @@ fn function_calls() { ..nested_shape }) }, - span.lo, - span.hi) + span.lo(), + span.hi()) } fn macros() { diff --git a/tests/target/closure.rs b/tests/target/closure.rs index bb31cad792b..1aa72baf132 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -24,9 +24,9 @@ fn main() { let loooooooooooooong_name = |field| { // format comments. if field.node.attrs.len() > 0 { - field.node.attrs[0].span.lo + field.node.attrs[0].span.lo() } else { - field.span.lo + field.span.lo() } }; @@ -106,7 +106,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { fn foo() { lifetimes_iter___map(|lasdfasfd| { let hi = if l.bounds.is_empty() { - l.lifetime.span.hi + l.lifetime.span.hi() }; }); } diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 74cdd8ed2f2..7285898436f 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -112,8 +112,8 @@ fn function_calls() { context.codemap, args.iter(), ")", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span.lo(), + |item| item.span.hi(), |item| { item.rewrite( context, @@ -123,16 +123,16 @@ fn function_calls() { }, ) }, - span.lo, - span.hi, + span.lo(), + span.hi(), ); itemize_list( context.codemap, args.iter(), ")", - |item| item.span.lo, - |item| item.span.hi, + |item| item.span.lo(), + |item| item.span.hi(), |item| { item.rewrite( context, @@ -142,8 +142,8 @@ fn function_calls() { }, ) }, - span.lo, - span.hi, + span.lo(), + span.hi(), ) } diff --git a/tests/target/nested-visual-block.rs b/tests/target/nested-visual-block.rs index 339873a3f97..95b9bc2dea2 100644 --- a/tests/target/nested-visual-block.rs +++ b/tests/target/nested-visual-block.rs @@ -5,17 +5,17 @@ fn main() { field_iter, "}", |item| match *item { - StructLitField::Regular(ref field) => field.span.lo, + StructLitField::Regular(ref field) => field.span.lo(), StructLitField::Base(ref expr) => { - let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo)); + let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) } }, |item| match *item { - StructLitField::Regular(ref field) => field.span.hi, - StructLitField::Base(ref expr) => expr.span.hi, + StructLitField::Regular(ref field) => field.span.hi(), + StructLitField::Base(ref expr) => expr.span.hi(), }, |item| { match *item { @@ -34,7 +34,7 @@ fn main() { } }, context.codemap.span_after(span, "{"), - span.hi, + span.hi(), ); // #1580 -- cgit 1.4.1-3-g733a5 From 39a91ba292af829bc6b678d19f475d91076c3166 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 31 Aug 2017 14:11:52 +1200 Subject: Fixup warnings and test formatting --- src/expr.rs | 11 +++++++---- src/items.rs | 9 ++++++--- src/lib.rs | 6 +++--- src/visitor.rs | 8 ++++---- 4 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e1c32235386..ffab5b02f5a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1198,11 +1198,11 @@ impl<'a> ControlFlow<'a> { // `for event in event` // Do not include label in the span. - let lo = self.label.map_or(self.span.lo, |label| label.span.hi); + let lo = self.label.map_or(self.span.lo(), |label| label.span.hi()); let between_kwd_cond = mk_sp( context .codemap - .span_after(mk_sp(lo, self.span.hi), self.keyword.trim()), + .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), self.pat .map_or(cond_span.lo(), |p| if self.matcher.is_empty() { p.span.lo() @@ -1611,11 +1611,14 @@ fn rewrite_match_arm( )); } ( - mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi(), arm.pats[0].span.lo()), + mk_sp( + arm.attrs[arm.attrs.len() - 1].span.hi(), + arm.pats[0].span.lo(), + ), try_opt!(arm.attrs.rewrite(context, shape)), ) } else { - (mk_sp(arm.span().lo, arm.span().lo), String::new()) + (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; let pats_str = try_opt!( rewrite_match_pattern(context, &arm.pats, &arm.guard, shape).and_then(|pats_str| { diff --git a/src/items.rs b/src/items.rs index 500150d877a..67d54749828 100644 --- a/src/items.rs +++ b/src/items.rs @@ -67,7 +67,10 @@ impl Rewrite for ast::Local { context, &attrs_str, "let ", - mk_sp(self.attrs.last().map(|a| a.span.hi).unwrap(), self.span.lo), + mk_sp( + self.attrs.last().map(|a| a.span.hi()).unwrap(), + self.span.lo(), + ), shape, false, )) @@ -556,7 +559,7 @@ pub fn format_impl( if generics.where_clause.predicates.is_empty() { if let Some(hi) = where_span_end { match recover_missing_comment_in_span( - mk_sp(self_ty.span.hi, hi), + mk_sp(self_ty.span.hi(), hi), Shape::indented(offset, context.config), context, last_line_width(&result), @@ -965,7 +968,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if let Some(lo) = item_snippet.chars().position(|c| c == '/') { // 1 = `{` let comment_hi = body_lo - BytePos(1); - let comment_lo = item.span.lo + BytePos(lo as u32); + let comment_lo = item.span.lo() + BytePos(lo as u32); if comment_lo < comment_hi { match recover_missing_comment_in_span( mk_sp(comment_lo, comment_hi), diff --git a/src/lib.rs b/src/lib.rs index da87ede7c60..8152973af43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,8 +118,8 @@ implement_spanned!(ast::Local); impl Spanned for ast::Stmt { fn span(&self) -> Span { match self.node { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo, self.span.hi), - ast::StmtKind::Item(ref item) => mk_sp(item.span().lo, self.span.hi), + ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo(), self.span.hi()) } @@ -128,7 +128,7 @@ impl Spanned for ast::Stmt { if attrs.is_empty() { self.span } else { - mk_sp(attrs[0].span.lo, self.span.hi) + mk_sp(attrs[0].span.lo(), self.span.hi()) } } } diff --git a/src/visitor.rs b/src/visitor.rs index 057bd0ee7ee..f31ebdb9033 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -197,7 +197,7 @@ impl<'a> FmtVisitor<'a> { let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); if unindent_comment { - let end_pos = source!(self, b.span).hi - brace_compensation - remove_len; + let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); unindent_comment = snippet.contains("//") || snippet.contains("/*"); } @@ -352,7 +352,7 @@ impl<'a> FmtVisitor<'a> { self.format_import(&item.vis, vp, item.span, &item.attrs); } ast::ItemKind::Impl(..) => { - self.format_missing_with_indent(source!(self, item.span).lo); + self.format_missing_with_indent(source!(self, item.span).lo()); let snippet = self.snippet(item.span); let where_span_end = snippet .find_uncommented("{") @@ -667,7 +667,7 @@ impl<'a> FmtVisitor<'a> { } let rewrite = attrs.rewrite(&self.get_context(), self.shape()); - let span = mk_sp(attrs[0].span.lo, attrs[attrs.len() - 1].span.hi); + let span = mk_sp(attrs[0].span.lo(), attrs[attrs.len() - 1].span.hi()); self.push_rewrite(span, rewrite); false @@ -943,7 +943,7 @@ impl<'a> Rewrite for [ast::Attribute] { }; let comment = try_opt!(recover_missing_comment_in_span( - mk_sp(self[i - 1].span.hi, a.span.lo), + mk_sp(self[i - 1].span.hi(), a.span.lo()), shape.with_max_width(context.config), context, 0, -- cgit 1.4.1-3-g733a5 From 16894b9cd2573291d31c1e1a3b529ffa51a97ce1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 29 Aug 2017 14:29:13 +0900 Subject: Put the closing brace of empty enum on the same line with the opening brace --- src/items.rs | 12 ++++-------- tests/source/configs-item_brace_style-always_next_line.rs | 4 ++++ tests/target/configs-item_brace_style-always_next_line.rs | 4 ++++ 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 67d54749828..12b57bc2372 100644 --- a/src/items.rs +++ b/src/items.rs @@ -387,8 +387,6 @@ impl<'a> FmtVisitor<'a> { Some(ref body_str) => self.buffer.push_str(body_str), None => if contains_comment(&enum_snippet[brace_pos..]) { self.format_missing_no_indent(span.hi() - BytePos(1)) - } else { - self.format_missing(span.hi() - BytePos(1)) }, } self.block_indent = self.block_indent.block_unindent(self.config); @@ -1092,12 +1090,10 @@ pub fn format_struct_struct( }; // 1 = `}` let overhead = if fields.is_empty() { 1 } else { 0 }; - let max_len = context - .config - .max_width() - .checked_sub(offset.width()) - .unwrap_or(0); - if !generics_str.contains('\n') && result.len() + generics_str.len() + overhead > max_len { + let total_width = result.len() + generics_str.len() + overhead; + if !generics_str.is_empty() && !generics_str.contains('\n') && + total_width > context.config.max_width() + { result.push('\n'); result.push_str(&offset.to_string(context.config)); result.push_str(&generics_str.trim_left()); diff --git a/tests/source/configs-item_brace_style-always_next_line.rs b/tests/source/configs-item_brace_style-always_next_line.rs index aa84801fe5d..b85d64b9e94 100644 --- a/tests/source/configs-item_brace_style-always_next_line.rs +++ b/tests/source/configs-item_brace_style-always_next_line.rs @@ -1,6 +1,10 @@ // rustfmt-item_brace_style: AlwaysNextLine // Item brace style +enum Foo {} + +struct Bar {} + struct Lorem { ipsum: bool, } diff --git a/tests/target/configs-item_brace_style-always_next_line.rs b/tests/target/configs-item_brace_style-always_next_line.rs index eb264446bde..888d255859b 100644 --- a/tests/target/configs-item_brace_style-always_next_line.rs +++ b/tests/target/configs-item_brace_style-always_next_line.rs @@ -1,6 +1,10 @@ // rustfmt-item_brace_style: AlwaysNextLine // Item brace style +enum Foo {} + +struct Bar {} + struct Lorem { ipsum: bool, -- cgit 1.4.1-3-g733a5 From 4ad81d0bd9ac23eaa53335f03e12ef52e5fcb8d0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 29 Aug 2017 15:19:56 +0900 Subject: Refactoring: use context.budget() --- src/items.rs | 98 ++++++++++++------------------------------------------------ 1 file changed, 19 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 12b57bc2372..8c81aed87e6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -533,11 +533,7 @@ pub fn format_impl( let where_budget = if result.contains('\n') { context.config.max_width() } else { - context - .config - .max_width() - .checked_sub(last_line_width(&result)) - .unwrap_or(0) + context.budget(last_line_width(&result)) }; let option = WhereClauseOption::snuggled(&ref_and_type); let where_clause_str = try_opt!(rewrite_where_clause( @@ -756,11 +752,7 @@ fn format_impl_ref_and_type( }; let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; // 1 = space before the type. - let budget = context - .config - .max_width() - .checked_sub(used_space + 1) - .unwrap_or(0); + let budget = context.budget(used_space + 1); if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { if !self_ty_str.contains('\n') { if trait_ref.is_some() { @@ -781,7 +773,7 @@ fn format_impl_ref_and_type( if trait_ref.is_some() { result.push_str("for "); } - let budget = context.config.max_width() - last_line_width(&result); + let budget = context.budget(last_line_width(&result)); let type_offset = match context.config.where_style() { Style::Legacy => new_line_offset + trait_ref_overhead, Style::Rfc => new_line_offset, @@ -925,12 +917,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) Density::Tall }; - let where_budget = try_opt!( - context - .config - .max_width() - .checked_sub(last_line_width(&result)) - ); + let where_budget = context.budget(last_line_width(&result)); let pos_before_where = if type_param_bounds.is_empty() { generics.where_clause.span.lo() } else { @@ -1076,11 +1063,7 @@ pub fn format_struct_struct( let overhead = if fields.is_empty() { 3 } else { 2 }; if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty()) || - context - .config - .max_width() - .checked_sub(result.len()) - .unwrap_or(0) < overhead + context.config.max_width() < overhead + result.len() { format!("\n{}{{", offset.block_only().to_string(context.config)) } else { @@ -1118,11 +1101,7 @@ pub fn format_struct_struct( } // 3 = ` ` and ` }` - let one_line_budget = context - .config - .max_width() - .checked_sub(result.len() + 3 + offset.width()) - .unwrap_or(0); + let one_line_budget = context.budget(result.len() + 3 + offset.width()); let one_line_budget = one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); @@ -1282,12 +1261,7 @@ pub fn rewrite_type_alias( let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); result.push_str(&generics_str); - let where_budget = try_opt!( - context - .config - .max_width() - .checked_sub(last_line_width(&result)) - ); + let where_budget = context.budget(last_line_width(&result)); let option = WhereClauseOption::snuggled(&result); let where_clause_str = try_opt!(rewrite_where_clause( context, @@ -1310,11 +1284,7 @@ pub fn rewrite_type_alias( let line_width = last_line_width(&result); // This checked_sub may fail as the extra space after '=' is not taken into account // In that case the budget is set to 0 which will make ty.rewrite retry on a new line - let budget = context - .config - .max_width() - .checked_sub(indent.width() + line_width + ";".len()) - .unwrap_or(0); + let budget = context.budget(indent.width() + line_width + ";".len()); let type_indent = indent + line_width; // Try to fit the type on the same line let ty_str = try_opt!( @@ -1327,12 +1297,7 @@ pub fn rewrite_type_alias( let type_indent = indent.block_indent(context.config); result.push('\n'); result.push_str(&type_indent.to_string(context.config)); - let budget = try_opt!( - context - .config - .max_width() - .checked_sub(type_indent.width() + ";".len()) - ); + let budget = context.budget(type_indent.width() + ";".len()); ty.rewrite(context, Shape::legacy(budget, type_indent)) }) ); @@ -1516,7 +1481,7 @@ pub fn rewrite_static( if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; - let remaining_width = context.config.max_width() - offset.block_indent - 1; + let remaining_width = context.budget(offset.block_indent + 1); rewrite_assign_rhs( context, lhs, @@ -1563,7 +1528,7 @@ pub fn rewrite_associated_type( let ty_str = try_opt!(ty.rewrite( context, Shape::legacy( - context.config.max_width() - indent.block_indent - prefix.len() - 2, + context.budget(indent.block_indent + prefix.len() + 2), indent.block_only(), ), )); @@ -1771,11 +1736,7 @@ fn rewrite_fn_base( 2 }; let used_width = last_line_used_width(&result, indent.width()); - let one_line_budget = context - .config - .max_width() - .checked_sub(used_width + overhead) - .unwrap_or(0); + let one_line_budget = context.budget(used_width + overhead); let shape = Shape { width: one_line_budget, indent: indent, @@ -2011,11 +1972,7 @@ fn rewrite_fn_base( }; if where_clause.predicates.len() == 1 && should_compress_where { - let budget = context - .config - .max_width() - .checked_sub(last_line_used_width(&result, indent.width())) - .unwrap_or(0); + let budget = context.budget(last_line_used_width(&result, indent.width())); if let Some(where_clause_str) = rewrite_where_clause( context, where_clause, @@ -2294,27 +2251,19 @@ fn compute_budgets_for_args( // 1 = `;` used_space += 1; } - let one_line_budget = context - .config - .max_width() - .checked_sub(used_space) - .unwrap_or(0); + let one_line_budget = context.budget(used_space); if one_line_budget > 0 { // 4 = "() {".len() let (indent, multi_line_budget) = match context.config.fn_args_layout() { IndentStyle::Block => { let indent = indent.block_indent(context.config); - let budget = - try_opt!(context.config.max_width().checked_sub(indent.width() + 1)); - (indent, budget) + (indent, context.budget(indent.width() + 1)) } IndentStyle::Visual => { let indent = indent + result.len() + 1; let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; - let budget = - try_opt!(context.config.max_width().checked_sub(multi_line_overhead)); - (indent, budget) + (indent, context.budget(multi_line_overhead)) } }; @@ -2330,8 +2279,7 @@ fn compute_budgets_for_args( // Account for `)` and possibly ` {`. IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, }; - let max_space = try_opt!(context.config.max_width().checked_sub(used_space)); - Some((0, max_space, new_indent)) + Some((0, context.budget(used_space), new_indent)) } fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: bool) -> bool { @@ -2744,11 +2692,7 @@ fn format_generics( let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = context - .config - .max_width() - .checked_sub(last_line_used_width(&result, offset.width())) - .unwrap_or(0); + let budget = context.budget(last_line_used_width(&result, offset.width())); let option = WhereClauseOption::snuggled(&result); let where_clause_str = try_opt!(rewrite_where_clause( context, @@ -2769,11 +2713,7 @@ fn format_generics( brace_style != BraceStyle::AlwaysNextLine }; let total_used_width = last_line_used_width(&result, used_width); - let remaining_budget = context - .config - .max_width() - .checked_sub(total_used_width) - .unwrap_or(0); + let remaining_budget = context.budget(total_used_width); // If the same line brace if forced, it indicates that we are rewriting an item with empty body, // and hence we take the closer into account as well for one line budget. // We assume that the closer has the same length as the opener. -- cgit 1.4.1-3-g733a5 From 4b79055a158e388e4b47026958da0f57e07dd940 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 29 Aug 2017 22:16:04 +0900 Subject: Apply refactoring from cargo clippy --- src/bin/cargo-fmt.rs | 20 +++++++------- src/bin/rustfmt.rs | 14 +++++----- src/chains.rs | 4 +-- src/codemap.rs | 7 ++--- src/comment.rs | 42 +++++++++++++---------------- src/config.rs | 6 ++--- src/expr.rs | 73 ++++++++++++++++++++++++-------------------------- src/file_lines.rs | 8 +++--- src/imports.rs | 14 +++++----- src/items.rs | 75 ++++++++++++++++++++++++++-------------------------- src/lib.rs | 9 +++---- src/lists.rs | 25 +++++++++--------- src/macros.rs | 5 ++-- src/missed_spans.rs | 4 +-- src/patterns.rs | 21 ++++++++------- src/summary.rs | 11 +------- src/types.rs | 6 ++--- src/utils.rs | 2 +- src/vertical.rs | 8 +----- src/visitor.rs | 19 ++++++------- tests/system.rs | 31 +++++++++++----------- 21 files changed, 188 insertions(+), 216 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 2c0ec3a84dc..3d0a5589d37 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -84,7 +84,7 @@ fn execute() -> i32 { let workspace_hitlist = WorkspaceHitlist::from_matches(&matches); - match format_crate(verbosity, workspace_hitlist) { + match format_crate(verbosity, &workspace_hitlist) { Err(e) => { print_usage(&opts, &e.to_string()); failure @@ -115,7 +115,7 @@ pub enum Verbosity { fn format_crate( verbosity: Verbosity, - workspace_hitlist: WorkspaceHitlist, + workspace_hitlist: &WorkspaceHitlist, ) -> Result { let targets = get_targets(workspace_hitlist)?; @@ -178,9 +178,9 @@ pub enum WorkspaceHitlist { } impl WorkspaceHitlist { - pub fn get_some<'a>(&'a self) -> Option<&'a [String]> { - if let &WorkspaceHitlist::Some(ref hitlist) = self { - Some(&hitlist) + pub fn get_some(&self) -> Option<&[String]> { + if let WorkspaceHitlist::Some(ref hitlist) = *self { + Some(hitlist) } else { None } @@ -196,9 +196,9 @@ impl WorkspaceHitlist { } // Returns a vector of all compile targets of a crate -fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std::io::Error> { +fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, std::io::Error> { let mut targets: Vec = vec![]; - if workspace_hitlist == WorkspaceHitlist::None { + if *workspace_hitlist == WorkspaceHitlist::None { let output = Command::new("cargo").arg("read-manifest").output()?; if output.status.success() { // None of the unwraps should fail if output of `cargo read-manifest` is correct @@ -229,7 +229,7 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: let data = &String::from_utf8(output.stdout).unwrap(); let json: Value = json::from_str(data).unwrap(); let json_obj = json.as_object().unwrap(); - let mut hitlist: HashSet<&String> = if workspace_hitlist != WorkspaceHitlist::All { + let mut hitlist: HashSet<&String> = if *workspace_hitlist != WorkspaceHitlist::All { HashSet::from_iter(workspace_hitlist.get_some().unwrap()) } else { HashSet::new() // Unused @@ -240,7 +240,7 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: .as_array() .unwrap() .into_iter() - .filter(|member| if workspace_hitlist == WorkspaceHitlist::All { + .filter(|member| if *workspace_hitlist == WorkspaceHitlist::All { true } else { let member_obj = member.as_object().unwrap(); @@ -248,7 +248,7 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result, std:: hitlist.take(&member_name.to_string()).is_some() }) .collect(); - if hitlist.len() != 0 { + if hitlist.is_empty() { // Mimick cargo of only outputting one spec. return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5bb5190e810..5b891dfd1db 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -104,7 +104,7 @@ fn match_cli_path_or_file( let toml = Config::from_toml_path(config_file.as_ref())?; return Ok((toml, Some(config_file))); } - Config::from_resolved_toml_path(input_file).map_err(|e| FmtError::from(e)) + Config::from_resolved_toml_path(input_file).map_err(FmtError::from) } fn make_opts() -> Options { @@ -161,21 +161,21 @@ fn execute(opts: &Options) -> FmtResult { Operation::Help => { print_usage(opts, ""); Summary::print_exit_codes(); - Ok(Summary::new()) + Ok(Summary::default()) } Operation::Version => { print_version(); - Ok(Summary::new()) + Ok(Summary::default()) } Operation::ConfigHelp => { Config::print_docs(); - Ok(Summary::new()) + Ok(Summary::default()) } Operation::ConfigOutputDefault { path } => { let mut file = File::create(path)?; let toml = Config::default().all_options().to_toml()?; file.write_all(toml.as_bytes())?; - Ok(Summary::new()) + Ok(Summary::default()) } Operation::Stdin { input, config_path } => { // try to read config from local directory @@ -222,7 +222,7 @@ fn execute(opts: &Options) -> FmtResult { } } - let mut error_summary = Summary::new(); + let mut error_summary = Summary::default(); for file in files { if !file.exists() { println!("Error: file `{}` does not exist", file.to_str().unwrap()); @@ -354,7 +354,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { return config_path_not_found(path.to_str().unwrap()); } } - path @ _ => path, + path => path, }; // If no path is given, we won't output a minimal config. diff --git a/src/chains.rs b/src/chains.rs index 27119dd6f0d..411c3c7f45f 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -256,7 +256,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - "{}{}{}", parent_rewrite, first_connector, - join_rewrites(&rewrites, &subexpr_list, &connector) + join_rewrites(&rewrites, subexpr_list, &connector) ) }; let result = format!("{}{}", result, repeat_try(suffix_try_num)); @@ -475,7 +475,7 @@ fn rewrite_method_call( let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); - let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 { + let type_str = if context.config.spaces_within_angle_brackets() && !type_list.is_empty() { format!("::< {} >", type_list.join(", ")) } else { format!("::<{}>", type_list.join(", ")) diff --git a/src/codemap.rs b/src/codemap.rs index e156f34015b..f62bb16dfa2 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module contains utilities that work with the `CodeMap` from libsyntax / syntex_syntax. +//! This module contains utilities that work with the `CodeMap` from `libsyntax` / `syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. use std::rc::Rc; @@ -77,8 +77,9 @@ impl LineRangeUtils for CodeMap { let lo = self.lookup_char_pos(span.lo()); let hi = self.lookup_char_pos(span.hi()); - assert!( - lo.file.name == hi.file.name, + assert_eq!( + lo.file.name, + hi.file.name, "span crossed file boundary: lo: {:?}, hi: {:?}", lo, hi diff --git a/src/comment.rs b/src/comment.rs index aa078f4dbf7..4cb8325d25e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -23,16 +23,14 @@ use utils::{first_line_width, last_line_width, wrap_str}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { false + } else if let Some(c) = comment.chars().nth(2) { + !c.is_alphanumeric() && !c.is_whitespace() } else { - if let Some(c) = comment.chars().nth(2) { - !c.is_alphanumeric() && !c.is_whitespace() - } else { - false - } + false } } -#[derive(PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq)] pub enum CommentStyle<'a> { DoubleSlash, TripleSlash, @@ -194,17 +192,15 @@ pub fn combine_strs_with_missing_comments( }; let second_sep = if missing_comment.is_empty() || next_str.is_empty() { String::new() + } else if missing_comment.starts_with("//") { + format!("\n{}", indent_str) } else { - if missing_comment.starts_with("//") { - format!("\n{}", indent_str) + one_line_width += missing_comment.len() + first_sep.len() + 1; + allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); + if prefer_same_line && allow_one_line && one_line_width <= shape.width { + String::from(" ") } else { - one_line_width += missing_comment.len() + first_sep.len() + 1; - allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); - if prefer_same_line && allow_one_line && one_line_width <= shape.width { - String::from(" ") - } else { - format!("\n{}", indent_str) - } + format!("\n{}", indent_str) } }; Some(format!( @@ -314,7 +310,7 @@ fn rewrite_comment_inner( line = line.trim(); // Drop old closer. if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = &line[..(line.len() - 2)].trim_right(); + line = line[..(line.len() - 2)].trim_right(); } line @@ -339,7 +335,7 @@ fn rewrite_comment_inner( } if config.wrap_comments() && line.len() > max_chars { - let rewrite = rewrite_string(line, &fmt).unwrap_or(line.to_owned()); + let rewrite = rewrite_string(line, &fmt).unwrap_or_else(|| line.to_owned()); result.push_str(&rewrite); } else { if line.is_empty() && result.ends_with(' ') { @@ -412,7 +408,7 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< // `*` in `/*`. let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); if let Some(fnw) = first_non_whitespace { - if l.as_bytes()[fnw] == '*' as u8 && fnw > 0 { + if l.as_bytes()[fnw] == b'*' && fnw > 0 { &l[fnw - 1..] } else { &l[fnw..] @@ -432,7 +428,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { line.starts_with("/** ") { &line[4..] - } else if let &CommentStyle::Custom(opener) = style { + } else if let CommentStyle::Custom(opener) = *style { if line.starts_with(opener) { &line[opener.len()..] } else { @@ -646,7 +642,7 @@ where _ => CharClassesStatus::Normal, }, CharClassesStatus::BlockComment(deepness) => { - assert!(deepness != 0); + assert_ne!(deepness, 0); self.status = match self.base.peek() { Some(next) if next.get_char() == '/' && chr == '*' => { CharClassesStatus::BlockCommentClosing(deepness - 1) @@ -901,10 +897,8 @@ impl<'a> Iterator for CommentReducer<'a> { if c == '*' { c = try_opt!(self.iter.next()); } - } else { - if c == '\n' { - self.at_start_line = true; - } + } else if c == '\n' { + self.at_start_line = true; } if !c.is_whitespace() { return Some(c); diff --git a/src/config.rs b/src/config.rs index 31eccf24941..bd847bab5bc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -280,11 +280,11 @@ macro_rules! create_config { } )+ - pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { + pub fn set(&mut self) -> ConfigSetter { ConfigSetter(self) } - pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { + pub fn was_set(&self) -> ConfigWasSet { ConfigWasSet(self) } @@ -306,7 +306,7 @@ macro_rules! create_config { let table = parsed .as_table() .ok_or(String::from("Parsed config was not table"))?; - for (key, _) in table { + for key in table.keys() { match &**key { $( stringify!($i) => (), diff --git a/src/expr.rs b/src/expr.rs index ffab5b02f5a..2bfbba2fb1f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -44,7 +44,7 @@ impl Rewrite for ast::Expr { } } -#[derive(PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum ExprType { Statement, SubExpression, @@ -249,7 +249,7 @@ pub fn format_expr( } match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { - (Some(ref lhs), Some(ref rhs)) => { + (Some(lhs), Some(rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { format!(" {} ", delim) } else if needs_space_before_range(context, lhs) { @@ -257,23 +257,23 @@ pub fn format_expr( } else { delim.into() }; - rewrite_pair(&**lhs, &**rhs, "", &sp_delim, "", context, shape) + rewrite_pair(&*lhs, &*rhs, "", &sp_delim, "", context, shape) } - (None, Some(ref rhs)) => { + (None, Some(rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { format!("{} ", delim) } else { delim.into() }; - rewrite_unary_prefix(context, &sp_delim, &**rhs, shape) + rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) } - (Some(ref lhs), None) => { + (Some(lhs), None) => { let sp_delim = if context.config.spaces_around_ranges() { format!(" {}", delim) } else { delim.into() }; - rewrite_unary_suffix(context, &sp_delim, &**lhs, shape) + rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) } (None, None) => wrap_str(delim.into(), context.config.max_width(), shape), } @@ -488,7 +488,7 @@ where let result = if context.config.array_layout() == IndentStyle::Visual || tactic == DefinitiveListTactic::Horizontal { - if context.config.spaces_within_square_brackets() && list_str.len() > 0 { + if context.config.spaces_within_square_brackets() && !list_str.is_empty() { format!("[ {} ]", list_str) } else { format!("[{}]", list_str) @@ -631,7 +631,7 @@ fn rewrite_closure( }; if no_return_type && !needs_block { // lock.stmts.len() == 1 - if let Some(ref expr) = stmt_expr(&block.stmts[0]) { + if let Some(expr) = stmt_expr(&block.stmts[0]) { if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, body_shape) { return Some(rw); } @@ -651,7 +651,7 @@ fn rewrite_closure( } // Either we require a block, or tried without and failed. - rewrite_closure_block(&block, &prefix, context, body_shape) + rewrite_closure_block(block, &prefix, context, body_shape) } else { rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { // The closure originally had a non-block expression, but we can't fit on @@ -715,7 +715,7 @@ fn rewrite_closure_block( // closure is large. let block_threshold = context.config.closure_block_indent_threshold(); if block_threshold >= 0 { - if let Some(block_str) = block.rewrite(&context, shape) { + if let Some(block_str) = block.rewrite(context, shape) { if block_str.matches('\n').count() <= block_threshold as usize && !need_block_indent(&block_str, shape) { @@ -729,7 +729,7 @@ fn rewrite_closure_block( // The body of the closure is big enough to be block indented, that // means we must re-format. let block_shape = shape.block(); - let block_str = try_opt!(block.rewrite(&context, block_shape)); + let block_str = try_opt!(block.rewrite(context, block_shape)); Some(format!("{} {}", prefix, block_str)) } @@ -933,7 +933,7 @@ struct ControlFlow<'a> { span: Span, } -fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option> { +fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { match expr.node { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( cond, @@ -1644,7 +1644,7 @@ fn rewrite_match_arm( fn rewrite_match_pattern( context: &RewriteContext, - pats: &Vec>, + pats: &[ptr::P], guard: &Option>, shape: Shape, ) -> Option { @@ -1722,9 +1722,9 @@ fn rewrite_match_body( has_guard: bool, is_last: bool, ) -> Option { - let (extend, body) = flatten_arm_body(context, &body); + let (extend, body) = flatten_arm_body(context, body); - let comma = arm_comma(&context.config, body, is_last); + let comma = arm_comma(context.config, body, is_last); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let alt_block_sep = alt_block_sep.as_str(); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { @@ -1790,7 +1790,7 @@ fn rewrite_match_body( // Let's try and get the arm body on the same line as the condition. // 4 = ` => `.len() let orig_body_shape = shape - .offset_left(extra_offset(&pats_str, shape) + 4) + .offset_left(extra_offset(pats_str, shape) + 4) .and_then(|shape| shape.sub_width(comma.len())); let orig_body = if let Some(body_shape) = orig_body_shape { let rewrite = nop_block_collapse( @@ -1985,10 +1985,8 @@ fn string_requires_rewrite( if line.len() > shape.width { return true; } - } else { - if line.len() > shape.width + shape.indent.width() { - return true; - } + } else if line.len() > shape.width + shape.indent.width() { + return true; } } @@ -2049,7 +2047,7 @@ pub fn rewrite_call( }; rewrite_call_inner( context, - &callee, + callee, &args.iter().map(|x| &**x).collect::>(), span, shape, @@ -2076,7 +2074,7 @@ where } else { 1 }; - let used_width = extra_offset(&callee_str, shape); + let used_width = extra_offset(callee_str, shape); let one_line_width = shape .width .checked_sub(used_width + 2 * paren_overhead) @@ -2117,7 +2115,7 @@ where } let args_shape = shape - .sub_width(last_line_width(&callee_str)) + .sub_width(last_line_width(callee_str)) .ok_or(Ordering::Less)?; Ok(format!( "{}{}", @@ -2203,19 +2201,18 @@ fn try_overflow_last_arg<'a, T>( where T: Rewrite + Spanned + ToExpr + 'a, { - let overflow_last = can_be_overflowed(&context, args); + let overflow_last = can_be_overflowed(context, args); // Replace the last item with its first line to see if it fits with // first arguments. let placeholder = if overflow_last { let mut context = context.clone(); if let Some(expr) = args[args.len() - 1].to_expr() { - match expr.node { - ast::ExprKind::MethodCall(..) => context.force_one_line_chain = true, - _ => (), + if let ast::ExprKind::MethodCall(..) = expr.node { + context.force_one_line_chain = true; } } - last_arg_shape(&context, &item_vec, shape, args_max_width).and_then(|arg_shape| { + last_arg_shape(&context, item_vec, shape, args_max_width).and_then(|arg_shape| { rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) }) } else { @@ -2253,12 +2250,12 @@ where fn last_arg_shape( context: &RewriteContext, - items: &Vec, + items: &[ListItem], shape: Shape, args_max_width: usize, ) -> Option { let overhead = items.iter().rev().skip(1).fold(0, |acc, i| { - acc + i.item.as_ref().map_or(0, |s| first_line_width(&s)) + acc + i.item.as_ref().map_or(0, |s| first_line_width(s)) }); let max_width = min(args_max_width, shape.width); let arg_indent = if context.use_block_indent() { @@ -2413,7 +2410,7 @@ pub fn wrap_args_with_parens( (context.inside_macro && !args_str.contains('\n') && args_str.len() + paren_overhead(context) <= shape.width) || is_extendable { - if context.config.spaces_within_parens() && args_str.len() > 0 { + if context.config.spaces_within_parens() && !args_str.is_empty() { format!("( {} )", args_str) } else { format!("({})", args_str) @@ -2445,7 +2442,7 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> .and_then(|s| s.sub_width(paren_overhead)) ); - let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && s.len() > 0 { + let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && !s.is_empty() { format!("( {} )", s) } else { format!("({})", s) @@ -2505,7 +2502,7 @@ fn rewrite_index( (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( "{}\n{}{}{}{}", expr_str, - indent.to_string(&context.config), + indent.to_string(context.config), lbr, new_index_str, rbr @@ -2513,7 +2510,7 @@ fn rewrite_index( (None, Some(ref new_index_str)) => Some(format!( "{}\n{}{}{}{}", expr_str, - indent.to_string(&context.config), + indent.to_string(context.config), lbr, new_index_str, rbr @@ -2556,7 +2553,7 @@ fn rewrite_struct_lit<'a>( path_shape, )); - if fields.len() == 0 && base.is_none() { + if fields.is_empty() && base.is_none() { return Some(format!("{} {{}}", path_str)); } @@ -2706,7 +2703,7 @@ pub fn rewrite_field( "{}{}:\n{}{}", attrs_str, name, - expr_offset.to_string(&context.config), + expr_offset.to_string(context.config), s ) }) @@ -2789,7 +2786,7 @@ where }; let list_str = try_opt!(write_list(&item_vec, &fmt)); - if context.config.spaces_within_parens() && list_str.len() > 0 { + if context.config.spaces_within_parens() && !list_str.is_empty() { Some(format!("( {} )", list_str)) } else { Some(format!("({})", list_str)) diff --git a/src/file_lines.rs b/src/file_lines.rs index 7df4dbb7399..704a89017d0 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -95,7 +95,7 @@ fn normalize_ranges(ranges: &mut HashMap>) { { let mut iter = ranges.into_iter().peekable(); while let Some(next) = iter.next() { - let mut next = next.clone(); + let mut next = *next; while let Some(&&mut peek) = iter.peek() { if let Some(merged) = next.merge(peek) { iter.next().unwrap(); @@ -166,7 +166,7 @@ impl FileLines { } } -/// FileLines files iterator. +/// `FileLines` files iterator. pub struct Files<'a>( Option<::std::collections::hash_map::Keys<'a, String, Vec>>, ); @@ -197,9 +197,9 @@ impl str::FromStr for FileLines { fn from_str(s: &str) -> Result { let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; let mut m = HashMap::new(); - for js in v.into_iter() { + for js in v { let (s, r) = JsonSpan::into_tuple(js)?; - m.entry(s).or_insert(vec![]).push(r); + m.entry(s).or_insert_with(|| vec![]).push(r); } Ok(FileLines::from_ranges(m)) } diff --git a/src/imports.rs b/src/imports.rs index 04492665d70..33efce19a40 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -25,8 +25,8 @@ use visitor::FmtVisitor; fn path_of(a: &ast::ViewPath_) -> &ast::Path { match *a { - ast::ViewPath_::ViewPathSimple(_, ref p) => p, - ast::ViewPath_::ViewPathGlob(ref p) => p, + ast::ViewPath_::ViewPathSimple(_, ref p) | + ast::ViewPath_::ViewPathGlob(ref p) | ast::ViewPath_::ViewPathList(ref p, _) => p, } } @@ -54,12 +54,10 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde } else { Ordering::Less } + } else if b_name_str == "self" { + Ordering::Greater } else { - if b_name_str == "self" { - Ordering::Greater - } else { - a_name_str.cmp(&b_name_str) - } + a_name_str.cmp(b_name_str) }; if name_ordering == Ordering::Equal { match a.node.rename { @@ -137,7 +135,7 @@ fn rewrite_view_path_prefix( path.segments.len() > 1 { let path = &ast::Path { - span: path.span.clone(), + span: path.span, segments: path.segments[..path.segments.len() - 1].to_owned(), }; try_opt!(rewrite_path( diff --git a/src/items.rs b/src/items.rs index 67d54749828..98759013efd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -80,7 +80,7 @@ impl Rewrite for ast::Local { let pat_shape = try_opt!(shape.offset_left(4)); // 1 = ; let pat_shape = try_opt!(pat_shape.sub_width(1)); - let pat_str = try_opt!(self.pat.rewrite(&context, pat_shape)); + let pat_str = try_opt!(self.pat.rewrite(context, pat_shape)); result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -111,7 +111,7 @@ impl Rewrite for ast::Local { // 1 = trailing semicolon; let nested_shape = try_opt!(shape.sub_width(1)); - result = try_opt!(rewrite_assign_rhs(&context, result, ex, nested_shape)); + result = try_opt!(rewrite_assign_rhs(context, result, ex, nested_shape)); } result.push(';'); @@ -195,7 +195,7 @@ impl<'a> FmtVisitor<'a> { fn format_body_element(&mut self, element: &BodyElement) { match *element { - BodyElement::ForeignItem(ref item) => self.format_foreign_item(item), + BodyElement::ForeignItem(item) => self.format_foreign_item(item), } } @@ -321,7 +321,7 @@ impl<'a> FmtVisitor<'a> { if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { let rewrite = { - if let Some(ref stmt) = block.stmts.first() { + if let Some(stmt) = block.stmts.first() { match stmt_expr(stmt) { Some(e) => { let suffix = if semicolon_for_expr(&self.get_context(), e) { @@ -574,10 +574,10 @@ pub fn format_impl( if try_opt!(is_impl_single_line( context, - &items, + items, &result, &where_clause_str, - &item, + item, )) { result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { @@ -680,7 +680,7 @@ fn format_impl_ref_and_type( let mut result = String::with_capacity(128); result.push_str(&format_visibility(&item.vis)); - result.push_str(&format_defaultness(defaultness)); + result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); result.push_str("impl"); @@ -713,7 +713,7 @@ fn format_impl_ref_and_type( let result_len = result.len(); if let Some(trait_ref_str) = rewrite_trait_ref( context, - &trait_ref, + trait_ref, offset, &generics_str, true, @@ -731,7 +731,7 @@ fn format_impl_ref_and_type( )); result.push_str(&try_opt!(rewrite_trait_ref( context, - &trait_ref, + trait_ref, offset, &generics_str, false, @@ -1100,7 +1100,7 @@ pub fn format_struct_struct( if !generics_str.contains('\n') && result.len() + generics_str.len() + overhead > max_len { result.push('\n'); result.push_str(&offset.to_string(context.config)); - result.push_str(&generics_str.trim_left()); + result.push_str(generics_str.trim_left()); } else { result.push_str(&generics_str); } @@ -1111,7 +1111,7 @@ pub fn format_struct_struct( // `struct S {}` } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { // fix indent - result.push_str(&snippet.trim_right()); + result.push_str(snippet.trim_right()); result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -1178,7 +1178,7 @@ fn format_tuple_struct( } else { // This is a dirty hack to work around a missing `)` from the span of the last field. let last_arg_span = fields[fields.len() - 1].span; - if context.snippet(last_arg_span).ends_with(")") { + if context.snippet(last_arg_span).ends_with(')') { last_arg_span.hi() } else { context @@ -1226,7 +1226,7 @@ fn format_tuple_struct( if snippet.is_empty() { // `struct S ()` } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - result.push_str(&snippet.trim_right()); + result.push_str(snippet.trim_right()); result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -1440,7 +1440,7 @@ pub fn rewrite_struct_field( let ty_rewritten = rewrite_struct_field_type(context, overhead, field, &spacing, shape); if let Some(ref ty) = ty_rewritten { if !ty.contains('\n') { - return Some(attr_prefix + &ty); + return Some(attr_prefix + ty); } } @@ -1461,17 +1461,17 @@ pub fn rewrite_struct_field( Some(ref new_ty) if !new_ty.contains('\n') => format!( "{}\n{}{}", prefix, - type_offset.to_string(&context.config), + type_offset.to_string(context.config), &new_ty ), - _ => prefix + &ty, + _ => prefix + ty, }, _ => { let ty = try_opt!(rewrite_type_in_next_line()); format!( "{}\n{}{}", prefix, - type_offset.to_string(&context.config), + type_offset.to_string(context.config), &ty ) } @@ -1554,7 +1554,7 @@ pub fn rewrite_associated_type( .map(|ty_bound| ty_bound.rewrite(context, shape)) .collect::>>() ); - if bounds.len() > 0 { + if !bounds.is_empty() { format!(": {}", join_bounds(context, shape, &bound_str)) } else { String::new() @@ -1798,7 +1798,7 @@ fn rewrite_fn_base( // return type later anyway. let ret_str = try_opt!( fd.output - .rewrite(&context, Shape::indented(indent, context.config)) + .rewrite(context, Shape::indented(indent, context.config)) ); let multi_line_ret_str = ret_str.contains('\n'); @@ -1826,26 +1826,24 @@ fn rewrite_fn_base( if one_line_budget == 0 { if snuggle_angle_bracket { result.push('('); + } else if context.config.fn_args_paren_newline() { + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + if context.config.fn_args_layout() == IndentStyle::Visual { + arg_indent = arg_indent + 1; // extra space for `(` + } + result.push('('); } else { - if context.config.fn_args_paren_newline() { + result.push_str("("); + if context.config.fn_args_layout() == IndentStyle::Visual { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); - if context.config.fn_args_layout() == IndentStyle::Visual { - arg_indent = arg_indent + 1; // extra space for `(` - } - result.push('('); - } else { - result.push_str("("); - if context.config.fn_args_layout() == IndentStyle::Visual { - result.push('\n'); - result.push_str(&arg_indent.to_string(context.config)); - } } } } else { result.push('('); } - if context.config.spaces_within_parens() && fd.inputs.len() > 0 && result.ends_with('(') { + if context.config.spaces_within_parens() && !fd.inputs.is_empty() && result.ends_with('(') { result.push(' ') } @@ -1900,10 +1898,10 @@ fn rewrite_fn_base( let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); // Put the closing brace on the next line if it overflows the max width. // 1 = `)` - if fd.inputs.len() == 0 && used_width + 1 > context.config.max_width() { + if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { result.push('\n'); } - if context.config.spaces_within_parens() && fd.inputs.len() > 0 { + if context.config.spaces_within_parens() && !fd.inputs.is_empty() { result.push(' ') } // If the last line of args contains comment, we cannot put the closing paren @@ -1924,7 +1922,7 @@ fn rewrite_fn_base( if let ast::FunctionRetTy::Ty(..) = fd.output { let ret_should_indent = match context.config.fn_args_layout() { // If our args are block layout then we surely must have space. - IndentStyle::Block if put_args_in_block || fd.inputs.len() == 0 => false, + IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, _ if args_last_line_contains_comment => false, _ if result.contains('\n') || multi_line_ret_str => true, _ => { @@ -2071,9 +2069,10 @@ fn rewrite_fn_base( result.push_str(&where_clause_str); force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - return Some((result, force_new_line_for_brace)); + Some((result, force_new_line_for_brace)) } +#[derive(Copy, Clone)] struct WhereClauseOption { suppress_comma: bool, // Force no trailing comma snuggle: bool, // Do not insert newline before `where` @@ -2121,7 +2120,7 @@ fn rewrite_args( let mut arg_item_strs = try_opt!( args.iter() .map(|arg| { - arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)) + arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) }) .collect::>>() ); @@ -2203,7 +2202,7 @@ fn rewrite_args( } let fits_in_one_line = !generics_str_contains_newline && - (arg_items.len() == 0 || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + (arg_items.is_empty() || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { item.item = Some(arg); @@ -2497,7 +2496,7 @@ fn rewrite_trait_bounds( let bound_str = try_opt!( bounds .iter() - .map(|ty_bound| ty_bound.rewrite(&context, shape)) + .map(|ty_bound| ty_bound.rewrite(context, shape)) .collect::>>() ); Some(format!(": {}", join_bounds(context, shape, &bound_str))) diff --git a/src/lib.rs b/src/lib.rs index 8152973af43..3c070d25c00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -504,7 +504,7 @@ impl FormattingError { fn msg_suffix(&self) -> String { match self.kind { - ErrorKind::LineOverflow(..) if self.is_comment => format!( + ErrorKind::LineOverflow(..) if self.is_comment => String::from( "use `error_on_line_overflow_comments = false` to suppress \ the warning against line comments\n", ), @@ -802,9 +802,8 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m last_wspace = Some(b); } } else if c == '/' { - match prev_char { - Some('/') => is_comment = true, - _ => (), + if let Some('/') = prev_char { + is_comment = true; } last_wspace = None; } else { @@ -869,7 +868,7 @@ pub fn format_input( config: &Config, mut out: Option<&mut T>, ) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { - let mut summary = Summary::new(); + let mut summary = Summary::default(); if config.disable_all_formatting() { return Ok((summary, FileMap::new(), FormatReport::new())); } diff --git a/src/lists.rs b/src/lists.rs index a9d705b4c64..301e9101c8f 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -20,7 +20,7 @@ use rewrite::RewriteContext; use utils::{first_line_width, last_line_width, mk_sp}; /// Formatting tactic for lists. This will be cast down to a -/// DefinitiveListTactic depending on the number and length of the items and +/// `DefinitiveListTactic` depending on the number and length of the items and /// their comments. #[derive(Eq, PartialEq, Debug, Copy, Clone)] pub enum ListTactic { @@ -172,7 +172,7 @@ impl DefinitiveListTactic { } /// The type of separator for lists. -#[derive(Eq, PartialEq, Debug)] +#[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum Separator { Comma, VerticalBar, @@ -346,9 +346,9 @@ where if tactic == DefinitiveListTactic::Vertical { // We cannot keep pre-comments on the same line if the comment if normalized. - let keep_comment = if formatting.config.normalize_comments() { - false - } else if item.pre_comment_style == ListItemCommentStyle::DifferentLine { + let keep_comment = if formatting.config.normalize_comments() || + item.pre_comment_style == ListItemCommentStyle::DifferentLine + { false } else { // We will try to keep the comment on the same line with the item here. @@ -405,7 +405,7 @@ where formatting.config.max_width(), )); } - let overhead = if let &mut Some(max_width) = item_max_width { + let overhead = if let Some(max_width) = *item_max_width { max_width + 2 } else { // 1 = space between item and comment. @@ -548,8 +548,7 @@ where .chars() .rev() .take(comment_end + 1) - .find(|c| *c == '\n') - .is_some() + .any(|c| c == '\n') { ( Some(trimmed_pre_snippet.to_owned()), @@ -612,7 +611,7 @@ where } None => post_snippet .find_uncommented(self.terminator) - .unwrap_or(post_snippet.len()), + .unwrap_or_else(|| post_snippet.len()), }; if !post_snippet.is_empty() && comment_end > 0 { @@ -621,12 +620,14 @@ where // Everything from the separator to the next item. let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len()); + let first_newline = test_snippet + .find('\n') + .unwrap_or_else(|| test_snippet.len()); // From the end of the first line of comments. let test_snippet = &test_snippet[first_newline..]; let first = test_snippet .find(|c: char| !c.is_whitespace()) - .unwrap_or(test_snippet.len()); + .unwrap_or_else(|| test_snippet.len()); // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; @@ -747,7 +748,7 @@ pub fn struct_lit_shape( IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); Shape { - width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())), + width: context.budget(shape.indent.width()), ..shape } } diff --git a/src/macros.rs b/src/macros.rs index d9156e08e85..4378febc2c3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -224,7 +224,7 @@ pub fn rewrite_macro( // If we are rewriting `vec!` macro or other special macros, // then we can rewrite this as an usual array literal. // Otherwise, we must preserve the original existence of trailing comma. - if FORCED_BRACKET_MACROS.contains(&¯o_name.as_str()) { + if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { context.inside_macro = false; trailing_comma = false; } @@ -355,8 +355,7 @@ fn indent_macro_snippet( fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { let mut width = 0; - let mut iter = s.chars(); - while let Some(c) = iter.next() { + for c in s.chars() { match c { ' ' => width += 1, '\t' => width += context.config.tab_spaces(), diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 43e81e12f71..301e1583029 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -90,7 +90,7 @@ impl<'a> FmtVisitor<'a> { let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; let big_diff = (span.lo() - big_span_lo).to_usize(); - let snippet = self.snippet(span.clone()); + let snippet = self.snippet(span); debug!("write_snippet `{}`", snippet); @@ -180,7 +180,7 @@ impl<'a> FmtVisitor<'a> { last_wspace = None; line_start = offset + subslice.len(); - if let Some('/') = subslice.chars().skip(1).next() { + if let Some('/') = subslice.chars().nth(1) { // check that there are no contained block comments if !subslice .split('\n') diff --git a/src/patterns.rs b/src/patterns.rs index 70d94f4bee7..c3475dfba73 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -139,7 +139,7 @@ fn rewrite_struct_pat( path_shape, )); - if fields.len() == 0 && !elipses { + if fields.is_empty() && !elipses { return Some(format!("{} {{}}", path_str)); } @@ -223,7 +223,7 @@ pub enum TuplePatField<'a> { impl<'a> Rewrite for TuplePatField<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { - TuplePatField::Pat(ref p) => p.rewrite(context, shape), + TuplePatField::Pat(p) => p.rewrite(context, shape), TuplePatField::Dotdot(_) => Some("..".to_string()), } } @@ -232,15 +232,15 @@ impl<'a> Rewrite for TuplePatField<'a> { impl<'a> Spanned for TuplePatField<'a> { fn span(&self) -> Span { match *self { - TuplePatField::Pat(ref p) => p.span(), + TuplePatField::Pat(p) => p.span(), TuplePatField::Dotdot(span) => span, } } } pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { - match pat { - &TuplePatField::Pat(ref pat) => match pat.node { + match *pat { + TuplePatField::Pat(pat) => match pat.node { ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => { context.use_block_indent() && len == 1 } @@ -250,7 +250,7 @@ pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), _ => false, }, - &TuplePatField::Dotdot(..) => false, + TuplePatField::Dotdot(..) => false, } } @@ -288,7 +288,7 @@ fn rewrite_tuple_pat( } if pat_vec.is_empty() { - return Some(format!("{}()", path_str.unwrap_or(String::new()))); + return Some(format!("{}()", path_str.unwrap_or_default())); } let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); @@ -313,12 +313,13 @@ fn rewrite_tuple_pat( if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { context.inside_macro = true; } - let path_str = path_str.unwrap_or(String::new()); + let path_str = path_str.unwrap_or_default(); let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); for pat in pat_vec { pat_ref_vec.push(pat); } - return rewrite_call_inner( + + rewrite_call_inner( &context, &path_str, &pat_ref_vec[..], @@ -326,7 +327,7 @@ fn rewrite_tuple_pat( shape, shape.width, add_comma, - ).ok(); + ).ok() } fn count_wildcard_suffix_len( diff --git a/src/summary.rs b/src/summary.rs index 065e357ea95..7ca885a645c 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -1,5 +1,5 @@ #[must_use] -#[derive(Debug, Clone)] +#[derive(Debug, Default, Clone)] pub struct Summary { // Encountered e.g. an IO error. has_operational_errors: bool, @@ -15,15 +15,6 @@ pub struct Summary { } impl Summary { - pub fn new() -> Summary { - Summary { - has_operational_errors: false, - has_parsing_errors: false, - has_formatting_errors: false, - has_diff: false, - } - } - pub fn has_operational_errors(&self) -> bool { self.has_operational_errors } diff --git a/src/types.rs b/src/types.rs index 86a6e4d3d72..027f9a9baff 100644 --- a/src/types.rs +++ b/src/types.rs @@ -447,7 +447,7 @@ impl Rewrite for ast::WherePredicate { ); let bounds_str = join_bounds(context, ty_shape, &bounds); - if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { + if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { format!( "for< {} > {}{}{}", lifetime_str, @@ -635,7 +635,7 @@ impl Rewrite for ast::PolyTraitRef { )); Some( - if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 { + if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { format!("for< {} > {}", lifetime_str, path_str) } else { format!("for<{}> {}", lifetime_str, path_str) @@ -812,7 +812,7 @@ fn rewrite_bare_fn( Some(result) } -pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &Vec) -> String { +pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { // Try to join types in a single line let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", diff --git a/src/utils.rs b/src/utils.rs index f99e1958f8c..438bb027637 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -123,7 +123,7 @@ pub fn last_line_contains_single_line_comment(s: &str) -> bool { #[inline] pub fn is_attributes_extendable(attrs_str: &str) -> bool { - !attrs_str.contains('\n') && !last_line_contains_single_line_comment(&attrs_str) + !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) } // The width of the first line in s. diff --git a/src/vertical.rs b/src/vertical.rs index 600bdeaba3a..f0cb887c59d 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -284,13 +284,7 @@ fn group_aligned_items( .skip(1) .collect::>() .join("\n"); - let spacings = if snippet - .lines() - .rev() - .skip(1) - .find(|l| l.trim().is_empty()) - .is_some() - { + let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) { "\n" } else { "" diff --git a/src/visitor.rs b/src/visitor.rs index f31ebdb9033..56c1783476a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -260,7 +260,7 @@ impl<'a> FmtVisitor<'a> { abi, vis, mk_sp(s.lo(), b.span.lo()), - &b, + b, ) } visit::FnKind::Method(ident, sig, vis, b) => { @@ -276,7 +276,7 @@ impl<'a> FmtVisitor<'a> { sig.abi, vis.unwrap_or(&ast::Visibility::Inherited), mk_sp(s.lo(), b.span.lo()), - &b, + b, ) } visit::FnKind::Closure(_) => unreachable!(), @@ -503,8 +503,8 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::MacroDef(..) => { // FIXME(#1539): macros 2.0 - let snippet = Some(self.snippet(item.span)); - self.push_rewrite(item.span, snippet); + let mac_snippet = Some(self.snippet(item.span)); + self.push_rewrite(item.span, mac_snippet); } } } @@ -719,7 +719,7 @@ impl<'a> FmtVisitor<'a> { // next item for output. if self.config.reorder_imports() && is_use_item(&*items_left[0]) { let used_items_len = self.reorder_items( - &items_left, + items_left, &is_use_item, self.config.reorder_imports_in_group(), ); @@ -727,7 +727,7 @@ impl<'a> FmtVisitor<'a> { items_left = rest; } else if self.config.reorder_extern_crates() && is_extern_crate(&*items_left[0]) { let used_items_len = self.reorder_items( - &items_left, + items_left, &is_extern_crate, self.config.reorder_extern_crates_in_group(), ); @@ -863,10 +863,7 @@ impl Rewrite for ast::MetaItem { .unwrap_or(0), ..shape }; - format!( - "{}", - try_opt!(rewrite_comment(&value, false, doc_shape, context.config)) - ) + try_opt!(rewrite_comment(&value, false, doc_shape, context.config)) } else { format!("{} = {}", name, value) } @@ -923,7 +920,7 @@ impl<'a> Rewrite for [ast::Attribute] { { // Look at before and after comment and see if there are any empty lines. let comment_begin = comment.chars().position(|c| c == '/'); - let len = comment_begin.unwrap_or(comment.len()); + let len = comment_begin.unwrap_or_else(|| comment.len()); let mlb = comment.chars().take(len).filter(|c| *c == '\n').count() > 1; let mla = if comment_begin.is_none() { mlb diff --git a/tests/system.rs b/tests/system.rs index 9559b545cc6..ce575f9f492 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -45,7 +45,7 @@ fn system_tests() { // Display results. println!("Ran {} system tests.", count); - assert!(fails == 0, "{} system tests failed", fails); + assert_eq!(fails, 0, "{} system tests failed", fails); } // Do the same for tests/coverage-source directory @@ -57,7 +57,7 @@ fn coverage_tests() { let (_reports, count, fails) = check_files(files); println!("Ran {} tests in coverage mode.", count); - assert!(fails == 0, "{} tests failed", fails); + assert_eq!(fails, 0, "{} tests failed", fails); } #[test] @@ -71,7 +71,7 @@ fn checkstyle_test() { // Helper function for comparing the results of rustfmt // to a known output file generated by one of the write modes. fn assert_output(source: &str, expected_filename: &str) { - let config = read_config(&source); + let config = read_config(source); let (file_map, _report) = format_file(source, &config); // Populate output by writing to a vec. @@ -86,7 +86,7 @@ fn assert_output(source: &str, expected_filename: &str) { .expect("Failed reading target"); let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); - if compare.len() > 0 { + if !compare.is_empty() { let mut failures = HashMap::new(); failures.insert(source.to_string(), compare); print_mismatches(failures); @@ -106,7 +106,7 @@ fn idempotence_tests() { // Display results. println!("Ran {} idempotent tests.", count); - assert!(fails == 0, "{} idempotent tests failed", fails); + assert_eq!(fails, 0, "{} idempotent tests failed", fails); } // Run rustfmt on itself. This operation must be idempotent. We also check that @@ -126,15 +126,16 @@ fn self_tests() { // Display results. println!("Ran {} self tests.", count); - assert!(fails == 0, "{} self tests failed", fails); + assert_eq!(fails, 0, "{} self tests failed", fails); for format_report in reports { println!("{}", format_report); warnings += format_report.warning_count(); } - assert!( - warnings == 0, + assert_eq!( + warnings, + 0, "Rustfmt's code generated {} warnings", warnings ); @@ -149,7 +150,7 @@ fn stdin_formatting_smoke_test() { assert!(error_summary.has_no_errors()); for &(ref file_name, ref text) in &file_map { if file_name == "stdin" { - assert!(text.to_string() == "fn main() {}\n"); + assert_eq!(text.to_string(), "fn main() {}\n"); return; } } @@ -210,7 +211,7 @@ fn print_mismatches(result: HashMap>) { } fn read_config(filename: &str) -> Config { - let sig_comments = read_significant_comments(&filename); + let sig_comments = read_significant_comments(filename); // Look for a config file... If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. @@ -241,8 +242,8 @@ fn format_file>(filepath: P, config: &Config) -> (FileMap, Form let filepath = filepath.into(); let input = Input::File(filepath); let (_error_summary, file_map, report) = - format_input::(input, &config, None).unwrap(); - return (file_map, report); + format_input::(input, config, None).unwrap(); + (file_map, report) } pub fn idempotent_check(filename: String) -> Result>> { @@ -273,7 +274,7 @@ fn get_config(config_file: Option<&str>) -> Config { None => return Default::default(), Some(file_name) => { let mut full_path = "tests/config/".to_owned(); - full_path.push_str(&file_name); + full_path.push_str(file_name); if !Path::new(&full_path).exists() { return Default::default(); }; @@ -296,7 +297,7 @@ fn read_significant_comments(file_name: &str) -> HashMap { let file = fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name)); let reader = BufReader::new(file); let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; - let regex = regex::Regex::new(&pattern).expect("Failed creating pattern 1"); + let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); // Matches lines containing significant comments or whitespace. let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") @@ -305,7 +306,7 @@ fn read_significant_comments(file_name: &str) -> HashMap { reader .lines() .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(&line)) + .take_while(|line| line_regex.is_match(line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { ( -- cgit 1.4.1-3-g733a5 From 9d49bd22f05cc00ec6f98c4614610e17605165dd Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 31 Aug 2017 13:24:32 +0900 Subject: Add explicit lifetime --- src/config.rs | 4 ++-- src/expr.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index bd847bab5bc..30d79cdc562 100644 --- a/src/config.rs +++ b/src/config.rs @@ -280,11 +280,11 @@ macro_rules! create_config { } )+ - pub fn set(&mut self) -> ConfigSetter { + pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { ConfigSetter(self) } - pub fn was_set(&self) -> ConfigWasSet { + pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { ConfigWasSet(self) } diff --git a/src/expr.rs b/src/expr.rs index 2bfbba2fb1f..3cfbf023faf 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -933,7 +933,7 @@ struct ControlFlow<'a> { span: Span, } -fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { +fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option> { match expr.node { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( cond, -- cgit 1.4.1-3-g733a5 From 848d4559e1629c4a6a603844217daaee479b486b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 30 Aug 2017 12:00:10 +0900 Subject: Enhance macro rewrite --- src/expr.rs | 19 +++++++- src/lib.rs | 45 +++++++++--------- src/macros.rs | 123 ++++++++++++++++++++++++++++++++----------------- tests/source/macros.rs | 17 +++++-- tests/target/macros.rs | 24 ++++++++-- 5 files changed, 156 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ffab5b02f5a..05707d79960 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -26,7 +26,7 @@ use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; -use macros::{rewrite_macro, MacroPosition}; +use macros::{rewrite_macro, MacroArg, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use string::{rewrite_string, StringFormat}; @@ -3015,3 +3015,20 @@ impl<'a> ToExpr for ast::StructField { false } } + +impl<'a> ToExpr for MacroArg { + fn to_expr(&self) -> Option<&ast::Expr> { + match self { + &MacroArg::Expr(ref expr) => Some(expr), + _ => None, + } + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + match self { + &MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), + &MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), + &MacroArg::Pat(..) => false, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 8152973af43..596fa5b5396 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ use std::rc::Rc; use errors::{DiagnosticBuilder, Handler}; use errors::emitter::{ColorConfig, EmitterWriter}; +use macros::MacroArg; use strings::string_buffer::StringBuffer; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping, Span}; @@ -216,6 +217,16 @@ impl Spanned for ast::TyParamBound { } } +impl Spanned for MacroArg { + fn span(&self) -> Span { + match *self { + MacroArg::Expr(ref expr) => expr.span(), + MacroArg::Ty(ref ty) => ty.span(), + MacroArg::Pat(ref pat) => pat.span(), + } + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of @@ -682,7 +693,6 @@ fn format_ast( parse_session: &mut ParseSess, main_file: &Path, config: &Config, - codemap: &Rc, mut after_file: F, ) -> Result<(FileMap, bool), io::Error> where @@ -703,29 +713,19 @@ where if config.verbose() { println!("Formatting {}", path_str); } - { - let mut visitor = FmtVisitor::from_codemap(parse_session, config); - let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == main_file { - visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); - } else { - visitor.last_pos = filemap.start_pos; - } - visitor.format_separate_mod(module, &*filemap); + let mut visitor = FmtVisitor::from_codemap(parse_session, config); + let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == main_file { + visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); + } else { + visitor.last_pos = filemap.start_pos; + } + visitor.format_separate_mod(module, &*filemap); - has_diff |= after_file(path_str, &mut visitor.buffer)?; + has_diff |= after_file(path_str, &mut visitor.buffer)?; - result.push((path_str.to_owned(), visitor.buffer)); - } - // Reset the error count. - if parse_session.span_diagnostic.has_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - } + result.push((path_str.to_owned(), visitor.buffer)); } Ok((result, has_diff)) @@ -913,7 +913,6 @@ pub fn format_input( &mut parse_session, &main_file, config, - &codemap, |file_name, file| { // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. diff --git a/src/macros.rs b/src/macros.rs index d9156e08e85..800dfaef2e4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,6 +22,7 @@ use syntax::ast; use syntax::codemap::BytePos; use syntax::parse::new_parser_from_tts; +use syntax::parse::parser::Parser; use syntax::parse::token::Token; use syntax::symbol; use syntax::tokenstream::TokenStream; @@ -61,6 +62,51 @@ impl MacroStyle { } } +pub enum MacroArg { + Expr(ast::Expr), + Ty(ast::Ty), + Pat(ast::Pat), +} + +impl Rewrite for MacroArg { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self { + &MacroArg::Expr(ref expr) => expr.rewrite(context, shape), + &MacroArg::Ty(ref ty) => ty.rewrite(context, shape), + &MacroArg::Pat(ref pat) => pat.rewrite(context, shape), + } + } +} + +fn parse_macro_arg(parser: &mut Parser) -> Option { + macro_rules! parse_macro_arg { + ($target:tt, $macro_arg:ident, $parser:ident) => { + let mut cloned_parser = (*parser).clone(); + match cloned_parser.$parser() { + Ok($target) => { + if parser.sess.span_diagnostic.has_errors() { + parser.sess.span_diagnostic.reset_err_count(); + } else { + // Parsing succeeded. + *parser = cloned_parser; + return Some(MacroArg::$macro_arg((*$target).clone())); + } + } + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + } + } + } + } + + parse_macro_arg!(expr, Expr, parse_expr); + parse_macro_arg!(ty, Ty, parse_ty); + parse_macro_arg!(pat, Pat, parse_pat); + + return None; +} + pub fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, @@ -93,7 +139,7 @@ pub fn rewrite_macro( original_style }; - let ts: TokenStream = mac.node.tts.clone().into(); + let ts: TokenStream = mac.node.stream(); if ts.is_empty() && !contains_comment(&context.snippet(mac.span)) { return match style { MacroStyle::Parens if position == MacroPosition::Item => { @@ -106,32 +152,16 @@ pub fn rewrite_macro( } let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - let mut expr_vec = Vec::new(); + let mut arg_vec = Vec::new(); let mut vec_with_semi = false; let mut trailing_comma = false; if MacroStyle::Braces != style { loop { - let expr = match parser.parse_expr() { - Ok(expr) => { - // Recovered errors. - if context.parse_session.span_diagnostic.has_errors() { - return indent_macro_snippet( - context, - &context.snippet(mac.span), - shape.indent, - ); - } - - expr - } - Err(mut e) => { - e.cancel(); - return indent_macro_snippet(context, &context.snippet(mac.span), shape.indent); - } - }; - - expr_vec.push(expr); + match parse_macro_arg(&mut parser) { + Some(arg) => arg_vec.push(arg), + None => return Some(context.snippet(mac.span)), + } match parser.token { Token::Eof => break, @@ -141,25 +171,22 @@ pub fn rewrite_macro( if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { parser.bump(); if parser.token != Token::Eof { - match parser.parse_expr() { - Ok(expr) => { - if context.parse_session.span_diagnostic.has_errors() { - return None; - } - expr_vec.push(expr); + match parse_macro_arg(&mut parser) { + Some(arg) => { + arg_vec.push(arg); parser.bump(); - if parser.token == Token::Eof && expr_vec.len() == 2 { + if parser.token == Token::Eof && arg_vec.len() == 2 { vec_with_semi = true; break; } } - Err(mut e) => e.cancel(), + None => return Some(context.snippet(mac.span)), } } } - return None; + return Some(context.snippet(mac.span)); } - _ => return None, + _ => return Some(context.snippet(mac.span)), } parser.bump(); @@ -178,7 +205,7 @@ pub fn rewrite_macro( let rw = rewrite_call_inner( context, ¯o_name, - &expr_vec.iter().map(|e| &**e).collect::>()[..], + &arg_vec.iter().map(|e| &*e).collect::>()[..], mac.span, shape, context.config.fn_call_width(), @@ -201,8 +228,8 @@ pub fn rewrite_macro( // 6 = `vec!` + `; ` let total_overhead = lbr.len() + rbr.len() + 6; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = try_opt!(expr_vec[0].rewrite(context, nested_shape)); - let rhs = try_opt!(expr_vec[1].rewrite(context, nested_shape)); + let lhs = try_opt!(arg_vec[0].rewrite(context, nested_shape)); + let rhs = try_opt!(arg_vec[1].rewrite(context, nested_shape)); if !lhs.contains('\n') && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { @@ -228,14 +255,26 @@ pub fn rewrite_macro( context.inside_macro = false; trailing_comma = false; } + // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. + let expr_vec: Vec<_> = arg_vec + .iter() + .filter_map(|e| match *e { + MacroArg::Expr(ref e) => Some(e.clone()), + _ => None, + }) + .collect(); + if expr_vec.len() != arg_vec.len() { + return Some(context.snippet(mac.span)); + } + let sp = mk_sp( + context + .codemap + .span_after(mac.span, original_style.opener()), + mac.span.hi() - BytePos(1), + ); let rewrite = try_opt!(rewrite_array( - expr_vec.iter().map(|x| &**x), - mk_sp( - context - .codemap - .span_after(mac.span, original_style.opener()), - mac.span.hi() - BytePos(1), - ), + expr_vec.iter(), + sp, context, mac_shape, trailing_comma, diff --git a/tests/source/macros.rs b/tests/source/macros.rs index caccd75a700..10f6e2d7ea0 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -164,9 +164,6 @@ fn issue_1921() { } } -// Put the following tests with macro invocations whose arguments cannot be parsed as expressioins -// at the end of the file for now. - // #1577 fn issue1577() { let json = json!({ @@ -178,3 +175,17 @@ gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", }); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) + ) + ); + assert_eq ! ( :: std :: mem :: align_of :: < HandleWithDtor < :: std :: os :: raw :: c_int > > ( ) , 8usize , concat ! ( "Alignment of template specialization: " , stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) ) ); +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 0b651cc5445..d47063d255c 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -208,9 +208,6 @@ fn issue_1921() { } } -// Put the following tests with macro invocations whose arguments cannot be parsed as expressioins -// at the end of the file for now. - // #1577 fn issue1577() { let json = json!({ @@ -222,3 +219,24 @@ gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", }); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); + assert_eq!( + ::std::mem::align_of::>(), + 8usize, + concat!( + "Alignment of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); +} -- cgit 1.4.1-3-g733a5 From 68da44eb9762b38d9d50548e7cb789fb844e5f46 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 1 Sep 2017 22:52:54 +0900 Subject: Avoid rewriting big block twice --- src/expr.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b65383311de..7ad24928d4e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -855,11 +855,17 @@ impl Rewrite for ast::Block { } let prefix = try_opt!(block_prefix(context, self, shape)); - if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { - return rw; + + let result = rewrite_block_with_visitor(context, &prefix, self, shape); + if let Some(ref result_str) = result { + if result_str.lines().count() <= 3 { + if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { + return rw; + } + } } - rewrite_block_with_visitor(context, &prefix, self, shape) + result } } -- cgit 1.4.1-3-g733a5 From 737186b8901a4c843f5b7eed2f3a9a8a3e41e397 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 3 Sep 2017 08:09:37 +0900 Subject: Use rewrite() instead of format_expr --- src/expr.rs | 7 +------ src/visitor.rs | 8 +------- 2 files changed, 2 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b65383311de..228722474e1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -876,13 +876,8 @@ impl Rewrite for ast::Stmt { "" }; - let expr_type = match self.node { - ast::StmtKind::Expr(_) => ExprType::SubExpression, - ast::StmtKind::Semi(_) => ExprType::Statement, - _ => unreachable!(), - }; let shape = try_opt!(shape.sub_width(suffix.len())); - format_expr(ex, expr_type, context, shape).map(|s| s + suffix) + format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; diff --git a/src/visitor.rs b/src/visitor.rs index 56c1783476a..a792148130b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -22,7 +22,6 @@ use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, C FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; -use expr::{format_expr, ExprType}; use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, rewrite_type_alias}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, @@ -77,12 +76,7 @@ impl<'a> FmtVisitor<'a> { let rewrite = stmt.rewrite(&self.get_context(), self.shape()); self.push_rewrite(stmt.span(), rewrite); } - ast::StmtKind::Expr(ref expr) => { - let rewrite = - format_expr(expr, ExprType::Statement, &self.get_context(), self.shape()); - self.push_rewrite(stmt.span(), rewrite) - } - ast::StmtKind::Semi(..) => { + ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let rewrite = stmt.rewrite(&self.get_context(), self.shape()); self.push_rewrite(stmt.span(), rewrite) } -- cgit 1.4.1-3-g733a5 From f8bdcd62e8f4087f602018c97063733590367ffe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 3 Sep 2017 08:10:12 +0900 Subject: Do not allow single-lined closure with block body --- src/expr.rs | 14 +------------- tests/target/chains-visual.rs | 4 +++- tests/target/chains.rs | 4 +++- tests/target/hard-tabs.rs | 4 +++- 4 files changed, 10 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 228722474e1..cc18d8edbac 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -630,7 +630,7 @@ fn rewrite_closure( false }; if no_return_type && !needs_block { - // lock.stmts.len() == 1 + // block.stmts.len() == 1 if let Some(expr) = stmt_expr(&block.stmts[0]) { if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, body_shape) { return Some(rw); @@ -638,18 +638,6 @@ fn rewrite_closure( } } - if !needs_block { - // We need braces, but we might still prefer a one-liner. - let stmt = &block.stmts[0]; - // 4 = braces and spaces. - if let Some(body_shape) = body_shape.sub_width(4) { - // Checks if rewrite succeeded and fits on a single line. - if let Some(rewrite) = and_one_line(stmt.rewrite(context, body_shape)) { - return Some(format!("{} {{ {} }}", prefix, rewrite)); - } - } - } - // Either we require a block, or tried without and failed. rewrite_closure_block(block, &prefix, context, body_shape) } else { diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 829a27867dd..ef166a2bb66 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -42,7 +42,9 @@ fn main() { }); fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 4955817da5c..2720f51d5f3 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -45,7 +45,9 @@ fn main() { }); fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 4ac6df5def8..ecaffc165e6 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -80,7 +80,9 @@ fn main() { }); fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { *root.borrow_mut() = Some(&script_task); }); + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); }); a.b.c.d(); -- cgit 1.4.1-3-g733a5 From 47062c8f0a3a197a8e2f83e070c4be1e866514fa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 3 Sep 2017 08:14:00 +0900 Subject: Format long derive --- src/visitor.rs | 34 +++++++++++++++++++++++++++++++++- tests/source/attrib.rs | 4 ++++ tests/target/attrib.rs | 5 +++++ 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index a792148130b..1fe8655309f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -973,7 +973,7 @@ impl<'a> Rewrite for [ast::Attribute] { Some(&(_, next_attr)) if is_derive(next_attr) => insert_new_line = false, // If not, rewrite the merged derives. _ => { - result.push_str(&format!("#[derive({})]", derive_args.join(", "))); + result.push_str(&try_opt!(format_derive(context, &derive_args, shape))); derive_args.clear(); } } @@ -990,6 +990,38 @@ impl<'a> Rewrite for [ast::Attribute] { } } +// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. +fn format_derive(context: &RewriteContext, derive_args: &[String], shape: Shape) -> Option { + let mut result = String::with_capacity(128); + result.push_str("#[derive("); + // 11 = `#[derive()]` + let initial_budget = try_opt!(shape.width.checked_sub(11)); + let mut budget = initial_budget; + let num = derive_args.len(); + for (i, a) in derive_args.iter().enumerate() { + // 2 = `, ` or `)]` + let width = a.len() + 2; + if width > budget { + if i > 0 { + // Remove trailing whitespace. + result.pop(); + } + result.push('\n'); + // 9 = `#[derive(` + result.push_str(&(shape.indent + 9).to_string(context.config)); + budget = initial_budget; + } else { + budget = budget.checked_sub(width).unwrap_or(0); + } + result.push_str(a); + if i != num - 1 { + result.push_str(", ") + } + } + result.push_str(")]"); + Some(result) +} + fn is_derive(attr: &ast::Attribute) -> bool { match attr.meta() { Some(meta_item) => match meta_item.node { diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 4d23d8b79d1..6653dd2daa9 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -146,3 +146,7 @@ fn attributes_on_statements() { # [ attr ( on ( mac ) ) ] foo!(); } + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] +pub struct HP(pub u8); diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 467d168ef4f..e220b48fb38 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -146,3 +146,8 @@ fn attributes_on_statements() { #[attr(on(mac))] foo!(); } + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, + Deserialize)] +pub struct HP(pub u8); -- cgit 1.4.1-3-g733a5 From 467b7b5a6c93f4c295664b271edeb529385ae4a4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 4 Sep 2017 16:15:32 +0900 Subject: Take attributes_on_same_line_as_field into account --- src/lists.rs | 2 +- src/vertical.rs | 4 +++- tests/source/configs-attributes_on_same_line_as_field-false.rs | 6 ++++++ tests/target/configs-attributes_on_same_line_as_field-false.rs | 6 ++++++ 4 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 301e9101c8f..117f1035867 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -265,7 +265,7 @@ where // Now that we know how we will layout, we can decide for sure if there // will be a trailing separator. let mut trailing_separator = formatting.needs_trailing_separator(); - let mut result = String::new(); + let mut result = String::with_capacity(128); let cloned_items = items.clone(); let mut iter = items.into_iter().enumerate().peekable(); let mut item_max_width: Option = None; diff --git a/src/vertical.rs b/src/vertical.rs index f0cb887c59d..e069032aab3 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -53,6 +53,8 @@ impl AlignedItem for ast::StructField { } else { mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; + let attrs_extendable = context.config.attributes_on_same_line_as_field() && + is_attributes_extendable(&attrs_str); rewrite_struct_field_prefix(context, self).and_then(|field_str| { combine_strs_with_missing_comments( context, @@ -60,7 +62,7 @@ impl AlignedItem for ast::StructField { &field_str, missing_span, shape, - is_attributes_extendable(&attrs_str), + attrs_extendable, ) }) } diff --git a/tests/source/configs-attributes_on_same_line_as_field-false.rs b/tests/source/configs-attributes_on_same_line_as_field-false.rs index ba63fd5caa0..202d3e56aee 100644 --- a/tests/source/configs-attributes_on_same_line_as_field-false.rs +++ b/tests/source/configs-attributes_on_same_line_as_field-false.rs @@ -9,3 +9,9 @@ struct Lorem { #[ serde(rename = "Amet") ] amet: usize, } + +// #1943 +pub struct Bzip2 { + # [ serde (rename = "level") ] + level: i32 , +} diff --git a/tests/target/configs-attributes_on_same_line_as_field-false.rs b/tests/target/configs-attributes_on_same_line_as_field-false.rs index 7cb074d13a9..98c3c4b791c 100644 --- a/tests/target/configs-attributes_on_same_line_as_field-false.rs +++ b/tests/target/configs-attributes_on_same_line_as_field-false.rs @@ -9,3 +9,9 @@ struct Lorem { #[serde(rename = "Amet")] amet: usize, } + +// #1943 +pub struct Bzip2 { + #[serde(rename = "level")] + level: i32, +} -- cgit 1.4.1-3-g733a5 From e6e696f7b039ff268f09caf906f66443fe4f68e3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Sep 2017 01:04:08 +0900 Subject: Avoid cloning String --- src/items.rs | 56 +++++++++++++++++++++++++++++++++----------------------- src/lib.rs | 11 +++++++++++ src/types.rs | 9 ++++----- 3 files changed, 48 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d5369e33ef8..79a178dd363 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2313,35 +2313,45 @@ fn rewrite_generics_inner( ) -> Option { // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. - let lifetimes: &[_] = &generics.lifetimes; - let tys: &[_] = &generics.ty_params; - if lifetimes.is_empty() && tys.is_empty() { - return Some(String::new()); - } - // Strings for the generics. - let lt_strs = lifetimes.iter().map(|lt| lt.rewrite(context, shape)); - let ty_strs = tys.iter().map(|ty_param| ty_param.rewrite(context, shape)); + // Wrapper type + enum GenericsArg<'a> { + Lifetime(&'a ast::LifetimeDef), + TyParam(&'a ast::TyParam), + } + impl<'a> Rewrite for GenericsArg<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + GenericsArg::Lifetime(ref lifetime) => lifetime.rewrite(context, shape), + GenericsArg::TyParam(ref ty) => ty.rewrite(context, shape), + } + } + } + impl<'a> Spanned for GenericsArg<'a> { + fn span(&self) -> Span { + match *self { + GenericsArg::Lifetime(ref lifetime) => lifetime.span(), + GenericsArg::TyParam(ref ty) => ty.span(), + } + } + } - // Extract comments between generics. - let lt_spans = lifetimes.iter().map(|l| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi() - } else { - l.bounds[l.bounds.len() - 1].span.hi() - }; - mk_sp(l.lifetime.span.lo(), hi) - }); - let ty_spans = tys.iter().map(|ty| ty.span()); + if generics.lifetimes.is_empty() && generics.ty_params.is_empty() { + return Some(String::new()); + } + let generics_args = generics + .lifetimes + .iter() + .map(|lt| GenericsArg::Lifetime(lt)) + .chain(generics.ty_params.iter().map(|ty| GenericsArg::TyParam(ty))); let items = itemize_list( context.codemap, - lt_spans.chain(ty_spans).zip(lt_strs.chain(ty_strs)), + generics_args, ">", - |&(sp, _)| sp.lo(), - |&(sp, _)| sp.hi(), - // FIXME: don't clone - |&(_, ref str)| str.clone(), + |arg| arg.span().lo(), + |arg| arg.span().hi(), + |arg| arg.rewrite(context, shape), context.codemap.span_after(span, "<"), span.hi(), false, diff --git a/src/lib.rs b/src/lib.rs index 2040a9e6e59..ee231e2e63c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,6 +217,17 @@ impl Spanned for ast::TyParamBound { } } +impl Spanned for ast::LifetimeDef { + fn span(&self) -> Span { + let hi = if self.bounds.is_empty() { + self.lifetime.span.hi() + } else { + self.bounds[self.bounds.len() - 1].span.hi() + }; + mk_sp(self.lifetime.span.lo(), hi) + } +} + impl Spanned for MacroArg { fn span(&self) -> Span { match *self { diff --git a/src/types.rs b/src/types.rs index 027f9a9baff..ceca0417aa8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -584,11 +584,10 @@ impl Rewrite for ast::TyParam { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::with_capacity(128); // FIXME: If there are more than one attributes, this will force multiline. - let attr_str = match (&*self.attrs).rewrite(context, shape) { - Some(ref rw) if !rw.is_empty() => format!("{} ", rw), - _ => String::new(), - }; - result.push_str(&attr_str); + match self.attrs.rewrite(context, shape) { + Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), + _ => (), + } result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); -- cgit 1.4.1-3-g733a5 From c720a3a38e1aa8a4973aac020b9169fd608cd591 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Sep 2017 01:04:31 +0900 Subject: Remove colon from faulty span --- src/lists.rs | 2 +- tests/source/structs.rs | 5 +++++ tests/target/structs.rs | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 301e9101c8f..9c6111bde61 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -641,7 +641,7 @@ where self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); let post_snippet = post_snippet[..comment_end].trim(); - let post_snippet_trimmed = if post_snippet.starts_with(',') { + let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { post_snippet[1..].trim_matches(white_space) } else if post_snippet.ends_with(',') { post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) diff --git a/tests/source/structs.rs b/tests/source/structs.rs index b759943292f..b782c98635a 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -15,6 +15,11 @@ pub struct Foo { pub i: TypeForPublicField } +// #1095 +struct S { + t: T, +} + // #1029 pub struct Foo { #[doc(hidden)] diff --git a/tests/target/structs.rs b/tests/target/structs.rs index a4c26269f8e..8284618bc39 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -14,6 +14,11 @@ pub struct Foo { pub i: TypeForPublicField, } +// #1095 +struct S { + t: T, +} + // #1029 pub struct Foo { #[doc(hidden)] -- cgit 1.4.1-3-g733a5 From 2fb5affb5f6a57e29178934ee8c691f0618644f2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Sep 2017 16:50:55 +0900 Subject: Remove duplicates inside visit_stmt() --- src/visitor.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 1fe8655309f..fb8a6f95b21 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -72,11 +72,7 @@ impl<'a> FmtVisitor<'a> { ast::StmtKind::Item(ref item) => { self.visit_item(item); } - ast::StmtKind::Local(..) => { - let rewrite = stmt.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(stmt.span(), rewrite); - } - ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let rewrite = stmt.rewrite(&self.get_context(), self.shape()); self.push_rewrite(stmt.span(), rewrite) } -- cgit 1.4.1-3-g733a5 From 97d9e6b37395625a19051a4d9c0c3d47f9437ded Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Sep 2017 16:51:54 +0900 Subject: Use the last line's width for indent width in rewriting missed span to fix unindented comments --- src/missed_spans.rs | 5 +++-- tests/source/comment.rs | 1 - tests/source/comment4.rs | 1 - tests/target/comment.rs | 5 ++--- tests/target/comment4.rs | 5 ++--- 5 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 301e1583029..5e350cf41b4 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use Shape; +use {Indent, Shape}; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::WriteMode; use syntax::codemap::{BytePos, Pos, Span}; @@ -169,11 +169,12 @@ impl<'a> FmtVisitor<'a> { self.config.comment_width(), self.config.max_width() - self.block_indent.width(), ); + let comment_indent = Indent::from_width(self.config, self.buffer.cur_offset()); self.buffer.push_str(&rewrite_comment( subslice, false, - Shape::legacy(comment_width, self.block_indent), + Shape::legacy(comment_width, comment_indent), self.config, ).unwrap()); diff --git a/tests/source/comment.rs b/tests/source/comment.rs index 61d7fc454aa..e8ddaf959a6 100644 --- a/tests/source/comment.rs +++ b/tests/source/comment.rs @@ -9,7 +9,6 @@ fn test() { // comment // comment2 - // FIXME(1275) code(); /* leave this comment alone! * ok? */ diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index 0ae5cf4c3f6..ff1445378d7 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -5,7 +5,6 @@ fn test() { // comment // comment2 - // FIXME(1275) code(); /* leave this comment alone! * ok? */ diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 168fb28edb9..f6de70a16ad 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -9,9 +9,8 @@ fn test() { // comment // comment2 - // FIXME(1275) code(); // leave this comment alone! - // ok? + // ok? // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam @@ -33,7 +32,7 @@ fn test() { // .unwrap()); funk(); // dontchangeme - // or me + // or me // #1388 const EXCEPTION_PATHS: &'static [&'static str] = &[ diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index 2916f083ca0..e07abf74a81 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -5,9 +5,8 @@ fn test() { // comment // comment2 - // FIXME(1275) code(); /* leave this comment alone! - * ok? */ + * ok? */ /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam @@ -28,7 +27,7 @@ fn test() { // .unwrap()); funk(); //dontchangeme - // or me + // or me } /// test123 -- cgit 1.4.1-3-g733a5 From af404b998c87bb28ffb0a36a2f779a7d8371a0d1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 6 Sep 2017 18:44:33 +0900 Subject: Factor out rewrite_extern_crate() --- src/visitor.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 1fe8655309f..2de2f6865df 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -367,17 +367,8 @@ impl<'a> FmtVisitor<'a> { } } ast::ItemKind::ExternCrate(_) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - let new_str = self.snippet(item.span); - if contains_comment(&new_str) { - self.buffer.push_str(&new_str) - } else { - let no_whitespace = - &new_str.split_whitespace().collect::>().join(" "); - self.buffer - .push_str(&Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")); - } - self.last_pos = source!(self, item.span).hi(); + let rw = rewrite_extern_crate(&self.get_context(), item); + self.push_rewrite(item.span, rw); } ast::ItemKind::Struct(ref def, ref generics) => { let rewrite = { @@ -1046,3 +1037,15 @@ fn get_derive_args(context: &RewriteContext, attr: &ast::Attribute) -> Option None, }) } + +// Rewrite `extern crate foo;` WITHOUT attributes. +pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { + assert!(is_extern_crate(item)); + let new_str = context.snippet(item.span); + Some(if contains_comment(&new_str) { + new_str + } else { + let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); + String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) + }) +} -- cgit 1.4.1-3-g733a5 From 662ee46e67dd04fae3e624d246b0bd7537273752 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 6 Sep 2017 18:47:50 +0900 Subject: Use write_list() to format imports --- src/imports.rs | 192 +++++++++++++++++++++++++++++++-------------------------- src/visitor.rs | 4 +- 2 files changed, 107 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 33efce19a40..7cfe5d8b6b9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,20 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cmp::{self, Ordering}; +use std::cmp::Ordering; use syntax::{ast, ptr}; use syntax::codemap::{BytePos, Span}; -use Shape; +use {Shape, Spanned}; use codemap::SpanUtils; +use comment::combine_strs_with_missing_comments; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, ListItem, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; -use utils; -use visitor::FmtVisitor; +use utils::{format_visibility, mk_sp}; +use visitor::{rewrite_extern_crate, FmtVisitor}; fn path_of(a: &ast::ViewPath_) -> &ast::Path { match *a { @@ -185,95 +186,115 @@ impl Rewrite for ast::ViewPath { } } -impl<'a> FmtVisitor<'a> { - pub fn format_imports(&mut self, use_items: &[ptr::P]) { - // Find the location immediately before the first use item in the run. This must not lie - // before the current `self.last_pos` - let pos_before_first_use_item = use_items - .first() - .map(|p_i| { - cmp::max( - self.last_pos, - p_i.attrs - .iter() - .map(|attr| attr.span.lo()) - .min() - .unwrap_or(p_i.span.lo()), - ) - }) - .unwrap_or(self.last_pos); - // Construct a list of pairs, each containing a `use` item and the start of span before - // that `use` item. - let mut last_pos_of_prev_use_item = pos_before_first_use_item; - let mut ordered_use_items = use_items - .iter() - .map(|p_i| { - let new_item = (&*p_i, last_pos_of_prev_use_item); - last_pos_of_prev_use_item = p_i.span.hi(); - new_item - }) - .collect::>(); - let pos_after_last_use_item = last_pos_of_prev_use_item; - // Order the imports by view-path & other import path properties - ordered_use_items.sort_by(|a, b| { - compare_use_items(&self.get_context(), a.0, b.0).unwrap() - }); - // First, output the span before the first import - let prev_span_str = self.snippet(utils::mk_sp(self.last_pos, pos_before_first_use_item)); - // Look for purely trailing space at the start of the prefix snippet before a linefeed, or - // a prefix that's entirely horizontal whitespace. - let prefix_span_start = match prev_span_str.find('\n') { - Some(offset) if prev_span_str[..offset].trim().is_empty() => { - self.last_pos + BytePos(offset as u32) - } - None if prev_span_str.trim().is_empty() => pos_before_first_use_item, - _ => self.last_pos, - }; - // Look for indent (the line part preceding the use is all whitespace) and excise that - // from the prefix - let span_end = match prev_span_str.rfind('\n') { - Some(offset) if prev_span_str[offset..].trim().is_empty() => { - self.last_pos + BytePos(offset as u32) +// Rewrite `use foo;` WITHOUT attributes. +fn rewrite_import( + context: &RewriteContext, + vis: &ast::Visibility, + vp: &ast::ViewPath, + attrs: &[ast::Attribute], + shape: Shape, +) -> Option { + let vis = format_visibility(vis); + // 4 = `use `, 1 = `;` + let rw = shape + .offset_left(vis.len() + 4) + .and_then(|shape| shape.sub_width(1)) + .and_then(|shape| match vp.node { + // If we have an empty path list with no attributes, we erase it + ast::ViewPath_::ViewPathList(_, ref path_list) + if path_list.is_empty() && attrs.is_empty() => + { + Some("".into()) } - _ => pos_before_first_use_item, - }; + _ => vp.rewrite(context, shape), + }); + match rw { + Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), + _ => rw, + } +} - self.last_pos = prefix_span_start; - self.format_missing(span_end); - for ordered in ordered_use_items { - // Fake out the formatter by setting `self.last_pos` to the appropriate location before - // each item before visiting it. - self.last_pos = ordered.1; - self.visit_item(ordered.0); +fn rewrite_imports( + context: &RewriteContext, + use_items: &[ptr::P], + shape: Shape, + span: Span, +) -> Option { + let items = itemize_list( + context.codemap, + use_items.iter(), + "", + |item| item.span().lo(), + |item| item.span().hi(), + |item| { + let attrs_str = try_opt!(item.attrs.rewrite(context, shape)); + + let missed_span = if item.attrs.is_empty() { + mk_sp(item.span.lo(), item.span.lo()) + } else { + mk_sp(item.attrs.last().unwrap().span.hi(), item.span.lo()) + }; + + let item_str = match item.node { + ast::ItemKind::Use(ref vp) => { + try_opt!(rewrite_import(context, &item.vis, vp, &item.attrs, shape)) + } + ast::ItemKind::ExternCrate(..) => try_opt!(rewrite_extern_crate(context, item)), + _ => return None, + }; + + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missed_span, + shape, + false, + ) + }, + span.lo(), + span.hi(), + false, + ); + let mut item_pair_vec: Vec<_> = items.zip(use_items.iter()).collect(); + item_pair_vec.sort_by(|a, b| compare_use_items(context, a.1, b.1).unwrap()); + let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: shape, + ends_with_newline: true, + preserve_newline: false, + config: context.config, + }; + + write_list(&item_vec, &fmt) +} + +impl<'a> FmtVisitor<'a> { + pub fn format_imports(&mut self, use_items: &[ptr::P]) { + if use_items.is_empty() { + return; } - self.last_pos = pos_after_last_use_item; + + let lo = use_items.first().unwrap().span().lo(); + let hi = use_items.last().unwrap().span().hi(); + let span = mk_sp(lo, hi); + let rw = rewrite_imports(&self.get_context(), use_items, self.shape(), span); + self.push_rewrite(span, rw); } - pub fn format_import( - &mut self, - vis: &ast::Visibility, - vp: &ast::ViewPath, - span: Span, - attrs: &[ast::Attribute], - ) { - let vis = utils::format_visibility(vis); - // 4 = `use `, 1 = `;` - let rw = self.shape() - .offset_left(vis.len() + 4) - .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| match vp.node { - // If we have an empty path list with no attributes, we erase it - ast::ViewPath_::ViewPathList(_, ref path_list) - if path_list.is_empty() && attrs.is_empty() => - { - Some("".into()) - } - _ => vp.rewrite(&self.get_context(), shape), - }); + pub fn format_import(&mut self, item: &ast::Item, vp: &ast::ViewPath) { + let span = item.span; + let shape = self.shape(); + let rw = rewrite_import(&self.get_context(), &item.vis, vp, &item.attrs, shape); match rw { Some(ref s) if s.is_empty() => { // Format up to last newline - let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo()); + let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); let span_end = match self.snippet(prev_span).rfind('\n') { Some(offset) => self.last_pos + BytePos(offset as u32), None => source!(self, span).lo(), @@ -282,7 +303,6 @@ impl<'a> FmtVisitor<'a> { self.last_pos = source!(self, span).hi(); } Some(ref s) => { - let s = format!("{}use {};", vis, s); self.format_missing_with_indent(source!(self, span).lo()); self.buffer.push_str(&s); self.last_pos = source!(self, span).hi(); diff --git a/src/visitor.rs b/src/visitor.rs index 2de2f6865df..76f6e4914e2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -342,9 +342,7 @@ impl<'a> FmtVisitor<'a> { } match item.node { - ast::ItemKind::Use(ref vp) => { - self.format_import(&item.vis, vp, item.span, &item.attrs); - } + ast::ItemKind::Use(ref vp) => self.format_import(&item, vp), ast::ItemKind::Impl(..) => { self.format_missing_with_indent(source!(self, item.span).lo()); let snippet = self.snippet(item.span); -- cgit 1.4.1-3-g733a5 From 4bd03737570c6f07e92b1bd1116bc3e56c571216 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 6 Sep 2017 19:24:14 +0900 Subject: No cloning --- src/visitor.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 76f6e4914e2..296c254ea87 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -300,7 +300,8 @@ impl<'a> FmtVisitor<'a> { // complex in the module case. It is complex because the module could be // in a separate file and there might be attributes in both files, but // the AST lumps them all together. - let mut attrs = item.attrs.clone(); + let filterd_attrs; + let mut attrs = &item.attrs; match item.node { ast::ItemKind::Mod(ref m) => { let outer_file = self.codemap.lookup_char_pos(item.span.lo()).file; @@ -318,7 +319,7 @@ impl<'a> FmtVisitor<'a> { } else { // Module is not inline and should not be skipped. We want // to process only the attributes in the current file. - let filterd_attrs = item.attrs + filterd_attrs = item.attrs .iter() .filter_map(|a| { let attr_file = self.codemap.lookup_char_pos(a.span.lo()).file; @@ -332,7 +333,7 @@ impl<'a> FmtVisitor<'a> { // Assert because if we should skip it should be caught by // the above case. assert!(!self.visit_attrs(&filterd_attrs, ast::AttrStyle::Outer)); - attrs = filterd_attrs; + attrs = &filterd_attrs; } } _ => if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { -- cgit 1.4.1-3-g733a5 From 4dbda0662964e02e02c2b1891cd1332966fef658 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 6 Sep 2017 19:24:23 +0900 Subject: Use push_rewrite() to remove duplicates --- src/visitor.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 296c254ea87..f4288d84462 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -345,25 +345,16 @@ impl<'a> FmtVisitor<'a> { match item.node { ast::ItemKind::Use(ref vp) => self.format_import(&item, vp), ast::ItemKind::Impl(..) => { - self.format_missing_with_indent(source!(self, item.span).lo()); let snippet = self.snippet(item.span); let where_span_end = snippet .find_uncommented("{") .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); - if let Some(impl_str) = - format_impl(&self.get_context(), item, self.block_indent, where_span_end) - { - self.buffer.push_str(&impl_str); - self.last_pos = source!(self, item.span).hi(); - } + let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); + self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { - self.format_missing_with_indent(item.span.lo()); - if let Some(trait_str) = format_trait(&self.get_context(), item, self.block_indent) - { - self.buffer.push_str(&trait_str); - self.last_pos = source!(self, item.span).hi(); - } + let rw = format_trait(&self.get_context(), item, self.block_indent); + self.push_rewrite(item.span, rw); } ast::ItemKind::ExternCrate(_) => { let rw = rewrite_extern_crate(&self.get_context(), item); @@ -371,17 +362,15 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Struct(ref def, ref generics) => { let rewrite = { - let indent = self.block_indent; - let context = self.get_context(); ::items::format_struct( - &context, + &self.get_context(), "struct ", item.ident, &item.vis, def, Some(generics), item.span, - indent, + self.block_indent, None, ).map(|s| match *def { ast::VariantData::Tuple(..) => s + ";", -- cgit 1.4.1-3-g733a5 From 903d815228d6d3a0afdce19defe5beafe9b039da Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 6 Sep 2017 19:30:51 +0900 Subject: Clean up --- src/visitor.rs | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index f4288d84462..aff768f450c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -22,8 +22,9 @@ use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, C FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; -use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, - rewrite_static, rewrite_type_alias}; +use items::{format_impl, format_struct, format_struct_struct, format_trait, + rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, + rewrite_type_alias}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; @@ -361,22 +362,20 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(item.span, rw); } ast::ItemKind::Struct(ref def, ref generics) => { - let rewrite = { - ::items::format_struct( - &self.get_context(), - "struct ", - item.ident, - &item.vis, - def, - Some(generics), - item.span, - self.block_indent, - None, - ).map(|s| match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - }) - }; + let rewrite = format_struct( + &self.get_context(), + "struct ", + item.ident, + &item.vis, + def, + Some(generics), + item.span, + self.block_indent, + None, + ).map(|s| match *def { + ast::VariantData::Tuple(..) => s + ";", + _ => s, + }); self.push_rewrite(item.span, rewrite); } ast::ItemKind::Enum(ref def, ref generics) => { @@ -457,7 +456,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(item.span, rewrite); } ast::ItemKind::Union(ref def, ref generics) => { - let rewrite = ::items::format_struct_struct( + let rewrite = format_struct_struct( &self.get_context(), "union ", item.ident, -- cgit 1.4.1-3-g733a5 From 45e48ec424b2e1db489db860581aaf7e684fbae0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 12:10:30 +0900 Subject: Add a new config option to control the placement of a binary operator --- src/config.rs | 2 + src/expr.rs | 112 +++++++++++++++++++++++++++++++++++++++++--------------- src/patterns.rs | 24 ++++++++++-- src/types.rs | 11 +++++- 4 files changed, 115 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 30d79cdc562..04020d1aeee 100644 --- a/src/config.rs +++ b/src/config.rs @@ -620,6 +620,8 @@ create_config! { multiline_match_arm_forces_block: bool, false, "Force multiline match arm bodies to be wrapped in a block"; merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one"; + binop_sep: SeparatorPlace, SeparatorPlace::Front, + "Where to put a binary operator when a binary expression goes multiline."; } #[cfg(test)] diff --git a/src/expr.rs b/src/expr.rs index 0b9511e02ce..dc11edde95f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -101,6 +101,7 @@ pub fn format_expr( "", context, shape, + context.config.binop_sep(), ) } ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), @@ -213,12 +214,26 @@ pub fn format_expr( ast::ExprKind::AddrOf(mutability, ref expr) => { rewrite_expr_addrof(context, mutability, expr, shape) } - ast::ExprKind::Cast(ref expr, ref ty) => { - rewrite_pair(&**expr, &**ty, "", " as ", "", context, shape) - } - ast::ExprKind::Type(ref expr, ref ty) => { - rewrite_pair(&**expr, &**ty, "", ": ", "", context, shape) - } + ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( + &**expr, + &**ty, + "", + " as ", + "", + context, + shape, + SeparatorPlace::Front, + ), + ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( + &**expr, + &**ty, + "", + ": ", + "", + context, + shape, + SeparatorPlace::Front, + ), ast::ExprKind::Index(ref expr, ref index) => { rewrite_index(&**expr, &**index, context, shape) } @@ -228,7 +243,16 @@ pub fn format_expr( } else { ("[", "]") }; - rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, shape) + rewrite_pair( + &**expr, + &**repeats, + lbr, + "; ", + rbr, + context, + shape, + SeparatorPlace::Back, + ) } ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { @@ -257,7 +281,16 @@ pub fn format_expr( } else { delim.into() }; - rewrite_pair(&*lhs, &*rhs, "", &sp_delim, "", context, shape) + rewrite_pair( + &*lhs, + &*rhs, + "", + &sp_delim, + "", + context, + shape, + SeparatorPlace::Front, + ) } (None, Some(rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { @@ -323,26 +356,29 @@ pub fn rewrite_pair( suffix: &str, context: &RewriteContext, shape: Shape, + separator_place: SeparatorPlace, ) -> Option where LHS: Rewrite, RHS: Rewrite, { - let sep = if infix.ends_with(' ') { " " } else { "" }; - let infix = infix.trim_right(); - let lhs_overhead = shape.used_width() + prefix.len() + infix.len(); + let lhs_overhead = match separator_place { + SeparatorPlace::Back => shape.used_width() + prefix.len() + infix.trim_right().len(), + SeparatorPlace::Front => shape.used_width(), + }; let lhs_shape = Shape { - width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)), + width: context.budget(lhs_overhead), ..shape }; let lhs_result = try_opt!( lhs.rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}{}", prefix, lhs_str, infix)) + .map(|lhs_str| format!("{}{}", prefix, lhs_str)) ); // Try to the both lhs and rhs on the same line. let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + suffix.len() + sep.len()) + .offset_left(last_line_width(&lhs_result) + infix.len()) + .and_then(|s| s.sub_width(suffix.len())) .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); if let Some(ref rhs_result) = rhs_orig_result { // If the rhs looks like block expression, we allow it to stay on the same line @@ -353,33 +389,49 @@ where .map(|first_line| first_line.ends_with('{')) .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { - return Some(format!("{}{}{}{}", lhs_result, sep, rhs_result, suffix)); + return Some(format!("{}{}{}{}", lhs_result, infix, rhs_result, suffix)); } } // We have to use multiple lines. // Re-evaluate the rhs because we have more space now: - let rhs_shape = match context.config.control_style() { - Style::Legacy => { - try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len()) - } + let mut rhs_shape = try_opt!(match context.config.control_style() { + Style::Legacy => shape + .sub_width(suffix.len() + prefix.len()) + .map(|s| s.visual_indent(prefix.len())), Style::Rfc => { // Try to calculate the initial constraint on the right hand side. let rhs_overhead = shape.rhs_overhead(context.config); - try_opt!( - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead) - ) + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(rhs_overhead) } + }); + let infix = match separator_place { + SeparatorPlace::Back => infix.trim_right(), + SeparatorPlace::Front => infix.trim_left(), }; + if separator_place == SeparatorPlace::Front { + rhs_shape = try_opt!(rhs_shape.offset_left(infix.len())); + } let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); - Some(format!( - "{}\n{}{}{}", - lhs_result, - rhs_shape.indent.to_string(context.config), - rhs_result, - suffix - )) + match separator_place { + SeparatorPlace::Back => Some(format!( + "{}{}\n{}{}{}", + lhs_result, + infix, + rhs_shape.indent.to_string(context.config), + rhs_result, + suffix + )), + SeparatorPlace::Front => Some(format!( + "{}\n{}{}{}{}", + lhs_result, + rhs_shape.indent.to_string(context.config), + infix, + rhs_result, + suffix + )), + } } pub fn rewrite_array<'a, I>( diff --git a/src/patterns.rs b/src/patterns.rs index c3475dfba73..ab61df22b68 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -18,7 +18,7 @@ use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, wrap_struct_field}; use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorTactic}; + struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use types::{rewrite_path, PathContext}; use utils::{format_mutability, mk_sp, wrap_str}; @@ -59,8 +59,26 @@ impl Rewrite for Pat { None }, PatKind::Range(ref lhs, ref rhs, ref end_kind) => match *end_kind { - RangeEnd::Included => rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape), - RangeEnd::Excluded => rewrite_pair(&**lhs, &**rhs, "", "..", "", context, shape), + RangeEnd::Included => rewrite_pair( + &**lhs, + &**rhs, + "", + "...", + "", + context, + shape, + SeparatorPlace::Front, + ), + RangeEnd::Excluded => rewrite_pair( + &**lhs, + &**rhs, + "", + "..", + "", + context, + shape, + SeparatorPlace::Front, + ), }, PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); diff --git a/src/types.rs b/src/types.rs index ceca0417aa8..535b71c9402 100644 --- a/src/types.rs +++ b/src/types.rs @@ -738,7 +738,16 @@ impl Rewrite for ast::Ty { let use_spaces = context.config.spaces_within_square_brackets(); let lbr = if use_spaces { "[ " } else { "[" }; let rbr = if use_spaces { " ]" } else { "]" }; - rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, shape) + rewrite_pair( + &**ty, + &**repeats, + lbr, + "; ", + rbr, + context, + shape, + SeparatorPlace::Back, + ) } ast::TyKind::Infer => if shape.width >= 1 { Some("_".to_owned()) -- cgit 1.4.1-3-g733a5 From f51261e93eedaba4ea17a70bd33fd0f34a5ded26 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 12:10:58 +0900 Subject: Cargo fmt --- src/chains.rs | 20 +++++----- src/comment.rs | 40 ++++++++++---------- src/expr.rs | 104 ++++++++++++++++++++++++++-------------------------- src/file_lines.rs | 4 +- src/imports.rs | 8 ++-- src/items.rs | 99 +++++++++++++++++++++++++------------------------ src/lib.rs | 4 +- src/lists.rs | 54 +++++++++++++-------------- src/macros.rs | 12 +++--- src/missed_spans.rs | 4 +- src/string.rs | 4 +- src/summary.rs | 4 +- src/types.rs | 4 +- src/utils.rs | 4 +- src/vertical.rs | 8 ++-- src/visitor.rs | 8 ++-- 16 files changed, 192 insertions(+), 189 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 411c3c7f45f..f6055927f86 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -183,9 +183,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { min(shape.width, context.config.chain_one_line_max()) }; - let all_in_one_line = !parent_rewrite_contains_newline && - rewrites.iter().all(|s| !s.contains('\n')) && - almost_total < one_line_budget; + let all_in_one_line = !parent_rewrite_contains_newline + && rewrites.iter().all(|s| !s.contains('\n')) + && almost_total < one_line_budget; let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, nested_shape); let (last_subexpr_str, fits_single_line) = try_opt!(if all_in_one_line || extend_last_subexr { parent_shape.offset_left(almost_total).map(|shape| { @@ -224,9 +224,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - format!("\n{}", nested_shape.indent.to_string(context.config)) }; - let first_connector = if is_small_parent || fits_single_line || - last_line_extendable(&parent_rewrite) || - context.config.chain_indent() == IndentStyle::Visual + let first_connector = if is_small_parent || fits_single_line + || last_line_extendable(&parent_rewrite) + || context.config.chain_indent() == IndentStyle::Visual { "" } else { @@ -445,12 +445,12 @@ fn choose_first_connector<'a>( ) -> &'a str { if subexpr_list.is_empty() { "" - } else if extend || subexpr_list.last().map_or(false, is_try) || - is_extendable_parent(context, parent_str) + } else if extend || subexpr_list.last().map_or(false, is_try) + || is_extendable_parent(context, parent_str) { // 1 = ";", being conservative here. - if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <= - context.config.max_width() + if last_line_width(parent_str) + first_line_width(first_child_str) + 1 + <= context.config.max_width() { "" } else { diff --git a/src/comment.rs b/src/comment.rs index 4cb8325d25e..32f46e195c1 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -91,13 +91,13 @@ impl<'a> CommentStyle<'a> { pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { match *self { CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { - line.trim_left().starts_with(self.line_start().trim_left()) || - comment_style(line, normalize_comments) == *self + line.trim_left().starts_with(self.line_start().trim_left()) + || comment_style(line, normalize_comments) == *self } CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { - line.trim_left().starts_with(self.closer().trim_left()) || - line.trim_left().starts_with(self.line_start().trim_left()) || - comment_style(line, normalize_comments) == *self + line.trim_left().starts_with(self.closer().trim_left()) + || line.trim_left().starts_with(self.line_start().trim_left()) + || comment_style(line, normalize_comments) == *self } CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), } @@ -121,8 +121,8 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { } else { CommentStyle::DoubleSlash } - } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) || - (orig.starts_with("/**") && !orig.starts_with("/**/")) + } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) + || (orig.starts_with("/**") && !orig.starts_with("/**/")) { CommentStyle::TripleSlash } else if orig.starts_with("//!") || orig.starts_with("/*!") { @@ -424,8 +424,8 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< /// Trims comment characters and possibly a single space from the left of a string. /// Does not trim all whitespace. fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { - if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || - line.starts_with("/** ") + if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") + || line.starts_with("/** ") { &line[4..] } else if let CommentStyle::Custom(opener) = *style { @@ -434,14 +434,14 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { } else { &line[opener.trim_right().len()..] } - } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || - line.starts_with("///") || line.starts_with("** ") || - line.starts_with("/*!") || - (line.starts_with("/**") && !line.starts_with("/**/")) + } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") + || line.starts_with("///") || line.starts_with("** ") + || line.starts_with("/*!") + || (line.starts_with("/**") && !line.starts_with("/**/")) { &line[3..] - } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || - line.starts_with("**") + } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") + || line.starts_with("**") { &line[2..] } else if line.starts_with('*') { @@ -771,9 +771,9 @@ impl<'a> Iterator for CommentCodeSlices<'a> { let mut iter = CharClasses::new(subslice.char_indices()); for (kind, (i, c)) in &mut iter { - let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal && - &subslice[..2] == "//" && - [' ', '\t'].contains(&c); + let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal + && &subslice[..2] == "//" + && [' ', '\t'].contains(&c); if is_comment_connector && first_whitespace.is_none() { first_whitespace = Some(i); @@ -913,8 +913,8 @@ fn remove_comment_header(comment: &str) -> &str { &comment[3..] } else if comment.starts_with("//") { &comment[2..] - } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) || - comment.starts_with("/*!") + } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) + || comment.starts_with("/*!") { &comment[3..comment.len() - 2] } else { diff --git a/src/expr.rs b/src/expr.rs index dc11edde95f..0d422ce7387 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -513,8 +513,8 @@ where }, }; let ends_with_newline = tactic.ends_with_newline(context.config.array_layout()); - if context.config.array_horizontal_layout_threshold() > 0 && - items.len() > context.config.array_horizontal_layout_threshold() + if context.config.array_horizontal_layout_threshold() > 0 + && items.len() > context.config.array_horizontal_layout_threshold() { tactic = DefinitiveListTactic::Mixed; } @@ -537,8 +537,8 @@ where }; let list_str = try_opt!(write_list(&items, &fmt)); - let result = if context.config.array_layout() == IndentStyle::Visual || - tactic == DefinitiveListTactic::Horizontal + let result = if context.config.array_layout() == IndentStyle::Visual + || tactic == DefinitiveListTactic::Horizontal { if context.config.spaces_within_square_brackets() && !list_str.is_empty() { format!("[ {} ]", list_str) @@ -671,10 +671,10 @@ fn rewrite_closure( } // Figure out if the block is necessary. - let needs_block = block.rules != ast::BlockCheckMode::Default || block.stmts.len() > 1 || - context.inside_macro || - block_contains_comment(block, context.codemap) || - prefix.contains('\n'); + let needs_block = block.rules != ast::BlockCheckMode::Default || block.stmts.len() > 1 + || context.inside_macro + || block_contains_comment(block, context.codemap) + || prefix.contains('\n'); let no_return_type = if let ast::FunctionRetTy::Default(_) = fn_decl.output { true @@ -756,8 +756,8 @@ fn rewrite_closure_block( let block_threshold = context.config.closure_block_indent_threshold(); if block_threshold >= 0 { if let Some(block_str) = block.rewrite(context, shape) { - if block_str.matches('\n').count() <= block_threshold as usize && - !need_block_indent(&block_str, shape) + if block_str.matches('\n').count() <= block_threshold as usize + && !need_block_indent(&block_str, shape) { if let Some(block_str) = block_str.rewrite(context, shape) { return Some(format!("{} {}", prefix, block_str)); @@ -780,8 +780,8 @@ fn and_one_line(x: Option) -> Option { fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| { - if block_str.starts_with('{') && budget >= 2 && - (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + if block_str.starts_with('{') && budget >= 2 + && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { "{}".to_owned() } else { @@ -805,8 +805,8 @@ fn rewrite_empty_block( let user_str = user_str.trim(); if user_str.starts_with('{') && user_str.ends_with('}') { let comment_str = user_str[1..user_str.len() - 1].trim(); - if block.stmts.is_empty() && !comment_str.contains('\n') && - !comment_str.starts_with("//") && comment_str.len() + 4 <= shape.width + if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") + && comment_str.len() + 4 <= shape.width { return Some(format!("{{ {} }}", comment_str)); } @@ -1118,9 +1118,9 @@ impl<'a> ControlFlow<'a> { let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node) = else_block.node { - if !is_simple_block(self.block, context.codemap) || - !is_simple_block(else_node, context.codemap) || - pat_expr_str.contains('\n') + if !is_simple_block(self.block, context.codemap) + || !is_simple_block(else_node, context.codemap) + || pat_expr_str.contains('\n') { return None; } @@ -1216,9 +1216,9 @@ impl<'a> ControlFlow<'a> { .max_width() .checked_sub(constr_shape.used_width() + offset + brace_overhead) .unwrap_or(0); - let force_newline_brace = context.config.control_style() == Style::Rfc && - (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) && - !last_line_extendable(&pat_expr_string); + let force_newline_brace = context.config.control_style() == Style::Rfc + && (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) + && !last_line_extendable(&pat_expr_string); // Try to format if-else on single line. if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { @@ -1259,8 +1259,8 @@ impl<'a> ControlFlow<'a> { let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { "" - } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine || - force_newline_brace + } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine + || force_newline_brace { alt_block_sep } else { @@ -1443,8 +1443,8 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { // FIXME: incorrectly returns false when comment is contained completely within // the expression. pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { - (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && - !block_contains_comment(block, codemap)) + (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) + && !block_contains_comment(block, codemap)) } /// Checks whether a block contains at most one statement or expression, and no comments. @@ -1739,8 +1739,8 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( - !context.config.multiline_match_arm_forces_block() && - expr.can_be_overflowed(context, 1), + !context.config.multiline_match_arm_forces_block() + && expr.can_be_overflowed(context, 1), &**expr, ) } else { @@ -1748,8 +1748,8 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo } } _ => ( - !context.config.multiline_match_arm_forces_block() && - body.can_be_overflowed(context, 1), + !context.config.multiline_match_arm_forces_block() + && body.can_be_overflowed(context, 1), &*body, ), } @@ -1841,9 +1841,9 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if !forbid_same_line && - (is_block || - (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => + if !forbid_same_line + && (is_block + || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => { return combine_orig_body(body_str); } @@ -1989,8 +1989,8 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt } } - if !context.config.force_format_strings() && - !string_requires_rewrite(context, span, &string_lit, shape) + if !context.config.force_format_strings() + && !string_requires_rewrite(context, span, &string_lit, shape) { return Some(string_lit); } @@ -2370,8 +2370,8 @@ where ast::ExprKind::Closure(..) => { // If the argument consists of multiple closures, we do not overflow // the last closure. - if args.len() > 1 && - args.iter() + if args.len() > 1 + && args.iter() .rev() .skip(1) .filter_map(|arg| arg.to_expr()) @@ -2410,8 +2410,8 @@ where pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { match expr.node { ast::ExprKind::Match(..) => { - (context.use_block_indent() && args_len == 1) || - (context.config.fn_call_style() == IndentStyle::Visual && args_len > 1) + (context.use_block_indent() && args_len == 1) + || (context.config.fn_call_style() == IndentStyle::Visual && args_len > 1) } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | @@ -2422,8 +2422,8 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { - context.use_block_indent() || - context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 + context.use_block_indent() + || context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 } ast::ExprKind::Array(..) | ast::ExprKind::Call(..) | @@ -2447,9 +2447,9 @@ pub fn wrap_args_with_parens( shape: Shape, nested_shape: Shape, ) -> String { - if !context.use_block_indent() || - (context.inside_macro && !args_str.contains('\n') && - args_str.len() + paren_overhead(context) <= shape.width) || is_extendable + if !context.use_block_indent() + || (context.inside_macro && !args_str.contains('\n') + && args_str.len() + paren_overhead(context) <= shape.width) || is_extendable { if context.config.spaces_within_parens() && !args_str.is_empty() { format!("( {} )", args_str) @@ -2492,8 +2492,8 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> let subexpr_str = try_opt!(subexpr.rewrite(context, sub_shape)); debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - if subexpr_str.contains('\n') || - first_line_width(&subexpr_str) + total_paren_overhead <= shape.width + if subexpr_str.contains('\n') + || first_line_width(&subexpr_str) + total_paren_overhead <= shape.width { Some(paren_wrapper(&subexpr_str)) } else { @@ -2603,8 +2603,8 @@ fn rewrite_struct_lit<'a>( let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.codemap.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, &base) && - context.config.struct_field_align_threshold() > 0 + let fields_str = if struct_lit_can_be_aligned(fields, &base) + && context.config.struct_field_align_threshold() > 0 { try_opt!(rewrite_with_alignment( fields, @@ -2678,10 +2678,10 @@ pub fn wrap_struct_field( nested_shape: Shape, one_line_width: usize, ) -> String { - if context.config.struct_lit_style() == IndentStyle::Block && - (fields_str.contains('\n') || - context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || - fields_str.len() > one_line_width) + if context.config.struct_lit_style() == IndentStyle::Block + && (fields_str.contains('\n') + || context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti + || fields_str.len() > one_line_width) { format!( "\n{}{}\n{}", @@ -2992,8 +2992,8 @@ fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { src.chars().filter(|&x| x == '\n').count() } - !next_line_rhs.contains('\n') || - count_line_breaks(orig_rhs) > count_line_breaks(next_line_rhs) + 1 + !next_line_rhs.contains('\n') + || count_line_breaks(orig_rhs) > count_line_breaks(next_line_rhs) + 1 } fn rewrite_expr_addrof( diff --git a/src/file_lines.rs b/src/file_lines.rs index 704a89017d0..948ffac0731 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -51,8 +51,8 @@ impl Range { if self.is_empty() || other.is_empty() { false } else { - (self.lo <= other.hi && other.hi <= self.hi) || - (other.lo <= self.hi && self.hi <= other.hi) + (self.lo <= other.hi && other.hi <= self.hi) + || (other.lo <= self.hi && self.hi <= other.hi) } } diff --git a/src/imports.rs b/src/imports.rs index 7cfe5d8b6b9..39446d1a97b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -132,8 +132,8 @@ fn rewrite_view_path_prefix( context: &RewriteContext, shape: Shape, ) -> Option { - let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && - path.segments.len() > 1 + let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" + && path.segments.len() > 1 { let path = &ast::Path { span: path.span, @@ -503,8 +503,8 @@ fn rewrite_use_list( IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), }; - let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && - tactic != DefinitiveListTactic::Horizontal; + let ends_with_newline = context.config.imports_indent() == IndentStyle::Block + && tactic != DefinitiveListTactic::Horizontal; let fmt = ListFormatting { tactic: tactic, diff --git a/src/items.rs b/src/items.rs index 79a178dd363..21ff353ff41 100644 --- a/src/items.rs +++ b/src/items.rs @@ -228,8 +228,8 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let block_snippet = self.snippet(mk_sp(block.span.lo(), block.span.hi())); - let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || - !context.config.fn_empty_single_line(); + let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() + || !context.config.fn_empty_single_line(); let mut newline_brace = newline_for_brace(self.config, &generics.where_clause, has_body); let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base( @@ -251,8 +251,8 @@ impl<'a> FmtVisitor<'a> { if force_newline_brace { newline_brace = true; - } else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine && - !result.contains('\n') + } else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine + && !result.contains('\n') { newline_brace = false; } @@ -313,8 +313,8 @@ impl<'a> FmtVisitor<'a> { let codemap = self.get_context().codemap; - if self.config.fn_empty_single_line() && is_empty_block(block, codemap) && - self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() + if self.config.fn_empty_single_line() && is_empty_block(block, codemap) + && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { return Some(format!("{}{{}}", fn_str)); } @@ -503,9 +503,9 @@ impl<'a> FmtVisitor<'a> { }, }; - let attrs_extendable = attrs_str.is_empty() || - (context.config.attributes_on_same_line_as_variant() && - is_attributes_extendable(&attrs_str)); + let attrs_extendable = attrs_str.is_empty() + || (context.config.attributes_on_same_line_as_variant() + && is_attributes_extendable(&attrs_str)); combine_strs_with_missing_comments( &context, &attrs_str, @@ -650,9 +650,9 @@ fn is_impl_single_line( let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; Some( - context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n') && - result.len() + where_clause_str.len() <= context.config.max_width() && - !contains_comment(&snippet[open_pos..]), + context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n') + && result.len() + where_clause_str.len() <= context.config.max_width() + && !contains_comment(&snippet[open_pos..]), ) } @@ -895,8 +895,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) )); // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line - if offset.width() + last_line_width(&result) + trait_bound_str.len() > - context.config.comment_width() + if offset.width() + last_line_width(&result) + trait_bound_str.len() + > context.config.comment_width() { result.push('\n'); let trait_indent = offset.block_only().block_indent(context.config); @@ -906,11 +906,11 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); - let where_density = if (context.config.where_density() == Density::Compressed && - (!result.contains('\n') || context.config.fn_args_layout() == IndentStyle::Block)) || - (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) || - (context.config.where_density() == Density::CompressedIfEmpty && !has_body && - !result.contains('\n')) + let where_density = if (context.config.where_density() == Density::Compressed + && (!result.contains('\n') || context.config.fn_args_layout() == IndentStyle::Block)) + || (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) + || (context.config.where_density() == Density::CompressedIfEmpty && !has_body + && !result.contains('\n')) { Density::Compressed } else { @@ -937,9 +937,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) )); // If the where clause cannot fit on the same line, // put the where clause on a new line - if !where_clause_str.contains('\n') && - last_line_width(&result) + where_clause_str.len() + offset.width() > - context.config.comment_width() + if !where_clause_str.contains('\n') + && last_line_width(&result) + where_clause_str.len() + offset.width() + > context.config.comment_width() { result.push('\n'); let width = offset.block_indent + context.config.tab_spaces() - 1; @@ -980,8 +980,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&offset.to_string(context.config)); } BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => if !where_clause_str.is_empty() && - (!trait_items.is_empty() || result.contains('\n')) + BraceStyle::SameLineWhere => if !where_clause_str.is_empty() + && (!trait_items.is_empty() || result.contains('\n')) { result.push('\n'); result.push_str(&offset.to_string(context.config)); @@ -1061,9 +1061,9 @@ pub fn format_struct_struct( None => { // 3 = ` {}`, 2 = ` {`. let overhead = if fields.is_empty() { 3 } else { 2 }; - if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine && - !fields.is_empty()) || - context.config.max_width() < overhead + result.len() + if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine + && !fields.is_empty()) + || context.config.max_width() < overhead + result.len() { format!("\n{}{{", offset.block_only().to_string(context.config)) } else { @@ -1074,8 +1074,8 @@ pub fn format_struct_struct( // 1 = `}` let overhead = if fields.is_empty() { 1 } else { 0 }; let total_width = result.len() + generics_str.len() + overhead; - if !generics_str.is_empty() && !generics_str.contains('\n') && - total_width > context.config.max_width() + if !generics_str.is_empty() && !generics_str.contains('\n') + && total_width > context.config.max_width() { result.push('\n'); result.push_str(&offset.to_string(context.config)); @@ -1224,10 +1224,10 @@ fn format_tuple_struct( result.push_str(&body); } - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') && - (result.contains('\n') || - offset.block_indent + result.len() + where_clause_str.len() + 1 > - context.config.max_width()) + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') + && (result.contains('\n') + || offset.block_indent + result.len() + where_clause_str.len() + 1 + > context.config.max_width()) { // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. @@ -1368,8 +1368,9 @@ pub fn rewrite_struct_field( let prefix = try_opt!(rewrite_struct_field_prefix(context, field)); let attrs_str = try_opt!(field.attrs.rewrite(context, shape)); - let attrs_extendable = attrs_str.is_empty() || - (context.config.attributes_on_same_line_as_field() && is_attributes_extendable(&attrs_str)); + let attrs_extendable = attrs_str.is_empty() + || (context.config.attributes_on_same_line_as_field() + && is_attributes_extendable(&attrs_str)); let missing_span = if field.attrs.is_empty() { mk_sp(field.span.lo(), field.span.lo()) } else { @@ -2154,8 +2155,9 @@ fn rewrite_args( arg_items.extend(more_items); } - let fits_in_one_line = !generics_str_contains_newline && - (arg_items.is_empty() || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + let fits_in_one_line = !generics_str_contains_newline + && (arg_items.is_empty() + || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { item.item = Some(arg); @@ -2419,8 +2421,8 @@ pub fn wrap_generics_with_angle_brackets( list_str: &str, list_offset: Indent, ) -> String { - if context.config.generics_indent() == IndentStyle::Block && - (list_str.contains('\n') || list_str.ends_with(',')) + if context.config.generics_indent() == IndentStyle::Block + && (list_str.contains('\n') || list_str.ends_with(',')) { format!( "<\n{}{}\n{}>", @@ -2528,9 +2530,9 @@ fn rewrite_where_clause_rfc_style( let newline_after_where = comment_separator(&comment_after, clause_shape); // 6 = `where ` - let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() && - comment_after.is_empty() && !preds_str.contains('\n') && - 6 + preds_str.len() <= shape.width + let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() + && comment_after.is_empty() && !preds_str.contains('\n') + && 6 + preds_str.len() <= shape.width { String::from(" ") } else { @@ -2643,8 +2645,8 @@ fn rewrite_where_clause( } else { terminator.len() }; - if density == Density::Tall || preds_str.contains('\n') || - shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width + if density == Density::Tall || preds_str.contains('\n') + || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { Some(format!( "\n{}where {}", @@ -2715,11 +2717,12 @@ fn format_generics( option, )); result.push_str(&where_clause_str); - force_same_line_brace || brace_style == BraceStyle::PreferSameLine || - (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1) + force_same_line_brace || brace_style == BraceStyle::PreferSameLine + || (generics.where_clause.predicates.is_empty() + && trimmed_last_line_width(&result) == 1) } else { - force_same_line_brace || trimmed_last_line_width(&result) == 1 || - brace_style != BraceStyle::AlwaysNextLine + force_same_line_brace || trimmed_last_line_width(&result) == 1 + || brace_style != BraceStyle::AlwaysNextLine }; let total_used_width = last_line_used_width(&result, used_width); let remaining_budget = context.budget(total_used_width); diff --git a/src/lib.rs b/src/lib.rs index ee231e2e63c..d5ea44393ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -786,8 +786,8 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m } // Check for any line width errors we couldn't correct. - let report_error_on_line_overflow = config.error_on_line_overflow() && - (config.error_on_line_overflow_comments() || !is_comment); + let report_error_on_line_overflow = config.error_on_line_overflow() + && (config.error_on_line_overflow_comments() || !is_comment); if report_error_on_line_overflow && line_len > config.max_width() { errors.push(FormattingError { line: cur_line, diff --git a/src/lists.rs b/src/lists.rs index 8d9357a0cc1..543e5296432 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -118,18 +118,18 @@ impl ListItem { } pub fn is_different_group(&self) -> bool { - self.inner_as_ref().contains('\n') || self.pre_comment.is_some() || - self.post_comment + self.inner_as_ref().contains('\n') || self.pre_comment.is_some() + || self.post_comment .as_ref() .map_or(false, |s| s.contains('\n')) } pub fn is_multiline(&self) -> bool { - self.inner_as_ref().contains('\n') || - self.pre_comment + self.inner_as_ref().contains('\n') + || self.pre_comment .as_ref() - .map_or(false, |s| s.contains('\n')) || - self.post_comment + .map_or(false, |s| s.contains('\n')) + || self.post_comment .as_ref() .map_or(false, |s| s.contains('\n')) } @@ -137,8 +137,8 @@ impl ListItem { pub fn has_comment(&self) -> bool { self.pre_comment .as_ref() - .map_or(false, |comment| comment.starts_with("//")) || - self.post_comment + .map_or(false, |comment| comment.starts_with("//")) + || self.post_comment .as_ref() .map_or(false, |comment| comment.starts_with("//")) } @@ -243,8 +243,8 @@ where let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); let real_total = total_width + total_sep_len; - if real_total <= limit && !pre_line_comments && - !items.into_iter().any(|item| item.as_ref().is_multiline()) + if real_total <= limit && !pre_line_comments + && !items.into_iter().any(|item| item.as_ref().is_multiline()) { DefinitiveListTactic::Horizontal } else { @@ -346,8 +346,8 @@ where if tactic == DefinitiveListTactic::Vertical { // We cannot keep pre-comments on the same line if the comment if normalized. - let keep_comment = if formatting.config.normalize_comments() || - item.pre_comment_style == ListItemCommentStyle::DifferentLine + let keep_comment = if formatting.config.normalize_comments() + || item.pre_comment_style == ListItemCommentStyle::DifferentLine { false } else { @@ -416,9 +416,9 @@ where let comment_shape = Shape::legacy(width, offset); // Use block-style only for the last item or multiline comments. - let block_style = !formatting.ends_with_newline && last || - comment.trim().contains('\n') || - comment.trim().len() > width; + let block_style = !formatting.ends_with_newline && last + || comment.trim().contains('\n') + || comment.trim().len() > width; rewrite_comment(comment, block_style, comment_shape, formatting.config) }; @@ -428,8 +428,8 @@ where if !formatted_comment.starts_with('\n') { let mut comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); - if first_line_width(&formatted_comment) + last_line_width(&result) + - comment_alignment + 1 > formatting.config.max_width() + if first_line_width(&formatted_comment) + last_line_width(&result) + + comment_alignment + 1 > formatting.config.max_width() { item_max_width = None; formatted_comment = try_opt!(rewrite_post_comment(&mut item_max_width)); @@ -452,8 +452,8 @@ where item_max_width = None; } - if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical && - item.new_lines + if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical + && item.new_lines { item_max_width = None; result.push('\n'); @@ -478,9 +478,9 @@ where for item in items.clone().into_iter().skip(i) { let item = item.as_ref(); let inner_item_width = item.inner_as_ref().len(); - if !first && - (item.is_different_group() || !item.post_comment.is_some() || - inner_item_width + overhead > max_budget) + if !first + && (item.is_different_group() || !item.post_comment.is_some() + || inner_item_width + overhead > max_budget) { return max_width; } @@ -714,9 +714,9 @@ where } fn total_item_width(item: &ListItem) -> usize { - comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + - comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + - item.item.as_ref().map_or(0, |str| str.len()) + comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + + item.item.as_ref().map_or(0, |str| str.len()) } fn comment_len(comment: Option<&str>) -> usize { @@ -800,8 +800,8 @@ pub fn struct_lit_formatting<'a>( context: &'a RewriteContext, force_no_trailing_comma: bool, ) -> ListFormatting<'a> { - let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual && - tactic == DefinitiveListTactic::Vertical; + let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual + && tactic == DefinitiveListTactic::Vertical; ListFormatting { tactic: tactic, separator: ",", diff --git a/src/macros.rs b/src/macros.rs index 790056e9a02..1e1bffaf995 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -230,8 +230,8 @@ pub fn rewrite_macro( let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); let lhs = try_opt!(arg_vec[0].rewrite(context, nested_shape)); let rhs = try_opt!(arg_vec[1].rewrite(context, nested_shape)); - if !lhs.contains('\n') && !rhs.contains('\n') && - lhs.len() + rhs.len() + total_overhead <= shape.width + if !lhs.contains('\n') && !rhs.contains('\n') + && lhs.len() + rhs.len() + total_overhead <= shape.width { Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) } else { @@ -373,13 +373,13 @@ fn indent_macro_snippet( ); Some( - String::from(first_line) + "\n" + - &trimmed_lines + String::from(first_line) + "\n" + + &trimmed_lines .iter() .map(|&(line, prefix_space_width)| match prefix_space_width { Some(original_indent_width) => { - let new_indent_width = indent.width() + - original_indent_width + let new_indent_width = indent.width() + + original_indent_width .checked_sub(min_prefix_space_width) .unwrap_or(0); let new_indent = Indent::from_width(context.config, new_indent_width); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 5e350cf41b4..c6f3e66669a 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -145,8 +145,8 @@ impl<'a> FmtVisitor<'a> { let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count(); - if rewrite_next_comment && - !self.config.file_lines().intersects_range( + if rewrite_next_comment + && !self.config.file_lines().intersects_range( file_name, cur_line, cur_line + subslice_num_lines, diff --git a/src/string.rs b/src/string.rs index 6cb2fcddaef..84271f20082 100644 --- a/src/string.rs +++ b/src/string.rs @@ -82,8 +82,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // If we can't break at whitespace or punctuation, grow the string instead. if cur_end < cur_start + MIN_STRING { cur_end = cur_start + max_chars; - while !(punctuation.contains(graphemes[cur_end - 1]) || - graphemes[cur_end - 1].trim().is_empty()) + while !(punctuation.contains(graphemes[cur_end - 1]) + || graphemes[cur_end - 1].trim().is_empty()) { if cur_end >= graphemes.len() { let line = &graphemes[cur_start..].join(""); diff --git a/src/summary.rs b/src/summary.rs index 7ca885a645c..cf034e7dff6 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -44,8 +44,8 @@ impl Summary { } pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors || - self.has_diff) + !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors + || self.has_diff) } pub fn add(&mut self, other: Summary) { diff --git a/src/types.rs b/src/types.rs index 535b71c9402..265ed723355 100644 --- a/src/types.rs +++ b/src/types.rs @@ -208,8 +208,8 @@ fn rewrite_segment( let params = if let Some(ref params) = segment.parameters { match **params { ast::PathParameters::AngleBracketed(ref data) - if !data.lifetimes.is_empty() || !data.types.is_empty() || - !data.bindings.is_empty() => + if !data.lifetimes.is_empty() || !data.types.is_empty() + || !data.bindings.is_empty() => { let param_list = data.lifetimes .iter() diff --git a/src/utils.rs b/src/utils.rs index 438bb027637..d8c18034830 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -165,8 +165,8 @@ pub fn trimmed_last_line_width(s: &str) -> usize { #[inline] pub fn last_line_extendable(s: &str) -> bool { s.lines().last().map_or(false, |s| { - s.ends_with("\"#") || - s.trim() + s.ends_with("\"#") + || s.trim() .chars() .all(|c| c == ')' || c == ']' || c == '}' || c == '?') }) diff --git a/src/vertical.rs b/src/vertical.rs index e069032aab3..a120eb868e5 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -53,8 +53,8 @@ impl AlignedItem for ast::StructField { } else { mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; - let attrs_extendable = context.config.attributes_on_same_line_as_field() && - is_attributes_extendable(&attrs_str); + let attrs_extendable = context.config.attributes_on_same_line_as_field() + && is_attributes_extendable(&attrs_str); rewrite_struct_field_prefix(context, self).and_then(|field_str| { combine_strs_with_missing_comments( context, @@ -184,8 +184,8 @@ pub fn rewrite_with_alignment( one_line_width, )); Some( - result + spaces + "\n" + - &shape + result + spaces + "\n" + + &shape .indent .block_indent(context.config) .to_string(context.config) + &rest_str, diff --git a/src/visitor.rs b/src/visitor.rs index 832883c2c3e..beb9ce108d2 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -722,8 +722,8 @@ impl<'a> FmtVisitor<'a> { // Decide whether this is an inline mod or an external mod. let local_file_name = self.codemap.span_to_filename(s); let inner_span = source!(self, m.inner); - let is_internal = !(inner_span.lo().0 == 0 && inner_span.hi().0 == 0) && - local_file_name == self.codemap.span_to_filename(inner_span); + let is_internal = !(inner_span.lo().0 == 0 && inner_span.hi().0 == 0) + && local_file_name == self.codemap.span_to_filename(inner_span); self.buffer.push_str(&*utils::format_visibility(vis)); self.buffer.push_str("mod "); @@ -883,8 +883,8 @@ impl<'a> Rewrite for [ast::Attribute] { // This particular horror show is to preserve line breaks in between doc // comments. An alternative would be to force such line breaks to start // with the usual doc comment token. - let (multi_line_before, multi_line_after) = if a.is_sugared_doc || - is_prev_sugared_doc + let (multi_line_before, multi_line_after) = if a.is_sugared_doc + || is_prev_sugared_doc { // Look at before and after comment and see if there are any empty lines. let comment_begin = comment.chars().position(|c| c == '/'); -- cgit 1.4.1-3-g733a5 From 2d21c0c30b03c8874660473217a072d5d84d9c79 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 15:04:30 +0900 Subject: Split after the colon of type ascription --- src/expr.rs | 2 +- tests/target/type-ascription.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0d422ce7387..defa2c215f5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -232,7 +232,7 @@ pub fn format_expr( "", context, shape, - SeparatorPlace::Front, + SeparatorPlace::Back, ), ast::ExprKind::Index(ref expr, ref index) => { rewrite_index(&**expr, &**index, context, shape) diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs index 7d581ca19a6..a2f082ba4b4 100644 --- a/tests/target/type-ascription.rs +++ b/tests/target/type-ascription.rs @@ -5,8 +5,8 @@ fn main() { let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww) - : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; x: u32 - 1u32 / 10f32: u32 } -- cgit 1.4.1-3-g733a5 From d55b3492c0c0b4cd6e7843c72a3437a534511d28 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 15:05:41 +0900 Subject: Rename binop_sep to binop_separator --- src/config.rs | 2 +- src/expr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 04020d1aeee..f76d13e5dc7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -620,7 +620,7 @@ create_config! { multiline_match_arm_forces_block: bool, false, "Force multiline match arm bodies to be wrapped in a block"; merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one"; - binop_sep: SeparatorPlace, SeparatorPlace::Front, + binop_separator: SeparatorPlace, SeparatorPlace::Front, "Where to put a binary operator when a binary expression goes multiline."; } diff --git a/src/expr.rs b/src/expr.rs index defa2c215f5..7f8a9ecfa79 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -101,7 +101,7 @@ pub fn format_expr( "", context, shape, - context.config.binop_sep(), + context.config.binop_separator(), ) } ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), -- cgit 1.4.1-3-g733a5 From 0b5d524486f572bf876df8a3c1c821506916bb97 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 17:09:30 +0900 Subject: Remove unnecessary references --- src/expr.rs | 14 +++++++------- src/items.rs | 2 +- src/lists.rs | 2 +- src/visitor.rs | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0b9511e02ce..a18d2581735 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -294,7 +294,7 @@ pub fn format_expr( Some(format!( "{}{}", "do catch ", - try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent))) + try_opt!(block.rewrite(context, Shape::legacy(budget, shape.indent))) )) } } @@ -3004,17 +3004,17 @@ impl<'a> ToExpr for ast::StructField { impl<'a> ToExpr for MacroArg { fn to_expr(&self) -> Option<&ast::Expr> { - match self { - &MacroArg::Expr(ref expr) => Some(expr), + match *self { + MacroArg::Expr(ref expr) => Some(expr), _ => None, } } fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - match self { - &MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), - &MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), - &MacroArg::Pat(..) => false, + match *self { + MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), + MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), + MacroArg::Pat(..) => false, } } } diff --git a/src/items.rs b/src/items.rs index 79a178dd363..f469ca8a11b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -330,7 +330,7 @@ impl<'a> FmtVisitor<'a> { "" }; - format_expr(&e, ExprType::Statement, &self.get_context(), self.shape()) + format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) .map(|s| s + suffix) .or_else(|| Some(self.snippet(e.span))) } diff --git a/src/lists.rs b/src/lists.rs index 8d9357a0cc1..42edc3d3d3c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -114,7 +114,7 @@ pub struct ListItem { impl ListItem { pub fn inner_as_ref(&self) -> &str { - self.item.as_ref().map_or("", |s| &*s) + self.item.as_ref().map_or("", |s| s) } pub fn is_different_group(&self) -> bool { diff --git a/src/visitor.rs b/src/visitor.rs index 832883c2c3e..d2e94540240 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -340,7 +340,7 @@ impl<'a> FmtVisitor<'a> { } match item.node { - ast::ItemKind::Use(ref vp) => self.format_import(&item, vp), + ast::ItemKind::Use(ref vp) => self.format_import(item, vp), ast::ItemKind::Impl(..) => { let snippet = self.snippet(item.span); let where_span_end = snippet @@ -381,7 +381,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Mod(ref module) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, &attrs); + self.format_mod(module, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::Mac(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); -- cgit 1.4.1-3-g733a5 From 0b3b89d51f7626895a83a48b4cf5776d0da8917c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 17:09:45 +0900 Subject: Remove unnecessary return --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 790056e9a02..daade94a5d6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -104,7 +104,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { parse_macro_arg!(ty, Ty, parse_ty); parse_macro_arg!(pat, Pat, parse_pat); - return None; + None } pub fn rewrite_macro( -- cgit 1.4.1-3-g733a5 From f0580ae91abc4e76c9d8d202460a49da874b9ac3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 18:11:24 +0900 Subject: Use Cow to avoid unnecessary allocation --- src/expr.rs | 13 +++++++++---- src/lib.rs | 35 ++++++++++++++++++++++------------- src/lists.rs | 2 +- src/macros.rs | 2 +- src/missed_spans.rs | 23 +++++++++++++++-------- src/utils.rs | 6 +++--- 6 files changed, 51 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a18d2581735..e365ef97ec5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::cmp::{min, Ordering}; +use std::borrow::Cow; use std::fmt::Write; use std::iter::{repeat, ExactSizeIterator}; @@ -1364,10 +1365,10 @@ impl<'a> Rewrite for ControlFlow<'a> { } } -fn rewrite_label(label: Option) -> String { +fn rewrite_label(label: Option) -> Cow<'static, str> { match label { - Some(ident) => format!("{}: ", ident.node), - None => "".to_owned(), + Some(ident) => Cow::from(format!("{}: ", ident.node)), + None => Cow::from(""), } } @@ -1926,7 +1927,11 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt string_lit .lines() .map(|line| { - new_indent.to_string(context.config) + line.trim_left() + format!( + "{}{}", + new_indent.to_string(context.config), + line.trim_left() + ) }) .collect::>() .join("\n") diff --git a/src/lib.rs b/src/lib.rs index ee231e2e63c..68ad35434d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ extern crate syntax; extern crate term; extern crate unicode_segmentation; +use std::borrow::Cow; use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, Write}; @@ -247,6 +248,10 @@ pub struct Indent { pub alignment: usize, } +// INDENT_BUFFER.len() == 60 +const INDENT_BUFFER: &str = " "; +const INDENT_BUFFER_LEN: usize = 60; + impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { Indent { @@ -294,21 +299,25 @@ impl Indent { self.block_indent + self.alignment } - pub fn to_string(&self, config: &Config) -> String { + pub fn to_string(&self, config: &Config) -> Cow<'static, str> { let (num_tabs, num_spaces) = if config.hard_tabs() { (self.block_indent / config.tab_spaces(), self.alignment) } else { (0, self.width()) }; let num_chars = num_tabs + num_spaces; - let mut indent = String::with_capacity(num_chars); - for _ in 0..num_tabs { - indent.push('\t') - } - for _ in 0..num_spaces { - indent.push(' ') + if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN { + Cow::from(&INDENT_BUFFER[..num_chars]) + } else { + let mut indent = String::with_capacity(num_chars); + for _ in 0..num_tabs { + indent.push('\t') + } + for _ in 0..num_spaces { + indent.push(' ') + } + Cow::from(indent) } - indent } } @@ -524,13 +533,13 @@ impl FormattingError { } } - fn msg_suffix(&self) -> String { + fn msg_suffix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) if self.is_comment => String::from( + ErrorKind::LineOverflow(..) if self.is_comment => { "use `error_on_line_overflow_comments = false` to suppress \ - the warning against line comments\n", - ), - _ => String::from(""), + the warning against line comments\n" + } + _ => "", } } diff --git a/src/lists.rs b/src/lists.rs index 42edc3d3d3c..c6b67e8e83b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -289,7 +289,7 @@ where inner_item.as_ref() }; let mut item_last_line_width = item_last_line.len() + item_sep_len; - if item_last_line.starts_with(indent_str) { + if item_last_line.starts_with(&**indent_str) { item_last_line_width -= indent_str.len(); } diff --git a/src/macros.rs b/src/macros.rs index daade94a5d6..317b020911e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -383,7 +383,7 @@ fn indent_macro_snippet( .checked_sub(min_prefix_space_width) .unwrap_or(0); let new_indent = Indent::from_width(context.config, new_indent_width); - new_indent.to_string(context.config) + line.trim() + format!("{}{}", new_indent.to_string(context.config), line.trim()) } None => String::new(), }) diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 5e350cf41b4..058e7eb210a 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; + use {Indent, Shape}; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::WriteMode; @@ -118,18 +120,23 @@ impl<'a> FmtVisitor<'a> { let file_name = &char_pos.file.name; let mut cur_line = char_pos.line; - fn replace_chars(string: &str) -> String { - string - .chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect() + fn replace_chars<'a>(string: &'a str) -> Cow<'a, str> { + if string.contains(char::is_whitespace) { + Cow::from( + string + .chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect::(), + ) + } else { + Cow::from(string) + } } - let replaced = match self.config.write_mode() { + let snippet = &*match self.config.write_mode() { WriteMode::Coverage => replace_chars(old_snippet), - _ => old_snippet.to_owned(), + _ => Cow::from(old_snippet), }; - let snippet = &*replaced; for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { debug!("{:?}: {:?}", kind, subslice); diff --git a/src/utils.rs b/src/utils.rs index 438bb027637..b6f37cce694 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -89,11 +89,11 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } #[inline] -pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String { +pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> Cow<'static, str> { if abi == abi::Abi::C && !explicit_abi { - "extern ".into() + Cow::from("extern ") } else { - format!("extern {} ", abi) + Cow::from(format!("extern {} ", abi)) } } -- cgit 1.4.1-3-g733a5 From 8e5c76094dc0c7fc85ef0e98b717480a7fb496e1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 15 Sep 2017 22:27:20 +0900 Subject: Implement ptr_vec_to_ref_vec() --- src/expr.rs | 15 ++++++--------- src/types.rs | 2 +- src/utils.rs | 8 +++++++- 3 files changed, 14 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0b9511e02ce..7d3a9453388 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -33,7 +33,7 @@ use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{binary_search, colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, - outer_attributes, paren_overhead, semicolon_for_stmt, stmt_expr, + outer_attributes, paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -85,7 +85,7 @@ pub fn format_expr( rewrite_call_with_binary_search( context, &**callee, - &args.iter().map(|x| &**x).collect::>()[..], + &ptr_vec_to_ref_vec(&args), inner_span, shape, ) @@ -112,12 +112,9 @@ pub fn format_expr( expr.span, shape, ), - ast::ExprKind::Tup(ref items) => rewrite_tuple( - context, - &items.iter().map(|x| &**x).collect::>()[..], - expr.span, - shape, - ), + ast::ExprKind::Tup(ref items) => { + rewrite_tuple(context, &ptr_vec_to_ref_vec(&items), expr.span, shape) + } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | ast::ExprKind::ForLoop(..) | @@ -2037,7 +2034,7 @@ pub fn rewrite_call( rewrite_call_inner( context, callee, - &args.iter().map(|x| &**x).collect::>(), + &ptr_vec_to_ref_vec(&args), span, shape, context.config.fn_call_width(), diff --git a/src/types.rs b/src/types.rs index ceca0417aa8..057acdcb0f1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -727,7 +727,7 @@ impl Rewrite for ast::Ty { } ast::TyKind::Tup(ref items) => rewrite_tuple( context, - &items.iter().map(|x| &**x).collect::>()[..], + &::utils::ptr_vec_to_ref_vec(&items), self.span, shape, ), diff --git a/src/utils.rs b/src/utils.rs index 438bb027637..6ec90fab59a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -11,7 +11,7 @@ use std::borrow::Cow; use std::cmp::Ordering; -use syntax::abi; +use syntax::{abi, ptr}; use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, Visibility}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; @@ -97,6 +97,12 @@ pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> String { } } +#[inline] +// Transform `Vec>` into `Vec<&T>` +pub fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { + vec.iter().map(|x| &**x).collect::>() +} + #[inline] pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { attrs -- cgit 1.4.1-3-g733a5 From 178a339fc3eb97480952a73e9409ba2e5d079f3d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 15 Sep 2017 22:31:52 +0900 Subject: Reorder use items inside blocks --- src/imports.rs | 6 +++--- src/visitor.rs | 55 ++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 45 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 7cfe5d8b6b9..ecfd091a43d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -10,7 +10,7 @@ use std::cmp::Ordering; -use syntax::{ast, ptr}; +use syntax::ast; use syntax::codemap::{BytePos, Span}; use {Shape, Spanned}; @@ -216,7 +216,7 @@ fn rewrite_import( fn rewrite_imports( context: &RewriteContext, - use_items: &[ptr::P], + use_items: &[&ast::Item], shape: Shape, span: Span, ) -> Option { @@ -275,7 +275,7 @@ fn rewrite_imports( } impl<'a> FmtVisitor<'a> { - pub fn format_imports(&mut self, use_items: &[ptr::P]) { + pub fn format_imports(&mut self, use_items: &[&ast::Item]) { if use_items.is_empty() { return; } diff --git a/src/visitor.rs b/src/visitor.rs index 832883c2c3e..46998bd78c4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,7 +11,7 @@ use std::cmp; use strings::string_buffer::StringBuffer; -use syntax::{ast, ptr, visit}; +use syntax::{ast, visit}; use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; @@ -30,7 +30,7 @@ use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, Sepa use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; -use utils::{self, contains_skip, inner_attributes, mk_sp}; +use utils::{self, contains_skip, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; fn is_use_item(item: &ast::Item) -> bool { match item.node { @@ -152,9 +152,7 @@ impl<'a> FmtVisitor<'a> { self.visit_attrs(attrs, ast::AttrStyle::Inner); } - for stmt in &b.stmts { - self.visit_stmt(stmt) - } + self.walk_block_stmts(b); if !b.stmts.is_empty() { if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { @@ -641,12 +639,7 @@ impl<'a> FmtVisitor<'a> { false } - fn reorder_items( - &mut self, - items_left: &[ptr::P], - is_item: &F, - in_group: bool, - ) -> usize + fn reorder_items(&mut self, items_left: &[&ast::Item], is_item: &F, in_group: bool) -> usize where F: Fn(&ast::Item) -> bool, { @@ -679,8 +672,7 @@ impl<'a> FmtVisitor<'a> { item_length } - fn walk_mod_items(&mut self, m: &ast::Mod) { - let mut items_left: &[ptr::P] = &m.items; + fn walk_items(&mut self, mut items_left: &[&ast::Item]) { while !items_left.is_empty() { // If the next item is a `use` declaration, then extract it and any subsequent `use`s // to be potentially reordered within `format_imports`. Otherwise, just format the @@ -711,6 +703,43 @@ impl<'a> FmtVisitor<'a> { } } + fn walk_mod_items(&mut self, m: &ast::Mod) { + self.walk_items(&ptr_vec_to_ref_vec(&m.items)); + } + + fn walk_stmts(&mut self, stmts: &[ast::Stmt]) { + fn to_stmt_item(stmt: &ast::Stmt) -> Option<&ast::Item> { + match stmt.node { + ast::StmtKind::Item(ref item) => Some(&**item), + _ => None, + } + } + + if stmts.is_empty() { + return; + } + + // Extract leading `use ...;`. + let items: Vec<_> = stmts + .iter() + .take_while(|stmt| to_stmt_item(stmt).is_some()) + .filter_map(|stmt| to_stmt_item(stmt)) + .take_while(|item| is_use_item(item)) + .collect(); + + if items.is_empty() { + self.visit_stmt(&stmts[0]); + self.walk_stmts(&stmts[1..]); + } else { + self.walk_items(&items); + self.walk_stmts(&stmts[items.len()..]); + } + } + + fn walk_block_stmts(&mut self, b: &ast::Block) { + self.walk_stmts(&b.stmts) + } + fn format_mod( &mut self, m: &ast::Mod, -- cgit 1.4.1-3-g733a5 From 1f1e037d8befd1172f52dd3695199aa293cc017d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 15:49:58 +0900 Subject: Avoid panicking when calling 'cargo fmt --all' --- src/bin/cargo-fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3d0a5589d37..4f611d85365 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -248,7 +248,7 @@ fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, std: hitlist.take(&member_name.to_string()).is_some() }) .collect(); - if hitlist.is_empty() { + if !hitlist.is_empty() { // Mimick cargo of only outputting one spec. return Err(std::io::Error::new( std::io::ErrorKind::InvalidInput, -- cgit 1.4.1-3-g733a5 From ede179c62ee27f835037fa81869183f71cba1382 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 17 Sep 2017 22:14:28 +0900 Subject: Echo back input from stdin when disable_all_formatting is true --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index ee231e2e63c..6e41f6a5f24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -881,6 +881,12 @@ pub fn format_input( ) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { let mut summary = Summary::default(); if config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err((e, summary)); + } + } return Ok((summary, FileMap::new(), FormatReport::new())); } let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); -- cgit 1.4.1-3-g733a5 From b02e813db70b180bb26f5c333ae9bb3e0ff233c5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 15 Sep 2017 22:56:00 +0900 Subject: Remove rewrite_call_with_binary_search() --- src/expr.rs | 55 +++++-------------------------------------------------- src/utils.rs | 44 -------------------------------------------- 2 files changed, 5 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e48b534da18..590360f0dbe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -32,9 +32,9 @@ use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; -use utils::{binary_search, colon_spaces, contains_skip, extra_offset, first_line_width, - inner_attributes, last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, - outer_attributes, paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr, +use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, + last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, outer_attributes, + paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -83,13 +83,8 @@ pub fn format_expr( }, ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); - rewrite_call_with_binary_search( - context, - &**callee, - &ptr_vec_to_ref_vec(&args), - inner_span, - shape, - ) + let callee_str = try_opt!(callee.rewrite(context, shape)); + rewrite_call(context, &callee_str, &args, inner_span, shape) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { @@ -2036,46 +2031,6 @@ fn string_requires_rewrite( false } -pub fn rewrite_call_with_binary_search( - context: &RewriteContext, - callee: &R, - args: &[&ast::Expr], - span: Span, - shape: Shape, -) -> Option -where - R: Rewrite, -{ - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) - } else { - false - }; - let closure = |callee_max_width| { - // FIXME using byte lens instead of char lens (and probably all over the - // place too) - let callee_shape = Shape { - width: callee_max_width, - ..shape - }; - let callee_str = callee - .rewrite(context, callee_shape) - .ok_or(Ordering::Greater)?; - - rewrite_call_inner( - context, - &callee_str, - args, - span, - shape, - context.config.fn_call_width(), - force_trailing_comma, - ) - }; - - binary_search(1, shape.width, closure) -} - pub fn rewrite_call( context: &RewriteContext, callee: &str, diff --git a/src/utils.rs b/src/utils.rs index c0795403a0c..3a53d6c48fc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::borrow::Cow; -use std::cmp::Ordering; use syntax::{abi, ptr}; use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, @@ -439,33 +438,6 @@ impl Rewrite for String { } } -// Binary search in integer range. Returns the first Ok value returned by the -// callback. -// The callback takes an integer and returns either an Ok, or an Err indicating -// whether the `guess' was too high (Ordering::Less), or too low. -// This function is guaranteed to try to the hi value first. -pub fn binary_search(mut lo: usize, mut hi: usize, callback: C) -> Option -where - C: Fn(usize) -> Result, -{ - let mut middle = hi; - - while lo <= hi { - match callback(middle) { - Ok(val) => return Some(val), - Err(Ordering::Less) => { - hi = middle - 1; - } - Err(..) => { - lo = middle + 1; - } - } - middle = (hi + lo) / 2; - } - - None -} - #[inline] pub fn colon_spaces(before: bool, after: bool) -> &'static str { match (before, after) { @@ -485,22 +457,6 @@ pub fn paren_overhead(context: &RewriteContext) -> usize { } } -#[test] -fn bin_search_test() { - let closure = |i| match i { - 4 => Ok(()), - j if j > 4 => Err(Ordering::Less), - j if j < 4 => Err(Ordering::Greater), - _ => unreachable!(), - }; - - assert_eq!(Some(()), binary_search(1, 10, &closure)); - assert_eq!(None, binary_search(1, 3, &closure)); - assert_eq!(Some(()), binary_search(0, 44, &closure)); - assert_eq!(Some(()), binary_search(4, 125, &closure)); - assert_eq!(None, binary_search(6, 100, &closure)); -} - pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { match e.node { ast::ExprKind::InPlace(ref e, _) | -- cgit 1.4.1-3-g733a5 From 20aecb3d98cac7ec87e1de1373dd241a80c54eed Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 18 Sep 2017 22:56:29 +0900 Subject: Run recover_comment_removed() only if the text changed after format --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 32f46e195c1..84169f565fd 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -826,7 +826,7 @@ pub fn recover_comment_removed( shape: Shape, ) -> Option { let snippet = context.snippet(span); - if changed_comment_content(&snippet, &new) { + if snippet != new && changed_comment_content(&snippet, &new) { // We missed some comments // Keep previous formatting if it satisfies the constrains wrap_str(snippet, context.config.max_width(), shape) -- cgit 1.4.1-3-g733a5 From 18cd19673d330111a4856640783a2efaf9b9e3f2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 18 Sep 2017 23:30:59 +0900 Subject: Remove wrap_str() from recover_comment_removed() since we will be using the original snippet no matter what. --- src/comment.rs | 8 +++----- src/expr.rs | 6 ++---- src/items.rs | 4 +--- 3 files changed, 6 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 84169f565fd..953060be226 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -18,7 +18,7 @@ use {Indent, Shape}; use config::Config; use rewrite::RewriteContext; use string::{rewrite_string, StringFormat}; -use utils::{first_line_width, last_line_width, wrap_str}; +use utils::{first_line_width, last_line_width}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { @@ -823,13 +823,11 @@ pub fn recover_comment_removed( new: String, span: Span, context: &RewriteContext, - shape: Shape, ) -> Option { let snippet = context.snippet(span); if snippet != new && changed_comment_content(&snippet, &new) { - // We missed some comments - // Keep previous formatting if it satisfies the constrains - wrap_str(snippet, context.config.max_width(), shape) + // We missed some comments. Keep the original text. + Some(snippet) } else { Some(new) } diff --git a/src/expr.rs b/src/expr.rs index 590360f0dbe..e1cf24cdf2b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -328,7 +328,7 @@ pub fn format_expr( expr_rw .and_then(|expr_str| { - recover_comment_removed(expr_str, expr.span, context, shape) + recover_comment_removed(expr_str, expr.span, context) }) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); @@ -920,9 +920,7 @@ impl Rewrite for ast::Stmt { } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, }; - result.and_then(|res| { - recover_comment_removed(res, self.span(), context, shape) - }) + result.and_then(|res| recover_comment_removed(res, self.span(), context)) } } diff --git a/src/items.rs b/src/items.rs index 344c7e57af1..13c669d698f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1488,9 +1488,7 @@ pub fn rewrite_static( lhs, expr, Shape::legacy(remaining_width, offset.block_only()), - ).and_then(|res| { - recover_comment_removed(res, span, context, Shape::indented(offset, context.config)) - }) + ).and_then(|res| recover_comment_removed(res, span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{}{};", prefix, ty_str)) -- cgit 1.4.1-3-g733a5 From df7d2be5629b7162426f8a3c6dbf005f228008fe Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 17 Sep 2017 15:23:25 +0900 Subject: Move Indent and Shape to shape.rs from lib.rs --- src/chains.rs | 2 +- src/comment.rs | 4 +- src/expr.rs | 3 +- src/imports.rs | 3 +- src/items.rs | 3 +- src/lib.rs | 341 +-------------------------------------------------- src/lists.rs | 2 +- src/macros.rs | 2 +- src/missed_spans.rs | 5 +- src/patterns.rs | 3 +- src/rewrite.rs | 2 +- src/shape.rs | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/string.rs | 5 +- src/types.rs | 3 +- src/utils.rs | 2 +- src/vertical.rs | 3 +- src/visitor.rs | 3 +- 17 files changed, 372 insertions(+), 358 deletions(-) create mode 100644 src/shape.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f6055927f86..23c311b9589 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -76,7 +76,7 @@ /// .qux /// ``` -use Shape; +use shape::Shape; use config::IndentStyle; use expr::rewrite_call; use macros::convert_try_mac; diff --git a/src/comment.rs b/src/comment.rs index 953060be226..f74684e5862 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -14,9 +14,9 @@ use std::{self, iter}; use syntax::codemap::Span; -use {Indent, Shape}; use config::Config; use rewrite::RewriteContext; +use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; use utils::{first_line_width, last_line_width}; @@ -928,7 +928,7 @@ fn remove_comment_header(comment: &str) -> &str { mod test { use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, FindUncommented, FullCodeCharKind}; - use {Indent, Shape}; + use shape::{Indent, Shape}; #[test] fn char_classes() { diff --git a/src/expr.rs b/src/expr.rs index e1cf24cdf2b..91e63d256bd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -17,7 +17,7 @@ use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; use syntax::parse::classify; -use {Indent, Shape, Spanned}; +use Spanned; use chains::rewrite_chain; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, @@ -30,6 +30,7 @@ use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_format use macros::{rewrite_macro, MacroArg, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, diff --git a/src/imports.rs b/src/imports.rs index 98a57fc112f..aa778341f2a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -13,13 +13,14 @@ use std::cmp::Ordering; use syntax::ast; use syntax::codemap::{BytePos, Span}; -use {Shape, Spanned}; +use Spanned; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, ListItem, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; use types::{rewrite_path, PathContext}; use utils::{format_visibility, mk_sp}; use visitor::{rewrite_extern_crate, FmtVisitor}; diff --git a/src/items.rs b/src/items.rs index 13c669d698f..4fcd0d8b494 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,7 +16,7 @@ use syntax::{abi, ast, ptr, symbol}; use syntax::ast::ImplItem; use syntax::codemap::{BytePos, Span}; -use {Indent, Shape, Spanned}; +use Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; @@ -26,6 +26,7 @@ use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, diff --git a/src/lib.rs b/src/lib.rs index 043f6f506d0..2e95966694f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,6 @@ use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, Write}; use std::iter::repeat; -use std::ops::{Add, Sub}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -52,6 +51,7 @@ pub use self::summary::Summary; #[macro_use] mod utils; +mod shape; pub mod config; pub mod codemap; pub mod filemap; @@ -239,260 +239,6 @@ impl Spanned for MacroArg { } } -#[derive(Copy, Clone, Debug)] -pub struct Indent { - // Width of the block indent, in characters. Must be a multiple of - // Config::tab_spaces. - pub block_indent: usize, - // Alignment in characters. - pub alignment: usize, -} - -// INDENT_BUFFER.len() == 60 -const INDENT_BUFFER: &str = " "; -const INDENT_BUFFER_LEN: usize = 60; - -impl Indent { - pub fn new(block_indent: usize, alignment: usize) -> Indent { - Indent { - block_indent: block_indent, - alignment: alignment, - } - } - - pub fn from_width(config: &Config, width: usize) -> Indent { - if config.hard_tabs() { - let tab_num = width / config.tab_spaces(); - let alignment = width % config.tab_spaces(); - Indent::new(config.tab_spaces() * tab_num, alignment) - } else { - Indent::new(width, 0) - } - } - - pub fn empty() -> Indent { - Indent::new(0, 0) - } - - pub fn block_only(&self) -> Indent { - Indent { - block_indent: self.block_indent, - alignment: 0, - } - } - - pub fn block_indent(mut self, config: &Config) -> Indent { - self.block_indent += config.tab_spaces(); - self - } - - pub fn block_unindent(mut self, config: &Config) -> Indent { - if self.block_indent < config.tab_spaces() { - Indent::new(self.block_indent, 0) - } else { - self.block_indent -= config.tab_spaces(); - self - } - } - - pub fn width(&self) -> usize { - self.block_indent + self.alignment - } - - pub fn to_string(&self, config: &Config) -> Cow<'static, str> { - let (num_tabs, num_spaces) = if config.hard_tabs() { - (self.block_indent / config.tab_spaces(), self.alignment) - } else { - (0, self.width()) - }; - let num_chars = num_tabs + num_spaces; - if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN { - Cow::from(&INDENT_BUFFER[..num_chars]) - } else { - let mut indent = String::with_capacity(num_chars); - for _ in 0..num_tabs { - indent.push('\t') - } - for _ in 0..num_spaces { - indent.push(' ') - } - Cow::from(indent) - } - } -} - -impl Add for Indent { - type Output = Indent; - - fn add(self, rhs: Indent) -> Indent { - Indent { - block_indent: self.block_indent + rhs.block_indent, - alignment: self.alignment + rhs.alignment, - } - } -} - -impl Sub for Indent { - type Output = Indent; - - fn sub(self, rhs: Indent) -> Indent { - Indent::new( - self.block_indent - rhs.block_indent, - self.alignment - rhs.alignment, - ) - } -} - -impl Add for Indent { - type Output = Indent; - - fn add(self, rhs: usize) -> Indent { - Indent::new(self.block_indent, self.alignment + rhs) - } -} - -impl Sub for Indent { - type Output = Indent; - - fn sub(self, rhs: usize) -> Indent { - Indent::new(self.block_indent, self.alignment - rhs) - } -} - -#[derive(Copy, Clone, Debug)] -pub struct Shape { - pub width: usize, - // The current indentation of code. - pub indent: Indent, - // Indentation + any already emitted text on the first line of the current - // statement. - pub offset: usize, -} - -impl Shape { - /// `indent` is the indentation of the first line. The next lines - /// should begin with at least `indent` spaces (except backwards - /// indentation). The first line should not begin with indentation. - /// `width` is the maximum number of characters on the last line - /// (excluding `indent`). The width of other lines is not limited by - /// `width`. - /// Note that in reality, we sometimes use width for lines other than the - /// last (i.e., we are conservative). - // .......*-------* - // | | - // | *-* - // *-----| - // |<------------>| max width - // |<---->| indent - // |<--->| width - pub fn legacy(width: usize, indent: Indent) -> Shape { - Shape { - width: width, - indent: indent, - offset: indent.alignment, - } - } - - pub fn indented(indent: Indent, config: &Config) -> Shape { - Shape { - width: config.max_width().checked_sub(indent.width()).unwrap_or(0), - indent: indent, - offset: indent.alignment, - } - } - - pub fn with_max_width(&self, config: &Config) -> Shape { - Shape { - width: config - .max_width() - .checked_sub(self.indent.width()) - .unwrap_or(0), - ..*self - } - } - - pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { - Shape { - width: width, - indent: indent, - offset: offset, - } - } - - pub fn visual_indent(&self, extra_width: usize) -> Shape { - let alignment = self.offset + extra_width; - Shape { - width: self.width, - indent: Indent::new(self.indent.block_indent, alignment), - offset: alignment, - } - } - - pub fn block_indent(&self, extra_width: usize) -> Shape { - if self.indent.alignment == 0 { - Shape { - width: self.width, - indent: Indent::new(self.indent.block_indent + extra_width, 0), - offset: 0, - } - } else { - Shape { - width: self.width, - indent: self.indent + extra_width, - offset: self.indent.alignment + extra_width, - } - } - } - - pub fn block_left(&self, width: usize) -> Option { - self.block_indent(width).sub_width(width) - } - - pub fn add_offset(&self, extra_width: usize) -> Shape { - Shape { - offset: self.offset + extra_width, - ..*self - } - } - - pub fn block(&self) -> Shape { - Shape { - indent: self.indent.block_only(), - ..*self - } - } - - pub fn sub_width(&self, width: usize) -> Option { - Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - ..*self - }) - } - - pub fn shrink_left(&self, width: usize) -> Option { - Some(Shape { - width: try_opt!(self.width.checked_sub(width)), - indent: self.indent + width, - offset: self.offset + width, - }) - } - - pub fn offset_left(&self, width: usize) -> Option { - self.add_offset(width).sub_width(width) - } - - pub fn used_width(&self) -> usize { - self.indent.block_indent + self.offset - } - - pub fn rhs_overhead(&self, config: &Config) -> usize { - config - .max_width() - .checked_sub(self.used_width() + self.width) - .unwrap_or(0) - } -} - pub enum ErrorKind { // Line has exceeded character limit (found, maximum) LineOverflow(usize, usize), @@ -1000,88 +746,3 @@ pub fn run(input: Input, config: &Config) -> Summary { } } } - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn indent_add_sub() { - let indent = Indent::new(4, 8) + Indent::new(8, 12); - assert_eq!(12, indent.block_indent); - assert_eq!(20, indent.alignment); - - let indent = indent - Indent::new(4, 4); - assert_eq!(8, indent.block_indent); - assert_eq!(16, indent.alignment); - } - - #[test] - fn indent_add_sub_alignment() { - let indent = Indent::new(4, 8) + 4; - assert_eq!(4, indent.block_indent); - assert_eq!(12, indent.alignment); - - let indent = indent - 4; - assert_eq!(4, indent.block_indent); - assert_eq!(8, indent.alignment); - } - - #[test] - fn indent_to_string_spaces() { - let config = Config::default(); - let indent = Indent::new(4, 8); - - // 12 spaces - assert_eq!(" ", indent.to_string(&config)); - } - - #[test] - fn indent_to_string_hard_tabs() { - let mut config = Config::default(); - config.set().hard_tabs(true); - let indent = Indent::new(8, 4); - - // 2 tabs + 4 spaces - assert_eq!("\t\t ", indent.to_string(&config)); - } - - #[test] - fn shape_visual_indent() { - let config = Config::default(); - let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.visual_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(4, shape.indent.block_indent); - assert_eq!(28, shape.indent.alignment); - assert_eq!(28, shape.offset); - } - - #[test] - fn shape_block_indent_without_alignment() { - let config = Config::default(); - let indent = Indent::new(4, 0); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.block_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(24, shape.indent.block_indent); - assert_eq!(0, shape.indent.alignment); - assert_eq!(0, shape.offset); - } - - #[test] - fn shape_block_indent_with_alignment() { - let config = Config::default(); - let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.block_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(4, shape.indent.block_indent); - assert_eq!(28, shape.indent.alignment); - assert_eq!(28, shape.offset); - } -} diff --git a/src/lists.rs b/src/lists.rs index 8fd21c7f737..f42e3ffe977 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -13,10 +13,10 @@ use std::iter::Peekable; use syntax::codemap::{BytePos, CodeMap}; -use {Indent, Shape}; use comment::{find_comment_end, rewrite_comment, FindUncommented}; use config::{Config, IndentStyle}; use rewrite::RewriteContext; +use shape::{Indent, Shape}; use utils::{first_line_width, last_line_width, mk_sp}; /// Formatting tactic for lists. This will be cast down to a diff --git a/src/macros.rs b/src/macros.rs index a1254b4541d..5b52567087e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -28,11 +28,11 @@ use syntax::symbol; use syntax::tokenstream::TokenStream; use syntax::util::ThinVec; -use {Indent, Shape}; use codemap::SpanUtils; use comment::{contains_comment, FindUncommented}; use expr::{rewrite_array, rewrite_call_inner}; use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; use utils::mk_sp; const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 32e321dd257..9d20e6c6e55 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -10,10 +10,11 @@ use std::borrow::Cow; -use {Indent, Shape}; +use syntax::codemap::{BytePos, Pos, Span}; + use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::WriteMode; -use syntax::codemap::{BytePos, Pos, Span}; +use shape::{Indent, Shape}; use utils::mk_sp; use visitor::FmtVisitor; diff --git a/src/patterns.rs b/src/patterns.rs index ab61df22b68..49c7556894f 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -12,7 +12,7 @@ use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd}; use syntax::codemap::{self, BytePos, Span}; use syntax::ptr; -use {Shape, Spanned}; +use Spanned; use codemap::SpanUtils; use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, @@ -20,6 +20,7 @@ use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_una use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; use types::{rewrite_path, PathContext}; use utils::{format_mutability, mk_sp, wrap_str}; diff --git a/src/rewrite.rs b/src/rewrite.rs index 6a7167537c9..e2be8ef086c 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -13,8 +13,8 @@ use syntax::codemap::{CodeMap, Span}; use syntax::parse::ParseSess; -use Shape; use config::{Config, IndentStyle}; +use shape::Shape; pub trait Rewrite { /// Rewrite self into shape. diff --git a/src/shape.rs b/src/shape.rs new file mode 100644 index 00000000000..63910c29707 --- /dev/null +++ b/src/shape.rs @@ -0,0 +1,344 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::{Add, Sub}; + +use Config; + +#[derive(Copy, Clone, Debug)] +pub struct Indent { + // Width of the block indent, in characters. Must be a multiple of + // Config::tab_spaces. + pub block_indent: usize, + // Alignment in characters. + pub alignment: usize, +} + +impl Indent { + pub fn new(block_indent: usize, alignment: usize) -> Indent { + Indent { + block_indent: block_indent, + alignment: alignment, + } + } + + pub fn from_width(config: &Config, width: usize) -> Indent { + if config.hard_tabs() { + let tab_num = width / config.tab_spaces(); + let alignment = width % config.tab_spaces(); + Indent::new(config.tab_spaces() * tab_num, alignment) + } else { + Indent::new(width, 0) + } + } + + pub fn empty() -> Indent { + Indent::new(0, 0) + } + + pub fn block_only(&self) -> Indent { + Indent { + block_indent: self.block_indent, + alignment: 0, + } + } + + pub fn block_indent(mut self, config: &Config) -> Indent { + self.block_indent += config.tab_spaces(); + self + } + + pub fn block_unindent(mut self, config: &Config) -> Indent { + if self.block_indent < config.tab_spaces() { + Indent::new(self.block_indent, 0) + } else { + self.block_indent -= config.tab_spaces(); + self + } + } + + pub fn width(&self) -> usize { + self.block_indent + self.alignment + } + + pub fn to_string(&self, config: &Config) -> String { + let (num_tabs, num_spaces) = if config.hard_tabs() { + (self.block_indent / config.tab_spaces(), self.alignment) + } else { + (0, self.width()) + }; + let num_chars = num_tabs + num_spaces; + let mut indent = String::with_capacity(num_chars); + for _ in 0..num_tabs { + indent.push('\t') + } + for _ in 0..num_spaces { + indent.push(' ') + } + indent + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: Indent) -> Indent { + Indent { + block_indent: self.block_indent + rhs.block_indent, + alignment: self.alignment + rhs.alignment, + } + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: Indent) -> Indent { + Indent::new( + self.block_indent - rhs.block_indent, + self.alignment - rhs.alignment, + ) + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment + rhs) + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment - rhs) + } +} + +#[derive(Copy, Clone, Debug)] +pub struct Shape { + pub width: usize, + // The current indentation of code. + pub indent: Indent, + // Indentation + any already emitted text on the first line of the current + // statement. + pub offset: usize, +} + +impl Shape { + /// `indent` is the indentation of the first line. The next lines + /// should begin with at least `indent` spaces (except backwards + /// indentation). The first line should not begin with indentation. + /// `width` is the maximum number of characters on the last line + /// (excluding `indent`). The width of other lines is not limited by + /// `width`. + /// Note that in reality, we sometimes use width for lines other than the + /// last (i.e., we are conservative). + // .......*-------* + // | | + // | *-* + // *-----| + // |<------------>| max width + // |<---->| indent + // |<--->| width + pub fn legacy(width: usize, indent: Indent) -> Shape { + Shape { + width: width, + indent: indent, + offset: indent.alignment, + } + } + + pub fn indented(indent: Indent, config: &Config) -> Shape { + Shape { + width: config.max_width().checked_sub(indent.width()).unwrap_or(0), + indent: indent, + offset: indent.alignment, + } + } + + pub fn with_max_width(&self, config: &Config) -> Shape { + Shape { + width: config + .max_width() + .checked_sub(self.indent.width()) + .unwrap_or(0), + ..*self + } + } + + pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { + Shape { + width: width, + indent: indent, + offset: offset, + } + } + + pub fn visual_indent(&self, extra_width: usize) -> Shape { + let alignment = self.offset + extra_width; + Shape { + width: self.width, + indent: Indent::new(self.indent.block_indent, alignment), + offset: alignment, + } + } + + pub fn block_indent(&self, extra_width: usize) -> Shape { + if self.indent.alignment == 0 { + Shape { + width: self.width, + indent: Indent::new(self.indent.block_indent + extra_width, 0), + offset: 0, + } + } else { + Shape { + width: self.width, + indent: self.indent + extra_width, + offset: self.indent.alignment + extra_width, + } + } + } + + pub fn block_left(&self, width: usize) -> Option { + self.block_indent(width).sub_width(width) + } + + pub fn add_offset(&self, extra_width: usize) -> Shape { + Shape { + offset: self.offset + extra_width, + ..*self + } + } + + pub fn block(&self) -> Shape { + Shape { + indent: self.indent.block_only(), + ..*self + } + } + + pub fn sub_width(&self, width: usize) -> Option { + Some(Shape { + width: try_opt!(self.width.checked_sub(width)), + ..*self + }) + } + + pub fn shrink_left(&self, width: usize) -> Option { + Some(Shape { + width: try_opt!(self.width.checked_sub(width)), + indent: self.indent + width, + offset: self.offset + width, + }) + } + + pub fn offset_left(&self, width: usize) -> Option { + self.add_offset(width).sub_width(width) + } + + pub fn used_width(&self) -> usize { + self.indent.block_indent + self.offset + } + + pub fn rhs_overhead(&self, config: &Config) -> usize { + config + .max_width() + .checked_sub(self.used_width() + self.width) + .unwrap_or(0) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn indent_add_sub() { + let indent = Indent::new(4, 8) + Indent::new(8, 12); + assert_eq!(12, indent.block_indent); + assert_eq!(20, indent.alignment); + + let indent = indent - Indent::new(4, 4); + assert_eq!(8, indent.block_indent); + assert_eq!(16, indent.alignment); + } + + #[test] + fn indent_add_sub_alignment() { + let indent = Indent::new(4, 8) + 4; + assert_eq!(4, indent.block_indent); + assert_eq!(12, indent.alignment); + + let indent = indent - 4; + assert_eq!(4, indent.block_indent); + assert_eq!(8, indent.alignment); + } + + #[test] + fn indent_to_string_spaces() { + let config = Config::default(); + let indent = Indent::new(4, 8); + + // 12 spaces + assert_eq!(" ", indent.to_string(&config)); + } + + #[test] + fn indent_to_string_hard_tabs() { + let mut config = Config::default(); + config.set().hard_tabs(true); + let indent = Indent::new(8, 4); + + // 2 tabs + 4 spaces + assert_eq!("\t\t ", indent.to_string(&config)); + } + + #[test] + fn shape_visual_indent() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.visual_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } + + #[test] + fn shape_block_indent_without_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 0); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(24, shape.indent.block_indent); + assert_eq!(0, shape.indent.alignment); + assert_eq!(0, shape.offset); + } + + #[test] + fn shape_block_indent_with_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } +} diff --git a/src/string.rs b/src/string.rs index 84271f20082..8090926522d 100644 --- a/src/string.rs +++ b/src/string.rs @@ -13,8 +13,8 @@ use regex::Regex; use unicode_segmentation::UnicodeSegmentation; -use Shape; use config::Config; +use shape::Shape; use utils::wrap_str; const MIN_STRING: usize = 10; @@ -128,6 +128,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option #[cfg(test)] mod test { use super::{rewrite_string, StringFormat}; + use shape::{Indent, Shape}; #[test] fn issue343() { @@ -137,7 +138,7 @@ mod test { closer: "\"", line_start: " ", line_end: "\\", - shape: ::Shape::legacy(2, ::Indent::empty()), + shape: Shape::legacy(2, Indent::empty()), trim_end: false, config: &config, }; diff --git a/src/types.rs b/src/types.rs index 65bcf872bf5..e6cf052d142 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,7 +17,7 @@ use syntax::codemap::{self, BytePos, Span}; use syntax::print::pprust; use syntax::symbol::keywords; -use {Shape, Spanned}; +use Spanned; use codemap::SpanUtils; use config::{IndentStyle, Style, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; @@ -25,6 +25,7 @@ use items::{format_generics_item_list, generics_shape_from_config}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp, wrap_str}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/src/utils.rs b/src/utils.rs index 3a53d6c48fc..3c97044f5c4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,8 +15,8 @@ use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, Neste Path, Visibility}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; -use Shape; use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; // When we get scoped annotations, we should have rustfmt::skip. const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; diff --git a/src/vertical.rs b/src/vertical.rs index a120eb868e5..13de2e22e5d 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -15,7 +15,7 @@ use std::cmp; use syntax::ast; use syntax::codemap::{BytePos, Span}; -use {Indent, Shape, Spanned}; +use Spanned; use codemap::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; @@ -23,6 +23,7 @@ use items::{rewrite_struct_field, rewrite_struct_field_prefix}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, SeparatorPlace}; use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; use utils::{contains_skip, is_attributes_extendable, mk_sp}; pub trait AlignedItem { diff --git a/src/visitor.rs b/src/visitor.rs index 32ab6af282e..fa9c8e3b537 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,7 +16,7 @@ use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; -use {Indent, Shape, Spanned}; +use Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, CommentCodeSlices, FindUncommented}; @@ -30,6 +30,7 @@ use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, Sepa use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; use utils::{self, contains_skip, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; fn is_use_item(item: &ast::Item) -> bool { -- cgit 1.4.1-3-g733a5 From 32fa51a6a97885491ae0e9bf115291760afc7e16 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 17 Sep 2017 15:32:00 +0900 Subject: Move Spanned to spanned.rs from lib.rs --- src/expr.rs | 2 +- src/imports.rs | 2 +- src/items.rs | 2 +- src/lib.rs | 169 +---------------------------------------------------- src/patterns.rs | 2 +- src/spanned.rs | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.rs | 2 +- src/vertical.rs | 2 +- src/visitor.rs | 2 +- 9 files changed, 188 insertions(+), 173 deletions(-) create mode 100644 src/spanned.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 91e63d256bd..699e8091d81 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -17,7 +17,7 @@ use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; use syntax::parse::classify; -use Spanned; +use spanned::Spanned; use chains::rewrite_chain; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, diff --git a/src/imports.rs b/src/imports.rs index aa778341f2a..4331ea84bc5 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -13,7 +13,7 @@ use std::cmp::Ordering; use syntax::ast; use syntax::codemap::{BytePos, Span}; -use Spanned; +use spanned::Spanned; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; use config::IndentStyle; diff --git a/src/items.rs b/src/items.rs index 4fcd0d8b494..7f2bbe906da 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,7 +16,7 @@ use syntax::{abi, ast, ptr, symbol}; use syntax::ast::ImplItem; use syntax::codemap::{BytePos, Span}; -use Spanned; +use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; diff --git a/src/lib.rs b/src/lib.rs index 2e95966694f..c78aa050984 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,17 +34,16 @@ use std::rc::Rc; use errors::{DiagnosticBuilder, Handler}; use errors::emitter::{ColorConfig, EmitterWriter}; -use macros::MacroArg; use strings::string_buffer::StringBuffer; use syntax::ast; -use syntax::codemap::{CodeMap, FilePathMapping, Span}; +use syntax::codemap::{CodeMap, FilePathMapping}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; -use utils::{isatty, mk_sp, outer_attributes}; +use utils::isatty; use visitor::FmtVisitor; pub use self::summary::Summary; @@ -52,6 +51,7 @@ pub use self::summary::Summary; #[macro_use] mod utils; mod shape; +mod spanned; pub mod config; pub mod codemap; pub mod filemap; @@ -76,169 +76,6 @@ mod patterns; mod summary; mod vertical; -/// Spanned returns a span including attributes, if available. -pub trait Spanned { - fn span(&self) -> Span; -} - -macro_rules! span_with_attrs_lo_hi { - ($this:ident, $lo:expr, $hi:expr) => { - { - let attrs = outer_attributes(&$this.attrs); - if attrs.is_empty() { - mk_sp($lo, $hi) - } else { - mk_sp(attrs[0].span.lo(), $hi) - } - } - } -} - -macro_rules! span_with_attrs { - ($this:ident) => { - span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) - } -} - -macro_rules! implement_spanned { - ($this:ty) => { - impl Spanned for $this { - fn span(&self) -> Span { - span_with_attrs!(self) - } - } - } -} - -// Implement `Spanned` for structs with `attrs` field. -implement_spanned!(ast::Expr); -implement_spanned!(ast::Field); -implement_spanned!(ast::ForeignItem); -implement_spanned!(ast::Item); -implement_spanned!(ast::Local); - -impl Spanned for ast::Stmt { - fn span(&self) -> Span { - match self.node { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), - ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { - mk_sp(expr.span().lo(), self.span.hi()) - } - ast::StmtKind::Mac(ref mac) => { - let (_, _, ref attrs) = **mac; - if attrs.is_empty() { - self.span - } else { - mk_sp(attrs[0].span.lo(), self.span.hi()) - } - } - } - } -} - -impl Spanned for ast::Pat { - fn span(&self) -> Span { - self.span - } -} - -impl Spanned for ast::Ty { - fn span(&self) -> Span { - self.span - } -} - -impl Spanned for ast::Arm { - fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.pats[0].span.lo(), self.body.span.hi()) - } -} - -impl Spanned for ast::Arg { - fn span(&self) -> Span { - if items::is_named_arg(self) { - utils::mk_sp(self.pat.span.lo(), self.ty.span.hi()) - } else { - self.ty.span - } - } -} - -impl Spanned for ast::StructField { - fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) - } -} - -impl Spanned for ast::WherePredicate { - fn span(&self) -> Span { - match *self { - ast::WherePredicate::BoundPredicate(ref p) => p.span, - ast::WherePredicate::RegionPredicate(ref p) => p.span, - ast::WherePredicate::EqPredicate(ref p) => p.span, - } - } -} - -impl Spanned for ast::FunctionRetTy { - fn span(&self) -> Span { - match *self { - ast::FunctionRetTy::Default(span) => span, - ast::FunctionRetTy::Ty(ref ty) => ty.span, - } - } -} - -impl Spanned for ast::TyParam { - fn span(&self) -> Span { - // Note that ty.span is the span for ty.ident, not the whole item. - let lo = if self.attrs.is_empty() { - self.span.lo() - } else { - self.attrs[0].span.lo() - }; - if let Some(ref def) = self.default { - return mk_sp(lo, def.span.hi()); - } - if self.bounds.is_empty() { - return mk_sp(lo, self.span.hi()); - } - let hi = self.bounds[self.bounds.len() - 1].span().hi(); - mk_sp(lo, hi) - } -} - -impl Spanned for ast::TyParamBound { - fn span(&self) -> Span { - match *self { - ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, - ast::TyParamBound::RegionTyParamBound(ref l) => l.span, - } - } -} - -impl Spanned for ast::LifetimeDef { - fn span(&self) -> Span { - let hi = if self.bounds.is_empty() { - self.lifetime.span.hi() - } else { - self.bounds[self.bounds.len() - 1].span.hi() - }; - mk_sp(self.lifetime.span.lo(), hi) - } -} - -impl Spanned for MacroArg { - fn span(&self) -> Span { - match *self { - MacroArg::Expr(ref expr) => expr.span(), - MacroArg::Ty(ref ty) => ty.span(), - MacroArg::Pat(ref pat) => pat.span(), - } - } -} - pub enum ErrorKind { // Line has exceeded character limit (found, maximum) LineOverflow(usize, usize), diff --git a/src/patterns.rs b/src/patterns.rs index 49c7556894f..d1b080f4a38 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -12,7 +12,7 @@ use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd}; use syntax::codemap::{self, BytePos, Span}; use syntax::ptr; -use Spanned; +use spanned::Spanned; use codemap::SpanUtils; use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, diff --git a/src/spanned.rs b/src/spanned.rs new file mode 100644 index 00000000000..6978f2812e6 --- /dev/null +++ b/src/spanned.rs @@ -0,0 +1,178 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::ast; +use syntax::codemap::Span; + +use macros::MacroArg; +use utils::{mk_sp, outer_attributes}; + +/// Spanned returns a span including attributes, if available. +pub trait Spanned { + fn span(&self) -> Span; +} + +macro_rules! span_with_attrs_lo_hi { + ($this:ident, $lo:expr, $hi:expr) => { + { + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo(), $hi) + } + } + } +} + +macro_rules! span_with_attrs { + ($this:ident) => { + span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) + } +} + +macro_rules! implement_spanned { + ($this:ty) => { + impl Spanned for $this { + fn span(&self) -> Span { + span_with_attrs!(self) + } + } + } +} + +// Implement `Spanned` for structs with `attrs` field. +implement_spanned!(ast::Expr); +implement_spanned!(ast::Field); +implement_spanned!(ast::ForeignItem); +implement_spanned!(ast::Item); +implement_spanned!(ast::Local); + +impl Spanned for ast::Stmt { + fn span(&self) -> Span { + match self.node { + ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { + mk_sp(expr.span().lo(), self.span.hi()) + } + ast::StmtKind::Mac(ref mac) => { + let (_, _, ref attrs) = **mac; + if attrs.is_empty() { + self.span + } else { + mk_sp(attrs[0].span.lo(), self.span.hi()) + } + } + } + } +} + +impl Spanned for ast::Pat { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Ty { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Arm { + fn span(&self) -> Span { + span_with_attrs_lo_hi!(self, self.pats[0].span.lo(), self.body.span.hi()) + } +} + +impl Spanned for ast::Arg { + fn span(&self) -> Span { + if ::items::is_named_arg(self) { + mk_sp(self.pat.span.lo(), self.ty.span.hi()) + } else { + self.ty.span + } + } +} + +impl Spanned for ast::StructField { + fn span(&self) -> Span { + span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) + } +} + +impl Spanned for ast::WherePredicate { + fn span(&self) -> Span { + match *self { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } + } +} + +impl Spanned for ast::FunctionRetTy { + fn span(&self) -> Span { + match *self { + ast::FunctionRetTy::Default(span) => span, + ast::FunctionRetTy::Ty(ref ty) => ty.span, + } + } +} + +impl Spanned for ast::TyParam { + fn span(&self) -> Span { + // Note that ty.span is the span for ty.ident, not the whole item. + let lo = if self.attrs.is_empty() { + self.span.lo() + } else { + self.attrs[0].span.lo() + }; + if let Some(ref def) = self.default { + return mk_sp(lo, def.span.hi()); + } + if self.bounds.is_empty() { + return mk_sp(lo, self.span.hi()); + } + let hi = self.bounds[self.bounds.len() - 1].span().hi(); + mk_sp(lo, hi) + } +} + +impl Spanned for ast::TyParamBound { + fn span(&self) -> Span { + match *self { + ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, + ast::TyParamBound::RegionTyParamBound(ref l) => l.span, + } + } +} + +impl Spanned for ast::LifetimeDef { + fn span(&self) -> Span { + let hi = if self.bounds.is_empty() { + self.lifetime.span.hi() + } else { + self.bounds[self.bounds.len() - 1].span.hi() + }; + mk_sp(self.lifetime.span.lo(), hi) + } +} + +impl Spanned for MacroArg { + fn span(&self) -> Span { + match *self { + MacroArg::Expr(ref expr) => expr.span(), + MacroArg::Ty(ref ty) => ty.span(), + MacroArg::Pat(ref pat) => pat.span(), + } + } +} diff --git a/src/types.rs b/src/types.rs index e6cf052d142..64f5ba93555 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,7 +17,7 @@ use syntax::codemap::{self, BytePos, Span}; use syntax::print::pprust; use syntax::symbol::keywords; -use Spanned; +use spanned::Spanned; use codemap::SpanUtils; use config::{IndentStyle, Style, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; diff --git a/src/vertical.rs b/src/vertical.rs index 13de2e22e5d..4f19cd17921 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -15,7 +15,7 @@ use std::cmp; use syntax::ast; use syntax::codemap::{BytePos, Span}; -use Spanned; +use spanned::Spanned; use codemap::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; diff --git a/src/visitor.rs b/src/visitor.rs index fa9c8e3b537..f6f46ca6188 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,7 +16,7 @@ use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; -use Spanned; +use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, CommentCodeSlices, FindUncommented}; -- cgit 1.4.1-3-g733a5 From b7510306405943c2e1188894ff1e0b300a69fbfc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 19 Sep 2017 11:40:20 +0900 Subject: Remove unnecessary wrap_str() --- src/expr.rs | 57 ++++++++++++++++++--------------------------------------- src/items.rs | 5 ++--- src/lib.rs | 1 - src/patterns.rs | 33 +++++++++++++++++++-------------- src/types.rs | 16 ++++++---------- 5 files changed, 45 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 699e8091d81..e06c928044a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -36,7 +36,7 @@ use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, outer_attributes, paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr, - trimmed_last_line_width, wrap_str}; + trimmed_last_line_width}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -76,11 +76,7 @@ pub fn format_expr( ast::LitKind::Str(_, ast::StrStyle::Cooked) => { rewrite_string_lit(context, l.span, shape) } - _ => wrap_str( - context.snippet(expr.span), - context.config.max_width(), - shape, - ), + _ => Some(context.snippet(expr.span)), }, ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); @@ -153,11 +149,7 @@ pub fn format_expr( Some(ident) => format!(" {}", ident.node), None => String::new(), }; - wrap_str( - format!("continue{}", id_str), - context.config.max_width(), - shape, - ) + Some(format!("continue{}", id_str)) } ast::ExprKind::Break(ref opt_ident, ref opt_expr) => { let id_str = match *opt_ident { @@ -168,17 +160,13 @@ pub fn format_expr( if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) } else { - wrap_str( - format!("break{}", id_str), - context.config.max_width(), - shape, - ) + Some(format!("break{}", id_str)) } } ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, "yield ", &**expr, shape) } else { - wrap_str("yield".to_string(), context.config.max_width(), shape) + Some("yield".to_string()) }, ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { rewrite_closure(capture, fn_decl, body, expr.span, context, shape) @@ -190,17 +178,10 @@ pub fn format_expr( ast::ExprKind::Mac(ref mac) => { // Failure to rewrite a marco should not imply failure to // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span), - context.config.max_width(), - shape, - ) - }) - } - ast::ExprKind::Ret(None) => { - wrap_str("return".to_owned(), context.config.max_width(), shape) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + .or_else(|| Some(context.snippet(expr.span))) } + ast::ExprKind::Ret(None) => Some("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { rewrite_unary_prefix(context, "return ", &**expr, shape) } @@ -302,16 +283,14 @@ pub fn format_expr( }; rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) } - (None, None) => wrap_str(delim.into(), context.config.max_width(), shape), + (None, None) => Some(delim.into()), } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => wrap_str( - context.snippet(expr.span), - context.config.max_width(), - shape, - ), + ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { + Some(context.snippet(expr.span)) + } ast::ExprKind::Catch(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { rw @@ -383,7 +362,11 @@ where .map(|first_line| first_line.ends_with('{')) .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { - return Some(format!("{}{}{}{}", lhs_result, infix, rhs_result, suffix)); + let one_line_width = last_line_width(&lhs_result) + infix.len() + + first_line_width(&rhs_result) + suffix.len(); + if one_line_width <= shape.width { + return Some(format!("{}{}{}{}", lhs_result, infix, rhs_result, suffix)); + } } } @@ -2665,11 +2648,7 @@ pub fn rewrite_field( prefix_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - return wrap_str( - context.snippet(field.span()), - context.config.max_width(), - shape, - ); + return Some(context.snippet(field.span())); } let name = &field.ident.node.to_string(); if field.is_shorthand { diff --git a/src/items.rs b/src/items.rs index 7f2bbe906da..9d35c83501f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -32,7 +32,7 @@ use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_a format_constness, format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, stmt_expr, - trim_newlines, trimmed_last_line_width, wrap_str}; + trim_newlines, trimmed_last_line_width}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -1361,8 +1361,7 @@ pub fn rewrite_struct_field( lhs_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - let span = context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi())); - return wrap_str(span, context.config.max_width(), shape); + return Some(context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi()))); } let type_annotation_spacing = type_annotation_spacing(context.config); diff --git a/src/lib.rs b/src/lib.rs index c78aa050984..14c50563baa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,6 @@ extern crate syntax; extern crate term; extern crate unicode_segmentation; -use std::borrow::Cow; use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, Write}; diff --git a/src/patterns.rs b/src/patterns.rs index d1b080f4a38..c58a98627ff 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -22,7 +22,7 @@ use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_sh use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use types::{rewrite_path, PathContext}; -use utils::{format_mutability, mk_sp, wrap_str}; +use utils::{format_mutability, mk_sp}; impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { @@ -51,8 +51,7 @@ impl Rewrite for Pat { None => "".to_owned(), }; - let result = format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat); - wrap_str(result, context.config.max_width(), shape) + Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) } PatKind::Wild => if 1 <= shape.width { Some("_".to_owned()) @@ -125,17 +124,13 @@ impl Rewrite for Pat { } else { format!("[{}]", pats.join(", ")) }; - wrap_str(result, context.config.max_width(), shape) + Some(result) } PatKind::Struct(ref path, ref fields, elipses) => { rewrite_struct_pat(path, fields, elipses, self.span, context, shape) } // FIXME(#819) format pattern macros. - PatKind::Mac(..) => wrap_str( - context.snippet(self.span), - context.config.max_width(), - shape, - ), + PatKind::Mac(..) => Some(context.snippet(self.span)), } } } @@ -225,11 +220,21 @@ impl Rewrite for FieldPat { if self.is_shorthand { pat } else { - wrap_str( - format!("{}: {}", self.ident.to_string(), try_opt!(pat)), - context.config.max_width(), - shape, - ) + let pat_str = try_opt!(pat); + let id_str = self.ident.to_string(); + let one_line_width = id_str.len() + 2 + pat_str.len(); + if one_line_width <= shape.width { + Some(format!("{}: {}", id_str, pat_str)) + } else { + let nested_shape = shape.block_indent(context.config.tab_spaces()); + let pat_str = try_opt!(self.pat.rewrite(context, nested_shape)); + Some(format!( + "{}:\n{}{}", + id_str, + nested_shape.indent.to_string(context.config), + pat_str, + )) + } } } } diff --git a/src/types.rs b/src/types.rs index 64f5ba93555..311192889d3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -26,7 +26,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTac SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp, wrap_str}; +use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -504,7 +504,7 @@ impl Rewrite for ast::WherePredicate { } }; - wrap_str(result, context.config.max_width(), shape) + Some(result) } } @@ -542,7 +542,7 @@ where colon, join_bounds(context, try_opt!(shape.sub_width(overhead)), &appendix) ); - wrap_str(result, context.config.max_width(), shape) + Some(result) } } @@ -565,12 +565,8 @@ impl Rewrite for ast::TyParamBound { } impl Rewrite for ast::Lifetime { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - wrap_str( - pprust::lifetime_to_string(self), - context.config.max_width(), - shape, - ) + fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { + Some(pprust::lifetime_to_string(self)) } } @@ -612,7 +608,7 @@ impl Rewrite for ast::TyParam { result.push_str(&rewrite); } - wrap_str(result, context.config.max_width(), shape) + Some(result) } } -- cgit 1.4.1-3-g733a5 From b12fecb6317949a3d51dc1339c3fa0d0f0dae57d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 19 Sep 2017 11:41:05 +0900 Subject: Use horizontal layout for a function with a single argument foo(long_arg) instead of foo( long_arg, ) --- src/expr.rs | 23 +++++++++++++++++------ src/lists.rs | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e06c928044a..dc6504de0b1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2215,12 +2215,23 @@ where _ if args.len() >= 1 => { item_vec[args.len() - 1].item = args.last() .and_then(|last_arg| last_arg.rewrite(context, shape)); - tactic = definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ); + // Use horizontal layout for a function with a single argument as long as + // everything fits in a single line. + if args.len() == 1 + && args_max_width != 0 // Vertical layout is forced. + && !item_vec[0].has_comment() + && !item_vec[0].inner_as_ref().contains('\n') + && ::lists::total_item_width(&item_vec[0]) <= one_line_width + { + tactic = DefinitiveListTactic::Horizontal; + } else { + tactic = definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ); + } } _ => (), } diff --git a/src/lists.rs b/src/lists.rs index f42e3ffe977..e499377e48a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -713,7 +713,7 @@ where .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) } -fn total_item_width(item: &ListItem) -> usize { +pub fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + item.item.as_ref().map_or(0, |str| str.len()) -- cgit 1.4.1-3-g733a5 From 2915167179161aa7b73a4416f638e779388bd95f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 19 Sep 2017 11:41:50 +0900 Subject: Cargo fmt and update tests --- src/file_lines.rs | 4 +--- tests/source/configs-fn_call_style-block-trailing-comma.rs | 2 +- tests/target/configs-fn_call_style-block-trailing-comma.rs | 1 + tests/target/enum.rs | 8 ++------ tests/target/expr-block.rs | 4 +--- tests/target/string-lit.rs | 5 ++--- 6 files changed, 8 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index 948ffac0731..a131038eb4e 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -167,9 +167,7 @@ impl FileLines { } /// `FileLines` files iterator. -pub struct Files<'a>( - Option<::std::collections::hash_map::Keys<'a, String, Vec>>, -); +pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, String, Vec>>); impl<'a> iter::Iterator for Files<'a> { type Item = &'a String; diff --git a/tests/source/configs-fn_call_style-block-trailing-comma.rs b/tests/source/configs-fn_call_style-block-trailing-comma.rs index 6f613fb10bb..ad813f6b98a 100644 --- a/tests/source/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/source/configs-fn_call_style-block-trailing-comma.rs @@ -4,5 +4,5 @@ // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo(oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); + foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); } diff --git a/tests/target/configs-fn_call_style-block-trailing-comma.rs b/tests/target/configs-fn_call_style-block-trailing-comma.rs index b6eb94eb677..4405f89f2af 100644 --- a/tests/target/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/target/configs-fn_call_style-block-trailing-comma.rs @@ -7,6 +7,7 @@ fn a() { "this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:" ); foo( + a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), ); } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 393ae5232ec..d2a39b241e1 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -170,10 +170,6 @@ enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo // #1046 pub enum Entry<'a, K: 'a, V: 'a> { - Vacant( - #[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>, - ), - Occupied( - #[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>, - ), + Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), + Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), } diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 6141ca8120e..329890e8b12 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -307,9 +307,7 @@ fn combine_block() { }; match x { - y => func( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - ), + y => func(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), _ => func( x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index fc92d379a52..e262d69b43e 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -25,9 +25,8 @@ formatting"#; filename.replace(" ", "\\"); - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = funktion( - "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", - ); + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); let unicode = "a̐éö̲\r\n"; let unicode2 = "Löwe 老虎 Léopard"; -- cgit 1.4.1-3-g733a5 From 2f819332727e2acbfcec0c170c8e57efef37fa8d Mon Sep 17 00:00:00 2001 From: Badel2 <2badel2@gmail.com> Date: Mon, 25 Sep 2017 20:51:19 +0200 Subject: Temporarily replace `RangeEnd::Included` with `_` --- src/patterns.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index c58a98627ff..91f13e20dac 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -59,21 +59,24 @@ impl Rewrite for Pat { None }, PatKind::Range(ref lhs, ref rhs, ref end_kind) => match *end_kind { - RangeEnd::Included => rewrite_pair( + RangeEnd::Excluded => rewrite_pair( &**lhs, &**rhs, "", - "...", + "..", "", context, shape, SeparatorPlace::Front, ), - RangeEnd::Excluded => rewrite_pair( + // FIXME: Change _ to RangeEnd::Included(RangeSyntax::DotDotDot) + // and add RangeEnd::Included(RangeSyntax::DotDotEq) + // once rust PR #44709 gets merged + _ => rewrite_pair( &**lhs, &**rhs, "", - "..", + "...", "", context, shape, -- cgit 1.4.1-3-g733a5 From dd0dcdf1acf3e01ad7e0452cb6193c286b1875ee Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 26 Sep 2017 11:20:47 +0900 Subject: Fix a budget bug in Arg::rewrite() --- src/items.rs | 11 ++++++----- tests/source/impls.rs | 13 +++++++++++++ tests/target/impls.rs | 13 +++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9d35c83501f..60af3f837e1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1598,11 +1598,12 @@ impl Rewrite for ast::Arg { if context.config.space_after_type_annotation_colon() { result.push_str(" "); } - let max_width = try_opt!(shape.width.checked_sub(result.len())); - let ty_str = try_opt!(self.ty.rewrite( - context, - Shape::legacy(max_width, shape.indent + result.len()), - )); + let overhead = last_line_width(&result); + let max_width = try_opt!(shape.width.checked_sub(overhead)); + let ty_str = try_opt!( + self.ty + .rewrite(context, Shape::legacy(max_width, shape.indent)) + ); result.push_str(&ty_str); } diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 17588fb9d35..ca8e486646a 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -139,3 +139,16 @@ pub trait Number: Copy + Eq + Not + Shl + pub trait SomeTrait : Clone + Eq + PartialEq + Ord + PartialOrd + Default + Hash + Debug + Display + Write + Read + FromStr { // comment } + +// #1995 +impl Foo { + fn f( + S { + aaaaaaaaaa: aaaaaaaaaa, + bbbbbbbbbb: bbbbbbbbbb, + cccccccccc: cccccccccc, + }: S + ) -> u32{ + 1 + } +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 216c9d5193d..e0070adcad4 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -202,3 +202,16 @@ pub trait SomeTrait + FromStr { // comment } + +// #1995 +impl Foo { + fn f( + S { + aaaaaaaaaa: aaaaaaaaaa, + bbbbbbbbbb: bbbbbbbbbb, + cccccccccc: cccccccccc, + }: S, + ) -> u32 { + 1 + } +} -- cgit 1.4.1-3-g733a5 From 28860000fe57818b2fddfea9cf18bdcd33d963d1 Mon Sep 17 00:00:00 2001 From: Badel2 <2badel2@gmail.com> Date: Wed, 27 Sep 2017 22:19:10 +0200 Subject: Support `..=` syntax --- src/expr.rs | 2 +- src/patterns.rs | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dc6504de0b1..9b59e0cbd78 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -232,7 +232,7 @@ pub fn format_expr( ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { ast::RangeLimits::HalfOpen => "..", - ast::RangeLimits::Closed => "...", + ast::RangeLimits::Closed => "..=", }; fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { diff --git a/src/patterns.rs b/src/patterns.rs index 91f13e20dac..b05889c29e9 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd}; +use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; use syntax::codemap::{self, BytePos, Span}; use syntax::ptr; @@ -58,31 +58,23 @@ impl Rewrite for Pat { } else { None }, - PatKind::Range(ref lhs, ref rhs, ref end_kind) => match *end_kind { - RangeEnd::Excluded => rewrite_pair( - &**lhs, - &**rhs, - "", - "..", - "", - context, - shape, - SeparatorPlace::Front, - ), - // FIXME: Change _ to RangeEnd::Included(RangeSyntax::DotDotDot) - // and add RangeEnd::Included(RangeSyntax::DotDotEq) - // once rust PR #44709 gets merged - _ => rewrite_pair( + PatKind::Range(ref lhs, ref rhs, ref end_kind) => { + let infix = match *end_kind { + RangeEnd::Included(RangeSyntax::DotDotDot) => "...", + RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", + RangeEnd::Excluded => "..", + }; + rewrite_pair( &**lhs, &**rhs, "", - "...", + infix, "", context, shape, SeparatorPlace::Front, - ), - }, + ) + } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, shape) -- cgit 1.4.1-3-g733a5 From 436a083fceae8e0f71605aa07dce047a316576c6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 28 Sep 2017 16:33:30 +0900 Subject: Change return type of rewrite_call_inner() to Option --- src/expr.rs | 27 +++++++++++---------------- src/items.rs | 20 +++++++++----------- src/macros.rs | 5 ++--- src/patterns.rs | 2 +- 4 files changed, 23 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dc6504de0b1..4aeeec4083b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cmp::{min, Ordering}; +use std::cmp::min; use std::borrow::Cow; use std::fmt::Write; use std::iter::{repeat, ExactSizeIterator}; @@ -2033,7 +2033,7 @@ pub fn rewrite_call( shape, context.config.fn_call_width(), force_trailing_comma, - ).ok() + ) } pub fn rewrite_call_inner<'a, T>( @@ -2044,7 +2044,7 @@ pub fn rewrite_call_inner<'a, T>( shape: Shape, args_max_width: usize, force_trailing_comma: bool, -) -> Result +) -> Option where T: Rewrite + Spanned + ToExpr + 'a, { @@ -2055,22 +2055,19 @@ where 1 }; let used_width = extra_offset(callee_str, shape); - let one_line_width = shape - .width - .checked_sub(used_width + 2 * paren_overhead) - .ok_or(Ordering::Greater)?; + let one_line_width = try_opt!(shape.width.checked_sub(used_width + 2 * paren_overhead)); - let nested_shape = shape_from_fn_call_style( + let nested_shape = try_opt!(shape_from_fn_call_style( context, shape, used_width + 2 * paren_overhead, used_width + paren_overhead, - ).ok_or(Ordering::Greater)?; + )); let span_lo = context.codemap.span_after(span, "("); let args_span = mk_sp(span_lo, span.hi()); - let (extendable, list_str) = rewrite_call_args( + let (extendable, list_str) = try_opt!(rewrite_call_args( context, args, args_span, @@ -2078,7 +2075,7 @@ where one_line_width, args_max_width, force_trailing_comma, - ).ok_or(Ordering::Less)?; + )); if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { let mut new_context = context.clone(); @@ -2094,10 +2091,8 @@ where ); } - let args_shape = shape - .sub_width(last_line_width(callee_str)) - .ok_or(Ordering::Less)?; - Ok(format!( + let args_shape = try_opt!(shape.sub_width(last_line_width(callee_str))); + Some(format!( "{}{}", callee_str, wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) @@ -2805,7 +2800,7 @@ where shape, context.config.fn_call_width(), force_trailing_comma, - ).ok() + ) } else { rewrite_tuple_in_visual_indent_style(context, items, span, shape) } diff --git a/src/items.rs b/src/items.rs index 9d35c83501f..c546c2ca94b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1211,17 +1211,15 @@ fn format_tuple_struct( result.push(')'); } else { // 3 = `();` - let body = try_opt!( - rewrite_call_inner( - context, - "", - &fields.iter().map(|field| field).collect::>()[..], - span, - Shape::legacy(context.budget(last_line_width(&result) + 3), offset), - context.config.fn_call_width(), - false, - ).ok() - ); + let body = try_opt!(rewrite_call_inner( + context, + "", + &fields.iter().map(|field| field).collect::>()[..], + span, + Shape::legacy(context.budget(last_line_width(&result) + 3), offset), + context.config.fn_call_width(), + false, + )); result.push_str(&body); } diff --git a/src/macros.rs b/src/macros.rs index 5b52567087e..4eaf97dd254 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -202,7 +202,7 @@ pub fn rewrite_macro( MacroStyle::Parens => { // Format macro invocation as function call, forcing no trailing // comma because not all macros support them. - let rw = rewrite_call_inner( + rewrite_call_inner( context, ¯o_name, &arg_vec.iter().map(|e| &*e).collect::>()[..], @@ -210,8 +210,7 @@ pub fn rewrite_macro( shape, context.config.fn_call_width(), trailing_comma, - ); - rw.ok().map(|rw| match position { + ).map(|rw| match position { MacroPosition::Item => format!("{};", rw), _ => rw, }) diff --git a/src/patterns.rs b/src/patterns.rs index c58a98627ff..7d2f81dc229 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -351,7 +351,7 @@ fn rewrite_tuple_pat( shape, shape.width, add_comma, - ).ok() + ) } fn count_wildcard_suffix_len( -- cgit 1.4.1-3-g733a5 From ee2b3b15290b468167db63e341169a7cf752b68c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 28 Sep 2017 20:12:04 +0900 Subject: Put the opening brace of fn body on the next line if it exceeds max width --- src/items.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9d35c83501f..b054e1d1dd3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -250,11 +250,12 @@ impl<'a> FmtVisitor<'a> { true, )); - if force_newline_brace { + if self.config.fn_brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace { newline_brace = true; - } else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine - && !result.contains('\n') - { + } else if last_line_width(&result) + 2 > self.shape().width { + // 2 = ` {` + newline_brace = true; + } else if !result.contains('\n') { newline_brace = false; } -- cgit 1.4.1-3-g733a5 From 7d448c2b26bd26825d8c83315992cc9175e1d09c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 29 Sep 2017 12:45:42 +0900 Subject: Implement FnSig type --- src/items.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9d35c83501f..805be05c44b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,6 +15,7 @@ use std::cmp::min; use syntax::{abi, ast, ptr, symbol}; use syntax::ast::ImplItem; use syntax::codemap::{BytePos, Span}; +use syntax::visit; use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; @@ -159,6 +160,74 @@ enum BodyElement<'a> { ForeignItem(&'a ast::ForeignItem), } +/// Represents a fn's signature. +pub struct FnSig<'a> { + decl: &'a ast::FnDecl, + generics: &'a ast::Generics, + abi: abi::Abi, + constness: ast::Constness, + defaultness: ast::Defaultness, + unsafety: ast::Unsafety, + visibility: ast::Visibility, +} + +impl<'a> FnSig<'a> { + pub fn new( + decl: &'a ast::FnDecl, + generics: &'a ast::Generics, + vis: ast::Visibility, + ) -> FnSig<'a> { + FnSig { + decl: decl, + generics: generics, + abi: abi::Abi::Rust, + constness: ast::Constness::NotConst, + defaultness: ast::Defaultness::Final, + unsafety: ast::Unsafety::Normal, + visibility: vis, + } + } + + pub fn from_method_sig(method_sig: &'a ast::MethodSig) -> FnSig { + FnSig { + unsafety: method_sig.unsafety, + constness: method_sig.constness.node, + defaultness: ast::Defaultness::Final, + abi: method_sig.abi, + decl: &*method_sig.decl, + generics: &method_sig.generics, + visibility: ast::Visibility::Inherited, + } + } + + pub fn from_fn_kind( + fn_kind: &'a visit::FnKind, + decl: &'a ast::FnDecl, + defualtness: ast::Defaultness, + ) -> FnSig<'a> { + match *fn_kind { + visit::FnKind::ItemFn(_, generics, unsafety, constness, abi, visibility, _) => FnSig { + decl: decl, + generics: generics, + abi: abi, + constness: constness.node, + defaultness: defualtness, + unsafety: unsafety, + visibility: visibility.clone(), + }, + visit::FnKind::Method(_, ref method_sig, vis, _) => { + let mut fn_sig = FnSig::from_method_sig(method_sig); + fn_sig.defaultness = defualtness; + if let Some(vis) = vis { + fn_sig.visibility = vis.clone(); + } + fn_sig + } + _ => unreachable!(), + } + } +} + impl<'a> FmtVisitor<'a> { fn format_item(&mut self, item: Item) { self.buffer.push_str(&item.abi); -- cgit 1.4.1-3-g733a5 From 2e6825cc8cf5447b7b13423a56a723d80c6116d9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 29 Sep 2017 12:49:39 +0900 Subject: Use FnSig in rewrite_fn() and rewrite_fn_base() --- src/items.rs | 65 ++++++++++++++++------------------------------------------ src/visitor.rs | 22 +++++--------------- 2 files changed, 23 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 805be05c44b..f74ae83cdf4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -285,13 +285,7 @@ impl<'a> FmtVisitor<'a> { &mut self, indent: Indent, ident: ast::Ident, - fd: &ast::FnDecl, - generics: &ast::Generics, - unsafety: ast::Unsafety, - constness: ast::Constness, - defaultness: ast::Defaultness, - abi: abi::Abi, - vis: &ast::Visibility, + fn_sig: &FnSig, span: Span, block: &ast::Block, ) -> Option { @@ -300,19 +294,14 @@ impl<'a> FmtVisitor<'a> { let block_snippet = self.snippet(mk_sp(block.span.lo(), block.span.hi())); let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() || !context.config.fn_empty_single_line(); - let mut newline_brace = newline_for_brace(self.config, &generics.where_clause, has_body); + let mut newline_brace = + newline_for_brace(self.config, &fn_sig.generics.where_clause, has_body); let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base( &context, indent, ident, - fd, - generics, - unsafety, - constness, - defaultness, - abi, - vis, + fn_sig, span, newline_brace, has_body, @@ -357,13 +346,7 @@ impl<'a> FmtVisitor<'a> { &context, indent, ident, - &sig.decl, - &sig.generics, - sig.unsafety, - sig.constness.node, - ast::Defaultness::Final, - sig.abi, - &ast::Visibility::Inherited, + &FnSig::from_method_sig(sig), span, false, false, @@ -1765,13 +1748,7 @@ fn rewrite_fn_base( context: &RewriteContext, indent: Indent, ident: ast::Ident, - fd: &ast::FnDecl, - generics: &ast::Generics, - unsafety: ast::Unsafety, - constness: ast::Constness, - defaultness: ast::Defaultness, - abi: abi::Abi, - vis: &ast::Visibility, + fn_sig: &FnSig, span: Span, newline_brace: bool, has_body: bool, @@ -1779,16 +1756,16 @@ fn rewrite_fn_base( ) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; - let where_clause = &generics.where_clause; + let where_clause = &fn_sig.generics.where_clause; let mut result = String::with_capacity(1024); // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(vis)); - result.push_str(format_defaultness(defaultness)); - result.push_str(format_constness(constness)); - result.push_str(format_unsafety(unsafety)); - if abi != abi::Abi::Rust { - result.push_str(&format_abi(abi, context.config.force_explicit_abi())); + result.push_str(&*format_visibility(&fn_sig.visibility)); + result.push_str(format_defaultness(fn_sig.defaultness)); + result.push_str(format_constness(fn_sig.constness)); + result.push_str(format_unsafety(fn_sig.unsafety)); + if fn_sig.abi != abi::Abi::Rust { + result.push_str(&format_abi(fn_sig.abi, context.config.force_explicit_abi())); } // fn foo @@ -1810,8 +1787,9 @@ fn rewrite_fn_base( indent: indent, offset: used_width, }; + let fd = fn_sig.decl; let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); + let generics_str = try_opt!(rewrite_generics(context, fn_sig.generics, shape, g_span)); result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -1873,7 +1851,8 @@ fn rewrite_fn_base( } // A conservative estimation, to goal is to be over all parens in generics - let args_start = generics + let args_start = fn_sig + .generics .ty_params .last() .map_or(span.lo(), |tp| end_typaram(tp)); @@ -2826,15 +2805,7 @@ impl Rewrite for ast::ForeignItem { context, shape.indent, self.ident, - fn_decl, - generics, - ast::Unsafety::Normal, - ast::Constness::NotConst, - ast::Defaultness::Final, - // These are not actually rust functions, - // but we format them as such. - abi::Abi::Rust, - &self.vis, + &FnSig::new(fn_decl, generics, self.vis.clone()), span, false, false, diff --git a/src/visitor.rs b/src/visitor.rs index f6f46ca6188..b4657f2e0d9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -24,7 +24,7 @@ use comment::rewrite_comment; use config::{BraceStyle, Config}; use items::{format_impl, format_struct, format_struct_struct, format_trait, rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, - rewrite_type_alias}; + rewrite_type_alias, FnSig}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; @@ -237,34 +237,22 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent; let block; let rewrite = match fk { - visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => { + visit::FnKind::ItemFn(ident, _, _, _, _, _, b) => { block = b; self.rewrite_fn( indent, ident, - fd, - generics, - unsafety, - constness.node, - defaultness, - abi, - vis, + &FnSig::from_fn_kind(&fk, fd, defaultness), mk_sp(s.lo(), b.span.lo()), b, ) } - visit::FnKind::Method(ident, sig, vis, b) => { + visit::FnKind::Method(ident, _, _, b) => { block = b; self.rewrite_fn( indent, ident, - fd, - &sig.generics, - sig.unsafety, - sig.constness.node, - defaultness, - sig.abi, - vis.unwrap_or(&ast::Visibility::Inherited), + &FnSig::from_fn_kind(&fk, fd, defaultness), mk_sp(s.lo(), b.span.lo()), b, ) -- cgit 1.4.1-3-g733a5 From d8fc9ec05e80850f46090dfcd186d457c66fba2d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 29 Sep 2017 12:50:35 +0900 Subject: Remove has_braces from argument --- src/items.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f74ae83cdf4..98f0dc4430e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -304,7 +304,6 @@ impl<'a> FmtVisitor<'a> { fn_sig, span, newline_brace, - has_body, true, )); @@ -350,7 +349,6 @@ impl<'a> FmtVisitor<'a> { span, false, false, - false, )); // Re-attach semicolon @@ -1752,7 +1750,6 @@ fn rewrite_fn_base( span: Span, newline_brace: bool, has_body: bool, - has_braces: bool, ) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; @@ -1773,7 +1770,7 @@ fn rewrite_fn_base( result.push_str(&ident.to_string()); // Generics. - let overhead = if has_braces && !newline_brace { + let overhead = if has_body && !newline_brace { // 4 = `() {` 4 } else { @@ -1814,7 +1811,7 @@ fn rewrite_fn_base( indent, ret_str_len, newline_brace, - has_braces, + has_body, multi_line_ret_str, )); @@ -2035,7 +2032,7 @@ fn rewrite_fn_base( } } - let option = WhereClauseOption::new(!has_braces, put_args_in_block && ret_str.is_empty()); + let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); let where_clause_str = try_opt!(rewrite_where_clause( context, where_clause, @@ -2809,7 +2806,6 @@ impl Rewrite for ast::ForeignItem { span, false, false, - false, ).map(|(s, _)| format!("{};", s)) } ast::ForeignItemKind::Static(ref ty, is_mutable) => { -- cgit 1.4.1-3-g733a5 From 9537437e524dcadd1da79bb833d4ed499eaa49d2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 29 Sep 2017 12:51:06 +0900 Subject: Use is_empty_block() --- src/items.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 98f0dc4430e..a22d1ec292b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -291,9 +291,8 @@ impl<'a> FmtVisitor<'a> { ) -> Option { let context = self.get_context(); - let block_snippet = self.snippet(mk_sp(block.span.lo(), block.span.hi())); - let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() - || !context.config.fn_empty_single_line(); + let has_body = + !is_empty_block(block, self.codemap) || !context.config.fn_empty_single_line(); let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause, has_body); -- cgit 1.4.1-3-g733a5 From 62e38860b90238f901ce6d5ea7ce7ca0108b51e5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 29 Sep 2017 15:08:48 +0900 Subject: Handle 'extern "Rust"' in format_abi() --- src/items.rs | 10 +++------- src/types.rs | 14 ++++++-------- src/utils.rs | 6 ++++-- 3 files changed, 13 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a22d1ec292b..f32ea1c803f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,6 +10,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. +use std::borrow::Cow; use std::cmp::min; use syntax::{abi, ast, ptr, symbol}; @@ -126,7 +127,7 @@ impl Rewrite for ast::Local { #[allow(dead_code)] struct Item<'a> { keyword: &'static str, - abi: String, + abi: Cow<'static, str>, vis: Option<&'a ast::Visibility>, body: Vec>, span: Span, @@ -134,14 +135,9 @@ struct Item<'a> { impl<'a> Item<'a> { fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { - let abi = if fm.abi == abi::Abi::C && !config.force_explicit_abi() { - "extern".into() - } else { - format!("extern {}", fm.abi) - }; Item { keyword: "", - abi: abi, + abi: format_abi(fm.abi, config.force_explicit_abi(), true), vis: None, body: fm.items .iter() diff --git a/src/types.rs b/src/types.rs index 311192889d3..1d6c80fb939 100644 --- a/src/types.rs +++ b/src/types.rs @@ -11,7 +11,6 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; -use syntax::abi; use syntax::ast::{self, FunctionRetTy, Mutability}; use syntax::codemap::{self, BytePos, Span}; use syntax::print::pprust; @@ -26,7 +25,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTac SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use utils::{colon_spaces, extra_offset, format_mutability, last_line_width, mk_sp}; +use utils::{colon_spaces, extra_offset, format_abi, format_mutability, last_line_width, mk_sp}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -792,12 +791,11 @@ fn rewrite_bare_fn( result.push_str(::utils::format_unsafety(bare_fn.unsafety)); - if bare_fn.abi != abi::Abi::Rust { - result.push_str(&::utils::format_abi( - bare_fn.abi, - context.config.force_explicit_abi(), - )); - } + result.push_str(&format_abi( + bare_fn.abi, + context.config.force_explicit_abi(), + false, + )); result.push_str("fn"); diff --git a/src/utils.rs b/src/utils.rs index 3c97044f5c4..a01e22aae29 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -88,8 +88,10 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } #[inline] -pub fn format_abi(abi: abi::Abi, explicit_abi: bool) -> Cow<'static, str> { - if abi == abi::Abi::C && !explicit_abi { +pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { + if abi == abi::Abi::Rust && !is_mod { + Cow::from("") + } else if abi == abi::Abi::C && !explicit_abi { Cow::from("extern ") } else { Cow::from(format!("extern {} ", abi)) -- cgit 1.4.1-3-g733a5 From 921e0c22ab0999e963fef21a0f2e162a9c809542 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 29 Sep 2017 15:09:13 +0900 Subject: Factor out FnSig::to_str() --- src/items.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f32ea1c803f..7e3d4442874 100644 --- a/src/items.rs +++ b/src/items.rs @@ -222,12 +222,26 @@ impl<'a> FnSig<'a> { _ => unreachable!(), } } + + fn to_str(&self, context: &RewriteContext) -> String { + let mut result = String::with_capacity(128); + // Vis defaultness constness unsafety abi. + result.push_str(&*format_visibility(&self.visibility)); + result.push_str(format_defaultness(self.defaultness)); + result.push_str(format_constness(self.constness)); + result.push_str(format_unsafety(self.unsafety)); + result.push_str(&format_abi( + self.abi, + context.config.force_explicit_abi(), + false, + )); + result + } } impl<'a> FmtVisitor<'a> { fn format_item(&mut self, item: Item) { self.buffer.push_str(&item.abi); - self.buffer.push_str(" "); let snippet = self.snippet(item.span); let brace_pos = snippet.find_uncommented("{").unwrap(); @@ -1751,14 +1765,7 @@ fn rewrite_fn_base( let where_clause = &fn_sig.generics.where_clause; let mut result = String::with_capacity(1024); - // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(&fn_sig.visibility)); - result.push_str(format_defaultness(fn_sig.defaultness)); - result.push_str(format_constness(fn_sig.constness)); - result.push_str(format_unsafety(fn_sig.unsafety)); - if fn_sig.abi != abi::Abi::Rust { - result.push_str(&format_abi(fn_sig.abi, context.config.force_explicit_abi())); - } + result.push_str(&fn_sig.to_str(context)); // fn foo result.push_str("fn "); -- cgit 1.4.1-3-g733a5 From 48ff9df8a4ea8c4e4820d811b3c9db3c4f78c5fd Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 28 Sep 2017 10:47:01 +0900 Subject: Add rewrite_literal() --- src/expr.rs | 14 ++++++++------ src/visitor.rs | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9b59e0cbd78..c240ecdda53 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -72,12 +72,7 @@ pub fn format_expr( shape, false, ), - ast::ExprKind::Lit(ref l) => match l.node { - ast::LitKind::Str(_, ast::StrStyle::Cooked) => { - rewrite_string_lit(context, l.span, shape) - } - _ => Some(context.snippet(expr.span)), - }, + ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); let callee_str = try_opt!(callee.rewrite(context, shape)); @@ -1938,6 +1933,13 @@ fn rewrite_pat_expr( .map(|expr_rw| format!("\n{}{}", nested_indent_str, expr_rw)) } +pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { + match l.node { + ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), + _ => Some(context.snippet(l.span)), + } +} + fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { let string_lit = context.snippet(span); diff --git a/src/visitor.rs b/src/visitor.rs index f6f46ca6188..36917c2f797 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,6 +16,7 @@ use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; +use expr::rewrite_literal; use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, CommentCodeSlices, @@ -810,7 +811,7 @@ impl Rewrite for ast::NestedMetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), - ast::NestedMetaItemKind::Literal(..) => Some(context.snippet(self.span)), + ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), } } } -- cgit 1.4.1-3-g733a5 From b74a0f960a6cecec889d8fff46921e621d5b81f6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 1 Oct 2017 19:39:00 +0900 Subject: Implement StringFormat::new() --- src/expr.rs | 12 +----------- src/string.rs | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c240ecdda53..c7a71cde69b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1976,20 +1976,10 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt return Some(string_lit); } - let fmt = StringFormat { - opener: "\"", - closer: "\"", - line_start: " ", - line_end: "\\", - shape: shape, - trim_end: false, - config: context.config, - }; - // Remove the quote characters. let str_lit = &string_lit[1..string_lit.len() - 1]; - rewrite_string(str_lit, &fmt) + rewrite_string(str_lit, &StringFormat::new(shape, context.config)) } fn string_requires_rewrite( diff --git a/src/string.rs b/src/string.rs index 8090926522d..efec7ff2377 100644 --- a/src/string.rs +++ b/src/string.rs @@ -29,6 +29,20 @@ pub struct StringFormat<'a> { pub config: &'a Config, } +impl<'a> StringFormat<'a> { + pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { + StringFormat { + opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + shape: shape, + trim_end: false, + config: config, + } + } +} + // FIXME: simplify this! pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { // Strip line breaks. @@ -133,16 +147,7 @@ mod test { #[test] fn issue343() { let config = Default::default(); - let fmt = StringFormat { - opener: "\"", - closer: "\"", - line_start: " ", - line_end: "\\", - shape: Shape::legacy(2, Indent::empty()), - trim_end: false, - config: &config, - }; - + let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); rewrite_string("eq_", &fmt); } } -- cgit 1.4.1-3-g733a5 From 74402bbdef10b0d654cdab11e9f39eaf5c7ba69d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 1 Oct 2017 19:39:41 +0900 Subject: Move logic for doc comments to ast::Attribute::rewrite() --- src/visitor.rs | 60 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 36917c2f797..bd799b5ce0d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -822,10 +822,11 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::Word => String::from(&*self.name.as_str()), ast::MetaItemKind::List(ref list) => { let name = self.name.as_str(); - // 3 = `#[` and `(`, 2 = `]` and `)` + // 1 = `(`, 2 = `]` and `)` let item_shape = try_opt!( shape - .shrink_left(name.len() + 3) + .visual_indent(0) + .shrink_left(name.len() + 1) .and_then(|s| s.sub_width(2)) ); let items = itemize_list( @@ -854,18 +855,10 @@ impl Rewrite for ast::MetaItem { } ast::MetaItemKind::NameValue(ref literal) => { let name = self.name.as_str(); - let value = context.snippet(literal.span); - if &*name == "doc" && contains_comment(&value) { - let doc_shape = Shape { - width: cmp::min(shape.width, context.config.comment_width()) - .checked_sub(shape.indent.width()) - .unwrap_or(0), - ..shape - }; - try_opt!(rewrite_comment(&value, false, doc_shape, context.config)) - } else { - format!("{} = {}", name, value) - } + // 3 = ` = ` + let lit_shape = try_opt!(shape.shrink_left(name.len() + 3)); + let value = try_opt!(rewrite_literal(context, literal, lit_shape)); + format!("{} = {}", name, value) } }) } @@ -873,22 +866,29 @@ impl Rewrite for ast::MetaItem { impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - try_opt!(self.meta()) - .rewrite(context, shape) - .map(|rw| if self.is_sugared_doc { - rw - } else { - let original = context.snippet(self.span); - let prefix = match self.style { - ast::AttrStyle::Inner => "#!", - ast::AttrStyle::Outer => "#", - }; - if contains_comment(&original) { - original - } else { - format!("{}[{}]", prefix, rw) - } - }) + let prefix = match self.style { + ast::AttrStyle::Inner => "#!", + ast::AttrStyle::Outer => "#", + }; + let snippet = context.snippet(self.span); + if self.is_sugared_doc { + let doc_shape = Shape { + width: cmp::min(shape.width, context.config.comment_width()) + .checked_sub(shape.indent.width()) + .unwrap_or(0), + ..shape + }; + rewrite_comment(&snippet, false, doc_shape, context.config) + } else { + if contains_comment(&snippet) { + return Some(snippet); + } + // 1 = `[` + let shape = try_opt!(shape.offset_left(prefix.len() + 1)); + try_opt!(self.meta()) + .rewrite(context, shape) + .map(|rw| format!("{}[{}]", prefix, rw)) + } } } -- cgit 1.4.1-3-g733a5 From 1771dfca08538a501ec2a2be438f09ff76a25c7b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 1 Oct 2017 21:20:15 +0900 Subject: Break after '=' if a single line rhs exceeds max width --- src/expr.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9b59e0cbd78..de2166bddbe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2895,7 +2895,7 @@ pub fn rewrite_assign_rhs>( let rhs = try_opt!(choose_rhs( context, ex, - shape, + orig_shape, ex.rewrite(context, orig_shape) )); Some(lhs + &rhs) @@ -2908,7 +2908,9 @@ fn choose_rhs( orig_rhs: Option, ) -> Option { match orig_rhs { - Some(ref new_str) if !new_str.contains('\n') => Some(format!(" {}", new_str)), + Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { + Some(format!(" {}", new_str)) + } _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. -- cgit 1.4.1-3-g733a5 From 1b84623aac1221d10d251ac82370cf4393157613 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 2 Oct 2017 00:00:12 +0900 Subject: Use offset_left() --- src/types.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 311192889d3..6f6e02f4d92 100644 --- a/src/types.rs +++ b/src/types.rs @@ -439,7 +439,7 @@ impl Rewrite for ast::WherePredicate { // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let ty_shape = try_opt!(shape.block_left(used_width)); + let ty_shape = try_opt!(shape.offset_left(used_width)); let bounds: Vec<_> = try_opt!( bounds .iter() @@ -553,10 +553,9 @@ impl Rewrite for ast::TyParamBound { tref.rewrite(context, shape) } ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { - let budget = try_opt!(shape.width.checked_sub(1)); Some(format!( "?{}", - try_opt!(tref.rewrite(context, Shape::legacy(budget, shape.indent + 1))) + try_opt!(tref.rewrite(context, try_opt!(shape.offset_left(1)))) )) } ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), @@ -624,11 +623,10 @@ impl Rewrite for ast::PolyTraitRef { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; - let max_path_width = try_opt!(shape.width.checked_sub(extra_offset)); - let path_str = try_opt!(self.trait_ref.rewrite( - context, - Shape::legacy(max_path_width, shape.indent + extra_offset), - )); + let path_str = try_opt!( + self.trait_ref + .rewrite(context, try_opt!(shape.offset_left(extra_offset))) + ); Some( if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { -- cgit 1.4.1-3-g733a5 From eebad40932d6ea1fbdd4bd07212079a229abadb5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 2 Oct 2017 00:00:48 +0900 Subject: Use a correct budget for where predicate --- src/items.rs | 6 ++++-- src/types.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8fdfdb4110c..8dbc5e8882e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2484,7 +2484,9 @@ fn rewrite_where_clause_rfc_style( "\n".to_owned() + &block_shape.indent.to_string(context.config) }; - let clause_shape = block_shape.block_indent(context.config.tab_spaces()); + let clause_shape = try_opt!(block_shape.block_left(context.config.tab_spaces())); + // 1 = `,` + let clause_shape = try_opt!(clause_shape.sub_width(1)); // each clause on one line, trailing comma (except if suppress_comma) let span_start = where_clause.predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the @@ -2498,7 +2500,7 @@ fn rewrite_where_clause_rfc_style( terminator, |pred| pred.span().lo(), |pred| pred.span().hi(), - |pred| pred.rewrite(context, block_shape), + |pred| pred.rewrite(context, clause_shape), span_start, span_end, false, diff --git a/src/types.rs b/src/types.rs index 6f6e02f4d92..2d8b6285f74 100644 --- a/src/types.rs +++ b/src/types.rs @@ -463,7 +463,7 @@ impl Rewrite for ast::WherePredicate { let used_width = type_str.len() + colon.len(); let ty_shape = match context.config.where_style() { Style::Legacy => try_opt!(shape.block_left(used_width)), - Style::Rfc => shape.block_indent(context.config.tab_spaces()), + Style::Rfc => shape, }; let bounds: Vec<_> = try_opt!( bounds -- cgit 1.4.1-3-g733a5 From 25d2671c5569e0b1cf833e1b53b53c338281928a Mon Sep 17 00:00:00 2001 From: Shohei Wada Date: Thu, 5 Oct 2017 00:23:17 +0900 Subject: Fix broken tests under CRLF env. --- src/items.rs | 6 +++--- src/lists.rs | 4 ++-- src/utils.rs | 4 ++++ 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8fdfdb4110c..a1e5fe4abda 100644 --- a/src/items.rs +++ b/src/items.rs @@ -31,8 +31,8 @@ use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, - last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, stmt_expr, - trim_newlines, trimmed_last_line_width}; + last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, + stmt_expr, trim_newlines, trimmed_last_line_width}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -1940,7 +1940,7 @@ fn rewrite_fn_base( // Try to preserve the layout of the original snippet. let original_starts_with_newline = snippet .find(|c| c != ' ') - .map_or(false, |i| snippet[i..].starts_with('\n')); + .map_or(false, |i| starts_with_newline(&snippet[i..])); let original_ends_with_newline = snippet .rfind(|c| c != ' ') .map_or(false, |i| snippet[i..].ends_with('\n')); diff --git a/src/lists.rs b/src/lists.rs index e499377e48a..a26165d48a0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -17,7 +17,7 @@ use comment::{find_comment_end, rewrite_comment, FindUncommented}; use config::{Config, IndentStyle}; use rewrite::RewriteContext; use shape::{Indent, Shape}; -use utils::{first_line_width, last_line_width, mk_sp}; +use utils::{first_line_width, last_line_width, mk_sp, starts_with_newline}; /// Formatting tactic for lists. This will be cast down to a /// `DefinitiveListTactic` depending on the number and length of the items and @@ -425,7 +425,7 @@ where let mut formatted_comment = try_opt!(rewrite_post_comment(&mut item_max_width)); - if !formatted_comment.starts_with('\n') { + if !starts_with_newline(&formatted_comment) { let mut comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); if first_line_width(&formatted_comment) + last_line_width(&result) diff --git a/src/utils.rs b/src/utils.rs index 3c97044f5c4..02c677704ef 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -493,3 +493,7 @@ pub fn isatty() -> bool { kernel32::GetConsoleMode(handle, &mut out) != 0 } } + +pub fn starts_with_newline(s: &str) -> bool { + s.starts_with('\n') || s.starts_with("\r\n") +} -- cgit 1.4.1-3-g733a5 From 9e963b87fced64c0df49f263da2e577153480944 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 5 Oct 2017 16:17:04 +0900 Subject: Add InString field to FullCodeCharKind --- src/comment.rs | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index f74684e5862..a236c2699a6 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -464,7 +464,7 @@ impl FindUncommented for str { return Some(i - pat.len()); } Some(c) => match kind { - FullCodeCharKind::Normal if b == c => {} + FullCodeCharKind::Normal | FullCodeCharKind::InString if b == c => {} _ => { needle_iter = pat.chars(); } @@ -487,7 +487,7 @@ impl FindUncommented for str { pub fn find_comment_end(s: &str) -> Option { let mut iter = CharClasses::new(s.char_indices()); for (kind, (i, _c)) in &mut iter { - if kind == FullCodeCharKind::Normal { + if kind == FullCodeCharKind::Normal || kind == FullCodeCharKind::InString { return Some(i); } } @@ -568,15 +568,17 @@ enum FullCodeCharKind { InComment, /// Last character of a comment, '\n' for a line comment, '/' for a block comment. EndComment, + /// Inside a string. + InString, } impl FullCodeCharKind { fn is_comment(&self) -> bool { match *self { - FullCodeCharKind::Normal => false, FullCodeCharKind::StartComment | FullCodeCharKind::InComment | FullCodeCharKind::EndComment => true, + _ => false, } } @@ -612,13 +614,23 @@ where fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { let item = try_opt!(self.base.next()); let chr = item.get_char(); + let mut char_kind = FullCodeCharKind::Normal; self.status = match self.status { CharClassesStatus::LitString => match chr { '"' => CharClassesStatus::Normal, - '\\' => CharClassesStatus::LitStringEscape, - _ => CharClassesStatus::LitString, + '\\' => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitStringEscape + } + _ => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } }, - CharClassesStatus::LitStringEscape => CharClassesStatus::LitString, + CharClassesStatus::LitStringEscape => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } CharClassesStatus::LitChar => match chr { '\\' => CharClassesStatus::LitCharEscape, '\'' => CharClassesStatus::Normal, @@ -626,7 +638,10 @@ where }, CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, CharClassesStatus::Normal => match chr { - '"' => CharClassesStatus::LitString, + '"' => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } '\'' => CharClassesStatus::LitChar, '/' => match self.base.peek() { Some(next) if next.get_char() == '*' => { @@ -680,7 +695,7 @@ where } }, }; - Some((FullCodeCharKind::Normal, item)) + Some((char_kind, item)) } } @@ -707,9 +722,12 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { fn next(&mut self) -> Option { let (kind, (start_idx, _)) = try_opt!(self.iter.next()); match kind { - FullCodeCharKind::Normal => { + FullCodeCharKind::Normal | FullCodeCharKind::InString => { // Consume all the Normal code - while let Some(&(FullCodeCharKind::Normal, (_, _))) = self.iter.peek() { + while let Some(&(char_kind, _)) = self.iter.peek() { + if char_kind.is_comment() { + break; + } let _ = self.iter.next(); } } @@ -1032,7 +1050,7 @@ mod test { fn uncommented(text: &str) -> String { CharClasses::new(text.chars()) .filter_map(|(s, c)| match s { - FullCodeCharKind::Normal => Some(c), + FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), _ => None, }) .collect() -- cgit 1.4.1-3-g733a5 From 106625bc5c43da24673c84c2e85e082e3f591a15 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 5 Oct 2017 16:17:59 +0900 Subject: Remove trailing whitespaces in macro def --- src/comment.rs | 29 +++++++++++++++++++++++++++++ src/visitor.rs | 6 +++--- 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index a236c2699a6..3c863086a36 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -505,6 +505,35 @@ pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) } +/// Remove trailing spaces from the specified snippet. We do not remove spaces +/// inside strings or comments. +pub fn remove_trailing_white_spaces(text: &str) -> String { + let mut buffer = String::with_capacity(text.len()); + let mut space_buffer = String::with_capacity(128); + for (char_kind, c) in CharClasses::new(text.chars()) { + match c { + '\n' => { + if char_kind == FullCodeCharKind::InString { + buffer.push_str(&space_buffer); + } + space_buffer.clear(); + buffer.push('\n'); + } + _ if c.is_whitespace() => { + space_buffer.push(c); + } + _ => { + if !space_buffer.is_empty() { + buffer.push_str(&space_buffer); + space_buffer.clear(); + } + buffer.push(c); + } + } + } + buffer +} + struct CharClasses where T: Iterator, diff --git a/src/visitor.rs b/src/visitor.rs index f6f46ca6188..29eaea39a7f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -18,8 +18,8 @@ use syntax::parse::ParseSess; use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{contains_comment, recover_missing_comment_in_span, CodeCharKind, CommentCodeSlices, - FindUncommented}; +use comment::{contains_comment, recover_missing_comment_in_span, remove_trailing_white_spaces, + CodeCharKind, CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; use items::{format_impl, format_struct, format_struct_struct, format_trait, @@ -470,7 +470,7 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::MacroDef(..) => { // FIXME(#1539): macros 2.0 - let mac_snippet = Some(self.snippet(item.span)); + let mac_snippet = Some(remove_trailing_white_spaces(&self.snippet(item.span))); self.push_rewrite(item.span, mac_snippet); } } -- cgit 1.4.1-3-g733a5 From fe69dde96be4b7afcef4975e825d385b23b51799 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 5 Oct 2017 20:50:19 +0900 Subject: Replace 'try_opt!' macro with a '?' operator --- src/chains.rs | 38 ++++--- src/comment.rs | 22 ++-- src/expr.rs | 304 +++++++++++++++++++++------------------------------- src/imports.rs | 40 ++----- src/items.rs | 322 +++++++++++++++++++++++--------------------------------- src/lists.rs | 25 ++--- src/macros.rs | 43 ++++---- src/patterns.rs | 45 +++----- src/shape.rs | 4 +- src/string.rs | 2 +- src/types.rs | 226 +++++++++++++++++---------------------- src/utils.rs | 9 -- src/vertical.rs | 23 ++-- src/visitor.rs | 30 +++--- 14 files changed, 457 insertions(+), 676 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 23c311b9589..74c43d783b7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -110,11 +110,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { shape }; - let parent_rewrite = try_opt!( - parent - .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num)) - ); + let parent_rewrite = parent + .rewrite(context, parent_shape) + .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); @@ -146,8 +144,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let overhead = last_line_width(&parent_rewrite); let offset = parent_rewrite.lines().rev().next().unwrap().trim().len(); match context.config.chain_indent() { - IndentStyle::Visual => try_opt!(parent_shape.offset_left(overhead)), - IndentStyle::Block => try_opt!(parent_shape.block().offset_left(offset)), + IndentStyle::Visual => parent_shape.offset_left(overhead)?, + IndentStyle::Block => parent_shape.block().offset_left(offset)?, } } else { other_child_shape @@ -165,11 +163,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let last_subexpr = &subexpr_list[suffix_try_num]; let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); - let mut rewrites = try_opt!( - iter.map(|(e, shape)| { - rewrite_chain_subexpr(e, total_span, context, shape) - }).collect::>>() - ); + let mut rewrites = iter.map(|(e, shape)| { + rewrite_chain_subexpr(e, total_span, context, shape) + }).collect::>>()?; // Total of all items excluding the last. let extend_last_subexr = last_line_extendable(&parent_rewrite) && rewrites.is_empty(); @@ -187,7 +183,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, nested_shape); - let (last_subexpr_str, fits_single_line) = try_opt!(if all_in_one_line || extend_last_subexr { + let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexr { parent_shape.offset_left(almost_total).map(|shape| { if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { let line_count = rw.lines().count(); @@ -207,11 +203,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { (rewrite_last(), false) } - }) + })? } else { - Some((rewrite_last(), false)) - }); - rewrites.push(try_opt!(last_subexpr_str)); + (rewrite_last(), false) + }; + rewrites.push(last_subexpr_str?); let connector = if fits_single_line && !parent_rewrite_contains_newline { // Yay, we can put everything on one line. @@ -288,7 +284,7 @@ fn rewrite_try( context: &RewriteContext, shape: Shape, ) -> Option { - let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count)))); + let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; Some(format!("{}{}", sub_expr, repeat_try(try_count))) } @@ -472,8 +468,10 @@ fn rewrite_method_call( let (lo, type_str) = if types.is_empty() { (args[0].span.hi(), String::new()) } else { - let type_list: Vec<_> = - try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + let type_list = types + .iter() + .map(|ty| ty.rewrite(context, shape)) + .collect::>>()?; let type_str = if context.config.spaces_within_angle_brackets() && !type_list.is_empty() { format!("::< {} >", type_list.join(", ")) diff --git a/src/comment.rs b/src/comment.rs index f74684e5862..f966d658dc8 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -152,7 +152,7 @@ pub fn combine_strs_with_missing_comments( last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); let indent_str = shape.indent.to_string(context.config); - let missing_comment = try_opt!(rewrite_missing_comment(span, shape, context)); + let missing_comment = rewrite_missing_comment(span, shape, context)?; if missing_comment.is_empty() { if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { @@ -254,13 +254,7 @@ fn identify_comment( .collect::>() .join("\n"); - let first_group_str = try_opt!(rewrite_comment_inner( - &first_group, - block_style, - style, - shape, - config, - )); + let first_group_str = rewrite_comment_inner(&first_group, block_style, style, shape, config)?; if rest.is_empty() { Some(first_group_str) } else { @@ -380,7 +374,7 @@ pub fn recover_missing_comment_in_span( context: &RewriteContext, used_width: usize, ) -> Option { - let missing_comment = try_opt!(rewrite_missing_comment(span, shape, context)); + let missing_comment = rewrite_missing_comment(span, shape, context)?; if missing_comment.is_empty() { Some(String::new()) } else { @@ -610,7 +604,7 @@ where type Item = (FullCodeCharKind, T::Item); fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { - let item = try_opt!(self.base.next()); + let item = self.base.next()?; let chr = item.get_char(); self.status = match self.status { CharClassesStatus::LitString => match chr { @@ -705,7 +699,7 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { type Item = (CodeCharKind, usize, &'a str); fn next(&mut self) -> Option { - let (kind, (start_idx, _)) = try_opt!(self.iter.next()); + let (kind, (start_idx, _)) = self.iter.next()?; match kind { FullCodeCharKind::Normal => { // Consume all the Normal code @@ -886,14 +880,14 @@ impl<'a> Iterator for CommentReducer<'a> { type Item = char; fn next(&mut self) -> Option { loop { - let mut c = try_opt!(self.iter.next()); + let mut c = self.iter.next()?; if self.is_block && self.at_start_line { while c.is_whitespace() { - c = try_opt!(self.iter.next()); + c = self.iter.next()?; } // Ignore leading '*' if c == '*' { - c = try_opt!(self.iter.next()); + c = self.iter.next()?; } } else if c == '\n' { self.at_start_line = true; diff --git a/src/expr.rs b/src/expr.rs index 270087f122e..083aee5a225 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -75,7 +75,7 @@ pub fn format_expr( ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); - let callee_str = try_opt!(callee.rewrite(context, shape)); + let callee_str = callee.rewrite(context, shape)?; rewrite_call(context, &callee_str, &args, inner_span, shape) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), @@ -120,7 +120,7 @@ pub fn format_expr( // Rewrite block without trying to put it in a single line. rw } else { - let prefix = try_opt!(block_prefix(context, block, shape)); + let prefix = block_prefix(context, block, shape)?; rewrite_block_with_visitor(context, &prefix, block, shape) } } @@ -295,7 +295,7 @@ pub fn format_expr( Some(format!( "{}{}", "do catch ", - try_opt!(block.rewrite(context, Shape::legacy(budget, shape.indent))) + block.rewrite(context, Shape::legacy(budget, shape.indent))? )) } } @@ -307,7 +307,7 @@ pub fn format_expr( }) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); - let attrs_str = try_opt!(attrs.rewrite(context, shape)); + let attrs_str = attrs.rewrite(context, shape)?; let span = mk_sp( attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), expr.span.lo(), @@ -338,10 +338,8 @@ where width: context.budget(lhs_overhead), ..shape }; - let lhs_result = try_opt!( - lhs.rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", prefix, lhs_str)) - ); + let lhs_result = lhs.rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}", prefix, lhs_str))?; // Try to the both lhs and rhs on the same line. let rhs_orig_result = shape @@ -367,25 +365,25 @@ where // We have to use multiple lines. // Re-evaluate the rhs because we have more space now: - let mut rhs_shape = try_opt!(match context.config.control_style() { + let mut rhs_shape = match context.config.control_style() { Style::Legacy => shape - .sub_width(suffix.len() + prefix.len()) - .map(|s| s.visual_indent(prefix.len())), + .sub_width(suffix.len() + prefix.len())? + .visual_indent(prefix.len()), Style::Rfc => { // Try to calculate the initial constraint on the right hand side. let rhs_overhead = shape.rhs_overhead(context.config); Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead) + .sub_width(rhs_overhead)? } - }); + }; let infix = match separator_place { SeparatorPlace::Back => infix.trim_right(), SeparatorPlace::Front => infix.trim_left(), }; if separator_place == SeparatorPlace::Front { - rhs_shape = try_opt!(rhs_shape.offset_left(infix.len())); + rhs_shape = rhs_shape.offset_left(infix.len())?; } - let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape)); + let rhs_result = rhs.rewrite(context, rhs_shape)?; match separator_place { SeparatorPlace::Back => Some(format!( "{}{}\n{}{}{}", @@ -423,18 +421,14 @@ where }; let nested_shape = match context.config.array_layout() { - IndentStyle::Block => try_opt!( - shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1) - ), - IndentStyle::Visual => try_opt!( - shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2) - ), + IndentStyle::Block => shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1)?, + IndentStyle::Visual => shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2)?, }; let items = itemize_list( @@ -507,7 +501,7 @@ where preserve_newline: false, config: context.config, }; - let list_str = try_opt!(write_list(&items, &fmt)); + let list_str = write_list(&items, &fmt)?; let result = if context.config.array_layout() == IndentStyle::Visual || tactic == DefinitiveListTactic::Horizontal @@ -545,12 +539,12 @@ fn rewrite_closure_fn_decl( }; // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. - let nested_shape = try_opt!(try_opt!(shape.shrink_left(mover.len())).sub_width(4)); + let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?; // 1 = | let argument_offset = nested_shape.indent + 1; - let arg_shape = try_opt!(nested_shape.offset_left(1)).visual_indent(0); - let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape)); + let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); + let ret_str = fn_decl.output.rewrite(context, arg_shape)?; let arg_items = itemize_list( context.codemap, @@ -576,7 +570,7 @@ fn rewrite_closure_fn_decl( horizontal_budget, ); let arg_shape = match tactic { - DefinitiveListTactic::Horizontal => try_opt!(arg_shape.sub_width(ret_str.len() + 1)), + DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, _ => arg_shape, }; @@ -590,7 +584,7 @@ fn rewrite_closure_fn_decl( preserve_newline: true, config: context.config, }; - let list_str = try_opt!(write_list(&item_vec, &fmt)); + let list_str = write_list(&item_vec, &fmt)?; let mut prefix = format!("{}|{}|", mover, list_str); // 1 = space between `|...|` and body. let extra_offset = extra_offset(&prefix, shape) + 1; @@ -625,16 +619,10 @@ fn rewrite_closure( context: &RewriteContext, shape: Shape, ) -> Option { - let (prefix, extra_offset) = try_opt!(rewrite_closure_fn_decl( - capture, - fn_decl, - body, - span, - context, - shape, - )); + let (prefix, extra_offset) = + rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?; // 1 = space between `|...|` and body. - let body_shape = try_opt!(shape.offset_left(extra_offset)); + let body_shape = shape.offset_left(extra_offset)?; if let ast::ExprKind::Block(ref block) = body.node { // The body of the closure is an empty block. @@ -741,7 +729,7 @@ fn rewrite_closure_block( // The body of the closure is big enough to be block indented, that // means we must re-format. let block_shape = shape.block(); - let block_str = try_opt!(block.rewrite(context, block_shape)); + let block_str = block.rewrite(context, block_shape)?; Some(format!("{} {}", prefix, block_str)) } @@ -791,21 +779,21 @@ fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> O Some(match block.rules { ast::BlockCheckMode::Unsafe(..) => { let snippet = context.snippet(block.span); - let open_pos = try_opt!(snippet.find_uncommented("{")); + let open_pos = snippet.find_uncommented("{")?; // Extract comment between unsafe and block start. let trimmed = &snippet[6..open_pos].trim(); if !trimmed.is_empty() { // 9 = "unsafe {".len(), 7 = "unsafe ".len() - let budget = try_opt!(shape.width.checked_sub(9)); + let budget = shape.width.checked_sub(9)?; format!( "unsafe {} ", - try_opt!(rewrite_comment( + rewrite_comment( trimmed, true, Shape::legacy(budget, shape.indent + 7), context.config, - )) + )? ) } else { "unsafe ".to_owned() @@ -823,7 +811,7 @@ fn rewrite_single_line_block( ) -> Option { if is_simple_block(block, context.codemap) { let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent); - let expr_str = try_opt!(block.stmts[0].rewrite(context, expr_shape)); + let expr_str = block.stmts[0].rewrite(context, expr_shape)?; let result = format!("{}{{ {} }}", prefix, expr_str); if result.len() <= shape.width && !result.contains('\n') { return Some(result); @@ -848,7 +836,7 @@ fn rewrite_block_with_visitor( match block.rules { ast::BlockCheckMode::Unsafe(..) => { let snippet = context.snippet(block.span); - let open_pos = try_opt!(snippet.find_uncommented("{")); + let open_pos = snippet.find_uncommented("{")?; visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) } ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), @@ -866,7 +854,7 @@ impl Rewrite for ast::Block { return rw; } - let prefix = try_opt!(block_prefix(context, self, shape)); + let prefix = block_prefix(context, self, shape)?; let result = rewrite_block_with_visitor(context, &prefix, self, shape); if let Some(ref result_str) = result { @@ -894,7 +882,7 @@ impl Rewrite for ast::Stmt { "" }; - let shape = try_opt!(shape.sub_width(suffix.len())); + let shape = shape.sub_width(suffix.len())?; format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) } ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, @@ -909,8 +897,8 @@ fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Opt ast::ExprKind::Match(ref cond, _) => { // `match `cond` {` let cond_shape = match context.config.control_style() { - Style::Legacy => try_opt!(shape.shrink_left(6).and_then(|s| s.sub_width(2))), - Style::Rfc => try_opt!(shape.offset_left(8)), + Style::Legacy => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, + Style::Rfc => shape.offset_left(8)?, }; cond.rewrite(context, cond_shape) } @@ -1084,7 +1072,7 @@ impl<'a> ControlFlow<'a> { width: usize, ) -> Option { assert!(self.allow_single_line); - let else_block = try_opt!(self.else_block); + let else_block = self.else_block?; let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node) = else_block.node { @@ -1095,14 +1083,13 @@ impl<'a> ControlFlow<'a> { return None; } - let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost)); + let new_width = width.checked_sub(pat_expr_str.len() + fixed_cost)?; let expr = &self.block.stmts[0]; - let if_str = try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); + let if_str = expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; - let new_width = try_opt!(new_width.checked_sub(if_str.len())); + let new_width = new_width.checked_sub(if_str.len())?; let else_expr = &else_node.stmts[0]; - let else_str = - try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))); + let else_str = else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; if if_str.contains('\n') || else_str.contains('\n') { return None; @@ -1146,7 +1133,7 @@ impl<'a> ControlFlow<'a> { let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - try_opt!(fresh_shape.offset_left(7)) + fresh_shape.offset_left(7)? } else { fresh_shape }; @@ -1158,10 +1145,10 @@ impl<'a> ControlFlow<'a> { let pat_expr_string = match self.cond { Some(cond) => { let cond_shape = match context.config.control_style() { - Style::Legacy => try_opt!(constr_shape.shrink_left(offset)), - Style::Rfc => try_opt!(constr_shape.offset_left(offset)), + Style::Legacy => constr_shape.shrink_left(offset)?, + Style::Rfc => constr_shape.offset_left(offset)?, }; - try_opt!(rewrite_pat_expr( + rewrite_pat_expr( context, self.pat, cond, @@ -1169,7 +1156,7 @@ impl<'a> ControlFlow<'a> { self.connector, self.keyword, cond_shape, - )) + )? } None => String::new(), }; @@ -1271,7 +1258,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); - let (cond_str, used_width) = try_opt!(self.rewrite_cond(context, shape, &alt_block_sep)); + let (cond_str, used_width) = self.rewrite_cond(context, shape, &alt_block_sep)?; // If `used_width` is 0, it indicates that whole control flow is written in a single line. if used_width == 0 { return Some(cond_str); @@ -1291,12 +1278,7 @@ impl<'a> Rewrite for ControlFlow<'a> { }; let mut block_context = context.clone(); block_context.is_if_else_block = self.else_block.is_some(); - let block_str = try_opt!(rewrite_block_with_visitor( - &block_context, - "", - self.block, - block_shape, - )); + let block_str = rewrite_block_with_visitor(&block_context, "", self.block, block_shape)?; let mut result = format!("{}{}", cond_str, block_str); @@ -1369,17 +1351,15 @@ impl<'a> Rewrite for ControlFlow<'a> { ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, _ => " ", }; - try_opt!( - write!( - &mut result, - "{}else{}", - between_kwd_else_block_comment - .as_ref() - .map_or(between_sep, |s| &**s), - after_else_comment.as_ref().map_or(after_sep, |s| &**s) - ).ok() - ); - result.push_str(&try_opt!(rewrite)); + write!( + &mut result, + "{}else{}", + between_kwd_else_block_comment + .as_ref() + .map_or(between_sep, |s| &**s), + after_else_comment.as_ref().map_or(after_sep, |s| &**s) + ).ok()?; + result.push_str(&rewrite?); } Some(result) @@ -1476,17 +1456,17 @@ fn rewrite_match( // Do not take the rhs overhead from the upper expressions into account // when rewriting match condition. - let new_width = try_opt!(context.config.max_width().checked_sub(shape.used_width())); + let new_width = context.config.max_width().checked_sub(shape.used_width())?; let cond_shape = Shape { width: new_width, ..shape }; // 6 = `match ` let cond_shape = match context.config.control_style() { - Style::Legacy => try_opt!(cond_shape.shrink_left(6)), - Style::Rfc => try_opt!(cond_shape.offset_left(6)), + Style::Legacy => cond_shape.shrink_left(6)?, + Style::Rfc => cond_shape.offset_left(6)?, }; - let cond_str = try_opt!(cond.rewrite(context, cond_shape)); + let cond_str = cond.rewrite(context, cond_shape)?; let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => &alt_block_sep, @@ -1505,11 +1485,9 @@ fn rewrite_match( let inner_attrs_str = if inner_attrs.is_empty() { String::new() } else { - try_opt!( - inner_attrs - .rewrite(context, shape) - .map(|s| format!("{}{}\n", nested_indent_str, s)) - ) + inner_attrs + .rewrite(context, shape) + .map(|s| format!("{}{}\n", nested_indent_str, s))? }; let open_brace_pos = if inner_attrs.is_empty() { @@ -1532,13 +1510,7 @@ fn rewrite_match( block_sep, inner_attrs_str, arm_indent_str, - try_opt!(rewrite_match_arms( - context, - arms, - shape, - span, - open_brace_pos, - )), + rewrite_match_arms(context, arms, shape, span, open_brace_pos,)?, shape.indent.to_string(context.config), )) } @@ -1626,12 +1598,12 @@ fn rewrite_match_arm( arm.attrs[arm.attrs.len() - 1].span.hi(), arm.pats[0].span.lo(), ), - try_opt!(arm.attrs.rewrite(context, shape)), + arm.attrs.rewrite(context, shape)?, ) } else { (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; - let pats_str = try_opt!( + let pats_str = rewrite_match_pattern(context, &arm.pats, &arm.guard, shape).and_then(|pats_str| { combine_strs_with_missing_comments( context, @@ -1641,8 +1613,7 @@ fn rewrite_match_arm( shape, false, ) - }) - ); + })?; rewrite_match_body( context, &arm.body, @@ -1661,13 +1632,11 @@ fn rewrite_match_pattern( ) -> Option { // Patterns // 5 = ` => {` - let pat_shape = try_opt!(shape.sub_width(5)); + let pat_shape = shape.sub_width(5)?; - let pat_strs = try_opt!( - pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>() - ); + let pat_strs = pats.iter() + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>()?; let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); let tactic = definitive_tactic( @@ -1686,15 +1655,10 @@ fn rewrite_match_pattern( preserve_newline: false, config: context.config, }; - let pats_str = try_opt!(write_list(&items, &fmt)); + let pats_str = write_list(&items, &fmt)?; // Guard - let guard_str = try_opt!(rewrite_guard( - context, - guard, - shape, - trimmed_last_line_width(&pats_str), - )); + let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; Some(format!("{}{}", pats_str, guard_str)) } @@ -1910,9 +1874,8 @@ fn rewrite_pat_expr( } else { format!("{} ", matcher) }; - let pat_shape = - try_opt!(try_opt!(shape.offset_left(matcher.len())).sub_width(connector.len())); - let pat_string = try_opt!(pat.rewrite(context, pat_shape)); + let pat_shape = shape.offset_left(matcher.len())?.sub_width(connector.len())?; + let pat_string = pat.rewrite(context, pat_shape)?; let result = format!("{}{}{}", matcher, pat_string, connector); return rewrite_assign_rhs(context, result, expr, shape); } @@ -2047,19 +2010,19 @@ where 1 }; let used_width = extra_offset(callee_str, shape); - let one_line_width = try_opt!(shape.width.checked_sub(used_width + 2 * paren_overhead)); + let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; - let nested_shape = try_opt!(shape_from_fn_call_style( + let nested_shape = shape_from_fn_call_style( context, shape, used_width + 2 * paren_overhead, used_width + paren_overhead, - )); + )?; let span_lo = context.codemap.span_after(span, "("); let args_span = mk_sp(span_lo, span.hi()); - let (extendable, list_str) = try_opt!(rewrite_call_args( + let (extendable, list_str) = rewrite_call_args( context, args, args_span, @@ -2067,7 +2030,7 @@ where one_line_width, args_max_width, force_trailing_comma, - )); + )?; if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { let mut new_context = context.clone(); @@ -2083,7 +2046,7 @@ where ); } - let args_shape = try_opt!(shape.sub_width(last_line_width(callee_str))); + let args_shape = shape.sub_width(last_line_width(callee_str))?; Some(format!( "{}{}", callee_str, @@ -2242,7 +2205,7 @@ fn last_arg_shape( shape.block().indent }; Some(Shape { - width: try_opt!(max_width.checked_sub(overhead)), + width: max_width.checked_sub(overhead)?, indent: arg_indent, offset: 0, }) @@ -2262,19 +2225,13 @@ fn rewrite_last_closure( } _ => body, }; - let (prefix, extra_offset) = try_opt!(rewrite_closure_fn_decl( - capture, - fn_decl, - body, - expr.span, - context, - shape, - )); + let (prefix, extra_offset) = + rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?; // If the closure goes multi line before its body, do not overflow the closure. if prefix.contains('\n') { return None; } - let body_shape = try_opt!(shape.offset_left(extra_offset)); + let body_shape = shape.offset_left(extra_offset)?; // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. let is_multi_lined_cond = rewrite_cond(context, body, body_shape) @@ -2414,11 +2371,9 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> debug!("rewrite_paren, shape: {:?}", shape); let total_paren_overhead = paren_overhead(context); let paren_overhead = total_paren_overhead / 2; - let sub_shape = try_opt!( - shape - .offset_left(paren_overhead) - .and_then(|s| s.sub_width(paren_overhead)) - ); + let sub_shape = shape + .offset_left(paren_overhead) + .and_then(|s| s.sub_width(paren_overhead))?; let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && !s.is_empty() { format!("( {} )", s) @@ -2426,7 +2381,7 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> format!("({})", s) }; - let subexpr_str = try_opt!(subexpr.rewrite(context, sub_shape)); + let subexpr_str = subexpr.rewrite(context, sub_shape)?; debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); if subexpr_str.contains('\n') @@ -2444,7 +2399,7 @@ fn rewrite_index( context: &RewriteContext, shape: Shape, ) -> Option { - let expr_str = try_opt!(expr.rewrite(context, shape)); + let expr_str = expr.rewrite(context, shape)?; let (lbr, rbr) = if context.config.spaces_within_square_brackets() { ("[ ", " ]") @@ -2473,8 +2428,8 @@ fn rewrite_index( // Try putting index on the next line and see if it fits in a single line. let indent = shape.indent.block_indent(context.config); - let index_shape = try_opt!(Shape::indented(indent, context.config).offset_left(lbr.len())); - let index_shape = try_opt!(index_shape.sub_width(rbr.len() + rhs_overhead)); + let index_shape = Shape::indented(indent, context.config).offset_left(lbr.len())?; + let index_shape = index_shape.sub_width(rbr.len() + rhs_overhead)?; let new_index_rw = index.rewrite(context, index_shape); match (orig_index_rw, new_index_rw) { (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( @@ -2522,34 +2477,28 @@ fn rewrite_struct_lit<'a>( } // 2 = " {".len() - let path_shape = try_opt!(shape.sub_width(2)); - let path_str = try_opt!(rewrite_path( - context, - PathContext::Expr, - None, - path, - path_shape, - )); + let path_shape = shape.sub_width(2)?; + let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; if fields.is_empty() && base.is_none() { return Some(format!("{} {{}}", path_str)); } // Foo { a: Foo } - indent is +3, width is -5. - let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2)); + let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.codemap.span_after(span, "{"); let fields_str = if struct_lit_can_be_aligned(fields, &base) && context.config.struct_field_align_threshold() > 0 { - try_opt!(rewrite_with_alignment( + rewrite_with_alignment( fields, context, shape, mk_sp(body_lo, span.hi()), one_line_width, - )) + )? } else { let field_iter = fields .into_iter() @@ -2572,11 +2521,11 @@ fn rewrite_struct_lit<'a>( let rewrite = |item: &StructLitField| match *item { StructLitField::Regular(field) => { // The 1 taken from the v_budget is for the comma. - rewrite_field(context, field, try_opt!(v_shape.sub_width(1)), 0) + rewrite_field(context, field, v_shape.sub_width(1)?, 0) } StructLitField::Base(expr) => { // 2 = .. - expr.rewrite(context, try_opt!(v_shape.offset_left(2))) + expr.rewrite(context, v_shape.offset_left(2)?) .map(|s| format!("..{}", s)) } }; @@ -2598,7 +2547,7 @@ fn rewrite_struct_lit<'a>( let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); - try_opt!(write_list(&item_vec, &fmt)) + write_list(&item_vec, &fmt)? }; let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); @@ -2657,10 +2606,10 @@ pub fn rewrite_field( separator.push(' '); } let overhead = name.len() + separator.len(); - let expr_shape = try_opt!(shape.offset_left(overhead)); + let expr_shape = shape.offset_left(overhead)?; let expr = field.expr.rewrite(context, expr_shape); - let mut attrs_str = try_opt!(field.attrs.rewrite(context, shape)); + let mut attrs_str = field.attrs.rewrite(context, shape)?; if !attrs_str.is_empty() { attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); }; @@ -2718,7 +2667,7 @@ where debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); if items.len() == 1 { // 3 = "(" + ",)" - let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1); + let nested_shape = shape.sub_width(3)?.visual_indent(1); return items.next().unwrap().rewrite(context, nested_shape).map( |s| if context.config.spaces_within_parens() { format!("( {}, )", s) @@ -2729,7 +2678,7 @@ where } let list_lo = context.codemap.span_after(span, "("); - let nested_shape = try_opt!(shape.sub_width(2)).visual_indent(1); + let nested_shape = shape.sub_width(2)?.visual_indent(1); let items = itemize_list( context.codemap, items, @@ -2758,7 +2707,7 @@ where preserve_newline: false, config: context.config, }; - let list_str = try_opt!(write_list(&item_vec, &fmt)); + let list_str = write_list(&item_vec, &fmt)?; if context.config.spaces_within_parens() && !list_str.is_empty() { Some(format!("( {} )", list_str)) @@ -2805,7 +2754,7 @@ pub fn rewrite_unary_prefix( shape: Shape, ) -> Option { rewrite - .rewrite(context, try_opt!(shape.offset_left(prefix.len()))) + .rewrite(context, shape.offset_left(prefix.len())?) .map(|r| format!("{}{}", prefix, r)) } @@ -2818,7 +2767,7 @@ pub fn rewrite_unary_suffix( shape: Shape, ) -> Option { rewrite - .rewrite(context, try_opt!(shape.sub_width(suffix.len()))) + .rewrite(context, shape.sub_width(suffix.len())?) .map(|mut r| { r.push_str(suffix); r @@ -2853,12 +2802,8 @@ fn rewrite_assignment( }; // 1 = space between lhs and operator. - let lhs_shape = try_opt!(shape.sub_width(operator_str.len() + 1)); - let lhs_str = format!( - "{} {}", - try_opt!(lhs.rewrite(context, lhs_shape)), - operator_str - ); + let lhs_shape = shape.sub_width(operator_str.len() + 1)?; + let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); rewrite_assign_rhs(context, lhs_str, rhs, shape) } @@ -2878,13 +2823,8 @@ pub fn rewrite_assign_rhs>( 0 }; // 1 = space between operator and rhs. - let orig_shape = try_opt!(shape.offset_left(last_line_width + 1)); - let rhs = try_opt!(choose_rhs( - context, - ex, - orig_shape, - ex.rewrite(context, orig_shape) - )); + let orig_shape = shape.offset_left(last_line_width + 1)?; + let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; Some(lhs + &rhs) } @@ -2901,12 +2841,10 @@ fn choose_rhs( _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = try_opt!( - Shape::indented( - shape.block().indent.block_indent(context.config), - context.config, - ).sub_width(shape.rhs_overhead(context.config)) - ); + let new_shape = Shape::indented( + shape.block().indent.block_indent(context.config), + context.config, + ).sub_width(shape.rhs_overhead(context.config))?; let new_rhs = expr.rewrite(context, new_shape); let new_indent_str = &new_shape.indent.to_string(context.config); diff --git a/src/imports.rs b/src/imports.rs index 4331ea84bc5..68c3ec32897 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -140,21 +140,9 @@ fn rewrite_view_path_prefix( span: path.span, segments: path.segments[..path.segments.len() - 1].to_owned(), }; - try_opt!(rewrite_path( - context, - PathContext::Import, - None, - path, - shape, - )) + rewrite_path(context, PathContext::Import, None, path, shape)? } else { - try_opt!(rewrite_path( - context, - PathContext::Import, - None, - path, - shape, - )) + rewrite_path(context, PathContext::Import, None, path, shape)? }; Some(path_str) } @@ -167,15 +155,15 @@ impl Rewrite for ast::ViewPath { } ast::ViewPath_::ViewPathGlob(ref path) => { // 4 = "::*".len() - let prefix_shape = try_opt!(shape.sub_width(3)); - let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); + let prefix_shape = shape.sub_width(3)?; + let path_str = rewrite_view_path_prefix(path, context, prefix_shape)?; Some(format!("{}::*", path_str)) } ast::ViewPath_::ViewPathSimple(ident, ref path) => { let ident_str = ident.to_string(); // 4 = " as ".len() - let prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4)); - let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape)); + let prefix_shape = shape.sub_width(ident_str.len() + 4)?; + let path_str = rewrite_view_path_prefix(path, context, prefix_shape)?; Some(if path.segments.last().unwrap().identifier == ident { path_str @@ -228,7 +216,7 @@ fn rewrite_imports( |item| item.span().lo(), |item| item.span().hi(), |item| { - let attrs_str = try_opt!(item.attrs.rewrite(context, shape)); + let attrs_str = item.attrs.rewrite(context, shape)?; let missed_span = if item.attrs.is_empty() { mk_sp(item.span.lo(), item.span.lo()) @@ -238,9 +226,9 @@ fn rewrite_imports( let item_str = match item.node { ast::ItemKind::Use(ref vp) => { - try_opt!(rewrite_import(context, &item.vis, vp, &item.attrs, shape)) + rewrite_import(context, &item.vis, vp, &item.attrs, shape)? } - ast::ItemKind::ExternCrate(..) => try_opt!(rewrite_extern_crate(context, item)), + ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, _ => return None, }; @@ -428,13 +416,7 @@ fn rewrite_use_list( context: &RewriteContext, ) -> Option { // Returns a different option to distinguish `::foo` and `foo` - let path_str = try_opt!(rewrite_path( - context, - PathContext::Import, - None, - path, - shape, - )); + let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; match path_list.len() { 0 => { @@ -521,7 +503,7 @@ fn rewrite_use_list( preserve_newline: true, config: context.config, }; - let list_str = try_opt!(write_list(&items[first_index..], &fmt)); + let list_str = write_list(&items[first_index..], &fmt)?; let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block { diff --git a/src/items.rs b/src/items.rs index 8678e40ad22..e2580bea8de 100644 --- a/src/items.rs +++ b/src/items.rs @@ -62,11 +62,11 @@ impl Rewrite for ast::Local { return None; } - let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + let attrs_str = self.attrs.rewrite(context, shape)?; let mut result = if attrs_str.is_empty() { "let ".to_owned() } else { - try_opt!(combine_strs_with_missing_comments( + combine_strs_with_missing_comments( context, &attrs_str, "let ", @@ -76,14 +76,14 @@ impl Rewrite for ast::Local { ), shape, false, - )) + )? }; // 4 = "let ".len() - let pat_shape = try_opt!(shape.offset_left(4)); + let pat_shape = shape.offset_left(4)?; // 1 = ; - let pat_shape = try_opt!(pat_shape.sub_width(1)); - let pat_str = try_opt!(self.pat.rewrite(context, pat_shape)); + let pat_shape = pat_shape.sub_width(1)?; + let pat_str = self.pat.rewrite(context, pat_shape)?; result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -94,8 +94,8 @@ impl Rewrite for ast::Local { let separator = type_annotation_separator(context.config); let indent = shape.indent + last_line_width(&result) + separator.len(); // 1 = ; - let budget = try_opt!(shape.width.checked_sub(indent.width() + 1)); - let rewrite = try_opt!(ty.rewrite(context, Shape::legacy(budget, indent))); + let budget = shape.width.checked_sub(indent.width() + 1)?; + let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?; infix.push_str(separator); infix.push_str(&rewrite); @@ -112,9 +112,9 @@ impl Rewrite for ast::Local { if let Some(ref ex) = self.init { // 1 = trailing semicolon; - let nested_shape = try_opt!(shape.sub_width(1)); + let nested_shape = shape.sub_width(1)?; - result = try_opt!(rewrite_assign_rhs(context, result, ex, nested_shape)); + result = rewrite_assign_rhs(context, result, ex, nested_shape)?; } result.push(';'); @@ -306,15 +306,8 @@ impl<'a> FmtVisitor<'a> { let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause, has_body); - let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base( - &context, - indent, - ident, - fn_sig, - span, - newline_brace, - true, - )); + let (mut result, force_newline_brace) = + rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; if self.config.fn_brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace { newline_brace = true; @@ -351,7 +344,7 @@ impl<'a> FmtVisitor<'a> { let span = mk_sp(span.lo(), span.hi() - BytePos(1)); let context = self.get_context(); - let (mut result, _) = try_opt!(rewrite_fn_base( + let (mut result, _) = rewrite_fn_base( &context, indent, ident, @@ -359,7 +352,7 @@ impl<'a> FmtVisitor<'a> { span, false, false, - )); + )?; // Re-attach semicolon result.push(';'); @@ -503,7 +496,7 @@ impl<'a> FmtVisitor<'a> { config: self.config, }; - let list = try_opt!(write_list(&items.collect::>(), &fmt)); + let list = write_list(&items.collect::>(), &fmt)?; result.push_str(&list); result.push('\n'); Some(result) @@ -520,7 +513,7 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let indent = self.block_indent; let shape = self.shape(); - let attrs_str = try_opt!(field.node.attrs.rewrite(&context, shape)); + let attrs_str = field.node.attrs.rewrite(&context, shape)?; let lo = field .node .attrs @@ -531,7 +524,7 @@ impl<'a> FmtVisitor<'a> { let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { // FIXME: Should limit the width, as we have a trailing comma - try_opt!(format_struct( + format_struct( &context, "", field.node.name, @@ -541,7 +534,7 @@ impl<'a> FmtVisitor<'a> { field.span, indent, Some(self.config.struct_variant_width()), - )) + )? } ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { let one_line_width = @@ -586,7 +579,7 @@ pub fn format_impl( ) -> Option { if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { let mut result = String::with_capacity(128); - let ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset)); + let ref_and_type = format_impl_ref_and_type(context, item, offset)?; let indent_str = offset.to_string(context.config); let sep = format!("\n{}", &indent_str); result.push_str(&ref_and_type); @@ -597,7 +590,7 @@ pub fn format_impl( context.budget(last_line_width(&result)) }; let option = WhereClauseOption::snuggled(&ref_and_type); - let where_clause_str = try_opt!(rewrite_where_clause( + let where_clause_str = rewrite_where_clause( context, &generics.where_clause, context.config.item_brace_style(), @@ -607,7 +600,7 @@ pub fn format_impl( where_span_end, self_ty.span.hi(), option, - )); + )?; // If there is no where clause, we may have missing comments between the trait name and // the opening brace. @@ -627,13 +620,7 @@ pub fn format_impl( } } - if try_opt!(is_impl_single_line( - context, - items, - &result, - &where_clause_str, - item, - )) { + if is_impl_single_line(context, items, &result, &where_clause_str, item)? { result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { result.push_str(&format!("{}{{{}}}", &sep, &sep)); @@ -665,7 +652,7 @@ pub fn format_impl( result.push('{'); let snippet = context.snippet(item.span); - let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + let open_pos = snippet.find_uncommented("{")? + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); @@ -708,7 +695,7 @@ fn is_impl_single_line( item: &ast::Item, ) -> Option { let snippet = context.snippet(item.span); - let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + let open_pos = snippet.find_uncommented("{")? + 1; Some( context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n') @@ -744,19 +731,14 @@ fn format_impl_ref_and_type( Some(ref tr) => tr.path.span.lo(), None => self_ty.span.lo(), }; - let shape = try_opt!(generics_shape_from_config( + let shape = generics_shape_from_config( context.config, Shape::indented(offset + last_line_width(&result), context.config), 0, - )); - let one_line_budget = try_opt!(shape.width.checked_sub(last_line_width(&result) + 2)); - let generics_str = try_opt!(rewrite_generics_inner( - context, - generics, - shape, - one_line_budget, - mk_sp(lo, hi), - )); + )?; + let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?; + let generics_str = + rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?; let polarity_str = if polarity == ast::ImplPolarity::Negative { "!" @@ -777,14 +759,9 @@ fn format_impl_ref_and_type( ) { result.push_str(&trait_ref_str); } else { - let generics_str = try_opt!(rewrite_generics_inner( - context, - generics, - shape, - 0, - mk_sp(lo, hi), - )); - result.push_str(&try_opt!(rewrite_trait_ref( + let generics_str = + rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?; + result.push_str(&rewrite_trait_ref( context, trait_ref, offset, @@ -792,7 +769,7 @@ fn format_impl_ref_and_type( false, polarity_str, result_len, - ))); + )?); } } else { result.push_str(&generics_str); @@ -839,9 +816,8 @@ fn format_impl_ref_and_type( Style::Legacy => new_line_offset + trait_ref_overhead, Style::Rfc => new_line_offset, }; - result.push_str(&*try_opt!( - self_ty.rewrite(context, Shape::legacy(budget, type_offset)) - )); + result.push_str(&*self_ty + .rewrite(context, Shape::legacy(budget, type_offset))?); Some(result) } else { unreachable!(); @@ -874,7 +850,7 @@ fn rewrite_trait_ref( if !retry { let offset = offset.block_indent(context.config); let shape = Shape::indented(offset, context.config); - let trait_ref_str = try_opt!(trait_ref.rewrite(context, shape)); + let trait_ref_str = trait_ref.rewrite(context, shape)?; Some(format!( "{}\n{}{}{}", generics_str, @@ -941,19 +917,15 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); let shape = Shape::indented(offset + last_line_width(&result), context.config); - let generics_str = try_opt!(rewrite_generics( - context, - generics, - shape, - mk_sp(item.span.lo(), body_lo), - )); + let generics_str = + rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; result.push_str(&generics_str); - let trait_bound_str = try_opt!(rewrite_trait_bounds( + let trait_bound_str = rewrite_trait_bounds( context, type_param_bounds, Shape::indented(offset, context.config), - )); + )?; // If the trait, generics, and trait bound cannot fit on the same line, // put the trait bounds on an indented new line if offset.width() + last_line_width(&result) + trait_bound_str.len() @@ -985,7 +957,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) type_param_bounds[type_param_bounds.len() - 1].span().hi() }; let option = WhereClauseOption::snuggled(&generics_str); - let where_clause_str = try_opt!(rewrite_where_clause( + let where_clause_str = rewrite_where_clause( context, &generics.where_clause, context.config.item_brace_style(), @@ -995,7 +967,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) None, pos_before_where, option, - )); + )?; // If the where clause cannot fit on the same line, // put the where clause on a new line if !where_clause_str.contains('\n') @@ -1053,7 +1025,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push('{'); let snippet = context.snippet(item.span); - let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + let open_pos = snippet.find_uncommented("{")? + 1; if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); @@ -1108,7 +1080,7 @@ pub fn format_struct_struct( let body_lo = context.codemap.span_after(span, "{"); let generics_str = match generics { - Some(g) => try_opt!(format_generics( + Some(g) => format_generics( context, g, "{", @@ -1118,7 +1090,7 @@ pub fn format_struct_struct( offset, mk_sp(span.lo(), body_lo), last_line_width(&result), - )), + )?, None => { // 3 = ` {}`, 2 = ` {`. let overhead = if fields.is_empty() { 3 } else { 2 }; @@ -1166,13 +1138,13 @@ pub fn format_struct_struct( let one_line_budget = one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); - let items_str = try_opt!(rewrite_with_alignment( + let items_str = rewrite_with_alignment( fields, context, Shape::indented(offset, context.config), mk_sp(body_lo, span.hi()), one_line_budget, - )); + )?; if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget { Some(format!("{} {} }}", result, items_str)) @@ -1228,12 +1200,12 @@ fn format_tuple_struct( let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); let g_span = mk_sp(span.lo(), body_lo); - let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); + let generics_str = rewrite_generics(context, generics, shape, g_span)?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); let option = WhereClauseOption::new(true, false); - try_opt!(rewrite_where_clause( + rewrite_where_clause( context, &generics.where_clause, context.config.item_brace_style(), @@ -1243,7 +1215,7 @@ fn format_tuple_struct( None, body_hi, option, - )) + )? } None => "".to_owned(), }; @@ -1271,7 +1243,7 @@ fn format_tuple_struct( result.push(')'); } else { // 3 = `();` - let body = try_opt!(rewrite_call_inner( + let body = rewrite_call_inner( context, "", &fields.iter().map(|field| field).collect::>()[..], @@ -1279,7 +1251,7 @@ fn format_tuple_struct( Shape::legacy(context.budget(last_line_width(&result) + 3), offset), context.config.fn_call_width(), false, - )); + )?; result.push_str(&body); } @@ -1315,14 +1287,14 @@ pub fn rewrite_type_alias( result.push_str(&ident.to_string()); // 2 = `= ` - let shape = try_opt!(Shape::indented(indent + result.len(), context.config).sub_width(2)); + let shape = Shape::indented(indent + result.len(), context.config).sub_width(2)?; let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo()); - let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span)); + let generics_str = rewrite_generics(context, generics, shape, g_span)?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); let option = WhereClauseOption::snuggled(&result); - let where_clause_str = try_opt!(rewrite_where_clause( + let where_clause_str = rewrite_where_clause( context, &generics.where_clause, context.config.item_brace_style(), @@ -1332,7 +1304,7 @@ pub fn rewrite_type_alias( Some(span.hi()), generics.span.hi(), option, - )); + )?; result.push_str(&where_clause_str); if where_clause_str.is_empty() { result.push_str(" = "); @@ -1346,20 +1318,18 @@ pub fn rewrite_type_alias( let budget = context.budget(indent.width() + line_width + ";".len()); let type_indent = indent + line_width; // Try to fit the type on the same line - let ty_str = try_opt!( - ty.rewrite(context, Shape::legacy(budget, type_indent)) - .or_else(|| { - // The line was too short, try to put the type on the next line - - // Remove the space after '=' - result.pop(); - let type_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&type_indent.to_string(context.config)); - let budget = context.budget(type_indent.width() + ";".len()); - ty.rewrite(context, Shape::legacy(budget, type_indent)) - }) - ); + let ty_str = ty.rewrite(context, Shape::legacy(budget, type_indent)) + .or_else(|| { + // The line was too short, try to put the type on the next line + + // Remove the space after '=' + result.pop(); + let type_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&type_indent.to_string(context.config)); + let budget = context.budget(type_indent.width() + ";".len()); + ty.rewrite(context, Shape::legacy(budget, type_indent)) + })?; result.push_str(&ty_str); result.push_str(";"); Some(result) @@ -1399,7 +1369,7 @@ fn rewrite_struct_field_type( spacing: &str, shape: Shape, ) -> Option { - let ty_shape = try_opt!(shape.offset_left(last_line_width + spacing.len())); + let ty_shape = shape.offset_left(last_line_width + spacing.len())?; field .ty .rewrite(context, ty_shape) @@ -1423,9 +1393,9 @@ pub fn rewrite_struct_field( } let type_annotation_spacing = type_annotation_spacing(context.config); - let prefix = try_opt!(rewrite_struct_field_prefix(context, field)); + let prefix = rewrite_struct_field_prefix(context, field)?; - let attrs_str = try_opt!(field.attrs.rewrite(context, shape)); + let attrs_str = field.attrs.rewrite(context, shape)?; let attrs_extendable = attrs_str.is_empty() || (context.config.attributes_on_same_line_as_field() && is_attributes_extendable(&attrs_str)); @@ -1440,14 +1410,14 @@ pub fn rewrite_struct_field( "" }); // Try to put everything on a single line. - let attr_prefix = try_opt!(combine_strs_with_missing_comments( + let attr_prefix = combine_strs_with_missing_comments( context, &attrs_str, &prefix, missing_span, shape, attrs_extendable, - )); + )?; let overhead = last_line_width(&attr_prefix); let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); for _ in 0..lhs_offset { @@ -1487,7 +1457,7 @@ pub fn rewrite_struct_field( _ => prefix + ty, }, _ => { - let ty = try_opt!(rewrite_type_in_next_line()); + let ty = rewrite_type_in_next_line()?; format!( "{}\n{}{}", prefix, @@ -1530,12 +1500,10 @@ pub fn rewrite_static( colon, ); // 2 = " =".len() - let ty_str = try_opt!(ty.rewrite( + let ty_str = ty.rewrite( context, - try_opt!( - Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2) - ), - )); + Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?, + )?; if let Some(expr) = expr_opt { let lhs = format!("{}{} =", prefix, ty_str); @@ -1564,14 +1532,12 @@ pub fn rewrite_associated_type( let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { // 2 = ": ".len() - let shape = try_opt!(Shape::indented(indent, context.config).offset_left(prefix.len() + 2)); + let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; let bounds: &[_] = ty_param_bounds; - let bound_str = try_opt!( - bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>() - ); + let bound_str = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; if !bounds.is_empty() { format!(": {}", join_bounds(context, shape, &bound_str)) } else { @@ -1582,13 +1548,13 @@ pub fn rewrite_associated_type( }; if let Some(ty) = ty_opt { - let ty_str = try_opt!(ty.rewrite( + let ty_str = ty.rewrite( context, Shape::legacy( context.budget(indent.block_indent + prefix.len() + 2), indent.block_only(), ), - )); + )?; Some(format!("{}{} = {};", prefix, type_bounds_str, ty_str)) } else { Some(format!("{}{};", prefix, type_bounds_str)) @@ -1603,13 +1569,7 @@ pub fn rewrite_associated_impl_type( context: &RewriteContext, indent: Indent, ) -> Option { - let result = try_opt!(rewrite_associated_type( - ident, - ty_opt, - ty_param_bounds_opt, - context, - indent, - )); + let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?; match defaultness { ast::Defaultness::Default => Some(format!("default {}", result)), @@ -1622,7 +1582,7 @@ impl Rewrite for ast::FunctionRetTy { match *self { ast::FunctionRetTy::Default(_) => Some(String::new()), ast::FunctionRetTy::Ty(ref ty) => { - let inner_width = try_opt!(shape.width.checked_sub(3)); + let inner_width = shape.width.checked_sub(3)?; ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) .map(|r| format!("-> {}", r)) } @@ -1643,10 +1603,8 @@ fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = try_opt!( - self.pat - .rewrite(context, Shape::legacy(shape.width, shape.indent)) - ); + let mut result = self.pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))?; if !is_empty_infer(context, &*self.ty) { if context.config.space_before_type_annotation() { @@ -1657,11 +1615,9 @@ impl Rewrite for ast::Arg { result.push_str(" "); } let overhead = last_line_width(&result); - let max_width = try_opt!(shape.width.checked_sub(overhead)); - let ty_str = try_opt!( - self.ty - .rewrite(context, Shape::legacy(max_width, shape.indent)) - ); + let max_width = shape.width.checked_sub(overhead)?; + let ty_str = self.ty + .rewrite(context, Shape::legacy(max_width, shape.indent))?; result.push_str(&ty_str); } @@ -1682,10 +1638,10 @@ fn rewrite_explicit_self( let mut_str = format_mutability(m); match lt { Some(ref l) => { - let lifetime_str = try_opt!(l.rewrite( + let lifetime_str = l.rewrite( context, Shape::legacy(context.config.max_width(), Indent::empty()), - )); + )?; Some(format!("&{} {}self", lifetime_str, mut_str)) } None => Some(format!("&{}self", mut_str)), @@ -1695,10 +1651,10 @@ fn rewrite_explicit_self( assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); let mutability = explicit_self_mutability(&args[0]); - let type_str = try_opt!(ty.rewrite( + let type_str = ty.rewrite( context, Shape::legacy(context.config.max_width(), Indent::empty()), - )); + )?; Some(format!( "{}self: {}", @@ -1788,7 +1744,7 @@ fn rewrite_fn_base( }; let fd = fn_sig.decl; let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = try_opt!(rewrite_generics(context, fn_sig.generics, shape, g_span)); + let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?; result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -1798,16 +1754,14 @@ fn rewrite_fn_base( // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. - let ret_str = try_opt!( - fd.output - .rewrite(context, Shape::indented(indent, context.config)) - ); + let ret_str = fd.output + .rewrite(context, Shape::indented(indent, context.config))?; let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = try_opt!(compute_budgets_for_args( + let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args( context, &result, indent, @@ -1815,7 +1769,7 @@ fn rewrite_fn_base( newline_brace, has_body, multi_line_ret_str, - )); + )?; debug!( "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", @@ -1869,7 +1823,7 @@ fn rewrite_fn_base( .span_after(mk_sp(args_start, span.hi()), "("), args_end, ); - let arg_str = try_opt!(rewrite_args( + let arg_str = rewrite_args( context, &fd.inputs, fd.get_self().as_ref(), @@ -1880,7 +1834,7 @@ fn rewrite_fn_base( args_span, fd.variadic, generics_str.contains('\n'), - )); + )?; let put_args_in_block = match context.config.fn_args_layout() { IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, @@ -1968,10 +1922,8 @@ fn rewrite_fn_base( if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = try_opt!( - fd.output - .rewrite(context, Shape::indented(ret_indent, context.config)) - ); + let ret_str = fd.output + .rewrite(context, Shape::indented(ret_indent, context.config))?; result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -2035,7 +1987,7 @@ fn rewrite_fn_base( } let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); - let where_clause_str = try_opt!(rewrite_where_clause( + let where_clause_str = rewrite_where_clause( context, where_clause, context.config.fn_brace_style(), @@ -2045,7 +1997,7 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, - )); + )?; // If there are neither where clause nor return type, we may be missing comments between // args and `{`. if where_clause_str.is_empty() { @@ -2116,13 +2068,11 @@ fn rewrite_args( variadic: bool, generics_str_contains_newline: bool, ) -> Option { - let mut arg_item_strs = try_opt!( - args.iter() - .map(|arg| { - arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) - }) - .collect::>>() - ); + let mut arg_item_strs = args.iter() + .map(|arg| { + arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) + }) + .collect::>>()?; // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked @@ -2344,7 +2294,7 @@ fn rewrite_generics( shape: Shape, span: Span, ) -> Option { - let g_shape = try_opt!(generics_shape_from_config(context.config, shape, 0)); + let g_shape = generics_shape_from_config(context.config, shape, 0)?; let one_line_width = shape.width.checked_sub(2).unwrap_or(0); rewrite_generics_inner(context, generics, g_shape, one_line_width, span).or_else(|| { rewrite_generics_inner(context, generics, g_shape, 0, span) @@ -2452,7 +2402,7 @@ where config: context.config, }; - let list_str = try_opt!(write_list(&item_vec, &fmt)); + let list_str = write_list(&item_vec, &fmt)?; Some(wrap_generics_with_angle_brackets( context, @@ -2494,12 +2444,10 @@ fn rewrite_trait_bounds( if bounds.is_empty() { return Some(String::new()); } - let bound_str = try_opt!( - bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>() - ); + let bound_str = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; Some(format!(": {}", join_bounds(context, shape, &bound_str))) } @@ -2516,12 +2464,8 @@ fn rewrite_where_clause_rfc_style( let (span_before, span_after) = missing_span_before_after_where(span_end_before_where, where_clause); - let (comment_before, comment_after) = try_opt!(rewrite_comments_before_after_where( - context, - span_before, - span_after, - shape, - )); + let (comment_before, comment_after) = + rewrite_comments_before_after_where(context, span_before, span_after, shape)?; let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { " ".to_owned() @@ -2529,9 +2473,9 @@ fn rewrite_where_clause_rfc_style( "\n".to_owned() + &block_shape.indent.to_string(context.config) }; - let clause_shape = try_opt!(block_shape.block_left(context.config.tab_spaces())); + let clause_shape = block_shape.block_left(context.config.tab_spaces())?; // 1 = `,` - let clause_shape = try_opt!(clause_shape.sub_width(1)); + let clause_shape = clause_shape.sub_width(1)?; // each clause on one line, trailing comma (except if suppress_comma) let span_start = where_clause.predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the @@ -2566,7 +2510,7 @@ fn rewrite_where_clause_rfc_style( preserve_newline: true, config: context.config, }; - let preds_str = try_opt!(write_list(&items.collect::>(), &fmt)); + let preds_str = write_list(&items.collect::>(), &fmt)?; let comment_separator = |comment: &str, shape: Shape| if comment.is_empty() { String::new() @@ -2678,7 +2622,7 @@ fn rewrite_where_clause( preserve_newline: true, config: context.config, }; - let preds_str = try_opt!(write_list(&item_vec, &fmt)); + let preds_str = write_list(&item_vec, &fmt)?; let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two @@ -2722,12 +2666,12 @@ fn rewrite_comments_before_after_where( span_after_where: Span, shape: Shape, ) -> Option<(String, String)> { - let before_comment = try_opt!(rewrite_missing_comment(span_before_where, shape, context)); - let after_comment = try_opt!(rewrite_missing_comment( + let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; + let after_comment = rewrite_missing_comment( span_after_where, shape.block_indent(context.config.tab_spaces()), context, - )); + )?; Some((before_comment, after_comment)) } @@ -2747,12 +2691,12 @@ fn format_generics( used_width: usize, ) -> Option { let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = try_opt!(rewrite_generics(context, generics, shape, span)); + let mut result = rewrite_generics(context, generics, shape, span)?; let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = context.budget(last_line_used_width(&result, offset.width())); let option = WhereClauseOption::snuggled(&result); - let where_clause_str = try_opt!(rewrite_where_clause( + let where_clause_str = rewrite_where_clause( context, &generics.where_clause, brace_style, @@ -2762,7 +2706,7 @@ fn format_generics( Some(span.hi()), generics.span.hi(), option, - )); + )?; result.push_str(&where_clause_str); force_same_line_brace || brace_style == BraceStyle::PreferSameLine || (generics.where_clause.predicates.is_empty() @@ -2795,12 +2739,12 @@ fn format_generics( impl Rewrite for ast::ForeignItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + let attrs_str = self.attrs.rewrite(context, shape)?; // Drop semicolon or it will be interpreted as comment. // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - let item_str = try_opt!(match self.node { + let item_str = match self.node { ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { rewrite_fn_base( context, @@ -2819,7 +2763,7 @@ impl Rewrite for ast::ForeignItem { let mut_str = if is_mutable { "mut " } else { "" }; let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); // 1 = ; - let shape = try_opt!(shape.sub_width(1)); + let shape = shape.sub_width(1)?; ty.rewrite(context, shape).map(|ty_str| { // 1 = space between prefix and type. let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { @@ -2831,7 +2775,7 @@ impl Rewrite for ast::ForeignItem { format!("{}{}{};", prefix, sep, ty_str) }) } - }); + }?; let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) diff --git a/src/lists.rs b/src/lists.rs index e499377e48a..12fb4032094 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -275,7 +275,7 @@ where let indent_str = &formatting.shape.indent.to_string(formatting.config); while let Some((i, item)) = iter.next() { let item = item.as_ref(); - let inner_item = try_opt!(item.item.as_ref()); + let inner_item = item.item.as_ref()?; let first = i == 0; let last = iter.peek().is_none(); let mut separate = !last || trailing_separator; @@ -336,12 +336,8 @@ where // Block style in non-vertical mode. let block_mode = tactic != DefinitiveListTactic::Vertical; // Width restriction is only relevant in vertical mode. - let comment = try_opt!(rewrite_comment( - comment, - block_mode, - formatting.shape, - formatting.config, - )); + let comment = + rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; result.push_str(&comment); if tactic == DefinitiveListTactic::Vertical { @@ -377,12 +373,12 @@ where // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = try_opt!(rewrite_comment( + let formatted_comment = rewrite_comment( comment, true, Shape::legacy(formatting.shape.width, Indent::empty()), formatting.config, - )); + )?; result.push(' '); result.push_str(&formatted_comment); @@ -423,7 +419,7 @@ where rewrite_comment(comment, block_style, comment_shape, formatting.config) }; - let mut formatted_comment = try_opt!(rewrite_post_comment(&mut item_max_width)); + let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; if !formatted_comment.starts_with('\n') { let mut comment_alignment = @@ -432,7 +428,7 @@ where + comment_alignment + 1 > formatting.config.max_width() { item_max_width = None; - formatted_comment = try_opt!(rewrite_post_comment(&mut item_max_width)); + formatted_comment = rewrite_post_comment(&mut item_max_width)?; comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); } for _ in 0..(comment_alignment + 1) { @@ -742,9 +738,10 @@ pub fn struct_lit_shape( suffix_width: usize, ) -> Option<(Option, Shape)> { let v_shape = match context.config.struct_lit_style() { - IndentStyle::Visual => try_opt!( - try_opt!(shape.visual_indent(0).shrink_left(prefix_width)).sub_width(suffix_width) - ), + IndentStyle::Visual => shape + .visual_indent(0) + .shrink_left(prefix_width)? + .sub_width(suffix_width)?, IndentStyle::Block => { let shape = shape.block_indent(context.config.tab_spaces()); Shape { diff --git a/src/macros.rs b/src/macros.rs index 4eaf97dd254..470f1e84fd8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -216,7 +216,7 @@ pub fn rewrite_macro( }) } MacroStyle::Brackets => { - let mac_shape = try_opt!(shape.offset_left(macro_name.len())); + let mac_shape = shape.offset_left(macro_name.len())?; // Handle special case: `vec![expr; expr]` if vec_with_semi { let (lbr, rbr) = if context.config.spaces_within_square_brackets() { @@ -227,8 +227,8 @@ pub fn rewrite_macro( // 6 = `vec!` + `; ` let total_overhead = lbr.len() + rbr.len() + 6; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = try_opt!(arg_vec[0].rewrite(context, nested_shape)); - let rhs = try_opt!(arg_vec[1].rewrite(context, nested_shape)); + let lhs = arg_vec[0].rewrite(context, nested_shape)?; + let rhs = arg_vec[1].rewrite(context, nested_shape)?; if !lhs.contains('\n') && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { @@ -271,13 +271,8 @@ pub fn rewrite_macro( .span_after(mac.span, original_style.opener()), mac.span.hi() - BytePos(1), ); - let rewrite = try_opt!(rewrite_array( - expr_vec.iter(), - sp, - context, - mac_shape, - trailing_comma, - )); + let rewrite = + rewrite_array(expr_vec.iter(), sp, context, mac_shape, trailing_comma)?; Some(format!("{}{}", macro_name, rewrite)) } @@ -299,7 +294,7 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option Option { let mut lines = macro_str.lines(); - let first_line = try_opt!(lines.next().map(|s| s.trim_right())); + let first_line = lines.next().map(|s| s.trim_right())?; let mut trimmed_lines = Vec::with_capacity(16); - let min_prefix_space_width = try_opt!( - lines - .filter_map(|line| { - let prefix_space_width = if is_empty_line(line) { - None - } else { - Some(get_prefix_space_width(context, line)) - }; - trimmed_lines.push((line.trim(), prefix_space_width)); - prefix_space_width - }) - .min() - ); + let min_prefix_space_width = lines + .filter_map(|line| { + let prefix_space_width = if is_empty_line(line) { + None + } else { + Some(get_prefix_space_width(context, line)) + }; + trimmed_lines.push((line.trim(), prefix_space_width)); + prefix_space_width + }) + .min()?; Some( String::from(first_line) + "\n" diff --git a/src/patterns.rs b/src/patterns.rs index 6d289736c51..4df36b87e4d 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -38,14 +38,12 @@ impl Rewrite for Pat { let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. - let width = try_opt!( - shape - .width - .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3) - ); + let width = shape + .width + .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?; format!( " @ {}", - try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent))) + p.rewrite(context, Shape::legacy(width, shape.indent))? ) } None => "".to_owned(), @@ -86,8 +84,7 @@ impl Rewrite for Pat { rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { - let path_str = - try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape)); + let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; rewrite_tuple_pat( pat_vec, dotdot_pos, @@ -101,9 +98,9 @@ impl Rewrite for Pat { PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { // Rewrite all the sub-patterns. let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = slice_pat.as_ref().map(|p| { - Some(format!("{}..", try_opt!(p.rewrite(context, shape)))) - }); + let slice_pat = slice_pat + .as_ref() + .map(|p| Some(format!("{}..", p.rewrite(context, shape)?))); let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. @@ -111,7 +108,7 @@ impl Rewrite for Pat { prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); // Check that all the rewrites succeeded, and if not return None. - let pats = try_opt!(pats); + let pats = pats?; // Unwrap all the sub-strings and join them with commas. let result = if context.config.spaces_within_square_brackets() { @@ -139,14 +136,8 @@ fn rewrite_struct_pat( shape: Shape, ) -> Option { // 2 = ` {` - let path_shape = try_opt!(shape.sub_width(2)); - let path_str = try_opt!(rewrite_path( - context, - PathContext::Expr, - None, - path, - path_shape, - )); + let path_shape = shape.sub_width(2)?; + let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; if fields.is_empty() && !elipses { return Some(format!("{} {{}}", path_str)); @@ -155,12 +146,8 @@ fn rewrite_struct_pat( let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; // 3 = ` { `, 2 = ` }`. - let (h_shape, v_shape) = try_opt!(struct_lit_shape( - shape, - context, - path_str.len() + 3, - elipses_str.len() + 2, - )); + let (h_shape, v_shape) = + struct_lit_shape(shape, context, path_str.len() + 3, elipses_str.len() + 2)?; let items = itemize_list( context.codemap, @@ -179,7 +166,7 @@ fn rewrite_struct_pat( let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); let fmt = struct_lit_formatting(nested_shape, tactic, context, false); - let mut fields_str = try_opt!(write_list(&item_vec, &fmt)); + let mut fields_str = write_list(&item_vec, &fmt)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); if elipses { @@ -215,14 +202,14 @@ impl Rewrite for FieldPat { if self.is_shorthand { pat } else { - let pat_str = try_opt!(pat); + let pat_str = pat?; let id_str = self.ident.to_string(); let one_line_width = id_str.len() + 2 + pat_str.len(); if one_line_width <= shape.width { Some(format!("{}: {}", id_str, pat_str)) } else { let nested_shape = shape.block_indent(context.config.tab_spaces()); - let pat_str = try_opt!(self.pat.rewrite(context, nested_shape)); + let pat_str = self.pat.rewrite(context, nested_shape)?; Some(format!( "{}:\n{}{}", id_str, diff --git a/src/shape.rs b/src/shape.rs index 63910c29707..b5d57997e87 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -229,14 +229,14 @@ impl Shape { pub fn sub_width(&self, width: usize) -> Option { Some(Shape { - width: try_opt!(self.width.checked_sub(width)), + width: self.width.checked_sub(width)?, ..*self }) } pub fn shrink_left(&self, width: usize) -> Option { Some(Shape { - width: try_opt!(self.width.checked_sub(width)), + width: self.width.checked_sub(width)?, indent: self.indent + width, offset: self.offset + width, }) diff --git a/src/string.rs b/src/string.rs index efec7ff2377..c072d3186a2 100644 --- a/src/string.rs +++ b/src/string.rs @@ -67,7 +67,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = try_opt!(shape.width.checked_sub(fmt.opener.len() + ender_length + 1)) + 1; + let max_chars = shape.width.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. diff --git a/src/types.rs b/src/types.rs index 060871df161..c17112c9404 100644 --- a/src/types.rs +++ b/src/types.rs @@ -58,7 +58,7 @@ pub fn rewrite_path( result.push_str(" ") } - let fmt_ty = try_opt!(qself.ty.rewrite(context, shape)); + let fmt_ty = qself.ty.rewrite(context, shape)?; result.push_str(&fmt_ty); if skip_count > 0 { @@ -69,9 +69,9 @@ pub fn rewrite_path( let extra_offset = extra_offset(&result, shape); // 3 = ">::".len() - let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3)); + let shape = shape.shrink_left(extra_offset)?.sub_width(3)?; - result = try_opt!(rewrite_path_segments( + result = rewrite_path_segments( PathContext::Type, result, path.segments.iter().take(skip_count), @@ -79,7 +79,7 @@ pub fn rewrite_path( path.span.hi(), context, shape, - )); + )?; } if context.config.spaces_within_angle_brackets() { @@ -128,15 +128,15 @@ where } let extra_offset = extra_offset(&buffer, shape); - let new_shape = try_opt!(shape.shrink_left(extra_offset)); - let segment_string = try_opt!(rewrite_segment( + let new_shape = shape.shrink_left(extra_offset)?; + let segment_string = rewrite_segment( path_context, segment, &mut span_lo, span_hi, context, new_shape, - )); + )?; buffer.push_str(&segment_string); } @@ -171,12 +171,10 @@ impl<'a> Rewrite for SegmentParam<'a> { TypeDensity::Wide => format!("{} = ", binding.ident), TypeDensity::Compressed => format!("{}=", binding.ident), }; - let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = try_opt!( - binding - .ty - .rewrite(context, Shape::legacy(budget, shape.indent + result.len())) - ); + let budget = shape.width.checked_sub(result.len())?; + let rewrite = binding + .ty + .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; result.push_str(&rewrite); Some(result) } @@ -203,7 +201,7 @@ fn rewrite_segment( shape: Shape, ) -> Option { let ident_len = segment.identifier.to_string().len(); - let shape = try_opt!(shape.shrink_left(ident_len)); + let shape = shape.shrink_left(ident_len)?; let params = if let Some(ref params) = segment.parameters { match **params { @@ -226,12 +224,9 @@ fn rewrite_segment( "" }; - let generics_shape = try_opt!(generics_shape_from_config( - context.config, - shape, - separator.len(), - )); - let one_line_width = try_opt!(shape.width.checked_sub(separator.len() + 2)); + let generics_shape = + generics_shape_from_config(context.config, shape, separator.len())?; + let one_line_width = shape.width.checked_sub(separator.len() + 2)?; let items = itemize_list( context.codemap, param_list.into_iter(), @@ -243,12 +238,8 @@ fn rewrite_segment( span_hi, false, ); - let generics_str = try_opt!(format_generics_item_list( - context, - items, - generics_shape, - one_line_width, - )); + let generics_str = + format_generics_item_list(context, items, generics_shape, one_line_width)?; // Update position of last bracket. *span_lo = next_span_lo; @@ -260,14 +251,14 @@ fn rewrite_segment( Some(ref ty) => FunctionRetTy::Ty(ty.clone()), None => FunctionRetTy::Default(codemap::DUMMY_SP), }; - try_opt!(format_function_type( + format_function_type( data.inputs.iter().map(|x| &**x), &output, false, data.span, context, shape, - )) + )? } _ => String::new(), } @@ -310,7 +301,7 @@ where }; // 2 for () - let budget = try_opt!(shape.width.checked_sub(2)); + let budget = shape.width.checked_sub(2)?; // 1 for ( let offset = match context.config.fn_args_layout() { IndentStyle::Block => { @@ -372,21 +363,21 @@ where config: context.config, }; - let list_str = try_opt!(write_list(&item_vec, &fmt)); + let list_str = write_list(&item_vec, &fmt)?; let ty_shape = match context.config.fn_args_layout() { IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), - IndentStyle::Visual => try_opt!(shape.block_left(4)), + IndentStyle::Visual => shape.block_left(4)?, }; let output = match *output { FunctionRetTy::Ty(ref ty) => { - let type_str = try_opt!(ty.rewrite(context, ty_shape)); + let type_str = ty.rewrite(context, ty_shape)?; format!(" -> {}", type_str) } FunctionRetTy::Default(..) => String::new(), }; - let shape = try_opt!(shape.sub_width(output.len())); + let shape = shape.sub_width(output.len())?; let extendable = !list_str.contains('\n') || list_str.is_empty(); let args = wrap_args_with_parens( context, @@ -424,27 +415,24 @@ impl Rewrite for ast::WherePredicate { ref bounds, .. }) => { - let type_str = try_opt!(bounded_ty.rewrite(context, shape)); + let type_str = bounded_ty.rewrite(context, shape)?; let colon = type_bound_colon(context); if !bound_lifetimes.is_empty() { - let lifetime_str: String = try_opt!( - bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, shape)) - .collect::>>() - ).join(", "); + let lifetime_str: String = bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, shape)) + .collect::>>()? + .join(", "); // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let ty_shape = try_opt!(shape.offset_left(used_width)); - let bounds: Vec<_> = try_opt!( - bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect() - ); + let ty_shape = shape.offset_left(used_width)?; + let bounds = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect::>>()?; let bounds_str = join_bounds(context, ty_shape, &bounds); if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { @@ -461,18 +449,15 @@ impl Rewrite for ast::WherePredicate { } else { let used_width = type_str.len() + colon.len(); let ty_shape = match context.config.where_style() { - Style::Legacy => try_opt!(shape.block_left(used_width)), + Style::Legacy => shape.block_left(used_width)?, Style::Rfc => shape, }; - let bounds: Vec<_> = try_opt!( - bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect() - ); + let bounds = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect::>>()?; let overhead = type_str.len() + colon.len(); - let bounds_str = - join_bounds(context, try_opt!(ty_shape.sub_width(overhead)), &bounds); + let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); format!("{}{}{}", type_str, colon, bounds_str) } @@ -481,24 +466,18 @@ impl Rewrite for ast::WherePredicate { ref lifetime, ref bounds, .. - }) => try_opt!(rewrite_bounded_lifetime( - lifetime, - bounds.iter(), - context, - shape, - )), + }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { - let lhs_ty_str = try_opt!(lhs_ty.rewrite(context, shape)); + let lhs_ty_str = lhs_ty.rewrite(context, shape)?; // 3 = " = ".len() let used_width = 3 + lhs_ty_str.len(); - let budget = try_opt!(shape.width.checked_sub(used_width)); - let rhs_ty_str = try_opt!( - rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width)) - ); + let budget = shape.width.checked_sub(used_width)?; + let rhs_ty_str = + rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; format!("{} = {}", lhs_ty_str, rhs_ty_str) } }; @@ -522,24 +501,22 @@ fn rewrite_bounded_lifetime<'b, I>( where I: ExactSizeIterator, { - let result = try_opt!(lt.rewrite(context, shape)); + let result = lt.rewrite(context, shape)?; if bounds.len() == 0 { Some(result) } else { - let appendix: Vec<_> = try_opt!( - bounds - .into_iter() - .map(|b| b.rewrite(context, shape)) - .collect() - ); + let appendix = bounds + .into_iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); let result = format!( "{}{}{}", result, colon, - join_bounds(context, try_opt!(shape.sub_width(overhead)), &appendix) + join_bounds(context, shape.sub_width(overhead)?, &appendix) ); Some(result) } @@ -554,7 +531,7 @@ impl Rewrite for ast::TyParamBound { ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { Some(format!( "?{}", - try_opt!(tref.rewrite(context, try_opt!(shape.offset_left(1)))) + tref.rewrite(context, shape.offset_left(1)?)? )) } ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), @@ -570,7 +547,9 @@ impl Rewrite for ast::Lifetime { impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs: Vec<_> = try_opt!(self.iter().map(|b| b.rewrite(context, shape)).collect()); + let strs = self.iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; join_bounds(context, shape, &strs).rewrite(context, shape) } } @@ -586,12 +565,10 @@ impl Rewrite for ast::TyParam { result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); - let strs: Vec<_> = try_opt!( - self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect() - ); + let strs = self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; result.push_str(&join_bounds(context, shape, &strs)); } if let Some(ref def) = self.default { @@ -600,9 +577,8 @@ impl Rewrite for ast::TyParam { TypeDensity::Wide => " = ", }; result.push_str(eq_str); - let budget = try_opt!(shape.width.checked_sub(result.len())); - let rewrite = - try_opt!(def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))); + let budget = shape.width.checked_sub(result.len())?; + let rewrite = def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; result.push_str(&rewrite); } @@ -613,19 +589,16 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if !self.bound_lifetimes.is_empty() { - let lifetime_str: String = try_opt!( - self.bound_lifetimes - .iter() - .map(|lt| lt.rewrite(context, shape)) - .collect::>>() - ).join(", "); + let lifetime_str: String = self.bound_lifetimes + .iter() + .map(|lt| lt.rewrite(context, shape)) + .collect::>>()? + .join(", "); // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; - let path_str = try_opt!( - self.trait_ref - .rewrite(context, try_opt!(shape.offset_left(extra_offset))) - ); + let path_str = self.trait_ref + .rewrite(context, shape.offset_left(extra_offset)?)?; Some( if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { @@ -663,34 +636,32 @@ impl Rewrite for ast::Ty { let mut_len = mut_str.len(); Some(match *lifetime { Some(ref lifetime) => { - let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len)); - let lt_str = try_opt!(lifetime.rewrite( + let lt_budget = shape.width.checked_sub(2 + mut_len)?; + let lt_str = lifetime.rewrite( context, Shape::legacy(lt_budget, shape.indent + 2 + mut_len), - )); + )?; let lt_len = lt_str.len(); - let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len)); + let budget = shape.width.checked_sub(2 + mut_len + lt_len)?; format!( "&{} {}{}", lt_str, mut_str, - try_opt!(mt.ty.rewrite( + mt.ty.rewrite( context, - Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len), - )) + Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len) + )? ) } None => { - let budget = try_opt!(shape.width.checked_sub(1 + mut_len)); + let budget = shape.width.checked_sub(1 + mut_len)?; format!( "&{}{}", mut_str, - try_opt!( - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 1 + mut_len), - ) - ) + mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 1 + mut_len), + )? ) } }) @@ -698,7 +669,7 @@ impl Rewrite for ast::Ty { // FIXME: we drop any comments here, even though it's a silly place to put // comments. ast::TyKind::Paren(ref ty) => { - let budget = try_opt!(shape.width.checked_sub(2)); + let budget = shape.width.checked_sub(2)?; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_parens() { format!("( {} )", ty_str) @@ -708,9 +679,9 @@ impl Rewrite for ast::Ty { } ast::TyKind::Slice(ref ty) => { let budget = if context.config.spaces_within_square_brackets() { - try_opt!(shape.width.checked_sub(4)) + shape.width.checked_sub(4)? } else { - try_opt!(shape.width.checked_sub(2)) + shape.width.checked_sub(2)? }; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| if context.config.spaces_within_square_brackets() { @@ -772,18 +743,17 @@ fn rewrite_bare_fn( // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. - result.push_str(&try_opt!( - bare_fn - .lifetimes - .iter() - .map(|l| { - l.rewrite( - context, - Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4), - ) - }) - .collect::>>() - ).join(", ")); + result.push_str(&bare_fn + .lifetimes + .iter() + .map(|l| { + l.rewrite( + context, + Shape::legacy(shape.width.checked_sub(6)?, shape.indent + 4), + ) + }) + .collect::>>()? + .join(", ")); result.push_str("> "); } @@ -797,16 +767,16 @@ fn rewrite_bare_fn( result.push_str("fn"); - let func_ty_shape = try_opt!(shape.offset_left(result.len())); + let func_ty_shape = shape.offset_left(result.len())?; - let rewrite = try_opt!(format_function_type( + let rewrite = format_function_type( bare_fn.decl.inputs.iter(), &bare_fn.decl.output, bare_fn.decl.variadic, span, context, func_ty_shape, - )); + )?; result.push_str(&rewrite); diff --git a/src/utils.rs b/src/utils.rs index a01e22aae29..d1324f1dafa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -343,15 +343,6 @@ macro_rules! impl_enum_serialize_and_deserialize { }; } -// Same as try!, but for Option -#[macro_export] -macro_rules! try_opt { - ($expr:expr) => (match $expr { - Some(val) => val, - None => { return None; } - }) -} - macro_rules! msg { ($($arg:tt)*) => ( match writeln!(&mut ::std::io::stderr(), $($arg)* ) { diff --git a/src/vertical.rs b/src/vertical.rs index 4f19cd17921..f5636672422 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -48,7 +48,7 @@ impl AlignedItem for ast::StructField { } fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + let attrs_str = self.attrs.rewrite(context, shape)?; let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) } else { @@ -88,7 +88,7 @@ impl AlignedItem for ast::Field { } fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = try_opt!(self.attrs.rewrite(context, shape)); + let attrs_str = self.attrs.rewrite(context, shape)?; let name = &self.ident.node.to_string(); let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) @@ -166,24 +166,13 @@ pub fn rewrite_with_alignment( }; let init_span = mk_sp(span.lo(), init_last_pos); let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; - let result = try_opt!(rewrite_aligned_items_inner( - context, - init, - init_span, - shape.indent, - one_line_width, - )); + let result = + rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?; if rest.is_empty() { Some(result + spaces) } else { let rest_span = mk_sp(init_last_pos, span.hi()); - let rest_str = try_opt!(rewrite_with_alignment( - rest, - context, - shape, - rest_span, - one_line_width, - )); + let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; Some( result + spaces + "\n" + &shape @@ -228,7 +217,7 @@ fn rewrite_aligned_items_inner( ) -> Option { let item_indent = offset.block_indent(context.config); // 1 = "," - let item_shape = try_opt!(Shape::indented(item_indent, context.config).sub_width(1)); + let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; let (mut field_prefix_max_width, field_prefix_min_width) = struct_field_preix_max_min_width(context, fields, item_shape); let max_diff = field_prefix_max_width diff --git a/src/visitor.rs b/src/visitor.rs index ddbbbd49eaa..80faa78a6fa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -811,12 +811,10 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::List(ref list) => { let name = self.name.as_str(); // 1 = `(`, 2 = `]` and `)` - let item_shape = try_opt!( - shape - .visual_indent(0) - .shrink_left(name.len() + 1) - .and_then(|s| s.sub_width(2)) - ); + let item_shape = shape + .visual_indent(0) + .shrink_left(name.len() + 1) + .and_then(|s| s.sub_width(2))?; let items = itemize_list( context.codemap, list.iter(), @@ -839,13 +837,13 @@ impl Rewrite for ast::MetaItem { preserve_newline: false, config: context.config, }; - format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt))) + format!("{}({})", name, write_list(&item_vec, &fmt)?) } ast::MetaItemKind::NameValue(ref literal) => { let name = self.name.as_str(); // 3 = ` = ` - let lit_shape = try_opt!(shape.shrink_left(name.len() + 3)); - let value = try_opt!(rewrite_literal(context, literal, lit_shape)); + let lit_shape = shape.shrink_left(name.len() + 3)?; + let value = rewrite_literal(context, literal, lit_shape)?; format!("{} = {}", name, value) } }) @@ -872,8 +870,8 @@ impl Rewrite for ast::Attribute { return Some(snippet); } // 1 = `[` - let shape = try_opt!(shape.offset_left(prefix.len() + 1)); - try_opt!(self.meta()) + let shape = shape.offset_left(prefix.len() + 1)?; + self.meta()? .rewrite(context, shape) .map(|rw| format!("{}[{}]", prefix, rw)) } @@ -894,7 +892,7 @@ impl<'a> Rewrite for [ast::Attribute] { let mut insert_new_line = true; let mut is_prev_sugared_doc = false; while let Some((i, a)) = iter.next() { - let a_str = try_opt!(a.rewrite(context, shape)); + let a_str = a.rewrite(context, shape)?; // Write comments and blank lines between attributes. if i > 0 { @@ -926,12 +924,12 @@ impl<'a> Rewrite for [ast::Attribute] { (false, false) }; - let comment = try_opt!(recover_missing_comment_in_span( + let comment = recover_missing_comment_in_span( mk_sp(self[i - 1].span.hi(), a.span.lo()), shape.with_max_width(context.config), context, 0, - )); + )?; if !comment.is_empty() { if multi_line_before { @@ -966,7 +964,7 @@ impl<'a> Rewrite for [ast::Attribute] { Some(&(_, next_attr)) if is_derive(next_attr) => insert_new_line = false, // If not, rewrite the merged derives. _ => { - result.push_str(&try_opt!(format_derive(context, &derive_args, shape))); + result.push_str(&format_derive(context, &derive_args, shape)?); derive_args.clear(); } } @@ -988,7 +986,7 @@ fn format_derive(context: &RewriteContext, derive_args: &[String], shape: Shape) let mut result = String::with_capacity(128); result.push_str("#[derive("); // 11 = `#[derive()]` - let initial_budget = try_opt!(shape.width.checked_sub(11)); + let initial_budget = shape.width.checked_sub(11)?; let mut budget = initial_budget; let num = derive_args.len(); for (i, a) in derive_args.iter().enumerate() { -- cgit 1.4.1-3-g733a5 From 47cf912c2c95675bc39bbd1045724ede4a0e6f9d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 5 Oct 2017 21:05:28 +0900 Subject: Use push_str() instead of write!() --- src/expr.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 083aee5a225..f41feb52631 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -10,7 +10,6 @@ use std::cmp::min; use std::borrow::Cow; -use std::fmt::Write; use std::iter::{repeat, ExactSizeIterator}; use syntax::{ast, ptr}; @@ -1351,14 +1350,14 @@ impl<'a> Rewrite for ControlFlow<'a> { ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, _ => " ", }; - write!( - &mut result, + + result.push_str(&format!( "{}else{}", between_kwd_else_block_comment .as_ref() .map_or(between_sep, |s| &**s), - after_else_comment.as_ref().map_or(after_sep, |s| &**s) - ).ok()?; + after_else_comment.as_ref().map_or(after_sep, |s| &**s), + )); result.push_str(&rewrite?); } -- cgit 1.4.1-3-g733a5 From 35cd72d9890d4800886de4fd3e4a4f245c3931d2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 21:48:05 +0900 Subject: Use correct budget for the last child of chain --- src/chains.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 74c43d783b7..c5a1644b67a 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -182,7 +182,17 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, nested_shape); + let last_shape = if rewrites.is_empty() { + // We only have a single child. + first_child_shape + } else { + match context.config.chain_indent() { + IndentStyle::Visual => other_child_shape.sub_width(shape.rhs_overhead(context.config))?, + IndentStyle::Block => other_child_shape, + } + }; + let last_shape = last_shape.sub_width(suffix_try_num)?; + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexr { parent_shape.offset_left(almost_total).map(|shape| { if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { -- cgit 1.4.1-3-g733a5 From 02ef2ee8de4c46be7a125c965e064d7a662cdc55 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 21:48:45 +0900 Subject: Fix a typo --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c5a1644b67a..d5016d8db26 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -198,7 +198,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { let line_count = rw.lines().count(); let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if (line_count >= 5 && fits_single_line) || extend_last_subexr { + if fits_single_line && (line_count >= 5 && fits_single_line || extend_last_subexr) { (Some(rw), true) } else { match rewrite_last() { -- cgit 1.4.1-3-g733a5 From 2b6e50436c6bd8826067a08688c74755d57b7b75 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 21:51:15 +0900 Subject: Run wrap_str() only when chain_indent is set to "Visual" --- src/chains.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index d5016d8db26..30a9444d4ae 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -266,7 +266,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ) }; let result = format!("{}{}", result, repeat_try(suffix_try_num)); - wrap_str(result, context.config.max_width(), shape) + if context.config.chain_indent() == IndentStyle::Visual { + wrap_str(result, context.config.max_width(), shape) + } else { + Some(result) + } } fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { -- cgit 1.4.1-3-g733a5 From dde0cdabe04ec5773e36d12b20649dc8f8b0f55c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 21:58:29 +0900 Subject: Remove String::rewrite() --- src/utils.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index a719525d4d9..4b8ceadbf20 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, Neste Path, Visibility}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; -use rewrite::{Rewrite, RewriteContext}; +use rewrite::RewriteContext; use shape::Shape; // When we get scoped annotations, we should have rustfmt::skip. @@ -425,12 +425,6 @@ pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option Option { - wrap_str(self, context.config.max_width(), shape).map(ToOwned::to_owned) - } -} - #[inline] pub fn colon_spaces(before: bool, after: bool) -> &'static str { match (before, after) { -- cgit 1.4.1-3-g733a5 From dd5ed5393098dc4a39558f119d7a2d862dc211ae Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:01:44 +0900 Subject: Remove calling rewrite() against String --- src/expr.rs | 4 +--- src/types.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f41feb52631..dbaf1cceefc 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -718,9 +718,7 @@ fn rewrite_closure_block( if block_str.matches('\n').count() <= block_threshold as usize && !need_block_indent(&block_str, shape) { - if let Some(block_str) = block_str.rewrite(context, shape) { - return Some(format!("{} {}", prefix, block_str)); - } + return Some(format!("{} {}", prefix, block_str)); } } } diff --git a/src/types.rs b/src/types.rs index c17112c9404..1b70b5448d9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -550,7 +550,7 @@ impl Rewrite for ast::TyParamBounds { let strs = self.iter() .map(|b| b.rewrite(context, shape)) .collect::>>()?; - join_bounds(context, shape, &strs).rewrite(context, shape) + Some(join_bounds(context, shape, &strs)) } } -- cgit 1.4.1-3-g733a5 From c046a261a80277441a59d339a3b5afb3a92d3d29 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:04:02 +0900 Subject: Change the signature of wrap_str() --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 4b8ceadbf20..e4ed4b884e2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -392,7 +392,7 @@ macro_rules! skip_out_of_file_lines_range_visitor { // Wraps string-like values in an Option. Returns Some when the string adheres // to the Rewrite constraints defined for the Rewrite trait and else otherwise. -pub fn wrap_str>(s: S, max_width: usize, shape: Shape) -> Option { +pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { { let snippet = s.as_ref(); -- cgit 1.4.1-3-g733a5 From d38b3acee148f1ee5b4b7284bc68f89e5c09bbfc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:14:33 +0900 Subject: Simplify wrap_str() --- src/utils.rs | 56 +++++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index e4ed4b884e2..649a6070fd2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -390,39 +390,37 @@ macro_rules! skip_out_of_file_lines_range_visitor { } } -// Wraps string-like values in an Option. Returns Some when the string adheres -// to the Rewrite constraints defined for the Rewrite trait and else otherwise. +// Wraps String in an Option. Returns Some when the string adheres to the +// Rewrite constraints defined for the Rewrite trait and else otherwise. pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { - { - let snippet = s.as_ref(); - - if !snippet.is_empty() { - if !snippet.contains('\n') && snippet.len() > shape.width { - return None; - } else { - let mut lines = snippet.lines(); - - if lines.next().unwrap().len() > shape.width { - return None; - } - - // The other lines must fit within the maximum width. - if lines.any(|line| line.len() > max_width) { - return None; - } + if is_valid_str(&s, max_width, shape) { + Some(s) + } else { + None + } +} - // `width` is the maximum length of the last line, excluding - // indentation. - // A special check for the last line, since the caller may - // place trailing characters on this line. - if snippet.lines().rev().next().unwrap().len() > shape.used_width() + shape.width { - return None; - } - } +fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { + if !snippet.is_empty() { + // First line must fits with `shape.width`. + if first_line_width(snippet) > shape.width { + return false; + } + // If the snippet does not include newline, we are done. + if first_line_width(snippet) == snippet.len() { + return true; + } + // The other lines must fit within the maximum width. + if snippet.lines().skip(1).any(|line| line.len() > max_width) { + return false; + } + // A special check for the last line, since the caller may + // place trailing characters on this line. + if last_line_width(snippet) > shape.used_width() + shape.width { + return false; } } - - Some(s) + true } #[inline] -- cgit 1.4.1-3-g733a5 From ed7ceebfe07c674933b002beda88391ad5cd6066 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:17:01 +0900 Subject: Faster last_line_extendable() --- src/utils.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index 649a6070fd2..3106df9ed8b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -171,12 +171,18 @@ pub fn trimmed_last_line_width(s: &str) -> usize { #[inline] pub fn last_line_extendable(s: &str) -> bool { - s.lines().last().map_or(false, |s| { - s.ends_with("\"#") - || s.trim() - .chars() - .all(|c| c == ')' || c == ']' || c == '}' || c == '?') - }) + if s.ends_with("\"#") { + return true; + } + for c in s.chars().rev() { + match c { + ')' | ']' | '}' | '?' => continue, + '\n' => break, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + true } #[inline] -- cgit 1.4.1-3-g733a5 From 1097a431bf758efe8b95e8cd7de1df140af3402b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:21:53 +0900 Subject: Change return type of Indent::to_string() to Cow<'static, str> --- src/shape.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/shape.rs b/src/shape.rs index b5d57997e87..fffbe2b9913 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; use std::ops::{Add, Sub}; use Config; @@ -21,6 +22,10 @@ pub struct Indent { pub alignment: usize, } +// INDENT_BUFFER.len() = 80 +const INDENT_BUFFER_LEN: usize = 80; +const INDENT_BUFFER: &str = + " "; impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { Indent { @@ -68,21 +73,25 @@ impl Indent { self.block_indent + self.alignment } - pub fn to_string(&self, config: &Config) -> String { + pub fn to_string(&self, config: &Config) -> Cow<'static, str> { let (num_tabs, num_spaces) = if config.hard_tabs() { (self.block_indent / config.tab_spaces(), self.alignment) } else { (0, self.width()) }; let num_chars = num_tabs + num_spaces; - let mut indent = String::with_capacity(num_chars); - for _ in 0..num_tabs { - indent.push('\t') - } - for _ in 0..num_spaces { - indent.push(' ') + if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN { + Cow::from(&INDENT_BUFFER[0..num_chars]) + } else { + let mut indent = String::with_capacity(num_chars); + for _ in 0..num_tabs { + indent.push('\t') + } + for _ in 0..num_spaces { + indent.push(' ') + } + Cow::from(indent) } - indent } } -- cgit 1.4.1-3-g733a5 From 427b4a831da4f0186049c627069c2376c370a76e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:29:53 +0900 Subject: Get rid of choose_first_connector() --- src/chains.rs | 47 ++++++++--------------------------------------- 1 file changed, 8 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 30a9444d4ae..289d05cf879 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -239,16 +239,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - connector.as_str() }; - let subexpr_num = subexpr_list.len(); let result = if is_small_parent && rewrites.len() > 1 { - let second_connector = choose_first_connector( - context, - &rewrites[0], - &rewrites[1], - &connector, - &subexpr_list[..subexpr_num - 1], - false, - ); + let second_connector = if fits_single_line || rewrites[1] == "?" + || last_line_extendable(&rewrites[0]) + || context.config.chain_indent() == IndentStyle::Visual + { + "" + } else { + &connector + }; format!( "{}{}{}{}{}", parent_rewrite, @@ -273,10 +272,6 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } } -fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool { - context.config.chain_indent() == IndentStyle::Block && last_line_extendable(parent_str) -} - // True if the chain is only `?`s. fn chain_only_try(exprs: &[ast::Expr]) -> bool { exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { @@ -445,32 +440,6 @@ fn is_try(expr: &ast::Expr) -> bool { } } -fn choose_first_connector<'a>( - context: &RewriteContext, - parent_str: &str, - first_child_str: &str, - connector: &'a str, - subexpr_list: &[ast::Expr], - extend: bool, -) -> &'a str { - if subexpr_list.is_empty() { - "" - } else if extend || subexpr_list.last().map_or(false, is_try) - || is_extendable_parent(context, parent_str) - { - // 1 = ";", being conservative here. - if last_line_width(parent_str) + first_line_width(first_child_str) + 1 - <= context.config.max_width() - { - "" - } else { - connector - } - } else { - connector - } -} - fn rewrite_method_call( method_name: ast::Ident, types: &[ptr::P], -- cgit 1.4.1-3-g733a5 From 7359d3ad34d09539fa6340cecf8d8bb56e4ceb72 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:30:12 +0900 Subject: Simplify join_rewrites() --- src/chains.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 289d05cf879..b55ce0982e8 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -254,14 +254,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - first_connector, rewrites[0], second_connector, - join_rewrites(&rewrites[1..], &subexpr_list[..subexpr_num - 1], &connector) + join_rewrites(&rewrites[1..], &connector) ) } else { format!( "{}{}{}", parent_rewrite, first_connector, - join_rewrites(&rewrites, subexpr_list, &connector) + join_rewrites(&rewrites, &connector) ) }; let result = format!("{}{}", result, repeat_try(suffix_try_num)); @@ -297,17 +297,14 @@ fn rewrite_try( Some(format!("{}{}", sub_expr, repeat_try(try_count))) } -fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String { +fn join_rewrites(rewrites: &[String], connector: &str) -> String { let mut rewrite_iter = rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); - let mut subexpr_iter = subexps.iter().rev(); - subexpr_iter.next(); - for (rewrite, expr) in rewrite_iter.zip(subexpr_iter) { - match expr.node { - ast::ExprKind::Try(_) => (), - _ => result.push_str(connector), - }; + for rewrite in rewrite_iter { + if rewrite != "?" { + result.push_str(connector); + } result.push_str(&rewrite[..]); } -- cgit 1.4.1-3-g733a5 From 923a7bc1d9fb7303eab061a1e2463794e03f0bcb Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:31:38 +0900 Subject: Update doc comments in chains.rs --- src/chains.rs | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index b55ce0982e8..570f78e5b32 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -24,6 +24,15 @@ /// alignment). /// E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the /// following values of `chain_indent`: +/// Block: +/// ``` +/// let foo = { +/// aaaa; +/// bbb; +/// ccc +/// }.bar +/// .baz(); +/// ``` /// Visual: /// ``` /// let foo = { @@ -34,46 +43,20 @@ /// .bar /// .baz(); /// ``` -/// Inherit: -/// ``` -/// let foo = { -/// aaaa; -/// bbb; -/// ccc -/// } -/// .bar -/// .baz(); -/// ``` -/// Tabbed: -/// ``` -/// let foo = { -/// aaaa; -/// bbb; -/// ccc -/// } -/// .bar -/// .baz(); -/// ``` /// /// If the first item in the chain is a block expression, we align the dots with /// the braces. -/// Visual: -/// ``` -/// let a = foo.bar -/// .baz() -/// .qux -/// ``` -/// Inherit: +/// Block: /// ``` /// let a = foo.bar -/// .baz() -/// .qux +/// .baz() +/// .qux /// ``` -/// Tabbed: +/// Visual: /// ``` /// let a = foo.bar -/// .baz() -/// .qux +/// .baz() +/// .qux /// ``` use shape::Shape; -- cgit 1.4.1-3-g733a5 From eb8566f3ee3caf39b3610df96219588ce2fffb21 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 7 Oct 2017 22:38:32 +0900 Subject: Run cargo fmt rustfmt removes trailing comma from a function call. This could be a bug. --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 1b70b5448d9..d73e8653121 100644 --- a/src/types.rs +++ b/src/types.rs @@ -660,7 +660,7 @@ impl Rewrite for ast::Ty { mut_str, mt.ty.rewrite( context, - Shape::legacy(budget, shape.indent + 1 + mut_len), + Shape::legacy(budget, shape.indent + 1 + mut_len) )? ) } -- cgit 1.4.1-3-g733a5 From 55fc5b5ec2c43da2aa876c0d032411dee168e800 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 8 Oct 2017 22:35:45 +0900 Subject: Get rid of rewrite_struct_field_type() --- src/items.rs | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 90b75a82f62..d731cb8858a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1362,20 +1362,6 @@ pub fn rewrite_struct_field_prefix( }) } -fn rewrite_struct_field_type( - context: &RewriteContext, - last_line_width: usize, - field: &ast::StructField, - spacing: &str, - shape: Shape, -) -> Option { - let ty_shape = shape.offset_left(last_line_width + spacing.len())?; - field - .ty - .rewrite(context, ty_shape) - .map(|ty| format!("{}{}", spacing, ty)) -} - impl Rewrite for ast::StructField { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { rewrite_struct_field(context, self, shape, 0) @@ -1427,10 +1413,10 @@ pub fn rewrite_struct_field( if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { spacing.push(' '); } - let ty_rewritten = rewrite_struct_field_type(context, overhead, field, &spacing, shape); - if let Some(ref ty) = ty_rewritten { + let ty_shape = shape.offset_left(overhead + spacing.len())?; + if let Some(ref ty) = field.ty.rewrite(context, ty_shape) { if !ty.contains('\n') { - return Some(attr_prefix + ty); + return Some(attr_prefix + &spacing + ty); } } -- cgit 1.4.1-3-g733a5 From 530a845d2fab69282326a7a5d0f8b603012932f3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 8 Oct 2017 22:36:03 +0900 Subject: Simplify multiline case in rewrite_struct_field() --- src/items.rs | 40 +++++++++++----------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d731cb8858a..be22db49fbf 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1421,36 +1421,18 @@ pub fn rewrite_struct_field( } // We must use multiline. - let last_line_width = last_line_width(&prefix); - let ty_rewritten = rewrite_struct_field_type(context, last_line_width, field, &spacing, shape); - - let type_offset = shape.indent.block_indent(context.config); - let rewrite_type_in_next_line = || { - field - .ty - .rewrite(context, Shape::indented(type_offset, context.config)) - }; + let new_shape = shape.with_max_width(context.config); + let ty_rewritten = field.ty.rewrite(context, new_shape)?; - let field_str = match ty_rewritten { - // If we start from the next line and type fits in a single line, then do so. - Some(ref ty) => match rewrite_type_in_next_line() { - Some(ref new_ty) if !new_ty.contains('\n') => format!( - "{}\n{}{}", - prefix, - type_offset.to_string(context.config), - &new_ty - ), - _ => prefix + ty, - }, - _ => { - let ty = rewrite_type_in_next_line()?; - format!( - "{}\n{}{}", - prefix, - type_offset.to_string(context.config), - &ty - ) - } + let field_str = if prefix.is_empty() { + ty_rewritten + } else if prefix.len() + first_line_width(&ty_rewritten) + 1 <= shape.width { + prefix + " " + &ty_rewritten + } else { + let type_offset = shape.indent.block_indent(context.config); + let nested_shape = Shape::indented(type_offset, context.config); + let nested_ty = field.ty.rewrite(context, nested_shape)?; + prefix + "\n" + &type_offset.to_string(context.config) + &nested_ty }; combine_strs_with_missing_comments( context, -- cgit 1.4.1-3-g733a5 From c7250d18b1bf4a91cb95535135b3eacf096d8906 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 9 Oct 2017 22:44:00 +0900 Subject: Fix a typo --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 570f78e5b32..38d015322ce 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -181,7 +181,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { let line_count = rw.lines().count(); let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if fits_single_line && (line_count >= 5 && fits_single_line || extend_last_subexr) { + if fits_single_line && (line_count >= 5 || extend_last_subexr) { (Some(rw), true) } else { match rewrite_last() { -- cgit 1.4.1-3-g733a5 From a1cfacdb12a475d05004249a1d00c612b0e27e5b Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 9 Oct 2017 20:56:16 +0200 Subject: output --dump-default-config to stdout if no path is given closes #1988 --- src/bin/rustfmt.rs | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5b891dfd1db..d1c04de8323 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -21,7 +21,7 @@ use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use getopts::{Matches, Options}; +use getopts::{HasArg, Matches, Occur, Options}; use rustfmt::{run, Input, Summary}; use rustfmt::file_lines::FileLines; @@ -44,8 +44,8 @@ enum Operation { Version, /// Print detailed configuration help. ConfigHelp, - /// Output default config to a file - ConfigOutputDefault { path: String }, + /// Output default config to a file, or stdout if None + ConfigOutputDefault { path: Option }, /// No file specified, read from stdin Stdin { input: String, @@ -125,11 +125,14 @@ fn make_opts() -> Options { "config-help", "show details of rustfmt configuration options", ); - opts.optopt( + opts.opt( "", "dump-default-config", - "Dumps the default configuration to a file and exits.", + "Dumps the default configuration to a file and exits. PATH defaults to rustfmt.toml if \ + omitted.", "PATH", + HasArg::Maybe, + Occur::Optional, ); opts.optopt( "", @@ -172,9 +175,13 @@ fn execute(opts: &Options) -> FmtResult { Ok(Summary::default()) } Operation::ConfigOutputDefault { path } => { - let mut file = File::create(path)?; let toml = Config::default().all_options().to_toml()?; - file.write_all(toml.as_bytes())?; + if let Some(path) = path { + let mut file = File::create(path)?; + file.write_all(toml.as_bytes())?; + } else { + io::stdout().write_all(toml.as_bytes())?; + } Ok(Summary::default()) } Operation::Stdin { input, config_path } => { @@ -327,8 +334,20 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::ConfigHelp); } - if let Some(path) = matches.opt_str("dump-default-config") { - return Ok(Operation::ConfigOutputDefault { path }); + if matches.opt_present("dump-default-config") { + // NOTE for some reason when configured with HasArg::Maybe + Occur::Optional opt_default + // doesn't recognize `--foo bar` as a long flag with an argument but as a long flag with no + // argument *plus* a free argument. Thus we check for that case in this branch -- this is + // required for backward compatibility. + if let Some(path) = matches.free.get(0) { + return Ok(Operation::ConfigOutputDefault { + path: Some(path.clone()), + }); + } else { + return Ok(Operation::ConfigOutputDefault { + path: matches.opt_str("dump-default-config"), + }); + } } if matches.opt_present("version") { -- cgit 1.4.1-3-g733a5 From 0c36c59175929a634f0619664929c1f67a22bf7b Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 9 Oct 2017 23:07:53 +0200 Subject: add `required-version` option to rustfmt.toml This option specifies the rustfmt version that *must* be used to format the code. Trying to use a different version raises an error. closes #1505 --- src/bin/rustfmt.rs | 12 +++++++++++- src/config.rs | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5b891dfd1db..bbaeb1fcc44 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -195,7 +195,13 @@ fn execute(opts: &Options) -> FmtResult { } } - Ok(run(Input::Text(input), &config)) + let mut error_summary = Summary::default(); + if config.version_meets_requirement(&mut error_summary) { + error_summary.add(run(Input::Text(input), &config)); + } + + Ok(error_summary) + } Operation::Format { files, @@ -247,6 +253,10 @@ fn execute(opts: &Options) -> FmtResult { config = config_tmp; } + if !config.version_meets_requirement(&mut error_summary) { + break + } + options.clone().apply_to(&mut config); error_summary.add(run(Input::File(file), &config)); } diff --git a/src/config.rs b/src/config.rs index f76d13e5dc7..778c445d2f6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -18,6 +18,7 @@ use std::path::{Path, PathBuf}; use file_lines::FileLines; use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; +use Summary; macro_rules! configuration_option_enum{ ($e:ident: $( $x:ident ),+ $(,)*) => { @@ -272,6 +273,23 @@ macro_rules! create_config { } impl Config { + pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool { + if self.was_set().required_version() { + let version = env!("CARGO_PKG_VERSION"); + let required_version = self.required_version(); + if version != required_version { + println!( + "Error: rustfmt version ({}) doesn't match the required version ({})", + version, + required_version, + ); + error_summary.add_formatting_error(); + return false; + } + } + + true + } $( pub fn $i(&self) -> $ty { @@ -622,6 +640,8 @@ create_config! { merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one"; binop_separator: SeparatorPlace, SeparatorPlace::Front, "Where to put a binary operator when a binary expression goes multiline."; + required_version: String, "".to_owned(), + "Require a specific version of rustfmt." } #[cfg(test)] -- cgit 1.4.1-3-g733a5 From 16a478368c8dcc0c0ee47372a9f663b23d28b097 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 10 Oct 2017 21:20:57 +0300 Subject: Fix breakage from `dyn Trait` --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 311192889d3..8c8627d7a71 100644 --- a/src/types.rs +++ b/src/types.rs @@ -652,7 +652,7 @@ impl Rewrite for ast::TraitRef { impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - ast::TyKind::TraitObject(ref bounds) => bounds.rewrite(context, shape), + ast::TyKind::TraitObject(ref bounds, ..) => bounds.rewrite(context, shape), ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { Mutability::Mutable => "*mut ", -- cgit 1.4.1-3-g733a5 From d2bf5b8068582bcc414eac6d2d973f9bfbb133e0 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Oct 2017 22:36:41 +0200 Subject: run cargo fmt --- src/bin/rustfmt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index bbaeb1fcc44..5a6cb3e6e16 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -201,7 +201,6 @@ fn execute(opts: &Options) -> FmtResult { } Ok(error_summary) - } Operation::Format { files, @@ -254,7 +253,7 @@ fn execute(opts: &Options) -> FmtResult { } if !config.version_meets_requirement(&mut error_summary) { - break + break; } options.clone().apply_to(&mut config); -- cgit 1.4.1-3-g733a5 From 77584e507c180ee8adf180300103c0b20767b289 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 10 Oct 2017 22:37:47 +0200 Subject: default required-version to the current rustfmt version --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 778c445d2f6..6fe6bbe7716 100644 --- a/src/config.rs +++ b/src/config.rs @@ -640,7 +640,7 @@ create_config! { merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one"; binop_separator: SeparatorPlace, SeparatorPlace::Front, "Where to put a binary operator when a binary expression goes multiline."; - required_version: String, "".to_owned(), + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), "Require a specific version of rustfmt." } -- cgit 1.4.1-3-g733a5 From f00c556263d66ee49a933b006188176153c6aa6a Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 14 Oct 2017 08:08:52 -0400 Subject: correct --dump-default-config usage string --- src/bin/rustfmt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index d1c04de8323..40ee8e70e94 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -128,8 +128,7 @@ fn make_opts() -> Options { opts.opt( "", "dump-default-config", - "Dumps the default configuration to a file and exits. PATH defaults to rustfmt.toml if \ - omitted.", + "Dumps default configuration to PATH. PATH defaults to stdout, if omitted." "PATH", HasArg::Maybe, Occur::Optional, -- cgit 1.4.1-3-g733a5 From 2bf4747c477ef3b9ee00b2789b5e98fc61aa29ff Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 17 Oct 2017 00:10:19 +0900 Subject: Take width of return type into account --- src/expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index dbaf1cceefc..8bef270cf76 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -585,8 +585,6 @@ fn rewrite_closure_fn_decl( }; let list_str = write_list(&item_vec, &fmt)?; let mut prefix = format!("{}|{}|", mover, list_str); - // 1 = space between `|...|` and body. - let extra_offset = extra_offset(&prefix, shape) + 1; if !ret_str.is_empty() { if prefix.contains('\n') { @@ -597,6 +595,8 @@ fn rewrite_closure_fn_decl( } prefix.push_str(&ret_str); } + // 1 = space between `|...|` and body. + let extra_offset = last_line_width(&prefix) + 1; Some((prefix, extra_offset)) } -- cgit 1.4.1-3-g733a5 From 043ddf146d095ac38ee6353c28c395f50ec3ba76 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 17 Oct 2017 11:13:20 +0900 Subject: Fix a typo --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 40ee8e70e94..e686b584496 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -128,7 +128,7 @@ fn make_opts() -> Options { opts.opt( "", "dump-default-config", - "Dumps default configuration to PATH. PATH defaults to stdout, if omitted." + "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", "PATH", HasArg::Maybe, Occur::Optional, -- cgit 1.4.1-3-g733a5 From 3f11c4b93a8c0cc654c24d60c86809f109101c55 Mon Sep 17 00:00:00 2001 From: Sunjay Varma Date: Sun, 15 Oct 2017 13:28:00 -0400 Subject: Updated rustfmt to account for changes from rust-lang/rust#44766 --- src/items.rs | 15 ++++++++++----- src/visitor.rs | 23 ++++++++++------------- 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index be22db49fbf..f0585592172 100644 --- a/src/items.rs +++ b/src/items.rs @@ -184,25 +184,29 @@ impl<'a> FnSig<'a> { } } - pub fn from_method_sig(method_sig: &'a ast::MethodSig) -> FnSig { + pub fn from_method_sig( + method_sig: &'a ast::MethodSig, + generics: &'a ast::Generics, + ) -> FnSig<'a> { FnSig { unsafety: method_sig.unsafety, constness: method_sig.constness.node, defaultness: ast::Defaultness::Final, abi: method_sig.abi, decl: &*method_sig.decl, - generics: &method_sig.generics, + generics: generics, visibility: ast::Visibility::Inherited, } } pub fn from_fn_kind( fn_kind: &'a visit::FnKind, + generics: &'a ast::Generics, decl: &'a ast::FnDecl, defualtness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { - visit::FnKind::ItemFn(_, generics, unsafety, constness, abi, visibility, _) => FnSig { + visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { decl: decl, generics: generics, abi: abi, @@ -212,7 +216,7 @@ impl<'a> FnSig<'a> { visibility: visibility.clone(), }, visit::FnKind::Method(_, ref method_sig, vis, _) => { - let mut fn_sig = FnSig::from_method_sig(method_sig); + let mut fn_sig = FnSig::from_method_sig(method_sig, generics); fn_sig.defaultness = defualtness; if let Some(vis) = vis { fn_sig.visibility = vis.clone(); @@ -338,6 +342,7 @@ impl<'a> FmtVisitor<'a> { indent: Indent, ident: ast::Ident, sig: &ast::MethodSig, + generics: &ast::Generics, span: Span, ) -> Option { // Drop semicolon or it will be interpreted as comment. @@ -348,7 +353,7 @@ impl<'a> FmtVisitor<'a> { &context, indent, ident, - &FnSig::from_method_sig(sig), + &FnSig::from_method_sig(sig, generics), span, false, false, diff --git a/src/visitor.rs b/src/visitor.rs index 76b23f79285..d678e3c6c0d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -229,6 +229,7 @@ impl<'a> FmtVisitor<'a> { fn visit_fn( &mut self, fk: visit::FnKind, + generics: &ast::Generics, fd: &ast::FnDecl, s: Span, _: ast::NodeId, @@ -238,12 +239,12 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent; let block; let rewrite = match fk { - visit::FnKind::ItemFn(ident, _, _, _, _, _, b) => { + visit::FnKind::ItemFn(ident, _, _, _, _, b) => { block = b; self.rewrite_fn( indent, ident, - &FnSig::from_fn_kind(&fk, fd, defaultness), + &FnSig::from_fn_kind(&fk, generics, fd, defaultness), mk_sp(s.lo(), b.span.lo()), b, ) @@ -253,7 +254,7 @@ impl<'a> FmtVisitor<'a> { self.rewrite_fn( indent, ident, - &FnSig::from_fn_kind(&fk, fd, defaultness), + &FnSig::from_fn_kind(&fk, generics, fd, defaultness), mk_sp(s.lo(), b.span.lo()), b, ) @@ -411,15 +412,8 @@ impl<'a> FmtVisitor<'a> { } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { self.visit_fn( - visit::FnKind::ItemFn( - item.ident, - generics, - unsafety, - constness, - abi, - &item.vis, - body, - ), + visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), + generics, decl, item.span, item.id, @@ -490,12 +484,14 @@ impl<'a> FmtVisitor<'a> { } ast::TraitItemKind::Method(ref sig, None) => { let indent = self.block_indent; - let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, ti.span); + let rewrite = + self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, Some(ref body)) => { self.visit_fn( visit::FnKind::Method(ti.ident, sig, None, body), + &ti.generics, &sig.decl, ti.span, ti.id, @@ -531,6 +527,7 @@ impl<'a> FmtVisitor<'a> { ast::ImplItemKind::Method(ref sig, ref body) => { self.visit_fn( visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), + &ii.generics, &sig.decl, ii.span, ii.id, -- cgit 1.4.1-3-g733a5 From 51d230ead3a79c9c6732beaad94fdc372480c11d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 18 Oct 2017 21:52:02 +0900 Subject: Use trimmed_last_line_width() --- src/chains.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 38d015322ce..43dfd83cc57 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -64,7 +64,8 @@ use config::IndentStyle; use expr::rewrite_call; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; -use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, wrap_str}; +use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, + trimmed_last_line_width, wrap_str}; use std::cmp::min; use std::iter; @@ -125,7 +126,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_child_shape = if extend { let overhead = last_line_width(&parent_rewrite); - let offset = parent_rewrite.lines().rev().next().unwrap().trim().len(); + let offset = trimmed_last_line_width(&parent_rewrite); match context.config.chain_indent() { IndentStyle::Visual => parent_shape.offset_left(overhead)?, IndentStyle::Block => parent_shape.block().offset_left(offset)?, -- cgit 1.4.1-3-g733a5 From ad47a7101203dbeda96b75487a104ff88b499e71 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 18 Oct 2017 21:55:45 +0900 Subject: Do not distinguish between a single-child chain from others `last_shape` is used when rewriting the last child on its own line. --- src/chains.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 43dfd83cc57..6743f605cf6 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -166,25 +166,64 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = if rewrites.is_empty() { - // We only have a single child. - first_child_shape - } else { - match context.config.chain_indent() { - IndentStyle::Visual => other_child_shape.sub_width(shape.rhs_overhead(context.config))?, - IndentStyle::Block => other_child_shape, - } + let last_shape = match context.config.chain_indent() { + IndentStyle::Visual => other_child_shape.sub_width(shape.rhs_overhead(context.config))?, + IndentStyle::Block => other_child_shape, }; let last_shape = last_shape.sub_width(suffix_try_num)?; + + // Rewrite the last child. The last child of a chain requires special treatment. We need to + // know whether 'overflowing' the last child make a better formatting: + // + // A chain with overflowing the last child: + // ``` + // parent.child1.child2.last_child( + // a, + // b, + // c, + // ) + // ``` + // + // A chain without overflowing the last child (in vertical layout): + // ``` + // parent + // .child1 + // .child2 + // .last_child(a, b, c) + // ``` + // + // In particular, overflowing is effective when the last child is a method with a multi-lined + // block-like argument (e.g. closure): + // ``` + // parent.child1.chlid2.last_child(|a, b, c| { + // let x = foo(a, b, c); + // let y = bar(a, b, c); + // + // // ... + // + // result + // }) + // ``` + + // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of + // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexr { + // First we try to 'overflow' the last child and see if it looks better than using + // vertical layout. parent_shape.offset_left(almost_total).map(|shape| { if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + // We allow overflowing here only if both of the following conditions match: + // 1. The entire chain fits in a single line expect the last child. + // 2. `last_chlid_str.lines().count() >= 5`. let line_count = rw.lines().count(); let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if fits_single_line && (line_count >= 5 || extend_last_subexr) { + if fits_single_line && line_count >= 5 { (Some(rw), true) } else { + // We could not know whether overflowing is better than using vertical layout, + // just by looking at the overflowed rewrite. Now we rewrite the last child + // on its own line, and compare two rewrites to choose which is better. match rewrite_last() { Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), Some(ref new_rw) if new_rw.lines().count() >= line_count => { -- cgit 1.4.1-3-g733a5 From 142fc45dbb7735be66ebce9efa88df80b8165175 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 18 Oct 2017 21:58:47 +0900 Subject: Take the width of trailing '?'s into account --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 6743f605cf6..20e0be36fe4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -157,7 +157,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - last_line_width(&parent_rewrite) } else { rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() - }; + } + suffix_try_num; let one_line_budget = if rewrites.is_empty() && !context.config.chain_split_single_child() { shape.width } else { -- cgit 1.4.1-3-g733a5 From 0d359eacd7973e435e27aff8f22d612a69c2e7d0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 18 Oct 2017 22:01:59 +0900 Subject: Cargo fmt --- src/expr.rs | 4 +++- src/items.rs | 24 ++++++++++-------------- src/string.rs | 4 +++- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8bef270cf76..4eaf52681ad 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1871,7 +1871,9 @@ fn rewrite_pat_expr( } else { format!("{} ", matcher) }; - let pat_shape = shape.offset_left(matcher.len())?.sub_width(connector.len())?; + let pat_shape = shape + .offset_left(matcher.len())? + .sub_width(connector.len())?; let pat_string = pat.rewrite(context, pat_shape)?; let result = format!("{}{}{}", matcher, pat_string, connector); return rewrite_assign_rhs(context, result, expr, shape); diff --git a/src/items.rs b/src/items.rs index be22db49fbf..e2a07194f2b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2037,9 +2037,7 @@ fn rewrite_args( generics_str_contains_newline: bool, ) -> Option { let mut arg_item_strs = args.iter() - .map(|arg| { - arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) - }) + .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) .collect::>>()?; // Account for sugary self. @@ -2713,17 +2711,15 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.node { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { - rewrite_fn_base( - context, - shape.indent, - self.ident, - &FnSig::new(fn_decl, generics, self.vis.clone()), - span, - false, - false, - ).map(|(s, _)| format!("{};", s)) - } + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => rewrite_fn_base( + context, + shape.indent, + self.ident, + &FnSig::new(fn_decl, generics, self.vis.clone()), + span, + false, + false, + ).map(|(s, _)| format!("{};", s)), ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. diff --git a/src/string.rs b/src/string.rs index c072d3186a2..9812b8af611 100644 --- a/src/string.rs +++ b/src/string.rs @@ -67,7 +67,9 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = shape.width.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + let max_chars = shape + .width + .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. -- cgit 1.4.1-3-g733a5 From 88f02975a1064e91ffe3e28efe1b744a11a39209 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Thu, 19 Oct 2017 20:49:33 +0100 Subject: Add a simple passing test for diffs. --- src/rustfmt_diff.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 3fb22865385..6884e39141d 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -162,3 +162,23 @@ where } } } + +#[cfg(test)] +mod test { + use super::{make_diff,Mismatch}; + use super::DiffLine::*; + + #[test] + fn simple_diff() { + let src = "one\ntwo\nthree\nfour\nfive\n"; + let dest= "one\ntwo\ntrois\nfour\nfive\n"; + let diff = make_diff(src, dest, 1); + assert_eq!(diff, vec![Mismatch { line_number: 2, + lines: vec![ + Context("two".into()), + Resulting("three".into()), + Expected("trois".into()), + Context("four".into()), + ] }]); + } +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 6282c970cf3dcd0e30c3e1751768cc2d18c7295d Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Thu, 19 Oct 2017 20:55:20 +0100 Subject: Add a failing test of zero context. --- src/rustfmt_diff.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 6884e39141d..644ad7ceeac 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -169,7 +169,7 @@ mod test { use super::DiffLine::*; #[test] - fn simple_diff() { + fn diff_simple() { let src = "one\ntwo\nthree\nfour\nfive\n"; let dest= "one\ntwo\ntrois\nfour\nfive\n"; let diff = make_diff(src, dest, 1); @@ -181,4 +181,16 @@ mod test { Context("four".into()), ] }]); } + + #[test] + fn diff_zerocontext() { + let src = "one\ntwo\nthree\nfour\nfive\n"; + let dest= "one\ntwo\ntrois\nfour\nfive\n"; + let diff = make_diff(src, dest, 0); + assert_eq!(diff, vec![Mismatch { line_number: 3, + lines: vec![ + Resulting("three".into()), + Expected("trois".into()), + ] }]); + } } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 6c1c81bbced8c6d98701ea70845f1626ac703c31 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Thu, 19 Oct 2017 23:03:27 +0100 Subject: Add a test for two nearby chunks (with context). --- src/rustfmt_diff.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 644ad7ceeac..fa3c6305ed8 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -182,6 +182,26 @@ mod test { ] }]); } + #[test] + fn diff_simple2() { + let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n"; + let dest= "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; + let diff = make_diff(src, dest, 1); + assert_eq!(diff, vec![Mismatch { line_number: 2, + lines: vec![ + Context("two".into()), + Resulting("three".into()), + Expected("trois".into()), + Context("four".into()), + ] }, + Mismatch { line_number: 5, + lines: vec![ + Resulting("five".into()), + Expected("cinq".into()), + Context("six".into()), + ] }]); + } + #[test] fn diff_zerocontext() { let src = "one\ntwo\nthree\nfour\nfive\n"; -- cgit 1.4.1-3-g733a5 From f9bcb58eb3f3b6508cd7a24e7728f21fcd8f63b9 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Thu, 19 Oct 2017 23:14:20 +0100 Subject: Add a couple of special cases which fix the zero-context diff case. --- src/rustfmt_diff.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index fa3c6305ed8..d6b021d42d4 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -47,7 +47,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { - if lines_since_mismatch >= context_size { + if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { results.push(mismatch); mismatch = Mismatch::new(line_number - context_queue.len() as u32); } @@ -60,7 +60,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { - if lines_since_mismatch >= context_size { + if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { results.push(mismatch); mismatch = Mismatch::new(line_number - context_queue.len() as u32); } @@ -80,7 +80,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec 0 { context_queue.push_back(str); } -- cgit 1.4.1-3-g733a5 From 2a84352d1df09d04fc38311f49bb4ccb4ad83a91 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Thu, 19 Oct 2017 23:32:27 +0100 Subject: Run rustfmt on the new changes. --- src/rustfmt_diff.rs | 80 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index d6b021d42d4..c0aca68fe2f 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -165,52 +165,72 @@ where #[cfg(test)] mod test { - use super::{make_diff,Mismatch}; + use super::{make_diff, Mismatch}; use super::DiffLine::*; #[test] fn diff_simple() { let src = "one\ntwo\nthree\nfour\nfive\n"; - let dest= "one\ntwo\ntrois\nfour\nfive\n"; + let dest = "one\ntwo\ntrois\nfour\nfive\n"; let diff = make_diff(src, dest, 1); - assert_eq!(diff, vec![Mismatch { line_number: 2, - lines: vec![ - Context("two".into()), - Resulting("three".into()), - Expected("trois".into()), - Context("four".into()), - ] }]); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 2, + lines: vec![ + Context("two".into()), + Resulting("three".into()), + Expected("trois".into()), + Context("four".into()), + ], + }, + ] + ); } #[test] fn diff_simple2() { let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n"; - let dest= "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; + let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; let diff = make_diff(src, dest, 1); - assert_eq!(diff, vec![Mismatch { line_number: 2, - lines: vec![ - Context("two".into()), - Resulting("three".into()), - Expected("trois".into()), - Context("four".into()), - ] }, - Mismatch { line_number: 5, - lines: vec![ - Resulting("five".into()), - Expected("cinq".into()), - Context("six".into()), - ] }]); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 2, + lines: vec![ + Context("two".into()), + Resulting("three".into()), + Expected("trois".into()), + Context("four".into()), + ], + }, + Mismatch { + line_number: 5, + lines: vec![ + Resulting("five".into()), + Expected("cinq".into()), + Context("six".into()), + ], + }, + ] + ); } #[test] fn diff_zerocontext() { let src = "one\ntwo\nthree\nfour\nfive\n"; - let dest= "one\ntwo\ntrois\nfour\nfive\n"; + let dest = "one\ntwo\ntrois\nfour\nfive\n"; let diff = make_diff(src, dest, 0); - assert_eq!(diff, vec![Mismatch { line_number: 3, - lines: vec![ - Resulting("three".into()), - Expected("trois".into()), - ] }]); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 3, + lines: vec![Resulting("three".into()), Expected("trois".into())], + }, + ] + ); } -} \ No newline at end of file +} -- cgit 1.4.1-3-g733a5 From 47a0bef91cdbb6d63263d98fcb837b66a4d64c49 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Thu, 19 Oct 2017 22:52:12 +1300 Subject: Return a more verbose error when formatting a file fails Expands the error message returned if the after_file function fails to also include path_str. This allows users to better identify files that are not being formatted. --- src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 14c50563baa..7834dfd2687 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,7 +325,14 @@ where } visitor.format_separate_mod(module, &*filemap); - has_diff |= after_file(path_str, &mut visitor.buffer)?; + has_diff |= match after_file(path_str, &mut visitor.buffer) { + Ok(result) => result, + Err(e) => { + // Create a new error with path_str to help users see which files failed + let mut err_msg = path_str.to_string() + &": ".to_string() + &e.to_string(); + return Err(io::Error::new(e.kind(), err_msg)); + } + }; result.push((path_str.to_owned(), visitor.buffer)); } -- cgit 1.4.1-3-g733a5 From 108e2cd77642368b8e7bb2d1d53bea9709f1a49d Mon Sep 17 00:00:00 2001 From: Matthew McAllister Date: Thu, 19 Oct 2017 23:58:24 -0700 Subject: Handle `#![rustfmt_skip]` at file top level --- src/lib.rs | 12 ++++++++---- tests/target/skip_mod.rs | 3 +++ 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 tests/target/skip_mod.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 14c50563baa..f9b96d59aca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,7 +137,7 @@ impl FormattingError { .count(); (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) } - _ => (0, 0), // unreachable + _ => unreachable!(), } } } @@ -319,11 +319,15 @@ where let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; // Format inner attributes if available. if !krate.attrs.is_empty() && path == main_file { - visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); + } else { + visitor.format_separate_mod(module, &*filemap); + } } else { visitor.last_pos = filemap.start_pos; - } - visitor.format_separate_mod(module, &*filemap); + visitor.format_separate_mod(module, &*filemap); + }; has_diff |= after_file(path_str, &mut visitor.buffer)?; diff --git a/tests/target/skip_mod.rs b/tests/target/skip_mod.rs new file mode 100644 index 00000000000..38ece8f070d --- /dev/null +++ b/tests/target/skip_mod.rs @@ -0,0 +1,3 @@ +#![rustfmt_skip] +use a :: b +; -- cgit 1.4.1-3-g733a5 From 1853d02ea9be5cb9b126db35eb8fe54434db6d46 Mon Sep 17 00:00:00 2001 From: Matthew McAllister Date: Fri, 20 Oct 2017 02:34:12 -0700 Subject: Handle `#![rustfmt_skip]` in block statements --- src/visitor.rs | 13 ++++++++-- tests/source/skip.rs | 73 ---------------------------------------------------- tests/target/skip.rs | 14 ++++++++++ 3 files changed, 25 insertions(+), 75 deletions(-) delete mode 100644 tests/source/skip.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 76b23f79285..d76677949a4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -150,8 +150,17 @@ impl<'a> FmtVisitor<'a> { } // Format inner attributes if available. - if let Some(attrs) = inner_attrs { - self.visit_attrs(attrs, ast::AttrStyle::Inner); + let skip_rewrite = if let Some(attrs) = inner_attrs { + self.visit_attrs(attrs, ast::AttrStyle::Inner) + } else { + false + }; + + if skip_rewrite { + self.push_rewrite(b.span, None); + self.close_block(false); + self.last_pos = source!(self, b.span).hi(); + return; } self.walk_block_stmts(b); diff --git a/tests/source/skip.rs b/tests/source/skip.rs deleted file mode 100644 index d28ccd77de0..00000000000 --- a/tests/source/skip.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Test the skip attribute works - -#[rustfmt_skip] -fn foo() { badly; formatted; stuff -; } - -#[rustfmt_skip] -trait Foo -{ -fn foo( -); -} - -impl LateLintPass for UsedUnderscoreBinding { - #[cfg_attr(rustfmt, rustfmt_skip)] - fn check_expr() { // comment - } -} - -fn issue1346() { - #[cfg_attr(rustfmt, rustfmt_skip)] - Box::new(self.inner.call(req).then(move |result| { - match result { - Ok(resp) => Box::new(future::done(Ok(resp))), - Err(e) => { - try_error!(clo_stderr, "{}", e); - Box::new(future::err(e)) - } - } - })) -} - -fn skip_on_statements() { - // Semi - #[cfg_attr(rustfmt, rustfmt_skip)] - foo( - 1, 2, 3, 4, - 1, 2, - 1, 2, 3, - ); - - // Local - #[cfg_attr(rustfmt, rustfmt_skip)] - let x = foo( a, b , c); - - // Item - #[cfg_attr(rustfmt, rustfmt_skip)] - use foobar ; - - // Mac - #[cfg_attr(rustfmt, rustfmt_skip)] - vec![ - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, - 1, - 1, 2, - 1, - ]; - - // Expr - #[cfg_attr(rustfmt, rustfmt_skip)] - foo( a, b , c) -} - -// Check that the skip attribute applies to other attributes. -#[rustfmt_skip] -#[cfg -( a , b -)] -fn -main() {} diff --git a/tests/target/skip.rs b/tests/target/skip.rs index d28ccd77de0..28897ade56f 100644 --- a/tests/target/skip.rs +++ b/tests/target/skip.rs @@ -31,6 +31,20 @@ fn issue1346() { } fn skip_on_statements() { + // Outside block + #[rustfmt_skip] + { + foo; bar; + // junk + } + + { + // Inside block + #![rustfmt_skip] + foo; bar; + // junk + } + // Semi #[cfg_attr(rustfmt, rustfmt_skip)] foo( -- cgit 1.4.1-3-g733a5 From e35e27659dec7a70d1e0e45be2c5f3a02b2c742c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 20 Oct 2017 15:53:06 +0200 Subject: Update to last Emitter update --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 14c50563baa..0c631bc3512 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -510,6 +510,7 @@ pub fn format_input( let silent_emitter = Box::new(EmitterWriter::new( Box::new(Vec::new()), Some(codemap.clone()), + false, )); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); -- cgit 1.4.1-3-g733a5 From ac33472d3659ca9d5a29b7c78720788f4bb1aa98 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Sun, 22 Oct 2017 00:47:45 -0600 Subject: Fix typo in --config-help "funciton" -> "function" --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 6fe6bbe7716..8aff7747dd2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -624,7 +624,7 @@ create_config! { Replace, Overwrite, Display, Plain, Diff, Coverage"; condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ tuple patterns"; - combine_control_expr: bool, true, "Combine control expressions with funciton calls."; + combine_control_expr: bool, true, "Combine control expressions with function calls."; struct_field_align_threshold: usize, 0, "Align struct fields if their diffs fits within \ threshold."; remove_blank_lines_at_start_or_end_of_block: bool, true, -- cgit 1.4.1-3-g733a5 From 7b9a4e6a067660daf7c578b326c719c4a2267838 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 25 Oct 2017 00:51:04 +0900 Subject: Use a correct span for fn with pub(crate) syntax --- src/items.rs | 8 +++++++- tests/source/fn-simple.rs | 3 +++ tests/target/fn-simple.rs | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index be22db49fbf..8d7bab22e25 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1771,12 +1771,18 @@ fn rewrite_fn_base( result.push(' ') } + // Skip `pub(crate)`. + let lo_after_visibility = if let ast::Visibility::Crate(s) = fn_sig.visibility { + context.codemap.span_after(mk_sp(s.hi(), span.hi()), ")") + } else { + span.lo() + }; // A conservative estimation, to goal is to be over all parens in generics let args_start = fn_sig .generics .ty_params .last() - .map_or(span.lo(), |tp| end_typaram(tp)); + .map_or(lo_after_visibility, |tp| end_typaram(tp)); let args_end = if fd.inputs.is_empty() { context .codemap diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 880566d3d91..88eb9c36892 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -59,3 +59,6 @@ mod foo { foo(); } } + +// #2082 +pub(crate) fn init() {} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 000c62310c8..909985454aa 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -101,3 +101,6 @@ mod foo { foo(); } } + +// #2082 +pub(crate) fn init() {} -- cgit 1.4.1-3-g733a5 From a67b8b0bbb39cb5f0ffeb951951c9f058c019f1a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 25 Oct 2017 01:08:32 +0900 Subject: Use rewrite_assign_rhs when rewriting unit variant --- src/items.rs | 18 +++--------------- tests/source/enum.rs | 5 +++++ tests/target/enum.rs | 6 ++++++ 3 files changed, 14 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index be22db49fbf..5c8b6202310 100644 --- a/src/items.rs +++ b/src/items.rs @@ -537,21 +537,9 @@ impl<'a> FmtVisitor<'a> { )? } ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { - let one_line_width = - field.node.name.to_string().len() + self.snippet(expr.span).len() + 3; - if one_line_width <= shape.width { - format!("{} = {}", field.node.name, self.snippet(expr.span)) - } else { - format!( - "{}\n{}{}", - field.node.name, - shape - .indent - .block_indent(self.config) - .to_string(self.config), - self.snippet(expr.span) - ) - } + let lhs = format!("{} =", field.node.name); + // 1 = ',' + rewrite_assign_rhs(&context, lhs, expr, shape.sub_width(1)?)? } else { String::from(field.node.name.to_string()) }, diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 0c8ed5536ec..53630699f1e 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -136,3 +136,8 @@ pub enum Entry<'a, K: 'a, V: 'a> { OccupiedEntry<'a, K, V>, ), } + +// #2081 +pub enum ForegroundColor { + CYAN = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index d2a39b241e1..2440d042d24 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -173,3 +173,9 @@ pub enum Entry<'a, K: 'a, V: 'a> { Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), } + +// #2081 +pub enum ForegroundColor { + CYAN = + (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, +} -- cgit 1.4.1-3-g733a5 From adac9fb43cd7ab33de3978614c5493f98ba0b432 Mon Sep 17 00:00:00 2001 From: Bryce Van Dyk Date: Mon, 23 Oct 2017 15:17:30 +1300 Subject: Use stderr for various errors and warnings. Adjusts several error and warning report cases to output using eprintln! instead of println! so that messages are sent to stderr. --- src/bin/cargo-fmt.rs | 34 ++++++++++++++++++++++------------ src/bin/rustfmt.rs | 36 +++++++++++++++++++++++------------- src/visitor.rs | 2 +- 3 files changed, 46 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 4f611d85365..826476bed3e 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -55,14 +55,14 @@ fn execute() -> i32 { .take_while(|a| a != "--") .find(|a| !a.starts_with('-')) { - print_usage(&opts, &format!("Invalid argument: `{}`.", arg)); + print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); return failure; } let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { Ok(m) => m, Err(e) => { - print_usage(&opts, &e.to_string()); + print_usage_to_stderr(&opts, &e.to_string()); return failure; } }; @@ -72,13 +72,13 @@ fn execute() -> i32 { (false, true) => Verbosity::Quiet, (true, false) => Verbosity::Verbose, (true, true) => { - print_usage(&opts, "quiet mode and verbose mode are not compatible"); + print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); return failure; } }; if matches.opt_present("h") { - print_usage(&opts, ""); + print_usage_to_stdout(&opts, ""); return success; } @@ -86,7 +86,7 @@ fn execute() -> i32 { match format_crate(verbosity, &workspace_hitlist) { Err(e) => { - print_usage(&opts, &e.to_string()); + print_usage_to_stderr(&opts, &e.to_string()); failure } Ok(status) => if status.success() { @@ -97,13 +97,23 @@ fn execute() -> i32 { } } -fn print_usage(opts: &Options, reason: &str) { - let msg = format!("{}\nusage: cargo fmt [options]", reason); - println!( - "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ - Arguments after `--` are passed to rustfmt.", - opts.usage(&msg) - ); +macro_rules! print_usage { + ($print:ident, $opts:ident, $reason:expr) => ({ + let msg = format!("{}\nusage: cargo fmt [options]", $reason); + $print!( + "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ + Arguments after `--` are passed to rustfmt.", + $opts.usage(&msg) + ); + }) +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + print_usage!(println, opts, reason); +} + +fn print_usage_to_stderr(opts: &Options, reason: &str) { + print_usage!(eprintln, opts, reason); } #[derive(Debug, Clone, Copy, PartialEq)] diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index e686b584496..541759b1782 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -161,7 +161,7 @@ fn execute(opts: &Options) -> FmtResult { match determine_operation(&matches)? { Operation::Help => { - print_usage(opts, ""); + print_usage_to_stdout(opts, ""); Summary::print_exit_codes(); Ok(Summary::default()) } @@ -196,7 +196,7 @@ fn execute(opts: &Options) -> FmtResult { config.set().file_lines(file_lines.parse()?); for f in config.file_lines().files() { if f != "stdin" { - println!("Warning: Extra file listed in file_lines option '{}'", f); + eprintln!("Warning: Extra file listed in file_lines option '{}'", f); } } } @@ -212,7 +212,7 @@ fn execute(opts: &Options) -> FmtResult { for f in options.file_lines.files() { if !files.contains(&PathBuf::from(f)) { - println!("Warning: Extra file listed in file_lines option '{}'", f); + eprintln!("Warning: Extra file listed in file_lines option '{}'", f); } } @@ -231,10 +231,10 @@ fn execute(opts: &Options) -> FmtResult { let mut error_summary = Summary::default(); for file in files { if !file.exists() { - println!("Error: file `{}` does not exist", file.to_str().unwrap()); + eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); error_summary.add_operational_error(); } else if file.is_dir() { - println!("Error: `{}` is a directory", file.to_str().unwrap()); + eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); error_summary.add_operational_error(); } else { // Check the file directory if the config-path could not be read or not provided @@ -293,7 +293,7 @@ fn main() { } } Err(e) => { - print_usage(&opts, &e.to_string()); + print_usage_to_stderr(&opts, &e.to_string()); 1 } }; @@ -307,13 +307,23 @@ fn main() { std::process::exit(exit_code); } -fn print_usage(opts: &Options, reason: &str) { - let reason = format!( - "{}\n\nusage: {} [options] ...", - reason, - env::args_os().next().unwrap().to_string_lossy() - ); - println!("{}", opts.usage(&reason)); +macro_rules! print_usage { + ($print:ident, $opts:ident, $reason:expr) => ({ + let msg = format!( + "{}\n\nusage: {} [options] ...", + $reason, + env::args_os().next().unwrap().to_string_lossy() + ); + $print!("{}", $opts.usage(&msg)); + }) +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + print_usage!(println, opts, reason); +} + +fn print_usage_to_stderr(opts: &Options, reason: &str) { + print_usage!(eprintln, opts, reason); } fn print_version() { diff --git a/src/visitor.rs b/src/visitor.rs index 76b23f79285..be44083e3d5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -601,7 +601,7 @@ impl<'a> FmtVisitor<'a> { match self.codemap.span_to_snippet(span) { Ok(s) => s, Err(_) => { - println!( + eprintln!( "Couldn't make snippet for span {:?}->{:?}", self.codemap.lookup_char_pos(span.lo()), self.codemap.lookup_char_pos(span.hi()) -- cgit 1.4.1-3-g733a5 From abf8f43233cd281ef005cda050e887406fa9e1e6 Mon Sep 17 00:00:00 2001 From: Ömer Sinan Ağacan Date: Sat, 7 Oct 2017 15:44:28 +0300 Subject: Implement match_arm_forces_newline option (#2039) --- src/config.rs | 2 ++ src/expr.rs | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 8aff7747dd2..8c200302c5b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -597,6 +597,8 @@ create_config! { the same line with the pattern of arms"; match_block_trailing_comma: bool, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + match_arm_forces_newline: bool, false, + "Force match arm bodies to be in a new lines"; indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \ indentation level as the match keyword"; match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, diff --git a/src/expr.rs b/src/expr.rs index 8bef270cf76..51dc7a9bb7a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1695,15 +1695,20 @@ fn rewrite_match_body( is_last: bool, ) -> Option { let (extend, body) = flatten_arm_body(context, body); - - let comma = arm_comma(context.config, body, is_last); - let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); - let alt_block_sep = alt_block_sep.as_str(); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { (true, is_empty_block(block, context.codemap)) } else { (false, false) }; + let extend = if context.config.match_arm_forces_newline() { + is_block + } else { + extend + }; + + let comma = arm_comma(context.config, body, is_last); + let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = alt_block_sep.as_str(); let combine_orig_body = |body_str: &str| { let block_sep = match context.config.control_brace_style() { @@ -1716,7 +1721,11 @@ fn rewrite_match_body( let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; let next_line_indent = if is_block { - shape.indent + if is_empty_block { + shape.indent.block_indent(context.config) + } else { + shape.indent + } } else { shape.indent.block_indent(context.config) }; @@ -1772,7 +1781,7 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if !forbid_same_line + if !forbid_same_line && !context.config.match_arm_forces_newline() && (is_block || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => { -- cgit 1.4.1-3-g733a5 From ab81011a5b4613d154bb31a98cd1d70afd705949 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 27 Oct 2017 15:41:42 +0900 Subject: Force to use block for body of closure when it contains comment --- src/expr.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4eaf52681ad..5cd2190f8e3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -899,9 +899,6 @@ fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Opt }; cond.rewrite(context, cond_shape) } - ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { - stmt_expr(&block.stmts[0]).and_then(|e| rewrite_cond(context, e, shape)) - } _ => to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); @@ -2219,7 +2216,7 @@ fn rewrite_last_closure( ) -> Option { if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node { let body = match body.node { - ast::ExprKind::Block(ref block) if block.stmts.len() == 1 => { + ast::ExprKind::Block(ref block) if is_simple_block(block, context.codemap) => { stmt_expr(&block.stmts[0]).unwrap_or(body) } _ => body, -- cgit 1.4.1-3-g733a5 From fa7d8de29fba0d691b3ba543e90f272afe499e36 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 27 Oct 2017 16:41:31 +0900 Subject: Only read the trailing comma of outermost fn call --- src/expr.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4eaf52681ad..33dc3a40e21 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2359,11 +2359,24 @@ pub fn wrap_args_with_parens( } } +/// Return true if a function call or a method call represented by the given span ends with a +/// trailing comma. This function is used when rewriting macro, as adding or removing a trailing +/// comma from macro can potentially break the code. fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { - let snippet = context.snippet(span); - snippet - .trim_right_matches(|c: char| c == ')' || c.is_whitespace()) - .ends_with(',') + let mut encountered_closing_paren = false; + for c in context.snippet(span).chars().rev() { + match c { + ',' => return true, + ')' => if encountered_closing_paren { + return false; + } else { + encountered_closing_paren = true; + }, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + false } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { -- cgit 1.4.1-3-g733a5 From 8d86b0eaf83e619c2d54b7ac55ff1a91b831ca0b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Oct 2017 01:35:32 +0900 Subject: Do not use 'cargo manifest' anymore as it is deprecated --- src/bin/cargo-fmt.rs | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 826476bed3e..e8ee918b120 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -208,29 +208,9 @@ impl WorkspaceHitlist { // Returns a vector of all compile targets of a crate fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, std::io::Error> { let mut targets: Vec = vec![]; - if *workspace_hitlist == WorkspaceHitlist::None { - let output = Command::new("cargo").arg("read-manifest").output()?; - if output.status.success() { - // None of the unwraps should fail if output of `cargo read-manifest` is correct - let data = &String::from_utf8(output.stdout).unwrap(); - let json: Value = json::from_str(data).unwrap(); - let json_obj = json.as_object().unwrap(); - let jtargets = json_obj.get("targets").unwrap().as_array().unwrap(); - for jtarget in jtargets { - targets.push(target_from_json(jtarget)); - } - return Ok(targets); } - return Err(std::io::Error::new( - std::io::ErrorKind::NotFound, - str::from_utf8(&output.stderr).unwrap(), - )); } - // This happens when cargo-fmt is not used inside a crate or - // is used inside a workspace. - // To ensure backward compatability, we only use `cargo metadata` for workspaces. - // TODO: Is it possible only use metadata or read-manifest let output = Command::new("cargo") .arg("metadata") .arg("--no-deps") @@ -275,12 +255,6 @@ fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, std: targets.push(target_from_json(jtarget)); } } - return Ok(targets); - } - Err(std::io::Error::new( - std::io::ErrorKind::NotFound, - str::from_utf8(&output.stderr).unwrap(), - )) } fn target_from_json(jtarget: &Value) -> Target { -- cgit 1.4.1-3-g733a5 From bdcd19d294a0b0eeaa4691bf111dbf25960c0558 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Oct 2017 01:38:04 +0900 Subject: Read local dependencies from cargo metadata --- src/bin/cargo-fmt.rs | 202 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 142 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index e8ee918b120..14d1715286a 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -180,6 +180,29 @@ pub struct Target { kind: TargetKind, } +impl Target { + pub fn from_json(json_val: &Value) -> Option { + let jtarget = json_val.as_object()?; + let path = PathBuf::from(jtarget.get("src_path")?.as_str()?); + let kinds = jtarget.get("kind")?.as_array()?; + let kind = match kinds[0].as_str()? { + "bin" => TargetKind::Bin, + "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, + "test" => TargetKind::Test, + "example" => TargetKind::Example, + "bench" => TargetKind::Bench, + "custom-build" => TargetKind::CustomBuild, + "proc-macro" => TargetKind::ProcMacro, + _ => TargetKind::Other, + }; + + Some(Target { + path: path, + kind: kind, + }) + } +} + #[derive(Debug, PartialEq, Eq)] pub enum WorkspaceHitlist { All, @@ -205,76 +228,135 @@ impl WorkspaceHitlist { } } -// Returns a vector of all compile targets of a crate -fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, std::io::Error> { +fn get_cargo_metadata_from_utf8(v: &[u8]) -> Option { + json::from_str(str::from_utf8(v).ok()?).ok() +} + +fn get_json_array_with<'a>(v: &'a Value, key: &str) -> Option<&'a Vec> { + v.as_object()?.get(key)?.as_array() +} + +// `cargo metadata --no-deps | jq '.["packages"]'` +fn get_packages(v: &[u8]) -> Result, io::Error> { + let e = io::Error::new( + io::ErrorKind::NotFound, + String::from("`cargo metadata` returned json without a 'packages' key"), + ); + match get_cargo_metadata_from_utf8(v) { + Some(ref json_obj) => get_json_array_with(json_obj, "packages").cloned().ok_or(e), + None => Err(e), + } +} + +fn extract_target_from_package(package: &Value) -> Option> { + let jtargets = get_json_array_with(package, "targets")?; let mut targets: Vec = vec![]; + for jtarget in jtargets { + targets.push(Target::from_json(&jtarget)?); + } + Some(targets) +} +fn filter_packages_with_hitlist<'a>( + packages: Vec, + workspace_hitlist: &'a WorkspaceHitlist, +) -> Result, &'a String> { + if *workspace_hitlist == WorkspaceHitlist::All { + return Ok(packages); + } + let mut hitlist: HashSet<&String> = workspace_hitlist + .get_some() + .map_or(HashSet::new(), HashSet::from_iter); + let members: Vec = packages + .into_iter() + .filter(|member| { + member + .as_object() + .and_then(|member_obj| { + member_obj + .get("name") + .and_then(Value::as_str) + .map(|member_name| { + hitlist.take(&member_name.to_string()).is_some() + }) + }) + .unwrap_or(false) + }) + .collect(); + if hitlist.is_empty() { + Ok(members) + } else { + Err(hitlist.into_iter().next().unwrap()) + } +} + +fn get_dependencies_from_package(package: &Value) -> Option> { + let jdependencies = get_json_array_with(package, "dependencies")?; + let root_path = env::current_dir().ok()?; + let mut dependencies: Vec = vec![]; + for jdep in jdependencies { + let jdependency = jdep.as_object()?; + if !jdependency.get("source")?.is_null() { + continue; + } + let name = jdependency.get("name")?.as_str()?; + let mut path = root_path.clone(); + path.push(&name); + dependencies.push(path); + } + Some(dependencies) +} + +// Returns a vector of local dependencies under this crate +fn get_path_to_local_dependencies(packages: &[Value]) -> Vec { + let mut local_dependencies: Vec = vec![]; + for package in packages { + if let Some(mut d) = get_dependencies_from_package(package) { + local_dependencies.append(&mut d); } } + local_dependencies +} + +// Returns a vector of all compile targets of a crate +fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, io::Error> { let output = Command::new("cargo") - .arg("metadata") - .arg("--no-deps") + .args(&["metadata", "--no-deps", "--format-version=1"]) .output()?; if output.status.success() { - let data = &String::from_utf8(output.stdout).unwrap(); - let json: Value = json::from_str(data).unwrap(); - let json_obj = json.as_object().unwrap(); - let mut hitlist: HashSet<&String> = if *workspace_hitlist != WorkspaceHitlist::All { - HashSet::from_iter(workspace_hitlist.get_some().unwrap()) - } else { - HashSet::new() // Unused - }; - let members: Vec<&Value> = json_obj - .get("packages") - .unwrap() - .as_array() - .unwrap() - .into_iter() - .filter(|member| if *workspace_hitlist == WorkspaceHitlist::All { - true - } else { - let member_obj = member.as_object().unwrap(); - let member_name = member_obj.get("name").unwrap().as_str().unwrap(); - hitlist.take(&member_name.to_string()).is_some() - }) - .collect(); - if !hitlist.is_empty() { - // Mimick cargo of only outputting one spec. - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!( - "package `{}` is not a member of the workspace", - hitlist.iter().next().unwrap() - ), - )); + let cur_dir = env::current_dir()?; + let mut targets: Vec = vec![]; + let packages = get_packages(&output.stdout)?; + + // If we can find any local dependencies, we will try to get targets from those as well. + for path in get_path_to_local_dependencies(&packages) { + env::set_current_dir(path)?; + targets.append(&mut get_targets(workspace_hitlist)?); } - for member in members { - let member_obj = member.as_object().unwrap(); - let jtargets = member_obj.get("targets").unwrap().as_array().unwrap(); - for jtarget in jtargets { - targets.push(target_from_json(jtarget)); + + env::set_current_dir(cur_dir)?; + match filter_packages_with_hitlist(packages, workspace_hitlist) { + Ok(packages) => { + for package in packages { + if let Some(mut target) = extract_target_from_package(&package) { + targets.append(&mut target); + } + } + Ok(targets) + } + Err(package) => { + // Mimick cargo of only outputting one spec. + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("package `{}` is not a member of the workspace", package), + )) } } -} - -fn target_from_json(jtarget: &Value) -> Target { - let jtarget = jtarget.as_object().unwrap(); - let path = PathBuf::from(jtarget.get("src_path").unwrap().as_str().unwrap()); - let kinds = jtarget.get("kind").unwrap().as_array().unwrap(); - let kind = match kinds[0].as_str().unwrap() { - "bin" => TargetKind::Bin, - "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, - "test" => TargetKind::Test, - "example" => TargetKind::Example, - "bench" => TargetKind::Bench, - "custom-build" => TargetKind::CustomBuild, - "proc-macro" => TargetKind::ProcMacro, - _ => TargetKind::Other, - }; - - Target { - path: path, - kind: kind, + } else { + Err(io::Error::new( + io::ErrorKind::NotFound, + str::from_utf8(&output.stderr).unwrap(), + )) } } -- cgit 1.4.1-3-g733a5 From 3b0d2c14266be9d989dd919ccf4089fbdcdce7dd Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Oct 2017 01:38:28 +0900 Subject: %s/std::io/io/g --- src/bin/cargo-fmt.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 14d1715286a..402ad23520e 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -17,7 +17,7 @@ extern crate getopts; extern crate serde_json as json; use std::env; -use std::io::Write; +use std::io::{self, Write}; use std::path::PathBuf; use std::process::{Command, ExitStatus}; use std::str; @@ -126,7 +126,7 @@ pub enum Verbosity { fn format_crate( verbosity: Verbosity, workspace_hitlist: &WorkspaceHitlist, -) -> Result { +) -> Result { let targets = get_targets(workspace_hitlist)?; // Currently only bin and lib files get formatted @@ -364,7 +364,7 @@ fn format_files( files: &[PathBuf], fmt_args: &[String], verbosity: Verbosity, -) -> Result { +) -> Result { let stdout = if verbosity == Verbosity::Quiet { std::process::Stdio::null() } else { @@ -386,8 +386,8 @@ fn format_files( .args(fmt_args) .spawn() .map_err(|e| match e.kind() { - std::io::ErrorKind::NotFound => std::io::Error::new( - std::io::ErrorKind::Other, + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, "Could not run rustfmt, please make sure it is in your PATH.", ), _ => e, -- cgit 1.4.1-3-g733a5 From d10df701388dead9c46a1fc0714b4b2b578db4ec Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Oct 2017 01:39:01 +0900 Subject: Remove iter() in for loop --- src/bin/cargo-fmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 402ad23520e..10d08ff7d19 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -372,10 +372,10 @@ fn format_files( }; if verbosity == Verbosity::Verbose { print!("rustfmt"); - for a in fmt_args.iter() { + for a in fmt_args { print!(" {}", a); } - for f in files.iter() { + for f in files { print!(" {}", f.display()); } println!(""); -- cgit 1.4.1-3-g733a5 From 92e374e778ac6c1b71658e98da8aedabbf454672 Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Fri, 27 Oct 2017 22:57:32 +0100 Subject: Fix a "variable does not need to be mutable" warning. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index c8045747bfb..a86aa9e5bdd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -333,7 +333,7 @@ where Ok(result) => result, Err(e) => { // Create a new error with path_str to help users see which files failed - let mut err_msg = path_str.to_string() + &": ".to_string() + &e.to_string(); + let err_msg = path_str.to_string() + &": ".to_string() + &e.to_string(); return Err(io::Error::new(e.kind(), err_msg)); } }; -- cgit 1.4.1-3-g733a5 From 5233f9cde0aa234090662b9a2e3bca99924b6af4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 28 Oct 2017 18:41:58 +1300 Subject: Add support for `crate` shorthand for `pub(crate)` --- Cargo.lock | 42 +++++++++++++++++++++--------------------- src/items.rs | 12 +++++++----- src/utils.rs | 7 ++++--- tests/source/fn-simple.rs | 2 ++ tests/source/pub-restricted.rs | 13 +++++++++++++ tests/target/fn-simple.rs | 2 ++ tests/target/pub-restricted.rs | 13 +++++++++++++ 7 files changed, 62 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 2ece75165b3..f2041542cc4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,24 +1,3 @@ -[root] -name = "rustfmt-nightly" -version = "0.2.9" -dependencies = [ - "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.6.3" @@ -115,6 +94,27 @@ name = "regex-syntax" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustfmt-nightly" +version = "0.2.9" +dependencies = [ + "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde" version = "1.0.15" diff --git a/src/items.rs b/src/items.rs index b6dbb9af1d2..562986da6a9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -14,7 +14,7 @@ use std::borrow::Cow; use std::cmp::min; use syntax::{abi, ast, ptr, symbol}; -use syntax::ast::ImplItem; +use syntax::ast::{CrateSugar, ImplItem}; use syntax::codemap::{BytePos, Span}; use syntax::visit; @@ -1765,10 +1765,12 @@ fn rewrite_fn_base( } // Skip `pub(crate)`. - let lo_after_visibility = if let ast::Visibility::Crate(s) = fn_sig.visibility { - context.codemap.span_after(mk_sp(s.hi(), span.hi()), ")") - } else { - span.lo() + let lo_after_visibility = match fn_sig.visibility { + ast::Visibility::Crate(s, CrateSugar::PubCrate) => { + context.codemap.span_after(mk_sp(s.hi(), span.hi()), ")") + } + ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), + _ => span.lo(), }; // A conservative estimation, to goal is to be over all parens in generics let args_start = fn_sig diff --git a/src/utils.rs b/src/utils.rs index 3106df9ed8b..3bdadf460e2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -11,8 +11,8 @@ use std::borrow::Cow; use syntax::{abi, ptr}; -use syntax::ast::{self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, - Path, Visibility}; +use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, + NestedMetaItemKind, Path, Visibility}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use rewrite::RewriteContext; @@ -37,7 +37,8 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { match *vis { Visibility::Public => Cow::from("pub "), Visibility::Inherited => Cow::from(""), - Visibility::Crate(_) => Cow::from("pub(crate) "), + Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "), + Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "), Visibility::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 88eb9c36892..ff08b04c704 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -62,3 +62,5 @@ mod foo { // #2082 pub(crate) fn init() {} + +crate fn init() {} diff --git a/tests/source/pub-restricted.rs b/tests/source/pub-restricted.rs index 5683acbf3aa..30051fa72ee 100644 --- a/tests/source/pub-restricted.rs +++ b/tests/source/pub-restricted.rs @@ -24,6 +24,19 @@ pub( crate ) enum WriteState { WriteData(Writer), } + crate enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + pub(in ::global:: path :: to::some_mod ) enum WriteState { WriteId { id: U64Writer, diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 909985454aa..6bbdf4be95d 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -104,3 +104,5 @@ mod foo { // #2082 pub(crate) fn init() {} + +crate fn init() {} diff --git a/tests/target/pub-restricted.rs b/tests/target/pub-restricted.rs index 0e178ef1013..8cc2ade612a 100644 --- a/tests/target/pub-restricted.rs +++ b/tests/target/pub-restricted.rs @@ -24,6 +24,19 @@ pub(crate) enum WriteState { WriteData(Writer), } +crate enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + pub(in global::path::to::some_mod) enum WriteState { WriteId { id: U64Writer, -- cgit 1.4.1-3-g733a5 From b0c7201c0e3ea6a7d928a4c5e15b4a83417e6a06 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Oct 2017 16:40:18 +0900 Subject: Do not propagate io error when dependencies are not found --- src/bin/cargo-fmt.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 10d08ff7d19..dac20fe2877 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -330,8 +330,13 @@ fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, io:: // If we can find any local dependencies, we will try to get targets from those as well. for path in get_path_to_local_dependencies(&packages) { - env::set_current_dir(path)?; - targets.append(&mut get_targets(workspace_hitlist)?); + match env::set_current_dir(path) { + Ok(..) => match get_targets(workspace_hitlist) { + Ok(ref mut t) => targets.append(t), + Err(..) => continue, + }, + Err(..) => continue, + } } env::set_current_dir(cur_dir)?; -- cgit 1.4.1-3-g733a5 From 685c9d332fe728e58ccf1bb6df5c096faaa3c172 Mon Sep 17 00:00:00 2001 From: Tarin Mahmood Date: Fri, 27 Oct 2017 21:45:35 +0600 Subject: Unstable options added --- src/bin/rustfmt.rs | 19 ++++ src/config.rs | 251 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 176 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5189b3396c6..c7461069db4 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -60,6 +60,7 @@ struct CliOptions { verbose: bool, write_mode: Option, file_lines: FileLines, // Default is all lines in all files. + unstable_features: bool, } impl CliOptions { @@ -67,6 +68,17 @@ impl CliOptions { let mut options = CliOptions::default(); options.skip_children = matches.opt_present("skip-children"); options.verbose = matches.opt_present("verbose"); + let unstable_features = matches.opt_present("unstable_features"); + let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false); + if unstable_features && !rust_nightly { + return Err(FmtError::from(format!( + "Unstable features are only available on Nightly channel" + ))); + } else { + options.unstable_features = unstable_features; + } if let Some(ref write_mode) = matches.opt_str("write-mode") { if let Ok(write_mode) = WriteMode::from_str(write_mode) { @@ -89,6 +101,7 @@ impl CliOptions { config.set().skip_children(self.skip_children); config.set().verbose(self.verbose); config.set().file_lines(self.file_lines); + config.set().unstable_features(self.unstable_features); if let Some(write_mode) = self.write_mode { config.set().write_mode(write_mode); } @@ -120,6 +133,12 @@ fn make_opts() -> Options { ); opts.optflag("", "skip-children", "don't reformat child modules"); + opts.optflag( + "", + "unstable-features", + "Enables unstable features. Only available on nightly channel", + ); + opts.optflag( "", "config-help", diff --git a/src/config.rs b/src/config.rs index 8c200302c5b..18969908c86 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,6 +20,15 @@ use file_lines::FileLines; use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; use Summary; + +macro_rules! is_nightly_channel { + () => { + env::var("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false) + } +} + macro_rules! configuration_option_enum{ ($e:ident: $( $x:ident ),+ $(,)*) => { #[derive(Copy, Clone, Eq, PartialEq, Debug)] @@ -215,13 +224,13 @@ impl ConfigHelpItem { } macro_rules! create_config { - ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => ( + ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[derive(Clone)] pub struct Config { // For each config item, we store a bool indicating whether it has // been accessed and the value, and a bool whether the option was // manually initialised, or taken from the default, - $($i: (Cell, bool, $ty)),+ + $($i: (Cell, bool, $ty, bool)),+ } // Just like the Config struct but with each property wrapped @@ -309,8 +318,18 @@ macro_rules! create_config { fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { - self.$i.1 = true; - self.$i.2 = val; + if !self.$i.3 { + self.$i.1 = true; + self.$i.2 = val; + } else { + if is_nightly_channel!() { + self.$i.1 = true; + self.$i.2 = val; + } else { + println!("Warning: can't set some features as unstable \ + features are only available in nightly channel."); + } + } } )+ self @@ -478,7 +497,7 @@ macro_rules! create_config { fn default() -> Config { Config { $( - $i: (Cell::new(false), false, $def), + $i: (Cell::new(false), false, $def, $stb), )+ } } @@ -511,138 +530,149 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { create_config! { - verbose: bool, false, "Use verbose output"; - disable_all_formatting: bool, false, "Don't reformat anything"; - skip_children: bool, false, "Don't reformat out of line modules"; - file_lines: FileLines, FileLines::all(), + unstable_features: bool, false, true, + "Enables unstable features. Only available on nightly channel"; + verbose: bool, false, false, "Use verbose output"; + disable_all_formatting: bool, false, false, "Don't reformat anything"; + skip_children: bool, false, false, "Don't reformat out of line modules"; + file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - max_width: usize, 100, "Maximum width of each line"; - error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width"; - error_on_line_overflow_comments: bool, true, "Error if unable to get comments within max_width"; - tab_spaces: usize, 4, "Number of spaces per tab"; - fn_call_width: usize, 60, + max_width: usize, 100, false, "Maximum width of each line"; + error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; + error_on_line_overflow_comments: bool, true, false, + "Error if unable to get comments within max_width"; + tab_spaces: usize, 4, false, "Number of spaces per tab"; + fn_call_width: usize, 60, false, "Maximum width of the args of a function call before falling back to vertical formatting"; - struct_lit_width: usize, 18, + struct_lit_width: usize, 18, false, "Maximum width in the body of a struct lit before falling back to vertical formatting"; - struct_variant_width: usize, 35, + struct_variant_width: usize, 35, false, "Maximum width in the body of a struct variant before falling back to vertical formatting"; - force_explicit_abi: bool, true, "Always print the abi for extern items"; - newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings"; - fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions"; - item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums"; - control_style: Style, Style::Rfc, "Indent style for control flow statements"; - control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, + force_explicit_abi: bool, true, false, "Always print the abi for extern items"; + newline_style: NewlineStyle, NewlineStyle::Unix, false, "Unix or Windows line endings"; + fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for functions"; + item_brace_style: BraceStyle, BraceStyle::SameLineWhere, false, + "Brace style for structs and enums"; + control_style: Style, Style::Rfc, false, "Indent style for control flow statements"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; - impl_empty_single_line: bool, true, "Put empty-body implementations on a single line"; - trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, + impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, "How to handle trailing commas for lists"; - trailing_semicolon: bool, true, "Add trailing semicolon after break, continue and return"; - fn_empty_single_line: bool, true, "Put empty-body functions on a single line"; - fn_single_line: bool, false, "Put single-expression functions on a single line"; - fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, + trailing_semicolon: bool, true, false, + "Add trailing semicolon after break, continue and return"; + fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; + fn_single_line: bool, false, false, "Put single-expression functions on a single line"; + fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, false, "Location of return type in function declaration"; - fn_args_paren_newline: bool, false, "If function argument parenthesis goes on a newline"; - fn_args_density: Density, Density::Tall, "Argument density in functions"; - fn_args_layout: IndentStyle, IndentStyle::Block, + fn_args_paren_newline: bool, false, false, "If function argument parenthesis goes on a newline"; + fn_args_density: Density, Density::Tall, false, "Argument density in functions"; + fn_args_layout: IndentStyle, IndentStyle::Block, false, "Layout of function arguments and tuple structs"; - array_layout: IndentStyle, IndentStyle::Block, "Indent on arrays"; - array_width: usize, 60, + array_layout: IndentStyle, IndentStyle::Block, false, "Indent on arrays"; + array_width: usize, 60, false, "Maximum width of an array literal before falling back to vertical formatting"; - array_horizontal_layout_threshold: usize, 0, + array_horizontal_layout_threshold: usize, 0, false, "How many elements array must have before rustfmt uses horizontal layout."; - type_punctuation_density: TypeDensity, TypeDensity::Wide, + type_punctuation_density: TypeDensity, TypeDensity::Wide, false, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - where_style: Style, Style::Rfc, "Overall strategy for where clauses"; + where_style: Style, Style::Rfc, false, "Overall strategy for where clauses"; // TODO: // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? // 2. Currently options `Tall` and `Vertical` produce the same output. - where_density: Density, Density::Vertical, "Density of a where clause"; - where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause"; - where_pred_indent: IndentStyle, IndentStyle::Visual, + where_density: Density, Density::Vertical, false, "Density of a where clause"; + where_layout: ListTactic, ListTactic::Vertical, false, "Element layout inside a where clause"; + where_pred_indent: IndentStyle, IndentStyle::Visual, false, "Indentation style of a where predicate"; - generics_indent: IndentStyle, IndentStyle::Block, "Indentation of generics"; - struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition"; - struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, + generics_indent: IndentStyle, IndentStyle::Block, false, "Indentation of generics"; + struct_lit_style: IndentStyle, IndentStyle::Block, false, "Style of struct definition"; + struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, false, "Multiline style on literal structs"; - fn_call_style: IndentStyle, IndentStyle::Block, "Indentation for function calls, etc."; - report_todo: ReportTactic, ReportTactic::Never, + fn_call_style: IndentStyle, IndentStyle::Block, false, "Indentation for function calls, etc."; + report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; - report_fixme: ReportTactic, ReportTactic::Never, + report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; - chain_indent: IndentStyle, IndentStyle::Block, "Indentation of chain"; - chain_one_line_max: usize, 60, "Maximum length of a chain to fit on a single line"; - chain_split_single_child: bool, false, "Split a chain with a single child if its length \ + chain_indent: IndentStyle, IndentStyle::Block, false, "Indentation of chain"; + chain_one_line_max: usize, 60, false, "Maximum length of a chain to fit on a single line"; + chain_split_single_child: bool, false, false, "Split a chain with a single child if its length \ exceeds `chain_one_line_max`"; - imports_indent: IndentStyle, IndentStyle::Visual, "Indent of imports"; - imports_layout: ListTactic, ListTactic::Mixed, "Item layout inside a import block"; - reorder_extern_crates: bool, true, "Reorder extern crate statements alphabetically"; - reorder_extern_crates_in_group: bool, true, "Reorder extern crate statements in group"; - reorder_imports: bool, false, "Reorder import statements alphabetically"; - reorder_imports_in_group: bool, false, "Reorder import statements in group"; - reorder_imported_names: bool, true, + imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; + imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; + reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; + reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; + reorder_imports: bool, false, false, "Reorder import statements alphabetically"; + reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; + reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; - single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \ + single_line_if_else_max_width: usize, 50, false, "Maximum line length for single line if-else \ expressions. A value of zero means always break \ if-else expressions."; - format_strings: bool, false, "Format string literals where necessary"; - force_format_strings: bool, false, "Always format string literals"; - take_source_hints: bool, false, "Retain some formatting characteristics from the source code"; - hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment"; - wrap_comments: bool, false, "Break comments to fit on the line"; - comment_width: usize, 80, "Maximum length of comments. No effect unless wrap_comments = true"; - normalize_comments: bool, false, "Convert /* */ comments to // comments where possible"; - wrap_match_arms: bool, true, "Wrap the body of arms in blocks when it does not fit on \ + format_strings: bool, false, false, "Format string literals where necessary"; + force_format_strings: bool, false, false, "Always format string literals"; + take_source_hints: bool, false, false, + "Retain some formatting characteristics from the source code"; + hard_tabs: bool, false, false, "Use tab characters for indentation, spaces for alignment"; + wrap_comments: bool, false, false, "Break comments to fit on the line"; + comment_width: usize, 80, false, + "Maximum length of comments. No effect unless wrap_comments = true"; + normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; + wrap_match_arms: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; - match_block_trailing_comma: bool, false, + match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - match_arm_forces_newline: bool, false, + match_arm_forces_newline: bool, false, false, "Force match arm bodies to be in a new lines"; - indent_match_arms: bool, true, "Indent match arms instead of keeping them at the same \ + indent_match_arms: bool, true, false, "Indent match arms instead of keeping them at the same \ indentation level as the match keyword"; - match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, + match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, false, "Put a match sub-patterns' separator in front or back."; - closure_block_indent_threshold: isize, 7, "How many lines a closure must have before it is \ - block indented. -1 means never use block indent."; - space_before_type_annotation: bool, false, + closure_block_indent_threshold: isize, 7, false, + "How many lines a closure must have before it is block indented. \ + -1 means never use block indent."; + space_before_type_annotation: bool, false, false, "Leave a space before the colon in a type annotation"; - space_after_type_annotation_colon: bool, true, + space_after_type_annotation_colon: bool, true, false, "Leave a space after the colon in a type annotation"; - space_before_struct_lit_field_colon: bool, false, + space_before_struct_lit_field_colon: bool, false, false, "Leave a space before the colon in a struct literal field"; - space_after_struct_lit_field_colon: bool, true, + space_after_struct_lit_field_colon: bool, true, false, "Leave a space after the colon in a struct literal field"; - space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound"; - space_after_bound_colon: bool, true, + space_before_bound: bool, false, false, + "Leave a space before the colon in a trait or lifetime bound"; + space_after_bound_colon: bool, true, false, "Leave a space after the colon in a trait or lifetime bound"; - spaces_around_ranges: bool, false, "Put spaces around the .. and ... range operators"; - spaces_within_angle_brackets: bool, false, "Put spaces within non-empty generic arguments"; - spaces_within_square_brackets: bool, false, "Put spaces within non-empty square brackets"; - spaces_within_parens: bool, false, "Put spaces within non-empty parentheses"; - use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand"; - write_mode: WriteMode, WriteMode::Overwrite, + spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; + spaces_within_angle_brackets: bool, false, false, + "Put spaces within non-empty generic arguments"; + spaces_within_square_brackets: bool, false, false, + "Put spaces within non-empty square brackets"; + spaces_within_parens: bool, false, false, "Put spaces within non-empty parentheses"; + use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; + write_mode: WriteMode, WriteMode::Overwrite, false, "What Write Mode to use when none is supplied: \ Replace, Overwrite, Display, Plain, Diff, Coverage"; - condense_wildcard_suffixes: bool, false, "Replace strings of _ wildcards by a single .. in \ - tuple patterns"; - combine_control_expr: bool, true, "Combine control expressions with function calls."; - struct_field_align_threshold: usize, 0, "Align struct fields if their diffs fits within \ + condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ + in tuple patterns"; + combine_control_expr: bool, true, false, "Combine control expressions with function calls."; + struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ threshold."; - remove_blank_lines_at_start_or_end_of_block: bool, true, + remove_blank_lines_at_start_or_end_of_block: bool, true, false, "Remove blank lines at start or end of a block"; - attributes_on_same_line_as_field: bool, true, + attributes_on_same_line_as_field: bool, true, false, "Try to put attributes on the same line as fields."; - attributes_on_same_line_as_variant: bool, true, + attributes_on_same_line_as_variant: bool, true, false, "Try to put attributes on the same line as variants in enum declarations."; - multiline_closure_forces_block: bool, false, + multiline_closure_forces_block: bool, false, false, "Force multiline closure bodies to be wrapped in a block"; - multiline_match_arm_forces_block: bool, false, + multiline_match_arm_forces_block: bool, false, false, "Force multiline match arm bodies to be wrapped in a block"; - merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one"; - binop_separator: SeparatorPlace, SeparatorPlace::Front, + merge_derives: bool, true, false, "Merge multiple `#[derive(...)]` into a single one"; + binop_separator: SeparatorPlace, SeparatorPlace::Front, false, "Where to put a binary operator when a binary expression goes multiline."; - required_version: String, env!("CARGO_PKG_VERSION").to_owned(), + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, "Require a specific version of rustfmt." } @@ -681,4 +711,37 @@ mod test { assert_eq!(config.was_set().hard_tabs(), true); assert_eq!(config.was_set().verbose(), false); } + + #[test] + fn test_as_not_nightly_channel() { + let mut config = Config::default(); + assert_eq!(config.was_set().unstable_features(), false); + config.set().unstable_features(true); + assert_eq!(config.was_set().unstable_features(), false); + } + + #[test] + fn test_as_nightly_channel() { + let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + let mut config = Config::default(); + config.set().unstable_features(true); + assert_eq!(config.was_set().unstable_features(), false); + config.set().unstable_features(true); + assert_eq!(config.unstable_features(), true); + ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + } + + #[test] + fn test_unstable_from_toml() { + let mut config = Config::from_toml("unstable_features = true").unwrap(); + assert_eq!(config.was_set().unstable_features(), false); + let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + config = Config::from_toml("unstable_features = true").unwrap(); + assert_eq!(config.was_set().unstable_features(), true); + assert_eq!(config.unstable_features(), true); + ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + } + } -- cgit 1.4.1-3-g733a5 From 98eb7da0d52f67d4e8d0d61239093dd8136c326b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 29 Oct 2017 00:12:28 +0900 Subject: Format dependency crates only when '--all' was passed --- src/bin/cargo-fmt.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index dac20fe2877..3caf5522948 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -329,13 +329,15 @@ fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, io:: let packages = get_packages(&output.stdout)?; // If we can find any local dependencies, we will try to get targets from those as well. - for path in get_path_to_local_dependencies(&packages) { - match env::set_current_dir(path) { - Ok(..) => match get_targets(workspace_hitlist) { - Ok(ref mut t) => targets.append(t), + if *workspace_hitlist == WorkspaceHitlist::All { + for path in get_path_to_local_dependencies(&packages) { + match env::set_current_dir(path) { + Ok(..) => match get_targets(workspace_hitlist) { + Ok(ref mut t) => targets.append(t), + Err(..) => continue, + }, Err(..) => continue, - }, - Err(..) => continue, + } } } -- cgit 1.4.1-3-g733a5 From 5e30a0183f5a1f1e244142940a6d65d0a3f7d76a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 29 Oct 2017 00:13:37 +0900 Subject: Filter packages only when '-p' was passed --- src/bin/cargo-fmt.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3caf5522948..2c0b964b001 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -261,12 +261,12 @@ fn filter_packages_with_hitlist<'a>( packages: Vec, workspace_hitlist: &'a WorkspaceHitlist, ) -> Result, &'a String> { - if *workspace_hitlist == WorkspaceHitlist::All { + let some_hitlist: Option> = + workspace_hitlist.get_some().map(HashSet::from_iter); + if some_hitlist.is_none() { return Ok(packages); } - let mut hitlist: HashSet<&String> = workspace_hitlist - .get_some() - .map_or(HashSet::new(), HashSet::from_iter); + let mut hitlist = some_hitlist.unwrap(); let members: Vec = packages .into_iter() .filter(|member| { -- cgit 1.4.1-3-g733a5 From 96566276e3ed0bfcdc4816ec6c90307a4569cfb7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 30 Oct 2017 07:39:28 +1300 Subject: Fix build Fixes #2096 --- src/items.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 562986da6a9..25ed376f277 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2740,6 +2740,8 @@ impl Rewrite for ast::ForeignItem { format!("{}{}{};", prefix, sep, ty_str) }) } + // FIXME(#2097) support extern types. + ast::ForeignItemKind::Ty => unimplemented!(), }?; let missing_span = if self.attrs.is_empty() { -- cgit 1.4.1-3-g733a5 From c1e897907ab7be25fe302a0ccd7a927ff0410203 Mon Sep 17 00:00:00 2001 From: Paul Lietar Date: Tue, 5 Sep 2017 02:22:17 +0100 Subject: Add suport for extern types. See https://github.com/rust-lang/rust/pull/44295 --- src/items.rs | 6 ++++-- tests/source/extern.rs | 5 +++++ tests/target/extern.rs | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 25ed376f277..82056c59dac 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2740,8 +2740,10 @@ impl Rewrite for ast::ForeignItem { format!("{}{}{};", prefix, sep, ty_str) }) } - // FIXME(#2097) support extern types. - ast::ForeignItemKind::Ty => unimplemented!(), + ast::ForeignItemKind::Ty => { + let vis = format_visibility(&self.vis); + Some(format!("{}type {};", vis, self.ident)) + } }?; let missing_span = if self.attrs.is_empty() { diff --git a/tests/source/extern.rs b/tests/source/extern.rs index 5546b217226..bc82bcd61db 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -25,6 +25,11 @@ extern { fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, devNr: c_uint, wildcard: c_char) -> TDMR_ERROR; fn quux() -> (); // Post comment + + pub type + Foo; + + type Bar; } extern "Rust" { static ext: u32; diff --git a/tests/target/extern.rs b/tests/target/extern.rs index c0601a4d0e1..1d49b76dc42 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -34,6 +34,10 @@ extern "C" { ) -> TDMR_ERROR; fn quux() -> (); // Post comment + + pub type Foo; + + type Bar; } extern "Rust" { -- cgit 1.4.1-3-g733a5 From fe39c0cd8c43f2360ef8db9311e44a4cd36d89c0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 30 Oct 2017 23:34:44 +0900 Subject: Fix a typo --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index c7461069db4..c886fc7aae6 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -68,7 +68,7 @@ impl CliOptions { let mut options = CliOptions::default(); options.skip_children = matches.opt_present("skip-children"); options.verbose = matches.opt_present("verbose"); - let unstable_features = matches.opt_present("unstable_features"); + let unstable_features = matches.opt_present("unstable-features"); let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") .map(|c| c == "nightly") .unwrap_or(false); -- cgit 1.4.1-3-g733a5 From e84e01c4428d1a16c04597e963d16bdb6427e9c7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 30 Oct 2017 23:31:20 +0900 Subject: Use context.budget() --- src/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9a020646927..67f8af1abbd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1450,9 +1450,8 @@ fn rewrite_match( // Do not take the rhs overhead from the upper expressions into account // when rewriting match condition. - let new_width = context.config.max_width().checked_sub(shape.used_width())?; let cond_shape = Shape { - width: new_width, + width: context.budget(shape.used_width()), ..shape }; // 6 = `match ` -- cgit 1.4.1-3-g733a5 From 2e06dea146eddea8a7fc4ad22f12cfe8fd9e1eed Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 30 Oct 2017 23:36:42 +0900 Subject: Format match expr with empty body --- src/expr.rs | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 67f8af1abbd..212f05b52b8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1444,10 +1444,6 @@ fn rewrite_match( span: Span, attrs: &[ast::Attribute], ) -> Option { - if arms.is_empty() { - return None; - } - // Do not take the rhs overhead from the upper expressions into account // when rewriting match condition. let cond_shape = Shape { @@ -1484,9 +1480,12 @@ fn rewrite_match( }; let open_brace_pos = if inner_attrs.is_empty() { - context - .codemap - .span_after(mk_sp(cond.span.hi(), arms[0].span().lo()), "{") + let hi = if arms.is_empty() { + span.hi() + } else { + arms[0].span().lo() + }; + context.codemap.span_after(mk_sp(cond.span.hi(), hi), "{") } else { inner_attrs[inner_attrs.len() - 1].span().hi() }; @@ -1497,15 +1496,25 @@ fn rewrite_match( shape.indent.to_string(context.config) }; - Some(format!( - "match {}{}{{\n{}{}{}\n{}}}", - cond_str, - block_sep, - inner_attrs_str, - arm_indent_str, - rewrite_match_arms(context, arms, shape, span, open_brace_pos,)?, - shape.indent.to_string(context.config), - )) + if arms.is_empty() { + let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); + if snippet.trim().is_empty() { + Some(format!("match {} {{}}", cond_str)) + } else { + // Empty match with comments or inner attributes? We are not going to bother, sorry ;) + Some(context.snippet(span)) + } + } else { + Some(format!( + "match {}{}{{\n{}{}{}\n{}}}", + cond_str, + block_sep, + inner_attrs_str, + arm_indent_str, + rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, + shape.indent.to_string(context.config), + )) + } } fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { -- cgit 1.4.1-3-g733a5 From b0d6d03a25a01338044c5e59ca9be2ea6ab32bac Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 30 Oct 2017 21:35:56 +0900 Subject: Use correct budget --- src/items.rs | 4 ++-- src/types.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 82056c59dac..8adfe080a2c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1235,13 +1235,13 @@ fn format_tuple_struct( } result.push(')'); } else { - // 3 = `();` + // 1 = "," let body = rewrite_call_inner( context, "", &fields.iter().map(|field| field).collect::>()[..], span, - Shape::legacy(context.budget(last_line_width(&result) + 3), offset), + Shape::indented(offset, context.config).sub_width(1)?, context.config.fn_call_width(), false, )?; diff --git a/src/types.rs b/src/types.rs index 8475b82d693..21b06ebaff5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -67,9 +67,8 @@ pub fn rewrite_path( result.push_str("::"); } - let extra_offset = extra_offset(&result, shape); // 3 = ">::".len() - let shape = shape.shrink_left(extra_offset)?.sub_width(3)?; + let shape = shape.sub_width(3)?; result = rewrite_path_segments( PathContext::Type, -- cgit 1.4.1-3-g733a5 From 7e99893e25c900ceb8b61c6c69e8a46d3e604c1d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 31 Oct 2017 15:03:46 +0900 Subject: Use visual indent only when rewriting string literal --- src/expr.rs | 2 +- src/string.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 212f05b52b8..193a5c847bb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1955,7 +1955,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt // Remove the quote characters. let str_lit = &string_lit[1..string_lit.len() - 1]; - rewrite_string(str_lit, &StringFormat::new(shape, context.config)) + rewrite_string(str_lit, &StringFormat::new(shape.visual_indent(0), context.config)) } fn string_requires_rewrite( diff --git a/src/string.rs b/src/string.rs index 9812b8af611..c3f1c5faf1e 100644 --- a/src/string.rs +++ b/src/string.rs @@ -50,7 +50,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let stripped_str = re.replace_all(orig, "$1"); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let shape = fmt.shape.visual_indent(0); + let shape = fmt.shape; let indent = shape.indent.to_string(fmt.config); let punctuation = ":,;."; -- cgit 1.4.1-3-g733a5 From bc310144230ad87edbfb40e1ed49c5d947d569bb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 31 Oct 2017 15:04:50 +0900 Subject: Add an optional max width argument to rewrite_string() --- src/expr.rs | 6 +++++- src/string.rs | 14 +++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 193a5c847bb..4c48337e036 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1955,7 +1955,11 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt // Remove the quote characters. let str_lit = &string_lit[1..string_lit.len() - 1]; - rewrite_string(str_lit, &StringFormat::new(shape.visual_indent(0), context.config)) + rewrite_string( + str_lit, + &StringFormat::new(shape.visual_indent(0), context.config), + None, + ) } fn string_requires_rewrite( diff --git a/src/string.rs b/src/string.rs index c3f1c5faf1e..43b1ccbcb93 100644 --- a/src/string.rs +++ b/src/string.rs @@ -44,7 +44,11 @@ impl<'a> StringFormat<'a> { } // FIXME: simplify this! -pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { +pub fn rewrite_string<'a>( + orig: &str, + fmt: &StringFormat<'a>, + max_width: Option, +) -> Option { // Strip line breaks. let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); let stripped_str = re.replace_all(orig, "$1"); @@ -67,7 +71,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option let ender_length = fmt.line_end.len(); // If we cannot put at least a single character per line, the rewrite won't // succeed. - let max_chars = shape + let mut max_chars = shape .width .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; @@ -135,6 +139,10 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // The next line starts where the current line ends. cur_start = cur_end; + + if let Some(new_max_chars) = max_width { + max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + } } result.push_str(fmt.closer); @@ -150,6 +158,6 @@ mod test { fn issue343() { let config = Default::default(); let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); - rewrite_string("eq_", &fmt); + rewrite_string("eq_", &fmt, None); } } -- cgit 1.4.1-3-g733a5 From 38399875b82cbad35f3405c40b34c469503020b5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 31 Oct 2017 15:07:19 +0900 Subject: Add has_url() --- src/comment.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 5112c333dee..156ae26725f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -349,6 +349,12 @@ fn rewrite_comment_inner( Some(result) } +/// Returns true if the given string MAY include URLs or alike. +fn has_url(s: &str) -> bool { + // This function may return false positive, but should get its job done in most cases. + s.contains("https://") || s.contains("http://") +} + /// Given the span, rewrite the missing comment inside it if available. /// Note that the given span must only include comments (or leading/trailing whitespaces). pub fn rewrite_missing_comment( -- cgit 1.4.1-3-g733a5 From dae76d21ff4280b336756fb24e160dee7d9d7057 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 31 Oct 2017 15:07:58 +0900 Subject: Implement soft wrapping for comments --- src/comment.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 156ae26725f..0e06545300a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -287,12 +287,13 @@ fn rewrite_comment_inner( .checked_sub(closer.len() + opener.len()) .unwrap_or(1); let indent_str = shape.indent.to_string(config); - let fmt = StringFormat { + let fmt_indent = shape.indent + (opener.len() - line_start.len()); + let mut fmt = StringFormat { opener: "", closer: "", line_start: line_start, line_end: "", - shape: Shape::legacy(max_chars, shape.indent + (opener.len() - line_start.len())), + shape: Shape::legacy(max_chars, fmt_indent), trim_end: true, config: config, }; @@ -317,26 +318,69 @@ fn rewrite_comment_inner( }); let mut result = opener.to_owned(); + let mut is_prev_line_multi_line = false; + let comment_line_separator = format!("\n{}{}", indent_str, line_start); for line in lines { if result == opener { if line.is_empty() { continue; } } else { - result.push('\n'); - result.push_str(&indent_str); - result.push_str(line_start); + if is_prev_line_multi_line && !line.is_empty() { + result.push(' ') + } else { + result.push_str(&comment_line_separator); + } } - if config.wrap_comments() && line.len() > max_chars { - let rewrite = rewrite_string(line, &fmt).unwrap_or_else(|| line.to_owned()); - result.push_str(&rewrite); + if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { + match rewrite_string(line, &fmt, Some(max_chars)) { + Some(ref s) => { + is_prev_line_multi_line = s.contains('\n'); + result.push_str(s); + } + None if is_prev_line_multi_line => { + // We failed to put the current `line` next to the previous `line`. + // Remove the trailing space, then start rewrite on the next line. + result.pop(); + result.push_str(&comment_line_separator); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + match rewrite_string(line, &fmt, Some(max_chars)) { + Some(ref s) => { + is_prev_line_multi_line = s.contains('\n'); + result.push_str(s); + } + None => { + is_prev_line_multi_line = false; + result.push_str(line); + } + } + } + None => { + is_prev_line_multi_line = false; + result.push_str(line); + } + } + + fmt.shape = if is_prev_line_multi_line { + // 1 = " " + let offset = 1 + last_line_width(&result) - line_start.len(); + Shape { + width: max_chars.checked_sub(offset).unwrap_or(0), + indent: fmt_indent, + offset: fmt.shape.offset + offset, + } + } else { + Shape::legacy(max_chars, fmt_indent) + }; } else { if line.is_empty() && result.ends_with(' ') { // Remove space if this is an empty comment or a doc comment. result.pop(); } result.push_str(line); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + is_prev_line_multi_line = false; } } -- cgit 1.4.1-3-g733a5 From 471e9110f5eac178ff7d19d28353023ea5a7d0c5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 1 Nov 2017 12:35:32 +0900 Subject: Add ftp and file protocols --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0e06545300a..8fad0e01b7a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -396,7 +396,7 @@ fn rewrite_comment_inner( /// Returns true if the given string MAY include URLs or alike. fn has_url(s: &str) -> bool { // This function may return false positive, but should get its job done in most cases. - s.contains("https://") || s.contains("http://") + s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") } /// Given the span, rewrite the missing comment inside it if available. -- cgit 1.4.1-3-g733a5 From f930a16b8d6ad1b4b1be930e34d84a065ee28594 Mon Sep 17 00:00:00 2001 From: Martin Lindhe Date: Wed, 1 Nov 2017 07:33:55 +0100 Subject: fix some typos --- Configurations.md | 10 +++++----- Design.md | 2 +- README.md | 4 ++-- src/chains.rs | 10 +++++----- src/comment.rs | 2 +- src/config.rs | 2 +- src/expr.rs | 2 +- src/issues.rs | 2 +- src/lists.rs | 2 +- src/macros.rs | 2 +- src/patterns.rs | 16 ++++++++-------- src/vertical.rs | 4 ++-- src/visitor.rs | 8 ++++---- tests/source/configs-struct_field_align_threshold-20.rs | 2 +- tests/source/fn-simple.rs | 2 +- tests/source/fn_args_density-vertical.rs | 2 +- tests/source/issue-1049.rs | 2 +- tests/source/issue-1468.rs | 2 +- tests/source/match.rs | 2 +- tests/source/structs.rs | 2 +- tests/source/unions.rs | 2 +- tests/target/configs-struct_field_align_threshold-20.rs | 2 +- tests/target/fn-simple.rs | 2 +- tests/target/fn_args_density-vertical.rs | 2 +- tests/target/issue-1049.rs | 2 +- tests/target/issue-1468.rs | 2 +- tests/target/match.rs | 2 +- tests/target/structs.rs | 2 +- tests/target/unions.rs | 2 +- 29 files changed, 49 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index bd67caef09f..46d94eb1474 100644 --- a/Configurations.md +++ b/Configurations.md @@ -506,7 +506,7 @@ trait Lorem { dolor: Dolor, sit: Sit, amet: Amet, - consectetur: onsectetur, + consectetur: Consectetur, adipiscing: Adipiscing, elit: Elit, ); @@ -516,7 +516,7 @@ trait Lorem { dolor: Dolor, sit: Sit, amet: Amet, - consectetur: onsectetur, + consectetur: Consectetur, adipiscing: Adipiscing, elit: Elit, ) { @@ -569,7 +569,7 @@ trait Lorem { dolor: Dolor, sit: Sit, amet: Amet, - consectetur: onsectetur, + consectetur: Consectetur, adipiscing: Adipiscing, elit: Elit, ) { @@ -598,7 +598,7 @@ trait Lorem { dolor: Dolor, sit: Sit, amet: Amet, - consectetur: onsectetur, + consectetur: Consectetur, adipiscing: Adipiscing, elit: Elit); @@ -606,7 +606,7 @@ trait Lorem { dolor: Dolor, sit: Sit, amet: Amet, - consectetur: onsectetur, + consectetur: Consectetur, adipiscing: Adipiscing, elit: Elit) { // body diff --git a/Design.md b/Design.md index 43caa7b81f8..15b11d82844 100644 --- a/Design.md +++ b/Design.md @@ -151,7 +151,7 @@ for its configuration. Our visitor keeps track of the desired current indent due to blocks ( `block_indent`). Each `visit_*` method reformats code according to this indent, `config.comment_width()` and `config.max_width()`. Most reformatting done in the -`visit_*` methods is a bit hackey and is meant to be temporary until it can be +`visit_*` methods is a bit hacky and is meant to be temporary until it can be done properly. There are a bunch of methods called `rewrite_*`. There do the bulk of the diff --git a/README.md b/README.md index 4942c537437..2041a508074 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ are included as out of line modules from `src/lib.rs`. If `rustfmt` successfully reformatted the code it will exit with `0` exit status. Exit status `1` signals some unexpected error, like an unknown option or a failure to read a file. Exit status `2` is returned if there are syntax errors -in the input files. `rustfmt` can't format syntatically invalid code. Finally, +in the input files. `rustfmt` can't format syntactically invalid code. Finally, exit status `3` is returned if there are some issues which can't be resolved automatically. For example, if you have a very long comment line `rustfmt` doesn't split it. Instead it prints a warning and exits with `3`. @@ -209,7 +209,7 @@ options covering different styles. File an issue, or even better, submit a PR. * When you run rustfmt, place a file named `rustfmt.toml` or `.rustfmt.toml` in target file directory or its parents to override the default settings of rustfmt. You can generate a file containing the default configuration with - `rustfm --dump-default-config rustfmt.toml` and customize as needed. + `rustfmt --dump-default-config rustfmt.toml` and customize as needed. * After successful compilation, a `rustfmt` executable can be found in the target directory. * If you're having issues compiling Rustfmt (or compile errors when trying to diff --git a/src/chains.rs b/src/chains.rs index 20e0be36fe4..e02cef8e38e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -152,8 +152,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }).collect::>>()?; // Total of all items excluding the last. - let extend_last_subexr = last_line_extendable(&parent_rewrite) && rewrites.is_empty(); - let almost_total = if extend_last_subexr { + let extend_last_subexpr = last_line_extendable(&parent_rewrite) && rewrites.is_empty(); + let almost_total = if extend_last_subexpr { last_line_width(&parent_rewrite) } else { rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() @@ -195,7 +195,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // In particular, overflowing is effective when the last child is a method with a multi-lined // block-like argument (e.g. closure): // ``` - // parent.child1.chlid2.last_child(|a, b, c| { + // parent.child1.child2.last_child(|a, b, c| { // let x = foo(a, b, c); // let y = bar(a, b, c); // @@ -208,14 +208,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); - let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexr { + let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. parent_shape.offset_left(almost_total).map(|shape| { if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line expect the last child. - // 2. `last_chlid_str.lines().count() >= 5`. + // 2. `last_child_str.lines().count() >= 5`. let line_count = rw.lines().count(); let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; if fits_single_line && line_count >= 5 { diff --git a/src/comment.rs b/src/comment.rs index 5112c333dee..8a34e3cbe66 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -170,7 +170,7 @@ pub fn combine_strs_with_missing_comments( // We have a missing comment between the first expression and the second expression. // Peek the the original source code and find out whether there is a newline between the first - // expression and the second expression or the missing comment. We will preserve the orginal + // expression and the second expression or the missing comment. We will preserve the original // layout whenever possible. let original_snippet = context.snippet(span); let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { diff --git a/src/config.rs b/src/config.rs index 18969908c86..85008f2915a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -235,7 +235,7 @@ macro_rules! create_config { // Just like the Config struct but with each property wrapped // as Option. This is used to parse a rustfmt.toml that doesn't - // specity all properties of `Config`. + // specify all properties of `Config`. // We first parse into `PartialConfig`, then create a default `Config` // and overwrite the properties with corresponding values from `PartialConfig`. #[derive(Deserialize, Serialize, Clone)] diff --git a/src/expr.rs b/src/expr.rs index 212f05b52b8..9855c7e32d0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -170,7 +170,7 @@ pub fn format_expr( ast::ExprKind::TupField(..) | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), ast::ExprKind::Mac(ref mac) => { - // Failure to rewrite a marco should not imply failure to + // Failure to rewrite a macro should not imply failure to // rewrite the expression. rewrite_macro(mac, None, context, shape, MacroPosition::Expression) .or_else(|| Some(context.snippet(expr.span))) diff --git a/src/issues.rs b/src/issues.rs index b81f902d59f..be30ff2d86e 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Objects for seeking through a char stream for occurences of TODO and FIXME. +// Objects for seeking through a char stream for occurrences of TODO and FIXME. // Depending on the loaded configuration, may also check that these have an // associated issue number. diff --git a/src/lists.rs b/src/lists.rs index bb75c9c60ad..73712033f6e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -572,7 +572,7 @@ where let comment_end = match self.inner.peek() { Some(..) => { let mut block_open_index = post_snippet.find("/*"); - // check if it realy is a block comment (and not //*) + // check if it really is a block comment (and not //*) if let Some(i) = block_open_index { if i > 0 && &post_snippet[i - 1..i] == "/" { block_open_index = None; diff --git a/src/macros.rs b/src/macros.rs index 470f1e84fd8..9d665c4a0b2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -15,7 +15,7 @@ // foo!( x, y, z ). The token x may represent an identifier in the code, but we // interpreted as an expression. // Macro uses which are not-list like, such as bar!(key => val), will not be -// reformated. +// reformatted. // List-like invocations with parentheses will be formatted as function calls, // and those with brackets will be formatted as array literals. diff --git a/src/patterns.rs b/src/patterns.rs index 4df36b87e4d..e4b24bafe2e 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -118,8 +118,8 @@ impl Rewrite for Pat { }; Some(result) } - PatKind::Struct(ref path, ref fields, elipses) => { - rewrite_struct_pat(path, fields, elipses, self.span, context, shape) + PatKind::Struct(ref path, ref fields, ellipsis) => { + rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } // FIXME(#819) format pattern macros. PatKind::Mac(..) => Some(context.snippet(self.span)), @@ -130,7 +130,7 @@ impl Rewrite for Pat { fn rewrite_struct_pat( path: &ast::Path, fields: &[codemap::Spanned], - elipses: bool, + ellipsis: bool, span: Span, context: &RewriteContext, shape: Shape, @@ -139,15 +139,15 @@ fn rewrite_struct_pat( let path_shape = shape.sub_width(2)?; let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - if fields.is_empty() && !elipses { + if fields.is_empty() && !ellipsis { return Some(format!("{} {{}}", path_str)); } - let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") }; + let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") }; // 3 = ` { `, 2 = ` }`. let (h_shape, v_shape) = - struct_lit_shape(shape, context, path_str.len() + 3, elipses_str.len() + 2)?; + struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?; let items = itemize_list( context.codemap, @@ -169,7 +169,7 @@ fn rewrite_struct_pat( let mut fields_str = write_list(&item_vec, &fmt)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); - if elipses { + if ellipsis { if fields_str.contains('\n') || fields_str.len() > one_line_width { // Add a missing trailing comma. if fmt.trailing_separator == SeparatorTactic::Never { @@ -180,7 +180,7 @@ fn rewrite_struct_pat( fields_str.push_str(".."); } else { if !fields_str.is_empty() { - // there are preceeding struct fields being matched on + // there are preceding struct fields being matched on if fmt.tactic == DefinitiveListTactic::Vertical { // if the tactic is Vertical, write_list already added a trailing , fields_str.push_str(" "); diff --git a/src/vertical.rs b/src/vertical.rs index f5636672422..3da31cb0aa3 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -183,7 +183,7 @@ pub fn rewrite_with_alignment( } } -fn struct_field_preix_max_min_width( +fn struct_field_prefix_max_min_width( context: &RewriteContext, fields: &[T], shape: Shape, @@ -219,7 +219,7 @@ fn rewrite_aligned_items_inner( // 1 = "," let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; let (mut field_prefix_max_width, field_prefix_min_width) = - struct_field_preix_max_min_width(context, fields, item_shape); + struct_field_prefix_max_min_width(context, fields, item_shape); let max_diff = field_prefix_max_width .checked_sub(field_prefix_min_width) .unwrap_or(0); diff --git a/src/visitor.rs b/src/visitor.rs index 7d75a1dd3bb..975d2cdf503 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -295,7 +295,7 @@ impl<'a> FmtVisitor<'a> { // complex in the module case. It is complex because the module could be // in a separate file and there might be attributes in both files, but // the AST lumps them all together. - let filterd_attrs; + let filtered_attrs; let mut attrs = &item.attrs; match item.node { ast::ItemKind::Mod(ref m) => { @@ -314,7 +314,7 @@ impl<'a> FmtVisitor<'a> { } else { // Module is not inline and should not be skipped. We want // to process only the attributes in the current file. - filterd_attrs = item.attrs + filtered_attrs = item.attrs .iter() .filter_map(|a| { let attr_file = self.codemap.lookup_char_pos(a.span.lo()).file; @@ -327,8 +327,8 @@ impl<'a> FmtVisitor<'a> { .collect::>(); // Assert because if we should skip it should be caught by // the above case. - assert!(!self.visit_attrs(&filterd_attrs, ast::AttrStyle::Outer)); - attrs = &filterd_attrs; + assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); + attrs = &filtered_attrs; } } _ => if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { diff --git a/tests/source/configs-struct_field_align_threshold-20.rs b/tests/source/configs-struct_field_align_threshold-20.rs index 3f37d72f3c6..e68340b027d 100644 --- a/tests/source/configs-struct_field_align_threshold-20.rs +++ b/tests/source/configs-struct_field_align_threshold-20.rs @@ -159,7 +159,7 @@ pub struct State ()> { now: F } pub struct State { now: F } -struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color +struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color foo: i32} // Splitting a single line comment into a block previously had a misalignment diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index ff08b04c704..f1ce503ab0a 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -7,7 +7,7 @@ fn op(x: Typ, key : &[u8], upd : Box) -> (memcache::S "cool"} -fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* tripple, even */*/*/, +fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* triple, even */*/*/, // Does this work? y: World ) { diff --git a/tests/source/fn_args_density-vertical.rs b/tests/source/fn_args_density-vertical.rs index 7dd4dcbfc4d..b61c337dfb9 100644 --- a/tests/source/fn_args_density-vertical.rs +++ b/tests/source/fn_args_density-vertical.rs @@ -1,6 +1,6 @@ // rustfmt-fn_args_density: Vertical -// Empty list shoul stay on one line. +// Empty list should stay on one line. fn do_bar( ) -> u8 { diff --git a/tests/source/issue-1049.rs b/tests/source/issue-1049.rs index 03f10a1ba38..bcfba41e768 100644 --- a/tests/source/issue-1049.rs +++ b/tests/source/issue-1049.rs @@ -10,7 +10,7 @@ impl Handle { } } -// Long function without return type that should not be reformated. +// Long function without return type that should not be reformatted. fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} diff --git a/tests/source/issue-1468.rs b/tests/source/issue-1468.rs index 1b45aa5d616..4d0d4f0eb98 100644 --- a/tests/source/issue-1468.rs +++ b/tests/source/issue-1468.rs @@ -2,7 +2,7 @@ fn issue1468() { euc_jp_decoder_functions!({ let trail_minus_offset = byte.wrapping_sub(0xA1); // Fast-track Hiragana (60% according to Lunde) -// and Katakana (10% acconding to Lunde). +// and Katakana (10% according to Lunde). if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { // Hiragana diff --git a/tests/source/match.rs b/tests/source/match.rs index 48a710e6f06..19d30b0dd00 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -193,7 +193,7 @@ fn issue355() { nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), // Rewrite splits macro oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), - // Macro support fails to recognise this macro as splitable + // Macro support fails to recognise this macro as splittable // We push the whole expr to a new line, TODO split this macro as well pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), // q, r and s: Rewrite splits match arm diff --git a/tests/source/structs.rs b/tests/source/structs.rs index b782c98635a..e63de8ecdb4 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -132,7 +132,7 @@ pub struct State ()> { now: F } pub struct State { now: F } -struct Palette { /// A map of indizes in the palette to a count of pixels in approximately that color +struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color foo: i32} // Splitting a single line comment into a block previously had a misalignment diff --git a/tests/source/unions.rs b/tests/source/unions.rs index 107be79873c..fc2908e2d9e 100644 --- a/tests/source/unions.rs +++ b/tests/source/unions.rs @@ -93,7 +93,7 @@ pub union State ()> { now: F } pub union State { now: F } -union Palette { /// A map of indizes in the palette to a count of pixels in approximately that color +union Palette { /// A map of indices in the palette to a count of pixels in approximately that color foo: i32} // Splitting a single line comment into a block previously had a misalignment diff --git a/tests/target/configs-struct_field_align_threshold-20.rs b/tests/target/configs-struct_field_align_threshold-20.rs index da933a75c7d..7d8200a0146 100644 --- a/tests/target/configs-struct_field_align_threshold-20.rs +++ b/tests/target/configs-struct_field_align_threshold-20.rs @@ -161,7 +161,7 @@ pub struct State { } struct Palette { - /// A map of indizes in the palette to a count of pixels in approximately + /// A map of indices in the palette to a count of pixels in approximately /// that color foo: i32, } diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 6bbdf4be95d..3b5e884d4a4 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -21,7 +21,7 @@ fn simple( fn weird_comment( // /*/ double level */ comment - x: Hello, // /*/* tripple, even */*/ + x: Hello, // /*/* triple, even */*/ // Does this work? y: World, ) { diff --git a/tests/target/fn_args_density-vertical.rs b/tests/target/fn_args_density-vertical.rs index dcc8478a138..477a48cc35f 100644 --- a/tests/target/fn_args_density-vertical.rs +++ b/tests/target/fn_args_density-vertical.rs @@ -1,6 +1,6 @@ // rustfmt-fn_args_density: Vertical -// Empty list shoul stay on one line. +// Empty list should stay on one line. fn do_bar() -> u8 { bar() } diff --git a/tests/target/issue-1049.rs b/tests/target/issue-1049.rs index 416db998065..c788519ca9a 100644 --- a/tests/target/issue-1049.rs +++ b/tests/target/issue-1049.rs @@ -16,7 +16,7 @@ impl Handle { } } -// Long function without return type that should not be reformated. +// Long function without return type that should not be reformatted. fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { diff --git a/tests/target/issue-1468.rs b/tests/target/issue-1468.rs index e10c83d45ac..4c14a0f746a 100644 --- a/tests/target/issue-1468.rs +++ b/tests/target/issue-1468.rs @@ -2,7 +2,7 @@ fn issue1468() { euc_jp_decoder_functions!({ let trail_minus_offset = byte.wrapping_sub(0xA1); // Fast-track Hiragana (60% according to Lunde) - // and Katakana (10% acconding to Lunde). + // and Katakana (10% according to Lunde). if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { // Hiragana handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) diff --git a/tests/target/match.rs b/tests/target/match.rs index 3d879d18c20..676b8603f2c 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -189,7 +189,7 @@ fn issue355() { oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => { vec![1, 2] } - // Macro support fails to recognise this macro as splitable + // Macro support fails to recognise this macro as splittable // We push the whole expr to a new line, TODO split this macro as well pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { vec![3; 4] diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 8284618bc39..5132162f3d5 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -134,7 +134,7 @@ pub struct State { } struct Palette { - /// A map of indizes in the palette to a count of pixels in approximately + /// A map of indices in the palette to a count of pixels in approximately /// that color foo: i32, } diff --git a/tests/target/unions.rs b/tests/target/unions.rs index cff00d064ff..ed7b842a411 100644 --- a/tests/target/unions.rs +++ b/tests/target/unions.rs @@ -90,7 +90,7 @@ pub union State { } union Palette { - /// A map of indizes in the palette to a count of pixels in approximately + /// A map of indices in the palette to a count of pixels in approximately /// that color foo: i32, } -- cgit 1.4.1-3-g733a5 From 3bae42aa5ada633d8842ac1b172335430110f751 Mon Sep 17 00:00:00 2001 From: clippered Date: Wed, 1 Nov 2017 23:45:35 +1100 Subject: fix output panics on unable to write to stderr --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cd9e19171db..6be778a5262 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -575,7 +575,9 @@ pub fn run(input: Input, config: &Config) -> Summary { if report.has_warnings() { match term::stderr() { - Some(ref t) if isatty() && t.supports_color() => { + Some(ref t) + if isatty() && t.supports_color() && t.supports_attr(term::Attr::Bold) => + { match report.print_warnings_fancy(term::stderr().unwrap()) { Ok(..) => (), Err(..) => panic!("Unable to write to stderr: {}", report), -- cgit 1.4.1-3-g733a5 From 87afdf44672e407033278ae951cb378dbd0104db Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 20:29:10 +0900 Subject: Combine PatKind::TupleStruct --- src/patterns.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index e4b24bafe2e..92e385543b7 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -247,9 +247,10 @@ impl<'a> Spanned for TuplePatField<'a> { pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { match *pat { TuplePatField::Pat(pat) => match pat.node { - ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) => { - context.use_block_indent() && len == 1 - } + ast::PatKind::Path(..) | + ast::PatKind::Tuple(..) | + ast::PatKind::Struct(..) | + ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) } -- cgit 1.4.1-3-g733a5 From 81cd12cc08fa0f12a5c5601f0e4f8740e7ed4648 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 21:41:46 +0900 Subject: Add args_have_many_closure() --- src/expr.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index bb3f5e08c2c..2c562570265 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2281,15 +2281,7 @@ where ast::ExprKind::Closure(..) => { // If the argument consists of multiple closures, we do not overflow // the last closure. - if args.len() > 1 - && args.iter() - .rev() - .skip(1) - .filter_map(|arg| arg.to_expr()) - .any(|expr| match expr.node { - ast::ExprKind::Closure(..) => true, - _ => false, - }) { + if args_have_many_closure(args) { None } else { rewrite_last_closure(context, expr, shape) @@ -2310,6 +2302,22 @@ where } } +fn args_have_many_closure(args: &[&T]) -> bool +where + T: ToExpr, +{ + args.iter() + .filter(|arg| { + arg.to_expr() + .map(|e| match e.node { + ast::ExprKind::Closure(..) => true, + _ => false, + }) + .unwrap_or(false) + }) + .count() > 1 +} + fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool where T: Rewrite + Spanned + ToExpr + 'a, -- cgit 1.4.1-3-g733a5 From e4f13dfdd6d2d644bacc38a3d6eb8c991e47c294 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 21:42:11 +0900 Subject: Use is_unsafe_block() --- src/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2c562570265..0e84a9eb94a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -630,8 +630,7 @@ fn rewrite_closure( } // Figure out if the block is necessary. - let needs_block = block.rules != ast::BlockCheckMode::Default || block.stmts.len() > 1 - || context.inside_macro + let needs_block = is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro || block_contains_comment(block, context.codemap) || prefix.contains('\n'); -- cgit 1.4.1-3-g733a5 From 960fec898b643660b866ce050a30568f79344572 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 21:43:33 +0900 Subject: Force to use block for closure's body when there is only a single control expr --- src/expr.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0e84a9eb94a..eb1b13cc0a1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -641,8 +641,12 @@ fn rewrite_closure( }; if no_return_type && !needs_block { // block.stmts.len() == 1 - if let Some(expr) = stmt_expr(&block.stmts[0]) { - if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, body_shape) { + if let Some(ref expr) = stmt_expr(&block.stmts[0]) { + if let Some(rw) = if is_block_closure_forced(expr) { + rewrite_closure_with_block(context, shape, &prefix, expr) + } else { + rewrite_closure_expr(expr, &prefix, context, body_shape) + } { return Some(rw); } } @@ -2247,7 +2251,34 @@ fn rewrite_last_closure( if prefix.contains('\n') { return None; } + // If we are inside macro, we do not want to add or remove block from closure body. + if context.inside_macro { + return expr.rewrite(context, shape); + } + let body_shape = shape.offset_left(extra_offset)?; + + // We force to use block for the body of the closure for certain kinds of expressions. + if is_block_closure_forced(body) { + return rewrite_closure_with_block(context, body_shape, &prefix, body).and_then( + |body_str| { + // If the expression can fit in a single line, we need not force block closure. + if body_str.lines().count() <= 7 { + match rewrite_closure_expr(body, &prefix, context, shape) { + Some(ref single_line_body_str) + if !single_line_body_str.contains('\n') => + { + Some(single_line_body_str.clone()) + } + _ => Some(body_str), + } + } else { + Some(body_str) + } + }, + ); + } + // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. let is_multi_lined_cond = rewrite_cond(context, body, body_shape) @@ -2263,6 +2294,23 @@ fn rewrite_last_closure( None } +fn is_block_closure_forced(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::If(..) | + ast::ExprKind::IfLet(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) | + ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::AddrOf(_, ref expr) | + ast::ExprKind::Box(ref expr) | + ast::ExprKind::Try(ref expr) | + ast::ExprKind::Unary(_, ref expr) | + ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr), + _ => false, + } +} + fn rewrite_last_arg_with_overflow<'a, T>( context: &RewriteContext, args: &[&T], -- cgit 1.4.1-3-g733a5 From b17de6228faae2d20e5648df4707a85a51f59f42 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 2 Nov 2017 21:45:00 +0900 Subject: Cargo fmt --- src/bin/cargo-fmt.rs | 6 ++++-- src/chains.rs | 10 ++++++---- src/comment.rs | 10 ++++++---- src/expr.rs | 25 +++++++++++++++---------- src/types.rs | 20 ++++++++++++-------- src/vertical.rs | 8 ++++---- src/visitor.rs | 16 +++++++++------- tests/system.rs | 16 +++++++++------- 8 files changed, 65 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 2c0b964b001..53e697d76ac 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -133,8 +133,10 @@ fn format_crate( let files: Vec<_> = targets .into_iter() .filter(|t| t.kind.should_format()) - .inspect(|t| if verbosity == Verbosity::Verbose { - println!("[{:?}] {:?}", t.kind, t.path) + .inspect(|t| { + if verbosity == Verbosity::Verbose { + println!("[{:?}] {:?}", t.kind, t.path) + } }) .map(|t| t.path) .collect(); diff --git a/src/chains.rs b/src/chains.rs index e02cef8e38e..a35648de5c2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -297,10 +297,12 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // True if the chain is only `?`s. fn chain_only_try(exprs: &[ast::Expr]) -> bool { - exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node { - true - } else { - false + exprs.iter().all(|e| { + if let ast::ExprKind::Try(_) = e.node { + true + } else { + false + } }) } diff --git a/src/comment.rs b/src/comment.rs index d3c4e8f12d7..713ef4922d9 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -311,10 +311,12 @@ fn rewrite_comment_inner( line }) .map(|s| left_trim_comment_line(s, &style)) - .map(|line| if orig.starts_with("/*") && line_breaks == 0 { - line.trim_left() - } else { - line + .map(|line| { + if orig.starts_with("/*") && line_breaks == 0 { + line.trim_left() + } else { + line + } }); let mut result = opener.to_owned(); diff --git a/src/expr.rs b/src/expr.rs index eb1b13cc0a1..89cb29881bd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1198,12 +1198,13 @@ impl<'a> ControlFlow<'a> { context .codemap .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), - self.pat - .map_or(cond_span.lo(), |p| if self.matcher.is_empty() { + self.pat.map_or(cond_span.lo(), |p| { + if self.matcher.is_empty() { p.span.lo() } else { context.codemap.span_before(self.span, self.matcher.trim()) - }), + } + }), ); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -2753,13 +2754,17 @@ where if items.len() == 1 { // 3 = "(" + ",)" let nested_shape = shape.sub_width(3)?.visual_indent(1); - return items.next().unwrap().rewrite(context, nested_shape).map( - |s| if context.config.spaces_within_parens() { - format!("( {}, )", s) - } else { - format!("({},)", s) - }, - ); + return items + .next() + .unwrap() + .rewrite(context, nested_shape) + .map(|s| { + if context.config.spaces_within_parens() { + format!("( {}, )", s) + } else { + format!("({},)", s) + } + }); } let list_lo = context.codemap.span_after(span, "("); diff --git a/src/types.rs b/src/types.rs index 21b06ebaff5..4bd942d21c9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -670,10 +670,12 @@ impl Rewrite for ast::Ty { ast::TyKind::Paren(ref ty) => { let budget = shape.width.checked_sub(2)?; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| if context.config.spaces_within_parens() { - format!("( {} )", ty_str) - } else { - format!("({})", ty_str) + .map(|ty_str| { + if context.config.spaces_within_parens() { + format!("( {} )", ty_str) + } else { + format!("({})", ty_str) + } }) } ast::TyKind::Slice(ref ty) => { @@ -683,10 +685,12 @@ impl Rewrite for ast::Ty { shape.width.checked_sub(2)? }; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| if context.config.spaces_within_square_brackets() { - format!("[ {} ]", ty_str) - } else { - format!("[{}]", ty_str) + .map(|ty_str| { + if context.config.spaces_within_square_brackets() { + format!("[ {} ]", ty_str) + } else { + format!("[{}]", ty_str) + } }) } ast::TyKind::Tup(ref items) => rewrite_tuple( diff --git a/src/vertical.rs b/src/vertical.rs index 3da31cb0aa3..32072acfc9e 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -191,13 +191,13 @@ fn struct_field_prefix_max_min_width( fields .iter() .map(|field| { - field - .rewrite_prefix(context, shape) - .and_then(|field_str| if field_str.contains('\n') { + field.rewrite_prefix(context, shape).and_then(|field_str| { + if field_str.contains('\n') { None } else { Some(field_str.len()) - }) + } + }) }) .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { (Some((max_len, min_len)), Some(len)) => { diff --git a/src/visitor.rs b/src/visitor.rs index 975d2cdf503..8a4f7302aa4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -136,13 +136,15 @@ impl<'a> FmtVisitor<'a> { self.last_pos, attr_lo.unwrap_or(first_stmt.span.lo()), )); - let len = CommentCodeSlices::new(&snippet).nth(0).and_then( - |(kind, _, s)| if kind == CodeCharKind::Normal { - s.rfind('\n') - } else { - None - }, - ); + let len = CommentCodeSlices::new(&snippet) + .nth(0) + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal { + s.rfind('\n') + } else { + None + } + }); if let Some(len) = len { self.last_pos = self.last_pos + BytePos::from_usize(len); } diff --git a/tests/system.rs b/tests/system.rs index a633c42d722..29332881c2f 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -446,15 +446,17 @@ struct CharsIgnoreNewlineRepr<'a>(Peekable>); impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { type Item = char; fn next(&mut self) -> Option { - self.0.next().map(|c| if c == '\r' { - if *self.0.peek().unwrap_or(&'\0') == '\n' { - self.0.next(); - '\n' + self.0.next().map(|c| { + if c == '\r' { + if *self.0.peek().unwrap_or(&'\0') == '\n' { + self.0.next(); + '\n' + } else { + '\r' + } } else { - '\r' + c } - } else { - c }) } } -- cgit 1.4.1-3-g733a5 From 9bf81f9d1292bef76d0a46f98a21f07bc3489834 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 3 Nov 2017 08:43:33 +1300 Subject: Remove LicensePolicy (dead code) Fixes #1320 --- src/config.rs | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 85008f2915a..302719e72e3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -113,15 +113,6 @@ impl Density { } } -configuration_option_enum! { LicensePolicy: - // Do not place license text at top of files - NoLicense, - // Use the text in "license" field as the license - TextLicense, - // Use a text file as the license text - FileLicense, -} - configuration_option_enum! { MultilineStyle: // Use horizontal layout if it fits in one line, fall back to vertical PreferSingle, -- cgit 1.4.1-3-g733a5 From bfaeac202af48a70e4a82d8ffb92fe85573af3a1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 3 Nov 2017 08:57:38 +0900 Subject: Add a comment on args_have_many_closure() --- src/expr.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 89cb29881bd..09b9a4e622e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2350,6 +2350,7 @@ where } } +/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. fn args_have_many_closure(args: &[&T]) -> bool where T: ToExpr, -- cgit 1.4.1-3-g733a5 From 84526ab87eb367a968130b54acfd65479be4cd23 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 3 Nov 2017 23:51:19 +0900 Subject: Add get_bytepos_after_visibility() --- src/items.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8adfe080a2c..27e46cb0874 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1154,6 +1154,25 @@ pub fn format_struct_struct( } } +/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not +/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need +/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args. +fn get_bytepos_after_visibility( + context: &RewriteContext, + vis: &ast::Visibility, + default_span: Span, + terminator: &str, +) -> BytePos { + match *vis { + ast::Visibility::Crate(s, CrateSugar::PubCrate) => context + .codemap + .span_after(mk_sp(s.hi(), default_span.hi()), terminator), + ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), + ast::Visibility::Restricted { ref path, .. } => path.span.hi(), + _ => default_span.lo(), + } +} + fn format_tuple_struct( context: &RewriteContext, item_name: &str, -- cgit 1.4.1-3-g733a5 From 3973cdd0a8dcccd986d38d7b3915e88ceeff1a8c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 3 Nov 2017 23:53:07 +0900 Subject: Use correct span for tuple struct's body --- src/items.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 27e46cb0874..5151ec92ced 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1189,12 +1189,13 @@ fn format_tuple_struct( result.push_str(&header_str); let body_lo = if fields.is_empty() { - context.codemap.span_after(span, "(") + let lo = get_bytepos_after_visibility(context, vis, span, ")"); + context.codemap.span_after(mk_sp(lo, span.hi()), "(") } else { fields[0].span.lo() }; let body_hi = if fields.is_empty() { - context.codemap.span_after(span, ")") + context.codemap.span_after(mk_sp(body_lo, span.hi()), ")") } else { // This is a dirty hack to work around a missing `)` from the span of the last field. let last_arg_span = fields[fields.len() - 1].span; @@ -1242,7 +1243,10 @@ fn format_tuple_struct( .to_string(context.config)) } result.push('('); - let snippet = context.snippet(mk_sp(body_lo, context.codemap.span_before(span, ")"))); + let snippet = context.snippet(mk_sp( + body_lo, + context.codemap.span_before(mk_sp(body_lo, span.hi()), ")"), + )); if snippet.is_empty() { // `struct S ()` } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { -- cgit 1.4.1-3-g733a5 From 16302d3578f4faa68051c90b153b581169bc240c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 3 Nov 2017 23:53:38 +0900 Subject: Use get_bytepos_after_visibility() --- src/items.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5151ec92ced..a0ae60b3c37 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1788,13 +1788,7 @@ fn rewrite_fn_base( } // Skip `pub(crate)`. - let lo_after_visibility = match fn_sig.visibility { - ast::Visibility::Crate(s, CrateSugar::PubCrate) => { - context.codemap.span_after(mk_sp(s.hi(), span.hi()), ")") - } - ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), - _ => span.lo(), - }; + let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")"); // A conservative estimation, to goal is to be over all parens in generics let args_start = fn_sig .generics -- cgit 1.4.1-3-g733a5 From d287b06ebac33c73bbb56cbee76f3882c6df1383 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 4 Nov 2017 22:24:43 +0900 Subject: Rename 'chain_one_line_max' to 'chain_width' --- Configurations.md | 12 ++++++------ src/chains.rs | 2 +- src/config.rs | 4 ++-- tests/source/chains.rs | 2 +- tests/source/configs-chain_one_line_max-above.rs | 2 +- tests/source/configs-chain_one_line_max-below.rs | 2 +- tests/target/chains.rs | 2 +- tests/target/configs-chain_one_line_max-above.rs | 2 +- tests/target/configs-chain_one_line_max-below.rs | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 46d94eb1474..29782dbec0e 100644 --- a/Configurations.md +++ b/Configurations.md @@ -227,26 +227,26 @@ let lorem = ipsum.dolor() .elit(); ``` -See also [`chain_one_line_max`](#chain_one_line_max). +See also [`chain_width`](#chain_width). -## `chain_one_line_max` +## `chain_width` Maximum length of a chain to fit on a single line - **Default value**: `60` - **Possible values**: any positive integer -#### Lines shorter than `chain_one_line_max`: +#### Lines shorter than `chain_width`: ```rust let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); ``` -#### Lines longer than `chain_one_line_max`: +#### Lines longer than `chain_width`: See [`chain_indent`](#chain_indent). ## `chain_split_single_child` -Split a chain with a single child if its length exceeds [`chain_one_line_max`](#chain_one_line_max). +Split a chain with a single child if its length exceeds [`chain_width`](#chain_width). - **Default value**: `false` - **Possible values**: `false`, `true` @@ -264,7 +264,7 @@ let files = fs::read_dir("tests/coverage/source") .expect("Couldn't read source dir"); ``` -See also [`chain_one_line_max`](#chain_one_line_max). +See also [`chain_width`](#chain_width). ## `closure_block_indent_threshold` diff --git a/src/chains.rs b/src/chains.rs index a35648de5c2..9864c901dc2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -161,7 +161,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let one_line_budget = if rewrites.is_empty() && !context.config.chain_split_single_child() { shape.width } else { - min(shape.width, context.config.chain_one_line_max()) + min(shape.width, context.config.chain_width()) }; let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) diff --git a/src/config.rs b/src/config.rs index 302719e72e3..99cea7e3c71 100644 --- a/src/config.rs +++ b/src/config.rs @@ -587,9 +587,9 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_indent: IndentStyle, IndentStyle::Block, false, "Indentation of chain"; - chain_one_line_max: usize, 60, false, "Maximum length of a chain to fit on a single line"; + chain_width: usize, 60, false, "Maximum length of a chain to fit on a single line"; chain_split_single_child: bool, false, false, "Split a chain with a single child if its length \ - exceeds `chain_one_line_max`"; + exceeds `chain_width`"; imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 7a8e4dc9176..fe5555f79cb 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chain_one_line_max: 100 +// rustfmt-chain_width: 100 // Test chain formatting. fn main() { diff --git a/tests/source/configs-chain_one_line_max-above.rs b/tests/source/configs-chain_one_line_max-above.rs index 6e72c09b215..d26505b8628 100644 --- a/tests/source/configs-chain_one_line_max-above.rs +++ b/tests/source/configs-chain_one_line_max-above.rs @@ -1,4 +1,4 @@ -// rustfmt-chain_one_line_max: 10 +// rustfmt-chain_width: 10 // Chain one line max fn main() { diff --git a/tests/source/configs-chain_one_line_max-below.rs b/tests/source/configs-chain_one_line_max-below.rs index e869c782d07..d877deb74eb 100644 --- a/tests/source/configs-chain_one_line_max-below.rs +++ b/tests/source/configs-chain_one_line_max-below.rs @@ -1,4 +1,4 @@ -// rustfmt-chain_one_line_max: 100 +// rustfmt-chain_width: 100 // Chain one line max fn main() { diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 573570704ab..d3868e1acd8 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chain_one_line_max: 100 +// rustfmt-chain_width: 100 // Test chain formatting. fn main() { diff --git a/tests/target/configs-chain_one_line_max-above.rs b/tests/target/configs-chain_one_line_max-above.rs index e766f0d0ea2..1b5e12c331a 100644 --- a/tests/target/configs-chain_one_line_max-above.rs +++ b/tests/target/configs-chain_one_line_max-above.rs @@ -1,4 +1,4 @@ -// rustfmt-chain_one_line_max: 10 +// rustfmt-chain_width: 10 // Chain one line max fn main() { diff --git a/tests/target/configs-chain_one_line_max-below.rs b/tests/target/configs-chain_one_line_max-below.rs index e869c782d07..d877deb74eb 100644 --- a/tests/target/configs-chain_one_line_max-below.rs +++ b/tests/target/configs-chain_one_line_max-below.rs @@ -1,4 +1,4 @@ -// rustfmt-chain_one_line_max: 100 +// rustfmt-chain_width: 100 // Chain one line max fn main() { -- cgit 1.4.1-3-g733a5 From 5096cdff56e15e4b9127c67737d59d856b9bb83d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 4 Nov 2017 22:45:09 +0900 Subject: Rename 'array_layout' to 'array_indent' --- Configurations.md | 10 +++++----- legacy-rustfmt.toml | 2 +- src/config.rs | 2 +- src/expr.rs | 10 +++++----- .../configs-array_horizontal_layout_threshold-1000-visual.rs | 2 +- tests/source/configs-array_layout-block.rs | 2 +- tests/source/configs-array_layout-visual.rs | 2 +- tests/source/configs-tab_spaces-2.rs | 2 +- tests/source/configs-tab_spaces-4.rs | 2 +- tests/source/expr-block.rs | 2 +- .../configs-array_horizontal_layout_threshold-1000-visual.rs | 2 +- tests/target/configs-array_layout-block.rs | 2 +- tests/target/configs-array_layout-visual.rs | 2 +- tests/target/configs-tab_spaces-2.rs | 2 +- tests/target/configs-tab_spaces-4.rs | 2 +- tests/target/expr-block.rs | 2 +- 16 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 46d94eb1474..63c6d78b961 100644 --- a/Configurations.md +++ b/Configurations.md @@ -5,7 +5,7 @@ Rustfmt is designed to be very configurable. You can create a TOML file called ` A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this: ```toml -array_layout = "Block" +array_indent = "Block" array_width = 80 reorder_imported_names = true ``` @@ -22,7 +22,7 @@ Use this option to prevent a huge array from being vertically formatted. - **Default value**: `0` - **Possible values**: any positive integer -**Note:** A value of `0` results in [`array_layout`](#array_layout) being applied regardless of a line's width. +**Note:** A value of `0` results in [`array_indent`](#array_indent) being applied regardless of a line's width. #### `0` (default): @@ -50,7 +50,7 @@ let a = vec![ ]; ``` -## `array_layout` +## `array_indent` Indent on arrays @@ -90,7 +90,7 @@ Maximum width of an array literal before falling back to vertical formatting - **Default value**: `60` - **Possible values**: any positive integer -**Note:** A value of `0` results in [`array_layout`](#array_layout) being applied regardless of a line's width. +**Note:** A value of `0` results in [`array_indent`](#array_indent) being applied regardless of a line's width. #### Lines shorter than `array_width`: ```rust @@ -98,7 +98,7 @@ let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", " ``` #### Lines longer than `array_width`: -See [`array_layout`](#array_layout). +See [`array_indent`](#array_indent). ## `attributes_on_same_line_as_field` diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml index da1da764b2e..8442f314197 100644 --- a/legacy-rustfmt.toml +++ b/legacy-rustfmt.toml @@ -1,5 +1,5 @@ fn_args_layout = "Visual" -array_layout = "Visual" +array_indent = "Visual" control_style = "Legacy" where_style = "Legacy" generics_indent = "Visual" diff --git a/src/config.rs b/src/config.rs index 302719e72e3..a223e2da68b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -561,7 +561,7 @@ create_config! { fn_args_density: Density, Density::Tall, false, "Argument density in functions"; fn_args_layout: IndentStyle, IndentStyle::Block, false, "Layout of function arguments and tuple structs"; - array_layout: IndentStyle, IndentStyle::Block, false, "Indent on arrays"; + array_indent: IndentStyle, IndentStyle::Block, false, "Indent on arrays"; array_width: usize, 60, false, "Maximum width of an array literal before falling back to vertical formatting"; array_horizontal_layout_threshold: usize, 0, false, diff --git a/src/expr.rs b/src/expr.rs index 09b9a4e622e..9888ffc3e00 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -419,7 +419,7 @@ where 1 // "[" }; - let nested_shape = match context.config.array_layout() { + let nested_shape = match context.config.array_indent() { IndentStyle::Block => shape .block() .block_indent(context.config.tab_spaces()) @@ -454,7 +454,7 @@ where .iter() .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - let mut tactic = match context.config.array_layout() { + let mut tactic = match context.config.array_indent() { IndentStyle::Block => { // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { @@ -477,7 +477,7 @@ where DefinitiveListTactic::Mixed }, }; - let ends_with_newline = tactic.ends_with_newline(context.config.array_layout()); + let ends_with_newline = tactic.ends_with_newline(context.config.array_indent()); if context.config.array_horizontal_layout_threshold() > 0 && items.len() > context.config.array_horizontal_layout_threshold() { @@ -489,7 +489,7 @@ where separator: ",", trailing_separator: if trailing_comma { SeparatorTactic::Always - } else if context.inside_macro || context.config.array_layout() == IndentStyle::Visual { + } else if context.inside_macro || context.config.array_indent() == IndentStyle::Visual { SeparatorTactic::Never } else { SeparatorTactic::Vertical @@ -502,7 +502,7 @@ where }; let list_str = write_list(&items, &fmt)?; - let result = if context.config.array_layout() == IndentStyle::Visual + let result = if context.config.array_indent() == IndentStyle::Visual || tactic == DefinitiveListTactic::Horizontal { if context.config.spaces_within_square_brackets() && !list_str.is_empty() { diff --git a/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs b/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs index 877d63194e8..84cfb06bced 100644 --- a/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs +++ b/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs @@ -1,5 +1,5 @@ // rustfmt-array_horizontal_layout_threshold: 1000 -// rustfmt-array_layout: Visual +// rustfmt-array_indent: Visual const ARRAY: [u8; 2048] = [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, diff --git a/tests/source/configs-array_layout-block.rs b/tests/source/configs-array_layout-block.rs index 02f38a836c3..7aefa36c187 100644 --- a/tests/source/configs-array_layout-block.rs +++ b/tests/source/configs-array_layout-block.rs @@ -1,4 +1,4 @@ -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // Array layout fn main() { diff --git a/tests/source/configs-array_layout-visual.rs b/tests/source/configs-array_layout-visual.rs index fa0d33a7edf..f448e9607d7 100644 --- a/tests/source/configs-array_layout-visual.rs +++ b/tests/source/configs-array_layout-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-array_layout: Visual +// rustfmt-array_indent: Visual // Array layout fn main() { diff --git a/tests/source/configs-tab_spaces-2.rs b/tests/source/configs-tab_spaces-2.rs index 5caf51bf234..cd3d601e1b6 100644 --- a/tests/source/configs-tab_spaces-2.rs +++ b/tests/source/configs-tab_spaces-2.rs @@ -1,6 +1,6 @@ // rustfmt-tab_spaces: 2 // rustfmt-max_width: 30 -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // Tab spaces fn lorem() { diff --git a/tests/source/configs-tab_spaces-4.rs b/tests/source/configs-tab_spaces-4.rs index 470849e769b..3a18f9be0ee 100644 --- a/tests/source/configs-tab_spaces-4.rs +++ b/tests/source/configs-tab_spaces-4.rs @@ -1,6 +1,6 @@ // rustfmt-tab_spaces: 4 // rustfmt-max_width: 30 -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // Tab spaces fn lorem() { diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 18706783fb4..2b899151535 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -1,4 +1,4 @@ -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // rustfmt-fn_call_style: Block // rustfmt-control_style: Rfc // Test expressions with block formatting. diff --git a/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs b/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs index 1f3dced2943..a4a2f6a3d2c 100644 --- a/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs +++ b/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs @@ -1,5 +1,5 @@ // rustfmt-array_horizontal_layout_threshold: 1000 -// rustfmt-array_layout: Visual +// rustfmt-array_indent: Visual const ARRAY: [u8; 2048] = [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, diff --git a/tests/target/configs-array_layout-block.rs b/tests/target/configs-array_layout-block.rs index a95f808978a..c6c22096759 100644 --- a/tests/target/configs-array_layout-block.rs +++ b/tests/target/configs-array_layout-block.rs @@ -1,4 +1,4 @@ -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // Array layout fn main() { diff --git a/tests/target/configs-array_layout-visual.rs b/tests/target/configs-array_layout-visual.rs index 07b5ae088e6..bd15f2a3737 100644 --- a/tests/target/configs-array_layout-visual.rs +++ b/tests/target/configs-array_layout-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-array_layout: Visual +// rustfmt-array_indent: Visual // Array layout fn main() { diff --git a/tests/target/configs-tab_spaces-2.rs b/tests/target/configs-tab_spaces-2.rs index 73b593d8fe1..3bbb4c05290 100644 --- a/tests/target/configs-tab_spaces-2.rs +++ b/tests/target/configs-tab_spaces-2.rs @@ -1,6 +1,6 @@ // rustfmt-tab_spaces: 2 // rustfmt-max_width: 30 -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // Tab spaces fn lorem() { diff --git a/tests/target/configs-tab_spaces-4.rs b/tests/target/configs-tab_spaces-4.rs index f4f6cd78d95..c8c802c9db5 100644 --- a/tests/target/configs-tab_spaces-4.rs +++ b/tests/target/configs-tab_spaces-4.rs @@ -1,6 +1,6 @@ // rustfmt-tab_spaces: 4 // rustfmt-max_width: 30 -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // Tab spaces fn lorem() { diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 329890e8b12..75d15418ba2 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -1,4 +1,4 @@ -// rustfmt-array_layout: Block +// rustfmt-array_indent: Block // rustfmt-fn_call_style: Block // rustfmt-control_style: Rfc // Test expressions with block formatting. -- cgit 1.4.1-3-g733a5 From 55c2000d947516798dac4ce6055fb1c470b09718 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 4 Nov 2017 22:45:47 +0900 Subject: Rename 'fn_args_layout' to 'fn_args_indent' --- Configurations.md | 2 +- legacy-rustfmt.toml | 2 +- src/config.rs | 2 +- src/items.rs | 20 ++++++++++---------- src/types.rs | 4 ++-- tests/config/small_tabs.toml | 2 +- tests/source/big-impl-rfc.rs | 2 +- tests/source/configs-fn_args_layout-block.rs | 2 +- tests/source/configs-fn_args_layout-visual.rs | 2 +- tests/source/fn-custom-2.rs | 2 +- tests/source/fn-custom-3.rs | 2 +- tests/source/fn-custom-6.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom-8.rs | 2 +- tests/source/fn_args_layout-block.rs | 2 +- tests/source/issue-1278.rs | 2 +- tests/source/where-clause-rfc.rs | 2 +- tests/target/big-impl-rfc.rs | 2 +- tests/target/configs-fn_args_layout-block.rs | 2 +- tests/target/configs-fn_args_layout-visual.rs | 2 +- tests/target/fn-custom-2.rs | 2 +- tests/target/fn-custom-3.rs | 2 +- tests/target/fn-custom-6.rs | 2 +- tests/target/fn-custom-7.rs | 2 +- tests/target/fn-custom-8.rs | 2 +- tests/target/fn_args_layout-block.rs | 2 +- tests/target/issue-1278.rs | 2 +- tests/target/issue-1624.rs | 2 +- tests/target/where-clause-rfc.rs | 2 +- 29 files changed, 39 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 63c6d78b961..f5d2cfa1df0 100644 --- a/Configurations.md +++ b/Configurations.md @@ -614,7 +614,7 @@ trait Lorem { } ``` -## `fn_args_layout` +## `fn_args_indent` Layout of function arguments and tuple structs diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml index 8442f314197..617791a2d25 100644 --- a/legacy-rustfmt.toml +++ b/legacy-rustfmt.toml @@ -1,4 +1,4 @@ -fn_args_layout = "Visual" +fn_args_indent = "Visual" array_indent = "Visual" control_style = "Legacy" where_style = "Legacy" diff --git a/src/config.rs b/src/config.rs index a223e2da68b..d80019b998b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -559,7 +559,7 @@ create_config! { "Location of return type in function declaration"; fn_args_paren_newline: bool, false, false, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; - fn_args_layout: IndentStyle, IndentStyle::Block, false, + fn_args_indent: IndentStyle, IndentStyle::Block, false, "Layout of function arguments and tuple structs"; array_indent: IndentStyle, IndentStyle::Block, false, "Indent on arrays"; array_width: usize, 60, false, diff --git a/src/items.rs b/src/items.rs index 8adfe080a2c..83f74374e32 100644 --- a/src/items.rs +++ b/src/items.rs @@ -933,8 +933,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); let where_density = if (context.config.where_density() == Density::Compressed - && (!result.contains('\n') || context.config.fn_args_layout() == IndentStyle::Block)) - || (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) + && (!result.contains('\n') || context.config.fn_args_indent() == IndentStyle::Block)) + || (context.config.fn_args_indent() == IndentStyle::Block && result.is_empty()) || (context.config.where_density() == Density::CompressedIfEmpty && !has_body && !result.contains('\n')) { @@ -1746,13 +1746,13 @@ fn rewrite_fn_base( } else if context.config.fn_args_paren_newline() { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); - if context.config.fn_args_layout() == IndentStyle::Visual { + if context.config.fn_args_indent() == IndentStyle::Visual { arg_indent = arg_indent + 1; // extra space for `(` } result.push('('); } else { result.push_str("("); - if context.config.fn_args_layout() == IndentStyle::Visual { + if context.config.fn_args_indent() == IndentStyle::Visual { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); } @@ -1805,7 +1805,7 @@ fn rewrite_fn_base( generics_str.contains('\n'), )?; - let put_args_in_block = match context.config.fn_args_layout() { + let put_args_in_block = match context.config.fn_args_indent() { IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, _ => false, } && !fd.inputs.is_empty(); @@ -1846,7 +1846,7 @@ fn rewrite_fn_base( // Return type. if let ast::FunctionRetTy::Ty(..) = fd.output { - let ret_should_indent = match context.config.fn_args_layout() { + let ret_should_indent = match context.config.fn_args_indent() { // If our args are block layout then we surely must have space. IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, _ if args_last_line_contains_comment => false, @@ -2131,7 +2131,7 @@ fn rewrite_args( .and_then(|item| item.post_comment.as_ref()) .map_or(false, |s| s.trim().starts_with("//")); - let (indent, trailing_comma) = match context.config.fn_args_layout() { + let (indent, trailing_comma) = match context.config.fn_args_indent() { IndentStyle::Block if fits_in_one_line => { (indent.block_indent(context.config), SeparatorTactic::Never) } @@ -2168,7 +2168,7 @@ fn rewrite_args( }, separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, indent), - ends_with_newline: tactic.ends_with_newline(context.config.fn_args_layout()), + ends_with_newline: tactic.ends_with_newline(context.config.fn_args_indent()), preserve_newline: true, config: context.config, }; @@ -2218,7 +2218,7 @@ fn compute_budgets_for_args( if one_line_budget > 0 { // 4 = "() {".len() - let (indent, multi_line_budget) = match context.config.fn_args_layout() { + let (indent, multi_line_budget) = match context.config.fn_args_indent() { IndentStyle::Block => { let indent = indent.block_indent(context.config); (indent, context.budget(indent.width() + 1)) @@ -2236,7 +2236,7 @@ fn compute_budgets_for_args( // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(context.config); - let used_space = match context.config.fn_args_layout() { + let used_space = match context.config.fn_args_indent() { // 1 = `,` IndentStyle::Block => new_indent.width() + 1, // Account for `)` and possibly ` {`. diff --git a/src/types.rs b/src/types.rs index 4bd942d21c9..e3f97cc6b70 100644 --- a/src/types.rs +++ b/src/types.rs @@ -302,7 +302,7 @@ where // 2 for () let budget = shape.width.checked_sub(2)?; // 1 for ( - let offset = match context.config.fn_args_layout() { + let offset = match context.config.fn_args_indent() { IndentStyle::Block => { shape .block() @@ -364,7 +364,7 @@ where let list_str = write_list(&item_vec, &fmt)?; - let ty_shape = match context.config.fn_args_layout() { + let ty_shape = match context.config.fn_args_indent() { IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), IndentStyle::Visual => shape.block_left(4)?, }; diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index a682a88e811..f6a972c46b6 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -6,7 +6,7 @@ fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" -fn_args_layout = "Visual" +fn_args_indent = "Visual" where_density = "Tall" where_layout = "Vertical" where_pred_indent = "Visual" diff --git a/tests/source/big-impl-rfc.rs b/tests/source/big-impl-rfc.rs index 2f04ee1ef92..2b3928f431f 100644 --- a/tests/source/big-impl-rfc.rs +++ b/tests/source/big-impl-rfc.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_call_style: Block // rustfmt-generics_indent: Block // rustfmt-where_style: Rfc diff --git a/tests/source/configs-fn_args_layout-block.rs b/tests/source/configs-fn_args_layout-block.rs index 28d1dffe6b3..169a538d70d 100644 --- a/tests/source/configs-fn_args_layout-block.rs +++ b/tests/source/configs-fn_args_layout-block.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // Function arguments layout fn lorem() {} diff --git a/tests/source/configs-fn_args_layout-visual.rs b/tests/source/configs-fn_args_layout-visual.rs index e0af153f982..adc1466bffc 100644 --- a/tests/source/configs-fn_args_layout-visual.rs +++ b/tests/source/configs-fn_args_layout-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Visual +// rustfmt-fn_args_indent: Visual // Function arguments layout fn lorem() {} diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index 8c6813b054f..bdbbb45aaa0 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-generics_indent: Block // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs index 38c7839a49a..2d05b1138f2 100644 --- a/tests/source/fn-custom-3.rs +++ b/tests/source/fn-custom-3.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-generics_indent: Block // rustfmt-where_layout: HorizontalVertical // Test different indents. diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index c056985c796..b8677e4bbec 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index 6ebf4236423..fceb4152575 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_args_density: Vertical // rustfmt-fn_brace_style: AlwaysNextLine diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs index 0855ca1058f..fbc411919c7 100644 --- a/tests/source/fn-custom-8.rs +++ b/tests/source/fn-custom-8.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/source/fn_args_layout-block.rs b/tests/source/fn_args_layout-block.rs index be22369ab8c..4368274cc84 100644 --- a/tests/source/fn_args_layout-block.rs +++ b/tests/source/fn_args_layout-block.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block fn foo() { foo(); diff --git a/tests/source/issue-1278.rs b/tests/source/issue-1278.rs index 1a458060bdd..d199773c834 100644 --- a/tests/source/issue-1278.rs +++ b/tests/source/issue-1278.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout = "block" +// rustfmt-fn_args_indent = "block" #![feature(pub_restricted)] diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs index 678b060602e..7dc5e87a9fe 100644 --- a/tests/source/where-clause-rfc.rs +++ b/tests/source/where-clause-rfc.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-where_style: Rfc fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { diff --git a/tests/target/big-impl-rfc.rs b/tests/target/big-impl-rfc.rs index da5ab03fd5e..5ce1613d23b 100644 --- a/tests/target/big-impl-rfc.rs +++ b/tests/target/big-impl-rfc.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_call_style: Block // rustfmt-generics_indent: Block // rustfmt-where_style: Rfc diff --git a/tests/target/configs-fn_args_layout-block.rs b/tests/target/configs-fn_args_layout-block.rs index 05d5d79a7e3..407a078596d 100644 --- a/tests/target/configs-fn_args_layout-block.rs +++ b/tests/target/configs-fn_args_layout-block.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // Function arguments layout fn lorem() {} diff --git a/tests/target/configs-fn_args_layout-visual.rs b/tests/target/configs-fn_args_layout-visual.rs index 778d6d4fc03..fedea41662a 100644 --- a/tests/target/configs-fn_args_layout-visual.rs +++ b/tests/target/configs-fn_args_layout-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Visual +// rustfmt-fn_args_indent: Visual // Function arguments layout fn lorem() {} diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index 430ffeb9fb7..cec0b29854f 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-generics_indent: Block // rustfmt-where_layout: Mixed // Test different indents. diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 655f1f1dc5b..633ab05030d 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-generics_indent: Block // rustfmt-where_layout: HorizontalVertical // Test different indents. diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 9a2d8d8981a..f7bf2f04eaf 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 1a134128d2b..b9f1820d066 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_args_density: Vertical // rustfmt-fn_brace_style: AlwaysNextLine diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index 854f4231480..78880206f34 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_brace_style: PreferSameLine // Test different indents. diff --git a/tests/target/fn_args_layout-block.rs b/tests/target/fn_args_layout-block.rs index c8847768e13..afe453ca233 100644 --- a/tests/target/fn_args_layout-block.rs +++ b/tests/target/fn_args_layout-block.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block fn foo() { foo(); diff --git a/tests/target/issue-1278.rs b/tests/target/issue-1278.rs index 1a458060bdd..d199773c834 100644 --- a/tests/target/issue-1278.rs +++ b/tests/target/issue-1278.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout = "block" +// rustfmt-fn_args_indent = "block" #![feature(pub_restricted)] diff --git a/tests/target/issue-1624.rs b/tests/target/issue-1624.rs index dcdb18611a6..a41fff2e750 100644 --- a/tests/target/issue-1624.rs +++ b/tests/target/issue-1624.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-fn_args_paren_newline: false // #1624 diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index f52cf3e220e..bf3a93e27fb 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_layout: Block +// rustfmt-fn_args_indent: Block // rustfmt-where_style: Rfc fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -- cgit 1.4.1-3-g733a5 From d5d874099393203365f6f42cd29828c403d94660 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 4 Nov 2017 22:46:40 +0900 Subject: Rename 'fn_call_style' to 'fn_call_indent' --- Configurations.md | 8 ++++---- legacy-rustfmt.toml | 2 +- src/config.rs | 2 +- src/expr.rs | 8 ++++---- src/rewrite.rs | 2 +- src/types.rs | 2 +- tests/source/big-impl-rfc.rs | 2 +- tests/source/closure-block-inside-macro.rs | 2 +- tests/source/configs-fn_call_style-block-trailing-comma.rs | 2 +- tests/source/configs-fn_call_style-block.rs | 2 +- tests/source/configs-fn_call_style-visual-trailing-comma.rs | 2 +- tests/source/configs-fn_call_style-visual.rs | 2 +- tests/source/configs-fn_call_width-zero.rs | 2 +- tests/source/expr-block.rs | 2 +- tests/target/big-impl-rfc.rs | 2 +- tests/target/closure-block-inside-macro.rs | 2 +- tests/target/configs-combine_control_expr-false.rs | 2 +- tests/target/configs-combine_control_expr-true.rs | 2 +- tests/target/configs-fn_call_style-block-tab_spaces-2.rs | 2 +- tests/target/configs-fn_call_style-block-trailing-comma.rs | 2 +- tests/target/configs-fn_call_style-block.rs | 2 +- tests/target/configs-fn_call_style-visual-trailing-comma.rs | 2 +- tests/target/configs-fn_call_style-visual.rs | 2 +- tests/target/configs-fn_call_width-zero.rs | 2 +- tests/target/expr-block.rs | 2 +- 25 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index f5d2cfa1df0..ae50daf7211 100644 --- a/Configurations.md +++ b/Configurations.md @@ -298,7 +298,7 @@ lorem_ipsum(|| { }); ``` -**Note**: This option only takes effect when `fn_call_style` is set to `"Visual"`. +**Note**: This option only takes effect when `fn_call_indent` is set to `"Visual"`. ## `combine_control_expr` @@ -758,7 +758,7 @@ where } ``` -## `fn_call_style` +## `fn_call_indent` Indentation for function calls, etc. @@ -809,7 +809,7 @@ lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "el #### Function call longer than `fn_call_width`: -See [`fn_call_style`](#fn_call_style). +See [`fn_call_indent`](#fn_call_indent). ## `fn_empty_single_line` @@ -874,7 +874,7 @@ fn lorem(ipsum: Ipsum, ``` -**Note**: This option only takes effect when `fn_call_style` is set to `"Visual"`. +**Note**: This option only takes effect when `fn_call_indent` is set to `"Visual"`. ## `fn_single_line` diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml index 617791a2d25..6adaf36b6b3 100644 --- a/legacy-rustfmt.toml +++ b/legacy-rustfmt.toml @@ -3,6 +3,6 @@ array_indent = "Visual" control_style = "Legacy" where_style = "Legacy" generics_indent = "Visual" -fn_call_style = "Visual" +fn_call_indent = "Visual" combine_control_expr = false fn_args_paren_newline = true diff --git a/src/config.rs b/src/config.rs index d80019b998b..a0d1dda2126 100644 --- a/src/config.rs +++ b/src/config.rs @@ -581,7 +581,7 @@ create_config! { struct_lit_style: IndentStyle, IndentStyle::Block, false, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, false, "Multiline style on literal structs"; - fn_call_style: IndentStyle, IndentStyle::Block, false, "Indentation for function calls, etc."; + fn_call_indent: IndentStyle, IndentStyle::Block, false, "Indentation for function calls, etc."; report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, diff --git a/src/expr.rs b/src/expr.rs index 9888ffc3e00..0bc09c7a390 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2033,7 +2033,7 @@ where let used_width = extra_offset(callee_str, shape); let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; - let nested_shape = shape_from_fn_call_style( + let nested_shape = shape_from_fn_call_indent( context, shape, used_width + 2 * paren_overhead, @@ -2379,7 +2379,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l match expr.node { ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) - || (context.config.fn_call_style() == IndentStyle::Visual && args_len > 1) + || (context.config.fn_call_indent() == IndentStyle::Visual && args_len > 1) } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | @@ -2391,7 +2391,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l } ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { context.use_block_indent() - || context.config.fn_call_style() == IndentStyle::Visual && args_len > 1 + || context.config.fn_call_indent() == IndentStyle::Visual && args_len > 1 } ast::ExprKind::Array(..) | ast::ExprKind::Call(..) | @@ -2722,7 +2722,7 @@ pub fn rewrite_field( } } -fn shape_from_fn_call_style( +fn shape_from_fn_call_indent( context: &RewriteContext, shape: Shape, overhead: usize, diff --git a/src/rewrite.rs b/src/rewrite.rs index e2be8ef086c..823f69dc6ff 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -43,7 +43,7 @@ impl<'a> RewriteContext<'a> { /// Return true if we should use block indent style for rewriting function call. pub fn use_block_indent(&self) -> bool { - self.config.fn_call_style() == IndentStyle::Block || self.use_block + self.config.fn_call_indent() == IndentStyle::Block || self.use_block } pub fn budget(&self, used_width: usize) -> usize { diff --git a/src/types.rs b/src/types.rs index e3f97cc6b70..fd41fedabb6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -357,7 +357,7 @@ where }, separator_place: SeparatorPlace::Back, shape: list_shape, - ends_with_newline: tactic.ends_with_newline(context.config.fn_call_style()), + ends_with_newline: tactic.ends_with_newline(context.config.fn_call_indent()), preserve_newline: true, config: context.config, }; diff --git a/tests/source/big-impl-rfc.rs b/tests/source/big-impl-rfc.rs index 2b3928f431f..86812fd5379 100644 --- a/tests/source/big-impl-rfc.rs +++ b/tests/source/big-impl-rfc.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_indent: Block -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-generics_indent: Block // rustfmt-where_style: Rfc diff --git a/tests/source/closure-block-inside-macro.rs b/tests/source/closure-block-inside-macro.rs index d567008c2ad..2f7e04957e9 100644 --- a/tests/source/closure-block-inside-macro.rs +++ b/tests/source/closure-block-inside-macro.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // #1547 fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { diff --git a/tests/source/configs-fn_call_style-block-trailing-comma.rs b/tests/source/configs-fn_call_style-block-trailing-comma.rs index ad813f6b98a..9d948594d8b 100644 --- a/tests/source/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/source/configs-fn_call_style-block-trailing-comma.rs @@ -1,5 +1,5 @@ // rustfmt-error_on_line_overflow: false -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { diff --git a/tests/source/configs-fn_call_style-block.rs b/tests/source/configs-fn_call_style-block.rs index ee6178c1902..76ccb001595 100644 --- a/tests/source/configs-fn_call_style-block.rs +++ b/tests/source/configs-fn_call_style-block.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // Function call style fn main() { diff --git a/tests/source/configs-fn_call_style-visual-trailing-comma.rs b/tests/source/configs-fn_call_style-visual-trailing-comma.rs index 61be7c5ea93..d6d1a86a631 100644 --- a/tests/source/configs-fn_call_style-visual-trailing-comma.rs +++ b/tests/source/configs-fn_call_style-visual-trailing-comma.rs @@ -1,5 +1,5 @@ // rustfmt-error_on_line_overflow: false -// rustfmt-fn_call_style: Visual +// rustfmt-fn_call_indent: Visual // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { diff --git a/tests/source/configs-fn_call_style-visual.rs b/tests/source/configs-fn_call_style-visual.rs index 1cb48cfadd6..9561ffae23b 100644 --- a/tests/source/configs-fn_call_style-visual.rs +++ b/tests/source/configs-fn_call_style-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Visual +// rustfmt-fn_call_indent: Visual // Function call style fn main() { diff --git a/tests/source/configs-fn_call_width-zero.rs b/tests/source/configs-fn_call_width-zero.rs index ee79c4ce805..da227dec4c7 100644 --- a/tests/source/configs-fn_call_width-zero.rs +++ b/tests/source/configs-fn_call_width-zero.rs @@ -1,5 +1,5 @@ // rustfmt-fn_call_width: 0 -// rustfmt-fn_call_style: block +// rustfmt-fn_call_indent: block // #1508 fn a() { diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 2b899151535..3d46e3a9801 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -1,5 +1,5 @@ // rustfmt-array_indent: Block -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-control_style: Rfc // Test expressions with block formatting. diff --git a/tests/target/big-impl-rfc.rs b/tests/target/big-impl-rfc.rs index 5ce1613d23b..b5c7b376f78 100644 --- a/tests/target/big-impl-rfc.rs +++ b/tests/target/big-impl-rfc.rs @@ -1,5 +1,5 @@ // rustfmt-fn_args_indent: Block -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-generics_indent: Block // rustfmt-where_style: Rfc diff --git a/tests/target/closure-block-inside-macro.rs b/tests/target/closure-block-inside-macro.rs index d567008c2ad..2f7e04957e9 100644 --- a/tests/target/closure-block-inside-macro.rs +++ b/tests/target/closure-block-inside-macro.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // #1547 fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { diff --git a/tests/target/configs-combine_control_expr-false.rs b/tests/target/configs-combine_control_expr-false.rs index 0d9ab24a6ed..432b2a03960 100644 --- a/tests/target/configs-combine_control_expr-false.rs +++ b/tests/target/configs-combine_control_expr-false.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-combine_control_expr: false // Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. diff --git a/tests/target/configs-combine_control_expr-true.rs b/tests/target/configs-combine_control_expr-true.rs index 925d2233539..58db874a825 100644 --- a/tests/target/configs-combine_control_expr-true.rs +++ b/tests/target/configs-combine_control_expr-true.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-combine_control_expr: true // Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. diff --git a/tests/target/configs-fn_call_style-block-tab_spaces-2.rs b/tests/target/configs-fn_call_style-block-tab_spaces-2.rs index 482c5c0e82a..238ab10060e 100644 --- a/tests/target/configs-fn_call_style-block-tab_spaces-2.rs +++ b/tests/target/configs-fn_call_style-block-tab_spaces-2.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-max_width: 80 // rustfmt-tab_spaces: 2 diff --git a/tests/target/configs-fn_call_style-block-trailing-comma.rs b/tests/target/configs-fn_call_style-block-trailing-comma.rs index 4405f89f2af..f54715aea55 100644 --- a/tests/target/configs-fn_call_style-block-trailing-comma.rs +++ b/tests/target/configs-fn_call_style-block-trailing-comma.rs @@ -1,5 +1,5 @@ // rustfmt-error_on_line_overflow: false -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { diff --git a/tests/target/configs-fn_call_style-block.rs b/tests/target/configs-fn_call_style-block.rs index 75d6b6765fb..0f9cbfcc0e3 100644 --- a/tests/target/configs-fn_call_style-block.rs +++ b/tests/target/configs-fn_call_style-block.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // Function call style fn main() { diff --git a/tests/target/configs-fn_call_style-visual-trailing-comma.rs b/tests/target/configs-fn_call_style-visual-trailing-comma.rs index 61be7c5ea93..d6d1a86a631 100644 --- a/tests/target/configs-fn_call_style-visual-trailing-comma.rs +++ b/tests/target/configs-fn_call_style-visual-trailing-comma.rs @@ -1,5 +1,5 @@ // rustfmt-error_on_line_overflow: false -// rustfmt-fn_call_style: Visual +// rustfmt-fn_call_indent: Visual // rustfmt should not add trailing comma when rewriting macro. See #1528. fn a() { diff --git a/tests/target/configs-fn_call_style-visual.rs b/tests/target/configs-fn_call_style-visual.rs index 598c2fff280..3a1e53a2274 100644 --- a/tests/target/configs-fn_call_style-visual.rs +++ b/tests/target/configs-fn_call_style-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_call_style: Visual +// rustfmt-fn_call_indent: Visual // Function call style fn main() { diff --git a/tests/target/configs-fn_call_width-zero.rs b/tests/target/configs-fn_call_width-zero.rs index 3193bc228f7..f91a03c8188 100644 --- a/tests/target/configs-fn_call_width-zero.rs +++ b/tests/target/configs-fn_call_width-zero.rs @@ -1,5 +1,5 @@ // rustfmt-fn_call_width: 0 -// rustfmt-fn_call_style: block +// rustfmt-fn_call_indent: block // #1508 fn a() { diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 75d15418ba2..a76c761f1dc 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -1,5 +1,5 @@ // rustfmt-array_indent: Block -// rustfmt-fn_call_style: Block +// rustfmt-fn_call_indent: Block // rustfmt-control_style: Rfc // Test expressions with block formatting. -- cgit 1.4.1-3-g733a5 From 40c5666af6bda89d3c8d5d12d01a53ed0afaf1e6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 4 Nov 2017 22:47:28 +0900 Subject: Rename 'struct_lit_style' to 'struct_lit_indent' --- Configurations.md | 10 +++++----- src/config.rs | 2 +- src/expr.rs | 4 ++-- src/lists.rs | 6 +++--- tests/config/small_tabs.toml | 2 +- tests/source/configs-struct_lit_style-block.rs | 2 +- tests/source/configs-struct_lit_style-visual.rs | 2 +- tests/source/struct_lits_visual.rs | 2 +- tests/source/struct_lits_visual_multiline.rs | 2 +- tests/source/struct_tuple_visual.rs | 2 +- tests/target/configs-struct_lit_style-block.rs | 2 +- tests/target/configs-struct_lit_style-visual.rs | 2 +- tests/target/struct_lits_visual.rs | 2 +- tests/target/struct_lits_visual_multiline.rs | 2 +- tests/target/struct_tuple_visual.rs | 2 +- 15 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ae50daf7211..ee340f438ff 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1868,9 +1868,9 @@ let lorem = Lorem { }; ``` -See also: [`struct_lit_style`](#struct_lit_style), [`struct_lit_width`](#struct_lit_width). +See also: [`struct_lit_indent`](#struct_lit_indent), [`struct_lit_width`](#struct_lit_width). -## `struct_lit_style` +## `struct_lit_indent` Style of struct definition @@ -1893,7 +1893,7 @@ let lorem = Lorem { ipsum: dolor, sit: amet, }; ``` -See also: [`struct_lit_multiline_style`](#struct_lit_multiline_style), [`struct_lit_style`](#struct_lit_style). +See also: [`struct_lit_multiline_style`](#struct_lit_multiline_style), [`struct_lit_indent`](#struct_lit_indent). ## `struct_lit_width` @@ -1910,9 +1910,9 @@ let lorem = Lorem { ipsum: dolor, sit: amet }; ``` #### Lines longer than `struct_lit_width`: -See [`struct_lit_style`](#struct_lit_style). +See [`struct_lit_indent`](#struct_lit_indent). -See also: [`struct_lit_multiline_style`](#struct_lit_multiline_style), [`struct_lit_style`](#struct_lit_style). +See also: [`struct_lit_multiline_style`](#struct_lit_multiline_style), [`struct_lit_indent`](#struct_lit_indent). ## `struct_variant_width` diff --git a/src/config.rs b/src/config.rs index a0d1dda2126..e9123ffc8cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -578,7 +578,7 @@ create_config! { where_pred_indent: IndentStyle, IndentStyle::Visual, false, "Indentation style of a where predicate"; generics_indent: IndentStyle, IndentStyle::Block, false, "Indentation of generics"; - struct_lit_style: IndentStyle, IndentStyle::Block, false, "Style of struct definition"; + struct_lit_indent: IndentStyle, IndentStyle::Block, false, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, false, "Multiline style on literal structs"; fn_call_indent: IndentStyle, IndentStyle::Block, false, "Indentation for function calls, etc."; diff --git a/src/expr.rs b/src/expr.rs index 0bc09c7a390..a297b00a5f2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2640,7 +2640,7 @@ fn rewrite_struct_lit<'a>( let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); Some(format!("{} {{{}}}", path_str, fields_str)) - // FIXME if context.config.struct_lit_style() == Visual, but we run out + // FIXME if context.config.struct_lit_indent() == Visual, but we run out // of space, we should fall back to BlockIndent. } @@ -2651,7 +2651,7 @@ pub fn wrap_struct_field( nested_shape: Shape, one_line_width: usize, ) -> String { - if context.config.struct_lit_style() == IndentStyle::Block + if context.config.struct_lit_indent() == IndentStyle::Block && (fields_str.contains('\n') || context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || fields_str.len() > one_line_width) diff --git a/src/lists.rs b/src/lists.rs index 73712033f6e..d560c88886c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -737,7 +737,7 @@ pub fn struct_lit_shape( prefix_width: usize, suffix_width: usize, ) -> Option<(Option, Shape)> { - let v_shape = match context.config.struct_lit_style() { + let v_shape = match context.config.struct_lit_indent() { IndentStyle::Visual => shape .visual_indent(0) .shrink_left(prefix_width)? @@ -766,7 +766,7 @@ pub fn struct_lit_tactic( items: &[ListItem], ) -> DefinitiveListTactic { if let Some(h_shape) = h_shape { - let prelim_tactic = match (context.config.struct_lit_style(), items.len()) { + let prelim_tactic = match (context.config.struct_lit_indent(), items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style().to_list_tactic(), }; @@ -797,7 +797,7 @@ pub fn struct_lit_formatting<'a>( context: &'a RewriteContext, force_no_trailing_comma: bool, ) -> ListFormatting<'a> { - let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual + let ends_with_newline = context.config.struct_lit_indent() != IndentStyle::Visual && tactic == DefinitiveListTactic::Vertical; ListFormatting { tactic: tactic, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index f6a972c46b6..d48810bd578 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -12,7 +12,7 @@ where_layout = "Vertical" where_pred_indent = "Visual" generics_indent = "Visual" trailing_comma = "Vertical" -struct_lit_style = "Block" +struct_lit_indent = "Block" report_todo = "Always" report_fixme = "Never" reorder_imports = false diff --git a/tests/source/configs-struct_lit_style-block.rs b/tests/source/configs-struct_lit_style-block.rs index 69caa81ba09..4f66c192bbc 100644 --- a/tests/source/configs-struct_lit_style-block.rs +++ b/tests/source/configs-struct_lit_style-block.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: Block +// rustfmt-struct_lit_indent: Block // Struct literal-style fn main() { diff --git a/tests/source/configs-struct_lit_style-visual.rs b/tests/source/configs-struct_lit_style-visual.rs index 1e461b3d64a..837ae1b40cb 100644 --- a/tests/source/configs-struct_lit_style-visual.rs +++ b/tests/source/configs-struct_lit_style-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual // Struct literal-style fn main() { diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index 9156328dd0f..de083183ab9 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual // rustfmt-error_on_line_overflow: false // Struct literal expressions. diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs index 16c06934c28..e8af1486f36 100644 --- a/tests/source/struct_lits_visual_multiline.rs +++ b/tests/source/struct_lits_visual_multiline.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual // rustfmt-struct_lit_multiline_style: ForceMulti // rustfmt-error_on_line_overflow: false diff --git a/tests/source/struct_tuple_visual.rs b/tests/source/struct_tuple_visual.rs index d7d9e961bc4..2bc2c11d333 100644 --- a/tests/source/struct_tuple_visual.rs +++ b/tests/source/struct_tuple_visual.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-error_on_line_overflow: false -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual fn foo() { Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); diff --git a/tests/target/configs-struct_lit_style-block.rs b/tests/target/configs-struct_lit_style-block.rs index dc64fcfd159..19e276c2d76 100644 --- a/tests/target/configs-struct_lit_style-block.rs +++ b/tests/target/configs-struct_lit_style-block.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: Block +// rustfmt-struct_lit_indent: Block // Struct literal-style fn main() { diff --git a/tests/target/configs-struct_lit_style-visual.rs b/tests/target/configs-struct_lit_style-visual.rs index eb470e1e29c..fd20e2cde6c 100644 --- a/tests/target/configs-struct_lit_style-visual.rs +++ b/tests/target/configs-struct_lit_style-visual.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual // Struct literal-style fn main() { diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 7a0abb480e8..cef6e8b68c5 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual // rustfmt-error_on_line_overflow: false // Struct literal expressions. diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs index 02bbfa18784..74dd654ac50 100644 --- a/tests/target/struct_lits_visual_multiline.rs +++ b/tests/target/struct_lits_visual_multiline.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual // rustfmt-struct_lit_multiline_style: ForceMulti // rustfmt-error_on_line_overflow: false diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs index 02811668bcb..7723f042e6f 100644 --- a/tests/target/struct_tuple_visual.rs +++ b/tests/target/struct_tuple_visual.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-error_on_line_overflow: false -// rustfmt-struct_lit_style: Visual +// rustfmt-struct_lit_indent: Visual fn foo() { Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); -- cgit 1.4.1-3-g733a5 From 18ac341413cbac544ee16be0a0dbab865947fb63 Mon Sep 17 00:00:00 2001 From: Anthony Deschamps Date: Sat, 4 Nov 2017 15:24:41 -0400 Subject: Handle case where there is a where clause but no generic parameters. Fixes #2103 --- src/items.rs | 12 ++++++++++-- tests/target/issue-2103.rs | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-2103.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8adfe080a2c..8fe51f7855c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1070,6 +1070,7 @@ pub fn format_struct_struct( let header_str = format_header(item_name, ident, vis); result.push_str(&header_str); + let header_hi = span.lo() + BytePos(header_str.len() as u32); let body_lo = context.codemap.span_after(span, "{"); let generics_str = match generics { @@ -1081,7 +1082,7 @@ pub fn format_struct_struct( context.config.item_brace_style(), fields.is_empty(), offset, - mk_sp(span.lo(), body_lo), + mk_sp(header_hi, body_lo), last_line_width(&result), )?, None => { @@ -2663,6 +2664,13 @@ fn format_generics( let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = context.budget(last_line_used_width(&result, offset.width())); let option = WhereClauseOption::snuggled(&result); + // If the generics are not parameterized then generics.span.hi() == 0, + // so we use span.lo(), which is the position after `struct Foo`. + let span_end_before_where = if generics.is_parameterized() { + generics.span.hi() + } else { + span.lo() + }; let where_clause_str = rewrite_where_clause( context, &generics.where_clause, @@ -2671,7 +2679,7 @@ fn format_generics( Density::Tall, terminator, Some(span.hi()), - generics.span.hi(), + span_end_before_where, option, )?; result.push_str(&where_clause_str); diff --git a/tests/target/issue-2103.rs b/tests/target/issue-2103.rs new file mode 100644 index 00000000000..5a043d54b75 --- /dev/null +++ b/tests/target/issue-2103.rs @@ -0,0 +1,14 @@ +struct X +where + i32: Sized, +{ + x: i32, +} + +struct X +// with comment +where + i32: Sized, +{ + x: i32, +} -- cgit 1.4.1-3-g733a5 From 536526685d296d81ec52755f85f1b369daab87f4 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Sun, 5 Nov 2017 12:26:06 +0100 Subject: Fix compile on 2017-11-04 nightly Breakage came from https://github.com/rust-lang/rust/pull/45247/ --- src/items.rs | 2 +- src/visitor.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8fe51f7855c..728433b62ec 100644 --- a/src/items.rs +++ b/src/items.rs @@ -894,7 +894,7 @@ pub fn format_struct( } pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { - if let ast::ItemKind::Trait(unsafety, ref generics, ref type_param_bounds, ref trait_items) = + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = item.node { let mut result = String::with_capacity(128); diff --git a/src/visitor.rs b/src/visitor.rs index 8a4f7302aa4..642f75e58ab 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -418,7 +418,7 @@ impl<'a> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } - ast::ItemKind::DefaultImpl(..) => { + ast::ItemKind::AutoImpl(..) => { // FIXME(#78): format impl definitions. } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { -- cgit 1.4.1-3-g733a5 From f412c875ea25d5f68bafe0837ccf46998596588e Mon Sep 17 00:00:00 2001 From: Afshin Mehrabani Date: Sun, 5 Nov 2017 22:53:17 +0000 Subject: Adding where_single_line option (#2030) * feat(where): adding where_single_line option and tests * fix(where): adding more tests * feat(where): changing the shape of where clause when where_single_line is true * feat: newline_for_brace should avoid adding a new line where where_single_line is true * fix(items): where_single_line should bypass the multi-item where clauses * fix(items): refactoring and removing redundant variables * fix(items): where_single_line should not be functional when args are multilined * fix(config): fixing conflict with upstream --- src/config.rs | 1 + src/items.rs | 39 ++++++++++++++++++++++++++----- tests/source/configs-where_single_line.rs | 24 +++++++++++++++++++ tests/target/configs-where_single_line.rs | 29 +++++++++++++++++++++++ 4 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 tests/source/configs-where_single_line.rs create mode 100644 tests/target/configs-where_single_line.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 99db3e6aca1..28839031836 100644 --- a/src/config.rs +++ b/src/config.rs @@ -574,6 +574,7 @@ create_config! { // function decl? // 2. Currently options `Tall` and `Vertical` produce the same output. where_density: Density, Density::Vertical, false, "Density of a where clause"; + where_single_line: bool, false, false, "To force single line where layout"; where_layout: ListTactic, ListTactic::Vertical, false, "Element layout inside a where clause"; where_pred_indent: IndentStyle, IndentStyle::Visual, false, "Indentation style of a where predicate"; diff --git a/src/items.rs b/src/items.rs index c179b44ede8..989793cb6ba 100644 --- a/src/items.rs +++ b/src/items.rs @@ -593,6 +593,7 @@ pub fn format_impl( where_span_end, self_ty.span.hi(), option, + false, )?; // If there is no where clause, we may have missing comments between the trait name and @@ -960,6 +961,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) None, pos_before_where, option, + false, )?; // If the where clause cannot fit on the same line, // put the where clause on a new line @@ -1229,6 +1231,7 @@ fn format_tuple_struct( None, body_hi, option, + false, )? } None => "".to_owned(), @@ -1321,6 +1324,7 @@ pub fn rewrite_type_alias( Some(span.hi()), generics.span.hi(), option, + false, )?; result.push_str(&where_clause_str); if where_clause_str.is_empty() { @@ -1954,6 +1958,8 @@ fn rewrite_fn_base( ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), }; + let is_args_multi_lined = arg_str.contains('\n'); + if where_clause.predicates.len() == 1 && should_compress_where { let budget = context.budget(last_line_used_width(&result, indent.width())); if let Some(where_clause_str) = rewrite_where_clause( @@ -1966,6 +1972,7 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, WhereClauseOption::compressed(), + is_args_multi_lined, ) { result.push_str(&where_clause_str); force_new_line_for_brace |= last_line_contains_single_line_comment(&result); @@ -1984,6 +1991,7 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, + is_args_multi_lined, )?; // If there are neither where clause nor return type, we may be missing comments between // args and `{`. @@ -2007,6 +2015,7 @@ fn rewrite_fn_base( result.push_str(&where_clause_str); force_new_line_for_brace |= last_line_contains_single_line_comment(&result); + force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line(); Some((result, force_new_line_for_brace)) } @@ -2264,11 +2273,16 @@ fn compute_budgets_for_args( } fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: bool) -> bool { + let predicate_count = where_clause.predicates.len(); + + if config.where_single_line() && predicate_count == 1 { + return false; + } match (config.fn_brace_style(), config.where_density()) { (BraceStyle::AlwaysNextLine, _) => true, - (_, Density::Compressed) if where_clause.predicates.len() == 1 => false, - (_, Density::CompressedIfEmpty) if where_clause.predicates.len() == 1 && !has_body => false, - (BraceStyle::SameLineWhere, _) if !where_clause.predicates.is_empty() => true, + (_, Density::Compressed) if predicate_count == 1 => false, + (_, Density::CompressedIfEmpty) if predicate_count == 1 && !has_body => false, + (BraceStyle::SameLineWhere, _) if predicate_count > 0 => true, _ => false, } } @@ -2444,6 +2458,7 @@ fn rewrite_where_clause_rfc_style( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, + is_args_multi_line: bool, ) -> Option { let block_shape = shape.block().with_max_width(context.config); @@ -2479,14 +2494,23 @@ fn rewrite_where_clause_rfc_style( span_end, false, ); - let comma_tactic = if where_clause_option.suppress_comma { + let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line; + let comma_tactic = if where_clause_option.suppress_comma || where_single_line { SeparatorTactic::Never } else { context.config.trailing_comma() }; + // shape should be vertical only and only if we have `where_single_line` option enabled + // and the number of items of the where clause is equal to 1 + let shape_tactic = if where_single_line { + DefinitiveListTactic::Horizontal + } else { + DefinitiveListTactic::Vertical + }; + let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, + tactic: shape_tactic, separator: ",", trailing_separator: comma_tactic, separator_place: SeparatorPlace::Back, @@ -2508,7 +2532,7 @@ fn rewrite_where_clause_rfc_style( // 6 = `where ` let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() && comment_after.is_empty() && !preds_str.contains('\n') - && 6 + preds_str.len() <= shape.width + && 6 + preds_str.len() <= shape.width || where_single_line { String::from(" ") } else { @@ -2536,6 +2560,7 @@ fn rewrite_where_clause( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, + is_args_multi_line: bool, ) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); @@ -2550,6 +2575,7 @@ fn rewrite_where_clause( span_end, span_end_before_where, where_clause_option, + is_args_multi_line, ); } @@ -2698,6 +2724,7 @@ fn format_generics( Some(span.hi()), span_end_before_where, option, + false, )?; result.push_str(&where_clause_str); force_same_line_brace || brace_style == BraceStyle::PreferSameLine diff --git a/tests/source/configs-where_single_line.rs b/tests/source/configs-where_single_line.rs new file mode 100644 index 00000000000..daaab865af2 --- /dev/null +++ b/tests/source/configs-where_single_line.rs @@ -0,0 +1,24 @@ +// rustfmt-where_single_line: true +// Where style + + +fn lorem_two_items() -> T where Ipsum: Eq, Lorem: Eq { + // body +} + +fn lorem_multi_line( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T +where + Ipsum: Eq, +{ + // body +} + +fn lorem() -> T where Ipsum: Eq { + // body +} diff --git a/tests/target/configs-where_single_line.rs b/tests/target/configs-where_single_line.rs new file mode 100644 index 00000000000..15ad1508b2d --- /dev/null +++ b/tests/target/configs-where_single_line.rs @@ -0,0 +1,29 @@ +// rustfmt-where_single_line: true +// Where style + + +fn lorem_two_items() -> T +where + Ipsum: Eq, + Lorem: Eq, +{ + // body +} + +fn lorem_multi_line( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T +where + Ipsum: Eq, +{ + // body +} + +fn lorem() -> T +where Ipsum: Eq { + // body +} -- cgit 1.4.1-3-g733a5 From 314c97387d3e46dce1a939d16788b917dd4420e8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:53:30 +0900 Subject: Squash redundant match arms --- src/imports.rs | 11 +++++------ src/visitor.rs | 12 +----------- 2 files changed, 6 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 68c3ec32897..699029e7151 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -94,15 +94,14 @@ fn compare_path_list_item_lists( fn compare_view_path_types(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering { use syntax::ast::ViewPath_::*; match (a, b) { - (&ViewPathSimple(..), &ViewPathSimple(..)) => Ordering::Equal, - (&ViewPathSimple(..), _) => Ordering::Less, - (&ViewPathGlob(_), &ViewPathSimple(..)) => Ordering::Greater, - (&ViewPathGlob(_), &ViewPathGlob(_)) => Ordering::Equal, - (&ViewPathGlob(_), &ViewPathList(..)) => Ordering::Less, + (&ViewPathSimple(..), &ViewPathSimple(..)) | (&ViewPathGlob(_), &ViewPathGlob(_)) => { + Ordering::Equal + } + (&ViewPathSimple(..), _) | (&ViewPathGlob(_), &ViewPathList(..)) => Ordering::Less, (&ViewPathList(_, ref a_items), &ViewPathList(_, ref b_items)) => { compare_path_list_item_lists(a_items, b_items) } - (&ViewPathList(..), _) => Ordering::Greater, + (&ViewPathGlob(_), &ViewPathSimple(..)) | (&ViewPathList(..), _) => Ordering::Greater, } } diff --git a/src/visitor.rs b/src/visitor.rs index 642f75e58ab..ee6e6be63f4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -250,17 +250,7 @@ impl<'a> FmtVisitor<'a> { let indent = self.block_indent; let block; let rewrite = match fk { - visit::FnKind::ItemFn(ident, _, _, _, _, b) => { - block = b; - self.rewrite_fn( - indent, - ident, - &FnSig::from_fn_kind(&fk, generics, fd, defaultness), - mk_sp(s.lo(), b.span.lo()), - b, - ) - } - visit::FnKind::Method(ident, _, _, b) => { + visit::FnKind::ItemFn(ident, _, _, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { block = b; self.rewrite_fn( indent, -- cgit 1.4.1-3-g733a5 From 6c5ac5a9b34b9169209e8ed2db852d965bdef8c8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:54:41 +0900 Subject: Remove needless borrows --- src/expr.rs | 8 ++++---- src/imports.rs | 2 +- src/items.rs | 10 +++++----- src/macros.rs | 8 ++++---- src/types.rs | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a297b00a5f2..6a6e982912a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -75,7 +75,7 @@ pub fn format_expr( ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); let callee_str = callee.rewrite(context, shape)?; - rewrite_call(context, &callee_str, &args, inner_span, shape) + rewrite_call(context, &callee_str, args, inner_span, shape) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { @@ -101,7 +101,7 @@ pub fn format_expr( shape, ), ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, &ptr_vec_to_ref_vec(&items), expr.span, shape) + rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | @@ -355,7 +355,7 @@ where .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { let one_line_width = last_line_width(&lhs_result) + infix.len() - + first_line_width(&rhs_result) + suffix.len(); + + first_line_width(rhs_result) + suffix.len(); if one_line_width <= shape.width { return Some(format!("{}{}{}{}", lhs_result, infix, rhs_result, suffix)); } @@ -2004,7 +2004,7 @@ pub fn rewrite_call( rewrite_call_inner( context, callee, - &ptr_vec_to_ref_vec(&args), + &ptr_vec_to_ref_vec(args), span, shape, context.config.fn_call_width(), diff --git a/src/imports.rs b/src/imports.rs index 699029e7151..a44206df049 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -292,7 +292,7 @@ impl<'a> FmtVisitor<'a> { } Some(ref s) => { self.format_missing_with_indent(source!(self, span).lo()); - self.buffer.push_str(&s); + self.buffer.push_str(s); self.last_pos = source!(self, span).hi(); } None => { diff --git a/src/items.rs b/src/items.rs index 989793cb6ba..c85f2fd5e62 100644 --- a/src/items.rs +++ b/src/items.rs @@ -215,7 +215,7 @@ impl<'a> FnSig<'a> { unsafety: unsafety, visibility: visibility.clone(), }, - visit::FnKind::Method(_, ref method_sig, vis, _) => { + visit::FnKind::Method(_, method_sig, vis, _) => { let mut fn_sig = FnSig::from_method_sig(method_sig, generics); fn_sig.defaultness = defualtness; if let Some(vis) = vis { @@ -2318,16 +2318,16 @@ fn rewrite_generics_inner( impl<'a> Rewrite for GenericsArg<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { - GenericsArg::Lifetime(ref lifetime) => lifetime.rewrite(context, shape), - GenericsArg::TyParam(ref ty) => ty.rewrite(context, shape), + GenericsArg::Lifetime(lifetime) => lifetime.rewrite(context, shape), + GenericsArg::TyParam(ty) => ty.rewrite(context, shape), } } } impl<'a> Spanned for GenericsArg<'a> { fn span(&self) -> Span { match *self { - GenericsArg::Lifetime(ref lifetime) => lifetime.span(), - GenericsArg::TyParam(ref ty) => ty.span(), + GenericsArg::Lifetime(lifetime) => lifetime.span(), + GenericsArg::TyParam(ty) => ty.span(), } } } diff --git a/src/macros.rs b/src/macros.rs index 9d665c4a0b2..42c31da3503 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -70,10 +70,10 @@ pub enum MacroArg { impl Rewrite for MacroArg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self { - &MacroArg::Expr(ref expr) => expr.rewrite(context, shape), - &MacroArg::Ty(ref ty) => ty.rewrite(context, shape), - &MacroArg::Pat(ref pat) => pat.rewrite(context, shape), + match *self { + MacroArg::Expr(ref expr) => expr.rewrite(context, shape), + MacroArg::Ty(ref ty) => ty.rewrite(context, shape), + MacroArg::Pat(ref pat) => pat.rewrite(context, shape), } } } diff --git a/src/types.rs b/src/types.rs index fd41fedabb6..a0b3a7c196a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -695,7 +695,7 @@ impl Rewrite for ast::Ty { } ast::TyKind::Tup(ref items) => rewrite_tuple( context, - &::utils::ptr_vec_to_ref_vec(&items), + &::utils::ptr_vec_to_ref_vec(items), self.span, shape, ), -- cgit 1.4.1-3-g733a5 From c7a788084b561547096f0265c982b1d2fb269474 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:55:36 +0900 Subject: Simplify let-if pattern --- src/visitor.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index ee6e6be63f4..7a7d46f8aea 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -197,12 +197,11 @@ impl<'a> FmtVisitor<'a> { } } - let mut unindent_comment = self.is_if_else_block && !b.stmts.is_empty(); - if unindent_comment { + let unindent_comment = (self.is_if_else_block && !b.stmts.is_empty()) && { let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); - unindent_comment = snippet.contains("//") || snippet.contains("/*"); - } + snippet.contains("//") || snippet.contains("/*") + }; // FIXME: we should compress any newlines here to just one if unindent_comment { self.block_indent = self.block_indent.block_unindent(self.config); -- cgit 1.4.1-3-g733a5 From f2eebb0e623b8c2de9efd1a7fbcd7cf8f9e1518a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:55:48 +0900 Subject: Prefer unreachable! to panic! --- src/modules.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 8e728f98cd1..3d4de51deb6 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -76,6 +76,6 @@ fn module_file( match parser::Parser::default_submod_path(id, dir_path, codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => path, - Err(_) => panic!("Couldn't find module {}", id), + Err(_) => unreachable!("Couldn't find module {}", id), } } -- cgit 1.4.1-3-g733a5 From 1a9d00bbef3b933f6b9cee52015e4ba3b26a9e70 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:56:39 +0900 Subject: Prefer ends_with() to chars().last().unwrap() --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c85f2fd5e62..042aa81f3ce 100644 --- a/src/items.rs +++ b/src/items.rs @@ -670,7 +670,7 @@ pub fn format_impl( result.push_str(&outer_indent_str); } - if result.chars().last().unwrap() == '{' { + if result.ends_with('{') { result.push_str(&sep); } result.push('}'); -- cgit 1.4.1-3-g733a5 From d66161c6a3cbc1d3d2c34d63df8c7b4d4a71a211 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:57:11 +0900 Subject: Prefer &[T] to &Vec --- src/imports.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index a44206df049..faf0638f7d1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -75,11 +75,11 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde } fn compare_path_list_item_lists( - a_items: &Vec, - b_items: &Vec, + a_items: &[ast::PathListItem], + b_items: &[ast::PathListItem], ) -> Ordering { - let mut a = a_items.clone(); - let mut b = b_items.clone(); + let mut a = a_items.to_owned(); + let mut b = b_items.to_owned(); a.sort_by(|a, b| compare_path_list_items(a, b)); b.sort_by(|a, b| compare_path_list_items(a, b)); for comparison_pair in a.iter().zip(b.iter()) { -- cgit 1.4.1-3-g733a5 From 39ca7db7c8bbc5b73ae5d51aa5146003f400876e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 26 Oct 2017 16:57:45 +0900 Subject: Remove unnecessary String::from() --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 042aa81f3ce..13450ea0f45 100644 --- a/src/items.rs +++ b/src/items.rs @@ -546,7 +546,7 @@ impl<'a> FmtVisitor<'a> { // 1 = ',' rewrite_assign_rhs(&context, lhs, expr, shape.sub_width(1)?)? } else { - String::from(field.node.name.to_string()) + field.node.name.to_string() }, }; -- cgit 1.4.1-3-g733a5 From 79c6f632efc4d259a976f4896875e3964ed56d19 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:00:24 +0900 Subject: Remove an unnecessary lifetime --- src/bin/cargo-fmt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 53e697d76ac..f760f41a0f5 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -259,10 +259,10 @@ fn extract_target_from_package(package: &Value) -> Option> { Some(targets) } -fn filter_packages_with_hitlist<'a>( +fn filter_packages_with_hitlist( packages: Vec, - workspace_hitlist: &'a WorkspaceHitlist, -) -> Result, &'a String> { + workspace_hitlist: &WorkspaceHitlist, +) -> Result, &String> { let some_hitlist: Option> = workspace_hitlist.get_some().map(HashSet::from_iter); if some_hitlist.is_none() { -- cgit 1.4.1-3-g733a5 From fc4a51a24200376f461f643eb9da7378eed075b5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:00:53 +0900 Subject: Prefer println!() to println!("") --- src/bin/cargo-fmt.rs | 2 +- src/config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index f760f41a0f5..f195efb376d 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -387,7 +387,7 @@ fn format_files( for f in files { print!(" {}", f.display()); } - println!(""); + println!(); } let mut command = Command::new("rustfmt") .stdout(stdout) diff --git a/src/config.rs b/src/config.rs index 28839031836..9e7dc9fb1e1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -478,7 +478,7 @@ macro_rules! create_config { $( println!("{}{}", space_str, $dstring); )+ - println!(""); + println!(); )+ } } -- cgit 1.4.1-3-g733a5 From b023cc831ce3f79efdda89a6b825967993b40069 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:02:46 +0900 Subject: Remove static lifetime --- src/bin/rustfmt-format-diff.rs | 2 +- src/config.rs | 2 +- src/macros.rs | 2 +- src/utils.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt-format-diff.rs b/src/bin/rustfmt-format-diff.rs index 5bd0e5d18cc..0df8d37807b 100644 --- a/src/bin/rustfmt-format-diff.rs +++ b/src/bin/rustfmt-format-diff.rs @@ -33,7 +33,7 @@ use regex::Regex; /// The default pattern of files to format. /// /// We only want to format rust files by default. -const DEFAULT_PATTERN: &'static str = r".*\.rs"; +const DEFAULT_PATTERN: &str = r".*\.rs"; #[derive(Debug)] enum FormatDiffError { diff --git a/src/config.rs b/src/config.rs index 9e7dc9fb1e1..450e016bc5a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -500,7 +500,7 @@ macro_rules! create_config { /// /// Return the path if a config file exists, empty if no file exists, and Error for IO errors pub fn get_toml_path(dir: &Path) -> Result, Error> { - const CONFIG_FILE_NAMES: [&'static str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; for config_file_name in &CONFIG_FILE_NAMES { let config_file = dir.join(config_file_name); match fs::metadata(&config_file) { diff --git a/src/macros.rs b/src/macros.rs index 42c31da3503..8f5feac474c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -35,7 +35,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use utils::mk_sp; -const FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"]; +const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; // FIXME: use the enum from libsyntax? #[derive(Clone, Copy, PartialEq, Eq)] diff --git a/src/utils.rs b/src/utils.rs index 3bdadf460e2..b8fb83fefe5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -19,7 +19,7 @@ use rewrite::RewriteContext; use shape::Shape; // When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &'static str = "rustfmt_skip"; +const SKIP_ANNOTATION: &str = "rustfmt_skip"; // Computes the length of a string's last line, minus offset. pub fn extra_offset(text: &str, shape: Shape) -> usize { -- cgit 1.4.1-3-g733a5 From 4e1a75a429f0d50e4587ad6325cca3ceb769cac2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:03:30 +0900 Subject: Collapse if-else --- src/comment.rs | 8 +++----- src/items.rs | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 713ef4922d9..6d5f48fbb26 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -327,12 +327,10 @@ fn rewrite_comment_inner( if line.is_empty() { continue; } + } else if is_prev_line_multi_line && !line.is_empty() { + result.push(' ') } else { - if is_prev_line_multi_line && !line.is_empty() { - result.push(' ') - } else { - result.push_str(&comment_line_separator); - } + result.push_str(&comment_line_separator); } if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { diff --git a/src/items.rs b/src/items.rs index 13450ea0f45..37a1b1ca40b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -313,10 +313,10 @@ impl<'a> FmtVisitor<'a> { let (mut result, force_newline_brace) = rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; - if self.config.fn_brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace { - newline_brace = true; - } else if last_line_width(&result) + 2 > self.shape().width { - // 2 = ` {` + // 2 = ` {` + if self.config.fn_brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace + || last_line_width(&result) + 2 > self.shape().width + { newline_brace = true; } else if !result.contains('\n') { newline_brace = false; -- cgit 1.4.1-3-g733a5 From feeca8a724f59aa2ce343104bb7133defa7c1bc7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:03:43 +0900 Subject: Remove unnecessary format!() call --- src/bin/rustfmt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index c886fc7aae6..f0e4f0a7897 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -73,9 +73,9 @@ impl CliOptions { .map(|c| c == "nightly") .unwrap_or(false); if unstable_features && !rust_nightly { - return Err(FmtError::from(format!( - "Unstable features are only available on Nightly channel" - ))); + return Err(FmtError::from( + "Unstable features are only available on Nightly channel", + )); } else { options.unstable_features = unstable_features; } -- cgit 1.4.1-3-g733a5 From 10cb568c18a4efb5655a0eaa3bd7bd11c441aa6c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:03:55 +0900 Subject: Remove redundant references --- src/bin/cargo-fmt.rs | 2 +- src/expr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index f195efb376d..60cc59bc1a0 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -254,7 +254,7 @@ fn extract_target_from_package(package: &Value) -> Option> { let jtargets = get_json_array_with(package, "targets")?; let mut targets: Vec = vec![]; for jtarget in jtargets { - targets.push(Target::from_json(&jtarget)?); + targets.push(Target::from_json(jtarget)?); } Some(targets) } diff --git a/src/expr.rs b/src/expr.rs index 6a6e982912a..d815bbe8dd7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -641,7 +641,7 @@ fn rewrite_closure( }; if no_return_type && !needs_block { // block.stmts.len() == 1 - if let Some(ref expr) = stmt_expr(&block.stmts[0]) { + if let Some(expr) = stmt_expr(&block.stmts[0]) { if let Some(rw) = if is_block_closure_forced(expr) { rewrite_closure_with_block(context, shape, &prefix, expr) } else { -- cgit 1.4.1-3-g733a5 From c73871c516f659262bb70a38b50e949f8ca39023 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:17:46 +0900 Subject: Introduce PairParts to reduce the number of args of rewrite_pair() --- src/expr.rs | 27 +++++++++------------------ src/patterns.rs | 6 ++---- src/types.rs | 6 ++---- 3 files changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d815bbe8dd7..0fc2743e57e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -83,9 +83,7 @@ pub fn format_expr( rewrite_pair( &**lhs, &**rhs, - "", - &format!(" {} ", context.snippet(op.span)), - "", + &PairParts("", &format!(" {} ", context.snippet(op.span)), ""), context, shape, context.config.binop_separator(), @@ -186,9 +184,7 @@ pub fn format_expr( ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - "", - " as ", - "", + &PairParts("", " as ", ""), context, shape, SeparatorPlace::Front, @@ -196,9 +192,7 @@ pub fn format_expr( ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - "", - ": ", - "", + &PairParts("", ": ", ""), context, shape, SeparatorPlace::Back, @@ -215,9 +209,7 @@ pub fn format_expr( rewrite_pair( &**expr, &**repeats, - lbr, - "; ", - rbr, + &PairParts(lbr, "; ", rbr), context, shape, SeparatorPlace::Back, @@ -253,9 +245,7 @@ pub fn format_expr( rewrite_pair( &*lhs, &*rhs, - "", - &sp_delim, - "", + &PairParts("", &sp_delim, ""), context, shape, SeparatorPlace::Front, @@ -315,12 +305,12 @@ pub fn format_expr( }) } +pub struct PairParts<'a>(pub &'a str, pub &'a str, pub &'a str); + pub fn rewrite_pair( lhs: &LHS, rhs: &RHS, - prefix: &str, - infix: &str, - suffix: &str, + pp: &PairParts, context: &RewriteContext, shape: Shape, separator_place: SeparatorPlace, @@ -329,6 +319,7 @@ where LHS: Rewrite, RHS: Rewrite, { + let &PairParts(prefix, infix, suffix) = pp; let lhs_overhead = match separator_place { SeparatorPlace::Back => shape.used_width() + prefix.len() + infix.trim_right().len(), SeparatorPlace::Front => shape.used_width(), diff --git a/src/patterns.rs b/src/patterns.rs index 92e385543b7..38d850962bb 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -16,7 +16,7 @@ use spanned::Spanned; use codemap::SpanUtils; use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, - wrap_struct_field}; + wrap_struct_field, PairParts}; use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; @@ -65,9 +65,7 @@ impl Rewrite for Pat { rewrite_pair( &**lhs, &**rhs, - "", - infix, - "", + &PairParts("", infix, ""), context, shape, SeparatorPlace::Front, diff --git a/src/types.rs b/src/types.rs index a0b3a7c196a..26b5f702a70 100644 --- a/src/types.rs +++ b/src/types.rs @@ -19,7 +19,7 @@ use syntax::symbol::keywords; use spanned::Spanned; use codemap::SpanUtils; use config::{IndentStyle, Style, TypeDensity}; -use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens}; +use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; use items::{format_generics_item_list, generics_shape_from_config}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -709,9 +709,7 @@ impl Rewrite for ast::Ty { rewrite_pair( &**ty, &**repeats, - lbr, - "; ", - rbr, + &PairParts(lbr, "; ", rbr), context, shape, SeparatorPlace::Back, -- cgit 1.4.1-3-g733a5 From a3f286a0dc68be3cd1775f50d9240001a3869e7c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:24:00 +0900 Subject: Remove an unused arg from visit_fn() --- src/visitor.rs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 7a7d46f8aea..fc66a99083e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -242,7 +242,6 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, fd: &ast::FnDecl, s: Span, - _: ast::NodeId, defaultness: ast::Defaultness, inner_attrs: Option<&[ast::Attribute]>, ) { @@ -416,7 +415,6 @@ impl<'a> FmtVisitor<'a> { generics, decl, item.span, - item.id, ast::Defaultness::Final, Some(&item.attrs), ) @@ -494,7 +492,6 @@ impl<'a> FmtVisitor<'a> { &ti.generics, &sig.decl, ti.span, - ti.id, ast::Defaultness::Final, Some(&ti.attrs), ); @@ -530,7 +527,6 @@ impl<'a> FmtVisitor<'a> { &ii.generics, &sig.decl, ii.span, - ii.id, ii.defaultness, Some(&ii.attrs), ); -- cgit 1.4.1-3-g733a5 From 8c6c15a0965e01807a3d7915487c6915c9048edc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:29:40 +0900 Subject: Remove unused args from format_generics() --- src/items.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 37a1b1ca40b..3314154e4a4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -428,8 +428,6 @@ impl<'a> FmtVisitor<'a> { let generics_str = format_generics( &self.get_context(), generics, - "{", - "{", self.config.item_brace_style(), enum_def.variants.is_empty(), self.block_indent, @@ -1079,8 +1077,6 @@ pub fn format_struct_struct( Some(g) => format_generics( context, g, - "{", - "{", context.config.item_brace_style(), fields.is_empty(), offset, @@ -2693,8 +2689,6 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S fn format_generics( context: &RewriteContext, generics: &ast::Generics, - opener: &str, - terminator: &str, brace_style: BraceStyle, force_same_line_brace: bool, offset: Indent, @@ -2720,7 +2714,7 @@ fn format_generics( brace_style, Shape::legacy(budget, offset.block_only()), Density::Tall, - terminator, + "{", Some(span.hi()), span_end_before_where, option, @@ -2740,9 +2734,11 @@ fn format_generics( // and hence we take the closer into account as well for one line budget. // We assume that the closer has the same length as the opener. let overhead = if force_same_line_brace { - 1 + opener.len() + opener.len() + // 3 = ` {}` + 3 } else { - 1 + opener.len() + // 2 = ` {` + 2 }; let forbid_same_line_brace = overhead > remaining_budget; if !forbid_same_line_brace && same_line_brace { @@ -2751,7 +2747,7 @@ fn format_generics( result.push('\n'); result.push_str(&offset.block_only().to_string(context.config)); } - result.push_str(opener); + result.push('{'); Some(result) } -- cgit 1.4.1-3-g733a5 From 318f9c89e0eb9fbc2bfbcdb372e7853716783e83 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 14:44:52 +0900 Subject: Add StaticParts to reduce the number of args in rewrite_static() --- src/items.rs | 39 ++++++++++++++++++++++++++++++++++----- src/visitor.rs | 44 +++++++++++++++++++++++--------------------- 2 files changed, 57 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3314154e4a4..c9baa3a0616 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1461,17 +1461,46 @@ pub fn rewrite_struct_field( ) } -pub fn rewrite_static( - prefix: &str, - vis: &ast::Visibility, +pub struct StaticParts<'a> { + vis: &'a ast::Visibility, ident: ast::Ident, - ty: &ast::Ty, + ty: &'a ast::Ty, mutability: ast::Mutability, - expr_opt: Option<&ptr::P>, + expr_opt: Option<&'a ptr::P>, +} + +impl<'a> StaticParts<'a> { + pub fn new( + vis: &'a ast::Visibility, + ident: ast::Ident, + ty: &'a ast::Ty, + mutability: ast::Mutability, + expr_opt: Option<&'a ptr::P>, + ) -> StaticParts<'a> { + StaticParts { + vis, + ident, + ty, + mutability, + expr_opt, + } + } +} + +pub fn rewrite_static( + prefix: &str, + static_parts: &StaticParts, offset: Indent, span: Span, context: &RewriteContext, ) -> Option { + let StaticParts { + vis, + ident, + ty, + mutability, + expr_opt, + } = *static_parts; let colon = colon_spaces( context.config.space_before_type_annotation(), context.config.space_after_type_annotation_colon(), diff --git a/src/visitor.rs b/src/visitor.rs index fc66a99083e..5b654b07336 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -25,7 +25,7 @@ use comment::rewrite_comment; use config::{BraceStyle, Config}; use items::{format_impl, format_struct, format_struct_struct, format_trait, rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, - rewrite_type_alias, FnSig}; + rewrite_type_alias, FnSig, StaticParts}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; @@ -381,11 +381,7 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::Static(ref ty, mutability, ref expr) => { let rewrite = rewrite_static( "static", - &item.vis, - item.ident, - ty, - mutability, - Some(expr), + &StaticParts::new(&item.vis, item.ident, ty, mutability, Some(expr)), self.block_indent, item.span, &self.get_context(), @@ -395,11 +391,13 @@ impl<'a> FmtVisitor<'a> { ast::ItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static( "const", - &item.vis, - item.ident, - ty, - ast::Mutability::Immutable, - Some(expr), + &StaticParts::new( + &item.vis, + item.ident, + ty, + ast::Mutability::Immutable, + Some(expr), + ), self.block_indent, item.span, &self.get_context(), @@ -469,11 +467,13 @@ impl<'a> FmtVisitor<'a> { ast::TraitItemKind::Const(ref ty, ref expr_opt) => { let rewrite = rewrite_static( "const", - &ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr_opt.as_ref(), + &StaticParts::new( + &ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr_opt.as_ref(), + ), self.block_indent, ti.span, &self.get_context(), @@ -534,11 +534,13 @@ impl<'a> FmtVisitor<'a> { ast::ImplItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_static( "const", - &ii.vis, - ii.ident, - ty, - ast::Mutability::Immutable, - Some(expr), + &StaticParts::new( + &ii.vis, + ii.ident, + ty, + ast::Mutability::Immutable, + Some(expr), + ), self.block_indent, ii.span, &self.get_context(), -- cgit 1.4.1-3-g733a5 From 3b2b7f67ee3b504d267a9791ea76c1230fdbc666 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 20:30:28 +0900 Subject: Add StructParts to reduce the number of args --- src/items.rs | 120 +++++++++++++++++++++++++++++++++------------------------ src/visitor.rs | 37 ++---------------- 2 files changed, 73 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c9baa3a0616..3e79cf3c1ce 100644 --- a/src/items.rs +++ b/src/items.rs @@ -411,6 +411,13 @@ impl<'a> FmtVisitor<'a> { None } + pub fn visit_struct(&mut self, struct_parts: &StructParts) { + let is_tuple = struct_parts.def.is_tuple(); + let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) + .map(|s| if is_tuple { s + ";" } else { s }); + self.push_rewrite(struct_parts.span, rewrite); + } + pub fn visit_enum( &mut self, ident: ast::Ident, @@ -529,12 +536,7 @@ impl<'a> FmtVisitor<'a> { // FIXME: Should limit the width, as we have a trailing comma format_struct( &context, - "", - field.node.name, - &ast::Visibility::Inherited, - &field.node.data, - None, - field.span, + &StructParts::from_variant(field), indent, Some(self.config.struct_variant_width()), )? @@ -855,40 +857,62 @@ fn rewrite_trait_ref( } } -pub fn format_struct( - context: &RewriteContext, - item_name: &str, +pub struct StructParts<'a> { + prefix: &'a str, ident: ast::Ident, - vis: &ast::Visibility, - struct_def: &ast::VariantData, - generics: Option<&ast::Generics>, + vis: &'a ast::Visibility, + def: &'a ast::VariantData, + generics: Option<&'a ast::Generics>, span: Span, +} + +impl<'a> StructParts<'a> { + fn format_header(&self) -> String { + format_header(self.prefix, self.ident, self.vis) + } + + fn from_variant(variant: &'a ast::Variant) -> Self { + StructParts { + prefix: "", + ident: variant.node.name, + vis: &ast::Visibility::Inherited, + def: &variant.node.data, + generics: None, + span: variant.span, + } + } + + pub fn from_item(item: &'a ast::Item) -> Self { + let (prefix, def, generics) = match item.node { + ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), + ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), + _ => unreachable!(), + }; + StructParts { + prefix: prefix, + ident: item.ident, + vis: &item.vis, + def: def, + generics: Some(generics), + span: item.span, + } + } +} + +fn format_struct( + context: &RewriteContext, + struct_parts: &StructParts, offset: Indent, one_line_width: Option, ) -> Option { - match *struct_def { - ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)), - ast::VariantData::Tuple(ref fields, _) => format_tuple_struct( - context, - item_name, - ident, - vis, - fields, - generics, - span, - offset, - ), - ast::VariantData::Struct(ref fields, _) => format_struct_struct( - context, - item_name, - ident, - vis, - fields, - generics, - span, - offset, - one_line_width, - ), + match *struct_parts.def { + ast::VariantData::Unit(..) => Some(format_unit_struct(struct_parts)), + ast::VariantData::Tuple(ref fields, _) => { + format_tuple_struct(context, struct_parts, fields, offset) + } + ast::VariantData::Struct(ref fields, _) => { + format_struct_struct(context, struct_parts, fields, offset, one_line_width) + } } } @@ -1050,30 +1074,27 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } -fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { - format!("{};", format_header(item_name, ident, vis)) +fn format_unit_struct(p: &StructParts) -> String { + format!("{};", format_header(p.prefix, p.ident, p.vis)) } pub fn format_struct_struct( context: &RewriteContext, - item_name: &str, - ident: ast::Ident, - vis: &ast::Visibility, + struct_parts: &StructParts, fields: &[ast::StructField], - generics: Option<&ast::Generics>, - span: Span, offset: Indent, one_line_width: Option, ) -> Option { let mut result = String::with_capacity(1024); + let span = struct_parts.span; - let header_str = format_header(item_name, ident, vis); + let header_str = struct_parts.format_header(); result.push_str(&header_str); let header_hi = span.lo() + BytePos(header_str.len() as u32); let body_lo = context.codemap.span_after(span, "{"); - let generics_str = match generics { + let generics_str = match struct_parts.generics { Some(g) => format_generics( context, g, @@ -1174,17 +1195,14 @@ fn get_bytepos_after_visibility( fn format_tuple_struct( context: &RewriteContext, - item_name: &str, - ident: ast::Ident, - vis: &ast::Visibility, + struct_parts: &StructParts, fields: &[ast::StructField], - generics: Option<&ast::Generics>, - span: Span, offset: Indent, ) -> Option { let mut result = String::with_capacity(1024); + let span = struct_parts.span; - let header_str = format_header(item_name, ident, vis); + let header_str = struct_parts.format_header(); result.push_str(&header_str); let body_lo = if fields.is_empty() { @@ -1207,7 +1225,7 @@ fn format_tuple_struct( } }; - let where_clause_str = match generics { + let where_clause_str = match struct_parts.generics { Some(generics) => { let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); diff --git a/src/visitor.rs b/src/visitor.rs index 5b654b07336..adcdb120ee3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -23,9 +23,8 @@ use comment::{contains_comment, recover_missing_comment_in_span, remove_trailing CodeCharKind, CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; -use items::{format_impl, format_struct, format_struct_struct, format_trait, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_static, - rewrite_type_alias, FnSig, StaticParts}; +use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, + rewrite_static, rewrite_type_alias, FnSig, StaticParts, StructParts}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; @@ -345,22 +344,8 @@ impl<'a> FmtVisitor<'a> { let rw = rewrite_extern_crate(&self.get_context(), item); self.push_rewrite(item.span, rw); } - ast::ItemKind::Struct(ref def, ref generics) => { - let rewrite = format_struct( - &self.get_context(), - "struct ", - item.ident, - &item.vis, - def, - Some(generics), - item.span, - self.block_indent, - None, - ).map(|s| match *def { - ast::VariantData::Tuple(..) => s + ";", - _ => s, - }); - self.push_rewrite(item.span, rewrite); + ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { + self.visit_struct(&StructParts::from_item(item)); } ast::ItemKind::Enum(ref def, ref generics) => { self.format_missing_with_indent(source!(self, item.span).lo()); @@ -429,20 +414,6 @@ impl<'a> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } - ast::ItemKind::Union(ref def, ref generics) => { - let rewrite = format_struct_struct( - &self.get_context(), - "union ", - item.ident, - &item.vis, - def.fields(), - Some(generics), - item.span, - self.block_indent, - None, - ); - self.push_rewrite(item.span, rewrite); - } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span)); self.push_rewrite(item.span, snippet); -- cgit 1.4.1-3-g733a5 From 082c001843ccf7eb4e20ce8c2f739c1b9eef02d4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 5 Nov 2017 21:59:33 +0900 Subject: Add visit_static() --- src/items.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++------------- src/visitor.rs | 63 ++++--------------------------------------------- 2 files changed, 63 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3e79cf3c1ce..829d9a1e2d7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -411,6 +411,11 @@ impl<'a> FmtVisitor<'a> { None } + pub fn visit_static(&mut self, static_parts: &StaticParts) { + let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); + self.push_rewrite(static_parts.span, rewrite); + } + pub fn visit_struct(&mut self, struct_parts: &StructParts) { let is_tuple = struct_parts.def.is_tuple(); let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) @@ -1480,44 +1485,81 @@ pub fn rewrite_struct_field( } pub struct StaticParts<'a> { + prefix: &'a str, vis: &'a ast::Visibility, ident: ast::Ident, ty: &'a ast::Ty, mutability: ast::Mutability, expr_opt: Option<&'a ptr::P>, + span: Span, } impl<'a> StaticParts<'a> { - pub fn new( - vis: &'a ast::Visibility, - ident: ast::Ident, - ty: &'a ast::Ty, - mutability: ast::Mutability, - expr_opt: Option<&'a ptr::P>, - ) -> StaticParts<'a> { + pub fn from_item(item: &'a ast::Item) -> Self { + let (prefix, ty, mutability, expr) = match item.node { + ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), + ast::ItemKind::Const(ref ty, ref expr) => { + ("const", ty, ast::Mutability::Immutable, expr) + } + _ => unreachable!(), + }; StaticParts { - vis, - ident, - ty, - mutability, - expr_opt, + prefix: prefix, + vis: &item.vis, + ident: item.ident, + ty: ty, + mutability: mutability, + expr_opt: Some(expr), + span: item.span, + } + } + + pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self { + let (ty, expr_opt) = match ti.node { + ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), + _ => unreachable!(), + }; + StaticParts { + prefix: "const", + vis: &ast::Visibility::Inherited, + ident: ti.ident, + ty: ty, + mutability: ast::Mutability::Immutable, + expr_opt: expr_opt.as_ref(), + span: ti.span, + } + } + + pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self { + let (ty, expr) = match ii.node { + ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), + _ => unreachable!(), + }; + StaticParts { + prefix: "const", + vis: &ii.vis, + ident: ii.ident, + ty: ty, + mutability: ast::Mutability::Immutable, + expr_opt: Some(expr), + span: ii.span, } } } -pub fn rewrite_static( - prefix: &str, +fn rewrite_static( + context: &RewriteContext, static_parts: &StaticParts, offset: Indent, - span: Span, - context: &RewriteContext, ) -> Option { let StaticParts { + prefix, vis, ident, ty, mutability, expr_opt, + span, } = *static_parts; let colon = colon_spaces( context.config.space_before_type_annotation(), diff --git a/src/visitor.rs b/src/visitor.rs index adcdb120ee3..417b12b2d53 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -24,7 +24,7 @@ use comment::{contains_comment, recover_missing_comment_in_span, remove_trailing use comment::rewrite_comment; use config::{BraceStyle, Config}; use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, - rewrite_static, rewrite_type_alias, FnSig, StaticParts, StructParts}; + rewrite_type_alias, FnSig, StaticParts, StructParts}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; @@ -363,31 +363,8 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(source!(self, item.span).lo()); self.format_foreign_mod(foreign_mod, item.span); } - ast::ItemKind::Static(ref ty, mutability, ref expr) => { - let rewrite = rewrite_static( - "static", - &StaticParts::new(&item.vis, item.ident, ty, mutability, Some(expr)), - self.block_indent, - item.span, - &self.get_context(), - ); - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_static( - "const", - &StaticParts::new( - &item.vis, - item.ident, - ty, - ast::Mutability::Immutable, - Some(expr), - ), - self.block_indent, - item.span, - &self.get_context(), - ); - self.push_rewrite(item.span, rewrite); + ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { + self.visit_static(&StaticParts::from_item(item)); } ast::ItemKind::AutoImpl(..) => { // FIXME(#78): format impl definitions. @@ -435,22 +412,7 @@ impl<'a> FmtVisitor<'a> { } match ti.node { - ast::TraitItemKind::Const(ref ty, ref expr_opt) => { - let rewrite = rewrite_static( - "const", - &StaticParts::new( - &ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr_opt.as_ref(), - ), - self.block_indent, - ti.span, - &self.get_context(), - ); - self.push_rewrite(ti.span, rewrite); - } + ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), ast::TraitItemKind::Method(ref sig, None) => { let indent = self.block_indent; let rewrite = @@ -502,22 +464,7 @@ impl<'a> FmtVisitor<'a> { Some(&ii.attrs), ); } - ast::ImplItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_static( - "const", - &StaticParts::new( - &ii.vis, - ii.ident, - ty, - ast::Mutability::Immutable, - Some(expr), - ), - self.block_indent, - ii.span, - &self.get_context(), - ); - self.push_rewrite(ii.span, rewrite); - } + ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), ast::ImplItemKind::Type(ref ty) => { let rewrite = rewrite_associated_impl_type( ii.ident, -- cgit 1.4.1-3-g733a5 From 3e8f4b79072c6d6ba4769f240e0b481d1615d37b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 6 Nov 2017 21:44:59 +0900 Subject: Fix PairParts related issues --- src/expr.rs | 78 ++++++++++++++++++++++++++++++--------------------------- src/lib.rs | 2 ++ src/patterns.rs | 2 +- src/types.rs | 2 +- 4 files changed, 45 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0fc2743e57e..d8f42944ad0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -83,7 +83,7 @@ pub fn format_expr( rewrite_pair( &**lhs, &**rhs, - &PairParts("", &format!(" {} ", context.snippet(op.span)), ""), + PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), context, shape, context.config.binop_separator(), @@ -184,7 +184,7 @@ pub fn format_expr( ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - &PairParts("", " as ", ""), + PairParts::new("", " as ", ""), context, shape, SeparatorPlace::Front, @@ -192,7 +192,7 @@ pub fn format_expr( ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - &PairParts("", ": ", ""), + PairParts::new("", ": ", ""), context, shape, SeparatorPlace::Back, @@ -209,7 +209,7 @@ pub fn format_expr( rewrite_pair( &**expr, &**repeats, - &PairParts(lbr, "; ", rbr), + PairParts::new(lbr, "; ", rbr), context, shape, SeparatorPlace::Back, @@ -245,7 +245,7 @@ pub fn format_expr( rewrite_pair( &*lhs, &*rhs, - &PairParts("", &sp_delim, ""), + PairParts::new("", &sp_delim, ""), context, shape, SeparatorPlace::Front, @@ -305,12 +305,17 @@ pub fn format_expr( }) } -pub struct PairParts<'a>(pub &'a str, pub &'a str, pub &'a str); +#[derive(new)] +pub struct PairParts<'a> { + prefix: &'a str, + infix: &'a str, + suffix: &'a str, +} pub fn rewrite_pair( lhs: &LHS, rhs: &RHS, - pp: &PairParts, + pp: PairParts, context: &RewriteContext, shape: Shape, separator_place: SeparatorPlace, @@ -319,9 +324,8 @@ where LHS: Rewrite, RHS: Rewrite, { - let &PairParts(prefix, infix, suffix) = pp; let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + prefix.len() + infix.trim_right().len(), + SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), SeparatorPlace::Front => shape.used_width(), }; let lhs_shape = Shape { @@ -329,12 +333,12 @@ where ..shape }; let lhs_result = lhs.rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", prefix, lhs_str))?; + .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; // Try to the both lhs and rhs on the same line. let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + infix.len()) - .and_then(|s| s.sub_width(suffix.len())) + .offset_left(last_line_width(&lhs_result) + pp.infix.len()) + .and_then(|s| s.sub_width(pp.suffix.len())) .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); if let Some(ref rhs_result) = rhs_orig_result { // If the rhs looks like block expression, we allow it to stay on the same line @@ -345,10 +349,16 @@ where .map(|first_line| first_line.ends_with('{')) .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) + infix.len() - + first_line_width(rhs_result) + suffix.len(); + let one_line_width = last_line_width(&lhs_result) + pp.infix.len() + + first_line_width(rhs_result) + pp.suffix.len(); if one_line_width <= shape.width { - return Some(format!("{}{}{}{}", lhs_result, infix, rhs_result, suffix)); + return Some(format!( + "{}{}{}{}", + lhs_result, + pp.infix, + rhs_result, + pp.suffix + )); } } } @@ -357,8 +367,8 @@ where // Re-evaluate the rhs because we have more space now: let mut rhs_shape = match context.config.control_style() { Style::Legacy => shape - .sub_width(suffix.len() + prefix.len())? - .visual_indent(prefix.len()), + .sub_width(pp.suffix.len() + pp.prefix.len())? + .visual_indent(pp.prefix.len()), Style::Rfc => { // Try to calculate the initial constraint on the right hand side. let rhs_overhead = shape.rhs_overhead(context.config); @@ -367,31 +377,25 @@ where } }; let infix = match separator_place { - SeparatorPlace::Back => infix.trim_right(), - SeparatorPlace::Front => infix.trim_left(), + SeparatorPlace::Back => pp.infix.trim_right(), + SeparatorPlace::Front => pp.infix.trim_left(), }; if separator_place == SeparatorPlace::Front { rhs_shape = rhs_shape.offset_left(infix.len())?; } let rhs_result = rhs.rewrite(context, rhs_shape)?; - match separator_place { - SeparatorPlace::Back => Some(format!( - "{}{}\n{}{}{}", - lhs_result, - infix, - rhs_shape.indent.to_string(context.config), - rhs_result, - suffix - )), - SeparatorPlace::Front => Some(format!( - "{}\n{}{}{}{}", - lhs_result, - rhs_shape.indent.to_string(context.config), - infix, - rhs_result, - suffix - )), - } + let indent_str = rhs_shape.indent.to_string(context.config); + let infix_with_sep = match separator_place { + SeparatorPlace::Back => format!("{}\n{}", infix, indent_str), + SeparatorPlace::Front => format!("\n{}{}", indent_str, infix), + }; + Some(format!( + "{}{}{}{}", + lhs_result, + infix_with_sep, + rhs_result, + pp.suffix + )) } pub fn rewrite_array<'a, I>( diff --git a/src/lib.rs b/src/lib.rs index 6be778a5262..ee9d551c880 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,8 @@ #![feature(rustc_private)] +#[macro_use] +extern crate derive_new; extern crate diff; #[macro_use] extern crate log; diff --git a/src/patterns.rs b/src/patterns.rs index 38d850962bb..a7e6c48b6d2 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -65,7 +65,7 @@ impl Rewrite for Pat { rewrite_pair( &**lhs, &**rhs, - &PairParts("", infix, ""), + PairParts::new("", infix, ""), context, shape, SeparatorPlace::Front, diff --git a/src/types.rs b/src/types.rs index 26b5f702a70..59b4ac438b0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -709,7 +709,7 @@ impl Rewrite for ast::Ty { rewrite_pair( &**ty, &**repeats, - &PairParts(lbr, "; ", rbr), + PairParts::new(lbr, "; ", rbr), context, shape, SeparatorPlace::Back, -- cgit 1.4.1-3-g733a5 From d8d9fedf9e61a6bc59e3ace276532533a23d7045 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 6 Nov 2017 21:45:54 +0900 Subject: Propagate an error rather than panic --- src/lib.rs | 2 +- src/modules.rs | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index ee9d551c880..c042d9d7954 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -309,7 +309,7 @@ where // We always skip children for the "Plain" write mode, since there is // nothing to distinguish the nested module contents. let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; - for (path, module) in modules::list_files(krate, parse_session.codemap()) { + for (path, module) in modules::list_files(krate, parse_session.codemap())? { if skip_children && path.as_path() != main_file { continue; } diff --git a/src/modules.rs b/src/modules.rs index 3d4de51deb6..d136f270991 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -10,6 +10,7 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; +use std::io; use syntax::ast; use syntax::codemap; @@ -23,7 +24,7 @@ use utils::contains_skip; pub fn list_files<'a>( krate: &'a ast::Crate, codemap: &codemap::CodeMap, -) -> BTreeMap { +) -> Result, io::Error> { let mut result = BTreeMap::new(); // Enforce file order determinism let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); list_submodules( @@ -31,9 +32,9 @@ pub fn list_files<'a>( root_filename.parent().unwrap(), codemap, &mut result, - ); + )?; result.insert(root_filename, &krate.module); - result + Ok(result) } /// Recursively list all external modules included in a module. @@ -42,7 +43,7 @@ fn list_submodules<'a>( search_dir: &Path, codemap: &codemap::CodeMap, result: &mut BTreeMap, -) { +) -> Result<(), io::Error> { debug!("list_submodules: search_dir: {:?}", search_dir); for item in &module.items { if let ast::ItemKind::Mod(ref sub_mod) = item.node { @@ -52,15 +53,16 @@ fn list_submodules<'a>( let dir_path = if is_internal { search_dir.join(&item.ident.to_string()) } else { - let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap); + let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; let dir_path = mod_path.parent().unwrap().to_owned(); result.insert(mod_path, sub_mod); dir_path }; - list_submodules(sub_mod, &dir_path, codemap, result); + list_submodules(sub_mod, &dir_path, codemap, result)?; } } } + Ok(()) } /// Find the file corresponding to an external mod @@ -69,13 +71,16 @@ fn module_file( attrs: &[ast::Attribute], dir_path: &Path, codemap: &codemap::CodeMap, -) -> PathBuf { +) -> Result { if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { - return path; + return Ok(path); } match parser::Parser::default_submod_path(id, dir_path, codemap).result { - Ok(parser::ModulePathSuccess { path, .. }) => path, - Err(_) => unreachable!("Couldn't find module {}", id), + Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + format!("Couldn't find module {}", id), + )), } } -- cgit 1.4.1-3-g733a5 From f39559fef0ffb8420d2dcaf7cd229cc2f422bf38 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 6 Nov 2017 21:46:45 +0900 Subject: Use accessors instead of destucting --- src/items.rs | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 829d9a1e2d7..731ce234388 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1211,7 +1211,7 @@ fn format_tuple_struct( result.push_str(&header_str); let body_lo = if fields.is_empty() { - let lo = get_bytepos_after_visibility(context, vis, span, ")"); + let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")"); context.codemap.span_after(mk_sp(lo, span.hi()), "(") } else { fields[0].span.lo() @@ -1552,34 +1552,24 @@ fn rewrite_static( static_parts: &StaticParts, offset: Indent, ) -> Option { - let StaticParts { - prefix, - vis, - ident, - ty, - mutability, - expr_opt, - span, - } = *static_parts; let colon = colon_spaces( context.config.space_before_type_annotation(), context.config.space_after_type_annotation_colon(), ); let prefix = format!( "{}{} {}{}{}", - format_visibility(vis), - prefix, - format_mutability(mutability), - ident, + format_visibility(static_parts.vis), + static_parts.prefix, + format_mutability(static_parts.mutability), + static_parts.ident, colon, ); // 2 = " =".len() - let ty_str = ty.rewrite( - context, - Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?, - )?; + let ty_shape = + Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; + let ty_str = static_parts.ty.rewrite(context, ty_shape)?; - if let Some(expr) = expr_opt { + if let Some(expr) = static_parts.expr_opt { let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; let remaining_width = context.budget(offset.block_indent + 1); @@ -1588,7 +1578,9 @@ fn rewrite_static( lhs, expr, Shape::legacy(remaining_width, offset.block_only()), - ).and_then(|res| recover_comment_removed(res, span, context)) + ).and_then(|res| { + recover_comment_removed(res, static_parts.span, context) + }) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{}{};", prefix, ty_str)) -- cgit 1.4.1-3-g733a5 From e917eff7bac845727416aa8fb5818ecf114627f3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 6 Nov 2017 21:47:21 +0900 Subject: Remove unused imports --- src/utils.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index b8fb83fefe5..999ba9f67b9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -298,7 +298,6 @@ macro_rules! impl_enum_serialize_and_deserialize { impl<'de> ::serde::de::Deserialize<'de> for $e { fn deserialize(d: D) -> Result where D: ::serde::Deserializer<'de> { - use std::ascii::AsciiExt; use serde::de::{Error, Visitor}; use std::marker::PhantomData; use std::fmt; @@ -328,7 +327,6 @@ macro_rules! impl_enum_serialize_and_deserialize { type Err = &'static str; fn from_str(s: &str) -> Result { - use std::ascii::AsciiExt; $( if stringify!($x).eq_ignore_ascii_case(s) { return Ok($e::$x); -- cgit 1.4.1-3-g733a5 From aafaa2fc2ee0dcd07e01d07e7c238428fb583799 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 8 Nov 2017 07:59:14 +1300 Subject: Add git-fmt tool --- Cargo.toml | 3 + src/bin/git-fmt.rs | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 src/bin/git-fmt.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 3af4803bc5f..975aff5e6cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,9 @@ name = "cargo-fmt" [[bin]] name = "rustfmt-format-diff" +[[bin]] +name = "git-fmt" + [features] default = ["cargo-fmt", "rustfmt-format-diff"] cargo-fmt = [] diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs new file mode 100644 index 00000000000..aa54c3b5718 --- /dev/null +++ b/src/bin/git-fmt.rs @@ -0,0 +1,193 @@ +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate rustfmt_nightly as rustfmt; + +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::str::FromStr; + +use getopts::{Matches, Options}; + +use rustfmt::{run, Input}; +use rustfmt::config; + + +fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> { + let prefixes: Vec<_> = files + .iter() + .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) + .map(|f| &f[..f.len() - 6]) + .collect(); + + let mut pruned_prefixes = vec![]; + for p1 in prefixes.into_iter() { + let mut include = true; + if !p1.starts_with("src/bin/") { + for p2 in pruned_prefixes.iter() { + if p1.starts_with(p2) { + include = false; + break; + } + } + } + if include { + pruned_prefixes.push(p1); + } + } + debug!("prefixes: {:?}", pruned_prefixes); + + files + .into_iter() + .filter(|f| { + let mut include = true; + if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { + return true; + } + for pp in pruned_prefixes.iter() { + if f.starts_with(pp) { + include = false; + break; + } + } + include + }) + .collect() +} + +fn git_diff(commits: String) -> String { + let mut cmd = Command::new("git"); + cmd.arg("diff"); + if commits != "0" { + cmd.arg(format!("HEAD~{}", commits)); + } + let output = cmd.output().expect("Couldn't execute `git diff`"); + String::from_utf8_lossy(&output.stdout).into_owned() +} + +fn get_files(input: &str) -> Vec<&str> { + input + .lines() + .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) + .map(|line| &line[6..]) + .collect() +} + +fn fmt_files(files: &[&str]) -> i32 { + let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) + .unwrap_or_else(|_| (config::Config::default(), None)); + + let mut exit_code = 0; + for file in files { + let summary = run(Input::File(PathBuf::from(file)), &config); + if !summary.has_no_errors() { + exit_code = 1; + } + } + exit_code +} + +fn uncommitted_files() -> Vec { + let mut cmd = Command::new("git"); + cmd.arg("ls-files"); + cmd.arg("--others"); + cmd.arg("--modified"); + cmd.arg("--exclude-standard"); + let output = cmd.output().expect("Couldn't execute Git"); + let stdout = String::from_utf8_lossy(&output.stdout); + stdout.lines().map(|s| s.to_owned()).collect() +} + +fn check_uncommitted() { + let uncommitted = uncommitted_files(); + debug!("uncommitted files: {:?}", uncommitted); + if !uncommitted.is_empty() { + println!("Found untracked changes:"); + for f in uncommitted.iter() { + println!(" {}", f); + } + println!("Commit your work, or run with `-u`."); + println!("Exiting."); + std::process::exit(1); + } +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("c", "check", "check only, don't format (unimplemented)"); + opts.optflag("u", "uncommitted", "format uncommitted files"); + opts +} + +struct Config { + commits: String, + uncommitted: bool, + check: bool, +} + +impl Config { + fn from_args(matches: &Matches, opts: &Options) -> Config { + // `--help` display help message and quit + if matches.opt_present("h") { + let message = format!( + "\nusage: {} [options]\n\n\ + commits: number of commits to format, default: 1", + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&message)); + std::process::exit(0); + } + + let mut config = Config { + commits: "1".to_owned(), + uncommitted: false, + check: false, + }; + + if matches.opt_present("c") { + config.check = true; + unimplemented!(); + } + + if matches.opt_present("u") { + config.uncommitted = true; + } + + if matches.free.len() > 1 { + panic!("unknown arguments, use `-h` for usage"); + } + if matches.free.len() == 1 { + let commits = matches.free[0].trim(); + if let Err(_) = u32::from_str(&commits) { + panic!("Couldn't parse number of commits"); + } + config.commits = commits.to_owned(); + } + + config + } +} + +fn main() { + let _ = env_logger::init(); + + let opts = make_opts(); + let matches = opts.parse(env::args().skip(1)) + .expect("Couldn't parse command line"); + let config = Config::from_args(&matches, &opts); + + if !config.uncommitted { + check_uncommitted(); + } + + let stdout = git_diff(config.commits); + let files = get_files(&stdout); + debug!("files: {:?}", files); + let files = prune_files(files); + debug!("pruned files: {:?}", files); + let exit_code = fmt_files(&files); + std::process::exit(exit_code); +} -- cgit 1.4.1-3-g733a5 From 6a314158675731b0abf93a69417b5baae611059f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 8 Nov 2017 08:25:23 +0900 Subject: Use correct shape when there is a single child --- src/chains.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9864c901dc2..5ab538c8c4e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -126,7 +126,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_child_shape = if extend { let overhead = last_line_width(&parent_rewrite); - let offset = trimmed_last_line_width(&parent_rewrite); + let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; match context.config.chain_indent() { IndentStyle::Visual => parent_shape.offset_left(overhead)?, IndentStyle::Block => parent_shape.block().offset_left(offset)?, @@ -166,9 +166,16 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = match context.config.chain_indent() { - IndentStyle::Visual => other_child_shape.sub_width(shape.rhs_overhead(context.config))?, - IndentStyle::Block => other_child_shape, + let last_shape = { + let last_shape = if rewrites.len() == 0 { + first_child_shape + } else { + other_child_shape + }; + match context.config.chain_indent() { + IndentStyle::Visual => last_shape.sub_width(shape.rhs_overhead(context.config))?, + IndentStyle::Block => last_shape, + } }; let last_shape = last_shape.sub_width(suffix_try_num)?; -- cgit 1.4.1-3-g733a5 From 30959bc16f8bdbb95bff66537021d6b01281a99d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 8 Nov 2017 08:25:42 +0900 Subject: Cargo fmt --- src/items.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 731ce234388..dc3abd88ffd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2142,7 +2142,9 @@ fn rewrite_args( generics_str_contains_newline: bool, ) -> Option { let mut arg_item_strs = args.iter() - .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) + .map(|arg| { + arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) + }) .collect::>>()?; // Account for sugary self. @@ -2841,15 +2843,17 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.node { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => rewrite_fn_base( - context, - shape.indent, - self.ident, - &FnSig::new(fn_decl, generics, self.vis.clone()), - span, - false, - false, - ).map(|(s, _)| format!("{};", s)), + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { + rewrite_fn_base( + context, + shape.indent, + self.ident, + &FnSig::new(fn_decl, generics, self.vis.clone()), + span, + false, + false, + ).map(|(s, _)| format!("{};", s)) + } ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. -- cgit 1.4.1-3-g733a5 From 19a3b0b5ca863ea842c479d05ea343504acdcc77 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 8 Nov 2017 11:52:25 +0900 Subject: Use struct prefix as a callee --- src/items.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 731ce234388..6cfcc3dd4b1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1282,16 +1282,15 @@ fn format_tuple_struct( result.push(')'); } else { // 1 = "," - let body = rewrite_call_inner( + result = rewrite_call_inner( context, - "", + &result, &fields.iter().map(|field| field).collect::>()[..], span, Shape::indented(offset, context.config).sub_width(1)?, context.config.fn_call_width(), false, )?; - result.push_str(&body); } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') -- cgit 1.4.1-3-g733a5 From 9337760dd9d8f0a7b2b9cdff38685e2e0db193ec Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 8 Nov 2017 11:53:13 +0900 Subject: Refactor: use less vertical lines --- src/items.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6cfcc3dd4b1..f311da0afee 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1281,16 +1281,10 @@ fn format_tuple_struct( } result.push(')'); } else { - // 1 = "," - result = rewrite_call_inner( - context, - &result, - &fields.iter().map(|field| field).collect::>()[..], - span, - Shape::indented(offset, context.config).sub_width(1)?, - context.config.fn_call_width(), - false, - )?; + let shape = Shape::indented(offset, context.config); + let fields = &fields.iter().map(|field| field).collect::>()[..]; + let one_line_width = context.config.fn_call_width(); + result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') -- cgit 1.4.1-3-g733a5 From e8bc2bf966d1d4999e7fdb3d683c768a54dbfdb6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 8 Nov 2017 18:17:12 +1300 Subject: Tweak the uncommitted file rules for git-fmt --- src/bin/git-fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs index aa54c3b5718..984134d64de 100644 --- a/src/bin/git-fmt.rs +++ b/src/bin/git-fmt.rs @@ -97,7 +97,7 @@ fn uncommitted_files() -> Vec { cmd.arg("--exclude-standard"); let output = cmd.output().expect("Couldn't execute Git"); let stdout = String::from_utf8_lossy(&output.stdout); - stdout.lines().map(|s| s.to_owned()).collect() + stdout.lines().filter(|s| s.ends_with(".rs")).map(|s| s.to_owned()).collect() } fn check_uncommitted() { -- cgit 1.4.1-3-g733a5 From bfa093d394ac64cdeb4842789890cb9c88269313 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 8 Nov 2017 21:10:47 +1300 Subject: Fix formatting in git-fmt --- src/bin/git-fmt.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs index 984134d64de..20a502f1553 100644 --- a/src/bin/git-fmt.rs +++ b/src/bin/git-fmt.rs @@ -97,7 +97,11 @@ fn uncommitted_files() -> Vec { cmd.arg("--exclude-standard"); let output = cmd.output().expect("Couldn't execute Git"); let stdout = String::from_utf8_lossy(&output.stdout); - stdout.lines().filter(|s| s.ends_with(".rs")).map(|s| s.to_owned()).collect() + stdout + .lines() + .filter(|s| s.ends_with(".rs")) + .map(|s| s.to_owned()) + .collect() } fn check_uncommitted() { -- cgit 1.4.1-3-g733a5 From fd10925a083e07ebcf56f6596e5a94410d9b9d1e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 8 Nov 2017 18:24:03 +0900 Subject: Implement soft wrapping on doc comments --- src/visitor.rs | 219 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 131 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 417b12b2d53..a3fc1218145 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -19,7 +19,7 @@ use syntax::parse::ParseSess; use expr::rewrite_literal; use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{contains_comment, recover_missing_comment_in_span, remove_trailing_white_spaces, +use comment::{combine_strs_with_missing_comments, contains_comment, remove_trailing_white_spaces, CodeCharKind, CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; @@ -791,106 +791,149 @@ impl Rewrite for ast::Attribute { } } +/// Returns the first group of attributes that fills the given predicate. +/// We consider two doc comments are in different group if they are separated by normal comments. +fn take_while_with_pred<'a, P>( + context: &RewriteContext, + attrs: &'a [ast::Attribute], + pred: P, +) -> Option<&'a [ast::Attribute]> +where + P: Fn(&ast::Attribute) -> bool, +{ + let mut last_index = 0; + let mut iter = attrs.iter().enumerate().peekable(); + while let Some((i, attr)) = iter.next() { + if !pred(attr) { + break; + } + if let Some(&(_, next_attr)) = iter.peek() { + // Extract comments between two attributes. + let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); + let snippet = context.snippet(span_between_attr); + if snippet.chars().filter(|c| *c == '\n').count() >= 2 || snippet.contains('/') { + break; + } + } + last_index = i; + } + if last_index == 0 { + None + } else { + Some(&attrs[..last_index + 1]) + } +} + +fn rewrite_first_group_attrs( + context: &RewriteContext, + attrs: &[ast::Attribute], + shape: Shape, +) -> Option<(usize, String)> { + if attrs.is_empty() { + return Some((0, String::new())); + } + // Rewrite doc comments + match take_while_with_pred(context, attrs, |a| a.is_sugared_doc) { + Some(sugared_docs) if !sugared_docs.is_empty() => { + let snippet = sugared_docs + .iter() + .map(|a| context.snippet(a.span)) + .collect::>() + .join("\n"); + return Some(( + sugared_docs.len(), + rewrite_comment(&snippet, false, shape, context.config)?, + )); + } + _ => (), + } + // Rewrite `#[derive(..)]`s. + if context.config.merge_derives() { + match take_while_with_pred(context, attrs, is_derive) { + Some(derives) if !derives.is_empty() => { + let mut derive_args = vec![]; + for derive in derives { + derive_args.append(&mut get_derive_args(context, derive)?); + } + return Some(( + derives.len(), + format_derive(context, &derive_args, shape)?, + )); + } + _ => (), + } + } + // Rewrite the first attribute. + Some((1, attrs[0].rewrite(context, shape)?)) +} + +fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { + // Look at before and after comment and see if there are any empty lines. + let comment_begin = comment.chars().position(|c| c == '/'); + let len = comment_begin.unwrap_or_else(|| comment.len()); + let mlb = comment.chars().take(len).filter(|c| *c == '\n').count() > 1; + let mla = if comment_begin.is_none() { + mlb + } else { + let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); + let len = comment_end.unwrap(); + comment + .chars() + .rev() + .take(len) + .filter(|c| *c == '\n') + .count() > 1 + }; + (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) +} + impl<'a> Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if self.is_empty() { return Some(String::new()); } - let mut result = String::with_capacity(128); - let indent = shape.indent.to_string(context.config); - - let mut derive_args = Vec::new(); - - let mut iter = self.iter().enumerate().peekable(); - let mut insert_new_line = true; - let mut is_prev_sugared_doc = false; - while let Some((i, a)) = iter.next() { - let a_str = a.rewrite(context, shape)?; - - // Write comments and blank lines between attributes. - if i > 0 { - let comment = context.snippet(mk_sp(self[i - 1].span.hi(), a.span.lo())); - // This particular horror show is to preserve line breaks in between doc - // comments. An alternative would be to force such line breaks to start - // with the usual doc comment token. - let (multi_line_before, multi_line_after) = if a.is_sugared_doc - || is_prev_sugared_doc - { - // Look at before and after comment and see if there are any empty lines. - let comment_begin = comment.chars().position(|c| c == '/'); - let len = comment_begin.unwrap_or_else(|| comment.len()); - let mlb = comment.chars().take(len).filter(|c| *c == '\n').count() > 1; - let mla = if comment_begin.is_none() { - mlb - } else { - let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); - let len = comment_end.unwrap(); - comment - .chars() - .rev() - .take(len) - .filter(|c| *c == '\n') - .count() > 1 - }; - (mlb, mla) - } else { - (false, false) - }; - - let comment = recover_missing_comment_in_span( - mk_sp(self[i - 1].span.hi(), a.span.lo()), + let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?; + if self.len() == 1 || first_group_len == self.len() { + Some(first_group_str) + } else { + let rest_str = self[first_group_len..].rewrite(context, shape)?; + let missing_span = mk_sp( + self[first_group_len - 1].span.hi(), + self[first_group_len].span.lo(), + ); + // Preserve an empty line before/after doc comments. + if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { + let snippet = context.snippet(missing_span); + let (mla, mlb) = has_newlines_before_after_comment(&snippet); + let comment = ::comment::recover_missing_comment_in_span( + missing_span, shape.with_max_width(context.config), context, 0, )?; - - if !comment.is_empty() { - if multi_line_before { - result.push('\n'); - } - result.push_str(&comment); - result.push('\n'); - if multi_line_after { - result.push('\n') - } - } else if insert_new_line { - result.push('\n'); - if multi_line_after { - result.push('\n') - } - } - - if derive_args.is_empty() { - result.push_str(&indent); - } - - insert_new_line = true; - } - - // Write the attribute itself. - if context.config.merge_derives() { - // If the attribute is `#[derive(...)]`, take the arguments. - if let Some(mut args) = get_derive_args(context, a) { - derive_args.append(&mut args); - match iter.peek() { - // If the next attribute is `#[derive(...)]` as well, skip rewriting. - Some(&(_, next_attr)) if is_derive(next_attr) => insert_new_line = false, - // If not, rewrite the merged derives. - _ => { - result.push_str(&format_derive(context, &derive_args, shape)?); - derive_args.clear(); - } - } + let comment = if comment.is_empty() { + format!("\n{}", mlb) } else { - result.push_str(&a_str); - } + format!("{}{}\n{}", mla, comment, mlb) + }; + Some(format!( + "{}{}{}{}", + first_group_str, + comment, + shape.indent.to_string(context.config), + rest_str + )) } else { - result.push_str(&a_str); + combine_strs_with_missing_comments( + context, + &first_group_str, + &rest_str, + missing_span, + shape, + false, + ) } - - is_prev_sugared_doc = a.is_sugared_doc; } - Some(result) } } -- cgit 1.4.1-3-g733a5 From 119b49dad0d1b9736138dc46dab4483a8d80df44 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 8 Nov 2017 18:24:13 +0900 Subject: Cargo fmt --- src/bin/git-fmt.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs index 984134d64de..20a502f1553 100644 --- a/src/bin/git-fmt.rs +++ b/src/bin/git-fmt.rs @@ -97,7 +97,11 @@ fn uncommitted_files() -> Vec { cmd.arg("--exclude-standard"); let output = cmd.output().expect("Couldn't execute Git"); let stdout = String::from_utf8_lossy(&output.stdout); - stdout.lines().filter(|s| s.ends_with(".rs")).map(|s| s.to_owned()).collect() + stdout + .lines() + .filter(|s| s.ends_with(".rs")) + .map(|s| s.to_owned()) + .collect() } fn check_uncommitted() { -- cgit 1.4.1-3-g733a5 From e079cb81efd07088f074191f8acbf07c7dc0890b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 9 Nov 2017 11:33:35 +0900 Subject: Remove 'Option<_>' from return type of 'take_while_with_pred()' --- src/visitor.rs | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index a3fc1218145..c613b3b8a55 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -797,7 +797,7 @@ fn take_while_with_pred<'a, P>( context: &RewriteContext, attrs: &'a [ast::Attribute], pred: P, -) -> Option<&'a [ast::Attribute]> +) -> &'a [ast::Attribute] where P: Fn(&ast::Attribute) -> bool, { @@ -818,9 +818,9 @@ where last_index = i; } if last_index == 0 { - None + &[] } else { - Some(&attrs[..last_index + 1]) + &attrs[..last_index + 1] } } @@ -833,34 +833,30 @@ fn rewrite_first_group_attrs( return Some((0, String::new())); } // Rewrite doc comments - match take_while_with_pred(context, attrs, |a| a.is_sugared_doc) { - Some(sugared_docs) if !sugared_docs.is_empty() => { - let snippet = sugared_docs - .iter() - .map(|a| context.snippet(a.span)) - .collect::>() - .join("\n"); - return Some(( - sugared_docs.len(), - rewrite_comment(&snippet, false, shape, context.config)?, - )); - } - _ => (), + let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); + if !sugared_docs.is_empty() { + let snippet = sugared_docs + .iter() + .map(|a| context.snippet(a.span)) + .collect::>() + .join("\n"); + return Some(( + sugared_docs.len(), + rewrite_comment(&snippet, false, shape, context.config)?, + )); } // Rewrite `#[derive(..)]`s. if context.config.merge_derives() { - match take_while_with_pred(context, attrs, is_derive) { - Some(derives) if !derives.is_empty() => { - let mut derive_args = vec![]; - for derive in derives { - derive_args.append(&mut get_derive_args(context, derive)?); - } - return Some(( - derives.len(), - format_derive(context, &derive_args, shape)?, - )); + let derives = take_while_with_pred(context, attrs, is_derive); + if !derives.is_empty() { + let mut derive_args = vec![]; + for derive in derives { + derive_args.append(&mut get_derive_args(context, derive)?); } - _ => (), + return Some(( + derives.len(), + format_derive(context, &derive_args, shape)?, + )); } } // Rewrite the first attribute. -- cgit 1.4.1-3-g733a5 From 6ce42823cb4fa397b60fda53625009420a7f6bd2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 10 Nov 2017 17:08:57 +0900 Subject: Add opt_snippet() and opt_span_after() --- src/codemap.rs | 8 ++++++++ src/visitor.rs | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs index f62bb16dfa2..efbe50bcf64 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -34,6 +34,7 @@ pub trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; fn span_after_last(&self, original: Span, needle: &str) -> BytePos; fn span_before(&self, original: Span, needle: &str) -> BytePos; + fn opt_span_after(&self, original: Span, needle: &str) -> Option; } pub trait LineRangeUtils { @@ -70,6 +71,13 @@ impl SpanUtils for CodeMap { original.lo() + BytePos(offset as u32) } + + fn opt_span_after(&self, original: Span, needle: &str) -> Option { + let snippet = self.span_to_snippet(original).ok()?; + let offset = snippet.find_uncommented(needle)? + needle.len(); + + Some(original.lo() + BytePos(offset as u32)) + } } impl LineRangeUtils for CodeMap { diff --git a/src/visitor.rs b/src/visitor.rs index c613b3b8a55..8e8cd379e82 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -510,6 +510,10 @@ impl<'a> FmtVisitor<'a> { } } + pub fn opt_snippet(&self, span: Span) -> Option { + self.codemap.span_to_snippet(span).ok() + } + pub fn snippet(&self, span: Span) -> String { match self.codemap.span_to_snippet(span) { Ok(s) => s, -- cgit 1.4.1-3-g733a5 From 05798572bb59b59078c1fbd213ae22916d498010 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 10 Nov 2017 17:09:31 +0900 Subject: Remove empty lines at the beginning of the file --- src/lib.rs | 2 ++ src/visitor.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index c042d9d7954..7b441c4de02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -321,6 +321,7 @@ where let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; // Format inner attributes if available. if !krate.attrs.is_empty() && path == main_file { + visitor.skip_empty_lines(filemap.end_pos); if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); } else { @@ -328,6 +329,7 @@ where } } else { visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); visitor.format_separate_mod(module, &*filemap); }; diff --git a/src/visitor.rs b/src/visitor.rs index 8e8cd379e82..b69edfda0c6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -699,6 +699,20 @@ impl<'a> FmtVisitor<'a> { self.format_missing_with_indent(filemap.end_pos); } + pub fn skip_empty_lines(&mut self, end_pos: BytePos) { + while let Some(pos) = self.codemap + .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") + { + if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { + if snippet.trim().is_empty() { + self.last_pos = pos; + } else { + return; + } + } + } + } + pub fn get_context(&self) -> RewriteContext { RewriteContext { parse_session: self.parse_session, -- cgit 1.4.1-3-g733a5 From 76f5bc06c4f33e7d0ef5425698754b52db17919a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 10 Nov 2017 21:21:06 +0900 Subject: Fix a typo --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 30f3d6f4be4..f6a6f81dbf1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -937,7 +937,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); - let shape = Shape::indented(offset + last_line_width(&result), context.config); + let shape = Shape::indented(offset, context.config); let generics_str = rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; result.push_str(&generics_str); -- cgit 1.4.1-3-g733a5 From 4d28e148a583cec7c64513ecd0dc9bd150f35f1e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 10 Nov 2017 21:21:53 +0900 Subject: Return None when there are comments around trait bounds --- src/items.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f6a6f81dbf1..dcca3a77cac 100644 --- a/src/items.rs +++ b/src/items.rs @@ -942,6 +942,15 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; result.push_str(&generics_str); + // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. + if !type_param_bounds.is_empty() { + let ident_hi = context.codemap.span_after(item.span, &format!("{}", item.ident)); + let bound_hi = type_param_bounds.last().unwrap().span().hi(); + let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); + if contains_comment(&snippet) { + return None; + } + } let trait_bound_str = rewrite_trait_bounds( context, type_param_bounds, -- cgit 1.4.1-3-g733a5 From 1664ebb18ba1d50fc2b77daef5a496b167f9fad0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 11 Nov 2017 23:14:24 +0900 Subject: Return 'None' when macro call snippet from source exceeds max width --- src/expr.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d8f42944ad0..6cbbcc5c466 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -35,7 +35,7 @@ use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, outer_attributes, paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr, - trimmed_last_line_width}; + trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -168,10 +168,13 @@ pub fn format_expr( ast::ExprKind::TupField(..) | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), ast::ExprKind::Mac(ref mac) => { - // Failure to rewrite a macro should not imply failure to - // rewrite the expression. - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - .or_else(|| Some(context.snippet(expr.span))) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str( + context.snippet(expr.span), + context.config.max_width(), + shape, + ) + }) } ast::ExprKind::Ret(None) => Some("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { -- cgit 1.4.1-3-g733a5 From 033ce59a6add4bb615676dc8564fdefba9eca193 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 11 Nov 2017 23:15:33 +0900 Subject: Return None when string literal from source exceeds max width --- src/expr.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6cbbcc5c466..28ad978fbc7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1929,7 +1929,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt .all(|line| line.ends_with('\\')) { let new_indent = shape.visual_indent(1).indent; - return Some(String::from( + let indented_string_lit = String::from( string_lit .lines() .map(|line| { @@ -1942,16 +1942,17 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt .collect::>() .join("\n") .trim_left(), - )); + ); + return wrap_str(indented_string_lit, context.config.max_width(), shape); } else { - return Some(string_lit); + return wrap_str(string_lit, context.config.max_width(), shape); } } if !context.config.force_format_strings() && !string_requires_rewrite(context, span, &string_lit, shape) { - return Some(string_lit); + return wrap_str(string_lit, context.config.max_width(), shape); } // Remove the quote characters. -- cgit 1.4.1-3-g733a5 From d9e31be40f8ce780e1808c158eb2a30753dcaaac Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 11 Nov 2017 23:15:57 +0900 Subject: Refactor: use less vertical lines --- src/expr.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 28ad978fbc7..4016cd1aa60 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1597,13 +1597,11 @@ fn rewrite_match_arm( arm_comma(context.config, body, is_last), )); } - ( - mk_sp( - arm.attrs[arm.attrs.len() - 1].span.hi(), - arm.pats[0].span.lo(), - ), - arm.attrs.rewrite(context, shape)?, - ) + let missing_span = mk_sp( + arm.attrs[arm.attrs.len() - 1].span.hi(), + arm.pats[0].span.lo(), + ); + (missing_span, arm.attrs.rewrite(context, shape)?) } else { (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; @@ -1727,14 +1725,10 @@ fn rewrite_match_body( }; let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; - let next_line_indent = if is_block { - if is_empty_block { - shape.indent.block_indent(context.config) - } else { - shape.indent - } - } else { + let next_line_indent = if !is_block || is_empty_block { shape.indent.block_indent(context.config) + } else { + shape.indent }; let combine_next_line_body = |body_str: &str| { if is_block { -- cgit 1.4.1-3-g733a5 From c485202907e568d7b61d3958f0b58ff16d8c16d7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 13 Nov 2017 08:02:06 +0900 Subject: Format generics on unit struct --- src/items.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index dcca3a77cac..b9c8e37ea0d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -911,7 +911,7 @@ fn format_struct( one_line_width: Option, ) -> Option { match *struct_parts.def { - ast::VariantData::Unit(..) => Some(format_unit_struct(struct_parts)), + ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset), ast::VariantData::Tuple(ref fields, _) => { format_tuple_struct(context, struct_parts, fields, offset) } @@ -1088,8 +1088,15 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } -fn format_unit_struct(p: &StructParts) -> String { - format!("{};", format_header(p.prefix, p.ident, p.vis)) +fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { + let header_str = format_header(p.prefix, p.ident, p.vis); + let generics_str = if let Some(generics) = p.generics { + let shape = Shape::indented(offset, context.config).offset_left(header_str.len())?; + rewrite_generics(context, generics, shape, generics.span)? + } else { + String::new() + }; + Some(format!("{}{};", header_str, generics_str)) } pub fn format_struct_struct( -- cgit 1.4.1-3-g733a5 From f45aba9ced97ff2dae47ecceb2bd03950a71a07d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 13 Nov 2017 08:02:23 +0900 Subject: Cargo clippy --- src/bin/git-fmt.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs index 20a502f1553..9bfeff8420e 100644 --- a/src/bin/git-fmt.rs +++ b/src/bin/git-fmt.rs @@ -15,7 +15,7 @@ use rustfmt::{run, Input}; use rustfmt::config; -fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> { +fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files .iter() .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) @@ -23,10 +23,10 @@ fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> { .collect(); let mut pruned_prefixes = vec![]; - for p1 in prefixes.into_iter() { + for p1 in prefixes { let mut include = true; if !p1.starts_with("src/bin/") { - for p2 in pruned_prefixes.iter() { + for p2 in &pruned_prefixes { if p1.starts_with(p2) { include = false; break; @@ -46,7 +46,7 @@ fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> { if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { return true; } - for pp in pruned_prefixes.iter() { + for pp in &pruned_prefixes { if f.starts_with(pp) { include = false; break; @@ -57,7 +57,7 @@ fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> { .collect() } -fn git_diff(commits: String) -> String { +fn git_diff(commits: &str) -> String { let mut cmd = Command::new("git"); cmd.arg("diff"); if commits != "0" { @@ -109,7 +109,7 @@ fn check_uncommitted() { debug!("uncommitted files: {:?}", uncommitted); if !uncommitted.is_empty() { println!("Found untracked changes:"); - for f in uncommitted.iter() { + for f in &uncommitted { println!(" {}", f); } println!("Commit your work, or run with `-u`."); @@ -165,7 +165,7 @@ impl Config { } if matches.free.len() == 1 { let commits = matches.free[0].trim(); - if let Err(_) = u32::from_str(&commits) { + if u32::from_str(commits).is_err() { panic!("Couldn't parse number of commits"); } config.commits = commits.to_owned(); @@ -187,7 +187,7 @@ fn main() { check_uncommitted(); } - let stdout = git_diff(config.commits); + let stdout = git_diff(&config.commits); let files = get_files(&stdout); debug!("files: {:?}", files); let files = prune_files(files); -- cgit 1.4.1-3-g733a5 From 687b26c688a2d4b05c753923db187e31cdcd057f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 13 Nov 2017 11:06:53 +0900 Subject: Add BracePos --- src/items.rs | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index b9c8e37ea0d..8aa63261ce5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -441,7 +441,11 @@ impl<'a> FmtVisitor<'a> { &self.get_context(), generics, self.config.item_brace_style(), - enum_def.variants.is_empty(), + if enum_def.variants.is_empty() { + BracePos::ForceSameLine + } else { + BracePos::Auto + }, self.block_indent, mk_sp(span.lo(), body_start), last_line_width(&enum_header), @@ -1120,7 +1124,11 @@ pub fn format_struct_struct( context, g, context.config.item_brace_style(), - fields.is_empty(), + if fields.is_empty() { + BracePos::ForceSameLine + } else { + BracePos::Auto + }, offset, mk_sp(header_hi, body_lo), last_line_width(&result), @@ -2778,11 +2786,18 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S format!("{}{}{}", format_visibility(vis), item_name, ident) } +#[derive(PartialEq, Eq)] +enum BracePos { + None, + Auto, + ForceSameLine, +} + fn format_generics( context: &RewriteContext, generics: &ast::Generics, brace_style: BraceStyle, - force_same_line_brace: bool, + brace_pos: BracePos, offset: Indent, span: Span, used_width: usize, @@ -2792,7 +2807,10 @@ fn format_generics( let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = context.budget(last_line_used_width(&result, offset.width())); - let option = WhereClauseOption::snuggled(&result); + let mut option = WhereClauseOption::snuggled(&result); + if brace_pos == BracePos::None { + option.suppress_comma = true; + } // If the generics are not parameterized then generics.span.hi() == 0, // so we use span.lo(), which is the position after `struct Foo`. let span_end_before_where = if generics.is_parameterized() { @@ -2813,19 +2831,22 @@ fn format_generics( false, )?; result.push_str(&where_clause_str); - force_same_line_brace || brace_style == BraceStyle::PreferSameLine + brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine || (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1) } else { - force_same_line_brace || trimmed_last_line_width(&result) == 1 + brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1 || brace_style != BraceStyle::AlwaysNextLine }; + if brace_pos == BracePos::None { + return Some(result); + } let total_used_width = last_line_used_width(&result, used_width); let remaining_budget = context.budget(total_used_width); // If the same line brace if forced, it indicates that we are rewriting an item with empty body, // and hence we take the closer into account as well for one line budget. // We assume that the closer has the same length as the opener. - let overhead = if force_same_line_brace { + let overhead = if brace_pos == BracePos::ForceSameLine { // 3 = ` {}` 3 } else { -- cgit 1.4.1-3-g733a5 From 6b8cd40d07ce0cb52891b419ee2b6574caf1e70f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 13 Nov 2017 11:07:09 +0900 Subject: Format where clause on unit struct --- src/items.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8aa63261ce5..de0dc763e1b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1095,8 +1095,20 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { let header_str = format_header(p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { - let shape = Shape::indented(offset, context.config).offset_left(header_str.len())?; - rewrite_generics(context, generics, shape, generics.span)? + let hi = if generics.where_clause.predicates.is_empty() { + generics.span.hi() + } else { + generics.where_clause.span.hi() + }; + format_generics( + context, + generics, + context.config.item_brace_style(), + BracePos::None, + offset, + mk_sp(generics.span.lo(), hi), + last_line_width(&header_str), + )? } else { String::new() }; -- cgit 1.4.1-3-g733a5 From 10bce817d9e9a3d3cbd4ab49d52a3af064e9ce3d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Nov 2017 15:13:23 +1300 Subject: Some basic refactoring --- src/expr.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4016cd1aa60..d264f568607 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -616,6 +616,8 @@ fn rewrite_closure( context: &RewriteContext, shape: Shape, ) -> Option { + debug!("rewrite_closure {:?}", body); + let (prefix, extra_offset) = rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?; // 1 = space between `|...|` and body. @@ -627,25 +629,26 @@ fn rewrite_closure( return Some(format!("{} {{}}", prefix)); } + let no_return_type = match fn_decl.output { + ast::FunctionRetTy::Default(_) => true, + _ => false, + }; + // Figure out if the block is necessary. let needs_block = is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro || block_contains_comment(block, context.codemap) || prefix.contains('\n'); - let no_return_type = if let ast::FunctionRetTy::Default(_) = fn_decl.output { - true - } else { - false - }; if no_return_type && !needs_block { // block.stmts.len() == 1 if let Some(expr) = stmt_expr(&block.stmts[0]) { - if let Some(rw) = if is_block_closure_forced(expr) { - rewrite_closure_with_block(context, shape, &prefix, expr) + let result = if is_block_closure_forced(expr) { + rewrite_closure_with_block(expr, &prefix, context, shape) } else { rewrite_closure_expr(expr, &prefix, context, body_shape) - } { - return Some(rw); + }; + if result.is_some() { + return result; } } } @@ -656,17 +659,17 @@ fn rewrite_closure( rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { // The closure originally had a non-block expression, but we can't fit on // one line, so we'll insert a block. - rewrite_closure_with_block(context, body_shape, &prefix, body) + rewrite_closure_with_block(body, &prefix, context, body_shape) }) } } // Rewrite closure with a single expression wrapping its body with block. fn rewrite_closure_with_block( + body: &ast::Expr, + prefix: &str, context: &RewriteContext, shape: Shape, - prefix: &str, - body: &ast::Expr, ) -> Option { let block = ast::Block { stmts: vec![ @@ -2254,7 +2257,7 @@ fn rewrite_last_closure( // We force to use block for the body of the closure for certain kinds of expressions. if is_block_closure_forced(body) { - return rewrite_closure_with_block(context, body_shape, &prefix, body).and_then( + return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( |body_str| { // If the expression can fit in a single line, we need not force block closure. if body_str.lines().count() <= 7 { @@ -2279,7 +2282,7 @@ fn rewrite_last_closure( .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) .unwrap_or(false); if is_multi_lined_cond { - return rewrite_closure_with_block(context, body_shape, &prefix, body); + return rewrite_closure_with_block(body, &prefix, context, body_shape); } // Seems fine, just format the closure in usual manner. -- cgit 1.4.1-3-g733a5 From e6253c4d3178b27b8055e7ce3936f38c645c9bdb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Nov 2017 15:26:33 +1300 Subject: Extract a closures module --- src/closures.rs | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/expr.rs | 337 ++----------------------------------------------------- src/lib.rs | 1 + 3 files changed, 349 insertions(+), 327 deletions(-) create mode 100644 src/closures.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs new file mode 100644 index 00000000000..6eff97af295 --- /dev/null +++ b/src/closures.rs @@ -0,0 +1,338 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::{ast, ptr}; +use syntax::codemap::Span; +use syntax::parse::classify; + +use codemap::SpanUtils; +use expr::{block_contains_comment, is_simple_block, is_unsafe_block, need_block_indent, + rewrite_cond, ToExpr}; +use items::{span_hi_for_arg, span_lo_for_arg}; +use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, + ListTactic, Separator, SeparatorPlace, SeparatorTactic}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{last_line_width, left_most_sub_expr, stmt_expr}; + +// This functions is pretty messy because of the rules around closures and blocks: +// FIXME - the below is probably no longer true in full. +// * if there is a return type, then there must be braces, +// * given a closure with braces, whether that is parsed to give an inner block +// or not depends on if there is a return type and if there are statements +// in that block, +// * if the first expression in the body ends with a block (i.e., is a +// statement without needing a semi-colon), then adding or removing braces +// can change whether it is treated as an expression or statement. +pub fn rewrite_closure( + capture: ast::CaptureBy, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + debug!("rewrite_closure {:?}", body); + + let (prefix, extra_offset) = + rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?; + // 1 = space between `|...|` and body. + let body_shape = shape.offset_left(extra_offset)?; + + if let ast::ExprKind::Block(ref block) = body.node { + // The body of the closure is an empty block. + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + return Some(format!("{} {{}}", prefix)); + } + + let no_return_type = match fn_decl.output { + ast::FunctionRetTy::Default(_) => true, + _ => false, + }; + + // Figure out if the block is necessary. + let needs_block = is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro + || block_contains_comment(block, context.codemap) + || prefix.contains('\n'); + + if no_return_type && !needs_block { + // block.stmts.len() == 1 + if let Some(expr) = stmt_expr(&block.stmts[0]) { + let result = if is_block_closure_forced(expr) { + rewrite_closure_with_block(expr, &prefix, context, shape) + } else { + rewrite_closure_expr(expr, &prefix, context, body_shape) + }; + if result.is_some() { + return result; + } + } + } + + // Either we require a block, or tried without and failed. + rewrite_closure_block(block, &prefix, context, body_shape) + } else { + rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { + // The closure originally had a non-block expression, but we can't fit on + // one line, so we'll insert a block. + rewrite_closure_with_block(body, &prefix, context, body_shape) + }) + } +} + +// Rewrite closure with a single expression wrapping its body with block. +fn rewrite_closure_with_block( + body: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + let block = ast::Block { + stmts: vec![ + ast::Stmt { + id: ast::NodeId::new(0), + node: ast::StmtKind::Expr(ptr::P(body.clone())), + span: body.span, + }, + ], + id: ast::NodeId::new(0), + rules: ast::BlockCheckMode::Default, + span: body.span, + }; + rewrite_closure_block(&block, prefix, context, shape) +} + +// Rewrite closure with a single expression without wrapping its body with block. +fn rewrite_closure_expr( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut rewrite = expr.rewrite(context, shape); + if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { + rewrite = and_one_line(rewrite); + } + rewrite = rewrite.and_then(|rw| { + if context.config.multiline_closure_forces_block() && rw.contains('\n') { + None + } else { + Some(rw) + } + }); + rewrite.map(|rw| format!("{} {}", prefix, rw)) +} + +// Rewrite closure whose body is block. +fn rewrite_closure_block( + block: &ast::Block, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + // Start with visual indent, then fall back to block indent if the + // closure is large. + let block_threshold = context.config.closure_block_indent_threshold(); + if block_threshold >= 0 { + if let Some(block_str) = block.rewrite(context, shape) { + if block_str.matches('\n').count() <= block_threshold as usize + && !need_block_indent(&block_str, shape) + { + return Some(format!("{} {}", prefix, block_str)); + } + } + } + + // The body of the closure is big enough to be block indented, that + // means we must re-format. + let block_shape = shape.block(); + let block_str = block.rewrite(context, block_shape)?; + Some(format!("{} {}", prefix, block_str)) +} + +// Return type is (prefix, extra_offset) +fn rewrite_closure_fn_decl( + capture: ast::CaptureBy, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option<(String, usize)> { + let mover = if capture == ast::CaptureBy::Value { + "move " + } else { + "" + }; + // 4 = "|| {".len(), which is overconservative when the closure consists of + // a single expression. + let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?; + + // 1 = | + let argument_offset = nested_shape.indent + 1; + let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); + let ret_str = fn_decl.output.rewrite(context, arg_shape)?; + + let arg_items = itemize_list( + context.codemap, + fn_decl.inputs.iter(), + "|", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(context, arg), + |arg| arg.rewrite(context, arg_shape), + context.codemap.span_after(span, "|"), + body.span.lo(), + false, + ); + let item_vec = arg_items.collect::>(); + // 1 = space between arguments and return type. + let horizontal_budget = nested_shape + .width + .checked_sub(ret_str.len() + 1) + .unwrap_or(0); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + horizontal_budget, + ); + let arg_shape = match tactic { + DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, + _ => arg_shape, + }; + + let fmt = ListFormatting { + tactic: tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arg_shape, + ends_with_newline: false, + preserve_newline: true, + config: context.config, + }; + let list_str = write_list(&item_vec, &fmt)?; + let mut prefix = format!("{}|{}|", mover, list_str); + + if !ret_str.is_empty() { + if prefix.contains('\n') { + prefix.push('\n'); + prefix.push_str(&argument_offset.to_string(context.config)); + } else { + prefix.push(' '); + } + prefix.push_str(&ret_str); + } + // 1 = space between `|...|` and body. + let extra_offset = last_line_width(&prefix) + 1; + + Some((prefix, extra_offset)) +} + +// Rewriting closure which is placed at the end of the function call's arg. +// Returns `None` if the reformatted closure 'looks bad'. +pub fn rewrite_last_closure( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, +) -> Option { + if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node { + let body = match body.node { + ast::ExprKind::Block(ref block) if is_simple_block(block, context.codemap) => { + stmt_expr(&block.stmts[0]).unwrap_or(body) + } + _ => body, + }; + let (prefix, extra_offset) = + rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?; + // If the closure goes multi line before its body, do not overflow the closure. + if prefix.contains('\n') { + return None; + } + // If we are inside macro, we do not want to add or remove block from closure body. + if context.inside_macro { + return expr.rewrite(context, shape); + } + + let body_shape = shape.offset_left(extra_offset)?; + + // We force to use block for the body of the closure for certain kinds of expressions. + if is_block_closure_forced(body) { + return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( + |body_str| { + // If the expression can fit in a single line, we need not force block closure. + if body_str.lines().count() <= 7 { + match rewrite_closure_expr(body, &prefix, context, shape) { + Some(ref single_line_body_str) + if !single_line_body_str.contains('\n') => + { + Some(single_line_body_str.clone()) + } + _ => Some(body_str), + } + } else { + Some(body_str) + } + }, + ); + } + + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + let is_multi_lined_cond = rewrite_cond(context, body, body_shape) + .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) + .unwrap_or(false); + if is_multi_lined_cond { + return rewrite_closure_with_block(body, &prefix, context, body_shape); + } + + // Seems fine, just format the closure in usual manner. + return expr.rewrite(context, shape); + } + None +} + +/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. +pub fn args_have_many_closure(args: &[&T]) -> bool +where + T: ToExpr, +{ + args.iter() + .filter(|arg| { + arg.to_expr() + .map(|e| match e.node { + ast::ExprKind::Closure(..) => true, + _ => false, + }) + .unwrap_or(false) + }) + .count() > 1 +} + +fn is_block_closure_forced(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::If(..) | + ast::ExprKind::IfLet(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) | + ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::AddrOf(_, ref expr) | + ast::ExprKind::Box(ref expr) | + ast::ExprKind::Try(ref expr) | + ast::ExprKind::Unary(_, ref expr) | + ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr), + _ => false, + } +} + +fn and_one_line(x: Option) -> Option { + x.and_then(|x| if x.contains('\n') { None } else { Some(x) }) +} diff --git a/src/expr.rs b/src/expr.rs index d264f568607..bea5fab17fa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -14,15 +14,14 @@ use std::iter::{repeat, ExactSizeIterator}; use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; -use syntax::parse::classify; use spanned::Spanned; use chains::rewrite_chain; +use closures; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, FindUncommented}; use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; -use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -33,9 +32,8 @@ use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, - last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, outer_attributes, - paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr, - trimmed_last_line_width, wrap_str}; + last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead, + ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -161,7 +159,7 @@ pub fn format_expr( Some("yield".to_string()) }, ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { - rewrite_closure(capture, fn_decl, body, expr.span, context, shape) + closures::rewrite_closure(capture, fn_decl, body, expr.span, context, shape) } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | @@ -520,224 +518,6 @@ where Some(result) } -// Return type is (prefix, extra_offset) -fn rewrite_closure_fn_decl( - capture: ast::CaptureBy, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option<(String, usize)> { - let mover = if capture == ast::CaptureBy::Value { - "move " - } else { - "" - }; - // 4 = "|| {".len(), which is overconservative when the closure consists of - // a single expression. - let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?; - - // 1 = | - let argument_offset = nested_shape.indent + 1; - let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); - let ret_str = fn_decl.output.rewrite(context, arg_shape)?; - - let arg_items = itemize_list( - context.codemap, - fn_decl.inputs.iter(), - "|", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(context, arg), - |arg| arg.rewrite(context, arg_shape), - context.codemap.span_after(span, "|"), - body.span.lo(), - false, - ); - let item_vec = arg_items.collect::>(); - // 1 = space between arguments and return type. - let horizontal_budget = nested_shape - .width - .checked_sub(ret_str.len() + 1) - .unwrap_or(0); - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - horizontal_budget, - ); - let arg_shape = match tactic { - DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, - _ => arg_shape, - }; - - let fmt = ListFormatting { - tactic: tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arg_shape, - ends_with_newline: false, - preserve_newline: true, - config: context.config, - }; - let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}|{}|", mover, list_str); - - if !ret_str.is_empty() { - if prefix.contains('\n') { - prefix.push('\n'); - prefix.push_str(&argument_offset.to_string(context.config)); - } else { - prefix.push(' '); - } - prefix.push_str(&ret_str); - } - // 1 = space between `|...|` and body. - let extra_offset = last_line_width(&prefix) + 1; - - Some((prefix, extra_offset)) -} - -// This functions is pretty messy because of the rules around closures and blocks: -// FIXME - the below is probably no longer true in full. -// * if there is a return type, then there must be braces, -// * given a closure with braces, whether that is parsed to give an inner block -// or not depends on if there is a return type and if there are statements -// in that block, -// * if the first expression in the body ends with a block (i.e., is a -// statement without needing a semi-colon), then adding or removing braces -// can change whether it is treated as an expression or statement. -fn rewrite_closure( - capture: ast::CaptureBy, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - debug!("rewrite_closure {:?}", body); - - let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?; - // 1 = space between `|...|` and body. - let body_shape = shape.offset_left(extra_offset)?; - - if let ast::ExprKind::Block(ref block) = body.node { - // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return Some(format!("{} {{}}", prefix)); - } - - let no_return_type = match fn_decl.output { - ast::FunctionRetTy::Default(_) => true, - _ => false, - }; - - // Figure out if the block is necessary. - let needs_block = is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro - || block_contains_comment(block, context.codemap) - || prefix.contains('\n'); - - if no_return_type && !needs_block { - // block.stmts.len() == 1 - if let Some(expr) = stmt_expr(&block.stmts[0]) { - let result = if is_block_closure_forced(expr) { - rewrite_closure_with_block(expr, &prefix, context, shape) - } else { - rewrite_closure_expr(expr, &prefix, context, body_shape) - }; - if result.is_some() { - return result; - } - } - } - - // Either we require a block, or tried without and failed. - rewrite_closure_block(block, &prefix, context, body_shape) - } else { - rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { - // The closure originally had a non-block expression, but we can't fit on - // one line, so we'll insert a block. - rewrite_closure_with_block(body, &prefix, context, body_shape) - }) - } -} - -// Rewrite closure with a single expression wrapping its body with block. -fn rewrite_closure_with_block( - body: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - let block = ast::Block { - stmts: vec![ - ast::Stmt { - id: ast::NodeId::new(0), - node: ast::StmtKind::Expr(ptr::P(body.clone())), - span: body.span, - }, - ], - id: ast::NodeId::new(0), - rules: ast::BlockCheckMode::Default, - span: body.span, - }; - rewrite_closure_block(&block, prefix, context, shape) -} - -// Rewrite closure with a single expression without wrapping its body with block. -fn rewrite_closure_expr( - expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - let mut rewrite = expr.rewrite(context, shape); - if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { - rewrite = and_one_line(rewrite); - } - rewrite = rewrite.and_then(|rw| { - if context.config.multiline_closure_forces_block() && rw.contains('\n') { - None - } else { - Some(rw) - } - }); - rewrite.map(|rw| format!("{} {}", prefix, rw)) -} - -// Rewrite closure whose body is block. -fn rewrite_closure_block( - block: &ast::Block, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - // Start with visual indent, then fall back to block indent if the - // closure is large. - let block_threshold = context.config.closure_block_indent_threshold(); - if block_threshold >= 0 { - if let Some(block_str) = block.rewrite(context, shape) { - if block_str.matches('\n').count() <= block_threshold as usize - && !need_block_indent(&block_str, shape) - { - return Some(format!("{} {}", prefix, block_str)); - } - } - } - - // The body of the closure is big enough to be block indented, that - // means we must re-format. - let block_shape = shape.block(); - let block_str = block.rewrite(context, block_shape)?; - Some(format!("{} {}", prefix, block_str)) -} - -fn and_one_line(x: Option) -> Option { - x.and_then(|x| if x.contains('\n') { None } else { Some(x) }) -} - fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| { @@ -893,7 +673,7 @@ impl Rewrite for ast::Stmt { } // Rewrite condition if the given expression has one. -fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { +pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { match expr.node { ast::ExprKind::Match(ref cond, _) => { // `match `cond` {` @@ -1383,7 +1163,7 @@ fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option } } -fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { +pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { let snippet = codemap.span_to_snippet(block.span).unwrap(); contains_comment(&snippet) } @@ -1413,7 +1193,7 @@ pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { } } -fn is_unsafe_block(block: &ast::Block) -> bool { +pub fn is_unsafe_block(block: &ast::Block) -> bool { if let ast::BlockCheckMode::Unsafe(..) = block.rules { true } else { @@ -2071,7 +1851,7 @@ where )) } -fn need_block_indent(s: &str, shape: Shape) -> bool { +pub fn need_block_indent(s: &str, shape: Shape) -> bool { s.lines().skip(1).any(|s| { s.find(|c| !char::is_whitespace(c)) .map_or(false, |w| w + 1 < shape.indent.width()) @@ -2228,86 +2008,6 @@ fn last_arg_shape( }) } -// Rewriting closure which is placed at the end of the function call's arg. -// Returns `None` if the reformatted closure 'looks bad'. -fn rewrite_last_closure( - context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, -) -> Option { - if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node { - let body = match body.node { - ast::ExprKind::Block(ref block) if is_simple_block(block, context.codemap) => { - stmt_expr(&block.stmts[0]).unwrap_or(body) - } - _ => body, - }; - let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?; - // If the closure goes multi line before its body, do not overflow the closure. - if prefix.contains('\n') { - return None; - } - // If we are inside macro, we do not want to add or remove block from closure body. - if context.inside_macro { - return expr.rewrite(context, shape); - } - - let body_shape = shape.offset_left(extra_offset)?; - - // We force to use block for the body of the closure for certain kinds of expressions. - if is_block_closure_forced(body) { - return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( - |body_str| { - // If the expression can fit in a single line, we need not force block closure. - if body_str.lines().count() <= 7 { - match rewrite_closure_expr(body, &prefix, context, shape) { - Some(ref single_line_body_str) - if !single_line_body_str.contains('\n') => - { - Some(single_line_body_str.clone()) - } - _ => Some(body_str), - } - } else { - Some(body_str) - } - }, - ); - } - - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - let is_multi_lined_cond = rewrite_cond(context, body, body_shape) - .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) - .unwrap_or(false); - if is_multi_lined_cond { - return rewrite_closure_with_block(body, &prefix, context, body_shape); - } - - // Seems fine, just format the closure in usual manner. - return expr.rewrite(context, shape); - } - None -} - -fn is_block_closure_forced(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::If(..) | - ast::ExprKind::IfLet(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) | - ast::ExprKind::ForLoop(..) => true, - ast::ExprKind::AddrOf(_, ref expr) | - ast::ExprKind::Box(ref expr) | - ast::ExprKind::Try(ref expr) | - ast::ExprKind::Unary(_, ref expr) | - ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr), - _ => false, - } -} - fn rewrite_last_arg_with_overflow<'a, T>( context: &RewriteContext, args: &[&T], @@ -2325,10 +2025,10 @@ where ast::ExprKind::Closure(..) => { // If the argument consists of multiple closures, we do not overflow // the last closure. - if args_have_many_closure(args) { + if closures::args_have_many_closure(args) { None } else { - rewrite_last_closure(context, expr, shape) + closures::rewrite_last_closure(context, expr, shape) } } _ => expr.rewrite(context, shape), @@ -2346,23 +2046,6 @@ where } } -/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. -fn args_have_many_closure(args: &[&T]) -> bool -where - T: ToExpr, -{ - args.iter() - .filter(|arg| { - arg.to_expr() - .map(|e| match e.node { - ast::ExprKind::Closure(..) => true, - _ => false, - }) - .unwrap_or(false) - }) - .count() > 1 -} - fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool where T: Rewrite + Spanned + ToExpr + 'a, diff --git a/src/lib.rs b/src/lib.rs index 7b441c4de02..771fe785339 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,6 +59,7 @@ pub mod filemap; pub mod file_lines; pub mod visitor; mod checkstyle; +mod closures; mod items; mod missed_spans; mod lists; -- cgit 1.4.1-3-g733a5 From e6800bf27db5838144c7be7af317239af91b9b55 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Nov 2017 15:40:16 +1300 Subject: remove closure_block_indent_threshold option --- Configurations.md | 34 ---------------------- src/closures.rs | 22 +++----------- src/config.rs | 3 -- src/expr.rs | 2 +- .../configs-closure_block_indent_threshold--1.rs | 5 ---- .../configs-closure_block_indent_threshold-10.rs | 12 -------- .../configs-closure_block_indent_threshold-2.rs | 12 -------- .../configs-closure_block_indent_threshold--1.rs | 7 ----- .../configs-closure_block_indent_threshold-10.rs | 12 -------- .../configs-closure_block_indent_threshold-2.rs | 12 -------- 10 files changed, 5 insertions(+), 116 deletions(-) delete mode 100644 tests/source/configs-closure_block_indent_threshold--1.rs delete mode 100644 tests/source/configs-closure_block_indent_threshold-10.rs delete mode 100644 tests/source/configs-closure_block_indent_threshold-2.rs delete mode 100644 tests/target/configs-closure_block_indent_threshold--1.rs delete mode 100644 tests/target/configs-closure_block_indent_threshold-10.rs delete mode 100644 tests/target/configs-closure_block_indent_threshold-2.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 14ad98cb813..99f4f2dacbc 100644 --- a/Configurations.md +++ b/Configurations.md @@ -266,40 +266,6 @@ let files = fs::read_dir("tests/coverage/source") See also [`chain_width`](#chain_width). -## `closure_block_indent_threshold` - -How many lines a closure must have before it is block indented. -1 means never use block indent. - -- **Default value**: `7` -- **Possible values**: `-1`, or any positive integer - -#### Closures shorter than `closure_block_indent_threshold`: -```rust -lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - }); -``` - -#### Closures longer than `closure_block_indent_threshold`: -```rust -lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - println!("consectetur"); - println!("adipiscing"); - println!("elit"); -}); -``` - -**Note**: This option only takes effect when `fn_call_indent` is set to `"Visual"`. - ## `combine_control_expr` Combine control expressions with function calls. diff --git a/src/closures.rs b/src/closures.rs index 6eff97af295..15bfae4553b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -13,8 +13,7 @@ use syntax::codemap::Span; use syntax::parse::classify; use codemap::SpanUtils; -use expr::{block_contains_comment, is_simple_block, is_unsafe_block, need_block_indent, - rewrite_cond, ToExpr}; +use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -22,7 +21,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use utils::{last_line_width, left_most_sub_expr, stmt_expr}; -// This functions is pretty messy because of the rules around closures and blocks: +// This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. // * if there is a return type, then there must be braces, // * given a closure with braces, whether that is parsed to give an inner block @@ -31,6 +30,8 @@ use utils::{last_line_width, left_most_sub_expr, stmt_expr}; // * if the first expression in the body ends with a block (i.e., is a // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. + + pub fn rewrite_closure( capture: ast::CaptureBy, fn_decl: &ast::FnDecl, @@ -137,21 +138,6 @@ fn rewrite_closure_block( context: &RewriteContext, shape: Shape, ) -> Option { - // Start with visual indent, then fall back to block indent if the - // closure is large. - let block_threshold = context.config.closure_block_indent_threshold(); - if block_threshold >= 0 { - if let Some(block_str) = block.rewrite(context, shape) { - if block_str.matches('\n').count() <= block_threshold as usize - && !need_block_indent(&block_str, shape) - { - return Some(format!("{} {}", prefix, block_str)); - } - } - } - - // The body of the closure is big enough to be block indented, that - // means we must re-format. let block_shape = shape.block(); let block_str = block.rewrite(context, block_shape)?; Some(format!("{} {}", prefix, block_str)) diff --git a/src/config.rs b/src/config.rs index 450e016bc5a..98939e9e191 100644 --- a/src/config.rs +++ b/src/config.rs @@ -621,9 +621,6 @@ create_config! { indentation level as the match keyword"; match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, false, "Put a match sub-patterns' separator in front or back."; - closure_block_indent_threshold: isize, 7, false, - "How many lines a closure must have before it is block indented. \ - -1 means never use block indent."; space_before_type_annotation: bool, false, false, "Leave a space before the colon in a type annotation"; space_after_type_annotation_colon: bool, true, false, diff --git a/src/expr.rs b/src/expr.rs index bea5fab17fa..d6c025422af 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1851,7 +1851,7 @@ where )) } -pub fn need_block_indent(s: &str, shape: Shape) -> bool { +fn need_block_indent(s: &str, shape: Shape) -> bool { s.lines().skip(1).any(|s| { s.find(|c| !char::is_whitespace(c)) .map_or(false, |w| w + 1 < shape.indent.width()) diff --git a/tests/source/configs-closure_block_indent_threshold--1.rs b/tests/source/configs-closure_block_indent_threshold--1.rs deleted file mode 100644 index 166f825b239..00000000000 --- a/tests/source/configs-closure_block_indent_threshold--1.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-closure_block_indent_threshold: -1 - -fn issue1755() { - b.iter(|| dfkljdklgjdlkfgjdlkgjldkjfgkdjgldjfgkljdfklgjlkdjfgkljdflkgjlkdfjgdjfsas::expect("parse")); -} diff --git a/tests/source/configs-closure_block_indent_threshold-10.rs b/tests/source/configs-closure_block_indent_threshold-10.rs deleted file mode 100644 index 21b47a8d7ca..00000000000 --- a/tests/source/configs-closure_block_indent_threshold-10.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-closure_block_indent_threshold: 10 -// Closure block indent threshold - -fn main() { - lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - }); -} diff --git a/tests/source/configs-closure_block_indent_threshold-2.rs b/tests/source/configs-closure_block_indent_threshold-2.rs deleted file mode 100644 index 089ac3288ef..00000000000 --- a/tests/source/configs-closure_block_indent_threshold-2.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-closure_block_indent_threshold: 2 -// Closure block indent threshold - -fn main() { - lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - }); -} diff --git a/tests/target/configs-closure_block_indent_threshold--1.rs b/tests/target/configs-closure_block_indent_threshold--1.rs deleted file mode 100644 index 3a62e6a27ed..00000000000 --- a/tests/target/configs-closure_block_indent_threshold--1.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-closure_block_indent_threshold: -1 - -fn issue1755() { - b.iter(|| { - dfkljdklgjdlkfgjdlkgjldkjfgkdjgldjfgkljdfklgjlkdjfgkljdflkgjlkdfjgdjfsas::expect("parse") - }); -} diff --git a/tests/target/configs-closure_block_indent_threshold-10.rs b/tests/target/configs-closure_block_indent_threshold-10.rs deleted file mode 100644 index 21b47a8d7ca..00000000000 --- a/tests/target/configs-closure_block_indent_threshold-10.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-closure_block_indent_threshold: 10 -// Closure block indent threshold - -fn main() { - lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - }); -} diff --git a/tests/target/configs-closure_block_indent_threshold-2.rs b/tests/target/configs-closure_block_indent_threshold-2.rs deleted file mode 100644 index 089ac3288ef..00000000000 --- a/tests/target/configs-closure_block_indent_threshold-2.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-closure_block_indent_threshold: 2 -// Closure block indent threshold - -fn main() { - lorem_ipsum(|| { - println!("lorem"); - println!("ipsum"); - println!("dolor"); - println!("sit"); - println!("amet"); - }); -} -- cgit 1.4.1-3-g733a5 From bc6e493ce07048787fb72d2679764f7afac70c5f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Nov 2017 16:07:34 +1300 Subject: More closures refactoring --- src/closures.rs | 81 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 15bfae4553b..94129921716 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -48,37 +48,10 @@ pub fn rewrite_closure( let body_shape = shape.offset_left(extra_offset)?; if let ast::ExprKind::Block(ref block) = body.node { - // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return Some(format!("{} {{}}", prefix)); - } - - let no_return_type = match fn_decl.output { - ast::FunctionRetTy::Default(_) => true, - _ => false, - }; - - // Figure out if the block is necessary. - let needs_block = is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro - || block_contains_comment(block, context.codemap) - || prefix.contains('\n'); - - if no_return_type && !needs_block { - // block.stmts.len() == 1 - if let Some(expr) = stmt_expr(&block.stmts[0]) { - let result = if is_block_closure_forced(expr) { - rewrite_closure_with_block(expr, &prefix, context, shape) - } else { - rewrite_closure_expr(expr, &prefix, context, body_shape) - }; - if result.is_some() { - return result; - } - } - } - - // Either we require a block, or tried without and failed. - rewrite_closure_block(block, &prefix, context, body_shape) + try_rewrite_without_block(block, fn_decl, &prefix, context, shape, body_shape).or_else(|| { + // Either we require a block, or tried without and failed. + rewrite_closure_block(block, &prefix, context, body_shape) + }) } else { rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { // The closure originally had a non-block expression, but we can't fit on @@ -88,6 +61,52 @@ pub fn rewrite_closure( } } +fn try_rewrite_without_block( + block: &ast::Block, + fn_decl: &ast::FnDecl, + prefix: &str, + context: &RewriteContext, + shape: Shape, + body_shape: Shape, +) -> Option { + // The body of the closure is an empty block. + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + return Some(format!("{} {{}}", prefix)); + } + + match fn_decl.output { + ast::FunctionRetTy::Default(_) => {} + _ => return None, + } + + get_inner_expr(block, prefix, context).and_then(|expr| { + return if is_block_closure_forced(expr) { + rewrite_closure_with_block(expr, prefix, context, shape) + } else { + rewrite_closure_expr(expr, prefix, context, body_shape) + }; + }) +} + +fn get_inner_expr<'a>( + block: &'a ast::Block, + prefix: &str, + context: &RewriteContext, +) -> Option<&'a ast::Expr> { + if !needs_block(block, prefix, context) { + // block.stmts.len() == 1 + stmt_expr(&block.stmts[0]) + } else { + None + } +} + +// Figure out if a block is necessary. +fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { + is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro + || block_contains_comment(block, context.codemap) || prefix.contains('\n') +} + // Rewrite closure with a single expression wrapping its body with block. fn rewrite_closure_with_block( body: &ast::Expr, -- cgit 1.4.1-3-g733a5 From 4da9a147e196c5024e5cc4d49405d785fbfc465f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 13 Nov 2017 16:45:54 +1300 Subject: Collapse multiple blocks in closures Fixes #1524 --- src/closures.rs | 55 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 94129921716..a180e116a8b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -48,7 +48,19 @@ pub fn rewrite_closure( let body_shape = shape.offset_left(extra_offset)?; if let ast::ExprKind::Block(ref block) = body.node { - try_rewrite_without_block(block, fn_decl, &prefix, context, shape, body_shape).or_else(|| { + // The body of the closure is an empty block. + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + return Some(format!("{} {{}}", prefix)); + } + + let result = match fn_decl.output { + ast::FunctionRetTy::Default(_) => { + try_rewrite_without_block(body, &prefix, context, shape, body_shape) + } + _ => None, + }; + + result.or_else(|| { // Either we require a block, or tried without and failed. rewrite_closure_block(block, &prefix, context, body_shape) }) @@ -62,43 +74,36 @@ pub fn rewrite_closure( } fn try_rewrite_without_block( - block: &ast::Block, - fn_decl: &ast::FnDecl, + expr: &ast::Expr, prefix: &str, context: &RewriteContext, shape: Shape, body_shape: Shape, ) -> Option { - // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return Some(format!("{} {{}}", prefix)); - } + let expr = get_inner_expr(expr, prefix, context); - match fn_decl.output { - ast::FunctionRetTy::Default(_) => {} - _ => return None, + if is_block_closure_forced(expr) { + rewrite_closure_with_block(expr, prefix, context, shape) + } else { + rewrite_closure_expr(expr, prefix, context, body_shape) } - - get_inner_expr(block, prefix, context).and_then(|expr| { - return if is_block_closure_forced(expr) { - rewrite_closure_with_block(expr, prefix, context, shape) - } else { - rewrite_closure_expr(expr, prefix, context, body_shape) - }; - }) } fn get_inner_expr<'a>( - block: &'a ast::Block, + expr: &'a ast::Expr, prefix: &str, context: &RewriteContext, -) -> Option<&'a ast::Expr> { - if !needs_block(block, prefix, context) { - // block.stmts.len() == 1 - stmt_expr(&block.stmts[0]) - } else { - None +) -> &'a ast::Expr { + if let ast::ExprKind::Block(ref block) = expr.node { + if !needs_block(block, prefix, context) { + // block.stmts.len() == 1 + if let Some(expr) = stmt_expr(&block.stmts[0]) { + return get_inner_expr(expr, prefix, context); + } + } } + + expr } // Figure out if a block is necessary. -- cgit 1.4.1-3-g733a5 From 04f09c9d8548253bff2758a2b239302d574455ad Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 13 Nov 2017 16:42:29 +0900 Subject: Replace '*_indent' with 'indent_style' in src --- src/chains.rs | 18 +++++++++--------- src/config.rs | 17 +---------------- src/expr.rs | 50 +++++++++++++++++++++++++------------------------- src/items.rs | 44 ++++++++++++++++++++++---------------------- src/lists.rs | 6 +++--- src/rewrite.rs | 2 +- src/types.rs | 14 +++++++------- 7 files changed, 68 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5ab538c8c4e..1a3586cd044 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -87,7 +87,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent, "\n") { - match context.config.chain_indent() { + match context.config.indent_style() { IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape, } @@ -105,10 +105,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { ( chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.chain_indent() == IndentStyle::Visual || is_small_parent, + context.config.indent_style() == IndentStyle::Visual || is_small_parent, ) } else if is_block_expr(context, &parent, &parent_rewrite) { - match context.config.chain_indent() { + match context.config.indent_style() { // Try to put the first child on the same line with parent's last line IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), // The parent is a block, so align the rest of the chain with the closing @@ -127,7 +127,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_child_shape = if extend { let overhead = last_line_width(&parent_rewrite); let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; - match context.config.chain_indent() { + match context.config.indent_style() { IndentStyle::Visual => parent_shape.offset_left(overhead)?, IndentStyle::Block => parent_shape.block().offset_left(offset)?, } @@ -172,7 +172,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { other_child_shape }; - match context.config.chain_indent() { + match context.config.indent_style() { IndentStyle::Visual => last_shape.sub_width(shape.rhs_overhead(context.config))?, IndentStyle::Block => last_shape, } @@ -262,7 +262,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_connector = if is_small_parent || fits_single_line || last_line_extendable(&parent_rewrite) - || context.config.chain_indent() == IndentStyle::Visual + || context.config.indent_style() == IndentStyle::Visual { "" } else { @@ -272,7 +272,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let result = if is_small_parent && rewrites.len() > 1 { let second_connector = if fits_single_line || rewrites[1] == "?" || last_line_extendable(&rewrites[0]) - || context.config.chain_indent() == IndentStyle::Visual + || context.config.indent_style() == IndentStyle::Visual { "" } else { @@ -295,7 +295,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ) }; let result = format!("{}{}", result, repeat_try(suffix_try_num)); - if context.config.chain_indent() == IndentStyle::Visual { + if context.config.indent_style() == IndentStyle::Visual { wrap_str(result, context.config.max_width(), shape) } else { Some(result) @@ -381,7 +381,7 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, } fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.chain_indent() { + match context.config.indent_style() { IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape .block_indent(context.config.tab_spaces()) diff --git a/src/config.rs b/src/config.rs index 98939e9e191..b946d006a0b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -40,11 +40,6 @@ macro_rules! configuration_option_enum{ } } -configuration_option_enum! { Style: - Rfc, // Follow the style RFCs style. - Legacy, // Follow the traditional Rustfmt style. -} - configuration_option_enum! { NewlineStyle: Windows, // \r\n Unix, // \n @@ -521,6 +516,7 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { create_config! { + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; unstable_features: bool, false, true, "Enables unstable features. Only available on nightly channel"; verbose: bool, false, false, "Use verbose output"; @@ -545,7 +541,6 @@ create_config! { fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for functions"; item_brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for structs and enums"; - control_style: Style, Style::Rfc, false, "Indent style for control flow statements"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; @@ -559,16 +554,12 @@ create_config! { "Location of return type in function declaration"; fn_args_paren_newline: bool, false, false, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; - fn_args_indent: IndentStyle, IndentStyle::Block, false, - "Layout of function arguments and tuple structs"; - array_indent: IndentStyle, IndentStyle::Block, false, "Indent on arrays"; array_width: usize, 60, false, "Maximum width of an array literal before falling back to vertical formatting"; array_horizontal_layout_threshold: usize, 0, false, "How many elements array must have before rustfmt uses horizontal layout."; type_punctuation_density: TypeDensity, TypeDensity::Wide, false, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - where_style: Style, Style::Rfc, false, "Overall strategy for where clauses"; // TODO: // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? @@ -576,18 +567,12 @@ create_config! { where_density: Density, Density::Vertical, false, "Density of a where clause"; where_single_line: bool, false, false, "To force single line where layout"; where_layout: ListTactic, ListTactic::Vertical, false, "Element layout inside a where clause"; - where_pred_indent: IndentStyle, IndentStyle::Visual, false, - "Indentation style of a where predicate"; - generics_indent: IndentStyle, IndentStyle::Block, false, "Indentation of generics"; - struct_lit_indent: IndentStyle, IndentStyle::Block, false, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, false, "Multiline style on literal structs"; - fn_call_indent: IndentStyle, IndentStyle::Block, false, "Indentation for function calls, etc."; report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; - chain_indent: IndentStyle, IndentStyle::Block, false, "Indentation of chain"; chain_width: usize, 60, false, "Maximum length of a chain to fit on a single line"; chain_split_single_child: bool, false, false, "Split a chain with a single child if its length \ exceeds `chain_width`"; diff --git a/src/expr.rs b/src/expr.rs index d6c025422af..5aee87dbbb7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -21,7 +21,7 @@ use closures; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, FindUncommented}; -use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style}; +use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -366,11 +366,11 @@ where // We have to use multiple lines. // Re-evaluate the rhs because we have more space now: - let mut rhs_shape = match context.config.control_style() { - Style::Legacy => shape + let mut rhs_shape = match context.config.indent_style() { + IndentStyle::Visual => shape .sub_width(pp.suffix.len() + pp.prefix.len())? .visual_indent(pp.prefix.len()), - Style::Rfc => { + IndentStyle::Block => { // Try to calculate the initial constraint on the right hand side. let rhs_overhead = shape.rhs_overhead(context.config); Shape::indented(shape.indent.block_indent(context.config), context.config) @@ -415,7 +415,7 @@ where 1 // "[" }; - let nested_shape = match context.config.array_indent() { + let nested_shape = match context.config.indent_style() { IndentStyle::Block => shape .block() .block_indent(context.config.tab_spaces()) @@ -450,7 +450,7 @@ where .iter() .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - let mut tactic = match context.config.array_indent() { + let mut tactic = match context.config.indent_style() { IndentStyle::Block => { // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { @@ -473,7 +473,7 @@ where DefinitiveListTactic::Mixed }, }; - let ends_with_newline = tactic.ends_with_newline(context.config.array_indent()); + let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); if context.config.array_horizontal_layout_threshold() > 0 && items.len() > context.config.array_horizontal_layout_threshold() { @@ -485,7 +485,7 @@ where separator: ",", trailing_separator: if trailing_comma { SeparatorTactic::Always - } else if context.inside_macro || context.config.array_indent() == IndentStyle::Visual { + } else if context.inside_macro || context.config.indent_style() == IndentStyle::Visual { SeparatorTactic::Never } else { SeparatorTactic::Vertical @@ -498,7 +498,7 @@ where }; let list_str = write_list(&items, &fmt)?; - let result = if context.config.array_indent() == IndentStyle::Visual + let result = if context.config.indent_style() == IndentStyle::Visual || tactic == DefinitiveListTactic::Horizontal { if context.config.spaces_within_square_brackets() && !list_str.is_empty() { @@ -677,9 +677,9 @@ pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> match expr.node { ast::ExprKind::Match(ref cond, _) => { // `match `cond` {` - let cond_shape = match context.config.control_style() { - Style::Legacy => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, - Style::Rfc => shape.offset_left(8)?, + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, + IndentStyle::Block => shape.offset_left(8)?, }; cond.rewrite(context, cond_shape) } @@ -922,9 +922,9 @@ impl<'a> ControlFlow<'a> { let pat_expr_string = match self.cond { Some(cond) => { - let cond_shape = match context.config.control_style() { - Style::Legacy => constr_shape.shrink_left(offset)?, - Style::Rfc => constr_shape.offset_left(offset)?, + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => constr_shape.shrink_left(offset)?, + IndentStyle::Block => constr_shape.offset_left(offset)?, }; rewrite_pat_expr( context, @@ -951,7 +951,7 @@ impl<'a> ControlFlow<'a> { .max_width() .checked_sub(constr_shape.used_width() + offset + brace_overhead) .unwrap_or(0); - let force_newline_brace = context.config.control_style() == Style::Rfc + let force_newline_brace = context.config.indent_style() == IndentStyle::Block && (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) && !last_line_extendable(&pat_expr_string); @@ -1236,9 +1236,9 @@ fn rewrite_match( ..shape }; // 6 = `match ` - let cond_shape = match context.config.control_style() { - Style::Legacy => cond_shape.shrink_left(6)?, - Style::Rfc => cond_shape.offset_left(6)?, + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => cond_shape.shrink_left(6)?, + IndentStyle::Block => cond_shape.offset_left(6)?, }; let cond_str = cond.rewrite(context, cond_shape)?; let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); @@ -1809,7 +1809,7 @@ where let used_width = extra_offset(callee_str, shape); let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; - let nested_shape = shape_from_fn_call_indent( + let nested_shape = shape_from_indent_style( context, shape, used_width + 2 * paren_overhead, @@ -2058,7 +2058,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l match expr.node { ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) - || (context.config.fn_call_indent() == IndentStyle::Visual && args_len > 1) + || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | @@ -2070,7 +2070,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l } ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { context.use_block_indent() - || context.config.fn_call_indent() == IndentStyle::Visual && args_len > 1 + || context.config.indent_style() == IndentStyle::Visual && args_len > 1 } ast::ExprKind::Array(..) | ast::ExprKind::Call(..) | @@ -2319,7 +2319,7 @@ fn rewrite_struct_lit<'a>( let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); Some(format!("{} {{{}}}", path_str, fields_str)) - // FIXME if context.config.struct_lit_indent() == Visual, but we run out + // FIXME if context.config.indent_style() == Visual, but we run out // of space, we should fall back to BlockIndent. } @@ -2330,7 +2330,7 @@ pub fn wrap_struct_field( nested_shape: Shape, one_line_width: usize, ) -> String { - if context.config.struct_lit_indent() == IndentStyle::Block + if context.config.indent_style() == IndentStyle::Block && (fields_str.contains('\n') || context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti || fields_str.len() > one_line_width) @@ -2401,7 +2401,7 @@ pub fn rewrite_field( } } -fn shape_from_fn_call_indent( +fn shape_from_indent_style( context: &RewriteContext, shape: Shape, overhead: usize, diff --git a/src/items.rs b/src/items.rs index de0dc763e1b..d5e02dde6e5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; -use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent, Style}; +use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, @@ -815,9 +815,9 @@ fn format_impl_ref_and_type( result.push_str("for "); } let budget = context.budget(last_line_width(&result)); - let type_offset = match context.config.where_style() { - Style::Legacy => new_line_offset + trait_ref_overhead, - Style::Rfc => new_line_offset, + let type_offset = match context.config.indent_style() { + IndentStyle::Visual => new_line_offset + trait_ref_overhead, + IndentStyle::Block => new_line_offset, }; result.push_str(&*self_ty .rewrite(context, Shape::legacy(budget, type_offset))?); @@ -974,8 +974,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let has_body = !trait_items.is_empty(); let where_density = if (context.config.where_density() == Density::Compressed - && (!result.contains('\n') || context.config.fn_args_indent() == IndentStyle::Block)) - || (context.config.fn_args_indent() == IndentStyle::Block && result.is_empty()) + && (!result.contains('\n') || context.config.indent_style() == IndentStyle::Block)) + || (context.config.indent_style() == IndentStyle::Block && result.is_empty()) || (context.config.where_density() == Density::CompressedIfEmpty && !has_body && !result.contains('\n')) { @@ -1880,13 +1880,13 @@ fn rewrite_fn_base( } else if context.config.fn_args_paren_newline() { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); - if context.config.fn_args_indent() == IndentStyle::Visual { + if context.config.indent_style() == IndentStyle::Visual { arg_indent = arg_indent + 1; // extra space for `(` } result.push('('); } else { result.push_str("("); - if context.config.fn_args_indent() == IndentStyle::Visual { + if context.config.indent_style() == IndentStyle::Visual { result.push('\n'); result.push_str(&arg_indent.to_string(context.config)); } @@ -1933,7 +1933,7 @@ fn rewrite_fn_base( generics_str.contains('\n'), )?; - let put_args_in_block = match context.config.fn_args_indent() { + let put_args_in_block = match context.config.indent_style() { IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, _ => false, } && !fd.inputs.is_empty(); @@ -1974,7 +1974,7 @@ fn rewrite_fn_base( // Return type. if let ast::FunctionRetTy::Ty(..) = fd.output { - let ret_should_indent = match context.config.fn_args_indent() { + let ret_should_indent = match context.config.indent_style() { // If our args are block layout then we surely must have space. IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, _ if args_last_line_contains_comment => false, @@ -2266,7 +2266,7 @@ fn rewrite_args( .and_then(|item| item.post_comment.as_ref()) .map_or(false, |s| s.trim().starts_with("//")); - let (indent, trailing_comma) = match context.config.fn_args_indent() { + let (indent, trailing_comma) = match context.config.indent_style() { IndentStyle::Block if fits_in_one_line => { (indent.block_indent(context.config), SeparatorTactic::Never) } @@ -2303,7 +2303,7 @@ fn rewrite_args( }, separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, indent), - ends_with_newline: tactic.ends_with_newline(context.config.fn_args_indent()), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, config: context.config, }; @@ -2353,7 +2353,7 @@ fn compute_budgets_for_args( if one_line_budget > 0 { // 4 = "() {".len() - let (indent, multi_line_budget) = match context.config.fn_args_indent() { + let (indent, multi_line_budget) = match context.config.indent_style() { IndentStyle::Block => { let indent = indent.block_indent(context.config); (indent, context.budget(indent.width() + 1)) @@ -2371,7 +2371,7 @@ fn compute_budgets_for_args( // Didn't work. we must force vertical layout and put args on a newline. let new_indent = indent.block_indent(context.config); - let used_space = match context.config.fn_args_indent() { + let used_space = match context.config.indent_style() { // 1 = `,` IndentStyle::Block => new_indent.width() + 1, // Account for `)` and possibly ` {`. @@ -2464,7 +2464,7 @@ fn rewrite_generics_inner( } pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { - match config.generics_indent() { + match config.indent_style() { IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), IndentStyle::Block => { // 1 = "," @@ -2497,14 +2497,14 @@ where let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: if context.config.generics_indent() == IndentStyle::Visual { + trailing_separator: if context.config.indent_style() == IndentStyle::Visual { SeparatorTactic::Never } else { context.config.trailing_comma() }, separator_place: SeparatorPlace::Back, shape: shape, - ends_with_newline: tactic.ends_with_newline(context.config.generics_indent()), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, config: context.config, }; @@ -2523,7 +2523,7 @@ pub fn wrap_generics_with_angle_brackets( list_str: &str, list_offset: Indent, ) -> String { - if context.config.generics_indent() == IndentStyle::Block + if context.config.indent_style() == IndentStyle::Block && (list_str.contains('\n') || list_str.ends_with(',')) { format!( @@ -2674,7 +2674,7 @@ fn rewrite_where_clause( return Some(String::new()); } - if context.config.where_style() == Style::Rfc { + if context.config.indent_style() == IndentStyle::Block { return rewrite_where_clause_rfc_style( context, where_clause, @@ -2689,12 +2689,12 @@ fn rewrite_where_clause( let extra_indent = Indent::new(context.config.tab_spaces(), 0); - let offset = match context.config.where_pred_indent() { + let offset = match context.config.indent_style() { IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), // 6 = "where ".len() IndentStyle::Visual => shape.indent + extra_indent + 6, }; - // FIXME: if where_pred_indent != Visual, then the budgets below might + // FIXME: if indent_style != Visual, then the budgets below might // be out by a char or two. let budget = context.config.max_width() - offset.width(); @@ -2737,7 +2737,7 @@ fn rewrite_where_clause( trailing_separator: comma_tactic, separator_place: SeparatorPlace::Back, shape: Shape::legacy(budget, offset), - ends_with_newline: tactic.ends_with_newline(context.config.where_pred_indent()), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, config: context.config, }; diff --git a/src/lists.rs b/src/lists.rs index d560c88886c..d7098d3a397 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -737,7 +737,7 @@ pub fn struct_lit_shape( prefix_width: usize, suffix_width: usize, ) -> Option<(Option, Shape)> { - let v_shape = match context.config.struct_lit_indent() { + let v_shape = match context.config.indent_style() { IndentStyle::Visual => shape .visual_indent(0) .shrink_left(prefix_width)? @@ -766,7 +766,7 @@ pub fn struct_lit_tactic( items: &[ListItem], ) -> DefinitiveListTactic { if let Some(h_shape) = h_shape { - let prelim_tactic = match (context.config.struct_lit_indent(), items.len()) { + let prelim_tactic = match (context.config.indent_style(), items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, _ => context.config.struct_lit_multiline_style().to_list_tactic(), }; @@ -797,7 +797,7 @@ pub fn struct_lit_formatting<'a>( context: &'a RewriteContext, force_no_trailing_comma: bool, ) -> ListFormatting<'a> { - let ends_with_newline = context.config.struct_lit_indent() != IndentStyle::Visual + let ends_with_newline = context.config.indent_style() != IndentStyle::Visual && tactic == DefinitiveListTactic::Vertical; ListFormatting { tactic: tactic, diff --git a/src/rewrite.rs b/src/rewrite.rs index 823f69dc6ff..1307f6731ff 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -43,7 +43,7 @@ impl<'a> RewriteContext<'a> { /// Return true if we should use block indent style for rewriting function call. pub fn use_block_indent(&self) -> bool { - self.config.fn_call_indent() == IndentStyle::Block || self.use_block + self.config.indent_style() == IndentStyle::Block || self.use_block } pub fn budget(&self, used_width: usize) -> usize { diff --git a/src/types.rs b/src/types.rs index 59b4ac438b0..d2e782db1aa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,7 +18,7 @@ use syntax::symbol::keywords; use spanned::Spanned; use codemap::SpanUtils; -use config::{IndentStyle, Style, TypeDensity}; +use config::{IndentStyle, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; use items::{format_generics_item_list, generics_shape_from_config}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, @@ -302,7 +302,7 @@ where // 2 for () let budget = shape.width.checked_sub(2)?; // 1 for ( - let offset = match context.config.fn_args_indent() { + let offset = match context.config.indent_style() { IndentStyle::Block => { shape .block() @@ -357,14 +357,14 @@ where }, separator_place: SeparatorPlace::Back, shape: list_shape, - ends_with_newline: tactic.ends_with_newline(context.config.fn_call_indent()), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, config: context.config, }; let list_str = write_list(&item_vec, &fmt)?; - let ty_shape = match context.config.fn_args_indent() { + let ty_shape = match context.config.indent_style() { IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), IndentStyle::Visual => shape.block_left(4)?, }; @@ -447,9 +447,9 @@ impl Rewrite for ast::WherePredicate { } } else { let used_width = type_str.len() + colon.len(); - let ty_shape = match context.config.where_style() { - Style::Legacy => shape.block_left(used_width)?, - Style::Rfc => shape, + let ty_shape = match context.config.indent_style() { + IndentStyle::Visual => shape.block_left(used_width)?, + IndentStyle::Block => shape, }; let bounds = bounds .iter() -- cgit 1.4.1-3-g733a5 From d2f2f2546358f60c22da98918535cd932589de5c Mon Sep 17 00:00:00 2001 From: clippered Date: Fri, 10 Nov 2017 07:23:12 +1100 Subject: add cli option for color --- src/bin/rustfmt.rs | 20 +++++++++++++++++++- src/config.rs | 11 +++++++++++ src/filemap.rs | 8 +++++--- src/lib.rs | 5 +++-- src/rustfmt_diff.rs | 7 ++++--- src/utils.rs | 9 +++++++++ tests/system.rs | 10 ++++++---- 7 files changed, 57 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index f0e4f0a7897..fd9f9021484 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -25,7 +25,7 @@ use getopts::{HasArg, Matches, Occur, Options}; use rustfmt::{run, Input, Summary}; use rustfmt::file_lines::FileLines; -use rustfmt::config::{get_toml_path, Config, WriteMode}; +use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; type FmtError = Box; type FmtResult = std::result::Result; @@ -59,6 +59,7 @@ struct CliOptions { skip_children: bool, verbose: bool, write_mode: Option, + color: Option, file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, } @@ -90,6 +91,14 @@ impl CliOptions { } } + if let Some(ref color) = matches.opt_str("color") { + if let Ok(color) = Color::from_str(color) { + options.color = Some(color); + } else { + return Err(FmtError::from(format!("Invalid color: {}", color))); + } + } + if let Some(ref file_lines) = matches.opt_str("file-lines") { options.file_lines = file_lines.parse()?; } @@ -105,6 +114,9 @@ impl CliOptions { if let Some(write_mode) = self.write_mode { config.set().write_mode(write_mode); } + if let Some(color) = self.color { + config.set().color(color); + } } } @@ -131,6 +143,12 @@ fn make_opts() -> Options { "how to write output (not usable when piping from stdin)", "[replace|overwrite|display|plain|diff|coverage|checkstyle]", ); + opts.optopt( + "", + "color", + "use colored output (if supported)", + "[always|never|auto]", + ); opts.optflag("", "skip-children", "don't reformat child modules"); opts.optflag( diff --git a/src/config.rs b/src/config.rs index 98939e9e191..430402d2784 100644 --- a/src/config.rs +++ b/src/config.rs @@ -152,6 +152,15 @@ configuration_option_enum! { WriteMode: Checkstyle, } +configuration_option_enum! { Color: + // Always use color, whether it is a piped or terminal output + Always, + // Never use color + Never, + // Automatically use color, if supported by terminal + Auto, +} + /// Trait for types that can be used in `Config`. pub trait ConfigType: Sized { /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a @@ -643,6 +652,8 @@ create_config! { write_mode: WriteMode, WriteMode::Overwrite, false, "What Write Mode to use when none is supplied: \ Replace, Overwrite, Display, Plain, Diff, Coverage"; + color: Color, Color::Auto, false, + "What Color option to use when none is supplied: Always, Never, Auto"; condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ in tuple patterns"; combine_control_expr: bool, true, false, "Combine control expressions with function calls."; diff --git a/src/filemap.rs b/src/filemap.rs index 72724da1c11..5942934d877 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -152,9 +152,11 @@ where if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { let mismatch = make_diff(&ori, &fmt, 3); let has_diff = !mismatch.is_empty(); - print_diff(mismatch, |line_num| { - format!("Diff in {} at line {}:", filename, line_num) - }); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename, line_num), + config.color(), + ); return Ok(has_diff); } } diff --git a/src/lib.rs b/src/lib.rs index 771fe785339..dfdf4b5143f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,7 @@ use checkstyle::{output_footer, output_header}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; -use utils::isatty; +use utils::iscolored; use visitor::FmtVisitor; pub use self::summary::Summary; @@ -581,7 +581,8 @@ pub fn run(input: Input, config: &Config) -> Summary { if report.has_warnings() { match term::stderr() { Some(ref t) - if isatty() && t.supports_color() && t.supports_attr(term::Attr::Bold) => + if iscolored(config.color()) && t.supports_color() + && t.supports_attr(term::Attr::Bold) => { match report.print_warnings_fancy(term::stderr().unwrap()) { Ok(..) => (), diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c0aca68fe2f..858fb876f6e 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use config::Color; use diff; use std::collections::VecDeque; use std::io; use term; -use utils::isatty; +use utils::iscolored; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -96,12 +97,12 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F) +pub fn print_diff(diff: Vec, get_section_title: F, color: Color) where F: Fn(u32) -> String, { match term::stdout() { - Some(ref t) if isatty() && t.supports_color() => { + Some(ref t) if iscolored(color) && t.supports_color() => { print_diff_fancy(diff, get_section_title, term::stdout().unwrap()) } _ => print_diff_basic(diff, get_section_title), diff --git a/src/utils.rs b/src/utils.rs index 999ba9f67b9..68fca8789d3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,6 +15,7 @@ use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMet NestedMetaItemKind, Path, Visibility}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; +use config::Color; use rewrite::RewriteContext; use shape::Shape; @@ -484,6 +485,14 @@ pub fn isatty() -> bool { } } +pub fn iscolored(color: Color) -> bool { + match color { + Color::Always => true, + Color::Never => false, + Color::Auto => isatty(), + } +} + pub fn starts_with_newline(s: &str) -> bool { s.starts_with('\n') || s.starts_with("\r\n") } diff --git a/tests/system.rs b/tests/system.rs index 29332881c2f..aaf287ea7aa 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -23,7 +23,7 @@ use std::str::Chars; use rustfmt::*; use rustfmt::filemap::{write_system_newlines, FileMap}; -use rustfmt::config::{Config, ReportTactic}; +use rustfmt::config::{Color, Config, ReportTactic}; use rustfmt::rustfmt_diff::*; const DIFF_CONTEXT_SIZE: usize = 3; @@ -229,9 +229,11 @@ fn print_mismatches(result: HashMap>) { let mut t = term::stdout().unwrap(); for (file_name, diff) in result { - print_diff(diff, |line_num| { - format!("\nMismatch at {}:{}:", file_name, line_num) - }); + print_diff( + diff, + |line_num| format!("\nMismatch at {}:{}:", file_name, line_num), + Color::Auto, + ); } t.reset().unwrap(); -- cgit 1.4.1-3-g733a5 From 794a215b27688426b926529fc499f535e63eb40c Mon Sep 17 00:00:00 2001 From: clippered Date: Mon, 13 Nov 2017 20:10:46 +1100 Subject: rename to use_colored_tty; used match as well --- src/bin/rustfmt.rs | 7 +++---- src/lib.rs | 4 ++-- src/rustfmt_diff.rs | 4 ++-- src/utils.rs | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index fd9f9021484..4a041144789 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -92,10 +92,9 @@ impl CliOptions { } if let Some(ref color) = matches.opt_str("color") { - if let Ok(color) = Color::from_str(color) { - options.color = Some(color); - } else { - return Err(FmtError::from(format!("Invalid color: {}", color))); + match Color::from_str(color) { + Ok(color) => options.color = Some(color), + _ => return Err(FmtError::from(format!("Invalid color: {}", color))), } } diff --git a/src/lib.rs b/src/lib.rs index dfdf4b5143f..1eec30833b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,7 @@ use checkstyle::{output_footer, output_header}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; -use utils::iscolored; +use utils::use_colored_tty; use visitor::FmtVisitor; pub use self::summary::Summary; @@ -581,7 +581,7 @@ pub fn run(input: Input, config: &Config) -> Summary { if report.has_warnings() { match term::stderr() { Some(ref t) - if iscolored(config.color()) && t.supports_color() + if use_colored_tty(config.color()) && t.supports_color() && t.supports_attr(term::Attr::Bold) => { match report.print_warnings_fancy(term::stderr().unwrap()) { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 858fb876f6e..daad73dc6ab 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -13,7 +13,7 @@ use diff; use std::collections::VecDeque; use std::io; use term; -use utils::iscolored; +use utils::use_colored_tty; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -102,7 +102,7 @@ where F: Fn(u32) -> String, { match term::stdout() { - Some(ref t) if iscolored(color) && t.supports_color() => { + Some(ref t) if use_colored_tty(color) && t.supports_color() => { print_diff_fancy(diff, get_section_title, term::stdout().unwrap()) } _ => print_diff_basic(diff, get_section_title), diff --git a/src/utils.rs b/src/utils.rs index 68fca8789d3..b87e2eaf493 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -485,7 +485,7 @@ pub fn isatty() -> bool { } } -pub fn iscolored(color: Color) -> bool { +pub fn use_colored_tty(color: Color) -> bool { match color { Color::Always => true, Color::Never => false, -- cgit 1.4.1-3-g733a5 From f8074b340d328513077b59084e0ea3856181e699 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 14 Nov 2017 10:47:02 +0900 Subject: Combine fn_brace_style and item_brace_style --- src/config.rs | 4 +-- src/items.rs | 31 +++++++++++----------- src/visitor.rs | 2 +- tests/config/small_tabs.toml | 2 +- .../configs-fn_brace_style-always_next_line.rs | 2 +- .../configs-fn_brace_style-prefer_same_line.rs | 2 +- .../configs-fn_brace_style-same_line_where.rs | 2 +- .../configs-item_brace_style-always_next_line.rs | 2 +- .../configs-item_brace_style-prefer_same_line.rs | 2 +- .../configs-item_brace_style-same_line_where.rs | 2 +- tests/source/fn-custom-6.rs | 2 +- tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom-8.rs | 2 +- tests/source/item-brace-style-always-next-line.rs | 2 +- tests/source/item-brace-style-prefer-same-line.rs | 2 +- tests/source/item-brace-style-same-line-where.rs | 2 +- .../configs-fn_brace_style-always_next_line.rs | 2 +- .../configs-fn_brace_style-prefer_same_line.rs | 2 +- .../configs-fn_brace_style-same_line_where.rs | 2 +- .../configs-item_brace_style-always_next_line.rs | 6 +++-- .../configs-item_brace_style-prefer_same_line.rs | 2 +- .../configs-item_brace_style-same_line_where.rs | 2 +- tests/target/fn-custom-6.rs | 2 +- tests/target/fn-custom-7.rs | 5 ++-- tests/target/fn-custom-8.rs | 2 +- tests/target/indented-impl.rs | 5 ++-- tests/target/item-brace-style-always-next-line.rs | 2 +- tests/target/item-brace-style-prefer-same-line.rs | 2 +- tests/target/item-brace-style-same-line-where.rs | 2 +- 29 files changed, 50 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index b946d006a0b..232e8ed8129 100644 --- a/src/config.rs +++ b/src/config.rs @@ -538,9 +538,7 @@ create_config! { "Maximum width in the body of a struct variant before falling back to vertical formatting"; force_explicit_abi: bool, true, false, "Always print the abi for extern items"; newline_style: NewlineStyle, NewlineStyle::Unix, false, "Unix or Windows line endings"; - fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for functions"; - item_brace_style: BraceStyle, BraceStyle::SameLineWhere, false, - "Brace style for structs and enums"; + brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; diff --git a/src/items.rs b/src/items.rs index d5e02dde6e5..cd3cb48c4db 100644 --- a/src/items.rs +++ b/src/items.rs @@ -314,7 +314,7 @@ impl<'a> FmtVisitor<'a> { rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; // 2 = ` {` - if self.config.fn_brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace + if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace || last_line_width(&result) + 2 > self.shape().width { newline_brace = true; @@ -440,7 +440,7 @@ impl<'a> FmtVisitor<'a> { let generics_str = format_generics( &self.get_context(), generics, - self.config.item_brace_style(), + self.config.brace_style(), if enum_def.variants.is_empty() { BracePos::ForceSameLine } else { @@ -595,7 +595,7 @@ pub fn format_impl( let where_clause_str = rewrite_where_clause( context, &generics.where_clause, - context.config.item_brace_style(), + context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), context.config.where_density(), "{", @@ -641,7 +641,7 @@ pub fn format_impl( } result.push_str(&where_clause_str); - match context.config.item_brace_style() { + match context.config.brace_style() { _ if last_line_contains_single_line_comment(&result) => result.push_str(&sep), BraceStyle::AlwaysNextLine => result.push_str(&sep), BraceStyle::PreferSameLine => result.push(' '), @@ -784,7 +784,7 @@ fn format_impl_ref_and_type( let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { // If there is no where clause adapt budget for type formatting to take space and curly // brace into account. - match context.config.item_brace_style() { + match context.config.brace_style() { BraceStyle::AlwaysNextLine => 0, _ => 2, } @@ -994,7 +994,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let where_clause_str = rewrite_where_clause( context, &generics.where_clause, - context.config.item_brace_style(), + context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), where_density, "{", @@ -1038,7 +1038,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } - match context.config.item_brace_style() { + match context.config.brace_style() { _ if last_line_contains_single_line_comment(&result) => { result.push('\n'); result.push_str(&offset.to_string(context.config)); @@ -1103,7 +1103,7 @@ fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) format_generics( context, generics, - context.config.item_brace_style(), + context.config.brace_style(), BracePos::None, offset, mk_sp(generics.span.lo(), hi), @@ -1135,7 +1135,7 @@ pub fn format_struct_struct( Some(g) => format_generics( context, g, - context.config.item_brace_style(), + context.config.brace_style(), if fields.is_empty() { BracePos::ForceSameLine } else { @@ -1148,8 +1148,7 @@ pub fn format_struct_struct( None => { // 3 = ` {}`, 2 = ` {`. let overhead = if fields.is_empty() { 3 } else { 2 }; - if (context.config.item_brace_style() == BraceStyle::AlwaysNextLine - && !fields.is_empty()) + if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty()) || context.config.max_width() < overhead + result.len() { format!("\n{}{{", offset.block_only().to_string(context.config)) @@ -1279,7 +1278,7 @@ fn format_tuple_struct( rewrite_where_clause( context, &generics.where_clause, - context.config.item_brace_style(), + context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), Density::Compressed, ";", @@ -1365,7 +1364,7 @@ pub fn rewrite_type_alias( let where_clause_str = rewrite_where_clause( context, &generics.where_clause, - context.config.item_brace_style(), + context.config.brace_style(), Shape::legacy(where_budget, indent), context.config.where_density(), "=", @@ -2071,7 +2070,7 @@ fn rewrite_fn_base( if let Some(where_clause_str) = rewrite_where_clause( context, where_clause, - context.config.fn_brace_style(), + context.config.brace_style(), Shape::legacy(budget, indent), Density::Compressed, "{", @@ -2090,7 +2089,7 @@ fn rewrite_fn_base( let where_clause_str = rewrite_where_clause( context, where_clause, - context.config.fn_brace_style(), + context.config.brace_style(), Shape::indented(indent, context.config), Density::Tall, "{", @@ -2386,7 +2385,7 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: if config.where_single_line() && predicate_count == 1 { return false; } - match (config.fn_brace_style(), config.where_density()) { + match (config.brace_style(), config.where_density()) { (BraceStyle::AlwaysNextLine, _) => true, (_, Density::Compressed) if predicate_count == 1 => false, (_, Density::CompressedIfEmpty) if predicate_count == 1 && !has_body => false, diff --git a/src/visitor.rs b/src/visitor.rs index b69edfda0c6..159f73452bd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -666,7 +666,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.push_str(&ident.to_string()); if is_internal { - match self.config.item_brace_style() { + match self.config.brace_style() { BraceStyle::AlwaysNextLine => self.buffer .push_str(&format!("\n{}{{", self.block_indent.to_string(self.config))), _ => self.buffer.push_str(" {"), diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 264591bc400..298094a7bc9 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -2,7 +2,7 @@ max_width = 100 comment_width = 80 tab_spaces = 2 newline_style = "Unix" -fn_brace_style = "SameLineWhere" +brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" diff --git a/tests/source/configs-fn_brace_style-always_next_line.rs b/tests/source/configs-fn_brace_style-always_next_line.rs index 9e1a6048a5a..d3bd9ac09aa 100644 --- a/tests/source/configs-fn_brace_style-always_next_line.rs +++ b/tests/source/configs-fn_brace_style-always_next_line.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine // Function brace style fn lorem() { diff --git a/tests/source/configs-fn_brace_style-prefer_same_line.rs b/tests/source/configs-fn_brace_style-prefer_same_line.rs index 2bca0f44618..78a4495243d 100644 --- a/tests/source/configs-fn_brace_style-prefer_same_line.rs +++ b/tests/source/configs-fn_brace_style-prefer_same_line.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Function brace style fn lorem() { diff --git a/tests/source/configs-fn_brace_style-same_line_where.rs b/tests/source/configs-fn_brace_style-same_line_where.rs index 7213634fdc4..3b78932e177 100644 --- a/tests/source/configs-fn_brace_style-same_line_where.rs +++ b/tests/source/configs-fn_brace_style-same_line_where.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_brace_style: SameLineWhere +// rustfmt-brace_style: SameLineWhere // Function brace style fn lorem() { diff --git a/tests/source/configs-item_brace_style-always_next_line.rs b/tests/source/configs-item_brace_style-always_next_line.rs index b85d64b9e94..0cc19b34da7 100644 --- a/tests/source/configs-item_brace_style-always_next_line.rs +++ b/tests/source/configs-item_brace_style-always_next_line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine // Item brace style enum Foo {} diff --git a/tests/source/configs-item_brace_style-prefer_same_line.rs b/tests/source/configs-item_brace_style-prefer_same_line.rs index a67f7e6478e..4412bc869a2 100644 --- a/tests/source/configs-item_brace_style-prefer_same_line.rs +++ b/tests/source/configs-item_brace_style-prefer_same_line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Item brace style struct Lorem { diff --git a/tests/source/configs-item_brace_style-same_line_where.rs b/tests/source/configs-item_brace_style-same_line_where.rs index 11d4015d4c9..b8e69147dc5 100644 --- a/tests/source/configs-item_brace_style-same_line_where.rs +++ b/tests/source/configs-item_brace_style-same_line_where.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: SameLineWhere +// rustfmt-brace_style: SameLineWhere // Item brace style struct Lorem { diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs index f345e1cb3e9..8e8bb6c274e 100644 --- a/tests/source/fn-custom-6.rs +++ b/tests/source/fn-custom-6.rs @@ -1,5 +1,5 @@ // rustfmt-indent_style: Block -// rustfmt-fn_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Test different indents. fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index 03b9a895970..f7670e07fc8 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-indent_style: Block // rustfmt-fn_args_density: Vertical -// rustfmt-fn_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine // Case with only one variable. fn foo(a: u8) -> u8 { diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs index 40ea44f084a..d3deb20a51c 100644 --- a/tests/source/fn-custom-8.rs +++ b/tests/source/fn-custom-8.rs @@ -1,5 +1,5 @@ // rustfmt-indent_style: Block -// rustfmt-fn_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Test different indents. fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { diff --git a/tests/source/item-brace-style-always-next-line.rs b/tests/source/item-brace-style-always-next-line.rs index 96a628349ea..38094d67a77 100644 --- a/tests/source/item-brace-style-always-next-line.rs +++ b/tests/source/item-brace-style-always-next-line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine mod M { enum A { diff --git a/tests/source/item-brace-style-prefer-same-line.rs b/tests/source/item-brace-style-prefer-same-line.rs index 636a584ff68..dff89b8b66b 100644 --- a/tests/source/item-brace-style-prefer-same-line.rs +++ b/tests/source/item-brace-style-prefer-same-line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine mod M { enum A diff --git a/tests/source/item-brace-style-same-line-where.rs b/tests/source/item-brace-style-same-line-where.rs index 7b2a95d3245..ee4a7c5daad 100644 --- a/tests/source/item-brace-style-same-line-where.rs +++ b/tests/source/item-brace-style-same-line-where.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: SameLineWhere +// rustfmt-brace_style: SameLineWhere mod M { enum A diff --git a/tests/target/configs-fn_brace_style-always_next_line.rs b/tests/target/configs-fn_brace_style-always_next_line.rs index 543fc015cba..2755a264689 100644 --- a/tests/target/configs-fn_brace_style-always_next_line.rs +++ b/tests/target/configs-fn_brace_style-always_next_line.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine // Function brace style fn lorem() diff --git a/tests/target/configs-fn_brace_style-prefer_same_line.rs b/tests/target/configs-fn_brace_style-prefer_same_line.rs index 498ed9f2a99..23f98b6dd7a 100644 --- a/tests/target/configs-fn_brace_style-prefer_same_line.rs +++ b/tests/target/configs-fn_brace_style-prefer_same_line.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Function brace style fn lorem() { diff --git a/tests/target/configs-fn_brace_style-same_line_where.rs b/tests/target/configs-fn_brace_style-same_line_where.rs index 4da07441eaa..2afe59943a3 100644 --- a/tests/target/configs-fn_brace_style-same_line_where.rs +++ b/tests/target/configs-fn_brace_style-same_line_where.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_brace_style: SameLineWhere +// rustfmt-brace_style: SameLineWhere // Function brace style fn lorem() { diff --git a/tests/target/configs-item_brace_style-always_next_line.rs b/tests/target/configs-item_brace_style-always_next_line.rs index 888d255859b..38ed449d178 100644 --- a/tests/target/configs-item_brace_style-always_next_line.rs +++ b/tests/target/configs-item_brace_style-always_next_line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine // Item brace style enum Foo {} @@ -21,5 +21,7 @@ where mod tests { #[test] - fn it_works() {} + fn it_works() + { + } } diff --git a/tests/target/configs-item_brace_style-prefer_same_line.rs b/tests/target/configs-item_brace_style-prefer_same_line.rs index 1b5dbfa9d49..5143d7517c7 100644 --- a/tests/target/configs-item_brace_style-prefer_same_line.rs +++ b/tests/target/configs-item_brace_style-prefer_same_line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Item brace style struct Lorem { diff --git a/tests/target/configs-item_brace_style-same_line_where.rs b/tests/target/configs-item_brace_style-same_line_where.rs index ab88c1ca3ab..8a3b2852654 100644 --- a/tests/target/configs-item_brace_style-same_line_where.rs +++ b/tests/target/configs-item_brace_style-same_line_where.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: SameLineWhere +// rustfmt-brace_style: SameLineWhere // Item brace style struct Lorem { diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs index 2c86ade3c83..720d4288c41 100644 --- a/tests/target/fn-custom-6.rs +++ b/tests/target/fn-custom-6.rs @@ -1,5 +1,5 @@ // rustfmt-indent_style: Block -// rustfmt-fn_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Test different indents. fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 88c6ab10d80..ec113c30d53 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-indent_style: Block // rustfmt-fn_args_density: Vertical -// rustfmt-fn_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine // Case with only one variable. fn foo(a: u8) -> u8 @@ -29,7 +29,8 @@ fn foo( bar() } -trait Test { +trait Test +{ fn foo(a: u8) { } diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs index 151f7f2a0f2..290557b979d 100644 --- a/tests/target/fn-custom-8.rs +++ b/tests/target/fn-custom-8.rs @@ -1,5 +1,5 @@ // rustfmt-indent_style: Block -// rustfmt-fn_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine // Test different indents. fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { diff --git a/tests/target/indented-impl.rs b/tests/target/indented-impl.rs index 422ed55b2db..eff579dddac 100644 --- a/tests/target/indented-impl.rs +++ b/tests/target/indented-impl.rs @@ -1,11 +1,12 @@ -// rustfmt-item_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine mod x { struct X(i8); impl Y for X { - fn y(self) -> () { + fn y(self) -> () + { println!("ok"); } } diff --git a/tests/target/item-brace-style-always-next-line.rs b/tests/target/item-brace-style-always-next-line.rs index 270cd35eb2e..531ac598683 100644 --- a/tests/target/item-brace-style-always-next-line.rs +++ b/tests/target/item-brace-style-always-next-line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: AlwaysNextLine +// rustfmt-brace_style: AlwaysNextLine mod M { diff --git a/tests/target/item-brace-style-prefer-same-line.rs b/tests/target/item-brace-style-prefer-same-line.rs index bb090479cab..ef8dc028c2d 100644 --- a/tests/target/item-brace-style-prefer-same-line.rs +++ b/tests/target/item-brace-style-prefer-same-line.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: PreferSameLine +// rustfmt-brace_style: PreferSameLine mod M { enum A { diff --git a/tests/target/item-brace-style-same-line-where.rs b/tests/target/item-brace-style-same-line-where.rs index 54ad69de42a..9a275efc96e 100644 --- a/tests/target/item-brace-style-same-line-where.rs +++ b/tests/target/item-brace-style-same-line-where.rs @@ -1,4 +1,4 @@ -// rustfmt-item_brace_style: SameLineWhere +// rustfmt-brace_style: SameLineWhere mod M { enum A { -- cgit 1.4.1-3-g733a5 From babc4797831367b18ca4bec32ad8b98c3074148b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 14 Nov 2017 23:25:36 +0900 Subject: Use space_before_colon and space_after_colon --- src/config.rs | 14 ++------------ src/expr.rs | 5 +---- src/items.rs | 25 +++++++------------------ src/types.rs | 4 ++-- 4 files changed, 12 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 555a6a207fa..1e990c68a9f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -613,18 +613,8 @@ create_config! { indentation level as the match keyword"; match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, false, "Put a match sub-patterns' separator in front or back."; - space_before_type_annotation: bool, false, false, - "Leave a space before the colon in a type annotation"; - space_after_type_annotation_colon: bool, true, false, - "Leave a space after the colon in a type annotation"; - space_before_struct_lit_field_colon: bool, false, false, - "Leave a space before the colon in a struct literal field"; - space_after_struct_lit_field_colon: bool, true, false, - "Leave a space after the colon in a struct literal field"; - space_before_bound: bool, false, false, - "Leave a space before the colon in a trait or lifetime bound"; - space_after_bound_colon: bool, true, false, - "Leave a space after the colon in a trait or lifetime bound"; + space_before_colon: bool, false, false, "Leave a space before the colon"; + space_after_colon: bool, true, false, "Leave a space after the colon"; spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; spaces_within_angle_brackets: bool, false, false, "Put spaces within non-empty generic arguments"; diff --git a/src/expr.rs b/src/expr.rs index 5aee87dbbb7..d9f210f2b8a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2348,10 +2348,7 @@ pub fn wrap_struct_field( } pub fn struct_lit_field_separator(config: &Config) -> &str { - colon_spaces( - config.space_before_struct_lit_field_colon(), - config.space_after_struct_lit_field_colon(), - ) + colon_spaces(config.space_before_colon(), config.space_after_colon()) } pub fn rewrite_field( diff --git a/src/items.rs b/src/items.rs index cd3cb48c4db..a01b692d681 100644 --- a/src/items.rs +++ b/src/items.rs @@ -39,10 +39,7 @@ use vertical::rewrite_with_alignment; use visitor::FmtVisitor; fn type_annotation_separator(config: &Config) -> &str { - colon_spaces( - config.space_before_type_annotation(), - config.space_after_type_annotation_colon(), - ) + colon_spaces(config.space_before_colon(), config.space_after_colon()) } // Statements of the form @@ -1405,16 +1402,8 @@ pub fn rewrite_type_alias( fn type_annotation_spacing(config: &Config) -> (&str, &str) { ( - if config.space_before_type_annotation() { - " " - } else { - "" - }, - if config.space_after_type_annotation_colon() { - " " - } else { - "" - }, + if config.space_before_colon() { " " } else { "" }, + if config.space_after_colon() { " " } else { "" }, ) } @@ -1581,8 +1570,8 @@ fn rewrite_static( offset: Indent, ) -> Option { let colon = colon_spaces( - context.config.space_before_type_annotation(), - context.config.space_after_type_annotation_colon(), + context.config.space_before_colon(), + context.config.space_after_colon(), ); let prefix = format!( "{}{} {}{}{}", @@ -1701,11 +1690,11 @@ impl Rewrite for ast::Arg { .rewrite(context, Shape::legacy(shape.width, shape.indent))?; if !is_empty_infer(context, &*self.ty) { - if context.config.space_before_type_annotation() { + if context.config.space_before_colon() { result.push_str(" "); } result.push_str(":"); - if context.config.space_after_type_annotation_colon() { + if context.config.space_after_colon() { result.push_str(" "); } let overhead = last_line_width(&result); diff --git a/src/types.rs b/src/types.rs index d2e782db1aa..c28afda3893 100644 --- a/src/types.rs +++ b/src/types.rs @@ -399,8 +399,8 @@ where fn type_bound_colon(context: &RewriteContext) -> &'static str { colon_spaces( - context.config.space_before_bound(), - context.config.space_after_bound_colon(), + context.config.space_before_colon(), + context.config.space_after_colon(), ) } -- cgit 1.4.1-3-g733a5 From bc543cce0b4548730625a00bd7f3de1f58424a94 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 14 Nov 2017 23:42:31 +0900 Subject: Combine spaces_within_parens and spaces_within_brackets --- src/chains.rs | 11 ++++++----- src/config.rs | 7 ++----- src/expr.rs | 29 +++++++++++++++-------------- src/items.rs | 8 +++++--- src/macros.rs | 2 +- src/patterns.rs | 2 +- src/types.rs | 18 ++++++++++-------- src/utils.rs | 2 +- 8 files changed, 41 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1a3586cd044..c7b91625c98 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -485,11 +485,12 @@ fn rewrite_method_call( .map(|ty| ty.rewrite(context, shape)) .collect::>>()?; - let type_str = if context.config.spaces_within_angle_brackets() && !type_list.is_empty() { - format!("::< {} >", type_list.join(", ")) - } else { - format!("::<{}>", type_list.join(", ")) - }; + let type_str = + if context.config.spaces_within_parens_and_brackets() && !type_list.is_empty() { + format!("::< {} >", type_list.join(", ")) + } else { + format!("::<{}>", type_list.join(", ")) + }; (types.last().unwrap().span.hi(), type_str) }; diff --git a/src/config.rs b/src/config.rs index 1e990c68a9f..c76933ca509 100644 --- a/src/config.rs +++ b/src/config.rs @@ -616,11 +616,8 @@ create_config! { space_before_colon: bool, false, false, "Leave a space before the colon"; space_after_colon: bool, true, false, "Leave a space after the colon"; spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; - spaces_within_angle_brackets: bool, false, false, - "Put spaces within non-empty generic arguments"; - spaces_within_square_brackets: bool, false, false, - "Put spaces within non-empty square brackets"; - spaces_within_parens: bool, false, false, "Put spaces within non-empty parentheses"; + spaces_within_parens_and_brackets: bool, false, false, + "Put spaces within non-empty parentheses or brackets"; use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; write_mode: WriteMode, WriteMode::Overwrite, false, "What Write Mode to use when none is supplied: \ diff --git a/src/expr.rs b/src/expr.rs index d9f210f2b8a..077ba5271a4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -202,7 +202,7 @@ pub fn format_expr( rewrite_index(&**expr, &**index, context, shape) } ast::ExprKind::Repeat(ref expr, ref repeats) => { - let (lbr, rbr) = if context.config.spaces_within_square_brackets() { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { ("[ ", " ]") } else { ("[", "]") @@ -409,7 +409,7 @@ pub fn rewrite_array<'a, I>( where I: Iterator, { - let bracket_size = if context.config.spaces_within_square_brackets() { + let bracket_size = if context.config.spaces_within_parens_and_brackets() { 2 // "[ " } else { 1 // "[" @@ -439,7 +439,7 @@ where ).collect::>(); if items.is_empty() { - if context.config.spaces_within_square_brackets() { + if context.config.spaces_within_parens_and_brackets() { return Some("[ ]".to_string()); } else { return Some("[]".to_string()); @@ -501,7 +501,7 @@ where let result = if context.config.indent_style() == IndentStyle::Visual || tactic == DefinitiveListTactic::Horizontal { - if context.config.spaces_within_square_brackets() && !list_str.is_empty() { + if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { format!("[ {} ]", list_str) } else { format!("[{}]", list_str) @@ -1801,7 +1801,7 @@ where T: Rewrite + Spanned + ToExpr + 'a, { // 2 = `( `, 1 = `(` - let paren_overhead = if context.config.spaces_within_parens() { + let paren_overhead = if context.config.spaces_within_parens_and_brackets() { 2 } else { 1 @@ -2098,7 +2098,7 @@ pub fn wrap_args_with_parens( || (context.inside_macro && !args_str.contains('\n') && args_str.len() + paren_overhead(context) <= shape.width) || is_extendable { - if context.config.spaces_within_parens() && !args_str.is_empty() { + if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() { format!("( {} )", args_str) } else { format!("({})", args_str) @@ -2141,11 +2141,12 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> .offset_left(paren_overhead) .and_then(|s| s.sub_width(paren_overhead))?; - let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && !s.is_empty() { - format!("( {} )", s) - } else { - format!("({})", s) - }; + let paren_wrapper = + |s: &str| if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { + format!("( {} )", s) + } else { + format!("({})", s) + }; let subexpr_str = subexpr.rewrite(context, sub_shape)?; debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); @@ -2167,7 +2168,7 @@ fn rewrite_index( ) -> Option { let expr_str = expr.rewrite(context, shape)?; - let (lbr, rbr) = if context.config.spaces_within_square_brackets() { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { ("[ ", " ]") } else { ("[", "]") @@ -2436,7 +2437,7 @@ where .unwrap() .rewrite(context, nested_shape) .map(|s| { - if context.config.spaces_within_parens() { + if context.config.spaces_within_parens_and_brackets() { format!("( {}, )", s) } else { format!("({},)", s) @@ -2476,7 +2477,7 @@ where }; let list_str = write_list(&item_vec, &fmt)?; - if context.config.spaces_within_parens() && !list_str.is_empty() { + if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { Some(format!("( {} )", list_str)) } else { Some(format!("({})", list_str)) diff --git a/src/items.rs b/src/items.rs index a01b692d681..fa697157ea3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1882,7 +1882,9 @@ fn rewrite_fn_base( } else { result.push('('); } - if context.config.spaces_within_parens() && !fd.inputs.is_empty() && result.ends_with('(') { + if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() + && result.ends_with('(') + { result.push(' ') } @@ -1943,7 +1945,7 @@ fn rewrite_fn_base( if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { result.push('\n'); } - if context.config.spaces_within_parens() && !fd.inputs.is_empty() { + if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() { result.push(' ') } // If the last line of args contains comment, we cannot put the closing paren @@ -2522,7 +2524,7 @@ pub fn wrap_generics_with_angle_brackets( .block_unindent(context.config) .to_string(context.config) ) - } else if context.config.spaces_within_angle_brackets() { + } else if context.config.spaces_within_parens_and_brackets() { format!("< {} >", list_str) } else { format!("<{}>", list_str) diff --git a/src/macros.rs b/src/macros.rs index 8f5feac474c..6e64a49361d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -219,7 +219,7 @@ pub fn rewrite_macro( let mac_shape = shape.offset_left(macro_name.len())?; // Handle special case: `vec![expr; expr]` if vec_with_semi { - let (lbr, rbr) = if context.config.spaces_within_square_brackets() { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { ("[ ", " ]") } else { ("[", "]") diff --git a/src/patterns.rs b/src/patterns.rs index a7e6c48b6d2..20ea14a5dfe 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -109,7 +109,7 @@ impl Rewrite for Pat { let pats = pats?; // Unwrap all the sub-strings and join them with commas. - let result = if context.config.spaces_within_square_brackets() { + let result = if context.config.spaces_within_parens_and_brackets() { format!("[ {} ]", pats.join(", ")) } else { format!("[{}]", pats.join(", ")) diff --git a/src/types.rs b/src/types.rs index c28afda3893..180a38b2f23 100644 --- a/src/types.rs +++ b/src/types.rs @@ -54,7 +54,7 @@ pub fn rewrite_path( if let Some(qself) = qself { result.push('<'); - if context.config.spaces_within_angle_brackets() { + if context.config.spaces_within_parens_and_brackets() { result.push_str(" ") } @@ -81,7 +81,7 @@ pub fn rewrite_path( )?; } - if context.config.spaces_within_angle_brackets() { + if context.config.spaces_within_parens_and_brackets() { result.push_str(" ") } @@ -434,7 +434,9 @@ impl Rewrite for ast::WherePredicate { .collect::>>()?; let bounds_str = join_bounds(context, ty_shape, &bounds); - if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { + if context.config.spaces_within_parens_and_brackets() + && !lifetime_str.is_empty() + { format!( "for< {} > {}{}{}", lifetime_str, @@ -600,7 +602,7 @@ impl Rewrite for ast::PolyTraitRef { .rewrite(context, shape.offset_left(extra_offset)?)?; Some( - if context.config.spaces_within_angle_brackets() && !lifetime_str.is_empty() { + if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { format!("for< {} > {}", lifetime_str, path_str) } else { format!("for<{}> {}", lifetime_str, path_str) @@ -671,7 +673,7 @@ impl Rewrite for ast::Ty { let budget = shape.width.checked_sub(2)?; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| { - if context.config.spaces_within_parens() { + if context.config.spaces_within_parens_and_brackets() { format!("( {} )", ty_str) } else { format!("({})", ty_str) @@ -679,14 +681,14 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::Slice(ref ty) => { - let budget = if context.config.spaces_within_square_brackets() { + let budget = if context.config.spaces_within_parens_and_brackets() { shape.width.checked_sub(4)? } else { shape.width.checked_sub(2)? }; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| { - if context.config.spaces_within_square_brackets() { + if context.config.spaces_within_parens_and_brackets() { format!("[ {} ]", ty_str) } else { format!("[{}]", ty_str) @@ -703,7 +705,7 @@ impl Rewrite for ast::Ty { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } ast::TyKind::Array(ref ty, ref repeats) => { - let use_spaces = context.config.spaces_within_square_brackets(); + let use_spaces = context.config.spaces_within_parens_and_brackets(); let lbr = if use_spaces { "[ " } else { "[" }; let rbr = if use_spaces { " ]" } else { "]" }; rewrite_pair( diff --git a/src/utils.rs b/src/utils.rs index b87e2eaf493..88272ff0d38 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -441,7 +441,7 @@ pub fn colon_spaces(before: bool, after: bool) -> &'static str { #[inline] pub fn paren_overhead(context: &RewriteContext) -> usize { - if context.config.spaces_within_parens() { + if context.config.spaces_within_parens_and_brackets() { 4 } else { 2 -- cgit 1.4.1-3-g733a5 From bdb8f369e8529c135fcaf8c1f2cf2c931032f067 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 15 Nov 2017 10:36:49 +0900 Subject: Return None when a literal exceeds budget --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5aee87dbbb7..625f584c9b2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1691,7 +1691,7 @@ fn rewrite_pat_expr( pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), - _ => Some(context.snippet(l.span)), + _ => wrap_str(context.snippet(l.span), context.config.max_width(), shape), } } -- cgit 1.4.1-3-g733a5 From 37b1779426f42d82c563a963f58f03172e88e5aa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 15 Nov 2017 10:55:40 +0900 Subject: Look for a newline after match arm only when there is one --- src/lists.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index d7098d3a397..a5d2334dcda 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -602,7 +602,11 @@ where // Match arms may not have trailing comma. In any case, for match arms, // we will assume that the post comment belongs to the next arm if they // do not end with trailing comma. - 1 + if let Some(newline_index) = newline_index { + newline_index + 1 + } else { + 0 + } } } None => post_snippet -- cgit 1.4.1-3-g733a5 From 95c7325ac2aa89043e2ab39b86a3dc1615bee5ce Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 15 Nov 2017 15:46:00 +0900 Subject: Do not get tricked by a nested comment --- src/lists.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index a5d2334dcda..dc55a8261fa 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -572,10 +572,12 @@ where let comment_end = match self.inner.peek() { Some(..) => { let mut block_open_index = post_snippet.find("/*"); - // check if it really is a block comment (and not //*) + // check if it really is a block comment (and not `//*` or a nested comment) if let Some(i) = block_open_index { - if i > 0 && &post_snippet[i - 1..i] == "/" { - block_open_index = None; + match post_snippet.find("/") { + Some(j) if j < i => block_open_index = None, + _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, + _ => (), } } let newline_index = post_snippet.find('\n'); -- cgit 1.4.1-3-g733a5 From 4cd2e6f39a469206671d93b6d2f8f581db0aba41 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 11:26:36 +0900 Subject: Generalize rewrite_assign_rhs() --- src/expr.rs | 8 ++++---- src/items.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7380dc4850e..46e7e500f22 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2578,10 +2578,10 @@ fn rewrite_assignment( // The left hand side must contain everything up to, and including, the // assignment operator. -pub fn rewrite_assign_rhs>( +pub fn rewrite_assign_rhs, R: Rewrite>( context: &RewriteContext, lhs: S, - ex: &ast::Expr, + ex: &R, shape: Shape, ) -> Option { let lhs = lhs.into(); @@ -2596,9 +2596,9 @@ pub fn rewrite_assign_rhs>( Some(lhs + &rhs) } -fn choose_rhs( +fn choose_rhs( context: &RewriteContext, - expr: &ast::Expr, + expr: &R, shape: Shape, orig_rhs: Option, ) -> Option { diff --git a/src/items.rs b/src/items.rs index fa697157ea3..e0bf02abe65 100644 --- a/src/items.rs +++ b/src/items.rs @@ -111,7 +111,7 @@ impl Rewrite for ast::Local { // 1 = trailing semicolon; let nested_shape = shape.sub_width(1)?; - result = rewrite_assign_rhs(context, result, ex, nested_shape)?; + result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?; } result.push(';'); @@ -550,7 +550,7 @@ impl<'a> FmtVisitor<'a> { ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { let lhs = format!("{} =", field.node.name); // 1 = ',' - rewrite_assign_rhs(&context, lhs, expr, shape.sub_width(1)?)? + rewrite_assign_rhs(&context, lhs, &**expr, shape.sub_width(1)?)? } else { field.node.name.to_string() }, @@ -1593,7 +1593,7 @@ fn rewrite_static( rewrite_assign_rhs( context, lhs, - expr, + &**expr, Shape::legacy(remaining_width, offset.block_only()), ).and_then(|res| { recover_comment_removed(res, static_parts.span, context) -- cgit 1.4.1-3-g733a5 From f7ef1f681cf026ee6e941f51de0fa9a3693e2153 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 11:27:11 +0900 Subject: Use rewrite_assign_rhs() when rewriting associated type --- src/items.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e0bf02abe65..5f6c043bb4a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1613,10 +1613,9 @@ pub fn rewrite_associated_type( ) -> Option { let prefix = format!("type {}", ident); - let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { + let type_bounds_str = if let Some(ref bounds) = ty_param_bounds_opt { // 2 = ": ".len() let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - let bounds: &[_] = ty_param_bounds; let bound_str = bounds .iter() .map(|ty_bound| ty_bound.rewrite(context, shape)) @@ -1631,14 +1630,10 @@ pub fn rewrite_associated_type( }; if let Some(ty) = ty_opt { - let ty_str = ty.rewrite( - context, - Shape::legacy( - context.budget(indent.block_indent + prefix.len() + 2), - indent.block_only(), - ), - )?; - Some(format!("{}{} = {};", prefix, type_bounds_str, ty_str)) + // 1 = `;` + let shape = Shape::indented(indent, context.config).sub_width(1)?; + let lhs = format!("{}{} =", prefix, type_bounds_str); + rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") } else { Some(format!("{}{};", prefix, type_bounds_str)) } -- cgit 1.4.1-3-g733a5 From 8ef54293e8ddee1047736dde5706843bc3bf44d2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 16:02:01 +0900 Subject: Force vertical layout for all variants if one of then use multiple lines --- src/items.rs | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5f6c043bb4a..0c1895c2391 100644 --- a/src/items.rs +++ b/src/items.rs @@ -484,21 +484,30 @@ impl<'a> FmtVisitor<'a> { let indentation = self.block_indent.to_string(self.config); result.push_str(&indentation); - let items = itemize_list( - self.codemap, - enum_def.variants.iter(), - "}", - |f| if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo() - } else { - f.span.lo() - }, - |f| f.span.hi(), - |f| self.format_variant(f), - body_lo, - body_hi, - false, - ); + let itemize_list_with = |one_line_width: usize| { + itemize_list( + self.codemap, + enum_def.variants.iter(), + "}", + |f| if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo() + } else { + f.span.lo() + }, + |f| f.span.hi(), + |f| self.format_variant(f, one_line_width), + body_lo, + body_hi, + false, + ).collect() + }; + let mut items: Vec<_> = itemize_list_with(self.config.struct_variant_width()); + // If one of the variants use multiple lines, use multi-lined formatting for all variants. + let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains("\n")); + let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains("\n")); + if has_multiline_variant && has_single_line_variant { + items = itemize_list_with(0); + } let shape = self.shape().sub_width(2).unwrap(); let fmt = ListFormatting { @@ -512,14 +521,14 @@ impl<'a> FmtVisitor<'a> { config: self.config, }; - let list = write_list(&items.collect::>(), &fmt)?; + let list = write_list(&items, &fmt)?; result.push_str(&list); result.push('\n'); Some(result) } // Variant of an enum. - fn format_variant(&self, field: &ast::Variant) -> Option { + fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option { if contains_skip(&field.node.attrs) { let lo = field.node.attrs[0].span.lo(); let span = mk_sp(lo, field.span.hi()); @@ -544,7 +553,7 @@ impl<'a> FmtVisitor<'a> { &context, &StructParts::from_variant(field), indent, - Some(self.config.struct_variant_width()), + Some(one_line_width), )? } ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { -- cgit 1.4.1-3-g733a5 From b1a6dd6b83c15e2de85a1c790a0fdc9f13817a2c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 16:07:15 +0900 Subject: Cargo fmr & update tests Note that we are forcing vertical layout when there are attributes on top of a variant. --- src/bin/rustfmt.rs | 4 +++- tests/target/enum.rs | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 4a041144789..41454c853ed 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -45,7 +45,9 @@ enum Operation { /// Print detailed configuration help. ConfigHelp, /// Output default config to a file, or stdout if None - ConfigOutputDefault { path: Option }, + ConfigOutputDefault { + path: Option, + }, /// No file specified, read from stdin Stdin { input: String, diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 30a32c4d896..f3e8f2d4d6b 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -44,7 +44,9 @@ enum StructLikeVariants { // Pre-comment #[Attr50] y: SomeType, // Aanother Comment }, - SL { a: A }, + SL { + a: A, + }, } enum X { @@ -65,7 +67,10 @@ pub enum EnumWithAttributes { SkippedItem(String,String,), // Post-comment #[another_attr] #[attr2] - ItemStruct { x: usize, y: usize }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + ItemStruct { + x: usize, + y: usize, + }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ // And another ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ -- cgit 1.4.1-3-g733a5 From 09d54512da002e9695402b88fda63bcc49f6b762 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 16:41:09 +0900 Subject: Break before '|' for multi-lined match arm pattern --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c76933ca509..9fbdfc2754b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -611,7 +611,7 @@ create_config! { "Force match arm bodies to be in a new lines"; indent_match_arms: bool, true, false, "Indent match arms instead of keeping them at the same \ indentation level as the match keyword"; - match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Back, false, + match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Front, false, "Put a match sub-patterns' separator in front or back."; space_before_colon: bool, false, false, "Leave a space before the colon"; space_after_colon: bool, true, false, "Leave a space after the colon"; -- cgit 1.4.1-3-g733a5 From 34c24990296ff473511dbd471f5ff288f956add5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 16:42:07 +0900 Subject: Cargo fmt --- src/bin/cargo-fmt.rs | 14 +++++++------- src/chains.rs | 32 +++++++++++++++---------------- src/closures.rs | 22 ++++++++++----------- src/comment.rs | 14 +++++++------- src/expr.rs | 54 ++++++++++++++++++++++++++-------------------------- src/imports.rs | 14 +++++++------- src/patterns.rs | 8 ++++---- src/utils.rs | 32 +++++++++++++++---------------- 8 files changed, 95 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 60cc59bc1a0..fdeb3cf4286 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -164,13 +164,13 @@ enum TargetKind { impl TargetKind { fn should_format(&self) -> bool { match *self { - TargetKind::Lib | - TargetKind::Bin | - TargetKind::Example | - TargetKind::Test | - TargetKind::Bench | - TargetKind::CustomBuild | - TargetKind::ProcMacro => true, + TargetKind::Lib + | TargetKind::Bin + | TargetKind::Example + | TargetKind::Test + | TargetKind::Bench + | TargetKind::CustomBuild + | TargetKind::ProcMacro => true, _ => false, } } diff --git a/src/chains.rs b/src/chains.rs index c7b91625c98..8a4b4257891 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -350,19 +350,19 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { context.use_block_indent() && repr.contains('\n') } - ast::ExprKind::Struct(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) | - ast::ExprKind::If(..) | - ast::ExprKind::IfLet(..) | - ast::ExprKind::Block(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::ForLoop(..) | - ast::ExprKind::Match(..) => repr.contains('\n'), - ast::ExprKind::Paren(ref expr) | - ast::ExprKind::Binary(_, _, ref expr) | - ast::ExprKind::Index(_, ref expr) | - ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), + ast::ExprKind::Struct(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) + | ast::ExprKind::Binary(_, _, ref expr) + | ast::ExprKind::Index(_, ref expr) + | ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), _ => false, } } @@ -396,9 +396,9 @@ fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { Some(convert_try(&expressions[0], context)) } - ast::ExprKind::TupField(ref subexpr, _) | - ast::ExprKind::Field(ref subexpr, _) | - ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), + ast::ExprKind::TupField(ref subexpr, _) + | ast::ExprKind::Field(ref subexpr, _) + | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), _ => None, } } diff --git a/src/closures.rs b/src/closures.rs index a180e116a8b..5f5b3d8fe26 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -328,17 +328,17 @@ where fn is_block_closure_forced(expr: &ast::Expr) -> bool { match expr.node { - ast::ExprKind::If(..) | - ast::ExprKind::IfLet(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) | - ast::ExprKind::ForLoop(..) => true, - ast::ExprKind::AddrOf(_, ref expr) | - ast::ExprKind::Box(ref expr) | - ast::ExprKind::Try(ref expr) | - ast::ExprKind::Unary(_, ref expr) | - ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr), + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr), _ => false, } } diff --git a/src/comment.rs b/src/comment.rs index 6d5f48fbb26..2511e5df216 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -64,10 +64,10 @@ impl<'a> CommentStyle<'a> { pub fn closer(&self) -> &'a str { match *self { - CommentStyle::DoubleSlash | - CommentStyle::TripleSlash | - CommentStyle::Custom(..) | - CommentStyle::Doc => "", + CommentStyle::DoubleSlash + | CommentStyle::TripleSlash + | CommentStyle::Custom(..) + | CommentStyle::Doc => "", CommentStyle::DoubleBullet => " **/", CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", } @@ -648,9 +648,9 @@ enum FullCodeCharKind { impl FullCodeCharKind { fn is_comment(&self) -> bool { match *self { - FullCodeCharKind::StartComment | - FullCodeCharKind::InComment | - FullCodeCharKind::EndComment => true, + FullCodeCharKind::StartComment + | FullCodeCharKind::InComment + | FullCodeCharKind::EndComment => true, _ => false, } } diff --git a/src/expr.rs b/src/expr.rs index 46e7e500f22..1086a7030ba 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -99,12 +99,12 @@ pub fn format_expr( ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) } - ast::ExprKind::If(..) | - ast::ExprKind::IfLet(..) | - ast::ExprKind::ForLoop(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), ast::ExprKind::Block(ref block) => { match expr_type { @@ -161,10 +161,10 @@ pub fn format_expr( ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { closures::rewrite_closure(capture, fn_decl, body, expr.span, context, shape) } - ast::ExprKind::Try(..) | - ast::ExprKind::Field(..) | - ast::ExprKind::TupField(..) | - ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), + ast::ExprKind::Try(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::TupField(..) + | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), ast::ExprKind::Mac(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( @@ -2060,29 +2060,29 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l (context.use_block_indent() && args_len == 1) || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) } - ast::ExprKind::If(..) | - ast::ExprKind::IfLet(..) | - ast::ExprKind::ForLoop(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) => { + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => { context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { context.use_block_indent() || context.config.indent_style() == IndentStyle::Visual && args_len > 1 } - ast::ExprKind::Array(..) | - ast::ExprKind::Call(..) | - ast::ExprKind::Mac(..) | - ast::ExprKind::MethodCall(..) | - ast::ExprKind::Struct(..) | - ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, - ast::ExprKind::AddrOf(_, ref expr) | - ast::ExprKind::Box(ref expr) | - ast::ExprKind::Try(ref expr) | - ast::ExprKind::Unary(_, ref expr) | - ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), + ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), _ => false, } } diff --git a/src/imports.rs b/src/imports.rs index faf0638f7d1..300aa046cf1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -27,9 +27,9 @@ use visitor::{rewrite_extern_crate, FmtVisitor}; fn path_of(a: &ast::ViewPath_) -> &ast::Path { match *a { - ast::ViewPath_::ViewPathSimple(_, ref p) | - ast::ViewPath_::ViewPathGlob(ref p) | - ast::ViewPath_::ViewPathList(ref p, _) => p, + ast::ViewPath_::ViewPathSimple(_, ref p) + | ast::ViewPath_::ViewPathGlob(ref p) + | ast::ViewPath_::ViewPathList(ref p, _) => p, } } @@ -366,10 +366,10 @@ impl<'a> ImportItem<'a> { fn to_str(&self) -> Option<&str> { match *self { - ImportItem::SelfImport(s) | - ImportItem::SnakeCase(s) | - ImportItem::CamelCase(s) | - ImportItem::AllCaps(s) => Some(s), + ImportItem::SelfImport(s) + | ImportItem::SnakeCase(s) + | ImportItem::CamelCase(s) + | ImportItem::AllCaps(s) => Some(s), ImportItem::Invalid => None, } } diff --git a/src/patterns.rs b/src/patterns.rs index 20ea14a5dfe..1b8840392ca 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -245,10 +245,10 @@ impl<'a> Spanned for TuplePatField<'a> { pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { match *pat { TuplePatField::Pat(pat) => match pat.node { - ast::PatKind::Path(..) | - ast::PatKind::Tuple(..) | - ast::PatKind::Struct(..) | - ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, + ast::PatKind::Path(..) + | ast::PatKind::Tuple(..) + | ast::PatKind::Struct(..) + | ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) } diff --git a/src/utils.rs b/src/utils.rs index 88272ff0d38..d851dfda79d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -240,10 +240,10 @@ pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { match stmt.node { ast::StmtKind::Semi(ref expr) => match expr.node { - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::ForLoop(..) => false, + ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) => false, ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { context.config.trailing_semicolon() } @@ -450,18 +450,18 @@ pub fn paren_overhead(context: &RewriteContext) -> usize { pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { match e.node { - ast::ExprKind::InPlace(ref e, _) | - ast::ExprKind::Call(ref e, _) | - ast::ExprKind::Binary(_, ref e, _) | - ast::ExprKind::Cast(ref e, _) | - ast::ExprKind::Type(ref e, _) | - ast::ExprKind::Assign(ref e, _) | - ast::ExprKind::AssignOp(_, ref e, _) | - ast::ExprKind::Field(ref e, _) | - ast::ExprKind::TupField(ref e, _) | - ast::ExprKind::Index(ref e, _) | - ast::ExprKind::Range(Some(ref e), _, _) | - ast::ExprKind::Try(ref e) => left_most_sub_expr(e), + ast::ExprKind::InPlace(ref e, _) + | ast::ExprKind::Call(ref e, _) + | ast::ExprKind::Binary(_, ref e, _) + | ast::ExprKind::Cast(ref e, _) + | ast::ExprKind::Type(ref e, _) + | ast::ExprKind::Assign(ref e, _) + | ast::ExprKind::AssignOp(_, ref e, _) + | ast::ExprKind::Field(ref e, _) + | ast::ExprKind::TupField(ref e, _) + | ast::ExprKind::Index(ref e, _) + | ast::ExprKind::Range(Some(ref e), _, _) + | ast::ExprKind::Try(ref e) => left_most_sub_expr(e), _ => e, } } -- cgit 1.4.1-3-g733a5 From 35466adbfe90939552580c15161a1ee9b9f1c4a5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 17:38:12 +0900 Subject: Generalize ListItems to allow a separator other than comma --- src/closures.rs | 1 + src/expr.rs | 5 +++++ src/imports.rs | 2 ++ src/items.rs | 5 +++++ src/lists.rs | 5 ++++- src/patterns.rs | 2 ++ src/types.rs | 2 ++ src/vertical.rs | 1 + src/visitor.rs | 1 + 9 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 5f5b3d8fe26..8290f1b09a1 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -194,6 +194,7 @@ fn rewrite_closure_fn_decl( context.codemap, fn_decl.inputs.iter(), "|", + ",", |arg| span_lo_for_arg(arg), |arg| span_hi_for_arg(context, arg), |arg| arg.rewrite(context, arg_shape), diff --git a/src/expr.rs b/src/expr.rs index 1086a7030ba..0b47bb847ed 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -430,6 +430,7 @@ where context.codemap, expr_iter, "]", + ",", |item| item.span.lo(), |item| item.span.hi(), |item| item.rewrite(context, nested_shape), @@ -1341,6 +1342,7 @@ fn rewrite_match_arms( .zip(is_last_iter) .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), "}", + "|", |arm| arm.arm.span().lo(), |arm| arm.arm.span().hi(), |arm| arm.rewrite(context, arm_shape), @@ -1874,6 +1876,7 @@ where context.codemap, args.iter(), ")", + ",", |item| item.span().lo(), |item| item.span().hi(), |item| item.rewrite(context, shape), @@ -2301,6 +2304,7 @@ fn rewrite_struct_lit<'a>( context.codemap, field_iter, "}", + ",", span_lo, span_hi, rewrite, @@ -2451,6 +2455,7 @@ where context.codemap, items, ")", + ",", |item| item.span().lo(), |item| item.span().hi(), |item| item.rewrite(context, nested_shape), diff --git a/src/imports.rs b/src/imports.rs index 300aa046cf1..56d23fa9827 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -212,6 +212,7 @@ fn rewrite_imports( context.codemap, use_items.iter(), "", + ";", |item| item.span().lo(), |item| item.span().hi(), |item| { @@ -442,6 +443,7 @@ fn rewrite_use_list( context.codemap, path_list.iter(), "}", + ",", |vpi| vpi.span.lo(), |vpi| vpi.span.hi(), rewrite_path_item, diff --git a/src/items.rs b/src/items.rs index 0c1895c2391..2dda5bc16bd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -489,6 +489,7 @@ impl<'a> FmtVisitor<'a> { self.codemap, enum_def.variants.iter(), "}", + ",", |f| if !f.node.attrs.is_empty() { f.node.attrs[0].span.lo() } else { @@ -2226,6 +2227,7 @@ fn rewrite_args( .map(ArgumentKind::Regular) .chain(variadic_arg), ")", + ",", |arg| match *arg { ArgumentKind::Regular(arg) => span_lo_for_arg(arg), ArgumentKind::Variadic(start) => start, @@ -2447,6 +2449,7 @@ fn rewrite_generics_inner( context.codemap, generics_args, ">", + ",", |arg| arg.span().lo(), |arg| arg.span().hi(), |arg| arg.rewrite(context, shape), @@ -2589,6 +2592,7 @@ fn rewrite_where_clause_rfc_style( context.codemap, where_clause.predicates.iter(), terminator, + ",", |pred| pred.span().lo(), |pred| pred.span().hi(), |pred| pred.rewrite(context, clause_shape), @@ -2702,6 +2706,7 @@ fn rewrite_where_clause( context.codemap, where_clause.predicates.iter(), terminator, + ",", |pred| pred.span().lo(), |pred| pred.span().hi(), |pred| pred.rewrite(context, Shape::legacy(budget, offset)), diff --git a/src/lists.rs b/src/lists.rs index dc55a8261fa..89382ab76ec 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -509,6 +509,7 @@ where prev_span_end: BytePos, next_span_start: BytePos, terminator: &'a str, + separator: &'a str, leave_last: bool, } @@ -581,7 +582,7 @@ where } } let newline_index = post_snippet.find('\n'); - if let Some(separator_index) = post_snippet.find_uncommented(",") { + if let Some(separator_index) = post_snippet.find_uncommented(self.separator) { match (block_open_index, newline_index) { // Separator before comment, with the next item on same line. // Comment belongs to next item. @@ -677,6 +678,7 @@ pub fn itemize_list<'a, T, I, F1, F2, F3>( codemap: &'a CodeMap, inner: I, terminator: &'a str, + separator: &'a str, get_lo: F1, get_hi: F2, get_item_string: F3, @@ -699,6 +701,7 @@ where prev_span_end: prev_span_end, next_span_start: next_span_start, terminator: terminator, + separator: separator, leave_last: leave_last, } } diff --git a/src/patterns.rs b/src/patterns.rs index 1b8840392ca..f4bb59e5127 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -151,6 +151,7 @@ fn rewrite_struct_pat( context.codemap, fields.iter(), terminator, + ",", |f| f.span.lo(), |f| f.span.hi(), |f| f.node.rewrite(context, v_shape), @@ -347,6 +348,7 @@ fn count_wildcard_suffix_len( context.codemap, patterns.iter(), ")", + ",", |item| item.span().lo(), |item| item.span().hi(), |item| item.rewrite(context, shape), diff --git a/src/types.rs b/src/types.rs index 180a38b2f23..ab4de7349b1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -230,6 +230,7 @@ fn rewrite_segment( context.codemap, param_list.into_iter(), ">", + ",", |param| param.get_span().lo(), |param| param.get_span().hi(), |seg| seg.rewrite(context, generics_shape), @@ -321,6 +322,7 @@ where .map(|i| ArgumentKind::Regular(Box::new(i))) .chain(variadic_arg), ")", + ",", |arg| match *arg { ArgumentKind::Regular(ref ty) => ty.span().lo(), ArgumentKind::Variadic(start) => start, diff --git a/src/vertical.rs b/src/vertical.rs index 32072acfc9e..bb4bad7852e 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -231,6 +231,7 @@ fn rewrite_aligned_items_inner( context.codemap, fields.iter(), "}", + ",", |field| field.get_span().lo(), |field| field.get_span().hi(), |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), diff --git a/src/visitor.rs b/src/visitor.rs index 159f73452bd..79bade0cc20 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -750,6 +750,7 @@ impl Rewrite for ast::MetaItem { context.codemap, list.iter(), ")", + ",", |nested_meta_item| nested_meta_item.span.lo(), |nested_meta_item| nested_meta_item.span.hi(), |nested_meta_item| nested_meta_item.rewrite(context, item_shape), -- cgit 1.4.1-3-g733a5 From 311a3c526c50cf12fd773c8a847a22a5db3022ee Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 17:39:38 +0900 Subject: Fix up write_list() to handle Mixed tactic --- src/lists.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 89382ab76ec..b80d8d6541e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -207,10 +207,18 @@ impl SeparatorPlace { *self == SeparatorPlace::Back } - pub fn from_tactic(default: SeparatorPlace, tactic: DefinitiveListTactic) -> SeparatorPlace { + pub fn from_tactic( + default: SeparatorPlace, + tactic: DefinitiveListTactic, + sep: &str, + ) -> SeparatorPlace { match tactic { DefinitiveListTactic::Vertical => default, - _ => SeparatorPlace::Back, + _ => if sep == "," { + SeparatorPlace::Back + } else { + default + }, } } } @@ -269,7 +277,8 @@ where let cloned_items = items.clone(); let mut iter = items.into_iter().enumerate().peekable(); let mut item_max_width: Option = None; - let mut sep_place = SeparatorPlace::from_tactic(formatting.separator_place, tactic); + let sep_place = + SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); let mut line_len = 0; let indent_str = &formatting.shape.indent.to_string(formatting.config); @@ -278,7 +287,10 @@ where let inner_item = item.item.as_ref()?; let first = i == 0; let last = iter.peek().is_none(); - let mut separate = !last || trailing_separator; + let mut separate = match sep_place { + SeparatorPlace::Front => !first, + SeparatorPlace::Back => !last || trailing_separator, + }; let item_sep_len = if separate { sep_len } else { 0 }; // Item string may be multi-line. Its length (used for block comment alignment) @@ -316,9 +328,6 @@ where trailing_separator = true; } } - sep_place = formatting.separator_place; - } else { - sep_place = SeparatorPlace::Back; } if line_len > 0 { -- cgit 1.4.1-3-g733a5 From e09a0cc83622e57cb157d4fed13b9740f1a40bfe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 17:40:24 +0900 Subject: Add is_short_pattern() --- src/expr.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0b47bb847ed..ab9bc2fa240 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1411,6 +1411,38 @@ fn rewrite_match_arm( ) } +/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: +/// +/// [small, ntp]: +/// - single token +/// - `&[single-line, ntp]` +/// +/// [small]: +/// - `[small, ntp]` +/// - unary tuple constructor `([small, ntp])` +/// - `&[small]` +fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { + // We also require that the pattern is reasonably 'small' with its literal width. + pat_str.len() <= 20 && !pat_str.contains("\n") && is_short_pattern_inner(pat) +} + +fn is_short_pattern_inner(pat: &ast::Pat) -> bool { + match pat.node { + ast::PatKind::Wild | ast::PatKind::Lit(_) => true, + ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), + ast::PatKind::Struct(..) + | ast::PatKind::Mac(..) + | ast::PatKind::Slice(..) + | ast::PatKind::Path(..) + | ast::PatKind::Range(..) => false, + ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, + ast::PatKind::TupleStruct(ref path, ref subpats, _) => { + path.segments.len() <= 1 && subpats.len() <= 1 + } + ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p), + } +} + fn rewrite_match_pattern( context: &RewriteContext, pats: &[ptr::P], -- cgit 1.4.1-3-g733a5 From 95d7619e345ac6fa997297af9565bfd44ef9e855 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 16 Nov 2017 17:40:33 +0900 Subject: Use mixed layout for patterns that are all short --- src/expr.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ab9bc2fa240..4716974153b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1457,13 +1457,20 @@ fn rewrite_match_pattern( .map(|p| p.rewrite(context, pat_shape)) .collect::>>()?; + let use_mixed_layout = pats.iter() + .zip(pat_strs.iter()) + .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::VerticalBar, - pat_shape.width, - ); + let tactic = if use_mixed_layout { + DefinitiveListTactic::Mixed + } else { + definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + pat_shape.width, + ) + }; let fmt = ListFormatting { tactic: tactic, separator: " |", -- cgit 1.4.1-3-g733a5 From d0df53d833b0c3fb461fd6fb80614f3306984a35 Mon Sep 17 00:00:00 2001 From: Utkarsh Kukreti Date: Fri, 17 Nov 2017 09:43:47 +0530 Subject: Fix checkstyle test. The only reason it passed before was due to a bug in the `diff` crate. The diff was empty even though the contents of the files were different -- namely one string had a trailing newline character while the other didn't. Now both have a trailing newline character. --- src/checkstyle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 0934ed3f719..34c1d81d40c 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -33,7 +33,7 @@ where { if mode == WriteMode::Checkstyle { let mut xml_tail = String::new(); - xml_tail.push_str(""); + xml_tail.push_str("\n"); write!(out, "{}", xml_tail)?; } Ok(()) -- cgit 1.4.1-3-g733a5 From d44d4a3fbcc2d8fdec1c100215a690f1f5a3b45a Mon Sep 17 00:00:00 2001 From: Utkarsh Kukreti Date: Fri, 17 Nov 2017 20:46:17 +0530 Subject: Add test for trailing newline in diff. Credits to @afshinm for most of the code. --- src/rustfmt_diff.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index daad73dc6ab..c2dac6c0416 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -234,4 +234,20 @@ mod test { ] ); } + + #[test] + fn diff_trailing_newline() { + let src = "one\ntwo\nthree\nfour\nfive"; + let dest = "one\ntwo\nthree\nfour\nfive\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 5, + lines: vec![Context("five".into()), Expected("".into())], + }, + ] + ); + } } -- cgit 1.4.1-3-g733a5 From d5152fc8c6d3725e236165e98690315f680eedec Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 18 Nov 2017 15:43:33 +0900 Subject: Use choose_rhs() for the layout of multi-lined struct field --- src/expr.rs | 2 +- src/items.rs | 33 +++++++++++---------------------- 2 files changed, 12 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 46e7e500f22..3418a7181c9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2596,7 +2596,7 @@ pub fn rewrite_assign_rhs, R: Rewrite>( Some(lhs + &rhs) } -fn choose_rhs( +pub fn choose_rhs( context: &RewriteContext, expr: &R, shape: Shape, diff --git a/src/items.rs b/src/items.rs index 0c1895c2391..36401472514 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,7 +23,7 @@ use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, +use expr::{choose_rhs, format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -1200,7 +1200,7 @@ pub fn format_struct_struct( let items_str = rewrite_with_alignment( fields, context, - Shape::indented(offset, context.config), + Shape::indented(offset, context.config).sub_width(1)?, mk_sp(body_lo, span.hi()), one_line_budget, )?; @@ -1480,34 +1480,23 @@ pub fn rewrite_struct_field( spacing.push(' '); } let ty_shape = shape.offset_left(overhead + spacing.len())?; - if let Some(ref ty) = field.ty.rewrite(context, ty_shape) { + let mut orig_ty = field.ty.rewrite(context, ty_shape); + if let Some(ref ty) = orig_ty { if !ty.contains('\n') { return Some(attr_prefix + &spacing + ty); } } - // We must use multiline. - let new_shape = shape.with_max_width(context.config); - let ty_rewritten = field.ty.rewrite(context, new_shape)?; - + // We must use multiline. We are going to put attributes and a field on different lines. + // 1 = " " + let rhs_shape = shape.offset_left(last_line_width(&prefix) + 1)?; + orig_ty = field.ty.rewrite(context, rhs_shape); let field_str = if prefix.is_empty() { - ty_rewritten - } else if prefix.len() + first_line_width(&ty_rewritten) + 1 <= shape.width { - prefix + " " + &ty_rewritten + orig_ty? } else { - let type_offset = shape.indent.block_indent(context.config); - let nested_shape = Shape::indented(type_offset, context.config); - let nested_ty = field.ty.rewrite(context, nested_shape)?; - prefix + "\n" + &type_offset.to_string(context.config) + &nested_ty + prefix + &choose_rhs(context, &*field.ty, rhs_shape, orig_ty)? }; - combine_strs_with_missing_comments( - context, - &attrs_str, - &field_str, - missing_span, - shape, - attrs_extendable, - ) + combine_strs_with_missing_comments(context, &attrs_str, &field_str, missing_span, shape, false) } pub struct StaticParts<'a> { -- cgit 1.4.1-3-g733a5 From 448991a6f357c78eca634643212353d0fa5779aa Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 18 Nov 2017 15:44:49 +0900 Subject: Handle multi-lined fn signature --- src/types.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 180a38b2f23..2ac57557817 100644 --- a/src/types.rs +++ b/src/types.rs @@ -25,7 +25,8 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTac SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use utils::{colon_spaces, extra_offset, format_abi, format_mutability, last_line_width, mk_sp}; +use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, + last_line_width, mk_sp}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { @@ -365,7 +366,8 @@ where let list_str = write_list(&item_vec, &fmt)?; let ty_shape = match context.config.indent_style() { - IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()), + // 4 = " -> " + IndentStyle::Block => shape.offset_left(4)?, IndentStyle::Visual => shape.block_left(4)?, }; let output = match *output { @@ -376,24 +378,23 @@ where FunctionRetTy::Default(..) => String::new(), }; - let shape = shape.sub_width(output.len())?; - let extendable = !list_str.contains('\n') || list_str.is_empty(); + let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains("\n"); let args = wrap_args_with_parens( context, &list_str, extendable, - shape, + shape.sub_width(first_line_width(&output))?, Shape::indented(offset, context.config), ); - if last_line_width(&args) + output.len() > shape.width { + if last_line_width(&args) + first_line_width(&output) <= shape.width { + Some(format!("{}{}", args, output)) + } else { Some(format!( "{}\n{}{}", args, offset.to_string(context.config), output.trim_left() )) - } else { - Some(format!("{}{}", args, output)) } } -- cgit 1.4.1-3-g733a5 From 6710f0dc9a08c458ddf7dc2ed5cb70f383046a96 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 20 Nov 2017 16:38:29 +0900 Subject: Do not squash unsafe block --- src/closures.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 8290f1b09a1..ebc12382bd7 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -256,7 +256,9 @@ pub fn rewrite_last_closure( ) -> Option { if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node { let body = match body.node { - ast::ExprKind::Block(ref block) if is_simple_block(block, context.codemap) => { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + { stmt_expr(&block.stmts[0]).unwrap_or(body) } _ => body, -- cgit 1.4.1-3-g733a5 From 34b0c9cf3fcf83a1f356b3d75430a0ac8b1f1790 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 21 Nov 2017 08:52:11 +0900 Subject: Do not give up when we run out of space when choosing rhs --- src/expr.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d3c3e760a27..ad74f11ddcd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2635,7 +2635,11 @@ pub fn rewrite_assign_rhs, R: Rewrite>( 0 }; // 1 = space between operator and rhs. - let orig_shape = shape.offset_left(last_line_width + 1)?; + let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { + width: 0, + offset: shape.offset + last_line_width + 1, + ..shape + }); let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; Some(lhs + &rhs) } -- cgit 1.4.1-3-g733a5 From 59ebde26f795c41665637d6d0a939a6711fe638a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 21 Nov 2017 08:52:43 +0900 Subject: Cargo fmt --- src/items.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3fe82f48ea5..a202a17d34f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -955,7 +955,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. if !type_param_bounds.is_empty() { - let ident_hi = context.codemap.span_after(item.span, &format!("{}", item.ident)); + let ident_hi = context + .codemap + .span_after(item.span, &format!("{}", item.ident)); let bound_hi = type_param_bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); if contains_comment(&snippet) { -- cgit 1.4.1-3-g733a5 From 53d7489221e4d6fa25bf624b78a80608c27aedf5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 23 Nov 2017 12:37:12 +0900 Subject: Force vertical layout when we find any kind of single line comments --- src/lists.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index b80d8d6541e..1e073945c0b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -137,10 +137,10 @@ impl ListItem { pub fn has_comment(&self) -> bool { self.pre_comment .as_ref() - .map_or(false, |comment| comment.starts_with("//")) + .map_or(false, |comment| comment.trim_left().starts_with("//")) || self.post_comment .as_ref() - .map_or(false, |comment| comment.starts_with("//")) + .map_or(false, |comment| comment.trim_left().starts_with("//")) } pub fn from_str>(s: S) -> ListItem { -- cgit 1.4.1-3-g733a5 From d92cfff43b2dc1ce43fdac172855a8d34bb79c8c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 23 Nov 2017 12:38:34 +0900 Subject: Align post comments with items when the it starts with newline --- src/lists.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 1e073945c0b..bf0d276574e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -410,7 +410,9 @@ where formatting.config.max_width(), )); } - let overhead = if let Some(max_width) = *item_max_width { + let overhead = if starts_with_newline(comment) { + 0 + } else if let Some(max_width) = *item_max_width { max_width + 2 } else { // 1 = space between item and comment. @@ -425,12 +427,17 @@ where || comment.trim().contains('\n') || comment.trim().len() > width; - rewrite_comment(comment, block_style, comment_shape, formatting.config) + rewrite_comment( + comment.trim_left(), + block_style, + comment_shape, + formatting.config, + ) }; let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; - if !starts_with_newline(&formatted_comment) { + if !starts_with_newline(&comment) { let mut comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); if first_line_width(&formatted_comment) + last_line_width(&result) @@ -448,6 +455,9 @@ where { result.push(' '); } + } else { + result.push('\n'); + result.push_str(&indent_str); } if formatted_comment.contains('\n') { item_max_width = None; -- cgit 1.4.1-3-g733a5 From d0f12b8ec8044200c09a9f3be2af59d026b85b83 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 13:08:02 +1300 Subject: Remove unused option `take_source_hints` --- Cargo.lock | 40 ++++++++++++++++++++-------------------- Configurations.md | 29 ----------------------------- src/config.rs | 2 -- tests/config/small_tabs.toml | 1 - tests/source/expr-no-hints.rs | 8 -------- tests/target/expr-no-hints.rs | 6 ------ 6 files changed, 20 insertions(+), 66 deletions(-) delete mode 100644 tests/source/expr-no-hints.rs delete mode 100644 tests/target/expr-no-hints.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 950f364c6c8..8341da37b04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,7 +55,7 @@ dependencies = [ [[package]] name = "lazy_static" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -115,10 +115,10 @@ dependencies = [ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "strings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -127,22 +127,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -151,18 +151,18 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "strings" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -200,7 +200,7 @@ name = "thread_local" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -209,7 +209,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -259,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" @@ -267,11 +267,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum serde 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "395993cac4e3599c7c1b70a6a92d3b3f55f4443df9f0b5294e362285ad7c9ecb" -"checksum serde_derive 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "7fa060f679fe2d5a9f7374dd4553dc907eba4f9acf183e4c7baf69eae02e6ca8" -"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" -"checksum serde_json 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ae1e67ce320daa7e494c578e34d4b00689f23bb94512fe0ca0dfaf02ea53fb67" -"checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" +"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e" +"checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" +"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" +"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" +"checksum strings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa481ee1bc42fc3df8195f91f7cb43cf8f2b71b48bac40bf5381cfaf7e481f3c" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" diff --git a/Configurations.md b/Configurations.md index 187d284fe84..219b7ced0c4 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2004,35 +2004,6 @@ fn lorem() { See also: [`hard_tabs`](#hard_tabs). -## `take_source_hints` - -Retain some formatting characteristics from the source code - -- **Default value**: `false` -- **Possible values**: `true`, `false` - -#### `false` (default): - -```rust -lorem - .ipsum() - .dolor(|| { sit.amet().consectetur().adipiscing().elit(); }); -``` - -#### `true`: - -```rust -lorem - .ipsum() - .dolor(|| { - sit.amet() - .consectetur() - .adipiscing() - .elit(); - }); -``` - -Note: This only applies if the call chain within the inner closure had already been formatted on separate lines before running rustfmt. ## `trailing_comma` diff --git a/src/config.rs b/src/config.rs index 9fbdfc2754b..51819028cbd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -596,8 +596,6 @@ create_config! { if-else expressions."; format_strings: bool, false, false, "Format string literals where necessary"; force_format_strings: bool, false, false, "Always format string literals"; - take_source_hints: bool, false, false, - "Retain some formatting characteristics from the source code"; hard_tabs: bool, false, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, false, "Break comments to fit on the line"; comment_width: usize, 80, false, diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 298094a7bc9..5b42f56ecdd 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -15,4 +15,3 @@ report_fixme = "Never" reorder_imports = false single_line_if_else_max_width = 0 format_strings = true -take_source_hints = true diff --git a/tests/source/expr-no-hints.rs b/tests/source/expr-no-hints.rs deleted file mode 100644 index 7329a742bac..00000000000 --- a/tests/source/expr-no-hints.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-take_source_hints: false -// We know best! - -fn main() { - a.b - .c - .d(); -} diff --git a/tests/target/expr-no-hints.rs b/tests/target/expr-no-hints.rs deleted file mode 100644 index 62dd64c28a6..00000000000 --- a/tests/target/expr-no-hints.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-take_source_hints: false -// We know best! - -fn main() { - a.b.c.d(); -} -- cgit 1.4.1-3-g733a5 From 4f65124422eb49e4474b8752c25614bf6ab5d013 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 13:19:36 +1300 Subject: Remove legacy option `fn_return_indent` --- Configurations.md | 42 ---------------------- src/config.rs | 10 ------ src/items.rs | 14 ++++---- tests/config/small_tabs.toml | 1 - tests/source/configs-fn_return_indent-with_args.rs | 6 ---- .../configs-fn_return_indent-with_where_clause.rs | 6 ---- tests/target/configs-fn_return_indent-with_args.rs | 16 --------- .../configs-fn_return_indent-with_where_clause.rs | 16 --------- 8 files changed, 6 insertions(+), 105 deletions(-) delete mode 100644 tests/source/configs-fn_return_indent-with_args.rs delete mode 100644 tests/source/configs-fn_return_indent-with_where_clause.rs delete mode 100644 tests/target/configs-fn_return_indent-with_args.rs delete mode 100644 tests/target/configs-fn_return_indent-with_where_clause.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 219b7ced0c4..d71a07e53b6 100644 --- a/Configurations.md +++ b/Configurations.md @@ -991,48 +991,6 @@ fn lorem() { See also [`control_brace_style`](#control_brace_style). -## `fn_return_indent` - -Location of return type in function declaration - -- **Default value**: `"WithArgs"` -- **Possible values**: `"WithArgs"`, `"WithWhereClause"` - -#### `"WithArgs"` (default): - -```rust -fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing) - -> Elit - where Ipsum: Eq -{ - // body -} - -``` - -#### `"WithWhereClause"`: - -```rust -fn lorem(ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing) - -> Elit - where Ipsum: Eq -{ - // body -} - -``` - -**Note**: This option only takes effect when `indent_style` is set to `"Visual"`. ## `fn_single_line` diff --git a/src/config.rs b/src/config.rs index 51819028cbd..1c3ecee904d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -63,14 +63,6 @@ configuration_option_enum! { ControlBraceStyle: AlwaysNextLine, } -// How to indent a function's return type. -configuration_option_enum! { ReturnIndent: - // Aligned with the arguments - WithArgs, - // Aligned with the where clause - WithWhereClause, -} - configuration_option_enum! { IndentStyle: // First line on the same line as the opening brace, all lines aligned with // the first line. @@ -557,8 +549,6 @@ create_config! { "Add trailing semicolon after break, continue and return"; fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - fn_return_indent: ReturnIndent, ReturnIndent::WithArgs, false, - "Location of return type in function declaration"; fn_args_paren_newline: bool, false, false, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; array_width: usize, 60, false, diff --git a/src/items.rs b/src/items.rs index 3fe82f48ea5..3d0a31639e6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; -use config::{BraceStyle, Config, Density, IndentStyle, ReturnIndent}; +use config::{BraceStyle, Config, Density, IndentStyle}; use expr::{choose_rhs, format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, @@ -1979,17 +1979,15 @@ fn rewrite_fn_base( } }; let ret_indent = if ret_should_indent { - let indent = match context.config.fn_return_indent() { - ReturnIndent::WithWhereClause => indent + 4, + let indent = if arg_str.is_empty() { // Aligning with non-existent args looks silly. - _ if arg_str.is_empty() => { - force_new_line_for_brace = true; - indent + 4 - } + force_new_line_for_brace = true; + indent + 4 + } else { // FIXME: we might want to check that using the arg indent // doesn't blow our budget, and if it does, then fallback to // the where clause indent. - _ => arg_indent, + arg_indent }; result.push('\n'); diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 5b42f56ecdd..e377446c013 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -3,7 +3,6 @@ comment_width = 80 tab_spaces = 2 newline_style = "Unix" brace_style = "SameLineWhere" -fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" where_density = "Tall" diff --git a/tests/source/configs-fn_return_indent-with_args.rs b/tests/source/configs-fn_return_indent-with_args.rs deleted file mode 100644 index 35d1459641a..00000000000 --- a/tests/source/configs-fn_return_indent-with_args.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_return_indent: WithArgs -// Function return type indent - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur, adipiscing: Adipiscing) -> Elit where Ipsum: Eq { - // body -} diff --git a/tests/source/configs-fn_return_indent-with_where_clause.rs b/tests/source/configs-fn_return_indent-with_where_clause.rs deleted file mode 100644 index 2fdbcd26572..00000000000 --- a/tests/source/configs-fn_return_indent-with_where_clause.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_return_indent: WithWhereClause -// Function return type indent - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur, adipiscing: Adipiscing) -> Elit where Ipsum: Eq { - // body -} diff --git a/tests/target/configs-fn_return_indent-with_args.rs b/tests/target/configs-fn_return_indent-with_args.rs deleted file mode 100644 index e1d49a65c25..00000000000 --- a/tests/target/configs-fn_return_indent-with_args.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_return_indent: WithArgs -// Function return type indent - -fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing, -) -> Elit -where - Ipsum: Eq, -{ - // body -} diff --git a/tests/target/configs-fn_return_indent-with_where_clause.rs b/tests/target/configs-fn_return_indent-with_where_clause.rs deleted file mode 100644 index 62a35af516b..00000000000 --- a/tests/target/configs-fn_return_indent-with_where_clause.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_return_indent: WithWhereClause -// Function return type indent - -fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing, -) -> Elit -where - Ipsum: Eq, -{ - // body -} -- cgit 1.4.1-3-g733a5 From 179b3c59de851f7f9fae4da0c39945ddeb73085f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 13:27:14 +1300 Subject: Remove legacy option `fn_args_paren_newline` --- Configurations.md | 33 ---------------------- legacy-rustfmt.toml | 1 - src/config.rs | 1 - src/items.rs | 7 ----- tests/config/small_tabs.toml | 1 - .../source/configs-fn_args_paren_newline-false.rs | 6 ---- tests/source/configs-fn_args_paren_newline-true.rs | 6 ---- .../target/configs-fn_args_paren_newline-false.rs | 11 -------- tests/target/configs-fn_args_paren_newline-true.rs | 12 -------- tests/target/issue-1624.rs | 3 -- 10 files changed, 81 deletions(-) delete mode 100644 tests/source/configs-fn_args_paren_newline-false.rs delete mode 100644 tests/source/configs-fn_args_paren_newline-true.rs delete mode 100644 tests/target/configs-fn_args_paren_newline-false.rs delete mode 100644 tests/target/configs-fn_args_paren_newline-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index d71a07e53b6..b7f8018b60d 100644 --- a/Configurations.md +++ b/Configurations.md @@ -806,39 +806,6 @@ trait Lorem { } ``` -## `fn_args_paren_newline` - -If function argument parenthesis goes on a newline - -- **Default value**: `false` -- **Possible values**: `true`, `false` - -#### `false` (default): - -```rust -fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, -) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { - // body -} -``` - -#### `true`: - -```rust -fn lorem - ( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, -) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { - // body -} -``` ## `brace_style` diff --git a/legacy-rustfmt.toml b/legacy-rustfmt.toml index 7c87391fef7..f976fa68e4c 100644 --- a/legacy-rustfmt.toml +++ b/legacy-rustfmt.toml @@ -1,3 +1,2 @@ indent_style = "Visual" combine_control_expr = false -fn_args_paren_newline = true diff --git a/src/config.rs b/src/config.rs index 1c3ecee904d..d3357f0370b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -549,7 +549,6 @@ create_config! { "Add trailing semicolon after break, continue and return"; fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - fn_args_paren_newline: bool, false, false, "If function argument parenthesis goes on a newline"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; array_width: usize, 60, false, "Maximum width of an array literal before falling back to vertical formatting"; diff --git a/src/items.rs b/src/items.rs index 3d0a31639e6..9ddb314d717 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1859,13 +1859,6 @@ fn rewrite_fn_base( if one_line_budget == 0 { if snuggle_angle_bracket { result.push('('); - } else if context.config.fn_args_paren_newline() { - result.push('\n'); - result.push_str(&arg_indent.to_string(context.config)); - if context.config.indent_style() == IndentStyle::Visual { - arg_indent = arg_indent + 1; // extra space for `(` - } - result.push('('); } else { result.push_str("("); if context.config.indent_style() == IndentStyle::Visual { diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index e377446c013..298ca5af9bd 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -3,7 +3,6 @@ comment_width = 80 tab_spaces = 2 newline_style = "Unix" brace_style = "SameLineWhere" -fn_args_paren_newline = true fn_args_density = "Tall" where_density = "Tall" where_layout = "Vertical" diff --git a/tests/source/configs-fn_args_paren_newline-false.rs b/tests/source/configs-fn_args_paren_newline-false.rs deleted file mode 100644 index edffeb14044..00000000000 --- a/tests/source/configs-fn_args_paren_newline-false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_args_paren_newline: false -// Function arguments parenthesis on a newline - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/source/configs-fn_args_paren_newline-true.rs b/tests/source/configs-fn_args_paren_newline-true.rs deleted file mode 100644 index d60c510b6cf..00000000000 --- a/tests/source/configs-fn_args_paren_newline-true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_args_paren_newline: true -// Function arguments parenthesis on a newline - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/target/configs-fn_args_paren_newline-false.rs b/tests/target/configs-fn_args_paren_newline-false.rs deleted file mode 100644 index 031d39014b3..00000000000 --- a/tests/target/configs-fn_args_paren_newline-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_args_paren_newline: false -// Function arguments parenthesis on a newline - -fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, -) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/target/configs-fn_args_paren_newline-true.rs b/tests/target/configs-fn_args_paren_newline-true.rs deleted file mode 100644 index 50e9e6484d8..00000000000 --- a/tests/target/configs-fn_args_paren_newline-true.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-fn_args_paren_newline: true -// Function arguments parenthesis on a newline - -fn lorem - ( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, -) -> DolorSitAmetConsecteturAdipiscingElitLoremIpsumDolorSitAmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/target/issue-1624.rs b/tests/target/issue-1624.rs index 7385118528b..477fc27353f 100644 --- a/tests/target/issue-1624.rs +++ b/tests/target/issue-1624.rs @@ -1,6 +1,3 @@ -// rustfmt-indent_style: Block -// rustfmt-fn_args_paren_newline: false - // #1624 pub unsafe fn some_long_function_name( arg1: Type1, -- cgit 1.4.1-3-g733a5 From 8a7b6b88068fd2e1d06d9a16444783e07f93316a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 14:01:44 +1300 Subject: Remove `match_pattern_separator_break_point` in favour of `binop_separator` --- Configurations.md | 33 ---------------------- src/config.rs | 2 -- src/expr.rs | 2 +- ...gs-match_pattern_separator_break_point-Front.rs | 9 ------ ...gs-match_pattern_separator_break_point-Front.rs | 12 -------- 5 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 tests/source/configs-match_pattern_separator_break_point-Front.rs delete mode 100644 tests/target/configs-match_pattern_separator_break_point-Front.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index b7f8018b60d..6f56ce6b8bc 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1283,39 +1283,6 @@ match lorem { See also: [`indent_match_arms`](#indent_match_arms), [`trailing_comma`](#trailing_comma), [`wrap_match_arms`](#wrap_match_arms). -## `match_pattern_separator_break_point` - -Put a match sub-patterns' separator (`|`) in front or back. - -- **Default value**: `"Back"` -- **Possible values**: `"Back"`, `"Front"` - -#### `"Back"` (default): - -```rust -match m { - Variant::Tag | - Variant::Tag2 | - Variant::Tag3 | - Variant::Tag4 | - Variant::Tag5 | - Variant::Tag6 => {} -} -``` - -#### `Front`: - -```rust -match m { - Variant::Tag - | Variant::Tag2 - | Variant::Tag3 - | Variant::Tag4 - | Variant::Tag5 - | Variant::Tag6 => {} -} -``` - ## `max_width` Maximum width of each line diff --git a/src/config.rs b/src/config.rs index d3357f0370b..59818f237c8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -598,8 +598,6 @@ create_config! { "Force match arm bodies to be in a new lines"; indent_match_arms: bool, true, false, "Indent match arms instead of keeping them at the same \ indentation level as the match keyword"; - match_pattern_separator_break_point: SeparatorPlace, SeparatorPlace::Front, false, - "Put a match sub-patterns' separator in front or back."; space_before_colon: bool, false, false, "Leave a space before the colon"; space_after_colon: bool, true, false, "Leave a space after the colon"; spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; diff --git a/src/expr.rs b/src/expr.rs index d3c3e760a27..f483736855d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1475,7 +1475,7 @@ fn rewrite_match_pattern( tactic: tactic, separator: " |", trailing_separator: SeparatorTactic::Never, - separator_place: context.config.match_pattern_separator_break_point(), + separator_place: context.config.binop_separator(), shape: pat_shape, ends_with_newline: false, preserve_newline: false, diff --git a/tests/source/configs-match_pattern_separator_break_point-Front.rs b/tests/source/configs-match_pattern_separator_break_point-Front.rs deleted file mode 100644 index 68a79bb0ab0..00000000000 --- a/tests/source/configs-match_pattern_separator_break_point-Front.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-match_pattern_separator_break_point: Front -// Whether `|` goes to front or to back. - -fn main() { - match lorem { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | cccccccccccccccccccccccccccccccccccccccc | dddddddddddddddddddddddddddddddddddddddd => (), - _ => (), - } -} diff --git a/tests/target/configs-match_pattern_separator_break_point-Front.rs b/tests/target/configs-match_pattern_separator_break_point-Front.rs deleted file mode 100644 index d6cb87e0121..00000000000 --- a/tests/target/configs-match_pattern_separator_break_point-Front.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-match_pattern_separator_break_point: Front -// Whether `|` goes to front or to back. - -fn main() { - match lorem { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - | cccccccccccccccccccccccccccccccccccccccc - | dddddddddddddddddddddddddddddddddddddddd => (), - _ => (), - } -} -- cgit 1.4.1-3-g733a5 From 4cb474b5ee1bbc8b771cc2a2d88944c06aaaf0f6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 14:07:37 +1300 Subject: Remove `force_format_strings` in favour of `format_strings` --- Configurations.md | 13 +-------- src/config.rs | 1 - src/expr.rs | 31 +--------------------- tests/source/configs-force_format_strings-false.rs | 9 ------- tests/source/configs-force_format_strings-true.rs | 8 ------ tests/source/long-match-arms-brace-newline.rs | 1 - tests/source/string-lit.rs | 2 +- tests/target/configs-force_format_strings-false.rs | 9 ------- tests/target/configs-force_format_strings-true.rs | 10 ------- tests/target/long-match-arms-brace-newline.rs | 1 - tests/target/string-lit.rs | 2 +- 11 files changed, 4 insertions(+), 83 deletions(-) delete mode 100644 tests/source/configs-force_format_strings-false.rs delete mode 100644 tests/source/configs-force_format_strings-true.rs delete mode 100644 tests/target/configs-force_format_strings-false.rs delete mode 100644 tests/target/configs-force_format_strings-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 6f56ce6b8bc..946689e940b 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1017,17 +1017,6 @@ extern { } ``` -## `force_format_strings` - -Always format string literals - -- **Default value**: `false` -- **Possible values**: `true`, `false` - -See [`format_strings`](#format_strings). - -See also [`max_width`](#max_width). - ## `format_strings` Format string literals where necessary @@ -1049,7 +1038,7 @@ let lorem = adipiscing elit lorem ipsum dolor sit"; ``` -See also [`force_format_strings`](#force_format_strings), [`max_width`](#max_width). +See also [`max_width`](#max_width). ## `hard_tabs` diff --git a/src/config.rs b/src/config.rs index 59818f237c8..75fff0131f4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -584,7 +584,6 @@ create_config! { expressions. A value of zero means always break \ if-else expressions."; format_strings: bool, false, false, "Format string literals where necessary"; - force_format_strings: bool, false, false, "Always format string literals"; hard_tabs: bool, false, false, "Use tab characters for indentation, spaces for alignment"; wrap_comments: bool, false, false, "Break comments to fit on the line"; comment_width: usize, 80, false, diff --git a/src/expr.rs b/src/expr.rs index f483736855d..ad8cb25b53f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1739,7 +1739,7 @@ pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { let string_lit = context.snippet(span); - if !context.config.format_strings() && !context.config.force_format_strings() { + if !context.config.format_strings() { if string_lit .lines() .rev() @@ -1767,12 +1767,6 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt } } - if !context.config.force_format_strings() - && !string_requires_rewrite(context, span, &string_lit, shape) - { - return wrap_str(string_lit, context.config.max_width(), shape); - } - // Remove the quote characters. let str_lit = &string_lit[1..string_lit.len() - 1]; @@ -1783,29 +1777,6 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } -fn string_requires_rewrite( - context: &RewriteContext, - span: Span, - string: &str, - shape: Shape, -) -> bool { - if context.codemap.lookup_char_pos(span.lo()).col.0 != shape.indent.width() { - return true; - } - - for (i, line) in string.lines().enumerate() { - if i == 0 { - if line.len() > shape.width { - return true; - } - } else if line.len() > shape.width + shape.indent.width() { - return true; - } - } - - false -} - pub fn rewrite_call( context: &RewriteContext, callee: &str, diff --git a/tests/source/configs-force_format_strings-false.rs b/tests/source/configs-force_format_strings-false.rs deleted file mode 100644 index 49f32c557b3..00000000000 --- a/tests/source/configs-force_format_strings-false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-force_format_strings: false -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/tests/source/configs-force_format_strings-true.rs b/tests/source/configs-force_format_strings-true.rs deleted file mode 100644 index 7a87bed4d15..00000000000 --- a/tests/source/configs-force_format_strings-true.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-force_format_strings: true -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/tests/source/long-match-arms-brace-newline.rs b/tests/source/long-match-arms-brace-newline.rs index bc5c9deef68..927ada0ffb2 100644 --- a/tests/source/long-match-arms-brace-newline.rs +++ b/tests/source/long-match-arms-brace-newline.rs @@ -1,5 +1,4 @@ // rustfmt-format_strings: true -// rustfmt-force_format_strings: true // rustfmt-max_width: 80 // rustfmt-control_brace_style: AlwaysNextLine diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs index b282656d470..e86f65f9f52 100644 --- a/tests/source/string-lit.rs +++ b/tests/source/string-lit.rs @@ -1,4 +1,4 @@ -// rustfmt-force_format_strings: true +// rustfmt-format_strings: true // rustfmt-error_on_line_overflow: false // Long string literals diff --git a/tests/target/configs-force_format_strings-false.rs b/tests/target/configs-force_format_strings-false.rs deleted file mode 100644 index 49f32c557b3..00000000000 --- a/tests/target/configs-force_format_strings-false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-force_format_strings: false -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/tests/target/configs-force_format_strings-true.rs b/tests/target/configs-force_format_strings-true.rs deleted file mode 100644 index 49ba3e7d46c..00000000000 --- a/tests/target/configs-force_format_strings-true.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-force_format_strings: true -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet \ - consectetur adipiscing elit \ - lorem ipsum dolor sit"; -} diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs index da82d971593..aeb384e7203 100644 --- a/tests/target/long-match-arms-brace-newline.rs +++ b/tests/target/long-match-arms-brace-newline.rs @@ -1,5 +1,4 @@ // rustfmt-format_strings: true -// rustfmt-force_format_strings: true // rustfmt-max_width: 80 // rustfmt-control_brace_style: AlwaysNextLine diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs index 97cf0213a16..f60002ac618 100644 --- a/tests/target/string-lit.rs +++ b/tests/target/string-lit.rs @@ -1,4 +1,4 @@ -// rustfmt-force_format_strings: true +// rustfmt-format_strings: true // rustfmt-error_on_line_overflow: false // Long string literals -- cgit 1.4.1-3-g733a5 From d00c60df5cfa714b24182925bc3631392adfd0dc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 14:12:54 +1300 Subject: Remove `chain_split_single_child` option --- Configurations.md | 21 --------------------- src/chains.rs | 2 +- src/config.rs | 2 -- .../configs-chain_split_single_child-false.rs | 5 ----- .../target/configs-chain_split_single_child-true.rs | 6 ------ 5 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 tests/target/configs-chain_split_single_child-false.rs delete mode 100644 tests/target/configs-chain_split_single_child-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 946689e940b..45fda5beaee 100644 --- a/Configurations.md +++ b/Configurations.md @@ -440,27 +440,6 @@ let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); #### Lines longer than `chain_width`: See [`chain_indent`](#chain_indent). -## `chain_split_single_child` - -Split a chain with a single child if its length exceeds [`chain_width`](#chain_width). - -- **Default value**: `false` -- **Possible values**: `false`, `true` - -#### `false` (default): - -```rust -let files = fs::read_dir("tests/coverage/source").expect("Couldn't read source dir"); -``` - -#### `true`: - -```rust -let files = fs::read_dir("tests/coverage/source") - .expect("Couldn't read source dir"); -``` - -See also [`chain_width`](#chain_width). ## `combine_control_expr` diff --git a/src/chains.rs b/src/chains.rs index 8a4b4257891..526eebfd262 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -158,7 +158,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } else { rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() } + suffix_try_num; - let one_line_budget = if rewrites.is_empty() && !context.config.chain_split_single_child() { + let one_line_budget = if rewrites.is_empty() { shape.width } else { min(shape.width, context.config.chain_width()) diff --git a/src/config.rs b/src/config.rs index 75fff0131f4..2eae8867527 100644 --- a/src/config.rs +++ b/src/config.rs @@ -570,8 +570,6 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; chain_width: usize, 60, false, "Maximum length of a chain to fit on a single line"; - chain_split_single_child: bool, false, false, "Split a chain with a single child if its length \ - exceeds `chain_width`"; imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; diff --git a/tests/target/configs-chain_split_single_child-false.rs b/tests/target/configs-chain_split_single_child-false.rs deleted file mode 100644 index 1863c6ac33f..00000000000 --- a/tests/target/configs-chain_split_single_child-false.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-chain_split_single_child: false - -fn main() { - let files = fs::read_dir("tests/source").expect("Couldn't read source dir"); -} diff --git a/tests/target/configs-chain_split_single_child-true.rs b/tests/target/configs-chain_split_single_child-true.rs deleted file mode 100644 index 154fa0bfa2e..00000000000 --- a/tests/target/configs-chain_split_single_child-true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-chain_split_single_child: true - -fn main() { - let files = fs::read_dir("tests/source") - .expect("Couldn't read source dir"); -} -- cgit 1.4.1-3-g733a5 From 20805acf42e1bc78c0434276b71309df0a583045 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 14:29:44 +1300 Subject: Merge `attributes_on_same_line_as_field` and `attributes_on_same_line_as_variant` into `same_line_attributes` --- Configurations.md | 32 ++++++---------------- src/config.rs | 6 ++-- src/items.rs | 6 ++-- src/vertical.rs | 4 +-- ...nfigs-attributes_on_same_line_as_field-false.rs | 17 ------------ ...onfigs-attributes_on_same_line_as_field-true.rs | 11 -------- ...igs-attributes_on_same_line_as_variant-false.rs | 11 -------- ...figs-attributes_on_same_line_as_variant-true.rs | 11 -------- ...nfigs-attributes_on_same_line_as_field-false.rs | 17 ------------ ...onfigs-attributes_on_same_line_as_field-true.rs | 8 ------ ...igs-attributes_on_same_line_as_variant-false.rs | 11 -------- ...figs-attributes_on_same_line_as_variant-true.rs | 8 ------ 12 files changed, 15 insertions(+), 127 deletions(-) delete mode 100644 tests/source/configs-attributes_on_same_line_as_field-false.rs delete mode 100644 tests/source/configs-attributes_on_same_line_as_field-true.rs delete mode 100644 tests/source/configs-attributes_on_same_line_as_variant-false.rs delete mode 100644 tests/source/configs-attributes_on_same_line_as_variant-true.rs delete mode 100644 tests/target/configs-attributes_on_same_line_as_field-false.rs delete mode 100644 tests/target/configs-attributes_on_same_line_as_field-true.rs delete mode 100644 tests/target/configs-attributes_on_same_line_as_variant-false.rs delete mode 100644 tests/target/configs-attributes_on_same_line_as_variant-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 45fda5beaee..c7fae70d1dd 100644 --- a/Configurations.md +++ b/Configurations.md @@ -296,9 +296,9 @@ let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", " #### Lines longer than `array_width`: See [`indent_style`](#indent_style). -## `attributes_on_same_line_as_field` +## `same_line_attributes` -Try to put attributes on the same line as fields +Try to put attributes on the same line as fields and variants - **Default value**: `true` - **Possible values**: `true`, `false` @@ -311,6 +311,12 @@ struct Lorem { #[serde(rename = "Dolor")] dolor: usize, #[serde(rename = "Amet")] amet: usize, } + +enum Lorem { + #[serde(skip_serializing)] Ipsum, + #[serde(skip_serializing)] Dolor, + #[serde(skip_serializing)] Amet, +} ``` #### `false`: @@ -324,28 +330,7 @@ struct Lorem { #[serde(rename = "Amet")] amet: usize, } -``` - -## `attributes_on_same_line_as_variant` - -Try to put attributes on the same line as variants - -- **Default value**: `true` -- **Possible values**: `true`, `false` - -#### `true` (default): - -```rust -enum Lorem { - #[serde(skip_serializing)] Ipsum, - #[serde(skip_serializing)] Dolor, - #[serde(skip_serializing)] Amet, -} -``` - -#### `false`: -```rust enum Lorem { #[serde(skip_serializing)] Ipsum, @@ -356,6 +341,7 @@ enum Lorem { } ``` + ## `binop_separator` Where to put a binary operator when a binary expression goes multiline. diff --git a/src/config.rs b/src/config.rs index 2eae8867527..ebbe67dada5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -613,10 +613,8 @@ create_config! { threshold."; remove_blank_lines_at_start_or_end_of_block: bool, true, false, "Remove blank lines at start or end of a block"; - attributes_on_same_line_as_field: bool, true, false, - "Try to put attributes on the same line as fields."; - attributes_on_same_line_as_variant: bool, true, false, - "Try to put attributes on the same line as variants in enum declarations."; + same_line_attributes: bool, true, false, + "Try to put attributes on the same line as fields and variants."; multiline_closure_forces_block: bool, false, false, "Force multiline closure bodies to be wrapped in a block"; multiline_match_arm_forces_block: bool, false, false, diff --git a/src/items.rs b/src/items.rs index 9ddb314d717..c99a4db0fdf 100644 --- a/src/items.rs +++ b/src/items.rs @@ -567,8 +567,7 @@ impl<'a> FmtVisitor<'a> { }; let attrs_extendable = attrs_str.is_empty() - || (context.config.attributes_on_same_line_as_variant() - && is_attributes_extendable(&attrs_str)); + || (context.config.same_line_attributes() && is_attributes_extendable(&attrs_str)); combine_strs_with_missing_comments( &context, &attrs_str, @@ -1450,8 +1449,7 @@ pub fn rewrite_struct_field( let attrs_str = field.attrs.rewrite(context, shape)?; let attrs_extendable = attrs_str.is_empty() - || (context.config.attributes_on_same_line_as_field() - && is_attributes_extendable(&attrs_str)); + || (context.config.same_line_attributes() && is_attributes_extendable(&attrs_str)); let missing_span = if field.attrs.is_empty() { mk_sp(field.span.lo(), field.span.lo()) } else { diff --git a/src/vertical.rs b/src/vertical.rs index bb4bad7852e..d3b35677407 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -54,8 +54,8 @@ impl AlignedItem for ast::StructField { } else { mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; - let attrs_extendable = context.config.attributes_on_same_line_as_field() - && is_attributes_extendable(&attrs_str); + let attrs_extendable = + context.config.same_line_attributes() && is_attributes_extendable(&attrs_str); rewrite_struct_field_prefix(context, self).and_then(|field_str| { combine_strs_with_missing_comments( context, diff --git a/tests/source/configs-attributes_on_same_line_as_field-false.rs b/tests/source/configs-attributes_on_same_line_as_field-false.rs deleted file mode 100644 index 202d3e56aee..00000000000 --- a/tests/source/configs-attributes_on_same_line_as_field-false.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-attributes_on_same_line_as_field: false -// Option to place attributes on the same line as fields where possible - -struct Lorem { - #[ serde(rename = "Ipsum") ] - ipsum: usize, - #[ serde(rename = "Dolor") ] - dolor: usize, - #[ serde(rename = "Amet") ] - amet: usize, -} - -// #1943 -pub struct Bzip2 { - # [ serde (rename = "level") ] - level: i32 , -} diff --git a/tests/source/configs-attributes_on_same_line_as_field-true.rs b/tests/source/configs-attributes_on_same_line_as_field-true.rs deleted file mode 100644 index 3258c754e50..00000000000 --- a/tests/source/configs-attributes_on_same_line_as_field-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-attributes_on_same_line_as_field: true -// Option to place attributes on the same line as fields where possible - -struct Lorem { - #[ serde(rename = "Ipsum") ] - ipsum: usize, - #[ serde(rename = "Dolor") ] - dolor: usize, - #[ serde(rename = "Amet") ] - amet: usize, -} diff --git a/tests/source/configs-attributes_on_same_line_as_variant-false.rs b/tests/source/configs-attributes_on_same_line_as_variant-false.rs deleted file mode 100644 index d3456b7087c..00000000000 --- a/tests/source/configs-attributes_on_same_line_as_variant-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-attributes_on_same_line_as_variant: false -// Option to place attributes on the same line as variants where possible - -enum Lorem { - #[ serde(skip_serializing) ] - Ipsum, - #[ serde(skip_serializing) ] - Dolor, - #[ serde(skip_serializing) ] - Amet, -} diff --git a/tests/source/configs-attributes_on_same_line_as_variant-true.rs b/tests/source/configs-attributes_on_same_line_as_variant-true.rs deleted file mode 100644 index 0f7d98f200a..00000000000 --- a/tests/source/configs-attributes_on_same_line_as_variant-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-attributes_on_same_line_as_variant: true -// Option to place attributes on the same line as variants where possible - -enum Lorem { - #[ serde(skip_serializing) ] - Ipsum, - #[ serde(skip_serializing) ] - Dolor, - #[ serde(skip_serializing) ] - Amet, -} diff --git a/tests/target/configs-attributes_on_same_line_as_field-false.rs b/tests/target/configs-attributes_on_same_line_as_field-false.rs deleted file mode 100644 index 98c3c4b791c..00000000000 --- a/tests/target/configs-attributes_on_same_line_as_field-false.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-attributes_on_same_line_as_field: false -// Option to place attributes on the same line as fields where possible - -struct Lorem { - #[serde(rename = "Ipsum")] - ipsum: usize, - #[serde(rename = "Dolor")] - dolor: usize, - #[serde(rename = "Amet")] - amet: usize, -} - -// #1943 -pub struct Bzip2 { - #[serde(rename = "level")] - level: i32, -} diff --git a/tests/target/configs-attributes_on_same_line_as_field-true.rs b/tests/target/configs-attributes_on_same_line_as_field-true.rs deleted file mode 100644 index 3261fa24ea0..00000000000 --- a/tests/target/configs-attributes_on_same_line_as_field-true.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-attributes_on_same_line_as_field: true -// Option to place attributes on the same line as fields where possible - -struct Lorem { - #[serde(rename = "Ipsum")] ipsum: usize, - #[serde(rename = "Dolor")] dolor: usize, - #[serde(rename = "Amet")] amet: usize, -} diff --git a/tests/target/configs-attributes_on_same_line_as_variant-false.rs b/tests/target/configs-attributes_on_same_line_as_variant-false.rs deleted file mode 100644 index 3442a10915a..00000000000 --- a/tests/target/configs-attributes_on_same_line_as_variant-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-attributes_on_same_line_as_variant: false -// Option to place attributes on the same line as variants where possible - -enum Lorem { - #[serde(skip_serializing)] - Ipsum, - #[serde(skip_serializing)] - Dolor, - #[serde(skip_serializing)] - Amet, -} diff --git a/tests/target/configs-attributes_on_same_line_as_variant-true.rs b/tests/target/configs-attributes_on_same_line_as_variant-true.rs deleted file mode 100644 index 0bced842c75..00000000000 --- a/tests/target/configs-attributes_on_same_line_as_variant-true.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-attributes_on_same_line_as_variant: true -// Option to place attributes on the same line as variants where possible - -enum Lorem { - #[serde(skip_serializing)] Ipsum, - #[serde(skip_serializing)] Dolor, - #[serde(skip_serializing)] Amet, -} -- cgit 1.4.1-3-g733a5 From 45d4f7a2dd1c95e47d4ae4dc413dfb71e53c16ff Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 14:45:18 +1300 Subject: struct_lit_multiline_style -> struct_lit_single_line (and make it a bool) --- Configurations.md | 16 ++++++++-------- src/config.rs | 20 ++------------------ src/expr.rs | 5 ++--- src/lists.rs | 3 ++- ...configs-struct_lit_multiline_style-force_multi.rs | 6 ------ ...nfigs-struct_lit_multiline_style-prefer_single.rs | 7 ------- tests/source/configs-struct_lit_single_line-false.rs | 6 ++++++ tests/source/configs-struct_lit_single_line-true.rs | 7 +++++++ tests/source/struct_lits_multiline.rs | 2 +- tests/source/struct_lits_visual_multiline.rs | 2 +- ...configs-struct_lit_multiline_style-force_multi.rs | 9 --------- ...nfigs-struct_lit_multiline_style-prefer_single.rs | 7 ------- tests/target/configs-struct_lit_single_line-false.rs | 9 +++++++++ tests/target/configs-struct_lit_single_line-true.rs | 7 +++++++ tests/target/struct_lits_multiline.rs | 2 +- tests/target/struct_lits_visual_multiline.rs | 2 +- 16 files changed, 47 insertions(+), 63 deletions(-) delete mode 100644 tests/source/configs-struct_lit_multiline_style-force_multi.rs delete mode 100644 tests/source/configs-struct_lit_multiline_style-prefer_single.rs create mode 100644 tests/source/configs-struct_lit_single_line-false.rs create mode 100644 tests/source/configs-struct_lit_single_line-true.rs delete mode 100644 tests/target/configs-struct_lit_multiline_style-force_multi.rs delete mode 100644 tests/target/configs-struct_lit_multiline_style-prefer_single.rs create mode 100644 tests/target/configs-struct_lit_single_line-false.rs create mode 100644 tests/target/configs-struct_lit_single_line-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index c7fae70d1dd..275d4883760 100644 --- a/Configurations.md +++ b/Configurations.md @@ -246,7 +246,7 @@ let lorem = Lorem { ipsum: dolor, sit: amet, }; ``` -See also: [`struct_lit_multiline_style`](#struct_lit_multiline_style), [`indent_style`](#indent_style). +See also: [`struct_lit_single_line`](#struct_lit_single_line), [`indent_style`](#indent_style). ### Where predicates @@ -1746,20 +1746,20 @@ let lorem: [ usize; 2 ] = [ ipsum, dolor ]; See also: [`spaces_within_parens_and_brackets`](#spaces_within_parens_and_brackets), [`spaces_within_parens_and_brackets`](#spaces_within_parens_and_brackets). -## `struct_lit_multiline_style` +## `struct_lit_single_line` -Multiline style on literal structs +Put small struct literals on a single line -- **Default value**: `"PreferSingle"` -- **Possible values**: `"ForceMulti"`, `"PreferSingle"` +- **Default value**: `true` +- **Possible values**: `true`, `false` -#### `"PreferSingle"` (default): +#### `true` (default): ```rust let lorem = Lorem { ipsum: dolor, sit: amet }; ``` -#### `"ForceMulti"`: +#### `false`: ```rust let lorem = Lorem { @@ -1787,7 +1787,7 @@ let lorem = Lorem { ipsum: dolor, sit: amet }; #### Lines longer than `struct_lit_width`: See [`indent_style`](#indent_style). -See also: [`struct_lit_multiline_style`](#struct_lit_multiline_style), [`indent_style`](#indent_style). +See also: [`struct_lit_single_line`](#struct_lit_single_line), [`indent_style`](#indent_style). ## `struct_variant_width` diff --git a/src/config.rs b/src/config.rs index ebbe67dada5..88af2b5e0a0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -100,22 +100,6 @@ impl Density { } } -configuration_option_enum! { MultilineStyle: - // Use horizontal layout if it fits in one line, fall back to vertical - PreferSingle, - // Use vertical layout - ForceMulti, -} - -impl MultilineStyle { - pub fn to_list_tactic(self) -> ListTactic { - match self { - MultilineStyle::PreferSingle => ListTactic::HorizontalVertical, - MultilineStyle::ForceMulti => ListTactic::Vertical, - } - } -} - configuration_option_enum! { ReportTactic: Always, Unnumbered, @@ -563,8 +547,8 @@ create_config! { where_density: Density, Density::Vertical, false, "Density of a where clause"; where_single_line: bool, false, false, "To force single line where layout"; where_layout: ListTactic, ListTactic::Vertical, false, "Element layout inside a where clause"; - struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, false, - "Multiline style on literal structs"; + struct_lit_single_line: bool, true, false, + "Put small struct literals on a single line"; report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, diff --git a/src/expr.rs b/src/expr.rs index ad8cb25b53f..b9c33a52be7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -21,7 +21,7 @@ use closures; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, FindUncommented}; -use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle}; +use config::{Config, ControlBraceStyle, IndentStyle}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -2346,8 +2346,7 @@ pub fn wrap_struct_field( one_line_width: usize, ) -> String { if context.config.indent_style() == IndentStyle::Block - && (fields_str.contains('\n') - || context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti + && (fields_str.contains('\n') || !context.config.struct_lit_single_line() || fields_str.len() > one_line_width) { format!( diff --git a/src/lists.rs b/src/lists.rs index bf0d276574e..5f8149c6f3e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -796,7 +796,8 @@ pub fn struct_lit_tactic( if let Some(h_shape) = h_shape { let prelim_tactic = match (context.config.indent_style(), items.len()) { (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ => context.config.struct_lit_multiline_style().to_list_tactic(), + _ if context.config.struct_lit_single_line() => ListTactic::HorizontalVertical, + _ => ListTactic::Vertical, }; definitive_tactic(items, prelim_tactic, Separator::Comma, h_shape.width) } else { diff --git a/tests/source/configs-struct_lit_multiline_style-force_multi.rs b/tests/source/configs-struct_lit_multiline_style-force_multi.rs deleted file mode 100644 index 42e1b088bd1..00000000000 --- a/tests/source/configs-struct_lit_multiline_style-force_multi.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-struct_lit_multiline_style: ForceMulti -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs-struct_lit_multiline_style-prefer_single.rs b/tests/source/configs-struct_lit_multiline_style-prefer_single.rs deleted file mode 100644 index 9a4ac481335..00000000000 --- a/tests/source/configs-struct_lit_multiline_style-prefer_single.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-struct_lit_multiline_style: PreferSingle -// rustfmt-struct_lit_width: 100 -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs-struct_lit_single_line-false.rs b/tests/source/configs-struct_lit_single_line-false.rs new file mode 100644 index 00000000000..17cad8dde29 --- /dev/null +++ b/tests/source/configs-struct_lit_single_line-false.rs @@ -0,0 +1,6 @@ +// rustfmt-struct_lit_single_line: false +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/tests/source/configs-struct_lit_single_line-true.rs b/tests/source/configs-struct_lit_single_line-true.rs new file mode 100644 index 00000000000..363bf5b114e --- /dev/null +++ b/tests/source/configs-struct_lit_single_line-true.rs @@ -0,0 +1,7 @@ +// rustfmt-struct_lit_single_line: true +// rustfmt-struct_lit_width: 100 +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs index 120cc93471a..256ba1bbda3 100644 --- a/tests/source/struct_lits_multiline.rs +++ b/tests/source/struct_lits_multiline.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true -// rustfmt-struct_lit_multiline_style: ForceMulti +// rustfmt-struct_lit_single_line: false // Struct literal expressions. diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs index 074853cf3da..d0b5ea6efba 100644 --- a/tests/source/struct_lits_visual_multiline.rs +++ b/tests/source/struct_lits_visual_multiline.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-indent_style: Visual -// rustfmt-struct_lit_multiline_style: ForceMulti +// rustfmt-struct_lit_single_line: false // rustfmt-error_on_line_overflow: false // Struct literal expressions. diff --git a/tests/target/configs-struct_lit_multiline_style-force_multi.rs b/tests/target/configs-struct_lit_multiline_style-force_multi.rs deleted file mode 100644 index 1abd2f09d9c..00000000000 --- a/tests/target/configs-struct_lit_multiline_style-force_multi.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-struct_lit_multiline_style: ForceMulti -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { - ipsum: dolor, - sit: amet, - }; -} diff --git a/tests/target/configs-struct_lit_multiline_style-prefer_single.rs b/tests/target/configs-struct_lit_multiline_style-prefer_single.rs deleted file mode 100644 index 9a4ac481335..00000000000 --- a/tests/target/configs-struct_lit_multiline_style-prefer_single.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-struct_lit_multiline_style: PreferSingle -// rustfmt-struct_lit_width: 100 -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/target/configs-struct_lit_single_line-false.rs b/tests/target/configs-struct_lit_single_line-false.rs new file mode 100644 index 00000000000..e2732b5a7c9 --- /dev/null +++ b/tests/target/configs-struct_lit_single_line-false.rs @@ -0,0 +1,9 @@ +// rustfmt-struct_lit_single_line: false +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; +} diff --git a/tests/target/configs-struct_lit_single_line-true.rs b/tests/target/configs-struct_lit_single_line-true.rs new file mode 100644 index 00000000000..363bf5b114e --- /dev/null +++ b/tests/target/configs-struct_lit_single_line-true.rs @@ -0,0 +1,7 @@ +// rustfmt-struct_lit_single_line: true +// rustfmt-struct_lit_width: 100 +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index 0eb7b8b759f..c831dc7a8ba 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -1,6 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true -// rustfmt-struct_lit_multiline_style: ForceMulti +// rustfmt-struct_lit_single_line: false // Struct literal expressions. diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs index 936a4061cb4..2809d3a2612 100644 --- a/tests/target/struct_lits_visual_multiline.rs +++ b/tests/target/struct_lits_visual_multiline.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true // rustfmt-indent_style: Visual -// rustfmt-struct_lit_multiline_style: ForceMulti +// rustfmt-struct_lit_single_line: false // rustfmt-error_on_line_overflow: false // Struct literal expressions. -- cgit 1.4.1-3-g733a5 From e5bcb2259aefd3c811a71e68cf2a7cf9d918c0ee Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 15:17:41 +1300 Subject: Reorganise config options and stabilise a few --- src/config.rs | 139 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 88af2b5e0a0..f30f0039ccd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -501,45 +501,44 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { create_config! { + // Fundamental stuff + max_width: usize, 100, true, "Maximum width of each line"; + hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; + tab_spaces: usize, 4, true, "Number of spaces per tab"; + newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; - unstable_features: bool, false, true, - "Enables unstable features. Only available on nightly channel"; - verbose: bool, false, false, "Use verbose output"; - disable_all_formatting: bool, false, false, "Don't reformat anything"; - skip_children: bool, false, false, "Don't reformat out of line modules"; - file_lines: FileLines, FileLines::all(), false, - "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ - via the --file-lines option"; - max_width: usize, 100, false, "Maximum width of each line"; - error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; - error_on_line_overflow_comments: bool, true, false, - "Error if unable to get comments within max_width"; - tab_spaces: usize, 4, false, "Number of spaces per tab"; + + // strings and comments + format_strings: bool, false, false, "Format string literals where necessary"; + wrap_comments: bool, false, true, "Break comments to fit on the line"; + comment_width: usize, 80, false, + "Maximum length of comments. No effect unless wrap_comments = true"; + normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; + + // Width heuristics fn_call_width: usize, 60, false, "Maximum width of the args of a function call before falling back to vertical formatting"; struct_lit_width: usize, 18, false, "Maximum width in the body of a struct lit before falling back to vertical formatting"; struct_variant_width: usize, 35, false, "Maximum width in the body of a struct variant before falling back to vertical formatting"; - force_explicit_abi: bool, true, false, "Always print the abi for extern items"; - newline_style: NewlineStyle, NewlineStyle::Unix, false, "Unix or Windows line endings"; - brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; - control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, - "Brace style for control flow constructs"; - impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; - trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, - "How to handle trailing commas for lists"; - trailing_semicolon: bool, true, false, - "Add trailing semicolon after break, continue and return"; - fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; - fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - fn_args_density: Density, Density::Tall, false, "Argument density in functions"; array_width: usize, 60, false, "Maximum width of an array literal before falling back to vertical formatting"; array_horizontal_layout_threshold: usize, 0, false, "How many elements array must have before rustfmt uses horizontal layout."; - type_punctuation_density: TypeDensity, TypeDensity::Wide, false, - "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; + chain_width: usize, 60, false, "Maximum length of a chain to fit on a single line"; + single_line_if_else_max_width: usize, 50, false, "Maximum line length for single line if-else \ + expressions. A value of zero means always break \ + if-else expressions."; + + // Single line expressions and items. + struct_lit_single_line: bool, true, false, + "Put small struct literals on a single line"; + impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; + fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; + fn_single_line: bool, false, false, "Put single-expression functions on a single line"; + + // Where clauses // TODO: // 1. Should we at least try to put the where clause on the same line as the rest of the // function decl? @@ -547,30 +546,20 @@ create_config! { where_density: Density, Density::Vertical, false, "Density of a where clause"; where_single_line: bool, false, false, "To force single line where layout"; where_layout: ListTactic, ListTactic::Vertical, false, "Element layout inside a where clause"; - struct_lit_single_line: bool, true, false, - "Put small struct literals on a single line"; - report_todo: ReportTactic, ReportTactic::Never, false, - "Report all, none or unnumbered occurrences of TODO in source file comments"; - report_fixme: ReportTactic, ReportTactic::Never, false, - "Report all, none or unnumbered occurrences of FIXME in source file comments"; - chain_width: usize, 60, false, "Maximum length of a chain to fit on a single line"; + + // Imports imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; + + // Ordering reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; reorder_imports: bool, false, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; - single_line_if_else_max_width: usize, 50, false, "Maximum line length for single line if-else \ - expressions. A value of zero means always break \ - if-else expressions."; - format_strings: bool, false, false, "Format string literals where necessary"; - hard_tabs: bool, false, false, "Use tab characters for indentation, spaces for alignment"; - wrap_comments: bool, false, false, "Break comments to fit on the line"; - comment_width: usize, 80, false, - "Maximum length of comments. No effect unless wrap_comments = true"; - normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; + + // Match wrap_match_arms: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; match_block_trailing_comma: bool, false, false, @@ -579,19 +568,21 @@ create_config! { "Force match arm bodies to be in a new lines"; indent_match_arms: bool, true, false, "Indent match arms instead of keeping them at the same \ indentation level as the match keyword"; + multiline_match_arm_forces_block: bool, false, false, + "Force multiline match arm bodies to be wrapped in a block"; + + // Spaces around punctuation + binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + "Where to put a binary operator when a binary expression goes multiline."; + type_punctuation_density: TypeDensity, TypeDensity::Wide, false, + "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; space_before_colon: bool, false, false, "Leave a space before the colon"; space_after_colon: bool, true, false, "Leave a space after the colon"; spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; spaces_within_parens_and_brackets: bool, false, false, "Put spaces within non-empty parentheses or brackets"; - use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; - write_mode: WriteMode, WriteMode::Overwrite, false, - "What Write Mode to use when none is supplied: \ - Replace, Overwrite, Display, Plain, Diff, Coverage"; - color: Color, Color::Auto, false, - "What Color option to use when none is supplied: Always, Never, Auto"; - condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ - in tuple patterns"; + + // Misc. combine_control_expr: bool, true, false, "Combine control expressions with function calls."; struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ threshold."; @@ -601,13 +592,45 @@ create_config! { "Try to put attributes on the same line as fields and variants."; multiline_closure_forces_block: bool, false, false, "Force multiline closure bodies to be wrapped in a block"; - multiline_match_arm_forces_block: bool, false, false, - "Force multiline match arm bodies to be wrapped in a block"; - merge_derives: bool, true, false, "Merge multiple `#[derive(...)]` into a single one"; - binop_separator: SeparatorPlace, SeparatorPlace::Front, false, - "Where to put a binary operator when a binary expression goes multiline."; + fn_args_density: Density, Density::Tall, false, "Argument density in functions"; + brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, + "Brace style for control flow constructs"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, + "How to handle trailing commas for lists"; + trailing_semicolon: bool, true, false, + "Add trailing semicolon after break, continue and return"; + + // Options that can change the source code beyond whitespace/blocks (somewhat linty things) + merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; + use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; + condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ + in tuple patterns"; + force_explicit_abi: bool, true, true, "Always print the abi for extern items"; + + // Control options (changes the operation of rustfmt, rather than the formatting) + write_mode: WriteMode, WriteMode::Overwrite, false, + "What Write Mode to use when none is supplied: \ + Replace, Overwrite, Display, Plain, Diff, Coverage"; + color: Color, Color::Auto, false, + "What Color option to use when none is supplied: Always, Never, Auto"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, - "Require a specific version of rustfmt." + "Require a specific version of rustfmt."; + unstable_features: bool, false, true, + "Enables unstable features. Only available on nightly channel"; + verbose: bool, false, false, "Use verbose output"; + disable_all_formatting: bool, false, false, "Don't reformat anything"; + skip_children: bool, false, false, "Don't reformat out of line modules"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; + error_on_line_overflow_comments: bool, true, false, + "Error if unable to get comments within max_width"; + report_todo: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of TODO in source file comments"; + report_fixme: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of FIXME in source file comments"; } #[cfg(test)] -- cgit 1.4.1-3-g733a5 From 96886cd67f1faa83bfb360c31c6614e1aea46bf7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 15:37:01 +1300 Subject: Fix a typo in the unstable options handling and address fallout --- src/config.rs | 66 ++++++++++++++++++++++---------------------- tests/config/issue-1124.toml | 2 -- tests/source/issue-1124.rs | 3 ++ tests/target/issue-1124.rs | 3 ++ 4 files changed, 39 insertions(+), 35 deletions(-) delete mode 100644 tests/config/issue-1124.toml (limited to 'src') diff --git a/src/config.rs b/src/config.rs index f30f0039ccd..1536d8f4a6a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -289,7 +289,7 @@ macro_rules! create_config { fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { - if !self.$i.3 { + if self.$i.3 { self.$i.1 = true; self.$i.2 = val; } else { @@ -669,36 +669,36 @@ mod test { assert_eq!(config.was_set().verbose(), false); } - #[test] - fn test_as_not_nightly_channel() { - let mut config = Config::default(); - assert_eq!(config.was_set().unstable_features(), false); - config.set().unstable_features(true); - assert_eq!(config.was_set().unstable_features(), false); - } - - #[test] - fn test_as_nightly_channel() { - let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - let mut config = Config::default(); - config.set().unstable_features(true); - assert_eq!(config.was_set().unstable_features(), false); - config.set().unstable_features(true); - assert_eq!(config.unstable_features(), true); - ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - } - - #[test] - fn test_unstable_from_toml() { - let mut config = Config::from_toml("unstable_features = true").unwrap(); - assert_eq!(config.was_set().unstable_features(), false); - let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - config = Config::from_toml("unstable_features = true").unwrap(); - assert_eq!(config.was_set().unstable_features(), true); - assert_eq!(config.unstable_features(), true); - ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - } - + // FIXME(#2183) these tests cannot be run in parallel because they use env vars + // #[test] + // fn test_as_not_nightly_channel() { + // let mut config = Config::default(); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // } + + // #[test] + // fn test_as_nightly_channel() { + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // let mut config = Config::default(); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } + + // #[test] + // fn test_unstable_from_toml() { + // let mut config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), false); + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } } diff --git a/tests/config/issue-1124.toml b/tests/config/issue-1124.toml deleted file mode 100644 index ca318207235..00000000000 --- a/tests/config/issue-1124.toml +++ /dev/null @@ -1,2 +0,0 @@ -reorder_imports = true -normalize_comments = true diff --git a/tests/source/issue-1124.rs b/tests/source/issue-1124.rs index 0b9d68f49b8..69aa1bb1c59 100644 --- a/tests/source/issue-1124.rs +++ b/tests/source/issue-1124.rs @@ -1,3 +1,6 @@ +// rustfmt-reorder_imports: true +// rustfmt-normalize_comments: true + use d; use c; use b; use a; // The previous line has a space after the `use a;` diff --git a/tests/target/issue-1124.rs b/tests/target/issue-1124.rs index 7f38fe75a8f..d34870b2a28 100644 --- a/tests/target/issue-1124.rs +++ b/tests/target/issue-1124.rs @@ -1,3 +1,6 @@ +// rustfmt-reorder_imports: true +// rustfmt-normalize_comments: true + use a; use b; use c; -- cgit 1.4.1-3-g733a5 From e6ce65b214966b54c9f19bcc5b8bf12c80c57d06 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 24 Nov 2017 12:05:02 +0900 Subject: Put rhs on the same line as lhs if putting rhs on next line exceeds max width --- src/expr.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ad8cb25b53f..4c651a2bd37 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2632,6 +2632,12 @@ pub fn choose_rhs( let new_indent_str = &new_shape.indent.to_string(context.config); match (orig_rhs, new_rhs) { + (Some(ref orig_rhs), Some(ref new_rhs)) + if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) + .is_none() => + { + Some(format!(" {}", orig_rhs)) + } (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { Some(format!("\n{}{}", new_indent_str, new_rhs)) } -- cgit 1.4.1-3-g733a5 From dd1fbca99a9518c6a0dfedd77300d0856c9d4a21 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 20:17:06 +1300 Subject: Replace various small width heuristics with a single option Closes #1984 --- Configurations.md | 218 ++++++--------------- src/chains.rs | 2 +- src/config.rs | 121 +++++++++--- src/expr.rs | 34 ++-- src/items.rs | 5 +- src/lists.rs | 2 +- src/macros.rs | 2 +- tests/config/small_tabs.toml | 1 - tests/source/chains-visual.rs | 1 - tests/source/chains.rs | 3 +- ...rray_horizontal_layout_threshold-1000-visual.rs | 108 ---------- ...nfigs-array_horizontal_layout_threshold-1000.rs | 107 ---------- tests/source/configs-array_width-above.rs | 6 - tests/source/configs-array_width-below.rs | 6 - tests/source/configs-chain_width-above.rs | 6 - tests/source/configs-chain_width-below.rs | 6 - tests/source/configs-fn_call_width-above.rs | 6 - tests/source/configs-fn_call_width-below.rs | 6 - tests/source/configs-fn_call_width-zero.rs | 7 - .../configs-single_line_if_else_max_width-above.rs | 6 - .../configs-single_line_if_else_max_width-below.rs | 6 - .../source/configs-struct_lit_single_line-true.rs | 7 - tests/source/configs-struct_lit_width-above.rs | 6 - tests/source/configs-struct_lit_width-below.rs | 6 - tests/source/configs-struct_variant_width-above.rs | 8 - tests/source/configs-struct_variant_width-below.rs | 8 - .../source/else-if-brace-style-always-next-line.rs | 1 - .../source/else-if-brace-style-always-same-line.rs | 1 - .../else-if-brace-style-closing-next-line.rs | 1 - tests/source/hard-tabs.rs | 1 - tests/source/single-line-if-else.rs | 1 - tests/target/chains-visual.rs | 13 +- tests/target/chains.rs | 18 +- ...rray_horizontal_layout_threshold-1000-visual.rs | 96 --------- ...nfigs-array_horizontal_layout_threshold-1000.rs | 94 --------- tests/target/configs-array_width-above.rs | 14 -- tests/target/configs-array_width-below.rs | 6 - tests/target/configs-chain_width-above.rs | 12 -- tests/target/configs-chain_width-below.rs | 6 - tests/target/configs-fn_call_width-above.rs | 15 -- tests/target/configs-fn_call_width-below.rs | 6 - tests/target/configs-fn_call_width-zero.rs | 9 - .../configs-single_line_if_else_max_width-above.rs | 10 - .../configs-single_line_if_else_max_width-below.rs | 6 - .../target/configs-struct_lit_single_line-true.rs | 7 - tests/target/configs-struct_lit_width-above.rs | 9 - tests/target/configs-struct_lit_width-below.rs | 6 - tests/target/configs-struct_variant_width-0.rs | 29 --- tests/target/configs-struct_variant_width-above.rs | 11 -- tests/target/configs-struct_variant_width-below.rs | 8 - .../target/else-if-brace-style-always-next-line.rs | 10 +- .../target/else-if-brace-style-always-same-line.rs | 7 +- .../else-if-brace-style-closing-next-line.rs | 8 +- tests/target/hard-tabs.rs | 9 +- tests/target/issue-1802.rs | 7 +- tests/target/single-line-if-else.rs | 14 +- 56 files changed, 214 insertions(+), 915 deletions(-) delete mode 100644 tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs delete mode 100644 tests/source/configs-array_horizontal_layout_threshold-1000.rs delete mode 100644 tests/source/configs-array_width-above.rs delete mode 100644 tests/source/configs-array_width-below.rs delete mode 100644 tests/source/configs-chain_width-above.rs delete mode 100644 tests/source/configs-chain_width-below.rs delete mode 100644 tests/source/configs-fn_call_width-above.rs delete mode 100644 tests/source/configs-fn_call_width-below.rs delete mode 100644 tests/source/configs-fn_call_width-zero.rs delete mode 100644 tests/source/configs-single_line_if_else_max_width-above.rs delete mode 100644 tests/source/configs-single_line_if_else_max_width-below.rs delete mode 100644 tests/source/configs-struct_lit_single_line-true.rs delete mode 100644 tests/source/configs-struct_lit_width-above.rs delete mode 100644 tests/source/configs-struct_lit_width-below.rs delete mode 100644 tests/source/configs-struct_variant_width-above.rs delete mode 100644 tests/source/configs-struct_variant_width-below.rs delete mode 100644 tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs delete mode 100644 tests/target/configs-array_horizontal_layout_threshold-1000.rs delete mode 100644 tests/target/configs-array_width-above.rs delete mode 100644 tests/target/configs-array_width-below.rs delete mode 100644 tests/target/configs-chain_width-above.rs delete mode 100644 tests/target/configs-chain_width-below.rs delete mode 100644 tests/target/configs-fn_call_width-above.rs delete mode 100644 tests/target/configs-fn_call_width-below.rs delete mode 100644 tests/target/configs-fn_call_width-zero.rs delete mode 100644 tests/target/configs-single_line_if_else_max_width-above.rs delete mode 100644 tests/target/configs-single_line_if_else_max_width-below.rs delete mode 100644 tests/target/configs-struct_lit_single_line-true.rs delete mode 100644 tests/target/configs-struct_lit_width-above.rs delete mode 100644 tests/target/configs-struct_lit_width-below.rs delete mode 100644 tests/target/configs-struct_variant_width-0.rs delete mode 100644 tests/target/configs-struct_variant_width-above.rs delete mode 100644 tests/target/configs-struct_variant_width-below.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 275d4883760..968b5a2d634 100644 --- a/Configurations.md +++ b/Configurations.md @@ -6,7 +6,6 @@ A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this: ```toml indent_style = "Block" -array_width = 80 reorder_imported_names = true ``` @@ -14,41 +13,6 @@ reorder_imported_names = true Below you find a detailed visual guide on all the supported configuration options of rustfmt: -## `array_horizontal_layout_threshold` - -How many elements array must have before rustfmt uses horizontal layout. -Use this option to prevent a huge array from being vertically formatted. - -- **Default value**: `0` -- **Possible values**: any positive integer - -**Note:** A value of `0` results in [`indent_style`](#indent_style) being applied regardless of a line's width. - -#### `0` (default): - -```rust -// Each element will be placed on its own line. -let a = vec![ - 0, - 1, - 2, - 3, - 4, - ... - 999, - 1000, -]; -``` - -#### `1000`: - -```rust -// Each element will be placed on the same line as much as possible. -let a = vec![ - 0, 1, 2, 3, 4, ... - ..., 999, 1000, -]; -``` ## `indent_style` @@ -279,22 +243,6 @@ fn lorem() -> T See also: [`where_density`](#where_density), [`where_layout`](#where_layout). -## `array_width` - -Maximum width of an array literal before falling back to vertical formatting - -- **Default value**: `60` -- **Possible values**: any positive integer - -**Note:** A value of `0` results in [`indent_style`](#indent_style) being applied regardless of a line's width. - -#### Lines shorter than `array_width`: -```rust -let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"]; -``` - -#### Lines longer than `array_width`: -See [`indent_style`](#indent_style). ## `same_line_attributes` @@ -341,6 +289,66 @@ enum Lorem { } ``` +## `use_small_heuristics` + +Whether to use different formatting for items and expressions if they satisfy a heuristic notion of 'small'. + +- **Default value**: `true` +- **Possible values**: `true`, `false` + +#### `true` (default): + +```rust +enum Lorem { + Ipsum, + Dolor(bool), + Sit { amet: Consectetur, adipiscing: Elit }, +} + +fn main() { + lorem( + "lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + ); + + let lorem = Lorem { ipsum: dolor, sit: amet }; + + let lorem = if ipsum { dolor } else { sit }; +} +``` + +#### `false`: + +```rust +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} +``` ## `binop_separator` @@ -409,22 +417,6 @@ let lorem = ipsum.dolor() .elit(); ``` -See also [`chain_width`](#chain_width). - -## `chain_width` - -Maximum length of a chain to fit on a single line - -- **Default value**: `60` -- **Possible values**: any positive integer - -#### Lines shorter than `chain_width`: -```rust -let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); -``` - -#### Lines longer than `chain_width`: -See [`chain_indent`](#chain_indent). ## `combine_control_expr` @@ -883,23 +875,7 @@ struct Dolor } ``` -## `fn_call_width` - -Maximum width of the args of a function call before falling back to vertical formatting - -- **Default value**: `60` -- **Possible values**: any positive integer - -**Note:** A value of `0` results in vertical formatting being applied regardless of a line's width. - -#### Function call shorter than `fn_call_width`: -```rust -lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); -``` - -#### Function call longer than `fn_call_width`: -See [`indent_style`](#indent_style). ## `fn_empty_single_line` @@ -1533,30 +1509,6 @@ it contains a `#X` (with `X` being a number) in parentheses following the See also [`report_todo`](#report_todo). -## `single_line_if_else_max_width` - -Maximum line length for single line if-else expressions. - -- **Default value**: `50` -- **Possible values**: any positive integer - -**Note:** A value of `0` results in if-else expressions being broken regardless of their line's width. - -#### Lines shorter than `single_line_if_else_max_width`: -```rust -let lorem = if ipsum { dolor } else { sit }; -``` - -#### Lines longer than `single_line_if_else_max_width`: -```rust -let lorem = if ipsum { - dolor -} else { - sit -}; -``` - -See also: [`control_brace_style`](#control_brace_style). ## `skip_children` @@ -1768,56 +1720,8 @@ let lorem = Lorem { }; ``` -See also: [`indent_style`](#indent_style), [`struct_lit_width`](#struct_lit_width). - -## `struct_lit_width` - -Maximum width in the body of a struct lit before falling back to vertical formatting - -- **Default value**: `18` -- **Possible values**: any positive integer - -**Note:** A value of `0` results in vertical formatting being applied regardless of a line's width. - -#### Lines shorter than `struct_lit_width`: -```rust -let lorem = Lorem { ipsum: dolor, sit: amet }; -``` - -#### Lines longer than `struct_lit_width`: -See [`indent_style`](#indent_style). - -See also: [`struct_lit_single_line`](#struct_lit_single_line), [`indent_style`](#indent_style). - -## `struct_variant_width` - -Maximum width in the body of a struct variant before falling back to vertical formatting - -- **Default value**: `35` -- **Possible values**: any positive integer - -**Note:** A value of `0` results in vertical formatting being applied regardless of a line's width. - -#### Struct variants shorter than `struct_variant_width`: -```rust -enum Lorem { - Ipsum, - Dolor(bool), - Sit { amet: Consectetur, adipiscing: Elit }, -} -``` +See also: [`indent_style`](#indent_style). -#### Struct variants longer than `struct_variant_width`: -```rust -enum Lorem { - Ipsum, - Dolor(bool), - Sit { - amet: Consectetur, - adipiscing: Elit, - }, -} -``` ## `tab_spaces` diff --git a/src/chains.rs b/src/chains.rs index 526eebfd262..1442f6b84a1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -161,7 +161,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let one_line_budget = if rewrites.is_empty() { shape.width } else { - min(shape.width, context.config.chain_width()) + min(shape.width, context.config.width_heuristics().chain_width) }; let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) diff --git a/src/config.rs b/src/config.rs index 1536d8f4a6a..22c6cd6121d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -12,6 +12,7 @@ extern crate toml; use std::{env, fs}; use std::cell::Cell; +use std::default::Default; use std::fs::File; use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; @@ -132,6 +133,68 @@ configuration_option_enum! { Color: Auto, } +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct WidthHeuristics { + // Maximum width of the args of a function call before falling back + // to vertical formatting. + pub fn_call_width: usize, + // Maximum width in the body of a struct lit before falling back to + // vertical formatting. + pub struct_lit_width: usize, + // Maximum width in the body of a struct variant before falling back + // to vertical formatting. + pub struct_variant_width: usize, + // Maximum width of an array literal before falling back to vertical + // formatting. + pub array_width: usize, + // Maximum length of a chain to fit on a single line. + pub chain_width: usize, + // Maximum line length for single line if-else expressions. A value + // of zero means always break if-else expressions. + pub single_line_if_else_max_width: usize, +} + +impl WidthHeuristics { + // Using this WidthHeuristics means we ignore heuristics. + fn null() -> WidthHeuristics { + WidthHeuristics { + fn_call_width: usize::max_value(), + struct_lit_width: 0, + struct_variant_width: 0, + array_width: usize::max_value(), + chain_width: usize::max_value(), + single_line_if_else_max_width: 0, + } + } +} + +impl Default for WidthHeuristics { + fn default() -> WidthHeuristics { + WidthHeuristics { + fn_call_width: 60, + struct_lit_width: 18, + struct_variant_width: 35, + array_width: 60, + chain_width: 60, + single_line_if_else_max_width: 50, + } + } +} + +impl ::std::str::FromStr for WidthHeuristics { + type Err = &'static str; + + fn from_str(_: &str) -> Result { + Err("WidthHeuristics is not parsable") + } +} + +impl ::config::ConfigType for WidthHeuristics { + fn doc_hint() -> String { + String::new() + } +} + /// Trait for types that can be used in `Config`. pub trait ConfigType: Sized { /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a @@ -216,9 +279,11 @@ macro_rules! create_config { impl PartialConfig { pub fn to_toml(&self) -> Result { - // file_lines can't be specified in TOML + // Non-user-facing options can't be specified in TOML let mut cloned = self.clone(); cloned.file_lines = None; + cloned.verbose = None; + cloned.width_heuristics = None; toml::to_string(&cloned) .map_err(|e| format!("Could not output config: {}", e.to_string())) @@ -236,6 +301,9 @@ macro_rules! create_config { $( pub fn $i(&mut self, value: $ty) { (self.0).$i.2 = value; + if stringify!($i) == "use_small_heuristics" { + self.0.set_heuristics(); + } } )+ } @@ -303,6 +371,7 @@ macro_rules! create_config { } } )+ + self.set_heuristics(); self } @@ -374,6 +443,10 @@ macro_rules! create_config { )+ _ => panic!("Unknown config key in override: {}", key) } + + if key == "use_small_heuristics" { + self.set_heuristics(); + } } /// Construct a `Config` from the toml file specified at `file_path`. @@ -461,6 +534,14 @@ macro_rules! create_config { println!(); )+ } + + fn set_heuristics(&mut self) { + if self.use_small_heuristics.2 { + self.set().width_heuristics(WidthHeuristics::default()); + } else { + self.set().width_heuristics(WidthHeuristics::null()); + } + } } // Template for the default configuration @@ -507,6 +588,8 @@ create_config! { tab_spaces: usize, 4, true, "Number of spaces per tab"; newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; + use_small_heuristics: bool, true, false, "Whether to use different formatting for items and\ + expressions if they satisfy a heuristic notion of 'small'."; // strings and comments format_strings: bool, false, false, "Format string literals where necessary"; @@ -515,22 +598,6 @@ create_config! { "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; - // Width heuristics - fn_call_width: usize, 60, false, - "Maximum width of the args of a function call before falling back to vertical formatting"; - struct_lit_width: usize, 18, false, - "Maximum width in the body of a struct lit before falling back to vertical formatting"; - struct_variant_width: usize, 35, false, - "Maximum width in the body of a struct variant before falling back to vertical formatting"; - array_width: usize, 60, false, - "Maximum width of an array literal before falling back to vertical formatting"; - array_horizontal_layout_threshold: usize, 0, false, - "How many elements array must have before rustfmt uses horizontal layout."; - chain_width: usize, 60, false, "Maximum length of a chain to fit on a single line"; - single_line_if_else_max_width: usize, 50, false, "Maximum line length for single line if-else \ - expressions. A value of zero means always break \ - if-else expressions."; - // Single line expressions and items. struct_lit_single_line: bool, true, false, "Put small struct literals on a single line"; @@ -618,12 +685,8 @@ create_config! { "Require a specific version of rustfmt."; unstable_features: bool, false, true, "Enables unstable features. Only available on nightly channel"; - verbose: bool, false, false, "Use verbose output"; disable_all_formatting: bool, false, false, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; - file_lines: FileLines, FileLines::all(), false, - "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ - via the --file-lines option"; error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; error_on_line_overflow_comments: bool, true, false, "Error if unable to get comments within max_width"; @@ -631,6 +694,14 @@ create_config! { "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; + + // Not user-facing. + verbose: bool, false, false, "Use verbose output"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + width_heuristics: WidthHeuristics, WidthHeuristics::default(), false, + "'small' heuristic values"; } #[cfg(test)] @@ -650,14 +721,18 @@ mod test { fn test_config_used_to_toml() { let config = Config::default(); - let verbose = config.verbose(); + let merge_derives = config.merge_derives(); let skip_children = config.skip_children(); let used_options = config.used_options(); let toml = used_options.to_toml().unwrap(); assert_eq!( toml, - format!("verbose = {}\nskip_children = {}\n", verbose, skip_children) + format!( + "merge_derives = {}\nskip_children = {}\n", + merge_derives, + skip_children, + ) ); } diff --git a/src/expr.rs b/src/expr.rs index b9c33a52be7..fb71d5c054b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -451,13 +451,14 @@ where .iter() .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - let mut tactic = match context.config.indent_style() { + let tactic = match context.config.indent_style() { IndentStyle::Block => { // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { Some(width) => { - let tactic = - ListTactic::LimitedHorizontalVertical(context.config.array_width()); + let tactic = ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ); definitive_tactic(&items, tactic, Separator::Comma, width) } None => DefinitiveListTactic::Vertical, @@ -466,7 +467,9 @@ where IndentStyle::Visual => if has_long_item || items.iter().any(ListItem::is_multiline) { definitive_tactic( &items, - ListTactic::LimitedHorizontalVertical(context.config.array_width()), + ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ), Separator::Comma, nested_shape.width, ) @@ -475,11 +478,6 @@ where }, }; let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); - if context.config.array_horizontal_layout_threshold() > 0 - && items.len() > context.config.array_horizontal_layout_threshold() - { - tactic = DefinitiveListTactic::Mixed; - } let fmt = ListFormatting { tactic: tactic, @@ -957,11 +955,21 @@ impl<'a> ControlFlow<'a> { && !last_line_extendable(&pat_expr_string); // Try to format if-else on single line. - if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { + if self.allow_single_line + && context + .config + .width_heuristics() + .single_line_if_else_max_width > 0 + { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if let Some(cond_str) = trial { - if cond_str.len() <= context.config.single_line_if_else_max_width() { + if cond_str.len() + <= context + .config + .width_heuristics() + .single_line_if_else_max_width + { return Some((cond_str, 0)); } } @@ -1795,7 +1803,7 @@ pub fn rewrite_call( &ptr_vec_to_ref_vec(args), span, shape, - context.config.fn_call_width(), + context.config.width_heuristics().fn_call_width, force_trailing_comma, ) } @@ -2521,7 +2529,7 @@ where items, span, shape, - context.config.fn_call_width(), + context.config.width_heuristics().fn_call_width, force_trailing_comma, ) } else { diff --git a/src/items.rs b/src/items.rs index c99a4db0fdf..695ee71f0c3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -502,7 +502,8 @@ impl<'a> FmtVisitor<'a> { false, ).collect() }; - let mut items: Vec<_> = itemize_list_with(self.config.struct_variant_width()); + let mut items: Vec<_> = + itemize_list_with(self.config.width_heuristics().struct_variant_width); // If one of the variants use multiple lines, use multi-lined formatting for all variants. let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains("\n")); let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains("\n")); @@ -1324,7 +1325,7 @@ fn format_tuple_struct( } else { let shape = Shape::indented(offset, context.config); let fields = &fields.iter().map(|field| field).collect::>()[..]; - let one_line_width = context.config.fn_call_width(); + let one_line_width = context.config.width_heuristics().fn_call_width; result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; } diff --git a/src/lists.rs b/src/lists.rs index 5f8149c6f3e..edc896e26c2 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -780,7 +780,7 @@ pub fn struct_lit_shape( }; let shape_width = shape.width.checked_sub(prefix_width + suffix_width); if let Some(w) = shape_width { - let shape_width = cmp::min(w, context.config.struct_lit_width()); + let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) } else { Some((None, v_shape)) diff --git a/src/macros.rs b/src/macros.rs index 6e64a49361d..8c8b50b7ca3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -208,7 +208,7 @@ pub fn rewrite_macro( &arg_vec.iter().map(|e| &*e).collect::>()[..], mac.span, shape, - context.config.fn_call_width(), + context.config.width_heuristics().fn_call_width, trailing_comma, ).map(|rw| match position { MacroPosition::Item => format!("{};", rw), diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 298ca5af9bd..472df014435 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -11,5 +11,4 @@ indent_style = "Block" report_todo = "Always" report_fixme = "Never" reorder_imports = false -single_line_if_else_max_width = 0 format_strings = true diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs index 99dfa921a71..2fd36225881 100644 --- a/tests/source/chains-visual.rs +++ b/tests/source/chains-visual.rs @@ -1,5 +1,4 @@ // rustfmt-normalize_comments: true -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-indent_style: Visual // Test chain formatting. diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 6199eb77edc..f14a0293123 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,6 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chain_width: 100 +// rustfmt-use_small_heuristics: false // Test chain formatting. fn main() { diff --git a/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs b/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs deleted file mode 100644 index 3036f3598ef..00000000000 --- a/tests/source/configs-array_horizontal_layout_threshold-1000-visual.rs +++ /dev/null @@ -1,108 +0,0 @@ -// rustfmt-array_horizontal_layout_threshold: 1000 -// rustfmt-indent_style: Visual - -const ARRAY: [u8; 2048] = - [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, - 21, 18, 37, 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, - 87, 69, 42, 38, 25, 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, - 29, 111, 120, 26, 0, 78, 36, 115, 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, - 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, 124, 124, 102, 74, 35, 9, 83, 22, 121, - 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, 54, 17, 58, 105, 13, 96, 61, 99, - 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, 56, 5, 114, 11, 25, 16, 97, - 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, 58, 103, 2, 88, - 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, 97, - 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, - 9, 21, 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, - 61, 8, 124, 110, 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, - 44, 73, 82, 10, 49, 95, 72, 89, 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, - 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, 31, 33, 84, 72, 128, 91, 3, 84, 92, - 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, 43, 66, 21, 90, 31, 102, 45, - 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, 54, 11, 103, 45, - 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, 93, - 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, - 92, 105, 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, - 52, 46, 81, 28, 46, 82, 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, - 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, - 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, 48, 51, 54, 56, 105, 90, 50, 67, - 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, 75, 29, 15, 15, 47, 33, - 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, 86, 101, - 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, - 36, 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, - 62, 86, 104, 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, - 23, 68, 115, 106, 15, 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, - 88, 8, 32, 3, 63, 77, 14, 86, 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, - 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, 67, 42, 109, 30, 93, 40, 113, 13, 85, - 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, 102, 25, 4, 113, 84, 63, - 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, 81, 38, 55, 82, - 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, 123, - 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, - 49, 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, - 83, 36, 38, 71, 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, - 49, 86, 7, 84, 40, 42, 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, - 50, 42, 34, 122, 116, 75, 31, 109, 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, - 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, 3, 18, 110, 84, 70, 23, 84, 23, - 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, 86, 67, 78, 126, 86, - 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, 86, 34, 91, - 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, 102, - 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, - 58, 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, - 115, 44, 4, 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, - 20, 44, 46, 4, 116, 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, - 10, 36, 68, 94, 40, 87, 74, 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, - 40, 97, 43, 58, 16, 120, 74, 52, 42, 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, - 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, 71, 92, 70, 57, 37, 42, 21, 83, 2, - 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, 52, 80, 94, 46, 18, 68, 72, - 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, 81, 45, 79, 121, - 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, 115, 29, - 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, - 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, - 101, 68, 26, 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, - 54, 69, 34, 22, 21, 54, 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, - 65, 40, 34, 12, 6, 127, 32, 90, 62, 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, - 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, 45, 85, 40, 3, 114, 36, 23, 109, 118, - 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, 47, 126, 118, 105, 10, 59, 12, - 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, 106, 110, 49, 50, 20, - 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, 79, 85, - 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, - 126, 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, - 116, 114, 119, 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, - 92, 70, 49, 59, 51, 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, - 2, 98, 47, 25, 100, 37, 42, 115, 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, - 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, 16, 113, 68, 20, 76, 99, 93, 121, 18, - 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, 6, 96, 12, 100, 33, 5, - 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, 114, 84, - 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, - 110, 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, - 115, 47, 80, 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, - 81, 76, 66, 17, 108, 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, - 12, 16, 114, 50, 49, 12, 3, 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, - 27, 28, 24, 46, 101, 10, 104, 51, 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, - 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, 56, 80, 20, 117, 65, 53, 58, 66, 5, - 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, 31, 80, 29, 12, 115, 75, - 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, 98, 118, 26, - 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, - 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, - 109, 109, 97, 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, - 81, 111, 6, 11, 28, 5, 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, - 29, 60, 91, 72, 94, 15, 31, 98, 47, 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, - 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, 103, 88, 22, 107, 38, 39, 100, - 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, 19, 59, 87, 128, 16, 46, - 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, 100, 41, 51, - 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, - 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, - 16, 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, - 91, 16, 46, 117, 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, - 5, 21, 81, 43, 58, 61, 59, 39, 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, - 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, - 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, 32, 3, 2, 117, 41, 80, 96, 122, - 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, 22, 68, 39, 119, - 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, 115, - 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, - 125, 1, 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, - 47, 21, 103, 63, 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, - 104, 43, 73, 17, 111, 36, 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, - 54, 71, 38, 58, 86, 124, 3, 103, 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, - 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, - 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, 45, 97, 8, 39, 125, 9, 22, 91, - 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, 106, 32, 105, 27, 0, 56, - 66, 51, 4, 94, 72, 117, 69]; diff --git a/tests/source/configs-array_horizontal_layout_threshold-1000.rs b/tests/source/configs-array_horizontal_layout_threshold-1000.rs deleted file mode 100644 index c1fb8e92872..00000000000 --- a/tests/source/configs-array_horizontal_layout_threshold-1000.rs +++ /dev/null @@ -1,107 +0,0 @@ -// rustfmt-array_horizontal_layout_threshold: 1000 - -const ARRAY: [u8; 2048] = - [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, - 21, 18, 37, 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, - 87, 69, 42, 38, 25, 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, - 29, 111, 120, 26, 0, 78, 36, 115, 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, - 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, 124, 124, 102, 74, 35, 9, 83, 22, 121, - 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, 54, 17, 58, 105, 13, 96, 61, 99, - 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, 56, 5, 114, 11, 25, 16, 97, - 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, 58, 103, 2, 88, - 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, 97, - 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, - 9, 21, 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, - 61, 8, 124, 110, 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, - 44, 73, 82, 10, 49, 95, 72, 89, 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, - 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, 31, 33, 84, 72, 128, 91, 3, 84, 92, - 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, 43, 66, 21, 90, 31, 102, 45, - 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, 54, 11, 103, 45, - 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, 93, - 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, - 92, 105, 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, - 52, 46, 81, 28, 46, 82, 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, - 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, - 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, 48, 51, 54, 56, 105, 90, 50, 67, - 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, 75, 29, 15, 15, 47, 33, - 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, 86, 101, - 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, - 36, 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, - 62, 86, 104, 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, - 23, 68, 115, 106, 15, 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, - 88, 8, 32, 3, 63, 77, 14, 86, 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, - 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, 67, 42, 109, 30, 93, 40, 113, 13, 85, - 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, 102, 25, 4, 113, 84, 63, - 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, 81, 38, 55, 82, - 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, 123, - 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, - 49, 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, - 83, 36, 38, 71, 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, - 49, 86, 7, 84, 40, 42, 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, - 50, 42, 34, 122, 116, 75, 31, 109, 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, - 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, 3, 18, 110, 84, 70, 23, 84, 23, - 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, 86, 67, 78, 126, 86, - 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, 86, 34, 91, - 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, 102, - 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, - 58, 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, - 115, 44, 4, 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, - 20, 44, 46, 4, 116, 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, - 10, 36, 68, 94, 40, 87, 74, 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, - 40, 97, 43, 58, 16, 120, 74, 52, 42, 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, - 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, 71, 92, 70, 57, 37, 42, 21, 83, 2, - 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, 52, 80, 94, 46, 18, 68, 72, - 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, 81, 45, 79, 121, - 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, 115, 29, - 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, - 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, - 101, 68, 26, 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, - 54, 69, 34, 22, 21, 54, 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, - 65, 40, 34, 12, 6, 127, 32, 90, 62, 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, - 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, 45, 85, 40, 3, 114, 36, 23, 109, 118, - 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, 47, 126, 118, 105, 10, 59, 12, - 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, 106, 110, 49, 50, 20, - 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, 79, 85, - 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, - 126, 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, - 116, 114, 119, 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, - 92, 70, 49, 59, 51, 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, - 2, 98, 47, 25, 100, 37, 42, 115, 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, - 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, 16, 113, 68, 20, 76, 99, 93, 121, 18, - 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, 6, 96, 12, 100, 33, 5, - 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, 114, 84, - 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, - 110, 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, - 115, 47, 80, 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, - 81, 76, 66, 17, 108, 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, - 12, 16, 114, 50, 49, 12, 3, 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, - 27, 28, 24, 46, 101, 10, 104, 51, 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, - 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, 56, 80, 20, 117, 65, 53, 58, 66, 5, - 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, 31, 80, 29, 12, 115, 75, - 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, 98, 118, 26, - 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, - 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, - 109, 109, 97, 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, - 81, 111, 6, 11, 28, 5, 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, - 29, 60, 91, 72, 94, 15, 31, 98, 47, 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, - 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, 103, 88, 22, 107, 38, 39, 100, - 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, 19, 59, 87, 128, 16, 46, - 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, 100, 41, 51, - 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, - 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, - 16, 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, - 91, 16, 46, 117, 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, - 5, 21, 81, 43, 58, 61, 59, 39, 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, - 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, - 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, 32, 3, 2, 117, 41, 80, 96, 122, - 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, 22, 68, 39, 119, - 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, 115, - 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, - 125, 1, 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, - 47, 21, 103, 63, 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, - 104, 43, 73, 17, 111, 36, 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, - 54, 71, 38, 58, 86, 124, 3, 103, 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, - 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, - 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, 45, 97, 8, 39, 125, 9, 22, 91, - 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, 106, 32, 105, 27, 0, 56, - 66, 51, 4, 94, 72, 117, 69]; diff --git a/tests/source/configs-array_width-above.rs b/tests/source/configs-array_width-above.rs deleted file mode 100644 index 020a984438e..00000000000 --- a/tests/source/configs-array_width-above.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-array_width: 10 -// Array width - -fn main() { - let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"]; -} diff --git a/tests/source/configs-array_width-below.rs b/tests/source/configs-array_width-below.rs deleted file mode 100644 index d76d539773a..00000000000 --- a/tests/source/configs-array_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-array_width: 100 -// Array width - -fn main() { - let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"]; -} diff --git a/tests/source/configs-chain_width-above.rs b/tests/source/configs-chain_width-above.rs deleted file mode 100644 index d26505b8628..00000000000 --- a/tests/source/configs-chain_width-above.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-chain_width: 10 -// Chain one line max - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); -} diff --git a/tests/source/configs-chain_width-below.rs b/tests/source/configs-chain_width-below.rs deleted file mode 100644 index d877deb74eb..00000000000 --- a/tests/source/configs-chain_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-chain_width: 100 -// Chain one line max - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); -} diff --git a/tests/source/configs-fn_call_width-above.rs b/tests/source/configs-fn_call_width-above.rs deleted file mode 100644 index 237e72c3034..00000000000 --- a/tests/source/configs-fn_call_width-above.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_call_width: 10 -// Function call width - -fn main() { - lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); -} diff --git a/tests/source/configs-fn_call_width-below.rs b/tests/source/configs-fn_call_width-below.rs deleted file mode 100644 index b79918f5b98..00000000000 --- a/tests/source/configs-fn_call_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_call_width: 100 -// Function call width - -fn main() { - lorem("lorem", "ipsum", "dolor"); -} diff --git a/tests/source/configs-fn_call_width-zero.rs b/tests/source/configs-fn_call_width-zero.rs deleted file mode 100644 index e7db3261556..00000000000 --- a/tests/source/configs-fn_call_width-zero.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-fn_call_width: 0 -// rustfmt-indent_style: block - -// #1508 -fn a() { - let x = f(y); -} diff --git a/tests/source/configs-single_line_if_else_max_width-above.rs b/tests/source/configs-single_line_if_else_max_width-above.rs deleted file mode 100644 index 698fa8bc460..00000000000 --- a/tests/source/configs-single_line_if_else_max_width-above.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 10 -// Single line if-else max width - -fn main() { - let lorem = if ipsum { dolor } else { sit }; -} diff --git a/tests/source/configs-single_line_if_else_max_width-below.rs b/tests/source/configs-single_line_if_else_max_width-below.rs deleted file mode 100644 index efafa6c4498..00000000000 --- a/tests/source/configs-single_line_if_else_max_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 100 -// Single line if-else max width - -fn main() { - let lorem = if ipsum { dolor } else { sit }; -} diff --git a/tests/source/configs-struct_lit_single_line-true.rs b/tests/source/configs-struct_lit_single_line-true.rs deleted file mode 100644 index 363bf5b114e..00000000000 --- a/tests/source/configs-struct_lit_single_line-true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-struct_lit_single_line: true -// rustfmt-struct_lit_width: 100 -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs-struct_lit_width-above.rs b/tests/source/configs-struct_lit_width-above.rs deleted file mode 100644 index 123fa59f90e..00000000000 --- a/tests/source/configs-struct_lit_width-above.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-struct_lit_width: 10 -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs-struct_lit_width-below.rs b/tests/source/configs-struct_lit_width-below.rs deleted file mode 100644 index 7ffe4a32eaf..00000000000 --- a/tests/source/configs-struct_lit_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-struct_lit_width: 100 -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs-struct_variant_width-above.rs b/tests/source/configs-struct_variant_width-above.rs deleted file mode 100644 index 13ceed0bc63..00000000000 --- a/tests/source/configs-struct_variant_width-above.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-struct_variant_width: 10 -// Struct variant width - -enum Lorem { - Ipsum, - Dolor(bool), - Sit { amet: Consectetur, adipiscing: Elit, }, -} diff --git a/tests/source/configs-struct_variant_width-below.rs b/tests/source/configs-struct_variant_width-below.rs deleted file mode 100644 index a16a57e19b8..00000000000 --- a/tests/source/configs-struct_variant_width-below.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-struct_variant_width: 100 -// Struct variant width - -enum Lorem { - Ipsum, - Dolor(bool), - Sit { amet: Consectetur, adipiscing: Elit }, -} diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/tests/source/else-if-brace-style-always-next-line.rs index 12208dd7c8b..7b4870fc65a 100644 --- a/tests/source/else-if-brace-style-always-next-line.rs +++ b/tests/source/else-if-brace-style-always-next-line.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-control_brace_style: AlwaysNextLine fn main() { diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/tests/source/else-if-brace-style-always-same-line.rs index c844275ef5b..41f5305bf8c 100644 --- a/tests/source/else-if-brace-style-always-same-line.rs +++ b/tests/source/else-if-brace-style-always-same-line.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-control_brace_style: AlwaysSameLine fn main() { diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/tests/source/else-if-brace-style-closing-next-line.rs index ccc8d7b0f3f..3b885b3faaa 100644 --- a/tests/source/else-if-brace-style-closing-next-line.rs +++ b/tests/source/else-if-brace-style-closing-next-line.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-control_brace_style: ClosingNextLine fn main() { diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs index a7173897b0d..f598ad881d0 100644 --- a/tests/source/hard-tabs.rs +++ b/tests/source/hard-tabs.rs @@ -1,5 +1,4 @@ // rustfmt-normalize_comments: true -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-wrap_comments: true // rustfmt-hard_tabs: true // rustfmt-error_on_line_overflow: false diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs index 3780ef7659f..bcde390d116 100644 --- a/tests/source/single-line-if-else.rs +++ b/tests/source/single-line-if-else.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 100 // Format if-else expressions on a single line, when possible. diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 9533e2f04b1..abb81d8119c 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -1,5 +1,4 @@ // rustfmt-normalize_comments: true -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-indent_style: Visual // Test chain formatting. @@ -21,11 +20,7 @@ fn main() { false => (), }); - loong_func().quux(move || if true { - 1 - } else { - 2 - }); + loong_func().quux(move || if true { 1 } else { 2 }); some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { let x = c; @@ -67,11 +62,7 @@ fn floaters() { field2: val2, }.method_call() .method_call(); - let y = if cond { - val1 - } else { - val2 - }.method_call(); + let y = if cond { val1 } else { val2 }.method_call(); { match x { diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 48691b3b6c9..00855de4f98 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,6 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-single_line_if_else_max_width: 0 -// rustfmt-chain_width: 100 +// rustfmt-use_small_heuristics: false // Test chain formatting. fn main() { @@ -102,11 +101,12 @@ fn floaters() { }.bar() .baz(); - Foo { x: val } - .baz(|| { - force(); - multiline(); - }) + Foo { + x: val, + }.baz(|| { + force(); + multiline(); + }) .quux(); Foo { @@ -152,9 +152,7 @@ fn try_shorthand() { .0 .x; - parameterized(f, substs, def_id, Ns::Value, &[], |tcx| { - tcx.lookup_item_type(def_id).generics - })?; + parameterized(f, substs, def_id, Ns::Value, &[], |tcx| tcx.lookup_item_type(def_id).generics)?; fooooooooooooooooooooooooooo()? .bar()? .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; diff --git a/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs b/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs deleted file mode 100644 index 78a3c828c5d..00000000000 --- a/tests/target/configs-array_horizontal_layout_threshold-1000-visual.rs +++ /dev/null @@ -1,96 +0,0 @@ -// rustfmt-array_horizontal_layout_threshold: 1000 -// rustfmt-indent_style: Visual - -const ARRAY: [u8; 2048] = - [99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, - 61, 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, 87, 69, 42, 38, 25, - 105, 6, 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, 29, 111, 120, 26, 0, 78, 36, 115, - 86, 66, 10, 52, 87, 27, 125, 122, 42, 126, 101, 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, - 124, 124, 102, 74, 35, 9, 83, 22, 121, 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, - 54, 17, 58, 105, 13, 96, 61, 99, 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, - 56, 5, 114, 11, 25, 16, 97, 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, - 58, 103, 2, 88, 85, 9, 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, - 97, 59, 39, 37, 79, 110, 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, 9, 21, - 65, 119, 2, 20, 64, 56, 34, 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, 61, 8, 124, 110, - 87, 64, 99, 26, 122, 56, 127, 94, 8, 121, 19, 24, 27, 61, 34, 44, 73, 82, 10, 49, 95, 72, 89, - 27, 124, 75, 33, 64, 48, 73, 21, 101, 34, 47, 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, - 31, 33, 84, 72, 128, 91, 3, 84, 92, 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, - 43, 66, 21, 90, 31, 102, 45, 66, 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, - 54, 11, 103, 45, 44, 101, 106, 53, 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, - 93, 34, 101, 48, 114, 127, 65, 69, 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, 92, 105, - 119, 17, 32, 23, 37, 8, 127, 99, 71, 54, 80, 109, 54, 51, 44, 20, 40, 52, 46, 81, 28, 46, 82, - 39, 39, 70, 3, 90, 41, 40, 36, 127, 48, 124, 26, 115, 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, - 46, 16, 65, 114, 53, 51, 123, 16, 36, 98, 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, - 48, 51, 54, 56, 105, 90, 50, 67, 111, 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, - 75, 29, 15, 15, 47, 33, 119, 85, 11, 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, - 86, 101, 79, 103, 98, 70, 122, 110, 38, 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, 36, - 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, 32, 96, 64, 71, 89, 108, 10, 106, 62, 86, 104, - 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, 111, 102, 4, 126, 95, 23, 68, 115, 106, 15, - 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, 7, 52, 77, 88, 8, 32, 3, 63, 77, 14, 86, - 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, 74, 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, - 67, 42, 109, 30, 93, 40, 113, 13, 85, 17, 51, 63, 57, 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, - 102, 25, 4, 113, 84, 63, 64, 63, 73, 83, 39, 123, 113, 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, - 81, 38, 55, 82, 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, 77, 74, 62, 126, 36, 110, 66, 4, 86, - 123, 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, 0, 59, 76, 47, 94, 6, 94, 86, 49, - 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, 18, 32, 69, 1, 83, 36, 38, 71, - 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, 79, 97, 49, 86, 7, 84, 40, 42, - 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, 50, 42, 34, 122, 116, 75, 31, 109, - 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, 114, 105, 16, 79, 53, 19, 78, 86, 110, 4, 43, 97, - 3, 18, 110, 84, 70, 23, 84, 23, 48, 125, 36, 58, 25, 90, 111, 103, 83, 38, 112, 127, 28, 53, - 86, 67, 78, 126, 86, 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, 90, 42, 108, 29, 72, - 86, 34, 91, 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, 52, 116, 65, 15, - 102, 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, 16, 31, 8, 58, - 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, 115, 44, 4, - 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, 20, 44, 46, 4, 116, - 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, 10, 36, 68, 94, 40, 87, 74, - 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, 40, 97, 43, 58, 16, 120, 74, 52, 42, - 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, 9, - 71, 92, 70, 57, 37, 42, 21, 83, 2, 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, - 52, 80, 94, 46, 18, 68, 72, 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, - 81, 45, 79, 121, 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, - 115, 29, 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, - 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, 101, 68, 26, - 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, 54, 69, 34, 22, 21, 54, - 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, 65, 40, 34, 12, 6, 127, 32, 90, 62, - 47, 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, - 45, 85, 40, 3, 114, 36, 23, 109, 118, 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, - 47, 126, 118, 105, 10, 59, 12, 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, - 106, 110, 49, 50, 20, 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, - 79, 85, 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, 126, - 104, 57, 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, 116, 114, 119, - 125, 61, 81, 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, 92, 70, 49, 59, 51, - 104, 103, 62, 96, 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, 2, 98, 47, 25, 100, 37, 42, 115, - 105, 42, 127, 65, 24, 102, 122, 33, 79, 87, 22, 47, 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, - 16, 113, 68, 20, 76, 99, 93, 121, 18, 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, - 6, 96, 12, 100, 33, 5, 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, - 114, 84, 125, 124, 113, 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, 110, - 96, 42, 4, 64, 41, 110, 97, 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, 115, 47, 80, - 55, 67, 92, 127, 120, 8, 42, 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, 81, 76, 66, 17, 108, - 55, 17, 50, 31, 64, 102, 88, 5, 32, 12, 37, 120, 48, 46, 43, 99, 12, 16, 114, 50, 49, 12, 3, - 63, 64, 27, 54, 53, 31, 73, 2, 15, 39, 102, 12, 60, 100, 27, 28, 24, 46, 101, 10, 104, 51, - 127, 101, 60, 55, 114, 25, 3, 29, 20, 53, 108, 7, 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, - 56, 80, 20, 117, 65, 53, 58, 66, 5, 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, - 31, 80, 29, 12, 115, 75, 84, 91, 91, 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, - 98, 118, 26, 19, 36, 35, 122, 29, 41, 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, - 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, 47, 2, 112, 2, 42, 126, 12, 15, 15, 109, 109, 97, - 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, 24, 21, 68, 42, 49, 69, 81, 111, 6, 11, 28, 5, - 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, 54, 25, 29, 60, 91, 72, 94, 15, 31, 98, 47, - 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, 96, 65, 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, - 103, 88, 22, 107, 38, 39, 100, 102, 96, 1, 66, 44, 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, - 19, 59, 87, 128, 16, 46, 51, 34, 34, 71, 117, 113, 66, 89, 126, 127, 35, 125, 11, 81, 120, - 100, 41, 51, 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, 95, 75, 31, 33, 84, 83, 22, 35, 99, - 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, 53, 57, 15, 82, 60, 101, 10, 16, - 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, 14, 35, 3, 51, 91, 16, 46, 117, - 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, 5, 21, 81, 43, 58, 61, 59, 39, - 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, 23, 64, 28, 32, 2, 119, 2, 55, 125, 57, - 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, 100, 98, 53, 116, 22, 64, 63, 112, 19, 60, 77, 95, - 32, 3, 2, 117, 41, 80, 96, 122, 15, 45, 118, 102, 26, 89, 74, 2, 17, 63, 21, 52, 23, 82, 97, - 22, 68, 39, 119, 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, 47, 59, 91, 46, 124, - 115, 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, 113, 45, 116, 125, 1, - 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, 47, 21, 103, 63, - 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, 104, 43, 73, 17, 111, 36, - 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, 54, 71, 38, 58, 86, 124, 3, 103, - 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, 62, 48, 115, 30, 19, 80, 14, 7, 21, 124, - 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, 58, - 45, 97, 8, 39, 125, 9, 22, 91, 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, - 106, 32, 105, 27, 0, 56, 66, 51, 4, 94, 72, 117, 69]; diff --git a/tests/target/configs-array_horizontal_layout_threshold-1000.rs b/tests/target/configs-array_horizontal_layout_threshold-1000.rs deleted file mode 100644 index 7c4347f9519..00000000000 --- a/tests/target/configs-array_horizontal_layout_threshold-1000.rs +++ /dev/null @@ -1,94 +0,0 @@ -// rustfmt-array_horizontal_layout_threshold: 1000 - -const ARRAY: [u8; 2048] = [ - 99, 72, 48, 104, 44, 112, 38, 62, 40, 93, 23, 24, 32, 21, 102, 76, 65, 29, 116, 21, 18, 37, 61, - 10, 108, 31, 85, 93, 2, 108, 103, 77, 109, 40, 92, 88, 114, 32, 31, 87, 69, 42, 38, 25, 105, 6, - 61, 128, 45, 6, 43, 81, 7, 3, 1, 125, 24, 123, 2, 29, 111, 120, 26, 0, 78, 36, 115, 86, 66, 10, - 52, 87, 27, 125, 122, 42, 126, 101, 70, 78, 90, 62, 72, 43, 3, 111, 8, 110, 11, 124, 124, 102, - 74, 35, 9, 83, 22, 121, 34, 70, 69, 52, 31, 92, 94, 67, 21, 76, 65, 10, 79, 54, 17, 58, 105, - 13, 96, 61, 99, 31, 87, 41, 78, 88, 120, 35, 95, 25, 80, 100, 45, 79, 49, 56, 5, 114, 11, 25, - 16, 97, 2, 43, 17, 71, 63, 102, 81, 55, 14, 59, 102, 55, 101, 119, 29, 58, 103, 2, 88, 85, 9, - 70, 91, 73, 37, 70, 123, 15, 68, 50, 76, 52, 46, 126, 87, 44, 85, 3, 97, 59, 39, 37, 79, 110, - 25, 109, 90, 124, 109, 6, 47, 60, 79, 15, 40, 3, 40, 20, 98, 9, 21, 65, 119, 2, 20, 64, 56, 34, - 116, 22, 125, 113, 57, 30, 21, 92, 76, 10, 107, 61, 8, 124, 110, 87, 64, 99, 26, 122, 56, 127, - 94, 8, 121, 19, 24, 27, 61, 34, 44, 73, 82, 10, 49, 95, 72, 89, 27, 124, 75, 33, 64, 48, 73, - 21, 101, 34, 47, 103, 114, 11, 31, 11, 93, 31, 54, 102, 117, 38, 31, 33, 84, 72, 128, 91, 3, - 84, 92, 48, 69, 39, 97, 113, 70, 26, 96, 107, 117, 76, 59, 50, 43, 66, 21, 90, 31, 102, 45, 66, - 5, 115, 63, 61, 83, 37, 16, 78, 22, 120, 52, 24, 25, 70, 71, 54, 11, 103, 45, 44, 101, 106, 53, - 39, 116, 83, 4, 68, 12, 59, 3, 37, 112, 123, 7, 120, 127, 93, 34, 101, 48, 114, 127, 65, 69, - 16, 79, 125, 18, 71, 69, 72, 54, 60, 107, 52, 18, 92, 105, 119, 17, 32, 23, 37, 8, 127, 99, 71, - 54, 80, 109, 54, 51, 44, 20, 40, 52, 46, 81, 28, 46, 82, 39, 39, 70, 3, 90, 41, 40, 36, 127, - 48, 124, 26, 115, 47, 93, 104, 4, 70, 88, 3, 4, 34, 75, 46, 16, 65, 114, 53, 51, 123, 16, 36, - 98, 36, 37, 36, 80, 71, 3, 116, 89, 52, 74, 7, 116, 39, 48, 51, 54, 56, 105, 90, 50, 67, 111, - 111, 7, 55, 87, 30, 15, 75, 50, 23, 9, 115, 2, 27, 45, 75, 29, 15, 15, 47, 33, 119, 85, 11, - 116, 127, 53, 37, 3, 0, 116, 77, 4, 37, 56, 8, 92, 105, 86, 101, 79, 103, 98, 70, 122, 110, 38, - 50, 52, 51, 62, 98, 95, 49, 21, 116, 30, 61, 1, 36, 96, 33, 78, 75, 23, 118, 88, 10, 4, 91, 38, - 32, 96, 64, 71, 89, 108, 10, 106, 62, 86, 104, 24, 117, 2, 72, 99, 60, 117, 109, 67, 112, 124, - 111, 102, 4, 126, 95, 23, 68, 115, 106, 15, 103, 101, 19, 30, 7, 29, 109, 62, 93, 22, 30, 106, - 7, 52, 77, 88, 8, 32, 3, 63, 77, 14, 86, 82, 114, 104, 119, 122, 40, 92, 3, 98, 128, 53, 74, - 40, 1, 94, 5, 112, 59, 29, 128, 119, 33, 67, 42, 109, 30, 93, 40, 113, 13, 85, 17, 51, 63, 57, - 4, 2, 102, 93, 25, 61, 39, 110, 56, 21, 102, 25, 4, 113, 84, 63, 64, 63, 73, 83, 39, 123, 113, - 68, 83, 95, 7, 23, 18, 73, 52, 16, 41, 81, 38, 55, 82, 59, 93, 6, 30, 25, 65, 67, 44, 99, 18, - 77, 74, 62, 126, 36, 110, 66, 4, 86, 123, 21, 109, 46, 93, 112, 107, 35, 14, 127, 112, 54, 65, - 0, 59, 76, 47, 94, 6, 94, 86, 49, 118, 44, 10, 15, 5, 105, 12, 28, 5, 94, 56, 31, 79, 86, 116, - 18, 32, 69, 1, 83, 36, 38, 71, 38, 71, 23, 71, 9, 30, 64, 2, 6, 21, 112, 55, 1, 43, 126, 33, - 79, 97, 49, 86, 7, 84, 40, 42, 25, 35, 51, 118, 56, 115, 104, 103, 20, 103, 95, 92, 43, 50, 42, - 34, 122, 116, 75, 31, 109, 53, 44, 6, 48, 1, 52, 119, 123, 32, 50, 63, 114, 105, 16, 79, 53, - 19, 78, 86, 110, 4, 43, 97, 3, 18, 110, 84, 70, 23, 84, 23, 48, 125, 36, 58, 25, 90, 111, 103, - 83, 38, 112, 127, 28, 53, 86, 67, 78, 126, 86, 8, 41, 76, 10, 54, 11, 22, 3, 12, 2, 50, 91, 82, - 90, 42, 108, 29, 72, 86, 34, 91, 115, 46, 86, 28, 46, 22, 97, 104, 48, 8, 22, 92, 10, 71, 102, - 52, 116, 65, 15, 102, 8, 113, 53, 110, 49, 81, 102, 48, 91, 32, 18, 67, 49, 124, 35, 83, 37, - 16, 31, 8, 58, 48, 77, 104, 71, 60, 40, 44, 74, 2, 40, 12, 22, 23, 49, 17, 98, 21, 83, 117, 64, - 115, 44, 4, 46, 70, 47, 115, 24, 66, 71, 80, 59, 32, 46, 81, 118, 8, 29, 93, 86, 81, 20, 44, - 46, 4, 116, 107, 117, 11, 30, 78, 13, 61, 110, 45, 101, 113, 34, 102, 19, 64, 10, 36, 68, 94, - 40, 87, 74, 105, 81, 70, 58, 44, 46, 108, 90, 60, 32, 36, 23, 115, 40, 97, 43, 58, 16, 120, 74, - 52, 42, 49, 16, 62, 122, 97, 107, 15, 104, 13, 17, 103, 49, 112, 123, 23, 107, 49, 40, 101, 62, - 9, 71, 92, 70, 57, 37, 42, 21, 83, 2, 20, 116, 22, 8, 34, 61, 56, 65, 115, 121, 116, 67, 111, - 52, 80, 94, 46, 18, 68, 72, 3, 61, 96, 127, 46, 7, 90, 100, 31, 30, 80, 123, 72, 74, 115, 74, - 81, 45, 79, 121, 57, 85, 117, 5, 88, 101, 97, 10, 12, 43, 57, 107, 83, 25, 12, 117, 103, 72, - 115, 29, 58, 101, 103, 120, 115, 74, 125, 127, 70, 7, 24, 92, 15, 103, 58, 83, 54, 75, 30, 9, - 111, 68, 53, 29, 25, 19, 96, 38, 93, 123, 126, 63, 115, 92, 119, 76, 50, 7, 9, 101, 68, 26, - 122, 5, 77, 4, 116, 89, 81, 21, 8, 111, 5, 33, 66, 121, 20, 106, 42, 54, 69, 34, 22, 21, 54, - 78, 46, 76, 64, 47, 44, 38, 84, 19, 73, 18, 92, 74, 63, 65, 40, 34, 12, 6, 127, 32, 90, 62, 47, - 42, 72, 121, 128, 44, 77, 121, 23, 105, 95, 43, 67, 63, 103, 22, 17, 45, 118, 28, 29, 17, 45, - 85, 40, 3, 114, 36, 23, 109, 118, 76, 16, 90, 111, 11, 98, 51, 127, 12, 68, 53, 116, 81, 47, - 126, 118, 105, 10, 59, 12, 101, 72, 114, 34, 19, 82, 68, 115, 12, 119, 123, 66, 21, 32, 106, - 110, 49, 50, 20, 3, 39, 119, 36, 53, 5, 13, 61, 70, 30, 57, 74, 61, 125, 39, 73, 9, 67, 79, 85, - 95, 74, 67, 61, 5, 30, 76, 39, 86, 32, 71, 108, 6, 49, 117, 60, 63, 57, 54, 107, 126, 104, 57, - 59, 120, 68, 6, 108, 81, 113, 126, 64, 36, 60, 123, 117, 13, 68, 8, 116, 114, 119, 125, 61, 81, - 98, 34, 53, 62, 11, 31, 117, 44, 54, 115, 30, 73, 69, 54, 92, 70, 49, 59, 51, 104, 103, 62, 96, - 121, 98, 26, 45, 77, 24, 124, 28, 70, 100, 2, 98, 47, 25, 100, 37, 42, 115, 105, 42, 127, 65, - 24, 102, 122, 33, 79, 87, 22, 47, 35, 50, 59, 54, 68, 16, 36, 91, 127, 39, 16, 113, 68, 20, 76, - 99, 93, 121, 18, 23, 6, 32, 108, 8, 114, 65, 81, 106, 39, 91, 54, 8, 92, 6, 96, 12, 100, 33, 5, - 105, 50, 89, 70, 33, 40, 85, 39, 93, 119, 26, 97, 90, 18, 74, 11, 105, 114, 84, 125, 124, 113, - 86, 124, 90, 90, 87, 64, 83, 121, 39, 108, 66, 23, 55, 43, 31, 110, 96, 42, 4, 64, 41, 110, 97, - 24, 95, 121, 125, 118, 85, 97, 110, 115, 75, 74, 60, 115, 47, 80, 55, 67, 92, 127, 120, 8, 42, - 5, 50, 55, 35, 117, 60, 106, 127, 77, 58, 81, 76, 66, 17, 108, 55, 17, 50, 31, 64, 102, 88, 5, - 32, 12, 37, 120, 48, 46, 43, 99, 12, 16, 114, 50, 49, 12, 3, 63, 64, 27, 54, 53, 31, 73, 2, 15, - 39, 102, 12, 60, 100, 27, 28, 24, 46, 101, 10, 104, 51, 127, 101, 60, 55, 114, 25, 3, 29, 20, - 53, 108, 7, 71, 4, 102, 14, 44, 72, 10, 56, 92, 86, 96, 56, 80, 20, 117, 65, 53, 58, 66, 5, - 103, 88, 17, 10, 34, 63, 83, 84, 43, 70, 41, 8, 111, 117, 31, 80, 29, 12, 115, 75, 84, 91, 91, - 10, 91, 26, 40, 30, 36, 44, 12, 18, 83, 29, 19, 15, 123, 98, 118, 26, 19, 36, 35, 122, 29, 41, - 23, 40, 74, 25, 70, 78, 24, 75, 109, 31, 0, 89, 45, 128, 35, 120, 79, 108, 89, 84, 84, 81, 108, - 47, 2, 112, 2, 42, 126, 12, 15, 15, 109, 109, 97, 76, 126, 5, 23, 66, 65, 1, 39, 102, 121, 127, - 24, 21, 68, 42, 49, 69, 81, 111, 6, 11, 28, 5, 89, 31, 74, 33, 118, 15, 55, 105, 107, 30, 103, - 54, 25, 29, 60, 91, 72, 94, 15, 31, 98, 47, 16, 27, 100, 109, 99, 82, 53, 25, 122, 119, 96, 65, - 4, 24, 50, 79, 40, 65, 6, 91, 125, 7, 80, 103, 88, 22, 107, 38, 39, 100, 102, 96, 1, 66, 44, - 33, 101, 88, 61, 10, 35, 39, 47, 93, 63, 19, 59, 87, 128, 16, 46, 51, 34, 34, 71, 117, 113, 66, - 89, 126, 127, 35, 125, 11, 81, 120, 100, 41, 51, 85, 30, 82, 68, 86, 114, 77, 56, 125, 10, 2, - 95, 75, 31, 33, 84, 83, 22, 35, 99, 12, 18, 40, 4, 88, 104, 46, 100, 99, 113, 45, 36, 51, 88, - 53, 57, 15, 82, 60, 101, 10, 16, 83, 23, 78, 47, 34, 27, 56, 85, 14, 14, 53, 20, 71, 101, 82, - 14, 35, 3, 51, 91, 16, 46, 117, 108, 30, 120, 124, 22, 89, 57, 119, 50, 91, 52, 77, 7, 10, 79, - 5, 21, 81, 43, 58, 61, 59, 39, 60, 122, 23, 68, 21, 19, 81, 3, 31, 64, 54, 126, 56, 23, 64, 28, - 32, 2, 119, 2, 55, 125, 57, 7, 51, 116, 93, 34, 15, 96, 120, 6, 73, 100, 98, 53, 116, 22, 64, - 63, 112, 19, 60, 77, 95, 32, 3, 2, 117, 41, 80, 96, 122, 15, 45, 118, 102, 26, 89, 74, 2, 17, - 63, 21, 52, 23, 82, 97, 22, 68, 39, 119, 117, 128, 49, 71, 55, 38, 55, 87, 3, 76, 80, 13, 57, - 47, 59, 91, 46, 124, 115, 7, 74, 95, 26, 128, 86, 16, 20, 107, 117, 10, 72, 35, 30, 128, 75, - 113, 45, 116, 125, 1, 46, 98, 14, 34, 29, 100, 17, 122, 65, 35, 69, 72, 12, 6, 5, 65, 29, 112, - 47, 21, 103, 63, 118, 75, 21, 99, 6, 36, 46, 86, 59, 9, 117, 23, 82, 75, 13, 4, 9, 104, 43, 73, - 17, 111, 36, 60, 38, 120, 99, 114, 117, 110, 27, 100, 104, 63, 87, 53, 54, 71, 38, 58, 86, 124, - 3, 103, 92, 79, 127, 97, 17, 103, 13, 25, 65, 12, 28, 89, 62, 48, 115, 30, 19, 80, 14, 7, 21, - 124, 91, 104, 110, 97, 97, 0, 104, 124, 93, 24, 70, 13, 99, 91, 73, 55, 84, 25, 22, 111, 115, - 58, 45, 97, 8, 39, 125, 9, 22, 91, 98, 19, 14, 54, 26, 33, 46, 61, 98, 122, 69, 72, 97, 71, 73, - 106, 32, 105, 27, 0, 56, 66, 51, 4, 94, 72, 117, 69, -]; diff --git a/tests/target/configs-array_width-above.rs b/tests/target/configs-array_width-above.rs deleted file mode 100644 index 1265ebe0d8b..00000000000 --- a/tests/target/configs-array_width-above.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-array_width: 10 -// Array width - -fn main() { - let lorem = vec![ - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ]; -} diff --git a/tests/target/configs-array_width-below.rs b/tests/target/configs-array_width-below.rs deleted file mode 100644 index d76d539773a..00000000000 --- a/tests/target/configs-array_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-array_width: 100 -// Array width - -fn main() { - let lorem = vec!["ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"]; -} diff --git a/tests/target/configs-chain_width-above.rs b/tests/target/configs-chain_width-above.rs deleted file mode 100644 index 1b5e12c331a..00000000000 --- a/tests/target/configs-chain_width-above.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-chain_width: 10 -// Chain one line max - -fn main() { - let lorem = ipsum - .dolor() - .sit() - .amet() - .consectetur() - .adipiscing() - .elit(); -} diff --git a/tests/target/configs-chain_width-below.rs b/tests/target/configs-chain_width-below.rs deleted file mode 100644 index d877deb74eb..00000000000 --- a/tests/target/configs-chain_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-chain_width: 100 -// Chain one line max - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elit(); -} diff --git a/tests/target/configs-fn_call_width-above.rs b/tests/target/configs-fn_call_width-above.rs deleted file mode 100644 index 3f84928ed59..00000000000 --- a/tests/target/configs-fn_call_width-above.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-fn_call_width: 10 -// Function call width - -fn main() { - lorem( - "lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ); -} diff --git a/tests/target/configs-fn_call_width-below.rs b/tests/target/configs-fn_call_width-below.rs deleted file mode 100644 index b79918f5b98..00000000000 --- a/tests/target/configs-fn_call_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_call_width: 100 -// Function call width - -fn main() { - lorem("lorem", "ipsum", "dolor"); -} diff --git a/tests/target/configs-fn_call_width-zero.rs b/tests/target/configs-fn_call_width-zero.rs deleted file mode 100644 index 1455ecd967c..00000000000 --- a/tests/target/configs-fn_call_width-zero.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-fn_call_width: 0 -// rustfmt-indent_style: block - -// #1508 -fn a() { - let x = f( - y, - ); -} diff --git a/tests/target/configs-single_line_if_else_max_width-above.rs b/tests/target/configs-single_line_if_else_max_width-above.rs deleted file mode 100644 index d883dbbb469..00000000000 --- a/tests/target/configs-single_line_if_else_max_width-above.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 10 -// Single line if-else max width - -fn main() { - let lorem = if ipsum { - dolor - } else { - sit - }; -} diff --git a/tests/target/configs-single_line_if_else_max_width-below.rs b/tests/target/configs-single_line_if_else_max_width-below.rs deleted file mode 100644 index efafa6c4498..00000000000 --- a/tests/target/configs-single_line_if_else_max_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-single_line_if_else_max_width: 100 -// Single line if-else max width - -fn main() { - let lorem = if ipsum { dolor } else { sit }; -} diff --git a/tests/target/configs-struct_lit_single_line-true.rs b/tests/target/configs-struct_lit_single_line-true.rs deleted file mode 100644 index 363bf5b114e..00000000000 --- a/tests/target/configs-struct_lit_single_line-true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-struct_lit_single_line: true -// rustfmt-struct_lit_width: 100 -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/target/configs-struct_lit_width-above.rs b/tests/target/configs-struct_lit_width-above.rs deleted file mode 100644 index 75a1a64095d..00000000000 --- a/tests/target/configs-struct_lit_width-above.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-struct_lit_width: 10 -// Struct literal-style - -fn main() { - let lorem = Lorem { - ipsum: dolor, - sit: amet, - }; -} diff --git a/tests/target/configs-struct_lit_width-below.rs b/tests/target/configs-struct_lit_width-below.rs deleted file mode 100644 index 7ffe4a32eaf..00000000000 --- a/tests/target/configs-struct_lit_width-below.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-struct_lit_width: 100 -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/target/configs-struct_variant_width-0.rs b/tests/target/configs-struct_variant_width-0.rs deleted file mode 100644 index 54c93d48031..00000000000 --- a/tests/target/configs-struct_variant_width-0.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-struct_variant_width: 0 - -// Force vertical layout when struct_variant_width is set to 0. - -enum State { - TryRecv { - pos: usize, - lap: u8, - closed_count: usize, - }, - Subscribe { - pos: usize, - }, - IsReady { - pos: usize, - ready: bool, - }, - Unsubscribe { - pos: usize, - lap: u8, - id_woken: usize, - }, - FinalTryRecv { - pos: usize, - id_woken: usize, - }, - TimedOut, - Disconnected, -} diff --git a/tests/target/configs-struct_variant_width-above.rs b/tests/target/configs-struct_variant_width-above.rs deleted file mode 100644 index 1fefbda81d5..00000000000 --- a/tests/target/configs-struct_variant_width-above.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-struct_variant_width: 10 -// Struct variant width - -enum Lorem { - Ipsum, - Dolor(bool), - Sit { - amet: Consectetur, - adipiscing: Elit, - }, -} diff --git a/tests/target/configs-struct_variant_width-below.rs b/tests/target/configs-struct_variant_width-below.rs deleted file mode 100644 index a16a57e19b8..00000000000 --- a/tests/target/configs-struct_variant_width-below.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-struct_variant_width: 100 -// Struct variant width - -enum Lorem { - Ipsum, - Dolor(bool), - Sit { amet: Consectetur, adipiscing: Elit }, -} diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs index 4a2ef877b85..c180ff697fc 100644 --- a/tests/target/else-if-brace-style-always-next-line.rs +++ b/tests/target/else-if-brace-style-always-next-line.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-control_brace_style: AlwaysNextLine fn main() { @@ -16,14 +15,7 @@ fn main() { } - let a = if 0 > 1 - { - unreachable!() - } - else - { - 0x0 - }; + let a = if 0 > 1 { unreachable!() } else { 0x0 }; if true diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs index 9baaa3f9b36..4c6153d5f1f 100644 --- a/tests/target/else-if-brace-style-always-same-line.rs +++ b/tests/target/else-if-brace-style-always-same-line.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-control_brace_style: AlwaysSameLine fn main() { @@ -15,11 +14,7 @@ fn main() { } - let a = if 0 > 1 { - unreachable!() - } else { - 0x0 - }; + let a = if 0 > 1 { unreachable!() } else { 0x0 }; if true { diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs index f1af1943431..04ee82bb828 100644 --- a/tests/target/else-if-brace-style-closing-next-line.rs +++ b/tests/target/else-if-brace-style-closing-next-line.rs @@ -1,4 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-control_brace_style: ClosingNextLine fn main() { @@ -15,12 +14,7 @@ fn main() { } - let a = if 0 > 1 { - unreachable!() - } - else { - 0x0 - }; + let a = if 0 > 1 { unreachable!() } else { 0x0 }; if true { diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 07a96214285..72d366b1fa1 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -1,5 +1,4 @@ // rustfmt-normalize_comments: true -// rustfmt-single_line_if_else_max_width: 0 // rustfmt-wrap_comments: true // rustfmt-hard_tabs: true // rustfmt-error_on_line_overflow: false @@ -73,13 +72,7 @@ fn main() { arg(a, b, c, d, e) } - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } - }); + loong_func().quux(move || if true { 1 } else { 2 }); fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { diff --git a/tests/target/issue-1802.rs b/tests/target/issue-1802.rs index 236a49f2ff3..a4679463ba2 100644 --- a/tests/target/issue-1802.rs +++ b/tests/target/issue-1802.rs @@ -1,11 +1,10 @@ // rustfmt-tab_spaces: 2 -// rustfmt-max_width: 10 -// rustfmt-struct_variant_width: 10 +// rustfmt-max_width: 30 // rustfmt-error_on_line_overflow: false enum F { X { - a: d, - b: e, + a: dddddddddddddd, + b: eeeeeeeeeeeeeee, }, } diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs index ac55d062134..98fd793cba2 100644 --- a/tests/target/single-line-if-else.rs +++ b/tests/target/single-line-if-else.rs @@ -1,5 +1,3 @@ -// rustfmt-single_line_if_else_max_width: 100 - // Format if-else expressions on a single line, when possible. fn main() { @@ -28,7 +26,11 @@ fn main() { 10 }; - let d = if let Some(val) = turbo { "cool" } else { "beans" }; + let d = if let Some(val) = turbo { + "cool" + } else { + "beans" + }; if cond() { statement(); @@ -46,7 +48,11 @@ fn main() { bbbbbbbbbb }; - let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; + let x = if veeeeeeeeery_loooooong_condition() { + aaaaaaaaaaaaaaaaaaaaaaaaa + } else { + bbbbbbbbbb + }; funk(if test() { 1 } else { 2 }, arg2); } -- cgit 1.4.1-3-g733a5 From 86007e7d17e1a669ebe0385e0c2e469ec0af5abe Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 24 Nov 2017 21:08:24 +1300 Subject: Remove `where_density` and `where_layout` options There is a choice between block and visual indent for where clauses, plus the single line option. I think these two are too fine-grained to be useful. --- Configurations.md | 159 --------------------- src/config.rs | 8 -- src/items.rs | 84 +++-------- tests/config/small_tabs.toml | 2 - tests/source/configs-where_density-compressed.rs | 10 -- .../configs-where_density-compressed_if_empty.rs | 10 -- tests/source/configs-where_density-tall.rs | 10 -- tests/source/configs-where_density-vertical.rs | 10 -- tests/source/configs-where_layout-horizontal.rs | 11 -- .../configs-where_layout-horizontal_vertical.rs | 10 -- tests/source/configs-where_layout-mixed.rs | 10 -- tests/source/configs-where_layout-vertical.rs | 10 -- tests/source/fn-custom-2.rs | 1 - tests/source/fn-custom-3.rs | 1 - tests/source/fn-custom-4.rs | 1 - tests/target/configs-where_density-compressed.rs | 12 -- .../configs-where_density-compressed_if_empty.rs | 14 -- tests/target/configs-where_density-tall.rs | 15 -- tests/target/configs-where_density-vertical.rs | 15 -- tests/target/configs-where_layout-horizontal.rs | 21 --- .../configs-where_layout-horizontal_vertical.rs | 20 --- tests/target/configs-where_layout-mixed.rs | 20 --- tests/target/configs-where_layout-vertical.rs | 20 --- tests/target/fn-custom-2.rs | 1 - tests/target/fn-custom-3.rs | 1 - tests/target/fn-custom-4.rs | 5 +- 26 files changed, 19 insertions(+), 462 deletions(-) delete mode 100644 tests/source/configs-where_density-compressed.rs delete mode 100644 tests/source/configs-where_density-compressed_if_empty.rs delete mode 100644 tests/source/configs-where_density-tall.rs delete mode 100644 tests/source/configs-where_density-vertical.rs delete mode 100644 tests/source/configs-where_layout-horizontal.rs delete mode 100644 tests/source/configs-where_layout-horizontal_vertical.rs delete mode 100644 tests/source/configs-where_layout-mixed.rs delete mode 100644 tests/source/configs-where_layout-vertical.rs delete mode 100644 tests/target/configs-where_density-compressed.rs delete mode 100644 tests/target/configs-where_density-compressed_if_empty.rs delete mode 100644 tests/target/configs-where_density-tall.rs delete mode 100644 tests/target/configs-where_density-vertical.rs delete mode 100644 tests/target/configs-where_layout-horizontal.rs delete mode 100644 tests/target/configs-where_layout-horizontal_vertical.rs delete mode 100644 tests/target/configs-where_layout-mixed.rs delete mode 100644 tests/target/configs-where_layout-vertical.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 968b5a2d634..498cf76eafe 100644 --- a/Configurations.md +++ b/Configurations.md @@ -241,8 +241,6 @@ fn lorem() -> T } ``` -See also: [`where_density`](#where_density), [`where_layout`](#where_layout). - ## `same_line_attributes` @@ -1869,163 +1867,6 @@ let lorem = try!(ipsum.map(|dolor|dolor.sit())); let lorem = ipsum.map(|dolor| dolor.sit())?; ``` -## `where_density` - -Density of a where clause. - -- **Default value**: `"Vertical"` -- **Possible values**: `"Compressed"`, `"CompressedIfEmpty"`, `"Tall"`, `"Vertical"` - -#### `"Vertical"` (default): - -```rust -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq, - { - // body - } -} -``` - -**Note:** `where_density = "Vertical"` currently produces the same output as `where_density = "Tall"`. - -#### `"CompressedIfEmpty"`: - -```rust -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq, - { - // body - } -} -``` - -#### `"Compressed"`: - -```rust -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq { - // body - } -} -``` - -#### `"Tall"`: - -```rust -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq, - { - // body - } -} -``` - -**Note:** `where_density = "Tall"` currently produces the same output as `where_density = "Vertical"`. - -See also: [`where_layout`](#where_layout), [`indent_style`](#indent_style). - -## `where_layout` - -Element layout inside a where clause - -- **Default value**: `"Vertical"` -- **Possible values**: `"Horizontal"`, `"HorizontalVertical"`, `"Mixed"`, `"Vertical"` - -#### `"Vertical"` (default): - -```rust -fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit -{ - // body -} -``` - -#### `"Horizontal"`: - -```rust -fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit -{ - // body -} -``` - -#### `"HorizontalVertical"`: - -```rust -fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit -{ - // body -} -``` - -#### `"Mixed"`: - -```rust -fn lorem(ipsum: Ipsum, dolor: Dolor) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) - where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit -{ - // body -} -``` - -See also: [`where_density`](#where_density), [`indent_style`](#indent_style). ## `wrap_comments` diff --git a/src/config.rs b/src/config.rs index 22c6cd6121d..808cde0e382 100644 --- a/src/config.rs +++ b/src/config.rs @@ -604,15 +604,7 @@ create_config! { impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - - // Where clauses - // TODO: - // 1. Should we at least try to put the where clause on the same line as the rest of the - // function decl? - // 2. Currently options `Tall` and `Vertical` produce the same output. - where_density: Density, Density::Vertical, false, "Density of a where clause"; where_single_line: bool, false, false, "To force single line where layout"; - where_layout: ListTactic, ListTactic::Vertical, false, "Element layout inside a where clause"; // Imports imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; diff --git a/src/items.rs b/src/items.rs index 695ee71f0c3..d1dd61bbc1c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -302,10 +302,7 @@ impl<'a> FmtVisitor<'a> { ) -> Option { let context = self.get_context(); - let has_body = - !is_empty_block(block, self.codemap) || !context.config.fn_empty_single_line(); - let mut newline_brace = - newline_for_brace(self.config, &fn_sig.generics.where_clause, has_body); + let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause); let (mut result, force_newline_brace) = rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; @@ -604,7 +601,7 @@ pub fn format_impl( &generics.where_clause, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), - context.config.where_density(), + Density::Vertical, "{", where_span_end, self_ty.span.hi(), @@ -978,18 +975,12 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&trait_bound_str); - let has_body = !trait_items.is_empty(); - - let where_density = if (context.config.where_density() == Density::Compressed - && (!result.contains('\n') || context.config.indent_style() == IndentStyle::Block)) - || (context.config.indent_style() == IndentStyle::Block && result.is_empty()) - || (context.config.where_density() == Density::CompressedIfEmpty && !has_body - && !result.contains('\n')) - { - Density::Compressed - } else { - Density::Tall - }; + let where_density = + if context.config.indent_style() == IndentStyle::Block && result.is_empty() { + Density::Compressed + } else { + Density::Tall + }; let where_budget = context.budget(last_line_width(&result)); let pos_before_where = if type_param_bounds.is_empty() { @@ -1373,7 +1364,7 @@ pub fn rewrite_type_alias( &generics.where_clause, context.config.brace_style(), Shape::legacy(where_budget, indent), - context.config.where_density(), + Density::Vertical, "=", Some(span.hi()), generics.span.hi(), @@ -2027,12 +2018,6 @@ fn rewrite_fn_base( } } - let should_compress_where = match context.config.where_density() { - Density::Compressed => !result.contains('\n'), - Density::CompressedIfEmpty => !has_body && !result.contains('\n'), - _ => false, - }; - let pos_before_where = match fd.output { ast::FunctionRetTy::Default(..) => args_span.hi(), ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), @@ -2040,26 +2025,6 @@ fn rewrite_fn_base( let is_args_multi_lined = arg_str.contains('\n'); - if where_clause.predicates.len() == 1 && should_compress_where { - let budget = context.budget(last_line_used_width(&result, indent.width())); - if let Some(where_clause_str) = rewrite_where_clause( - context, - where_clause, - context.config.brace_style(), - Shape::legacy(budget, indent), - Density::Compressed, - "{", - Some(span.hi()), - pos_before_where, - WhereClauseOption::compressed(), - is_args_multi_lined, - ) { - result.push_str(&where_clause_str); - force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - return Some((result, force_new_line_for_brace)); - } - } - let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); let where_clause_str = rewrite_where_clause( context, @@ -2115,14 +2080,6 @@ impl WhereClauseOption { } } - pub fn compressed() -> WhereClauseOption { - WhereClauseOption { - suppress_comma: true, - snuggle: false, - compress_where: true, - } - } - pub fn snuggled(current: &str) -> WhereClauseOption { WhereClauseOption { suppress_comma: false, @@ -2355,19 +2312,16 @@ fn compute_budgets_for_args( Some((0, context.budget(used_space), new_indent)) } -fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: bool) -> bool { +fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { let predicate_count = where_clause.predicates.len(); if config.where_single_line() && predicate_count == 1 { return false; } - match (config.brace_style(), config.where_density()) { - (BraceStyle::AlwaysNextLine, _) => true, - (_, Density::Compressed) if predicate_count == 1 => false, - (_, Density::CompressedIfEmpty) if predicate_count == 1 && !has_body => false, - (BraceStyle::SameLineWhere, _) if predicate_count > 0 => true, - _ => false, - } + let brace_style = config.brace_style(); + + brace_style == BraceStyle::AlwaysNextLine + || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0) } fn rewrite_generics( @@ -2694,14 +2648,8 @@ fn rewrite_where_clause( false, ); let item_vec = items.collect::>(); - // FIXME: we don't need to collect here if the where_layout isn't - // HorizontalVertical. - let tactic = definitive_tactic( - &item_vec, - context.config.where_layout(), - Separator::Comma, - budget, - ); + // FIXME: we don't need to collect here + let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget); let mut comma_tactic = context.config.trailing_comma(); // Kind of a hack because we don't usually have trailing commas in where clauses. diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 472df014435..d03ac281acb 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -4,8 +4,6 @@ tab_spaces = 2 newline_style = "Unix" brace_style = "SameLineWhere" fn_args_density = "Tall" -where_density = "Tall" -where_layout = "Vertical" trailing_comma = "Vertical" indent_style = "Block" report_todo = "Always" diff --git a/tests/source/configs-where_density-compressed.rs b/tests/source/configs-where_density-compressed.rs deleted file mode 100644 index d10c860db07..00000000000 --- a/tests/source/configs-where_density-compressed.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_density: Compressed -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq { - // body - } -} diff --git a/tests/source/configs-where_density-compressed_if_empty.rs b/tests/source/configs-where_density-compressed_if_empty.rs deleted file mode 100644 index 1d234a417d2..00000000000 --- a/tests/source/configs-where_density-compressed_if_empty.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_density: CompressedIfEmpty -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq { - // body - } -} diff --git a/tests/source/configs-where_density-tall.rs b/tests/source/configs-where_density-tall.rs deleted file mode 100644 index bf404715ec9..00000000000 --- a/tests/source/configs-where_density-tall.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_density: Tall -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq { - // body - } -} diff --git a/tests/source/configs-where_density-vertical.rs b/tests/source/configs-where_density-vertical.rs deleted file mode 100644 index dd4e1da9618..00000000000 --- a/tests/source/configs-where_density-vertical.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_density: Vertical -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit where Dolor: Eq { - // body - } -} diff --git a/tests/source/configs-where_layout-horizontal.rs b/tests/source/configs-where_layout-horizontal.rs deleted file mode 100644 index 0d676b74d7b..00000000000 --- a/tests/source/configs-where_layout-horizontal.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-where_layout: Horizontal -// rustfmt-error_on_line_overflow: false -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur { - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/source/configs-where_layout-horizontal_vertical.rs b/tests/source/configs-where_layout-horizontal_vertical.rs deleted file mode 100644 index dd389dbfd39..00000000000 --- a/tests/source/configs-where_layout-horizontal_vertical.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_layout: HorizontalVertical -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur { - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/source/configs-where_layout-mixed.rs b/tests/source/configs-where_layout-mixed.rs deleted file mode 100644 index c3b78b2cd2e..00000000000 --- a/tests/source/configs-where_layout-mixed.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_layout: Mixed -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur { - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/source/configs-where_layout-vertical.rs b/tests/source/configs-where_layout-vertical.rs deleted file mode 100644 index 76f2ed0bb4d..00000000000 --- a/tests/source/configs-where_layout-vertical.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-where_layout: Vertical -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur { - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) where Ipsum: IpsumDolorSitAmet, Dolor: DolorSitAmetConsectetur, Sit: SitAmetConsecteturAdipiscing, Amet: AmetConsecteturAdipiscingElit { - // body -} diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs index 4fb427a1b1f..72d841544a8 100644 --- a/tests/source/fn-custom-2.rs +++ b/tests/source/fn-custom-2.rs @@ -1,5 +1,4 @@ // rustfmt-indent_style: Block -// rustfmt-where_layout: Mixed // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs index efaf559c9da..9934fb61efd 100644 --- a/tests/source/fn-custom-3.rs +++ b/tests/source/fn-custom-3.rs @@ -1,5 +1,4 @@ // rustfmt-indent_style: Block -// rustfmt-where_layout: HorizontalVertical // Test different indents. fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { diff --git a/tests/source/fn-custom-4.rs b/tests/source/fn-custom-4.rs index 668cdce382d..01c00aecb86 100644 --- a/tests/source/fn-custom-4.rs +++ b/tests/source/fn-custom-4.rs @@ -1,5 +1,4 @@ // rustfmt-indent_style: Block -// rustfmt-where_density: Compressed // Test different indents. fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { diff --git a/tests/target/configs-where_density-compressed.rs b/tests/target/configs-where_density-compressed.rs deleted file mode 100644 index deddbee459f..00000000000 --- a/tests/target/configs-where_density-compressed.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-where_density: Compressed -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq { - // body - } -} diff --git a/tests/target/configs-where_density-compressed_if_empty.rs b/tests/target/configs-where_density-compressed_if_empty.rs deleted file mode 100644 index 45f22eb602c..00000000000 --- a/tests/target/configs-where_density-compressed_if_empty.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-where_density: CompressedIfEmpty -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq, - { - // body - } -} diff --git a/tests/target/configs-where_density-tall.rs b/tests/target/configs-where_density-tall.rs deleted file mode 100644 index e256f1c221c..00000000000 --- a/tests/target/configs-where_density-tall.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-where_density: Tall -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq, - { - // body - } -} diff --git a/tests/target/configs-where_density-vertical.rs b/tests/target/configs-where_density-vertical.rs deleted file mode 100644 index 96ac111ba74..00000000000 --- a/tests/target/configs-where_density-vertical.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-where_density: Vertical -// Where density - -trait Lorem { - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq; - - fn ipsum(dolor: Dolor) -> Sit - where - Dolor: Eq, - { - // body - } -} diff --git a/tests/target/configs-where_layout-horizontal.rs b/tests/target/configs-where_layout-horizontal.rs deleted file mode 100644 index 062f62ff4e7..00000000000 --- a/tests/target/configs-where_layout-horizontal.rs +++ /dev/null @@ -1,21 +0,0 @@ -// rustfmt-where_layout: Horizontal -// rustfmt-error_on_line_overflow: false -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit, -{ - // body -} diff --git a/tests/target/configs-where_layout-horizontal_vertical.rs b/tests/target/configs-where_layout-horizontal_vertical.rs deleted file mode 100644 index 56d125e1cf7..00000000000 --- a/tests/target/configs-where_layout-horizontal_vertical.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-where_layout: HorizontalVertical -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit, -{ - // body -} diff --git a/tests/target/configs-where_layout-mixed.rs b/tests/target/configs-where_layout-mixed.rs deleted file mode 100644 index fa896b77267..00000000000 --- a/tests/target/configs-where_layout-mixed.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-where_layout: Mixed -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit, -{ - // body -} diff --git a/tests/target/configs-where_layout-vertical.rs b/tests/target/configs-where_layout-vertical.rs deleted file mode 100644 index 024a74dd9ac..00000000000 --- a/tests/target/configs-where_layout-vertical.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-where_layout: Vertical -// Where layout - -fn lorem(ipsum: Ipsum, dolor: Dolor) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, -{ - // body -} - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) -where - Ipsum: IpsumDolorSitAmet, - Dolor: DolorSitAmetConsectetur, - Sit: SitAmetConsecteturAdipiscing, - Amet: AmetConsecteturAdipiscingElit, -{ - // body -} diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs index bf528989fd4..c2b3580c668 100644 --- a/tests/target/fn-custom-2.rs +++ b/tests/target/fn-custom-2.rs @@ -1,5 +1,4 @@ // rustfmt-indent_style: Block -// rustfmt-where_layout: Mixed // Test different indents. fn foo( diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs index 6561140196b..baa1e39231b 100644 --- a/tests/target/fn-custom-3.rs +++ b/tests/target/fn-custom-3.rs @@ -1,5 +1,4 @@ // rustfmt-indent_style: Block -// rustfmt-where_layout: HorizontalVertical // Test different indents. fn foo( diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs index 35895f386d0..0a223ef5fac 100644 --- a/tests/target/fn-custom-4.rs +++ b/tests/target/fn-custom-4.rs @@ -1,5 +1,4 @@ // rustfmt-indent_style: Block -// rustfmt-where_density: Compressed // Test different indents. fn qux() @@ -13,7 +12,9 @@ where } fn qux() -where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ baz(); } -- cgit 1.4.1-3-g733a5 From 0e1fa2c244f030e93643a2e34d6f07636cb792a6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 27 Nov 2017 15:49:14 +1300 Subject: Remove `indent_match_arms` --- Configurations.md | 34 ++----------------------- src/config.rs | 6 ++--- src/expr.rs | 16 +++--------- tests/source/configs-indent_match_arms-false.rs | 8 ------ tests/source/configs-indent_match_arms-true.rs | 8 ------ tests/source/indent_match_arms.rs | 26 ------------------- tests/target/configs-indent_match_arms-false.rs | 11 -------- tests/target/configs-indent_match_arms-true.rs | 11 -------- tests/target/indent_match_arms.rs | 26 ------------------- 9 files changed, 8 insertions(+), 138 deletions(-) delete mode 100644 tests/source/configs-indent_match_arms-false.rs delete mode 100644 tests/source/configs-indent_match_arms-true.rs delete mode 100644 tests/source/indent_match_arms.rs delete mode 100644 tests/target/configs-indent_match_arms-false.rs delete mode 100644 tests/target/configs-indent_match_arms-true.rs delete mode 100644 tests/target/indent_match_arms.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 498cf76eafe..ce0a56b0f1c 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1026,36 +1026,6 @@ impl Lorem { See also [`brace_style`](#brace_style). -## `indent_match_arms` - -Indent match arms instead of keeping them at the same indentation level as the match keyword - -- **Default value**: `true` -- **Possible values**: `true`, `false` - -#### `true` (default): - -```rust -match lorem { - Lorem::Ipsum => (), - Lorem::Dolor => (), - Lorem::Sit => (), - Lorem::Amet => (), -} -``` - -#### `false`: - -```rust -match lorem { -Lorem::Ipsum => (), -Lorem::Dolor => (), -Lorem::Sit => (), -Lorem::Amet => (), -} -``` - -See also: [`match_block_trailing_comma`](#match_block_trailing_comma), [`wrap_match_arms`](#wrap_match_arms). ## `imports_indent` @@ -1209,7 +1179,7 @@ match lorem { } ``` -See also: [`indent_match_arms`](#indent_match_arms), [`trailing_comma`](#trailing_comma), [`wrap_match_arms`](#wrap_match_arms). +See also: [`trailing_comma`](#trailing_comma), [`wrap_match_arms`](#wrap_match_arms). ## `max_width` @@ -1919,7 +1889,7 @@ match lorem { } ``` -See also: [`indent_match_arms`](#indent_match_arms), [`match_block_trailing_comma`](#match_block_trailing_comma). +See also: [`match_block_trailing_comma`](#match_block_trailing_comma). ## `write_mode` diff --git a/src/config.rs b/src/config.rs index 808cde0e382..51e593e0f2a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -621,14 +621,12 @@ create_config! { // Match wrap_match_arms: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; + multiline_match_arm_forces_block: bool, false, false, + "Force multiline match arm bodies to be wrapped in a block"; match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; match_arm_forces_newline: bool, false, false, "Force match arm bodies to be in a new lines"; - indent_match_arms: bool, true, false, "Indent match arms instead of keeping them at the same \ - indentation level as the match keyword"; - multiline_match_arm_forces_block: bool, false, false, - "Force multiline match arm bodies to be wrapped in a block"; // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, diff --git a/src/expr.rs b/src/expr.rs index 9c82b75a65b..dc44f20d1b3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1284,12 +1284,6 @@ fn rewrite_match( inner_attrs[inner_attrs.len() - 1].span().hi() }; - let arm_indent_str = if context.config.indent_match_arms() { - nested_indent_str - } else { - shape.indent.to_string(context.config) - }; - if arms.is_empty() { let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); if snippet.trim().is_empty() { @@ -1304,7 +1298,7 @@ fn rewrite_match( cond_str, block_sep, inner_attrs_str, - arm_indent_str, + nested_indent_str, rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, shape.indent.to_string(context.config), )) @@ -1334,11 +1328,9 @@ fn rewrite_match_arms( span: Span, open_brace_pos: BytePos, ) -> Option { - let arm_shape = if context.config.indent_match_arms() { - shape.block_indent(context.config.tab_spaces()) - } else { - shape.block_indent(0) - }.with_max_width(context.config); + let arm_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); let arm_len = arms.len(); let is_last_iter = repeat(false) diff --git a/tests/source/configs-indent_match_arms-false.rs b/tests/source/configs-indent_match_arms-false.rs deleted file mode 100644 index 3bd9fc4dd7d..00000000000 --- a/tests/source/configs-indent_match_arms-false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-indent_match_arms: false -// Indent match arms - -fn main() { - match lorem { - Lorem::Ipsum => (), Lorem::Dolor => (), Lorem::Sit => (), Lorem::Amet => (), - } -} diff --git a/tests/source/configs-indent_match_arms-true.rs b/tests/source/configs-indent_match_arms-true.rs deleted file mode 100644 index aa657980806..00000000000 --- a/tests/source/configs-indent_match_arms-true.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-indent_match_arms: true -// Indent match arms - -fn main() { - match lorem { - Lorem::Ipsum => (), Lorem::Dolor => (), Lorem::Sit => (), Lorem::Amet => (), - } -} diff --git a/tests/source/indent_match_arms.rs b/tests/source/indent_match_arms.rs deleted file mode 100644 index 75cee57f10d..00000000000 --- a/tests/source/indent_match_arms.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-indent_match_arms: false - -fn main() { - match x { - 1 => "one", - 2 => "two", - 3 => "three", - 4 => "four", - 5 => "five", - _ => "something else", - } - - match x { - 1 => "one", - 2 => "two", - 3 => "three", - 4 => "four", - 5 => match y { - 'a' => 'A', - 'b' => 'B', - 'c' => 'C', - _ => "Nope", - }, - _ => "something else", - } -} diff --git a/tests/target/configs-indent_match_arms-false.rs b/tests/target/configs-indent_match_arms-false.rs deleted file mode 100644 index 3084e01d45f..00000000000 --- a/tests/target/configs-indent_match_arms-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_match_arms: false -// Indent match arms - -fn main() { - match lorem { - Lorem::Ipsum => (), - Lorem::Dolor => (), - Lorem::Sit => (), - Lorem::Amet => (), - } -} diff --git a/tests/target/configs-indent_match_arms-true.rs b/tests/target/configs-indent_match_arms-true.rs deleted file mode 100644 index 02e2368378f..00000000000 --- a/tests/target/configs-indent_match_arms-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_match_arms: true -// Indent match arms - -fn main() { - match lorem { - Lorem::Ipsum => (), - Lorem::Dolor => (), - Lorem::Sit => (), - Lorem::Amet => (), - } -} diff --git a/tests/target/indent_match_arms.rs b/tests/target/indent_match_arms.rs deleted file mode 100644 index 8d5e7ef7887..00000000000 --- a/tests/target/indent_match_arms.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-indent_match_arms: false - -fn main() { - match x { - 1 => "one", - 2 => "two", - 3 => "three", - 4 => "four", - 5 => "five", - _ => "something else", - } - - match x { - 1 => "one", - 2 => "two", - 3 => "three", - 4 => "four", - 5 => match y { - 'a' => 'A', - 'b' => 'B', - 'c' => 'C', - _ => "Nope", - }, - _ => "something else", - } -} -- cgit 1.4.1-3-g733a5 From 087f8b58545519aec6cca7a0a69feb7b0738455e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 27 Nov 2017 16:31:49 +1300 Subject: Remove `match_arm_forces_newline` --- Configurations.md | 41 -------------------- src/config.rs | 2 - src/expr.rs | 7 +--- .../configs-match_arm_forces_newline-true.rs | 20 ---------- .../configs-match_arm_forces_newline-true.rs | 44 ---------------------- 5 files changed, 1 insertion(+), 113 deletions(-) delete mode 100644 tests/source/configs-match_arm_forces_newline-true.rs delete mode 100644 tests/target/configs-match_arm_forces_newline-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ce0a56b0f1c..ee4851eb2e5 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1108,47 +1108,6 @@ use foo::{aaa, fff}; ``` -## `match_arm_forces_newline` - -Consistently put match arms (block based or not) in a newline. - -- **Default value**: `false` -- **Possible values**: `true`, `false` - -#### `false` (default): - -```rust -match x { - // a non-empty block - X0 => { - f(); - } - // an empty block - X1 => {} - // a non-block - X2 => println!("ok"), -} -``` - -#### `true`: - -```rust -match x { - // a non-empty block - X0 => { - f(); - } - // an empty block - X1 => - {} - // a non-block - X2 => { - println!("ok") - } -} -``` - -See also: [`wrap_match_arms`](#wrap_match_arms). ## `match_block_trailing_comma` diff --git a/src/config.rs b/src/config.rs index 51e593e0f2a..fe18f02d33e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -625,8 +625,6 @@ create_config! { "Force multiline match arm bodies to be wrapped in a block"; match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - match_arm_forces_newline: bool, false, false, - "Force match arm bodies to be in a new lines"; // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, diff --git a/src/expr.rs b/src/expr.rs index dc44f20d1b3..14913fef9e7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1529,11 +1529,6 @@ fn rewrite_match_body( } else { (false, false) }; - let extend = if context.config.match_arm_forces_newline() { - is_block - } else { - extend - }; let comma = arm_comma(context.config, body, is_last); let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); @@ -1606,7 +1601,7 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if !forbid_same_line && !context.config.match_arm_forces_newline() + if !forbid_same_line && (is_block || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => { diff --git a/tests/source/configs-match_arm_forces_newline-true.rs b/tests/source/configs-match_arm_forces_newline-true.rs deleted file mode 100644 index e9c8d575f1d..00000000000 --- a/tests/source/configs-match_arm_forces_newline-true.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-match_arm_forces_newline: true -// rustfmt-wrap_match_arms: false - -// match_arm_forces_newline puts all match arms bodies in a newline and indents -// them. - -fn main() { - match x() { - // a short non-empty block - X0 => { f(); } - // a long non-empty block - X1 => { some.really.long.expression.fooooooooooooooooooooooooooooooooooooooooo().baaaaarrrrrrrrrrrrrrrrrrrrrrrrrr(); } - // an empty block - X2 => {} - // a short non-block - X3 => println!("ok"), - // a long non-block - X4 => foo.bar.baz.test.x.y.z.a.s.d.fasdfasdf.asfads.fasd.fasdfasdf.dfasfdsaf(), - } -} diff --git a/tests/target/configs-match_arm_forces_newline-true.rs b/tests/target/configs-match_arm_forces_newline-true.rs deleted file mode 100644 index 5629a56d664..00000000000 --- a/tests/target/configs-match_arm_forces_newline-true.rs +++ /dev/null @@ -1,44 +0,0 @@ -// rustfmt-match_arm_forces_newline: true -// rustfmt-wrap_match_arms: false - -// match_arm_forces_newline puts all match arms bodies in a newline and indents -// them. - -fn main() { - match x() { - // a short non-empty block - X0 => { - f(); - } - // a long non-empty block - X1 => { - some.really - .long - .expression - .fooooooooooooooooooooooooooooooooooooooooo() - .baaaaarrrrrrrrrrrrrrrrrrrrrrrrrr(); - } - // an empty block - X2 => - {} - // a short non-block - X3 => - println!("ok"), - // a long non-block - X4 => - foo.bar - .baz - .test - .x - .y - .z - .a - .s - .d - .fasdfasdf - .asfads - .fasd - .fasdfasdf - .dfasfdsaf(), - } -} -- cgit 1.4.1-3-g733a5 From 8f4d85a9d727440b246aee8f54549c5c72022700 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 27 Nov 2017 17:01:49 +1300 Subject: Merge multiline_closure_forces_block and multiline_match_arm_forces_block into force_multiline_block --- Configurations.md | 34 +++++++--------------- src/closures.rs | 2 +- src/config.rs | 6 ++-- src/expr.rs | 6 ++-- .../source/configs-force_multiline_block-false.rs | 22 ++++++++++++++ tests/source/configs-force_multiline_block-true.rs | 18 ++++++++++++ ...configs-multiline_closure_forces_block-false.rs | 11 ------- .../configs-multiline_closure_forces_block-true.rs | 9 ------ ...nfigs-multiline_match_arm_forces_block-false.rs | 13 --------- ...onfigs-multiline_match_arm_forces_block-true.rs | 11 ------- .../target/configs-force_multiline_block-false.rs | 18 ++++++++++++ tests/target/configs-force_multiline_block-true.rs | 22 ++++++++++++++ ...configs-multiline_closure_forces_block-false.rs | 9 ------ .../configs-multiline_closure_forces_block-true.rs | 11 ------- ...nfigs-multiline_match_arm_forces_block-false.rs | 11 ------- ...onfigs-multiline_match_arm_forces_block-true.rs | 13 --------- 16 files changed, 95 insertions(+), 121 deletions(-) create mode 100644 tests/source/configs-force_multiline_block-false.rs create mode 100644 tests/source/configs-force_multiline_block-true.rs delete mode 100644 tests/source/configs-multiline_closure_forces_block-false.rs delete mode 100644 tests/source/configs-multiline_closure_forces_block-true.rs delete mode 100644 tests/source/configs-multiline_match_arm_forces_block-false.rs delete mode 100644 tests/source/configs-multiline_match_arm_forces_block-true.rs create mode 100644 tests/target/configs-force_multiline_block-false.rs create mode 100644 tests/target/configs-force_multiline_block-true.rs delete mode 100644 tests/target/configs-multiline_closure_forces_block-false.rs delete mode 100644 tests/target/configs-multiline_closure_forces_block-true.rs delete mode 100644 tests/target/configs-multiline_match_arm_forces_block-false.rs delete mode 100644 tests/target/configs-multiline_match_arm_forces_block-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ee4851eb2e5..76589314e03 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1172,9 +1172,9 @@ pub enum Foo {} pub enum Foo {} ``` -## `multiline_closure_forces_block` +## `force_multiline_blocks` -Force multiline closure bodies to be wrapped in a block +Force multiline closure and match arm bodies to be wrapped in a block - **Default value**: `false` - **Possible values**: `false`, `true` @@ -1186,6 +1186,13 @@ result.and_then(|maybe_value| match maybe_value { None => ..., Some(value) => ..., }) + +match lorem { + None => if ipsum { + println!("Hello World"); + }, + Some(dolor) => ..., +} ``` #### `true`: @@ -1198,29 +1205,7 @@ result.and_then(|maybe_value| { Some(value) => ..., } }) -``` - -## `multiline_match_arm_forces_block` - -Force multiline match arm bodies to be wrapped in a block - -- **Default value**: `false` -- **Possible values**: `false`, `true` - -#### `false` (default): - -```rust -match lorem { - None => if ipsum { - println!("Hello World"); - }, - Some(dolor) => ..., -} -``` -#### `true`: - -```rust match lorem { None => { if ipsum { @@ -1231,6 +1216,7 @@ match lorem { } ``` + ## `newline_style` Unix or Windows line endings diff --git a/src/closures.rs b/src/closures.rs index ebc12382bd7..71862b82ba0 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -146,7 +146,7 @@ fn rewrite_closure_expr( rewrite = and_one_line(rewrite); } rewrite = rewrite.and_then(|rw| { - if context.config.multiline_closure_forces_block() && rw.contains('\n') { + if context.config.force_multiline_blocks() && rw.contains('\n') { None } else { Some(rw) diff --git a/src/config.rs b/src/config.rs index fe18f02d33e..c6225222231 100644 --- a/src/config.rs +++ b/src/config.rs @@ -621,8 +621,6 @@ create_config! { // Match wrap_match_arms: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; - multiline_match_arm_forces_block: bool, false, false, - "Force multiline match arm bodies to be wrapped in a block"; match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; @@ -645,8 +643,8 @@ create_config! { "Remove blank lines at start or end of a block"; same_line_attributes: bool, true, false, "Try to put attributes on the same line as fields and variants."; - multiline_closure_forces_block: bool, false, false, - "Force multiline closure bodies to be wrapped in a block"; + force_multiline_blocks: bool, false, false, + "Force multiline closure bodies and match arms to be wrapped in a block"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, diff --git a/src/expr.rs b/src/expr.rs index 14913fef9e7..9d29425a5dd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1499,8 +1499,7 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( - !context.config.multiline_match_arm_forces_block() - && expr.can_be_overflowed(context, 1), + !context.config.force_multiline_blocks() && expr.can_be_overflowed(context, 1), &**expr, ) } else { @@ -1508,8 +1507,7 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo } } _ => ( - !context.config.multiline_match_arm_forces_block() - && body.can_be_overflowed(context, 1), + !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), &*body, ), } diff --git a/tests/source/configs-force_multiline_block-false.rs b/tests/source/configs-force_multiline_block-false.rs new file mode 100644 index 00000000000..b97e348e5da --- /dev/null +++ b/tests/source/configs-force_multiline_block-false.rs @@ -0,0 +1,22 @@ +// rustfmt-force_multiline_blocks: false +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/tests/source/configs-force_multiline_block-true.rs b/tests/source/configs-force_multiline_block-true.rs new file mode 100644 index 00000000000..db9d3de4614 --- /dev/null +++ b/tests/source/configs-force_multiline_block-true.rs @@ -0,0 +1,18 @@ +// rustfmt-force_multiline_blocks: true +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => if ipsum { + println!("dolor"); + }, + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/tests/source/configs-multiline_closure_forces_block-false.rs b/tests/source/configs-multiline_closure_forces_block-false.rs deleted file mode 100644 index e885dff5ee6..00000000000 --- a/tests/source/configs-multiline_closure_forces_block-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-multiline_closure_forces_block: false -// Option forces multiline closure bodies to be wrapped in a block - -fn main() { - result.and_then(|maybe_value| { - match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - } - }); -} diff --git a/tests/source/configs-multiline_closure_forces_block-true.rs b/tests/source/configs-multiline_closure_forces_block-true.rs deleted file mode 100644 index f267466ac66..00000000000 --- a/tests/source/configs-multiline_closure_forces_block-true.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-multiline_closure_forces_block: true -// Option forces multiline closure bodies to be wrapped in a block - -fn main() { - result.and_then(|maybe_value| match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - }); -} diff --git a/tests/source/configs-multiline_match_arm_forces_block-false.rs b/tests/source/configs-multiline_match_arm_forces_block-false.rs deleted file mode 100644 index 4cbec0c7c1c..00000000000 --- a/tests/source/configs-multiline_match_arm_forces_block-false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-multiline_match_arm_forces_block: false -// Option forces multiline match arm bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} diff --git a/tests/source/configs-multiline_match_arm_forces_block-true.rs b/tests/source/configs-multiline_match_arm_forces_block-true.rs deleted file mode 100644 index 602076a4e74..00000000000 --- a/tests/source/configs-multiline_match_arm_forces_block-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-multiline_match_arm_forces_block: true -// Option forces multiline match arm bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => if ipsum { - println!("dolor"); - }, - Lorem::Dolor => println!("amet"), - } -} diff --git a/tests/target/configs-force_multiline_block-false.rs b/tests/target/configs-force_multiline_block-false.rs new file mode 100644 index 00000000000..11ccc9a7512 --- /dev/null +++ b/tests/target/configs-force_multiline_block-false.rs @@ -0,0 +1,18 @@ +// rustfmt-force_multiline_blocks: false +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => if ipsum { + println!("dolor"); + }, + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/tests/target/configs-force_multiline_block-true.rs b/tests/target/configs-force_multiline_block-true.rs new file mode 100644 index 00000000000..aec50afe5a8 --- /dev/null +++ b/tests/target/configs-force_multiline_block-true.rs @@ -0,0 +1,22 @@ +// rustfmt-force_multiline_blocks: true +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/tests/target/configs-multiline_closure_forces_block-false.rs b/tests/target/configs-multiline_closure_forces_block-false.rs deleted file mode 100644 index 7fb3d597da1..00000000000 --- a/tests/target/configs-multiline_closure_forces_block-false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-multiline_closure_forces_block: false -// Option forces multiline closure bodies to be wrapped in a block - -fn main() { - result.and_then(|maybe_value| match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - }); -} diff --git a/tests/target/configs-multiline_closure_forces_block-true.rs b/tests/target/configs-multiline_closure_forces_block-true.rs deleted file mode 100644 index 01e2de43527..00000000000 --- a/tests/target/configs-multiline_closure_forces_block-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-multiline_closure_forces_block: true -// Option forces multiline closure bodies to be wrapped in a block - -fn main() { - result.and_then(|maybe_value| { - match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - } - }); -} diff --git a/tests/target/configs-multiline_match_arm_forces_block-false.rs b/tests/target/configs-multiline_match_arm_forces_block-false.rs deleted file mode 100644 index 3c4c1470b0f..00000000000 --- a/tests/target/configs-multiline_match_arm_forces_block-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-multiline_match_arm_forces_block: false -// Option forces multiline match arm bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => if ipsum { - println!("dolor"); - }, - Lorem::Dolor => println!("amet"), - } -} diff --git a/tests/target/configs-multiline_match_arm_forces_block-true.rs b/tests/target/configs-multiline_match_arm_forces_block-true.rs deleted file mode 100644 index c36d59c315c..00000000000 --- a/tests/target/configs-multiline_match_arm_forces_block-true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-multiline_match_arm_forces_block: true -// Option forces multiline match arm bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} -- cgit 1.4.1-3-g733a5 From 9a332558348cda0c5f0e2a1647b8e8be38553784 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 27 Nov 2017 17:35:27 +1300 Subject: Rename wrap_match_arms to match_arm_blocks --- Configurations.md | 4 ++-- src/config.rs | 10 ++++------ src/expr.rs | 2 +- tests/source/configs-match_arm_blocks-false.rs | 11 +++++++++++ tests/source/configs-match_arm_blocks-true.rs | 11 +++++++++++ tests/source/configs-wrap_match_arms-false.rs | 11 ----------- tests/source/configs-wrap_match_arms-true.rs | 11 ----------- tests/source/issue-1127.rs | 2 +- tests/source/match-nowrap-trailing-comma.rs | 2 +- tests/source/match-nowrap.rs | 2 +- tests/target/configs-control_style-rfc.rs | 2 +- tests/target/configs-match_arm_blocks-false.rs | 10 ++++++++++ tests/target/configs-match_arm_blocks-true.rs | 11 +++++++++++ tests/target/configs-wrap_match_arms-false.rs | 10 ---------- tests/target/configs-wrap_match_arms-true.rs | 11 ----------- tests/target/issue-1127.rs | 2 +- tests/target/match-nowrap-trailing-comma.rs | 2 +- tests/target/match-nowrap.rs | 2 +- 18 files changed, 57 insertions(+), 59 deletions(-) create mode 100644 tests/source/configs-match_arm_blocks-false.rs create mode 100644 tests/source/configs-match_arm_blocks-true.rs delete mode 100644 tests/source/configs-wrap_match_arms-false.rs delete mode 100644 tests/source/configs-wrap_match_arms-true.rs create mode 100644 tests/target/configs-match_arm_blocks-false.rs create mode 100644 tests/target/configs-match_arm_blocks-true.rs delete mode 100644 tests/target/configs-wrap_match_arms-false.rs delete mode 100644 tests/target/configs-wrap_match_arms-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 76589314e03..50a0c4a1c89 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1138,7 +1138,7 @@ match lorem { } ``` -See also: [`trailing_comma`](#trailing_comma), [`wrap_match_arms`](#wrap_match_arms). +See also: [`trailing_comma`](#trailing_comma), [`match_arm_blocks`](#match_arm_blocks). ## `max_width` @@ -1806,7 +1806,7 @@ Break comments to fit on the line // commodo consequat. ``` -## `wrap_match_arms` +## `match_arm_blocks` Wrap the body of arms in blocks when it does not fit on the same line with the pattern of arms diff --git a/src/config.rs b/src/config.rs index c6225222231..f1ce217a36b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -618,12 +618,6 @@ create_config! { reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; - // Match - wrap_match_arms: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ - the same line with the pattern of arms"; - match_block_trailing_comma: bool, false, false, - "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, "Where to put a binary operator when a binary expression goes multiline."; @@ -643,6 +637,8 @@ create_config! { "Remove blank lines at start or end of a block"; same_line_attributes: bool, true, false, "Try to put attributes on the same line as fields and variants."; + match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ + the same line with the pattern of arms"; force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; fn_args_density: Density, Density::Tall, false, "Argument density in functions"; @@ -653,6 +649,8 @@ create_config! { "How to handle trailing commas for lists"; trailing_semicolon: bool, true, false, "Add trailing semicolon after break, continue and return"; + match_block_trailing_comma: bool, false, false, + "Put a trailing comma after a block based match arm (non-block arms are not affected)"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/src/expr.rs b/src/expr.rs index 9d29425a5dd..812ebd5cf3a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1559,7 +1559,7 @@ fn rewrite_match_body( let indent_str = shape.indent.to_string(context.config); let nested_indent_str = next_line_indent.to_string(context.config); - let (body_prefix, body_suffix) = if context.config.wrap_match_arms() { + let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { let comma = if context.config.match_block_trailing_comma() { "," } else { diff --git a/tests/source/configs-match_arm_blocks-false.rs b/tests/source/configs-match_arm_blocks-false.rs new file mode 100644 index 00000000000..53e37e13c4f --- /dev/null +++ b/tests/source/configs-match_arm_blocks-false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: false +// Wrap match-arms + +fn main() { + match lorem { + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => { + println!("{}", sit) + } + } +} diff --git a/tests/source/configs-match_arm_blocks-true.rs b/tests/source/configs-match_arm_blocks-true.rs new file mode 100644 index 00000000000..a452b13cd27 --- /dev/null +++ b/tests/source/configs-match_arm_blocks-true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: true +// Wrap match-arms + +fn main() { + match lorem { + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => { + println!("{}", sit) + } + } +} diff --git a/tests/source/configs-wrap_match_arms-false.rs b/tests/source/configs-wrap_match_arms-false.rs deleted file mode 100644 index d1c05c27fd7..00000000000 --- a/tests/source/configs-wrap_match_arms-false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-wrap_match_arms: false -// Wrap match-arms - -fn main() { - match lorem { - true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => { - println!("{}", sit) - } - } -} diff --git a/tests/source/configs-wrap_match_arms-true.rs b/tests/source/configs-wrap_match_arms-true.rs deleted file mode 100644 index 8ddc5ebdc2e..00000000000 --- a/tests/source/configs-wrap_match_arms-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-wrap_match_arms: true -// Wrap match-arms - -fn main() { - match lorem { - true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => { - println!("{}", sit) - } - } -} diff --git a/tests/source/issue-1127.rs b/tests/source/issue-1127.rs index 4820f5ea229..9996c194818 100644 --- a/tests/source/issue-1127.rs +++ b/tests/source/issue-1127.rs @@ -1,5 +1,5 @@ // rustfmt-max_width:120 -// rustfmt-wrap_match_arms: false +// rustfmt-match_arm_blocks: false // rustfmt-match_block_trailing_comma: true fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { diff --git a/tests/source/match-nowrap-trailing-comma.rs b/tests/source/match-nowrap-trailing-comma.rs index f6e88406bb4..134d2fdf9a4 100644 --- a/tests/source/match-nowrap-trailing-comma.rs +++ b/tests/source/match-nowrap-trailing-comma.rs @@ -1,4 +1,4 @@ -// rustfmt-wrap_match_arms: false +// rustfmt-match_arm_blocks: false // rustfmt-match_block_trailing_comma: true // Match expressions, no unwrapping of block arms or wrapping of multiline // expressions. diff --git a/tests/source/match-nowrap.rs b/tests/source/match-nowrap.rs index 83e0fbbd450..db22cd9f010 100644 --- a/tests/source/match-nowrap.rs +++ b/tests/source/match-nowrap.rs @@ -1,4 +1,4 @@ -// rustfmt-wrap_match_arms: false +// rustfmt-match_arm_blocks: false // Match expressions, no unwrapping of block arms or wrapping of multiline // expressions. diff --git a/tests/target/configs-control_style-rfc.rs b/tests/target/configs-control_style-rfc.rs index 5e19681f90b..6619d8b2630 100644 --- a/tests/target/configs-control_style-rfc.rs +++ b/tests/target/configs-control_style-rfc.rs @@ -26,7 +26,7 @@ fn issue1656() { match rewrite { Some(ref body_str) if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) - || !context.config.wrap_match_arms() + || !context.config.match_arm_blocks() || (extend && first_line_width(body_str) <= arm_shape.width) || is_block => { diff --git a/tests/target/configs-match_arm_blocks-false.rs b/tests/target/configs-match_arm_blocks-false.rs new file mode 100644 index 00000000000..4d53a96a7b7 --- /dev/null +++ b/tests/target/configs-match_arm_blocks-false.rs @@ -0,0 +1,10 @@ +// rustfmt-match_arm_blocks: false +// Wrap match-arms + +fn main() { + match lorem { + true => + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => println!("{}", sit), + } +} diff --git a/tests/target/configs-match_arm_blocks-true.rs b/tests/target/configs-match_arm_blocks-true.rs new file mode 100644 index 00000000000..d75ef03397a --- /dev/null +++ b/tests/target/configs-match_arm_blocks-true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: true +// Wrap match-arms + +fn main() { + match lorem { + true => { + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) + } + false => println!("{}", sit), + } +} diff --git a/tests/target/configs-wrap_match_arms-false.rs b/tests/target/configs-wrap_match_arms-false.rs deleted file mode 100644 index e4ca37bc6e5..00000000000 --- a/tests/target/configs-wrap_match_arms-false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-wrap_match_arms: false -// Wrap match-arms - -fn main() { - match lorem { - true => - foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => println!("{}", sit), - } -} diff --git a/tests/target/configs-wrap_match_arms-true.rs b/tests/target/configs-wrap_match_arms-true.rs deleted file mode 100644 index f6307e53e43..00000000000 --- a/tests/target/configs-wrap_match_arms-true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-wrap_match_arms: true -// Wrap match-arms - -fn main() { - match lorem { - true => { - foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) - } - false => println!("{}", sit), - } -} diff --git a/tests/target/issue-1127.rs b/tests/target/issue-1127.rs index afc79767cb7..dbdd234b8e4 100644 --- a/tests/target/issue-1127.rs +++ b/tests/target/issue-1127.rs @@ -1,5 +1,5 @@ // rustfmt-max_width:120 -// rustfmt-wrap_match_arms: false +// rustfmt-match_arm_blocks: false // rustfmt-match_block_trailing_comma: true fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { diff --git a/tests/target/match-nowrap-trailing-comma.rs b/tests/target/match-nowrap-trailing-comma.rs index 0abc358a340..19ef2144822 100644 --- a/tests/target/match-nowrap-trailing-comma.rs +++ b/tests/target/match-nowrap-trailing-comma.rs @@ -1,4 +1,4 @@ -// rustfmt-wrap_match_arms: false +// rustfmt-match_arm_blocks: false // rustfmt-match_block_trailing_comma: true // Match expressions, no unwrapping of block arms or wrapping of multiline // expressions. diff --git a/tests/target/match-nowrap.rs b/tests/target/match-nowrap.rs index 14571098218..9e674b1e2f5 100644 --- a/tests/target/match-nowrap.rs +++ b/tests/target/match-nowrap.rs @@ -1,4 +1,4 @@ -// rustfmt-wrap_match_arms: false +// rustfmt-match_arm_blocks: false // Match expressions, no unwrapping of block arms or wrapping of multiline // expressions. -- cgit 1.4.1-3-g733a5 From 677446e99d67a58966392b0882783ddd447e8525 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 27 Nov 2017 17:46:09 +1300 Subject: Merge fn_empty_single_line and impl_empty_single_line into empty_item_single_line --- Configurations.md | 34 +++++----------------- src/config.rs | 4 +-- src/items.rs | 4 +-- .../source/configs-empty_item_single_line-false.rs | 17 +++++++++++ .../source/configs-empty_item_single_line-true.rs | 17 +++++++++++ tests/source/configs-fn_empty_single_line-false.rs | 9 ------ tests/source/configs-fn_empty_single_line-true.rs | 9 ------ .../source/configs-impl_empty_single_line-false.rs | 10 ------- .../source/configs-impl_empty_single_line-true.rs | 10 ------- .../target/configs-empty_item_single_line-false.rs | 15 ++++++++++ .../target/configs-empty_item_single_line-true.rs | 10 +++++++ tests/target/configs-fn_empty_single_line-false.rs | 9 ------ tests/target/configs-fn_empty_single_line-true.rs | 6 ---- .../target/configs-impl_empty_single_line-false.rs | 8 ----- .../target/configs-impl_empty_single_line-true.rs | 6 ---- 15 files changed, 71 insertions(+), 97 deletions(-) create mode 100644 tests/source/configs-empty_item_single_line-false.rs create mode 100644 tests/source/configs-empty_item_single_line-true.rs delete mode 100644 tests/source/configs-fn_empty_single_line-false.rs delete mode 100644 tests/source/configs-fn_empty_single_line-true.rs delete mode 100644 tests/source/configs-impl_empty_single_line-false.rs delete mode 100644 tests/source/configs-impl_empty_single_line-true.rs create mode 100644 tests/target/configs-empty_item_single_line-false.rs create mode 100644 tests/target/configs-empty_item_single_line-true.rs delete mode 100644 tests/target/configs-fn_empty_single_line-false.rs delete mode 100644 tests/target/configs-fn_empty_single_line-true.rs delete mode 100644 tests/target/configs-impl_empty_single_line-false.rs delete mode 100644 tests/target/configs-impl_empty_single_line-true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 50a0c4a1c89..f155abe63ca 100644 --- a/Configurations.md +++ b/Configurations.md @@ -874,10 +874,9 @@ struct Dolor ``` +## `empty_item_single_line` -## `fn_empty_single_line` - -Put empty-body functions on a single line +Put empty-body functions and impls on a single line - **Default value**: `true` - **Possible values**: `true`, `false` @@ -886,6 +885,8 @@ Put empty-body functions on a single line ```rust fn lorem() {} + +impl Lorem {} ``` #### `false`: @@ -893,9 +894,12 @@ fn lorem() {} ```rust fn lorem() { } + +impl Lorem { +} ``` -See also [`control_brace_style`](#control_brace_style). +See also [`brace_style`](#brace_style), [`control_brace_style`](#control_brace_style). ## `fn_single_line` @@ -1004,28 +1008,6 @@ fn lorem() -> usize { See also: [`tab_spaces`](#tab_spaces). -## `impl_empty_single_line` - -Put empty-body implementations on a single line - -- **Default value**: `true` -- **Possible values**: `true`, `false` - -#### `true` (default): - -```rust -impl Lorem {} -``` - -#### `false`: - -```rust -impl Lorem { -} -``` - -See also [`brace_style`](#brace_style). - ## `imports_indent` diff --git a/src/config.rs b/src/config.rs index f1ce217a36b..1a32b4a9c6c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -599,10 +599,10 @@ create_config! { normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; // Single line expressions and items. + empty_item_single_line: bool, true, false, + "Put empty-body functions and impls on a single line"; struct_lit_single_line: bool, true, false, "Put small struct literals on a single line"; - impl_empty_single_line: bool, true, false, "Put empty-body implementations on a single line"; - fn_empty_single_line: bool, true, false, "Put empty-body functions on a single line"; fn_single_line: bool, false, false, "Put single-expression functions on a single line"; where_single_line: bool, false, false, "To force single line where layout"; diff --git a/src/items.rs b/src/items.rs index d1dd61bbc1c..c9552cb1315 100644 --- a/src/items.rs +++ b/src/items.rs @@ -366,7 +366,7 @@ impl<'a> FmtVisitor<'a> { let codemap = self.get_context().codemap; - if self.config.fn_empty_single_line() && is_empty_block(block, codemap) + if self.config.empty_item_single_line() && is_empty_block(block, codemap) && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { return Some(format!("{}{{}}", fn_str)); @@ -705,7 +705,7 @@ fn is_impl_single_line( let open_pos = snippet.find_uncommented("{")? + 1; Some( - context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n') + context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n') && result.len() + where_clause_str.len() <= context.config.max_width() && !contains_comment(&snippet[open_pos..]), ) diff --git a/tests/source/configs-empty_item_single_line-false.rs b/tests/source/configs-empty_item_single_line-false.rs new file mode 100644 index 00000000000..8fa74f28802 --- /dev/null +++ b/tests/source/configs-empty_item_single_line-false.rs @@ -0,0 +1,17 @@ +// rustfmt-empty_item_single_line: false +// Empty impl on single line + +impl Lorem { + +} + +impl Ipsum { + +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/tests/source/configs-empty_item_single_line-true.rs b/tests/source/configs-empty_item_single_line-true.rs new file mode 100644 index 00000000000..02e703d1904 --- /dev/null +++ b/tests/source/configs-empty_item_single_line-true.rs @@ -0,0 +1,17 @@ +// rustfmt-empty_item_single_line: true +// Empty impl on single line + +impl Lorem { + +} + +impl Ipsum { + +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/tests/source/configs-fn_empty_single_line-false.rs b/tests/source/configs-fn_empty_single_line-false.rs deleted file mode 100644 index 86a279b5869..00000000000 --- a/tests/source/configs-fn_empty_single_line-false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-fn_empty_single_line: false -// Empty function on single line - -fn lorem() { -} - -fn lorem() { - -} diff --git a/tests/source/configs-fn_empty_single_line-true.rs b/tests/source/configs-fn_empty_single_line-true.rs deleted file mode 100644 index 2603efd0754..00000000000 --- a/tests/source/configs-fn_empty_single_line-true.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-fn_empty_single_line: true -// Empty function on single line - -fn lorem() { -} - -fn lorem() { - -} diff --git a/tests/source/configs-impl_empty_single_line-false.rs b/tests/source/configs-impl_empty_single_line-false.rs deleted file mode 100644 index bdd114e544a..00000000000 --- a/tests/source/configs-impl_empty_single_line-false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-impl_empty_single_line: false -// Empty impl on single line - -impl Lorem { - -} - -impl Ipsum { - -} diff --git a/tests/source/configs-impl_empty_single_line-true.rs b/tests/source/configs-impl_empty_single_line-true.rs deleted file mode 100644 index 3b1f84f5cd0..00000000000 --- a/tests/source/configs-impl_empty_single_line-true.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-impl_empty_single_line: true -// Empty impl on single line - -impl Lorem { - -} - -impl Ipsum { - -} diff --git a/tests/target/configs-empty_item_single_line-false.rs b/tests/target/configs-empty_item_single_line-false.rs new file mode 100644 index 00000000000..b7886df2aa8 --- /dev/null +++ b/tests/target/configs-empty_item_single_line-false.rs @@ -0,0 +1,15 @@ +// rustfmt-empty_item_single_line: false +// Empty impl on single line + +impl Lorem { +} + +impl Ipsum { +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/tests/target/configs-empty_item_single_line-true.rs b/tests/target/configs-empty_item_single_line-true.rs new file mode 100644 index 00000000000..0755485fea9 --- /dev/null +++ b/tests/target/configs-empty_item_single_line-true.rs @@ -0,0 +1,10 @@ +// rustfmt-empty_item_single_line: true +// Empty impl on single line + +impl Lorem {} + +impl Ipsum {} + +fn lorem() {} + +fn lorem() {} diff --git a/tests/target/configs-fn_empty_single_line-false.rs b/tests/target/configs-fn_empty_single_line-false.rs deleted file mode 100644 index 86a279b5869..00000000000 --- a/tests/target/configs-fn_empty_single_line-false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-fn_empty_single_line: false -// Empty function on single line - -fn lorem() { -} - -fn lorem() { - -} diff --git a/tests/target/configs-fn_empty_single_line-true.rs b/tests/target/configs-fn_empty_single_line-true.rs deleted file mode 100644 index a54cd5e6f3f..00000000000 --- a/tests/target/configs-fn_empty_single_line-true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-fn_empty_single_line: true -// Empty function on single line - -fn lorem() {} - -fn lorem() {} diff --git a/tests/target/configs-impl_empty_single_line-false.rs b/tests/target/configs-impl_empty_single_line-false.rs deleted file mode 100644 index c8f97efec0a..00000000000 --- a/tests/target/configs-impl_empty_single_line-false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-impl_empty_single_line: false -// Empty impl on single line - -impl Lorem { -} - -impl Ipsum { -} diff --git a/tests/target/configs-impl_empty_single_line-true.rs b/tests/target/configs-impl_empty_single_line-true.rs deleted file mode 100644 index 9a485d2d877..00000000000 --- a/tests/target/configs-impl_empty_single_line-true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-impl_empty_single_line: true -// Empty impl on single line - -impl Lorem {} - -impl Ipsum {} -- cgit 1.4.1-3-g733a5 From f0af1d48187bf19b9f71608ccf18924010438c08 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 27 Nov 2017 17:49:55 +1300 Subject: Remove CompressedIfEmpty option from fn_args_density It was identical to Tall --- Configurations.md | 31 +------------------ src/config.rs | 4 +-- .../configs-fn_args_density-compressed_if_empty.rs | 20 ------------ .../configs-fn_args_density-compressed_if_empty.rs | 36 ---------------------- 4 files changed, 2 insertions(+), 89 deletions(-) delete mode 100644 tests/source/configs-fn_args_density-compressed_if_empty.rs delete mode 100644 tests/target/configs-fn_args_density-compressed_if_empty.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index f155abe63ca..7726193fafe 100644 --- a/Configurations.md +++ b/Configurations.md @@ -636,7 +636,7 @@ See also [`comment_width`](#comment_width). Argument density in functions - **Default value**: `"Tall"` -- **Possible values**: `"Compressed"`, `"CompressedIfEmpty"`, `"Tall"`, `"Vertical"` +- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"` #### `"Tall"` (default): @@ -696,35 +696,6 @@ trait Lorem { } ``` -#### `"CompressedIfEmpty"`: - -```rust -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur, - adipiscing: Adipiscing, elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: Consectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} -``` - #### `"Vertical"`: ```rust diff --git a/src/config.rs b/src/config.rs index 1a32b4a9c6c..0f333337bf3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -77,8 +77,6 @@ configuration_option_enum! { Density: Compressed, // Use more lines. Tall, - // Try to compress if the body is empty. - CompressedIfEmpty, // Place every item on a separate line. Vertical, } @@ -95,7 +93,7 @@ impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { Density::Compressed => ListTactic::Mixed, - Density::Tall | Density::CompressedIfEmpty => ListTactic::HorizontalVertical, + Density::Tall => ListTactic::HorizontalVertical, Density::Vertical => ListTactic::Vertical, } } diff --git a/tests/source/configs-fn_args_density-compressed_if_empty.rs b/tests/source/configs-fn_args_density-compressed_if_empty.rs deleted file mode 100644 index 3506ae8ea5c..00000000000 --- a/tests/source/configs-fn_args_density-compressed_if_empty.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-fn_args_density: CompressedIfEmpty -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - // FIXME: Previous line should be formatted like this: - // fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - // adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/target/configs-fn_args_density-compressed_if_empty.rs b/tests/target/configs-fn_args_density-compressed_if_empty.rs deleted file mode 100644 index 1a0f127f59c..00000000000 --- a/tests/target/configs-fn_args_density-compressed_if_empty.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-fn_args_density: CompressedIfEmpty -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - // FIXME: Previous line should be formatted like this: - // fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - // adipiscing: Adipiscing, elit: Elit); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} -- cgit 1.4.1-3-g733a5 From d5c98008f00c5c0c8504fa19f2d9645a05de80d6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 13:50:01 +0900 Subject: Recover from failing to format variants even where there is no comment --- src/items.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d1dd61bbc1c..5ad260bec7e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -452,9 +452,7 @@ impl<'a> FmtVisitor<'a> { let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); match variant_list { Some(ref body_str) => self.buffer.push_str(body_str), - None => if contains_comment(&enum_snippet[brace_pos..]) { - self.format_missing_no_indent(span.hi() - BytePos(1)) - }, + None => self.format_missing_no_indent(span.hi() - BytePos(1)), } self.block_indent = self.block_indent.block_unindent(self.config); -- cgit 1.4.1-3-g733a5 From 1b1122654f0c4f436961e57778c8219b4f286660 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 18:37:21 +0900 Subject: Add cargo_metadata to dependency --- Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/bin/cargo-fmt.rs | 1 + 3 files changed, 94 insertions(+) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 8341da37b04..160fce6e55d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,60 @@ dependencies = [ "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cargo_metadata" +version = "0.3.2" +source = "git+https://github.com/topecongiro/cargo_metadata#1f5bbc43efdad3dfc1d622174b976982cf1f8bf8" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "dbghelp-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive-new" version = "0.5.0" @@ -34,6 +88,14 @@ dependencies = [ "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getopts" version = "0.2.15" @@ -103,10 +165,16 @@ name = "regex-syntax" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustfmt-nightly" version = "0.2.16" dependencies = [ + "cargo_metadata 0.3.2 (git+https://github.com/topecongiro/cargo_metadata)", "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -125,6 +193,20 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "semver" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "1.0.21" @@ -252,10 +334,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" +"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum cargo_metadata 0.3.2 (git+https://github.com/topecongiro/cargo_metadata)" = "" +"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -267,6 +356,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e" "checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" diff --git a/Cargo.toml b/Cargo.toml index 9e9090e1f0e..64036396dc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ log = "0.3" env_logger = "0.4" getopts = "0.2" derive-new = "0.5" +cargo_metadata = { git = "https://github.com/topecongiro/cargo_metadata" } [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index fdeb3cf4286..5c518c90b80 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -13,6 +13,7 @@ #![cfg(not(test))] #![deny(warnings)] +extern crate cargo_metadata; extern crate getopts; extern crate serde_json as json; -- cgit 1.4.1-3-g733a5 From 58e83fb4266999926482d248d79358aea2670ba0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 18:45:26 +0900 Subject: Implement PartialEq, Eq and Hash trait for Target and move Target::from_json() to TargetKind::from_str() --- src/bin/cargo-fmt.rs | 56 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 5c518c90b80..6e18588da81 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -18,6 +18,7 @@ extern crate getopts; extern crate serde_json as json; use std::env; +use std::hash::{Hash, Hasher}; use std::io::{self, Write}; use std::path::PathBuf; use std::process::{Command, ExitStatus}; @@ -175,20 +176,9 @@ impl TargetKind { _ => false, } } -} - -#[derive(Debug)] -pub struct Target { - path: PathBuf, - kind: TargetKind, -} -impl Target { - pub fn from_json(json_val: &Value) -> Option { - let jtarget = json_val.as_object()?; - let path = PathBuf::from(jtarget.get("src_path")?.as_str()?); - let kinds = jtarget.get("kind")?.as_array()?; - let kind = match kinds[0].as_str()? { + fn from_str(s: &str) -> Self { + match s { "bin" => TargetKind::Bin, "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, "test" => TargetKind::Test, @@ -197,12 +187,42 @@ impl Target { "custom-build" => TargetKind::CustomBuild, "proc-macro" => TargetKind::ProcMacro, _ => TargetKind::Other, - }; + } + } +} - Some(Target { - path: path, - kind: kind, - }) +/// Target uses a `path` field for equality and hashing. +#[derive(Debug)] +pub struct Target { + /// A path to the main source file of the target. + path: PathBuf, + /// A kind of target (e.g. lib, bin, example, ...). + kind: TargetKind, +} + +impl Target { + pub fn from_target(target: &cargo_metadata::Target) -> Self { + let path = PathBuf::from(&target.src_path); + let canonicalized = fs::canonicalize(&path).unwrap_or(path); + + Target { + path: canonicalized, + kind: TargetKind::from_str(&target.kind[0]), + } + } +} + +impl PartialEq for Target { + fn eq(&self, other: &Target) -> bool { + self.path == other.path + } +} + +impl Eq for Target {} + +impl Hash for Target { + fn hash(&self, state: &mut H) { + self.path.hash(state); } } -- cgit 1.4.1-3-g733a5 From 33ab1f49272d45804a144705ac7b1248b781cb6c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 18:47:07 +0900 Subject: Use cargo_metadata crate over json crate --- src/bin/cargo-fmt.rs | 203 ++++++++++++++++++++++----------------------------- 1 file changed, 86 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 6e18588da81..5fe8c9cdf52 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -18,16 +18,16 @@ extern crate getopts; extern crate serde_json as json; use std::env; +use std::fs; use std::hash::{Hash, Hasher}; use std::io::{self, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::{Command, ExitStatus}; use std::str; use std::collections::HashSet; use std::iter::FromIterator; use getopts::{Matches, Options}; -use json::Value; fn main() { let exit_status = execute(); @@ -251,145 +251,104 @@ impl WorkspaceHitlist { } } -fn get_cargo_metadata_from_utf8(v: &[u8]) -> Option { - json::from_str(str::from_utf8(v).ok()?).ok() -} - -fn get_json_array_with<'a>(v: &'a Value, key: &str) -> Option<&'a Vec> { - v.as_object()?.get(key)?.as_array() -} - -// `cargo metadata --no-deps | jq '.["packages"]'` -fn get_packages(v: &[u8]) -> Result, io::Error> { - let e = io::Error::new( - io::ErrorKind::NotFound, - String::from("`cargo metadata` returned json without a 'packages' key"), - ); - match get_cargo_metadata_from_utf8(v) { - Some(ref json_obj) => get_json_array_with(json_obj, "packages").cloned().ok_or(e), - None => Err(e), - } -} +fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, io::Error> { + let mut targets = HashSet::new(); -fn extract_target_from_package(package: &Value) -> Option> { - let jtargets = get_json_array_with(package, "targets")?; - let mut targets: Vec = vec![]; - for jtarget in jtargets { - targets.push(Target::from_json(jtarget)?); + match *workspace_hitlist { + WorkspaceHitlist::None => get_targets_root_only(&mut targets)?, + WorkspaceHitlist::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, + WorkspaceHitlist::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, } - Some(targets) -} -fn filter_packages_with_hitlist( - packages: Vec, - workspace_hitlist: &WorkspaceHitlist, -) -> Result, &String> { - let some_hitlist: Option> = - workspace_hitlist.get_some().map(HashSet::from_iter); - if some_hitlist.is_none() { - return Ok(packages); - } - let mut hitlist = some_hitlist.unwrap(); - let members: Vec = packages - .into_iter() - .filter(|member| { - member - .as_object() - .and_then(|member_obj| { - member_obj - .get("name") - .and_then(Value::as_str) - .map(|member_name| { - hitlist.take(&member_name.to_string()).is_some() - }) - }) - .unwrap_or(false) - }) - .collect(); - if hitlist.is_empty() { - Ok(members) + if targets.is_empty() { + Err(io::Error::new( + io::ErrorKind::Other, + format!("Failed to find targets"), + )) } else { - Err(hitlist.into_iter().next().unwrap()) + Ok(targets) } } -fn get_dependencies_from_package(package: &Value) -> Option> { - let jdependencies = get_json_array_with(package, "dependencies")?; - let root_path = env::current_dir().ok()?; - let mut dependencies: Vec = vec![]; - for jdep in jdependencies { - let jdependency = jdep.as_object()?; - if !jdependency.get("source")?.is_null() { - continue; +fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + + for package in metadata.packages { + for target in package.targets { + if target.name == package.name { + targets.insert(Target::from_target(&target)); + } } - let name = jdependency.get("name")?.as_str()?; - let mut path = root_path.clone(); - path.push(&name); - dependencies.push(path); } - Some(dependencies) + + Ok(()) } -// Returns a vector of local dependencies under this crate -fn get_path_to_local_dependencies(packages: &[Value]) -> Vec { - let mut local_dependencies: Vec = vec![]; - for package in packages { - if let Some(mut d) = get_dependencies_from_package(package) { - local_dependencies.append(&mut d); +fn get_targets_recursive( + manifest_path: Option<&Path>, + mut targets: &mut HashSet, + visited: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(manifest_path)?; + + for package in metadata.packages { + add_targets(&package.targets, &mut targets); + + // Look for local dependencies. + for dependency in package.dependencies { + if dependency.source.is_some() || visited.contains(&dependency.name) { + continue; + } + + let mut manifest_path = PathBuf::from(&package.manifest_path); + + manifest_path.pop(); + manifest_path.push(&dependency.name); + manifest_path.push("Cargo.toml"); + + if manifest_path.exists() { + visited.insert(dependency.name); + get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; + } } } - local_dependencies + + Ok(()) } -// Returns a vector of all compile targets of a crate -fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, io::Error> { - let output = Command::new("cargo") - .args(&["metadata", "--no-deps", "--format-version=1"]) - .output()?; - if output.status.success() { - let cur_dir = env::current_dir()?; - let mut targets: Vec = vec![]; - let packages = get_packages(&output.stdout)?; - - // If we can find any local dependencies, we will try to get targets from those as well. - if *workspace_hitlist == WorkspaceHitlist::All { - for path in get_path_to_local_dependencies(&packages) { - match env::set_current_dir(path) { - Ok(..) => match get_targets(workspace_hitlist) { - Ok(ref mut t) => targets.append(t), - Err(..) => continue, - }, - Err(..) => continue, - } - } - } +fn get_targets_with_hitlist( + target_names: &[String], + targets: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; - env::set_current_dir(cur_dir)?; - match filter_packages_with_hitlist(packages, workspace_hitlist) { - Ok(packages) => { - for package in packages { - if let Some(mut target) = extract_target_from_package(&package) { - targets.append(&mut target); - } - } - Ok(targets) - } - Err(package) => { - // Mimick cargo of only outputting one spec. - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("package `{}` is not a member of the workspace", package), - )) + let mut hitlist: HashSet<&String> = HashSet::from_iter(target_names); + + for package in metadata.packages { + for target in package.targets { + if hitlist.remove(&target.name) { + targets.insert(Target::from_target(&target)); } } + } + + if hitlist.is_empty() { + Ok(()) } else { + let package = hitlist.iter().next().unwrap(); Err(io::Error::new( - io::ErrorKind::NotFound, - str::from_utf8(&output.stderr).unwrap(), + io::ErrorKind::InvalidInput, + format!("package `{}` is not a member of the workspace", package), )) } } +fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { + for target in target_paths { + targets.insert(Target::from_target(&target)); + } +} + fn format_files( files: &[PathBuf], fmt_args: &[String], @@ -424,3 +383,13 @@ fn format_files( })?; command.wait() } + +fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { + match cargo_metadata::metadata(manifest_path) { + Ok(metadata) => Ok(metadata), + Err(..) => Err(io::Error::new( + io::ErrorKind::Other, + "`cargo manifest` failed.", + )), + } +} -- cgit 1.4.1-3-g733a5 From fbe06c6f77c2b02903141cdffdcd52e0e3258f2d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 18:48:16 +0900 Subject: Random formatting --- src/bin/cargo-fmt.rs | 3 +++ src/config.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 5fe8c9cdf52..1c69e80899c 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -359,6 +359,7 @@ fn format_files( } else { std::process::Stdio::inherit() }; + if verbosity == Verbosity::Verbose { print!("rustfmt"); for a in fmt_args { @@ -369,6 +370,7 @@ fn format_files( } println!(); } + let mut command = Command::new("rustfmt") .stdout(stdout) .args(files) @@ -381,6 +383,7 @@ fn format_files( ), _ => e, })?; + command.wait() } diff --git a/src/config.rs b/src/config.rs index 0f333337bf3..acf86f42565 100644 --- a/src/config.rs +++ b/src/config.rs @@ -364,7 +364,7 @@ macro_rules! create_config { self.$i.2 = val; } else { println!("Warning: can't set some features as unstable \ - features are only available in nightly channel."); + features are only available in nightly channel."); } } } -- cgit 1.4.1-3-g733a5 From bf87d9b79ffccf9dc3f5f0ec102568097def2127 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 18:57:46 +0900 Subject: Rename WorkspaceHitlist to CargoFmtStrategy --- src/bin/cargo-fmt.rs | 54 ++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 1c69e80899c..fb1a13d07f7 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -84,9 +84,9 @@ fn execute() -> i32 { return success; } - let workspace_hitlist = WorkspaceHitlist::from_matches(&matches); + let strategy = CargoFmtStrategy::from_matches(&matches); - match format_crate(verbosity, &workspace_hitlist) { + match format_crate(verbosity, &strategy) { Err(e) => { print_usage_to_stderr(&opts, &e.to_string()); failure @@ -127,9 +127,9 @@ pub enum Verbosity { fn format_crate( verbosity: Verbosity, - workspace_hitlist: &WorkspaceHitlist, + strategy: &CargoFmtStrategy, ) -> Result { - let targets = get_targets(workspace_hitlist)?; + let targets = get_targets(strategy)?; // Currently only bin and lib files get formatted let files: Vec<_> = targets @@ -227,37 +227,33 @@ impl Hash for Target { } #[derive(Debug, PartialEq, Eq)] -pub enum WorkspaceHitlist { +pub enum CargoFmtStrategy { + /// Format every packages and dependencies. All, + /// Format pacakges that are specified by the command line argument. Some(Vec), - None, + /// Format the root packages only. + Root, } -impl WorkspaceHitlist { - pub fn get_some(&self) -> Option<&[String]> { - if let WorkspaceHitlist::Some(ref hitlist) = *self { - Some(hitlist) - } else { - None - } - } - - pub fn from_matches(matches: &Matches) -> WorkspaceHitlist { +impl CargoFmtStrategy { + pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { match (matches.opt_present("all"), matches.opt_present("p")) { - (false, false) => WorkspaceHitlist::None, - (true, _) => WorkspaceHitlist::All, - (false, true) => WorkspaceHitlist::Some(matches.opt_strs("p")), + (false, false) => CargoFmtStrategy::Root, + (true, _) => CargoFmtStrategy::All, + (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), } } } -fn get_targets(workspace_hitlist: &WorkspaceHitlist) -> Result, io::Error> { +/// Based on the specified CargoFmtStrategy, returns a set of main source files. +fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { let mut targets = HashSet::new(); - match *workspace_hitlist { - WorkspaceHitlist::None => get_targets_root_only(&mut targets)?, - WorkspaceHitlist::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, - WorkspaceHitlist::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, + match *strategy { + CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, + CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, + CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, } if targets.is_empty() { @@ -317,25 +313,25 @@ fn get_targets_recursive( } fn get_targets_with_hitlist( - target_names: &[String], + hitlist: &[String], targets: &mut HashSet, ) -> Result<(), io::Error> { let metadata = get_cargo_metadata(None)?; - let mut hitlist: HashSet<&String> = HashSet::from_iter(target_names); + let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); for package in metadata.packages { for target in package.targets { - if hitlist.remove(&target.name) { + if workspace_hitlist.remove(&target.name) { targets.insert(Target::from_target(&target)); } } } - if hitlist.is_empty() { + if workspace_hitlist.is_empty() { Ok(()) } else { - let package = hitlist.iter().next().unwrap(); + let package = workspace_hitlist.iter().next().unwrap(); Err(io::Error::new( io::ErrorKind::InvalidInput, format!("package `{}` is not a member of the workspace", package), -- cgit 1.4.1-3-g733a5 From a5b647faa71c307c8480e9a0699b6dd1bbd4461e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 19:29:26 +0900 Subject: Allow '--package ' --- src/bin/cargo-fmt.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index fb1a13d07f7..33e7db7adcd 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -52,13 +52,16 @@ fn execute() -> i32 { opts.optflag("", "all", "format all packages (only usable in workspaces)"); // If there is any invalid argument passed to `cargo fmt`, return without formatting. - if let Some(arg) = env::args() - .skip(2) - .take_while(|a| a != "--") - .find(|a| !a.starts_with('-')) - { - print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); - return failure; + let mut is_package_arg = false; + for arg in env::args().skip(2).take_while(|a| a != "--") { + if arg.starts_with("-") { + is_package_arg = arg.starts_with("--package"); + } else if !is_package_arg { + print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); + return failure; + } else { + is_package_arg = false; + } } let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { -- cgit 1.4.1-3-g733a5 From 261d325e15ed04a052fdf71df717774817aee597 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 20:54:55 +0900 Subject: Remove width of a trailing comma on variant --- src/items.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 41c1b7981ad..24c7625df50 100644 --- a/src/items.rs +++ b/src/items.rs @@ -534,7 +534,8 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let indent = self.block_indent; - let shape = self.shape(); + // 1 = ',' + let shape = self.shape().sub_width(1)?; let attrs_str = field.node.attrs.rewrite(&context, shape)?; let lo = field .node @@ -555,8 +556,7 @@ impl<'a> FmtVisitor<'a> { } ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { let lhs = format!("{} =", field.node.name); - // 1 = ',' - rewrite_assign_rhs(&context, lhs, &**expr, shape.sub_width(1)?)? + rewrite_assign_rhs(&context, lhs, &**expr, shape)? } else { field.node.name.to_string() }, @@ -1312,7 +1312,7 @@ fn format_tuple_struct( } result.push(')'); } else { - let shape = Shape::indented(offset, context.config); + let shape = Shape::indented(offset, context.config).sub_width(1)?; let fields = &fields.iter().map(|field| field).collect::>()[..]; let one_line_width = context.config.width_heuristics().fn_call_width; result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; -- cgit 1.4.1-3-g733a5 From 5c81741733299f98dabd4e4dd2285116ac0ee672 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 20:57:06 +0900 Subject: Minor refactoring --- src/items.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 24c7625df50..80aa0552ed6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -533,7 +533,6 @@ impl<'a> FmtVisitor<'a> { } let context = self.get_context(); - let indent = self.block_indent; // 1 = ',' let shape = self.shape().sub_width(1)?; let attrs_str = field.node.attrs.rewrite(&context, shape)?; @@ -550,7 +549,7 @@ impl<'a> FmtVisitor<'a> { format_struct( &context, &StructParts::from_variant(field), - indent, + self.block_indent, Some(one_line_width), )? } -- cgit 1.4.1-3-g733a5 From dff2ebba05d88fa85080966213e624f1440f6fb2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 20:58:39 +0900 Subject: Remove FIXME now is the time --- src/items.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 80aa0552ed6..4fb4f37d071 100644 --- a/src/items.rs +++ b/src/items.rs @@ -545,7 +545,6 @@ impl<'a> FmtVisitor<'a> { let variant_body = match field.node.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { - // FIXME: Should limit the width, as we have a trailing comma format_struct( &context, &StructParts::from_variant(field), -- cgit 1.4.1-3-g733a5 From 940758b1bdb9423085c5f761acc724e453d9e826 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 21:00:27 +0900 Subject: Cargo fmt --- src/items.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 4fb4f37d071..da110eef934 100644 --- a/src/items.rs +++ b/src/items.rs @@ -544,14 +544,12 @@ impl<'a> FmtVisitor<'a> { let span = mk_sp(lo, field.span.lo()); let variant_body = match field.node.data { - ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => { - format_struct( - &context, - &StructParts::from_variant(field), - self.block_indent, - Some(one_line_width), - )? - } + ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( + &context, + &StructParts::from_variant(field), + self.block_indent, + Some(one_line_width), + )?, ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { let lhs = format!("{} =", field.node.name); rewrite_assign_rhs(&context, lhs, &**expr, shape)? -- cgit 1.4.1-3-g733a5 From f06cb340220d2f594d4532c409183e78ea30bdfe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 27 Nov 2017 22:09:01 +0900 Subject: Replace TargetKind with simple String --- src/bin/cargo-fmt.rs | 47 +++-------------------------------------------- 1 file changed, 3 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 33e7db7adcd..001ffb649c6 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -137,10 +137,9 @@ fn format_crate( // Currently only bin and lib files get formatted let files: Vec<_> = targets .into_iter() - .filter(|t| t.kind.should_format()) .inspect(|t| { if verbosity == Verbosity::Verbose { - println!("[{:?}] {:?}", t.kind, t.path) + println!("[{}] {:?}", t.kind, t.path) } }) .map(|t| t.path) @@ -154,53 +153,13 @@ fn get_fmt_args() -> Vec { env::args().skip_while(|a| a != "--").skip(1).collect() } -#[derive(Debug)] -enum TargetKind { - Lib, // dylib, staticlib, lib - Bin, // bin - Example, // example file - Test, // test file - Bench, // bench file - CustomBuild, // build script - ProcMacro, // a proc macro implementation - Other, // plugin,... -} - -impl TargetKind { - fn should_format(&self) -> bool { - match *self { - TargetKind::Lib - | TargetKind::Bin - | TargetKind::Example - | TargetKind::Test - | TargetKind::Bench - | TargetKind::CustomBuild - | TargetKind::ProcMacro => true, - _ => false, - } - } - - fn from_str(s: &str) -> Self { - match s { - "bin" => TargetKind::Bin, - "lib" | "dylib" | "staticlib" | "cdylib" | "rlib" => TargetKind::Lib, - "test" => TargetKind::Test, - "example" => TargetKind::Example, - "bench" => TargetKind::Bench, - "custom-build" => TargetKind::CustomBuild, - "proc-macro" => TargetKind::ProcMacro, - _ => TargetKind::Other, - } - } -} - /// Target uses a `path` field for equality and hashing. #[derive(Debug)] pub struct Target { /// A path to the main source file of the target. path: PathBuf, /// A kind of target (e.g. lib, bin, example, ...). - kind: TargetKind, + kind: String, } impl Target { @@ -210,7 +169,7 @@ impl Target { Target { path: canonicalized, - kind: TargetKind::from_str(&target.kind[0]), + kind: target.kind[0].clone(), } } } -- cgit 1.4.1-3-g733a5 From 4e04e825b59cc5f79d6390f5062d06230e074b12 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Nov 2017 15:03:02 +1300 Subject: Use the right kind of doc comment in chains.rs cc #2185 --- src/chains.rs | 100 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1442f6b84a1..a35770427b5 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -8,56 +8,56 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// Formatting of chained expressions, i.e. expressions which are chained by -/// dots: struct and enum field access, method calls, and try shorthand (?). -/// -/// Instead of walking these subexpressions one-by-one, as is our usual strategy -/// for expression formatting, we collect maximal sequences of these expressions -/// and handle them simultaneously. -/// -/// Whenever possible, the entire chain is put on a single line. If that fails, -/// we put each subexpression on a separate, much like the (default) function -/// argument function argument strategy. -/// -/// Depends on config options: `chain_indent` is the indent to use for -/// blocks in the parent/root/base of the chain (and the rest of the chain's -/// alignment). -/// E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the -/// following values of `chain_indent`: -/// Block: -/// ``` -/// let foo = { -/// aaaa; -/// bbb; -/// ccc -/// }.bar -/// .baz(); -/// ``` -/// Visual: -/// ``` -/// let foo = { -/// aaaa; -/// bbb; -/// ccc -/// } -/// .bar -/// .baz(); -/// ``` -/// -/// If the first item in the chain is a block expression, we align the dots with -/// the braces. -/// Block: -/// ``` -/// let a = foo.bar -/// .baz() -/// .qux -/// ``` -/// Visual: -/// ``` -/// let a = foo.bar -/// .baz() -/// .qux -/// ``` +//! Formatting of chained expressions, i.e. expressions which are chained by +//! dots: struct and enum field access, method calls, and try shorthand (?). +//! +//! Instead of walking these subexpressions one-by-one, as is our usual strategy +//! for expression formatting, we collect maximal sequences of these expressions +//! and handle them simultaneously. +//! +//! Whenever possible, the entire chain is put on a single line. If that fails, +//! we put each subexpression on a separate, much like the (default) function +//! argument function argument strategy. +//! +//! Depends on config options: `chain_indent` is the indent to use for +//! blocks in the parent/root/base of the chain (and the rest of the chain's +//! alignment). +//! E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the +//! following values of `chain_indent`: +//! Block: +//! ``` +//! let foo = { +//! aaaa; +//! bbb; +//! ccc +//! }.bar +//! .baz(); +//! ``` +//! Visual: +//! ``` +//! let foo = { +//! aaaa; +//! bbb; +//! ccc +//! } +//! .bar +//! .baz(); +//! ``` +//! +//! If the first item in the chain is a block expression, we align the dots with +//! the braces. +//! Block: +//! ``` +//! let a = foo.bar +//! .baz() +//! .qux +//! ``` +//! Visual: +//! ``` +//! let a = foo.bar +//! .baz() +//! .qux +//! ``` use shape::Shape; use config::IndentStyle; -- cgit 1.4.1-3-g733a5 From be19bab9dee0a4e54638327a3b072ceb0868484f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 29 Nov 2017 17:29:38 +0900 Subject: Take into account the rhs overhead when rewriting the last element of chain --- src/chains.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index a35770427b5..cb8e8d62988 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -166,18 +166,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = { - let last_shape = if rewrites.len() == 0 { - first_child_shape - } else { - other_child_shape - }; - match context.config.indent_style() { - IndentStyle::Visual => last_shape.sub_width(shape.rhs_overhead(context.config))?, - IndentStyle::Block => last_shape, - } - }; - let last_shape = last_shape.sub_width(suffix_try_num)?; + let last_shape = if rewrites.len() == 0 { + first_child_shape + } else { + other_child_shape + }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: -- cgit 1.4.1-3-g733a5 From 94a770a777d3995e80938a31ec51c6e85d7ab694 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 29 Nov 2017 17:32:31 +0900 Subject: Use correct shape when rewriting the last arg with overflowing --- src/expr.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 812ebd5cf3a..96132229c90 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1814,6 +1814,10 @@ where let used_width = extra_offset(callee_str, shape); let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; + // 1 = "(" or ")" + let one_line_shape = shape + .offset_left(last_line_width(callee_str) + 1)? + .sub_width(1)?; let nested_shape = shape_from_indent_style( context, shape, @@ -1828,6 +1832,7 @@ where context, args, args_span, + one_line_shape, nested_shape, one_line_width, args_max_width, @@ -1867,7 +1872,8 @@ fn rewrite_call_args<'a, T>( context: &RewriteContext, args: &[&T], span: Span, - shape: Shape, + one_line_shape: Shape, + nested_shape: Shape, one_line_width: usize, args_max_width: usize, force_trailing_comma: bool, @@ -1882,7 +1888,7 @@ where ",", |item| item.span().lo(), |item| item.span().hi(), - |item| item.rewrite(context, shape), + |item| item.rewrite(context, nested_shape), span.lo(), span.hi(), true, @@ -1896,7 +1902,8 @@ where context, &mut item_vec, &args[..], - shape, + one_line_shape, + nested_shape, one_line_width, args_max_width, ); @@ -1912,7 +1919,7 @@ where context.config.trailing_comma() }, separator_place: SeparatorPlace::Back, - shape: shape, + shape: nested_shape, ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, preserve_newline: false, config: context.config, @@ -1927,7 +1934,8 @@ fn try_overflow_last_arg<'a, T>( context: &RewriteContext, item_vec: &mut Vec, args: &[&T], - shape: Shape, + one_line_shape: Shape, + nested_shape: Shape, one_line_width: usize, args_max_width: usize, ) -> DefinitiveListTactic @@ -1945,7 +1953,7 @@ where context.force_one_line_chain = true; } } - last_arg_shape(&context, item_vec, shape, args_max_width).and_then(|arg_shape| { + last_arg_shape(&context, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) }) } else { -- cgit 1.4.1-3-g733a5 From af663d8f627420d111b307ed057918dc44b1a7f0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 29 Nov 2017 17:36:51 +0900 Subject: Ignore fn_call_width when rewriting a call with a single non-call arg --- src/expr.rs | 52 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 96132229c90..d51d355dbdd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1953,7 +1953,7 @@ where context.force_one_line_chain = true; } } - last_arg_shape(&context, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { + last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) }) } else { @@ -2000,26 +2000,32 @@ where tactic } -fn last_arg_shape( - context: &RewriteContext, +/// Returns a shape for the last argument which is going to be overflowed. +fn last_arg_shape( + lists: &[&T], items: &[ListItem], shape: Shape, args_max_width: usize, -) -> Option { - let overhead = items.iter().rev().skip(1).fold(0, |acc, i| { - acc + i.item.as_ref().map_or(0, |s| first_line_width(s)) +) -> Option +where + T: Rewrite + Spanned + ToExpr, +{ + let is_nested_call = lists + .iter() + .next() + .and_then(|item| item.to_expr()) + .map_or(false, is_nested_call); + if items.len() == 1 && !is_nested_call { + return Some(shape); + } + let offset = items.iter().rev().skip(1).fold(0, |acc, i| { + // 2 = ", " + acc + 2 + i.inner_as_ref().len() }); - let max_width = min(args_max_width, shape.width); - let arg_indent = if context.use_block_indent() { - shape.block().indent.block_unindent(context.config) - } else { - shape.block().indent - }; - Some(Shape { - width: max_width.checked_sub(overhead)?, - indent: arg_indent, - offset: 0, - }) + Shape { + width: min(args_max_width, shape.width), + ..shape + }.offset_left(offset) } fn rewrite_last_arg_with_overflow<'a, T>( @@ -2101,6 +2107,18 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l } } +fn is_nested_call(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), + _ => false, + } +} + pub fn wrap_args_with_parens( context: &RewriteContext, args_str: &str, -- cgit 1.4.1-3-g733a5 From 8b53d7806ccb066e7041bcaccc61421a20a4829c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 29 Nov 2017 17:37:51 +0900 Subject: Cargo fmt --- src/bin/rustfmt.rs | 7 ++++--- src/chains.rs | 5 ++--- src/comment.rs | 4 +--- src/expr.rs | 8 ++------ src/items.rs | 20 ++++++-------------- src/visitor.rs | 9 ++------- 6 files changed, 17 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 41454c853ed..001f2c8e0f7 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -87,9 +87,10 @@ impl CliOptions { if let Ok(write_mode) = WriteMode::from_str(write_mode) { options.write_mode = Some(write_mode); } else { - return Err(FmtError::from( - format!("Invalid write-mode: {}", write_mode), - )); + return Err(FmtError::from(format!( + "Invalid write-mode: {}", + write_mode + ))); } } diff --git a/src/chains.rs b/src/chains.rs index cb8e8d62988..576d036d47b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -147,9 +147,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let last_subexpr = &subexpr_list[suffix_try_num]; let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); - let mut rewrites = iter.map(|(e, shape)| { - rewrite_chain_subexpr(e, total_span, context, shape) - }).collect::>>()?; + let mut rewrites = iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) + .collect::>>()?; // Total of all items excluding the last. let extend_last_subexpr = last_line_extendable(&parent_rewrite) && rewrites.is_empty(); diff --git a/src/comment.rs b/src/comment.rs index 2511e5df216..2e3dadd2066 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -224,9 +224,7 @@ pub fn rewrite_comment( // we should stop now. let num_bare_lines = orig.lines() .map(|line| line.trim()) - .filter(|l| { - !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*")) - }) + .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) .count(); if num_bare_lines > 0 && !config.normalize_comments() { return Some(orig.to_owned()); diff --git a/src/expr.rs b/src/expr.rs index d51d355dbdd..ad3bb053de9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -292,9 +292,7 @@ pub fn format_expr( }; expr_rw - .and_then(|expr_str| { - recover_comment_removed(expr_str, expr.span, context) - }) + .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); let attrs_str = attrs.rewrite(context, shape)?; @@ -1925,9 +1923,7 @@ where config: context.config, }; - write_list(&item_vec, &fmt).map(|args_str| { - (tactic != DefinitiveListTactic::Vertical, args_str) - }) + write_list(&item_vec, &fmt).map(|args_str| (tactic != DefinitiveListTactic::Vertical, args_str)) } fn try_overflow_last_arg<'a, T>( diff --git a/src/items.rs b/src/items.rs index da110eef934..6285811e79e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -817,8 +817,7 @@ fn format_impl_ref_and_type( IndentStyle::Visual => new_line_offset + trait_ref_overhead, IndentStyle::Block => new_line_offset, }; - result.push_str(&*self_ty - .rewrite(context, Shape::legacy(budget, type_offset))?); + result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); Some(result) } else { unreachable!(); @@ -1578,9 +1577,7 @@ fn rewrite_static( lhs, &**expr, Shape::legacy(remaining_width, offset.block_only()), - ).and_then(|res| { - recover_comment_removed(res, static_parts.span, context) - }) + ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{}{};", prefix, ty_str)) @@ -2096,18 +2093,14 @@ fn rewrite_args( generics_str_contains_newline: bool, ) -> Option { let mut arg_item_strs = args.iter() - .map(|arg| { - arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) - }) + .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) .collect::>>()?; // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. let min_args = explicit_self - .and_then(|explicit_self| { - rewrite_explicit_self(explicit_self, args, context) - }) + .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) .map_or(1, |self_str| { arg_item_strs[0] = self_str; 2 @@ -2326,9 +2319,8 @@ fn rewrite_generics( ) -> Option { let g_shape = generics_shape_from_config(context.config, shape, 0)?; let one_line_width = shape.width.checked_sub(2).unwrap_or(0); - rewrite_generics_inner(context, generics, g_shape, one_line_width, span).or_else(|| { - rewrite_generics_inner(context, generics, g_shape, 0, span) - }) + rewrite_generics_inner(context, generics, g_shape, one_line_width, span) + .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span)) } fn rewrite_generics_inner( diff --git a/src/visitor.rs b/src/visitor.rs index 79bade0cc20..00d62aeeff7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -109,9 +109,7 @@ impl<'a> FmtVisitor<'a> { if self.config.remove_blank_lines_at_start_or_end_of_block() { if let Some(first_stmt) = b.stmts.first() { let attr_lo = inner_attrs - .and_then(|attrs| { - inner_attributes(attrs).first().map(|attr| attr.span.lo()) - }) + .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) .or_else(|| { // Attributes for an item in a statement position // do not belong to the statement. (rust-lang/rust#34459) @@ -872,10 +870,7 @@ fn rewrite_first_group_attrs( for derive in derives { derive_args.append(&mut get_derive_args(context, derive)?); } - return Some(( - derives.len(), - format_derive(context, &derive_args, shape)?, - )); + return Some((derives.len(), format_derive(context, &derive_args, shape)?)); } } // Rewrite the first attribute. -- cgit 1.4.1-3-g733a5 From 4cb1dccb974744f04c42bed63c0f9e6752fda99f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 29 Nov 2017 20:31:58 +0900 Subject: Print unstable option's name on warning --- src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index acf86f42565..ce045502c9c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -363,8 +363,8 @@ macro_rules! create_config { self.$i.1 = true; self.$i.2 = val; } else { - println!("Warning: can't set some features as unstable \ - features are only available in nightly channel."); + println!("Warning: can't set `{} = {:?}`, unstable features are only \ + available in nightly channel.", stringify!($i), val); } } } -- cgit 1.4.1-3-g733a5 From 54f3c21a2f41c01dc112d81fb9fa80bacf572e30 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 30 Nov 2017 04:56:19 +0900 Subject: Fix a typo --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ad3bb053de9..b47f56dcb8d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1971,7 +1971,7 @@ where } _ if args.len() >= 1 => { item_vec[args.len() - 1].item = args.last() - .and_then(|last_arg| last_arg.rewrite(context, shape)); + .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); // Use horizontal layout for a function with a single argument as long as // everything fits in a single line. if args.len() == 1 -- cgit 1.4.1-3-g733a5 From b5e4c99ca72cefd811820425b2d1297e7e59cff4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 30 Nov 2017 06:12:32 +0900 Subject: Use an explicit flag to decide on whether to add brace compensation --- src/closures.rs | 3 ++- src/expr.rs | 12 +++++++----- src/visitor.rs | 13 ++++++++----- 3 files changed, 17 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 71862b82ba0..1743b1a03a8 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -131,7 +131,8 @@ fn rewrite_closure_with_block( rules: ast::BlockCheckMode::Default, span: body.span, }; - rewrite_closure_block(&block, prefix, context, shape) + let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, true)?; + Some(format!("{} {}", prefix, block)) } // Rewrite closure with a single expression without wrapping its body with block. diff --git a/src/expr.rs b/src/expr.rs index b47f56dcb8d..6d7114524fd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -116,7 +116,7 @@ pub fn format_expr( rw } else { let prefix = block_prefix(context, block, shape)?; - rewrite_block_with_visitor(context, &prefix, block, shape) + rewrite_block_with_visitor(context, &prefix, block, shape, false) } } ExprType::SubExpression => block.rewrite(context, shape), @@ -598,11 +598,12 @@ fn rewrite_single_line_block( None } -fn rewrite_block_with_visitor( +pub fn rewrite_block_with_visitor( context: &RewriteContext, prefix: &str, block: &ast::Block, shape: Shape, + is_dummy: bool, ) -> Option { if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { return rw; @@ -620,7 +621,7 @@ fn rewrite_block_with_visitor( ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), } - visitor.visit_block(block, None); + visitor.visit_block(block, None, is_dummy); Some(format!("{}{}", prefix, visitor.buffer)) } @@ -634,7 +635,7 @@ impl Rewrite for ast::Block { let prefix = block_prefix(context, self, shape)?; - let result = rewrite_block_with_visitor(context, &prefix, self, shape); + let result = rewrite_block_with_visitor(context, &prefix, self, shape, false); if let Some(ref result_str) = result { if result_str.lines().count() <= 3 { if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { @@ -1064,7 +1065,8 @@ impl<'a> Rewrite for ControlFlow<'a> { }; let mut block_context = context.clone(); block_context.is_if_else_block = self.else_block.is_some(); - let block_str = rewrite_block_with_visitor(&block_context, "", self.block, block_shape)?; + let block_str = + rewrite_block_with_visitor(&block_context, "", self.block, block_shape, false)?; let mut result = format!("{}{}", cond_str, block_str); diff --git a/src/visitor.rs b/src/visitor.rs index 00d62aeeff7..d97fb44438c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -90,7 +90,12 @@ impl<'a> FmtVisitor<'a> { } } - pub fn visit_block(&mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>) { + pub fn visit_block( + &mut self, + b: &ast::Block, + inner_attrs: Option<&[ast::Attribute]>, + is_dummy: bool, + ) { debug!( "visit_block: {:?} {:?}", self.codemap.lookup_char_pos(b.span.lo()), @@ -98,9 +103,7 @@ impl<'a> FmtVisitor<'a> { ); // Check if this block has braces. - let snippet = self.snippet(b.span); - let has_braces = snippet.starts_with('{') || snippet.starts_with("unsafe"); - let brace_compensation = if has_braces { BytePos(1) } else { BytePos(0) }; + let brace_compensation = BytePos(if is_dummy { 0 } else { 1 }); self.last_pos = self.last_pos + brace_compensation; self.block_indent = self.block_indent.block_indent(self.config); @@ -272,7 +275,7 @@ impl<'a> FmtVisitor<'a> { } self.last_pos = source!(self, block.span).lo(); - self.visit_block(block, inner_attrs) + self.visit_block(block, inner_attrs, false) } pub fn visit_item(&mut self, item: &ast::Item) { -- cgit 1.4.1-3-g733a5 From 1323abf93f28b0847fe05663c3fb774b8c707b60 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 30 Nov 2017 06:13:42 +0900 Subject: Fix a typo --- src/expr.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6d7114524fd..1fde6f21777 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -634,6 +634,7 @@ impl Rewrite for ast::Block { } let prefix = block_prefix(context, self, shape)?; + let shape = shape.offset_left(last_line_width(&prefix))?; let result = rewrite_block_with_visitor(context, &prefix, self, shape, false); if let Some(ref result_str) = result { -- cgit 1.4.1-3-g733a5 From f99b775de77ff7e138a3eca3d739f80bd797028f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 30 Nov 2017 06:40:29 +0900 Subject: Rename is_dummy to has_braces --- src/closures.rs | 2 +- src/expr.rs | 10 +++++----- src/visitor.rs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 1743b1a03a8..1ea7982ba66 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -131,7 +131,7 @@ fn rewrite_closure_with_block( rules: ast::BlockCheckMode::Default, span: body.span, }; - let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, true)?; + let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; Some(format!("{} {}", prefix, block)) } diff --git a/src/expr.rs b/src/expr.rs index 1fde6f21777..d1303d95276 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -116,7 +116,7 @@ pub fn format_expr( rw } else { let prefix = block_prefix(context, block, shape)?; - rewrite_block_with_visitor(context, &prefix, block, shape, false) + rewrite_block_with_visitor(context, &prefix, block, shape, true) } } ExprType::SubExpression => block.rewrite(context, shape), @@ -603,7 +603,7 @@ pub fn rewrite_block_with_visitor( prefix: &str, block: &ast::Block, shape: Shape, - is_dummy: bool, + has_braces: bool, ) -> Option { if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { return rw; @@ -621,7 +621,7 @@ pub fn rewrite_block_with_visitor( ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), } - visitor.visit_block(block, None, is_dummy); + visitor.visit_block(block, None, has_braces); Some(format!("{}{}", prefix, visitor.buffer)) } @@ -636,7 +636,7 @@ impl Rewrite for ast::Block { let prefix = block_prefix(context, self, shape)?; let shape = shape.offset_left(last_line_width(&prefix))?; - let result = rewrite_block_with_visitor(context, &prefix, self, shape, false); + let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); if let Some(ref result_str) = result { if result_str.lines().count() <= 3 { if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { @@ -1067,7 +1067,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let mut block_context = context.clone(); block_context.is_if_else_block = self.else_block.is_some(); let block_str = - rewrite_block_with_visitor(&block_context, "", self.block, block_shape, false)?; + rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?; let mut result = format!("{}{}", cond_str, block_str); diff --git a/src/visitor.rs b/src/visitor.rs index d97fb44438c..85a8fb38f07 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -94,7 +94,7 @@ impl<'a> FmtVisitor<'a> { &mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>, - is_dummy: bool, + has_braces: bool, ) { debug!( "visit_block: {:?} {:?}", @@ -103,7 +103,7 @@ impl<'a> FmtVisitor<'a> { ); // Check if this block has braces. - let brace_compensation = BytePos(if is_dummy { 0 } else { 1 }); + let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); self.last_pos = self.last_pos + brace_compensation; self.block_indent = self.block_indent.block_indent(self.config); @@ -275,7 +275,7 @@ impl<'a> FmtVisitor<'a> { } self.last_pos = source!(self, block.span).lo(); - self.visit_block(block, inner_attrs, false) + self.visit_block(block, inner_attrs, true) } pub fn visit_item(&mut self, item: &ast::Item) { -- cgit 1.4.1-3-g733a5 From 39d85b0d4112818141bec1bf7a87d4d0db5e55a6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 30 Nov 2017 15:00:32 +0900 Subject: Combine a sigle argument and a short callee --- src/expr.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d1303d95276..e9e0226e286 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1814,6 +1814,9 @@ where }; let used_width = extra_offset(callee_str, shape); let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; + // 1 = "(" + let combine_arg_with_callee = + callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; // 1 = "(" or ")" let one_line_shape = shape @@ -1838,6 +1841,7 @@ where one_line_width, args_max_width, force_trailing_comma, + combine_arg_with_callee, )?; if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { @@ -1878,6 +1882,7 @@ fn rewrite_call_args<'a, T>( one_line_width: usize, args_max_width: usize, force_trailing_comma: bool, + combine_arg_with_callee: bool, ) -> Option<(bool, String)> where T: Rewrite + Spanned + ToExpr + 'a, @@ -1907,6 +1912,7 @@ where nested_shape, one_line_width, args_max_width, + combine_arg_with_callee, ); let fmt = ListFormatting { @@ -1937,19 +1943,22 @@ fn try_overflow_last_arg<'a, T>( nested_shape: Shape, one_line_width: usize, args_max_width: usize, + combine_arg_with_callee: bool, ) -> DefinitiveListTactic where T: Rewrite + Spanned + ToExpr + 'a, { - let overflow_last = can_be_overflowed(context, args); + let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); // Replace the last item with its first line to see if it fits with // first arguments. let placeholder = if overflow_last { let mut context = context.clone(); - if let Some(expr) = args[args.len() - 1].to_expr() { - if let ast::ExprKind::MethodCall(..) = expr.node { - context.force_one_line_chain = true; + if !combine_arg_with_callee { + if let Some(expr) = args[args.len() - 1].to_expr() { + if let ast::ExprKind::MethodCall(..) = expr.node { + context.force_one_line_chain = true; + } } } last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { -- cgit 1.4.1-3-g733a5 From 9667cc2484cb04066664d86f04d51940d7f334bf Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Nov 2017 09:22:00 +0100 Subject: Address clippy lints --- src/chains.rs | 2 +- src/expr.rs | 2 +- src/filemap.rs | 2 +- src/issues.rs | 4 ++-- src/items.rs | 11 +++++------ src/lists.rs | 16 +++++++--------- src/types.rs | 2 +- 7 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 576d036d47b..5aebc160750 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -165,7 +165,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = if rewrites.len() == 0 { + let last_shape = if rewrites.is_empty() { first_child_shape } else { other_child_shape diff --git a/src/expr.rs b/src/expr.rs index d1303d95276..1faa109c50b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1424,7 +1424,7 @@ fn rewrite_match_arm( /// - `&[small]` fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { // We also require that the pattern is reasonably 'small' with its literal width. - pat_str.len() <= 20 && !pat_str.contains("\n") && is_short_pattern_inner(pat) + pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) } fn is_short_pattern_inner(pat: &ast::Pat) -> bool { diff --git a/src/filemap.rs b/src/filemap.rs index 5942934d877..0532646b9f4 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -30,7 +30,7 @@ pub fn append_newline(s: &mut StringBuffer) { s.push_str("\n"); } -pub fn write_all_files(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error> +pub fn write_all_files(file_map: &[FileRecord], out: &mut T, config: &Config) -> Result<(), io::Error> where T: Write, { diff --git a/src/issues.rs b/src/issues.rs index be30ff2d86e..58c9dd5d7ab 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -16,8 +16,8 @@ use std::fmt; pub use config::ReportTactic; -const TO_DO_CHARS: &'static [char] = &['T', 'O', 'D', 'O']; -const FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E']; +const TO_DO_CHARS: &[char] = &['T', 'O', 'D', 'O']; +const FIX_ME_CHARS: &[char] = &['F', 'I', 'X', 'M', 'E']; // Enabled implementation detail is here because it is // irrelevant outside the issues module diff --git a/src/items.rs b/src/items.rs index 6285811e79e..fcdc3b2c858 100644 --- a/src/items.rs +++ b/src/items.rs @@ -500,8 +500,8 @@ impl<'a> FmtVisitor<'a> { let mut items: Vec<_> = itemize_list_with(self.config.width_heuristics().struct_variant_width); // If one of the variants use multiple lines, use multi-lined formatting for all variants. - let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains("\n")); - let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains("\n")); + let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); + let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); if has_multiline_variant && has_single_line_variant { items = itemize_list_with(0); } @@ -1308,7 +1308,7 @@ fn format_tuple_struct( result.push(')'); } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; - let fields = &fields.iter().map(|field| field).collect::>()[..]; + let fields = &fields.iter().collect::>()[..]; let one_line_width = context.config.width_heuristics().fn_call_width; result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; } @@ -1593,7 +1593,7 @@ pub fn rewrite_associated_type( ) -> Option { let prefix = format!("type {}", ident); - let type_bounds_str = if let Some(ref bounds) = ty_param_bounds_opt { + let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { // 2 = ": ".len() let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; let bound_str = bounds @@ -2459,10 +2459,9 @@ pub fn wrap_generics_with_angle_brackets( fn rewrite_trait_bounds( context: &RewriteContext, - type_param_bounds: &ast::TyParamBounds, + bounds: &[ast::TyParamBound], shape: Shape, ) -> Option { - let bounds: &[_] = type_param_bounds; if bounds.is_empty() { return Some(String::new()); diff --git a/src/lists.rs b/src/lists.rs index edc896e26c2..f3e1c362dc1 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -437,7 +437,7 @@ where let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; - if !starts_with_newline(&comment) { + if !starts_with_newline(comment) { let mut comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); if first_line_width(&formatted_comment) + last_line_width(&result) @@ -457,7 +457,7 @@ where } } else { result.push('\n'); - result.push_str(&indent_str); + result.push_str(indent_str); } if formatted_comment.contains('\n') { item_max_width = None; @@ -594,7 +594,7 @@ where let mut block_open_index = post_snippet.find("/*"); // check if it really is a block comment (and not `//*` or a nested comment) if let Some(i) = block_open_index { - match post_snippet.find("/") { + match post_snippet.find('/') { Some(j) if j < i => block_open_index = None, _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, _ => (), @@ -620,15 +620,13 @@ where (_, Some(j)) if j > separator_index => j + 1, _ => post_snippet.len(), } - } else { + } else if let Some(newline_index) = newline_index { // Match arms may not have trailing comma. In any case, for match arms, // we will assume that the post comment belongs to the next arm if they // do not end with trailing comma. - if let Some(newline_index) = newline_index { - newline_index + 1 - } else { - 0 - } + newline_index + 1 + } else { + 0 } } None => post_snippet diff --git a/src/types.rs b/src/types.rs index 25bbd92b108..cad5195428f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -380,7 +380,7 @@ where FunctionRetTy::Default(..) => String::new(), }; - let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains("\n"); + let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n'); let args = wrap_args_with_parens( context, &list_str, -- cgit 1.4.1-3-g733a5 From 89bf00986de724873858f07af6b49665abf38996 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 16 Aug 2017 00:46:54 +0900 Subject: Do not put if on the same line as match arm --- src/expr.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d1303d95276..46641a10ae6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1500,7 +1500,8 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( - !context.config.force_multiline_blocks() && expr.can_be_overflowed(context, 1), + !context.config.force_multiline_blocks() + && (can_extend_match_arm_body(expr), &**expr), &**expr, ) } else { @@ -1723,6 +1724,33 @@ fn rewrite_pat_expr( .map(|expr_rw| format!("\n{}{}", nested_indent_str, expr_rw)) } +fn can_extend_match_arm_body(body: &ast::Expr) -> bool { + match body.node { + // We do not allow `if` to stay on the same line, since we could easily mistake + // `pat => if cond { ... }` and `pat if cond => { ... }`. + ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, + ast::ExprKind::ForLoop(..) | + ast::ExprKind::Loop(..) | + ast::ExprKind::While(..) | + ast::ExprKind::WhileLet(..) | + ast::ExprKind::Match(..) | + ast::ExprKind::Block(..) | + ast::ExprKind::Closure(..) | + ast::ExprKind::Array(..) | + ast::ExprKind::Call(..) | + ast::ExprKind::MethodCall(..) | + ast::ExprKind::Mac(..) | + ast::ExprKind::Struct(..) | + ast::ExprKind::Tup(..) => true, + ast::ExprKind::AddrOf(_, ref expr) | + ast::ExprKind::Box(ref expr) | + ast::ExprKind::Try(ref expr) | + ast::ExprKind::Unary(_, ref expr) | + ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), + _ => false, + } +} + pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), -- cgit 1.4.1-3-g733a5 From 22c9025027144a74bc86893a6af6b9ad807f21dc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 16 Aug 2017 00:48:12 +0900 Subject: Format source codes --- src/bin/cargo-fmt.rs | 12 +++++++----- src/config.rs | 8 +++++--- src/expr.rs | 30 ++++++++++++++++-------------- src/issues.rs | 32 +++++++++++++++++++------------- src/items.rs | 44 +++++++++++++++++++++++++------------------- src/macros.rs | 12 +++++++----- src/patterns.rs | 12 +++++++----- src/types.rs | 12 +++++++----- src/visitor.rs | 10 ++++++---- 9 files changed, 99 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 001ffb649c6..e6a86e04b9e 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -94,11 +94,13 @@ fn execute() -> i32 { print_usage_to_stderr(&opts, &e.to_string()); failure } - Ok(status) => if status.success() { - success - } else { - status.code().unwrap_or(failure) - }, + Ok(status) => { + if status.success() { + success + } else { + status.code().unwrap_or(failure) + } + } } } diff --git a/src/config.rs b/src/config.rs index ce045502c9c..2b4665729c4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -568,9 +568,11 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { Ok(ref md) if md.is_file() => return Ok(Some(config_file)), // Return the error if it's something other than `NotFound`; otherwise we didn't // find the project file yet, and continue searching. - Err(e) => if e.kind() != ErrorKind::NotFound { - return Err(e); - }, + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e); + } + } _ => {} } } diff --git a/src/expr.rs b/src/expr.rs index 46641a10ae6..e75c7e2c9dd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -462,18 +462,20 @@ where None => DefinitiveListTactic::Vertical, } } - IndentStyle::Visual => if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic( - &items, - ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ), - Separator::Comma, - nested_shape.width, - ) - } else { - DefinitiveListTactic::Mixed - }, + IndentStyle::Visual => { + if has_long_item || items.iter().any(ListItem::is_multiline) { + definitive_tactic( + &items, + ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ), + Separator::Comma, + nested_shape.width, + ) + } else { + DefinitiveListTactic::Mixed + } + } }; let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); @@ -1501,8 +1503,8 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( !context.config.force_multiline_blocks() - && (can_extend_match_arm_body(expr), &**expr), - &**expr, + && can_extend_match_arm_body(expr), + &*expr, ) } else { (false, &*body) diff --git a/src/issues.rs b/src/issues.rs index be30ff2d86e..f05aa0512da 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -190,19 +190,25 @@ impl BadIssueSeeker { } match part { - NumberPart::OpenParen => if c != '(' { - return IssueClassification::Bad(issue); - } else { - part = NumberPart::Pound; - }, - NumberPart::Pound => if c == '#' { - part = NumberPart::Number; - }, - NumberPart::Number => if c >= '0' && c <= '9' { - part = NumberPart::CloseParen; - } else { - return IssueClassification::Bad(issue); - }, + NumberPart::OpenParen => { + if c != '(' { + return IssueClassification::Bad(issue); + } else { + part = NumberPart::Pound; + } + } + NumberPart::Pound => { + if c == '#' { + part = NumberPart::Number; + } + } + NumberPart::Number => { + if c >= '0' && c <= '9' { + part = NumberPart::CloseParen; + } else { + return IssueClassification::Bad(issue); + } + } NumberPart::CloseParen => {} } diff --git a/src/items.rs b/src/items.rs index 6285811e79e..867051baea0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -550,12 +550,14 @@ impl<'a> FmtVisitor<'a> { self.block_indent, Some(one_line_width), )?, - ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", field.node.name); - rewrite_assign_rhs(&context, lhs, &**expr, shape)? - } else { - field.node.name.to_string() - }, + ast::VariantData::Unit(..) => { + if let Some(ref expr) = field.node.disr_expr { + let lhs = format!("{} =", field.node.name); + rewrite_assign_rhs(&context, lhs, &**expr, shape)? + } else { + field.node.name.to_string() + } + } }; let attrs_extendable = attrs_str.is_empty() @@ -643,11 +645,13 @@ pub fn format_impl( _ if last_line_contains_single_line_comment(&result) => result.push_str(&sep), BraceStyle::AlwaysNextLine => result.push_str(&sep), BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => if !where_clause_str.is_empty() { - result.push_str(&sep); - } else { - result.push(' '); - }, + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() { + result.push_str(&sep); + } else { + result.push(' '); + } + } } result.push('{'); @@ -1039,14 +1043,16 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&offset.to_string(context.config)); } BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => if !where_clause_str.is_empty() - && (!trait_items.is_empty() || result.contains('\n')) - { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push(' '); - }, + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() + && (!trait_items.is_empty() || result.contains('\n')) + { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push(' '); + } + } } result.push('{'); diff --git a/src/macros.rs b/src/macros.rs index 8c8b50b7ca3..9247a75ce86 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -126,11 +126,13 @@ pub fn rewrite_macro( let macro_name = match extra_ident { None => format!("{}!", mac.node.path), - Some(ident) => if ident == symbol::keywords::Invalid.ident() { - format!("{}!", mac.node.path) - } else { - format!("{}! {}", mac.node.path, ident) - }, + Some(ident) => { + if ident == symbol::keywords::Invalid.ident() { + format!("{}!", mac.node.path) + } else { + format!("{}! {}", mac.node.path, ident) + } + } }; let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { diff --git a/src/patterns.rs b/src/patterns.rs index f4bb59e5127..90a47d785f0 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -51,11 +51,13 @@ impl Rewrite for Pat { Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) } - PatKind::Wild => if 1 <= shape.width { - Some("_".to_owned()) - } else { - None - }, + PatKind::Wild => { + if 1 <= shape.width { + Some("_".to_owned()) + } else { + None + } + } PatKind::Range(ref lhs, ref rhs, ref end_kind) => { let infix = match *end_kind { RangeEnd::Included(RangeSyntax::DotDotDot) => "...", diff --git a/src/types.rs b/src/types.rs index 25bbd92b108..72cace33def 100644 --- a/src/types.rs +++ b/src/types.rs @@ -720,11 +720,13 @@ impl Rewrite for ast::Ty { SeparatorPlace::Back, ) } - ast::TyKind::Infer => if shape.width >= 1 { - Some("_".to_owned()) - } else { - None - }, + ast::TyKind::Infer => { + if shape.width >= 1 { + Some("_".to_owned()) + } else { + None + } + } ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Some(String::from("!")), ast::TyKind::Mac(..) => None, diff --git a/src/visitor.rs b/src/visitor.rs index 85a8fb38f07..2896b39b09d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -321,10 +321,12 @@ impl<'a> FmtVisitor<'a> { attrs = &filtered_attrs; } } - _ => if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_rewrite(item.span, None); - return; - }, + _ => { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { + self.push_rewrite(item.span, None); + return; + } + } } match item.node { -- cgit 1.4.1-3-g733a5 From 8116e3491d4224844b0a1edf31402b1b2e982e7a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 30 Nov 2017 18:07:10 +0900 Subject: Cargo fmt & update a test --- src/expr.rs | 39 +++++++++++----------- .../target/configs-force_multiline_block-false.rs | 8 +++-- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e75c7e2c9dd..33e79d5c2b2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1502,8 +1502,7 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( - !context.config.force_multiline_blocks() - && can_extend_match_arm_body(expr), + !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), &*expr, ) } else { @@ -1731,24 +1730,24 @@ fn can_extend_match_arm_body(body: &ast::Expr) -> bool { // We do not allow `if` to stay on the same line, since we could easily mistake // `pat => if cond { ... }` and `pat if cond => { ... }`. ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, - ast::ExprKind::ForLoop(..) | - ast::ExprKind::Loop(..) | - ast::ExprKind::While(..) | - ast::ExprKind::WhileLet(..) | - ast::ExprKind::Match(..) | - ast::ExprKind::Block(..) | - ast::ExprKind::Closure(..) | - ast::ExprKind::Array(..) | - ast::ExprKind::Call(..) | - ast::ExprKind::MethodCall(..) | - ast::ExprKind::Mac(..) | - ast::ExprKind::Struct(..) | - ast::ExprKind::Tup(..) => true, - ast::ExprKind::AddrOf(_, ref expr) | - ast::ExprKind::Box(ref expr) | - ast::ExprKind::Try(ref expr) | - ast::ExprKind::Unary(_, ref expr) | - ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), + ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Closure(..) + | ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), _ => false, } } diff --git a/tests/target/configs-force_multiline_block-false.rs b/tests/target/configs-force_multiline_block-false.rs index 11ccc9a7512..7cb4cac1d69 100644 --- a/tests/target/configs-force_multiline_block-false.rs +++ b/tests/target/configs-force_multiline_block-false.rs @@ -3,9 +3,11 @@ fn main() { match lorem { - Lorem::Ipsum => if ipsum { - println!("dolor"); - }, + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } Lorem::Dolor => println!("amet"), } } -- cgit 1.4.1-3-g733a5 From 3b36371b7885b06b141bd4a979ba068958e0471d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 30 Nov 2017 19:38:05 +0900 Subject: Format defualtness on specialized impl const --- src/items.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6285811e79e..a16aa3cde53 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1490,6 +1490,7 @@ pub struct StaticParts<'a> { ty: &'a ast::Ty, mutability: ast::Mutability, expr_opt: Option<&'a ptr::P>, + defaultness: Option, span: Span, } @@ -1509,6 +1510,7 @@ impl<'a> StaticParts<'a> { ty: ty, mutability: mutability, expr_opt: Some(expr), + defaultness: None, span: item.span, } } @@ -1525,6 +1527,7 @@ impl<'a> StaticParts<'a> { ty: ty, mutability: ast::Mutability::Immutable, expr_opt: expr_opt.as_ref(), + defaultness: None, span: ti.span, } } @@ -1541,6 +1544,7 @@ impl<'a> StaticParts<'a> { ty: ty, mutability: ast::Mutability::Immutable, expr_opt: Some(expr), + defaultness: Some(ii.defaultness), span: ii.span, } } @@ -1556,8 +1560,9 @@ fn rewrite_static( context.config.space_after_colon(), ); let prefix = format!( - "{}{} {}{}{}", + "{}{}{} {}{}{}", format_visibility(static_parts.vis), + static_parts.defaultness.map_or("", format_defaultness), static_parts.prefix, format_mutability(static_parts.mutability), static_parts.ident, -- cgit 1.4.1-3-g733a5 From 65cb9b4649108a000c77e64cd784f122cdb185f8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 30 Nov 2017 22:13:28 +0900 Subject: Generalize rewrite_array() to types other than ast::Expr --- src/expr.rs | 17 +++++++---------- src/macros.rs | 14 ++------------ 2 files changed, 9 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d1303d95276..e7418562770 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -63,7 +63,7 @@ pub fn format_expr( let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( - expr_vec.iter().map(|e| &**e), + &ptr_vec_to_ref_vec(expr_vec), mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi()), context, shape, @@ -397,16 +397,13 @@ where )) } -pub fn rewrite_array<'a, I>( - expr_iter: I, +pub fn rewrite_array( + exprs: &[&T], span: Span, context: &RewriteContext, shape: Shape, trailing_comma: bool, -) -> Option -where - I: Iterator, -{ +) -> Option { let bracket_size = if context.config.spaces_within_parens_and_brackets() { 2 // "[ " } else { @@ -426,11 +423,11 @@ where let items = itemize_list( context.codemap, - expr_iter, + exprs.iter(), "]", ",", - |item| item.span.lo(), - |item| item.span.hi(), + |item| item.span().lo(), + |item| item.span().hi(), |item| item.rewrite(context, nested_shape), span.lo(), span.hi(), diff --git a/src/macros.rs b/src/macros.rs index 8c8b50b7ca3..6d115e155d0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -255,24 +255,14 @@ pub fn rewrite_macro( trailing_comma = false; } // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. - let expr_vec: Vec<_> = arg_vec - .iter() - .filter_map(|e| match *e { - MacroArg::Expr(ref e) => Some(e.clone()), - _ => None, - }) - .collect(); - if expr_vec.len() != arg_vec.len() { - return Some(context.snippet(mac.span)); - } let sp = mk_sp( context .codemap .span_after(mac.span, original_style.opener()), mac.span.hi() - BytePos(1), ); - let rewrite = - rewrite_array(expr_vec.iter(), sp, context, mac_shape, trailing_comma)?; + let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; + let rewrite = rewrite_array(arg_vec, sp, context, mac_shape, trailing_comma)?; Some(format!("{}{}", macro_name, rewrite)) } -- cgit 1.4.1-3-g733a5 From b33df45d04aeda1e8ed7923b855269eb63306a67 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 30 Nov 2017 22:14:06 +0900 Subject: Look for trailing comma on array and preserve it inside macro call --- src/expr.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e7418562770..49a8479ca0f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -479,7 +479,17 @@ pub fn rewrite_array( separator: ",", trailing_separator: if trailing_comma { SeparatorTactic::Always - } else if context.inside_macro || context.config.indent_style() == IndentStyle::Visual { + } else if context.inside_macro && !exprs.is_empty() { + let ends_with_bracket = context.snippet(span).ends_with(']'); + let bracket_offset = if ends_with_bracket { 1 } else { 0 }; + let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); + let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?; + if &snippet[last_char_index..last_char_index + 1] == "," { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } else if context.config.indent_style() == IndentStyle::Visual { SeparatorTactic::Never } else { SeparatorTactic::Vertical -- cgit 1.4.1-3-g733a5 From ae18c6064aa44ac81963fcb623cc17cf3e94f78c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 30 Nov 2017 15:04:19 +0100 Subject: Run rustfmt --- src/filemap.rs | 6 +++++- src/items.rs | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 0532646b9f4..8bed486e7b9 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -30,7 +30,11 @@ pub fn append_newline(s: &mut StringBuffer) { s.push_str("\n"); } -pub fn write_all_files(file_map: &[FileRecord], out: &mut T, config: &Config) -> Result<(), io::Error> +pub fn write_all_files( + file_map: &[FileRecord], + out: &mut T, + config: &Config, +) -> Result<(), io::Error> where T: Write, { diff --git a/src/items.rs b/src/items.rs index fcdc3b2c858..65dce5ac9b4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2462,7 +2462,6 @@ fn rewrite_trait_bounds( bounds: &[ast::TyParamBound], shape: Shape, ) -> Option { - if bounds.is_empty() { return Some(String::new()); } -- cgit 1.4.1-3-g733a5 From 9d8cfbcd93209aaa56f9576324a2d7e5784390da Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 30 Nov 2017 23:55:12 +0100 Subject: Fix imports formatting broken after AST change --- src/imports.rs | 260 +++++++++++++++++++++++++++++---------------------------- src/visitor.rs | 2 +- 2 files changed, 135 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 56d23fa9827..24ca36851a1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -13,6 +13,7 @@ use std::cmp::Ordering; use syntax::ast; use syntax::codemap::{BytePos, Span}; + use spanned::Spanned; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; @@ -25,14 +26,6 @@ use types::{rewrite_path, PathContext}; use utils::{format_visibility, mk_sp}; use visitor::{rewrite_extern_crate, FmtVisitor}; -fn path_of(a: &ast::ViewPath_) -> &ast::Path { - match *a { - ast::ViewPath_::ViewPathSimple(_, ref p) - | ast::ViewPath_::ViewPathGlob(ref p) - | ast::ViewPath_::ViewPathList(ref p, _) => p, - } -} - fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) } @@ -47,75 +40,76 @@ fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { a.segments.len().cmp(&b.segments.len()) } -fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Ordering { - let a_name_str = &*a.node.name.name.as_str(); - let b_name_str = &*b.node.name.name.as_str(); - let name_ordering = if a_name_str == "self" { - if b_name_str == "self" { - Ordering::Equal - } else { - Ordering::Less - } - } else if b_name_str == "self" { - Ordering::Greater - } else { - a_name_str.cmp(b_name_str) - }; - if name_ordering == Ordering::Equal { - match a.node.rename { - Some(a_rename) => match b.node.rename { - Some(b_rename) => a_rename.name.as_str().cmp(&b_rename.name.as_str()), - None => Ordering::Greater, - }, - None => Ordering::Less, - } - } else { - name_ordering - } -} +fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Ordering { + use ast::UseTreeKind::*; -fn compare_path_list_item_lists( - a_items: &[ast::PathListItem], - b_items: &[ast::PathListItem], -) -> Ordering { - let mut a = a_items.to_owned(); - let mut b = b_items.to_owned(); - a.sort_by(|a, b| compare_path_list_items(a, b)); - b.sort_by(|a, b| compare_path_list_items(a, b)); - for comparison_pair in a.iter().zip(b.iter()) { - let ord = compare_path_list_items(comparison_pair.0, comparison_pair.1); - if ord != Ordering::Equal { - return ord; + // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be + // fully added + if !nested { + let paths_cmp = compare_paths(&a.prefix, &b.prefix); + if paths_cmp != Ordering::Equal { + return paths_cmp; } } - a.len().cmp(&b.len()) -} -fn compare_view_path_types(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering { - use syntax::ast::ViewPath_::*; - match (a, b) { - (&ViewPathSimple(..), &ViewPathSimple(..)) | (&ViewPathGlob(_), &ViewPathGlob(_)) => { - Ordering::Equal + match (&a.kind, &b.kind) { + (&Simple(ident_a), &Simple(ident_b)) => { + let name_a = &*a.prefix.segments.last().unwrap().identifier.name.as_str(); + let name_b = &*b.prefix.segments.last().unwrap().identifier.name.as_str(); + let name_ordering = if name_a == "self" { + if name_b == "self" { + Ordering::Equal + } else { + Ordering::Less + } + } else if name_b == "self" { + Ordering::Greater + } else { + name_a.cmp(name_b) + }; + if name_ordering == Ordering::Equal { + if ident_a.name.as_str() != name_a { + if ident_b.name.as_str() != name_b { + ident_a.name.as_str().cmp(&ident_b.name.as_str()) + } else { + Ordering::Greater + } + } else { + Ordering::Less + } + } else { + name_ordering + } } - (&ViewPathSimple(..), _) | (&ViewPathGlob(_), &ViewPathList(..)) => Ordering::Less, - (&ViewPathList(_, ref a_items), &ViewPathList(_, ref b_items)) => { - compare_path_list_item_lists(a_items, b_items) + (&Glob, &Glob) => Ordering::Equal, + (&Simple(_), _) | (&Glob, &Nested(_)) => Ordering::Less, + (&Nested(ref a_items), &Nested(ref b_items)) => { + let mut a = a_items + .iter() + .map(|&(ref tree, _)| tree.clone()) + .collect::>(); + let mut b = b_items + .iter() + .map(|&(ref tree, _)| tree.clone()) + .collect::>(); + a.sort_by(|a, b| compare_use_trees(a, b, true)); + b.sort_by(|a, b| compare_use_trees(a, b, true)); + for comparison_pair in a.iter().zip(b.iter()) { + let ord = compare_use_trees(comparison_pair.0, comparison_pair.1, true); + if ord != Ordering::Equal { + return ord; + } + } + a.len().cmp(&b.len()) } - (&ViewPathGlob(_), &ViewPathSimple(..)) | (&ViewPathList(..), _) => Ordering::Greater, - } -} - -fn compare_view_paths(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering { - match compare_paths(path_of(a), path_of(b)) { - Ordering::Equal => compare_view_path_types(a, b), - cmp => cmp, + (&Glob, &Simple(_)) | (&Nested(_), _) => Ordering::Greater, } } fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> Option { match (&a.node, &b.node) { - (&ast::ItemKind::Use(ref a_vp), &ast::ItemKind::Use(ref b_vp)) => { - Some(compare_view_paths(&a_vp.node, &b_vp.node)) + (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { + Some(compare_use_trees(&a_tree, &b_tree, false)) } (&ast::ItemKind::ExternCrate(..), &ast::ItemKind::ExternCrate(..)) => { Some(context.snippet(a.span).cmp(&context.snippet(b.span))) @@ -127,11 +121,7 @@ fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> // TODO (some day) remove unused imports, expand globs, compress many single // imports into a list import. -fn rewrite_view_path_prefix( - path: &ast::Path, - context: &RewriteContext, - shape: Shape, -) -> Option { +fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" && path.segments.len() > 1 { @@ -146,29 +136,34 @@ fn rewrite_view_path_prefix( Some(path_str) } -impl Rewrite for ast::ViewPath { +impl Rewrite for ast::UseTree { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - ast::ViewPath_::ViewPathList(ref path, ref path_list) => { - rewrite_use_list(shape, path, path_list, self.span, context) + match self.kind { + ast::UseTreeKind::Nested(ref items) => { + rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context) } - ast::ViewPath_::ViewPathGlob(ref path) => { - // 4 = "::*".len() + ast::UseTreeKind::Glob => { let prefix_shape = shape.sub_width(3)?; - let path_str = rewrite_view_path_prefix(path, context, prefix_shape)?; - Some(format!("{}::*", path_str)) + + if self.prefix.segments.len() > 0 { + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; + Some(format!("{}::*", path_str)) + } else { + Some("*".into()) + } } - ast::ViewPath_::ViewPathSimple(ident, ref path) => { + ast::UseTreeKind::Simple(ident) => { let ident_str = ident.to_string(); + // 4 = " as ".len() let prefix_shape = shape.sub_width(ident_str.len() + 4)?; - let path_str = rewrite_view_path_prefix(path, context, prefix_shape)?; + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; - Some(if path.segments.last().unwrap().identifier == ident { - path_str + if self.prefix.segments.last().unwrap().identifier == ident { + Some(path_str) } else { - format!("{} as {}", path_str, ident_str) - }) + Some(format!("{} as {}", path_str, ident_str)) + } } } } @@ -178,7 +173,7 @@ impl Rewrite for ast::ViewPath { fn rewrite_import( context: &RewriteContext, vis: &ast::Visibility, - vp: &ast::ViewPath, + tree: &ast::UseTree, attrs: &[ast::Attribute], shape: Shape, ) -> Option { @@ -187,14 +182,12 @@ fn rewrite_import( let rw = shape .offset_left(vis.len() + 4) .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| match vp.node { - // If we have an empty path list with no attributes, we erase it - ast::ViewPath_::ViewPathList(_, ref path_list) - if path_list.is_empty() && attrs.is_empty() => - { + .and_then(|shape| match tree.kind { + // If we have an empty nested group with no attributes, we erase it + ast::UseTreeKind::Nested(ref items) if items.is_empty() && attrs.is_empty() => { Some("".into()) } - _ => vp.rewrite(context, shape), + _ => tree.rewrite(context, shape), }); match rw { Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), @@ -225,8 +218,8 @@ fn rewrite_imports( }; let item_str = match item.node { - ast::ItemKind::Use(ref vp) => { - rewrite_import(context, &item.vis, vp, &item.attrs, shape)? + ast::ItemKind::Use(ref tree) => { + rewrite_import(context, &item.vis, tree, &item.attrs, shape)? } ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, _ => return None, @@ -276,10 +269,10 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(span, rw); } - pub fn format_import(&mut self, item: &ast::Item, vp: &ast::ViewPath) { + pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { let span = item.span; let shape = self.shape(); - let rw = rewrite_import(&self.get_context(), &item.vis, vp, &item.attrs, shape); + let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape); match rw { Some(ref s) if s.is_empty() => { // Format up to last newline @@ -304,34 +297,48 @@ impl<'a> FmtVisitor<'a> { } } -fn rewrite_single_use_list(path_str: String, vpi: &ast::PathListItem) -> String { - let mut item_str = vpi.node.name.to_string(); - if item_str == "self" { - item_str = "".to_owned(); - } - let path_item_str = if path_str.is_empty() { - if item_str.is_empty() { - "self".to_owned() +fn rewrite_nested_use_tree_single(path_str: String, tree: &ast::UseTree) -> String { + if let ast::UseTreeKind::Simple(rename) = tree.kind { + let ident = tree.prefix.segments.last().unwrap().identifier; + let mut item_str = ident.name.to_string(); + if item_str == "self" { + item_str = "".to_owned(); + } + + let path_item_str = if path_str.is_empty() { + if item_str.is_empty() { + "self".to_owned() + } else { + item_str + } + } else if item_str.is_empty() { + path_str } else { - item_str + format!("{}::{}", path_str, item_str) + }; + + if ident == rename { + path_item_str + } else { + format!("{} as {}", path_item_str, rename) } - } else if item_str.is_empty() { - path_str } else { - format!("{}::{}", path_str, item_str) - }; - append_alias(path_item_str, vpi) + unimplemented!("`use_nested_groups` is not yet fully supported"); + } } -fn rewrite_path_item(vpi: &&ast::PathListItem) -> Option { - Some(append_alias(vpi.node.name.to_string(), vpi)) -} +fn rewrite_nested_use_tree_item(tree: &&ast::UseTree) -> Option { + Some(if let ast::UseTreeKind::Simple(rename) = tree.kind { + let ident = tree.prefix.segments.last().unwrap().identifier; -fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String { - match vpi.node.rename { - Some(rename) => format!("{} as {}", path_item_str, rename), - None => path_item_str, - } + if ident == rename { + ident.name.to_string() + } else { + format!("{} as {}", ident.name.to_string(), rename) + } + } else { + unimplemented!("`use_nested_groups` is not yet fully supported"); + }) } #[derive(Eq, PartialEq)] @@ -408,22 +415,23 @@ impl<'a> Ord for ImportItem<'a> { // Pretty prints a multi-item import. // If the path list is empty, it leaves the braces empty. -fn rewrite_use_list( +fn rewrite_nested_use_tree( shape: Shape, path: &ast::Path, - path_list: &[ast::PathListItem], + trees: &[(ast::UseTree, ast::NodeId)], span: Span, context: &RewriteContext, ) -> Option { // Returns a different option to distinguish `::foo` and `foo` let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; - match path_list.len() { + match trees.len() { 0 => { return rewrite_path(context, PathContext::Import, None, path, shape) .map(|path_str| format!("{}::{{}}", path_str)); } - 1 => return Some(rewrite_single_use_list(path_str, &path_list[0])), + // TODO: fix this + 1 => return Some(rewrite_nested_use_tree_single(path_str, &trees[0].0)), _ => (), } @@ -441,12 +449,12 @@ fn rewrite_use_list( let mut items = vec![ListItem::from_str("")]; let iter = itemize_list( context.codemap, - path_list.iter(), + trees.iter().map(|ref tree| &tree.0), "}", ",", - |vpi| vpi.span.lo(), - |vpi| vpi.span.hi(), - rewrite_path_item, + |tree| tree.span.lo(), + |tree| tree.span.hi(), + rewrite_nested_use_tree_item, context.codemap.span_after(span, "{"), span.hi(), false, diff --git a/src/visitor.rs b/src/visitor.rs index 85a8fb38f07..6f3ec851c25 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -328,7 +328,7 @@ impl<'a> FmtVisitor<'a> { } match item.node { - ast::ItemKind::Use(ref vp) => self.format_import(item, vp), + ast::ItemKind::Use(ref tree) => self.format_import(item, tree), ast::ItemKind::Impl(..) => { let snippet = self.snippet(item.span); let where_span_end = snippet -- cgit 1.4.1-3-g733a5 From c4c9bf028ab833ca4582f64f5640be37304de872 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 2 Dec 2017 17:43:50 +0900 Subject: Keep vertical spaces between items or statements within range --- src/config.rs | 4 ++++ src/missed_spans.rs | 22 +++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 2b4665729c4..0c7d5c02c01 100644 --- a/src/config.rs +++ b/src/config.rs @@ -651,6 +651,10 @@ create_config! { "Add trailing semicolon after break, continue and return"; match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + blank_lines_upper_bound: usize, 1, false, + "Maximum number of blank lines which can be put between items."; + blank_lines_lower_bound: usize, 0, false, + "Minimum number of blank lines which must be put between items."; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 9d20e6c6e55..101d49305ff 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::borrow::Cow; +use std::iter::repeat; use syntax::codemap::{BytePos, Pos, Span}; @@ -74,8 +75,27 @@ impl<'a> FmtVisitor<'a> { self.last_pos = end; let span = mk_sp(start, end); + let snippet = self.snippet(span); + if snippet.trim().is_empty() { + // Keep vertical spaces within range. + self.push_vertical_spaces(&snippet); + process_last_snippet(self, "", &snippet); + } else { + self.write_snippet(span, &process_last_snippet); + } + } - self.write_snippet(span, &process_last_snippet); + fn push_vertical_spaces(&mut self, original: &str) { + let mut newline_count = original.chars().filter(|&c| c == '\n').count(); + let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; + let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; + if newline_count > newline_upper_bound { + newline_count = newline_upper_bound; + } else if newline_count < newline_lower_bound { + newline_count = newline_lower_bound; + } + let blank_lines: String = repeat('\n').take(newline_count).collect(); + self.buffer.push_str(&blank_lines); } fn write_snippet(&mut self, span: Span, process_last_snippet: F) -- cgit 1.4.1-3-g733a5 From 89f27764edcd5086278e032603efb8ea9b1591c1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 2 Dec 2017 17:45:39 +0900 Subject: Cargo fmt and update tests --- build.rs | 1 - src/bin/git-fmt.rs | 1 - src/bin/rustfmt.rs | 1 - src/comment.rs | 5 ----- src/config.rs | 4 ---- src/imports.rs | 1 - src/items.rs | 1 - src/modules.rs | 1 - tests/target/control-brace-style-always-next-line.rs | 4 ---- tests/target/control-brace-style-always-same-line.rs | 4 ---- tests/target/else-if-brace-style-always-next-line.rs | 2 -- tests/target/else-if-brace-style-always-same-line.rs | 2 -- tests/target/else-if-brace-style-closing-next-line.rs | 2 -- tests/target/empty-tuple-no-conversion-to-unit-struct.rs | 1 - tests/target/enum.rs | 1 - tests/target/fn-simple.rs | 1 - tests/target/fn.rs | 1 - tests/target/impls.rs | 1 - tests/target/multiple.rs | 1 - tests/target/type_alias.rs | 1 - 20 files changed, 36 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index 42d9330f75d..2643946236d 100644 --- a/build.rs +++ b/build.rs @@ -14,7 +14,6 @@ use std::io::Write; use std::path::PathBuf; use std::process::Command; - fn main() { let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs index 9bfeff8420e..5e7cb458649 100644 --- a/src/bin/git-fmt.rs +++ b/src/bin/git-fmt.rs @@ -14,7 +14,6 @@ use getopts::{Matches, Options}; use rustfmt::{run, Input}; use rustfmt::config; - fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files .iter() diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 001f2c8e0f7..9bf26887881 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -10,7 +10,6 @@ #![cfg(not(test))] - extern crate env_logger; extern crate getopts; extern crate rustfmt_nightly as rustfmt; diff --git a/src/comment.rs b/src/comment.rs index 2e3dadd2066..4b16199d826 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -824,9 +824,6 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { } } - - - /// Iterator over an alternating sequence of functional and commented parts of /// a string. The first item is always a, possibly zero length, subslice of /// functional text. Line style comments contain their ending newlines. @@ -948,7 +945,6 @@ fn changed_comment_content(orig: &str, new: &str) -> bool { res } - /// Iterator over the 'payload' characters of a comment. /// It skips whitespace, comment start/end marks, and '*' at the beginning of lines. /// The comment must be one comment, ie not more than one start mark (no multiple line comments, @@ -994,7 +990,6 @@ impl<'a> Iterator for CommentReducer<'a> { } } - fn remove_comment_header(comment: &str) -> &str { if comment.starts_with("///") || comment.starts_with("//!") { &comment[3..] diff --git a/src/config.rs b/src/config.rs index 0c7d5c02c01..4172710a089 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,7 +21,6 @@ use file_lines::FileLines; use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; use Summary; - macro_rules! is_nightly_channel { () => { env::var("CFG_RELEASE_CHANNEL") @@ -88,7 +87,6 @@ configuration_option_enum! { TypeDensity: Wide, } - impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { @@ -579,8 +577,6 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { Ok(None) } - - create_config! { // Fundamental stuff max_width: usize, 100, true, "Maximum width of each line"; diff --git a/src/imports.rs b/src/imports.rs index 24ca36851a1..f38e41eca89 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -13,7 +13,6 @@ use std::cmp::Ordering; use syntax::ast; use syntax::codemap::{BytePos, Span}; - use spanned::Spanned; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; diff --git a/src/items.rs b/src/items.rs index ce0439b127b..2fc34057355 100644 --- a/src/items.rs +++ b/src/items.rs @@ -285,7 +285,6 @@ impl<'a> FmtVisitor<'a> { self.format_item(item); } - fn format_foreign_item(&mut self, item: &ast::ForeignItem) { let rewrite = item.rewrite(&self.get_context(), self.shape()); self.push_rewrite(item.span(), rewrite); diff --git a/src/modules.rs b/src/modules.rs index d136f270991..30deafd3f9e 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -18,7 +18,6 @@ use syntax::parse::parser; use utils::contains_skip; - /// List all the files containing modules of a crate. /// If a file is used twice in a crate, it appears only once. pub fn list_files<'a>( diff --git a/tests/target/control-brace-style-always-next-line.rs b/tests/target/control-brace-style-always-next-line.rs index 5b368fd08db..054a3075ca0 100644 --- a/tests/target/control-brace-style-always-next-line.rs +++ b/tests/target/control-brace-style-always-next-line.rs @@ -7,28 +7,24 @@ fn main() { (); } - 'label: loop // loop comment { (); } - cond = true; while cond { (); } - 'while_label: while cond { // while comment (); } - for obj in iter { for sub_obj in obj diff --git a/tests/target/control-brace-style-always-same-line.rs b/tests/target/control-brace-style-always-same-line.rs index 46b74b95d82..ae6bf4a5682 100644 --- a/tests/target/control-brace-style-always-same-line.rs +++ b/tests/target/control-brace-style-always-same-line.rs @@ -6,26 +6,22 @@ fn main() { (); } - 'label: loop // loop comment { (); } - cond = true; while cond { (); } - 'while_label: while cond { // while comment (); } - for obj in iter { for sub_obj in obj { 'nested_while_label: while cond { diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs index c180ff697fc..31e12cfa0d0 100644 --- a/tests/target/else-if-brace-style-always-next-line.rs +++ b/tests/target/else-if-brace-style-always-next-line.rs @@ -14,10 +14,8 @@ fn main() { (); } - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - if true { (); diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs index 4c6153d5f1f..5e5ab21a0d8 100644 --- a/tests/target/else-if-brace-style-always-same-line.rs +++ b/tests/target/else-if-brace-style-always-same-line.rs @@ -13,10 +13,8 @@ fn main() { (); } - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - if true { (); } else if false { diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs index 04ee82bb828..c99807dc06d 100644 --- a/tests/target/else-if-brace-style-closing-next-line.rs +++ b/tests/target/else-if-brace-style-closing-next-line.rs @@ -13,10 +13,8 @@ fn main() { (); } - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - if true { (); } diff --git a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs index 778937b0d56..0b9a15e8a92 100644 --- a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs +++ b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs @@ -3,7 +3,6 @@ enum TestEnum { Arm2, } - fn foo() { let test = TestEnum::Arm1; match test { diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 78b0fd1b69d..779c8b168a3 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -95,7 +95,6 @@ where Right { list: I, root: T }, // Post Comment } - enum EmtpyWithComment { // Some comment } diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index 3b5e884d4a4..4e6e6493835 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -18,7 +18,6 @@ fn simple( "cool" } - fn weird_comment( // /*/ double level */ comment x: Hello, // /*/* triple, even */*/ diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 8b581e83539..b78a8b5b21e 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -24,7 +24,6 @@ where } - fn foo( a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, diff --git a/tests/target/impls.rs b/tests/target/impls.rs index e0070adcad4..a743d7f3067 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -78,7 +78,6 @@ mod a { } } - mod b { mod a { impl Foo { diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 6e61c82e5f6..b766eb72f68 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -129,7 +129,6 @@ fn main() { println!("{}", i); } - while true { hello(); } diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index 5aef092934e..8833be9e1a0 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -52,7 +52,6 @@ pub type CommentTest< T, > = (); - pub type WithWhereClause where T: Clone, -- cgit 1.4.1-3-g733a5 From b9126fac82280f5a1ba9365957dce5bb8268ee15 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 2 Dec 2017 23:01:50 +0900 Subject: Do not format fenced code blocks in comment --- src/comment.rs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 2e3dadd2066..9b9056c4170 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -319,6 +319,7 @@ fn rewrite_comment_inner( let mut result = opener.to_owned(); let mut is_prev_line_multi_line = false; + let mut inside_code_block = false; let comment_line_separator = format!("\n{}{}", indent_str, line_start); for line in lines { if result == opener { @@ -331,6 +332,14 @@ fn rewrite_comment_inner( result.push_str(&comment_line_separator); } + if line.starts_with("```") { + inside_code_block = !inside_code_block; + } + if inside_code_block { + result.push_str(line); + continue; + } + if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { match rewrite_string(line, &fmt, Some(max_chars)) { Some(ref s) => { -- cgit 1.4.1-3-g733a5 From ffbe52eb7638f6647d09564d44314b9bf8d76836 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 1 Dec 2017 13:28:36 +0900 Subject: Add whitelists of macros that need special-case format --- src/expr.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index afa31983046..ce2ea65b65a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1807,6 +1807,18 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } +const FORMAT_LIKE_WHITELIST: &[&str] = &[ + "eprint!", + "eprintln!", + "format!", + "format_args!", + "panic!", + "println!", + "unreachable!", +]; + +const WRITE_LIKE_WHITELIST: &[&str] = &["assert!", "write!", "writeln!"]; + pub fn rewrite_call( context: &RewriteContext, callee: &str, -- cgit 1.4.1-3-g733a5 From 0f5dcc665da4da6af0532bf1ca5e96ac4c9f6286 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 1 Dec 2017 13:30:04 +0900 Subject: Handle special-case macros --- src/expr.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- src/lists.rs | 28 +++++++++++++++++- 2 files changed, 108 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ce2ea65b65a..70363f7dd23 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1862,9 +1862,6 @@ where }; let used_width = extra_offset(callee_str, shape); let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; - // 1 = "(" - let combine_arg_with_callee = - callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; // 1 = "(" or ")" let one_line_shape = shape @@ -1889,7 +1886,7 @@ where one_line_width, args_max_width, force_trailing_comma, - combine_arg_with_callee, + callee_str, )?; if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { @@ -1930,7 +1927,7 @@ fn rewrite_call_args<'a, T>( one_line_width: usize, args_max_width: usize, force_trailing_comma: bool, - combine_arg_with_callee: bool, + callee_str: &str, ) -> Option<(bool, String)> where T: Rewrite + Spanned + ToExpr + 'a, @@ -1960,7 +1957,7 @@ where nested_shape, one_line_width, args_max_width, - combine_arg_with_callee, + callee_str, ); let fmt = ListFormatting { @@ -1980,7 +1977,8 @@ where config: context.config, }; - write_list(&item_vec, &fmt).map(|args_str| (tactic != DefinitiveListTactic::Vertical, args_str)) + write_list(&item_vec, &fmt) + .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str)) } fn try_overflow_last_arg<'a, T>( @@ -1991,11 +1989,14 @@ fn try_overflow_last_arg<'a, T>( nested_shape: Shape, one_line_width: usize, args_max_width: usize, - combine_arg_with_callee: bool, + callee_str: &str, ) -> DefinitiveListTactic where T: Rewrite + Spanned + ToExpr + 'a, { + // 1 = "(" + let combine_arg_with_callee = + callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); // Replace the last item with its first line to see if it fits with @@ -2032,6 +2033,16 @@ where _ if args.len() >= 1 => { item_vec[args.len() - 1].item = args.last() .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); + + let default_tactic = || { + definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ) + }; + // Use horizontal layout for a function with a single argument as long as // everything fits in a single line. if args.len() == 1 @@ -2042,12 +2053,44 @@ where { tactic = DefinitiveListTactic::Horizontal; } else { - tactic = definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ); + tactic = default_tactic(); + let is_simple_enough = + tactic == DefinitiveListTactic::Vertical && is_every_args_simple(args); + if is_simple_enough + && FORMAT_LIKE_WHITELIST + .iter() + .find(|s| **s == callee_str) + .is_some() + { + let args_tactic = definitive_tactic( + &item_vec[1..], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ); + tactic = if args_tactic == DefinitiveListTactic::Horizontal { + DefinitiveListTactic::FormatCall + } else { + default_tactic() + }; + } else if is_simple_enough && item_vec.len() >= 2 + && WRITE_LIKE_WHITELIST + .iter() + .find(|s| **s == callee_str) + .is_some() + { + let args_tactic = definitive_tactic( + &item_vec[2..], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ); + tactic = if args_tactic == DefinitiveListTactic::Horizontal { + DefinitiveListTactic::WriteCall + } else { + default_tactic() + }; + } } } _ => (), @@ -2056,6 +2099,30 @@ where tactic } +fn is_simple_arg(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Lit(..) => true, + ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Cast(ref expr, _) + | ast::ExprKind::Field(ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::TupField(ref expr, _) + | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr), + ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { + is_simple_arg(lhs) && is_simple_arg(rhs) + } + _ => false, + } +} + +fn is_every_args_simple(lists: &[&T]) -> bool { + lists + .iter() + .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) +} + /// Returns a shape for the last argument which is going to be overflowed. fn last_arg_shape( lists: &[&T], diff --git a/src/lists.rs b/src/lists.rs index f3e1c362dc1..a51653b3732 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -160,6 +160,10 @@ pub enum DefinitiveListTactic { Vertical, Horizontal, Mixed, + // Special case tactic for `format!()` variants. + FormatCall, + // Special case tactic for `write!()` varianta. + WriteCall, } impl DefinitiveListTactic { @@ -267,7 +271,7 @@ where I: IntoIterator + Clone, T: AsRef, { - let tactic = formatting.tactic; + let mut tactic = formatting.tactic; let sep_len = formatting.separator.len(); // Now that we know how we will layout, we can decide for sure if there @@ -309,6 +313,28 @@ where DefinitiveListTactic::Horizontal if !first => { result.push(' '); } + DefinitiveListTactic::FormatCall if !first => { + result.push('\n'); + result.push_str(indent_str); + tactic = DefinitiveListTactic::Horizontal; + } + DefinitiveListTactic::WriteCall => { + let second = i == 1; + let third = i == 2; + + if first { + // Nothing + } else if second { + result.push('\n'); + result.push_str(indent_str); + } else if third { + result.push('\n'); + result.push_str(indent_str); + tactic = DefinitiveListTactic::Horizontal; + } else { + unreachable!(); + } + } DefinitiveListTactic::Vertical if !first => { result.push('\n'); result.push_str(indent_str); -- cgit 1.4.1-3-g733a5 From 16184d3e165018fa5b78f5f99cfc844e5af33bd6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 1 Dec 2017 13:30:21 +0900 Subject: Cargo fmt and update a test --- src/checkstyle.rs | 3 +-- src/comment.rs | 6 +----- src/config.rs | 3 +-- src/expr.rs | 20 ++++---------------- src/items.rs | 4 +--- src/lib.rs | 3 +-- src/types.rs | 5 +---- tests/target/macros.rs | 3 +-- 8 files changed, 11 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 34c1d81d40c..cbb6573b322 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -57,8 +57,7 @@ where writer, "", - mismatch.line_number, - message + mismatch.line_number, message )?; } } diff --git a/src/comment.rs b/src/comment.rs index 9b9056c4170..8b8112618b4 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -205,11 +205,7 @@ pub fn combine_strs_with_missing_comments( }; Some(format!( "{}{}{}{}{}", - prev_str, - first_sep, - missing_comment, - second_sep, - next_str, + prev_str, first_sep, missing_comment, second_sep, next_str, )) } diff --git a/src/config.rs b/src/config.rs index 2b4665729c4..d7b5e8c6ee3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -714,8 +714,7 @@ mod test { toml, format!( "merge_derives = {}\nskip_children = {}\n", - merge_derives, - skip_children, + merge_derives, skip_children, ) ); } diff --git a/src/expr.rs b/src/expr.rs index 70363f7dd23..0215975f9a3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -353,10 +353,7 @@ where if one_line_width <= shape.width { return Some(format!( "{}{}{}{}", - lhs_result, - pp.infix, - rhs_result, - pp.suffix + lhs_result, pp.infix, rhs_result, pp.suffix )); } } @@ -390,10 +387,7 @@ where }; Some(format!( "{}{}{}{}", - lhs_result, - infix_with_sep, - rhs_result, - pp.suffix + lhs_result, infix_with_sep, rhs_result, pp.suffix )) } @@ -883,10 +877,7 @@ impl<'a> ControlFlow<'a> { let result = format!( "{} {} {{ {} }} else {{ {} }}", - self.keyword, - pat_expr_str, - if_str, - else_str + self.keyword, pat_expr_str, if_str, else_str ); if result.len() <= width { @@ -1589,10 +1580,7 @@ fn rewrite_match_body( Some(format!( "{} =>{}{}{}", - pats_str, - block_sep, - body_str, - body_suffix + pats_str, block_sep, body_str, body_suffix )) }; diff --git a/src/items.rs b/src/items.rs index ce0439b127b..b4fd5a340bc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -844,9 +844,7 @@ fn rewrite_trait_ref( if !(retry && trait_ref_str.contains('\n')) { return Some(format!( "{} {}{}", - generics_str, - polarity_str, - &trait_ref_str + generics_str, polarity_str, &trait_ref_str )); } } diff --git a/src/lib.rs b/src/lib.rs index 1eec30833b9..0b54c71a6eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,8 +93,7 @@ impl fmt::Display for ErrorKind { ErrorKind::LineOverflow(found, maximum) => write!( fmt, "line exceeded maximum width (maximum: {}, found: {})", - maximum, - found + maximum, found ), ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), diff --git a/src/types.rs b/src/types.rs index 92a1adbbc8e..ef185a3f7d4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -442,10 +442,7 @@ impl Rewrite for ast::WherePredicate { { format!( "for< {} > {}{}{}", - lifetime_str, - type_str, - colon, - bounds_str + lifetime_str, type_str, colon, bounds_str ) } else { format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 8230ae91161..8b22a457463 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -135,8 +135,7 @@ fn issue_1279() { fn issue_1555() { let hello = &format!( "HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", - "65454654654654654654654655464", - "4" + "65454654654654654654654655464", "4" ); } -- cgit 1.4.1-3-g733a5 From 27a540db4709307928f5f5ca0e4b7f3e1ac947c9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 1 Dec 2017 13:44:40 +0900 Subject: Factor out a mess --- src/expr.rs | 70 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0215975f9a3..2c878fe16b5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2042,42 +2042,27 @@ where tactic = DefinitiveListTactic::Horizontal; } else { tactic = default_tactic(); - let is_simple_enough = - tactic == DefinitiveListTactic::Vertical && is_every_args_simple(args); - if is_simple_enough - && FORMAT_LIKE_WHITELIST - .iter() - .find(|s| **s == callee_str) - .is_some() - { - let args_tactic = definitive_tactic( - &item_vec[1..], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ); - tactic = if args_tactic == DefinitiveListTactic::Horizontal { - DefinitiveListTactic::FormatCall - } else { - default_tactic() - }; - } else if is_simple_enough && item_vec.len() >= 2 - && WRITE_LIKE_WHITELIST - .iter() - .find(|s| **s == callee_str) - .is_some() - { + + // For special-case macros, we may want to use different tactics. + let maybe_args_offset = maybe_get_args_offset(callee_str, args); + + if tactic == DefinitiveListTactic::Vertical && maybe_args_offset.is_some() { + let args_offset = maybe_args_offset.unwrap(); let args_tactic = definitive_tactic( - &item_vec[2..], + &item_vec[args_offset..], ListTactic::HorizontalVertical, Separator::Comma, nested_shape.width, ); - tactic = if args_tactic == DefinitiveListTactic::Horizontal { - DefinitiveListTactic::WriteCall - } else { - default_tactic() - }; + + // Every argument is simple and fits on a single line. + if args_tactic == DefinitiveListTactic::Horizontal { + tactic = if args_offset == 1 { + DefinitiveListTactic::FormatCall + } else { + DefinitiveListTactic::WriteCall + }; + } } } } @@ -2111,6 +2096,29 @@ fn is_every_args_simple(lists: &[&T]) -> bool { .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) } +/// In case special-case style is required, returns an offset from which we start horizontal layout. +fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option { + if FORMAT_LIKE_WHITELIST + .iter() + .find(|s| **s == callee_str) + .is_some() + && args.len() >= 1 + && is_every_args_simple(args) + { + Some(1) + } else if WRITE_LIKE_WHITELIST + .iter() + .find(|s| **s == callee_str) + .is_some() + && args.len() >= 2 + && is_every_args_simple(args) + { + Some(2) + } else { + None + } +} + /// Returns a shape for the last argument which is going to be overflowed. fn last_arg_shape( lists: &[&T], -- cgit 1.4.1-3-g733a5 From 8f395bd953ad856b03a98836268ca01bebc10733 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 1 Dec 2017 19:47:56 +0900 Subject: Cargo fmt --- src/expr.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2c878fe16b5..e82d23b21fd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2101,17 +2101,13 @@ fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option= 1 - && is_every_args_simple(args) + .is_some() && args.len() >= 1 && is_every_args_simple(args) { Some(1) } else if WRITE_LIKE_WHITELIST .iter() .find(|s| **s == callee_str) - .is_some() - && args.len() >= 2 - && is_every_args_simple(args) + .is_some() && args.len() >= 2 && is_every_args_simple(args) { Some(2) } else { -- cgit 1.4.1-3-g733a5 From aeb33986b1a5a509bd036e5ee105495b4e894797 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 3 Dec 2017 11:37:55 +0900 Subject: Add macros from the log crate to whitelist --- src/expr.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e82d23b21fd..e3b06b343fe 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1796,6 +1796,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt } const FORMAT_LIKE_WHITELIST: &[&str] = &[ + // From the Rust Standard Library. "eprint!", "eprintln!", "format!", @@ -1803,6 +1804,12 @@ const FORMAT_LIKE_WHITELIST: &[&str] = &[ "panic!", "println!", "unreachable!", + // From the `log` crate. + "debug!", + "error!", + "info!", + "panic!", + "warn!", ]; const WRITE_LIKE_WHITELIST: &[&str] = &["assert!", "write!", "writeln!"]; -- cgit 1.4.1-3-g733a5 From 026c716168963f0fa8739112f91cea3354534edc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 3 Dec 2017 11:38:16 +0900 Subject: Cargo fmt --- src/chains.rs | 3 +-- src/items.rs | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5aebc160750..642fb93c3ba 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -136,8 +136,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; debug!( "child_shapes {:?} {:?}", - first_child_shape, - other_child_shape + first_child_shape, other_child_shape ); let child_shape_iter = Some(first_child_shape) diff --git a/src/items.rs b/src/items.rs index b4fd5a340bc..a198d93ca76 100644 --- a/src/items.rs +++ b/src/items.rs @@ -48,9 +48,7 @@ impl Rewrite for ast::Local { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { debug!( "Local::rewrite {:?} {} {:?}", - self, - shape.width, - shape.indent + self, shape.width, shape.indent ); skip_out_of_file_lines_range!(context, self.span); @@ -1840,9 +1838,7 @@ fn rewrite_fn_base( debug!( "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", - one_line_budget, - multi_line_budget, - arg_indent + one_line_budget, multi_line_budget, arg_indent ); // Check if vertical layout was forced. -- cgit 1.4.1-3-g733a5 From ef4b3d9bfa9496f6b76ff1c6546c39f9c7c7331e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 4 Dec 2017 11:34:27 +0900 Subject: Inspect CFG_RELEASE_CHANNEL env var at compile time --- src/config.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index d7b5e8c6ee3..e0fae952d6b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,9 +24,9 @@ use Summary; macro_rules! is_nightly_channel { () => { - env::var("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(false) + option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false) } } -- cgit 1.4.1-3-g733a5 From 8cf99b1d9065df4d941fb7fd0c67337eeb71de56 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 4 Dec 2017 12:06:46 +0900 Subject: Factor out array_tactic --- src/expr.rs | 74 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e3b06b343fe..cbfb0f10512 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -436,38 +436,7 @@ pub fn rewrite_array( } } - let has_long_item = items - .iter() - .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - - let tactic = match context.config.indent_style() { - IndentStyle::Block => { - // FIXME wrong shape in one-line case - match shape.width.checked_sub(2 * bracket_size) { - Some(width) => { - let tactic = ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ); - definitive_tactic(&items, tactic, Separator::Comma, width) - } - None => DefinitiveListTactic::Vertical, - } - } - IndentStyle::Visual => { - if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic( - &items, - ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ), - Separator::Comma, - nested_shape.width, - ) - } else { - DefinitiveListTactic::Mixed - } - } - }; + let tactic = array_tactic(context, shape, nested_shape, exprs, &items, bracket_size); let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); let fmt = ListFormatting { @@ -518,6 +487,47 @@ pub fn rewrite_array( Some(result) } +fn array_tactic( + context: &RewriteContext, + shape: Shape, + nested_shape: Shape, + exprs: &[&T], + items: &[ListItem], + bracket_size: usize, +) -> DefinitiveListTactic { + let has_long_item = items + .iter() + .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); + + match context.config.indent_style() { + IndentStyle::Block => { + match shape.width.checked_sub(2 * bracket_size) { + Some(width) => { + let tactic = ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ); + definitive_tactic(items, tactic, Separator::Comma, width) + } + None => DefinitiveListTactic::Vertical, + } + } + IndentStyle::Visual => { + if has_long_item || items.iter().any(ListItem::is_multiline) { + definitive_tactic( + items, + ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ), + Separator::Comma, + nested_shape.width, + ) + } else { + DefinitiveListTactic::Mixed + } + } + } +} + fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| { -- cgit 1.4.1-3-g733a5 From 1684df6a0ac5b97a122a8223a8412e6c442bbbfe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 4 Dec 2017 12:07:06 +0900 Subject: Compress an array with simple items --- src/expr.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index cbfb0f10512..db256c3ba7d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -501,7 +501,7 @@ fn array_tactic( match context.config.indent_style() { IndentStyle::Block => { - match shape.width.checked_sub(2 * bracket_size) { + let tactic = match shape.width.checked_sub(2 * bracket_size) { Some(width) => { let tactic = ListTactic::LimitedHorizontalVertical( context.config.width_heuristics().array_width, @@ -509,6 +509,13 @@ fn array_tactic( definitive_tactic(items, tactic, Separator::Comma, width) } None => DefinitiveListTactic::Vertical, + }; + if tactic == DefinitiveListTactic::Vertical && !has_long_item + && is_every_args_simple(exprs) + { + DefinitiveListTactic::Mixed + } else { + tactic } } IndentStyle::Visual => { -- cgit 1.4.1-3-g733a5 From 65c90dc08c7b9565a1acf3292c1ddeb71876bcd2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 08:01:29 +0900 Subject: Do not pass files as arguments to rustfmt when dumping the default config --- src/bin/cargo-fmt.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index e6a86e04b9e..e04d772ba0e 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -134,7 +134,12 @@ fn format_crate( verbosity: Verbosity, strategy: &CargoFmtStrategy, ) -> Result { - let targets = get_targets(strategy)?; + let rustfmt_args = get_fmt_args(); + let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") { + HashSet::new() + } else { + get_targets(strategy)? + }; // Currently only bin and lib files get formatted let files: Vec<_> = targets @@ -147,7 +152,7 @@ fn format_crate( .map(|t| t.path) .collect(); - format_files(&files, &get_fmt_args(), verbosity) + format_files(&files, &rustfmt_args, verbosity) } fn get_fmt_args() -> Vec { -- cgit 1.4.1-3-g733a5 From b2b14d0f7ffd325a2e81ebd0378fb3d9719cc26b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 08:41:20 +0900 Subject: Foramt macro on types --- src/types.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index ef185a3f7d4..88f9dba5c3f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -23,6 +23,7 @@ use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_par use items::{format_generics_item_list, generics_shape_from_config}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; +use macros::{rewrite_macro, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, @@ -726,7 +727,9 @@ impl Rewrite for ast::Ty { } ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Some(String::from("!")), - ast::TyKind::Mac(..) => None, + ast::TyKind::Mac(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + } ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) .map(|it_str| format!("impl {}", it_str)), -- cgit 1.4.1-3-g733a5 From 0c1eb20575c6d95ac50a5e732130a15808364656 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 10:03:23 +0900 Subject: Fix indent of chain with small parent --- src/chains.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 642fb93c3ba..816ce60ad4d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -150,7 +150,11 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .collect::>>()?; // Total of all items excluding the last. - let extend_last_subexpr = last_line_extendable(&parent_rewrite) && rewrites.is_empty(); + let extend_last_subexpr = if is_small_parent { + rewrites.len() == 1 && last_line_extendable(&rewrites[0]) + } else { + rewrites.is_empty() && last_line_extendable(&parent_rewrite) + }; let almost_total = if extend_last_subexpr { last_line_width(&parent_rewrite) } else { -- cgit 1.4.1-3-g733a5 From 228578b9c7a3aced361e814dfd2dbabf4d131435 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 15:17:40 +0900 Subject: Add count_newlines() utility function --- src/comment.rs | 4 ++-- src/expr.rs | 8 ++------ src/lists.rs | 4 ++-- src/missed_spans.rs | 6 +++--- src/utils.rs | 5 +++++ src/visitor.rs | 6 +++--- 6 files changed, 17 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4b16199d826..ac7779d0b21 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -18,7 +18,7 @@ use config::Config; use rewrite::RewriteContext; use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; -use utils::{first_line_width, last_line_width}; +use utils::{count_newlines, first_line_width, last_line_width}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { @@ -296,7 +296,7 @@ fn rewrite_comment_inner( config: config, }; - let line_breaks = orig.trim_right().chars().filter(|&c| c == '\n').count(); + let line_breaks = count_newlines(orig.trim_right()); let lines = orig.lines() .enumerate() .map(|(i, mut line)| { diff --git a/src/expr.rs b/src/expr.rs index afa31983046..fe3dfca6270 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2712,12 +2712,8 @@ pub fn choose_rhs( } fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - fn count_line_breaks(src: &str) -> usize { - src.chars().filter(|&x| x == '\n').count() - } - - !next_line_rhs.contains('\n') - || count_line_breaks(orig_rhs) > count_line_breaks(next_line_rhs) + 1 + use utils::count_newlines; + !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } fn rewrite_expr_addrof( diff --git a/src/lists.rs b/src/lists.rs index f3e1c362dc1..dde8cb54b28 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -17,7 +17,7 @@ use comment::{find_comment_end, rewrite_comment, FindUncommented}; use config::{Config, IndentStyle}; use rewrite::RewriteContext; use shape::{Indent, Shape}; -use utils::{first_line_width, last_line_width, mk_sp, starts_with_newline}; +use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; /// Formatting tactic for lists. This will be cast down to a /// `DefinitiveListTactic` depending on the number and length of the items and @@ -651,7 +651,7 @@ where // From the end of the first line of comments to the next non-whitespace char. let test_snippet = &test_snippet[..first]; - if test_snippet.chars().filter(|c| c == &'\n').count() > 1 { + if count_newlines(test_snippet) > 1 { // There were multiple line breaks which got trimmed to nothing. new_lines = true; } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 101d49305ff..ffdc4e56e44 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -16,7 +16,7 @@ use syntax::codemap::{BytePos, Pos, Span}; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::WriteMode; use shape::{Indent, Shape}; -use utils::mk_sp; +use utils::{count_newlines, mk_sp}; use visitor::FmtVisitor; impl<'a> FmtVisitor<'a> { @@ -86,7 +86,7 @@ impl<'a> FmtVisitor<'a> { } fn push_vertical_spaces(&mut self, original: &str) { - let mut newline_count = original.chars().filter(|&c| c == '\n').count(); + let mut newline_count = count_newlines(original); let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; if newline_count > newline_upper_bound { @@ -171,7 +171,7 @@ impl<'a> FmtVisitor<'a> { let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count(); + let subslice_num_lines = count_newlines(subslice); if rewrite_next_comment && !self.config.file_lines().intersects_range( diff --git a/src/utils.rs b/src/utils.rs index d851dfda79d..7d3fcf73d56 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -262,6 +262,11 @@ pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { } } +#[inline] +pub fn count_newlines(input: &str) -> usize { + input.chars().filter(|&c| c == '\n').count() +} + #[inline] pub fn trim_newlines(input: &str) -> &str { match input.find(|c| c != '\n' && c != '\r') { diff --git a/src/visitor.rs b/src/visitor.rs index f278ec35d47..6db1999ee23 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -31,7 +31,7 @@ use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; -use utils::{self, contains_skip, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; +use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; fn is_use_item(item: &ast::Item) -> bool { match item.node { @@ -833,7 +833,7 @@ where // Extract comments between two attributes. let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); let snippet = context.snippet(span_between_attr); - if snippet.chars().filter(|c| *c == '\n').count() >= 2 || snippet.contains('/') { + if count_newlines(&snippet) >= 2 || snippet.contains('/') { break; } } @@ -886,7 +886,7 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { // Look at before and after comment and see if there are any empty lines. let comment_begin = comment.chars().position(|c| c == '/'); let len = comment_begin.unwrap_or_else(|| comment.len()); - let mlb = comment.chars().take(len).filter(|c| *c == '\n').count() > 1; + let mlb = count_newlines(&comment[..len]) > 1; let mla = if comment_begin.is_none() { mlb } else { -- cgit 1.4.1-3-g733a5 From d96a48c5174c2be11874e677d770b840bc424646 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 15:19:36 +0900 Subject: Change the type of argument of push_vertical_spaces() --- src/missed_spans.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index ffdc4e56e44..a66dcd7a7b0 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -78,15 +78,14 @@ impl<'a> FmtVisitor<'a> { let snippet = self.snippet(span); if snippet.trim().is_empty() { // Keep vertical spaces within range. - self.push_vertical_spaces(&snippet); + self.push_vertical_spaces(count_newlines(&snippet)); process_last_snippet(self, "", &snippet); } else { self.write_snippet(span, &process_last_snippet); } } - fn push_vertical_spaces(&mut self, original: &str) { - let mut newline_count = count_newlines(original); + fn push_vertical_spaces(&mut self, mut newline_count: usize) { let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; if newline_count > newline_upper_bound { -- cgit 1.4.1-3-g733a5 From 829d94940ebb07a49f5d841d2adc66947678ed5c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 16:25:33 +0900 Subject: Factor out process_comment() --- src/missed_spans.rs | 227 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 134 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index a66dcd7a7b0..e71e08a00b3 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -119,6 +119,85 @@ impl<'a> FmtVisitor<'a> { self.write_snippet_inner(big_snippet, big_diff, &snippet, span, process_last_snippet); } + fn process_comment( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + big_snippet: &str, + offset: usize, + big_diff: usize, + subslice: &str, + file_name: &str, + ) -> bool { + let last_char = big_snippet[..(offset + big_diff)] + .chars() + .rev() + .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) + .next(); + + let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); + + let subslice_num_lines = count_newlines(subslice); + let skip_this_range = !self.config.file_lines().intersects_range( + file_name, + status.cur_line, + status.cur_line + subslice_num_lines, + ); + + if status.rewrite_next_comment && skip_this_range { + status.rewrite_next_comment = false; + } + + if status.rewrite_next_comment { + if fix_indent { + if let Some('{') = last_char { + self.buffer.push_str("\n"); + } + self.buffer + .push_str(&self.block_indent.to_string(self.config)); + } else { + self.buffer.push_str(" "); + } + + let comment_width = ::std::cmp::min( + self.config.comment_width(), + self.config.max_width() - self.block_indent.width(), + ); + let comment_indent = Indent::from_width(self.config, self.buffer.cur_offset()); + let comment_shape = Shape::legacy(comment_width, comment_indent); + let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) + .unwrap_or_else(|| String::from(subslice)); + self.buffer.push_str(&comment_str); + + status.last_wspace = None; + status.line_start = offset + subslice.len(); + + if let Some('/') = subslice.chars().nth(1) { + // check that there are no contained block comments + if !subslice + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() >= 2 && &s[0..2] == "/*") + { + // Add a newline after line comments + self.buffer.push_str("\n"); + } + } else if status.line_start <= snippet.len() { + // For other comments add a newline if there isn't one at the end already + match snippet[status.line_start..].chars().next() { + Some('\n') | Some('\r') => (), + _ => self.buffer.push_str("\n"), + } + } + + status.cur_line += subslice_num_lines; + true + } else { + status.rewrite_next_comment = false; + false + } + } + fn write_snippet_inner( &mut self, big_snippet: &str, @@ -132,13 +211,9 @@ impl<'a> FmtVisitor<'a> { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. - let mut line_start = 0; - let mut last_wspace = None; - let mut rewrite_next_comment = true; - let char_pos = self.codemap.lookup_char_pos(span.lo()); let file_name = &char_pos.file.name; - let mut cur_line = char_pos.line; + let mut status = SnippetStatus::new(char_pos.line); fn replace_chars<'a>(string: &'a str) -> Cow<'a, str> { if string.contains(char::is_whitespace) { @@ -162,121 +237,87 @@ impl<'a> FmtVisitor<'a> { debug!("{:?}: {:?}", kind, subslice); if let CodeCharKind::Comment = kind { - let last_char = big_snippet[..(offset + big_diff)] - .chars() - .rev() - .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) - .next(); - - let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - - let subslice_num_lines = count_newlines(subslice); - - if rewrite_next_comment - && !self.config.file_lines().intersects_range( - file_name, - cur_line, - cur_line + subslice_num_lines, - ) { - rewrite_next_comment = false; - } - - if rewrite_next_comment { - if fix_indent { - if let Some('{') = last_char { - self.buffer.push_str("\n"); - } - self.buffer - .push_str(&self.block_indent.to_string(self.config)); - } else { - self.buffer.push_str(" "); - } - - let comment_width = ::std::cmp::min( - self.config.comment_width(), - self.config.max_width() - self.block_indent.width(), - ); - let comment_indent = Indent::from_width(self.config, self.buffer.cur_offset()); - - self.buffer.push_str(&rewrite_comment( - subslice, - false, - Shape::legacy(comment_width, comment_indent), - self.config, - ).unwrap()); - - last_wspace = None; - line_start = offset + subslice.len(); - - if let Some('/') = subslice.chars().nth(1) { - // check that there are no contained block comments - if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() >= 2 && &s[0..2] == "/*") - { - // Add a newline after line comments - self.buffer.push_str("\n"); - } - } else if line_start <= snippet.len() { - // For other comments add a newline if there isn't one at the end already - match snippet[line_start..].chars().next() { - Some('\n') | Some('\r') => (), - _ => self.buffer.push_str("\n"), - } - } - - cur_line += subslice_num_lines; + if self.process_comment( + &mut status, + snippet, + big_snippet, + offset, + big_diff, + subslice, + file_name, + ) { continue; - } else { - rewrite_next_comment = false; } } + // cur_line += newline_count; + // rewirte_next_comment = true; + for (mut i, c) in subslice.char_indices() { i += offset; if c == '\n' { - if !self.config.file_lines().contains_line(file_name, cur_line) { - last_wspace = None; + if !self.config + .file_lines() + .contains_line(file_name, status.cur_line) + { + status.last_wspace = None; } - if let Some(lw) = last_wspace { - self.buffer.push_str(&snippet[line_start..lw]); + if let Some(lw) = status.last_wspace { + self.buffer.push_str(&snippet[status.line_start..lw]); self.buffer.push_str("\n"); } else { - self.buffer.push_str(&snippet[line_start..i + 1]); + self.buffer.push_str(&snippet[status.line_start..i + 1]); } - cur_line += 1; - line_start = i + 1; - last_wspace = None; - rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + status.cur_line += 1; + status.line_start = i + 1; + status.last_wspace = None; + status.rewrite_next_comment = true; } else if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(i); + if status.last_wspace.is_none() { + status.last_wspace = Some(i); } } else if c == ';' { - if last_wspace.is_some() { - line_start = i; + if status.last_wspace.is_some() { + status.line_start = i; } - rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; - last_wspace = None; + status.rewrite_next_comment = true; + status.last_wspace = None; } else { - rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; - last_wspace = None; + status.rewrite_next_comment = true; + status.last_wspace = None; } } - let remaining = snippet[line_start..subslice.len() + offset].trim(); + let remaining = snippet[status.line_start..subslice.len() + offset].trim(); if !remaining.is_empty() { self.buffer.push_str(remaining); - line_start = subslice.len() + offset; - rewrite_next_comment = rewrite_next_comment || kind == CodeCharKind::Normal; + status.line_start = subslice.len() + offset; + status.rewrite_next_comment = true; } } - process_last_snippet(self, &snippet[line_start..], snippet); + process_last_snippet(self, &snippet[status.line_start..], snippet); + } +} + +struct SnippetStatus { + line_start: usize, + last_wspace: Option, + rewrite_next_comment: bool, + cur_line: usize, +} + +impl SnippetStatus { + fn new(cur_line: usize) -> Self { + SnippetStatus { + line_start: 0, + last_wspace: None, + rewrite_next_comment: true, + cur_line, + } } } -- cgit 1.4.1-3-g733a5 From 53616f63b13935df6c761a449bfa940d3146ef47 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 16:39:45 +0900 Subject: Keep blank lines around comments with range --- src/missed_spans.rs | 92 +++++++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index e71e08a00b3..b25f15b4880 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -250,54 +250,64 @@ impl<'a> FmtVisitor<'a> { } } - // cur_line += newline_count; - // rewirte_next_comment = true; - - for (mut i, c) in subslice.char_indices() { - i += offset; - - if c == '\n' { - if !self.config - .file_lines() - .contains_line(file_name, status.cur_line) - { + let newline_count = count_newlines(&subslice); + if subslice.trim().is_empty() && newline_count > 0 + && self.config.file_lines().intersects_range( + file_name, + status.cur_line, + status.cur_line + newline_count, + ) { + self.push_vertical_spaces(newline_count); + status.cur_line += newline_count; + status.rewrite_next_comment = true; + status.line_start = offset + newline_count; + } else { + for (mut i, c) in subslice.char_indices() { + i += offset; + + if c == '\n' { + if !self.config + .file_lines() + .contains_line(file_name, status.cur_line) + { + status.last_wspace = None; + } + + if let Some(lw) = status.last_wspace { + self.buffer.push_str(&snippet[status.line_start..lw]); + self.buffer.push_str("\n"); + } else { + self.buffer.push_str(&snippet[status.line_start..i + 1]); + } + + status.cur_line += 1; + status.line_start = i + 1; + status.last_wspace = None; + status.rewrite_next_comment = true; + } else if c.is_whitespace() { + if status.last_wspace.is_none() { + status.last_wspace = Some(i); + } + } else if c == ';' { + if status.last_wspace.is_some() { + status.line_start = i; + } + + status.rewrite_next_comment = true; status.last_wspace = None; - } - - if let Some(lw) = status.last_wspace { - self.buffer.push_str(&snippet[status.line_start..lw]); - self.buffer.push_str("\n"); } else { - self.buffer.push_str(&snippet[status.line_start..i + 1]); - } - - status.cur_line += 1; - status.line_start = i + 1; - status.last_wspace = None; - status.rewrite_next_comment = true; - } else if c.is_whitespace() { - if status.last_wspace.is_none() { - status.last_wspace = Some(i); - } - } else if c == ';' { - if status.last_wspace.is_some() { - status.line_start = i; + status.rewrite_next_comment = true; + status.last_wspace = None; } + } + let remaining = snippet[status.line_start..subslice.len() + offset].trim(); + if !remaining.is_empty() { + self.buffer.push_str(remaining); + status.line_start = subslice.len() + offset; status.rewrite_next_comment = true; - status.last_wspace = None; - } else { - status.rewrite_next_comment = true; - status.last_wspace = None; } } - - let remaining = snippet[status.line_start..subslice.len() + offset].trim(); - if !remaining.is_empty() { - self.buffer.push_str(remaining); - status.line_start = subslice.len() + offset; - status.rewrite_next_comment = true; - } } process_last_snippet(self, &snippet[status.line_start..], snippet); -- cgit 1.4.1-3-g733a5 From 5632a7c0758167014ddac5283720f235cb08f184 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 17:14:30 +0900 Subject: Process blank lines if only they're within file lines range --- src/missed_spans.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b25f15b4880..ba99bdd92c0 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -13,6 +13,7 @@ use std::iter::repeat; use syntax::codemap::{BytePos, Pos, Span}; +use codemap::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::WriteMode; use shape::{Indent, Shape}; @@ -76,7 +77,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = end; let span = mk_sp(start, end); let snippet = self.snippet(span); - if snippet.trim().is_empty() { + if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { // Keep vertical spaces within range. self.push_vertical_spaces(count_newlines(&snippet)); process_last_snippet(self, "", &snippet); -- cgit 1.4.1-3-g733a5 From 1d1305eef8d8f90c0ae4ab9ab79eba2b918c9c2f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 17:15:42 +0900 Subject: Take into account a trailing newline in buffer --- src/missed_spans.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index ba99bdd92c0..94bfc034db6 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -87,6 +87,10 @@ impl<'a> FmtVisitor<'a> { } fn push_vertical_spaces(&mut self, mut newline_count: usize) { + // The buffer already has a trailing newline. + if self.buffer.cur_offset() == 0 { + newline_count = newline_count.checked_sub(1).unwrap_or(0); + } let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; if newline_count > newline_upper_bound { -- cgit 1.4.1-3-g733a5 From 454c85e359ee8de9bf1736a5ecae3d9abd7526c2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 17:15:58 +0900 Subject: Cargo fmt --- src/closures.rs | 1 - src/filemap.rs | 1 - 2 files changed, 2 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 1ea7982ba66..73ef2064295 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -31,7 +31,6 @@ use utils::{last_line_width, left_most_sub_expr, stmt_expr}; // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. - pub fn rewrite_closure( capture: ast::CaptureBy, fn_decl: &ast::FnDecl, diff --git a/src/filemap.rs b/src/filemap.rs index 8bed486e7b9..c46b477abaa 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - // TODO: add tests use std::fs::{self, File}; -- cgit 1.4.1-3-g733a5 From 04449c6622eb039ca71a74972dfdc6e28339c6cc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Dec 2017 17:38:27 +0900 Subject: Handle cases when bound changed from the default --- src/missed_spans.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 94bfc034db6..a3cad47063e 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -88,11 +88,9 @@ impl<'a> FmtVisitor<'a> { fn push_vertical_spaces(&mut self, mut newline_count: usize) { // The buffer already has a trailing newline. - if self.buffer.cur_offset() == 0 { - newline_count = newline_count.checked_sub(1).unwrap_or(0); - } - let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; - let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; + let offset = if self.buffer.cur_offset() == 0 { 0 } else { 1 }; + let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; + let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; if newline_count > newline_upper_bound { newline_count = newline_upper_bound; } else if newline_count < newline_lower_bound { -- cgit 1.4.1-3-g733a5 From eb42956e84cd284abc7ee4c28c562daf3d408293 Mon Sep 17 00:00:00 2001 From: David Alber Date: Tue, 5 Dec 2017 16:49:48 -0800 Subject: Adding `print!` specially-formatted `format!`-like macros list This commit corrects what appears to be an accidental inclusion of `panic!` twice in the list resulting from the union of ffbe52e and aeb3398. --- src/expr.rs | 2 +- tests/source/macros.rs | 4 ++++ tests/target/macros.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index db256c3ba7d..a94f51bb811 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1818,7 +1818,7 @@ const FORMAT_LIKE_WHITELIST: &[&str] = &[ "eprintln!", "format!", "format_args!", - "panic!", + "print!", "println!", "unreachable!", // From the `log` crate. diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 8f4bd75fe2b..f1df8b9b876 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -234,6 +234,10 @@ fn special_case_macros() { let r = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); let s = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + let q = print!("{}", 1); + let r = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + let q = println!("{}", 1); let r = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); let s = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 47dad382e0a..a242235833c 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -411,6 +411,41 @@ fn special_case_macros() { 26 ); + let q = print!("{}", 1); + let r = print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + let q = println!("{}", 1); let r = println!( "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", -- cgit 1.4.1-3-g733a5 From b8448f62239e3b9b3e291d40ec0ef5cc35aa0077 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Dec 2017 12:41:04 +0900 Subject: Use package name instead of target name for --package filter --- src/bin/cargo-fmt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index e04d772ba0e..63d7d2c3353 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -290,8 +290,8 @@ fn get_targets_with_hitlist( let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); for package in metadata.packages { - for target in package.targets { - if workspace_hitlist.remove(&target.name) { + if workspace_hitlist.remove(&package.name) { + for target in package.targets { targets.insert(Target::from_target(&target)); } } -- cgit 1.4.1-3-g733a5 From 98860ab89066c69e9ebefbbe914ca30b6f198d16 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Dec 2017 22:48:48 +0900 Subject: Add SnippetProvider --- src/visitor.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 6db1999ee23..510bf6e8f5c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::rc::Rc; use std::cmp; +use std::mem; use strings::string_buffer::StringBuffer; use syntax::{ast, visit}; @@ -47,6 +49,32 @@ fn is_extern_crate(item: &ast::Item) -> bool { } } +/// Creates a string slice corresponding to the specified span. +pub struct SnippetProvider { + /// A pointer to the content of the file we are formatting. + big_snippet: *const Rc, + /// A position of the start of `big_snippet`, used as an offset. + start_pos: usize, +} + +impl SnippetProvider { + pub fn span_to_snippet(&self, span: Span) -> Option<&str> { + let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; + let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; + unsafe { Some(&(*self.big_snippet)[start_index..end_index]) } + } + + pub fn from_codemap(codemap: &CodeMap, span: Span) -> Self { + let filemap = codemap.lookup_char_pos(span.lo()).file; + let big_snippet = unsafe { mem::transmute(&filemap.src) }; + let start_pos = filemap.start_pos.to_usize(); + SnippetProvider { + big_snippet, + start_pos, + } + } +} + pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, -- cgit 1.4.1-3-g733a5 From 09287625626925b30ea0689ef9d051f3a8889149 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Dec 2017 22:49:49 +0900 Subject: Use SnippetProvider in FmtVisitor and RewriteContext --- src/rewrite.rs | 6 ++++-- src/visitor.rs | 23 +++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/rewrite.rs b/src/rewrite.rs index 1307f6731ff..5e4d00518a5 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -15,6 +15,7 @@ use syntax::parse::ParseSess; use config::{Config, IndentStyle}; use shape::Shape; +use visitor::SnippetProvider; pub trait Rewrite { /// Rewrite self into shape. @@ -34,11 +35,12 @@ pub struct RewriteContext<'a> { pub is_if_else_block: bool, // When rewriting chain, veto going multi line except the last element pub force_one_line_chain: bool, + pub snippet_provider: &'a SnippetProvider, } impl<'a> RewriteContext<'a> { - pub fn snippet(&self, span: Span) -> String { - self.codemap.span_to_snippet(span).unwrap() + pub fn snippet(&self, span: Span) -> &str { + self.snippet_provider.span_to_snippet(span).unwrap() } /// Return true if we should use block indent style for rewriting function call. diff --git a/src/visitor.rs b/src/visitor.rs index 510bf6e8f5c..1a4d55a779b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -84,6 +84,7 @@ pub struct FmtVisitor<'a> { pub block_indent: Indent, pub config: &'a Config, pub is_if_else_block: bool, + pub snippet_provier: SnippetProvider, } impl<'a> FmtVisitor<'a> { @@ -538,25 +539,18 @@ impl<'a> FmtVisitor<'a> { block_indent: Indent::empty(), config: config, is_if_else_block: false, + snippet_provier: SnippetProvider::from_codemap(parse_session.codemap(), span), } } - pub fn opt_snippet(&self, span: Span) -> Option { - self.codemap.span_to_snippet(span).ok() + pub fn opt_snippet<'b: 'a>(&'a self, span: Span) -> Option<&'b str> { + self.snippet_provier + .span_to_snippet(span) + .map(|s| unsafe { mem::transmute::<&'a str, &'b str>(s) }) } - pub fn snippet(&self, span: Span) -> String { - match self.codemap.span_to_snippet(span) { - Ok(s) => s, - Err(_) => { - eprintln!( - "Couldn't make snippet for span {:?}->{:?}", - self.codemap.lookup_char_pos(span.lo()), - self.codemap.lookup_char_pos(span.hi()) - ); - "".to_owned() - } - } + pub fn snippet<'b: 'a>(&'a self, span: Span) -> &'b str { + self.opt_snippet(span).unwrap() } // Returns true if we should skip the following item. @@ -753,6 +747,7 @@ impl<'a> FmtVisitor<'a> { use_block: false, is_if_else_block: false, force_one_line_chain: false, + snippet_provider: &self.snippet_provier, } } } -- cgit 1.4.1-3-g733a5 From 69a15b2eee671f76f934f1a2b8901c82c2eeee77 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Dec 2017 22:51:52 +0900 Subject: Update FmtVisitor::from_codemap() --- src/expr.rs | 2 +- src/items.rs | 6 ++++-- src/lib.rs | 2 +- src/visitor.rs | 6 +++++- 4 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 42de975e127..35a441012d8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -629,7 +629,7 @@ pub fn rewrite_block_with_visitor( return rw; } - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, block.span); visitor.block_indent = shape.indent; visitor.is_if_else_block = context.is_if_else_block; match block.rules { diff --git a/src/items.rs b/src/items.rs index c1345bceb12..8fa1a784c0e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -657,7 +657,8 @@ pub fn format_impl( let open_pos = snippet.find_uncommented("{")? + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); + let mut visitor = + FmtVisitor::from_codemap(context.parse_session, context.config, item.span); visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); @@ -1055,7 +1056,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let open_pos = snippet.find_uncommented("{")? + 1; if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config); + let mut visitor = + FmtVisitor::from_codemap(context.parse_session, context.config, item.span); visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); diff --git a/src/lib.rs b/src/lib.rs index 0b54c71a6eb..72e01a4b1aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -317,7 +317,7 @@ where if config.verbose() { println!("Formatting {}", path_str); } - let mut visitor = FmtVisitor::from_codemap(parse_session, config); + let mut visitor = FmtVisitor::from_codemap(parse_session, config, module.inner); let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; // Format inner attributes if available. if !krate.attrs.is_empty() && path == main_file { diff --git a/src/visitor.rs b/src/visitor.rs index 1a4d55a779b..fc83ccef3a4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -530,7 +530,11 @@ impl<'a> FmtVisitor<'a> { self.last_pos = source!(self, span).hi(); } - pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> { + pub fn from_codemap( + parse_session: &'a ParseSess, + config: &'a Config, + span: Span, + ) -> FmtVisitor<'a> { FmtVisitor { parse_session: parse_session, codemap: parse_session.codemap(), -- cgit 1.4.1-3-g733a5 From db0a72318aa2a579d1ee33caa4923e16327ccb4b Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Wed, 6 Dec 2017 16:22:09 +0000 Subject: Fix config warnings leaking into stdout --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 1ece6171d9b..4c6390c7627 100644 --- a/src/config.rs +++ b/src/config.rs @@ -361,7 +361,7 @@ macro_rules! create_config { self.$i.1 = true; self.$i.2 = val; } else { - println!("Warning: can't set `{} = {:?}`, unstable features are only \ + eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ available in nightly channel.", stringify!($i), val); } } -- cgit 1.4.1-3-g733a5 From 7c4a84751f8b08068a9a6c4188c88a19f1174dd8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Dec 2017 22:52:43 +0900 Subject: Convert '&str' into 'String' whenever necessary --- src/comment.rs | 2 +- src/expr.rs | 20 ++++++++++++-------- src/items.rs | 7 ++++--- src/macros.rs | 10 +++++----- src/patterns.rs | 2 +- src/visitor.rs | 22 +++++++++++++--------- 6 files changed, 36 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 5903323f2f4..62ebd8aaeab 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -918,7 +918,7 @@ pub fn recover_comment_removed( let snippet = context.snippet(span); if snippet != new && changed_comment_content(&snippet, &new) { // We missed some comments. Keep the original text. - Some(snippet) + Some(snippet.into()) } else { Some(new) } diff --git a/src/expr.rs b/src/expr.rs index 35a441012d8..8f107888cea 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -58,7 +58,7 @@ pub fn format_expr( skip_out_of_file_lines_range!(context, expr.span); if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span())); + return Some(context.snippet(expr.span()).into()); } let expr_rw = match expr.node { @@ -168,7 +168,7 @@ pub fn format_expr( ast::ExprKind::Mac(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( - context.snippet(expr.span), + context.snippet(expr.span).into(), context.config.max_width(), shape, ) @@ -274,7 +274,7 @@ pub fn format_expr( // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - Some(context.snippet(expr.span)) + Some(context.snippet(expr.span).into()) } ast::ExprKind::Catch(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { @@ -1308,7 +1308,7 @@ fn rewrite_match( Some(format!("match {} {{}}", cond_str)) } else { // Empty match with comments or inner attributes? We are not going to bother, sorry ;) - Some(context.snippet(span)) + Some(context.snippet(span).into()) } } else { Some(format!( @@ -1767,7 +1767,11 @@ fn can_extend_match_arm_body(body: &ast::Expr) -> bool { pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), - _ => wrap_str(context.snippet(l.span), context.config.max_width(), shape), + _ => wrap_str( + context.snippet(l.span).into(), + context.config.max_width(), + shape, + ), } } @@ -1798,7 +1802,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ); return wrap_str(indented_string_lit, context.config.max_width(), shape); } else { - return wrap_str(string_lit, context.config.max_width(), shape); + return wrap_str(string_lit.into(), context.config.max_width(), shape); } } @@ -2530,7 +2534,7 @@ pub fn rewrite_field( prefix_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - return Some(context.snippet(field.span())); + return Some(context.snippet(field.span()).into()); } let name = &field.ident.node.to_string(); if field.is_shorthand { @@ -2738,7 +2742,7 @@ fn rewrite_assignment( ) -> Option { let operator_str = match op { Some(op) => context.snippet(op.span), - None => "=".to_owned(), + None => "=", }; // 1 = space between lhs and operator. diff --git a/src/items.rs b/src/items.rs index 8fa1a784c0e..9d525f9ba9d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -382,7 +382,7 @@ impl<'a> FmtVisitor<'a> { format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span))) + .or_else(|| Some(self.snippet(e.span).into())) } None => stmt.rewrite(&self.get_context(), self.shape()), } @@ -526,7 +526,7 @@ impl<'a> FmtVisitor<'a> { if contains_skip(&field.node.attrs) { let lo = field.node.attrs[0].span.lo(); let span = mk_sp(lo, field.span.hi()); - return Some(self.snippet(span)); + return Some(self.snippet(span).into()); } let context = self.get_context(); @@ -1429,7 +1429,8 @@ pub fn rewrite_struct_field( lhs_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - return Some(context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi()))); + let snippet = context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi())); + return Some(snippet.into()); } let type_annotation_spacing = type_annotation_spacing(context.config); diff --git a/src/macros.rs b/src/macros.rs index f53acbc024a..a6de1ded863 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -162,7 +162,7 @@ pub fn rewrite_macro( loop { match parse_macro_arg(&mut parser) { Some(arg) => arg_vec.push(arg), - None => return Some(context.snippet(mac.span)), + None => return Some(context.snippet(mac.span).into()), } match parser.token { @@ -182,13 +182,13 @@ pub fn rewrite_macro( break; } } - None => return Some(context.snippet(mac.span)), + None => return Some(context.snippet(mac.span).into()), } } } - return Some(context.snippet(mac.span)); + return Some(context.snippet(mac.span).into()); } - _ => return Some(context.snippet(mac.span)), + _ => return Some(context.snippet(mac.span).into()), } parser.bump(); @@ -271,7 +271,7 @@ pub fn rewrite_macro( } MacroStyle::Braces => { // Skip macro invocations with braces, for now. - indent_macro_snippet(context, &context.snippet(mac.span), shape.indent) + indent_macro_snippet(context, context.snippet(mac.span), shape.indent) } } } diff --git a/src/patterns.rs b/src/patterns.rs index 90a47d785f0..2e4c01b7aaa 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -122,7 +122,7 @@ impl Rewrite for Pat { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } // FIXME(#819) format pattern macros. - PatKind::Mac(..) => Some(context.snippet(self.span)), + PatKind::Mac(..) => Some(context.snippet(self.span).into()), } } } diff --git a/src/visitor.rs b/src/visitor.rs index fc83ccef3a4..f7ae9ec1034 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -424,7 +424,7 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(item.span, rewrite); } ast::ItemKind::GlobalAsm(..) => { - let snippet = Some(self.snippet(item.span)); + let snippet = Some(self.snippet(item.span).into()); self.push_rewrite(item.span, snippet); } ast::ItemKind::MacroDef(..) => { @@ -525,8 +525,12 @@ impl<'a> FmtVisitor<'a> { pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo()); - let result = rewrite.unwrap_or_else(|| self.snippet(span)); - self.buffer.push_str(&result); + if let Some(ref s) = rewrite { + self.buffer.push_str(s); + } else { + let snippet = self.snippet(span); + self.buffer.push_str(snippet); + } self.last_pos = source!(self, span).hi(); } @@ -826,10 +830,10 @@ impl Rewrite for ast::Attribute { .unwrap_or(0), ..shape }; - rewrite_comment(&snippet, false, doc_shape, context.config) + rewrite_comment(snippet, false, doc_shape, context.config) } else { - if contains_comment(&snippet) { - return Some(snippet); + if contains_comment(snippet) { + return Some(snippet.into()); } // 1 = `[` let shape = shape.offset_left(prefix.len() + 1)?; @@ -980,7 +984,7 @@ impl<'a> Rewrite for [ast::Attribute] { } // Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. -fn format_derive(context: &RewriteContext, derive_args: &[String], shape: Shape) -> Option { +fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option { let mut result = String::with_capacity(128); result.push_str("#[derive("); // 11 = `#[derive()]` @@ -1022,7 +1026,7 @@ fn is_derive(attr: &ast::Attribute) -> bool { } /// Returns the arguments of `#[derive(...)]`. -fn get_derive_args(context: &RewriteContext, attr: &ast::Attribute) -> Option> { +fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { attr.meta().and_then(|meta_item| match meta_item.node { ast::MetaItemKind::List(ref args) if meta_item.name.as_str() == "derive" => { // Every argument of `derive` should be `NestedMetaItemKind::Literal`. @@ -1041,7 +1045,7 @@ pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Optio assert!(is_extern_crate(item)); let new_str = context.snippet(item.span); Some(if contains_comment(&new_str) { - new_str + new_str.into() } else { let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) -- cgit 1.4.1-3-g733a5 From 1d9a10e00e6b1f76624ec14471706525613df411 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Dec 2017 13:51:30 +0900 Subject: Use explicit lifetime to get rid of unsafe code at least this is why we use Rust --- src/lib.rs | 11 ++++++++--- src/rewrite.rs | 2 +- src/visitor.rs | 35 +++++++++++++++-------------------- 3 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 72e01a4b1aa..f6902db969c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; use utils::use_colored_tty; -use visitor::FmtVisitor; +use visitor::{FmtVisitor, SnippetProvider}; pub use self::summary::Summary; @@ -317,8 +317,13 @@ where if config.verbose() { println!("Formatting {}", path_str); } - let mut visitor = FmtVisitor::from_codemap(parse_session, config, module.inner); - let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; + let filemap = parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); // Format inner attributes if available. if !krate.attrs.is_empty() && path == main_file { visitor.skip_empty_lines(filemap.end_pos); diff --git a/src/rewrite.rs b/src/rewrite.rs index 5e4d00518a5..708e31d86dd 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -35,7 +35,7 @@ pub struct RewriteContext<'a> { pub is_if_else_block: bool, // When rewriting chain, veto going multi line except the last element pub force_one_line_chain: bool, - pub snippet_provider: &'a SnippetProvider, + pub snippet_provider: &'a SnippetProvider<'a>, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index f7ae9ec1034..b1859418086 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -10,7 +10,6 @@ use std::rc::Rc; use std::cmp; -use std::mem; use strings::string_buffer::StringBuffer; use syntax::{ast, visit}; @@ -50,24 +49,22 @@ fn is_extern_crate(item: &ast::Item) -> bool { } /// Creates a string slice corresponding to the specified span. -pub struct SnippetProvider { +pub struct SnippetProvider<'a> { /// A pointer to the content of the file we are formatting. - big_snippet: *const Rc, + big_snippet: &'a Rc, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, } -impl SnippetProvider { - pub fn span_to_snippet(&self, span: Span) -> Option<&str> { +impl<'b, 'a: 'b> SnippetProvider<'a> { + pub fn span_to_snippet(&'b self, span: Span) -> Option<&'a str> { let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; - unsafe { Some(&(*self.big_snippet)[start_index..end_index]) } + Some(&self.big_snippet[start_index..end_index]) } - pub fn from_codemap(codemap: &CodeMap, span: Span) -> Self { - let filemap = codemap.lookup_char_pos(span.lo()).file; - let big_snippet = unsafe { mem::transmute(&filemap.src) }; - let start_pos = filemap.start_pos.to_usize(); + pub fn new(start_pos: BytePos, big_snippet: &'a Rc) -> Self { + let start_pos = start_pos.to_usize(); SnippetProvider { big_snippet, start_pos, @@ -84,10 +81,10 @@ pub struct FmtVisitor<'a> { pub block_indent: Indent, pub config: &'a Config, pub is_if_else_block: bool, - pub snippet_provier: SnippetProvider, + pub snippet_provider: &'a SnippetProvider<'a>, } -impl<'a> FmtVisitor<'a> { +impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn shape(&self) -> Shape { Shape::indented(self.block_indent, self.config) } @@ -537,7 +534,7 @@ impl<'a> FmtVisitor<'a> { pub fn from_codemap( parse_session: &'a ParseSess, config: &'a Config, - span: Span, + snippet_provider: &'a SnippetProvider, ) -> FmtVisitor<'a> { FmtVisitor { parse_session: parse_session, @@ -547,17 +544,15 @@ impl<'a> FmtVisitor<'a> { block_indent: Indent::empty(), config: config, is_if_else_block: false, - snippet_provier: SnippetProvider::from_codemap(parse_session.codemap(), span), + snippet_provider: snippet_provider, } } - pub fn opt_snippet<'b: 'a>(&'a self, span: Span) -> Option<&'b str> { - self.snippet_provier - .span_to_snippet(span) - .map(|s| unsafe { mem::transmute::<&'a str, &'b str>(s) }) + pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { + self.snippet_provider.span_to_snippet(span) } - pub fn snippet<'b: 'a>(&'a self, span: Span) -> &'b str { + pub fn snippet(&'b self, span: Span) -> &'a str { self.opt_snippet(span).unwrap() } @@ -755,7 +750,7 @@ impl<'a> FmtVisitor<'a> { use_block: false, is_if_else_block: false, force_one_line_chain: false, - snippet_provider: &self.snippet_provier, + snippet_provider: &self.snippet_provider, } } } -- cgit 1.4.1-3-g733a5 From c0eb8c3212d2ebee66ca1b846c2b8a230e8586e5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Dec 2017 13:53:10 +0900 Subject: Add FmtVisitor::from_context() --- src/expr.rs | 2 +- src/items.rs | 6 ++---- src/visitor.rs | 4 ++++ 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8f107888cea..e014e506b05 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -629,7 +629,7 @@ pub fn rewrite_block_with_visitor( return rw; } - let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, block.span); + let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.is_if_else_block = context.is_if_else_block; match block.rules { diff --git a/src/items.rs b/src/items.rs index 9d525f9ba9d..95638a90fc0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -657,8 +657,7 @@ pub fn format_impl( let open_pos = snippet.find_uncommented("{")? + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = - FmtVisitor::from_codemap(context.parse_session, context.config, item.span); + let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); @@ -1056,8 +1055,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let open_pos = snippet.find_uncommented("{")? + 1; if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = - FmtVisitor::from_codemap(context.parse_session, context.config, item.span); + let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = offset.block_only().block_indent(context.config); visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); diff --git a/src/visitor.rs b/src/visitor.rs index b1859418086..f2b4750460f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -531,6 +531,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = source!(self, span).hi(); } + pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { + FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) + } + pub fn from_codemap( parse_session: &'a ParseSess, config: &'a Config, -- cgit 1.4.1-3-g733a5 From 0f561a1447533e531a59ab5bfd6d4db467f90f2a Mon Sep 17 00:00:00 2001 From: David Alber Date: Wed, 6 Dec 2017 22:23:02 -0800 Subject: Moving `panic!` into the list of macros from the Standard Library --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a94f51bb811..feed584dba6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1820,12 +1820,12 @@ const FORMAT_LIKE_WHITELIST: &[&str] = &[ "format_args!", "print!", "println!", + "panic!", "unreachable!", // From the `log` crate. "debug!", "error!", "info!", - "panic!", "warn!", ]; -- cgit 1.4.1-3-g733a5 From d6d8d86e9443a01f9afb7d61eeffb3e5891be92a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Dec 2017 17:32:19 +0900 Subject: Replace &Rc with &str --- src/visitor.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index f2b4750460f..bc4be2131b7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::rc::Rc; use std::cmp; use strings::string_buffer::StringBuffer; @@ -51,7 +50,7 @@ fn is_extern_crate(item: &ast::Item) -> bool { /// Creates a string slice corresponding to the specified span. pub struct SnippetProvider<'a> { /// A pointer to the content of the file we are formatting. - big_snippet: &'a Rc, + big_snippet: &'a str, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, } @@ -63,7 +62,7 @@ impl<'b, 'a: 'b> SnippetProvider<'a> { Some(&self.big_snippet[start_index..end_index]) } - pub fn new(start_pos: BytePos, big_snippet: &'a Rc) -> Self { + pub fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { let start_pos = start_pos.to_usize(); SnippetProvider { big_snippet, -- cgit 1.4.1-3-g733a5 From c776443981d08ccad32ca536554a86a3a46c89b2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 8 Dec 2017 13:07:28 +0900 Subject: Remove unused lifetime --- src/visitor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index bc4be2131b7..758253a2eda 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -55,8 +55,8 @@ pub struct SnippetProvider<'a> { start_pos: usize, } -impl<'b, 'a: 'b> SnippetProvider<'a> { - pub fn span_to_snippet(&'b self, span: Span) -> Option<&'a str> { +impl<'a> SnippetProvider<'a> { + pub fn span_to_snippet(&self, span: Span) -> Option<&str> { let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; Some(&self.big_snippet[start_index..end_index]) -- cgit 1.4.1-3-g733a5 From 3ebe0543626111475a2658c544b6d582d199d147 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 8 Dec 2017 13:07:42 +0900 Subject: Replace into() on &str with to_owned() --- src/bin/rustfmt-format-diff.rs | 10 +++++----- src/comment.rs | 2 +- src/expr.rs | 22 +++++++++++----------- src/imports.rs | 4 ++-- src/items.rs | 6 +++--- src/macros.rs | 8 ++++---- src/patterns.rs | 2 +- src/rustfmt_diff.rs | 26 +++++++++++++------------- src/visitor.rs | 6 +++--- 9 files changed, 43 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt-format-diff.rs b/src/bin/rustfmt-format-diff.rs index 0df8d37807b..c42fbb6f7cf 100644 --- a/src/bin/rustfmt-format-diff.rs +++ b/src/bin/rustfmt-format-diff.rs @@ -120,7 +120,7 @@ fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { let filter = matches .opt_str("f") - .unwrap_or_else(|| DEFAULT_PATTERN.into()); + .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); let skip_prefix = matches .opt_str("p") @@ -247,19 +247,19 @@ fn scan_simple_git_diff() { &ranges, &[ Range { - file: "src/ir/item.rs".into(), + file: "src/ir/item.rs".to_owned(), range: [148, 158], }, Range { - file: "src/ir/item.rs".into(), + file: "src/ir/item.rs".to_owned(), range: [160, 170], }, Range { - file: "src/ir/traversal.rs".into(), + file: "src/ir/traversal.rs".to_owned(), range: [9, 16], }, Range { - file: "src/ir/traversal.rs".into(), + file: "src/ir/traversal.rs".to_owned(), range: [35, 43], } ] diff --git a/src/comment.rs b/src/comment.rs index 62ebd8aaeab..8cd491b6ee3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -918,7 +918,7 @@ pub fn recover_comment_removed( let snippet = context.snippet(span); if snippet != new && changed_comment_content(&snippet, &new) { // We missed some comments. Keep the original text. - Some(snippet.into()) + Some(snippet.to_owned()) } else { Some(new) } diff --git a/src/expr.rs b/src/expr.rs index e014e506b05..9fa1d794457 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -58,7 +58,7 @@ pub fn format_expr( skip_out_of_file_lines_range!(context, expr.span); if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span()).into()); + return Some(context.snippet(expr.span()).to_owned()); } let expr_rw = match expr.node { @@ -168,7 +168,7 @@ pub fn format_expr( ast::ExprKind::Mac(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( - context.snippet(expr.span).into(), + context.snippet(expr.span).to_owned(), context.config.max_width(), shape, ) @@ -241,7 +241,7 @@ pub fn format_expr( } else if needs_space_before_range(context, lhs) { format!(" {}", delim) } else { - delim.into() + delim.to_owned() }; rewrite_pair( &*lhs, @@ -256,7 +256,7 @@ pub fn format_expr( let sp_delim = if context.config.spaces_around_ranges() { format!("{} ", delim) } else { - delim.into() + delim.to_owned() }; rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) } @@ -264,17 +264,17 @@ pub fn format_expr( let sp_delim = if context.config.spaces_around_ranges() { format!(" {}", delim) } else { - delim.into() + delim.to_owned() }; rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) } - (None, None) => Some(delim.into()), + (None, None) => Some(delim.to_owned()), } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - Some(context.snippet(expr.span).into()) + Some(context.snippet(expr.span).to_owned()) } ast::ExprKind::Catch(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { @@ -1308,7 +1308,7 @@ fn rewrite_match( Some(format!("match {} {{}}", cond_str)) } else { // Empty match with comments or inner attributes? We are not going to bother, sorry ;) - Some(context.snippet(span).into()) + Some(context.snippet(span).to_owned()) } } else { Some(format!( @@ -1768,7 +1768,7 @@ pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), _ => wrap_str( - context.snippet(l.span).into(), + context.snippet(l.span).to_owned(), context.config.max_width(), shape, ), @@ -1802,7 +1802,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ); return wrap_str(indented_string_lit, context.config.max_width(), shape); } else { - return wrap_str(string_lit.into(), context.config.max_width(), shape); + return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); } } @@ -2534,7 +2534,7 @@ pub fn rewrite_field( prefix_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - return Some(context.snippet(field.span()).into()); + return Some(context.snippet(field.span()).to_owned()); } let name = &field.ident.node.to_string(); if field.is_shorthand { diff --git a/src/imports.rs b/src/imports.rs index f38e41eca89..9fbf814919a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -148,7 +148,7 @@ impl Rewrite for ast::UseTree { let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; Some(format!("{}::*", path_str)) } else { - Some("*".into()) + Some("*".to_owned()) } } ast::UseTreeKind::Simple(ident) => { @@ -184,7 +184,7 @@ fn rewrite_import( .and_then(|shape| match tree.kind { // If we have an empty nested group with no attributes, we erase it ast::UseTreeKind::Nested(ref items) if items.is_empty() && attrs.is_empty() => { - Some("".into()) + Some("".to_owned()) } _ => tree.rewrite(context, shape), }); diff --git a/src/items.rs b/src/items.rs index 95638a90fc0..b3647f26f53 100644 --- a/src/items.rs +++ b/src/items.rs @@ -382,7 +382,7 @@ impl<'a> FmtVisitor<'a> { format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span).into())) + .or_else(|| Some(self.snippet(e.span).to_owned())) } None => stmt.rewrite(&self.get_context(), self.shape()), } @@ -526,7 +526,7 @@ impl<'a> FmtVisitor<'a> { if contains_skip(&field.node.attrs) { let lo = field.node.attrs[0].span.lo(); let span = mk_sp(lo, field.span.hi()); - return Some(self.snippet(span).into()); + return Some(self.snippet(span).to_owned()); } let context = self.get_context(); @@ -1428,7 +1428,7 @@ pub fn rewrite_struct_field( ) -> Option { if contains_skip(&field.attrs) { let snippet = context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi())); - return Some(snippet.into()); + return Some(snippet.to_owned()); } let type_annotation_spacing = type_annotation_spacing(context.config); diff --git a/src/macros.rs b/src/macros.rs index a6de1ded863..3c5db3c977a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -162,7 +162,7 @@ pub fn rewrite_macro( loop { match parse_macro_arg(&mut parser) { Some(arg) => arg_vec.push(arg), - None => return Some(context.snippet(mac.span).into()), + None => return Some(context.snippet(mac.span).to_owned()), } match parser.token { @@ -182,13 +182,13 @@ pub fn rewrite_macro( break; } } - None => return Some(context.snippet(mac.span).into()), + None => return Some(context.snippet(mac.span).to_owned()), } } } - return Some(context.snippet(mac.span).into()); + return Some(context.snippet(mac.span).to_owned()); } - _ => return Some(context.snippet(mac.span).into()), + _ => return Some(context.snippet(mac.span).to_owned()), } parser.bump(); diff --git a/src/patterns.rs b/src/patterns.rs index 2e4c01b7aaa..74ae537e534 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -122,7 +122,7 @@ impl Rewrite for Pat { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } // FIXME(#819) format pattern macros. - PatKind::Mac(..) => Some(context.snippet(self.span).into()), + PatKind::Mac(..) => Some(context.snippet(self.span).to_owned()), } } } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c2dac6c0416..69633568755 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -180,10 +180,10 @@ mod test { Mismatch { line_number: 2, lines: vec![ - Context("two".into()), - Resulting("three".into()), - Expected("trois".into()), - Context("four".into()), + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), ], }, ] @@ -201,18 +201,18 @@ mod test { Mismatch { line_number: 2, lines: vec![ - Context("two".into()), - Resulting("three".into()), - Expected("trois".into()), - Context("four".into()), + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), ], }, Mismatch { line_number: 5, lines: vec![ - Resulting("five".into()), - Expected("cinq".into()), - Context("six".into()), + Resulting("five".to_owned()), + Expected("cinq".to_owned()), + Context("six".to_owned()), ], }, ] @@ -229,7 +229,7 @@ mod test { vec![ Mismatch { line_number: 3, - lines: vec![Resulting("three".into()), Expected("trois".into())], + lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], }, ] ); @@ -245,7 +245,7 @@ mod test { vec![ Mismatch { line_number: 5, - lines: vec![Context("five".into()), Expected("".into())], + lines: vec![Context("five".to_owned()), Expected("".to_owned())], }, ] ); diff --git a/src/visitor.rs b/src/visitor.rs index 758253a2eda..2ba0b744a58 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -420,7 +420,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(item.span, rewrite); } ast::ItemKind::GlobalAsm(..) => { - let snippet = Some(self.snippet(item.span).into()); + let snippet = Some(self.snippet(item.span).to_owned()); self.push_rewrite(item.span, snippet); } ast::ItemKind::MacroDef(..) => { @@ -831,7 +831,7 @@ impl Rewrite for ast::Attribute { rewrite_comment(snippet, false, doc_shape, context.config) } else { if contains_comment(snippet) { - return Some(snippet.into()); + return Some(snippet.to_owned()); } // 1 = `[` let shape = shape.offset_left(prefix.len() + 1)?; @@ -1043,7 +1043,7 @@ pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Optio assert!(is_extern_crate(item)); let new_str = context.snippet(item.span); Some(if contains_comment(&new_str) { - new_str.into() + new_str.to_owned() } else { let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) -- cgit 1.4.1-3-g733a5 From 5e6bb3edb0a627dd2104a5314232a15ad342b7d5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 8 Dec 2017 16:59:04 +0900 Subject: Keep track of line number in visitor --- src/imports.rs | 2 +- src/items.rs | 23 +++++++++++------------ src/lib.rs | 5 +++++ src/missed_spans.rs | 36 +++++++++++++++++------------------- src/visitor.rs | 37 +++++++++++++++++++++++-------------- 5 files changed, 57 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9fbf814919a..1d38328d45c 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -285,7 +285,7 @@ impl<'a> FmtVisitor<'a> { } Some(ref s) => { self.format_missing_with_indent(source!(self, span).lo()); - self.buffer.push_str(s); + self.push_str(s); self.last_pos = source!(self, span).hi(); } None => { diff --git a/src/items.rs b/src/items.rs index b3647f26f53..44c03ebf95b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -240,12 +240,12 @@ impl<'a> FnSig<'a> { impl<'a> FmtVisitor<'a> { fn format_item(&mut self, item: Item) { - self.buffer.push_str(&item.abi); + self.push_str(&item.abi); let snippet = self.snippet(item.span); let brace_pos = snippet.find_uncommented("{").unwrap(); - self.buffer.push_str("{"); + self.push_str("{"); if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { // FIXME: this skips comments between the extern keyword and the opening // brace. @@ -255,9 +255,8 @@ impl<'a> FmtVisitor<'a> { if item.body.is_empty() { self.format_missing_no_indent(item.span.hi() - BytePos(1)); self.block_indent = self.block_indent.block_unindent(self.config); - - self.buffer - .push_str(&self.block_indent.to_string(self.config)); + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); } else { for item in &item.body { self.format_body_element(item); @@ -268,7 +267,7 @@ impl<'a> FmtVisitor<'a> { } } - self.buffer.push_str("}"); + self.push_str("}"); self.last_pos = item.span.hi(); } @@ -423,7 +422,7 @@ impl<'a> FmtVisitor<'a> { span: Span, ) { let enum_header = format_header("enum ", ident, vis); - self.buffer.push_str(&enum_header); + self.push_str(&enum_header); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); @@ -441,23 +440,23 @@ impl<'a> FmtVisitor<'a> { mk_sp(span.lo(), body_start), last_line_width(&enum_header), ).unwrap(); - self.buffer.push_str(&generics_str); + self.push_str(&generics_str); self.last_pos = body_start; self.block_indent = self.block_indent.block_indent(self.config); let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); match variant_list { - Some(ref body_str) => self.buffer.push_str(body_str), + Some(ref body_str) => self.push_str(body_str), None => self.format_missing_no_indent(span.hi() - BytePos(1)), } self.block_indent = self.block_indent.block_unindent(self.config); if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - self.buffer - .push_str(&self.block_indent.to_string(self.config)); + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); } - self.buffer.push_str("}"); + self.push_str("}"); self.last_pos = span.hi(); } diff --git a/src/lib.rs b/src/lib.rs index f6902db969c..3acba4a4cf1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -338,6 +338,11 @@ where visitor.format_separate_mod(module, &*filemap); }; + assert_eq!( + visitor.line_number, + ::utils::count_newlines(&format!("{}", visitor.buffer)) + ); + has_diff |= match after_file(path_str, &mut visitor.buffer) { Ok(result) => result, Err(e) => { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index a3cad47063e..2ed1f50182b 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -28,27 +28,25 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| { - this.buffer.push_str(last_snippet) - }) + self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) } pub fn format_missing_with_indent(&mut self, end: BytePos) { let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { - this.buffer.push_str(last_snippet.trim_right()); + this.push_str(last_snippet.trim_right()); if last_snippet == snippet && !this.output_at_start() { // No new lines in the snippet. - this.buffer.push_str("\n"); + this.push_str("\n"); } let indent = this.block_indent.to_string(config); - this.buffer.push_str(&indent); + this.push_str(&indent); }) } pub fn format_missing_no_indent(&mut self, end: BytePos) { self.format_missing_inner(end, |this, last_snippet, _| { - this.buffer.push_str(last_snippet.trim_right()); + this.push_str(last_snippet.trim_right()); }) } @@ -97,7 +95,7 @@ impl<'a> FmtVisitor<'a> { newline_count = newline_lower_bound; } let blank_lines: String = repeat('\n').take(newline_count).collect(); - self.buffer.push_str(&blank_lines); + self.push_str(&blank_lines); } fn write_snippet(&mut self, span: Span, process_last_snippet: F) @@ -154,12 +152,12 @@ impl<'a> FmtVisitor<'a> { if status.rewrite_next_comment { if fix_indent { if let Some('{') = last_char { - self.buffer.push_str("\n"); + self.push_str("\n"); } - self.buffer - .push_str(&self.block_indent.to_string(self.config)); + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); } else { - self.buffer.push_str(" "); + self.push_str(" "); } let comment_width = ::std::cmp::min( @@ -170,7 +168,7 @@ impl<'a> FmtVisitor<'a> { let comment_shape = Shape::legacy(comment_width, comment_indent); let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) .unwrap_or_else(|| String::from(subslice)); - self.buffer.push_str(&comment_str); + self.push_str(&comment_str); status.last_wspace = None; status.line_start = offset + subslice.len(); @@ -183,13 +181,13 @@ impl<'a> FmtVisitor<'a> { .any(|s| s.len() >= 2 && &s[0..2] == "/*") { // Add a newline after line comments - self.buffer.push_str("\n"); + self.push_str("\n"); } } else if status.line_start <= snippet.len() { // For other comments add a newline if there isn't one at the end already match snippet[status.line_start..].chars().next() { Some('\n') | Some('\r') => (), - _ => self.buffer.push_str("\n"), + _ => self.push_str("\n"), } } @@ -277,10 +275,10 @@ impl<'a> FmtVisitor<'a> { } if let Some(lw) = status.last_wspace { - self.buffer.push_str(&snippet[status.line_start..lw]); - self.buffer.push_str("\n"); + self.push_str(&snippet[status.line_start..lw]); + self.push_str("\n"); } else { - self.buffer.push_str(&snippet[status.line_start..i + 1]); + self.push_str(&snippet[status.line_start..i + 1]); } status.cur_line += 1; @@ -306,7 +304,7 @@ impl<'a> FmtVisitor<'a> { let remaining = snippet[status.line_start..subslice.len() + offset].trim(); if !remaining.is_empty() { - self.buffer.push_str(remaining); + self.push_str(remaining); status.line_start = subslice.len() + offset; status.rewrite_next_comment = true; } diff --git a/src/visitor.rs b/src/visitor.rs index 2ba0b744a58..dc11dcd8938 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -81,6 +81,7 @@ pub struct FmtVisitor<'a> { pub config: &'a Config, pub is_if_else_block: bool, pub snippet_provider: &'a SnippetProvider<'a>, + pub line_number: usize, } impl<'b, 'a: 'b> FmtVisitor<'a> { @@ -132,7 +133,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = self.last_pos + brace_compensation; self.block_indent = self.block_indent.block_indent(self.config); - self.buffer.push_str("{"); + self.push_str("{"); if self.config.remove_blank_lines_at_start_or_end_of_block() { if let Some(first_stmt) = b.stmts.first() { @@ -195,7 +196,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if !b.stmts.is_empty() { if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { if utils::semicolon_for_expr(&self.get_context(), expr) { - self.buffer.push_str(";"); + self.push_str(";"); } } } @@ -255,7 +256,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.config.tab_spaces() }; self.buffer.truncate(total_len - chars_too_many); - self.buffer.push_str("}"); + self.push_str("}"); self.block_indent = self.block_indent.block_unindent(self.config); } @@ -288,7 +289,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if let Some(fn_str) = rewrite { self.format_missing_with_indent(source!(self, s).lo()); - self.buffer.push_str(&fn_str); + self.push_str(&fn_str); if let Some(c) = fn_str.chars().last() { if c == '}' { self.last_pos = source!(self, block.span).hi(); @@ -519,13 +520,18 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(mac.span, rewrite); } + pub fn push_str(&mut self, s: &str) { + self.line_number += count_newlines(s); + self.buffer.push_str(s); + } + pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo()); if let Some(ref s) = rewrite { - self.buffer.push_str(s); + self.push_str(s); } else { let snippet = self.snippet(span); - self.buffer.push_str(snippet); + self.push_str(snippet); } self.last_pos = source!(self, span).hi(); } @@ -548,6 +554,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { config: config, is_if_else_block: false, snippet_provider: snippet_provider, + line_number: 0, } } @@ -692,15 +699,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let is_internal = !(inner_span.lo().0 == 0 && inner_span.hi().0 == 0) && local_file_name == self.codemap.span_to_filename(inner_span); - self.buffer.push_str(&*utils::format_visibility(vis)); - self.buffer.push_str("mod "); - self.buffer.push_str(&ident.to_string()); + self.push_str(&*utils::format_visibility(vis)); + self.push_str("mod "); + self.push_str(&ident.to_string()); if is_internal { match self.config.brace_style() { - BraceStyle::AlwaysNextLine => self.buffer - .push_str(&format!("\n{}{{", self.block_indent.to_string(self.config))), - _ => self.buffer.push_str(" {"), + BraceStyle::AlwaysNextLine => { + let sep_str = format!("\n{}{{", self.block_indent.to_string(self.config)); + self.push_str(&sep_str); + } + _ => self.push_str(" {"), } // Hackery to account for the closing }. let mod_lo = self.codemap.span_after(source!(self, s), "{"); @@ -708,7 +717,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { - self.buffer.push_str("}"); + self.push_str("}"); } else { self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); @@ -719,7 +728,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } self.last_pos = source!(self, m.inner).hi(); } else { - self.buffer.push_str(";"); + self.push_str(";"); self.last_pos = source!(self, s).hi(); } } -- cgit 1.4.1-3-g733a5 From 821d04b2a4a11ae000aed4c30b1d838fe276890f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 8 Dec 2017 17:46:43 +0900 Subject: Do not report errors on skipped items or statements --- src/lib.rs | 39 ++++++++++++++++++++++++++++----------- src/spanned.rs | 2 ++ src/visitor.rs | 45 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3acba4a4cf1..229e25bb65b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -300,7 +300,7 @@ fn format_ast( mut after_file: F, ) -> Result<(FileMap, bool), io::Error> where - F: FnMut(&str, &mut StringBuffer) -> Result, + F: FnMut(&str, &mut StringBuffer, &[(usize, usize)]) -> Result, { let mut result = FileMap::new(); // diff mode: check if any files are differing @@ -343,7 +343,7 @@ where ::utils::count_newlines(&format!("{}", visitor.buffer)) ); - has_diff |= match after_file(path_str, &mut visitor.buffer) { + has_diff |= match after_file(path_str, &mut visitor.buffer, &visitor.skipped_range) { Ok(result) => result, Err(e) => { // Create a new error with path_str to help users see which files failed @@ -358,10 +358,24 @@ where Ok((result, has_diff)) } +/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`. +fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { + skipped_range + .iter() + .any(|&(lo, hi)| lo <= line_number && line_number <= hi) +} + // Formatting done on a char by char or line by line basis. // FIXME(#209) warn on bad license // FIXME(#20) other stuff for parity with make tidy -fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &mut FormatReport) { +fn format_lines( + text: &mut StringBuffer, + name: &str, + skipped_range: &[(usize, usize)], + config: &Config, + report: &mut FormatReport, +) { + println!("skipped_range: {:?}", skipped_range); // Iterate over the chars in the file map. let mut trims = vec![]; let mut last_wspace: Option = None; @@ -403,6 +417,7 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m // Check for any line width errors we couldn't correct. let report_error_on_line_overflow = config.error_on_line_overflow() + && !is_skipped_line(cur_line, skipped_range) && (config.error_on_line_overflow_comments() || !is_comment); if report_error_on_line_overflow && line_len > config.max_width() { errors.push(FormattingError { @@ -448,12 +463,14 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m } for &(l, _, _, ref b) in &trims { - errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - is_comment: false, - line_buffer: b.clone(), - }); + if !is_skipped_line(l, skipped_range) { + errors.push(FormattingError { + line: l, + kind: ErrorKind::TrailingWhitespace, + is_comment: false, + line_buffer: b.clone(), + }); + } } report.file_error_map.insert(name.to_owned(), errors); @@ -546,12 +563,12 @@ pub fn format_input( &mut parse_session, &main_file, config, - |file_name, file| { + |file_name, file, skipped_range| { // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. filemap::append_newline(file); - format_lines(file, file_name, config, &mut report); + format_lines(file, file_name, skipped_range, config, &mut report); if let Some(ref mut out) = out { return filemap::write_file(file, file_name, out, config); diff --git a/src/spanned.rs b/src/spanned.rs index 6978f2812e6..7181512273e 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -54,6 +54,8 @@ implement_spanned!(ast::Field); implement_spanned!(ast::ForeignItem); implement_spanned!(ast::Item); implement_spanned!(ast::Local); +implement_spanned!(ast::TraitItem); +implement_spanned!(ast::ImplItem); impl Spanned for ast::Stmt { fn span(&self) -> Span { diff --git a/src/visitor.rs b/src/visitor.rs index dc11dcd8938..ac5501cae4c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -82,6 +82,7 @@ pub struct FmtVisitor<'a> { pub is_if_else_block: bool, pub snippet_provider: &'a SnippetProvider<'a>, pub line_number: usize, + pub skipped_range: Vec<(usize, usize)>, } impl<'b, 'a: 'b> FmtVisitor<'a> { @@ -101,13 +102,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_item(item); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - let rewrite = stmt.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(stmt.span(), rewrite) + if contains_skip(get_attrs_from_stmt(stmt)) { + self.push_skipped_with_span(stmt.span()); + } else { + let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(stmt.span(), rewrite) + } } ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, ref attrs) = **mac; if self.visit_attrs(attrs, ast::AttrStyle::Outer) { - self.push_rewrite(stmt.span(), None); + self.push_skipped_with_span(stmt.span()); } else { self.visit_mac(mac, None, MacroPosition::Statement); } @@ -321,7 +326,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Module is inline, in this case we treat modules like any // other item. if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_rewrite(item.span, None); + self.push_skipped_with_span(item.span()); return; } } else if contains_skip(&item.attrs) { @@ -349,7 +354,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } _ => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_rewrite(item.span, None); + self.push_skipped_with_span(item.span()); return; } } @@ -436,7 +441,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, ti.span); if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { - self.push_rewrite(ti.span, None); + self.push_skipped_with_span(ti.span()); return; } @@ -478,7 +483,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, ii.span); if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_rewrite(ii.span, None); + self.push_skipped_with_span(ii.span()); return; } @@ -525,8 +530,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.buffer.push_str(s); } - pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { - self.format_missing_with_indent(source!(self, span).lo()); + fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { if let Some(ref s) = rewrite { self.push_str(s); } else { @@ -536,6 +540,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = source!(self, span).hi(); } + pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { + self.format_missing_with_indent(source!(self, span).lo()); + self.push_rewrite_inner(span, rewrite); + } + + pub fn push_skipped_with_span(&mut self, span: Span) { + self.format_missing_with_indent(source!(self, span).lo()); + let lo = self.line_number + 1; + self.push_rewrite_inner(span, None); + let hi = self.line_number + 1; + self.skipped_range.push((lo, hi)); + } + pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) } @@ -555,6 +572,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { is_if_else_block: false, snippet_provider: snippet_provider, line_number: 0, + skipped_range: vec![], } } @@ -1058,3 +1076,12 @@ pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Optio String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) }) } + +fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { + match stmt.node { + ast::StmtKind::Local(ref local) => &local.attrs, + ast::StmtKind::Item(ref item) => &item.attrs, + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, + ast::StmtKind::Mac(ref mac) => &mac.2, + } +} -- cgit 1.4.1-3-g733a5 From adc3b12ad496a014cd1b3cdbeabafbcd3f206796 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 8 Dec 2017 17:48:49 +0900 Subject: Remove println! debug :( --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 229e25bb65b..18e802b1d2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -375,7 +375,6 @@ fn format_lines( config: &Config, report: &mut FormatReport, ) { - println!("skipped_range: {:?}", skipped_range); // Iterate over the chars in the file map. let mut trims = vec![]; let mut last_wspace: Option = None; -- cgit 1.4.1-3-g733a5 From 234c7da87194a6a5934469d135c15f9d1127ed6c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 9 Dec 2017 16:43:22 +0900 Subject: Handle nested imports --- src/imports.rs | 153 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9fbf814919a..31021f3f0c9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -53,8 +53,8 @@ fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Orderi match (&a.kind, &b.kind) { (&Simple(ident_a), &Simple(ident_b)) => { - let name_a = &*a.prefix.segments.last().unwrap().identifier.name.as_str(); - let name_b = &*b.prefix.segments.last().unwrap().identifier.name.as_str(); + let name_a = &*path_to_imported_ident(&a.prefix).name.as_str(); + let name_b = &*path_to_imported_ident(&b.prefix).name.as_str(); let name_ordering = if name_a == "self" { if name_b == "self" { Ordering::Equal @@ -121,18 +121,15 @@ fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> // imports into a list import. fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { - let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" - && path.segments.len() > 1 - { + if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { let path = &ast::Path { span: path.span, segments: path.segments[..path.segments.len() - 1].to_owned(), }; - rewrite_path(context, PathContext::Import, None, path, shape)? + rewrite_path(context, PathContext::Import, None, path, shape) } else { - rewrite_path(context, PathContext::Import, None, path, shape)? - }; - Some(path_str) + rewrite_path(context, PathContext::Import, None, path, shape) + } } impl Rewrite for ast::UseTree { @@ -155,10 +152,16 @@ impl Rewrite for ast::UseTree { let ident_str = ident.to_string(); // 4 = " as ".len() - let prefix_shape = shape.sub_width(ident_str.len() + 4)?; - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; + let is_same_name_bind = path_to_imported_ident(&self.prefix) == ident; + let prefix_shape = if is_same_name_bind { + shape + } else { + shape.sub_width(ident_str.len() + 4)? + }; + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) + .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); - if self.prefix.segments.last().unwrap().identifier == ident { + if is_same_name_bind { Some(path_str) } else { Some(format!("{} as {}", path_str, ident_str)) @@ -168,6 +171,21 @@ impl Rewrite for ast::UseTree { } } +fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool { + attrs.is_empty() && is_unused_import_inner(tree) +} + +fn is_unused_import_inner(tree: &ast::UseTree) -> bool { + match tree.kind { + ast::UseTreeKind::Nested(ref items) => match items.len() { + 0 => true, + 1 => is_unused_import_inner(&items[0].0), + _ => false, + }, + _ => false, + } +} + // Rewrite `use foo;` WITHOUT attributes. fn rewrite_import( context: &RewriteContext, @@ -181,12 +199,13 @@ fn rewrite_import( let rw = shape .offset_left(vis.len() + 4) .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| match tree.kind { + .and_then(|shape| { // If we have an empty nested group with no attributes, we erase it - ast::UseTreeKind::Nested(ref items) if items.is_empty() && attrs.is_empty() => { + if is_unused_import(tree, attrs) { Some("".to_owned()) + } else { + tree.rewrite(context, shape) } - _ => tree.rewrite(context, shape), }); match rw { Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), @@ -296,48 +315,45 @@ impl<'a> FmtVisitor<'a> { } } -fn rewrite_nested_use_tree_single(path_str: String, tree: &ast::UseTree) -> String { - if let ast::UseTreeKind::Simple(rename) = tree.kind { - let ident = tree.prefix.segments.last().unwrap().identifier; - let mut item_str = ident.name.to_string(); - if item_str == "self" { - item_str = "".to_owned(); - } +fn rewrite_nested_use_tree_single( + context: &RewriteContext, + path_str: &str, + tree: &ast::UseTree, + shape: Shape, +) -> Option { + match tree.kind { + ast::UseTreeKind::Simple(rename) => { + let ident = path_to_imported_ident(&tree.prefix); + let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; + if item_str == "self" { + item_str = "".to_owned(); + } - let path_item_str = if path_str.is_empty() { - if item_str.is_empty() { - "self".to_owned() + let path_item_str = if path_str.is_empty() { + if item_str.is_empty() { + "self".to_owned() + } else { + item_str + } + } else if item_str.is_empty() { + path_str.to_owned() } else { - item_str - } - } else if item_str.is_empty() { - path_str - } else { - format!("{}::{}", path_str, item_str) - }; + format!("{}::{}", path_str, item_str) + }; - if ident == rename { - path_item_str - } else { - format!("{} as {}", path_item_str, rename) + Some(if ident == rename { + path_item_str + } else { + format!("{} as {}", path_item_str, rename) + }) } - } else { - unimplemented!("`use_nested_groups` is not yet fully supported"); - } -} - -fn rewrite_nested_use_tree_item(tree: &&ast::UseTree) -> Option { - Some(if let ast::UseTreeKind::Simple(rename) = tree.kind { - let ident = tree.prefix.segments.last().unwrap().identifier; - - if ident == rename { - ident.name.to_string() - } else { - format!("{} as {}", ident.name.to_string(), rename) + ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { + // 2 = "::" + let nested_shape = shape.offset_left(path_str.len() + 2)?; + tree.rewrite(context, nested_shape) + .map(|item| format!("{}::{}", path_str, item)) } - } else { - unimplemented!("`use_nested_groups` is not yet fully supported"); - }) + } } #[derive(Eq, PartialEq)] @@ -426,11 +442,13 @@ fn rewrite_nested_use_tree( match trees.len() { 0 => { + let shape = shape.offset_left(path_str.len() + 3)?; return rewrite_path(context, PathContext::Import, None, path, shape) .map(|path_str| format!("{}::{{}}", path_str)); } - // TODO: fix this - 1 => return Some(rewrite_nested_use_tree_single(path_str, &trees[0].0)), + 1 => { + return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape); + } _ => (), } @@ -442,6 +460,16 @@ fn rewrite_nested_use_tree( // 2 = "{}" let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); + let nested_indent = match context.config.imports_indent() { + IndentStyle::Block => shape.indent.block_indent(context.config), + // 1 = `{` + IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, + }; + + let nested_shape = match context.config.imports_indent() { + IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?, + IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), + }; let mut items = { // Dummy value, see explanation below. @@ -453,7 +481,7 @@ fn rewrite_nested_use_tree( ",", |tree| tree.span.lo(), |tree| tree.span.hi(), - rewrite_nested_use_tree_item, + |tree| tree.rewrite(context, nested_shape), context.codemap.span_after(span, "{"), span.hi(), false, @@ -483,17 +511,6 @@ fn rewrite_nested_use_tree( remaining_width, ); - let nested_indent = match context.config.imports_indent() { - IndentStyle::Block => shape.indent.block_indent(context.config), - // 1 = `{` - IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, - }; - - let nested_shape = match context.config.imports_indent() { - IndentStyle::Block => Shape::indented(nested_indent, context.config), - IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), - }; - let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; @@ -541,3 +558,7 @@ fn move_self_to_front(items: &mut Vec) -> bool { None => false, } } + +fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { + path.segments.last().unwrap().identifier +} -- cgit 1.4.1-3-g733a5 From 5624175574990ba448557473ccf3ae04c15835b1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 00:22:00 +0900 Subject: Format macro in pattern position --- src/macros.rs | 1 + src/patterns.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 3c5db3c977a..71be3b65224 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -50,6 +50,7 @@ pub enum MacroPosition { Item, Statement, Expression, + Pat, } impl MacroStyle { diff --git a/src/patterns.rs b/src/patterns.rs index 74ae537e534..700fbd0da21 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -19,6 +19,7 @@ use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_una wrap_struct_field, PairParts}; use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic}; +use macros::{rewrite_macro, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use types::{rewrite_path, PathContext}; @@ -121,8 +122,7 @@ impl Rewrite for Pat { PatKind::Struct(ref path, ref fields, ellipsis) => { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } - // FIXME(#819) format pattern macros. - PatKind::Mac(..) => Some(context.snippet(self.span).to_owned()), + PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), } } } -- cgit 1.4.1-3-g733a5 From 7e2c3cb8572fb8b057db97c72c5b8369e6a95f60 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 6 Dec 2017 18:07:19 -0500 Subject: unstable_features without CFG_RELEASE_CHANNEL Per discussion in #2228 https://github.com/rust-lang-nursery/rustfmt/pull/2228#issuecomment-348893294 https://github.com/rust-lang-nursery/rustfmt/pull/2228#issuecomment-349799548 Inline comment should explain the reasoning. --- src/config.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 4c6390c7627..6dc1056b5af 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,11 +21,21 @@ use file_lines::FileLines; use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; use Summary; +/// Check if we're in a nightly build. +/// +/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap +/// to "stable", "beta", or "nightly" depending on what toolchain is being built. +/// If we are being built as part of the stable or beta toolchains, we want +/// to disable unstable configuration options. +/// +/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), +/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the +/// nightly compiler when installed from crates.io, default to nightly mode. macro_rules! is_nightly_channel { () => { option_env!("CFG_RELEASE_CHANNEL") .map(|c| c == "nightly") - .unwrap_or(false) + .unwrap_or(true) } } -- cgit 1.4.1-3-g733a5 From 5871967312dffd7df20c692ffe233719ac41b10c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 21:27:28 +0900 Subject: Verify whether adding block is safe in rewrite_closure_with_block() Also ensure that the expression is nested to avoid false-positive. --- src/closures.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 73ef2064295..3a80c7adc93 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -118,6 +118,12 @@ fn rewrite_closure_with_block( context: &RewriteContext, shape: Shape, ) -> Option { + let left_most = left_most_sub_expr(body); + let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most); + if veto_block { + return None; + } + let block = ast::Block { stmts: vec![ ast::Stmt { @@ -142,9 +148,6 @@ fn rewrite_closure_expr( shape: Shape, ) -> Option { let mut rewrite = expr.rewrite(context, shape); - if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) { - rewrite = and_one_line(rewrite); - } rewrite = rewrite.and_then(|rw| { if context.config.force_multiline_blocks() && rw.contains('\n') { None -- cgit 1.4.1-3-g733a5 From 812fc4ca560261c76c9b988be8c2aa9242c50431 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 21:30:12 +0900 Subject: Remove and_one_line() --- src/closures.rs | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 3a80c7adc93..bf110bf8002 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -348,7 +348,3 @@ fn is_block_closure_forced(expr: &ast::Expr) -> bool { _ => false, } } - -fn and_one_line(x: Option) -> Option { - x.and_then(|x| if x.contains('\n') { None } else { Some(x) }) -} -- cgit 1.4.1-3-g733a5 From bd6bef8cfa851728a300f77066de3542ccea9362 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 21:49:59 +0900 Subject: Move macro check to is_block_closure_forced() --- src/closures.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index bf110bf8002..05e121560f9 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -81,7 +81,7 @@ fn try_rewrite_without_block( ) -> Option { let expr = get_inner_expr(expr, prefix, context); - if is_block_closure_forced(expr) { + if is_block_closure_forced(context, expr) { rewrite_closure_with_block(expr, prefix, context, shape) } else { rewrite_closure_expr(expr, prefix, context, body_shape) @@ -107,7 +107,7 @@ fn get_inner_expr<'a>( // Figure out if a block is necessary. fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { - is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro + is_unsafe_block(block) || block.stmts.len() > 1 || block_contains_comment(block, context.codemap) || prefix.contains('\n') } @@ -272,15 +272,11 @@ pub fn rewrite_last_closure( if prefix.contains('\n') { return None; } - // If we are inside macro, we do not want to add or remove block from closure body. - if context.inside_macro { - return expr.rewrite(context, shape); - } let body_shape = shape.offset_left(extra_offset)?; // We force to use block for the body of the closure for certain kinds of expressions. - if is_block_closure_forced(body) { + if is_block_closure_forced(context, body) { return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( |body_str| { // If the expression can fit in a single line, we need not force block closure. @@ -332,7 +328,16 @@ where .count() > 1 } -fn is_block_closure_forced(expr: &ast::Expr) -> bool { +fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { + // If we are inside macro, we do not want to add or remove block from closure body. + if context.inside_macro { + false + } else { + is_block_closure_forced_inner(expr) + } +} + +fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) @@ -344,7 +349,7 @@ fn is_block_closure_forced(expr: &ast::Expr) -> bool { | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr), + | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr), _ => false, } } -- cgit 1.4.1-3-g733a5 From 42726906f7e1d08ce7b3ef78cf3cf2150a8cb1be Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 21:52:23 +0900 Subject: Allow struct to be multi-lined in closure's body without block --- src/closures.rs | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 05e121560f9..f169a3f4d22 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -147,15 +147,37 @@ fn rewrite_closure_expr( context: &RewriteContext, shape: Shape, ) -> Option { - let mut rewrite = expr.rewrite(context, shape); - rewrite = rewrite.and_then(|rw| { - if context.config.force_multiline_blocks() && rw.contains('\n') { - None - } else { - Some(rw) + fn allow_multi_line(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Catch(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::Struct(..) => true, + + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), + + _ => false, } - }); - rewrite.map(|rw| format!("{} {}", prefix, rw)) + } + + // When rewriting closure's body without block, we require it to fit in a single line + // unless it is a block-like expression or we are inside macro call. + let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro) + || context.config.force_multiline_blocks(); + expr.rewrite(context, shape) + .and_then(|rw| { + if veto_multiline && rw.contains('\n') { + None + } else { + Some(rw) + } + }) + .map(|rw| format!("{} {}", prefix, rw)) } // Rewrite closure whose body is block. @@ -341,7 +363,6 @@ fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) - | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | ast::ExprKind::ForLoop(..) => true, -- cgit 1.4.1-3-g733a5 From 90383d7426c2a71bd7b6b904f81a185dc553d128 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 21:53:01 +0900 Subject: Do not set inside_macro flag when converting try!() to '?' This will keep rustfmt idempotent when using 'use_try_shorthand' config option. --- src/macros.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 3c5db3c977a..731ebd5adfc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -118,6 +118,7 @@ pub fn rewrite_macro( context.inside_macro = true; if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { + context.inside_macro = false; return expr.rewrite(context, shape); } } -- cgit 1.4.1-3-g733a5 From e3d2f2c2b1a33265375fde45e5152c9250f81b19 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 21:54:26 +0900 Subject: Cargo fmt --- src/chains.rs | 10 ++++++---- src/expr.rs | 7 ++++--- src/items.rs | 20 ++++++++++++-------- 3 files changed, 22 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 816ce60ad4d..7512ef72e27 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -419,10 +419,12 @@ fn rewrite_chain_subexpr( context: &RewriteContext, shape: Shape, ) -> Option { - let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width { - Some(expr_str) - } else { - None + let rewrite_element = |expr_str: String| { + if expr_str.len() <= shape.width { + Some(expr_str) + } else { + None + } }; match expr.node { diff --git a/src/expr.rs b/src/expr.rs index 259ac0007ed..ed4adffb9f5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2316,12 +2316,13 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> .offset_left(paren_overhead) .and_then(|s| s.sub_width(paren_overhead))?; - let paren_wrapper = - |s: &str| if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { + let paren_wrapper = |s: &str| { + if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { format!("( {} )", s) } else { format!("({})", s) - }; + } + }; let subexpr_str = subexpr.rewrite(context, sub_shape)?; debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); diff --git a/src/items.rs b/src/items.rs index b3647f26f53..496c66971d7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -482,10 +482,12 @@ impl<'a> FmtVisitor<'a> { enum_def.variants.iter(), "}", ",", - |f| if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo() - } else { - f.span.lo() + |f| { + if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo() + } else { + f.span.lo() + } }, |f| f.span.hi(), |f| self.format_variant(f, one_line_width), @@ -2549,10 +2551,12 @@ fn rewrite_where_clause_rfc_style( }; let preds_str = write_list(&items.collect::>(), &fmt)?; - let comment_separator = |comment: &str, shape: Shape| if comment.is_empty() { - String::new() - } else { - format!("\n{}", shape.indent.to_string(context.config)) + let comment_separator = |comment: &str, shape: Shape| { + if comment.is_empty() { + String::new() + } else { + format!("\n{}", shape.indent.to_string(context.config)) + } }; let newline_before_where = comment_separator(&comment_before, shape); let newline_after_where = comment_separator(&comment_after, clause_shape); -- cgit 1.4.1-3-g733a5 From a7060f9fdf5b0681e224e5650052e612cbcd7fb3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 23:39:09 +0900 Subject: Remove excessive block() and block_only() Since we now use the same indent style for every expressions, these safe guards can be removed. --- src/chains.rs | 2 +- src/closures.rs | 4 +--- src/expr.rs | 14 ++++++-------- 3 files changed, 8 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 816ce60ad4d..b346b9a38a2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -129,7 +129,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; match context.config.indent_style() { IndentStyle::Visual => parent_shape.offset_left(overhead)?, - IndentStyle::Block => parent_shape.block().offset_left(offset)?, + IndentStyle::Block => parent_shape.offset_left(offset)?, } } else { other_child_shape diff --git a/src/closures.rs b/src/closures.rs index 73ef2064295..f8f39f4f27b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -162,9 +162,7 @@ fn rewrite_closure_block( context: &RewriteContext, shape: Shape, ) -> Option { - let block_shape = shape.block(); - let block_str = block.rewrite(context, block_shape)?; - Some(format!("{} {}", prefix, block_str)) + Some(format!("{} {}", prefix, block.rewrite(context, shape)?)) } // Return type is (prefix, extra_offset) diff --git a/src/expr.rs b/src/expr.rs index 259ac0007ed..e406792332d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1061,8 +1061,7 @@ impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { debug!("ControlFlow::rewrite {:?} {:?}", self, shape); - let alt_block_sep = - String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); let (cond_str, used_width) = self.rewrite_cond(context, shape, &alt_block_sep)?; // If `used_width` is 0, it indicates that whole control flow is written in a single line. if used_width == 0 { @@ -1268,7 +1267,7 @@ fn rewrite_match( IndentStyle::Block => cond_shape.offset_left(6)?, }; let cond_str = cond.rewrite(context, cond_shape)?; - let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => &alt_block_sep, _ if last_line_extendable(&cond_str) => " ", @@ -1547,7 +1546,7 @@ fn rewrite_match_body( }; let comma = arm_comma(context.config, body, is_last); - let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config); + let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); let alt_block_sep = alt_block_sep.as_str(); let combine_orig_body = |body_str: &str| { @@ -2785,10 +2784,9 @@ pub fn choose_rhs( _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = Shape::indented( - shape.block().indent.block_indent(context.config), - context.config, - ).sub_width(shape.rhs_overhead(context.config))?; + let new_shape = + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(shape.rhs_overhead(context.config))?; let new_rhs = expr.rewrite(context, new_shape); let new_indent_str = &new_shape.indent.to_string(context.config); -- cgit 1.4.1-3-g733a5 From b29a3afb962244316f3a8cd03195760e710b123e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 23:54:34 +0900 Subject: Fix indentation in multi lined pattern --- src/expr.rs | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e406792332d..bb4b71f2963 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -937,21 +937,16 @@ impl<'a> ControlFlow<'a> { let offset = self.keyword.len() + label_string.len() + 1; let pat_expr_string = match self.cond { - Some(cond) => { - let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => constr_shape.shrink_left(offset)?, - IndentStyle::Block => constr_shape.offset_left(offset)?, - }; - rewrite_pat_expr( - context, - self.pat, - cond, - self.matcher, - self.connector, - self.keyword, - cond_shape, - )? - } + Some(cond) => rewrite_pat_expr( + context, + self.pat, + cond, + self.matcher, + self.connector, + self.keyword, + constr_shape, + offset, + )?, None => String::new(), }; @@ -967,8 +962,8 @@ impl<'a> ControlFlow<'a> { .max_width() .checked_sub(constr_shape.used_width() + offset + brace_overhead) .unwrap_or(0); - let force_newline_brace = context.config.indent_style() == IndentStyle::Block - && (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) + let force_newline_brace = (pat_expr_string.contains('\n') + || pat_expr_string.len() > one_line_budget) && !last_line_extendable(&pat_expr_string); // Try to format if-else on single line. @@ -1704,23 +1699,25 @@ fn rewrite_pat_expr( connector: &str, keyword: &str, shape: Shape, + offset: usize, ) -> Option { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); + let cond_shape = shape.offset_left(offset)?; if let Some(pat) = pat { let matcher = if matcher.is_empty() { matcher.to_owned() } else { format!("{} ", matcher) }; - let pat_shape = shape + let pat_shape = cond_shape .offset_left(matcher.len())? .sub_width(connector.len())?; let pat_string = pat.rewrite(context, pat_shape)?; let result = format!("{}{}{}", matcher, pat_string, connector); - return rewrite_assign_rhs(context, result, expr, shape); + return rewrite_assign_rhs(context, result, expr, cond_shape); } - let expr_rw = expr.rewrite(context, shape); + let expr_rw = expr.rewrite(context, cond_shape); // The expression may (partially) fit on the current line. // We do not allow splitting between `if` and condition. if keyword == "if" || expr_rw.is_some() { -- cgit 1.4.1-3-g733a5 From 414a99592623df7f0cb4c80d69d735462f3027c3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 17:40:51 +0900 Subject: Replace StringBuffer with String --- Cargo.lock | 10 ---------- Cargo.toml | 1 - src/filemap.rs | 20 +++++++------------- src/lib.rs | 14 +++++++------- src/missed_spans.rs | 10 +++++++--- src/visitor.rs | 7 +++---- 6 files changed, 24 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 1e78ede87ca..b53820421c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,7 +186,6 @@ dependencies = [ "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "strings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -242,14 +241,6 @@ dependencies = [ "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "strings" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "syn" version = "0.11.11" @@ -363,7 +354,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" "checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" -"checksum strings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa481ee1bc42fc3df8195f91f7cb43cf8f2b71b48bac40bf5381cfaf7e481f3c" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" diff --git a/Cargo.toml b/Cargo.toml index 551f7b38b39..79acfac5b2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ serde_json = "1.0" unicode-segmentation = "1.0.0" regex = "0.2" term = "0.4" -strings = "0.1" diff = "0.1" log = "0.3" env_logger = "0.4" diff --git a/src/filemap.rs b/src/filemap.rs index c46b477abaa..68e06f5c9ac 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -13,8 +13,6 @@ use std::fs::{self, File}; use std::io::{self, BufWriter, Read, Write}; -use strings::string_buffer::StringBuffer; - use checkstyle::{output_checkstyle_file, output_footer, output_header}; use config::{Config, NewlineStyle, WriteMode}; use rustfmt_diff::{make_diff, print_diff, Mismatch}; @@ -22,10 +20,10 @@ use rustfmt_diff::{make_diff, print_diff, Mismatch}; // A map of the files of a crate, with their new content pub type FileMap = Vec; -pub type FileRecord = (String, StringBuffer); +pub type FileRecord = (String, String); // Append a newline to the end of each file. -pub fn append_newline(s: &mut StringBuffer) { +pub fn append_newline(s: &mut String) { s.push_str("\n"); } @@ -47,11 +45,7 @@ where } // Prints all newlines either as `\n` or as `\r\n`. -pub fn write_system_newlines( - writer: T, - text: &StringBuffer, - config: &Config, -) -> Result<(), io::Error> +pub fn write_system_newlines(writer: T, text: &String, config: &Config) -> Result<(), io::Error> where T: Write, { @@ -71,7 +65,7 @@ where match style { NewlineStyle::Unix => write!(writer, "{}", text), NewlineStyle::Windows => { - for (c, _) in text.chars() { + for c in text.chars() { match c { '\n' => write!(writer, "\r\n")?, '\r' => continue, @@ -85,7 +79,7 @@ where } pub fn write_file( - text: &StringBuffer, + text: &String, filename: &str, out: &mut T, config: &Config, @@ -94,7 +88,7 @@ where T: Write, { fn source_and_formatted_text( - text: &StringBuffer, + text: &String, filename: &str, config: &Config, ) -> Result<(String, String), io::Error> { @@ -109,7 +103,7 @@ where fn create_diff( filename: &str, - text: &StringBuffer, + text: &String, config: &Config, ) -> Result, io::Error> { let (ori, fmt) = source_and_formatted_text(text, filename, config)?; diff --git a/src/lib.rs b/src/lib.rs index 18e802b1d2e..a300e961421 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,6 @@ extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; -extern crate strings; extern crate syntax; extern crate term; extern crate unicode_segmentation; @@ -35,7 +34,6 @@ use std::rc::Rc; use errors::{DiagnosticBuilder, Handler}; use errors::emitter::{ColorConfig, EmitterWriter}; -use strings::string_buffer::StringBuffer; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping}; use syntax::parse::{self, ParseSess}; @@ -300,7 +298,7 @@ fn format_ast( mut after_file: F, ) -> Result<(FileMap, bool), io::Error> where - F: FnMut(&str, &mut StringBuffer, &[(usize, usize)]) -> Result, + F: FnMut(&str, &mut String, &[(usize, usize)]) -> Result, { let mut result = FileMap::new(); // diff mode: check if any files are differing @@ -369,7 +367,7 @@ fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool // FIXME(#209) warn on bad license // FIXME(#20) other stuff for parity with make tidy fn format_lines( - text: &mut StringBuffer, + text: &mut String, name: &str, skipped_range: &[(usize, usize)], config: &Config, @@ -386,8 +384,10 @@ fn format_lines( let mut prev_char: Option = None; let mut is_comment = false; let mut line_buffer = String::with_capacity(config.max_width() * 2); + let mut b = 0; - for (c, b) in text.chars() { + for c in text.chars() { + b += 1; if c == '\r' { continue; } @@ -456,8 +456,8 @@ fn format_lines( } if newline_count > 1 { - debug!("track truncate: {} {}", text.len, newline_count); - let line = text.len - newline_count + 1; + debug!("track truncate: {} {}", text.len(), newline_count); + let line = text.len() - newline_count + 1; text.truncate(line); } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2ed1f50182b..2c4faa42b85 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -17,12 +17,12 @@ use codemap::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::WriteMode; use shape::{Indent, Shape}; -use utils::{count_newlines, mk_sp}; +use utils::{count_newlines, last_line_width, mk_sp}; use visitor::FmtVisitor; impl<'a> FmtVisitor<'a> { fn output_at_start(&self) -> bool { - self.buffer.len == 0 + self.buffer.len() == 0 } // TODO these format_missing methods are ugly. Refactor and add unit tests @@ -86,7 +86,11 @@ impl<'a> FmtVisitor<'a> { fn push_vertical_spaces(&mut self, mut newline_count: usize) { // The buffer already has a trailing newline. - let offset = if self.buffer.cur_offset() == 0 { 0 } else { 1 }; + let offset = if last_line_width(&self.buffer) == 0 { + 0 + } else { + 1 + }; let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; if newline_count > newline_upper_bound { diff --git a/src/visitor.rs b/src/visitor.rs index ac5501cae4c..a7c33d2697c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -10,7 +10,6 @@ use std::cmp; -use strings::string_buffer::StringBuffer; use syntax::{ast, visit}; use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; @@ -74,7 +73,7 @@ impl<'a> SnippetProvider<'a> { pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, - pub buffer: StringBuffer, + pub buffer: String, pub last_pos: BytePos, // FIXME: use an RAII util or closure for indenting pub block_indent: Indent, @@ -252,7 +251,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // The closing brace itself, however, should be indented at a shallower // level. fn close_block(&mut self, unindent_comment: bool) { - let total_len = self.buffer.len; + let total_len = self.buffer.len(); let chars_too_many = if unindent_comment { 0 } else if self.config.hard_tabs() { @@ -565,7 +564,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { FmtVisitor { parse_session: parse_session, codemap: parse_session.codemap(), - buffer: StringBuffer::new(), + buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), last_pos: BytePos(0), block_indent: Indent::empty(), config: config, -- cgit 1.4.1-3-g733a5 From db29f9e0f7fd0c085a94b21eb9ac8dbdb8f6cfcd Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 17:41:02 +0900 Subject: Fix indent issue when recovering comments Closes #1989 --- src/missed_spans.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2c4faa42b85..08fd5bd79e3 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -154,21 +154,21 @@ impl<'a> FmtVisitor<'a> { } if status.rewrite_next_comment { - if fix_indent { + let comment_indent = if fix_indent { if let Some('{') = last_char { self.push_str("\n"); } let indent_str = self.block_indent.to_string(self.config); self.push_str(&indent_str); + self.block_indent } else { self.push_str(" "); - } - + Indent::from_width(self.config, last_line_width(&self.buffer)) + }; let comment_width = ::std::cmp::min( self.config.comment_width(), self.config.max_width() - self.block_indent.width(), ); - let comment_indent = Indent::from_width(self.config, self.buffer.cur_offset()); let comment_shape = Shape::legacy(comment_width, comment_indent); let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) .unwrap_or_else(|| String::from(subslice)); -- cgit 1.4.1-3-g733a5 From 5faf31bb3245fefc350fc9c34659f1e551311381 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 11:37:13 +0900 Subject: Trim a trailing whitespace on empty line inside code block comment --- src/comment.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 8cd491b6ee3..4a44c77a4a2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -332,7 +332,11 @@ fn rewrite_comment_inner( inside_code_block = !inside_code_block; } if inside_code_block { - result.push_str(line); + if line.is_empty() && result.ends_with(' ') { + result.pop(); + } else { + result.push_str(line); + } continue; } -- cgit 1.4.1-3-g733a5 From d1e5d7866b3dc39481ba5e83287ba5078963137e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 9 Dec 2017 20:23:48 +0900 Subject: Make CharClasses and FullCodeCharKind public --- src/comment.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 8cd491b6ee3..bf462e38b7a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -581,7 +581,7 @@ pub fn remove_trailing_white_spaces(text: &str) -> String { buffer } -struct CharClasses +pub struct CharClasses where T: Iterator, T::Item: RichChar, @@ -606,6 +606,12 @@ impl RichChar for (usize, char) { } } +impl RichChar for (char, usize) { + fn get_char(&self) -> char { + self.0 + } +} + #[derive(PartialEq, Eq, Debug, Clone, Copy)] enum CharClassesStatus { Normal, @@ -635,7 +641,7 @@ pub enum CodeCharKind { /// describing opening and closing of comments for ease when chunking /// code from tagged characters #[derive(PartialEq, Eq, Debug, Clone, Copy)] -enum FullCodeCharKind { +pub enum FullCodeCharKind { Normal, /// The first character of a comment, there is only one for a comment (always '/') StartComment, @@ -649,7 +655,7 @@ enum FullCodeCharKind { } impl FullCodeCharKind { - fn is_comment(&self) -> bool { + pub fn is_comment(&self) -> bool { match *self { FullCodeCharKind::StartComment | FullCodeCharKind::InComment @@ -658,6 +664,10 @@ impl FullCodeCharKind { } } + pub fn is_string(&self) -> bool { + *self == FullCodeCharKind::InString + } + fn to_codecharkind(&self) -> CodeCharKind { if self.is_comment() { CodeCharKind::Comment @@ -672,7 +682,7 @@ where T: Iterator, T::Item: RichChar, { - fn new(base: T) -> CharClasses { + pub fn new(base: T) -> CharClasses { CharClasses { base: base.peekable(), status: CharClassesStatus::Normal, -- cgit 1.4.1-3-g733a5 From ef6ebaa2155d1c0da71d06f793707d419f56009f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 9 Dec 2017 20:24:14 +0900 Subject: Add a config option to suppress error message on string literal --- src/config.rs | 2 ++ src/lib.rs | 83 +++++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 6dc1056b5af..d15507f4962 100644 --- a/src/config.rs +++ b/src/config.rs @@ -684,6 +684,8 @@ create_config! { error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; error_on_line_overflow_comments: bool, true, false, "Error if unable to get comments within max_width"; + error_on_line_overflow_strings: bool, true, false, + "Error if unable to get string letrais within max_width"; report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, diff --git a/src/lib.rs b/src/lib.rs index a300e961421..0db8925d01d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,6 +39,7 @@ use syntax::codemap::{CodeMap, FilePathMapping}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; +use comment::{CharClasses, FullCodeCharKind}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; @@ -76,6 +77,7 @@ mod patterns; mod summary; mod vertical; +#[derive(Clone, Copy)] pub enum ErrorKind { // Line has exceeded character limit (found, maximum) LineOverflow(usize, usize), @@ -104,6 +106,7 @@ pub struct FormattingError { line: usize, kind: ErrorKind, is_comment: bool, + is_string: bool, line_buffer: String, } @@ -116,12 +119,14 @@ impl FormattingError { } fn msg_suffix(&self) -> &str { - match self.kind { - ErrorKind::LineOverflow(..) if self.is_comment => { - "use `error_on_line_overflow_comments = false` to suppress \ - the warning against line comments\n" - } - _ => "", + if self.is_comment { + "use `error_on_line_overflow_comments = false` to suppress \ + the warning against comments\n" + } else if self.is_string { + "use `error_on_line_overflow_strings = false` to suppress \ + the warning against string literals\n" + } else { + "" } } @@ -363,6 +368,27 @@ fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool .any(|&(lo, hi)| lo <= line_number && line_number <= hi) } +fn should_report_error( + config: &Config, + char_kind: FullCodeCharKind, + is_string: bool, + error_kind: ErrorKind, +) -> bool { + let allow_error_report = if char_kind.is_comment() { + config.error_on_line_overflow_comments() + } else if is_string { + config.error_on_line_overflow_strings() + } else { + true + }; + + match error_kind { + ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, + ErrorKind::TrailingWhitespace => allow_error_report, + _ => true, + } +} + // Formatting done on a char by char or line by line basis. // FIXME(#209) warn on bad license // FIXME(#20) other stuff for parity with make tidy @@ -381,19 +407,17 @@ fn format_lines( let mut newline_count = 0; let mut errors = vec![]; let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); - let mut prev_char: Option = None; - let mut is_comment = false; let mut line_buffer = String::with_capacity(config.max_width() * 2); + let mut is_string = false; // true if the current line contains a string literal. + let mut format_line = config.file_lines().contains_line(name, cur_line); let mut b = 0; - for c in text.chars() { + for (kind, c) in CharClasses::new(text.chars()) { b += 1; if c == '\r' { continue; } - let format_line = config.file_lines().contains_line(name, cur_line as usize); - if format_line { // Add warnings for bad todos/ fixmes if let Some(issue) = issue_seeker.inspect(c) { @@ -401,6 +425,7 @@ fn format_lines( line: cur_line, kind: ErrorKind::BadIssue(issue), is_comment: false, + is_string: false, line_buffer: String::new(), }); } @@ -409,20 +434,24 @@ fn format_lines( if c == '\n' { if format_line { // Check for (and record) trailing whitespace. - if let Some(lw) = last_wspace { - trims.push((cur_line, lw, b, line_buffer.clone())); + if let Some(..) = last_wspace { + if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) { + trims.push((cur_line, kind, line_buffer.clone())); + } line_len -= 1; } // Check for any line width errors we couldn't correct. - let report_error_on_line_overflow = config.error_on_line_overflow() + let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); + if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) - && (config.error_on_line_overflow_comments() || !is_comment); - if report_error_on_line_overflow && line_len > config.max_width() { + && should_report_error(config, kind, is_string, error_kind) + { errors.push(FormattingError { line: cur_line, - kind: ErrorKind::LineOverflow(line_len, config.max_width()), - is_comment: is_comment, + kind: error_kind, + is_comment: kind.is_comment(), + is_string: is_string, line_buffer: line_buffer.clone(), }); } @@ -430,11 +459,11 @@ fn format_lines( line_len = 0; cur_line += 1; + format_line = config.file_lines().contains_line(name, cur_line); newline_count += 1; last_wspace = None; - prev_char = None; - is_comment = false; line_buffer.clear(); + is_string = false; } else { newline_count = 0; line_len += 1; @@ -442,16 +471,13 @@ fn format_lines( if last_wspace.is_none() { last_wspace = Some(b); } - } else if c == '/' { - if let Some('/') = prev_char { - is_comment = true; - } - last_wspace = None; } else { last_wspace = None; } - prev_char = Some(c); line_buffer.push(c); + if kind.is_string() { + is_string = true; + } } } @@ -461,12 +487,13 @@ fn format_lines( text.truncate(line); } - for &(l, _, _, ref b) in &trims { + for &(l, kind, ref b) in &trims { if !is_skipped_line(l, skipped_range) { errors.push(FormattingError { line: l, kind: ErrorKind::TrailingWhitespace, - is_comment: false, + is_comment: kind.is_comment(), + is_string: kind.is_string(), line_buffer: b.clone(), }); } -- cgit 1.4.1-3-g733a5 From 6c3de706aeb17c0d0d35b52e21a3f378b9d06c37 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 9 Dec 2017 23:37:42 +0900 Subject: Make RichChar public --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index bf462e38b7a..0442a23876a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -590,7 +590,7 @@ where status: CharClassesStatus, } -trait RichChar { +pub trait RichChar { fn get_char(&self) -> char; } -- cgit 1.4.1-3-g733a5 From 4d9226ffeefcd2863c2f300381e6d9067e165dc0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 10 Dec 2017 18:14:17 +0900 Subject: Fix a typo --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index d15507f4962..960f0f687d3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -685,7 +685,7 @@ create_config! { error_on_line_overflow_comments: bool, true, false, "Error if unable to get comments within max_width"; error_on_line_overflow_strings: bool, true, false, - "Error if unable to get string letrais within max_width"; + "Error if unable to get string literals within max_width"; report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, -- cgit 1.4.1-3-g733a5 From aea19d5e3347d6ba31306e4ecbf84f883a2442f4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 09:39:06 +0900 Subject: Combine error_on_line_overflow_comments/strings 1. Rename to error_on_unformatted_comments_or_strings 2. Set the option to false by default. --- src/config.rs | 7 +++---- src/lib.rs | 18 ++++++------------ .../configs-error_on_line_overflow_comment-false.rs | 7 ------- .../configs-error_on_line_overflow_strings-false.rs | 9 --------- ...s-error_on_unformatted_comments_or_strings-false.rs | 12 ++++++++++++ 5 files changed, 21 insertions(+), 32 deletions(-) delete mode 100644 tests/target/configs-error_on_line_overflow_comment-false.rs delete mode 100644 tests/target/configs-error_on_line_overflow_strings-false.rs create mode 100644 tests/target/configs-error_on_unformatted_comments_or_strings-false.rs (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 960f0f687d3..2c7d32ab648 100644 --- a/src/config.rs +++ b/src/config.rs @@ -682,10 +682,9 @@ create_config! { disable_all_formatting: bool, false, false, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; - error_on_line_overflow_comments: bool, true, false, - "Error if unable to get comments within max_width"; - error_on_line_overflow_strings: bool, true, false, - "Error if unable to get string literals within max_width"; + error_on_unformatted_comments_or_strings: bool, false, false, + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces"; report_todo: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, diff --git a/src/lib.rs b/src/lib.rs index 0db8925d01d..6a67343303f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,12 +119,9 @@ impl FormattingError { } fn msg_suffix(&self) -> &str { - if self.is_comment { - "use `error_on_line_overflow_comments = false` to suppress \ - the warning against comments\n" - } else if self.is_string { - "use `error_on_line_overflow_strings = false` to suppress \ - the warning against string literals\n" + if self.is_comment || self.is_string { + "set `error_on_unformatted_comments_or_strings = false` to suppress \ + the warning against comments or string literals\n" } else { "" } @@ -374,10 +371,8 @@ fn should_report_error( is_string: bool, error_kind: ErrorKind, ) -> bool { - let allow_error_report = if char_kind.is_comment() { - config.error_on_line_overflow_comments() - } else if is_string { - config.error_on_line_overflow_strings() + let allow_error_report = if char_kind.is_comment() || is_string { + config.error_on_unformatted_comments_or_strings() } else { true }; @@ -443,8 +438,7 @@ fn format_lines( // Check for any line width errors we couldn't correct. let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); - if line_len > config.max_width() - && !is_skipped_line(cur_line, skipped_range) + if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) && should_report_error(config, kind, is_string, error_kind) { errors.push(FormattingError { diff --git a/tests/target/configs-error_on_line_overflow_comment-false.rs b/tests/target/configs-error_on_line_overflow_comment-false.rs deleted file mode 100644 index 9fd9e01e274..00000000000 --- a/tests/target/configs-error_on_line_overflow_comment-false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-error_on_line_overflow_comments: false -// Error on line overflow comment - -// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -fn main() { - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -} diff --git a/tests/target/configs-error_on_line_overflow_strings-false.rs b/tests/target/configs-error_on_line_overflow_strings-false.rs deleted file mode 100644 index b5922745cf2..00000000000 --- a/tests/target/configs-error_on_line_overflow_strings-false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-error_on_line_overflow_strings: false -// Suppress an error on line overflow strings. - -fn main() { - let x = " "; - let a = " - -"; -} diff --git a/tests/target/configs-error_on_unformatted_comments_or_strings-false.rs b/tests/target/configs-error_on_unformatted_comments_or_strings-false.rs new file mode 100644 index 00000000000..ff9a35eb6b8 --- /dev/null +++ b/tests/target/configs-error_on_unformatted_comments_or_strings-false.rs @@ -0,0 +1,12 @@ +// rustfmt-error_on_unformatted_comments_or_strings: false +// Error on line overflow comment or string literals. + +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn main() { + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + let x = " "; + let a = " + +"; +} -- cgit 1.4.1-3-g733a5 From d17168f4ba004000a560aacd1bb7b9b215c64084 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 09:54:44 +0900 Subject: Add error-on-unformatted command line option --- src/bin/rustfmt.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 9bf26887881..aea8174f139 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -163,6 +163,12 @@ fn make_opts() -> Options { "config-help", "show details of rustfmt configuration options", ); + opts.optflag( + "", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces", + ); opts.opt( "", "dump-default-config", -- cgit 1.4.1-3-g733a5 From cbd3608c30cfdee4954820d8ee1f940a4f1abf08 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 09:55:15 +0900 Subject: Organize command line options and start with upper case --- src/bin/rustfmt.rs | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index aea8174f139..713d320aa78 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -135,33 +135,20 @@ fn match_cli_path_or_file( fn make_opts() -> Options { let mut opts = Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("V", "version", "show version information"); - opts.optflag("v", "verbose", "print verbose output"); - opts.optopt( - "", - "write-mode", - "how to write output (not usable when piping from stdin)", - "[replace|overwrite|display|plain|diff|coverage|checkstyle]", - ); - opts.optopt( - "", - "color", - "use colored output (if supported)", - "[always|never|auto]", - ); - opts.optflag("", "skip-children", "don't reformat child modules"); + opts.optflag("h", "help", "Show this message"); + opts.optflag("V", "version", "Show version information"); + opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("", "skip-children", "Don't reformat child modules"); opts.optflag( "", "unstable-features", "Enables unstable features. Only available on nightly channel", ); - opts.optflag( "", "config-help", - "show details of rustfmt configuration options", + "Show details of rustfmt configuration options", ); opts.optflag( "", @@ -169,13 +156,24 @@ fn make_opts() -> Options { "Error if unable to get comments or string literals within max_width, \ or they are left with trailing whitespaces", ); - opts.opt( + + opts.optopt( + "", + "write-mode", + "How to write output (not usable when piping from stdin)", + "[replace|overwrite|display|plain|diff|coverage|checkstyle]", + ); + opts.optopt( + "", + "color", + "Use colored output (if supported)", + "[always|never|auto]", + ); + opts.optopt( "", "dump-default-config", "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", "PATH", - HasArg::Maybe, - Occur::Optional, ); opts.optopt( "", -- cgit 1.4.1-3-g733a5 From 1e982c66a0ba9f04af745bbf1b70bf43d8596403 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 10:00:49 +0900 Subject: Fix a typo --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 713d320aa78..75b45156ace 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -20,7 +20,7 @@ use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use getopts::{HasArg, Matches, Occur, Options}; +use getopts::{Matches, Options}; use rustfmt::{run, Input, Summary}; use rustfmt::file_lines::FileLines; -- cgit 1.4.1-3-g733a5 From 93a75de18ecb8c52b61432f355458ad14e4bba69 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 10:01:00 +0900 Subject: Print command line options in alphabetical order --- src/bin/rustfmt.rs | 56 +++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 75b45156ace..4eb1deb2e74 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -136,38 +136,24 @@ fn match_cli_path_or_file( fn make_opts() -> Options { let mut opts = Options::new(); - opts.optflag("h", "help", "Show this message"); - opts.optflag("V", "version", "Show version information"); - opts.optflag("v", "verbose", "Print verbose output"); - opts.optflag("", "skip-children", "Don't reformat child modules"); - opts.optflag( + // Sorted in alphabetical order. + opts.optopt( "", - "unstable-features", - "Enables unstable features. Only available on nightly channel", + "color", + "Use colored output (if supported)", + "[always|never|auto]", ); opts.optflag( "", "config-help", "Show details of rustfmt configuration options", ); - opts.optflag( - "", - "error-on-unformatted", - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces", - ); - - opts.optopt( - "", - "write-mode", - "How to write output (not usable when piping from stdin)", - "[replace|overwrite|display|plain|diff|coverage|checkstyle]", - ); opts.optopt( "", - "color", - "Use colored output (if supported)", - "[always|never|auto]", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ + found reverts to the input file path", + "[Path for the configuration file]", ); opts.optopt( "", @@ -181,12 +167,11 @@ fn make_opts() -> Options { "Dumps configuration options that were checked during formatting to a file.", "PATH", ); - opts.optopt( + opts.optflag( "", - "config-path", - "Recursively searches the given path for the rustfmt.toml config file. If not \ - found reverts to the input file path", - "[Path for the configuration file]", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces", ); opts.optopt( "", @@ -194,6 +179,21 @@ fn make_opts() -> Options { "Format specified line ranges. See README for more detail on the JSON format.", "JSON", ); + opts.optflag("h", "help", "Show this message"); + opts.optflag("", "skip-children", "Don't reformat child modules"); + opts.optflag( + "", + "unstable-features", + "Enables unstable features. Only available on nightly channel", + ); + opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("V", "version", "Show version information"); + opts.optopt( + "", + "write-mode", + "How to write output (not usable when piping from stdin)", + "[replace|overwrite|display|plain|diff|coverage|checkstyle]", + ); opts } -- cgit 1.4.1-3-g733a5 From d3ee7f3f06b8636ce3a26bf3c53242975bccc2de Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 10:15:31 +0900 Subject: Set error_on_unformatted_comments_or_strings to true when --error-on-unformatted option is passed --- src/bin/rustfmt.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 4eb1deb2e74..81be0761aae 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -63,6 +63,7 @@ struct CliOptions { color: Option, file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, + error_on_unformatted: bool, } impl CliOptions { @@ -104,6 +105,10 @@ impl CliOptions { options.file_lines = file_lines.parse()?; } + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = true; + } + Ok(options) } @@ -112,6 +117,7 @@ impl CliOptions { config.set().verbose(self.verbose); config.set().file_lines(self.file_lines); config.set().unstable_features(self.unstable_features); + config.set().error_on_unformatted_comments_or_strings(self.error_on_unformatted); if let Some(write_mode) = self.write_mode { config.set().write_mode(write_mode); } -- cgit 1.4.1-3-g733a5 From e45c0c48155f742fcb7f13206ed116af4f7d0eb2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 11:46:04 +0900 Subject: Rename error_on_unformatted_comments_or_strings to error_on_unformatted --- src/bin/rustfmt.rs | 2 +- src/config.rs | 2 +- src/lib.rs | 4 ++-- tests/target/configs-error_on_unformatted-false.rs | 12 ++++++++++++ ...configs-error_on_unformatted_comments_or_strings-false.rs | 12 ------------ 5 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 tests/target/configs-error_on_unformatted-false.rs delete mode 100644 tests/target/configs-error_on_unformatted_comments_or_strings-false.rs (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 81be0761aae..aebd19d8e4b 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -117,7 +117,7 @@ impl CliOptions { config.set().verbose(self.verbose); config.set().file_lines(self.file_lines); config.set().unstable_features(self.unstable_features); - config.set().error_on_unformatted_comments_or_strings(self.error_on_unformatted); + config.set().error_on_unformatted(self.error_on_unformatted); if let Some(write_mode) = self.write_mode { config.set().write_mode(write_mode); } diff --git a/src/config.rs b/src/config.rs index 2c7d32ab648..ed44df022a9 100644 --- a/src/config.rs +++ b/src/config.rs @@ -682,7 +682,7 @@ create_config! { disable_all_formatting: bool, false, false, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; - error_on_unformatted_comments_or_strings: bool, false, false, + error_on_unformatted: bool, false, false, "Error if unable to get comments or string literals within max_width, \ or they are left with trailing whitespaces"; report_todo: ReportTactic, ReportTactic::Never, false, diff --git a/src/lib.rs b/src/lib.rs index 6a67343303f..2c867539881 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -120,7 +120,7 @@ impl FormattingError { fn msg_suffix(&self) -> &str { if self.is_comment || self.is_string { - "set `error_on_unformatted_comments_or_strings = false` to suppress \ + "set `error_on_unformatted = false` to suppress \ the warning against comments or string literals\n" } else { "" @@ -372,7 +372,7 @@ fn should_report_error( error_kind: ErrorKind, ) -> bool { let allow_error_report = if char_kind.is_comment() || is_string { - config.error_on_unformatted_comments_or_strings() + config.error_on_unformatted() } else { true }; diff --git a/tests/target/configs-error_on_unformatted-false.rs b/tests/target/configs-error_on_unformatted-false.rs new file mode 100644 index 00000000000..6a78374e2a2 --- /dev/null +++ b/tests/target/configs-error_on_unformatted-false.rs @@ -0,0 +1,12 @@ +// rustfmt-error_on_unformatted: false +// Error on line overflow comment or string literals. + +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn main() { + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + let x = " "; + let a = " + +"; +} diff --git a/tests/target/configs-error_on_unformatted_comments_or_strings-false.rs b/tests/target/configs-error_on_unformatted_comments_or_strings-false.rs deleted file mode 100644 index ff9a35eb6b8..00000000000 --- a/tests/target/configs-error_on_unformatted_comments_or_strings-false.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-error_on_unformatted_comments_or_strings: false -// Error on line overflow comment or string literals. - -// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -fn main() { - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - - let x = " "; - let a = " - -"; -} -- cgit 1.4.1-3-g733a5 From 3dd31e25bf3285a52dc02cd5ea0c3b344910f52b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Dec 2017 11:50:11 +0900 Subject: Use enumerate() --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 2c867539881..b00caf40cd5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -405,10 +405,8 @@ fn format_lines( let mut line_buffer = String::with_capacity(config.max_width() * 2); let mut is_string = false; // true if the current line contains a string literal. let mut format_line = config.file_lines().contains_line(name, cur_line); - let mut b = 0; - for (kind, c) in CharClasses::new(text.chars()) { - b += 1; + for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { if c == '\r' { continue; } -- cgit 1.4.1-3-g733a5 From 32804c1f092a50ca01c6df9b84f0c157f0ea5d68 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 12 Dec 2017 00:54:37 +0900 Subject: Do not print usage when rustfmt failed --- src/bin/rustfmt.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index aebd19d8e4b..f4b9c081821 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -350,7 +350,7 @@ fn main() { } } Err(e) => { - print_usage_to_stderr(&opts, &e.to_string()); + eprintln!("{}", e.to_string()); 1 } }; @@ -364,23 +364,18 @@ fn main() { std::process::exit(exit_code); } -macro_rules! print_usage { - ($print:ident, $opts:ident, $reason:expr) => ({ - let msg = format!( - "{}\n\nusage: {} [options] ...", - $reason, - env::args_os().next().unwrap().to_string_lossy() - ); - $print!("{}", $opts.usage(&msg)); - }) -} - fn print_usage_to_stdout(opts: &Options, reason: &str) { - print_usage!(println, opts, reason); -} - -fn print_usage_to_stderr(opts: &Options, reason: &str) { - print_usage!(eprintln, opts, reason); + let sep = if reason.is_empty() { + String::new() + } else { + format!("{}\n\n", reason) + }; + let msg = format!( + "{}Format Rust code\n\nusage: {} [options] ...", + sep, + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&msg)); } fn print_version() { -- cgit 1.4.1-3-g733a5 From 17154c30cbd68db17589acd63bc5f86e5902202d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 12 Dec 2017 00:54:55 +0900 Subject: Warn when there are unknown config options --- src/config.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index ed44df022a9..ff90a96b91e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -394,22 +394,23 @@ macro_rules! create_config { $( stringify!($i) => (), )+ - _ => { - let msg = - &format!("Warning: Unknown configuration option `{}`\n", - key); - err.push_str(msg) - } + _ => { + let msg = + &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } } } } match parsed.try_into() { - Ok(parsed_config) => - Ok(Config::default().fill_from_parsed_config(parsed_config)), + Ok(parsed_config) => { + eprintln!("{}", err); + Ok(Config::default().fill_from_parsed_config(parsed_config)) + } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); err.push_str(format!("{}\n", e).as_str()); - err.push_str("Please check your config file.\n"); + err.push_str("Please check your config file."); Err(err) } } -- cgit 1.4.1-3-g733a5 From 516f15aba154e2cc66b999d0c9613479f4d53275 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 12 Dec 2017 13:48:12 +0900 Subject: Cargo clippy --- src/bin/cargo-fmt.rs | 8 ++++---- src/comment.rs | 2 +- src/expr.rs | 16 ++++++---------- src/filemap.rs | 8 ++++---- src/imports.rs | 8 ++++---- src/items.rs | 14 +++++++------- src/macros.rs | 2 +- src/summary.rs | 2 +- src/visitor.rs | 17 ++++++++--------- 9 files changed, 36 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 63d7d2c3353..3916b52fe5f 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -54,7 +54,7 @@ fn execute() -> i32 { // If there is any invalid argument passed to `cargo fmt`, return without formatting. let mut is_package_arg = false; for arg in env::args().skip(2).take_while(|a| a != "--") { - if arg.starts_with("-") { + if arg.starts_with('-') { is_package_arg = arg.starts_with("--package"); } else if !is_package_arg { print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); @@ -215,7 +215,7 @@ impl CargoFmtStrategy { } } -/// Based on the specified CargoFmtStrategy, returns a set of main source files. +/// Based on the specified `CargoFmtStrategy`, returns a set of main source files. fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { let mut targets = HashSet::new(); @@ -228,7 +228,7 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error if targets.is_empty() { Err(io::Error::new( io::ErrorKind::Other, - format!("Failed to find targets"), + "Failed to find targets".to_owned(), )) } else { Ok(targets) @@ -310,7 +310,7 @@ fn get_targets_with_hitlist( fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { for target in target_paths { - targets.insert(Target::from_target(&target)); + targets.insert(Target::from_target(target)); } } diff --git a/src/comment.rs b/src/comment.rs index a9fc31ea0b0..439a7f6a05f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -930,7 +930,7 @@ pub fn recover_comment_removed( context: &RewriteContext, ) -> Option { let snippet = context.snippet(span); - if snippet != new && changed_comment_content(&snippet, &new) { + if snippet != new && changed_comment_content(snippet, &new) { // We missed some comments. Keep the original text. Some(snippet.to_owned()) } else { diff --git a/src/expr.rs b/src/expr.rs index 4fe97a2cb2b..8ef55b1716c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -304,7 +304,7 @@ pub fn format_expr( }) } -#[derive(new)] +#[derive(new, Clone, Copy)] pub struct PairParts<'a> { prefix: &'a str, infix: &'a str, @@ -729,7 +729,7 @@ struct ControlFlow<'a> { span: Span, } -fn to_control_flow<'a>(expr: &'a ast::Expr, expr_type: ExprType) -> Option> { +fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { match expr.node { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( cond, @@ -2122,16 +2122,12 @@ fn is_every_args_simple(lists: &[&T]) -> bool { /// In case special-case style is required, returns an offset from which we start horizontal layout. fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option { - if FORMAT_LIKE_WHITELIST - .iter() - .find(|s| **s == callee_str) - .is_some() && args.len() >= 1 && is_every_args_simple(args) + if FORMAT_LIKE_WHITELIST.iter().any(|s| *s == callee_str) && args.len() >= 1 + && is_every_args_simple(args) { Some(1) - } else if WRITE_LIKE_WHITELIST - .iter() - .find(|s| **s == callee_str) - .is_some() && args.len() >= 2 && is_every_args_simple(args) + } else if WRITE_LIKE_WHITELIST.iter().any(|s| *s == callee_str) && args.len() >= 2 + && is_every_args_simple(args) { Some(2) } else { diff --git a/src/filemap.rs b/src/filemap.rs index 68e06f5c9ac..c7fa5e2f1ef 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -45,7 +45,7 @@ where } // Prints all newlines either as `\n` or as `\r\n`. -pub fn write_system_newlines(writer: T, text: &String, config: &Config) -> Result<(), io::Error> +pub fn write_system_newlines(writer: T, text: &str, config: &Config) -> Result<(), io::Error> where T: Write, { @@ -79,7 +79,7 @@ where } pub fn write_file( - text: &String, + text: &str, filename: &str, out: &mut T, config: &Config, @@ -88,7 +88,7 @@ where T: Write, { fn source_and_formatted_text( - text: &String, + text: &str, filename: &str, config: &Config, ) -> Result<(String, String), io::Error> { @@ -103,7 +103,7 @@ where fn create_diff( filename: &str, - text: &String, + text: &str, config: &Config, ) -> Result, io::Error> { let (ori, fmt) = source_and_formatted_text(text, filename, config)?; diff --git a/src/imports.rs b/src/imports.rs index b8a7e3bb6ba..53ccd67b792 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -108,10 +108,10 @@ fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Orderi fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> Option { match (&a.node, &b.node) { (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { - Some(compare_use_trees(&a_tree, &b_tree, false)) + Some(compare_use_trees(a_tree, b_tree, false)) } (&ast::ItemKind::ExternCrate(..), &ast::ItemKind::ExternCrate(..)) => { - Some(context.snippet(a.span).cmp(&context.snippet(b.span))) + Some(context.snippet(a.span).cmp(context.snippet(b.span))) } _ => None, } @@ -141,7 +141,7 @@ impl Rewrite for ast::UseTree { ast::UseTreeKind::Glob => { let prefix_shape = shape.sub_width(3)?; - if self.prefix.segments.len() > 0 { + if !self.prefix.segments.is_empty() { let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; Some(format!("{}::*", path_str)) } else { @@ -476,7 +476,7 @@ fn rewrite_nested_use_tree( let mut items = vec![ListItem::from_str("")]; let iter = itemize_list( context.codemap, - trees.iter().map(|ref tree| &tree.0), + trees.iter().map(|tree| &tree.0), "}", ",", |tree| tree.span.lo(), diff --git a/src/items.rs b/src/items.rs index bff5c00d2f4..7771344f3db 100644 --- a/src/items.rs +++ b/src/items.rs @@ -239,8 +239,8 @@ impl<'a> FnSig<'a> { } impl<'a> FmtVisitor<'a> { - fn format_item(&mut self, item: Item) { - self.push_str(&item.abi); + fn format_item(&mut self, item: &Item) { + self.buffer.push_str(&item.abi); let snippet = self.snippet(item.span); let brace_pos = snippet.find_uncommented("{").unwrap(); @@ -279,7 +279,7 @@ impl<'a> FmtVisitor<'a> { pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { let item = Item::from_foreign_mod(fm, span, self.config); - self.format_item(item); + self.format_item(&item); } fn format_foreign_item(&mut self, item: &ast::ForeignItem) { @@ -950,7 +950,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) .span_after(item.span, &format!("{}", item.ident)); let bound_hi = type_param_bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); - if contains_comment(&snippet) { + if contains_comment(snippet) { return None; } } @@ -1175,7 +1175,7 @@ pub fn format_struct_struct( result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { - result.push_str(&snippet); + result.push_str(snippet); } result.push('}'); return Some(result); @@ -1307,7 +1307,7 @@ fn format_tuple_struct( result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { - result.push_str(&snippet); + result.push_str(snippet); } result.push(')'); } else { @@ -2718,7 +2718,7 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S format!("{}{}{}", format_visibility(vis), item_name, ident) } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Clone, Copy)] enum BracePos { None, Auto, diff --git a/src/macros.rs b/src/macros.rs index ce0616d9ebf..9c32e7f62be 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -144,7 +144,7 @@ pub fn rewrite_macro( }; let ts: TokenStream = mac.node.stream(); - if ts.is_empty() && !contains_comment(&context.snippet(mac.span)) { + if ts.is_empty() && !contains_comment(context.snippet(mac.span)) { return match style { MacroStyle::Parens if position == MacroPosition::Item => { Some(format!("{}();", macro_name)) diff --git a/src/summary.rs b/src/summary.rs index cf034e7dff6..73ee80dac85 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -1,5 +1,5 @@ #[must_use] -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default, Clone, Copy)] pub struct Summary { // Encountered e.g. an IO error. has_operational_errors: bool, diff --git a/src/visitor.rs b/src/visitor.rs index a7c33d2697c..8f6cab0e2df 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -166,7 +166,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos, attr_lo.unwrap_or(first_stmt.span.lo()), )); - let len = CommentCodeSlices::new(&snippet) + let len = CommentCodeSlices::new(snippet) .nth(0) .and_then(|(kind, _, s)| { if kind == CodeCharKind::Normal { @@ -212,7 +212,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { stmt.span.hi(), source!(self, b.span).hi() - brace_compensation, )); - let len = CommentCodeSlices::new(&snippet) + let len = CommentCodeSlices::new(snippet) .last() .and_then(|(kind, _, s)| { if kind == CodeCharKind::Normal && s.trim().is_empty() { @@ -430,7 +430,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } ast::ItemKind::MacroDef(..) => { // FIXME(#1539): macros 2.0 - let mac_snippet = Some(remove_trailing_white_spaces(&self.snippet(item.span))); + let mac_snippet = Some(remove_trailing_white_spaces(self.snippet(item.span))); self.push_rewrite(item.span, mac_snippet); } } @@ -684,9 +684,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Extract leading `use ...;`. let items: Vec<_> = stmts .iter() - .take_while(|stmt| to_stmt_item(stmt).is_some()) + .take_while(|stmt| to_stmt_item(stmt).map_or(false, is_use_item)) .filter_map(|stmt| to_stmt_item(stmt)) - .take_while(|item| is_use_item(item)) .collect(); if items.is_empty() { @@ -779,7 +778,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { use_block: false, is_if_else_block: false, force_one_line_chain: false, - snippet_provider: &self.snippet_provider, + snippet_provider: self.snippet_provider, } } } @@ -888,7 +887,7 @@ where // Extract comments between two attributes. let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); let snippet = context.snippet(span_between_attr); - if count_newlines(&snippet) >= 2 || snippet.contains('/') { + if count_newlines(snippet) >= 2 || snippet.contains('/') { break; } } @@ -974,7 +973,7 @@ impl<'a> Rewrite for [ast::Attribute] { // Preserve an empty line before/after doc comments. if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { let snippet = context.snippet(missing_span); - let (mla, mlb) = has_newlines_before_after_comment(&snippet); + let (mla, mlb) = has_newlines_before_after_comment(snippet); let comment = ::comment::recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), @@ -1068,7 +1067,7 @@ fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Op pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { assert!(is_extern_crate(item)); let new_str = context.snippet(item.span); - Some(if contains_comment(&new_str) { + Some(if contains_comment(new_str) { new_str.to_owned() } else { let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); -- cgit 1.4.1-3-g733a5 From efb68ee21a2680794dd1179ed071b245ade9c91e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 12 Dec 2017 13:48:24 +0900 Subject: Refactor write_snippet_inner() --- src/missed_spans.rs | 329 ++++++++++++++++++++++++---------------------------- 1 file changed, 151 insertions(+), 178 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 08fd5bd79e3..4e1f2a37ef4 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -20,9 +20,28 @@ use shape::{Indent, Shape}; use utils::{count_newlines, last_line_width, mk_sp}; use visitor::FmtVisitor; +struct SnippetStatus { + /// An offset to the current line from the beginnig of the original snippet. + line_start: usize, + /// A length of trailing whitespaces on the current line. + last_wspace: Option, + /// The current line number. + cur_line: usize, +} + +impl SnippetStatus { + fn new(cur_line: usize) -> Self { + SnippetStatus { + line_start: 0, + last_wspace: None, + cur_line, + } + } +} + impl<'a> FmtVisitor<'a> { fn output_at_start(&self) -> bool { - self.buffer.len() == 0 + self.buffer.is_empty() } // TODO these format_missing methods are ugly. Refactor and add unit tests @@ -77,8 +96,8 @@ impl<'a> FmtVisitor<'a> { let snippet = self.snippet(span); if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { // Keep vertical spaces within range. - self.push_vertical_spaces(count_newlines(&snippet)); - process_last_snippet(self, "", &snippet); + self.push_vertical_spaces(count_newlines(snippet)); + process_last_snippet(self, "", snippet); } else { self.write_snippet(span, &process_last_snippet); } @@ -86,11 +105,7 @@ impl<'a> FmtVisitor<'a> { fn push_vertical_spaces(&mut self, mut newline_count: usize) { // The buffer already has a trailing newline. - let offset = if last_line_width(&self.buffer) == 0 { - 0 - } else { - 1 - }; + let offset = if self.buffer.ends_with('\n') { 0 } else { 1 }; let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; if newline_count > newline_upper_bound { @@ -121,86 +136,7 @@ impl<'a> FmtVisitor<'a> { debug!("write_snippet `{}`", snippet); - self.write_snippet_inner(big_snippet, big_diff, &snippet, span, process_last_snippet); - } - - fn process_comment( - &mut self, - status: &mut SnippetStatus, - snippet: &str, - big_snippet: &str, - offset: usize, - big_diff: usize, - subslice: &str, - file_name: &str, - ) -> bool { - let last_char = big_snippet[..(offset + big_diff)] - .chars() - .rev() - .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) - .next(); - - let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - - let subslice_num_lines = count_newlines(subslice); - let skip_this_range = !self.config.file_lines().intersects_range( - file_name, - status.cur_line, - status.cur_line + subslice_num_lines, - ); - - if status.rewrite_next_comment && skip_this_range { - status.rewrite_next_comment = false; - } - - if status.rewrite_next_comment { - let comment_indent = if fix_indent { - if let Some('{') = last_char { - self.push_str("\n"); - } - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - self.block_indent - } else { - self.push_str(" "); - Indent::from_width(self.config, last_line_width(&self.buffer)) - }; - let comment_width = ::std::cmp::min( - self.config.comment_width(), - self.config.max_width() - self.block_indent.width(), - ); - let comment_shape = Shape::legacy(comment_width, comment_indent); - let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) - .unwrap_or_else(|| String::from(subslice)); - self.push_str(&comment_str); - - status.last_wspace = None; - status.line_start = offset + subslice.len(); - - if let Some('/') = subslice.chars().nth(1) { - // check that there are no contained block comments - if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() >= 2 && &s[0..2] == "/*") - { - // Add a newline after line comments - self.push_str("\n"); - } - } else if status.line_start <= snippet.len() { - // For other comments add a newline if there isn't one at the end already - match snippet[status.line_start..].chars().next() { - Some('\n') | Some('\r') => (), - _ => self.push_str("\n"), - } - } - - status.cur_line += subslice_num_lines; - true - } else { - status.rewrite_next_comment = false; - false - } + self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); } fn write_snippet_inner( @@ -220,19 +156,6 @@ impl<'a> FmtVisitor<'a> { let file_name = &char_pos.file.name; let mut status = SnippetStatus::new(char_pos.line); - fn replace_chars<'a>(string: &'a str) -> Cow<'a, str> { - if string.contains(char::is_whitespace) { - Cow::from( - string - .chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect::(), - ) - } else { - Cow::from(string) - } - } - let snippet = &*match self.config.write_mode() { WriteMode::Coverage => replace_chars(old_snippet), _ => Cow::from(old_snippet), @@ -241,98 +164,148 @@ impl<'a> FmtVisitor<'a> { for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { debug!("{:?}: {:?}", kind, subslice); - if let CodeCharKind::Comment = kind { - if self.process_comment( + let newline_count = count_newlines(subslice); + let within_file_lines_range = self.config.file_lines().intersects_range( + file_name, + status.cur_line, + status.cur_line + newline_count, + ); + + if CodeCharKind::Comment == kind && within_file_lines_range { + // 1: comment. + self.process_comment( &mut status, snippet, - big_snippet, + &big_snippet[..(offset + big_diff)], offset, - big_diff, subslice, - file_name, - ) { - continue; - } - } - - let newline_count = count_newlines(&subslice); - if subslice.trim().is_empty() && newline_count > 0 - && self.config.file_lines().intersects_range( - file_name, - status.cur_line, - status.cur_line + newline_count, - ) { + ); + } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range { + // 2: blank lines. self.push_vertical_spaces(newline_count); status.cur_line += newline_count; - status.rewrite_next_comment = true; status.line_start = offset + newline_count; } else { - for (mut i, c) in subslice.char_indices() { - i += offset; - - if c == '\n' { - if !self.config - .file_lines() - .contains_line(file_name, status.cur_line) - { - status.last_wspace = None; - } - - if let Some(lw) = status.last_wspace { - self.push_str(&snippet[status.line_start..lw]); - self.push_str("\n"); - } else { - self.push_str(&snippet[status.line_start..i + 1]); - } - - status.cur_line += 1; - status.line_start = i + 1; - status.last_wspace = None; - status.rewrite_next_comment = true; - } else if c.is_whitespace() { - if status.last_wspace.is_none() { - status.last_wspace = Some(i); - } - } else if c == ';' { - if status.last_wspace.is_some() { - status.line_start = i; - } - - status.rewrite_next_comment = true; - status.last_wspace = None; - } else { - status.rewrite_next_comment = true; - status.last_wspace = None; - } - } - - let remaining = snippet[status.line_start..subslice.len() + offset].trim(); - if !remaining.is_empty() { - self.push_str(remaining); - status.line_start = subslice.len() + offset; - status.rewrite_next_comment = true; - } + // 3: code which we failed to format or which is not within file-lines range. + self.process_missing_code(&mut status, snippet, subslice, offset, file_name); } } process_last_snippet(self, &snippet[status.line_start..], snippet); } -} -struct SnippetStatus { - line_start: usize, - last_wspace: Option, - rewrite_next_comment: bool, - cur_line: usize, -} + fn process_comment( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + big_snippet: &str, + offset: usize, + subslice: &str, + ) { + let last_char = big_snippet + .chars() + .rev() + .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) + .next(); -impl SnippetStatus { - fn new(cur_line: usize) -> Self { - SnippetStatus { - line_start: 0, - last_wspace: None, - rewrite_next_comment: true, - cur_line, + let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); + + if fix_indent { + if let Some('{') = last_char { + self.push_str("\n"); + } + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + } else { + self.push_str(" "); + } + + let comment_width = ::std::cmp::min( + self.config.comment_width(), + self.config.max_width() - self.block_indent.width(), + ); + let comment_indent = Indent::from_width(self.config, last_line_width(&self.buffer)); + let comment_shape = Shape::legacy(comment_width, comment_indent); + let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) + .unwrap_or_else(|| String::from(subslice)); + self.push_str(&comment_str); + + status.last_wspace = None; + status.line_start = offset + subslice.len(); + + if let Some('/') = subslice.chars().nth(1) { + // check that there are no contained block comments + if !subslice + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() >= 2 && &s[0..2] == "/*") + { + // Add a newline after line comments + self.push_str("\n"); + } + } else if status.line_start <= snippet.len() { + // For other comments add a newline if there isn't one at the end already + match snippet[status.line_start..].chars().next() { + Some('\n') | Some('\r') => (), + _ => self.push_str("\n"), + } } + + status.cur_line += count_newlines(subslice); } + + fn process_missing_code( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + subslice: &str, + offset: usize, + file_name: &str, + ) { + for (mut i, c) in subslice.char_indices() { + i += offset; + + if c == '\n' { + let skip_this_line = !self.config + .file_lines() + .contains_line(file_name, status.cur_line); + if skip_this_line { + status.last_wspace = None; + } + + if let Some(lw) = status.last_wspace { + self.push_str(&snippet[status.line_start..lw]); + self.push_str("\n"); + status.last_wspace = None; + } else { + self.push_str(&snippet[status.line_start..i + 1]); + } + + status.cur_line += 1; + status.line_start = i + 1; + } else if c.is_whitespace() && status.last_wspace.is_none() { + status.last_wspace = Some(i); + } else if c == ';' && status.last_wspace.is_some() { + status.line_start = i; + status.last_wspace = None; + } else { + status.last_wspace = None; + } + } + + let remaining = snippet[status.line_start..subslice.len() + offset].trim(); + if !remaining.is_empty() { + self.push_str(remaining); + status.line_start = subslice.len() + offset; + } + } +} + +fn replace_chars(string: &str) -> Cow { + Cow::from( + string + .chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect::(), + ) } -- cgit 1.4.1-3-g733a5 From 7229b26f14aaaa860b5658d7b12b91562ede0c1a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 12 Dec 2017 14:10:31 +0900 Subject: Do not print to stderr when parsing the toml file succeeded --- src/config.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index ff90a96b91e..67ca3f6c3ad 100644 --- a/src/config.rs +++ b/src/config.rs @@ -372,7 +372,7 @@ macro_rules! create_config { self.$i.2 = val; } else { eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ - available in nightly channel.", stringify!($i), val); + available in nightly channel.", stringify!($i), val); } } } @@ -404,7 +404,9 @@ macro_rules! create_config { } match parsed.try_into() { Ok(parsed_config) => { - eprintln!("{}", err); + if !err.is_empty() { + eprint!("{}", err); + } Ok(Config::default().fill_from_parsed_config(parsed_config)) } Err(e) => { -- cgit 1.4.1-3-g733a5 From fad903fd14ad0df045dc574cac0717312860c380 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 8 Dec 2017 14:16:47 +0100 Subject: Move from String to PathBuf where applicable --- src/bin/rustfmt.rs | 16 ++++++--- src/checkstyle.rs | 5 +-- src/codemap.rs | 6 ++-- src/file_lines.rs | 47 +++++++++++++++------------ src/filemap.rs | 33 ++++++++++++------- src/lib.rs | 38 ++++++++++++---------- src/missed_spans.rs | 4 +-- src/modules.rs | 23 ++++++------- tests/system.rs | 94 +++++++++++++++++++++++++++++------------------------ 9 files changed, 152 insertions(+), 114 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index f4b9c081821..0e48ab7c23a 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_private)] #![cfg(not(test))] extern crate env_logger; @@ -22,7 +23,7 @@ use std::str::FromStr; use getopts::{Matches, Options}; -use rustfmt::{run, Input, Summary}; +use rustfmt::{run, FileName, Input, Summary}; use rustfmt::file_lines::FileLines; use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; @@ -243,8 +244,9 @@ fn execute(opts: &Options) -> FmtResult { if let Some(ref file_lines) = matches.opt_str("file-lines") { config.set().file_lines(file_lines.parse()?); for f in config.file_lines().files() { - if f != "stdin" { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f); + match *f { + FileName::Custom(ref f) if f == "stdin" => {} + _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), } } } @@ -264,8 +266,12 @@ fn execute(opts: &Options) -> FmtResult { let options = CliOptions::from_matches(&matches)?; for f in options.file_lines.files() { - if !files.contains(&PathBuf::from(f)) { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f); + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) + } + _ => eprintln!("Warning: Not a file '{}'", f), } } diff --git a/src/checkstyle.rs b/src/checkstyle.rs index cbb6573b322..7f6e650ad22 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::io::{self, Write}; +use std::path::Path; use config::WriteMode; use rustfmt_diff::{DiffLine, Mismatch}; @@ -41,13 +42,13 @@ where pub fn output_checkstyle_file( mut writer: T, - filename: &str, + filename: &Path, diff: Vec, ) -> Result<(), io::Error> where T: Write, { - write!(writer, "", filename)?; + write!(writer, "", filename.display())?; for mismatch in diff { for line in mismatch.lines { // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. diff --git a/src/codemap.rs b/src/codemap.rs index efbe50bcf64..e0401b0b197 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -13,7 +13,7 @@ use std::rc::Rc; -use syntax::codemap::{BytePos, CodeMap, FileMap, Span}; +use syntax::codemap::{BytePos, CodeMap, FileMap, FileName, Span}; use comment::FindUncommented; @@ -25,8 +25,8 @@ pub struct LineRange { } impl LineRange { - pub fn file_name(&self) -> &str { - self.file.as_ref().name.as_str() + pub fn file_name(&self) -> &FileName { + &self.file.name } } diff --git a/src/file_lines.rs b/src/file_lines.rs index a131038eb4e..82844a4b222 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -10,12 +10,14 @@ //! This module contains types and functions to support formatting specific line ranges. -use std::{cmp, iter, path, str}; +use std::{cmp, iter, str}; use std::collections::HashMap; +use serde::de::{Deserialize, Deserializer}; use serde_json as json; use codemap::LineRange; +use syntax::codemap::FileName; /// A range that is inclusive of both ends. #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] @@ -84,11 +86,11 @@ impl Range { /// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all /// lines in all files. #[derive(Clone, Debug, Default)] -pub struct FileLines(Option>>); +pub struct FileLines(Option>>); /// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, /// and ordered by their start point. -fn normalize_ranges(ranges: &mut HashMap>) { +fn normalize_ranges(ranges: &mut HashMap>) { for ranges in ranges.values_mut() { ranges.sort(); let mut result = vec![]; @@ -117,7 +119,7 @@ impl FileLines { FileLines(None) } - pub fn from_ranges(mut ranges: HashMap>) -> FileLines { + pub fn from_ranges(mut ranges: HashMap>) -> FileLines { normalize_ranges(&mut ranges); FileLines(Some(ranges)) } @@ -129,7 +131,7 @@ impl FileLines { /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in /// the designated file (if any) and returns true if `f` ever does. - fn file_range_matches(&self, file_name: &str, f: F) -> bool + fn file_range_matches(&self, file_name: &FileName, f: F) -> bool where F: FnMut(&Range) -> bool, { @@ -156,35 +158,31 @@ impl FileLines { } /// Returns true if `line` from `file_name` is in `self`. - pub fn contains_line(&self, file_name: &str, line: usize) -> bool { + pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool { self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) } /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. - pub fn intersects_range(&self, file_name: &str, lo: usize, hi: usize) -> bool { + pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) } } /// `FileLines` files iterator. -pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, String, Vec>>); +pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec>>); impl<'a> iter::Iterator for Files<'a> { - type Item = &'a String; + type Item = &'a FileName; - fn next(&mut self) -> Option<&'a String> { + fn next(&mut self) -> Option<&'a FileName> { self.0.as_mut().and_then(Iterator::next) } } -fn canonicalize_path_string(s: &str) -> Option { - if s == "stdin" { - return Some(s.to_string()); - } - - match path::PathBuf::from(s).canonicalize() { - Ok(canonicalized) => canonicalized.to_str().map(|s| s.to_string()), - _ => None, +fn canonicalize_path_string(file: &FileName) -> Option { + match *file { + FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real), + _ => Some(file.clone()), } } @@ -206,12 +204,21 @@ impl str::FromStr for FileLines { // For JSON decoding. #[derive(Clone, Debug, Deserialize)] struct JsonSpan { - file: String, + #[serde(deserialize_with = "deserialize_filename")] file: FileName, range: (usize, usize), } +fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { + let s = String::deserialize(d)?; + if s == "stdin" { + Ok(FileName::Custom(s)) + } else { + Ok(FileName::Real(s.into())) + } +} + impl JsonSpan { - fn into_tuple(self) -> Result<(String, Range), String> { + fn into_tuple(self) -> Result<(FileName, Range), String> { let (lo, hi) = self.range; let canonical = canonicalize_path_string(&self.file) .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; diff --git a/src/filemap.rs b/src/filemap.rs index c7fa5e2f1ef..5678dd59c55 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -12,15 +12,17 @@ use std::fs::{self, File}; use std::io::{self, BufWriter, Read, Write}; +use std::path::Path; use checkstyle::{output_checkstyle_file, output_footer, output_header}; use config::{Config, NewlineStyle, WriteMode}; use rustfmt_diff::{make_diff, print_diff, Mismatch}; +use syntax::codemap::FileName; // A map of the files of a crate, with their new content pub type FileMap = Vec; -pub type FileRecord = (String, String); +pub type FileRecord = (FileName, String); // Append a newline to the end of each file. pub fn append_newline(s: &mut String) { @@ -80,7 +82,7 @@ where pub fn write_file( text: &str, - filename: &str, + filename: &FileName, out: &mut T, config: &Config, ) -> Result @@ -89,7 +91,7 @@ where { fn source_and_formatted_text( text: &str, - filename: &str, + filename: &Path, config: &Config, ) -> Result<(String, String), io::Error> { let mut f = File::open(filename)?; @@ -102,7 +104,7 @@ where } fn create_diff( - filename: &str, + filename: &Path, text: &str, config: &Config, ) -> Result, io::Error> { @@ -110,15 +112,21 @@ where Ok(make_diff(&ori, &fmt, 3)) } + let filename_to_path = || match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` with WriteMode::Replace", filename), + }; + match config.write_mode() { WriteMode::Replace => { - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, &filename, config) { if fmt != ori { // Do a little dance to make writing safer - write to a temp file // rename the original to a .bk, then rename the temp file to the // original. - let tmp_name = filename.to_owned() + ".tmp"; - let bk_name = filename.to_owned() + ".bk"; + let tmp_name = filename.with_extension("tmp"); + let bk_name = filename.with_extension("bk"); { // Write text to temp file let tmp_file = File::create(&tmp_name)?; @@ -132,7 +140,8 @@ where } WriteMode::Overwrite => { // Write text directly over original file if there is a diff. - let (source, formatted) = source_and_formatted_text(text, filename, config)?; + let filename = filename_to_path(); + let (source, formatted) = source_and_formatted_text(text, &filename, config)?; if source != formatted { let file = File::create(filename)?; write_system_newlines(file, text, config)?; @@ -146,19 +155,21 @@ where write_system_newlines(out, text, config)?; } WriteMode::Diff => { - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, &filename, config) { let mismatch = make_diff(&ori, &fmt, 3); let has_diff = !mismatch.is_empty(); print_diff( mismatch, - |line_num| format!("Diff in {} at line {}:", filename, line_num), + |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), config.color(), ); return Ok(has_diff); } } WriteMode::Checkstyle => { - let diff = create_diff(filename, text, config)?; + let filename = filename_to_path(); + let diff = create_diff(&filename, text, config)?; output_checkstyle_file(out, filename, diff)?; } } diff --git a/src/lib.rs b/src/lib.rs index b00caf40cd5..14914359bdc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,13 +29,14 @@ use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, Write}; use std::iter::repeat; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::rc::Rc; use errors::{DiagnosticBuilder, Handler}; use errors::emitter::{ColorConfig, EmitterWriter}; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping}; +pub use syntax::codemap::FileName; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; @@ -146,7 +147,7 @@ impl FormattingError { pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. - file_error_map: HashMap>, + file_error_map: HashMap>, } impl FormatReport { @@ -295,12 +296,12 @@ impl fmt::Display for FormatReport { fn format_ast( krate: &ast::Crate, parse_session: &mut ParseSess, - main_file: &Path, + main_file: &FileName, config: &Config, mut after_file: F, ) -> Result<(FileMap, bool), io::Error> where - F: FnMut(&str, &mut String, &[(usize, usize)]) -> Result, + F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result, { let mut result = FileMap::new(); // diff mode: check if any files are differing @@ -310,12 +311,11 @@ where // nothing to distinguish the nested module contents. let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; for (path, module) in modules::list_files(krate, parse_session.codemap())? { - if skip_children && path.as_path() != main_file { + if skip_children && path != *main_file { continue; } - let path_str = path.to_str().unwrap(); if config.verbose() { - println!("Formatting {}", path_str); + println!("Formatting {}", path); } let filemap = parse_session .codemap() @@ -325,7 +325,7 @@ where let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); // Format inner attributes if available. - if !krate.attrs.is_empty() && path == main_file { + if !krate.attrs.is_empty() && path == *main_file { visitor.skip_empty_lines(filemap.end_pos); if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); @@ -343,16 +343,17 @@ where ::utils::count_newlines(&format!("{}", visitor.buffer)) ); - has_diff |= match after_file(path_str, &mut visitor.buffer, &visitor.skipped_range) { + let filename = path.clone(); + has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) { Ok(result) => result, Err(e) => { // Create a new error with path_str to help users see which files failed - let err_msg = path_str.to_string() + &": ".to_string() + &e.to_string(); + let err_msg = format!("{}: {}", path, e); return Err(io::Error::new(e.kind(), err_msg)); } }; - result.push((path_str.to_owned(), visitor.buffer)); + result.push((filename, visitor.buffer)); } Ok((result, has_diff)) @@ -389,7 +390,7 @@ fn should_report_error( // FIXME(#20) other stuff for parity with make tidy fn format_lines( text: &mut String, - name: &str, + name: &FileName, skipped_range: &[(usize, usize)], config: &Config, report: &mut FormatReport, @@ -491,7 +492,7 @@ fn format_lines( } } - report.file_error_map.insert(name.to_owned(), errors); + report.file_error_map.insert(name.clone(), errors); } fn parse_input( @@ -505,8 +506,11 @@ fn parse_input( parser.parse_crate_mod() } Input::Text(text) => { - let mut parser = - parse::new_parser_from_source_str(parse_session, "stdin".to_owned(), text); + let mut parser = parse::new_parser_from_source_str( + parse_session, + FileName::Custom("stdin".to_owned()), + text, + ); parser.cfg_mods = false; parser.parse_crate_mod() } @@ -547,8 +551,8 @@ pub fn format_input( let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); let main_file = match input { - Input::File(ref file) => file.clone(), - Input::Text(..) => PathBuf::from("stdin"), + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Custom("stdin".to_owned()), }; let krate = match parse_input(input, &parse_session) { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 4e1f2a37ef4..718ac6bfaab 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -11,7 +11,7 @@ use std::borrow::Cow; use std::iter::repeat; -use syntax::codemap::{BytePos, Pos, Span}; +use syntax::codemap::{BytePos, FileName, Pos, Span}; use codemap::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; @@ -260,7 +260,7 @@ impl<'a> FmtVisitor<'a> { snippet: &str, subslice: &str, offset: usize, - file_name: &str, + file_name: &FileName, ) { for (mut i, c) in subslice.char_indices() { i += offset; diff --git a/src/modules.rs b/src/modules.rs index 30deafd3f9e..ce63597b394 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -13,7 +13,7 @@ use std::path::{Path, PathBuf}; use std::io; use syntax::ast; -use syntax::codemap; +use syntax::codemap::{self, FileName}; use syntax::parse::parser; use utils::contains_skip; @@ -23,15 +23,16 @@ use utils::contains_skip; pub fn list_files<'a>( krate: &'a ast::Crate, codemap: &codemap::CodeMap, -) -> Result, io::Error> { +) -> Result, io::Error> { let mut result = BTreeMap::new(); // Enforce file order determinism - let root_filename: PathBuf = codemap.span_to_filename(krate.span).into(); - list_submodules( - &krate.module, - root_filename.parent().unwrap(), - codemap, - &mut result, - )?; + let root_filename = codemap.span_to_filename(krate.span); + { + let parent = match root_filename { + FileName::Real(ref path) => path.parent().unwrap(), + _ => Path::new(""), + }; + list_submodules(&krate.module, parent, codemap, &mut result)?; + } result.insert(root_filename, &krate.module); Ok(result) } @@ -41,7 +42,7 @@ fn list_submodules<'a>( module: &'a ast::Mod, search_dir: &Path, codemap: &codemap::CodeMap, - result: &mut BTreeMap, + result: &mut BTreeMap, ) -> Result<(), io::Error> { debug!("list_submodules: search_dir: {:?}", search_dir); for item in &module.items { @@ -54,7 +55,7 @@ fn list_submodules<'a>( } else { let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; let dir_path = mod_path.parent().unwrap().to_owned(); - result.insert(mod_path, sub_mod); + result.insert(FileName::Real(mod_path), sub_mod); dir_path }; list_submodules(sub_mod, &dir_path, codemap, result)?; diff --git a/tests/system.rs b/tests/system.rs index 3bb41b1cd6b..212e23f4f10 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_private)] + #[macro_use] extern crate log; extern crate regex; @@ -28,10 +30,8 @@ use rustfmt::rustfmt_diff::*; const DIFF_CONTEXT_SIZE: usize = 3; -fn get_path_string(dir_entry: io::Result) -> String { - let path = dir_entry.expect("Couldn't get DirEntry").path(); - - path.to_str().expect("Couldn't stringify path").to_owned() +fn get_path_string(dir_entry: io::Result) -> PathBuf { + dir_entry.expect("Couldn't get DirEntry").path().to_owned() } // Integration tests. The files in the tests/source are formatted and compared @@ -68,12 +68,12 @@ fn coverage_tests() { fn checkstyle_test() { let filename = "tests/writemode/source/fn-single-line.rs"; let expected_filename = "tests/writemode/target/checkstyle.xml"; - assert_output(filename, expected_filename); + assert_output(Path::new(filename), Path::new(expected_filename)); } // Helper function for comparing the results of rustfmt // to a known output file generated by one of the write modes. -fn assert_output(source: &str, expected_filename: &str) { +fn assert_output(source: &Path, expected_filename: &Path) { let config = read_config(source); let (file_map, _report) = format_file(source, &config); @@ -91,7 +91,7 @@ fn assert_output(source: &str, expected_filename: &str) { let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); if !compare.is_empty() { let mut failures = HashMap::new(); - failures.insert(source.to_string(), compare); + failures.insert(source.to_owned(), compare); print_mismatches(failures); assert!(false, "Text does not match expected output"); } @@ -121,8 +121,8 @@ fn self_tests() { .chain(fs::read_dir("tests").expect("Couldn't read tests dir")) .map(get_path_string); // Hack because there's no `IntoIterator` impl for `[T; N]`. - let files = files.chain(Some("src/lib.rs".to_owned()).into_iter()); - let files = files.chain(Some("build.rs".to_owned()).into_iter()); + let files = files.chain(Some(PathBuf::from("src/lib.rs")).into_iter()); + let files = files.chain(Some(PathBuf::from("build.rs")).into_iter()); let (reports, count, fails) = check_files(files); let mut warnings = 0; @@ -152,9 +152,11 @@ fn stdin_formatting_smoke_test() { format_input::(input, &config, None).unwrap(); assert!(error_summary.has_no_errors()); for &(ref file_name, ref text) in &file_map { - if file_name == "stdin" { - assert_eq!(text.to_string(), "fn main() {}\n"); - return; + if let FileName::Custom(ref file_name) = *file_name { + if file_name == "stdin" { + assert_eq!(text.to_string(), "fn main() {}\n"); + return; + } } } panic!("no stdin"); @@ -197,14 +199,14 @@ fn format_lines_errors_are_reported() { // Returns the number of files checked and the number of failures. fn check_files(files: I) -> (Vec, u32, u32) where - I: Iterator, + I: Iterator, { let mut count = 0; let mut fails = 0; let mut reports = vec![]; - for file_name in files.filter(|f| f.ends_with(".rs")) { - debug!("Testing '{}'...", file_name); + for file_name in files.filter(|f| f.extension().map_or(false, |f| f == "rs")) { + debug!("Testing '{}'...", file_name.display()); match idempotent_check(file_name) { Ok(ref report) if report.has_warnings() => { @@ -224,13 +226,13 @@ where (reports, count, fails) } -fn print_mismatches(result: HashMap>) { +fn print_mismatches(result: HashMap>) { let mut t = term::stdout().unwrap(); for (file_name, diff) in result { print_diff( diff, - |line_num| format!("\nMismatch at {}:{}:", file_name, line_num), + |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num), Color::Auto, ); } @@ -238,20 +240,15 @@ fn print_mismatches(result: HashMap>) { t.reset().unwrap(); } -fn read_config(filename: &str) -> Config { +fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); // Look for a config file... If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(|x| &(*x)[..])) + get_config(sig_comments.get("config").map(Path::new)) } else { - get_config( - Path::new(filename) - .with_extension("toml") - .file_name() - .and_then(std::ffi::OsStr::to_str), - ) + get_config(filename.with_extension("toml").file_name().map(Path::new)) }; for (key, val) in &sig_comments { @@ -274,7 +271,9 @@ fn format_file>(filepath: P, config: &Config) -> (FileMap, Form (file_map, report) } -pub fn idempotent_check(filename: String) -> Result>> { +pub fn idempotent_check( + filename: PathBuf, +) -> Result>> { let sig_comments = read_significant_comments(&filename); let config = read_config(&filename); let (file_map, format_report) = format_file(filename, &config); @@ -286,7 +285,9 @@ pub fn idempotent_check(filename: String) -> Result Result) -> Config { +fn get_config(config_file: Option<&Path>) -> Config { let config_file_name = match config_file { None => return Default::default(), Some(file_name) => { - let mut full_path = "tests/config/".to_owned(); - full_path.push_str(file_name); - if !Path::new(&full_path).exists() { + let mut full_path = PathBuf::from("tests/config/"); + full_path.push(file_name); + if !full_path.exists() { return Default::default(); }; full_path @@ -321,8 +322,9 @@ fn get_config(config_file: Option<&str>) -> Config { // Reads significant comments of the form: // rustfmt-key: value // into a hash map. -fn read_significant_comments(file_name: &str) -> HashMap { - let file = fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name)); +fn read_significant_comments(file_name: &Path) -> HashMap { + let file = + fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); let reader = BufReader::new(file); let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); @@ -357,9 +359,9 @@ fn read_significant_comments(file_name: &str) -> HashMap { // Compare output to input. // TODO: needs a better name, more explanation. fn handle_result( - result: HashMap, + result: HashMap, target: Option<&str>, -) -> Result<(), HashMap>> { +) -> Result<(), HashMap>> { let mut failures = HashMap::new(); for (file_name, fmt_text) in result { @@ -391,15 +393,21 @@ fn handle_result( } // Map source file paths to their target paths. -fn get_target(file_name: &str, target: Option<&str>) -> String { - if file_name.contains("source") { - let target_file_name = file_name.replace("source", "target"); +fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { + if let Some(n) = file_name + .components() + .position(|c| c.as_os_str() == "source") + { + let mut target_file_name = PathBuf::new(); + for (i, c) in file_name.components().enumerate() { + if i == n { + target_file_name.push("target"); + } else { + target_file_name.push(c.as_os_str()); + } + } if let Some(replace_name) = target { - Path::new(&target_file_name) - .with_file_name(replace_name) - .into_os_string() - .into_string() - .unwrap() + target_file_name.with_file_name(replace_name) } else { target_file_name } -- cgit 1.4.1-3-g733a5 From d60c2ec5d343a5b987e584e7e6e070a0b43302ba Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Dec 2017 10:35:07 +0900 Subject: Add an initial support for trait aliases --- src/visitor.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 8f6cab0e2df..a02baaf14da 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -373,6 +373,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = format_trait(&self.get_context(), item, self.block_indent); self.push_rewrite(item.span, rw); } + ast::ItemKind::TraitAlias(..) => { + // FIXME: #2283. + self.push_rewrite(item.span, None); + } ast::ItemKind::ExternCrate(_) => { let rw = rewrite_extern_crate(&self.get_context(), item); self.push_rewrite(item.span, rw); -- cgit 1.4.1-3-g733a5 From 3a98b5a5bee9234cb22e964864b11288a12bd67c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Dec 2017 13:47:52 +0900 Subject: Format trait aliases --- src/items.rs | 16 ++++++++++++++++ src/visitor.rs | 17 ++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7771344f3db..0c152d98767 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1087,6 +1087,22 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } +pub fn format_trait_alias( + context: &RewriteContext, + ident: ast::Ident, + generics: &ast::Generics, + ty_param_bounds: &ast::TyParamBounds, + shape: Shape, +) -> Option { + let alias = ident.name.as_str(); + // 6 = "trait ", 2 = " =" + let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?; + let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?; + let lhs = format!("trait {}{} =", alias, generics_str); + // 1 = ";" + rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") +} + fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { let header_str = format_header(p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { diff --git a/src/visitor.rs b/src/visitor.rs index a02baaf14da..ae9f7a091f9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -22,8 +22,8 @@ use comment::{combine_strs_with_missing_comments, contains_comment, remove_trail CodeCharKind, CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; -use items::{format_impl, format_trait, rewrite_associated_impl_type, rewrite_associated_type, - rewrite_type_alias, FnSig, StaticParts, StructParts}; +use items::{format_impl, format_trait, format_trait_alias, rewrite_associated_impl_type, + rewrite_associated_type, rewrite_type_alias, FnSig, StaticParts, StructParts}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use macros::{rewrite_macro, MacroPosition}; @@ -373,9 +373,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = format_trait(&self.get_context(), item, self.block_indent); self.push_rewrite(item.span, rw); } - ast::ItemKind::TraitAlias(..) => { - // FIXME: #2283. - self.push_rewrite(item.span, None); + ast::ItemKind::TraitAlias(ref generics, ref ty_param_bounds) => { + let shape = Shape::indented(self.block_indent, self.config); + let rw = format_trait_alias( + &self.get_context(), + item.ident, + generics, + ty_param_bounds, + shape, + ); + self.push_rewrite(item.span, rw); } ast::ItemKind::ExternCrate(_) => { let rw = rewrite_extern_crate(&self.get_context(), item); -- cgit 1.4.1-3-g733a5 From 81eb88c4c083eef44f6a821b99ef00dbe6b195df Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 17 Dec 2017 15:24:49 +0900 Subject: Respect leading whitespace in original comment when wrapping comment --- src/comment.rs | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 439a7f6a05f..6423ebca477 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -305,20 +305,29 @@ fn rewrite_comment_inner( line }) .map(|s| left_trim_comment_line(s, &style)) - .map(|line| { + .map(|(line, has_leading_whitespace)| { if orig.starts_with("/*") && line_breaks == 0 { - line.trim_left() + ( + line.trim_left(), + has_leading_whitespace || config.normalize_comments(), + ) } else { - line + (line, has_leading_whitespace || config.normalize_comments()) } }); - let mut result = opener.to_owned(); + let mut result = String::with_capacity(orig.len() * 2); + result.push_str(opener); let mut is_prev_line_multi_line = false; let mut inside_code_block = false; let comment_line_separator = format!("\n{}{}", indent_str, line_start); - for line in lines { + for (i, (line, has_leading_whitespace)) in lines.enumerate() { + let is_last = i == count_newlines(orig); if result == opener { + let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; + if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { + result.pop(); + } if line.is_empty() { continue; } @@ -326,6 +335,9 @@ fn rewrite_comment_inner( result.push(' ') } else { result.push_str(&comment_line_separator); + if !has_leading_whitespace && result.ends_with(' ') { + result.pop(); + } } if line.starts_with("```") { @@ -473,32 +485,33 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option< } /// Trims comment characters and possibly a single space from the left of a string. -/// Does not trim all whitespace. -fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str { +/// Does not trim all whitespace. If a single space is trimmed from the left of the string, +/// this function returns true. +fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") || line.starts_with("/** ") { - &line[4..] + (&line[4..], true) } else if let CommentStyle::Custom(opener) = *style { if line.starts_with(opener) { - &line[opener.len()..] + (&line[opener.len()..], true) } else { - &line[opener.trim_right().len()..] + (&line[opener.trim_right().len()..], false) } } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") || line.starts_with("///") || line.starts_with("** ") || line.starts_with("/*!") || (line.starts_with("/**") && !line.starts_with("/**/")) { - &line[3..] + (&line[3..], line.chars().nth(2).unwrap() == ' ') } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") || line.starts_with("**") { - &line[2..] + (&line[2..], line.chars().nth(1).unwrap() == ' ') } else if line.starts_with('*') { - &line[1..] + (&line[1..], false) } else { - line + (line, line.starts_with(' ')) } } -- cgit 1.4.1-3-g733a5 From ccc487ade798231a41cff965672c14d1a19145a4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 17 Dec 2017 15:25:24 +0900 Subject: Do not put comment's line start and closer on the same line --- src/comment.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 6423ebca477..441bb858e2a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -333,6 +333,9 @@ fn rewrite_comment_inner( } } else if is_prev_line_multi_line && !line.is_empty() { result.push(' ') + } else if is_last && !closer.is_empty() && line.is_empty() { + result.push('\n'); + result.push_str(&indent_str); } else { result.push_str(&comment_line_separator); if !has_leading_whitespace && result.ends_with(' ') { @@ -393,7 +396,7 @@ fn rewrite_comment_inner( Shape::legacy(max_chars, fmt_indent) }; } else { - if line.is_empty() && result.ends_with(' ') { + if line.is_empty() && result.ends_with(' ') && !is_last { // Remove space if this is an empty comment or a doc comment. result.pop(); } -- cgit 1.4.1-3-g733a5 From 366ff40ae7fed8380cb3a421d6924ddb6485c234 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 19 Dec 2017 09:41:05 +0900 Subject: Take the width of block's prefix into account only once --- src/expr.rs | 3 +-- tests/source/expr.rs | 6 ++++++ tests/target/closure.rs | 9 +++------ tests/target/expr.rs | 7 +++++++ 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8ef55b1716c..dc2743425ec 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -608,7 +608,7 @@ fn rewrite_single_line_block( shape: Shape, ) -> Option { if is_simple_block(block, context.codemap) { - let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent); + let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; let result = format!("{}{{ {} }}", prefix, expr_str); if result.len() <= shape.width && !result.contains('\n') { @@ -654,7 +654,6 @@ impl Rewrite for ast::Block { } let prefix = block_prefix(context, self, shape)?; - let shape = shape.offset_left(last_line_width(&prefix))?; let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); if let Some(ref result_str) = result { diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 06b31340d88..f87c950735f 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -108,6 +108,12 @@ fn baz() { unsafe { foo(); } + + // #2289 + let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; + let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; + let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; + let identifier_3 = unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; } // Test some empty blocks. diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 1912c16ef6e..5bc89d58222 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -123,9 +123,7 @@ fn foo() { fn issue1405() { open_raw_fd(fd, b'r').and_then(|file| { - Capture::new_raw(None, |_, err| unsafe { - raw::pcap_fopen_offline(file, err) - }) + Capture::new_raw(None, |_, err| unsafe { raw::pcap_fopen_offline(file, err) }) }); } @@ -176,9 +174,8 @@ fn issue1329() { } fn issue325() { - let f = || unsafe { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - }; + let f = + || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; } fn issue1697() { diff --git a/tests/target/expr.rs b/tests/target/expr.rs index edf83b66fc4..3c5d85b7d76 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -147,6 +147,13 @@ fn baz() { unsafe { foo(); } + + // #2289 + let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; + let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; + let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; + let identifier_3 = + unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; } // Test some empty blocks. -- cgit 1.4.1-3-g733a5 From 85ef4638b65a0443fca54f3cf6af55df923b1923 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 20 Dec 2017 22:46:24 +0900 Subject: Make 'cargo fmt' formats every workspace member --- CHANGELOG.md | 4 ++++ src/bin/cargo-fmt.rs | 11 ++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e399017f0d..0cf1ec76749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Changed + +- `cargo fmt` will format every workspace member. + ## [0.3.2] 2017-12-15 ### Changed diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3916b52fe5f..e45521de30b 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -240,7 +240,7 @@ fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> for package in metadata.packages { for target in package.targets { - if target.name == package.name { + if is_target_workspace_members(&target.name, &metadata.workspace_members) { targets.insert(Target::from_target(&target)); } } @@ -249,6 +249,15 @@ fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> Ok(()) } +fn is_target_workspace_members(target: &str, workspace_members: &[String]) -> bool { + workspace_members.iter().any(|member| { + member + .split_whitespace() + .nth(0) + .map_or(false, |name| name == target) + }) +} + fn get_targets_recursive( manifest_path: Option<&Path>, mut targets: &mut HashSet, -- cgit 1.4.1-3-g733a5 From 1d8619d49a2edd224541a6e243983ab7b4518b2b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 21 Dec 2017 09:58:13 +0900 Subject: Fix wrong indentation on type alias Use rewrite_assign_rhs() when rewriting type alias. --- src/expr.rs | 12 +++++++----- src/items.rs | 38 +++++++++++--------------------------- tests/target/type_alias.rs | 17 ++++++----------- 3 files changed, 24 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8ef55b1716c..6a543f14004 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2754,11 +2754,13 @@ pub fn rewrite_assign_rhs, R: Rewrite>( shape: Shape, ) -> Option { let lhs = lhs.into(); - let last_line_width = last_line_width(&lhs) - if lhs.contains('\n') { - shape.indent.width() - } else { - 0 - }; + let last_line_width = last_line_width(&lhs) + .checked_sub(if lhs.contains('\n') { + shape.indent.width() + } else { + 0 + }) + .unwrap_or(0); // 1 = space between operator and rhs. let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { width: 0, diff --git a/src/items.rs b/src/items.rs index 0c152d98767..66b9d81e163 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1365,9 +1365,11 @@ pub fn rewrite_type_alias( result.push_str(&ident.to_string()); // 2 = `= ` - let shape = Shape::indented(indent + result.len(), context.config).sub_width(2)?; + let g_shape = Shape::indented(indent, context.config) + .offset_left(result.len())? + .sub_width(2)?; let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo()); - let generics_str = rewrite_generics(context, generics, shape, g_span)?; + let generics_str = rewrite_generics(context, generics, g_shape, g_span)?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1386,32 +1388,14 @@ pub fn rewrite_type_alias( )?; result.push_str(&where_clause_str); if where_clause_str.is_empty() { - result.push_str(" = "); + result.push_str(" ="); } else { - result.push_str(&format!("\n{}= ", indent.to_string(context.config))); - } - - let line_width = last_line_width(&result); - // This checked_sub may fail as the extra space after '=' is not taken into account - // In that case the budget is set to 0 which will make ty.rewrite retry on a new line - let budget = context.budget(indent.width() + line_width + ";".len()); - let type_indent = indent + line_width; - // Try to fit the type on the same line - let ty_str = ty.rewrite(context, Shape::legacy(budget, type_indent)) - .or_else(|| { - // The line was too short, try to put the type on the next line - - // Remove the space after '=' - result.pop(); - let type_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&type_indent.to_string(context.config)); - let budget = context.budget(type_indent.width() + ";".len()); - ty.rewrite(context, Shape::legacy(budget, type_indent)) - })?; - result.push_str(&ty_str); - result.push_str(";"); - Some(result) + result.push_str(&format!("\n{}=", indent.to_string(context.config))); + } + + // 1 = ";" + let ty_shape = Shape::indented(indent, context.config).sub_width(1)?; + rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";") } fn type_annotation_spacing(config: &Config) -> (&str, &str) { diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs index 8833be9e1a0..862f9ecbeec 100644 --- a/tests/target/type_alias.rs +++ b/tests/target/type_alias.rs @@ -26,9 +26,8 @@ pub type LongGenericListTest< pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; -pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec< - Test, ->; +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = + Vec; pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; @@ -71,11 +70,7 @@ where type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); // #1683 -pub type Between = super::operators::Between< - Lhs, - super::operators::And, AsExpr>, ->; -pub type NotBetween = super::operators::NotBetween< - Lhs, - super::operators::And, AsExpr>, ->; +pub type Between = + super::operators::Between, AsExpr>>; +pub type NotBetween = + super::operators::NotBetween, AsExpr>>; -- cgit 1.4.1-3-g733a5 From 6aaed5b08f54ed95b692d40733a551d925363319 Mon Sep 17 00:00:00 2001 From: David Alber Date: Wed, 20 Dec 2017 21:48:59 -0800 Subject: Adding --version option to cargo-fmt --- src/bin/cargo-fmt.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 3916b52fe5f..15d0bbe950c 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -49,6 +49,7 @@ fn execute() -> i32 { "specify package to format (only usable in workspaces)", "", ); + opts.optflag("", "version", "print rustfmt version and exit"); opts.optflag("", "all", "format all packages (only usable in workspaces)"); // If there is any invalid argument passed to `cargo fmt`, return without formatting. @@ -87,6 +88,10 @@ fn execute() -> i32 { return success; } + if matches.opt_present("version") { + return handle_command_status(get_version(), &opts); + } + let strategy = CargoFmtStrategy::from_matches(&matches); match format_crate(verbosity, &strategy) { @@ -130,6 +135,40 @@ pub enum Verbosity { Quiet, } +fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { + let success = 0; + let failure = 1; + + match status { + Err(e) => { + print_usage_to_stderr(&opts, &e.to_string()); + failure + } + Ok(status) => { + if status.success() { + success + } else { + status.code().unwrap_or(failure) + } + } + } +} + +fn get_version() -> Result { + let mut command = Command::new("rustfmt") + .args(vec!["--version"]) + .spawn() + .map_err(|e| match e.kind() { + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), + _ => e, + })?; + + command.wait() +} + fn format_crate( verbosity: Verbosity, strategy: &CargoFmtStrategy, -- cgit 1.4.1-3-g733a5 From 655022c42b267b1337ac12c4b7776087dfdeaac7 Mon Sep 17 00:00:00 2001 From: David Alber Date: Wed, 20 Dec 2017 21:53:33 -0800 Subject: Factoring out status code values --- src/bin/cargo-fmt.rs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 15d0bbe950c..aeb05e90c54 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -35,10 +35,10 @@ fn main() { std::process::exit(exit_status); } -fn execute() -> i32 { - let success = 0; - let failure = 1; +const SUCCESS: i32 = 0; +const FAILURE: i32 = 1; +fn execute() -> i32 { let mut opts = getopts::Options::new(); opts.optflag("h", "help", "show this message"); opts.optflag("q", "quiet", "no output printed to stdout"); @@ -59,7 +59,7 @@ fn execute() -> i32 { is_package_arg = arg.starts_with("--package"); } else if !is_package_arg { print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); - return failure; + return FAILURE; } else { is_package_arg = false; } @@ -69,7 +69,7 @@ fn execute() -> i32 { Ok(m) => m, Err(e) => { print_usage_to_stderr(&opts, &e.to_string()); - return failure; + return FAILURE; } }; @@ -79,13 +79,13 @@ fn execute() -> i32 { (true, false) => Verbosity::Verbose, (true, true) => { print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); - return failure; + return FAILURE; } }; if matches.opt_present("h") { print_usage_to_stdout(&opts, ""); - return success; + return SUCCESS; } if matches.opt_present("version") { @@ -97,13 +97,13 @@ fn execute() -> i32 { match format_crate(verbosity, &strategy) { Err(e) => { print_usage_to_stderr(&opts, &e.to_string()); - failure + FAILURE } Ok(status) => { if status.success() { - success + SUCCESS } else { - status.code().unwrap_or(failure) + status.code().unwrap_or(FAILURE) } } } @@ -136,19 +136,16 @@ pub enum Verbosity { } fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { - let success = 0; - let failure = 1; - match status { Err(e) => { print_usage_to_stderr(&opts, &e.to_string()); - failure + FAILURE } Ok(status) => { if status.success() { - success + SUCCESS } else { - status.code().unwrap_or(failure) + status.code().unwrap_or(FAILURE) } } } -- cgit 1.4.1-3-g733a5 From f17556966c3a30b14254ead7d1447a2ed949f151 Mon Sep 17 00:00:00 2001 From: David Alber Date: Wed, 20 Dec 2017 22:36:36 -0800 Subject: Reusing status-handling function --- src/bin/cargo-fmt.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index aeb05e90c54..efcdc397307 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -93,20 +93,7 @@ fn execute() -> i32 { } let strategy = CargoFmtStrategy::from_matches(&matches); - - match format_crate(verbosity, &strategy) { - Err(e) => { - print_usage_to_stderr(&opts, &e.to_string()); - FAILURE - } - Ok(status) => { - if status.success() { - SUCCESS - } else { - status.code().unwrap_or(FAILURE) - } - } - } + handle_command_status(format_crate(verbosity, &strategy), &opts) } macro_rules! print_usage { -- cgit 1.4.1-3-g733a5 From 09d0ca48920cafafe8e1a053ae355ee6edf9e7b7 Mon Sep 17 00:00:00 2001 From: David Alber Date: Wed, 20 Dec 2017 23:15:14 -0800 Subject: Using common execute rustfmt function --- src/bin/cargo-fmt.rs | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index efcdc397307..973e0aa3d78 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -89,7 +89,7 @@ fn execute() -> i32 { } if matches.opt_present("version") { - return handle_command_status(get_version(), &opts); + return handle_command_status(get_version(verbosity), &opts); } let strategy = CargoFmtStrategy::from_matches(&matches); @@ -138,19 +138,8 @@ fn handle_command_status(status: Result, opts: &getopts:: } } -fn get_version() -> Result { - let mut command = Command::new("rustfmt") - .args(vec!["--version"]) - .spawn() - .map_err(|e| match e.kind() { - io::ErrorKind::NotFound => io::Error::new( - io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your PATH.", - ), - _ => e, - })?; - - command.wait() +fn get_version(verbosity: Verbosity) -> Result { + run_rustfmt(&vec![], &vec![String::from("--version")], verbosity) } fn format_crate( @@ -175,7 +164,7 @@ fn format_crate( .map(|t| t.path) .collect(); - format_files(&files, &rustfmt_args, verbosity) + run_rustfmt(&files, &rustfmt_args, verbosity) } fn get_fmt_args() -> Vec { @@ -337,7 +326,7 @@ fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet Date: Fri, 22 Dec 2017 11:12:11 +1300 Subject: fix libsyntax fallout --- src/modules.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index ce63597b394..81414ee175e 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -76,7 +76,7 @@ fn module_file( return Ok(path); } - match parser::Parser::default_submod_path(id, dir_path, codemap).result { + match parser::Parser::default_submod_path(id, None, dir_path, codemap).result { Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), Err(_) => Err(io::Error::new( io::ErrorKind::Other, -- cgit 1.4.1-3-g733a5 From fa67631b32fcc21e2739df29b888841a8aa817a2 Mon Sep 17 00:00:00 2001 From: Bastian Köcher Date: Fri, 22 Dec 2017 02:52:22 +0100 Subject: Fixes compilation with rust version 2017-12-21 --- src/items.rs | 20 ++++++++++++++++---- src/types.rs | 26 +++++++++++++++++++------- 2 files changed, 35 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 66b9d81e163..13b4c0e4940 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1869,7 +1869,12 @@ fn rewrite_fn_base( // A conservative estimation, to goal is to be over all parens in generics let args_start = fn_sig .generics - .ty_params + .params + .iter() + .filter_map(|p| match p { + &ast::GenericParam::Type(ref t) => Some(t), + _ => None, + }) .last() .map_or(lo_after_visibility, |tp| end_typaram(tp)); let args_end = if fd.inputs.is_empty() { @@ -2363,15 +2368,22 @@ fn rewrite_generics_inner( } } - if generics.lifetimes.is_empty() && generics.ty_params.is_empty() { + if generics.params.is_empty() { return Some(String::new()); } let generics_args = generics - .lifetimes + .params .iter() + .filter_map(|p| match p { + &ast::GenericParam::Lifetime(ref l) => Some(l), + _ => None, + }) .map(|lt| GenericsArg::Lifetime(lt)) - .chain(generics.ty_params.iter().map(|ty| GenericsArg::TyParam(ty))); + .chain(generics.params.iter().filter_map(|ty| match ty { + &ast::GenericParam::Type(ref ty) => Some(GenericsArg::TyParam(ty)), + _ => None, + })); let items = itemize_list( context.codemap, generics_args, diff --git a/src/types.rs b/src/types.rs index 88f9dba5c3f..d07af7376f1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -413,7 +413,7 @@ impl Rewrite for ast::WherePredicate { // TODO: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_lifetimes, + ref bound_generic_params, ref bounded_ty, ref bounds, .. @@ -422,9 +422,13 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); - if !bound_lifetimes.is_empty() { - let lifetime_str: String = bound_lifetimes + if bound_generic_params.iter().filter(|p| p.is_lifetime_param()).count() > 0 { + let lifetime_str: String = bound_generic_params .iter() + .filter_map(|p| match p { + &ast::GenericParam::Lifetime(ref l) => Some(l), + _ => None, + }) .map(|lt| lt.rewrite(context, shape)) .collect::>>()? .join(", "); @@ -590,9 +594,13 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if !self.bound_lifetimes.is_empty() { - let lifetime_str: String = self.bound_lifetimes + if self.bound_generic_params.iter().filter(|p| p.is_lifetime_param()).count() > 0 { + let lifetime_str: String = self.bound_generic_params .iter() + .filter_map(|p| match p { + &ast::GenericParam::Lifetime(ref l) => Some(l), + _ => None, + }) .map(|lt| lt.rewrite(context, shape)) .collect::>>()? .join(", "); @@ -746,14 +754,18 @@ fn rewrite_bare_fn( ) -> Option { let mut result = String::with_capacity(128); - if !bare_fn.lifetimes.is_empty() { + if bare_fn.generic_params.iter().filter(|p| p.is_lifetime_param()).count() > 0 { result.push_str("for<"); // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. result.push_str(&bare_fn - .lifetimes + .generic_params .iter() + .filter_map(|p| match p { + &ast::GenericParam::Lifetime(ref l) => Some(l), + _ => None, + }) .map(|l| { l.rewrite( context, -- cgit 1.4.1-3-g733a5 From de5683cf11b90c706a18c1061632bb4c569dd7f4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Dec 2017 15:30:45 +1300 Subject: fix tests --- src/types.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index d07af7376f1..a1156a7b4bb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -422,7 +422,11 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); - if bound_generic_params.iter().filter(|p| p.is_lifetime_param()).count() > 0 { + if bound_generic_params + .iter() + .filter(|p| p.is_lifetime_param()) + .count() > 0 + { let lifetime_str: String = bound_generic_params .iter() .filter_map(|p| match p { @@ -594,7 +598,11 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if self.bound_generic_params.iter().filter(|p| p.is_lifetime_param()).count() > 0 { + if self.bound_generic_params + .iter() + .filter(|p| p.is_lifetime_param()) + .count() > 0 + { let lifetime_str: String = self.bound_generic_params .iter() .filter_map(|p| match p { @@ -754,7 +762,12 @@ fn rewrite_bare_fn( ) -> Option { let mut result = String::with_capacity(128); - if bare_fn.generic_params.iter().filter(|p| p.is_lifetime_param()).count() > 0 { + if bare_fn + .generic_params + .iter() + .filter(|p| p.is_lifetime_param()) + .count() > 0 + { result.push_str("for<"); // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for mutliline situation with lots of -- cgit 1.4.1-3-g733a5 From 984ac100a4072b7f64898913afa70e71c65c79da Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 22 Dec 2017 12:00:24 +0900 Subject: Fix indent width bug when recovering comments Using last_line_width() ignores the width of tab character ('\t'). --- src/missed_spans.rs | 7 ++++--- tests/source/hard-tabs.rs | 11 +++++++++++ tests/target/hard-tabs.rs | 11 +++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 718ac6bfaab..dff6b94bd75 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -210,21 +210,22 @@ impl<'a> FmtVisitor<'a> { let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - if fix_indent { + let comment_indent = if fix_indent { if let Some('{') = last_char { self.push_str("\n"); } let indent_str = self.block_indent.to_string(self.config); self.push_str(&indent_str); + self.block_indent } else { self.push_str(" "); - } + Indent::from_width(self.config, last_line_width(&self.buffer)) + }; let comment_width = ::std::cmp::min( self.config.comment_width(), self.config.max_width() - self.block_indent.width(), ); - let comment_indent = Indent::from_width(self.config, last_line_width(&self.buffer)); let comment_shape = Shape::legacy(comment_width, comment_indent); let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) .unwrap_or_else(|| String::from(subslice)); diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs index f598ad881d0..b8fd09f8792 100644 --- a/tests/source/hard-tabs.rs +++ b/tests/source/hard-tabs.rs @@ -72,3 +72,14 @@ fn generic(arg: T) -> &SomeType } }); } + +// #2296 +impl Foo { + // a comment + // on multiple lines + fn foo() { + // another comment + // on multiple lines + let x = true; + } +} diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs index 72d366b1fa1..90be4d6b367 100644 --- a/tests/target/hard-tabs.rs +++ b/tests/target/hard-tabs.rs @@ -86,3 +86,14 @@ fn main() { false => (), }); } + +// #2296 +impl Foo { + // a comment + // on multiple lines + fn foo() { + // another comment + // on multiple lines + let x = true; + } +} -- cgit 1.4.1-3-g733a5 From e343521276897715e3bab70133cdf27eb0853c0e Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 23 Dec 2017 01:06:17 +0000 Subject: Add assert_eq! to special-cased macros Allows for this form of assert_eq! macros: ```rust assert_eq!( left.id, right.id, "IDs are not equal: {:?} {:?}", left, right ); ``` Also allows for assert! macros to have the format arguments split across multiple lines even if the assert condition is not simple: ```rust assert!( result >= 42, "The result must be at least 42: {:?}", result, result.code, context ); ``` --- src/codemap.rs | 6 +-- src/expr.rs | 102 +++++++++++++++++++++++++++++-------------------- src/lists.rs | 45 ++++++++++++---------- tests/source/macros.rs | 15 +++++--- tests/system.rs | 3 +- tests/target/macros.rs | 55 +++++++++++++++++++++++--- 6 files changed, 147 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs index e0401b0b197..5a8d43a072f 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -86,11 +86,9 @@ impl LineRangeUtils for CodeMap { let hi = self.lookup_char_pos(span.hi()); assert_eq!( - lo.file.name, - hi.file.name, + lo.file.name, hi.file.name, "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, - hi + lo, hi ); LineRange { diff --git a/src/expr.rs b/src/expr.rs index 45804b5b701..43e153bbe64 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1811,25 +1811,34 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } -const FORMAT_LIKE_WHITELIST: &[&str] = &[ +const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ + // format! like macros // From the Rust Standard Library. - "eprint!", - "eprintln!", - "format!", - "format_args!", - "print!", - "println!", - "panic!", - "unreachable!", + ("eprint!", 0), + ("eprintln!", 0), + ("format!", 0), + ("format_args!", 0), + ("print!", 0), + ("println!", 0), + ("panic!", 0), + ("unreachable!", 0), // From the `log` crate. - "debug!", - "error!", - "info!", - "warn!", + ("debug!", 0), + ("error!", 0), + ("info!", 0), + ("warn!", 0), + // write! like macros + ("assert!", 1), + ("debug_assert!", 1), + ("write!", 1), + ("writeln!", 1), + // assert_eq! like macros + ("assert_eq!", 2), + ("assert_ne!", 2), + ("debug_assert_eq!", 2), + ("debug_assert_ne!", 2), ]; -const WRITE_LIKE_WHITELIST: &[&str] = &["assert!", "write!", "writeln!"]; - pub fn rewrite_call( context: &RewriteContext, callee: &str, @@ -2066,25 +2075,31 @@ where } else { tactic = default_tactic(); - // For special-case macros, we may want to use different tactics. - let maybe_args_offset = maybe_get_args_offset(callee_str, args); - - if tactic == DefinitiveListTactic::Vertical && maybe_args_offset.is_some() { - let args_offset = maybe_args_offset.unwrap(); - let args_tactic = definitive_tactic( - &item_vec[args_offset..], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ); - - // Every argument is simple and fits on a single line. - if args_tactic == DefinitiveListTactic::Horizontal { - tactic = if args_offset == 1 { - DefinitiveListTactic::FormatCall - } else { - DefinitiveListTactic::WriteCall - }; + if tactic == DefinitiveListTactic::Vertical { + if let Some((all_simple_before, all_simple_after, num_args_before)) = + maybe_get_args_offset(callee_str, args) + { + let one_line_before = all_simple_before + && definitive_tactic( + &item_vec[..num_args_before - 1], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ) == DefinitiveListTactic::Horizontal; + + let one_line_after = all_simple_after + && definitive_tactic( + &item_vec[num_args_before + 1..], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ) == DefinitiveListTactic::Horizontal; + + tactic = DefinitiveListTactic::SpecialMacro( + one_line_before, + one_line_after, + num_args_before, + ); } } } @@ -2120,15 +2135,18 @@ fn is_every_args_simple(lists: &[&T]) -> bool { } /// In case special-case style is required, returns an offset from which we start horizontal layout. -fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option { - if FORMAT_LIKE_WHITELIST.iter().any(|s| *s == callee_str) && args.len() >= 1 - && is_every_args_simple(args) - { - Some(1) - } else if WRITE_LIKE_WHITELIST.iter().any(|s| *s == callee_str) && args.len() >= 2 - && is_every_args_simple(args) +fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, bool, usize)> { + if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST + .iter() + .find(|&&(s, _)| s == callee_str) { - Some(2) + let all_simple_before = num_args_before >= 1 && args.len() >= num_args_before + && is_every_args_simple(&args[..num_args_before]); + + let all_simple_after = + args.len() >= num_args_before + 1 && is_every_args_simple(&args[num_args_before + 1..]); + + Some((all_simple_before, all_simple_after, num_args_before)) } else { None } diff --git a/src/lists.rs b/src/lists.rs index 12840e26d5d..e167c638a53 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -160,10 +160,8 @@ pub enum DefinitiveListTactic { Vertical, Horizontal, Mixed, - // Special case tactic for `format!()` variants. - FormatCall, - // Special case tactic for `write!()` varianta. - WriteCall, + // Special case tactic for `format!()`, `write!()` style macros. + SpecialMacro(bool, bool, usize), } impl DefinitiveListTactic { @@ -271,7 +269,7 @@ where I: IntoIterator + Clone, T: AsRef, { - let mut tactic = formatting.tactic; + let tactic = formatting.tactic; let sep_len = formatting.separator.len(); // Now that we know how we will layout, we can decide for sure if there @@ -313,26 +311,33 @@ where DefinitiveListTactic::Horizontal if !first => { result.push(' '); } - DefinitiveListTactic::FormatCall if !first => { - result.push('\n'); - result.push_str(indent_str); - tactic = DefinitiveListTactic::Horizontal; - } - DefinitiveListTactic::WriteCall => { - let second = i == 1; - let third = i == 2; - - if first { + DefinitiveListTactic::SpecialMacro( + one_line_before, + one_line_after, + num_args_before, + ) => { + if i == 0 { // Nothing - } else if second { + } else if i < num_args_before { + if one_line_before { + result.push(' '); + } else { + result.push('\n'); + result.push_str(indent_str); + } + } else if i == num_args_before { result.push('\n'); result.push_str(indent_str); - } else if third { + } else if i == num_args_before + 1 { result.push('\n'); result.push_str(indent_str); - tactic = DefinitiveListTactic::Horizontal; - } else { - unreachable!(); + } else if i > num_args_before + 1 { + if one_line_after { + result.push(' '); + } else { + result.push('\n'); + result.push_str(indent_str); + } } } DefinitiveListTactic::Vertical if !first => { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index db3c04f0d9b..8d02eb67fcb 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -266,16 +266,21 @@ fn special_case_macros() { warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - assert!(result, "Ahoy there, {}!", target); - assert!(result, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert!(result, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + assert!(result == 42, "Ahoy there, {}!", target); + assert!(result == 42, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + assert_eq!(left, right, "Ahoy there, {}!", target); + assert_eq!(left, right, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + assert_eq!(left + 42, right, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); write!(&mut s, "Ahoy there, {}!", target); - write!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + write!(&mut s, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); write!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); writeln!(&mut s, "Ahoy there, {}!", target); - writeln!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + writeln!(&mut s, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); writeln!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); } diff --git a/tests/system.rs b/tests/system.rs index c1d838169ae..98f19d896e0 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -137,8 +137,7 @@ fn self_tests() { } assert_eq!( - warnings, - 0, + warnings, 0, "Rustfmt's code generated {} warnings", warnings ); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 6897d4c8796..3a9d200bde7 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -691,14 +691,57 @@ fn special_case_macros() { 26 ); - assert!(result, "Ahoy there, {}!", target); + assert!(result == 42, "Ahoy there, {}!", target); assert!( - result, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result == 42, + "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected ); assert!( - result, + result == 42, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + assert_eq!(left, right, "Ahoy there, {}!", target); + assert_eq!( + left, right, + "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", + result, input, expected + ); + assert_eq!( + left + 42, + right, + "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", + result, input, expected + ); + assert_eq!( + left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, @@ -731,7 +774,7 @@ fn special_case_macros() { write!(&mut s, "Ahoy there, {}!", target); write!( &mut s, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected ); write!( @@ -768,7 +811,7 @@ fn special_case_macros() { writeln!(&mut s, "Ahoy there, {}!", target); writeln!( &mut s, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected ); writeln!( -- cgit 1.4.1-3-g733a5 From ef8b2efd135c79ddabcb707b06dabc1af08b7bed Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 23 Dec 2017 01:32:55 +0000 Subject: Fix off-by-one error in assert_eq! line wrapping If two really long conditions are checked for equality, they wouldn't be split into multiple lines if the last condition is the one to push the line past the width limit. Fix the off-by-one error that caused this, and add a test-case for it. --- src/expr.rs | 6 +++--- tests/source/macros.rs | 1 + tests/target/macros.rs | 6 ++++++ 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 43e153bbe64..45dabaf7f88 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2081,7 +2081,7 @@ where { let one_line_before = all_simple_before && definitive_tactic( - &item_vec[..num_args_before - 1], + &item_vec[..num_args_before], ListTactic::HorizontalVertical, Separator::Comma, nested_shape.width, @@ -2140,8 +2140,8 @@ fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bo .iter() .find(|&&(s, _)| s == callee_str) { - let all_simple_before = num_args_before >= 1 && args.len() >= num_args_before - && is_every_args_simple(&args[..num_args_before]); + let all_simple_before = + args.len() >= num_args_before && is_every_args_simple(&args[..num_args_before]); let all_simple_after = args.len() >= num_args_before + 1 && is_every_args_simple(&args[num_args_before + 1..]); diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 8d02eb67fcb..4862c4f107d 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -272,6 +272,7 @@ fn special_case_macros() { assert_eq!(left, right, "Ahoy there, {}!", target); assert_eq!(left, right, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); assert_eq!(left + 42, right, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 3a9d200bde7..933fe000c9f 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -734,6 +734,12 @@ fn special_case_macros() { "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected ); + assert_eq!( + first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, + second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, + "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", + result, input, expected + ); assert_eq!( left + 42, right, -- cgit 1.4.1-3-g733a5 From 02bb1c8c973689a9ee3ac89a2d41b9b1576bb2db Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 23 Dec 2017 11:58:19 +0900 Subject: Rustup to rustc 1.24.0-nightly (5165ee9e2 2017-12-22) --- src/closures.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index cfc75664f30..f63242f6355 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -135,6 +135,7 @@ fn rewrite_closure_with_block( id: ast::NodeId::new(0), rules: ast::BlockCheckMode::Default, span: body.span, + recovered: false, }; let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; Some(format!("{} {}", prefix, block)) -- cgit 1.4.1-3-g733a5 From 0ef2b99b745cd85c10a1a5d8d4e048a9a00a1e08 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 23 Dec 2017 12:24:58 +0900 Subject: Remove workspace membership check --- src/bin/cargo-fmt.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index dda99b43d4b..270ed1446d6 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -252,24 +252,13 @@ fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> for package in metadata.packages { for target in package.targets { - if is_target_workspace_members(&target.name, &metadata.workspace_members) { - targets.insert(Target::from_target(&target)); - } + targets.insert(Target::from_target(&target)); } } Ok(()) } -fn is_target_workspace_members(target: &str, workspace_members: &[String]) -> bool { - workspace_members.iter().any(|member| { - member - .split_whitespace() - .nth(0) - .map_or(false, |name| name == target) - }) -} - fn get_targets_recursive( manifest_path: Option<&Path>, mut targets: &mut HashSet, -- cgit 1.4.1-3-g733a5 From 1ef6bccea37839b3d33cbadc15e5e243b6371ea5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 24 Dec 2017 00:28:58 +0900 Subject: Cargo fmt Run 'cargo fmt' with the following setting: ``` reorder_imports = true reorder_imports_in_group = true ``` --- src/chains.rs | 2 +- src/config.rs | 2 +- src/expr.rs | 4 ++-- src/filemap.rs | 8 ++++---- src/imports.rs | 2 +- src/items.rs | 2 +- src/modules.rs | 2 +- src/patterns.rs | 2 +- src/types.rs | 2 +- src/vertical.rs | 2 +- src/visitor.rs | 4 ++-- 11 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f63ddd44c1d..383e7077d66 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -59,11 +59,11 @@ //! .qux //! ``` -use shape::Shape; use config::IndentStyle; use expr::rewrite_call; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, wrap_str}; diff --git a/src/config.rs b/src/config.rs index 67ca3f6c3ad..bdf39ed6a2c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,9 +17,9 @@ use std::fs::File; use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; +use Summary; use file_lines::FileLines; use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; -use Summary; /// Check if we're in a nightly build. /// diff --git a/src/expr.rs b/src/expr.rs index 45804b5b701..3d9e7b502da 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -8,14 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cmp::min; use std::borrow::Cow; +use std::cmp::min; use std::iter::{repeat, ExactSizeIterator}; use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; -use spanned::Spanned; use chains::rewrite_chain; use closures; use codemap::{LineRangeUtils, SpanUtils}; @@ -29,6 +28,7 @@ use macros::{rewrite_macro, MacroArg, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, diff --git a/src/filemap.rs b/src/filemap.rs index 5678dd59c55..81f950cfb9b 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -120,7 +120,7 @@ where match config.write_mode() { WriteMode::Replace => { let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, &filename, config) { + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { if fmt != ori { // Do a little dance to make writing safer - write to a temp file // rename the original to a .bk, then rename the temp file to the @@ -141,7 +141,7 @@ where WriteMode::Overwrite => { // Write text directly over original file if there is a diff. let filename = filename_to_path(); - let (source, formatted) = source_and_formatted_text(text, &filename, config)?; + let (source, formatted) = source_and_formatted_text(text, filename, config)?; if source != formatted { let file = File::create(filename)?; write_system_newlines(file, text, config)?; @@ -156,7 +156,7 @@ where } WriteMode::Diff => { let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, &filename, config) { + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { let mismatch = make_diff(&ori, &fmt, 3); let has_diff = !mismatch.is_empty(); print_diff( @@ -169,7 +169,7 @@ where } WriteMode::Checkstyle => { let filename = filename_to_path(); - let diff = create_diff(&filename, text, config)?; + let diff = create_diff(filename, text, config)?; output_checkstyle_file(out, filename, diff)?; } } diff --git a/src/imports.rs b/src/imports.rs index 53ccd67b792..dac748af9b1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -13,7 +13,6 @@ use std::cmp::Ordering; use syntax::ast; use syntax::codemap::{BytePos, Span}; -use spanned::Spanned; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; use config::IndentStyle; @@ -21,6 +20,7 @@ use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, L ListItem, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use spanned::Spanned; use types::{rewrite_path, PathContext}; use utils::{format_visibility, mk_sp}; use visitor::{rewrite_extern_crate, FmtVisitor}; diff --git a/src/items.rs b/src/items.rs index 13b4c0e4940..35dd5c39d38 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,7 +18,6 @@ use syntax::ast::{CrateSugar, ImplItem}; use syntax::codemap::{BytePos, Span}; use syntax::visit; -use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; @@ -29,6 +28,7 @@ use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, L ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use spanned::Spanned; use types::join_bounds; use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, diff --git a/src/modules.rs b/src/modules.rs index 81414ee175e..0f439910324 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -9,8 +9,8 @@ // except according to those terms. use std::collections::BTreeMap; -use std::path::{Path, PathBuf}; use std::io; +use std::path::{Path, PathBuf}; use syntax::ast; use syntax::codemap::{self, FileName}; diff --git a/src/patterns.rs b/src/patterns.rs index 700fbd0da21..f877239f518 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -12,7 +12,6 @@ use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSynt use syntax::codemap::{self, BytePos, Span}; use syntax::ptr; -use spanned::Spanned; use codemap::SpanUtils; use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, @@ -22,6 +21,7 @@ use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_sh use macros::{rewrite_macro, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use spanned::Spanned; use types::{rewrite_path, PathContext}; use utils::{format_mutability, mk_sp}; diff --git a/src/types.rs b/src/types.rs index a1156a7b4bb..77dffd3cd89 100644 --- a/src/types.rs +++ b/src/types.rs @@ -16,7 +16,6 @@ use syntax::codemap::{self, BytePos, Span}; use syntax::print::pprust; use syntax::symbol::keywords; -use spanned::Spanned; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; @@ -26,6 +25,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTac use macros::{rewrite_macro, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use spanned::Spanned; use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_width, mk_sp}; diff --git a/src/vertical.rs b/src/vertical.rs index d3b35677407..9644f76cca4 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -15,7 +15,6 @@ use std::cmp; use syntax::ast; use syntax::codemap::{BytePos, Span}; -use spanned::Spanned; use codemap::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; @@ -24,6 +23,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTac SeparatorPlace}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use spanned::Spanned; use utils::{contains_skip, is_attributes_extendable, mk_sp}; pub trait AlignedItem { diff --git a/src/visitor.rs b/src/visitor.rs index ae9f7a091f9..095f5c6865b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -15,13 +15,12 @@ use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; -use expr::rewrite_literal; -use spanned::Spanned; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, remove_trailing_white_spaces, CodeCharKind, CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; +use expr::rewrite_literal; use items::{format_impl, format_trait, format_trait_alias, rewrite_associated_impl_type, rewrite_associated_type, rewrite_type_alias, FnSig, StaticParts, StructParts}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, @@ -30,6 +29,7 @@ use macros::{rewrite_macro, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use spanned::Spanned; use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; fn is_use_item(item: &ast::Item) -> bool { -- cgit 1.4.1-3-g733a5 From 939a6c58202f775a63e46fbde4e0d6b3b04cf8aa Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 24 Dec 2017 00:29:59 +0900 Subject: Get rid of GenericsArg wrapper type `GenericsArg` is basically identical to `ast::GenericParam`. Just use the latter. --- src/items.rs | 57 ++++++++++++++------------------------------------------- src/spanned.rs | 9 +++++++++ src/utils.rs | 13 ------------- 3 files changed, 23 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 35dd5c39d38..d09d95699b7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -30,9 +30,9 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; use types::join_bounds; -use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi, - format_constness, format_defaultness, format_mutability, format_unsafety, - format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, +use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, + format_defaultness, format_mutability, format_unsafety, format_visibility, + is_attributes_extendable, last_line_contains_single_line_comment, last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, stmt_expr, trim_newlines, trimmed_last_line_width}; use vertical::rewrite_with_alignment; @@ -1871,12 +1871,8 @@ fn rewrite_fn_base( .generics .params .iter() - .filter_map(|p| match p { - &ast::GenericParam::Type(ref t) => Some(t), - _ => None, - }) .last() - .map_or(lo_after_visibility, |tp| end_typaram(tp)); + .map_or(lo_after_visibility, |param| param.span().hi()); let args_end = if fd.inputs.is_empty() { context .codemap @@ -2346,47 +2342,13 @@ fn rewrite_generics_inner( // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. - // Wrapper type - enum GenericsArg<'a> { - Lifetime(&'a ast::LifetimeDef), - TyParam(&'a ast::TyParam), - } - impl<'a> Rewrite for GenericsArg<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - GenericsArg::Lifetime(lifetime) => lifetime.rewrite(context, shape), - GenericsArg::TyParam(ty) => ty.rewrite(context, shape), - } - } - } - impl<'a> Spanned for GenericsArg<'a> { - fn span(&self) -> Span { - match *self { - GenericsArg::Lifetime(lifetime) => lifetime.span(), - GenericsArg::TyParam(ty) => ty.span(), - } - } - } - if generics.params.is_empty() { return Some(String::new()); } - let generics_args = generics - .params - .iter() - .filter_map(|p| match p { - &ast::GenericParam::Lifetime(ref l) => Some(l), - _ => None, - }) - .map(|lt| GenericsArg::Lifetime(lt)) - .chain(generics.params.iter().filter_map(|ty| match ty { - &ast::GenericParam::Type(ref ty) => Some(GenericsArg::TyParam(ty)), - _ => None, - })); let items = itemize_list( context.codemap, - generics_args, + generics.params.iter(), ">", ",", |arg| arg.span().lo(), @@ -2868,3 +2830,12 @@ impl Rewrite for ast::ForeignItem { ) } } + +impl Rewrite for ast::GenericParam { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape), + ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape), + } + } +} diff --git a/src/spanned.rs b/src/spanned.rs index 7181512273e..eb36a117428 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -105,6 +105,15 @@ impl Spanned for ast::Arg { } } +impl Spanned for ast::GenericParam { + fn span(&self) -> Span { + match *self { + ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(), + ast::GenericParam::Type(ref ty) => ty.span(), + } + } +} + impl Spanned for ast::StructField { fn span(&self) -> Span { span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) diff --git a/src/utils.rs b/src/utils.rs index 7d3fcf73d56..1bad8aecdf4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -213,19 +213,6 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { .any(|a| a.meta().map_or(false, |a| is_skip(&a))) } -// Find the end of a TyParam -#[inline] -pub fn end_typaram(typaram: &ast::TyParam) -> BytePos { - typaram - .bounds - .last() - .map_or(typaram.span, |bound| match *bound { - ast::RegionTyParamBound(ref lt) => lt.span, - ast::TraitTyParamBound(ref prt, _) => prt.span, - }) - .hi() -} - #[inline] pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { match expr.node { -- cgit 1.4.1-3-g733a5 From f523ec58ab25596ae9f7139dae322376a94c5b1a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 24 Dec 2017 13:57:29 +0900 Subject: Do not give up rewriting struct field when attribute is long --- src/items.rs | 24 ++++++++++++------------ tests/source/struct-field-attributes.rs | 6 ++++++ tests/target/struct-field-attributes.rs | 6 ++++++ 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d09d95699b7..e313179fae9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{choose_rhs, format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_call_inner, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; @@ -1430,8 +1430,7 @@ pub fn rewrite_struct_field( lhs_max_width: usize, ) -> Option { if contains_skip(&field.attrs) { - let snippet = context.snippet(mk_sp(field.attrs[0].span.lo(), field.span.hi())); - return Some(snippet.to_owned()); + return Some(context.snippet(field.span()).to_owned()); } let type_annotation_spacing = type_annotation_spacing(context.config); @@ -1468,24 +1467,25 @@ pub fn rewrite_struct_field( if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { spacing.push(' '); } - let ty_shape = shape.offset_left(overhead + spacing.len())?; - let mut orig_ty = field.ty.rewrite(context, ty_shape); + let orig_ty = shape + .offset_left(overhead + spacing.len()) + .and_then(|ty_shape| field.ty.rewrite(context, ty_shape)); if let Some(ref ty) = orig_ty { if !ty.contains('\n') { return Some(attr_prefix + &spacing + ty); } } + let is_prefix_empty = prefix.is_empty(); // We must use multiline. We are going to put attributes and a field on different lines. - // 1 = " " - let rhs_shape = shape.offset_left(last_line_width(&prefix) + 1)?; - orig_ty = field.ty.rewrite(context, rhs_shape); - let field_str = if prefix.is_empty() { - orig_ty? + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; + // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. + let field_str = if is_prefix_empty { + field_str.trim_left() } else { - prefix + &choose_rhs(context, &*field.ty, rhs_shape, orig_ty)? + &field_str }; - combine_strs_with_missing_comments(context, &attrs_str, &field_str, missing_span, shape, false) + combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) } pub struct StaticParts<'a> { diff --git a/tests/source/struct-field-attributes.rs b/tests/source/struct-field-attributes.rs index b66ed1ed8f1..76d6eda8853 100644 --- a/tests/source/struct-field-attributes.rs +++ b/tests/source/struct-field-attributes.rs @@ -44,3 +44,9 @@ pub enum State { struct Fields( #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] Arc>, ); + +// #2309 +pub struct A { +#[doc="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] +pub foos:Vec +} diff --git a/tests/target/struct-field-attributes.rs b/tests/target/struct-field-attributes.rs index d9d790c00af..8bf10fae3e1 100644 --- a/tests/target/struct-field-attributes.rs +++ b/tests/target/struct-field-attributes.rs @@ -46,3 +46,9 @@ struct Fields( #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] Arc>, ); + +// #2309 +pub struct A { + #[doc = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] + pub foos: Vec, +} -- cgit 1.4.1-3-g733a5 From 0291331203e741b43eda016f8669f5dcdc807ed3 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 24 Dec 2017 12:27:07 +0000 Subject: Add documentation to expr::SPECIAL_MACRO_WHITELIST --- src/expr.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2d4b731a69d..0c60ba5a201 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1811,6 +1811,12 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } +/// A list of `format!`-like macros, that take a long format string and a list of arguments to +/// format. +/// +/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of +/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, +/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ // format! like macros // From the Rust Standard Library. -- cgit 1.4.1-3-g733a5 From 212a8a3c291bb7b602137578c1a2c4149c4844e9 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 24 Dec 2017 12:29:54 +0000 Subject: Slightly simplify `write_list` for `DefinitiveListTactic::SpecialMacro` --- src/lists.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index e167c638a53..da2dbf0d248 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -160,7 +160,7 @@ pub enum DefinitiveListTactic { Vertical, Horizontal, Mixed, - // Special case tactic for `format!()`, `write!()` style macros. + /// Special case tactic for `format!()`, `write!()` style macros. SpecialMacro(bool, bool, usize), } @@ -325,13 +325,10 @@ where result.push('\n'); result.push_str(indent_str); } - } else if i == num_args_before { + } else if i <= num_args_before + 1 { result.push('\n'); result.push_str(indent_str); - } else if i == num_args_before + 1 { - result.push('\n'); - result.push_str(indent_str); - } else if i > num_args_before + 1 { + } else { if one_line_after { result.push(' '); } else { -- cgit 1.4.1-3-g733a5 From 27167cbbaa862fc96017831f21f492c51eb8eed0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 24 Dec 2017 23:40:53 +0900 Subject: Format code block in comment Closes #554. Closes #1695. --- src/comment.rs | 74 ++++++++++++++++--------- src/lib.rs | 133 +++++++++++++++++++++++++++++++++++++++++++++ tests/target/issue-2197.rs | 10 +++- 3 files changed, 190 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 441bb858e2a..eb9e96f2509 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -318,41 +318,65 @@ fn rewrite_comment_inner( let mut result = String::with_capacity(orig.len() * 2); result.push_str(opener); + let mut code_block_buffer = String::with_capacity(128); let mut is_prev_line_multi_line = false; let mut inside_code_block = false; let comment_line_separator = format!("\n{}{}", indent_str, line_start); + let join_code_block_with_comment_line_separator = |s: &str| { + let mut result = String::with_capacity(s.len() + 128); + let mut iter = s.lines().peekable(); + while let Some(line) = iter.next() { + result.push_str(line); + result.push_str(match iter.peek() { + Some(ref next_line) if next_line.is_empty() => comment_line_separator.trim_right(), + Some(..) => &comment_line_separator, + None => "", + }); + } + result + }; + for (i, (line, has_leading_whitespace)) in lines.enumerate() { let is_last = i == count_newlines(orig); - if result == opener { - let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; - if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - if line.is_empty() { - continue; - } - } else if is_prev_line_multi_line && !line.is_empty() { - result.push(' ') - } else if is_last && !closer.is_empty() && line.is_empty() { - result.push('\n'); - result.push_str(&indent_str); - } else { - result.push_str(&comment_line_separator); - if !has_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - } - if line.starts_with("```") { - inside_code_block = !inside_code_block; - } if inside_code_block { - if line.is_empty() && result.ends_with(' ') { - result.pop(); - } else { + if line.starts_with("```") { + inside_code_block = false; + result.push_str(&comment_line_separator); + let code_block = ::format_code_block(&code_block_buffer, config) + .unwrap_or_else(|| code_block_buffer.to_owned()); + result.push_str(&join_code_block_with_comment_line_separator(&code_block)); + code_block_buffer.clear(); + result.push_str(&comment_line_separator); result.push_str(line); + } else { + code_block_buffer.push_str(line); + code_block_buffer.push('\n'); } + continue; + } else { + inside_code_block = line.starts_with("```"); + + if result == opener { + let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; + if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + if line.is_empty() { + continue; + } + } else if is_prev_line_multi_line && !line.is_empty() { + result.push(' ') + } else if is_last && !closer.is_empty() && line.is_empty() { + result.push('\n'); + result.push_str(&indent_str); + } else { + result.push_str(&comment_line_separator); + if !has_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + } } if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { diff --git a/src/lib.rs b/src/lib.rs index 14914359bdc..d221f6a7d60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,7 @@ use comment::{CharClasses, FullCodeCharKind}; use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; +use shape::Indent; use utils::use_colored_tty; use visitor::{FmtVisitor, SnippetProvider}; @@ -529,6 +530,55 @@ fn parse_input( } } +/// Format the given snippet. The snippet is expected to be *complete* code. +/// When we cannot parse the given snippet, this function returns `None`. +pub fn format_snippet(snippet: &str, config: &Config) -> Option { + let mut out: Vec = Vec::with_capacity(snippet.len() * 2); + let input = Input::Text(snippet.into()); + let mut config = config.clone(); + config.set().write_mode(config::WriteMode::Plain); + match format_input(input, &config, Some(&mut out)) { + // `format_input()` returns an empty string on parsing error. + Ok(..) if out.is_empty() && !snippet.is_empty() => None, + Ok(..) => String::from_utf8(out).ok(), + Err(..) => None, + } +} + +/// Format the given code block. Mainly targeted for code block in comment. +/// The code block may be incomplete (i.e. parser may be unable to parse it). +/// To avoid panic in parser, we wrap the code block with a dummy function. +/// The returned code block does *not* end with newline. +pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { + // Wrap the given code block with `fn main()` if it does not have one. + let fn_main_prefix = "fn main() {\n"; + let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}"; + + // Trim "fn main() {" on the first line and "}" on the last line, + // then unindent the whole code block. + format_snippet(&snippet, config).map(|s| { + // 2 = "}\n" + s[fn_main_prefix.len()..s.len().checked_sub(2).unwrap_or(0)] + .lines() + .map(|line| { + if line.len() > config.tab_spaces() { + // Make sure that the line has leading whitespaces. + let indent_str = + Indent::from_width(config, config.tab_spaces()).to_string(config); + if line.starts_with(indent_str.as_ref()) { + &line[config.tab_spaces()..] + } else { + line + } + } else { + line + } + }) + .collect::>() + .join("\n") + }) +} + pub fn format_input( input: Input, config: &Config, @@ -650,3 +700,86 @@ pub fn run(input: Input, config: &Config) -> Summary { } } } + +#[cfg(test)] +mod test { + use super::{format_code_block, format_snippet, Config}; + + #[test] + fn test_no_panic_on_format_snippet_and_format_code_block() { + // `format_snippet()` and `format_code_block()` should not panic + // even when we cannot parse the given snippet. + let snippet = "let"; + assert!(format_snippet(snippet, &Config::default()).is_none()); + assert!(format_code_block(snippet, &Config::default()).is_none()); + } + + fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool + where + F: Fn(&str, &Config) -> Option, + { + let output = formatter(input, &Config::default()); + output.is_some() && output.unwrap() == expected + } + + #[test] + fn test_format_snippet() { + let snippet = "fn main() { println!(\"hello, world\"); }"; + let expected = "fn main() {\n \ + println!(\"hello, world\");\n\ + }\n"; + assert!(test_format_inner(format_snippet, snippet, expected)); + } + + #[test] + fn test_format_code_block() { + // simple code block + let code_block = "let x=3;"; + let expected = "let x = 3;"; + assert!(test_format_inner(format_code_block, code_block, expected)); + + // more complex code block, taken from chains.rs. + let code_block = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +context.config.indent_style() == IndentStyle::Visual || is_small_parent, +) +} else if is_block_expr(context, &parent, &parent_rewrite) { +match context.config.indent_style() { +// Try to put the first child on the same line with parent's last line +IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), +// The parent is a block, so align the rest of the chain with the closing +// brace. +IndentStyle::Visual => (parent_shape, false), +} +} else { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +false, +) +}; +"; + let expected = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + context.config.indent_style() == IndentStyle::Visual || is_small_parent, + ) +} else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } +} else { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + false, + ) +};"; + assert!(test_format_inner(format_code_block, code_block, expected)); + } +} diff --git a/tests/target/issue-2197.rs b/tests/target/issue-2197.rs index d26ca1a80e5..76dbbefc3a7 100644 --- a/tests/target/issue-2197.rs +++ b/tests/target/issue-2197.rs @@ -4,8 +4,14 @@ /// ```rust /// unsafe fn sum_sse2(x: i32x4) -> i32 { -/// let x = vendor::_mm_add_epi32(x, vendor::_mm_srli_si128(x.into(), 8).into()); -/// let x = vendor::_mm_add_epi32(x, vendor::_mm_srli_si128(x.into(), 4).into()); +/// let x = vendor::_mm_add_epi32( +/// x, +/// vendor::_mm_srli_si128(x.into(), 8).into(), +/// ); +/// let x = vendor::_mm_add_epi32( +/// x, +/// vendor::_mm_srli_si128(x.into(), 4).into(), +/// ); /// vendor::_mm_cvtsi128_si32(x) /// } /// ``` -- cgit 1.4.1-3-g733a5 From 4604fea0a0f6d9a7034638a9d416d65c35a94d67 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 Dec 2017 00:13:59 +0900 Subject: Refactoring 1. Cargo clippy 2. Run 'cargo fmt' with import reordering options set to `true`. 3. Factor out `rewrite_lifetime_param()`. --- src/bin/cargo-fmt.rs | 8 +++--- src/bin/rustfmt.rs | 2 +- src/types.rs | 73 ++++++++++++++++++---------------------------------- tests/system.rs | 2 +- 4 files changed, 31 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 270ed1446d6..180c6f0abf3 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -17,15 +17,15 @@ extern crate cargo_metadata; extern crate getopts; extern crate serde_json as json; +use std::collections::HashSet; use std::env; use std::fs; use std::hash::{Hash, Hasher}; use std::io::{self, Write}; +use std::iter::FromIterator; use std::path::{Path, PathBuf}; use std::process::{Command, ExitStatus}; use std::str; -use std::collections::HashSet; -use std::iter::FromIterator; use getopts::{Matches, Options}; @@ -125,7 +125,7 @@ pub enum Verbosity { fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { match status { Err(e) => { - print_usage_to_stderr(&opts, &e.to_string()); + print_usage_to_stderr(opts, &e.to_string()); FAILURE } Ok(status) => { @@ -139,7 +139,7 @@ fn handle_command_status(status: Result, opts: &getopts:: } fn get_version(verbosity: Verbosity) -> Result { - run_rustfmt(&vec![], &vec![String::from("--version")], verbosity) + run_rustfmt(&[], &[String::from("--version")], verbosity) } fn format_crate( diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 0e48ab7c23a..ba586e1fd91 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -24,8 +24,8 @@ use std::str::FromStr; use getopts::{Matches, Options}; use rustfmt::{run, FileName, Input, Summary}; -use rustfmt::file_lines::FileLines; use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; +use rustfmt::file_lines::FileLines; type FmtError = Box; type FmtResult = std::result::Result; diff --git a/src/types.rs b/src/types.rs index 77dffd3cd89..588d9100fe6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -422,21 +422,9 @@ impl Rewrite for ast::WherePredicate { let colon = type_bound_colon(context); - if bound_generic_params - .iter() - .filter(|p| p.is_lifetime_param()) - .count() > 0 + if let Some(lifetime_str) = + rewrite_lifetime_param(context, shape, bound_generic_params) { - let lifetime_str: String = bound_generic_params - .iter() - .filter_map(|p| match p { - &ast::GenericParam::Lifetime(ref l) => Some(l), - _ => None, - }) - .map(|lt| lt.rewrite(context, shape)) - .collect::>>()? - .join(", "); - // 6 = "for<> ".len() let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; let ty_shape = shape.offset_left(used_width)?; @@ -598,21 +586,9 @@ impl Rewrite for ast::TyParam { impl Rewrite for ast::PolyTraitRef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if self.bound_generic_params - .iter() - .filter(|p| p.is_lifetime_param()) - .count() > 0 + if let Some(lifetime_str) = + rewrite_lifetime_param(context, shape, &self.bound_generic_params) { - let lifetime_str: String = self.bound_generic_params - .iter() - .filter_map(|p| match p { - &ast::GenericParam::Lifetime(ref l) => Some(l), - _ => None, - }) - .map(|lt| lt.rewrite(context, shape)) - .collect::>>()? - .join(", "); - // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; let path_str = self.trait_ref @@ -762,31 +738,13 @@ fn rewrite_bare_fn( ) -> Option { let mut result = String::with_capacity(128); - if bare_fn - .generic_params - .iter() - .filter(|p| p.is_lifetime_param()) - .count() > 0 + if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params) { result.push_str("for<"); // 6 = "for<> ".len(), 4 = "for<". // This doesn't work out so nicely for mutliline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. - result.push_str(&bare_fn - .generic_params - .iter() - .filter_map(|p| match p { - &ast::GenericParam::Lifetime(ref l) => Some(l), - _ => None, - }) - .map(|l| { - l.rewrite( - context, - Shape::legacy(shape.width.checked_sub(6)?, shape.indent + 4), - ) - }) - .collect::>>()? - .join(", ")); + result.push_str(lifetime_str); result.push_str("> "); } @@ -841,3 +799,22 @@ pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize _ => false, } } + +/// Returns `None` if there is no `LifetimeDef` in the given generic parameters. +fn rewrite_lifetime_param( + context: &RewriteContext, + shape: Shape, + generic_params: &[ast::GenericParam], +) -> Option { + let result = generic_params + .iter() + .filter(|p| p.is_lifetime_param()) + .map(|lt| lt.rewrite(context, shape)) + .collect::>>()? + .join(", "); + if result.is_empty() { + None + } else { + Some(result) + } +} diff --git a/tests/system.rs b/tests/system.rs index c1d838169ae..4beb616dd3c 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -24,8 +24,8 @@ use std::path::{Path, PathBuf}; use std::str::Chars; use rustfmt::*; -use rustfmt::filemap::{write_system_newlines, FileMap}; use rustfmt::config::{Color, Config, ReportTactic}; +use rustfmt::filemap::{write_system_newlines, FileMap}; use rustfmt::rustfmt_diff::*; const DIFF_CONTEXT_SIZE: usize = 3; -- cgit 1.4.1-3-g733a5 From dc356ffef71ef8cc679c414542ae9efcdf88cf52 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Tue, 14 Nov 2017 14:42:48 +0100 Subject: Add rudimentary timing of parsing and formatting phases --- Cargo.lock | 67 ++++++++++++++++++++++++++++++++++++++++++---------------- Cargo.toml | 1 + src/lib.rs | 19 +++++++++++++++-- src/summary.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 87d2529fe24..b1c986eba83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,8 +36,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -84,7 +84,7 @@ name = "env_logger" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -127,8 +127,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "memchr" @@ -148,6 +159,11 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "redox_syscall" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "regex" version = "0.2.3" @@ -181,12 +197,13 @@ dependencies = [ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -198,7 +215,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -208,22 +225,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -238,7 +255,7 @@ dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -277,12 +294,23 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "time" +version = "0.1.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -341,23 +369,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" -"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a89a0c46ba789b8a247d4c567aed4d7c68e624672d238b45cc3ec20dc9f940" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1c57ab4ec5fa85d08aaf8ed9245899d9bbdd66768945b21113b84d5f595cb6a1" -"checksum serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "02c92ea07b6e49b959c1481804ebc9bfd92d3c459f1274c9a9546829e42a66ce" -"checksum serde_derive_internals 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75c6aac7b99801a16db5b40b7bf0d7e4ba16e76fbf231e32a4677f271cac0603" +"checksum serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "386122ba68c214599c44587e0c0b411e8d90894503a95425b4f9508e4317901f" +"checksum serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0bfa6c5784e7d110514448da0e1dbad41ea5514c3e68be755b23858b83a399" +"checksum serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "730fe9f29fe8db69a601837f416e46cba07792031ed6b27557a43e49d62d89ae" "checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/Cargo.toml b/Cargo.toml index a0f974c6614..5fd98c005e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ env_logger = "0.4" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.4" +time = "0.1" [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/src/lib.rs b/src/lib.rs index d221f6a7d60..c371d81efad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ extern crate serde_derive; extern crate serde_json; extern crate syntax; extern crate term; +extern crate time; extern crate unicode_segmentation; use std::collections::HashMap; @@ -616,6 +617,8 @@ pub fn format_input( } }; + summary.mark_parse_time(); + if parse_session.span_diagnostic.has_errors() { summary.add_parsing_error(); } @@ -630,7 +633,7 @@ pub fn format_input( let mut report = FormatReport::new(); - match format_ast( + let format_result = format_ast( &krate, &mut parse_session, &main_file, @@ -647,7 +650,19 @@ pub fn format_input( } Ok(false) }, - ) { + ); + + summary.mark_format_time(); + + if config.verbose() { + println!( + "Spent {} in the parsing phase, and {} in the formatting phase", + summary.get_parse_time().unwrap(), + summary.get_format_time().unwrap(), + ); + } + + match format_result { Ok((file_map, has_diff)) => { if report.has_warnings() { summary.add_formatting_error(); diff --git a/src/summary.rs b/src/summary.rs index 73ee80dac85..33260d8c91e 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -1,3 +1,6 @@ +use time::{precise_time_ns, Duration}; +use std::default::Default; + #[must_use] #[derive(Debug, Default, Clone, Copy)] pub struct Summary { @@ -12,9 +15,42 @@ pub struct Summary { // Formatted code differs from existing code (write-mode diff only). pub has_diff: bool, + + // Keeps track of time spent in parsing and formatting steps. + timer: Timer, } impl Summary { + pub fn mark_parse_time(&mut self) { + self.timer = self.timer.done_parsing(); + } + + pub fn mark_format_time(&mut self) { + self.timer = self.timer.done_formatting(); + } + + /// Returns the time it took to parse the source files in nanoseconds. + pub fn get_parse_time(&self) -> Option { + match self.timer { + Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { + // This should never underflow since `precise_time_ns()` guarantees monotonicity. + Some(Duration::nanoseconds((parse_time - init) as i64)) + } + Timer::Initialized(..) => None, + } + } + + /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is + /// not included. + pub fn get_format_time(&self) -> Option { + match self.timer { + Timer::DoneFormatting(_init, parse_time, format_time) => { + Some(Duration::nanoseconds((format_time - parse_time) as i64)) + } + Timer::DoneParsing(..) | Timer::Initialized(..) => None, + } + } + pub fn has_operational_errors(&self) -> bool { self.has_operational_errors } @@ -65,3 +101,34 @@ impl Summary { println!("{}", exit_codes); } } + +#[derive(Clone, Copy, Debug)] +enum Timer { + Initialized(u64), + DoneParsing(u64, u64), + DoneFormatting(u64, u64, u64), +} + +impl Default for Timer { + fn default() -> Self { + Timer::Initialized(precise_time_ns()) + } +} + +impl Timer { + fn done_parsing(self) -> Self { + match self { + Timer::Initialized(init_time) => Timer::DoneParsing(init_time, precise_time_ns()), + _ => panic!("Timer can only transition to DoneParsing from Initialized state"), + } + } + + fn done_formatting(self) -> Self { + match self { + Timer::DoneParsing(init_time, parse_time) => { + Timer::DoneFormatting(init_time, parse_time, precise_time_ns()) + } + _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), + } + } +} -- cgit 1.4.1-3-g733a5 From 656edbf0f041d83cd564c5ae742c7720f005b005 Mon Sep 17 00:00:00 2001 From: Marcus Klaas Date: Fri, 17 Nov 2017 14:21:46 +0100 Subject: Use std time --- Cargo.lock | 19 ------------------- Cargo.toml | 1 - src/lib.rs | 12 ++++++++---- src/summary.rs | 20 ++++++++++---------- 4 files changed, 18 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b1c986eba83..672c5f59da3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,11 +159,6 @@ name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "redox_syscall" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "regex" version = "0.2.3" @@ -203,7 +198,6 @@ dependencies = [ "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -294,17 +288,6 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "time" -version = "0.1.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "toml" version = "0.4.5" @@ -374,7 +357,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" @@ -388,7 +370,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" -"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/Cargo.toml b/Cargo.toml index 5fd98c005e3..a0f974c6614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ env_logger = "0.4" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.4" -time = "0.1" [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/src/lib.rs b/src/lib.rs index c371d81efad..58735d539ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,6 @@ extern crate serde_derive; extern crate serde_json; extern crate syntax; extern crate term; -extern crate time; extern crate unicode_segmentation; use std::collections::HashMap; @@ -32,6 +31,7 @@ use std::io::{self, stdout, Write}; use std::iter::repeat; use std::path::PathBuf; use std::rc::Rc; +use std::time::Duration; use errors::{DiagnosticBuilder, Handler}; use errors::emitter::{ColorConfig, EmitterWriter}; @@ -655,10 +655,14 @@ pub fn format_input( summary.mark_format_time(); if config.verbose() { + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } + println!( - "Spent {} in the parsing phase, and {} in the formatting phase", - summary.get_parse_time().unwrap(), - summary.get_format_time().unwrap(), + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + duration_to_f32(summary.get_parse_time().unwrap()), + duration_to_f32(summary.get_format_time().unwrap()), ); } diff --git a/src/summary.rs b/src/summary.rs index 33260d8c91e..3e339fa4469 100644 --- a/src/summary.rs +++ b/src/summary.rs @@ -1,4 +1,4 @@ -use time::{precise_time_ns, Duration}; +use std::time::{Duration, Instant}; use std::default::Default; #[must_use] @@ -33,8 +33,8 @@ impl Summary { pub fn get_parse_time(&self) -> Option { match self.timer { Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { - // This should never underflow since `precise_time_ns()` guarantees monotonicity. - Some(Duration::nanoseconds((parse_time - init) as i64)) + // This should never underflow since `Instant::now()` guarantees monotonicity. + Some(parse_time.duration_since(init)) } Timer::Initialized(..) => None, } @@ -45,7 +45,7 @@ impl Summary { pub fn get_format_time(&self) -> Option { match self.timer { Timer::DoneFormatting(_init, parse_time, format_time) => { - Some(Duration::nanoseconds((format_time - parse_time) as i64)) + Some(format_time.duration_since(parse_time)) } Timer::DoneParsing(..) | Timer::Initialized(..) => None, } @@ -104,21 +104,21 @@ impl Summary { #[derive(Clone, Copy, Debug)] enum Timer { - Initialized(u64), - DoneParsing(u64, u64), - DoneFormatting(u64, u64, u64), + Initialized(Instant), + DoneParsing(Instant, Instant), + DoneFormatting(Instant, Instant, Instant), } impl Default for Timer { fn default() -> Self { - Timer::Initialized(precise_time_ns()) + Timer::Initialized(Instant::now()) } } impl Timer { fn done_parsing(self) -> Self { match self { - Timer::Initialized(init_time) => Timer::DoneParsing(init_time, precise_time_ns()), + Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), _ => panic!("Timer can only transition to DoneParsing from Initialized state"), } } @@ -126,7 +126,7 @@ impl Timer { fn done_formatting(self) -> Self { match self { Timer::DoneParsing(init_time, parse_time) => { - Timer::DoneFormatting(init_time, parse_time, precise_time_ns()) + Timer::DoneFormatting(init_time, parse_time, Instant::now()) } _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), } -- cgit 1.4.1-3-g733a5 From e95541c7d2556e40ee118f0163829efa95fa5b17 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Dec 2017 10:08:27 +1300 Subject: Make the import of Config pub --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 58735d539ca..1b51e3126a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; use comment::{CharClasses, FullCodeCharKind}; -use config::Config; +pub use config::Config; use filemap::FileMap; use issues::{BadIssueSeeker, Issue}; use shape::Indent; -- cgit 1.4.1-3-g733a5 From 39e2f43f91e3c3677f39d89f420105648e0a268d Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 27 Dec 2017 21:19:42 +0000 Subject: Split assert_eq! if any arguments are not simple --- src/expr.rs | 26 +++++++++----------------- src/lists.rs | 22 ++++------------------ tests/source/macros.rs | 12 ++++++------ tests/target/macros.rs | 27 +++++++++++++++++---------- 4 files changed, 36 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0c60ba5a201..e64ea7436e3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2082,18 +2082,16 @@ where tactic = default_tactic(); if tactic == DefinitiveListTactic::Vertical { - if let Some((all_simple_before, all_simple_after, num_args_before)) = + if let Some((all_simple, num_args_before)) = maybe_get_args_offset(callee_str, args) { - let one_line_before = all_simple_before + let one_line = all_simple && definitive_tactic( &item_vec[..num_args_before], ListTactic::HorizontalVertical, Separator::Comma, nested_shape.width, - ) == DefinitiveListTactic::Horizontal; - - let one_line_after = all_simple_after + ) == DefinitiveListTactic::Horizontal && definitive_tactic( &item_vec[num_args_before + 1..], ListTactic::HorizontalVertical, @@ -2101,11 +2099,9 @@ where nested_shape.width, ) == DefinitiveListTactic::Horizontal; - tactic = DefinitiveListTactic::SpecialMacro( - one_line_before, - one_line_after, - num_args_before, - ); + if one_line { + tactic = DefinitiveListTactic::SpecialMacro(num_args_before); + }; } } } @@ -2141,18 +2137,14 @@ fn is_every_args_simple(lists: &[&T]) -> bool { } /// In case special-case style is required, returns an offset from which we start horizontal layout. -fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, bool, usize)> { +fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST .iter() .find(|&&(s, _)| s == callee_str) { - let all_simple_before = - args.len() >= num_args_before && is_every_args_simple(&args[..num_args_before]); - - let all_simple_after = - args.len() >= num_args_before + 1 && is_every_args_simple(&args[num_args_before + 1..]); + let all_simple = args.len() >= num_args_before && is_every_args_simple(args); - Some((all_simple_before, all_simple_after, num_args_before)) + Some((all_simple, num_args_before)) } else { None } diff --git a/src/lists.rs b/src/lists.rs index da2dbf0d248..193cd4f3c32 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -161,7 +161,7 @@ pub enum DefinitiveListTactic { Horizontal, Mixed, /// Special case tactic for `format!()`, `write!()` style macros. - SpecialMacro(bool, bool, usize), + SpecialMacro(usize), } impl DefinitiveListTactic { @@ -311,30 +311,16 @@ where DefinitiveListTactic::Horizontal if !first => { result.push(' '); } - DefinitiveListTactic::SpecialMacro( - one_line_before, - one_line_after, - num_args_before, - ) => { + DefinitiveListTactic::SpecialMacro(num_args_before) => { if i == 0 { // Nothing } else if i < num_args_before { - if one_line_before { - result.push(' '); - } else { - result.push('\n'); - result.push_str(indent_str); - } + result.push(' '); } else if i <= num_args_before + 1 { result.push('\n'); result.push_str(indent_str); } else { - if one_line_after { - result.push(' '); - } else { - result.push('\n'); - result.push_str(indent_str); - } + result.push(' '); } } DefinitiveListTactic::Vertical if !first => { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 4862c4f107d..fc2ebcd7e4c 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -267,21 +267,21 @@ fn special_case_macros() { warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); assert!(result == 42, "Ahoy there, {}!", target); - assert!(result == 42, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + assert!(result == 42, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); assert_eq!(left, right, "Ahoy there, {}!", target); - assert_eq!(left, right, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); - assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); - assert_eq!(left + 42, right, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + assert_eq!(left, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(left + 42, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); write!(&mut s, "Ahoy there, {}!", target); - write!(&mut s, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + write!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); write!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); writeln!(&mut s, "Ahoy there, {}!", target); - writeln!(&mut s, "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", result, input, expected); + writeln!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); writeln!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 933fe000c9f..be9027dd108 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -694,8 +694,10 @@ fn special_case_macros() { assert!(result == 42, "Ahoy there, {}!", target); assert!( result == 42, - "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", - result, input, expected + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected ); assert!( result == 42, @@ -731,23 +733,28 @@ fn special_case_macros() { assert_eq!(left, right, "Ahoy there, {}!", target); assert_eq!( left, right, - "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected ); assert_eq!( first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, - "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", - result, input, expected + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected ); assert_eq!( left + 42, right, - "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", - result, input, expected + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected ); assert_eq!( - left, right, + left, + right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, @@ -780,7 +787,7 @@ fn special_case_macros() { write!(&mut s, "Ahoy there, {}!", target); write!( &mut s, - "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected ); write!( @@ -817,7 +824,7 @@ fn special_case_macros() { writeln!(&mut s, "Ahoy there, {}!", target); writeln!( &mut s, - "Arr! Batten down the hatches, we got '{}' but not '{}' (we expected '{}')", + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected ); writeln!( -- cgit 1.4.1-3-g733a5 From f86f6dcd9c33fa7b2b1bcda29edbed4d4fd9cba2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 1 Jan 2018 19:40:51 +1300 Subject: Format some macros 2.0 macro defs cc #1539 --- src/config.rs | 1 + src/lib.rs | 13 +- src/macros.rs | 417 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/visitor.rs | 20 ++- 4 files changed, 437 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index bdf39ed6a2c..fb0cdf6aaf2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -684,6 +684,7 @@ create_config! { "Enables unstable features. Only available on nightly channel"; disable_all_formatting: bool, false, false, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; + hide_parse_errors: bool, false, false, "Hide errors from the parser"; error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; error_on_unformatted: bool, false, false, "Error if unable to get comments or string literals within max_width, \ diff --git a/src/lib.rs b/src/lib.rs index 1b51e3126a6..111345a24b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(rustc_private)] +#![feature(type_ascription)] #[macro_use] extern crate derive_new; @@ -597,8 +598,16 @@ pub fn format_input( } let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - let tty_handler = - Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())); + let tty_handler = if config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())) + }; let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); let main_file = match input { diff --git a/src/macros.rs b/src/macros.rs index 9c32e7f62be..d642b31ef42 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -19,21 +19,23 @@ // List-like invocations with parentheses will be formatted as function calls, // and those with brackets will be formatted as array literals. +use std::collections::HashMap; use syntax::ast; -use syntax::codemap::BytePos; +use syntax::codemap::{BytePos, Span}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; -use syntax::parse::token::Token; +use syntax::parse::token::{BinOpToken, DelimToken, Token}; +use syntax::print::pprust; use syntax::symbol; -use syntax::tokenstream::TokenStream; +use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::util::ThinVec; use codemap::SpanUtils; -use comment::{contains_comment, FindUncommented}; +use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; use expr::{rewrite_array, rewrite_call_inner}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; -use utils::mk_sp; +use utils::{format_visibility, mk_sp}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -278,6 +280,306 @@ pub fn rewrite_macro( } } +pub fn rewrite_macro_def( + context: &RewriteContext, + indent: Indent, + def: &ast::MacroDef, + ident: ast::Ident, + vis: &ast::Visibility, + span: Span, +) -> Option { + let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); + + if def.legacy { + return snippet; + } + + let mut parser = MacroParser::new(def.stream().into_trees()); + let mut parsed_def = match parser.parse() { + Some(def) => def, + None => return snippet, + }; + + // Only attempt to format function-like macros. + if parsed_def.branches.len() != 1 || parsed_def.branches[0].args_paren_kind != DelimToken::Paren + { + // FIXME(#1539): implement for non-sugared macros. + return snippet; + } + + let branch = parsed_def.branches.remove(0); + let args_str = format_macro_args(branch.args)?; + + // The macro body is the most interesting part. It might end up as various + // AST nodes, but also has special variables (e.g, `$foo`) which can't be + // parsed as regular Rust code (and note that these can be escaped using + // `$$`). We'll try and format like an AST node, but we'll substitute + // variables for new names with the same length first. + + let body_sp = match branch.body { + Some(sp) => sp, + None => { + // FIXME: should check the single-line empty function option + return Some(format!( + "{}macro {}({}) {{}}\n", + format_visibility(vis), + ident, + args_str, + )); + } + }; + let old_body = context.snippet(body_sp); + let (body_str, substs) = replace_names(old_body); + + // We'll hack the indent below, take this into account when formatting, + let mut config = context.config.clone(); + let new_width = config.max_width() - indent.block_indent(&config).width(); + config.set().max_width(new_width); + config.set().hide_parse_errors(true); + + // First try to format as items, then as statements. + let new_body = match ::format_snippet(&body_str, &config) { + Some(new_body) => new_body, + None => match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return snippet, + }, + }; + + // Indent the body since it is in a block. + let indent_str = indent.block_indent(&config).to_string(&config); + let mut new_body = new_body + .lines() + .map(|l| format!("{}{}", indent_str, l)) + .collect::>() + .join("\n"); + + // Undo our replacement of macro variables. + // FIXME: this could be *much* more efficient. + for (old, new) in substs.iter() { + if old_body.find(new).is_some() { + debug!( + "rewrite_macro_def: bailing matching variable: `{}` in `{}`", + new, ident + ); + return snippet; + } + new_body = new_body.replace(new, old); + } + + let result = format!( + "{}macro {}({}) {{\n{}\n{}}}", + format_visibility(vis), + ident, + args_str, + new_body, + indent.to_string(&context.config), + ); + + Some(result) +} + +// Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we +// aren't causing problems. +// This should also work for escaped `$` variables, where we leave earlier `$`s. +fn replace_names(input: &str) -> (String, HashMap) { + // Each substitution will require five or six extra bytes. + let mut result = String::with_capacity(input.len() + 64); + let mut substs = HashMap::new(); + let mut dollar_count = 0; + let mut cur_name = String::new(); + + for c in input.chars() { + if c == '$' { + dollar_count += 1; + } else if dollar_count == 0 { + result.push(c); + } else if !c.is_alphanumeric() && !cur_name.is_empty() { + // Terminates a name following one or more dollars. + let mut new_name = String::new(); + let mut old_name = String::new(); + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&cur_name); + old_name.push_str(&cur_name); + + result.push_str(&new_name); + substs.insert(old_name, new_name); + + result.push(c); + + dollar_count = 0; + cur_name = String::new(); + } else if c.is_alphanumeric() { + cur_name.push(c); + } + } + + // FIXME: duplicate code + if !cur_name.is_empty() { + let mut new_name = String::new(); + let mut old_name = String::new(); + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&cur_name); + old_name.push_str(&cur_name); + + result.push_str(&new_name); + substs.insert(old_name, new_name); + } + + debug!("replace_names `{}` {:?}", result, substs); + + (result, substs) +} + +// This is a bit sketchy. The token rules probably need tweaking, but it works +// for some common cases. I hope the basic logic is sufficient. Note that the +// meaning of some tokens is a bit different here from usual Rust, e.g., `*` +// and `(`/`)` have special meaning. +// +// We always try and format on one line. +fn format_macro_args(toks: ThinTokenStream) -> Option { + let mut result = String::with_capacity(128); + let mut insert_space = SpaceState::Never; + + for tok in (toks.into(): TokenStream).trees() { + match tok { + TokenTree::Token(_, t) => { + if !result.is_empty() && force_space_before(&t) { + insert_space = SpaceState::Always; + } + if force_no_space_before(&t) { + insert_space = SpaceState::Never; + } + match (insert_space, ident_like(&t)) { + (SpaceState::Always, _) + | (SpaceState::Punctuation, false) + | (SpaceState::Ident, true) => { + result.push(' '); + } + _ => {} + } + result.push_str(&pprust::token_to_string(&t)); + insert_space = next_space(&t); + } + TokenTree::Delimited(_, d) => { + let formatted = format_macro_args(d.tts)?; + match insert_space { + SpaceState::Always => { + result.push(' '); + } + _ => {} + } + match d.delim { + DelimToken::Paren => { + result.push_str(&format!("({})", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::Bracket => { + result.push_str(&format!("[{}]", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::Brace => { + result.push_str(&format!(" {{ {} }}", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::NoDelim => { + result.push_str(&format!("{}", formatted)); + insert_space = SpaceState::Always; + } + } + } + } + } + + Some(result) +} + +// We should insert a space if the next token is a: +#[derive(Copy, Clone)] +enum SpaceState { + Never, + Punctuation, + Ident, // Or ident/literal-like thing. + Always, +} + +fn force_space_before(tok: &Token) -> bool { + match *tok { + Token::Eq + | Token::Lt + | Token::Le + | Token::EqEq + | Token::Ne + | Token::Ge + | Token::Gt + | Token::AndAnd + | Token::OrOr + | Token::Not + | Token::Tilde + | Token::BinOpEq(_) + | Token::At + | Token::RArrow + | Token::LArrow + | Token::FatArrow + | Token::Pound + | Token::Dollar => true, + Token::BinOp(bot) => bot != BinOpToken::Star, + _ => false, + } +} + +fn force_no_space_before(tok: &Token) -> bool { + match *tok { + Token::Semi | Token::Comma | Token::Dot => true, + Token::BinOp(bot) => bot == BinOpToken::Star, + _ => false, + } +} +fn ident_like(tok: &Token) -> bool { + match *tok { + Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, + _ => false, + } +} + +fn next_space(tok: &Token) -> SpaceState { + match *tok { + Token::Not + | Token::Tilde + | Token::At + | Token::Comma + | Token::Dot + | Token::DotDot + | Token::DotDotDot + | Token::DotDotEq + | Token::DotEq + | Token::Question + | Token::Underscore + | Token::BinOp(_) => SpaceState::Punctuation, + + Token::ModSep + | Token::Pound + | Token::Dollar + | Token::OpenDelim(_) + | Token::CloseDelim(_) + | Token::Whitespace => SpaceState::Never, + + Token::Literal(..) | Token::Ident(_) | Token::Lifetime(_) => SpaceState::Ident, + + _ => SpaceState::Always, + } +} + /// Tries to convert a macro use into a short hand try expression. Returns None /// when the macro is not an instance of try! (or parsing the inner expression /// failed). @@ -393,3 +695,108 @@ fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { fn is_empty_line(s: &str) -> bool { s.is_empty() || s.chars().all(char::is_whitespace) } + +// A very simple parser that just parses a macros 2.0 definition into its branches. +// Currently we do not attempt to parse any further than that. +#[derive(new)] +struct MacroParser { + toks: Cursor, +} + +impl MacroParser { + // (`(` ... `)` `=>` `{` ... `}`)* + fn parse(&mut self) -> Option { + let mut branches = vec![]; + while self.toks.look_ahead(1).is_some() { + branches.push(self.parse_branch()?); + } + + Some(Macro { branches }) + } + + // `(` ... `)` `=>` `{` ... `}` + fn parse_branch(&mut self) -> Option { + let (args_paren_kind, args) = match self.toks.next()? { + TokenTree::Token(..) => return None, + TokenTree::Delimited(_, ref d) => (d.delim, d.tts.clone().into()), + }; + match self.toks.next()? { + TokenTree::Token(_, Token::FatArrow) => {} + _ => return None, + } + let body = match self.toks.next()? { + TokenTree::Token(..) => return None, + TokenTree::Delimited(_, ref d) => inner_span(d.tts.clone().into()), + }; + Some(MacroBranch { + args, + args_paren_kind, + body, + }) + } +} + +fn inner_span(ts: TokenStream) -> Option { + let mut cursor = ts.trees(); + let first = match cursor.next() { + Some(t) => t.span(), + None => return None, + }; + + let last = match cursor.last() { + Some(t) => t.span(), + None => return Some(first), + }; + + Some(first.to(last)) +} + +// A parsed macros 2.0 macro definition. +struct Macro { + branches: Vec, +} + +// FIXME: it would be more efficient to use references to the token streams +// rather than clone them, if we can make the borrowing work out. +struct MacroBranch { + args: ThinTokenStream, + args_paren_kind: DelimToken, + body: Option, +} + +#[cfg(test)] +mod test { + use super::*; + use syntax::parse::{parse_stream_from_source_str, ParseSess}; + use syntax::codemap::{FileName, FilePathMapping}; + + fn format_macro_args_str(s: &str) -> String { + let input = parse_stream_from_source_str( + FileName::Custom("stdin".to_owned()), + s.to_owned(), + &ParseSess::new(FilePathMapping::empty()), + None, + ); + format_macro_args(input.into()).unwrap() + } + + #[test] + fn test_format_macro_args() { + assert_eq!(format_macro_args_str(""), "".to_owned()); + assert_eq!(format_macro_args_str("$ x : ident"), "$x: ident".to_owned()); + assert_eq!( + format_macro_args_str("$ m1 : ident , $ m2 : ident , $ x : ident"), + "$m1: ident, $m2: ident, $x: ident".to_owned() + ); + assert_eq!( + format_macro_args_str("$($beginning:ident),*;$middle:ident;$($end:ident),*"), + "$($beginning: ident),*; $middle: ident; $($end: ident),*".to_owned() + ); + assert_eq!( + format_macro_args_str( + "$ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) *" + ), + "$name: ident($($dol: tt $var: ident)*) $($body: tt)*".to_owned() + ); + } +} diff --git a/src/visitor.rs b/src/visitor.rs index 095f5c6865b..3e454876307 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -16,8 +16,8 @@ use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, remove_trailing_white_spaces, - CodeCharKind, CommentCodeSlices, FindUncommented}; +use comment::{combine_strs_with_missing_comments, contains_comment, CodeCharKind, + CommentCodeSlices, FindUncommented}; use comment::rewrite_comment; use config::{BraceStyle, Config}; use expr::rewrite_literal; @@ -25,7 +25,7 @@ use items::{format_impl, format_trait, format_trait_alias, rewrite_associated_im rewrite_associated_type, rewrite_type_alias, FnSig, StaticParts, StructParts}; use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; -use macros::{rewrite_macro, MacroPosition}; +use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use regex::Regex; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; @@ -439,10 +439,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let snippet = Some(self.snippet(item.span).to_owned()); self.push_rewrite(item.span, snippet); } - ast::ItemKind::MacroDef(..) => { - // FIXME(#1539): macros 2.0 - let mac_snippet = Some(remove_trailing_white_spaces(self.snippet(item.span))); - self.push_rewrite(item.span, mac_snippet); + ast::ItemKind::MacroDef(ref def) => { + let rewrite = rewrite_macro_def( + &self.get_context(), + self.block_indent, + def, + item.ident, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); } } } -- cgit 1.4.1-3-g733a5 From 12ddaf93e26d3bfccfd9424ed7c0840334554a79 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 2 Jan 2018 13:04:39 +0900 Subject: Remove trim_newlines() We call `trim_newlines()` after the `trim()`ed buffer, which is unnecessary. --- src/items.rs | 6 +++--- src/utils.rs | 11 ----------- 2 files changed, 3 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e313179fae9..2de3a025e4d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -34,7 +34,7 @@ use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_co format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, - stmt_expr, trim_newlines, trimmed_last_line_width}; + stmt_expr, trimmed_last_line_width}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -674,7 +674,7 @@ pub fn format_impl( result.push('\n'); result.push_str(&inner_indent_str); - result.push_str(trim_newlines(visitor.buffer.to_string().trim())); + result.push_str(visitor.buffer.to_string().trim()); result.push('\n'); result.push_str(&outer_indent_str); } @@ -1073,7 +1073,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push('\n'); result.push_str(&inner_indent_str); - result.push_str(trim_newlines(visitor.buffer.to_string().trim())); + result.push_str(visitor.buffer.to_string().trim()); result.push('\n'); result.push_str(&outer_indent_str); } else if result.contains('\n') { diff --git a/src/utils.rs b/src/utils.rs index 1bad8aecdf4..73103e88a64 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -254,17 +254,6 @@ pub fn count_newlines(input: &str) -> usize { input.chars().filter(|&c| c == '\n').count() } -#[inline] -pub fn trim_newlines(input: &str) -> &str { - match input.find(|c| c != '\n' && c != '\r') { - Some(start) => { - let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1; - &input[start..end] - } - None => "", - } -} - // Macro for deriving implementations of Serialize/Deserialize for enums #[macro_export] macro_rules! impl_enum_serialize_and_deserialize { -- cgit 1.4.1-3-g733a5 From aa758d671f19c9d7398a78c11c0075f53b0c6c7f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 3 Jan 2018 20:36:52 +1300 Subject: Better handling of comments in macro defs --- src/macros.rs | 44 +++++++++++++------------------------------- tests/source/macros.rs | 8 ++++++++ tests/target/macros.rs | 12 +++++++++++- 3 files changed, 32 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index d642b31ef42..f09e884c670 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -316,19 +316,7 @@ pub fn rewrite_macro_def( // `$$`). We'll try and format like an AST node, but we'll substitute // variables for new names with the same length first. - let body_sp = match branch.body { - Some(sp) => sp, - None => { - // FIXME: should check the single-line empty function option - return Some(format!( - "{}macro {}({}) {{}}\n", - format_visibility(vis), - ident, - args_str, - )); - } - }; - let old_body = context.snippet(body_sp); + let old_body = context.snippet(branch.body).trim(); let (body_str, substs) = replace_names(old_body); // We'll hack the indent below, take this into account when formatting, @@ -350,7 +338,13 @@ pub fn rewrite_macro_def( let indent_str = indent.block_indent(&config).to_string(&config); let mut new_body = new_body .lines() - .map(|l| format!("{}{}", indent_str, l)) + .map(|l| { + if l.is_empty() { + l.to_owned() + } else { + format!("{}{}", indent_str, l) + } + }) .collect::>() .join("\n"); @@ -726,7 +720,10 @@ impl MacroParser { } let body = match self.toks.next()? { TokenTree::Token(..) => return None, - TokenTree::Delimited(_, ref d) => inner_span(d.tts.clone().into()), + TokenTree::Delimited(sp, _) => { + let data = sp.data(); + Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt) + } }; Some(MacroBranch { args, @@ -736,21 +733,6 @@ impl MacroParser { } } -fn inner_span(ts: TokenStream) -> Option { - let mut cursor = ts.trees(); - let first = match cursor.next() { - Some(t) => t.span(), - None => return None, - }; - - let last = match cursor.last() { - Some(t) => t.span(), - None => return Some(first), - }; - - Some(first.to(last)) -} - // A parsed macros 2.0 macro definition. struct Macro { branches: Vec, @@ -761,7 +743,7 @@ struct Macro { struct MacroBranch { args: ThinTokenStream, args_paren_kind: DelimToken, - body: Option, + body: Span, } #[cfg(test)] diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 45a40eded13..f5421b9fd09 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -312,3 +312,11 @@ pub macro bar($x:ident+$y:expr; ) { $x.bar($y)); } } + +macro foo() { + // a comment + fn foo() { + // another comment + bar(); + } +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index efb15831724..4fe81c800e4 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -823,7 +823,9 @@ fn macro_in_pattern_position() { }; } -macro foo() {} +macro foo() { + +} pub macro bar($x: ident + $y: expr;) { fn foo($x: Foo) { @@ -833,3 +835,11 @@ pub macro bar($x: ident + $y: expr;) { ); } } + +macro foo() { + // a comment + fn foo() { + // another comment + bar(); + } +} -- cgit 1.4.1-3-g733a5 From 361a30b159b40baf65d314e7498b71df83c206e3 Mon Sep 17 00:00:00 2001 From: Joost Hopmans Date: Wed, 3 Jan 2018 14:15:45 +0100 Subject: Rename git-fmt to git-rustfmt --- Cargo.toml | 2 +- src/bin/git-fmt.rs | 196 ------------------------------------------------- src/bin/git-rustfmt.rs | 196 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 197 deletions(-) delete mode 100644 src/bin/git-fmt.rs create mode 100644 src/bin/git-rustfmt.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index a0f974c6614..b2ecd547784 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ name = "cargo-fmt" name = "rustfmt-format-diff" [[bin]] -name = "git-fmt" +name = "git-rustfmt" [features] default = ["cargo-fmt", "rustfmt-format-diff"] diff --git a/src/bin/git-fmt.rs b/src/bin/git-fmt.rs deleted file mode 100644 index 5e7cb458649..00000000000 --- a/src/bin/git-fmt.rs +++ /dev/null @@ -1,196 +0,0 @@ -extern crate env_logger; -extern crate getopts; -#[macro_use] -extern crate log; -extern crate rustfmt_nightly as rustfmt; - -use std::env; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::str::FromStr; - -use getopts::{Matches, Options}; - -use rustfmt::{run, Input}; -use rustfmt::config; - -fn prune_files(files: Vec<&str>) -> Vec<&str> { - let prefixes: Vec<_> = files - .iter() - .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) - .map(|f| &f[..f.len() - 6]) - .collect(); - - let mut pruned_prefixes = vec![]; - for p1 in prefixes { - let mut include = true; - if !p1.starts_with("src/bin/") { - for p2 in &pruned_prefixes { - if p1.starts_with(p2) { - include = false; - break; - } - } - } - if include { - pruned_prefixes.push(p1); - } - } - debug!("prefixes: {:?}", pruned_prefixes); - - files - .into_iter() - .filter(|f| { - let mut include = true; - if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { - return true; - } - for pp in &pruned_prefixes { - if f.starts_with(pp) { - include = false; - break; - } - } - include - }) - .collect() -} - -fn git_diff(commits: &str) -> String { - let mut cmd = Command::new("git"); - cmd.arg("diff"); - if commits != "0" { - cmd.arg(format!("HEAD~{}", commits)); - } - let output = cmd.output().expect("Couldn't execute `git diff`"); - String::from_utf8_lossy(&output.stdout).into_owned() -} - -fn get_files(input: &str) -> Vec<&str> { - input - .lines() - .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) - .map(|line| &line[6..]) - .collect() -} - -fn fmt_files(files: &[&str]) -> i32 { - let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) - .unwrap_or_else(|_| (config::Config::default(), None)); - - let mut exit_code = 0; - for file in files { - let summary = run(Input::File(PathBuf::from(file)), &config); - if !summary.has_no_errors() { - exit_code = 1; - } - } - exit_code -} - -fn uncommitted_files() -> Vec { - let mut cmd = Command::new("git"); - cmd.arg("ls-files"); - cmd.arg("--others"); - cmd.arg("--modified"); - cmd.arg("--exclude-standard"); - let output = cmd.output().expect("Couldn't execute Git"); - let stdout = String::from_utf8_lossy(&output.stdout); - stdout - .lines() - .filter(|s| s.ends_with(".rs")) - .map(|s| s.to_owned()) - .collect() -} - -fn check_uncommitted() { - let uncommitted = uncommitted_files(); - debug!("uncommitted files: {:?}", uncommitted); - if !uncommitted.is_empty() { - println!("Found untracked changes:"); - for f in &uncommitted { - println!(" {}", f); - } - println!("Commit your work, or run with `-u`."); - println!("Exiting."); - std::process::exit(1); - } -} - -fn make_opts() -> Options { - let mut opts = Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("c", "check", "check only, don't format (unimplemented)"); - opts.optflag("u", "uncommitted", "format uncommitted files"); - opts -} - -struct Config { - commits: String, - uncommitted: bool, - check: bool, -} - -impl Config { - fn from_args(matches: &Matches, opts: &Options) -> Config { - // `--help` display help message and quit - if matches.opt_present("h") { - let message = format!( - "\nusage: {} [options]\n\n\ - commits: number of commits to format, default: 1", - env::args_os().next().unwrap().to_string_lossy() - ); - println!("{}", opts.usage(&message)); - std::process::exit(0); - } - - let mut config = Config { - commits: "1".to_owned(), - uncommitted: false, - check: false, - }; - - if matches.opt_present("c") { - config.check = true; - unimplemented!(); - } - - if matches.opt_present("u") { - config.uncommitted = true; - } - - if matches.free.len() > 1 { - panic!("unknown arguments, use `-h` for usage"); - } - if matches.free.len() == 1 { - let commits = matches.free[0].trim(); - if u32::from_str(commits).is_err() { - panic!("Couldn't parse number of commits"); - } - config.commits = commits.to_owned(); - } - - config - } -} - -fn main() { - let _ = env_logger::init(); - - let opts = make_opts(); - let matches = opts.parse(env::args().skip(1)) - .expect("Couldn't parse command line"); - let config = Config::from_args(&matches, &opts); - - if !config.uncommitted { - check_uncommitted(); - } - - let stdout = git_diff(&config.commits); - let files = get_files(&stdout); - debug!("files: {:?}", files); - let files = prune_files(files); - debug!("pruned files: {:?}", files); - let exit_code = fmt_files(&files); - std::process::exit(exit_code); -} diff --git a/src/bin/git-rustfmt.rs b/src/bin/git-rustfmt.rs new file mode 100644 index 00000000000..5e7cb458649 --- /dev/null +++ b/src/bin/git-rustfmt.rs @@ -0,0 +1,196 @@ +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate rustfmt_nightly as rustfmt; + +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::str::FromStr; + +use getopts::{Matches, Options}; + +use rustfmt::{run, Input}; +use rustfmt::config; + +fn prune_files(files: Vec<&str>) -> Vec<&str> { + let prefixes: Vec<_> = files + .iter() + .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) + .map(|f| &f[..f.len() - 6]) + .collect(); + + let mut pruned_prefixes = vec![]; + for p1 in prefixes { + let mut include = true; + if !p1.starts_with("src/bin/") { + for p2 in &pruned_prefixes { + if p1.starts_with(p2) { + include = false; + break; + } + } + } + if include { + pruned_prefixes.push(p1); + } + } + debug!("prefixes: {:?}", pruned_prefixes); + + files + .into_iter() + .filter(|f| { + let mut include = true; + if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { + return true; + } + for pp in &pruned_prefixes { + if f.starts_with(pp) { + include = false; + break; + } + } + include + }) + .collect() +} + +fn git_diff(commits: &str) -> String { + let mut cmd = Command::new("git"); + cmd.arg("diff"); + if commits != "0" { + cmd.arg(format!("HEAD~{}", commits)); + } + let output = cmd.output().expect("Couldn't execute `git diff`"); + String::from_utf8_lossy(&output.stdout).into_owned() +} + +fn get_files(input: &str) -> Vec<&str> { + input + .lines() + .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) + .map(|line| &line[6..]) + .collect() +} + +fn fmt_files(files: &[&str]) -> i32 { + let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) + .unwrap_or_else(|_| (config::Config::default(), None)); + + let mut exit_code = 0; + for file in files { + let summary = run(Input::File(PathBuf::from(file)), &config); + if !summary.has_no_errors() { + exit_code = 1; + } + } + exit_code +} + +fn uncommitted_files() -> Vec { + let mut cmd = Command::new("git"); + cmd.arg("ls-files"); + cmd.arg("--others"); + cmd.arg("--modified"); + cmd.arg("--exclude-standard"); + let output = cmd.output().expect("Couldn't execute Git"); + let stdout = String::from_utf8_lossy(&output.stdout); + stdout + .lines() + .filter(|s| s.ends_with(".rs")) + .map(|s| s.to_owned()) + .collect() +} + +fn check_uncommitted() { + let uncommitted = uncommitted_files(); + debug!("uncommitted files: {:?}", uncommitted); + if !uncommitted.is_empty() { + println!("Found untracked changes:"); + for f in &uncommitted { + println!(" {}", f); + } + println!("Commit your work, or run with `-u`."); + println!("Exiting."); + std::process::exit(1); + } +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("c", "check", "check only, don't format (unimplemented)"); + opts.optflag("u", "uncommitted", "format uncommitted files"); + opts +} + +struct Config { + commits: String, + uncommitted: bool, + check: bool, +} + +impl Config { + fn from_args(matches: &Matches, opts: &Options) -> Config { + // `--help` display help message and quit + if matches.opt_present("h") { + let message = format!( + "\nusage: {} [options]\n\n\ + commits: number of commits to format, default: 1", + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&message)); + std::process::exit(0); + } + + let mut config = Config { + commits: "1".to_owned(), + uncommitted: false, + check: false, + }; + + if matches.opt_present("c") { + config.check = true; + unimplemented!(); + } + + if matches.opt_present("u") { + config.uncommitted = true; + } + + if matches.free.len() > 1 { + panic!("unknown arguments, use `-h` for usage"); + } + if matches.free.len() == 1 { + let commits = matches.free[0].trim(); + if u32::from_str(commits).is_err() { + panic!("Couldn't parse number of commits"); + } + config.commits = commits.to_owned(); + } + + config + } +} + +fn main() { + let _ = env_logger::init(); + + let opts = make_opts(); + let matches = opts.parse(env::args().skip(1)) + .expect("Couldn't parse command line"); + let config = Config::from_args(&matches, &opts); + + if !config.uncommitted { + check_uncommitted(); + } + + let stdout = git_diff(&config.commits); + let files = get_files(&stdout); + debug!("files: {:?}", files); + let files = prune_files(files); + debug!("pruned files: {:?}", files); + let exit_code = fmt_files(&files); + std::process::exit(exit_code); +} -- cgit 1.4.1-3-g733a5 From c355f3854c0e6d751d493dca3782533918e8c84d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 2 Jan 2018 13:51:25 +0900 Subject: Use correct budget when rewriting generics of trait --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2de3a025e4d..93492e3f8e0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -938,7 +938,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.codemap.span_after(item.span, "{"); - let shape = Shape::indented(offset, context.config); + let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; result.push_str(&generics_str); -- cgit 1.4.1-3-g733a5 From 19d6a3c7868c5c887c1c617fbef86bba8718625c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 2 Jan 2018 13:52:19 +0900 Subject: Put the opening brace of impl on the next line We put the opening brace on the next line if the following conditions hold: 1. the result before '{' ends with comments or contains newline 2. the last line of the result before '{' is not extendable (i.e. consists of '>' and whitespaces). --- src/items.rs | 8 +++++--- src/utils.rs | 2 +- tests/target/trait.rs | 7 +++---- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 93492e3f8e0..d8d490f72c0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -33,8 +33,8 @@ use types::join_bounds; use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, - last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, - stmt_expr, trimmed_last_line_width}; + last_line_extendable, last_line_used_width, last_line_width, mk_sp, + semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -639,8 +639,10 @@ pub fn format_impl( } result.push_str(&where_clause_str); + let need_newline = !last_line_extendable(&result) + && (last_line_contains_single_line_comment(&result) || result.contains('\n')); match context.config.brace_style() { - _ if last_line_contains_single_line_comment(&result) => result.push_str(&sep), + _ if need_newline => result.push_str(&sep), BraceStyle::AlwaysNextLine => result.push_str(&sep), BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { diff --git a/src/utils.rs b/src/utils.rs index 73103e88a64..2f65d273246 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -178,7 +178,7 @@ pub fn last_line_extendable(s: &str) -> bool { } for c in s.chars().rev() { match c { - ')' | ']' | '}' | '?' => continue, + ')' | ']' | '}' | '?' | '>' => continue, '\n' => break, _ if c.is_whitespace() => continue, _ => return false, diff --git a/tests/target/trait.rs b/tests/target/trait.rs index e4d78f72229..133e8babedb 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -103,14 +103,13 @@ trait Foo { // #2331 trait MyTrait< AAAAAAAAAAAAAAAAAAAA, -BBBBBBBBBBBBBBBBBBBB, -CCCCCCCCCCCCCCCCCCCC, -DDDDDDDDDDDDDDDDDDDD, + BBBBBBBBBBBBBBBBBBBB, + CCCCCCCCCCCCCCCCCCCC, + DDDDDDDDDDDDDDDDDDDD, > { fn foo() {} } - // Trait aliases trait FooBar = Foo + Bar; trait FooBar = Foo + Bar; -- cgit 1.4.1-3-g733a5 From 75cb2367119aa577067b3266eae481c026974ec6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 4 Jan 2018 10:15:13 +0900 Subject: Compare extern crate items with its name instead of span When we use span, bugs easily sneak in. --- src/imports.rs | 27 +++++++++++++++++++++++---- src/lib.rs | 1 + tests/source/extern.rs | 4 ++++ tests/target/extern.rs | 6 +++++- 4 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index dac748af9b1..b940dcc9de7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -105,13 +105,32 @@ fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Orderi } } -fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> Option { +fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { match (&a.node, &b.node) { (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { Some(compare_use_trees(a_tree, b_tree, false)) } - (&ast::ItemKind::ExternCrate(..), &ast::ItemKind::ExternCrate(..)) => { - Some(context.snippet(a.span).cmp(context.snippet(b.span))) + (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { + // `extern crate foo as bar;` + // ^^^ Comparing this. + let a_orig_name = + a_name.map_or_else(|| a.ident.name.as_str(), |symbol| symbol.as_str()); + let b_orig_name = + b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); + let result = a_orig_name.cmp(&b_orig_name); + if result != Ordering::Equal { + return Some(result); + } + + // `extern crate foo as bar;` + // ^^^ Comparing this. + let result = match (a_name, b_name) { + (Some(..), None) => Ordering::Greater, + (None, Some(..)) => Ordering::Less, + (None, None) => Ordering::Equal, + (Some(..), Some(..)) => a.ident.name.cmp(&b.ident.name), + }; + Some(result) } _ => None, } @@ -257,7 +276,7 @@ fn rewrite_imports( false, ); let mut item_pair_vec: Vec<_> = items.zip(use_items.iter()).collect(); - item_pair_vec.sort_by(|a, b| compare_use_items(context, a.1, b.1).unwrap()); + item_pair_vec.sort_by(|a, b| compare_use_items(a.1, b.1).unwrap()); let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); let fmt = ListFormatting { diff --git a/src/lib.rs b/src/lib.rs index 111345a24b6..f9c9626a1f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(match_default_bindings)] #![feature(rustc_private)] #![feature(type_ascription)] diff --git a/tests/source/extern.rs b/tests/source/extern.rs index bc82bcd61db..187e698607a 100644 --- a/tests/source/extern.rs +++ b/tests/source/extern.rs @@ -10,6 +10,10 @@ extern crate chrono; extern crate foo; extern crate bar; +// #2315 +extern crate proc_macro2; +extern crate proc_macro; + extern "C" { fn c_func(x: *mut *mut libc::c_void); diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 1d49b76dc42..b0aa51127d5 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,7 +1,7 @@ // rustfmt-normalize_comments: true -extern crate foo as bar; extern crate foo; +extern crate foo as bar; extern crate chrono; extern crate dotenv; @@ -10,6 +10,10 @@ extern crate futures; extern crate bar; extern crate foo; +// #2315 +extern crate proc_macro; +extern crate proc_macro2; + extern "C" { fn c_func(x: *mut *mut libc::c_void); -- cgit 1.4.1-3-g733a5 From 405360a3fd6ef6b4bebbd60637acee2d66a46978 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 4 Jan 2018 10:16:59 +0900 Subject: Refactoring: use methods from libsyntax attr module --- src/visitor.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 3e454876307..d544eb9b2df 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1056,27 +1056,16 @@ fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) - } fn is_derive(attr: &ast::Attribute) -> bool { - match attr.meta() { - Some(meta_item) => match meta_item.node { - ast::MetaItemKind::List(..) => meta_item.name.as_str() == "derive", - _ => false, - }, - _ => false, - } + attr.check_name("derive") } /// Returns the arguments of `#[derive(...)]`. fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { - attr.meta().and_then(|meta_item| match meta_item.node { - ast::MetaItemKind::List(ref args) if meta_item.name.as_str() == "derive" => { - // Every argument of `derive` should be `NestedMetaItemKind::Literal`. - Some( - args.iter() - .map(|a| context.snippet(a.span)) - .collect::>(), - ) - } - _ => None, + attr.meta_item_list().map(|meta_item_list| { + meta_item_list + .iter() + .map(|nested_meta_item| context.snippet(nested_meta_item.span)) + .collect() }) } -- cgit 1.4.1-3-g733a5 From 3345b00952251e7b2141c1d064ec4dc988adcb50 Mon Sep 17 00:00:00 2001 From: Vishal Sodani Date: Thu, 4 Jan 2018 09:37:08 +0530 Subject: Fix #2300 --- src/config.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index fb0cdf6aaf2..cfbc1e181bf 100644 --- a/src/config.rs +++ b/src/config.rs @@ -518,6 +518,7 @@ macro_rules! create_config { pub fn print_docs() { use std::cmp; + const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"]; let max = 0; $( let max = cmp::max(max, stringify!($i).len()+1); )+ let mut space_str = String::with_capacity(max); @@ -527,20 +528,23 @@ macro_rules! create_config { println!("Configuration Options:"); $( let name_raw = stringify!($i); - let mut name_out = String::with_capacity(max); - for _ in name_raw.len()..max-1 { - name_out.push(' ') + + if !HIDE_OPTIONS.contains(&name_raw) { + let mut name_out = String::with_capacity(max); + for _ in name_raw.len()..max-1 { + name_out.push(' ') + } + name_out.push_str(name_raw); + name_out.push(' '); + println!("{}{} Default: {:?}", + name_out, + <$ty>::doc_hint(), + $def); + $( + println!("{}{}", space_str, $dstring); + )+ + println!(); } - name_out.push_str(name_raw); - name_out.push(' '); - println!("{}{} Default: {:?}", - name_out, - <$ty>::doc_hint(), - $def); - $( - println!("{}{}", space_str, $dstring); - )+ - println!(); )+ } -- cgit 1.4.1-3-g733a5 From 85ccb98469596a595e747466b7fd789971203a6d Mon Sep 17 00:00:00 2001 From: David Alber Date: Wed, 13 Dec 2017 00:40:07 -0800 Subject: Adding test to verify code block idempotency in Configurations.md --- Cargo.lock | 1 + Cargo.toml | 3 + Configurations.md | 4 +- src/rustfmt_diff.rs | 23 ++++- tests/system.rs | 277 +++++++++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 288 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 672c5f59da3..3349ad3410a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,6 +191,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index b2ecd547784..dd748d46854 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,9 @@ getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.4" +[dev-dependencies] +lazy_static = "1.0.0" + [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/Configurations.md b/Configurations.md index 37e6fa0a998..b91f39f31ca 100644 --- a/Configurations.md +++ b/Configurations.md @@ -511,12 +511,12 @@ Maximum length of comments. No effect unless`wrap_comments = true`. **Note:** A value of `0` results in [`wrap_comments`](#wrap_comments) being applied regardless of a line's width. -#### Comments shorter than `comment_width`: +#### `80` (default; comments shorter than `comment_width`): ```rust // Lorem ipsum dolor sit amet, consectetur adipiscing elit. ``` -#### Comments longer than `comment_width`: +#### `60` (comments longer than `comment_width`): ```rust // Lorem ipsum dolor sit amet, // consectetur adipiscing elit. diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 69633568755..f37ab5c16ef 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -97,15 +97,28 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec Self { + match term::stdout() { + Some(ref t) if use_colored_tty(color) && t.supports_color() => PrintType::Fancy, + _ => PrintType::Basic, + } + } +} + pub fn print_diff(diff: Vec, get_section_title: F, color: Color) where F: Fn(u32) -> String, { - match term::stdout() { - Some(ref t) if use_colored_tty(color) && t.supports_color() => { - print_diff_fancy(diff, get_section_title, term::stdout().unwrap()) - } - _ => print_diff_basic(diff, get_section_title), + match PrintType::get(color) { + PrintType::Fancy => print_diff_fancy(diff, get_section_title, term::stdout().unwrap()), + PrintType::Basic => print_diff_basic(diff, get_section_title), } } diff --git a/tests/system.rs b/tests/system.rs index dceb5600634..a551ca67eae 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -10,6 +10,8 @@ #![feature(rustc_private)] +#[macro_use] +extern crate lazy_static; #[macro_use] extern crate log; extern crate regex; @@ -19,7 +21,7 @@ extern crate term; use std::collections::HashMap; use std::fs; use std::io::{self, BufRead, BufReader, Read}; -use std::iter::Peekable; +use std::iter::{Enumerate, Peekable}; use std::path::{Path, PathBuf}; use std::str::Chars; @@ -29,6 +31,7 @@ use rustfmt::filemap::{write_system_newlines, FileMap}; use rustfmt::rustfmt_diff::*; const DIFF_CONTEXT_SIZE: usize = 3; +const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; // Returns a `Vec` containing `PathBuf`s of files with a rs extension in the // given path. The `recursive` argument controls if files from subdirectories @@ -98,6 +101,17 @@ fn verify_config_test_names() { } } +// This writes to the terminal using the same approach (via term::stdout or +// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing +// using only one or the other will cause the output order to differ when +// `print_diff` selects the approach not used. +fn write_message(msg: String) { + match PrintType::get(Color::Auto) { + PrintType::Fancy => writeln!(term::stdout().unwrap(), "{}", msg).unwrap(), + PrintType::Basic => println!("{}", msg), + } +} + // Integration tests. The files in the tests/source are formatted and compared // to their equivalent in tests/target. The target file and config can be // overridden by annotations in the source file. The input and output must match @@ -152,7 +166,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { if !compare.is_empty() { let mut failures = HashMap::new(); failures.insert(source.to_owned(), compare); - print_mismatches(failures); + print_mismatches_default_message(failures, source.display()); assert!(false, "Text does not match expected output"); } } @@ -259,7 +273,7 @@ fn check_files(files: Vec) -> (Vec, u32, u32) { for file_name in files { debug!("Testing '{}'...", file_name.display()); - match idempotent_check(file_name) { + match idempotent_check(&file_name) { Ok(ref report) if report.has_warnings() => { print!("{}", report); fails += 1; @@ -267,7 +281,7 @@ fn check_files(files: Vec) -> (Vec, u32, u32) { Ok(report) => reports.push(report), Err(err) => { if let IdempotentCheckError::Mismatch(msg) = err { - print_mismatches(msg); + print_mismatches_default_message(msg, file_name.display()); } fails += 1; } @@ -279,15 +293,22 @@ fn check_files(files: Vec) -> (Vec, u32, u32) { (reports, count, fails) } -fn print_mismatches(result: HashMap>) { - let mut t = term::stdout().unwrap(); +fn print_mismatches_default_message( + result: HashMap>, + file_name: std::path::Display, +) { + print_mismatches(result, |line_num| { + format!("\nMismatch at {}:{}:", file_name, line_num) + }); +} - for (file_name, diff) in result { - print_diff( - diff, - |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num), - Color::Auto, - ); +fn print_mismatches String>( + result: HashMap>, + mismatch_msg_formatter: T, +) { + let mut t = term::stdout().unwrap(); + for (_file_name, diff) in result { + print_diff(diff, &mismatch_msg_formatter, Color::Auto); } t.reset().unwrap(); @@ -327,7 +348,7 @@ pub enum IdempotentCheckError { Parse, } -pub fn idempotent_check(filename: PathBuf) -> Result { +pub fn idempotent_check(filename: &PathBuf) -> Result { let sig_comments = read_significant_comments(&filename); let config = read_config(&filename); let (error_summary, file_map, format_report) = format_file(filename, &config); @@ -536,3 +557,233 @@ fn string_eq_ignore_newline_repr_test() { assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); } + +// This enum is used to represent one of three text features in Configurations.md: a block of code +// with its starting line number, the name of a rustfmt configuration option, or the value of a +// rustfmt configuration option. +enum ConfigurationSection { + CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) + ConfigName(String), + ConfigValue(String), +} + +impl ConfigurationSection { + fn get_section>( + file: &mut Enumerate, + ) -> Option { + lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#).expect("Failed creating configuration value pattern"); + } + + loop { + match file.next() { + Some((i, line)) => { + if line.starts_with("```rust") { + // Get the lines of the code block. + let lines: Vec = file.map(|(_i, l)| l) + .take_while(|l| !l.starts_with("```")) + .collect(); + let block = format!("{}\n", lines.join("\n")); + + // +1 to translate to one-based indexing + // +1 to get to first line of code (line after "```") + let start_line = (i + 2) as u32; + + return Some(ConfigurationSection::CodeBlock((block, start_line))); + } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); + } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); + } + } + None => return None, // reached the end of the file + } + } + } +} + +// This struct stores the information about code blocks in the configurations +// file, formats the code blocks, and prints formatting errors. +struct ConfigCodeBlock { + config_name: Option, + config_value: Option, + code_block: Option, + code_block_start: Option, +} + +impl ConfigCodeBlock { + fn new() -> ConfigCodeBlock { + ConfigCodeBlock { + config_name: None, + config_value: None, + code_block: None, + code_block_start: None, + } + } + + fn set_config_name(&mut self, name: Option) { + self.config_name = name; + self.config_value = None; + } + + fn set_config_value(&mut self, value: Option) { + self.config_value = value; + } + + fn set_code_block(&mut self, code_block: String, code_block_start: u32) { + self.code_block = Some(code_block); + self.code_block_start = Some(code_block_start); + } + + fn get_block_config(&self) -> Config { + let mut config = Config::default(); + config.override_value( + self.config_name.as_ref().unwrap(), + self.config_value.as_ref().unwrap(), + ); + config + } + + fn code_block_valid(&self) -> bool { + // We never expect to not have a code block. + assert!(self.code_block.is_some() && self.code_block_start.is_some()); + + if self.config_name.is_none() { + write_message(format!( + "configuration name not found for block beginning at line {}", + self.code_block_start.unwrap() + )); + return false; + } + if self.config_value.is_none() { + write_message(format!( + "configuration value not found for block beginning at line {}", + self.code_block_start.unwrap() + )); + return false; + } + true + } + + fn has_parsing_errors(&self, error_summary: Summary) -> bool { + if error_summary.has_parsing_errors() { + write_message(format!( + "\u{261d}\u{1f3fd} Failed to format block starting at Line {} in {}", + self.code_block_start.unwrap(), + CONFIGURATIONS_FILE_NAME + )); + return true; + } + + false + } + + fn print_diff(&self, compare: Vec) { + let mut mismatches = HashMap::new(); + mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); + print_mismatches(mismatches, |line_num| { + format!( + "\nMismatch at {}:{}:", + CONFIGURATIONS_FILE_NAME, + line_num + self.code_block_start.unwrap() - 1 + ) + }); + } + + fn formatted_has_diff(&self, file_map: FileMap) -> bool { + let &(ref _file_name, ref text) = file_map.first().unwrap(); + let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + self.print_diff(compare); + return true; + } + + false + } + + // Return a bool indicating if formatting this code block is an idempotent + // operation. This function also triggers printing any formatting failure + // messages. + fn formatted_is_idempotent(&self) -> bool { + // Verify that we have all of the expected information. + if !self.code_block_valid() { + return false; + } + + let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); + let config = self.get_block_config(); + + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + + !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(file_map) + } + + // Extract a code block from the iterator. Behavior: + // - Rust code blocks are identifed by lines beginning with "```rust". + // - One explicit configuration setting is supported per code block. + // - Rust code blocks with no configuration setting are illegal and cause an + // assertion failure. + // - Configuration names in Configurations.md must be in the form of + // "## `NAME`". + // - Configuration values in Configurations.md must be in the form of + // "#### `VALUE`". + fn extract>( + file: &mut Enumerate, + prev: Option<&ConfigCodeBlock>, + ) -> Option { + let mut code_block = ConfigCodeBlock::new(); + code_block.config_name = prev.map_or(None, |cb| cb.config_name.clone()); + + loop { + match ConfigurationSection::get_section(file) { + Some(ConfigurationSection::CodeBlock((block, start_line))) => { + code_block.set_code_block(block, start_line); + break; + } + Some(ConfigurationSection::ConfigName(name)) => { + code_block.set_config_name(Some(name)); + } + Some(ConfigurationSection::ConfigValue(value)) => { + code_block.set_config_value(Some(value)); + } + None => return None, // end of file was reached + } + } + + Some(code_block) + } +} + +#[test] +#[ignore] +fn configuration_snippet_tests() { + // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one + // entry for each Rust code block found. + fn get_code_blocks() -> Vec { + let mut file_iter = BufReader::new( + fs::File::open(CONFIGURATIONS_FILE_NAME) + .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + ).lines() + .map(|l| l.unwrap()) + .enumerate(); + let mut code_blocks: Vec = Vec::new(); + + while let Some(cb) = ConfigCodeBlock::extract(&mut file_iter, code_blocks.last()) { + code_blocks.push(cb); + } + + code_blocks + } + + let blocks = get_code_blocks(); + let failures = blocks + .iter() + .map(|b| b.formatted_is_idempotent()) + .fold(0, |acc, r| acc + (!r as u32)); + + // Display results. + println!("Ran {} configurations tests.", blocks.len()); + assert_eq!(failures, 0, "{} configurations tests failed", failures); +} -- cgit 1.4.1-3-g733a5 From d981fb89c002ab2781704728ee4d2f63ac5a6f08 Mon Sep 17 00:00:00 2001 From: David Alber Date: Sat, 6 Jan 2018 21:23:54 -0800 Subject: Removing unused name --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e64ea7436e3..77cea7de4c6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -10,7 +10,7 @@ use std::borrow::Cow; use std::cmp::min; -use std::iter::{repeat, ExactSizeIterator}; +use std::iter::repeat; use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; -- cgit 1.4.1-3-g733a5 From 590857db3726c2de8903d443964bb28f32a1fc5e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 10 Jan 2018 17:15:02 +0900 Subject: Reformat a nested function call with a single newline using larger budget --- src/expr.rs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 77cea7de4c6..157147c4a06 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,9 +31,10 @@ use shape::{Indent, Shape}; use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; -use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead, - ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, wrap_str}; +use utils::{colon_spaces, contains_skip, count_newlines, extra_offset, first_line_width, + inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, + paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, + wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -2053,6 +2054,26 @@ where // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. match (overflow_last, tactic, placeholder) { + (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) if args.len() == 1 => { + // When we are rewriting a nested function call, we restrict the + // bugdet for the inner function to avoid them being deeply nested. + // However, when the inner function has a prefix or a suffix + // (e.g. `foo() as u32`), this budget reduction may produce poorly + // formatted code, where a prefix or a suffix being left on its own + // line. Here we explicitlly check those cases. + if count_newlines(overflowed) == 1 { + let rw = args.last() + .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); + let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); + if no_newline { + item_vec[args.len() - 1].item = rw; + } else { + item_vec[args.len() - 1].item = Some(overflowed.to_owned()); + } + } else { + item_vec[args.len() - 1].item = Some(overflowed.to_owned()); + } + } (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { item_vec[args.len() - 1].item = placeholder; } @@ -2824,7 +2845,6 @@ pub fn choose_rhs( } fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - use utils::count_newlines; !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } -- cgit 1.4.1-3-g733a5 From cb0b366b381e4268ce9ce4f1669c2745af01f17e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 10 Jan 2018 17:17:06 +0900 Subject: Cargo fmt --- src/items.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d8d490f72c0..32f0ae1c9f0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1343,8 +1343,9 @@ fn format_tuple_struct( // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); - result.push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) - .to_string(context.config)); + result + .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) + .to_string(context.config)); } result.push_str(&where_clause_str); -- cgit 1.4.1-3-g733a5 From 949708f617ae7e815da8ebd69b7128c5ae184299 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 10 Jan 2018 21:30:41 +0900 Subject: Use correct BytePos when recovering comments on removed import --- src/imports.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index b940dcc9de7..c49a95b6ff7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -314,11 +314,14 @@ impl<'a> FmtVisitor<'a> { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); - let span_end = match self.snippet(prev_span).rfind('\n') { - Some(offset) => self.last_pos + BytePos(offset as u32), - None => source!(self, span).lo(), - }; + let trimmed_snippet = self.snippet(prev_span).trim_right(); + let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32); self.format_missing(span_end); + // We have an excessive newline from the removed import. + if self.buffer.ends_with('\n') { + self.buffer.pop(); + self.line_number -= 1; + } self.last_pos = source!(self, span).hi(); } Some(ref s) => { -- cgit 1.4.1-3-g733a5 From eaab51db2eafae35d8e631ecd5ed90673c783336 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 10 Jan 2018 23:23:42 +0900 Subject: Break after colon if static item does not fit in a single line --- src/items.rs | 15 +++++++++++++-- tests/source/static.rs | 2 ++ tests/target/static.rs | 3 +++ 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d8d490f72c0..183373c7347 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1566,7 +1566,7 @@ fn rewrite_static( context.config.space_before_colon(), context.config.space_after_colon(), ); - let prefix = format!( + let mut prefix = format!( "{}{}{} {}{}{}", format_visibility(static_parts.vis), static_parts.defaultness.map_or("", format_defaultness), @@ -1578,7 +1578,18 @@ fn rewrite_static( // 2 = " =".len() let ty_shape = Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; - let ty_str = static_parts.ty.rewrite(context, ty_shape)?; + let ty_str = match static_parts.ty.rewrite(context, ty_shape) { + Some(ty_str) => ty_str, + None => { + if prefix.ends_with(' ') { + prefix.pop(); + } + let nested_indent = offset.block_indent(context.config); + let nested_shape = Shape::indented(nested_indent, context.config); + let ty_str = static_parts.ty.rewrite(context, nested_shape)?; + format!("\n{}{}", nested_indent.to_string(context.config), ty_str) + } + }; if let Some(expr) = static_parts.expr_opt { let lhs = format!("{}{} =", prefix, ty_str); diff --git a/tests/source/static.rs b/tests/source/static.rs index b51c56d1205..970786381cc 100644 --- a/tests/source/static.rs +++ b/tests/source/static.rs @@ -19,3 +19,5 @@ impl Color { // #1391 pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; + +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/tests/target/static.rs b/tests/target/static.rs index dc1a5c78c5d..5daccf3e7f7 100644 --- a/tests/target/static.rs +++ b/tests/target/static.rs @@ -22,3 +22,6 @@ impl Color { // #1391 pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; + +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: + Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; -- cgit 1.4.1-3-g733a5 From 1ced6d1037d6dfc88b84c94275fb618be4bf4daf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 11 Jan 2018 17:40:05 +1300 Subject: Minor refactoring in macros.rs --- src/macros.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index f09e884c670..926c76dce7f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -40,7 +40,7 @@ use utils::{format_visibility, mk_sp}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; // FIXME: use the enum from libsyntax? -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] enum MacroStyle { Parens, Brackets, @@ -65,6 +65,7 @@ impl MacroStyle { } } +#[derive(Debug)] pub enum MacroArg { Expr(ast::Expr), Ty(ast::Ty), @@ -83,16 +84,16 @@ impl Rewrite for MacroArg { fn parse_macro_arg(parser: &mut Parser) -> Option { macro_rules! parse_macro_arg { - ($target:tt, $macro_arg:ident, $parser:ident) => { + ($macro_arg: ident, $parser: ident) => { let mut cloned_parser = (*parser).clone(); match cloned_parser.$parser() { - Ok($target) => { + Ok(x) => { if parser.sess.span_diagnostic.has_errors() { parser.sess.span_diagnostic.reset_err_count(); } else { // Parsing succeeded. *parser = cloned_parser; - return Some(MacroArg::$macro_arg((*$target).clone())); + return Some(MacroArg::$macro_arg((*x).clone())); } } Err(mut e) => { @@ -103,9 +104,9 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { } } - parse_macro_arg!(expr, Expr, parse_expr); - parse_macro_arg!(ty, Ty, parse_ty); - parse_macro_arg!(pat, Pat, parse_pat); + parse_macro_arg!(Expr, parse_expr); + parse_macro_arg!(Ty, parse_ty); + parse_macro_arg!(Pat, parse_pat); None } -- cgit 1.4.1-3-g733a5 From cf4ab38f6774e3b348a04f0ccfed39b32de0d409 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 11 Jan 2018 15:19:23 +0900 Subject: Hide parse error in format_snippet() --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index f9c9626a1f5..e24a6c1949c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -540,6 +540,7 @@ pub fn format_snippet(snippet: &str, config: &Config) -> Option { let input = Input::Text(snippet.into()); let mut config = config.clone(); config.set().write_mode(config::WriteMode::Plain); + config.set().hide_parse_errors(true); match format_input(input, &config, Some(&mut out)) { // `format_input()` returns an empty string on parsing error. Ok(..) if out.is_empty() && !snippet.is_empty() => None, -- cgit 1.4.1-3-g733a5 From 279acda4c40080887afb50057bbe773234c88bc5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 11 Jan 2018 16:52:28 +0900 Subject: Remove same_line_attributes config option --- Configurations.md | 47 ---------------------- src/config.rs | 2 - tests/source/configs/same_line_attributes/false.rs | 26 ------------ tests/source/configs/same_line_attributes/true.rs | 20 --------- tests/target/configs/same_line_attributes/false.rs | 26 ------------ tests/target/configs/same_line_attributes/true.rs | 14 ------- 6 files changed, 135 deletions(-) delete mode 100644 tests/source/configs/same_line_attributes/false.rs delete mode 100644 tests/source/configs/same_line_attributes/true.rs delete mode 100644 tests/target/configs/same_line_attributes/false.rs delete mode 100644 tests/target/configs/same_line_attributes/true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index b91f39f31ca..4b19ea07912 100644 --- a/Configurations.md +++ b/Configurations.md @@ -246,53 +246,6 @@ fn lorem() -> T } ``` - -## `same_line_attributes` - -Try to put attributes on the same line as fields and variants - -- **Default value**: `true` -- **Possible values**: `true`, `false` -- **Stable**: No - -#### `true` (default): - -```rust -struct Lorem { - #[serde(rename = "Ipsum")] ipsum: usize, - #[serde(rename = "Dolor")] dolor: usize, - #[serde(rename = "Amet")] amet: usize, -} - -enum Lorem { - #[serde(skip_serializing)] Ipsum, - #[serde(skip_serializing)] Dolor, - #[serde(skip_serializing)] Amet, -} -``` - -#### `false`: - -```rust -struct Lorem { - #[serde(rename = "Ipsum")] - ipsum: usize, - #[serde(rename = "Dolor")] - dolor: usize, - #[serde(rename = "Amet")] - amet: usize, -} - -enum Lorem { - #[serde(skip_serializing)] - Ipsum, - #[serde(skip_serializing)] - Dolor, - #[serde(skip_serializing)] - Amet, -} -``` - ## `use_small_heuristics` Whether to use different formatting for items and expressions if they satisfy a heuristic notion of 'small'. diff --git a/src/config.rs b/src/config.rs index cfbc1e181bf..954858b93a6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -648,8 +648,6 @@ create_config! { threshold."; remove_blank_lines_at_start_or_end_of_block: bool, true, false, "Remove blank lines at start or end of a block"; - same_line_attributes: bool, true, false, - "Try to put attributes on the same line as fields and variants."; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; force_multiline_blocks: bool, false, false, diff --git a/tests/source/configs/same_line_attributes/false.rs b/tests/source/configs/same_line_attributes/false.rs deleted file mode 100644 index a7983fdd092..00000000000 --- a/tests/source/configs/same_line_attributes/false.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-same_line_attributes: false -// Option to place attributes on the same line as fields and variants where possible - -enum Lorem { - #[ serde(skip_serializing) ] - Ipsum, - #[ serde(skip_serializing) ] - Dolor, - #[ serde(skip_serializing) ] - Amet, -} - -struct Lorem { - #[ serde(rename = "Ipsum") ] - ipsum: usize, - #[ serde(rename = "Dolor") ] - dolor: usize, - #[ serde(rename = "Amet") ] - amet: usize, -} - -// #1943 -pub struct Bzip2 { - # [ serde (rename = "level") ] - level: i32 , -} diff --git a/tests/source/configs/same_line_attributes/true.rs b/tests/source/configs/same_line_attributes/true.rs deleted file mode 100644 index bf796954dd4..00000000000 --- a/tests/source/configs/same_line_attributes/true.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-same_line_attributes: true -// Option to place attributes on the same line as fields and variants where possible - -enum Lorem { - #[ serde(skip_serializing) ] - Ipsum, - #[ serde(skip_serializing) ] - Dolor, - #[ serde(skip_serializing) ] - Amet, -} - -struct Lorem { - #[ serde(rename = "Ipsum") ] - ipsum: usize, - #[ serde(rename = "Dolor") ] - dolor: usize, - #[ serde(rename = "Amet") ] - amet: usize, -} diff --git a/tests/target/configs/same_line_attributes/false.rs b/tests/target/configs/same_line_attributes/false.rs deleted file mode 100644 index 84ac3517411..00000000000 --- a/tests/target/configs/same_line_attributes/false.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-same_line_attributes: false -// Option to place attributes on the same line as fields and variants where possible - -enum Lorem { - #[serde(skip_serializing)] - Ipsum, - #[serde(skip_serializing)] - Dolor, - #[serde(skip_serializing)] - Amet, -} - -struct Lorem { - #[serde(rename = "Ipsum")] - ipsum: usize, - #[serde(rename = "Dolor")] - dolor: usize, - #[serde(rename = "Amet")] - amet: usize, -} - -// #1943 -pub struct Bzip2 { - #[serde(rename = "level")] - level: i32, -} diff --git a/tests/target/configs/same_line_attributes/true.rs b/tests/target/configs/same_line_attributes/true.rs deleted file mode 100644 index c2d48bb0ba1..00000000000 --- a/tests/target/configs/same_line_attributes/true.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-same_line_attributes: true -// Option to place attributes on the same line as fields and variants where possible - -enum Lorem { - #[serde(skip_serializing)] Ipsum, - #[serde(skip_serializing)] Dolor, - #[serde(skip_serializing)] Amet, -} - -struct Lorem { - #[serde(rename = "Ipsum")] ipsum: usize, - #[serde(rename = "Dolor")] dolor: usize, - #[serde(rename = "Amet")] amet: usize, -} -- cgit 1.4.1-3-g733a5 From 2420d346c57557fa42b25f0bcc2cb50db3922b47 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 11 Jan 2018 16:55:50 +0900 Subject: Put attributes and struct fields on different line --- src/file_lines.rs | 3 ++- src/items.rs | 7 ++----- src/vertical.rs | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/file_lines.rs b/src/file_lines.rs index 82844a4b222..7f2273c6f69 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -204,7 +204,8 @@ impl str::FromStr for FileLines { // For JSON decoding. #[derive(Clone, Debug, Deserialize)] struct JsonSpan { - #[serde(deserialize_with = "deserialize_filename")] file: FileName, + #[serde(deserialize_with = "deserialize_filename")] + file: FileName, range: (usize, usize), } diff --git a/src/items.rs b/src/items.rs index d8d490f72c0..39fb129cd4d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -558,15 +558,13 @@ impl<'a> FmtVisitor<'a> { } }; - let attrs_extendable = attrs_str.is_empty() - || (context.config.same_line_attributes() && is_attributes_extendable(&attrs_str)); combine_strs_with_missing_comments( &context, &attrs_str, &variant_body, span, shape, - attrs_extendable, + is_attributes_extendable(&attrs_str), ) } } @@ -1439,8 +1437,7 @@ pub fn rewrite_struct_field( let prefix = rewrite_struct_field_prefix(context, field)?; let attrs_str = field.attrs.rewrite(context, shape)?; - let attrs_extendable = attrs_str.is_empty() - || (context.config.same_line_attributes() && is_attributes_extendable(&attrs_str)); + let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str); let missing_span = if field.attrs.is_empty() { mk_sp(field.span.lo(), field.span.lo()) } else { diff --git a/src/vertical.rs b/src/vertical.rs index 9644f76cca4..e56410202eb 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -54,8 +54,7 @@ impl AlignedItem for ast::StructField { } else { mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) }; - let attrs_extendable = - context.config.same_line_attributes() && is_attributes_extendable(&attrs_str); + let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str); rewrite_struct_field_prefix(context, self).and_then(|field_str| { combine_strs_with_missing_comments( context, -- cgit 1.4.1-3-g733a5 From 2e82ad8c365caf103df95e321446ec6779b370cb Mon Sep 17 00:00:00 2001 From: Pascal Seitz Date: Thu, 11 Jan 2018 11:04:28 +0100 Subject: case insensitive FIXME and TODO --- src/issues.rs | 87 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/issues.rs b/src/issues.rs index 8bb1218f88a..6cd0586f3e4 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -16,8 +16,8 @@ use std::fmt; pub use config::ReportTactic; -const TO_DO_CHARS: &[char] = &['T', 'O', 'D', 'O']; -const FIX_ME_CHARS: &[char] = &['F', 'I', 'X', 'M', 'E']; +const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o']; +const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e']; // Enabled implementation detail is here because it is // irrelevant outside the issues module @@ -127,44 +127,45 @@ impl BadIssueSeeker { } fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking { - // FIXME: Should we also check for lower case characters? - if self.report_todo.is_enabled() && c == TO_DO_CHARS[todo_idx] { - todo_idx += 1; - if todo_idx == TO_DO_CHARS.len() { - return Seeking::Number { - issue: Issue { - issue_type: IssueType::Todo, - missing_number: if let ReportTactic::Unnumbered = self.report_todo { - true - } else { - false + if let Some(lower_case_c) = c.to_lowercase().next() { + if self.report_todo.is_enabled() && lower_case_c == TO_DO_CHARS[todo_idx] { + todo_idx += 1; + if todo_idx == TO_DO_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Todo, + missing_number: if let ReportTactic::Unnumbered = self.report_todo { + true + } else { + false + }, }, - }, - part: NumberPart::OpenParen, - }; - } - fixme_idx = 0; - } else if self.report_fixme.is_enabled() && c == FIX_ME_CHARS[fixme_idx] { - // Exploit the fact that the character sets of todo and fixme - // are disjoint by adding else. - fixme_idx += 1; - if fixme_idx == FIX_ME_CHARS.len() { - return Seeking::Number { - issue: Issue { - issue_type: IssueType::Fixme, - missing_number: if let ReportTactic::Unnumbered = self.report_fixme { - true - } else { - false + part: NumberPart::OpenParen, + }; + } + fixme_idx = 0; + } else if self.report_fixme.is_enabled() && lower_case_c == FIX_ME_CHARS[fixme_idx] { + // Exploit the fact that the character sets of todo and fixme + // are disjoint by adding else. + fixme_idx += 1; + if fixme_idx == FIX_ME_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Fixme, + missing_number: if let ReportTactic::Unnumbered = self.report_fixme { + true + } else { + false + }, }, - }, - part: NumberPart::OpenParen, - }; + part: NumberPart::OpenParen, + }; + } + todo_idx = 0; + } else { + todo_idx = 0; + fixme_idx = 0; } - todo_idx = 0; - } else { - todo_idx = 0; - fixme_idx = 0; } Seeking::Issue { @@ -268,12 +269,24 @@ fn find_issue() { ReportTactic::Always, )); + assert!(!is_bad_issue( + "Todo: mixed case\n", + ReportTactic::Never, + ReportTactic::Always, + )); + assert!(is_bad_issue( "This is a FIXME(#1)\n", ReportTactic::Never, ReportTactic::Always, )); + assert!(is_bad_issue( + "This is a FixMe(#1) mixed case\n", + ReportTactic::Never, + ReportTactic::Always, + )); + assert!(!is_bad_issue( "bad FIXME\n", ReportTactic::Always, -- cgit 1.4.1-3-g733a5 From 9f5f9d2250c03dc915ab949c59dbdbffead5b72b Mon Sep 17 00:00:00 2001 From: David Alber Date: Sat, 6 Jan 2018 00:32:48 -0800 Subject: Consolidating the logic for printing output --- src/rustfmt_diff.rs | 103 +++++++++++++++++++++------------------------------- tests/system.rs | 6 +-- 2 files changed, 44 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index f37ab5c16ef..d563e6eee3c 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -37,6 +37,43 @@ impl Mismatch { } } +// This struct handles writing output to stdout and abstracts away the logic +// of printing in color, if it's possible in the executing environment. +pub struct OutputWriter { + terminal: Option>>, +} + +impl OutputWriter { + // Create a new OutputWriter instance based on the caller's preference + // for colorized output and the capabilities of the terminal. + pub fn new(color: Color) -> Self { + if let Some(t) = term::stdout() { + if use_colored_tty(color) && t.supports_color() { + return OutputWriter { terminal: Some(t) }; + } + } + OutputWriter { terminal: None } + } + + // Write output in the optionally specified color. The output is written + // in the specified color if this OutputWriter instance contains a + // Terminal in its `terminal` field. + pub fn writeln(&mut self, msg: &str, color: Option) { + match &mut self.terminal { + Some(ref mut t) => { + if let Some(color) = color { + t.fg(color).unwrap(); + } + writeln!(t, "{}", msg).unwrap(); + if color.is_some() { + t.reset().unwrap(); + } + } + None => println!("{}", msg), + } + } +} + // Produces a diff between the expected output and actual output of rustfmt. pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { let mut line_number = 1; @@ -97,80 +134,24 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec Self { - match term::stdout() { - Some(ref t) if use_colored_tty(color) && t.supports_color() => PrintType::Fancy, - _ => PrintType::Basic, - } - } -} - pub fn print_diff(diff: Vec, get_section_title: F, color: Color) where F: Fn(u32) -> String, { - match PrintType::get(color) { - PrintType::Fancy => print_diff_fancy(diff, get_section_title, term::stdout().unwrap()), - PrintType::Basic => print_diff_basic(diff, get_section_title), - } -} - -fn print_diff_fancy( - diff: Vec, - get_section_title: F, - mut t: Box>, -) where - F: Fn(u32) -> String, -{ - for mismatch in diff { - let title = get_section_title(mismatch.line_number); - writeln!(t, "{}", title).unwrap(); - - for line in mismatch.lines { - match line { - DiffLine::Context(ref str) => { - t.reset().unwrap(); - writeln!(t, " {}⏎", str).unwrap(); - } - DiffLine::Expected(ref str) => { - t.fg(term::color::GREEN).unwrap(); - writeln!(t, "+{}⏎", str).unwrap(); - } - DiffLine::Resulting(ref str) => { - t.fg(term::color::RED).unwrap(); - writeln!(t, "-{}⏎", str).unwrap(); - } - } - } - t.reset().unwrap(); - } -} + let mut writer = OutputWriter::new(color); -pub fn print_diff_basic(diff: Vec, get_section_title: F) -where - F: Fn(u32) -> String, -{ for mismatch in diff { let title = get_section_title(mismatch.line_number); - println!("{}", title); + writer.writeln(&format!("{}", title), None); for line in mismatch.lines { match line { - DiffLine::Context(ref str) => { - println!(" {}⏎", str); - } + DiffLine::Context(ref str) => writer.writeln(&format!(" {}⏎", str), None), DiffLine::Expected(ref str) => { - println!("+{}⏎", str); + writer.writeln(&format!("+{}⏎", str), Some(term::color::GREEN)) } DiffLine::Resulting(ref str) => { - println!("-{}⏎", str); + writer.writeln(&format!("-{}⏎", str), Some(term::color::RED)) } } } diff --git a/tests/system.rs b/tests/system.rs index d99e1a4a4e2..0671a845b2e 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -106,10 +106,8 @@ fn verify_config_test_names() { // using only one or the other will cause the output order to differ when // `print_diff` selects the approach not used. fn write_message(msg: String) { - match PrintType::get(Color::Auto) { - PrintType::Fancy => writeln!(term::stdout().unwrap(), "{}", msg).unwrap(), - PrintType::Basic => println!("{}", msg), - } + let mut writer = OutputWriter::new(Color::Auto); + writer.writeln(&format!("{}", msg), None); } // Integration tests. The files in the tests/source are formatted and compared -- cgit 1.4.1-3-g733a5 From fa782303a6a12fa4c13d8c8e2af13239b36813b5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 15 Jan 2018 20:50:47 +0900 Subject: 0.3.5 --- CHANGELOG.md | 9 ++++ Cargo.lock | 160 ++++++++++++++++++++++++++------------------------------- Cargo.toml | 6 +-- src/visitor.rs | 3 -- 4 files changed, 86 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index c771de7d044..eeadd460718 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,18 @@ ## [Unreleased] +## [0.3.5] 2018-01-15 + ### Changed +- Format code block in comments when `wrap_comments` is set to `true`. - Remove `same_line_attributes` configuration option. +- Rename `git-fmt` to `git-rustfmt`. + +### Fixed + +- Rustup to `rustc 1.25.0-nightly (e6072a7b3 2018-01-13)`. +- Fix formatting bugs. ## [0.3.4] 2017-12-23 diff --git a/Cargo.lock b/Cargo.lock index 64680d70daa..6e506a11dcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,16 +8,14 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -25,8 +23,8 @@ name = "backtrace-sys" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -36,19 +34,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -56,15 +54,6 @@ name = "cfg-if" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "dbghelp-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "derive-new" version = "0.5.0" @@ -90,7 +79,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -98,7 +87,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -141,7 +130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.34" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -149,12 +138,12 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -165,7 +154,7 @@ name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -195,7 +184,7 @@ name = "parking_lot_core" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -212,29 +201,29 @@ version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "7.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -243,57 +232,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "7.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "7.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "7.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "7.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "7.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -305,23 +294,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustfmt-nightly" -version = "0.3.4" +version = "0.3.5" dependencies = [ - "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -334,7 +323,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -344,22 +333,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -368,13 +357,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -428,7 +417,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -495,13 +484,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" -"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e" +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" -"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643" -"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" +"checksum cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f410f43295c912ae1328de55e5c050dbef882c17b836f5ed41cc8b96c40d6cc5" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" "checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" @@ -513,9 +501,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" +"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a89a0c46ba789b8a247d4c567aed4d7c68e624672d238b45cc3ec20dc9f940" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" @@ -523,21 +511,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" -"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rustc-ap-rustc_cratesio_shim 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a02d8f4e45e3351128d29da1f50d4b0ac58a3b992db0be2f05a1a139f241ac76" -"checksum rustc-ap-rustc_data_structures 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "857204fad56d38c71d8f6aea7a39eebe9bceb84934e7e2aaa2f6db0e6c802782" -"checksum rustc-ap-rustc_errors 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1fd9cb0f0a1286cca0846a40ad9ed7d5bf146ae7f7c0078327a18e90ddbf2d" -"checksum rustc-ap-serialize 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc12bdfc05879c75fb7893c179ee2095cc817a9559f8779667a0d2a5c56d4e1" -"checksum rustc-ap-syntax 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f9c63a0726f460e5aed49542ebd06ce9c52076b3ad14e96a2028eb8c5e5f910" -"checksum rustc-ap-syntax_pos 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "583fefdc6fd407a93d5a08f40ab020f36e0c8defe4e72ee766ce99755ec68651" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" +"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e" +"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc" +"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0" +"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604" +"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c" +"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "386122ba68c214599c44587e0c0b411e8d90894503a95425b4f9508e4317901f" -"checksum serde_derive 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0bfa6c5784e7d110514448da0e1dbad41ea5514c3e68be755b23858b83a399" -"checksum serde_derive_internals 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "730fe9f29fe8db69a601837f416e46cba07792031ed6b27557a43e49d62d89ae" -"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" +"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" diff --git a/Cargo.toml b/Cargo.toml index 021ae5a006f..5991e82c65d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.3.4" +version = "0.3.5" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" @@ -44,8 +44,8 @@ env_logger = "0.4" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.4" -rustc-ap-syntax = "7.0.0" -rustc-ap-rustc_errors = "7.0.0" +rustc-ap-syntax = "12.0.0" +rustc-ap-rustc_errors = "12.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/visitor.rs b/src/visitor.rs index d544eb9b2df..2d7d140c179 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -410,9 +410,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::AutoImpl(..) => { - // FIXME(#78): format impl definitions. - } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { self.visit_fn( visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), -- cgit 1.4.1-3-g733a5 From 4c4e07961363a4650b1354bf36032be653c43fa9 Mon Sep 17 00:00:00 2001 From: Chris Stinson Date: Tue, 16 Jan 2018 17:39:21 +1300 Subject: Fixing binop_separator="Back" for ranges Hardcoded Separator::Place=Front in call to rewrite_pair for range caused binop_separator="Back" to be hendled incorrectly Fixed rewrite_pair call and the example in Configuration.md showing the faulty behaviour --- Configurations.md | 4 ++-- src/expr.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index c4e9435edf0..8b0039314ee 100644 --- a/Configurations.md +++ b/Configurations.md @@ -341,8 +341,8 @@ fn main() { let sum = 123456789012345678901234567890 + 123456789012345678901234567890 + 123456789012345678901234567890; - let range = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; // 🐜 See #2364. + let range = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.. + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; } ``` diff --git a/src/expr.rs b/src/expr.rs index 157147c4a06..a82e47e69b9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -250,7 +250,7 @@ pub fn format_expr( PairParts::new("", &sp_delim, ""), context, shape, - SeparatorPlace::Front, + context.config.binop_separator(), ) } (None, Some(rhs)) => { -- cgit 1.4.1-3-g733a5 From 298f29a57dfb02e7f1475469dfa3571521f30ee3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 18 Jan 2018 00:50:16 +0900 Subject: Do not panic when special macros have less args than expected --- src/expr.rs | 2 +- tests/source/macros.rs | 6 ++++++ tests/target/macros.rs | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a82e47e69b9..5965f3007b4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2163,7 +2163,7 @@ fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bo .iter() .find(|&&(s, _)| s == callee_str) { - let all_simple = args.len() >= num_args_before && is_every_args_simple(args); + let all_simple = args.len() > num_args_before && is_every_args_simple(args); Some((all_simple, num_args_before)) } else { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 797c1ffc2f2..dca1e0e7033 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -218,6 +218,7 @@ make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [ } fn special_case_macros() { + let p = eprint!(); let q = eprint!("{}", 1); let r = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); let s = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); @@ -266,10 +267,15 @@ fn special_case_macros() { warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + assert!(); + assert!(result == 42); assert!(result == 42, "Ahoy there, {}!", target); assert!(result == 42, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + assert_eq!(); + assert_eq!(left); + assert_eq!(left, right); assert_eq!(left, right, "Ahoy there, {}!", target); assert_eq!(left, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 805f983d18c..75238b11ab7 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -271,6 +271,7 @@ fn issue2214() { } fn special_case_macros() { + let p = eprint!(); let q = eprint!("{}", 1); let r = eprint!( "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", @@ -691,6 +692,8 @@ fn special_case_macros() { 26 ); + assert!(); + assert!(result == 42); assert!(result == 42, "Ahoy there, {}!", target); assert!( result == 42, @@ -730,6 +733,9 @@ fn special_case_macros() { 26 ); + assert_eq!(); + assert_eq!(left); + assert_eq!(left, right); assert_eq!(left, right, "Ahoy there, {}!", target); assert_eq!( left, right, -- cgit 1.4.1-3-g733a5 From 1fb172f98952e8f8a26115de219f46f5f889dbbd Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Fri, 19 Jan 2018 12:18:25 -0500 Subject: LineOverflow: Count tabs as tab_spaces when measuring line length for overflow --- src/lib.rs | 2 +- tests/system.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index e24a6c1949c..817188925cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -463,7 +463,7 @@ fn format_lines( is_string = false; } else { newline_count = 0; - line_len += 1; + line_len += if c == '\t' { config.tab_spaces() } else { 1 }; if c.is_whitespace() { if last_wspace.is_none() { last_wspace = Some(b); diff --git a/tests/system.rs b/tests/system.rs index 8125e7fd2b6..24a6b15e421 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -261,6 +261,16 @@ fn format_lines_errors_are_reported() { assert!(error_summary.has_formatting_errors()); } +#[test] +fn format_lines_errors_are_reported_with_tabs() { + let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); + let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); + let config = Config::from_toml("hard_tabs = true").unwrap(); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: Vec) -> (Vec, u32, u32) { -- cgit 1.4.1-3-g733a5 From 69f27673df41d2657386f9d498ab6e274db9733f Mon Sep 17 00:00:00 2001 From: David Alber Date: Sun, 21 Jan 2018 16:25:24 -0800 Subject: Extending `spaces_around_ranges` to ranges in match arm patterns --- Configurations.md | 42 ++++++++++++++++++++-- src/patterns.rs | 7 +++- tests/source/configs/spaces_around_ranges/false.rs | 18 +++++++++- tests/source/configs/spaces_around_ranges/true.rs | 16 +++++++++ tests/target/configs/spaces_around_ranges/false.rs | 16 +++++++++ tests/target/configs/spaces_around_ranges/true.rs | 16 +++++++++ 6 files changed, 110 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 1b9c13ae39d..659784bfd78 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1468,7 +1468,7 @@ struct Foo { ## `spaces_around_ranges` -Put spaces around the .. and ... range operators +Put spaces around the .., ..=, and ... range operators - **Default value**: `false` - **Possible values**: `true`, `false` @@ -1477,13 +1477,49 @@ Put spaces around the .. and ... range operators #### `false` (default): ```rust -let lorem = 0..10; +fn main() { + let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } +} ``` #### `true`: ```rust -let lorem = 0 .. 10; +fn main() { + let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } +} ``` ## `spaces_within_parens_and_brackets` diff --git a/src/patterns.rs b/src/patterns.rs index f877239f518..4719160061b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -65,10 +65,15 @@ impl Rewrite for Pat { RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", RangeEnd::Excluded => "..", }; + let infix = if context.config.spaces_around_ranges() { + format!(" {} ", infix) + } else { + infix.to_owned() + }; rewrite_pair( &**lhs, &**rhs, - PairParts::new("", infix, ""), + PairParts::new("", &infix, ""), context, shape, SeparatorPlace::Front, diff --git a/tests/source/configs/spaces_around_ranges/false.rs b/tests/source/configs/spaces_around_ranges/false.rs index 3d431e4d1ce..11ca76b1345 100644 --- a/tests/source/configs/spaces_around_ranges/false.rs +++ b/tests/source/configs/spaces_around_ranges/false.rs @@ -2,5 +2,21 @@ // Spaces around ranges fn main() { - let lorem = 0..10; + let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } } diff --git a/tests/source/configs/spaces_around_ranges/true.rs b/tests/source/configs/spaces_around_ranges/true.rs index 8e9a311abf3..50170892130 100644 --- a/tests/source/configs/spaces_around_ranges/true.rs +++ b/tests/source/configs/spaces_around_ranges/true.rs @@ -3,4 +3,20 @@ fn main() { let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } } diff --git a/tests/target/configs/spaces_around_ranges/false.rs b/tests/target/configs/spaces_around_ranges/false.rs index 3d431e4d1ce..6319da98572 100644 --- a/tests/target/configs/spaces_around_ranges/false.rs +++ b/tests/target/configs/spaces_around_ranges/false.rs @@ -3,4 +3,20 @@ fn main() { let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } } diff --git a/tests/target/configs/spaces_around_ranges/true.rs b/tests/target/configs/spaces_around_ranges/true.rs index 2a456a6daea..7bfcc23c8ea 100644 --- a/tests/target/configs/spaces_around_ranges/true.rs +++ b/tests/target/configs/spaces_around_ranges/true.rs @@ -3,4 +3,20 @@ fn main() { let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } } -- cgit 1.4.1-3-g733a5 From fa6892eb6389dbcdf8037670bd480767a61b5a8d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 22 Jan 2018 13:04:20 +0900 Subject: Use field initialization shorthand if possible Also this PR fixes a bug that attributes on a shorthand field get removed. --- src/expr.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5965f3007b4..09917ca088b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2565,9 +2565,13 @@ pub fn rewrite_field( if contains_skip(&field.attrs) { return Some(context.snippet(field.span()).to_owned()); } - let name = &field.ident.node.to_string(); + let mut attrs_str = field.attrs.rewrite(context, shape)?; + if !attrs_str.is_empty() { + attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); + }; + let name = field.ident.node.to_string(); if field.is_shorthand { - Some(name.to_string()) + Some(attrs_str + &name) } else { let mut separator = String::from(struct_lit_field_separator(context.config)); for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { @@ -2577,12 +2581,8 @@ pub fn rewrite_field( let expr_shape = shape.offset_left(overhead)?; let expr = field.expr.rewrite(context, expr_shape); - let mut attrs_str = field.attrs.rewrite(context, shape)?; - if !attrs_str.is_empty() { - attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); - }; - match expr { + Some(ref e) if e.as_str() == name => Some(attrs_str + &name), Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); -- cgit 1.4.1-3-g733a5 From 154bf8e1afafed035b769955ed81490dca62a50a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 22 Jan 2018 13:05:18 +0900 Subject: Cargo fmt --- src/bin/rustfmt.rs | 8 ++++---- src/closures.rs | 2 +- src/comment.rs | 8 ++++---- src/expr.rs | 44 ++++++++++++++++++++++---------------------- src/file_lines.rs | 2 +- src/imports.rs | 6 +++--- src/issues.rs | 13 +++++-------- src/items.rs | 46 +++++++++++++++++++++++----------------------- src/lib.rs | 2 +- src/lists.rs | 32 ++++++++++++++++---------------- src/rustfmt_diff.rs | 2 +- src/shape.rs | 16 ++++++++-------- src/string.rs | 4 ++-- src/types.rs | 2 +- src/vertical.rs | 2 +- src/visitor.rs | 6 +++--- tests/target/closure.rs | 2 +- tests/target/impl.rs | 2 +- 18 files changed, 98 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index ba586e1fd91..66ee49297a3 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -453,7 +453,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::Stdin { input: buffer, - config_path: config_path, + config_path, }); } @@ -469,8 +469,8 @@ fn determine_operation(matches: &Matches) -> FmtResult { .collect(); Ok(Operation::Format { - files: files, - config_path: config_path, - minimal_config_path: minimal_config_path, + files, + config_path, + minimal_config_path, }) } diff --git a/src/closures.rs b/src/closures.rs index f63242f6355..fcb985ebf12 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -244,7 +244,7 @@ fn rewrite_closure_fn_decl( }; let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: SeparatorTactic::Never, separator_place: SeparatorPlace::Back, diff --git a/src/comment.rs b/src/comment.rs index eb9e96f2509..edcd5153fc3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -285,11 +285,11 @@ fn rewrite_comment_inner( let mut fmt = StringFormat { opener: "", closer: "", - line_start: line_start, + line_start, line_end: "", shape: Shape::legacy(max_chars, fmt_indent), trim_end: true, - config: config, + config, }; let line_breaks = count_newlines(orig.trim_right()); @@ -895,7 +895,7 @@ pub struct CommentCodeSlices<'a> { impl<'a> CommentCodeSlices<'a> { pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { CommentCodeSlices { - slice: slice, + slice, last_slice_kind: CodeCharKind::Comment, last_slice_end: 0, } @@ -1019,7 +1019,7 @@ impl<'a> CommentReducer<'a> { let is_block = comment.starts_with("/*"); let comment = remove_comment_header(comment); CommentReducer { - is_block: is_block, + is_block, at_start_line: false, // There are no supplementary '*' on the first line iter: comment.chars(), } diff --git a/src/expr.rs b/src/expr.rs index 09917ca088b..d59e383389f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -441,7 +441,7 @@ pub fn rewrite_array( let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if trailing_comma { SeparatorTactic::Always @@ -462,7 +462,7 @@ pub fn rewrite_array( }, separator_place: SeparatorPlace::Back, shape: nested_shape, - ends_with_newline: ends_with_newline, + ends_with_newline, preserve_newline: false, config: context.config, }; @@ -779,19 +779,19 @@ impl<'a> ControlFlow<'a> { ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), - block: block, - else_block: else_block, + block, + else_block, label: None, - pat: pat, + pat, keyword: "if", matcher: match pat { Some(..) => "let", None => "", }, connector: " =", - allow_single_line: allow_single_line, - nested_if: nested_if, - span: span, + allow_single_line, + nested_if, + span, } } @@ -802,16 +802,16 @@ impl<'a> ControlFlow<'a> { ) -> ControlFlow<'a> { ControlFlow { cond: None, - block: block, + block, else_block: None, - label: label, + label, pat: None, keyword: "loop", matcher: "", connector: "", allow_single_line: false, nested_if: false, - span: span, + span, } } @@ -824,10 +824,10 @@ impl<'a> ControlFlow<'a> { ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), - block: block, + block, else_block: None, - label: label, - pat: pat, + label, + pat, keyword: "while", matcher: match pat { Some(..) => "let", @@ -836,7 +836,7 @@ impl<'a> ControlFlow<'a> { connector: " =", allow_single_line: false, nested_if: false, - span: span, + span, } } @@ -849,16 +849,16 @@ impl<'a> ControlFlow<'a> { ) -> ControlFlow<'a> { ControlFlow { cond: Some(cond), - block: block, + block, else_block: None, - label: label, + label, pat: Some(pat), keyword: "for", matcher: "", connector: " in", allow_single_line: false, nested_if: false, - span: span, + span, } } @@ -1484,7 +1484,7 @@ fn rewrite_match_pattern( ) }; let fmt = ListFormatting { - tactic: tactic, + tactic, separator: " |", trailing_separator: SeparatorTactic::Never, separator_place: context.config.binop_separator(), @@ -1988,7 +1988,7 @@ where ); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if force_trailing_comma { SeparatorTactic::Always @@ -2671,11 +2671,11 @@ where nested_shape.width, ); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: SeparatorTactic::Never, separator_place: SeparatorPlace::Back, - shape: shape, + shape, ends_with_newline: false, preserve_newline: false, config: context.config, diff --git a/src/file_lines.rs b/src/file_lines.rs index 7f2273c6f69..028c631b1b9 100644 --- a/src/file_lines.rs +++ b/src/file_lines.rs @@ -34,7 +34,7 @@ impl<'a> From<&'a LineRange> for Range { impl Range { pub fn new(lo: usize, hi: usize) -> Range { - Range { lo: lo, hi: hi } + Range { lo, hi } } fn is_empty(self) -> bool { diff --git a/src/imports.rs b/src/imports.rs index c49a95b6ff7..2fd85143044 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -284,7 +284,7 @@ fn rewrite_imports( separator: "", trailing_separator: SeparatorTactic::Never, separator_place: SeparatorPlace::Back, - shape: shape, + shape, ends_with_newline: true, preserve_newline: false, config: context.config, @@ -537,7 +537,7 @@ fn rewrite_nested_use_tree( && tactic != DefinitiveListTactic::Horizontal; let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if ends_with_newline { context.config.trailing_comma() @@ -546,7 +546,7 @@ fn rewrite_nested_use_tree( }, separator_place: SeparatorPlace::Back, shape: nested_shape, - ends_with_newline: ends_with_newline, + ends_with_newline, preserve_newline: true, config: context.config, }; diff --git a/src/issues.rs b/src/issues.rs index 6cd0586f3e4..2efd61a3d7d 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -90,8 +90,8 @@ impl BadIssueSeeker { todo_idx: 0, fixme_idx: 0, }, - report_todo: report_todo, - report_fixme: report_fixme, + report_todo, + report_fixme, } } @@ -169,8 +169,8 @@ impl BadIssueSeeker { } Seeking::Issue { - todo_idx: todo_idx, - fixme_idx: fixme_idx, + todo_idx, + fixme_idx, } } @@ -213,10 +213,7 @@ impl BadIssueSeeker { NumberPart::CloseParen => {} } - self.state = Seeking::Number { - part: part, - issue: issue, - }; + self.state = Seeking::Number { part, issue }; IssueClassification::None } diff --git a/src/items.rs b/src/items.rs index fcf545a37bd..fdd769ef289 100644 --- a/src/items.rs +++ b/src/items.rs @@ -138,7 +138,7 @@ impl<'a> Item<'a> { .iter() .map(|i| BodyElement::ForeignItem(i)) .collect(), - span: span, + span, } } } @@ -169,8 +169,8 @@ impl<'a> FnSig<'a> { vis: ast::Visibility, ) -> FnSig<'a> { FnSig { - decl: decl, - generics: generics, + decl, + generics, abi: abi::Abi::Rust, constness: ast::Constness::NotConst, defaultness: ast::Defaultness::Final, @@ -189,7 +189,7 @@ impl<'a> FnSig<'a> { defaultness: ast::Defaultness::Final, abi: method_sig.abi, decl: &*method_sig.decl, - generics: generics, + generics, visibility: ast::Visibility::Inherited, } } @@ -202,12 +202,12 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { match *fn_kind { visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { - decl: decl, - generics: generics, - abi: abi, + decl, + generics, + abi, constness: constness.node, defaultness: defualtness, - unsafety: unsafety, + unsafety, visibility: visibility.clone(), }, visit::FnKind::Method(_, method_sig, vis, _) => { @@ -510,7 +510,7 @@ impl<'a> FmtVisitor<'a> { separator: ",", trailing_separator: self.config.trailing_comma(), separator_place: SeparatorPlace::Back, - shape: shape, + shape, ends_with_newline: true, preserve_newline: true, config: self.config, @@ -895,10 +895,10 @@ impl<'a> StructParts<'a> { _ => unreachable!(), }; StructParts { - prefix: prefix, + prefix, ident: item.ident, vis: &item.vis, - def: def, + def, generics: Some(generics), span: item.span, } @@ -1509,11 +1509,11 @@ impl<'a> StaticParts<'a> { _ => unreachable!(), }; StaticParts { - prefix: prefix, + prefix, vis: &item.vis, ident: item.ident, - ty: ty, - mutability: mutability, + ty, + mutability, expr_opt: Some(expr), defaultness: None, span: item.span, @@ -1529,7 +1529,7 @@ impl<'a> StaticParts<'a> { prefix: "const", vis: &ast::Visibility::Inherited, ident: ti.ident, - ty: ty, + ty, mutability: ast::Mutability::Immutable, expr_opt: expr_opt.as_ref(), defaultness: None, @@ -1546,7 +1546,7 @@ impl<'a> StaticParts<'a> { prefix: "const", vis: &ii.vis, ident: ii.ident, - ty: ty, + ty, mutability: ast::Mutability::Immutable, expr_opt: Some(expr), defaultness: Some(ii.defaultness), @@ -1818,7 +1818,7 @@ fn rewrite_fn_base( let one_line_budget = context.budget(used_width + overhead); let shape = Shape { width: one_line_budget, - indent: indent, + indent, offset: used_width, }; let fd = fn_sig.decl; @@ -2085,8 +2085,8 @@ struct WhereClauseOption { impl WhereClauseOption { pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { WhereClauseOption { - suppress_comma: suppress_comma, - snuggle: snuggle, + suppress_comma, + snuggle, compress_where: false, } } @@ -2233,7 +2233,7 @@ fn rewrite_args( debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if variadic { SeparatorTactic::Never @@ -2404,7 +2404,7 @@ where one_line_budget, ); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if context.config.indent_style() == IndentStyle::Visual { SeparatorTactic::Never @@ -2412,7 +2412,7 @@ where context.config.trailing_comma() }, separator_place: SeparatorPlace::Back, - shape: shape, + shape, ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, config: context.config, @@ -2637,7 +2637,7 @@ fn rewrite_where_clause( } let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: comma_tactic, separator_place: SeparatorPlace::Back, diff --git a/src/lib.rs b/src/lib.rs index 817188925cd..ec846de04db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -448,7 +448,7 @@ fn format_lines( line: cur_line, kind: error_kind, is_comment: kind.is_comment(), - is_string: is_string, + is_string, line_buffer: line_buffer.clone(), }); } diff --git a/src/lists.rs b/src/lists.rs index 193cd4f3c32..aa1e0b430ef 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -690,15 +690,15 @@ where }; ListItem { - pre_comment: pre_comment, - pre_comment_style: pre_comment_style, + pre_comment, + pre_comment_style, item: if self.inner.peek().is_none() && self.leave_last { None } else { (self.get_item_string)(&item) }, - post_comment: post_comment, - new_lines: new_lines, + post_comment, + new_lines, } }) } @@ -724,16 +724,16 @@ where F3: Fn(&T) -> Option, { ListItems { - codemap: codemap, + codemap, inner: inner.peekable(), - get_lo: get_lo, - get_hi: get_hi, - get_item_string: get_item_string, - prev_span_end: prev_span_end, - next_span_start: next_span_start, - terminator: terminator, - separator: separator, - leave_last: leave_last, + get_lo, + get_hi, + get_item_string, + prev_span_end, + next_span_start, + terminator, + separator, + leave_last, } } @@ -841,7 +841,7 @@ pub fn struct_lit_formatting<'a>( let ends_with_newline = context.config.indent_style() != IndentStyle::Visual && tactic == DefinitiveListTactic::Vertical; ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if force_no_trailing_comma { SeparatorTactic::Never @@ -849,8 +849,8 @@ pub fn struct_lit_formatting<'a>( context.config.trailing_comma() }, separator_place: SeparatorPlace::Back, - shape: shape, - ends_with_newline: ends_with_newline, + shape, + ends_with_newline, preserve_newline: true, config: context.config, } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index d563e6eee3c..1a2f570f89e 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -31,7 +31,7 @@ pub struct Mismatch { impl Mismatch { fn new(line_number: u32) -> Mismatch { Mismatch { - line_number: line_number, + line_number, lines: Vec::new(), } } diff --git a/src/shape.rs b/src/shape.rs index fffbe2b9913..8fe2e2b18c0 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -29,8 +29,8 @@ const INDENT_BUFFER: &str = impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { Indent { - block_indent: block_indent, - alignment: alignment, + block_indent, + alignment, } } @@ -161,8 +161,8 @@ impl Shape { // |<--->| width pub fn legacy(width: usize, indent: Indent) -> Shape { Shape { - width: width, - indent: indent, + width, + indent, offset: indent.alignment, } } @@ -170,7 +170,7 @@ impl Shape { pub fn indented(indent: Indent, config: &Config) -> Shape { Shape { width: config.max_width().checked_sub(indent.width()).unwrap_or(0), - indent: indent, + indent, offset: indent.alignment, } } @@ -187,9 +187,9 @@ impl Shape { pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { Shape { - width: width, - indent: indent, - offset: offset, + width, + indent, + offset, } } diff --git a/src/string.rs b/src/string.rs index 43b1ccbcb93..2386d90ec8a 100644 --- a/src/string.rs +++ b/src/string.rs @@ -36,9 +36,9 @@ impl<'a> StringFormat<'a> { closer: "\"", line_start: " ", line_end: "\\", - shape: shape, + shape, trim_end: false, - config: config, + config, } } } diff --git a/src/types.rs b/src/types.rs index 588d9100fe6..a7472567a81 100644 --- a/src/types.rs +++ b/src/types.rs @@ -352,7 +352,7 @@ where ); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: if !context.use_block_indent() || variadic { SeparatorTactic::Never diff --git a/src/vertical.rs b/src/vertical.rs index e56410202eb..2ccb5d81339 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -247,7 +247,7 @@ fn rewrite_aligned_items_inner( ); let fmt = ListFormatting { - tactic: tactic, + tactic, separator: ",", trailing_separator: context.config.trailing_comma(), separator_place: SeparatorPlace::Back, diff --git a/src/visitor.rs b/src/visitor.rs index 2d7d140c179..83d5bca4052 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -576,14 +576,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider: &'a SnippetProvider, ) -> FmtVisitor<'a> { FmtVisitor { - parse_session: parse_session, + parse_session, codemap: parse_session.codemap(), buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), last_pos: BytePos(0), block_indent: Indent::empty(), - config: config, + config, is_if_else_block: false, - snippet_provider: snippet_provider, + snippet_provider, line_number: 0, skipped_range: vec![], } diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 5bc89d58222..54ad25b1b37 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -147,7 +147,7 @@ fn issue470() { hair::PatternRef::Hair(pattern), &lvalue, ); - ArgDecl { ty: ty } + ArgDecl { ty } }, ); } diff --git a/tests/target/impl.rs b/tests/target/impl.rs index 99922d406f4..5895c74bcc9 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -13,7 +13,7 @@ where pub fn new(value: V) -> Self { Test { cloned_value: value.clone(), - value: value, + value, } } } -- cgit 1.4.1-3-g733a5 From 6d294e6bcb7a8bbefbce62ad8e553f4cae5bde3d Mon Sep 17 00:00:00 2001 From: Alex McArther Date: Tue, 23 Jan 2018 07:55:50 -0800 Subject: Make rustfmt-bin's CARGO_PKG_VERSION envvar optional --- src/bin/rustfmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index ba586e1fd91..5a9119cdb11 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -387,7 +387,7 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) { fn print_version() { println!( "{}-nightly{}", - env!("CARGO_PKG_VERSION"), + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) ) } -- cgit 1.4.1-3-g733a5 From dfc67a5df7e71d692fad67227cb06c0a98d8a020 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 26 Jan 2018 14:53:28 +0900 Subject: Cargo clippy --- src/comment.rs | 2 +- src/lib.rs | 2 +- src/macros.rs | 15 ++++++--------- tests/system.rs | 20 ++++++++++---------- 4 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index eb9e96f2509..31b6f25bf08 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -328,7 +328,7 @@ fn rewrite_comment_inner( while let Some(line) = iter.next() { result.push_str(line); result.push_str(match iter.peek() { - Some(ref next_line) if next_line.is_empty() => comment_line_separator.trim_right(), + Some(next_line) if next_line.is_empty() => comment_line_separator.trim_right(), Some(..) => &comment_line_separator, None => "", }); diff --git a/src/lib.rs b/src/lib.rs index 817188925cd..1dd12213374 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,7 +165,7 @@ impl FormatReport { self.file_error_map .iter() .map(|(_, errors)| errors.len()) - .fold(0, |acc, x| acc + x) + .sum() } pub fn has_warnings(&self) -> bool { diff --git a/src/macros.rs b/src/macros.rs index 926c76dce7f..b0080695449 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -351,7 +351,7 @@ pub fn rewrite_macro_def( // Undo our replacement of macro variables. // FIXME: this could be *much* more efficient. - for (old, new) in substs.iter() { + for (old, new) in &substs { if old_body.find(new).is_some() { debug!( "rewrite_macro_def: bailing matching variable: `{}` in `{}`", @@ -368,7 +368,7 @@ pub fn rewrite_macro_def( ident, args_str, new_body, - indent.to_string(&context.config), + indent.to_string(context.config), ); Some(result) @@ -467,13 +467,10 @@ fn format_macro_args(toks: ThinTokenStream) -> Option { insert_space = next_space(&t); } TokenTree::Delimited(_, d) => { - let formatted = format_macro_args(d.tts)?; - match insert_space { - SpaceState::Always => { - result.push(' '); - } - _ => {} + if let SpaceState::Always = insert_space { + result.push(' '); } + let formatted = format_macro_args(d.tts)?; match d.delim { DelimToken::Paren => { result.push_str(&format!("({})", formatted)); @@ -713,7 +710,7 @@ impl MacroParser { fn parse_branch(&mut self) -> Option { let (args_paren_kind, args) = match self.toks.next()? { TokenTree::Token(..) => return None, - TokenTree::Delimited(_, ref d) => (d.delim, d.tts.clone().into()), + TokenTree::Delimited(_, ref d) => (d.delim, d.tts.clone()), }; match self.toks.next()? { TokenTree::Token(_, Token::FatArrow) => {} diff --git a/tests/system.rs b/tests/system.rs index 24a6b15e421..06bfa1418d1 100644 --- a/tests/system.rs +++ b/tests/system.rs @@ -95,7 +95,7 @@ fn verify_config_test_names() { let config_name = path.file_name().unwrap().to_str().unwrap(); // Make sure that config name is used in the files in the directory. - verify_config_used(&path, &config_name); + verify_config_used(&path, config_name); } } } @@ -105,7 +105,7 @@ fn verify_config_test_names() { // println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing // using only one or the other will cause the output order to differ when // `print_diff` selects the approach not used. -fn write_message(msg: String) { +fn write_message(msg: &str) { let mut writer = OutputWriter::new(Color::Auto); writer.writeln(&format!("{}", msg), None); } @@ -359,8 +359,8 @@ pub enum IdempotentCheckError { } pub fn idempotent_check(filename: &PathBuf) -> Result { - let sig_comments = read_significant_comments(&filename); - let config = read_config(&filename); + let sig_comments = read_significant_comments(filename); + let config = read_config(filename); let (error_summary, file_map, format_report) = format_file(filename, &config); if error_summary.has_parsing_errors() { return Err(IdempotentCheckError::Parse); @@ -660,7 +660,7 @@ impl ConfigCodeBlock { assert!(self.code_block.is_some() && self.code_block_start.is_some()); if self.config_name.is_none() { - write_message(format!( + write_message(&format!( "No configuration name for {}:{}", CONFIGURATIONS_FILE_NAME, self.code_block_start.unwrap() @@ -668,7 +668,7 @@ impl ConfigCodeBlock { return false; } if self.config_value.is_none() { - write_message(format!( + write_message(&format!( "No configuration value for {}:{}", CONFIGURATIONS_FILE_NAME, self.code_block_start.unwrap() @@ -680,7 +680,7 @@ impl ConfigCodeBlock { fn has_parsing_errors(&self, error_summary: Summary) -> bool { if error_summary.has_parsing_errors() { - write_message(format!( + write_message(&format!( "\u{261d}\u{1f3fd} Cannot format {}:{}", CONFIGURATIONS_FILE_NAME, self.code_block_start.unwrap() @@ -703,7 +703,7 @@ impl ConfigCodeBlock { }); } - fn formatted_has_diff(&self, file_map: FileMap) -> bool { + fn formatted_has_diff(&self, file_map: &FileMap) -> bool { let &(ref _file_name, ref text) = file_map.first().unwrap(); let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); if !compare.is_empty() { @@ -729,7 +729,7 @@ impl ConfigCodeBlock { let (error_summary, file_map, _report) = format_input::(input, &config, None).unwrap(); - !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(file_map) + !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) } // Extract a code block from the iterator. Behavior: @@ -746,7 +746,7 @@ impl ConfigCodeBlock { prev: Option<&ConfigCodeBlock>, ) -> Option { let mut code_block = ConfigCodeBlock::new(); - code_block.config_name = prev.map_or(None, |cb| cb.config_name.clone()); + code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); loop { match ConfigurationSection::get_section(file) { -- cgit 1.4.1-3-g733a5 From c60d865b98f325c83df35aa952b5f5b1720787e3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 26 Jan 2018 16:20:00 +0900 Subject: Put attributes and enum variants on different lines --- src/comment.rs | 5 +++++ src/items.rs | 11 ++--------- tests/source/enum.rs | 12 ++++++++++++ tests/target/enum.rs | 24 ++++++++++++++++++++++-- 4 files changed, 41 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index eb9e96f2509..6b6ce159132 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -134,6 +134,11 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { } } +/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain +/// comments between two strings. If there are such comments, then that will be +/// recovered. If `allow_extend` is true and there is no comment between the two +/// strings, then they will be put on a single line as long as doing so does not +/// exceed max width. pub fn combine_strs_with_missing_comments( context: &RewriteContext, prev_str: &str, diff --git a/src/items.rs b/src/items.rs index fcf545a37bd..d0c5cf361c3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -504,7 +504,7 @@ impl<'a> FmtVisitor<'a> { items = itemize_list_with(0); } - let shape = self.shape().sub_width(2).unwrap(); + let shape = self.shape().sub_width(2)?; let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", @@ -558,14 +558,7 @@ impl<'a> FmtVisitor<'a> { } }; - combine_strs_with_missing_comments( - &context, - &attrs_str, - &variant_body, - span, - shape, - is_attributes_extendable(&attrs_str), - ) + combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) } } diff --git a/tests/source/enum.rs b/tests/source/enum.rs index f228e5ef646..f3dbae4b84d 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -180,3 +180,15 @@ enum WidthOf101 { Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), } + +// #2389 +pub enum QlError { + #[fail(display = "Parsing error: {}", 0)] LexError(parser::lexer::LexError), + #[fail(display = "Parsing error: {:?}", 0)] ParseError(parser::ParseError), + #[fail(display = "Validation error: {:?}", 0)] ValidationError(Vec), + #[fail(display = "Execution error: {}", 0)] ExecutionError(String), + // (from, to) + #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), + // (kind, input, expected) + #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 09578d7ec24..de88f610b6a 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -24,7 +24,8 @@ enum EmtpyWithComment { // C-style enum enum Bar { A = 1, - #[someAttr(test)] B = 2, // comment + #[someAttr(test)] + B = 2, // comment C, } @@ -225,7 +226,8 @@ enum AnError { // #2193 enum WidthOf101 { - #[fail(display = ".....................................................")] Io(::std::io::Error), + #[fail(display = ".....................................................")] + Io(::std::io::Error), #[fail(display = ".....................................................")] Ioo(::std::io::Error), Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), @@ -233,3 +235,21 @@ enum WidthOf101 { ::std::io::Error, ), } + +// #2389 +pub enum QlError { + #[fail(display = "Parsing error: {}", 0)] + LexError(parser::lexer::LexError), + #[fail(display = "Parsing error: {:?}", 0)] + ParseError(parser::ParseError), + #[fail(display = "Validation error: {:?}", 0)] + ValidationError(Vec), + #[fail(display = "Execution error: {}", 0)] + ExecutionError(String), + // (from, to) + #[fail(display = "Translation error: from {} to {}", 0, 1)] + TranslationError(String, String), + // (kind, input, expected) + #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] + ResolveError(&'static str, String, Option), +} -- cgit 1.4.1-3-g733a5 From 7d63490d8573eca400260f836ae6a75555620b4f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Jan 2018 21:44:26 +0900 Subject: Update to the latest libsyntax changes --- src/closures.rs | 2 +- src/expr.rs | 32 ++++++++++++++------------------ 2 files changed, 15 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index f63242f6355..b9009598f1a 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -278,7 +278,7 @@ pub fn rewrite_last_closure( expr: &ast::Expr, shape: Shape, ) -> Option { - if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node { + if let ast::ExprKind::Closure(capture, _, ref fn_decl, ref body, _) = expr.node { let body = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => diff --git a/src/expr.rs b/src/expr.rs index 5965f3007b4..dc18a7f532e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -135,16 +135,16 @@ pub fn format_expr( ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { rewrite_assignment(context, lhs, rhs, Some(op), shape) } - ast::ExprKind::Continue(ref opt_ident) => { - let id_str = match *opt_ident { - Some(ident) => format!(" {}", ident.node), + ast::ExprKind::Continue(ref opt_label) => { + let id_str = match *opt_label { + Some(label) => format!(" {}", label.ident), None => String::new(), }; Some(format!("continue{}", id_str)) } - ast::ExprKind::Break(ref opt_ident, ref opt_expr) => { - let id_str = match *opt_ident { - Some(ident) => format!(" {}", ident.node), + ast::ExprKind::Break(ref opt_label, ref opt_expr) => { + let id_str = match *opt_label { + Some(label) => format!(" {}", label.ident), None => String::new(), }; @@ -159,7 +159,7 @@ pub fn format_expr( } else { Some("yield".to_string()) }, - ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => { + ast::ExprKind::Closure(capture, _, ref fn_decl, ref body, _) => { closures::rewrite_closure(capture, fn_decl, body, expr.span, context, shape) } ast::ExprKind::Try(..) @@ -718,7 +718,7 @@ struct ControlFlow<'a> { cond: Option<&'a ast::Expr>, block: &'a ast::Block, else_block: Option<&'a ast::Expr>, - label: Option, + label: Option, pat: Option<&'a ast::Pat>, keyword: &'a str, matcher: &'a str, @@ -795,11 +795,7 @@ impl<'a> ControlFlow<'a> { } } - fn new_loop( - block: &'a ast::Block, - label: Option, - span: Span, - ) -> ControlFlow<'a> { + fn new_loop(block: &'a ast::Block, label: Option, span: Span) -> ControlFlow<'a> { ControlFlow { cond: None, block: block, @@ -819,7 +815,7 @@ impl<'a> ControlFlow<'a> { pat: Option<&'a ast::Pat>, cond: &'a ast::Expr, block: &'a ast::Block, - label: Option, + label: Option, span: Span, ) -> ControlFlow<'a> { ControlFlow { @@ -844,7 +840,7 @@ impl<'a> ControlFlow<'a> { pat: &'a ast::Pat, cond: &'a ast::Expr, block: &'a ast::Block, - label: Option, + label: Option, span: Span, ) -> ControlFlow<'a> { ControlFlow { @@ -1166,9 +1162,9 @@ impl<'a> Rewrite for ControlFlow<'a> { } } -fn rewrite_label(label: Option) -> Cow<'static, str> { - match label { - Some(ident) => Cow::from(format!("{}: ", ident.node)), +fn rewrite_label(opt_label: Option) -> Cow<'static, str> { + match opt_label { + Some(label) => Cow::from(format!("{}: ", label.ident)), None => Cow::from(""), } } -- cgit 1.4.1-3-g733a5 From 56c6d73d824eb4f84d3dfa1f9862e5b724c2b9dc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Jan 2018 21:59:15 +0900 Subject: Reorder modules Add `reorder_modules` config option. Two things we must keep in mind when reordering modules: 1. We should not reorder modules with attributes, as doing so could potentially break the code (e.g. `#[macro_use]`). 2. We should not reorder inline modules e.g. `mod foo { /* .. */ }`. We should only reorder module declarations e.g. `mod foo;`. Some open questions: 1. Should we bring modules with `pub` in front of those without `pub` so that they stand out from others? 2. Instead of keeping modules with attributes in the same place, can we bring them in front of others? Is this safe? --- CHANGELOG.md | 4 + src/config.rs | 1 + src/imports.rs | 35 ++++-- src/lib.rs | 1 + src/visitor.rs | 131 ++++++++++++---------- tests/source/configs/reorder_modules/dolor/mod.rs | 1 + tests/source/configs/reorder_modules/false.rs | 7 ++ tests/source/configs/reorder_modules/ipsum/mod.rs | 1 + tests/source/configs/reorder_modules/lorem/mod.rs | 1 + tests/source/configs/reorder_modules/sit/mod.rs | 1 + tests/source/configs/reorder_modules/true.rs | 7 ++ tests/target/configs/reorder_modules/dolor/mod.rs | 1 + tests/target/configs/reorder_modules/false.rs | 7 ++ tests/target/configs/reorder_modules/ipsum/mod.rs | 1 + tests/target/configs/reorder_modules/lorem/mod.rs | 1 + tests/target/configs/reorder_modules/sit/mod.rs | 1 + tests/target/configs/reorder_modules/true.rs | 7 ++ 17 files changed, 138 insertions(+), 70 deletions(-) create mode 100644 tests/source/configs/reorder_modules/dolor/mod.rs create mode 100644 tests/source/configs/reorder_modules/false.rs create mode 100644 tests/source/configs/reorder_modules/ipsum/mod.rs create mode 100644 tests/source/configs/reorder_modules/lorem/mod.rs create mode 100644 tests/source/configs/reorder_modules/sit/mod.rs create mode 100644 tests/source/configs/reorder_modules/true.rs create mode 100644 tests/target/configs/reorder_modules/dolor/mod.rs create mode 100644 tests/target/configs/reorder_modules/false.rs create mode 100644 tests/target/configs/reorder_modules/ipsum/mod.rs create mode 100644 tests/target/configs/reorder_modules/lorem/mod.rs create mode 100644 tests/target/configs/reorder_modules/sit/mod.rs create mode 100644 tests/target/configs/reorder_modules/true.rs (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index eb21e634ffa..21d30756179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- Add `reorder_modules` configuration option. + ## [0.3.6] 2018-01-18 ### Fixed diff --git a/src/config.rs b/src/config.rs index 954858b93a6..4b7f959b3de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -630,6 +630,7 @@ create_config! { reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; + reorder_modules: bool, false, false, "Reorder module statemtents alphabetically in group"; // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, diff --git a/src/imports.rs b/src/imports.rs index c49a95b6ff7..c6997bd157f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -105,10 +105,13 @@ fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Orderi } } -fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { +fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Ordering { match (&a.node, &b.node) { + (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { + a.ident.name.as_str().cmp(&b.ident.name.as_str()) + } (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { - Some(compare_use_trees(a_tree, b_tree, false)) + compare_use_trees(a_tree, b_tree, false) } (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` @@ -119,7 +122,7 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); let result = a_orig_name.cmp(&b_orig_name); if result != Ordering::Equal { - return Some(result); + return result; } // `extern crate foo as bar;` @@ -128,11 +131,11 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option { (Some(..), None) => Ordering::Greater, (None, Some(..)) => Ordering::Less, (None, None) => Ordering::Equal, - (Some(..), Some(..)) => a.ident.name.cmp(&b.ident.name), + (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), }; - Some(result) + result } - _ => None, + _ => unreachable!(), } } @@ -232,6 +235,16 @@ fn rewrite_import( } } +/// Rewrite an inline mod. +fn rewrite_mod(item: &ast::Item) -> String { + let mut result = String::with_capacity(32); + result.push_str(&*format_visibility(&item.vis)); + result.push_str("mod "); + result.push_str(&item.ident.to_string()); + result.push(';'); + result +} + fn rewrite_imports( context: &RewriteContext, use_items: &[&ast::Item], @@ -246,12 +259,13 @@ fn rewrite_imports( |item| item.span().lo(), |item| item.span().hi(), |item| { - let attrs_str = item.attrs.rewrite(context, shape)?; + let attrs = ::visitor::filter_inline_attrs(&item.attrs, item.span()); + let attrs_str = attrs.rewrite(context, shape)?; - let missed_span = if item.attrs.is_empty() { + let missed_span = if attrs.is_empty() { mk_sp(item.span.lo(), item.span.lo()) } else { - mk_sp(item.attrs.last().unwrap().span.hi(), item.span.lo()) + mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) }; let item_str = match item.node { @@ -259,6 +273,7 @@ fn rewrite_imports( rewrite_import(context, &item.vis, tree, &item.attrs, shape)? } ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, + ast::ItemKind::Mod(..) => rewrite_mod(item), _ => return None, }; @@ -276,7 +291,7 @@ fn rewrite_imports( false, ); let mut item_pair_vec: Vec<_> = items.zip(use_items.iter()).collect(); - item_pair_vec.sort_by(|a, b| compare_use_items(a.1, b.1).unwrap()); + item_pair_vec.sort_by(|a, b| compare_use_items(a.1, b.1)); let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); let fmt = ListFormatting { diff --git a/src/lib.rs b/src/lib.rs index e24a6c1949c..af50de2b459 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(decl_macro)] #![feature(match_default_bindings)] #![feature(rustc_private)] #![feature(type_ascription)] diff --git a/src/visitor.rs b/src/visitor.rs index 2d7d140c179..8063057e9e9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -32,6 +32,33 @@ use shape::{Indent, Shape}; use spanned::Spanned; use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; +/// Returns attributes that are within `outer_span`. +pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { + attrs + .iter() + .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) + .cloned() + .collect() +} + +/// Returns true for `mod foo;`, false for `mod foo { .. }`. +fn is_mod_decl(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Mod(ref m) => { + !(m.inner.lo() == BytePos(0) && m.inner.hi() == BytePos(0)) + && m.inner.hi() != item.span.hi() + } + _ => false, + } +} + +/// Returns true for `mod foo;` without any inline attributes. +/// We cannot reorder modules with attributes because doing so can break the code. +/// e.g. `#[macro_use]`. +fn is_mod_decl_without_attr(item: &ast::Item) -> bool { + is_mod_decl(item) && filter_inline_attrs(&item.attrs, item.span()).is_empty() +} + fn is_use_item(item: &ast::Item) -> bool { match item.node { ast::ItemKind::Use(_) => true, @@ -318,39 +345,26 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let filtered_attrs; let mut attrs = &item.attrs; match item.node { - ast::ItemKind::Mod(ref m) => { - let outer_file = self.codemap.lookup_char_pos(item.span.lo()).file; - let inner_file = self.codemap.lookup_char_pos(m.inner.lo()).file; - if outer_file.name == inner_file.name { - // Module is inline, in this case we treat modules like any - // other item. - if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); - return; - } - } else if contains_skip(&item.attrs) { - // Module is not inline, but should be skipped. + // Module is inline, in this case we treat it like any other item. + _ if !is_mod_decl(item) => { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(item.span()); return; - } else { - // Module is not inline and should not be skipped. We want - // to process only the attributes in the current file. - filtered_attrs = item.attrs - .iter() - .filter_map(|a| { - let attr_file = self.codemap.lookup_char_pos(a.span.lo()).file; - if attr_file.name == outer_file.name { - Some(a.clone()) - } else { - None - } - }) - .collect::>(); - // Assert because if we should skip it should be caught by - // the above case. - assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); - attrs = &filtered_attrs; } } + // Module is not inline, but should be skipped. + ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => { + return; + } + // Module is not inline and should not be skipped. We want + // to process only the attributes in the current file. + ast::ItemKind::Mod(..) => { + filtered_attrs = filter_inline_attrs(&item.attrs, item.span()); + // Assert because if we should skip it should be caught by + // the above case. + assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); + attrs = &filtered_attrs; + } _ => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_skipped_with_span(item.span()); @@ -397,8 +411,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = source!(self, item.span).hi(); } ast::ItemKind::Mod(ref module) => { + let is_inline = !is_mod_decl(item); self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs); + self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); } ast::ItemKind::Mac(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -649,33 +664,34 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } fn walk_items(&mut self, mut items_left: &[&ast::Item]) { - while !items_left.is_empty() { - // If the next item is a `use` declaration, then extract it and any subsequent `use`s - // to be potentially reordered within `format_imports`. Otherwise, just format the - // next item for output. - if self.config.reorder_imports() && is_use_item(&*items_left[0]) { - let used_items_len = self.reorder_items( - items_left, - &is_use_item, - self.config.reorder_imports_in_group(), - ); + macro try_reorder_items_with($reorder: ident, $in_group: ident, $pred: ident) { + if self.config.$reorder() && $pred(&*items_left[0]) { + let used_items_len = + self.reorder_items(items_left, &$pred, self.config.$in_group()); let (_, rest) = items_left.split_at(used_items_len); items_left = rest; - } else if self.config.reorder_extern_crates() && is_extern_crate(&*items_left[0]) { - let used_items_len = self.reorder_items( - items_left, - &is_extern_crate, - self.config.reorder_extern_crates_in_group(), + continue; + } + } + + while !items_left.is_empty() { + // If the next item is a `use`, `extern crate` or `mod`, then extract it and any + // subsequent items that have the same item kind to be reordered within + // `format_imports`. Otherwise, just format the next item for output. + { + try_reorder_items_with!(reorder_imports, reorder_imports_in_group, is_use_item); + try_reorder_items_with!( + reorder_extern_crates, + reorder_extern_crates_in_group, + is_extern_crate ); - let (_, rest) = items_left.split_at(used_items_len); - items_left = rest; - } else { - // `unwrap()` is safe here because we know `items_left` - // has elements from the loop condition - let (item, rest) = items_left.split_first().unwrap(); - self.visit_item(item); - items_left = rest; + try_reorder_items_with!(reorder_modules, reorder_modules, is_mod_decl_without_attr); } + // Reaching here means items were not reordered. There must be at least + // one item left in `items_left`, so calling `unwrap()` here is safe. + let (item, rest) = items_left.split_first().unwrap(); + self.visit_item(item); + items_left = rest; } } @@ -722,13 +738,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { s: Span, ident: ast::Ident, attrs: &[ast::Attribute], + is_internal: bool, ) { - // Decide whether this is an inline mod or an external mod. - let local_file_name = self.codemap.span_to_filename(s); - let inner_span = source!(self, m.inner); - let is_internal = !(inner_span.lo().0 == 0 && inner_span.hi().0 == 0) - && local_file_name == self.codemap.span_to_filename(inner_span); - self.push_str(&*utils::format_visibility(vis)); self.push_str("mod "); self.push_str(&ident.to_string()); diff --git a/tests/source/configs/reorder_modules/dolor/mod.rs b/tests/source/configs/reorder_modules/dolor/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/dolor/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/false.rs b/tests/source/configs/reorder_modules/false.rs new file mode 100644 index 00000000000..56b1aa03ed7 --- /dev/null +++ b/tests/source/configs/reorder_modules/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: false +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/tests/source/configs/reorder_modules/ipsum/mod.rs b/tests/source/configs/reorder_modules/ipsum/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/ipsum/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/lorem/mod.rs b/tests/source/configs/reorder_modules/lorem/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/lorem/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/sit/mod.rs b/tests/source/configs/reorder_modules/sit/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/sit/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/true.rs b/tests/source/configs/reorder_modules/true.rs new file mode 100644 index 00000000000..79b0ab1e355 --- /dev/null +++ b/tests/source/configs/reorder_modules/true.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: true +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/tests/target/configs/reorder_modules/dolor/mod.rs b/tests/target/configs/reorder_modules/dolor/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/dolor/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/false.rs b/tests/target/configs/reorder_modules/false.rs new file mode 100644 index 00000000000..56b1aa03ed7 --- /dev/null +++ b/tests/target/configs/reorder_modules/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: false +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/tests/target/configs/reorder_modules/ipsum/mod.rs b/tests/target/configs/reorder_modules/ipsum/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/ipsum/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/lorem/mod.rs b/tests/target/configs/reorder_modules/lorem/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/lorem/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/sit/mod.rs b/tests/target/configs/reorder_modules/sit/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/sit/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/true.rs b/tests/target/configs/reorder_modules/true.rs new file mode 100644 index 00000000000..18361e88b5f --- /dev/null +++ b/tests/target/configs/reorder_modules/true.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: true +// Reorder modules + +mod dolor; +mod ipsum; +mod lorem; +mod sit; -- cgit 1.4.1-3-g733a5 From 4c9ab8b405c8b096ce27947de6b62cb2ba7a6e48 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Jan 2018 22:00:07 +0900 Subject: Cargo fmt with modules reordering enabled --- src/lib.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index af50de2b459..37c21da8514 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,32 +56,32 @@ pub use self::summary::Summary; #[macro_use] mod utils; -mod shape; -mod spanned; -pub mod config; -pub mod codemap; -pub mod filemap; -pub mod file_lines; -pub mod visitor; +mod chains; mod checkstyle; mod closures; -mod items; -mod missed_spans; -mod lists; -mod types; +pub mod codemap; +mod comment; +pub mod config; mod expr; +pub mod file_lines; +pub mod filemap; mod imports; mod issues; -mod rewrite; -mod string; -mod comment; -pub mod modules; -pub mod rustfmt_diff; -mod chains; +mod items; +mod lists; mod macros; +mod missed_spans; +pub mod modules; mod patterns; +mod rewrite; +pub mod rustfmt_diff; +mod shape; +mod spanned; +mod string; mod summary; +mod types; mod vertical; +pub mod visitor; #[derive(Clone, Copy)] pub enum ErrorKind { -- cgit 1.4.1-3-g733a5 From c9c346a89ff2c1ecc065786bdab0fce550eaa318 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Jan 2018 22:14:25 +0900 Subject: Add 'use_field_init_shorthand' config option --- CHANGELOG.md | 4 +++ Configurations.md | 42 ++++++++++++++++++++++ src/config.rs | 1 + src/expr.rs | 4 ++- .../configs/use_field_init_shorthand/false.rs | 19 ++++++++++ .../configs/use_field_init_shorthand/true.rs | 19 ++++++++++ tests/source/init_shorthand.rs | 18 ---------- tests/target/closure.rs | 2 +- .../configs/use_field_init_shorthand/false.rs | 15 ++++++++ .../configs/use_field_init_shorthand/true.rs | 15 ++++++++ tests/target/init_shorthand.rs | 14 -------- 11 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 tests/source/configs/use_field_init_shorthand/false.rs create mode 100644 tests/source/configs/use_field_init_shorthand/true.rs delete mode 100644 tests/source/init_shorthand.rs create mode 100644 tests/target/configs/use_field_init_shorthand/false.rs create mode 100644 tests/target/configs/use_field_init_shorthand/true.rs delete mode 100644 tests/target/init_shorthand.rs (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index eb21e634ffa..563a28df17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- Add `use_field_init_shorthand` config option. + ## [0.3.6] 2018-01-18 ### Fixed diff --git a/Configurations.md b/Configurations.md index 1b9c13ae39d..eb693833c46 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1685,6 +1685,48 @@ fn lorem() { } ``` +## `use_field_init_shorthand` + +Use field initialize shorthand if possible. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): + +```rust +struct Foo { + x: u32, + y: u32, + z: u32, +} + +fn main() { + let x = 1; + let y = 2; + let z = 3; + let a = Foo { x: x, y: y, z: z }; +} +``` + +#### `true`: + +```rust +struct Foo { + x: u32, + y: u32, + z: u32, +} + +fn main() { + let x = 1; + let y = 2; + let z = 3; + let a = Foo { x, y, z }; +} +``` + ## `use_try_shorthand` Replace uses of the try! macro by the ? shorthand diff --git a/src/config.rs b/src/config.rs index 954858b93a6..4483cbe14eb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -673,6 +673,7 @@ create_config! { condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ in tuple patterns"; force_explicit_abi: bool, true, true, "Always print the abi for extern items"; + use_field_init_shorthand: bool, false, false, "Use field initialization shorthand if possible"; // Control options (changes the operation of rustfmt, rather than the formatting) write_mode: WriteMode, WriteMode::Overwrite, false, diff --git a/src/expr.rs b/src/expr.rs index d59e383389f..39fa17e0fee 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2582,7 +2582,9 @@ pub fn rewrite_field( let expr = field.expr.rewrite(context, expr_shape); match expr { - Some(ref e) if e.as_str() == name => Some(attrs_str + &name), + Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { + Some(attrs_str + &name) + } Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { let expr_offset = shape.indent.block_indent(context.config); diff --git a/tests/source/configs/use_field_init_shorthand/false.rs b/tests/source/configs/use_field_init_shorthand/false.rs new file mode 100644 index 00000000000..16ce740f1b9 --- /dev/null +++ b/tests/source/configs/use_field_init_shorthand/false.rs @@ -0,0 +1,19 @@ +// rustfmt-use_field_init_shorthand: false +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { + x: x, + y: y, + z: z, + }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/source/configs/use_field_init_shorthand/true.rs b/tests/source/configs/use_field_init_shorthand/true.rs new file mode 100644 index 00000000000..1e36c6cff35 --- /dev/null +++ b/tests/source/configs/use_field_init_shorthand/true.rs @@ -0,0 +1,19 @@ +// rustfmt-use_field_init_shorthand: true +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { + x: x, + y: y, + z: z, + }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/source/init_shorthand.rs b/tests/source/init_shorthand.rs deleted file mode 100644 index 31c8fa294ad..00000000000 --- a/tests/source/init_shorthand.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { - x: x, - y: y, - z: z, - }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/tests/target/closure.rs b/tests/target/closure.rs index 54ad25b1b37..5bc89d58222 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure.rs @@ -147,7 +147,7 @@ fn issue470() { hair::PatternRef::Hair(pattern), &lvalue, ); - ArgDecl { ty } + ArgDecl { ty: ty } }, ); } diff --git a/tests/target/configs/use_field_init_shorthand/false.rs b/tests/target/configs/use_field_init_shorthand/false.rs new file mode 100644 index 00000000000..dcebe0b6f1d --- /dev/null +++ b/tests/target/configs/use_field_init_shorthand/false.rs @@ -0,0 +1,15 @@ +// rustfmt-use_field_init_shorthand: false +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { x: x, y: y, z: z }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/target/configs/use_field_init_shorthand/true.rs b/tests/target/configs/use_field_init_shorthand/true.rs new file mode 100644 index 00000000000..ad78093ee8e --- /dev/null +++ b/tests/target/configs/use_field_init_shorthand/true.rs @@ -0,0 +1,15 @@ +// rustfmt-use_field_init_shorthand: true +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { x, y, z }; + + let b = Bar { + x, + y, + #[attr] + z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/target/init_shorthand.rs b/tests/target/init_shorthand.rs deleted file mode 100644 index be315fff35c..00000000000 --- a/tests/target/init_shorthand.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { x, y, z }; - - let b = Bar { - x, - y, - #[attr] - z, - #[rustfmt_skip] - skipped: skipped, - }; -} -- cgit 1.4.1-3-g733a5 From 28bb16a5a0be862a20606c7854dacd00e731957b Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Tue, 30 Jan 2018 22:14:33 +0800 Subject: add a support for immovable generators --- src/closures.rs | 29 +++++++++++++++++++++++------ src/expr.rs | 12 ++++++++++-- tests/source/immovable_generators.rs | 7 +++++++ tests/target/immovable_generators.rs | 7 +++++++ 4 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 tests/source/immovable_generators.rs create mode 100644 tests/target/immovable_generators.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index b9009598f1a..1d8641339f0 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -33,6 +33,7 @@ use utils::{last_line_width, left_most_sub_expr, stmt_expr}; pub fn rewrite_closure( capture: ast::CaptureBy, + movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, span: Span, @@ -42,7 +43,7 @@ pub fn rewrite_closure( debug!("rewrite_closure {:?}", body); let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?; + rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?; // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; @@ -194,6 +195,7 @@ fn rewrite_closure_block( // Return type is (prefix, extra_offset) fn rewrite_closure_fn_decl( capture: ast::CaptureBy, + movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, span: Span, @@ -205,9 +207,17 @@ fn rewrite_closure_fn_decl( } else { "" }; + + let immovable = if movability == ast::Movability::Static { + "static " + } else { + "" + }; // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. - let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?; + let nested_shape = shape + .shrink_left(mover.len() + immovable.len())? + .sub_width(4)?; // 1 = | let argument_offset = nested_shape.indent + 1; @@ -254,7 +264,7 @@ fn rewrite_closure_fn_decl( config: context.config, }; let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}|{}|", mover, list_str); + let mut prefix = format!("{}{}|{}|", immovable, mover, list_str); if !ret_str.is_empty() { if prefix.contains('\n') { @@ -278,7 +288,7 @@ pub fn rewrite_last_closure( expr: &ast::Expr, shape: Shape, ) -> Option { - if let ast::ExprKind::Closure(capture, _, ref fn_decl, ref body, _) = expr.node { + if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { let body = match body.node { ast::ExprKind::Block(ref block) if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => @@ -287,8 +297,15 @@ pub fn rewrite_last_closure( } _ => body, }; - let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?; + let (prefix, extra_offset) = rewrite_closure_fn_decl( + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, + )?; // If the closure goes multi line before its body, do not overflow the closure. if prefix.contains('\n') { return None; diff --git a/src/expr.rs b/src/expr.rs index dc18a7f532e..e5c29e1c510 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -159,8 +159,16 @@ pub fn format_expr( } else { Some("yield".to_string()) }, - ast::ExprKind::Closure(capture, _, ref fn_decl, ref body, _) => { - closures::rewrite_closure(capture, fn_decl, body, expr.span, context, shape) + ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { + closures::rewrite_closure( + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, + ) } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) diff --git a/tests/source/immovable_generators.rs b/tests/source/immovable_generators.rs new file mode 100644 index 00000000000..c57a1e14483 --- /dev/null +++ b/tests/source/immovable_generators.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +unsafe fn foo() { + let mut ga = static || { + yield 1; + }; +} diff --git a/tests/target/immovable_generators.rs b/tests/target/immovable_generators.rs new file mode 100644 index 00000000000..0bf7a2d91ba --- /dev/null +++ b/tests/target/immovable_generators.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +unsafe fn foo() { + let mut ga = static || { + yield 1; + }; +} -- cgit 1.4.1-3-g733a5 From 7c3a422742d75f611275dff8e910898741cb5067 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 2 Feb 2018 14:18:30 +1300 Subject: Update libsyntax crates --- Cargo.lock | 50 +++++++++++++++++++++++++------------------------- Cargo.toml | 4 ++-- src/lib.rs | 2 ++ 3 files changed, 29 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 14a8d459de8..ec6a1117b51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,7 +223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "26.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -232,57 +232,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "26.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "26.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "26.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "26.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "26.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -306,8 +306,8 @@ dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -513,12 +513,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" "checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" -"checksum rustc-ap-rustc_cratesio_shim 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c883f9a3e52bfc3bd463ab7747aa04ebec864ed04f0ee42327b308910e6e58a" -"checksum rustc-ap-rustc_data_structures 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b8955de8d85b55d91e38e7f45ec0b92a6ebdede45a782e8e6d3341eb4ac98" -"checksum rustc-ap-rustc_errors 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f36946ec337c31859627baadf0992a3bfd87b0ff568978cd06cc17a4113f5243" -"checksum rustc-ap-serialize 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2aaabc8226d2e06ac2d22c63a24a0fb36b03f53523979094a4dcdb78dc09d05" -"checksum rustc-ap-syntax 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23f04ea1fc07186bea53269436162d0eb7acadb9ea56d52de3b5723c871296c6" -"checksum rustc-ap-syntax_pos 26.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e43797465d858dfd39cd27cc484085a832f09dc10c3df617c0b7927d6e2a0d1" +"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524" +"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad" +"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182" +"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b" +"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d" +"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" diff --git a/Cargo.toml b/Cargo.toml index 28d796354f5..689178fecd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,8 +44,8 @@ env_logger = "0.4" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.4" -rustc-ap-syntax = "26.0.0" -rustc-ap-rustc_errors = "26.0.0" +rustc-ap-syntax = "29.0.0" +rustc-ap-rustc_errors = "29.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/lib.rs b/src/lib.rs index fb2f5ca5fa6..773567e5f88 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -606,6 +606,7 @@ pub fn format_input( Box::new(Vec::new()), Some(codemap.clone()), false, + false, )); Handler::with_emitter(true, false, silent_emitter) } else { @@ -640,6 +641,7 @@ pub fn format_input( Box::new(Vec::new()), Some(codemap.clone()), false, + false, )); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); -- cgit 1.4.1-3-g733a5 From 30a28a262cd4f0cfd1e4c71792d657bc0fc8624c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 2 Feb 2018 15:16:29 +1300 Subject: Make `is_mod_decl` more accommodating Fixes #2403 (I think) --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/codemap.rs | 4 ++-- src/visitor.rs | 5 +---- 4 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ec6a1117b51..05c03910231 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -294,7 +294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustfmt-nightly" -version = "0.3.7" +version = "0.3.8" dependencies = [ "cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 689178fecd7..a54e1fe482d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.3.7" +version = "0.3.8" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/src/codemap.rs b/src/codemap.rs index 5a8d43a072f..d74d24439d9 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -48,8 +48,8 @@ pub trait LineRangeUtils { impl SpanUtils for CodeMap { fn span_after(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap() + needle.len(); + let snippet = self.span_to_snippet(original).expect("Bad snippet"); + let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len(); original.lo() + BytePos(offset as u32) } diff --git a/src/visitor.rs b/src/visitor.rs index 75e7c0be254..3157597697d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -44,10 +44,7 @@ pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec bool { match item.node { - ast::ItemKind::Mod(ref m) => { - !(m.inner.lo() == BytePos(0) && m.inner.hi() == BytePos(0)) - && m.inner.hi() != item.span.hi() - } + ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), _ => false, } } -- cgit 1.4.1-3-g733a5 From 61b23a4293e643202d0e92439d9902c869259333 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 4 Feb 2018 08:52:50 +0900 Subject: Skip rewriting macro def with repeat --- src/macros.rs | 12 +++++++++--- tests/source/macros.rs | 4 ++++ tests/target/macros.rs | 4 ++++ 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b0080695449..7df793ca79d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -318,7 +318,10 @@ pub fn rewrite_macro_def( // variables for new names with the same length first. let old_body = context.snippet(branch.body).trim(); - let (body_str, substs) = replace_names(old_body); + let (body_str, substs) = match replace_names(old_body) { + Some(result) => result, + None => return snippet, + }; // We'll hack the indent below, take this into account when formatting, let mut config = context.config.clone(); @@ -377,7 +380,7 @@ pub fn rewrite_macro_def( // Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we // aren't causing problems. // This should also work for escaped `$` variables, where we leave earlier `$`s. -fn replace_names(input: &str) -> (String, HashMap) { +fn replace_names(input: &str) -> Option<(String, HashMap)> { // Each substitution will require five or six extra bytes. let mut result = String::with_capacity(input.len() + 64); let mut substs = HashMap::new(); @@ -409,6 +412,9 @@ fn replace_names(input: &str) -> (String, HashMap) { dollar_count = 0; cur_name = String::new(); + } else if c == '(' && cur_name.is_empty() { + // FIXME: Support macro def with repeat. + return None; } else if c.is_alphanumeric() { cur_name.push(c); } @@ -433,7 +439,7 @@ fn replace_names(input: &str) -> (String, HashMap) { debug!("replace_names `{}` {:?}", result, substs); - (result, substs) + Some((result, substs)) } // This is a bit sketchy. The token rules probably need tweaking, but it works diff --git a/tests/source/macros.rs b/tests/source/macros.rs index dca1e0e7033..ffd5c19cc8c 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -332,3 +332,7 @@ macro foo() { bar(); } } + +macro lex_err($kind: ident $(, $body: expr)*) { + Err(QlError::LexError(LexError::$kind($($body,)*))) +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 75238b11ab7..a79eb8fb294 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -905,3 +905,7 @@ macro foo() { bar(); } } + +macro lex_err($kind: ident $(, $body: expr)*) { + Err(QlError::LexError(LexError::$kind($($body,)*))) +} -- cgit 1.4.1-3-g733a5 From 3bb0a2a7495011868a52cdbb848f87e59bdc98d8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 4 Feb 2018 12:08:02 +0900 Subject: Do not reorder items with '#[macro_use]' Reordering items with `#[macro_use]` could change the semantic of source code. There could exist other attributes that requires special treatment. --- src/visitor.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 3157597697d..c28eed561a5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,7 +11,7 @@ use std::cmp; use syntax::{ast, visit}; -use syntax::attr::HasAttrs; +use syntax::attr::{self, HasAttrs}; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; @@ -49,11 +49,15 @@ fn is_mod_decl(item: &ast::Item) -> bool { } } +fn contains_macro_use_attr(attrs: &[ast::Attribute], span: Span) -> bool { + attr::contains_name(&filter_inline_attrs(attrs, span), "macro_use") +} + /// Returns true for `mod foo;` without any inline attributes. /// We cannot reorder modules with attributes because doing so can break the code. /// e.g. `#[macro_use]`. fn is_mod_decl_without_attr(item: &ast::Item) -> bool { - is_mod_decl(item) && filter_inline_attrs(&item.attrs, item.span()).is_empty() + is_mod_decl(item) && !contains_macro_use_attr(&item.attrs, item.span()) } fn is_use_item(item: &ast::Item) -> bool { @@ -63,6 +67,10 @@ fn is_use_item(item: &ast::Item) -> bool { } } +fn is_use_item_without_attr(item: &ast::Item) -> bool { + is_use_item(item) && !contains_macro_use_attr(&item.attrs, item.span()) +} + fn is_extern_crate(item: &ast::Item) -> bool { match item.node { ast::ItemKind::ExternCrate(..) => true, @@ -70,6 +78,10 @@ fn is_extern_crate(item: &ast::Item) -> bool { } } +fn is_extern_crate_without_attr(item: &ast::Item) -> bool { + is_extern_crate(item) && !contains_macro_use_attr(&item.attrs, item.span()) +} + /// Creates a string slice corresponding to the specified span. pub struct SnippetProvider<'a> { /// A pointer to the content of the file we are formatting. @@ -676,11 +688,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // subsequent items that have the same item kind to be reordered within // `format_imports`. Otherwise, just format the next item for output. { - try_reorder_items_with!(reorder_imports, reorder_imports_in_group, is_use_item); + try_reorder_items_with!( + reorder_imports, + reorder_imports_in_group, + is_use_item_without_attr + ); try_reorder_items_with!( reorder_extern_crates, reorder_extern_crates_in_group, - is_extern_crate + is_extern_crate_without_attr ); try_reorder_items_with!(reorder_modules, reorder_modules, is_mod_decl_without_attr); } -- cgit 1.4.1-3-g733a5 From f815858420980bc4f9119731647a0fae9e7978c7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 4 Feb 2018 17:21:10 +0900 Subject: Use correct offset when unindenting code block When using hard tabs, we should only remove '\t'. --- src/lib.rs | 7 ++++++- tests/target/issue-2401.rs | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-2401.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 773567e5f88..2b89bde72c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -571,7 +571,12 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); if line.starts_with(indent_str.as_ref()) { - &line[config.tab_spaces()..] + let offset = if config.hard_tabs() { + 1 + } else { + config.tab_spaces() + }; + &line[offset..] } else { line } diff --git a/tests/target/issue-2401.rs b/tests/target/issue-2401.rs new file mode 100644 index 00000000000..ec8f27b732f --- /dev/null +++ b/tests/target/issue-2401.rs @@ -0,0 +1,7 @@ +// rustfmt-hard_tabs = true +// rustfmt-normalize_comments = true + +/// ``` +/// println!("Hello, World!"); +/// ``` +fn main() {} -- cgit 1.4.1-3-g733a5 From 5d973d2e8c1021ca8a7844f5d994c2e2be8b7a07 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 24 Jan 2018 18:21:01 +0000 Subject: Initial support for macros 1.1 --- src/macros.rs | 150 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 84 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 7df793ca79d..86ac93d19be 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -291,88 +291,103 @@ pub fn rewrite_macro_def( ) -> Option { let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); - if def.legacy { - return snippet; - } - let mut parser = MacroParser::new(def.stream().into_trees()); - let mut parsed_def = match parser.parse() { + let parsed_def = match parser.parse() { Some(def) => def, None => return snippet, }; - // Only attempt to format function-like macros. - if parsed_def.branches.len() != 1 || parsed_def.branches[0].args_paren_kind != DelimToken::Paren - { - // FIXME(#1539): implement for non-sugared macros. - return snippet; - } + let mut result = if def.legacy { + String::from("macro_rules!") + } else { + format!("{}macro", format_visibility(vis)) + }; - let branch = parsed_def.branches.remove(0); - let args_str = format_macro_args(branch.args)?; + result += " "; + result += &ident.name.as_str(); + result += " {"; - // The macro body is the most interesting part. It might end up as various - // AST nodes, but also has special variables (e.g, `$foo`) which can't be - // parsed as regular Rust code (and note that these can be escaped using - // `$$`). We'll try and format like an AST node, but we'll substitute - // variables for new names with the same length first. + let mac_indent = indent.block_indent(context.config); + let mac_indent_str = mac_indent.to_string(context.config); - let old_body = context.snippet(branch.body).trim(); - let (body_str, substs) = match replace_names(old_body) { - Some(result) => result, - None => return snippet, - }; + for branch in parsed_def.branches { + // Only attempt to format function-like macros. + if branch.args_paren_kind != DelimToken::Paren { + // FIXME(#1539): implement for non-sugared macros. + return snippet; + } + + result += "\n"; + result += &mac_indent_str; + result += "("; + result += &format_macro_args(branch.args)?; + result += ") => {\n"; + + // The macro body is the most interesting part. It might end up as various + // AST nodes, but also has special variables (e.g, `$foo`) which can't be + // parsed as regular Rust code (and note that these can be escaped using + // `$$`). We'll try and format like an AST node, but we'll substitute + // variables for new names with the same length first. + + let old_body = context.snippet(branch.body).trim(); + let (body_str, substs) = match replace_names(old_body) { + Some(result) => result, + None => return snippet, + }; - // We'll hack the indent below, take this into account when formatting, - let mut config = context.config.clone(); - let new_width = config.max_width() - indent.block_indent(&config).width(); - config.set().max_width(new_width); - config.set().hide_parse_errors(true); + // We'll hack the indent below, take this into account when formatting, + let mut config = context.config.clone(); + let body_indent = mac_indent.block_indent(&config); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); + config.set().hide_parse_errors(true); - // First try to format as items, then as statements. - let new_body = match ::format_snippet(&body_str, &config) { - Some(new_body) => new_body, - None => match ::format_code_block(&body_str, &config) { + // First try to format as items, then as statements. + let new_body = match ::format_snippet(&body_str, &config) { Some(new_body) => new_body, - None => return snippet, - }, - }; + None => match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return snippet, + }, + }; - // Indent the body since it is in a block. - let indent_str = indent.block_indent(&config).to_string(&config); - let mut new_body = new_body - .lines() - .map(|l| { - if l.is_empty() { - l.to_owned() - } else { - format!("{}{}", indent_str, l) + // Indent the body since it is in a block. + let indent_str = body_indent.to_string(&config); + let mut new_body = new_body + .trim_right() + .lines() + .fold(String::new(), |mut s, l| { + if !l.is_empty() { + s += &indent_str; + } + s + l + "\n" + }); + + // Undo our replacement of macro variables. + // FIXME: this could be *much* more efficient. + for (old, new) in &substs { + if old_body.find(new).is_some() { + debug!( + "rewrite_macro_def: bailing matching variable: `{}` in `{}`", + new, ident + ); + return snippet; } - }) - .collect::>() - .join("\n"); - - // Undo our replacement of macro variables. - // FIXME: this could be *much* more efficient. - for (old, new) in &substs { - if old_body.find(new).is_some() { - debug!( - "rewrite_macro_def: bailing matching variable: `{}` in `{}`", - new, ident - ); - return snippet; + new_body = new_body.replace(new, old); + } + + result += &new_body; + + result += &mac_indent_str; + result += "}"; + if def.legacy{ + result += ";"; } - new_body = new_body.replace(new, old); + result += "\n"; } - let result = format!( - "{}macro {}({}) {{\n{}\n{}}}", - format_visibility(vis), - ident, - args_str, - new_body, - indent.to_string(context.config), - ); + result += &indent.to_string(context.config); + result += "}"; Some(result) } @@ -729,6 +744,9 @@ impl MacroParser { Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt) } }; + if let Some(TokenTree::Token(_, Token::Semi)) = self.toks.look_ahead(0) { + self.toks.next(); + } Some(MacroBranch { args, args_paren_kind, -- cgit 1.4.1-3-g733a5 From 9318b4d2cfc3690812a4cad93934d505d1a6f72d Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 24 Jan 2018 19:25:57 +0000 Subject: Update some macro tests --- src/bin/cargo-fmt.rs | 2 +- tests/target/macro_not_expr.rs | 3 ++- tests/target/macros.rs | 46 +++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 180c6f0abf3..2c5f16b46fb 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -97,7 +97,7 @@ fn execute() -> i32 { } macro_rules! print_usage { - ($print:ident, $opts:ident, $reason:expr) => ({ + ($print: ident, $opts: ident, $reason: expr) => ({ let msg = format!("{}\nusage: cargo fmt [options]", $reason); $print!( "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ diff --git a/tests/target/macro_not_expr.rs b/tests/target/macro_not_expr.rs index d8de4dce38f..20dcfe2d622 100644 --- a/tests/target/macro_not_expr.rs +++ b/tests/target/macro_not_expr.rs @@ -1,5 +1,6 @@ macro_rules! test { - ($($t:tt)*) => {} + ($($t: tt)*) => { + }; } fn main() { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index a79eb8fb294..471c90bf470 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -141,7 +141,8 @@ fn issue_1555() { fn issue1178() { macro_rules! foo { - (#[$attr:meta] $name:ident) => {} + (#[$attr: meta] $name: ident) => { + }; } foo!( @@ -246,11 +247,15 @@ fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { // #878 macro_rules! try_opt { - ($expr:expr) => (match $expr { - Some(val) => val, + ($expr: expr) => { + match $expr { + Some(val) => val, - None => { return None; } - }) + None => { + return None; + } + } + }; } // #2214 @@ -885,24 +890,29 @@ fn macro_in_pattern_position() { }; } -macro foo() { - +macro foo { + () => { + } } -pub macro bar($x: ident + $y: expr;) { - fn foo($x: Foo) { - long_function( - a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), - $x.bar($y), - ); +pub macro bar { + ($x: ident + $y: expr;) => { + fn foo($x: Foo) { + long_function( + a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), + $x.bar($y), + ); + } } } -macro foo() { - // a comment - fn foo() { - // another comment - bar(); +macro foo { + () => { + // a comment + fn foo() { + // another comment + bar(); + } } } -- cgit 1.4.1-3-g733a5 From 1b9fd0134367be836ff53422175cfcff3eeb06d6 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 25 Jan 2018 13:28:55 +0000 Subject: Support compact macros 2.0 representation --- src/macros.rs | 36 ++++++++++++++++++++++++++---------- tests/target/macros.rs | 35 ++++++++++++++--------------------- 2 files changed, 40 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 86ac93d19be..a15227fb020 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -305,9 +305,16 @@ pub fn rewrite_macro_def( result += " "; result += &ident.name.as_str(); - result += " {"; - let mac_indent = indent.block_indent(context.config); + let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; + + let mac_indent = if multi_branch_style { + result += " {"; + indent.block_indent(context.config) + } else { + indent + }; + let mac_indent_str = mac_indent.to_string(context.config); for branch in parsed_def.branches { @@ -317,11 +324,18 @@ pub fn rewrite_macro_def( return snippet; } - result += "\n"; - result += &mac_indent_str; - result += "("; - result += &format_macro_args(branch.args)?; - result += ") => {\n"; + let args = format!("({})", format_macro_args(branch.args)?); + + if multi_branch_style { + result += "\n"; + result += &mac_indent_str; + result += &args; + result += " =>"; + } else { + result += &args; + } + + result += " {\n"; // The macro body is the most interesting part. It might end up as various // AST nodes, but also has special variables (e.g, `$foo`) which can't be @@ -380,14 +394,16 @@ pub fn rewrite_macro_def( result += &mac_indent_str; result += "}"; - if def.legacy{ + if def.legacy { result += ";"; } result += "\n"; } - result += &indent.to_string(context.config); - result += "}"; + if multi_branch_style { + result += &indent.to_string(context.config); + result += "}"; + } Some(result) } diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 471c90bf470..82cc76554f5 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -27,9 +27,8 @@ fn main() { ); kaas!( - // comments - a, // post macro - b // another + /* comments */ a, /* post macro */ + b /* another */ ); trailingcomma!(a, b, c,); @@ -890,29 +889,23 @@ fn macro_in_pattern_position() { }; } -macro foo { - () => { - } +macro foo() { } -pub macro bar { - ($x: ident + $y: expr;) => { - fn foo($x: Foo) { - long_function( - a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), - $x.bar($y), - ); - } +pub macro bar($x: ident + $y: expr;) { + fn foo($x: Foo) { + long_function( + a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), + $x.bar($y), + ); } } -macro foo { - () => { - // a comment - fn foo() { - // another comment - bar(); - } +macro foo() { + // a comment + fn foo() { + // another comment + bar(); } } -- cgit 1.4.1-3-g733a5 From 5bd036fcac1b109baf6b0d9a05af5232ec82c495 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 25 Jan 2018 14:06:37 +0000 Subject: Optimise common `=> {{` macro pattern --- src/bin/cargo-fmt.rs | 4 ++-- src/macros.rs | 29 +++++++++++++++++++++-------- tests/target/macro_rules.rs | 10 ++++------ 3 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs index 2c5f16b46fb..1acad99688a 100644 --- a/src/bin/cargo-fmt.rs +++ b/src/bin/cargo-fmt.rs @@ -97,14 +97,14 @@ fn execute() -> i32 { } macro_rules! print_usage { - ($print: ident, $opts: ident, $reason: expr) => ({ + ($print: ident, $opts: ident, $reason: expr) => {{ let msg = format!("{}\nusage: cargo fmt [options]", $reason); $print!( "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ Arguments after `--` are passed to rustfmt.", $opts.usage(&msg) ); - }) + }}; } fn print_usage_to_stdout(opts: &Options, reason: &str) { diff --git a/src/macros.rs b/src/macros.rs index a15227fb020..f362736ea92 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -335,8 +335,6 @@ pub fn rewrite_macro_def( result += &args; } - result += " {\n"; - // The macro body is the most interesting part. It might end up as various // AST nodes, but also has special variables (e.g, `$foo`) which can't be // parsed as regular Rust code (and note that these can be escaped using @@ -349,13 +347,23 @@ pub fn rewrite_macro_def( None => return snippet, }; - // We'll hack the indent below, take this into account when formatting, let mut config = context.config.clone(); - let body_indent = mac_indent.block_indent(&config); - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); config.set().hide_parse_errors(true); + result += " {"; + + let has_block_body = old_body.starts_with("{"); + + let body_indent = if has_block_body { + mac_indent + } else { + // We'll hack the indent below, take this into account when formatting, + let body_indent = mac_indent.block_indent(&config); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); + body_indent + }; + // First try to format as items, then as statements. let new_body = match ::format_snippet(&body_str, &config) { Some(new_body) => new_body, @@ -390,9 +398,14 @@ pub fn rewrite_macro_def( new_body = new_body.replace(new, old); } - result += &new_body; + if has_block_body { + result += new_body.trim(); + } else { + result += "\n"; + result += &new_body; + result += &mac_indent_str; + } - result += &mac_indent_str; result += "}"; if def.legacy { result += ";"; diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index c1b1d017adb..4c494c932d6 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -1,10 +1,8 @@ macro_rules! m { - ($expr: expr, $func: ident) => { - { - let x = $expr; - $func(x) - } - }; + ($expr: expr, $func: ident) => {{ + let x = $expr; + $func(x) + }}; () => { }; -- cgit 1.4.1-3-g733a5 From 9423cdba82026ce78bb5e24e7af619dde0b56a0e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 25 Jan 2018 14:12:18 +0000 Subject: Omit newline for empty macro branches --- src/macros.rs | 2 +- tests/target/macro_not_expr.rs | 3 +-- tests/target/macro_rules.rs | 3 +-- tests/target/macros.rs | 6 ++---- 4 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index f362736ea92..2f7c4262b6b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -400,7 +400,7 @@ pub fn rewrite_macro_def( if has_block_body { result += new_body.trim(); - } else { + } else if !new_body.is_empty() { result += "\n"; result += &new_body; result += &mac_indent_str; diff --git a/tests/target/macro_not_expr.rs b/tests/target/macro_not_expr.rs index 20dcfe2d622..c76a6492a9d 100644 --- a/tests/target/macro_not_expr.rs +++ b/tests/target/macro_not_expr.rs @@ -1,6 +1,5 @@ macro_rules! test { - ($($t: tt)*) => { - }; + ($($t: tt)*) => {}; } fn main() { diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 4c494c932d6..d5ce0f7309e 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -4,8 +4,7 @@ macro_rules! m { $func(x) }}; - () => { - }; + () => {}; ($item: ident) => { mod macro_item { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 83116de7e3d..9b32c6623bb 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -141,8 +141,7 @@ fn issue_1555() { fn issue1178() { macro_rules! foo { - (#[$attr: meta] $name: ident) => { - }; + (#[$attr: meta] $name: ident) => {}; } foo!( @@ -890,8 +889,7 @@ fn macro_in_pattern_position() { }; } -macro foo() { -} +macro foo() {} pub macro bar($x: ident + $y: expr;) { fn foo($x: Foo) { -- cgit 1.4.1-3-g733a5 From 41c393c7516d4c1d5d8ad29fa177b43fb620b211 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 28 Jan 2018 19:08:09 +0000 Subject: Keep delimiter as part of macro args list --- src/macros.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 2f7c4262b6b..10f03e95c2f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -324,7 +324,7 @@ pub fn rewrite_macro_def( return snippet; } - let args = format!("({})", format_macro_args(branch.args)?); + let args = format_macro_args(branch.args)?; if multi_branch_style { result += "\n"; @@ -758,10 +758,12 @@ impl MacroParser { // `(` ... `)` `=>` `{` ... `}` fn parse_branch(&mut self) -> Option { - let (args_paren_kind, args) = match self.toks.next()? { + let tok = self.toks.next()?; + let args_paren_kind = match tok { TokenTree::Token(..) => return None, - TokenTree::Delimited(_, ref d) => (d.delim, d.tts.clone()), + TokenTree::Delimited(_, ref d) => d.delim, }; + let args = tok.joint().into(); match self.toks.next()? { TokenTree::Token(_, Token::FatArrow) => {} _ => return None, -- cgit 1.4.1-3-g733a5 From 70e77162621c7cde2435224cf1decdee088be27e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 29 Jan 2018 10:15:18 +0000 Subject: Comments WIP --- src/macros.rs | 201 ++++++++++++++++++++++++++------------------ src/visitor.rs | 1 + tests/source/macro_rules.rs | 6 +- 3 files changed, 124 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 10f03e95c2f..1c9ca3057f0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,6 +33,7 @@ use syntax::util::ThinVec; use codemap::SpanUtils; use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; use expr::{rewrite_array, rewrite_call_inner}; +use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use utils::{format_visibility, mk_sp}; @@ -283,6 +284,7 @@ pub fn rewrite_macro( pub fn rewrite_macro_def( context: &RewriteContext, + shape: Shape, indent: Indent, def: &ast::MacroDef, ident: ast::Ident, @@ -317,101 +319,132 @@ pub fn rewrite_macro_def( let mac_indent_str = mac_indent.to_string(context.config); - for branch in parsed_def.branches { - // Only attempt to format function-like macros. - if branch.args_paren_kind != DelimToken::Paren { - // FIXME(#1539): implement for non-sugared macros. - return snippet; - } + let branch_items = itemize_list( + context.codemap, + parsed_def.branches.iter(), + "", + "", + |branch| branch.args_span.lo(), + |branch| branch.body.hi(), + |branch| { + let mut result = String::new(); + + // Only attempt to format function-like macros. + if branch.args_paren_kind != DelimToken::Paren { + // FIXME(#1539): implement for non-sugared macros. + return None; + } - let args = format_macro_args(branch.args)?; + let args = format_macro_args(branch.args.clone())?; - if multi_branch_style { - result += "\n"; - result += &mac_indent_str; - result += &args; - result += " =>"; - } else { - result += &args; - } + if multi_branch_style { + result += "\n"; + result += &mac_indent_str; + result += &args; + result += " =>"; + } else { + result += &args; + } - // The macro body is the most interesting part. It might end up as various - // AST nodes, but also has special variables (e.g, `$foo`) which can't be - // parsed as regular Rust code (and note that these can be escaped using - // `$$`). We'll try and format like an AST node, but we'll substitute - // variables for new names with the same length first. + // The macro body is the most interesting part. It might end up as various + // AST nodes, but also has special variables (e.g, `$foo`) which can't be + // parsed as regular Rust code (and note that these can be escaped using + // `$$`). We'll try and format like an AST node, but we'll substitute + // variables for new names with the same length first. - let old_body = context.snippet(branch.body).trim(); - let (body_str, substs) = match replace_names(old_body) { - Some(result) => result, - None => return snippet, - }; + let old_body = context.snippet(branch.body).trim(); + let (body_str, substs) = match replace_names(old_body) { + Some(result) => result, + None => return snippet, + }; - let mut config = context.config.clone(); - config.set().hide_parse_errors(true); + let mut config = context.config.clone(); + config.set().hide_parse_errors(true); - result += " {"; + result += " {"; - let has_block_body = old_body.starts_with("{"); + let has_block_body = old_body.starts_with('{'); - let body_indent = if has_block_body { - mac_indent - } else { - // We'll hack the indent below, take this into account when formatting, - let body_indent = mac_indent.block_indent(&config); - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); - body_indent - }; + let body_indent = if has_block_body { + mac_indent + } else { + // We'll hack the indent below, take this into account when formatting, + let body_indent = mac_indent.block_indent(&config); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); + body_indent + }; - // First try to format as items, then as statements. - let new_body = match ::format_snippet(&body_str, &config) { - Some(new_body) => new_body, - None => match ::format_code_block(&body_str, &config) { + // First try to format as items, then as statements. + let new_body = match ::format_snippet(&body_str, &config) { Some(new_body) => new_body, - None => return snippet, - }, - }; + None => match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return None, + }, + }; - // Indent the body since it is in a block. - let indent_str = body_indent.to_string(&config); - let mut new_body = new_body - .trim_right() - .lines() - .fold(String::new(), |mut s, l| { - if !l.is_empty() { - s += &indent_str; + // Indent the body since it is in a block. + let indent_str = body_indent.to_string(&config); + let mut new_body = new_body + .trim_right() + .lines() + .fold(String::new(), |mut s, l| { + if !l.is_empty() { + s += &indent_str; + } + s + l + "\n" + }); + + // Undo our replacement of macro variables. + // FIXME: this could be *much* more efficient. + for (old, new) in &substs { + if old_body.find(new).is_some() { + debug!( + "rewrite_macro_def: bailing matching variable: `{}` in `{}`", + new, ident + ); + return None; } - s + l + "\n" - }); - - // Undo our replacement of macro variables. - // FIXME: this could be *much* more efficient. - for (old, new) in &substs { - if old_body.find(new).is_some() { - debug!( - "rewrite_macro_def: bailing matching variable: `{}` in `{}`", - new, ident - ); - return snippet; + new_body = new_body.replace(new, old); } - new_body = new_body.replace(new, old); - } - if has_block_body { - result += new_body.trim(); - } else if !new_body.is_empty() { + if has_block_body { + result += new_body.trim(); + } else if !new_body.is_empty() { + result += "\n"; + result += &new_body; + result += &mac_indent_str; + } + + result += "}"; + if def.legacy { + result += ";"; + } result += "\n"; - result += &new_body; - result += &mac_indent_str; - } + Some(result) + }, + span.lo(), + span.hi(), + false + ).collect::>(); + + let arm_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arm_shape, + ends_with_newline: false, + preserve_newline: true, + config: context.config, + }; - result += "}"; - if def.legacy { - result += ";"; - } - result += "\n"; - } + result += write_list(&branch_items, &fmt)?.as_str(); if multi_branch_style { result += &indent.to_string(context.config); @@ -759,9 +792,9 @@ impl MacroParser { // `(` ... `)` `=>` `{` ... `}` fn parse_branch(&mut self) -> Option { let tok = self.toks.next()?; - let args_paren_kind = match tok { + let (args_span, args_paren_kind) = match tok { TokenTree::Token(..) => return None, - TokenTree::Delimited(_, ref d) => d.delim, + TokenTree::Delimited(sp, ref d) => (sp, d.delim), }; let args = tok.joint().into(); match self.toks.next()? { @@ -779,8 +812,9 @@ impl MacroParser { self.toks.next(); } Some(MacroBranch { - args, args_paren_kind, + args_span, + args, body, }) } @@ -794,8 +828,9 @@ struct Macro { // FIXME: it would be more efficient to use references to the token streams // rather than clone them, if we can make the borrowing work out. struct MacroBranch { - args: ThinTokenStream, args_paren_kind: DelimToken, + args_span: Span, + args: ThinTokenStream, body: Span, } diff --git a/src/visitor.rs b/src/visitor.rs index 3157597697d..398fc57ce47 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -451,6 +451,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::MacroDef(ref def) => { let rewrite = rewrite_macro_def( &self.get_context(), + self.shape(), self.block_indent, def, item.ident, diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index 24d4b669011..39de86b9bf6 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -1,4 +1,5 @@ macro_rules! m { + // a ($expr :expr, $( $func : ident ) * ) => { { let x = $expr; @@ -8,8 +9,11 @@ macro_rules! m { } }; - () => { }; + /* b */ + () => {/* c */}; + +// d ( $item:ident ) => { mod macro_item { struct $item ; } }; -- cgit 1.4.1-3-g733a5 From 6377c5223307e6bff3d1555c0cddd34bef1b68a0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 30 Jan 2018 17:05:31 +0000 Subject: Fix comment handling in macros --- src/macros.rs | 50 ++++++++++++++++++++++++--------------------- tests/source/macro_rules.rs | 31 ++++++++++++++++++++++++++++ tests/target/macro_rules.rs | 31 +++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 1c9ca3057f0..bd1523f2dea 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -311,7 +311,6 @@ pub fn rewrite_macro_def( let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; let mac_indent = if multi_branch_style { - result += " {"; indent.block_indent(context.config) } else { indent @@ -322,28 +321,25 @@ pub fn rewrite_macro_def( let branch_items = itemize_list( context.codemap, parsed_def.branches.iter(), - "", - "", - |branch| branch.args_span.lo(), - |branch| branch.body.hi(), + "}", + ";", + |branch| { + branch.span.lo() + }, + |branch| { + branch.span.hi() + }, |branch| { - let mut result = String::new(); - // Only attempt to format function-like macros. if branch.args_paren_kind != DelimToken::Paren { // FIXME(#1539): implement for non-sugared macros. return None; } - let args = format_macro_args(branch.args.clone())?; + let mut result = format_macro_args(branch.args.clone())?; if multi_branch_style { - result += "\n"; - result += &mac_indent_str; - result += &args; result += " =>"; - } else { - result += &args; } // The macro body is the most interesting part. It might end up as various @@ -418,13 +414,14 @@ pub fn rewrite_macro_def( } result += "}"; + if def.legacy { result += ";"; } - result += "\n"; + Some(result) }, - span.lo(), + context.codemap.span_after(span, "{"), span.hi(), false ).collect::>(); @@ -439,14 +436,20 @@ pub fn rewrite_macro_def( trailing_separator: SeparatorTactic::Never, separator_place: SeparatorPlace::Back, shape: arm_shape, - ends_with_newline: false, + ends_with_newline: true, preserve_newline: true, config: context.config, }; + if multi_branch_style { + result += " {\n"; + result += &mac_indent_str; + } + result += write_list(&branch_items, &fmt)?.as_str(); if multi_branch_style { + result += "\n"; result += &indent.to_string(context.config); result += "}"; } @@ -792,28 +795,29 @@ impl MacroParser { // `(` ... `)` `=>` `{` ... `}` fn parse_branch(&mut self) -> Option { let tok = self.toks.next()?; - let (args_span, args_paren_kind) = match tok { + let (lo, args_paren_kind) = match tok { TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, ref d) => (sp, d.delim), + TokenTree::Delimited(sp, ref d) => (sp.lo(), d.delim), }; let args = tok.joint().into(); match self.toks.next()? { TokenTree::Token(_, Token::FatArrow) => {} _ => return None, } - let body = match self.toks.next()? { + let (mut hi, body) = match self.toks.next()? { TokenTree::Token(..) => return None, TokenTree::Delimited(sp, _) => { let data = sp.data(); - Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt) + (data.hi, Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt)) } }; - if let Some(TokenTree::Token(_, Token::Semi)) = self.toks.look_ahead(0) { + if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { self.toks.next(); + hi = sp.hi(); } Some(MacroBranch { + span: mk_sp(lo, hi), args_paren_kind, - args_span, args, body, }) @@ -828,8 +832,8 @@ struct Macro { // FIXME: it would be more efficient to use references to the token streams // rather than clone them, if we can make the borrowing work out. struct MacroBranch { + span: Span, args_paren_kind: DelimToken, - args_span: Span, args: ThinTokenStream, body: Span, } diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index 39de86b9bf6..7d14f44971d 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -13,8 +13,39 @@ macro_rules! m { () => {/* c */}; + (@tag) => + { + + }; + // d ( $item:ident ) => { mod macro_item { struct $item ; } }; } + +macro m2 { + // a + ($expr :expr, $( $func : ident ) * ) => { + { + let x = $expr; + $func ( + x + ) + } + } + + /* b */ + + () => {/* c */} + + (@tag) => + { + + } + +// d +( $item:ident ) => { + mod macro_item { struct $item ; } +} +} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 5835c27faee..647d442034f 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -1,14 +1,43 @@ macro_rules! m { + // a ($expr: expr, $($func: ident)*) => {{ let x = $expr; $func(x) }}; - () => {}; + /* b */ + () => { + /* c */ + }; + + (@tag) => {}; + // d ($item: ident) => { mod macro_item { struct $item; } }; } + +macro m2 { + // a + ($expr: expr, $($func: ident)*) => {{ + let x = $expr; + $func(x) + }} + + /* b */ + () => { + /* c */ + } + + (@tag) => {} + + // d + ($item: ident) => { + mod macro_item { + struct $item; + } + } +} -- cgit 1.4.1-3-g733a5 From bc9185451d547a071b74e9432d1c447dbbdeac6e Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 30 Jan 2018 17:14:13 +0000 Subject: Move ; between macro branches to a separator --- src/macros.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index bd1523f2dea..d7e49ec0e0a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -415,10 +415,6 @@ pub fn rewrite_macro_def( result += "}"; - if def.legacy { - result += ";"; - } - Some(result) }, context.codemap.span_after(span, "{"), @@ -432,8 +428,8 @@ pub fn rewrite_macro_def( let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, - separator: "", - trailing_separator: SeparatorTactic::Never, + separator: if def.legacy { ";" } else { "" }, + trailing_separator: SeparatorTactic::Always, separator_place: SeparatorPlace::Back, shape: arm_shape, ends_with_newline: true, -- cgit 1.4.1-3-g733a5 From 571af9d4b11d8ccc64ab637d9881485e0f6a059a Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 30 Jan 2018 17:24:28 +0000 Subject: Format --- src/macros.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index d7e49ec0e0a..42a091fc57b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -323,12 +323,8 @@ pub fn rewrite_macro_def( parsed_def.branches.iter(), "}", ";", - |branch| { - branch.span.lo() - }, - |branch| { - branch.span.hi() - }, + |branch| branch.span.lo(), + |branch| branch.span.hi(), |branch| { // Only attempt to format function-like macros. if branch.args_paren_kind != DelimToken::Paren { @@ -419,7 +415,7 @@ pub fn rewrite_macro_def( }, context.codemap.span_after(span, "{"), span.hi(), - false + false, ).collect::>(); let arm_shape = shape @@ -804,7 +800,10 @@ impl MacroParser { TokenTree::Token(..) => return None, TokenTree::Delimited(sp, _) => { let data = sp.data(); - (data.hi, Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt)) + ( + data.hi, + Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), + ) } }; if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { -- cgit 1.4.1-3-g733a5 From d8c154f05254cf09bf15a14fdfdadb4f50fb9e55 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 30 Jan 2018 18:19:47 +0000 Subject: Extract branch rewrite function --- src/macros.rs | 193 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 95 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 42a091fc57b..bb623368b97 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -310,14 +310,14 @@ pub fn rewrite_macro_def( let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; - let mac_indent = if multi_branch_style { - indent.block_indent(context.config) + let arm_shape = if multi_branch_style { + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) } else { - indent + shape }; - let mac_indent_str = mac_indent.to_string(context.config); - let branch_items = itemize_list( context.codemap, parsed_def.branches.iter(), @@ -325,103 +325,12 @@ pub fn rewrite_macro_def( ";", |branch| branch.span.lo(), |branch| branch.span.hi(), - |branch| { - // Only attempt to format function-like macros. - if branch.args_paren_kind != DelimToken::Paren { - // FIXME(#1539): implement for non-sugared macros. - return None; - } - - let mut result = format_macro_args(branch.args.clone())?; - - if multi_branch_style { - result += " =>"; - } - - // The macro body is the most interesting part. It might end up as various - // AST nodes, but also has special variables (e.g, `$foo`) which can't be - // parsed as regular Rust code (and note that these can be escaped using - // `$$`). We'll try and format like an AST node, but we'll substitute - // variables for new names with the same length first. - - let old_body = context.snippet(branch.body).trim(); - let (body_str, substs) = match replace_names(old_body) { - Some(result) => result, - None => return snippet, - }; - - let mut config = context.config.clone(); - config.set().hide_parse_errors(true); - - result += " {"; - - let has_block_body = old_body.starts_with('{'); - - let body_indent = if has_block_body { - mac_indent - } else { - // We'll hack the indent below, take this into account when formatting, - let body_indent = mac_indent.block_indent(&config); - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); - body_indent - }; - - // First try to format as items, then as statements. - let new_body = match ::format_snippet(&body_str, &config) { - Some(new_body) => new_body, - None => match ::format_code_block(&body_str, &config) { - Some(new_body) => new_body, - None => return None, - }, - }; - - // Indent the body since it is in a block. - let indent_str = body_indent.to_string(&config); - let mut new_body = new_body - .trim_right() - .lines() - .fold(String::new(), |mut s, l| { - if !l.is_empty() { - s += &indent_str; - } - s + l + "\n" - }); - - // Undo our replacement of macro variables. - // FIXME: this could be *much* more efficient. - for (old, new) in &substs { - if old_body.find(new).is_some() { - debug!( - "rewrite_macro_def: bailing matching variable: `{}` in `{}`", - new, ident - ); - return None; - } - new_body = new_body.replace(new, old); - } - - if has_block_body { - result += new_body.trim(); - } else if !new_body.is_empty() { - result += "\n"; - result += &new_body; - result += &mac_indent_str; - } - - result += "}"; - - Some(result) - }, + |branch| branch.rewrite(context, arm_shape, multi_branch_style), context.codemap.span_after(span, "{"), span.hi(), false, ).collect::>(); - let arm_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: if def.legacy { ";" } else { "" }, @@ -435,7 +344,7 @@ pub fn rewrite_macro_def( if multi_branch_style { result += " {\n"; - result += &mac_indent_str; + result += &arm_shape.indent.to_string(context.config); } result += write_list(&branch_items, &fmt)?.as_str(); @@ -833,6 +742,94 @@ struct MacroBranch { body: Span, } +impl MacroBranch { + fn rewrite(&self, context: &RewriteContext, shape: Shape, multi_branch_style: bool) -> Option { + // Only attempt to format function-like macros. + if self.args_paren_kind != DelimToken::Paren { + // FIXME(#1539): implement for non-sugared macros. + return None; + } + + let mut result = format_macro_args(self.args.clone())?; + + if multi_branch_style { + result += " =>"; + } + + // The macro body is the most interesting part. It might end up as various + // AST nodes, but also has special variables (e.g, `$foo`) which can't be + // parsed as regular Rust code (and note that these can be escaped using + // `$$`). We'll try and format like an AST node, but we'll substitute + // variables for new names with the same length first. + + let old_body = context.snippet(self.body).trim(); + let (body_str, substs) = replace_names(old_body)?; + + let mut config = context.config.clone(); + config.set().hide_parse_errors(true); + + result += " {"; + + let has_block_body = old_body.starts_with('{'); + + let body_indent = if has_block_body { + shape.indent + } else { + // We'll hack the indent below, take this into account when formatting, + let body_indent = shape.indent.block_indent(&config); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); + body_indent + }; + + // First try to format as items, then as statements. + let new_body = match ::format_snippet(&body_str, &config) { + Some(new_body) => new_body, + None => match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return None, + }, + }; + + // Indent the body since it is in a block. + let indent_str = body_indent.to_string(&config); + let mut new_body = new_body + .trim_right() + .lines() + .fold(String::new(), |mut s, l| { + if !l.is_empty() { + s += &indent_str; + } + s + l + "\n" + }); + + // Undo our replacement of macro variables. + // FIXME: this could be *much* more efficient. + for (old, new) in &substs { + if old_body.find(new).is_some() { + debug!( + "rewrite_macro_def: bailing matching variable: `{}`", + new + ); + return None; + } + new_body = new_body.replace(new, old); + } + + if has_block_body { + result += new_body.trim(); + } else if !new_body.is_empty() { + result += "\n"; + result += &new_body; + result += &shape.indent.to_string(&config); + } + + result += "}"; + + Some(result) + } +} + #[cfg(test)] mod test { use super::*; -- cgit 1.4.1-3-g733a5 From 8691c64e9970043f13ed3d5a6f1ac62ced7159f3 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Sun, 4 Feb 2018 12:09:03 +0000 Subject: cargo run cargo-fmt Reformat codebase with current version to pass self_tests (formats macros without repetitions). --- src/config.rs | 2 +- src/macros.rs | 21 ++++++++++++--------- src/spanned.rs | 24 +++++++++++------------- src/utils.rs | 19 ++++++++++--------- 4 files changed, 34 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index c313f8e2aef..cca1779a4a8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -36,7 +36,7 @@ macro_rules! is_nightly_channel { option_env!("CFG_RELEASE_CHANNEL") .map(|c| c == "nightly") .unwrap_or(true) - } + }; } macro_rules! configuration_option_enum{ diff --git a/src/macros.rs b/src/macros.rs index bb623368b97..3abfe6239fd 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,8 @@ use syntax::util::ThinVec; use codemap::SpanUtils; use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; use expr::{rewrite_array, rewrite_call_inner}; -use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, SeparatorTactic}; +use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, + SeparatorTactic}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use utils::{format_visibility, mk_sp}; @@ -102,7 +103,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { parser.sess.span_diagnostic.reset_err_count(); } } - } + }; } parse_macro_arg!(Expr, parse_expr); @@ -312,8 +313,8 @@ pub fn rewrite_macro_def( let arm_shape = if multi_branch_style { shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) } else { shape }; @@ -743,7 +744,12 @@ struct MacroBranch { } impl MacroBranch { - fn rewrite(&self, context: &RewriteContext, shape: Shape, multi_branch_style: bool) -> Option { + fn rewrite( + &self, + context: &RewriteContext, + shape: Shape, + multi_branch_style: bool, + ) -> Option { // Only attempt to format function-like macros. if self.args_paren_kind != DelimToken::Paren { // FIXME(#1539): implement for non-sugared macros. @@ -807,10 +813,7 @@ impl MacroBranch { // FIXME: this could be *much* more efficient. for (old, new) in &substs { if old_body.find(new).is_some() { - debug!( - "rewrite_macro_def: bailing matching variable: `{}`", - new - ); + debug!("rewrite_macro_def: bailing matching variable: `{}`", new); return None; } new_body = new_body.replace(new, old); diff --git a/src/spanned.rs b/src/spanned.rs index eb36a117428..a431f3a544a 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -20,32 +20,30 @@ pub trait Spanned { } macro_rules! span_with_attrs_lo_hi { - ($this:ident, $lo:expr, $hi:expr) => { - { - let attrs = outer_attributes(&$this.attrs); - if attrs.is_empty() { - mk_sp($lo, $hi) - } else { - mk_sp(attrs[0].span.lo(), $hi) - } + ($this: ident, $lo: expr, $hi: expr) => {{ + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo(), $hi) } - } + }}; } macro_rules! span_with_attrs { - ($this:ident) => { + ($this: ident) => { span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) - } + }; } macro_rules! implement_spanned { - ($this:ty) => { + ($this: ty) => { impl Spanned for $this { fn span(&self) -> Span { span_with_attrs!(self) } } - } + }; } // Implement `Spanned` for structs with `attrs` field. diff --git a/src/utils.rs b/src/utils.rs index 2f65d273246..443dc6c7a05 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -342,9 +342,9 @@ macro_rules! msg { // For format_missing and last_pos, need to use the source callsite (if applicable). // Required as generated code spans aren't guaranteed to follow on from the last span. macro_rules! source { - ($this:ident, $sp: expr) => { + ($this: ident, $sp: expr) => { $sp.source_callsite() - } + }; } pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { @@ -353,28 +353,29 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { // Return true if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { - ($self:ident, $span:expr) => { - !$self.config + ($self: ident, $span: expr) => { + !$self + .config .file_lines() .intersects(&$self.codemap.lookup_line_range($span)) - } + }; } macro_rules! skip_out_of_file_lines_range { - ($self:ident, $span:expr) => { + ($self: ident, $span: expr) => { if out_of_file_lines_range!($self, $span) { return None; } - } + }; } macro_rules! skip_out_of_file_lines_range_visitor { - ($self:ident, $span:expr) => { + ($self: ident, $span: expr) => { if out_of_file_lines_range!($self, $span) { $self.push_rewrite($span, None); return; } - } + }; } // Wraps String in an Option. Returns Some when the string adheres to the -- cgit 1.4.1-3-g733a5 From 7f949a5018d77922891e12f134651590e6e78a6e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 6 Feb 2018 09:29:00 +0900 Subject: Explicitly disable colored output when it is not supported --- src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 2b89bde72c1..db05a24f979 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -615,7 +615,13 @@ pub fn format_input( )); Handler::with_emitter(true, false, silent_emitter) } else { - Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())) + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) }; let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); -- cgit 1.4.1-3-g733a5 From 5e0c6f9716af84361a2f15f8b1f91e9407d722f3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 6 Feb 2018 09:36:29 +0900 Subject: Avoid orphan in chain with punctuation --- src/imports.rs | 5 ++--- src/lib.rs | 1 - src/utils.rs | 2 +- tests/source/chains.rs | 15 +++++++++++++++ tests/target/chains.rs | 13 +++++++++++++ 5 files changed, 31 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 3818fd21950..0b65cafe730 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -127,13 +127,12 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Ordering { // `extern crate foo as bar;` // ^^^ Comparing this. - let result = match (a_name, b_name) { + match (a_name, b_name) { (Some(..), None) => Ordering::Greater, (None, Some(..)) => Ordering::Less, (None, None) => Ordering::Equal, (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), - }; - result + } } _ => unreachable!(), } diff --git a/src/lib.rs b/src/lib.rs index 2b89bde72c1..fc9fb2a9ce0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,6 @@ #![feature(decl_macro)] #![feature(match_default_bindings)] -#![feature(rustc_private)] #![feature(type_ascription)] #[macro_use] diff --git a/src/utils.rs b/src/utils.rs index 443dc6c7a05..20f4fdfe6d0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -178,7 +178,7 @@ pub fn last_line_extendable(s: &str) -> bool { } for c in s.chars().rev() { match c { - ')' | ']' | '}' | '?' | '>' => continue, + '(' | ')' | ']' | '}' | '?' | '>' => continue, '\n' => break, _ if c.is_whitespace() => continue, _ => return false, diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 0977212ef21..0ed52ae61be 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -214,3 +214,18 @@ impl Foo { }).collect(); } } + +// #2415 +// Avoid orphan in chain +fn issue2415() { + let base_url = (|| { + // stuff + + Ok((|| { + // stuff + Some(value.to_string()) + })() + .ok_or("")?) + })() + .unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 6e1fc809764..8a41eec2bde 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -246,3 +246,16 @@ impl Foo { .collect(); } } + +// #2415 +// Avoid orphan in chain +fn issue2415() { + let base_url = (|| { + // stuff + + Ok((|| { + // stuff + Some(value.to_string()) + })().ok_or("")?) + })().unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); +} -- cgit 1.4.1-3-g733a5 From 4af2aa3a9e2ab32e584c3d7bc97d74bdc8b35836 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 7 Feb 2018 22:48:05 +0900 Subject: Create rustfmt_core crate --- rustfmt-core/Cargo.toml | 33 + rustfmt-core/src/chains.rs | 499 ++++ rustfmt-core/src/checkstyle.rs | 85 + rustfmt-core/src/closures.rs | 392 +++ rustfmt-core/src/codemap.rs | 86 + rustfmt-core/src/comment.rs | 1234 +++++++++ rustfmt-core/src/expr.rs | 2930 ++++++++++++++++++++ rustfmt-core/src/filemap.rs | 176 ++ rustfmt-core/src/imports.rs | 600 ++++ rustfmt-core/src/issues.rs | 323 +++ rustfmt-core/src/items.rs | 2845 +++++++++++++++++++ rustfmt-core/src/lib.rs | 826 ++++++ rustfmt-core/src/lists.rs | 769 +++++ rustfmt-core/src/macros.rs | 872 ++++++ rustfmt-core/src/missed_spans.rs | 312 +++ rustfmt-core/src/modules.rs | 86 + rustfmt-core/src/patterns.rs | 380 +++ rustfmt-core/src/rewrite.rs | 54 + rustfmt-core/src/rustfmt_diff.rs | 247 ++ rustfmt-core/src/shape.rs | 353 +++ rustfmt-core/src/spanned.rs | 187 ++ rustfmt-core/src/string.rs | 163 ++ rustfmt-core/src/types.rs | 820 ++++++ rustfmt-core/src/utils.rs | 404 +++ rustfmt-core/src/vertical.rs | 290 ++ rustfmt-core/src/visitor.rs | 1113 ++++++++ .../tests/config/disable_all_formatting.toml | 1 + rustfmt-core/tests/config/issue-1111.toml | 1 + rustfmt-core/tests/config/small_tabs.toml | 12 + rustfmt-core/tests/coverage/source/comments.rs | 7 + rustfmt-core/tests/coverage/target/comments.rs | 7 + rustfmt-core/tests/lib.rs | 818 ++++++ rustfmt-core/tests/source/assignment.rs | 30 + .../source/associated-types-bounds-wrapping.rs | 6 + rustfmt-core/tests/source/attrib.rs | 152 + rustfmt-core/tests/source/big-impl-rfc.rs | 125 + rustfmt-core/tests/source/big-impl.rs | 104 + rustfmt-core/tests/source/break-and-continue.rs | 23 + rustfmt-core/tests/source/catch.rs | 27 + rustfmt-core/tests/source/chains-indent-tabbed.rs | 5 + rustfmt-core/tests/source/chains-indent-visual.rs | 5 + rustfmt-core/tests/source/chains-visual.rs | 159 ++ rustfmt-core/tests/source/chains.rs | 231 ++ .../tests/source/closure-block-inside-macro.rs | 11 + rustfmt-core/tests/source/closure.rs | 213 ++ rustfmt-core/tests/source/comment.rs | 90 + rustfmt-core/tests/source/comment2.rs | 4 + rustfmt-core/tests/source/comment3.rs | 5 + rustfmt-core/tests/source/comment4.rs | 52 + rustfmt-core/tests/source/comment5.rs | 14 + rustfmt-core/tests/source/comment_crlf_newline.rs | 4 + .../source/configs/blank_lines_lower_bound/1.rs | 13 + .../configs/brace_style/fn_always_next_line.rs | 14 + .../configs/brace_style/fn_prefer_same_line.rs | 14 + .../configs/brace_style/fn_same_line_where.rs | 14 + .../configs/brace_style/item_always_next_line.rs | 20 + .../configs/brace_style/item_prefer_same_line.rs | 16 + .../configs/brace_style/item_same_line_where.rs | 16 + .../tests/source/configs/comment_width/above.rs | 7 + .../tests/source/configs/comment_width/below.rs | 7 + .../tests/source/configs/comment_width/ignore.rs | 7 + .../configs/condense_wildcard_suffixes/false.rs | 6 + .../configs/condense_wildcard_suffixes/true.rs | 6 + .../control_brace_style/always_next_line.rs | 10 + .../control_brace_style/always_same_line.rs | 10 + .../control_brace_style/closing_next_line.rs | 10 + .../source/configs/disable_all_formatting/false.rs | 6 + .../source/configs/disable_all_formatting/true.rs | 6 + .../source/configs/empty_item_single_line/false.rs | 17 + .../source/configs/empty_item_single_line/true.rs | 17 + .../source/configs/error_on_line_overflow/false.rs | 6 + .../source/configs/fn_args_density/compressed.rs | 16 + .../tests/source/configs/fn_args_density/tall.rs | 16 + .../source/configs/fn_args_density/vertical.rs | 16 + .../tests/source/configs/fn_single_line/false.rs | 11 + .../tests/source/configs/fn_single_line/true.rs | 11 + .../source/configs/force_explicit_abi/false.rs | 6 + .../source/configs/force_explicit_abi/true.rs | 6 + .../source/configs/force_multiline_block/false.rs | 22 + .../source/configs/force_multiline_block/true.rs | 18 + .../tests/source/configs/format_strings/false.rs | 8 + .../tests/source/configs/format_strings/true.rs | 7 + .../tests/source/configs/hard_tabs/false.rs | 6 + .../tests/source/configs/hard_tabs/true.rs | 6 + .../source/configs/indent_style/block_args.rs | 26 + .../source/configs/indent_style/block_array.rs | 6 + .../source/configs/indent_style/block_call.rs | 133 + .../source/configs/indent_style/block_chain.rs | 6 + .../source/configs/indent_style/block_generic.rs | 6 + .../configs/indent_style/block_struct_lit.rs | 6 + .../indent_style/block_trailing_comma_call.rs | 8 + .../configs/indent_style/block_where_pred.rs | 6 + .../tests/source/configs/indent_style/default.rs | 6 + .../tests/source/configs/indent_style/rfc_where.rs | 6 + .../source/configs/indent_style/visual_args.rs | 32 + .../source/configs/indent_style/visual_array.rs | 6 + .../source/configs/indent_style/visual_call.rs | 6 + .../source/configs/indent_style/visual_chain.rs | 6 + .../source/configs/indent_style/visual_generics.rs | 6 + .../configs/indent_style/visual_struct_lit.rs | 6 + .../configs/indent_style/visual_trailing_comma.rs | 7 + .../configs/indent_style/visual_where_pred.rs | 6 + .../tests/source/configs/match_arm_blocks/false.rs | 11 + .../tests/source/configs/match_arm_blocks/true.rs | 11 + .../configs/match_block_trailing_comma/false.rs | 11 + .../configs/match_block_trailing_comma/true.rs | 11 + .../tests/source/configs/merge_derives/true.rs | 46 + .../source/configs/normalize_comments/false.rs | 13 + .../source/configs/normalize_comments/true.rs | 13 + .../source/configs/reorder_extern_crates/false.rs | 11 + .../source/configs/reorder_extern_crates/true.rs | 11 + .../source/configs/reorder_imported_names/false.rs | 4 + .../source/configs/reorder_imported_names/true.rs | 4 + .../tests/source/configs/reorder_imports/false.rs | 7 + .../tests/source/configs/reorder_imports/true.rs | 19 + .../configs/reorder_imports_in_group/false.rs | 13 + .../configs/reorder_imports_in_group/true.rs | 13 + .../source/configs/reorder_modules/dolor/mod.rs | 1 + .../tests/source/configs/reorder_modules/false.rs | 7 + .../source/configs/reorder_modules/ipsum/mod.rs | 1 + .../source/configs/reorder_modules/lorem/mod.rs | 1 + .../source/configs/reorder_modules/sit/mod.rs | 1 + .../tests/source/configs/reorder_modules/true.rs | 7 + .../source/configs/space_before_colon/true.rs | 11 + .../source/configs/spaces_around_ranges/false.rs | 22 + .../source/configs/spaces_around_ranges/true.rs | 22 + .../spaces_within_parens_and_brackets/false.rs | 7 + .../spaces_within_parens_and_brackets/true.rs | 133 + .../configs/struct_field_align_threshold/20.rs | 383 +++ .../source/configs/struct_lit_single_line/false.rs | 6 + rustfmt-core/tests/source/configs/tab_spaces/2.rs | 11 + rustfmt-core/tests/source/configs/tab_spaces/4.rs | 11 + .../tests/source/configs/trailing_comma/always.rs | 7 + .../tests/source/configs/trailing_comma/never.rs | 23 + .../source/configs/trailing_comma/vertical.rs | 7 + .../configs/type_punctuation_density/compressed.rs | 6 + .../configs/type_punctuation_density/wide.rs | 6 + .../configs/use_field_init_shorthand/false.rs | 19 + .../configs/use_field_init_shorthand/true.rs | 19 + .../source/configs/use_try_shorthand/false.rs | 6 + .../tests/source/configs/use_try_shorthand/true.rs | 6 + .../tests/source/configs/where_single_line/true.rs | 24 + .../tests/source/configs/wrap_comments/false.rs | 8 + .../tests/source/configs/wrap_comments/true.rs | 15 + .../source/control-brace-style-always-next-line.rs | 44 + .../source/control-brace-style-always-same-line.rs | 44 + rustfmt-core/tests/source/doc.rs | 4 + .../source/else-if-brace-style-always-next-line.rs | 54 + .../source/else-if-brace-style-always-same-line.rs | 54 + .../else-if-brace-style-closing-next-line.rs | 54 + rustfmt-core/tests/source/empty_file.rs | 0 rustfmt-core/tests/source/enum.rs | 194 ++ rustfmt-core/tests/source/expr-block.rs | 286 ++ rustfmt-core/tests/source/expr.rs | 372 +++ rustfmt-core/tests/source/extern.rs | 60 + rustfmt-core/tests/source/extern_not_explicit.rs | 14 + rustfmt-core/tests/source/file-lines-1.rs | 29 + rustfmt-core/tests/source/file-lines-2.rs | 29 + rustfmt-core/tests/source/file-lines-3.rs | 30 + rustfmt-core/tests/source/file-lines-4.rs | 30 + rustfmt-core/tests/source/file-lines-5.rs | 17 + rustfmt-core/tests/source/file-lines-6.rs | 18 + rustfmt-core/tests/source/file-lines-item.rs | 22 + rustfmt-core/tests/source/fn-custom-2.rs | 36 + rustfmt-core/tests/source/fn-custom-3.rs | 32 + rustfmt-core/tests/source/fn-custom-4.rs | 14 + rustfmt-core/tests/source/fn-custom-6.rs | 41 + rustfmt-core/tests/source/fn-custom-7.rs | 25 + rustfmt-core/tests/source/fn-custom-8.rs | 49 + rustfmt-core/tests/source/fn-custom.rs | 13 + rustfmt-core/tests/source/fn-simple.rs | 66 + rustfmt-core/tests/source/fn-single-line.rs | 79 + .../tests/source/fn_args_density-vertical.rs | 33 + rustfmt-core/tests/source/fn_args_indent-block.rs | 78 + rustfmt-core/tests/source/hard-tabs.rs | 85 + rustfmt-core/tests/source/hello.rs | 6 + rustfmt-core/tests/source/hello2.rs | 8 + rustfmt-core/tests/source/immovable_generators.rs | 7 + rustfmt-core/tests/source/impls.rs | 154 + .../source/imports-reorder-lines-and-items.rs | 10 + rustfmt-core/tests/source/imports-reorder-lines.rs | 34 + rustfmt-core/tests/source/imports-reorder.rs | 6 + rustfmt-core/tests/source/imports.rs | 89 + rustfmt-core/tests/source/issue-1021.rs | 22 + rustfmt-core/tests/source/issue-1049.rs | 18 + rustfmt-core/tests/source/issue-1111.rs | 1 + rustfmt-core/tests/source/issue-1120.rs | 9 + rustfmt-core/tests/source/issue-1124.rs | 16 + rustfmt-core/tests/source/issue-1127.rs | 23 + rustfmt-core/tests/source/issue-1158.rs | 3 + rustfmt-core/tests/source/issue-1177.rs | 7 + rustfmt-core/tests/source/issue-1192.rs | 3 + rustfmt-core/tests/source/issue-1211.rs | 15 + rustfmt-core/tests/source/issue-1216.rs | 5 + rustfmt-core/tests/source/issue-1239.rs | 9 + rustfmt-core/tests/source/issue-1278.rs | 9 + rustfmt-core/tests/source/issue-1350.rs | 16 + rustfmt-core/tests/source/issue-1366.rs | 12 + rustfmt-core/tests/source/issue-1468.rs | 27 + rustfmt-core/tests/source/issue-1693.rs | 3 + rustfmt-core/tests/source/issue-1800.rs | 3 + rustfmt-core/tests/source/issue-1914.rs | 6 + rustfmt-core/tests/source/issue-2025.rs | 8 + rustfmt-core/tests/source/issue-2111.rs | 28 + rustfmt-core/tests/source/issue-2164.rs | 4 + rustfmt-core/tests/source/issue-2179.rs | 35 + rustfmt-core/tests/source/issue-2256.rs | 12 + rustfmt-core/tests/source/issue-2342.rs | 5 + rustfmt-core/tests/source/issue-447.rs | 39 + rustfmt-core/tests/source/issue-510.rs | 37 + rustfmt-core/tests/source/issue-811.rs | 19 + rustfmt-core/tests/source/issue-850.rs | 1 + rustfmt-core/tests/source/issue-855.rs | 20 + rustfmt-core/tests/source/issue-913.rs | 22 + rustfmt-core/tests/source/issue-945.rs | 5 + rustfmt-core/tests/source/issue-977.rs | 8 + .../source/item-brace-style-always-next-line.rs | 29 + .../source/item-brace-style-prefer-same-line.rs | 29 + .../source/item-brace-style-same-line-where.rs | 31 + rustfmt-core/tests/source/large-block.rs | 5 + rustfmt-core/tests/source/large_vec.rs | 29 + .../tests/source/long-match-arms-brace-newline.rs | 15 + rustfmt-core/tests/source/long_field_access.rs | 3 + rustfmt-core/tests/source/loop.rs | 29 + rustfmt-core/tests/source/macro_not_expr.rs | 7 + rustfmt-core/tests/source/macro_rules.rs | 51 + rustfmt-core/tests/source/macros.rs | 338 +++ .../tests/source/match-block-trailing-comma.rs | 14 + .../tests/source/match-nowrap-trailing-comma.rs | 15 + rustfmt-core/tests/source/match-nowrap.rs | 12 + rustfmt-core/tests/source/match.rs | 453 +++ .../tests/source/max-line-length-in-chars.rs | 4 + rustfmt-core/tests/source/mod-1.rs | 29 + rustfmt-core/tests/source/mod-2.rs | 4 + rustfmt-core/tests/source/mod_skip_child.rs | 2 + rustfmt-core/tests/source/multiple.rs | 134 + rustfmt-core/tests/source/nested-if-else.rs | 11 + rustfmt-core/tests/source/nested_skipped/mod.rs | 3 + rustfmt-core/tests/source/nestedmod/mod.rs | 13 + rustfmt-core/tests/source/nestedmod/mod2a.rs | 4 + rustfmt-core/tests/source/nestedmod/mod2b.rs | 3 + rustfmt-core/tests/source/nestedmod/mod2c.rs | 3 + .../tests/source/nestedmod/mymod1/mod3a.rs | 2 + rustfmt-core/tests/source/nestedmod/submod2/a.rs | 6 + rustfmt-core/tests/source/nestedmod/submod2/mod.rs | 5 + rustfmt-core/tests/source/no_new_line_beginning.rs | 2 + rustfmt-core/tests/source/other.rs | 5 + rustfmt-core/tests/source/paths.rs | 25 + .../tests/source/pattern-condense-wildcards.rs | 12 + rustfmt-core/tests/source/pattern.rs | 65 + rustfmt-core/tests/source/pub-restricted.rs | 64 + rustfmt-core/tests/source/remove_blank_lines.rs | 44 + rustfmt-core/tests/source/single-line-if-else.rs | 49 + rustfmt-core/tests/source/soft-wrapping.rs | 15 + .../tests/source/space-not-before-newline.rs | 8 + rustfmt-core/tests/source/spaces-around-ranges.rs | 15 + rustfmt-core/tests/source/static.rs | 23 + rustfmt-core/tests/source/string-lit-2.rs | 25 + rustfmt-core/tests/source/string-lit.rs | 62 + rustfmt-core/tests/source/string_punctuation.rs | 8 + .../tests/source/struct-field-attributes.rs | 52 + rustfmt-core/tests/source/struct_lits.rs | 144 + rustfmt-core/tests/source/struct_lits_multiline.rs | 81 + rustfmt-core/tests/source/struct_lits_visual.rs | 47 + .../tests/source/struct_lits_visual_multiline.rs | 45 + rustfmt-core/tests/source/struct_tuple_visual.rs | 37 + rustfmt-core/tests/source/structs.rs | 283 ++ rustfmt-core/tests/source/trailing-comma-never.rs | 41 + rustfmt-core/tests/source/trailing_commas.rs | 47 + rustfmt-core/tests/source/trait.rs | 94 + rustfmt-core/tests/source/try-conversion.rs | 18 + rustfmt-core/tests/source/tuple.rs | 52 + rustfmt-core/tests/source/type-ascription.rs | 9 + rustfmt-core/tests/source/type-punctuation.rs | 32 + rustfmt-core/tests/source/type.rs | 25 + rustfmt-core/tests/source/type_alias.rs | 34 + rustfmt-core/tests/source/unions.rs | 195 ++ rustfmt-core/tests/source/where-clause-rfc.rs | 58 + rustfmt-core/tests/source/where-clause.rs | 16 + rustfmt-core/tests/target/assignment.rs | 36 + rustfmt-core/tests/target/associated-items.rs | 3 + .../target/associated-types-bounds-wrapping.rs | 7 + .../tests/target/associated_type_defaults.rs | 4 + rustfmt-core/tests/target/attrib-extern-crate.rs | 17 + rustfmt-core/tests/target/attrib.rs | 154 + rustfmt-core/tests/target/big-impl-rfc.rs | 87 + rustfmt-core/tests/target/big-impl.rs | 75 + rustfmt-core/tests/target/break-and-continue.rs | 23 + rustfmt-core/tests/target/catch.rs | 21 + rustfmt-core/tests/target/chains-indent-tabbed.rs | 10 + rustfmt-core/tests/target/chains-indent-visual.rs | 9 + rustfmt-core/tests/target/chains-visual.rs | 159 ++ rustfmt-core/tests/target/chains.rs | 261 ++ .../tests/target/closure-block-inside-macro.rs | 11 + rustfmt-core/tests/target/closure.rs | 248 ++ rustfmt-core/tests/target/comment-inside-const.rs | 9 + rustfmt-core/tests/target/comment-not-disappear.rs | 36 + rustfmt-core/tests/target/comment.rs | 95 + rustfmt-core/tests/target/comment2.rs | 5 + rustfmt-core/tests/target/comment3.rs | 6 + rustfmt-core/tests/target/comment4.rs | 51 + rustfmt-core/tests/target/comment5.rs | 16 + rustfmt-core/tests/target/comment_crlf_newline.rs | 4 + rustfmt-core/tests/target/comments-fn.rs | 39 + .../target/configs/blank_lines_lower_bound/1.rs | 16 + .../configs/brace_style/fn_always_next_line.rs | 19 + .../configs/brace_style/fn_prefer_same_line.rs | 16 + .../configs/brace_style/fn_same_line_where.rs | 17 + .../configs/brace_style/item_always_next_line.rs | 27 + .../configs/brace_style/item_prefer_same_line.rs | 18 + .../configs/brace_style/item_same_line_where.rs | 19 + .../target/configs/combine_control_expr/false.rs | 133 + .../target/configs/combine_control_expr/true.rs | 121 + .../tests/target/configs/comment_width/above.rs | 8 + .../tests/target/configs/comment_width/below.rs | 7 + .../tests/target/configs/comment_width/ignore.rs | 7 + .../configs/condense_wildcard_suffixes/false.rs | 6 + .../configs/condense_wildcard_suffixes/true.rs | 6 + .../control_brace_style/always_next_line.rs | 18 + .../control_brace_style/always_same_line.rs | 14 + .../control_brace_style/closing_next_line.rs | 15 + .../target/configs/disable_all_formatting/false.rs | 10 + .../target/configs/disable_all_formatting/true.rs | 6 + .../target/configs/empty_item_single_line/false.rs | 15 + .../target/configs/empty_item_single_line/true.rs | 10 + .../target/configs/error_on_line_overflow/false.rs | 6 + .../target/configs/error_on_unformatted/false.rs | 12 + .../target/configs/fn_args_density/compressed.rs | 22 + .../tests/target/configs/fn_args_density/tall.rs | 32 + .../target/configs/fn_args_density/vertical.rs | 42 + .../tests/target/configs/fn_single_line/false.rs | 11 + .../tests/target/configs/fn_single_line/true.rs | 9 + .../target/configs/force_explicit_abi/false.rs | 6 + .../target/configs/force_explicit_abi/true.rs | 6 + .../target/configs/force_multiline_block/false.rs | 20 + .../target/configs/force_multiline_block/true.rs | 22 + .../tests/target/configs/format_strings/false.rs | 8 + .../tests/target/configs/format_strings/true.rs | 9 + .../tests/target/configs/hard_tabs/false.rs | 6 + .../tests/target/configs/hard_tabs/true.rs | 6 + .../tests/target/configs/imports_indent/block.rs | 7 + .../configs/imports_layout/horizontal_vertical.rs | 18 + .../tests/target/configs/imports_layout/mixed.rs | 9 + .../target/configs/indent_style/block_args.rs | 47 + .../target/configs/indent_style/block_array.rs | 14 + .../target/configs/indent_style/block_call.rs | 149 + .../target/configs/indent_style/block_chain.rs | 12 + .../target/configs/indent_style/block_generic.rs | 22 + .../configs/indent_style/block_struct_lit.rs | 9 + .../configs/indent_style/block_tab_spaces_call.rs | 14 + .../indent_style/block_trailing_comma_call.rs | 11 + .../configs/indent_style/block_where_pred.rs | 12 + .../tests/target/configs/indent_style/default.rs | 11 + .../target/configs/indent_style/rfc_control.rs | 39 + .../tests/target/configs/indent_style/rfc_where.rs | 12 + .../target/configs/indent_style/visual_args.rs | 40 + .../target/configs/indent_style/visual_array.rs | 12 + .../target/configs/indent_style/visual_call.rs | 13 + .../target/configs/indent_style/visual_chain.rs | 11 + .../target/configs/indent_style/visual_generics.rs | 20 + .../configs/indent_style/visual_struct_lit.rs | 7 + .../configs/indent_style/visual_trailing_comma.rs | 7 + .../configs/indent_style/visual_where_pred.rs | 11 + .../tests/target/configs/match_arm_blocks/false.rs | 10 + .../tests/target/configs/match_arm_blocks/true.rs | 11 + .../configs/match_block_trailing_comma/false.rs | 11 + .../configs/match_block_trailing_comma/true.rs | 11 + .../tests/target/configs/merge_derives/true.rs | 40 + .../target/configs/normalize_comments/false.rs | 13 + .../target/configs/normalize_comments/true.rs | 13 + .../target/configs/reorder_extern_crates/false.rs | 11 + .../target/configs/reorder_extern_crates/true.rs | 11 + .../target/configs/reorder_imported_names/false.rs | 4 + .../target/configs/reorder_imported_names/true.rs | 4 + .../tests/target/configs/reorder_imports/false.rs | 7 + .../tests/target/configs/reorder_imports/true.rs | 19 + .../configs/reorder_imports_in_group/false.rs | 12 + .../configs/reorder_imports_in_group/true.rs | 13 + .../target/configs/reorder_modules/dolor/mod.rs | 1 + .../tests/target/configs/reorder_modules/false.rs | 7 + .../target/configs/reorder_modules/ipsum/mod.rs | 1 + .../target/configs/reorder_modules/lorem/mod.rs | 1 + .../target/configs/reorder_modules/sit/mod.rs | 1 + .../tests/target/configs/reorder_modules/true.rs | 7 + .../target/configs/space_before_colon/true.rs | 11 + .../target/configs/spaces_around_ranges/false.rs | 22 + .../target/configs/spaces_around_ranges/true.rs | 22 + .../spaces_within_parens_and_brackets/false.rs | 7 + .../spaces_within_parens_and_brackets/true.rs | 145 + .../configs/struct_field_align_threshold/20.rs | 467 ++++ .../target/configs/struct_lit_single_line/false.rs | 9 + rustfmt-core/tests/target/configs/tab_spaces/2.rs | 14 + rustfmt-core/tests/target/configs/tab_spaces/4.rs | 14 + .../tests/target/configs/trailing_comma/always.rs | 14 + .../tests/target/configs/trailing_comma/never.rs | 35 + .../target/configs/trailing_comma/vertical.rs | 14 + .../target/configs/trailing_semicolon/false.rs | 27 + .../target/configs/trailing_semicolon/true.rs | 27 + .../configs/type_punctuation_density/compressed.rs | 6 + .../configs/type_punctuation_density/wide.rs | 6 + .../configs/use_field_init_shorthand/false.rs | 15 + .../configs/use_field_init_shorthand/true.rs | 15 + .../target/configs/use_try_shorthand/false.rs | 6 + .../tests/target/configs/use_try_shorthand/true.rs | 6 + .../tests/target/configs/where_single_line/true.rs | 28 + .../tests/target/configs/wrap_comments/false.rs | 8 + .../tests/target/configs/wrap_comments/true.rs | 20 + .../target/control-brace-style-always-next-line.rs | 50 + .../target/control-brace-style-always-same-line.rs | 42 + rustfmt-core/tests/target/doc.rs | 4 + .../target/else-if-brace-style-always-next-line.rs | 53 + .../target/else-if-brace-style-always-same-line.rs | 45 + .../else-if-brace-style-closing-next-line.rs | 49 + .../empty-tuple-no-conversion-to-unit-struct.rs | 12 + rustfmt-core/tests/target/empty_file.rs | 1 + rustfmt-core/tests/target/enum.rs | 255 ++ rustfmt-core/tests/target/expr-block.rs | 299 ++ rustfmt-core/tests/target/expr.rs | 397 +++ rustfmt-core/tests/target/extern.rs | 73 + rustfmt-core/tests/target/extern_not_explicit.rs | 18 + rustfmt-core/tests/target/file-lines-1.rs | 29 + rustfmt-core/tests/target/file-lines-2.rs | 24 + rustfmt-core/tests/target/file-lines-3.rs | 25 + rustfmt-core/tests/target/file-lines-4.rs | 30 + rustfmt-core/tests/target/file-lines-5.rs | 17 + rustfmt-core/tests/target/file-lines-6.rs | 18 + rustfmt-core/tests/target/file-lines-item.rs | 22 + .../tests/target/fn-args-with-last-line-comment.rs | 24 + rustfmt-core/tests/target/fn-custom-2.rs | 78 + rustfmt-core/tests/target/fn-custom-3.rs | 72 + rustfmt-core/tests/target/fn-custom-4.rs | 27 + rustfmt-core/tests/target/fn-custom-6.rs | 72 + rustfmt-core/tests/target/fn-custom-7.rs | 41 + rustfmt-core/tests/target/fn-custom-8.rs | 78 + rustfmt-core/tests/target/fn-custom.rs | 19 + rustfmt-core/tests/target/fn-simple.rs | 107 + rustfmt-core/tests/target/fn-single-line.rs | 70 + rustfmt-core/tests/target/fn-ty.rs | 14 + rustfmt-core/tests/target/fn.rs | 122 + .../tests/target/fn_args_density-vertical.rs | 39 + rustfmt-core/tests/target/fn_args_indent-block.rs | 144 + rustfmt-core/tests/target/fn_once.rs | 8 + rustfmt-core/tests/target/hard-tabs.rs | 99 + rustfmt-core/tests/target/hello.rs | 8 + rustfmt-core/tests/target/immovable_generators.rs | 7 + rustfmt-core/tests/target/impl.rs | 43 + rustfmt-core/tests/target/impls.rs | 219 ++ .../tests/target/import-fencepost-length.rs | 4 + .../target/imports-reorder-lines-and-items.rs | 10 + rustfmt-core/tests/target/imports-reorder-lines.rs | 33 + rustfmt-core/tests/target/imports-reorder.rs | 6 + rustfmt-core/tests/target/imports.rs | 88 + rustfmt-core/tests/target/indented-impl.rs | 13 + rustfmt-core/tests/target/issue-1021.rs | 22 + rustfmt-core/tests/target/issue-1049.rs | 29 + rustfmt-core/tests/target/issue-1055.rs | 3 + rustfmt-core/tests/target/issue-1111.rs | 1 + rustfmt-core/tests/target/issue-1113.rs | 33 + rustfmt-core/tests/target/issue-1120.rs | 11 + rustfmt-core/tests/target/issue-1124.rs | 20 + rustfmt-core/tests/target/issue-1127.rs | 25 + rustfmt-core/tests/target/issue-1158.rs | 3 + rustfmt-core/tests/target/issue-1177.rs | 7 + rustfmt-core/tests/target/issue-1192.rs | 3 + rustfmt-core/tests/target/issue-1211.rs | 13 + rustfmt-core/tests/target/issue-1214.rs | 8 + rustfmt-core/tests/target/issue-1216.rs | 5 + rustfmt-core/tests/target/issue-1239.rs | 10 + rustfmt-core/tests/target/issue-1247.rs | 8 + rustfmt-core/tests/target/issue-1255.rs | 10 + rustfmt-core/tests/target/issue-1278.rs | 9 + rustfmt-core/tests/target/issue-1350.rs | 14 + rustfmt-core/tests/target/issue-1366.rs | 13 + rustfmt-core/tests/target/issue-1397.rs | 25 + rustfmt-core/tests/target/issue-1468.rs | 29 + rustfmt-core/tests/target/issue-1598.rs | 6 + rustfmt-core/tests/target/issue-1624.rs | 6 + rustfmt-core/tests/target/issue-1681.rs | 20 + rustfmt-core/tests/target/issue-1693.rs | 10 + rustfmt-core/tests/target/issue-1703.rs | 9 + rustfmt-core/tests/target/issue-1800.rs | 3 + rustfmt-core/tests/target/issue-1802.rs | 10 + rustfmt-core/tests/target/issue-1824.rs | 5 + rustfmt-core/tests/target/issue-1914.rs | 7 + rustfmt-core/tests/target/issue-2025.rs | 4 + rustfmt-core/tests/target/issue-2103.rs | 14 + rustfmt-core/tests/target/issue-2111.rs | 26 + rustfmt-core/tests/target/issue-2123.rs | 6 + rustfmt-core/tests/target/issue-2164.rs | 132 + rustfmt-core/tests/target/issue-2179.rs | 36 + rustfmt-core/tests/target/issue-2197.rs | 18 + rustfmt-core/tests/target/issue-2256.rs | 7 + rustfmt-core/tests/target/issue-2324.rs | 7 + rustfmt-core/tests/target/issue-2329.rs | 30 + rustfmt-core/tests/target/issue-2342.rs | 6 + rustfmt-core/tests/target/issue-2401.rs | 7 + rustfmt-core/tests/target/issue-447.rs | 40 + rustfmt-core/tests/target/issue-510.rs | 41 + rustfmt-core/tests/target/issue-64.rs | 7 + rustfmt-core/tests/target/issue-691.rs | 9 + rustfmt-core/tests/target/issue-770.rs | 10 + rustfmt-core/tests/target/issue-811.rs | 19 + rustfmt-core/tests/target/issue-831.rs | 9 + rustfmt-core/tests/target/issue-850.rs | 1 + rustfmt-core/tests/target/issue-855.rs | 27 + rustfmt-core/tests/target/issue-913.rs | 24 + rustfmt-core/tests/target/issue-945.rs | 17 + rustfmt-core/tests/target/issue-977.rs | 16 + .../target/item-brace-style-always-next-line.rs | 42 + .../target/item-brace-style-prefer-same-line.rs | 35 + .../target/item-brace-style-same-line-where.rs | 39 + rustfmt-core/tests/target/large-block.rs | 5 + rustfmt-core/tests/target/large_vec.rs | 42 + rustfmt-core/tests/target/long-fn-1.rs | 21 + .../tests/target/long-match-arms-brace-newline.rs | 15 + rustfmt-core/tests/target/long_field_access.rs | 4 + rustfmt-core/tests/target/loop.rs | 34 + rustfmt-core/tests/target/macro_not_expr.rs | 7 + rustfmt-core/tests/target/macro_rules.rs | 43 + rustfmt-core/tests/target/macros.rs | 913 ++++++ .../tests/target/match-block-trailing-comma.rs | 16 + .../tests/target/match-nowrap-trailing-comma.rs | 17 + rustfmt-core/tests/target/match-nowrap.rs | 13 + rustfmt-core/tests/target/match.rs | 485 ++++ .../tests/target/max-line-length-in-chars.rs | 4 + rustfmt-core/tests/target/mod-1.rs | 38 + rustfmt-core/tests/target/mod-2.rs | 5 + rustfmt-core/tests/target/mod_skip_child.rs | 2 + rustfmt-core/tests/target/mulit-file.rs | 10 + rustfmt-core/tests/target/multiple.rs | 178 ++ rustfmt-core/tests/target/nested-if-else.rs | 11 + rustfmt-core/tests/target/nested-visual-block.rs | 59 + rustfmt-core/tests/target/nested_skipped/mod.rs | 3 + rustfmt-core/tests/target/nestedmod/mod.rs | 12 + rustfmt-core/tests/target/nestedmod/mod2a.rs | 4 + rustfmt-core/tests/target/nestedmod/mod2b.rs | 2 + rustfmt-core/tests/target/nestedmod/mod2c.rs | 3 + .../tests/target/nestedmod/mymod1/mod3a.rs | 2 + rustfmt-core/tests/target/nestedmod/submod2/a.rs | 6 + rustfmt-core/tests/target/nestedmod/submod2/mod.rs | 5 + rustfmt-core/tests/target/no_new_line_beginning.rs | 1 + rustfmt-core/tests/target/other.rs | 5 + rustfmt-core/tests/target/paths.rs | 28 + .../tests/target/pattern-condense-wildcards.rs | 12 + rustfmt-core/tests/target/pattern.rs | 77 + rustfmt-core/tests/target/pub-restricted.rs | 64 + rustfmt-core/tests/target/remove_blank_lines.rs | 28 + rustfmt-core/tests/target/single-line-if-else.rs | 58 + rustfmt-core/tests/target/skip.rs | 87 + rustfmt-core/tests/target/skip_mod.rs | 3 + rustfmt-core/tests/target/soft-wrapping.rs | 15 + .../tests/target/space-not-before-newline.rs | 8 + rustfmt-core/tests/target/spaces-around-ranges.rs | 15 + rustfmt-core/tests/target/static.rs | 27 + rustfmt-core/tests/target/string-lit-2.rs | 25 + rustfmt-core/tests/target/string-lit-custom.rs | 22 + rustfmt-core/tests/target/string-lit.rs | 64 + rustfmt-core/tests/target/string_punctuation.rs | 15 + .../tests/target/struct-field-attributes.rs | 56 + rustfmt-core/tests/target/struct_lits.rs | 191 ++ rustfmt-core/tests/target/struct_lits_multiline.rs | 117 + rustfmt-core/tests/target/struct_lits_visual.rs | 50 + .../tests/target/struct_lits_visual_multiline.rs | 50 + rustfmt-core/tests/target/struct_tuple_visual.rs | 37 + rustfmt-core/tests/target/structs.rs | 332 +++ rustfmt-core/tests/target/trailing-comma-never.rs | 31 + rustfmt-core/tests/target/trailing_commas.rs | 103 + rustfmt-core/tests/target/trait.rs | 132 + rustfmt-core/tests/target/try-conversion.rs | 27 + rustfmt-core/tests/target/tuple.rs | 89 + rustfmt-core/tests/target/type-ascription.rs | 12 + rustfmt-core/tests/target/type-punctuation.rs | 36 + rustfmt-core/tests/target/type.rs | 31 + rustfmt-core/tests/target/type_alias.rs | 76 + .../tests/target/unindent_if_else_cond_comment.rs | 27 + rustfmt-core/tests/target/unions.rs | 196 ++ rustfmt-core/tests/target/where-clause-rfc.rs | 128 + rustfmt-core/tests/target/where-clause.rs | 29 + .../tests/writemode/source/fn-single-line.rs | 80 + rustfmt-core/tests/writemode/target/checkstyle.xml | 2 + src/chains.rs | 499 ---- src/checkstyle.rs | 85 - src/closures.rs | 392 --- src/codemap.rs | 100 - src/comment.rs | 1234 --------- src/expr.rs | 2930 -------------------- src/filemap.rs | 179 -- src/imports.rs | 600 ---- src/issues.rs | 325 --- src/items.rs | 2845 ------------------- src/lib.rs | 828 ------ src/lists.rs | 857 ------ src/macros.rs | 871 ------ src/missed_spans.rs | 312 --- src/modules.rs | 86 - src/patterns.rs | 379 --- src/rewrite.rs | 54 - src/rustfmt_diff.rs | 247 -- src/shape.rs | 353 --- src/spanned.rs | 187 -- src/string.rs | 163 -- src/types.rs | 820 ------ src/utils.rs | 480 ---- src/vertical.rs | 290 -- src/visitor.rs | 1113 -------- tests/config/disable_all_formatting.toml | 1 - tests/config/issue-1111.toml | 1 - tests/config/small_tabs.toml | 12 - tests/coverage/source/comments.rs | 7 - tests/coverage/target/comments.rs | 7 - tests/source/assignment.rs | 30 - tests/source/associated-types-bounds-wrapping.rs | 6 - tests/source/attrib.rs | 152 - tests/source/big-impl-rfc.rs | 125 - tests/source/big-impl.rs | 104 - tests/source/break-and-continue.rs | 23 - tests/source/catch.rs | 27 - tests/source/chains-indent-tabbed.rs | 5 - tests/source/chains-indent-visual.rs | 5 - tests/source/chains-visual.rs | 159 -- tests/source/chains.rs | 231 -- tests/source/closure-block-inside-macro.rs | 11 - tests/source/closure.rs | 213 -- tests/source/comment.rs | 90 - tests/source/comment2.rs | 4 - tests/source/comment3.rs | 5 - tests/source/comment4.rs | 52 - tests/source/comment5.rs | 14 - tests/source/comment_crlf_newline.rs | 4 - tests/source/configs/blank_lines_lower_bound/1.rs | 13 - .../configs/brace_style/fn_always_next_line.rs | 14 - .../configs/brace_style/fn_prefer_same_line.rs | 14 - .../configs/brace_style/fn_same_line_where.rs | 14 - .../configs/brace_style/item_always_next_line.rs | 20 - .../configs/brace_style/item_prefer_same_line.rs | 16 - .../configs/brace_style/item_same_line_where.rs | 16 - tests/source/configs/comment_width/above.rs | 7 - tests/source/configs/comment_width/below.rs | 7 - tests/source/configs/comment_width/ignore.rs | 7 - .../configs/condense_wildcard_suffixes/false.rs | 6 - .../configs/condense_wildcard_suffixes/true.rs | 6 - .../control_brace_style/always_next_line.rs | 10 - .../control_brace_style/always_same_line.rs | 10 - .../control_brace_style/closing_next_line.rs | 10 - .../source/configs/disable_all_formatting/false.rs | 6 - .../source/configs/disable_all_formatting/true.rs | 6 - .../source/configs/empty_item_single_line/false.rs | 17 - .../source/configs/empty_item_single_line/true.rs | 17 - .../source/configs/error_on_line_overflow/false.rs | 6 - tests/source/configs/fn_args_density/compressed.rs | 16 - tests/source/configs/fn_args_density/tall.rs | 16 - tests/source/configs/fn_args_density/vertical.rs | 16 - tests/source/configs/fn_single_line/false.rs | 11 - tests/source/configs/fn_single_line/true.rs | 11 - tests/source/configs/force_explicit_abi/false.rs | 6 - tests/source/configs/force_explicit_abi/true.rs | 6 - .../source/configs/force_multiline_block/false.rs | 22 - tests/source/configs/force_multiline_block/true.rs | 18 - tests/source/configs/format_strings/false.rs | 8 - tests/source/configs/format_strings/true.rs | 7 - tests/source/configs/hard_tabs/false.rs | 6 - tests/source/configs/hard_tabs/true.rs | 6 - tests/source/configs/indent_style/block_args.rs | 26 - tests/source/configs/indent_style/block_array.rs | 6 - tests/source/configs/indent_style/block_call.rs | 133 - tests/source/configs/indent_style/block_chain.rs | 6 - tests/source/configs/indent_style/block_generic.rs | 6 - .../configs/indent_style/block_struct_lit.rs | 6 - .../indent_style/block_trailing_comma_call.rs | 8 - .../configs/indent_style/block_where_pred.rs | 6 - tests/source/configs/indent_style/default.rs | 6 - tests/source/configs/indent_style/rfc_where.rs | 6 - tests/source/configs/indent_style/visual_args.rs | 32 - tests/source/configs/indent_style/visual_array.rs | 6 - tests/source/configs/indent_style/visual_call.rs | 6 - tests/source/configs/indent_style/visual_chain.rs | 6 - .../source/configs/indent_style/visual_generics.rs | 6 - .../configs/indent_style/visual_struct_lit.rs | 6 - .../configs/indent_style/visual_trailing_comma.rs | 7 - .../configs/indent_style/visual_where_pred.rs | 6 - tests/source/configs/match_arm_blocks/false.rs | 11 - tests/source/configs/match_arm_blocks/true.rs | 11 - .../configs/match_block_trailing_comma/false.rs | 11 - .../configs/match_block_trailing_comma/true.rs | 11 - tests/source/configs/merge_derives/true.rs | 46 - tests/source/configs/normalize_comments/false.rs | 13 - tests/source/configs/normalize_comments/true.rs | 13 - .../source/configs/reorder_extern_crates/false.rs | 11 - tests/source/configs/reorder_extern_crates/true.rs | 11 - .../source/configs/reorder_imported_names/false.rs | 4 - .../source/configs/reorder_imported_names/true.rs | 4 - tests/source/configs/reorder_imports/false.rs | 7 - tests/source/configs/reorder_imports/true.rs | 19 - .../configs/reorder_imports_in_group/false.rs | 13 - .../configs/reorder_imports_in_group/true.rs | 13 - tests/source/configs/reorder_modules/dolor/mod.rs | 1 - tests/source/configs/reorder_modules/false.rs | 7 - tests/source/configs/reorder_modules/ipsum/mod.rs | 1 - tests/source/configs/reorder_modules/lorem/mod.rs | 1 - tests/source/configs/reorder_modules/sit/mod.rs | 1 - tests/source/configs/reorder_modules/true.rs | 7 - tests/source/configs/space_before_colon/true.rs | 11 - tests/source/configs/spaces_around_ranges/false.rs | 22 - tests/source/configs/spaces_around_ranges/true.rs | 22 - .../spaces_within_parens_and_brackets/false.rs | 7 - .../spaces_within_parens_and_brackets/true.rs | 133 - .../configs/struct_field_align_threshold/20.rs | 383 --- .../source/configs/struct_lit_single_line/false.rs | 6 - tests/source/configs/tab_spaces/2.rs | 11 - tests/source/configs/tab_spaces/4.rs | 11 - tests/source/configs/trailing_comma/always.rs | 7 - tests/source/configs/trailing_comma/never.rs | 23 - tests/source/configs/trailing_comma/vertical.rs | 7 - .../configs/type_punctuation_density/compressed.rs | 6 - .../configs/type_punctuation_density/wide.rs | 6 - .../configs/use_field_init_shorthand/false.rs | 19 - .../configs/use_field_init_shorthand/true.rs | 19 - tests/source/configs/use_try_shorthand/false.rs | 6 - tests/source/configs/use_try_shorthand/true.rs | 6 - tests/source/configs/where_single_line/true.rs | 24 - tests/source/configs/wrap_comments/false.rs | 8 - tests/source/configs/wrap_comments/true.rs | 15 - .../source/control-brace-style-always-next-line.rs | 44 - .../source/control-brace-style-always-same-line.rs | 44 - tests/source/doc.rs | 4 - .../source/else-if-brace-style-always-next-line.rs | 54 - .../source/else-if-brace-style-always-same-line.rs | 54 - .../else-if-brace-style-closing-next-line.rs | 54 - tests/source/empty_file.rs | 0 tests/source/enum.rs | 194 -- tests/source/expr-block.rs | 286 -- tests/source/expr.rs | 372 --- tests/source/extern.rs | 60 - tests/source/extern_not_explicit.rs | 14 - tests/source/file-lines-1.rs | 29 - tests/source/file-lines-2.rs | 29 - tests/source/file-lines-3.rs | 30 - tests/source/file-lines-4.rs | 30 - tests/source/file-lines-5.rs | 17 - tests/source/file-lines-6.rs | 18 - tests/source/file-lines-item.rs | 22 - tests/source/fn-custom-2.rs | 36 - tests/source/fn-custom-3.rs | 32 - tests/source/fn-custom-4.rs | 14 - tests/source/fn-custom-6.rs | 41 - tests/source/fn-custom-7.rs | 25 - tests/source/fn-custom-8.rs | 49 - tests/source/fn-custom.rs | 13 - tests/source/fn-simple.rs | 66 - tests/source/fn-single-line.rs | 79 - tests/source/fn_args_density-vertical.rs | 33 - tests/source/fn_args_indent-block.rs | 78 - tests/source/hard-tabs.rs | 85 - tests/source/hello.rs | 6 - tests/source/hello2.rs | 8 - tests/source/immovable_generators.rs | 7 - tests/source/impls.rs | 154 - tests/source/imports-reorder-lines-and-items.rs | 10 - tests/source/imports-reorder-lines.rs | 34 - tests/source/imports-reorder.rs | 6 - tests/source/imports.rs | 89 - tests/source/issue-1021.rs | 22 - tests/source/issue-1049.rs | 18 - tests/source/issue-1111.rs | 1 - tests/source/issue-1120.rs | 9 - tests/source/issue-1124.rs | 16 - tests/source/issue-1127.rs | 23 - tests/source/issue-1158.rs | 3 - tests/source/issue-1177.rs | 7 - tests/source/issue-1192.rs | 3 - tests/source/issue-1211.rs | 15 - tests/source/issue-1216.rs | 5 - tests/source/issue-1239.rs | 9 - tests/source/issue-1278.rs | 9 - tests/source/issue-1350.rs | 16 - tests/source/issue-1366.rs | 12 - tests/source/issue-1468.rs | 27 - tests/source/issue-1693.rs | 3 - tests/source/issue-1800.rs | 3 - tests/source/issue-1914.rs | 6 - tests/source/issue-2025.rs | 8 - tests/source/issue-2111.rs | 28 - tests/source/issue-2164.rs | 4 - tests/source/issue-2179.rs | 35 - tests/source/issue-2256.rs | 12 - tests/source/issue-2342.rs | 5 - tests/source/issue-447.rs | 39 - tests/source/issue-510.rs | 37 - tests/source/issue-811.rs | 19 - tests/source/issue-850.rs | 1 - tests/source/issue-855.rs | 20 - tests/source/issue-913.rs | 22 - tests/source/issue-945.rs | 5 - tests/source/issue-977.rs | 8 - tests/source/item-brace-style-always-next-line.rs | 29 - tests/source/item-brace-style-prefer-same-line.rs | 29 - tests/source/item-brace-style-same-line-where.rs | 31 - tests/source/large-block.rs | 5 - tests/source/large_vec.rs | 29 - tests/source/long-match-arms-brace-newline.rs | 15 - tests/source/long_field_access.rs | 3 - tests/source/loop.rs | 29 - tests/source/macro_not_expr.rs | 7 - tests/source/macro_rules.rs | 51 - tests/source/macros.rs | 338 --- tests/source/match-block-trailing-comma.rs | 14 - tests/source/match-nowrap-trailing-comma.rs | 15 - tests/source/match-nowrap.rs | 12 - tests/source/match.rs | 453 --- tests/source/max-line-length-in-chars.rs | 4 - tests/source/mod-1.rs | 29 - tests/source/mod-2.rs | 4 - tests/source/mod_skip_child.rs | 2 - tests/source/multiple.rs | 134 - tests/source/nested-if-else.rs | 11 - tests/source/nested_skipped/mod.rs | 3 - tests/source/nestedmod/mod.rs | 13 - tests/source/nestedmod/mod2a.rs | 4 - tests/source/nestedmod/mod2b.rs | 3 - tests/source/nestedmod/mod2c.rs | 3 - tests/source/nestedmod/mymod1/mod3a.rs | 2 - tests/source/nestedmod/submod2/a.rs | 6 - tests/source/nestedmod/submod2/mod.rs | 5 - tests/source/no_new_line_beginning.rs | 2 - tests/source/other.rs | 5 - tests/source/paths.rs | 25 - tests/source/pattern-condense-wildcards.rs | 12 - tests/source/pattern.rs | 65 - tests/source/pub-restricted.rs | 64 - tests/source/remove_blank_lines.rs | 44 - tests/source/single-line-if-else.rs | 49 - tests/source/soft-wrapping.rs | 15 - tests/source/space-not-before-newline.rs | 8 - tests/source/spaces-around-ranges.rs | 15 - tests/source/static.rs | 23 - tests/source/string-lit-2.rs | 25 - tests/source/string-lit.rs | 62 - tests/source/string_punctuation.rs | 8 - tests/source/struct-field-attributes.rs | 52 - tests/source/struct_lits.rs | 144 - tests/source/struct_lits_multiline.rs | 81 - tests/source/struct_lits_visual.rs | 47 - tests/source/struct_lits_visual_multiline.rs | 45 - tests/source/struct_tuple_visual.rs | 37 - tests/source/structs.rs | 283 -- tests/source/trailing-comma-never.rs | 41 - tests/source/trailing_commas.rs | 47 - tests/source/trait.rs | 94 - tests/source/try-conversion.rs | 18 - tests/source/tuple.rs | 52 - tests/source/type-ascription.rs | 9 - tests/source/type-punctuation.rs | 32 - tests/source/type.rs | 25 - tests/source/type_alias.rs | 34 - tests/source/unions.rs | 195 -- tests/source/where-clause-rfc.rs | 58 - tests/source/where-clause.rs | 16 - tests/system.rs | 801 ------ tests/target/assignment.rs | 36 - tests/target/associated-items.rs | 3 - tests/target/associated-types-bounds-wrapping.rs | 7 - tests/target/associated_type_defaults.rs | 4 - tests/target/attrib-extern-crate.rs | 17 - tests/target/attrib.rs | 154 - tests/target/big-impl-rfc.rs | 87 - tests/target/big-impl.rs | 75 - tests/target/break-and-continue.rs | 23 - tests/target/catch.rs | 21 - tests/target/chains-indent-tabbed.rs | 10 - tests/target/chains-indent-visual.rs | 9 - tests/target/chains-visual.rs | 159 -- tests/target/chains.rs | 261 -- tests/target/closure-block-inside-macro.rs | 11 - tests/target/closure.rs | 248 -- tests/target/comment-inside-const.rs | 9 - tests/target/comment-not-disappear.rs | 36 - tests/target/comment.rs | 95 - tests/target/comment2.rs | 5 - tests/target/comment3.rs | 6 - tests/target/comment4.rs | 51 - tests/target/comment5.rs | 16 - tests/target/comment_crlf_newline.rs | 4 - tests/target/comments-fn.rs | 39 - tests/target/configs/blank_lines_lower_bound/1.rs | 16 - .../configs/brace_style/fn_always_next_line.rs | 19 - .../configs/brace_style/fn_prefer_same_line.rs | 16 - .../configs/brace_style/fn_same_line_where.rs | 17 - .../configs/brace_style/item_always_next_line.rs | 27 - .../configs/brace_style/item_prefer_same_line.rs | 18 - .../configs/brace_style/item_same_line_where.rs | 19 - tests/target/configs/combine_control_expr/false.rs | 133 - tests/target/configs/combine_control_expr/true.rs | 121 - tests/target/configs/comment_width/above.rs | 8 - tests/target/configs/comment_width/below.rs | 7 - tests/target/configs/comment_width/ignore.rs | 7 - .../configs/condense_wildcard_suffixes/false.rs | 6 - .../configs/condense_wildcard_suffixes/true.rs | 6 - .../control_brace_style/always_next_line.rs | 18 - .../control_brace_style/always_same_line.rs | 14 - .../control_brace_style/closing_next_line.rs | 15 - .../target/configs/disable_all_formatting/false.rs | 10 - .../target/configs/disable_all_formatting/true.rs | 6 - .../target/configs/empty_item_single_line/false.rs | 15 - .../target/configs/empty_item_single_line/true.rs | 10 - .../target/configs/error_on_line_overflow/false.rs | 6 - tests/target/configs/error_on_unformatted/false.rs | 12 - tests/target/configs/fn_args_density/compressed.rs | 22 - tests/target/configs/fn_args_density/tall.rs | 32 - tests/target/configs/fn_args_density/vertical.rs | 42 - tests/target/configs/fn_single_line/false.rs | 11 - tests/target/configs/fn_single_line/true.rs | 9 - tests/target/configs/force_explicit_abi/false.rs | 6 - tests/target/configs/force_explicit_abi/true.rs | 6 - .../target/configs/force_multiline_block/false.rs | 20 - tests/target/configs/force_multiline_block/true.rs | 22 - tests/target/configs/format_strings/false.rs | 8 - tests/target/configs/format_strings/true.rs | 9 - tests/target/configs/hard_tabs/false.rs | 6 - tests/target/configs/hard_tabs/true.rs | 6 - tests/target/configs/imports_indent/block.rs | 7 - .../configs/imports_layout/horizontal_vertical.rs | 18 - tests/target/configs/imports_layout/mixed.rs | 9 - tests/target/configs/indent_style/block_args.rs | 47 - tests/target/configs/indent_style/block_array.rs | 14 - tests/target/configs/indent_style/block_call.rs | 149 - tests/target/configs/indent_style/block_chain.rs | 12 - tests/target/configs/indent_style/block_generic.rs | 22 - .../configs/indent_style/block_struct_lit.rs | 9 - .../configs/indent_style/block_tab_spaces_call.rs | 14 - .../indent_style/block_trailing_comma_call.rs | 11 - .../configs/indent_style/block_where_pred.rs | 12 - tests/target/configs/indent_style/default.rs | 11 - tests/target/configs/indent_style/rfc_control.rs | 39 - tests/target/configs/indent_style/rfc_where.rs | 12 - tests/target/configs/indent_style/visual_args.rs | 40 - tests/target/configs/indent_style/visual_array.rs | 12 - tests/target/configs/indent_style/visual_call.rs | 13 - tests/target/configs/indent_style/visual_chain.rs | 11 - .../target/configs/indent_style/visual_generics.rs | 20 - .../configs/indent_style/visual_struct_lit.rs | 7 - .../configs/indent_style/visual_trailing_comma.rs | 7 - .../configs/indent_style/visual_where_pred.rs | 11 - tests/target/configs/match_arm_blocks/false.rs | 10 - tests/target/configs/match_arm_blocks/true.rs | 11 - .../configs/match_block_trailing_comma/false.rs | 11 - .../configs/match_block_trailing_comma/true.rs | 11 - tests/target/configs/merge_derives/true.rs | 40 - tests/target/configs/normalize_comments/false.rs | 13 - tests/target/configs/normalize_comments/true.rs | 13 - .../target/configs/reorder_extern_crates/false.rs | 11 - tests/target/configs/reorder_extern_crates/true.rs | 11 - .../target/configs/reorder_imported_names/false.rs | 4 - .../target/configs/reorder_imported_names/true.rs | 4 - tests/target/configs/reorder_imports/false.rs | 7 - tests/target/configs/reorder_imports/true.rs | 19 - .../configs/reorder_imports_in_group/false.rs | 12 - .../configs/reorder_imports_in_group/true.rs | 13 - tests/target/configs/reorder_modules/dolor/mod.rs | 1 - tests/target/configs/reorder_modules/false.rs | 7 - tests/target/configs/reorder_modules/ipsum/mod.rs | 1 - tests/target/configs/reorder_modules/lorem/mod.rs | 1 - tests/target/configs/reorder_modules/sit/mod.rs | 1 - tests/target/configs/reorder_modules/true.rs | 7 - tests/target/configs/space_before_colon/true.rs | 11 - tests/target/configs/spaces_around_ranges/false.rs | 22 - tests/target/configs/spaces_around_ranges/true.rs | 22 - .../spaces_within_parens_and_brackets/false.rs | 7 - .../spaces_within_parens_and_brackets/true.rs | 145 - .../configs/struct_field_align_threshold/20.rs | 467 ---- .../target/configs/struct_lit_single_line/false.rs | 9 - tests/target/configs/tab_spaces/2.rs | 14 - tests/target/configs/tab_spaces/4.rs | 14 - tests/target/configs/trailing_comma/always.rs | 14 - tests/target/configs/trailing_comma/never.rs | 35 - tests/target/configs/trailing_comma/vertical.rs | 14 - tests/target/configs/trailing_semicolon/false.rs | 27 - tests/target/configs/trailing_semicolon/true.rs | 27 - .../configs/type_punctuation_density/compressed.rs | 6 - .../configs/type_punctuation_density/wide.rs | 6 - .../configs/use_field_init_shorthand/false.rs | 15 - .../configs/use_field_init_shorthand/true.rs | 15 - tests/target/configs/use_try_shorthand/false.rs | 6 - tests/target/configs/use_try_shorthand/true.rs | 6 - tests/target/configs/where_single_line/true.rs | 28 - tests/target/configs/wrap_comments/false.rs | 8 - tests/target/configs/wrap_comments/true.rs | 20 - .../target/control-brace-style-always-next-line.rs | 50 - .../target/control-brace-style-always-same-line.rs | 42 - tests/target/doc.rs | 4 - .../target/else-if-brace-style-always-next-line.rs | 53 - .../target/else-if-brace-style-always-same-line.rs | 45 - .../else-if-brace-style-closing-next-line.rs | 49 - .../empty-tuple-no-conversion-to-unit-struct.rs | 12 - tests/target/empty_file.rs | 1 - tests/target/enum.rs | 255 -- tests/target/expr-block.rs | 299 -- tests/target/expr.rs | 397 --- tests/target/extern.rs | 73 - tests/target/extern_not_explicit.rs | 18 - tests/target/file-lines-1.rs | 29 - tests/target/file-lines-2.rs | 24 - tests/target/file-lines-3.rs | 25 - tests/target/file-lines-4.rs | 30 - tests/target/file-lines-5.rs | 17 - tests/target/file-lines-6.rs | 18 - tests/target/file-lines-item.rs | 22 - tests/target/fn-args-with-last-line-comment.rs | 24 - tests/target/fn-custom-2.rs | 78 - tests/target/fn-custom-3.rs | 72 - tests/target/fn-custom-4.rs | 27 - tests/target/fn-custom-6.rs | 72 - tests/target/fn-custom-7.rs | 41 - tests/target/fn-custom-8.rs | 78 - tests/target/fn-custom.rs | 19 - tests/target/fn-simple.rs | 107 - tests/target/fn-single-line.rs | 70 - tests/target/fn-ty.rs | 14 - tests/target/fn.rs | 122 - tests/target/fn_args_density-vertical.rs | 39 - tests/target/fn_args_indent-block.rs | 144 - tests/target/fn_once.rs | 8 - tests/target/hard-tabs.rs | 99 - tests/target/hello.rs | 8 - tests/target/immovable_generators.rs | 7 - tests/target/impl.rs | 43 - tests/target/impls.rs | 219 -- tests/target/import-fencepost-length.rs | 4 - tests/target/imports-reorder-lines-and-items.rs | 10 - tests/target/imports-reorder-lines.rs | 33 - tests/target/imports-reorder.rs | 6 - tests/target/imports.rs | 88 - tests/target/indented-impl.rs | 13 - tests/target/issue-1021.rs | 22 - tests/target/issue-1049.rs | 29 - tests/target/issue-1055.rs | 3 - tests/target/issue-1111.rs | 1 - tests/target/issue-1113.rs | 33 - tests/target/issue-1120.rs | 11 - tests/target/issue-1124.rs | 20 - tests/target/issue-1127.rs | 25 - tests/target/issue-1158.rs | 3 - tests/target/issue-1177.rs | 7 - tests/target/issue-1192.rs | 3 - tests/target/issue-1211.rs | 13 - tests/target/issue-1214.rs | 8 - tests/target/issue-1216.rs | 5 - tests/target/issue-1239.rs | 10 - tests/target/issue-1247.rs | 8 - tests/target/issue-1255.rs | 10 - tests/target/issue-1278.rs | 9 - tests/target/issue-1350.rs | 14 - tests/target/issue-1366.rs | 13 - tests/target/issue-1397.rs | 25 - tests/target/issue-1468.rs | 29 - tests/target/issue-1598.rs | 6 - tests/target/issue-1624.rs | 6 - tests/target/issue-1681.rs | 20 - tests/target/issue-1693.rs | 10 - tests/target/issue-1703.rs | 9 - tests/target/issue-1800.rs | 3 - tests/target/issue-1802.rs | 10 - tests/target/issue-1824.rs | 5 - tests/target/issue-1914.rs | 7 - tests/target/issue-2025.rs | 4 - tests/target/issue-2103.rs | 14 - tests/target/issue-2111.rs | 26 - tests/target/issue-2123.rs | 6 - tests/target/issue-2164.rs | 132 - tests/target/issue-2179.rs | 36 - tests/target/issue-2197.rs | 18 - tests/target/issue-2256.rs | 7 - tests/target/issue-2324.rs | 7 - tests/target/issue-2329.rs | 30 - tests/target/issue-2342.rs | 6 - tests/target/issue-2401.rs | 7 - tests/target/issue-447.rs | 40 - tests/target/issue-510.rs | 41 - tests/target/issue-64.rs | 7 - tests/target/issue-691.rs | 9 - tests/target/issue-770.rs | 10 - tests/target/issue-811.rs | 19 - tests/target/issue-831.rs | 9 - tests/target/issue-850.rs | 1 - tests/target/issue-855.rs | 27 - tests/target/issue-913.rs | 24 - tests/target/issue-945.rs | 17 - tests/target/issue-977.rs | 16 - tests/target/item-brace-style-always-next-line.rs | 42 - tests/target/item-brace-style-prefer-same-line.rs | 35 - tests/target/item-brace-style-same-line-where.rs | 39 - tests/target/large-block.rs | 5 - tests/target/large_vec.rs | 42 - tests/target/long-fn-1.rs | 21 - tests/target/long-match-arms-brace-newline.rs | 15 - tests/target/long_field_access.rs | 4 - tests/target/loop.rs | 34 - tests/target/macro_not_expr.rs | 7 - tests/target/macro_rules.rs | 43 - tests/target/macros.rs | 913 ------ tests/target/match-block-trailing-comma.rs | 16 - tests/target/match-nowrap-trailing-comma.rs | 17 - tests/target/match-nowrap.rs | 13 - tests/target/match.rs | 485 ---- tests/target/max-line-length-in-chars.rs | 4 - tests/target/mod-1.rs | 38 - tests/target/mod-2.rs | 5 - tests/target/mod_skip_child.rs | 2 - tests/target/mulit-file.rs | 10 - tests/target/multiple.rs | 178 -- tests/target/nested-if-else.rs | 11 - tests/target/nested-visual-block.rs | 59 - tests/target/nested_skipped/mod.rs | 3 - tests/target/nestedmod/mod.rs | 12 - tests/target/nestedmod/mod2a.rs | 4 - tests/target/nestedmod/mod2b.rs | 2 - tests/target/nestedmod/mod2c.rs | 3 - tests/target/nestedmod/mymod1/mod3a.rs | 2 - tests/target/nestedmod/submod2/a.rs | 6 - tests/target/nestedmod/submod2/mod.rs | 5 - tests/target/no_new_line_beginning.rs | 1 - tests/target/other.rs | 5 - tests/target/paths.rs | 28 - tests/target/pattern-condense-wildcards.rs | 12 - tests/target/pattern.rs | 77 - tests/target/pub-restricted.rs | 64 - tests/target/remove_blank_lines.rs | 28 - tests/target/single-line-if-else.rs | 58 - tests/target/skip.rs | 87 - tests/target/skip_mod.rs | 3 - tests/target/soft-wrapping.rs | 15 - tests/target/space-not-before-newline.rs | 8 - tests/target/spaces-around-ranges.rs | 15 - tests/target/static.rs | 27 - tests/target/string-lit-2.rs | 25 - tests/target/string-lit-custom.rs | 22 - tests/target/string-lit.rs | 64 - tests/target/string_punctuation.rs | 15 - tests/target/struct-field-attributes.rs | 56 - tests/target/struct_lits.rs | 191 -- tests/target/struct_lits_multiline.rs | 117 - tests/target/struct_lits_visual.rs | 50 - tests/target/struct_lits_visual_multiline.rs | 50 - tests/target/struct_tuple_visual.rs | 37 - tests/target/structs.rs | 332 --- tests/target/trailing-comma-never.rs | 31 - tests/target/trailing_commas.rs | 103 - tests/target/trait.rs | 132 - tests/target/try-conversion.rs | 27 - tests/target/tuple.rs | 89 - tests/target/type-ascription.rs | 12 - tests/target/type-punctuation.rs | 36 - tests/target/type.rs | 31 - tests/target/type_alias.rs | 76 - tests/target/unindent_if_else_cond_comment.rs | 27 - tests/target/unions.rs | 196 -- tests/target/where-clause-rfc.rs | 128 - tests/target/where-clause.rs | 29 - tests/writemode/source/fn-single-line.rs | 80 - tests/writemode/target/checkstyle.xml | 2 - 1159 files changed, 37516 insertions(+), 37649 deletions(-) create mode 100644 rustfmt-core/Cargo.toml create mode 100644 rustfmt-core/src/chains.rs create mode 100644 rustfmt-core/src/checkstyle.rs create mode 100644 rustfmt-core/src/closures.rs create mode 100644 rustfmt-core/src/codemap.rs create mode 100644 rustfmt-core/src/comment.rs create mode 100644 rustfmt-core/src/expr.rs create mode 100644 rustfmt-core/src/filemap.rs create mode 100644 rustfmt-core/src/imports.rs create mode 100644 rustfmt-core/src/issues.rs create mode 100644 rustfmt-core/src/items.rs create mode 100644 rustfmt-core/src/lib.rs create mode 100644 rustfmt-core/src/lists.rs create mode 100644 rustfmt-core/src/macros.rs create mode 100644 rustfmt-core/src/missed_spans.rs create mode 100644 rustfmt-core/src/modules.rs create mode 100644 rustfmt-core/src/patterns.rs create mode 100644 rustfmt-core/src/rewrite.rs create mode 100644 rustfmt-core/src/rustfmt_diff.rs create mode 100644 rustfmt-core/src/shape.rs create mode 100644 rustfmt-core/src/spanned.rs create mode 100644 rustfmt-core/src/string.rs create mode 100644 rustfmt-core/src/types.rs create mode 100644 rustfmt-core/src/utils.rs create mode 100644 rustfmt-core/src/vertical.rs create mode 100644 rustfmt-core/src/visitor.rs create mode 100644 rustfmt-core/tests/config/disable_all_formatting.toml create mode 100755 rustfmt-core/tests/config/issue-1111.toml create mode 100644 rustfmt-core/tests/config/small_tabs.toml create mode 100644 rustfmt-core/tests/coverage/source/comments.rs create mode 100644 rustfmt-core/tests/coverage/target/comments.rs create mode 100644 rustfmt-core/tests/lib.rs create mode 100644 rustfmt-core/tests/source/assignment.rs create mode 100644 rustfmt-core/tests/source/associated-types-bounds-wrapping.rs create mode 100644 rustfmt-core/tests/source/attrib.rs create mode 100644 rustfmt-core/tests/source/big-impl-rfc.rs create mode 100644 rustfmt-core/tests/source/big-impl.rs create mode 100644 rustfmt-core/tests/source/break-and-continue.rs create mode 100644 rustfmt-core/tests/source/catch.rs create mode 100644 rustfmt-core/tests/source/chains-indent-tabbed.rs create mode 100644 rustfmt-core/tests/source/chains-indent-visual.rs create mode 100644 rustfmt-core/tests/source/chains-visual.rs create mode 100644 rustfmt-core/tests/source/chains.rs create mode 100644 rustfmt-core/tests/source/closure-block-inside-macro.rs create mode 100644 rustfmt-core/tests/source/closure.rs create mode 100644 rustfmt-core/tests/source/comment.rs create mode 100644 rustfmt-core/tests/source/comment2.rs create mode 100644 rustfmt-core/tests/source/comment3.rs create mode 100644 rustfmt-core/tests/source/comment4.rs create mode 100644 rustfmt-core/tests/source/comment5.rs create mode 100644 rustfmt-core/tests/source/comment_crlf_newline.rs create mode 100644 rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs create mode 100644 rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs create mode 100644 rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs create mode 100644 rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs create mode 100644 rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs create mode 100644 rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs create mode 100644 rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs create mode 100644 rustfmt-core/tests/source/configs/comment_width/above.rs create mode 100644 rustfmt-core/tests/source/configs/comment_width/below.rs create mode 100644 rustfmt-core/tests/source/configs/comment_width/ignore.rs create mode 100644 rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs create mode 100644 rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs create mode 100644 rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs create mode 100644 rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs create mode 100644 rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs create mode 100644 rustfmt-core/tests/source/configs/disable_all_formatting/false.rs create mode 100644 rustfmt-core/tests/source/configs/disable_all_formatting/true.rs create mode 100644 rustfmt-core/tests/source/configs/empty_item_single_line/false.rs create mode 100644 rustfmt-core/tests/source/configs/empty_item_single_line/true.rs create mode 100644 rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs create mode 100644 rustfmt-core/tests/source/configs/fn_args_density/compressed.rs create mode 100644 rustfmt-core/tests/source/configs/fn_args_density/tall.rs create mode 100644 rustfmt-core/tests/source/configs/fn_args_density/vertical.rs create mode 100644 rustfmt-core/tests/source/configs/fn_single_line/false.rs create mode 100644 rustfmt-core/tests/source/configs/fn_single_line/true.rs create mode 100644 rustfmt-core/tests/source/configs/force_explicit_abi/false.rs create mode 100644 rustfmt-core/tests/source/configs/force_explicit_abi/true.rs create mode 100644 rustfmt-core/tests/source/configs/force_multiline_block/false.rs create mode 100644 rustfmt-core/tests/source/configs/force_multiline_block/true.rs create mode 100644 rustfmt-core/tests/source/configs/format_strings/false.rs create mode 100644 rustfmt-core/tests/source/configs/format_strings/true.rs create mode 100644 rustfmt-core/tests/source/configs/hard_tabs/false.rs create mode 100644 rustfmt-core/tests/source/configs/hard_tabs/true.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_args.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_array.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_call.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_chain.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_generic.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/default.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/rfc_where.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_args.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_array.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_call.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_chain.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_generics.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs create mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs create mode 100644 rustfmt-core/tests/source/configs/match_arm_blocks/false.rs create mode 100644 rustfmt-core/tests/source/configs/match_arm_blocks/true.rs create mode 100644 rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs create mode 100644 rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs create mode 100644 rustfmt-core/tests/source/configs/merge_derives/true.rs create mode 100644 rustfmt-core/tests/source/configs/normalize_comments/false.rs create mode 100644 rustfmt-core/tests/source/configs/normalize_comments/true.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_imported_names/false.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_imported_names/true.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_imports/false.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_imports/true.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_modules/false.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs create mode 100644 rustfmt-core/tests/source/configs/reorder_modules/true.rs create mode 100644 rustfmt-core/tests/source/configs/space_before_colon/true.rs create mode 100644 rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs create mode 100644 rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs create mode 100644 rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs create mode 100644 rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs create mode 100644 rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs create mode 100644 rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs create mode 100644 rustfmt-core/tests/source/configs/tab_spaces/2.rs create mode 100644 rustfmt-core/tests/source/configs/tab_spaces/4.rs create mode 100644 rustfmt-core/tests/source/configs/trailing_comma/always.rs create mode 100644 rustfmt-core/tests/source/configs/trailing_comma/never.rs create mode 100644 rustfmt-core/tests/source/configs/trailing_comma/vertical.rs create mode 100644 rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs create mode 100644 rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs create mode 100644 rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs create mode 100644 rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs create mode 100644 rustfmt-core/tests/source/configs/use_try_shorthand/false.rs create mode 100644 rustfmt-core/tests/source/configs/use_try_shorthand/true.rs create mode 100644 rustfmt-core/tests/source/configs/where_single_line/true.rs create mode 100644 rustfmt-core/tests/source/configs/wrap_comments/false.rs create mode 100644 rustfmt-core/tests/source/configs/wrap_comments/true.rs create mode 100644 rustfmt-core/tests/source/control-brace-style-always-next-line.rs create mode 100644 rustfmt-core/tests/source/control-brace-style-always-same-line.rs create mode 100644 rustfmt-core/tests/source/doc.rs create mode 100644 rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs create mode 100644 rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs create mode 100644 rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs create mode 100644 rustfmt-core/tests/source/empty_file.rs create mode 100644 rustfmt-core/tests/source/enum.rs create mode 100644 rustfmt-core/tests/source/expr-block.rs create mode 100644 rustfmt-core/tests/source/expr.rs create mode 100644 rustfmt-core/tests/source/extern.rs create mode 100644 rustfmt-core/tests/source/extern_not_explicit.rs create mode 100644 rustfmt-core/tests/source/file-lines-1.rs create mode 100644 rustfmt-core/tests/source/file-lines-2.rs create mode 100644 rustfmt-core/tests/source/file-lines-3.rs create mode 100644 rustfmt-core/tests/source/file-lines-4.rs create mode 100644 rustfmt-core/tests/source/file-lines-5.rs create mode 100644 rustfmt-core/tests/source/file-lines-6.rs create mode 100644 rustfmt-core/tests/source/file-lines-item.rs create mode 100644 rustfmt-core/tests/source/fn-custom-2.rs create mode 100644 rustfmt-core/tests/source/fn-custom-3.rs create mode 100644 rustfmt-core/tests/source/fn-custom-4.rs create mode 100644 rustfmt-core/tests/source/fn-custom-6.rs create mode 100644 rustfmt-core/tests/source/fn-custom-7.rs create mode 100644 rustfmt-core/tests/source/fn-custom-8.rs create mode 100644 rustfmt-core/tests/source/fn-custom.rs create mode 100644 rustfmt-core/tests/source/fn-simple.rs create mode 100644 rustfmt-core/tests/source/fn-single-line.rs create mode 100644 rustfmt-core/tests/source/fn_args_density-vertical.rs create mode 100644 rustfmt-core/tests/source/fn_args_indent-block.rs create mode 100644 rustfmt-core/tests/source/hard-tabs.rs create mode 100644 rustfmt-core/tests/source/hello.rs create mode 100644 rustfmt-core/tests/source/hello2.rs create mode 100644 rustfmt-core/tests/source/immovable_generators.rs create mode 100644 rustfmt-core/tests/source/impls.rs create mode 100644 rustfmt-core/tests/source/imports-reorder-lines-and-items.rs create mode 100644 rustfmt-core/tests/source/imports-reorder-lines.rs create mode 100644 rustfmt-core/tests/source/imports-reorder.rs create mode 100644 rustfmt-core/tests/source/imports.rs create mode 100644 rustfmt-core/tests/source/issue-1021.rs create mode 100644 rustfmt-core/tests/source/issue-1049.rs create mode 100644 rustfmt-core/tests/source/issue-1111.rs create mode 100644 rustfmt-core/tests/source/issue-1120.rs create mode 100644 rustfmt-core/tests/source/issue-1124.rs create mode 100644 rustfmt-core/tests/source/issue-1127.rs create mode 100644 rustfmt-core/tests/source/issue-1158.rs create mode 100644 rustfmt-core/tests/source/issue-1177.rs create mode 100644 rustfmt-core/tests/source/issue-1192.rs create mode 100644 rustfmt-core/tests/source/issue-1211.rs create mode 100644 rustfmt-core/tests/source/issue-1216.rs create mode 100644 rustfmt-core/tests/source/issue-1239.rs create mode 100644 rustfmt-core/tests/source/issue-1278.rs create mode 100644 rustfmt-core/tests/source/issue-1350.rs create mode 100644 rustfmt-core/tests/source/issue-1366.rs create mode 100644 rustfmt-core/tests/source/issue-1468.rs create mode 100644 rustfmt-core/tests/source/issue-1693.rs create mode 100644 rustfmt-core/tests/source/issue-1800.rs create mode 100644 rustfmt-core/tests/source/issue-1914.rs create mode 100644 rustfmt-core/tests/source/issue-2025.rs create mode 100644 rustfmt-core/tests/source/issue-2111.rs create mode 100644 rustfmt-core/tests/source/issue-2164.rs create mode 100644 rustfmt-core/tests/source/issue-2179.rs create mode 100644 rustfmt-core/tests/source/issue-2256.rs create mode 100644 rustfmt-core/tests/source/issue-2342.rs create mode 100644 rustfmt-core/tests/source/issue-447.rs create mode 100644 rustfmt-core/tests/source/issue-510.rs create mode 100644 rustfmt-core/tests/source/issue-811.rs create mode 100644 rustfmt-core/tests/source/issue-850.rs create mode 100644 rustfmt-core/tests/source/issue-855.rs create mode 100644 rustfmt-core/tests/source/issue-913.rs create mode 100644 rustfmt-core/tests/source/issue-945.rs create mode 100644 rustfmt-core/tests/source/issue-977.rs create mode 100644 rustfmt-core/tests/source/item-brace-style-always-next-line.rs create mode 100644 rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs create mode 100644 rustfmt-core/tests/source/item-brace-style-same-line-where.rs create mode 100644 rustfmt-core/tests/source/large-block.rs create mode 100644 rustfmt-core/tests/source/large_vec.rs create mode 100644 rustfmt-core/tests/source/long-match-arms-brace-newline.rs create mode 100644 rustfmt-core/tests/source/long_field_access.rs create mode 100644 rustfmt-core/tests/source/loop.rs create mode 100644 rustfmt-core/tests/source/macro_not_expr.rs create mode 100644 rustfmt-core/tests/source/macro_rules.rs create mode 100644 rustfmt-core/tests/source/macros.rs create mode 100644 rustfmt-core/tests/source/match-block-trailing-comma.rs create mode 100644 rustfmt-core/tests/source/match-nowrap-trailing-comma.rs create mode 100644 rustfmt-core/tests/source/match-nowrap.rs create mode 100644 rustfmt-core/tests/source/match.rs create mode 100644 rustfmt-core/tests/source/max-line-length-in-chars.rs create mode 100644 rustfmt-core/tests/source/mod-1.rs create mode 100644 rustfmt-core/tests/source/mod-2.rs create mode 100644 rustfmt-core/tests/source/mod_skip_child.rs create mode 100644 rustfmt-core/tests/source/multiple.rs create mode 100644 rustfmt-core/tests/source/nested-if-else.rs create mode 100644 rustfmt-core/tests/source/nested_skipped/mod.rs create mode 100644 rustfmt-core/tests/source/nestedmod/mod.rs create mode 100644 rustfmt-core/tests/source/nestedmod/mod2a.rs create mode 100644 rustfmt-core/tests/source/nestedmod/mod2b.rs create mode 100644 rustfmt-core/tests/source/nestedmod/mod2c.rs create mode 100644 rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs create mode 100644 rustfmt-core/tests/source/nestedmod/submod2/a.rs create mode 100644 rustfmt-core/tests/source/nestedmod/submod2/mod.rs create mode 100644 rustfmt-core/tests/source/no_new_line_beginning.rs create mode 100644 rustfmt-core/tests/source/other.rs create mode 100644 rustfmt-core/tests/source/paths.rs create mode 100644 rustfmt-core/tests/source/pattern-condense-wildcards.rs create mode 100644 rustfmt-core/tests/source/pattern.rs create mode 100644 rustfmt-core/tests/source/pub-restricted.rs create mode 100644 rustfmt-core/tests/source/remove_blank_lines.rs create mode 100644 rustfmt-core/tests/source/single-line-if-else.rs create mode 100644 rustfmt-core/tests/source/soft-wrapping.rs create mode 100644 rustfmt-core/tests/source/space-not-before-newline.rs create mode 100644 rustfmt-core/tests/source/spaces-around-ranges.rs create mode 100644 rustfmt-core/tests/source/static.rs create mode 100644 rustfmt-core/tests/source/string-lit-2.rs create mode 100644 rustfmt-core/tests/source/string-lit.rs create mode 100644 rustfmt-core/tests/source/string_punctuation.rs create mode 100644 rustfmt-core/tests/source/struct-field-attributes.rs create mode 100644 rustfmt-core/tests/source/struct_lits.rs create mode 100644 rustfmt-core/tests/source/struct_lits_multiline.rs create mode 100644 rustfmt-core/tests/source/struct_lits_visual.rs create mode 100644 rustfmt-core/tests/source/struct_lits_visual_multiline.rs create mode 100644 rustfmt-core/tests/source/struct_tuple_visual.rs create mode 100644 rustfmt-core/tests/source/structs.rs create mode 100644 rustfmt-core/tests/source/trailing-comma-never.rs create mode 100644 rustfmt-core/tests/source/trailing_commas.rs create mode 100644 rustfmt-core/tests/source/trait.rs create mode 100644 rustfmt-core/tests/source/try-conversion.rs create mode 100644 rustfmt-core/tests/source/tuple.rs create mode 100644 rustfmt-core/tests/source/type-ascription.rs create mode 100644 rustfmt-core/tests/source/type-punctuation.rs create mode 100644 rustfmt-core/tests/source/type.rs create mode 100644 rustfmt-core/tests/source/type_alias.rs create mode 100644 rustfmt-core/tests/source/unions.rs create mode 100644 rustfmt-core/tests/source/where-clause-rfc.rs create mode 100644 rustfmt-core/tests/source/where-clause.rs create mode 100644 rustfmt-core/tests/target/assignment.rs create mode 100644 rustfmt-core/tests/target/associated-items.rs create mode 100644 rustfmt-core/tests/target/associated-types-bounds-wrapping.rs create mode 100644 rustfmt-core/tests/target/associated_type_defaults.rs create mode 100644 rustfmt-core/tests/target/attrib-extern-crate.rs create mode 100644 rustfmt-core/tests/target/attrib.rs create mode 100644 rustfmt-core/tests/target/big-impl-rfc.rs create mode 100644 rustfmt-core/tests/target/big-impl.rs create mode 100644 rustfmt-core/tests/target/break-and-continue.rs create mode 100644 rustfmt-core/tests/target/catch.rs create mode 100644 rustfmt-core/tests/target/chains-indent-tabbed.rs create mode 100644 rustfmt-core/tests/target/chains-indent-visual.rs create mode 100644 rustfmt-core/tests/target/chains-visual.rs create mode 100644 rustfmt-core/tests/target/chains.rs create mode 100644 rustfmt-core/tests/target/closure-block-inside-macro.rs create mode 100644 rustfmt-core/tests/target/closure.rs create mode 100644 rustfmt-core/tests/target/comment-inside-const.rs create mode 100644 rustfmt-core/tests/target/comment-not-disappear.rs create mode 100644 rustfmt-core/tests/target/comment.rs create mode 100644 rustfmt-core/tests/target/comment2.rs create mode 100644 rustfmt-core/tests/target/comment3.rs create mode 100644 rustfmt-core/tests/target/comment4.rs create mode 100644 rustfmt-core/tests/target/comment5.rs create mode 100644 rustfmt-core/tests/target/comment_crlf_newline.rs create mode 100644 rustfmt-core/tests/target/comments-fn.rs create mode 100644 rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs create mode 100644 rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs create mode 100644 rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs create mode 100644 rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs create mode 100644 rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs create mode 100644 rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs create mode 100644 rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs create mode 100644 rustfmt-core/tests/target/configs/combine_control_expr/false.rs create mode 100644 rustfmt-core/tests/target/configs/combine_control_expr/true.rs create mode 100644 rustfmt-core/tests/target/configs/comment_width/above.rs create mode 100644 rustfmt-core/tests/target/configs/comment_width/below.rs create mode 100644 rustfmt-core/tests/target/configs/comment_width/ignore.rs create mode 100644 rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs create mode 100644 rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs create mode 100644 rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs create mode 100644 rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs create mode 100644 rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs create mode 100644 rustfmt-core/tests/target/configs/disable_all_formatting/false.rs create mode 100644 rustfmt-core/tests/target/configs/disable_all_formatting/true.rs create mode 100644 rustfmt-core/tests/target/configs/empty_item_single_line/false.rs create mode 100644 rustfmt-core/tests/target/configs/empty_item_single_line/true.rs create mode 100644 rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs create mode 100644 rustfmt-core/tests/target/configs/error_on_unformatted/false.rs create mode 100644 rustfmt-core/tests/target/configs/fn_args_density/compressed.rs create mode 100644 rustfmt-core/tests/target/configs/fn_args_density/tall.rs create mode 100644 rustfmt-core/tests/target/configs/fn_args_density/vertical.rs create mode 100644 rustfmt-core/tests/target/configs/fn_single_line/false.rs create mode 100644 rustfmt-core/tests/target/configs/fn_single_line/true.rs create mode 100644 rustfmt-core/tests/target/configs/force_explicit_abi/false.rs create mode 100644 rustfmt-core/tests/target/configs/force_explicit_abi/true.rs create mode 100644 rustfmt-core/tests/target/configs/force_multiline_block/false.rs create mode 100644 rustfmt-core/tests/target/configs/force_multiline_block/true.rs create mode 100644 rustfmt-core/tests/target/configs/format_strings/false.rs create mode 100644 rustfmt-core/tests/target/configs/format_strings/true.rs create mode 100644 rustfmt-core/tests/target/configs/hard_tabs/false.rs create mode 100644 rustfmt-core/tests/target/configs/hard_tabs/true.rs create mode 100644 rustfmt-core/tests/target/configs/imports_indent/block.rs create mode 100644 rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs create mode 100644 rustfmt-core/tests/target/configs/imports_layout/mixed.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_args.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_array.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_call.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_chain.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_generic.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/default.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/rfc_control.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/rfc_where.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_args.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_array.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_call.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_chain.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_generics.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs create mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs create mode 100644 rustfmt-core/tests/target/configs/match_arm_blocks/false.rs create mode 100644 rustfmt-core/tests/target/configs/match_arm_blocks/true.rs create mode 100644 rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs create mode 100644 rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs create mode 100644 rustfmt-core/tests/target/configs/merge_derives/true.rs create mode 100644 rustfmt-core/tests/target/configs/normalize_comments/false.rs create mode 100644 rustfmt-core/tests/target/configs/normalize_comments/true.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_imported_names/false.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_imported_names/true.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_imports/false.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_imports/true.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_modules/false.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs create mode 100644 rustfmt-core/tests/target/configs/reorder_modules/true.rs create mode 100644 rustfmt-core/tests/target/configs/space_before_colon/true.rs create mode 100644 rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs create mode 100644 rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs create mode 100644 rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs create mode 100644 rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs create mode 100644 rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs create mode 100644 rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs create mode 100644 rustfmt-core/tests/target/configs/tab_spaces/2.rs create mode 100644 rustfmt-core/tests/target/configs/tab_spaces/4.rs create mode 100644 rustfmt-core/tests/target/configs/trailing_comma/always.rs create mode 100644 rustfmt-core/tests/target/configs/trailing_comma/never.rs create mode 100644 rustfmt-core/tests/target/configs/trailing_comma/vertical.rs create mode 100644 rustfmt-core/tests/target/configs/trailing_semicolon/false.rs create mode 100644 rustfmt-core/tests/target/configs/trailing_semicolon/true.rs create mode 100644 rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs create mode 100644 rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs create mode 100644 rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs create mode 100644 rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs create mode 100644 rustfmt-core/tests/target/configs/use_try_shorthand/false.rs create mode 100644 rustfmt-core/tests/target/configs/use_try_shorthand/true.rs create mode 100644 rustfmt-core/tests/target/configs/where_single_line/true.rs create mode 100644 rustfmt-core/tests/target/configs/wrap_comments/false.rs create mode 100644 rustfmt-core/tests/target/configs/wrap_comments/true.rs create mode 100644 rustfmt-core/tests/target/control-brace-style-always-next-line.rs create mode 100644 rustfmt-core/tests/target/control-brace-style-always-same-line.rs create mode 100644 rustfmt-core/tests/target/doc.rs create mode 100644 rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs create mode 100644 rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs create mode 100644 rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs create mode 100644 rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs create mode 100644 rustfmt-core/tests/target/empty_file.rs create mode 100644 rustfmt-core/tests/target/enum.rs create mode 100644 rustfmt-core/tests/target/expr-block.rs create mode 100644 rustfmt-core/tests/target/expr.rs create mode 100644 rustfmt-core/tests/target/extern.rs create mode 100644 rustfmt-core/tests/target/extern_not_explicit.rs create mode 100644 rustfmt-core/tests/target/file-lines-1.rs create mode 100644 rustfmt-core/tests/target/file-lines-2.rs create mode 100644 rustfmt-core/tests/target/file-lines-3.rs create mode 100644 rustfmt-core/tests/target/file-lines-4.rs create mode 100644 rustfmt-core/tests/target/file-lines-5.rs create mode 100644 rustfmt-core/tests/target/file-lines-6.rs create mode 100644 rustfmt-core/tests/target/file-lines-item.rs create mode 100644 rustfmt-core/tests/target/fn-args-with-last-line-comment.rs create mode 100644 rustfmt-core/tests/target/fn-custom-2.rs create mode 100644 rustfmt-core/tests/target/fn-custom-3.rs create mode 100644 rustfmt-core/tests/target/fn-custom-4.rs create mode 100644 rustfmt-core/tests/target/fn-custom-6.rs create mode 100644 rustfmt-core/tests/target/fn-custom-7.rs create mode 100644 rustfmt-core/tests/target/fn-custom-8.rs create mode 100644 rustfmt-core/tests/target/fn-custom.rs create mode 100644 rustfmt-core/tests/target/fn-simple.rs create mode 100644 rustfmt-core/tests/target/fn-single-line.rs create mode 100644 rustfmt-core/tests/target/fn-ty.rs create mode 100644 rustfmt-core/tests/target/fn.rs create mode 100644 rustfmt-core/tests/target/fn_args_density-vertical.rs create mode 100644 rustfmt-core/tests/target/fn_args_indent-block.rs create mode 100644 rustfmt-core/tests/target/fn_once.rs create mode 100644 rustfmt-core/tests/target/hard-tabs.rs create mode 100644 rustfmt-core/tests/target/hello.rs create mode 100644 rustfmt-core/tests/target/immovable_generators.rs create mode 100644 rustfmt-core/tests/target/impl.rs create mode 100644 rustfmt-core/tests/target/impls.rs create mode 100644 rustfmt-core/tests/target/import-fencepost-length.rs create mode 100644 rustfmt-core/tests/target/imports-reorder-lines-and-items.rs create mode 100644 rustfmt-core/tests/target/imports-reorder-lines.rs create mode 100644 rustfmt-core/tests/target/imports-reorder.rs create mode 100644 rustfmt-core/tests/target/imports.rs create mode 100644 rustfmt-core/tests/target/indented-impl.rs create mode 100644 rustfmt-core/tests/target/issue-1021.rs create mode 100644 rustfmt-core/tests/target/issue-1049.rs create mode 100644 rustfmt-core/tests/target/issue-1055.rs create mode 100644 rustfmt-core/tests/target/issue-1111.rs create mode 100644 rustfmt-core/tests/target/issue-1113.rs create mode 100644 rustfmt-core/tests/target/issue-1120.rs create mode 100644 rustfmt-core/tests/target/issue-1124.rs create mode 100644 rustfmt-core/tests/target/issue-1127.rs create mode 100644 rustfmt-core/tests/target/issue-1158.rs create mode 100644 rustfmt-core/tests/target/issue-1177.rs create mode 100644 rustfmt-core/tests/target/issue-1192.rs create mode 100644 rustfmt-core/tests/target/issue-1211.rs create mode 100644 rustfmt-core/tests/target/issue-1214.rs create mode 100644 rustfmt-core/tests/target/issue-1216.rs create mode 100644 rustfmt-core/tests/target/issue-1239.rs create mode 100644 rustfmt-core/tests/target/issue-1247.rs create mode 100644 rustfmt-core/tests/target/issue-1255.rs create mode 100644 rustfmt-core/tests/target/issue-1278.rs create mode 100644 rustfmt-core/tests/target/issue-1350.rs create mode 100644 rustfmt-core/tests/target/issue-1366.rs create mode 100644 rustfmt-core/tests/target/issue-1397.rs create mode 100644 rustfmt-core/tests/target/issue-1468.rs create mode 100644 rustfmt-core/tests/target/issue-1598.rs create mode 100644 rustfmt-core/tests/target/issue-1624.rs create mode 100644 rustfmt-core/tests/target/issue-1681.rs create mode 100644 rustfmt-core/tests/target/issue-1693.rs create mode 100644 rustfmt-core/tests/target/issue-1703.rs create mode 100644 rustfmt-core/tests/target/issue-1800.rs create mode 100644 rustfmt-core/tests/target/issue-1802.rs create mode 100644 rustfmt-core/tests/target/issue-1824.rs create mode 100644 rustfmt-core/tests/target/issue-1914.rs create mode 100644 rustfmt-core/tests/target/issue-2025.rs create mode 100644 rustfmt-core/tests/target/issue-2103.rs create mode 100644 rustfmt-core/tests/target/issue-2111.rs create mode 100644 rustfmt-core/tests/target/issue-2123.rs create mode 100644 rustfmt-core/tests/target/issue-2164.rs create mode 100644 rustfmt-core/tests/target/issue-2179.rs create mode 100644 rustfmt-core/tests/target/issue-2197.rs create mode 100644 rustfmt-core/tests/target/issue-2256.rs create mode 100644 rustfmt-core/tests/target/issue-2324.rs create mode 100644 rustfmt-core/tests/target/issue-2329.rs create mode 100644 rustfmt-core/tests/target/issue-2342.rs create mode 100644 rustfmt-core/tests/target/issue-2401.rs create mode 100644 rustfmt-core/tests/target/issue-447.rs create mode 100644 rustfmt-core/tests/target/issue-510.rs create mode 100644 rustfmt-core/tests/target/issue-64.rs create mode 100644 rustfmt-core/tests/target/issue-691.rs create mode 100644 rustfmt-core/tests/target/issue-770.rs create mode 100644 rustfmt-core/tests/target/issue-811.rs create mode 100644 rustfmt-core/tests/target/issue-831.rs create mode 100644 rustfmt-core/tests/target/issue-850.rs create mode 100644 rustfmt-core/tests/target/issue-855.rs create mode 100644 rustfmt-core/tests/target/issue-913.rs create mode 100644 rustfmt-core/tests/target/issue-945.rs create mode 100644 rustfmt-core/tests/target/issue-977.rs create mode 100644 rustfmt-core/tests/target/item-brace-style-always-next-line.rs create mode 100644 rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs create mode 100644 rustfmt-core/tests/target/item-brace-style-same-line-where.rs create mode 100644 rustfmt-core/tests/target/large-block.rs create mode 100644 rustfmt-core/tests/target/large_vec.rs create mode 100644 rustfmt-core/tests/target/long-fn-1.rs create mode 100644 rustfmt-core/tests/target/long-match-arms-brace-newline.rs create mode 100644 rustfmt-core/tests/target/long_field_access.rs create mode 100644 rustfmt-core/tests/target/loop.rs create mode 100644 rustfmt-core/tests/target/macro_not_expr.rs create mode 100644 rustfmt-core/tests/target/macro_rules.rs create mode 100644 rustfmt-core/tests/target/macros.rs create mode 100644 rustfmt-core/tests/target/match-block-trailing-comma.rs create mode 100644 rustfmt-core/tests/target/match-nowrap-trailing-comma.rs create mode 100644 rustfmt-core/tests/target/match-nowrap.rs create mode 100644 rustfmt-core/tests/target/match.rs create mode 100644 rustfmt-core/tests/target/max-line-length-in-chars.rs create mode 100644 rustfmt-core/tests/target/mod-1.rs create mode 100644 rustfmt-core/tests/target/mod-2.rs create mode 100644 rustfmt-core/tests/target/mod_skip_child.rs create mode 100644 rustfmt-core/tests/target/mulit-file.rs create mode 100644 rustfmt-core/tests/target/multiple.rs create mode 100644 rustfmt-core/tests/target/nested-if-else.rs create mode 100644 rustfmt-core/tests/target/nested-visual-block.rs create mode 100644 rustfmt-core/tests/target/nested_skipped/mod.rs create mode 100644 rustfmt-core/tests/target/nestedmod/mod.rs create mode 100644 rustfmt-core/tests/target/nestedmod/mod2a.rs create mode 100644 rustfmt-core/tests/target/nestedmod/mod2b.rs create mode 100644 rustfmt-core/tests/target/nestedmod/mod2c.rs create mode 100644 rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs create mode 100644 rustfmt-core/tests/target/nestedmod/submod2/a.rs create mode 100644 rustfmt-core/tests/target/nestedmod/submod2/mod.rs create mode 100644 rustfmt-core/tests/target/no_new_line_beginning.rs create mode 100644 rustfmt-core/tests/target/other.rs create mode 100644 rustfmt-core/tests/target/paths.rs create mode 100644 rustfmt-core/tests/target/pattern-condense-wildcards.rs create mode 100644 rustfmt-core/tests/target/pattern.rs create mode 100644 rustfmt-core/tests/target/pub-restricted.rs create mode 100644 rustfmt-core/tests/target/remove_blank_lines.rs create mode 100644 rustfmt-core/tests/target/single-line-if-else.rs create mode 100644 rustfmt-core/tests/target/skip.rs create mode 100644 rustfmt-core/tests/target/skip_mod.rs create mode 100644 rustfmt-core/tests/target/soft-wrapping.rs create mode 100644 rustfmt-core/tests/target/space-not-before-newline.rs create mode 100644 rustfmt-core/tests/target/spaces-around-ranges.rs create mode 100644 rustfmt-core/tests/target/static.rs create mode 100644 rustfmt-core/tests/target/string-lit-2.rs create mode 100644 rustfmt-core/tests/target/string-lit-custom.rs create mode 100644 rustfmt-core/tests/target/string-lit.rs create mode 100644 rustfmt-core/tests/target/string_punctuation.rs create mode 100644 rustfmt-core/tests/target/struct-field-attributes.rs create mode 100644 rustfmt-core/tests/target/struct_lits.rs create mode 100644 rustfmt-core/tests/target/struct_lits_multiline.rs create mode 100644 rustfmt-core/tests/target/struct_lits_visual.rs create mode 100644 rustfmt-core/tests/target/struct_lits_visual_multiline.rs create mode 100644 rustfmt-core/tests/target/struct_tuple_visual.rs create mode 100644 rustfmt-core/tests/target/structs.rs create mode 100644 rustfmt-core/tests/target/trailing-comma-never.rs create mode 100644 rustfmt-core/tests/target/trailing_commas.rs create mode 100644 rustfmt-core/tests/target/trait.rs create mode 100644 rustfmt-core/tests/target/try-conversion.rs create mode 100644 rustfmt-core/tests/target/tuple.rs create mode 100644 rustfmt-core/tests/target/type-ascription.rs create mode 100644 rustfmt-core/tests/target/type-punctuation.rs create mode 100644 rustfmt-core/tests/target/type.rs create mode 100644 rustfmt-core/tests/target/type_alias.rs create mode 100644 rustfmt-core/tests/target/unindent_if_else_cond_comment.rs create mode 100644 rustfmt-core/tests/target/unions.rs create mode 100644 rustfmt-core/tests/target/where-clause-rfc.rs create mode 100644 rustfmt-core/tests/target/where-clause.rs create mode 100644 rustfmt-core/tests/writemode/source/fn-single-line.rs create mode 100644 rustfmt-core/tests/writemode/target/checkstyle.xml delete mode 100644 src/chains.rs delete mode 100644 src/checkstyle.rs delete mode 100644 src/closures.rs delete mode 100644 src/codemap.rs delete mode 100644 src/comment.rs delete mode 100644 src/expr.rs delete mode 100644 src/filemap.rs delete mode 100644 src/imports.rs delete mode 100644 src/issues.rs delete mode 100644 src/items.rs delete mode 100644 src/lib.rs delete mode 100644 src/lists.rs delete mode 100644 src/macros.rs delete mode 100644 src/missed_spans.rs delete mode 100644 src/modules.rs delete mode 100644 src/patterns.rs delete mode 100644 src/rewrite.rs delete mode 100644 src/rustfmt_diff.rs delete mode 100644 src/shape.rs delete mode 100644 src/spanned.rs delete mode 100644 src/string.rs delete mode 100644 src/types.rs delete mode 100644 src/utils.rs delete mode 100644 src/vertical.rs delete mode 100644 src/visitor.rs delete mode 100644 tests/config/disable_all_formatting.toml delete mode 100755 tests/config/issue-1111.toml delete mode 100644 tests/config/small_tabs.toml delete mode 100644 tests/coverage/source/comments.rs delete mode 100644 tests/coverage/target/comments.rs delete mode 100644 tests/source/assignment.rs delete mode 100644 tests/source/associated-types-bounds-wrapping.rs delete mode 100644 tests/source/attrib.rs delete mode 100644 tests/source/big-impl-rfc.rs delete mode 100644 tests/source/big-impl.rs delete mode 100644 tests/source/break-and-continue.rs delete mode 100644 tests/source/catch.rs delete mode 100644 tests/source/chains-indent-tabbed.rs delete mode 100644 tests/source/chains-indent-visual.rs delete mode 100644 tests/source/chains-visual.rs delete mode 100644 tests/source/chains.rs delete mode 100644 tests/source/closure-block-inside-macro.rs delete mode 100644 tests/source/closure.rs delete mode 100644 tests/source/comment.rs delete mode 100644 tests/source/comment2.rs delete mode 100644 tests/source/comment3.rs delete mode 100644 tests/source/comment4.rs delete mode 100644 tests/source/comment5.rs delete mode 100644 tests/source/comment_crlf_newline.rs delete mode 100644 tests/source/configs/blank_lines_lower_bound/1.rs delete mode 100644 tests/source/configs/brace_style/fn_always_next_line.rs delete mode 100644 tests/source/configs/brace_style/fn_prefer_same_line.rs delete mode 100644 tests/source/configs/brace_style/fn_same_line_where.rs delete mode 100644 tests/source/configs/brace_style/item_always_next_line.rs delete mode 100644 tests/source/configs/brace_style/item_prefer_same_line.rs delete mode 100644 tests/source/configs/brace_style/item_same_line_where.rs delete mode 100644 tests/source/configs/comment_width/above.rs delete mode 100644 tests/source/configs/comment_width/below.rs delete mode 100644 tests/source/configs/comment_width/ignore.rs delete mode 100644 tests/source/configs/condense_wildcard_suffixes/false.rs delete mode 100644 tests/source/configs/condense_wildcard_suffixes/true.rs delete mode 100644 tests/source/configs/control_brace_style/always_next_line.rs delete mode 100644 tests/source/configs/control_brace_style/always_same_line.rs delete mode 100644 tests/source/configs/control_brace_style/closing_next_line.rs delete mode 100644 tests/source/configs/disable_all_formatting/false.rs delete mode 100644 tests/source/configs/disable_all_formatting/true.rs delete mode 100644 tests/source/configs/empty_item_single_line/false.rs delete mode 100644 tests/source/configs/empty_item_single_line/true.rs delete mode 100644 tests/source/configs/error_on_line_overflow/false.rs delete mode 100644 tests/source/configs/fn_args_density/compressed.rs delete mode 100644 tests/source/configs/fn_args_density/tall.rs delete mode 100644 tests/source/configs/fn_args_density/vertical.rs delete mode 100644 tests/source/configs/fn_single_line/false.rs delete mode 100644 tests/source/configs/fn_single_line/true.rs delete mode 100644 tests/source/configs/force_explicit_abi/false.rs delete mode 100644 tests/source/configs/force_explicit_abi/true.rs delete mode 100644 tests/source/configs/force_multiline_block/false.rs delete mode 100644 tests/source/configs/force_multiline_block/true.rs delete mode 100644 tests/source/configs/format_strings/false.rs delete mode 100644 tests/source/configs/format_strings/true.rs delete mode 100644 tests/source/configs/hard_tabs/false.rs delete mode 100644 tests/source/configs/hard_tabs/true.rs delete mode 100644 tests/source/configs/indent_style/block_args.rs delete mode 100644 tests/source/configs/indent_style/block_array.rs delete mode 100644 tests/source/configs/indent_style/block_call.rs delete mode 100644 tests/source/configs/indent_style/block_chain.rs delete mode 100644 tests/source/configs/indent_style/block_generic.rs delete mode 100644 tests/source/configs/indent_style/block_struct_lit.rs delete mode 100644 tests/source/configs/indent_style/block_trailing_comma_call.rs delete mode 100644 tests/source/configs/indent_style/block_where_pred.rs delete mode 100644 tests/source/configs/indent_style/default.rs delete mode 100644 tests/source/configs/indent_style/rfc_where.rs delete mode 100644 tests/source/configs/indent_style/visual_args.rs delete mode 100644 tests/source/configs/indent_style/visual_array.rs delete mode 100644 tests/source/configs/indent_style/visual_call.rs delete mode 100644 tests/source/configs/indent_style/visual_chain.rs delete mode 100644 tests/source/configs/indent_style/visual_generics.rs delete mode 100644 tests/source/configs/indent_style/visual_struct_lit.rs delete mode 100644 tests/source/configs/indent_style/visual_trailing_comma.rs delete mode 100644 tests/source/configs/indent_style/visual_where_pred.rs delete mode 100644 tests/source/configs/match_arm_blocks/false.rs delete mode 100644 tests/source/configs/match_arm_blocks/true.rs delete mode 100644 tests/source/configs/match_block_trailing_comma/false.rs delete mode 100644 tests/source/configs/match_block_trailing_comma/true.rs delete mode 100644 tests/source/configs/merge_derives/true.rs delete mode 100644 tests/source/configs/normalize_comments/false.rs delete mode 100644 tests/source/configs/normalize_comments/true.rs delete mode 100644 tests/source/configs/reorder_extern_crates/false.rs delete mode 100644 tests/source/configs/reorder_extern_crates/true.rs delete mode 100644 tests/source/configs/reorder_imported_names/false.rs delete mode 100644 tests/source/configs/reorder_imported_names/true.rs delete mode 100644 tests/source/configs/reorder_imports/false.rs delete mode 100644 tests/source/configs/reorder_imports/true.rs delete mode 100644 tests/source/configs/reorder_imports_in_group/false.rs delete mode 100644 tests/source/configs/reorder_imports_in_group/true.rs delete mode 100644 tests/source/configs/reorder_modules/dolor/mod.rs delete mode 100644 tests/source/configs/reorder_modules/false.rs delete mode 100644 tests/source/configs/reorder_modules/ipsum/mod.rs delete mode 100644 tests/source/configs/reorder_modules/lorem/mod.rs delete mode 100644 tests/source/configs/reorder_modules/sit/mod.rs delete mode 100644 tests/source/configs/reorder_modules/true.rs delete mode 100644 tests/source/configs/space_before_colon/true.rs delete mode 100644 tests/source/configs/spaces_around_ranges/false.rs delete mode 100644 tests/source/configs/spaces_around_ranges/true.rs delete mode 100644 tests/source/configs/spaces_within_parens_and_brackets/false.rs delete mode 100644 tests/source/configs/spaces_within_parens_and_brackets/true.rs delete mode 100644 tests/source/configs/struct_field_align_threshold/20.rs delete mode 100644 tests/source/configs/struct_lit_single_line/false.rs delete mode 100644 tests/source/configs/tab_spaces/2.rs delete mode 100644 tests/source/configs/tab_spaces/4.rs delete mode 100644 tests/source/configs/trailing_comma/always.rs delete mode 100644 tests/source/configs/trailing_comma/never.rs delete mode 100644 tests/source/configs/trailing_comma/vertical.rs delete mode 100644 tests/source/configs/type_punctuation_density/compressed.rs delete mode 100644 tests/source/configs/type_punctuation_density/wide.rs delete mode 100644 tests/source/configs/use_field_init_shorthand/false.rs delete mode 100644 tests/source/configs/use_field_init_shorthand/true.rs delete mode 100644 tests/source/configs/use_try_shorthand/false.rs delete mode 100644 tests/source/configs/use_try_shorthand/true.rs delete mode 100644 tests/source/configs/where_single_line/true.rs delete mode 100644 tests/source/configs/wrap_comments/false.rs delete mode 100644 tests/source/configs/wrap_comments/true.rs delete mode 100644 tests/source/control-brace-style-always-next-line.rs delete mode 100644 tests/source/control-brace-style-always-same-line.rs delete mode 100644 tests/source/doc.rs delete mode 100644 tests/source/else-if-brace-style-always-next-line.rs delete mode 100644 tests/source/else-if-brace-style-always-same-line.rs delete mode 100644 tests/source/else-if-brace-style-closing-next-line.rs delete mode 100644 tests/source/empty_file.rs delete mode 100644 tests/source/enum.rs delete mode 100644 tests/source/expr-block.rs delete mode 100644 tests/source/expr.rs delete mode 100644 tests/source/extern.rs delete mode 100644 tests/source/extern_not_explicit.rs delete mode 100644 tests/source/file-lines-1.rs delete mode 100644 tests/source/file-lines-2.rs delete mode 100644 tests/source/file-lines-3.rs delete mode 100644 tests/source/file-lines-4.rs delete mode 100644 tests/source/file-lines-5.rs delete mode 100644 tests/source/file-lines-6.rs delete mode 100644 tests/source/file-lines-item.rs delete mode 100644 tests/source/fn-custom-2.rs delete mode 100644 tests/source/fn-custom-3.rs delete mode 100644 tests/source/fn-custom-4.rs delete mode 100644 tests/source/fn-custom-6.rs delete mode 100644 tests/source/fn-custom-7.rs delete mode 100644 tests/source/fn-custom-8.rs delete mode 100644 tests/source/fn-custom.rs delete mode 100644 tests/source/fn-simple.rs delete mode 100644 tests/source/fn-single-line.rs delete mode 100644 tests/source/fn_args_density-vertical.rs delete mode 100644 tests/source/fn_args_indent-block.rs delete mode 100644 tests/source/hard-tabs.rs delete mode 100644 tests/source/hello.rs delete mode 100644 tests/source/hello2.rs delete mode 100644 tests/source/immovable_generators.rs delete mode 100644 tests/source/impls.rs delete mode 100644 tests/source/imports-reorder-lines-and-items.rs delete mode 100644 tests/source/imports-reorder-lines.rs delete mode 100644 tests/source/imports-reorder.rs delete mode 100644 tests/source/imports.rs delete mode 100644 tests/source/issue-1021.rs delete mode 100644 tests/source/issue-1049.rs delete mode 100644 tests/source/issue-1111.rs delete mode 100644 tests/source/issue-1120.rs delete mode 100644 tests/source/issue-1124.rs delete mode 100644 tests/source/issue-1127.rs delete mode 100644 tests/source/issue-1158.rs delete mode 100644 tests/source/issue-1177.rs delete mode 100644 tests/source/issue-1192.rs delete mode 100644 tests/source/issue-1211.rs delete mode 100644 tests/source/issue-1216.rs delete mode 100644 tests/source/issue-1239.rs delete mode 100644 tests/source/issue-1278.rs delete mode 100644 tests/source/issue-1350.rs delete mode 100644 tests/source/issue-1366.rs delete mode 100644 tests/source/issue-1468.rs delete mode 100644 tests/source/issue-1693.rs delete mode 100644 tests/source/issue-1800.rs delete mode 100644 tests/source/issue-1914.rs delete mode 100644 tests/source/issue-2025.rs delete mode 100644 tests/source/issue-2111.rs delete mode 100644 tests/source/issue-2164.rs delete mode 100644 tests/source/issue-2179.rs delete mode 100644 tests/source/issue-2256.rs delete mode 100644 tests/source/issue-2342.rs delete mode 100644 tests/source/issue-447.rs delete mode 100644 tests/source/issue-510.rs delete mode 100644 tests/source/issue-811.rs delete mode 100644 tests/source/issue-850.rs delete mode 100644 tests/source/issue-855.rs delete mode 100644 tests/source/issue-913.rs delete mode 100644 tests/source/issue-945.rs delete mode 100644 tests/source/issue-977.rs delete mode 100644 tests/source/item-brace-style-always-next-line.rs delete mode 100644 tests/source/item-brace-style-prefer-same-line.rs delete mode 100644 tests/source/item-brace-style-same-line-where.rs delete mode 100644 tests/source/large-block.rs delete mode 100644 tests/source/large_vec.rs delete mode 100644 tests/source/long-match-arms-brace-newline.rs delete mode 100644 tests/source/long_field_access.rs delete mode 100644 tests/source/loop.rs delete mode 100644 tests/source/macro_not_expr.rs delete mode 100644 tests/source/macro_rules.rs delete mode 100644 tests/source/macros.rs delete mode 100644 tests/source/match-block-trailing-comma.rs delete mode 100644 tests/source/match-nowrap-trailing-comma.rs delete mode 100644 tests/source/match-nowrap.rs delete mode 100644 tests/source/match.rs delete mode 100644 tests/source/max-line-length-in-chars.rs delete mode 100644 tests/source/mod-1.rs delete mode 100644 tests/source/mod-2.rs delete mode 100644 tests/source/mod_skip_child.rs delete mode 100644 tests/source/multiple.rs delete mode 100644 tests/source/nested-if-else.rs delete mode 100644 tests/source/nested_skipped/mod.rs delete mode 100644 tests/source/nestedmod/mod.rs delete mode 100644 tests/source/nestedmod/mod2a.rs delete mode 100644 tests/source/nestedmod/mod2b.rs delete mode 100644 tests/source/nestedmod/mod2c.rs delete mode 100644 tests/source/nestedmod/mymod1/mod3a.rs delete mode 100644 tests/source/nestedmod/submod2/a.rs delete mode 100644 tests/source/nestedmod/submod2/mod.rs delete mode 100644 tests/source/no_new_line_beginning.rs delete mode 100644 tests/source/other.rs delete mode 100644 tests/source/paths.rs delete mode 100644 tests/source/pattern-condense-wildcards.rs delete mode 100644 tests/source/pattern.rs delete mode 100644 tests/source/pub-restricted.rs delete mode 100644 tests/source/remove_blank_lines.rs delete mode 100644 tests/source/single-line-if-else.rs delete mode 100644 tests/source/soft-wrapping.rs delete mode 100644 tests/source/space-not-before-newline.rs delete mode 100644 tests/source/spaces-around-ranges.rs delete mode 100644 tests/source/static.rs delete mode 100644 tests/source/string-lit-2.rs delete mode 100644 tests/source/string-lit.rs delete mode 100644 tests/source/string_punctuation.rs delete mode 100644 tests/source/struct-field-attributes.rs delete mode 100644 tests/source/struct_lits.rs delete mode 100644 tests/source/struct_lits_multiline.rs delete mode 100644 tests/source/struct_lits_visual.rs delete mode 100644 tests/source/struct_lits_visual_multiline.rs delete mode 100644 tests/source/struct_tuple_visual.rs delete mode 100644 tests/source/structs.rs delete mode 100644 tests/source/trailing-comma-never.rs delete mode 100644 tests/source/trailing_commas.rs delete mode 100644 tests/source/trait.rs delete mode 100644 tests/source/try-conversion.rs delete mode 100644 tests/source/tuple.rs delete mode 100644 tests/source/type-ascription.rs delete mode 100644 tests/source/type-punctuation.rs delete mode 100644 tests/source/type.rs delete mode 100644 tests/source/type_alias.rs delete mode 100644 tests/source/unions.rs delete mode 100644 tests/source/where-clause-rfc.rs delete mode 100644 tests/source/where-clause.rs delete mode 100644 tests/system.rs delete mode 100644 tests/target/assignment.rs delete mode 100644 tests/target/associated-items.rs delete mode 100644 tests/target/associated-types-bounds-wrapping.rs delete mode 100644 tests/target/associated_type_defaults.rs delete mode 100644 tests/target/attrib-extern-crate.rs delete mode 100644 tests/target/attrib.rs delete mode 100644 tests/target/big-impl-rfc.rs delete mode 100644 tests/target/big-impl.rs delete mode 100644 tests/target/break-and-continue.rs delete mode 100644 tests/target/catch.rs delete mode 100644 tests/target/chains-indent-tabbed.rs delete mode 100644 tests/target/chains-indent-visual.rs delete mode 100644 tests/target/chains-visual.rs delete mode 100644 tests/target/chains.rs delete mode 100644 tests/target/closure-block-inside-macro.rs delete mode 100644 tests/target/closure.rs delete mode 100644 tests/target/comment-inside-const.rs delete mode 100644 tests/target/comment-not-disappear.rs delete mode 100644 tests/target/comment.rs delete mode 100644 tests/target/comment2.rs delete mode 100644 tests/target/comment3.rs delete mode 100644 tests/target/comment4.rs delete mode 100644 tests/target/comment5.rs delete mode 100644 tests/target/comment_crlf_newline.rs delete mode 100644 tests/target/comments-fn.rs delete mode 100644 tests/target/configs/blank_lines_lower_bound/1.rs delete mode 100644 tests/target/configs/brace_style/fn_always_next_line.rs delete mode 100644 tests/target/configs/brace_style/fn_prefer_same_line.rs delete mode 100644 tests/target/configs/brace_style/fn_same_line_where.rs delete mode 100644 tests/target/configs/brace_style/item_always_next_line.rs delete mode 100644 tests/target/configs/brace_style/item_prefer_same_line.rs delete mode 100644 tests/target/configs/brace_style/item_same_line_where.rs delete mode 100644 tests/target/configs/combine_control_expr/false.rs delete mode 100644 tests/target/configs/combine_control_expr/true.rs delete mode 100644 tests/target/configs/comment_width/above.rs delete mode 100644 tests/target/configs/comment_width/below.rs delete mode 100644 tests/target/configs/comment_width/ignore.rs delete mode 100644 tests/target/configs/condense_wildcard_suffixes/false.rs delete mode 100644 tests/target/configs/condense_wildcard_suffixes/true.rs delete mode 100644 tests/target/configs/control_brace_style/always_next_line.rs delete mode 100644 tests/target/configs/control_brace_style/always_same_line.rs delete mode 100644 tests/target/configs/control_brace_style/closing_next_line.rs delete mode 100644 tests/target/configs/disable_all_formatting/false.rs delete mode 100644 tests/target/configs/disable_all_formatting/true.rs delete mode 100644 tests/target/configs/empty_item_single_line/false.rs delete mode 100644 tests/target/configs/empty_item_single_line/true.rs delete mode 100644 tests/target/configs/error_on_line_overflow/false.rs delete mode 100644 tests/target/configs/error_on_unformatted/false.rs delete mode 100644 tests/target/configs/fn_args_density/compressed.rs delete mode 100644 tests/target/configs/fn_args_density/tall.rs delete mode 100644 tests/target/configs/fn_args_density/vertical.rs delete mode 100644 tests/target/configs/fn_single_line/false.rs delete mode 100644 tests/target/configs/fn_single_line/true.rs delete mode 100644 tests/target/configs/force_explicit_abi/false.rs delete mode 100644 tests/target/configs/force_explicit_abi/true.rs delete mode 100644 tests/target/configs/force_multiline_block/false.rs delete mode 100644 tests/target/configs/force_multiline_block/true.rs delete mode 100644 tests/target/configs/format_strings/false.rs delete mode 100644 tests/target/configs/format_strings/true.rs delete mode 100644 tests/target/configs/hard_tabs/false.rs delete mode 100644 tests/target/configs/hard_tabs/true.rs delete mode 100644 tests/target/configs/imports_indent/block.rs delete mode 100644 tests/target/configs/imports_layout/horizontal_vertical.rs delete mode 100644 tests/target/configs/imports_layout/mixed.rs delete mode 100644 tests/target/configs/indent_style/block_args.rs delete mode 100644 tests/target/configs/indent_style/block_array.rs delete mode 100644 tests/target/configs/indent_style/block_call.rs delete mode 100644 tests/target/configs/indent_style/block_chain.rs delete mode 100644 tests/target/configs/indent_style/block_generic.rs delete mode 100644 tests/target/configs/indent_style/block_struct_lit.rs delete mode 100644 tests/target/configs/indent_style/block_tab_spaces_call.rs delete mode 100644 tests/target/configs/indent_style/block_trailing_comma_call.rs delete mode 100644 tests/target/configs/indent_style/block_where_pred.rs delete mode 100644 tests/target/configs/indent_style/default.rs delete mode 100644 tests/target/configs/indent_style/rfc_control.rs delete mode 100644 tests/target/configs/indent_style/rfc_where.rs delete mode 100644 tests/target/configs/indent_style/visual_args.rs delete mode 100644 tests/target/configs/indent_style/visual_array.rs delete mode 100644 tests/target/configs/indent_style/visual_call.rs delete mode 100644 tests/target/configs/indent_style/visual_chain.rs delete mode 100644 tests/target/configs/indent_style/visual_generics.rs delete mode 100644 tests/target/configs/indent_style/visual_struct_lit.rs delete mode 100644 tests/target/configs/indent_style/visual_trailing_comma.rs delete mode 100644 tests/target/configs/indent_style/visual_where_pred.rs delete mode 100644 tests/target/configs/match_arm_blocks/false.rs delete mode 100644 tests/target/configs/match_arm_blocks/true.rs delete mode 100644 tests/target/configs/match_block_trailing_comma/false.rs delete mode 100644 tests/target/configs/match_block_trailing_comma/true.rs delete mode 100644 tests/target/configs/merge_derives/true.rs delete mode 100644 tests/target/configs/normalize_comments/false.rs delete mode 100644 tests/target/configs/normalize_comments/true.rs delete mode 100644 tests/target/configs/reorder_extern_crates/false.rs delete mode 100644 tests/target/configs/reorder_extern_crates/true.rs delete mode 100644 tests/target/configs/reorder_imported_names/false.rs delete mode 100644 tests/target/configs/reorder_imported_names/true.rs delete mode 100644 tests/target/configs/reorder_imports/false.rs delete mode 100644 tests/target/configs/reorder_imports/true.rs delete mode 100644 tests/target/configs/reorder_imports_in_group/false.rs delete mode 100644 tests/target/configs/reorder_imports_in_group/true.rs delete mode 100644 tests/target/configs/reorder_modules/dolor/mod.rs delete mode 100644 tests/target/configs/reorder_modules/false.rs delete mode 100644 tests/target/configs/reorder_modules/ipsum/mod.rs delete mode 100644 tests/target/configs/reorder_modules/lorem/mod.rs delete mode 100644 tests/target/configs/reorder_modules/sit/mod.rs delete mode 100644 tests/target/configs/reorder_modules/true.rs delete mode 100644 tests/target/configs/space_before_colon/true.rs delete mode 100644 tests/target/configs/spaces_around_ranges/false.rs delete mode 100644 tests/target/configs/spaces_around_ranges/true.rs delete mode 100644 tests/target/configs/spaces_within_parens_and_brackets/false.rs delete mode 100644 tests/target/configs/spaces_within_parens_and_brackets/true.rs delete mode 100644 tests/target/configs/struct_field_align_threshold/20.rs delete mode 100644 tests/target/configs/struct_lit_single_line/false.rs delete mode 100644 tests/target/configs/tab_spaces/2.rs delete mode 100644 tests/target/configs/tab_spaces/4.rs delete mode 100644 tests/target/configs/trailing_comma/always.rs delete mode 100644 tests/target/configs/trailing_comma/never.rs delete mode 100644 tests/target/configs/trailing_comma/vertical.rs delete mode 100644 tests/target/configs/trailing_semicolon/false.rs delete mode 100644 tests/target/configs/trailing_semicolon/true.rs delete mode 100644 tests/target/configs/type_punctuation_density/compressed.rs delete mode 100644 tests/target/configs/type_punctuation_density/wide.rs delete mode 100644 tests/target/configs/use_field_init_shorthand/false.rs delete mode 100644 tests/target/configs/use_field_init_shorthand/true.rs delete mode 100644 tests/target/configs/use_try_shorthand/false.rs delete mode 100644 tests/target/configs/use_try_shorthand/true.rs delete mode 100644 tests/target/configs/where_single_line/true.rs delete mode 100644 tests/target/configs/wrap_comments/false.rs delete mode 100644 tests/target/configs/wrap_comments/true.rs delete mode 100644 tests/target/control-brace-style-always-next-line.rs delete mode 100644 tests/target/control-brace-style-always-same-line.rs delete mode 100644 tests/target/doc.rs delete mode 100644 tests/target/else-if-brace-style-always-next-line.rs delete mode 100644 tests/target/else-if-brace-style-always-same-line.rs delete mode 100644 tests/target/else-if-brace-style-closing-next-line.rs delete mode 100644 tests/target/empty-tuple-no-conversion-to-unit-struct.rs delete mode 100644 tests/target/empty_file.rs delete mode 100644 tests/target/enum.rs delete mode 100644 tests/target/expr-block.rs delete mode 100644 tests/target/expr.rs delete mode 100644 tests/target/extern.rs delete mode 100644 tests/target/extern_not_explicit.rs delete mode 100644 tests/target/file-lines-1.rs delete mode 100644 tests/target/file-lines-2.rs delete mode 100644 tests/target/file-lines-3.rs delete mode 100644 tests/target/file-lines-4.rs delete mode 100644 tests/target/file-lines-5.rs delete mode 100644 tests/target/file-lines-6.rs delete mode 100644 tests/target/file-lines-item.rs delete mode 100644 tests/target/fn-args-with-last-line-comment.rs delete mode 100644 tests/target/fn-custom-2.rs delete mode 100644 tests/target/fn-custom-3.rs delete mode 100644 tests/target/fn-custom-4.rs delete mode 100644 tests/target/fn-custom-6.rs delete mode 100644 tests/target/fn-custom-7.rs delete mode 100644 tests/target/fn-custom-8.rs delete mode 100644 tests/target/fn-custom.rs delete mode 100644 tests/target/fn-simple.rs delete mode 100644 tests/target/fn-single-line.rs delete mode 100644 tests/target/fn-ty.rs delete mode 100644 tests/target/fn.rs delete mode 100644 tests/target/fn_args_density-vertical.rs delete mode 100644 tests/target/fn_args_indent-block.rs delete mode 100644 tests/target/fn_once.rs delete mode 100644 tests/target/hard-tabs.rs delete mode 100644 tests/target/hello.rs delete mode 100644 tests/target/immovable_generators.rs delete mode 100644 tests/target/impl.rs delete mode 100644 tests/target/impls.rs delete mode 100644 tests/target/import-fencepost-length.rs delete mode 100644 tests/target/imports-reorder-lines-and-items.rs delete mode 100644 tests/target/imports-reorder-lines.rs delete mode 100644 tests/target/imports-reorder.rs delete mode 100644 tests/target/imports.rs delete mode 100644 tests/target/indented-impl.rs delete mode 100644 tests/target/issue-1021.rs delete mode 100644 tests/target/issue-1049.rs delete mode 100644 tests/target/issue-1055.rs delete mode 100644 tests/target/issue-1111.rs delete mode 100644 tests/target/issue-1113.rs delete mode 100644 tests/target/issue-1120.rs delete mode 100644 tests/target/issue-1124.rs delete mode 100644 tests/target/issue-1127.rs delete mode 100644 tests/target/issue-1158.rs delete mode 100644 tests/target/issue-1177.rs delete mode 100644 tests/target/issue-1192.rs delete mode 100644 tests/target/issue-1211.rs delete mode 100644 tests/target/issue-1214.rs delete mode 100644 tests/target/issue-1216.rs delete mode 100644 tests/target/issue-1239.rs delete mode 100644 tests/target/issue-1247.rs delete mode 100644 tests/target/issue-1255.rs delete mode 100644 tests/target/issue-1278.rs delete mode 100644 tests/target/issue-1350.rs delete mode 100644 tests/target/issue-1366.rs delete mode 100644 tests/target/issue-1397.rs delete mode 100644 tests/target/issue-1468.rs delete mode 100644 tests/target/issue-1598.rs delete mode 100644 tests/target/issue-1624.rs delete mode 100644 tests/target/issue-1681.rs delete mode 100644 tests/target/issue-1693.rs delete mode 100644 tests/target/issue-1703.rs delete mode 100644 tests/target/issue-1800.rs delete mode 100644 tests/target/issue-1802.rs delete mode 100644 tests/target/issue-1824.rs delete mode 100644 tests/target/issue-1914.rs delete mode 100644 tests/target/issue-2025.rs delete mode 100644 tests/target/issue-2103.rs delete mode 100644 tests/target/issue-2111.rs delete mode 100644 tests/target/issue-2123.rs delete mode 100644 tests/target/issue-2164.rs delete mode 100644 tests/target/issue-2179.rs delete mode 100644 tests/target/issue-2197.rs delete mode 100644 tests/target/issue-2256.rs delete mode 100644 tests/target/issue-2324.rs delete mode 100644 tests/target/issue-2329.rs delete mode 100644 tests/target/issue-2342.rs delete mode 100644 tests/target/issue-2401.rs delete mode 100644 tests/target/issue-447.rs delete mode 100644 tests/target/issue-510.rs delete mode 100644 tests/target/issue-64.rs delete mode 100644 tests/target/issue-691.rs delete mode 100644 tests/target/issue-770.rs delete mode 100644 tests/target/issue-811.rs delete mode 100644 tests/target/issue-831.rs delete mode 100644 tests/target/issue-850.rs delete mode 100644 tests/target/issue-855.rs delete mode 100644 tests/target/issue-913.rs delete mode 100644 tests/target/issue-945.rs delete mode 100644 tests/target/issue-977.rs delete mode 100644 tests/target/item-brace-style-always-next-line.rs delete mode 100644 tests/target/item-brace-style-prefer-same-line.rs delete mode 100644 tests/target/item-brace-style-same-line-where.rs delete mode 100644 tests/target/large-block.rs delete mode 100644 tests/target/large_vec.rs delete mode 100644 tests/target/long-fn-1.rs delete mode 100644 tests/target/long-match-arms-brace-newline.rs delete mode 100644 tests/target/long_field_access.rs delete mode 100644 tests/target/loop.rs delete mode 100644 tests/target/macro_not_expr.rs delete mode 100644 tests/target/macro_rules.rs delete mode 100644 tests/target/macros.rs delete mode 100644 tests/target/match-block-trailing-comma.rs delete mode 100644 tests/target/match-nowrap-trailing-comma.rs delete mode 100644 tests/target/match-nowrap.rs delete mode 100644 tests/target/match.rs delete mode 100644 tests/target/max-line-length-in-chars.rs delete mode 100644 tests/target/mod-1.rs delete mode 100644 tests/target/mod-2.rs delete mode 100644 tests/target/mod_skip_child.rs delete mode 100644 tests/target/mulit-file.rs delete mode 100644 tests/target/multiple.rs delete mode 100644 tests/target/nested-if-else.rs delete mode 100644 tests/target/nested-visual-block.rs delete mode 100644 tests/target/nested_skipped/mod.rs delete mode 100644 tests/target/nestedmod/mod.rs delete mode 100644 tests/target/nestedmod/mod2a.rs delete mode 100644 tests/target/nestedmod/mod2b.rs delete mode 100644 tests/target/nestedmod/mod2c.rs delete mode 100644 tests/target/nestedmod/mymod1/mod3a.rs delete mode 100644 tests/target/nestedmod/submod2/a.rs delete mode 100644 tests/target/nestedmod/submod2/mod.rs delete mode 100644 tests/target/no_new_line_beginning.rs delete mode 100644 tests/target/other.rs delete mode 100644 tests/target/paths.rs delete mode 100644 tests/target/pattern-condense-wildcards.rs delete mode 100644 tests/target/pattern.rs delete mode 100644 tests/target/pub-restricted.rs delete mode 100644 tests/target/remove_blank_lines.rs delete mode 100644 tests/target/single-line-if-else.rs delete mode 100644 tests/target/skip.rs delete mode 100644 tests/target/skip_mod.rs delete mode 100644 tests/target/soft-wrapping.rs delete mode 100644 tests/target/space-not-before-newline.rs delete mode 100644 tests/target/spaces-around-ranges.rs delete mode 100644 tests/target/static.rs delete mode 100644 tests/target/string-lit-2.rs delete mode 100644 tests/target/string-lit-custom.rs delete mode 100644 tests/target/string-lit.rs delete mode 100644 tests/target/string_punctuation.rs delete mode 100644 tests/target/struct-field-attributes.rs delete mode 100644 tests/target/struct_lits.rs delete mode 100644 tests/target/struct_lits_multiline.rs delete mode 100644 tests/target/struct_lits_visual.rs delete mode 100644 tests/target/struct_lits_visual_multiline.rs delete mode 100644 tests/target/struct_tuple_visual.rs delete mode 100644 tests/target/structs.rs delete mode 100644 tests/target/trailing-comma-never.rs delete mode 100644 tests/target/trailing_commas.rs delete mode 100644 tests/target/trait.rs delete mode 100644 tests/target/try-conversion.rs delete mode 100644 tests/target/tuple.rs delete mode 100644 tests/target/type-ascription.rs delete mode 100644 tests/target/type-punctuation.rs delete mode 100644 tests/target/type.rs delete mode 100644 tests/target/type_alias.rs delete mode 100644 tests/target/unindent_if_else_cond_comment.rs delete mode 100644 tests/target/unions.rs delete mode 100644 tests/target/where-clause-rfc.rs delete mode 100644 tests/target/where-clause.rs delete mode 100644 tests/writemode/source/fn-single-line.rs delete mode 100644 tests/writemode/target/checkstyle.xml (limited to 'src') diff --git a/rustfmt-core/Cargo.toml b/rustfmt-core/Cargo.toml new file mode 100644 index 00000000000..2cf72e3f210 --- /dev/null +++ b/rustfmt-core/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "rustfmt-core" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "A core library of rustfmt" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +categories = ["development-tools"] + +[lib] +doctest = false + +[dependencies] +derive-new = "0.5" +diff = "0.1" +log = "0.3" +regex = "0.2" +rustc-ap-syntax = "29.0.0" +rustc-ap-rustc_errors = "29.0.0" +rustfmt-config = { path = "../rustfmt-config" } +term = "0.4" +unicode-segmentation = "1.0.0" + +[dev-dependencies] +lazy_static = "1.0.0" + +[target.'cfg(unix)'.dependencies] +libc = "0.2.11" + +[target.'cfg(windows)'.dependencies] +kernel32-sys = "0.2.2" +winapi = "0.2.7" diff --git a/rustfmt-core/src/chains.rs b/rustfmt-core/src/chains.rs new file mode 100644 index 00000000000..383e7077d66 --- /dev/null +++ b/rustfmt-core/src/chains.rs @@ -0,0 +1,499 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Formatting of chained expressions, i.e. expressions which are chained by +//! dots: struct and enum field access, method calls, and try shorthand (?). +//! +//! Instead of walking these subexpressions one-by-one, as is our usual strategy +//! for expression formatting, we collect maximal sequences of these expressions +//! and handle them simultaneously. +//! +//! Whenever possible, the entire chain is put on a single line. If that fails, +//! we put each subexpression on a separate, much like the (default) function +//! argument function argument strategy. +//! +//! Depends on config options: `chain_indent` is the indent to use for +//! blocks in the parent/root/base of the chain (and the rest of the chain's +//! alignment). +//! E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the +//! following values of `chain_indent`: +//! Block: +//! ``` +//! let foo = { +//! aaaa; +//! bbb; +//! ccc +//! }.bar +//! .baz(); +//! ``` +//! Visual: +//! ``` +//! let foo = { +//! aaaa; +//! bbb; +//! ccc +//! } +//! .bar +//! .baz(); +//! ``` +//! +//! If the first item in the chain is a block expression, we align the dots with +//! the braces. +//! Block: +//! ``` +//! let a = foo.bar +//! .baz() +//! .qux +//! ``` +//! Visual: +//! ``` +//! let a = foo.bar +//! .baz() +//! .qux +//! ``` + +use config::IndentStyle; +use expr::rewrite_call; +use macros::convert_try_mac; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, + trimmed_last_line_width, wrap_str}; + +use std::cmp::min; +use std::iter; +use syntax::{ast, ptr}; +use syntax::codemap::Span; + +pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { + debug!("rewrite_chain {:?}", shape); + let total_span = expr.span; + let (parent, subexpr_list) = make_subexpr_list(expr, context); + + // Bail out if the chain is just try sugar, i.e., an expression followed by + // any number of `?`s. + if chain_only_try(&subexpr_list) { + return rewrite_try(&parent, subexpr_list.len(), context, shape); + } + let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); + let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); + + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. + let parent_shape = if is_block_expr(context, &parent, "\n") { + match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape, + } + } else { + shape + }; + let parent_rewrite = parent + .rewrite(context, parent_shape) + .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?; + let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); + let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); + + // Decide how to layout the rest of the chain. `extend` is true if we can + // put the first non-parent item on the same line as the parent. + let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + context.config.indent_style() == IndentStyle::Visual || is_small_parent, + ) + } else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } + } else { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + false, + ) + }; + + let other_child_shape = nested_shape.with_max_width(context.config); + + let first_child_shape = if extend { + let overhead = last_line_width(&parent_rewrite); + let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; + match context.config.indent_style() { + IndentStyle::Visual => parent_shape.offset_left(overhead)?, + IndentStyle::Block => parent_shape.offset_left(offset)?, + } + } else { + other_child_shape + }; + debug!( + "child_shapes {:?} {:?}", + first_child_shape, other_child_shape + ); + + let child_shape_iter = Some(first_child_shape) + .into_iter() + .chain(iter::repeat(other_child_shape)); + let subexpr_num = subexpr_list.len(); + let last_subexpr = &subexpr_list[suffix_try_num]; + let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; + let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); + let mut rewrites = iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) + .collect::>>()?; + + // Total of all items excluding the last. + let extend_last_subexpr = if is_small_parent { + rewrites.len() == 1 && last_line_extendable(&rewrites[0]) + } else { + rewrites.is_empty() && last_line_extendable(&parent_rewrite) + }; + let almost_total = if extend_last_subexpr { + last_line_width(&parent_rewrite) + } else { + rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() + } + suffix_try_num; + let one_line_budget = if rewrites.is_empty() { + shape.width + } else { + min(shape.width, context.config.width_heuristics().chain_width) + }; + let all_in_one_line = !parent_rewrite_contains_newline + && rewrites.iter().all(|s| !s.contains('\n')) + && almost_total < one_line_budget; + let last_shape = if rewrites.is_empty() { + first_child_shape + } else { + other_child_shape + }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; + + // Rewrite the last child. The last child of a chain requires special treatment. We need to + // know whether 'overflowing' the last child make a better formatting: + // + // A chain with overflowing the last child: + // ``` + // parent.child1.child2.last_child( + // a, + // b, + // c, + // ) + // ``` + // + // A chain without overflowing the last child (in vertical layout): + // ``` + // parent + // .child1 + // .child2 + // .last_child(a, b, c) + // ``` + // + // In particular, overflowing is effective when the last child is a method with a multi-lined + // block-like argument (e.g. closure): + // ``` + // parent.child1.child2.last_child(|a, b, c| { + // let x = foo(a, b, c); + // let y = bar(a, b, c); + // + // // ... + // + // result + // }) + // ``` + + // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of + // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); + let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { + // First we try to 'overflow' the last child and see if it looks better than using + // vertical layout. + parent_shape.offset_left(almost_total).map(|shape| { + if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + // We allow overflowing here only if both of the following conditions match: + // 1. The entire chain fits in a single line expect the last child. + // 2. `last_child_str.lines().count() >= 5`. + let line_count = rw.lines().count(); + let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + if fits_single_line && line_count >= 5 { + (Some(rw), true) + } else { + // We could not know whether overflowing is better than using vertical layout, + // just by looking at the overflowed rewrite. Now we rewrite the last child + // on its own line, and compare two rewrites to choose which is better. + match rewrite_last() { + Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), + Some(ref new_rw) if new_rw.lines().count() >= line_count => { + (Some(rw), fits_single_line) + } + new_rw @ Some(..) => (new_rw, false), + _ => (Some(rw), fits_single_line), + } + } + } else { + (rewrite_last(), false) + } + })? + } else { + (rewrite_last(), false) + }; + rewrites.push(last_subexpr_str?); + + let connector = if fits_single_line && !parent_rewrite_contains_newline { + // Yay, we can put everything on one line. + String::new() + } else { + // Use new lines. + if context.force_one_line_chain { + return None; + } + format!("\n{}", nested_shape.indent.to_string(context.config)) + }; + + let first_connector = if is_small_parent || fits_single_line + || last_line_extendable(&parent_rewrite) + || context.config.indent_style() == IndentStyle::Visual + { + "" + } else { + connector.as_str() + }; + + let result = if is_small_parent && rewrites.len() > 1 { + let second_connector = if fits_single_line || rewrites[1] == "?" + || last_line_extendable(&rewrites[0]) + || context.config.indent_style() == IndentStyle::Visual + { + "" + } else { + &connector + }; + format!( + "{}{}{}{}{}", + parent_rewrite, + first_connector, + rewrites[0], + second_connector, + join_rewrites(&rewrites[1..], &connector) + ) + } else { + format!( + "{}{}{}", + parent_rewrite, + first_connector, + join_rewrites(&rewrites, &connector) + ) + }; + let result = format!("{}{}", result, repeat_try(suffix_try_num)); + if context.config.indent_style() == IndentStyle::Visual { + wrap_str(result, context.config.max_width(), shape) + } else { + Some(result) + } +} + +// True if the chain is only `?`s. +fn chain_only_try(exprs: &[ast::Expr]) -> bool { + exprs.iter().all(|e| { + if let ast::ExprKind::Try(_) = e.node { + true + } else { + false + } + }) +} + +// Try to rewrite and replace the last non-try child. Return `true` if +// replacing succeeds. +fn repeat_try(try_count: usize) -> String { + iter::repeat("?").take(try_count).collect::() +} + +fn rewrite_try( + expr: &ast::Expr, + try_count: usize, + context: &RewriteContext, + shape: Shape, +) -> Option { + let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; + Some(format!("{}{}", sub_expr, repeat_try(try_count))) +} + +fn join_rewrites(rewrites: &[String], connector: &str) -> String { + let mut rewrite_iter = rewrites.iter(); + let mut result = rewrite_iter.next().unwrap().clone(); + + for rewrite in rewrite_iter { + if rewrite != "?" { + result.push_str(connector); + } + result.push_str(&rewrite[..]); + } + + result +} + +// States whether an expression's last line exclusively consists of closing +// parens, braces, and brackets in its idiomatic formatting. +fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { + match expr.node { + ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { + context.use_block_indent() && repr.contains('\n') + } + ast::ExprKind::Struct(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) + | ast::ExprKind::Binary(_, _, ref expr) + | ast::ExprKind::Index(_, ref expr) + | ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), + _ => false, + } +} + +// Returns the root of the chain and a Vec of the prefixes of the rest of the chain. +// E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) +fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { + let mut subexpr_list = vec![expr.clone()]; + + while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { + subexpr_list.push(subexpr.clone()); + } + + let parent = subexpr_list.pop().unwrap(); + (parent, subexpr_list) +} + +fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { + match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), + } +} + +// Returns the expression's subexpression, if it exists. When the subexpr +// is a try! macro, we'll convert it to shorthand when the option is set. +fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { + match expr.node { + ast::ExprKind::MethodCall(_, ref expressions) => { + Some(convert_try(&expressions[0], context)) + } + ast::ExprKind::TupField(ref subexpr, _) + | ast::ExprKind::Field(ref subexpr, _) + | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), + _ => None, + } +} + +fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { + match expr.node { + ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { + if let Some(subexpr) = convert_try_mac(mac, context) { + subexpr + } else { + expr.clone() + } + } + _ => expr.clone(), + } +} + +// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite +// `.c`. +fn rewrite_chain_subexpr( + expr: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let rewrite_element = |expr_str: String| { + if expr_str.len() <= shape.width { + Some(expr_str) + } else { + None + } + }; + + match expr.node { + ast::ExprKind::MethodCall(ref segment, ref expressions) => { + let types = match segment.parameters { + Some(ref params) => match **params { + ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + _ => &[], + }, + _ => &[], + }; + rewrite_method_call(segment.identifier, types, expressions, span, context, shape) + } + ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), + ast::ExprKind::TupField(ref expr, ref field) => { + let space = match expr.node { + ast::ExprKind::TupField(..) => " ", + _ => "", + }; + rewrite_element(format!("{}.{}", space, field.node)) + } + ast::ExprKind::Try(_) => rewrite_element(String::from("?")), + _ => unreachable!(), + } +} + +// Determines if we can continue formatting a given expression on the same line. +fn is_continuable(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Path(..) => true, + _ => false, + } +} + +fn is_try(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Try(..) => true, + _ => false, + } +} + +fn rewrite_method_call( + method_name: ast::Ident, + types: &[ptr::P], + args: &[ptr::P], + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let (lo, type_str) = if types.is_empty() { + (args[0].span.hi(), String::new()) + } else { + let type_list = types + .iter() + .map(|ty| ty.rewrite(context, shape)) + .collect::>>()?; + + let type_str = + if context.config.spaces_within_parens_and_brackets() && !type_list.is_empty() { + format!("::< {} >", type_list.join(", ")) + } else { + format!("::<{}>", type_list.join(", ")) + }; + + (types.last().unwrap().span.hi(), type_str) + }; + + let callee_str = format!(".{}{}", method_name, type_str); + let span = mk_sp(lo, span.hi()); + + rewrite_call(context, &callee_str, &args[1..], span, shape) +} diff --git a/rustfmt-core/src/checkstyle.rs b/rustfmt-core/src/checkstyle.rs new file mode 100644 index 00000000000..7f6e650ad22 --- /dev/null +++ b/rustfmt-core/src/checkstyle.rs @@ -0,0 +1,85 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io::{self, Write}; +use std::path::Path; + +use config::WriteMode; +use rustfmt_diff::{DiffLine, Mismatch}; + +pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> +where + T: Write, +{ + if mode == WriteMode::Checkstyle { + let mut xml_heading = String::new(); + xml_heading.push_str(""); + xml_heading.push_str("\n"); + xml_heading.push_str(""); + write!(out, "{}", xml_heading)?; + } + Ok(()) +} + +pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> +where + T: Write, +{ + if mode == WriteMode::Checkstyle { + let mut xml_tail = String::new(); + xml_tail.push_str("\n"); + write!(out, "{}", xml_tail)?; + } + Ok(()) +} + +pub fn output_checkstyle_file( + mut writer: T, + filename: &Path, + diff: Vec, +) -> Result<(), io::Error> +where + T: Write, +{ + write!(writer, "", filename.display())?; + for mismatch in diff { + for line in mismatch.lines { + // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. + if let DiffLine::Expected(ref str) = line { + let message = xml_escape_str(str); + write!( + writer, + "", + mismatch.line_number, message + )?; + } + } + } + write!(writer, "")?; + Ok(()) +} + +// Convert special characters into XML entities. +// This is needed for checkstyle output. +fn xml_escape_str(string: &str) -> String { + let mut out = String::new(); + for c in string.chars() { + match c { + '<' => out.push_str("<"), + '>' => out.push_str(">"), + '"' => out.push_str("""), + '\'' => out.push_str("'"), + '&' => out.push_str("&"), + _ => out.push(c), + } + } + out +} diff --git a/rustfmt-core/src/closures.rs b/rustfmt-core/src/closures.rs new file mode 100644 index 00000000000..be1681c7671 --- /dev/null +++ b/rustfmt-core/src/closures.rs @@ -0,0 +1,392 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::lists::*; +use syntax::{ast, ptr}; +use syntax::codemap::Span; +use syntax::parse::classify; + +use codemap::SpanUtils; +use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; +use items::{span_hi_for_arg, span_lo_for_arg}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{last_line_width, left_most_sub_expr, stmt_expr}; + +// This module is pretty messy because of the rules around closures and blocks: +// FIXME - the below is probably no longer true in full. +// * if there is a return type, then there must be braces, +// * given a closure with braces, whether that is parsed to give an inner block +// or not depends on if there is a return type and if there are statements +// in that block, +// * if the first expression in the body ends with a block (i.e., is a +// statement without needing a semi-colon), then adding or removing braces +// can change whether it is treated as an expression or statement. + +pub fn rewrite_closure( + capture: ast::CaptureBy, + movability: ast::Movability, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + debug!("rewrite_closure {:?}", body); + + let (prefix, extra_offset) = + rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?; + // 1 = space between `|...|` and body. + let body_shape = shape.offset_left(extra_offset)?; + + if let ast::ExprKind::Block(ref block) = body.node { + // The body of the closure is an empty block. + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + return Some(format!("{} {{}}", prefix)); + } + + let result = match fn_decl.output { + ast::FunctionRetTy::Default(_) => { + try_rewrite_without_block(body, &prefix, context, shape, body_shape) + } + _ => None, + }; + + result.or_else(|| { + // Either we require a block, or tried without and failed. + rewrite_closure_block(block, &prefix, context, body_shape) + }) + } else { + rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { + // The closure originally had a non-block expression, but we can't fit on + // one line, so we'll insert a block. + rewrite_closure_with_block(body, &prefix, context, body_shape) + }) + } +} + +fn try_rewrite_without_block( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, + body_shape: Shape, +) -> Option { + let expr = get_inner_expr(expr, prefix, context); + + if is_block_closure_forced(context, expr) { + rewrite_closure_with_block(expr, prefix, context, shape) + } else { + rewrite_closure_expr(expr, prefix, context, body_shape) + } +} + +fn get_inner_expr<'a>( + expr: &'a ast::Expr, + prefix: &str, + context: &RewriteContext, +) -> &'a ast::Expr { + if let ast::ExprKind::Block(ref block) = expr.node { + if !needs_block(block, prefix, context) { + // block.stmts.len() == 1 + if let Some(expr) = stmt_expr(&block.stmts[0]) { + return get_inner_expr(expr, prefix, context); + } + } + } + + expr +} + +// Figure out if a block is necessary. +fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { + is_unsafe_block(block) || block.stmts.len() > 1 + || block_contains_comment(block, context.codemap) || prefix.contains('\n') +} + +// Rewrite closure with a single expression wrapping its body with block. +fn rewrite_closure_with_block( + body: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + let left_most = left_most_sub_expr(body); + let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most); + if veto_block { + return None; + } + + let block = ast::Block { + stmts: vec![ + ast::Stmt { + id: ast::NodeId::new(0), + node: ast::StmtKind::Expr(ptr::P(body.clone())), + span: body.span, + }, + ], + id: ast::NodeId::new(0), + rules: ast::BlockCheckMode::Default, + span: body.span, + recovered: false, + }; + let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; + Some(format!("{} {}", prefix, block)) +} + +// Rewrite closure with a single expression without wrapping its body with block. +fn rewrite_closure_expr( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + fn allow_multi_line(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Catch(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::Struct(..) => true, + + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), + + _ => false, + } + } + + // When rewriting closure's body without block, we require it to fit in a single line + // unless it is a block-like expression or we are inside macro call. + let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro) + || context.config.force_multiline_blocks(); + expr.rewrite(context, shape) + .and_then(|rw| { + if veto_multiline && rw.contains('\n') { + None + } else { + Some(rw) + } + }) + .map(|rw| format!("{} {}", prefix, rw)) +} + +// Rewrite closure whose body is block. +fn rewrite_closure_block( + block: &ast::Block, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + Some(format!("{} {}", prefix, block.rewrite(context, shape)?)) +} + +// Return type is (prefix, extra_offset) +fn rewrite_closure_fn_decl( + capture: ast::CaptureBy, + movability: ast::Movability, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option<(String, usize)> { + let mover = if capture == ast::CaptureBy::Value { + "move " + } else { + "" + }; + + let immovable = if movability == ast::Movability::Static { + "static " + } else { + "" + }; + // 4 = "|| {".len(), which is overconservative when the closure consists of + // a single expression. + let nested_shape = shape + .shrink_left(mover.len() + immovable.len())? + .sub_width(4)?; + + // 1 = | + let argument_offset = nested_shape.indent + 1; + let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); + let ret_str = fn_decl.output.rewrite(context, arg_shape)?; + + let arg_items = itemize_list( + context.codemap, + fn_decl.inputs.iter(), + "|", + ",", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(context, arg), + |arg| arg.rewrite(context, arg_shape), + context.codemap.span_after(span, "|"), + body.span.lo(), + false, + ); + let item_vec = arg_items.collect::>(); + // 1 = space between arguments and return type. + let horizontal_budget = nested_shape + .width + .checked_sub(ret_str.len() + 1) + .unwrap_or(0); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + horizontal_budget, + ); + let arg_shape = match tactic { + DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, + _ => arg_shape, + }; + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arg_shape, + ends_with_newline: false, + preserve_newline: true, + config: context.config, + }; + let list_str = write_list(&item_vec, &fmt)?; + let mut prefix = format!("{}{}|{}|", immovable, mover, list_str); + + if !ret_str.is_empty() { + if prefix.contains('\n') { + prefix.push('\n'); + prefix.push_str(&argument_offset.to_string(context.config)); + } else { + prefix.push(' '); + } + prefix.push_str(&ret_str); + } + // 1 = space between `|...|` and body. + let extra_offset = last_line_width(&prefix) + 1; + + Some((prefix, extra_offset)) +} + +// Rewriting closure which is placed at the end of the function call's arg. +// Returns `None` if the reformatted closure 'looks bad'. +pub fn rewrite_last_closure( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, +) -> Option { + if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { + let body = match body.node { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + { + stmt_expr(&block.stmts[0]).unwrap_or(body) + } + _ => body, + }; + let (prefix, extra_offset) = rewrite_closure_fn_decl( + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, + )?; + // If the closure goes multi line before its body, do not overflow the closure. + if prefix.contains('\n') { + return None; + } + + let body_shape = shape.offset_left(extra_offset)?; + + // We force to use block for the body of the closure for certain kinds of expressions. + if is_block_closure_forced(context, body) { + return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( + |body_str| { + // If the expression can fit in a single line, we need not force block closure. + if body_str.lines().count() <= 7 { + match rewrite_closure_expr(body, &prefix, context, shape) { + Some(ref single_line_body_str) + if !single_line_body_str.contains('\n') => + { + Some(single_line_body_str.clone()) + } + _ => Some(body_str), + } + } else { + Some(body_str) + } + }, + ); + } + + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + let is_multi_lined_cond = rewrite_cond(context, body, body_shape) + .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) + .unwrap_or(false); + if is_multi_lined_cond { + return rewrite_closure_with_block(body, &prefix, context, body_shape); + } + + // Seems fine, just format the closure in usual manner. + return expr.rewrite(context, shape); + } + None +} + +/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. +pub fn args_have_many_closure(args: &[&T]) -> bool +where + T: ToExpr, +{ + args.iter() + .filter(|arg| { + arg.to_expr() + .map(|e| match e.node { + ast::ExprKind::Closure(..) => true, + _ => false, + }) + .unwrap_or(false) + }) + .count() > 1 +} + +fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { + // If we are inside macro, we do not want to add or remove block from closure body. + if context.inside_macro { + false + } else { + is_block_closure_forced_inner(expr) + } +} + +fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr), + _ => false, + } +} diff --git a/rustfmt-core/src/codemap.rs b/rustfmt-core/src/codemap.rs new file mode 100644 index 00000000000..85716f73615 --- /dev/null +++ b/rustfmt-core/src/codemap.rs @@ -0,0 +1,86 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains utilities that work with the `CodeMap` from `libsyntax` / `syntex_syntax`. +//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. + +use config::file_lines::LineRange; +use syntax::codemap::{BytePos, CodeMap, Span}; + +use comment::FindUncommented; + +pub trait SpanUtils { + fn span_after(&self, original: Span, needle: &str) -> BytePos; + fn span_after_last(&self, original: Span, needle: &str) -> BytePos; + fn span_before(&self, original: Span, needle: &str) -> BytePos; + fn opt_span_after(&self, original: Span, needle: &str) -> Option; +} + +pub trait LineRangeUtils { + /// Returns the `LineRange` that corresponds to `span` in `self`. + /// + /// # Panics + /// + /// Panics if `span` crosses a file boundary, which shouldn't happen. + fn lookup_line_range(&self, span: Span) -> LineRange; +} + +impl SpanUtils for CodeMap { + fn span_after(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).expect("Bad snippet"); + let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len(); + + original.lo() + BytePos(offset as u32) + } + + fn span_after_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo() + BytePos(offset as u32) + } + + fn span_before(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap(); + + original.lo() + BytePos(offset as u32) + } + + fn opt_span_after(&self, original: Span, needle: &str) -> Option { + let snippet = self.span_to_snippet(original).ok()?; + let offset = snippet.find_uncommented(needle)? + needle.len(); + + Some(original.lo() + BytePos(offset as u32)) + } +} + +impl LineRangeUtils for CodeMap { + fn lookup_line_range(&self, span: Span) -> LineRange { + let lo = self.lookup_char_pos(span.lo()); + let hi = self.lookup_char_pos(span.hi()); + + assert_eq!( + lo.file.name, hi.file.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, hi + ); + + LineRange { + file: lo.file.clone(), + lo: lo.line, + hi: hi.line, + } + } +} diff --git a/rustfmt-core/src/comment.rs b/rustfmt-core/src/comment.rs new file mode 100644 index 00000000000..9c0322bcaeb --- /dev/null +++ b/rustfmt-core/src/comment.rs @@ -0,0 +1,1234 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Formatting and tools for comments. + +use std::{self, iter}; + +use syntax::codemap::Span; + +use config::Config; +use rewrite::RewriteContext; +use shape::{Indent, Shape}; +use string::{rewrite_string, StringFormat}; +use utils::{count_newlines, first_line_width, last_line_width}; + +fn is_custom_comment(comment: &str) -> bool { + if !comment.starts_with("//") { + false + } else if let Some(c) = comment.chars().nth(2) { + !c.is_alphanumeric() && !c.is_whitespace() + } else { + false + } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum CommentStyle<'a> { + DoubleSlash, + TripleSlash, + Doc, + SingleBullet, + DoubleBullet, + Exclamation, + Custom(&'a str), +} + +fn custom_opener(s: &str) -> &str { + s.lines().next().map_or("", |first_line| { + first_line + .find(' ') + .map_or(first_line, |space_index| &first_line[0..space_index + 1]) + }) +} + +impl<'a> CommentStyle<'a> { + pub fn opener(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash => "// ", + CommentStyle::TripleSlash => "/// ", + CommentStyle::Doc => "//! ", + CommentStyle::SingleBullet => "/* ", + CommentStyle::DoubleBullet => "/** ", + CommentStyle::Exclamation => "/*! ", + CommentStyle::Custom(opener) => opener, + } + } + + pub fn closer(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash + | CommentStyle::TripleSlash + | CommentStyle::Custom(..) + | CommentStyle::Doc => "", + CommentStyle::DoubleBullet => " **/", + CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", + } + } + + pub fn line_start(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash => "// ", + CommentStyle::TripleSlash => "/// ", + CommentStyle::Doc => "//! ", + CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", + CommentStyle::DoubleBullet => " ** ", + CommentStyle::Custom(opener) => opener, + } + } + + pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { + (self.opener(), self.closer(), self.line_start()) + } + + pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { + match *self { + CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { + line.trim_left().starts_with(self.line_start().trim_left()) + || comment_style(line, normalize_comments) == *self + } + CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { + line.trim_left().starts_with(self.closer().trim_left()) + || line.trim_left().starts_with(self.line_start().trim_left()) + || comment_style(line, normalize_comments) == *self + } + CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), + } + } +} + +fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { + if !normalize_comments { + if orig.starts_with("/**") && !orig.starts_with("/**/") { + CommentStyle::DoubleBullet + } else if orig.starts_with("/*!") { + CommentStyle::Exclamation + } else if orig.starts_with("/*") { + CommentStyle::SingleBullet + } else if orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/') { + CommentStyle::TripleSlash + } else if orig.starts_with("//!") { + CommentStyle::Doc + } else if is_custom_comment(orig) { + CommentStyle::Custom(custom_opener(orig)) + } else { + CommentStyle::DoubleSlash + } + } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) + || (orig.starts_with("/**") && !orig.starts_with("/**/")) + { + CommentStyle::TripleSlash + } else if orig.starts_with("//!") || orig.starts_with("/*!") { + CommentStyle::Doc + } else if is_custom_comment(orig) { + CommentStyle::Custom(custom_opener(orig)) + } else { + CommentStyle::DoubleSlash + } +} + +/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain +/// comments between two strings. If there are such comments, then that will be +/// recovered. If `allow_extend` is true and there is no comment between the two +/// strings, then they will be put on a single line as long as doing so does not +/// exceed max width. +pub fn combine_strs_with_missing_comments( + context: &RewriteContext, + prev_str: &str, + next_str: &str, + span: Span, + shape: Shape, + allow_extend: bool, +) -> Option { + let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); + let first_sep = if prev_str.is_empty() || next_str.is_empty() { + "" + } else { + " " + }; + let mut one_line_width = + last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); + + let indent_str = shape.indent.to_string(context.config); + let missing_comment = rewrite_missing_comment(span, shape, context)?; + + if missing_comment.is_empty() { + if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { + return Some(format!("{}{}{}", prev_str, first_sep, next_str)); + } else { + let sep = if prev_str.is_empty() { + String::new() + } else { + String::from("\n") + &indent_str + }; + return Some(format!("{}{}{}", prev_str, sep, next_str)); + } + } + + // We have a missing comment between the first expression and the second expression. + + // Peek the the original source code and find out whether there is a newline between the first + // expression and the second expression or the missing comment. We will preserve the original + // layout whenever possible. + let original_snippet = context.snippet(span); + let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { + !original_snippet[..pos].contains('\n') + } else { + !original_snippet.contains('\n') + }; + + one_line_width -= first_sep.len(); + let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { + String::new() + } else { + let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; + if prefer_same_line && one_line_width <= shape.width { + String::from(" ") + } else { + format!("\n{}", indent_str) + } + }; + let second_sep = if missing_comment.is_empty() || next_str.is_empty() { + String::new() + } else if missing_comment.starts_with("//") { + format!("\n{}", indent_str) + } else { + one_line_width += missing_comment.len() + first_sep.len() + 1; + allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); + if prefer_same_line && allow_one_line && one_line_width <= shape.width { + String::from(" ") + } else { + format!("\n{}", indent_str) + } + }; + Some(format!( + "{}{}{}{}{}", + prev_str, first_sep, missing_comment, second_sep, next_str, + )) +} + +pub fn rewrite_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, +) -> Option { + // If there are lines without a starting sigil, we won't format them correctly + // so in that case we won't even re-align (if !config.normalize_comments()) and + // we should stop now. + let num_bare_lines = orig.lines() + .map(|line| line.trim()) + .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) + .count(); + if num_bare_lines > 0 && !config.normalize_comments() { + return Some(orig.to_owned()); + } + if !config.normalize_comments() && !config.wrap_comments() { + return light_rewrite_comment(orig, shape.indent, config); + } + + identify_comment(orig, block_style, shape, config) +} + +fn identify_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, +) -> Option { + let style = comment_style(orig, false); + let first_group = orig.lines() + .take_while(|l| style.line_with_same_comment_style(l, false)) + .collect::>() + .join("\n"); + let rest = orig.lines() + .skip(first_group.lines().count()) + .collect::>() + .join("\n"); + + let first_group_str = rewrite_comment_inner(&first_group, block_style, style, shape, config)?; + if rest.is_empty() { + Some(first_group_str) + } else { + identify_comment(&rest, block_style, shape, config).map(|rest_str| { + format!( + "{}\n{}{}", + first_group_str, + shape.indent.to_string(config), + rest_str + ) + }) + } +} + +fn rewrite_comment_inner( + orig: &str, + block_style: bool, + style: CommentStyle, + shape: Shape, + config: &Config, +) -> Option { + let (opener, closer, line_start) = if block_style { + CommentStyle::SingleBullet.to_str_tuplet() + } else { + comment_style(orig, config.normalize_comments()).to_str_tuplet() + }; + + let max_chars = shape + .width + .checked_sub(closer.len() + opener.len()) + .unwrap_or(1); + let indent_str = shape.indent.to_string(config); + let fmt_indent = shape.indent + (opener.len() - line_start.len()); + let mut fmt = StringFormat { + opener: "", + closer: "", + line_start, + line_end: "", + shape: Shape::legacy(max_chars, fmt_indent), + trim_end: true, + config, + }; + + let line_breaks = count_newlines(orig.trim_right()); + let lines = orig.lines() + .enumerate() + .map(|(i, mut line)| { + line = line.trim(); + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = line[..(line.len() - 2)].trim_right(); + } + + line + }) + .map(|s| left_trim_comment_line(s, &style)) + .map(|(line, has_leading_whitespace)| { + if orig.starts_with("/*") && line_breaks == 0 { + ( + line.trim_left(), + has_leading_whitespace || config.normalize_comments(), + ) + } else { + (line, has_leading_whitespace || config.normalize_comments()) + } + }); + + let mut result = String::with_capacity(orig.len() * 2); + result.push_str(opener); + let mut code_block_buffer = String::with_capacity(128); + let mut is_prev_line_multi_line = false; + let mut inside_code_block = false; + let comment_line_separator = format!("\n{}{}", indent_str, line_start); + let join_code_block_with_comment_line_separator = |s: &str| { + let mut result = String::with_capacity(s.len() + 128); + let mut iter = s.lines().peekable(); + while let Some(line) = iter.next() { + result.push_str(line); + result.push_str(match iter.peek() { + Some(next_line) if next_line.is_empty() => comment_line_separator.trim_right(), + Some(..) => &comment_line_separator, + None => "", + }); + } + result + }; + + for (i, (line, has_leading_whitespace)) in lines.enumerate() { + let is_last = i == count_newlines(orig); + + if inside_code_block { + if line.starts_with("```") { + inside_code_block = false; + result.push_str(&comment_line_separator); + let code_block = ::format_code_block(&code_block_buffer, config) + .unwrap_or_else(|| code_block_buffer.to_owned()); + result.push_str(&join_code_block_with_comment_line_separator(&code_block)); + code_block_buffer.clear(); + result.push_str(&comment_line_separator); + result.push_str(line); + } else { + code_block_buffer.push_str(line); + code_block_buffer.push('\n'); + } + + continue; + } else { + inside_code_block = line.starts_with("```"); + + if result == opener { + let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; + if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + if line.is_empty() { + continue; + } + } else if is_prev_line_multi_line && !line.is_empty() { + result.push(' ') + } else if is_last && !closer.is_empty() && line.is_empty() { + result.push('\n'); + result.push_str(&indent_str); + } else { + result.push_str(&comment_line_separator); + if !has_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + } + } + + if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { + match rewrite_string(line, &fmt, Some(max_chars)) { + Some(ref s) => { + is_prev_line_multi_line = s.contains('\n'); + result.push_str(s); + } + None if is_prev_line_multi_line => { + // We failed to put the current `line` next to the previous `line`. + // Remove the trailing space, then start rewrite on the next line. + result.pop(); + result.push_str(&comment_line_separator); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + match rewrite_string(line, &fmt, Some(max_chars)) { + Some(ref s) => { + is_prev_line_multi_line = s.contains('\n'); + result.push_str(s); + } + None => { + is_prev_line_multi_line = false; + result.push_str(line); + } + } + } + None => { + is_prev_line_multi_line = false; + result.push_str(line); + } + } + + fmt.shape = if is_prev_line_multi_line { + // 1 = " " + let offset = 1 + last_line_width(&result) - line_start.len(); + Shape { + width: max_chars.checked_sub(offset).unwrap_or(0), + indent: fmt_indent, + offset: fmt.shape.offset + offset, + } + } else { + Shape::legacy(max_chars, fmt_indent) + }; + } else { + if line.is_empty() && result.ends_with(' ') && !is_last { + // Remove space if this is an empty comment or a doc comment. + result.pop(); + } + result.push_str(line); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + is_prev_line_multi_line = false; + } + } + + result.push_str(closer); + if result == opener && result.ends_with(' ') { + // Trailing space. + result.pop(); + } + + Some(result) +} + +/// Returns true if the given string MAY include URLs or alike. +fn has_url(s: &str) -> bool { + // This function may return false positive, but should get its job done in most cases. + s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") +} + +/// Given the span, rewrite the missing comment inside it if available. +/// Note that the given span must only include comments (or leading/trailing whitespaces). +pub fn rewrite_missing_comment( + span: Span, + shape: Shape, + context: &RewriteContext, +) -> Option { + let missing_snippet = context.snippet(span); + let trimmed_snippet = missing_snippet.trim(); + if !trimmed_snippet.is_empty() { + rewrite_comment(trimmed_snippet, false, shape, context.config) + } else { + Some(String::new()) + } +} + +/// Recover the missing comments in the specified span, if available. +/// The layout of the comments will be preserved as long as it does not break the code +/// and its total width does not exceed the max width. +pub fn recover_missing_comment_in_span( + span: Span, + shape: Shape, + context: &RewriteContext, + used_width: usize, +) -> Option { + let missing_comment = rewrite_missing_comment(span, shape, context)?; + if missing_comment.is_empty() { + Some(String::new()) + } else { + let missing_snippet = context.snippet(span); + let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); + // 1 = ` ` + let total_width = missing_comment.len() + used_width + 1; + let force_new_line_before_comment = + missing_snippet[..pos].contains('\n') || total_width > context.config.max_width(); + let sep = if force_new_line_before_comment { + format!("\n{}", shape.indent.to_string(context.config)) + } else { + String::from(" ") + }; + Some(format!("{}{}", sep, missing_comment)) + } +} + +/// Trims whitespace and aligns to indent, but otherwise does not change comments. +fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option { + let lines: Vec<&str> = orig.lines() + .map(|l| { + // This is basically just l.trim(), but in the case that a line starts + // with `*` we want to leave one space before it, so it aligns with the + // `*` in `/*`. + let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); + if let Some(fnw) = first_non_whitespace { + if l.as_bytes()[fnw] == b'*' && fnw > 0 { + &l[fnw - 1..] + } else { + &l[fnw..] + } + } else { + "" + }.trim_right() + }) + .collect(); + Some(lines.join(&format!("\n{}", offset.to_string(config)))) +} + +/// Trims comment characters and possibly a single space from the left of a string. +/// Does not trim all whitespace. If a single space is trimmed from the left of the string, +/// this function returns true. +fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { + if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") + || line.starts_with("/** ") + { + (&line[4..], true) + } else if let CommentStyle::Custom(opener) = *style { + if line.starts_with(opener) { + (&line[opener.len()..], true) + } else { + (&line[opener.trim_right().len()..], false) + } + } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") + || line.starts_with("///") || line.starts_with("** ") + || line.starts_with("/*!") + || (line.starts_with("/**") && !line.starts_with("/**/")) + { + (&line[3..], line.chars().nth(2).unwrap() == ' ') + } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") + || line.starts_with("**") + { + (&line[2..], line.chars().nth(1).unwrap() == ' ') + } else if line.starts_with('*') { + (&line[1..], false) + } else { + (line, line.starts_with(' ')) + } +} + +pub trait FindUncommented { + fn find_uncommented(&self, pat: &str) -> Option; +} + +impl FindUncommented for str { + fn find_uncommented(&self, pat: &str) -> Option { + let mut needle_iter = pat.chars(); + for (kind, (i, b)) in CharClasses::new(self.char_indices()) { + match needle_iter.next() { + None => { + return Some(i - pat.len()); + } + Some(c) => match kind { + FullCodeCharKind::Normal | FullCodeCharKind::InString if b == c => {} + _ => { + needle_iter = pat.chars(); + } + }, + } + } + + // Handle case where the pattern is a suffix of the search string + match needle_iter.next() { + Some(_) => None, + None => Some(self.len() - pat.len()), + } + } +} + +// Returns the first byte position after the first comment. The given string +// is expected to be prefixed by a comment, including delimiters. +// Good: "/* /* inner */ outer */ code();" +// Bad: "code(); // hello\n world!" +pub fn find_comment_end(s: &str) -> Option { + let mut iter = CharClasses::new(s.char_indices()); + for (kind, (i, _c)) in &mut iter { + if kind == FullCodeCharKind::Normal || kind == FullCodeCharKind::InString { + return Some(i); + } + } + + // Handle case where the comment ends at the end of s. + if iter.status == CharClassesStatus::Normal { + Some(s.len()) + } else { + None + } +} + +/// Returns true if text contains any comment. +pub fn contains_comment(text: &str) -> bool { + CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) +} + +/// Remove trailing spaces from the specified snippet. We do not remove spaces +/// inside strings or comments. +pub fn remove_trailing_white_spaces(text: &str) -> String { + let mut buffer = String::with_capacity(text.len()); + let mut space_buffer = String::with_capacity(128); + for (char_kind, c) in CharClasses::new(text.chars()) { + match c { + '\n' => { + if char_kind == FullCodeCharKind::InString { + buffer.push_str(&space_buffer); + } + space_buffer.clear(); + buffer.push('\n'); + } + _ if c.is_whitespace() => { + space_buffer.push(c); + } + _ => { + if !space_buffer.is_empty() { + buffer.push_str(&space_buffer); + space_buffer.clear(); + } + buffer.push(c); + } + } + } + buffer +} + +pub struct CharClasses +where + T: Iterator, + T::Item: RichChar, +{ + base: iter::Peekable, + status: CharClassesStatus, +} + +pub trait RichChar { + fn get_char(&self) -> char; +} + +impl RichChar for char { + fn get_char(&self) -> char { + *self + } +} + +impl RichChar for (usize, char) { + fn get_char(&self) -> char { + self.1 + } +} + +impl RichChar for (char, usize) { + fn get_char(&self) -> char { + self.0 + } +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum CharClassesStatus { + Normal, + LitString, + LitStringEscape, + LitChar, + LitCharEscape, + // The u32 is the nesting deepness of the comment + BlockComment(u32), + // Status when the '/' has been consumed, but not yet the '*', deepness is + // the new deepness (after the comment opening). + BlockCommentOpening(u32), + // Status when the '*' has been consumed, but not yet the '/', deepness is + // the new deepness (after the comment closing). + BlockCommentClosing(u32), + LineComment, +} + +/// Distinguish between functional part of code and comments +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum CodeCharKind { + Normal, + Comment, +} + +/// Distinguish between functional part of code and comments, +/// describing opening and closing of comments for ease when chunking +/// code from tagged characters +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum FullCodeCharKind { + Normal, + /// The first character of a comment, there is only one for a comment (always '/') + StartComment, + /// Any character inside a comment including the second character of comment + /// marks ("//", "/*") + InComment, + /// Last character of a comment, '\n' for a line comment, '/' for a block comment. + EndComment, + /// Inside a string. + InString, +} + +impl FullCodeCharKind { + pub fn is_comment(&self) -> bool { + match *self { + FullCodeCharKind::StartComment + | FullCodeCharKind::InComment + | FullCodeCharKind::EndComment => true, + _ => false, + } + } + + pub fn is_string(&self) -> bool { + *self == FullCodeCharKind::InString + } + + fn to_codecharkind(&self) -> CodeCharKind { + if self.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + } + } +} + +impl CharClasses +where + T: Iterator, + T::Item: RichChar, +{ + pub fn new(base: T) -> CharClasses { + CharClasses { + base: base.peekable(), + status: CharClassesStatus::Normal, + } + } +} + +impl Iterator for CharClasses +where + T: Iterator, + T::Item: RichChar, +{ + type Item = (FullCodeCharKind, T::Item); + + fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { + let item = self.base.next()?; + let chr = item.get_char(); + let mut char_kind = FullCodeCharKind::Normal; + self.status = match self.status { + CharClassesStatus::LitString => match chr { + '"' => CharClassesStatus::Normal, + '\\' => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitStringEscape + } + _ => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + }, + CharClassesStatus::LitStringEscape => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + CharClassesStatus::LitChar => match chr { + '\\' => CharClassesStatus::LitCharEscape, + '\'' => CharClassesStatus::Normal, + _ => CharClassesStatus::LitChar, + }, + CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, + CharClassesStatus::Normal => match chr { + '"' => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + '\'' => CharClassesStatus::LitChar, + '/' => match self.base.peek() { + Some(next) if next.get_char() == '*' => { + self.status = CharClassesStatus::BlockCommentOpening(1); + return Some((FullCodeCharKind::StartComment, item)); + } + Some(next) if next.get_char() == '/' => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::StartComment, item)); + } + _ => CharClassesStatus::Normal, + }, + _ => CharClassesStatus::Normal, + }, + CharClassesStatus::BlockComment(deepness) => { + assert_ne!(deepness, 0); + self.status = match self.base.peek() { + Some(next) if next.get_char() == '/' && chr == '*' => { + CharClassesStatus::BlockCommentClosing(deepness - 1) + } + Some(next) if next.get_char() == '*' && chr == '/' => { + CharClassesStatus::BlockCommentOpening(deepness + 1) + } + _ => CharClassesStatus::BlockComment(deepness), + }; + return Some((FullCodeCharKind::InComment, item)); + } + CharClassesStatus::BlockCommentOpening(deepness) => { + assert_eq!(chr, '*'); + self.status = CharClassesStatus::BlockComment(deepness); + return Some((FullCodeCharKind::InComment, item)); + } + CharClassesStatus::BlockCommentClosing(deepness) => { + assert_eq!(chr, '/'); + if deepness == 0 { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); + } else { + self.status = CharClassesStatus::BlockComment(deepness); + return Some((FullCodeCharKind::InComment, item)); + } + } + CharClassesStatus::LineComment => match chr { + '\n' => { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); + } + _ => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::InComment, item)); + } + }, + }; + Some((char_kind, item)) + } +} + +/// Iterator over functional and commented parts of a string. Any part of a string is either +/// functional code, either *one* block comment, either *one* line comment. Whitespace between +/// comments is functional code. Line comments contain their ending newlines. +struct UngroupedCommentCodeSlices<'a> { + slice: &'a str, + iter: iter::Peekable>>, +} + +impl<'a> UngroupedCommentCodeSlices<'a> { + fn new(code: &'a str) -> UngroupedCommentCodeSlices<'a> { + UngroupedCommentCodeSlices { + slice: code, + iter: CharClasses::new(code.char_indices()).peekable(), + } + } +} + +impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { + type Item = (CodeCharKind, usize, &'a str); + + fn next(&mut self) -> Option { + let (kind, (start_idx, _)) = self.iter.next()?; + match kind { + FullCodeCharKind::Normal | FullCodeCharKind::InString => { + // Consume all the Normal code + while let Some(&(char_kind, _)) = self.iter.peek() { + if char_kind.is_comment() { + break; + } + let _ = self.iter.next(); + } + } + FullCodeCharKind::StartComment => { + // Consume the whole comment + while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {} + } + _ => panic!(), + } + let slice = match self.iter.peek() { + Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx], + None => &self.slice[start_idx..], + }; + Some(( + if kind.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + }, + start_idx, + slice, + )) + } +} + +/// Iterator over an alternating sequence of functional and commented parts of +/// a string. The first item is always a, possibly zero length, subslice of +/// functional text. Line style comments contain their ending newlines. +pub struct CommentCodeSlices<'a> { + slice: &'a str, + last_slice_kind: CodeCharKind, + last_slice_end: usize, +} + +impl<'a> CommentCodeSlices<'a> { + pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { + CommentCodeSlices { + slice, + last_slice_kind: CodeCharKind::Comment, + last_slice_end: 0, + } + } +} + +impl<'a> Iterator for CommentCodeSlices<'a> { + type Item = (CodeCharKind, usize, &'a str); + + fn next(&mut self) -> Option { + if self.last_slice_end == self.slice.len() { + return None; + } + + let mut sub_slice_end = self.last_slice_end; + let mut first_whitespace = None; + let subslice = &self.slice[self.last_slice_end..]; + let mut iter = CharClasses::new(subslice.char_indices()); + + for (kind, (i, c)) in &mut iter { + let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal + && &subslice[..2] == "//" + && [' ', '\t'].contains(&c); + + if is_comment_connector && first_whitespace.is_none() { + first_whitespace = Some(i); + } + + if kind.to_codecharkind() == self.last_slice_kind && !is_comment_connector { + let last_index = match first_whitespace { + Some(j) => j, + None => i, + }; + sub_slice_end = self.last_slice_end + last_index; + break; + } + + if !is_comment_connector { + first_whitespace = None; + } + } + + if let (None, true) = (iter.next(), sub_slice_end == self.last_slice_end) { + // This was the last subslice. + sub_slice_end = match first_whitespace { + Some(i) => self.last_slice_end + i, + None => self.slice.len(), + }; + } + + let kind = match self.last_slice_kind { + CodeCharKind::Comment => CodeCharKind::Normal, + CodeCharKind::Normal => CodeCharKind::Comment, + }; + let res = ( + kind, + self.last_slice_end, + &self.slice[self.last_slice_end..sub_slice_end], + ); + self.last_slice_end = sub_slice_end; + self.last_slice_kind = kind; + + Some(res) + } +} + +/// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text +/// (if it fits in the width/offset, else return None), else return `new` +pub fn recover_comment_removed( + new: String, + span: Span, + context: &RewriteContext, +) -> Option { + let snippet = context.snippet(span); + if snippet != new && changed_comment_content(snippet, &new) { + // We missed some comments. Keep the original text. + Some(snippet.to_owned()) + } else { + Some(new) + } +} + +/// Return true if the two strings of code have the same payload of comments. +/// The payload of comments is everything in the string except: +/// - actual code (not comments) +/// - comment start/end marks +/// - whitespace +/// - '*' at the beginning of lines in block comments +fn changed_comment_content(orig: &str, new: &str) -> bool { + // Cannot write this as a fn since we cannot return types containing closures + let code_comment_content = |code| { + let slices = UngroupedCommentCodeSlices::new(code); + slices + .filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) + .flat_map(|(_, _, s)| CommentReducer::new(s)) + }; + let res = code_comment_content(orig).ne(code_comment_content(new)); + debug!( + "comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", + res, + orig, + new, + code_comment_content(orig).collect::(), + code_comment_content(new).collect::() + ); + res +} + +/// Iterator over the 'payload' characters of a comment. +/// It skips whitespace, comment start/end marks, and '*' at the beginning of lines. +/// The comment must be one comment, ie not more than one start mark (no multiple line comments, +/// for example). +struct CommentReducer<'a> { + is_block: bool, + at_start_line: bool, + iter: std::str::Chars<'a>, +} + +impl<'a> CommentReducer<'a> { + fn new(comment: &'a str) -> CommentReducer<'a> { + let is_block = comment.starts_with("/*"); + let comment = remove_comment_header(comment); + CommentReducer { + is_block, + at_start_line: false, // There are no supplementary '*' on the first line + iter: comment.chars(), + } + } +} + +impl<'a> Iterator for CommentReducer<'a> { + type Item = char; + fn next(&mut self) -> Option { + loop { + let mut c = self.iter.next()?; + if self.is_block && self.at_start_line { + while c.is_whitespace() { + c = self.iter.next()?; + } + // Ignore leading '*' + if c == '*' { + c = self.iter.next()?; + } + } else if c == '\n' { + self.at_start_line = true; + } + if !c.is_whitespace() { + return Some(c); + } + } + } +} + +fn remove_comment_header(comment: &str) -> &str { + if comment.starts_with("///") || comment.starts_with("//!") { + &comment[3..] + } else if comment.starts_with("//") { + &comment[2..] + } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) + || comment.starts_with("/*!") + { + &comment[3..comment.len() - 2] + } else { + assert!( + comment.starts_with("/*"), + format!("string '{}' is not a comment", comment) + ); + &comment[2..comment.len() - 2] + } +} + +#[cfg(test)] +mod test { + use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, + FindUncommented, FullCodeCharKind}; + use shape::{Indent, Shape}; + + #[test] + fn char_classes() { + let mut iter = CharClasses::new("//\n\n".chars()); + + assert_eq!((FullCodeCharKind::StartComment, '/'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::InComment, '/'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::EndComment, '\n'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::Normal, '\n'), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices() { + let input = "code(); /* test */ 1 + 1"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 8, "/* test */"), + iter.next().unwrap() + ); + assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices_two() { + let input = "// comment\n test();"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 0, "// comment\n"), + iter.next().unwrap() + ); + assert_eq!( + (CodeCharKind::Normal, 11, " test();"), + iter.next().unwrap() + ); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices_three() { + let input = "1 // comment\n // comment2\n\n"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 2, "// comment\n // comment2\n"), + iter.next().unwrap() + ); + assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn format_comments() { + let mut config: ::config::Config = Default::default(); + config.set().wrap_comments(true); + config.set().normalize_comments(true); + + let comment = rewrite_comment(" //test", + true, + Shape::legacy(100, Indent::new(0, 100)), + &config).unwrap(); + assert_eq!("/* test */", comment); + + let comment = rewrite_comment("// comment on a", + false, + Shape::legacy(10, Indent::empty()), + &config).unwrap(); + assert_eq!("// comment\n// on a", comment); + + let comment = rewrite_comment("// A multi line comment\n // between args.", + false, + Shape::legacy(60, Indent::new(0, 12)), + &config).unwrap(); + assert_eq!("// A multi line comment\n // between args.", comment); + + let input = "// comment"; + let expected = + "/* comment */"; + let comment = rewrite_comment(input, + true, + Shape::legacy(9, Indent::new(0, 69)), + &config).unwrap(); + assert_eq!(expected, comment); + + let comment = rewrite_comment("/* trimmed */", + true, + Shape::legacy(100, Indent::new(0, 100)), + &config).unwrap(); + assert_eq!("/* trimmed */", comment); + } + + // This is probably intended to be a non-test fn, but it is not used. I'm + // keeping it around unless it helps us test stuff. + fn uncommented(text: &str) -> String { + CharClasses::new(text.chars()) + .filter_map(|(s, c)| match s { + FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), + _ => None, + }) + .collect() + } + + #[test] + fn test_uncommented() { + assert_eq!(&uncommented("abc/*...*/"), "abc"); + assert_eq!( + &uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), + "..ac\n" + ); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); + } + + #[test] + fn test_contains_comment() { + assert_eq!(contains_comment("abc"), false); + assert_eq!(contains_comment("abc // qsdf"), true); + assert_eq!(contains_comment("abc /* kqsdf"), true); + assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); + } + + #[test] + fn test_find_uncommented() { + fn check(haystack: &str, needle: &str, expected: Option) { + assert_eq!(expected, haystack.find_uncommented(needle)); + } + + check("/*/ */test", "test", Some(6)); + check("//test\ntest", "test", Some(7)); + check("/* comment only */", "whatever", None); + check( + "/* comment */ some text /* more commentary */ result", + "result", + Some(46), + ); + check("sup // sup", "p", Some(2)); + check("sup", "x", None); + check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); + check("/*sup yo? \n sup*/ sup", "p", Some(20)); + check("hel/*lohello*/lo", "hello", None); + check("acb", "ab", None); + check(",/*A*/ ", ",", Some(0)); + check("abc", "abc", Some(0)); + check("/* abc */", "abc", None); + check("/**/abc/* */", "abc", Some(4)); + check("\"/* abc */\"", "abc", Some(4)); + check("\"/* abc", "abc", Some(4)); + } +} diff --git a/rustfmt-core/src/expr.rs b/rustfmt-core/src/expr.rs new file mode 100644 index 00000000000..1d572f642e2 --- /dev/null +++ b/rustfmt-core/src/expr.rs @@ -0,0 +1,2930 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::cmp::min; +use std::iter::repeat; + +use config::lists::*; +use syntax::{ast, ptr}; +use syntax::codemap::{BytePos, CodeMap, Span}; + +use chains::rewrite_chain; +use closures; +use codemap::{LineRangeUtils, SpanUtils}; +use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + rewrite_comment, rewrite_missing_comment, FindUncommented}; +use config::{Config, ControlBraceStyle, IndentStyle}; +use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, + struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; +use macros::{rewrite_macro, MacroArg, MacroPosition}; +use patterns::{can_be_overflowed_pat, TuplePatField}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use string::{rewrite_string, StringFormat}; +use types::{can_be_overflowed_type, rewrite_path, PathContext}; +use utils::{colon_spaces, contains_skip, count_newlines, extra_offset, first_line_width, + inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, + paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, + wrap_str}; +use vertical::rewrite_with_alignment; +use visitor::FmtVisitor; + +impl Rewrite for ast::Expr { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + format_expr(self, ExprType::SubExpression, context, shape) + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum ExprType { + Statement, + SubExpression, +} + +pub fn format_expr( + expr: &ast::Expr, + expr_type: ExprType, + context: &RewriteContext, + shape: Shape, +) -> Option { + skip_out_of_file_lines_range!(context, expr.span); + + if contains_skip(&*expr.attrs) { + return Some(context.snippet(expr.span()).to_owned()); + } + + let expr_rw = match expr.node { + ast::ExprKind::Array(ref expr_vec) => rewrite_array( + &ptr_vec_to_ref_vec(expr_vec), + mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi()), + context, + shape, + false, + ), + ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), + ast::ExprKind::Call(ref callee, ref args) => { + let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); + let callee_str = callee.rewrite(context, shape)?; + rewrite_call(context, &callee_str, args, inner_span, shape) + } + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), + ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { + // FIXME: format comments between operands and operator + rewrite_pair( + &**lhs, + &**rhs, + PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), + context, + shape, + context.config.binop_separator(), + ) + } + ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), + ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( + context, + path, + fields, + base.as_ref().map(|e| &**e), + expr.span, + shape, + ), + ast::ExprKind::Tup(ref items) => { + rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) + } + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) + .and_then(|control_flow| control_flow.rewrite(context, shape)), + ast::ExprKind::Block(ref block) => { + match expr_type { + ExprType::Statement => { + if is_unsafe_block(block) { + block.rewrite(context, shape) + } else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + // Rewrite block without trying to put it in a single line. + rw + } else { + let prefix = block_prefix(context, block, shape)?; + rewrite_block_with_visitor(context, &prefix, block, shape, true) + } + } + ExprType::SubExpression => block.rewrite(context, shape), + } + } + ast::ExprKind::Match(ref cond, ref arms) => { + rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs) + } + ast::ExprKind::Path(ref qself, ref path) => { + rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) + } + ast::ExprKind::Assign(ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, None, shape) + } + ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, Some(op), shape) + } + ast::ExprKind::Continue(ref opt_label) => { + let id_str = match *opt_label { + Some(label) => format!(" {}", label.ident), + None => String::new(), + }; + Some(format!("continue{}", id_str)) + } + ast::ExprKind::Break(ref opt_label, ref opt_expr) => { + let id_str = match *opt_label { + Some(label) => format!(" {}", label.ident), + None => String::new(), + }; + + if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) + } else { + Some(format!("break{}", id_str)) + } + } + ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, "yield ", &**expr, shape) + } else { + Some("yield".to_string()) + }, + ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { + closures::rewrite_closure( + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, + ) + } + ast::ExprKind::Try(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::TupField(..) + | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), + ast::ExprKind::Mac(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + }) + } + ast::ExprKind::Ret(None) => Some("return".to_owned()), + ast::ExprKind::Ret(Some(ref expr)) => { + rewrite_unary_prefix(context, "return ", &**expr, shape) + } + ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), + ast::ExprKind::AddrOf(mutability, ref expr) => { + rewrite_expr_addrof(context, mutability, expr, shape) + } + ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( + &**expr, + &**ty, + PairParts::new("", " as ", ""), + context, + shape, + SeparatorPlace::Front, + ), + ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( + &**expr, + &**ty, + PairParts::new("", ": ", ""), + context, + shape, + SeparatorPlace::Back, + ), + ast::ExprKind::Index(ref expr, ref index) => { + rewrite_index(&**expr, &**index, context, shape) + } + ast::ExprKind::Repeat(ref expr, ref repeats) => { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + rewrite_pair( + &**expr, + &**repeats, + PairParts::new(lbr, "; ", rbr), + context, + shape, + SeparatorPlace::Back, + ) + } + ast::ExprKind::Range(ref lhs, ref rhs, limits) => { + let delim = match limits { + ast::RangeLimits::HalfOpen => "..", + ast::RangeLimits::Closed => "..=", + }; + + fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { + match lhs.node { + ast::ExprKind::Lit(ref lit) => match lit.node { + ast::LitKind::FloatUnsuffixed(..) => { + context.snippet(lit.span).ends_with('.') + } + _ => false, + }, + _ => false, + } + } + + match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { + (Some(lhs), Some(rhs)) => { + let sp_delim = if context.config.spaces_around_ranges() { + format!(" {} ", delim) + } else if needs_space_before_range(context, lhs) { + format!(" {}", delim) + } else { + delim.to_owned() + }; + rewrite_pair( + &*lhs, + &*rhs, + PairParts::new("", &sp_delim, ""), + context, + shape, + context.config.binop_separator(), + ) + } + (None, Some(rhs)) => { + let sp_delim = if context.config.spaces_around_ranges() { + format!("{} ", delim) + } else { + delim.to_owned() + }; + rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) + } + (Some(lhs), None) => { + let sp_delim = if context.config.spaces_around_ranges() { + format!(" {}", delim) + } else { + delim.to_owned() + }; + rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) + } + (None, None) => Some(delim.to_owned()), + } + } + // We do not format these expressions yet, but they should still + // satisfy our width restrictions. + ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { + Some(context.snippet(expr.span).to_owned()) + } + ast::ExprKind::Catch(ref block) => { + if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { + rw + } else { + // 9 = `do catch ` + let budget = shape.width.checked_sub(9).unwrap_or(0); + Some(format!( + "{}{}", + "do catch ", + block.rewrite(context, Shape::legacy(budget, shape.indent))? + )) + } + } + }; + + expr_rw + .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) + .and_then(|expr_str| { + let attrs = outer_attributes(&expr.attrs); + let attrs_str = attrs.rewrite(context, shape)?; + let span = mk_sp( + attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), + expr.span.lo(), + ); + combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) + }) +} + +#[derive(new, Clone, Copy)] +pub struct PairParts<'a> { + prefix: &'a str, + infix: &'a str, + suffix: &'a str, +} + +pub fn rewrite_pair( + lhs: &LHS, + rhs: &RHS, + pp: PairParts, + context: &RewriteContext, + shape: Shape, + separator_place: SeparatorPlace, +) -> Option +where + LHS: Rewrite, + RHS: Rewrite, +{ + let lhs_overhead = match separator_place { + SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), + SeparatorPlace::Front => shape.used_width(), + }; + let lhs_shape = Shape { + width: context.budget(lhs_overhead), + ..shape + }; + let lhs_result = lhs.rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; + + // Try to the both lhs and rhs on the same line. + let rhs_orig_result = shape + .offset_left(last_line_width(&lhs_result) + pp.infix.len()) + .and_then(|s| s.sub_width(pp.suffix.len())) + .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); + if let Some(ref rhs_result) = rhs_orig_result { + // If the rhs looks like block expression, we allow it to stay on the same line + // with the lhs even if it is multi-lined. + let allow_same_line = rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); + if !rhs_result.contains('\n') || allow_same_line { + let one_line_width = last_line_width(&lhs_result) + pp.infix.len() + + first_line_width(rhs_result) + pp.suffix.len(); + if one_line_width <= shape.width { + return Some(format!( + "{}{}{}{}", + lhs_result, pp.infix, rhs_result, pp.suffix + )); + } + } + } + + // We have to use multiple lines. + // Re-evaluate the rhs because we have more space now: + let mut rhs_shape = match context.config.indent_style() { + IndentStyle::Visual => shape + .sub_width(pp.suffix.len() + pp.prefix.len())? + .visual_indent(pp.prefix.len()), + IndentStyle::Block => { + // Try to calculate the initial constraint on the right hand side. + let rhs_overhead = shape.rhs_overhead(context.config); + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(rhs_overhead)? + } + }; + let infix = match separator_place { + SeparatorPlace::Back => pp.infix.trim_right(), + SeparatorPlace::Front => pp.infix.trim_left(), + }; + if separator_place == SeparatorPlace::Front { + rhs_shape = rhs_shape.offset_left(infix.len())?; + } + let rhs_result = rhs.rewrite(context, rhs_shape)?; + let indent_str = rhs_shape.indent.to_string(context.config); + let infix_with_sep = match separator_place { + SeparatorPlace::Back => format!("{}\n{}", infix, indent_str), + SeparatorPlace::Front => format!("\n{}{}", indent_str, infix), + }; + Some(format!( + "{}{}{}{}", + lhs_result, infix_with_sep, rhs_result, pp.suffix + )) +} + +pub fn rewrite_array( + exprs: &[&T], + span: Span, + context: &RewriteContext, + shape: Shape, + trailing_comma: bool, +) -> Option { + let bracket_size = if context.config.spaces_within_parens_and_brackets() { + 2 // "[ " + } else { + 1 // "[" + }; + + let nested_shape = match context.config.indent_style() { + IndentStyle::Block => shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1)?, + IndentStyle::Visual => shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2)?, + }; + + let items = itemize_list( + context.codemap, + exprs.iter(), + "]", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, nested_shape), + span.lo(), + span.hi(), + false, + ).collect::>(); + + if items.is_empty() { + if context.config.spaces_within_parens_and_brackets() { + return Some("[ ]".to_string()); + } else { + return Some("[]".to_string()); + } + } + + let tactic = array_tactic(context, shape, nested_shape, exprs, &items, bracket_size); + let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro && !exprs.is_empty() { + let ends_with_bracket = context.snippet(span).ends_with(']'); + let bracket_offset = if ends_with_bracket { 1 } else { 0 }; + let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); + let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?; + if &snippet[last_char_index..last_char_index + 1] == "," { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } else if context.config.indent_style() == IndentStyle::Visual { + SeparatorTactic::Never + } else { + SeparatorTactic::Vertical + }, + separator_place: SeparatorPlace::Back, + shape: nested_shape, + ends_with_newline, + preserve_newline: false, + config: context.config, + }; + let list_str = write_list(&items, &fmt)?; + + let result = if context.config.indent_style() == IndentStyle::Visual + || tactic == DefinitiveListTactic::Horizontal + { + if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { + format!("[ {} ]", list_str) + } else { + format!("[{}]", list_str) + } + } else { + format!( + "[\n{}{}\n{}]", + nested_shape.indent.to_string(context.config), + list_str, + shape.block().indent.to_string(context.config) + ) + }; + + Some(result) +} + +fn array_tactic( + context: &RewriteContext, + shape: Shape, + nested_shape: Shape, + exprs: &[&T], + items: &[ListItem], + bracket_size: usize, +) -> DefinitiveListTactic { + let has_long_item = items + .iter() + .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); + + match context.config.indent_style() { + IndentStyle::Block => { + let tactic = match shape.width.checked_sub(2 * bracket_size) { + Some(width) => { + let tactic = ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ); + definitive_tactic(items, tactic, Separator::Comma, width) + } + None => DefinitiveListTactic::Vertical, + }; + if tactic == DefinitiveListTactic::Vertical && !has_long_item + && is_every_args_simple(exprs) + { + DefinitiveListTactic::Mixed + } else { + tactic + } + } + IndentStyle::Visual => { + if has_long_item || items.iter().any(ListItem::is_multiline) { + definitive_tactic( + items, + ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ), + Separator::Comma, + nested_shape.width, + ) + } else { + DefinitiveListTactic::Mixed + } + } + } +} + +fn nop_block_collapse(block_str: Option, budget: usize) -> Option { + debug!("nop_block_collapse {:?} {}", block_str, budget); + block_str.map(|block_str| { + if block_str.starts_with('{') && budget >= 2 + && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + { + "{}".to_owned() + } else { + block_str.to_owned() + } + }) +} + +fn rewrite_empty_block( + context: &RewriteContext, + block: &ast::Block, + shape: Shape, +) -> Option { + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 + { + return Some("{}".to_owned()); + } + + // If a block contains only a single-line comment, then leave it on one line. + let user_str = context.snippet(block.span); + let user_str = user_str.trim(); + if user_str.starts_with('{') && user_str.ends_with('}') { + let comment_str = user_str[1..user_str.len() - 1].trim(); + if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") + && comment_str.len() + 4 <= shape.width + { + return Some(format!("{{ {} }}", comment_str)); + } + } + + None +} + +fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> Option { + Some(match block.rules { + ast::BlockCheckMode::Unsafe(..) => { + let snippet = context.snippet(block.span); + let open_pos = snippet.find_uncommented("{")?; + // Extract comment between unsafe and block start. + let trimmed = &snippet[6..open_pos].trim(); + + if !trimmed.is_empty() { + // 9 = "unsafe {".len(), 7 = "unsafe ".len() + let budget = shape.width.checked_sub(9)?; + format!( + "unsafe {} ", + rewrite_comment( + trimmed, + true, + Shape::legacy(budget, shape.indent + 7), + context.config, + )? + ) + } else { + "unsafe ".to_owned() + } + } + ast::BlockCheckMode::Default => String::new(), + }) +} + +fn rewrite_single_line_block( + context: &RewriteContext, + prefix: &str, + block: &ast::Block, + shape: Shape, +) -> Option { + if is_simple_block(block, context.codemap) { + let expr_shape = shape.offset_left(last_line_width(prefix))?; + let expr_str = block.stmts[0].rewrite(context, expr_shape)?; + let result = format!("{}{{ {} }}", prefix, expr_str); + if result.len() <= shape.width && !result.contains('\n') { + return Some(result); + } + } + None +} + +pub fn rewrite_block_with_visitor( + context: &RewriteContext, + prefix: &str, + block: &ast::Block, + shape: Shape, + has_braces: bool, +) -> Option { + if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + return rw; + } + + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = shape.indent; + visitor.is_if_else_block = context.is_if_else_block; + match block.rules { + ast::BlockCheckMode::Unsafe(..) => { + let snippet = context.snippet(block.span); + let open_pos = snippet.find_uncommented("{")?; + visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) + } + ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), + } + + visitor.visit_block(block, None, has_braces); + Some(format!("{}{}", prefix, visitor.buffer)) +} + +impl Rewrite for ast::Block { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + // shape.width is used only for the single line case: either the empty block `{}`, + // or an unsafe expression `unsafe { e }`. + if let rw @ Some(_) = rewrite_empty_block(context, self, shape) { + return rw; + } + + let prefix = block_prefix(context, self, shape)?; + + let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); + if let Some(ref result_str) = result { + if result_str.lines().count() <= 3 { + if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { + return rw; + } + } + } + + result + } +} + +impl Rewrite for ast::Stmt { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + skip_out_of_file_lines_range!(context, self.span()); + + let result = match self.node { + ast::StmtKind::Local(ref local) => local.rewrite(context, shape), + ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { + let suffix = if semicolon_for_stmt(context, self) { + ";" + } else { + "" + }; + + let shape = shape.sub_width(suffix.len())?; + format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) + } + ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, + }; + result.and_then(|res| recover_comment_removed(res, self.span(), context)) + } +} + +// Rewrite condition if the given expression has one. +pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { + match expr.node { + ast::ExprKind::Match(ref cond, _) => { + // `match `cond` {` + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, + IndentStyle::Block => shape.offset_left(8)?, + }; + cond.rewrite(context, cond_shape) + } + _ => to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { + let alt_block_sep = + String::from("\n") + &shape.indent.block_only().to_string(context.config); + control_flow + .rewrite_cond(context, shape, &alt_block_sep) + .and_then(|rw| Some(rw.0)) + }), + } +} + +// Abstraction over control flow expressions +#[derive(Debug)] +struct ControlFlow<'a> { + cond: Option<&'a ast::Expr>, + block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, + label: Option, + pat: Option<&'a ast::Pat>, + keyword: &'a str, + matcher: &'a str, + connector: &'a str, + allow_single_line: bool, + // True if this is an `if` expression in an `else if` :-( hacky + nested_if: bool, + span: Span, +} + +fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { + match expr.node { + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( + cond, + None, + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )), + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { + Some(ControlFlow::new_if( + cond, + Some(pat), + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )) + } + ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { + Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) + } + ast::ExprKind::Loop(ref block, label) => { + Some(ControlFlow::new_loop(block, label, expr.span)) + } + ast::ExprKind::While(ref cond, ref block, label) => { + Some(ControlFlow::new_while(None, cond, block, label, expr.span)) + } + ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( + ControlFlow::new_while(Some(pat), cond, block, label, expr.span), + ), + _ => None, + } +} + +impl<'a> ControlFlow<'a> { + fn new_if( + cond: &'a ast::Expr, + pat: Option<&'a ast::Pat>, + block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, + allow_single_line: bool, + nested_if: bool, + span: Span, + ) -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block, + else_block, + label: None, + pat, + keyword: "if", + matcher: match pat { + Some(..) => "let", + None => "", + }, + connector: " =", + allow_single_line, + nested_if, + span, + } + } + + fn new_loop(block: &'a ast::Block, label: Option, span: Span) -> ControlFlow<'a> { + ControlFlow { + cond: None, + block, + else_block: None, + label, + pat: None, + keyword: "loop", + matcher: "", + connector: "", + allow_single_line: false, + nested_if: false, + span, + } + } + + fn new_while( + pat: Option<&'a ast::Pat>, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block, + else_block: None, + label, + pat, + keyword: "while", + matcher: match pat { + Some(..) => "let", + None => "", + }, + connector: " =", + allow_single_line: false, + nested_if: false, + span, + } + } + + fn new_for( + pat: &'a ast::Pat, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block, + else_block: None, + label, + pat: Some(pat), + keyword: "for", + matcher: "", + connector: " in", + allow_single_line: false, + nested_if: false, + span, + } + } + + fn rewrite_single_line( + &self, + pat_expr_str: &str, + context: &RewriteContext, + width: usize, + ) -> Option { + assert!(self.allow_single_line); + let else_block = self.else_block?; + let fixed_cost = self.keyword.len() + " { } else { }".len(); + + if let ast::ExprKind::Block(ref else_node) = else_block.node { + if !is_simple_block(self.block, context.codemap) + || !is_simple_block(else_node, context.codemap) + || pat_expr_str.contains('\n') + { + return None; + } + + let new_width = width.checked_sub(pat_expr_str.len() + fixed_cost)?; + let expr = &self.block.stmts[0]; + let if_str = expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; + + let new_width = new_width.checked_sub(if_str.len())?; + let else_expr = &else_node.stmts[0]; + let else_str = else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; + + if if_str.contains('\n') || else_str.contains('\n') { + return None; + } + + let result = format!( + "{} {} {{ {} }} else {{ {} }}", + self.keyword, pat_expr_str, if_str, else_str + ); + + if result.len() <= width { + return Some(result); + } + } + + None + } +} + +impl<'a> ControlFlow<'a> { + fn rewrite_cond( + &self, + context: &RewriteContext, + shape: Shape, + alt_block_sep: &str, + ) -> Option<(String, usize)> { + // Do not take the rhs overhead from the upper expressions into account + // when rewriting pattern. + let new_width = context + .config + .max_width() + .checked_sub(shape.used_width()) + .unwrap_or(0); + let fresh_shape = Shape { + width: new_width, + ..shape + }; + let constr_shape = if self.nested_if { + // We are part of an if-elseif-else chain. Our constraints are tightened. + // 7 = "} else " .len() + fresh_shape.offset_left(7)? + } else { + fresh_shape + }; + + let label_string = rewrite_label(self.label); + // 1 = space after keyword. + let offset = self.keyword.len() + label_string.len() + 1; + + let pat_expr_string = match self.cond { + Some(cond) => rewrite_pat_expr( + context, + self.pat, + cond, + self.matcher, + self.connector, + self.keyword, + constr_shape, + offset, + )?, + None => String::new(), + }; + + let brace_overhead = + if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { + // 2 = ` {` + 2 + } else { + 0 + }; + let one_line_budget = context + .config + .max_width() + .checked_sub(constr_shape.used_width() + offset + brace_overhead) + .unwrap_or(0); + let force_newline_brace = (pat_expr_string.contains('\n') + || pat_expr_string.len() > one_line_budget) + && !last_line_extendable(&pat_expr_string); + + // Try to format if-else on single line. + if self.allow_single_line + && context + .config + .width_heuristics() + .single_line_if_else_max_width > 0 + { + let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); + + if let Some(cond_str) = trial { + if cond_str.len() + <= context + .config + .width_heuristics() + .single_line_if_else_max_width + { + return Some((cond_str, 0)); + } + } + } + + let cond_span = if let Some(cond) = self.cond { + cond.span + } else { + mk_sp(self.block.span.lo(), self.block.span.lo()) + }; + + // `for event in event` + // Do not include label in the span. + let lo = self.label.map_or(self.span.lo(), |label| label.span.hi()); + let between_kwd_cond = mk_sp( + context + .codemap + .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), + self.pat.map_or(cond_span.lo(), |p| { + if self.matcher.is_empty() { + p.span.lo() + } else { + context.codemap.span_before(self.span, self.matcher.trim()) + } + }), + ); + + let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); + + let after_cond_comment = + extract_comment(mk_sp(cond_span.hi(), self.block.span.lo()), context, shape); + + let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { + "" + } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine + || force_newline_brace + { + alt_block_sep + } else { + " " + }; + + let used_width = if pat_expr_string.contains('\n') { + last_line_width(&pat_expr_string) + } else { + // 2 = spaces after keyword and condition. + label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 + }; + + Some(( + format!( + "{}{}{}{}{}", + label_string, + self.keyword, + between_kwd_cond_comment.as_ref().map_or( + if pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { + "" + } else { + " " + }, + |s| &**s, + ), + pat_expr_string, + after_cond_comment.as_ref().map_or(block_sep, |s| &**s) + ), + used_width, + )) + } +} + +impl<'a> Rewrite for ControlFlow<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("ControlFlow::rewrite {:?} {:?}", self, shape); + + let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); + let (cond_str, used_width) = self.rewrite_cond(context, shape, &alt_block_sep)?; + // If `used_width` is 0, it indicates that whole control flow is written in a single line. + if used_width == 0 { + return Some(cond_str); + } + + let block_width = shape.width.checked_sub(used_width).unwrap_or(0); + // This is used only for the empty block case: `{}`. So, we use 1 if we know + // we should avoid the single line case. + let block_width = if self.else_block.is_some() || self.nested_if { + min(1, block_width) + } else { + block_width + }; + let block_shape = Shape { + width: block_width, + ..shape + }; + let mut block_context = context.clone(); + block_context.is_if_else_block = self.else_block.is_some(); + let block_str = + rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?; + + let mut result = format!("{}{}", cond_str, block_str); + + if let Some(else_block) = self.else_block { + let shape = Shape::indented(shape.indent, context.config); + let mut last_in_chain = false; + let rewrite = match else_block.node { + // If the else expression is another if-else expression, prevent it + // from being formatted on a single line. + // Note how we're passing the original shape, as the + // cost of "else" should not cascade. + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { + ControlFlow::new_if( + cond, + Some(pat), + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo(), self.span.hi()), + ).rewrite(context, shape) + } + ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { + ControlFlow::new_if( + cond, + None, + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo(), self.span.hi()), + ).rewrite(context, shape) + } + _ => { + last_in_chain = true; + // When rewriting a block, the width is only used for single line + // blocks, passing 1 lets us avoid that. + let else_shape = Shape { + width: min(1, shape.width), + ..shape + }; + format_expr(else_block, ExprType::Statement, context, else_shape) + } + }; + + let between_kwd_else_block = mk_sp( + self.block.span.hi(), + context + .codemap + .span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), + ); + let between_kwd_else_block_comment = + extract_comment(between_kwd_else_block, context, shape); + + let after_else = mk_sp( + context + .codemap + .span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), + else_block.span.lo(), + ); + let after_else_comment = extract_comment(after_else, context, shape); + + let between_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => { + &*alt_block_sep + } + ControlBraceStyle::AlwaysSameLine => " ", + }; + let after_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, + _ => " ", + }; + + result.push_str(&format!( + "{}else{}", + between_kwd_else_block_comment + .as_ref() + .map_or(between_sep, |s| &**s), + after_else_comment.as_ref().map_or(after_sep, |s| &**s), + )); + result.push_str(&rewrite?); + } + + Some(result) + } +} + +fn rewrite_label(opt_label: Option) -> Cow<'static, str> { + match opt_label { + Some(label) => Cow::from(format!("{}: ", label.ident)), + None => Cow::from(""), + } +} + +fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { + match rewrite_missing_comment(span, shape, context) { + Some(ref comment) if !comment.is_empty() => Some(format!( + "\n{indent}{}\n{indent}", + comment, + indent = shape.indent.to_string(context.config) + )), + _ => None, + } +} + +pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { + let snippet = codemap.span_to_snippet(block.span).unwrap(); + contains_comment(&snippet) +} + +// Checks that a block contains no statements, an expression and no comments. +// FIXME: incorrectly returns false when comment is contained completely within +// the expression. +pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { + (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) + && !block_contains_comment(block, codemap)) +} + +/// Checks whether a block contains at most one statement or expression, and no comments. +pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { + block.stmts.len() <= 1 && !block_contains_comment(block, codemap) +} + +/// Checks whether a block contains no statements, expressions, or comments. +pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { + block.stmts.is_empty() && !block_contains_comment(block, codemap) +} + +pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::StmtKind::Expr(..) => true, + _ => false, + } +} + +pub fn is_unsafe_block(block: &ast::Block) -> bool { + if let ast::BlockCheckMode::Unsafe(..) = block.rules { + true + } else { + false + } +} + +// A simple wrapper type against ast::Arm. Used inside write_list(). +struct ArmWrapper<'a> { + pub arm: &'a ast::Arm, + // True if the arm is the last one in match expression. Used to decide on whether we should add + // trailing comma to the match arm when `config.trailing_comma() == Never`. + pub is_last: bool, +} + +impl<'a> ArmWrapper<'a> { + pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> { + ArmWrapper { arm, is_last } + } +} + +impl<'a> Rewrite for ArmWrapper<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_match_arm(context, self.arm, shape, self.is_last) + } +} + +fn rewrite_match( + context: &RewriteContext, + cond: &ast::Expr, + arms: &[ast::Arm], + shape: Shape, + span: Span, + attrs: &[ast::Attribute], +) -> Option { + // Do not take the rhs overhead from the upper expressions into account + // when rewriting match condition. + let cond_shape = Shape { + width: context.budget(shape.used_width()), + ..shape + }; + // 6 = `match ` + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => cond_shape.shrink_left(6)?, + IndentStyle::Block => cond_shape.offset_left(6)?, + }; + let cond_str = cond.rewrite(context, cond_shape)?; + let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine => &alt_block_sep, + _ if last_line_extendable(&cond_str) => " ", + // 2 = ` {` + _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => &alt_block_sep, + _ => " ", + }; + + let nested_indent_str = shape + .indent + .block_indent(context.config) + .to_string(context.config); + // Inner attributes. + let inner_attrs = &inner_attributes(attrs); + let inner_attrs_str = if inner_attrs.is_empty() { + String::new() + } else { + inner_attrs + .rewrite(context, shape) + .map(|s| format!("{}{}\n", nested_indent_str, s))? + }; + + let open_brace_pos = if inner_attrs.is_empty() { + let hi = if arms.is_empty() { + span.hi() + } else { + arms[0].span().lo() + }; + context.codemap.span_after(mk_sp(cond.span.hi(), hi), "{") + } else { + inner_attrs[inner_attrs.len() - 1].span().hi() + }; + + if arms.is_empty() { + let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); + if snippet.trim().is_empty() { + Some(format!("match {} {{}}", cond_str)) + } else { + // Empty match with comments or inner attributes? We are not going to bother, sorry ;) + Some(context.snippet(span).to_owned()) + } + } else { + Some(format!( + "match {}{}{{\n{}{}{}\n{}}}", + cond_str, + block_sep, + inner_attrs_str, + nested_indent_str, + rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, + shape.indent.to_string(context.config), + )) + } +} + +fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { + if is_last && config.trailing_comma() == SeparatorTactic::Never { + "" + } else if config.match_block_trailing_comma() { + "," + } else if let ast::ExprKind::Block(ref block) = body.node { + if let ast::BlockCheckMode::Default = block.rules { + "" + } else { + "," + } + } else { + "," + } +} + +fn rewrite_match_arms( + context: &RewriteContext, + arms: &[ast::Arm], + shape: Shape, + span: Span, + open_brace_pos: BytePos, +) -> Option { + let arm_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + + let arm_len = arms.len(); + let is_last_iter = repeat(false) + .take(arm_len.checked_sub(1).unwrap_or(0)) + .chain(repeat(true)); + let items = itemize_list( + context.codemap, + arms.iter() + .zip(is_last_iter) + .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), + "}", + "|", + |arm| arm.arm.span().lo(), + |arm| arm.arm.span().hi(), + |arm| arm.rewrite(context, arm_shape), + open_brace_pos, + span.hi(), + false, + ); + let arms_vec: Vec<_> = items.collect(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arm_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + + write_list(&arms_vec, &fmt) +} + +fn rewrite_match_arm( + context: &RewriteContext, + arm: &ast::Arm, + shape: Shape, + is_last: bool, +) -> Option { + let (missing_span, attrs_str) = if !arm.attrs.is_empty() { + if contains_skip(&arm.attrs) { + let (_, body) = flatten_arm_body(context, &arm.body); + // `arm.span()` does not include trailing comma, add it manually. + return Some(format!( + "{}{}", + context.snippet(arm.span()), + arm_comma(context.config, body, is_last), + )); + } + let missing_span = mk_sp( + arm.attrs[arm.attrs.len() - 1].span.hi(), + arm.pats[0].span.lo(), + ); + (missing_span, arm.attrs.rewrite(context, shape)?) + } else { + (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) + }; + let pats_str = + rewrite_match_pattern(context, &arm.pats, &arm.guard, shape).and_then(|pats_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &pats_str, + missing_span, + shape, + false, + ) + })?; + rewrite_match_body( + context, + &arm.body, + &pats_str, + shape, + arm.guard.is_some(), + is_last, + ) +} + +/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: +/// +/// [small, ntp]: +/// - single token +/// - `&[single-line, ntp]` +/// +/// [small]: +/// - `[small, ntp]` +/// - unary tuple constructor `([small, ntp])` +/// - `&[small]` +fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { + // We also require that the pattern is reasonably 'small' with its literal width. + pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) +} + +fn is_short_pattern_inner(pat: &ast::Pat) -> bool { + match pat.node { + ast::PatKind::Wild | ast::PatKind::Lit(_) => true, + ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), + ast::PatKind::Struct(..) + | ast::PatKind::Mac(..) + | ast::PatKind::Slice(..) + | ast::PatKind::Path(..) + | ast::PatKind::Range(..) => false, + ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, + ast::PatKind::TupleStruct(ref path, ref subpats, _) => { + path.segments.len() <= 1 && subpats.len() <= 1 + } + ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p), + } +} + +fn rewrite_match_pattern( + context: &RewriteContext, + pats: &[ptr::P], + guard: &Option>, + shape: Shape, +) -> Option { + // Patterns + // 5 = ` => {` + let pat_shape = shape.sub_width(5)?; + + let pat_strs = pats.iter() + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>()?; + + let use_mixed_layout = pats.iter() + .zip(pat_strs.iter()) + .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let tactic = if use_mixed_layout { + DefinitiveListTactic::Mixed + } else { + definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + pat_shape.width, + ) + }; + let fmt = ListFormatting { + tactic, + separator: " |", + trailing_separator: SeparatorTactic::Never, + separator_place: context.config.binop_separator(), + shape: pat_shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + let pats_str = write_list(&items, &fmt)?; + + // Guard + let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; + + Some(format!("{}{}", pats_str, guard_str)) +} + +// (extend, body) +// @extend: true if the arm body can be put next to `=>` +// @body: flattened body, if the body is block with a single expression +fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { + match body.node { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { + ( + !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), + &*expr, + ) + } else { + (false, &*body) + } + } + _ => ( + !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), + &*body, + ), + } +} + +fn rewrite_match_body( + context: &RewriteContext, + body: &ptr::P, + pats_str: &str, + shape: Shape, + has_guard: bool, + is_last: bool, +) -> Option { + let (extend, body) = flatten_arm_body(context, body); + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { + (true, is_empty_block(block, context.codemap)) + } else { + (false, false) + }; + + let comma = arm_comma(context.config, body, is_last); + let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); + let alt_block_sep = alt_block_sep.as_str(); + + let combine_orig_body = |body_str: &str| { + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, + _ => " ", + }; + + Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) + }; + + let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; + let next_line_indent = if !is_block || is_empty_block { + shape.indent.block_indent(context.config) + } else { + shape.indent + }; + let combine_next_line_body = |body_str: &str| { + if is_block { + return Some(format!( + "{} =>\n{}{}", + pats_str, + next_line_indent.to_string(context.config), + body_str + )); + } + + let indent_str = shape.indent.to_string(context.config); + let nested_indent_str = next_line_indent.to_string(context.config); + let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { + let comma = if context.config.match_block_trailing_comma() { + "," + } else { + "" + }; + ("{", format!("\n{}}}{}", indent_str, comma)) + } else { + ("", String::from(",")) + }; + + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine => format!("{}{}\n", alt_block_sep, body_prefix), + _ if body_prefix.is_empty() => "\n".to_owned(), + _ if forbid_same_line => format!("{}{}\n", alt_block_sep, body_prefix), + _ => format!(" {}\n", body_prefix), + } + &nested_indent_str; + + Some(format!( + "{} =>{}{}{}", + pats_str, block_sep, body_str, body_suffix + )) + }; + + // Let's try and get the arm body on the same line as the condition. + // 4 = ` => `.len() + let orig_body_shape = shape + .offset_left(extra_offset(pats_str, shape) + 4) + .and_then(|shape| shape.sub_width(comma.len())); + let orig_body = if let Some(body_shape) = orig_body_shape { + let rewrite = nop_block_collapse( + format_expr(body, ExprType::Statement, context, body_shape), + body_shape.width, + ); + + match rewrite { + Some(ref body_str) + if !forbid_same_line + && (is_block + || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => + { + return combine_orig_body(body_str); + } + _ => rewrite, + } + } else { + None + }; + let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); + + // Try putting body on the next line and see if it looks better. + let next_line_body_shape = Shape::indented(next_line_indent, context.config); + let next_line_body = nop_block_collapse( + format_expr(body, ExprType::Statement, context, next_line_body_shape), + next_line_body_shape.width, + ); + match (orig_body, next_line_body) { + (Some(ref orig_str), Some(ref next_line_str)) + if forbid_same_line || prefer_next_line(orig_str, next_line_str) => + { + combine_next_line_body(next_line_str) + } + (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { + combine_orig_body(orig_str) + } + (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { + combine_next_line_body(next_line_str) + } + (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), + (None, None) => None, + (Some(ref orig_str), _) => combine_orig_body(orig_str), + } +} + +// The `if ...` guard on a match arm. +fn rewrite_guard( + context: &RewriteContext, + guard: &Option>, + shape: Shape, + // The amount of space used up on this line for the pattern in + // the arm (excludes offset). + pattern_width: usize, +) -> Option { + if let Some(ref guard) = *guard { + // First try to fit the guard string on the same line as the pattern. + // 4 = ` if `, 5 = ` => {` + let cond_shape = shape + .offset_left(pattern_width + 4) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { + return Some(format!(" if {}", cond_str)); + } + } + } + + // Not enough space to put the guard after the pattern, try a newline. + // 3 = `if `, 5 = ` => {` + let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) + .offset_left(3) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + return Some(format!( + "\n{}if {}", + cond_shape.indent.to_string(context.config), + cond_str + )); + } + } + + None + } else { + Some(String::new()) + } +} + +fn rewrite_pat_expr( + context: &RewriteContext, + pat: Option<&ast::Pat>, + expr: &ast::Expr, + matcher: &str, + // Connecting piece between pattern and expression, + // *without* trailing space. + connector: &str, + keyword: &str, + shape: Shape, + offset: usize, +) -> Option { + debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); + let cond_shape = shape.offset_left(offset)?; + if let Some(pat) = pat { + let matcher = if matcher.is_empty() { + matcher.to_owned() + } else { + format!("{} ", matcher) + }; + let pat_shape = cond_shape + .offset_left(matcher.len())? + .sub_width(connector.len())?; + let pat_string = pat.rewrite(context, pat_shape)?; + let result = format!("{}{}{}", matcher, pat_string, connector); + return rewrite_assign_rhs(context, result, expr, cond_shape); + } + + let expr_rw = expr.rewrite(context, cond_shape); + // The expression may (partially) fit on the current line. + // We do not allow splitting between `if` and condition. + if keyword == "if" || expr_rw.is_some() { + return expr_rw; + } + + // The expression won't fit on the current line, jump to next. + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let nested_indent_str = nested_shape.indent.to_string(context.config); + expr.rewrite(context, nested_shape) + .map(|expr_rw| format!("\n{}{}", nested_indent_str, expr_rw)) +} + +fn can_extend_match_arm_body(body: &ast::Expr) -> bool { + match body.node { + // We do not allow `if` to stay on the same line, since we could easily mistake + // `pat => if cond { ... }` and `pat if cond => { ... }`. + ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, + ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Closure(..) + | ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), + _ => false, + } +} + +pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { + match l.node { + ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), + _ => wrap_str( + context.snippet(l.span).to_owned(), + context.config.max_width(), + shape, + ), + } +} + +fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { + let string_lit = context.snippet(span); + + if !context.config.format_strings() { + if string_lit + .lines() + .rev() + .skip(1) + .all(|line| line.ends_with('\\')) + { + let new_indent = shape.visual_indent(1).indent; + let indented_string_lit = String::from( + string_lit + .lines() + .map(|line| { + format!( + "{}{}", + new_indent.to_string(context.config), + line.trim_left() + ) + }) + .collect::>() + .join("\n") + .trim_left(), + ); + return wrap_str(indented_string_lit, context.config.max_width(), shape); + } else { + return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); + } + } + + // Remove the quote characters. + let str_lit = &string_lit[1..string_lit.len() - 1]; + + rewrite_string( + str_lit, + &StringFormat::new(shape.visual_indent(0), context.config), + None, + ) +} + +/// A list of `format!`-like macros, that take a long format string and a list of arguments to +/// format. +/// +/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of +/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, +/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). +const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ + // format! like macros + // From the Rust Standard Library. + ("eprint!", 0), + ("eprintln!", 0), + ("format!", 0), + ("format_args!", 0), + ("print!", 0), + ("println!", 0), + ("panic!", 0), + ("unreachable!", 0), + // From the `log` crate. + ("debug!", 0), + ("error!", 0), + ("info!", 0), + ("warn!", 0), + // write! like macros + ("assert!", 1), + ("debug_assert!", 1), + ("write!", 1), + ("writeln!", 1), + // assert_eq! like macros + ("assert_eq!", 2), + ("assert_ne!", 2), + ("debug_assert_eq!", 2), + ("debug_assert_ne!", 2), +]; + +pub fn rewrite_call( + context: &RewriteContext, + callee: &str, + args: &[ptr::P], + span: Span, + shape: Shape, +) -> Option { + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + false + }; + rewrite_call_inner( + context, + callee, + &ptr_vec_to_ref_vec(args), + span, + shape, + context.config.width_heuristics().fn_call_width, + force_trailing_comma, + ) +} + +pub fn rewrite_call_inner<'a, T>( + context: &RewriteContext, + callee_str: &str, + args: &[&T], + span: Span, + shape: Shape, + args_max_width: usize, + force_trailing_comma: bool, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + // 2 = `( `, 1 = `(` + let paren_overhead = if context.config.spaces_within_parens_and_brackets() { + 2 + } else { + 1 + }; + let used_width = extra_offset(callee_str, shape); + let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; + + // 1 = "(" or ")" + let one_line_shape = shape + .offset_left(last_line_width(callee_str) + 1)? + .sub_width(1)?; + let nested_shape = shape_from_indent_style( + context, + shape, + used_width + 2 * paren_overhead, + used_width + paren_overhead, + )?; + + let span_lo = context.codemap.span_after(span, "("); + let args_span = mk_sp(span_lo, span.hi()); + + let (extendable, list_str) = rewrite_call_args( + context, + args, + args_span, + one_line_shape, + nested_shape, + one_line_width, + args_max_width, + force_trailing_comma, + callee_str, + )?; + + if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { + let mut new_context = context.clone(); + new_context.use_block = true; + return rewrite_call_inner( + &new_context, + callee_str, + args, + span, + shape, + args_max_width, + force_trailing_comma, + ); + } + + let args_shape = shape.sub_width(last_line_width(callee_str))?; + Some(format!( + "{}{}", + callee_str, + wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) + )) +} + +fn need_block_indent(s: &str, shape: Shape) -> bool { + s.lines().skip(1).any(|s| { + s.find(|c| !char::is_whitespace(c)) + .map_or(false, |w| w + 1 < shape.indent.width()) + }) +} + +fn rewrite_call_args<'a, T>( + context: &RewriteContext, + args: &[&T], + span: Span, + one_line_shape: Shape, + nested_shape: Shape, + one_line_width: usize, + args_max_width: usize, + force_trailing_comma: bool, + callee_str: &str, +) -> Option<(bool, String)> +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + let items = itemize_list( + context.codemap, + args.iter(), + ")", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, nested_shape), + span.lo(), + span.hi(), + true, + ); + let mut item_vec: Vec<_> = items.collect(); + + // Try letting the last argument overflow to the next line with block + // indentation. If its first line fits on one line with the other arguments, + // we format the function arguments horizontally. + let tactic = try_overflow_last_arg( + context, + &mut item_vec, + &args[..], + one_line_shape, + nested_shape, + one_line_width, + args_max_width, + callee_str, + ); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if force_trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro || !context.use_block_indent() { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape: nested_shape, + ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, + preserve_newline: false, + config: context.config, + }; + + write_list(&item_vec, &fmt) + .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str)) +} + +fn try_overflow_last_arg<'a, T>( + context: &RewriteContext, + item_vec: &mut Vec, + args: &[&T], + one_line_shape: Shape, + nested_shape: Shape, + one_line_width: usize, + args_max_width: usize, + callee_str: &str, +) -> DefinitiveListTactic +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + // 1 = "(" + let combine_arg_with_callee = + callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; + let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); + + // Replace the last item with its first line to see if it fits with + // first arguments. + let placeholder = if overflow_last { + let mut context = context.clone(); + if !combine_arg_with_callee { + if let Some(expr) = args[args.len() - 1].to_expr() { + if let ast::ExprKind::MethodCall(..) = expr.node { + context.force_one_line_chain = true; + } + } + } + last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { + rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) + }) + } else { + None + }; + + let mut tactic = definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ); + + // Replace the stub with the full overflowing last argument if the rewrite + // succeeded and its first line fits with the other arguments. + match (overflow_last, tactic, placeholder) { + (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) if args.len() == 1 => { + // When we are rewriting a nested function call, we restrict the + // bugdet for the inner function to avoid them being deeply nested. + // However, when the inner function has a prefix or a suffix + // (e.g. `foo() as u32`), this budget reduction may produce poorly + // formatted code, where a prefix or a suffix being left on its own + // line. Here we explicitlly check those cases. + if count_newlines(overflowed) == 1 { + let rw = args.last() + .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); + let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); + if no_newline { + item_vec[args.len() - 1].item = rw; + } else { + item_vec[args.len() - 1].item = Some(overflowed.to_owned()); + } + } else { + item_vec[args.len() - 1].item = Some(overflowed.to_owned()); + } + } + (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { + item_vec[args.len() - 1].item = placeholder; + } + _ if args.len() >= 1 => { + item_vec[args.len() - 1].item = args.last() + .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); + + let default_tactic = || { + definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ) + }; + + // Use horizontal layout for a function with a single argument as long as + // everything fits in a single line. + if args.len() == 1 + && args_max_width != 0 // Vertical layout is forced. + && !item_vec[0].has_comment() + && !item_vec[0].inner_as_ref().contains('\n') + && ::lists::total_item_width(&item_vec[0]) <= one_line_width + { + tactic = DefinitiveListTactic::Horizontal; + } else { + tactic = default_tactic(); + + if tactic == DefinitiveListTactic::Vertical { + if let Some((all_simple, num_args_before)) = + maybe_get_args_offset(callee_str, args) + { + let one_line = all_simple + && definitive_tactic( + &item_vec[..num_args_before], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ) == DefinitiveListTactic::Horizontal + && definitive_tactic( + &item_vec[num_args_before + 1..], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ) == DefinitiveListTactic::Horizontal; + + if one_line { + tactic = DefinitiveListTactic::SpecialMacro(num_args_before); + }; + } + } + } + } + _ => (), + } + + tactic +} + +fn is_simple_arg(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Lit(..) => true, + ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Cast(ref expr, _) + | ast::ExprKind::Field(ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::TupField(ref expr, _) + | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr), + ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { + is_simple_arg(lhs) && is_simple_arg(rhs) + } + _ => false, + } +} + +fn is_every_args_simple(lists: &[&T]) -> bool { + lists + .iter() + .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) +} + +/// In case special-case style is required, returns an offset from which we start horizontal layout. +fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { + if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST + .iter() + .find(|&&(s, _)| s == callee_str) + { + let all_simple = args.len() > num_args_before && is_every_args_simple(args); + + Some((all_simple, num_args_before)) + } else { + None + } +} + +/// Returns a shape for the last argument which is going to be overflowed. +fn last_arg_shape( + lists: &[&T], + items: &[ListItem], + shape: Shape, + args_max_width: usize, +) -> Option +where + T: Rewrite + Spanned + ToExpr, +{ + let is_nested_call = lists + .iter() + .next() + .and_then(|item| item.to_expr()) + .map_or(false, is_nested_call); + if items.len() == 1 && !is_nested_call { + return Some(shape); + } + let offset = items.iter().rev().skip(1).fold(0, |acc, i| { + // 2 = ", " + acc + 2 + i.inner_as_ref().len() + }); + Shape { + width: min(args_max_width, shape.width), + ..shape + }.offset_left(offset) +} + +fn rewrite_last_arg_with_overflow<'a, T>( + context: &RewriteContext, + args: &[&T], + last_item: &mut ListItem, + shape: Shape, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + let last_arg = args[args.len() - 1]; + let rewrite = if let Some(expr) = last_arg.to_expr() { + match expr.node { + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + ast::ExprKind::Closure(..) => { + // If the argument consists of multiple closures, we do not overflow + // the last closure. + if closures::args_have_many_closure(args) { + None + } else { + closures::rewrite_last_closure(context, expr, shape) + } + } + _ => expr.rewrite(context, shape), + } + } else { + last_arg.rewrite(context, shape) + }; + + if let Some(rewrite) = rewrite { + let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); + last_item.item = rewrite_first_line; + Some(rewrite) + } else { + None + } +} + +fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + args.last() + .map_or(false, |x| x.can_be_overflowed(context, args.len())) +} + +pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { + match expr.node { + ast::ExprKind::Match(..) => { + (context.use_block_indent() && args_len == 1) + || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) + } + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => { + context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 + } + ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { + context.use_block_indent() + || context.config.indent_style() == IndentStyle::Visual && args_len > 1 + } + ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), + _ => false, + } +} + +fn is_nested_call(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), + _ => false, + } +} + +pub fn wrap_args_with_parens( + context: &RewriteContext, + args_str: &str, + is_extendable: bool, + shape: Shape, + nested_shape: Shape, +) -> String { + if !context.use_block_indent() + || (context.inside_macro && !args_str.contains('\n') + && args_str.len() + paren_overhead(context) <= shape.width) || is_extendable + { + if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() { + format!("( {} )", args_str) + } else { + format!("({})", args_str) + } + } else { + format!( + "(\n{}{}\n{})", + nested_shape.indent.to_string(context.config), + args_str, + shape.block().indent.to_string(context.config) + ) + } +} + +/// Return true if a function call or a method call represented by the given span ends with a +/// trailing comma. This function is used when rewriting macro, as adding or removing a trailing +/// comma from macro can potentially break the code. +fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { + let mut encountered_closing_paren = false; + for c in context.snippet(span).chars().rev() { + match c { + ',' => return true, + ')' => if encountered_closing_paren { + return false; + } else { + encountered_closing_paren = true; + }, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + false +} + +fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { + debug!("rewrite_paren, shape: {:?}", shape); + let total_paren_overhead = paren_overhead(context); + let paren_overhead = total_paren_overhead / 2; + let sub_shape = shape + .offset_left(paren_overhead) + .and_then(|s| s.sub_width(paren_overhead))?; + + let paren_wrapper = |s: &str| { + if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { + format!("( {} )", s) + } else { + format!("({})", s) + } + }; + + let subexpr_str = subexpr.rewrite(context, sub_shape)?; + debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); + + if subexpr_str.contains('\n') + || first_line_width(&subexpr_str) + total_paren_overhead <= shape.width + { + Some(paren_wrapper(&subexpr_str)) + } else { + None + } +} + +fn rewrite_index( + expr: &ast::Expr, + index: &ast::Expr, + context: &RewriteContext, + shape: Shape, +) -> Option { + let expr_str = expr.rewrite(context, shape)?; + + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + + let offset = last_line_width(&expr_str) + lbr.len(); + let rhs_overhead = shape.rhs_overhead(context.config); + let index_shape = if expr_str.contains('\n') { + Shape::legacy(context.config.max_width(), shape.indent) + .offset_left(offset) + .and_then(|shape| shape.sub_width(rbr.len() + rhs_overhead)) + } else { + shape.visual_indent(offset).sub_width(offset + rbr.len()) + }; + let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); + + // Return if index fits in a single line. + match orig_index_rw { + Some(ref index_str) if !index_str.contains('\n') => { + return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); + } + _ => (), + } + + // Try putting index on the next line and see if it fits in a single line. + let indent = shape.indent.block_indent(context.config); + let index_shape = Shape::indented(indent, context.config).offset_left(lbr.len())?; + let index_shape = index_shape.sub_width(rbr.len() + rhs_overhead)?; + let new_index_rw = index.rewrite(context, index_shape); + match (orig_index_rw, new_index_rw) { + (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent.to_string(context.config), + lbr, + new_index_str, + rbr + )), + (None, Some(ref new_index_str)) => Some(format!( + "{}\n{}{}{}{}", + expr_str, + indent.to_string(context.config), + lbr, + new_index_str, + rbr + )), + (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), + _ => None, + } +} + +fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { + if base.is_some() { + return false; + } + + fields.iter().all(|field| !field.is_shorthand) +} + +fn rewrite_struct_lit<'a>( + context: &RewriteContext, + path: &ast::Path, + fields: &'a [ast::Field], + base: Option<&'a ast::Expr>, + span: Span, + shape: Shape, +) -> Option { + debug!("rewrite_struct_lit: shape {:?}", shape); + + enum StructLitField<'a> { + Regular(&'a ast::Field), + Base(&'a ast::Expr), + } + + // 2 = " {".len() + let path_shape = shape.sub_width(2)?; + let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; + + if fields.is_empty() && base.is_none() { + return Some(format!("{} {{}}", path_str)); + } + + // Foo { a: Foo } - indent is +3, width is -5. + let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; + + let one_line_width = h_shape.map_or(0, |shape| shape.width); + let body_lo = context.codemap.span_after(span, "{"); + let fields_str = if struct_lit_can_be_aligned(fields, &base) + && context.config.struct_field_align_threshold() > 0 + { + rewrite_with_alignment( + fields, + context, + shape, + mk_sp(body_lo, span.hi()), + one_line_width, + )? + } else { + let field_iter = fields + .into_iter() + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); + + let span_lo = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span().lo(), + StructLitField::Base(expr) => { + let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }; + let span_hi = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span().hi(), + StructLitField::Base(expr) => expr.span.hi(), + }; + let rewrite = |item: &StructLitField| match *item { + StructLitField::Regular(field) => { + // The 1 taken from the v_budget is for the comma. + rewrite_field(context, field, v_shape.sub_width(1)?, 0) + } + StructLitField::Base(expr) => { + // 2 = .. + expr.rewrite(context, v_shape.offset_left(2)?) + .map(|s| format!("..{}", s)) + } + }; + + let items = itemize_list( + context.codemap, + field_iter, + "}", + ",", + span_lo, + span_hi, + rewrite, + body_lo, + span.hi(), + false, + ); + let item_vec = items.collect::>(); + + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); + + write_list(&item_vec, &fmt)? + }; + + let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + Some(format!("{} {{{}}}", path_str, fields_str)) + + // FIXME if context.config.indent_style() == Visual, but we run out + // of space, we should fall back to BlockIndent. +} + +pub fn wrap_struct_field( + context: &RewriteContext, + fields_str: &str, + shape: Shape, + nested_shape: Shape, + one_line_width: usize, +) -> String { + if context.config.indent_style() == IndentStyle::Block + && (fields_str.contains('\n') || !context.config.struct_lit_single_line() + || fields_str.len() > one_line_width) + { + format!( + "\n{}{}\n{}", + nested_shape.indent.to_string(context.config), + fields_str, + shape.indent.to_string(context.config) + ) + } else { + // One liner or visual indent. + format!(" {} ", fields_str) + } +} + +pub fn struct_lit_field_separator(config: &Config) -> &str { + colon_spaces(config.space_before_colon(), config.space_after_colon()) +} + +pub fn rewrite_field( + context: &RewriteContext, + field: &ast::Field, + shape: Shape, + prefix_max_width: usize, +) -> Option { + if contains_skip(&field.attrs) { + return Some(context.snippet(field.span()).to_owned()); + } + let mut attrs_str = field.attrs.rewrite(context, shape)?; + if !attrs_str.is_empty() { + attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); + }; + let name = field.ident.node.to_string(); + if field.is_shorthand { + Some(attrs_str + &name) + } else { + let mut separator = String::from(struct_lit_field_separator(context.config)); + for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { + separator.push(' '); + } + let overhead = name.len() + separator.len(); + let expr_shape = shape.offset_left(overhead)?; + let expr = field.expr.rewrite(context, expr_shape); + + match expr { + Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { + Some(attrs_str + &name) + } + Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), + None => { + let expr_offset = shape.indent.block_indent(context.config); + let expr = field + .expr + .rewrite(context, Shape::indented(expr_offset, context.config)); + expr.map(|s| { + format!( + "{}{}:\n{}{}", + attrs_str, + name, + expr_offset.to_string(context.config), + s + ) + }) + } + } + } +} + +fn shape_from_indent_style( + context: &RewriteContext, + shape: Shape, + overhead: usize, + offset: usize, +) -> Option { + if context.use_block_indent() { + // 1 = "," + shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1) + } else { + shape.visual_indent(offset).sub_width(overhead) + } +} + +fn rewrite_tuple_in_visual_indent_style<'a, T>( + context: &RewriteContext, + items: &[&T], + span: Span, + shape: Shape, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + let mut items = items.iter(); + // In case of length 1, need a trailing comma + debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); + if items.len() == 1 { + // 3 = "(" + ",)" + let nested_shape = shape.sub_width(3)?.visual_indent(1); + return items + .next() + .unwrap() + .rewrite(context, nested_shape) + .map(|s| { + if context.config.spaces_within_parens_and_brackets() { + format!("( {}, )", s) + } else { + format!("({},)", s) + } + }); + } + + let list_lo = context.codemap.span_after(span, "("); + let nested_shape = shape.sub_width(2)?.visual_indent(1); + let items = itemize_list( + context.codemap, + items, + ")", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, nested_shape), + list_lo, + span.hi() - BytePos(1), + false, + ); + let item_vec: Vec<_> = items.collect(); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ); + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + let list_str = write_list(&item_vec, &fmt)?; + + if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { + Some(format!("( {} )", list_str)) + } else { + Some(format!("({})", list_str)) + } +} + +pub fn rewrite_tuple<'a, T>( + context: &RewriteContext, + items: &[&T], + span: Span, + shape: Shape, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + debug!("rewrite_tuple {:?}", shape); + if context.use_block_indent() { + // We use the same rule as function calls for rewriting tuples. + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + items.len() == 1 + }; + rewrite_call_inner( + context, + &String::new(), + items, + span, + shape, + context.config.width_heuristics().fn_call_width, + force_trailing_comma, + ) + } else { + rewrite_tuple_in_visual_indent_style(context, items, span, shape) + } +} + +pub fn rewrite_unary_prefix( + context: &RewriteContext, + prefix: &str, + rewrite: &R, + shape: Shape, +) -> Option { + rewrite + .rewrite(context, shape.offset_left(prefix.len())?) + .map(|r| format!("{}{}", prefix, r)) +} + +// FIXME: this is probably not correct for multi-line Rewrites. we should +// subtract suffix.len() from the last line budget, not the first! +pub fn rewrite_unary_suffix( + context: &RewriteContext, + suffix: &str, + rewrite: &R, + shape: Shape, +) -> Option { + rewrite + .rewrite(context, shape.sub_width(suffix.len())?) + .map(|mut r| { + r.push_str(suffix); + r + }) +} + +fn rewrite_unary_op( + context: &RewriteContext, + op: &ast::UnOp, + expr: &ast::Expr, + shape: Shape, +) -> Option { + // For some reason, an UnOp is not spanned like BinOp! + let operator_str = match *op { + ast::UnOp::Deref => "*", + ast::UnOp::Not => "!", + ast::UnOp::Neg => "-", + }; + rewrite_unary_prefix(context, operator_str, expr, shape) +} + +fn rewrite_assignment( + context: &RewriteContext, + lhs: &ast::Expr, + rhs: &ast::Expr, + op: Option<&ast::BinOp>, + shape: Shape, +) -> Option { + let operator_str = match op { + Some(op) => context.snippet(op.span), + None => "=", + }; + + // 1 = space between lhs and operator. + let lhs_shape = shape.sub_width(operator_str.len() + 1)?; + let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); + + rewrite_assign_rhs(context, lhs_str, rhs, shape) +} + +// The left hand side must contain everything up to, and including, the +// assignment operator. +pub fn rewrite_assign_rhs, R: Rewrite>( + context: &RewriteContext, + lhs: S, + ex: &R, + shape: Shape, +) -> Option { + let lhs = lhs.into(); + let last_line_width = last_line_width(&lhs) + .checked_sub(if lhs.contains('\n') { + shape.indent.width() + } else { + 0 + }) + .unwrap_or(0); + // 1 = space between operator and rhs. + let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { + width: 0, + offset: shape.offset + last_line_width + 1, + ..shape + }); + let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; + Some(lhs + &rhs) +} + +pub fn choose_rhs( + context: &RewriteContext, + expr: &R, + shape: Shape, + orig_rhs: Option, +) -> Option { + match orig_rhs { + Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { + Some(format!(" {}", new_str)) + } + _ => { + // Expression did not fit on the same line as the identifier. + // Try splitting the line and see if that works better. + let new_shape = + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(shape.rhs_overhead(context.config))?; + let new_rhs = expr.rewrite(context, new_shape); + let new_indent_str = &new_shape.indent.to_string(context.config); + + match (orig_rhs, new_rhs) { + (Some(ref orig_rhs), Some(ref new_rhs)) + if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) + .is_none() => + { + Some(format!(" {}", orig_rhs)) + } + (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { + Some(format!("\n{}{}", new_indent_str, new_rhs)) + } + (None, Some(ref new_rhs)) => Some(format!("\n{}{}", new_indent_str, new_rhs)), + (None, None) => None, + (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), + } + } + } +} + +fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { + !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 +} + +fn rewrite_expr_addrof( + context: &RewriteContext, + mutability: ast::Mutability, + expr: &ast::Expr, + shape: Shape, +) -> Option { + let operator_str = match mutability { + ast::Mutability::Immutable => "&", + ast::Mutability::Mutable => "&mut ", + }; + rewrite_unary_prefix(context, operator_str, expr, shape) +} + +pub trait ToExpr { + fn to_expr(&self) -> Option<&ast::Expr>; + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool; +} + +impl ToExpr for ast::Expr { + fn to_expr(&self) -> Option<&ast::Expr> { + Some(self) + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_expr(context, self, len) + } +} + +impl ToExpr for ast::Ty { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_type(context, self, len) + } +} + +impl<'a> ToExpr for TuplePatField<'a> { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_pat(context, self, len) + } +} + +impl<'a> ToExpr for ast::StructField { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { + false + } +} + +impl<'a> ToExpr for MacroArg { + fn to_expr(&self) -> Option<&ast::Expr> { + match *self { + MacroArg::Expr(ref expr) => Some(expr), + _ => None, + } + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + match *self { + MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), + MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), + MacroArg::Pat(..) => false, + } + } +} diff --git a/rustfmt-core/src/filemap.rs b/rustfmt-core/src/filemap.rs new file mode 100644 index 00000000000..5986dbd6fa3 --- /dev/null +++ b/rustfmt-core/src/filemap.rs @@ -0,0 +1,176 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// TODO: add tests + +use std::fs::{self, File}; +use std::io::{self, BufWriter, Read, Write}; +use std::path::Path; + +use checkstyle::{output_checkstyle_file, output_footer, output_header}; +use config::{Config, NewlineStyle, WriteMode}; +use rustfmt_diff::{make_diff, print_diff, Mismatch}; +use syntax::codemap::FileName; + +use FileRecord; + +// Append a newline to the end of each file. +pub fn append_newline(s: &mut String) { + s.push_str("\n"); +} + +pub fn write_all_files( + file_map: &[FileRecord], + out: &mut T, + config: &Config, +) -> Result<(), io::Error> +where + T: Write, +{ + output_header(out, config.write_mode()).ok(); + for &(ref filename, ref text) in file_map { + write_file(text, filename, out, config)?; + } + output_footer(out, config.write_mode()).ok(); + + Ok(()) +} + +// Prints all newlines either as `\n` or as `\r\n`. +pub fn write_system_newlines(writer: T, text: &str, config: &Config) -> Result<(), io::Error> +where + T: Write, +{ + // Buffer output, since we're writing a since char at a time. + let mut writer = BufWriter::new(writer); + + let style = if config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + config.newline_style() + }; + + match style { + NewlineStyle::Unix => write!(writer, "{}", text), + NewlineStyle::Windows => { + for c in text.chars() { + match c { + '\n' => write!(writer, "\r\n")?, + '\r' => continue, + c => write!(writer, "{}", c)?, + } + } + Ok(()) + } + NewlineStyle::Native => unreachable!(), + } +} + +pub fn write_file( + text: &str, + filename: &FileName, + out: &mut T, + config: &Config, +) -> Result +where + T: Write, +{ + fn source_and_formatted_text( + text: &str, + filename: &Path, + config: &Config, + ) -> Result<(String, String), io::Error> { + let mut f = File::open(filename)?; + let mut ori_text = String::new(); + f.read_to_string(&mut ori_text)?; + let mut v = Vec::new(); + write_system_newlines(&mut v, text, config)?; + let fmt_text = String::from_utf8(v).unwrap(); + Ok((ori_text, fmt_text)) + } + + fn create_diff( + filename: &Path, + text: &str, + config: &Config, + ) -> Result, io::Error> { + let (ori, fmt) = source_and_formatted_text(text, filename, config)?; + Ok(make_diff(&ori, &fmt, 3)) + } + + let filename_to_path = || match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` with WriteMode::Replace", filename), + }; + + match config.write_mode() { + WriteMode::Replace => { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + if fmt != ori { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.with_extension("tmp"); + let bk_name = filename.with_extension("bk"); + { + // Write text to temp file + let tmp_file = File::create(&tmp_name)?; + write_system_newlines(tmp_file, text, config)?; + } + + fs::rename(filename, bk_name)?; + fs::rename(tmp_name, filename)?; + } + } + } + WriteMode::Overwrite => { + // Write text directly over original file if there is a diff. + let filename = filename_to_path(); + let (source, formatted) = source_and_formatted_text(text, filename, config)?; + if source != formatted { + let file = File::create(filename)?; + write_system_newlines(file, text, config)?; + } + } + WriteMode::Plain => { + write_system_newlines(out, text, config)?; + } + WriteMode::Display | WriteMode::Coverage => { + println!("{}:\n", filename); + write_system_newlines(out, text, config)?; + } + WriteMode::Diff => { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + let mismatch = make_diff(&ori, &fmt, 3); + let has_diff = !mismatch.is_empty(); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), + config.color(), + ); + return Ok(has_diff); + } + } + WriteMode::Checkstyle => { + let filename = filename_to_path(); + let diff = create_diff(filename, text, config)?; + output_checkstyle_file(out, filename, diff)?; + } + } + + // when we are not in diff mode, don't indicate differing files + Ok(false) +} diff --git a/rustfmt-core/src/imports.rs b/rustfmt-core/src/imports.rs new file mode 100644 index 00000000000..31ff4229ae2 --- /dev/null +++ b/rustfmt-core/src/imports.rs @@ -0,0 +1,600 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering; + +use config::lists::*; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; + +use codemap::SpanUtils; +use comment::combine_strs_with_missing_comments; +use config::IndentStyle; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use types::{rewrite_path, PathContext}; +use utils::{format_visibility, mk_sp}; +use visitor::{rewrite_extern_crate, FmtVisitor}; + +fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { + a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) +} + +fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { + for segment in a.segments.iter().zip(b.segments.iter()) { + let ord = compare_path_segments(segment.0, segment.1); + if ord != Ordering::Equal { + return ord; + } + } + a.segments.len().cmp(&b.segments.len()) +} + +fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Ordering { + use ast::UseTreeKind::*; + + // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be + // fully added + if !nested { + let paths_cmp = compare_paths(&a.prefix, &b.prefix); + if paths_cmp != Ordering::Equal { + return paths_cmp; + } + } + + match (&a.kind, &b.kind) { + (&Simple(ident_a), &Simple(ident_b)) => { + let name_a = &*path_to_imported_ident(&a.prefix).name.as_str(); + let name_b = &*path_to_imported_ident(&b.prefix).name.as_str(); + let name_ordering = if name_a == "self" { + if name_b == "self" { + Ordering::Equal + } else { + Ordering::Less + } + } else if name_b == "self" { + Ordering::Greater + } else { + name_a.cmp(name_b) + }; + if name_ordering == Ordering::Equal { + if ident_a.name.as_str() != name_a { + if ident_b.name.as_str() != name_b { + ident_a.name.as_str().cmp(&ident_b.name.as_str()) + } else { + Ordering::Greater + } + } else { + Ordering::Less + } + } else { + name_ordering + } + } + (&Glob, &Glob) => Ordering::Equal, + (&Simple(_), _) | (&Glob, &Nested(_)) => Ordering::Less, + (&Nested(ref a_items), &Nested(ref b_items)) => { + let mut a = a_items + .iter() + .map(|&(ref tree, _)| tree.clone()) + .collect::>(); + let mut b = b_items + .iter() + .map(|&(ref tree, _)| tree.clone()) + .collect::>(); + a.sort_by(|a, b| compare_use_trees(a, b, true)); + b.sort_by(|a, b| compare_use_trees(a, b, true)); + for comparison_pair in a.iter().zip(b.iter()) { + let ord = compare_use_trees(comparison_pair.0, comparison_pair.1, true); + if ord != Ordering::Equal { + return ord; + } + } + a.len().cmp(&b.len()) + } + (&Glob, &Simple(_)) | (&Nested(_), _) => Ordering::Greater, + } +} + +fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Ordering { + match (&a.node, &b.node) { + (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { + a.ident.name.as_str().cmp(&b.ident.name.as_str()) + } + (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { + compare_use_trees(a_tree, b_tree, false) + } + (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { + // `extern crate foo as bar;` + // ^^^ Comparing this. + let a_orig_name = + a_name.map_or_else(|| a.ident.name.as_str(), |symbol| symbol.as_str()); + let b_orig_name = + b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); + let result = a_orig_name.cmp(&b_orig_name); + if result != Ordering::Equal { + return result; + } + + // `extern crate foo as bar;` + // ^^^ Comparing this. + match (a_name, b_name) { + (Some(..), None) => Ordering::Greater, + (None, Some(..)) => Ordering::Less, + (None, None) => Ordering::Equal, + (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), + } + } + _ => unreachable!(), + } +} + +// TODO (some day) remove unused imports, expand globs, compress many single +// imports into a list import. + +fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { + if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { + let path = &ast::Path { + span: path.span, + segments: path.segments[..path.segments.len() - 1].to_owned(), + }; + rewrite_path(context, PathContext::Import, None, path, shape) + } else { + rewrite_path(context, PathContext::Import, None, path, shape) + } +} + +impl Rewrite for ast::UseTree { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.kind { + ast::UseTreeKind::Nested(ref items) => { + rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context) + } + ast::UseTreeKind::Glob => { + let prefix_shape = shape.sub_width(3)?; + + if !self.prefix.segments.is_empty() { + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; + Some(format!("{}::*", path_str)) + } else { + Some("*".to_owned()) + } + } + ast::UseTreeKind::Simple(ident) => { + let ident_str = ident.to_string(); + + // 4 = " as ".len() + let is_same_name_bind = path_to_imported_ident(&self.prefix) == ident; + let prefix_shape = if is_same_name_bind { + shape + } else { + shape.sub_width(ident_str.len() + 4)? + }; + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) + .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); + + if is_same_name_bind { + Some(path_str) + } else { + Some(format!("{} as {}", path_str, ident_str)) + } + } + } + } +} + +fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool { + attrs.is_empty() && is_unused_import_inner(tree) +} + +fn is_unused_import_inner(tree: &ast::UseTree) -> bool { + match tree.kind { + ast::UseTreeKind::Nested(ref items) => match items.len() { + 0 => true, + 1 => is_unused_import_inner(&items[0].0), + _ => false, + }, + _ => false, + } +} + +// Rewrite `use foo;` WITHOUT attributes. +fn rewrite_import( + context: &RewriteContext, + vis: &ast::Visibility, + tree: &ast::UseTree, + attrs: &[ast::Attribute], + shape: Shape, +) -> Option { + let vis = format_visibility(vis); + // 4 = `use `, 1 = `;` + let rw = shape + .offset_left(vis.len() + 4) + .and_then(|shape| shape.sub_width(1)) + .and_then(|shape| { + // If we have an empty nested group with no attributes, we erase it + if is_unused_import(tree, attrs) { + Some("".to_owned()) + } else { + tree.rewrite(context, shape) + } + }); + match rw { + Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), + _ => rw, + } +} + +/// Rewrite an inline mod. +fn rewrite_mod(item: &ast::Item) -> String { + let mut result = String::with_capacity(32); + result.push_str(&*format_visibility(&item.vis)); + result.push_str("mod "); + result.push_str(&item.ident.to_string()); + result.push(';'); + result +} + +fn rewrite_imports( + context: &RewriteContext, + use_items: &[&ast::Item], + shape: Shape, + span: Span, +) -> Option { + let items = itemize_list( + context.codemap, + use_items.iter(), + "", + ";", + |item| item.span().lo(), + |item| item.span().hi(), + |item| { + let attrs = ::visitor::filter_inline_attrs(&item.attrs, item.span()); + let attrs_str = attrs.rewrite(context, shape)?; + + let missed_span = if attrs.is_empty() { + mk_sp(item.span.lo(), item.span.lo()) + } else { + mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) + }; + + let item_str = match item.node { + ast::ItemKind::Use(ref tree) => { + rewrite_import(context, &item.vis, tree, &item.attrs, shape)? + } + ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, + ast::ItemKind::Mod(..) => rewrite_mod(item), + _ => return None, + }; + + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missed_span, + shape, + false, + ) + }, + span.lo(), + span.hi(), + false, + ); + let mut item_pair_vec: Vec<_> = items.zip(use_items.iter()).collect(); + item_pair_vec.sort_by(|a, b| compare_use_items(a.1, b.1)); + let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: true, + preserve_newline: false, + config: context.config, + }; + + write_list(&item_vec, &fmt) +} + +impl<'a> FmtVisitor<'a> { + pub fn format_imports(&mut self, use_items: &[&ast::Item]) { + if use_items.is_empty() { + return; + } + + let lo = use_items.first().unwrap().span().lo(); + let hi = use_items.last().unwrap().span().hi(); + let span = mk_sp(lo, hi); + let rw = rewrite_imports(&self.get_context(), use_items, self.shape(), span); + self.push_rewrite(span, rw); + } + + pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { + let span = item.span; + let shape = self.shape(); + let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape); + match rw { + Some(ref s) if s.is_empty() => { + // Format up to last newline + let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); + let trimmed_snippet = self.snippet(prev_span).trim_right(); + let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32); + self.format_missing(span_end); + // We have an excessive newline from the removed import. + if self.buffer.ends_with('\n') { + self.buffer.pop(); + self.line_number -= 1; + } + self.last_pos = source!(self, span).hi(); + } + Some(ref s) => { + self.format_missing_with_indent(source!(self, span).lo()); + self.push_str(s); + self.last_pos = source!(self, span).hi(); + } + None => { + self.format_missing_with_indent(source!(self, span).lo()); + self.format_missing(source!(self, span).hi()); + } + } + } +} + +fn rewrite_nested_use_tree_single( + context: &RewriteContext, + path_str: &str, + tree: &ast::UseTree, + shape: Shape, +) -> Option { + match tree.kind { + ast::UseTreeKind::Simple(rename) => { + let ident = path_to_imported_ident(&tree.prefix); + let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; + if item_str == "self" { + item_str = "".to_owned(); + } + + let path_item_str = if path_str.is_empty() { + if item_str.is_empty() { + "self".to_owned() + } else { + item_str + } + } else if item_str.is_empty() { + path_str.to_owned() + } else { + format!("{}::{}", path_str, item_str) + }; + + Some(if ident == rename { + path_item_str + } else { + format!("{} as {}", path_item_str, rename) + }) + } + ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { + // 2 = "::" + let nested_shape = shape.offset_left(path_str.len() + 2)?; + tree.rewrite(context, nested_shape) + .map(|item| format!("{}::{}", path_str, item)) + } + } +} + +#[derive(Eq, PartialEq)] +enum ImportItem<'a> { + // `self` or `self as a` + SelfImport(&'a str), + // name_one, name_two, ... + SnakeCase(&'a str), + // NameOne, NameTwo, ... + CamelCase(&'a str), + // NAME_ONE, NAME_TWO, ... + AllCaps(&'a str), + // Failed to format the import item + Invalid, +} + +impl<'a> ImportItem<'a> { + fn from_str(s: &str) -> ImportItem { + if s == "self" || s.starts_with("self as") { + ImportItem::SelfImport(s) + } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') { + ImportItem::SnakeCase(s) + } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') { + ImportItem::AllCaps(s) + } else { + ImportItem::CamelCase(s) + } + } + + fn from_opt_str(s: Option<&String>) -> ImportItem { + s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s)) + } + + fn to_str(&self) -> Option<&str> { + match *self { + ImportItem::SelfImport(s) + | ImportItem::SnakeCase(s) + | ImportItem::CamelCase(s) + | ImportItem::AllCaps(s) => Some(s), + ImportItem::Invalid => None, + } + } + + fn to_u32(&self) -> u32 { + match *self { + ImportItem::SelfImport(..) => 0, + ImportItem::SnakeCase(..) => 1, + ImportItem::CamelCase(..) => 2, + ImportItem::AllCaps(..) => 3, + ImportItem::Invalid => 4, + } + } +} + +impl<'a> PartialOrd for ImportItem<'a> { + fn partial_cmp(&self, other: &ImportItem<'a>) -> Option { + Some(self.cmp(other)) + } +} + +impl<'a> Ord for ImportItem<'a> { + fn cmp(&self, other: &ImportItem<'a>) -> Ordering { + let res = self.to_u32().cmp(&other.to_u32()); + if res != Ordering::Equal { + return res; + } + self.to_str().map_or(Ordering::Greater, |self_str| { + other + .to_str() + .map_or(Ordering::Less, |other_str| self_str.cmp(other_str)) + }) + } +} + +// Pretty prints a multi-item import. +// If the path list is empty, it leaves the braces empty. +fn rewrite_nested_use_tree( + shape: Shape, + path: &ast::Path, + trees: &[(ast::UseTree, ast::NodeId)], + span: Span, + context: &RewriteContext, +) -> Option { + // Returns a different option to distinguish `::foo` and `foo` + let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; + + match trees.len() { + 0 => { + let shape = shape.offset_left(path_str.len() + 3)?; + return rewrite_path(context, PathContext::Import, None, path, shape) + .map(|path_str| format!("{}::{{}}", path_str)); + } + 1 => { + return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape); + } + _ => (), + } + + let path_str = if path_str.is_empty() { + path_str + } else { + format!("{}::", path_str) + }; + + // 2 = "{}" + let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); + let nested_indent = match context.config.imports_indent() { + IndentStyle::Block => shape.indent.block_indent(context.config), + // 1 = `{` + IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, + }; + + let nested_shape = match context.config.imports_indent() { + IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?, + IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), + }; + + let mut items = { + // Dummy value, see explanation below. + let mut items = vec![ListItem::from_str("")]; + let iter = itemize_list( + context.codemap, + trees.iter().map(|tree| &tree.0), + "}", + ",", + |tree| tree.span.lo(), + |tree| tree.span.hi(), + |tree| tree.rewrite(context, nested_shape), + context.codemap.span_after(span, "{"), + span.hi(), + false, + ); + items.extend(iter); + items + }; + + // We prefixed the item list with a dummy value so that we can + // potentially move "self" to the front of the vector without touching + // the rest of the items. + let has_self = move_self_to_front(&mut items); + let first_index = if has_self { 0 } else { 1 }; + + if context.config.reorder_imported_names() { + items[1..].sort_by(|a, b| { + let a = ImportItem::from_opt_str(a.item.as_ref()); + let b = ImportItem::from_opt_str(b.item.as_ref()); + a.cmp(&b) + }); + } + + let tactic = definitive_tactic( + &items[first_index..], + context.config.imports_layout(), + Separator::Comma, + remaining_width, + ); + + let ends_with_newline = context.config.imports_indent() == IndentStyle::Block + && tactic != DefinitiveListTactic::Horizontal; + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if ends_with_newline { + context.config.trailing_comma() + } else { + SeparatorTactic::Never + }, + separator_place: SeparatorPlace::Back, + shape: nested_shape, + ends_with_newline, + preserve_newline: true, + config: context.config, + }; + let list_str = write_list(&items[first_index..], &fmt)?; + + let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block + { + format!( + "{}{{\n{}{}\n{}}}", + path_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.indent.to_string(context.config) + ) + } else { + format!("{}{{{}}}", path_str, list_str) + }; + Some(result) +} + +// Returns true when self item was found. +fn move_self_to_front(items: &mut Vec) -> bool { + match items + .iter() + .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) + { + Some(pos) => { + items[0] = items.remove(pos); + true + } + None => false, + } +} + +fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { + path.segments.last().unwrap().identifier +} diff --git a/rustfmt-core/src/issues.rs b/rustfmt-core/src/issues.rs new file mode 100644 index 00000000000..353f8349d2a --- /dev/null +++ b/rustfmt-core/src/issues.rs @@ -0,0 +1,323 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Objects for seeking through a char stream for occurrences of TODO and FIXME. +// Depending on the loaded configuration, may also check that these have an +// associated issue number. + +use std::fmt; + +use config::ReportTactic; + +const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o']; +const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e']; + +// Enabled implementation detail is here because it is +// irrelevant outside the issues module +fn is_enabled(report_tactic: ReportTactic) -> bool { + report_tactic != ReportTactic::Never +} + +#[derive(Clone, Copy)] +enum Seeking { + Issue { todo_idx: usize, fixme_idx: usize }, + Number { issue: Issue, part: NumberPart }, +} + +#[derive(Clone, Copy)] +enum NumberPart { + OpenParen, + Pound, + Number, + CloseParen, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub struct Issue { + issue_type: IssueType, + // Indicates whether we're looking for issues with missing numbers, or + // all issues of this type. + missing_number: bool, +} + +impl fmt::Display for Issue { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let msg = match self.issue_type { + IssueType::Todo => "TODO", + IssueType::Fixme => "FIXME", + }; + let details = if self.missing_number { + " without issue number" + } else { + "" + }; + + write!(fmt, "{}{}", msg, details) + } +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum IssueType { + Todo, + Fixme, +} + +enum IssueClassification { + Good, + Bad(Issue), + None, +} + +pub struct BadIssueSeeker { + state: Seeking, + report_todo: ReportTactic, + report_fixme: ReportTactic, +} + +impl BadIssueSeeker { + pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { + BadIssueSeeker { + state: Seeking::Issue { + todo_idx: 0, + fixme_idx: 0, + }, + report_todo, + report_fixme, + } + } + + // Check whether or not the current char is conclusive evidence for an + // unnumbered TO-DO or FIX-ME. + pub fn inspect(&mut self, c: char) -> Option { + match self.state { + Seeking::Issue { + todo_idx, + fixme_idx, + } => { + self.state = self.inspect_issue(c, todo_idx, fixme_idx); + } + Seeking::Number { issue, part } => { + let result = self.inspect_number(c, issue, part); + + if let IssueClassification::None = result { + return None; + } + + self.state = Seeking::Issue { + todo_idx: 0, + fixme_idx: 0, + }; + + if let IssueClassification::Bad(issue) = result { + return Some(issue); + } + } + } + + None + } + + fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking { + if let Some(lower_case_c) = c.to_lowercase().next() { + if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] { + todo_idx += 1; + if todo_idx == TO_DO_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Todo, + missing_number: if let ReportTactic::Unnumbered = self.report_todo { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; + } + fixme_idx = 0; + } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] { + // Exploit the fact that the character sets of todo and fixme + // are disjoint by adding else. + fixme_idx += 1; + if fixme_idx == FIX_ME_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Fixme, + missing_number: if let ReportTactic::Unnumbered = self.report_fixme { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; + } + todo_idx = 0; + } else { + todo_idx = 0; + fixme_idx = 0; + } + } + + Seeking::Issue { + todo_idx, + fixme_idx, + } + } + + fn inspect_number( + &mut self, + c: char, + issue: Issue, + mut part: NumberPart, + ) -> IssueClassification { + if !issue.missing_number || c == '\n' { + return IssueClassification::Bad(issue); + } else if c == ')' { + return if let NumberPart::CloseParen = part { + IssueClassification::Good + } else { + IssueClassification::Bad(issue) + }; + } + + match part { + NumberPart::OpenParen => { + if c != '(' { + return IssueClassification::Bad(issue); + } else { + part = NumberPart::Pound; + } + } + NumberPart::Pound => { + if c == '#' { + part = NumberPart::Number; + } + } + NumberPart::Number => { + if c >= '0' && c <= '9' { + part = NumberPart::CloseParen; + } else { + return IssueClassification::Bad(issue); + } + } + NumberPart::CloseParen => {} + } + + self.state = Seeking::Number { part, issue }; + + IssueClassification::None + } +} + +#[test] +fn find_unnumbered_issue() { + fn check_fail(text: &str, failing_pos: usize) { + let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); + assert_eq!( + Some(failing_pos), + text.chars().position(|c| seeker.inspect(c).is_some()) + ); + } + + fn check_pass(text: &str) { + let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); + assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); + } + + check_fail("TODO\n", 4); + check_pass(" TO FIX DOME\n"); + check_fail(" \n FIXME\n", 8); + check_fail("FIXME(\n", 6); + check_fail("FIXME(#\n", 7); + check_fail("FIXME(#1\n", 8); + check_fail("FIXME(#)1\n", 7); + check_pass("FIXME(#1222)\n"); + check_fail("FIXME(#12\n22)\n", 9); + check_pass("FIXME(@maintainer, #1222, hello)\n"); + check_fail("TODO(#22) FIXME\n", 15); +} + +#[test] +fn find_issue() { + fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { + let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); + text.chars().any(|c| seeker.inspect(c).is_some()) + } + + assert!(is_bad_issue( + "TODO(@maintainer, #1222, hello)\n", + ReportTactic::Always, + ReportTactic::Never, + )); + + assert!(!is_bad_issue( + "TODO: no number\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(!is_bad_issue( + "Todo: mixed case\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(is_bad_issue( + "This is a FIXME(#1)\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(is_bad_issue( + "This is a FixMe(#1) mixed case\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(!is_bad_issue( + "bad FIXME\n", + ReportTactic::Always, + ReportTactic::Never, + )); +} + +#[test] +fn issue_type() { + let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); + let expected = Some(Issue { + issue_type: IssueType::Todo, + missing_number: false, + }); + + assert_eq!( + expected, + "TODO(#100): more awesomeness" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap() + ); + + let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); + let expected = Some(Issue { + issue_type: IssueType::Fixme, + missing_number: true, + }); + + assert_eq!( + expected, + "Test. FIXME: bad, bad, not good" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap() + ); +} diff --git a/rustfmt-core/src/items.rs b/rustfmt-core/src/items.rs new file mode 100644 index 00000000000..9f3b0a1e6b2 --- /dev/null +++ b/rustfmt-core/src/items.rs @@ -0,0 +1,2845 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Formatting top-level items - functions, structs, enums, traits, impls. + +use std::borrow::Cow; +use std::cmp::min; + +use config::lists::*; +use syntax::{abi, ast, ptr, symbol}; +use syntax::ast::{CrateSugar, ImplItem}; +use syntax::codemap::{BytePos, Span}; +use syntax::visit; + +use codemap::{LineRangeUtils, SpanUtils}; +use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; +use config::{BraceStyle, Config, Density, IndentStyle}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_call_inner, ExprType}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use types::join_bounds; +use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, + format_defaultness, format_mutability, format_unsafety, format_visibility, + is_attributes_extendable, last_line_contains_single_line_comment, + last_line_extendable, last_line_used_width, last_line_width, mk_sp, + semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; +use vertical::rewrite_with_alignment; +use visitor::FmtVisitor; + +fn type_annotation_separator(config: &Config) -> &str { + colon_spaces(config.space_before_colon(), config.space_after_colon()) +} + +// Statements of the form +// let pat: ty = init; +impl Rewrite for ast::Local { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!( + "Local::rewrite {:?} {} {:?}", + self, shape.width, shape.indent + ); + + skip_out_of_file_lines_range!(context, self.span); + + if contains_skip(&self.attrs) { + return None; + } + + let attrs_str = self.attrs.rewrite(context, shape)?; + let mut result = if attrs_str.is_empty() { + "let ".to_owned() + } else { + combine_strs_with_missing_comments( + context, + &attrs_str, + "let ", + mk_sp( + self.attrs.last().map(|a| a.span.hi()).unwrap(), + self.span.lo(), + ), + shape, + false, + )? + }; + + // 4 = "let ".len() + let pat_shape = shape.offset_left(4)?; + // 1 = ; + let pat_shape = pat_shape.sub_width(1)?; + let pat_str = self.pat.rewrite(context, pat_shape)?; + result.push_str(&pat_str); + + // String that is placed within the assignment pattern and expression. + let infix = { + let mut infix = String::with_capacity(32); + + if let Some(ref ty) = self.ty { + let separator = type_annotation_separator(context.config); + let indent = shape.indent + last_line_width(&result) + separator.len(); + // 1 = ; + let budget = shape.width.checked_sub(indent.width() + 1)?; + let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?; + + infix.push_str(separator); + infix.push_str(&rewrite); + } + + if self.init.is_some() { + infix.push_str(" ="); + } + + infix + }; + + result.push_str(&infix); + + if let Some(ref ex) = self.init { + // 1 = trailing semicolon; + let nested_shape = shape.sub_width(1)?; + + result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?; + } + + result.push(';'); + Some(result) + } +} + +// TODO convert to using rewrite style rather than visitor +// TODO format modules in this style +#[allow(dead_code)] +struct Item<'a> { + keyword: &'static str, + abi: Cow<'static, str>, + vis: Option<&'a ast::Visibility>, + body: Vec>, + span: Span, +} + +impl<'a> Item<'a> { + fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { + Item { + keyword: "", + abi: format_abi(fm.abi, config.force_explicit_abi(), true), + vis: None, + body: fm.items + .iter() + .map(|i| BodyElement::ForeignItem(i)) + .collect(), + span, + } + } +} + +enum BodyElement<'a> { + // Stmt(&'a ast::Stmt), + // Field(&'a ast::Field), + // Variant(&'a ast::Variant), + // Item(&'a ast::Item), + ForeignItem(&'a ast::ForeignItem), +} + +/// Represents a fn's signature. +pub struct FnSig<'a> { + decl: &'a ast::FnDecl, + generics: &'a ast::Generics, + abi: abi::Abi, + constness: ast::Constness, + defaultness: ast::Defaultness, + unsafety: ast::Unsafety, + visibility: ast::Visibility, +} + +impl<'a> FnSig<'a> { + pub fn new( + decl: &'a ast::FnDecl, + generics: &'a ast::Generics, + vis: ast::Visibility, + ) -> FnSig<'a> { + FnSig { + decl, + generics, + abi: abi::Abi::Rust, + constness: ast::Constness::NotConst, + defaultness: ast::Defaultness::Final, + unsafety: ast::Unsafety::Normal, + visibility: vis, + } + } + + pub fn from_method_sig( + method_sig: &'a ast::MethodSig, + generics: &'a ast::Generics, + ) -> FnSig<'a> { + FnSig { + unsafety: method_sig.unsafety, + constness: method_sig.constness.node, + defaultness: ast::Defaultness::Final, + abi: method_sig.abi, + decl: &*method_sig.decl, + generics, + visibility: ast::Visibility::Inherited, + } + } + + pub fn from_fn_kind( + fn_kind: &'a visit::FnKind, + generics: &'a ast::Generics, + decl: &'a ast::FnDecl, + defualtness: ast::Defaultness, + ) -> FnSig<'a> { + match *fn_kind { + visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { + decl, + generics, + abi, + constness: constness.node, + defaultness: defualtness, + unsafety, + visibility: visibility.clone(), + }, + visit::FnKind::Method(_, method_sig, vis, _) => { + let mut fn_sig = FnSig::from_method_sig(method_sig, generics); + fn_sig.defaultness = defualtness; + if let Some(vis) = vis { + fn_sig.visibility = vis.clone(); + } + fn_sig + } + _ => unreachable!(), + } + } + + fn to_str(&self, context: &RewriteContext) -> String { + let mut result = String::with_capacity(128); + // Vis defaultness constness unsafety abi. + result.push_str(&*format_visibility(&self.visibility)); + result.push_str(format_defaultness(self.defaultness)); + result.push_str(format_constness(self.constness)); + result.push_str(format_unsafety(self.unsafety)); + result.push_str(&format_abi( + self.abi, + context.config.force_explicit_abi(), + false, + )); + result + } +} + +impl<'a> FmtVisitor<'a> { + fn format_item(&mut self, item: &Item) { + self.buffer.push_str(&item.abi); + + let snippet = self.snippet(item.span); + let brace_pos = snippet.find_uncommented("{").unwrap(); + + self.push_str("{"); + if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { + // FIXME: this skips comments between the extern keyword and the opening + // brace. + self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1); + self.block_indent = self.block_indent.block_indent(self.config); + + if item.body.is_empty() { + self.format_missing_no_indent(item.span.hi() - BytePos(1)); + self.block_indent = self.block_indent.block_unindent(self.config); + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + } else { + for item in &item.body { + self.format_body_element(item); + } + + self.block_indent = self.block_indent.block_unindent(self.config); + self.format_missing_with_indent(item.span.hi() - BytePos(1)); + } + } + + self.push_str("}"); + self.last_pos = item.span.hi(); + } + + fn format_body_element(&mut self, element: &BodyElement) { + match *element { + BodyElement::ForeignItem(item) => self.format_foreign_item(item), + } + } + + pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { + let item = Item::from_foreign_mod(fm, span, self.config); + self.format_item(&item); + } + + fn format_foreign_item(&mut self, item: &ast::ForeignItem) { + let rewrite = item.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(item.span(), rewrite); + self.last_pos = item.span.hi(); + } + + pub fn rewrite_fn( + &mut self, + indent: Indent, + ident: ast::Ident, + fn_sig: &FnSig, + span: Span, + block: &ast::Block, + ) -> Option { + let context = self.get_context(); + + let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause); + + let (mut result, force_newline_brace) = + rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; + + // 2 = ` {` + if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace + || last_line_width(&result) + 2 > self.shape().width + { + newline_brace = true; + } else if !result.contains('\n') { + newline_brace = false; + } + + // Prepare for the function body by possibly adding a newline and + // indent. + // FIXME we'll miss anything between the end of the signature and the + // start of the body, but we need more spans from the compiler to solve + // this. + if newline_brace { + result.push('\n'); + result.push_str(&indent.to_string(self.config)); + } else { + result.push(' '); + } + + self.single_line_fn(&result, block).or_else(|| Some(result)) + } + + pub fn rewrite_required_fn( + &mut self, + indent: Indent, + ident: ast::Ident, + sig: &ast::MethodSig, + generics: &ast::Generics, + span: Span, + ) -> Option { + // Drop semicolon or it will be interpreted as comment. + let span = mk_sp(span.lo(), span.hi() - BytePos(1)); + let context = self.get_context(); + + let (mut result, _) = rewrite_fn_base( + &context, + indent, + ident, + &FnSig::from_method_sig(sig, generics), + span, + false, + false, + )?; + + // Re-attach semicolon + result.push(';'); + + Some(result) + } + + fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { + if fn_str.contains('\n') { + return None; + } + + let codemap = self.get_context().codemap; + + if self.config.empty_item_single_line() && is_empty_block(block, codemap) + && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() + { + return Some(format!("{}{{}}", fn_str)); + } + + if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { + let rewrite = { + if let Some(stmt) = block.stmts.first() { + match stmt_expr(stmt) { + Some(e) => { + let suffix = if semicolon_for_expr(&self.get_context(), e) { + ";" + } else { + "" + }; + + format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) + .map(|s| s + suffix) + .or_else(|| Some(self.snippet(e.span).to_owned())) + } + None => stmt.rewrite(&self.get_context(), self.shape()), + } + } else { + None + } + }; + + if let Some(res) = rewrite { + let width = self.block_indent.width() + fn_str.len() + res.len() + 4; + if !res.contains('\n') && width <= self.config.max_width() { + return Some(format!("{}{{ {} }}", fn_str, res)); + } + } + } + + None + } + + pub fn visit_static(&mut self, static_parts: &StaticParts) { + let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); + self.push_rewrite(static_parts.span, rewrite); + } + + pub fn visit_struct(&mut self, struct_parts: &StructParts) { + let is_tuple = struct_parts.def.is_tuple(); + let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) + .map(|s| if is_tuple { s + ";" } else { s }); + self.push_rewrite(struct_parts.span, rewrite); + } + + pub fn visit_enum( + &mut self, + ident: ast::Ident, + vis: &ast::Visibility, + enum_def: &ast::EnumDef, + generics: &ast::Generics, + span: Span, + ) { + let enum_header = format_header("enum ", ident, vis); + self.push_str(&enum_header); + + let enum_snippet = self.snippet(span); + let brace_pos = enum_snippet.find_uncommented("{").unwrap(); + let body_start = span.lo() + BytePos(brace_pos as u32 + 1); + let generics_str = format_generics( + &self.get_context(), + generics, + self.config.brace_style(), + if enum_def.variants.is_empty() { + BracePos::ForceSameLine + } else { + BracePos::Auto + }, + self.block_indent, + mk_sp(span.lo(), body_start), + last_line_width(&enum_header), + ).unwrap(); + self.push_str(&generics_str); + + self.last_pos = body_start; + + self.block_indent = self.block_indent.block_indent(self.config); + let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); + match variant_list { + Some(ref body_str) => self.push_str(body_str), + None => self.format_missing_no_indent(span.hi() - BytePos(1)), + } + self.block_indent = self.block_indent.block_unindent(self.config); + + if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + } + self.push_str("}"); + self.last_pos = span.hi(); + } + + // Format the body of an enum definition + fn format_variant_list( + &self, + enum_def: &ast::EnumDef, + body_lo: BytePos, + body_hi: BytePos, + ) -> Option { + if enum_def.variants.is_empty() { + return None; + } + let mut result = String::with_capacity(1024); + result.push('\n'); + let indentation = self.block_indent.to_string(self.config); + result.push_str(&indentation); + + let itemize_list_with = |one_line_width: usize| { + itemize_list( + self.codemap, + enum_def.variants.iter(), + "}", + ",", + |f| { + if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo() + } else { + f.span.lo() + } + }, + |f| f.span.hi(), + |f| self.format_variant(f, one_line_width), + body_lo, + body_hi, + false, + ).collect() + }; + let mut items: Vec<_> = + itemize_list_with(self.config.width_heuristics().struct_variant_width); + // If one of the variants use multiple lines, use multi-lined formatting for all variants. + let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); + let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); + if has_multiline_variant && has_single_line_variant { + items = itemize_list_with(0); + } + + let shape = self.shape().sub_width(2)?; + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: self.config.trailing_comma(), + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: true, + preserve_newline: true, + config: self.config, + }; + + let list = write_list(&items, &fmt)?; + result.push_str(&list); + result.push('\n'); + Some(result) + } + + // Variant of an enum. + fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option { + if contains_skip(&field.node.attrs) { + let lo = field.node.attrs[0].span.lo(); + let span = mk_sp(lo, field.span.hi()); + return Some(self.snippet(span).to_owned()); + } + + let context = self.get_context(); + // 1 = ',' + let shape = self.shape().sub_width(1)?; + let attrs_str = field.node.attrs.rewrite(&context, shape)?; + let lo = field + .node + .attrs + .last() + .map_or(field.span.lo(), |attr| attr.span.hi()); + let span = mk_sp(lo, field.span.lo()); + + let variant_body = match field.node.data { + ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( + &context, + &StructParts::from_variant(field), + self.block_indent, + Some(one_line_width), + )?, + ast::VariantData::Unit(..) => { + if let Some(ref expr) = field.node.disr_expr { + let lhs = format!("{} =", field.node.name); + rewrite_assign_rhs(&context, lhs, &**expr, shape)? + } else { + field.node.name.to_string() + } + } + }; + + combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) + } +} + +pub fn format_impl( + context: &RewriteContext, + item: &ast::Item, + offset: Indent, + where_span_end: Option, +) -> Option { + if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { + let mut result = String::with_capacity(128); + let ref_and_type = format_impl_ref_and_type(context, item, offset)?; + let indent_str = offset.to_string(context.config); + let sep = format!("\n{}", &indent_str); + result.push_str(&ref_and_type); + + let where_budget = if result.contains('\n') { + context.config.max_width() + } else { + context.budget(last_line_width(&result)) + }; + let option = WhereClauseOption::snuggled(&ref_and_type); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + Density::Vertical, + "{", + where_span_end, + self_ty.span.hi(), + option, + false, + )?; + + // If there is no where clause, we may have missing comments between the trait name and + // the opening brace. + if generics.where_clause.predicates.is_empty() { + if let Some(hi) = where_span_end { + match recover_missing_comment_in_span( + mk_sp(self_ty.span.hi(), hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + } + _ => (), + } + } + } + + if is_impl_single_line(context, items, &result, &where_clause_str, item)? { + result.push_str(&where_clause_str); + if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { + result.push_str(&format!("{}{{{}}}", &sep, &sep)); + } else { + result.push_str(" {}"); + } + return Some(result); + } + + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { + result.push('\n'); + let width = offset.block_indent + context.config.tab_spaces() - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string(context.config)); + } + result.push_str(&where_clause_str); + + let need_newline = !last_line_extendable(&result) + && (last_line_contains_single_line_comment(&result) || result.contains('\n')); + match context.config.brace_style() { + _ if need_newline => result.push_str(&sep), + BraceStyle::AlwaysNextLine => result.push_str(&sep), + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() { + result.push_str(&sep); + } else { + result.push(' '); + } + } + } + + result.push('{'); + + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + + if !items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = offset.block_only().block_indent(context.config); + visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); + + visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); + for item in items { + visitor.visit_impl_item(item); + } + + visitor.format_missing(item.span.hi() - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string(context.config); + let outer_indent_str = offset.block_only().to_string(context.config); + + result.push('\n'); + result.push_str(&inner_indent_str); + result.push_str(visitor.buffer.to_string().trim()); + result.push('\n'); + result.push_str(&outer_indent_str); + } + + if result.ends_with('{') { + result.push_str(&sep); + } + result.push('}'); + + Some(result) + } else { + unreachable!(); + } +} + +fn is_impl_single_line( + context: &RewriteContext, + items: &[ImplItem], + result: &str, + where_clause_str: &str, + item: &ast::Item, +) -> Option { + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + + Some( + context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n') + && result.len() + where_clause_str.len() <= context.config.max_width() + && !contains_comment(&snippet[open_pos..]), + ) +} + +fn format_impl_ref_and_type( + context: &RewriteContext, + item: &ast::Item, + offset: Indent, +) -> Option { + if let ast::ItemKind::Impl( + unsafety, + polarity, + defaultness, + ref generics, + ref trait_ref, + ref self_ty, + _, + ) = item.node + { + let mut result = String::with_capacity(128); + + result.push_str(&format_visibility(&item.vis)); + result.push_str(format_defaultness(defaultness)); + result.push_str(format_unsafety(unsafety)); + result.push_str("impl"); + + let lo = context.codemap.span_after(item.span, "impl"); + let hi = match *trait_ref { + Some(ref tr) => tr.path.span.lo(), + None => self_ty.span.lo(), + }; + let shape = generics_shape_from_config( + context.config, + Shape::indented(offset + last_line_width(&result), context.config), + 0, + )?; + let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?; + let generics_str = + rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?; + + let polarity_str = if polarity == ast::ImplPolarity::Negative { + "!" + } else { + "" + }; + + if let Some(ref trait_ref) = *trait_ref { + let result_len = result.len(); + if let Some(trait_ref_str) = rewrite_trait_ref( + context, + trait_ref, + offset, + &generics_str, + true, + polarity_str, + result_len, + ) { + result.push_str(&trait_ref_str); + } else { + let generics_str = + rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?; + result.push_str(&rewrite_trait_ref( + context, + trait_ref, + offset, + &generics_str, + false, + polarity_str, + result_len, + )?); + } + } else { + result.push_str(&generics_str); + } + + // Try to put the self type in a single line. + // ` for` + let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; + let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { + // If there is no where clause adapt budget for type formatting to take space and curly + // brace into account. + match context.config.brace_style() { + BraceStyle::AlwaysNextLine => 0, + _ => 2, + } + } else { + 0 + }; + let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; + // 1 = space before the type. + let budget = context.budget(used_space + 1); + if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { + if !self_ty_str.contains('\n') { + if trait_ref.is_some() { + result.push_str(" for "); + } else { + result.push(' '); + } + result.push_str(&self_ty_str); + return Some(result); + } + } + + // Couldn't fit the self type on a single line, put it on a new line. + result.push('\n'); + // Add indentation of one additional tab. + let new_line_offset = offset.block_indent(context.config); + result.push_str(&new_line_offset.to_string(context.config)); + if trait_ref.is_some() { + result.push_str("for "); + } + let budget = context.budget(last_line_width(&result)); + let type_offset = match context.config.indent_style() { + IndentStyle::Visual => new_line_offset + trait_ref_overhead, + IndentStyle::Block => new_line_offset, + }; + result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); + Some(result) + } else { + unreachable!(); + } +} + +fn rewrite_trait_ref( + context: &RewriteContext, + trait_ref: &ast::TraitRef, + offset: Indent, + generics_str: &str, + retry: bool, + polarity_str: &str, + result_len: usize, +) -> Option { + // 1 = space between generics and trait_ref + let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len); + let shape = Shape::indented(offset + used_space, context.config); + if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { + if !(retry && trait_ref_str.contains('\n')) { + return Some(format!( + "{} {}{}", + generics_str, polarity_str, &trait_ref_str + )); + } + } + // We could not make enough space for trait_ref, so put it on new line. + if !retry { + let offset = offset.block_indent(context.config); + let shape = Shape::indented(offset, context.config); + let trait_ref_str = trait_ref.rewrite(context, shape)?; + Some(format!( + "{}\n{}{}{}", + generics_str, + &offset.to_string(context.config), + polarity_str, + &trait_ref_str + )) + } else { + None + } +} + +pub struct StructParts<'a> { + prefix: &'a str, + ident: ast::Ident, + vis: &'a ast::Visibility, + def: &'a ast::VariantData, + generics: Option<&'a ast::Generics>, + span: Span, +} + +impl<'a> StructParts<'a> { + fn format_header(&self) -> String { + format_header(self.prefix, self.ident, self.vis) + } + + fn from_variant(variant: &'a ast::Variant) -> Self { + StructParts { + prefix: "", + ident: variant.node.name, + vis: &ast::Visibility::Inherited, + def: &variant.node.data, + generics: None, + span: variant.span, + } + } + + pub fn from_item(item: &'a ast::Item) -> Self { + let (prefix, def, generics) = match item.node { + ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), + ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), + _ => unreachable!(), + }; + StructParts { + prefix, + ident: item.ident, + vis: &item.vis, + def, + generics: Some(generics), + span: item.span, + } + } +} + +fn format_struct( + context: &RewriteContext, + struct_parts: &StructParts, + offset: Indent, + one_line_width: Option, +) -> Option { + match *struct_parts.def { + ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset), + ast::VariantData::Tuple(ref fields, _) => { + format_tuple_struct(context, struct_parts, fields, offset) + } + ast::VariantData::Struct(ref fields, _) => { + format_struct_struct(context, struct_parts, fields, offset, one_line_width) + } + } +} + +pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = + item.node + { + let mut result = String::with_capacity(128); + let header = format!( + "{}{}trait {}", + format_visibility(&item.vis), + format_unsafety(unsafety), + item.ident + ); + + result.push_str(&header); + + let body_lo = context.codemap.span_after(item.span, "{"); + + let shape = Shape::indented(offset, context.config).offset_left(result.len())?; + let generics_str = + rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; + result.push_str(&generics_str); + + // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. + if !type_param_bounds.is_empty() { + let ident_hi = context + .codemap + .span_after(item.span, &format!("{}", item.ident)); + let bound_hi = type_param_bounds.last().unwrap().span().hi(); + let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); + if contains_comment(snippet) { + return None; + } + } + let trait_bound_str = rewrite_trait_bounds( + context, + type_param_bounds, + Shape::indented(offset, context.config), + )?; + // If the trait, generics, and trait bound cannot fit on the same line, + // put the trait bounds on an indented new line + if offset.width() + last_line_width(&result) + trait_bound_str.len() + > context.config.comment_width() + { + result.push('\n'); + let trait_indent = offset.block_only().block_indent(context.config); + result.push_str(&trait_indent.to_string(context.config)); + } + result.push_str(&trait_bound_str); + + let where_density = + if context.config.indent_style() == IndentStyle::Block && result.is_empty() { + Density::Compressed + } else { + Density::Tall + }; + + let where_budget = context.budget(last_line_width(&result)); + let pos_before_where = if type_param_bounds.is_empty() { + generics.where_clause.span.lo() + } else { + type_param_bounds[type_param_bounds.len() - 1].span().hi() + }; + let option = WhereClauseOption::snuggled(&generics_str); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + where_density, + "{", + None, + pos_before_where, + option, + false, + )?; + // If the where clause cannot fit on the same line, + // put the where clause on a new line + if !where_clause_str.contains('\n') + && last_line_width(&result) + where_clause_str.len() + offset.width() + > context.config.comment_width() + { + result.push('\n'); + let width = offset.block_indent + context.config.tab_spaces() - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string(context.config)); + } + result.push_str(&where_clause_str); + + if generics.where_clause.predicates.is_empty() { + let item_snippet = context.snippet(item.span); + if let Some(lo) = item_snippet.chars().position(|c| c == '/') { + // 1 = `{` + let comment_hi = body_lo - BytePos(1); + let comment_lo = item.span.lo() + BytePos(lo as u32); + if comment_lo < comment_hi { + match recover_missing_comment_in_span( + mk_sp(comment_lo, comment_hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + } + _ => (), + } + } + } + } + + match context.config.brace_style() { + _ if last_line_contains_single_line_comment(&result) => { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } + BraceStyle::AlwaysNextLine => { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() + && (!trait_items.is_empty() || result.contains('\n')) + { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push(' '); + } + } + } + result.push('{'); + + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + + if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = offset.block_only().block_indent(context.config); + visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); + + for item in trait_items { + visitor.visit_trait_item(item); + } + + visitor.format_missing(item.span.hi() - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string(context.config); + let outer_indent_str = offset.block_only().to_string(context.config); + + result.push('\n'); + result.push_str(&inner_indent_str); + result.push_str(visitor.buffer.to_string().trim()); + result.push('\n'); + result.push_str(&outer_indent_str); + } else if result.contains('\n') { + result.push('\n'); + } + + result.push('}'); + Some(result) + } else { + unreachable!(); + } +} + +pub fn format_trait_alias( + context: &RewriteContext, + ident: ast::Ident, + generics: &ast::Generics, + ty_param_bounds: &ast::TyParamBounds, + shape: Shape, +) -> Option { + let alias = ident.name.as_str(); + // 6 = "trait ", 2 = " =" + let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?; + let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?; + let lhs = format!("trait {}{} =", alias, generics_str); + // 1 = ";" + rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") +} + +fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { + let header_str = format_header(p.prefix, p.ident, p.vis); + let generics_str = if let Some(generics) = p.generics { + let hi = if generics.where_clause.predicates.is_empty() { + generics.span.hi() + } else { + generics.where_clause.span.hi() + }; + format_generics( + context, + generics, + context.config.brace_style(), + BracePos::None, + offset, + mk_sp(generics.span.lo(), hi), + last_line_width(&header_str), + )? + } else { + String::new() + }; + Some(format!("{}{};", header_str, generics_str)) +} + +pub fn format_struct_struct( + context: &RewriteContext, + struct_parts: &StructParts, + fields: &[ast::StructField], + offset: Indent, + one_line_width: Option, +) -> Option { + let mut result = String::with_capacity(1024); + let span = struct_parts.span; + + let header_str = struct_parts.format_header(); + result.push_str(&header_str); + + let header_hi = span.lo() + BytePos(header_str.len() as u32); + let body_lo = context.codemap.span_after(span, "{"); + + let generics_str = match struct_parts.generics { + Some(g) => format_generics( + context, + g, + context.config.brace_style(), + if fields.is_empty() { + BracePos::ForceSameLine + } else { + BracePos::Auto + }, + offset, + mk_sp(header_hi, body_lo), + last_line_width(&result), + )?, + None => { + // 3 = ` {}`, 2 = ` {`. + let overhead = if fields.is_empty() { 3 } else { 2 }; + if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty()) + || context.config.max_width() < overhead + result.len() + { + format!("\n{}{{", offset.block_only().to_string(context.config)) + } else { + " {".to_owned() + } + } + }; + // 1 = `}` + let overhead = if fields.is_empty() { 1 } else { 0 }; + let total_width = result.len() + generics_str.len() + overhead; + if !generics_str.is_empty() && !generics_str.contains('\n') + && total_width > context.config.max_width() + { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + result.push_str(generics_str.trim_left()); + } else { + result.push_str(&generics_str); + } + + if fields.is_empty() { + let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1))); + if snippet.trim().is_empty() { + // `struct S {}` + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { + // fix indent + result.push_str(snippet.trim_right()); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push_str(snippet); + } + result.push('}'); + return Some(result); + } + + // 3 = ` ` and ` }` + let one_line_budget = context.budget(result.len() + 3 + offset.width()); + let one_line_budget = + one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); + + let items_str = rewrite_with_alignment( + fields, + context, + Shape::indented(offset, context.config).sub_width(1)?, + mk_sp(body_lo, span.hi()), + one_line_budget, + )?; + + if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget { + Some(format!("{} {} }}", result, items_str)) + } else { + Some(format!( + "{}\n{}{}\n{}}}", + result, + offset + .block_indent(context.config) + .to_string(context.config), + items_str, + offset.to_string(context.config) + )) + } +} + +/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not +/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need +/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args. +fn get_bytepos_after_visibility( + context: &RewriteContext, + vis: &ast::Visibility, + default_span: Span, + terminator: &str, +) -> BytePos { + match *vis { + ast::Visibility::Crate(s, CrateSugar::PubCrate) => context + .codemap + .span_after(mk_sp(s.hi(), default_span.hi()), terminator), + ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), + ast::Visibility::Restricted { ref path, .. } => path.span.hi(), + _ => default_span.lo(), + } +} + +fn format_tuple_struct( + context: &RewriteContext, + struct_parts: &StructParts, + fields: &[ast::StructField], + offset: Indent, +) -> Option { + let mut result = String::with_capacity(1024); + let span = struct_parts.span; + + let header_str = struct_parts.format_header(); + result.push_str(&header_str); + + let body_lo = if fields.is_empty() { + let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")"); + context.codemap.span_after(mk_sp(lo, span.hi()), "(") + } else { + fields[0].span.lo() + }; + let body_hi = if fields.is_empty() { + context.codemap.span_after(mk_sp(body_lo, span.hi()), ")") + } else { + // This is a dirty hack to work around a missing `)` from the span of the last field. + let last_arg_span = fields[fields.len() - 1].span; + if context.snippet(last_arg_span).ends_with(')') { + last_arg_span.hi() + } else { + context + .codemap + .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") + } + }; + + let where_clause_str = match struct_parts.generics { + Some(generics) => { + let budget = context.budget(last_line_width(&header_str)); + let shape = Shape::legacy(budget, offset); + let g_span = mk_sp(span.lo(), body_lo); + let generics_str = rewrite_generics(context, generics, shape, g_span)?; + result.push_str(&generics_str); + + let where_budget = context.budget(last_line_width(&result)); + let option = WhereClauseOption::new(true, false); + rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + Density::Compressed, + ";", + None, + body_hi, + option, + false, + )? + } + None => "".to_owned(), + }; + + if fields.is_empty() { + // 3 = `();` + let used_width = last_line_used_width(&result, offset.width()) + 3; + if used_width > context.config.max_width() { + result.push('\n'); + result.push_str(&offset + .block_indent(context.config) + .to_string(context.config)) + } + result.push('('); + let snippet = context.snippet(mk_sp( + body_lo, + context.codemap.span_before(mk_sp(body_lo, span.hi()), ")"), + )); + if snippet.is_empty() { + // `struct S ()` + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { + result.push_str(snippet.trim_right()); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push_str(snippet); + } + result.push(')'); + } else { + let shape = Shape::indented(offset, context.config).sub_width(1)?; + let fields = &fields.iter().collect::>()[..]; + let one_line_width = context.config.width_heuristics().fn_call_width; + result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; + } + + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') + && (result.contains('\n') + || offset.block_indent + result.len() + where_clause_str.len() + 1 + > context.config.max_width()) + { + // We need to put the where clause on a new line, but we didn't + // know that earlier, so the where clause will not be indented properly. + result.push('\n'); + result + .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) + .to_string(context.config)); + } + result.push_str(&where_clause_str); + + Some(result) +} + +pub fn rewrite_type_alias( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + ty: &ast::Ty, + generics: &ast::Generics, + vis: &ast::Visibility, + span: Span, +) -> Option { + let mut result = String::with_capacity(128); + + result.push_str(&format_visibility(vis)); + result.push_str("type "); + result.push_str(&ident.to_string()); + + // 2 = `= ` + let g_shape = Shape::indented(indent, context.config) + .offset_left(result.len())? + .sub_width(2)?; + let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo()); + let generics_str = rewrite_generics(context, generics, g_shape, g_span)?; + result.push_str(&generics_str); + + let where_budget = context.budget(last_line_width(&result)); + let option = WhereClauseOption::snuggled(&result); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, indent), + Density::Vertical, + "=", + Some(span.hi()), + generics.span.hi(), + option, + false, + )?; + result.push_str(&where_clause_str); + if where_clause_str.is_empty() { + result.push_str(" ="); + } else { + result.push_str(&format!("\n{}=", indent.to_string(context.config))); + } + + // 1 = ";" + let ty_shape = Shape::indented(indent, context.config).sub_width(1)?; + rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";") +} + +fn type_annotation_spacing(config: &Config) -> (&str, &str) { + ( + if config.space_before_colon() { " " } else { "" }, + if config.space_after_colon() { " " } else { "" }, + ) +} + +pub fn rewrite_struct_field_prefix( + context: &RewriteContext, + field: &ast::StructField, +) -> Option { + let vis = format_visibility(&field.vis); + let type_annotation_spacing = type_annotation_spacing(context.config); + Some(match field.ident { + Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), + None => format!("{}", vis), + }) +} + +impl Rewrite for ast::StructField { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_struct_field(context, self, shape, 0) + } +} + +pub fn rewrite_struct_field( + context: &RewriteContext, + field: &ast::StructField, + shape: Shape, + lhs_max_width: usize, +) -> Option { + if contains_skip(&field.attrs) { + return Some(context.snippet(field.span()).to_owned()); + } + + let type_annotation_spacing = type_annotation_spacing(context.config); + let prefix = rewrite_struct_field_prefix(context, field)?; + + let attrs_str = field.attrs.rewrite(context, shape)?; + let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str); + let missing_span = if field.attrs.is_empty() { + mk_sp(field.span.lo(), field.span.lo()) + } else { + mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo()) + }; + let mut spacing = String::from(if field.ident.is_some() { + type_annotation_spacing.1 + } else { + "" + }); + // Try to put everything on a single line. + let attr_prefix = combine_strs_with_missing_comments( + context, + &attrs_str, + &prefix, + missing_span, + shape, + attrs_extendable, + )?; + let overhead = last_line_width(&attr_prefix); + let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); + for _ in 0..lhs_offset { + spacing.push(' '); + } + // In this extreme case we will be missing a space betweeen an attribute and a field. + if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { + spacing.push(' '); + } + let orig_ty = shape + .offset_left(overhead + spacing.len()) + .and_then(|ty_shape| field.ty.rewrite(context, ty_shape)); + if let Some(ref ty) = orig_ty { + if !ty.contains('\n') { + return Some(attr_prefix + &spacing + ty); + } + } + + let is_prefix_empty = prefix.is_empty(); + // We must use multiline. We are going to put attributes and a field on different lines. + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; + // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. + let field_str = if is_prefix_empty { + field_str.trim_left() + } else { + &field_str + }; + combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) +} + +pub struct StaticParts<'a> { + prefix: &'a str, + vis: &'a ast::Visibility, + ident: ast::Ident, + ty: &'a ast::Ty, + mutability: ast::Mutability, + expr_opt: Option<&'a ptr::P>, + defaultness: Option, + span: Span, +} + +impl<'a> StaticParts<'a> { + pub fn from_item(item: &'a ast::Item) -> Self { + let (prefix, ty, mutability, expr) = match item.node { + ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), + ast::ItemKind::Const(ref ty, ref expr) => { + ("const", ty, ast::Mutability::Immutable, expr) + } + _ => unreachable!(), + }; + StaticParts { + prefix, + vis: &item.vis, + ident: item.ident, + ty, + mutability, + expr_opt: Some(expr), + defaultness: None, + span: item.span, + } + } + + pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self { + let (ty, expr_opt) = match ti.node { + ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), + _ => unreachable!(), + }; + StaticParts { + prefix: "const", + vis: &ast::Visibility::Inherited, + ident: ti.ident, + ty, + mutability: ast::Mutability::Immutable, + expr_opt: expr_opt.as_ref(), + defaultness: None, + span: ti.span, + } + } + + pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self { + let (ty, expr) = match ii.node { + ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), + _ => unreachable!(), + }; + StaticParts { + prefix: "const", + vis: &ii.vis, + ident: ii.ident, + ty, + mutability: ast::Mutability::Immutable, + expr_opt: Some(expr), + defaultness: Some(ii.defaultness), + span: ii.span, + } + } +} + +fn rewrite_static( + context: &RewriteContext, + static_parts: &StaticParts, + offset: Indent, +) -> Option { + let colon = colon_spaces( + context.config.space_before_colon(), + context.config.space_after_colon(), + ); + let mut prefix = format!( + "{}{}{} {}{}{}", + format_visibility(static_parts.vis), + static_parts.defaultness.map_or("", format_defaultness), + static_parts.prefix, + format_mutability(static_parts.mutability), + static_parts.ident, + colon, + ); + // 2 = " =".len() + let ty_shape = + Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; + let ty_str = match static_parts.ty.rewrite(context, ty_shape) { + Some(ty_str) => ty_str, + None => { + if prefix.ends_with(' ') { + prefix.pop(); + } + let nested_indent = offset.block_indent(context.config); + let nested_shape = Shape::indented(nested_indent, context.config); + let ty_str = static_parts.ty.rewrite(context, nested_shape)?; + format!("\n{}{}", nested_indent.to_string(context.config), ty_str) + } + }; + + if let Some(expr) = static_parts.expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.budget(offset.block_indent + 1); + rewrite_assign_rhs( + context, + lhs, + &**expr, + Shape::legacy(remaining_width, offset.block_only()), + ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) + .map(|s| if s.ends_with(';') { s } else { s + ";" }) + } else { + Some(format!("{}{};", prefix, ty_str)) + } +} + +pub fn rewrite_associated_type( + ident: ast::Ident, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent, +) -> Option { + let prefix = format!("type {}", ident); + + let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { + // 2 = ": ".len() + let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; + let bound_str = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; + if !bounds.is_empty() { + format!(": {}", join_bounds(context, shape, &bound_str)) + } else { + String::new() + } + } else { + String::new() + }; + + if let Some(ty) = ty_opt { + // 1 = `;` + let shape = Shape::indented(indent, context.config).sub_width(1)?; + let lhs = format!("{}{} =", prefix, type_bounds_str); + rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") + } else { + Some(format!("{}{};", prefix, type_bounds_str)) + } +} + +pub fn rewrite_associated_impl_type( + ident: ast::Ident, + defaultness: ast::Defaultness, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent, +) -> Option { + let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?; + + match defaultness { + ast::Defaultness::Default => Some(format!("default {}", result)), + _ => Some(result), + } +} + +impl Rewrite for ast::FunctionRetTy { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::FunctionRetTy::Default(_) => Some(String::new()), + ast::FunctionRetTy::Ty(ref ty) => { + let inner_width = shape.width.checked_sub(3)?; + ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) + .map(|r| format!("-> {}", r)) + } + } + } +} + +fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { + match ty.node { + ast::TyKind::Infer => { + let original = context.snippet(ty.span); + original != "_" + } + _ => false, + } +} + +impl Rewrite for ast::Arg { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + if is_named_arg(self) { + let mut result = self.pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))?; + + if !is_empty_infer(context, &*self.ty) { + if context.config.space_before_colon() { + result.push_str(" "); + } + result.push_str(":"); + if context.config.space_after_colon() { + result.push_str(" "); + } + let overhead = last_line_width(&result); + let max_width = shape.width.checked_sub(overhead)?; + let ty_str = self.ty + .rewrite(context, Shape::legacy(max_width, shape.indent))?; + result.push_str(&ty_str); + } + + Some(result) + } else { + self.ty.rewrite(context, shape) + } + } +} + +fn rewrite_explicit_self( + explicit_self: &ast::ExplicitSelf, + args: &[ast::Arg], + context: &RewriteContext, +) -> Option { + match explicit_self.node { + ast::SelfKind::Region(lt, m) => { + let mut_str = format_mutability(m); + match lt { + Some(ref l) => { + let lifetime_str = l.rewrite( + context, + Shape::legacy(context.config.max_width(), Indent::empty()), + )?; + Some(format!("&{} {}self", lifetime_str, mut_str)) + } + None => Some(format!("&{}self", mut_str)), + } + } + ast::SelfKind::Explicit(ref ty, _) => { + assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); + + let mutability = explicit_self_mutability(&args[0]); + let type_str = ty.rewrite( + context, + Shape::legacy(context.config.max_width(), Indent::empty()), + )?; + + Some(format!( + "{}self: {}", + format_mutability(mutability), + type_str + )) + } + ast::SelfKind::Value(_) => { + assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); + + let mutability = explicit_self_mutability(&args[0]); + + Some(format!("{}self", format_mutability(mutability))) + } + } +} + +// Hacky solution caused by absence of `Mutability` in `SelfValue` and +// `SelfExplicit` variants of `ast::ExplicitSelf_`. +fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { + if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node { + mutability + } else { + unreachable!() + } +} + +pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { + if is_named_arg(arg) { + arg.pat.span.lo() + } else { + arg.ty.span.lo() + } +} + +pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { + match arg.ty.node { + ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), + ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), + _ => arg.ty.span.hi(), + } +} + +pub fn is_named_arg(arg: &ast::Arg) -> bool { + if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { + ident.node != symbol::keywords::Invalid.ident() + } else { + true + } +} + +// Return type is (result, force_new_line_for_brace) +fn rewrite_fn_base( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + fn_sig: &FnSig, + span: Span, + newline_brace: bool, + has_body: bool, +) -> Option<(String, bool)> { + let mut force_new_line_for_brace = false; + + let where_clause = &fn_sig.generics.where_clause; + + let mut result = String::with_capacity(1024); + result.push_str(&fn_sig.to_str(context)); + + // fn foo + result.push_str("fn "); + result.push_str(&ident.to_string()); + + // Generics. + let overhead = if has_body && !newline_brace { + // 4 = `() {` + 4 + } else { + // 2 = `()` + 2 + }; + let used_width = last_line_used_width(&result, indent.width()); + let one_line_budget = context.budget(used_width + overhead); + let shape = Shape { + width: one_line_budget, + indent, + offset: used_width, + }; + let fd = fn_sig.decl; + let g_span = mk_sp(span.lo(), fd.output.span().lo()); + let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?; + result.push_str(&generics_str); + + let snuggle_angle_bracket = generics_str + .lines() + .last() + .map_or(false, |l| l.trim_left().len() == 1); + + // Note that the width and indent don't really matter, we'll re-layout the + // return type later anyway. + let ret_str = fd.output + .rewrite(context, Shape::indented(indent, context.config))?; + + let multi_line_ret_str = ret_str.contains('\n'); + let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; + + // Args. + let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args( + context, + &result, + indent, + ret_str_len, + newline_brace, + has_body, + multi_line_ret_str, + )?; + + debug!( + "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", + one_line_budget, multi_line_budget, arg_indent + ); + + // Check if vertical layout was forced. + if one_line_budget == 0 { + if snuggle_angle_bracket { + result.push('('); + } else { + result.push_str("("); + if context.config.indent_style() == IndentStyle::Visual { + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + } + } + } else { + result.push('('); + } + if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() + && result.ends_with('(') + { + result.push(' ') + } + + // Skip `pub(crate)`. + let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")"); + // A conservative estimation, to goal is to be over all parens in generics + let args_start = fn_sig + .generics + .params + .iter() + .last() + .map_or(lo_after_visibility, |param| param.span().hi()); + let args_end = if fd.inputs.is_empty() { + context + .codemap + .span_after(mk_sp(args_start, span.hi()), ")") + } else { + let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); + context.codemap.span_after(last_span, ")") + }; + let args_span = mk_sp( + context + .codemap + .span_after(mk_sp(args_start, span.hi()), "("), + args_end, + ); + let arg_str = rewrite_args( + context, + &fd.inputs, + fd.get_self().as_ref(), + one_line_budget, + multi_line_budget, + indent, + arg_indent, + args_span, + fd.variadic, + generics_str.contains('\n'), + )?; + + let put_args_in_block = match context.config.indent_style() { + IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, + _ => false, + } && !fd.inputs.is_empty(); + + let mut args_last_line_contains_comment = false; + if put_args_in_block { + arg_indent = indent.block_indent(context.config); + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + result.push_str(&arg_str); + result.push('\n'); + result.push_str(&indent.to_string(context.config)); + result.push(')'); + } else { + result.push_str(&arg_str); + let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); + // Put the closing brace on the next line if it overflows the max width. + // 1 = `)` + if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { + result.push('\n'); + } + if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() { + result.push(' ') + } + // If the last line of args contains comment, we cannot put the closing paren + // on the same line. + if arg_str + .lines() + .last() + .map_or(false, |last_line| last_line.contains("//")) + { + args_last_line_contains_comment = true; + result.push('\n'); + result.push_str(&arg_indent.to_string(context.config)); + } + result.push(')'); + } + + // Return type. + if let ast::FunctionRetTy::Ty(..) = fd.output { + let ret_should_indent = match context.config.indent_style() { + // If our args are block layout then we surely must have space. + IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, + _ if args_last_line_contains_comment => false, + _ if result.contains('\n') || multi_line_ret_str => true, + _ => { + // If the return type would push over the max width, then put the return type on + // a new line. With the +1 for the signature length an additional space between + // the closing parenthesis of the argument and the arrow '->' is considered. + let mut sig_length = result.len() + indent.width() + ret_str_len + 1; + + // If there is no where clause, take into account the space after the return type + // and the brace. + if where_clause.predicates.is_empty() { + sig_length += 2; + } + + sig_length > context.config.max_width() + } + }; + let ret_indent = if ret_should_indent { + let indent = if arg_str.is_empty() { + // Aligning with non-existent args looks silly. + force_new_line_for_brace = true; + indent + 4 + } else { + // FIXME: we might want to check that using the arg indent + // doesn't blow our budget, and if it does, then fallback to + // the where clause indent. + arg_indent + }; + + result.push('\n'); + result.push_str(&indent.to_string(context.config)); + indent + } else { + result.push(' '); + Indent::new(indent.block_indent, last_line_width(&result)) + }; + + if multi_line_ret_str || ret_should_indent { + // Now that we know the proper indent and width, we need to + // re-layout the return type. + let ret_str = fd.output + .rewrite(context, Shape::indented(ret_indent, context.config))?; + result.push_str(&ret_str); + } else { + result.push_str(&ret_str); + } + + // Comment between return type and the end of the decl. + let snippet_lo = fd.output.span().hi(); + if where_clause.predicates.is_empty() { + let snippet_hi = span.hi(); + let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); + // Try to preserve the layout of the original snippet. + let original_starts_with_newline = snippet + .find(|c| c != ' ') + .map_or(false, |i| starts_with_newline(&snippet[i..])); + let original_ends_with_newline = snippet + .rfind(|c| c != ' ') + .map_or(false, |i| snippet[i..].ends_with('\n')); + let snippet = snippet.trim(); + if !snippet.is_empty() { + result.push(if original_starts_with_newline { + '\n' + } else { + ' ' + }); + result.push_str(snippet); + if original_ends_with_newline { + force_new_line_for_brace = true; + } + } + } + } + + let pos_before_where = match fd.output { + ast::FunctionRetTy::Default(..) => args_span.hi(), + ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), + }; + + let is_args_multi_lined = arg_str.contains('\n'); + + let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); + let where_clause_str = rewrite_where_clause( + context, + where_clause, + context.config.brace_style(), + Shape::indented(indent, context.config), + Density::Tall, + "{", + Some(span.hi()), + pos_before_where, + option, + is_args_multi_lined, + )?; + // If there are neither where clause nor return type, we may be missing comments between + // args and `{`. + if where_clause_str.is_empty() { + if let ast::FunctionRetTy::Default(ret_span) = fd.output { + match recover_missing_comment_in_span( + mk_sp(args_span.hi(), ret_span.hi()), + shape, + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + force_new_line_for_brace = true; + } + _ => (), + } + } + } + + result.push_str(&where_clause_str); + + force_new_line_for_brace |= last_line_contains_single_line_comment(&result); + force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line(); + Some((result, force_new_line_for_brace)) +} + +#[derive(Copy, Clone)] +struct WhereClauseOption { + suppress_comma: bool, // Force no trailing comma + snuggle: bool, // Do not insert newline before `where` + compress_where: bool, // Try single line where clause instead of vertical layout +} + +impl WhereClauseOption { + pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { + WhereClauseOption { + suppress_comma, + snuggle, + compress_where: false, + } + } + + pub fn snuggled(current: &str) -> WhereClauseOption { + WhereClauseOption { + suppress_comma: false, + snuggle: trimmed_last_line_width(current) == 1, + compress_where: false, + } + } +} + +fn rewrite_args( + context: &RewriteContext, + args: &[ast::Arg], + explicit_self: Option<&ast::ExplicitSelf>, + one_line_budget: usize, + multi_line_budget: usize, + indent: Indent, + arg_indent: Indent, + span: Span, + variadic: bool, + generics_str_contains_newline: bool, +) -> Option { + let mut arg_item_strs = args.iter() + .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) + .collect::>>()?; + + // Account for sugary self. + // FIXME: the comment for the self argument is dropped. This is blocked + // on rust issue #27522. + let min_args = explicit_self + .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) + .map_or(1, |self_str| { + arg_item_strs[0] = self_str; + 2 + }); + + // Comments between args. + let mut arg_items = Vec::new(); + if min_args == 2 { + arg_items.push(ListItem::from_str("")); + } + + // FIXME(#21): if there are no args, there might still be a comment, but + // without spans for the comment or parens, there is no chance of + // getting it right. You also don't get to put a comment on self, unless + // it is explicit. + if args.len() >= min_args || variadic { + let comment_span_start = if min_args == 2 { + let second_arg_start = if arg_has_pattern(&args[1]) { + args[1].pat.span.lo() + } else { + args[1].ty.span.lo() + }; + let reduced_span = mk_sp(span.lo(), second_arg_start); + + context.codemap.span_after_last(reduced_span, ",") + } else { + span.lo() + }; + + enum ArgumentKind<'a> { + Regular(&'a ast::Arg), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi()); + let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + + let more_items = itemize_list( + context.codemap, + args[min_args - 1..] + .iter() + .map(ArgumentKind::Regular) + .chain(variadic_arg), + ")", + ",", + |arg| match *arg { + ArgumentKind::Regular(arg) => span_lo_for_arg(arg), + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(arg) => arg.ty.span.hi(), + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(..) => None, + ArgumentKind::Variadic(..) => Some("...".to_owned()), + }, + comment_span_start, + span.hi(), + false, + ); + + arg_items.extend(more_items); + } + + let fits_in_one_line = !generics_str_contains_newline + && (arg_items.is_empty() + || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + + for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { + item.item = Some(arg); + } + + let last_line_ends_with_comment = arg_items + .iter() + .last() + .and_then(|item| item.post_comment.as_ref()) + .map_or(false, |s| s.trim().starts_with("//")); + + let (indent, trailing_comma) = match context.config.indent_style() { + IndentStyle::Block if fits_in_one_line => { + (indent.block_indent(context.config), SeparatorTactic::Never) + } + IndentStyle::Block => ( + indent.block_indent(context.config), + context.config.trailing_comma(), + ), + IndentStyle::Visual if last_line_ends_with_comment => { + (arg_indent, context.config.trailing_comma()) + } + IndentStyle::Visual => (arg_indent, SeparatorTactic::Never), + }; + + let tactic = definitive_tactic( + &arg_items, + context.config.fn_args_density().to_list_tactic(), + Separator::Comma, + one_line_budget, + ); + let budget = match tactic { + DefinitiveListTactic::Horizontal => one_line_budget, + _ => multi_line_budget, + }; + + debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if variadic { + SeparatorTactic::Never + } else { + trailing_comma + }, + separator_place: SeparatorPlace::Back, + shape: Shape::legacy(budget, indent), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + + write_list(&arg_items, &fmt) +} + +fn arg_has_pattern(arg: &ast::Arg) -> bool { + if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { + ident.node != symbol::keywords::Invalid.ident() + } else { + true + } +} + +fn compute_budgets_for_args( + context: &RewriteContext, + result: &str, + indent: Indent, + ret_str_len: usize, + newline_brace: bool, + has_braces: bool, + force_vertical_layout: bool, +) -> Option<((usize, usize, Indent))> { + debug!( + "compute_budgets_for_args {} {:?}, {}, {}", + result.len(), + indent, + ret_str_len, + newline_brace + ); + // Try keeping everything on the same line. + if !result.contains('\n') && !force_vertical_layout { + // 2 = `()`, 3 = `() `, space is before ret_string. + let overhead = if ret_str_len == 0 { 2 } else { 3 }; + let mut used_space = indent.width() + result.len() + ret_str_len + overhead; + if has_braces { + if !newline_brace { + // 2 = `{}` + used_space += 2; + } + } else { + // 1 = `;` + used_space += 1; + } + let one_line_budget = context.budget(used_space); + + if one_line_budget > 0 { + // 4 = "() {".len() + let (indent, multi_line_budget) = match context.config.indent_style() { + IndentStyle::Block => { + let indent = indent.block_indent(context.config); + (indent, context.budget(indent.width() + 1)) + } + IndentStyle::Visual => { + let indent = indent + result.len() + 1; + let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; + (indent, context.budget(multi_line_overhead)) + } + }; + + return Some((one_line_budget, multi_line_budget, indent)); + } + } + + // Didn't work. we must force vertical layout and put args on a newline. + let new_indent = indent.block_indent(context.config); + let used_space = match context.config.indent_style() { + // 1 = `,` + IndentStyle::Block => new_indent.width() + 1, + // Account for `)` and possibly ` {`. + IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, + }; + Some((0, context.budget(used_space), new_indent)) +} + +fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { + let predicate_count = where_clause.predicates.len(); + + if config.where_single_line() && predicate_count == 1 { + return false; + } + let brace_style = config.brace_style(); + + brace_style == BraceStyle::AlwaysNextLine + || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0) +} + +fn rewrite_generics( + context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + span: Span, +) -> Option { + let g_shape = generics_shape_from_config(context.config, shape, 0)?; + let one_line_width = shape.width.checked_sub(2).unwrap_or(0); + rewrite_generics_inner(context, generics, g_shape, one_line_width, span) + .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span)) +} + +fn rewrite_generics_inner( + context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + one_line_width: usize, + span: Span, +) -> Option { + // FIXME: convert bounds to where clauses where they get too big or if + // there is a where clause at all. + + if generics.params.is_empty() { + return Some(String::new()); + } + + let items = itemize_list( + context.codemap, + generics.params.iter(), + ">", + ",", + |arg| arg.span().lo(), + |arg| arg.span().hi(), + |arg| arg.rewrite(context, shape), + context.codemap.span_after(span, "<"), + span.hi(), + false, + ); + format_generics_item_list(context, items, shape, one_line_width) +} + +pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { + match config.indent_style() { + IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), + IndentStyle::Block => { + // 1 = "," + shape + .block() + .block_indent(config.tab_spaces()) + .with_max_width(config) + .sub_width(1) + } + } +} + +pub fn format_generics_item_list( + context: &RewriteContext, + items: I, + shape: Shape, + one_line_budget: usize, +) -> Option +where + I: Iterator, +{ + let item_vec = items.collect::>(); + + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + one_line_budget, + ); + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if context.config.indent_style() == IndentStyle::Visual { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + + let list_str = write_list(&item_vec, &fmt)?; + + Some(wrap_generics_with_angle_brackets( + context, + &list_str, + shape.indent, + )) +} + +pub fn wrap_generics_with_angle_brackets( + context: &RewriteContext, + list_str: &str, + list_offset: Indent, +) -> String { + if context.config.indent_style() == IndentStyle::Block + && (list_str.contains('\n') || list_str.ends_with(',')) + { + format!( + "<\n{}{}\n{}>", + list_offset.to_string(context.config), + list_str, + list_offset + .block_unindent(context.config) + .to_string(context.config) + ) + } else if context.config.spaces_within_parens_and_brackets() { + format!("< {} >", list_str) + } else { + format!("<{}>", list_str) + } +} + +fn rewrite_trait_bounds( + context: &RewriteContext, + bounds: &[ast::TyParamBound], + shape: Shape, +) -> Option { + if bounds.is_empty() { + return Some(String::new()); + } + let bound_str = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; + Some(format!(": {}", join_bounds(context, shape, &bound_str))) +} + +fn rewrite_where_clause_rfc_style( + context: &RewriteContext, + where_clause: &ast::WhereClause, + shape: Shape, + terminator: &str, + span_end: Option, + span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, + is_args_multi_line: bool, +) -> Option { + let block_shape = shape.block().with_max_width(context.config); + + let (span_before, span_after) = + missing_span_before_after_where(span_end_before_where, where_clause); + let (comment_before, comment_after) = + rewrite_comments_before_after_where(context, span_before, span_after, shape)?; + + let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { + " ".to_owned() + } else { + "\n".to_owned() + &block_shape.indent.to_string(context.config) + }; + + let clause_shape = block_shape.block_left(context.config.tab_spaces())?; + // 1 = `,` + let clause_shape = clause_shape.sub_width(1)?; + // each clause on one line, trailing comma (except if suppress_comma) + let span_start = where_clause.predicates[0].span().lo(); + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = where_clause.predicates[len - 1].span().hi(); + let span_end = span_end.unwrap_or(end_of_preds); + let items = itemize_list( + context.codemap, + where_clause.predicates.iter(), + terminator, + ",", + |pred| pred.span().lo(), + |pred| pred.span().hi(), + |pred| pred.rewrite(context, clause_shape), + span_start, + span_end, + false, + ); + let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line; + let comma_tactic = if where_clause_option.suppress_comma || where_single_line { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }; + + // shape should be vertical only and only if we have `where_single_line` option enabled + // and the number of items of the where clause is equal to 1 + let shape_tactic = if where_single_line { + DefinitiveListTactic::Horizontal + } else { + DefinitiveListTactic::Vertical + }; + + let fmt = ListFormatting { + tactic: shape_tactic, + separator: ",", + trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, + shape: clause_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + let preds_str = write_list(&items.collect::>(), &fmt)?; + + let comment_separator = |comment: &str, shape: Shape| { + if comment.is_empty() { + String::new() + } else { + format!("\n{}", shape.indent.to_string(context.config)) + } + }; + let newline_before_where = comment_separator(&comment_before, shape); + let newline_after_where = comment_separator(&comment_after, clause_shape); + + // 6 = `where ` + let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() + && comment_after.is_empty() && !preds_str.contains('\n') + && 6 + preds_str.len() <= shape.width || where_single_line + { + String::from(" ") + } else { + format!("\n{}", clause_shape.indent.to_string(context.config)) + }; + Some(format!( + "{}{}{}where{}{}{}{}", + starting_newline, + comment_before, + newline_before_where, + newline_after_where, + comment_after, + clause_sep, + preds_str + )) +} + +fn rewrite_where_clause( + context: &RewriteContext, + where_clause: &ast::WhereClause, + brace_style: BraceStyle, + shape: Shape, + density: Density, + terminator: &str, + span_end: Option, + span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, + is_args_multi_line: bool, +) -> Option { + if where_clause.predicates.is_empty() { + return Some(String::new()); + } + + if context.config.indent_style() == IndentStyle::Block { + return rewrite_where_clause_rfc_style( + context, + where_clause, + shape, + terminator, + span_end, + span_end_before_where, + where_clause_option, + is_args_multi_line, + ); + } + + let extra_indent = Indent::new(context.config.tab_spaces(), 0); + + let offset = match context.config.indent_style() { + IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), + // 6 = "where ".len() + IndentStyle::Visual => shape.indent + extra_indent + 6, + }; + // FIXME: if indent_style != Visual, then the budgets below might + // be out by a char or two. + + let budget = context.config.max_width() - offset.width(); + let span_start = where_clause.predicates[0].span().lo(); + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = where_clause.predicates[len - 1].span().hi(); + let span_end = span_end.unwrap_or(end_of_preds); + let items = itemize_list( + context.codemap, + where_clause.predicates.iter(), + terminator, + ",", + |pred| pred.span().lo(), + |pred| pred.span().hi(), + |pred| pred.rewrite(context, Shape::legacy(budget, offset)), + span_start, + span_end, + false, + ); + let item_vec = items.collect::>(); + // FIXME: we don't need to collect here + let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget); + + let mut comma_tactic = context.config.trailing_comma(); + // Kind of a hack because we don't usually have trailing commas in where clauses. + if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma { + comma_tactic = SeparatorTactic::Never; + } + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, + shape: Shape::legacy(budget, offset), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + let preds_str = write_list(&item_vec, &fmt)?; + + let end_length = if terminator == "{" { + // If the brace is on the next line we don't need to count it otherwise it needs two + // characters " {" + match brace_style { + BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0, + BraceStyle::PreferSameLine => 2, + } + } else if terminator == "=" { + 2 + } else { + terminator.len() + }; + if density == Density::Tall || preds_str.contains('\n') + || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width + { + Some(format!( + "\n{}where {}", + (shape.indent + extra_indent).to_string(context.config), + preds_str + )) + } else { + Some(format!(" where {}", preds_str)) + } +} + +fn missing_span_before_after_where( + before_item_span_end: BytePos, + where_clause: &ast::WhereClause, +) -> (Span, Span) { + let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo()); + // 5 = `where` + let pos_after_where = where_clause.span.lo() + BytePos(5); + let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo()); + (missing_span_before, missing_span_after) +} + +fn rewrite_comments_before_after_where( + context: &RewriteContext, + span_before_where: Span, + span_after_where: Span, + shape: Shape, +) -> Option<(String, String)> { + let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; + let after_comment = rewrite_missing_comment( + span_after_where, + shape.block_indent(context.config.tab_spaces()), + context, + )?; + Some((before_comment, after_comment)) +} + +fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { + format!("{}{}{}", format_visibility(vis), item_name, ident) +} + +#[derive(PartialEq, Eq, Clone, Copy)] +enum BracePos { + None, + Auto, + ForceSameLine, +} + +fn format_generics( + context: &RewriteContext, + generics: &ast::Generics, + brace_style: BraceStyle, + brace_pos: BracePos, + offset: Indent, + span: Span, + used_width: usize, +) -> Option { + let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); + let mut result = rewrite_generics(context, generics, shape, span)?; + + let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { + let budget = context.budget(last_line_used_width(&result, offset.width())); + let mut option = WhereClauseOption::snuggled(&result); + if brace_pos == BracePos::None { + option.suppress_comma = true; + } + // If the generics are not parameterized then generics.span.hi() == 0, + // so we use span.lo(), which is the position after `struct Foo`. + let span_end_before_where = if generics.is_parameterized() { + generics.span.hi() + } else { + span.lo() + }; + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + brace_style, + Shape::legacy(budget, offset.block_only()), + Density::Tall, + "{", + Some(span.hi()), + span_end_before_where, + option, + false, + )?; + result.push_str(&where_clause_str); + brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine + || (generics.where_clause.predicates.is_empty() + && trimmed_last_line_width(&result) == 1) + } else { + brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1 + || brace_style != BraceStyle::AlwaysNextLine + }; + if brace_pos == BracePos::None { + return Some(result); + } + let total_used_width = last_line_used_width(&result, used_width); + let remaining_budget = context.budget(total_used_width); + // If the same line brace if forced, it indicates that we are rewriting an item with empty body, + // and hence we take the closer into account as well for one line budget. + // We assume that the closer has the same length as the opener. + let overhead = if brace_pos == BracePos::ForceSameLine { + // 3 = ` {}` + 3 + } else { + // 2 = ` {` + 2 + }; + let forbid_same_line_brace = overhead > remaining_budget; + if !forbid_same_line_brace && same_line_brace { + result.push(' '); + } else { + result.push('\n'); + result.push_str(&offset.block_only().to_string(context.config)); + } + result.push('{'); + + Some(result) +} + +impl Rewrite for ast::ForeignItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = self.attrs.rewrite(context, shape)?; + // Drop semicolon or it will be interpreted as comment. + // FIXME: this may be a faulty span from libsyntax. + let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); + + let item_str = match self.node { + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { + rewrite_fn_base( + context, + shape.indent, + self.ident, + &FnSig::new(fn_decl, generics, self.vis.clone()), + span, + false, + false, + ).map(|(s, _)| format!("{};", s)) + } + ast::ForeignItemKind::Static(ref ty, is_mutable) => { + // FIXME(#21): we're dropping potential comments in between the + // function keywords here. + let vis = format_visibility(&self.vis); + let mut_str = if is_mutable { "mut " } else { "" }; + let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); + // 1 = ; + let shape = shape.sub_width(1)?; + ty.rewrite(context, shape).map(|ty_str| { + // 1 = space between prefix and type. + let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { + String::from(" ") + } else { + let nested_indent = shape.indent.block_indent(context.config); + format!("\n{}", nested_indent.to_string(context.config)) + }; + format!("{}{}{};", prefix, sep, ty_str) + }) + } + ast::ForeignItemKind::Ty => { + let vis = format_visibility(&self.vis); + Some(format!("{}type {};", vis, self.ident)) + } + }?; + + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo(), self.span.lo()) + } else { + mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo()) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missing_span, + shape, + false, + ) + } +} + +impl Rewrite for ast::GenericParam { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape), + ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape), + } + } +} diff --git a/rustfmt-core/src/lib.rs b/rustfmt-core/src/lib.rs new file mode 100644 index 00000000000..785d638756d --- /dev/null +++ b/rustfmt-core/src/lib.rs @@ -0,0 +1,826 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(decl_macro)] +#![feature(match_default_bindings)] +#![feature(type_ascription)] + +#[macro_use] +extern crate derive_new; +extern crate diff; +#[macro_use] +extern crate log; +extern crate regex; +extern crate rustc_errors as errors; +extern crate rustfmt_config as config; +extern crate syntax; +extern crate term; +extern crate unicode_segmentation; + +use std::collections::HashMap; +use std::fmt; +use std::io::{self, stdout, Write}; +use std::iter::repeat; +use std::path::PathBuf; +use std::rc::Rc; +use std::time::Duration; + +use errors::{DiagnosticBuilder, Handler}; +use errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::ast; +use syntax::codemap::{CodeMap, FilePathMapping}; +pub use syntax::codemap::FileName; +use syntax::parse::{self, ParseSess}; + +use checkstyle::{output_footer, output_header}; +use comment::{CharClasses, FullCodeCharKind}; +use issues::{BadIssueSeeker, Issue}; +use shape::Indent; +use utils::use_colored_tty; +use visitor::{FmtVisitor, SnippetProvider}; + +use config::Config; +use config::summary::Summary; + +#[macro_use] +mod utils; +mod chains; +mod checkstyle; +mod closures; +pub mod codemap; +mod comment; +mod expr; +pub mod filemap; +mod imports; +mod issues; +mod items; +mod lists; +mod macros; +mod missed_spans; +pub mod modules; +mod patterns; +mod rewrite; +pub mod rustfmt_diff; +mod shape; +mod spanned; +mod string; +mod types; +mod vertical; +pub mod visitor; + +// A map of the files of a crate, with their new content +pub type FileMap = Vec; + +pub type FileRecord = (FileName, String); + +#[derive(Clone, Copy)] +pub enum ErrorKind { + // Line has exceeded character limit (found, maximum) + LineOverflow(usize, usize), + // Line ends in whitespace + TrailingWhitespace, + // TO-DO or FIX-ME item without an issue number + BadIssue(Issue), +} + +impl fmt::Display for ErrorKind { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ErrorKind::LineOverflow(found, maximum) => write!( + fmt, + "line exceeded maximum width (maximum: {}, found: {})", + maximum, found + ), + ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), + ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), + } + } +} + +// Formatting errors that are identified *after* rustfmt has run. +pub struct FormattingError { + line: usize, + kind: ErrorKind, + is_comment: bool, + is_string: bool, + line_buffer: String, +} + +impl FormattingError { + fn msg_prefix(&self) -> &str { + match self.kind { + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "error:", + ErrorKind::BadIssue(_) => "WARNING:", + } + } + + fn msg_suffix(&self) -> &str { + if self.is_comment || self.is_string { + "set `error_on_unformatted = false` to suppress \ + the warning against comments or string literals\n" + } else { + "" + } + } + + // (space, target) + pub fn format_len(&self) -> (usize, usize) { + match self.kind { + ErrorKind::LineOverflow(found, max) => (max, found - max), + ErrorKind::TrailingWhitespace => { + let trailing_ws_len = self.line_buffer + .chars() + .rev() + .take_while(|c| c.is_whitespace()) + .count(); + (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) + } + _ => unreachable!(), + } + } +} + +pub struct FormatReport { + // Maps stringified file paths to their associated formatting errors. + file_error_map: HashMap>, +} + +impl FormatReport { + fn new() -> FormatReport { + FormatReport { + file_error_map: HashMap::new(), + } + } + + pub fn warning_count(&self) -> usize { + self.file_error_map + .iter() + .map(|(_, errors)| errors.len()) + .sum() + } + + pub fn has_warnings(&self) -> bool { + self.warning_count() > 0 + } + + pub fn print_warnings_fancy( + &self, + mut t: Box>, + ) -> Result<(), term::Error> { + for (file, errors) in &self.file_error_map { + for error in errors { + let prefix_space_len = error.line.to_string().len(); + let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + + // First line: the overview of error + t.fg(term::color::RED)?; + t.attr(term::Attr::Bold)?; + write!(t, "{} ", error.msg_prefix())?; + t.reset()?; + t.attr(term::Attr::Bold)?; + write!(t, "{}\n", error.kind)?; + + // Second line: file info + write!(t, "{}--> ", &prefix_spaces[1..])?; + t.reset()?; + write!(t, "{}:{}\n", file, error.line)?; + + // Third to fifth lines: show the line which triggered error, if available. + if !error.line_buffer.is_empty() { + let (space_len, target_len) = error.format_len(); + t.attr(term::Attr::Bold)?; + write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; + t.reset()?; + write!(t, "{}\n", error.line_buffer)?; + t.attr(term::Attr::Bold)?; + write!(t, "{}| ", prefix_spaces)?; + t.fg(term::color::RED)?; + write!(t, "{}\n", target_str(space_len, target_len))?; + t.reset()?; + } + + // The last line: show note if available. + let msg_suffix = error.msg_suffix(); + if !msg_suffix.is_empty() { + t.attr(term::Attr::Bold)?; + write!(t, "{}= note: ", prefix_spaces)?; + t.reset()?; + write!(t, "{}\n", error.msg_suffix())?; + } else { + write!(t, "\n")?; + } + t.reset()?; + } + } + + if !self.file_error_map.is_empty() { + t.attr(term::Attr::Bold)?; + write!(t, "warning: ")?; + t.reset()?; + write!( + t, + "rustfmt may have failed to format. See previous {} errors.\n\n", + self.warning_count(), + )?; + } + + Ok(()) + } +} + +fn target_str(space_len: usize, target_len: usize) -> String { + let empty_line: String = repeat(" ").take(space_len).collect(); + let overflowed: String = repeat("^").take(target_len).collect(); + empty_line + &overflowed +} + +impl fmt::Display for FormatReport { + // Prints all the formatting errors. + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + for (file, errors) in &self.file_error_map { + for error in errors { + let prefix_space_len = error.line.to_string().len(); + let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + + let error_line_buffer = if error.line_buffer.is_empty() { + String::from(" ") + } else { + let (space_len, target_len) = error.format_len(); + format!( + "{}|\n{} | {}\n{}| {}", + prefix_spaces, + error.line, + error.line_buffer, + prefix_spaces, + target_str(space_len, target_len) + ) + }; + + let error_info = format!("{} {}", error.msg_prefix(), error.kind); + let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line); + let msg_suffix = error.msg_suffix(); + let note = if msg_suffix.is_empty() { + String::new() + } else { + format!("{}note= ", prefix_spaces) + }; + + write!( + fmt, + "{}\n{}\n{}\n{}{}\n", + error_info, + file_info, + error_line_buffer, + note, + error.msg_suffix() + )?; + } + } + if !self.file_error_map.is_empty() { + write!( + fmt, + "warning: rustfmt may have failed to format. See previous {} errors.\n", + self.warning_count(), + )?; + } + Ok(()) + } +} + +// Formatting which depends on the AST. +fn format_ast( + krate: &ast::Crate, + parse_session: &mut ParseSess, + main_file: &FileName, + config: &Config, + mut after_file: F, +) -> Result<(FileMap, bool), io::Error> +where + F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result, +{ + let mut result = FileMap::new(); + // diff mode: check if any files are differing + let mut has_diff = false; + + // We always skip children for the "Plain" write mode, since there is + // nothing to distinguish the nested module contents. + let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; + for (path, module) in modules::list_files(krate, parse_session.codemap())? { + if skip_children && path != *main_file { + continue; + } + if config.verbose() { + println!("Formatting {}", path); + } + let filemap = parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == *main_file { + visitor.skip_empty_lines(filemap.end_pos); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); + } else { + visitor.format_separate_mod(module, &*filemap); + } + } else { + visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); + visitor.format_separate_mod(module, &*filemap); + }; + + assert_eq!( + visitor.line_number, + ::utils::count_newlines(&format!("{}", visitor.buffer)) + ); + + let filename = path.clone(); + has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) { + Ok(result) => result, + Err(e) => { + // Create a new error with path_str to help users see which files failed + let err_msg = format!("{}: {}", path, e); + return Err(io::Error::new(e.kind(), err_msg)); + } + }; + + result.push((filename, visitor.buffer)); + } + + Ok((result, has_diff)) +} + +/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`. +fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { + skipped_range + .iter() + .any(|&(lo, hi)| lo <= line_number && line_number <= hi) +} + +fn should_report_error( + config: &Config, + char_kind: FullCodeCharKind, + is_string: bool, + error_kind: ErrorKind, +) -> bool { + let allow_error_report = if char_kind.is_comment() || is_string { + config.error_on_unformatted() + } else { + true + }; + + match error_kind { + ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, + ErrorKind::TrailingWhitespace => allow_error_report, + _ => true, + } +} + +// Formatting done on a char by char or line by line basis. +// FIXME(#209) warn on bad license +// FIXME(#20) other stuff for parity with make tidy +fn format_lines( + text: &mut String, + name: &FileName, + skipped_range: &[(usize, usize)], + config: &Config, + report: &mut FormatReport, +) { + // Iterate over the chars in the file map. + let mut trims = vec![]; + let mut last_wspace: Option = None; + let mut line_len = 0; + let mut cur_line = 1; + let mut newline_count = 0; + let mut errors = vec![]; + let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); + let mut line_buffer = String::with_capacity(config.max_width() * 2); + let mut is_string = false; // true if the current line contains a string literal. + let mut format_line = config.file_lines().contains_line(name, cur_line); + + for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { + if c == '\r' { + continue; + } + + if format_line { + // Add warnings for bad todos/ fixmes + if let Some(issue) = issue_seeker.inspect(c) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::BadIssue(issue), + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); + } + } + + if c == '\n' { + if format_line { + // Check for (and record) trailing whitespace. + if let Some(..) = last_wspace { + if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) { + trims.push((cur_line, kind, line_buffer.clone())); + } + line_len -= 1; + } + + // Check for any line width errors we couldn't correct. + let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); + if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) + && should_report_error(config, kind, is_string, error_kind) + { + errors.push(FormattingError { + line: cur_line, + kind: error_kind, + is_comment: kind.is_comment(), + is_string, + line_buffer: line_buffer.clone(), + }); + } + } + + line_len = 0; + cur_line += 1; + format_line = config.file_lines().contains_line(name, cur_line); + newline_count += 1; + last_wspace = None; + line_buffer.clear(); + is_string = false; + } else { + newline_count = 0; + line_len += if c == '\t' { config.tab_spaces() } else { 1 }; + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(b); + } + } else { + last_wspace = None; + } + line_buffer.push(c); + if kind.is_string() { + is_string = true; + } + } + } + + if newline_count > 1 { + debug!("track truncate: {} {}", text.len(), newline_count); + let line = text.len() - newline_count + 1; + text.truncate(line); + } + + for &(l, kind, ref b) in &trims { + if !is_skipped_line(l, skipped_range) { + errors.push(FormattingError { + line: l, + kind: ErrorKind::TrailingWhitespace, + is_comment: kind.is_comment(), + is_string: kind.is_string(), + line_buffer: b.clone(), + }); + } + } + + report.file_error_map.insert(name.clone(), errors); +} + +fn parse_input( + input: Input, + parse_session: &ParseSess, +) -> Result> { + let result = match input { + Input::File(file) => { + let mut parser = parse::new_parser_from_file(parse_session, &file); + parser.cfg_mods = false; + parser.parse_crate_mod() + } + Input::Text(text) => { + let mut parser = parse::new_parser_from_source_str( + parse_session, + FileName::Custom("stdin".to_owned()), + text, + ); + parser.cfg_mods = false; + parser.parse_crate_mod() + } + }; + + match result { + Ok(c) => { + if parse_session.span_diagnostic.has_errors() { + // Bail out if the parser recovered from an error. + Err(None) + } else { + Ok(c) + } + } + Err(e) => Err(Some(e)), + } +} + +/// Format the given snippet. The snippet is expected to be *complete* code. +/// When we cannot parse the given snippet, this function returns `None`. +pub fn format_snippet(snippet: &str, config: &Config) -> Option { + let mut out: Vec = Vec::with_capacity(snippet.len() * 2); + let input = Input::Text(snippet.into()); + let mut config = config.clone(); + config.set().write_mode(config::WriteMode::Plain); + config.set().hide_parse_errors(true); + match format_input(input, &config, Some(&mut out)) { + // `format_input()` returns an empty string on parsing error. + Ok(..) if out.is_empty() && !snippet.is_empty() => None, + Ok(..) => String::from_utf8(out).ok(), + Err(..) => None, + } +} + +/// Format the given code block. Mainly targeted for code block in comment. +/// The code block may be incomplete (i.e. parser may be unable to parse it). +/// To avoid panic in parser, we wrap the code block with a dummy function. +/// The returned code block does *not* end with newline. +pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { + // Wrap the given code block with `fn main()` if it does not have one. + let fn_main_prefix = "fn main() {\n"; + let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}"; + + // Trim "fn main() {" on the first line and "}" on the last line, + // then unindent the whole code block. + format_snippet(&snippet, config).map(|s| { + // 2 = "}\n" + s[fn_main_prefix.len()..s.len().checked_sub(2).unwrap_or(0)] + .lines() + .map(|line| { + if line.len() > config.tab_spaces() { + // Make sure that the line has leading whitespaces. + let indent_str = + Indent::from_width(config, config.tab_spaces()).to_string(config); + if line.starts_with(indent_str.as_ref()) { + let offset = if config.hard_tabs() { + 1 + } else { + config.tab_spaces() + }; + &line[offset..] + } else { + line + } + } else { + line + } + }) + .collect::>() + .join("\n") + }) +} + +pub fn format_input( + input: Input, + config: &Config, + mut out: Option<&mut T>, +) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { + let mut summary = Summary::default(); + if config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err((e, summary)); + } + } + return Ok((summary, FileMap::new(), FormatReport::new())); + } + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + + let tty_handler = if config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; + let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + + let main_file = match input { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Custom("stdin".to_owned()), + }; + + let krate = match parse_input(input, &parse_session) { + Ok(krate) => krate, + Err(diagnostic) => { + if let Some(mut diagnostic) = diagnostic { + diagnostic.emit(); + } + summary.add_parsing_error(); + return Ok((summary, FileMap::new(), FormatReport::new())); + } + }; + + summary.mark_parse_time(); + + if parse_session.span_diagnostic.has_errors() { + summary.add_parsing_error(); + } + + // Suppress error output after parsing. + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + + let mut report = FormatReport::new(); + + let format_result = format_ast( + &krate, + &mut parse_session, + &main_file, + config, + |file_name, file, skipped_range| { + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(file); + + format_lines(file, file_name, skipped_range, config, &mut report); + + if let Some(ref mut out) = out { + return filemap::write_file(file, file_name, out, config); + } + Ok(false) + }, + ); + + summary.mark_format_time(); + + if config.verbose() { + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } + + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + duration_to_f32(summary.get_parse_time().unwrap()), + duration_to_f32(summary.get_format_time().unwrap()), + ); + } + + match format_result { + Ok((file_map, has_diff)) => { + if report.has_warnings() { + summary.add_formatting_error(); + } + + if has_diff { + summary.add_diff(); + } + + Ok((summary, file_map, report)) + } + Err(e) => Err((e, summary)), + } +} + +#[derive(Debug)] +pub enum Input { + File(PathBuf), + Text(String), +} + +pub fn run(input: Input, config: &Config) -> Summary { + let out = &mut stdout(); + output_header(out, config.write_mode()).ok(); + match format_input(input, config, Some(out)) { + Ok((summary, _, report)) => { + output_footer(out, config.write_mode()).ok(); + + if report.has_warnings() { + match term::stderr() { + Some(ref t) + if use_colored_tty(config.color()) && t.supports_color() + && t.supports_attr(term::Attr::Bold) => + { + match report.print_warnings_fancy(term::stderr().unwrap()) { + Ok(..) => (), + Err(..) => panic!("Unable to write to stderr: {}", report), + } + } + _ => msg!("{}", report), + } + } + + summary + } + Err((msg, mut summary)) => { + msg!("Error writing files: {}", msg); + summary.add_operational_error(); + summary + } + } +} + +#[cfg(test)] +mod test { + use super::{format_code_block, format_snippet, Config}; + + #[test] + fn test_no_panic_on_format_snippet_and_format_code_block() { + // `format_snippet()` and `format_code_block()` should not panic + // even when we cannot parse the given snippet. + let snippet = "let"; + assert!(format_snippet(snippet, &Config::default()).is_none()); + assert!(format_code_block(snippet, &Config::default()).is_none()); + } + + fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool + where + F: Fn(&str, &Config) -> Option, + { + let output = formatter(input, &Config::default()); + output.is_some() && output.unwrap() == expected + } + + #[test] + fn test_format_snippet() { + let snippet = "fn main() { println!(\"hello, world\"); }"; + let expected = "fn main() {\n \ + println!(\"hello, world\");\n\ + }\n"; + assert!(test_format_inner(format_snippet, snippet, expected)); + } + + #[test] + fn test_format_code_block() { + // simple code block + let code_block = "let x=3;"; + let expected = "let x = 3;"; + assert!(test_format_inner(format_code_block, code_block, expected)); + + // more complex code block, taken from chains.rs. + let code_block = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +context.config.indent_style() == IndentStyle::Visual || is_small_parent, +) +} else if is_block_expr(context, &parent, &parent_rewrite) { +match context.config.indent_style() { +// Try to put the first child on the same line with parent's last line +IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), +// The parent is a block, so align the rest of the chain with the closing +// brace. +IndentStyle::Visual => (parent_shape, false), +} +} else { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +false, +) +}; +"; + let expected = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + context.config.indent_style() == IndentStyle::Visual || is_small_parent, + ) +} else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } +} else { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + false, + ) +};"; + assert!(test_format_inner(format_code_block, code_block, expected)); + } +} diff --git a/rustfmt-core/src/lists.rs b/rustfmt-core/src/lists.rs new file mode 100644 index 00000000000..a67088042c8 --- /dev/null +++ b/rustfmt-core/src/lists.rs @@ -0,0 +1,769 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Format list-like expressions and items. + +use std::cmp; +use std::iter::Peekable; + +use config::lists::*; +use syntax::codemap::{BytePos, CodeMap}; + +use comment::{find_comment_end, rewrite_comment, FindUncommented}; +use config::{Config, IndentStyle}; +use rewrite::RewriteContext; +use shape::{Indent, Shape}; +use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; + +pub struct ListFormatting<'a> { + pub tactic: DefinitiveListTactic, + pub separator: &'a str, + pub trailing_separator: SeparatorTactic, + pub separator_place: SeparatorPlace, + pub shape: Shape, + // Non-expressions, e.g. items, will have a new line at the end of the list. + // Important for comment styles. + pub ends_with_newline: bool, + // Remove newlines between list elements for expressions. + pub preserve_newline: bool, + pub config: &'a Config, +} + +impl<'a> ListFormatting<'a> { + pub fn needs_trailing_separator(&self) -> bool { + match self.trailing_separator { + // We always put separator in front. + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => self.tactic == DefinitiveListTactic::Vertical, + SeparatorTactic::Never => { + self.tactic == DefinitiveListTactic::Vertical && self.separator_place.is_front() + } + } + } +} + +impl AsRef for ListItem { + fn as_ref(&self) -> &ListItem { + self + } +} + +#[derive(PartialEq, Eq)] +pub enum ListItemCommentStyle { + // Try to keep the comment on the same line with the item. + SameLine, + // Put the comment on the previous or the next line of the item. + DifferentLine, + // No comment available. + None, +} + +pub struct ListItem { + // None for comments mean that they are not present. + pub pre_comment: Option, + pub pre_comment_style: ListItemCommentStyle, + // Item should include attributes and doc comments. None indicates a failed + // rewrite. + pub item: Option, + pub post_comment: Option, + // Whether there is extra whitespace before this item. + pub new_lines: bool, +} + +impl ListItem { + pub fn inner_as_ref(&self) -> &str { + self.item.as_ref().map_or("", |s| s) + } + + pub fn is_different_group(&self) -> bool { + self.inner_as_ref().contains('\n') || self.pre_comment.is_some() + || self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + } + + pub fn is_multiline(&self) -> bool { + self.inner_as_ref().contains('\n') + || self.pre_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + || self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + } + + pub fn has_comment(&self) -> bool { + self.pre_comment + .as_ref() + .map_or(false, |comment| comment.trim_left().starts_with("//")) + || self.post_comment + .as_ref() + .map_or(false, |comment| comment.trim_left().starts_with("//")) + } + + pub fn from_str>(s: S) -> ListItem { + ListItem { + pre_comment: None, + pre_comment_style: ListItemCommentStyle::None, + item: Some(s.into()), + post_comment: None, + new_lines: false, + } + } +} + +/// The type of separator for lists. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum Separator { + Comma, + VerticalBar, +} + +impl Separator { + pub fn len(&self) -> usize { + match *self { + // 2 = `, ` + Separator::Comma => 2, + // 3 = ` | ` + Separator::VerticalBar => 3, + } + } +} + +pub fn definitive_tactic( + items: I, + tactic: ListTactic, + sep: Separator, + width: usize, +) -> DefinitiveListTactic +where + I: IntoIterator + Clone, + T: AsRef, +{ + let pre_line_comments = items + .clone() + .into_iter() + .any(|item| item.as_ref().has_comment()); + + let limit = match tactic { + _ if pre_line_comments => return DefinitiveListTactic::Vertical, + ListTactic::Mixed => return DefinitiveListTactic::Mixed, + ListTactic::Horizontal => return DefinitiveListTactic::Horizontal, + ListTactic::Vertical => return DefinitiveListTactic::Vertical, + ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit), + ListTactic::HorizontalVertical => width, + }; + + let (sep_count, total_width) = calculate_width(items.clone()); + let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); + let real_total = total_width + total_sep_len; + + if real_total <= limit && !pre_line_comments + && !items.into_iter().any(|item| item.as_ref().is_multiline()) + { + DefinitiveListTactic::Horizontal + } else { + DefinitiveListTactic::Vertical + } +} + +// Format a list of commented items into a string. +// TODO: add unit tests +pub fn write_list(items: I, formatting: &ListFormatting) -> Option +where + I: IntoIterator + Clone, + T: AsRef, +{ + let tactic = formatting.tactic; + let sep_len = formatting.separator.len(); + + // Now that we know how we will layout, we can decide for sure if there + // will be a trailing separator. + let mut trailing_separator = formatting.needs_trailing_separator(); + let mut result = String::with_capacity(128); + let cloned_items = items.clone(); + let mut iter = items.into_iter().enumerate().peekable(); + let mut item_max_width: Option = None; + let sep_place = + SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); + + let mut line_len = 0; + let indent_str = &formatting.shape.indent.to_string(formatting.config); + while let Some((i, item)) = iter.next() { + let item = item.as_ref(); + let inner_item = item.item.as_ref()?; + let first = i == 0; + let last = iter.peek().is_none(); + let mut separate = match sep_place { + SeparatorPlace::Front => !first, + SeparatorPlace::Back => !last || trailing_separator, + }; + let item_sep_len = if separate { sep_len } else { 0 }; + + // Item string may be multi-line. Its length (used for block comment alignment) + // should be only the length of the last line. + let item_last_line = if item.is_multiline() { + inner_item.lines().last().unwrap_or("") + } else { + inner_item.as_ref() + }; + let mut item_last_line_width = item_last_line.len() + item_sep_len; + if item_last_line.starts_with(&**indent_str) { + item_last_line_width -= indent_str.len(); + } + + match tactic { + DefinitiveListTactic::Horizontal if !first => { + result.push(' '); + } + DefinitiveListTactic::SpecialMacro(num_args_before) => { + if i == 0 { + // Nothing + } else if i < num_args_before { + result.push(' '); + } else if i <= num_args_before + 1 { + result.push('\n'); + result.push_str(indent_str); + } else { + result.push(' '); + } + } + DefinitiveListTactic::Vertical if !first => { + result.push('\n'); + result.push_str(indent_str); + } + DefinitiveListTactic::Mixed => { + let total_width = total_item_width(item) + item_sep_len; + + // 1 is space between separator and item. + if line_len > 0 && line_len + 1 + total_width > formatting.shape.width { + result.push('\n'); + result.push_str(indent_str); + line_len = 0; + if formatting.ends_with_newline { + if last { + separate = true; + } else { + trailing_separator = true; + } + } + } + + if line_len > 0 { + result.push(' '); + line_len += 1; + } + + line_len += total_width; + } + _ => {} + } + + // Pre-comments + if let Some(ref comment) = item.pre_comment { + // Block style in non-vertical mode. + let block_mode = tactic != DefinitiveListTactic::Vertical; + // Width restriction is only relevant in vertical mode. + let comment = + rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; + result.push_str(&comment); + + if tactic == DefinitiveListTactic::Vertical { + // We cannot keep pre-comments on the same line if the comment if normalized. + let keep_comment = if formatting.config.normalize_comments() + || item.pre_comment_style == ListItemCommentStyle::DifferentLine + { + false + } else { + // We will try to keep the comment on the same line with the item here. + // 1 = ` ` + let total_width = total_item_width(item) + item_sep_len + 1; + total_width <= formatting.shape.width + }; + if keep_comment { + result.push(' '); + } else { + result.push('\n'); + result.push_str(indent_str); + } + } else { + result.push(' '); + } + item_max_width = None; + } + + if separate && sep_place.is_front() && !first { + result.push_str(formatting.separator.trim()); + result.push(' '); + } + result.push_str(&inner_item[..]); + + // Post-comments + if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { + let comment = item.post_comment.as_ref().unwrap(); + let formatted_comment = rewrite_comment( + comment, + true, + Shape::legacy(formatting.shape.width, Indent::empty()), + formatting.config, + )?; + + result.push(' '); + result.push_str(&formatted_comment); + } + + if separate && sep_place.is_back() { + result.push_str(formatting.separator); + } + + if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { + let comment = item.post_comment.as_ref().unwrap(); + let overhead = last_line_width(&result) + first_line_width(comment.trim()); + + let rewrite_post_comment = |item_max_width: &mut Option| { + if item_max_width.is_none() && !last && !inner_item.contains('\n') { + *item_max_width = Some(max_width_of_item_with_post_comment( + &cloned_items, + i, + overhead, + formatting.config.max_width(), + )); + } + let overhead = if starts_with_newline(comment) { + 0 + } else if let Some(max_width) = *item_max_width { + max_width + 2 + } else { + // 1 = space between item and comment. + item_last_line_width + 1 + }; + let width = formatting.shape.width.checked_sub(overhead).unwrap_or(1); + let offset = formatting.shape.indent + overhead; + let comment_shape = Shape::legacy(width, offset); + + // Use block-style only for the last item or multiline comments. + let block_style = !formatting.ends_with_newline && last + || comment.trim().contains('\n') + || comment.trim().len() > width; + + rewrite_comment( + comment.trim_left(), + block_style, + comment_shape, + formatting.config, + ) + }; + + let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; + + if !starts_with_newline(comment) { + let mut comment_alignment = + post_comment_alignment(item_max_width, inner_item.len()); + if first_line_width(&formatted_comment) + last_line_width(&result) + + comment_alignment + 1 > formatting.config.max_width() + { + item_max_width = None; + formatted_comment = rewrite_post_comment(&mut item_max_width)?; + comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); + } + for _ in 0..(comment_alignment + 1) { + result.push(' '); + } + // An additional space for the missing trailing separator. + if last && item_max_width.is_some() && !separate && !formatting.separator.is_empty() + { + result.push(' '); + } + } else { + result.push('\n'); + result.push_str(indent_str); + } + if formatted_comment.contains('\n') { + item_max_width = None; + } + result.push_str(&formatted_comment); + } else { + item_max_width = None; + } + + if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical + && item.new_lines + { + item_max_width = None; + result.push('\n'); + } + } + + Some(result) +} + +fn max_width_of_item_with_post_comment( + items: &I, + i: usize, + overhead: usize, + max_budget: usize, +) -> usize +where + I: IntoIterator + Clone, + T: AsRef, +{ + let mut max_width = 0; + let mut first = true; + for item in items.clone().into_iter().skip(i) { + let item = item.as_ref(); + let inner_item_width = item.inner_as_ref().len(); + if !first + && (item.is_different_group() || !item.post_comment.is_some() + || inner_item_width + overhead > max_budget) + { + return max_width; + } + if max_width < inner_item_width { + max_width = inner_item_width; + } + if item.new_lines { + return max_width; + } + first = false; + } + max_width +} + +fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { + item_max_width + .and_then(|max_line_width| max_line_width.checked_sub(inner_item_len)) + .unwrap_or(0) +} + +pub struct ListItems<'a, I, F1, F2, F3> +where + I: Iterator, +{ + codemap: &'a CodeMap, + inner: Peekable, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos, + terminator: &'a str, + separator: &'a str, + leave_last: bool, +} + +impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, +{ + type Item = ListItem; + + fn next(&mut self) -> Option { + let white_space: &[_] = &[' ', '\t']; + + self.inner.next().map(|item| { + let mut new_lines = false; + // Pre-comment + let pre_snippet = self.codemap + .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) + .unwrap(); + let trimmed_pre_snippet = pre_snippet.trim(); + let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); + let has_block_comment = trimmed_pre_snippet.starts_with("/*"); + let (pre_comment, pre_comment_style) = if has_single_line_comment { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else if has_block_comment { + let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); + if pre_snippet + .chars() + .rev() + .take(comment_end + 1) + .any(|c| c == '\n') + { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::SameLine, + ) + } + } else { + (None, ListItemCommentStyle::None) + }; + + // Post-comment + let next_start = match self.inner.peek() { + Some(next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.codemap + .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let mut block_open_index = post_snippet.find("/*"); + // check if it really is a block comment (and not `//*` or a nested comment) + if let Some(i) = block_open_index { + match post_snippet.find('/') { + Some(j) if j < i => block_open_index = None, + _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, + _ => (), + } + } + let newline_index = post_snippet.find('\n'); + if let Some(separator_index) = post_snippet.find_uncommented(self.separator) { + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => separator_index + 1, + // Block-style post-comment before the separator. + (Some(i), None) => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Potential *single* line comment. + (_, Some(j)) if j > separator_index => j + 1, + _ => post_snippet.len(), + } + } else if let Some(newline_index) = newline_index { + // Match arms may not have trailing comma. In any case, for match arms, + // we will assume that the post comment belongs to the next arm if they + // do not end with trailing comma. + newline_index + 1 + } else { + 0 + } + } + None => post_snippet + .find_uncommented(self.terminator) + .unwrap_or_else(|| post_snippet.len()), + }; + + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end - 1..]; + let first_newline = test_snippet + .find('\n') + .unwrap_or_else(|| test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet + .find(|c: char| !c.is_whitespace()) + .unwrap_or_else(|| test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if count_newlines(test_snippet) > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; + } + } + + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let post_snippet = post_snippet[..comment_end].trim(); + + let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.ends_with(',') { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; + + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + }; + + ListItem { + pre_comment, + pre_comment_style, + item: if self.inner.peek().is_none() && self.leave_last { + None + } else { + (self.get_item_string)(&item) + }, + post_comment, + new_lines, + } + }) + } +} + +// Creates an iterator over a list's items with associated comments. +pub fn itemize_list<'a, T, I, F1, F2, F3>( + codemap: &'a CodeMap, + inner: I, + terminator: &'a str, + separator: &'a str, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos, + leave_last: bool, +) -> ListItems<'a, I, F1, F2, F3> +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, +{ + ListItems { + codemap, + inner: inner.peekable(), + get_lo, + get_hi, + get_item_string, + prev_span_end, + next_span_start, + terminator, + separator, + leave_last, + } +} + +/// Returns the count and total width of the list items. +fn calculate_width(items: I) -> (usize, usize) +where + I: IntoIterator, + T: AsRef, +{ + items + .into_iter() + .map(|item| total_item_width(item.as_ref())) + .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) +} + +pub fn total_item_width(item: &ListItem) -> usize { + comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + + item.item.as_ref().map_or(0, |str| str.len()) +} + +fn comment_len(comment: Option<&str>) -> usize { + match comment { + Some(s) => { + let text_len = s.trim().len(); + if text_len > 0 { + // We'll put " /*" before and " */" after inline comments. + text_len + 6 + } else { + text_len + } + } + None => 0, + } +} + +// Compute horizontal and vertical shapes for a struct-lit-like thing. +pub fn struct_lit_shape( + shape: Shape, + context: &RewriteContext, + prefix_width: usize, + suffix_width: usize, +) -> Option<(Option, Shape)> { + let v_shape = match context.config.indent_style() { + IndentStyle::Visual => shape + .visual_indent(0) + .shrink_left(prefix_width)? + .sub_width(suffix_width)?, + IndentStyle::Block => { + let shape = shape.block_indent(context.config.tab_spaces()); + Shape { + width: context.budget(shape.indent.width()), + ..shape + } + } + }; + let shape_width = shape.width.checked_sub(prefix_width + suffix_width); + if let Some(w) = shape_width { + let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); + Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) + } else { + Some((None, v_shape)) + } +} + +// Compute the tactic for the internals of a struct-lit-like thing. +pub fn struct_lit_tactic( + h_shape: Option, + context: &RewriteContext, + items: &[ListItem], +) -> DefinitiveListTactic { + if let Some(h_shape) = h_shape { + let prelim_tactic = match (context.config.indent_style(), items.len()) { + (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, + _ if context.config.struct_lit_single_line() => ListTactic::HorizontalVertical, + _ => ListTactic::Vertical, + }; + definitive_tactic(items, prelim_tactic, Separator::Comma, h_shape.width) + } else { + DefinitiveListTactic::Vertical + } +} + +// Given a tactic and possible shapes for horizontal and vertical layout, +// come up with the actual shape to use. +pub fn shape_for_tactic( + tactic: DefinitiveListTactic, + h_shape: Option, + v_shape: Shape, +) -> Shape { + match tactic { + DefinitiveListTactic::Horizontal => h_shape.unwrap(), + _ => v_shape, + } +} + +// Create a ListFormatting object for formatting the internals of a +// struct-lit-like thing, that is a series of fields. +pub fn struct_lit_formatting<'a>( + shape: Shape, + tactic: DefinitiveListTactic, + context: &'a RewriteContext, + force_no_trailing_comma: bool, +) -> ListFormatting<'a> { + let ends_with_newline = context.config.indent_style() != IndentStyle::Visual + && tactic == DefinitiveListTactic::Vertical; + ListFormatting { + tactic, + separator: ",", + trailing_separator: if force_no_trailing_comma { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline, + preserve_newline: true, + config: context.config, + } +} diff --git a/rustfmt-core/src/macros.rs b/rustfmt-core/src/macros.rs new file mode 100644 index 00000000000..535a82c81de --- /dev/null +++ b/rustfmt-core/src/macros.rs @@ -0,0 +1,872 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format list-like macro invocations. These are invocations whose token trees +// can be interpreted as expressions and separated by commas. +// Note that these token trees do not actually have to be interpreted as +// expressions by the compiler. An example of an invocation we would reformat is +// foo!( x, y, z ). The token x may represent an identifier in the code, but we +// interpreted as an expression. +// Macro uses which are not-list like, such as bar!(key => val), will not be +// reformatted. +// List-like invocations with parentheses will be formatted as function calls, +// and those with brackets will be formatted as array literals. + +use std::collections::HashMap; + +use config::lists::*; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; +use syntax::parse::new_parser_from_tts; +use syntax::parse::parser::Parser; +use syntax::parse::token::{BinOpToken, DelimToken, Token}; +use syntax::print::pprust; +use syntax::symbol; +use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; +use syntax::util::ThinVec; + +use codemap::SpanUtils; +use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; +use expr::{rewrite_array, rewrite_call_inner}; +use lists::{itemize_list, write_list, ListFormatting}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use utils::{format_visibility, mk_sp}; + +const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; + +// FIXME: use the enum from libsyntax? +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum MacroStyle { + Parens, + Brackets, + Braces, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MacroPosition { + Item, + Statement, + Expression, + Pat, +} + +impl MacroStyle { + fn opener(&self) -> &'static str { + match *self { + MacroStyle::Parens => "(", + MacroStyle::Brackets => "[", + MacroStyle::Braces => "{", + } + } +} + +#[derive(Debug)] +pub enum MacroArg { + Expr(ast::Expr), + Ty(ast::Ty), + Pat(ast::Pat), +} + +impl Rewrite for MacroArg { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + MacroArg::Expr(ref expr) => expr.rewrite(context, shape), + MacroArg::Ty(ref ty) => ty.rewrite(context, shape), + MacroArg::Pat(ref pat) => pat.rewrite(context, shape), + } + } +} + +fn parse_macro_arg(parser: &mut Parser) -> Option { + macro_rules! parse_macro_arg { + ($macro_arg: ident, $parser: ident) => { + let mut cloned_parser = (*parser).clone(); + match cloned_parser.$parser() { + Ok(x) => { + if parser.sess.span_diagnostic.has_errors() { + parser.sess.span_diagnostic.reset_err_count(); + } else { + // Parsing succeeded. + *parser = cloned_parser; + return Some(MacroArg::$macro_arg((*x).clone())); + } + } + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + } + } + }; + } + + parse_macro_arg!(Expr, parse_expr); + parse_macro_arg!(Ty, parse_ty); + parse_macro_arg!(Pat, parse_pat); + + None +} + +pub fn rewrite_macro( + mac: &ast::Mac, + extra_ident: Option, + context: &RewriteContext, + shape: Shape, + position: MacroPosition, +) -> Option { + let context = &mut context.clone(); + context.inside_macro = true; + if context.config.use_try_shorthand() { + if let Some(expr) = convert_try_mac(mac, context) { + context.inside_macro = false; + return expr.rewrite(context, shape); + } + } + + let original_style = macro_style(mac, context); + + let macro_name = match extra_ident { + None => format!("{}!", mac.node.path), + Some(ident) => { + if ident == symbol::keywords::Invalid.ident() { + format!("{}!", mac.node.path) + } else { + format!("{}! {}", mac.node.path, ident) + } + } + }; + + let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + MacroStyle::Brackets + } else { + original_style + }; + + let ts: TokenStream = mac.node.stream(); + if ts.is_empty() && !contains_comment(context.snippet(mac.span)) { + return match style { + MacroStyle::Parens if position == MacroPosition::Item => { + Some(format!("{}();", macro_name)) + } + MacroStyle::Parens => Some(format!("{}()", macro_name)), + MacroStyle::Brackets => Some(format!("{}[]", macro_name)), + MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), + }; + } + + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut arg_vec = Vec::new(); + let mut vec_with_semi = false; + let mut trailing_comma = false; + + if MacroStyle::Braces != style { + loop { + match parse_macro_arg(&mut parser) { + Some(arg) => arg_vec.push(arg), + None => return Some(context.snippet(mac.span).to_owned()), + } + + match parser.token { + Token::Eof => break, + Token::Comma => (), + Token::Semi => { + // Try to parse `vec![expr; expr]` + if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + parser.bump(); + if parser.token != Token::Eof { + match parse_macro_arg(&mut parser) { + Some(arg) => { + arg_vec.push(arg); + parser.bump(); + if parser.token == Token::Eof && arg_vec.len() == 2 { + vec_with_semi = true; + break; + } + } + None => return Some(context.snippet(mac.span).to_owned()), + } + } + } + return Some(context.snippet(mac.span).to_owned()); + } + _ => return Some(context.snippet(mac.span).to_owned()), + } + + parser.bump(); + + if parser.token == Token::Eof { + trailing_comma = true; + break; + } + } + } + + match style { + MacroStyle::Parens => { + // Format macro invocation as function call, forcing no trailing + // comma because not all macros support them. + rewrite_call_inner( + context, + ¯o_name, + &arg_vec.iter().map(|e| &*e).collect::>()[..], + mac.span, + shape, + context.config.width_heuristics().fn_call_width, + trailing_comma, + ).map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) + } + MacroStyle::Brackets => { + let mac_shape = shape.offset_left(macro_name.len())?; + // Handle special case: `vec![expr; expr]` + if vec_with_semi { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + // 6 = `vec!` + `; ` + let total_overhead = lbr.len() + rbr.len() + 6; + let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); + let lhs = arg_vec[0].rewrite(context, nested_shape)?; + let rhs = arg_vec[1].rewrite(context, nested_shape)?; + if !lhs.contains('\n') && !rhs.contains('\n') + && lhs.len() + rhs.len() + total_overhead <= shape.width + { + Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) + } else { + Some(format!( + "{}{}\n{}{};\n{}{}\n{}{}", + macro_name, + lbr, + nested_shape.indent.to_string(context.config), + lhs, + nested_shape.indent.to_string(context.config), + rhs, + shape.indent.to_string(context.config), + rbr + )) + } + } else { + // If we are rewriting `vec!` macro or other special macros, + // then we can rewrite this as an usual array literal. + // Otherwise, we must preserve the original existence of trailing comma. + if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { + context.inside_macro = false; + trailing_comma = false; + } + // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. + let sp = mk_sp( + context + .codemap + .span_after(mac.span, original_style.opener()), + mac.span.hi() - BytePos(1), + ); + let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; + let rewrite = rewrite_array(arg_vec, sp, context, mac_shape, trailing_comma)?; + + Some(format!("{}{}", macro_name, rewrite)) + } + } + MacroStyle::Braces => { + // Skip macro invocations with braces, for now. + indent_macro_snippet(context, context.snippet(mac.span), shape.indent) + } + } +} + +pub fn rewrite_macro_def( + context: &RewriteContext, + shape: Shape, + indent: Indent, + def: &ast::MacroDef, + ident: ast::Ident, + vis: &ast::Visibility, + span: Span, +) -> Option { + let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); + + let mut parser = MacroParser::new(def.stream().into_trees()); + let parsed_def = match parser.parse() { + Some(def) => def, + None => return snippet, + }; + + let mut result = if def.legacy { + String::from("macro_rules!") + } else { + format!("{}macro", format_visibility(vis)) + }; + + result += " "; + result += &ident.name.as_str(); + + let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; + + let arm_shape = if multi_branch_style { + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + } else { + shape + }; + + let branch_items = itemize_list( + context.codemap, + parsed_def.branches.iter(), + "}", + ";", + |branch| branch.span.lo(), + |branch| branch.span.hi(), + |branch| branch.rewrite(context, arm_shape, multi_branch_style), + context.codemap.span_after(span, "{"), + span.hi(), + false, + ).collect::>(); + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: if def.legacy { ";" } else { "" }, + trailing_separator: SeparatorTactic::Always, + separator_place: SeparatorPlace::Back, + shape: arm_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + + if multi_branch_style { + result += " {\n"; + result += &arm_shape.indent.to_string(context.config); + } + + result += write_list(&branch_items, &fmt)?.as_str(); + + if multi_branch_style { + result += "\n"; + result += &indent.to_string(context.config); + result += "}"; + } + + Some(result) +} + +// Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we +// aren't causing problems. +// This should also work for escaped `$` variables, where we leave earlier `$`s. +fn replace_names(input: &str) -> Option<(String, HashMap)> { + // Each substitution will require five or six extra bytes. + let mut result = String::with_capacity(input.len() + 64); + let mut substs = HashMap::new(); + let mut dollar_count = 0; + let mut cur_name = String::new(); + + for c in input.chars() { + if c == '$' { + dollar_count += 1; + } else if dollar_count == 0 { + result.push(c); + } else if !c.is_alphanumeric() && !cur_name.is_empty() { + // Terminates a name following one or more dollars. + let mut new_name = String::new(); + let mut old_name = String::new(); + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&cur_name); + old_name.push_str(&cur_name); + + result.push_str(&new_name); + substs.insert(old_name, new_name); + + result.push(c); + + dollar_count = 0; + cur_name = String::new(); + } else if c == '(' && cur_name.is_empty() { + // FIXME: Support macro def with repeat. + return None; + } else if c.is_alphanumeric() { + cur_name.push(c); + } + } + + // FIXME: duplicate code + if !cur_name.is_empty() { + let mut new_name = String::new(); + let mut old_name = String::new(); + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&cur_name); + old_name.push_str(&cur_name); + + result.push_str(&new_name); + substs.insert(old_name, new_name); + } + + debug!("replace_names `{}` {:?}", result, substs); + + Some((result, substs)) +} + +// This is a bit sketchy. The token rules probably need tweaking, but it works +// for some common cases. I hope the basic logic is sufficient. Note that the +// meaning of some tokens is a bit different here from usual Rust, e.g., `*` +// and `(`/`)` have special meaning. +// +// We always try and format on one line. +fn format_macro_args(toks: ThinTokenStream) -> Option { + let mut result = String::with_capacity(128); + let mut insert_space = SpaceState::Never; + + for tok in (toks.into(): TokenStream).trees() { + match tok { + TokenTree::Token(_, t) => { + if !result.is_empty() && force_space_before(&t) { + insert_space = SpaceState::Always; + } + if force_no_space_before(&t) { + insert_space = SpaceState::Never; + } + match (insert_space, ident_like(&t)) { + (SpaceState::Always, _) + | (SpaceState::Punctuation, false) + | (SpaceState::Ident, true) => { + result.push(' '); + } + _ => {} + } + result.push_str(&pprust::token_to_string(&t)); + insert_space = next_space(&t); + } + TokenTree::Delimited(_, d) => { + if let SpaceState::Always = insert_space { + result.push(' '); + } + let formatted = format_macro_args(d.tts)?; + match d.delim { + DelimToken::Paren => { + result.push_str(&format!("({})", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::Bracket => { + result.push_str(&format!("[{}]", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::Brace => { + result.push_str(&format!(" {{ {} }}", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::NoDelim => { + result.push_str(&format!("{}", formatted)); + insert_space = SpaceState::Always; + } + } + } + } + } + + Some(result) +} + +// We should insert a space if the next token is a: +#[derive(Copy, Clone)] +enum SpaceState { + Never, + Punctuation, + Ident, // Or ident/literal-like thing. + Always, +} + +fn force_space_before(tok: &Token) -> bool { + match *tok { + Token::Eq + | Token::Lt + | Token::Le + | Token::EqEq + | Token::Ne + | Token::Ge + | Token::Gt + | Token::AndAnd + | Token::OrOr + | Token::Not + | Token::Tilde + | Token::BinOpEq(_) + | Token::At + | Token::RArrow + | Token::LArrow + | Token::FatArrow + | Token::Pound + | Token::Dollar => true, + Token::BinOp(bot) => bot != BinOpToken::Star, + _ => false, + } +} + +fn force_no_space_before(tok: &Token) -> bool { + match *tok { + Token::Semi | Token::Comma | Token::Dot => true, + Token::BinOp(bot) => bot == BinOpToken::Star, + _ => false, + } +} +fn ident_like(tok: &Token) -> bool { + match *tok { + Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, + _ => false, + } +} + +fn next_space(tok: &Token) -> SpaceState { + match *tok { + Token::Not + | Token::Tilde + | Token::At + | Token::Comma + | Token::Dot + | Token::DotDot + | Token::DotDotDot + | Token::DotDotEq + | Token::DotEq + | Token::Question + | Token::Underscore + | Token::BinOp(_) => SpaceState::Punctuation, + + Token::ModSep + | Token::Pound + | Token::Dollar + | Token::OpenDelim(_) + | Token::CloseDelim(_) + | Token::Whitespace => SpaceState::Never, + + Token::Literal(..) | Token::Ident(_) | Token::Lifetime(_) => SpaceState::Ident, + + _ => SpaceState::Always, + } +} + +/// Tries to convert a macro use into a short hand try expression. Returns None +/// when the macro is not an instance of try! (or parsing the inner expression +/// failed). +pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { + if &format!("{}", mac.node.path)[..] == "try" { + let ts: TokenStream = mac.node.tts.clone().into(); + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + + Some(ast::Expr { + id: ast::NodeId::new(0), // dummy value + node: ast::ExprKind::Try(parser.parse_expr().ok()?), + span: mac.span, // incorrect span, but shouldn't matter too much + attrs: ThinVec::new(), + }) + } else { + None + } +} + +fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { + let snippet = context.snippet(mac.span); + let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); + let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); + let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); + + if paren_pos < bracket_pos && paren_pos < brace_pos { + MacroStyle::Parens + } else if bracket_pos < brace_pos { + MacroStyle::Brackets + } else { + MacroStyle::Braces + } +} + +/// Indent each line according to the specified `indent`. +/// e.g. +/// ```rust +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +/// ), +/// } +/// ``` +/// will become +/// ```rust +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +// ), +/// } +/// ``` +fn indent_macro_snippet( + context: &RewriteContext, + macro_str: &str, + indent: Indent, +) -> Option { + let mut lines = macro_str.lines(); + let first_line = lines.next().map(|s| s.trim_right())?; + let mut trimmed_lines = Vec::with_capacity(16); + + let min_prefix_space_width = lines + .filter_map(|line| { + let prefix_space_width = if is_empty_line(line) { + None + } else { + Some(get_prefix_space_width(context, line)) + }; + trimmed_lines.push((line.trim(), prefix_space_width)); + prefix_space_width + }) + .min()?; + + Some( + String::from(first_line) + "\n" + + &trimmed_lines + .iter() + .map(|&(line, prefix_space_width)| match prefix_space_width { + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width + .checked_sub(min_prefix_space_width) + .unwrap_or(0); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line.trim()) + } + None => String::new(), + }) + .collect::>() + .join("\n"), + ) +} + +fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { + let mut width = 0; + for c in s.chars() { + match c { + ' ' => width += 1, + '\t' => width += context.config.tab_spaces(), + _ => return width, + } + } + width +} + +fn is_empty_line(s: &str) -> bool { + s.is_empty() || s.chars().all(char::is_whitespace) +} + +// A very simple parser that just parses a macros 2.0 definition into its branches. +// Currently we do not attempt to parse any further than that. +#[derive(new)] +struct MacroParser { + toks: Cursor, +} + +impl MacroParser { + // (`(` ... `)` `=>` `{` ... `}`)* + fn parse(&mut self) -> Option { + let mut branches = vec![]; + while self.toks.look_ahead(1).is_some() { + branches.push(self.parse_branch()?); + } + + Some(Macro { branches }) + } + + // `(` ... `)` `=>` `{` ... `}` + fn parse_branch(&mut self) -> Option { + let tok = self.toks.next()?; + let (lo, args_paren_kind) = match tok { + TokenTree::Token(..) => return None, + TokenTree::Delimited(sp, ref d) => (sp.lo(), d.delim), + }; + let args = tok.joint().into(); + match self.toks.next()? { + TokenTree::Token(_, Token::FatArrow) => {} + _ => return None, + } + let (mut hi, body) = match self.toks.next()? { + TokenTree::Token(..) => return None, + TokenTree::Delimited(sp, _) => { + let data = sp.data(); + ( + data.hi, + Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), + ) + } + }; + if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { + self.toks.next(); + hi = sp.hi(); + } + Some(MacroBranch { + span: mk_sp(lo, hi), + args_paren_kind, + args, + body, + }) + } +} + +// A parsed macros 2.0 macro definition. +struct Macro { + branches: Vec, +} + +// FIXME: it would be more efficient to use references to the token streams +// rather than clone them, if we can make the borrowing work out. +struct MacroBranch { + span: Span, + args_paren_kind: DelimToken, + args: ThinTokenStream, + body: Span, +} + +impl MacroBranch { + fn rewrite( + &self, + context: &RewriteContext, + shape: Shape, + multi_branch_style: bool, + ) -> Option { + // Only attempt to format function-like macros. + if self.args_paren_kind != DelimToken::Paren { + // FIXME(#1539): implement for non-sugared macros. + return None; + } + + let mut result = format_macro_args(self.args.clone())?; + + if multi_branch_style { + result += " =>"; + } + + // The macro body is the most interesting part. It might end up as various + // AST nodes, but also has special variables (e.g, `$foo`) which can't be + // parsed as regular Rust code (and note that these can be escaped using + // `$$`). We'll try and format like an AST node, but we'll substitute + // variables for new names with the same length first. + + let old_body = context.snippet(self.body).trim(); + let (body_str, substs) = replace_names(old_body)?; + + let mut config = context.config.clone(); + config.set().hide_parse_errors(true); + + result += " {"; + + let has_block_body = old_body.starts_with('{'); + + let body_indent = if has_block_body { + shape.indent + } else { + // We'll hack the indent below, take this into account when formatting, + let body_indent = shape.indent.block_indent(&config); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); + body_indent + }; + + // First try to format as items, then as statements. + let new_body = match ::format_snippet(&body_str, &config) { + Some(new_body) => new_body, + None => match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return None, + }, + }; + + // Indent the body since it is in a block. + let indent_str = body_indent.to_string(&config); + let mut new_body = new_body + .trim_right() + .lines() + .fold(String::new(), |mut s, l| { + if !l.is_empty() { + s += &indent_str; + } + s + l + "\n" + }); + + // Undo our replacement of macro variables. + // FIXME: this could be *much* more efficient. + for (old, new) in &substs { + if old_body.find(new).is_some() { + debug!("rewrite_macro_def: bailing matching variable: `{}`", new); + return None; + } + new_body = new_body.replace(new, old); + } + + if has_block_body { + result += new_body.trim(); + } else if !new_body.is_empty() { + result += "\n"; + result += &new_body; + result += &shape.indent.to_string(&config); + } + + result += "}"; + + Some(result) + } +} + +#[cfg(test)] +mod test { + use super::*; + use syntax::parse::{parse_stream_from_source_str, ParseSess}; + use syntax::codemap::{FileName, FilePathMapping}; + + fn format_macro_args_str(s: &str) -> String { + let input = parse_stream_from_source_str( + FileName::Custom("stdin".to_owned()), + s.to_owned(), + &ParseSess::new(FilePathMapping::empty()), + None, + ); + format_macro_args(input.into()).unwrap() + } + + #[test] + fn test_format_macro_args() { + assert_eq!(format_macro_args_str(""), "".to_owned()); + assert_eq!(format_macro_args_str("$ x : ident"), "$x: ident".to_owned()); + assert_eq!( + format_macro_args_str("$ m1 : ident , $ m2 : ident , $ x : ident"), + "$m1: ident, $m2: ident, $x: ident".to_owned() + ); + assert_eq!( + format_macro_args_str("$($beginning:ident),*;$middle:ident;$($end:ident),*"), + "$($beginning: ident),*; $middle: ident; $($end: ident),*".to_owned() + ); + assert_eq!( + format_macro_args_str( + "$ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) *" + ), + "$name: ident($($dol: tt $var: ident)*) $($body: tt)*".to_owned() + ); + } +} diff --git a/rustfmt-core/src/missed_spans.rs b/rustfmt-core/src/missed_spans.rs new file mode 100644 index 00000000000..dff6b94bd75 --- /dev/null +++ b/rustfmt-core/src/missed_spans.rs @@ -0,0 +1,312 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::iter::repeat; + +use syntax::codemap::{BytePos, FileName, Pos, Span}; + +use codemap::LineRangeUtils; +use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use config::WriteMode; +use shape::{Indent, Shape}; +use utils::{count_newlines, last_line_width, mk_sp}; +use visitor::FmtVisitor; + +struct SnippetStatus { + /// An offset to the current line from the beginnig of the original snippet. + line_start: usize, + /// A length of trailing whitespaces on the current line. + last_wspace: Option, + /// The current line number. + cur_line: usize, +} + +impl SnippetStatus { + fn new(cur_line: usize) -> Self { + SnippetStatus { + line_start: 0, + last_wspace: None, + cur_line, + } + } +} + +impl<'a> FmtVisitor<'a> { + fn output_at_start(&self) -> bool { + self.buffer.is_empty() + } + + // TODO these format_missing methods are ugly. Refactor and add unit tests + // for the central whitespace stripping loop. + pub fn format_missing(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) + } + + pub fn format_missing_with_indent(&mut self, end: BytePos) { + let config = self.config; + self.format_missing_inner(end, |this, last_snippet, snippet| { + this.push_str(last_snippet.trim_right()); + if last_snippet == snippet && !this.output_at_start() { + // No new lines in the snippet. + this.push_str("\n"); + } + let indent = this.block_indent.to_string(config); + this.push_str(&indent); + }) + } + + pub fn format_missing_no_indent(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, _| { + this.push_str(last_snippet.trim_right()); + }) + } + + fn format_missing_inner( + &mut self, + end: BytePos, + process_last_snippet: F, + ) { + let start = self.last_pos; + + if start == end { + // Do nothing if this is the beginning of the file. + if !self.output_at_start() { + process_last_snippet(self, "", ""); + } + return; + } + + assert!( + start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end) + ); + + self.last_pos = end; + let span = mk_sp(start, end); + let snippet = self.snippet(span); + if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { + // Keep vertical spaces within range. + self.push_vertical_spaces(count_newlines(snippet)); + process_last_snippet(self, "", snippet); + } else { + self.write_snippet(span, &process_last_snippet); + } + } + + fn push_vertical_spaces(&mut self, mut newline_count: usize) { + // The buffer already has a trailing newline. + let offset = if self.buffer.ends_with('\n') { 0 } else { 1 }; + let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; + let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; + if newline_count > newline_upper_bound { + newline_count = newline_upper_bound; + } else if newline_count < newline_lower_bound { + newline_count = newline_lower_bound; + } + let blank_lines: String = repeat('\n').take(newline_count).collect(); + self.push_str(&blank_lines); + } + + fn write_snippet(&mut self, span: Span, process_last_snippet: F) + where + F: Fn(&mut FmtVisitor, &str, &str), + { + // Get a snippet from the file start to the span's hi without allocating. + // We need it to determine what precedes the current comment. If the comment + // follows code on the same line, we won't touch it. + let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos; + let local_begin = self.codemap.lookup_byte_offset(big_span_lo); + let local_end = self.codemap.lookup_byte_offset(span.hi()); + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; + + let big_diff = (span.lo() - big_span_lo).to_usize(); + let snippet = self.snippet(span); + + debug!("write_snippet `{}`", snippet); + + self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); + } + + fn write_snippet_inner( + &mut self, + big_snippet: &str, + big_diff: usize, + old_snippet: &str, + span: Span, + process_last_snippet: F, + ) where + F: Fn(&mut FmtVisitor, &str, &str), + { + // Trim whitespace from the right hand side of each line. + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let char_pos = self.codemap.lookup_char_pos(span.lo()); + let file_name = &char_pos.file.name; + let mut status = SnippetStatus::new(char_pos.line); + + let snippet = &*match self.config.write_mode() { + WriteMode::Coverage => replace_chars(old_snippet), + _ => Cow::from(old_snippet), + }; + + for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { + debug!("{:?}: {:?}", kind, subslice); + + let newline_count = count_newlines(subslice); + let within_file_lines_range = self.config.file_lines().intersects_range( + file_name, + status.cur_line, + status.cur_line + newline_count, + ); + + if CodeCharKind::Comment == kind && within_file_lines_range { + // 1: comment. + self.process_comment( + &mut status, + snippet, + &big_snippet[..(offset + big_diff)], + offset, + subslice, + ); + } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range { + // 2: blank lines. + self.push_vertical_spaces(newline_count); + status.cur_line += newline_count; + status.line_start = offset + newline_count; + } else { + // 3: code which we failed to format or which is not within file-lines range. + self.process_missing_code(&mut status, snippet, subslice, offset, file_name); + } + } + + process_last_snippet(self, &snippet[status.line_start..], snippet); + } + + fn process_comment( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + big_snippet: &str, + offset: usize, + subslice: &str, + ) { + let last_char = big_snippet + .chars() + .rev() + .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) + .next(); + + let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); + + let comment_indent = if fix_indent { + if let Some('{') = last_char { + self.push_str("\n"); + } + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + self.block_indent + } else { + self.push_str(" "); + Indent::from_width(self.config, last_line_width(&self.buffer)) + }; + + let comment_width = ::std::cmp::min( + self.config.comment_width(), + self.config.max_width() - self.block_indent.width(), + ); + let comment_shape = Shape::legacy(comment_width, comment_indent); + let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) + .unwrap_or_else(|| String::from(subslice)); + self.push_str(&comment_str); + + status.last_wspace = None; + status.line_start = offset + subslice.len(); + + if let Some('/') = subslice.chars().nth(1) { + // check that there are no contained block comments + if !subslice + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() >= 2 && &s[0..2] == "/*") + { + // Add a newline after line comments + self.push_str("\n"); + } + } else if status.line_start <= snippet.len() { + // For other comments add a newline if there isn't one at the end already + match snippet[status.line_start..].chars().next() { + Some('\n') | Some('\r') => (), + _ => self.push_str("\n"), + } + } + + status.cur_line += count_newlines(subslice); + } + + fn process_missing_code( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + subslice: &str, + offset: usize, + file_name: &FileName, + ) { + for (mut i, c) in subslice.char_indices() { + i += offset; + + if c == '\n' { + let skip_this_line = !self.config + .file_lines() + .contains_line(file_name, status.cur_line); + if skip_this_line { + status.last_wspace = None; + } + + if let Some(lw) = status.last_wspace { + self.push_str(&snippet[status.line_start..lw]); + self.push_str("\n"); + status.last_wspace = None; + } else { + self.push_str(&snippet[status.line_start..i + 1]); + } + + status.cur_line += 1; + status.line_start = i + 1; + } else if c.is_whitespace() && status.last_wspace.is_none() { + status.last_wspace = Some(i); + } else if c == ';' && status.last_wspace.is_some() { + status.line_start = i; + status.last_wspace = None; + } else { + status.last_wspace = None; + } + } + + let remaining = snippet[status.line_start..subslice.len() + offset].trim(); + if !remaining.is_empty() { + self.push_str(remaining); + status.line_start = subslice.len() + offset; + } + } +} + +fn replace_chars(string: &str) -> Cow { + Cow::from( + string + .chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect::(), + ) +} diff --git a/rustfmt-core/src/modules.rs b/rustfmt-core/src/modules.rs new file mode 100644 index 00000000000..0f439910324 --- /dev/null +++ b/rustfmt-core/src/modules.rs @@ -0,0 +1,86 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeMap; +use std::io; +use std::path::{Path, PathBuf}; + +use syntax::ast; +use syntax::codemap::{self, FileName}; +use syntax::parse::parser; + +use utils::contains_skip; + +/// List all the files containing modules of a crate. +/// If a file is used twice in a crate, it appears only once. +pub fn list_files<'a>( + krate: &'a ast::Crate, + codemap: &codemap::CodeMap, +) -> Result, io::Error> { + let mut result = BTreeMap::new(); // Enforce file order determinism + let root_filename = codemap.span_to_filename(krate.span); + { + let parent = match root_filename { + FileName::Real(ref path) => path.parent().unwrap(), + _ => Path::new(""), + }; + list_submodules(&krate.module, parent, codemap, &mut result)?; + } + result.insert(root_filename, &krate.module); + Ok(result) +} + +/// Recursively list all external modules included in a module. +fn list_submodules<'a>( + module: &'a ast::Mod, + search_dir: &Path, + codemap: &codemap::CodeMap, + result: &mut BTreeMap, +) -> Result<(), io::Error> { + debug!("list_submodules: search_dir: {:?}", search_dir); + for item in &module.items { + if let ast::ItemKind::Mod(ref sub_mod) = item.node { + if !contains_skip(&item.attrs) { + let is_internal = + codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); + let dir_path = if is_internal { + search_dir.join(&item.ident.to_string()) + } else { + let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; + let dir_path = mod_path.parent().unwrap().to_owned(); + result.insert(FileName::Real(mod_path), sub_mod); + dir_path + }; + list_submodules(sub_mod, &dir_path, codemap, result)?; + } + } + } + Ok(()) +} + +/// Find the file corresponding to an external mod +fn module_file( + id: ast::Ident, + attrs: &[ast::Attribute], + dir_path: &Path, + codemap: &codemap::CodeMap, +) -> Result { + if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { + return Ok(path); + } + + match parser::Parser::default_submod_path(id, None, dir_path, codemap).result { + Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + format!("Couldn't find module {}", id), + )), + } +} diff --git a/rustfmt-core/src/patterns.rs b/rustfmt-core/src/patterns.rs new file mode 100644 index 00000000000..dc20a6644ff --- /dev/null +++ b/rustfmt-core/src/patterns.rs @@ -0,0 +1,380 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::lists::*; +use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; +use syntax::codemap::{self, BytePos, Span}; +use syntax::ptr; + +use codemap::SpanUtils; +use comment::FindUncommented; +use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, + wrap_struct_field, PairParts}; +use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list}; +use macros::{rewrite_macro, MacroPosition}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use types::{rewrite_path, PathContext}; +use utils::{format_mutability, mk_sp}; + +impl Rewrite for Pat { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), + PatKind::Ident(binding_mode, ident, ref sub_pat) => { + let (prefix, mutability) = match binding_mode { + BindingMode::ByRef(mutability) => ("ref ", mutability), + BindingMode::ByValue(mutability) => ("", mutability), + }; + let mut_infix = format_mutability(mutability); + let id_str = ident.node.to_string(); + let sub_pat = match *sub_pat { + Some(ref p) => { + // 3 - ` @ `. + let width = shape + .width + .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?; + format!( + " @ {}", + p.rewrite(context, Shape::legacy(width, shape.indent))? + ) + } + None => "".to_owned(), + }; + + Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) + } + PatKind::Wild => { + if 1 <= shape.width { + Some("_".to_owned()) + } else { + None + } + } + PatKind::Range(ref lhs, ref rhs, ref end_kind) => { + let infix = match *end_kind { + RangeEnd::Included(RangeSyntax::DotDotDot) => "...", + RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", + RangeEnd::Excluded => "..", + }; + let infix = if context.config.spaces_around_ranges() { + format!(" {} ", infix) + } else { + infix.to_owned() + }; + rewrite_pair( + &**lhs, + &**rhs, + PairParts::new("", &infix, ""), + context, + shape, + SeparatorPlace::Front, + ) + } + PatKind::Ref(ref pat, mutability) => { + let prefix = format!("&{}", format_mutability(mutability)); + rewrite_unary_prefix(context, &prefix, &**pat, shape) + } + PatKind::Tuple(ref items, dotdot_pos) => { + rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) + } + PatKind::Path(ref q_self, ref path) => { + rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) + } + PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { + let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; + rewrite_tuple_pat( + pat_vec, + dotdot_pos, + Some(path_str), + self.span, + context, + shape, + ) + } + PatKind::Lit(ref expr) => expr.rewrite(context, shape), + PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { + // Rewrite all the sub-patterns. + let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); + let slice_pat = slice_pat + .as_ref() + .map(|p| Some(format!("{}..", p.rewrite(context, shape)?))); + let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); + + // Munge them together. + let pats: Option> = + prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); + + // Check that all the rewrites succeeded, and if not return None. + let pats = pats?; + + // Unwrap all the sub-strings and join them with commas. + let result = if context.config.spaces_within_parens_and_brackets() { + format!("[ {} ]", pats.join(", ")) + } else { + format!("[{}]", pats.join(", ")) + }; + Some(result) + } + PatKind::Struct(ref path, ref fields, ellipsis) => { + rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) + } + PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), + } + } +} + +fn rewrite_struct_pat( + path: &ast::Path, + fields: &[codemap::Spanned], + ellipsis: bool, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + // 2 = ` {` + let path_shape = shape.sub_width(2)?; + let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; + + if fields.is_empty() && !ellipsis { + return Some(format!("{} {{}}", path_str)); + } + + let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") }; + + // 3 = ` { `, 2 = ` }`. + let (h_shape, v_shape) = + struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?; + + let items = itemize_list( + context.codemap, + fields.iter(), + terminator, + ",", + |f| f.span.lo(), + |f| f.span.hi(), + |f| f.node.rewrite(context, v_shape), + context.codemap.span_after(span, "{"), + span.hi(), + false, + ); + let item_vec = items.collect::>(); + + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, false); + + let mut fields_str = write_list(&item_vec, &fmt)?; + let one_line_width = h_shape.map_or(0, |shape| shape.width); + + if ellipsis { + if fields_str.contains('\n') || fields_str.len() > one_line_width { + // Add a missing trailing comma. + if fmt.trailing_separator == SeparatorTactic::Never { + fields_str.push_str(","); + } + fields_str.push_str("\n"); + fields_str.push_str(&nested_shape.indent.to_string(context.config)); + fields_str.push_str(".."); + } else { + if !fields_str.is_empty() { + // there are preceding struct fields being matched on + if fmt.tactic == DefinitiveListTactic::Vertical { + // if the tactic is Vertical, write_list already added a trailing , + fields_str.push_str(" "); + } else { + fields_str.push_str(", "); + } + } + fields_str.push_str(".."); + } + } + + let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + Some(format!("{} {{{}}}", path_str, fields_str)) +} + +impl Rewrite for FieldPat { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let pat = self.pat.rewrite(context, shape); + if self.is_shorthand { + pat + } else { + let pat_str = pat?; + let id_str = self.ident.to_string(); + let one_line_width = id_str.len() + 2 + pat_str.len(); + if one_line_width <= shape.width { + Some(format!("{}: {}", id_str, pat_str)) + } else { + let nested_shape = shape.block_indent(context.config.tab_spaces()); + let pat_str = self.pat.rewrite(context, nested_shape)?; + Some(format!( + "{}:\n{}{}", + id_str, + nested_shape.indent.to_string(context.config), + pat_str, + )) + } + } + } +} + +pub enum TuplePatField<'a> { + Pat(&'a ptr::P), + Dotdot(Span), +} + +impl<'a> Rewrite for TuplePatField<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + TuplePatField::Pat(p) => p.rewrite(context, shape), + TuplePatField::Dotdot(_) => Some("..".to_string()), + } + } +} + +impl<'a> Spanned for TuplePatField<'a> { + fn span(&self) -> Span { + match *self { + TuplePatField::Pat(p) => p.span(), + TuplePatField::Dotdot(span) => span, + } + } +} + +pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { + match *pat { + TuplePatField::Pat(pat) => match pat.node { + ast::PatKind::Path(..) + | ast::PatKind::Tuple(..) + | ast::PatKind::Struct(..) + | ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, + ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { + can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) + } + ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), + _ => false, + }, + TuplePatField::Dotdot(..) => false, + } +} + +fn rewrite_tuple_pat( + pats: &[ptr::P], + dotdot_pos: Option, + path_str: Option, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); + + if let Some(pos) = dotdot_pos { + let prev = if pos == 0 { + span.lo() + } else { + pats[pos - 1].span().hi() + }; + let next = if pos + 1 >= pats.len() { + span.hi() + } else { + pats[pos + 1].span().lo() + }; + let dot_span = mk_sp(prev, next); + let snippet = context.snippet(dot_span); + let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32); + let dotdot = TuplePatField::Dotdot(Span::new( + lo, + // 2 == "..".len() + lo + BytePos(2), + codemap::NO_EXPANSION, + )); + pat_vec.insert(pos, dotdot); + } + + if pat_vec.is_empty() { + return Some(format!("{}()", path_str.unwrap_or_default())); + } + + let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); + let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 + { + let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; + let sp = pat_vec[new_item_count - 1].span(); + let snippet = context.snippet(sp); + let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + ( + &pat_vec[..new_item_count], + mk_sp(span.lo(), lo + BytePos(1)), + ) + } else { + (&pat_vec[..], span) + }; + + // add comma if `(x,)` + let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + let mut context = context.clone(); + if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { + context.inside_macro = true; + } + let path_str = path_str.unwrap_or_default(); + let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); + for pat in pat_vec { + pat_ref_vec.push(pat); + } + + rewrite_call_inner( + &context, + &path_str, + &pat_ref_vec[..], + span, + shape, + shape.width, + add_comma, + ) +} + +fn count_wildcard_suffix_len( + context: &RewriteContext, + patterns: &[TuplePatField], + span: Span, + shape: Shape, +) -> usize { + let mut suffix_len = 0; + + let items: Vec<_> = itemize_list( + context.codemap, + patterns.iter(), + ")", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, shape), + context.codemap.span_after(span, "("), + span.hi() - BytePos(1), + false, + ).collect(); + + for item in items.iter().rev().take_while(|i| match i.item { + Some(ref internal_string) if internal_string == "_" => true, + _ => false, + }) { + suffix_len += 1; + + if item.pre_comment.is_some() || item.post_comment.is_some() { + break; + } + } + + suffix_len +} diff --git a/rustfmt-core/src/rewrite.rs b/rustfmt-core/src/rewrite.rs new file mode 100644 index 00000000000..708e31d86dd --- /dev/null +++ b/rustfmt-core/src/rewrite.rs @@ -0,0 +1,54 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// A generic trait to abstract the rewriting of an element (of the AST). + +use syntax::codemap::{CodeMap, Span}; +use syntax::parse::ParseSess; + +use config::{Config, IndentStyle}; +use shape::Shape; +use visitor::SnippetProvider; + +pub trait Rewrite { + /// Rewrite self into shape. + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; +} + +#[derive(Clone)] +pub struct RewriteContext<'a> { + pub parse_session: &'a ParseSess, + pub codemap: &'a CodeMap, + pub config: &'a Config, + pub inside_macro: bool, + // Force block indent style even if we are using visual indent style. + pub use_block: bool, + // When `format_if_else_cond_comment` is true, unindent the comment on top + // of the `else` or `else if`. + pub is_if_else_block: bool, + // When rewriting chain, veto going multi line except the last element + pub force_one_line_chain: bool, + pub snippet_provider: &'a SnippetProvider<'a>, +} + +impl<'a> RewriteContext<'a> { + pub fn snippet(&self, span: Span) -> &str { + self.snippet_provider.span_to_snippet(span).unwrap() + } + + /// Return true if we should use block indent style for rewriting function call. + pub fn use_block_indent(&self) -> bool { + self.config.indent_style() == IndentStyle::Block || self.use_block + } + + pub fn budget(&self, used_width: usize) -> usize { + self.config.max_width().checked_sub(used_width).unwrap_or(0) + } +} diff --git a/rustfmt-core/src/rustfmt_diff.rs b/rustfmt-core/src/rustfmt_diff.rs new file mode 100644 index 00000000000..1a2f570f89e --- /dev/null +++ b/rustfmt-core/src/rustfmt_diff.rs @@ -0,0 +1,247 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::Color; +use diff; +use std::collections::VecDeque; +use std::io; +use term; +use utils::use_colored_tty; + +#[derive(Debug, PartialEq)] +pub enum DiffLine { + Context(String), + Expected(String), + Resulting(String), +} + +#[derive(Debug, PartialEq)] +pub struct Mismatch { + pub line_number: u32, + pub lines: Vec, +} + +impl Mismatch { + fn new(line_number: u32) -> Mismatch { + Mismatch { + line_number, + lines: Vec::new(), + } + } +} + +// This struct handles writing output to stdout and abstracts away the logic +// of printing in color, if it's possible in the executing environment. +pub struct OutputWriter { + terminal: Option>>, +} + +impl OutputWriter { + // Create a new OutputWriter instance based on the caller's preference + // for colorized output and the capabilities of the terminal. + pub fn new(color: Color) -> Self { + if let Some(t) = term::stdout() { + if use_colored_tty(color) && t.supports_color() { + return OutputWriter { terminal: Some(t) }; + } + } + OutputWriter { terminal: None } + } + + // Write output in the optionally specified color. The output is written + // in the specified color if this OutputWriter instance contains a + // Terminal in its `terminal` field. + pub fn writeln(&mut self, msg: &str, color: Option) { + match &mut self.terminal { + Some(ref mut t) => { + if let Some(color) = color { + t.fg(color).unwrap(); + } + writeln!(t, "{}", msg).unwrap(); + if color.is_some() { + t.reset().unwrap(); + } + } + None => println!("{}", msg), + } + } +} + +// Produces a diff between the expected output and actual output of rustfmt. +pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { + let mut line_number = 1; + let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); + let mut lines_since_mismatch = context_size + 1; + let mut results = Vec::new(); + let mut mismatch = Mismatch::new(0); + + for result in diff::lines(expected, actual) { + match result { + diff::Result::Left(str) => { + if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { + results.push(mismatch); + mismatch = Mismatch::new(line_number - context_queue.len() as u32); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Resulting(str.to_owned())); + lines_since_mismatch = 0; + } + diff::Result::Right(str) => { + if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { + results.push(mismatch); + mismatch = Mismatch::new(line_number - context_queue.len() as u32); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Expected(str.to_owned())); + line_number += 1; + lines_since_mismatch = 0; + } + diff::Result::Both(str, _) => { + if context_queue.len() >= context_size { + let _ = context_queue.pop_front(); + } + + if lines_since_mismatch < context_size { + mismatch.lines.push(DiffLine::Context(str.to_owned())); + } else if context_size > 0 { + context_queue.push_back(str); + } + + line_number += 1; + lines_since_mismatch += 1; + } + } + } + + results.push(mismatch); + results.remove(0); + + results +} + +pub fn print_diff(diff: Vec, get_section_title: F, color: Color) +where + F: Fn(u32) -> String, +{ + let mut writer = OutputWriter::new(color); + + for mismatch in diff { + let title = get_section_title(mismatch.line_number); + writer.writeln(&format!("{}", title), None); + + for line in mismatch.lines { + match line { + DiffLine::Context(ref str) => writer.writeln(&format!(" {}⏎", str), None), + DiffLine::Expected(ref str) => { + writer.writeln(&format!("+{}⏎", str), Some(term::color::GREEN)) + } + DiffLine::Resulting(ref str) => { + writer.writeln(&format!("-{}⏎", str), Some(term::color::RED)) + } + } + } + } +} + +#[cfg(test)] +mod test { + use super::{make_diff, Mismatch}; + use super::DiffLine::*; + + #[test] + fn diff_simple() { + let src = "one\ntwo\nthree\nfour\nfive\n"; + let dest = "one\ntwo\ntrois\nfour\nfive\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 2, + lines: vec![ + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), + ], + }, + ] + ); + } + + #[test] + fn diff_simple2() { + let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n"; + let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 2, + lines: vec![ + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), + ], + }, + Mismatch { + line_number: 5, + lines: vec![ + Resulting("five".to_owned()), + Expected("cinq".to_owned()), + Context("six".to_owned()), + ], + }, + ] + ); + } + + #[test] + fn diff_zerocontext() { + let src = "one\ntwo\nthree\nfour\nfive\n"; + let dest = "one\ntwo\ntrois\nfour\nfive\n"; + let diff = make_diff(src, dest, 0); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 3, + lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], + }, + ] + ); + } + + #[test] + fn diff_trailing_newline() { + let src = "one\ntwo\nthree\nfour\nfive"; + let dest = "one\ntwo\nthree\nfour\nfive\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 5, + lines: vec![Context("five".to_owned()), Expected("".to_owned())], + }, + ] + ); + } +} diff --git a/rustfmt-core/src/shape.rs b/rustfmt-core/src/shape.rs new file mode 100644 index 00000000000..8fe2e2b18c0 --- /dev/null +++ b/rustfmt-core/src/shape.rs @@ -0,0 +1,353 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::ops::{Add, Sub}; + +use Config; + +#[derive(Copy, Clone, Debug)] +pub struct Indent { + // Width of the block indent, in characters. Must be a multiple of + // Config::tab_spaces. + pub block_indent: usize, + // Alignment in characters. + pub alignment: usize, +} + +// INDENT_BUFFER.len() = 80 +const INDENT_BUFFER_LEN: usize = 80; +const INDENT_BUFFER: &str = + " "; +impl Indent { + pub fn new(block_indent: usize, alignment: usize) -> Indent { + Indent { + block_indent, + alignment, + } + } + + pub fn from_width(config: &Config, width: usize) -> Indent { + if config.hard_tabs() { + let tab_num = width / config.tab_spaces(); + let alignment = width % config.tab_spaces(); + Indent::new(config.tab_spaces() * tab_num, alignment) + } else { + Indent::new(width, 0) + } + } + + pub fn empty() -> Indent { + Indent::new(0, 0) + } + + pub fn block_only(&self) -> Indent { + Indent { + block_indent: self.block_indent, + alignment: 0, + } + } + + pub fn block_indent(mut self, config: &Config) -> Indent { + self.block_indent += config.tab_spaces(); + self + } + + pub fn block_unindent(mut self, config: &Config) -> Indent { + if self.block_indent < config.tab_spaces() { + Indent::new(self.block_indent, 0) + } else { + self.block_indent -= config.tab_spaces(); + self + } + } + + pub fn width(&self) -> usize { + self.block_indent + self.alignment + } + + pub fn to_string(&self, config: &Config) -> Cow<'static, str> { + let (num_tabs, num_spaces) = if config.hard_tabs() { + (self.block_indent / config.tab_spaces(), self.alignment) + } else { + (0, self.width()) + }; + let num_chars = num_tabs + num_spaces; + if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN { + Cow::from(&INDENT_BUFFER[0..num_chars]) + } else { + let mut indent = String::with_capacity(num_chars); + for _ in 0..num_tabs { + indent.push('\t') + } + for _ in 0..num_spaces { + indent.push(' ') + } + Cow::from(indent) + } + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: Indent) -> Indent { + Indent { + block_indent: self.block_indent + rhs.block_indent, + alignment: self.alignment + rhs.alignment, + } + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: Indent) -> Indent { + Indent::new( + self.block_indent - rhs.block_indent, + self.alignment - rhs.alignment, + ) + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment + rhs) + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment - rhs) + } +} + +#[derive(Copy, Clone, Debug)] +pub struct Shape { + pub width: usize, + // The current indentation of code. + pub indent: Indent, + // Indentation + any already emitted text on the first line of the current + // statement. + pub offset: usize, +} + +impl Shape { + /// `indent` is the indentation of the first line. The next lines + /// should begin with at least `indent` spaces (except backwards + /// indentation). The first line should not begin with indentation. + /// `width` is the maximum number of characters on the last line + /// (excluding `indent`). The width of other lines is not limited by + /// `width`. + /// Note that in reality, we sometimes use width for lines other than the + /// last (i.e., we are conservative). + // .......*-------* + // | | + // | *-* + // *-----| + // |<------------>| max width + // |<---->| indent + // |<--->| width + pub fn legacy(width: usize, indent: Indent) -> Shape { + Shape { + width, + indent, + offset: indent.alignment, + } + } + + pub fn indented(indent: Indent, config: &Config) -> Shape { + Shape { + width: config.max_width().checked_sub(indent.width()).unwrap_or(0), + indent, + offset: indent.alignment, + } + } + + pub fn with_max_width(&self, config: &Config) -> Shape { + Shape { + width: config + .max_width() + .checked_sub(self.indent.width()) + .unwrap_or(0), + ..*self + } + } + + pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { + Shape { + width, + indent, + offset, + } + } + + pub fn visual_indent(&self, extra_width: usize) -> Shape { + let alignment = self.offset + extra_width; + Shape { + width: self.width, + indent: Indent::new(self.indent.block_indent, alignment), + offset: alignment, + } + } + + pub fn block_indent(&self, extra_width: usize) -> Shape { + if self.indent.alignment == 0 { + Shape { + width: self.width, + indent: Indent::new(self.indent.block_indent + extra_width, 0), + offset: 0, + } + } else { + Shape { + width: self.width, + indent: self.indent + extra_width, + offset: self.indent.alignment + extra_width, + } + } + } + + pub fn block_left(&self, width: usize) -> Option { + self.block_indent(width).sub_width(width) + } + + pub fn add_offset(&self, extra_width: usize) -> Shape { + Shape { + offset: self.offset + extra_width, + ..*self + } + } + + pub fn block(&self) -> Shape { + Shape { + indent: self.indent.block_only(), + ..*self + } + } + + pub fn sub_width(&self, width: usize) -> Option { + Some(Shape { + width: self.width.checked_sub(width)?, + ..*self + }) + } + + pub fn shrink_left(&self, width: usize) -> Option { + Some(Shape { + width: self.width.checked_sub(width)?, + indent: self.indent + width, + offset: self.offset + width, + }) + } + + pub fn offset_left(&self, width: usize) -> Option { + self.add_offset(width).sub_width(width) + } + + pub fn used_width(&self) -> usize { + self.indent.block_indent + self.offset + } + + pub fn rhs_overhead(&self, config: &Config) -> usize { + config + .max_width() + .checked_sub(self.used_width() + self.width) + .unwrap_or(0) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn indent_add_sub() { + let indent = Indent::new(4, 8) + Indent::new(8, 12); + assert_eq!(12, indent.block_indent); + assert_eq!(20, indent.alignment); + + let indent = indent - Indent::new(4, 4); + assert_eq!(8, indent.block_indent); + assert_eq!(16, indent.alignment); + } + + #[test] + fn indent_add_sub_alignment() { + let indent = Indent::new(4, 8) + 4; + assert_eq!(4, indent.block_indent); + assert_eq!(12, indent.alignment); + + let indent = indent - 4; + assert_eq!(4, indent.block_indent); + assert_eq!(8, indent.alignment); + } + + #[test] + fn indent_to_string_spaces() { + let config = Config::default(); + let indent = Indent::new(4, 8); + + // 12 spaces + assert_eq!(" ", indent.to_string(&config)); + } + + #[test] + fn indent_to_string_hard_tabs() { + let mut config = Config::default(); + config.set().hard_tabs(true); + let indent = Indent::new(8, 4); + + // 2 tabs + 4 spaces + assert_eq!("\t\t ", indent.to_string(&config)); + } + + #[test] + fn shape_visual_indent() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.visual_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } + + #[test] + fn shape_block_indent_without_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 0); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(24, shape.indent.block_indent); + assert_eq!(0, shape.indent.alignment); + assert_eq!(0, shape.offset); + } + + #[test] + fn shape_block_indent_with_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } +} diff --git a/rustfmt-core/src/spanned.rs b/rustfmt-core/src/spanned.rs new file mode 100644 index 00000000000..a431f3a544a --- /dev/null +++ b/rustfmt-core/src/spanned.rs @@ -0,0 +1,187 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::ast; +use syntax::codemap::Span; + +use macros::MacroArg; +use utils::{mk_sp, outer_attributes}; + +/// Spanned returns a span including attributes, if available. +pub trait Spanned { + fn span(&self) -> Span; +} + +macro_rules! span_with_attrs_lo_hi { + ($this: ident, $lo: expr, $hi: expr) => {{ + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo(), $hi) + } + }}; +} + +macro_rules! span_with_attrs { + ($this: ident) => { + span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) + }; +} + +macro_rules! implement_spanned { + ($this: ty) => { + impl Spanned for $this { + fn span(&self) -> Span { + span_with_attrs!(self) + } + } + }; +} + +// Implement `Spanned` for structs with `attrs` field. +implement_spanned!(ast::Expr); +implement_spanned!(ast::Field); +implement_spanned!(ast::ForeignItem); +implement_spanned!(ast::Item); +implement_spanned!(ast::Local); +implement_spanned!(ast::TraitItem); +implement_spanned!(ast::ImplItem); + +impl Spanned for ast::Stmt { + fn span(&self) -> Span { + match self.node { + ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { + mk_sp(expr.span().lo(), self.span.hi()) + } + ast::StmtKind::Mac(ref mac) => { + let (_, _, ref attrs) = **mac; + if attrs.is_empty() { + self.span + } else { + mk_sp(attrs[0].span.lo(), self.span.hi()) + } + } + } + } +} + +impl Spanned for ast::Pat { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Ty { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Arm { + fn span(&self) -> Span { + span_with_attrs_lo_hi!(self, self.pats[0].span.lo(), self.body.span.hi()) + } +} + +impl Spanned for ast::Arg { + fn span(&self) -> Span { + if ::items::is_named_arg(self) { + mk_sp(self.pat.span.lo(), self.ty.span.hi()) + } else { + self.ty.span + } + } +} + +impl Spanned for ast::GenericParam { + fn span(&self) -> Span { + match *self { + ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(), + ast::GenericParam::Type(ref ty) => ty.span(), + } + } +} + +impl Spanned for ast::StructField { + fn span(&self) -> Span { + span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) + } +} + +impl Spanned for ast::WherePredicate { + fn span(&self) -> Span { + match *self { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } + } +} + +impl Spanned for ast::FunctionRetTy { + fn span(&self) -> Span { + match *self { + ast::FunctionRetTy::Default(span) => span, + ast::FunctionRetTy::Ty(ref ty) => ty.span, + } + } +} + +impl Spanned for ast::TyParam { + fn span(&self) -> Span { + // Note that ty.span is the span for ty.ident, not the whole item. + let lo = if self.attrs.is_empty() { + self.span.lo() + } else { + self.attrs[0].span.lo() + }; + if let Some(ref def) = self.default { + return mk_sp(lo, def.span.hi()); + } + if self.bounds.is_empty() { + return mk_sp(lo, self.span.hi()); + } + let hi = self.bounds[self.bounds.len() - 1].span().hi(); + mk_sp(lo, hi) + } +} + +impl Spanned for ast::TyParamBound { + fn span(&self) -> Span { + match *self { + ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, + ast::TyParamBound::RegionTyParamBound(ref l) => l.span, + } + } +} + +impl Spanned for ast::LifetimeDef { + fn span(&self) -> Span { + let hi = if self.bounds.is_empty() { + self.lifetime.span.hi() + } else { + self.bounds[self.bounds.len() - 1].span.hi() + }; + mk_sp(self.lifetime.span.lo(), hi) + } +} + +impl Spanned for MacroArg { + fn span(&self) -> Span { + match *self { + MacroArg::Expr(ref expr) => expr.span(), + MacroArg::Ty(ref ty) => ty.span(), + MacroArg::Pat(ref pat) => pat.span(), + } + } +} diff --git a/rustfmt-core/src/string.rs b/rustfmt-core/src/string.rs new file mode 100644 index 00000000000..2386d90ec8a --- /dev/null +++ b/rustfmt-core/src/string.rs @@ -0,0 +1,163 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format string literals. + +use regex::Regex; +use unicode_segmentation::UnicodeSegmentation; + +use config::Config; +use shape::Shape; +use utils::wrap_str; + +const MIN_STRING: usize = 10; + +pub struct StringFormat<'a> { + pub opener: &'a str, + pub closer: &'a str, + pub line_start: &'a str, + pub line_end: &'a str, + pub shape: Shape, + pub trim_end: bool, + pub config: &'a Config, +} + +impl<'a> StringFormat<'a> { + pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { + StringFormat { + opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + shape, + trim_end: false, + config, + } + } +} + +// FIXME: simplify this! +pub fn rewrite_string<'a>( + orig: &str, + fmt: &StringFormat<'a>, + max_width: Option, +) -> Option { + // Strip line breaks. + let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); + let stripped_str = re.replace_all(orig, "$1"); + + let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); + let shape = fmt.shape; + let indent = shape.indent.to_string(fmt.config); + let punctuation = ":,;."; + + // `cur_start` is the position in `orig` of the start of the current line. + let mut cur_start = 0; + let mut result = String::with_capacity( + stripped_str + .len() + .checked_next_power_of_two() + .unwrap_or(usize::max_value()), + ); + result.push_str(fmt.opener); + + let ender_length = fmt.line_end.len(); + // If we cannot put at least a single character per line, the rewrite won't + // succeed. + let mut max_chars = shape + .width + .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + + // Snip a line at a time from `orig` until it is used up. Push the snippet + // onto result. + 'outer: loop { + // `cur_end` will be where we break the line, as an offset into `orig`. + // Initialised to the maximum it could be (which may be beyond `orig`). + let mut cur_end = cur_start + max_chars; + + // We can fit the rest of the string on this line, so we're done. + if cur_end >= graphemes.len() { + let line = &graphemes[cur_start..].join(""); + result.push_str(line); + break 'outer; + } + + // Push cur_end left until we reach whitespace (or the line is too small). + while !graphemes[cur_end - 1].trim().is_empty() { + cur_end -= 1; + if cur_end < cur_start + MIN_STRING { + // We couldn't find whitespace before the string got too small. + // So start again at the max length and look for punctuation. + cur_end = cur_start + max_chars; + while !punctuation.contains(graphemes[cur_end - 1]) { + cur_end -= 1; + + // If we can't break at whitespace or punctuation, grow the string instead. + if cur_end < cur_start + MIN_STRING { + cur_end = cur_start + max_chars; + while !(punctuation.contains(graphemes[cur_end - 1]) + || graphemes[cur_end - 1].trim().is_empty()) + { + if cur_end >= graphemes.len() { + let line = &graphemes[cur_start..].join(""); + result.push_str(line); + break 'outer; + } + cur_end += 1; + } + break; + } + } + break; + } + } + // Make sure there is no whitespace to the right of the break. + while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { + cur_end += 1; + } + + // Make the current line and add it on to result. + let raw_line = graphemes[cur_start..cur_end].join(""); + let line = if fmt.trim_end { + raw_line.trim() + } else { + raw_line.as_str() + }; + + result.push_str(line); + result.push_str(fmt.line_end); + result.push('\n'); + result.push_str(&indent); + result.push_str(fmt.line_start); + + // The next line starts where the current line ends. + cur_start = cur_end; + + if let Some(new_max_chars) = max_width { + max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + } + } + + result.push_str(fmt.closer); + wrap_str(result, fmt.config.max_width(), fmt.shape) +} + +#[cfg(test)] +mod test { + use super::{rewrite_string, StringFormat}; + use shape::{Indent, Shape}; + + #[test] + fn issue343() { + let config = Default::default(); + let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); + rewrite_string("eq_", &fmt, None); + } +} diff --git a/rustfmt-core/src/types.rs b/rustfmt-core/src/types.rs new file mode 100644 index 00000000000..f6f80ba312b --- /dev/null +++ b/rustfmt-core/src/types.rs @@ -0,0 +1,820 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter::ExactSizeIterator; +use std::ops::Deref; + +use config::lists::*; +use syntax::ast::{self, FunctionRetTy, Mutability}; +use syntax::codemap::{self, BytePos, Span}; +use syntax::print::pprust; +use syntax::symbol::keywords; + +use codemap::SpanUtils; +use config::{IndentStyle, TypeDensity}; +use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; +use items::{format_generics_item_list, generics_shape_from_config}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use macros::{rewrite_macro, MacroPosition}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, + last_line_width, mk_sp}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum PathContext { + Expr, + Type, + Import, +} + +// Does not wrap on simple segments. +pub fn rewrite_path( + context: &RewriteContext, + path_context: PathContext, + qself: Option<&ast::QSelf>, + path: &ast::Path, + shape: Shape, +) -> Option { + let skip_count = qself.map_or(0, |x| x.position); + + let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import { + "::".to_owned() + } else { + String::new() + }; + + let mut span_lo = path.span.lo(); + + if let Some(qself) = qself { + result.push('<'); + if context.config.spaces_within_parens_and_brackets() { + result.push_str(" ") + } + + let fmt_ty = qself.ty.rewrite(context, shape)?; + result.push_str(&fmt_ty); + + if skip_count > 0 { + result.push_str(" as "); + if path.is_global() && path_context != PathContext::Import { + result.push_str("::"); + } + + // 3 = ">::".len() + let shape = shape.sub_width(3)?; + + result = rewrite_path_segments( + PathContext::Type, + result, + path.segments.iter().take(skip_count), + span_lo, + path.span.hi(), + context, + shape, + )?; + } + + if context.config.spaces_within_parens_and_brackets() { + result.push_str(" ") + } + + result.push_str(">::"); + span_lo = qself.ty.span.hi() + BytePos(1); + } + + rewrite_path_segments( + path_context, + result, + path.segments.iter().skip(skip_count), + span_lo, + path.span.hi(), + context, + shape, + ) +} + +fn rewrite_path_segments<'a, I>( + path_context: PathContext, + mut buffer: String, + iter: I, + mut span_lo: BytePos, + span_hi: BytePos, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: Iterator, +{ + let mut first = true; + let shape = shape.visual_indent(0); + + for segment in iter { + // Indicates a global path, shouldn't be rendered. + if segment.identifier.name == keywords::CrateRoot.name() { + continue; + } + if first { + first = false; + } else { + buffer.push_str("::"); + } + + let extra_offset = extra_offset(&buffer, shape); + let new_shape = shape.shrink_left(extra_offset)?; + let segment_string = rewrite_segment( + path_context, + segment, + &mut span_lo, + span_hi, + context, + new_shape, + )?; + + buffer.push_str(&segment_string); + } + + Some(buffer) +} + +#[derive(Debug)] +enum SegmentParam<'a> { + LifeTime(&'a ast::Lifetime), + Type(&'a ast::Ty), + Binding(&'a ast::TypeBinding), +} + +impl<'a> SegmentParam<'a> { + fn get_span(&self) -> Span { + match *self { + SegmentParam::LifeTime(lt) => lt.span, + SegmentParam::Type(ty) => ty.span, + SegmentParam::Binding(binding) => binding.span, + } + } +} + +impl<'a> Rewrite for SegmentParam<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), + SegmentParam::Type(ty) => ty.rewrite(context, shape), + SegmentParam::Binding(binding) => { + let mut result = match context.config.type_punctuation_density() { + TypeDensity::Wide => format!("{} = ", binding.ident), + TypeDensity::Compressed => format!("{}=", binding.ident), + }; + let budget = shape.width.checked_sub(result.len())?; + let rewrite = binding + .ty + .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; + result.push_str(&rewrite); + Some(result) + } + } + } +} + +// Formats a path segment. There are some hacks involved to correctly determine +// the segment's associated span since it's not part of the AST. +// +// The span_lo is assumed to be greater than the end of any previous segment's +// parameters and lesser or equal than the start of current segment. +// +// span_hi is assumed equal to the end of the entire path. +// +// When the segment contains a positive number of parameters, we update span_lo +// so that invariants described above will hold for the next segment. +fn rewrite_segment( + path_context: PathContext, + segment: &ast::PathSegment, + span_lo: &mut BytePos, + span_hi: BytePos, + context: &RewriteContext, + shape: Shape, +) -> Option { + let ident_len = segment.identifier.to_string().len(); + let shape = shape.shrink_left(ident_len)?; + + let params = if let Some(ref params) = segment.parameters { + match **params { + ast::PathParameters::AngleBracketed(ref data) + if !data.lifetimes.is_empty() || !data.types.is_empty() + || !data.bindings.is_empty() => + { + let param_list = data.lifetimes + .iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .collect::>(); + + let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1); + let list_lo = context.codemap.span_after(mk_sp(*span_lo, span_hi), "<"); + let separator = if path_context == PathContext::Expr { + "::" + } else { + "" + }; + + let generics_shape = + generics_shape_from_config(context.config, shape, separator.len())?; + let one_line_width = shape.width.checked_sub(separator.len() + 2)?; + let items = itemize_list( + context.codemap, + param_list.into_iter(), + ">", + ",", + |param| param.get_span().lo(), + |param| param.get_span().hi(), + |seg| seg.rewrite(context, generics_shape), + list_lo, + span_hi, + false, + ); + let generics_str = + format_generics_item_list(context, items, generics_shape, one_line_width)?; + + // Update position of last bracket. + *span_lo = next_span_lo; + + format!("{}{}", separator, generics_str) + } + ast::PathParameters::Parenthesized(ref data) => { + let output = match data.output { + Some(ref ty) => FunctionRetTy::Ty(ty.clone()), + None => FunctionRetTy::Default(codemap::DUMMY_SP), + }; + format_function_type( + data.inputs.iter().map(|x| &**x), + &output, + false, + data.span, + context, + shape, + )? + } + _ => String::new(), + } + } else { + String::new() + }; + + Some(format!("{}{}", segment.identifier, params)) +} + +fn format_function_type<'a, I>( + inputs: I, + output: &FunctionRetTy, + variadic: bool, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, + ::Item: Deref, + ::Target: Rewrite + Spanned + 'a, +{ + // Code for handling variadics is somewhat duplicated for items, but they + // are different enough to need some serious refactoring to share code. + enum ArgumentKind + where + T: Deref, + ::Target: Rewrite + Spanned, + { + Regular(Box), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_start = context.codemap.span_before(span, "..."); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + + // 2 for () + let budget = shape.width.checked_sub(2)?; + // 1 for ( + let offset = match context.config.indent_style() { + IndentStyle::Block => { + shape + .block() + .block_indent(context.config.tab_spaces()) + .indent + } + IndentStyle::Visual => shape.indent + 1, + }; + let list_shape = Shape::legacy(budget, offset); + let list_lo = context.codemap.span_after(span, "("); + let items = itemize_list( + context.codemap, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs + .map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), + ")", + ",", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo(), + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi(), + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi(), + false, + ); + + let item_vec: Vec<_> = items.collect(); + + let tactic = definitive_tactic( + &*item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + budget, + ); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if !context.use_block_indent() || variadic { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape: list_shape, + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + + let list_str = write_list(&item_vec, &fmt)?; + + let ty_shape = match context.config.indent_style() { + // 4 = " -> " + IndentStyle::Block => shape.offset_left(4)?, + IndentStyle::Visual => shape.block_left(4)?, + }; + let output = match *output { + FunctionRetTy::Ty(ref ty) => { + let type_str = ty.rewrite(context, ty_shape)?; + format!(" -> {}", type_str) + } + FunctionRetTy::Default(..) => String::new(), + }; + + let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n'); + let args = wrap_args_with_parens( + context, + &list_str, + extendable, + shape.sub_width(first_line_width(&output))?, + Shape::indented(offset, context.config), + ); + if last_line_width(&args) + first_line_width(&output) <= shape.width { + Some(format!("{}{}", args, output)) + } else { + Some(format!( + "{}\n{}{}", + args, + offset.to_string(context.config), + output.trim_left() + )) + } +} + +fn type_bound_colon(context: &RewriteContext) -> &'static str { + colon_spaces( + context.config.space_before_colon(), + context.config.space_after_colon(), + ) +} + +impl Rewrite for ast::WherePredicate { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + // TODO: dead spans? + let result = match *self { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + ref bound_generic_params, + ref bounded_ty, + ref bounds, + .. + }) => { + let type_str = bounded_ty.rewrite(context, shape)?; + + let colon = type_bound_colon(context); + + if let Some(lifetime_str) = + rewrite_lifetime_param(context, shape, bound_generic_params) + { + // 6 = "for<> ".len() + let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; + let ty_shape = shape.offset_left(used_width)?; + let bounds = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect::>>()?; + let bounds_str = join_bounds(context, ty_shape, &bounds); + + if context.config.spaces_within_parens_and_brackets() + && !lifetime_str.is_empty() + { + format!( + "for< {} > {}{}{}", + lifetime_str, type_str, colon, bounds_str + ) + } else { + format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) + } + } else { + let used_width = type_str.len() + colon.len(); + let ty_shape = match context.config.indent_style() { + IndentStyle::Visual => shape.block_left(used_width)?, + IndentStyle::Block => shape, + }; + let bounds = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect::>>()?; + let overhead = type_str.len() + colon.len(); + let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); + + format!("{}{}{}", type_str, colon, bounds_str) + } + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + ref lifetime, + ref bounds, + .. + }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + ref lhs_ty, + ref rhs_ty, + .. + }) => { + let lhs_ty_str = lhs_ty.rewrite(context, shape)?; + // 3 = " = ".len() + let used_width = 3 + lhs_ty_str.len(); + let budget = shape.width.checked_sub(used_width)?; + let rhs_ty_str = + rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; + format!("{} = {}", lhs_ty_str, rhs_ty_str) + } + }; + + Some(result) + } +} + +impl Rewrite for ast::LifetimeDef { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) + } +} + +fn rewrite_bounded_lifetime<'b, I>( + lt: &ast::Lifetime, + bounds: I, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, +{ + let result = lt.rewrite(context, shape)?; + + if bounds.len() == 0 { + Some(result) + } else { + let appendix = bounds + .into_iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; + let colon = type_bound_colon(context); + let overhead = last_line_width(&result) + colon.len(); + let result = format!( + "{}{}{}", + result, + colon, + join_bounds(context, shape.sub_width(overhead)?, &appendix) + ); + Some(result) + } +} + +impl Rewrite for ast::TyParamBound { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { + tref.rewrite(context, shape) + } + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { + Some(format!( + "?{}", + tref.rewrite(context, shape.offset_left(1)?)? + )) + } + ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), + } + } +} + +impl Rewrite for ast::Lifetime { + fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { + Some(pprust::lifetime_to_string(self)) + } +} + +impl Rewrite for ast::TyParamBounds { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let strs = self.iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; + Some(join_bounds(context, shape, &strs)) + } +} + +impl Rewrite for ast::TyParam { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let mut result = String::with_capacity(128); + // FIXME: If there are more than one attributes, this will force multiline. + match self.attrs.rewrite(context, shape) { + Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), + _ => (), + } + result.push_str(&self.ident.to_string()); + if !self.bounds.is_empty() { + result.push_str(type_bound_colon(context)); + let strs = self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; + result.push_str(&join_bounds(context, shape, &strs)); + } + if let Some(ref def) = self.default { + let eq_str = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "=", + TypeDensity::Wide => " = ", + }; + result.push_str(eq_str); + let budget = shape.width.checked_sub(result.len())?; + let rewrite = def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; + result.push_str(&rewrite); + } + + Some(result) + } +} + +impl Rewrite for ast::PolyTraitRef { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + if let Some(lifetime_str) = + rewrite_lifetime_param(context, shape, &self.bound_generic_params) + { + // 6 is "for<> ".len() + let extra_offset = lifetime_str.len() + 6; + let path_str = self.trait_ref + .rewrite(context, shape.offset_left(extra_offset)?)?; + + Some( + if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }, + ) + } else { + self.trait_ref.rewrite(context, shape) + } + } +} + +impl Rewrite for ast::TraitRef { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_path(context, PathContext::Type, None, &self.path, shape) + } +} + +impl Rewrite for ast::Ty { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + ast::TyKind::TraitObject(ref bounds, ..) => bounds.rewrite(context, shape), + ast::TyKind::Ptr(ref mt) => { + let prefix = match mt.mutbl { + Mutability::Mutable => "*mut ", + Mutability::Immutable => "*const ", + }; + + rewrite_unary_prefix(context, prefix, &*mt.ty, shape) + } + ast::TyKind::Rptr(ref lifetime, ref mt) => { + let mut_str = format_mutability(mt.mutbl); + let mut_len = mut_str.len(); + Some(match *lifetime { + Some(ref lifetime) => { + let lt_budget = shape.width.checked_sub(2 + mut_len)?; + let lt_str = lifetime.rewrite( + context, + Shape::legacy(lt_budget, shape.indent + 2 + mut_len), + )?; + let lt_len = lt_str.len(); + let budget = shape.width.checked_sub(2 + mut_len + lt_len)?; + format!( + "&{} {}{}", + lt_str, + mut_str, + mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len) + )? + ) + } + None => { + let budget = shape.width.checked_sub(1 + mut_len)?; + format!( + "&{}{}", + mut_str, + mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 1 + mut_len) + )? + ) + } + }) + } + // FIXME: we drop any comments here, even though it's a silly place to put + // comments. + ast::TyKind::Paren(ref ty) => { + let budget = shape.width.checked_sub(2)?; + ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) + .map(|ty_str| { + if context.config.spaces_within_parens_and_brackets() { + format!("( {} )", ty_str) + } else { + format!("({})", ty_str) + } + }) + } + ast::TyKind::Slice(ref ty) => { + let budget = if context.config.spaces_within_parens_and_brackets() { + shape.width.checked_sub(4)? + } else { + shape.width.checked_sub(2)? + }; + ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) + .map(|ty_str| { + if context.config.spaces_within_parens_and_brackets() { + format!("[ {} ]", ty_str) + } else { + format!("[{}]", ty_str) + } + }) + } + ast::TyKind::Tup(ref items) => rewrite_tuple( + context, + &::utils::ptr_vec_to_ref_vec(items), + self.span, + shape, + ), + ast::TyKind::Path(ref q_self, ref path) => { + rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) + } + ast::TyKind::Array(ref ty, ref repeats) => { + let use_spaces = context.config.spaces_within_parens_and_brackets(); + let lbr = if use_spaces { "[ " } else { "[" }; + let rbr = if use_spaces { " ]" } else { "]" }; + rewrite_pair( + &**ty, + &**repeats, + PairParts::new(lbr, "; ", rbr), + context, + shape, + SeparatorPlace::Back, + ) + } + ast::TyKind::Infer => { + if shape.width >= 1 { + Some("_".to_owned()) + } else { + None + } + } + ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), + ast::TyKind::Never => Some(String::from("!")), + ast::TyKind::Mac(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + } + ast::TyKind::ImplicitSelf => Some(String::from("")), + ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) + .map(|it_str| format!("impl {}", it_str)), + ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), + } + } +} + +fn rewrite_bare_fn( + bare_fn: &ast::BareFnTy, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut result = String::with_capacity(128); + + if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params) + { + result.push_str("for<"); + // 6 = "for<> ".len(), 4 = "for<". + // This doesn't work out so nicely for mutliline situation with lots of + // rightward drift. If that is a problem, we could use the list stuff. + result.push_str(lifetime_str); + result.push_str("> "); + } + + result.push_str(::utils::format_unsafety(bare_fn.unsafety)); + + result.push_str(&format_abi( + bare_fn.abi, + context.config.force_explicit_abi(), + false, + )); + + result.push_str("fn"); + + let func_ty_shape = shape.offset_left(result.len())?; + + let rewrite = format_function_type( + bare_fn.decl.inputs.iter(), + &bare_fn.decl.output, + bare_fn.decl.variadic, + span, + context, + func_ty_shape, + )?; + + result.push_str(&rewrite); + + Some(result) +} + +pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { + // Try to join types in a single line + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let result = type_strs.join(joiner); + if result.contains('\n') || result.len() > shape.width { + let joiner_indent = shape.indent.block_indent(context.config); + let joiner = format!("\n{}+ ", joiner_indent.to_string(context.config)); + type_strs.join(&joiner) + } else { + result + } +} + +pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { + match ty.node { + ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, + ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { + can_be_overflowed_type(context, &*mutty.ty, len) + } + _ => false, + } +} + +/// Returns `None` if there is no `LifetimeDef` in the given generic parameters. +fn rewrite_lifetime_param( + context: &RewriteContext, + shape: Shape, + generic_params: &[ast::GenericParam], +) -> Option { + let result = generic_params + .iter() + .filter(|p| p.is_lifetime_param()) + .map(|lt| lt.rewrite(context, shape)) + .collect::>>()? + .join(", "); + if result.is_empty() { + None + } else { + Some(result) + } +} diff --git a/rustfmt-core/src/utils.rs b/rustfmt-core/src/utils.rs new file mode 100644 index 00000000000..d1bb7e26f5e --- /dev/null +++ b/rustfmt-core/src/utils.rs @@ -0,0 +1,404 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; + +use syntax::{abi, ptr}; +use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, + NestedMetaItemKind, Path, Visibility}; +use syntax::codemap::{BytePos, Span, NO_EXPANSION}; + +use config::Color; +use rewrite::RewriteContext; +use shape::Shape; + +// When we get scoped annotations, we should have rustfmt::skip. +const SKIP_ANNOTATION: &str = "rustfmt_skip"; + +// Computes the length of a string's last line, minus offset. +pub fn extra_offset(text: &str, shape: Shape) -> usize { + match text.rfind('\n') { + // 1 for newline character + Some(idx) => text.len() + .checked_sub(idx + 1 + shape.used_width()) + .unwrap_or(0), + None => text.len(), + } +} + +// Uses Cow to avoid allocating in the common cases. +pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { + match *vis { + Visibility::Public => Cow::from("pub "), + Visibility::Inherited => Cow::from(""), + Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "), + Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "), + Visibility::Restricted { ref path, .. } => { + let Path { ref segments, .. } = **path; + let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); + if path.is_global() { + segments_iter + .next() + .expect("Non-global path in pub(restricted)?"); + } + let is_keyword = |s: &str| s == "self" || s == "super"; + let path = segments_iter.collect::>().join("::"); + let in_str = if is_keyword(&path) { "" } else { "in " }; + + Cow::from(format!("pub({}{}) ", in_str, path)) + } + } +} + +#[inline] +pub fn format_constness(constness: ast::Constness) -> &'static str { + match constness { + ast::Constness::Const => "const ", + ast::Constness::NotConst => "", + } +} + +#[inline] +pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { + match defaultness { + ast::Defaultness::Default => "default ", + ast::Defaultness::Final => "", + } +} + +#[inline] +pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { + match unsafety { + ast::Unsafety::Unsafe => "unsafe ", + ast::Unsafety::Normal => "", + } +} + +#[inline] +pub fn format_mutability(mutability: ast::Mutability) -> &'static str { + match mutability { + ast::Mutability::Mutable => "mut ", + ast::Mutability::Immutable => "", + } +} + +#[inline] +pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { + if abi == abi::Abi::Rust && !is_mod { + Cow::from("") + } else if abi == abi::Abi::C && !explicit_abi { + Cow::from("extern ") + } else { + Cow::from(format!("extern {} ", abi)) + } +} + +#[inline] +// Transform `Vec>` into `Vec<&T>` +pub fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { + vec.iter().map(|x| &**x).collect::>() +} + +#[inline] +pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { + attrs + .iter() + .filter(|a| a.style == style) + .cloned() + .collect::>() +} + +#[inline] +pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Inner) +} + +#[inline] +pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Outer) +} + +#[inline] +pub fn last_line_contains_single_line_comment(s: &str) -> bool { + s.lines().last().map_or(false, |l| l.contains("//")) +} + +#[inline] +pub fn is_attributes_extendable(attrs_str: &str) -> bool { + !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) +} + +// The width of the first line in s. +#[inline] +pub fn first_line_width(s: &str) -> usize { + match s.find('\n') { + Some(n) => n, + None => s.len(), + } +} + +// The width of the last line in s. +#[inline] +pub fn last_line_width(s: &str) -> usize { + match s.rfind('\n') { + Some(n) => s.len() - n - 1, + None => s.len(), + } +} + +// The total used width of the last line. +#[inline] +pub fn last_line_used_width(s: &str, offset: usize) -> usize { + if s.contains('\n') { + last_line_width(s) + } else { + offset + s.len() + } +} + +#[inline] +pub fn trimmed_last_line_width(s: &str) -> usize { + match s.rfind('\n') { + Some(n) => s[(n + 1)..].trim().len(), + None => s.trim().len(), + } +} + +#[inline] +pub fn last_line_extendable(s: &str) -> bool { + if s.ends_with("\"#") { + return true; + } + for c in s.chars().rev() { + match c { + '(' | ')' | ']' | '}' | '?' | '>' => continue, + '\n' => break, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + true +} + +#[inline] +fn is_skip(meta_item: &MetaItem) -> bool { + match meta_item.node { + MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION, + MetaItemKind::List(ref l) => { + meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + } + _ => false, + } +} + +#[inline] +fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { + match meta_item.node { + NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi), + NestedMetaItemKind::Literal(_) => false, + } +} + +#[inline] +pub fn contains_skip(attrs: &[Attribute]) -> bool { + attrs + .iter() + .any(|a| a.meta().map_or(false, |a| is_skip(&a))) +} + +#[inline] +pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { + context.config.trailing_semicolon() + } + _ => false, + } +} + +#[inline] +pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::StmtKind::Semi(ref expr) => match expr.node { + ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) => false, + ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { + context.config.trailing_semicolon() + } + _ => true, + }, + ast::StmtKind::Expr(..) => false, + _ => true, + } +} + +#[inline] +pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { + match stmt.node { + ast::StmtKind::Expr(ref expr) => Some(expr), + _ => None, + } +} + +#[inline] +pub fn count_newlines(input: &str) -> usize { + input.chars().filter(|&c| c == '\n').count() +} + +macro_rules! msg { + ($($arg:tt)*) => ( + match writeln!(&mut ::std::io::stderr(), $($arg)* ) { + Ok(_) => {}, + Err(x) => panic!("Unable to write to stderr: {}", x), + } + ) +} + +// For format_missing and last_pos, need to use the source callsite (if applicable). +// Required as generated code spans aren't guaranteed to follow on from the last span. +macro_rules! source { + ($this: ident, $sp: expr) => { + $sp.source_callsite() + }; +} + +pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { + Span::new(lo, hi, NO_EXPANSION) +} + +// Return true if the given span does not intersect with file lines. +macro_rules! out_of_file_lines_range { + ($self: ident, $span: expr) => { + !$self + .config + .file_lines() + .intersects(&$self.codemap.lookup_line_range($span)) + }; +} + +macro_rules! skip_out_of_file_lines_range { + ($self: ident, $span: expr) => { + if out_of_file_lines_range!($self, $span) { + return None; + } + }; +} + +macro_rules! skip_out_of_file_lines_range_visitor { + ($self: ident, $span: expr) => { + if out_of_file_lines_range!($self, $span) { + $self.push_rewrite($span, None); + return; + } + }; +} + +// Wraps String in an Option. Returns Some when the string adheres to the +// Rewrite constraints defined for the Rewrite trait and else otherwise. +pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { + if is_valid_str(&s, max_width, shape) { + Some(s) + } else { + None + } +} + +fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { + if !snippet.is_empty() { + // First line must fits with `shape.width`. + if first_line_width(snippet) > shape.width { + return false; + } + // If the snippet does not include newline, we are done. + if first_line_width(snippet) == snippet.len() { + return true; + } + // The other lines must fit within the maximum width. + if snippet.lines().skip(1).any(|line| line.len() > max_width) { + return false; + } + // A special check for the last line, since the caller may + // place trailing characters on this line. + if last_line_width(snippet) > shape.used_width() + shape.width { + return false; + } + } + true +} + +#[inline] +pub fn colon_spaces(before: bool, after: bool) -> &'static str { + match (before, after) { + (true, true) => " : ", + (true, false) => " :", + (false, true) => ": ", + (false, false) => ":", + } +} + +#[inline] +pub fn paren_overhead(context: &RewriteContext) -> usize { + if context.config.spaces_within_parens_and_brackets() { + 4 + } else { + 2 + } +} + +pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { + match e.node { + ast::ExprKind::InPlace(ref e, _) + | ast::ExprKind::Call(ref e, _) + | ast::ExprKind::Binary(_, ref e, _) + | ast::ExprKind::Cast(ref e, _) + | ast::ExprKind::Type(ref e, _) + | ast::ExprKind::Assign(ref e, _) + | ast::ExprKind::AssignOp(_, ref e, _) + | ast::ExprKind::Field(ref e, _) + | ast::ExprKind::TupField(ref e, _) + | ast::ExprKind::Index(ref e, _) + | ast::ExprKind::Range(Some(ref e), _, _) + | ast::ExprKind::Try(ref e) => left_most_sub_expr(e), + _ => e, + } +} + +// isatty shamelessly adapted from cargo. +#[cfg(unix)] +pub fn isatty() -> bool { + extern crate libc; + + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +pub fn isatty() -> bool { + extern crate kernel32; + extern crate winapi; + + unsafe { + let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); + let mut out = 0; + kernel32::GetConsoleMode(handle, &mut out) != 0 + } +} + +pub fn use_colored_tty(color: Color) -> bool { + match color { + Color::Always => true, + Color::Never => false, + Color::Auto => isatty(), + } +} + +pub fn starts_with_newline(s: &str) -> bool { + s.starts_with('\n') || s.starts_with("\r\n") +} diff --git a/rustfmt-core/src/vertical.rs b/rustfmt-core/src/vertical.rs new file mode 100644 index 00000000000..e7fc03d41b1 --- /dev/null +++ b/rustfmt-core/src/vertical.rs @@ -0,0 +1,290 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format with vertical alignment. + +use std::cmp; + +use config::lists::*; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; + +use codemap::SpanUtils; +use comment::{combine_strs_with_missing_comments, contains_comment}; +use expr::rewrite_field; +use items::{rewrite_struct_field, rewrite_struct_field_prefix}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use utils::{contains_skip, is_attributes_extendable, mk_sp}; + +pub trait AlignedItem { + fn skip(&self) -> bool; + fn get_span(&self) -> Span; + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option; + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option; +} + +impl AlignedItem for ast::StructField { + fn skip(&self) -> bool { + contains_skip(&self.attrs) + } + + fn get_span(&self) -> Span { + self.span() + } + + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = self.attrs.rewrite(context, shape)?; + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo(), self.span.lo()) + } else { + mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) + }; + let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str); + rewrite_struct_field_prefix(context, self).and_then(|field_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &field_str, + missing_span, + shape, + attrs_extendable, + ) + }) + } + + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option { + rewrite_struct_field(context, self, shape, prefix_max_width) + } +} + +impl AlignedItem for ast::Field { + fn skip(&self) -> bool { + contains_skip(&self.attrs) + } + + fn get_span(&self) -> Span { + self.span() + } + + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = self.attrs.rewrite(context, shape)?; + let name = &self.ident.node.to_string(); + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo(), self.span.lo()) + } else { + mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + name, + missing_span, + shape, + is_attributes_extendable(&attrs_str), + ) + } + + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option { + rewrite_field(context, self, shape, prefix_max_width) + } +} + +pub fn rewrite_with_alignment( + fields: &[T], + context: &RewriteContext, + shape: Shape, + span: Span, + one_line_width: usize, +) -> Option { + let (spaces, group_index) = if context.config.struct_field_align_threshold() > 0 { + group_aligned_items(context, fields) + } else { + ("", fields.len() - 1) + }; + let init = &fields[0..group_index + 1]; + let rest = &fields[group_index + 1..]; + let init_last_pos = if rest.is_empty() { + span.hi() + } else { + // Decide whether the missing comments should stick to init or rest. + let init_hi = init[init.len() - 1].get_span().hi(); + let rest_lo = rest[0].get_span().lo(); + let missing_span = mk_sp(init_hi, rest_lo); + let missing_span = mk_sp( + context.codemap.span_after(missing_span, ","), + missing_span.hi(), + ); + + let snippet = context.snippet(missing_span); + if snippet.trim_left().starts_with("//") { + let offset = snippet.lines().next().map_or(0, |l| l.len()); + // 2 = "," + "\n" + init_hi + BytePos(offset as u32 + 2) + } else if snippet.trim_left().starts_with("/*") { + let comment_lines = snippet + .lines() + .position(|line| line.trim_right().ends_with("*/")) + .unwrap_or(0); + + let offset = snippet + .lines() + .take(comment_lines + 1) + .collect::>() + .join("\n") + .len(); + + init_hi + BytePos(offset as u32 + 2) + } else { + missing_span.lo() + } + }; + let init_span = mk_sp(span.lo(), init_last_pos); + let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; + let result = + rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?; + if rest.is_empty() { + Some(result + spaces) + } else { + let rest_span = mk_sp(init_last_pos, span.hi()); + let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; + Some( + result + spaces + "\n" + + &shape + .indent + .block_indent(context.config) + .to_string(context.config) + &rest_str, + ) + } +} + +fn struct_field_prefix_max_min_width( + context: &RewriteContext, + fields: &[T], + shape: Shape, +) -> (usize, usize) { + fields + .iter() + .map(|field| { + field.rewrite_prefix(context, shape).and_then(|field_str| { + if field_str.contains('\n') { + None + } else { + Some(field_str.len()) + } + }) + }) + .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { + (Some((max_len, min_len)), Some(len)) => { + Some((cmp::max(max_len, len), cmp::min(min_len, len))) + } + _ => None, + }) + .unwrap_or((0, 0)) +} + +fn rewrite_aligned_items_inner( + context: &RewriteContext, + fields: &[T], + span: Span, + offset: Indent, + one_line_width: usize, +) -> Option { + let item_indent = offset.block_indent(context.config); + // 1 = "," + let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; + let (mut field_prefix_max_width, field_prefix_min_width) = + struct_field_prefix_max_min_width(context, fields, item_shape); + let max_diff = field_prefix_max_width + .checked_sub(field_prefix_min_width) + .unwrap_or(0); + if max_diff > context.config.struct_field_align_threshold() { + field_prefix_max_width = 0; + } + + let items = itemize_list( + context.codemap, + fields.iter(), + "}", + ",", + |field| field.get_span().lo(), + |field| field.get_span().hi(), + |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), + span.lo(), + span.hi(), + false, + ).collect::>(); + + let tactic = definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::Comma, + one_line_width, + ); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: context.config.trailing_comma(), + separator_place: SeparatorPlace::Back, + shape: item_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + write_list(&items, &fmt) +} + +fn group_aligned_items( + context: &RewriteContext, + fields: &[T], +) -> (&'static str, usize) { + let mut index = 0; + for i in 0..fields.len() - 1 { + if fields[i].skip() { + return ("", index); + } + // See if there are comments or empty lines between fields. + let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo()); + let snippet = context + .snippet(span) + .lines() + .skip(1) + .collect::>() + .join("\n"); + let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) { + "\n" + } else { + "" + }; + if contains_comment(&snippet) || snippet.lines().count() > 1 { + return (spacings, index); + } + index += 1; + } + ("", index) +} diff --git a/rustfmt-core/src/visitor.rs b/rustfmt-core/src/visitor.rs new file mode 100644 index 00000000000..0a0d59d0f02 --- /dev/null +++ b/rustfmt-core/src/visitor.rs @@ -0,0 +1,1113 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp; + +use config::lists::*; +use syntax::{ast, visit}; +use syntax::attr::{self, HasAttrs}; +use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; +use syntax::parse::ParseSess; + +use codemap::{LineRangeUtils, SpanUtils}; +use comment::{combine_strs_with_missing_comments, contains_comment, CodeCharKind, + CommentCodeSlices, FindUncommented}; +use comment::rewrite_comment; +use config::{BraceStyle, Config}; +use expr::rewrite_literal; +use items::{format_impl, format_trait, format_trait_alias, rewrite_associated_impl_type, + rewrite_associated_type, rewrite_type_alias, FnSig, StaticParts, StructParts}; +use lists::{itemize_list, write_list, ListFormatting}; +use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; +use regex::Regex; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; + +/// Returns attributes that are within `outer_span`. +pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { + attrs + .iter() + .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) + .cloned() + .collect() +} + +/// Returns true for `mod foo;`, false for `mod foo { .. }`. +fn is_mod_decl(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), + _ => false, + } +} + +fn contains_macro_use_attr(attrs: &[ast::Attribute], span: Span) -> bool { + attr::contains_name(&filter_inline_attrs(attrs, span), "macro_use") +} + +/// Returns true for `mod foo;` without any inline attributes. +/// We cannot reorder modules with attributes because doing so can break the code. +/// e.g. `#[macro_use]`. +fn is_mod_decl_without_attr(item: &ast::Item) -> bool { + is_mod_decl(item) && !contains_macro_use_attr(&item.attrs, item.span()) +} + +fn is_use_item(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Use(_) => true, + _ => false, + } +} + +fn is_use_item_without_attr(item: &ast::Item) -> bool { + is_use_item(item) && !contains_macro_use_attr(&item.attrs, item.span()) +} + +fn is_extern_crate(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::ExternCrate(..) => true, + _ => false, + } +} + +fn is_extern_crate_without_attr(item: &ast::Item) -> bool { + is_extern_crate(item) && !contains_macro_use_attr(&item.attrs, item.span()) +} + +/// Creates a string slice corresponding to the specified span. +pub struct SnippetProvider<'a> { + /// A pointer to the content of the file we are formatting. + big_snippet: &'a str, + /// A position of the start of `big_snippet`, used as an offset. + start_pos: usize, +} + +impl<'a> SnippetProvider<'a> { + pub fn span_to_snippet(&self, span: Span) -> Option<&str> { + let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; + let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; + Some(&self.big_snippet[start_index..end_index]) + } + + pub fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { + let start_pos = start_pos.to_usize(); + SnippetProvider { + big_snippet, + start_pos, + } + } +} + +pub struct FmtVisitor<'a> { + pub parse_session: &'a ParseSess, + pub codemap: &'a CodeMap, + pub buffer: String, + pub last_pos: BytePos, + // FIXME: use an RAII util or closure for indenting + pub block_indent: Indent, + pub config: &'a Config, + pub is_if_else_block: bool, + pub snippet_provider: &'a SnippetProvider<'a>, + pub line_number: usize, + pub skipped_range: Vec<(usize, usize)>, +} + +impl<'b, 'a: 'b> FmtVisitor<'a> { + pub fn shape(&self) -> Shape { + Shape::indented(self.block_indent, self.config) + } + + fn visit_stmt(&mut self, stmt: &ast::Stmt) { + debug!( + "visit_stmt: {:?} {:?}", + self.codemap.lookup_char_pos(stmt.span.lo()), + self.codemap.lookup_char_pos(stmt.span.hi()) + ); + + match stmt.node { + ast::StmtKind::Item(ref item) => { + self.visit_item(item); + } + ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + if contains_skip(get_attrs_from_stmt(stmt)) { + self.push_skipped_with_span(stmt.span()); + } else { + let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(stmt.span(), rewrite) + } + } + ast::StmtKind::Mac(ref mac) => { + let (ref mac, _macro_style, ref attrs) = **mac; + if self.visit_attrs(attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(stmt.span()); + } else { + self.visit_mac(mac, None, MacroPosition::Statement); + } + self.format_missing(stmt.span.hi()); + } + } + } + + pub fn visit_block( + &mut self, + b: &ast::Block, + inner_attrs: Option<&[ast::Attribute]>, + has_braces: bool, + ) { + debug!( + "visit_block: {:?} {:?}", + self.codemap.lookup_char_pos(b.span.lo()), + self.codemap.lookup_char_pos(b.span.hi()) + ); + + // Check if this block has braces. + let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); + + self.last_pos = self.last_pos + brace_compensation; + self.block_indent = self.block_indent.block_indent(self.config); + self.push_str("{"); + + if self.config.remove_blank_lines_at_start_or_end_of_block() { + if let Some(first_stmt) = b.stmts.first() { + let attr_lo = inner_attrs + .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) + .or_else(|| { + // Attributes for an item in a statement position + // do not belong to the statement. (rust-lang/rust#34459) + if let ast::StmtKind::Item(ref item) = first_stmt.node { + item.attrs.first() + } else { + first_stmt.attrs().first() + }.and_then(|attr| { + // Some stmts can have embedded attributes. + // e.g. `match { #![attr] ... }` + let attr_lo = attr.span.lo(); + if attr_lo < first_stmt.span.lo() { + Some(attr_lo) + } else { + None + } + }) + }); + + let snippet = self.snippet(mk_sp( + self.last_pos, + attr_lo.unwrap_or(first_stmt.span.lo()), + )); + let len = CommentCodeSlices::new(snippet) + .nth(0) + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal { + s.rfind('\n') + } else { + None + } + }); + if let Some(len) = len { + self.last_pos = self.last_pos + BytePos::from_usize(len); + } + } + } + + // Format inner attributes if available. + let skip_rewrite = if let Some(attrs) = inner_attrs { + self.visit_attrs(attrs, ast::AttrStyle::Inner) + } else { + false + }; + + if skip_rewrite { + self.push_rewrite(b.span, None); + self.close_block(false); + self.last_pos = source!(self, b.span).hi(); + return; + } + + self.walk_block_stmts(b); + + if !b.stmts.is_empty() { + if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { + if utils::semicolon_for_expr(&self.get_context(), expr) { + self.push_str(";"); + } + } + } + + let mut remove_len = BytePos(0); + if self.config.remove_blank_lines_at_start_or_end_of_block() { + if let Some(stmt) = b.stmts.last() { + let snippet = self.snippet(mk_sp( + stmt.span.hi(), + source!(self, b.span).hi() - brace_compensation, + )); + let len = CommentCodeSlices::new(snippet) + .last() + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal && s.trim().is_empty() { + Some(s.len()) + } else { + None + } + }); + if let Some(len) = len { + remove_len = BytePos::from_usize(len); + } + } + } + + let unindent_comment = (self.is_if_else_block && !b.stmts.is_empty()) && { + let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; + let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); + snippet.contains("//") || snippet.contains("/*") + }; + // FIXME: we should compress any newlines here to just one + if unindent_comment { + self.block_indent = self.block_indent.block_unindent(self.config); + } + self.format_missing_with_indent( + source!(self, b.span).hi() - brace_compensation - remove_len, + ); + if unindent_comment { + self.block_indent = self.block_indent.block_indent(self.config); + } + self.close_block(unindent_comment); + self.last_pos = source!(self, b.span).hi(); + } + + // FIXME: this is a terrible hack to indent the comments between the last + // item in the block and the closing brace to the block's level. + // The closing brace itself, however, should be indented at a shallower + // level. + fn close_block(&mut self, unindent_comment: bool) { + let total_len = self.buffer.len(); + let chars_too_many = if unindent_comment { + 0 + } else if self.config.hard_tabs() { + 1 + } else { + self.config.tab_spaces() + }; + self.buffer.truncate(total_len - chars_too_many); + self.push_str("}"); + self.block_indent = self.block_indent.block_unindent(self.config); + } + + // Note that this only gets called for function definitions. Required methods + // on traits do not get handled here. + fn visit_fn( + &mut self, + fk: visit::FnKind, + generics: &ast::Generics, + fd: &ast::FnDecl, + s: Span, + defaultness: ast::Defaultness, + inner_attrs: Option<&[ast::Attribute]>, + ) { + let indent = self.block_indent; + let block; + let rewrite = match fk { + visit::FnKind::ItemFn(ident, _, _, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { + block = b; + self.rewrite_fn( + indent, + ident, + &FnSig::from_fn_kind(&fk, generics, fd, defaultness), + mk_sp(s.lo(), b.span.lo()), + b, + ) + } + visit::FnKind::Closure(_) => unreachable!(), + }; + + if let Some(fn_str) = rewrite { + self.format_missing_with_indent(source!(self, s).lo()); + self.push_str(&fn_str); + if let Some(c) = fn_str.chars().last() { + if c == '}' { + self.last_pos = source!(self, block.span).hi(); + return; + } + } + } else { + self.format_missing(source!(self, block.span).lo()); + } + + self.last_pos = source!(self, block.span).lo(); + self.visit_block(block, inner_attrs, true) + } + + pub fn visit_item(&mut self, item: &ast::Item) { + skip_out_of_file_lines_range_visitor!(self, item.span); + + // This is where we bail out if there is a skip attribute. This is only + // complex in the module case. It is complex because the module could be + // in a separate file and there might be attributes in both files, but + // the AST lumps them all together. + let filtered_attrs; + let mut attrs = &item.attrs; + match item.node { + // Module is inline, in this case we treat it like any other item. + _ if !is_mod_decl(item) => { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(item.span()); + return; + } + } + // Module is not inline, but should be skipped. + ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => { + return; + } + // Module is not inline and should not be skipped. We want + // to process only the attributes in the current file. + ast::ItemKind::Mod(..) => { + filtered_attrs = filter_inline_attrs(&item.attrs, item.span()); + // Assert because if we should skip it should be caught by + // the above case. + assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); + attrs = &filtered_attrs; + } + _ => { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(item.span()); + return; + } + } + } + + match item.node { + ast::ItemKind::Use(ref tree) => self.format_import(item, tree), + ast::ItemKind::Impl(..) => { + let snippet = self.snippet(item.span); + let where_span_end = snippet + .find_uncommented("{") + .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); + let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::Trait(..) => { + let rw = format_trait(&self.get_context(), item, self.block_indent); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::TraitAlias(ref generics, ref ty_param_bounds) => { + let shape = Shape::indented(self.block_indent, self.config); + let rw = format_trait_alias( + &self.get_context(), + item.ident, + generics, + ty_param_bounds, + shape, + ); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::ExternCrate(_) => { + let rw = rewrite_extern_crate(&self.get_context(), item); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { + self.visit_struct(&StructParts::from_item(item)); + } + ast::ItemKind::Enum(ref def, ref generics) => { + self.format_missing_with_indent(source!(self, item.span).lo()); + self.visit_enum(item.ident, &item.vis, def, generics, item.span); + self.last_pos = source!(self, item.span).hi(); + } + ast::ItemKind::Mod(ref module) => { + let is_inline = !is_mod_decl(item); + self.format_missing_with_indent(source!(self, item.span).lo()); + self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); + } + ast::ItemKind::Mac(ref mac) => { + self.visit_mac(mac, Some(item.ident), MacroPosition::Item); + } + ast::ItemKind::ForeignMod(ref foreign_mod) => { + self.format_missing_with_indent(source!(self, item.span).lo()); + self.format_foreign_mod(foreign_mod, item.span); + } + ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { + self.visit_static(&StaticParts::from_item(item)); + } + ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { + self.visit_fn( + visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), + generics, + decl, + item.span, + ast::Defaultness::Final, + Some(&item.attrs), + ) + } + ast::ItemKind::Ty(ref ty, ref generics) => { + let rewrite = rewrite_type_alias( + &self.get_context(), + self.block_indent, + item.ident, + ty, + generics, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + ast::ItemKind::GlobalAsm(..) => { + let snippet = Some(self.snippet(item.span).to_owned()); + self.push_rewrite(item.span, snippet); + } + ast::ItemKind::MacroDef(ref def) => { + let rewrite = rewrite_macro_def( + &self.get_context(), + self.shape(), + self.block_indent, + def, + item.ident, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + } + } + + pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + skip_out_of_file_lines_range_visitor!(self, ti.span); + + if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(ti.span()); + return; + } + + match ti.node { + ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), + ast::TraitItemKind::Method(ref sig, None) => { + let indent = self.block_indent; + let rewrite = + self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); + self.push_rewrite(ti.span, rewrite); + } + ast::TraitItemKind::Method(ref sig, Some(ref body)) => { + self.visit_fn( + visit::FnKind::Method(ti.ident, sig, None, body), + &ti.generics, + &sig.decl, + ti.span, + ast::Defaultness::Final, + Some(&ti.attrs), + ); + } + ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { + let rewrite = rewrite_associated_type( + ti.ident, + type_default.as_ref(), + Some(type_param_bounds), + &self.get_context(), + self.block_indent, + ); + self.push_rewrite(ti.span, rewrite); + } + ast::TraitItemKind::Macro(ref mac) => { + self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); + } + } + } + + pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + skip_out_of_file_lines_range_visitor!(self, ii.span); + + if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(ii.span()); + return; + } + + match ii.node { + ast::ImplItemKind::Method(ref sig, ref body) => { + self.visit_fn( + visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), + &ii.generics, + &sig.decl, + ii.span, + ii.defaultness, + Some(&ii.attrs), + ); + } + ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), + ast::ImplItemKind::Type(ref ty) => { + let rewrite = rewrite_associated_impl_type( + ii.ident, + ii.defaultness, + Some(ty), + None, + &self.get_context(), + self.block_indent, + ); + self.push_rewrite(ii.span, rewrite); + } + ast::ImplItemKind::Macro(ref mac) => { + self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); + } + } + } + + fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { + skip_out_of_file_lines_range_visitor!(self, mac.span); + + // 1 = ; + let shape = self.shape().sub_width(1).unwrap(); + let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); + self.push_rewrite(mac.span, rewrite); + } + + pub fn push_str(&mut self, s: &str) { + self.line_number += count_newlines(s); + self.buffer.push_str(s); + } + + fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { + if let Some(ref s) = rewrite { + self.push_str(s); + } else { + let snippet = self.snippet(span); + self.push_str(snippet); + } + self.last_pos = source!(self, span).hi(); + } + + pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { + self.format_missing_with_indent(source!(self, span).lo()); + self.push_rewrite_inner(span, rewrite); + } + + pub fn push_skipped_with_span(&mut self, span: Span) { + self.format_missing_with_indent(source!(self, span).lo()); + let lo = self.line_number + 1; + self.push_rewrite_inner(span, None); + let hi = self.line_number + 1; + self.skipped_range.push((lo, hi)); + } + + pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { + FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) + } + + pub fn from_codemap( + parse_session: &'a ParseSess, + config: &'a Config, + snippet_provider: &'a SnippetProvider, + ) -> FmtVisitor<'a> { + FmtVisitor { + parse_session, + codemap: parse_session.codemap(), + buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), + last_pos: BytePos(0), + block_indent: Indent::empty(), + config, + is_if_else_block: false, + snippet_provider, + line_number: 0, + skipped_range: vec![], + } + } + + pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { + self.snippet_provider.span_to_snippet(span) + } + + pub fn snippet(&'b self, span: Span) -> &'a str { + self.opt_snippet(span).unwrap() + } + + // Returns true if we should skip the following item. + pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { + if contains_skip(attrs) { + return true; + } + + let attrs: Vec<_> = attrs.iter().filter(|a| a.style == style).cloned().collect(); + if attrs.is_empty() { + return false; + } + + let rewrite = attrs.rewrite(&self.get_context(), self.shape()); + let span = mk_sp(attrs[0].span.lo(), attrs[attrs.len() - 1].span.hi()); + self.push_rewrite(span, rewrite); + + false + } + + fn reorder_items(&mut self, items_left: &[&ast::Item], is_item: &F, in_group: bool) -> usize + where + F: Fn(&ast::Item) -> bool, + { + let mut last = self.codemap.lookup_line_range(items_left[0].span()); + let item_length = items_left + .iter() + .take_while(|ppi| { + is_item(&***ppi) && (!in_group || { + let current = self.codemap.lookup_line_range(ppi.span()); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) + }) + .count(); + let items = &items_left[..item_length]; + + let at_least_one_in_file_lines = items + .iter() + .any(|item| !out_of_file_lines_range!(self, item.span)); + + if at_least_one_in_file_lines { + self.format_imports(items); + } else { + for item in items { + self.push_rewrite(item.span, None); + } + } + + item_length + } + + fn walk_items(&mut self, mut items_left: &[&ast::Item]) { + macro try_reorder_items_with($reorder: ident, $in_group: ident, $pred: ident) { + if self.config.$reorder() && $pred(&*items_left[0]) { + let used_items_len = + self.reorder_items(items_left, &$pred, self.config.$in_group()); + let (_, rest) = items_left.split_at(used_items_len); + items_left = rest; + continue; + } + } + + while !items_left.is_empty() { + // If the next item is a `use`, `extern crate` or `mod`, then extract it and any + // subsequent items that have the same item kind to be reordered within + // `format_imports`. Otherwise, just format the next item for output. + { + try_reorder_items_with!( + reorder_imports, + reorder_imports_in_group, + is_use_item_without_attr + ); + try_reorder_items_with!( + reorder_extern_crates, + reorder_extern_crates_in_group, + is_extern_crate_without_attr + ); + try_reorder_items_with!(reorder_modules, reorder_modules, is_mod_decl_without_attr); + } + // Reaching here means items were not reordered. There must be at least + // one item left in `items_left`, so calling `unwrap()` here is safe. + let (item, rest) = items_left.split_first().unwrap(); + self.visit_item(item); + items_left = rest; + } + } + + fn walk_mod_items(&mut self, m: &ast::Mod) { + self.walk_items(&ptr_vec_to_ref_vec(&m.items)); + } + + fn walk_stmts(&mut self, stmts: &[ast::Stmt]) { + fn to_stmt_item(stmt: &ast::Stmt) -> Option<&ast::Item> { + match stmt.node { + ast::StmtKind::Item(ref item) => Some(&**item), + _ => None, + } + } + + if stmts.is_empty() { + return; + } + + // Extract leading `use ...;`. + let items: Vec<_> = stmts + .iter() + .take_while(|stmt| to_stmt_item(stmt).map_or(false, is_use_item)) + .filter_map(|stmt| to_stmt_item(stmt)) + .collect(); + + if items.is_empty() { + self.visit_stmt(&stmts[0]); + self.walk_stmts(&stmts[1..]); + } else { + self.walk_items(&items); + self.walk_stmts(&stmts[items.len()..]); + } + } + + fn walk_block_stmts(&mut self, b: &ast::Block) { + self.walk_stmts(&b.stmts) + } + + fn format_mod( + &mut self, + m: &ast::Mod, + vis: &ast::Visibility, + s: Span, + ident: ast::Ident, + attrs: &[ast::Attribute], + is_internal: bool, + ) { + self.push_str(&*utils::format_visibility(vis)); + self.push_str("mod "); + self.push_str(&ident.to_string()); + + if is_internal { + match self.config.brace_style() { + BraceStyle::AlwaysNextLine => { + let sep_str = format!("\n{}{{", self.block_indent.to_string(self.config)); + self.push_str(&sep_str); + } + _ => self.push_str(" {"), + } + // Hackery to account for the closing }. + let mod_lo = self.codemap.span_after(source!(self, s), "{"); + let body_snippet = + self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); + let body_snippet = body_snippet.trim(); + if body_snippet.is_empty() { + self.push_str("}"); + } else { + self.last_pos = mod_lo; + self.block_indent = self.block_indent.block_indent(self.config); + self.visit_attrs(attrs, ast::AttrStyle::Inner); + self.walk_mod_items(m); + self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); + self.close_block(false); + } + self.last_pos = source!(self, m.inner).hi(); + } else { + self.push_str(";"); + self.last_pos = source!(self, s).hi(); + } + } + + pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { + self.block_indent = Indent::empty(); + self.walk_mod_items(m); + self.format_missing_with_indent(filemap.end_pos); + } + + pub fn skip_empty_lines(&mut self, end_pos: BytePos) { + while let Some(pos) = self.codemap + .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") + { + if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { + if snippet.trim().is_empty() { + self.last_pos = pos; + } else { + return; + } + } + } + } + + pub fn get_context(&self) -> RewriteContext { + RewriteContext { + parse_session: self.parse_session, + codemap: self.codemap, + config: self.config, + inside_macro: false, + use_block: false, + is_if_else_block: false, + force_one_line_chain: false, + snippet_provider: self.snippet_provider, + } + } +} + +impl Rewrite for ast::NestedMetaItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), + ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), + } + } +} + +impl Rewrite for ast::MetaItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + Some(match self.node { + ast::MetaItemKind::Word => String::from(&*self.name.as_str()), + ast::MetaItemKind::List(ref list) => { + let name = self.name.as_str(); + // 1 = `(`, 2 = `]` and `)` + let item_shape = shape + .visual_indent(0) + .shrink_left(name.len() + 1) + .and_then(|s| s.sub_width(2))?; + let items = itemize_list( + context.codemap, + list.iter(), + ")", + ",", + |nested_meta_item| nested_meta_item.span.lo(), + |nested_meta_item| nested_meta_item.span.hi(), + |nested_meta_item| nested_meta_item.rewrite(context, item_shape), + self.span.lo(), + self.span.hi(), + false, + ); + let item_vec = items.collect::>(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: item_shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + format!("{}({})", name, write_list(&item_vec, &fmt)?) + } + ast::MetaItemKind::NameValue(ref literal) => { + let name = self.name.as_str(); + // 3 = ` = ` + let lit_shape = shape.shrink_left(name.len() + 3)?; + let value = rewrite_literal(context, literal, lit_shape)?; + format!("{} = {}", name, value) + } + }) + } +} + +impl Rewrite for ast::Attribute { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let prefix = match self.style { + ast::AttrStyle::Inner => "#!", + ast::AttrStyle::Outer => "#", + }; + let snippet = context.snippet(self.span); + if self.is_sugared_doc { + let doc_shape = Shape { + width: cmp::min(shape.width, context.config.comment_width()) + .checked_sub(shape.indent.width()) + .unwrap_or(0), + ..shape + }; + rewrite_comment(snippet, false, doc_shape, context.config) + } else { + if contains_comment(snippet) { + return Some(snippet.to_owned()); + } + // 1 = `[` + let shape = shape.offset_left(prefix.len() + 1)?; + self.meta()? + .rewrite(context, shape) + .map(|rw| format!("{}[{}]", prefix, rw)) + } + } +} + +/// Returns the first group of attributes that fills the given predicate. +/// We consider two doc comments are in different group if they are separated by normal comments. +fn take_while_with_pred<'a, P>( + context: &RewriteContext, + attrs: &'a [ast::Attribute], + pred: P, +) -> &'a [ast::Attribute] +where + P: Fn(&ast::Attribute) -> bool, +{ + let mut last_index = 0; + let mut iter = attrs.iter().enumerate().peekable(); + while let Some((i, attr)) = iter.next() { + if !pred(attr) { + break; + } + if let Some(&(_, next_attr)) = iter.peek() { + // Extract comments between two attributes. + let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); + let snippet = context.snippet(span_between_attr); + if count_newlines(snippet) >= 2 || snippet.contains('/') { + break; + } + } + last_index = i; + } + if last_index == 0 { + &[] + } else { + &attrs[..last_index + 1] + } +} + +fn rewrite_first_group_attrs( + context: &RewriteContext, + attrs: &[ast::Attribute], + shape: Shape, +) -> Option<(usize, String)> { + if attrs.is_empty() { + return Some((0, String::new())); + } + // Rewrite doc comments + let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); + if !sugared_docs.is_empty() { + let snippet = sugared_docs + .iter() + .map(|a| context.snippet(a.span)) + .collect::>() + .join("\n"); + return Some(( + sugared_docs.len(), + rewrite_comment(&snippet, false, shape, context.config)?, + )); + } + // Rewrite `#[derive(..)]`s. + if context.config.merge_derives() { + let derives = take_while_with_pred(context, attrs, is_derive); + if !derives.is_empty() { + let mut derive_args = vec![]; + for derive in derives { + derive_args.append(&mut get_derive_args(context, derive)?); + } + return Some((derives.len(), format_derive(context, &derive_args, shape)?)); + } + } + // Rewrite the first attribute. + Some((1, attrs[0].rewrite(context, shape)?)) +} + +fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { + // Look at before and after comment and see if there are any empty lines. + let comment_begin = comment.chars().position(|c| c == '/'); + let len = comment_begin.unwrap_or_else(|| comment.len()); + let mlb = count_newlines(&comment[..len]) > 1; + let mla = if comment_begin.is_none() { + mlb + } else { + let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); + let len = comment_end.unwrap(); + comment + .chars() + .rev() + .take(len) + .filter(|c| *c == '\n') + .count() > 1 + }; + (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) +} + +impl<'a> Rewrite for [ast::Attribute] { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + if self.is_empty() { + return Some(String::new()); + } + let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?; + if self.len() == 1 || first_group_len == self.len() { + Some(first_group_str) + } else { + let rest_str = self[first_group_len..].rewrite(context, shape)?; + let missing_span = mk_sp( + self[first_group_len - 1].span.hi(), + self[first_group_len].span.lo(), + ); + // Preserve an empty line before/after doc comments. + if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { + let snippet = context.snippet(missing_span); + let (mla, mlb) = has_newlines_before_after_comment(snippet); + let comment = ::comment::recover_missing_comment_in_span( + missing_span, + shape.with_max_width(context.config), + context, + 0, + )?; + let comment = if comment.is_empty() { + format!("\n{}", mlb) + } else { + format!("{}{}\n{}", mla, comment, mlb) + }; + Some(format!( + "{}{}{}{}", + first_group_str, + comment, + shape.indent.to_string(context.config), + rest_str + )) + } else { + combine_strs_with_missing_comments( + context, + &first_group_str, + &rest_str, + missing_span, + shape, + false, + ) + } + } + } +} + +// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. +fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option { + let mut result = String::with_capacity(128); + result.push_str("#[derive("); + // 11 = `#[derive()]` + let initial_budget = shape.width.checked_sub(11)?; + let mut budget = initial_budget; + let num = derive_args.len(); + for (i, a) in derive_args.iter().enumerate() { + // 2 = `, ` or `)]` + let width = a.len() + 2; + if width > budget { + if i > 0 { + // Remove trailing whitespace. + result.pop(); + } + result.push('\n'); + // 9 = `#[derive(` + result.push_str(&(shape.indent + 9).to_string(context.config)); + budget = initial_budget; + } else { + budget = budget.checked_sub(width).unwrap_or(0); + } + result.push_str(a); + if i != num - 1 { + result.push_str(", ") + } + } + result.push_str(")]"); + Some(result) +} + +fn is_derive(attr: &ast::Attribute) -> bool { + attr.check_name("derive") +} + +/// Returns the arguments of `#[derive(...)]`. +fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { + attr.meta_item_list().map(|meta_item_list| { + meta_item_list + .iter() + .map(|nested_meta_item| context.snippet(nested_meta_item.span)) + .collect() + }) +} + +// Rewrite `extern crate foo;` WITHOUT attributes. +pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { + assert!(is_extern_crate(item)); + let new_str = context.snippet(item.span); + Some(if contains_comment(new_str) { + new_str.to_owned() + } else { + let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); + String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) + }) +} + +fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { + match stmt.node { + ast::StmtKind::Local(ref local) => &local.attrs, + ast::StmtKind::Item(ref item) => &item.attrs, + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, + ast::StmtKind::Mac(ref mac) => &mac.2, + } +} diff --git a/rustfmt-core/tests/config/disable_all_formatting.toml b/rustfmt-core/tests/config/disable_all_formatting.toml new file mode 100644 index 00000000000..c7ad93bafe3 --- /dev/null +++ b/rustfmt-core/tests/config/disable_all_formatting.toml @@ -0,0 +1 @@ +disable_all_formatting = true diff --git a/rustfmt-core/tests/config/issue-1111.toml b/rustfmt-core/tests/config/issue-1111.toml new file mode 100755 index 00000000000..44148a2d3c3 --- /dev/null +++ b/rustfmt-core/tests/config/issue-1111.toml @@ -0,0 +1 @@ +reorder_imports = true diff --git a/rustfmt-core/tests/config/small_tabs.toml b/rustfmt-core/tests/config/small_tabs.toml new file mode 100644 index 00000000000..d03ac281acb --- /dev/null +++ b/rustfmt-core/tests/config/small_tabs.toml @@ -0,0 +1,12 @@ +max_width = 100 +comment_width = 80 +tab_spaces = 2 +newline_style = "Unix" +brace_style = "SameLineWhere" +fn_args_density = "Tall" +trailing_comma = "Vertical" +indent_style = "Block" +report_todo = "Always" +report_fixme = "Never" +reorder_imports = false +format_strings = true diff --git a/rustfmt-core/tests/coverage/source/comments.rs b/rustfmt-core/tests/coverage/source/comments.rs new file mode 100644 index 00000000000..e79557af713 --- /dev/null +++ b/rustfmt-core/tests/coverage/source/comments.rs @@ -0,0 +1,7 @@ +// rustfmt-write_mode: coverage +/// Here's a doc comment! +fn main() { + // foo is bar + let foo = "bar"; + // loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment!!!!! +} diff --git a/rustfmt-core/tests/coverage/target/comments.rs b/rustfmt-core/tests/coverage/target/comments.rs new file mode 100644 index 00000000000..8f9c223aef2 --- /dev/null +++ b/rustfmt-core/tests/coverage/target/comments.rs @@ -0,0 +1,7 @@ +XX XXXXXXXXXXXXXXXXXXX XXXXXXXX +/// Here's a doc comment! +fn main() { + XX XXX XX XXX + let foo = "bar"; + XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX +} diff --git a/rustfmt-core/tests/lib.rs b/rustfmt-core/tests/lib.rs new file mode 100644 index 00000000000..be72cb8a9ef --- /dev/null +++ b/rustfmt-core/tests/lib.rs @@ -0,0 +1,818 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; +extern crate regex; +extern crate rustfmt_config as config; +extern crate rustfmt_core as rustfmt; +extern crate term; + +use std::collections::HashMap; +use std::fs; +use std::io::{self, BufRead, BufReader, Read}; +use std::iter::{Enumerate, Peekable}; +use std::path::{Path, PathBuf}; +use std::str::Chars; + +use rustfmt::*; +use config::{Color, Config, ReportTactic}; +use config::summary::Summary; +use config::file_lines::FileLines; +use rustfmt::filemap::write_system_newlines; +use rustfmt::rustfmt_diff::*; + +const DIFF_CONTEXT_SIZE: usize = 3; +const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; + +// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the +// given path. The `recursive` argument controls if files from subdirectories +// are also returned. +fn get_test_files(path: &Path, recursive: bool) -> Vec { + let mut files = vec![]; + if path.is_dir() { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read directory {}", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get DirEntry"); + let path = entry.path(); + if path.is_dir() && recursive { + files.append(&mut get_test_files(&path, recursive)); + } else if path.extension().map_or(false, |f| f == "rs") { + files.push(path); + } + } + } + files +} + +fn verify_config_used(path: &Path, config_name: &str) { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read {} directory", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.extension().map_or(false, |f| f == "rs") { + // check if "// rustfmt-:" appears in the file. + let filebuf = BufReader::new( + fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), + ); + assert!( + filebuf + .lines() + .map(|l| l.unwrap()) + .take_while(|l| l.starts_with("//")) + .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), + format!( + "config option file {} does not contain expected config name", + path.display() + ) + ); + } + } +} + +#[test] +fn verify_config_test_names() { + for path in &[ + Path::new("tests/source/configs"), + Path::new("tests/target/configs"), + ] { + for entry in fs::read_dir(path).expect("Couldn't read configs directory") { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.is_dir() { + let config_name = path.file_name().unwrap().to_str().unwrap(); + + // Make sure that config name is used in the files in the directory. + verify_config_used(&path, config_name); + } + } + } +} + +// This writes to the terminal using the same approach (via term::stdout or +// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing +// using only one or the other will cause the output order to differ when +// `print_diff` selects the approach not used. +fn write_message(msg: &str) { + let mut writer = OutputWriter::new(Color::Auto); + writer.writeln(&format!("{}", msg), None); +} + +// Integration tests. The files in the tests/source are formatted and compared +// to their equivalent in tests/target. The target file and config can be +// overridden by annotations in the source file. The input and output must match +// exactly. +#[test] +fn system_tests() { + // Get all files in the tests/source directory. + let files = get_test_files(Path::new("tests/source"), true); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} system tests.", count); + assert_eq!(fails, 0, "{} system tests failed", fails); +} + +// Do the same for tests/coverage-source directory +// the only difference is the coverage mode +#[test] +fn coverage_tests() { + let files = get_test_files(Path::new("tests/coverage/source"), true); + let (_reports, count, fails) = check_files(files); + + println!("Ran {} tests in coverage mode.", count); + assert_eq!(fails, 0, "{} tests failed", fails); +} + +#[test] +fn checkstyle_test() { + let filename = "tests/writemode/source/fn-single-line.rs"; + let expected_filename = "tests/writemode/target/checkstyle.xml"; + assert_output(Path::new(filename), Path::new(expected_filename)); +} + +// Helper function for comparing the results of rustfmt +// to a known output file generated by one of the write modes. +fn assert_output(source: &Path, expected_filename: &Path) { + let config = read_config(source); + let (_error_summary, file_map, _report) = format_file(source, &config); + + // Populate output by writing to a vec. + let mut out = vec![]; + let _ = filemap::write_all_files(&file_map, &mut out, &config); + let output = String::from_utf8(out).unwrap(); + + let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); + let mut expected_text = String::new(); + expected_file + .read_to_string(&mut expected_text) + .expect("Failed reading target"); + + let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + let mut failures = HashMap::new(); + failures.insert(source.to_owned(), compare); + print_mismatches_default_message(failures); + assert!(false, "Text does not match expected output"); + } +} + +// Idempotence tests. Files in tests/target are checked to be unaltered by +// rustfmt. +#[test] +fn idempotence_tests() { + // Get all files in the tests/target directory. + let files = get_test_files(Path::new("tests/target"), true); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} idempotent tests.", count); + assert_eq!(fails, 0, "{} idempotent tests failed", fails); +} + +// Run rustfmt on itself. This operation must be idempotent. We also check that +// no warnings are emitted. +#[test] +fn self_tests() { + let mut files = get_test_files(Path::new("tests"), false); + let bin_directories = vec![ + "cargo-fmt", + "git-rustfmt", + "rustfmt-bin", + "rustfmt-format-diff", + ]; + for dir in bin_directories { + let mut path = PathBuf::from(".."); + path.push(dir); + path.push("src/main.rs"); + files.push(path); + } + let lib_directories = vec!["rustfmt-core", "rustfmt-config"]; + for dir in lib_directories { + let mut path = PathBuf::from(".."); + path.push(dir); + path.push("src/lib.rs"); + files.push(path); + } + + let (reports, count, fails) = check_files(files); + let mut warnings = 0; + + // Display results. + println!("Ran {} self tests.", count); + assert_eq!(fails, 0, "{} self tests failed", fails); + + for format_report in reports { + println!("{}", format_report); + warnings += format_report.warning_count(); + } + + assert_eq!( + warnings, 0, + "Rustfmt's code generated {} warnings", + warnings + ); +} + +#[test] +fn stdin_formatting_smoke_test() { + let input = Input::Text("fn main () {}".to_owned()); + let config = Config::default(); + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_no_errors()); + for &(ref file_name, ref text) in &file_map { + if let FileName::Custom(ref file_name) = *file_name { + if file_name == "stdin" { + assert_eq!(text.to_string(), "fn main() {}\n"); + return; + } + } + } + panic!("no stdin"); +} + +// FIXME(#1990) restore this test +// #[test] +// fn stdin_disable_all_formatting_test() { +// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); +// let mut child = Command::new("./target/debug/rustfmt") +// .stdin(Stdio::piped()) +// .stdout(Stdio::piped()) +// .arg("--config-path=./tests/config/disable_all_formatting.toml") +// .spawn() +// .expect("failed to execute child"); + +// { +// let stdin = child.stdin.as_mut().expect("failed to get stdin"); +// stdin +// .write_all(input.as_bytes()) +// .expect("failed to write stdin"); +// } +// let output = child.wait_with_output().expect("failed to wait on child"); +// assert!(output.status.success()); +// assert!(output.stderr.is_empty()); +// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); +// } + +#[test] +fn format_lines_errors_are_reported() { + let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); + let input = Input::Text(format!("fn {}() {{}}", long_identifier)); + let config = Config::default(); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + +#[test] +fn format_lines_errors_are_reported_with_tabs() { + let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); + let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); + let config = Config::from_toml("hard_tabs = true").unwrap(); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + +// For each file, run rustfmt and collect the output. +// Returns the number of files checked and the number of failures. +fn check_files(files: Vec) -> (Vec, u32, u32) { + let mut count = 0; + let mut fails = 0; + let mut reports = vec![]; + + for file_name in files { + debug!("Testing '{}'...", file_name.display()); + + match idempotent_check(&file_name) { + Ok(ref report) if report.has_warnings() => { + print!("{}", report); + fails += 1; + } + Ok(report) => reports.push(report), + Err(err) => { + if let IdempotentCheckError::Mismatch(msg) = err { + print_mismatches_default_message(msg); + } + fails += 1; + } + } + + count += 1; + } + + (reports, count, fails) +} + +fn print_mismatches_default_message(result: HashMap>) { + let mut t = term::stdout().unwrap(); + for (file_name, diff) in result { + let mismatch_msg_formatter = + |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); + print_diff(diff, &mismatch_msg_formatter, Color::Auto); + } + + t.reset().unwrap(); +} + +fn print_mismatches String>( + result: HashMap>, + mismatch_msg_formatter: T, +) { + let mut t = term::stdout().unwrap(); + for (_file_name, diff) in result { + print_diff(diff, &mismatch_msg_formatter, Color::Auto); + } + + t.reset().unwrap(); +} + +fn read_config(filename: &Path) -> Config { + let sig_comments = read_significant_comments(filename); + // Look for a config file... If there is a 'config' property in the significant comments, use + // that. Otherwise, if there are no significant comments at all, look for a config file with + // the same name as the test file. + let mut config = if !sig_comments.is_empty() { + get_config(sig_comments.get("config").map(Path::new)) + } else { + get_config(filename.with_extension("toml").file_name().map(Path::new)) + }; + + for (key, val) in &sig_comments { + if key != "target" && key != "config" { + config.override_value(key, val); + } + } + + // Don't generate warnings for to-do items. + config.set().report_todo(ReportTactic::Never); + + config +} + +fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { + let filepath = filepath.into(); + let input = Input::File(filepath); + format_input::(input, config, None).unwrap() +} + +pub enum IdempotentCheckError { + Mismatch(HashMap>), + Parse, +} + +pub fn idempotent_check(filename: &PathBuf) -> Result { + let sig_comments = read_significant_comments(filename); + let config = read_config(filename); + let (error_summary, file_map, format_report) = format_file(filename, &config); + if error_summary.has_parsing_errors() { + return Err(IdempotentCheckError::Parse); + } + + let mut write_result = HashMap::new(); + for &(ref filename, ref text) in &file_map { + let mut v = Vec::new(); + // Won't panic, as we're not doing any IO. + write_system_newlines(&mut v, text, &config).unwrap(); + // Won't panic, we are writing correct utf8. + let one_result = String::from_utf8(v).unwrap(); + if let FileName::Real(ref filename) = *filename { + write_result.insert(filename.to_owned(), one_result); + } + } + + let target = sig_comments.get("target").map(|x| &(*x)[..]); + + handle_result(write_result, target).map(|_| format_report) +} + +// Reads test config file using the supplied (optional) file name. If there's no file name or the +// file doesn't exist, just return the default config. Otherwise, the file must be read +// successfully. +fn get_config(config_file: Option<&Path>) -> Config { + let config_file_name = match config_file { + None => return Default::default(), + Some(file_name) => { + let mut full_path = PathBuf::from("tests/config/"); + full_path.push(file_name); + if !full_path.exists() { + return Default::default(); + }; + full_path + } + }; + + let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); + let mut def_config = String::new(); + def_config_file + .read_to_string(&mut def_config) + .expect("Couldn't read config"); + + Config::from_toml(&def_config).expect("Invalid toml") +} + +// Reads significant comments of the form: // rustfmt-key: value +// into a hash map. +fn read_significant_comments(file_name: &Path) -> HashMap { + let file = + fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); + let reader = BufReader::new(file); + let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; + let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); + + // Matches lines containing significant comments or whitespace. + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") + .expect("Failed creating pattern 2"); + + reader + .lines() + .map(|line| line.expect("Failed getting line")) + .take_while(|line| line_regex.is_match(line)) + .filter_map(|line| { + regex.captures_iter(&line).next().map(|capture| { + ( + capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + ) + }) + }) + .collect() +} + +// Compare output to input. +// TODO: needs a better name, more explanation. +fn handle_result( + result: HashMap, + target: Option<&str>, +) -> Result<(), IdempotentCheckError> { + let mut failures = HashMap::new(); + + for (file_name, fmt_text) in result { + // If file is in tests/source, compare to file with same name in tests/target. + let target = get_target(&file_name, target); + let open_error = format!("Couldn't open target {:?}", &target); + let mut f = fs::File::open(&target).expect(&open_error); + + let mut text = String::new(); + let read_error = format!("Failed reading target {:?}", &target); + f.read_to_string(&mut text).expect(&read_error); + + // Ignore LF and CRLF difference for Windows. + if !string_eq_ignore_newline_repr(&fmt_text, &text) { + let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); + assert!( + !diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?" + ); + failures.insert(file_name, diff); + } + } + + if failures.is_empty() { + Ok(()) + } else { + Err(IdempotentCheckError::Mismatch(failures)) + } +} + +// Map source file paths to their target paths. +fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { + if let Some(n) = file_name + .components() + .position(|c| c.as_os_str() == "source") + { + let mut target_file_name = PathBuf::new(); + for (i, c) in file_name.components().enumerate() { + if i == n { + target_file_name.push("target"); + } else { + target_file_name.push(c.as_os_str()); + } + } + if let Some(replace_name) = target { + target_file_name.with_file_name(replace_name) + } else { + target_file_name + } + } else { + // This is either and idempotence check or a self check + file_name.to_owned() + } +} + +#[test] +fn rustfmt_diff_make_diff_tests() { + let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 1, + lines: vec![ + DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into()), + ], + }, + ] + ); +} + +#[test] +fn rustfmt_diff_no_diff_test() { + let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); + assert_eq!(diff, vec![]); +} + +// Compare strings without distinguishing between CRLF and LF +fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { + let left = CharsIgnoreNewlineRepr(left.chars().peekable()); + let right = CharsIgnoreNewlineRepr(right.chars().peekable()); + left.eq(right) +} + +struct CharsIgnoreNewlineRepr<'a>(Peekable>); + +impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { + type Item = char; + fn next(&mut self) -> Option { + self.0.next().map(|c| { + if c == '\r' { + if *self.0.peek().unwrap_or(&'\0') == '\n' { + self.0.next(); + '\n' + } else { + '\r' + } + } else { + c + } + }) + } +} + +#[test] +fn string_eq_ignore_newline_repr_test() { + assert!(string_eq_ignore_newline_repr("", "")); + assert!(!string_eq_ignore_newline_repr("", "abc")); + assert!(!string_eq_ignore_newline_repr("abc", "")); + assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); + assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); + assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); +} + +// This enum is used to represent one of three text features in Configurations.md: a block of code +// with its starting line number, the name of a rustfmt configuration option, or the value of a +// rustfmt configuration option. +enum ConfigurationSection { + CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) + ConfigName(String), + ConfigValue(String), +} + +impl ConfigurationSection { + fn get_section>( + file: &mut Enumerate, + ) -> Option { + lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#).expect("Failed creating configuration value pattern"); + } + + loop { + match file.next() { + Some((i, line)) => { + if line.starts_with("```rust") { + // Get the lines of the code block. + let lines: Vec = file.map(|(_i, l)| l) + .take_while(|l| !l.starts_with("```")) + .collect(); + let block = format!("{}\n", lines.join("\n")); + + // +1 to translate to one-based indexing + // +1 to get to first line of code (line after "```") + let start_line = (i + 2) as u32; + + return Some(ConfigurationSection::CodeBlock((block, start_line))); + } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); + } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); + } + } + None => return None, // reached the end of the file + } + } + } +} + +// This struct stores the information about code blocks in the configurations +// file, formats the code blocks, and prints formatting errors. +struct ConfigCodeBlock { + config_name: Option, + config_value: Option, + code_block: Option, + code_block_start: Option, +} + +impl ConfigCodeBlock { + fn new() -> ConfigCodeBlock { + ConfigCodeBlock { + config_name: None, + config_value: None, + code_block: None, + code_block_start: None, + } + } + + fn set_config_name(&mut self, name: Option) { + self.config_name = name; + self.config_value = None; + } + + fn set_config_value(&mut self, value: Option) { + self.config_value = value; + } + + fn set_code_block(&mut self, code_block: String, code_block_start: u32) { + self.code_block = Some(code_block); + self.code_block_start = Some(code_block_start); + } + + fn get_block_config(&self) -> Config { + let mut config = Config::default(); + config.override_value( + self.config_name.as_ref().unwrap(), + self.config_value.as_ref().unwrap(), + ); + config + } + + fn code_block_valid(&self) -> bool { + // We never expect to not have a code block. + assert!(self.code_block.is_some() && self.code_block_start.is_some()); + + if self.config_name.is_none() { + write_message(&format!( + "No configuration name for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + if self.config_value.is_none() { + write_message(&format!( + "No configuration value for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + true + } + + fn has_parsing_errors(&self, error_summary: Summary) -> bool { + if error_summary.has_parsing_errors() { + write_message(&format!( + "\u{261d}\u{1f3fd} Cannot format {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return true; + } + + false + } + + fn print_diff(&self, compare: Vec) { + let mut mismatches = HashMap::new(); + mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); + print_mismatches(mismatches, |line_num| { + format!( + "\nMismatch at {}:{}:", + CONFIGURATIONS_FILE_NAME, + line_num + self.code_block_start.unwrap() - 1 + ) + }); + } + + fn formatted_has_diff(&self, file_map: &FileMap) -> bool { + let &(ref _file_name, ref text) = file_map.first().unwrap(); + let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + self.print_diff(compare); + return true; + } + + false + } + + // Return a bool indicating if formatting this code block is an idempotent + // operation. This function also triggers printing any formatting failure + // messages. + fn formatted_is_idempotent(&self) -> bool { + // Verify that we have all of the expected information. + if !self.code_block_valid() { + return false; + } + + let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); + let config = self.get_block_config(); + + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + + !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) + } + + // Extract a code block from the iterator. Behavior: + // - Rust code blocks are identifed by lines beginning with "```rust". + // - One explicit configuration setting is supported per code block. + // - Rust code blocks with no configuration setting are illegal and cause an + // assertion failure. + // - Configuration names in Configurations.md must be in the form of + // "## `NAME`". + // - Configuration values in Configurations.md must be in the form of + // "#### `VALUE`". + fn extract>( + file: &mut Enumerate, + prev: Option<&ConfigCodeBlock>, + ) -> Option { + let mut code_block = ConfigCodeBlock::new(); + code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); + + loop { + match ConfigurationSection::get_section(file) { + Some(ConfigurationSection::CodeBlock((block, start_line))) => { + code_block.set_code_block(block, start_line); + break; + } + Some(ConfigurationSection::ConfigName(name)) => { + code_block.set_config_name(Some(name)); + } + Some(ConfigurationSection::ConfigValue(value)) => { + code_block.set_config_value(Some(value)); + } + None => return None, // end of file was reached + } + } + + Some(code_block) + } +} + +#[test] +#[ignore] +fn configuration_snippet_tests() { + // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one + // entry for each Rust code block found. + fn get_code_blocks() -> Vec { + let mut file_iter = BufReader::new( + fs::File::open(CONFIGURATIONS_FILE_NAME) + .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + ).lines() + .map(|l| l.unwrap()) + .enumerate(); + let mut code_blocks: Vec = Vec::new(); + + while let Some(cb) = ConfigCodeBlock::extract(&mut file_iter, code_blocks.last()) { + code_blocks.push(cb); + } + + code_blocks + } + + let blocks = get_code_blocks(); + let failures = blocks + .iter() + .map(|b| b.formatted_is_idempotent()) + .fold(0, |acc, r| acc + (!r as u32)); + + // Display results. + println!("Ran {} configurations tests.", blocks.len()); + assert_eq!(failures, 0, "{} configurations tests failed", failures); +} diff --git a/rustfmt-core/tests/source/assignment.rs b/rustfmt-core/tests/source/assignment.rs new file mode 100644 index 00000000000..d5860532086 --- /dev/null +++ b/rustfmt-core/tests/source/assignment.rs @@ -0,0 +1,30 @@ +// Test assignment + +fn main() { + let some_var : Type ; + + let mut mutable; + + let variable = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; + + variable = LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; + + let single_line_fit = + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + single_line_fit = 5;single_lit_fit >>= 10; +} + +fn break_meee() { + { + (block_start, block_size, margin_block_start, margin_block_end) = match (block_start, + block_end, + block_size) { + x => 1, + _ => 2, + }; + } +} + +// #2018 +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/rustfmt-core/tests/source/associated-types-bounds-wrapping.rs b/rustfmt-core/tests/source/associated-types-bounds-wrapping.rs new file mode 100644 index 00000000000..8f5e2172569 --- /dev/null +++ b/rustfmt-core/tests/source/associated-types-bounds-wrapping.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 100 +// Test proper wrapping of long associated type bounds + +pub trait HttpService { + type WsService: 'static + Service; +} diff --git a/rustfmt-core/tests/source/attrib.rs b/rustfmt-core/tests/source/attrib.rs new file mode 100644 index 00000000000..6653dd2daa9 --- /dev/null +++ b/rustfmt-core/tests/source/attrib.rs @@ -0,0 +1,152 @@ +// rustfmt-wrap_comments: true +// Test attributes and doc comments are preserved. + +//! Doc comment + +#![attribute] + +//! Crate doc comment + +// Comment + +// Comment on attribute +#![the(attribute)] + +// Another comment + +#[invalid attribute] +fn foo() {} + +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. + +/// Blah blah blah. +impl Bar { + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + #[an_attribute] + fn foo(&mut self) -> isize { + } + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + pub fn f2(self) { + (foo, bar) + } + + #[another_attribute] + fn f3(self) -> Dog { + } + + /// Blah blah bing. + + #[attrib1] + /// Blah blah bing. + #[attrib2] + // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo loooooooooooong. + /// Blah blah bing. + fn f4(self) -> Cat { + } + + // We want spaces around `=` + #[cfg(feature="nightly")] + fn f5(self) -> Monkey {} +} + +// #984 +struct Foo { + # [ derive ( Clone , PartialEq , Debug , Deserialize , Serialize ) ] + foo: usize, +} + +// #1668 + +/// Default path (*nix) +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] +fn foo() { + #[cfg(target_os = "freertos")] + match port_id { + 'a' | 'A' => GpioPort { port_address: GPIO_A }, + 'b' | 'B' => GpioPort { port_address: GPIO_B }, + _ => panic!(), + } + + #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] + let x = 3; +} + +// #1777 +#[test] +#[should_panic(expected = "(")] +#[should_panic(expected = /* ( */ "(")] +#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] +#[should_panic( + /* (((((((( *//* + (((((((((()(((((((( */ + expected = "(" + // (((((((( +)] +fn foo() {} + +// #1799 +fn issue_1799() { + #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 + Some( Err(error) ) ; + + #[allow(unreachable_code)] + // https://github.com/rust-lang/rust/issues/43336 + Some( Err(error) ) ; +} + +// Formatting inner attributes +fn inner_attributes() { + #![ this_is_an_inner_attribute ( foo ) ] + + foo(); +} + +impl InnerAttributes() { + #![ this_is_an_inner_attribute ( foo ) ] + + fn foo() {} +} + +mod InnerAttributes { + #![ this_is_an_inner_attribute ( foo ) ] +} + +fn attributes_on_statements() { + // Local + # [ attr ( on ( local ) ) ] + let x = 3; + + // Item + # [ attr ( on ( item ) ) ] + use foo; + + // Expr + # [ attr ( on ( expr ) ) ] + {} + + // Semi + # [ attr ( on ( semi ) ) ] + foo(); + + // Mac + # [ attr ( on ( mac ) ) ] + foo!(); +} + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] +pub struct HP(pub u8); diff --git a/rustfmt-core/tests/source/big-impl-rfc.rs b/rustfmt-core/tests/source/big-impl-rfc.rs new file mode 100644 index 00000000000..737dd5aeb6a --- /dev/null +++ b/rustfmt-core/tests/source/big-impl-rfc.rs @@ -0,0 +1,125 @@ +// rustfmt-indent_style: Block + +// #1357 +impl< + 'a, + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + Groupby, + DB, +> InternalBoxedDsl<'a, DB> + for SelectStatement< + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + GroupBy, + > where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} + +// #1689 +impl SubSelectDirect + where + M: select::Selector, + S: event::Stream, + F: for<'t> FnMut(transform::Api< + 't, + Stream>, + >) + -> transform::Api<'t, X>, + X: event::Stream, +{ +} diff --git a/rustfmt-core/tests/source/big-impl.rs b/rustfmt-core/tests/source/big-impl.rs new file mode 100644 index 00000000000..c36b7e6cadb --- /dev/null +++ b/rustfmt-core/tests/source/big-impl.rs @@ -0,0 +1,104 @@ +// #1357 +impl< + 'a, + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + Groupby, + DB, +> InternalBoxedDsl<'a, DB> + for SelectStatement< + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + GroupBy, + > where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo + for Bar { + fn foo() {} +} diff --git a/rustfmt-core/tests/source/break-and-continue.rs b/rustfmt-core/tests/source/break-and-continue.rs new file mode 100644 index 00000000000..c01d8a07845 --- /dev/null +++ b/rustfmt-core/tests/source/break-and-continue.rs @@ -0,0 +1,23 @@ +// break and continue formatting + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} diff --git a/rustfmt-core/tests/source/catch.rs b/rustfmt-core/tests/source/catch.rs new file mode 100644 index 00000000000..64cc9e7a207 --- /dev/null +++ b/rustfmt-core/tests/source/catch.rs @@ -0,0 +1,27 @@ +#![feature(catch_expr)] + +fn main() { + let x = do catch { + foo()? + }; + + let x = do catch /* Invisible comment */ { foo()? }; + + let x = do catch { + unsafe { foo()? } + }; + + let y = match (do catch { + foo()? + }) { + _ => (), + }; + + do catch { + foo()?; + }; + + do catch { + // Regular do catch block + }; +} diff --git a/rustfmt-core/tests/source/chains-indent-tabbed.rs b/rustfmt-core/tests/source/chains-indent-tabbed.rs new file mode 100644 index 00000000000..6a9a40cb98f --- /dev/null +++ b/rustfmt-core/tests/source/chains-indent-tabbed.rs @@ -0,0 +1,5 @@ +// rustfmt-indent_style: Block + +fn test() { + let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); +} diff --git a/rustfmt-core/tests/source/chains-indent-visual.rs b/rustfmt-core/tests/source/chains-indent-visual.rs new file mode 100644 index 00000000000..8fdd3c4cabf --- /dev/null +++ b/rustfmt-core/tests/source/chains-indent-visual.rs @@ -0,0 +1,5 @@ +// rustfmt-indent_style: Visual + +fn test() { + let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); +} diff --git a/rustfmt-core/tests/source/chains-visual.rs b/rustfmt-core/tests/source/chains-visual.rs new file mode 100644 index 00000000000..466f6840887 --- /dev/null +++ b/rustfmt-core/tests/source/chains-visual.rs @@ -0,0 +1,159 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Visual +// Test chain formatting. + +fn main() { + // Don't put chains on a single line if it wasn't so in source. + let a = b .c + .d.1 + .foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x() + .y(|| match cond() { true => (), false => () }); + + loong_func() + .quux(move || if true { + 1 + } else { + 2 + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }).method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }).filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } + + if cond { some(); } else { none(); } + .bar() + .baz(); + + Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); + + Foo { y: i_am_multi_line, z: ok } + .baz(|| { + force(); multiline(); + }) + .quux(); + + a + match x { true => "yay!", false => "boo!" }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained( + self.id, constraints)).unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn issue_1389() { + let names = String::from_utf8(names)?.split('|').map(str::to_owned).collect(); +} + +fn issue1217() -> Result { +let random_chars: String = OsRng::new()? + .gen_ascii_chars() + .take(self.bit_length) + .collect(); + + Ok(Mnemonic::new(&random_chars)) +} + +fn issue1236(options: Vec) -> Result> { +let process = Command::new("dmenu").stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; +} + +fn issue1434() { + for _ in 0..100 { + let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; + } +} + +fn issue2264() { + { + something.function() + .map(|| { + if let a_very_very_very_very_very_very_very_very_long_variable = + compute_this_variable() + { + println!("Hello"); + } + }) + .collect(); + } +} diff --git a/rustfmt-core/tests/source/chains.rs b/rustfmt-core/tests/source/chains.rs new file mode 100644 index 00000000000..0ed52ae61be --- /dev/null +++ b/rustfmt-core/tests/source/chains.rs @@ -0,0 +1,231 @@ +// rustfmt-normalize_comments: true +// rustfmt-use_small_heuristics: false +// Test chain formatting. + +fn main() { + let a = b .c + .d.1 + .foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + + let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x() + .y(|| match cond() { true => (), false => () }); + + loong_func() + .quux(move || if true { + 1 + } else { + 2 + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }).method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + body.fold(Body::new(), |mut body, chunk| { + body.extend(chunk); + Ok(body) + }).and_then(move |body| { + let req = Request::from_parts(parts, body); + f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) + }); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }).filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } + + if cond { some(); } else { none(); } + .bar() + .baz(); + + Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); + + Foo { y: i_am_multi_line, z: ok } + .baz(|| { + force(); multiline(); + }) + .quux(); + + a + match x { true => "yay!", false => "boo!" }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained( + self.id, constraints)).unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + let x = expr?; + let y = expr.kaas()?.test(); + let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); + let zzzz = expr?.another?.another?.another?.another?; + let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??; + + let y = a.very .loooooooooooooooooooooooooooooooooooooong() .chain() + .inside() .weeeeeeeeeeeeeee()? .test() .0 + .x; + + parameterized(f, + substs, + def_id, + Ns::Value, + &[], + |tcx| tcx.lookup_item_type(def_id).generics)?; + fooooooooooooooooooooooooooo()?.bar()?.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; +} + +fn issue_1004() { + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), + } + ?; + + ty::tls::with(|tcx| { + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + }) + ?; +} + +fn issue1392() { + test_method(r#" + if foo { + a(); + } + else { + b(); + } + "#.trim()); +} + +// #2067 +impl Settings { + fn save(&self) -> Result<()> { + let mut file = File::create(&settings_path).chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; + } +} + +fn issue2126() { + { + { + { + { + { + let x = self.span_from(sub_span.expect("No span found for struct arant variant")); + self.sspanpan_from_span(sub_span.expect("No span found for struct variant")); + let x = self.spanpan_from_span(sub_span.expect("No span found for struct variant"))?; + } + } + } + } + } +} + +// #2200 +impl Foo { + pub fn from_ast(diagnostic: &::errors::Handler, + attrs: &[ast::Attribute]) -> Attributes { + let other_attrs = attrs.iter().filter_map(|attr| { + attr.with_desugared_doc(|attr| { + if attr.check_name("doc") { + if let Some(mi) = attr.meta() { + if let Some(value) = mi.value_str() { + doc_strings.push(DocFragment::Include(line, + attr.span, + filename, + contents)); + } + } + } + }) + }).collect(); + } +} + +// #2415 +// Avoid orphan in chain +fn issue2415() { + let base_url = (|| { + // stuff + + Ok((|| { + // stuff + Some(value.to_string()) + })() + .ok_or("")?) + })() + .unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); +} diff --git a/rustfmt-core/tests/source/closure-block-inside-macro.rs b/rustfmt-core/tests/source/closure-block-inside-macro.rs new file mode 100644 index 00000000000..c1260592083 --- /dev/null +++ b/rustfmt-core/tests/source/closure-block-inside-macro.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Block + +// #1547 +fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; + } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); +}); diff --git a/rustfmt-core/tests/source/closure.rs b/rustfmt-core/tests/source/closure.rs new file mode 100644 index 00000000000..e93cc3fb40f --- /dev/null +++ b/rustfmt-core/tests/source/closure.rs @@ -0,0 +1,213 @@ +// rustfmt-normalize_comments: true +// Closures + +fn main() { + let square = ( |i: i32 | i * i ); + + let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // format comments. + if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo() + } else { + field.span.lo() + }}; + + let unblock_me = |trivial| { + closure() + }; + + let empty = |arg| {}; + + let simple = |arg| { /* comment formatting */ foo(arg) }; + + let test = | | { do_something(); do_something_else(); }; + + let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; + + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { + foo() + }; + + let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; + arg2 * arg1 - temp }; + + let block_body_with_comment = args.iter() + .map(|a| { + // Emitting only dep-info is possible only for final crate type, as + // as others may emit required metadata for dependent crate types + if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { + "--emit=dep-info" + } else { a } + }); +} + +fn issue311() { + let func = |x| println!("{}", x); + + (func)(0.0); +} + +fn issue863() { + let closure = |x| match x { + 0 => true, + _ => false, + } == true; +} + +fn issue934() { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) + } + } + } +} + +fn foo() { + lifetimes_iter___map(|lasdfasfd| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi() + }; + }); +} + +fn issue1405() { + open_raw_fd(fd, b'r') + .and_then(|file| Capture::new_raw(None, |_, err| unsafe { + raw::pcap_fopen_offline(file, err) + })); +} + +fn issue1466() { + let vertex_buffer = frame.scope(|ctx| { + let buffer = + ctx.create_host_visible_buffer::>(&vertices); + ctx.create_device_local_buffer(buffer) + }); +} + +fn issue470() { + {{{ + let explicit_arg_decls = + explicit_arguments.into_iter() + .enumerate() + .map(|(index, (ty, pattern))| { + let lvalue = Lvalue::Arg(index as u32); + block = this.pattern(block, + argument_extent, + hair::PatternRef::Hair(pattern), + &lvalue); + ArgDecl { ty: ty } + }); + }}} +} + +// #1509 +impl Foo { + pub fn bar(&self) { + Some(SomeType { + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { + Ok(f) + })), + }) + } +} + +fn issue1329() { + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }) + .filter +} + +fn issue325() { + let f = || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; +} + +fn issue1697() { + Test.func_a(A_VERY_LONG_CONST_VARIABLE_NAME, move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4) +} + +fn issue1694() { + foooooo(|_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| format!("refs/pull/{}/merge", pr_id)) +} + +fn issue1713() { + rayon::join( + || recurse(left, is_less, pred, limit), + || recurse(right, is_less, Some(pivot), limit), + ); + + rayon::join( + 1, + || recurse(left, is_less, pred, limit), + 2, + || recurse(right, is_less, Some(pivot), limit), + ); +} + +fn issue2063() { + |ctx: Ctx<(String, String)>| -> io::Result { + Ok(Response::new().with_body(ctx.params.0)) + } +} + +fn issue1524() { + let f = |x| {{{{x}}}}; + let f = |x| {{{x}}}; + let f = |x| {{x}}; + let f = |x| {x}; + let f = |x| x; +} + +fn issue2171() { + foo(|| unsafe { + if PERIPHERALS { + loop {} + } else { + PERIPHERALS = true; + } + }) +} + +fn issue2207() { + a.map(|_| unsafe { + a_very_very_very_very_very_very_very_long_function_name_or_anything_else() + }.to_string()) +} + +fn issue2262() { + result.init(&mut result.slave.borrow_mut(), &mut (result.strategy)()).map_err(|factory| Error { + factory, + slave: None, + })?; +} diff --git a/rustfmt-core/tests/source/comment.rs b/rustfmt-core/tests/source/comment.rs new file mode 100644 index 00000000000..b6ce5267fcb --- /dev/null +++ b/rustfmt-core/tests/source/comment.rs @@ -0,0 +1,90 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//! Doc comment +fn test() { + /*! + * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam */ + +// comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me + + // #1388 + const EXCEPTION_PATHS: &'static [&'static str] = + &[// std crates + "src/libstd/sys/", // Platform-specific code for std lives here. + "src/bootstrap"]; +} + + /// test123 +fn doc_comment() { +} + +fn chains() { + foo.bar(|| { + let x = 10; + /* comment */ x }) +} + +fn issue_1086() { + /**/ +} + +/* + * random comment */ + +fn main() {/* Test */} + +// #1643 +fn some_fn() /* some comment */ +{ +} + +fn some_fn1() +// some comment +{ +} + +fn some_fn2() // some comment +{ +} + +fn some_fn3() /* some comment some comment some comment some comment some comment some comment so */ +{ +} + +fn some_fn4() +/* some comment some comment some comment some comment some comment some comment some comment */ +{ +} + +// #1603 +pub enum Foo { + A, // `/** **/` + B, // `/*!` + C, +} diff --git a/rustfmt-core/tests/source/comment2.rs b/rustfmt-core/tests/source/comment2.rs new file mode 100644 index 00000000000..d68bb5483dc --- /dev/null +++ b/rustfmt-core/tests/source/comment2.rs @@ -0,0 +1,4 @@ +// rustfmt-wrap_comments: true + +/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. +pub mod foo {} diff --git a/rustfmt-core/tests/source/comment3.rs b/rustfmt-core/tests/source/comment3.rs new file mode 100644 index 00000000000..f19a8586334 --- /dev/null +++ b/rustfmt-core/tests/source/comment3.rs @@ -0,0 +1,5 @@ +// rustfmt-wrap_comments: true + +//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. + +pub mod foo {} diff --git a/rustfmt-core/tests/source/comment4.rs b/rustfmt-core/tests/source/comment4.rs new file mode 100644 index 00000000000..ff1445378d7 --- /dev/null +++ b/rustfmt-core/tests/source/comment4.rs @@ -0,0 +1,52 @@ +#![allow(dead_code)] // bar + +//! Doc comment +fn test() { +// comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + + /// test123 +fn doc_comment() { +} + +/* +Regression test for issue #956 + +(some very important text) +*/ + +/* +fn debug_function() { + println!("hello"); +} +// */ + +#[link_section=".vectors"] +#[no_mangle] // Test this attribute is preserved. +#[cfg_attr(rustfmt, rustfmt_skip)] +pub static ISSUE_1284: [i32; 16] = []; diff --git a/rustfmt-core/tests/source/comment5.rs b/rustfmt-core/tests/source/comment5.rs new file mode 100644 index 00000000000..2835d8b2578 --- /dev/null +++ b/rustfmt-core/tests/source/comment5.rs @@ -0,0 +1,14 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//@ special comment +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ +//@foo +fn test() {} + +//@@@ another special comment +//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@@@ +//@@@foo +fn bar() {} diff --git a/rustfmt-core/tests/source/comment_crlf_newline.rs b/rustfmt-core/tests/source/comment_crlf_newline.rs new file mode 100644 index 00000000000..7a65f762f6c --- /dev/null +++ b/rustfmt-core/tests/source/comment_crlf_newline.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true +/* Block comments followed by CRLF newlines should not an extra newline at the end */ + +/* Something else */ diff --git a/rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs b/rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs new file mode 100644 index 00000000000..c6058a55b0a --- /dev/null +++ b/rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs @@ -0,0 +1,13 @@ +// rustfmt-blank_lines_lower_bound: 1 + +fn foo() {} +fn bar() {} +// comment +fn foobar() {} + +fn foo1() {} +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs b/rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs new file mode 100644 index 00000000000..d3bd9ac09aa --- /dev/null +++ b/rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs @@ -0,0 +1,14 @@ +// rustfmt-brace_style: AlwaysNextLine +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { + // body +} diff --git a/rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs b/rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs new file mode 100644 index 00000000000..78a4495243d --- /dev/null +++ b/rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs @@ -0,0 +1,14 @@ +// rustfmt-brace_style: PreferSameLine +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { + // body +} diff --git a/rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs b/rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs new file mode 100644 index 00000000000..3b78932e177 --- /dev/null +++ b/rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs @@ -0,0 +1,14 @@ +// rustfmt-brace_style: SameLineWhere +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { + // body +} diff --git a/rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs b/rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs new file mode 100644 index 00000000000..0cc19b34da7 --- /dev/null +++ b/rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs @@ -0,0 +1,20 @@ +// rustfmt-brace_style: AlwaysNextLine +// Item brace style + +enum Foo {} + +struct Bar {} + +struct Lorem { + ipsum: bool, +} + +struct Dolor where T: Eq { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs b/rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs new file mode 100644 index 00000000000..4412bc869a2 --- /dev/null +++ b/rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs @@ -0,0 +1,16 @@ +// rustfmt-brace_style: PreferSameLine +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor where T: Eq { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs b/rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs new file mode 100644 index 00000000000..b8e69147dc5 --- /dev/null +++ b/rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs @@ -0,0 +1,16 @@ +// rustfmt-brace_style: SameLineWhere +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor where T: Eq { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/rustfmt-core/tests/source/configs/comment_width/above.rs b/rustfmt-core/tests/source/configs/comment_width/above.rs new file mode 100644 index 00000000000..36187ce0af4 --- /dev/null +++ b/rustfmt-core/tests/source/configs/comment_width/above.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/rustfmt-core/tests/source/configs/comment_width/below.rs b/rustfmt-core/tests/source/configs/comment_width/below.rs new file mode 100644 index 00000000000..abbc5930c4c --- /dev/null +++ b/rustfmt-core/tests/source/configs/comment_width/below.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 80 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/rustfmt-core/tests/source/configs/comment_width/ignore.rs b/rustfmt-core/tests/source/configs/comment_width/ignore.rs new file mode 100644 index 00000000000..c86e71c2898 --- /dev/null +++ b/rustfmt-core/tests/source/configs/comment_width/ignore.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: false +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs b/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs new file mode 100644 index 00000000000..3b967f35a8e --- /dev/null +++ b/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: false +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, _, _) = (1, 2, 3, 4); +} diff --git a/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs b/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs new file mode 100644 index 00000000000..3798a6b9902 --- /dev/null +++ b/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: true +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, _, _) = (1, 2, 3, 4); +} diff --git a/rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs b/rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs new file mode 100644 index 00000000000..c4ddad9ce27 --- /dev/null +++ b/rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs @@ -0,0 +1,10 @@ +// rustfmt-control_brace_style: AlwaysNextLine +// Control brace style + +fn main() { + if lorem { println!("ipsum!"); } else { println!("dolor!"); } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs b/rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs new file mode 100644 index 00000000000..a9c699d27e3 --- /dev/null +++ b/rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs @@ -0,0 +1,10 @@ +// rustfmt-control_brace_style: AlwaysSameLine +// Control brace style + +fn main() { + if lorem { println!("ipsum!"); } else { println!("dolor!"); } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs b/rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs new file mode 100644 index 00000000000..1a74a28f26a --- /dev/null +++ b/rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs @@ -0,0 +1,10 @@ +// rustfmt-control_brace_style: ClosingNextLine +// Control brace style + +fn main() { + if lorem { println!("ipsum!"); } else { println!("dolor!"); } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/rustfmt-core/tests/source/configs/disable_all_formatting/false.rs b/rustfmt-core/tests/source/configs/disable_all_formatting/false.rs new file mode 100644 index 00000000000..834ca7a3c89 --- /dev/null +++ b/rustfmt-core/tests/source/configs/disable_all_formatting/false.rs @@ -0,0 +1,6 @@ +// rustfmt-disable_all_formatting: false +// Disable all formatting + +fn main() { + if lorem{println!("ipsum!");}else{println!("dolor!");} +} diff --git a/rustfmt-core/tests/source/configs/disable_all_formatting/true.rs b/rustfmt-core/tests/source/configs/disable_all_formatting/true.rs new file mode 100644 index 00000000000..56955bf384d --- /dev/null +++ b/rustfmt-core/tests/source/configs/disable_all_formatting/true.rs @@ -0,0 +1,6 @@ +// rustfmt-disable_all_formatting: true +// Disable all formatting + +fn main() { + iflorem{println!("ipsum!");}else{println!("dolor!");} +} diff --git a/rustfmt-core/tests/source/configs/empty_item_single_line/false.rs b/rustfmt-core/tests/source/configs/empty_item_single_line/false.rs new file mode 100644 index 00000000000..8fa74f28802 --- /dev/null +++ b/rustfmt-core/tests/source/configs/empty_item_single_line/false.rs @@ -0,0 +1,17 @@ +// rustfmt-empty_item_single_line: false +// Empty impl on single line + +impl Lorem { + +} + +impl Ipsum { + +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/rustfmt-core/tests/source/configs/empty_item_single_line/true.rs b/rustfmt-core/tests/source/configs/empty_item_single_line/true.rs new file mode 100644 index 00000000000..02e703d1904 --- /dev/null +++ b/rustfmt-core/tests/source/configs/empty_item_single_line/true.rs @@ -0,0 +1,17 @@ +// rustfmt-empty_item_single_line: true +// Empty impl on single line + +impl Lorem { + +} + +impl Ipsum { + +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs b/rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs new file mode 100644 index 00000000000..fa70ae78352 --- /dev/null +++ b/rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs @@ -0,0 +1,6 @@ +// rustfmt-error_on_line_overflow: false +// Error on line overflow + +fn main() { + let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; +} diff --git a/rustfmt-core/tests/source/configs/fn_args_density/compressed.rs b/rustfmt-core/tests/source/configs/fn_args_density/compressed.rs new file mode 100644 index 00000000000..86c0b42e53c --- /dev/null +++ b/rustfmt-core/tests/source/configs/fn_args_density/compressed.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_density: Compressed +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/rustfmt-core/tests/source/configs/fn_args_density/tall.rs b/rustfmt-core/tests/source/configs/fn_args_density/tall.rs new file mode 100644 index 00000000000..fc400e1c113 --- /dev/null +++ b/rustfmt-core/tests/source/configs/fn_args_density/tall.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_density: Tall +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/rustfmt-core/tests/source/configs/fn_args_density/vertical.rs b/rustfmt-core/tests/source/configs/fn_args_density/vertical.rs new file mode 100644 index 00000000000..20b1427d83d --- /dev/null +++ b/rustfmt-core/tests/source/configs/fn_args_density/vertical.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_density: Vertical +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/rustfmt-core/tests/source/configs/fn_single_line/false.rs b/rustfmt-core/tests/source/configs/fn_single_line/false.rs new file mode 100644 index 00000000000..3d092f0c0bf --- /dev/null +++ b/rustfmt-core/tests/source/configs/fn_single_line/false.rs @@ -0,0 +1,11 @@ +// rustfmt-fn_single_line: false +// Single-expression function on single line + +fn lorem() -> usize { + 42 +} + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/rustfmt-core/tests/source/configs/fn_single_line/true.rs b/rustfmt-core/tests/source/configs/fn_single_line/true.rs new file mode 100644 index 00000000000..3cb0fdedf0b --- /dev/null +++ b/rustfmt-core/tests/source/configs/fn_single_line/true.rs @@ -0,0 +1,11 @@ +// rustfmt-fn_single_line: true +// Single-expression function on single line + +fn lorem() -> usize { + 42 +} + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/rustfmt-core/tests/source/configs/force_explicit_abi/false.rs b/rustfmt-core/tests/source/configs/force_explicit_abi/false.rs new file mode 100644 index 00000000000..3c48f8e0c78 --- /dev/null +++ b/rustfmt-core/tests/source/configs/force_explicit_abi/false.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: false +// Force explicit abi + +extern { + pub static lorem: c_int; +} diff --git a/rustfmt-core/tests/source/configs/force_explicit_abi/true.rs b/rustfmt-core/tests/source/configs/force_explicit_abi/true.rs new file mode 100644 index 00000000000..e5ff6cf7dd7 --- /dev/null +++ b/rustfmt-core/tests/source/configs/force_explicit_abi/true.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: true +// Force explicit abi + +extern { + pub static lorem: c_int; +} diff --git a/rustfmt-core/tests/source/configs/force_multiline_block/false.rs b/rustfmt-core/tests/source/configs/force_multiline_block/false.rs new file mode 100644 index 00000000000..b97e348e5da --- /dev/null +++ b/rustfmt-core/tests/source/configs/force_multiline_block/false.rs @@ -0,0 +1,22 @@ +// rustfmt-force_multiline_blocks: false +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/rustfmt-core/tests/source/configs/force_multiline_block/true.rs b/rustfmt-core/tests/source/configs/force_multiline_block/true.rs new file mode 100644 index 00000000000..db9d3de4614 --- /dev/null +++ b/rustfmt-core/tests/source/configs/force_multiline_block/true.rs @@ -0,0 +1,18 @@ +// rustfmt-force_multiline_blocks: true +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => if ipsum { + println!("dolor"); + }, + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/rustfmt-core/tests/source/configs/format_strings/false.rs b/rustfmt-core/tests/source/configs/format_strings/false.rs new file mode 100644 index 00000000000..ecca0d7d1fc --- /dev/null +++ b/rustfmt-core/tests/source/configs/format_strings/false.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; +} diff --git a/rustfmt-core/tests/source/configs/format_strings/true.rs b/rustfmt-core/tests/source/configs/format_strings/true.rs new file mode 100644 index 00000000000..33731447821 --- /dev/null +++ b/rustfmt-core/tests/source/configs/format_strings/true.rs @@ -0,0 +1,7 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; +} diff --git a/rustfmt-core/tests/source/configs/hard_tabs/false.rs b/rustfmt-core/tests/source/configs/hard_tabs/false.rs new file mode 100644 index 00000000000..bf92162b424 --- /dev/null +++ b/rustfmt-core/tests/source/configs/hard_tabs/false.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: false +// Hard tabs + +fn lorem() -> usize { +42 // spaces before 42 +} diff --git a/rustfmt-core/tests/source/configs/hard_tabs/true.rs b/rustfmt-core/tests/source/configs/hard_tabs/true.rs new file mode 100644 index 00000000000..738922a4dfb --- /dev/null +++ b/rustfmt-core/tests/source/configs/hard_tabs/true.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: true +// Hard tabs + +fn lorem() -> usize { +42 // spaces before 42 +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_args.rs b/rustfmt-core/tests/source/configs/indent_style/block_args.rs new file mode 100644 index 00000000000..4d2d280a16b --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_args.rs @@ -0,0 +1,26 @@ +// rustfmt-indent_style: Block +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { + // body +} + +// #1441 +extern "system" { + pub fn GetConsoleHistoryInfo(console_history_info: *mut ConsoleHistoryInfo) -> Boooooooooooooool; +} + +// rustfmt should not add trailing comma for variadic function. See #1623. +extern "C" { + pub fn variadic_fn(first_parameter: FirstParameterType, + second_parameter: SecondParameterType, + ...); +} + +// #1652 +fn deconstruct(foo: Bar) -> (SocketAddr, Header, Method, RequestUri, HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_array.rs b/rustfmt-core/tests/source/configs/indent_style/block_array.rs new file mode 100644 index 00000000000..8404f65f471 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_array.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Array layout + +fn main() { + let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_call.rs b/rustfmt-core/tests/source/configs/indent_style/block_call.rs new file mode 100644 index 00000000000..c82b6b8e38f --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_call.rs @@ -0,0 +1,133 @@ +// rustfmt-indent_style: Block +// Function call style + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); + // #1501 + let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); + + // chain + let x = yooooooooooooo.fooooooooooooooo.baaaaaaaaaaaaar(hello, world); + + // #1380 + { + { + let creds = self.client + .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; + } + } + + // nesting macro and function call + try!(foo(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)); + try!(foo(try!(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx))); +} + +// #1521 +impl Foo { + fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { + unsafe { + Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw())) + } + } +} + +fn issue1420() { + given( + r#" + # Getting started + ... + "#, + ) + .running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| { + Post { + title: row.get(0), + date: row.get(1), + } + }, + )?; + + Ok(()) +} + +// #1449 +fn future_rayon_wait_1_thread() { + // run with only 1 worker thread; this would deadlock if we couldn't make progress + let mut result = None; + ThreadPool::new(Configuration::new().num_threads(1)) + .unwrap() + .install( + || { + scope( + |s| { + use std::sync::mpsc::channel; + let (tx, rx) = channel(); + let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); + // ^^^^ FIXME: why is this needed? + let b = s.spawn_future(a.map(|v| v + 1)); + let c = s.spawn_future(b.map(|v| v + 1)); + s.spawn(move |_| tx.send(20).unwrap()); + result = Some(c.rayon_wait().unwrap()); + }, + ); + }, + ); + assert_eq!(result, Some(22)); +} + +// #1494 +impl Cursor { + fn foo() { + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical != *self { + canonical.num_template_args() + } else { + None + } + }); + } +} + +fn issue1581() { + bootstrap.checks.register( + "PERSISTED_LOCATIONS", + move || if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + }, + ); +} + +fn issue1651() { + { + let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + } +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_chain.rs b/rustfmt-core/tests/source/configs/indent_style/block_chain.rs new file mode 100644 index 00000000000..41d91469114 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_chain.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Chain indent + +fn main() { + let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_generic.rs b/rustfmt-core/tests/source/configs/indent_style/block_generic.rs new file mode 100644 index 00000000000..2cf17be56ef --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_generic.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Generics indent + +fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { + // body +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs b/rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs new file mode 100644 index 00000000000..47a6994f40c --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Struct literal-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs b/rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs new file mode 100644 index 00000000000..c907ec50d45 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs @@ -0,0 +1,8 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); +} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs b/rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs new file mode 100644 index 00000000000..450491f0270 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Where predicate indent + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/rustfmt-core/tests/source/configs/indent_style/default.rs b/rustfmt-core/tests/source/configs/indent_style/default.rs new file mode 100644 index 00000000000..f08f5c64460 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/default.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Where style + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/rustfmt-core/tests/source/configs/indent_style/rfc_where.rs b/rustfmt-core/tests/source/configs/indent_style/rfc_where.rs new file mode 100644 index 00000000000..012840be28d --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/rfc_where.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Where style + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_args.rs b/rustfmt-core/tests/source/configs/indent_style/visual_args.rs new file mode 100644 index 00000000000..5aa28a62b9c --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_args.rs @@ -0,0 +1,32 @@ +// rustfmt-indent_style: Visual +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { + // body +} + +// #1922 +extern "C" { + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + a: *const lapack_complex_float, + lda: lapack_int, ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int + )-> lapack_int; + + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + lda: lapack_int, ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int + ) -> lapack_int; +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_array.rs b/rustfmt-core/tests/source/configs/indent_style/visual_array.rs new file mode 100644 index 00000000000..05bbf00b1d2 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_array.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Array layout + +fn main() { + let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_call.rs b/rustfmt-core/tests/source/configs/indent_style/visual_call.rs new file mode 100644 index 00000000000..9a679d6bb4c --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_call.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Function call style + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_chain.rs b/rustfmt-core/tests/source/configs/indent_style/visual_chain.rs new file mode 100644 index 00000000000..b7494875398 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_chain.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Chain indent + +fn main() { + let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_generics.rs b/rustfmt-core/tests/source/configs/indent_style/visual_generics.rs new file mode 100644 index 00000000000..1f910d32d87 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_generics.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Generics indent + +fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { + // body +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs b/rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs new file mode 100644 index 00000000000..45538e70482 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Struct literal-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs b/rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs new file mode 100644 index 00000000000..9738d397dbf --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs b/rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs new file mode 100644 index 00000000000..055806b6862 --- /dev/null +++ b/rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Where predicate indent + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/rustfmt-core/tests/source/configs/match_arm_blocks/false.rs b/rustfmt-core/tests/source/configs/match_arm_blocks/false.rs new file mode 100644 index 00000000000..53e37e13c4f --- /dev/null +++ b/rustfmt-core/tests/source/configs/match_arm_blocks/false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: false +// Wrap match-arms + +fn main() { + match lorem { + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => { + println!("{}", sit) + } + } +} diff --git a/rustfmt-core/tests/source/configs/match_arm_blocks/true.rs b/rustfmt-core/tests/source/configs/match_arm_blocks/true.rs new file mode 100644 index 00000000000..a452b13cd27 --- /dev/null +++ b/rustfmt-core/tests/source/configs/match_arm_blocks/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: true +// Wrap match-arms + +fn main() { + match lorem { + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => { + println!("{}", sit) + } + } +} diff --git a/rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs b/rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs new file mode 100644 index 00000000000..70e02955fb0 --- /dev/null +++ b/rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: false +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + } + Lorem::Dolor => println!("dolor"), + } +} diff --git a/rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs b/rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs new file mode 100644 index 00000000000..b9af3d47202 --- /dev/null +++ b/rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: true +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + } + Lorem::Dolor => println!("dolor"), + } +} diff --git a/rustfmt-core/tests/source/configs/merge_derives/true.rs b/rustfmt-core/tests/source/configs/merge_derives/true.rs new file mode 100644 index 00000000000..18b8443f0d7 --- /dev/null +++ b/rustfmt-core/tests/source/configs/merge_derives/true.rs @@ -0,0 +1,46 @@ +// rustfmt-merge_derives: true +// Merge multiple derives to a single one. + +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} + +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} + +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum FooBar {} + +mod foo { +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} +} + +mod bar { +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} +} + +mod foobar { +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum FooBar {} +} diff --git a/rustfmt-core/tests/source/configs/normalize_comments/false.rs b/rustfmt-core/tests/source/configs/normalize_comments/false.rs new file mode 100644 index 00000000000..488962ed936 --- /dev/null +++ b/rustfmt-core/tests/source/configs/normalize_comments/false.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: false +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +/* sit amet: */ +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/source/configs/normalize_comments/true.rs b/rustfmt-core/tests/source/configs/normalize_comments/true.rs new file mode 100644 index 00000000000..c74a9808e61 --- /dev/null +++ b/rustfmt-core/tests/source/configs/normalize_comments/true.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: true +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +/* sit amet: */ +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs b/rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs new file mode 100644 index 00000000000..6bef132e5c3 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: false + +extern crate foo; +extern crate bar; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs b/rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs new file mode 100644 index 00000000000..bdf00f57cda --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: true + +extern crate foo; +extern crate bar; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/rustfmt-core/tests/source/configs/reorder_imported_names/false.rs b/rustfmt-core/tests/source/configs/reorder_imported_names/false.rs new file mode 100644 index 00000000000..91db89ceeaa --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_imported_names/false.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: false +// Reorder imported names + +use super::{lorem, ipsum, dolor, sit}; diff --git a/rustfmt-core/tests/source/configs/reorder_imported_names/true.rs b/rustfmt-core/tests/source/configs/reorder_imported_names/true.rs new file mode 100644 index 00000000000..69da6186d5a --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_imported_names/true.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: true +// Reorder imported names + +use super::{lorem, ipsum, dolor, sit}; diff --git a/rustfmt-core/tests/source/configs/reorder_imports/false.rs b/rustfmt-core/tests/source/configs/reorder_imports/false.rs new file mode 100644 index 00000000000..4b85684dc01 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_imports/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_imports: false +// Reorder imports + +use lorem; +use ipsum; +use dolor; +use sit; diff --git a/rustfmt-core/tests/source/configs/reorder_imports/true.rs b/rustfmt-core/tests/source/configs/reorder_imports/true.rs new file mode 100644 index 00000000000..2a40f6d069f --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_imports/true.rs @@ -0,0 +1,19 @@ +// rustfmt-reorder_imports: true +// Reorder imports + +use lorem; +use ipsum; +use dolor; +use sit; + +fn foo() { + use C; + use B; + use A; + + bar(); + + use F; + use E; + use D; +} diff --git a/rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs b/rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs new file mode 100644 index 00000000000..87711bb142b --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: false +// Reorder imports in group + +/// This comment should stay with `use std::mem;` +use std::mem; +use std::io; + +use lorem; +/// This comment should stay with `use ipsum;` +use ipsum; +use dolor; +use sit; diff --git a/rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs b/rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs new file mode 100644 index 00000000000..b5690b89cc0 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: true +// Reorder imports in group + +/// This comment should stay with `use std::mem;` +use std::mem; +use std::io; + +use lorem; +/// This comment should stay with `use ipsum;` +use ipsum; +use dolor; +use sit; diff --git a/rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/source/configs/reorder_modules/false.rs b/rustfmt-core/tests/source/configs/reorder_modules/false.rs new file mode 100644 index 00000000000..56b1aa03ed7 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_modules/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: false +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/source/configs/reorder_modules/true.rs b/rustfmt-core/tests/source/configs/reorder_modules/true.rs new file mode 100644 index 00000000000..79b0ab1e355 --- /dev/null +++ b/rustfmt-core/tests/source/configs/reorder_modules/true.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: true +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/rustfmt-core/tests/source/configs/space_before_colon/true.rs b/rustfmt-core/tests/source/configs/space_before_colon/true.rs new file mode 100644 index 00000000000..0a597602528 --- /dev/null +++ b/rustfmt-core/tests/source/configs/space_before_colon/true.rs @@ -0,0 +1,11 @@ +// rustfmt-space_before_colon: true +// Space before colon + +fn lorem(t : T) { + let ipsum: Dolor = sit; +} + +const LOREM : Lorem = Lorem { + ipsum : dolor, + sit : amet, +}; diff --git a/rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs b/rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs new file mode 100644 index 00000000000..11ca76b1345 --- /dev/null +++ b/rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: false +// Spaces around ranges + +fn main() { + let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } +} diff --git a/rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs b/rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs new file mode 100644 index 00000000000..50170892130 --- /dev/null +++ b/rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: true +// Spaces around ranges + +fn main() { + let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } +} diff --git a/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs b/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs new file mode 100644 index 00000000000..908373ca9b0 --- /dev/null +++ b/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs @@ -0,0 +1,7 @@ +// rustfmt-spaces_within_parens_and_brackets: false +// Spaces within parens and brackets + +fn lorem(t: T) { + let lorem = (ipsum, dolor); + let lorem: [usize; 2] = [ipsum, dolor]; +} diff --git a/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs b/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs new file mode 100644 index 00000000000..2e3c92da2fc --- /dev/null +++ b/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs @@ -0,0 +1,133 @@ +// rustfmt-spaces_within_parens_and_brackets: true +// Spaces within parens and brackets + +fn lorem(t: T) { + let lorem = (ipsum, dolor); + let lorem: [usize; 2] = [ipsum, dolor]; +} + +enum E { + A(u32), + B(u32, u32), + C(u32, u32, u32), + D(), +} + +struct TupleStruct0(); +struct TupleStruct1(u32); +struct TupleStruct2(u32, u32); + +fn fooEmpty() {} + +fn foo(e: E, _: u32) -> (u32, u32) { + // Tuples + let t1 = (); + let t2 = (1,); + let t3 = (1, 2); + + let ts0 = TupleStruct0(); + let ts1 = TupleStruct1(1); + let ts2 = TupleStruct2(1, 2); + + // Tuple pattern + let (a,b,c) = (1,2,3); + + // Expressions + let x = (1 + 2) * (3); + + // Function call + fooEmpty(); + foo(1, 2); + + // Pattern matching + match e { + A(_) => (), + B(_, _) => (), + C(..) => (), + D => (), + } + + (1,2) +} + +struct Foo { + i: T, +} + +struct Bar { + i: T, + e: E, +} + +struct Foo<'a> { + i: &'a str, +} + +enum E { + T(T), +} + +enum E { + T(T), + S(S), +} + +fn foo(a: T) { + foo::(10); +} + +fn foo(a: T, b: E) { + foo::(10, "bar"); +} + +fn foo(a: T, b: E) { + foo::(10, "bar"); + + let opt: Option; + let res: Result; +} + +fn foo<'a>(a: &'a str) { + foo("foo"); +} + +fn foo<'a, 'b>(a: &'a str, b: &'b str) { + foo("foo", "bar"); +} + +impl Foo { + fn bar() { + ::bar(); + } +} + +trait MyTrait {} +impl MyTrait for Foo {} + +fn foo() where for<'a> u32: 'a {} + +fn main() { + let arr: [i32; 5] = [1, 2, 3, 4, 5]; + let arr: [i32; 500] = [0; 500]; + + let v = vec![1, 2, 3]; + assert_eq!(arr, [1, 2, 3]); + + let i = arr[0]; + + let slice = &arr[1..2]; + + let line100_________________________________________________________________________ = [1, 2]; + let line101__________________________________________________________________________ = [1, 2]; + let line102___________________________________________________________________________ = [1, 2]; + let line103____________________________________________________________________________ = [1, 2]; + let line104_____________________________________________________________________________ = [1, 2]; + + let line100_____________________________________________________________________ = vec![1, 2]; + let line101______________________________________________________________________ = vec![1, 2]; + let line102_______________________________________________________________________ = vec![1, 2]; + let line103________________________________________________________________________ = vec![1, 2]; + let line104_________________________________________________________________________ = vec![1, 2]; +} + +fn f(slice: &[i32]) {} diff --git a/rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs b/rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs new file mode 100644 index 00000000000..e68340b027d --- /dev/null +++ b/rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs @@ -0,0 +1,383 @@ +// rustfmt-struct_field_align_threshold: 20 +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false + +struct Foo { + x: u32, + yy: u32, // comment + zzz: u32, +} + +pub struct Bar { + x: u32, + yy: u32, + zzz: u32, + + xxxxxxx: u32, +} + +fn main() { + let foo = Foo { + x: 0, + yy: 1, + zzz: 2, + }; + + let bar = Bar { + x: 0, + yy: 1, + zzz: 2, + + xxxxxxx: 3, + }; +} + + /// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct +NewInt (pub i32, SomeType /* inline comment */, T /* sup */ + + + ); + +struct Qux<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy> +( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +struct Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +struct Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +// Will this be a one-liner? +struct Tuple( + A, //Comment + B +); + +pub struct State time::Timespec> { now: F } + +pub struct State ()> { now: F } + +pub struct State { now: F } + +struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(T); +struct Foo(T) where T: Copy, T: Eq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU); + +mod m { + struct X where T: Sized { + a: T, + } +} + +struct Foo(TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +struct Foo {} +struct Foo { + } +struct Foo { + // comment + } +struct Foo { + // trailing space -> + + + } +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:f() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo + { a : 1, b:f( 2)}; + Foo{a:1,b:f(2),..g(3)}; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; + IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { a: bb, c: dd, e: ff }; + + Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ + e: eeeeeeeee }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, .. base }; + Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ + eeeeeeeee }; + Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; +} diff --git a/rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs b/rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs new file mode 100644 index 00000000000..17cad8dde29 --- /dev/null +++ b/rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs @@ -0,0 +1,6 @@ +// rustfmt-struct_lit_single_line: false +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/rustfmt-core/tests/source/configs/tab_spaces/2.rs b/rustfmt-core/tests/source/configs/tab_spaces/2.rs new file mode 100644 index 00000000000..5c2667bc2c7 --- /dev/null +++ b/rustfmt-core/tests/source/configs/tab_spaces/2.rs @@ -0,0 +1,11 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { +let ipsum = dolor(); +let sit = vec![ +"amet", "consectetur", "adipiscing", "elit." +]; +} diff --git a/rustfmt-core/tests/source/configs/tab_spaces/4.rs b/rustfmt-core/tests/source/configs/tab_spaces/4.rs new file mode 100644 index 00000000000..da61bbd42a7 --- /dev/null +++ b/rustfmt-core/tests/source/configs/tab_spaces/4.rs @@ -0,0 +1,11 @@ +// rustfmt-tab_spaces: 4 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { +let ipsum = dolor(); +let sit = vec![ +"amet", "consectetur", "adipiscing", "elit." +]; +} diff --git a/rustfmt-core/tests/source/configs/trailing_comma/always.rs b/rustfmt-core/tests/source/configs/trailing_comma/always.rs new file mode 100644 index 00000000000..57e874cd822 --- /dev/null +++ b/rustfmt-core/tests/source/configs/trailing_comma/always.rs @@ -0,0 +1,7 @@ +// rustfmt-trailing_comma: Always +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; +} diff --git a/rustfmt-core/tests/source/configs/trailing_comma/never.rs b/rustfmt-core/tests/source/configs/trailing_comma/never.rs new file mode 100644 index 00000000000..4da3b996f29 --- /dev/null +++ b/rustfmt-core/tests/source/configs/trailing_comma/never.rs @@ -0,0 +1,23 @@ +// rustfmt-trailing_comma: Never +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; + + // #1544 + if let VrMsg::ClientReply {request_num: reply_req_num, value, ..} = msg { + let _ = safe_assert_eq!(reply_req_num, request_num, op); + return Ok((request_num, op, value)); + } + + // #1710 + pub struct FileInput { + input: StringInput, + file_name: OsString, + } + match len { + Some(len) => Ok(new(self.input, self.pos + len)), + None => Err(self), + } +} diff --git a/rustfmt-core/tests/source/configs/trailing_comma/vertical.rs b/rustfmt-core/tests/source/configs/trailing_comma/vertical.rs new file mode 100644 index 00000000000..c903e822158 --- /dev/null +++ b/rustfmt-core/tests/source/configs/trailing_comma/vertical.rs @@ -0,0 +1,7 @@ +// rustfmt-trailing_comma: Vertical +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; +} diff --git a/rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs b/rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs new file mode 100644 index 00000000000..6e16e610566 --- /dev/null +++ b/rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs @@ -0,0 +1,6 @@ +// rustfmt-type_punctuation_density: Compressed +// Type punctuation density + +fn lorem() { + // body +} diff --git a/rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs b/rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs new file mode 100644 index 00000000000..1fcdddf0f9a --- /dev/null +++ b/rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs @@ -0,0 +1,6 @@ +// rustfmt-type_punctuation_density: Wide +// Type punctuation density + +fn lorem() { + // body +} diff --git a/rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs b/rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs new file mode 100644 index 00000000000..16ce740f1b9 --- /dev/null +++ b/rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs @@ -0,0 +1,19 @@ +// rustfmt-use_field_init_shorthand: false +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { + x: x, + y: y, + z: z, + }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs b/rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs new file mode 100644 index 00000000000..1e36c6cff35 --- /dev/null +++ b/rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs @@ -0,0 +1,19 @@ +// rustfmt-use_field_init_shorthand: true +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { + x: x, + y: y, + z: z, + }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/rustfmt-core/tests/source/configs/use_try_shorthand/false.rs b/rustfmt-core/tests/source/configs/use_try_shorthand/false.rs new file mode 100644 index 00000000000..de7f8b4a5e2 --- /dev/null +++ b/rustfmt-core/tests/source/configs/use_try_shorthand/false.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: false +// Use try! shorthand + +fn main() { + let lorem = try!(ipsum.map(|dolor| dolor.sit())); +} diff --git a/rustfmt-core/tests/source/configs/use_try_shorthand/true.rs b/rustfmt-core/tests/source/configs/use_try_shorthand/true.rs new file mode 100644 index 00000000000..9015ec41e5e --- /dev/null +++ b/rustfmt-core/tests/source/configs/use_try_shorthand/true.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: true +// Use try! shorthand + +fn main() { + let lorem = try!(ipsum.map(|dolor| dolor.sit())); +} diff --git a/rustfmt-core/tests/source/configs/where_single_line/true.rs b/rustfmt-core/tests/source/configs/where_single_line/true.rs new file mode 100644 index 00000000000..daaab865af2 --- /dev/null +++ b/rustfmt-core/tests/source/configs/where_single_line/true.rs @@ -0,0 +1,24 @@ +// rustfmt-where_single_line: true +// Where style + + +fn lorem_two_items() -> T where Ipsum: Eq, Lorem: Eq { + // body +} + +fn lorem_multi_line( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T +where + Ipsum: Eq, +{ + // body +} + +fn lorem() -> T where Ipsum: Eq { + // body +} diff --git a/rustfmt-core/tests/source/configs/wrap_comments/false.rs b/rustfmt-core/tests/source/configs/wrap_comments/false.rs new file mode 100644 index 00000000000..48ecd88accb --- /dev/null +++ b/rustfmt-core/tests/source/configs/wrap_comments/false.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +} diff --git a/rustfmt-core/tests/source/configs/wrap_comments/true.rs b/rustfmt-core/tests/source/configs/wrap_comments/true.rs new file mode 100644 index 00000000000..39a79a4cacc --- /dev/null +++ b/rustfmt-core/tests/source/configs/wrap_comments/true.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +} + +fn code_block() { + // ```rust + // let x = 3; + // + // println!("x = {}", x); + // ``` +} diff --git a/rustfmt-core/tests/source/control-brace-style-always-next-line.rs b/rustfmt-core/tests/source/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..9079fb46c0c --- /dev/null +++ b/rustfmt-core/tests/source/control-brace-style-always-next-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop { + (); + (); + } + + + 'label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/rustfmt-core/tests/source/control-brace-style-always-same-line.rs b/rustfmt-core/tests/source/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..1c8f487e7cd --- /dev/null +++ b/rustfmt-core/tests/source/control-brace-style-always-same-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + + 'label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/rustfmt-core/tests/source/doc.rs b/rustfmt-core/tests/source/doc.rs new file mode 100644 index 00000000000..e03933e4516 --- /dev/null +++ b/rustfmt-core/tests/source/doc.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true + +// sadfsdfa +//sdffsdfasdf diff --git a/rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs b/rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs new file mode 100644 index 00000000000..7b4870fc65a --- /dev/null +++ b/rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs @@ -0,0 +1,54 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs b/rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs new file mode 100644 index 00000000000..41f5305bf8c --- /dev/null +++ b/rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs @@ -0,0 +1,54 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs b/rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs new file mode 100644 index 00000000000..3b885b3faaa --- /dev/null +++ b/rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs @@ -0,0 +1,54 @@ +// rustfmt-control_brace_style: ClosingNextLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/rustfmt-core/tests/source/empty_file.rs b/rustfmt-core/tests/source/empty_file.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/rustfmt-core/tests/source/enum.rs b/rustfmt-core/tests/source/enum.rs new file mode 100644 index 00000000000..f3dbae4b84d --- /dev/null +++ b/rustfmt-core/tests/source/enum.rs @@ -0,0 +1,194 @@ +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Enums test + +#[atrr] +pub enum Test { + A, B(u32, + A /* comment */, + SomeType), + /// Doc comment + C, +} + +pub enum Foo<'a, Y: Baz> where X: Whatever +{ A, } + +enum EmtpyWithComment { + // Some comment +} + +// C-style enum +enum Bar { + A = 1, + #[someAttr(test)] + B = 2, // comment + C, +} + +enum LongVariants { +First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment +VARIANT), + // This is the second variant + Second +} + +enum StructLikeVariants { + Normal(u32, String, ), + StructLike { x: i32, // Test comment + // Pre-comment + #[Attr50] y: SomeType, // Aanother Comment + }, SL { a: A } +} + +enum X { + CreateWebGLPaintTask(Size2D, GLContextAttributes, IpcSender, usize), String>>), // This is a post comment +} + +pub enum EnumWithAttributes { + //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // Pre Comment + #[rustfmt_skip] + SkippedItem(String,String,), // Post-comment + #[another_attr] + #[attr2] + ItemStruct {x: usize, y: usize}, // Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // And another + ForcedPreflight // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +pub enum SingleTuple { + // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + Match(usize, usize, String) // Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +pub enum SingleStruct { + Match {name: String, loc: usize} // Post-comment +} + +pub enum GenericEnum +where I: Iterator { + // Pre Comment + Left {list: I, root: T}, // Post-comment + Right {list: I, root: T} // Post Comment +} + + +enum EmtpyWithComment { + // Some comment +} + +enum TestFormatFails { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +fn nested_enum_test() { + if true { + enum TestEnum { + One(usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize,), // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA + Two // AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA + } + enum TestNestedFormatFail { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + } +} + + pub struct EmtpyWithComment { + // FIXME: Implement this struct +} + +// #1115 +pub enum Bencoding<'i> { + Str(&'i [u8]), + Int(i64), + List(Vec>), + /// A bencoded dict value. The first element the slice of bytes in the source that the dict is + /// composed of. The second is the dict, decoded into an ordered map. + // TODO make Dict "structlike" AKA name the two values. + Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), +} + +// #1261 +pub enum CoreResourceMsg { + SetCookieForUrl( + ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource + ), +} + +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { Foo } + +// #1046 +pub enum Entry<'a, K: 'a, V: 'a> { + Vacant( + #[ stable( feature = "rust1", since = "1.0.0" ) ] VacantEntry<'a, K, V>, + ), + Occupied( + #[ stable( feature = "rust1", since = "1.0.0" ) ] + OccupiedEntry<'a, K, V>, + ), +} + +// #2081 +pub enum ForegroundColor { + CYAN = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, +} + +// #2098 +pub enum E<'a> { + V ( < std::slice::Iter<'a, Xxxxxxxxxxxxxx> as Iterator> :: Item ) , +} + +// #1809 +enum State { + TryRecv { + pos: usize, + lap: u8, + closed_count: usize, + }, + Subscribe { pos: usize }, + IsReady { pos: usize, ready: bool }, + Unsubscribe { + pos: usize, + lap: u8, + id_woken: usize, + }, + FinalTryRecv { pos: usize, id_woken: usize }, + TimedOut, + Disconnected, +} + +// #2190 +#[derive(Debug, Fail)] +enum AnError { + #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] + UnexpectedSingleToken { token: syn::Token }, +} + +// #2193 +enum WidthOf101 { + #[fail(display = ".....................................................")] Io(::std::io::Error), + #[fail(display = ".....................................................")] Ioo(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), +} + +// #2389 +pub enum QlError { + #[fail(display = "Parsing error: {}", 0)] LexError(parser::lexer::LexError), + #[fail(display = "Parsing error: {:?}", 0)] ParseError(parser::ParseError), + #[fail(display = "Validation error: {:?}", 0)] ValidationError(Vec), + #[fail(display = "Execution error: {}", 0)] ExecutionError(String), + // (from, to) + #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), + // (kind, input, expected) + #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), +} diff --git a/rustfmt-core/tests/source/expr-block.rs b/rustfmt-core/tests/source/expr-block.rs new file mode 100644 index 00000000000..a2e7ac8fc44 --- /dev/null +++ b/rustfmt-core/tests/source/expr-block.rs @@ -0,0 +1,286 @@ +// rustfmt-indent_style: Block +// Test expressions with block formatting. + +fn arrays() { + [ ]; + let empty = []; + + let foo = [a_long_name, a_very_lng_name, a_long_name]; + + let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name]; + + vec![a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name]; + + [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name] +} + +fn arrays() { + let x = [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; + + let a =WeightedChoice::new(&mut [Weighted { + weight: x, + item: 0, + }, + Weighted { + weight: 1, + item: 1, + }, + Weighted { + weight: x, + item: 2, + }, + Weighted { + weight: 1, + item: 3, + }]); + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; + + [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] +} + +fn function_calls() { + let items = itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo(), + span.hi()); + + itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo(), + span.hi()) +} + +fn macros() { + baz!(do_not, add, trailing, commas, inside, of, function, like, macros, even, if_they, are, long); + + baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); + + let _ = match option { + None => baz!(function, like, macro_as, expression, which, is, loooooooooooooooong), + Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), + }; +} + +fn issue_1450() { + if selfstate + .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( + STATE_PARKED, + STATE_UNPARKED, + Release, + Relaxed, + Release, + Relaxed, + ) + .is_ok() { + return; + } +} + +fn foo() { + if real_total <= limit && !pre_line_comments && + !items.into_iter().any(|item| item.as_ref().is_multiline()) { + DefinitiveListTactic::Horizontal + } +} + +fn combine_block() { + foo( + Bar { + x: value, + y: value2, + }, + ); + + foo((Bar { + x: value, + y: value2, + },)); + + foo((1, 2, 3, Bar { + x: value, + y: value2, + })); + + foo((1, 2, 3, |x| { + let y = x + 1; + let z = y + 1; + z + })); + + let opt = Some( + Struct( + long_argument_one, + long_argument_two, + long_argggggggg, + ), + ); + + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); + + Ok( + some_function( + lllllllllong_argument_one, + lllllllllong_argument_two, + lllllllllllllllllllllllllllllong_argument_three, + ), + ); + + foo( + thing, + bar( + param2, + pparam1param1param1param1param1param1param1param1param1param1aram1, + param3, + ), + ); + + foo.map_or( + || { + Ok( + SomeStruct { + f1: 0, + f2: 0, + f3: 0, + }, + ) + }, + ); + + match opt { + Some(x) => somefunc(anotherfunc( + long_argument_one, + long_argument_two, + long_argument_three, + )), + Some(x) => |x| { + let y = x + 1; + let z = y + 1; + z + }, + Some(x) => (1, 2, |x| { + let y = x + 1; + let z = y + 1; + z + }), + Some(x) => SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }, + None => Ok(SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }), + }; + + match x { + y => func( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ), + _ => func( + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzz, + ), + } +} + +fn issue_1862() { + foo( + /* bar = */ None , + something_something, + /* baz = */ None , + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ None , + /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , + ) +} + +fn issue_1878() { + let channel: &str = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; +} diff --git a/rustfmt-core/tests/source/expr.rs b/rustfmt-core/tests/source/expr.rs new file mode 100644 index 00000000000..f87c950735f --- /dev/null +++ b/rustfmt-core/tests/source/expr.rs @@ -0,0 +1,372 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// Test expressions + +fn foo() -> bool { + let boxed: Box = box 5; + let referenced = &5 ; + + let very_long_variable_name = ( a + first + simple + test ); + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + + let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - + function_call(x, *very_long_pointer, y)) + + 1000 ; + +some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 + - 50000 * sqrt(-1), + trivial_value); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; + + { for _ in 0..10 {} } + + {{{{}}}} + + if 1 + 2 > 0 { let result = 5; result } else { 4}; + + if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + // Nothing + } + + if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + + 2 + 3 { + } + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} + + if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + + 2 + 3 { + } + + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = item.node + { + // nothing + } + + let test = if true { 5 } else { 3 }; + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + // Check subformatting + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } +} + +fn bar() { + let range = ( 111111111 + 333333333333333333 + 1111 + 400000000000000000) .. (2222 + 2333333333333333); + + let another_range = 5..some_func( a , b /* comment */); + + for _ in 1 ..{ call_forever(); } + + syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 }); + + let third = ..10; + let infi_range = .. ; + let foo = 1..; + let bar = 5 ; + let nonsense = (10 .. 0)..(0..10); + + loop{if true {break}} + + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + a); +} + +fn baz() { + unsafe /* {}{}{}{{{{}} */ { + let foo = 1u32; + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} + + unsafe // So this is a very long comment. + // Multi-line, too. + // Will it still format correctly? + { + } + + unsafe { + // Regular unsafe block + } + + unsafe { + foo() + } + + unsafe { + foo(); + } + + // #2289 + let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; + let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; + let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; + let identifier_3 = unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; +} + +// Test some empty blocks. +fn qux() { + {} + // FIXME this one could be done better. + { /* a block with a comment */ } + { + + } + { + // A block with a comment. + } +} + +fn issue227() { + { + let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); + } +} + +fn issue184(source: &str) { + for c in source.chars() { + if index < 'a' { + continue; + } + } +} + +fn arrays() { + let x = [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; + + let a =WeightedChoice::new(&mut [Weighted { + weightweight: x, + item: 0, + }, + Weighted { + weightweight: 1, + item: 1, + }, + Weighted { + weightweight: x, + item: 2, + }, + Weighted { + weightweight: 1, + item: 3, + }]); + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; + + [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] +} + +fn returns() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && return; + + return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +} + +fn addrof() { + & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); +} + +fn casts() { + fn unpack(packed: u32) -> [u16; 2] { + [ + (packed >> 16) as u16, + (packed >> 0) as u16, + ] + } + + let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx + as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; + let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; +} + +fn indices() { + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; + let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; + let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; +} + +fn repeats() { + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc; x + y + z ]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz ]; +} + +fn blocks() { + if 1 + 1 == 2 { + println!("yay arithmetix!"); + }; +} + +fn issue767() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} + +fn ranges() { + let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ..= bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let z = ..= x ; + + // #1766 + let x = [0. ..10.0]; + let x = [0. ..=10.0]; + + a ..= b + + // the expr below won't compile because inclusive ranges need a defined end + // let a = 0 ..= ; +} + +fn if_else() { + let exact = diff / + (if size == 0 { + 1 +} else { + size +}); + + let cx = tp1.x + + any * radius * + if anticlockwise { + 1.0 + } else { + -1.0 + }; +} + +fn complex_if_else() { + if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { + yo(); + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { + yo(); + } +} + +fn issue1106() { + { + if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map.expect_item(enum_node_id).node { + } + } + + for entry in + WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) { + } +} + +fn issue1570() { + a_very_long_function_name({some_func(1, {1})}) +} + +fn issue1714() { + v = &mut {v}[mid..]; + let (left, right) = {v}.split_at_mut(mid); +} + +// Multi-lined index should be put on the next line if it fits in one line. +fn issue1749() { + { + { + { + if self.shape[(r as f32 + self.x_offset) as usize][(c as f32 + self.y_offset) as usize] != 0 { + // hello + } + } + } + } +} + +// #1172 +fn newlines_between_list_like_expr() { + foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ); + + vec![ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ]; + + match x { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy | + + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), + _ => bar(), + }; +} + +fn issue2178() { + Ok(result.iter().map(|item| ls_util::rls_to_location(item)).collect()) +} diff --git a/rustfmt-core/tests/source/extern.rs b/rustfmt-core/tests/source/extern.rs new file mode 100644 index 00000000000..187e698607a --- /dev/null +++ b/rustfmt-core/tests/source/extern.rs @@ -0,0 +1,60 @@ +// rustfmt-normalize_comments: true + + extern crate foo ; + extern crate foo as bar ; + +extern crate futures; +extern crate dotenv; +extern crate chrono; + +extern crate foo; +extern crate bar; + +// #2315 +extern crate proc_macro2; +extern crate proc_macro; + + extern "C" { + fn c_func(x: *mut *mut libc::c_void); + + fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); + + #[test123] + fn foo() -> uint64_t; + +pub fn bar() ; + } + +extern { + fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, devNr: c_uint, wildcard: c_char) -> TDMR_ERROR; + + fn quux() -> (); // Post comment + + pub type + Foo; + + type Bar; +} + +extern "Rust" { static ext: u32; + // Some comment. + pub static mut var : SomeType ; } + +extern "C" { + fn syscall(number: libc::c_long /* comment 1 */, /* comm 2 */ ... /* sup? */) -> libc::c_long; + + fn foo (x: *const c_char , ... ) -> +libc::c_long; + } + + extern { + pub fn freopen(filename: *const c_char, mode: *const c_char + , mode2: *const c_char + , mode3: *const c_char, + file: *mut FILE) + -> *mut FILE; + } + +extern { + +} diff --git a/rustfmt-core/tests/source/extern_not_explicit.rs b/rustfmt-core/tests/source/extern_not_explicit.rs new file mode 100644 index 00000000000..9d6c4c2a1cd --- /dev/null +++ b/rustfmt-core/tests/source/extern_not_explicit.rs @@ -0,0 +1,14 @@ +// rustfmt-force_explicit_abi: false + + extern "C" { + fn some_fn() -> (); + } + + extern "C" fn sup() { + + } + +type funky_func = extern "C" fn (unsafe extern "rust-call" fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8); diff --git a/rustfmt-core/tests/source/file-lines-1.rs b/rustfmt-core/tests/source/file-lines-1.rs new file mode 100644 index 00000000000..0164e30a854 --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-1.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/source/file-lines-2.rs b/rustfmt-core/tests/source/file-lines-2.rs new file mode 100644 index 00000000000..6f44ec6e69d --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-2.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/source/file-lines-3.rs b/rustfmt-core/tests/source/file-lines-3.rs new file mode 100644 index 00000000000..c4f3e21b1ae --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-3.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] +// rustfmt-error_on_line_overflow: false + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/source/file-lines-4.rs b/rustfmt-core/tests/source/file-lines-4.rs new file mode 100644 index 00000000000..83928bf6fec --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-4.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [] +// (Test that nothing is formatted if an empty array is specified.) + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + // aaaaaaaaaaaaa + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/source/file-lines-5.rs b/rustfmt-core/tests/source/file-lines-5.rs new file mode 100644 index 00000000000..8ec2c67bc44 --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-5.rs @@ -0,0 +1,17 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] + +struct A { +t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + fn baz() { + let j = 15; + } +} diff --git a/rustfmt-core/tests/source/file-lines-6.rs b/rustfmt-core/tests/source/file-lines-6.rs new file mode 100644 index 00000000000..2eacc8a0e75 --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-6.rs @@ -0,0 +1,18 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + + fn baz() { +/// + let j = 15; + } +} diff --git a/rustfmt-core/tests/source/file-lines-item.rs b/rustfmt-core/tests/source/file-lines-item.rs new file mode 100644 index 00000000000..0ed4b93df5f --- /dev/null +++ b/rustfmt-core/tests/source/file-lines-item.rs @@ -0,0 +1,22 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] +// rustfmt-reorder_imports: true + +use foo::{c, b, a}; +use bar; + +fn foo() { + bar ( ) ; +} + +impl Drop for Context { + fn drop(&mut self) { + } +} + +impl Bar for Baz { + fn foo() { + bar( + baz, // Who knows? + ) + } +} diff --git a/rustfmt-core/tests/source/fn-custom-2.rs b/rustfmt-core/tests/source/fn-custom-2.rs new file mode 100644 index 00000000000..72d841544a8 --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom-2.rs @@ -0,0 +1,36 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); +} + +fn baz() where X: TTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); + } + + fn baz() where X: TTTTTTTT { + baz(); + } +} + +struct Foo { + foo: Foo, +} diff --git a/rustfmt-core/tests/source/fn-custom-3.rs b/rustfmt-core/tests/source/fn-custom-3.rs new file mode 100644 index 00000000000..9934fb61efd --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom-3.rs @@ -0,0 +1,32 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); + } +} + +struct Foo { + foo: Foo, +} diff --git a/rustfmt-core/tests/source/fn-custom-4.rs b/rustfmt-core/tests/source/fn-custom-4.rs new file mode 100644 index 00000000000..01c00aecb86 --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom-4.rs @@ -0,0 +1,14 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux(a: Aaaaaaaaaaaaaaaaa) where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} diff --git a/rustfmt-core/tests/source/fn-custom-6.rs b/rustfmt-core/tests/source/fn-custom-6.rs new file mode 100644 index 00000000000..8e8bb6c274e --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom-6.rs @@ -0,0 +1,41 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/rustfmt-core/tests/source/fn-custom-7.rs b/rustfmt-core/tests/source/fn-custom-7.rs new file mode 100644 index 00000000000..f7670e07fc8 --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom-7.rs @@ -0,0 +1,25 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block +// rustfmt-fn_args_density: Vertical +// rustfmt-brace_style: AlwaysNextLine + +// Case with only one variable. +fn foo(a: u8) -> u8 { + bar() +} + +// Case with 2 variables and some pre-comments. +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +// Case with 2 variables and some post-comments. +fn foo(/* Comment 1 */ a: u8, /* Comment 2 */ b: u8) -> u8 { + bar() +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/rustfmt-core/tests/source/fn-custom-8.rs b/rustfmt-core/tests/source/fn-custom-8.rs new file mode 100644 index 00000000000..d3deb20a51c --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom-8.rs @@ -0,0 +1,49 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} + +trait Test { + fn foo( + a: u8) { + + } + + fn bar(a: u8) + -> String { + + } + + fn bar(a: u8) -> String where Foo: foooo, Bar: barrr {} +} diff --git a/rustfmt-core/tests/source/fn-custom.rs b/rustfmt-core/tests/source/fn-custom.rs new file mode 100644 index 00000000000..b8d734bfbaf --- /dev/null +++ b/rustfmt-core/tests/source/fn-custom.rs @@ -0,0 +1,13 @@ +// rustfmt-fn_args_density: Compressed +// Test some of the ways function signatures can be customised. + +// Test compressed layout of args. +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } +} diff --git a/rustfmt-core/tests/source/fn-simple.rs b/rustfmt-core/tests/source/fn-simple.rs new file mode 100644 index 00000000000..f1ce503ab0a --- /dev/null +++ b/rustfmt-core/tests/source/fn-simple.rs @@ -0,0 +1,66 @@ +// rustfmt-normalize_comments: true + +fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ + ,response: NoWay /* hose */) { +fn op(x: Typ, key : &[u8], upd : Box) -> (memcache::Status, Result>)>) -> MapResult {} + + "cool"} + + +fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* triple, even */*/*/, +// Does this work? +y: World +) { + simple(/* does this preserve comments now? */ 42, NoWay) +} + +fn generic(arg: T) -> &SomeType + where T: Fn(// First arg + A, + // Second argument + B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { + arg(a, b, c, d, e) +} + +fn foo() -> ! {} + +pub fn http_fetch_async(listener:Box< AsyncCORSResponseListener+Send >, script_chan: Box) { +} + +fn some_func>(val:T){} + +fn zzzzzzzzzzzzzzzzzzzz + (selff: Type, mut handle: node::Handle>, Type, NodeType>) + -> SearchStack<'a, K, V, Type, NodeType>{ +} + +unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8) { + let f: fn ( _ , _ ) -> _ = panic!() ; +} + +pub fn start_export_thread(database: &Database, crypto_scheme: &C, block_size: usize, source_path: &Path) -> BonzoResult> {} + +pub fn waltz(cwd: &Path) -> CliAssert { + { + { + formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig); + } + } +} + +// #2003 +mod foo { + fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() { + foo(); + } +} + +// #2082 +pub(crate) fn init() {} + +crate fn init() {} diff --git a/rustfmt-core/tests/source/fn-single-line.rs b/rustfmt-core/tests/source/fn-single-line.rs new file mode 100644 index 00000000000..6d7f764d280 --- /dev/null +++ b/rustfmt-core/tests/source/fn-single-line.rs @@ -0,0 +1,79 @@ +// rustfmt-fn_single_line: true +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/rustfmt-core/tests/source/fn_args_density-vertical.rs b/rustfmt-core/tests/source/fn_args_density-vertical.rs new file mode 100644 index 00000000000..b61c337dfb9 --- /dev/null +++ b/rustfmt-core/tests/source/fn_args_density-vertical.rs @@ -0,0 +1,33 @@ +// rustfmt-fn_args_density: Vertical + +// Empty list should stay on one line. +fn do_bar( + +) -> u8 { + bar() +} + +// A single argument should stay on the same line. +fn do_bar( + a: u8) -> u8 { + bar() +} + +// Multiple arguments should each get their own line. +fn do_bar(a: u8, mut b: u8, c: &u8, d: &mut u8, closure: &Fn(i32) -> i32) -> i32 { + // This feature should not affect closures. + let bar = |x: i32, y: i32| -> i32 { x + y }; + bar(a, b) +} + +// If the first argument doesn't fit on the same line with the function name, +// the whole list should probably be pushed to the next line with hanging +// indent. That's not what happens though, so check current behaviour instead. +// In any case, it should maintain single argument per line. +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, c: u8, d: u8) { + this(); + that(); + the_other_thing(); +} diff --git a/rustfmt-core/tests/source/fn_args_indent-block.rs b/rustfmt-core/tests/source/fn_args_indent-block.rs new file mode 100644 index 00000000000..b056fcb56fe --- /dev/null +++ b/rustfmt-core/tests/source/fn_args_indent-block.rs @@ -0,0 +1,78 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { + bar() +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T where X: Foooo, Y: Baaar { + foo(); +} + +fn foo() where X: Foooo { +} + +fn foo() where X: Foooo, Y: Baaar { +} + +fn foo() -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) { + foo(); +} + +fn foo() { + foo(); +} + +fn foo() { + foo(); +} + +fn foo() { + foo(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} +} + +fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { + foo(); +} + +fn foo() -> (Looooooooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiiiiiiis, Loooooooooooooooooooooong) { + foo(); +} diff --git a/rustfmt-core/tests/source/hard-tabs.rs b/rustfmt-core/tests/source/hard-tabs.rs new file mode 100644 index 00000000000..b8fd09f8792 --- /dev/null +++ b/rustfmt-core/tests/source/hard-tabs.rs @@ -0,0 +1,85 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-hard_tabs: true +// rustfmt-error_on_line_overflow: false + +fn main() { +let x = Bar; + +let y = Foo {a: x }; + +Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + +fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) {} + +let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + +if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 ++ 2 + 3 { +} + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } + +unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} + +unsafe // So this is a very long comment. + // Multi-line, too. + // Will it still format correctly? +{ +} + +let chain = funktion_kall().go_to_next_line_with_tab().go_to_next_line_with_tab().go_to_next_line_with_tab(); + +let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; + +fn generic(arg: T) -> &SomeType + where T: Fn(// First arg + A, + // Second argument + B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { + arg(a, b, c, d, e) +} + + loong_func().quux(move || { + if true { + 1 + } else { + 2 + } + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + a.b + .c + .d(); + + x().y(|| { + match cond() { + true => (), + false => (), + } + }); +} + +// #2296 +impl Foo { + // a comment + // on multiple lines + fn foo() { + // another comment + // on multiple lines + let x = true; + } +} diff --git a/rustfmt-core/tests/source/hello.rs b/rustfmt-core/tests/source/hello.rs new file mode 100644 index 00000000000..f892e6debb1 --- /dev/null +++ b/rustfmt-core/tests/source/hello.rs @@ -0,0 +1,6 @@ +// rustfmt-config: small_tabs.toml +// rustfmt-target: hello.rs + +// Smoke test - hello world. + +fn main() { println!("Hello world!"); } diff --git a/rustfmt-core/tests/source/hello2.rs b/rustfmt-core/tests/source/hello2.rs new file mode 100644 index 00000000000..48af7de3887 --- /dev/null +++ b/rustfmt-core/tests/source/hello2.rs @@ -0,0 +1,8 @@ +// rustfmt-config: small_tabs.toml +// rustfmt-target: hello.rs + +// Smoke test - hello world. + +fn main( ) { +println!("Hello world!"); +} diff --git a/rustfmt-core/tests/source/immovable_generators.rs b/rustfmt-core/tests/source/immovable_generators.rs new file mode 100644 index 00000000000..c57a1e14483 --- /dev/null +++ b/rustfmt-core/tests/source/immovable_generators.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +unsafe fn foo() { + let mut ga = static || { + yield 1; + }; +} diff --git a/rustfmt-core/tests/source/impls.rs b/rustfmt-core/tests/source/impls.rs new file mode 100644 index 00000000000..ca8e486646a --- /dev/null +++ b/rustfmt-core/tests/source/impls.rs @@ -0,0 +1,154 @@ +// rustfmt-normalize_comments: true +impl Foo for Bar { fn foo() { "hi" } } + +pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; + // Comment 1 + fn foo() { "hi" } + // Comment 2 + fn foo() { "hi" } + // Comment 3 +} + +pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { + fn foo() { "hi" } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> +{ + fn foo() { "hi" } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> +{ + fn foo() { "hi" } +} + +impl Foo for Bar where T: Baz +{ +} + +impl Foo for Bar where T: Baz { /* Comment */ } + +impl Foo { + fn foo() {} +} + +impl Boo { + + // BOO + fn boo() {} + // FOO + + + +} + +mod a { + impl Foo { + // Hello! + fn foo() {} + } +} + + +mod b { + mod a { + impl Foo { + fn foo() {} + } + } +} + +impl Foo { add_fun!(); } + +impl Blah { + fn boop() {} + add_fun!(); +} + +impl X { fn do_parse( mut self : X ) {} } + +impl Y5000 { + fn bar(self: X< 'a , 'b >, y: Y) {} + + fn bad(&self, ( x, y): CoorT) {} + + fn turbo_bad(self: X< 'a , 'b > , ( x, y): CoorT) { + + } +} + +pub impl Foo for Bar where T: Foo +{ + fn foo() { "hi" } +} + +pub impl Foo for Bar where T: Foo, Z: Baz {} + +mod m { + impl PartialEq for S where T: PartialEq { + fn eq(&self, other: &Self) { + true + } + } + + impl PartialEq for S where T: PartialEq { } + } + +impl Handle, HandleType> { +} + +impl PartialEq for Handle, HandleType> { +} + +mod x { + impl Foo + where A: 'static, + B: 'static, + C: 'static, + D: 'static { } +} + +impl Issue1249 { + // Creates a new flow constructor. + fn foo() {} +} + +// #1600 +impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { + fn drop() {} +} + +// #1168 +pub trait Number: Copy + Eq + Not + Shl + + Shr + + BitAnd + BitOr + BitAndAssign + BitOrAssign + + + +{ + // test + fn zero() -> Self; +} + +// #1642 +pub trait SomeTrait : Clone + Eq + PartialEq + Ord + PartialOrd + Default + Hash + Debug + Display + Write + Read + FromStr { + // comment +} + +// #1995 +impl Foo { + fn f( + S { + aaaaaaaaaa: aaaaaaaaaa, + bbbbbbbbbb: bbbbbbbbbb, + cccccccccc: cccccccccc, + }: S + ) -> u32{ + 1 + } +} diff --git a/rustfmt-core/tests/source/imports-reorder-lines-and-items.rs b/rustfmt-core/tests/source/imports-reorder-lines-and-items.rs new file mode 100644 index 00000000000..3c71f9984fe --- /dev/null +++ b/rustfmt-core/tests/source/imports-reorder-lines-and-items.rs @@ -0,0 +1,10 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true + +/// This comment should stay with `use std::str;` +use std::str; +use std::cmp::{d, c, b, a}; +use std::ddd::aaa; +use std::ddd::{d as p, c as g, b, a}; +// This comment should stay with `use std::ddd:bbb;` +use std::ddd::bbb; diff --git a/rustfmt-core/tests/source/imports-reorder-lines.rs b/rustfmt-core/tests/source/imports-reorder-lines.rs new file mode 100644 index 00000000000..a855a964235 --- /dev/null +++ b/rustfmt-core/tests/source/imports-reorder-lines.rs @@ -0,0 +1,34 @@ +// rustfmt-reorder_imports: true + +use std::str; +use std::cmp::{d, c, b, a}; +use std::cmp::{b, e, g, f}; +use std::ddd::aaa; +// This comment should stay with `use std::ddd;` +use std::ddd; +use std::ddd::bbb; + +mod test { +} + +use aaa::bbb; +use aaa; +use aaa::*; + +mod test {} +// If item names are equal, order by rename + +use test::{a as bb, b}; +use test::{a as aa, c}; + +mod test {} +// If item names are equal, order by rename - no rename comes before a rename + +use test::{a as bb, b}; +use test::{a, c}; + +mod test {} +// `self` always comes first + +use test::{a as aa, c}; +use test::{self as bb, b}; diff --git a/rustfmt-core/tests/source/imports-reorder.rs b/rustfmt-core/tests/source/imports-reorder.rs new file mode 100644 index 00000000000..200cad2d13c --- /dev/null +++ b/rustfmt-core/tests/source/imports-reorder.rs @@ -0,0 +1,6 @@ +// rustfmt-normalize_comments: true +// rustfmt-reorder_imported_names: true + +use path::{C,/*A*/ A, B /* B */, self /* self */}; + +use {ab, ac, aa, Z, b}; diff --git a/rustfmt-core/tests/source/imports.rs b/rustfmt-core/tests/source/imports.rs new file mode 100644 index 00000000000..73d1419f47d --- /dev/null +++ b/rustfmt-core/tests/source/imports.rs @@ -0,0 +1,89 @@ +// rustfmt-normalize_comments: true +// rustfmt-error_on_line_overflow: false + +// Imports. + +// Long import. +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; +use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; + +use list::{ + // Some item + SomeItem /* Comment */, /* Another item */ AnotherItem /* Another Comment */, // Last Item + LastItem +}; + +use test::{ Other /* C */ , /* A */ self /* B */ }; + +use syntax::{self}; +use {/* Pre-comment! */ + Foo, Bar /* comment */}; +use Foo::{Bar, Baz}; +pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; +use syntax::some::{}; + +use self; +use std::io::{self}; +use std::io::self; + +mod Foo { + pub use syntax::ast::{ + ItemForeignMod, + ItemImpl, + ItemMac, + ItemMod, + ItemStatic, + ItemDefaultImpl + }; + + mod Foo2 { + pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; + } +} + +fn test() { +use Baz::*; + use Qux; +} + +// Simple imports +use foo::bar::baz as baz ; +use bar::quux as kaas; +use foo; + +// With aliases. +use foo::{self as bar, baz}; +use foo::{self as bar}; +use foo::{qux as bar}; +use foo::{baz, qux as bar}; + +// With absolute paths +use ::foo; +use ::foo::{Bar}; +use ::foo::{Bar, Baz}; +use ::{Foo}; +use ::{Bar, Baz}; + +// Root globs +use *; +use ::*; + +// spaces used to cause glob imports to disappear (#1356) +use super:: * ; +use foo::issue_1356:: * ; + +// We shouldn't remove imports which have attributes attached (#1858) +#[cfg(unix)] +use self::unix::{}; + +// nested imports +use foo::{a, bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}, b, boo, c,}; + +use fooo::{baar::{foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}}, z, bar, bar::*, x, y}; + +// nested imports with a single sub-tree. +use a::{b::{c::*}}; +use a::{b::{c::{}}}; +use a::{b::{c::d}}; +use a::{b::{c::{xxx, yyy, zzz}}}; diff --git a/rustfmt-core/tests/source/issue-1021.rs b/rustfmt-core/tests/source/issue-1021.rs new file mode 100644 index 00000000000..380e24cc0b0 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1021.rs @@ -0,0 +1,22 @@ +// rustfmt-normalize_comments: true +fn main() { + match x { + S(true , .., true ) => (), + S(true , .. ) => (), + S(.., true ) => (), + S( .. ) => (), + S(_) => (), + S(/* .. */ .. ) => (), + S(/* .. */ .., true ) => (), + } + + match y { + (true , .., true ) => (), + (true , .. ) => (), + (.., true ) => (), + ( .. ) => (), + (_,) => (), + (/* .. */ .. ) => (), + (/* .. */ .., true ) => (), + } +} diff --git a/rustfmt-core/tests/source/issue-1049.rs b/rustfmt-core/tests/source/issue-1049.rs new file mode 100644 index 00000000000..bcfba41e768 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1049.rs @@ -0,0 +1,18 @@ +// Test overlong function signature +pub unsafe fn reborrow_mut(&mut X: Abcde) -> Handle, HandleType> { +} + +pub fn merge(mut X: Abcdef) -> Handle, K, V, marker::Internal>, marker::Edge> { +} + +impl Handle { + pub fn merge(a: Abcd) -> Handle, K, V, marker::Internal>, marker::Edge> { + } +} + +// Long function without return type that should not be reformatted. +fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} diff --git a/rustfmt-core/tests/source/issue-1111.rs b/rustfmt-core/tests/source/issue-1111.rs new file mode 100644 index 00000000000..2e1a89ad78e --- /dev/null +++ b/rustfmt-core/tests/source/issue-1111.rs @@ -0,0 +1 @@ +use bar; diff --git a/rustfmt-core/tests/source/issue-1120.rs b/rustfmt-core/tests/source/issue-1120.rs new file mode 100644 index 00000000000..e85c9af99d4 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1120.rs @@ -0,0 +1,9 @@ +// rustfmt-reorder_imports: true + +// Ensure that a use at the start of an inline module is correctly formatted. +mod foo {use bar;} + +// Ensure that an indented `use` gets the correct indentation. +mod foo { + use bar; +} diff --git a/rustfmt-core/tests/source/issue-1124.rs b/rustfmt-core/tests/source/issue-1124.rs new file mode 100644 index 00000000000..69aa1bb1c59 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1124.rs @@ -0,0 +1,16 @@ +// rustfmt-reorder_imports: true +// rustfmt-normalize_comments: true + +use d; use c; use b; use a; +// The previous line has a space after the `use a;` + +mod a { use d; use c; use b; use a; } + +use z; + +use y; + + + +use x; +use a; \ No newline at end of file diff --git a/rustfmt-core/tests/source/issue-1127.rs b/rustfmt-core/tests/source/issue-1127.rs new file mode 100644 index 00000000000..9996c194818 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1127.rs @@ -0,0 +1,23 @@ +// rustfmt-max_width:120 +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true + +fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { + 42 +} + +enum TestEnum { + AVeryVeryLongEnumName, + AnotherVeryLongEnumName, + TheLastVeryLongEnumName, +} + +fn main() { + let var = TestEnum::AVeryVeryLongEnumName; + let num = match var { + TestEnum::AVeryVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::AnotherVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::TheLastVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + }; +} + diff --git a/rustfmt-core/tests/source/issue-1158.rs b/rustfmt-core/tests/source/issue-1158.rs new file mode 100644 index 00000000000..6742e17459e --- /dev/null +++ b/rustfmt-core/tests/source/issue-1158.rs @@ -0,0 +1,3 @@ +trait T { + itemmacro!(this, is.now() .formatted(yay)); +} diff --git a/rustfmt-core/tests/source/issue-1177.rs b/rustfmt-core/tests/source/issue-1177.rs new file mode 100644 index 00000000000..3ac423c5aef --- /dev/null +++ b/rustfmt-core/tests/source/issue-1177.rs @@ -0,0 +1,7 @@ +// rustfmt-normalize_comments: true +fn main() { + // Line Comment + /* Block Comment */ + + let d = 5; +} diff --git a/rustfmt-core/tests/source/issue-1192.rs b/rustfmt-core/tests/source/issue-1192.rs new file mode 100644 index 00000000000..4e39fbf9a36 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1192.rs @@ -0,0 +1,3 @@ +fn main() { + assert!(true) ; +} diff --git a/rustfmt-core/tests/source/issue-1211.rs b/rustfmt-core/tests/source/issue-1211.rs new file mode 100644 index 00000000000..5818736bf6b --- /dev/null +++ b/rustfmt-core/tests/source/issue-1211.rs @@ -0,0 +1,15 @@ +fn main() { + for iface in &ifaces { + match iface.addr { + get_if_addrs::IfAddr::V4(ref addr) => { + match addr.broadcast { + Some(ip) => { + sock.send_to(&buf, (ip, 8765)).expect("foobar"); + } + _ => () + } + } + _ => () + }; + } +} diff --git a/rustfmt-core/tests/source/issue-1216.rs b/rustfmt-core/tests/source/issue-1216.rs new file mode 100644 index 00000000000..d727c158ab8 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1216.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +enum E { + A, //* I am not a block comment (caused panic) + B, +} diff --git a/rustfmt-core/tests/source/issue-1239.rs b/rustfmt-core/tests/source/issue-1239.rs new file mode 100644 index 00000000000..913058257ed --- /dev/null +++ b/rustfmt-core/tests/source/issue-1239.rs @@ -0,0 +1,9 @@ +fn foo() { + let with_alignment = if condition__uses_alignment_for_first_if__0 || + condition__uses_alignment_for_first_if__1 || + condition__uses_alignment_for_first_if__2 { + } else if condition__no_alignment_for_later_else__0 || + condition__no_alignment_for_later_else__1 || + condition__no_alignment_for_later_else__2 { + }; +} diff --git a/rustfmt-core/tests/source/issue-1278.rs b/rustfmt-core/tests/source/issue-1278.rs new file mode 100644 index 00000000000..e25376561a9 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1278.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style = "block" + +#![feature(pub_restricted)] + +mod inner_mode { + pub(super) fn func_name(abc: i32) -> i32 { + abc + } +} diff --git a/rustfmt-core/tests/source/issue-1350.rs b/rustfmt-core/tests/source/issue-1350.rs new file mode 100644 index 00000000000..1baa1985a7e --- /dev/null +++ b/rustfmt-core/tests/source/issue-1350.rs @@ -0,0 +1,16 @@ +// rustfmt-max_width: 120 +// rustfmt-comment_width: 110 + +impl Struct { + fn fun() { + let result = match ::deserialize(&json) { + Ok(v) => v, + Err(e) => { + match ::deserialize(&json) { + Ok(v) => return Err(Error::with_json(v)), + Err(e2) => return Err(Error::with_json(e)), + } + } + }; + } +} diff --git a/rustfmt-core/tests/source/issue-1366.rs b/rustfmt-core/tests/source/issue-1366.rs new file mode 100644 index 00000000000..9d2964fc77c --- /dev/null +++ b/rustfmt-core/tests/source/issue-1366.rs @@ -0,0 +1,12 @@ +fn main() { + fn f() -> Option { + Some("fffffffsssssssssddddssssfffffddddff").map(|s| s).map(|s| s.to_string()).map(|res| { + match Some(res) { + Some(ref s) if s == "" => 41, + Some(_) => 42, + _ => 43, + } + }) + } + println!("{:?}", f()) +} diff --git a/rustfmt-core/tests/source/issue-1468.rs b/rustfmt-core/tests/source/issue-1468.rs new file mode 100644 index 00000000000..4d0d4f0eb98 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1468.rs @@ -0,0 +1,27 @@ +fn issue1468() { +euc_jp_decoder_functions!({ +let trail_minus_offset = byte.wrapping_sub(0xA1); +// Fast-track Hiragana (60% according to Lunde) +// and Katakana (10% according to Lunde). +if jis0208_lead_minus_offset == 0x03 && +trail_minus_offset < 0x53 { +// Hiragana +handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) +} else if jis0208_lead_minus_offset == 0x04 && +trail_minus_offset < 0x56 { +// Katakana +handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) +} else if trail_minus_offset > (0xFE - 0xA1) { +if byte < 0x80 { +return (DecoderResult::Malformed(1, 0), +unread_handle_trail.unread(), +handle.written()); +} +return (DecoderResult::Malformed(2, 0), +unread_handle_trail.consumed(), +handle.written()); +} else { +unreachable!(); +} +}); +} diff --git a/rustfmt-core/tests/source/issue-1693.rs b/rustfmt-core/tests/source/issue-1693.rs new file mode 100644 index 00000000000..0622ce50235 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1693.rs @@ -0,0 +1,3 @@ +fn issue1693() { + let pixel_data = vec![(f16::from_f32(0.82), f16::from_f32(1.78), f16::from_f32(0.21)); 256 * 256]; +} diff --git a/rustfmt-core/tests/source/issue-1800.rs b/rustfmt-core/tests/source/issue-1800.rs new file mode 100644 index 00000000000..eae22653258 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1800.rs @@ -0,0 +1,3 @@ +#![doc(html_root_url = "http://example.com")] +#[cfg(feature = "foo")] +fn a() {} diff --git a/rustfmt-core/tests/source/issue-1914.rs b/rustfmt-core/tests/source/issue-1914.rs new file mode 100644 index 00000000000..447296c4b87 --- /dev/null +++ b/rustfmt-core/tests/source/issue-1914.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 80 + +extern "C" { +#[link_name = "_ZN7MyClass26example_check_no_collisionE"] + pub static mut MyClass_example_check_no_collision : * const :: std :: os :: raw :: c_int ; +} diff --git a/rustfmt-core/tests/source/issue-2025.rs b/rustfmt-core/tests/source/issue-2025.rs new file mode 100644 index 00000000000..c6f61b4e3e1 --- /dev/null +++ b/rustfmt-core/tests/source/issue-2025.rs @@ -0,0 +1,8 @@ + + + + +// See if rustfmt removes empty lines on top of the file. +pub fn foo() { + println!("hello, world"); +} diff --git a/rustfmt-core/tests/source/issue-2111.rs b/rustfmt-core/tests/source/issue-2111.rs new file mode 100644 index 00000000000..d1b02053e2a --- /dev/null +++ b/rustfmt-core/tests/source/issue-2111.rs @@ -0,0 +1,28 @@ +// rustfmt-normalize_comments: false + +// An import with single line comments. +use super::{ + SCHEMA_VERSIONS, + LodaModel, + ModelProperties, + StringMap, + ModelSelector, + RequestDescription, + MethodDescription, + ModelBehaviour, + ModelRequestGraph, + DelayChoice, + Holding, + Destinations, + ModelEdges, + Switch, + // ModelMetaData, + // Generated, + // SecondsString, + // DateString, + // ModelConfiguration, + // ModelRequests, + // RestResponse, + // RestResponseCode, + // UniformHolding +}; diff --git a/rustfmt-core/tests/source/issue-2164.rs b/rustfmt-core/tests/source/issue-2164.rs new file mode 100644 index 00000000000..6c288e1bd62 --- /dev/null +++ b/rustfmt-core/tests/source/issue-2164.rs @@ -0,0 +1,4 @@ +// A stress test against code generated by bindgen. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct emacs_env_25 { pub size : isize , pub private_members : * mut emacs_env_private , pub make_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , any_reference : emacs_value ) -> emacs_value > , pub free_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , global_reference : emacs_value ) > , pub non_local_exit_check : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) -> emacs_funcall_exit > , pub non_local_exit_clear : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) > , pub non_local_exit_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol_out : * mut emacs_value , non_local_exit_data_out : * mut emacs_value ) -> emacs_funcall_exit > , pub non_local_exit_signal : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol : emacs_value , non_local_exit_data : emacs_value ) > , pub non_local_exit_throw : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , tag : emacs_value , value : emacs_value ) > , pub make_function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , min_arity : isize , max_arity : isize , function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , nargs : isize , args : * mut emacs_value , arg1 : * mut ::libc :: c_void ) -> emacs_value > , documentation : * const ::libc :: c_char , data : * mut ::libc :: c_void ) -> emacs_value > , pub funcall : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , function : emacs_value , nargs : isize , args : * mut emacs_value ) -> emacs_value > , pub intern : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , symbol_name : * const ::libc :: c_char ) -> emacs_value > , pub type_of : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> emacs_value > , pub is_not_nil : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> bool > , pub eq : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , a : emacs_value , b : emacs_value ) -> bool > , pub extract_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> intmax_t > , pub make_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : intmax_t ) -> emacs_value > , pub extract_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> f64 > , pub make_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : f64 ) -> emacs_value > , pub copy_string_contents : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value , buffer : * mut ::libc :: c_char , size_inout : * mut isize ) -> bool > , pub make_string : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , contents : * const ::libc :: c_char , length : isize ) -> emacs_value > , pub make_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > , ptr : * mut ::libc :: c_void ) -> emacs_value > , pub get_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value ) -> * mut ::libc :: c_void > , pub set_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , ptr : * mut ::libc :: c_void ) > , pub get_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) -> :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) > > , pub set_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > ) > , pub vec_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize ) -> emacs_value > , pub vec_set : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize , val : emacs_value ) > , pub vec_size : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value ) -> isize > , } diff --git a/rustfmt-core/tests/source/issue-2179.rs b/rustfmt-core/tests/source/issue-2179.rs new file mode 100644 index 00000000000..ade953971ec --- /dev/null +++ b/rustfmt-core/tests/source/issue-2179.rs @@ -0,0 +1,35 @@ +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = + { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; + +} diff --git a/rustfmt-core/tests/source/issue-2256.rs b/rustfmt-core/tests/source/issue-2256.rs new file mode 100644 index 00000000000..b505b96e2b3 --- /dev/null +++ b/rustfmt-core/tests/source/issue-2256.rs @@ -0,0 +1,12 @@ +// こんにちは +use std::{}; +use std::borrow::Cow; + +/* comment */ use std::{}; +/* comment */ use std::{}; + + + + + +/* comment */ use std::{}; diff --git a/rustfmt-core/tests/source/issue-2342.rs b/rustfmt-core/tests/source/issue-2342.rs new file mode 100644 index 00000000000..f86d24a146b --- /dev/null +++ b/rustfmt-core/tests/source/issue-2342.rs @@ -0,0 +1,5 @@ +// rustfmt-max_width: 80 + +struct Foo { + #[cfg(feature = "serde")] bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN +} diff --git a/rustfmt-core/tests/source/issue-447.rs b/rustfmt-core/tests/source/issue-447.rs new file mode 100644 index 00000000000..7c542cb58c2 --- /dev/null +++ b/rustfmt-core/tests/source/issue-447.rs @@ -0,0 +1,39 @@ +// rustfmt-normalize_comments: true + +fn main() { + if /* shouldn't be dropped + shouldn't be dropped */ + + cond /* shouldn't be dropped + shouldn't be dropped */ + + { + } /* shouldn't be dropped + shouldn't be dropped */ + + else /* shouldn't be dropped + shouldn't be dropped */ + + if /* shouldn't be dropped + shouldn't be dropped */ + + cond /* shouldn't be dropped + shouldn't be dropped */ + + { + } /* shouldn't be dropped + shouldn't be dropped */ + + else /* shouldn't be dropped + shouldn't be dropped */ + + { + } + + if /* shouldn't be dropped + shouldn't be dropped */ + let Some(x) = y/* shouldn't be dropped + shouldn't be dropped */ + { + } +} diff --git a/rustfmt-core/tests/source/issue-510.rs b/rustfmt-core/tests/source/issue-510.rs new file mode 100644 index 00000000000..4c60859e6cf --- /dev/null +++ b/rustfmt-core/tests/source/issue-510.rs @@ -0,0 +1,37 @@ +impl ISizeAndMarginsComputer for AbsoluteNonReplaced { +fn solve_inline_size_constraints(&self, +block: &mut BlockFlow, +input: &ISizeConstraintInput) +-> ISizeConstraintSolution { +let (inline_start,inline_size,margin_inline_start,margin_inline_end) = +match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { +(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { +let margin_start = inline_start_margin.specified_or_zero(); +let margin_end = inline_end_margin.specified_or_zero(); +// Now it is the same situation as inline-start Specified and inline-end +// and inline-size Auto. +// +// Set inline-end to zero to calculate inline-size. +let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - +(margin_start + margin_end)); +(Au(0), inline_size, margin_start, margin_end) +} +}; + + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = + block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; +} +} diff --git a/rustfmt-core/tests/source/issue-811.rs b/rustfmt-core/tests/source/issue-811.rs new file mode 100644 index 00000000000..b7a89b5d0f9 --- /dev/null +++ b/rustfmt-core/tests/source/issue-811.rs @@ -0,0 +1,19 @@ +trait FooTrait: Sized { + type Bar: BarTrait; +} + +trait BarTrait: Sized { + type Baz; + fn foo(); +} + +type Foo = <>::Bar as BarTrait>::Baz; +type Bar = >::Baz; + +fn some_func, U>() { + <>::Bar as BarTrait>::foo(); +} + +fn some_func>() { + >::foo(); +} diff --git a/rustfmt-core/tests/source/issue-850.rs b/rustfmt-core/tests/source/issue-850.rs new file mode 100644 index 00000000000..c939716a6a8 --- /dev/null +++ b/rustfmt-core/tests/source/issue-850.rs @@ -0,0 +1 @@ +const unsafe fn x() {} diff --git a/rustfmt-core/tests/source/issue-855.rs b/rustfmt-core/tests/source/issue-855.rs new file mode 100644 index 00000000000..8f33fa685ae --- /dev/null +++ b/rustfmt-core/tests/source/issue-855.rs @@ -0,0 +1,20 @@ +fn main() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} + +fn main2() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | + Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} diff --git a/rustfmt-core/tests/source/issue-913.rs b/rustfmt-core/tests/source/issue-913.rs new file mode 100644 index 00000000000..e1c1b225fa5 --- /dev/null +++ b/rustfmt-core/tests/source/issue-913.rs @@ -0,0 +1,22 @@ +// rustfmt-error_on_line_overflow: false + +mod client { + impl Client { + fn test(self) -> Result<()> { + let next_state = match self.state { + State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { + let x = reformat . meeee() ; + } + }; + + let next_state = match self.state { + State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { + // The pattern cannot be formatted in a way that the match stays + // within the column limit. The rewrite should therefore be + // skipped. + let x = dont . reformat . meeee(); + } + }; + } + } +} diff --git a/rustfmt-core/tests/source/issue-945.rs b/rustfmt-core/tests/source/issue-945.rs new file mode 100644 index 00000000000..37d703c4679 --- /dev/null +++ b/rustfmt-core/tests/source/issue-945.rs @@ -0,0 +1,5 @@ +impl Bar { default const unsafe fn foo() { "hi" } } + +impl Baz { default unsafe extern "C" fn foo() { "hi" } } + +impl Foo for Bar { default fn foo() { "hi" } } diff --git a/rustfmt-core/tests/source/issue-977.rs b/rustfmt-core/tests/source/issue-977.rs new file mode 100644 index 00000000000..b028b36a055 --- /dev/null +++ b/rustfmt-core/tests/source/issue-977.rs @@ -0,0 +1,8 @@ +// rustfmt-normalize_comments: true +// FIXME(#919) + +trait NameC { /* comment */ } +struct FooC { /* comment */ } +enum MooC { /* comment */ } +mod BarC { /* comment */ } +extern { /* comment */ } diff --git a/rustfmt-core/tests/source/item-brace-style-always-next-line.rs b/rustfmt-core/tests/source/item-brace-style-always-next-line.rs new file mode 100644 index 00000000000..38094d67a77 --- /dev/null +++ b/rustfmt-core/tests/source/item-brace-style-always-next-line.rs @@ -0,0 +1,29 @@ +// rustfmt-brace_style: AlwaysNextLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs b/rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs new file mode 100644 index 00000000000..dff89b8b66b --- /dev/null +++ b/rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs @@ -0,0 +1,29 @@ +// rustfmt-brace_style: PreferSameLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/rustfmt-core/tests/source/item-brace-style-same-line-where.rs b/rustfmt-core/tests/source/item-brace-style-same-line-where.rs new file mode 100644 index 00000000000..ee4a7c5daad --- /dev/null +++ b/rustfmt-core/tests/source/item-brace-style-same-line-where.rs @@ -0,0 +1,31 @@ +// rustfmt-brace_style: SameLineWhere + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/rustfmt-core/tests/source/large-block.rs b/rustfmt-core/tests/source/large-block.rs new file mode 100644 index 00000000000..09e9169f340 --- /dev/null +++ b/rustfmt-core/tests/source/large-block.rs @@ -0,0 +1,5 @@ +fn issue1351() { + std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ + static __STATIC_FMTSTR: &'static [&'static str] = &[]; + }); +} diff --git a/rustfmt-core/tests/source/large_vec.rs b/rustfmt-core/tests/source/large_vec.rs new file mode 100644 index 00000000000..34d5bf39954 --- /dev/null +++ b/rustfmt-core/tests/source/large_vec.rs @@ -0,0 +1,29 @@ +// See #1470. + +impl Environment { + pub fn new_root() -> Rc> { + let mut env = Environment::new(); + let builtin_functions = &[("println", + Function::NativeVoid(CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println)), + ("run_http_server", + Function::NativeVoid(CallSign { + num_params: 1, + variadic: false, + param_types: + vec![Some(ConstraintType::Function)], + }, + native_run_http_server)), + ("len", + Function::NativeReturning(CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len))]; + } +} diff --git a/rustfmt-core/tests/source/long-match-arms-brace-newline.rs b/rustfmt-core/tests/source/long-match-arms-brace-newline.rs new file mode 100644 index 00000000000..927ada0ffb2 --- /dev/null +++ b/rustfmt-core/tests/source/long-match-arms-brace-newline.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 80 +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + match x { + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == + "aaaaaaaaaaa \ + aaaaaaa \ + aaaaaa" => { + Ok(()) + } + _ => Err(x), + } +} diff --git a/rustfmt-core/tests/source/long_field_access.rs b/rustfmt-core/tests/source/long_field_access.rs new file mode 100644 index 00000000000..7aa626221ae --- /dev/null +++ b/rustfmt-core/tests/source/long_field_access.rs @@ -0,0 +1,3 @@ +fn f() { + block_flow.base.stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; +} diff --git a/rustfmt-core/tests/source/loop.rs b/rustfmt-core/tests/source/loop.rs new file mode 100644 index 00000000000..6e92cdc6c2c --- /dev/null +++ b/rustfmt-core/tests/source/loop.rs @@ -0,0 +1,29 @@ + +fn main() { + loop + { return some_val;} + +let x = loop { do_forever(); }; + + 'label : loop { + // Just comments + } + + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value{} + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {} + + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { + // do smth + } + + while let Some(i) = x.find('s') + { + x.update(); + continue; + continue 'foo; + } +} diff --git a/rustfmt-core/tests/source/macro_not_expr.rs b/rustfmt-core/tests/source/macro_not_expr.rs new file mode 100644 index 00000000000..d8de4dce38f --- /dev/null +++ b/rustfmt-core/tests/source/macro_not_expr.rs @@ -0,0 +1,7 @@ +macro_rules! test { + ($($t:tt)*) => {} +} + +fn main() { + test!( a : B => c d ); +} diff --git a/rustfmt-core/tests/source/macro_rules.rs b/rustfmt-core/tests/source/macro_rules.rs new file mode 100644 index 00000000000..7d14f44971d --- /dev/null +++ b/rustfmt-core/tests/source/macro_rules.rs @@ -0,0 +1,51 @@ +macro_rules! m { + // a + ($expr :expr, $( $func : ident ) * ) => { + { + let x = $expr; + $func ( + x + ) + } + }; + + /* b */ + + () => {/* c */}; + + (@tag) => + { + + }; + +// d +( $item:ident ) => { + mod macro_item { struct $item ; } +}; +} + +macro m2 { + // a + ($expr :expr, $( $func : ident ) * ) => { + { + let x = $expr; + $func ( + x + ) + } + } + + /* b */ + + () => {/* c */} + + (@tag) => + { + + } + +// d +( $item:ident ) => { + mod macro_item { struct $item ; } +} +} diff --git a/rustfmt-core/tests/source/macros.rs b/rustfmt-core/tests/source/macros.rs new file mode 100644 index 00000000000..ffd5c19cc8c --- /dev/null +++ b/rustfmt-core/tests/source/macros.rs @@ -0,0 +1,338 @@ +// rustfmt-normalize_comments: true +itemmacro!(this, is.now() .formatted(yay)); + +itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); + +itemmacro!{this, is.bracket().formatted()} + +peg_file! modname ("mygrammarfile.rustpeg"); + +fn main() { + foo! ( ); + + bar!( a , b , c ); + + bar!( a , b , c , ); + + baz!(1+2+3, quux. kaas()); + + quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + + kaas!(/* comments */ a /* post macro */, b /* another */); + + trailingcomma!( a , b , c , ); + // Preserve trailing comma only when necessary. + ok!(file.seek( + SeekFrom::Start( + table.map(|table| fixture.offset(table)).unwrap_or(0), + ) + )); + + noexpr!( i am not an expression, OK? ); + + vec! [ a , b , c]; + + vec! [AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, + BBBBB, 5, 100-30, 1.33, b, b, b]; + + vec! [a /* comment */]; + + // Trailing spaces after a comma + vec![ + a, + ]; + + vec![a; b]; + vec!(a; b); + vec!{a; b}; + + vec![a, b; c]; + vec![a; b, c]; + + vec![a; (|x| { let y = x + 1; let z = y + 1; z })(2)]; + vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![a; unsafe { + x + 1 + }]; + + unknown_bracket_macro__comma_should_not_be_stripped![ + a, + ]; + + foo(makro!(1, 3)); + + hamkaas!{ () }; + + macrowithbraces! {dont, format, me} + + x!(fn); + + some_macro!( + + ); + + some_macro![ + ]; + + some_macro!{ + // comment + }; + + some_macro!{ + // comment + }; + + some_macro!( + // comment + not function like + ); + + // #1712 + let image = gray_image!( + 00, 01, 02; + 10, 11, 12; + 20, 21, 22); + + // #1092 + chain!(input, a:take!(max_size), || []); +} + +impl X { + empty_invoc!{} +} + +fn issue_1279() { + println!("dsfs"); // a comment +} + +fn issue_1555() { + let hello = &format!("HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", + "65454654654654654654654655464", + "4"); +} + +fn issue1178() { + macro_rules! foo { + (#[$attr:meta] $name:ident) => {} + } + + foo!(#[doc = "bar"] baz); +} + +fn issue1739() { + sql_function!(add_rss_item, + add_rss_item_t, + (a: types::Integer, + b: types::Timestamptz, + c: types::Text, + d: types::Text, + e: types::Text)); + + w.slice_mut(s![.., init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], ..]) + .par_map_inplace(|el| *el = 0.); +} + +fn issue_1885() { + let threads = people.into_iter().map(|name| { + chan_select! { + rx.recv() => {} + } + }).collect::>(); +} + +fn issue_1917() { + mod x { + quickcheck! { + fn test(a: String, s: String, b: String) -> TestResult { + if a.find(&s).is_none() { + + TestResult::from_bool(true) + } else { + TestResult::discard() + } + } + } + } +} + +fn issue_1921() { + // Macro with tabs. + lazy_static! { + static ref ONE: u32 = 1; + static ref TWO: u32 = 2; + static ref THREE: u32 = 3; + static ref FOUR: u32 = { + let mut acc = 1; + acc += 1; + acc += 2; + acc + } +} +} + +// #1577 +fn issue1577() { + let json = json!({ + "foo": "bar", + }); +} + +gfx_pipeline!(pipe { + vbuf: gfx::VertexBuffer = (), + out: gfx::RenderTarget = "Target0", +}); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) + ) + ); + assert_eq ! ( :: std :: mem :: align_of :: < HandleWithDtor < :: std :: os :: raw :: c_int > > ( ) , 8usize , concat ! ( "Alignment of template specialization: " , stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) ) ); +} + +// #878 +macro_rules! try_opt { + ($expr:expr) => (match $expr { + Some(val) => val, + + None => { return None; } + }) +} + +// #2214 +// macro call whose argument is an array with trailing comma. +fn issue2214() { +make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [ + Reject(0, 1), + Match (1, 3), + Reject(3, 4), + Match (4, 6), + Reject(6, 7), +]); +} + +fn special_case_macros() { + let p = eprint!(); + let q = eprint!("{}", 1); + let r = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = eprintln!("{}", 1); + let r = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = format!("{}", 1); + let r = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = format_args!("{}", 1); + let r = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = print!("{}", 1); + let r = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = println!("{}", 1); + let r = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = unreachable!("{}", 1); + let r = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + debug!("{}", 1); + debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + error!("{}", 1); + error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + info!("{}", 1); + info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + panic!("{}", 1); + panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + warn!("{}", 1); + warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + assert!(); + assert!(result == 42); + assert!(result == 42, "Ahoy there, {}!", target); + assert!(result == 42, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + assert_eq!(); + assert_eq!(left); + assert_eq!(left, right); + assert_eq!(left, right, "Ahoy there, {}!", target); + assert_eq!(left, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(left + 42, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + write!(&mut s, "Ahoy there, {}!", target); + write!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + write!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + writeln!(&mut s, "Ahoy there, {}!", target); + writeln!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + writeln!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); +} + +// #1209 +impl Foo { + /// foo + pub fn foo(&self) -> Bar {} +} + +// #819 +fn macro_in_pattern_position () { + let x = match y { + foo!( ) => (), + bar!( a, b, + c) => (), + bar!(a + , b + , c + ,) => (), + baz!( 1 + 2 + 3, quux.kaas( ) + ) => (), + quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) => (), + }; +} + +macro foo() { + + +} + +pub macro bar($x:ident+$y:expr; ) { + fn foo($x: Foo) { + long_function(a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), + $x.bar($y)); + } +} + +macro foo() { + // a comment + fn foo() { + // another comment + bar(); + } +} + +macro lex_err($kind: ident $(, $body: expr)*) { + Err(QlError::LexError(LexError::$kind($($body,)*))) +} diff --git a/rustfmt-core/tests/source/match-block-trailing-comma.rs b/rustfmt-core/tests/source/match-block-trailing-comma.rs new file mode 100644 index 00000000000..e9daac13bf9 --- /dev/null +++ b/rustfmt-core/tests/source/match-block-trailing-comma.rs @@ -0,0 +1,14 @@ +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + } + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/rustfmt-core/tests/source/match-nowrap-trailing-comma.rs b/rustfmt-core/tests/source/match-nowrap-trailing-comma.rs new file mode 100644 index 00000000000..134d2fdf9a4 --- /dev/null +++ b/rustfmt-core/tests/source/match-nowrap-trailing-comma.rs @@ -0,0 +1,15 @@ +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + } + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/rustfmt-core/tests/source/match-nowrap.rs b/rustfmt-core/tests/source/match-nowrap.rs new file mode 100644 index 00000000000..db22cd9f010 --- /dev/null +++ b/rustfmt-core/tests/source/match-nowrap.rs @@ -0,0 +1,12 @@ +// rustfmt-match_arm_blocks: false +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { foo() } + b => + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/rustfmt-core/tests/source/match.rs b/rustfmt-core/tests/source/match.rs new file mode 100644 index 00000000000..23df0d3b681 --- /dev/null +++ b/rustfmt-core/tests/source/match.rs @@ -0,0 +1,453 @@ +// rustfmt-normalize_comments: true +// Match expressions. + +fn foo() { + // A match expression. + match x { + // Some comment. + a => foo(), + b if 0 < 42 => foo(), + c => { // Another comment. + // Comment. + an_expression; + foo() + } + Foo(ref bar) => + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Pattern1 | Pattern2 | Pattern3 => false, + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + blah + } + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn => meh, + + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, + + Patternnnnnnnnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => + meh, + + // Test that earlier patterns can take the guard space + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} + + _ => {} + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => {} + } + + let whatever = match something { + /// DOC COMMENT! + Some(_) => 42, + // Comment on an attribute. + #[an_attribute] + // Comment after an attribute. + None => 0, + #[rustfmt_skip] + Blurb => { } + }; +} + +// Test that a match on an overflow line is laid out properly. +fn main() { + let sub_span = + match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; +} + +// Test that one-line bodies align. +fn main() { + match r { + Variableeeeeeeeeeeeeeeeee => ( "variable", + vec!("id", "name", "qualname", + "value", "type", "scopeid"), + true, + true), + Enummmmmmmmmmmmmmmmmmmmm => ("enum", + vec!("id","qualname","scopeid","value"), + true, + true), + Variantttttttttttttttttttttttt => ("variant", + vec!("id", + "name", + "qualname", + "type", + "value", + "scopeid"), + true, + true), + }; + + match x{ + y=>{/*Block with comment. Preserve me.*/ } + z=>{stmt();} } +} + +fn matches() { + match 1 { + -1 => 10, + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0 // baz + } +} + +fn match_skip() { + let _ = match Some(1) { + #[rustfmt_skip] + Some( n ) => n, + None => 1, + }; +} + +fn issue339() { + match a { + b => {} + c => { } + d => { + } + e => { + + + + } + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { + } + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { // comment above block + } + i => { + } // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => { + } n => { } o => + { + + } + p => { // Dont collapse me + } q => { } r => + { + + } + s => 0, // s comment + // t comment + t => 1, + u => 2, + v => { + } /* funky block + * comment */ + // final comment + } +} + +fn issue355() { + match mac { + a => println!("a", b), + b => vec!(1, 2), + c => vec!(3; 4), + d => { + println!("a", b) + } + e => { + vec!(1, 2) + } + f => { + vec!(3; 4) + } + h => println!("a", b), // h comment + i => vec!(1, 2), // i comment + j => vec!(3; 4), // j comment + // k comment + k => println!("a", b), + // l comment + l => vec!(1, 2), + // m comment + m => vec!(3; 4), + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), + // Macro support fails to recognise this macro as splittable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), + // Funky bracketing styles + t => println!{"a", b}, + u => vec!{1, 2}, + v => vec!{3; 4}, + w => println!["a", b], + x => vec![1, 2], + y =>vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec!{1, 2}, // comment + vc =>vec!{3; 4}, // comment + wc =>println!["a", b], // comment + xc => vec![1,2], // comment + yc => vec![3; 4], // comment + yd => + looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd), + } +} + +fn issue280() { + { + match x { + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == + '\n', + ast::ItemConst(ref typ, ref expr) => self.process_static_or_const_item(item, + &typ, + &expr), + } + } +} + +fn issue383() { + match resolution.last_private {LastImport{..} => false, _ => true}; +} + +fn issue507() { + match 1 { + 1 => unsafe { std::intrinsics::abort() }, + _ => (), + } +} + +fn issue508() { + match s.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement))) => true, + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), + Some(NodeTypeId::Element(_)) => false, + } +} + +fn issue496() {{{{ + match def { + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => + match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + Some(const_expr) => { x }}}}}}} + +fn issue494() { + { + match stmt.node { + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => + result.push( + StmtRef::Mirror( + Box::new(Stmt { span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref() } }))), + } + } +} + +fn issue386() { + match foo { + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => + true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => + false, + } +} + +fn guards() { + match foo { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if fooooooooooooooooooooo && + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {} + } +} + +fn issue1371() { + Some(match type_ { + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; + + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => { + TextEntered { + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + } + } + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; + + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; + + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) +} + +fn issue1395() { + let bar = Some(true); + let foo = Some(true); + let mut x = false; + bar.and_then(|_| { + match foo { + None => None, + Some(b) => { + x = true; + Some(b) + } + } + }); +} + +fn issue1456() { + Ok(Recording { + artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) +} + +fn issue1460() { + let _ = match foo { + REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => "internal_spec_insert_internal_spec_insert_internal_spec_insert", + _ => "reorder_something", + }; +} + +fn issue525() { + foobar(f, "{}", match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }); +} + +// #1838, #1839 +fn match_with_near_max_width() { + let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { + _ => unimplemented!(), + }; + + let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { + _ => unimplemented!(), + }; + + let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression + { + _ => unimplemented!(), + }; + match m { + Variant::Tag | Variant::Tag2 | Variant::Tag3 | Variant::Tag4 | Variant::Tag5 | Variant::Tag6 => + {} + } +} + +fn match_with_trailing_spaces() { + match x { + #![allow(simple_match)] + Some(..) => 0, + None => 1, + } +} + +fn issue_2099() { + let a = match x { +}; + let b = match x { + + }; + + match x {} +} + +// #2021 +impl<'tcx> Const<'tcx> { + pub fn from_constval<'a>() -> Const<'tcx> { + let val = match *cv { + ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv), + }; + } +} + +// #2151 +fn issue_2151() { + match either { + x => { + + }y => () + } +} + +// #2152 +fn issue_2152() { + match m { + "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" if true => {} + "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => true, + } +} diff --git a/rustfmt-core/tests/source/max-line-length-in-chars.rs b/rustfmt-core/tests/source/max-line-length-in-chars.rs new file mode 100644 index 00000000000..d49fbb7e30e --- /dev/null +++ b/rustfmt-core/tests/source/max-line-length-in-chars.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 25 + +// абвгдеёжзийклмнопрст +fn main() {} diff --git a/rustfmt-core/tests/source/mod-1.rs b/rustfmt-core/tests/source/mod-1.rs new file mode 100644 index 00000000000..427a355b6be --- /dev/null +++ b/rustfmt-core/tests/source/mod-1.rs @@ -0,0 +1,29 @@ +// Deeply indented modules. + + mod foo { mod bar { mod baz {} } } + +mod foo { + mod bar { + mod baz { + fn foo() { bar() } + } + } + + mod qux { + + } +} + +mod boxed { pub use std::boxed::{Box, HEAP}; } + +pub mod x { + pub fn freopen(filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE) + -> *mut FILE{} +} + + mod y { // sup boooooiiii + } diff --git a/rustfmt-core/tests/source/mod-2.rs b/rustfmt-core/tests/source/mod-2.rs new file mode 100644 index 00000000000..7202e00203e --- /dev/null +++ b/rustfmt-core/tests/source/mod-2.rs @@ -0,0 +1,4 @@ +// Some nested mods + +#[cfg(test)] mod nestedmod ; +pub mod no_new_line_beginning; diff --git a/rustfmt-core/tests/source/mod_skip_child.rs b/rustfmt-core/tests/source/mod_skip_child.rs new file mode 100644 index 00000000000..d48c4a37e81 --- /dev/null +++ b/rustfmt-core/tests/source/mod_skip_child.rs @@ -0,0 +1,2 @@ +// rustfmt-skip_children: true +mod nested_skipped; diff --git a/rustfmt-core/tests/source/multiple.rs b/rustfmt-core/tests/source/multiple.rs new file mode 100644 index 00000000000..68cfacfcb4b --- /dev/null +++ b/rustfmt-core/tests/source/multiple.rs @@ -0,0 +1,134 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-format_strings: true +// Test of lots of random stuff. +// FIXME split this into multiple, self-contained tests. + + +#[attr1] extern crate foo; +#[attr2] #[attr3] extern crate foo; +#[attr1]extern crate foo; +#[attr2]#[attr3]extern crate foo; + +use std::cell::*; +use std::{any, ascii, self, borrow, boxed, char, borrow, boxed, char, borrow, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char}; + +mod doc; +mod other; + + +// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff + + fn foo(a: isize, + b: u32, /* blah blah */ + c: f64) { + +} + +fn foo()->Box where 'a: 'b, for<'a> D<'b>: 'a { + hello!() +} + +fn baz<'a: 'b /* comment on 'a */, T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */>(a: A, b: B /* comment on b */, c: C) -> Bob { + #[attr1] extern crate foo; + #[attr2] #[attr3] extern crate foo; + #[attr1]extern crate foo; + #[attr2]#[attr3]extern crate foo; +} + +#[rustfmt_skip] +fn qux(a: dadsfa, // Comment 1 + b: sdfasdfa, // Comment 2 + c: dsfdsafa) // Comment 3 +{ + +} + +/// Blah blah blah. +impl Bar { + fn foo(&mut self, a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a + b: sdfasdfsdfasfs /*closing comment*/ ) -> isize {} + + /// Blah blah blah. + pub fn f2(self) { + (foo, bar) + } + + #[an_attribute] + fn f3(self) -> Dog { + } +} + +/// The `nodes` and `edges` method each return instantiations of +/// `Cow<[T]>` to leave implementers the freedom to create + +/// entirely new vectors or to pass back slices into internally owned +/// vectors. +pub trait GraphWalk<'a, N, E> { + /// Returns all the nodes in this graph. + fn nodes(&'a self) -> Nodes<'a, N>; + /// Returns all of the edges in this graph. + fn edges(&'a self) -> Edges<'a, E>; + /// The source node for `edge`. + fn source(&'a self, edge: &E) -> N; + /// The target node for `edge`. + fn target(&'a self, edge: &E) -> N; +} + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f : SomeType, // Comment beside a field + // Comment on a field + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType,} + +struct Bar; + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +fn foo(ann: &'a (PpAnn+'a)) {} + +fn main() { + for i in 0i32..4 { + println!("{}", i); + } + + + while true { + hello(); + } + + let rc = Cell::new(42usize,42usize, Cell::new(42usize, remaining_widthremaining_widthremaining_widthremaining_width), 42usize); + let rc = RefCell::new(42usize,remaining_width, remaining_width); // a comment + let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; + let s = expand(a + , + b); } + +fn deconstruct() -> (SocketAddr, Method, Headers, + RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} + +fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, + RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} + +#[rustfmt_skip] +mod a{ +fn foo(x: T) { + let x: T = dfasdf; +} +} diff --git a/rustfmt-core/tests/source/nested-if-else.rs b/rustfmt-core/tests/source/nested-if-else.rs new file mode 100644 index 00000000000..9a54789ddcd --- /dev/null +++ b/rustfmt-core/tests/source/nested-if-else.rs @@ -0,0 +1,11 @@ +fn issue1518() { + Some(Object { + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) +} diff --git a/rustfmt-core/tests/source/nested_skipped/mod.rs b/rustfmt-core/tests/source/nested_skipped/mod.rs new file mode 100644 index 00000000000..44b25ca8797 --- /dev/null +++ b/rustfmt-core/tests/source/nested_skipped/mod.rs @@ -0,0 +1,3 @@ +fn ugly() { +92; +} diff --git a/rustfmt-core/tests/source/nestedmod/mod.rs b/rustfmt-core/tests/source/nestedmod/mod.rs new file mode 100644 index 00000000000..d04e49570a4 --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/mod.rs @@ -0,0 +1,13 @@ + +mod mod2a; +mod mod2b; + +mod mymod1 { + use mod2a::{Foo,Bar}; +mod mod3a; +} + +#[path="mod2c.rs"] +mod mymod2; + +mod submod2; diff --git a/rustfmt-core/tests/source/nestedmod/mod2a.rs b/rustfmt-core/tests/source/nestedmod/mod2a.rs new file mode 100644 index 00000000000..5df457a8316 --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/mod2a.rs @@ -0,0 +1,4 @@ +// This is an empty file containing only +// comments + +// ................... diff --git a/rustfmt-core/tests/source/nestedmod/mod2b.rs b/rustfmt-core/tests/source/nestedmod/mod2b.rs new file mode 100644 index 00000000000..f128e2da6db --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/mod2b.rs @@ -0,0 +1,3 @@ + +#[path="mod2a.rs"] +mod c; diff --git a/rustfmt-core/tests/source/nestedmod/mod2c.rs b/rustfmt-core/tests/source/nestedmod/mod2c.rs new file mode 100644 index 00000000000..eda6b233e4b --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/mod2c.rs @@ -0,0 +1,3 @@ +// A standard mod + +fn a( ) {} diff --git a/rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs b/rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs new file mode 100644 index 00000000000..f28bde5e56d --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs @@ -0,0 +1,2 @@ +// Another mod +fn a( ) { } diff --git a/rustfmt-core/tests/source/nestedmod/submod2/a.rs b/rustfmt-core/tests/source/nestedmod/submod2/a.rs new file mode 100644 index 00000000000..0eaf08f0d2c --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/submod2/a.rs @@ -0,0 +1,6 @@ +// Yet Another mod +// Nested + +use c::a; + +fn foo( ) { } diff --git a/rustfmt-core/tests/source/nestedmod/submod2/mod.rs b/rustfmt-core/tests/source/nestedmod/submod2/mod.rs new file mode 100644 index 00000000000..52f8be91022 --- /dev/null +++ b/rustfmt-core/tests/source/nestedmod/submod2/mod.rs @@ -0,0 +1,5 @@ +// Another mod + +mod a; + +use a::a; diff --git a/rustfmt-core/tests/source/no_new_line_beginning.rs b/rustfmt-core/tests/source/no_new_line_beginning.rs new file mode 100644 index 00000000000..f79c691f085 --- /dev/null +++ b/rustfmt-core/tests/source/no_new_line_beginning.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/rustfmt-core/tests/source/other.rs b/rustfmt-core/tests/source/other.rs new file mode 100644 index 00000000000..dfce84fcdc4 --- /dev/null +++ b/rustfmt-core/tests/source/other.rs @@ -0,0 +1,5 @@ +// Part of multiple.rs + +fn bob() { + println!("hello other!"); +} diff --git a/rustfmt-core/tests/source/paths.rs b/rustfmt-core/tests/source/paths.rs new file mode 100644 index 00000000000..ebc26f146e4 --- /dev/null +++ b/rustfmt-core/tests/source/paths.rs @@ -0,0 +1,25 @@ +// rustfmt-normalize_comments: true + +fn main() { + let constellation_chan = Constellation:: ::start( + compositor_proxy, + resource_task, + image_cache_task,font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard + ); + + Quux::::some_func(); + + < *mut JSObject >:: relocate(entry); + + let x: Foo; + let x: Foo/*::*/; +} + +fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/rustfmt-core/tests/source/pattern-condense-wildcards.rs b/rustfmt-core/tests/source/pattern-condense-wildcards.rs new file mode 100644 index 00000000000..244e935639a --- /dev/null +++ b/rustfmt-core/tests/source/pattern-condense-wildcards.rs @@ -0,0 +1,12 @@ +// rustfmt-normalize_comments: true +// rustfmt-condense_wildcard_suffixes: true + +fn main() { + match x { + Butt (_,_) => "hah", + Tup (_) => "nah", + Quad (_,_, x,_) => " also no rewrite", + Quad (x, _, _, _) => "condense me pls", + Weird (x, _, _, /* dont condense before */ _, _, _) => "pls work", + } +} diff --git a/rustfmt-core/tests/source/pattern.rs b/rustfmt-core/tests/source/pattern.rs new file mode 100644 index 00000000000..7c052c87bc4 --- /dev/null +++ b/rustfmt-core/tests/source/pattern.rs @@ -0,0 +1,65 @@ +// rustfmt-normalize_comments: true +fn main() { + let z = match x { + "pat1" => 1, + ( ref x, ref mut y /*comment*/) => 2, + }; + + if let < T as Trait > :: CONST = ident { + do_smth(); + } + + let Some ( ref xyz /* comment! */) = opt; + + if let None = opt2 { panic!("oh noes"); } + + let foo@bar (f) = 42; + let a::foo ( ..) = 42; + let [ ] = 42; + let [a.., b,c ] = 42; + let [ a,b,c.. ] = 42; + let [a, b, c, d..,e,f, g] = 42; + let foo { } = 42; + let foo {..} = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; +} + +impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { + fn mutate_fragment(&mut self, fragment: &mut Fragment) { + match **info { + GeneratedContentInfo::ContentItem( + ContentItem::Counter( + ref counter_name, + counter_style + ) + ) => {}}} +} + +fn issue_1319() { + if let (Event { .. }, .. ) = ev_state {} +} + +fn issue_1874() { + if let Some(()) = x { +y + } +} + +fn combine_patterns() { + let x = match y { + Some( + Some( + Foo { + z: Bar(..), + a: Bar(..), + b: Bar(..), + }, + ), + ) => z, + _ => return, + }; +} diff --git a/rustfmt-core/tests/source/pub-restricted.rs b/rustfmt-core/tests/source/pub-restricted.rs new file mode 100644 index 00000000000..30051fa72ee --- /dev/null +++ b/rustfmt-core/tests/source/pub-restricted.rs @@ -0,0 +1,64 @@ +pub( super ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( crate ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + + crate enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(in ::global:: path :: to::some_mod ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( in local:: path :: to::some_mod ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} diff --git a/rustfmt-core/tests/source/remove_blank_lines.rs b/rustfmt-core/tests/source/remove_blank_lines.rs new file mode 100644 index 00000000000..7466e21eed8 --- /dev/null +++ b/rustfmt-core/tests/source/remove_blank_lines.rs @@ -0,0 +1,44 @@ +fn main() { + + + + + let x = 1; + + + let y = 2; + + + println!("x + y = {}", x + y); + + + +} + + +fn foo() { + + #![attribute] + + let x = 1; + + // comment + + +} +// comment after item + + +// comment before item +fn bar() { + let x = 1; + // comment after statement + + + // comment before statment + let y = 2; + let z = 3; + + + println!("x + y + z = {}", x + y + z); +} diff --git a/rustfmt-core/tests/source/single-line-if-else.rs b/rustfmt-core/tests/source/single-line-if-else.rs new file mode 100644 index 00000000000..bcde390d116 --- /dev/null +++ b/rustfmt-core/tests/source/single-line-if-else.rs @@ -0,0 +1,49 @@ + +// Format if-else expressions on a single line, when possible. + +fn main() { + let a = if 1 > 2 { + unreachable!() + } else { + 10 + }; + + let a = if x { 1 } else if y { 2 } else { 3 }; + + let b = if cond() { + 5 + } else { + // Brief comment. + 10 + }; + + let c = if cond() { + statement(); + + 5 + } else { + 10 + }; + + let d = if let Some(val) = turbo + { "cool" } else { + "beans" }; + + if cond() { statement(); } else { other_statement(); } + + if true { + do_something() + } + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { + bbbbbbbbbb }; + + funk(if test() { + 1 + } else { + 2 + }, + arg2); +} diff --git a/rustfmt-core/tests/source/soft-wrapping.rs b/rustfmt-core/tests/source/soft-wrapping.rs new file mode 100644 index 00000000000..ace8359409c --- /dev/null +++ b/rustfmt-core/tests/source/soft-wrapping.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 80 +// Soft wrapping for comments. + +// #535, soft wrapping for comments +// Compare the lowest `f32` of both inputs for greater than or equal. The +// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off +// the result are the upper 96 bits of `a`. + +/// Compare the lowest `f32` of both inputs for greater than or equal. The +/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off +/// the result are the upper 96 bits of `a`. +fn foo() {} diff --git a/rustfmt-core/tests/source/space-not-before-newline.rs b/rustfmt-core/tests/source/space-not-before-newline.rs new file mode 100644 index 00000000000..2a1e1856908 --- /dev/null +++ b/rustfmt-core/tests/source/space-not-before-newline.rs @@ -0,0 +1,8 @@ +struct Foo { + a: (), + // spaces ^^^ to be removed +} +enum Foo { + Bar, + // spaces ^^^ to be removed +} diff --git a/rustfmt-core/tests/source/spaces-around-ranges.rs b/rustfmt-core/tests/source/spaces-around-ranges.rs new file mode 100644 index 00000000000..1936b5e161f --- /dev/null +++ b/rustfmt-core/tests/source/spaces-around-ranges.rs @@ -0,0 +1,15 @@ +// rustfmt-spaces_around_ranges: true + +fn bar(v: &[u8]) {} + +fn foo() { + let a = vec![0; 20]; + for j in 0..=20 { + for i in 0..3 { + bar(a[i..j]); + bar(a[i..]); + bar(a[..j]); + bar(a[..=(j + 1)]); + } + } +} diff --git a/rustfmt-core/tests/source/static.rs b/rustfmt-core/tests/source/static.rs new file mode 100644 index 00000000000..970786381cc --- /dev/null +++ b/rustfmt-core/tests/source/static.rs @@ -0,0 +1,23 @@ +const FILE_GENERIC_READ: DWORD = + STANDARD_RIGHTS_READ | FILE_READ_DATA | + FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; + +static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", + "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", + "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", + "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; + +static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + + pub static count : u8 = 10 ; + +pub const test: &Type = &val; + +impl Color { + pub const WHITE: u32 = 10; +} + +// #1391 +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; + +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/rustfmt-core/tests/source/string-lit-2.rs b/rustfmt-core/tests/source/string-lit-2.rs new file mode 100644 index 00000000000..6b95e25a052 --- /dev/null +++ b/rustfmt-core/tests/source/string-lit-2.rs @@ -0,0 +1,25 @@ +fn main() -> &'static str { + let too_many_lines = "Hello"; + let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} + +fn issue_1237() { + let msg = "eedadn\n\ + drvtee\n\ + eandsr\n\ + raavrd\n\ + atevrs\n\ + tsrnev\n\ + sdttsa\n\ + rasrtv\n\ + nssdts\n\ + ntnada\n\ + svetve\n\ + tesnvt\n\ + vntsnd\n\ + vrdear\n\ + dvrsen\n\ + enarar"; +} diff --git a/rustfmt-core/tests/source/string-lit.rs b/rustfmt-core/tests/source/string-lit.rs new file mode 100644 index 00000000000..e86f65f9f52 --- /dev/null +++ b/rustfmt-core/tests/source/string-lit.rs @@ -0,0 +1,62 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false +// Long string literals + +fn main() -> &'static str { + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let too_many_lines = "H\ + e\ + l\ + l\ + o"; + + // Make sure we don't break after an escape character. + let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + + let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let raw_string = r#"Do +not +remove +formatting"#; + + filename.replace(" ", "\\" ); + + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + let unicode = "a̐éö̲\r\n"; + let unicode2 = "Löwe 老虎 Léopard"; + let unicode3 = "中华Việt Nam"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + + "stuffin'" +} + +fn issue682() { + let a = "hello \\ o/"; + let b = a.replace("\\ ", "\\"); +} + +fn issue716() { + println!("forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()"); +} + +fn issue_1282() { + { + match foo { + Permission::AndroidPermissionAccessLocationExtraCommands => { + "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" + } + } + } +} + +// #1987 +#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] +extern "C" {} diff --git a/rustfmt-core/tests/source/string_punctuation.rs b/rustfmt-core/tests/source/string_punctuation.rs new file mode 100644 index 00000000000..6a0afd45e5a --- /dev/null +++ b/rustfmt-core/tests/source/string_punctuation.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false + +fn main() { + println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); + println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); +} diff --git a/rustfmt-core/tests/source/struct-field-attributes.rs b/rustfmt-core/tests/source/struct-field-attributes.rs new file mode 100644 index 00000000000..76d6eda8853 --- /dev/null +++ b/rustfmt-core/tests/source/struct-field-attributes.rs @@ -0,0 +1,52 @@ +// #1535 +#![feature(struct_field_attributes)] + +struct Foo { + bar: u64, + + #[cfg(test)] + qux: u64, +} + +fn do_something() -> Foo { + Foo { + bar: 0, + + #[cfg(test)] + qux: 1, + } +} + +fn main() { + do_something(); +} + +// #1462 +struct Foo { + foo: usize, + #[cfg(feature="include-bar")] + bar: usize, +} + +fn new_foo() -> Foo { + Foo { + foo: 0, + #[cfg(feature="include-bar")] + bar: 0, + } +} + +// #2044 +pub enum State { + Closure(#[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] GcPtr), +} + +struct Fields( + #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] Arc>, +); + +// #2309 +pub struct A { +#[doc="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] +pub foos:Vec +} diff --git a/rustfmt-core/tests/source/struct_lits.rs b/rustfmt-core/tests/source/struct_lits.rs new file mode 100644 index 00000000000..3a8016367b6 --- /dev/null +++ b/rustfmt-core/tests/source/struct_lits.rs @@ -0,0 +1,144 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:f() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo + { a : 1, b:f( 2)}; + Foo{a:1,b:f(2),..g(3)}; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; + IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { a: bb, c: dd, e: ff }; + + Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ + e: eeeeeeeee }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, .. base }; + Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ + eeeeeeeee }; + Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; +} diff --git a/rustfmt-core/tests/source/struct_lits_multiline.rs b/rustfmt-core/tests/source/struct_lits_multiline.rs new file mode 100644 index 00000000000..256ba1bbda3 --- /dev/null +++ b/rustfmt-core/tests/source/struct_lits_multiline.rs @@ -0,0 +1,81 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-struct_lit_single_line: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; +} diff --git a/rustfmt-core/tests/source/struct_lits_visual.rs b/rustfmt-core/tests/source/struct_lits_visual.rs new file mode 100644 index 00000000000..2c6cc674960 --- /dev/null +++ b/rustfmt-core/tests/source/struct_lits_visual.rs @@ -0,0 +1,47 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:f() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, z: zzzzz // test + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/rustfmt-core/tests/source/struct_lits_visual_multiline.rs b/rustfmt-core/tests/source/struct_lits_visual_multiline.rs new file mode 100644 index 00000000000..d0b5ea6efba --- /dev/null +++ b/rustfmt-core/tests/source/struct_lits_visual_multiline.rs @@ -0,0 +1,45 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-struct_lit_single_line: false +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/rustfmt-core/tests/source/struct_tuple_visual.rs b/rustfmt-core/tests/source/struct_tuple_visual.rs new file mode 100644 index 00000000000..369feae71d2 --- /dev/null +++ b/rustfmt-core/tests/source/struct_tuple_visual.rs @@ -0,0 +1,37 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual +fn foo() { + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment + foo(), /* Comment */ + // Comment + bar() /* Comment */); + + Foo(Bar, f()); + + Quux(if cond { + bar(); + }, + baz()); + + Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + zzzzz /* test */); + + A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + Item); + + Diagram(// o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + G) +} diff --git a/rustfmt-core/tests/source/structs.rs b/rustfmt-core/tests/source/structs.rs new file mode 100644 index 00000000000..25070aef34c --- /dev/null +++ b/rustfmt-core/tests/source/structs.rs @@ -0,0 +1,283 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + + /// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1095 +struct S { + t: T, +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct +NewInt (pub i32, SomeType /* inline comment */, T /* sup */ + + + ); + +struct Qux<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy> +( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +struct Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +struct Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +// Will this be a one-liner? +struct Tuple( + A, //Comment + B +); + +pub struct State time::Timespec> { now: F } + +pub struct State ()> { now: F } + +pub struct State { now: F } + +struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(T); +struct Foo(T) where T: Copy, T: Eq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU); + +mod m { + struct X where T: Sized { + a: T, + } +} + +struct Foo(TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +struct Foo {} +struct Foo { + } +struct Foo { + // comment + } +struct Foo { + // trailing space -> + + + } +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +struct Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} + +// structs with long identifier +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { x: i32 } + +// structs with visibility, do not duplicate visibility (#2110). +pub(in self) struct Foo{} +pub(super) struct Foo{} +pub(crate) struct Foo{} +pub(in self) struct Foo(); +pub(super) struct Foo(); +pub(crate) struct Foo(); + +// #2125 +pub struct ReadinessCheckRegistry(Mutex, Box ReadinessCheck + Sync + Send>>>); + +// #2144 unit struct with generics +struct MyBox; +struct MyBoxx where T: ?Sized, S: Clone; + +// #2208 +struct Test { + /// foo + #[serde(default)] + pub join: Vec, + #[serde(default)] pub tls: bool, +} diff --git a/rustfmt-core/tests/source/trailing-comma-never.rs b/rustfmt-core/tests/source/trailing-comma-never.rs new file mode 100644 index 00000000000..5985b514724 --- /dev/null +++ b/rustfmt-core/tests/source/trailing-comma-never.rs @@ -0,0 +1,41 @@ +// rustfmt-trailing_comma: Never + +enum X { + A, + B, +} + +enum Y { + A, + B +} + +enum TupX { + A(u32), + B(i32, u16), +} + +enum TupY { + A(u32), + B(i32, u16) +} + +enum StructX { + A { + s: u16, + }, + B { + u: u32, + i: i32, + }, +} + +enum StructY { + A { + s: u16, + }, + B { + u: u32, + i: i32, + } +} diff --git a/rustfmt-core/tests/source/trailing_commas.rs b/rustfmt-core/tests/source/trailing_commas.rs new file mode 100644 index 00000000000..3e5fcc8080f --- /dev/null +++ b/rustfmt-core/tests/source/trailing_commas.rs @@ -0,0 +1,47 @@ +// rustfmt-match_block_trailing_comma: true +// rustfmt-trailing_comma: Always + +fn main() { + match foo { + x => {} + y => { + foo(); + } + _ => x + } +} + +fn f(x: T, y: S) -> T where T: P, S: Q +{ + x +} + +impl Trait for T where T: P +{ + fn f(x: T) -> T where T: Q + R + { + x + } +} + +struct Pair where T: P, S: P + Q { + a: T, + b: S +} + +struct TupPair (S, T) where T: P, S: P + Q; + +enum E where S: P, T: P { + A {a: T}, +} + +type Double where T: P, T: Q = Pair; + +extern "C" { + fn f(x: T, y: S) -> T where T: P, S: Q; +} + +trait Q where T: P, S: R +{ + fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; +} diff --git a/rustfmt-core/tests/source/trait.rs b/rustfmt-core/tests/source/trait.rs new file mode 100644 index 00000000000..e8de36db35e --- /dev/null +++ b/rustfmt-core/tests/source/trait.rs @@ -0,0 +1,94 @@ +// Test traits + +trait Foo { + fn bar(x: i32 ) -> Baz< U> { Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, +b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) +-> RetType; + + fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment +b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType ; // Some comment + + fn baz(&mut self ) -> i32 ; + +fn increment(& mut self, x: i32 ); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where R: Read; +} + +pub trait WriteMessage { + fn write_message (&mut self, &FrontendMessage) -> io::Result<()>; +} + +trait Runnable { + fn handler(self: & Runnable ); +} + +trait TraitWithExpr { + fn fn_with_expr(x: [i32; 1]); +} + +trait Test { + fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; +} + +trait T<> {} + +trait Foo { type Bar: Baz; type Inner: Foo = Box< Foo >; } + +trait ConstCheck:Foo where T: Baz { + const J: i32; +} + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } + +trait WhereList where T: Foo, J: Bar {} + +trait X /* comment */ {} +trait Y // comment +{ +} + +// #2055 +pub trait Foo: +// A and C +A + C +// and B + + B +{} + +// #2158 +trait Foo { + type ItRev = > as UntypedTimeSeries>::IterRev; + type IteRev = > as UntypedTimeSeries>::IterRev; +} + +// #2331 +trait MyTrait { + fn foo() {} +} + +// Trait aliases +trait FooBar = + Foo + + Bar; +trait FooBar = + Foo + + Bar; +trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; +#[rustfmt_skip] +trait FooBar = Foo + + Bar; diff --git a/rustfmt-core/tests/source/try-conversion.rs b/rustfmt-core/tests/source/try-conversion.rs new file mode 100644 index 00000000000..ed83ee9e101 --- /dev/null +++ b/rustfmt-core/tests/source/try-conversion.rs @@ -0,0 +1,18 @@ +// rustfmt-use_try_shorthand: true + +fn main() { + let x = try!(some_expr()); + + let y = try!(a.very.loooooooooooooooooooooooooooooooooooooong().chain().inside().weeeeeeeeeeeeeee()).test().0.x; +} + +fn test() { + a? +} + +fn issue1291() { + try!(fs::create_dir_all(&gitfiledir).chain_err(|| { + format!("failed to create the {} submodule directory for the workarea", + name) + })); +} diff --git a/rustfmt-core/tests/source/tuple.rs b/rustfmt-core/tests/source/tuple.rs new file mode 100644 index 00000000000..6c3ec8f1115 --- /dev/null +++ b/rustfmt-core/tests/source/tuple.rs @@ -0,0 +1,52 @@ +// Test tuple litterals + +fn foo() { + let a = (a, a, a, a, a); + let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); + let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa); + let a = (a,); + + let b = (// This is a comment + b, // Comment + b /* Trailing comment */); + + // #1063 + foo(x.0 .0); +} + +fn a() { + ((aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa),) +} + +fn b() { + ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + bbbbbbbbbbbbbbbbbb) +} + +fn issue550() { + self.visitor.visit_volume(self.level.sector_id(sector), (floor_y, + if is_sky_flat(ceil_tex) {from_wad_height(self.height_range.1)} else {ceil_y})); +} + +fn issue775() { + if indent { + let a = mk_object(&[("a".to_string(), Boolean(true)), + ("b".to_string(), + Array(vec![mk_object(&[("c".to_string(), + String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))])]))]); + } +} + +fn issue1725() { + bench_antialiased_lines!(bench_draw_antialiased_line_segment_diagonal, (10, 10), (450, 450)); + bench_antialiased_lines!(bench_draw_antialiased_line_segment_shallow, (10, 10), (450, 80)); +} diff --git a/rustfmt-core/tests/source/type-ascription.rs b/rustfmt-core/tests/source/type-ascription.rs new file mode 100644 index 00000000000..3b761f4fc78 --- /dev/null +++ b/rustfmt-core/tests/source/type-ascription.rs @@ -0,0 +1,9 @@ +fn main() { + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; + + let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + x : u32 - 1u32 / 10f32 : u32 +} diff --git a/rustfmt-core/tests/source/type-punctuation.rs b/rustfmt-core/tests/source/type-punctuation.rs new file mode 100644 index 00000000000..0980e4a3732 --- /dev/null +++ b/rustfmt-core/tests/source/type-punctuation.rs @@ -0,0 +1,32 @@ +// rustfmt-type_punctuation_density: Compressed + +struct Foo + where U: Eq + Clone { + // body +} + +trait Foo<'a, T = usize> + where T: 'a + Eq + Clone +{ + type Bar: Eq + Clone; +} + +trait Foo: Eq + Clone { + // body +} + +impl Foo<'a> for Bar + where for<'a> T: 'a + Eq + Clone +{ + // body +} + +fn foo<'a, 'b, 'c>() + where 'a: 'b + 'c +{ + // body +} + +fn Foo + Foo>() { + let i = 6; +} diff --git a/rustfmt-core/tests/source/type.rs b/rustfmt-core/tests/source/type.rs new file mode 100644 index 00000000000..0a46ffb2ee4 --- /dev/null +++ b/rustfmt-core/tests/source/type.rs @@ -0,0 +1,25 @@ +// rustfmt-normalize_comments: true +fn types() { + let x: [ Vec < _ > ] = []; + let y: * mut [ SomeType ; konst_funk() ] = expr(); + let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); + let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk(); +} + +struct F { + f: extern "C" fn(x: u8, ... /* comment */), + g: extern "C" fn(x: u8,/* comment */ ...), + h: extern "C" fn(x: u8, ... ), + i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3 + z: Foo, /* comment */ .../* comment 2*/ ), +} + +fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} + +fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} + +fn impl_trait_fn_2() -> impl Future {} + +fn issue_1234() { + do_parse!(name: take_while1!(is_token) >> (Header)) +} diff --git a/rustfmt-core/tests/source/type_alias.rs b/rustfmt-core/tests/source/type_alias.rs new file mode 100644 index 00000000000..58c807f4029 --- /dev/null +++ b/rustfmt-core/tests/source/type_alias.rs @@ -0,0 +1,34 @@ +// rustfmt-normalize_comments: true + +type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); + +pub type PublicTest<'a, I, O> = Result, Box + 'a>, Box + 'a>>; + +pub type LongGenericListTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Option>; + +pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; + +pub type GenericsFitButNotEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A1, B, C> = Vec; + +pub type CommentTest< /* Lifetime */ 'a + , + // Type + T + > = (); + + +pub type WithWhereClause where T: Clone, LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; + +pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); + +// #1683 +pub type Between = super::operators::Between, AsExpr>>; +pub type NotBetween = super::operators::NotBetween, AsExpr>>; diff --git a/rustfmt-core/tests/source/unions.rs b/rustfmt-core/tests/source/unions.rs new file mode 100644 index 00000000000..fc2908e2d9e --- /dev/null +++ b/rustfmt-core/tests/source/unions.rs @@ -0,0 +1,195 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + + /// A Doc comment +#[AnAttribute] +pub union Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1029 +pub union Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +union X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub union Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +// With a where clause and generics. +pub union Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +union Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +union Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +union Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +union Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +pub union State time::Timespec> { now: F } + +pub union State ()> { now: F } + +pub union State { now: F } + +union Palette { /// A map of indices in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +union FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +mod m { + union X where T: Sized { + a: T, + } +} + +union Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +union Foo {} +union Foo { + } +union Foo { + // comment + } +union Foo { + // trailing space -> + + + } +union Foo { /* comment */ } + +union LongUnion { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +union Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} diff --git a/rustfmt-core/tests/source/where-clause-rfc.rs b/rustfmt-core/tests/source/where-clause-rfc.rs new file mode 100644 index 00000000000..e41e9a6cea1 --- /dev/null +++ b/rustfmt-core/tests/source/where-clause-rfc.rs @@ -0,0 +1,58 @@ +// rustfmt-indent_style: Block + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; + +struct Exactly100CharsToSemicolon + (LongLongTypename, i32, i32) + where A: LongTrait1234; + +struct AlwaysOnNextLine where A: LongTrait { + x: i32 +} + +pub trait SomeTrait + where + T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr +{ +} + +// #2020 +impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { + fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) + where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssociatedItem), + { + // ... + } +} diff --git a/rustfmt-core/tests/source/where-clause.rs b/rustfmt-core/tests/source/where-clause.rs new file mode 100644 index 00000000000..9e4a2f65698 --- /dev/null +++ b/rustfmt-core/tests/source/where-clause.rs @@ -0,0 +1,16 @@ +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; + +struct Exactly100CharsToSemicolon + (LongLongTypename, i32, i32) + where A: LongTrait1234; + +struct AlwaysOnNextLine where A: LongTrait { + x: i32 +} diff --git a/rustfmt-core/tests/target/assignment.rs b/rustfmt-core/tests/target/assignment.rs new file mode 100644 index 00000000000..4e8689ed23e --- /dev/null +++ b/rustfmt-core/tests/target/assignment.rs @@ -0,0 +1,36 @@ +// Test assignment + +fn main() { + let some_var: Type; + + let mut mutable; + + let variable = + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; + + variable = + LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; + + let single_line_fit = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + single_line_fit = 5; + single_lit_fit >>= 10; +} + +fn break_meee() { + { + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) = match (block_start, block_end, block_size) { + x => 1, + _ => 2, + }; + } +} + +// #2018 +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = + "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/rustfmt-core/tests/target/associated-items.rs b/rustfmt-core/tests/target/associated-items.rs new file mode 100644 index 00000000000..1b0a828d029 --- /dev/null +++ b/rustfmt-core/tests/target/associated-items.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", ::default()); +} diff --git a/rustfmt-core/tests/target/associated-types-bounds-wrapping.rs b/rustfmt-core/tests/target/associated-types-bounds-wrapping.rs new file mode 100644 index 00000000000..d5b94a5e869 --- /dev/null +++ b/rustfmt-core/tests/target/associated-types-bounds-wrapping.rs @@ -0,0 +1,7 @@ +// rustfmt-max_width: 100 +// Test proper wrapping of long associated type bounds + +pub trait HttpService { + type WsService: 'static + + Service; +} diff --git a/rustfmt-core/tests/target/associated_type_defaults.rs b/rustfmt-core/tests/target/associated_type_defaults.rs new file mode 100644 index 00000000000..d0a08133725 --- /dev/null +++ b/rustfmt-core/tests/target/associated_type_defaults.rs @@ -0,0 +1,4 @@ +#![feature(associated_type_defaults)] +trait Foo { + type Bar = (); +} diff --git a/rustfmt-core/tests/target/attrib-extern-crate.rs b/rustfmt-core/tests/target/attrib-extern-crate.rs new file mode 100644 index 00000000000..ed64a0aeb07 --- /dev/null +++ b/rustfmt-core/tests/target/attrib-extern-crate.rs @@ -0,0 +1,17 @@ +// Attributes on extern crate. + +#[Attr1] +extern crate Bar; +#[Attr2] +#[Attr2] +extern crate Baz; +extern crate Foo; + +fn foo() { + #[Attr1] + extern crate Bar; + #[Attr2] + #[Attr2] + extern crate Baz; + extern crate Foo; +} diff --git a/rustfmt-core/tests/target/attrib.rs b/rustfmt-core/tests/target/attrib.rs new file mode 100644 index 00000000000..43c4f9f327f --- /dev/null +++ b/rustfmt-core/tests/target/attrib.rs @@ -0,0 +1,154 @@ +// rustfmt-wrap_comments: true +// Test attributes and doc comments are preserved. + +//! Doc comment + +#![attribute] + +//! Crate doc comment + +// Comment + +// Comment on attribute +#![the(attribute)] + +// Another comment + +#[invalid attribute] +fn foo() {} + +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. + +/// Blah blah blah. +impl Bar { + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + #[an_attribute] + fn foo(&mut self) -> isize {} + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + pub fn f2(self) { + (foo, bar) + } + + #[another_attribute] + fn f3(self) -> Dog {} + + /// Blah blah bing. + + #[attrib1] + /// Blah blah bing. + #[attrib2] + // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo + // loooooooooooong. + /// Blah blah bing. + fn f4(self) -> Cat {} + + // We want spaces around `=` + #[cfg(feature = "nightly")] + fn f5(self) -> Monkey {} +} + +// #984 +struct Foo { + #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] + foo: usize, +} + +// #1668 + +/// Default path (*nix) +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] +fn foo() { + #[cfg(target_os = "freertos")] + match port_id { + 'a' | 'A' => GpioPort { + port_address: GPIO_A, + }, + 'b' | 'B' => GpioPort { + port_address: GPIO_B, + }, + _ => panic!(), + } + + #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] + let x = 3; +} + +// #1777 +#[test] +#[should_panic(expected = "(")] +#[should_panic(expected = /* ( */ "(")] +#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] +#[should_panic( + /* (((((((( *//* + (((((((((()(((((((( */ + expected = "(" + // (((((((( +)] +fn foo() {} + +// #1799 +fn issue_1799() { + #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 + Some(Err(error)); + + #[allow(unreachable_code)] + // https://github.com/rust-lang/rust/issues/43336 + Some(Err(error)); +} + +// Formatting inner attributes +fn inner_attributes() { + #![this_is_an_inner_attribute(foo)] + + foo(); +} + +impl InnerAttributes() { + #![this_is_an_inner_attribute(foo)] + + fn foo() {} +} + +mod InnerAttributes { + #![this_is_an_inner_attribute(foo)] +} + +fn attributes_on_statements() { + // Local + #[attr(on(local))] + let x = 3; + + // Item + #[attr(on(item))] + use foo; + + // Expr + #[attr(on(expr))] + {} + + // Semi + #[attr(on(semi))] + foo(); + + // Mac + #[attr(on(mac))] + foo!(); +} + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, + Deserialize)] +pub struct HP(pub u8); diff --git a/rustfmt-core/tests/target/big-impl-rfc.rs b/rustfmt-core/tests/target/big-impl-rfc.rs new file mode 100644 index 00000000000..bc16f12c9d7 --- /dev/null +++ b/rustfmt-core/tests/target/big-impl-rfc.rs @@ -0,0 +1,87 @@ +// rustfmt-indent_style: Block + +// #1357 +impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> + for SelectStatement +where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} +impl Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} + +// #1689 +impl SubSelectDirect +where + M: select::Selector, + S: event::Stream, + F: for<'t> FnMut(transform::Api<'t, Stream>>) -> transform::Api<'t, X>, + X: event::Stream, +{ +} diff --git a/rustfmt-core/tests/target/big-impl.rs b/rustfmt-core/tests/target/big-impl.rs new file mode 100644 index 00000000000..6f122e7e0b6 --- /dev/null +++ b/rustfmt-core/tests/target/big-impl.rs @@ -0,0 +1,75 @@ +// #1357 +impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> + for SelectStatement +where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} +impl Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} diff --git a/rustfmt-core/tests/target/break-and-continue.rs b/rustfmt-core/tests/target/break-and-continue.rs new file mode 100644 index 00000000000..c01d8a07845 --- /dev/null +++ b/rustfmt-core/tests/target/break-and-continue.rs @@ -0,0 +1,23 @@ +// break and continue formatting + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} diff --git a/rustfmt-core/tests/target/catch.rs b/rustfmt-core/tests/target/catch.rs new file mode 100644 index 00000000000..640f9bade49 --- /dev/null +++ b/rustfmt-core/tests/target/catch.rs @@ -0,0 +1,21 @@ +#![feature(catch_expr)] + +fn main() { + let x = do catch { foo()? }; + + let x = do catch /* Invisible comment */ { foo()? }; + + let x = do catch { unsafe { foo()? } }; + + let y = match (do catch { foo()? }) { + _ => (), + }; + + do catch { + foo()?; + }; + + do catch { + // Regular do catch block + }; +} diff --git a/rustfmt-core/tests/target/chains-indent-tabbed.rs b/rustfmt-core/tests/target/chains-indent-tabbed.rs new file mode 100644 index 00000000000..ea6b5764e44 --- /dev/null +++ b/rustfmt-core/tests/target/chains-indent-tabbed.rs @@ -0,0 +1,10 @@ +// rustfmt-indent_style: Block + +fn test() { + let x = my_long_function() + .my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); +} diff --git a/rustfmt-core/tests/target/chains-indent-visual.rs b/rustfmt-core/tests/target/chains-indent-visual.rs new file mode 100644 index 00000000000..23814e3dbe1 --- /dev/null +++ b/rustfmt-core/tests/target/chains-indent-visual.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style: Visual + +fn test() { + let x = my_long_function().my_even_longer_function() + .my_nested_function() + .some_random_name() + .another_function() + .do_it(); +} diff --git a/rustfmt-core/tests/target/chains-visual.rs b/rustfmt-core/tests/target/chains-visual.rs new file mode 100644 index 00000000000..b842d73c99f --- /dev/null +++ b/rustfmt-core/tests/target/chains-visual.rs @@ -0,0 +1,159 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Visual +// Test chain formatting. + +fn main() { + // Don't put chains on a single line if it wasn't so in source. + let a = b.c.d.1.foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd + .eeeeeeee(); + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x().y(|| match cond() { + true => (), + false => (), + }); + + loong_func().quux(move || if true { 1 } else { 2 }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }) + .method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = + xxxxxxx.map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { field1: val1, + field2: val2, }; + + let x = Foo { field1: val1, + field2: val2, }.method_call() + .method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone()); + } + } + } + + if cond { + some(); + } else { + none(); + }.bar() + .baz(); + + Foo { x: val }.baz(|| { + force(); + multiline(); + }) + .quux(); + + Foo { y: i_am_multi_line, + z: ok, }.baz(|| { + force(); + multiline(); + }) + .quux(); + + a + match x { + true => "yay!", + false => "boo!", + }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) + .unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn issue_1389() { + let names = String::from_utf8(names)?.split('|') + .map(str::to_owned) + .collect(); +} + +fn issue1217() -> Result { + let random_chars: String = OsRng::new()?.gen_ascii_chars() + .take(self.bit_length) + .collect(); + + Ok(Mnemonic::new(&random_chars)) +} + +fn issue1236(options: Vec) -> Result> { + let process = Command::new("dmenu").stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; +} + +fn issue1434() { + for _ in 0..100 { + let prototype_id = + PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; + } +} + +fn issue2264() { + { + something.function() + .map(|| { + if let a_very_very_very_very_very_very_very_very_long_variable = + compute_this_variable() + { + println!("Hello"); + } + }) + .collect(); + } +} diff --git a/rustfmt-core/tests/target/chains.rs b/rustfmt-core/tests/target/chains.rs new file mode 100644 index 00000000000..8a41eec2bde --- /dev/null +++ b/rustfmt-core/tests/target/chains.rs @@ -0,0 +1,261 @@ +// rustfmt-normalize_comments: true +// rustfmt-use_small_heuristics: false +// Test chain formatting. + +fn main() { + let a = b.c.d.1.foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb + .ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd + .eeeeeeee(); + + let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo + .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x().y(|| match cond() { + true => (), + false => (), + }); + + loong_func().quux(move || { + if true { + 1 + } else { + 2 + } + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }) + .method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = + xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x); + + body.fold(Body::new(), |mut body, chunk| { + body.extend(chunk); + Ok(body) + }).and_then(move |body| { + let req = Request::from_parts(parts, body); + f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) + }); + + aaaaaaaaaaaaaaaa + .map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + }.method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push( + mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone(), + ); + } + } + } + + if cond { + some(); + } else { + none(); + }.bar() + .baz(); + + Foo { + x: val, + }.baz(|| { + force(); + multiline(); + }) + .quux(); + + Foo { + y: i_am_multi_line, + z: ok, + }.baz(|| { + force(); + multiline(); + }) + .quux(); + + a + match x { + true => "yay!", + false => "boo!", + }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + let x = expr?; + let y = expr.kaas()?.test(); + let loooooooooooooooooooooooooooooooooooooooooong = + does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); + let zzzz = expr?.another?.another?.another?.another?; + let aaa = x??????????????????????????????????????????????????????????????????????????; + + let y = a.very + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; + + parameterized(f, substs, def_id, Ns::Value, &[], |tcx| tcx.lookup_item_type(def_id).generics)?; + fooooooooooooooooooooooooooo()? + .bar()? + .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; +} + +fn issue_1004() { + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), + }?; + + ty::tls::with(|tcx| { + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + })?; +} + +fn issue1392() { + test_method( + r#" + if foo { + a(); + } + else { + b(); + } + "#.trim(), + ); +} + +// #2067 +impl Settings { + fn save(&self) -> Result<()> { + let mut file = File::create(&settings_path) + .chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; + } +} + +fn issue2126() { + { + { + { + { + { + let x = self.span_from( + sub_span.expect("No span found for struct arant variant"), + ); + self.sspanpan_from_span( + sub_span.expect("No span found for struct variant"), + ); + let x = self.spanpan_from_span( + sub_span.expect("No span found for struct variant"), + )?; + } + } + } + } + } +} + +// #2200 +impl Foo { + pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes { + let other_attrs = attrs + .iter() + .filter_map(|attr| { + attr.with_desugared_doc(|attr| { + if attr.check_name("doc") { + if let Some(mi) = attr.meta() { + if let Some(value) = mi.value_str() { + doc_strings.push(DocFragment::Include( + line, + attr.span, + filename, + contents, + )); + } + } + } + }) + }) + .collect(); + } +} + +// #2415 +// Avoid orphan in chain +fn issue2415() { + let base_url = (|| { + // stuff + + Ok((|| { + // stuff + Some(value.to_string()) + })().ok_or("")?) + })().unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); +} diff --git a/rustfmt-core/tests/target/closure-block-inside-macro.rs b/rustfmt-core/tests/target/closure-block-inside-macro.rs new file mode 100644 index 00000000000..c1260592083 --- /dev/null +++ b/rustfmt-core/tests/target/closure-block-inside-macro.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Block + +// #1547 +fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; + } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); +}); diff --git a/rustfmt-core/tests/target/closure.rs b/rustfmt-core/tests/target/closure.rs new file mode 100644 index 00000000000..5bc89d58222 --- /dev/null +++ b/rustfmt-core/tests/target/closure.rs @@ -0,0 +1,248 @@ +// rustfmt-normalize_comments: true +// Closures + +fn main() { + let square = (|i: i32| i * i); + + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| { + ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ) + }; + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // format comments. + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo() + } else { + field.span.lo() + } + }; + + let unblock_me = |trivial| closure(); + + let empty = |arg| {}; + + let simple = |arg| { + // comment formatting + foo(arg) + }; + + let test = || { + do_something(); + do_something_else(); + }; + + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { foo() }; + + let closure_with_return_type = + |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + + |arg1, arg2, _, _, arg3, arg4| { + let temp = arg4 + arg3; + arg2 * arg1 - temp + }; + + let block_body_with_comment = args.iter().map(|a| { + // Emitting only dep-info is possible only for final crate type, as + // as others may emit required metadata for dependent crate types + if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { + "--emit=dep-info" + } else { + a + } + }); +} + +fn issue311() { + let func = |x| println!("{}", x); + + (func)(0.0); +} + +fn issue863() { + let closure = |x| match x { + 0 => true, + _ => false, + } == true; +} + +fn issue934() { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) + } + } + } +} + +fn foo() { + lifetimes_iter___map(|lasdfasfd| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi() + }; + }); +} + +fn issue1405() { + open_raw_fd(fd, b'r').and_then(|file| { + Capture::new_raw(None, |_, err| unsafe { raw::pcap_fopen_offline(file, err) }) + }); +} + +fn issue1466() { + let vertex_buffer = frame.scope(|ctx| { + let buffer = ctx.create_host_visible_buffer::>(&vertices); + ctx.create_device_local_buffer(buffer) + }); +} + +fn issue470() { + { + { + { + let explicit_arg_decls = explicit_arguments.into_iter().enumerate().map( + |(index, (ty, pattern))| { + let lvalue = Lvalue::Arg(index as u32); + block = this.pattern( + block, + argument_extent, + hair::PatternRef::Hair(pattern), + &lvalue, + ); + ArgDecl { ty: ty } + }, + ); + } + } + } +} + +// #1509 +impl Foo { + pub fn bar(&self) { + Some(SomeType { + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| Ok(f))), + }) + } +} + +fn issue1329() { + aaaaaaaaaaaaaaaa + .map(|x| { + x += 1; + x + }) + .filter +} + +fn issue325() { + let f = + || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; +} + +fn issue1697() { + Test.func_a( + A_VERY_LONG_CONST_VARIABLE_NAME, + move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4, + ) +} + +fn issue1694() { + foooooo( + |_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| { + format!("refs/pull/{}/merge", pr_id) + }, + ) +} + +fn issue1713() { + rayon::join( + || recurse(left, is_less, pred, limit), + || recurse(right, is_less, Some(pivot), limit), + ); + + rayon::join( + 1, + || recurse(left, is_less, pred, limit), + 2, + || recurse(right, is_less, Some(pivot), limit), + ); +} + +fn issue2063() { + |ctx: Ctx<(String, String)>| -> io::Result { + Ok(Response::new().with_body(ctx.params.0)) + } +} + +fn issue1524() { + let f = |x| x; + let f = |x| x; + let f = |x| x; + let f = |x| x; + let f = |x| x; +} + +fn issue2171() { + foo(|| unsafe { + if PERIPHERALS { + loop {} + } else { + PERIPHERALS = true; + } + }) +} + +fn issue2207() { + a.map(|_| { + unsafe { a_very_very_very_very_very_very_very_long_function_name_or_anything_else() } + .to_string() + }) +} + +fn issue2262() { + result + .init(&mut result.slave.borrow_mut(), &mut (result.strategy)()) + .map_err(|factory| Error { + factory, + slave: None, + })?; +} diff --git a/rustfmt-core/tests/target/comment-inside-const.rs b/rustfmt-core/tests/target/comment-inside-const.rs new file mode 100644 index 00000000000..f847f2c69de --- /dev/null +++ b/rustfmt-core/tests/target/comment-inside-const.rs @@ -0,0 +1,9 @@ +fn issue982() { + const SOME_CONSTANT: u32 = + // Explanation why SOME_CONSTANT needs FLAG_A to be set. + FLAG_A | + // Explanation why SOME_CONSTANT needs FLAG_B to be set. + FLAG_B | + // Explanation why SOME_CONSTANT needs FLAG_C to be set. + FLAG_C; +} diff --git a/rustfmt-core/tests/target/comment-not-disappear.rs b/rustfmt-core/tests/target/comment-not-disappear.rs new file mode 100644 index 00000000000..646b37e46e2 --- /dev/null +++ b/rustfmt-core/tests/target/comment-not-disappear.rs @@ -0,0 +1,36 @@ +// All the comments here should not disappear. + +fn a() { + match x { + X | + // A comment + Y => {} + }; +} + +fn b() { + match x { + X => + // A comment + y + } +} + +fn c() { + a() /* ... */; +} + +fn foo() -> Vec { + (0..11) + .map(|x| + // This comment disappears. + if x % 2 == 0 { x } else { x * 2 }) + .collect() +} + +fn calc_page_len(prefix_len: usize, sofar: usize) -> usize { + 2 // page type and flags + + 1 // stored depth + + 2 // stored count + + prefix_len + sofar // sum of size of all the actual items +} diff --git a/rustfmt-core/tests/target/comment.rs b/rustfmt-core/tests/target/comment.rs new file mode 100644 index 00000000000..5abf5369066 --- /dev/null +++ b/rustfmt-core/tests/target/comment.rs @@ -0,0 +1,95 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//! Doc comment +fn test() { + //! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam + //! lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + + // comment + // comment2 + + code(); // leave this comment alone! + // ok? + + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + // viverra nec consectetur ante hendrerit. Donec et mollis dolor. + // Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + // tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + // libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + // amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + // felis, pulvinar a semper sed, adipiscing id dolor. + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment + // that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); // dontchangeme + // or me + + // #1388 + const EXCEPTION_PATHS: &'static [&'static str] = &[ + // std crates + "src/libstd/sys/", // Platform-specific code for std lives here. + "src/bootstrap", + ]; +} + +/// test123 +fn doc_comment() {} + +fn chains() { + foo.bar(|| { + let x = 10; + // comment + x + }) +} + +fn issue_1086() { + // +} + +// random comment + +fn main() { + // Test +} + +// #1643 +fn some_fn() // some comment +{ +} + +fn some_fn1() +// some comment +{ +} + +fn some_fn2() // some comment +{ +} + +fn some_fn3() // some comment some comment some comment some comment some comment some comment so +{ +} + +fn some_fn4() +// some comment some comment some comment some comment some comment some comment +// some comment +{ +} + +// #1603 +pub enum Foo { + A, // `/** **/` + B, // `/*!` + C, +} diff --git a/rustfmt-core/tests/target/comment2.rs b/rustfmt-core/tests/target/comment2.rs new file mode 100644 index 00000000000..04f84a15c95 --- /dev/null +++ b/rustfmt-core/tests/target/comment2.rs @@ -0,0 +1,5 @@ +// rustfmt-wrap_comments: true + +/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly +/// and justly. +pub mod foo {} diff --git a/rustfmt-core/tests/target/comment3.rs b/rustfmt-core/tests/target/comment3.rs new file mode 100644 index 00000000000..3a810590d7b --- /dev/null +++ b/rustfmt-core/tests/target/comment3.rs @@ -0,0 +1,6 @@ +// rustfmt-wrap_comments: true + +//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly +//! and justly. + +pub mod foo {} diff --git a/rustfmt-core/tests/target/comment4.rs b/rustfmt-core/tests/target/comment4.rs new file mode 100644 index 00000000000..e07abf74a81 --- /dev/null +++ b/rustfmt-core/tests/target/comment4.rs @@ -0,0 +1,51 @@ +#![allow(dead_code)] // bar + +//! Doc comment +fn test() { + // comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + +/// test123 +fn doc_comment() {} + +/* +Regression test for issue #956 + +(some very important text) +*/ + +/* +fn debug_function() { + println!("hello"); +} +// */ + +#[link_section=".vectors"] +#[no_mangle] // Test this attribute is preserved. +#[cfg_attr(rustfmt, rustfmt_skip)] +pub static ISSUE_1284: [i32; 16] = []; diff --git a/rustfmt-core/tests/target/comment5.rs b/rustfmt-core/tests/target/comment5.rs new file mode 100644 index 00000000000..c52f9b38977 --- /dev/null +++ b/rustfmt-core/tests/target/comment5.rs @@ -0,0 +1,16 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//@ special comment +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam +//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ +//@ foo +fn test() {} + +//@@@ another special comment +//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam +//@@@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@@@ +//@@@ foo +fn bar() {} diff --git a/rustfmt-core/tests/target/comment_crlf_newline.rs b/rustfmt-core/tests/target/comment_crlf_newline.rs new file mode 100644 index 00000000000..aab9e94d9e6 --- /dev/null +++ b/rustfmt-core/tests/target/comment_crlf_newline.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true +// Block comments followed by CRLF newlines should not an extra newline at the end + +// Something else diff --git a/rustfmt-core/tests/target/comments-fn.rs b/rustfmt-core/tests/target/comments-fn.rs new file mode 100644 index 00000000000..39af3fd064e --- /dev/null +++ b/rustfmt-core/tests/target/comments-fn.rs @@ -0,0 +1,39 @@ +// Test comments on functions are preserved. + +// Comment on foo. +fn foo( + a: aaaaaaaaaaaaa, // A comment + b: bbbbbbbbbbbbb, // a second comment + c: ccccccccccccc, + // Newline comment + d: ddddddddddddd, + // A multi line comment + // between args. + e: eeeeeeeeeeeee, /* comment before paren */ +) -> bar +where + F: Foo, // COmment after where clause + G: Goo, // final comment +{ + +} + +fn bar() {} + +fn baz() -> Baz /* Comment after return type */ {} + +fn some_fn() +where + T: Eq, // some comment +{ +} + +fn issue458(a: &str, f: F) +// comment1 +where + // comment2 + F: FnOnce(&str) -> bool, +{ + f(a); + () +} diff --git a/rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs b/rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs new file mode 100644 index 00000000000..9706699dc7a --- /dev/null +++ b/rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs @@ -0,0 +1,16 @@ +// rustfmt-blank_lines_lower_bound: 1 + +fn foo() {} + +fn bar() {} + +// comment +fn foobar() {} + +fn foo1() {} + +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs b/rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs new file mode 100644 index 00000000000..2755a264689 --- /dev/null +++ b/rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs @@ -0,0 +1,19 @@ +// rustfmt-brace_style: AlwaysNextLine +// Function brace style + +fn lorem() +{ + // body +} + +fn lorem(ipsum: usize) +{ + // body +} + +fn lorem(ipsum: T) +where + T: Add + Sub + Mul + Div, +{ + // body +} diff --git a/rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs b/rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs new file mode 100644 index 00000000000..23f98b6dd7a --- /dev/null +++ b/rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs @@ -0,0 +1,16 @@ +// rustfmt-brace_style: PreferSameLine +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) +where + T: Add + Sub + Mul + Div, { + // body +} diff --git a/rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs b/rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs new file mode 100644 index 00000000000..2afe59943a3 --- /dev/null +++ b/rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs @@ -0,0 +1,17 @@ +// rustfmt-brace_style: SameLineWhere +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) +where + T: Add + Sub + Mul + Div, +{ + // body +} diff --git a/rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs b/rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs new file mode 100644 index 00000000000..38ed449d178 --- /dev/null +++ b/rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs @@ -0,0 +1,27 @@ +// rustfmt-brace_style: AlwaysNextLine +// Item brace style + +enum Foo {} + +struct Bar {} + +struct Lorem +{ + ipsum: bool, +} + +struct Dolor +where + T: Eq, +{ + sit: T, +} + +#[cfg(test)] +mod tests +{ + #[test] + fn it_works() + { + } +} diff --git a/rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs b/rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs new file mode 100644 index 00000000000..5143d7517c7 --- /dev/null +++ b/rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs @@ -0,0 +1,18 @@ +// rustfmt-brace_style: PreferSameLine +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor +where + T: Eq, { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs b/rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs new file mode 100644 index 00000000000..8a3b2852654 --- /dev/null +++ b/rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs @@ -0,0 +1,19 @@ +// rustfmt-brace_style: SameLineWhere +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor +where + T: Eq, +{ + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/rustfmt-core/tests/target/configs/combine_control_expr/false.rs b/rustfmt-core/tests/target/configs/combine_control_expr/false.rs new file mode 100644 index 00000000000..81eff08660d --- /dev/null +++ b/rustfmt-core/tests/target/configs/combine_control_expr/false.rs @@ -0,0 +1,133 @@ +// rustfmt-indent_style: Block +// rustfmt-combine_control_expr: false +// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. + +fn main() { + // Call + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Mac + foo(foo!( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // MethodCall + foo(x.foo::( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Block + foo!({ + foo(); + bar(); + }); + + // Closure + foo(|x| { + let y = x + 1; + y + }); + + // Match + foo(match opt { + Some(x) => x, + None => y, + }); + + // Struct + foo(Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // If + foo!( + if x { + foo(); + } else { + bar(); + } + ); + + // IfLet + foo!( + if let Some(..) = x { + foo(); + } else { + bar(); + } + ); + + // While + foo!( + while x { + foo(); + bar(); + } + ); + + // WhileLet + foo!( + while let Some(..) = x { + foo(); + bar(); + } + ); + + // ForLoop + foo!( + for x in y { + foo(); + bar(); + } + ); + + // Loop + foo!( + loop { + foo(); + bar(); + } + ); + + // Tuple + foo(( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // AddrOf + foo(&bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Box + foo(box Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // Unary + foo(!bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Try + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )?); + + // Cast + foo(Bar { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + } as i64); +} diff --git a/rustfmt-core/tests/target/configs/combine_control_expr/true.rs b/rustfmt-core/tests/target/configs/combine_control_expr/true.rs new file mode 100644 index 00000000000..c5372c2ff37 --- /dev/null +++ b/rustfmt-core/tests/target/configs/combine_control_expr/true.rs @@ -0,0 +1,121 @@ +// rustfmt-indent_style: Block +// rustfmt-combine_control_expr: true +// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. + +fn main() { + // Call + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Mac + foo(foo!( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // MethodCall + foo(x.foo::( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Block + foo!({ + foo(); + bar(); + }); + + // Closure + foo(|x| { + let y = x + 1; + y + }); + + // Match + foo(match opt { + Some(x) => x, + None => y, + }); + + // Struct + foo(Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // If + foo!(if x { + foo(); + } else { + bar(); + }); + + // IfLet + foo!(if let Some(..) = x { + foo(); + } else { + bar(); + }); + + // While + foo!(while x { + foo(); + bar(); + }); + + // WhileLet + foo!(while let Some(..) = x { + foo(); + bar(); + }); + + // ForLoop + foo!(for x in y { + foo(); + bar(); + }); + + // Loop + foo!(loop { + foo(); + bar(); + }); + + // Tuple + foo(( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // AddrOf + foo(&bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Box + foo(box Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // Unary + foo(!bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Try + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )?); + + // Cast + foo(Bar { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + } as i64); +} diff --git a/rustfmt-core/tests/target/configs/comment_width/above.rs b/rustfmt-core/tests/target/configs/comment_width/above.rs new file mode 100644 index 00000000000..ddfecda65c1 --- /dev/null +++ b/rustfmt-core/tests/target/configs/comment_width/above.rs @@ -0,0 +1,8 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, + // consectetur adipiscing elit. +} diff --git a/rustfmt-core/tests/target/configs/comment_width/below.rs b/rustfmt-core/tests/target/configs/comment_width/below.rs new file mode 100644 index 00000000000..abbc5930c4c --- /dev/null +++ b/rustfmt-core/tests/target/configs/comment_width/below.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 80 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/rustfmt-core/tests/target/configs/comment_width/ignore.rs b/rustfmt-core/tests/target/configs/comment_width/ignore.rs new file mode 100644 index 00000000000..c86e71c2898 --- /dev/null +++ b/rustfmt-core/tests/target/configs/comment_width/ignore.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: false +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs b/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs new file mode 100644 index 00000000000..3b967f35a8e --- /dev/null +++ b/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: false +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, _, _) = (1, 2, 3, 4); +} diff --git a/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs b/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs new file mode 100644 index 00000000000..4f880abe80e --- /dev/null +++ b/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: true +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, ..) = (1, 2, 3, 4); +} diff --git a/rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs b/rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs new file mode 100644 index 00000000000..7dc06f207fe --- /dev/null +++ b/rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs @@ -0,0 +1,18 @@ +// rustfmt-control_brace_style: AlwaysNextLine +// Control brace style + +fn main() { + if lorem + { + println!("ipsum!"); + } + else + { + println!("dolor!"); + } + match magi + { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs b/rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs new file mode 100644 index 00000000000..993b6b681fe --- /dev/null +++ b/rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs @@ -0,0 +1,14 @@ +// rustfmt-control_brace_style: AlwaysSameLine +// Control brace style + +fn main() { + if lorem { + println!("ipsum!"); + } else { + println!("dolor!"); + } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs b/rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs new file mode 100644 index 00000000000..013852ee79a --- /dev/null +++ b/rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs @@ -0,0 +1,15 @@ +// rustfmt-control_brace_style: ClosingNextLine +// Control brace style + +fn main() { + if lorem { + println!("ipsum!"); + } + else { + println!("dolor!"); + } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/rustfmt-core/tests/target/configs/disable_all_formatting/false.rs b/rustfmt-core/tests/target/configs/disable_all_formatting/false.rs new file mode 100644 index 00000000000..1a0477ddb39 --- /dev/null +++ b/rustfmt-core/tests/target/configs/disable_all_formatting/false.rs @@ -0,0 +1,10 @@ +// rustfmt-disable_all_formatting: false +// Disable all formatting + +fn main() { + if lorem { + println!("ipsum!"); + } else { + println!("dolor!"); + } +} diff --git a/rustfmt-core/tests/target/configs/disable_all_formatting/true.rs b/rustfmt-core/tests/target/configs/disable_all_formatting/true.rs new file mode 100644 index 00000000000..736ccf56942 --- /dev/null +++ b/rustfmt-core/tests/target/configs/disable_all_formatting/true.rs @@ -0,0 +1,6 @@ +// rustfmt-disable_all_formatting: true +// Disable all formatting + +fn main() { + if lorem{println!("ipsum!");}else{println!("dolor!");} +} diff --git a/rustfmt-core/tests/target/configs/empty_item_single_line/false.rs b/rustfmt-core/tests/target/configs/empty_item_single_line/false.rs new file mode 100644 index 00000000000..b7886df2aa8 --- /dev/null +++ b/rustfmt-core/tests/target/configs/empty_item_single_line/false.rs @@ -0,0 +1,15 @@ +// rustfmt-empty_item_single_line: false +// Empty impl on single line + +impl Lorem { +} + +impl Ipsum { +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/rustfmt-core/tests/target/configs/empty_item_single_line/true.rs b/rustfmt-core/tests/target/configs/empty_item_single_line/true.rs new file mode 100644 index 00000000000..0755485fea9 --- /dev/null +++ b/rustfmt-core/tests/target/configs/empty_item_single_line/true.rs @@ -0,0 +1,10 @@ +// rustfmt-empty_item_single_line: true +// Empty impl on single line + +impl Lorem {} + +impl Ipsum {} + +fn lorem() {} + +fn lorem() {} diff --git a/rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs b/rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs new file mode 100644 index 00000000000..fa70ae78352 --- /dev/null +++ b/rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs @@ -0,0 +1,6 @@ +// rustfmt-error_on_line_overflow: false +// Error on line overflow + +fn main() { + let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; +} diff --git a/rustfmt-core/tests/target/configs/error_on_unformatted/false.rs b/rustfmt-core/tests/target/configs/error_on_unformatted/false.rs new file mode 100644 index 00000000000..6a78374e2a2 --- /dev/null +++ b/rustfmt-core/tests/target/configs/error_on_unformatted/false.rs @@ -0,0 +1,12 @@ +// rustfmt-error_on_unformatted: false +// Error on line overflow comment or string literals. + +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn main() { + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + let x = " "; + let a = " + +"; +} diff --git a/rustfmt-core/tests/target/configs/fn_args_density/compressed.rs b/rustfmt-core/tests/target/configs/fn_args_density/compressed.rs new file mode 100644 index 00000000000..99283722bee --- /dev/null +++ b/rustfmt-core/tests/target/configs/fn_args_density/compressed.rs @@ -0,0 +1,22 @@ +// rustfmt-fn_args_density: Compressed +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit, + ) { + // body + } +} diff --git a/rustfmt-core/tests/target/configs/fn_args_density/tall.rs b/rustfmt-core/tests/target/configs/fn_args_density/tall.rs new file mode 100644 index 00000000000..6ee43b41a19 --- /dev/null +++ b/rustfmt-core/tests/target/configs/fn_args_density/tall.rs @@ -0,0 +1,32 @@ +// rustfmt-fn_args_density: Tall +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} diff --git a/rustfmt-core/tests/target/configs/fn_args_density/vertical.rs b/rustfmt-core/tests/target/configs/fn_args_density/vertical.rs new file mode 100644 index 00000000000..d48b3492452 --- /dev/null +++ b/rustfmt-core/tests/target/configs/fn_args_density/vertical.rs @@ -0,0 +1,42 @@ +// rustfmt-fn_args_density: Vertical +// Function arguments density + +trait Lorem { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} diff --git a/rustfmt-core/tests/target/configs/fn_single_line/false.rs b/rustfmt-core/tests/target/configs/fn_single_line/false.rs new file mode 100644 index 00000000000..3d092f0c0bf --- /dev/null +++ b/rustfmt-core/tests/target/configs/fn_single_line/false.rs @@ -0,0 +1,11 @@ +// rustfmt-fn_single_line: false +// Single-expression function on single line + +fn lorem() -> usize { + 42 +} + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/rustfmt-core/tests/target/configs/fn_single_line/true.rs b/rustfmt-core/tests/target/configs/fn_single_line/true.rs new file mode 100644 index 00000000000..10d94e02f16 --- /dev/null +++ b/rustfmt-core/tests/target/configs/fn_single_line/true.rs @@ -0,0 +1,9 @@ +// rustfmt-fn_single_line: true +// Single-expression function on single line + +fn lorem() -> usize { 42 } + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/rustfmt-core/tests/target/configs/force_explicit_abi/false.rs b/rustfmt-core/tests/target/configs/force_explicit_abi/false.rs new file mode 100644 index 00000000000..3c48f8e0c78 --- /dev/null +++ b/rustfmt-core/tests/target/configs/force_explicit_abi/false.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: false +// Force explicit abi + +extern { + pub static lorem: c_int; +} diff --git a/rustfmt-core/tests/target/configs/force_explicit_abi/true.rs b/rustfmt-core/tests/target/configs/force_explicit_abi/true.rs new file mode 100644 index 00000000000..90f5a8c4ecb --- /dev/null +++ b/rustfmt-core/tests/target/configs/force_explicit_abi/true.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: true +// Force explicit abi + +extern "C" { + pub static lorem: c_int; +} diff --git a/rustfmt-core/tests/target/configs/force_multiline_block/false.rs b/rustfmt-core/tests/target/configs/force_multiline_block/false.rs new file mode 100644 index 00000000000..7cb4cac1d69 --- /dev/null +++ b/rustfmt-core/tests/target/configs/force_multiline_block/false.rs @@ -0,0 +1,20 @@ +// rustfmt-force_multiline_blocks: false +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/rustfmt-core/tests/target/configs/force_multiline_block/true.rs b/rustfmt-core/tests/target/configs/force_multiline_block/true.rs new file mode 100644 index 00000000000..aec50afe5a8 --- /dev/null +++ b/rustfmt-core/tests/target/configs/force_multiline_block/true.rs @@ -0,0 +1,22 @@ +// rustfmt-force_multiline_blocks: true +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/rustfmt-core/tests/target/configs/format_strings/false.rs b/rustfmt-core/tests/target/configs/format_strings/false.rs new file mode 100644 index 00000000000..ecca0d7d1fc --- /dev/null +++ b/rustfmt-core/tests/target/configs/format_strings/false.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; +} diff --git a/rustfmt-core/tests/target/configs/format_strings/true.rs b/rustfmt-core/tests/target/configs/format_strings/true.rs new file mode 100644 index 00000000000..fdd5ab2c97d --- /dev/null +++ b/rustfmt-core/tests/target/configs/format_strings/true.rs @@ -0,0 +1,9 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet \ + consectetur adipiscing elit \ + lorem ipsum dolor sit"; +} diff --git a/rustfmt-core/tests/target/configs/hard_tabs/false.rs b/rustfmt-core/tests/target/configs/hard_tabs/false.rs new file mode 100644 index 00000000000..ccfb53d8c86 --- /dev/null +++ b/rustfmt-core/tests/target/configs/hard_tabs/false.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: false +// Hard tabs + +fn lorem() -> usize { + 42 // spaces before 42 +} diff --git a/rustfmt-core/tests/target/configs/hard_tabs/true.rs b/rustfmt-core/tests/target/configs/hard_tabs/true.rs new file mode 100644 index 00000000000..3ed4e4f20aa --- /dev/null +++ b/rustfmt-core/tests/target/configs/hard_tabs/true.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: true +// Hard tabs + +fn lorem() -> usize { + 42 // spaces before 42 +} diff --git a/rustfmt-core/tests/target/configs/imports_indent/block.rs b/rustfmt-core/tests/target/configs/imports_indent/block.rs new file mode 100644 index 00000000000..84c3b26bd6e --- /dev/null +++ b/rustfmt-core/tests/target/configs/imports_indent/block.rs @@ -0,0 +1,7 @@ +// rustfmt-imports_indent: Block + +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, + SeparatorTactic, +}; diff --git a/rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs b/rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs new file mode 100644 index 00000000000..4a63556d45b --- /dev/null +++ b/rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs @@ -0,0 +1,18 @@ +// rustfmt-imports_indent: Block +// rustfmt-imports_layout: HorizontalVertical + +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use lists::{ + definitive_tactic, + itemize_list, + shape_for_tactic, + struct_lit_formatting, + struct_lit_shape, + struct_lit_tactic, + write_list, + DefinitiveListTactic, + ListFormatting, + ListItem, + ListTactic, + SeparatorTactic, +}; diff --git a/rustfmt-core/tests/target/configs/imports_layout/mixed.rs b/rustfmt-core/tests/target/configs/imports_layout/mixed.rs new file mode 100644 index 00000000000..5d3349a01bb --- /dev/null +++ b/rustfmt-core/tests/target/configs/imports_layout/mixed.rs @@ -0,0 +1,9 @@ +// rustfmt-imports_indent: Block +// rustfmt-imports_layout: Mixed + +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, + SeparatorTactic, +}; diff --git a/rustfmt-core/tests/target/configs/indent_style/block_args.rs b/rustfmt-core/tests/target/configs/indent_style/block_args.rs new file mode 100644 index 00000000000..80f4e133356 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_args.rs @@ -0,0 +1,47 @@ +// rustfmt-indent_style: Block +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem( + ipsum: usize, + dolor: usize, + sit: usize, + amet: usize, + consectetur: usize, + adipiscing: usize, + elit: usize, +) { + // body +} + +// #1441 +extern "system" { + pub fn GetConsoleHistoryInfo( + console_history_info: *mut ConsoleHistoryInfo, + ) -> Boooooooooooooool; +} + +// rustfmt should not add trailing comma for variadic function. See #1623. +extern "C" { + pub fn variadic_fn( + first_parameter: FirstParameterType, + second_parameter: SecondParameterType, + ... + ); +} + +// #1652 +fn deconstruct( + foo: Bar, +) -> ( + SocketAddr, + Header, + Method, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_array.rs b/rustfmt-core/tests/target/configs/indent_style/block_array.rs new file mode 100644 index 00000000000..5d458248c0b --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_array.rs @@ -0,0 +1,14 @@ +// rustfmt-indent_style: Block +// Array layout + +fn main() { + let lorem = vec![ + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ]; +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_call.rs b/rustfmt-core/tests/target/configs/indent_style/block_call.rs new file mode 100644 index 00000000000..d3522214c2e --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_call.rs @@ -0,0 +1,149 @@ +// rustfmt-indent_style: Block +// Function call style + +fn main() { + lorem( + "lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ); + // #1501 + let hyper = Arc::new(Client::with_connector(HttpsConnector::new( + TlsClient::new(), + ))); + + // chain + let x = yooooooooooooo + .fooooooooooooooo + .baaaaaaaaaaaaar(hello, world); + + // #1380 + { + { + let creds = self.client + .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; + } + } + + // nesting macro and function call + try!(foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + )); + try!(foo(try!( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ))); +} + +// #1521 +impl Foo { + fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { + unsafe { + Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords( + self.render_texture, + point.raw(), + view.raw(), + )) + } + } +} + +fn issue1420() { + given( + r#" + # Getting started + ... + "#, + ).running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| Post { + title: row.get(0), + date: row.get(1), + }, + )?; + + Ok(()) +} + +// #1449 +fn future_rayon_wait_1_thread() { + // run with only 1 worker thread; this would deadlock if we couldn't make progress + let mut result = None; + ThreadPool::new(Configuration::new().num_threads(1)) + .unwrap() + .install(|| { + scope(|s| { + use std::sync::mpsc::channel; + let (tx, rx) = channel(); + let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); + // ^^^^ FIXME: why is this needed? + let b = s.spawn_future(a.map(|v| v + 1)); + let c = s.spawn_future(b.map(|v| v + 1)); + s.spawn(move |_| tx.send(20).unwrap()); + result = Some(c.rayon_wait().unwrap()); + }); + }); + assert_eq!(result, Some(22)); +} + +// #1494 +impl Cursor { + fn foo() { + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical != *self { + canonical.num_template_args() + } else { + None + } + }); + } +} + +fn issue1581() { + bootstrap.checks.register("PERSISTED_LOCATIONS", move || { + if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + } + }); +} + +fn issue1651() { + { + let type_list: Vec<_> = + try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + } +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_chain.rs b/rustfmt-core/tests/target/configs/indent_style/block_chain.rs new file mode 100644 index 00000000000..23340a4aba2 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_chain.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Block +// Chain indent + +fn main() { + let lorem = ipsum + .dolor() + .sit() + .amet() + .consectetur() + .adipiscing() + .elite(); +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_generic.rs b/rustfmt-core/tests/target/configs/indent_style/block_generic.rs new file mode 100644 index 00000000000..c4fcaaf65d1 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_generic.rs @@ -0,0 +1,22 @@ +// rustfmt-indent_style: Block +// Generics indent + +fn lorem< + Ipsum: Eq = usize, + Dolor: Eq = usize, + Sit: Eq = usize, + Amet: Eq = usize, + Adipiscing: Eq = usize, + Consectetur: Eq = usize, + Elit: Eq = usize, +>( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + adipiscing: Adipiscing, + consectetur: Consectetur, + elit: Elit, +) -> T { + // body +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs b/rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs new file mode 100644 index 00000000000..656b562266f --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style: Block +// Struct literal-style + +fn main() { + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs b/rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs new file mode 100644 index 00000000000..5531e61ddc8 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs @@ -0,0 +1,14 @@ +// rustfmt-indent_style: Block +// rustfmt-max_width: 80 +// rustfmt-tab_spaces: 2 + +// #1427 +fn main() { + exceptaions::config(move || { + ( + NmiConfig {}, + HardFaultConfig {}, + SysTickConfig { gpio_sbsrr }, + ) + }); +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs b/rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs new file mode 100644 index 00000000000..a7e8590ed97 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs @@ -0,0 +1,11 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo( + a, + oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), + ); +} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs b/rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs new file mode 100644 index 00000000000..ad7e0b8f363 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Block +// Where predicate indent + +fn lorem() -> T +where + Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq, +{ + // body +} diff --git a/rustfmt-core/tests/target/configs/indent_style/default.rs b/rustfmt-core/tests/target/configs/indent_style/default.rs new file mode 100644 index 00000000000..a8f0902b34e --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/default.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Visual +// Where style + +fn lorem() -> T + where Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq +{ + // body +} diff --git a/rustfmt-core/tests/target/configs/indent_style/rfc_control.rs b/rustfmt-core/tests/target/configs/indent_style/rfc_control.rs new file mode 100644 index 00000000000..6619d8b2630 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/rfc_control.rs @@ -0,0 +1,39 @@ +// rustfmt-indent_style: Block + +// #1618 +fn main() { + loop { + if foo { + if ((right_paddle_speed < 0.) && (right_paddle.position().y - paddle_size.y / 2. > 5.)) + || ((right_paddle_speed > 0.) + && (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) + { + foo + } + if ai_timer.elapsed_time().as_microseconds() > ai_time.as_microseconds() { + if ball.position().y + ball_radius > right_paddle.position().y + paddle_size.y / 2. + { + foo + } + } + } + } +} + +fn issue1656() { + { + { + match rewrite { + Some(ref body_str) + if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) + || !context.config.match_arm_blocks() + || (extend && first_line_width(body_str) <= arm_shape.width) + || is_block => + { + return None; + } + _ => {} + } + } + } +} diff --git a/rustfmt-core/tests/target/configs/indent_style/rfc_where.rs b/rustfmt-core/tests/target/configs/indent_style/rfc_where.rs new file mode 100644 index 00000000000..a7b9a4f02b3 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/rfc_where.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Block +// Where style + +fn lorem() -> T +where + Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq, +{ + // body +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_args.rs b/rustfmt-core/tests/target/configs/indent_style/visual_args.rs new file mode 100644 index 00000000000..04c2eaee3cf --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_args.rs @@ -0,0 +1,40 @@ +// rustfmt-indent_style: Visual +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem(ipsum: usize, + dolor: usize, + sit: usize, + amet: usize, + consectetur: usize, + adipiscing: usize, + elit: usize) { + // body +} + +// #1922 +extern "C" { + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + a: *const lapack_complex_float, + lda: lapack_int, + ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int) + -> lapack_int; + + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + lda: lapack_int, + ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int) + -> lapack_int; +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_array.rs b/rustfmt-core/tests/target/configs/indent_style/visual_array.rs new file mode 100644 index 00000000000..1da6ff23738 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_array.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Visual +// Array layout + +fn main() { + let lorem = vec!["ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit"]; +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_call.rs b/rustfmt-core/tests/target/configs/indent_style/visual_call.rs new file mode 100644 index 00000000000..5454c44ef96 --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_call.rs @@ -0,0 +1,13 @@ +// rustfmt-indent_style: Visual +// Function call style + +fn main() { + lorem("lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit"); +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_chain.rs b/rustfmt-core/tests/target/configs/indent_style/visual_chain.rs new file mode 100644 index 00000000000..569f3d8b81d --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_chain.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Visual +// Chain indent + +fn main() { + let lorem = ipsum.dolor() + .sit() + .amet() + .consectetur() + .adipiscing() + .elite(); +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_generics.rs b/rustfmt-core/tests/target/configs/indent_style/visual_generics.rs new file mode 100644 index 00000000000..491075a146d --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_generics.rs @@ -0,0 +1,20 @@ +// rustfmt-indent_style: Visual +// Generics indent + +fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + adipiscing: Adipiscing, + consectetur: Consectetur, + elit: Elit) + -> T { + // body +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs b/rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs new file mode 100644 index 00000000000..b4effba0e8a --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs @@ -0,0 +1,7 @@ +// rustfmt-indent_style: Visual +// Struct literal-style + +fn main() { + let lorem = Lorem { ipsum: dolor, + sit: amet, }; +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs b/rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs new file mode 100644 index 00000000000..9738d397dbf --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs b/rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs new file mode 100644 index 00000000000..45799dcd5fc --- /dev/null +++ b/rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Visual +// Where predicate indent + +fn lorem() -> T + where Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq +{ + // body +} diff --git a/rustfmt-core/tests/target/configs/match_arm_blocks/false.rs b/rustfmt-core/tests/target/configs/match_arm_blocks/false.rs new file mode 100644 index 00000000000..4d53a96a7b7 --- /dev/null +++ b/rustfmt-core/tests/target/configs/match_arm_blocks/false.rs @@ -0,0 +1,10 @@ +// rustfmt-match_arm_blocks: false +// Wrap match-arms + +fn main() { + match lorem { + true => + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => println!("{}", sit), + } +} diff --git a/rustfmt-core/tests/target/configs/match_arm_blocks/true.rs b/rustfmt-core/tests/target/configs/match_arm_blocks/true.rs new file mode 100644 index 00000000000..d75ef03397a --- /dev/null +++ b/rustfmt-core/tests/target/configs/match_arm_blocks/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: true +// Wrap match-arms + +fn main() { + match lorem { + true => { + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) + } + false => println!("{}", sit), + } +} diff --git a/rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs b/rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs new file mode 100644 index 00000000000..70e02955fb0 --- /dev/null +++ b/rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: false +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + } + Lorem::Dolor => println!("dolor"), + } +} diff --git a/rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs b/rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs new file mode 100644 index 00000000000..b78b046dc1c --- /dev/null +++ b/rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: true +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + }, + Lorem::Dolor => println!("dolor"), + } +} diff --git a/rustfmt-core/tests/target/configs/merge_derives/true.rs b/rustfmt-core/tests/target/configs/merge_derives/true.rs new file mode 100644 index 00000000000..4d0148b1c6e --- /dev/null +++ b/rustfmt-core/tests/target/configs/merge_derives/true.rs @@ -0,0 +1,40 @@ +// rustfmt-merge_derives: true +// Merge multiple derives to a single one. + +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} + +#[derive(Eq, PartialEq, Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum FooBar {} + +mod foo { + #[bar] + #[derive(Eq, PartialEq)] + #[foo] + #[derive(Debug)] + #[foobar] + #[derive(Copy, Clone)] + pub enum Foo {} +} + +mod bar { + #[derive(Eq, PartialEq, Debug)] + #[foobar] + #[derive(Copy, Clone)] + pub enum Bar {} +} + +mod foobar { + #[derive(Eq, PartialEq, Debug, Copy, Clone)] + pub enum FooBar {} +} diff --git a/rustfmt-core/tests/target/configs/normalize_comments/false.rs b/rustfmt-core/tests/target/configs/normalize_comments/false.rs new file mode 100644 index 00000000000..488962ed936 --- /dev/null +++ b/rustfmt-core/tests/target/configs/normalize_comments/false.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: false +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +/* sit amet: */ +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/target/configs/normalize_comments/true.rs b/rustfmt-core/tests/target/configs/normalize_comments/true.rs new file mode 100644 index 00000000000..0bdbe08ab4f --- /dev/null +++ b/rustfmt-core/tests/target/configs/normalize_comments/true.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: true +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +// sit amet: +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs b/rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs new file mode 100644 index 00000000000..6bef132e5c3 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: false + +extern crate foo; +extern crate bar; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs b/rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs new file mode 100644 index 00000000000..86aba38b5d1 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: true + +extern crate bar; +extern crate foo; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/rustfmt-core/tests/target/configs/reorder_imported_names/false.rs b/rustfmt-core/tests/target/configs/reorder_imported_names/false.rs new file mode 100644 index 00000000000..91db89ceeaa --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_imported_names/false.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: false +// Reorder imported names + +use super::{lorem, ipsum, dolor, sit}; diff --git a/rustfmt-core/tests/target/configs/reorder_imported_names/true.rs b/rustfmt-core/tests/target/configs/reorder_imported_names/true.rs new file mode 100644 index 00000000000..59f55f4718a --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_imported_names/true.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: true +// Reorder imported names + +use super::{dolor, ipsum, lorem, sit}; diff --git a/rustfmt-core/tests/target/configs/reorder_imports/false.rs b/rustfmt-core/tests/target/configs/reorder_imports/false.rs new file mode 100644 index 00000000000..4b85684dc01 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_imports/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_imports: false +// Reorder imports + +use lorem; +use ipsum; +use dolor; +use sit; diff --git a/rustfmt-core/tests/target/configs/reorder_imports/true.rs b/rustfmt-core/tests/target/configs/reorder_imports/true.rs new file mode 100644 index 00000000000..e4ff7295fd0 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_imports/true.rs @@ -0,0 +1,19 @@ +// rustfmt-reorder_imports: true +// Reorder imports + +use dolor; +use ipsum; +use lorem; +use sit; + +fn foo() { + use A; + use B; + use C; + + bar(); + + use D; + use E; + use F; +} diff --git a/rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs b/rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs new file mode 100644 index 00000000000..29460da50aa --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs @@ -0,0 +1,12 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: false +// Reorder imports in group + +use dolor; +/// This comment should stay with `use ipsum;` +use ipsum; +use lorem; +use sit; +use std::io; +/// This comment should stay with `use std::mem;` +use std::mem; diff --git a/rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs b/rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs new file mode 100644 index 00000000000..c5e353662b5 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: true +// Reorder imports in group + +use std::io; +/// This comment should stay with `use std::mem;` +use std::mem; + +use dolor; +/// This comment should stay with `use ipsum;` +use ipsum; +use lorem; +use sit; diff --git a/rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/target/configs/reorder_modules/false.rs b/rustfmt-core/tests/target/configs/reorder_modules/false.rs new file mode 100644 index 00000000000..56b1aa03ed7 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_modules/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: false +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/target/configs/reorder_modules/true.rs b/rustfmt-core/tests/target/configs/reorder_modules/true.rs new file mode 100644 index 00000000000..18361e88b5f --- /dev/null +++ b/rustfmt-core/tests/target/configs/reorder_modules/true.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: true +// Reorder modules + +mod dolor; +mod ipsum; +mod lorem; +mod sit; diff --git a/rustfmt-core/tests/target/configs/space_before_colon/true.rs b/rustfmt-core/tests/target/configs/space_before_colon/true.rs new file mode 100644 index 00000000000..e2895b5d77b --- /dev/null +++ b/rustfmt-core/tests/target/configs/space_before_colon/true.rs @@ -0,0 +1,11 @@ +// rustfmt-space_before_colon: true +// Space before colon + +fn lorem(t : T) { + let ipsum : Dolor = sit; +} + +const LOREM : Lorem = Lorem { + ipsum : dolor, + sit : amet, +}; diff --git a/rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs b/rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs new file mode 100644 index 00000000000..6319da98572 --- /dev/null +++ b/rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: false +// Spaces around ranges + +fn main() { + let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } +} diff --git a/rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs b/rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs new file mode 100644 index 00000000000..7bfcc23c8ea --- /dev/null +++ b/rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: true +// Spaces around ranges + +fn main() { + let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } +} diff --git a/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs b/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs new file mode 100644 index 00000000000..908373ca9b0 --- /dev/null +++ b/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs @@ -0,0 +1,7 @@ +// rustfmt-spaces_within_parens_and_brackets: false +// Spaces within parens and brackets + +fn lorem(t: T) { + let lorem = (ipsum, dolor); + let lorem: [usize; 2] = [ipsum, dolor]; +} diff --git a/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs b/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs new file mode 100644 index 00000000000..7aff7131506 --- /dev/null +++ b/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs @@ -0,0 +1,145 @@ +// rustfmt-spaces_within_parens_and_brackets: true +// Spaces within parens and brackets + +fn lorem< T: Eq >( t: T ) { + let lorem = ( ipsum, dolor ); + let lorem: [ usize; 2 ] = [ ipsum, dolor ]; +} + +enum E { + A( u32 ), + B( u32, u32 ), + C( u32, u32, u32 ), + D(), +} + +struct TupleStruct0(); +struct TupleStruct1( u32 ); +struct TupleStruct2( u32, u32 ); + +fn fooEmpty() {} + +fn foo( e: E, _: u32 ) -> ( u32, u32 ) { + // Tuples + let t1 = (); + let t2 = ( 1, ); + let t3 = ( 1, 2 ); + + let ts0 = TupleStruct0(); + let ts1 = TupleStruct1( 1 ); + let ts2 = TupleStruct2( 1, 2 ); + + // Tuple pattern + let ( a, b, c ) = ( 1, 2, 3 ); + + // Expressions + let x = ( 1 + 2 ) * ( 3 ); + + // Function call + fooEmpty(); + foo( 1, 2 ); + + // Pattern matching + match e { + A( _ ) => (), + B( _, _ ) => (), + C( .. ) => (), + D => (), + } + + ( 1, 2 ) +} + +struct Foo< T > { + i: T, +} + +struct Bar< T, E > { + i: T, + e: E, +} + +struct Foo< 'a > { + i: &'a str, +} + +enum E< T > { + T( T ), +} + +enum E< T, S > { + T( T ), + S( S ), +} + +fn foo< T >( a: T ) { + foo::< u32 >( 10 ); +} + +fn foo< T, E >( a: T, b: E ) { + foo::< u32, str >( 10, "bar" ); +} + +fn foo< T: Send, E: Send >( a: T, b: E ) { + foo::< u32, str >( 10, "bar" ); + + let opt: Option< u32 >; + let res: Result< u32, String >; +} + +fn foo< 'a >( a: &'a str ) { + foo( "foo" ); +} + +fn foo< 'a, 'b >( a: &'a str, b: &'b str ) { + foo( "foo", "bar" ); +} + +impl Foo { + fn bar() { + < Foo as Foo >::bar(); + } +} + +trait MyTrait< A, D > {} +impl< A: Send, D: Send > MyTrait< A, D > for Foo {} + +fn foo() +where + for< 'a > u32: 'a, +{ +} + +fn main() { + let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; + let arr: [ i32; 500 ] = [ 0; 500 ]; + + let v = vec![ 1, 2, 3 ]; + assert_eq!( arr, [ 1, 2, 3 ] ); + + let i = arr[ 0 ]; + + let slice = &arr[ 1..2 ]; + + let line100_________________________________________________________________________ = [ 1, 2 ]; + let line101__________________________________________________________________________ = + [ 1, 2 ]; + let line102___________________________________________________________________________ = + [ 1, 2 ]; + let line103____________________________________________________________________________ = + [ 1, 2 ]; + let line104_____________________________________________________________________________ = + [ 1, 2 ]; + + let line100_____________________________________________________________________ = vec![ 1, 2 ]; + let line101______________________________________________________________________ = + vec![ 1, 2 ]; + let line102_______________________________________________________________________ = + vec![ 1, 2 ]; + let line103________________________________________________________________________ = + vec![ 1, 2 ]; + let line104_________________________________________________________________________ = + vec![ 1, 2 ]; +} + +fn f( slice: &[ i32 ] ) {} diff --git a/rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs b/rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs new file mode 100644 index 00000000000..b84afc56835 --- /dev/null +++ b/rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs @@ -0,0 +1,467 @@ +// rustfmt-struct_field_align_threshold: 20 +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false + +struct Foo { + x: u32, + yy: u32, // comment + zzz: u32, +} + +pub struct Bar { + x: u32, + yy: u32, + zzz: u32, + + xxxxxxx: u32, +} + +fn main() { + let foo = Foo { + x: 0, + yy: 1, + zzz: 2, + }; + + let bar = Bar { + x: 0, + yy: 1, + zzz: 2, + + xxxxxxx: 3, + }; +} + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct NewInt( + pub i32, + SomeType, // inline comment + T, // sup +); + +struct Qux< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy, +>( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple( + // Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +struct Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +struct Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +// Will this be a one-liner? +struct Tuple( + A, // Comment + B, +); + +pub struct State time::Timespec> { + now: F, +} + +pub struct State ()> { + now: F, +} + +pub struct State { + now: F, +} + +struct Palette { + /// A map of indices in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(T); +struct Foo(T) +where + T: Copy, + T: Eq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +); +struct Foo( + TTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU, // Bar + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU, +); + +mod m { + struct X + where + T: Sized, + { + a: T, + } +} + +struct Foo( + TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU, +); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +struct Foo {} +struct Foo {} +struct Foo { + // comment +} +struct Foo { + // trailing space -> +} +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: f(), + b: b(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a: Bar, b: f() }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S { a: 0, ..b }; +} + +fn issue201_2() { + let s = S { a: S2 { ..c }, ..b }; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo { a: 1, b: f(2) }; + Foo { + a: 1, + b: f(2), + ..g(3) + }; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { + ..base + }; + IntrinsicISizesContribution { + content_intrinsic_sizes: IntrinsicISizes { + minimum_inline_size: 0, + }, + }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { + a: bb, + c: dd, + e: ff, + }; + + Foo { + a: ddddddddddddddddddddd, + b: cccccccccccccccccccccccccccccccccccccc, + }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { + a: aaaaaaaaaa, + b: bbbbbbbb, + c: cccccccccc, + d: dddddddddd, // a comment + e: eeeeeeeee, + }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, ..base }; + Foo { + aaaaaaaaaa, + bbbbbbbb, + cccccccccc, + dddddddddd, // a comment + eeeeeeeee, + }; + Record { + ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; +} diff --git a/rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs b/rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs new file mode 100644 index 00000000000..e2732b5a7c9 --- /dev/null +++ b/rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs @@ -0,0 +1,9 @@ +// rustfmt-struct_lit_single_line: false +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; +} diff --git a/rustfmt-core/tests/target/configs/tab_spaces/2.rs b/rustfmt-core/tests/target/configs/tab_spaces/2.rs new file mode 100644 index 00000000000..85961706ea7 --- /dev/null +++ b/rustfmt-core/tests/target/configs/tab_spaces/2.rs @@ -0,0 +1,14 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { + let ipsum = dolor(); + let sit = vec![ + "amet", + "consectetur", + "adipiscing", + "elit.", + ]; +} diff --git a/rustfmt-core/tests/target/configs/tab_spaces/4.rs b/rustfmt-core/tests/target/configs/tab_spaces/4.rs new file mode 100644 index 00000000000..524a55121e4 --- /dev/null +++ b/rustfmt-core/tests/target/configs/tab_spaces/4.rs @@ -0,0 +1,14 @@ +// rustfmt-tab_spaces: 4 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { + let ipsum = dolor(); + let sit = vec![ + "amet", + "consectetur", + "adipiscing", + "elit.", + ]; +} diff --git a/rustfmt-core/tests/target/configs/trailing_comma/always.rs b/rustfmt-core/tests/target/configs/trailing_comma/always.rs new file mode 100644 index 00000000000..951dc680912 --- /dev/null +++ b/rustfmt-core/tests/target/configs/trailing_comma/always.rs @@ -0,0 +1,14 @@ +// rustfmt-trailing_comma: Always +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { + ipsum, + dolor, + sit, + amet, + consectetur, + adipiscing, + } = elit; +} diff --git a/rustfmt-core/tests/target/configs/trailing_comma/never.rs b/rustfmt-core/tests/target/configs/trailing_comma/never.rs new file mode 100644 index 00000000000..ae0e50f96d1 --- /dev/null +++ b/rustfmt-core/tests/target/configs/trailing_comma/never.rs @@ -0,0 +1,35 @@ +// rustfmt-trailing_comma: Never +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit } = amet; + let Lorem { + ipsum, + dolor, + sit, + amet, + consectetur, + adipiscing + } = elit; + + // #1544 + if let VrMsg::ClientReply { + request_num: reply_req_num, + value, + .. + } = msg + { + let _ = safe_assert_eq!(reply_req_num, request_num, op); + return Ok((request_num, op, value)); + } + + // #1710 + pub struct FileInput { + input: StringInput, + file_name: OsString + } + match len { + Some(len) => Ok(new(self.input, self.pos + len)), + None => Err(self) + } +} diff --git a/rustfmt-core/tests/target/configs/trailing_comma/vertical.rs b/rustfmt-core/tests/target/configs/trailing_comma/vertical.rs new file mode 100644 index 00000000000..7283cde8d06 --- /dev/null +++ b/rustfmt-core/tests/target/configs/trailing_comma/vertical.rs @@ -0,0 +1,14 @@ +// rustfmt-trailing_comma: Vertical +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit } = amet; + let Lorem { + ipsum, + dolor, + sit, + amet, + consectetur, + adipiscing, + } = elit; +} diff --git a/rustfmt-core/tests/target/configs/trailing_semicolon/false.rs b/rustfmt-core/tests/target/configs/trailing_semicolon/false.rs new file mode 100644 index 00000000000..9fa746e9c0f --- /dev/null +++ b/rustfmt-core/tests/target/configs/trailing_semicolon/false.rs @@ -0,0 +1,27 @@ +// rustfmt-trailing_semicolon: false + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b + } + + let x = loop { + break 5 + }; + + let x = 'c: loop { + break 'c 5 + }; +} + +fn foo() -> usize { + return 0 +} diff --git a/rustfmt-core/tests/target/configs/trailing_semicolon/true.rs b/rustfmt-core/tests/target/configs/trailing_semicolon/true.rs new file mode 100644 index 00000000000..61b6843d677 --- /dev/null +++ b/rustfmt-core/tests/target/configs/trailing_semicolon/true.rs @@ -0,0 +1,27 @@ +// rustfmt-trailing_semicolon: true + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} + +fn foo() -> usize { + return 0; +} diff --git a/rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs b/rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs new file mode 100644 index 00000000000..4b3e02e19ea --- /dev/null +++ b/rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs @@ -0,0 +1,6 @@ +// rustfmt-type_punctuation_density: Compressed +// Type punctuation density + +fn lorem() { + // body +} diff --git a/rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs b/rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs new file mode 100644 index 00000000000..8909036e688 --- /dev/null +++ b/rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs @@ -0,0 +1,6 @@ +// rustfmt-type_punctuation_density: Wide +// Type punctuation density + +fn lorem() { + // body +} diff --git a/rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs b/rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs new file mode 100644 index 00000000000..dcebe0b6f1d --- /dev/null +++ b/rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs @@ -0,0 +1,15 @@ +// rustfmt-use_field_init_shorthand: false +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { x: x, y: y, z: z }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs b/rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs new file mode 100644 index 00000000000..ad78093ee8e --- /dev/null +++ b/rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs @@ -0,0 +1,15 @@ +// rustfmt-use_field_init_shorthand: true +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { x, y, z }; + + let b = Bar { + x, + y, + #[attr] + z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/rustfmt-core/tests/target/configs/use_try_shorthand/false.rs b/rustfmt-core/tests/target/configs/use_try_shorthand/false.rs new file mode 100644 index 00000000000..de7f8b4a5e2 --- /dev/null +++ b/rustfmt-core/tests/target/configs/use_try_shorthand/false.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: false +// Use try! shorthand + +fn main() { + let lorem = try!(ipsum.map(|dolor| dolor.sit())); +} diff --git a/rustfmt-core/tests/target/configs/use_try_shorthand/true.rs b/rustfmt-core/tests/target/configs/use_try_shorthand/true.rs new file mode 100644 index 00000000000..d3aa035792c --- /dev/null +++ b/rustfmt-core/tests/target/configs/use_try_shorthand/true.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: true +// Use try! shorthand + +fn main() { + let lorem = ipsum.map(|dolor| dolor.sit())?; +} diff --git a/rustfmt-core/tests/target/configs/where_single_line/true.rs b/rustfmt-core/tests/target/configs/where_single_line/true.rs new file mode 100644 index 00000000000..c4a7f5d3802 --- /dev/null +++ b/rustfmt-core/tests/target/configs/where_single_line/true.rs @@ -0,0 +1,28 @@ +// rustfmt-where_single_line: true +// Where style + +fn lorem_two_items() -> T +where + Ipsum: Eq, + Lorem: Eq, +{ + // body +} + +fn lorem_multi_line( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T +where + Ipsum: Eq, +{ + // body +} + +fn lorem() -> T +where Ipsum: Eq { + // body +} diff --git a/rustfmt-core/tests/target/configs/wrap_comments/false.rs b/rustfmt-core/tests/target/configs/wrap_comments/false.rs new file mode 100644 index 00000000000..48ecd88accb --- /dev/null +++ b/rustfmt-core/tests/target/configs/wrap_comments/false.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +} diff --git a/rustfmt-core/tests/target/configs/wrap_comments/true.rs b/rustfmt-core/tests/target/configs/wrap_comments/true.rs new file mode 100644 index 00000000000..4096fd4d89d --- /dev/null +++ b/rustfmt-core/tests/target/configs/wrap_comments/true.rs @@ -0,0 +1,20 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur + // adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna + // aliqua. Ut enim ad minim veniam, quis + // nostrud exercitation ullamco laboris nisi + // ut aliquip ex ea commodo consequat. +} + +fn code_block() { + // ```rust + // let x = 3; + // + // println!("x = {}", x); + // ``` +} diff --git a/rustfmt-core/tests/target/control-brace-style-always-next-line.rs b/rustfmt-core/tests/target/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..054a3075ca0 --- /dev/null +++ b/rustfmt-core/tests/target/control-brace-style-always-next-line.rs @@ -0,0 +1,50 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop + { + (); + (); + } + + 'label: loop + // loop comment + { + (); + } + + cond = true; + while cond + { + (); + } + + 'while_label: while cond + { + // while comment + (); + } + + for obj in iter + { + for sub_obj in obj + { + 'nested_while_label: while cond + { + (); + } + } + } + + match some_var + { + // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => + { + do_stuff(); + val2 + } + }; +} diff --git a/rustfmt-core/tests/target/control-brace-style-always-same-line.rs b/rustfmt-core/tests/target/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..ae6bf4a5682 --- /dev/null +++ b/rustfmt-core/tests/target/control-brace-style-always-same-line.rs @@ -0,0 +1,42 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + 'label: loop + // loop comment + { + (); + } + + cond = true; + while cond { + (); + } + + 'while_label: while cond { + // while comment + (); + } + + for obj in iter { + for sub_obj in obj { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { + // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + } + }; +} diff --git a/rustfmt-core/tests/target/doc.rs b/rustfmt-core/tests/target/doc.rs new file mode 100644 index 00000000000..99d2ae7873f --- /dev/null +++ b/rustfmt-core/tests/target/doc.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true + +// sadfsdfa +// sdffsdfasdf diff --git a/rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs b/rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs new file mode 100644 index 00000000000..31e12cfa0d0 --- /dev/null +++ b/rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs @@ -0,0 +1,53 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + if false + { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { unreachable!() } else { 0x0 }; + + if true + { + (); + } + else if false + { + (); + (); + } + else + { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } + else if false + // else-if-chain else-if comment + { + (); + (); + } + else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs b/rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs new file mode 100644 index 00000000000..5e5ab21a0d8 --- /dev/null +++ b/rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs @@ -0,0 +1,45 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + if false { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { unreachable!() } else { 0x0 }; + + if true { + (); + } else if false { + (); + (); + } else { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } else if false + // else-if-chain else-if comment + { + (); + (); + } else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs b/rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs new file mode 100644 index 00000000000..c99807dc06d --- /dev/null +++ b/rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs @@ -0,0 +1,49 @@ +// rustfmt-control_brace_style: ClosingNextLine + +fn main() { + if false { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { unreachable!() } else { 0x0 }; + + if true { + (); + } + else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } + else if false + // else-if-chain else-if comment + { + (); + (); + } + else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs new file mode 100644 index 00000000000..0b9a15e8a92 --- /dev/null +++ b/rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs @@ -0,0 +1,12 @@ +enum TestEnum { + Arm1(), + Arm2, +} + +fn foo() { + let test = TestEnum::Arm1; + match test { + TestEnum::Arm1() => {} + TestEnum::Arm2 => {} + } +} diff --git a/rustfmt-core/tests/target/empty_file.rs b/rustfmt-core/tests/target/empty_file.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/rustfmt-core/tests/target/empty_file.rs @@ -0,0 +1 @@ + diff --git a/rustfmt-core/tests/target/enum.rs b/rustfmt-core/tests/target/enum.rs new file mode 100644 index 00000000000..de88f610b6a --- /dev/null +++ b/rustfmt-core/tests/target/enum.rs @@ -0,0 +1,255 @@ +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Enums test + +#[atrr] +pub enum Test { + A, + B(u32, A /* comment */, SomeType), + /// Doc comment + C, +} + +pub enum Foo<'a, Y: Baz> +where + X: Whatever, +{ + A, +} + +enum EmtpyWithComment { + // Some comment +} + +// C-style enum +enum Bar { + A = 1, + #[someAttr(test)] + B = 2, // comment + C, +} + +enum LongVariants { + First( + LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment + VARIANT, + ), + // This is the second variant + Second, +} + +enum StructLikeVariants { + Normal(u32, String), + StructLike { + x: i32, // Test comment + // Pre-comment + #[Attr50] + y: SomeType, // Aanother Comment + }, + SL { + a: A, + }, +} + +enum X { + CreateWebGLPaintTask( + Size2D, + GLContextAttributes, + IpcSender, usize), String>>, + ), // This is a post comment +} + +pub enum EnumWithAttributes { + //This is a pre comment + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + // Pre Comment + #[rustfmt_skip] + SkippedItem(String,String,), // Post-comment + #[another_attr] + #[attr2] + ItemStruct { + x: usize, + y: usize, + }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + // And another + ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ +} + +pub enum SingleTuple { + // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + Match(usize, usize, String), /* Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ +} + +pub enum SingleStruct { + Match { name: String, loc: usize }, // Post-comment +} + +pub enum GenericEnum +where + I: Iterator, +{ + // Pre Comment + Left { list: I, root: T }, // Post-comment + Right { list: I, root: T }, // Post Comment +} + +enum EmtpyWithComment { + // Some comment +} + +enum TestFormatFails { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +fn nested_enum_test() { + if true { + enum TestEnum { + One( + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + ), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAA */ + Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAA */ + } + enum TestNestedFormatFail { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + } + } +} + +pub struct EmtpyWithComment { + // FIXME: Implement this struct +} + +// #1115 +pub enum Bencoding<'i> { + Str(&'i [u8]), + Int(i64), + List(Vec>), + /// A bencoded dict value. The first element the slice of bytes in the source that the dict is + /// composed of. The second is the dict, decoded into an ordered map. + // TODO make Dict "structlike" AKA name the two values. + Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), +} + +// #1261 +pub enum CoreResourceMsg { + SetCookieForUrl( + ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource, + ), +} + +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{ + Foo, +} + +// #1046 +pub enum Entry<'a, K: 'a, V: 'a> { + Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), + Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), +} + +// #2081 +pub enum ForegroundColor { + CYAN = + (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, +} + +// #2098 +pub enum E<'a> { + V( as Iterator>::Item), +} + +// #1809 +enum State { + TryRecv { + pos: usize, + lap: u8, + closed_count: usize, + }, + Subscribe { + pos: usize, + }, + IsReady { + pos: usize, + ready: bool, + }, + Unsubscribe { + pos: usize, + lap: u8, + id_woken: usize, + }, + FinalTryRecv { + pos: usize, + id_woken: usize, + }, + TimedOut, + Disconnected, +} + +// #2190 +#[derive(Debug, Fail)] +enum AnError { + #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] + UnexpectedSingleToken { token: syn::Token }, +} + +// #2193 +enum WidthOf101 { + #[fail(display = ".....................................................")] + Io(::std::io::Error), + #[fail(display = ".....................................................")] + Ioo(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ::std::io::Error, + ), +} + +// #2389 +pub enum QlError { + #[fail(display = "Parsing error: {}", 0)] + LexError(parser::lexer::LexError), + #[fail(display = "Parsing error: {:?}", 0)] + ParseError(parser::ParseError), + #[fail(display = "Validation error: {:?}", 0)] + ValidationError(Vec), + #[fail(display = "Execution error: {}", 0)] + ExecutionError(String), + // (from, to) + #[fail(display = "Translation error: from {} to {}", 0, 1)] + TranslationError(String, String), + // (kind, input, expected) + #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] + ResolveError(&'static str, String, Option), +} diff --git a/rustfmt-core/tests/target/expr-block.rs b/rustfmt-core/tests/target/expr-block.rs new file mode 100644 index 00000000000..277990c5a60 --- /dev/null +++ b/rustfmt-core/tests/target/expr-block.rs @@ -0,0 +1,299 @@ +// rustfmt-indent_style: Block +// Test expressions with block formatting. + +fn arrays() { + []; + let empty = []; + + let foo = [a_long_name, a_very_lng_name, a_long_name]; + + let foo = [ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + ]; + + vec![ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_very_lng_name, + ]; + + [ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_very_lng_name, + ] +} + +fn arrays() { + let x = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, + ]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ + strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + /* comment */ 1, + ]; + + let a = WeightedChoice::new(&mut [ + Weighted { weight: x, item: 0 }, + Weighted { weight: 1, item: 1 }, + Weighted { weight: x, item: 2 }, + Weighted { weight: 1, item: 3 }, + ]); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzz, + q, + ]; + + [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] +} + +fn function_calls() { + let items = itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo(), + span.hi(), + ); + + itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo(), + span.hi(), + ) +} + +fn macros() { + baz!( + do_not, + add, + trailing, + commas, + inside, + of, + function, + like, + macros, + even, + if_they, + are, + long + ); + + baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); + + let _ = match option { + None => baz!( + function, + like, + macro_as, + expression, + which, + is, + loooooooooooooooong + ), + Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), + }; +} + +fn issue_1450() { + if selfstate + .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( + STATE_PARKED, + STATE_UNPARKED, + Release, + Relaxed, + Release, + Relaxed, + ) + .is_ok() + { + return; + } +} + +fn foo() { + if real_total <= limit && !pre_line_comments + && !items.into_iter().any(|item| item.as_ref().is_multiline()) + { + DefinitiveListTactic::Horizontal + } +} + +fn combine_block() { + foo(Bar { + x: value, + y: value2, + }); + + foo((Bar { + x: value, + y: value2, + },)); + + foo(( + 1, + 2, + 3, + Bar { + x: value, + y: value2, + }, + )); + + foo((1, 2, 3, |x| { + let y = x + 1; + let z = y + 1; + z + })); + + let opt = Some(Struct( + long_argument_one, + long_argument_two, + long_argggggggg, + )); + + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); + + Ok(some_function( + lllllllllong_argument_one, + lllllllllong_argument_two, + lllllllllllllllllllllllllllllong_argument_three, + )); + + foo( + thing, + bar( + param2, + pparam1param1param1param1param1param1param1param1param1param1aram1, + param3, + ), + ); + + foo.map_or(|| { + Ok(SomeStruct { + f1: 0, + f2: 0, + f3: 0, + }) + }); + + match opt { + Some(x) => somefunc(anotherfunc( + long_argument_one, + long_argument_two, + long_argument_three, + )), + Some(x) => |x| { + let y = x + 1; + let z = y + 1; + z + }, + Some(x) => (1, 2, |x| { + let y = x + 1; + let z = y + 1; + z + }), + Some(x) => SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }, + None => Ok(SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }), + }; + + match x { + y => func(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), + _ => func( + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzz, + ), + } +} + +fn issue_1862() { + foo( + /* bar = */ None, + something_something, + /* baz = */ None, + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ + None, + /* com */ + this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, + ) +} + +fn issue_1878() { + let channel: &str = seq.next_element()? + .ok_or_else(|| de::Error::invalid_length(2, &self))?; +} diff --git a/rustfmt-core/tests/target/expr.rs b/rustfmt-core/tests/target/expr.rs new file mode 100644 index 00000000000..3c5d85b7d76 --- /dev/null +++ b/rustfmt-core/tests/target/expr.rs @@ -0,0 +1,397 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// Test expressions + +fn foo() -> bool { + let boxed: Box = box 5; + let referenced = &5; + + let very_long_variable_name = (a + first + simple + test); + let very_long_variable_name = + (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + + let is_internalxxxx = + self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb + / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; + + some_ridiculously_loooooooooooooooooooooong_function( + 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), + trivial_value, + ); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaa))))))))); + + { + for _ in 0..10 {} + } + + { + { + { + {} + } + } + } + + if 1 + 2 > 0 { + let result = 5; + result + } else { + 4 + }; + + if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + // Nothing + } + + if let Some(x) = + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) + {} + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1111 + 2222 + {} + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} + + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = + item.node + { + // nothing + } + + let test = if true { 5 } else { 3 }; + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + // Check subformatting + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } +} + +fn bar() { + let range = + (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + 2333333333333333); + + let another_range = 5..some_func(a, b /* comment */); + + for _ in 1.. { + call_forever(); + } + + syntactically_correct( + loop { + sup('?'); + }, + if cond { 0 } else { 1 }, + ); + + let third = ..10; + let infi_range = ..; + let foo = 1..; + let bar = 5; + let nonsense = (10..0)..(0..10); + + loop { + if true { + break; + } + } + + let x = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + a, + ); +} + +fn baz() { + unsafe /* {}{}{}{{{{}} */ { + let foo = 1u32; + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + * comment */ { + } + + unsafe /* So this is a very long comment. + * Multi-line, too. + * Will it still format correctly? */ { + } + + unsafe { + // Regular unsafe block + } + + unsafe { foo() } + + unsafe { + foo(); + } + + // #2289 + let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; + let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; + let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; + let identifier_3 = + unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; +} + +// Test some empty blocks. +fn qux() { + {} + // FIXME this one could be done better. + { /* a block with a comment */ } + {} + { + // A block with a comment. + } +} + +fn issue227() { + { + let handler = + box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); + } +} + +fn issue184(source: &str) { + for c in source.chars() { + if index < 'a' { + continue; + } + } +} + +fn arrays() { + let x = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, + ]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ + strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + // comment + 1, + ]; + + let a = WeightedChoice::new(&mut [ + Weighted { + weightweight: x, + item: 0, + }, + Weighted { + weightweight: 1, + item: 1, + }, + Weighted { + weightweight: x, + item: 2, + }, + Weighted { + weightweight: 1, + item: 3, + }, + ]); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q, + ]; + + [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] +} + +fn returns() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + && return; + + return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +} + +fn addrof() { + &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); +} + +fn casts() { + fn unpack(packed: u32) -> [u16; 2] { + [(packed >> 16) as u16, (packed >> 0) as u16] + } + + let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; + let slightly_longer_trait = + yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; +} + +fn indices() { + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) + [x + y + z]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) + [xxxxx + yyyyy + zzzzz]; + let z = xxxxxxxxxx + .x() + .y() + .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; + let z = xxxxxxxxxx + .x() + .y() + .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz() + [aaaaa]; +} + +fn repeats() { + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; + x + y + z]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; + xxxxx + yyyyy + zzzzz]; +} + +fn blocks() { + if 1 + 1 == 2 { + println!("yay arithmetix!"); + }; +} + +fn issue767() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} + +fn ranges() { + let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let z = ..=x; + + // #1766 + let x = [0. ..10.0]; + let x = [0. ..=10.0]; + + a..=b + + // the expr below won't compile because inclusive ranges need a defined end + // let a = 0 ..= ; +} + +fn if_else() { + let exact = diff / (if size == 0 { 1 } else { size }); + + let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; +} + +fn complex_if_else() { + if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { + yo(); + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx + { + yo(); + } +} + +fn issue1106() { + { + if let hir::ItemEnum(ref enum_def, ref generics) = + self.ast_map.expect_item(enum_node_id).node + {} + } + + for entry in WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) + {} +} + +fn issue1570() { + a_very_long_function_name({ some_func(1, { 1 }) }) +} + +fn issue1714() { + v = &mut { v }[mid..]; + let (left, right) = { v }.split_at_mut(mid); +} + +// Multi-lined index should be put on the next line if it fits in one line. +fn issue1749() { + { + { + { + if self.shape[(r as f32 + self.x_offset) as usize] + [(c as f32 + self.y_offset) as usize] != 0 + { + // hello + } + } + } + } +} + +// #1172 +fn newlines_between_list_like_expr() { + foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ); + + vec![ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ]; + + match x { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + | zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), + _ => bar(), + }; +} + +fn issue2178() { + Ok(result + .iter() + .map(|item| ls_util::rls_to_location(item)) + .collect()) +} diff --git a/rustfmt-core/tests/target/extern.rs b/rustfmt-core/tests/target/extern.rs new file mode 100644 index 00000000000..b0aa51127d5 --- /dev/null +++ b/rustfmt-core/tests/target/extern.rs @@ -0,0 +1,73 @@ +// rustfmt-normalize_comments: true + +extern crate foo; +extern crate foo as bar; + +extern crate chrono; +extern crate dotenv; +extern crate futures; + +extern crate bar; +extern crate foo; + +// #2315 +extern crate proc_macro; +extern crate proc_macro2; + +extern "C" { + fn c_func(x: *mut *mut libc::c_void); + + fn c_func( + x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, + y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY, + ); + + #[test123] + fn foo() -> uint64_t; + + pub fn bar(); +} + +extern "C" { + fn DMR_GetDevice( + pHDev: *mut HDEV, + searchMode: DeviceSearchMode, + pSearchString: *const c_char, + devNr: c_uint, + wildcard: c_char, + ) -> TDMR_ERROR; + + fn quux() -> (); // Post comment + + pub type Foo; + + type Bar; +} + +extern "Rust" { + static ext: u32; + // Some comment. + pub static mut var: SomeType; +} + +extern "C" { + fn syscall( + number: libc::c_long, // comment 1 + // comm 2 + ... // sup? + ) -> libc::c_long; + + fn foo(x: *const c_char, ...) -> libc::c_long; +} + +extern "C" { + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE, + ) -> *mut FILE; +} + +extern "C" {} diff --git a/rustfmt-core/tests/target/extern_not_explicit.rs b/rustfmt-core/tests/target/extern_not_explicit.rs new file mode 100644 index 00000000000..b55b64d05b3 --- /dev/null +++ b/rustfmt-core/tests/target/extern_not_explicit.rs @@ -0,0 +1,18 @@ +// rustfmt-force_explicit_abi: false + +extern { + fn some_fn() -> (); +} + +extern fn sup() {} + +type funky_func = extern fn( + unsafe extern "rust-call" fn( + *const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal, + ) -> u8, +); diff --git a/rustfmt-core/tests/target/file-lines-1.rs b/rustfmt-core/tests/target/file-lines-1.rs new file mode 100644 index 00000000000..2601ca9fc94 --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-1.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + }.method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/target/file-lines-2.rs b/rustfmt-core/tests/target/file-lines-2.rs new file mode 100644 index 00000000000..bc25698c2ed --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-2.rs @@ -0,0 +1,24 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/target/file-lines-3.rs b/rustfmt-core/tests/target/file-lines-3.rs new file mode 100644 index 00000000000..fe465750ae1 --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-3.rs @@ -0,0 +1,25 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] +// rustfmt-error_on_line_overflow: false + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + }.method_call() + .method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/target/file-lines-4.rs b/rustfmt-core/tests/target/file-lines-4.rs new file mode 100644 index 00000000000..83928bf6fec --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-4.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [] +// (Test that nothing is formatted if an empty array is specified.) + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + // aaaaaaaaaaaaa + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/rustfmt-core/tests/target/file-lines-5.rs b/rustfmt-core/tests/target/file-lines-5.rs new file mode 100644 index 00000000000..3966dc06303 --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-5.rs @@ -0,0 +1,17 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + fn baz() { + let j = 15; + } +} diff --git a/rustfmt-core/tests/target/file-lines-6.rs b/rustfmt-core/tests/target/file-lines-6.rs new file mode 100644 index 00000000000..8a092df869a --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-6.rs @@ -0,0 +1,18 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + + fn baz() { +/// + let j = 15; + } +} diff --git a/rustfmt-core/tests/target/file-lines-item.rs b/rustfmt-core/tests/target/file-lines-item.rs new file mode 100644 index 00000000000..e155e75f34c --- /dev/null +++ b/rustfmt-core/tests/target/file-lines-item.rs @@ -0,0 +1,22 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] +// rustfmt-reorder_imports: true + +use foo::{c, b, a}; +use bar; + +fn foo() { + bar(); +} + +impl Drop for Context { + fn drop(&mut self) { + } +} + +impl Bar for Baz { + fn foo() { + bar( + baz, // Who knows? + ) + } +} diff --git a/rustfmt-core/tests/target/fn-args-with-last-line-comment.rs b/rustfmt-core/tests/target/fn-args-with-last-line-comment.rs new file mode 100644 index 00000000000..27e0e09653e --- /dev/null +++ b/rustfmt-core/tests/target/fn-args-with-last-line-comment.rs @@ -0,0 +1,24 @@ +// #1587 +pub trait X { + fn a(&self) -> &'static str; + fn bcd( + &self, + c: &str, // comment on this arg + d: u16, // comment on this arg + e: &Vec, // comment on this arg + ) -> Box; +} + +// #1595 +fn foo( + arg1: LongTypeName, + arg2: LongTypeName, + arg3: LongTypeName, + arg4: LongTypeName, + arg5: LongTypeName, + arg6: LongTypeName, + arg7: LongTypeName, + //arg8: LongTypeName, +) { + // do stuff +} diff --git a/rustfmt-core/tests/target/fn-custom-2.rs b/rustfmt-core/tests/target/fn-custom-2.rs new file mode 100644 index 00000000000..c2b3580c668 --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom-2.rs @@ -0,0 +1,78 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + foo(); +} + +fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, +>( + a: Aaaaaaaaaaaaaaa, +) { + bar(); +} + +fn baz() +where + X: TTTTTTTT, +{ + baz(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +impl Foo { + fn foo( + self, + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, + ) { + foo(); + } + + fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, + >( + a: Aaaaaaaaaaaaaaa, + ) { + bar(); + } + + fn baz() + where + X: TTTTTTTT, + { + baz(); + } +} + +struct Foo< + TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUU, + VVVVVVVVVVVVVVVVVVVVVVVVVVV, + WWWWWWWWWWWWWWWWWWWWWWWW, +> { + foo: Foo, +} diff --git a/rustfmt-core/tests/target/fn-custom-3.rs b/rustfmt-core/tests/target/fn-custom-3.rs new file mode 100644 index 00000000000..baa1e39231b --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom-3.rs @@ -0,0 +1,72 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + foo(); +} + +fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, +>( + a: Aaaaaaaaaaaaaaa, +) { + bar(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +impl Foo { + fn foo( + self, + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, + ) { + foo(); + } + + fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, + >( + a: Aaaaaaaaaaaaaaa, + ) { + bar(); + } +} + +struct Foo< + TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUU, + VVVVVVVVVVVVVVVVVVVVVVVVVVV, + WWWWWWWWWWWWWWWWWWWWWWWW, +> { + foo: Foo, +} diff --git a/rustfmt-core/tests/target/fn-custom-4.rs b/rustfmt-core/tests/target/fn-custom-4.rs new file mode 100644 index 00000000000..0a223ef5fac --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom-4.rs @@ -0,0 +1,27 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +fn qux(a: Aaaaaaaaaaaaaaaaa) +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} diff --git a/rustfmt-core/tests/target/fn-custom-6.rs b/rustfmt-core/tests/target/fn-custom-6.rs new file mode 100644 index 00000000000..720d4288c41 --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom-6.rs @@ -0,0 +1,72 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) where + T: UUUUUUUUUUU, { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String +where + T: UUUUUUUUUUU, { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/rustfmt-core/tests/target/fn-custom-7.rs b/rustfmt-core/tests/target/fn-custom-7.rs new file mode 100644 index 00000000000..ec113c30d53 --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom-7.rs @@ -0,0 +1,41 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block +// rustfmt-fn_args_density: Vertical +// rustfmt-brace_style: AlwaysNextLine + +// Case with only one variable. +fn foo(a: u8) -> u8 +{ + bar() +} + +// Case with 2 variables and some pre-comments. +fn foo( + a: u8, // Comment 1 + b: u8, // Comment 2 +) -> u8 +{ + bar() +} + +// Case with 2 variables and some post-comments. +fn foo( + // Comment 1 + a: u8, + // Comment 2 + b: u8, +) -> u8 +{ + bar() +} + +trait Test +{ + fn foo(a: u8) + { + } + + fn bar(a: u8) -> String + { + } +} diff --git a/rustfmt-core/tests/target/fn-custom-8.rs b/rustfmt-core/tests/target/fn-custom-8.rs new file mode 100644 index 00000000000..290557b979d --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom-8.rs @@ -0,0 +1,78 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) where + T: UUUUUUUUUUU, { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String +where + T: UUUUUUUUUUU, { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} + + fn bar(a: u8) -> String + where + Foo: foooo, + Bar: barrr, { + } +} diff --git a/rustfmt-core/tests/target/fn-custom.rs b/rustfmt-core/tests/target/fn-custom.rs new file mode 100644 index 00000000000..bf87553dedc --- /dev/null +++ b/rustfmt-core/tests/target/fn-custom.rs @@ -0,0 +1,19 @@ +// rustfmt-fn_args_density: Compressed +// Test some of the ways function signatures can be customised. + +// Test compressed layout of args. +fn foo( + a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + foo(); +} + +impl Foo { + fn foo( + self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee, + ) { + foo(); + } +} diff --git a/rustfmt-core/tests/target/fn-simple.rs b/rustfmt-core/tests/target/fn-simple.rs new file mode 100644 index 00000000000..4e6e6493835 --- /dev/null +++ b/rustfmt-core/tests/target/fn-simple.rs @@ -0,0 +1,107 @@ +// rustfmt-normalize_comments: true + +fn simple( + // pre-comment on a function!? + i: i32, // yes, it's possible! + response: NoWay, // hose +) { + fn op( + x: Typ, + key: &[u8], + upd: Box< + Fn(Option<&memcache::Item>) + -> (memcache::Status, Result>), + >, + ) -> MapResult { + } + + "cool" +} + +fn weird_comment( + // /*/ double level */ comment + x: Hello, // /*/* triple, even */*/ + // Does this work? + y: World, +) { + simple(/* does this preserve comments now? */ 42, NoWay) +} + +fn generic(arg: T) -> &SomeType +where + T: Fn( + // First arg + A, + // Second argument + B, + C, + D, + // pre comment + E, // last comment + ) -> &SomeType, +{ + arg(a, b, c, d, e) +} + +fn foo() -> ! {} + +pub fn http_fetch_async( + listener: Box, + script_chan: Box, +) { +} + +fn some_func>(val: T) {} + +fn zzzzzzzzzzzzzzzzzzzz( + selff: Type, + mut handle: node::Handle>, Type, NodeType>, +) -> SearchStack<'a, K, V, Type, NodeType> { +} + +unsafe fn generic_call( + cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern "C" fn( + *const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal, + ) -> u8, +) { + let f: fn(_, _) -> _ = panic!(); +} + +pub fn start_export_thread( + database: &Database, + crypto_scheme: &C, + block_size: usize, + source_path: &Path, +) -> BonzoResult> { +} + +pub fn waltz(cwd: &Path) -> CliAssert { + { + { + formatted_comment = + rewrite_comment(comment, block_style, width, offset, formatting_fig); + } + } +} + +// #2003 +mod foo { + fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() + { + foo(); + } +} + +// #2082 +pub(crate) fn init() {} + +crate fn init() {} diff --git a/rustfmt-core/tests/target/fn-single-line.rs b/rustfmt-core/tests/target/fn-single-line.rs new file mode 100644 index 00000000000..3617506d89a --- /dev/null +++ b/rustfmt-core/tests/target/fn-single-line.rs @@ -0,0 +1,70 @@ +// rustfmt-fn_single_line: true +// Test single-line functions. + +fn foo_expr() { 1 } + +fn foo_stmt() { foo(); } + +fn foo_decl_local() { let z = 5; } + +fn foo_decl_item(x: &mut i32) { x = 3; } + +fn empty() {} + +fn foo_return() -> String { "yay" } + +fn foo_where() -> T +where + T: Sync, +{ + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space() { 1 } + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) {} +} + +trait CoolerTypes { + fn dummy(&self) {} +} + +fn Foo() +where + T: Bar, +{ +} diff --git a/rustfmt-core/tests/target/fn-ty.rs b/rustfmt-core/tests/target/fn-ty.rs new file mode 100644 index 00000000000..7d48f3b32db --- /dev/null +++ b/rustfmt-core/tests/target/fn-ty.rs @@ -0,0 +1,14 @@ +fn f( + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, + xxxxxxxxxxxxxxxxxx: fn() -> a, + xxxxxxxxxxxxxxxxxx: fn(a, b, b), + xxxxxxxxxxxxxxxxxx: fn(), + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, + xxxxxxxxxxxxxxxxxx: fn() -> !, +) where + F1: Fn(a, b, b) -> a, + F2: Fn(a, b, b), + F3: Fn(), + F4: Fn() -> u32, +{ +} diff --git a/rustfmt-core/tests/target/fn.rs b/rustfmt-core/tests/target/fn.rs new file mode 100644 index 00000000000..b78a8b5b21e --- /dev/null +++ b/rustfmt-core/tests/target/fn.rs @@ -0,0 +1,122 @@ +// Tests different fns + +fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} + +fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType +where + T: Blah, +{ +} + +fn foo(a: AAA /* (comment) */) +where + T: Blah, +{ +} + +fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +) -> RetType +where + T: Blah, +{ + +} + +fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +) -> RetType +where + T: Blah, + U: dsfasdfasdfasd, +{ + +} + +fn foo B /* paren inside generics */>() {} + +impl Foo { + fn with_no_errors(&mut self, f: F) -> T + where + F: FnOnce(&mut Resolver) -> T, + { + } + + fn foo(mut self, mut bar: u32) {} + + fn bar(self, mut bazz: u32) {} +} + +pub fn render< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write, +>( + g: &'a G, + w: &mut W, +) -> io::Result<()> { + render_opts(g, w, &[]) +} + +const fn foo() { + x; +} + +pub const fn foo() { + x; +} + +impl Foo { + const fn foo() { + x; + } +} + +fn homura>(_: T) {} + +fn issue377() -> (Box, Box) {} + +fn main() { + let _ = function(move || 5); + let _ = move || 42; + let _ = || unsafe { abort() }; +} + +// With inner attributes. +fn inner() { + #![inline] + x +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn foo(a: i32) -> i32 { + // comment + if a > 0 { 1 } else { 2 } +} + +fn ______________________baz( + a: i32, +) -> *mut ::std::option::Option< + extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) -> (), +> { +} + +pub fn check_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), +) { +} + +pub fn check_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), +) { +} diff --git a/rustfmt-core/tests/target/fn_args_density-vertical.rs b/rustfmt-core/tests/target/fn_args_density-vertical.rs new file mode 100644 index 00000000000..477a48cc35f --- /dev/null +++ b/rustfmt-core/tests/target/fn_args_density-vertical.rs @@ -0,0 +1,39 @@ +// rustfmt-fn_args_density: Vertical + +// Empty list should stay on one line. +fn do_bar() -> u8 { + bar() +} + +// A single argument should stay on the same line. +fn do_bar(a: u8) -> u8 { + bar() +} + +// Multiple arguments should each get their own line. +fn do_bar( + a: u8, + mut b: u8, + c: &u8, + d: &mut u8, + closure: &Fn(i32) -> i32, +) -> i32 { + // This feature should not affect closures. + let bar = |x: i32, y: i32| -> i32 { x + y }; + bar(a, b) +} + +// If the first argument doesn't fit on the same line with the function name, +// the whole list should probably be pushed to the next line with hanging +// indent. That's not what happens though, so check current behaviour instead. +// In any case, it should maintain single argument per line. +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, + c: u8, + d: u8, +) { + this(); + that(); + the_other_thing(); +} diff --git a/rustfmt-core/tests/target/fn_args_indent-block.rs b/rustfmt-core/tests/target/fn_args_indent-block.rs new file mode 100644 index 00000000000..04c18816d0b --- /dev/null +++ b/rustfmt-core/tests/target/fn_args_indent-block.rs @@ -0,0 +1,144 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String { + bar(); +} + +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo( + a: u8, // Comment 1 + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, // Comment 2 +) -> u8 { + bar() +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String +where + X: Fooooo, + Y: Baaar, +{ + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T +where + X: Foooo, + Y: Baaar, +{ + foo(); +} + +fn foo() +where + X: Foooo, +{ +} + +fn foo() +where + X: Foooo, + Y: Baaar, +{ +} + +fn foo() -> ( + Loooooooooooooooooooooong, + Reeeeeeeeeeeeeeeeeeeeeeeeturn, + iiiiiiiiis, + Looooooooooooooooong, +) { + foo(); +} + +fn foo() { + foo(); +} + +fn foo< + L: Loooooooooooooooooooooong, + G: Geeeeeeeeeeeneric, + I: iiiiiiiiis, + L: Looooooooooooooooong, +>() { + foo(); +} + +fn foo() { + foo(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, + ) -> String { + } +} + +fn foo( + a: Aaaaaaaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, +) { + foo(); +} + +fn foo() -> ( + Looooooooooooooooooooooooooong, + Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, + iiiiiiiiiiiiiis, + Loooooooooooooooooooooong, +) { + foo(); +} diff --git a/rustfmt-core/tests/target/fn_once.rs b/rustfmt-core/tests/target/fn_once.rs new file mode 100644 index 00000000000..42b8f98e78a --- /dev/null +++ b/rustfmt-core/tests/target/fn_once.rs @@ -0,0 +1,8 @@ +struct Add(usize); + +impl FnOnce<(usize,)> for Add { + type Output = Add; + extern "rust-call" fn call_once(self, to: (usize,)) -> Add { + Add(self.0 + to.0) + } +} diff --git a/rustfmt-core/tests/target/hard-tabs.rs b/rustfmt-core/tests/target/hard-tabs.rs new file mode 100644 index 00000000000..90be4d6b367 --- /dev/null +++ b/rustfmt-core/tests/target/hard-tabs.rs @@ -0,0 +1,99 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-hard_tabs: true +// rustfmt-error_on_line_overflow: false + +fn main() { + let x = Bar; + + let y = Foo { a: x }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) { + } + + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + * comment */ { + } + + unsafe /* So this is a very long comment. + * Multi-line, too. + * Will it still format correctly? */ { + } + + let chain = funktion_kall() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab(); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q, + ]; + + fn generic(arg: T) -> &SomeType + where + T: Fn( + // First arg + A, + // Second argument + B, + C, + D, + // pre comment + E, // last comment + ) -> &SomeType, + { + arg(a, b, c, d, e) + } + + loong_func().quux(move || if true { 1 } else { 2 }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + a.b.c.d(); + + x().y(|| match cond() { + true => (), + false => (), + }); +} + +// #2296 +impl Foo { + // a comment + // on multiple lines + fn foo() { + // another comment + // on multiple lines + let x = true; + } +} diff --git a/rustfmt-core/tests/target/hello.rs b/rustfmt-core/tests/target/hello.rs new file mode 100644 index 00000000000..d9f90b0b5e8 --- /dev/null +++ b/rustfmt-core/tests/target/hello.rs @@ -0,0 +1,8 @@ +// rustfmt-config: small_tabs.toml +// rustfmt-target: hello.rs + +// Smoke test - hello world. + +fn main() { + println!("Hello world!"); +} diff --git a/rustfmt-core/tests/target/immovable_generators.rs b/rustfmt-core/tests/target/immovable_generators.rs new file mode 100644 index 00000000000..0bf7a2d91ba --- /dev/null +++ b/rustfmt-core/tests/target/immovable_generators.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +unsafe fn foo() { + let mut ga = static || { + yield 1; + }; +} diff --git a/rustfmt-core/tests/target/impl.rs b/rustfmt-core/tests/target/impl.rs new file mode 100644 index 00000000000..5895c74bcc9 --- /dev/null +++ b/rustfmt-core/tests/target/impl.rs @@ -0,0 +1,43 @@ +// Test impls + +impl JSTraceable for SmallVec<[T; 1]> {} + +impl>> Handle { + // Keep this. +} + +impl Test +where + V: Clone, // This comment is NOT removed by formating! +{ + pub fn new(value: V) -> Self { + Test { + cloned_value: value.clone(), + value, + } + } +} + +impl X /* comment */ {} +impl Y // comment +{ +} + +impl Foo for T +// comment1 +where + // comment2 + // blah + T: Clone, +{ +} + +// #1823 +default impl Trait for X {} +default unsafe impl Trait for Y {} +pub default unsafe impl Trait for Z {} + +// #2212 +impl ConstWithDefault { + default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; +} diff --git a/rustfmt-core/tests/target/impls.rs b/rustfmt-core/tests/target/impls.rs new file mode 100644 index 00000000000..91172b39fe5 --- /dev/null +++ b/rustfmt-core/tests/target/impls.rs @@ -0,0 +1,219 @@ +// rustfmt-normalize_comments: true +impl Foo for Bar { + fn foo() { + "hi" + } +} + +pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; + // Comment 1 + fn foo() { + "hi" + } + // Comment 2 + fn foo() { + "hi" + } + // Comment 3 +} + +pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> +where + X: Foo<'a, Z>, +{ + fn foo() { + "hi" + } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> +where + X: Fooooooooooooooooooooooooooooo<'a, Z>, +{ + fn foo() { + "hi" + } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> +where + X: Foooooooooooooooooooooooooooo<'a, Z>, +{ + fn foo() { + "hi" + } +} + +impl Foo for Bar +where + T: Baz, +{ +} + +impl Foo for Bar +where + T: Baz, +{ + // Comment +} + +impl Foo { + fn foo() {} +} + +impl Boo { + // BOO + fn boo() {} + // FOO +} + +mod a { + impl Foo { + // Hello! + fn foo() {} + } +} + +mod b { + mod a { + impl Foo { + fn foo() {} + } + } +} + +impl Foo { + add_fun!(); +} + +impl Blah { + fn boop() {} + add_fun!(); +} + +impl X { + fn do_parse(mut self: X) {} +} + +impl Y5000 { + fn bar(self: X<'a, 'b>, y: Y) {} + + fn bad(&self, (x, y): CoorT) {} + + fn turbo_bad(self: X<'a, 'b>, (x, y): CoorT) {} +} + +pub impl Foo for Bar +where + T: Foo, +{ + fn foo() { + "hi" + } +} + +pub impl Foo for Bar +where + T: Foo, + Z: Baz, +{ +} + +mod m { + impl PartialEq for S + where + T: PartialEq, + { + fn eq(&self, other: &Self) { + true + } + } + + impl PartialEq for S + where + T: PartialEq, + { + } +} + +impl + Handle, HandleType> +{ +} + +impl PartialEq + for Handle, HandleType> +{ +} + +mod x { + impl Foo + where + A: 'static, + B: 'static, + C: 'static, + D: 'static, + { + } +} + +impl + Issue1249 +{ + // Creates a new flow constructor. + fn foo() {} +} + +// #1600 +impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { + fn drop() {} +} + +// #1168 +pub trait Number + : Copy + + Eq + + Not + + Shl + + Shr + + BitAnd + + BitOr + + BitAndAssign + + BitOrAssign { + // test + fn zero() -> Self; +} + +// #1642 +pub trait SomeTrait + : Clone + + Eq + + PartialEq + + Ord + + PartialOrd + + Default + + Hash + + Debug + + Display + + Write + + Read + + FromStr { + // comment +} + +// #1995 +impl Foo { + fn f( + S { + aaaaaaaaaa: aaaaaaaaaa, + bbbbbbbbbb: bbbbbbbbbb, + cccccccccc: cccccccccc, + }: S, + ) -> u32 { + 1 + } +} diff --git a/rustfmt-core/tests/target/import-fencepost-length.rs b/rustfmt-core/tests/target/import-fencepost-length.rs new file mode 100644 index 00000000000..e4f885c09b1 --- /dev/null +++ b/rustfmt-core/tests/target/import-fencepost-length.rs @@ -0,0 +1,4 @@ +use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; +use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; +use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, + ddddddddd}; diff --git a/rustfmt-core/tests/target/imports-reorder-lines-and-items.rs b/rustfmt-core/tests/target/imports-reorder-lines-and-items.rs new file mode 100644 index 00000000000..f395710b186 --- /dev/null +++ b/rustfmt-core/tests/target/imports-reorder-lines-and-items.rs @@ -0,0 +1,10 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true + +use std::cmp::{a, b, c, d}; +use std::ddd::{a, b, c as g, d as p}; +use std::ddd::aaa; +// This comment should stay with `use std::ddd:bbb;` +use std::ddd::bbb; +/// This comment should stay with `use std::str;` +use std::str; diff --git a/rustfmt-core/tests/target/imports-reorder-lines.rs b/rustfmt-core/tests/target/imports-reorder-lines.rs new file mode 100644 index 00000000000..3695d6b4913 --- /dev/null +++ b/rustfmt-core/tests/target/imports-reorder-lines.rs @@ -0,0 +1,33 @@ +// rustfmt-reorder_imports: true + +use std::cmp::{a, b, c, d}; +use std::cmp::{b, e, f, g}; +// This comment should stay with `use std::ddd;` +use std::ddd; +use std::ddd::aaa; +use std::ddd::bbb; +use std::str; + +mod test {} + +use aaa; +use aaa::*; +use aaa::bbb; + +mod test {} +// If item names are equal, order by rename + +use test::{a as aa, c}; +use test::{a as bb, b}; + +mod test {} +// If item names are equal, order by rename - no rename comes before a rename + +use test::{a, c}; +use test::{a as bb, b}; + +mod test {} +// `self` always comes first + +use test::{self as bb, b}; +use test::{a as aa, c}; diff --git a/rustfmt-core/tests/target/imports-reorder.rs b/rustfmt-core/tests/target/imports-reorder.rs new file mode 100644 index 00000000000..fbb56e3aa0c --- /dev/null +++ b/rustfmt-core/tests/target/imports-reorder.rs @@ -0,0 +1,6 @@ +// rustfmt-normalize_comments: true +// rustfmt-reorder_imported_names: true + +use path::{self /* self */, /* A */ A, B /* B */, C}; + +use {aa, ab, ac, b, Z}; diff --git a/rustfmt-core/tests/target/imports.rs b/rustfmt-core/tests/target/imports.rs new file mode 100644 index 00000000000..2b825526199 --- /dev/null +++ b/rustfmt-core/tests/target/imports.rs @@ -0,0 +1,88 @@ +// rustfmt-normalize_comments: true +// rustfmt-error_on_line_overflow: false + +// Imports. + +// Long import. +use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; +use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; + +use list::{// Another item + AnotherItem, // Another Comment + // Last Item + LastItem, + // Some item + SomeItem /* Comment */}; + +use test::{/* A */ self /* B */, Other /* C */}; + +use syntax; +use {Bar /* comment */, /* Pre-comment! */ Foo}; +use Foo::{Bar, Baz}; +pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; + +use self; +use std::io; +use std::io; + +mod Foo { + pub use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; + + mod Foo2 { + pub use syntax::ast::{self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, + ItemStatic}; + } +} + +fn test() { + use Baz::*; + use Qux; +} + +// Simple imports +use foo::bar::baz; +use bar::quux as kaas; +use foo; + +// With aliases. +use foo::{self as bar, baz}; +use foo as bar; +use foo::qux as bar; +use foo::{baz, qux as bar}; + +// With absolute paths +use foo; +use foo::Bar; +use foo::{Bar, Baz}; +use Foo; +use {Bar, Baz}; + +// Root globs +use ::*; +use ::*; + +// spaces used to cause glob imports to disappear (#1356) +use super::*; +use foo::issue_1356::*; + +// We shouldn't remove imports which have attributes attached (#1858) +#[cfg(unix)] +use self::unix::{}; + +// nested imports +use foo::{a, b, boo, c, + bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, + foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}}; + +use fooo::{bar, x, y, z, + baar::foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}, + bar::*}; + +// nested imports with a single sub-tree. +use a::b::c::*; +use a::b::c::d; +use a::b::c::{xxx, yyy, zzz}; diff --git a/rustfmt-core/tests/target/indented-impl.rs b/rustfmt-core/tests/target/indented-impl.rs new file mode 100644 index 00000000000..eff579dddac --- /dev/null +++ b/rustfmt-core/tests/target/indented-impl.rs @@ -0,0 +1,13 @@ +// rustfmt-brace_style: AlwaysNextLine +mod x +{ + struct X(i8); + + impl Y for X + { + fn y(self) -> () + { + println!("ok"); + } + } +} diff --git a/rustfmt-core/tests/target/issue-1021.rs b/rustfmt-core/tests/target/issue-1021.rs new file mode 100644 index 00000000000..ba1029d4e61 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1021.rs @@ -0,0 +1,22 @@ +// rustfmt-normalize_comments: true +fn main() { + match x { + S(true, .., true) => (), + S(true, ..) => (), + S(.., true) => (), + S(..) => (), + S(_) => (), + S(/* .. */ ..) => (), + S(/* .. */ .., true) => (), + } + + match y { + (true, .., true) => (), + (true, ..) => (), + (.., true) => (), + (..) => (), + (_,) => (), + (/* .. */ ..) => (), + (/* .. */ .., true) => (), + } +} diff --git a/rustfmt-core/tests/target/issue-1049.rs b/rustfmt-core/tests/target/issue-1049.rs new file mode 100644 index 00000000000..c788519ca9a --- /dev/null +++ b/rustfmt-core/tests/target/issue-1049.rs @@ -0,0 +1,29 @@ +// Test overlong function signature +pub unsafe fn reborrow_mut( + &mut X: Abcde, +) -> Handle, HandleType> { +} + +pub fn merge( + mut X: Abcdef, +) -> Handle, K, V, marker::Internal>, marker::Edge> { +} + +impl Handle { + pub fn merge( + a: Abcd, + ) -> Handle, K, V, marker::Internal>, marker::Edge> { + } +} + +// Long function without return type that should not be reformatted. +fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { +} + +fn veeeeeeeeeeeeeeeeeeeeeeery_long_name( + a: FirstTypeeeeeeeeee, + b: SecondTypeeeeeeeeeeeeeeeeeeeeeee, +) { +} diff --git a/rustfmt-core/tests/target/issue-1055.rs b/rustfmt-core/tests/target/issue-1055.rs new file mode 100644 index 00000000000..ee143e792b0 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1055.rs @@ -0,0 +1,3 @@ +fn issue_1055() { + let foo = (|| {})(); +} diff --git a/rustfmt-core/tests/target/issue-1111.rs b/rustfmt-core/tests/target/issue-1111.rs new file mode 100644 index 00000000000..2e1a89ad78e --- /dev/null +++ b/rustfmt-core/tests/target/issue-1111.rs @@ -0,0 +1 @@ +use bar; diff --git a/rustfmt-core/tests/target/issue-1113.rs b/rustfmt-core/tests/target/issue-1113.rs new file mode 100644 index 00000000000..1245bcd057c --- /dev/null +++ b/rustfmt-core/tests/target/issue-1113.rs @@ -0,0 +1,33 @@ +pub fn foo() -> fmt::Result +//pub fn writeStringToken +{ + panic!() +} + +pub fn foo() -> fmt::Result // pub fn writeStringToken +{ + panic!() +} + +pub fn foo() -> fmt::Result /* pub fn writeStringToken */ { + panic!() +} + +pub fn foo() -> fmt::Result +/* pub fn writeStringToken */ { + panic!() +} + +pub fn foo() -> fmt::Result +/* pub fn writeStringToken */ +{ + panic!() +} + +pub fn foo() -> fmt::Result /* + * + * + */ +{ + panic!() +} diff --git a/rustfmt-core/tests/target/issue-1120.rs b/rustfmt-core/tests/target/issue-1120.rs new file mode 100644 index 00000000000..f44597e7d1e --- /dev/null +++ b/rustfmt-core/tests/target/issue-1120.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_imports: true + +// Ensure that a use at the start of an inline module is correctly formatted. +mod foo { + use bar; +} + +// Ensure that an indented `use` gets the correct indentation. +mod foo { + use bar; +} diff --git a/rustfmt-core/tests/target/issue-1124.rs b/rustfmt-core/tests/target/issue-1124.rs new file mode 100644 index 00000000000..d34870b2a28 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1124.rs @@ -0,0 +1,20 @@ +// rustfmt-reorder_imports: true +// rustfmt-normalize_comments: true + +use a; +use b; +use c; +use d; +// The previous line has a space after the `use a;` + +mod a { + use a; + use b; + use c; + use d; +} + +use a; +use x; +use y; +use z; diff --git a/rustfmt-core/tests/target/issue-1127.rs b/rustfmt-core/tests/target/issue-1127.rs new file mode 100644 index 00000000000..dbdd234b8e4 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1127.rs @@ -0,0 +1,25 @@ +// rustfmt-max_width:120 +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true + +fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { + 42 +} + +enum TestEnum { + AVeryVeryLongEnumName, + AnotherVeryLongEnumName, + TheLastVeryLongEnumName, +} + +fn main() { + let var = TestEnum::AVeryVeryLongEnumName; + let num = match var { + TestEnum::AVeryVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::AnotherVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::TheLastVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + }; +} diff --git a/rustfmt-core/tests/target/issue-1158.rs b/rustfmt-core/tests/target/issue-1158.rs new file mode 100644 index 00000000000..2abfa5a29f2 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1158.rs @@ -0,0 +1,3 @@ +trait T { + itemmacro!(this, is.now().formatted(yay)); +} diff --git a/rustfmt-core/tests/target/issue-1177.rs b/rustfmt-core/tests/target/issue-1177.rs new file mode 100644 index 00000000000..dcda3972814 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1177.rs @@ -0,0 +1,7 @@ +// rustfmt-normalize_comments: true +fn main() { + // Line Comment + // Block Comment + + let d = 5; +} diff --git a/rustfmt-core/tests/target/issue-1192.rs b/rustfmt-core/tests/target/issue-1192.rs new file mode 100644 index 00000000000..432fe8cce7c --- /dev/null +++ b/rustfmt-core/tests/target/issue-1192.rs @@ -0,0 +1,3 @@ +fn main() { + assert!(true); +} diff --git a/rustfmt-core/tests/target/issue-1211.rs b/rustfmt-core/tests/target/issue-1211.rs new file mode 100644 index 00000000000..de4c5c87ee6 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1211.rs @@ -0,0 +1,13 @@ +fn main() { + for iface in &ifaces { + match iface.addr { + get_if_addrs::IfAddr::V4(ref addr) => match addr.broadcast { + Some(ip) => { + sock.send_to(&buf, (ip, 8765)).expect("foobar"); + } + _ => (), + }, + _ => (), + }; + } +} diff --git a/rustfmt-core/tests/target/issue-1214.rs b/rustfmt-core/tests/target/issue-1214.rs new file mode 100644 index 00000000000..c622abb3a85 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1214.rs @@ -0,0 +1,8 @@ +/*! +# Example + +``` + // Here goes some example +``` + */ +struct Item; diff --git a/rustfmt-core/tests/target/issue-1216.rs b/rustfmt-core/tests/target/issue-1216.rs new file mode 100644 index 00000000000..d727c158ab8 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1216.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +enum E { + A, //* I am not a block comment (caused panic) + B, +} diff --git a/rustfmt-core/tests/target/issue-1239.rs b/rustfmt-core/tests/target/issue-1239.rs new file mode 100644 index 00000000000..b10afb5cb6c --- /dev/null +++ b/rustfmt-core/tests/target/issue-1239.rs @@ -0,0 +1,10 @@ +fn foo() { + let with_alignment = if condition__uses_alignment_for_first_if__0 + || condition__uses_alignment_for_first_if__1 + || condition__uses_alignment_for_first_if__2 + { + } else if condition__no_alignment_for_later_else__0 || condition__no_alignment_for_later_else__1 + || condition__no_alignment_for_later_else__2 + { + }; +} diff --git a/rustfmt-core/tests/target/issue-1247.rs b/rustfmt-core/tests/target/issue-1247.rs new file mode 100644 index 00000000000..16c63e0f53d --- /dev/null +++ b/rustfmt-core/tests/target/issue-1247.rs @@ -0,0 +1,8 @@ +// rustfmt-max_width: 80 + +fn foo() { + polyfill::slice::fill( + &mut self.pending[padding_pos..(self.algorithm.block_len - 8)], + 0, + ); +} diff --git a/rustfmt-core/tests/target/issue-1255.rs b/rustfmt-core/tests/target/issue-1255.rs new file mode 100644 index 00000000000..2d4633844a9 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1255.rs @@ -0,0 +1,10 @@ +// Test for issue #1255 +// Default annotation incorrectly removed on associated types +#![feature(specialization)] + +trait Trait { + type Type; +} +impl Trait for T { + default type Type = u64; // 'default' should not be removed +} diff --git a/rustfmt-core/tests/target/issue-1278.rs b/rustfmt-core/tests/target/issue-1278.rs new file mode 100644 index 00000000000..e25376561a9 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1278.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style = "block" + +#![feature(pub_restricted)] + +mod inner_mode { + pub(super) fn func_name(abc: i32) -> i32 { + abc + } +} diff --git a/rustfmt-core/tests/target/issue-1350.rs b/rustfmt-core/tests/target/issue-1350.rs new file mode 100644 index 00000000000..2cf65509c93 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1350.rs @@ -0,0 +1,14 @@ +// rustfmt-max_width: 120 +// rustfmt-comment_width: 110 + +impl Struct { + fn fun() { + let result = match ::deserialize(&json) { + Ok(v) => v, + Err(e) => match ::deserialize(&json) { + Ok(v) => return Err(Error::with_json(v)), + Err(e2) => return Err(Error::with_json(e)), + }, + }; + } +} diff --git a/rustfmt-core/tests/target/issue-1366.rs b/rustfmt-core/tests/target/issue-1366.rs new file mode 100644 index 00000000000..eee147baab9 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1366.rs @@ -0,0 +1,13 @@ +fn main() { + fn f() -> Option { + Some("fffffffsssssssssddddssssfffffddddff") + .map(|s| s) + .map(|s| s.to_string()) + .map(|res| match Some(res) { + Some(ref s) if s == "" => 41, + Some(_) => 42, + _ => 43, + }) + } + println!("{:?}", f()) +} diff --git a/rustfmt-core/tests/target/issue-1397.rs b/rustfmt-core/tests/target/issue-1397.rs new file mode 100644 index 00000000000..86b7a78411f --- /dev/null +++ b/rustfmt-core/tests/target/issue-1397.rs @@ -0,0 +1,25 @@ +pub enum TransactionState { + Committed(i64), +} + +pub enum Packet { + Transaction { state: TransactionState }, +} + +fn baz(p: Packet) { + loop { + loop { + loop { + loop { + if let Packet::Transaction { + state: TransactionState::Committed(ts, ..), + .. + } = p + { + unreachable!() + } + } + } + } + } +} diff --git a/rustfmt-core/tests/target/issue-1468.rs b/rustfmt-core/tests/target/issue-1468.rs new file mode 100644 index 00000000000..4c14a0f746a --- /dev/null +++ b/rustfmt-core/tests/target/issue-1468.rs @@ -0,0 +1,29 @@ +fn issue1468() { + euc_jp_decoder_functions!({ + let trail_minus_offset = byte.wrapping_sub(0xA1); + // Fast-track Hiragana (60% according to Lunde) + // and Katakana (10% according to Lunde). + if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { + // Hiragana + handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) + } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 { + // Katakana + handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) + } else if trail_minus_offset > (0xFE - 0xA1) { + if byte < 0x80 { + return ( + DecoderResult::Malformed(1, 0), + unread_handle_trail.unread(), + handle.written(), + ); + } + return ( + DecoderResult::Malformed(2, 0), + unread_handle_trail.consumed(), + handle.written(), + ); + } else { + unreachable!(); + } + }); +} diff --git a/rustfmt-core/tests/target/issue-1598.rs b/rustfmt-core/tests/target/issue-1598.rs new file mode 100644 index 00000000000..c7e02c961a6 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1598.rs @@ -0,0 +1,6 @@ +fn main() { + //foo + /* + */ + format!("hello"); +} diff --git a/rustfmt-core/tests/target/issue-1624.rs b/rustfmt-core/tests/target/issue-1624.rs new file mode 100644 index 00000000000..477fc27353f --- /dev/null +++ b/rustfmt-core/tests/target/issue-1624.rs @@ -0,0 +1,6 @@ +// #1624 +pub unsafe fn some_long_function_name( + arg1: Type1, + arg2: Type2, +) -> (SomeLongTypeName, AnotherLongTypeName, AnotherLongTypeName) { +} diff --git a/rustfmt-core/tests/target/issue-1681.rs b/rustfmt-core/tests/target/issue-1681.rs new file mode 100644 index 00000000000..5734fd5502d --- /dev/null +++ b/rustfmt-core/tests/target/issue-1681.rs @@ -0,0 +1,20 @@ +// rustfmt-max_width: 80 + +// We would like to surround closure body with block when overflowing the last +// argument of function call if the last argument has condition and without +// block it may go multi lines. +fn foo() { + refmut_map_result(self.cache.borrow_mut(), |cache| { + match cache.entry(cache_key) { + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => { + let statement = { + let sql = try!(entry.key().sql(source)); + prepare_fn(&sql) + }; + + Ok(entry.insert(try!(statement))) + } + } + }).map(MaybeCached::Cached) +} diff --git a/rustfmt-core/tests/target/issue-1693.rs b/rustfmt-core/tests/target/issue-1693.rs new file mode 100644 index 00000000000..85421a123bb --- /dev/null +++ b/rustfmt-core/tests/target/issue-1693.rs @@ -0,0 +1,10 @@ +fn issue1693() { + let pixel_data = vec![ + ( + f16::from_f32(0.82), + f16::from_f32(1.78), + f16::from_f32(0.21) + ); + 256 * 256 + ]; +} diff --git a/rustfmt-core/tests/target/issue-1703.rs b/rustfmt-core/tests/target/issue-1703.rs new file mode 100644 index 00000000000..4079ef4cfca --- /dev/null +++ b/rustfmt-core/tests/target/issue-1703.rs @@ -0,0 +1,9 @@ +// rustfmt should not remove doc comments or comments inside attributes. + +/** +This function has a block doc comment. + */ +fn test_function() {} + +#[foo /* do not remove this! */] +fn foo() {} diff --git a/rustfmt-core/tests/target/issue-1800.rs b/rustfmt-core/tests/target/issue-1800.rs new file mode 100644 index 00000000000..06c5cfd0567 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1800.rs @@ -0,0 +1,3 @@ +#![doc(html_root_url = "http://example.com")] +#[cfg(feature = "foo")] +fn a() {} diff --git a/rustfmt-core/tests/target/issue-1802.rs b/rustfmt-core/tests/target/issue-1802.rs new file mode 100644 index 00000000000..a4679463ba2 --- /dev/null +++ b/rustfmt-core/tests/target/issue-1802.rs @@ -0,0 +1,10 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 30 +// rustfmt-error_on_line_overflow: false + +enum F { + X { + a: dddddddddddddd, + b: eeeeeeeeeeeeeee, + }, +} diff --git a/rustfmt-core/tests/target/issue-1824.rs b/rustfmt-core/tests/target/issue-1824.rs new file mode 100644 index 00000000000..1c4c2db46dc --- /dev/null +++ b/rustfmt-core/tests/target/issue-1824.rs @@ -0,0 +1,5 @@ +pub trait Ingredient +where + Self: Send, +{ +} diff --git a/rustfmt-core/tests/target/issue-1914.rs b/rustfmt-core/tests/target/issue-1914.rs new file mode 100644 index 00000000000..d2d532af1dc --- /dev/null +++ b/rustfmt-core/tests/target/issue-1914.rs @@ -0,0 +1,7 @@ +// rustfmt-max_width: 80 + +extern "C" { + #[link_name = "_ZN7MyClass26example_check_no_collisionE"] + pub static mut MyClass_example_check_no_collision: + *const ::std::os::raw::c_int; +} diff --git a/rustfmt-core/tests/target/issue-2025.rs b/rustfmt-core/tests/target/issue-2025.rs new file mode 100644 index 00000000000..38bf369bea3 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2025.rs @@ -0,0 +1,4 @@ +// See if rustfmt removes empty lines on top of the file. +pub fn foo() { + println!("hello, world"); +} diff --git a/rustfmt-core/tests/target/issue-2103.rs b/rustfmt-core/tests/target/issue-2103.rs new file mode 100644 index 00000000000..5a043d54b75 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2103.rs @@ -0,0 +1,14 @@ +struct X +where + i32: Sized, +{ + x: i32, +} + +struct X +// with comment +where + i32: Sized, +{ + x: i32, +} diff --git a/rustfmt-core/tests/target/issue-2111.rs b/rustfmt-core/tests/target/issue-2111.rs new file mode 100644 index 00000000000..13303a736a3 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2111.rs @@ -0,0 +1,26 @@ +// rustfmt-normalize_comments: false + +// An import with single line comments. +use super::{DelayChoice, + Destinations, + Holding, + LodaModel, + MethodDescription, + ModelBehaviour, + ModelEdges, + ModelProperties, + ModelRequestGraph, + ModelSelector, + RequestDescription, + StringMap, + Switch, + // ModelMetaData, + // Generated, + // SecondsString, + // DateString, + // ModelConfiguration, + // ModelRequests, + // RestResponse, + // RestResponseCode, + // UniformHolding + SCHEMA_VERSIONS}; diff --git a/rustfmt-core/tests/target/issue-2123.rs b/rustfmt-core/tests/target/issue-2123.rs new file mode 100644 index 00000000000..5e9917b4023 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2123.rs @@ -0,0 +1,6 @@ +// rustfmt-wrap_comments: true + +//hello +//world + +fn main() {} diff --git a/rustfmt-core/tests/target/issue-2164.rs b/rustfmt-core/tests/target/issue-2164.rs new file mode 100644 index 00000000000..ab1d7dfd37a --- /dev/null +++ b/rustfmt-core/tests/target/issue-2164.rs @@ -0,0 +1,132 @@ +// A stress test against code generated by bindgen. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct emacs_env_25 { + pub size: isize, + pub private_members: *mut emacs_env_private, + pub make_global_ref: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, any_reference: emacs_value) -> emacs_value, + >, + pub free_global_ref: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, global_reference: emacs_value), + >, + pub non_local_exit_check: + ::std::option::Option emacs_funcall_exit>, + pub non_local_exit_clear: ::std::option::Option, + pub non_local_exit_get: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + non_local_exit_symbol_out: *mut emacs_value, + non_local_exit_data_out: *mut emacs_value, + ) -> emacs_funcall_exit, + >, + pub non_local_exit_signal: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + non_local_exit_symbol: emacs_value, + non_local_exit_data: emacs_value, + ), + >, + pub non_local_exit_throw: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, tag: emacs_value, value: emacs_value), + >, + pub make_function: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + min_arity: isize, + max_arity: isize, + function: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + nargs: isize, + args: *mut emacs_value, + arg1: *mut ::libc::c_void, + ) -> emacs_value, + >, + documentation: *const ::libc::c_char, + data: *mut ::libc::c_void, + ) -> emacs_value, + >, + pub funcall: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + function: emacs_value, + nargs: isize, + args: *mut emacs_value, + ) -> emacs_value, + >, + pub intern: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, symbol_name: *const ::libc::c_char) + -> emacs_value, + >, + pub type_of: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> emacs_value, + >, + pub is_not_nil: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> bool, + >, + pub eq: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, a: emacs_value, b: emacs_value) -> bool, + >, + pub extract_integer: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> intmax_t, + >, + pub make_integer: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: intmax_t) -> emacs_value, + >, + pub extract_float: + ::std::option::Option f64>, + pub make_float: + ::std::option::Option emacs_value>, + pub copy_string_contents: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + value: emacs_value, + buffer: *mut ::libc::c_char, + size_inout: *mut isize, + ) -> bool, + >, + pub make_string: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, contents: *const ::libc::c_char, length: isize) + -> emacs_value, + >, + pub make_user_ptr: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + fin: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::libc::c_void), + >, + ptr: *mut ::libc::c_void, + ) -> emacs_value, + >, + pub get_user_ptr: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value) -> *mut ::libc::c_void, + >, + pub set_user_ptr: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value, ptr: *mut ::libc::c_void), + >, + pub get_user_finalizer: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value + ) -> ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value), + >, + >, + pub set_user_finalizer: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + uptr: emacs_value, + fin: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::libc::c_void), + >, + ), + >, + pub vec_get: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize) -> emacs_value, + >, + pub vec_set: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize, val: emacs_value), + >, + pub vec_size: + ::std::option::Option isize>, +} diff --git a/rustfmt-core/tests/target/issue-2179.rs b/rustfmt-core/tests/target/issue-2179.rs new file mode 100644 index 00000000000..db8f9c557b4 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2179.rs @@ -0,0 +1,36 @@ +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!( + "cargo - couldn't find binary `{}` specified in `build_bin` configuration", + build_bin + ); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; +} diff --git a/rustfmt-core/tests/target/issue-2197.rs b/rustfmt-core/tests/target/issue-2197.rs new file mode 100644 index 00000000000..76dbbefc3a7 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2197.rs @@ -0,0 +1,18 @@ +// rustfmt-max_width: 79 +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false + +/// ```rust +/// unsafe fn sum_sse2(x: i32x4) -> i32 { +/// let x = vendor::_mm_add_epi32( +/// x, +/// vendor::_mm_srli_si128(x.into(), 8).into(), +/// ); +/// let x = vendor::_mm_add_epi32( +/// x, +/// vendor::_mm_srli_si128(x.into(), 4).into(), +/// ); +/// vendor::_mm_cvtsi128_si32(x) +/// } +/// ``` +fn foo() {} diff --git a/rustfmt-core/tests/target/issue-2256.rs b/rustfmt-core/tests/target/issue-2256.rs new file mode 100644 index 00000000000..4b546223f94 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2256.rs @@ -0,0 +1,7 @@ +// こんにちは +use std::borrow::Cow; + +/* comment */ +/* comment */ + +/* comment */ diff --git a/rustfmt-core/tests/target/issue-2324.rs b/rustfmt-core/tests/target/issue-2324.rs new file mode 100644 index 00000000000..9211b24d81f --- /dev/null +++ b/rustfmt-core/tests/target/issue-2324.rs @@ -0,0 +1,7 @@ +// nested function calls with cast. +fn main() { + self.ptr + .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T); + self.ptr + .set(intrinsics::arith_offset(self.ptr.get(), mem::size_of::() as isize) as *mut u8); +} diff --git a/rustfmt-core/tests/target/issue-2329.rs b/rustfmt-core/tests/target/issue-2329.rs new file mode 100644 index 00000000000..e36e9546b24 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2329.rs @@ -0,0 +1,30 @@ +// Comments with characters which must be represented by multibyte. + +// フー +use foo; +// バー +use bar; + +impl MyStruct { + // コメント + fn f1() {} // こんにちは + fn f2() {} // ありがとう + // コメント +} + +trait MyTrait { + // コメント + fn f1() {} // こんにちは + fn f2() {} // ありがとう + // コメント +} + +fn main() { + // コメント + let x = 1; // X + println!( + "x = {}", // xの値 + x, // X + ); + // コメント +} diff --git a/rustfmt-core/tests/target/issue-2342.rs b/rustfmt-core/tests/target/issue-2342.rs new file mode 100644 index 00000000000..f9c26857e15 --- /dev/null +++ b/rustfmt-core/tests/target/issue-2342.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 80 + +struct Foo { + #[cfg(feature = "serde")] + bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN +} diff --git a/rustfmt-core/tests/target/issue-2401.rs b/rustfmt-core/tests/target/issue-2401.rs new file mode 100644 index 00000000000..ec8f27b732f --- /dev/null +++ b/rustfmt-core/tests/target/issue-2401.rs @@ -0,0 +1,7 @@ +// rustfmt-hard_tabs = true +// rustfmt-normalize_comments = true + +/// ``` +/// println!("Hello, World!"); +/// ``` +fn main() {} diff --git a/rustfmt-core/tests/target/issue-447.rs b/rustfmt-core/tests/target/issue-447.rs new file mode 100644 index 00000000000..d41cdb65cd0 --- /dev/null +++ b/rustfmt-core/tests/target/issue-447.rs @@ -0,0 +1,40 @@ +// rustfmt-normalize_comments: true + +fn main() { + if + // shouldn't be dropped + // shouldn't be dropped + cond + // shouldn't be dropped + // shouldn't be dropped + { + } + // shouldn't be dropped + // shouldn't be dropped + else + // shouldn't be dropped + // shouldn't be dropped + if + // shouldn't be dropped + // shouldn't be dropped + cond + // shouldn't be dropped + // shouldn't be dropped + { + } + // shouldn't be dropped + // shouldn't be dropped + else + // shouldn't be dropped + // shouldn't be dropped + { + } + + if + // shouldn't be dropped + // shouldn't be dropped + let Some(x) = y + // shouldn't be dropped + // shouldn't be dropped + {} +} diff --git a/rustfmt-core/tests/target/issue-510.rs b/rustfmt-core/tests/target/issue-510.rs new file mode 100644 index 00000000000..a166b68498f --- /dev/null +++ b/rustfmt-core/tests/target/issue-510.rs @@ -0,0 +1,41 @@ +impl ISizeAndMarginsComputer for AbsoluteNonReplaced { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match ( + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + ) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); + (Au(0), inline_size, margin_start, margin_end) + } + }; + + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); + (Au(0), inline_size, margin_start, margin_end) + } + }; + } +} diff --git a/rustfmt-core/tests/target/issue-64.rs b/rustfmt-core/tests/target/issue-64.rs new file mode 100644 index 00000000000..c0660630203 --- /dev/null +++ b/rustfmt-core/tests/target/issue-64.rs @@ -0,0 +1,7 @@ +// Regression test for issue 64 + +pub fn header_name() -> &'static str { + let name = ::header_name(); + let func = ::header_name; + name +} diff --git a/rustfmt-core/tests/target/issue-691.rs b/rustfmt-core/tests/target/issue-691.rs new file mode 100644 index 00000000000..7473d070eff --- /dev/null +++ b/rustfmt-core/tests/target/issue-691.rs @@ -0,0 +1,9 @@ +// rustfmt-normalize_comments: true + +//! `std` or `core` and simply link to this library. In case the target +//! platform has no hardware +//! support for some operation, software implementations provided by this +//! library will be used automagically. +// TODO: provide instructions to override default libm link and how to link to +// this library. +fn foo() {} diff --git a/rustfmt-core/tests/target/issue-770.rs b/rustfmt-core/tests/target/issue-770.rs new file mode 100644 index 00000000000..5fbedd7b734 --- /dev/null +++ b/rustfmt-core/tests/target/issue-770.rs @@ -0,0 +1,10 @@ +fn main() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} diff --git a/rustfmt-core/tests/target/issue-811.rs b/rustfmt-core/tests/target/issue-811.rs new file mode 100644 index 00000000000..b7a89b5d0f9 --- /dev/null +++ b/rustfmt-core/tests/target/issue-811.rs @@ -0,0 +1,19 @@ +trait FooTrait: Sized { + type Bar: BarTrait; +} + +trait BarTrait: Sized { + type Baz; + fn foo(); +} + +type Foo = <>::Bar as BarTrait>::Baz; +type Bar = >::Baz; + +fn some_func, U>() { + <>::Bar as BarTrait>::foo(); +} + +fn some_func>() { + >::foo(); +} diff --git a/rustfmt-core/tests/target/issue-831.rs b/rustfmt-core/tests/target/issue-831.rs new file mode 100644 index 00000000000..1d6327c2158 --- /dev/null +++ b/rustfmt-core/tests/target/issue-831.rs @@ -0,0 +1,9 @@ +fn main() { + let y = a.iter().any(|x| { + println!("a"); + }) || b.iter().any(|x| { + println!("b"); + }) || c.iter().any(|x| { + println!("c"); + }); +} diff --git a/rustfmt-core/tests/target/issue-850.rs b/rustfmt-core/tests/target/issue-850.rs new file mode 100644 index 00000000000..c939716a6a8 --- /dev/null +++ b/rustfmt-core/tests/target/issue-850.rs @@ -0,0 +1 @@ +const unsafe fn x() {} diff --git a/rustfmt-core/tests/target/issue-855.rs b/rustfmt-core/tests/target/issue-855.rs new file mode 100644 index 00000000000..0430cc62954 --- /dev/null +++ b/rustfmt-core/tests/target/issue-855.rs @@ -0,0 +1,27 @@ +fn main() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Some(Keycode::Escape), + .. + } => break 'running, + } + } + } +} + +fn main2() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDownXXXXXXXXXXXXX { + keycode: Some(Keycode::Escape), + .. + } => break 'running, + } + } + } +} diff --git a/rustfmt-core/tests/target/issue-913.rs b/rustfmt-core/tests/target/issue-913.rs new file mode 100644 index 00000000000..2158b70a46f --- /dev/null +++ b/rustfmt-core/tests/target/issue-913.rs @@ -0,0 +1,24 @@ +// rustfmt-error_on_line_overflow: false + +mod client { + impl Client { + fn test(self) -> Result<()> { + let next_state = match self.state { + State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { + let x = reformat.meeee(); + } + }; + + let next_state = match self.state { + State::V5(v5::State::Command(v5::comand::State::WriteVersion( + ref mut response, + ))) => { + // The pattern cannot be formatted in a way that the match stays + // within the column limit. The rewrite should therefore be + // skipped. + let x = dont.reformat.meeee(); + } + }; + } + } +} diff --git a/rustfmt-core/tests/target/issue-945.rs b/rustfmt-core/tests/target/issue-945.rs new file mode 100644 index 00000000000..d46c69a4f09 --- /dev/null +++ b/rustfmt-core/tests/target/issue-945.rs @@ -0,0 +1,17 @@ +impl Bar { + default const unsafe fn foo() { + "hi" + } +} + +impl Baz { + default unsafe extern "C" fn foo() { + "hi" + } +} + +impl Foo for Bar { + default fn foo() { + "hi" + } +} diff --git a/rustfmt-core/tests/target/issue-977.rs b/rustfmt-core/tests/target/issue-977.rs new file mode 100644 index 00000000000..9420054449d --- /dev/null +++ b/rustfmt-core/tests/target/issue-977.rs @@ -0,0 +1,16 @@ +// rustfmt-normalize_comments: true +// FIXME(#919) + +trait NameC { + // comment +} +struct FooC { /* comment */ } +enum MooC { + // comment +} +mod BarC { + // comment +} +extern "C" { + // comment +} diff --git a/rustfmt-core/tests/target/item-brace-style-always-next-line.rs b/rustfmt-core/tests/target/item-brace-style-always-next-line.rs new file mode 100644 index 00000000000..531ac598683 --- /dev/null +++ b/rustfmt-core/tests/target/item-brace-style-always-next-line.rs @@ -0,0 +1,42 @@ +// rustfmt-brace_style: AlwaysNextLine + +mod M +{ + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where + T: Copy, + { + A, + } + + struct B + where + T: Copy, + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where + T: Copy, {} + + struct D + where + T: Copy, {} +} diff --git a/rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs b/rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs new file mode 100644 index 00000000000..ef8dc028c2d --- /dev/null +++ b/rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs @@ -0,0 +1,35 @@ +// rustfmt-brace_style: PreferSameLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + enum C {} + + struct D {} + + enum A + where + T: Copy, { + A, + } + + struct B + where + T: Copy, { + b: i32, + } + + enum C + where + T: Copy, {} + + struct D + where + T: Copy, {} +} diff --git a/rustfmt-core/tests/target/item-brace-style-same-line-where.rs b/rustfmt-core/tests/target/item-brace-style-same-line-where.rs new file mode 100644 index 00000000000..9a275efc96e --- /dev/null +++ b/rustfmt-core/tests/target/item-brace-style-same-line-where.rs @@ -0,0 +1,39 @@ +// rustfmt-brace_style: SameLineWhere + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where + T: Copy, + { + A, + } + + struct B + where + T: Copy, + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where + T: Copy, {} + + struct D + where + T: Copy, {} +} diff --git a/rustfmt-core/tests/target/large-block.rs b/rustfmt-core/tests/target/large-block.rs new file mode 100644 index 00000000000..09e9169f340 --- /dev/null +++ b/rustfmt-core/tests/target/large-block.rs @@ -0,0 +1,5 @@ +fn issue1351() { + std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ + static __STATIC_FMTSTR: &'static [&'static str] = &[]; + }); +} diff --git a/rustfmt-core/tests/target/large_vec.rs b/rustfmt-core/tests/target/large_vec.rs new file mode 100644 index 00000000000..95d1fc43c03 --- /dev/null +++ b/rustfmt-core/tests/target/large_vec.rs @@ -0,0 +1,42 @@ +// See #1470. + +impl Environment { + pub fn new_root() -> Rc> { + let mut env = Environment::new(); + let builtin_functions = &[ + ( + "println", + Function::NativeVoid( + CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println, + ), + ), + ( + "run_http_server", + Function::NativeVoid( + CallSign { + num_params: 1, + variadic: false, + param_types: vec![Some(ConstraintType::Function)], + }, + native_run_http_server, + ), + ), + ( + "len", + Function::NativeReturning( + CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len, + ), + ), + ]; + } +} diff --git a/rustfmt-core/tests/target/long-fn-1.rs b/rustfmt-core/tests/target/long-fn-1.rs new file mode 100644 index 00000000000..c3d44de7c69 --- /dev/null +++ b/rustfmt-core/tests/target/long-fn-1.rs @@ -0,0 +1,21 @@ +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input( + &mut self, + input: Input, + input_path: Option, + ) -> (Input, Option) { + } + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { + } +} + +// #1843 +#[allow(non_snake_case)] +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash( +) -> bool { + false +} diff --git a/rustfmt-core/tests/target/long-match-arms-brace-newline.rs b/rustfmt-core/tests/target/long-match-arms-brace-newline.rs new file mode 100644 index 00000000000..aeb384e7203 --- /dev/null +++ b/rustfmt-core/tests/target/long-match-arms-brace-newline.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 80 +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + match x + { + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) + if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => + { + Ok(()) + } + _ => Err(x), + } +} diff --git a/rustfmt-core/tests/target/long_field_access.rs b/rustfmt-core/tests/target/long_field_access.rs new file mode 100644 index 00000000000..349d2c2f639 --- /dev/null +++ b/rustfmt-core/tests/target/long_field_access.rs @@ -0,0 +1,4 @@ +fn f() { + block_flow.base.stacking_relative_position_of_display_port = + self.base.stacking_relative_position_of_display_port; +} diff --git a/rustfmt-core/tests/target/loop.rs b/rustfmt-core/tests/target/loop.rs new file mode 100644 index 00000000000..f669e7e2c58 --- /dev/null +++ b/rustfmt-core/tests/target/loop.rs @@ -0,0 +1,34 @@ +fn main() { + loop { + return some_val; + } + + let x = loop { + do_forever(); + }; + + 'label: loop { + // Just comments + } + + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value + { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + } + + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) + { + // do smth + } + + while let Some(i) = x.find('s') { + x.update(); + continue; + continue 'foo; + } +} diff --git a/rustfmt-core/tests/target/macro_not_expr.rs b/rustfmt-core/tests/target/macro_not_expr.rs new file mode 100644 index 00000000000..c76a6492a9d --- /dev/null +++ b/rustfmt-core/tests/target/macro_not_expr.rs @@ -0,0 +1,7 @@ +macro_rules! test { + ($($t: tt)*) => {}; +} + +fn main() { + test!( a : B => c d ); +} diff --git a/rustfmt-core/tests/target/macro_rules.rs b/rustfmt-core/tests/target/macro_rules.rs new file mode 100644 index 00000000000..647d442034f --- /dev/null +++ b/rustfmt-core/tests/target/macro_rules.rs @@ -0,0 +1,43 @@ +macro_rules! m { + // a + ($expr: expr, $($func: ident)*) => {{ + let x = $expr; + $func(x) + }}; + + /* b */ + () => { + /* c */ + }; + + (@tag) => {}; + + // d + ($item: ident) => { + mod macro_item { + struct $item; + } + }; +} + +macro m2 { + // a + ($expr: expr, $($func: ident)*) => {{ + let x = $expr; + $func(x) + }} + + /* b */ + () => { + /* c */ + } + + (@tag) => {} + + // d + ($item: ident) => { + mod macro_item { + struct $item; + } + } +} diff --git a/rustfmt-core/tests/target/macros.rs b/rustfmt-core/tests/target/macros.rs new file mode 100644 index 00000000000..9b32c6623bb --- /dev/null +++ b/rustfmt-core/tests/target/macros.rs @@ -0,0 +1,913 @@ +// rustfmt-normalize_comments: true +itemmacro!(this, is.now().formatted(yay)); + +itemmacro!( + really, + long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() + .is + .formatted() +); + +itemmacro!{this, is.bracket().formatted()} + +peg_file! modname("mygrammarfile.rustpeg"); + +fn main() { + foo!(); + + bar!(a, b, c); + + bar!(a, b, c,); + + baz!(1 + 2 + 3, quux.kaas()); + + quux!( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + ); + + kaas!( + // comments + a, // post macro + b // another + ); + + trailingcomma!(a, b, c,); + // Preserve trailing comma only when necessary. + ok!(file.seek(SeekFrom::Start( + table.map(|table| fixture.offset(table)).unwrap_or(0), + ))); + + noexpr!( i am not an expression, OK? ); + + vec![a, b, c]; + + vec![ + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + BBBBB, + 5, + 100 - 30, + 1.33, + b, + b, + b, + ]; + + vec![a /* comment */]; + + // Trailing spaces after a comma + vec![a]; + + vec![a; b]; + vec![a; b]; + vec![a; b]; + + vec![a, b; c]; + vec![a; b, c]; + + vec![ + a; + (|x| { + let y = x + 1; + let z = y + 1; + z + })(2) + ]; + vec![ + a; + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ]; + vec![a; unsafe { x + 1 }]; + + unknown_bracket_macro__comma_should_not_be_stripped![a,]; + + foo(makro!(1, 3)); + + hamkaas!{ () }; + + macrowithbraces! {dont, format, me} + + x!(fn); + + some_macro!(); + + some_macro![]; + + some_macro!{ + // comment + }; + + some_macro!{ + // comment + }; + + some_macro!( + // comment + not function like + ); + + // #1712 + let image = gray_image!( + 00, 01, 02; + 10, 11, 12; + 20, 21, 22); + + // #1092 + chain!(input, a: take!(max_size), || []); +} + +impl X { + empty_invoc!{} +} + +fn issue_1279() { + println!("dsfs"); // a comment +} + +fn issue_1555() { + let hello = &format!( + "HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", + "65454654654654654654654655464", "4" + ); +} + +fn issue1178() { + macro_rules! foo { + (#[$attr: meta] $name: ident) => {}; + } + + foo!( + #[doc = "bar"] + baz + ); +} + +fn issue1739() { + sql_function!( + add_rss_item, + add_rss_item_t, + ( + a: types::Integer, + b: types::Timestamptz, + c: types::Text, + d: types::Text, + e: types::Text + ) + ); + + w.slice_mut(s![ + .., + init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], + .. + ]).par_map_inplace(|el| *el = 0.); +} + +fn issue_1885() { + let threads = people + .into_iter() + .map(|name| { + chan_select! { + rx.recv() => {} + } + }) + .collect::>(); +} + +fn issue_1917() { + mod x { + quickcheck! { + fn test(a: String, s: String, b: String) -> TestResult { + if a.find(&s).is_none() { + + TestResult::from_bool(true) + } else { + TestResult::discard() + } + } + } + } +} + +fn issue_1921() { + // Macro with tabs. + lazy_static! { + static ref ONE: u32 = 1; + static ref TWO: u32 = 2; + static ref THREE: u32 = 3; + static ref FOUR: u32 = { + let mut acc = 1; + acc += 1; + acc += 2; + acc + } + } +} + +// #1577 +fn issue1577() { + let json = json!({ + "foo": "bar", + }); +} + +gfx_pipeline!(pipe { + vbuf: gfx::VertexBuffer = (), + out: gfx::RenderTarget = "Target0", +}); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); + assert_eq!( + ::std::mem::align_of::>(), + 8usize, + concat!( + "Alignment of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); +} + +// #878 +macro_rules! try_opt { + ($expr: expr) => { + match $expr { + Some(val) => val, + + None => { + return None; + } + } + }; +} + +// #2214 +// macro call whose argument is an array with trailing comma. +fn issue2214() { + make_test!( + str_searcher_ascii_haystack, + "bb", + "abbcbbd", + [ + Reject(0, 1), + Match(1, 3), + Reject(3, 4), + Match(4, 6), + Reject(6, 7), + ] + ); +} + +fn special_case_macros() { + let p = eprint!(); + let q = eprint!("{}", 1); + let r = eprint!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = eprint!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = eprintln!("{}", 1); + let r = eprintln!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = eprintln!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = format!("{}", 1); + let r = format!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = format!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = format_args!("{}", 1); + let r = format_args!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = format_args!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = print!("{}", 1); + let r = print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = println!("{}", 1); + let r = println!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = println!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = unreachable!("{}", 1); + let r = unreachable!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = unreachable!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + debug!("{}", 1); + debug!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + debug!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + error!("{}", 1); + error!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + error!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + info!("{}", 1); + info!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + info!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + panic!("{}", 1); + panic!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + panic!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + warn!("{}", 1); + warn!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + warn!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + assert!(); + assert!(result == 42); + assert!(result == 42, "Ahoy there, {}!", target); + assert!( + result == 42, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected + ); + assert!( + result == 42, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + assert_eq!(); + assert_eq!(left); + assert_eq!(left, right); + assert_eq!(left, right, "Ahoy there, {}!", target); + assert_eq!( + left, right, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, input, expected + ); + assert_eq!( + first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, + second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected + ); + assert_eq!( + left + 42, + right, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected + ); + assert_eq!( + left, + right, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + write!(&mut s, "Ahoy there, {}!", target); + write!( + &mut s, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, input, expected + ); + write!( + &mut s, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + writeln!(&mut s, "Ahoy there, {}!", target); + writeln!( + &mut s, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, input, expected + ); + writeln!( + &mut s, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); +} + +// #1209 +impl Foo { + /// foo + pub fn foo(&self) -> Bar {} +} + +// #819 +fn macro_in_pattern_position() { + let x = match y { + foo!() => (), + bar!(a, b, c) => (), + bar!(a, b, c,) => (), + baz!(1 + 2 + 3, quux.kaas()) => (), + quux!( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + ) => (), + }; +} + +macro foo() {} + +pub macro bar($x: ident + $y: expr;) { + fn foo($x: Foo) { + long_function( + a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), + $x.bar($y), + ); + } +} + +macro foo() { + // a comment + fn foo() { + // another comment + bar(); + } +} + +macro lex_err($kind: ident $(, $body: expr)*) { + Err(QlError::LexError(LexError::$kind($($body,)*))) +} diff --git a/rustfmt-core/tests/target/match-block-trailing-comma.rs b/rustfmt-core/tests/target/match-block-trailing-comma.rs new file mode 100644 index 00000000000..44d1f289f8e --- /dev/null +++ b/rustfmt-core/tests/target/match-block-trailing-comma.rs @@ -0,0 +1,16 @@ +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + }, + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + } +} diff --git a/rustfmt-core/tests/target/match-nowrap-trailing-comma.rs b/rustfmt-core/tests/target/match-nowrap-trailing-comma.rs new file mode 100644 index 00000000000..19ef2144822 --- /dev/null +++ b/rustfmt-core/tests/target/match-nowrap-trailing-comma.rs @@ -0,0 +1,17 @@ +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + }, + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + } +} diff --git a/rustfmt-core/tests/target/match-nowrap.rs b/rustfmt-core/tests/target/match-nowrap.rs new file mode 100644 index 00000000000..9e674b1e2f5 --- /dev/null +++ b/rustfmt-core/tests/target/match-nowrap.rs @@ -0,0 +1,13 @@ +// rustfmt-match_arm_blocks: false +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => foo(), + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + } +} diff --git a/rustfmt-core/tests/target/match.rs b/rustfmt-core/tests/target/match.rs new file mode 100644 index 00000000000..83ee4f97b73 --- /dev/null +++ b/rustfmt-core/tests/target/match.rs @@ -0,0 +1,485 @@ +// rustfmt-normalize_comments: true +// Match expressions. + +fn foo() { + // A match expression. + match x { + // Some comment. + a => foo(), + b if 0 < 42 => foo(), + c => { + // Another comment. + // Comment. + an_expression; + foo() + } + Foo(ref bar) => { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } + Pattern1 | Pattern2 | Pattern3 => false, + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + | Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => blah, + Patternnnnnnnnnnnnnnnnnnn + | Patternnnnnnnnnnnnnnnnnnn + | Patternnnnnnnnnnnnnnnnnnn + | Patternnnnnnnnnnnnnnnnnnn => meh, + + Patternnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => { + meh + } + + Patternnnnnnnnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnnnnnnnn + if looooooooooooooooooooooooooooooooooooooooong_guard => + { + meh + } + + // Test that earlier patterns can take the guard space + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) + | Patternnnnnnnnnnnnnnnnnnnnnnnnn + if loooooooooooooooooooooooooooooooooooooooooong_guard => {} + + _ => {} + ast::PathParameters::AngleBracketedParameters(ref data) + if data.lifetimes.len() > 0 || data.types.len() > 0 || data.bindings.len() > 0 => {} + } + + let whatever = match something { + /// DOC COMMENT! + Some(_) => 42, + // Comment on an attribute. + #[an_attribute] + // Comment after an attribute. + None => 0, + #[rustfmt_skip] + Blurb => { } + }; +} + +// Test that a match on an overflow line is laid out properly. +fn main() { + let sub_span = + match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; +} + +// Test that one-line bodies align. +fn main() { + match r { + Variableeeeeeeeeeeeeeeeee => ( + "variable", + vec!["id", "name", "qualname", "value", "type", "scopeid"], + true, + true, + ), + Enummmmmmmmmmmmmmmmmmmmm => ( + "enum", + vec!["id", "qualname", "scopeid", "value"], + true, + true, + ), + Variantttttttttttttttttttttttt => ( + "variant", + vec!["id", "name", "qualname", "type", "value", "scopeid"], + true, + true, + ), + }; + + match x { + y => { /*Block with comment. Preserve me.*/ } + z => { + stmt(); + } + } +} + +fn matches() { + match 1 { + -1 => 10, + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0, // baz + } +} + +fn match_skip() { + let _ = match Some(1) { + #[rustfmt_skip] + Some( n ) => n, + None => 1, + }; +} + +fn issue339() { + match a { + b => {} + c => {} + d => {} + e => {} + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { + // comment above block + } + i => {} // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => {} + n => {} + o => {} + p => { + // Dont collapse me + } + q => {} + r => {} + s => 0, // s comment + // t comment + t => 1, + u => 2, + v => {} /* funky block + * comment */ + /* final comment */ + } +} + +fn issue355() { + match mac { + a => println!("a", b), + b => vec![1, 2], + c => vec![3; 4], + d => println!("a", b), + e => vec![1, 2], + f => vec![3; 4], + h => println!("a", b), // h comment + i => vec![1, 2], // i comment + j => vec![3; 4], // j comment + // k comment + k => println!("a", b), + // l comment + l => vec![1, 2], + // m comment + m => vec![3; 4], + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + println!("a", b) + } + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => { + vec![1, 2] + } + // Macro support fails to recognise this macro as splittable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { + vec![3; 4] + } + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { + println!("a", b) + } + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => { + vec![1, 2] + } + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { + vec![3; 4] + } + // Funky bracketing styles + t => println!{"a", b}, + u => vec![1, 2], + v => vec![3; 4], + w => println!["a", b], + x => vec![1, 2], + y => vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec![1, 2], // comment + vc => vec![3; 4], // comment + wc => println!["a", b], // comment + xc => vec![1, 2], // comment + yc => vec![3; 4], // comment + yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( + aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd, + ), + } +} + +fn issue280() { + { + match x { + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => { + ch == '\n' + } + ast::ItemConst(ref typ, ref expr) => { + self.process_static_or_const_item(item, &typ, &expr) + } + } + } +} + +fn issue383() { + match resolution.last_private { + LastImport { .. } => false, + _ => true, + }; +} + +fn issue507() { + match 1 { + 1 => unsafe { std::intrinsics::abort() }, + _ => (), + } +} + +fn issue508() { + match s.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement, + ))) => true, + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement, + ))) => s.has_object_data(), + Some(NodeTypeId::Element(_)) => false, + } +} + +fn issue496() { + { + { + { + match def { + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { + match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + Some(const_expr) => x, + } + } + } + } + } + } +} + +fn issue494() { + { + match stmt.node { + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { + result.push(StmtRef::Mirror(Box::new(Stmt { + span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref(), + }, + }))) + } + } + } +} + +fn issue386() { + match foo { + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr + | BiShl | BiShr => false, + } +} + +fn guards() { + match foo { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if fooooooooooooooooooooo + && (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + || cccccccccccccccccccccccccccccccccccccccc) => {} + } +} + +fn issue1371() { + Some(match type_ { + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; + + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => TextEntered { + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + }, + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; + + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; + + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) +} + +fn issue1395() { + let bar = Some(true); + let foo = Some(true); + let mut x = false; + bar.and_then(|_| match foo { + None => None, + Some(b) => { + x = true; + Some(b) + } + }); +} + +fn issue1456() { + Ok(Recording { + artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) +} + +fn issue1460() { + let _ = match foo { + REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => { + "internal_spec_insert_internal_spec_insert_internal_spec_insert" + } + _ => "reorder_something", + }; +} + +fn issue525() { + foobar( + f, + "{}", + match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }, + ); +} + +// #1838, #1839 +fn match_with_near_max_width() { + let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { + _ => unimplemented!(), + }; + + let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { + _ => unimplemented!(), + }; + + let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression + { + _ => unimplemented!(), + }; + match m { + Variant::Tag + | Variant::Tag2 + | Variant::Tag3 + | Variant::Tag4 + | Variant::Tag5 + | Variant::Tag6 => {} + } +} + +fn match_with_trailing_spaces() { + match x { + #![allow(simple_match)] + Some(..) => 0, + None => 1, + } +} + +fn issue_2099() { + let a = match x {}; + let b = match x {}; + + match x {} +} + +// #2021 +impl<'tcx> Const<'tcx> { + pub fn from_constval<'a>() -> Const<'tcx> { + let val = match *cv { + ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!( + "MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", + cv + ), + }; + } +} + +// #2151 +fn issue_2151() { + match either { + x => {} + y => (), + } +} + +// #2152 +fn issue_2152() { + match m { + "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" + if true => {} + "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => { + true + } + } +} diff --git a/rustfmt-core/tests/target/max-line-length-in-chars.rs b/rustfmt-core/tests/target/max-line-length-in-chars.rs new file mode 100644 index 00000000000..d49fbb7e30e --- /dev/null +++ b/rustfmt-core/tests/target/max-line-length-in-chars.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 25 + +// абвгдеёжзийклмнопрст +fn main() {} diff --git a/rustfmt-core/tests/target/mod-1.rs b/rustfmt-core/tests/target/mod-1.rs new file mode 100644 index 00000000000..a5d186c5df7 --- /dev/null +++ b/rustfmt-core/tests/target/mod-1.rs @@ -0,0 +1,38 @@ +// Deeply indented modules. + +mod foo { + mod bar { + mod baz {} + } +} + +mod foo { + mod bar { + mod baz { + fn foo() { + bar() + } + } + } + + mod qux {} +} + +mod boxed { + pub use std::boxed::{Box, HEAP}; +} + +pub mod x { + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE, + ) -> *mut FILE { + } +} + +mod y { + // sup boooooiiii +} diff --git a/rustfmt-core/tests/target/mod-2.rs b/rustfmt-core/tests/target/mod-2.rs new file mode 100644 index 00000000000..1a093bd5201 --- /dev/null +++ b/rustfmt-core/tests/target/mod-2.rs @@ -0,0 +1,5 @@ +// Some nested mods + +#[cfg(test)] +mod nestedmod; +pub mod no_new_line_beginning; diff --git a/rustfmt-core/tests/target/mod_skip_child.rs b/rustfmt-core/tests/target/mod_skip_child.rs new file mode 100644 index 00000000000..d48c4a37e81 --- /dev/null +++ b/rustfmt-core/tests/target/mod_skip_child.rs @@ -0,0 +1,2 @@ +// rustfmt-skip_children: true +mod nested_skipped; diff --git a/rustfmt-core/tests/target/mulit-file.rs b/rustfmt-core/tests/target/mulit-file.rs new file mode 100644 index 00000000000..1f829b36f3f --- /dev/null +++ b/rustfmt-core/tests/target/mulit-file.rs @@ -0,0 +1,10 @@ +// Tests that where a single file is referred to in multiple places, we don't +// crash. + +#[cfg(all(foo))] +#[path = "closure.rs"] +pub mod imp; + +#[cfg(all(bar))] +#[path = "closure.rs"] +pub mod imp; diff --git a/rustfmt-core/tests/target/multiple.rs b/rustfmt-core/tests/target/multiple.rs new file mode 100644 index 00000000000..0c330d80a56 --- /dev/null +++ b/rustfmt-core/tests/target/multiple.rs @@ -0,0 +1,178 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-format_strings: true +// Test of lots of random stuff. +// FIXME split this into multiple, self-contained tests. + +#[attr1] +extern crate foo; +#[attr2] +#[attr3] +extern crate foo; +#[attr1] +extern crate foo; +#[attr2] +#[attr3] +extern crate foo; + +use std::cell::*; +use std::{self, any, ascii, borrow, borrow, borrow, borrow, borrow, borrow, borrow, borrow, + borrow, borrow, borrow, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, + boxed, char, char, char, char, char, char, char, char, char, char}; + +mod doc; +mod other; + +// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff +// ffffffffffffffffffffffffffffffffffffffffff + +fn foo(a: isize, b: u32 /* blah blah */, c: f64) {} + +fn foo() -> Box +where + 'a: 'b, + for<'a> D<'b>: 'a, +{ + hello!() +} + +fn baz< + 'a: 'b, // comment on 'a + T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, // comment on T +>( + a: A, + b: B, // comment on b + c: C, +) -> Bob { + #[attr1] + extern crate foo; + #[attr2] + #[attr3] + extern crate foo; + #[attr1] + extern crate foo; + #[attr2] + #[attr3] + extern crate foo; +} + +#[rustfmt_skip] +fn qux(a: dadsfa, // Comment 1 + b: sdfasdfa, // Comment 2 + c: dsfdsafa) // Comment 3 +{ + +} + +/// Blah blah blah. +impl Bar { + fn foo( + &mut self, + a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a + b: sdfasdfsdfasfs, // closing comment + ) -> isize { + } + + /// Blah blah blah. + pub fn f2(self) { + (foo, bar) + } + + #[an_attribute] + fn f3(self) -> Dog {} +} + +/// The `nodes` and `edges` method each return instantiations of +/// `Cow<[T]>` to leave implementers the freedom to create + +/// entirely new vectors or to pass back slices into internally owned +/// vectors. +pub trait GraphWalk<'a, N, E> { + /// Returns all the nodes in this graph. + fn nodes(&'a self) -> Nodes<'a, N>; + /// Returns all of the edges in this graph. + fn edges(&'a self) -> Edges<'a, E>; + /// The source node for `edge`. + fn source(&'a self, edge: &E) -> N; + /// The target node for `edge`. + fn target(&'a self, edge: &E) -> N; +} + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, +} + +struct Bar; + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +fn foo(ann: &'a (PpAnn + 'a)) {} + +fn main() { + for i in 0i32..4 { + println!("{}", i); + } + + while true { + hello(); + } + + let rc = Cell::new( + 42usize, + 42usize, + Cell::new( + 42usize, + remaining_widthremaining_widthremaining_widthremaining_width, + ), + 42usize, + ); + let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment + let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd"; + let s = expand(a, b); +} + +fn deconstruct() -> ( + SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { +} + +fn deconstruct( + foo: Bar, +) -> ( + SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { +} + +#[rustfmt_skip] +mod a{ +fn foo(x: T) { + let x: T = dfasdf; +} +} diff --git a/rustfmt-core/tests/target/nested-if-else.rs b/rustfmt-core/tests/target/nested-if-else.rs new file mode 100644 index 00000000000..9a54789ddcd --- /dev/null +++ b/rustfmt-core/tests/target/nested-if-else.rs @@ -0,0 +1,11 @@ +fn issue1518() { + Some(Object { + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) +} diff --git a/rustfmt-core/tests/target/nested-visual-block.rs b/rustfmt-core/tests/target/nested-visual-block.rs new file mode 100644 index 00000000000..95b9bc2dea2 --- /dev/null +++ b/rustfmt-core/tests/target/nested-visual-block.rs @@ -0,0 +1,59 @@ +fn main() { + // #1078 + let items = itemize_list( + context.codemap, + field_iter, + "}", + |item| match *item { + StructLitField::Regular(ref field) => field.span.lo(), + StructLitField::Base(ref expr) => { + let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }, + |item| match *item { + StructLitField::Regular(ref field) => field.span.hi(), + StructLitField::Base(ref expr) => expr.span.hi(), + }, + |item| { + match *item { + StructLitField::Regular(ref field) => rewrite_field( + inner_context, + &field, + &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent), + ), + StructLitField::Base(ref expr) => { + // 2 = .. + expr.rewrite( + inner_context, + &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2), + ).map(|s| format!("..{}", s)) + } + } + }, + context.codemap.span_after(span, "{"), + span.hi(), + ); + + // #1580 + self.0.pool.execute(move || { + let _timer = segments.0.rotate_timer.time(); + if let Err(e) = segments.rotate_async(wal) { + error!("error compacting segment storage WAL", unsafe { error: e.display() }); + } + }); + + // #1581 + bootstrap.checks.register("PERSISTED_LOCATIONS", move || { + if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + } + }); +} diff --git a/rustfmt-core/tests/target/nested_skipped/mod.rs b/rustfmt-core/tests/target/nested_skipped/mod.rs new file mode 100644 index 00000000000..0ab6f081e44 --- /dev/null +++ b/rustfmt-core/tests/target/nested_skipped/mod.rs @@ -0,0 +1,3 @@ +fn ugly() { + 92; +} diff --git a/rustfmt-core/tests/target/nestedmod/mod.rs b/rustfmt-core/tests/target/nestedmod/mod.rs new file mode 100644 index 00000000000..1df46293184 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/mod.rs @@ -0,0 +1,12 @@ +mod mod2a; +mod mod2b; + +mod mymod1 { + use mod2a::{Bar, Foo}; + mod mod3a; +} + +#[path = "mod2c.rs"] +mod mymod2; + +mod submod2; diff --git a/rustfmt-core/tests/target/nestedmod/mod2a.rs b/rustfmt-core/tests/target/nestedmod/mod2a.rs new file mode 100644 index 00000000000..5df457a8316 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/mod2a.rs @@ -0,0 +1,4 @@ +// This is an empty file containing only +// comments + +// ................... diff --git a/rustfmt-core/tests/target/nestedmod/mod2b.rs b/rustfmt-core/tests/target/nestedmod/mod2b.rs new file mode 100644 index 00000000000..9b6ea844e65 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/mod2b.rs @@ -0,0 +1,2 @@ +#[path = "mod2a.rs"] +mod c; diff --git a/rustfmt-core/tests/target/nestedmod/mod2c.rs b/rustfmt-core/tests/target/nestedmod/mod2c.rs new file mode 100644 index 00000000000..7db4572e777 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/mod2c.rs @@ -0,0 +1,3 @@ +// A standard mod + +fn a() {} diff --git a/rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs b/rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs new file mode 100644 index 00000000000..ae09d8ddac0 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs @@ -0,0 +1,2 @@ +// Another mod +fn a() {} diff --git a/rustfmt-core/tests/target/nestedmod/submod2/a.rs b/rustfmt-core/tests/target/nestedmod/submod2/a.rs new file mode 100644 index 00000000000..120b17145e3 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/submod2/a.rs @@ -0,0 +1,6 @@ +// Yet Another mod +// Nested + +use c::a; + +fn foo() {} diff --git a/rustfmt-core/tests/target/nestedmod/submod2/mod.rs b/rustfmt-core/tests/target/nestedmod/submod2/mod.rs new file mode 100644 index 00000000000..52f8be91022 --- /dev/null +++ b/rustfmt-core/tests/target/nestedmod/submod2/mod.rs @@ -0,0 +1,5 @@ +// Another mod + +mod a; + +use a::a; diff --git a/rustfmt-core/tests/target/no_new_line_beginning.rs b/rustfmt-core/tests/target/no_new_line_beginning.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/rustfmt-core/tests/target/no_new_line_beginning.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/rustfmt-core/tests/target/other.rs b/rustfmt-core/tests/target/other.rs new file mode 100644 index 00000000000..dfce84fcdc4 --- /dev/null +++ b/rustfmt-core/tests/target/other.rs @@ -0,0 +1,5 @@ +// Part of multiple.rs + +fn bob() { + println!("hello other!"); +} diff --git a/rustfmt-core/tests/target/paths.rs b/rustfmt-core/tests/target/paths.rs new file mode 100644 index 00000000000..0d2ba797eb7 --- /dev/null +++ b/rustfmt-core/tests/target/paths.rs @@ -0,0 +1,28 @@ +// rustfmt-normalize_comments: true + +fn main() { + let constellation_chan = + Constellation::::start( + compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard, + ); + + Quux::< + ParamOne, // Comment 1 + ParamTwo, // Comment 2 + >::some_func(); + + <*mut JSObject>::relocate(entry); + + let x: Foo; + let x: Foo/*::*/; +} + +fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {} diff --git a/rustfmt-core/tests/target/pattern-condense-wildcards.rs b/rustfmt-core/tests/target/pattern-condense-wildcards.rs new file mode 100644 index 00000000000..39f99d9e123 --- /dev/null +++ b/rustfmt-core/tests/target/pattern-condense-wildcards.rs @@ -0,0 +1,12 @@ +// rustfmt-normalize_comments: true +// rustfmt-condense_wildcard_suffixes: true + +fn main() { + match x { + Butt(..) => "hah", + Tup(_) => "nah", + Quad(_, _, x, _) => " also no rewrite", + Quad(x, ..) => "condense me pls", + Weird(x, _, _, /* dont condense before */ ..) => "pls work", + } +} diff --git a/rustfmt-core/tests/target/pattern.rs b/rustfmt-core/tests/target/pattern.rs new file mode 100644 index 00000000000..6c62affb848 --- /dev/null +++ b/rustfmt-core/tests/target/pattern.rs @@ -0,0 +1,77 @@ +// rustfmt-normalize_comments: true +fn main() { + let z = match x { + "pat1" => 1, + (ref x, ref mut y /* comment */) => 2, + }; + + if let ::CONST = ident { + do_smth(); + } + + let Some(ref xyz /* comment! */) = opt; + + if let None = opt2 { + panic!("oh noes"); + } + + let foo @ bar(f) = 42; + let a::foo(..) = 42; + let [] = 42; + let [a.., b, c] = 42; + let [a, b, c..] = 42; + let [a, b, c, d.., e, f, g] = 42; + let foo {} = 42; + let foo { .. } = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. + } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. + }; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + }; +} + +impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { + fn mutate_fragment(&mut self, fragment: &mut Fragment) { + match **info { + GeneratedContentInfo::ContentItem(ContentItem::Counter( + ref counter_name, + counter_style, + )) => {} + } + } +} + +fn issue_1319() { + if let (Event { .. }, ..) = ev_state {} +} + +fn issue_1874() { + if let Some(()) = x { + y + } +} + +fn combine_patterns() { + let x = match y { + Some(Some(Foo { + z: Bar(..), + a: Bar(..), + b: Bar(..), + })) => z, + _ => return, + }; +} diff --git a/rustfmt-core/tests/target/pub-restricted.rs b/rustfmt-core/tests/target/pub-restricted.rs new file mode 100644 index 00000000000..8cc2ade612a --- /dev/null +++ b/rustfmt-core/tests/target/pub-restricted.rs @@ -0,0 +1,64 @@ +pub(super) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(crate) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +crate enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(in global::path::to::some_mod) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(in local::path::to::some_mod) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} diff --git a/rustfmt-core/tests/target/remove_blank_lines.rs b/rustfmt-core/tests/target/remove_blank_lines.rs new file mode 100644 index 00000000000..89b18e40b83 --- /dev/null +++ b/rustfmt-core/tests/target/remove_blank_lines.rs @@ -0,0 +1,28 @@ +fn main() { + let x = 1; + + let y = 2; + + println!("x + y = {}", x + y); +} + +fn foo() { + #![attribute] + + let x = 1; + + // comment +} +// comment after item + +// comment before item +fn bar() { + let x = 1; + // comment after statement + + // comment before statment + let y = 2; + let z = 3; + + println!("x + y + z = {}", x + y + z); +} diff --git a/rustfmt-core/tests/target/single-line-if-else.rs b/rustfmt-core/tests/target/single-line-if-else.rs new file mode 100644 index 00000000000..98fd793cba2 --- /dev/null +++ b/rustfmt-core/tests/target/single-line-if-else.rs @@ -0,0 +1,58 @@ +// Format if-else expressions on a single line, when possible. + +fn main() { + let a = if 1 > 2 { unreachable!() } else { 10 }; + + let a = if x { + 1 + } else if y { + 2 + } else { + 3 + }; + + let b = if cond() { + 5 + } else { + // Brief comment. + 10 + }; + + let c = if cond() { + statement(); + + 5 + } else { + 10 + }; + + let d = if let Some(val) = turbo { + "cool" + } else { + "beans" + }; + + if cond() { + statement(); + } else { + other_statement(); + } + + if true { + do_something() + } + + let x = if veeeeeeeeery_loooooong_condition() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } else { + bbbbbbbbbb + }; + + let x = if veeeeeeeeery_loooooong_condition() { + aaaaaaaaaaaaaaaaaaaaaaaaa + } else { + bbbbbbbbbb + }; + + funk(if test() { 1 } else { 2 }, arg2); +} diff --git a/rustfmt-core/tests/target/skip.rs b/rustfmt-core/tests/target/skip.rs new file mode 100644 index 00000000000..28897ade56f --- /dev/null +++ b/rustfmt-core/tests/target/skip.rs @@ -0,0 +1,87 @@ +// Test the skip attribute works + +#[rustfmt_skip] +fn foo() { badly; formatted; stuff +; } + +#[rustfmt_skip] +trait Foo +{ +fn foo( +); +} + +impl LateLintPass for UsedUnderscoreBinding { + #[cfg_attr(rustfmt, rustfmt_skip)] + fn check_expr() { // comment + } +} + +fn issue1346() { + #[cfg_attr(rustfmt, rustfmt_skip)] + Box::new(self.inner.call(req).then(move |result| { + match result { + Ok(resp) => Box::new(future::done(Ok(resp))), + Err(e) => { + try_error!(clo_stderr, "{}", e); + Box::new(future::err(e)) + } + } + })) +} + +fn skip_on_statements() { + // Outside block + #[rustfmt_skip] + { + foo; bar; + // junk + } + + { + // Inside block + #![rustfmt_skip] + foo; bar; + // junk + } + + // Semi + #[cfg_attr(rustfmt, rustfmt_skip)] + foo( + 1, 2, 3, 4, + 1, 2, + 1, 2, 3, + ); + + // Local + #[cfg_attr(rustfmt, rustfmt_skip)] + let x = foo( a, b , c); + + // Item + #[cfg_attr(rustfmt, rustfmt_skip)] + use foobar ; + + // Mac + #[cfg_attr(rustfmt, rustfmt_skip)] + vec![ + 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, + 1, + 1, 2, + 1, + ]; + + // Expr + #[cfg_attr(rustfmt, rustfmt_skip)] + foo( a, b , c) +} + +// Check that the skip attribute applies to other attributes. +#[rustfmt_skip] +#[cfg +( a , b +)] +fn +main() {} diff --git a/rustfmt-core/tests/target/skip_mod.rs b/rustfmt-core/tests/target/skip_mod.rs new file mode 100644 index 00000000000..38ece8f070d --- /dev/null +++ b/rustfmt-core/tests/target/skip_mod.rs @@ -0,0 +1,3 @@ +#![rustfmt_skip] +use a :: b +; diff --git a/rustfmt-core/tests/target/soft-wrapping.rs b/rustfmt-core/tests/target/soft-wrapping.rs new file mode 100644 index 00000000000..58f3557fbe2 --- /dev/null +++ b/rustfmt-core/tests/target/soft-wrapping.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 80 +// Soft wrapping for comments. + +// #535, soft wrapping for comments +// Compare the lowest `f32` of both inputs for greater than or equal. The +// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits +// off the result are the upper 96 bits of `a`. + +/// Compare the lowest `f32` of both inputs for greater than or equal. The +/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits +/// off the result are the upper 96 bits of `a`. +fn foo() {} diff --git a/rustfmt-core/tests/target/space-not-before-newline.rs b/rustfmt-core/tests/target/space-not-before-newline.rs new file mode 100644 index 00000000000..9d75b726aa0 --- /dev/null +++ b/rustfmt-core/tests/target/space-not-before-newline.rs @@ -0,0 +1,8 @@ +struct Foo { + a: (), + // spaces ^^^ to be removed +} +enum Foo { + Bar, + // spaces ^^^ to be removed +} diff --git a/rustfmt-core/tests/target/spaces-around-ranges.rs b/rustfmt-core/tests/target/spaces-around-ranges.rs new file mode 100644 index 00000000000..b53e5b58b8c --- /dev/null +++ b/rustfmt-core/tests/target/spaces-around-ranges.rs @@ -0,0 +1,15 @@ +// rustfmt-spaces_around_ranges: true + +fn bar(v: &[u8]) {} + +fn foo() { + let a = vec![0; 20]; + for j in 0 ..= 20 { + for i in 0 .. 3 { + bar(a[i .. j]); + bar(a[i ..]); + bar(a[.. j]); + bar(a[..= (j + 1)]); + } + } +} diff --git a/rustfmt-core/tests/target/static.rs b/rustfmt-core/tests/target/static.rs new file mode 100644 index 00000000000..5daccf3e7f7 --- /dev/null +++ b/rustfmt-core/tests/target/static.rs @@ -0,0 +1,27 @@ +const FILE_GENERIC_READ: DWORD = + STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; + +static boolnames: &'static [&'static str] = &[ + "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", + "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", + "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", + "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr", +]; + +static mut name: SomeType = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + +pub static count: u8 = 10; + +pub const test: &Type = &val; + +impl Color { + pub const WHITE: u32 = 10; +} + +// #1391 +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = + 0 as usize; + +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: + Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/rustfmt-core/tests/target/string-lit-2.rs b/rustfmt-core/tests/target/string-lit-2.rs new file mode 100644 index 00000000000..6b95e25a052 --- /dev/null +++ b/rustfmt-core/tests/target/string-lit-2.rs @@ -0,0 +1,25 @@ +fn main() -> &'static str { + let too_many_lines = "Hello"; + let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} + +fn issue_1237() { + let msg = "eedadn\n\ + drvtee\n\ + eandsr\n\ + raavrd\n\ + atevrs\n\ + tsrnev\n\ + sdttsa\n\ + rasrtv\n\ + nssdts\n\ + ntnada\n\ + svetve\n\ + tesnvt\n\ + vntsnd\n\ + vrdear\n\ + dvrsen\n\ + enarar"; +} diff --git a/rustfmt-core/tests/target/string-lit-custom.rs b/rustfmt-core/tests/target/string-lit-custom.rs new file mode 100644 index 00000000000..50ebb97491b --- /dev/null +++ b/rustfmt-core/tests/target/string-lit-custom.rs @@ -0,0 +1,22 @@ +// rustfmt-format_strings: false + +fn main() { + let expected = "; ModuleID = \'foo\' + +; Function Attrs: nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 + +declare i32 @write(i32, i8*, i32) + +declare i32 @putchar(i32) + +declare i32 @getchar() + +define i32 @main() { +entry: + ret i32 0 +} + +attributes #0 = { nounwind } +"; +} diff --git a/rustfmt-core/tests/target/string-lit.rs b/rustfmt-core/tests/target/string-lit.rs new file mode 100644 index 00000000000..f60002ac618 --- /dev/null +++ b/rustfmt-core/tests/target/string-lit.rs @@ -0,0 +1,64 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false +// Long string literals + +fn main() -> &'static str { + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let too_many_lines = "Hello"; + + // Make sure we don't break after an escape character. + let odd_length_name = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let even_length_name = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + + let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let raw_string = r#"Do +not +remove +formatting"#; + + filename.replace(" ", "\\"); + + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + let unicode = "a̐éö̲\r\n"; + let unicode2 = "Löwe 老虎 Léopard"; + let unicode3 = "中华Việt Nam"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + + "stuffin'" +} + +fn issue682() { + let a = "hello \\ o/"; + let b = a.replace("\\ ", "\\"); +} + +fn issue716() { + println!( + "forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()" + ); +} + +fn issue_1282() { + { + match foo { + Permission::AndroidPermissionAccessLocationExtraCommands => { + "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" + } + } + } +} + +// #1987 +#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] \ + -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] +extern "C" {} diff --git a/rustfmt-core/tests/target/string_punctuation.rs b/rustfmt-core/tests/target/string_punctuation.rs new file mode 100644 index 00000000000..1cc73d14060 --- /dev/null +++ b/rustfmt-core/tests/target/string_punctuation.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false + +fn main() { + println!( + "ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ + Likethisssssssssssss" + ); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); + println!( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ + adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ + ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea" + ); +} diff --git a/rustfmt-core/tests/target/struct-field-attributes.rs b/rustfmt-core/tests/target/struct-field-attributes.rs new file mode 100644 index 00000000000..5d6e92a91d9 --- /dev/null +++ b/rustfmt-core/tests/target/struct-field-attributes.rs @@ -0,0 +1,56 @@ +// #1535 +#![feature(struct_field_attributes)] + +struct Foo { + bar: u64, + + #[cfg(test)] + qux: u64, +} + +fn do_something() -> Foo { + Foo { + bar: 0, + + #[cfg(test)] + qux: 1, + } +} + +fn main() { + do_something(); +} + +// #1462 +struct Foo { + foo: usize, + #[cfg(feature = "include-bar")] + bar: usize, +} + +fn new_foo() -> Foo { + Foo { + foo: 0, + #[cfg(feature = "include-bar")] + bar: 0, + } +} + +// #2044 +pub enum State { + Closure( + #[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] + GcPtr, + ), +} + +struct Fields( + #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] + Arc>, +); + +// #2309 +pub struct A { + #[doc = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] + pub foos: Vec, +} diff --git a/rustfmt-core/tests/target/struct_lits.rs b/rustfmt-core/tests/target/struct_lits.rs new file mode 100644 index 00000000000..648c723d357 --- /dev/null +++ b/rustfmt-core/tests/target/struct_lits.rs @@ -0,0 +1,191 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: f(), + b: b(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a: Bar, b: f() }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S { a: 0, ..b }; +} + +fn issue201_2() { + let s = S { a: S2 { ..c }, ..b }; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo { a: 1, b: f(2) }; + Foo { + a: 1, + b: f(2), + ..g(3) + }; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { + ..base + }; + IntrinsicISizesContribution { + content_intrinsic_sizes: IntrinsicISizes { + minimum_inline_size: 0, + }, + }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { + a: bb, + c: dd, + e: ff, + }; + + Foo { + a: ddddddddddddddddddddd, + b: cccccccccccccccccccccccccccccccccccccc, + }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { + a: aaaaaaaaaa, + b: bbbbbbbb, + c: cccccccccc, + d: dddddddddd, // a comment + e: eeeeeeeee, + }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, ..base }; + Foo { + aaaaaaaaaa, + bbbbbbbb, + cccccccccc, + dddddddddd, // a comment + eeeeeeeee, + }; + Record { + ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; +} diff --git a/rustfmt-core/tests/target/struct_lits_multiline.rs b/rustfmt-core/tests/target/struct_lits_multiline.rs new file mode 100644 index 00000000000..c831dc7a8ba --- /dev/null +++ b/rustfmt-core/tests/target/struct_lits_multiline.rs @@ -0,0 +1,117 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-struct_lit_single_line: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { + a: x, + }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { + a: Bar, + b: foo(), + }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { + memb: 10, + }; +} + +fn issue201() { + let s = S { + a: 0, + ..b + }; +} + +fn issue201_2() { + let s = S { + a: S2 { + ..c + }, + ..b + }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; +} diff --git a/rustfmt-core/tests/target/struct_lits_visual.rs b/rustfmt-core/tests/target/struct_lits_visual.rs new file mode 100644 index 00000000000..7e93b91d8c1 --- /dev/null +++ b/rustfmt-core/tests/target/struct_lits_visual.rs @@ -0,0 +1,50 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* Comment */ + // Comment + b: bar(), /* Comment */ }; + + Foo { a: Bar, b: f() }; + + Quux { x: if cond { + bar(); + }, + y: baz(), }; + + Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + z: zzzzz, /* test */ }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +} diff --git a/rustfmt-core/tests/target/struct_lits_visual_multiline.rs b/rustfmt-core/tests/target/struct_lits_visual_multiline.rs new file mode 100644 index 00000000000..2809d3a2612 --- /dev/null +++ b/rustfmt-core/tests/target/struct_lits_visual_multiline.rs @@ -0,0 +1,50 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-struct_lit_single_line: false +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* Comment */ + // Comment + b: bar(), /* Comment */ }; + + Foo { a: Bar, + b: foo(), }; + + Quux { x: if cond { + bar(); + }, + y: baz(), }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +} diff --git a/rustfmt-core/tests/target/struct_tuple_visual.rs b/rustfmt-core/tests/target/struct_tuple_visual.rs new file mode 100644 index 00000000000..369feae71d2 --- /dev/null +++ b/rustfmt-core/tests/target/struct_tuple_visual.rs @@ -0,0 +1,37 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual +fn foo() { + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment + foo(), /* Comment */ + // Comment + bar() /* Comment */); + + Foo(Bar, f()); + + Quux(if cond { + bar(); + }, + baz()); + + Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + zzzzz /* test */); + + A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + Item); + + Diagram(// o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + G) +} diff --git a/rustfmt-core/tests/target/structs.rs b/rustfmt-core/tests/target/structs.rs new file mode 100644 index 00000000000..59a57a9b5b4 --- /dev/null +++ b/rustfmt-core/tests/target/structs.rs @@ -0,0 +1,332 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1095 +struct S { + t: T, +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct NewInt( + pub i32, + SomeType, // inline comment + T, // sup +); + +struct Qux< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy, +>( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple( + // Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +struct Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +struct Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +// Will this be a one-liner? +struct Tuple( + A, // Comment + B, +); + +pub struct State time::Timespec> { + now: F, +} + +pub struct State ()> { + now: F, +} + +pub struct State { + now: F, +} + +struct Palette { + /// A map of indices in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(T); +struct Foo(T) +where + T: Copy, + T: Eq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +); +struct Foo( + TTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU, // Bar + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU, +); + +mod m { + struct X + where + T: Sized, + { + a: T, + } +} + +struct Foo( + TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU, +); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +struct Foo {} +struct Foo {} +struct Foo { + // comment +} +struct Foo { + // trailing space -> +} +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +struct Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} + +// structs with long identifier +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{ + x: i32, +} + +// structs with visibility, do not duplicate visibility (#2110). +pub(self) struct Foo {} +pub(super) struct Foo {} +pub(crate) struct Foo {} +pub(self) struct Foo(); +pub(super) struct Foo(); +pub(crate) struct Foo(); + +// #2125 +pub struct ReadinessCheckRegistry( + Mutex, Box ReadinessCheck + Sync + Send>>>, +); + +// #2144 unit struct with generics +struct MyBox; +struct MyBoxx +where + T: ?Sized, + S: Clone; + +// #2208 +struct Test { + /// foo + #[serde(default)] + pub join: Vec, + #[serde(default)] + pub tls: bool, +} diff --git a/rustfmt-core/tests/target/trailing-comma-never.rs b/rustfmt-core/tests/target/trailing-comma-never.rs new file mode 100644 index 00000000000..3df0c7950eb --- /dev/null +++ b/rustfmt-core/tests/target/trailing-comma-never.rs @@ -0,0 +1,31 @@ +// rustfmt-trailing_comma: Never + +enum X { + A, + B +} + +enum Y { + A, + B +} + +enum TupX { + A(u32), + B(i32, u16) +} + +enum TupY { + A(u32), + B(i32, u16) +} + +enum StructX { + A { s: u16 }, + B { u: u32, i: i32 } +} + +enum StructY { + A { s: u16 }, + B { u: u32, i: i32 } +} diff --git a/rustfmt-core/tests/target/trailing_commas.rs b/rustfmt-core/tests/target/trailing_commas.rs new file mode 100644 index 00000000000..61b82035450 --- /dev/null +++ b/rustfmt-core/tests/target/trailing_commas.rs @@ -0,0 +1,103 @@ +// rustfmt-match_block_trailing_comma: true +// rustfmt-trailing_comma: Always + +fn main() { + match foo { + x => {}, + y => { + foo(); + }, + _ => x, + } +} + +fn f< + S, T, +>( + x: T, + y: S, +) -> T +where + T: P, + S: Q, +{ + x +} + +impl Trait for T +where + T: P, +{ + fn f(x: T) -> T + where + T: Q + R, + { + x + } +} + +struct Pair< + S, T, +> where + T: P, + S: P + Q, +{ + a: T, + b: S, +} + +struct TupPair< + S, T, +>(S, T,) +where + T: P, + S: P + Q; + +enum E< + S, T, +> where + S: P, + T: P, +{ + A { a: T, }, +} + +type Double< + T, +> where + T: P, + T: Q, += Pair< + T, T, +>; + +extern "C" { + fn f< + S, T, + >( + x: T, + y: S, + ) -> T + where + T: P, + S: Q; +} + +trait Q< + S, T, +> where + T: P, + S: R, +{ + fn f< + U, V, + >( + self, + x: T, + y: S, + z: U, + ) -> Self + where + U: P, + V: P; +} diff --git a/rustfmt-core/tests/target/trait.rs b/rustfmt-core/tests/target/trait.rs new file mode 100644 index 00000000000..133e8babedb --- /dev/null +++ b/rustfmt-core/tests/target/trait.rs @@ -0,0 +1,132 @@ +// Test traits + +trait Foo { + fn bar(x: i32) -> Baz { + Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; + + fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + ) -> RetType; // Some comment + + fn baz(&mut self) -> i32; + + fn increment(&mut self, x: i32); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where + R: Read; +} + +pub trait WriteMessage { + fn write_message(&mut self, &FrontendMessage) -> io::Result<()>; +} + +trait Runnable { + fn handler(self: &Runnable); +} + +trait TraitWithExpr { + fn fn_with_expr(x: [i32; 1]); +} + +trait Test { + fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result + where + F: FnOnce(&mut Self) -> Result; +} + +trait T {} + +trait Foo { + type Bar: Baz; + type Inner: Foo = Box; +} + +trait ConstCheck: Foo +where + T: Baz, +{ + const J: i32; +} + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + T: Foo, +{ +} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + T: Foo, +{ +} + +trait FooBar + : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + J: Bar, +{ + fn test(); +} + +trait WhereList +where + T: Foo, + J: Bar, +{ +} + +trait X /* comment */ {} +trait Y // comment +{ +} + +// #2055 +pub trait Foo: +// A and C +A + C +// and B + + B +{} + +// #2158 +trait Foo { + type ItRev = > as UntypedTimeSeries>::IterRev; + type IteRev = + > as UntypedTimeSeries>::IterRev; +} + +// #2331 +trait MyTrait< + AAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBB, + CCCCCCCCCCCCCCCCCCCC, + DDDDDDDDDDDDDDDDDDDD, +> { + fn foo() {} +} + +// Trait aliases +trait FooBar = Foo + Bar; +trait FooBar = Foo + Bar; +trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAA = + BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAA = + BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = + FooBar; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA< + A, + B, + C, + D, + E, +> = FooBar; +#[rustfmt_skip] +trait FooBar = Foo + + Bar; diff --git a/rustfmt-core/tests/target/try-conversion.rs b/rustfmt-core/tests/target/try-conversion.rs new file mode 100644 index 00000000000..e16fba278d2 --- /dev/null +++ b/rustfmt-core/tests/target/try-conversion.rs @@ -0,0 +1,27 @@ +// rustfmt-use_try_shorthand: true + +fn main() { + let x = some_expr()?; + + let y = a.very + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; +} + +fn test() { + a? +} + +fn issue1291() { + fs::create_dir_all(&gitfiledir).chain_err(|| { + format!( + "failed to create the {} submodule directory for the workarea", + name + ) + })?; +} diff --git a/rustfmt-core/tests/target/tuple.rs b/rustfmt-core/tests/target/tuple.rs new file mode 100644 index 00000000000..a22586284dc --- /dev/null +++ b/rustfmt-core/tests/target/tuple.rs @@ -0,0 +1,89 @@ +// Test tuple litterals + +fn foo() { + let a = (a, a, a, a, a); + let aaaaaaaaaaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + ); + let aaaaaaaaaaaaaaaaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa, + ); + let a = (a,); + + let b = ( + // This is a comment + b, // Comment + b, /* Trailing comment */ + ); + + // #1063 + foo(x.0 .0); +} + +fn a() { + (( + aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + ),) +} + +fn b() { + ( + ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + bbbbbbbbbbbbbbbbbb, + ) +} + +fn issue550() { + self.visitor.visit_volume( + self.level.sector_id(sector), + ( + floor_y, + if is_sky_flat(ceil_tex) { + from_wad_height(self.height_range.1) + } else { + ceil_y + }, + ), + ); +} + +fn issue775() { + if indent { + let a = mk_object(&[ + ("a".to_string(), Boolean(true)), + ( + "b".to_string(), + Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]), + ]), + ), + ]); + } +} + +fn issue1725() { + bench_antialiased_lines!( + bench_draw_antialiased_line_segment_diagonal, + (10, 10), + (450, 450) + ); + bench_antialiased_lines!( + bench_draw_antialiased_line_segment_shallow, + (10, 10), + (450, 80) + ); +} diff --git a/rustfmt-core/tests/target/type-ascription.rs b/rustfmt-core/tests/target/type-ascription.rs new file mode 100644 index 00000000000..a2f082ba4b4 --- /dev/null +++ b/rustfmt-core/tests/target/type-ascription.rs @@ -0,0 +1,12 @@ +fn main() { + let xxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + + let xxxxxxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + x: u32 - 1u32 / 10f32: u32 +} diff --git a/rustfmt-core/tests/target/type-punctuation.rs b/rustfmt-core/tests/target/type-punctuation.rs new file mode 100644 index 00000000000..f35293de626 --- /dev/null +++ b/rustfmt-core/tests/target/type-punctuation.rs @@ -0,0 +1,36 @@ +// rustfmt-type_punctuation_density: Compressed + +struct Foo +where + U: Eq+Clone, { + // body +} + +trait Foo<'a, T=usize> +where + T: 'a+Eq+Clone, +{ + type Bar: Eq+Clone; +} + +trait Foo: Eq+Clone { + // body +} + +impl Foo<'a> for Bar +where + for<'a> T: 'a+Eq+Clone, +{ + // body +} + +fn foo<'a, 'b, 'c>() +where + 'a: 'b+'c, +{ + // body +} + +fn Foo+Foo>() { + let i = 6; +} diff --git a/rustfmt-core/tests/target/type.rs b/rustfmt-core/tests/target/type.rs new file mode 100644 index 00000000000..2f35e796512 --- /dev/null +++ b/rustfmt-core/tests/target/type.rs @@ -0,0 +1,31 @@ +// rustfmt-normalize_comments: true +fn types() { + let x: [Vec<_>] = []; + let y: *mut [SomeType; konst_funk()] = expr(); + let z: (/* #digits */ usize, /* exp */ i16) = funk(); + let z: (usize /* #digits */, i16 /* exp */) = funk(); +} + +struct F { + f: extern "C" fn(x: u8, ... /* comment */), + g: extern "C" fn(x: u8, /* comment */ ...), + h: extern "C" fn(x: u8, ...), + i: extern "C" fn( + x: u8, + // comment 4 + y: String, // comment 3 + z: Foo, + // comment + ... // comment 2 + ), +} + +fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} + +fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} + +fn impl_trait_fn_2() -> impl Future {} + +fn issue_1234() { + do_parse!(name: take_while1!(is_token) >> (Header)) +} diff --git a/rustfmt-core/tests/target/type_alias.rs b/rustfmt-core/tests/target/type_alias.rs new file mode 100644 index 00000000000..862f9ecbeec --- /dev/null +++ b/rustfmt-core/tests/target/type_alias.rs @@ -0,0 +1,76 @@ +// rustfmt-normalize_comments: true + +type PrivateTest<'a, I> = ( + Box + 'a>, + Box + 'a>, +); + +pub type PublicTest<'a, I, O> = Result< + Vec, + Box + 'a>, + Box + 'a>, +>; + +pub type LongGenericListTest< + 'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A, + B, + C, +> = Option>; + +pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = + Vec; + +pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = + Vec; + +pub type GenericsFitButNotEqualTest< + 'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A1, + B, + C, +> = Vec; + +pub type CommentTest< + // Lifetime + 'a, + // Type + T, +> = (); + +pub type WithWhereClause +where + T: Clone, + LONGPARAMETERNAME: Clone + Eq + OtherTrait, += Option; + +pub type Exactly100CharstoEqualWhereTest +where + T: Clone + Ord + Eq + SomeOtherTrait, += Option; + +pub type Exactly101CharstoEqualWhereTest +where + T: Clone + Ord + Eq + SomeOtherTrait, += Option; + +type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); + +// #1683 +pub type Between = + super::operators::Between, AsExpr>>; +pub type NotBetween = + super::operators::NotBetween, AsExpr>>; diff --git a/rustfmt-core/tests/target/unindent_if_else_cond_comment.rs b/rustfmt-core/tests/target/unindent_if_else_cond_comment.rs new file mode 100644 index 00000000000..98621b1eed1 --- /dev/null +++ b/rustfmt-core/tests/target/unindent_if_else_cond_comment.rs @@ -0,0 +1,27 @@ +// Comments on else block. See #1575. + +fn example() { + // `if` comment + if x { + foo(); + // `else if` comment + } else if y { + foo(); + // Comment on `else if`. + // Comment on `else if`. + } else if z { + bar(); + /* + * Multi line comment on `else if` + */ + } else if xx { + bar(); + /* Single line comment on `else if` */ + } else if yy { + foo(); + // `else` comment + } else { + foo(); + // Comment at the end of `else` block + }; +} diff --git a/rustfmt-core/tests/target/unions.rs b/rustfmt-core/tests/target/unions.rs new file mode 100644 index 00000000000..eb6c3ae7e15 --- /dev/null +++ b/rustfmt-core/tests/target/unions.rs @@ -0,0 +1,196 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +/// A Doc comment +#[AnAttribute] +pub union Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1029 +pub union Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +union X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub union Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +// With a where clause and generics. +pub union Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +union Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +union Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +union Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +union Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +pub union State time::Timespec> { + now: F, +} + +pub union State ()> { + now: F, +} + +pub union State { + now: F, +} + +union Palette { + /// A map of indices in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +union FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +mod m { + union X + where + T: Sized, + { + a: T, + } +} + +union Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +union Foo {} +union Foo {} +union Foo { + // comment +} +union Foo { + // trailing space -> +} +union Foo { /* comment */ } + +union LongUnion { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +union Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} diff --git a/rustfmt-core/tests/target/where-clause-rfc.rs b/rustfmt-core/tests/target/where-clause-rfc.rs new file mode 100644 index 00000000000..1e83d5b3abc --- /dev/null +++ b/rustfmt-core/tests/target/where-clause-rfc.rs @@ -0,0 +1,128 @@ +// rustfmt-indent_style: Block + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) +where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) +where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape, +) where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape, +) where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, +) -> Option +where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, +) -> Option +where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType +where + F: FnMut(Self::Item) -> bool, +{ +} + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) +where + A: LongTrait; + +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) +where + A: LongTrait1234; + +struct AlwaysOnNextLine +where + A: LongTrait, +{ + x: i32, +} + +pub trait SomeTrait +where + T: Something + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read + + FromStr, +{ +} + +// #2020 +impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { + fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) + where + F: for<'b> FnMut( + &mut ProbeContext<'b, 'gcx, 'tcx>, + ty::PolyTraitRef<'tcx>, + ty::AssociatedItem, + ), + { + // ... + } +} diff --git a/rustfmt-core/tests/target/where-clause.rs b/rustfmt-core/tests/target/where-clause.rs new file mode 100644 index 00000000000..724f3b34bf0 --- /dev/null +++ b/rustfmt-core/tests/target/where-clause.rs @@ -0,0 +1,29 @@ +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType +where + F: FnMut(Self::Item) -> bool, +{ +} + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) +where + A: LongTrait; + +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) +where + A: LongTrait1234; + +struct AlwaysOnNextLine +where + A: LongTrait, +{ + x: i32, +} diff --git a/rustfmt-core/tests/writemode/source/fn-single-line.rs b/rustfmt-core/tests/writemode/source/fn-single-line.rs new file mode 100644 index 00000000000..289dd9aa093 --- /dev/null +++ b/rustfmt-core/tests/writemode/source/fn-single-line.rs @@ -0,0 +1,80 @@ +// rustfmt-fn_single_line: true +// rustfmt-write_mode: checkstyle +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/rustfmt-core/tests/writemode/target/checkstyle.xml b/rustfmt-core/tests/writemode/target/checkstyle.xml new file mode 100644 index 00000000000..30ab5ad7579 --- /dev/null +++ b/rustfmt-core/tests/writemode/target/checkstyle.xml @@ -0,0 +1,2 @@ + + diff --git a/src/chains.rs b/src/chains.rs deleted file mode 100644 index 383e7077d66..00000000000 --- a/src/chains.rs +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Formatting of chained expressions, i.e. expressions which are chained by -//! dots: struct and enum field access, method calls, and try shorthand (?). -//! -//! Instead of walking these subexpressions one-by-one, as is our usual strategy -//! for expression formatting, we collect maximal sequences of these expressions -//! and handle them simultaneously. -//! -//! Whenever possible, the entire chain is put on a single line. If that fails, -//! we put each subexpression on a separate, much like the (default) function -//! argument function argument strategy. -//! -//! Depends on config options: `chain_indent` is the indent to use for -//! blocks in the parent/root/base of the chain (and the rest of the chain's -//! alignment). -//! E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the -//! following values of `chain_indent`: -//! Block: -//! ``` -//! let foo = { -//! aaaa; -//! bbb; -//! ccc -//! }.bar -//! .baz(); -//! ``` -//! Visual: -//! ``` -//! let foo = { -//! aaaa; -//! bbb; -//! ccc -//! } -//! .bar -//! .baz(); -//! ``` -//! -//! If the first item in the chain is a block expression, we align the dots with -//! the braces. -//! Block: -//! ``` -//! let a = foo.bar -//! .baz() -//! .qux -//! ``` -//! Visual: -//! ``` -//! let a = foo.bar -//! .baz() -//! .qux -//! ``` - -use config::IndentStyle; -use expr::rewrite_call; -use macros::convert_try_mac; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, - trimmed_last_line_width, wrap_str}; - -use std::cmp::min; -use std::iter; -use syntax::{ast, ptr}; -use syntax::codemap::Span; - -pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - debug!("rewrite_chain {:?}", shape); - let total_span = expr.span; - let (parent, subexpr_list) = make_subexpr_list(expr, context); - - // Bail out if the chain is just try sugar, i.e., an expression followed by - // any number of `?`s. - if chain_only_try(&subexpr_list) { - return rewrite_try(&parent, subexpr_list.len(), context, shape); - } - let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); - let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); - - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = if is_block_expr(context, &parent, "\n") { - match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape, - } - } else { - shape - }; - let parent_rewrite = parent - .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?; - let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); - let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); - - // Decide how to layout the rest of the chain. `extend` is true if we can - // put the first non-parent item on the same line as the parent. - let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.indent_style() == IndentStyle::Visual || is_small_parent, - ) - } else if is_block_expr(context, &parent, &parent_rewrite) { - match context.config.indent_style() { - // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), - // The parent is a block, so align the rest of the chain with the closing - // brace. - IndentStyle::Visual => (parent_shape, false), - } - } else { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - false, - ) - }; - - let other_child_shape = nested_shape.with_max_width(context.config); - - let first_child_shape = if extend { - let overhead = last_line_width(&parent_rewrite); - let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; - match context.config.indent_style() { - IndentStyle::Visual => parent_shape.offset_left(overhead)?, - IndentStyle::Block => parent_shape.offset_left(offset)?, - } - } else { - other_child_shape - }; - debug!( - "child_shapes {:?} {:?}", - first_child_shape, other_child_shape - ); - - let child_shape_iter = Some(first_child_shape) - .into_iter() - .chain(iter::repeat(other_child_shape)); - let subexpr_num = subexpr_list.len(); - let last_subexpr = &subexpr_list[suffix_try_num]; - let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; - let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); - let mut rewrites = iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) - .collect::>>()?; - - // Total of all items excluding the last. - let extend_last_subexpr = if is_small_parent { - rewrites.len() == 1 && last_line_extendable(&rewrites[0]) - } else { - rewrites.is_empty() && last_line_extendable(&parent_rewrite) - }; - let almost_total = if extend_last_subexpr { - last_line_width(&parent_rewrite) - } else { - rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() - } + suffix_try_num; - let one_line_budget = if rewrites.is_empty() { - shape.width - } else { - min(shape.width, context.config.width_heuristics().chain_width) - }; - let all_in_one_line = !parent_rewrite_contains_newline - && rewrites.iter().all(|s| !s.contains('\n')) - && almost_total < one_line_budget; - let last_shape = if rewrites.is_empty() { - first_child_shape - } else { - other_child_shape - }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; - - // Rewrite the last child. The last child of a chain requires special treatment. We need to - // know whether 'overflowing' the last child make a better formatting: - // - // A chain with overflowing the last child: - // ``` - // parent.child1.child2.last_child( - // a, - // b, - // c, - // ) - // ``` - // - // A chain without overflowing the last child (in vertical layout): - // ``` - // parent - // .child1 - // .child2 - // .last_child(a, b, c) - // ``` - // - // In particular, overflowing is effective when the last child is a method with a multi-lined - // block-like argument (e.g. closure): - // ``` - // parent.child1.child2.last_child(|a, b, c| { - // let x = foo(a, b, c); - // let y = bar(a, b, c); - // - // // ... - // - // result - // }) - // ``` - - // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of - // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); - let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { - // First we try to 'overflow' the last child and see if it looks better than using - // vertical layout. - parent_shape.offset_left(almost_total).map(|shape| { - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { - // We allow overflowing here only if both of the following conditions match: - // 1. The entire chain fits in a single line expect the last child. - // 2. `last_child_str.lines().count() >= 5`. - let line_count = rw.lines().count(); - let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if fits_single_line && line_count >= 5 { - (Some(rw), true) - } else { - // We could not know whether overflowing is better than using vertical layout, - // just by looking at the overflowed rewrite. Now we rewrite the last child - // on its own line, and compare two rewrites to choose which is better. - match rewrite_last() { - Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), - Some(ref new_rw) if new_rw.lines().count() >= line_count => { - (Some(rw), fits_single_line) - } - new_rw @ Some(..) => (new_rw, false), - _ => (Some(rw), fits_single_line), - } - } - } else { - (rewrite_last(), false) - } - })? - } else { - (rewrite_last(), false) - }; - rewrites.push(last_subexpr_str?); - - let connector = if fits_single_line && !parent_rewrite_contains_newline { - // Yay, we can put everything on one line. - String::new() - } else { - // Use new lines. - if context.force_one_line_chain { - return None; - } - format!("\n{}", nested_shape.indent.to_string(context.config)) - }; - - let first_connector = if is_small_parent || fits_single_line - || last_line_extendable(&parent_rewrite) - || context.config.indent_style() == IndentStyle::Visual - { - "" - } else { - connector.as_str() - }; - - let result = if is_small_parent && rewrites.len() > 1 { - let second_connector = if fits_single_line || rewrites[1] == "?" - || last_line_extendable(&rewrites[0]) - || context.config.indent_style() == IndentStyle::Visual - { - "" - } else { - &connector - }; - format!( - "{}{}{}{}{}", - parent_rewrite, - first_connector, - rewrites[0], - second_connector, - join_rewrites(&rewrites[1..], &connector) - ) - } else { - format!( - "{}{}{}", - parent_rewrite, - first_connector, - join_rewrites(&rewrites, &connector) - ) - }; - let result = format!("{}{}", result, repeat_try(suffix_try_num)); - if context.config.indent_style() == IndentStyle::Visual { - wrap_str(result, context.config.max_width(), shape) - } else { - Some(result) - } -} - -// True if the chain is only `?`s. -fn chain_only_try(exprs: &[ast::Expr]) -> bool { - exprs.iter().all(|e| { - if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - } - }) -} - -// Try to rewrite and replace the last non-try child. Return `true` if -// replacing succeeds. -fn repeat_try(try_count: usize) -> String { - iter::repeat("?").take(try_count).collect::() -} - -fn rewrite_try( - expr: &ast::Expr, - try_count: usize, - context: &RewriteContext, - shape: Shape, -) -> Option { - let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; - Some(format!("{}{}", sub_expr, repeat_try(try_count))) -} - -fn join_rewrites(rewrites: &[String], connector: &str) -> String { - let mut rewrite_iter = rewrites.iter(); - let mut result = rewrite_iter.next().unwrap().clone(); - - for rewrite in rewrite_iter { - if rewrite != "?" { - result.push_str(connector); - } - result.push_str(&rewrite[..]); - } - - result -} - -// States whether an expression's last line exclusively consists of closing -// parens, braces, and brackets in its idiomatic formatting. -fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { - match expr.node { - ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { - context.use_block_indent() && repr.contains('\n') - } - ast::ExprKind::Struct(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Match(..) => repr.contains('\n'), - ast::ExprKind::Paren(ref expr) - | ast::ExprKind::Binary(_, _, ref expr) - | ast::ExprKind::Index(_, ref expr) - | ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), - _ => false, - } -} - -// Returns the root of the chain and a Vec of the prefixes of the rest of the chain. -// E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) -fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { - let mut subexpr_list = vec![expr.clone()]; - - while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { - subexpr_list.push(subexpr.clone()); - } - - let parent = subexpr_list.pop().unwrap(); - (parent, subexpr_list) -} - -fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), - } -} - -// Returns the expression's subexpression, if it exists. When the subexpr -// is a try! macro, we'll convert it to shorthand when the option is set. -fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { - match expr.node { - ast::ExprKind::MethodCall(_, ref expressions) => { - Some(convert_try(&expressions[0], context)) - } - ast::ExprKind::TupField(ref subexpr, _) - | ast::ExprKind::Field(ref subexpr, _) - | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), - _ => None, - } -} - -fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { - match expr.node { - ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { - if let Some(subexpr) = convert_try_mac(mac, context) { - subexpr - } else { - expr.clone() - } - } - _ => expr.clone(), - } -} - -// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite -// `.c`. -fn rewrite_chain_subexpr( - expr: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let rewrite_element = |expr_str: String| { - if expr_str.len() <= shape.width { - Some(expr_str) - } else { - None - } - }; - - match expr.node { - ast::ExprKind::MethodCall(ref segment, ref expressions) => { - let types = match segment.parameters { - Some(ref params) => match **params { - ast::PathParameters::AngleBracketed(ref data) => &data.types[..], - _ => &[], - }, - _ => &[], - }; - rewrite_method_call(segment.identifier, types, expressions, span, context, shape) - } - ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), - ast::ExprKind::TupField(ref expr, ref field) => { - let space = match expr.node { - ast::ExprKind::TupField(..) => " ", - _ => "", - }; - rewrite_element(format!("{}.{}", space, field.node)) - } - ast::ExprKind::Try(_) => rewrite_element(String::from("?")), - _ => unreachable!(), - } -} - -// Determines if we can continue formatting a given expression on the same line. -fn is_continuable(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Path(..) => true, - _ => false, - } -} - -fn is_try(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Try(..) => true, - _ => false, - } -} - -fn rewrite_method_call( - method_name: ast::Ident, - types: &[ptr::P], - args: &[ptr::P], - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let (lo, type_str) = if types.is_empty() { - (args[0].span.hi(), String::new()) - } else { - let type_list = types - .iter() - .map(|ty| ty.rewrite(context, shape)) - .collect::>>()?; - - let type_str = - if context.config.spaces_within_parens_and_brackets() && !type_list.is_empty() { - format!("::< {} >", type_list.join(", ")) - } else { - format!("::<{}>", type_list.join(", ")) - }; - - (types.last().unwrap().span.hi(), type_str) - }; - - let callee_str = format!(".{}{}", method_name, type_str); - let span = mk_sp(lo, span.hi()); - - rewrite_call(context, &callee_str, &args[1..], span, shape) -} diff --git a/src/checkstyle.rs b/src/checkstyle.rs deleted file mode 100644 index 7f6e650ad22..00000000000 --- a/src/checkstyle.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io::{self, Write}; -use std::path::Path; - -use config::WriteMode; -use rustfmt_diff::{DiffLine, Mismatch}; - -pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> -where - T: Write, -{ - if mode == WriteMode::Checkstyle { - let mut xml_heading = String::new(); - xml_heading.push_str(""); - xml_heading.push_str("\n"); - xml_heading.push_str(""); - write!(out, "{}", xml_heading)?; - } - Ok(()) -} - -pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> -where - T: Write, -{ - if mode == WriteMode::Checkstyle { - let mut xml_tail = String::new(); - xml_tail.push_str("\n"); - write!(out, "{}", xml_tail)?; - } - Ok(()) -} - -pub fn output_checkstyle_file( - mut writer: T, - filename: &Path, - diff: Vec, -) -> Result<(), io::Error> -where - T: Write, -{ - write!(writer, "", filename.display())?; - for mismatch in diff { - for line in mismatch.lines { - // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. - if let DiffLine::Expected(ref str) = line { - let message = xml_escape_str(str); - write!( - writer, - "", - mismatch.line_number, message - )?; - } - } - } - write!(writer, "")?; - Ok(()) -} - -// Convert special characters into XML entities. -// This is needed for checkstyle output. -fn xml_escape_str(string: &str) -> String { - let mut out = String::new(); - for c in string.chars() { - match c { - '<' => out.push_str("<"), - '>' => out.push_str(">"), - '"' => out.push_str("""), - '\'' => out.push_str("'"), - '&' => out.push_str("&"), - _ => out.push(c), - } - } - out -} diff --git a/src/closures.rs b/src/closures.rs deleted file mode 100644 index 61287543da9..00000000000 --- a/src/closures.rs +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::{ast, ptr}; -use syntax::codemap::Span; -use syntax::parse::classify; - -use codemap::SpanUtils; -use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; -use items::{span_hi_for_arg, span_lo_for_arg}; -use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListTactic, Separator, SeparatorPlace, SeparatorTactic}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use utils::{last_line_width, left_most_sub_expr, stmt_expr}; - -// This module is pretty messy because of the rules around closures and blocks: -// FIXME - the below is probably no longer true in full. -// * if there is a return type, then there must be braces, -// * given a closure with braces, whether that is parsed to give an inner block -// or not depends on if there is a return type and if there are statements -// in that block, -// * if the first expression in the body ends with a block (i.e., is a -// statement without needing a semi-colon), then adding or removing braces -// can change whether it is treated as an expression or statement. - -pub fn rewrite_closure( - capture: ast::CaptureBy, - movability: ast::Movability, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - debug!("rewrite_closure {:?}", body); - - let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?; - // 1 = space between `|...|` and body. - let body_shape = shape.offset_left(extra_offset)?; - - if let ast::ExprKind::Block(ref block) = body.node { - // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return Some(format!("{} {{}}", prefix)); - } - - let result = match fn_decl.output { - ast::FunctionRetTy::Default(_) => { - try_rewrite_without_block(body, &prefix, context, shape, body_shape) - } - _ => None, - }; - - result.or_else(|| { - // Either we require a block, or tried without and failed. - rewrite_closure_block(block, &prefix, context, body_shape) - }) - } else { - rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { - // The closure originally had a non-block expression, but we can't fit on - // one line, so we'll insert a block. - rewrite_closure_with_block(body, &prefix, context, body_shape) - }) - } -} - -fn try_rewrite_without_block( - expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, - body_shape: Shape, -) -> Option { - let expr = get_inner_expr(expr, prefix, context); - - if is_block_closure_forced(context, expr) { - rewrite_closure_with_block(expr, prefix, context, shape) - } else { - rewrite_closure_expr(expr, prefix, context, body_shape) - } -} - -fn get_inner_expr<'a>( - expr: &'a ast::Expr, - prefix: &str, - context: &RewriteContext, -) -> &'a ast::Expr { - if let ast::ExprKind::Block(ref block) = expr.node { - if !needs_block(block, prefix, context) { - // block.stmts.len() == 1 - if let Some(expr) = stmt_expr(&block.stmts[0]) { - return get_inner_expr(expr, prefix, context); - } - } - } - - expr -} - -// Figure out if a block is necessary. -fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { - is_unsafe_block(block) || block.stmts.len() > 1 - || block_contains_comment(block, context.codemap) || prefix.contains('\n') -} - -// Rewrite closure with a single expression wrapping its body with block. -fn rewrite_closure_with_block( - body: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - let left_most = left_most_sub_expr(body); - let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most); - if veto_block { - return None; - } - - let block = ast::Block { - stmts: vec![ - ast::Stmt { - id: ast::NodeId::new(0), - node: ast::StmtKind::Expr(ptr::P(body.clone())), - span: body.span, - }, - ], - id: ast::NodeId::new(0), - rules: ast::BlockCheckMode::Default, - span: body.span, - recovered: false, - }; - let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; - Some(format!("{} {}", prefix, block)) -} - -// Rewrite closure with a single expression without wrapping its body with block. -fn rewrite_closure_expr( - expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - fn allow_multi_line(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Match(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Catch(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::Struct(..) => true, - - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), - - _ => false, - } - } - - // When rewriting closure's body without block, we require it to fit in a single line - // unless it is a block-like expression or we are inside macro call. - let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro) - || context.config.force_multiline_blocks(); - expr.rewrite(context, shape) - .and_then(|rw| { - if veto_multiline && rw.contains('\n') { - None - } else { - Some(rw) - } - }) - .map(|rw| format!("{} {}", prefix, rw)) -} - -// Rewrite closure whose body is block. -fn rewrite_closure_block( - block: &ast::Block, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - Some(format!("{} {}", prefix, block.rewrite(context, shape)?)) -} - -// Return type is (prefix, extra_offset) -fn rewrite_closure_fn_decl( - capture: ast::CaptureBy, - movability: ast::Movability, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option<(String, usize)> { - let mover = if capture == ast::CaptureBy::Value { - "move " - } else { - "" - }; - - let immovable = if movability == ast::Movability::Static { - "static " - } else { - "" - }; - // 4 = "|| {".len(), which is overconservative when the closure consists of - // a single expression. - let nested_shape = shape - .shrink_left(mover.len() + immovable.len())? - .sub_width(4)?; - - // 1 = | - let argument_offset = nested_shape.indent + 1; - let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); - let ret_str = fn_decl.output.rewrite(context, arg_shape)?; - - let arg_items = itemize_list( - context.codemap, - fn_decl.inputs.iter(), - "|", - ",", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(context, arg), - |arg| arg.rewrite(context, arg_shape), - context.codemap.span_after(span, "|"), - body.span.lo(), - false, - ); - let item_vec = arg_items.collect::>(); - // 1 = space between arguments and return type. - let horizontal_budget = nested_shape - .width - .checked_sub(ret_str.len() + 1) - .unwrap_or(0); - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - horizontal_budget, - ); - let arg_shape = match tactic { - DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, - _ => arg_shape, - }; - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arg_shape, - ends_with_newline: false, - preserve_newline: true, - config: context.config, - }; - let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}{}|{}|", immovable, mover, list_str); - - if !ret_str.is_empty() { - if prefix.contains('\n') { - prefix.push('\n'); - prefix.push_str(&argument_offset.to_string(context.config)); - } else { - prefix.push(' '); - } - prefix.push_str(&ret_str); - } - // 1 = space between `|...|` and body. - let extra_offset = last_line_width(&prefix) + 1; - - Some((prefix, extra_offset)) -} - -// Rewriting closure which is placed at the end of the function call's arg. -// Returns `None` if the reformatted closure 'looks bad'. -pub fn rewrite_last_closure( - context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, -) -> Option { - if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { - let body = match body.node { - ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => - { - stmt_expr(&block.stmts[0]).unwrap_or(body) - } - _ => body, - }; - let (prefix, extra_offset) = rewrite_closure_fn_decl( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, - )?; - // If the closure goes multi line before its body, do not overflow the closure. - if prefix.contains('\n') { - return None; - } - - let body_shape = shape.offset_left(extra_offset)?; - - // We force to use block for the body of the closure for certain kinds of expressions. - if is_block_closure_forced(context, body) { - return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( - |body_str| { - // If the expression can fit in a single line, we need not force block closure. - if body_str.lines().count() <= 7 { - match rewrite_closure_expr(body, &prefix, context, shape) { - Some(ref single_line_body_str) - if !single_line_body_str.contains('\n') => - { - Some(single_line_body_str.clone()) - } - _ => Some(body_str), - } - } else { - Some(body_str) - } - }, - ); - } - - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - let is_multi_lined_cond = rewrite_cond(context, body, body_shape) - .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) - .unwrap_or(false); - if is_multi_lined_cond { - return rewrite_closure_with_block(body, &prefix, context, body_shape); - } - - // Seems fine, just format the closure in usual manner. - return expr.rewrite(context, shape); - } - None -} - -/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. -pub fn args_have_many_closure(args: &[&T]) -> bool -where - T: ToExpr, -{ - args.iter() - .filter(|arg| { - arg.to_expr() - .map(|e| match e.node { - ast::ExprKind::Closure(..) => true, - _ => false, - }) - .unwrap_or(false) - }) - .count() > 1 -} - -fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { - // If we are inside macro, we do not want to add or remove block from closure body. - if context.inside_macro { - false - } else { - is_block_closure_forced_inner(expr) - } -} - -fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::ForLoop(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr), - _ => false, - } -} diff --git a/src/codemap.rs b/src/codemap.rs deleted file mode 100644 index d74d24439d9..00000000000 --- a/src/codemap.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This module contains utilities that work with the `CodeMap` from `libsyntax` / `syntex_syntax`. -//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. - -use std::rc::Rc; - -use syntax::codemap::{BytePos, CodeMap, FileMap, FileName, Span}; - -use comment::FindUncommented; - -/// A range of lines in a file, inclusive of both ends. -pub struct LineRange { - pub file: Rc, - pub lo: usize, - pub hi: usize, -} - -impl LineRange { - pub fn file_name(&self) -> &FileName { - &self.file.name - } -} - -pub trait SpanUtils { - fn span_after(&self, original: Span, needle: &str) -> BytePos; - fn span_after_last(&self, original: Span, needle: &str) -> BytePos; - fn span_before(&self, original: Span, needle: &str) -> BytePos; - fn opt_span_after(&self, original: Span, needle: &str) -> Option; -} - -pub trait LineRangeUtils { - /// Returns the `LineRange` that corresponds to `span` in `self`. - /// - /// # Panics - /// - /// Panics if `span` crosses a file boundary, which shouldn't happen. - fn lookup_line_range(&self, span: Span) -> LineRange; -} - -impl SpanUtils for CodeMap { - fn span_after(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).expect("Bad snippet"); - let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len(); - - original.lo() + BytePos(offset as u32) - } - - fn span_after_last(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let mut offset = 0; - - while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { - offset += additional_offset + needle.len(); - } - - original.lo() + BytePos(offset as u32) - } - - fn span_before(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap(); - - original.lo() + BytePos(offset as u32) - } - - fn opt_span_after(&self, original: Span, needle: &str) -> Option { - let snippet = self.span_to_snippet(original).ok()?; - let offset = snippet.find_uncommented(needle)? + needle.len(); - - Some(original.lo() + BytePos(offset as u32)) - } -} - -impl LineRangeUtils for CodeMap { - fn lookup_line_range(&self, span: Span) -> LineRange { - let lo = self.lookup_char_pos(span.lo()); - let hi = self.lookup_char_pos(span.hi()); - - assert_eq!( - lo.file.name, hi.file.name, - "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, hi - ); - - LineRange { - file: lo.file.clone(), - lo: lo.line, - hi: hi.line, - } - } -} diff --git a/src/comment.rs b/src/comment.rs deleted file mode 100644 index 9c0322bcaeb..00000000000 --- a/src/comment.rs +++ /dev/null @@ -1,1234 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Formatting and tools for comments. - -use std::{self, iter}; - -use syntax::codemap::Span; - -use config::Config; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; -use string::{rewrite_string, StringFormat}; -use utils::{count_newlines, first_line_width, last_line_width}; - -fn is_custom_comment(comment: &str) -> bool { - if !comment.starts_with("//") { - false - } else if let Some(c) = comment.chars().nth(2) { - !c.is_alphanumeric() && !c.is_whitespace() - } else { - false - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum CommentStyle<'a> { - DoubleSlash, - TripleSlash, - Doc, - SingleBullet, - DoubleBullet, - Exclamation, - Custom(&'a str), -} - -fn custom_opener(s: &str) -> &str { - s.lines().next().map_or("", |first_line| { - first_line - .find(' ') - .map_or(first_line, |space_index| &first_line[0..space_index + 1]) - }) -} - -impl<'a> CommentStyle<'a> { - pub fn opener(&self) -> &'a str { - match *self { - CommentStyle::DoubleSlash => "// ", - CommentStyle::TripleSlash => "/// ", - CommentStyle::Doc => "//! ", - CommentStyle::SingleBullet => "/* ", - CommentStyle::DoubleBullet => "/** ", - CommentStyle::Exclamation => "/*! ", - CommentStyle::Custom(opener) => opener, - } - } - - pub fn closer(&self) -> &'a str { - match *self { - CommentStyle::DoubleSlash - | CommentStyle::TripleSlash - | CommentStyle::Custom(..) - | CommentStyle::Doc => "", - CommentStyle::DoubleBullet => " **/", - CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", - } - } - - pub fn line_start(&self) -> &'a str { - match *self { - CommentStyle::DoubleSlash => "// ", - CommentStyle::TripleSlash => "/// ", - CommentStyle::Doc => "//! ", - CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", - CommentStyle::DoubleBullet => " ** ", - CommentStyle::Custom(opener) => opener, - } - } - - pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { - (self.opener(), self.closer(), self.line_start()) - } - - pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { - match *self { - CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { - line.trim_left().starts_with(self.line_start().trim_left()) - || comment_style(line, normalize_comments) == *self - } - CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { - line.trim_left().starts_with(self.closer().trim_left()) - || line.trim_left().starts_with(self.line_start().trim_left()) - || comment_style(line, normalize_comments) == *self - } - CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), - } - } -} - -fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { - if !normalize_comments { - if orig.starts_with("/**") && !orig.starts_with("/**/") { - CommentStyle::DoubleBullet - } else if orig.starts_with("/*!") { - CommentStyle::Exclamation - } else if orig.starts_with("/*") { - CommentStyle::SingleBullet - } else if orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/') { - CommentStyle::TripleSlash - } else if orig.starts_with("//!") { - CommentStyle::Doc - } else if is_custom_comment(orig) { - CommentStyle::Custom(custom_opener(orig)) - } else { - CommentStyle::DoubleSlash - } - } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) - || (orig.starts_with("/**") && !orig.starts_with("/**/")) - { - CommentStyle::TripleSlash - } else if orig.starts_with("//!") || orig.starts_with("/*!") { - CommentStyle::Doc - } else if is_custom_comment(orig) { - CommentStyle::Custom(custom_opener(orig)) - } else { - CommentStyle::DoubleSlash - } -} - -/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain -/// comments between two strings. If there are such comments, then that will be -/// recovered. If `allow_extend` is true and there is no comment between the two -/// strings, then they will be put on a single line as long as doing so does not -/// exceed max width. -pub fn combine_strs_with_missing_comments( - context: &RewriteContext, - prev_str: &str, - next_str: &str, - span: Span, - shape: Shape, - allow_extend: bool, -) -> Option { - let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); - let first_sep = if prev_str.is_empty() || next_str.is_empty() { - "" - } else { - " " - }; - let mut one_line_width = - last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); - - let indent_str = shape.indent.to_string(context.config); - let missing_comment = rewrite_missing_comment(span, shape, context)?; - - if missing_comment.is_empty() { - if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { - return Some(format!("{}{}{}", prev_str, first_sep, next_str)); - } else { - let sep = if prev_str.is_empty() { - String::new() - } else { - String::from("\n") + &indent_str - }; - return Some(format!("{}{}{}", prev_str, sep, next_str)); - } - } - - // We have a missing comment between the first expression and the second expression. - - // Peek the the original source code and find out whether there is a newline between the first - // expression and the second expression or the missing comment. We will preserve the original - // layout whenever possible. - let original_snippet = context.snippet(span); - let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { - !original_snippet[..pos].contains('\n') - } else { - !original_snippet.contains('\n') - }; - - one_line_width -= first_sep.len(); - let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { - String::new() - } else { - let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; - if prefer_same_line && one_line_width <= shape.width { - String::from(" ") - } else { - format!("\n{}", indent_str) - } - }; - let second_sep = if missing_comment.is_empty() || next_str.is_empty() { - String::new() - } else if missing_comment.starts_with("//") { - format!("\n{}", indent_str) - } else { - one_line_width += missing_comment.len() + first_sep.len() + 1; - allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); - if prefer_same_line && allow_one_line && one_line_width <= shape.width { - String::from(" ") - } else { - format!("\n{}", indent_str) - } - }; - Some(format!( - "{}{}{}{}{}", - prev_str, first_sep, missing_comment, second_sep, next_str, - )) -} - -pub fn rewrite_comment( - orig: &str, - block_style: bool, - shape: Shape, - config: &Config, -) -> Option { - // If there are lines without a starting sigil, we won't format them correctly - // so in that case we won't even re-align (if !config.normalize_comments()) and - // we should stop now. - let num_bare_lines = orig.lines() - .map(|line| line.trim()) - .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) - .count(); - if num_bare_lines > 0 && !config.normalize_comments() { - return Some(orig.to_owned()); - } - if !config.normalize_comments() && !config.wrap_comments() { - return light_rewrite_comment(orig, shape.indent, config); - } - - identify_comment(orig, block_style, shape, config) -} - -fn identify_comment( - orig: &str, - block_style: bool, - shape: Shape, - config: &Config, -) -> Option { - let style = comment_style(orig, false); - let first_group = orig.lines() - .take_while(|l| style.line_with_same_comment_style(l, false)) - .collect::>() - .join("\n"); - let rest = orig.lines() - .skip(first_group.lines().count()) - .collect::>() - .join("\n"); - - let first_group_str = rewrite_comment_inner(&first_group, block_style, style, shape, config)?; - if rest.is_empty() { - Some(first_group_str) - } else { - identify_comment(&rest, block_style, shape, config).map(|rest_str| { - format!( - "{}\n{}{}", - first_group_str, - shape.indent.to_string(config), - rest_str - ) - }) - } -} - -fn rewrite_comment_inner( - orig: &str, - block_style: bool, - style: CommentStyle, - shape: Shape, - config: &Config, -) -> Option { - let (opener, closer, line_start) = if block_style { - CommentStyle::SingleBullet.to_str_tuplet() - } else { - comment_style(orig, config.normalize_comments()).to_str_tuplet() - }; - - let max_chars = shape - .width - .checked_sub(closer.len() + opener.len()) - .unwrap_or(1); - let indent_str = shape.indent.to_string(config); - let fmt_indent = shape.indent + (opener.len() - line_start.len()); - let mut fmt = StringFormat { - opener: "", - closer: "", - line_start, - line_end: "", - shape: Shape::legacy(max_chars, fmt_indent), - trim_end: true, - config, - }; - - let line_breaks = count_newlines(orig.trim_right()); - let lines = orig.lines() - .enumerate() - .map(|(i, mut line)| { - line = line.trim(); - // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = line[..(line.len() - 2)].trim_right(); - } - - line - }) - .map(|s| left_trim_comment_line(s, &style)) - .map(|(line, has_leading_whitespace)| { - if orig.starts_with("/*") && line_breaks == 0 { - ( - line.trim_left(), - has_leading_whitespace || config.normalize_comments(), - ) - } else { - (line, has_leading_whitespace || config.normalize_comments()) - } - }); - - let mut result = String::with_capacity(orig.len() * 2); - result.push_str(opener); - let mut code_block_buffer = String::with_capacity(128); - let mut is_prev_line_multi_line = false; - let mut inside_code_block = false; - let comment_line_separator = format!("\n{}{}", indent_str, line_start); - let join_code_block_with_comment_line_separator = |s: &str| { - let mut result = String::with_capacity(s.len() + 128); - let mut iter = s.lines().peekable(); - while let Some(line) = iter.next() { - result.push_str(line); - result.push_str(match iter.peek() { - Some(next_line) if next_line.is_empty() => comment_line_separator.trim_right(), - Some(..) => &comment_line_separator, - None => "", - }); - } - result - }; - - for (i, (line, has_leading_whitespace)) in lines.enumerate() { - let is_last = i == count_newlines(orig); - - if inside_code_block { - if line.starts_with("```") { - inside_code_block = false; - result.push_str(&comment_line_separator); - let code_block = ::format_code_block(&code_block_buffer, config) - .unwrap_or_else(|| code_block_buffer.to_owned()); - result.push_str(&join_code_block_with_comment_line_separator(&code_block)); - code_block_buffer.clear(); - result.push_str(&comment_line_separator); - result.push_str(line); - } else { - code_block_buffer.push_str(line); - code_block_buffer.push('\n'); - } - - continue; - } else { - inside_code_block = line.starts_with("```"); - - if result == opener { - let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; - if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - if line.is_empty() { - continue; - } - } else if is_prev_line_multi_line && !line.is_empty() { - result.push(' ') - } else if is_last && !closer.is_empty() && line.is_empty() { - result.push('\n'); - result.push_str(&indent_str); - } else { - result.push_str(&comment_line_separator); - if !has_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - } - } - - if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { - match rewrite_string(line, &fmt, Some(max_chars)) { - Some(ref s) => { - is_prev_line_multi_line = s.contains('\n'); - result.push_str(s); - } - None if is_prev_line_multi_line => { - // We failed to put the current `line` next to the previous `line`. - // Remove the trailing space, then start rewrite on the next line. - result.pop(); - result.push_str(&comment_line_separator); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - match rewrite_string(line, &fmt, Some(max_chars)) { - Some(ref s) => { - is_prev_line_multi_line = s.contains('\n'); - result.push_str(s); - } - None => { - is_prev_line_multi_line = false; - result.push_str(line); - } - } - } - None => { - is_prev_line_multi_line = false; - result.push_str(line); - } - } - - fmt.shape = if is_prev_line_multi_line { - // 1 = " " - let offset = 1 + last_line_width(&result) - line_start.len(); - Shape { - width: max_chars.checked_sub(offset).unwrap_or(0), - indent: fmt_indent, - offset: fmt.shape.offset + offset, - } - } else { - Shape::legacy(max_chars, fmt_indent) - }; - } else { - if line.is_empty() && result.ends_with(' ') && !is_last { - // Remove space if this is an empty comment or a doc comment. - result.pop(); - } - result.push_str(line); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - is_prev_line_multi_line = false; - } - } - - result.push_str(closer); - if result == opener && result.ends_with(' ') { - // Trailing space. - result.pop(); - } - - Some(result) -} - -/// Returns true if the given string MAY include URLs or alike. -fn has_url(s: &str) -> bool { - // This function may return false positive, but should get its job done in most cases. - s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") -} - -/// Given the span, rewrite the missing comment inside it if available. -/// Note that the given span must only include comments (or leading/trailing whitespaces). -pub fn rewrite_missing_comment( - span: Span, - shape: Shape, - context: &RewriteContext, -) -> Option { - let missing_snippet = context.snippet(span); - let trimmed_snippet = missing_snippet.trim(); - if !trimmed_snippet.is_empty() { - rewrite_comment(trimmed_snippet, false, shape, context.config) - } else { - Some(String::new()) - } -} - -/// Recover the missing comments in the specified span, if available. -/// The layout of the comments will be preserved as long as it does not break the code -/// and its total width does not exceed the max width. -pub fn recover_missing_comment_in_span( - span: Span, - shape: Shape, - context: &RewriteContext, - used_width: usize, -) -> Option { - let missing_comment = rewrite_missing_comment(span, shape, context)?; - if missing_comment.is_empty() { - Some(String::new()) - } else { - let missing_snippet = context.snippet(span); - let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); - // 1 = ` ` - let total_width = missing_comment.len() + used_width + 1; - let force_new_line_before_comment = - missing_snippet[..pos].contains('\n') || total_width > context.config.max_width(); - let sep = if force_new_line_before_comment { - format!("\n{}", shape.indent.to_string(context.config)) - } else { - String::from(" ") - }; - Some(format!("{}{}", sep, missing_comment)) - } -} - -/// Trims whitespace and aligns to indent, but otherwise does not change comments. -fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option { - let lines: Vec<&str> = orig.lines() - .map(|l| { - // This is basically just l.trim(), but in the case that a line starts - // with `*` we want to leave one space before it, so it aligns with the - // `*` in `/*`. - let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); - if let Some(fnw) = first_non_whitespace { - if l.as_bytes()[fnw] == b'*' && fnw > 0 { - &l[fnw - 1..] - } else { - &l[fnw..] - } - } else { - "" - }.trim_right() - }) - .collect(); - Some(lines.join(&format!("\n{}", offset.to_string(config)))) -} - -/// Trims comment characters and possibly a single space from the left of a string. -/// Does not trim all whitespace. If a single space is trimmed from the left of the string, -/// this function returns true. -fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { - if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") - || line.starts_with("/** ") - { - (&line[4..], true) - } else if let CommentStyle::Custom(opener) = *style { - if line.starts_with(opener) { - (&line[opener.len()..], true) - } else { - (&line[opener.trim_right().len()..], false) - } - } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") - || line.starts_with("///") || line.starts_with("** ") - || line.starts_with("/*!") - || (line.starts_with("/**") && !line.starts_with("/**/")) - { - (&line[3..], line.chars().nth(2).unwrap() == ' ') - } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") - || line.starts_with("**") - { - (&line[2..], line.chars().nth(1).unwrap() == ' ') - } else if line.starts_with('*') { - (&line[1..], false) - } else { - (line, line.starts_with(' ')) - } -} - -pub trait FindUncommented { - fn find_uncommented(&self, pat: &str) -> Option; -} - -impl FindUncommented for str { - fn find_uncommented(&self, pat: &str) -> Option { - let mut needle_iter = pat.chars(); - for (kind, (i, b)) in CharClasses::new(self.char_indices()) { - match needle_iter.next() { - None => { - return Some(i - pat.len()); - } - Some(c) => match kind { - FullCodeCharKind::Normal | FullCodeCharKind::InString if b == c => {} - _ => { - needle_iter = pat.chars(); - } - }, - } - } - - // Handle case where the pattern is a suffix of the search string - match needle_iter.next() { - Some(_) => None, - None => Some(self.len() - pat.len()), - } - } -} - -// Returns the first byte position after the first comment. The given string -// is expected to be prefixed by a comment, including delimiters. -// Good: "/* /* inner */ outer */ code();" -// Bad: "code(); // hello\n world!" -pub fn find_comment_end(s: &str) -> Option { - let mut iter = CharClasses::new(s.char_indices()); - for (kind, (i, _c)) in &mut iter { - if kind == FullCodeCharKind::Normal || kind == FullCodeCharKind::InString { - return Some(i); - } - } - - // Handle case where the comment ends at the end of s. - if iter.status == CharClassesStatus::Normal { - Some(s.len()) - } else { - None - } -} - -/// Returns true if text contains any comment. -pub fn contains_comment(text: &str) -> bool { - CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) -} - -/// Remove trailing spaces from the specified snippet. We do not remove spaces -/// inside strings or comments. -pub fn remove_trailing_white_spaces(text: &str) -> String { - let mut buffer = String::with_capacity(text.len()); - let mut space_buffer = String::with_capacity(128); - for (char_kind, c) in CharClasses::new(text.chars()) { - match c { - '\n' => { - if char_kind == FullCodeCharKind::InString { - buffer.push_str(&space_buffer); - } - space_buffer.clear(); - buffer.push('\n'); - } - _ if c.is_whitespace() => { - space_buffer.push(c); - } - _ => { - if !space_buffer.is_empty() { - buffer.push_str(&space_buffer); - space_buffer.clear(); - } - buffer.push(c); - } - } - } - buffer -} - -pub struct CharClasses -where - T: Iterator, - T::Item: RichChar, -{ - base: iter::Peekable, - status: CharClassesStatus, -} - -pub trait RichChar { - fn get_char(&self) -> char; -} - -impl RichChar for char { - fn get_char(&self) -> char { - *self - } -} - -impl RichChar for (usize, char) { - fn get_char(&self) -> char { - self.1 - } -} - -impl RichChar for (char, usize) { - fn get_char(&self) -> char { - self.0 - } -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -enum CharClassesStatus { - Normal, - LitString, - LitStringEscape, - LitChar, - LitCharEscape, - // The u32 is the nesting deepness of the comment - BlockComment(u32), - // Status when the '/' has been consumed, but not yet the '*', deepness is - // the new deepness (after the comment opening). - BlockCommentOpening(u32), - // Status when the '*' has been consumed, but not yet the '/', deepness is - // the new deepness (after the comment closing). - BlockCommentClosing(u32), - LineComment, -} - -/// Distinguish between functional part of code and comments -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum CodeCharKind { - Normal, - Comment, -} - -/// Distinguish between functional part of code and comments, -/// describing opening and closing of comments for ease when chunking -/// code from tagged characters -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum FullCodeCharKind { - Normal, - /// The first character of a comment, there is only one for a comment (always '/') - StartComment, - /// Any character inside a comment including the second character of comment - /// marks ("//", "/*") - InComment, - /// Last character of a comment, '\n' for a line comment, '/' for a block comment. - EndComment, - /// Inside a string. - InString, -} - -impl FullCodeCharKind { - pub fn is_comment(&self) -> bool { - match *self { - FullCodeCharKind::StartComment - | FullCodeCharKind::InComment - | FullCodeCharKind::EndComment => true, - _ => false, - } - } - - pub fn is_string(&self) -> bool { - *self == FullCodeCharKind::InString - } - - fn to_codecharkind(&self) -> CodeCharKind { - if self.is_comment() { - CodeCharKind::Comment - } else { - CodeCharKind::Normal - } - } -} - -impl CharClasses -where - T: Iterator, - T::Item: RichChar, -{ - pub fn new(base: T) -> CharClasses { - CharClasses { - base: base.peekable(), - status: CharClassesStatus::Normal, - } - } -} - -impl Iterator for CharClasses -where - T: Iterator, - T::Item: RichChar, -{ - type Item = (FullCodeCharKind, T::Item); - - fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { - let item = self.base.next()?; - let chr = item.get_char(); - let mut char_kind = FullCodeCharKind::Normal; - self.status = match self.status { - CharClassesStatus::LitString => match chr { - '"' => CharClassesStatus::Normal, - '\\' => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitStringEscape - } - _ => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } - }, - CharClassesStatus::LitStringEscape => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } - CharClassesStatus::LitChar => match chr { - '\\' => CharClassesStatus::LitCharEscape, - '\'' => CharClassesStatus::Normal, - _ => CharClassesStatus::LitChar, - }, - CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, - CharClassesStatus::Normal => match chr { - '"' => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } - '\'' => CharClassesStatus::LitChar, - '/' => match self.base.peek() { - Some(next) if next.get_char() == '*' => { - self.status = CharClassesStatus::BlockCommentOpening(1); - return Some((FullCodeCharKind::StartComment, item)); - } - Some(next) if next.get_char() == '/' => { - self.status = CharClassesStatus::LineComment; - return Some((FullCodeCharKind::StartComment, item)); - } - _ => CharClassesStatus::Normal, - }, - _ => CharClassesStatus::Normal, - }, - CharClassesStatus::BlockComment(deepness) => { - assert_ne!(deepness, 0); - self.status = match self.base.peek() { - Some(next) if next.get_char() == '/' && chr == '*' => { - CharClassesStatus::BlockCommentClosing(deepness - 1) - } - Some(next) if next.get_char() == '*' && chr == '/' => { - CharClassesStatus::BlockCommentOpening(deepness + 1) - } - _ => CharClassesStatus::BlockComment(deepness), - }; - return Some((FullCodeCharKind::InComment, item)); - } - CharClassesStatus::BlockCommentOpening(deepness) => { - assert_eq!(chr, '*'); - self.status = CharClassesStatus::BlockComment(deepness); - return Some((FullCodeCharKind::InComment, item)); - } - CharClassesStatus::BlockCommentClosing(deepness) => { - assert_eq!(chr, '/'); - if deepness == 0 { - self.status = CharClassesStatus::Normal; - return Some((FullCodeCharKind::EndComment, item)); - } else { - self.status = CharClassesStatus::BlockComment(deepness); - return Some((FullCodeCharKind::InComment, item)); - } - } - CharClassesStatus::LineComment => match chr { - '\n' => { - self.status = CharClassesStatus::Normal; - return Some((FullCodeCharKind::EndComment, item)); - } - _ => { - self.status = CharClassesStatus::LineComment; - return Some((FullCodeCharKind::InComment, item)); - } - }, - }; - Some((char_kind, item)) - } -} - -/// Iterator over functional and commented parts of a string. Any part of a string is either -/// functional code, either *one* block comment, either *one* line comment. Whitespace between -/// comments is functional code. Line comments contain their ending newlines. -struct UngroupedCommentCodeSlices<'a> { - slice: &'a str, - iter: iter::Peekable>>, -} - -impl<'a> UngroupedCommentCodeSlices<'a> { - fn new(code: &'a str) -> UngroupedCommentCodeSlices<'a> { - UngroupedCommentCodeSlices { - slice: code, - iter: CharClasses::new(code.char_indices()).peekable(), - } - } -} - -impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { - type Item = (CodeCharKind, usize, &'a str); - - fn next(&mut self) -> Option { - let (kind, (start_idx, _)) = self.iter.next()?; - match kind { - FullCodeCharKind::Normal | FullCodeCharKind::InString => { - // Consume all the Normal code - while let Some(&(char_kind, _)) = self.iter.peek() { - if char_kind.is_comment() { - break; - } - let _ = self.iter.next(); - } - } - FullCodeCharKind::StartComment => { - // Consume the whole comment - while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {} - } - _ => panic!(), - } - let slice = match self.iter.peek() { - Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx], - None => &self.slice[start_idx..], - }; - Some(( - if kind.is_comment() { - CodeCharKind::Comment - } else { - CodeCharKind::Normal - }, - start_idx, - slice, - )) - } -} - -/// Iterator over an alternating sequence of functional and commented parts of -/// a string. The first item is always a, possibly zero length, subslice of -/// functional text. Line style comments contain their ending newlines. -pub struct CommentCodeSlices<'a> { - slice: &'a str, - last_slice_kind: CodeCharKind, - last_slice_end: usize, -} - -impl<'a> CommentCodeSlices<'a> { - pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { - CommentCodeSlices { - slice, - last_slice_kind: CodeCharKind::Comment, - last_slice_end: 0, - } - } -} - -impl<'a> Iterator for CommentCodeSlices<'a> { - type Item = (CodeCharKind, usize, &'a str); - - fn next(&mut self) -> Option { - if self.last_slice_end == self.slice.len() { - return None; - } - - let mut sub_slice_end = self.last_slice_end; - let mut first_whitespace = None; - let subslice = &self.slice[self.last_slice_end..]; - let mut iter = CharClasses::new(subslice.char_indices()); - - for (kind, (i, c)) in &mut iter { - let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal - && &subslice[..2] == "//" - && [' ', '\t'].contains(&c); - - if is_comment_connector && first_whitespace.is_none() { - first_whitespace = Some(i); - } - - if kind.to_codecharkind() == self.last_slice_kind && !is_comment_connector { - let last_index = match first_whitespace { - Some(j) => j, - None => i, - }; - sub_slice_end = self.last_slice_end + last_index; - break; - } - - if !is_comment_connector { - first_whitespace = None; - } - } - - if let (None, true) = (iter.next(), sub_slice_end == self.last_slice_end) { - // This was the last subslice. - sub_slice_end = match first_whitespace { - Some(i) => self.last_slice_end + i, - None => self.slice.len(), - }; - } - - let kind = match self.last_slice_kind { - CodeCharKind::Comment => CodeCharKind::Normal, - CodeCharKind::Normal => CodeCharKind::Comment, - }; - let res = ( - kind, - self.last_slice_end, - &self.slice[self.last_slice_end..sub_slice_end], - ); - self.last_slice_end = sub_slice_end; - self.last_slice_kind = kind; - - Some(res) - } -} - -/// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text -/// (if it fits in the width/offset, else return None), else return `new` -pub fn recover_comment_removed( - new: String, - span: Span, - context: &RewriteContext, -) -> Option { - let snippet = context.snippet(span); - if snippet != new && changed_comment_content(snippet, &new) { - // We missed some comments. Keep the original text. - Some(snippet.to_owned()) - } else { - Some(new) - } -} - -/// Return true if the two strings of code have the same payload of comments. -/// The payload of comments is everything in the string except: -/// - actual code (not comments) -/// - comment start/end marks -/// - whitespace -/// - '*' at the beginning of lines in block comments -fn changed_comment_content(orig: &str, new: &str) -> bool { - // Cannot write this as a fn since we cannot return types containing closures - let code_comment_content = |code| { - let slices = UngroupedCommentCodeSlices::new(code); - slices - .filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) - .flat_map(|(_, _, s)| CommentReducer::new(s)) - }; - let res = code_comment_content(orig).ne(code_comment_content(new)); - debug!( - "comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", - res, - orig, - new, - code_comment_content(orig).collect::(), - code_comment_content(new).collect::() - ); - res -} - -/// Iterator over the 'payload' characters of a comment. -/// It skips whitespace, comment start/end marks, and '*' at the beginning of lines. -/// The comment must be one comment, ie not more than one start mark (no multiple line comments, -/// for example). -struct CommentReducer<'a> { - is_block: bool, - at_start_line: bool, - iter: std::str::Chars<'a>, -} - -impl<'a> CommentReducer<'a> { - fn new(comment: &'a str) -> CommentReducer<'a> { - let is_block = comment.starts_with("/*"); - let comment = remove_comment_header(comment); - CommentReducer { - is_block, - at_start_line: false, // There are no supplementary '*' on the first line - iter: comment.chars(), - } - } -} - -impl<'a> Iterator for CommentReducer<'a> { - type Item = char; - fn next(&mut self) -> Option { - loop { - let mut c = self.iter.next()?; - if self.is_block && self.at_start_line { - while c.is_whitespace() { - c = self.iter.next()?; - } - // Ignore leading '*' - if c == '*' { - c = self.iter.next()?; - } - } else if c == '\n' { - self.at_start_line = true; - } - if !c.is_whitespace() { - return Some(c); - } - } - } -} - -fn remove_comment_header(comment: &str) -> &str { - if comment.starts_with("///") || comment.starts_with("//!") { - &comment[3..] - } else if comment.starts_with("//") { - &comment[2..] - } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) - || comment.starts_with("/*!") - { - &comment[3..comment.len() - 2] - } else { - assert!( - comment.starts_with("/*"), - format!("string '{}' is not a comment", comment) - ); - &comment[2..comment.len() - 2] - } -} - -#[cfg(test)] -mod test { - use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, - FindUncommented, FullCodeCharKind}; - use shape::{Indent, Shape}; - - #[test] - fn char_classes() { - let mut iter = CharClasses::new("//\n\n".chars()); - - assert_eq!((FullCodeCharKind::StartComment, '/'), iter.next().unwrap()); - assert_eq!((FullCodeCharKind::InComment, '/'), iter.next().unwrap()); - assert_eq!((FullCodeCharKind::EndComment, '\n'), iter.next().unwrap()); - assert_eq!((FullCodeCharKind::Normal, '\n'), iter.next().unwrap()); - assert_eq!(None, iter.next()); - } - - #[test] - fn comment_code_slices() { - let input = "code(); /* test */ 1 + 1"; - let mut iter = CommentCodeSlices::new(input); - - assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); - assert_eq!( - (CodeCharKind::Comment, 8, "/* test */"), - iter.next().unwrap() - ); - assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap()); - assert_eq!(None, iter.next()); - } - - #[test] - fn comment_code_slices_two() { - let input = "// comment\n test();"; - let mut iter = CommentCodeSlices::new(input); - - assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap()); - assert_eq!( - (CodeCharKind::Comment, 0, "// comment\n"), - iter.next().unwrap() - ); - assert_eq!( - (CodeCharKind::Normal, 11, " test();"), - iter.next().unwrap() - ); - assert_eq!(None, iter.next()); - } - - #[test] - fn comment_code_slices_three() { - let input = "1 // comment\n // comment2\n\n"; - let mut iter = CommentCodeSlices::new(input); - - assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap()); - assert_eq!( - (CodeCharKind::Comment, 2, "// comment\n // comment2\n"), - iter.next().unwrap() - ); - assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap()); - assert_eq!(None, iter.next()); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn format_comments() { - let mut config: ::config::Config = Default::default(); - config.set().wrap_comments(true); - config.set().normalize_comments(true); - - let comment = rewrite_comment(" //test", - true, - Shape::legacy(100, Indent::new(0, 100)), - &config).unwrap(); - assert_eq!("/* test */", comment); - - let comment = rewrite_comment("// comment on a", - false, - Shape::legacy(10, Indent::empty()), - &config).unwrap(); - assert_eq!("// comment\n// on a", comment); - - let comment = rewrite_comment("// A multi line comment\n // between args.", - false, - Shape::legacy(60, Indent::new(0, 12)), - &config).unwrap(); - assert_eq!("// A multi line comment\n // between args.", comment); - - let input = "// comment"; - let expected = - "/* comment */"; - let comment = rewrite_comment(input, - true, - Shape::legacy(9, Indent::new(0, 69)), - &config).unwrap(); - assert_eq!(expected, comment); - - let comment = rewrite_comment("/* trimmed */", - true, - Shape::legacy(100, Indent::new(0, 100)), - &config).unwrap(); - assert_eq!("/* trimmed */", comment); - } - - // This is probably intended to be a non-test fn, but it is not used. I'm - // keeping it around unless it helps us test stuff. - fn uncommented(text: &str) -> String { - CharClasses::new(text.chars()) - .filter_map(|(s, c)| match s { - FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), - _ => None, - }) - .collect() - } - - #[test] - fn test_uncommented() { - assert_eq!(&uncommented("abc/*...*/"), "abc"); - assert_eq!( - &uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), - "..ac\n" - ); - assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); - } - - #[test] - fn test_contains_comment() { - assert_eq!(contains_comment("abc"), false); - assert_eq!(contains_comment("abc // qsdf"), true); - assert_eq!(contains_comment("abc /* kqsdf"), true); - assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); - } - - #[test] - fn test_find_uncommented() { - fn check(haystack: &str, needle: &str, expected: Option) { - assert_eq!(expected, haystack.find_uncommented(needle)); - } - - check("/*/ */test", "test", Some(6)); - check("//test\ntest", "test", Some(7)); - check("/* comment only */", "whatever", None); - check( - "/* comment */ some text /* more commentary */ result", - "result", - Some(46), - ); - check("sup // sup", "p", Some(2)); - check("sup", "x", None); - check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); - check("/*sup yo? \n sup*/ sup", "p", Some(20)); - check("hel/*lohello*/lo", "hello", None); - check("acb", "ab", None); - check(",/*A*/ ", ",", Some(0)); - check("abc", "abc", Some(0)); - check("/* abc */", "abc", None); - check("/**/abc/* */", "abc", Some(4)); - check("\"/* abc */\"", "abc", Some(4)); - check("\"/* abc", "abc", Some(4)); - } -} diff --git a/src/expr.rs b/src/expr.rs deleted file mode 100644 index fb873ee26d3..00000000000 --- a/src/expr.rs +++ /dev/null @@ -1,2930 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; -use std::cmp::min; -use std::iter::repeat; - -use syntax::{ast, ptr}; -use syntax::codemap::{BytePos, CodeMap, Span}; - -use chains::rewrite_chain; -use closures; -use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, FindUncommented}; -use config::{Config, ControlBraceStyle, IndentStyle}; -use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, - struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; -use macros::{rewrite_macro, MacroArg, MacroPosition}; -use patterns::{can_be_overflowed_pat, TuplePatField}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use string::{rewrite_string, StringFormat}; -use types::{can_be_overflowed_type, rewrite_path, PathContext}; -use utils::{colon_spaces, contains_skip, count_newlines, extra_offset, first_line_width, - inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, - paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, - wrap_str}; -use vertical::rewrite_with_alignment; -use visitor::FmtVisitor; - -impl Rewrite for ast::Expr { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - format_expr(self, ExprType::SubExpression, context, shape) - } -} - -#[derive(Copy, Clone, PartialEq)] -pub enum ExprType { - Statement, - SubExpression, -} - -pub fn format_expr( - expr: &ast::Expr, - expr_type: ExprType, - context: &RewriteContext, - shape: Shape, -) -> Option { - skip_out_of_file_lines_range!(context, expr.span); - - if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span()).to_owned()); - } - - let expr_rw = match expr.node { - ast::ExprKind::Array(ref expr_vec) => rewrite_array( - &ptr_vec_to_ref_vec(expr_vec), - mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi()), - context, - shape, - false, - ), - ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), - ast::ExprKind::Call(ref callee, ref args) => { - let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); - let callee_str = callee.rewrite(context, shape)?; - rewrite_call(context, &callee_str, args, inner_span, shape) - } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), - ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { - // FIXME: format comments between operands and operator - rewrite_pair( - &**lhs, - &**rhs, - PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), - context, - shape, - context.config.binop_separator(), - ) - } - ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( - context, - path, - fields, - base.as_ref().map(|e| &**e), - expr.span, - shape, - ), - ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) - } - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) - .and_then(|control_flow| control_flow.rewrite(context, shape)), - ast::ExprKind::Block(ref block) => { - match expr_type { - ExprType::Statement => { - if is_unsafe_block(block) { - block.rewrite(context, shape) - } else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { - // Rewrite block without trying to put it in a single line. - rw - } else { - let prefix = block_prefix(context, block, shape)?; - rewrite_block_with_visitor(context, &prefix, block, shape, true) - } - } - ExprType::SubExpression => block.rewrite(context, shape), - } - } - ast::ExprKind::Match(ref cond, ref arms) => { - rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs) - } - ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) - } - ast::ExprKind::Assign(ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, None, shape) - } - ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), shape) - } - ast::ExprKind::Continue(ref opt_label) => { - let id_str = match *opt_label { - Some(label) => format!(" {}", label.ident), - None => String::new(), - }; - Some(format!("continue{}", id_str)) - } - ast::ExprKind::Break(ref opt_label, ref opt_expr) => { - let id_str = match *opt_label { - Some(label) => format!(" {}", label.ident), - None => String::new(), - }; - - if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) - } else { - Some(format!("break{}", id_str)) - } - } - ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape) - } else { - Some("yield".to_string()) - }, - ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { - closures::rewrite_closure( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, - ) - } - ast::ExprKind::Try(..) - | ast::ExprKind::Field(..) - | ast::ExprKind::TupField(..) - | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), - ast::ExprKind::Mac(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - }) - } - ast::ExprKind::Ret(None) => Some("return".to_owned()), - ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, shape) - } - ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), - ast::ExprKind::AddrOf(mutability, ref expr) => { - rewrite_expr_addrof(context, mutability, expr, shape) - } - ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( - &**expr, - &**ty, - PairParts::new("", " as ", ""), - context, - shape, - SeparatorPlace::Front, - ), - ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( - &**expr, - &**ty, - PairParts::new("", ": ", ""), - context, - shape, - SeparatorPlace::Back, - ), - ast::ExprKind::Index(ref expr, ref index) => { - rewrite_index(&**expr, &**index, context, shape) - } - ast::ExprKind::Repeat(ref expr, ref repeats) => { - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - rewrite_pair( - &**expr, - &**repeats, - PairParts::new(lbr, "; ", rbr), - context, - shape, - SeparatorPlace::Back, - ) - } - ast::ExprKind::Range(ref lhs, ref rhs, limits) => { - let delim = match limits { - ast::RangeLimits::HalfOpen => "..", - ast::RangeLimits::Closed => "..=", - }; - - fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { - match lhs.node { - ast::ExprKind::Lit(ref lit) => match lit.node { - ast::LitKind::FloatUnsuffixed(..) => { - context.snippet(lit.span).ends_with('.') - } - _ => false, - }, - _ => false, - } - } - - match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { - (Some(lhs), Some(rhs)) => { - let sp_delim = if context.config.spaces_around_ranges() { - format!(" {} ", delim) - } else if needs_space_before_range(context, lhs) { - format!(" {}", delim) - } else { - delim.to_owned() - }; - rewrite_pair( - &*lhs, - &*rhs, - PairParts::new("", &sp_delim, ""), - context, - shape, - context.config.binop_separator(), - ) - } - (None, Some(rhs)) => { - let sp_delim = if context.config.spaces_around_ranges() { - format!("{} ", delim) - } else { - delim.to_owned() - }; - rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) - } - (Some(lhs), None) => { - let sp_delim = if context.config.spaces_around_ranges() { - format!(" {}", delim) - } else { - delim.to_owned() - }; - rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) - } - (None, None) => Some(delim.to_owned()), - } - } - // We do not format these expressions yet, but they should still - // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - Some(context.snippet(expr.span).to_owned()) - } - ast::ExprKind::Catch(ref block) => { - if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { - rw - } else { - // 9 = `do catch ` - let budget = shape.width.checked_sub(9).unwrap_or(0); - Some(format!( - "{}{}", - "do catch ", - block.rewrite(context, Shape::legacy(budget, shape.indent))? - )) - } - } - }; - - expr_rw - .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) - .and_then(|expr_str| { - let attrs = outer_attributes(&expr.attrs); - let attrs_str = attrs.rewrite(context, shape)?; - let span = mk_sp( - attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), - expr.span.lo(), - ); - combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) - }) -} - -#[derive(new, Clone, Copy)] -pub struct PairParts<'a> { - prefix: &'a str, - infix: &'a str, - suffix: &'a str, -} - -pub fn rewrite_pair( - lhs: &LHS, - rhs: &RHS, - pp: PairParts, - context: &RewriteContext, - shape: Shape, - separator_place: SeparatorPlace, -) -> Option -where - LHS: Rewrite, - RHS: Rewrite, -{ - let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), - SeparatorPlace::Front => shape.used_width(), - }; - let lhs_shape = Shape { - width: context.budget(lhs_overhead), - ..shape - }; - let lhs_result = lhs.rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; - - // Try to the both lhs and rhs on the same line. - let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + pp.infix.len()) - .and_then(|s| s.sub_width(pp.suffix.len())) - .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); - if let Some(ref rhs_result) = rhs_orig_result { - // If the rhs looks like block expression, we allow it to stay on the same line - // with the lhs even if it is multi-lined. - let allow_same_line = rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); - if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) + pp.infix.len() - + first_line_width(rhs_result) + pp.suffix.len(); - if one_line_width <= shape.width { - return Some(format!( - "{}{}{}{}", - lhs_result, pp.infix, rhs_result, pp.suffix - )); - } - } - } - - // We have to use multiple lines. - // Re-evaluate the rhs because we have more space now: - let mut rhs_shape = match context.config.indent_style() { - IndentStyle::Visual => shape - .sub_width(pp.suffix.len() + pp.prefix.len())? - .visual_indent(pp.prefix.len()), - IndentStyle::Block => { - // Try to calculate the initial constraint on the right hand side. - let rhs_overhead = shape.rhs_overhead(context.config); - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead)? - } - }; - let infix = match separator_place { - SeparatorPlace::Back => pp.infix.trim_right(), - SeparatorPlace::Front => pp.infix.trim_left(), - }; - if separator_place == SeparatorPlace::Front { - rhs_shape = rhs_shape.offset_left(infix.len())?; - } - let rhs_result = rhs.rewrite(context, rhs_shape)?; - let indent_str = rhs_shape.indent.to_string(context.config); - let infix_with_sep = match separator_place { - SeparatorPlace::Back => format!("{}\n{}", infix, indent_str), - SeparatorPlace::Front => format!("\n{}{}", indent_str, infix), - }; - Some(format!( - "{}{}{}{}", - lhs_result, infix_with_sep, rhs_result, pp.suffix - )) -} - -pub fn rewrite_array( - exprs: &[&T], - span: Span, - context: &RewriteContext, - shape: Shape, - trailing_comma: bool, -) -> Option { - let bracket_size = if context.config.spaces_within_parens_and_brackets() { - 2 // "[ " - } else { - 1 // "[" - }; - - let nested_shape = match context.config.indent_style() { - IndentStyle::Block => shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1)?, - IndentStyle::Visual => shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2)?, - }; - - let items = itemize_list( - context.codemap, - exprs.iter(), - "]", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - span.lo(), - span.hi(), - false, - ).collect::>(); - - if items.is_empty() { - if context.config.spaces_within_parens_and_brackets() { - return Some("[ ]".to_string()); - } else { - return Some("[]".to_string()); - } - } - - let tactic = array_tactic(context, shape, nested_shape, exprs, &items, bracket_size); - let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro && !exprs.is_empty() { - let ends_with_bracket = context.snippet(span).ends_with(']'); - let bracket_offset = if ends_with_bracket { 1 } else { 0 }; - let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); - let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?; - if &snippet[last_char_index..last_char_index + 1] == "," { - SeparatorTactic::Always - } else { - SeparatorTactic::Never - } - } else if context.config.indent_style() == IndentStyle::Visual { - SeparatorTactic::Never - } else { - SeparatorTactic::Vertical - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline, - preserve_newline: false, - config: context.config, - }; - let list_str = write_list(&items, &fmt)?; - - let result = if context.config.indent_style() == IndentStyle::Visual - || tactic == DefinitiveListTactic::Horizontal - { - if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { - format!("[ {} ]", list_str) - } else { - format!("[{}]", list_str) - } - } else { - format!( - "[\n{}{}\n{}]", - nested_shape.indent.to_string(context.config), - list_str, - shape.block().indent.to_string(context.config) - ) - }; - - Some(result) -} - -fn array_tactic( - context: &RewriteContext, - shape: Shape, - nested_shape: Shape, - exprs: &[&T], - items: &[ListItem], - bracket_size: usize, -) -> DefinitiveListTactic { - let has_long_item = items - .iter() - .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - - match context.config.indent_style() { - IndentStyle::Block => { - let tactic = match shape.width.checked_sub(2 * bracket_size) { - Some(width) => { - let tactic = ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ); - definitive_tactic(items, tactic, Separator::Comma, width) - } - None => DefinitiveListTactic::Vertical, - }; - if tactic == DefinitiveListTactic::Vertical && !has_long_item - && is_every_args_simple(exprs) - { - DefinitiveListTactic::Mixed - } else { - tactic - } - } - IndentStyle::Visual => { - if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic( - items, - ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ), - Separator::Comma, - nested_shape.width, - ) - } else { - DefinitiveListTactic::Mixed - } - } - } -} - -fn nop_block_collapse(block_str: Option, budget: usize) -> Option { - debug!("nop_block_collapse {:?} {}", block_str, budget); - block_str.map(|block_str| { - if block_str.starts_with('{') && budget >= 2 - && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) - { - "{}".to_owned() - } else { - block_str.to_owned() - } - }) -} - -fn rewrite_empty_block( - context: &RewriteContext, - block: &ast::Block, - shape: Shape, -) -> Option { - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 - { - return Some("{}".to_owned()); - } - - // If a block contains only a single-line comment, then leave it on one line. - let user_str = context.snippet(block.span); - let user_str = user_str.trim(); - if user_str.starts_with('{') && user_str.ends_with('}') { - let comment_str = user_str[1..user_str.len() - 1].trim(); - if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") - && comment_str.len() + 4 <= shape.width - { - return Some(format!("{{ {} }}", comment_str)); - } - } - - None -} - -fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> Option { - Some(match block.rules { - ast::BlockCheckMode::Unsafe(..) => { - let snippet = context.snippet(block.span); - let open_pos = snippet.find_uncommented("{")?; - // Extract comment between unsafe and block start. - let trimmed = &snippet[6..open_pos].trim(); - - if !trimmed.is_empty() { - // 9 = "unsafe {".len(), 7 = "unsafe ".len() - let budget = shape.width.checked_sub(9)?; - format!( - "unsafe {} ", - rewrite_comment( - trimmed, - true, - Shape::legacy(budget, shape.indent + 7), - context.config, - )? - ) - } else { - "unsafe ".to_owned() - } - } - ast::BlockCheckMode::Default => String::new(), - }) -} - -fn rewrite_single_line_block( - context: &RewriteContext, - prefix: &str, - block: &ast::Block, - shape: Shape, -) -> Option { - if is_simple_block(block, context.codemap) { - let expr_shape = shape.offset_left(last_line_width(prefix))?; - let expr_str = block.stmts[0].rewrite(context, expr_shape)?; - let result = format!("{}{{ {} }}", prefix, expr_str); - if result.len() <= shape.width && !result.contains('\n') { - return Some(result); - } - } - None -} - -pub fn rewrite_block_with_visitor( - context: &RewriteContext, - prefix: &str, - block: &ast::Block, - shape: Shape, - has_braces: bool, -) -> Option { - if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { - return rw; - } - - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = shape.indent; - visitor.is_if_else_block = context.is_if_else_block; - match block.rules { - ast::BlockCheckMode::Unsafe(..) => { - let snippet = context.snippet(block.span); - let open_pos = snippet.find_uncommented("{")?; - visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) - } - ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), - } - - visitor.visit_block(block, None, has_braces); - Some(format!("{}{}", prefix, visitor.buffer)) -} - -impl Rewrite for ast::Block { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - // shape.width is used only for the single line case: either the empty block `{}`, - // or an unsafe expression `unsafe { e }`. - if let rw @ Some(_) = rewrite_empty_block(context, self, shape) { - return rw; - } - - let prefix = block_prefix(context, self, shape)?; - - let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); - if let Some(ref result_str) = result { - if result_str.lines().count() <= 3 { - if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { - return rw; - } - } - } - - result - } -} - -impl Rewrite for ast::Stmt { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - skip_out_of_file_lines_range!(context, self.span()); - - let result = match self.node { - ast::StmtKind::Local(ref local) => local.rewrite(context, shape), - ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { - let suffix = if semicolon_for_stmt(context, self) { - ";" - } else { - "" - }; - - let shape = shape.sub_width(suffix.len())?; - format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) - } - ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, - }; - result.and_then(|res| recover_comment_removed(res, self.span(), context)) - } -} - -// Rewrite condition if the given expression has one. -pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { - match expr.node { - ast::ExprKind::Match(ref cond, _) => { - // `match `cond` {` - let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, - IndentStyle::Block => shape.offset_left(8)?, - }; - cond.rewrite(context, cond_shape) - } - _ => to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { - let alt_block_sep = - String::from("\n") + &shape.indent.block_only().to_string(context.config); - control_flow - .rewrite_cond(context, shape, &alt_block_sep) - .and_then(|rw| Some(rw.0)) - }), - } -} - -// Abstraction over control flow expressions -#[derive(Debug)] -struct ControlFlow<'a> { - cond: Option<&'a ast::Expr>, - block: &'a ast::Block, - else_block: Option<&'a ast::Expr>, - label: Option, - pat: Option<&'a ast::Pat>, - keyword: &'a str, - matcher: &'a str, - connector: &'a str, - allow_single_line: bool, - // True if this is an `if` expression in an `else if` :-( hacky - nested_if: bool, - span: Span, -} - -fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { - match expr.node { - ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( - cond, - None, - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - )), - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { - Some(ControlFlow::new_if( - cond, - Some(pat), - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - )) - } - ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) - } - ast::ExprKind::Loop(ref block, label) => { - Some(ControlFlow::new_loop(block, label, expr.span)) - } - ast::ExprKind::While(ref cond, ref block, label) => { - Some(ControlFlow::new_while(None, cond, block, label, expr.span)) - } - ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( - ControlFlow::new_while(Some(pat), cond, block, label, expr.span), - ), - _ => None, - } -} - -impl<'a> ControlFlow<'a> { - fn new_if( - cond: &'a ast::Expr, - pat: Option<&'a ast::Pat>, - block: &'a ast::Block, - else_block: Option<&'a ast::Expr>, - allow_single_line: bool, - nested_if: bool, - span: Span, - ) -> ControlFlow<'a> { - ControlFlow { - cond: Some(cond), - block, - else_block, - label: None, - pat, - keyword: "if", - matcher: match pat { - Some(..) => "let", - None => "", - }, - connector: " =", - allow_single_line, - nested_if, - span, - } - } - - fn new_loop(block: &'a ast::Block, label: Option, span: Span) -> ControlFlow<'a> { - ControlFlow { - cond: None, - block, - else_block: None, - label, - pat: None, - keyword: "loop", - matcher: "", - connector: "", - allow_single_line: false, - nested_if: false, - span, - } - } - - fn new_while( - pat: Option<&'a ast::Pat>, - cond: &'a ast::Expr, - block: &'a ast::Block, - label: Option, - span: Span, - ) -> ControlFlow<'a> { - ControlFlow { - cond: Some(cond), - block, - else_block: None, - label, - pat, - keyword: "while", - matcher: match pat { - Some(..) => "let", - None => "", - }, - connector: " =", - allow_single_line: false, - nested_if: false, - span, - } - } - - fn new_for( - pat: &'a ast::Pat, - cond: &'a ast::Expr, - block: &'a ast::Block, - label: Option, - span: Span, - ) -> ControlFlow<'a> { - ControlFlow { - cond: Some(cond), - block, - else_block: None, - label, - pat: Some(pat), - keyword: "for", - matcher: "", - connector: " in", - allow_single_line: false, - nested_if: false, - span, - } - } - - fn rewrite_single_line( - &self, - pat_expr_str: &str, - context: &RewriteContext, - width: usize, - ) -> Option { - assert!(self.allow_single_line); - let else_block = self.else_block?; - let fixed_cost = self.keyword.len() + " { } else { }".len(); - - if let ast::ExprKind::Block(ref else_node) = else_block.node { - if !is_simple_block(self.block, context.codemap) - || !is_simple_block(else_node, context.codemap) - || pat_expr_str.contains('\n') - { - return None; - } - - let new_width = width.checked_sub(pat_expr_str.len() + fixed_cost)?; - let expr = &self.block.stmts[0]; - let if_str = expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; - - let new_width = new_width.checked_sub(if_str.len())?; - let else_expr = &else_node.stmts[0]; - let else_str = else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; - - if if_str.contains('\n') || else_str.contains('\n') { - return None; - } - - let result = format!( - "{} {} {{ {} }} else {{ {} }}", - self.keyword, pat_expr_str, if_str, else_str - ); - - if result.len() <= width { - return Some(result); - } - } - - None - } -} - -impl<'a> ControlFlow<'a> { - fn rewrite_cond( - &self, - context: &RewriteContext, - shape: Shape, - alt_block_sep: &str, - ) -> Option<(String, usize)> { - // Do not take the rhs overhead from the upper expressions into account - // when rewriting pattern. - let new_width = context - .config - .max_width() - .checked_sub(shape.used_width()) - .unwrap_or(0); - let fresh_shape = Shape { - width: new_width, - ..shape - }; - let constr_shape = if self.nested_if { - // We are part of an if-elseif-else chain. Our constraints are tightened. - // 7 = "} else " .len() - fresh_shape.offset_left(7)? - } else { - fresh_shape - }; - - let label_string = rewrite_label(self.label); - // 1 = space after keyword. - let offset = self.keyword.len() + label_string.len() + 1; - - let pat_expr_string = match self.cond { - Some(cond) => rewrite_pat_expr( - context, - self.pat, - cond, - self.matcher, - self.connector, - self.keyword, - constr_shape, - offset, - )?, - None => String::new(), - }; - - let brace_overhead = - if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { - // 2 = ` {` - 2 - } else { - 0 - }; - let one_line_budget = context - .config - .max_width() - .checked_sub(constr_shape.used_width() + offset + brace_overhead) - .unwrap_or(0); - let force_newline_brace = (pat_expr_string.contains('\n') - || pat_expr_string.len() > one_line_budget) - && !last_line_extendable(&pat_expr_string); - - // Try to format if-else on single line. - if self.allow_single_line - && context - .config - .width_heuristics() - .single_line_if_else_max_width > 0 - { - let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); - - if let Some(cond_str) = trial { - if cond_str.len() - <= context - .config - .width_heuristics() - .single_line_if_else_max_width - { - return Some((cond_str, 0)); - } - } - } - - let cond_span = if let Some(cond) = self.cond { - cond.span - } else { - mk_sp(self.block.span.lo(), self.block.span.lo()) - }; - - // `for event in event` - // Do not include label in the span. - let lo = self.label.map_or(self.span.lo(), |label| label.span.hi()); - let between_kwd_cond = mk_sp( - context - .codemap - .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), - self.pat.map_or(cond_span.lo(), |p| { - if self.matcher.is_empty() { - p.span.lo() - } else { - context.codemap.span_before(self.span, self.matcher.trim()) - } - }), - ); - - let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); - - let after_cond_comment = - extract_comment(mk_sp(cond_span.hi(), self.block.span.lo()), context, shape); - - let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { - "" - } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine - || force_newline_brace - { - alt_block_sep - } else { - " " - }; - - let used_width = if pat_expr_string.contains('\n') { - last_line_width(&pat_expr_string) - } else { - // 2 = spaces after keyword and condition. - label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 - }; - - Some(( - format!( - "{}{}{}{}{}", - label_string, - self.keyword, - between_kwd_cond_comment.as_ref().map_or( - if pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { - "" - } else { - " " - }, - |s| &**s, - ), - pat_expr_string, - after_cond_comment.as_ref().map_or(block_sep, |s| &**s) - ), - used_width, - )) - } -} - -impl<'a> Rewrite for ControlFlow<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!("ControlFlow::rewrite {:?} {:?}", self, shape); - - let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); - let (cond_str, used_width) = self.rewrite_cond(context, shape, &alt_block_sep)?; - // If `used_width` is 0, it indicates that whole control flow is written in a single line. - if used_width == 0 { - return Some(cond_str); - } - - let block_width = shape.width.checked_sub(used_width).unwrap_or(0); - // This is used only for the empty block case: `{}`. So, we use 1 if we know - // we should avoid the single line case. - let block_width = if self.else_block.is_some() || self.nested_if { - min(1, block_width) - } else { - block_width - }; - let block_shape = Shape { - width: block_width, - ..shape - }; - let mut block_context = context.clone(); - block_context.is_if_else_block = self.else_block.is_some(); - let block_str = - rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?; - - let mut result = format!("{}{}", cond_str, block_str); - - if let Some(else_block) = self.else_block { - let shape = Shape::indented(shape.indent, context.config); - let mut last_in_chain = false; - let rewrite = match else_block.node { - // If the else expression is another if-else expression, prevent it - // from being formatted on a single line. - // Note how we're passing the original shape, as the - // cost of "else" should not cascade. - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if( - cond, - Some(pat), - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) - } - ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if( - cond, - None, - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) - } - _ => { - last_in_chain = true; - // When rewriting a block, the width is only used for single line - // blocks, passing 1 lets us avoid that. - let else_shape = Shape { - width: min(1, shape.width), - ..shape - }; - format_expr(else_block, ExprType::Statement, context, else_shape) - } - }; - - let between_kwd_else_block = mk_sp( - self.block.span.hi(), - context - .codemap - .span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), - ); - let between_kwd_else_block_comment = - extract_comment(between_kwd_else_block, context, shape); - - let after_else = mk_sp( - context - .codemap - .span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), - else_block.span.lo(), - ); - let after_else_comment = extract_comment(after_else, context, shape); - - let between_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => { - &*alt_block_sep - } - ControlBraceStyle::AlwaysSameLine => " ", - }; - let after_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, - _ => " ", - }; - - result.push_str(&format!( - "{}else{}", - between_kwd_else_block_comment - .as_ref() - .map_or(between_sep, |s| &**s), - after_else_comment.as_ref().map_or(after_sep, |s| &**s), - )); - result.push_str(&rewrite?); - } - - Some(result) - } -} - -fn rewrite_label(opt_label: Option) -> Cow<'static, str> { - match opt_label { - Some(label) => Cow::from(format!("{}: ", label.ident)), - None => Cow::from(""), - } -} - -fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { - match rewrite_missing_comment(span, shape, context) { - Some(ref comment) if !comment.is_empty() => Some(format!( - "\n{indent}{}\n{indent}", - comment, - indent = shape.indent.to_string(context.config) - )), - _ => None, - } -} - -pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { - let snippet = codemap.span_to_snippet(block.span).unwrap(); - contains_comment(&snippet) -} - -// Checks that a block contains no statements, an expression and no comments. -// FIXME: incorrectly returns false when comment is contained completely within -// the expression. -pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { - (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, codemap)) -} - -/// Checks whether a block contains at most one statement or expression, and no comments. -pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.len() <= 1 && !block_contains_comment(block, codemap) -} - -/// Checks whether a block contains no statements, expressions, or comments. -pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.is_empty() && !block_contains_comment(block, codemap) -} - -pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::StmtKind::Expr(..) => true, - _ => false, - } -} - -pub fn is_unsafe_block(block: &ast::Block) -> bool { - if let ast::BlockCheckMode::Unsafe(..) = block.rules { - true - } else { - false - } -} - -// A simple wrapper type against ast::Arm. Used inside write_list(). -struct ArmWrapper<'a> { - pub arm: &'a ast::Arm, - // True if the arm is the last one in match expression. Used to decide on whether we should add - // trailing comma to the match arm when `config.trailing_comma() == Never`. - pub is_last: bool, -} - -impl<'a> ArmWrapper<'a> { - pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> { - ArmWrapper { arm, is_last } - } -} - -impl<'a> Rewrite for ArmWrapper<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) - } -} - -fn rewrite_match( - context: &RewriteContext, - cond: &ast::Expr, - arms: &[ast::Arm], - shape: Shape, - span: Span, - attrs: &[ast::Attribute], -) -> Option { - // Do not take the rhs overhead from the upper expressions into account - // when rewriting match condition. - let cond_shape = Shape { - width: context.budget(shape.used_width()), - ..shape - }; - // 6 = `match ` - let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => cond_shape.shrink_left(6)?, - IndentStyle::Block => cond_shape.offset_left(6)?, - }; - let cond_str = cond.rewrite(context, cond_shape)?; - let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => &alt_block_sep, - _ if last_line_extendable(&cond_str) => " ", - // 2 = ` {` - _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => &alt_block_sep, - _ => " ", - }; - - let nested_indent_str = shape - .indent - .block_indent(context.config) - .to_string(context.config); - // Inner attributes. - let inner_attrs = &inner_attributes(attrs); - let inner_attrs_str = if inner_attrs.is_empty() { - String::new() - } else { - inner_attrs - .rewrite(context, shape) - .map(|s| format!("{}{}\n", nested_indent_str, s))? - }; - - let open_brace_pos = if inner_attrs.is_empty() { - let hi = if arms.is_empty() { - span.hi() - } else { - arms[0].span().lo() - }; - context.codemap.span_after(mk_sp(cond.span.hi(), hi), "{") - } else { - inner_attrs[inner_attrs.len() - 1].span().hi() - }; - - if arms.is_empty() { - let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); - if snippet.trim().is_empty() { - Some(format!("match {} {{}}", cond_str)) - } else { - // Empty match with comments or inner attributes? We are not going to bother, sorry ;) - Some(context.snippet(span).to_owned()) - } - } else { - Some(format!( - "match {}{}{{\n{}{}{}\n{}}}", - cond_str, - block_sep, - inner_attrs_str, - nested_indent_str, - rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, - shape.indent.to_string(context.config), - )) - } -} - -fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { - if is_last && config.trailing_comma() == SeparatorTactic::Never { - "" - } else if config.match_block_trailing_comma() { - "," - } else if let ast::ExprKind::Block(ref block) = body.node { - if let ast::BlockCheckMode::Default = block.rules { - "" - } else { - "," - } - } else { - "," - } -} - -fn rewrite_match_arms( - context: &RewriteContext, - arms: &[ast::Arm], - shape: Shape, - span: Span, - open_brace_pos: BytePos, -) -> Option { - let arm_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - - let arm_len = arms.len(); - let is_last_iter = repeat(false) - .take(arm_len.checked_sub(1).unwrap_or(0)) - .chain(repeat(true)); - let items = itemize_list( - context.codemap, - arms.iter() - .zip(is_last_iter) - .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), - "}", - "|", - |arm| arm.arm.span().lo(), - |arm| arm.arm.span().hi(), - |arm| arm.rewrite(context, arm_shape), - open_brace_pos, - span.hi(), - false, - ); - let arms_vec: Vec<_> = items.collect(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - - write_list(&arms_vec, &fmt) -} - -fn rewrite_match_arm( - context: &RewriteContext, - arm: &ast::Arm, - shape: Shape, - is_last: bool, -) -> Option { - let (missing_span, attrs_str) = if !arm.attrs.is_empty() { - if contains_skip(&arm.attrs) { - let (_, body) = flatten_arm_body(context, &arm.body); - // `arm.span()` does not include trailing comma, add it manually. - return Some(format!( - "{}{}", - context.snippet(arm.span()), - arm_comma(context.config, body, is_last), - )); - } - let missing_span = mk_sp( - arm.attrs[arm.attrs.len() - 1].span.hi(), - arm.pats[0].span.lo(), - ); - (missing_span, arm.attrs.rewrite(context, shape)?) - } else { - (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) - }; - let pats_str = - rewrite_match_pattern(context, &arm.pats, &arm.guard, shape).and_then(|pats_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &pats_str, - missing_span, - shape, - false, - ) - })?; - rewrite_match_body( - context, - &arm.body, - &pats_str, - shape, - arm.guard.is_some(), - is_last, - ) -} - -/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: -/// -/// [small, ntp]: -/// - single token -/// - `&[single-line, ntp]` -/// -/// [small]: -/// - `[small, ntp]` -/// - unary tuple constructor `([small, ntp])` -/// - `&[small]` -fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { - // We also require that the pattern is reasonably 'small' with its literal width. - pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) -} - -fn is_short_pattern_inner(pat: &ast::Pat) -> bool { - match pat.node { - ast::PatKind::Wild | ast::PatKind::Lit(_) => true, - ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), - ast::PatKind::Struct(..) - | ast::PatKind::Mac(..) - | ast::PatKind::Slice(..) - | ast::PatKind::Path(..) - | ast::PatKind::Range(..) => false, - ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, - ast::PatKind::TupleStruct(ref path, ref subpats, _) => { - path.segments.len() <= 1 && subpats.len() <= 1 - } - ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p), - } -} - -fn rewrite_match_pattern( - context: &RewriteContext, - pats: &[ptr::P], - guard: &Option>, - shape: Shape, -) -> Option { - // Patterns - // 5 = ` => {` - let pat_shape = shape.sub_width(5)?; - - let pat_strs = pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>()?; - - let use_mixed_layout = pats.iter() - .zip(pat_strs.iter()) - .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = if use_mixed_layout { - DefinitiveListTactic::Mixed - } else { - definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::VerticalBar, - pat_shape.width, - ) - }; - let fmt = ListFormatting { - tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - separator_place: context.config.binop_separator(), - shape: pat_shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - let pats_str = write_list(&items, &fmt)?; - - // Guard - let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; - - Some(format!("{}{}", pats_str, guard_str)) -} - -// (extend, body) -// @extend: true if the arm body can be put next to `=>` -// @body: flattened body, if the body is block with a single expression -fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { - match body.node { - ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => - { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - ( - !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), - &*expr, - ) - } else { - (false, &*body) - } - } - _ => ( - !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), - &*body, - ), - } -} - -fn rewrite_match_body( - context: &RewriteContext, - body: &ptr::P, - pats_str: &str, - shape: Shape, - has_guard: bool, - is_last: bool, -) -> Option { - let (extend, body) = flatten_arm_body(context, body); - let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { - (true, is_empty_block(block, context.codemap)) - } else { - (false, false) - }; - - let comma = arm_comma(context.config, body, is_last); - let alt_block_sep = String::from("\n") + &shape.indent.to_string(context.config); - let alt_block_sep = alt_block_sep.as_str(); - - let combine_orig_body = |body_str: &str| { - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, - _ => " ", - }; - - Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) - }; - - let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; - let next_line_indent = if !is_block || is_empty_block { - shape.indent.block_indent(context.config) - } else { - shape.indent - }; - let combine_next_line_body = |body_str: &str| { - if is_block { - return Some(format!( - "{} =>\n{}{}", - pats_str, - next_line_indent.to_string(context.config), - body_str - )); - } - - let indent_str = shape.indent.to_string(context.config); - let nested_indent_str = next_line_indent.to_string(context.config); - let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { - let comma = if context.config.match_block_trailing_comma() { - "," - } else { - "" - }; - ("{", format!("\n{}}}{}", indent_str, comma)) - } else { - ("", String::from(",")) - }; - - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => format!("{}{}\n", alt_block_sep, body_prefix), - _ if body_prefix.is_empty() => "\n".to_owned(), - _ if forbid_same_line => format!("{}{}\n", alt_block_sep, body_prefix), - _ => format!(" {}\n", body_prefix), - } + &nested_indent_str; - - Some(format!( - "{} =>{}{}{}", - pats_str, block_sep, body_str, body_suffix - )) - }; - - // Let's try and get the arm body on the same line as the condition. - // 4 = ` => `.len() - let orig_body_shape = shape - .offset_left(extra_offset(pats_str, shape) + 4) - .and_then(|shape| shape.sub_width(comma.len())); - let orig_body = if let Some(body_shape) = orig_body_shape { - let rewrite = nop_block_collapse( - format_expr(body, ExprType::Statement, context, body_shape), - body_shape.width, - ); - - match rewrite { - Some(ref body_str) - if !forbid_same_line - && (is_block - || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => - { - return combine_orig_body(body_str); - } - _ => rewrite, - } - } else { - None - }; - let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); - - // Try putting body on the next line and see if it looks better. - let next_line_body_shape = Shape::indented(next_line_indent, context.config); - let next_line_body = nop_block_collapse( - format_expr(body, ExprType::Statement, context, next_line_body_shape), - next_line_body_shape.width, - ); - match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) - if forbid_same_line || prefer_next_line(orig_str, next_line_str) => - { - combine_next_line_body(next_line_str) - } - (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { - combine_orig_body(orig_str) - } - (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { - combine_next_line_body(next_line_str) - } - (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), - (None, None) => None, - (Some(ref orig_str), _) => combine_orig_body(orig_str), - } -} - -// The `if ...` guard on a match arm. -fn rewrite_guard( - context: &RewriteContext, - guard: &Option>, - shape: Shape, - // The amount of space used up on this line for the pattern in - // the arm (excludes offset). - pattern_width: usize, -) -> Option { - if let Some(ref guard) = *guard { - // First try to fit the guard string on the same line as the pattern. - // 4 = ` if `, 5 = ` => {` - let cond_shape = shape - .offset_left(pattern_width + 4) - .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { - return Some(format!(" if {}", cond_str)); - } - } - } - - // Not enough space to put the guard after the pattern, try a newline. - // 3 = `if `, 5 = ` => {` - let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) - .offset_left(3) - .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - return Some(format!( - "\n{}if {}", - cond_shape.indent.to_string(context.config), - cond_str - )); - } - } - - None - } else { - Some(String::new()) - } -} - -fn rewrite_pat_expr( - context: &RewriteContext, - pat: Option<&ast::Pat>, - expr: &ast::Expr, - matcher: &str, - // Connecting piece between pattern and expression, - // *without* trailing space. - connector: &str, - keyword: &str, - shape: Shape, - offset: usize, -) -> Option { - debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); - let cond_shape = shape.offset_left(offset)?; - if let Some(pat) = pat { - let matcher = if matcher.is_empty() { - matcher.to_owned() - } else { - format!("{} ", matcher) - }; - let pat_shape = cond_shape - .offset_left(matcher.len())? - .sub_width(connector.len())?; - let pat_string = pat.rewrite(context, pat_shape)?; - let result = format!("{}{}{}", matcher, pat_string, connector); - return rewrite_assign_rhs(context, result, expr, cond_shape); - } - - let expr_rw = expr.rewrite(context, cond_shape); - // The expression may (partially) fit on the current line. - // We do not allow splitting between `if` and condition. - if keyword == "if" || expr_rw.is_some() { - return expr_rw; - } - - // The expression won't fit on the current line, jump to next. - let nested_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - let nested_indent_str = nested_shape.indent.to_string(context.config); - expr.rewrite(context, nested_shape) - .map(|expr_rw| format!("\n{}{}", nested_indent_str, expr_rw)) -} - -fn can_extend_match_arm_body(body: &ast::Expr) -> bool { - match body.node { - // We do not allow `if` to stay on the same line, since we could easily mistake - // `pat => if cond { ... }` and `pat if cond => { ... }`. - ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, - ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::Match(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Closure(..) - | ast::ExprKind::Array(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Mac(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::Tup(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), - _ => false, - } -} - -pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { - match l.node { - ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), - _ => wrap_str( - context.snippet(l.span).to_owned(), - context.config.max_width(), - shape, - ), - } -} - -fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { - let string_lit = context.snippet(span); - - if !context.config.format_strings() { - if string_lit - .lines() - .rev() - .skip(1) - .all(|line| line.ends_with('\\')) - { - let new_indent = shape.visual_indent(1).indent; - let indented_string_lit = String::from( - string_lit - .lines() - .map(|line| { - format!( - "{}{}", - new_indent.to_string(context.config), - line.trim_left() - ) - }) - .collect::>() - .join("\n") - .trim_left(), - ); - return wrap_str(indented_string_lit, context.config.max_width(), shape); - } else { - return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); - } - } - - // Remove the quote characters. - let str_lit = &string_lit[1..string_lit.len() - 1]; - - rewrite_string( - str_lit, - &StringFormat::new(shape.visual_indent(0), context.config), - None, - ) -} - -/// A list of `format!`-like macros, that take a long format string and a list of arguments to -/// format. -/// -/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of -/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, -/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). -const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ - // format! like macros - // From the Rust Standard Library. - ("eprint!", 0), - ("eprintln!", 0), - ("format!", 0), - ("format_args!", 0), - ("print!", 0), - ("println!", 0), - ("panic!", 0), - ("unreachable!", 0), - // From the `log` crate. - ("debug!", 0), - ("error!", 0), - ("info!", 0), - ("warn!", 0), - // write! like macros - ("assert!", 1), - ("debug_assert!", 1), - ("write!", 1), - ("writeln!", 1), - // assert_eq! like macros - ("assert_eq!", 2), - ("assert_ne!", 2), - ("debug_assert_eq!", 2), - ("debug_assert_ne!", 2), -]; - -pub fn rewrite_call( - context: &RewriteContext, - callee: &str, - args: &[ptr::P], - span: Span, - shape: Shape, -) -> Option { - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) - } else { - false - }; - rewrite_call_inner( - context, - callee, - &ptr_vec_to_ref_vec(args), - span, - shape, - context.config.width_heuristics().fn_call_width, - force_trailing_comma, - ) -} - -pub fn rewrite_call_inner<'a, T>( - context: &RewriteContext, - callee_str: &str, - args: &[&T], - span: Span, - shape: Shape, - args_max_width: usize, - force_trailing_comma: bool, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - // 2 = `( `, 1 = `(` - let paren_overhead = if context.config.spaces_within_parens_and_brackets() { - 2 - } else { - 1 - }; - let used_width = extra_offset(callee_str, shape); - let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?; - - // 1 = "(" or ")" - let one_line_shape = shape - .offset_left(last_line_width(callee_str) + 1)? - .sub_width(1)?; - let nested_shape = shape_from_indent_style( - context, - shape, - used_width + 2 * paren_overhead, - used_width + paren_overhead, - )?; - - let span_lo = context.codemap.span_after(span, "("); - let args_span = mk_sp(span_lo, span.hi()); - - let (extendable, list_str) = rewrite_call_args( - context, - args, - args_span, - one_line_shape, - nested_shape, - one_line_width, - args_max_width, - force_trailing_comma, - callee_str, - )?; - - if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { - let mut new_context = context.clone(); - new_context.use_block = true; - return rewrite_call_inner( - &new_context, - callee_str, - args, - span, - shape, - args_max_width, - force_trailing_comma, - ); - } - - let args_shape = shape.sub_width(last_line_width(callee_str))?; - Some(format!( - "{}{}", - callee_str, - wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) - )) -} - -fn need_block_indent(s: &str, shape: Shape) -> bool { - s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)) - .map_or(false, |w| w + 1 < shape.indent.width()) - }) -} - -fn rewrite_call_args<'a, T>( - context: &RewriteContext, - args: &[&T], - span: Span, - one_line_shape: Shape, - nested_shape: Shape, - one_line_width: usize, - args_max_width: usize, - force_trailing_comma: bool, - callee_str: &str, -) -> Option<(bool, String)> -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let items = itemize_list( - context.codemap, - args.iter(), - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - span.lo(), - span.hi(), - true, - ); - let mut item_vec: Vec<_> = items.collect(); - - // Try letting the last argument overflow to the next line with block - // indentation. If its first line fits on one line with the other arguments, - // we format the function arguments horizontally. - let tactic = try_overflow_last_arg( - context, - &mut item_vec, - &args[..], - one_line_shape, - nested_shape, - one_line_width, - args_max_width, - callee_str, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if force_trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro || !context.use_block_indent() { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, - preserve_newline: false, - config: context.config, - }; - - write_list(&item_vec, &fmt) - .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str)) -} - -fn try_overflow_last_arg<'a, T>( - context: &RewriteContext, - item_vec: &mut Vec, - args: &[&T], - one_line_shape: Shape, - nested_shape: Shape, - one_line_width: usize, - args_max_width: usize, - callee_str: &str, -) -> DefinitiveListTactic -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - // 1 = "(" - let combine_arg_with_callee = - callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; - let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); - - // Replace the last item with its first line to see if it fits with - // first arguments. - let placeholder = if overflow_last { - let mut context = context.clone(); - if !combine_arg_with_callee { - if let Some(expr) = args[args.len() - 1].to_expr() { - if let ast::ExprKind::MethodCall(..) = expr.node { - context.force_one_line_chain = true; - } - } - } - last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { - rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) - }) - } else { - None - }; - - let mut tactic = definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ); - - // Replace the stub with the full overflowing last argument if the rewrite - // succeeded and its first line fits with the other arguments. - match (overflow_last, tactic, placeholder) { - (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) if args.len() == 1 => { - // When we are rewriting a nested function call, we restrict the - // bugdet for the inner function to avoid them being deeply nested. - // However, when the inner function has a prefix or a suffix - // (e.g. `foo() as u32`), this budget reduction may produce poorly - // formatted code, where a prefix or a suffix being left on its own - // line. Here we explicitlly check those cases. - if count_newlines(overflowed) == 1 { - let rw = args.last() - .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); - let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); - if no_newline { - item_vec[args.len() - 1].item = rw; - } else { - item_vec[args.len() - 1].item = Some(overflowed.to_owned()); - } - } else { - item_vec[args.len() - 1].item = Some(overflowed.to_owned()); - } - } - (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { - item_vec[args.len() - 1].item = placeholder; - } - _ if args.len() >= 1 => { - item_vec[args.len() - 1].item = args.last() - .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); - - let default_tactic = || { - definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ) - }; - - // Use horizontal layout for a function with a single argument as long as - // everything fits in a single line. - if args.len() == 1 - && args_max_width != 0 // Vertical layout is forced. - && !item_vec[0].has_comment() - && !item_vec[0].inner_as_ref().contains('\n') - && ::lists::total_item_width(&item_vec[0]) <= one_line_width - { - tactic = DefinitiveListTactic::Horizontal; - } else { - tactic = default_tactic(); - - if tactic == DefinitiveListTactic::Vertical { - if let Some((all_simple, num_args_before)) = - maybe_get_args_offset(callee_str, args) - { - let one_line = all_simple - && definitive_tactic( - &item_vec[..num_args_before], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ) == DefinitiveListTactic::Horizontal - && definitive_tactic( - &item_vec[num_args_before + 1..], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ) == DefinitiveListTactic::Horizontal; - - if one_line { - tactic = DefinitiveListTactic::SpecialMacro(num_args_before); - }; - } - } - } - } - _ => (), - } - - tactic -} - -fn is_simple_arg(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Lit(..) => true, - ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Cast(ref expr, _) - | ast::ExprKind::Field(ref expr, _) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::TupField(ref expr, _) - | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr), - ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { - is_simple_arg(lhs) && is_simple_arg(rhs) - } - _ => false, - } -} - -fn is_every_args_simple(lists: &[&T]) -> bool { - lists - .iter() - .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) -} - -/// In case special-case style is required, returns an offset from which we start horizontal layout. -fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { - if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST - .iter() - .find(|&&(s, _)| s == callee_str) - { - let all_simple = args.len() > num_args_before && is_every_args_simple(args); - - Some((all_simple, num_args_before)) - } else { - None - } -} - -/// Returns a shape for the last argument which is going to be overflowed. -fn last_arg_shape( - lists: &[&T], - items: &[ListItem], - shape: Shape, - args_max_width: usize, -) -> Option -where - T: Rewrite + Spanned + ToExpr, -{ - let is_nested_call = lists - .iter() - .next() - .and_then(|item| item.to_expr()) - .map_or(false, is_nested_call); - if items.len() == 1 && !is_nested_call { - return Some(shape); - } - let offset = items.iter().rev().skip(1).fold(0, |acc, i| { - // 2 = ", " - acc + 2 + i.inner_as_ref().len() - }); - Shape { - width: min(args_max_width, shape.width), - ..shape - }.offset_left(offset) -} - -fn rewrite_last_arg_with_overflow<'a, T>( - context: &RewriteContext, - args: &[&T], - last_item: &mut ListItem, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let last_arg = args[args.len() - 1]; - let rewrite = if let Some(expr) = last_arg.to_expr() { - match expr.node { - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - ast::ExprKind::Closure(..) => { - // If the argument consists of multiple closures, we do not overflow - // the last closure. - if closures::args_have_many_closure(args) { - None - } else { - closures::rewrite_last_closure(context, expr, shape) - } - } - _ => expr.rewrite(context, shape), - } - } else { - last_arg.rewrite(context, shape) - }; - - if let Some(rewrite) = rewrite { - let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); - last_item.item = rewrite_first_line; - Some(rewrite) - } else { - None - } -} - -fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - args.last() - .map_or(false, |x| x.can_be_overflowed(context, args.len())) -} - -pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { - match expr.node { - ast::ExprKind::Match(..) => { - (context.use_block_indent() && args_len == 1) - || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) - } - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => { - context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 - } - ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { - context.use_block_indent() - || context.config.indent_style() == IndentStyle::Visual && args_len > 1 - } - ast::ExprKind::Array(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::Mac(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), - _ => false, - } -} - -fn is_nested_call(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), - _ => false, - } -} - -pub fn wrap_args_with_parens( - context: &RewriteContext, - args_str: &str, - is_extendable: bool, - shape: Shape, - nested_shape: Shape, -) -> String { - if !context.use_block_indent() - || (context.inside_macro && !args_str.contains('\n') - && args_str.len() + paren_overhead(context) <= shape.width) || is_extendable - { - if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() { - format!("( {} )", args_str) - } else { - format!("({})", args_str) - } - } else { - format!( - "(\n{}{}\n{})", - nested_shape.indent.to_string(context.config), - args_str, - shape.block().indent.to_string(context.config) - ) - } -} - -/// Return true if a function call or a method call represented by the given span ends with a -/// trailing comma. This function is used when rewriting macro, as adding or removing a trailing -/// comma from macro can potentially break the code. -fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { - let mut encountered_closing_paren = false; - for c in context.snippet(span).chars().rev() { - match c { - ',' => return true, - ')' => if encountered_closing_paren { - return false; - } else { - encountered_closing_paren = true; - }, - _ if c.is_whitespace() => continue, - _ => return false, - } - } - false -} - -fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { - debug!("rewrite_paren, shape: {:?}", shape); - let total_paren_overhead = paren_overhead(context); - let paren_overhead = total_paren_overhead / 2; - let sub_shape = shape - .offset_left(paren_overhead) - .and_then(|s| s.sub_width(paren_overhead))?; - - let paren_wrapper = |s: &str| { - if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { - format!("( {} )", s) - } else { - format!("({})", s) - } - }; - - let subexpr_str = subexpr.rewrite(context, sub_shape)?; - debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - - if subexpr_str.contains('\n') - || first_line_width(&subexpr_str) + total_paren_overhead <= shape.width - { - Some(paren_wrapper(&subexpr_str)) - } else { - None - } -} - -fn rewrite_index( - expr: &ast::Expr, - index: &ast::Expr, - context: &RewriteContext, - shape: Shape, -) -> Option { - let expr_str = expr.rewrite(context, shape)?; - - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - - let offset = last_line_width(&expr_str) + lbr.len(); - let rhs_overhead = shape.rhs_overhead(context.config); - let index_shape = if expr_str.contains('\n') { - Shape::legacy(context.config.max_width(), shape.indent) - .offset_left(offset) - .and_then(|shape| shape.sub_width(rbr.len() + rhs_overhead)) - } else { - shape.visual_indent(offset).sub_width(offset + rbr.len()) - }; - let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); - - // Return if index fits in a single line. - match orig_index_rw { - Some(ref index_str) if !index_str.contains('\n') => { - return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); - } - _ => (), - } - - // Try putting index on the next line and see if it fits in a single line. - let indent = shape.indent.block_indent(context.config); - let index_shape = Shape::indented(indent, context.config).offset_left(lbr.len())?; - let index_shape = index_shape.sub_width(rbr.len() + rhs_overhead)?; - let new_index_rw = index.rewrite(context, index_shape); - match (orig_index_rw, new_index_rw) { - (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( - "{}\n{}{}{}{}", - expr_str, - indent.to_string(context.config), - lbr, - new_index_str, - rbr - )), - (None, Some(ref new_index_str)) => Some(format!( - "{}\n{}{}{}{}", - expr_str, - indent.to_string(context.config), - lbr, - new_index_str, - rbr - )), - (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), - _ => None, - } -} - -fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { - if base.is_some() { - return false; - } - - fields.iter().all(|field| !field.is_shorthand) -} - -fn rewrite_struct_lit<'a>( - context: &RewriteContext, - path: &ast::Path, - fields: &'a [ast::Field], - base: Option<&'a ast::Expr>, - span: Span, - shape: Shape, -) -> Option { - debug!("rewrite_struct_lit: shape {:?}", shape); - - enum StructLitField<'a> { - Regular(&'a ast::Field), - Base(&'a ast::Expr), - } - - // 2 = " {".len() - let path_shape = shape.sub_width(2)?; - let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - - if fields.is_empty() && base.is_none() { - return Some(format!("{} {{}}", path_str)); - } - - // Foo { a: Foo } - indent is +3, width is -5. - let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; - - let one_line_width = h_shape.map_or(0, |shape| shape.width); - let body_lo = context.codemap.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, &base) - && context.config.struct_field_align_threshold() > 0 - { - rewrite_with_alignment( - fields, - context, - shape, - mk_sp(body_lo, span.hi()), - one_line_width, - )? - } else { - let field_iter = fields - .into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); - - let span_lo = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span().lo(), - StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - }; - let span_hi = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span().hi(), - StructLitField::Base(expr) => expr.span.hi(), - }; - let rewrite = |item: &StructLitField| match *item { - StructLitField::Regular(field) => { - // The 1 taken from the v_budget is for the comma. - rewrite_field(context, field, v_shape.sub_width(1)?, 0) - } - StructLitField::Base(expr) => { - // 2 = .. - expr.rewrite(context, v_shape.offset_left(2)?) - .map(|s| format!("..{}", s)) - } - }; - - let items = itemize_list( - context.codemap, - field_iter, - "}", - ",", - span_lo, - span_hi, - rewrite, - body_lo, - span.hi(), - false, - ); - let item_vec = items.collect::>(); - - let tactic = struct_lit_tactic(h_shape, context, &item_vec); - let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); - let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); - - write_list(&item_vec, &fmt)? - }; - - let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); - Some(format!("{} {{{}}}", path_str, fields_str)) - - // FIXME if context.config.indent_style() == Visual, but we run out - // of space, we should fall back to BlockIndent. -} - -pub fn wrap_struct_field( - context: &RewriteContext, - fields_str: &str, - shape: Shape, - nested_shape: Shape, - one_line_width: usize, -) -> String { - if context.config.indent_style() == IndentStyle::Block - && (fields_str.contains('\n') || !context.config.struct_lit_single_line() - || fields_str.len() > one_line_width) - { - format!( - "\n{}{}\n{}", - nested_shape.indent.to_string(context.config), - fields_str, - shape.indent.to_string(context.config) - ) - } else { - // One liner or visual indent. - format!(" {} ", fields_str) - } -} - -pub fn struct_lit_field_separator(config: &Config) -> &str { - colon_spaces(config.space_before_colon(), config.space_after_colon()) -} - -pub fn rewrite_field( - context: &RewriteContext, - field: &ast::Field, - shape: Shape, - prefix_max_width: usize, -) -> Option { - if contains_skip(&field.attrs) { - return Some(context.snippet(field.span()).to_owned()); - } - let mut attrs_str = field.attrs.rewrite(context, shape)?; - if !attrs_str.is_empty() { - attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config))); - }; - let name = field.ident.node.to_string(); - if field.is_shorthand { - Some(attrs_str + &name) - } else { - let mut separator = String::from(struct_lit_field_separator(context.config)); - for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { - separator.push(' '); - } - let overhead = name.len() + separator.len(); - let expr_shape = shape.offset_left(overhead)?; - let expr = field.expr.rewrite(context, expr_shape); - - match expr { - Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { - Some(attrs_str + &name) - } - Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), - None => { - let expr_offset = shape.indent.block_indent(context.config); - let expr = field - .expr - .rewrite(context, Shape::indented(expr_offset, context.config)); - expr.map(|s| { - format!( - "{}{}:\n{}{}", - attrs_str, - name, - expr_offset.to_string(context.config), - s - ) - }) - } - } - } -} - -fn shape_from_indent_style( - context: &RewriteContext, - shape: Shape, - overhead: usize, - offset: usize, -) -> Option { - if context.use_block_indent() { - // 1 = "," - shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1) - } else { - shape.visual_indent(offset).sub_width(overhead) - } -} - -fn rewrite_tuple_in_visual_indent_style<'a, T>( - context: &RewriteContext, - items: &[&T], - span: Span, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let mut items = items.iter(); - // In case of length 1, need a trailing comma - debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); - if items.len() == 1 { - // 3 = "(" + ",)" - let nested_shape = shape.sub_width(3)?.visual_indent(1); - return items - .next() - .unwrap() - .rewrite(context, nested_shape) - .map(|s| { - if context.config.spaces_within_parens_and_brackets() { - format!("( {}, )", s) - } else { - format!("({},)", s) - } - }); - } - - let list_lo = context.codemap.span_after(span, "("); - let nested_shape = shape.sub_width(2)?.visual_indent(1); - let items = itemize_list( - context.codemap, - items, - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - list_lo, - span.hi() - BytePos(1), - false, - ); - let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - let list_str = write_list(&item_vec, &fmt)?; - - if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { - Some(format!("( {} )", list_str)) - } else { - Some(format!("({})", list_str)) - } -} - -pub fn rewrite_tuple<'a, T>( - context: &RewriteContext, - items: &[&T], - span: Span, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - debug!("rewrite_tuple {:?}", shape); - if context.use_block_indent() { - // We use the same rule as function calls for rewriting tuples. - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) - } else { - items.len() == 1 - }; - rewrite_call_inner( - context, - &String::new(), - items, - span, - shape, - context.config.width_heuristics().fn_call_width, - force_trailing_comma, - ) - } else { - rewrite_tuple_in_visual_indent_style(context, items, span, shape) - } -} - -pub fn rewrite_unary_prefix( - context: &RewriteContext, - prefix: &str, - rewrite: &R, - shape: Shape, -) -> Option { - rewrite - .rewrite(context, shape.offset_left(prefix.len())?) - .map(|r| format!("{}{}", prefix, r)) -} - -// FIXME: this is probably not correct for multi-line Rewrites. we should -// subtract suffix.len() from the last line budget, not the first! -pub fn rewrite_unary_suffix( - context: &RewriteContext, - suffix: &str, - rewrite: &R, - shape: Shape, -) -> Option { - rewrite - .rewrite(context, shape.sub_width(suffix.len())?) - .map(|mut r| { - r.push_str(suffix); - r - }) -} - -fn rewrite_unary_op( - context: &RewriteContext, - op: &ast::UnOp, - expr: &ast::Expr, - shape: Shape, -) -> Option { - // For some reason, an UnOp is not spanned like BinOp! - let operator_str = match *op { - ast::UnOp::Deref => "*", - ast::UnOp::Not => "!", - ast::UnOp::Neg => "-", - }; - rewrite_unary_prefix(context, operator_str, expr, shape) -} - -fn rewrite_assignment( - context: &RewriteContext, - lhs: &ast::Expr, - rhs: &ast::Expr, - op: Option<&ast::BinOp>, - shape: Shape, -) -> Option { - let operator_str = match op { - Some(op) => context.snippet(op.span), - None => "=", - }; - - // 1 = space between lhs and operator. - let lhs_shape = shape.sub_width(operator_str.len() + 1)?; - let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); - - rewrite_assign_rhs(context, lhs_str, rhs, shape) -} - -// The left hand side must contain everything up to, and including, the -// assignment operator. -pub fn rewrite_assign_rhs, R: Rewrite>( - context: &RewriteContext, - lhs: S, - ex: &R, - shape: Shape, -) -> Option { - let lhs = lhs.into(); - let last_line_width = last_line_width(&lhs) - .checked_sub(if lhs.contains('\n') { - shape.indent.width() - } else { - 0 - }) - .unwrap_or(0); - // 1 = space between operator and rhs. - let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { - width: 0, - offset: shape.offset + last_line_width + 1, - ..shape - }); - let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; - Some(lhs + &rhs) -} - -pub fn choose_rhs( - context: &RewriteContext, - expr: &R, - shape: Shape, - orig_rhs: Option, -) -> Option { - match orig_rhs { - Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { - Some(format!(" {}", new_str)) - } - _ => { - // Expression did not fit on the same line as the identifier. - // Try splitting the line and see if that works better. - let new_shape = - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(shape.rhs_overhead(context.config))?; - let new_rhs = expr.rewrite(context, new_shape); - let new_indent_str = &new_shape.indent.to_string(context.config); - - match (orig_rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref new_rhs)) - if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) - .is_none() => - { - Some(format!(" {}", orig_rhs)) - } - (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { - Some(format!("\n{}{}", new_indent_str, new_rhs)) - } - (None, Some(ref new_rhs)) => Some(format!("\n{}{}", new_indent_str, new_rhs)), - (None, None) => None, - (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), - } - } - } -} - -fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 -} - -fn rewrite_expr_addrof( - context: &RewriteContext, - mutability: ast::Mutability, - expr: &ast::Expr, - shape: Shape, -) -> Option { - let operator_str = match mutability { - ast::Mutability::Immutable => "&", - ast::Mutability::Mutable => "&mut ", - }; - rewrite_unary_prefix(context, operator_str, expr, shape) -} - -pub trait ToExpr { - fn to_expr(&self) -> Option<&ast::Expr>; - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool; -} - -impl ToExpr for ast::Expr { - fn to_expr(&self) -> Option<&ast::Expr> { - Some(self) - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_expr(context, self, len) - } -} - -impl ToExpr for ast::Ty { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_type(context, self, len) - } -} - -impl<'a> ToExpr for TuplePatField<'a> { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_pat(context, self, len) - } -} - -impl<'a> ToExpr for ast::StructField { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { - false - } -} - -impl<'a> ToExpr for MacroArg { - fn to_expr(&self) -> Option<&ast::Expr> { - match *self { - MacroArg::Expr(ref expr) => Some(expr), - _ => None, - } - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - match *self { - MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), - MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), - MacroArg::Pat(..) => false, - } - } -} diff --git a/src/filemap.rs b/src/filemap.rs deleted file mode 100644 index 81f950cfb9b..00000000000 --- a/src/filemap.rs +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// TODO: add tests - -use std::fs::{self, File}; -use std::io::{self, BufWriter, Read, Write}; -use std::path::Path; - -use checkstyle::{output_checkstyle_file, output_footer, output_header}; -use config::{Config, NewlineStyle, WriteMode}; -use rustfmt_diff::{make_diff, print_diff, Mismatch}; -use syntax::codemap::FileName; - -// A map of the files of a crate, with their new content -pub type FileMap = Vec; - -pub type FileRecord = (FileName, String); - -// Append a newline to the end of each file. -pub fn append_newline(s: &mut String) { - s.push_str("\n"); -} - -pub fn write_all_files( - file_map: &[FileRecord], - out: &mut T, - config: &Config, -) -> Result<(), io::Error> -where - T: Write, -{ - output_header(out, config.write_mode()).ok(); - for &(ref filename, ref text) in file_map { - write_file(text, filename, out, config)?; - } - output_footer(out, config.write_mode()).ok(); - - Ok(()) -} - -// Prints all newlines either as `\n` or as `\r\n`. -pub fn write_system_newlines(writer: T, text: &str, config: &Config) -> Result<(), io::Error> -where - T: Write, -{ - // Buffer output, since we're writing a since char at a time. - let mut writer = BufWriter::new(writer); - - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; - - match style { - NewlineStyle::Unix => write!(writer, "{}", text), - NewlineStyle::Windows => { - for c in text.chars() { - match c { - '\n' => write!(writer, "\r\n")?, - '\r' => continue, - c => write!(writer, "{}", c)?, - } - } - Ok(()) - } - NewlineStyle::Native => unreachable!(), - } -} - -pub fn write_file( - text: &str, - filename: &FileName, - out: &mut T, - config: &Config, -) -> Result -where - T: Write, -{ - fn source_and_formatted_text( - text: &str, - filename: &Path, - config: &Config, - ) -> Result<(String, String), io::Error> { - let mut f = File::open(filename)?; - let mut ori_text = String::new(); - f.read_to_string(&mut ori_text)?; - let mut v = Vec::new(); - write_system_newlines(&mut v, text, config)?; - let fmt_text = String::from_utf8(v).unwrap(); - Ok((ori_text, fmt_text)) - } - - fn create_diff( - filename: &Path, - text: &str, - config: &Config, - ) -> Result, io::Error> { - let (ori, fmt) = source_and_formatted_text(text, filename, config)?; - Ok(make_diff(&ori, &fmt, 3)) - } - - let filename_to_path = || match *filename { - FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` with WriteMode::Replace", filename), - }; - - match config.write_mode() { - WriteMode::Replace => { - let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - if fmt != ori { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.with_extension("tmp"); - let bk_name = filename.with_extension("bk"); - { - // Write text to temp file - let tmp_file = File::create(&tmp_name)?; - write_system_newlines(tmp_file, text, config)?; - } - - fs::rename(filename, bk_name)?; - fs::rename(tmp_name, filename)?; - } - } - } - WriteMode::Overwrite => { - // Write text directly over original file if there is a diff. - let filename = filename_to_path(); - let (source, formatted) = source_and_formatted_text(text, filename, config)?; - if source != formatted { - let file = File::create(filename)?; - write_system_newlines(file, text, config)?; - } - } - WriteMode::Plain => { - write_system_newlines(out, text, config)?; - } - WriteMode::Display | WriteMode::Coverage => { - println!("{}:\n", filename); - write_system_newlines(out, text, config)?; - } - WriteMode::Diff => { - let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - let mismatch = make_diff(&ori, &fmt, 3); - let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config.color(), - ); - return Ok(has_diff); - } - } - WriteMode::Checkstyle => { - let filename = filename_to_path(); - let diff = create_diff(filename, text, config)?; - output_checkstyle_file(out, filename, diff)?; - } - } - - // when we are not in diff mode, don't indicate differing files - Ok(false) -} diff --git a/src/imports.rs b/src/imports.rs deleted file mode 100644 index 0b65cafe730..00000000000 --- a/src/imports.rs +++ /dev/null @@ -1,600 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Ordering; - -use syntax::ast; -use syntax::codemap::{BytePos, Span}; - -use codemap::SpanUtils; -use comment::combine_strs_with_missing_comments; -use config::IndentStyle; -use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, Separator, SeparatorPlace, SeparatorTactic}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use spanned::Spanned; -use types::{rewrite_path, PathContext}; -use utils::{format_visibility, mk_sp}; -use visitor::{rewrite_extern_crate, FmtVisitor}; - -fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { - a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) -} - -fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { - for segment in a.segments.iter().zip(b.segments.iter()) { - let ord = compare_path_segments(segment.0, segment.1); - if ord != Ordering::Equal { - return ord; - } - } - a.segments.len().cmp(&b.segments.len()) -} - -fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Ordering { - use ast::UseTreeKind::*; - - // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be - // fully added - if !nested { - let paths_cmp = compare_paths(&a.prefix, &b.prefix); - if paths_cmp != Ordering::Equal { - return paths_cmp; - } - } - - match (&a.kind, &b.kind) { - (&Simple(ident_a), &Simple(ident_b)) => { - let name_a = &*path_to_imported_ident(&a.prefix).name.as_str(); - let name_b = &*path_to_imported_ident(&b.prefix).name.as_str(); - let name_ordering = if name_a == "self" { - if name_b == "self" { - Ordering::Equal - } else { - Ordering::Less - } - } else if name_b == "self" { - Ordering::Greater - } else { - name_a.cmp(name_b) - }; - if name_ordering == Ordering::Equal { - if ident_a.name.as_str() != name_a { - if ident_b.name.as_str() != name_b { - ident_a.name.as_str().cmp(&ident_b.name.as_str()) - } else { - Ordering::Greater - } - } else { - Ordering::Less - } - } else { - name_ordering - } - } - (&Glob, &Glob) => Ordering::Equal, - (&Simple(_), _) | (&Glob, &Nested(_)) => Ordering::Less, - (&Nested(ref a_items), &Nested(ref b_items)) => { - let mut a = a_items - .iter() - .map(|&(ref tree, _)| tree.clone()) - .collect::>(); - let mut b = b_items - .iter() - .map(|&(ref tree, _)| tree.clone()) - .collect::>(); - a.sort_by(|a, b| compare_use_trees(a, b, true)); - b.sort_by(|a, b| compare_use_trees(a, b, true)); - for comparison_pair in a.iter().zip(b.iter()) { - let ord = compare_use_trees(comparison_pair.0, comparison_pair.1, true); - if ord != Ordering::Equal { - return ord; - } - } - a.len().cmp(&b.len()) - } - (&Glob, &Simple(_)) | (&Nested(_), _) => Ordering::Greater, - } -} - -fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Ordering { - match (&a.node, &b.node) { - (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { - a.ident.name.as_str().cmp(&b.ident.name.as_str()) - } - (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { - compare_use_trees(a_tree, b_tree, false) - } - (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { - // `extern crate foo as bar;` - // ^^^ Comparing this. - let a_orig_name = - a_name.map_or_else(|| a.ident.name.as_str(), |symbol| symbol.as_str()); - let b_orig_name = - b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); - let result = a_orig_name.cmp(&b_orig_name); - if result != Ordering::Equal { - return result; - } - - // `extern crate foo as bar;` - // ^^^ Comparing this. - match (a_name, b_name) { - (Some(..), None) => Ordering::Greater, - (None, Some(..)) => Ordering::Less, - (None, None) => Ordering::Equal, - (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), - } - } - _ => unreachable!(), - } -} - -// TODO (some day) remove unused imports, expand globs, compress many single -// imports into a list import. - -fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { - if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { - let path = &ast::Path { - span: path.span, - segments: path.segments[..path.segments.len() - 1].to_owned(), - }; - rewrite_path(context, PathContext::Import, None, path, shape) - } else { - rewrite_path(context, PathContext::Import, None, path, shape) - } -} - -impl Rewrite for ast::UseTree { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.kind { - ast::UseTreeKind::Nested(ref items) => { - rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context) - } - ast::UseTreeKind::Glob => { - let prefix_shape = shape.sub_width(3)?; - - if !self.prefix.segments.is_empty() { - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; - Some(format!("{}::*", path_str)) - } else { - Some("*".to_owned()) - } - } - ast::UseTreeKind::Simple(ident) => { - let ident_str = ident.to_string(); - - // 4 = " as ".len() - let is_same_name_bind = path_to_imported_ident(&self.prefix) == ident; - let prefix_shape = if is_same_name_bind { - shape - } else { - shape.sub_width(ident_str.len() + 4)? - }; - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) - .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); - - if is_same_name_bind { - Some(path_str) - } else { - Some(format!("{} as {}", path_str, ident_str)) - } - } - } - } -} - -fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool { - attrs.is_empty() && is_unused_import_inner(tree) -} - -fn is_unused_import_inner(tree: &ast::UseTree) -> bool { - match tree.kind { - ast::UseTreeKind::Nested(ref items) => match items.len() { - 0 => true, - 1 => is_unused_import_inner(&items[0].0), - _ => false, - }, - _ => false, - } -} - -// Rewrite `use foo;` WITHOUT attributes. -fn rewrite_import( - context: &RewriteContext, - vis: &ast::Visibility, - tree: &ast::UseTree, - attrs: &[ast::Attribute], - shape: Shape, -) -> Option { - let vis = format_visibility(vis); - // 4 = `use `, 1 = `;` - let rw = shape - .offset_left(vis.len() + 4) - .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| { - // If we have an empty nested group with no attributes, we erase it - if is_unused_import(tree, attrs) { - Some("".to_owned()) - } else { - tree.rewrite(context, shape) - } - }); - match rw { - Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), - _ => rw, - } -} - -/// Rewrite an inline mod. -fn rewrite_mod(item: &ast::Item) -> String { - let mut result = String::with_capacity(32); - result.push_str(&*format_visibility(&item.vis)); - result.push_str("mod "); - result.push_str(&item.ident.to_string()); - result.push(';'); - result -} - -fn rewrite_imports( - context: &RewriteContext, - use_items: &[&ast::Item], - shape: Shape, - span: Span, -) -> Option { - let items = itemize_list( - context.codemap, - use_items.iter(), - "", - ";", - |item| item.span().lo(), - |item| item.span().hi(), - |item| { - let attrs = ::visitor::filter_inline_attrs(&item.attrs, item.span()); - let attrs_str = attrs.rewrite(context, shape)?; - - let missed_span = if attrs.is_empty() { - mk_sp(item.span.lo(), item.span.lo()) - } else { - mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) - }; - - let item_str = match item.node { - ast::ItemKind::Use(ref tree) => { - rewrite_import(context, &item.vis, tree, &item.attrs, shape)? - } - ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, - ast::ItemKind::Mod(..) => rewrite_mod(item), - _ => return None, - }; - - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missed_span, - shape, - false, - ) - }, - span.lo(), - span.hi(), - false, - ); - let mut item_pair_vec: Vec<_> = items.zip(use_items.iter()).collect(); - item_pair_vec.sort_by(|a, b| compare_use_items(a.1, b.1)); - let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); - - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: true, - preserve_newline: false, - config: context.config, - }; - - write_list(&item_vec, &fmt) -} - -impl<'a> FmtVisitor<'a> { - pub fn format_imports(&mut self, use_items: &[&ast::Item]) { - if use_items.is_empty() { - return; - } - - let lo = use_items.first().unwrap().span().lo(); - let hi = use_items.last().unwrap().span().hi(); - let span = mk_sp(lo, hi); - let rw = rewrite_imports(&self.get_context(), use_items, self.shape(), span); - self.push_rewrite(span, rw); - } - - pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { - let span = item.span; - let shape = self.shape(); - let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape); - match rw { - Some(ref s) if s.is_empty() => { - // Format up to last newline - let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); - let trimmed_snippet = self.snippet(prev_span).trim_right(); - let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32); - self.format_missing(span_end); - // We have an excessive newline from the removed import. - if self.buffer.ends_with('\n') { - self.buffer.pop(); - self.line_number -= 1; - } - self.last_pos = source!(self, span).hi(); - } - Some(ref s) => { - self.format_missing_with_indent(source!(self, span).lo()); - self.push_str(s); - self.last_pos = source!(self, span).hi(); - } - None => { - self.format_missing_with_indent(source!(self, span).lo()); - self.format_missing(source!(self, span).hi()); - } - } - } -} - -fn rewrite_nested_use_tree_single( - context: &RewriteContext, - path_str: &str, - tree: &ast::UseTree, - shape: Shape, -) -> Option { - match tree.kind { - ast::UseTreeKind::Simple(rename) => { - let ident = path_to_imported_ident(&tree.prefix); - let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; - if item_str == "self" { - item_str = "".to_owned(); - } - - let path_item_str = if path_str.is_empty() { - if item_str.is_empty() { - "self".to_owned() - } else { - item_str - } - } else if item_str.is_empty() { - path_str.to_owned() - } else { - format!("{}::{}", path_str, item_str) - }; - - Some(if ident == rename { - path_item_str - } else { - format!("{} as {}", path_item_str, rename) - }) - } - ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { - // 2 = "::" - let nested_shape = shape.offset_left(path_str.len() + 2)?; - tree.rewrite(context, nested_shape) - .map(|item| format!("{}::{}", path_str, item)) - } - } -} - -#[derive(Eq, PartialEq)] -enum ImportItem<'a> { - // `self` or `self as a` - SelfImport(&'a str), - // name_one, name_two, ... - SnakeCase(&'a str), - // NameOne, NameTwo, ... - CamelCase(&'a str), - // NAME_ONE, NAME_TWO, ... - AllCaps(&'a str), - // Failed to format the import item - Invalid, -} - -impl<'a> ImportItem<'a> { - fn from_str(s: &str) -> ImportItem { - if s == "self" || s.starts_with("self as") { - ImportItem::SelfImport(s) - } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') { - ImportItem::SnakeCase(s) - } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') { - ImportItem::AllCaps(s) - } else { - ImportItem::CamelCase(s) - } - } - - fn from_opt_str(s: Option<&String>) -> ImportItem { - s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s)) - } - - fn to_str(&self) -> Option<&str> { - match *self { - ImportItem::SelfImport(s) - | ImportItem::SnakeCase(s) - | ImportItem::CamelCase(s) - | ImportItem::AllCaps(s) => Some(s), - ImportItem::Invalid => None, - } - } - - fn to_u32(&self) -> u32 { - match *self { - ImportItem::SelfImport(..) => 0, - ImportItem::SnakeCase(..) => 1, - ImportItem::CamelCase(..) => 2, - ImportItem::AllCaps(..) => 3, - ImportItem::Invalid => 4, - } - } -} - -impl<'a> PartialOrd for ImportItem<'a> { - fn partial_cmp(&self, other: &ImportItem<'a>) -> Option { - Some(self.cmp(other)) - } -} - -impl<'a> Ord for ImportItem<'a> { - fn cmp(&self, other: &ImportItem<'a>) -> Ordering { - let res = self.to_u32().cmp(&other.to_u32()); - if res != Ordering::Equal { - return res; - } - self.to_str().map_or(Ordering::Greater, |self_str| { - other - .to_str() - .map_or(Ordering::Less, |other_str| self_str.cmp(other_str)) - }) - } -} - -// Pretty prints a multi-item import. -// If the path list is empty, it leaves the braces empty. -fn rewrite_nested_use_tree( - shape: Shape, - path: &ast::Path, - trees: &[(ast::UseTree, ast::NodeId)], - span: Span, - context: &RewriteContext, -) -> Option { - // Returns a different option to distinguish `::foo` and `foo` - let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; - - match trees.len() { - 0 => { - let shape = shape.offset_left(path_str.len() + 3)?; - return rewrite_path(context, PathContext::Import, None, path, shape) - .map(|path_str| format!("{}::{{}}", path_str)); - } - 1 => { - return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape); - } - _ => (), - } - - let path_str = if path_str.is_empty() { - path_str - } else { - format!("{}::", path_str) - }; - - // 2 = "{}" - let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); - let nested_indent = match context.config.imports_indent() { - IndentStyle::Block => shape.indent.block_indent(context.config), - // 1 = `{` - IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, - }; - - let nested_shape = match context.config.imports_indent() { - IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?, - IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), - }; - - let mut items = { - // Dummy value, see explanation below. - let mut items = vec![ListItem::from_str("")]; - let iter = itemize_list( - context.codemap, - trees.iter().map(|tree| &tree.0), - "}", - ",", - |tree| tree.span.lo(), - |tree| tree.span.hi(), - |tree| tree.rewrite(context, nested_shape), - context.codemap.span_after(span, "{"), - span.hi(), - false, - ); - items.extend(iter); - items - }; - - // We prefixed the item list with a dummy value so that we can - // potentially move "self" to the front of the vector without touching - // the rest of the items. - let has_self = move_self_to_front(&mut items); - let first_index = if has_self { 0 } else { 1 }; - - if context.config.reorder_imported_names() { - items[1..].sort_by(|a, b| { - let a = ImportItem::from_opt_str(a.item.as_ref()); - let b = ImportItem::from_opt_str(b.item.as_ref()); - a.cmp(&b) - }); - } - - let tactic = definitive_tactic( - &items[first_index..], - context.config.imports_layout(), - Separator::Comma, - remaining_width, - ); - - let ends_with_newline = context.config.imports_indent() == IndentStyle::Block - && tactic != DefinitiveListTactic::Horizontal; - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if ends_with_newline { - context.config.trailing_comma() - } else { - SeparatorTactic::Never - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline, - preserve_newline: true, - config: context.config, - }; - let list_str = write_list(&items[first_index..], &fmt)?; - - let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block - { - format!( - "{}{{\n{}{}\n{}}}", - path_str, - nested_shape.indent.to_string(context.config), - list_str, - shape.indent.to_string(context.config) - ) - } else { - format!("{}{{{}}}", path_str, list_str) - }; - Some(result) -} - -// Returns true when self item was found. -fn move_self_to_front(items: &mut Vec) -> bool { - match items - .iter() - .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) - { - Some(pos) => { - items[0] = items.remove(pos); - true - } - None => false, - } -} - -fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { - path.segments.last().unwrap().identifier -} diff --git a/src/issues.rs b/src/issues.rs deleted file mode 100644 index 2efd61a3d7d..00000000000 --- a/src/issues.rs +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Objects for seeking through a char stream for occurrences of TODO and FIXME. -// Depending on the loaded configuration, may also check that these have an -// associated issue number. - -use std::fmt; - -pub use config::ReportTactic; - -const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o']; -const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e']; - -// Enabled implementation detail is here because it is -// irrelevant outside the issues module -impl ReportTactic { - fn is_enabled(&self) -> bool { - *self != ReportTactic::Never - } -} - -#[derive(Clone, Copy)] -enum Seeking { - Issue { todo_idx: usize, fixme_idx: usize }, - Number { issue: Issue, part: NumberPart }, -} - -#[derive(Clone, Copy)] -enum NumberPart { - OpenParen, - Pound, - Number, - CloseParen, -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub struct Issue { - issue_type: IssueType, - // Indicates whether we're looking for issues with missing numbers, or - // all issues of this type. - missing_number: bool, -} - -impl fmt::Display for Issue { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let msg = match self.issue_type { - IssueType::Todo => "TODO", - IssueType::Fixme => "FIXME", - }; - let details = if self.missing_number { - " without issue number" - } else { - "" - }; - - write!(fmt, "{}{}", msg, details) - } -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -enum IssueType { - Todo, - Fixme, -} - -enum IssueClassification { - Good, - Bad(Issue), - None, -} - -pub struct BadIssueSeeker { - state: Seeking, - report_todo: ReportTactic, - report_fixme: ReportTactic, -} - -impl BadIssueSeeker { - pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { - BadIssueSeeker { - state: Seeking::Issue { - todo_idx: 0, - fixme_idx: 0, - }, - report_todo, - report_fixme, - } - } - - // Check whether or not the current char is conclusive evidence for an - // unnumbered TO-DO or FIX-ME. - pub fn inspect(&mut self, c: char) -> Option { - match self.state { - Seeking::Issue { - todo_idx, - fixme_idx, - } => { - self.state = self.inspect_issue(c, todo_idx, fixme_idx); - } - Seeking::Number { issue, part } => { - let result = self.inspect_number(c, issue, part); - - if let IssueClassification::None = result { - return None; - } - - self.state = Seeking::Issue { - todo_idx: 0, - fixme_idx: 0, - }; - - if let IssueClassification::Bad(issue) = result { - return Some(issue); - } - } - } - - None - } - - fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking { - if let Some(lower_case_c) = c.to_lowercase().next() { - if self.report_todo.is_enabled() && lower_case_c == TO_DO_CHARS[todo_idx] { - todo_idx += 1; - if todo_idx == TO_DO_CHARS.len() { - return Seeking::Number { - issue: Issue { - issue_type: IssueType::Todo, - missing_number: if let ReportTactic::Unnumbered = self.report_todo { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; - } - fixme_idx = 0; - } else if self.report_fixme.is_enabled() && lower_case_c == FIX_ME_CHARS[fixme_idx] { - // Exploit the fact that the character sets of todo and fixme - // are disjoint by adding else. - fixme_idx += 1; - if fixme_idx == FIX_ME_CHARS.len() { - return Seeking::Number { - issue: Issue { - issue_type: IssueType::Fixme, - missing_number: if let ReportTactic::Unnumbered = self.report_fixme { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; - } - todo_idx = 0; - } else { - todo_idx = 0; - fixme_idx = 0; - } - } - - Seeking::Issue { - todo_idx, - fixme_idx, - } - } - - fn inspect_number( - &mut self, - c: char, - issue: Issue, - mut part: NumberPart, - ) -> IssueClassification { - if !issue.missing_number || c == '\n' { - return IssueClassification::Bad(issue); - } else if c == ')' { - return if let NumberPart::CloseParen = part { - IssueClassification::Good - } else { - IssueClassification::Bad(issue) - }; - } - - match part { - NumberPart::OpenParen => { - if c != '(' { - return IssueClassification::Bad(issue); - } else { - part = NumberPart::Pound; - } - } - NumberPart::Pound => { - if c == '#' { - part = NumberPart::Number; - } - } - NumberPart::Number => { - if c >= '0' && c <= '9' { - part = NumberPart::CloseParen; - } else { - return IssueClassification::Bad(issue); - } - } - NumberPart::CloseParen => {} - } - - self.state = Seeking::Number { part, issue }; - - IssueClassification::None - } -} - -#[test] -fn find_unnumbered_issue() { - fn check_fail(text: &str, failing_pos: usize) { - let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!( - Some(failing_pos), - text.chars().position(|c| seeker.inspect(c).is_some()) - ); - } - - fn check_pass(text: &str) { - let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); - } - - check_fail("TODO\n", 4); - check_pass(" TO FIX DOME\n"); - check_fail(" \n FIXME\n", 8); - check_fail("FIXME(\n", 6); - check_fail("FIXME(#\n", 7); - check_fail("FIXME(#1\n", 8); - check_fail("FIXME(#)1\n", 7); - check_pass("FIXME(#1222)\n"); - check_fail("FIXME(#12\n22)\n", 9); - check_pass("FIXME(@maintainer, #1222, hello)\n"); - check_fail("TODO(#22) FIXME\n", 15); -} - -#[test] -fn find_issue() { - fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { - let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); - text.chars().any(|c| seeker.inspect(c).is_some()) - } - - assert!(is_bad_issue( - "TODO(@maintainer, #1222, hello)\n", - ReportTactic::Always, - ReportTactic::Never, - )); - - assert!(!is_bad_issue( - "TODO: no number\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(!is_bad_issue( - "Todo: mixed case\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(is_bad_issue( - "This is a FIXME(#1)\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(is_bad_issue( - "This is a FixMe(#1) mixed case\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(!is_bad_issue( - "bad FIXME\n", - ReportTactic::Always, - ReportTactic::Never, - )); -} - -#[test] -fn issue_type() { - let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); - let expected = Some(Issue { - issue_type: IssueType::Todo, - missing_number: false, - }); - - assert_eq!( - expected, - "TODO(#100): more awesomeness" - .chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap() - ); - - let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); - let expected = Some(Issue { - issue_type: IssueType::Fixme, - missing_number: true, - }); - - assert_eq!( - expected, - "Test. FIXME: bad, bad, not good" - .chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap() - ); -} diff --git a/src/items.rs b/src/items.rs deleted file mode 100644 index 510c96681b8..00000000000 --- a/src/items.rs +++ /dev/null @@ -1,2845 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Formatting top-level items - functions, structs, enums, traits, impls. - -use std::borrow::Cow; -use std::cmp::min; - -use syntax::{abi, ast, ptr, symbol}; -use syntax::ast::{CrateSugar, ImplItem}; -use syntax::codemap::{BytePos, Span}; -use syntax::visit; - -use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; -use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, - rewrite_call_inner, ExprType}; -use lists::{definitive_tactic, itemize_list, write_list, DefinitiveListTactic, ListFormatting, - ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use types::join_bounds; -use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, - format_defaultness, format_mutability, format_unsafety, format_visibility, - is_attributes_extendable, last_line_contains_single_line_comment, - last_line_extendable, last_line_used_width, last_line_width, mk_sp, - semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; -use vertical::rewrite_with_alignment; -use visitor::FmtVisitor; - -fn type_annotation_separator(config: &Config) -> &str { - colon_spaces(config.space_before_colon(), config.space_after_colon()) -} - -// Statements of the form -// let pat: ty = init; -impl Rewrite for ast::Local { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!( - "Local::rewrite {:?} {} {:?}", - self, shape.width, shape.indent - ); - - skip_out_of_file_lines_range!(context, self.span); - - if contains_skip(&self.attrs) { - return None; - } - - let attrs_str = self.attrs.rewrite(context, shape)?; - let mut result = if attrs_str.is_empty() { - "let ".to_owned() - } else { - combine_strs_with_missing_comments( - context, - &attrs_str, - "let ", - mk_sp( - self.attrs.last().map(|a| a.span.hi()).unwrap(), - self.span.lo(), - ), - shape, - false, - )? - }; - - // 4 = "let ".len() - let pat_shape = shape.offset_left(4)?; - // 1 = ; - let pat_shape = pat_shape.sub_width(1)?; - let pat_str = self.pat.rewrite(context, pat_shape)?; - result.push_str(&pat_str); - - // String that is placed within the assignment pattern and expression. - let infix = { - let mut infix = String::with_capacity(32); - - if let Some(ref ty) = self.ty { - let separator = type_annotation_separator(context.config); - let indent = shape.indent + last_line_width(&result) + separator.len(); - // 1 = ; - let budget = shape.width.checked_sub(indent.width() + 1)?; - let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?; - - infix.push_str(separator); - infix.push_str(&rewrite); - } - - if self.init.is_some() { - infix.push_str(" ="); - } - - infix - }; - - result.push_str(&infix); - - if let Some(ref ex) = self.init { - // 1 = trailing semicolon; - let nested_shape = shape.sub_width(1)?; - - result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?; - } - - result.push(';'); - Some(result) - } -} - -// TODO convert to using rewrite style rather than visitor -// TODO format modules in this style -#[allow(dead_code)] -struct Item<'a> { - keyword: &'static str, - abi: Cow<'static, str>, - vis: Option<&'a ast::Visibility>, - body: Vec>, - span: Span, -} - -impl<'a> Item<'a> { - fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { - Item { - keyword: "", - abi: format_abi(fm.abi, config.force_explicit_abi(), true), - vis: None, - body: fm.items - .iter() - .map(|i| BodyElement::ForeignItem(i)) - .collect(), - span, - } - } -} - -enum BodyElement<'a> { - // Stmt(&'a ast::Stmt), - // Field(&'a ast::Field), - // Variant(&'a ast::Variant), - // Item(&'a ast::Item), - ForeignItem(&'a ast::ForeignItem), -} - -/// Represents a fn's signature. -pub struct FnSig<'a> { - decl: &'a ast::FnDecl, - generics: &'a ast::Generics, - abi: abi::Abi, - constness: ast::Constness, - defaultness: ast::Defaultness, - unsafety: ast::Unsafety, - visibility: ast::Visibility, -} - -impl<'a> FnSig<'a> { - pub fn new( - decl: &'a ast::FnDecl, - generics: &'a ast::Generics, - vis: ast::Visibility, - ) -> FnSig<'a> { - FnSig { - decl, - generics, - abi: abi::Abi::Rust, - constness: ast::Constness::NotConst, - defaultness: ast::Defaultness::Final, - unsafety: ast::Unsafety::Normal, - visibility: vis, - } - } - - pub fn from_method_sig( - method_sig: &'a ast::MethodSig, - generics: &'a ast::Generics, - ) -> FnSig<'a> { - FnSig { - unsafety: method_sig.unsafety, - constness: method_sig.constness.node, - defaultness: ast::Defaultness::Final, - abi: method_sig.abi, - decl: &*method_sig.decl, - generics, - visibility: ast::Visibility::Inherited, - } - } - - pub fn from_fn_kind( - fn_kind: &'a visit::FnKind, - generics: &'a ast::Generics, - decl: &'a ast::FnDecl, - defualtness: ast::Defaultness, - ) -> FnSig<'a> { - match *fn_kind { - visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { - decl, - generics, - abi, - constness: constness.node, - defaultness: defualtness, - unsafety, - visibility: visibility.clone(), - }, - visit::FnKind::Method(_, method_sig, vis, _) => { - let mut fn_sig = FnSig::from_method_sig(method_sig, generics); - fn_sig.defaultness = defualtness; - if let Some(vis) = vis { - fn_sig.visibility = vis.clone(); - } - fn_sig - } - _ => unreachable!(), - } - } - - fn to_str(&self, context: &RewriteContext) -> String { - let mut result = String::with_capacity(128); - // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(&self.visibility)); - result.push_str(format_defaultness(self.defaultness)); - result.push_str(format_constness(self.constness)); - result.push_str(format_unsafety(self.unsafety)); - result.push_str(&format_abi( - self.abi, - context.config.force_explicit_abi(), - false, - )); - result - } -} - -impl<'a> FmtVisitor<'a> { - fn format_item(&mut self, item: &Item) { - self.buffer.push_str(&item.abi); - - let snippet = self.snippet(item.span); - let brace_pos = snippet.find_uncommented("{").unwrap(); - - self.push_str("{"); - if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { - // FIXME: this skips comments between the extern keyword and the opening - // brace. - self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1); - self.block_indent = self.block_indent.block_indent(self.config); - - if item.body.is_empty() { - self.format_missing_no_indent(item.span.hi() - BytePos(1)); - self.block_indent = self.block_indent.block_unindent(self.config); - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - } else { - for item in &item.body { - self.format_body_element(item); - } - - self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(item.span.hi() - BytePos(1)); - } - } - - self.push_str("}"); - self.last_pos = item.span.hi(); - } - - fn format_body_element(&mut self, element: &BodyElement) { - match *element { - BodyElement::ForeignItem(item) => self.format_foreign_item(item), - } - } - - pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { - let item = Item::from_foreign_mod(fm, span, self.config); - self.format_item(&item); - } - - fn format_foreign_item(&mut self, item: &ast::ForeignItem) { - let rewrite = item.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(item.span(), rewrite); - self.last_pos = item.span.hi(); - } - - pub fn rewrite_fn( - &mut self, - indent: Indent, - ident: ast::Ident, - fn_sig: &FnSig, - span: Span, - block: &ast::Block, - ) -> Option { - let context = self.get_context(); - - let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause); - - let (mut result, force_newline_brace) = - rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; - - // 2 = ` {` - if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace - || last_line_width(&result) + 2 > self.shape().width - { - newline_brace = true; - } else if !result.contains('\n') { - newline_brace = false; - } - - // Prepare for the function body by possibly adding a newline and - // indent. - // FIXME we'll miss anything between the end of the signature and the - // start of the body, but we need more spans from the compiler to solve - // this. - if newline_brace { - result.push('\n'); - result.push_str(&indent.to_string(self.config)); - } else { - result.push(' '); - } - - self.single_line_fn(&result, block).or_else(|| Some(result)) - } - - pub fn rewrite_required_fn( - &mut self, - indent: Indent, - ident: ast::Ident, - sig: &ast::MethodSig, - generics: &ast::Generics, - span: Span, - ) -> Option { - // Drop semicolon or it will be interpreted as comment. - let span = mk_sp(span.lo(), span.hi() - BytePos(1)); - let context = self.get_context(); - - let (mut result, _) = rewrite_fn_base( - &context, - indent, - ident, - &FnSig::from_method_sig(sig, generics), - span, - false, - false, - )?; - - // Re-attach semicolon - result.push(';'); - - Some(result) - } - - fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { - if fn_str.contains('\n') { - return None; - } - - let codemap = self.get_context().codemap; - - if self.config.empty_item_single_line() && is_empty_block(block, codemap) - && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() - { - return Some(format!("{}{{}}", fn_str)); - } - - if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { - let rewrite = { - if let Some(stmt) = block.stmts.first() { - match stmt_expr(stmt) { - Some(e) => { - let suffix = if semicolon_for_expr(&self.get_context(), e) { - ";" - } else { - "" - }; - - format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) - .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span).to_owned())) - } - None => stmt.rewrite(&self.get_context(), self.shape()), - } - } else { - None - } - }; - - if let Some(res) = rewrite { - let width = self.block_indent.width() + fn_str.len() + res.len() + 4; - if !res.contains('\n') && width <= self.config.max_width() { - return Some(format!("{}{{ {} }}", fn_str, res)); - } - } - } - - None - } - - pub fn visit_static(&mut self, static_parts: &StaticParts) { - let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); - self.push_rewrite(static_parts.span, rewrite); - } - - pub fn visit_struct(&mut self, struct_parts: &StructParts) { - let is_tuple = struct_parts.def.is_tuple(); - let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) - .map(|s| if is_tuple { s + ";" } else { s }); - self.push_rewrite(struct_parts.span, rewrite); - } - - pub fn visit_enum( - &mut self, - ident: ast::Ident, - vis: &ast::Visibility, - enum_def: &ast::EnumDef, - generics: &ast::Generics, - span: Span, - ) { - let enum_header = format_header("enum ", ident, vis); - self.push_str(&enum_header); - - let enum_snippet = self.snippet(span); - let brace_pos = enum_snippet.find_uncommented("{").unwrap(); - let body_start = span.lo() + BytePos(brace_pos as u32 + 1); - let generics_str = format_generics( - &self.get_context(), - generics, - self.config.brace_style(), - if enum_def.variants.is_empty() { - BracePos::ForceSameLine - } else { - BracePos::Auto - }, - self.block_indent, - mk_sp(span.lo(), body_start), - last_line_width(&enum_header), - ).unwrap(); - self.push_str(&generics_str); - - self.last_pos = body_start; - - self.block_indent = self.block_indent.block_indent(self.config); - let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); - match variant_list { - Some(ref body_str) => self.push_str(body_str), - None => self.format_missing_no_indent(span.hi() - BytePos(1)), - } - self.block_indent = self.block_indent.block_unindent(self.config); - - if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - } - self.push_str("}"); - self.last_pos = span.hi(); - } - - // Format the body of an enum definition - fn format_variant_list( - &self, - enum_def: &ast::EnumDef, - body_lo: BytePos, - body_hi: BytePos, - ) -> Option { - if enum_def.variants.is_empty() { - return None; - } - let mut result = String::with_capacity(1024); - result.push('\n'); - let indentation = self.block_indent.to_string(self.config); - result.push_str(&indentation); - - let itemize_list_with = |one_line_width: usize| { - itemize_list( - self.codemap, - enum_def.variants.iter(), - "}", - ",", - |f| { - if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo() - } else { - f.span.lo() - } - }, - |f| f.span.hi(), - |f| self.format_variant(f, one_line_width), - body_lo, - body_hi, - false, - ).collect() - }; - let mut items: Vec<_> = - itemize_list_with(self.config.width_heuristics().struct_variant_width); - // If one of the variants use multiple lines, use multi-lined formatting for all variants. - let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); - let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); - if has_multiline_variant && has_single_line_variant { - items = itemize_list_with(0); - } - - let shape = self.shape().sub_width(2)?; - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: ",", - trailing_separator: self.config.trailing_comma(), - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: true, - preserve_newline: true, - config: self.config, - }; - - let list = write_list(&items, &fmt)?; - result.push_str(&list); - result.push('\n'); - Some(result) - } - - // Variant of an enum. - fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option { - if contains_skip(&field.node.attrs) { - let lo = field.node.attrs[0].span.lo(); - let span = mk_sp(lo, field.span.hi()); - return Some(self.snippet(span).to_owned()); - } - - let context = self.get_context(); - // 1 = ',' - let shape = self.shape().sub_width(1)?; - let attrs_str = field.node.attrs.rewrite(&context, shape)?; - let lo = field - .node - .attrs - .last() - .map_or(field.span.lo(), |attr| attr.span.hi()); - let span = mk_sp(lo, field.span.lo()); - - let variant_body = match field.node.data { - ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( - &context, - &StructParts::from_variant(field), - self.block_indent, - Some(one_line_width), - )?, - ast::VariantData::Unit(..) => { - if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", field.node.name); - rewrite_assign_rhs(&context, lhs, &**expr, shape)? - } else { - field.node.name.to_string() - } - } - }; - - combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) - } -} - -pub fn format_impl( - context: &RewriteContext, - item: &ast::Item, - offset: Indent, - where_span_end: Option, -) -> Option { - if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { - let mut result = String::with_capacity(128); - let ref_and_type = format_impl_ref_and_type(context, item, offset)?; - let indent_str = offset.to_string(context.config); - let sep = format!("\n{}", &indent_str); - result.push_str(&ref_and_type); - - let where_budget = if result.contains('\n') { - context.config.max_width() - } else { - context.budget(last_line_width(&result)) - }; - let option = WhereClauseOption::snuggled(&ref_and_type); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - Density::Vertical, - "{", - where_span_end, - self_ty.span.hi(), - option, - false, - )?; - - // If there is no where clause, we may have missing comments between the trait name and - // the opening brace. - if generics.where_clause.predicates.is_empty() { - if let Some(hi) = where_span_end { - match recover_missing_comment_in_span( - mk_sp(self_ty.span.hi(), hi), - Shape::indented(offset, context.config), - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - } - _ => (), - } - } - } - - if is_impl_single_line(context, items, &result, &where_clause_str, item)? { - result.push_str(&where_clause_str); - if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { - result.push_str(&format!("{}{{{}}}", &sep, &sep)); - } else { - result.push_str(" {}"); - } - return Some(result); - } - - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { - result.push('\n'); - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string(context.config)); - } - result.push_str(&where_clause_str); - - let need_newline = !last_line_extendable(&result) - && (last_line_contains_single_line_comment(&result) || result.contains('\n')); - match context.config.brace_style() { - _ if need_newline => result.push_str(&sep), - BraceStyle::AlwaysNextLine => result.push_str(&sep), - BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { - result.push_str(&sep); - } else { - result.push(' '); - } - } - } - - result.push('{'); - - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - - if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); - - visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); - for item in items { - visitor.visit_impl_item(item); - } - - visitor.format_missing(item.span.hi() - BytePos(1)); - - let inner_indent_str = visitor.block_indent.to_string(context.config); - let outer_indent_str = offset.block_only().to_string(context.config); - - result.push('\n'); - result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.to_string().trim()); - result.push('\n'); - result.push_str(&outer_indent_str); - } - - if result.ends_with('{') { - result.push_str(&sep); - } - result.push('}'); - - Some(result) - } else { - unreachable!(); - } -} - -fn is_impl_single_line( - context: &RewriteContext, - items: &[ImplItem], - result: &str, - where_clause_str: &str, - item: &ast::Item, -) -> Option { - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - - Some( - context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n') - && result.len() + where_clause_str.len() <= context.config.max_width() - && !contains_comment(&snippet[open_pos..]), - ) -} - -fn format_impl_ref_and_type( - context: &RewriteContext, - item: &ast::Item, - offset: Indent, -) -> Option { - if let ast::ItemKind::Impl( - unsafety, - polarity, - defaultness, - ref generics, - ref trait_ref, - ref self_ty, - _, - ) = item.node - { - let mut result = String::with_capacity(128); - - result.push_str(&format_visibility(&item.vis)); - result.push_str(format_defaultness(defaultness)); - result.push_str(format_unsafety(unsafety)); - result.push_str("impl"); - - let lo = context.codemap.span_after(item.span, "impl"); - let hi = match *trait_ref { - Some(ref tr) => tr.path.span.lo(), - None => self_ty.span.lo(), - }; - let shape = generics_shape_from_config( - context.config, - Shape::indented(offset + last_line_width(&result), context.config), - 0, - )?; - let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?; - let generics_str = - rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?; - - let polarity_str = if polarity == ast::ImplPolarity::Negative { - "!" - } else { - "" - }; - - if let Some(ref trait_ref) = *trait_ref { - let result_len = result.len(); - if let Some(trait_ref_str) = rewrite_trait_ref( - context, - trait_ref, - offset, - &generics_str, - true, - polarity_str, - result_len, - ) { - result.push_str(&trait_ref_str); - } else { - let generics_str = - rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?; - result.push_str(&rewrite_trait_ref( - context, - trait_ref, - offset, - &generics_str, - false, - polarity_str, - result_len, - )?); - } - } else { - result.push_str(&generics_str); - } - - // Try to put the self type in a single line. - // ` for` - let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; - let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { - // If there is no where clause adapt budget for type formatting to take space and curly - // brace into account. - match context.config.brace_style() { - BraceStyle::AlwaysNextLine => 0, - _ => 2, - } - } else { - 0 - }; - let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; - // 1 = space before the type. - let budget = context.budget(used_space + 1); - if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { - if !self_ty_str.contains('\n') { - if trait_ref.is_some() { - result.push_str(" for "); - } else { - result.push(' '); - } - result.push_str(&self_ty_str); - return Some(result); - } - } - - // Couldn't fit the self type on a single line, put it on a new line. - result.push('\n'); - // Add indentation of one additional tab. - let new_line_offset = offset.block_indent(context.config); - result.push_str(&new_line_offset.to_string(context.config)); - if trait_ref.is_some() { - result.push_str("for "); - } - let budget = context.budget(last_line_width(&result)); - let type_offset = match context.config.indent_style() { - IndentStyle::Visual => new_line_offset + trait_ref_overhead, - IndentStyle::Block => new_line_offset, - }; - result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); - Some(result) - } else { - unreachable!(); - } -} - -fn rewrite_trait_ref( - context: &RewriteContext, - trait_ref: &ast::TraitRef, - offset: Indent, - generics_str: &str, - retry: bool, - polarity_str: &str, - result_len: usize, -) -> Option { - // 1 = space between generics and trait_ref - let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len); - let shape = Shape::indented(offset + used_space, context.config); - if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { - if !(retry && trait_ref_str.contains('\n')) { - return Some(format!( - "{} {}{}", - generics_str, polarity_str, &trait_ref_str - )); - } - } - // We could not make enough space for trait_ref, so put it on new line. - if !retry { - let offset = offset.block_indent(context.config); - let shape = Shape::indented(offset, context.config); - let trait_ref_str = trait_ref.rewrite(context, shape)?; - Some(format!( - "{}\n{}{}{}", - generics_str, - &offset.to_string(context.config), - polarity_str, - &trait_ref_str - )) - } else { - None - } -} - -pub struct StructParts<'a> { - prefix: &'a str, - ident: ast::Ident, - vis: &'a ast::Visibility, - def: &'a ast::VariantData, - generics: Option<&'a ast::Generics>, - span: Span, -} - -impl<'a> StructParts<'a> { - fn format_header(&self) -> String { - format_header(self.prefix, self.ident, self.vis) - } - - fn from_variant(variant: &'a ast::Variant) -> Self { - StructParts { - prefix: "", - ident: variant.node.name, - vis: &ast::Visibility::Inherited, - def: &variant.node.data, - generics: None, - span: variant.span, - } - } - - pub fn from_item(item: &'a ast::Item) -> Self { - let (prefix, def, generics) = match item.node { - ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), - ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), - _ => unreachable!(), - }; - StructParts { - prefix, - ident: item.ident, - vis: &item.vis, - def, - generics: Some(generics), - span: item.span, - } - } -} - -fn format_struct( - context: &RewriteContext, - struct_parts: &StructParts, - offset: Indent, - one_line_width: Option, -) -> Option { - match *struct_parts.def { - ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset), - ast::VariantData::Tuple(ref fields, _) => { - format_tuple_struct(context, struct_parts, fields, offset) - } - ast::VariantData::Struct(ref fields, _) => { - format_struct_struct(context, struct_parts, fields, offset, one_line_width) - } - } -} - -pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node - { - let mut result = String::with_capacity(128); - let header = format!( - "{}{}trait {}", - format_visibility(&item.vis), - format_unsafety(unsafety), - item.ident - ); - - result.push_str(&header); - - let body_lo = context.codemap.span_after(item.span, "{"); - - let shape = Shape::indented(offset, context.config).offset_left(result.len())?; - let generics_str = - rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; - result.push_str(&generics_str); - - // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. - if !type_param_bounds.is_empty() { - let ident_hi = context - .codemap - .span_after(item.span, &format!("{}", item.ident)); - let bound_hi = type_param_bounds.last().unwrap().span().hi(); - let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); - if contains_comment(snippet) { - return None; - } - } - let trait_bound_str = rewrite_trait_bounds( - context, - type_param_bounds, - Shape::indented(offset, context.config), - )?; - // If the trait, generics, and trait bound cannot fit on the same line, - // put the trait bounds on an indented new line - if offset.width() + last_line_width(&result) + trait_bound_str.len() - > context.config.comment_width() - { - result.push('\n'); - let trait_indent = offset.block_only().block_indent(context.config); - result.push_str(&trait_indent.to_string(context.config)); - } - result.push_str(&trait_bound_str); - - let where_density = - if context.config.indent_style() == IndentStyle::Block && result.is_empty() { - Density::Compressed - } else { - Density::Tall - }; - - let where_budget = context.budget(last_line_width(&result)); - let pos_before_where = if type_param_bounds.is_empty() { - generics.where_clause.span.lo() - } else { - type_param_bounds[type_param_bounds.len() - 1].span().hi() - }; - let option = WhereClauseOption::snuggled(&generics_str); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - where_density, - "{", - None, - pos_before_where, - option, - false, - )?; - // If the where clause cannot fit on the same line, - // put the where clause on a new line - if !where_clause_str.contains('\n') - && last_line_width(&result) + where_clause_str.len() + offset.width() - > context.config.comment_width() - { - result.push('\n'); - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string(context.config)); - } - result.push_str(&where_clause_str); - - if generics.where_clause.predicates.is_empty() { - let item_snippet = context.snippet(item.span); - if let Some(lo) = item_snippet.chars().position(|c| c == '/') { - // 1 = `{` - let comment_hi = body_lo - BytePos(1); - let comment_lo = item.span.lo() + BytePos(lo as u32); - if comment_lo < comment_hi { - match recover_missing_comment_in_span( - mk_sp(comment_lo, comment_hi), - Shape::indented(offset, context.config), - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - } - _ => (), - } - } - } - } - - match context.config.brace_style() { - _ if last_line_contains_single_line_comment(&result) => { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } - BraceStyle::AlwaysNextLine => { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } - BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() - && (!trait_items.is_empty() || result.contains('\n')) - { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push(' '); - } - } - } - result.push('{'); - - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - - if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); - - for item in trait_items { - visitor.visit_trait_item(item); - } - - visitor.format_missing(item.span.hi() - BytePos(1)); - - let inner_indent_str = visitor.block_indent.to_string(context.config); - let outer_indent_str = offset.block_only().to_string(context.config); - - result.push('\n'); - result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.to_string().trim()); - result.push('\n'); - result.push_str(&outer_indent_str); - } else if result.contains('\n') { - result.push('\n'); - } - - result.push('}'); - Some(result) - } else { - unreachable!(); - } -} - -pub fn format_trait_alias( - context: &RewriteContext, - ident: ast::Ident, - generics: &ast::Generics, - ty_param_bounds: &ast::TyParamBounds, - shape: Shape, -) -> Option { - let alias = ident.name.as_str(); - // 6 = "trait ", 2 = " =" - let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?; - let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?; - let lhs = format!("trait {}{} =", alias, generics_str); - // 1 = ";" - rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") -} - -fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { - let header_str = format_header(p.prefix, p.ident, p.vis); - let generics_str = if let Some(generics) = p.generics { - let hi = if generics.where_clause.predicates.is_empty() { - generics.span.hi() - } else { - generics.where_clause.span.hi() - }; - format_generics( - context, - generics, - context.config.brace_style(), - BracePos::None, - offset, - mk_sp(generics.span.lo(), hi), - last_line_width(&header_str), - )? - } else { - String::new() - }; - Some(format!("{}{};", header_str, generics_str)) -} - -pub fn format_struct_struct( - context: &RewriteContext, - struct_parts: &StructParts, - fields: &[ast::StructField], - offset: Indent, - one_line_width: Option, -) -> Option { - let mut result = String::with_capacity(1024); - let span = struct_parts.span; - - let header_str = struct_parts.format_header(); - result.push_str(&header_str); - - let header_hi = span.lo() + BytePos(header_str.len() as u32); - let body_lo = context.codemap.span_after(span, "{"); - - let generics_str = match struct_parts.generics { - Some(g) => format_generics( - context, - g, - context.config.brace_style(), - if fields.is_empty() { - BracePos::ForceSameLine - } else { - BracePos::Auto - }, - offset, - mk_sp(header_hi, body_lo), - last_line_width(&result), - )?, - None => { - // 3 = ` {}`, 2 = ` {`. - let overhead = if fields.is_empty() { 3 } else { 2 }; - if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty()) - || context.config.max_width() < overhead + result.len() - { - format!("\n{}{{", offset.block_only().to_string(context.config)) - } else { - " {".to_owned() - } - } - }; - // 1 = `}` - let overhead = if fields.is_empty() { 1 } else { 0 }; - let total_width = result.len() + generics_str.len() + overhead; - if !generics_str.is_empty() && !generics_str.contains('\n') - && total_width > context.config.max_width() - { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - result.push_str(generics_str.trim_left()); - } else { - result.push_str(&generics_str); - } - - if fields.is_empty() { - let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1))); - if snippet.trim().is_empty() { - // `struct S {}` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - // fix indent - result.push_str(snippet.trim_right()); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push_str(snippet); - } - result.push('}'); - return Some(result); - } - - // 3 = ` ` and ` }` - let one_line_budget = context.budget(result.len() + 3 + offset.width()); - let one_line_budget = - one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); - - let items_str = rewrite_with_alignment( - fields, - context, - Shape::indented(offset, context.config).sub_width(1)?, - mk_sp(body_lo, span.hi()), - one_line_budget, - )?; - - if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget { - Some(format!("{} {} }}", result, items_str)) - } else { - Some(format!( - "{}\n{}{}\n{}}}", - result, - offset - .block_indent(context.config) - .to_string(context.config), - items_str, - offset.to_string(context.config) - )) - } -} - -/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not -/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need -/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args. -fn get_bytepos_after_visibility( - context: &RewriteContext, - vis: &ast::Visibility, - default_span: Span, - terminator: &str, -) -> BytePos { - match *vis { - ast::Visibility::Crate(s, CrateSugar::PubCrate) => context - .codemap - .span_after(mk_sp(s.hi(), default_span.hi()), terminator), - ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), - ast::Visibility::Restricted { ref path, .. } => path.span.hi(), - _ => default_span.lo(), - } -} - -fn format_tuple_struct( - context: &RewriteContext, - struct_parts: &StructParts, - fields: &[ast::StructField], - offset: Indent, -) -> Option { - let mut result = String::with_capacity(1024); - let span = struct_parts.span; - - let header_str = struct_parts.format_header(); - result.push_str(&header_str); - - let body_lo = if fields.is_empty() { - let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")"); - context.codemap.span_after(mk_sp(lo, span.hi()), "(") - } else { - fields[0].span.lo() - }; - let body_hi = if fields.is_empty() { - context.codemap.span_after(mk_sp(body_lo, span.hi()), ")") - } else { - // This is a dirty hack to work around a missing `)` from the span of the last field. - let last_arg_span = fields[fields.len() - 1].span; - if context.snippet(last_arg_span).ends_with(')') { - last_arg_span.hi() - } else { - context - .codemap - .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") - } - }; - - let where_clause_str = match struct_parts.generics { - Some(generics) => { - let budget = context.budget(last_line_width(&header_str)); - let shape = Shape::legacy(budget, offset); - let g_span = mk_sp(span.lo(), body_lo); - let generics_str = rewrite_generics(context, generics, shape, g_span)?; - result.push_str(&generics_str); - - let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::new(true, false); - rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - Density::Compressed, - ";", - None, - body_hi, - option, - false, - )? - } - None => "".to_owned(), - }; - - if fields.is_empty() { - // 3 = `();` - let used_width = last_line_used_width(&result, offset.width()) + 3; - if used_width > context.config.max_width() { - result.push('\n'); - result.push_str(&offset - .block_indent(context.config) - .to_string(context.config)) - } - result.push('('); - let snippet = context.snippet(mk_sp( - body_lo, - context.codemap.span_before(mk_sp(body_lo, span.hi()), ")"), - )); - if snippet.is_empty() { - // `struct S ()` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - result.push_str(snippet.trim_right()); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push_str(snippet); - } - result.push(')'); - } else { - let shape = Shape::indented(offset, context.config).sub_width(1)?; - let fields = &fields.iter().collect::>()[..]; - let one_line_width = context.config.width_heuristics().fn_call_width; - result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; - } - - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') - && (result.contains('\n') - || offset.block_indent + result.len() + where_clause_str.len() + 1 - > context.config.max_width()) - { - // We need to put the where clause on a new line, but we didn't - // know that earlier, so the where clause will not be indented properly. - result.push('\n'); - result - .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) - .to_string(context.config)); - } - result.push_str(&where_clause_str); - - Some(result) -} - -pub fn rewrite_type_alias( - context: &RewriteContext, - indent: Indent, - ident: ast::Ident, - ty: &ast::Ty, - generics: &ast::Generics, - vis: &ast::Visibility, - span: Span, -) -> Option { - let mut result = String::with_capacity(128); - - result.push_str(&format_visibility(vis)); - result.push_str("type "); - result.push_str(&ident.to_string()); - - // 2 = `= ` - let g_shape = Shape::indented(indent, context.config) - .offset_left(result.len())? - .sub_width(2)?; - let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo()); - let generics_str = rewrite_generics(context, generics, g_shape, g_span)?; - result.push_str(&generics_str); - - let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::snuggled(&result); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, indent), - Density::Vertical, - "=", - Some(span.hi()), - generics.span.hi(), - option, - false, - )?; - result.push_str(&where_clause_str); - if where_clause_str.is_empty() { - result.push_str(" ="); - } else { - result.push_str(&format!("\n{}=", indent.to_string(context.config))); - } - - // 1 = ";" - let ty_shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";") -} - -fn type_annotation_spacing(config: &Config) -> (&str, &str) { - ( - if config.space_before_colon() { " " } else { "" }, - if config.space_after_colon() { " " } else { "" }, - ) -} - -pub fn rewrite_struct_field_prefix( - context: &RewriteContext, - field: &ast::StructField, -) -> Option { - let vis = format_visibility(&field.vis); - let type_annotation_spacing = type_annotation_spacing(context.config); - Some(match field.ident { - Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), - None => format!("{}", vis), - }) -} - -impl Rewrite for ast::StructField { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_struct_field(context, self, shape, 0) - } -} - -pub fn rewrite_struct_field( - context: &RewriteContext, - field: &ast::StructField, - shape: Shape, - lhs_max_width: usize, -) -> Option { - if contains_skip(&field.attrs) { - return Some(context.snippet(field.span()).to_owned()); - } - - let type_annotation_spacing = type_annotation_spacing(context.config); - let prefix = rewrite_struct_field_prefix(context, field)?; - - let attrs_str = field.attrs.rewrite(context, shape)?; - let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str); - let missing_span = if field.attrs.is_empty() { - mk_sp(field.span.lo(), field.span.lo()) - } else { - mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo()) - }; - let mut spacing = String::from(if field.ident.is_some() { - type_annotation_spacing.1 - } else { - "" - }); - // Try to put everything on a single line. - let attr_prefix = combine_strs_with_missing_comments( - context, - &attrs_str, - &prefix, - missing_span, - shape, - attrs_extendable, - )?; - let overhead = last_line_width(&attr_prefix); - let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); - for _ in 0..lhs_offset { - spacing.push(' '); - } - // In this extreme case we will be missing a space betweeen an attribute and a field. - if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { - spacing.push(' '); - } - let orig_ty = shape - .offset_left(overhead + spacing.len()) - .and_then(|ty_shape| field.ty.rewrite(context, ty_shape)); - if let Some(ref ty) = orig_ty { - if !ty.contains('\n') { - return Some(attr_prefix + &spacing + ty); - } - } - - let is_prefix_empty = prefix.is_empty(); - // We must use multiline. We are going to put attributes and a field on different lines. - let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; - // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. - let field_str = if is_prefix_empty { - field_str.trim_left() - } else { - &field_str - }; - combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) -} - -pub struct StaticParts<'a> { - prefix: &'a str, - vis: &'a ast::Visibility, - ident: ast::Ident, - ty: &'a ast::Ty, - mutability: ast::Mutability, - expr_opt: Option<&'a ptr::P>, - defaultness: Option, - span: Span, -} - -impl<'a> StaticParts<'a> { - pub fn from_item(item: &'a ast::Item) -> Self { - let (prefix, ty, mutability, expr) = match item.node { - ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), - ast::ItemKind::Const(ref ty, ref expr) => { - ("const", ty, ast::Mutability::Immutable, expr) - } - _ => unreachable!(), - }; - StaticParts { - prefix, - vis: &item.vis, - ident: item.ident, - ty, - mutability, - expr_opt: Some(expr), - defaultness: None, - span: item.span, - } - } - - pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self { - let (ty, expr_opt) = match ti.node { - ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), - _ => unreachable!(), - }; - StaticParts { - prefix: "const", - vis: &ast::Visibility::Inherited, - ident: ti.ident, - ty, - mutability: ast::Mutability::Immutable, - expr_opt: expr_opt.as_ref(), - defaultness: None, - span: ti.span, - } - } - - pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self { - let (ty, expr) = match ii.node { - ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), - _ => unreachable!(), - }; - StaticParts { - prefix: "const", - vis: &ii.vis, - ident: ii.ident, - ty, - mutability: ast::Mutability::Immutable, - expr_opt: Some(expr), - defaultness: Some(ii.defaultness), - span: ii.span, - } - } -} - -fn rewrite_static( - context: &RewriteContext, - static_parts: &StaticParts, - offset: Indent, -) -> Option { - let colon = colon_spaces( - context.config.space_before_colon(), - context.config.space_after_colon(), - ); - let mut prefix = format!( - "{}{}{} {}{}{}", - format_visibility(static_parts.vis), - static_parts.defaultness.map_or("", format_defaultness), - static_parts.prefix, - format_mutability(static_parts.mutability), - static_parts.ident, - colon, - ); - // 2 = " =".len() - let ty_shape = - Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; - let ty_str = match static_parts.ty.rewrite(context, ty_shape) { - Some(ty_str) => ty_str, - None => { - if prefix.ends_with(' ') { - prefix.pop(); - } - let nested_indent = offset.block_indent(context.config); - let nested_shape = Shape::indented(nested_indent, context.config); - let ty_str = static_parts.ty.rewrite(context, nested_shape)?; - format!("\n{}{}", nested_indent.to_string(context.config), ty_str) - } - }; - - if let Some(expr) = static_parts.expr_opt { - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.budget(offset.block_indent + 1); - rewrite_assign_rhs( - context, - lhs, - &**expr, - Shape::legacy(remaining_width, offset.block_only()), - ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) - .map(|s| if s.ends_with(';') { s } else { s + ";" }) - } else { - Some(format!("{}{};", prefix, ty_str)) - } -} - -pub fn rewrite_associated_type( - ident: ast::Ident, - ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, - context: &RewriteContext, - indent: Indent, -) -> Option { - let prefix = format!("type {}", ident); - - let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { - // 2 = ": ".len() - let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - if !bounds.is_empty() { - format!(": {}", join_bounds(context, shape, &bound_str)) - } else { - String::new() - } - } else { - String::new() - }; - - if let Some(ty) = ty_opt { - // 1 = `;` - let shape = Shape::indented(indent, context.config).sub_width(1)?; - let lhs = format!("{}{} =", prefix, type_bounds_str); - rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") - } else { - Some(format!("{}{};", prefix, type_bounds_str)) - } -} - -pub fn rewrite_associated_impl_type( - ident: ast::Ident, - defaultness: ast::Defaultness, - ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, - context: &RewriteContext, - indent: Indent, -) -> Option { - let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?; - - match defaultness { - ast::Defaultness::Default => Some(format!("default {}", result)), - _ => Some(result), - } -} - -impl Rewrite for ast::FunctionRetTy { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::FunctionRetTy::Default(_) => Some(String::new()), - ast::FunctionRetTy::Ty(ref ty) => { - let inner_width = shape.width.checked_sub(3)?; - ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) - .map(|r| format!("-> {}", r)) - } - } - } -} - -fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { - match ty.node { - ast::TyKind::Infer => { - let original = context.snippet(ty.span); - original != "_" - } - _ => false, - } -} - -impl Rewrite for ast::Arg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if is_named_arg(self) { - let mut result = self.pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))?; - - if !is_empty_infer(context, &*self.ty) { - if context.config.space_before_colon() { - result.push_str(" "); - } - result.push_str(":"); - if context.config.space_after_colon() { - result.push_str(" "); - } - let overhead = last_line_width(&result); - let max_width = shape.width.checked_sub(overhead)?; - let ty_str = self.ty - .rewrite(context, Shape::legacy(max_width, shape.indent))?; - result.push_str(&ty_str); - } - - Some(result) - } else { - self.ty.rewrite(context, shape) - } - } -} - -fn rewrite_explicit_self( - explicit_self: &ast::ExplicitSelf, - args: &[ast::Arg], - context: &RewriteContext, -) -> Option { - match explicit_self.node { - ast::SelfKind::Region(lt, m) => { - let mut_str = format_mutability(m); - match lt { - Some(ref l) => { - let lifetime_str = l.rewrite( - context, - Shape::legacy(context.config.max_width(), Indent::empty()), - )?; - Some(format!("&{} {}self", lifetime_str, mut_str)) - } - None => Some(format!("&{}self", mut_str)), - } - } - ast::SelfKind::Explicit(ref ty, _) => { - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - - let mutability = explicit_self_mutability(&args[0]); - let type_str = ty.rewrite( - context, - Shape::legacy(context.config.max_width(), Indent::empty()), - )?; - - Some(format!( - "{}self: {}", - format_mutability(mutability), - type_str - )) - } - ast::SelfKind::Value(_) => { - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - - let mutability = explicit_self_mutability(&args[0]); - - Some(format!("{}self", format_mutability(mutability))) - } - } -} - -// Hacky solution caused by absence of `Mutability` in `SelfValue` and -// `SelfExplicit` variants of `ast::ExplicitSelf_`. -fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { - if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node { - mutability - } else { - unreachable!() - } -} - -pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { - if is_named_arg(arg) { - arg.pat.span.lo() - } else { - arg.ty.span.lo() - } -} - -pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { - match arg.ty.node { - ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), - ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), - _ => arg.ty.span.hi(), - } -} - -pub fn is_named_arg(arg: &ast::Arg) -> bool { - if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != symbol::keywords::Invalid.ident() - } else { - true - } -} - -// Return type is (result, force_new_line_for_brace) -fn rewrite_fn_base( - context: &RewriteContext, - indent: Indent, - ident: ast::Ident, - fn_sig: &FnSig, - span: Span, - newline_brace: bool, - has_body: bool, -) -> Option<(String, bool)> { - let mut force_new_line_for_brace = false; - - let where_clause = &fn_sig.generics.where_clause; - - let mut result = String::with_capacity(1024); - result.push_str(&fn_sig.to_str(context)); - - // fn foo - result.push_str("fn "); - result.push_str(&ident.to_string()); - - // Generics. - let overhead = if has_body && !newline_brace { - // 4 = `() {` - 4 - } else { - // 2 = `()` - 2 - }; - let used_width = last_line_used_width(&result, indent.width()); - let one_line_budget = context.budget(used_width + overhead); - let shape = Shape { - width: one_line_budget, - indent, - offset: used_width, - }; - let fd = fn_sig.decl; - let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?; - result.push_str(&generics_str); - - let snuggle_angle_bracket = generics_str - .lines() - .last() - .map_or(false, |l| l.trim_left().len() == 1); - - // Note that the width and indent don't really matter, we'll re-layout the - // return type later anyway. - let ret_str = fd.output - .rewrite(context, Shape::indented(indent, context.config))?; - - let multi_line_ret_str = ret_str.contains('\n'); - let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; - - // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args( - context, - &result, - indent, - ret_str_len, - newline_brace, - has_body, - multi_line_ret_str, - )?; - - debug!( - "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", - one_line_budget, multi_line_budget, arg_indent - ); - - // Check if vertical layout was forced. - if one_line_budget == 0 { - if snuggle_angle_bracket { - result.push('('); - } else { - result.push_str("("); - if context.config.indent_style() == IndentStyle::Visual { - result.push('\n'); - result.push_str(&arg_indent.to_string(context.config)); - } - } - } else { - result.push('('); - } - if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() - && result.ends_with('(') - { - result.push(' ') - } - - // Skip `pub(crate)`. - let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")"); - // A conservative estimation, to goal is to be over all parens in generics - let args_start = fn_sig - .generics - .params - .iter() - .last() - .map_or(lo_after_visibility, |param| param.span().hi()); - let args_end = if fd.inputs.is_empty() { - context - .codemap - .span_after(mk_sp(args_start, span.hi()), ")") - } else { - let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); - context.codemap.span_after(last_span, ")") - }; - let args_span = mk_sp( - context - .codemap - .span_after(mk_sp(args_start, span.hi()), "("), - args_end, - ); - let arg_str = rewrite_args( - context, - &fd.inputs, - fd.get_self().as_ref(), - one_line_budget, - multi_line_budget, - indent, - arg_indent, - args_span, - fd.variadic, - generics_str.contains('\n'), - )?; - - let put_args_in_block = match context.config.indent_style() { - IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, - _ => false, - } && !fd.inputs.is_empty(); - - let mut args_last_line_contains_comment = false; - if put_args_in_block { - arg_indent = indent.block_indent(context.config); - result.push('\n'); - result.push_str(&arg_indent.to_string(context.config)); - result.push_str(&arg_str); - result.push('\n'); - result.push_str(&indent.to_string(context.config)); - result.push(')'); - } else { - result.push_str(&arg_str); - let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); - // Put the closing brace on the next line if it overflows the max width. - // 1 = `)` - if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { - result.push('\n'); - } - if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() { - result.push(' ') - } - // If the last line of args contains comment, we cannot put the closing paren - // on the same line. - if arg_str - .lines() - .last() - .map_or(false, |last_line| last_line.contains("//")) - { - args_last_line_contains_comment = true; - result.push('\n'); - result.push_str(&arg_indent.to_string(context.config)); - } - result.push(')'); - } - - // Return type. - if let ast::FunctionRetTy::Ty(..) = fd.output { - let ret_should_indent = match context.config.indent_style() { - // If our args are block layout then we surely must have space. - IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, - _ if args_last_line_contains_comment => false, - _ if result.contains('\n') || multi_line_ret_str => true, - _ => { - // If the return type would push over the max width, then put the return type on - // a new line. With the +1 for the signature length an additional space between - // the closing parenthesis of the argument and the arrow '->' is considered. - let mut sig_length = result.len() + indent.width() + ret_str_len + 1; - - // If there is no where clause, take into account the space after the return type - // and the brace. - if where_clause.predicates.is_empty() { - sig_length += 2; - } - - sig_length > context.config.max_width() - } - }; - let ret_indent = if ret_should_indent { - let indent = if arg_str.is_empty() { - // Aligning with non-existent args looks silly. - force_new_line_for_brace = true; - indent + 4 - } else { - // FIXME: we might want to check that using the arg indent - // doesn't blow our budget, and if it does, then fallback to - // the where clause indent. - arg_indent - }; - - result.push('\n'); - result.push_str(&indent.to_string(context.config)); - indent - } else { - result.push(' '); - Indent::new(indent.block_indent, last_line_width(&result)) - }; - - if multi_line_ret_str || ret_should_indent { - // Now that we know the proper indent and width, we need to - // re-layout the return type. - let ret_str = fd.output - .rewrite(context, Shape::indented(ret_indent, context.config))?; - result.push_str(&ret_str); - } else { - result.push_str(&ret_str); - } - - // Comment between return type and the end of the decl. - let snippet_lo = fd.output.span().hi(); - if where_clause.predicates.is_empty() { - let snippet_hi = span.hi(); - let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); - // Try to preserve the layout of the original snippet. - let original_starts_with_newline = snippet - .find(|c| c != ' ') - .map_or(false, |i| starts_with_newline(&snippet[i..])); - let original_ends_with_newline = snippet - .rfind(|c| c != ' ') - .map_or(false, |i| snippet[i..].ends_with('\n')); - let snippet = snippet.trim(); - if !snippet.is_empty() { - result.push(if original_starts_with_newline { - '\n' - } else { - ' ' - }); - result.push_str(snippet); - if original_ends_with_newline { - force_new_line_for_brace = true; - } - } - } - } - - let pos_before_where = match fd.output { - ast::FunctionRetTy::Default(..) => args_span.hi(), - ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), - }; - - let is_args_multi_lined = arg_str.contains('\n'); - - let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); - let where_clause_str = rewrite_where_clause( - context, - where_clause, - context.config.brace_style(), - Shape::indented(indent, context.config), - Density::Tall, - "{", - Some(span.hi()), - pos_before_where, - option, - is_args_multi_lined, - )?; - // If there are neither where clause nor return type, we may be missing comments between - // args and `{`. - if where_clause_str.is_empty() { - if let ast::FunctionRetTy::Default(ret_span) = fd.output { - match recover_missing_comment_in_span( - mk_sp(args_span.hi(), ret_span.hi()), - shape, - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - force_new_line_for_brace = true; - } - _ => (), - } - } - } - - result.push_str(&where_clause_str); - - force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line(); - Some((result, force_new_line_for_brace)) -} - -#[derive(Copy, Clone)] -struct WhereClauseOption { - suppress_comma: bool, // Force no trailing comma - snuggle: bool, // Do not insert newline before `where` - compress_where: bool, // Try single line where clause instead of vertical layout -} - -impl WhereClauseOption { - pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { - WhereClauseOption { - suppress_comma, - snuggle, - compress_where: false, - } - } - - pub fn snuggled(current: &str) -> WhereClauseOption { - WhereClauseOption { - suppress_comma: false, - snuggle: trimmed_last_line_width(current) == 1, - compress_where: false, - } - } -} - -fn rewrite_args( - context: &RewriteContext, - args: &[ast::Arg], - explicit_self: Option<&ast::ExplicitSelf>, - one_line_budget: usize, - multi_line_budget: usize, - indent: Indent, - arg_indent: Indent, - span: Span, - variadic: bool, - generics_str_contains_newline: bool, -) -> Option { - let mut arg_item_strs = args.iter() - .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) - .collect::>>()?; - - // Account for sugary self. - // FIXME: the comment for the self argument is dropped. This is blocked - // on rust issue #27522. - let min_args = explicit_self - .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) - .map_or(1, |self_str| { - arg_item_strs[0] = self_str; - 2 - }); - - // Comments between args. - let mut arg_items = Vec::new(); - if min_args == 2 { - arg_items.push(ListItem::from_str("")); - } - - // FIXME(#21): if there are no args, there might still be a comment, but - // without spans for the comment or parens, there is no chance of - // getting it right. You also don't get to put a comment on self, unless - // it is explicit. - if args.len() >= min_args || variadic { - let comment_span_start = if min_args == 2 { - let second_arg_start = if arg_has_pattern(&args[1]) { - args[1].pat.span.lo() - } else { - args[1].ty.span.lo() - }; - let reduced_span = mk_sp(span.lo(), second_arg_start); - - context.codemap.span_after_last(reduced_span, ",") - } else { - span.lo() - }; - - enum ArgumentKind<'a> { - Regular(&'a ast::Arg), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi()); - let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - - let more_items = itemize_list( - context.codemap, - args[min_args - 1..] - .iter() - .map(ArgumentKind::Regular) - .chain(variadic_arg), - ")", - ",", - |arg| match *arg { - ArgumentKind::Regular(arg) => span_lo_for_arg(arg), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi(), - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => Some("...".to_owned()), - }, - comment_span_start, - span.hi(), - false, - ); - - arg_items.extend(more_items); - } - - let fits_in_one_line = !generics_str_contains_newline - && (arg_items.is_empty() - || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); - - for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { - item.item = Some(arg); - } - - let last_line_ends_with_comment = arg_items - .iter() - .last() - .and_then(|item| item.post_comment.as_ref()) - .map_or(false, |s| s.trim().starts_with("//")); - - let (indent, trailing_comma) = match context.config.indent_style() { - IndentStyle::Block if fits_in_one_line => { - (indent.block_indent(context.config), SeparatorTactic::Never) - } - IndentStyle::Block => ( - indent.block_indent(context.config), - context.config.trailing_comma(), - ), - IndentStyle::Visual if last_line_ends_with_comment => { - (arg_indent, context.config.trailing_comma()) - } - IndentStyle::Visual => (arg_indent, SeparatorTactic::Never), - }; - - let tactic = definitive_tactic( - &arg_items, - context.config.fn_args_density().to_list_tactic(), - Separator::Comma, - one_line_budget, - ); - let budget = match tactic { - DefinitiveListTactic::Horizontal => one_line_budget, - _ => multi_line_budget, - }; - - debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if variadic { - SeparatorTactic::Never - } else { - trailing_comma - }, - separator_place: SeparatorPlace::Back, - shape: Shape::legacy(budget, indent), - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - write_list(&arg_items, &fmt) -} - -fn arg_has_pattern(arg: &ast::Arg) -> bool { - if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != symbol::keywords::Invalid.ident() - } else { - true - } -} - -fn compute_budgets_for_args( - context: &RewriteContext, - result: &str, - indent: Indent, - ret_str_len: usize, - newline_brace: bool, - has_braces: bool, - force_vertical_layout: bool, -) -> Option<((usize, usize, Indent))> { - debug!( - "compute_budgets_for_args {} {:?}, {}, {}", - result.len(), - indent, - ret_str_len, - newline_brace - ); - // Try keeping everything on the same line. - if !result.contains('\n') && !force_vertical_layout { - // 2 = `()`, 3 = `() `, space is before ret_string. - let overhead = if ret_str_len == 0 { 2 } else { 3 }; - let mut used_space = indent.width() + result.len() + ret_str_len + overhead; - if has_braces { - if !newline_brace { - // 2 = `{}` - used_space += 2; - } - } else { - // 1 = `;` - used_space += 1; - } - let one_line_budget = context.budget(used_space); - - if one_line_budget > 0 { - // 4 = "() {".len() - let (indent, multi_line_budget) = match context.config.indent_style() { - IndentStyle::Block => { - let indent = indent.block_indent(context.config); - (indent, context.budget(indent.width() + 1)) - } - IndentStyle::Visual => { - let indent = indent + result.len() + 1; - let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; - (indent, context.budget(multi_line_overhead)) - } - }; - - return Some((one_line_budget, multi_line_budget, indent)); - } - } - - // Didn't work. we must force vertical layout and put args on a newline. - let new_indent = indent.block_indent(context.config); - let used_space = match context.config.indent_style() { - // 1 = `,` - IndentStyle::Block => new_indent.width() + 1, - // Account for `)` and possibly ` {`. - IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, - }; - Some((0, context.budget(used_space), new_indent)) -} - -fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { - let predicate_count = where_clause.predicates.len(); - - if config.where_single_line() && predicate_count == 1 { - return false; - } - let brace_style = config.brace_style(); - - brace_style == BraceStyle::AlwaysNextLine - || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0) -} - -fn rewrite_generics( - context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - span: Span, -) -> Option { - let g_shape = generics_shape_from_config(context.config, shape, 0)?; - let one_line_width = shape.width.checked_sub(2).unwrap_or(0); - rewrite_generics_inner(context, generics, g_shape, one_line_width, span) - .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span)) -} - -fn rewrite_generics_inner( - context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - one_line_width: usize, - span: Span, -) -> Option { - // FIXME: convert bounds to where clauses where they get too big or if - // there is a where clause at all. - - if generics.params.is_empty() { - return Some(String::new()); - } - - let items = itemize_list( - context.codemap, - generics.params.iter(), - ">", - ",", - |arg| arg.span().lo(), - |arg| arg.span().hi(), - |arg| arg.rewrite(context, shape), - context.codemap.span_after(span, "<"), - span.hi(), - false, - ); - format_generics_item_list(context, items, shape, one_line_width) -} - -pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { - match config.indent_style() { - IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), - IndentStyle::Block => { - // 1 = "," - shape - .block() - .block_indent(config.tab_spaces()) - .with_max_width(config) - .sub_width(1) - } - } -} - -pub fn format_generics_item_list( - context: &RewriteContext, - items: I, - shape: Shape, - one_line_budget: usize, -) -> Option -where - I: Iterator, -{ - let item_vec = items.collect::>(); - - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - one_line_budget, - ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if context.config.indent_style() == IndentStyle::Visual { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - let list_str = write_list(&item_vec, &fmt)?; - - Some(wrap_generics_with_angle_brackets( - context, - &list_str, - shape.indent, - )) -} - -pub fn wrap_generics_with_angle_brackets( - context: &RewriteContext, - list_str: &str, - list_offset: Indent, -) -> String { - if context.config.indent_style() == IndentStyle::Block - && (list_str.contains('\n') || list_str.ends_with(',')) - { - format!( - "<\n{}{}\n{}>", - list_offset.to_string(context.config), - list_str, - list_offset - .block_unindent(context.config) - .to_string(context.config) - ) - } else if context.config.spaces_within_parens_and_brackets() { - format!("< {} >", list_str) - } else { - format!("<{}>", list_str) - } -} - -fn rewrite_trait_bounds( - context: &RewriteContext, - bounds: &[ast::TyParamBound], - shape: Shape, -) -> Option { - if bounds.is_empty() { - return Some(String::new()); - } - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - Some(format!(": {}", join_bounds(context, shape, &bound_str))) -} - -fn rewrite_where_clause_rfc_style( - context: &RewriteContext, - where_clause: &ast::WhereClause, - shape: Shape, - terminator: &str, - span_end: Option, - span_end_before_where: BytePos, - where_clause_option: WhereClauseOption, - is_args_multi_line: bool, -) -> Option { - let block_shape = shape.block().with_max_width(context.config); - - let (span_before, span_after) = - missing_span_before_after_where(span_end_before_where, where_clause); - let (comment_before, comment_after) = - rewrite_comments_before_after_where(context, span_before, span_after, shape)?; - - let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { - " ".to_owned() - } else { - "\n".to_owned() + &block_shape.indent.to_string(context.config) - }; - - let clause_shape = block_shape.block_left(context.config.tab_spaces())?; - // 1 = `,` - let clause_shape = clause_shape.sub_width(1)?; - // each clause on one line, trailing comma (except if suppress_comma) - let span_start = where_clause.predicates[0].span().lo(); - // If we don't have the start of the next span, then use the end of the - // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi(); - let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list( - context.codemap, - where_clause.predicates.iter(), - terminator, - ",", - |pred| pred.span().lo(), - |pred| pred.span().hi(), - |pred| pred.rewrite(context, clause_shape), - span_start, - span_end, - false, - ); - let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line; - let comma_tactic = if where_clause_option.suppress_comma || where_single_line { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }; - - // shape should be vertical only and only if we have `where_single_line` option enabled - // and the number of items of the where clause is equal to 1 - let shape_tactic = if where_single_line { - DefinitiveListTactic::Horizontal - } else { - DefinitiveListTactic::Vertical - }; - - let fmt = ListFormatting { - tactic: shape_tactic, - separator: ",", - trailing_separator: comma_tactic, - separator_place: SeparatorPlace::Back, - shape: clause_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - let preds_str = write_list(&items.collect::>(), &fmt)?; - - let comment_separator = |comment: &str, shape: Shape| { - if comment.is_empty() { - String::new() - } else { - format!("\n{}", shape.indent.to_string(context.config)) - } - }; - let newline_before_where = comment_separator(&comment_before, shape); - let newline_after_where = comment_separator(&comment_after, clause_shape); - - // 6 = `where ` - let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() - && comment_after.is_empty() && !preds_str.contains('\n') - && 6 + preds_str.len() <= shape.width || where_single_line - { - String::from(" ") - } else { - format!("\n{}", clause_shape.indent.to_string(context.config)) - }; - Some(format!( - "{}{}{}where{}{}{}{}", - starting_newline, - comment_before, - newline_before_where, - newline_after_where, - comment_after, - clause_sep, - preds_str - )) -} - -fn rewrite_where_clause( - context: &RewriteContext, - where_clause: &ast::WhereClause, - brace_style: BraceStyle, - shape: Shape, - density: Density, - terminator: &str, - span_end: Option, - span_end_before_where: BytePos, - where_clause_option: WhereClauseOption, - is_args_multi_line: bool, -) -> Option { - if where_clause.predicates.is_empty() { - return Some(String::new()); - } - - if context.config.indent_style() == IndentStyle::Block { - return rewrite_where_clause_rfc_style( - context, - where_clause, - shape, - terminator, - span_end, - span_end_before_where, - where_clause_option, - is_args_multi_line, - ); - } - - let extra_indent = Indent::new(context.config.tab_spaces(), 0); - - let offset = match context.config.indent_style() { - IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), - // 6 = "where ".len() - IndentStyle::Visual => shape.indent + extra_indent + 6, - }; - // FIXME: if indent_style != Visual, then the budgets below might - // be out by a char or two. - - let budget = context.config.max_width() - offset.width(); - let span_start = where_clause.predicates[0].span().lo(); - // If we don't have the start of the next span, then use the end of the - // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi(); - let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list( - context.codemap, - where_clause.predicates.iter(), - terminator, - ",", - |pred| pred.span().lo(), - |pred| pred.span().hi(), - |pred| pred.rewrite(context, Shape::legacy(budget, offset)), - span_start, - span_end, - false, - ); - let item_vec = items.collect::>(); - // FIXME: we don't need to collect here - let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget); - - let mut comma_tactic = context.config.trailing_comma(); - // Kind of a hack because we don't usually have trailing commas in where clauses. - if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma { - comma_tactic = SeparatorTactic::Never; - } - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: comma_tactic, - separator_place: SeparatorPlace::Back, - shape: Shape::legacy(budget, offset), - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - let preds_str = write_list(&item_vec, &fmt)?; - - let end_length = if terminator == "{" { - // If the brace is on the next line we don't need to count it otherwise it needs two - // characters " {" - match brace_style { - BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0, - BraceStyle::PreferSameLine => 2, - } - } else if terminator == "=" { - 2 - } else { - terminator.len() - }; - if density == Density::Tall || preds_str.contains('\n') - || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width - { - Some(format!( - "\n{}where {}", - (shape.indent + extra_indent).to_string(context.config), - preds_str - )) - } else { - Some(format!(" where {}", preds_str)) - } -} - -fn missing_span_before_after_where( - before_item_span_end: BytePos, - where_clause: &ast::WhereClause, -) -> (Span, Span) { - let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo()); - // 5 = `where` - let pos_after_where = where_clause.span.lo() + BytePos(5); - let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo()); - (missing_span_before, missing_span_after) -} - -fn rewrite_comments_before_after_where( - context: &RewriteContext, - span_before_where: Span, - span_after_where: Span, - shape: Shape, -) -> Option<(String, String)> { - let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; - let after_comment = rewrite_missing_comment( - span_after_where, - shape.block_indent(context.config.tab_spaces()), - context, - )?; - Some((before_comment, after_comment)) -} - -fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, ident) -} - -#[derive(PartialEq, Eq, Clone, Copy)] -enum BracePos { - None, - Auto, - ForceSameLine, -} - -fn format_generics( - context: &RewriteContext, - generics: &ast::Generics, - brace_style: BraceStyle, - brace_pos: BracePos, - offset: Indent, - span: Span, - used_width: usize, -) -> Option { - let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = rewrite_generics(context, generics, shape, span)?; - - let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = context.budget(last_line_used_width(&result, offset.width())); - let mut option = WhereClauseOption::snuggled(&result); - if brace_pos == BracePos::None { - option.suppress_comma = true; - } - // If the generics are not parameterized then generics.span.hi() == 0, - // so we use span.lo(), which is the position after `struct Foo`. - let span_end_before_where = if generics.is_parameterized() { - generics.span.hi() - } else { - span.lo() - }; - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - brace_style, - Shape::legacy(budget, offset.block_only()), - Density::Tall, - "{", - Some(span.hi()), - span_end_before_where, - option, - false, - )?; - result.push_str(&where_clause_str); - brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine - || (generics.where_clause.predicates.is_empty() - && trimmed_last_line_width(&result) == 1) - } else { - brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1 - || brace_style != BraceStyle::AlwaysNextLine - }; - if brace_pos == BracePos::None { - return Some(result); - } - let total_used_width = last_line_used_width(&result, used_width); - let remaining_budget = context.budget(total_used_width); - // If the same line brace if forced, it indicates that we are rewriting an item with empty body, - // and hence we take the closer into account as well for one line budget. - // We assume that the closer has the same length as the opener. - let overhead = if brace_pos == BracePos::ForceSameLine { - // 3 = ` {}` - 3 - } else { - // 2 = ` {` - 2 - }; - let forbid_same_line_brace = overhead > remaining_budget; - if !forbid_same_line_brace && same_line_brace { - result.push(' '); - } else { - result.push('\n'); - result.push_str(&offset.block_only().to_string(context.config)); - } - result.push('{'); - - Some(result) -} - -impl Rewrite for ast::ForeignItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; - // Drop semicolon or it will be interpreted as comment. - // FIXME: this may be a faulty span from libsyntax. - let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - - let item_str = match self.node { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { - rewrite_fn_base( - context, - shape.indent, - self.ident, - &FnSig::new(fn_decl, generics, self.vis.clone()), - span, - false, - false, - ).map(|(s, _)| format!("{};", s)) - } - ast::ForeignItemKind::Static(ref ty, is_mutable) => { - // FIXME(#21): we're dropping potential comments in between the - // function keywords here. - let vis = format_visibility(&self.vis); - let mut_str = if is_mutable { "mut " } else { "" }; - let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); - // 1 = ; - let shape = shape.sub_width(1)?; - ty.rewrite(context, shape).map(|ty_str| { - // 1 = space between prefix and type. - let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { - String::from(" ") - } else { - let nested_indent = shape.indent.block_indent(context.config); - format!("\n{}", nested_indent.to_string(context.config)) - }; - format!("{}{}{};", prefix, sep, ty_str) - }) - } - ast::ForeignItemKind::Ty => { - let vis = format_visibility(&self.vis); - Some(format!("{}type {};", vis, self.ident)) - } - }?; - - let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo(), self.span.lo()) - } else { - mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo()) - }; - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missing_span, - shape, - false, - ) - } -} - -impl Rewrite for ast::GenericParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape), - ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape), - } - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 6aca11ab3ee..00000000000 --- a/src/lib.rs +++ /dev/null @@ -1,828 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(decl_macro)] -#![feature(match_default_bindings)] -#![feature(type_ascription)] - -#[macro_use] -extern crate derive_new; -extern crate diff; -#[macro_use] -extern crate log; -extern crate regex; -extern crate rustc_errors as errors; -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate syntax; -extern crate term; -extern crate unicode_segmentation; - -use std::collections::HashMap; -use std::fmt; -use std::io::{self, stdout, Write}; -use std::iter::repeat; -use std::path::PathBuf; -use std::rc::Rc; -use std::time::Duration; - -use errors::{DiagnosticBuilder, Handler}; -use errors::emitter::{ColorConfig, EmitterWriter}; -use syntax::ast; -use syntax::codemap::{CodeMap, FilePathMapping}; -pub use syntax::codemap::FileName; -use syntax::parse::{self, ParseSess}; - -use checkstyle::{output_footer, output_header}; -use comment::{CharClasses, FullCodeCharKind}; -pub use config::Config; -use filemap::FileMap; -use issues::{BadIssueSeeker, Issue}; -use shape::Indent; -use utils::use_colored_tty; -use visitor::{FmtVisitor, SnippetProvider}; - -pub use self::summary::Summary; - -#[macro_use] -mod utils; -mod chains; -mod checkstyle; -mod closures; -pub mod codemap; -mod comment; -pub mod config; -mod expr; -pub mod file_lines; -pub mod filemap; -mod imports; -mod issues; -mod items; -mod lists; -mod macros; -mod missed_spans; -pub mod modules; -mod patterns; -mod rewrite; -pub mod rustfmt_diff; -mod shape; -mod spanned; -mod string; -mod summary; -mod types; -mod vertical; -pub mod visitor; - -#[derive(Clone, Copy)] -pub enum ErrorKind { - // Line has exceeded character limit (found, maximum) - LineOverflow(usize, usize), - // Line ends in whitespace - TrailingWhitespace, - // TO-DO or FIX-ME item without an issue number - BadIssue(Issue), -} - -impl fmt::Display for ErrorKind { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - ErrorKind::LineOverflow(found, maximum) => write!( - fmt, - "line exceeded maximum width (maximum: {}, found: {})", - maximum, found - ), - ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), - ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), - } - } -} - -// Formatting errors that are identified *after* rustfmt has run. -pub struct FormattingError { - line: usize, - kind: ErrorKind, - is_comment: bool, - is_string: bool, - line_buffer: String, -} - -impl FormattingError { - fn msg_prefix(&self) -> &str { - match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "error:", - ErrorKind::BadIssue(_) => "WARNING:", - } - } - - fn msg_suffix(&self) -> &str { - if self.is_comment || self.is_string { - "set `error_on_unformatted = false` to suppress \ - the warning against comments or string literals\n" - } else { - "" - } - } - - // (space, target) - pub fn format_len(&self) -> (usize, usize) { - match self.kind { - ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace => { - let trailing_ws_len = self.line_buffer - .chars() - .rev() - .take_while(|c| c.is_whitespace()) - .count(); - (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) - } - _ => unreachable!(), - } - } -} - -pub struct FormatReport { - // Maps stringified file paths to their associated formatting errors. - file_error_map: HashMap>, -} - -impl FormatReport { - fn new() -> FormatReport { - FormatReport { - file_error_map: HashMap::new(), - } - } - - pub fn warning_count(&self) -> usize { - self.file_error_map - .iter() - .map(|(_, errors)| errors.len()) - .sum() - } - - pub fn has_warnings(&self) -> bool { - self.warning_count() > 0 - } - - pub fn print_warnings_fancy( - &self, - mut t: Box>, - ) -> Result<(), term::Error> { - for (file, errors) in &self.file_error_map { - for error in errors { - let prefix_space_len = error.line.to_string().len(); - let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); - - // First line: the overview of error - t.fg(term::color::RED)?; - t.attr(term::Attr::Bold)?; - write!(t, "{} ", error.msg_prefix())?; - t.reset()?; - t.attr(term::Attr::Bold)?; - write!(t, "{}\n", error.kind)?; - - // Second line: file info - write!(t, "{}--> ", &prefix_spaces[1..])?; - t.reset()?; - write!(t, "{}:{}\n", file, error.line)?; - - // Third to fifth lines: show the line which triggered error, if available. - if !error.line_buffer.is_empty() { - let (space_len, target_len) = error.format_len(); - t.attr(term::Attr::Bold)?; - write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; - t.reset()?; - write!(t, "{}\n", error.line_buffer)?; - t.attr(term::Attr::Bold)?; - write!(t, "{}| ", prefix_spaces)?; - t.fg(term::color::RED)?; - write!(t, "{}\n", target_str(space_len, target_len))?; - t.reset()?; - } - - // The last line: show note if available. - let msg_suffix = error.msg_suffix(); - if !msg_suffix.is_empty() { - t.attr(term::Attr::Bold)?; - write!(t, "{}= note: ", prefix_spaces)?; - t.reset()?; - write!(t, "{}\n", error.msg_suffix())?; - } else { - write!(t, "\n")?; - } - t.reset()?; - } - } - - if !self.file_error_map.is_empty() { - t.attr(term::Attr::Bold)?; - write!(t, "warning: ")?; - t.reset()?; - write!( - t, - "rustfmt may have failed to format. See previous {} errors.\n\n", - self.warning_count(), - )?; - } - - Ok(()) - } -} - -fn target_str(space_len: usize, target_len: usize) -> String { - let empty_line: String = repeat(" ").take(space_len).collect(); - let overflowed: String = repeat("^").take(target_len).collect(); - empty_line + &overflowed -} - -impl fmt::Display for FormatReport { - // Prints all the formatting errors. - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - for (file, errors) in &self.file_error_map { - for error in errors { - let prefix_space_len = error.line.to_string().len(); - let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); - - let error_line_buffer = if error.line_buffer.is_empty() { - String::from(" ") - } else { - let (space_len, target_len) = error.format_len(); - format!( - "{}|\n{} | {}\n{}| {}", - prefix_spaces, - error.line, - error.line_buffer, - prefix_spaces, - target_str(space_len, target_len) - ) - }; - - let error_info = format!("{} {}", error.msg_prefix(), error.kind); - let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line); - let msg_suffix = error.msg_suffix(); - let note = if msg_suffix.is_empty() { - String::new() - } else { - format!("{}note= ", prefix_spaces) - }; - - write!( - fmt, - "{}\n{}\n{}\n{}{}\n", - error_info, - file_info, - error_line_buffer, - note, - error.msg_suffix() - )?; - } - } - if !self.file_error_map.is_empty() { - write!( - fmt, - "warning: rustfmt may have failed to format. See previous {} errors.\n", - self.warning_count(), - )?; - } - Ok(()) - } -} - -// Formatting which depends on the AST. -fn format_ast( - krate: &ast::Crate, - parse_session: &mut ParseSess, - main_file: &FileName, - config: &Config, - mut after_file: F, -) -> Result<(FileMap, bool), io::Error> -where - F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result, -{ - let mut result = FileMap::new(); - // diff mode: check if any files are differing - let mut has_diff = false; - - // We always skip children for the "Plain" write mode, since there is - // nothing to distinguish the nested module contents. - let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; - for (path, module) in modules::list_files(krate, parse_session.codemap())? { - if skip_children && path != *main_file { - continue; - } - if config.verbose() { - println!("Formatting {}", path); - } - let filemap = parse_session - .codemap() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == *main_file { - visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, &*filemap); - } - } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); - visitor.format_separate_mod(module, &*filemap); - }; - - assert_eq!( - visitor.line_number, - ::utils::count_newlines(&format!("{}", visitor.buffer)) - ); - - let filename = path.clone(); - has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) { - Ok(result) => result, - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg)); - } - }; - - result.push((filename, visitor.buffer)); - } - - Ok((result, has_diff)) -} - -/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`. -fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { - skipped_range - .iter() - .any(|&(lo, hi)| lo <= line_number && line_number <= hi) -} - -fn should_report_error( - config: &Config, - char_kind: FullCodeCharKind, - is_string: bool, - error_kind: ErrorKind, -) -> bool { - let allow_error_report = if char_kind.is_comment() || is_string { - config.error_on_unformatted() - } else { - true - }; - - match error_kind { - ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, - ErrorKind::TrailingWhitespace => allow_error_report, - _ => true, - } -} - -// Formatting done on a char by char or line by line basis. -// FIXME(#209) warn on bad license -// FIXME(#20) other stuff for parity with make tidy -fn format_lines( - text: &mut String, - name: &FileName, - skipped_range: &[(usize, usize)], - config: &Config, - report: &mut FormatReport, -) { - // Iterate over the chars in the file map. - let mut trims = vec![]; - let mut last_wspace: Option = None; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); - let mut line_buffer = String::with_capacity(config.max_width() * 2); - let mut is_string = false; // true if the current line contains a string literal. - let mut format_line = config.file_lines().contains_line(name, cur_line); - - for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { - if c == '\r' { - continue; - } - - if format_line { - // Add warnings for bad todos/ fixmes - if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } - } - - if c == '\n' { - if format_line { - // Check for (and record) trailing whitespace. - if let Some(..) = last_wspace { - if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) { - trims.push((cur_line, kind, line_buffer.clone())); - } - line_len -= 1; - } - - // Check for any line width errors we couldn't correct. - let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); - if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) - && should_report_error(config, kind, is_string, error_kind) - { - errors.push(FormattingError { - line: cur_line, - kind: error_kind, - is_comment: kind.is_comment(), - is_string, - line_buffer: line_buffer.clone(), - }); - } - } - - line_len = 0; - cur_line += 1; - format_line = config.file_lines().contains_line(name, cur_line); - newline_count += 1; - last_wspace = None; - line_buffer.clear(); - is_string = false; - } else { - newline_count = 0; - line_len += if c == '\t' { config.tab_spaces() } else { 1 }; - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(b); - } - } else { - last_wspace = None; - } - line_buffer.push(c); - if kind.is_string() { - is_string = true; - } - } - } - - if newline_count > 1 { - debug!("track truncate: {} {}", text.len(), newline_count); - let line = text.len() - newline_count + 1; - text.truncate(line); - } - - for &(l, kind, ref b) in &trims { - if !is_skipped_line(l, skipped_range) { - errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - is_comment: kind.is_comment(), - is_string: kind.is_string(), - line_buffer: b.clone(), - }); - } - } - - report.file_error_map.insert(name.clone(), errors); -} - -fn parse_input( - input: Input, - parse_session: &ParseSess, -) -> Result> { - let result = match input { - Input::File(file) => { - let mut parser = parse::new_parser_from_file(parse_session, &file); - parser.cfg_mods = false; - parser.parse_crate_mod() - } - Input::Text(text) => { - let mut parser = parse::new_parser_from_source_str( - parse_session, - FileName::Custom("stdin".to_owned()), - text, - ); - parser.cfg_mods = false; - parser.parse_crate_mod() - } - }; - - match result { - Ok(c) => { - if parse_session.span_diagnostic.has_errors() { - // Bail out if the parser recovered from an error. - Err(None) - } else { - Ok(c) - } - } - Err(e) => Err(Some(e)), - } -} - -/// Format the given snippet. The snippet is expected to be *complete* code. -/// When we cannot parse the given snippet, this function returns `None`. -pub fn format_snippet(snippet: &str, config: &Config) -> Option { - let mut out: Vec = Vec::with_capacity(snippet.len() * 2); - let input = Input::Text(snippet.into()); - let mut config = config.clone(); - config.set().write_mode(config::WriteMode::Plain); - config.set().hide_parse_errors(true); - match format_input(input, &config, Some(&mut out)) { - // `format_input()` returns an empty string on parsing error. - Ok(..) if out.is_empty() && !snippet.is_empty() => None, - Ok(..) => String::from_utf8(out).ok(), - Err(..) => None, - } -} - -/// Format the given code block. Mainly targeted for code block in comment. -/// The code block may be incomplete (i.e. parser may be unable to parse it). -/// To avoid panic in parser, we wrap the code block with a dummy function. -/// The returned code block does *not* end with newline. -pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { - // Wrap the given code block with `fn main()` if it does not have one. - let fn_main_prefix = "fn main() {\n"; - let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}"; - - // Trim "fn main() {" on the first line and "}" on the last line, - // then unindent the whole code block. - format_snippet(&snippet, config).map(|s| { - // 2 = "}\n" - s[fn_main_prefix.len()..s.len().checked_sub(2).unwrap_or(0)] - .lines() - .map(|line| { - if line.len() > config.tab_spaces() { - // Make sure that the line has leading whitespaces. - let indent_str = - Indent::from_width(config, config.tab_spaces()).to_string(config); - if line.starts_with(indent_str.as_ref()) { - let offset = if config.hard_tabs() { - 1 - } else { - config.tab_spaces() - }; - &line[offset..] - } else { - line - } - } else { - line - } - }) - .collect::>() - .join("\n") - }) -} - -pub fn format_input( - input: Input, - config: &Config, - mut out: Option<&mut T>, -) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { - let mut summary = Summary::default(); - if config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err((e, summary)); - } - } - return Ok((summary, FileMap::new(), FormatReport::new())); - } - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - - let tty_handler = if config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - Handler::with_emitter(true, false, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) - }; - let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Custom("stdin".to_owned()), - }; - - let krate = match parse_input(input, &parse_session) { - Ok(krate) => krate, - Err(diagnostic) => { - if let Some(mut diagnostic) = diagnostic { - diagnostic.emit(); - } - summary.add_parsing_error(); - return Ok((summary, FileMap::new(), FormatReport::new())); - } - }; - - summary.mark_parse_time(); - - if parse_session.span_diagnostic.has_errors() { - summary.add_parsing_error(); - } - - // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - - let mut report = FormatReport::new(); - - let format_result = format_ast( - &krate, - &mut parse_session, - &main_file, - config, - |file_name, file, skipped_range| { - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(file); - - format_lines(file, file_name, skipped_range, config, &mut report); - - if let Some(ref mut out) = out { - return filemap::write_file(file, file_name, out, config); - } - Ok(false) - }, - ); - - summary.mark_format_time(); - - if config.verbose() { - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 - } - - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(summary.get_parse_time().unwrap()), - duration_to_f32(summary.get_format_time().unwrap()), - ); - } - - match format_result { - Ok((file_map, has_diff)) => { - if report.has_warnings() { - summary.add_formatting_error(); - } - - if has_diff { - summary.add_diff(); - } - - Ok((summary, file_map, report)) - } - Err(e) => Err((e, summary)), - } -} - -#[derive(Debug)] -pub enum Input { - File(PathBuf), - Text(String), -} - -pub fn run(input: Input, config: &Config) -> Summary { - let out = &mut stdout(); - output_header(out, config.write_mode()).ok(); - match format_input(input, config, Some(out)) { - Ok((summary, _, report)) => { - output_footer(out, config.write_mode()).ok(); - - if report.has_warnings() { - match term::stderr() { - Some(ref t) - if use_colored_tty(config.color()) && t.supports_color() - && t.supports_attr(term::Attr::Bold) => - { - match report.print_warnings_fancy(term::stderr().unwrap()) { - Ok(..) => (), - Err(..) => panic!("Unable to write to stderr: {}", report), - } - } - _ => msg!("{}", report), - } - } - - summary - } - Err((msg, mut summary)) => { - msg!("Error writing files: {}", msg); - summary.add_operational_error(); - summary - } - } -} - -#[cfg(test)] -mod test { - use super::{format_code_block, format_snippet, Config}; - - #[test] - fn test_no_panic_on_format_snippet_and_format_code_block() { - // `format_snippet()` and `format_code_block()` should not panic - // even when we cannot parse the given snippet. - let snippet = "let"; - assert!(format_snippet(snippet, &Config::default()).is_none()); - assert!(format_code_block(snippet, &Config::default()).is_none()); - } - - fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool - where - F: Fn(&str, &Config) -> Option, - { - let output = formatter(input, &Config::default()); - output.is_some() && output.unwrap() == expected - } - - #[test] - fn test_format_snippet() { - let snippet = "fn main() { println!(\"hello, world\"); }"; - let expected = "fn main() {\n \ - println!(\"hello, world\");\n\ - }\n"; - assert!(test_format_inner(format_snippet, snippet, expected)); - } - - #[test] - fn test_format_code_block() { - // simple code block - let code_block = "let x=3;"; - let expected = "let x = 3;"; - assert!(test_format_inner(format_code_block, code_block, expected)); - - // more complex code block, taken from chains.rs. - let code_block = -"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { -( -chain_indent(context, shape.add_offset(parent_rewrite.len())), -context.config.indent_style() == IndentStyle::Visual || is_small_parent, -) -} else if is_block_expr(context, &parent, &parent_rewrite) { -match context.config.indent_style() { -// Try to put the first child on the same line with parent's last line -IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), -// The parent is a block, so align the rest of the chain with the closing -// brace. -IndentStyle::Visual => (parent_shape, false), -} -} else { -( -chain_indent(context, shape.add_offset(parent_rewrite.len())), -false, -) -}; -"; - let expected = -"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.indent_style() == IndentStyle::Visual || is_small_parent, - ) -} else if is_block_expr(context, &parent, &parent_rewrite) { - match context.config.indent_style() { - // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), - // The parent is a block, so align the rest of the chain with the closing - // brace. - IndentStyle::Visual => (parent_shape, false), - } -} else { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - false, - ) -};"; - assert!(test_format_inner(format_code_block, code_block, expected)); - } -} diff --git a/src/lists.rs b/src/lists.rs deleted file mode 100644 index aa1e0b430ef..00000000000 --- a/src/lists.rs +++ /dev/null @@ -1,857 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp; -use std::iter::Peekable; - -use syntax::codemap::{BytePos, CodeMap}; - -use comment::{find_comment_end, rewrite_comment, FindUncommented}; -use config::{Config, IndentStyle}; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; -use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; - -/// Formatting tactic for lists. This will be cast down to a -/// `DefinitiveListTactic` depending on the number and length of the items and -/// their comments. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum ListTactic { - // One item per row. - Vertical, - // All items on one row. - Horizontal, - // Try Horizontal layout, if that fails then vertical. - HorizontalVertical, - // HorizontalVertical with a soft limit of n characters. - LimitedHorizontalVertical(usize), - // Pack as many items as possible per row over (possibly) many rows. - Mixed, -} - -impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); - -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum SeparatorTactic { - Always, - Never, - Vertical, -} - -impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); - -impl SeparatorTactic { - pub fn from_bool(b: bool) -> SeparatorTactic { - if b { - SeparatorTactic::Always - } else { - SeparatorTactic::Never - } - } -} - -pub struct ListFormatting<'a> { - pub tactic: DefinitiveListTactic, - pub separator: &'a str, - pub trailing_separator: SeparatorTactic, - pub separator_place: SeparatorPlace, - pub shape: Shape, - // Non-expressions, e.g. items, will have a new line at the end of the list. - // Important for comment styles. - pub ends_with_newline: bool, - // Remove newlines between list elements for expressions. - pub preserve_newline: bool, - pub config: &'a Config, -} - -impl<'a> ListFormatting<'a> { - pub fn needs_trailing_separator(&self) -> bool { - match self.trailing_separator { - // We always put separator in front. - SeparatorTactic::Always => true, - SeparatorTactic::Vertical => self.tactic == DefinitiveListTactic::Vertical, - SeparatorTactic::Never => { - self.tactic == DefinitiveListTactic::Vertical && self.separator_place.is_front() - } - } - } -} - -impl AsRef for ListItem { - fn as_ref(&self) -> &ListItem { - self - } -} - -#[derive(PartialEq, Eq)] -pub enum ListItemCommentStyle { - // Try to keep the comment on the same line with the item. - SameLine, - // Put the comment on the previous or the next line of the item. - DifferentLine, - // No comment available. - None, -} - -pub struct ListItem { - // None for comments mean that they are not present. - pub pre_comment: Option, - pub pre_comment_style: ListItemCommentStyle, - // Item should include attributes and doc comments. None indicates a failed - // rewrite. - pub item: Option, - pub post_comment: Option, - // Whether there is extra whitespace before this item. - pub new_lines: bool, -} - -impl ListItem { - pub fn inner_as_ref(&self) -> &str { - self.item.as_ref().map_or("", |s| s) - } - - pub fn is_different_group(&self) -> bool { - self.inner_as_ref().contains('\n') || self.pre_comment.is_some() - || self.post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) - } - - pub fn is_multiline(&self) -> bool { - self.inner_as_ref().contains('\n') - || self.pre_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) - || self.post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) - } - - pub fn has_comment(&self) -> bool { - self.pre_comment - .as_ref() - .map_or(false, |comment| comment.trim_left().starts_with("//")) - || self.post_comment - .as_ref() - .map_or(false, |comment| comment.trim_left().starts_with("//")) - } - - pub fn from_str>(s: S) -> ListItem { - ListItem { - pre_comment: None, - pre_comment_style: ListItemCommentStyle::None, - item: Some(s.into()), - post_comment: None, - new_lines: false, - } - } -} - -/// The definitive formatting tactic for lists. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum DefinitiveListTactic { - Vertical, - Horizontal, - Mixed, - /// Special case tactic for `format!()`, `write!()` style macros. - SpecialMacro(usize), -} - -impl DefinitiveListTactic { - pub fn ends_with_newline(&self, indent_style: IndentStyle) -> bool { - match indent_style { - IndentStyle::Block => *self != DefinitiveListTactic::Horizontal, - IndentStyle::Visual => false, - } - } -} - -/// The type of separator for lists. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum Separator { - Comma, - VerticalBar, -} - -impl Separator { - pub fn len(&self) -> usize { - match *self { - // 2 = `, ` - Separator::Comma => 2, - // 3 = ` | ` - Separator::VerticalBar => 3, - } - } -} - -/// Where to put separator. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum SeparatorPlace { - Front, - Back, -} - -impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); - -impl SeparatorPlace { - pub fn is_front(&self) -> bool { - *self == SeparatorPlace::Front - } - - pub fn is_back(&self) -> bool { - *self == SeparatorPlace::Back - } - - pub fn from_tactic( - default: SeparatorPlace, - tactic: DefinitiveListTactic, - sep: &str, - ) -> SeparatorPlace { - match tactic { - DefinitiveListTactic::Vertical => default, - _ => if sep == "," { - SeparatorPlace::Back - } else { - default - }, - } - } -} - -pub fn definitive_tactic( - items: I, - tactic: ListTactic, - sep: Separator, - width: usize, -) -> DefinitiveListTactic -where - I: IntoIterator + Clone, - T: AsRef, -{ - let pre_line_comments = items - .clone() - .into_iter() - .any(|item| item.as_ref().has_comment()); - - let limit = match tactic { - _ if pre_line_comments => return DefinitiveListTactic::Vertical, - ListTactic::Mixed => return DefinitiveListTactic::Mixed, - ListTactic::Horizontal => return DefinitiveListTactic::Horizontal, - ListTactic::Vertical => return DefinitiveListTactic::Vertical, - ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit), - ListTactic::HorizontalVertical => width, - }; - - let (sep_count, total_width) = calculate_width(items.clone()); - let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); - let real_total = total_width + total_sep_len; - - if real_total <= limit && !pre_line_comments - && !items.into_iter().any(|item| item.as_ref().is_multiline()) - { - DefinitiveListTactic::Horizontal - } else { - DefinitiveListTactic::Vertical - } -} - -// Format a list of commented items into a string. -// TODO: add unit tests -pub fn write_list(items: I, formatting: &ListFormatting) -> Option -where - I: IntoIterator + Clone, - T: AsRef, -{ - let tactic = formatting.tactic; - let sep_len = formatting.separator.len(); - - // Now that we know how we will layout, we can decide for sure if there - // will be a trailing separator. - let mut trailing_separator = formatting.needs_trailing_separator(); - let mut result = String::with_capacity(128); - let cloned_items = items.clone(); - let mut iter = items.into_iter().enumerate().peekable(); - let mut item_max_width: Option = None; - let sep_place = - SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); - - let mut line_len = 0; - let indent_str = &formatting.shape.indent.to_string(formatting.config); - while let Some((i, item)) = iter.next() { - let item = item.as_ref(); - let inner_item = item.item.as_ref()?; - let first = i == 0; - let last = iter.peek().is_none(); - let mut separate = match sep_place { - SeparatorPlace::Front => !first, - SeparatorPlace::Back => !last || trailing_separator, - }; - let item_sep_len = if separate { sep_len } else { 0 }; - - // Item string may be multi-line. Its length (used for block comment alignment) - // should be only the length of the last line. - let item_last_line = if item.is_multiline() { - inner_item.lines().last().unwrap_or("") - } else { - inner_item.as_ref() - }; - let mut item_last_line_width = item_last_line.len() + item_sep_len; - if item_last_line.starts_with(&**indent_str) { - item_last_line_width -= indent_str.len(); - } - - match tactic { - DefinitiveListTactic::Horizontal if !first => { - result.push(' '); - } - DefinitiveListTactic::SpecialMacro(num_args_before) => { - if i == 0 { - // Nothing - } else if i < num_args_before { - result.push(' '); - } else if i <= num_args_before + 1 { - result.push('\n'); - result.push_str(indent_str); - } else { - result.push(' '); - } - } - DefinitiveListTactic::Vertical if !first => { - result.push('\n'); - result.push_str(indent_str); - } - DefinitiveListTactic::Mixed => { - let total_width = total_item_width(item) + item_sep_len; - - // 1 is space between separator and item. - if line_len > 0 && line_len + 1 + total_width > formatting.shape.width { - result.push('\n'); - result.push_str(indent_str); - line_len = 0; - if formatting.ends_with_newline { - if last { - separate = true; - } else { - trailing_separator = true; - } - } - } - - if line_len > 0 { - result.push(' '); - line_len += 1; - } - - line_len += total_width; - } - _ => {} - } - - // Pre-comments - if let Some(ref comment) = item.pre_comment { - // Block style in non-vertical mode. - let block_mode = tactic != DefinitiveListTactic::Vertical; - // Width restriction is only relevant in vertical mode. - let comment = - rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; - result.push_str(&comment); - - if tactic == DefinitiveListTactic::Vertical { - // We cannot keep pre-comments on the same line if the comment if normalized. - let keep_comment = if formatting.config.normalize_comments() - || item.pre_comment_style == ListItemCommentStyle::DifferentLine - { - false - } else { - // We will try to keep the comment on the same line with the item here. - // 1 = ` ` - let total_width = total_item_width(item) + item_sep_len + 1; - total_width <= formatting.shape.width - }; - if keep_comment { - result.push(' '); - } else { - result.push('\n'); - result.push_str(indent_str); - } - } else { - result.push(' '); - } - item_max_width = None; - } - - if separate && sep_place.is_front() && !first { - result.push_str(formatting.separator.trim()); - result.push(' '); - } - result.push_str(&inner_item[..]); - - // Post-comments - if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { - let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = rewrite_comment( - comment, - true, - Shape::legacy(formatting.shape.width, Indent::empty()), - formatting.config, - )?; - - result.push(' '); - result.push_str(&formatted_comment); - } - - if separate && sep_place.is_back() { - result.push_str(formatting.separator); - } - - if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { - let comment = item.post_comment.as_ref().unwrap(); - let overhead = last_line_width(&result) + first_line_width(comment.trim()); - - let rewrite_post_comment = |item_max_width: &mut Option| { - if item_max_width.is_none() && !last && !inner_item.contains('\n') { - *item_max_width = Some(max_width_of_item_with_post_comment( - &cloned_items, - i, - overhead, - formatting.config.max_width(), - )); - } - let overhead = if starts_with_newline(comment) { - 0 - } else if let Some(max_width) = *item_max_width { - max_width + 2 - } else { - // 1 = space between item and comment. - item_last_line_width + 1 - }; - let width = formatting.shape.width.checked_sub(overhead).unwrap_or(1); - let offset = formatting.shape.indent + overhead; - let comment_shape = Shape::legacy(width, offset); - - // Use block-style only for the last item or multiline comments. - let block_style = !formatting.ends_with_newline && last - || comment.trim().contains('\n') - || comment.trim().len() > width; - - rewrite_comment( - comment.trim_left(), - block_style, - comment_shape, - formatting.config, - ) - }; - - let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; - - if !starts_with_newline(comment) { - let mut comment_alignment = - post_comment_alignment(item_max_width, inner_item.len()); - if first_line_width(&formatted_comment) + last_line_width(&result) - + comment_alignment + 1 > formatting.config.max_width() - { - item_max_width = None; - formatted_comment = rewrite_post_comment(&mut item_max_width)?; - comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); - } - for _ in 0..(comment_alignment + 1) { - result.push(' '); - } - // An additional space for the missing trailing separator. - if last && item_max_width.is_some() && !separate && !formatting.separator.is_empty() - { - result.push(' '); - } - } else { - result.push('\n'); - result.push_str(indent_str); - } - if formatted_comment.contains('\n') { - item_max_width = None; - } - result.push_str(&formatted_comment); - } else { - item_max_width = None; - } - - if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical - && item.new_lines - { - item_max_width = None; - result.push('\n'); - } - } - - Some(result) -} - -fn max_width_of_item_with_post_comment( - items: &I, - i: usize, - overhead: usize, - max_budget: usize, -) -> usize -where - I: IntoIterator + Clone, - T: AsRef, -{ - let mut max_width = 0; - let mut first = true; - for item in items.clone().into_iter().skip(i) { - let item = item.as_ref(); - let inner_item_width = item.inner_as_ref().len(); - if !first - && (item.is_different_group() || !item.post_comment.is_some() - || inner_item_width + overhead > max_budget) - { - return max_width; - } - if max_width < inner_item_width { - max_width = inner_item_width; - } - if item.new_lines { - return max_width; - } - first = false; - } - max_width -} - -fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { - item_max_width - .and_then(|max_line_width| max_line_width.checked_sub(inner_item_len)) - .unwrap_or(0) -} - -pub struct ListItems<'a, I, F1, F2, F3> -where - I: Iterator, -{ - codemap: &'a CodeMap, - inner: Peekable, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - prev_span_end: BytePos, - next_span_start: BytePos, - terminator: &'a str, - separator: &'a str, - leave_last: bool, -} - -impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> -where - I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option, -{ - type Item = ListItem; - - fn next(&mut self) -> Option { - let white_space: &[_] = &[' ', '\t']; - - self.inner.next().map(|item| { - let mut new_lines = false; - // Pre-comment - let pre_snippet = self.codemap - .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) - .unwrap(); - let trimmed_pre_snippet = pre_snippet.trim(); - let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); - let has_block_comment = trimmed_pre_snippet.starts_with("/*"); - let (pre_comment, pre_comment_style) = if has_single_line_comment { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else if has_block_comment { - let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); - if pre_snippet - .chars() - .rev() - .take(comment_end + 1) - .any(|c| c == '\n') - { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::SameLine, - ) - } - } else { - (None, ListItemCommentStyle::None) - }; - - // Post-comment - let next_start = match self.inner.peek() { - Some(next_item) => (self.get_lo)(next_item), - None => self.next_span_start, - }; - let post_snippet = self.codemap - .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let mut block_open_index = post_snippet.find("/*"); - // check if it really is a block comment (and not `//*` or a nested comment) - if let Some(i) = block_open_index { - match post_snippet.find('/') { - Some(j) if j < i => block_open_index = None, - _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, - _ => (), - } - } - let newline_index = post_snippet.find('\n'); - if let Some(separator_index) = post_snippet.find_uncommented(self.separator) { - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => separator_index + 1, - // Block-style post-comment before the separator. - (Some(i), None) => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Potential *single* line comment. - (_, Some(j)) if j > separator_index => j + 1, - _ => post_snippet.len(), - } - } else if let Some(newline_index) = newline_index { - // Match arms may not have trailing comma. In any case, for match arms, - // we will assume that the post comment belongs to the next arm if they - // do not end with trailing comma. - newline_index + 1 - } else { - 0 - } - } - None => post_snippet - .find_uncommented(self.terminator) - .unwrap_or_else(|| post_snippet.len()), - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet - .find('\n') - .unwrap_or_else(|| test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet - .find(|c: char| !c.is_whitespace()) - .unwrap_or_else(|| test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if count_newlines(test_snippet) > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; - } - } - - // Cleanup post-comment: strip separators and whitespace. - self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); - - let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { - post_snippet - }; - - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; - - ListItem { - pre_comment, - pre_comment_style, - item: if self.inner.peek().is_none() && self.leave_last { - None - } else { - (self.get_item_string)(&item) - }, - post_comment, - new_lines, - } - }) - } -} - -// Creates an iterator over a list's items with associated comments. -pub fn itemize_list<'a, T, I, F1, F2, F3>( - codemap: &'a CodeMap, - inner: I, - terminator: &'a str, - separator: &'a str, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - prev_span_end: BytePos, - next_span_start: BytePos, - leave_last: bool, -) -> ListItems<'a, I, F1, F2, F3> -where - I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option, -{ - ListItems { - codemap, - inner: inner.peekable(), - get_lo, - get_hi, - get_item_string, - prev_span_end, - next_span_start, - terminator, - separator, - leave_last, - } -} - -/// Returns the count and total width of the list items. -fn calculate_width(items: I) -> (usize, usize) -where - I: IntoIterator, - T: AsRef, -{ - items - .into_iter() - .map(|item| total_item_width(item.as_ref())) - .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) -} - -pub fn total_item_width(item: &ListItem) -> usize { - comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) - + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) - + item.item.as_ref().map_or(0, |str| str.len()) -} - -fn comment_len(comment: Option<&str>) -> usize { - match comment { - Some(s) => { - let text_len = s.trim().len(); - if text_len > 0 { - // We'll put " /*" before and " */" after inline comments. - text_len + 6 - } else { - text_len - } - } - None => 0, - } -} - -// Compute horizontal and vertical shapes for a struct-lit-like thing. -pub fn struct_lit_shape( - shape: Shape, - context: &RewriteContext, - prefix_width: usize, - suffix_width: usize, -) -> Option<(Option, Shape)> { - let v_shape = match context.config.indent_style() { - IndentStyle::Visual => shape - .visual_indent(0) - .shrink_left(prefix_width)? - .sub_width(suffix_width)?, - IndentStyle::Block => { - let shape = shape.block_indent(context.config.tab_spaces()); - Shape { - width: context.budget(shape.indent.width()), - ..shape - } - } - }; - let shape_width = shape.width.checked_sub(prefix_width + suffix_width); - if let Some(w) = shape_width { - let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); - Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) - } else { - Some((None, v_shape)) - } -} - -// Compute the tactic for the internals of a struct-lit-like thing. -pub fn struct_lit_tactic( - h_shape: Option, - context: &RewriteContext, - items: &[ListItem], -) -> DefinitiveListTactic { - if let Some(h_shape) = h_shape { - let prelim_tactic = match (context.config.indent_style(), items.len()) { - (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ if context.config.struct_lit_single_line() => ListTactic::HorizontalVertical, - _ => ListTactic::Vertical, - }; - definitive_tactic(items, prelim_tactic, Separator::Comma, h_shape.width) - } else { - DefinitiveListTactic::Vertical - } -} - -// Given a tactic and possible shapes for horizontal and vertical layout, -// come up with the actual shape to use. -pub fn shape_for_tactic( - tactic: DefinitiveListTactic, - h_shape: Option, - v_shape: Shape, -) -> Shape { - match tactic { - DefinitiveListTactic::Horizontal => h_shape.unwrap(), - _ => v_shape, - } -} - -// Create a ListFormatting object for formatting the internals of a -// struct-lit-like thing, that is a series of fields. -pub fn struct_lit_formatting<'a>( - shape: Shape, - tactic: DefinitiveListTactic, - context: &'a RewriteContext, - force_no_trailing_comma: bool, -) -> ListFormatting<'a> { - let ends_with_newline = context.config.indent_style() != IndentStyle::Visual - && tactic == DefinitiveListTactic::Vertical; - ListFormatting { - tactic, - separator: ",", - trailing_separator: if force_no_trailing_comma { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline, - preserve_newline: true, - config: context.config, - } -} diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index 3abfe6239fd..00000000000 --- a/src/macros.rs +++ /dev/null @@ -1,871 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Format list-like macro invocations. These are invocations whose token trees -// can be interpreted as expressions and separated by commas. -// Note that these token trees do not actually have to be interpreted as -// expressions by the compiler. An example of an invocation we would reformat is -// foo!( x, y, z ). The token x may represent an identifier in the code, but we -// interpreted as an expression. -// Macro uses which are not-list like, such as bar!(key => val), will not be -// reformatted. -// List-like invocations with parentheses will be formatted as function calls, -// and those with brackets will be formatted as array literals. - -use std::collections::HashMap; -use syntax::ast; -use syntax::codemap::{BytePos, Span}; -use syntax::parse::new_parser_from_tts; -use syntax::parse::parser::Parser; -use syntax::parse::token::{BinOpToken, DelimToken, Token}; -use syntax::print::pprust; -use syntax::symbol; -use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; -use syntax::util::ThinVec; - -use codemap::SpanUtils; -use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; -use expr::{rewrite_array, rewrite_call_inner}; -use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, - SeparatorTactic}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use utils::{format_visibility, mk_sp}; - -const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; - -// FIXME: use the enum from libsyntax? -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -enum MacroStyle { - Parens, - Brackets, - Braces, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum MacroPosition { - Item, - Statement, - Expression, - Pat, -} - -impl MacroStyle { - fn opener(&self) -> &'static str { - match *self { - MacroStyle::Parens => "(", - MacroStyle::Brackets => "[", - MacroStyle::Braces => "{", - } - } -} - -#[derive(Debug)] -pub enum MacroArg { - Expr(ast::Expr), - Ty(ast::Ty), - Pat(ast::Pat), -} - -impl Rewrite for MacroArg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - MacroArg::Expr(ref expr) => expr.rewrite(context, shape), - MacroArg::Ty(ref ty) => ty.rewrite(context, shape), - MacroArg::Pat(ref pat) => pat.rewrite(context, shape), - } - } -} - -fn parse_macro_arg(parser: &mut Parser) -> Option { - macro_rules! parse_macro_arg { - ($macro_arg: ident, $parser: ident) => { - let mut cloned_parser = (*parser).clone(); - match cloned_parser.$parser() { - Ok(x) => { - if parser.sess.span_diagnostic.has_errors() { - parser.sess.span_diagnostic.reset_err_count(); - } else { - // Parsing succeeded. - *parser = cloned_parser; - return Some(MacroArg::$macro_arg((*x).clone())); - } - } - Err(mut e) => { - e.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - } - } - }; - } - - parse_macro_arg!(Expr, parse_expr); - parse_macro_arg!(Ty, parse_ty); - parse_macro_arg!(Pat, parse_pat); - - None -} - -pub fn rewrite_macro( - mac: &ast::Mac, - extra_ident: Option, - context: &RewriteContext, - shape: Shape, - position: MacroPosition, -) -> Option { - let context = &mut context.clone(); - context.inside_macro = true; - if context.config.use_try_shorthand() { - if let Some(expr) = convert_try_mac(mac, context) { - context.inside_macro = false; - return expr.rewrite(context, shape); - } - } - - let original_style = macro_style(mac, context); - - let macro_name = match extra_ident { - None => format!("{}!", mac.node.path), - Some(ident) => { - if ident == symbol::keywords::Invalid.ident() { - format!("{}!", mac.node.path) - } else { - format!("{}! {}", mac.node.path, ident) - } - } - }; - - let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { - MacroStyle::Brackets - } else { - original_style - }; - - let ts: TokenStream = mac.node.stream(); - if ts.is_empty() && !contains_comment(context.snippet(mac.span)) { - return match style { - MacroStyle::Parens if position == MacroPosition::Item => { - Some(format!("{}();", macro_name)) - } - MacroStyle::Parens => Some(format!("{}()", macro_name)), - MacroStyle::Brackets => Some(format!("{}[]", macro_name)), - MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), - }; - } - - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - let mut arg_vec = Vec::new(); - let mut vec_with_semi = false; - let mut trailing_comma = false; - - if MacroStyle::Braces != style { - loop { - match parse_macro_arg(&mut parser) { - Some(arg) => arg_vec.push(arg), - None => return Some(context.snippet(mac.span).to_owned()), - } - - match parser.token { - Token::Eof => break, - Token::Comma => (), - Token::Semi => { - // Try to parse `vec![expr; expr]` - if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { - parser.bump(); - if parser.token != Token::Eof { - match parse_macro_arg(&mut parser) { - Some(arg) => { - arg_vec.push(arg); - parser.bump(); - if parser.token == Token::Eof && arg_vec.len() == 2 { - vec_with_semi = true; - break; - } - } - None => return Some(context.snippet(mac.span).to_owned()), - } - } - } - return Some(context.snippet(mac.span).to_owned()); - } - _ => return Some(context.snippet(mac.span).to_owned()), - } - - parser.bump(); - - if parser.token == Token::Eof { - trailing_comma = true; - break; - } - } - } - - match style { - MacroStyle::Parens => { - // Format macro invocation as function call, forcing no trailing - // comma because not all macros support them. - rewrite_call_inner( - context, - ¯o_name, - &arg_vec.iter().map(|e| &*e).collect::>()[..], - mac.span, - shape, - context.config.width_heuristics().fn_call_width, - trailing_comma, - ).map(|rw| match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - }) - } - MacroStyle::Brackets => { - let mac_shape = shape.offset_left(macro_name.len())?; - // Handle special case: `vec![expr; expr]` - if vec_with_semi { - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - // 6 = `vec!` + `; ` - let total_overhead = lbr.len() + rbr.len() + 6; - let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = arg_vec[0].rewrite(context, nested_shape)?; - let rhs = arg_vec[1].rewrite(context, nested_shape)?; - if !lhs.contains('\n') && !rhs.contains('\n') - && lhs.len() + rhs.len() + total_overhead <= shape.width - { - Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) - } else { - Some(format!( - "{}{}\n{}{};\n{}{}\n{}{}", - macro_name, - lbr, - nested_shape.indent.to_string(context.config), - lhs, - nested_shape.indent.to_string(context.config), - rhs, - shape.indent.to_string(context.config), - rbr - )) - } - } else { - // If we are rewriting `vec!` macro or other special macros, - // then we can rewrite this as an usual array literal. - // Otherwise, we must preserve the original existence of trailing comma. - if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { - context.inside_macro = false; - trailing_comma = false; - } - // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. - let sp = mk_sp( - context - .codemap - .span_after(mac.span, original_style.opener()), - mac.span.hi() - BytePos(1), - ); - let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; - let rewrite = rewrite_array(arg_vec, sp, context, mac_shape, trailing_comma)?; - - Some(format!("{}{}", macro_name, rewrite)) - } - } - MacroStyle::Braces => { - // Skip macro invocations with braces, for now. - indent_macro_snippet(context, context.snippet(mac.span), shape.indent) - } - } -} - -pub fn rewrite_macro_def( - context: &RewriteContext, - shape: Shape, - indent: Indent, - def: &ast::MacroDef, - ident: ast::Ident, - vis: &ast::Visibility, - span: Span, -) -> Option { - let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); - - let mut parser = MacroParser::new(def.stream().into_trees()); - let parsed_def = match parser.parse() { - Some(def) => def, - None => return snippet, - }; - - let mut result = if def.legacy { - String::from("macro_rules!") - } else { - format!("{}macro", format_visibility(vis)) - }; - - result += " "; - result += &ident.name.as_str(); - - let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; - - let arm_shape = if multi_branch_style { - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - } else { - shape - }; - - let branch_items = itemize_list( - context.codemap, - parsed_def.branches.iter(), - "}", - ";", - |branch| branch.span.lo(), - |branch| branch.span.hi(), - |branch| branch.rewrite(context, arm_shape, multi_branch_style), - context.codemap.span_after(span, "{"), - span.hi(), - false, - ).collect::>(); - - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: if def.legacy { ";" } else { "" }, - trailing_separator: SeparatorTactic::Always, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - - if multi_branch_style { - result += " {\n"; - result += &arm_shape.indent.to_string(context.config); - } - - result += write_list(&branch_items, &fmt)?.as_str(); - - if multi_branch_style { - result += "\n"; - result += &indent.to_string(context.config); - result += "}"; - } - - Some(result) -} - -// Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we -// aren't causing problems. -// This should also work for escaped `$` variables, where we leave earlier `$`s. -fn replace_names(input: &str) -> Option<(String, HashMap)> { - // Each substitution will require five or six extra bytes. - let mut result = String::with_capacity(input.len() + 64); - let mut substs = HashMap::new(); - let mut dollar_count = 0; - let mut cur_name = String::new(); - - for c in input.chars() { - if c == '$' { - dollar_count += 1; - } else if dollar_count == 0 { - result.push(c); - } else if !c.is_alphanumeric() && !cur_name.is_empty() { - // Terminates a name following one or more dollars. - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); - - result.push(c); - - dollar_count = 0; - cur_name = String::new(); - } else if c == '(' && cur_name.is_empty() { - // FIXME: Support macro def with repeat. - return None; - } else if c.is_alphanumeric() { - cur_name.push(c); - } - } - - // FIXME: duplicate code - if !cur_name.is_empty() { - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); - } - - debug!("replace_names `{}` {:?}", result, substs); - - Some((result, substs)) -} - -// This is a bit sketchy. The token rules probably need tweaking, but it works -// for some common cases. I hope the basic logic is sufficient. Note that the -// meaning of some tokens is a bit different here from usual Rust, e.g., `*` -// and `(`/`)` have special meaning. -// -// We always try and format on one line. -fn format_macro_args(toks: ThinTokenStream) -> Option { - let mut result = String::with_capacity(128); - let mut insert_space = SpaceState::Never; - - for tok in (toks.into(): TokenStream).trees() { - match tok { - TokenTree::Token(_, t) => { - if !result.is_empty() && force_space_before(&t) { - insert_space = SpaceState::Always; - } - if force_no_space_before(&t) { - insert_space = SpaceState::Never; - } - match (insert_space, ident_like(&t)) { - (SpaceState::Always, _) - | (SpaceState::Punctuation, false) - | (SpaceState::Ident, true) => { - result.push(' '); - } - _ => {} - } - result.push_str(&pprust::token_to_string(&t)); - insert_space = next_space(&t); - } - TokenTree::Delimited(_, d) => { - if let SpaceState::Always = insert_space { - result.push(' '); - } - let formatted = format_macro_args(d.tts)?; - match d.delim { - DelimToken::Paren => { - result.push_str(&format!("({})", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::Bracket => { - result.push_str(&format!("[{}]", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::Brace => { - result.push_str(&format!(" {{ {} }}", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::NoDelim => { - result.push_str(&format!("{}", formatted)); - insert_space = SpaceState::Always; - } - } - } - } - } - - Some(result) -} - -// We should insert a space if the next token is a: -#[derive(Copy, Clone)] -enum SpaceState { - Never, - Punctuation, - Ident, // Or ident/literal-like thing. - Always, -} - -fn force_space_before(tok: &Token) -> bool { - match *tok { - Token::Eq - | Token::Lt - | Token::Le - | Token::EqEq - | Token::Ne - | Token::Ge - | Token::Gt - | Token::AndAnd - | Token::OrOr - | Token::Not - | Token::Tilde - | Token::BinOpEq(_) - | Token::At - | Token::RArrow - | Token::LArrow - | Token::FatArrow - | Token::Pound - | Token::Dollar => true, - Token::BinOp(bot) => bot != BinOpToken::Star, - _ => false, - } -} - -fn force_no_space_before(tok: &Token) -> bool { - match *tok { - Token::Semi | Token::Comma | Token::Dot => true, - Token::BinOp(bot) => bot == BinOpToken::Star, - _ => false, - } -} -fn ident_like(tok: &Token) -> bool { - match *tok { - Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, - _ => false, - } -} - -fn next_space(tok: &Token) -> SpaceState { - match *tok { - Token::Not - | Token::Tilde - | Token::At - | Token::Comma - | Token::Dot - | Token::DotDot - | Token::DotDotDot - | Token::DotDotEq - | Token::DotEq - | Token::Question - | Token::Underscore - | Token::BinOp(_) => SpaceState::Punctuation, - - Token::ModSep - | Token::Pound - | Token::Dollar - | Token::OpenDelim(_) - | Token::CloseDelim(_) - | Token::Whitespace => SpaceState::Never, - - Token::Literal(..) | Token::Ident(_) | Token::Lifetime(_) => SpaceState::Ident, - - _ => SpaceState::Always, - } -} - -/// Tries to convert a macro use into a short hand try expression. Returns None -/// when the macro is not an instance of try! (or parsing the inner expression -/// failed). -pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { - if &format!("{}", mac.node.path)[..] == "try" { - let ts: TokenStream = mac.node.tts.clone().into(); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - - Some(ast::Expr { - id: ast::NodeId::new(0), // dummy value - node: ast::ExprKind::Try(parser.parse_expr().ok()?), - span: mac.span, // incorrect span, but shouldn't matter too much - attrs: ThinVec::new(), - }) - } else { - None - } -} - -fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { - let snippet = context.snippet(mac.span); - let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); - let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); - let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); - - if paren_pos < bracket_pos && paren_pos < brace_pos { - MacroStyle::Parens - } else if bracket_pos < brace_pos { - MacroStyle::Brackets - } else { - MacroStyle::Braces - } -} - -/// Indent each line according to the specified `indent`. -/// e.g. -/// ```rust -/// foo!{ -/// x, -/// y, -/// foo( -/// a, -/// b, -/// c, -/// ), -/// } -/// ``` -/// will become -/// ```rust -/// foo!{ -/// x, -/// y, -/// foo( -/// a, -/// b, -/// c, -// ), -/// } -/// ``` -fn indent_macro_snippet( - context: &RewriteContext, - macro_str: &str, - indent: Indent, -) -> Option { - let mut lines = macro_str.lines(); - let first_line = lines.next().map(|s| s.trim_right())?; - let mut trimmed_lines = Vec::with_capacity(16); - - let min_prefix_space_width = lines - .filter_map(|line| { - let prefix_space_width = if is_empty_line(line) { - None - } else { - Some(get_prefix_space_width(context, line)) - }; - trimmed_lines.push((line.trim(), prefix_space_width)); - prefix_space_width - }) - .min()?; - - Some( - String::from(first_line) + "\n" - + &trimmed_lines - .iter() - .map(|&(line, prefix_space_width)| match prefix_space_width { - Some(original_indent_width) => { - let new_indent_width = indent.width() - + original_indent_width - .checked_sub(min_prefix_space_width) - .unwrap_or(0); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) - } - None => String::new(), - }) - .collect::>() - .join("\n"), - ) -} - -fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { - let mut width = 0; - for c in s.chars() { - match c { - ' ' => width += 1, - '\t' => width += context.config.tab_spaces(), - _ => return width, - } - } - width -} - -fn is_empty_line(s: &str) -> bool { - s.is_empty() || s.chars().all(char::is_whitespace) -} - -// A very simple parser that just parses a macros 2.0 definition into its branches. -// Currently we do not attempt to parse any further than that. -#[derive(new)] -struct MacroParser { - toks: Cursor, -} - -impl MacroParser { - // (`(` ... `)` `=>` `{` ... `}`)* - fn parse(&mut self) -> Option { - let mut branches = vec![]; - while self.toks.look_ahead(1).is_some() { - branches.push(self.parse_branch()?); - } - - Some(Macro { branches }) - } - - // `(` ... `)` `=>` `{` ... `}` - fn parse_branch(&mut self) -> Option { - let tok = self.toks.next()?; - let (lo, args_paren_kind) = match tok { - TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, ref d) => (sp.lo(), d.delim), - }; - let args = tok.joint().into(); - match self.toks.next()? { - TokenTree::Token(_, Token::FatArrow) => {} - _ => return None, - } - let (mut hi, body) = match self.toks.next()? { - TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, _) => { - let data = sp.data(); - ( - data.hi, - Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), - ) - } - }; - if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { - self.toks.next(); - hi = sp.hi(); - } - Some(MacroBranch { - span: mk_sp(lo, hi), - args_paren_kind, - args, - body, - }) - } -} - -// A parsed macros 2.0 macro definition. -struct Macro { - branches: Vec, -} - -// FIXME: it would be more efficient to use references to the token streams -// rather than clone them, if we can make the borrowing work out. -struct MacroBranch { - span: Span, - args_paren_kind: DelimToken, - args: ThinTokenStream, - body: Span, -} - -impl MacroBranch { - fn rewrite( - &self, - context: &RewriteContext, - shape: Shape, - multi_branch_style: bool, - ) -> Option { - // Only attempt to format function-like macros. - if self.args_paren_kind != DelimToken::Paren { - // FIXME(#1539): implement for non-sugared macros. - return None; - } - - let mut result = format_macro_args(self.args.clone())?; - - if multi_branch_style { - result += " =>"; - } - - // The macro body is the most interesting part. It might end up as various - // AST nodes, but also has special variables (e.g, `$foo`) which can't be - // parsed as regular Rust code (and note that these can be escaped using - // `$$`). We'll try and format like an AST node, but we'll substitute - // variables for new names with the same length first. - - let old_body = context.snippet(self.body).trim(); - let (body_str, substs) = replace_names(old_body)?; - - let mut config = context.config.clone(); - config.set().hide_parse_errors(true); - - result += " {"; - - let has_block_body = old_body.starts_with('{'); - - let body_indent = if has_block_body { - shape.indent - } else { - // We'll hack the indent below, take this into account when formatting, - let body_indent = shape.indent.block_indent(&config); - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); - body_indent - }; - - // First try to format as items, then as statements. - let new_body = match ::format_snippet(&body_str, &config) { - Some(new_body) => new_body, - None => match ::format_code_block(&body_str, &config) { - Some(new_body) => new_body, - None => return None, - }, - }; - - // Indent the body since it is in a block. - let indent_str = body_indent.to_string(&config); - let mut new_body = new_body - .trim_right() - .lines() - .fold(String::new(), |mut s, l| { - if !l.is_empty() { - s += &indent_str; - } - s + l + "\n" - }); - - // Undo our replacement of macro variables. - // FIXME: this could be *much* more efficient. - for (old, new) in &substs { - if old_body.find(new).is_some() { - debug!("rewrite_macro_def: bailing matching variable: `{}`", new); - return None; - } - new_body = new_body.replace(new, old); - } - - if has_block_body { - result += new_body.trim(); - } else if !new_body.is_empty() { - result += "\n"; - result += &new_body; - result += &shape.indent.to_string(&config); - } - - result += "}"; - - Some(result) - } -} - -#[cfg(test)] -mod test { - use super::*; - use syntax::parse::{parse_stream_from_source_str, ParseSess}; - use syntax::codemap::{FileName, FilePathMapping}; - - fn format_macro_args_str(s: &str) -> String { - let input = parse_stream_from_source_str( - FileName::Custom("stdin".to_owned()), - s.to_owned(), - &ParseSess::new(FilePathMapping::empty()), - None, - ); - format_macro_args(input.into()).unwrap() - } - - #[test] - fn test_format_macro_args() { - assert_eq!(format_macro_args_str(""), "".to_owned()); - assert_eq!(format_macro_args_str("$ x : ident"), "$x: ident".to_owned()); - assert_eq!( - format_macro_args_str("$ m1 : ident , $ m2 : ident , $ x : ident"), - "$m1: ident, $m2: ident, $x: ident".to_owned() - ); - assert_eq!( - format_macro_args_str("$($beginning:ident),*;$middle:ident;$($end:ident),*"), - "$($beginning: ident),*; $middle: ident; $($end: ident),*".to_owned() - ); - assert_eq!( - format_macro_args_str( - "$ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) *" - ), - "$name: ident($($dol: tt $var: ident)*) $($body: tt)*".to_owned() - ); - } -} diff --git a/src/missed_spans.rs b/src/missed_spans.rs deleted file mode 100644 index dff6b94bd75..00000000000 --- a/src/missed_spans.rs +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; -use std::iter::repeat; - -use syntax::codemap::{BytePos, FileName, Pos, Span}; - -use codemap::LineRangeUtils; -use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; -use config::WriteMode; -use shape::{Indent, Shape}; -use utils::{count_newlines, last_line_width, mk_sp}; -use visitor::FmtVisitor; - -struct SnippetStatus { - /// An offset to the current line from the beginnig of the original snippet. - line_start: usize, - /// A length of trailing whitespaces on the current line. - last_wspace: Option, - /// The current line number. - cur_line: usize, -} - -impl SnippetStatus { - fn new(cur_line: usize) -> Self { - SnippetStatus { - line_start: 0, - last_wspace: None, - cur_line, - } - } -} - -impl<'a> FmtVisitor<'a> { - fn output_at_start(&self) -> bool { - self.buffer.is_empty() - } - - // TODO these format_missing methods are ugly. Refactor and add unit tests - // for the central whitespace stripping loop. - pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) - } - - pub fn format_missing_with_indent(&mut self, end: BytePos) { - let config = self.config; - self.format_missing_inner(end, |this, last_snippet, snippet| { - this.push_str(last_snippet.trim_right()); - if last_snippet == snippet && !this.output_at_start() { - // No new lines in the snippet. - this.push_str("\n"); - } - let indent = this.block_indent.to_string(config); - this.push_str(&indent); - }) - } - - pub fn format_missing_no_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| { - this.push_str(last_snippet.trim_right()); - }) - } - - fn format_missing_inner( - &mut self, - end: BytePos, - process_last_snippet: F, - ) { - let start = self.last_pos; - - if start == end { - // Do nothing if this is the beginning of the file. - if !self.output_at_start() { - process_last_snippet(self, "", ""); - } - return; - } - - assert!( - start < end, - "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end) - ); - - self.last_pos = end; - let span = mk_sp(start, end); - let snippet = self.snippet(span); - if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { - // Keep vertical spaces within range. - self.push_vertical_spaces(count_newlines(snippet)); - process_last_snippet(self, "", snippet); - } else { - self.write_snippet(span, &process_last_snippet); - } - } - - fn push_vertical_spaces(&mut self, mut newline_count: usize) { - // The buffer already has a trailing newline. - let offset = if self.buffer.ends_with('\n') { 0 } else { 1 }; - let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; - let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; - if newline_count > newline_upper_bound { - newline_count = newline_upper_bound; - } else if newline_count < newline_lower_bound { - newline_count = newline_lower_bound; - } - let blank_lines: String = repeat('\n').take(newline_count).collect(); - self.push_str(&blank_lines); - } - - fn write_snippet(&mut self, span: Span, process_last_snippet: F) - where - F: Fn(&mut FmtVisitor, &str, &str), - { - // Get a snippet from the file start to the span's hi without allocating. - // We need it to determine what precedes the current comment. If the comment - // follows code on the same line, we won't touch it. - let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos; - let local_begin = self.codemap.lookup_byte_offset(big_span_lo); - let local_end = self.codemap.lookup_byte_offset(span.hi()); - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; - - let big_diff = (span.lo() - big_span_lo).to_usize(); - let snippet = self.snippet(span); - - debug!("write_snippet `{}`", snippet); - - self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); - } - - fn write_snippet_inner( - &mut self, - big_snippet: &str, - big_diff: usize, - old_snippet: &str, - span: Span, - process_last_snippet: F, - ) where - F: Fn(&mut FmtVisitor, &str, &str), - { - // Trim whitespace from the right hand side of each line. - // Annoyingly, the library functions for splitting by lines etc. are not - // quite right, so we must do it ourselves. - let char_pos = self.codemap.lookup_char_pos(span.lo()); - let file_name = &char_pos.file.name; - let mut status = SnippetStatus::new(char_pos.line); - - let snippet = &*match self.config.write_mode() { - WriteMode::Coverage => replace_chars(old_snippet), - _ => Cow::from(old_snippet), - }; - - for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { - debug!("{:?}: {:?}", kind, subslice); - - let newline_count = count_newlines(subslice); - let within_file_lines_range = self.config.file_lines().intersects_range( - file_name, - status.cur_line, - status.cur_line + newline_count, - ); - - if CodeCharKind::Comment == kind && within_file_lines_range { - // 1: comment. - self.process_comment( - &mut status, - snippet, - &big_snippet[..(offset + big_diff)], - offset, - subslice, - ); - } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range { - // 2: blank lines. - self.push_vertical_spaces(newline_count); - status.cur_line += newline_count; - status.line_start = offset + newline_count; - } else { - // 3: code which we failed to format or which is not within file-lines range. - self.process_missing_code(&mut status, snippet, subslice, offset, file_name); - } - } - - process_last_snippet(self, &snippet[status.line_start..], snippet); - } - - fn process_comment( - &mut self, - status: &mut SnippetStatus, - snippet: &str, - big_snippet: &str, - offset: usize, - subslice: &str, - ) { - let last_char = big_snippet - .chars() - .rev() - .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) - .next(); - - let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - - let comment_indent = if fix_indent { - if let Some('{') = last_char { - self.push_str("\n"); - } - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - self.block_indent - } else { - self.push_str(" "); - Indent::from_width(self.config, last_line_width(&self.buffer)) - }; - - let comment_width = ::std::cmp::min( - self.config.comment_width(), - self.config.max_width() - self.block_indent.width(), - ); - let comment_shape = Shape::legacy(comment_width, comment_indent); - let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) - .unwrap_or_else(|| String::from(subslice)); - self.push_str(&comment_str); - - status.last_wspace = None; - status.line_start = offset + subslice.len(); - - if let Some('/') = subslice.chars().nth(1) { - // check that there are no contained block comments - if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() >= 2 && &s[0..2] == "/*") - { - // Add a newline after line comments - self.push_str("\n"); - } - } else if status.line_start <= snippet.len() { - // For other comments add a newline if there isn't one at the end already - match snippet[status.line_start..].chars().next() { - Some('\n') | Some('\r') => (), - _ => self.push_str("\n"), - } - } - - status.cur_line += count_newlines(subslice); - } - - fn process_missing_code( - &mut self, - status: &mut SnippetStatus, - snippet: &str, - subslice: &str, - offset: usize, - file_name: &FileName, - ) { - for (mut i, c) in subslice.char_indices() { - i += offset; - - if c == '\n' { - let skip_this_line = !self.config - .file_lines() - .contains_line(file_name, status.cur_line); - if skip_this_line { - status.last_wspace = None; - } - - if let Some(lw) = status.last_wspace { - self.push_str(&snippet[status.line_start..lw]); - self.push_str("\n"); - status.last_wspace = None; - } else { - self.push_str(&snippet[status.line_start..i + 1]); - } - - status.cur_line += 1; - status.line_start = i + 1; - } else if c.is_whitespace() && status.last_wspace.is_none() { - status.last_wspace = Some(i); - } else if c == ';' && status.last_wspace.is_some() { - status.line_start = i; - status.last_wspace = None; - } else { - status.last_wspace = None; - } - } - - let remaining = snippet[status.line_start..subslice.len() + offset].trim(); - if !remaining.is_empty() { - self.push_str(remaining); - status.line_start = subslice.len() + offset; - } - } -} - -fn replace_chars(string: &str) -> Cow { - Cow::from( - string - .chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect::(), - ) -} diff --git a/src/modules.rs b/src/modules.rs deleted file mode 100644 index 0f439910324..00000000000 --- a/src/modules.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::collections::BTreeMap; -use std::io; -use std::path::{Path, PathBuf}; - -use syntax::ast; -use syntax::codemap::{self, FileName}; -use syntax::parse::parser; - -use utils::contains_skip; - -/// List all the files containing modules of a crate. -/// If a file is used twice in a crate, it appears only once. -pub fn list_files<'a>( - krate: &'a ast::Crate, - codemap: &codemap::CodeMap, -) -> Result, io::Error> { - let mut result = BTreeMap::new(); // Enforce file order determinism - let root_filename = codemap.span_to_filename(krate.span); - { - let parent = match root_filename { - FileName::Real(ref path) => path.parent().unwrap(), - _ => Path::new(""), - }; - list_submodules(&krate.module, parent, codemap, &mut result)?; - } - result.insert(root_filename, &krate.module); - Ok(result) -} - -/// Recursively list all external modules included in a module. -fn list_submodules<'a>( - module: &'a ast::Mod, - search_dir: &Path, - codemap: &codemap::CodeMap, - result: &mut BTreeMap, -) -> Result<(), io::Error> { - debug!("list_submodules: search_dir: {:?}", search_dir); - for item in &module.items { - if let ast::ItemKind::Mod(ref sub_mod) = item.node { - if !contains_skip(&item.attrs) { - let is_internal = - codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); - let dir_path = if is_internal { - search_dir.join(&item.ident.to_string()) - } else { - let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; - let dir_path = mod_path.parent().unwrap().to_owned(); - result.insert(FileName::Real(mod_path), sub_mod); - dir_path - }; - list_submodules(sub_mod, &dir_path, codemap, result)?; - } - } - } - Ok(()) -} - -/// Find the file corresponding to an external mod -fn module_file( - id: ast::Ident, - attrs: &[ast::Attribute], - dir_path: &Path, - codemap: &codemap::CodeMap, -) -> Result { - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { - return Ok(path); - } - - match parser::Parser::default_submod_path(id, None, dir_path, codemap).result { - Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), - Err(_) => Err(io::Error::new( - io::ErrorKind::Other, - format!("Couldn't find module {}", id), - )), - } -} diff --git a/src/patterns.rs b/src/patterns.rs deleted file mode 100644 index 4719160061b..00000000000 --- a/src/patterns.rs +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; -use syntax::codemap::{self, BytePos, Span}; -use syntax::ptr; - -use codemap::SpanUtils; -use comment::FindUncommented; -use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, - wrap_struct_field, PairParts}; -use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic}; -use macros::{rewrite_macro, MacroPosition}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use spanned::Spanned; -use types::{rewrite_path, PathContext}; -use utils::{format_mutability, mk_sp}; - -impl Rewrite for Pat { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), - PatKind::Ident(binding_mode, ident, ref sub_pat) => { - let (prefix, mutability) = match binding_mode { - BindingMode::ByRef(mutability) => ("ref ", mutability), - BindingMode::ByValue(mutability) => ("", mutability), - }; - let mut_infix = format_mutability(mutability); - let id_str = ident.node.to_string(); - let sub_pat = match *sub_pat { - Some(ref p) => { - // 3 - ` @ `. - let width = shape - .width - .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?; - format!( - " @ {}", - p.rewrite(context, Shape::legacy(width, shape.indent))? - ) - } - None => "".to_owned(), - }; - - Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) - } - PatKind::Wild => { - if 1 <= shape.width { - Some("_".to_owned()) - } else { - None - } - } - PatKind::Range(ref lhs, ref rhs, ref end_kind) => { - let infix = match *end_kind { - RangeEnd::Included(RangeSyntax::DotDotDot) => "...", - RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", - RangeEnd::Excluded => "..", - }; - let infix = if context.config.spaces_around_ranges() { - format!(" {} ", infix) - } else { - infix.to_owned() - }; - rewrite_pair( - &**lhs, - &**rhs, - PairParts::new("", &infix, ""), - context, - shape, - SeparatorPlace::Front, - ) - } - PatKind::Ref(ref pat, mutability) => { - let prefix = format!("&{}", format_mutability(mutability)); - rewrite_unary_prefix(context, &prefix, &**pat, shape) - } - PatKind::Tuple(ref items, dotdot_pos) => { - rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) - } - PatKind::Path(ref q_self, ref path) => { - rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) - } - PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { - let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; - rewrite_tuple_pat( - pat_vec, - dotdot_pos, - Some(path_str), - self.span, - context, - shape, - ) - } - PatKind::Lit(ref expr) => expr.rewrite(context, shape), - PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { - // Rewrite all the sub-patterns. - let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = slice_pat - .as_ref() - .map(|p| Some(format!("{}..", p.rewrite(context, shape)?))); - let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); - - // Munge them together. - let pats: Option> = - prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); - - // Check that all the rewrites succeeded, and if not return None. - let pats = pats?; - - // Unwrap all the sub-strings and join them with commas. - let result = if context.config.spaces_within_parens_and_brackets() { - format!("[ {} ]", pats.join(", ")) - } else { - format!("[{}]", pats.join(", ")) - }; - Some(result) - } - PatKind::Struct(ref path, ref fields, ellipsis) => { - rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) - } - PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), - } - } -} - -fn rewrite_struct_pat( - path: &ast::Path, - fields: &[codemap::Spanned], - ellipsis: bool, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - // 2 = ` {` - let path_shape = shape.sub_width(2)?; - let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - - if fields.is_empty() && !ellipsis { - return Some(format!("{} {{}}", path_str)); - } - - let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") }; - - // 3 = ` { `, 2 = ` }`. - let (h_shape, v_shape) = - struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?; - - let items = itemize_list( - context.codemap, - fields.iter(), - terminator, - ",", - |f| f.span.lo(), - |f| f.span.hi(), - |f| f.node.rewrite(context, v_shape), - context.codemap.span_after(span, "{"), - span.hi(), - false, - ); - let item_vec = items.collect::>(); - - let tactic = struct_lit_tactic(h_shape, context, &item_vec); - let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); - let fmt = struct_lit_formatting(nested_shape, tactic, context, false); - - let mut fields_str = write_list(&item_vec, &fmt)?; - let one_line_width = h_shape.map_or(0, |shape| shape.width); - - if ellipsis { - if fields_str.contains('\n') || fields_str.len() > one_line_width { - // Add a missing trailing comma. - if fmt.trailing_separator == SeparatorTactic::Never { - fields_str.push_str(","); - } - fields_str.push_str("\n"); - fields_str.push_str(&nested_shape.indent.to_string(context.config)); - fields_str.push_str(".."); - } else { - if !fields_str.is_empty() { - // there are preceding struct fields being matched on - if fmt.tactic == DefinitiveListTactic::Vertical { - // if the tactic is Vertical, write_list already added a trailing , - fields_str.push_str(" "); - } else { - fields_str.push_str(", "); - } - } - fields_str.push_str(".."); - } - } - - let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); - Some(format!("{} {{{}}}", path_str, fields_str)) -} - -impl Rewrite for FieldPat { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let pat = self.pat.rewrite(context, shape); - if self.is_shorthand { - pat - } else { - let pat_str = pat?; - let id_str = self.ident.to_string(); - let one_line_width = id_str.len() + 2 + pat_str.len(); - if one_line_width <= shape.width { - Some(format!("{}: {}", id_str, pat_str)) - } else { - let nested_shape = shape.block_indent(context.config.tab_spaces()); - let pat_str = self.pat.rewrite(context, nested_shape)?; - Some(format!( - "{}:\n{}{}", - id_str, - nested_shape.indent.to_string(context.config), - pat_str, - )) - } - } - } -} - -pub enum TuplePatField<'a> { - Pat(&'a ptr::P), - Dotdot(Span), -} - -impl<'a> Rewrite for TuplePatField<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - TuplePatField::Pat(p) => p.rewrite(context, shape), - TuplePatField::Dotdot(_) => Some("..".to_string()), - } - } -} - -impl<'a> Spanned for TuplePatField<'a> { - fn span(&self) -> Span { - match *self { - TuplePatField::Pat(p) => p.span(), - TuplePatField::Dotdot(span) => span, - } - } -} - -pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { - match *pat { - TuplePatField::Pat(pat) => match pat.node { - ast::PatKind::Path(..) - | ast::PatKind::Tuple(..) - | ast::PatKind::Struct(..) - | ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, - ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { - can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) - } - ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), - _ => false, - }, - TuplePatField::Dotdot(..) => false, - } -} - -fn rewrite_tuple_pat( - pats: &[ptr::P], - dotdot_pos: Option, - path_str: Option, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); - - if let Some(pos) = dotdot_pos { - let prev = if pos == 0 { - span.lo() - } else { - pats[pos - 1].span().hi() - }; - let next = if pos + 1 >= pats.len() { - span.hi() - } else { - pats[pos + 1].span().lo() - }; - let dot_span = mk_sp(prev, next); - let snippet = context.snippet(dot_span); - let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32); - let dotdot = TuplePatField::Dotdot(Span::new( - lo, - // 2 == "..".len() - lo + BytePos(2), - codemap::NO_EXPANSION, - )); - pat_vec.insert(pos, dotdot); - } - - if pat_vec.is_empty() { - return Some(format!("{}()", path_str.unwrap_or_default())); - } - - let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); - let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 - { - let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; - let sp = pat_vec[new_item_count - 1].span(); - let snippet = context.snippet(sp); - let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); - ( - &pat_vec[..new_item_count], - mk_sp(span.lo(), lo + BytePos(1)), - ) - } else { - (&pat_vec[..], span) - }; - - // add comma if `(x,)` - let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); - let mut context = context.clone(); - if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { - context.inside_macro = true; - } - let path_str = path_str.unwrap_or_default(); - let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); - for pat in pat_vec { - pat_ref_vec.push(pat); - } - - rewrite_call_inner( - &context, - &path_str, - &pat_ref_vec[..], - span, - shape, - shape.width, - add_comma, - ) -} - -fn count_wildcard_suffix_len( - context: &RewriteContext, - patterns: &[TuplePatField], - span: Span, - shape: Shape, -) -> usize { - let mut suffix_len = 0; - - let items: Vec<_> = itemize_list( - context.codemap, - patterns.iter(), - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, shape), - context.codemap.span_after(span, "("), - span.hi() - BytePos(1), - false, - ).collect(); - - for item in items.iter().rev().take_while(|i| match i.item { - Some(ref internal_string) if internal_string == "_" => true, - _ => false, - }) { - suffix_len += 1; - - if item.pre_comment.is_some() || item.post_comment.is_some() { - break; - } - } - - suffix_len -} diff --git a/src/rewrite.rs b/src/rewrite.rs deleted file mode 100644 index 708e31d86dd..00000000000 --- a/src/rewrite.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A generic trait to abstract the rewriting of an element (of the AST). - -use syntax::codemap::{CodeMap, Span}; -use syntax::parse::ParseSess; - -use config::{Config, IndentStyle}; -use shape::Shape; -use visitor::SnippetProvider; - -pub trait Rewrite { - /// Rewrite self into shape. - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; -} - -#[derive(Clone)] -pub struct RewriteContext<'a> { - pub parse_session: &'a ParseSess, - pub codemap: &'a CodeMap, - pub config: &'a Config, - pub inside_macro: bool, - // Force block indent style even if we are using visual indent style. - pub use_block: bool, - // When `format_if_else_cond_comment` is true, unindent the comment on top - // of the `else` or `else if`. - pub is_if_else_block: bool, - // When rewriting chain, veto going multi line except the last element - pub force_one_line_chain: bool, - pub snippet_provider: &'a SnippetProvider<'a>, -} - -impl<'a> RewriteContext<'a> { - pub fn snippet(&self, span: Span) -> &str { - self.snippet_provider.span_to_snippet(span).unwrap() - } - - /// Return true if we should use block indent style for rewriting function call. - pub fn use_block_indent(&self) -> bool { - self.config.indent_style() == IndentStyle::Block || self.use_block - } - - pub fn budget(&self, used_width: usize) -> usize { - self.config.max_width().checked_sub(used_width).unwrap_or(0) - } -} diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs deleted file mode 100644 index 1a2f570f89e..00000000000 --- a/src/rustfmt_diff.rs +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use config::Color; -use diff; -use std::collections::VecDeque; -use std::io; -use term; -use utils::use_colored_tty; - -#[derive(Debug, PartialEq)] -pub enum DiffLine { - Context(String), - Expected(String), - Resulting(String), -} - -#[derive(Debug, PartialEq)] -pub struct Mismatch { - pub line_number: u32, - pub lines: Vec, -} - -impl Mismatch { - fn new(line_number: u32) -> Mismatch { - Mismatch { - line_number, - lines: Vec::new(), - } - } -} - -// This struct handles writing output to stdout and abstracts away the logic -// of printing in color, if it's possible in the executing environment. -pub struct OutputWriter { - terminal: Option>>, -} - -impl OutputWriter { - // Create a new OutputWriter instance based on the caller's preference - // for colorized output and the capabilities of the terminal. - pub fn new(color: Color) -> Self { - if let Some(t) = term::stdout() { - if use_colored_tty(color) && t.supports_color() { - return OutputWriter { terminal: Some(t) }; - } - } - OutputWriter { terminal: None } - } - - // Write output in the optionally specified color. The output is written - // in the specified color if this OutputWriter instance contains a - // Terminal in its `terminal` field. - pub fn writeln(&mut self, msg: &str, color: Option) { - match &mut self.terminal { - Some(ref mut t) => { - if let Some(color) = color { - t.fg(color).unwrap(); - } - writeln!(t, "{}", msg).unwrap(); - if color.is_some() { - t.reset().unwrap(); - } - } - None => println!("{}", msg), - } - } -} - -// Produces a diff between the expected output and actual output of rustfmt. -pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { - let mut line_number = 1; - let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); - let mut lines_since_mismatch = context_size + 1; - let mut results = Vec::new(); - let mut mismatch = Mismatch::new(0); - - for result in diff::lines(expected, actual) { - match result { - diff::Result::Left(str) => { - if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { - results.push(mismatch); - mismatch = Mismatch::new(line_number - context_queue.len() as u32); - } - - while let Some(line) = context_queue.pop_front() { - mismatch.lines.push(DiffLine::Context(line.to_owned())); - } - - mismatch.lines.push(DiffLine::Resulting(str.to_owned())); - lines_since_mismatch = 0; - } - diff::Result::Right(str) => { - if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { - results.push(mismatch); - mismatch = Mismatch::new(line_number - context_queue.len() as u32); - } - - while let Some(line) = context_queue.pop_front() { - mismatch.lines.push(DiffLine::Context(line.to_owned())); - } - - mismatch.lines.push(DiffLine::Expected(str.to_owned())); - line_number += 1; - lines_since_mismatch = 0; - } - diff::Result::Both(str, _) => { - if context_queue.len() >= context_size { - let _ = context_queue.pop_front(); - } - - if lines_since_mismatch < context_size { - mismatch.lines.push(DiffLine::Context(str.to_owned())); - } else if context_size > 0 { - context_queue.push_back(str); - } - - line_number += 1; - lines_since_mismatch += 1; - } - } - } - - results.push(mismatch); - results.remove(0); - - results -} - -pub fn print_diff(diff: Vec, get_section_title: F, color: Color) -where - F: Fn(u32) -> String, -{ - let mut writer = OutputWriter::new(color); - - for mismatch in diff { - let title = get_section_title(mismatch.line_number); - writer.writeln(&format!("{}", title), None); - - for line in mismatch.lines { - match line { - DiffLine::Context(ref str) => writer.writeln(&format!(" {}⏎", str), None), - DiffLine::Expected(ref str) => { - writer.writeln(&format!("+{}⏎", str), Some(term::color::GREEN)) - } - DiffLine::Resulting(ref str) => { - writer.writeln(&format!("-{}⏎", str), Some(term::color::RED)) - } - } - } - } -} - -#[cfg(test)] -mod test { - use super::{make_diff, Mismatch}; - use super::DiffLine::*; - - #[test] - fn diff_simple() { - let src = "one\ntwo\nthree\nfour\nfive\n"; - let dest = "one\ntwo\ntrois\nfour\nfive\n"; - let diff = make_diff(src, dest, 1); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 2, - lines: vec![ - Context("two".to_owned()), - Resulting("three".to_owned()), - Expected("trois".to_owned()), - Context("four".to_owned()), - ], - }, - ] - ); - } - - #[test] - fn diff_simple2() { - let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n"; - let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; - let diff = make_diff(src, dest, 1); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 2, - lines: vec![ - Context("two".to_owned()), - Resulting("three".to_owned()), - Expected("trois".to_owned()), - Context("four".to_owned()), - ], - }, - Mismatch { - line_number: 5, - lines: vec![ - Resulting("five".to_owned()), - Expected("cinq".to_owned()), - Context("six".to_owned()), - ], - }, - ] - ); - } - - #[test] - fn diff_zerocontext() { - let src = "one\ntwo\nthree\nfour\nfive\n"; - let dest = "one\ntwo\ntrois\nfour\nfive\n"; - let diff = make_diff(src, dest, 0); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 3, - lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], - }, - ] - ); - } - - #[test] - fn diff_trailing_newline() { - let src = "one\ntwo\nthree\nfour\nfive"; - let dest = "one\ntwo\nthree\nfour\nfive\n"; - let diff = make_diff(src, dest, 1); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 5, - lines: vec![Context("five".to_owned()), Expected("".to_owned())], - }, - ] - ); - } -} diff --git a/src/shape.rs b/src/shape.rs deleted file mode 100644 index 8fe2e2b18c0..00000000000 --- a/src/shape.rs +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; -use std::ops::{Add, Sub}; - -use Config; - -#[derive(Copy, Clone, Debug)] -pub struct Indent { - // Width of the block indent, in characters. Must be a multiple of - // Config::tab_spaces. - pub block_indent: usize, - // Alignment in characters. - pub alignment: usize, -} - -// INDENT_BUFFER.len() = 80 -const INDENT_BUFFER_LEN: usize = 80; -const INDENT_BUFFER: &str = - " "; -impl Indent { - pub fn new(block_indent: usize, alignment: usize) -> Indent { - Indent { - block_indent, - alignment, - } - } - - pub fn from_width(config: &Config, width: usize) -> Indent { - if config.hard_tabs() { - let tab_num = width / config.tab_spaces(); - let alignment = width % config.tab_spaces(); - Indent::new(config.tab_spaces() * tab_num, alignment) - } else { - Indent::new(width, 0) - } - } - - pub fn empty() -> Indent { - Indent::new(0, 0) - } - - pub fn block_only(&self) -> Indent { - Indent { - block_indent: self.block_indent, - alignment: 0, - } - } - - pub fn block_indent(mut self, config: &Config) -> Indent { - self.block_indent += config.tab_spaces(); - self - } - - pub fn block_unindent(mut self, config: &Config) -> Indent { - if self.block_indent < config.tab_spaces() { - Indent::new(self.block_indent, 0) - } else { - self.block_indent -= config.tab_spaces(); - self - } - } - - pub fn width(&self) -> usize { - self.block_indent + self.alignment - } - - pub fn to_string(&self, config: &Config) -> Cow<'static, str> { - let (num_tabs, num_spaces) = if config.hard_tabs() { - (self.block_indent / config.tab_spaces(), self.alignment) - } else { - (0, self.width()) - }; - let num_chars = num_tabs + num_spaces; - if num_tabs == 0 && num_chars <= INDENT_BUFFER_LEN { - Cow::from(&INDENT_BUFFER[0..num_chars]) - } else { - let mut indent = String::with_capacity(num_chars); - for _ in 0..num_tabs { - indent.push('\t') - } - for _ in 0..num_spaces { - indent.push(' ') - } - Cow::from(indent) - } - } -} - -impl Add for Indent { - type Output = Indent; - - fn add(self, rhs: Indent) -> Indent { - Indent { - block_indent: self.block_indent + rhs.block_indent, - alignment: self.alignment + rhs.alignment, - } - } -} - -impl Sub for Indent { - type Output = Indent; - - fn sub(self, rhs: Indent) -> Indent { - Indent::new( - self.block_indent - rhs.block_indent, - self.alignment - rhs.alignment, - ) - } -} - -impl Add for Indent { - type Output = Indent; - - fn add(self, rhs: usize) -> Indent { - Indent::new(self.block_indent, self.alignment + rhs) - } -} - -impl Sub for Indent { - type Output = Indent; - - fn sub(self, rhs: usize) -> Indent { - Indent::new(self.block_indent, self.alignment - rhs) - } -} - -#[derive(Copy, Clone, Debug)] -pub struct Shape { - pub width: usize, - // The current indentation of code. - pub indent: Indent, - // Indentation + any already emitted text on the first line of the current - // statement. - pub offset: usize, -} - -impl Shape { - /// `indent` is the indentation of the first line. The next lines - /// should begin with at least `indent` spaces (except backwards - /// indentation). The first line should not begin with indentation. - /// `width` is the maximum number of characters on the last line - /// (excluding `indent`). The width of other lines is not limited by - /// `width`. - /// Note that in reality, we sometimes use width for lines other than the - /// last (i.e., we are conservative). - // .......*-------* - // | | - // | *-* - // *-----| - // |<------------>| max width - // |<---->| indent - // |<--->| width - pub fn legacy(width: usize, indent: Indent) -> Shape { - Shape { - width, - indent, - offset: indent.alignment, - } - } - - pub fn indented(indent: Indent, config: &Config) -> Shape { - Shape { - width: config.max_width().checked_sub(indent.width()).unwrap_or(0), - indent, - offset: indent.alignment, - } - } - - pub fn with_max_width(&self, config: &Config) -> Shape { - Shape { - width: config - .max_width() - .checked_sub(self.indent.width()) - .unwrap_or(0), - ..*self - } - } - - pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { - Shape { - width, - indent, - offset, - } - } - - pub fn visual_indent(&self, extra_width: usize) -> Shape { - let alignment = self.offset + extra_width; - Shape { - width: self.width, - indent: Indent::new(self.indent.block_indent, alignment), - offset: alignment, - } - } - - pub fn block_indent(&self, extra_width: usize) -> Shape { - if self.indent.alignment == 0 { - Shape { - width: self.width, - indent: Indent::new(self.indent.block_indent + extra_width, 0), - offset: 0, - } - } else { - Shape { - width: self.width, - indent: self.indent + extra_width, - offset: self.indent.alignment + extra_width, - } - } - } - - pub fn block_left(&self, width: usize) -> Option { - self.block_indent(width).sub_width(width) - } - - pub fn add_offset(&self, extra_width: usize) -> Shape { - Shape { - offset: self.offset + extra_width, - ..*self - } - } - - pub fn block(&self) -> Shape { - Shape { - indent: self.indent.block_only(), - ..*self - } - } - - pub fn sub_width(&self, width: usize) -> Option { - Some(Shape { - width: self.width.checked_sub(width)?, - ..*self - }) - } - - pub fn shrink_left(&self, width: usize) -> Option { - Some(Shape { - width: self.width.checked_sub(width)?, - indent: self.indent + width, - offset: self.offset + width, - }) - } - - pub fn offset_left(&self, width: usize) -> Option { - self.add_offset(width).sub_width(width) - } - - pub fn used_width(&self) -> usize { - self.indent.block_indent + self.offset - } - - pub fn rhs_overhead(&self, config: &Config) -> usize { - config - .max_width() - .checked_sub(self.used_width() + self.width) - .unwrap_or(0) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn indent_add_sub() { - let indent = Indent::new(4, 8) + Indent::new(8, 12); - assert_eq!(12, indent.block_indent); - assert_eq!(20, indent.alignment); - - let indent = indent - Indent::new(4, 4); - assert_eq!(8, indent.block_indent); - assert_eq!(16, indent.alignment); - } - - #[test] - fn indent_add_sub_alignment() { - let indent = Indent::new(4, 8) + 4; - assert_eq!(4, indent.block_indent); - assert_eq!(12, indent.alignment); - - let indent = indent - 4; - assert_eq!(4, indent.block_indent); - assert_eq!(8, indent.alignment); - } - - #[test] - fn indent_to_string_spaces() { - let config = Config::default(); - let indent = Indent::new(4, 8); - - // 12 spaces - assert_eq!(" ", indent.to_string(&config)); - } - - #[test] - fn indent_to_string_hard_tabs() { - let mut config = Config::default(); - config.set().hard_tabs(true); - let indent = Indent::new(8, 4); - - // 2 tabs + 4 spaces - assert_eq!("\t\t ", indent.to_string(&config)); - } - - #[test] - fn shape_visual_indent() { - let config = Config::default(); - let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.visual_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(4, shape.indent.block_indent); - assert_eq!(28, shape.indent.alignment); - assert_eq!(28, shape.offset); - } - - #[test] - fn shape_block_indent_without_alignment() { - let config = Config::default(); - let indent = Indent::new(4, 0); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.block_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(24, shape.indent.block_indent); - assert_eq!(0, shape.indent.alignment); - assert_eq!(0, shape.offset); - } - - #[test] - fn shape_block_indent_with_alignment() { - let config = Config::default(); - let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.block_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(4, shape.indent.block_indent); - assert_eq!(28, shape.indent.alignment); - assert_eq!(28, shape.offset); - } -} diff --git a/src/spanned.rs b/src/spanned.rs deleted file mode 100644 index a431f3a544a..00000000000 --- a/src/spanned.rs +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::ast; -use syntax::codemap::Span; - -use macros::MacroArg; -use utils::{mk_sp, outer_attributes}; - -/// Spanned returns a span including attributes, if available. -pub trait Spanned { - fn span(&self) -> Span; -} - -macro_rules! span_with_attrs_lo_hi { - ($this: ident, $lo: expr, $hi: expr) => {{ - let attrs = outer_attributes(&$this.attrs); - if attrs.is_empty() { - mk_sp($lo, $hi) - } else { - mk_sp(attrs[0].span.lo(), $hi) - } - }}; -} - -macro_rules! span_with_attrs { - ($this: ident) => { - span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) - }; -} - -macro_rules! implement_spanned { - ($this: ty) => { - impl Spanned for $this { - fn span(&self) -> Span { - span_with_attrs!(self) - } - } - }; -} - -// Implement `Spanned` for structs with `attrs` field. -implement_spanned!(ast::Expr); -implement_spanned!(ast::Field); -implement_spanned!(ast::ForeignItem); -implement_spanned!(ast::Item); -implement_spanned!(ast::Local); -implement_spanned!(ast::TraitItem); -implement_spanned!(ast::ImplItem); - -impl Spanned for ast::Stmt { - fn span(&self) -> Span { - match self.node { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), - ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { - mk_sp(expr.span().lo(), self.span.hi()) - } - ast::StmtKind::Mac(ref mac) => { - let (_, _, ref attrs) = **mac; - if attrs.is_empty() { - self.span - } else { - mk_sp(attrs[0].span.lo(), self.span.hi()) - } - } - } - } -} - -impl Spanned for ast::Pat { - fn span(&self) -> Span { - self.span - } -} - -impl Spanned for ast::Ty { - fn span(&self) -> Span { - self.span - } -} - -impl Spanned for ast::Arm { - fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.pats[0].span.lo(), self.body.span.hi()) - } -} - -impl Spanned for ast::Arg { - fn span(&self) -> Span { - if ::items::is_named_arg(self) { - mk_sp(self.pat.span.lo(), self.ty.span.hi()) - } else { - self.ty.span - } - } -} - -impl Spanned for ast::GenericParam { - fn span(&self) -> Span { - match *self { - ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(), - ast::GenericParam::Type(ref ty) => ty.span(), - } - } -} - -impl Spanned for ast::StructField { - fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) - } -} - -impl Spanned for ast::WherePredicate { - fn span(&self) -> Span { - match *self { - ast::WherePredicate::BoundPredicate(ref p) => p.span, - ast::WherePredicate::RegionPredicate(ref p) => p.span, - ast::WherePredicate::EqPredicate(ref p) => p.span, - } - } -} - -impl Spanned for ast::FunctionRetTy { - fn span(&self) -> Span { - match *self { - ast::FunctionRetTy::Default(span) => span, - ast::FunctionRetTy::Ty(ref ty) => ty.span, - } - } -} - -impl Spanned for ast::TyParam { - fn span(&self) -> Span { - // Note that ty.span is the span for ty.ident, not the whole item. - let lo = if self.attrs.is_empty() { - self.span.lo() - } else { - self.attrs[0].span.lo() - }; - if let Some(ref def) = self.default { - return mk_sp(lo, def.span.hi()); - } - if self.bounds.is_empty() { - return mk_sp(lo, self.span.hi()); - } - let hi = self.bounds[self.bounds.len() - 1].span().hi(); - mk_sp(lo, hi) - } -} - -impl Spanned for ast::TyParamBound { - fn span(&self) -> Span { - match *self { - ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, - ast::TyParamBound::RegionTyParamBound(ref l) => l.span, - } - } -} - -impl Spanned for ast::LifetimeDef { - fn span(&self) -> Span { - let hi = if self.bounds.is_empty() { - self.lifetime.span.hi() - } else { - self.bounds[self.bounds.len() - 1].span.hi() - }; - mk_sp(self.lifetime.span.lo(), hi) - } -} - -impl Spanned for MacroArg { - fn span(&self) -> Span { - match *self { - MacroArg::Expr(ref expr) => expr.span(), - MacroArg::Ty(ref ty) => ty.span(), - MacroArg::Pat(ref pat) => pat.span(), - } - } -} diff --git a/src/string.rs b/src/string.rs deleted file mode 100644 index 2386d90ec8a..00000000000 --- a/src/string.rs +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Format string literals. - -use regex::Regex; -use unicode_segmentation::UnicodeSegmentation; - -use config::Config; -use shape::Shape; -use utils::wrap_str; - -const MIN_STRING: usize = 10; - -pub struct StringFormat<'a> { - pub opener: &'a str, - pub closer: &'a str, - pub line_start: &'a str, - pub line_end: &'a str, - pub shape: Shape, - pub trim_end: bool, - pub config: &'a Config, -} - -impl<'a> StringFormat<'a> { - pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { - StringFormat { - opener: "\"", - closer: "\"", - line_start: " ", - line_end: "\\", - shape, - trim_end: false, - config, - } - } -} - -// FIXME: simplify this! -pub fn rewrite_string<'a>( - orig: &str, - fmt: &StringFormat<'a>, - max_width: Option, -) -> Option { - // Strip line breaks. - let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); - let stripped_str = re.replace_all(orig, "$1"); - - let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let shape = fmt.shape; - let indent = shape.indent.to_string(fmt.config); - let punctuation = ":,;."; - - // `cur_start` is the position in `orig` of the start of the current line. - let mut cur_start = 0; - let mut result = String::with_capacity( - stripped_str - .len() - .checked_next_power_of_two() - .unwrap_or(usize::max_value()), - ); - result.push_str(fmt.opener); - - let ender_length = fmt.line_end.len(); - // If we cannot put at least a single character per line, the rewrite won't - // succeed. - let mut max_chars = shape - .width - .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; - - // Snip a line at a time from `orig` until it is used up. Push the snippet - // onto result. - 'outer: loop { - // `cur_end` will be where we break the line, as an offset into `orig`. - // Initialised to the maximum it could be (which may be beyond `orig`). - let mut cur_end = cur_start + max_chars; - - // We can fit the rest of the string on this line, so we're done. - if cur_end >= graphemes.len() { - let line = &graphemes[cur_start..].join(""); - result.push_str(line); - break 'outer; - } - - // Push cur_end left until we reach whitespace (or the line is too small). - while !graphemes[cur_end - 1].trim().is_empty() { - cur_end -= 1; - if cur_end < cur_start + MIN_STRING { - // We couldn't find whitespace before the string got too small. - // So start again at the max length and look for punctuation. - cur_end = cur_start + max_chars; - while !punctuation.contains(graphemes[cur_end - 1]) { - cur_end -= 1; - - // If we can't break at whitespace or punctuation, grow the string instead. - if cur_end < cur_start + MIN_STRING { - cur_end = cur_start + max_chars; - while !(punctuation.contains(graphemes[cur_end - 1]) - || graphemes[cur_end - 1].trim().is_empty()) - { - if cur_end >= graphemes.len() { - let line = &graphemes[cur_start..].join(""); - result.push_str(line); - break 'outer; - } - cur_end += 1; - } - break; - } - } - break; - } - } - // Make sure there is no whitespace to the right of the break. - while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { - cur_end += 1; - } - - // Make the current line and add it on to result. - let raw_line = graphemes[cur_start..cur_end].join(""); - let line = if fmt.trim_end { - raw_line.trim() - } else { - raw_line.as_str() - }; - - result.push_str(line); - result.push_str(fmt.line_end); - result.push('\n'); - result.push_str(&indent); - result.push_str(fmt.line_start); - - // The next line starts where the current line ends. - cur_start = cur_end; - - if let Some(new_max_chars) = max_width { - max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; - } - } - - result.push_str(fmt.closer); - wrap_str(result, fmt.config.max_width(), fmt.shape) -} - -#[cfg(test)] -mod test { - use super::{rewrite_string, StringFormat}; - use shape::{Indent, Shape}; - - #[test] - fn issue343() { - let config = Default::default(); - let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); - rewrite_string("eq_", &fmt, None); - } -} diff --git a/src/types.rs b/src/types.rs deleted file mode 100644 index a7472567a81..00000000000 --- a/src/types.rs +++ /dev/null @@ -1,820 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::iter::ExactSizeIterator; -use std::ops::Deref; - -use syntax::ast::{self, FunctionRetTy, Mutability}; -use syntax::codemap::{self, BytePos, Span}; -use syntax::print::pprust; -use syntax::symbol::keywords; - -use codemap::SpanUtils; -use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; -use items::{format_generics_item_list, generics_shape_from_config}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, - SeparatorPlace, SeparatorTactic}; -use macros::{rewrite_macro, MacroPosition}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use spanned::Spanned; -use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, - last_line_width, mk_sp}; - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum PathContext { - Expr, - Type, - Import, -} - -// Does not wrap on simple segments. -pub fn rewrite_path( - context: &RewriteContext, - path_context: PathContext, - qself: Option<&ast::QSelf>, - path: &ast::Path, - shape: Shape, -) -> Option { - let skip_count = qself.map_or(0, |x| x.position); - - let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import { - "::".to_owned() - } else { - String::new() - }; - - let mut span_lo = path.span.lo(); - - if let Some(qself) = qself { - result.push('<'); - if context.config.spaces_within_parens_and_brackets() { - result.push_str(" ") - } - - let fmt_ty = qself.ty.rewrite(context, shape)?; - result.push_str(&fmt_ty); - - if skip_count > 0 { - result.push_str(" as "); - if path.is_global() && path_context != PathContext::Import { - result.push_str("::"); - } - - // 3 = ">::".len() - let shape = shape.sub_width(3)?; - - result = rewrite_path_segments( - PathContext::Type, - result, - path.segments.iter().take(skip_count), - span_lo, - path.span.hi(), - context, - shape, - )?; - } - - if context.config.spaces_within_parens_and_brackets() { - result.push_str(" ") - } - - result.push_str(">::"); - span_lo = qself.ty.span.hi() + BytePos(1); - } - - rewrite_path_segments( - path_context, - result, - path.segments.iter().skip(skip_count), - span_lo, - path.span.hi(), - context, - shape, - ) -} - -fn rewrite_path_segments<'a, I>( - path_context: PathContext, - mut buffer: String, - iter: I, - mut span_lo: BytePos, - span_hi: BytePos, - context: &RewriteContext, - shape: Shape, -) -> Option -where - I: Iterator, -{ - let mut first = true; - let shape = shape.visual_indent(0); - - for segment in iter { - // Indicates a global path, shouldn't be rendered. - if segment.identifier.name == keywords::CrateRoot.name() { - continue; - } - if first { - first = false; - } else { - buffer.push_str("::"); - } - - let extra_offset = extra_offset(&buffer, shape); - let new_shape = shape.shrink_left(extra_offset)?; - let segment_string = rewrite_segment( - path_context, - segment, - &mut span_lo, - span_hi, - context, - new_shape, - )?; - - buffer.push_str(&segment_string); - } - - Some(buffer) -} - -#[derive(Debug)] -enum SegmentParam<'a> { - LifeTime(&'a ast::Lifetime), - Type(&'a ast::Ty), - Binding(&'a ast::TypeBinding), -} - -impl<'a> SegmentParam<'a> { - fn get_span(&self) -> Span { - match *self { - SegmentParam::LifeTime(lt) => lt.span, - SegmentParam::Type(ty) => ty.span, - SegmentParam::Binding(binding) => binding.span, - } - } -} - -impl<'a> Rewrite for SegmentParam<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), - SegmentParam::Type(ty) => ty.rewrite(context, shape), - SegmentParam::Binding(binding) => { - let mut result = match context.config.type_punctuation_density() { - TypeDensity::Wide => format!("{} = ", binding.ident), - TypeDensity::Compressed => format!("{}=", binding.ident), - }; - let budget = shape.width.checked_sub(result.len())?; - let rewrite = binding - .ty - .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); - Some(result) - } - } - } -} - -// Formats a path segment. There are some hacks involved to correctly determine -// the segment's associated span since it's not part of the AST. -// -// The span_lo is assumed to be greater than the end of any previous segment's -// parameters and lesser or equal than the start of current segment. -// -// span_hi is assumed equal to the end of the entire path. -// -// When the segment contains a positive number of parameters, we update span_lo -// so that invariants described above will hold for the next segment. -fn rewrite_segment( - path_context: PathContext, - segment: &ast::PathSegment, - span_lo: &mut BytePos, - span_hi: BytePos, - context: &RewriteContext, - shape: Shape, -) -> Option { - let ident_len = segment.identifier.to_string().len(); - let shape = shape.shrink_left(ident_len)?; - - let params = if let Some(ref params) = segment.parameters { - match **params { - ast::PathParameters::AngleBracketed(ref data) - if !data.lifetimes.is_empty() || !data.types.is_empty() - || !data.bindings.is_empty() => - { - let param_list = data.lifetimes - .iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) - .collect::>(); - - let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1); - let list_lo = context.codemap.span_after(mk_sp(*span_lo, span_hi), "<"); - let separator = if path_context == PathContext::Expr { - "::" - } else { - "" - }; - - let generics_shape = - generics_shape_from_config(context.config, shape, separator.len())?; - let one_line_width = shape.width.checked_sub(separator.len() + 2)?; - let items = itemize_list( - context.codemap, - param_list.into_iter(), - ">", - ",", - |param| param.get_span().lo(), - |param| param.get_span().hi(), - |seg| seg.rewrite(context, generics_shape), - list_lo, - span_hi, - false, - ); - let generics_str = - format_generics_item_list(context, items, generics_shape, one_line_width)?; - - // Update position of last bracket. - *span_lo = next_span_lo; - - format!("{}{}", separator, generics_str) - } - ast::PathParameters::Parenthesized(ref data) => { - let output = match data.output { - Some(ref ty) => FunctionRetTy::Ty(ty.clone()), - None => FunctionRetTy::Default(codemap::DUMMY_SP), - }; - format_function_type( - data.inputs.iter().map(|x| &**x), - &output, - false, - data.span, - context, - shape, - )? - } - _ => String::new(), - } - } else { - String::new() - }; - - Some(format!("{}{}", segment.identifier, params)) -} - -fn format_function_type<'a, I>( - inputs: I, - output: &FunctionRetTy, - variadic: bool, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option -where - I: ExactSizeIterator, - ::Item: Deref, - ::Target: Rewrite + Spanned + 'a, -{ - // Code for handling variadics is somewhat duplicated for items, but they - // are different enough to need some serious refactoring to share code. - enum ArgumentKind - where - T: Deref, - ::Target: Rewrite + Spanned, - { - Regular(Box), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_start = context.codemap.span_before(span, "..."); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - - // 2 for () - let budget = shape.width.checked_sub(2)?; - // 1 for ( - let offset = match context.config.indent_style() { - IndentStyle::Block => { - shape - .block() - .block_indent(context.config.tab_spaces()) - .indent - } - IndentStyle::Visual => shape.indent + 1, - }; - let list_shape = Shape::legacy(budget, offset); - let list_lo = context.codemap.span_after(span, "("); - let items = itemize_list( - context.codemap, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs - .map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), - ")", - ",", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo(), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi(), - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, - list_lo, - span.hi(), - false, - ); - - let item_vec: Vec<_> = items.collect(); - - let tactic = definitive_tactic( - &*item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - budget, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if !context.use_block_indent() || variadic { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape: list_shape, - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - let list_str = write_list(&item_vec, &fmt)?; - - let ty_shape = match context.config.indent_style() { - // 4 = " -> " - IndentStyle::Block => shape.offset_left(4)?, - IndentStyle::Visual => shape.block_left(4)?, - }; - let output = match *output { - FunctionRetTy::Ty(ref ty) => { - let type_str = ty.rewrite(context, ty_shape)?; - format!(" -> {}", type_str) - } - FunctionRetTy::Default(..) => String::new(), - }; - - let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n'); - let args = wrap_args_with_parens( - context, - &list_str, - extendable, - shape.sub_width(first_line_width(&output))?, - Shape::indented(offset, context.config), - ); - if last_line_width(&args) + first_line_width(&output) <= shape.width { - Some(format!("{}{}", args, output)) - } else { - Some(format!( - "{}\n{}{}", - args, - offset.to_string(context.config), - output.trim_left() - )) - } -} - -fn type_bound_colon(context: &RewriteContext) -> &'static str { - colon_spaces( - context.config.space_before_colon(), - context.config.space_after_colon(), - ) -} - -impl Rewrite for ast::WherePredicate { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - // TODO: dead spans? - let result = match *self { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_generic_params, - ref bounded_ty, - ref bounds, - .. - }) => { - let type_str = bounded_ty.rewrite(context, shape)?; - - let colon = type_bound_colon(context); - - if let Some(lifetime_str) = - rewrite_lifetime_param(context, shape, bound_generic_params) - { - // 6 = "for<> ".len() - let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let ty_shape = shape.offset_left(used_width)?; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let bounds_str = join_bounds(context, ty_shape, &bounds); - - if context.config.spaces_within_parens_and_brackets() - && !lifetime_str.is_empty() - { - format!( - "for< {} > {}{}{}", - lifetime_str, type_str, colon, bounds_str - ) - } else { - format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) - } - } else { - let used_width = type_str.len() + colon.len(); - let ty_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.block_left(used_width)?, - IndentStyle::Block => shape, - }; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let overhead = type_str.len() + colon.len(); - let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); - - format!("{}{}{}", type_str, colon, bounds_str) - } - } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - ref lifetime, - ref bounds, - .. - }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - let lhs_ty_str = lhs_ty.rewrite(context, shape)?; - // 3 = " = ".len() - let used_width = 3 + lhs_ty_str.len(); - let budget = shape.width.checked_sub(used_width)?; - let rhs_ty_str = - rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; - format!("{} = {}", lhs_ty_str, rhs_ty_str) - } - }; - - Some(result) - } -} - -impl Rewrite for ast::LifetimeDef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) - } -} - -fn rewrite_bounded_lifetime<'b, I>( - lt: &ast::Lifetime, - bounds: I, - context: &RewriteContext, - shape: Shape, -) -> Option -where - I: ExactSizeIterator, -{ - let result = lt.rewrite(context, shape)?; - - if bounds.len() == 0 { - Some(result) - } else { - let appendix = bounds - .into_iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - let colon = type_bound_colon(context); - let overhead = last_line_width(&result) + colon.len(); - let result = format!( - "{}{}{}", - result, - colon, - join_bounds(context, shape.sub_width(overhead)?, &appendix) - ); - Some(result) - } -} - -impl Rewrite for ast::TyParamBound { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { - tref.rewrite(context, shape) - } - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => { - Some(format!( - "?{}", - tref.rewrite(context, shape.offset_left(1)?)? - )) - } - ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), - } - } -} - -impl Rewrite for ast::Lifetime { - fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { - Some(pprust::lifetime_to_string(self)) - } -} - -impl Rewrite for ast::TyParamBounds { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs = self.iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - Some(join_bounds(context, shape, &strs)) - } -} - -impl Rewrite for ast::TyParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let mut result = String::with_capacity(128); - // FIXME: If there are more than one attributes, this will force multiline. - match self.attrs.rewrite(context, shape) { - Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), - _ => (), - } - result.push_str(&self.ident.to_string()); - if !self.bounds.is_empty() { - result.push_str(type_bound_colon(context)); - let strs = self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - result.push_str(&join_bounds(context, shape, &strs)); - } - if let Some(ref def) = self.default { - let eq_str = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "=", - TypeDensity::Wide => " = ", - }; - result.push_str(eq_str); - let budget = shape.width.checked_sub(result.len())?; - let rewrite = def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); - } - - Some(result) - } -} - -impl Rewrite for ast::PolyTraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if let Some(lifetime_str) = - rewrite_lifetime_param(context, shape, &self.bound_generic_params) - { - // 6 is "for<> ".len() - let extra_offset = lifetime_str.len() + 6; - let path_str = self.trait_ref - .rewrite(context, shape.offset_left(extra_offset)?)?; - - Some( - if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }, - ) - } else { - self.trait_ref.rewrite(context, shape) - } - } -} - -impl Rewrite for ast::TraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_path(context, PathContext::Type, None, &self.path, shape) - } -} - -impl Rewrite for ast::Ty { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - ast::TyKind::TraitObject(ref bounds, ..) => bounds.rewrite(context, shape), - ast::TyKind::Ptr(ref mt) => { - let prefix = match mt.mutbl { - Mutability::Mutable => "*mut ", - Mutability::Immutable => "*const ", - }; - - rewrite_unary_prefix(context, prefix, &*mt.ty, shape) - } - ast::TyKind::Rptr(ref lifetime, ref mt) => { - let mut_str = format_mutability(mt.mutbl); - let mut_len = mut_str.len(); - Some(match *lifetime { - Some(ref lifetime) => { - let lt_budget = shape.width.checked_sub(2 + mut_len)?; - let lt_str = lifetime.rewrite( - context, - Shape::legacy(lt_budget, shape.indent + 2 + mut_len), - )?; - let lt_len = lt_str.len(); - let budget = shape.width.checked_sub(2 + mut_len + lt_len)?; - format!( - "&{} {}{}", - lt_str, - mut_str, - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len) - )? - ) - } - None => { - let budget = shape.width.checked_sub(1 + mut_len)?; - format!( - "&{}{}", - mut_str, - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 1 + mut_len) - )? - ) - } - }) - } - // FIXME: we drop any comments here, even though it's a silly place to put - // comments. - ast::TyKind::Paren(ref ty) => { - let budget = shape.width.checked_sub(2)?; - ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| { - if context.config.spaces_within_parens_and_brackets() { - format!("( {} )", ty_str) - } else { - format!("({})", ty_str) - } - }) - } - ast::TyKind::Slice(ref ty) => { - let budget = if context.config.spaces_within_parens_and_brackets() { - shape.width.checked_sub(4)? - } else { - shape.width.checked_sub(2)? - }; - ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| { - if context.config.spaces_within_parens_and_brackets() { - format!("[ {} ]", ty_str) - } else { - format!("[{}]", ty_str) - } - }) - } - ast::TyKind::Tup(ref items) => rewrite_tuple( - context, - &::utils::ptr_vec_to_ref_vec(items), - self.span, - shape, - ), - ast::TyKind::Path(ref q_self, ref path) => { - rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) - } - ast::TyKind::Array(ref ty, ref repeats) => { - let use_spaces = context.config.spaces_within_parens_and_brackets(); - let lbr = if use_spaces { "[ " } else { "[" }; - let rbr = if use_spaces { " ]" } else { "]" }; - rewrite_pair( - &**ty, - &**repeats, - PairParts::new(lbr, "; ", rbr), - context, - shape, - SeparatorPlace::Back, - ) - } - ast::TyKind::Infer => { - if shape.width >= 1 { - Some("_".to_owned()) - } else { - None - } - } - ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), - ast::TyKind::Never => Some(String::from("!")), - ast::TyKind::Mac(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - } - ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) - .map(|it_str| format!("impl {}", it_str)), - ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), - } - } -} - -fn rewrite_bare_fn( - bare_fn: &ast::BareFnTy, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let mut result = String::with_capacity(128); - - if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params) - { - result.push_str("for<"); - // 6 = "for<> ".len(), 4 = "for<". - // This doesn't work out so nicely for mutliline situation with lots of - // rightward drift. If that is a problem, we could use the list stuff. - result.push_str(lifetime_str); - result.push_str("> "); - } - - result.push_str(::utils::format_unsafety(bare_fn.unsafety)); - - result.push_str(&format_abi( - bare_fn.abi, - context.config.force_explicit_abi(), - false, - )); - - result.push_str("fn"); - - let func_ty_shape = shape.offset_left(result.len())?; - - let rewrite = format_function_type( - bare_fn.decl.inputs.iter(), - &bare_fn.decl.output, - bare_fn.decl.variadic, - span, - context, - func_ty_shape, - )?; - - result.push_str(&rewrite); - - Some(result) -} - -pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { - // Try to join types in a single line - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let result = type_strs.join(joiner); - if result.contains('\n') || result.len() > shape.width { - let joiner_indent = shape.indent.block_indent(context.config); - let joiner = format!("\n{}+ ", joiner_indent.to_string(context.config)); - type_strs.join(&joiner) - } else { - result - } -} - -pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { - match ty.node { - ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { - can_be_overflowed_type(context, &*mutty.ty, len) - } - _ => false, - } -} - -/// Returns `None` if there is no `LifetimeDef` in the given generic parameters. -fn rewrite_lifetime_param( - context: &RewriteContext, - shape: Shape, - generic_params: &[ast::GenericParam], -) -> Option { - let result = generic_params - .iter() - .filter(|p| p.is_lifetime_param()) - .map(|lt| lt.rewrite(context, shape)) - .collect::>>()? - .join(", "); - if result.is_empty() { - None - } else { - Some(result) - } -} diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 20f4fdfe6d0..00000000000 --- a/src/utils.rs +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; - -use syntax::{abi, ptr}; -use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, - NestedMetaItemKind, Path, Visibility}; -use syntax::codemap::{BytePos, Span, NO_EXPANSION}; - -use config::Color; -use rewrite::RewriteContext; -use shape::Shape; - -// When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &str = "rustfmt_skip"; - -// Computes the length of a string's last line, minus offset. -pub fn extra_offset(text: &str, shape: Shape) -> usize { - match text.rfind('\n') { - // 1 for newline character - Some(idx) => text.len() - .checked_sub(idx + 1 + shape.used_width()) - .unwrap_or(0), - None => text.len(), - } -} - -// Uses Cow to avoid allocating in the common cases. -pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { - match *vis { - Visibility::Public => Cow::from("pub "), - Visibility::Inherited => Cow::from(""), - Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "), - Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "), - Visibility::Restricted { ref path, .. } => { - let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); - if path.is_global() { - segments_iter - .next() - .expect("Non-global path in pub(restricted)?"); - } - let is_keyword = |s: &str| s == "self" || s == "super"; - let path = segments_iter.collect::>().join("::"); - let in_str = if is_keyword(&path) { "" } else { "in " }; - - Cow::from(format!("pub({}{}) ", in_str, path)) - } - } -} - -#[inline] -pub fn format_constness(constness: ast::Constness) -> &'static str { - match constness { - ast::Constness::Const => "const ", - ast::Constness::NotConst => "", - } -} - -#[inline] -pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { - match defaultness { - ast::Defaultness::Default => "default ", - ast::Defaultness::Final => "", - } -} - -#[inline] -pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { - match unsafety { - ast::Unsafety::Unsafe => "unsafe ", - ast::Unsafety::Normal => "", - } -} - -#[inline] -pub fn format_mutability(mutability: ast::Mutability) -> &'static str { - match mutability { - ast::Mutability::Mutable => "mut ", - ast::Mutability::Immutable => "", - } -} - -#[inline] -pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { - if abi == abi::Abi::Rust && !is_mod { - Cow::from("") - } else if abi == abi::Abi::C && !explicit_abi { - Cow::from("extern ") - } else { - Cow::from(format!("extern {} ", abi)) - } -} - -#[inline] -// Transform `Vec>` into `Vec<&T>` -pub fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { - vec.iter().map(|x| &**x).collect::>() -} - -#[inline] -pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { - attrs - .iter() - .filter(|a| a.style == style) - .cloned() - .collect::>() -} - -#[inline] -pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { - filter_attributes(attrs, ast::AttrStyle::Inner) -} - -#[inline] -pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { - filter_attributes(attrs, ast::AttrStyle::Outer) -} - -#[inline] -pub fn last_line_contains_single_line_comment(s: &str) -> bool { - s.lines().last().map_or(false, |l| l.contains("//")) -} - -#[inline] -pub fn is_attributes_extendable(attrs_str: &str) -> bool { - !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) -} - -// The width of the first line in s. -#[inline] -pub fn first_line_width(s: &str) -> usize { - match s.find('\n') { - Some(n) => n, - None => s.len(), - } -} - -// The width of the last line in s. -#[inline] -pub fn last_line_width(s: &str) -> usize { - match s.rfind('\n') { - Some(n) => s.len() - n - 1, - None => s.len(), - } -} - -// The total used width of the last line. -#[inline] -pub fn last_line_used_width(s: &str, offset: usize) -> usize { - if s.contains('\n') { - last_line_width(s) - } else { - offset + s.len() - } -} - -#[inline] -pub fn trimmed_last_line_width(s: &str) -> usize { - match s.rfind('\n') { - Some(n) => s[(n + 1)..].trim().len(), - None => s.trim().len(), - } -} - -#[inline] -pub fn last_line_extendable(s: &str) -> bool { - if s.ends_with("\"#") { - return true; - } - for c in s.chars().rev() { - match c { - '(' | ')' | ']' | '}' | '?' | '>' => continue, - '\n' => break, - _ if c.is_whitespace() => continue, - _ => return false, - } - } - true -} - -#[inline] -fn is_skip(meta_item: &MetaItem) -> bool { - match meta_item.node { - MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION, - MetaItemKind::List(ref l) => { - meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) - } - _ => false, - } -} - -#[inline] -fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { - match meta_item.node { - NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi), - NestedMetaItemKind::Literal(_) => false, - } -} - -#[inline] -pub fn contains_skip(attrs: &[Attribute]) -> bool { - attrs - .iter() - .any(|a| a.meta().map_or(false, |a| is_skip(&a))) -} - -#[inline] -pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { - context.config.trailing_semicolon() - } - _ => false, - } -} - -#[inline] -pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::StmtKind::Semi(ref expr) => match expr.node { - ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) => false, - ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { - context.config.trailing_semicolon() - } - _ => true, - }, - ast::StmtKind::Expr(..) => false, - _ => true, - } -} - -#[inline] -pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { - match stmt.node { - ast::StmtKind::Expr(ref expr) => Some(expr), - _ => None, - } -} - -#[inline] -pub fn count_newlines(input: &str) -> usize { - input.chars().filter(|&c| c == '\n').count() -} - -// Macro for deriving implementations of Serialize/Deserialize for enums -#[macro_export] -macro_rules! impl_enum_serialize_and_deserialize { - ( $e:ident, $( $x:ident ),* ) => { - impl ::serde::ser::Serialize for $e { - fn serialize(&self, serializer: S) -> Result - where S: ::serde::ser::Serializer - { - use serde::ser::Error; - - // We don't know whether the user of the macro has given us all options. - #[allow(unreachable_patterns)] - match *self { - $( - $e::$x => serializer.serialize_str(stringify!($x)), - )* - _ => { - Err(S::Error::custom(format!("Cannot serialize {:?}", self))) - } - } - } - } - - impl<'de> ::serde::de::Deserialize<'de> for $e { - fn deserialize(d: D) -> Result - where D: ::serde::Deserializer<'de> { - use serde::de::{Error, Visitor}; - use std::marker::PhantomData; - use std::fmt; - struct StringOnly(PhantomData); - impl<'de, T> Visitor<'de> for StringOnly - where T: ::serde::Deserializer<'de> { - type Value = String; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("string") - } - fn visit_str(self, value: &str) -> Result { - Ok(String::from(value)) - } - } - let s = d.deserialize_string(StringOnly::(PhantomData))?; - $( - if stringify!($x).eq_ignore_ascii_case(&s) { - return Ok($e::$x); - } - )* - static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; - Err(D::Error::unknown_variant(&s, ALLOWED)) - } - } - - impl ::std::str::FromStr for $e { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - $( - if stringify!($x).eq_ignore_ascii_case(s) { - return Ok($e::$x); - } - )* - Err("Bad variant") - } - } - - impl ::config::ConfigType for $e { - fn doc_hint() -> String { - let mut variants = Vec::new(); - $( - variants.push(stringify!($x)); - )* - format!("[{}]", variants.join("|")) - } - } - }; -} - -macro_rules! msg { - ($($arg:tt)*) => ( - match writeln!(&mut ::std::io::stderr(), $($arg)* ) { - Ok(_) => {}, - Err(x) => panic!("Unable to write to stderr: {}", x), - } - ) -} - -// For format_missing and last_pos, need to use the source callsite (if applicable). -// Required as generated code spans aren't guaranteed to follow on from the last span. -macro_rules! source { - ($this: ident, $sp: expr) => { - $sp.source_callsite() - }; -} - -pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { - Span::new(lo, hi, NO_EXPANSION) -} - -// Return true if the given span does not intersect with file lines. -macro_rules! out_of_file_lines_range { - ($self: ident, $span: expr) => { - !$self - .config - .file_lines() - .intersects(&$self.codemap.lookup_line_range($span)) - }; -} - -macro_rules! skip_out_of_file_lines_range { - ($self: ident, $span: expr) => { - if out_of_file_lines_range!($self, $span) { - return None; - } - }; -} - -macro_rules! skip_out_of_file_lines_range_visitor { - ($self: ident, $span: expr) => { - if out_of_file_lines_range!($self, $span) { - $self.push_rewrite($span, None); - return; - } - }; -} - -// Wraps String in an Option. Returns Some when the string adheres to the -// Rewrite constraints defined for the Rewrite trait and else otherwise. -pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { - if is_valid_str(&s, max_width, shape) { - Some(s) - } else { - None - } -} - -fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { - if !snippet.is_empty() { - // First line must fits with `shape.width`. - if first_line_width(snippet) > shape.width { - return false; - } - // If the snippet does not include newline, we are done. - if first_line_width(snippet) == snippet.len() { - return true; - } - // The other lines must fit within the maximum width. - if snippet.lines().skip(1).any(|line| line.len() > max_width) { - return false; - } - // A special check for the last line, since the caller may - // place trailing characters on this line. - if last_line_width(snippet) > shape.used_width() + shape.width { - return false; - } - } - true -} - -#[inline] -pub fn colon_spaces(before: bool, after: bool) -> &'static str { - match (before, after) { - (true, true) => " : ", - (true, false) => " :", - (false, true) => ": ", - (false, false) => ":", - } -} - -#[inline] -pub fn paren_overhead(context: &RewriteContext) -> usize { - if context.config.spaces_within_parens_and_brackets() { - 4 - } else { - 2 - } -} - -pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { - match e.node { - ast::ExprKind::InPlace(ref e, _) - | ast::ExprKind::Call(ref e, _) - | ast::ExprKind::Binary(_, ref e, _) - | ast::ExprKind::Cast(ref e, _) - | ast::ExprKind::Type(ref e, _) - | ast::ExprKind::Assign(ref e, _) - | ast::ExprKind::AssignOp(_, ref e, _) - | ast::ExprKind::Field(ref e, _) - | ast::ExprKind::TupField(ref e, _) - | ast::ExprKind::Index(ref e, _) - | ast::ExprKind::Range(Some(ref e), _, _) - | ast::ExprKind::Try(ref e) => left_most_sub_expr(e), - _ => e, - } -} - -// isatty shamelessly adapted from cargo. -#[cfg(unix)] -pub fn isatty() -> bool { - extern crate libc; - - unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } -} -#[cfg(windows)] -pub fn isatty() -> bool { - extern crate kernel32; - extern crate winapi; - - unsafe { - let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); - let mut out = 0; - kernel32::GetConsoleMode(handle, &mut out) != 0 - } -} - -pub fn use_colored_tty(color: Color) -> bool { - match color { - Color::Always => true, - Color::Never => false, - Color::Auto => isatty(), - } -} - -pub fn starts_with_newline(s: &str) -> bool { - s.starts_with('\n') || s.starts_with("\r\n") -} diff --git a/src/vertical.rs b/src/vertical.rs deleted file mode 100644 index 2ccb5d81339..00000000000 --- a/src/vertical.rs +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Format with vertical alignment. - -use std::cmp; - -use syntax::ast; -use syntax::codemap::{BytePos, Span}; - -use codemap::SpanUtils; -use comment::{combine_strs_with_missing_comments, contains_comment}; -use expr::rewrite_field; -use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListTactic, Separator, - SeparatorPlace}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use utils::{contains_skip, is_attributes_extendable, mk_sp}; - -pub trait AlignedItem { - fn skip(&self) -> bool; - fn get_span(&self) -> Span; - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option; - fn rewrite_aligned_item( - &self, - context: &RewriteContext, - shape: Shape, - prefix_max_width: usize, - ) -> Option; -} - -impl AlignedItem for ast::StructField { - fn skip(&self) -> bool { - contains_skip(&self.attrs) - } - - fn get_span(&self) -> Span { - self.span() - } - - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; - let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo(), self.span.lo()) - } else { - mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) - }; - let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str); - rewrite_struct_field_prefix(context, self).and_then(|field_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &field_str, - missing_span, - shape, - attrs_extendable, - ) - }) - } - - fn rewrite_aligned_item( - &self, - context: &RewriteContext, - shape: Shape, - prefix_max_width: usize, - ) -> Option { - rewrite_struct_field(context, self, shape, prefix_max_width) - } -} - -impl AlignedItem for ast::Field { - fn skip(&self) -> bool { - contains_skip(&self.attrs) - } - - fn get_span(&self) -> Span { - self.span() - } - - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; - let name = &self.ident.node.to_string(); - let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo(), self.span.lo()) - } else { - mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) - }; - combine_strs_with_missing_comments( - context, - &attrs_str, - name, - missing_span, - shape, - is_attributes_extendable(&attrs_str), - ) - } - - fn rewrite_aligned_item( - &self, - context: &RewriteContext, - shape: Shape, - prefix_max_width: usize, - ) -> Option { - rewrite_field(context, self, shape, prefix_max_width) - } -} - -pub fn rewrite_with_alignment( - fields: &[T], - context: &RewriteContext, - shape: Shape, - span: Span, - one_line_width: usize, -) -> Option { - let (spaces, group_index) = if context.config.struct_field_align_threshold() > 0 { - group_aligned_items(context, fields) - } else { - ("", fields.len() - 1) - }; - let init = &fields[0..group_index + 1]; - let rest = &fields[group_index + 1..]; - let init_last_pos = if rest.is_empty() { - span.hi() - } else { - // Decide whether the missing comments should stick to init or rest. - let init_hi = init[init.len() - 1].get_span().hi(); - let rest_lo = rest[0].get_span().lo(); - let missing_span = mk_sp(init_hi, rest_lo); - let missing_span = mk_sp( - context.codemap.span_after(missing_span, ","), - missing_span.hi(), - ); - - let snippet = context.snippet(missing_span); - if snippet.trim_left().starts_with("//") { - let offset = snippet.lines().next().map_or(0, |l| l.len()); - // 2 = "," + "\n" - init_hi + BytePos(offset as u32 + 2) - } else if snippet.trim_left().starts_with("/*") { - let comment_lines = snippet - .lines() - .position(|line| line.trim_right().ends_with("*/")) - .unwrap_or(0); - - let offset = snippet - .lines() - .take(comment_lines + 1) - .collect::>() - .join("\n") - .len(); - - init_hi + BytePos(offset as u32 + 2) - } else { - missing_span.lo() - } - }; - let init_span = mk_sp(span.lo(), init_last_pos); - let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; - let result = - rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?; - if rest.is_empty() { - Some(result + spaces) - } else { - let rest_span = mk_sp(init_last_pos, span.hi()); - let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; - Some( - result + spaces + "\n" - + &shape - .indent - .block_indent(context.config) - .to_string(context.config) + &rest_str, - ) - } -} - -fn struct_field_prefix_max_min_width( - context: &RewriteContext, - fields: &[T], - shape: Shape, -) -> (usize, usize) { - fields - .iter() - .map(|field| { - field.rewrite_prefix(context, shape).and_then(|field_str| { - if field_str.contains('\n') { - None - } else { - Some(field_str.len()) - } - }) - }) - .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { - (Some((max_len, min_len)), Some(len)) => { - Some((cmp::max(max_len, len), cmp::min(min_len, len))) - } - _ => None, - }) - .unwrap_or((0, 0)) -} - -fn rewrite_aligned_items_inner( - context: &RewriteContext, - fields: &[T], - span: Span, - offset: Indent, - one_line_width: usize, -) -> Option { - let item_indent = offset.block_indent(context.config); - // 1 = "," - let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; - let (mut field_prefix_max_width, field_prefix_min_width) = - struct_field_prefix_max_min_width(context, fields, item_shape); - let max_diff = field_prefix_max_width - .checked_sub(field_prefix_min_width) - .unwrap_or(0); - if max_diff > context.config.struct_field_align_threshold() { - field_prefix_max_width = 0; - } - - let items = itemize_list( - context.codemap, - fields.iter(), - "}", - ",", - |field| field.get_span().lo(), - |field| field.get_span().hi(), - |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), - span.lo(), - span.hi(), - false, - ).collect::>(); - - let tactic = definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::Comma, - one_line_width, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: context.config.trailing_comma(), - separator_place: SeparatorPlace::Back, - shape: item_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - write_list(&items, &fmt) -} - -fn group_aligned_items( - context: &RewriteContext, - fields: &[T], -) -> (&'static str, usize) { - let mut index = 0; - for i in 0..fields.len() - 1 { - if fields[i].skip() { - return ("", index); - } - // See if there are comments or empty lines between fields. - let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo()); - let snippet = context - .snippet(span) - .lines() - .skip(1) - .collect::>() - .join("\n"); - let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) { - "\n" - } else { - "" - }; - if contains_comment(&snippet) || snippet.lines().count() > 1 { - return (spacings, index); - } - index += 1; - } - ("", index) -} diff --git a/src/visitor.rs b/src/visitor.rs deleted file mode 100644 index cd6c0740ee6..00000000000 --- a/src/visitor.rs +++ /dev/null @@ -1,1113 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp; - -use syntax::{ast, visit}; -use syntax::attr::{self, HasAttrs}; -use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; -use syntax::parse::ParseSess; - -use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, CodeCharKind, - CommentCodeSlices, FindUncommented}; -use comment::rewrite_comment; -use config::{BraceStyle, Config}; -use expr::rewrite_literal; -use items::{format_impl, format_trait, format_trait_alias, rewrite_associated_impl_type, - rewrite_associated_type, rewrite_type_alias, FnSig, StaticParts, StructParts}; -use lists::{itemize_list, write_list, DefinitiveListTactic, ListFormatting, SeparatorPlace, - SeparatorTactic}; -use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; -use regex::Regex; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; - -/// Returns attributes that are within `outer_span`. -pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { - attrs - .iter() - .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) - .cloned() - .collect() -} - -/// Returns true for `mod foo;`, false for `mod foo { .. }`. -fn is_mod_decl(item: &ast::Item) -> bool { - match item.node { - ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), - _ => false, - } -} - -fn contains_macro_use_attr(attrs: &[ast::Attribute], span: Span) -> bool { - attr::contains_name(&filter_inline_attrs(attrs, span), "macro_use") -} - -/// Returns true for `mod foo;` without any inline attributes. -/// We cannot reorder modules with attributes because doing so can break the code. -/// e.g. `#[macro_use]`. -fn is_mod_decl_without_attr(item: &ast::Item) -> bool { - is_mod_decl(item) && !contains_macro_use_attr(&item.attrs, item.span()) -} - -fn is_use_item(item: &ast::Item) -> bool { - match item.node { - ast::ItemKind::Use(_) => true, - _ => false, - } -} - -fn is_use_item_without_attr(item: &ast::Item) -> bool { - is_use_item(item) && !contains_macro_use_attr(&item.attrs, item.span()) -} - -fn is_extern_crate(item: &ast::Item) -> bool { - match item.node { - ast::ItemKind::ExternCrate(..) => true, - _ => false, - } -} - -fn is_extern_crate_without_attr(item: &ast::Item) -> bool { - is_extern_crate(item) && !contains_macro_use_attr(&item.attrs, item.span()) -} - -/// Creates a string slice corresponding to the specified span. -pub struct SnippetProvider<'a> { - /// A pointer to the content of the file we are formatting. - big_snippet: &'a str, - /// A position of the start of `big_snippet`, used as an offset. - start_pos: usize, -} - -impl<'a> SnippetProvider<'a> { - pub fn span_to_snippet(&self, span: Span) -> Option<&str> { - let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; - let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; - Some(&self.big_snippet[start_index..end_index]) - } - - pub fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { - let start_pos = start_pos.to_usize(); - SnippetProvider { - big_snippet, - start_pos, - } - } -} - -pub struct FmtVisitor<'a> { - pub parse_session: &'a ParseSess, - pub codemap: &'a CodeMap, - pub buffer: String, - pub last_pos: BytePos, - // FIXME: use an RAII util or closure for indenting - pub block_indent: Indent, - pub config: &'a Config, - pub is_if_else_block: bool, - pub snippet_provider: &'a SnippetProvider<'a>, - pub line_number: usize, - pub skipped_range: Vec<(usize, usize)>, -} - -impl<'b, 'a: 'b> FmtVisitor<'a> { - pub fn shape(&self) -> Shape { - Shape::indented(self.block_indent, self.config) - } - - fn visit_stmt(&mut self, stmt: &ast::Stmt) { - debug!( - "visit_stmt: {:?} {:?}", - self.codemap.lookup_char_pos(stmt.span.lo()), - self.codemap.lookup_char_pos(stmt.span.hi()) - ); - - match stmt.node { - ast::StmtKind::Item(ref item) => { - self.visit_item(item); - } - ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - if contains_skip(get_attrs_from_stmt(stmt)) { - self.push_skipped_with_span(stmt.span()); - } else { - let rewrite = stmt.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(stmt.span(), rewrite) - } - } - ast::StmtKind::Mac(ref mac) => { - let (ref mac, _macro_style, ref attrs) = **mac; - if self.visit_attrs(attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(stmt.span()); - } else { - self.visit_mac(mac, None, MacroPosition::Statement); - } - self.format_missing(stmt.span.hi()); - } - } - } - - pub fn visit_block( - &mut self, - b: &ast::Block, - inner_attrs: Option<&[ast::Attribute]>, - has_braces: bool, - ) { - debug!( - "visit_block: {:?} {:?}", - self.codemap.lookup_char_pos(b.span.lo()), - self.codemap.lookup_char_pos(b.span.hi()) - ); - - // Check if this block has braces. - let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); - - self.last_pos = self.last_pos + brace_compensation; - self.block_indent = self.block_indent.block_indent(self.config); - self.push_str("{"); - - if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(first_stmt) = b.stmts.first() { - let attr_lo = inner_attrs - .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) - .or_else(|| { - // Attributes for an item in a statement position - // do not belong to the statement. (rust-lang/rust#34459) - if let ast::StmtKind::Item(ref item) = first_stmt.node { - item.attrs.first() - } else { - first_stmt.attrs().first() - }.and_then(|attr| { - // Some stmts can have embedded attributes. - // e.g. `match { #![attr] ... }` - let attr_lo = attr.span.lo(); - if attr_lo < first_stmt.span.lo() { - Some(attr_lo) - } else { - None - } - }) - }); - - let snippet = self.snippet(mk_sp( - self.last_pos, - attr_lo.unwrap_or(first_stmt.span.lo()), - )); - let len = CommentCodeSlices::new(snippet) - .nth(0) - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal { - s.rfind('\n') - } else { - None - } - }); - if let Some(len) = len { - self.last_pos = self.last_pos + BytePos::from_usize(len); - } - } - } - - // Format inner attributes if available. - let skip_rewrite = if let Some(attrs) = inner_attrs { - self.visit_attrs(attrs, ast::AttrStyle::Inner) - } else { - false - }; - - if skip_rewrite { - self.push_rewrite(b.span, None); - self.close_block(false); - self.last_pos = source!(self, b.span).hi(); - return; - } - - self.walk_block_stmts(b); - - if !b.stmts.is_empty() { - if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { - if utils::semicolon_for_expr(&self.get_context(), expr) { - self.push_str(";"); - } - } - } - - let mut remove_len = BytePos(0); - if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(stmt) = b.stmts.last() { - let snippet = self.snippet(mk_sp( - stmt.span.hi(), - source!(self, b.span).hi() - brace_compensation, - )); - let len = CommentCodeSlices::new(snippet) - .last() - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal && s.trim().is_empty() { - Some(s.len()) - } else { - None - } - }); - if let Some(len) = len { - remove_len = BytePos::from_usize(len); - } - } - } - - let unindent_comment = (self.is_if_else_block && !b.stmts.is_empty()) && { - let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; - let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); - snippet.contains("//") || snippet.contains("/*") - }; - // FIXME: we should compress any newlines here to just one - if unindent_comment { - self.block_indent = self.block_indent.block_unindent(self.config); - } - self.format_missing_with_indent( - source!(self, b.span).hi() - brace_compensation - remove_len, - ); - if unindent_comment { - self.block_indent = self.block_indent.block_indent(self.config); - } - self.close_block(unindent_comment); - self.last_pos = source!(self, b.span).hi(); - } - - // FIXME: this is a terrible hack to indent the comments between the last - // item in the block and the closing brace to the block's level. - // The closing brace itself, however, should be indented at a shallower - // level. - fn close_block(&mut self, unindent_comment: bool) { - let total_len = self.buffer.len(); - let chars_too_many = if unindent_comment { - 0 - } else if self.config.hard_tabs() { - 1 - } else { - self.config.tab_spaces() - }; - self.buffer.truncate(total_len - chars_too_many); - self.push_str("}"); - self.block_indent = self.block_indent.block_unindent(self.config); - } - - // Note that this only gets called for function definitions. Required methods - // on traits do not get handled here. - fn visit_fn( - &mut self, - fk: visit::FnKind, - generics: &ast::Generics, - fd: &ast::FnDecl, - s: Span, - defaultness: ast::Defaultness, - inner_attrs: Option<&[ast::Attribute]>, - ) { - let indent = self.block_indent; - let block; - let rewrite = match fk { - visit::FnKind::ItemFn(ident, _, _, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { - block = b; - self.rewrite_fn( - indent, - ident, - &FnSig::from_fn_kind(&fk, generics, fd, defaultness), - mk_sp(s.lo(), b.span.lo()), - b, - ) - } - visit::FnKind::Closure(_) => unreachable!(), - }; - - if let Some(fn_str) = rewrite { - self.format_missing_with_indent(source!(self, s).lo()); - self.push_str(&fn_str); - if let Some(c) = fn_str.chars().last() { - if c == '}' { - self.last_pos = source!(self, block.span).hi(); - return; - } - } - } else { - self.format_missing(source!(self, block.span).lo()); - } - - self.last_pos = source!(self, block.span).lo(); - self.visit_block(block, inner_attrs, true) - } - - pub fn visit_item(&mut self, item: &ast::Item) { - skip_out_of_file_lines_range_visitor!(self, item.span); - - // This is where we bail out if there is a skip attribute. This is only - // complex in the module case. It is complex because the module could be - // in a separate file and there might be attributes in both files, but - // the AST lumps them all together. - let filtered_attrs; - let mut attrs = &item.attrs; - match item.node { - // Module is inline, in this case we treat it like any other item. - _ if !is_mod_decl(item) => { - if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); - return; - } - } - // Module is not inline, but should be skipped. - ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => { - return; - } - // Module is not inline and should not be skipped. We want - // to process only the attributes in the current file. - ast::ItemKind::Mod(..) => { - filtered_attrs = filter_inline_attrs(&item.attrs, item.span()); - // Assert because if we should skip it should be caught by - // the above case. - assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); - attrs = &filtered_attrs; - } - _ => { - if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); - return; - } - } - } - - match item.node { - ast::ItemKind::Use(ref tree) => self.format_import(item, tree), - ast::ItemKind::Impl(..) => { - let snippet = self.snippet(item.span); - let where_span_end = snippet - .find_uncommented("{") - .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); - let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::Trait(..) => { - let rw = format_trait(&self.get_context(), item, self.block_indent); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::TraitAlias(ref generics, ref ty_param_bounds) => { - let shape = Shape::indented(self.block_indent, self.config); - let rw = format_trait_alias( - &self.get_context(), - item.ident, - generics, - ty_param_bounds, - shape, - ); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::ExternCrate(_) => { - let rw = rewrite_extern_crate(&self.get_context(), item); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { - self.visit_struct(&StructParts::from_item(item)); - } - ast::ItemKind::Enum(ref def, ref generics) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - self.visit_enum(item.ident, &item.vis, def, generics, item.span); - self.last_pos = source!(self, item.span).hi(); - } - ast::ItemKind::Mod(ref module) => { - let is_inline = !is_mod_decl(item); - self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); - } - ast::ItemKind::Mac(ref mac) => { - self.visit_mac(mac, Some(item.ident), MacroPosition::Item); - } - ast::ItemKind::ForeignMod(ref foreign_mod) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_foreign_mod(foreign_mod, item.span); - } - ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { - self.visit_static(&StaticParts::from_item(item)); - } - ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { - self.visit_fn( - visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), - generics, - decl, - item.span, - ast::Defaultness::Final, - Some(&item.attrs), - ) - } - ast::ItemKind::Ty(ref ty, ref generics) => { - let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, - item.ident, - ty, - generics, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::GlobalAsm(..) => { - let snippet = Some(self.snippet(item.span).to_owned()); - self.push_rewrite(item.span, snippet); - } - ast::ItemKind::MacroDef(ref def) => { - let rewrite = rewrite_macro_def( - &self.get_context(), - self.shape(), - self.block_indent, - def, - item.ident, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } - } - } - - pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { - skip_out_of_file_lines_range_visitor!(self, ti.span); - - if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ti.span()); - return; - } - - match ti.node { - ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), - ast::TraitItemKind::Method(ref sig, None) => { - let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); - self.push_rewrite(ti.span, rewrite); - } - ast::TraitItemKind::Method(ref sig, Some(ref body)) => { - self.visit_fn( - visit::FnKind::Method(ti.ident, sig, None, body), - &ti.generics, - &sig.decl, - ti.span, - ast::Defaultness::Final, - Some(&ti.attrs), - ); - } - ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { - let rewrite = rewrite_associated_type( - ti.ident, - type_default.as_ref(), - Some(type_param_bounds), - &self.get_context(), - self.block_indent, - ); - self.push_rewrite(ti.span, rewrite); - } - ast::TraitItemKind::Macro(ref mac) => { - self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); - } - } - } - - pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { - skip_out_of_file_lines_range_visitor!(self, ii.span); - - if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ii.span()); - return; - } - - match ii.node { - ast::ImplItemKind::Method(ref sig, ref body) => { - self.visit_fn( - visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), - &ii.generics, - &sig.decl, - ii.span, - ii.defaultness, - Some(&ii.attrs), - ); - } - ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_impl_type( - ii.ident, - ii.defaultness, - Some(ty), - None, - &self.get_context(), - self.block_indent, - ); - self.push_rewrite(ii.span, rewrite); - } - ast::ImplItemKind::Macro(ref mac) => { - self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); - } - } - } - - fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { - skip_out_of_file_lines_range_visitor!(self, mac.span); - - // 1 = ; - let shape = self.shape().sub_width(1).unwrap(); - let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); - self.push_rewrite(mac.span, rewrite); - } - - pub fn push_str(&mut self, s: &str) { - self.line_number += count_newlines(s); - self.buffer.push_str(s); - } - - fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { - if let Some(ref s) = rewrite { - self.push_str(s); - } else { - let snippet = self.snippet(span); - self.push_str(snippet); - } - self.last_pos = source!(self, span).hi(); - } - - pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { - self.format_missing_with_indent(source!(self, span).lo()); - self.push_rewrite_inner(span, rewrite); - } - - pub fn push_skipped_with_span(&mut self, span: Span) { - self.format_missing_with_indent(source!(self, span).lo()); - let lo = self.line_number + 1; - self.push_rewrite_inner(span, None); - let hi = self.line_number + 1; - self.skipped_range.push((lo, hi)); - } - - pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { - FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) - } - - pub fn from_codemap( - parse_session: &'a ParseSess, - config: &'a Config, - snippet_provider: &'a SnippetProvider, - ) -> FmtVisitor<'a> { - FmtVisitor { - parse_session, - codemap: parse_session.codemap(), - buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), - last_pos: BytePos(0), - block_indent: Indent::empty(), - config, - is_if_else_block: false, - snippet_provider, - line_number: 0, - skipped_range: vec![], - } - } - - pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { - self.snippet_provider.span_to_snippet(span) - } - - pub fn snippet(&'b self, span: Span) -> &'a str { - self.opt_snippet(span).unwrap() - } - - // Returns true if we should skip the following item. - pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { - if contains_skip(attrs) { - return true; - } - - let attrs: Vec<_> = attrs.iter().filter(|a| a.style == style).cloned().collect(); - if attrs.is_empty() { - return false; - } - - let rewrite = attrs.rewrite(&self.get_context(), self.shape()); - let span = mk_sp(attrs[0].span.lo(), attrs[attrs.len() - 1].span.hi()); - self.push_rewrite(span, rewrite); - - false - } - - fn reorder_items(&mut self, items_left: &[&ast::Item], is_item: &F, in_group: bool) -> usize - where - F: Fn(&ast::Item) -> bool, - { - let mut last = self.codemap.lookup_line_range(items_left[0].span()); - let item_length = items_left - .iter() - .take_while(|ppi| { - is_item(&***ppi) && (!in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) - }) - .count(); - let items = &items_left[..item_length]; - - let at_least_one_in_file_lines = items - .iter() - .any(|item| !out_of_file_lines_range!(self, item.span)); - - if at_least_one_in_file_lines { - self.format_imports(items); - } else { - for item in items { - self.push_rewrite(item.span, None); - } - } - - item_length - } - - fn walk_items(&mut self, mut items_left: &[&ast::Item]) { - macro try_reorder_items_with($reorder: ident, $in_group: ident, $pred: ident) { - if self.config.$reorder() && $pred(&*items_left[0]) { - let used_items_len = - self.reorder_items(items_left, &$pred, self.config.$in_group()); - let (_, rest) = items_left.split_at(used_items_len); - items_left = rest; - continue; - } - } - - while !items_left.is_empty() { - // If the next item is a `use`, `extern crate` or `mod`, then extract it and any - // subsequent items that have the same item kind to be reordered within - // `format_imports`. Otherwise, just format the next item for output. - { - try_reorder_items_with!( - reorder_imports, - reorder_imports_in_group, - is_use_item_without_attr - ); - try_reorder_items_with!( - reorder_extern_crates, - reorder_extern_crates_in_group, - is_extern_crate_without_attr - ); - try_reorder_items_with!(reorder_modules, reorder_modules, is_mod_decl_without_attr); - } - // Reaching here means items were not reordered. There must be at least - // one item left in `items_left`, so calling `unwrap()` here is safe. - let (item, rest) = items_left.split_first().unwrap(); - self.visit_item(item); - items_left = rest; - } - } - - fn walk_mod_items(&mut self, m: &ast::Mod) { - self.walk_items(&ptr_vec_to_ref_vec(&m.items)); - } - - fn walk_stmts(&mut self, stmts: &[ast::Stmt]) { - fn to_stmt_item(stmt: &ast::Stmt) -> Option<&ast::Item> { - match stmt.node { - ast::StmtKind::Item(ref item) => Some(&**item), - _ => None, - } - } - - if stmts.is_empty() { - return; - } - - // Extract leading `use ...;`. - let items: Vec<_> = stmts - .iter() - .take_while(|stmt| to_stmt_item(stmt).map_or(false, is_use_item)) - .filter_map(|stmt| to_stmt_item(stmt)) - .collect(); - - if items.is_empty() { - self.visit_stmt(&stmts[0]); - self.walk_stmts(&stmts[1..]); - } else { - self.walk_items(&items); - self.walk_stmts(&stmts[items.len()..]); - } - } - - fn walk_block_stmts(&mut self, b: &ast::Block) { - self.walk_stmts(&b.stmts) - } - - fn format_mod( - &mut self, - m: &ast::Mod, - vis: &ast::Visibility, - s: Span, - ident: ast::Ident, - attrs: &[ast::Attribute], - is_internal: bool, - ) { - self.push_str(&*utils::format_visibility(vis)); - self.push_str("mod "); - self.push_str(&ident.to_string()); - - if is_internal { - match self.config.brace_style() { - BraceStyle::AlwaysNextLine => { - let sep_str = format!("\n{}{{", self.block_indent.to_string(self.config)); - self.push_str(&sep_str); - } - _ => self.push_str(" {"), - } - // Hackery to account for the closing }. - let mod_lo = self.codemap.span_after(source!(self, s), "{"); - let body_snippet = - self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); - let body_snippet = body_snippet.trim(); - if body_snippet.is_empty() { - self.push_str("}"); - } else { - self.last_pos = mod_lo; - self.block_indent = self.block_indent.block_indent(self.config); - self.visit_attrs(attrs, ast::AttrStyle::Inner); - self.walk_mod_items(m); - self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); - self.close_block(false); - } - self.last_pos = source!(self, m.inner).hi(); - } else { - self.push_str(";"); - self.last_pos = source!(self, s).hi(); - } - } - - pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { - self.block_indent = Indent::empty(); - self.walk_mod_items(m); - self.format_missing_with_indent(filemap.end_pos); - } - - pub fn skip_empty_lines(&mut self, end_pos: BytePos) { - while let Some(pos) = self.codemap - .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") - { - if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { - if snippet.trim().is_empty() { - self.last_pos = pos; - } else { - return; - } - } - } - } - - pub fn get_context(&self) -> RewriteContext { - RewriteContext { - parse_session: self.parse_session, - codemap: self.codemap, - config: self.config, - inside_macro: false, - use_block: false, - is_if_else_block: false, - force_one_line_chain: false, - snippet_provider: self.snippet_provider, - } - } -} - -impl Rewrite for ast::NestedMetaItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), - ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), - } - } -} - -impl Rewrite for ast::MetaItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - Some(match self.node { - ast::MetaItemKind::Word => String::from(&*self.name.as_str()), - ast::MetaItemKind::List(ref list) => { - let name = self.name.as_str(); - // 1 = `(`, 2 = `]` and `)` - let item_shape = shape - .visual_indent(0) - .shrink_left(name.len() + 1) - .and_then(|s| s.sub_width(2))?; - let items = itemize_list( - context.codemap, - list.iter(), - ")", - ",", - |nested_meta_item| nested_meta_item.span.lo(), - |nested_meta_item| nested_meta_item.span.hi(), - |nested_meta_item| nested_meta_item.rewrite(context, item_shape), - self.span.lo(), - self.span.hi(), - false, - ); - let item_vec = items.collect::>(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: item_shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - format!("{}({})", name, write_list(&item_vec, &fmt)?) - } - ast::MetaItemKind::NameValue(ref literal) => { - let name = self.name.as_str(); - // 3 = ` = ` - let lit_shape = shape.shrink_left(name.len() + 3)?; - let value = rewrite_literal(context, literal, lit_shape)?; - format!("{} = {}", name, value) - } - }) - } -} - -impl Rewrite for ast::Attribute { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let prefix = match self.style { - ast::AttrStyle::Inner => "#!", - ast::AttrStyle::Outer => "#", - }; - let snippet = context.snippet(self.span); - if self.is_sugared_doc { - let doc_shape = Shape { - width: cmp::min(shape.width, context.config.comment_width()) - .checked_sub(shape.indent.width()) - .unwrap_or(0), - ..shape - }; - rewrite_comment(snippet, false, doc_shape, context.config) - } else { - if contains_comment(snippet) { - return Some(snippet.to_owned()); - } - // 1 = `[` - let shape = shape.offset_left(prefix.len() + 1)?; - self.meta()? - .rewrite(context, shape) - .map(|rw| format!("{}[{}]", prefix, rw)) - } - } -} - -/// Returns the first group of attributes that fills the given predicate. -/// We consider two doc comments are in different group if they are separated by normal comments. -fn take_while_with_pred<'a, P>( - context: &RewriteContext, - attrs: &'a [ast::Attribute], - pred: P, -) -> &'a [ast::Attribute] -where - P: Fn(&ast::Attribute) -> bool, -{ - let mut last_index = 0; - let mut iter = attrs.iter().enumerate().peekable(); - while let Some((i, attr)) = iter.next() { - if !pred(attr) { - break; - } - if let Some(&(_, next_attr)) = iter.peek() { - // Extract comments between two attributes. - let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); - let snippet = context.snippet(span_between_attr); - if count_newlines(snippet) >= 2 || snippet.contains('/') { - break; - } - } - last_index = i; - } - if last_index == 0 { - &[] - } else { - &attrs[..last_index + 1] - } -} - -fn rewrite_first_group_attrs( - context: &RewriteContext, - attrs: &[ast::Attribute], - shape: Shape, -) -> Option<(usize, String)> { - if attrs.is_empty() { - return Some((0, String::new())); - } - // Rewrite doc comments - let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); - if !sugared_docs.is_empty() { - let snippet = sugared_docs - .iter() - .map(|a| context.snippet(a.span)) - .collect::>() - .join("\n"); - return Some(( - sugared_docs.len(), - rewrite_comment(&snippet, false, shape, context.config)?, - )); - } - // Rewrite `#[derive(..)]`s. - if context.config.merge_derives() { - let derives = take_while_with_pred(context, attrs, is_derive); - if !derives.is_empty() { - let mut derive_args = vec![]; - for derive in derives { - derive_args.append(&mut get_derive_args(context, derive)?); - } - return Some((derives.len(), format_derive(context, &derive_args, shape)?)); - } - } - // Rewrite the first attribute. - Some((1, attrs[0].rewrite(context, shape)?)) -} - -fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { - // Look at before and after comment and see if there are any empty lines. - let comment_begin = comment.chars().position(|c| c == '/'); - let len = comment_begin.unwrap_or_else(|| comment.len()); - let mlb = count_newlines(&comment[..len]) > 1; - let mla = if comment_begin.is_none() { - mlb - } else { - let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); - let len = comment_end.unwrap(); - comment - .chars() - .rev() - .take(len) - .filter(|c| *c == '\n') - .count() > 1 - }; - (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) -} - -impl<'a> Rewrite for [ast::Attribute] { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if self.is_empty() { - return Some(String::new()); - } - let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?; - if self.len() == 1 || first_group_len == self.len() { - Some(first_group_str) - } else { - let rest_str = self[first_group_len..].rewrite(context, shape)?; - let missing_span = mk_sp( - self[first_group_len - 1].span.hi(), - self[first_group_len].span.lo(), - ); - // Preserve an empty line before/after doc comments. - if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { - let snippet = context.snippet(missing_span); - let (mla, mlb) = has_newlines_before_after_comment(snippet); - let comment = ::comment::recover_missing_comment_in_span( - missing_span, - shape.with_max_width(context.config), - context, - 0, - )?; - let comment = if comment.is_empty() { - format!("\n{}", mlb) - } else { - format!("{}{}\n{}", mla, comment, mlb) - }; - Some(format!( - "{}{}{}{}", - first_group_str, - comment, - shape.indent.to_string(context.config), - rest_str - )) - } else { - combine_strs_with_missing_comments( - context, - &first_group_str, - &rest_str, - missing_span, - shape, - false, - ) - } - } - } -} - -// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. -fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option { - let mut result = String::with_capacity(128); - result.push_str("#[derive("); - // 11 = `#[derive()]` - let initial_budget = shape.width.checked_sub(11)?; - let mut budget = initial_budget; - let num = derive_args.len(); - for (i, a) in derive_args.iter().enumerate() { - // 2 = `, ` or `)]` - let width = a.len() + 2; - if width > budget { - if i > 0 { - // Remove trailing whitespace. - result.pop(); - } - result.push('\n'); - // 9 = `#[derive(` - result.push_str(&(shape.indent + 9).to_string(context.config)); - budget = initial_budget; - } else { - budget = budget.checked_sub(width).unwrap_or(0); - } - result.push_str(a); - if i != num - 1 { - result.push_str(", ") - } - } - result.push_str(")]"); - Some(result) -} - -fn is_derive(attr: &ast::Attribute) -> bool { - attr.check_name("derive") -} - -/// Returns the arguments of `#[derive(...)]`. -fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { - attr.meta_item_list().map(|meta_item_list| { - meta_item_list - .iter() - .map(|nested_meta_item| context.snippet(nested_meta_item.span)) - .collect() - }) -} - -// Rewrite `extern crate foo;` WITHOUT attributes. -pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { - assert!(is_extern_crate(item)); - let new_str = context.snippet(item.span); - Some(if contains_comment(new_str) { - new_str.to_owned() - } else { - let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); - String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) - }) -} - -fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { - match stmt.node { - ast::StmtKind::Local(ref local) => &local.attrs, - ast::StmtKind::Item(ref item) => &item.attrs, - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, - ast::StmtKind::Mac(ref mac) => &mac.2, - } -} diff --git a/tests/config/disable_all_formatting.toml b/tests/config/disable_all_formatting.toml deleted file mode 100644 index c7ad93bafe3..00000000000 --- a/tests/config/disable_all_formatting.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/tests/config/issue-1111.toml b/tests/config/issue-1111.toml deleted file mode 100755 index 44148a2d3c3..00000000000 --- a/tests/config/issue-1111.toml +++ /dev/null @@ -1 +0,0 @@ -reorder_imports = true diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml deleted file mode 100644 index d03ac281acb..00000000000 --- a/tests/config/small_tabs.toml +++ /dev/null @@ -1,12 +0,0 @@ -max_width = 100 -comment_width = 80 -tab_spaces = 2 -newline_style = "Unix" -brace_style = "SameLineWhere" -fn_args_density = "Tall" -trailing_comma = "Vertical" -indent_style = "Block" -report_todo = "Always" -report_fixme = "Never" -reorder_imports = false -format_strings = true diff --git a/tests/coverage/source/comments.rs b/tests/coverage/source/comments.rs deleted file mode 100644 index e79557af713..00000000000 --- a/tests/coverage/source/comments.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-write_mode: coverage -/// Here's a doc comment! -fn main() { - // foo is bar - let foo = "bar"; - // loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment!!!!! -} diff --git a/tests/coverage/target/comments.rs b/tests/coverage/target/comments.rs deleted file mode 100644 index 8f9c223aef2..00000000000 --- a/tests/coverage/target/comments.rs +++ /dev/null @@ -1,7 +0,0 @@ -XX XXXXXXXXXXXXXXXXXXX XXXXXXXX -/// Here's a doc comment! -fn main() { - XX XXX XX XXX - let foo = "bar"; - XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX -} diff --git a/tests/source/assignment.rs b/tests/source/assignment.rs deleted file mode 100644 index d5860532086..00000000000 --- a/tests/source/assignment.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Test assignment - -fn main() { - let some_var : Type ; - - let mut mutable; - - let variable = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; - - variable = LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; - - let single_line_fit = - DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; - - single_line_fit = 5;single_lit_fit >>= 10; -} - -fn break_meee() { - { - (block_start, block_size, margin_block_start, margin_block_end) = match (block_start, - block_end, - block_size) { - x => 1, - _ => 2, - }; - } -} - -// #2018 -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/tests/source/associated-types-bounds-wrapping.rs b/tests/source/associated-types-bounds-wrapping.rs deleted file mode 100644 index 8f5e2172569..00000000000 --- a/tests/source/associated-types-bounds-wrapping.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-max_width: 100 -// Test proper wrapping of long associated type bounds - -pub trait HttpService { - type WsService: 'static + Service; -} diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs deleted file mode 100644 index 6653dd2daa9..00000000000 --- a/tests/source/attrib.rs +++ /dev/null @@ -1,152 +0,0 @@ -// rustfmt-wrap_comments: true -// Test attributes and doc comments are preserved. - -//! Doc comment - -#![attribute] - -//! Crate doc comment - -// Comment - -// Comment on attribute -#![the(attribute)] - -// Another comment - -#[invalid attribute] -fn foo() {} - -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. - -/// Blah blah blah. -impl Bar { - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - #[an_attribute] - fn foo(&mut self) -> isize { - } - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - pub fn f2(self) { - (foo, bar) - } - - #[another_attribute] - fn f3(self) -> Dog { - } - - /// Blah blah bing. - - #[attrib1] - /// Blah blah bing. - #[attrib2] - // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo loooooooooooong. - /// Blah blah bing. - fn f4(self) -> Cat { - } - - // We want spaces around `=` - #[cfg(feature="nightly")] - fn f5(self) -> Monkey {} -} - -// #984 -struct Foo { - # [ derive ( Clone , PartialEq , Debug , Deserialize , Serialize ) ] - foo: usize, -} - -// #1668 - -/// Default path (*nix) -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -fn foo() { - #[cfg(target_os = "freertos")] - match port_id { - 'a' | 'A' => GpioPort { port_address: GPIO_A }, - 'b' | 'B' => GpioPort { port_address: GPIO_B }, - _ => panic!(), - } - - #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] - let x = 3; -} - -// #1777 -#[test] -#[should_panic(expected = "(")] -#[should_panic(expected = /* ( */ "(")] -#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] -#[should_panic( - /* (((((((( *//* - (((((((((()(((((((( */ - expected = "(" - // (((((((( -)] -fn foo() {} - -// #1799 -fn issue_1799() { - #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 - Some( Err(error) ) ; - - #[allow(unreachable_code)] - // https://github.com/rust-lang/rust/issues/43336 - Some( Err(error) ) ; -} - -// Formatting inner attributes -fn inner_attributes() { - #![ this_is_an_inner_attribute ( foo ) ] - - foo(); -} - -impl InnerAttributes() { - #![ this_is_an_inner_attribute ( foo ) ] - - fn foo() {} -} - -mod InnerAttributes { - #![ this_is_an_inner_attribute ( foo ) ] -} - -fn attributes_on_statements() { - // Local - # [ attr ( on ( local ) ) ] - let x = 3; - - // Item - # [ attr ( on ( item ) ) ] - use foo; - - // Expr - # [ attr ( on ( expr ) ) ] - {} - - // Semi - # [ attr ( on ( semi ) ) ] - foo(); - - // Mac - # [ attr ( on ( mac ) ) ] - foo!(); -} - -// Large derive -#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] -pub struct HP(pub u8); diff --git a/tests/source/big-impl-rfc.rs b/tests/source/big-impl-rfc.rs deleted file mode 100644 index 737dd5aeb6a..00000000000 --- a/tests/source/big-impl-rfc.rs +++ /dev/null @@ -1,125 +0,0 @@ -// rustfmt-indent_style: Block - -// #1357 -impl< - 'a, - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - Groupby, - DB, -> InternalBoxedDsl<'a, DB> - for SelectStatement< - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - GroupBy, - > where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} - -// #1689 -impl SubSelectDirect - where - M: select::Selector, - S: event::Stream, - F: for<'t> FnMut(transform::Api< - 't, - Stream>, - >) - -> transform::Api<'t, X>, - X: event::Stream, -{ -} diff --git a/tests/source/big-impl.rs b/tests/source/big-impl.rs deleted file mode 100644 index c36b7e6cadb..00000000000 --- a/tests/source/big-impl.rs +++ /dev/null @@ -1,104 +0,0 @@ -// #1357 -impl< - 'a, - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - Groupby, - DB, -> InternalBoxedDsl<'a, DB> - for SelectStatement< - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - GroupBy, - > where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl Foo - for Bar { - fn foo() {} -} diff --git a/tests/source/break-and-continue.rs b/tests/source/break-and-continue.rs deleted file mode 100644 index c01d8a07845..00000000000 --- a/tests/source/break-and-continue.rs +++ /dev/null @@ -1,23 +0,0 @@ -// break and continue formatting - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a; - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b; - } - - let x = loop { - break 5; - }; - - let x = 'c: loop { - break 'c 5; - }; -} diff --git a/tests/source/catch.rs b/tests/source/catch.rs deleted file mode 100644 index 64cc9e7a207..00000000000 --- a/tests/source/catch.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![feature(catch_expr)] - -fn main() { - let x = do catch { - foo()? - }; - - let x = do catch /* Invisible comment */ { foo()? }; - - let x = do catch { - unsafe { foo()? } - }; - - let y = match (do catch { - foo()? - }) { - _ => (), - }; - - do catch { - foo()?; - }; - - do catch { - // Regular do catch block - }; -} diff --git a/tests/source/chains-indent-tabbed.rs b/tests/source/chains-indent-tabbed.rs deleted file mode 100644 index 6a9a40cb98f..00000000000 --- a/tests/source/chains-indent-tabbed.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-indent_style: Block - -fn test() { - let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); -} diff --git a/tests/source/chains-indent-visual.rs b/tests/source/chains-indent-visual.rs deleted file mode 100644 index 8fdd3c4cabf..00000000000 --- a/tests/source/chains-indent-visual.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-indent_style: Visual - -fn test() { - let x = my_long_function().my_even_longer_function().my_nested_function().some_random_name().another_function().do_it(); -} diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs deleted file mode 100644 index 466f6840887..00000000000 --- a/tests/source/chains-visual.rs +++ /dev/null @@ -1,159 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Visual -// Test chain formatting. - -fn main() { - // Don't put chains on a single line if it wasn't so in source. - let a = b .c - .d.1 - .foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x() - .y(|| match cond() { true => (), false => () }); - - loong_func() - .quux(move || if true { - 1 - } else { - 2 - }); - - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }).method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx - .map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }).filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { - field1: val1, - field2: val2, - }; - - let x = Foo { - field1: val1, - field2: val2, - }.method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } - - if cond { some(); } else { none(); } - .bar() - .baz(); - - Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); - - Foo { y: i_am_multi_line, z: ok } - .baz(|| { - force(); multiline(); - }) - .quux(); - - a + match x { true => "yay!", false => "boo!" }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained( - self.id, constraints)).unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn issue_1389() { - let names = String::from_utf8(names)?.split('|').map(str::to_owned).collect(); -} - -fn issue1217() -> Result { -let random_chars: String = OsRng::new()? - .gen_ascii_chars() - .take(self.bit_length) - .collect(); - - Ok(Mnemonic::new(&random_chars)) -} - -fn issue1236(options: Vec) -> Result> { -let process = Command::new("dmenu").stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .chain_err(|| "failed to spawn dmenu")?; -} - -fn issue1434() { - for _ in 0..100 { - let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { - format!("could not read prototype ID at offset {:#010x}", - current_offset) - })?; - } -} - -fn issue2264() { - { - something.function() - .map(|| { - if let a_very_very_very_very_very_very_very_very_long_variable = - compute_this_variable() - { - println!("Hello"); - } - }) - .collect(); - } -} diff --git a/tests/source/chains.rs b/tests/source/chains.rs deleted file mode 100644 index 0ed52ae61be..00000000000 --- a/tests/source/chains.rs +++ /dev/null @@ -1,231 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-use_small_heuristics: false -// Test chain formatting. - -fn main() { - let a = b .c - .d.1 - .foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); - - let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x() - .y(|| match cond() { true => (), false => () }); - - loong_func() - .quux(move || if true { - 1 - } else { - 2 - }); - - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }).method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx - .map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - body.fold(Body::new(), |mut body, chunk| { - body.extend(chunk); - Ok(body) - }).and_then(move |body| { - let req = Request::from_parts(parts, body); - f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) - }); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }).filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { - field1: val1, - field2: val2, - }; - - let x = Foo { - field1: val1, - field2: val2, - }.method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } - - if cond { some(); } else { none(); } - .bar() - .baz(); - - Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); - - Foo { y: i_am_multi_line, z: ok } - .baz(|| { - force(); multiline(); - }) - .quux(); - - a + match x { true => "yay!", false => "boo!" }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained( - self.id, constraints)).unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn try_shorthand() { - let x = expr?; - let y = expr.kaas()?.test(); - let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; - let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); - let zzzz = expr?.another?.another?.another?.another?; - let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??; - - let y = a.very .loooooooooooooooooooooooooooooooooooooong() .chain() - .inside() .weeeeeeeeeeeeeee()? .test() .0 - .x; - - parameterized(f, - substs, - def_id, - Ns::Value, - &[], - |tcx| tcx.lookup_item_type(def_id).generics)?; - fooooooooooooooooooooooooooo()?.bar()?.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; -} - -fn issue_1004() { - match *self { - ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), - } - ?; - - ty::tls::with(|tcx| { - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - }) - ?; -} - -fn issue1392() { - test_method(r#" - if foo { - a(); - } - else { - b(); - } - "#.trim()); -} - -// #2067 -impl Settings { - fn save(&self) -> Result<()> { - let mut file = File::create(&settings_path).chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; - } -} - -fn issue2126() { - { - { - { - { - { - let x = self.span_from(sub_span.expect("No span found for struct arant variant")); - self.sspanpan_from_span(sub_span.expect("No span found for struct variant")); - let x = self.spanpan_from_span(sub_span.expect("No span found for struct variant"))?; - } - } - } - } - } -} - -// #2200 -impl Foo { - pub fn from_ast(diagnostic: &::errors::Handler, - attrs: &[ast::Attribute]) -> Attributes { - let other_attrs = attrs.iter().filter_map(|attr| { - attr.with_desugared_doc(|attr| { - if attr.check_name("doc") { - if let Some(mi) = attr.meta() { - if let Some(value) = mi.value_str() { - doc_strings.push(DocFragment::Include(line, - attr.span, - filename, - contents)); - } - } - } - }) - }).collect(); - } -} - -// #2415 -// Avoid orphan in chain -fn issue2415() { - let base_url = (|| { - // stuff - - Ok((|| { - // stuff - Some(value.to_string()) - })() - .ok_or("")?) - })() - .unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); -} diff --git a/tests/source/closure-block-inside-macro.rs b/tests/source/closure-block-inside-macro.rs deleted file mode 100644 index c1260592083..00000000000 --- a/tests/source/closure-block-inside-macro.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Block - -// #1547 -fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { - let index = *first as usize; - if index >= ENCODINGS.len() { - return; - } - let encoding = ENCODINGS[index]; - dispatch_test(encoding, &data[1..]); -}); diff --git a/tests/source/closure.rs b/tests/source/closure.rs deleted file mode 100644 index e93cc3fb40f..00000000000 --- a/tests/source/closure.rs +++ /dev/null @@ -1,213 +0,0 @@ -// rustfmt-normalize_comments: true -// Closures - -fn main() { - let square = ( |i: i32 | i * i ); - - let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); - - let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - }; - - let loooooooooooooong_name = |field| { - // format comments. - if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo() - } else { - field.span.lo() - }}; - - let unblock_me = |trivial| { - closure() - }; - - let empty = |arg| {}; - - let simple = |arg| { /* comment formatting */ foo(arg) }; - - let test = | | { do_something(); do_something_else(); }; - - let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - - let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; - - let simple_closure = move || -> () {}; - - let closure = |input: Ty| -> Option { - foo() - }; - - let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; - - |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; - arg2 * arg1 - temp }; - - let block_body_with_comment = args.iter() - .map(|a| { - // Emitting only dep-info is possible only for final crate type, as - // as others may emit required metadata for dependent crate types - if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { - "--emit=dep-info" - } else { a } - }); -} - -fn issue311() { - let func = |x| println!("{}", x); - - (func)(0.0); -} - -fn issue863() { - let closure = |x| match x { - 0 => true, - _ => false, - } == true; -} - -fn issue934() { - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; - - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish(); - }; -} - -impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { - pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { - match (&left.node, &right.node) { - (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) - } - } - } -} - -fn foo() { - lifetimes_iter___map(|lasdfasfd| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi() - }; - }); -} - -fn issue1405() { - open_raw_fd(fd, b'r') - .and_then(|file| Capture::new_raw(None, |_, err| unsafe { - raw::pcap_fopen_offline(file, err) - })); -} - -fn issue1466() { - let vertex_buffer = frame.scope(|ctx| { - let buffer = - ctx.create_host_visible_buffer::>(&vertices); - ctx.create_device_local_buffer(buffer) - }); -} - -fn issue470() { - {{{ - let explicit_arg_decls = - explicit_arguments.into_iter() - .enumerate() - .map(|(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); - block = this.pattern(block, - argument_extent, - hair::PatternRef::Hair(pattern), - &lvalue); - ArgDecl { ty: ty } - }); - }}} -} - -// #1509 -impl Foo { - pub fn bar(&self) { - Some(SomeType { - push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { - Ok(f) - })), - }) - } -} - -fn issue1329() { - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter -} - -fn issue325() { - let f = || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; -} - -fn issue1697() { - Test.func_a(A_VERY_LONG_CONST_VARIABLE_NAME, move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4) -} - -fn issue1694() { - foooooo(|_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| format!("refs/pull/{}/merge", pr_id)) -} - -fn issue1713() { - rayon::join( - || recurse(left, is_less, pred, limit), - || recurse(right, is_less, Some(pivot), limit), - ); - - rayon::join( - 1, - || recurse(left, is_less, pred, limit), - 2, - || recurse(right, is_less, Some(pivot), limit), - ); -} - -fn issue2063() { - |ctx: Ctx<(String, String)>| -> io::Result { - Ok(Response::new().with_body(ctx.params.0)) - } -} - -fn issue1524() { - let f = |x| {{{{x}}}}; - let f = |x| {{{x}}}; - let f = |x| {{x}}; - let f = |x| {x}; - let f = |x| x; -} - -fn issue2171() { - foo(|| unsafe { - if PERIPHERALS { - loop {} - } else { - PERIPHERALS = true; - } - }) -} - -fn issue2207() { - a.map(|_| unsafe { - a_very_very_very_very_very_very_very_long_function_name_or_anything_else() - }.to_string()) -} - -fn issue2262() { - result.init(&mut result.slave.borrow_mut(), &mut (result.strategy)()).map_err(|factory| Error { - factory, - slave: None, - })?; -} diff --git a/tests/source/comment.rs b/tests/source/comment.rs deleted file mode 100644 index b6ce5267fcb..00000000000 --- a/tests/source/comment.rs +++ /dev/null @@ -1,90 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//! Doc comment -fn test() { - /*! - * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam */ - -// comment - // comment2 - - code(); /* leave this comment alone! - * ok? */ - - /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - * viverra nec consectetur ante hendrerit. Donec et mollis dolor. - * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - * felis, pulvinar a semper sed, adipiscing id dolor. */ - - // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); //dontchangeme - // or me - - // #1388 - const EXCEPTION_PATHS: &'static [&'static str] = - &[// std crates - "src/libstd/sys/", // Platform-specific code for std lives here. - "src/bootstrap"]; -} - - /// test123 -fn doc_comment() { -} - -fn chains() { - foo.bar(|| { - let x = 10; - /* comment */ x }) -} - -fn issue_1086() { - /**/ -} - -/* - * random comment */ - -fn main() {/* Test */} - -// #1643 -fn some_fn() /* some comment */ -{ -} - -fn some_fn1() -// some comment -{ -} - -fn some_fn2() // some comment -{ -} - -fn some_fn3() /* some comment some comment some comment some comment some comment some comment so */ -{ -} - -fn some_fn4() -/* some comment some comment some comment some comment some comment some comment some comment */ -{ -} - -// #1603 -pub enum Foo { - A, // `/** **/` - B, // `/*!` - C, -} diff --git a/tests/source/comment2.rs b/tests/source/comment2.rs deleted file mode 100644 index d68bb5483dc..00000000000 --- a/tests/source/comment2.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-wrap_comments: true - -/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. -pub mod foo {} diff --git a/tests/source/comment3.rs b/tests/source/comment3.rs deleted file mode 100644 index f19a8586334..00000000000 --- a/tests/source/comment3.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-wrap_comments: true - -//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. - -pub mod foo {} diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs deleted file mode 100644 index ff1445378d7..00000000000 --- a/tests/source/comment4.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow(dead_code)] // bar - -//! Doc comment -fn test() { -// comment - // comment2 - - code(); /* leave this comment alone! - * ok? */ - - /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - * viverra nec consectetur ante hendrerit. Donec et mollis dolor. - * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - * felis, pulvinar a semper sed, adipiscing id dolor. */ - - // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); //dontchangeme - // or me -} - - /// test123 -fn doc_comment() { -} - -/* -Regression test for issue #956 - -(some very important text) -*/ - -/* -fn debug_function() { - println!("hello"); -} -// */ - -#[link_section=".vectors"] -#[no_mangle] // Test this attribute is preserved. -#[cfg_attr(rustfmt, rustfmt_skip)] -pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/source/comment5.rs b/tests/source/comment5.rs deleted file mode 100644 index 2835d8b2578..00000000000 --- a/tests/source/comment5.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//@ special comment -//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@ -//@foo -fn test() {} - -//@@@ another special comment -//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@@@ -//@@@foo -fn bar() {} diff --git a/tests/source/comment_crlf_newline.rs b/tests/source/comment_crlf_newline.rs deleted file mode 100644 index 7a65f762f6c..00000000000 --- a/tests/source/comment_crlf_newline.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true -/* Block comments followed by CRLF newlines should not an extra newline at the end */ - -/* Something else */ diff --git a/tests/source/configs/blank_lines_lower_bound/1.rs b/tests/source/configs/blank_lines_lower_bound/1.rs deleted file mode 100644 index c6058a55b0a..00000000000 --- a/tests/source/configs/blank_lines_lower_bound/1.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-blank_lines_lower_bound: 1 - -fn foo() {} -fn bar() {} -// comment -fn foobar() {} - -fn foo1() {} -fn bar1() {} - -// comment - -fn foobar1() {} diff --git a/tests/source/configs/brace_style/fn_always_next_line.rs b/tests/source/configs/brace_style/fn_always_next_line.rs deleted file mode 100644 index d3bd9ac09aa..00000000000 --- a/tests/source/configs/brace_style/fn_always_next_line.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { - // body -} diff --git a/tests/source/configs/brace_style/fn_prefer_same_line.rs b/tests/source/configs/brace_style/fn_prefer_same_line.rs deleted file mode 100644 index 78a4495243d..00000000000 --- a/tests/source/configs/brace_style/fn_prefer_same_line.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { - // body -} diff --git a/tests/source/configs/brace_style/fn_same_line_where.rs b/tests/source/configs/brace_style/fn_same_line_where.rs deleted file mode 100644 index 3b78932e177..00000000000 --- a/tests/source/configs/brace_style/fn_same_line_where.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { - // body -} diff --git a/tests/source/configs/brace_style/item_always_next_line.rs b/tests/source/configs/brace_style/item_always_next_line.rs deleted file mode 100644 index 0cc19b34da7..00000000000 --- a/tests/source/configs/brace_style/item_always_next_line.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Item brace style - -enum Foo {} - -struct Bar {} - -struct Lorem { - ipsum: bool, -} - -struct Dolor where T: Eq { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/tests/source/configs/brace_style/item_prefer_same_line.rs b/tests/source/configs/brace_style/item_prefer_same_line.rs deleted file mode 100644 index 4412bc869a2..00000000000 --- a/tests/source/configs/brace_style/item_prefer_same_line.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor where T: Eq { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/tests/source/configs/brace_style/item_same_line_where.rs b/tests/source/configs/brace_style/item_same_line_where.rs deleted file mode 100644 index b8e69147dc5..00000000000 --- a/tests/source/configs/brace_style/item_same_line_where.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor where T: Eq { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/tests/source/configs/comment_width/above.rs b/tests/source/configs/comment_width/above.rs deleted file mode 100644 index 36187ce0af4..00000000000 --- a/tests/source/configs/comment_width/above.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/tests/source/configs/comment_width/below.rs b/tests/source/configs/comment_width/below.rs deleted file mode 100644 index abbc5930c4c..00000000000 --- a/tests/source/configs/comment_width/below.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 80 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/tests/source/configs/comment_width/ignore.rs b/tests/source/configs/comment_width/ignore.rs deleted file mode 100644 index c86e71c2898..00000000000 --- a/tests/source/configs/comment_width/ignore.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: false -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/tests/source/configs/condense_wildcard_suffixes/false.rs b/tests/source/configs/condense_wildcard_suffixes/false.rs deleted file mode 100644 index 3b967f35a8e..00000000000 --- a/tests/source/configs/condense_wildcard_suffixes/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: false -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, _, _) = (1, 2, 3, 4); -} diff --git a/tests/source/configs/condense_wildcard_suffixes/true.rs b/tests/source/configs/condense_wildcard_suffixes/true.rs deleted file mode 100644 index 3798a6b9902..00000000000 --- a/tests/source/configs/condense_wildcard_suffixes/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: true -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, _, _) = (1, 2, 3, 4); -} diff --git a/tests/source/configs/control_brace_style/always_next_line.rs b/tests/source/configs/control_brace_style/always_next_line.rs deleted file mode 100644 index c4ddad9ce27..00000000000 --- a/tests/source/configs/control_brace_style/always_next_line.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine -// Control brace style - -fn main() { - if lorem { println!("ipsum!"); } else { println!("dolor!"); } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/tests/source/configs/control_brace_style/always_same_line.rs b/tests/source/configs/control_brace_style/always_same_line.rs deleted file mode 100644 index a9c699d27e3..00000000000 --- a/tests/source/configs/control_brace_style/always_same_line.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine -// Control brace style - -fn main() { - if lorem { println!("ipsum!"); } else { println!("dolor!"); } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/tests/source/configs/control_brace_style/closing_next_line.rs b/tests/source/configs/control_brace_style/closing_next_line.rs deleted file mode 100644 index 1a74a28f26a..00000000000 --- a/tests/source/configs/control_brace_style/closing_next_line.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine -// Control brace style - -fn main() { - if lorem { println!("ipsum!"); } else { println!("dolor!"); } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/tests/source/configs/disable_all_formatting/false.rs b/tests/source/configs/disable_all_formatting/false.rs deleted file mode 100644 index 834ca7a3c89..00000000000 --- a/tests/source/configs/disable_all_formatting/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: false -// Disable all formatting - -fn main() { - if lorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/tests/source/configs/disable_all_formatting/true.rs b/tests/source/configs/disable_all_formatting/true.rs deleted file mode 100644 index 56955bf384d..00000000000 --- a/tests/source/configs/disable_all_formatting/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: true -// Disable all formatting - -fn main() { - iflorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/tests/source/configs/empty_item_single_line/false.rs b/tests/source/configs/empty_item_single_line/false.rs deleted file mode 100644 index 8fa74f28802..00000000000 --- a/tests/source/configs/empty_item_single_line/false.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-empty_item_single_line: false -// Empty impl on single line - -impl Lorem { - -} - -impl Ipsum { - -} - -fn lorem() { -} - -fn lorem() { - -} diff --git a/tests/source/configs/empty_item_single_line/true.rs b/tests/source/configs/empty_item_single_line/true.rs deleted file mode 100644 index 02e703d1904..00000000000 --- a/tests/source/configs/empty_item_single_line/true.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-empty_item_single_line: true -// Empty impl on single line - -impl Lorem { - -} - -impl Ipsum { - -} - -fn lorem() { -} - -fn lorem() { - -} diff --git a/tests/source/configs/error_on_line_overflow/false.rs b/tests/source/configs/error_on_line_overflow/false.rs deleted file mode 100644 index fa70ae78352..00000000000 --- a/tests/source/configs/error_on_line_overflow/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// Error on line overflow - -fn main() { - let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; -} diff --git a/tests/source/configs/fn_args_density/compressed.rs b/tests/source/configs/fn_args_density/compressed.rs deleted file mode 100644 index 86c0b42e53c..00000000000 --- a/tests/source/configs/fn_args_density/compressed.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/source/configs/fn_args_density/tall.rs b/tests/source/configs/fn_args_density/tall.rs deleted file mode 100644 index fc400e1c113..00000000000 --- a/tests/source/configs/fn_args_density/tall.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Tall -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/source/configs/fn_args_density/vertical.rs b/tests/source/configs/fn_args_density/vertical.rs deleted file mode 100644 index 20b1427d83d..00000000000 --- a/tests/source/configs/fn_args_density/vertical.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Vertical -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/source/configs/fn_single_line/false.rs b/tests/source/configs/fn_single_line/false.rs deleted file mode 100644 index 3d092f0c0bf..00000000000 --- a/tests/source/configs/fn_single_line/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_single_line: false -// Single-expression function on single line - -fn lorem() -> usize { - 42 -} - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/tests/source/configs/fn_single_line/true.rs b/tests/source/configs/fn_single_line/true.rs deleted file mode 100644 index 3cb0fdedf0b..00000000000 --- a/tests/source/configs/fn_single_line/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_single_line: true -// Single-expression function on single line - -fn lorem() -> usize { - 42 -} - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/tests/source/configs/force_explicit_abi/false.rs b/tests/source/configs/force_explicit_abi/false.rs deleted file mode 100644 index 3c48f8e0c78..00000000000 --- a/tests/source/configs/force_explicit_abi/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: false -// Force explicit abi - -extern { - pub static lorem: c_int; -} diff --git a/tests/source/configs/force_explicit_abi/true.rs b/tests/source/configs/force_explicit_abi/true.rs deleted file mode 100644 index e5ff6cf7dd7..00000000000 --- a/tests/source/configs/force_explicit_abi/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: true -// Force explicit abi - -extern { - pub static lorem: c_int; -} diff --git a/tests/source/configs/force_multiline_block/false.rs b/tests/source/configs/force_multiline_block/false.rs deleted file mode 100644 index b97e348e5da..00000000000 --- a/tests/source/configs/force_multiline_block/false.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-force_multiline_blocks: false -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| { - match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - } - }); -} diff --git a/tests/source/configs/force_multiline_block/true.rs b/tests/source/configs/force_multiline_block/true.rs deleted file mode 100644 index db9d3de4614..00000000000 --- a/tests/source/configs/force_multiline_block/true.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-force_multiline_blocks: true -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => if ipsum { - println!("dolor"); - }, - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - }); -} diff --git a/tests/source/configs/format_strings/false.rs b/tests/source/configs/format_strings/false.rs deleted file mode 100644 index ecca0d7d1fc..00000000000 --- a/tests/source/configs/format_strings/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/tests/source/configs/format_strings/true.rs b/tests/source/configs/format_strings/true.rs deleted file mode 100644 index 33731447821..00000000000 --- a/tests/source/configs/format_strings/true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 50 -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/tests/source/configs/hard_tabs/false.rs b/tests/source/configs/hard_tabs/false.rs deleted file mode 100644 index bf92162b424..00000000000 --- a/tests/source/configs/hard_tabs/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: false -// Hard tabs - -fn lorem() -> usize { -42 // spaces before 42 -} diff --git a/tests/source/configs/hard_tabs/true.rs b/tests/source/configs/hard_tabs/true.rs deleted file mode 100644 index 738922a4dfb..00000000000 --- a/tests/source/configs/hard_tabs/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: true -// Hard tabs - -fn lorem() -> usize { -42 // spaces before 42 -} diff --git a/tests/source/configs/indent_style/block_args.rs b/tests/source/configs/indent_style/block_args.rs deleted file mode 100644 index 4d2d280a16b..00000000000 --- a/tests/source/configs/indent_style/block_args.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-indent_style: Block -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { - // body -} - -// #1441 -extern "system" { - pub fn GetConsoleHistoryInfo(console_history_info: *mut ConsoleHistoryInfo) -> Boooooooooooooool; -} - -// rustfmt should not add trailing comma for variadic function. See #1623. -extern "C" { - pub fn variadic_fn(first_parameter: FirstParameterType, - second_parameter: SecondParameterType, - ...); -} - -// #1652 -fn deconstruct(foo: Bar) -> (SocketAddr, Header, Method, RequestUri, HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { -} diff --git a/tests/source/configs/indent_style/block_array.rs b/tests/source/configs/indent_style/block_array.rs deleted file mode 100644 index 8404f65f471..00000000000 --- a/tests/source/configs/indent_style/block_array.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Array layout - -fn main() { - let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; -} diff --git a/tests/source/configs/indent_style/block_call.rs b/tests/source/configs/indent_style/block_call.rs deleted file mode 100644 index c82b6b8e38f..00000000000 --- a/tests/source/configs/indent_style/block_call.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-indent_style: Block -// Function call style - -fn main() { - lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); - // #1501 - let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); - - // chain - let x = yooooooooooooo.fooooooooooooooo.baaaaaaaaaaaaar(hello, world); - - // #1380 - { - { - let creds = self.client - .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; - } - } - - // nesting macro and function call - try!(foo(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)); - try!(foo(try!(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx))); -} - -// #1521 -impl Foo { - fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { - unsafe { - Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw())) - } - } -} - -fn issue1420() { - given( - r#" - # Getting started - ... - "#, - ) - .running(waltz) -} - -// #1563 -fn query(conn: &Connection) -> Result<()> { - conn.query_row( - r#" - SELECT title, date - FROM posts, - WHERE DATE(date) = $1 - "#, - &[], - |row| { - Post { - title: row.get(0), - date: row.get(1), - } - }, - )?; - - Ok(()) -} - -// #1449 -fn future_rayon_wait_1_thread() { - // run with only 1 worker thread; this would deadlock if we couldn't make progress - let mut result = None; - ThreadPool::new(Configuration::new().num_threads(1)) - .unwrap() - .install( - || { - scope( - |s| { - use std::sync::mpsc::channel; - let (tx, rx) = channel(); - let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); - // ^^^^ FIXME: why is this needed? - let b = s.spawn_future(a.map(|v| v + 1)); - let c = s.spawn_future(b.map(|v| v + 1)); - s.spawn(move |_| tx.send(20).unwrap()); - result = Some(c.rayon_wait().unwrap()); - }, - ); - }, - ); - assert_eq!(result, Some(22)); -} - -// #1494 -impl Cursor { - fn foo() { - self.cur_type() - .num_template_args() - .or_else(|| { - let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; - - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - }) - .or_else(|| { - let canonical = self.canonical(); - if canonical != *self { - canonical.num_template_args() - } else { - None - } - }); - } -} - -fn issue1581() { - bootstrap.checks.register( - "PERSISTED_LOCATIONS", - move || if locations2.0.inner_mut.lock().poisoned { - Check::new( - State::Error, - "Persisted location storage is poisoned due to a write failure", - ) - } else { - Check::new(State::Healthy, "Persisted location storage is healthy") - }, - ); -} - -fn issue1651() { - { - let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); - } -} diff --git a/tests/source/configs/indent_style/block_chain.rs b/tests/source/configs/indent_style/block_chain.rs deleted file mode 100644 index 41d91469114..00000000000 --- a/tests/source/configs/indent_style/block_chain.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Chain indent - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); -} diff --git a/tests/source/configs/indent_style/block_generic.rs b/tests/source/configs/indent_style/block_generic.rs deleted file mode 100644 index 2cf17be56ef..00000000000 --- a/tests/source/configs/indent_style/block_generic.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Generics indent - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { - // body -} diff --git a/tests/source/configs/indent_style/block_struct_lit.rs b/tests/source/configs/indent_style/block_struct_lit.rs deleted file mode 100644 index 47a6994f40c..00000000000 --- a/tests/source/configs/indent_style/block_struct_lit.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs/indent_style/block_trailing_comma_call.rs b/tests/source/configs/indent_style/block_trailing_comma_call.rs deleted file mode 100644 index c907ec50d45..00000000000 --- a/tests/source/configs/indent_style/block_trailing_comma_call.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Block - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); -} diff --git a/tests/source/configs/indent_style/block_where_pred.rs b/tests/source/configs/indent_style/block_where_pred.rs deleted file mode 100644 index 450491f0270..00000000000 --- a/tests/source/configs/indent_style/block_where_pred.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Where predicate indent - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/tests/source/configs/indent_style/default.rs b/tests/source/configs/indent_style/default.rs deleted file mode 100644 index f08f5c64460..00000000000 --- a/tests/source/configs/indent_style/default.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Where style - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/tests/source/configs/indent_style/rfc_where.rs b/tests/source/configs/indent_style/rfc_where.rs deleted file mode 100644 index 012840be28d..00000000000 --- a/tests/source/configs/indent_style/rfc_where.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Where style - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/tests/source/configs/indent_style/visual_args.rs b/tests/source/configs/indent_style/visual_args.rs deleted file mode 100644 index 5aa28a62b9c..00000000000 --- a/tests/source/configs/indent_style/visual_args.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-indent_style: Visual -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { - // body -} - -// #1922 -extern "C" { - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - a: *const lapack_complex_float, - lda: lapack_int, ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int - )-> lapack_int; - - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - lda: lapack_int, ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int - ) -> lapack_int; -} diff --git a/tests/source/configs/indent_style/visual_array.rs b/tests/source/configs/indent_style/visual_array.rs deleted file mode 100644 index 05bbf00b1d2..00000000000 --- a/tests/source/configs/indent_style/visual_array.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Array layout - -fn main() { - let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; -} diff --git a/tests/source/configs/indent_style/visual_call.rs b/tests/source/configs/indent_style/visual_call.rs deleted file mode 100644 index 9a679d6bb4c..00000000000 --- a/tests/source/configs/indent_style/visual_call.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Function call style - -fn main() { - lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); -} diff --git a/tests/source/configs/indent_style/visual_chain.rs b/tests/source/configs/indent_style/visual_chain.rs deleted file mode 100644 index b7494875398..00000000000 --- a/tests/source/configs/indent_style/visual_chain.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Chain indent - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); -} diff --git a/tests/source/configs/indent_style/visual_generics.rs b/tests/source/configs/indent_style/visual_generics.rs deleted file mode 100644 index 1f910d32d87..00000000000 --- a/tests/source/configs/indent_style/visual_generics.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Generics indent - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { - // body -} diff --git a/tests/source/configs/indent_style/visual_struct_lit.rs b/tests/source/configs/indent_style/visual_struct_lit.rs deleted file mode 100644 index 45538e70482..00000000000 --- a/tests/source/configs/indent_style/visual_struct_lit.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs/indent_style/visual_trailing_comma.rs b/tests/source/configs/indent_style/visual_trailing_comma.rs deleted file mode 100644 index 9738d397dbf..00000000000 --- a/tests/source/configs/indent_style/visual_trailing_comma.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); -} diff --git a/tests/source/configs/indent_style/visual_where_pred.rs b/tests/source/configs/indent_style/visual_where_pred.rs deleted file mode 100644 index 055806b6862..00000000000 --- a/tests/source/configs/indent_style/visual_where_pred.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Where predicate indent - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/tests/source/configs/match_arm_blocks/false.rs b/tests/source/configs/match_arm_blocks/false.rs deleted file mode 100644 index 53e37e13c4f..00000000000 --- a/tests/source/configs/match_arm_blocks/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Wrap match-arms - -fn main() { - match lorem { - true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => { - println!("{}", sit) - } - } -} diff --git a/tests/source/configs/match_arm_blocks/true.rs b/tests/source/configs/match_arm_blocks/true.rs deleted file mode 100644 index a452b13cd27..00000000000 --- a/tests/source/configs/match_arm_blocks/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_arm_blocks: true -// Wrap match-arms - -fn main() { - match lorem { - true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => { - println!("{}", sit) - } - } -} diff --git a/tests/source/configs/match_block_trailing_comma/false.rs b/tests/source/configs/match_block_trailing_comma/false.rs deleted file mode 100644 index 70e02955fb0..00000000000 --- a/tests/source/configs/match_block_trailing_comma/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: false -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - } - Lorem::Dolor => println!("dolor"), - } -} diff --git a/tests/source/configs/match_block_trailing_comma/true.rs b/tests/source/configs/match_block_trailing_comma/true.rs deleted file mode 100644 index b9af3d47202..00000000000 --- a/tests/source/configs/match_block_trailing_comma/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - } - Lorem::Dolor => println!("dolor"), - } -} diff --git a/tests/source/configs/merge_derives/true.rs b/tests/source/configs/merge_derives/true.rs deleted file mode 100644 index 18b8443f0d7..00000000000 --- a/tests/source/configs/merge_derives/true.rs +++ /dev/null @@ -1,46 +0,0 @@ -// rustfmt-merge_derives: true -// Merge multiple derives to a single one. - -#[bar] -#[derive(Eq, PartialEq)] -#[foo] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Foo {} - -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Bar {} - -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[derive(Copy, Clone)] -pub enum FooBar {} - -mod foo { -#[bar] -#[derive(Eq, PartialEq)] -#[foo] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Foo {} -} - -mod bar { -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Bar {} -} - -mod foobar { -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[derive(Copy, Clone)] -pub enum FooBar {} -} diff --git a/tests/source/configs/normalize_comments/false.rs b/tests/source/configs/normalize_comments/false.rs deleted file mode 100644 index 488962ed936..00000000000 --- a/tests/source/configs/normalize_comments/false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: false -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -/* sit amet: */ -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/source/configs/normalize_comments/true.rs b/tests/source/configs/normalize_comments/true.rs deleted file mode 100644 index c74a9808e61..00000000000 --- a/tests/source/configs/normalize_comments/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: true -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -/* sit amet: */ -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/source/configs/reorder_extern_crates/false.rs b/tests/source/configs/reorder_extern_crates/false.rs deleted file mode 100644 index 6bef132e5c3..00000000000 --- a/tests/source/configs/reorder_extern_crates/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: false - -extern crate foo; -extern crate bar; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/tests/source/configs/reorder_extern_crates/true.rs b/tests/source/configs/reorder_extern_crates/true.rs deleted file mode 100644 index bdf00f57cda..00000000000 --- a/tests/source/configs/reorder_extern_crates/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: true - -extern crate foo; -extern crate bar; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/tests/source/configs/reorder_imported_names/false.rs b/tests/source/configs/reorder_imported_names/false.rs deleted file mode 100644 index 91db89ceeaa..00000000000 --- a/tests/source/configs/reorder_imported_names/false.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: false -// Reorder imported names - -use super::{lorem, ipsum, dolor, sit}; diff --git a/tests/source/configs/reorder_imported_names/true.rs b/tests/source/configs/reorder_imported_names/true.rs deleted file mode 100644 index 69da6186d5a..00000000000 --- a/tests/source/configs/reorder_imported_names/true.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: true -// Reorder imported names - -use super::{lorem, ipsum, dolor, sit}; diff --git a/tests/source/configs/reorder_imports/false.rs b/tests/source/configs/reorder_imports/false.rs deleted file mode 100644 index 4b85684dc01..00000000000 --- a/tests/source/configs/reorder_imports/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_imports: false -// Reorder imports - -use lorem; -use ipsum; -use dolor; -use sit; diff --git a/tests/source/configs/reorder_imports/true.rs b/tests/source/configs/reorder_imports/true.rs deleted file mode 100644 index 2a40f6d069f..00000000000 --- a/tests/source/configs/reorder_imports/true.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-reorder_imports: true -// Reorder imports - -use lorem; -use ipsum; -use dolor; -use sit; - -fn foo() { - use C; - use B; - use A; - - bar(); - - use F; - use E; - use D; -} diff --git a/tests/source/configs/reorder_imports_in_group/false.rs b/tests/source/configs/reorder_imports_in_group/false.rs deleted file mode 100644 index 87711bb142b..00000000000 --- a/tests/source/configs/reorder_imports_in_group/false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: false -// Reorder imports in group - -/// This comment should stay with `use std::mem;` -use std::mem; -use std::io; - -use lorem; -/// This comment should stay with `use ipsum;` -use ipsum; -use dolor; -use sit; diff --git a/tests/source/configs/reorder_imports_in_group/true.rs b/tests/source/configs/reorder_imports_in_group/true.rs deleted file mode 100644 index b5690b89cc0..00000000000 --- a/tests/source/configs/reorder_imports_in_group/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: true -// Reorder imports in group - -/// This comment should stay with `use std::mem;` -use std::mem; -use std::io; - -use lorem; -/// This comment should stay with `use ipsum;` -use ipsum; -use dolor; -use sit; diff --git a/tests/source/configs/reorder_modules/dolor/mod.rs b/tests/source/configs/reorder_modules/dolor/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/source/configs/reorder_modules/dolor/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/source/configs/reorder_modules/false.rs b/tests/source/configs/reorder_modules/false.rs deleted file mode 100644 index 56b1aa03ed7..00000000000 --- a/tests/source/configs/reorder_modules/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: false -// Reorder modules - -mod lorem; -mod ipsum; -mod dolor; -mod sit; diff --git a/tests/source/configs/reorder_modules/ipsum/mod.rs b/tests/source/configs/reorder_modules/ipsum/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/source/configs/reorder_modules/ipsum/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/source/configs/reorder_modules/lorem/mod.rs b/tests/source/configs/reorder_modules/lorem/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/source/configs/reorder_modules/lorem/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/source/configs/reorder_modules/sit/mod.rs b/tests/source/configs/reorder_modules/sit/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/source/configs/reorder_modules/sit/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/source/configs/reorder_modules/true.rs b/tests/source/configs/reorder_modules/true.rs deleted file mode 100644 index 79b0ab1e355..00000000000 --- a/tests/source/configs/reorder_modules/true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: true -// Reorder modules - -mod lorem; -mod ipsum; -mod dolor; -mod sit; diff --git a/tests/source/configs/space_before_colon/true.rs b/tests/source/configs/space_before_colon/true.rs deleted file mode 100644 index 0a597602528..00000000000 --- a/tests/source/configs/space_before_colon/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-space_before_colon: true -// Space before colon - -fn lorem(t : T) { - let ipsum: Dolor = sit; -} - -const LOREM : Lorem = Lorem { - ipsum : dolor, - sit : amet, -}; diff --git a/tests/source/configs/spaces_around_ranges/false.rs b/tests/source/configs/spaces_around_ranges/false.rs deleted file mode 100644 index 11ca76b1345..00000000000 --- a/tests/source/configs/spaces_around_ranges/false.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: false -// Spaces around ranges - -fn main() { - let lorem = 0 .. 10; - let ipsum = 0 ..= 10; - - match lorem { - 1 .. 5 => foo(), - _ => bar, - } - - match lorem { - 1 ..= 5 => foo(), - _ => bar, - } - - match lorem { - 1 ... 5 => foo(), - _ => bar, - } -} diff --git a/tests/source/configs/spaces_around_ranges/true.rs b/tests/source/configs/spaces_around_ranges/true.rs deleted file mode 100644 index 50170892130..00000000000 --- a/tests/source/configs/spaces_around_ranges/true.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: true -// Spaces around ranges - -fn main() { - let lorem = 0..10; - let ipsum = 0..=10; - - match lorem { - 1..5 => foo(), - _ => bar, - } - - match lorem { - 1..=5 => foo(), - _ => bar, - } - - match lorem { - 1...5 => foo(), - _ => bar, - } -} diff --git a/tests/source/configs/spaces_within_parens_and_brackets/false.rs b/tests/source/configs/spaces_within_parens_and_brackets/false.rs deleted file mode 100644 index 908373ca9b0..00000000000 --- a/tests/source/configs/spaces_within_parens_and_brackets/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: false -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} diff --git a/tests/source/configs/spaces_within_parens_and_brackets/true.rs b/tests/source/configs/spaces_within_parens_and_brackets/true.rs deleted file mode 100644 index 2e3c92da2fc..00000000000 --- a/tests/source/configs/spaces_within_parens_and_brackets/true.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: true -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} - -enum E { - A(u32), - B(u32, u32), - C(u32, u32, u32), - D(), -} - -struct TupleStruct0(); -struct TupleStruct1(u32); -struct TupleStruct2(u32, u32); - -fn fooEmpty() {} - -fn foo(e: E, _: u32) -> (u32, u32) { - // Tuples - let t1 = (); - let t2 = (1,); - let t3 = (1, 2); - - let ts0 = TupleStruct0(); - let ts1 = TupleStruct1(1); - let ts2 = TupleStruct2(1, 2); - - // Tuple pattern - let (a,b,c) = (1,2,3); - - // Expressions - let x = (1 + 2) * (3); - - // Function call - fooEmpty(); - foo(1, 2); - - // Pattern matching - match e { - A(_) => (), - B(_, _) => (), - C(..) => (), - D => (), - } - - (1,2) -} - -struct Foo { - i: T, -} - -struct Bar { - i: T, - e: E, -} - -struct Foo<'a> { - i: &'a str, -} - -enum E { - T(T), -} - -enum E { - T(T), - S(S), -} - -fn foo(a: T) { - foo::(10); -} - -fn foo(a: T, b: E) { - foo::(10, "bar"); -} - -fn foo(a: T, b: E) { - foo::(10, "bar"); - - let opt: Option; - let res: Result; -} - -fn foo<'a>(a: &'a str) { - foo("foo"); -} - -fn foo<'a, 'b>(a: &'a str, b: &'b str) { - foo("foo", "bar"); -} - -impl Foo { - fn bar() { - ::bar(); - } -} - -trait MyTrait {} -impl MyTrait for Foo {} - -fn foo() where for<'a> u32: 'a {} - -fn main() { - let arr: [i32; 5] = [1, 2, 3, 4, 5]; - let arr: [i32; 500] = [0; 500]; - - let v = vec![1, 2, 3]; - assert_eq!(arr, [1, 2, 3]); - - let i = arr[0]; - - let slice = &arr[1..2]; - - let line100_________________________________________________________________________ = [1, 2]; - let line101__________________________________________________________________________ = [1, 2]; - let line102___________________________________________________________________________ = [1, 2]; - let line103____________________________________________________________________________ = [1, 2]; - let line104_____________________________________________________________________________ = [1, 2]; - - let line100_____________________________________________________________________ = vec![1, 2]; - let line101______________________________________________________________________ = vec![1, 2]; - let line102_______________________________________________________________________ = vec![1, 2]; - let line103________________________________________________________________________ = vec![1, 2]; - let line104_________________________________________________________________________ = vec![1, 2]; -} - -fn f(slice: &[i32]) {} diff --git a/tests/source/configs/struct_field_align_threshold/20.rs b/tests/source/configs/struct_field_align_threshold/20.rs deleted file mode 100644 index e68340b027d..00000000000 --- a/tests/source/configs/struct_field_align_threshold/20.rs +++ /dev/null @@ -1,383 +0,0 @@ -// rustfmt-struct_field_align_threshold: 20 -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false - -struct Foo { - x: u32, - yy: u32, // comment - zzz: u32, -} - -pub struct Bar { - x: u32, - yy: u32, - zzz: u32, - - xxxxxxx: u32, -} - -fn main() { - let foo = Foo { - x: 0, - yy: 1, - zzz: 2, - }; - - let bar = Bar { - x: 0, - yy: 1, - zzz: 2, - - xxxxxxx: 3, - }; -} - - /// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] //only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct -NewInt (pub i32, SomeType /* inline comment */, T /* sup */ - - - ); - -struct Qux<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy> -( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C - -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - - - - c: C, // Comment C -} - -struct Baz { - - a: A, - - b: B, - c: C, - - - - - d: D - -} - -struct Baz -{ - // Comment A - a: A, - - // Comment B -b: B, - // Comment C - c: C,} - -// Will this be a one-liner? -struct Tuple( - A, //Comment - B -); - -pub struct State time::Timespec> { now: F } - -pub struct State ()> { now: F } - -pub struct State { now: F } - -struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color - foo: i32} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB - //Another pre comment - #[attr1] - #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(T); -struct Foo(T) where T: Copy, T: Eq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU); - -mod m { - struct X where T: Sized { - a: T, - } -} - -struct Foo(TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn( obj: - *const libc::c_void, tracer : *mut JSTracer ), -} - -struct Foo {} -struct Foo { - } -struct Foo { - // comment - } -struct Foo { - // trailing space -> - - - } -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:f() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { memb: T } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S{a:0, .. b}; -} - -fn issue201_2() { - let s = S{a: S2{ .. c}, .. b}; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo - { a : 1, b:f( 2)}; - Foo{a:1,b:f(2),..g(3)}; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; - IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { a: bb, c: dd, e: ff }; - - Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ - e: eeeeeeeee }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, .. base }; - Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ - eeeeeeeee }; - Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; -} diff --git a/tests/source/configs/struct_lit_single_line/false.rs b/tests/source/configs/struct_lit_single_line/false.rs deleted file mode 100644 index 17cad8dde29..00000000000 --- a/tests/source/configs/struct_lit_single_line/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-struct_lit_single_line: false -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/tests/source/configs/tab_spaces/2.rs b/tests/source/configs/tab_spaces/2.rs deleted file mode 100644 index 5c2667bc2c7..00000000000 --- a/tests/source/configs/tab_spaces/2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-tab_spaces: 2 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { -let ipsum = dolor(); -let sit = vec![ -"amet", "consectetur", "adipiscing", "elit." -]; -} diff --git a/tests/source/configs/tab_spaces/4.rs b/tests/source/configs/tab_spaces/4.rs deleted file mode 100644 index da61bbd42a7..00000000000 --- a/tests/source/configs/tab_spaces/4.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-tab_spaces: 4 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { -let ipsum = dolor(); -let sit = vec![ -"amet", "consectetur", "adipiscing", "elit." -]; -} diff --git a/tests/source/configs/trailing_comma/always.rs b/tests/source/configs/trailing_comma/always.rs deleted file mode 100644 index 57e874cd822..00000000000 --- a/tests/source/configs/trailing_comma/always.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-trailing_comma: Always -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; -} diff --git a/tests/source/configs/trailing_comma/never.rs b/tests/source/configs/trailing_comma/never.rs deleted file mode 100644 index 4da3b996f29..00000000000 --- a/tests/source/configs/trailing_comma/never.rs +++ /dev/null @@ -1,23 +0,0 @@ -// rustfmt-trailing_comma: Never -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; - - // #1544 - if let VrMsg::ClientReply {request_num: reply_req_num, value, ..} = msg { - let _ = safe_assert_eq!(reply_req_num, request_num, op); - return Ok((request_num, op, value)); - } - - // #1710 - pub struct FileInput { - input: StringInput, - file_name: OsString, - } - match len { - Some(len) => Ok(new(self.input, self.pos + len)), - None => Err(self), - } -} diff --git a/tests/source/configs/trailing_comma/vertical.rs b/tests/source/configs/trailing_comma/vertical.rs deleted file mode 100644 index c903e822158..00000000000 --- a/tests/source/configs/trailing_comma/vertical.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-trailing_comma: Vertical -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; -} diff --git a/tests/source/configs/type_punctuation_density/compressed.rs b/tests/source/configs/type_punctuation_density/compressed.rs deleted file mode 100644 index 6e16e610566..00000000000 --- a/tests/source/configs/type_punctuation_density/compressed.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed -// Type punctuation density - -fn lorem() { - // body -} diff --git a/tests/source/configs/type_punctuation_density/wide.rs b/tests/source/configs/type_punctuation_density/wide.rs deleted file mode 100644 index 1fcdddf0f9a..00000000000 --- a/tests/source/configs/type_punctuation_density/wide.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-type_punctuation_density: Wide -// Type punctuation density - -fn lorem() { - // body -} diff --git a/tests/source/configs/use_field_init_shorthand/false.rs b/tests/source/configs/use_field_init_shorthand/false.rs deleted file mode 100644 index 16ce740f1b9..00000000000 --- a/tests/source/configs/use_field_init_shorthand/false.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-use_field_init_shorthand: false -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { - x: x, - y: y, - z: z, - }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/tests/source/configs/use_field_init_shorthand/true.rs b/tests/source/configs/use_field_init_shorthand/true.rs deleted file mode 100644 index 1e36c6cff35..00000000000 --- a/tests/source/configs/use_field_init_shorthand/true.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-use_field_init_shorthand: true -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { - x: x, - y: y, - z: z, - }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/tests/source/configs/use_try_shorthand/false.rs b/tests/source/configs/use_try_shorthand/false.rs deleted file mode 100644 index de7f8b4a5e2..00000000000 --- a/tests/source/configs/use_try_shorthand/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: false -// Use try! shorthand - -fn main() { - let lorem = try!(ipsum.map(|dolor| dolor.sit())); -} diff --git a/tests/source/configs/use_try_shorthand/true.rs b/tests/source/configs/use_try_shorthand/true.rs deleted file mode 100644 index 9015ec41e5e..00000000000 --- a/tests/source/configs/use_try_shorthand/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: true -// Use try! shorthand - -fn main() { - let lorem = try!(ipsum.map(|dolor| dolor.sit())); -} diff --git a/tests/source/configs/where_single_line/true.rs b/tests/source/configs/where_single_line/true.rs deleted file mode 100644 index daaab865af2..00000000000 --- a/tests/source/configs/where_single_line/true.rs +++ /dev/null @@ -1,24 +0,0 @@ -// rustfmt-where_single_line: true -// Where style - - -fn lorem_two_items() -> T where Ipsum: Eq, Lorem: Eq { - // body -} - -fn lorem_multi_line( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) -> T -where - Ipsum: Eq, -{ - // body -} - -fn lorem() -> T where Ipsum: Eq { - // body -} diff --git a/tests/source/configs/wrap_comments/false.rs b/tests/source/configs/wrap_comments/false.rs deleted file mode 100644 index 48ecd88accb..00000000000 --- a/tests/source/configs/wrap_comments/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-wrap_comments: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -} diff --git a/tests/source/configs/wrap_comments/true.rs b/tests/source/configs/wrap_comments/true.rs deleted file mode 100644 index 39a79a4cacc..00000000000 --- a/tests/source/configs/wrap_comments/true.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 50 -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -} - -fn code_block() { - // ```rust - // let x = 3; - // - // println!("x = {}", x); - // ``` -} diff --git a/tests/source/control-brace-style-always-next-line.rs b/tests/source/control-brace-style-always-next-line.rs deleted file mode 100644 index 9079fb46c0c..00000000000 --- a/tests/source/control-brace-style-always-next-line.rs +++ /dev/null @@ -1,44 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - loop { - (); - (); - } - - - 'label: loop // loop comment - { - (); - } - - - cond = true; - while cond { - (); - } - - - 'while_label: while cond { // while comment - (); - } - - - for obj in iter { - for sub_obj in obj - { - 'nested_while_label: while cond { - (); - } - } - } - - match some_var { // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => { - do_stuff(); - val2 - }, - }; -} diff --git a/tests/source/control-brace-style-always-same-line.rs b/tests/source/control-brace-style-always-same-line.rs deleted file mode 100644 index 1c8f487e7cd..00000000000 --- a/tests/source/control-brace-style-always-same-line.rs +++ /dev/null @@ -1,44 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - loop { - (); - (); - } - - - 'label: loop // loop comment - { - (); - } - - - cond = true; - while cond { - (); - } - - - 'while_label: while cond { // while comment - (); - } - - - for obj in iter { - for sub_obj in obj - { - 'nested_while_label: while cond { - (); - } - } - } - - match some_var { // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => { - do_stuff(); - val2 - }, - }; -} diff --git a/tests/source/doc.rs b/tests/source/doc.rs deleted file mode 100644 index e03933e4516..00000000000 --- a/tests/source/doc.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true - -// sadfsdfa -//sdffsdfasdf diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/tests/source/else-if-brace-style-always-next-line.rs deleted file mode 100644 index 7b4870fc65a..00000000000 --- a/tests/source/else-if-brace-style-always-next-line.rs +++ /dev/null @@ -1,54 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - if false - { - (); - (); - } - - if false // lone if comment - { - (); - (); - } - - - let a = - if 0 > 1 { - unreachable!() - } - else - { - 0x0 - }; - - - if true - { - (); - } else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true // else-if-chain if comment - { - (); - } - else if false // else-if-chain else-if comment - { - (); - (); - } else // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/tests/source/else-if-brace-style-always-same-line.rs deleted file mode 100644 index 41f5305bf8c..00000000000 --- a/tests/source/else-if-brace-style-always-same-line.rs +++ /dev/null @@ -1,54 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - if false - { - (); - (); - } - - if false // lone if comment - { - (); - (); - } - - - let a = - if 0 > 1 { - unreachable!() - } - else - { - 0x0 - }; - - - if true - { - (); - } else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true // else-if-chain if comment - { - (); - } - else if false // else-if-chain else-if comment - { - (); - (); - } else // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/tests/source/else-if-brace-style-closing-next-line.rs deleted file mode 100644 index 3b885b3faaa..00000000000 --- a/tests/source/else-if-brace-style-closing-next-line.rs +++ /dev/null @@ -1,54 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine - -fn main() { - if false - { - (); - (); - } - - if false // lone if comment - { - (); - (); - } - - - let a = - if 0 > 1 { - unreachable!() - } - else - { - 0x0 - }; - - - if true - { - (); - } else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true // else-if-chain if comment - { - (); - } - else if false // else-if-chain else-if comment - { - (); - (); - } else // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/tests/source/empty_file.rs b/tests/source/empty_file.rs deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/source/enum.rs b/tests/source/enum.rs deleted file mode 100644 index f3dbae4b84d..00000000000 --- a/tests/source/enum.rs +++ /dev/null @@ -1,194 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Enums test - -#[atrr] -pub enum Test { - A, B(u32, - A /* comment */, - SomeType), - /// Doc comment - C, -} - -pub enum Foo<'a, Y: Baz> where X: Whatever -{ A, } - -enum EmtpyWithComment { - // Some comment -} - -// C-style enum -enum Bar { - A = 1, - #[someAttr(test)] - B = 2, // comment - C, -} - -enum LongVariants { -First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment -VARIANT), - // This is the second variant - Second -} - -enum StructLikeVariants { - Normal(u32, String, ), - StructLike { x: i32, // Test comment - // Pre-comment - #[Attr50] y: SomeType, // Aanother Comment - }, SL { a: A } -} - -enum X { - CreateWebGLPaintTask(Size2D, GLContextAttributes, IpcSender, usize), String>>), // This is a post comment -} - -pub enum EnumWithAttributes { - //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - // Pre Comment - #[rustfmt_skip] - SkippedItem(String,String,), // Post-comment - #[another_attr] - #[attr2] - ItemStruct {x: usize, y: usize}, // Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - // And another - ForcedPreflight // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -} - -pub enum SingleTuple { - // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - Match(usize, usize, String) // Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -} - -pub enum SingleStruct { - Match {name: String, loc: usize} // Post-comment -} - -pub enum GenericEnum -where I: Iterator { - // Pre Comment - Left {list: I, root: T}, // Post-comment - Right {list: I, root: T} // Post Comment -} - - -enum EmtpyWithComment { - // Some comment -} - -enum TestFormatFails { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -} - -fn nested_enum_test() { - if true { - enum TestEnum { - One(usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize,), // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA - Two // AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA - } - enum TestNestedFormatFail { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - } - } -} - - pub struct EmtpyWithComment { - // FIXME: Implement this struct -} - -// #1115 -pub enum Bencoding<'i> { - Str(&'i [u8]), - Int(i64), - List(Vec>), - /// A bencoded dict value. The first element the slice of bytes in the source that the dict is - /// composed of. The second is the dict, decoded into an ordered map. - // TODO make Dict "structlike" AKA name the two values. - Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), -} - -// #1261 -pub enum CoreResourceMsg { - SetCookieForUrl( - ServoUrl, - #[serde(deserialize_with = "::hyper_serde::deserialize", - serialize_with = "::hyper_serde::serialize")] - Cookie, - CookieSource - ), -} - -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { Foo } - -// #1046 -pub enum Entry<'a, K: 'a, V: 'a> { - Vacant( - #[ stable( feature = "rust1", since = "1.0.0" ) ] VacantEntry<'a, K, V>, - ), - Occupied( - #[ stable( feature = "rust1", since = "1.0.0" ) ] - OccupiedEntry<'a, K, V>, - ), -} - -// #2081 -pub enum ForegroundColor { - CYAN = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, -} - -// #2098 -pub enum E<'a> { - V ( < std::slice::Iter<'a, Xxxxxxxxxxxxxx> as Iterator> :: Item ) , -} - -// #1809 -enum State { - TryRecv { - pos: usize, - lap: u8, - closed_count: usize, - }, - Subscribe { pos: usize }, - IsReady { pos: usize, ready: bool }, - Unsubscribe { - pos: usize, - lap: u8, - id_woken: usize, - }, - FinalTryRecv { pos: usize, id_woken: usize }, - TimedOut, - Disconnected, -} - -// #2190 -#[derive(Debug, Fail)] -enum AnError { - #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - UnexpectedSingleToken { token: syn::Token }, -} - -// #2193 -enum WidthOf101 { - #[fail(display = ".....................................................")] Io(::std::io::Error), - #[fail(display = ".....................................................")] Ioo(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), -} - -// #2389 -pub enum QlError { - #[fail(display = "Parsing error: {}", 0)] LexError(parser::lexer::LexError), - #[fail(display = "Parsing error: {:?}", 0)] ParseError(parser::ParseError), - #[fail(display = "Validation error: {:?}", 0)] ValidationError(Vec), - #[fail(display = "Execution error: {}", 0)] ExecutionError(String), - // (from, to) - #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), - // (kind, input, expected) - #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), -} diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs deleted file mode 100644 index a2e7ac8fc44..00000000000 --- a/tests/source/expr-block.rs +++ /dev/null @@ -1,286 +0,0 @@ -// rustfmt-indent_style: Block -// Test expressions with block formatting. - -fn arrays() { - [ ]; - let empty = []; - - let foo = [a_long_name, a_very_lng_name, a_long_name]; - - let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name]; - - vec![a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name]; - - [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name] -} - -fn arrays() { - let x = [0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; - - let a =WeightedChoice::new(&mut [Weighted { - weight: x, - item: 0, - }, - Weighted { - weight: 1, - item: 1, - }, - Weighted { - weight: x, - item: 2, - }, - Weighted { - weight: 1, - item: 3, - }]); - - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; - - [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] -} - -fn function_calls() { - let items = itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite(context, - Shape { - width: remaining_width, - ..nested_shape - }) - }, - span.lo(), - span.hi()); - - itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite(context, - Shape { - width: remaining_width, - ..nested_shape - }) - }, - span.lo(), - span.hi()) -} - -fn macros() { - baz!(do_not, add, trailing, commas, inside, of, function, like, macros, even, if_they, are, long); - - baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); - - let _ = match option { - None => baz!(function, like, macro_as, expression, which, is, loooooooooooooooong), - Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), - }; -} - -fn issue_1450() { - if selfstate - .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( - STATE_PARKED, - STATE_UNPARKED, - Release, - Relaxed, - Release, - Relaxed, - ) - .is_ok() { - return; - } -} - -fn foo() { - if real_total <= limit && !pre_line_comments && - !items.into_iter().any(|item| item.as_ref().is_multiline()) { - DefinitiveListTactic::Horizontal - } -} - -fn combine_block() { - foo( - Bar { - x: value, - y: value2, - }, - ); - - foo((Bar { - x: value, - y: value2, - },)); - - foo((1, 2, 3, Bar { - x: value, - y: value2, - })); - - foo((1, 2, 3, |x| { - let y = x + 1; - let z = y + 1; - z - })); - - let opt = Some( - Struct( - long_argument_one, - long_argument_two, - long_argggggggg, - ), - ); - - do_thing( - |param| { - action(); - foo(param) - }, - ); - - do_thing( - x, - |param| { - action(); - foo(param) - }, - ); - - do_thing( - x, - ( - 1, - 2, - 3, - |param| { - action(); - foo(param) - }, - ), - ); - - Ok( - some_function( - lllllllllong_argument_one, - lllllllllong_argument_two, - lllllllllllllllllllllllllllllong_argument_three, - ), - ); - - foo( - thing, - bar( - param2, - pparam1param1param1param1param1param1param1param1param1param1aram1, - param3, - ), - ); - - foo.map_or( - || { - Ok( - SomeStruct { - f1: 0, - f2: 0, - f3: 0, - }, - ) - }, - ); - - match opt { - Some(x) => somefunc(anotherfunc( - long_argument_one, - long_argument_two, - long_argument_three, - )), - Some(x) => |x| { - let y = x + 1; - let z = y + 1; - z - }, - Some(x) => (1, 2, |x| { - let y = x + 1; - let z = y + 1; - z - }), - Some(x) => SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }, - None => Ok(SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }), - }; - - match x { - y => func( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - ), - _ => func( - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzz, - ), - } -} - -fn issue_1862() { - foo( - /* bar = */ None , - something_something, - /* baz = */ None , - /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ None , - /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , - ) -} - -fn issue_1878() { - let channel: &str = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; -} diff --git a/tests/source/expr.rs b/tests/source/expr.rs deleted file mode 100644 index f87c950735f..00000000000 --- a/tests/source/expr.rs +++ /dev/null @@ -1,372 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// Test expressions - -fn foo() -> bool { - let boxed: Box = box 5; - let referenced = &5 ; - - let very_long_variable_name = ( a + first + simple + test ); - let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - - let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); - - let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - - function_call(x, *very_long_pointer, y)) - + 1000 ; - -some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 - - 50000 * sqrt(-1), - trivial_value); - (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; - - { for _ in 0..10 {} } - - {{{{}}}} - - if 1 + 2 > 0 { let result = 5; result } else { 4}; - - if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { - // Nothing - } - - if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} - - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 - + 2 + 3 { - } - - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} - - if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 - + 2 + 3 { - } - - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = item.node - { - // nothing - } - - let test = if true { 5 } else { 3 }; - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - // Check subformatting - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } -} - -fn bar() { - let range = ( 111111111 + 333333333333333333 + 1111 + 400000000000000000) .. (2222 + 2333333333333333); - - let another_range = 5..some_func( a , b /* comment */); - - for _ in 1 ..{ call_forever(); } - - syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 }); - - let third = ..10; - let infi_range = .. ; - let foo = 1..; - let bar = 5 ; - let nonsense = (10 .. 0)..(0..10); - - loop{if true {break}} - - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - a); -} - -fn baz() { - unsafe /* {}{}{}{{{{}} */ { - let foo = 1u32; - } - - unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} - - unsafe // So this is a very long comment. - // Multi-line, too. - // Will it still format correctly? - { - } - - unsafe { - // Regular unsafe block - } - - unsafe { - foo() - } - - unsafe { - foo(); - } - - // #2289 - let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; - let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; - let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; - let identifier_3 = unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; -} - -// Test some empty blocks. -fn qux() { - {} - // FIXME this one could be done better. - { /* a block with a comment */ } - { - - } - { - // A block with a comment. - } -} - -fn issue227() { - { - let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - -fn issue184(source: &str) { - for c in source.chars() { - if index < 'a' { - continue; - } - } -} - -fn arrays() { - let x = [0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; - - let a =WeightedChoice::new(&mut [Weighted { - weightweight: x, - item: 0, - }, - Weighted { - weightweight: 1, - item: 1, - }, - Weighted { - weightweight: x, - item: 2, - }, - Weighted { - weightweight: 1, - item: 3, - }]); - - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; - - [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] -} - -fn returns() { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && return; - - return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -} - -fn addrof() { - & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); - & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); -} - -fn casts() { - fn unpack(packed: u32) -> [u16; 2] { - [ - (packed >> 16) as u16, - (packed >> 0) as u16, - ] - } - - let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx - as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; -} - -fn indices() { - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; - let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; - let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; - let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; -} - -fn repeats() { - let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc; x + y + z ]; - let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz ]; -} - -fn blocks() { - if 1 + 1 == 2 { - println!("yay arithmetix!"); - }; -} - -fn issue767() { - if false { - if false { - } else { - // A let binding here seems necessary to trigger it. - let _ = (); - } - } else if let false = false { - } -} - -fn ranges() { - let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ..= bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let z = ..= x ; - - // #1766 - let x = [0. ..10.0]; - let x = [0. ..=10.0]; - - a ..= b - - // the expr below won't compile because inclusive ranges need a defined end - // let a = 0 ..= ; -} - -fn if_else() { - let exact = diff / - (if size == 0 { - 1 -} else { - size -}); - - let cx = tp1.x + - any * radius * - if anticlockwise { - 1.0 - } else { - -1.0 - }; -} - -fn complex_if_else() { - if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { - yo(); - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { - yo(); - } -} - -fn issue1106() { - { - if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map.expect_item(enum_node_id).node { - } - } - - for entry in - WalkDir::new(path) - .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) { - } -} - -fn issue1570() { - a_very_long_function_name({some_func(1, {1})}) -} - -fn issue1714() { - v = &mut {v}[mid..]; - let (left, right) = {v}.split_at_mut(mid); -} - -// Multi-lined index should be put on the next line if it fits in one line. -fn issue1749() { - { - { - { - if self.shape[(r as f32 + self.x_offset) as usize][(c as f32 + self.y_offset) as usize] != 0 { - // hello - } - } - } - } -} - -// #1172 -fn newlines_between_list_like_expr() { - foo( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ); - - vec![ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ]; - - match x { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | - - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy | - - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), - _ => bar(), - }; -} - -fn issue2178() { - Ok(result.iter().map(|item| ls_util::rls_to_location(item)).collect()) -} diff --git a/tests/source/extern.rs b/tests/source/extern.rs deleted file mode 100644 index 187e698607a..00000000000 --- a/tests/source/extern.rs +++ /dev/null @@ -1,60 +0,0 @@ -// rustfmt-normalize_comments: true - - extern crate foo ; - extern crate foo as bar ; - -extern crate futures; -extern crate dotenv; -extern crate chrono; - -extern crate foo; -extern crate bar; - -// #2315 -extern crate proc_macro2; -extern crate proc_macro; - - extern "C" { - fn c_func(x: *mut *mut libc::c_void); - - fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); - - #[test123] - fn foo() -> uint64_t; - -pub fn bar() ; - } - -extern { - fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, devNr: c_uint, wildcard: c_char) -> TDMR_ERROR; - - fn quux() -> (); // Post comment - - pub type - Foo; - - type Bar; -} - -extern "Rust" { static ext: u32; - // Some comment. - pub static mut var : SomeType ; } - -extern "C" { - fn syscall(number: libc::c_long /* comment 1 */, /* comm 2 */ ... /* sup? */) -> libc::c_long; - - fn foo (x: *const c_char , ... ) -> -libc::c_long; - } - - extern { - pub fn freopen(filename: *const c_char, mode: *const c_char - , mode2: *const c_char - , mode3: *const c_char, - file: *mut FILE) - -> *mut FILE; - } - -extern { - -} diff --git a/tests/source/extern_not_explicit.rs b/tests/source/extern_not_explicit.rs deleted file mode 100644 index 9d6c4c2a1cd..00000000000 --- a/tests/source/extern_not_explicit.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-force_explicit_abi: false - - extern "C" { - fn some_fn() -> (); - } - - extern "C" fn sup() { - - } - -type funky_func = extern "C" fn (unsafe extern "rust-call" fn(*const JSJitInfo, *mut JSContext, - HandleObject, *mut libc::c_void, u32, - *mut JSVal) - -> u8); diff --git a/tests/source/file-lines-1.rs b/tests/source/file-lines-1.rs deleted file mode 100644 index 0164e30a854..00000000000 --- a/tests/source/file-lines-1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/source/file-lines-2.rs b/tests/source/file-lines-2.rs deleted file mode 100644 index 6f44ec6e69d..00000000000 --- a/tests/source/file-lines-2.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/source/file-lines-3.rs b/tests/source/file-lines-3.rs deleted file mode 100644 index c4f3e21b1ae..00000000000 --- a/tests/source/file-lines-3.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] -// rustfmt-error_on_line_overflow: false - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/source/file-lines-4.rs b/tests/source/file-lines-4.rs deleted file mode 100644 index 83928bf6fec..00000000000 --- a/tests/source/file-lines-4.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-file_lines: [] -// (Test that nothing is formatted if an empty array is specified.) - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - // aaaaaaaaaaaaa - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/source/file-lines-5.rs b/tests/source/file-lines-5.rs deleted file mode 100644 index 8ec2c67bc44..00000000000 --- a/tests/source/file-lines-5.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] - -struct A { -t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - fn baz() { - let j = 15; - } -} diff --git a/tests/source/file-lines-6.rs b/tests/source/file-lines-6.rs deleted file mode 100644 index 2eacc8a0e75..00000000000 --- a/tests/source/file-lines-6.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] - -struct A { - t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - - fn baz() { -/// - let j = 15; - } -} diff --git a/tests/source/file-lines-item.rs b/tests/source/file-lines-item.rs deleted file mode 100644 index 0ed4b93df5f..00000000000 --- a/tests/source/file-lines-item.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] -// rustfmt-reorder_imports: true - -use foo::{c, b, a}; -use bar; - -fn foo() { - bar ( ) ; -} - -impl Drop for Context { - fn drop(&mut self) { - } -} - -impl Bar for Baz { - fn foo() { - bar( - baz, // Who knows? - ) - } -} diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs deleted file mode 100644 index 72d841544a8..00000000000 --- a/tests/source/fn-custom-2.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); -} - -fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); -} - -fn baz() where X: TTTTTTTT { - baz(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); - } - - fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); - } - - fn baz() where X: TTTTTTTT { - baz(); - } -} - -struct Foo { - foo: Foo, -} diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs deleted file mode 100644 index 9934fb61efd..00000000000 --- a/tests/source/fn-custom-3.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); -} - -fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); - } - - fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); - } -} - -struct Foo { - foo: Foo, -} diff --git a/tests/source/fn-custom-4.rs b/tests/source/fn-custom-4.rs deleted file mode 100644 index 01c00aecb86..00000000000 --- a/tests/source/fn-custom-4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -fn qux(a: Aaaaaaaaaaaaaaaaa) where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs deleted file mode 100644 index 8e8bb6c274e..00000000000 --- a/tests/source/fn-custom-6.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs deleted file mode 100644 index f7670e07fc8..00000000000 --- a/tests/source/fn-custom-7.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block -// rustfmt-fn_args_density: Vertical -// rustfmt-brace_style: AlwaysNextLine - -// Case with only one variable. -fn foo(a: u8) -> u8 { - bar() -} - -// Case with 2 variables and some pre-comments. -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -// Case with 2 variables and some post-comments. -fn foo(/* Comment 1 */ a: u8, /* Comment 2 */ b: u8) -> u8 { - bar() -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs deleted file mode 100644 index d3deb20a51c..00000000000 --- a/tests/source/fn-custom-8.rs +++ /dev/null @@ -1,49 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { - bar(); -} - -trait Test { - fn foo( - a: u8) { - - } - - fn bar(a: u8) - -> String { - - } - - fn bar(a: u8) -> String where Foo: foooo, Bar: barrr {} -} diff --git a/tests/source/fn-custom.rs b/tests/source/fn-custom.rs deleted file mode 100644 index b8d734bfbaf..00000000000 --- a/tests/source/fn-custom.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Test some of the ways function signatures can be customised. - -// Test compressed layout of args. -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); -} - -impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); - } -} diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs deleted file mode 100644 index f1ce503ab0a..00000000000 --- a/tests/source/fn-simple.rs +++ /dev/null @@ -1,66 +0,0 @@ -// rustfmt-normalize_comments: true - -fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ - ,response: NoWay /* hose */) { -fn op(x: Typ, key : &[u8], upd : Box) -> (memcache::Status, Result>)>) -> MapResult {} - - "cool"} - - -fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* triple, even */*/*/, -// Does this work? -y: World -) { - simple(/* does this preserve comments now? */ 42, NoWay) -} - -fn generic(arg: T) -> &SomeType - where T: Fn(// First arg - A, - // Second argument - B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { - arg(a, b, c, d, e) -} - -fn foo() -> ! {} - -pub fn http_fetch_async(listener:Box< AsyncCORSResponseListener+Send >, script_chan: Box) { -} - -fn some_func>(val:T){} - -fn zzzzzzzzzzzzzzzzzzzz - (selff: Type, mut handle: node::Handle>, Type, NodeType>) - -> SearchStack<'a, K, V, Type, NodeType>{ -} - -unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, - is_lenient: bool, - call: unsafe extern fn(*const JSJitInfo, *mut JSContext, - HandleObject, *mut libc::c_void, u32, - *mut JSVal) - -> u8) { - let f: fn ( _ , _ ) -> _ = panic!() ; -} - -pub fn start_export_thread(database: &Database, crypto_scheme: &C, block_size: usize, source_path: &Path) -> BonzoResult> {} - -pub fn waltz(cwd: &Path) -> CliAssert { - { - { - formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig); - } - } -} - -// #2003 -mod foo { - fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() { - foo(); - } -} - -// #2082 -pub(crate) fn init() {} - -crate fn init() {} diff --git a/tests/source/fn-single-line.rs b/tests/source/fn-single-line.rs deleted file mode 100644 index 6d7f764d280..00000000000 --- a/tests/source/fn-single-line.rs +++ /dev/null @@ -1,79 +0,0 @@ -// rustfmt-fn_single_line: true -// Test single-line functions. - -fn foo_expr() { - 1 -} - -fn foo_stmt() { - foo(); -} - -fn foo_decl_local() { - let z = 5; - } - -fn foo_decl_item(x: &mut i32) { - x = 3; -} - - fn empty() { - -} - -fn foo_return() -> String { - "yay" -} - -fn foo_where() -> T where T: Sync { - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space () { - 1 -} - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) { - } -} - -trait CoolerTypes { fn dummy(&self) { -} -} - -fn Foo() where T: Bar { -} diff --git a/tests/source/fn_args_density-vertical.rs b/tests/source/fn_args_density-vertical.rs deleted file mode 100644 index b61c337dfb9..00000000000 --- a/tests/source/fn_args_density-vertical.rs +++ /dev/null @@ -1,33 +0,0 @@ -// rustfmt-fn_args_density: Vertical - -// Empty list should stay on one line. -fn do_bar( - -) -> u8 { - bar() -} - -// A single argument should stay on the same line. -fn do_bar( - a: u8) -> u8 { - bar() -} - -// Multiple arguments should each get their own line. -fn do_bar(a: u8, mut b: u8, c: &u8, d: &mut u8, closure: &Fn(i32) -> i32) -> i32 { - // This feature should not affect closures. - let bar = |x: i32, y: i32| -> i32 { x + y }; - bar(a, b) -} - -// If the first argument doesn't fit on the same line with the function name, -// the whole list should probably be pushed to the next line with hanging -// indent. That's not what happens though, so check current behaviour instead. -// In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, c: u8, d: u8) { - this(); - that(); - the_other_thing(); -} diff --git a/tests/source/fn_args_indent-block.rs b/tests/source/fn_args_indent-block.rs deleted file mode 100644 index b056fcb56fe..00000000000 --- a/tests/source/fn_args_indent-block.rs +++ /dev/null @@ -1,78 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { - bar() -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { - bar(); -} - -fn foo() -> T { - foo(); -} - -fn foo() -> T where X: Foooo, Y: Baaar { - foo(); -} - -fn foo() where X: Foooo { -} - -fn foo() where X: Foooo, Y: Baaar { -} - -fn foo() -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) { - foo(); -} - -fn foo() { - foo(); -} - -fn foo() { - foo(); -} - -fn foo() { - foo(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} -} - -fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { - foo(); -} - -fn foo() -> (Looooooooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiiiiiiis, Loooooooooooooooooooooong) { - foo(); -} diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs deleted file mode 100644 index b8fd09f8792..00000000000 --- a/tests/source/hard-tabs.rs +++ /dev/null @@ -1,85 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-hard_tabs: true -// rustfmt-error_on_line_overflow: false - -fn main() { -let x = Bar; - -let y = Foo {a: x }; - -Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - -fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) {} - -let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - -if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 -+ 2 + 3 { -} - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } - -unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} - -unsafe // So this is a very long comment. - // Multi-line, too. - // Will it still format correctly? -{ -} - -let chain = funktion_kall().go_to_next_line_with_tab().go_to_next_line_with_tab().go_to_next_line_with_tab(); - -let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; - -fn generic(arg: T) -> &SomeType - where T: Fn(// First arg - A, - // Second argument - B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { - arg(a, b, c, d, e) -} - - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - a.b - .c - .d(); - - x().y(|| { - match cond() { - true => (), - false => (), - } - }); -} - -// #2296 -impl Foo { - // a comment - // on multiple lines - fn foo() { - // another comment - // on multiple lines - let x = true; - } -} diff --git a/tests/source/hello.rs b/tests/source/hello.rs deleted file mode 100644 index f892e6debb1..00000000000 --- a/tests/source/hello.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-config: small_tabs.toml -// rustfmt-target: hello.rs - -// Smoke test - hello world. - -fn main() { println!("Hello world!"); } diff --git a/tests/source/hello2.rs b/tests/source/hello2.rs deleted file mode 100644 index 48af7de3887..00000000000 --- a/tests/source/hello2.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-config: small_tabs.toml -// rustfmt-target: hello.rs - -// Smoke test - hello world. - -fn main( ) { -println!("Hello world!"); -} diff --git a/tests/source/immovable_generators.rs b/tests/source/immovable_generators.rs deleted file mode 100644 index c57a1e14483..00000000000 --- a/tests/source/immovable_generators.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(generators)] - -unsafe fn foo() { - let mut ga = static || { - yield 1; - }; -} diff --git a/tests/source/impls.rs b/tests/source/impls.rs deleted file mode 100644 index ca8e486646a..00000000000 --- a/tests/source/impls.rs +++ /dev/null @@ -1,154 +0,0 @@ -// rustfmt-normalize_comments: true -impl Foo for Bar { fn foo() { "hi" } } - -pub impl Foo for Bar { - // Associated Constants - const Baz: i32 = 16; - // Associated Types - type FooBar = usize; - // Comment 1 - fn foo() { "hi" } - // Comment 2 - fn foo() { "hi" } - // Comment 3 -} - -pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { - fn foo() { "hi" } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> -{ - fn foo() { "hi" } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> -{ - fn foo() { "hi" } -} - -impl Foo for Bar where T: Baz -{ -} - -impl Foo for Bar where T: Baz { /* Comment */ } - -impl Foo { - fn foo() {} -} - -impl Boo { - - // BOO - fn boo() {} - // FOO - - - -} - -mod a { - impl Foo { - // Hello! - fn foo() {} - } -} - - -mod b { - mod a { - impl Foo { - fn foo() {} - } - } -} - -impl Foo { add_fun!(); } - -impl Blah { - fn boop() {} - add_fun!(); -} - -impl X { fn do_parse( mut self : X ) {} } - -impl Y5000 { - fn bar(self: X< 'a , 'b >, y: Y) {} - - fn bad(&self, ( x, y): CoorT) {} - - fn turbo_bad(self: X< 'a , 'b > , ( x, y): CoorT) { - - } -} - -pub impl Foo for Bar where T: Foo -{ - fn foo() { "hi" } -} - -pub impl Foo for Bar where T: Foo, Z: Baz {} - -mod m { - impl PartialEq for S where T: PartialEq { - fn eq(&self, other: &Self) { - true - } - } - - impl PartialEq for S where T: PartialEq { } - } - -impl Handle, HandleType> { -} - -impl PartialEq for Handle, HandleType> { -} - -mod x { - impl Foo - where A: 'static, - B: 'static, - C: 'static, - D: 'static { } -} - -impl Issue1249 { - // Creates a new flow constructor. - fn foo() {} -} - -// #1600 -impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { - fn drop() {} -} - -// #1168 -pub trait Number: Copy + Eq + Not + Shl + - Shr + - BitAnd + BitOr + BitAndAssign + BitOrAssign - - - -{ - // test - fn zero() -> Self; -} - -// #1642 -pub trait SomeTrait : Clone + Eq + PartialEq + Ord + PartialOrd + Default + Hash + Debug + Display + Write + Read + FromStr { - // comment -} - -// #1995 -impl Foo { - fn f( - S { - aaaaaaaaaa: aaaaaaaaaa, - bbbbbbbbbb: bbbbbbbbbb, - cccccccccc: cccccccccc, - }: S - ) -> u32{ - 1 - } -} diff --git a/tests/source/imports-reorder-lines-and-items.rs b/tests/source/imports-reorder-lines-and-items.rs deleted file mode 100644 index 3c71f9984fe..00000000000 --- a/tests/source/imports-reorder-lines-and-items.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imported_names: true - -/// This comment should stay with `use std::str;` -use std::str; -use std::cmp::{d, c, b, a}; -use std::ddd::aaa; -use std::ddd::{d as p, c as g, b, a}; -// This comment should stay with `use std::ddd:bbb;` -use std::ddd::bbb; diff --git a/tests/source/imports-reorder-lines.rs b/tests/source/imports-reorder-lines.rs deleted file mode 100644 index a855a964235..00000000000 --- a/tests/source/imports-reorder-lines.rs +++ /dev/null @@ -1,34 +0,0 @@ -// rustfmt-reorder_imports: true - -use std::str; -use std::cmp::{d, c, b, a}; -use std::cmp::{b, e, g, f}; -use std::ddd::aaa; -// This comment should stay with `use std::ddd;` -use std::ddd; -use std::ddd::bbb; - -mod test { -} - -use aaa::bbb; -use aaa; -use aaa::*; - -mod test {} -// If item names are equal, order by rename - -use test::{a as bb, b}; -use test::{a as aa, c}; - -mod test {} -// If item names are equal, order by rename - no rename comes before a rename - -use test::{a as bb, b}; -use test::{a, c}; - -mod test {} -// `self` always comes first - -use test::{a as aa, c}; -use test::{self as bb, b}; diff --git a/tests/source/imports-reorder.rs b/tests/source/imports-reorder.rs deleted file mode 100644 index 200cad2d13c..00000000000 --- a/tests/source/imports-reorder.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-reorder_imported_names: true - -use path::{C,/*A*/ A, B /* B */, self /* self */}; - -use {ab, ac, aa, Z, b}; diff --git a/tests/source/imports.rs b/tests/source/imports.rs deleted file mode 100644 index 73d1419f47d..00000000000 --- a/tests/source/imports.rs +++ /dev/null @@ -1,89 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-error_on_line_overflow: false - -// Imports. - -// Long import. -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; -use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; - -use list::{ - // Some item - SomeItem /* Comment */, /* Another item */ AnotherItem /* Another Comment */, // Last Item - LastItem -}; - -use test::{ Other /* C */ , /* A */ self /* B */ }; - -use syntax::{self}; -use {/* Pre-comment! */ - Foo, Bar /* comment */}; -use Foo::{Bar, Baz}; -pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; -use syntax::some::{}; - -use self; -use std::io::{self}; -use std::io::self; - -mod Foo { - pub use syntax::ast::{ - ItemForeignMod, - ItemImpl, - ItemMac, - ItemMod, - ItemStatic, - ItemDefaultImpl - }; - - mod Foo2 { - pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; - } -} - -fn test() { -use Baz::*; - use Qux; -} - -// Simple imports -use foo::bar::baz as baz ; -use bar::quux as kaas; -use foo; - -// With aliases. -use foo::{self as bar, baz}; -use foo::{self as bar}; -use foo::{qux as bar}; -use foo::{baz, qux as bar}; - -// With absolute paths -use ::foo; -use ::foo::{Bar}; -use ::foo::{Bar, Baz}; -use ::{Foo}; -use ::{Bar, Baz}; - -// Root globs -use *; -use ::*; - -// spaces used to cause glob imports to disappear (#1356) -use super:: * ; -use foo::issue_1356:: * ; - -// We shouldn't remove imports which have attributes attached (#1858) -#[cfg(unix)] -use self::unix::{}; - -// nested imports -use foo::{a, bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}, b, boo, c,}; - -use fooo::{baar::{foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}}, z, bar, bar::*, x, y}; - -// nested imports with a single sub-tree. -use a::{b::{c::*}}; -use a::{b::{c::{}}}; -use a::{b::{c::d}}; -use a::{b::{c::{xxx, yyy, zzz}}}; diff --git a/tests/source/issue-1021.rs b/tests/source/issue-1021.rs deleted file mode 100644 index 380e24cc0b0..00000000000 --- a/tests/source/issue-1021.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - match x { - S(true , .., true ) => (), - S(true , .. ) => (), - S(.., true ) => (), - S( .. ) => (), - S(_) => (), - S(/* .. */ .. ) => (), - S(/* .. */ .., true ) => (), - } - - match y { - (true , .., true ) => (), - (true , .. ) => (), - (.., true ) => (), - ( .. ) => (), - (_,) => (), - (/* .. */ .. ) => (), - (/* .. */ .., true ) => (), - } -} diff --git a/tests/source/issue-1049.rs b/tests/source/issue-1049.rs deleted file mode 100644 index bcfba41e768..00000000000 --- a/tests/source/issue-1049.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Test overlong function signature -pub unsafe fn reborrow_mut(&mut X: Abcde) -> Handle, HandleType> { -} - -pub fn merge(mut X: Abcdef) -> Handle, K, V, marker::Internal>, marker::Edge> { -} - -impl Handle { - pub fn merge(a: Abcd) -> Handle, K, V, marker::Internal>, marker::Edge> { - } -} - -// Long function without return type that should not be reformatted. -fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} - -fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} - -fn veeeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} diff --git a/tests/source/issue-1111.rs b/tests/source/issue-1111.rs deleted file mode 100644 index 2e1a89ad78e..00000000000 --- a/tests/source/issue-1111.rs +++ /dev/null @@ -1 +0,0 @@ -use bar; diff --git a/tests/source/issue-1120.rs b/tests/source/issue-1120.rs deleted file mode 100644 index e85c9af99d4..00000000000 --- a/tests/source/issue-1120.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-reorder_imports: true - -// Ensure that a use at the start of an inline module is correctly formatted. -mod foo {use bar;} - -// Ensure that an indented `use` gets the correct indentation. -mod foo { - use bar; -} diff --git a/tests/source/issue-1124.rs b/tests/source/issue-1124.rs deleted file mode 100644 index 69aa1bb1c59..00000000000 --- a/tests/source/issue-1124.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-normalize_comments: true - -use d; use c; use b; use a; -// The previous line has a space after the `use a;` - -mod a { use d; use c; use b; use a; } - -use z; - -use y; - - - -use x; -use a; \ No newline at end of file diff --git a/tests/source/issue-1127.rs b/tests/source/issue-1127.rs deleted file mode 100644 index 9996c194818..00000000000 --- a/tests/source/issue-1127.rs +++ /dev/null @@ -1,23 +0,0 @@ -// rustfmt-max_width:120 -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true - -fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { - 42 -} - -enum TestEnum { - AVeryVeryLongEnumName, - AnotherVeryLongEnumName, - TheLastVeryLongEnumName, -} - -fn main() { - let var = TestEnum::AVeryVeryLongEnumName; - let num = match var { - TestEnum::AVeryVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::AnotherVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::TheLastVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - }; -} - diff --git a/tests/source/issue-1158.rs b/tests/source/issue-1158.rs deleted file mode 100644 index 6742e17459e..00000000000 --- a/tests/source/issue-1158.rs +++ /dev/null @@ -1,3 +0,0 @@ -trait T { - itemmacro!(this, is.now() .formatted(yay)); -} diff --git a/tests/source/issue-1177.rs b/tests/source/issue-1177.rs deleted file mode 100644 index 3ac423c5aef..00000000000 --- a/tests/source/issue-1177.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - // Line Comment - /* Block Comment */ - - let d = 5; -} diff --git a/tests/source/issue-1192.rs b/tests/source/issue-1192.rs deleted file mode 100644 index 4e39fbf9a36..00000000000 --- a/tests/source/issue-1192.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - assert!(true) ; -} diff --git a/tests/source/issue-1211.rs b/tests/source/issue-1211.rs deleted file mode 100644 index 5818736bf6b..00000000000 --- a/tests/source/issue-1211.rs +++ /dev/null @@ -1,15 +0,0 @@ -fn main() { - for iface in &ifaces { - match iface.addr { - get_if_addrs::IfAddr::V4(ref addr) => { - match addr.broadcast { - Some(ip) => { - sock.send_to(&buf, (ip, 8765)).expect("foobar"); - } - _ => () - } - } - _ => () - }; - } -} diff --git a/tests/source/issue-1216.rs b/tests/source/issue-1216.rs deleted file mode 100644 index d727c158ab8..00000000000 --- a/tests/source/issue-1216.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-normalize_comments: true -enum E { - A, //* I am not a block comment (caused panic) - B, -} diff --git a/tests/source/issue-1239.rs b/tests/source/issue-1239.rs deleted file mode 100644 index 913058257ed..00000000000 --- a/tests/source/issue-1239.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn foo() { - let with_alignment = if condition__uses_alignment_for_first_if__0 || - condition__uses_alignment_for_first_if__1 || - condition__uses_alignment_for_first_if__2 { - } else if condition__no_alignment_for_later_else__0 || - condition__no_alignment_for_later_else__1 || - condition__no_alignment_for_later_else__2 { - }; -} diff --git a/tests/source/issue-1278.rs b/tests/source/issue-1278.rs deleted file mode 100644 index e25376561a9..00000000000 --- a/tests/source/issue-1278.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style = "block" - -#![feature(pub_restricted)] - -mod inner_mode { - pub(super) fn func_name(abc: i32) -> i32 { - abc - } -} diff --git a/tests/source/issue-1350.rs b/tests/source/issue-1350.rs deleted file mode 100644 index 1baa1985a7e..00000000000 --- a/tests/source/issue-1350.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-max_width: 120 -// rustfmt-comment_width: 110 - -impl Struct { - fn fun() { - let result = match ::deserialize(&json) { - Ok(v) => v, - Err(e) => { - match ::deserialize(&json) { - Ok(v) => return Err(Error::with_json(v)), - Err(e2) => return Err(Error::with_json(e)), - } - } - }; - } -} diff --git a/tests/source/issue-1366.rs b/tests/source/issue-1366.rs deleted file mode 100644 index 9d2964fc77c..00000000000 --- a/tests/source/issue-1366.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - fn f() -> Option { - Some("fffffffsssssssssddddssssfffffddddff").map(|s| s).map(|s| s.to_string()).map(|res| { - match Some(res) { - Some(ref s) if s == "" => 41, - Some(_) => 42, - _ => 43, - } - }) - } - println!("{:?}", f()) -} diff --git a/tests/source/issue-1468.rs b/tests/source/issue-1468.rs deleted file mode 100644 index 4d0d4f0eb98..00000000000 --- a/tests/source/issue-1468.rs +++ /dev/null @@ -1,27 +0,0 @@ -fn issue1468() { -euc_jp_decoder_functions!({ -let trail_minus_offset = byte.wrapping_sub(0xA1); -// Fast-track Hiragana (60% according to Lunde) -// and Katakana (10% according to Lunde). -if jis0208_lead_minus_offset == 0x03 && -trail_minus_offset < 0x53 { -// Hiragana -handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) -} else if jis0208_lead_minus_offset == 0x04 && -trail_minus_offset < 0x56 { -// Katakana -handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) -} else if trail_minus_offset > (0xFE - 0xA1) { -if byte < 0x80 { -return (DecoderResult::Malformed(1, 0), -unread_handle_trail.unread(), -handle.written()); -} -return (DecoderResult::Malformed(2, 0), -unread_handle_trail.consumed(), -handle.written()); -} else { -unreachable!(); -} -}); -} diff --git a/tests/source/issue-1693.rs b/tests/source/issue-1693.rs deleted file mode 100644 index 0622ce50235..00000000000 --- a/tests/source/issue-1693.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn issue1693() { - let pixel_data = vec![(f16::from_f32(0.82), f16::from_f32(1.78), f16::from_f32(0.21)); 256 * 256]; -} diff --git a/tests/source/issue-1800.rs b/tests/source/issue-1800.rs deleted file mode 100644 index eae22653258..00000000000 --- a/tests/source/issue-1800.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![doc(html_root_url = "http://example.com")] -#[cfg(feature = "foo")] -fn a() {} diff --git a/tests/source/issue-1914.rs b/tests/source/issue-1914.rs deleted file mode 100644 index 447296c4b87..00000000000 --- a/tests/source/issue-1914.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-max_width: 80 - -extern "C" { -#[link_name = "_ZN7MyClass26example_check_no_collisionE"] - pub static mut MyClass_example_check_no_collision : * const :: std :: os :: raw :: c_int ; -} diff --git a/tests/source/issue-2025.rs b/tests/source/issue-2025.rs deleted file mode 100644 index c6f61b4e3e1..00000000000 --- a/tests/source/issue-2025.rs +++ /dev/null @@ -1,8 +0,0 @@ - - - - -// See if rustfmt removes empty lines on top of the file. -pub fn foo() { - println!("hello, world"); -} diff --git a/tests/source/issue-2111.rs b/tests/source/issue-2111.rs deleted file mode 100644 index d1b02053e2a..00000000000 --- a/tests/source/issue-2111.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-normalize_comments: false - -// An import with single line comments. -use super::{ - SCHEMA_VERSIONS, - LodaModel, - ModelProperties, - StringMap, - ModelSelector, - RequestDescription, - MethodDescription, - ModelBehaviour, - ModelRequestGraph, - DelayChoice, - Holding, - Destinations, - ModelEdges, - Switch, - // ModelMetaData, - // Generated, - // SecondsString, - // DateString, - // ModelConfiguration, - // ModelRequests, - // RestResponse, - // RestResponseCode, - // UniformHolding -}; diff --git a/tests/source/issue-2164.rs b/tests/source/issue-2164.rs deleted file mode 100644 index 6c288e1bd62..00000000000 --- a/tests/source/issue-2164.rs +++ /dev/null @@ -1,4 +0,0 @@ -// A stress test against code generated by bindgen. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct emacs_env_25 { pub size : isize , pub private_members : * mut emacs_env_private , pub make_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , any_reference : emacs_value ) -> emacs_value > , pub free_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , global_reference : emacs_value ) > , pub non_local_exit_check : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) -> emacs_funcall_exit > , pub non_local_exit_clear : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) > , pub non_local_exit_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol_out : * mut emacs_value , non_local_exit_data_out : * mut emacs_value ) -> emacs_funcall_exit > , pub non_local_exit_signal : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol : emacs_value , non_local_exit_data : emacs_value ) > , pub non_local_exit_throw : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , tag : emacs_value , value : emacs_value ) > , pub make_function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , min_arity : isize , max_arity : isize , function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , nargs : isize , args : * mut emacs_value , arg1 : * mut ::libc :: c_void ) -> emacs_value > , documentation : * const ::libc :: c_char , data : * mut ::libc :: c_void ) -> emacs_value > , pub funcall : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , function : emacs_value , nargs : isize , args : * mut emacs_value ) -> emacs_value > , pub intern : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , symbol_name : * const ::libc :: c_char ) -> emacs_value > , pub type_of : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> emacs_value > , pub is_not_nil : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> bool > , pub eq : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , a : emacs_value , b : emacs_value ) -> bool > , pub extract_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> intmax_t > , pub make_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : intmax_t ) -> emacs_value > , pub extract_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> f64 > , pub make_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : f64 ) -> emacs_value > , pub copy_string_contents : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value , buffer : * mut ::libc :: c_char , size_inout : * mut isize ) -> bool > , pub make_string : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , contents : * const ::libc :: c_char , length : isize ) -> emacs_value > , pub make_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > , ptr : * mut ::libc :: c_void ) -> emacs_value > , pub get_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value ) -> * mut ::libc :: c_void > , pub set_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , ptr : * mut ::libc :: c_void ) > , pub get_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) -> :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) > > , pub set_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > ) > , pub vec_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize ) -> emacs_value > , pub vec_set : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize , val : emacs_value ) > , pub vec_size : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value ) -> isize > , } diff --git a/tests/source/issue-2179.rs b/tests/source/issue-2179.rs deleted file mode 100644 index ade953971ec..00000000000 --- a/tests/source/issue-2179.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -fn issue_2179() { - let (opts, rustflags, clear_env_rust_log) = - { - // We mustn't lock configuration for the whole build process - let rls_config = rls_config.lock().unwrap(); - - let opts = CargoOptions::new(&rls_config); - trace!("Cargo compilation options:\n{:?}", opts); - let rustflags = prepare_cargo_rustflags(&rls_config); - - // Warn about invalid specified bin target or package depending on current mode - // TODO: Return client notifications along with diagnostics to inform the user - if !rls_config.workspace_mode { - let cur_pkg_targets = ws.current().unwrap().targets(); - - if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { - let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); - if let None = bins.find(|x| x.name() == build_bin) { - warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); - } - } - } else { - for package in &opts.package { - if let None = ws.members().find(|x| x.name() == package) { - warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); - } - } - } - - (opts, rustflags, rls_config.clear_env_rust_log) - }; - -} diff --git a/tests/source/issue-2256.rs b/tests/source/issue-2256.rs deleted file mode 100644 index b505b96e2b3..00000000000 --- a/tests/source/issue-2256.rs +++ /dev/null @@ -1,12 +0,0 @@ -// こんにちは -use std::{}; -use std::borrow::Cow; - -/* comment */ use std::{}; -/* comment */ use std::{}; - - - - - -/* comment */ use std::{}; diff --git a/tests/source/issue-2342.rs b/tests/source/issue-2342.rs deleted file mode 100644 index f86d24a146b..00000000000 --- a/tests/source/issue-2342.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-max_width: 80 - -struct Foo { - #[cfg(feature = "serde")] bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN -} diff --git a/tests/source/issue-447.rs b/tests/source/issue-447.rs deleted file mode 100644 index 7c542cb58c2..00000000000 --- a/tests/source/issue-447.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - if /* shouldn't be dropped - shouldn't be dropped */ - - cond /* shouldn't be dropped - shouldn't be dropped */ - - { - } /* shouldn't be dropped - shouldn't be dropped */ - - else /* shouldn't be dropped - shouldn't be dropped */ - - if /* shouldn't be dropped - shouldn't be dropped */ - - cond /* shouldn't be dropped - shouldn't be dropped */ - - { - } /* shouldn't be dropped - shouldn't be dropped */ - - else /* shouldn't be dropped - shouldn't be dropped */ - - { - } - - if /* shouldn't be dropped - shouldn't be dropped */ - let Some(x) = y/* shouldn't be dropped - shouldn't be dropped */ - { - } -} diff --git a/tests/source/issue-510.rs b/tests/source/issue-510.rs deleted file mode 100644 index 4c60859e6cf..00000000000 --- a/tests/source/issue-510.rs +++ /dev/null @@ -1,37 +0,0 @@ -impl ISizeAndMarginsComputer for AbsoluteNonReplaced { -fn solve_inline_size_constraints(&self, -block: &mut BlockFlow, -input: &ISizeConstraintInput) --> ISizeConstraintSolution { -let (inline_start,inline_size,margin_inline_start,margin_inline_end) = -match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { -(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { -let margin_start = inline_start_margin.specified_or_zero(); -let margin_end = inline_end_margin.specified_or_zero(); -// Now it is the same situation as inline-start Specified and inline-end -// and inline-size Auto. -// -// Set inline-end to zero to calculate inline-size. -let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - -(margin_start + margin_end)); -(Au(0), inline_size, margin_start, margin_end) -} -}; - - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_start, inline_end, computed_inline_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - (Au(0), inline_size, margin_start, margin_end) - } - }; -} -} diff --git a/tests/source/issue-811.rs b/tests/source/issue-811.rs deleted file mode 100644 index b7a89b5d0f9..00000000000 --- a/tests/source/issue-811.rs +++ /dev/null @@ -1,19 +0,0 @@ -trait FooTrait: Sized { - type Bar: BarTrait; -} - -trait BarTrait: Sized { - type Baz; - fn foo(); -} - -type Foo = <>::Bar as BarTrait>::Baz; -type Bar = >::Baz; - -fn some_func, U>() { - <>::Bar as BarTrait>::foo(); -} - -fn some_func>() { - >::foo(); -} diff --git a/tests/source/issue-850.rs b/tests/source/issue-850.rs deleted file mode 100644 index c939716a6a8..00000000000 --- a/tests/source/issue-850.rs +++ /dev/null @@ -1 +0,0 @@ -const unsafe fn x() {} diff --git a/tests/source/issue-855.rs b/tests/source/issue-855.rs deleted file mode 100644 index 8f33fa685ae..00000000000 --- a/tests/source/issue-855.rs +++ /dev/null @@ -1,20 +0,0 @@ -fn main() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, - } - } - } -} - -fn main2() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit {..} | - Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => break 'running, - } - } - } -} diff --git a/tests/source/issue-913.rs b/tests/source/issue-913.rs deleted file mode 100644 index e1c1b225fa5..00000000000 --- a/tests/source/issue-913.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -mod client { - impl Client { - fn test(self) -> Result<()> { - let next_state = match self.state { - State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { - let x = reformat . meeee() ; - } - }; - - let next_state = match self.state { - State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { - // The pattern cannot be formatted in a way that the match stays - // within the column limit. The rewrite should therefore be - // skipped. - let x = dont . reformat . meeee(); - } - }; - } - } -} diff --git a/tests/source/issue-945.rs b/tests/source/issue-945.rs deleted file mode 100644 index 37d703c4679..00000000000 --- a/tests/source/issue-945.rs +++ /dev/null @@ -1,5 +0,0 @@ -impl Bar { default const unsafe fn foo() { "hi" } } - -impl Baz { default unsafe extern "C" fn foo() { "hi" } } - -impl Foo for Bar { default fn foo() { "hi" } } diff --git a/tests/source/issue-977.rs b/tests/source/issue-977.rs deleted file mode 100644 index b028b36a055..00000000000 --- a/tests/source/issue-977.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-normalize_comments: true -// FIXME(#919) - -trait NameC { /* comment */ } -struct FooC { /* comment */ } -enum MooC { /* comment */ } -mod BarC { /* comment */ } -extern { /* comment */ } diff --git a/tests/source/item-brace-style-always-next-line.rs b/tests/source/item-brace-style-always-next-line.rs deleted file mode 100644 index 38094d67a77..00000000000 --- a/tests/source/item-brace-style-always-next-line.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/tests/source/item-brace-style-prefer-same-line.rs b/tests/source/item-brace-style-prefer-same-line.rs deleted file mode 100644 index dff89b8b66b..00000000000 --- a/tests/source/item-brace-style-prefer-same-line.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-brace_style: PreferSameLine - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/tests/source/item-brace-style-same-line-where.rs b/tests/source/item-brace-style-same-line-where.rs deleted file mode 100644 index ee4a7c5daad..00000000000 --- a/tests/source/item-brace-style-same-line-where.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-brace_style: SameLineWhere - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/tests/source/large-block.rs b/tests/source/large-block.rs deleted file mode 100644 index 09e9169f340..00000000000 --- a/tests/source/large-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn issue1351() { - std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ - static __STATIC_FMTSTR: &'static [&'static str] = &[]; - }); -} diff --git a/tests/source/large_vec.rs b/tests/source/large_vec.rs deleted file mode 100644 index 34d5bf39954..00000000000 --- a/tests/source/large_vec.rs +++ /dev/null @@ -1,29 +0,0 @@ -// See #1470. - -impl Environment { - pub fn new_root() -> Rc> { - let mut env = Environment::new(); - let builtin_functions = &[("println", - Function::NativeVoid(CallSign { - num_params: 0, - variadic: true, - param_types: vec![], - }, - native_println)), - ("run_http_server", - Function::NativeVoid(CallSign { - num_params: 1, - variadic: false, - param_types: - vec![Some(ConstraintType::Function)], - }, - native_run_http_server)), - ("len", - Function::NativeReturning(CallSign { - num_params: 1, - variadic: false, - param_types: vec![None], - }, - native_len))]; - } -} diff --git a/tests/source/long-match-arms-brace-newline.rs b/tests/source/long-match-arms-brace-newline.rs deleted file mode 100644 index 927ada0ffb2..00000000000 --- a/tests/source/long-match-arms-brace-newline.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 80 -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - match x { - aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == - "aaaaaaaaaaa \ - aaaaaaa \ - aaaaaa" => { - Ok(()) - } - _ => Err(x), - } -} diff --git a/tests/source/long_field_access.rs b/tests/source/long_field_access.rs deleted file mode 100644 index 7aa626221ae..00000000000 --- a/tests/source/long_field_access.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn f() { - block_flow.base.stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; -} diff --git a/tests/source/loop.rs b/tests/source/loop.rs deleted file mode 100644 index 6e92cdc6c2c..00000000000 --- a/tests/source/loop.rs +++ /dev/null @@ -1,29 +0,0 @@ - -fn main() { - loop - { return some_val;} - -let x = loop { do_forever(); }; - - 'label : loop { - // Just comments - } - - 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value{} - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { - } - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {} - - 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { - // do smth - } - - while let Some(i) = x.find('s') - { - x.update(); - continue; - continue 'foo; - } -} diff --git a/tests/source/macro_not_expr.rs b/tests/source/macro_not_expr.rs deleted file mode 100644 index d8de4dce38f..00000000000 --- a/tests/source/macro_not_expr.rs +++ /dev/null @@ -1,7 +0,0 @@ -macro_rules! test { - ($($t:tt)*) => {} -} - -fn main() { - test!( a : B => c d ); -} diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs deleted file mode 100644 index 7d14f44971d..00000000000 --- a/tests/source/macro_rules.rs +++ /dev/null @@ -1,51 +0,0 @@ -macro_rules! m { - // a - ($expr :expr, $( $func : ident ) * ) => { - { - let x = $expr; - $func ( - x - ) - } - }; - - /* b */ - - () => {/* c */}; - - (@tag) => - { - - }; - -// d -( $item:ident ) => { - mod macro_item { struct $item ; } -}; -} - -macro m2 { - // a - ($expr :expr, $( $func : ident ) * ) => { - { - let x = $expr; - $func ( - x - ) - } - } - - /* b */ - - () => {/* c */} - - (@tag) => - { - - } - -// d -( $item:ident ) => { - mod macro_item { struct $item ; } -} -} diff --git a/tests/source/macros.rs b/tests/source/macros.rs deleted file mode 100644 index ffd5c19cc8c..00000000000 --- a/tests/source/macros.rs +++ /dev/null @@ -1,338 +0,0 @@ -// rustfmt-normalize_comments: true -itemmacro!(this, is.now() .formatted(yay)); - -itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); - -itemmacro!{this, is.bracket().formatted()} - -peg_file! modname ("mygrammarfile.rustpeg"); - -fn main() { - foo! ( ); - - bar!( a , b , c ); - - bar!( a , b , c , ); - - baz!(1+2+3, quux. kaas()); - - quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); - - kaas!(/* comments */ a /* post macro */, b /* another */); - - trailingcomma!( a , b , c , ); - // Preserve trailing comma only when necessary. - ok!(file.seek( - SeekFrom::Start( - table.map(|table| fixture.offset(table)).unwrap_or(0), - ) - )); - - noexpr!( i am not an expression, OK? ); - - vec! [ a , b , c]; - - vec! [AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, - BBBBB, 5, 100-30, 1.33, b, b, b]; - - vec! [a /* comment */]; - - // Trailing spaces after a comma - vec![ - a, - ]; - - vec![a; b]; - vec!(a; b); - vec!{a; b}; - - vec![a, b; c]; - vec![a; b, c]; - - vec![a; (|x| { let y = x + 1; let z = y + 1; z })(2)]; - vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; - vec![a; unsafe { - x + 1 - }]; - - unknown_bracket_macro__comma_should_not_be_stripped![ - a, - ]; - - foo(makro!(1, 3)); - - hamkaas!{ () }; - - macrowithbraces! {dont, format, me} - - x!(fn); - - some_macro!( - - ); - - some_macro![ - ]; - - some_macro!{ - // comment - }; - - some_macro!{ - // comment - }; - - some_macro!( - // comment - not function like - ); - - // #1712 - let image = gray_image!( - 00, 01, 02; - 10, 11, 12; - 20, 21, 22); - - // #1092 - chain!(input, a:take!(max_size), || []); -} - -impl X { - empty_invoc!{} -} - -fn issue_1279() { - println!("dsfs"); // a comment -} - -fn issue_1555() { - let hello = &format!("HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", - "65454654654654654654654655464", - "4"); -} - -fn issue1178() { - macro_rules! foo { - (#[$attr:meta] $name:ident) => {} - } - - foo!(#[doc = "bar"] baz); -} - -fn issue1739() { - sql_function!(add_rss_item, - add_rss_item_t, - (a: types::Integer, - b: types::Timestamptz, - c: types::Text, - d: types::Text, - e: types::Text)); - - w.slice_mut(s![.., init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], ..]) - .par_map_inplace(|el| *el = 0.); -} - -fn issue_1885() { - let threads = people.into_iter().map(|name| { - chan_select! { - rx.recv() => {} - } - }).collect::>(); -} - -fn issue_1917() { - mod x { - quickcheck! { - fn test(a: String, s: String, b: String) -> TestResult { - if a.find(&s).is_none() { - - TestResult::from_bool(true) - } else { - TestResult::discard() - } - } - } - } -} - -fn issue_1921() { - // Macro with tabs. - lazy_static! { - static ref ONE: u32 = 1; - static ref TWO: u32 = 2; - static ref THREE: u32 = 3; - static ref FOUR: u32 = { - let mut acc = 1; - acc += 1; - acc += 2; - acc - } -} -} - -// #1577 -fn issue1577() { - let json = json!({ - "foo": "bar", - }); -} - -gfx_pipeline!(pipe { - vbuf: gfx::VertexBuffer = (), - out: gfx::RenderTarget = "Target0", -}); - -// #1919 -#[test] -fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq ! ( :: std :: mem :: align_of :: < HandleWithDtor < :: std :: os :: raw :: c_int > > ( ) , 8usize , concat ! ( "Alignment of template specialization: " , stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) ) ); -} - -// #878 -macro_rules! try_opt { - ($expr:expr) => (match $expr { - Some(val) => val, - - None => { return None; } - }) -} - -// #2214 -// macro call whose argument is an array with trailing comma. -fn issue2214() { -make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [ - Reject(0, 1), - Match (1, 3), - Reject(3, 4), - Match (4, 6), - Reject(6, 7), -]); -} - -fn special_case_macros() { - let p = eprint!(); - let q = eprint!("{}", 1); - let r = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = eprintln!("{}", 1); - let r = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = format!("{}", 1); - let r = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = format_args!("{}", 1); - let r = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = print!("{}", 1); - let r = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = println!("{}", 1); - let r = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = unreachable!("{}", 1); - let r = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - debug!("{}", 1); - debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - error!("{}", 1); - error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - info!("{}", 1); - info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - panic!("{}", 1); - panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - warn!("{}", 1); - warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - assert!(); - assert!(result == 42); - assert!(result == 42, "Ahoy there, {}!", target); - assert!(result == 42, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - assert_eq!(); - assert_eq!(left); - assert_eq!(left, right); - assert_eq!(left, right, "Ahoy there, {}!", target); - assert_eq!(left, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert_eq!(left + 42, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - write!(&mut s, "Ahoy there, {}!", target); - write!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - write!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - writeln!(&mut s, "Ahoy there, {}!", target); - writeln!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - writeln!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); -} - -// #1209 -impl Foo { - /// foo - pub fn foo(&self) -> Bar {} -} - -// #819 -fn macro_in_pattern_position () { - let x = match y { - foo!( ) => (), - bar!( a, b, - c) => (), - bar!(a - , b - , c - ,) => (), - baz!( 1 + 2 + 3, quux.kaas( ) - ) => (), - quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) => (), - }; -} - -macro foo() { - - -} - -pub macro bar($x:ident+$y:expr; ) { - fn foo($x: Foo) { - long_function(a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), - $x.bar($y)); - } -} - -macro foo() { - // a comment - fn foo() { - // another comment - bar(); - } -} - -macro lex_err($kind: ident $(, $body: expr)*) { - Err(QlError::LexError(LexError::$kind($($body,)*))) -} diff --git a/tests/source/match-block-trailing-comma.rs b/tests/source/match-block-trailing-comma.rs deleted file mode 100644 index e9daac13bf9..00000000000 --- a/tests/source/match-block-trailing-comma.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - } - b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - } -} diff --git a/tests/source/match-nowrap-trailing-comma.rs b/tests/source/match-nowrap-trailing-comma.rs deleted file mode 100644 index 134d2fdf9a4..00000000000 --- a/tests/source/match-nowrap-trailing-comma.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - } - b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - } -} diff --git a/tests/source/match-nowrap.rs b/tests/source/match-nowrap.rs deleted file mode 100644 index db22cd9f010..00000000000 --- a/tests/source/match-nowrap.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { foo() } - b => - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - } -} diff --git a/tests/source/match.rs b/tests/source/match.rs deleted file mode 100644 index 23df0d3b681..00000000000 --- a/tests/source/match.rs +++ /dev/null @@ -1,453 +0,0 @@ -// rustfmt-normalize_comments: true -// Match expressions. - -fn foo() { - // A match expression. - match x { - // Some comment. - a => foo(), - b if 0 < 42 => foo(), - c => { // Another comment. - // Comment. - an_expression; - foo() - } - Foo(ref bar) => - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - Pattern1 | Pattern2 | Pattern3 => false, - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { - blah - } - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn => meh, - - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, - - Patternnnnnnnnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => - meh, - - // Test that earlier patterns can take the guard space - (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | - Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} - - _ => {} - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || - data.types.len() > 0 || - data.bindings.len() > 0 => {} - } - - let whatever = match something { - /// DOC COMMENT! - Some(_) => 42, - // Comment on an attribute. - #[an_attribute] - // Comment after an attribute. - None => 0, - #[rustfmt_skip] - Blurb => { } - }; -} - -// Test that a match on an overflow line is laid out properly. -fn main() { - let sub_span = - match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - Some(sub_span) => Some(sub_span), - None => sub_span, - }; -} - -// Test that one-line bodies align. -fn main() { - match r { - Variableeeeeeeeeeeeeeeeee => ( "variable", - vec!("id", "name", "qualname", - "value", "type", "scopeid"), - true, - true), - Enummmmmmmmmmmmmmmmmmmmm => ("enum", - vec!("id","qualname","scopeid","value"), - true, - true), - Variantttttttttttttttttttttttt => ("variant", - vec!("id", - "name", - "qualname", - "type", - "value", - "scopeid"), - true, - true), - }; - - match x{ - y=>{/*Block with comment. Preserve me.*/ } - z=>{stmt();} } -} - -fn matches() { - match 1 { - -1 => 10, - 1 => 1, // foo - 2 => 2, - // bar - 3 => 3, - _ => 0 // baz - } -} - -fn match_skip() { - let _ = match Some(1) { - #[rustfmt_skip] - Some( n ) => n, - None => 1, - }; -} - -fn issue339() { - match a { - b => {} - c => { } - d => { - } - e => { - - - - } - // collapsing here is safe - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { - } - // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } - h => { // comment above block - } - i => { - } // comment below block - j => { - // comment inside block - } - j2 => { - // comments inside... - } // ... and after - // TODO uncomment when vertical whitespace is handled better - // k => { - // - // // comment with WS above - // } - // l => { - // // comment with ws below - // - // } - m => { - } n => { } o => - { - - } - p => { // Dont collapse me - } q => { } r => - { - - } - s => 0, // s comment - // t comment - t => 1, - u => 2, - v => { - } /* funky block - * comment */ - // final comment - } -} - -fn issue355() { - match mac { - a => println!("a", b), - b => vec!(1, 2), - c => vec!(3; 4), - d => { - println!("a", b) - } - e => { - vec!(1, 2) - } - f => { - vec!(3; 4) - } - h => println!("a", b), // h comment - i => vec!(1, 2), // i comment - j => vec!(3; 4), // j comment - // k comment - k => println!("a", b), - // l comment - l => vec!(1, 2), - // m comment - m => vec!(3; 4), - // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), - // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), - // Macro support fails to recognise this macro as splittable - // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), - // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), - // Funky bracketing styles - t => println!{"a", b}, - u => vec!{1, 2}, - v => vec!{3; 4}, - w => println!["a", b], - x => vec![1, 2], - y =>vec![3; 4], - // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec!{1, 2}, // comment - vc =>vec!{3; 4}, // comment - wc =>println!["a", b], // comment - xc => vec![1,2], // comment - yc => vec![3; 4], // comment - yd => - looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd), - } -} - -fn issue280() { - { - match x { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == - '\n', - ast::ItemConst(ref typ, ref expr) => self.process_static_or_const_item(item, - &typ, - &expr), - } - } -} - -fn issue383() { - match resolution.last_private {LastImport{..} => false, _ => true}; -} - -fn issue507() { - match 1 { - 1 => unsafe { std::intrinsics::abort() }, - _ => (), - } -} - -fn issue508() { - match s.type_id() { - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLCanvasElement))) => true, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), - Some(NodeTypeId::Element(_)) => false, - } -} - -fn issue496() {{{{ - match def { - def::DefConst(def_id) | def::DefAssociatedConst(def_id) => - match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { - Some(const_expr) => { x }}}}}}} - -fn issue494() { - { - match stmt.node { - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => - result.push( - StmtRef::Mirror( - Box::new(Stmt { span: stmt.span, - kind: StmtKind::Expr { - scope: cx.tcx.region_maps.node_extent(id), - expr: expr.to_ref() } }))), - } - } -} - -fn issue386() { - match foo { - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => - true, - BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | - BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => - false, - } -} - -fn guards() { - match foo { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if fooooooooooooooooooooo && - (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {} - } -} - -fn issue1371() { - Some(match type_ { - sfEvtClosed => Closed, - sfEvtResized => { - let e = unsafe { *event.size.as_ref() }; - - Resized { - width: e.width, - height: e.height, - } - } - sfEvtLostFocus => LostFocus, - sfEvtGainedFocus => GainedFocus, - sfEvtTextEntered => { - TextEntered { - unicode: unsafe { - ::std::char::from_u32((*event.text.as_ref()).unicode) - .expect("Invalid unicode encountered on TextEntered event") - }, - } - } - sfEvtKeyPressed => { - let e = unsafe { event.key.as_ref() }; - - KeyPressed { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - sfEvtKeyReleased => { - let e = unsafe { event.key.as_ref() }; - - KeyReleased { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - }) -} - -fn issue1395() { - let bar = Some(true); - let foo = Some(true); - let mut x = false; - bar.and_then(|_| { - match foo { - None => None, - Some(b) => { - x = true; - Some(b) - } - } - }); -} - -fn issue1456() { - Ok(Recording { - artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { - Nodeset(nodeset) => { - let res: Result, ReadError> = nodeset - .iter() - .map(|node| { - XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) - }) - .collect(); - res? - } - _ => Vec::new(), - }, - }) -} - -fn issue1460() { - let _ = match foo { - REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => "internal_spec_insert_internal_spec_insert_internal_spec_insert", - _ => "reorder_something", - }; -} - -fn issue525() { - foobar(f, "{}", match *self { - TaskState::Started => "started", - TaskState::Success => "success", - TaskState::Failed => "failed", - }); -} - -// #1838, #1839 -fn match_with_near_max_width() { - let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { - _ => unimplemented!(), - }; - - let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { - _ => unimplemented!(), - }; - - let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression - { - _ => unimplemented!(), - }; - match m { - Variant::Tag | Variant::Tag2 | Variant::Tag3 | Variant::Tag4 | Variant::Tag5 | Variant::Tag6 => - {} - } -} - -fn match_with_trailing_spaces() { - match x { - #![allow(simple_match)] - Some(..) => 0, - None => 1, - } -} - -fn issue_2099() { - let a = match x { -}; - let b = match x { - - }; - - match x {} -} - -// #2021 -impl<'tcx> Const<'tcx> { - pub fn from_constval<'a>() -> Const<'tcx> { - let val = match *cv { - ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv), - }; - } -} - -// #2151 -fn issue_2151() { - match either { - x => { - - }y => () - } -} - -// #2152 -fn issue_2152() { - match m { - "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" if true => {} - "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => true, - } -} diff --git a/tests/source/max-line-length-in-chars.rs b/tests/source/max-line-length-in-chars.rs deleted file mode 100644 index d49fbb7e30e..00000000000 --- a/tests/source/max-line-length-in-chars.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-max_width: 25 - -// абвгдеёжзийклмнопрст -fn main() {} diff --git a/tests/source/mod-1.rs b/tests/source/mod-1.rs deleted file mode 100644 index 427a355b6be..00000000000 --- a/tests/source/mod-1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Deeply indented modules. - - mod foo { mod bar { mod baz {} } } - -mod foo { - mod bar { - mod baz { - fn foo() { bar() } - } - } - - mod qux { - - } -} - -mod boxed { pub use std::boxed::{Box, HEAP}; } - -pub mod x { - pub fn freopen(filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE) - -> *mut FILE{} -} - - mod y { // sup boooooiiii - } diff --git a/tests/source/mod-2.rs b/tests/source/mod-2.rs deleted file mode 100644 index 7202e00203e..00000000000 --- a/tests/source/mod-2.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Some nested mods - -#[cfg(test)] mod nestedmod ; -pub mod no_new_line_beginning; diff --git a/tests/source/mod_skip_child.rs b/tests/source/mod_skip_child.rs deleted file mode 100644 index d48c4a37e81..00000000000 --- a/tests/source/mod_skip_child.rs +++ /dev/null @@ -1,2 +0,0 @@ -// rustfmt-skip_children: true -mod nested_skipped; diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs deleted file mode 100644 index 68cfacfcb4b..00000000000 --- a/tests/source/multiple.rs +++ /dev/null @@ -1,134 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-format_strings: true -// Test of lots of random stuff. -// FIXME split this into multiple, self-contained tests. - - -#[attr1] extern crate foo; -#[attr2] #[attr3] extern crate foo; -#[attr1]extern crate foo; -#[attr2]#[attr3]extern crate foo; - -use std::cell::*; -use std::{any, ascii, self, borrow, boxed, char, borrow, boxed, char, borrow, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char}; - -mod doc; -mod other; - - -// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff - - fn foo(a: isize, - b: u32, /* blah blah */ - c: f64) { - -} - -fn foo()->Box where 'a: 'b, for<'a> D<'b>: 'a { - hello!() -} - -fn baz<'a: 'b /* comment on 'a */, T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */>(a: A, b: B /* comment on b */, c: C) -> Bob { - #[attr1] extern crate foo; - #[attr2] #[attr3] extern crate foo; - #[attr1]extern crate foo; - #[attr2]#[attr3]extern crate foo; -} - -#[rustfmt_skip] -fn qux(a: dadsfa, // Comment 1 - b: sdfasdfa, // Comment 2 - c: dsfdsafa) // Comment 3 -{ - -} - -/// Blah blah blah. -impl Bar { - fn foo(&mut self, a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a - b: sdfasdfsdfasfs /*closing comment*/ ) -> isize {} - - /// Blah blah blah. - pub fn f2(self) { - (foo, bar) - } - - #[an_attribute] - fn f3(self) -> Dog { - } -} - -/// The `nodes` and `edges` method each return instantiations of -/// `Cow<[T]>` to leave implementers the freedom to create - -/// entirely new vectors or to pass back slices into internally owned -/// vectors. -pub trait GraphWalk<'a, N, E> { - /// Returns all the nodes in this graph. - fn nodes(&'a self) -> Nodes<'a, N>; - /// Returns all of the edges in this graph. - fn edges(&'a self) -> Edges<'a, E>; - /// The source node for `edge`. - fn source(&'a self, edge: &E) -> N; - /// The target node for `edge`. - fn target(&'a self, edge: &E) -> N; -} - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f : SomeType, // Comment beside a field - // Comment on a field - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType,} - -struct Bar; - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -fn foo(ann: &'a (PpAnn+'a)) {} - -fn main() { - for i in 0i32..4 { - println!("{}", i); - } - - - while true { - hello(); - } - - let rc = Cell::new(42usize,42usize, Cell::new(42usize, remaining_widthremaining_widthremaining_widthremaining_width), 42usize); - let rc = RefCell::new(42usize,remaining_width, remaining_width); // a comment - let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; - let s = expand(a - , - b); } - -fn deconstruct() -> (SocketAddr, Method, Headers, - RequestUri, HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { -} - -fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, - RequestUri, HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { -} - -#[rustfmt_skip] -mod a{ -fn foo(x: T) { - let x: T = dfasdf; -} -} diff --git a/tests/source/nested-if-else.rs b/tests/source/nested-if-else.rs deleted file mode 100644 index 9a54789ddcd..00000000000 --- a/tests/source/nested-if-else.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn issue1518() { - Some(Object { - field: if a { - a_thing - } else if b { - b_thing - } else { - c_thing - }, - }) -} diff --git a/tests/source/nested_skipped/mod.rs b/tests/source/nested_skipped/mod.rs deleted file mode 100644 index 44b25ca8797..00000000000 --- a/tests/source/nested_skipped/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn ugly() { -92; -} diff --git a/tests/source/nestedmod/mod.rs b/tests/source/nestedmod/mod.rs deleted file mode 100644 index d04e49570a4..00000000000 --- a/tests/source/nestedmod/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ - -mod mod2a; -mod mod2b; - -mod mymod1 { - use mod2a::{Foo,Bar}; -mod mod3a; -} - -#[path="mod2c.rs"] -mod mymod2; - -mod submod2; diff --git a/tests/source/nestedmod/mod2a.rs b/tests/source/nestedmod/mod2a.rs deleted file mode 100644 index 5df457a8316..00000000000 --- a/tests/source/nestedmod/mod2a.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This is an empty file containing only -// comments - -// ................... diff --git a/tests/source/nestedmod/mod2b.rs b/tests/source/nestedmod/mod2b.rs deleted file mode 100644 index f128e2da6db..00000000000 --- a/tests/source/nestedmod/mod2b.rs +++ /dev/null @@ -1,3 +0,0 @@ - -#[path="mod2a.rs"] -mod c; diff --git a/tests/source/nestedmod/mod2c.rs b/tests/source/nestedmod/mod2c.rs deleted file mode 100644 index eda6b233e4b..00000000000 --- a/tests/source/nestedmod/mod2c.rs +++ /dev/null @@ -1,3 +0,0 @@ -// A standard mod - -fn a( ) {} diff --git a/tests/source/nestedmod/mymod1/mod3a.rs b/tests/source/nestedmod/mymod1/mod3a.rs deleted file mode 100644 index f28bde5e56d..00000000000 --- a/tests/source/nestedmod/mymod1/mod3a.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Another mod -fn a( ) { } diff --git a/tests/source/nestedmod/submod2/a.rs b/tests/source/nestedmod/submod2/a.rs deleted file mode 100644 index 0eaf08f0d2c..00000000000 --- a/tests/source/nestedmod/submod2/a.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Yet Another mod -// Nested - -use c::a; - -fn foo( ) { } diff --git a/tests/source/nestedmod/submod2/mod.rs b/tests/source/nestedmod/submod2/mod.rs deleted file mode 100644 index 52f8be91022..00000000000 --- a/tests/source/nestedmod/submod2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Another mod - -mod a; - -use a::a; diff --git a/tests/source/no_new_line_beginning.rs b/tests/source/no_new_line_beginning.rs deleted file mode 100644 index f79c691f085..00000000000 --- a/tests/source/no_new_line_beginning.rs +++ /dev/null @@ -1,2 +0,0 @@ -fn main() { -} diff --git a/tests/source/other.rs b/tests/source/other.rs deleted file mode 100644 index dfce84fcdc4..00000000000 --- a/tests/source/other.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Part of multiple.rs - -fn bob() { - println!("hello other!"); -} diff --git a/tests/source/paths.rs b/tests/source/paths.rs deleted file mode 100644 index ebc26f146e4..00000000000 --- a/tests/source/paths.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - let constellation_chan = Constellation:: ::start( - compositor_proxy, - resource_task, - image_cache_task,font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard - ); - - Quux::::some_func(); - - < *mut JSObject >:: relocate(entry); - - let x: Foo; - let x: Foo/*::*/; -} - -fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/source/pattern-condense-wildcards.rs b/tests/source/pattern-condense-wildcards.rs deleted file mode 100644 index 244e935639a..00000000000 --- a/tests/source/pattern-condense-wildcards.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-condense_wildcard_suffixes: true - -fn main() { - match x { - Butt (_,_) => "hah", - Tup (_) => "nah", - Quad (_,_, x,_) => " also no rewrite", - Quad (x, _, _, _) => "condense me pls", - Weird (x, _, _, /* dont condense before */ _, _, _) => "pls work", - } -} diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs deleted file mode 100644 index 7c052c87bc4..00000000000 --- a/tests/source/pattern.rs +++ /dev/null @@ -1,65 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - let z = match x { - "pat1" => 1, - ( ref x, ref mut y /*comment*/) => 2, - }; - - if let < T as Trait > :: CONST = ident { - do_smth(); - } - - let Some ( ref xyz /* comment! */) = opt; - - if let None = opt2 { panic!("oh noes"); } - - let foo@bar (f) = 42; - let a::foo ( ..) = 42; - let [ ] = 42; - let [a.., b,c ] = 42; - let [ a,b,c.. ] = 42; - let [a, b, c, d..,e,f, g] = 42; - let foo { } = 42; - let foo {..} = 42; - let foo { x, y: ref foo, .. } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; -} - -impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { - fn mutate_fragment(&mut self, fragment: &mut Fragment) { - match **info { - GeneratedContentInfo::ContentItem( - ContentItem::Counter( - ref counter_name, - counter_style - ) - ) => {}}} -} - -fn issue_1319() { - if let (Event { .. }, .. ) = ev_state {} -} - -fn issue_1874() { - if let Some(()) = x { -y - } -} - -fn combine_patterns() { - let x = match y { - Some( - Some( - Foo { - z: Bar(..), - a: Bar(..), - b: Bar(..), - }, - ), - ) => z, - _ => return, - }; -} diff --git a/tests/source/pub-restricted.rs b/tests/source/pub-restricted.rs deleted file mode 100644 index 30051fa72ee..00000000000 --- a/tests/source/pub-restricted.rs +++ /dev/null @@ -1,64 +0,0 @@ -pub( super ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub( crate ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - - crate enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(in ::global:: path :: to::some_mod ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub( in local:: path :: to::some_mod ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} diff --git a/tests/source/remove_blank_lines.rs b/tests/source/remove_blank_lines.rs deleted file mode 100644 index 7466e21eed8..00000000000 --- a/tests/source/remove_blank_lines.rs +++ /dev/null @@ -1,44 +0,0 @@ -fn main() { - - - - - let x = 1; - - - let y = 2; - - - println!("x + y = {}", x + y); - - - -} - - -fn foo() { - - #![attribute] - - let x = 1; - - // comment - - -} -// comment after item - - -// comment before item -fn bar() { - let x = 1; - // comment after statement - - - // comment before statment - let y = 2; - let z = 3; - - - println!("x + y + z = {}", x + y + z); -} diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs deleted file mode 100644 index bcde390d116..00000000000 --- a/tests/source/single-line-if-else.rs +++ /dev/null @@ -1,49 +0,0 @@ - -// Format if-else expressions on a single line, when possible. - -fn main() { - let a = if 1 > 2 { - unreachable!() - } else { - 10 - }; - - let a = if x { 1 } else if y { 2 } else { 3 }; - - let b = if cond() { - 5 - } else { - // Brief comment. - 10 - }; - - let c = if cond() { - statement(); - - 5 - } else { - 10 - }; - - let d = if let Some(val) = turbo - { "cool" } else { - "beans" }; - - if cond() { statement(); } else { other_statement(); } - - if true { - do_something() - } - - let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; - - let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { - bbbbbbbbbb }; - - funk(if test() { - 1 - } else { - 2 - }, - arg2); -} diff --git a/tests/source/soft-wrapping.rs b/tests/source/soft-wrapping.rs deleted file mode 100644 index ace8359409c..00000000000 --- a/tests/source/soft-wrapping.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 80 -// Soft wrapping for comments. - -// #535, soft wrapping for comments -// Compare the lowest `f32` of both inputs for greater than or equal. The -// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off -// the result are the upper 96 bits of `a`. - -/// Compare the lowest `f32` of both inputs for greater than or equal. The -/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off -/// the result are the upper 96 bits of `a`. -fn foo() {} diff --git a/tests/source/space-not-before-newline.rs b/tests/source/space-not-before-newline.rs deleted file mode 100644 index 2a1e1856908..00000000000 --- a/tests/source/space-not-before-newline.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo { - a: (), - // spaces ^^^ to be removed -} -enum Foo { - Bar, - // spaces ^^^ to be removed -} diff --git a/tests/source/spaces-around-ranges.rs b/tests/source/spaces-around-ranges.rs deleted file mode 100644 index 1936b5e161f..00000000000 --- a/tests/source/spaces-around-ranges.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-spaces_around_ranges: true - -fn bar(v: &[u8]) {} - -fn foo() { - let a = vec![0; 20]; - for j in 0..=20 { - for i in 0..3 { - bar(a[i..j]); - bar(a[i..]); - bar(a[..j]); - bar(a[..=(j + 1)]); - } - } -} diff --git a/tests/source/static.rs b/tests/source/static.rs deleted file mode 100644 index 970786381cc..00000000000 --- a/tests/source/static.rs +++ /dev/null @@ -1,23 +0,0 @@ -const FILE_GENERIC_READ: DWORD = - STANDARD_RIGHTS_READ | FILE_READ_DATA | - FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; - -static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", - "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", - "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", - "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; - -static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; - - pub static count : u8 = 10 ; - -pub const test: &Type = &val; - -impl Color { - pub const WHITE: u32 = 10; -} - -// #1391 -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; - -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/tests/source/string-lit-2.rs b/tests/source/string-lit-2.rs deleted file mode 100644 index 6b95e25a052..00000000000 --- a/tests/source/string-lit-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn main() -> &'static str { - let too_many_lines = "Hello"; - let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ - s - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; -} - -fn issue_1237() { - let msg = "eedadn\n\ - drvtee\n\ - eandsr\n\ - raavrd\n\ - atevrs\n\ - tsrnev\n\ - sdttsa\n\ - rasrtv\n\ - nssdts\n\ - ntnada\n\ - svetve\n\ - tesnvt\n\ - vntsnd\n\ - vrdear\n\ - dvrsen\n\ - enarar"; -} diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs deleted file mode 100644 index e86f65f9f52..00000000000 --- a/tests/source/string-lit.rs +++ /dev/null @@ -1,62 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false -// Long string literals - -fn main() -> &'static str { - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let too_many_lines = "H\ - e\ - l\ - l\ - o"; - - // Make sure we don't break after an escape character. - let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - - let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let raw_string = r#"Do -not -remove -formatting"#; - - filename.replace(" ", "\\" ); - - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = - funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); - - let unicode = "a̐éö̲\r\n"; - let unicode2 = "Löwe 老虎 Léopard"; - let unicode3 = "中华Việt Nam"; - let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; - - "stuffin'" -} - -fn issue682() { - let a = "hello \\ o/"; - let b = a.replace("\\ ", "\\"); -} - -fn issue716() { - println!("forall x. mult(e(), x) = x /\\ - forall x. mult(x, x) = e()"); -} - -fn issue_1282() { - { - match foo { - Permission::AndroidPermissionAccessLocationExtraCommands => { - "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" - } - } - } -} - -// #1987 -#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] -extern "C" {} diff --git a/tests/source/string_punctuation.rs b/tests/source/string_punctuation.rs deleted file mode 100644 index 6a0afd45e5a..00000000000 --- a/tests/source/string_punctuation.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false - -fn main() { - println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); - format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); - println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); -} diff --git a/tests/source/struct-field-attributes.rs b/tests/source/struct-field-attributes.rs deleted file mode 100644 index 76d6eda8853..00000000000 --- a/tests/source/struct-field-attributes.rs +++ /dev/null @@ -1,52 +0,0 @@ -// #1535 -#![feature(struct_field_attributes)] - -struct Foo { - bar: u64, - - #[cfg(test)] - qux: u64, -} - -fn do_something() -> Foo { - Foo { - bar: 0, - - #[cfg(test)] - qux: 1, - } -} - -fn main() { - do_something(); -} - -// #1462 -struct Foo { - foo: usize, - #[cfg(feature="include-bar")] - bar: usize, -} - -fn new_foo() -> Foo { - Foo { - foo: 0, - #[cfg(feature="include-bar")] - bar: 0, - } -} - -// #2044 -pub enum State { - Closure(#[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] GcPtr), -} - -struct Fields( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] Arc>, -); - -// #2309 -pub struct A { -#[doc="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] -pub foos:Vec -} diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs deleted file mode 100644 index 3a8016367b6..00000000000 --- a/tests/source/struct_lits.rs +++ /dev/null @@ -1,144 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:f() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { memb: T } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S{a:0, .. b}; -} - -fn issue201_2() { - let s = S{a: S2{ .. c}, .. b}; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo - { a : 1, b:f( 2)}; - Foo{a:1,b:f(2),..g(3)}; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; - IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { a: bb, c: dd, e: ff }; - - Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ - e: eeeeeeeee }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, .. base }; - Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ - eeeeeeeee }; - Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; -} diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs deleted file mode 100644 index 256ba1bbda3..00000000000 --- a/tests/source/struct_lits_multiline.rs +++ /dev/null @@ -1,81 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-struct_lit_single_line: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:foo() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { memb: T } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S{a:0, .. b}; -} - -fn issue201_2() { - let s = S{a: S2{ .. c}, .. b}; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; -} diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs deleted file mode 100644 index 2c6cc674960..00000000000 --- a/tests/source/struct_lits_visual.rs +++ /dev/null @@ -1,47 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:f() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, z: zzzzz // test - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs deleted file mode 100644 index d0b5ea6efba..00000000000 --- a/tests/source/struct_lits_visual_multiline.rs +++ /dev/null @@ -1,45 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-struct_lit_single_line: false -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:foo() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} diff --git a/tests/source/struct_tuple_visual.rs b/tests/source/struct_tuple_visual.rs deleted file mode 100644 index 369feae71d2..00000000000 --- a/tests/source/struct_tuple_visual.rs +++ /dev/null @@ -1,37 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual -fn foo() { - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment - foo(), /* Comment */ - // Comment - bar() /* Comment */); - - Foo(Bar, f()); - - Quux(if cond { - bar(); - }, - baz()); - - Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - zzzzz /* test */); - - A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - Item); - - Diagram(// o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - G) -} diff --git a/tests/source/structs.rs b/tests/source/structs.rs deleted file mode 100644 index 25070aef34c..00000000000 --- a/tests/source/structs.rs +++ /dev/null @@ -1,283 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - - /// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField -} - -// #1095 -struct S { - t: T, -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] //only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct -NewInt (pub i32, SomeType /* inline comment */, T /* sup */ - - - ); - -struct Qux<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy> -( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C - -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - - - - c: C, // Comment C -} - -struct Baz { - - a: A, - - b: B, - c: C, - - - - - d: D - -} - -struct Baz -{ - // Comment A - a: A, - - // Comment B -b: B, - // Comment C - c: C,} - -// Will this be a one-liner? -struct Tuple( - A, //Comment - B -); - -pub struct State time::Timespec> { now: F } - -pub struct State ()> { now: F } - -pub struct State { now: F } - -struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color - foo: i32} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB - //Another pre comment - #[attr1] - #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(T); -struct Foo(T) where T: Copy, T: Eq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU); - -mod m { - struct X where T: Sized { - a: T, - } -} - -struct Foo(TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn( obj: - *const libc::c_void, tracer : *mut JSTracer ), -} - -struct Foo {} -struct Foo { - } -struct Foo { - // comment - } -struct Foo { - // trailing space -> - - - } -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -struct Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} - -// structs with long identifier -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { x: i32 } - -// structs with visibility, do not duplicate visibility (#2110). -pub(in self) struct Foo{} -pub(super) struct Foo{} -pub(crate) struct Foo{} -pub(in self) struct Foo(); -pub(super) struct Foo(); -pub(crate) struct Foo(); - -// #2125 -pub struct ReadinessCheckRegistry(Mutex, Box ReadinessCheck + Sync + Send>>>); - -// #2144 unit struct with generics -struct MyBox; -struct MyBoxx where T: ?Sized, S: Clone; - -// #2208 -struct Test { - /// foo - #[serde(default)] - pub join: Vec, - #[serde(default)] pub tls: bool, -} diff --git a/tests/source/trailing-comma-never.rs b/tests/source/trailing-comma-never.rs deleted file mode 100644 index 5985b514724..00000000000 --- a/tests/source/trailing-comma-never.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-trailing_comma: Never - -enum X { - A, - B, -} - -enum Y { - A, - B -} - -enum TupX { - A(u32), - B(i32, u16), -} - -enum TupY { - A(u32), - B(i32, u16) -} - -enum StructX { - A { - s: u16, - }, - B { - u: u32, - i: i32, - }, -} - -enum StructY { - A { - s: u16, - }, - B { - u: u32, - i: i32, - } -} diff --git a/tests/source/trailing_commas.rs b/tests/source/trailing_commas.rs deleted file mode 100644 index 3e5fcc8080f..00000000000 --- a/tests/source/trailing_commas.rs +++ /dev/null @@ -1,47 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// rustfmt-trailing_comma: Always - -fn main() { - match foo { - x => {} - y => { - foo(); - } - _ => x - } -} - -fn f(x: T, y: S) -> T where T: P, S: Q -{ - x -} - -impl Trait for T where T: P -{ - fn f(x: T) -> T where T: Q + R - { - x - } -} - -struct Pair where T: P, S: P + Q { - a: T, - b: S -} - -struct TupPair (S, T) where T: P, S: P + Q; - -enum E where S: P, T: P { - A {a: T}, -} - -type Double where T: P, T: Q = Pair; - -extern "C" { - fn f(x: T, y: S) -> T where T: P, S: Q; -} - -trait Q where T: P, S: R -{ - fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; -} diff --git a/tests/source/trait.rs b/tests/source/trait.rs deleted file mode 100644 index e8de36db35e..00000000000 --- a/tests/source/trait.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Test traits - -trait Foo { - fn bar(x: i32 ) -> Baz< U> { Baz::new() - } - - fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, -b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) --> RetType; - - fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment -b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) - -> RetType ; // Some comment - - fn baz(&mut self ) -> i32 ; - -fn increment(& mut self, x: i32 ); - - fn read(&mut self, x: BufReader /* Used to be MemReader */) - where R: Read; -} - -pub trait WriteMessage { - fn write_message (&mut self, &FrontendMessage) -> io::Result<()>; -} - -trait Runnable { - fn handler(self: & Runnable ); -} - -trait TraitWithExpr { - fn fn_with_expr(x: [i32; 1]); -} - -trait Test { - fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; -} - -trait T<> {} - -trait Foo { type Bar: Baz; type Inner: Foo = Box< Foo >; } - -trait ConstCheck:Foo where T: Baz { - const J: i32; -} - -trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt - where T: Foo {} - -trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} - -trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } - -trait WhereList where T: Foo, J: Bar {} - -trait X /* comment */ {} -trait Y // comment -{ -} - -// #2055 -pub trait Foo: -// A and C -A + C -// and B - + B -{} - -// #2158 -trait Foo { - type ItRev = > as UntypedTimeSeries>::IterRev; - type IteRev = > as UntypedTimeSeries>::IterRev; -} - -// #2331 -trait MyTrait { - fn foo() {} -} - -// Trait aliases -trait FooBar = - Foo - + Bar; -trait FooBar = - Foo - + Bar; -trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; -#[rustfmt_skip] -trait FooBar = Foo - + Bar; diff --git a/tests/source/try-conversion.rs b/tests/source/try-conversion.rs deleted file mode 100644 index ed83ee9e101..00000000000 --- a/tests/source/try-conversion.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-use_try_shorthand: true - -fn main() { - let x = try!(some_expr()); - - let y = try!(a.very.loooooooooooooooooooooooooooooooooooooong().chain().inside().weeeeeeeeeeeeeee()).test().0.x; -} - -fn test() { - a? -} - -fn issue1291() { - try!(fs::create_dir_all(&gitfiledir).chain_err(|| { - format!("failed to create the {} submodule directory for the workarea", - name) - })); -} diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs deleted file mode 100644 index 6c3ec8f1115..00000000000 --- a/tests/source/tuple.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Test tuple litterals - -fn foo() { - let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); - let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaa, - aaaa); - let a = (a,); - - let b = (// This is a comment - b, // Comment - b /* Trailing comment */); - - // #1063 - foo(x.0 .0); -} - -fn a() { - ((aaaaaaaa, - aaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa),) -} - -fn b() { - ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - bbbbbbbbbbbbbbbbbb) -} - -fn issue550() { - self.visitor.visit_volume(self.level.sector_id(sector), (floor_y, - if is_sky_flat(ceil_tex) {from_wad_height(self.height_range.1)} else {ceil_y})); -} - -fn issue775() { - if indent { - let a = mk_object(&[("a".to_string(), Boolean(true)), - ("b".to_string(), - Array(vec![mk_object(&[("c".to_string(), - String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), String("".to_string()))])]))]); - } -} - -fn issue1725() { - bench_antialiased_lines!(bench_draw_antialiased_line_segment_diagonal, (10, 10), (450, 450)); - bench_antialiased_lines!(bench_draw_antialiased_line_segment_shallow, (10, 10), (450, 80)); -} diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs deleted file mode 100644 index 3b761f4fc78..00000000000 --- a/tests/source/type-ascription.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; - - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - x : u32 - 1u32 / 10f32 : u32 -} diff --git a/tests/source/type-punctuation.rs b/tests/source/type-punctuation.rs deleted file mode 100644 index 0980e4a3732..00000000000 --- a/tests/source/type-punctuation.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed - -struct Foo - where U: Eq + Clone { - // body -} - -trait Foo<'a, T = usize> - where T: 'a + Eq + Clone -{ - type Bar: Eq + Clone; -} - -trait Foo: Eq + Clone { - // body -} - -impl Foo<'a> for Bar - where for<'a> T: 'a + Eq + Clone -{ - // body -} - -fn foo<'a, 'b, 'c>() - where 'a: 'b + 'c -{ - // body -} - -fn Foo + Foo>() { - let i = 6; -} diff --git a/tests/source/type.rs b/tests/source/type.rs deleted file mode 100644 index 0a46ffb2ee4..00000000000 --- a/tests/source/type.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-normalize_comments: true -fn types() { - let x: [ Vec < _ > ] = []; - let y: * mut [ SomeType ; konst_funk() ] = expr(); - let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); - let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk(); -} - -struct F { - f: extern "C" fn(x: u8, ... /* comment */), - g: extern "C" fn(x: u8,/* comment */ ...), - h: extern "C" fn(x: u8, ... ), - i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3 - z: Foo, /* comment */ .../* comment 2*/ ), -} - -fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} - -fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} - -fn impl_trait_fn_2() -> impl Future {} - -fn issue_1234() { - do_parse!(name: take_while1!(is_token) >> (Header)) -} diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs deleted file mode 100644 index 58c807f4029..00000000000 --- a/tests/source/type_alias.rs +++ /dev/null @@ -1,34 +0,0 @@ -// rustfmt-normalize_comments: true - -type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); - -pub type PublicTest<'a, I, O> = Result, Box + 'a>, Box + 'a>>; - -pub type LongGenericListTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Option>; - -pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; - -pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; - -pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; - -pub type GenericsFitButNotEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A1, B, C> = Vec; - -pub type CommentTest< /* Lifetime */ 'a - , - // Type - T - > = (); - - -pub type WithWhereClause where T: Clone, LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; - -pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; - -pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; - -type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); - -// #1683 -pub type Between = super::operators::Between, AsExpr>>; -pub type NotBetween = super::operators::NotBetween, AsExpr>>; diff --git a/tests/source/unions.rs b/tests/source/unions.rs deleted file mode 100644 index fc2908e2d9e..00000000000 --- a/tests/source/unions.rs +++ /dev/null @@ -1,195 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - - /// A Doc comment -#[AnAttribute] -pub union Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField -} - -// #1029 -pub union Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -union X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub union Writebatch { - #[allow(dead_code)] //only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -// With a where clause and generics. -pub union Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -union Baz { - - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C - -} - -union Baz { - a: A, // Comment A - - b: B, // Comment B - - - - - c: C, // Comment C -} - -union Baz { - - a: A, - - b: B, - c: C, - - - - - d: D - -} - -union Baz -{ - // Comment A - a: A, - - // Comment B -b: B, - // Comment C - c: C,} - -pub union State time::Timespec> { now: F } - -pub union State ()> { now: F } - -pub union State { now: F } - -union Palette { /// A map of indices in the palette to a count of pixels in approximately that color - foo: i32} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -union FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB - //Another pre comment - #[attr1] - #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -mod m { - union X where T: Sized { - a: T, - } -} - -union Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn( obj: - *const libc::c_void, tracer : *mut JSTracer ), -} - -union Foo {} -union Foo { - } -union Foo { - // comment - } -union Foo { - // trailing space -> - - - } -union Foo { /* comment */ } - -union LongUnion { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -union Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs deleted file mode 100644 index e41e9a6cea1..00000000000 --- a/tests/source/where-clause-rfc.rs +++ /dev/null @@ -1,58 +0,0 @@ -// rustfmt-indent_style: Block - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { - let mut effects = HashMap::new(); -} - -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; - - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; - -struct Exactly100CharsToSemicolon - (LongLongTypename, i32, i32) - where A: LongTrait1234; - -struct AlwaysOnNextLine where A: LongTrait { - x: i32 -} - -pub trait SomeTrait - where - T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr -{ -} - -// #2020 -impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { - fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) - where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssociatedItem), - { - // ... - } -} diff --git a/tests/source/where-clause.rs b/tests/source/where-clause.rs deleted file mode 100644 index 9e4a2f65698..00000000000 --- a/tests/source/where-clause.rs +++ /dev/null @@ -1,16 +0,0 @@ -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; - -struct Exactly100CharsToSemicolon - (LongLongTypename, i32, i32) - where A: LongTrait1234; - -struct AlwaysOnNextLine where A: LongTrait { - x: i32 -} diff --git a/tests/system.rs b/tests/system.rs deleted file mode 100644 index 06bfa1418d1..00000000000 --- a/tests/system.rs +++ /dev/null @@ -1,801 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(rustc_private)] - -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; -extern crate regex; -extern crate rustfmt_nightly as rustfmt; -extern crate term; - -use std::collections::HashMap; -use std::fs; -use std::io::{self, BufRead, BufReader, Read}; -use std::iter::{Enumerate, Peekable}; -use std::path::{Path, PathBuf}; -use std::str::Chars; - -use rustfmt::*; -use rustfmt::config::{Color, Config, ReportTactic}; -use rustfmt::filemap::{write_system_newlines, FileMap}; -use rustfmt::rustfmt_diff::*; - -const DIFF_CONTEXT_SIZE: usize = 3; -const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; - -// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the -// given path. The `recursive` argument controls if files from subdirectories -// are also returned. -fn get_test_files(path: &Path, recursive: bool) -> Vec { - let mut files = vec![]; - if path.is_dir() { - for entry in fs::read_dir(path).expect(&format!( - "Couldn't read directory {}", - path.to_str().unwrap() - )) { - let entry = entry.expect("Couldn't get DirEntry"); - let path = entry.path(); - if path.is_dir() && recursive { - files.append(&mut get_test_files(&path, recursive)); - } else if path.extension().map_or(false, |f| f == "rs") { - files.push(path); - } - } - } - files -} - -fn verify_config_used(path: &Path, config_name: &str) { - for entry in fs::read_dir(path).expect(&format!( - "Couldn't read {} directory", - path.to_str().unwrap() - )) { - let entry = entry.expect("Couldn't get directory entry"); - let path = entry.path(); - if path.extension().map_or(false, |f| f == "rs") { - // check if "// rustfmt-:" appears in the file. - let filebuf = BufReader::new( - fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), - ); - assert!( - filebuf - .lines() - .map(|l| l.unwrap()) - .take_while(|l| l.starts_with("//")) - .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), - format!( - "config option file {} does not contain expected config name", - path.display() - ) - ); - } - } -} - -#[test] -fn verify_config_test_names() { - for path in &[ - Path::new("tests/source/configs"), - Path::new("tests/target/configs"), - ] { - for entry in fs::read_dir(path).expect("Couldn't read configs directory") { - let entry = entry.expect("Couldn't get directory entry"); - let path = entry.path(); - if path.is_dir() { - let config_name = path.file_name().unwrap().to_str().unwrap(); - - // Make sure that config name is used in the files in the directory. - verify_config_used(&path, config_name); - } - } - } -} - -// This writes to the terminal using the same approach (via term::stdout or -// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing -// using only one or the other will cause the output order to differ when -// `print_diff` selects the approach not used. -fn write_message(msg: &str) { - let mut writer = OutputWriter::new(Color::Auto); - writer.writeln(&format!("{}", msg), None); -} - -// Integration tests. The files in the tests/source are formatted and compared -// to their equivalent in tests/target. The target file and config can be -// overridden by annotations in the source file. The input and output must match -// exactly. -#[test] -fn system_tests() { - // Get all files in the tests/source directory. - let files = get_test_files(Path::new("tests/source"), true); - let (_reports, count, fails) = check_files(files); - - // Display results. - println!("Ran {} system tests.", count); - assert_eq!(fails, 0, "{} system tests failed", fails); -} - -// Do the same for tests/coverage-source directory -// the only difference is the coverage mode -#[test] -fn coverage_tests() { - let files = get_test_files(Path::new("tests/coverage/source"), true); - let (_reports, count, fails) = check_files(files); - - println!("Ran {} tests in coverage mode.", count); - assert_eq!(fails, 0, "{} tests failed", fails); -} - -#[test] -fn checkstyle_test() { - let filename = "tests/writemode/source/fn-single-line.rs"; - let expected_filename = "tests/writemode/target/checkstyle.xml"; - assert_output(Path::new(filename), Path::new(expected_filename)); -} - -// Helper function for comparing the results of rustfmt -// to a known output file generated by one of the write modes. -fn assert_output(source: &Path, expected_filename: &Path) { - let config = read_config(source); - let (_error_summary, file_map, _report) = format_file(source, &config); - - // Populate output by writing to a vec. - let mut out = vec![]; - let _ = filemap::write_all_files(&file_map, &mut out, &config); - let output = String::from_utf8(out).unwrap(); - - let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); - let mut expected_text = String::new(); - expected_file - .read_to_string(&mut expected_text) - .expect("Failed reading target"); - - let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - let mut failures = HashMap::new(); - failures.insert(source.to_owned(), compare); - print_mismatches_default_message(failures); - assert!(false, "Text does not match expected output"); - } -} - -// Idempotence tests. Files in tests/target are checked to be unaltered by -// rustfmt. -#[test] -fn idempotence_tests() { - // Get all files in the tests/target directory. - let files = get_test_files(Path::new("tests/target"), true); - let (_reports, count, fails) = check_files(files); - - // Display results. - println!("Ran {} idempotent tests.", count); - assert_eq!(fails, 0, "{} idempotent tests failed", fails); -} - -// Run rustfmt on itself. This operation must be idempotent. We also check that -// no warnings are emitted. -#[test] -fn self_tests() { - let mut files = get_test_files(Path::new("src/bin"), false); - files.append(&mut get_test_files(Path::new("tests"), false)); - files.push(PathBuf::from("src/lib.rs")); - files.push(PathBuf::from("build.rs")); - - let (reports, count, fails) = check_files(files); - let mut warnings = 0; - - // Display results. - println!("Ran {} self tests.", count); - assert_eq!(fails, 0, "{} self tests failed", fails); - - for format_report in reports { - println!("{}", format_report); - warnings += format_report.warning_count(); - } - - assert_eq!( - warnings, 0, - "Rustfmt's code generated {} warnings", - warnings - ); -} - -#[test] -fn stdin_formatting_smoke_test() { - let input = Input::Text("fn main () {}".to_owned()); - let config = Config::default(); - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_no_errors()); - for &(ref file_name, ref text) in &file_map { - if let FileName::Custom(ref file_name) = *file_name { - if file_name == "stdin" { - assert_eq!(text.to_string(), "fn main() {}\n"); - return; - } - } - } - panic!("no stdin"); -} - -// FIXME(#1990) restore this test -// #[test] -// fn stdin_disable_all_formatting_test() { -// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); -// let mut child = Command::new("./target/debug/rustfmt") -// .stdin(Stdio::piped()) -// .stdout(Stdio::piped()) -// .arg("--config-path=./tests/config/disable_all_formatting.toml") -// .spawn() -// .expect("failed to execute child"); - -// { -// let stdin = child.stdin.as_mut().expect("failed to get stdin"); -// stdin -// .write_all(input.as_bytes()) -// .expect("failed to write stdin"); -// } -// let output = child.wait_with_output().expect("failed to wait on child"); -// assert!(output.status.success()); -// assert!(output.stderr.is_empty()); -// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); -// } - -#[test] -fn format_lines_errors_are_reported() { - let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); - let input = Input::Text(format!("fn {}() {{}}", long_identifier)); - let config = Config::default(); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); -} - -#[test] -fn format_lines_errors_are_reported_with_tabs() { - let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); - let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); - let config = Config::from_toml("hard_tabs = true").unwrap(); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); -} - -// For each file, run rustfmt and collect the output. -// Returns the number of files checked and the number of failures. -fn check_files(files: Vec) -> (Vec, u32, u32) { - let mut count = 0; - let mut fails = 0; - let mut reports = vec![]; - - for file_name in files { - debug!("Testing '{}'...", file_name.display()); - - match idempotent_check(&file_name) { - Ok(ref report) if report.has_warnings() => { - print!("{}", report); - fails += 1; - } - Ok(report) => reports.push(report), - Err(err) => { - if let IdempotentCheckError::Mismatch(msg) = err { - print_mismatches_default_message(msg); - } - fails += 1; - } - } - - count += 1; - } - - (reports, count, fails) -} - -fn print_mismatches_default_message(result: HashMap>) { - let mut t = term::stdout().unwrap(); - for (file_name, diff) in result { - let mismatch_msg_formatter = - |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); - print_diff(diff, &mismatch_msg_formatter, Color::Auto); - } - - t.reset().unwrap(); -} - -fn print_mismatches String>( - result: HashMap>, - mismatch_msg_formatter: T, -) { - let mut t = term::stdout().unwrap(); - for (_file_name, diff) in result { - print_diff(diff, &mismatch_msg_formatter, Color::Auto); - } - - t.reset().unwrap(); -} - -fn read_config(filename: &Path) -> Config { - let sig_comments = read_significant_comments(filename); - // Look for a config file... If there is a 'config' property in the significant comments, use - // that. Otherwise, if there are no significant comments at all, look for a config file with - // the same name as the test file. - let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(Path::new)) - } else { - get_config(filename.with_extension("toml").file_name().map(Path::new)) - }; - - for (key, val) in &sig_comments { - if key != "target" && key != "config" { - config.override_value(key, val); - } - } - - // Don't generate warnings for to-do items. - config.set().report_todo(ReportTactic::Never); - - config -} - -fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { - let filepath = filepath.into(); - let input = Input::File(filepath); - format_input::(input, config, None).unwrap() -} - -pub enum IdempotentCheckError { - Mismatch(HashMap>), - Parse, -} - -pub fn idempotent_check(filename: &PathBuf) -> Result { - let sig_comments = read_significant_comments(filename); - let config = read_config(filename); - let (error_summary, file_map, format_report) = format_file(filename, &config); - if error_summary.has_parsing_errors() { - return Err(IdempotentCheckError::Parse); - } - - let mut write_result = HashMap::new(); - for &(ref filename, ref text) in &file_map { - let mut v = Vec::new(); - // Won't panic, as we're not doing any IO. - write_system_newlines(&mut v, text, &config).unwrap(); - // Won't panic, we are writing correct utf8. - let one_result = String::from_utf8(v).unwrap(); - if let FileName::Real(ref filename) = *filename { - write_result.insert(filename.to_owned(), one_result); - } - } - - let target = sig_comments.get("target").map(|x| &(*x)[..]); - - handle_result(write_result, target).map(|_| format_report) -} - -// Reads test config file using the supplied (optional) file name. If there's no file name or the -// file doesn't exist, just return the default config. Otherwise, the file must be read -// successfully. -fn get_config(config_file: Option<&Path>) -> Config { - let config_file_name = match config_file { - None => return Default::default(), - Some(file_name) => { - let mut full_path = PathBuf::from("tests/config/"); - full_path.push(file_name); - if !full_path.exists() { - return Default::default(); - }; - full_path - } - }; - - let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); - let mut def_config = String::new(); - def_config_file - .read_to_string(&mut def_config) - .expect("Couldn't read config"); - - Config::from_toml(&def_config).expect("Invalid toml") -} - -// Reads significant comments of the form: // rustfmt-key: value -// into a hash map. -fn read_significant_comments(file_name: &Path) -> HashMap { - let file = - fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); - let reader = BufReader::new(file); - let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; - let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); - - // Matches lines containing significant comments or whitespace. - let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") - .expect("Failed creating pattern 2"); - - reader - .lines() - .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(line)) - .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { - ( - capture - .get(1) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - capture - .get(2) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - ) - }) - }) - .collect() -} - -// Compare output to input. -// TODO: needs a better name, more explanation. -fn handle_result( - result: HashMap, - target: Option<&str>, -) -> Result<(), IdempotentCheckError> { - let mut failures = HashMap::new(); - - for (file_name, fmt_text) in result { - // If file is in tests/source, compare to file with same name in tests/target. - let target = get_target(&file_name, target); - let open_error = format!("Couldn't open target {:?}", &target); - let mut f = fs::File::open(&target).expect(&open_error); - - let mut text = String::new(); - let read_error = format!("Failed reading target {:?}", &target); - f.read_to_string(&mut text).expect(&read_error); - - // Ignore LF and CRLF difference for Windows. - if !string_eq_ignore_newline_repr(&fmt_text, &text) { - let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); - assert!( - !diff.is_empty(), - "Empty diff? Maybe due to a missing a newline at the end of a file?" - ); - failures.insert(file_name, diff); - } - } - - if failures.is_empty() { - Ok(()) - } else { - Err(IdempotentCheckError::Mismatch(failures)) - } -} - -// Map source file paths to their target paths. -fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { - if let Some(n) = file_name - .components() - .position(|c| c.as_os_str() == "source") - { - let mut target_file_name = PathBuf::new(); - for (i, c) in file_name.components().enumerate() { - if i == n { - target_file_name.push("target"); - } else { - target_file_name.push(c.as_os_str()); - } - } - if let Some(replace_name) = target { - target_file_name.with_file_name(replace_name) - } else { - target_file_name - } - } else { - // This is either and idempotence check or a self check - file_name.to_owned() - } -} - -#[test] -fn rustfmt_diff_make_diff_tests() { - let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 1, - lines: vec![ - DiffLine::Context("a".into()), - DiffLine::Resulting("b".into()), - DiffLine::Expected("e".into()), - DiffLine::Context("c".into()), - DiffLine::Context("d".into()), - ], - }, - ] - ); -} - -#[test] -fn rustfmt_diff_no_diff_test() { - let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); - assert_eq!(diff, vec![]); -} - -// Compare strings without distinguishing between CRLF and LF -fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { - let left = CharsIgnoreNewlineRepr(left.chars().peekable()); - let right = CharsIgnoreNewlineRepr(right.chars().peekable()); - left.eq(right) -} - -struct CharsIgnoreNewlineRepr<'a>(Peekable>); - -impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { - type Item = char; - fn next(&mut self) -> Option { - self.0.next().map(|c| { - if c == '\r' { - if *self.0.peek().unwrap_or(&'\0') == '\n' { - self.0.next(); - '\n' - } else { - '\r' - } - } else { - c - } - }) - } -} - -#[test] -fn string_eq_ignore_newline_repr_test() { - assert!(string_eq_ignore_newline_repr("", "")); - assert!(!string_eq_ignore_newline_repr("", "abc")); - assert!(!string_eq_ignore_newline_repr("abc", "")); - assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); - assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); - assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); -} - -// This enum is used to represent one of three text features in Configurations.md: a block of code -// with its starting line number, the name of a rustfmt configuration option, or the value of a -// rustfmt configuration option. -enum ConfigurationSection { - CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) - ConfigName(String), - ConfigValue(String), -} - -impl ConfigurationSection { - fn get_section>( - file: &mut Enumerate, - ) -> Option { - lazy_static! { - static ref CONFIG_NAME_REGEX: regex::Regex = regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); - static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#).expect("Failed creating configuration value pattern"); - } - - loop { - match file.next() { - Some((i, line)) => { - if line.starts_with("```rust") { - // Get the lines of the code block. - let lines: Vec = file.map(|(_i, l)| l) - .take_while(|l| !l.starts_with("```")) - .collect(); - let block = format!("{}\n", lines.join("\n")); - - // +1 to translate to one-based indexing - // +1 to get to first line of code (line after "```") - let start_line = (i + 2) as u32; - - return Some(ConfigurationSection::CodeBlock((block, start_line))); - } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); - } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); - } - } - None => return None, // reached the end of the file - } - } - } -} - -// This struct stores the information about code blocks in the configurations -// file, formats the code blocks, and prints formatting errors. -struct ConfigCodeBlock { - config_name: Option, - config_value: Option, - code_block: Option, - code_block_start: Option, -} - -impl ConfigCodeBlock { - fn new() -> ConfigCodeBlock { - ConfigCodeBlock { - config_name: None, - config_value: None, - code_block: None, - code_block_start: None, - } - } - - fn set_config_name(&mut self, name: Option) { - self.config_name = name; - self.config_value = None; - } - - fn set_config_value(&mut self, value: Option) { - self.config_value = value; - } - - fn set_code_block(&mut self, code_block: String, code_block_start: u32) { - self.code_block = Some(code_block); - self.code_block_start = Some(code_block_start); - } - - fn get_block_config(&self) -> Config { - let mut config = Config::default(); - config.override_value( - self.config_name.as_ref().unwrap(), - self.config_value.as_ref().unwrap(), - ); - config - } - - fn code_block_valid(&self) -> bool { - // We never expect to not have a code block. - assert!(self.code_block.is_some() && self.code_block_start.is_some()); - - if self.config_name.is_none() { - write_message(&format!( - "No configuration name for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - if self.config_value.is_none() { - write_message(&format!( - "No configuration value for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - true - } - - fn has_parsing_errors(&self, error_summary: Summary) -> bool { - if error_summary.has_parsing_errors() { - write_message(&format!( - "\u{261d}\u{1f3fd} Cannot format {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return true; - } - - false - } - - fn print_diff(&self, compare: Vec) { - let mut mismatches = HashMap::new(); - mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); - print_mismatches(mismatches, |line_num| { - format!( - "\nMismatch at {}:{}:", - CONFIGURATIONS_FILE_NAME, - line_num + self.code_block_start.unwrap() - 1 - ) - }); - } - - fn formatted_has_diff(&self, file_map: &FileMap) -> bool { - let &(ref _file_name, ref text) = file_map.first().unwrap(); - let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - self.print_diff(compare); - return true; - } - - false - } - - // Return a bool indicating if formatting this code block is an idempotent - // operation. This function also triggers printing any formatting failure - // messages. - fn formatted_is_idempotent(&self) -> bool { - // Verify that we have all of the expected information. - if !self.code_block_valid() { - return false; - } - - let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); - let config = self.get_block_config(); - - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); - - !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) - } - - // Extract a code block from the iterator. Behavior: - // - Rust code blocks are identifed by lines beginning with "```rust". - // - One explicit configuration setting is supported per code block. - // - Rust code blocks with no configuration setting are illegal and cause an - // assertion failure. - // - Configuration names in Configurations.md must be in the form of - // "## `NAME`". - // - Configuration values in Configurations.md must be in the form of - // "#### `VALUE`". - fn extract>( - file: &mut Enumerate, - prev: Option<&ConfigCodeBlock>, - ) -> Option { - let mut code_block = ConfigCodeBlock::new(); - code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); - - loop { - match ConfigurationSection::get_section(file) { - Some(ConfigurationSection::CodeBlock((block, start_line))) => { - code_block.set_code_block(block, start_line); - break; - } - Some(ConfigurationSection::ConfigName(name)) => { - code_block.set_config_name(Some(name)); - } - Some(ConfigurationSection::ConfigValue(value)) => { - code_block.set_config_value(Some(value)); - } - None => return None, // end of file was reached - } - } - - Some(code_block) - } -} - -#[test] -#[ignore] -fn configuration_snippet_tests() { - // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one - // entry for each Rust code block found. - fn get_code_blocks() -> Vec { - let mut file_iter = BufReader::new( - fs::File::open(CONFIGURATIONS_FILE_NAME) - .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), - ).lines() - .map(|l| l.unwrap()) - .enumerate(); - let mut code_blocks: Vec = Vec::new(); - - while let Some(cb) = ConfigCodeBlock::extract(&mut file_iter, code_blocks.last()) { - code_blocks.push(cb); - } - - code_blocks - } - - let blocks = get_code_blocks(); - let failures = blocks - .iter() - .map(|b| b.formatted_is_idempotent()) - .fold(0, |acc, r| acc + (!r as u32)); - - // Display results. - println!("Ran {} configurations tests.", blocks.len()); - assert_eq!(failures, 0, "{} configurations tests failed", failures); -} diff --git a/tests/target/assignment.rs b/tests/target/assignment.rs deleted file mode 100644 index 4e8689ed23e..00000000000 --- a/tests/target/assignment.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Test assignment - -fn main() { - let some_var: Type; - - let mut mutable; - - let variable = - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; - - variable = - LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; - - let single_line_fit = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; - - single_line_fit = 5; - single_lit_fit >>= 10; -} - -fn break_meee() { - { - ( - block_start, - block_size, - margin_block_start, - margin_block_end, - ) = match (block_start, block_end, block_size) { - x => 1, - _ => 2, - }; - } -} - -// #2018 -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = - "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/tests/target/associated-items.rs b/tests/target/associated-items.rs deleted file mode 100644 index 1b0a828d029..00000000000 --- a/tests/target/associated-items.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("{}", ::default()); -} diff --git a/tests/target/associated-types-bounds-wrapping.rs b/tests/target/associated-types-bounds-wrapping.rs deleted file mode 100644 index d5b94a5e869..00000000000 --- a/tests/target/associated-types-bounds-wrapping.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-max_width: 100 -// Test proper wrapping of long associated type bounds - -pub trait HttpService { - type WsService: 'static - + Service; -} diff --git a/tests/target/associated_type_defaults.rs b/tests/target/associated_type_defaults.rs deleted file mode 100644 index d0a08133725..00000000000 --- a/tests/target/associated_type_defaults.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(associated_type_defaults)] -trait Foo { - type Bar = (); -} diff --git a/tests/target/attrib-extern-crate.rs b/tests/target/attrib-extern-crate.rs deleted file mode 100644 index ed64a0aeb07..00000000000 --- a/tests/target/attrib-extern-crate.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Attributes on extern crate. - -#[Attr1] -extern crate Bar; -#[Attr2] -#[Attr2] -extern crate Baz; -extern crate Foo; - -fn foo() { - #[Attr1] - extern crate Bar; - #[Attr2] - #[Attr2] - extern crate Baz; - extern crate Foo; -} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs deleted file mode 100644 index 43c4f9f327f..00000000000 --- a/tests/target/attrib.rs +++ /dev/null @@ -1,154 +0,0 @@ -// rustfmt-wrap_comments: true -// Test attributes and doc comments are preserved. - -//! Doc comment - -#![attribute] - -//! Crate doc comment - -// Comment - -// Comment on attribute -#![the(attribute)] - -// Another comment - -#[invalid attribute] -fn foo() {} - -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. - -/// Blah blah blah. -impl Bar { - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - #[an_attribute] - fn foo(&mut self) -> isize {} - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - pub fn f2(self) { - (foo, bar) - } - - #[another_attribute] - fn f3(self) -> Dog {} - - /// Blah blah bing. - - #[attrib1] - /// Blah blah bing. - #[attrib2] - // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo - // loooooooooooong. - /// Blah blah bing. - fn f4(self) -> Cat {} - - // We want spaces around `=` - #[cfg(feature = "nightly")] - fn f5(self) -> Monkey {} -} - -// #984 -struct Foo { - #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] - foo: usize, -} - -// #1668 - -/// Default path (*nix) -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -fn foo() { - #[cfg(target_os = "freertos")] - match port_id { - 'a' | 'A' => GpioPort { - port_address: GPIO_A, - }, - 'b' | 'B' => GpioPort { - port_address: GPIO_B, - }, - _ => panic!(), - } - - #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] - let x = 3; -} - -// #1777 -#[test] -#[should_panic(expected = "(")] -#[should_panic(expected = /* ( */ "(")] -#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] -#[should_panic( - /* (((((((( *//* - (((((((((()(((((((( */ - expected = "(" - // (((((((( -)] -fn foo() {} - -// #1799 -fn issue_1799() { - #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 - Some(Err(error)); - - #[allow(unreachable_code)] - // https://github.com/rust-lang/rust/issues/43336 - Some(Err(error)); -} - -// Formatting inner attributes -fn inner_attributes() { - #![this_is_an_inner_attribute(foo)] - - foo(); -} - -impl InnerAttributes() { - #![this_is_an_inner_attribute(foo)] - - fn foo() {} -} - -mod InnerAttributes { - #![this_is_an_inner_attribute(foo)] -} - -fn attributes_on_statements() { - // Local - #[attr(on(local))] - let x = 3; - - // Item - #[attr(on(item))] - use foo; - - // Expr - #[attr(on(expr))] - {} - - // Semi - #[attr(on(semi))] - foo(); - - // Mac - #[attr(on(mac))] - foo!(); -} - -// Large derive -#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, - Deserialize)] -pub struct HP(pub u8); diff --git a/tests/target/big-impl-rfc.rs b/tests/target/big-impl-rfc.rs deleted file mode 100644 index bc16f12c9d7..00000000000 --- a/tests/target/big-impl-rfc.rs +++ /dev/null @@ -1,87 +0,0 @@ -// rustfmt-indent_style: Block - -// #1357 -impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> - for SelectStatement -where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} -impl Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} - -// #1689 -impl SubSelectDirect -where - M: select::Selector, - S: event::Stream, - F: for<'t> FnMut(transform::Api<'t, Stream>>) -> transform::Api<'t, X>, - X: event::Stream, -{ -} diff --git a/tests/target/big-impl.rs b/tests/target/big-impl.rs deleted file mode 100644 index 6f122e7e0b6..00000000000 --- a/tests/target/big-impl.rs +++ /dev/null @@ -1,75 +0,0 @@ -// #1357 -impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> - for SelectStatement -where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} -impl Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} diff --git a/tests/target/break-and-continue.rs b/tests/target/break-and-continue.rs deleted file mode 100644 index c01d8a07845..00000000000 --- a/tests/target/break-and-continue.rs +++ /dev/null @@ -1,23 +0,0 @@ -// break and continue formatting - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a; - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b; - } - - let x = loop { - break 5; - }; - - let x = 'c: loop { - break 'c 5; - }; -} diff --git a/tests/target/catch.rs b/tests/target/catch.rs deleted file mode 100644 index 640f9bade49..00000000000 --- a/tests/target/catch.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(catch_expr)] - -fn main() { - let x = do catch { foo()? }; - - let x = do catch /* Invisible comment */ { foo()? }; - - let x = do catch { unsafe { foo()? } }; - - let y = match (do catch { foo()? }) { - _ => (), - }; - - do catch { - foo()?; - }; - - do catch { - // Regular do catch block - }; -} diff --git a/tests/target/chains-indent-tabbed.rs b/tests/target/chains-indent-tabbed.rs deleted file mode 100644 index ea6b5764e44..00000000000 --- a/tests/target/chains-indent-tabbed.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-indent_style: Block - -fn test() { - let x = my_long_function() - .my_even_longer_function() - .my_nested_function() - .some_random_name() - .another_function() - .do_it(); -} diff --git a/tests/target/chains-indent-visual.rs b/tests/target/chains-indent-visual.rs deleted file mode 100644 index 23814e3dbe1..00000000000 --- a/tests/target/chains-indent-visual.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style: Visual - -fn test() { - let x = my_long_function().my_even_longer_function() - .my_nested_function() - .some_random_name() - .another_function() - .do_it(); -} diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs deleted file mode 100644 index b842d73c99f..00000000000 --- a/tests/target/chains-visual.rs +++ /dev/null @@ -1,159 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Visual -// Test chain formatting. - -fn main() { - // Don't put chains on a single line if it wasn't so in source. - let a = b.c.d.1.foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x().y(|| match cond() { - true => (), - false => (), - }); - - loong_func().quux(move || if true { 1 } else { 2 }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }) - .method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = - xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { field1: val1, - field2: val2, }; - - let x = Foo { field1: val1, - field2: val2, }.method_call() - .method_call(); - - let y = if cond { val1 } else { val2 }.method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }].clone()); - } - } - } - - if cond { - some(); - } else { - none(); - }.bar() - .baz(); - - Foo { x: val }.baz(|| { - force(); - multiline(); - }) - .quux(); - - Foo { y: i_am_multi_line, - z: ok, }.baz(|| { - force(); - multiline(); - }) - .quux(); - - a + match x { - true => "yay!", - false => "boo!", - }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) - .unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn issue_1389() { - let names = String::from_utf8(names)?.split('|') - .map(str::to_owned) - .collect(); -} - -fn issue1217() -> Result { - let random_chars: String = OsRng::new()?.gen_ascii_chars() - .take(self.bit_length) - .collect(); - - Ok(Mnemonic::new(&random_chars)) -} - -fn issue1236(options: Vec) -> Result> { - let process = Command::new("dmenu").stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .chain_err(|| "failed to spawn dmenu")?; -} - -fn issue1434() { - for _ in 0..100 { - let prototype_id = - PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { - format!("could not read prototype ID at offset {:#010x}", - current_offset) - })?; - } -} - -fn issue2264() { - { - something.function() - .map(|| { - if let a_very_very_very_very_very_very_very_very_long_variable = - compute_this_variable() - { - println!("Hello"); - } - }) - .collect(); - } -} diff --git a/tests/target/chains.rs b/tests/target/chains.rs deleted file mode 100644 index 8a41eec2bde..00000000000 --- a/tests/target/chains.rs +++ /dev/null @@ -1,261 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-use_small_heuristics: false -// Test chain formatting. - -fn main() { - let a = b.c.d.1.foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb - .ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); - - let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo - .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x().y(|| match cond() { - true => (), - false => (), - }); - - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }) - .method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = - xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x); - - body.fold(Body::new(), |mut body, chunk| { - body.extend(chunk); - Ok(body) - }).and_then(move |body| { - let req = Request::from_parts(parts, body); - f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) - }); - - aaaaaaaaaaaaaaaa - .map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { - field1: val1, - field2: val2, - }; - - let x = Foo { - field1: val1, - field2: val2, - }.method_call() - .method_call(); - - let y = if cond { - val1 - } else { - val2 - }.method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push( - mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }].clone(), - ); - } - } - } - - if cond { - some(); - } else { - none(); - }.bar() - .baz(); - - Foo { - x: val, - }.baz(|| { - force(); - multiline(); - }) - .quux(); - - Foo { - y: i_am_multi_line, - z: ok, - }.baz(|| { - force(); - multiline(); - }) - .quux(); - - a + match x { - true => "yay!", - false => "boo!", - }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn try_shorthand() { - let x = expr?; - let y = expr.kaas()?.test(); - let loooooooooooooooooooooooooooooooooooooooooong = - does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; - let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); - let zzzz = expr?.another?.another?.another?.another?; - let aaa = x??????????????????????????????????????????????????????????????????????????; - - let y = a.very - .loooooooooooooooooooooooooooooooooooooong() - .chain() - .inside() - .weeeeeeeeeeeeeee()? - .test() - .0 - .x; - - parameterized(f, substs, def_id, Ns::Value, &[], |tcx| tcx.lookup_item_type(def_id).generics)?; - fooooooooooooooooooooooooooo()? - .bar()? - .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; -} - -fn issue_1004() { - match *self { - ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), - }?; - - ty::tls::with(|tcx| { - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - })?; -} - -fn issue1392() { - test_method( - r#" - if foo { - a(); - } - else { - b(); - } - "#.trim(), - ); -} - -// #2067 -impl Settings { - fn save(&self) -> Result<()> { - let mut file = File::create(&settings_path) - .chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; - } -} - -fn issue2126() { - { - { - { - { - { - let x = self.span_from( - sub_span.expect("No span found for struct arant variant"), - ); - self.sspanpan_from_span( - sub_span.expect("No span found for struct variant"), - ); - let x = self.spanpan_from_span( - sub_span.expect("No span found for struct variant"), - )?; - } - } - } - } - } -} - -// #2200 -impl Foo { - pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes { - let other_attrs = attrs - .iter() - .filter_map(|attr| { - attr.with_desugared_doc(|attr| { - if attr.check_name("doc") { - if let Some(mi) = attr.meta() { - if let Some(value) = mi.value_str() { - doc_strings.push(DocFragment::Include( - line, - attr.span, - filename, - contents, - )); - } - } - } - }) - }) - .collect(); - } -} - -// #2415 -// Avoid orphan in chain -fn issue2415() { - let base_url = (|| { - // stuff - - Ok((|| { - // stuff - Some(value.to_string()) - })().ok_or("")?) - })().unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); -} diff --git a/tests/target/closure-block-inside-macro.rs b/tests/target/closure-block-inside-macro.rs deleted file mode 100644 index c1260592083..00000000000 --- a/tests/target/closure-block-inside-macro.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Block - -// #1547 -fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { - let index = *first as usize; - if index >= ENCODINGS.len() { - return; - } - let encoding = ENCODINGS[index]; - dispatch_test(encoding, &data[1..]); -}); diff --git a/tests/target/closure.rs b/tests/target/closure.rs deleted file mode 100644 index 5bc89d58222..00000000000 --- a/tests/target/closure.rs +++ /dev/null @@ -1,248 +0,0 @@ -// rustfmt-normalize_comments: true -// Closures - -fn main() { - let square = (|i: i32| i * i); - - let commented = |// first - a, // argument - // second - b: WithType, // argument - // ignored - _| { - ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ) - }; - - let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - }; - - let loooooooooooooong_name = |field| { - // format comments. - if field.node.attrs.len() > 0 { - field.node.attrs[0].span.lo() - } else { - field.span.lo() - } - }; - - let unblock_me = |trivial| closure(); - - let empty = |arg| {}; - - let simple = |arg| { - // comment formatting - foo(arg) - }; - - let test = || { - do_something(); - do_something_else(); - }; - - let arg_test = - |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - - let arg_test = - |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - - let simple_closure = move || -> () {}; - - let closure = |input: Ty| -> Option { foo() }; - - let closure_with_return_type = - |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; - - |arg1, arg2, _, _, arg3, arg4| { - let temp = arg4 + arg3; - arg2 * arg1 - temp - }; - - let block_body_with_comment = args.iter().map(|a| { - // Emitting only dep-info is possible only for final crate type, as - // as others may emit required metadata for dependent crate types - if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { - "--emit=dep-info" - } else { - a - } - }); -} - -fn issue311() { - let func = |x| println!("{}", x); - - (func)(0.0); -} - -fn issue863() { - let closure = |x| match x { - 0 => true, - _ => false, - } == true; -} - -fn issue934() { - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; - - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish(); - }; -} - -impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { - pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { - match (&left.node, &right.node) { - (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { - l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - }) - } - } - } -} - -fn foo() { - lifetimes_iter___map(|lasdfasfd| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi() - }; - }); -} - -fn issue1405() { - open_raw_fd(fd, b'r').and_then(|file| { - Capture::new_raw(None, |_, err| unsafe { raw::pcap_fopen_offline(file, err) }) - }); -} - -fn issue1466() { - let vertex_buffer = frame.scope(|ctx| { - let buffer = ctx.create_host_visible_buffer::>(&vertices); - ctx.create_device_local_buffer(buffer) - }); -} - -fn issue470() { - { - { - { - let explicit_arg_decls = explicit_arguments.into_iter().enumerate().map( - |(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); - block = this.pattern( - block, - argument_extent, - hair::PatternRef::Hair(pattern), - &lvalue, - ); - ArgDecl { ty: ty } - }, - ); - } - } - } -} - -// #1509 -impl Foo { - pub fn bar(&self) { - Some(SomeType { - push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| Ok(f))), - }) - } -} - -fn issue1329() { - aaaaaaaaaaaaaaaa - .map(|x| { - x += 1; - x - }) - .filter -} - -fn issue325() { - let f = - || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; -} - -fn issue1697() { - Test.func_a( - A_VERY_LONG_CONST_VARIABLE_NAME, - move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4, - ) -} - -fn issue1694() { - foooooo( - |_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| { - format!("refs/pull/{}/merge", pr_id) - }, - ) -} - -fn issue1713() { - rayon::join( - || recurse(left, is_less, pred, limit), - || recurse(right, is_less, Some(pivot), limit), - ); - - rayon::join( - 1, - || recurse(left, is_less, pred, limit), - 2, - || recurse(right, is_less, Some(pivot), limit), - ); -} - -fn issue2063() { - |ctx: Ctx<(String, String)>| -> io::Result { - Ok(Response::new().with_body(ctx.params.0)) - } -} - -fn issue1524() { - let f = |x| x; - let f = |x| x; - let f = |x| x; - let f = |x| x; - let f = |x| x; -} - -fn issue2171() { - foo(|| unsafe { - if PERIPHERALS { - loop {} - } else { - PERIPHERALS = true; - } - }) -} - -fn issue2207() { - a.map(|_| { - unsafe { a_very_very_very_very_very_very_very_long_function_name_or_anything_else() } - .to_string() - }) -} - -fn issue2262() { - result - .init(&mut result.slave.borrow_mut(), &mut (result.strategy)()) - .map_err(|factory| Error { - factory, - slave: None, - })?; -} diff --git a/tests/target/comment-inside-const.rs b/tests/target/comment-inside-const.rs deleted file mode 100644 index f847f2c69de..00000000000 --- a/tests/target/comment-inside-const.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn issue982() { - const SOME_CONSTANT: u32 = - // Explanation why SOME_CONSTANT needs FLAG_A to be set. - FLAG_A | - // Explanation why SOME_CONSTANT needs FLAG_B to be set. - FLAG_B | - // Explanation why SOME_CONSTANT needs FLAG_C to be set. - FLAG_C; -} diff --git a/tests/target/comment-not-disappear.rs b/tests/target/comment-not-disappear.rs deleted file mode 100644 index 646b37e46e2..00000000000 --- a/tests/target/comment-not-disappear.rs +++ /dev/null @@ -1,36 +0,0 @@ -// All the comments here should not disappear. - -fn a() { - match x { - X | - // A comment - Y => {} - }; -} - -fn b() { - match x { - X => - // A comment - y - } -} - -fn c() { - a() /* ... */; -} - -fn foo() -> Vec { - (0..11) - .map(|x| - // This comment disappears. - if x % 2 == 0 { x } else { x * 2 }) - .collect() -} - -fn calc_page_len(prefix_len: usize, sofar: usize) -> usize { - 2 // page type and flags - + 1 // stored depth - + 2 // stored count - + prefix_len + sofar // sum of size of all the actual items -} diff --git a/tests/target/comment.rs b/tests/target/comment.rs deleted file mode 100644 index 5abf5369066..00000000000 --- a/tests/target/comment.rs +++ /dev/null @@ -1,95 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//! Doc comment -fn test() { - //! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam - //! lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - - // comment - // comment2 - - code(); // leave this comment alone! - // ok? - - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - // viverra nec consectetur ante hendrerit. Donec et mollis dolor. - // Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - // tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - // libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - // amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - // felis, pulvinar a semper sed, adipiscing id dolor. - - // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment - // that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); // dontchangeme - // or me - - // #1388 - const EXCEPTION_PATHS: &'static [&'static str] = &[ - // std crates - "src/libstd/sys/", // Platform-specific code for std lives here. - "src/bootstrap", - ]; -} - -/// test123 -fn doc_comment() {} - -fn chains() { - foo.bar(|| { - let x = 10; - // comment - x - }) -} - -fn issue_1086() { - // -} - -// random comment - -fn main() { - // Test -} - -// #1643 -fn some_fn() // some comment -{ -} - -fn some_fn1() -// some comment -{ -} - -fn some_fn2() // some comment -{ -} - -fn some_fn3() // some comment some comment some comment some comment some comment some comment so -{ -} - -fn some_fn4() -// some comment some comment some comment some comment some comment some comment -// some comment -{ -} - -// #1603 -pub enum Foo { - A, // `/** **/` - B, // `/*!` - C, -} diff --git a/tests/target/comment2.rs b/tests/target/comment2.rs deleted file mode 100644 index 04f84a15c95..00000000000 --- a/tests/target/comment2.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-wrap_comments: true - -/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly -/// and justly. -pub mod foo {} diff --git a/tests/target/comment3.rs b/tests/target/comment3.rs deleted file mode 100644 index 3a810590d7b..00000000000 --- a/tests/target/comment3.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-wrap_comments: true - -//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly -//! and justly. - -pub mod foo {} diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs deleted file mode 100644 index e07abf74a81..00000000000 --- a/tests/target/comment4.rs +++ /dev/null @@ -1,51 +0,0 @@ -#![allow(dead_code)] // bar - -//! Doc comment -fn test() { - // comment - // comment2 - - code(); /* leave this comment alone! - * ok? */ - - /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - * viverra nec consectetur ante hendrerit. Donec et mollis dolor. - * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - * felis, pulvinar a semper sed, adipiscing id dolor. */ - - // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); //dontchangeme - // or me -} - -/// test123 -fn doc_comment() {} - -/* -Regression test for issue #956 - -(some very important text) -*/ - -/* -fn debug_function() { - println!("hello"); -} -// */ - -#[link_section=".vectors"] -#[no_mangle] // Test this attribute is preserved. -#[cfg_attr(rustfmt, rustfmt_skip)] -pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/target/comment5.rs b/tests/target/comment5.rs deleted file mode 100644 index c52f9b38977..00000000000 --- a/tests/target/comment5.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//@ special comment -//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam -//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@ -//@ foo -fn test() {} - -//@@@ another special comment -//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam -//@@@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@@@ -//@@@ foo -fn bar() {} diff --git a/tests/target/comment_crlf_newline.rs b/tests/target/comment_crlf_newline.rs deleted file mode 100644 index aab9e94d9e6..00000000000 --- a/tests/target/comment_crlf_newline.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true -// Block comments followed by CRLF newlines should not an extra newline at the end - -// Something else diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs deleted file mode 100644 index 39af3fd064e..00000000000 --- a/tests/target/comments-fn.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Test comments on functions are preserved. - -// Comment on foo. -fn foo( - a: aaaaaaaaaaaaa, // A comment - b: bbbbbbbbbbbbb, // a second comment - c: ccccccccccccc, - // Newline comment - d: ddddddddddddd, - // A multi line comment - // between args. - e: eeeeeeeeeeeee, /* comment before paren */ -) -> bar -where - F: Foo, // COmment after where clause - G: Goo, // final comment -{ - -} - -fn bar() {} - -fn baz() -> Baz /* Comment after return type */ {} - -fn some_fn() -where - T: Eq, // some comment -{ -} - -fn issue458(a: &str, f: F) -// comment1 -where - // comment2 - F: FnOnce(&str) -> bool, -{ - f(a); - () -} diff --git a/tests/target/configs/blank_lines_lower_bound/1.rs b/tests/target/configs/blank_lines_lower_bound/1.rs deleted file mode 100644 index 9706699dc7a..00000000000 --- a/tests/target/configs/blank_lines_lower_bound/1.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-blank_lines_lower_bound: 1 - -fn foo() {} - -fn bar() {} - -// comment -fn foobar() {} - -fn foo1() {} - -fn bar1() {} - -// comment - -fn foobar1() {} diff --git a/tests/target/configs/brace_style/fn_always_next_line.rs b/tests/target/configs/brace_style/fn_always_next_line.rs deleted file mode 100644 index 2755a264689..00000000000 --- a/tests/target/configs/brace_style/fn_always_next_line.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Function brace style - -fn lorem() -{ - // body -} - -fn lorem(ipsum: usize) -{ - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, -{ - // body -} diff --git a/tests/target/configs/brace_style/fn_prefer_same_line.rs b/tests/target/configs/brace_style/fn_prefer_same_line.rs deleted file mode 100644 index 23f98b6dd7a..00000000000 --- a/tests/target/configs/brace_style/fn_prefer_same_line.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, { - // body -} diff --git a/tests/target/configs/brace_style/fn_same_line_where.rs b/tests/target/configs/brace_style/fn_same_line_where.rs deleted file mode 100644 index 2afe59943a3..00000000000 --- a/tests/target/configs/brace_style/fn_same_line_where.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, -{ - // body -} diff --git a/tests/target/configs/brace_style/item_always_next_line.rs b/tests/target/configs/brace_style/item_always_next_line.rs deleted file mode 100644 index 38ed449d178..00000000000 --- a/tests/target/configs/brace_style/item_always_next_line.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Item brace style - -enum Foo {} - -struct Bar {} - -struct Lorem -{ - ipsum: bool, -} - -struct Dolor -where - T: Eq, -{ - sit: T, -} - -#[cfg(test)] -mod tests -{ - #[test] - fn it_works() - { - } -} diff --git a/tests/target/configs/brace_style/item_prefer_same_line.rs b/tests/target/configs/brace_style/item_prefer_same_line.rs deleted file mode 100644 index 5143d7517c7..00000000000 --- a/tests/target/configs/brace_style/item_prefer_same_line.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor -where - T: Eq, { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/tests/target/configs/brace_style/item_same_line_where.rs b/tests/target/configs/brace_style/item_same_line_where.rs deleted file mode 100644 index 8a3b2852654..00000000000 --- a/tests/target/configs/brace_style/item_same_line_where.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor -where - T: Eq, -{ - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/tests/target/configs/combine_control_expr/false.rs b/tests/target/configs/combine_control_expr/false.rs deleted file mode 100644 index 81eff08660d..00000000000 --- a/tests/target/configs/combine_control_expr/false.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-combine_control_expr: false -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. - -fn main() { - // Call - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Mac - foo(foo!( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // MethodCall - foo(x.foo::( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Block - foo!({ - foo(); - bar(); - }); - - // Closure - foo(|x| { - let y = x + 1; - y - }); - - // Match - foo(match opt { - Some(x) => x, - None => y, - }); - - // Struct - foo(Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // If - foo!( - if x { - foo(); - } else { - bar(); - } - ); - - // IfLet - foo!( - if let Some(..) = x { - foo(); - } else { - bar(); - } - ); - - // While - foo!( - while x { - foo(); - bar(); - } - ); - - // WhileLet - foo!( - while let Some(..) = x { - foo(); - bar(); - } - ); - - // ForLoop - foo!( - for x in y { - foo(); - bar(); - } - ); - - // Loop - foo!( - loop { - foo(); - bar(); - } - ); - - // Tuple - foo(( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // AddrOf - foo(&bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // Unary - foo(!bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Try - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )?); - - // Cast - foo(Bar { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - } as i64); -} diff --git a/tests/target/configs/combine_control_expr/true.rs b/tests/target/configs/combine_control_expr/true.rs deleted file mode 100644 index c5372c2ff37..00000000000 --- a/tests/target/configs/combine_control_expr/true.rs +++ /dev/null @@ -1,121 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-combine_control_expr: true -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. - -fn main() { - // Call - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Mac - foo(foo!( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // MethodCall - foo(x.foo::( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Block - foo!({ - foo(); - bar(); - }); - - // Closure - foo(|x| { - let y = x + 1; - y - }); - - // Match - foo(match opt { - Some(x) => x, - None => y, - }); - - // Struct - foo(Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // If - foo!(if x { - foo(); - } else { - bar(); - }); - - // IfLet - foo!(if let Some(..) = x { - foo(); - } else { - bar(); - }); - - // While - foo!(while x { - foo(); - bar(); - }); - - // WhileLet - foo!(while let Some(..) = x { - foo(); - bar(); - }); - - // ForLoop - foo!(for x in y { - foo(); - bar(); - }); - - // Loop - foo!(loop { - foo(); - bar(); - }); - - // Tuple - foo(( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // AddrOf - foo(&bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // Unary - foo(!bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Try - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )?); - - // Cast - foo(Bar { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - } as i64); -} diff --git a/tests/target/configs/comment_width/above.rs b/tests/target/configs/comment_width/above.rs deleted file mode 100644 index ddfecda65c1..00000000000 --- a/tests/target/configs/comment_width/above.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, - // consectetur adipiscing elit. -} diff --git a/tests/target/configs/comment_width/below.rs b/tests/target/configs/comment_width/below.rs deleted file mode 100644 index abbc5930c4c..00000000000 --- a/tests/target/configs/comment_width/below.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 80 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/tests/target/configs/comment_width/ignore.rs b/tests/target/configs/comment_width/ignore.rs deleted file mode 100644 index c86e71c2898..00000000000 --- a/tests/target/configs/comment_width/ignore.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: false -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/tests/target/configs/condense_wildcard_suffixes/false.rs b/tests/target/configs/condense_wildcard_suffixes/false.rs deleted file mode 100644 index 3b967f35a8e..00000000000 --- a/tests/target/configs/condense_wildcard_suffixes/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: false -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, _, _) = (1, 2, 3, 4); -} diff --git a/tests/target/configs/condense_wildcard_suffixes/true.rs b/tests/target/configs/condense_wildcard_suffixes/true.rs deleted file mode 100644 index 4f880abe80e..00000000000 --- a/tests/target/configs/condense_wildcard_suffixes/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: true -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, ..) = (1, 2, 3, 4); -} diff --git a/tests/target/configs/control_brace_style/always_next_line.rs b/tests/target/configs/control_brace_style/always_next_line.rs deleted file mode 100644 index 7dc06f207fe..00000000000 --- a/tests/target/configs/control_brace_style/always_next_line.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine -// Control brace style - -fn main() { - if lorem - { - println!("ipsum!"); - } - else - { - println!("dolor!"); - } - match magi - { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/tests/target/configs/control_brace_style/always_same_line.rs b/tests/target/configs/control_brace_style/always_same_line.rs deleted file mode 100644 index 993b6b681fe..00000000000 --- a/tests/target/configs/control_brace_style/always_same_line.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine -// Control brace style - -fn main() { - if lorem { - println!("ipsum!"); - } else { - println!("dolor!"); - } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/tests/target/configs/control_brace_style/closing_next_line.rs b/tests/target/configs/control_brace_style/closing_next_line.rs deleted file mode 100644 index 013852ee79a..00000000000 --- a/tests/target/configs/control_brace_style/closing_next_line.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine -// Control brace style - -fn main() { - if lorem { - println!("ipsum!"); - } - else { - println!("dolor!"); - } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/tests/target/configs/disable_all_formatting/false.rs b/tests/target/configs/disable_all_formatting/false.rs deleted file mode 100644 index 1a0477ddb39..00000000000 --- a/tests/target/configs/disable_all_formatting/false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-disable_all_formatting: false -// Disable all formatting - -fn main() { - if lorem { - println!("ipsum!"); - } else { - println!("dolor!"); - } -} diff --git a/tests/target/configs/disable_all_formatting/true.rs b/tests/target/configs/disable_all_formatting/true.rs deleted file mode 100644 index 736ccf56942..00000000000 --- a/tests/target/configs/disable_all_formatting/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: true -// Disable all formatting - -fn main() { - if lorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/tests/target/configs/empty_item_single_line/false.rs b/tests/target/configs/empty_item_single_line/false.rs deleted file mode 100644 index b7886df2aa8..00000000000 --- a/tests/target/configs/empty_item_single_line/false.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-empty_item_single_line: false -// Empty impl on single line - -impl Lorem { -} - -impl Ipsum { -} - -fn lorem() { -} - -fn lorem() { - -} diff --git a/tests/target/configs/empty_item_single_line/true.rs b/tests/target/configs/empty_item_single_line/true.rs deleted file mode 100644 index 0755485fea9..00000000000 --- a/tests/target/configs/empty_item_single_line/true.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-empty_item_single_line: true -// Empty impl on single line - -impl Lorem {} - -impl Ipsum {} - -fn lorem() {} - -fn lorem() {} diff --git a/tests/target/configs/error_on_line_overflow/false.rs b/tests/target/configs/error_on_line_overflow/false.rs deleted file mode 100644 index fa70ae78352..00000000000 --- a/tests/target/configs/error_on_line_overflow/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// Error on line overflow - -fn main() { - let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; -} diff --git a/tests/target/configs/error_on_unformatted/false.rs b/tests/target/configs/error_on_unformatted/false.rs deleted file mode 100644 index 6a78374e2a2..00000000000 --- a/tests/target/configs/error_on_unformatted/false.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-error_on_unformatted: false -// Error on line overflow comment or string literals. - -// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -fn main() { - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - - let x = " "; - let a = " - -"; -} diff --git a/tests/target/configs/fn_args_density/compressed.rs b/tests/target/configs/fn_args_density/compressed.rs deleted file mode 100644 index 99283722bee..00000000000 --- a/tests/target/configs/fn_args_density/compressed.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit, - ) { - // body - } -} diff --git a/tests/target/configs/fn_args_density/tall.rs b/tests/target/configs/fn_args_density/tall.rs deleted file mode 100644 index 6ee43b41a19..00000000000 --- a/tests/target/configs/fn_args_density/tall.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-fn_args_density: Tall -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} diff --git a/tests/target/configs/fn_args_density/vertical.rs b/tests/target/configs/fn_args_density/vertical.rs deleted file mode 100644 index d48b3492452..00000000000 --- a/tests/target/configs/fn_args_density/vertical.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-fn_args_density: Vertical -// Function arguments density - -trait Lorem { - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - ) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} diff --git a/tests/target/configs/fn_single_line/false.rs b/tests/target/configs/fn_single_line/false.rs deleted file mode 100644 index 3d092f0c0bf..00000000000 --- a/tests/target/configs/fn_single_line/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_single_line: false -// Single-expression function on single line - -fn lorem() -> usize { - 42 -} - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/tests/target/configs/fn_single_line/true.rs b/tests/target/configs/fn_single_line/true.rs deleted file mode 100644 index 10d94e02f16..00000000000 --- a/tests/target/configs/fn_single_line/true.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-fn_single_line: true -// Single-expression function on single line - -fn lorem() -> usize { 42 } - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/tests/target/configs/force_explicit_abi/false.rs b/tests/target/configs/force_explicit_abi/false.rs deleted file mode 100644 index 3c48f8e0c78..00000000000 --- a/tests/target/configs/force_explicit_abi/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: false -// Force explicit abi - -extern { - pub static lorem: c_int; -} diff --git a/tests/target/configs/force_explicit_abi/true.rs b/tests/target/configs/force_explicit_abi/true.rs deleted file mode 100644 index 90f5a8c4ecb..00000000000 --- a/tests/target/configs/force_explicit_abi/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: true -// Force explicit abi - -extern "C" { - pub static lorem: c_int; -} diff --git a/tests/target/configs/force_multiline_block/false.rs b/tests/target/configs/force_multiline_block/false.rs deleted file mode 100644 index 7cb4cac1d69..00000000000 --- a/tests/target/configs/force_multiline_block/false.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-force_multiline_blocks: false -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - }); -} diff --git a/tests/target/configs/force_multiline_block/true.rs b/tests/target/configs/force_multiline_block/true.rs deleted file mode 100644 index aec50afe5a8..00000000000 --- a/tests/target/configs/force_multiline_block/true.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-force_multiline_blocks: true -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| { - match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - } - }); -} diff --git a/tests/target/configs/format_strings/false.rs b/tests/target/configs/format_strings/false.rs deleted file mode 100644 index ecca0d7d1fc..00000000000 --- a/tests/target/configs/format_strings/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/tests/target/configs/format_strings/true.rs b/tests/target/configs/format_strings/true.rs deleted file mode 100644 index fdd5ab2c97d..00000000000 --- a/tests/target/configs/format_strings/true.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 50 -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet \ - consectetur adipiscing elit \ - lorem ipsum dolor sit"; -} diff --git a/tests/target/configs/hard_tabs/false.rs b/tests/target/configs/hard_tabs/false.rs deleted file mode 100644 index ccfb53d8c86..00000000000 --- a/tests/target/configs/hard_tabs/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: false -// Hard tabs - -fn lorem() -> usize { - 42 // spaces before 42 -} diff --git a/tests/target/configs/hard_tabs/true.rs b/tests/target/configs/hard_tabs/true.rs deleted file mode 100644 index 3ed4e4f20aa..00000000000 --- a/tests/target/configs/hard_tabs/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: true -// Hard tabs - -fn lorem() -> usize { - 42 // spaces before 42 -} diff --git a/tests/target/configs/imports_indent/block.rs b/tests/target/configs/imports_indent/block.rs deleted file mode 100644 index 84c3b26bd6e..00000000000 --- a/tests/target/configs/imports_indent/block.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-imports_indent: Block - -use lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, - SeparatorTactic, -}; diff --git a/tests/target/configs/imports_layout/horizontal_vertical.rs b/tests/target/configs/imports_layout/horizontal_vertical.rs deleted file mode 100644 index 4a63556d45b..00000000000 --- a/tests/target/configs/imports_layout/horizontal_vertical.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-imports_indent: Block -// rustfmt-imports_layout: HorizontalVertical - -use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; -use lists::{ - definitive_tactic, - itemize_list, - shape_for_tactic, - struct_lit_formatting, - struct_lit_shape, - struct_lit_tactic, - write_list, - DefinitiveListTactic, - ListFormatting, - ListItem, - ListTactic, - SeparatorTactic, -}; diff --git a/tests/target/configs/imports_layout/mixed.rs b/tests/target/configs/imports_layout/mixed.rs deleted file mode 100644 index 5d3349a01bb..00000000000 --- a/tests/target/configs/imports_layout/mixed.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-imports_indent: Block -// rustfmt-imports_layout: Mixed - -use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; -use lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, - SeparatorTactic, -}; diff --git a/tests/target/configs/indent_style/block_args.rs b/tests/target/configs/indent_style/block_args.rs deleted file mode 100644 index 80f4e133356..00000000000 --- a/tests/target/configs/indent_style/block_args.rs +++ /dev/null @@ -1,47 +0,0 @@ -// rustfmt-indent_style: Block -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem( - ipsum: usize, - dolor: usize, - sit: usize, - amet: usize, - consectetur: usize, - adipiscing: usize, - elit: usize, -) { - // body -} - -// #1441 -extern "system" { - pub fn GetConsoleHistoryInfo( - console_history_info: *mut ConsoleHistoryInfo, - ) -> Boooooooooooooool; -} - -// rustfmt should not add trailing comma for variadic function. See #1623. -extern "C" { - pub fn variadic_fn( - first_parameter: FirstParameterType, - second_parameter: SecondParameterType, - ... - ); -} - -// #1652 -fn deconstruct( - foo: Bar, -) -> ( - SocketAddr, - Header, - Method, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -) { -} diff --git a/tests/target/configs/indent_style/block_array.rs b/tests/target/configs/indent_style/block_array.rs deleted file mode 100644 index 5d458248c0b..00000000000 --- a/tests/target/configs/indent_style/block_array.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-indent_style: Block -// Array layout - -fn main() { - let lorem = vec![ - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ]; -} diff --git a/tests/target/configs/indent_style/block_call.rs b/tests/target/configs/indent_style/block_call.rs deleted file mode 100644 index d3522214c2e..00000000000 --- a/tests/target/configs/indent_style/block_call.rs +++ /dev/null @@ -1,149 +0,0 @@ -// rustfmt-indent_style: Block -// Function call style - -fn main() { - lorem( - "lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ); - // #1501 - let hyper = Arc::new(Client::with_connector(HttpsConnector::new( - TlsClient::new(), - ))); - - // chain - let x = yooooooooooooo - .fooooooooooooooo - .baaaaaaaaaaaaar(hello, world); - - // #1380 - { - { - let creds = self.client - .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; - } - } - - // nesting macro and function call - try!(foo( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - )); - try!(foo(try!( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - ))); -} - -// #1521 -impl Foo { - fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { - unsafe { - Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords( - self.render_texture, - point.raw(), - view.raw(), - )) - } - } -} - -fn issue1420() { - given( - r#" - # Getting started - ... - "#, - ).running(waltz) -} - -// #1563 -fn query(conn: &Connection) -> Result<()> { - conn.query_row( - r#" - SELECT title, date - FROM posts, - WHERE DATE(date) = $1 - "#, - &[], - |row| Post { - title: row.get(0), - date: row.get(1), - }, - )?; - - Ok(()) -} - -// #1449 -fn future_rayon_wait_1_thread() { - // run with only 1 worker thread; this would deadlock if we couldn't make progress - let mut result = None; - ThreadPool::new(Configuration::new().num_threads(1)) - .unwrap() - .install(|| { - scope(|s| { - use std::sync::mpsc::channel; - let (tx, rx) = channel(); - let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); - // ^^^^ FIXME: why is this needed? - let b = s.spawn_future(a.map(|v| v + 1)); - let c = s.spawn_future(b.map(|v| v + 1)); - s.spawn(move |_| tx.send(20).unwrap()); - result = Some(c.rayon_wait().unwrap()); - }); - }); - assert_eq!(result, Some(22)); -} - -// #1494 -impl Cursor { - fn foo() { - self.cur_type() - .num_template_args() - .or_else(|| { - let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; - - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - }) - .or_else(|| { - let canonical = self.canonical(); - if canonical != *self { - canonical.num_template_args() - } else { - None - } - }); - } -} - -fn issue1581() { - bootstrap.checks.register("PERSISTED_LOCATIONS", move || { - if locations2.0.inner_mut.lock().poisoned { - Check::new( - State::Error, - "Persisted location storage is poisoned due to a write failure", - ) - } else { - Check::new(State::Healthy, "Persisted location storage is healthy") - } - }); -} - -fn issue1651() { - { - let type_list: Vec<_> = - try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); - } -} diff --git a/tests/target/configs/indent_style/block_chain.rs b/tests/target/configs/indent_style/block_chain.rs deleted file mode 100644 index 23340a4aba2..00000000000 --- a/tests/target/configs/indent_style/block_chain.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Block -// Chain indent - -fn main() { - let lorem = ipsum - .dolor() - .sit() - .amet() - .consectetur() - .adipiscing() - .elite(); -} diff --git a/tests/target/configs/indent_style/block_generic.rs b/tests/target/configs/indent_style/block_generic.rs deleted file mode 100644 index c4fcaaf65d1..00000000000 --- a/tests/target/configs/indent_style/block_generic.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-indent_style: Block -// Generics indent - -fn lorem< - Ipsum: Eq = usize, - Dolor: Eq = usize, - Sit: Eq = usize, - Amet: Eq = usize, - Adipiscing: Eq = usize, - Consectetur: Eq = usize, - Elit: Eq = usize, ->( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - adipiscing: Adipiscing, - consectetur: Consectetur, - elit: Elit, -) -> T { - // body -} diff --git a/tests/target/configs/indent_style/block_struct_lit.rs b/tests/target/configs/indent_style/block_struct_lit.rs deleted file mode 100644 index 656b562266f..00000000000 --- a/tests/target/configs/indent_style/block_struct_lit.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style: Block -// Struct literal-style - -fn main() { - let lorem = Lorem { - ipsum: dolor, - sit: amet, - }; -} diff --git a/tests/target/configs/indent_style/block_tab_spaces_call.rs b/tests/target/configs/indent_style/block_tab_spaces_call.rs deleted file mode 100644 index 5531e61ddc8..00000000000 --- a/tests/target/configs/indent_style/block_tab_spaces_call.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-max_width: 80 -// rustfmt-tab_spaces: 2 - -// #1427 -fn main() { - exceptaions::config(move || { - ( - NmiConfig {}, - HardFaultConfig {}, - SysTickConfig { gpio_sbsrr }, - ) - }); -} diff --git a/tests/target/configs/indent_style/block_trailing_comma_call.rs b/tests/target/configs/indent_style/block_trailing_comma_call.rs deleted file mode 100644 index a7e8590ed97..00000000000 --- a/tests/target/configs/indent_style/block_trailing_comma_call.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Block - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo( - a, - oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), - ); -} diff --git a/tests/target/configs/indent_style/block_where_pred.rs b/tests/target/configs/indent_style/block_where_pred.rs deleted file mode 100644 index ad7e0b8f363..00000000000 --- a/tests/target/configs/indent_style/block_where_pred.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Block -// Where predicate indent - -fn lorem() -> T -where - Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq, -{ - // body -} diff --git a/tests/target/configs/indent_style/default.rs b/tests/target/configs/indent_style/default.rs deleted file mode 100644 index a8f0902b34e..00000000000 --- a/tests/target/configs/indent_style/default.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Visual -// Where style - -fn lorem() -> T - where Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq -{ - // body -} diff --git a/tests/target/configs/indent_style/rfc_control.rs b/tests/target/configs/indent_style/rfc_control.rs deleted file mode 100644 index 6619d8b2630..00000000000 --- a/tests/target/configs/indent_style/rfc_control.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-indent_style: Block - -// #1618 -fn main() { - loop { - if foo { - if ((right_paddle_speed < 0.) && (right_paddle.position().y - paddle_size.y / 2. > 5.)) - || ((right_paddle_speed > 0.) - && (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) - { - foo - } - if ai_timer.elapsed_time().as_microseconds() > ai_time.as_microseconds() { - if ball.position().y + ball_radius > right_paddle.position().y + paddle_size.y / 2. - { - foo - } - } - } - } -} - -fn issue1656() { - { - { - match rewrite { - Some(ref body_str) - if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) - || !context.config.match_arm_blocks() - || (extend && first_line_width(body_str) <= arm_shape.width) - || is_block => - { - return None; - } - _ => {} - } - } - } -} diff --git a/tests/target/configs/indent_style/rfc_where.rs b/tests/target/configs/indent_style/rfc_where.rs deleted file mode 100644 index a7b9a4f02b3..00000000000 --- a/tests/target/configs/indent_style/rfc_where.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Block -// Where style - -fn lorem() -> T -where - Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq, -{ - // body -} diff --git a/tests/target/configs/indent_style/visual_args.rs b/tests/target/configs/indent_style/visual_args.rs deleted file mode 100644 index 04c2eaee3cf..00000000000 --- a/tests/target/configs/indent_style/visual_args.rs +++ /dev/null @@ -1,40 +0,0 @@ -// rustfmt-indent_style: Visual -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem(ipsum: usize, - dolor: usize, - sit: usize, - amet: usize, - consectetur: usize, - adipiscing: usize, - elit: usize) { - // body -} - -// #1922 -extern "C" { - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - a: *const lapack_complex_float, - lda: lapack_int, - ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int) - -> lapack_int; - - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - lda: lapack_int, - ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int) - -> lapack_int; -} diff --git a/tests/target/configs/indent_style/visual_array.rs b/tests/target/configs/indent_style/visual_array.rs deleted file mode 100644 index 1da6ff23738..00000000000 --- a/tests/target/configs/indent_style/visual_array.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Visual -// Array layout - -fn main() { - let lorem = vec!["ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit"]; -} diff --git a/tests/target/configs/indent_style/visual_call.rs b/tests/target/configs/indent_style/visual_call.rs deleted file mode 100644 index 5454c44ef96..00000000000 --- a/tests/target/configs/indent_style/visual_call.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-indent_style: Visual -// Function call style - -fn main() { - lorem("lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit"); -} diff --git a/tests/target/configs/indent_style/visual_chain.rs b/tests/target/configs/indent_style/visual_chain.rs deleted file mode 100644 index 569f3d8b81d..00000000000 --- a/tests/target/configs/indent_style/visual_chain.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Visual -// Chain indent - -fn main() { - let lorem = ipsum.dolor() - .sit() - .amet() - .consectetur() - .adipiscing() - .elite(); -} diff --git a/tests/target/configs/indent_style/visual_generics.rs b/tests/target/configs/indent_style/visual_generics.rs deleted file mode 100644 index 491075a146d..00000000000 --- a/tests/target/configs/indent_style/visual_generics.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-indent_style: Visual -// Generics indent - -fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - adipiscing: Adipiscing, - consectetur: Consectetur, - elit: Elit) - -> T { - // body -} diff --git a/tests/target/configs/indent_style/visual_struct_lit.rs b/tests/target/configs/indent_style/visual_struct_lit.rs deleted file mode 100644 index b4effba0e8a..00000000000 --- a/tests/target/configs/indent_style/visual_struct_lit.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-indent_style: Visual -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, - sit: amet, }; -} diff --git a/tests/target/configs/indent_style/visual_trailing_comma.rs b/tests/target/configs/indent_style/visual_trailing_comma.rs deleted file mode 100644 index 9738d397dbf..00000000000 --- a/tests/target/configs/indent_style/visual_trailing_comma.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); -} diff --git a/tests/target/configs/indent_style/visual_where_pred.rs b/tests/target/configs/indent_style/visual_where_pred.rs deleted file mode 100644 index 45799dcd5fc..00000000000 --- a/tests/target/configs/indent_style/visual_where_pred.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Visual -// Where predicate indent - -fn lorem() -> T - where Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq -{ - // body -} diff --git a/tests/target/configs/match_arm_blocks/false.rs b/tests/target/configs/match_arm_blocks/false.rs deleted file mode 100644 index 4d53a96a7b7..00000000000 --- a/tests/target/configs/match_arm_blocks/false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Wrap match-arms - -fn main() { - match lorem { - true => - foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => println!("{}", sit), - } -} diff --git a/tests/target/configs/match_arm_blocks/true.rs b/tests/target/configs/match_arm_blocks/true.rs deleted file mode 100644 index d75ef03397a..00000000000 --- a/tests/target/configs/match_arm_blocks/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_arm_blocks: true -// Wrap match-arms - -fn main() { - match lorem { - true => { - foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) - } - false => println!("{}", sit), - } -} diff --git a/tests/target/configs/match_block_trailing_comma/false.rs b/tests/target/configs/match_block_trailing_comma/false.rs deleted file mode 100644 index 70e02955fb0..00000000000 --- a/tests/target/configs/match_block_trailing_comma/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: false -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - } - Lorem::Dolor => println!("dolor"), - } -} diff --git a/tests/target/configs/match_block_trailing_comma/true.rs b/tests/target/configs/match_block_trailing_comma/true.rs deleted file mode 100644 index b78b046dc1c..00000000000 --- a/tests/target/configs/match_block_trailing_comma/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - }, - Lorem::Dolor => println!("dolor"), - } -} diff --git a/tests/target/configs/merge_derives/true.rs b/tests/target/configs/merge_derives/true.rs deleted file mode 100644 index 4d0148b1c6e..00000000000 --- a/tests/target/configs/merge_derives/true.rs +++ /dev/null @@ -1,40 +0,0 @@ -// rustfmt-merge_derives: true -// Merge multiple derives to a single one. - -#[bar] -#[derive(Eq, PartialEq)] -#[foo] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Foo {} - -#[derive(Eq, PartialEq, Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Bar {} - -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum FooBar {} - -mod foo { - #[bar] - #[derive(Eq, PartialEq)] - #[foo] - #[derive(Debug)] - #[foobar] - #[derive(Copy, Clone)] - pub enum Foo {} -} - -mod bar { - #[derive(Eq, PartialEq, Debug)] - #[foobar] - #[derive(Copy, Clone)] - pub enum Bar {} -} - -mod foobar { - #[derive(Eq, PartialEq, Debug, Copy, Clone)] - pub enum FooBar {} -} diff --git a/tests/target/configs/normalize_comments/false.rs b/tests/target/configs/normalize_comments/false.rs deleted file mode 100644 index 488962ed936..00000000000 --- a/tests/target/configs/normalize_comments/false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: false -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -/* sit amet: */ -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/target/configs/normalize_comments/true.rs b/tests/target/configs/normalize_comments/true.rs deleted file mode 100644 index 0bdbe08ab4f..00000000000 --- a/tests/target/configs/normalize_comments/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: true -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -// sit amet: -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/target/configs/reorder_extern_crates/false.rs b/tests/target/configs/reorder_extern_crates/false.rs deleted file mode 100644 index 6bef132e5c3..00000000000 --- a/tests/target/configs/reorder_extern_crates/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: false - -extern crate foo; -extern crate bar; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/tests/target/configs/reorder_extern_crates/true.rs b/tests/target/configs/reorder_extern_crates/true.rs deleted file mode 100644 index 86aba38b5d1..00000000000 --- a/tests/target/configs/reorder_extern_crates/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: true - -extern crate bar; -extern crate foo; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/tests/target/configs/reorder_imported_names/false.rs b/tests/target/configs/reorder_imported_names/false.rs deleted file mode 100644 index 91db89ceeaa..00000000000 --- a/tests/target/configs/reorder_imported_names/false.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: false -// Reorder imported names - -use super::{lorem, ipsum, dolor, sit}; diff --git a/tests/target/configs/reorder_imported_names/true.rs b/tests/target/configs/reorder_imported_names/true.rs deleted file mode 100644 index 59f55f4718a..00000000000 --- a/tests/target/configs/reorder_imported_names/true.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: true -// Reorder imported names - -use super::{dolor, ipsum, lorem, sit}; diff --git a/tests/target/configs/reorder_imports/false.rs b/tests/target/configs/reorder_imports/false.rs deleted file mode 100644 index 4b85684dc01..00000000000 --- a/tests/target/configs/reorder_imports/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_imports: false -// Reorder imports - -use lorem; -use ipsum; -use dolor; -use sit; diff --git a/tests/target/configs/reorder_imports/true.rs b/tests/target/configs/reorder_imports/true.rs deleted file mode 100644 index e4ff7295fd0..00000000000 --- a/tests/target/configs/reorder_imports/true.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-reorder_imports: true -// Reorder imports - -use dolor; -use ipsum; -use lorem; -use sit; - -fn foo() { - use A; - use B; - use C; - - bar(); - - use D; - use E; - use F; -} diff --git a/tests/target/configs/reorder_imports_in_group/false.rs b/tests/target/configs/reorder_imports_in_group/false.rs deleted file mode 100644 index 29460da50aa..00000000000 --- a/tests/target/configs/reorder_imports_in_group/false.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: false -// Reorder imports in group - -use dolor; -/// This comment should stay with `use ipsum;` -use ipsum; -use lorem; -use sit; -use std::io; -/// This comment should stay with `use std::mem;` -use std::mem; diff --git a/tests/target/configs/reorder_imports_in_group/true.rs b/tests/target/configs/reorder_imports_in_group/true.rs deleted file mode 100644 index c5e353662b5..00000000000 --- a/tests/target/configs/reorder_imports_in_group/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: true -// Reorder imports in group - -use std::io; -/// This comment should stay with `use std::mem;` -use std::mem; - -use dolor; -/// This comment should stay with `use ipsum;` -use ipsum; -use lorem; -use sit; diff --git a/tests/target/configs/reorder_modules/dolor/mod.rs b/tests/target/configs/reorder_modules/dolor/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/target/configs/reorder_modules/dolor/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/target/configs/reorder_modules/false.rs b/tests/target/configs/reorder_modules/false.rs deleted file mode 100644 index 56b1aa03ed7..00000000000 --- a/tests/target/configs/reorder_modules/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: false -// Reorder modules - -mod lorem; -mod ipsum; -mod dolor; -mod sit; diff --git a/tests/target/configs/reorder_modules/ipsum/mod.rs b/tests/target/configs/reorder_modules/ipsum/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/target/configs/reorder_modules/ipsum/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/target/configs/reorder_modules/lorem/mod.rs b/tests/target/configs/reorder_modules/lorem/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/target/configs/reorder_modules/lorem/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/target/configs/reorder_modules/sit/mod.rs b/tests/target/configs/reorder_modules/sit/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/target/configs/reorder_modules/sit/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/target/configs/reorder_modules/true.rs b/tests/target/configs/reorder_modules/true.rs deleted file mode 100644 index 18361e88b5f..00000000000 --- a/tests/target/configs/reorder_modules/true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: true -// Reorder modules - -mod dolor; -mod ipsum; -mod lorem; -mod sit; diff --git a/tests/target/configs/space_before_colon/true.rs b/tests/target/configs/space_before_colon/true.rs deleted file mode 100644 index e2895b5d77b..00000000000 --- a/tests/target/configs/space_before_colon/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-space_before_colon: true -// Space before colon - -fn lorem(t : T) { - let ipsum : Dolor = sit; -} - -const LOREM : Lorem = Lorem { - ipsum : dolor, - sit : amet, -}; diff --git a/tests/target/configs/spaces_around_ranges/false.rs b/tests/target/configs/spaces_around_ranges/false.rs deleted file mode 100644 index 6319da98572..00000000000 --- a/tests/target/configs/spaces_around_ranges/false.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: false -// Spaces around ranges - -fn main() { - let lorem = 0..10; - let ipsum = 0..=10; - - match lorem { - 1..5 => foo(), - _ => bar, - } - - match lorem { - 1..=5 => foo(), - _ => bar, - } - - match lorem { - 1...5 => foo(), - _ => bar, - } -} diff --git a/tests/target/configs/spaces_around_ranges/true.rs b/tests/target/configs/spaces_around_ranges/true.rs deleted file mode 100644 index 7bfcc23c8ea..00000000000 --- a/tests/target/configs/spaces_around_ranges/true.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: true -// Spaces around ranges - -fn main() { - let lorem = 0 .. 10; - let ipsum = 0 ..= 10; - - match lorem { - 1 .. 5 => foo(), - _ => bar, - } - - match lorem { - 1 ..= 5 => foo(), - _ => bar, - } - - match lorem { - 1 ... 5 => foo(), - _ => bar, - } -} diff --git a/tests/target/configs/spaces_within_parens_and_brackets/false.rs b/tests/target/configs/spaces_within_parens_and_brackets/false.rs deleted file mode 100644 index 908373ca9b0..00000000000 --- a/tests/target/configs/spaces_within_parens_and_brackets/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: false -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} diff --git a/tests/target/configs/spaces_within_parens_and_brackets/true.rs b/tests/target/configs/spaces_within_parens_and_brackets/true.rs deleted file mode 100644 index 7aff7131506..00000000000 --- a/tests/target/configs/spaces_within_parens_and_brackets/true.rs +++ /dev/null @@ -1,145 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: true -// Spaces within parens and brackets - -fn lorem< T: Eq >( t: T ) { - let lorem = ( ipsum, dolor ); - let lorem: [ usize; 2 ] = [ ipsum, dolor ]; -} - -enum E { - A( u32 ), - B( u32, u32 ), - C( u32, u32, u32 ), - D(), -} - -struct TupleStruct0(); -struct TupleStruct1( u32 ); -struct TupleStruct2( u32, u32 ); - -fn fooEmpty() {} - -fn foo( e: E, _: u32 ) -> ( u32, u32 ) { - // Tuples - let t1 = (); - let t2 = ( 1, ); - let t3 = ( 1, 2 ); - - let ts0 = TupleStruct0(); - let ts1 = TupleStruct1( 1 ); - let ts2 = TupleStruct2( 1, 2 ); - - // Tuple pattern - let ( a, b, c ) = ( 1, 2, 3 ); - - // Expressions - let x = ( 1 + 2 ) * ( 3 ); - - // Function call - fooEmpty(); - foo( 1, 2 ); - - // Pattern matching - match e { - A( _ ) => (), - B( _, _ ) => (), - C( .. ) => (), - D => (), - } - - ( 1, 2 ) -} - -struct Foo< T > { - i: T, -} - -struct Bar< T, E > { - i: T, - e: E, -} - -struct Foo< 'a > { - i: &'a str, -} - -enum E< T > { - T( T ), -} - -enum E< T, S > { - T( T ), - S( S ), -} - -fn foo< T >( a: T ) { - foo::< u32 >( 10 ); -} - -fn foo< T, E >( a: T, b: E ) { - foo::< u32, str >( 10, "bar" ); -} - -fn foo< T: Send, E: Send >( a: T, b: E ) { - foo::< u32, str >( 10, "bar" ); - - let opt: Option< u32 >; - let res: Result< u32, String >; -} - -fn foo< 'a >( a: &'a str ) { - foo( "foo" ); -} - -fn foo< 'a, 'b >( a: &'a str, b: &'b str ) { - foo( "foo", "bar" ); -} - -impl Foo { - fn bar() { - < Foo as Foo >::bar(); - } -} - -trait MyTrait< A, D > {} -impl< A: Send, D: Send > MyTrait< A, D > for Foo {} - -fn foo() -where - for< 'a > u32: 'a, -{ -} - -fn main() { - let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; - let arr: [ i32; 500 ] = [ 0; 500 ]; - - let v = vec![ 1, 2, 3 ]; - assert_eq!( arr, [ 1, 2, 3 ] ); - - let i = arr[ 0 ]; - - let slice = &arr[ 1..2 ]; - - let line100_________________________________________________________________________ = [ 1, 2 ]; - let line101__________________________________________________________________________ = - [ 1, 2 ]; - let line102___________________________________________________________________________ = - [ 1, 2 ]; - let line103____________________________________________________________________________ = - [ 1, 2 ]; - let line104_____________________________________________________________________________ = - [ 1, 2 ]; - - let line100_____________________________________________________________________ = vec![ 1, 2 ]; - let line101______________________________________________________________________ = - vec![ 1, 2 ]; - let line102_______________________________________________________________________ = - vec![ 1, 2 ]; - let line103________________________________________________________________________ = - vec![ 1, 2 ]; - let line104_________________________________________________________________________ = - vec![ 1, 2 ]; -} - -fn f( slice: &[ i32 ] ) {} diff --git a/tests/target/configs/struct_field_align_threshold/20.rs b/tests/target/configs/struct_field_align_threshold/20.rs deleted file mode 100644 index b84afc56835..00000000000 --- a/tests/target/configs/struct_field_align_threshold/20.rs +++ /dev/null @@ -1,467 +0,0 @@ -// rustfmt-struct_field_align_threshold: 20 -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false - -struct Foo { - x: u32, - yy: u32, // comment - zzz: u32, -} - -pub struct Bar { - x: u32, - yy: u32, - zzz: u32, - - xxxxxxx: u32, -} - -fn main() { - let foo = Foo { - x: 0, - yy: 1, - zzz: 2, - }; - - let bar = Bar { - x: 0, - yy: 1, - zzz: 2, - - xxxxxxx: 3, - }; -} - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField, -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] // only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct NewInt( - pub i32, - SomeType, // inline comment - T, // sup -); - -struct Qux< - 'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy, ->( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple( - // Comment 1 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - c: C, // Comment C -} - -struct Baz { - a: A, - - b: B, - c: C, - - d: D, -} - -struct Baz { - // Comment A - a: A, - - // Comment B - b: B, - // Comment C - c: C, -} - -// Will this be a one-liner? -struct Tuple( - A, // Comment - B, -); - -pub struct State time::Timespec> { - now: F, -} - -pub struct State ()> { - now: F, -} - -pub struct State { - now: F, -} - -struct Palette { - /// A map of indices in the palette to a count of pixels in approximately - /// that color - foo: i32, -} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ - // Another pre comment - #[attr1] - #[attr2] - pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC - * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(T); -struct Foo(T) -where - T: Copy, - T: Eq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -); -struct Foo( - TTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU, // Bar - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU, -); - -mod m { - struct X - where - T: Sized, - { - a: T, - } -} - -struct Foo( - TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU, -); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - -struct Foo {} -struct Foo {} -struct Foo { - // comment -} -struct Foo { - // trailing space -> -} -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: f(), - b: b(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a: Bar, b: f() }; - - Quux { - x: if cond { - bar(); - }, - y: baz(), - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { - // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, - } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { - memb: T, - } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S { a: 0, ..b }; -} - -fn issue201_2() { - let s = S { a: S2 { ..c }, ..b }; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo { a: 1, b: f(2) }; - Foo { - a: 1, - b: f(2), - ..g(3) - }; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { - ..base - }; - IntrinsicISizesContribution { - content_intrinsic_sizes: IntrinsicISizes { - minimum_inline_size: 0, - }, - }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { - a: bb, - c: dd, - e: ff, - }; - - Foo { - a: ddddddddddddddddddddd, - b: cccccccccccccccccccccccccccccccccccccc, - }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { - a: aaaaaaaaaa, - b: bbbbbbbb, - c: cccccccccc, - d: dddddddddd, // a comment - e: eeeeeeeee, - }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, ..base }; - Foo { - aaaaaaaaaa, - bbbbbbbb, - cccccccccc, - dddddddddd, // a comment - eeeeeeeee, - }; - Record { - ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; -} diff --git a/tests/target/configs/struct_lit_single_line/false.rs b/tests/target/configs/struct_lit_single_line/false.rs deleted file mode 100644 index e2732b5a7c9..00000000000 --- a/tests/target/configs/struct_lit_single_line/false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-struct_lit_single_line: false -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { - ipsum: dolor, - sit: amet, - }; -} diff --git a/tests/target/configs/tab_spaces/2.rs b/tests/target/configs/tab_spaces/2.rs deleted file mode 100644 index 85961706ea7..00000000000 --- a/tests/target/configs/tab_spaces/2.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-tab_spaces: 2 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { - let ipsum = dolor(); - let sit = vec![ - "amet", - "consectetur", - "adipiscing", - "elit.", - ]; -} diff --git a/tests/target/configs/tab_spaces/4.rs b/tests/target/configs/tab_spaces/4.rs deleted file mode 100644 index 524a55121e4..00000000000 --- a/tests/target/configs/tab_spaces/4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-tab_spaces: 4 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { - let ipsum = dolor(); - let sit = vec![ - "amet", - "consectetur", - "adipiscing", - "elit.", - ]; -} diff --git a/tests/target/configs/trailing_comma/always.rs b/tests/target/configs/trailing_comma/always.rs deleted file mode 100644 index 951dc680912..00000000000 --- a/tests/target/configs/trailing_comma/always.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-trailing_comma: Always -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { - ipsum, - dolor, - sit, - amet, - consectetur, - adipiscing, - } = elit; -} diff --git a/tests/target/configs/trailing_comma/never.rs b/tests/target/configs/trailing_comma/never.rs deleted file mode 100644 index ae0e50f96d1..00000000000 --- a/tests/target/configs/trailing_comma/never.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-trailing_comma: Never -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit } = amet; - let Lorem { - ipsum, - dolor, - sit, - amet, - consectetur, - adipiscing - } = elit; - - // #1544 - if let VrMsg::ClientReply { - request_num: reply_req_num, - value, - .. - } = msg - { - let _ = safe_assert_eq!(reply_req_num, request_num, op); - return Ok((request_num, op, value)); - } - - // #1710 - pub struct FileInput { - input: StringInput, - file_name: OsString - } - match len { - Some(len) => Ok(new(self.input, self.pos + len)), - None => Err(self) - } -} diff --git a/tests/target/configs/trailing_comma/vertical.rs b/tests/target/configs/trailing_comma/vertical.rs deleted file mode 100644 index 7283cde8d06..00000000000 --- a/tests/target/configs/trailing_comma/vertical.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-trailing_comma: Vertical -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit } = amet; - let Lorem { - ipsum, - dolor, - sit, - amet, - consectetur, - adipiscing, - } = elit; -} diff --git a/tests/target/configs/trailing_semicolon/false.rs b/tests/target/configs/trailing_semicolon/false.rs deleted file mode 100644 index 9fa746e9c0f..00000000000 --- a/tests/target/configs/trailing_semicolon/false.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-trailing_semicolon: false - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b - } - - let x = loop { - break 5 - }; - - let x = 'c: loop { - break 'c 5 - }; -} - -fn foo() -> usize { - return 0 -} diff --git a/tests/target/configs/trailing_semicolon/true.rs b/tests/target/configs/trailing_semicolon/true.rs deleted file mode 100644 index 61b6843d677..00000000000 --- a/tests/target/configs/trailing_semicolon/true.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-trailing_semicolon: true - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a; - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b; - } - - let x = loop { - break 5; - }; - - let x = 'c: loop { - break 'c 5; - }; -} - -fn foo() -> usize { - return 0; -} diff --git a/tests/target/configs/type_punctuation_density/compressed.rs b/tests/target/configs/type_punctuation_density/compressed.rs deleted file mode 100644 index 4b3e02e19ea..00000000000 --- a/tests/target/configs/type_punctuation_density/compressed.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed -// Type punctuation density - -fn lorem() { - // body -} diff --git a/tests/target/configs/type_punctuation_density/wide.rs b/tests/target/configs/type_punctuation_density/wide.rs deleted file mode 100644 index 8909036e688..00000000000 --- a/tests/target/configs/type_punctuation_density/wide.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-type_punctuation_density: Wide -// Type punctuation density - -fn lorem() { - // body -} diff --git a/tests/target/configs/use_field_init_shorthand/false.rs b/tests/target/configs/use_field_init_shorthand/false.rs deleted file mode 100644 index dcebe0b6f1d..00000000000 --- a/tests/target/configs/use_field_init_shorthand/false.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-use_field_init_shorthand: false -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { x: x, y: y, z: z }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/tests/target/configs/use_field_init_shorthand/true.rs b/tests/target/configs/use_field_init_shorthand/true.rs deleted file mode 100644 index ad78093ee8e..00000000000 --- a/tests/target/configs/use_field_init_shorthand/true.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-use_field_init_shorthand: true -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { x, y, z }; - - let b = Bar { - x, - y, - #[attr] - z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/tests/target/configs/use_try_shorthand/false.rs b/tests/target/configs/use_try_shorthand/false.rs deleted file mode 100644 index de7f8b4a5e2..00000000000 --- a/tests/target/configs/use_try_shorthand/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: false -// Use try! shorthand - -fn main() { - let lorem = try!(ipsum.map(|dolor| dolor.sit())); -} diff --git a/tests/target/configs/use_try_shorthand/true.rs b/tests/target/configs/use_try_shorthand/true.rs deleted file mode 100644 index d3aa035792c..00000000000 --- a/tests/target/configs/use_try_shorthand/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: true -// Use try! shorthand - -fn main() { - let lorem = ipsum.map(|dolor| dolor.sit())?; -} diff --git a/tests/target/configs/where_single_line/true.rs b/tests/target/configs/where_single_line/true.rs deleted file mode 100644 index c4a7f5d3802..00000000000 --- a/tests/target/configs/where_single_line/true.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-where_single_line: true -// Where style - -fn lorem_two_items() -> T -where - Ipsum: Eq, - Lorem: Eq, -{ - // body -} - -fn lorem_multi_line( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) -> T -where - Ipsum: Eq, -{ - // body -} - -fn lorem() -> T -where Ipsum: Eq { - // body -} diff --git a/tests/target/configs/wrap_comments/false.rs b/tests/target/configs/wrap_comments/false.rs deleted file mode 100644 index 48ecd88accb..00000000000 --- a/tests/target/configs/wrap_comments/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-wrap_comments: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -} diff --git a/tests/target/configs/wrap_comments/true.rs b/tests/target/configs/wrap_comments/true.rs deleted file mode 100644 index 4096fd4d89d..00000000000 --- a/tests/target/configs/wrap_comments/true.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 50 -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur - // adipiscing elit, sed do eiusmod tempor - // incididunt ut labore et dolore magna - // aliqua. Ut enim ad minim veniam, quis - // nostrud exercitation ullamco laboris nisi - // ut aliquip ex ea commodo consequat. -} - -fn code_block() { - // ```rust - // let x = 3; - // - // println!("x = {}", x); - // ``` -} diff --git a/tests/target/control-brace-style-always-next-line.rs b/tests/target/control-brace-style-always-next-line.rs deleted file mode 100644 index 054a3075ca0..00000000000 --- a/tests/target/control-brace-style-always-next-line.rs +++ /dev/null @@ -1,50 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - loop - { - (); - (); - } - - 'label: loop - // loop comment - { - (); - } - - cond = true; - while cond - { - (); - } - - 'while_label: while cond - { - // while comment - (); - } - - for obj in iter - { - for sub_obj in obj - { - 'nested_while_label: while cond - { - (); - } - } - } - - match some_var - { - // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => - { - do_stuff(); - val2 - } - }; -} diff --git a/tests/target/control-brace-style-always-same-line.rs b/tests/target/control-brace-style-always-same-line.rs deleted file mode 100644 index ae6bf4a5682..00000000000 --- a/tests/target/control-brace-style-always-same-line.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - loop { - (); - (); - } - - 'label: loop - // loop comment - { - (); - } - - cond = true; - while cond { - (); - } - - 'while_label: while cond { - // while comment - (); - } - - for obj in iter { - for sub_obj in obj { - 'nested_while_label: while cond { - (); - } - } - } - - match some_var { - // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => { - do_stuff(); - val2 - } - }; -} diff --git a/tests/target/doc.rs b/tests/target/doc.rs deleted file mode 100644 index 99d2ae7873f..00000000000 --- a/tests/target/doc.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true - -// sadfsdfa -// sdffsdfasdf diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs deleted file mode 100644 index 31e12cfa0d0..00000000000 --- a/tests/target/else-if-brace-style-always-next-line.rs +++ /dev/null @@ -1,53 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - if false - { - (); - (); - } - - if false - // lone if comment - { - (); - (); - } - - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - - if true - { - (); - } - else if false - { - (); - (); - } - else - { - (); - (); - (); - } - - if true - // else-if-chain if comment - { - (); - } - else if false - // else-if-chain else-if comment - { - (); - (); - } - else - // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs deleted file mode 100644 index 5e5ab21a0d8..00000000000 --- a/tests/target/else-if-brace-style-always-same-line.rs +++ /dev/null @@ -1,45 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - if false { - (); - (); - } - - if false - // lone if comment - { - (); - (); - } - - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - - if true { - (); - } else if false { - (); - (); - } else { - (); - (); - (); - } - - if true - // else-if-chain if comment - { - (); - } else if false - // else-if-chain else-if comment - { - (); - (); - } else - // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs deleted file mode 100644 index c99807dc06d..00000000000 --- a/tests/target/else-if-brace-style-closing-next-line.rs +++ /dev/null @@ -1,49 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine - -fn main() { - if false { - (); - (); - } - - if false - // lone if comment - { - (); - (); - } - - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - - if true { - (); - } - else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true - // else-if-chain if comment - { - (); - } - else if false - // else-if-chain else-if comment - { - (); - (); - } - else - // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs deleted file mode 100644 index 0b9a15e8a92..00000000000 --- a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs +++ /dev/null @@ -1,12 +0,0 @@ -enum TestEnum { - Arm1(), - Arm2, -} - -fn foo() { - let test = TestEnum::Arm1; - match test { - TestEnum::Arm1() => {} - TestEnum::Arm2 => {} - } -} diff --git a/tests/target/empty_file.rs b/tests/target/empty_file.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/tests/target/empty_file.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/target/enum.rs b/tests/target/enum.rs deleted file mode 100644 index de88f610b6a..00000000000 --- a/tests/target/enum.rs +++ /dev/null @@ -1,255 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Enums test - -#[atrr] -pub enum Test { - A, - B(u32, A /* comment */, SomeType), - /// Doc comment - C, -} - -pub enum Foo<'a, Y: Baz> -where - X: Whatever, -{ - A, -} - -enum EmtpyWithComment { - // Some comment -} - -// C-style enum -enum Bar { - A = 1, - #[someAttr(test)] - B = 2, // comment - C, -} - -enum LongVariants { - First( - LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment - VARIANT, - ), - // This is the second variant - Second, -} - -enum StructLikeVariants { - Normal(u32, String), - StructLike { - x: i32, // Test comment - // Pre-comment - #[Attr50] - y: SomeType, // Aanother Comment - }, - SL { - a: A, - }, -} - -enum X { - CreateWebGLPaintTask( - Size2D, - GLContextAttributes, - IpcSender, usize), String>>, - ), // This is a post comment -} - -pub enum EnumWithAttributes { - //This is a pre comment - // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ - // Pre Comment - #[rustfmt_skip] - SkippedItem(String,String,), // Post-comment - #[another_attr] - #[attr2] - ItemStruct { - x: usize, - y: usize, - }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ - // And another - ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ -} - -pub enum SingleTuple { - // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - Match(usize, usize, String), /* Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ -} - -pub enum SingleStruct { - Match { name: String, loc: usize }, // Post-comment -} - -pub enum GenericEnum -where - I: Iterator, -{ - // Pre Comment - Left { list: I, root: T }, // Post-comment - Right { list: I, root: T }, // Post Comment -} - -enum EmtpyWithComment { - // Some comment -} - -enum TestFormatFails { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -fn nested_enum_test() { - if true { - enum TestEnum { - One( - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - ), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAA */ - Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAA */ - } - enum TestNestedFormatFail { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - } - } -} - -pub struct EmtpyWithComment { - // FIXME: Implement this struct -} - -// #1115 -pub enum Bencoding<'i> { - Str(&'i [u8]), - Int(i64), - List(Vec>), - /// A bencoded dict value. The first element the slice of bytes in the source that the dict is - /// composed of. The second is the dict, decoded into an ordered map. - // TODO make Dict "structlike" AKA name the two values. - Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), -} - -// #1261 -pub enum CoreResourceMsg { - SetCookieForUrl( - ServoUrl, - #[serde(deserialize_with = "::hyper_serde::deserialize", - serialize_with = "::hyper_serde::serialize")] - Cookie, - CookieSource, - ), -} - -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{ - Foo, -} - -// #1046 -pub enum Entry<'a, K: 'a, V: 'a> { - Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), - Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), -} - -// #2081 -pub enum ForegroundColor { - CYAN = - (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, -} - -// #2098 -pub enum E<'a> { - V( as Iterator>::Item), -} - -// #1809 -enum State { - TryRecv { - pos: usize, - lap: u8, - closed_count: usize, - }, - Subscribe { - pos: usize, - }, - IsReady { - pos: usize, - ready: bool, - }, - Unsubscribe { - pos: usize, - lap: u8, - id_woken: usize, - }, - FinalTryRecv { - pos: usize, - id_woken: usize, - }, - TimedOut, - Disconnected, -} - -// #2190 -#[derive(Debug, Fail)] -enum AnError { - #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - UnexpectedSingleToken { token: syn::Token }, -} - -// #2193 -enum WidthOf101 { - #[fail(display = ".....................................................")] - Io(::std::io::Error), - #[fail(display = ".....................................................")] - Ioo(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ::std::io::Error, - ), -} - -// #2389 -pub enum QlError { - #[fail(display = "Parsing error: {}", 0)] - LexError(parser::lexer::LexError), - #[fail(display = "Parsing error: {:?}", 0)] - ParseError(parser::ParseError), - #[fail(display = "Validation error: {:?}", 0)] - ValidationError(Vec), - #[fail(display = "Execution error: {}", 0)] - ExecutionError(String), - // (from, to) - #[fail(display = "Translation error: from {} to {}", 0, 1)] - TranslationError(String, String), - // (kind, input, expected) - #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] - ResolveError(&'static str, String, Option), -} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs deleted file mode 100644 index 277990c5a60..00000000000 --- a/tests/target/expr-block.rs +++ /dev/null @@ -1,299 +0,0 @@ -// rustfmt-indent_style: Block -// Test expressions with block formatting. - -fn arrays() { - []; - let empty = []; - - let foo = [a_long_name, a_very_lng_name, a_long_name]; - - let foo = [ - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - ]; - - vec![ - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_very_lng_name, - ]; - - [ - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_very_lng_name, - ] -} - -fn arrays() { - let x = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 0, - ]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ - strukt { - test123: value_one_two_three_four, - turbo: coolio(), - }, - /* comment */ 1, - ]; - - let a = WeightedChoice::new(&mut [ - Weighted { weight: x, item: 0 }, - Weighted { weight: 1, item: 1 }, - Weighted { weight: x, item: 2 }, - Weighted { weight: 1, item: 3 }, - ]); - - let z = [ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzz, - q, - ]; - - [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] -} - -fn function_calls() { - let items = itemize_list( - context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite( - context, - Shape { - width: remaining_width, - ..nested_shape - }, - ) - }, - span.lo(), - span.hi(), - ); - - itemize_list( - context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite( - context, - Shape { - width: remaining_width, - ..nested_shape - }, - ) - }, - span.lo(), - span.hi(), - ) -} - -fn macros() { - baz!( - do_not, - add, - trailing, - commas, - inside, - of, - function, - like, - macros, - even, - if_they, - are, - long - ); - - baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); - - let _ = match option { - None => baz!( - function, - like, - macro_as, - expression, - which, - is, - loooooooooooooooong - ), - Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), - }; -} - -fn issue_1450() { - if selfstate - .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( - STATE_PARKED, - STATE_UNPARKED, - Release, - Relaxed, - Release, - Relaxed, - ) - .is_ok() - { - return; - } -} - -fn foo() { - if real_total <= limit && !pre_line_comments - && !items.into_iter().any(|item| item.as_ref().is_multiline()) - { - DefinitiveListTactic::Horizontal - } -} - -fn combine_block() { - foo(Bar { - x: value, - y: value2, - }); - - foo((Bar { - x: value, - y: value2, - },)); - - foo(( - 1, - 2, - 3, - Bar { - x: value, - y: value2, - }, - )); - - foo((1, 2, 3, |x| { - let y = x + 1; - let z = y + 1; - z - })); - - let opt = Some(Struct( - long_argument_one, - long_argument_two, - long_argggggggg, - )); - - do_thing(|param| { - action(); - foo(param) - }); - - do_thing(x, |param| { - action(); - foo(param) - }); - - do_thing( - x, - (1, 2, 3, |param| { - action(); - foo(param) - }), - ); - - Ok(some_function( - lllllllllong_argument_one, - lllllllllong_argument_two, - lllllllllllllllllllllllllllllong_argument_three, - )); - - foo( - thing, - bar( - param2, - pparam1param1param1param1param1param1param1param1param1param1aram1, - param3, - ), - ); - - foo.map_or(|| { - Ok(SomeStruct { - f1: 0, - f2: 0, - f3: 0, - }) - }); - - match opt { - Some(x) => somefunc(anotherfunc( - long_argument_one, - long_argument_two, - long_argument_three, - )), - Some(x) => |x| { - let y = x + 1; - let z = y + 1; - z - }, - Some(x) => (1, 2, |x| { - let y = x + 1; - let z = y + 1; - z - }), - Some(x) => SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }, - None => Ok(SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }), - }; - - match x { - y => func(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), - _ => func( - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzz, - ), - } -} - -fn issue_1862() { - foo( - /* bar = */ None, - something_something, - /* baz = */ None, - /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ - None, - /* com */ - this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, - ) -} - -fn issue_1878() { - let channel: &str = seq.next_element()? - .ok_or_else(|| de::Error::invalid_length(2, &self))?; -} diff --git a/tests/target/expr.rs b/tests/target/expr.rs deleted file mode 100644 index 3c5d85b7d76..00000000000 --- a/tests/target/expr.rs +++ /dev/null @@ -1,397 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// Test expressions - -fn foo() -> bool { - let boxed: Box = box 5; - let referenced = &5; - - let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = - (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - - let is_internalxxxx = - self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); - - let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb - / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; - - some_ridiculously_loooooooooooooooooooooong_function( - 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), - trivial_value, - ); - (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + a - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaa))))))))); - - { - for _ in 0..10 {} - } - - { - { - { - {} - } - } - } - - if 1 + 2 > 0 { - let result = 5; - result - } else { - 4 - }; - - if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { - // Nothing - } - - if let Some(x) = - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) - {} - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1 + 2 + 3 - {} - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1111 + 2222 - {} - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1 + 2 + 3 - {} - - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node - { - // nothing - } - - let test = if true { 5 } else { 3 }; - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - // Check subformatting - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } -} - -fn bar() { - let range = - (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + 2333333333333333); - - let another_range = 5..some_func(a, b /* comment */); - - for _ in 1.. { - call_forever(); - } - - syntactically_correct( - loop { - sup('?'); - }, - if cond { 0 } else { 1 }, - ); - - let third = ..10; - let infi_range = ..; - let foo = 1..; - let bar = 5; - let nonsense = (10..0)..(0..10); - - loop { - if true { - break; - } - } - - let x = ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - a, - ); -} - -fn baz() { - unsafe /* {}{}{}{{{{}} */ { - let foo = 1u32; - } - - unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong - * comment */ { - } - - unsafe /* So this is a very long comment. - * Multi-line, too. - * Will it still format correctly? */ { - } - - unsafe { - // Regular unsafe block - } - - unsafe { foo() } - - unsafe { - foo(); - } - - // #2289 - let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; - let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; - let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; - let identifier_3 = - unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; -} - -// Test some empty blocks. -fn qux() { - {} - // FIXME this one could be done better. - { /* a block with a comment */ } - {} - { - // A block with a comment. - } -} - -fn issue227() { - { - let handler = - box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - -fn issue184(source: &str) { - for c in source.chars() { - if index < 'a' { - continue; - } - } -} - -fn arrays() { - let x = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 0, - ]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ - strukt { - test123: value_one_two_three_four, - turbo: coolio(), - }, - // comment - 1, - ]; - - let a = WeightedChoice::new(&mut [ - Weighted { - weightweight: x, - item: 0, - }, - Weighted { - weightweight: 1, - item: 1, - }, - Weighted { - weightweight: x, - item: 2, - }, - Weighted { - weightweight: 1, - item: 3, - }, - ]); - - let z = [ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q, - ]; - - [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] -} - -fn returns() { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - && return; - - return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -} - -fn addrof() { - &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); - &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); -} - -fn casts() { - fn unpack(packed: u32) -> [u16; 2] { - [(packed >> 16) as u16, (packed >> 0) as u16] - } - - let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - let slightly_longer_trait = - yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; -} - -fn indices() { - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) - [x + y + z]; - let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) - [xxxxx + yyyyy + zzzzz]; - let z = xxxxxxxxxx - .x() - .y() - .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; - let z = xxxxxxxxxx - .x() - .y() - .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz() - [aaaaa]; -} - -fn repeats() { - let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; - x + y + z]; - let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; - xxxxx + yyyyy + zzzzz]; -} - -fn blocks() { - if 1 + 1 == 2 { - println!("yay arithmetix!"); - }; -} - -fn issue767() { - if false { - if false { - } else { - // A let binding here seems necessary to trigger it. - let _ = (); - } - } else if let false = false { - } -} - -fn ranges() { - let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let y = - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let z = ..=x; - - // #1766 - let x = [0. ..10.0]; - let x = [0. ..=10.0]; - - a..=b - - // the expr below won't compile because inclusive ranges need a defined end - // let a = 0 ..= ; -} - -fn if_else() { - let exact = diff / (if size == 0 { 1 } else { size }); - - let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; -} - -fn complex_if_else() { - if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { - yo(); - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx - { - yo(); - } -} - -fn issue1106() { - { - if let hir::ItemEnum(ref enum_def, ref generics) = - self.ast_map.expect_item(enum_node_id).node - {} - } - - for entry in WalkDir::new(path) - .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) - {} -} - -fn issue1570() { - a_very_long_function_name({ some_func(1, { 1 }) }) -} - -fn issue1714() { - v = &mut { v }[mid..]; - let (left, right) = { v }.split_at_mut(mid); -} - -// Multi-lined index should be put on the next line if it fits in one line. -fn issue1749() { - { - { - { - if self.shape[(r as f32 + self.x_offset) as usize] - [(c as f32 + self.y_offset) as usize] != 0 - { - // hello - } - } - } - } -} - -// #1172 -fn newlines_between_list_like_expr() { - foo( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ); - - vec![ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ]; - - match x { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - | zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), - _ => bar(), - }; -} - -fn issue2178() { - Ok(result - .iter() - .map(|item| ls_util::rls_to_location(item)) - .collect()) -} diff --git a/tests/target/extern.rs b/tests/target/extern.rs deleted file mode 100644 index b0aa51127d5..00000000000 --- a/tests/target/extern.rs +++ /dev/null @@ -1,73 +0,0 @@ -// rustfmt-normalize_comments: true - -extern crate foo; -extern crate foo as bar; - -extern crate chrono; -extern crate dotenv; -extern crate futures; - -extern crate bar; -extern crate foo; - -// #2315 -extern crate proc_macro; -extern crate proc_macro2; - -extern "C" { - fn c_func(x: *mut *mut libc::c_void); - - fn c_func( - x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, - y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY, - ); - - #[test123] - fn foo() -> uint64_t; - - pub fn bar(); -} - -extern "C" { - fn DMR_GetDevice( - pHDev: *mut HDEV, - searchMode: DeviceSearchMode, - pSearchString: *const c_char, - devNr: c_uint, - wildcard: c_char, - ) -> TDMR_ERROR; - - fn quux() -> (); // Post comment - - pub type Foo; - - type Bar; -} - -extern "Rust" { - static ext: u32; - // Some comment. - pub static mut var: SomeType; -} - -extern "C" { - fn syscall( - number: libc::c_long, // comment 1 - // comm 2 - ... // sup? - ) -> libc::c_long; - - fn foo(x: *const c_char, ...) -> libc::c_long; -} - -extern "C" { - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE, - ) -> *mut FILE; -} - -extern "C" {} diff --git a/tests/target/extern_not_explicit.rs b/tests/target/extern_not_explicit.rs deleted file mode 100644 index b55b64d05b3..00000000000 --- a/tests/target/extern_not_explicit.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-force_explicit_abi: false - -extern { - fn some_fn() -> (); -} - -extern fn sup() {} - -type funky_func = extern fn( - unsafe extern "rust-call" fn( - *const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal, - ) -> u8, -); diff --git a/tests/target/file-lines-1.rs b/tests/target/file-lines-1.rs deleted file mode 100644 index 2601ca9fc94..00000000000 --- a/tests/target/file-lines-1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - }.method_call() - .method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/target/file-lines-2.rs b/tests/target/file-lines-2.rs deleted file mode 100644 index bc25698c2ed..00000000000 --- a/tests/target/file-lines-2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { val1 } else { val2 }.method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/target/file-lines-3.rs b/tests/target/file-lines-3.rs deleted file mode 100644 index fe465750ae1..00000000000 --- a/tests/target/file-lines-3.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] -// rustfmt-error_on_line_overflow: false - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - }.method_call() - .method_call(); - - let y = if cond { val1 } else { val2 }.method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/target/file-lines-4.rs b/tests/target/file-lines-4.rs deleted file mode 100644 index 83928bf6fec..00000000000 --- a/tests/target/file-lines-4.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-file_lines: [] -// (Test that nothing is formatted if an empty array is specified.) - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - // aaaaaaaaaaaaa - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/tests/target/file-lines-5.rs b/tests/target/file-lines-5.rs deleted file mode 100644 index 3966dc06303..00000000000 --- a/tests/target/file-lines-5.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] - -struct A { - t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - fn baz() { - let j = 15; - } -} diff --git a/tests/target/file-lines-6.rs b/tests/target/file-lines-6.rs deleted file mode 100644 index 8a092df869a..00000000000 --- a/tests/target/file-lines-6.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] - -struct A { - t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - - fn baz() { -/// - let j = 15; - } -} diff --git a/tests/target/file-lines-item.rs b/tests/target/file-lines-item.rs deleted file mode 100644 index e155e75f34c..00000000000 --- a/tests/target/file-lines-item.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] -// rustfmt-reorder_imports: true - -use foo::{c, b, a}; -use bar; - -fn foo() { - bar(); -} - -impl Drop for Context { - fn drop(&mut self) { - } -} - -impl Bar for Baz { - fn foo() { - bar( - baz, // Who knows? - ) - } -} diff --git a/tests/target/fn-args-with-last-line-comment.rs b/tests/target/fn-args-with-last-line-comment.rs deleted file mode 100644 index 27e0e09653e..00000000000 --- a/tests/target/fn-args-with-last-line-comment.rs +++ /dev/null @@ -1,24 +0,0 @@ -// #1587 -pub trait X { - fn a(&self) -> &'static str; - fn bcd( - &self, - c: &str, // comment on this arg - d: u16, // comment on this arg - e: &Vec, // comment on this arg - ) -> Box; -} - -// #1595 -fn foo( - arg1: LongTypeName, - arg2: LongTypeName, - arg3: LongTypeName, - arg4: LongTypeName, - arg5: LongTypeName, - arg6: LongTypeName, - arg7: LongTypeName, - //arg8: LongTypeName, -) { - // do stuff -} diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs deleted file mode 100644 index c2b3580c668..00000000000 --- a/tests/target/fn-custom-2.rs +++ /dev/null @@ -1,78 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) { - foo(); -} - -fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, ->( - a: Aaaaaaaaaaaaaaa, -) { - bar(); -} - -fn baz() -where - X: TTTTTTTT, -{ - baz(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -impl Foo { - fn foo( - self, - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, - ) { - foo(); - } - - fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, - >( - a: Aaaaaaaaaaaaaaa, - ) { - bar(); - } - - fn baz() - where - X: TTTTTTTT, - { - baz(); - } -} - -struct Foo< - TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUU, - VVVVVVVVVVVVVVVVVVVVVVVVVVV, - WWWWWWWWWWWWWWWWWWWWWWWW, -> { - foo: Foo, -} diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs deleted file mode 100644 index baa1e39231b..00000000000 --- a/tests/target/fn-custom-3.rs +++ /dev/null @@ -1,72 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) { - foo(); -} - -fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, ->( - a: Aaaaaaaaaaaaaaa, -) { - bar(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -impl Foo { - fn foo( - self, - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, - ) { - foo(); - } - - fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, - >( - a: Aaaaaaaaaaaaaaa, - ) { - bar(); - } -} - -struct Foo< - TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUU, - VVVVVVVVVVVVVVVVVVVVVVVVVVV, - WWWWWWWWWWWWWWWWWWWWWWWW, -> { - foo: Foo, -} diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs deleted file mode 100644 index 0a223ef5fac..00000000000 --- a/tests/target/fn-custom-4.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -fn qux(a: Aaaaaaaaaaaaaaaaa) -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs deleted file mode 100644 index 720d4288c41..00000000000 --- a/tests/target/fn-custom-6.rs +++ /dev/null @@ -1,72 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) where - T: UUUUUUUUUUU, { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String -where - T: UUUUUUUUUUU, { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs deleted file mode 100644 index ec113c30d53..00000000000 --- a/tests/target/fn-custom-7.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block -// rustfmt-fn_args_density: Vertical -// rustfmt-brace_style: AlwaysNextLine - -// Case with only one variable. -fn foo(a: u8) -> u8 -{ - bar() -} - -// Case with 2 variables and some pre-comments. -fn foo( - a: u8, // Comment 1 - b: u8, // Comment 2 -) -> u8 -{ - bar() -} - -// Case with 2 variables and some post-comments. -fn foo( - // Comment 1 - a: u8, - // Comment 2 - b: u8, -) -> u8 -{ - bar() -} - -trait Test -{ - fn foo(a: u8) - { - } - - fn bar(a: u8) -> String - { - } -} diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs deleted file mode 100644 index 290557b979d..00000000000 --- a/tests/target/fn-custom-8.rs +++ /dev/null @@ -1,78 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) where - T: UUUUUUUUUUU, { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String -where - T: UUUUUUUUUUU, { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} - - fn bar(a: u8) -> String - where - Foo: foooo, - Bar: barrr, { - } -} diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs deleted file mode 100644 index bf87553dedc..00000000000 --- a/tests/target/fn-custom.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Test some of the ways function signatures can be customised. - -// Test compressed layout of args. -fn foo( - a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) { - foo(); -} - -impl Foo { - fn foo( - self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee, - ) { - foo(); - } -} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs deleted file mode 100644 index 4e6e6493835..00000000000 --- a/tests/target/fn-simple.rs +++ /dev/null @@ -1,107 +0,0 @@ -// rustfmt-normalize_comments: true - -fn simple( - // pre-comment on a function!? - i: i32, // yes, it's possible! - response: NoWay, // hose -) { - fn op( - x: Typ, - key: &[u8], - upd: Box< - Fn(Option<&memcache::Item>) - -> (memcache::Status, Result>), - >, - ) -> MapResult { - } - - "cool" -} - -fn weird_comment( - // /*/ double level */ comment - x: Hello, // /*/* triple, even */*/ - // Does this work? - y: World, -) { - simple(/* does this preserve comments now? */ 42, NoWay) -} - -fn generic(arg: T) -> &SomeType -where - T: Fn( - // First arg - A, - // Second argument - B, - C, - D, - // pre comment - E, // last comment - ) -> &SomeType, -{ - arg(a, b, c, d, e) -} - -fn foo() -> ! {} - -pub fn http_fetch_async( - listener: Box, - script_chan: Box, -) { -} - -fn some_func>(val: T) {} - -fn zzzzzzzzzzzzzzzzzzzz( - selff: Type, - mut handle: node::Handle>, Type, NodeType>, -) -> SearchStack<'a, K, V, Type, NodeType> { -} - -unsafe fn generic_call( - cx: *mut JSContext, - argc: libc::c_uint, - vp: *mut JSVal, - is_lenient: bool, - call: unsafe extern "C" fn( - *const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal, - ) -> u8, -) { - let f: fn(_, _) -> _ = panic!(); -} - -pub fn start_export_thread( - database: &Database, - crypto_scheme: &C, - block_size: usize, - source_path: &Path, -) -> BonzoResult> { -} - -pub fn waltz(cwd: &Path) -> CliAssert { - { - { - formatted_comment = - rewrite_comment(comment, block_style, width, offset, formatting_fig); - } - } -} - -// #2003 -mod foo { - fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() - { - foo(); - } -} - -// #2082 -pub(crate) fn init() {} - -crate fn init() {} diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs deleted file mode 100644 index 3617506d89a..00000000000 --- a/tests/target/fn-single-line.rs +++ /dev/null @@ -1,70 +0,0 @@ -// rustfmt-fn_single_line: true -// Test single-line functions. - -fn foo_expr() { 1 } - -fn foo_stmt() { foo(); } - -fn foo_decl_local() { let z = 5; } - -fn foo_decl_item(x: &mut i32) { x = 3; } - -fn empty() {} - -fn foo_return() -> String { "yay" } - -fn foo_where() -> T -where - T: Sync, -{ - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space() { 1 } - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) {} -} - -trait CoolerTypes { - fn dummy(&self) {} -} - -fn Foo() -where - T: Bar, -{ -} diff --git a/tests/target/fn-ty.rs b/tests/target/fn-ty.rs deleted file mode 100644 index 7d48f3b32db..00000000000 --- a/tests/target/fn-ty.rs +++ /dev/null @@ -1,14 +0,0 @@ -fn f( - xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, - xxxxxxxxxxxxxxxxxx: fn() -> a, - xxxxxxxxxxxxxxxxxx: fn(a, b, b), - xxxxxxxxxxxxxxxxxx: fn(), - xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, - xxxxxxxxxxxxxxxxxx: fn() -> !, -) where - F1: Fn(a, b, b) -> a, - F2: Fn(a, b, b), - F3: Fn(), - F4: Fn() -> u32, -{ -} diff --git a/tests/target/fn.rs b/tests/target/fn.rs deleted file mode 100644 index b78a8b5b21e..00000000000 --- a/tests/target/fn.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Tests different fns - -fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} - -fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType -where - T: Blah, -{ -} - -fn foo(a: AAA /* (comment) */) -where - T: Blah, -{ -} - -fn foo( - a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -) -> RetType -where - T: Blah, -{ - -} - -fn foo( - a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -) -> RetType -where - T: Blah, - U: dsfasdfasdfasd, -{ - -} - -fn foo B /* paren inside generics */>() {} - -impl Foo { - fn with_no_errors(&mut self, f: F) -> T - where - F: FnOnce(&mut Resolver) -> T, - { - } - - fn foo(mut self, mut bar: u32) {} - - fn bar(self, mut bazz: u32) {} -} - -pub fn render< - 'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write, ->( - g: &'a G, - w: &mut W, -) -> io::Result<()> { - render_opts(g, w, &[]) -} - -const fn foo() { - x; -} - -pub const fn foo() { - x; -} - -impl Foo { - const fn foo() { - x; - } -} - -fn homura>(_: T) {} - -fn issue377() -> (Box, Box) {} - -fn main() { - let _ = function(move || 5); - let _ = move || 42; - let _ = || unsafe { abort() }; -} - -// With inner attributes. -fn inner() { - #![inline] - x -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -fn foo(a: i32) -> i32 { - // comment - if a > 0 { 1 } else { 2 } -} - -fn ______________________baz( - a: i32, -) -> *mut ::std::option::Option< - extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) -> (), -> { -} - -pub fn check_path<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - path: &hir::Path, - id: ast::NodeId, - cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), -) { -} - -pub fn check_path<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - path: &hir::Path, - id: ast::NodeId, - cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), -) { -} diff --git a/tests/target/fn_args_density-vertical.rs b/tests/target/fn_args_density-vertical.rs deleted file mode 100644 index 477a48cc35f..00000000000 --- a/tests/target/fn_args_density-vertical.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-fn_args_density: Vertical - -// Empty list should stay on one line. -fn do_bar() -> u8 { - bar() -} - -// A single argument should stay on the same line. -fn do_bar(a: u8) -> u8 { - bar() -} - -// Multiple arguments should each get their own line. -fn do_bar( - a: u8, - mut b: u8, - c: &u8, - d: &mut u8, - closure: &Fn(i32) -> i32, -) -> i32 { - // This feature should not affect closures. - let bar = |x: i32, y: i32| -> i32 { x + y }; - bar(a, b) -} - -// If the first argument doesn't fit on the same line with the function name, -// the whole list should probably be pushed to the next line with hanging -// indent. That's not what happens though, so check current behaviour instead. -// In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, - c: u8, - d: u8, -) { - this(); - that(); - the_other_thing(); -} diff --git a/tests/target/fn_args_indent-block.rs b/tests/target/fn_args_indent-block.rs deleted file mode 100644 index 04c18816d0b..00000000000 --- a/tests/target/fn_args_indent-block.rs +++ /dev/null @@ -1,144 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -fn foo( - a: u8, // Comment 1 - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, // Comment 2 -) -> u8 { - bar() -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String -where - X: Fooooo, - Y: Baaar, -{ - bar(); -} - -fn foo() -> T { - foo(); -} - -fn foo() -> T -where - X: Foooo, - Y: Baaar, -{ - foo(); -} - -fn foo() -where - X: Foooo, -{ -} - -fn foo() -where - X: Foooo, - Y: Baaar, -{ -} - -fn foo() -> ( - Loooooooooooooooooooooong, - Reeeeeeeeeeeeeeeeeeeeeeeeturn, - iiiiiiiiis, - Looooooooooooooooong, -) { - foo(); -} - -fn foo() { - foo(); -} - -fn foo< - L: Loooooooooooooooooooooong, - G: Geeeeeeeeeeeneric, - I: iiiiiiiiis, - L: Looooooooooooooooong, ->() { - foo(); -} - -fn foo() { - foo(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, - ) -> String { - } -} - -fn foo( - a: Aaaaaaaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, -) { - foo(); -} - -fn foo() -> ( - Looooooooooooooooooooooooooong, - Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, - iiiiiiiiiiiiiis, - Loooooooooooooooooooooong, -) { - foo(); -} diff --git a/tests/target/fn_once.rs b/tests/target/fn_once.rs deleted file mode 100644 index 42b8f98e78a..00000000000 --- a/tests/target/fn_once.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Add(usize); - -impl FnOnce<(usize,)> for Add { - type Output = Add; - extern "rust-call" fn call_once(self, to: (usize,)) -> Add { - Add(self.0 + to.0) - } -} diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs deleted file mode 100644 index 90be4d6b367..00000000000 --- a/tests/target/hard-tabs.rs +++ /dev/null @@ -1,99 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-hard_tabs: true -// rustfmt-error_on_line_overflow: false - -fn main() { - let x = Bar; - - let y = Foo { a: x }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) { - } - - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1 + 2 + 3 - {} - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } - - unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong - * comment */ { - } - - unsafe /* So this is a very long comment. - * Multi-line, too. - * Will it still format correctly? */ { - } - - let chain = funktion_kall() - .go_to_next_line_with_tab() - .go_to_next_line_with_tab() - .go_to_next_line_with_tab(); - - let z = [ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q, - ]; - - fn generic(arg: T) -> &SomeType - where - T: Fn( - // First arg - A, - // Second argument - B, - C, - D, - // pre comment - E, // last comment - ) -> &SomeType, - { - arg(a, b, c, d, e) - } - - loong_func().quux(move || if true { 1 } else { 2 }); - - fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - a.b.c.d(); - - x().y(|| match cond() { - true => (), - false => (), - }); -} - -// #2296 -impl Foo { - // a comment - // on multiple lines - fn foo() { - // another comment - // on multiple lines - let x = true; - } -} diff --git a/tests/target/hello.rs b/tests/target/hello.rs deleted file mode 100644 index d9f90b0b5e8..00000000000 --- a/tests/target/hello.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-config: small_tabs.toml -// rustfmt-target: hello.rs - -// Smoke test - hello world. - -fn main() { - println!("Hello world!"); -} diff --git a/tests/target/immovable_generators.rs b/tests/target/immovable_generators.rs deleted file mode 100644 index 0bf7a2d91ba..00000000000 --- a/tests/target/immovable_generators.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(generators)] - -unsafe fn foo() { - let mut ga = static || { - yield 1; - }; -} diff --git a/tests/target/impl.rs b/tests/target/impl.rs deleted file mode 100644 index 5895c74bcc9..00000000000 --- a/tests/target/impl.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Test impls - -impl JSTraceable for SmallVec<[T; 1]> {} - -impl>> Handle { - // Keep this. -} - -impl Test -where - V: Clone, // This comment is NOT removed by formating! -{ - pub fn new(value: V) -> Self { - Test { - cloned_value: value.clone(), - value, - } - } -} - -impl X /* comment */ {} -impl Y // comment -{ -} - -impl Foo for T -// comment1 -where - // comment2 - // blah - T: Clone, -{ -} - -// #1823 -default impl Trait for X {} -default unsafe impl Trait for Y {} -pub default unsafe impl Trait for Z {} - -// #2212 -impl ConstWithDefault { - default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; -} diff --git a/tests/target/impls.rs b/tests/target/impls.rs deleted file mode 100644 index 91172b39fe5..00000000000 --- a/tests/target/impls.rs +++ /dev/null @@ -1,219 +0,0 @@ -// rustfmt-normalize_comments: true -impl Foo for Bar { - fn foo() { - "hi" - } -} - -pub impl Foo for Bar { - // Associated Constants - const Baz: i32 = 16; - // Associated Types - type FooBar = usize; - // Comment 1 - fn foo() { - "hi" - } - // Comment 2 - fn foo() { - "hi" - } - // Comment 3 -} - -pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> -where - X: Foo<'a, Z>, -{ - fn foo() { - "hi" - } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> -where - X: Fooooooooooooooooooooooooooooo<'a, Z>, -{ - fn foo() { - "hi" - } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> -where - X: Foooooooooooooooooooooooooooo<'a, Z>, -{ - fn foo() { - "hi" - } -} - -impl Foo for Bar -where - T: Baz, -{ -} - -impl Foo for Bar -where - T: Baz, -{ - // Comment -} - -impl Foo { - fn foo() {} -} - -impl Boo { - // BOO - fn boo() {} - // FOO -} - -mod a { - impl Foo { - // Hello! - fn foo() {} - } -} - -mod b { - mod a { - impl Foo { - fn foo() {} - } - } -} - -impl Foo { - add_fun!(); -} - -impl Blah { - fn boop() {} - add_fun!(); -} - -impl X { - fn do_parse(mut self: X) {} -} - -impl Y5000 { - fn bar(self: X<'a, 'b>, y: Y) {} - - fn bad(&self, (x, y): CoorT) {} - - fn turbo_bad(self: X<'a, 'b>, (x, y): CoorT) {} -} - -pub impl Foo for Bar -where - T: Foo, -{ - fn foo() { - "hi" - } -} - -pub impl Foo for Bar -where - T: Foo, - Z: Baz, -{ -} - -mod m { - impl PartialEq for S - where - T: PartialEq, - { - fn eq(&self, other: &Self) { - true - } - } - - impl PartialEq for S - where - T: PartialEq, - { - } -} - -impl - Handle, HandleType> -{ -} - -impl PartialEq - for Handle, HandleType> -{ -} - -mod x { - impl Foo - where - A: 'static, - B: 'static, - C: 'static, - D: 'static, - { - } -} - -impl - Issue1249 -{ - // Creates a new flow constructor. - fn foo() {} -} - -// #1600 -impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { - fn drop() {} -} - -// #1168 -pub trait Number - : Copy - + Eq - + Not - + Shl - + Shr - + BitAnd - + BitOr - + BitAndAssign - + BitOrAssign { - // test - fn zero() -> Self; -} - -// #1642 -pub trait SomeTrait - : Clone - + Eq - + PartialEq - + Ord - + PartialOrd - + Default - + Hash - + Debug - + Display - + Write - + Read - + FromStr { - // comment -} - -// #1995 -impl Foo { - fn f( - S { - aaaaaaaaaa: aaaaaaaaaa, - bbbbbbbbbb: bbbbbbbbbb, - cccccccccc: cccccccccc, - }: S, - ) -> u32 { - 1 - } -} diff --git a/tests/target/import-fencepost-length.rs b/tests/target/import-fencepost-length.rs deleted file mode 100644 index e4f885c09b1..00000000000 --- a/tests/target/import-fencepost-length.rs +++ /dev/null @@ -1,4 +0,0 @@ -use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; -use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; -use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, - ddddddddd}; diff --git a/tests/target/imports-reorder-lines-and-items.rs b/tests/target/imports-reorder-lines-and-items.rs deleted file mode 100644 index f395710b186..00000000000 --- a/tests/target/imports-reorder-lines-and-items.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imported_names: true - -use std::cmp::{a, b, c, d}; -use std::ddd::{a, b, c as g, d as p}; -use std::ddd::aaa; -// This comment should stay with `use std::ddd:bbb;` -use std::ddd::bbb; -/// This comment should stay with `use std::str;` -use std::str; diff --git a/tests/target/imports-reorder-lines.rs b/tests/target/imports-reorder-lines.rs deleted file mode 100644 index 3695d6b4913..00000000000 --- a/tests/target/imports-reorder-lines.rs +++ /dev/null @@ -1,33 +0,0 @@ -// rustfmt-reorder_imports: true - -use std::cmp::{a, b, c, d}; -use std::cmp::{b, e, f, g}; -// This comment should stay with `use std::ddd;` -use std::ddd; -use std::ddd::aaa; -use std::ddd::bbb; -use std::str; - -mod test {} - -use aaa; -use aaa::*; -use aaa::bbb; - -mod test {} -// If item names are equal, order by rename - -use test::{a as aa, c}; -use test::{a as bb, b}; - -mod test {} -// If item names are equal, order by rename - no rename comes before a rename - -use test::{a, c}; -use test::{a as bb, b}; - -mod test {} -// `self` always comes first - -use test::{self as bb, b}; -use test::{a as aa, c}; diff --git a/tests/target/imports-reorder.rs b/tests/target/imports-reorder.rs deleted file mode 100644 index fbb56e3aa0c..00000000000 --- a/tests/target/imports-reorder.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-reorder_imported_names: true - -use path::{self /* self */, /* A */ A, B /* B */, C}; - -use {aa, ab, ac, b, Z}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs deleted file mode 100644 index 2b825526199..00000000000 --- a/tests/target/imports.rs +++ /dev/null @@ -1,88 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-error_on_line_overflow: false - -// Imports. - -// Long import. -use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; -use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; - -use list::{// Another item - AnotherItem, // Another Comment - // Last Item - LastItem, - // Some item - SomeItem /* Comment */}; - -use test::{/* A */ self /* B */, Other /* C */}; - -use syntax; -use {Bar /* comment */, /* Pre-comment! */ Foo}; -use Foo::{Bar, Baz}; -pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; - -use self; -use std::io; -use std::io; - -mod Foo { - pub use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; - - mod Foo2 { - pub use syntax::ast::{self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, - ItemStatic}; - } -} - -fn test() { - use Baz::*; - use Qux; -} - -// Simple imports -use foo::bar::baz; -use bar::quux as kaas; -use foo; - -// With aliases. -use foo::{self as bar, baz}; -use foo as bar; -use foo::qux as bar; -use foo::{baz, qux as bar}; - -// With absolute paths -use foo; -use foo::Bar; -use foo::{Bar, Baz}; -use Foo; -use {Bar, Baz}; - -// Root globs -use ::*; -use ::*; - -// spaces used to cause glob imports to disappear (#1356) -use super::*; -use foo::issue_1356::*; - -// We shouldn't remove imports which have attributes attached (#1858) -#[cfg(unix)] -use self::unix::{}; - -// nested imports -use foo::{a, b, boo, c, - bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, - foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}}; - -use fooo::{bar, x, y, z, - baar::foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}, - bar::*}; - -// nested imports with a single sub-tree. -use a::b::c::*; -use a::b::c::d; -use a::b::c::{xxx, yyy, zzz}; diff --git a/tests/target/indented-impl.rs b/tests/target/indented-impl.rs deleted file mode 100644 index eff579dddac..00000000000 --- a/tests/target/indented-impl.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -mod x -{ - struct X(i8); - - impl Y for X - { - fn y(self) -> () - { - println!("ok"); - } - } -} diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs deleted file mode 100644 index ba1029d4e61..00000000000 --- a/tests/target/issue-1021.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - match x { - S(true, .., true) => (), - S(true, ..) => (), - S(.., true) => (), - S(..) => (), - S(_) => (), - S(/* .. */ ..) => (), - S(/* .. */ .., true) => (), - } - - match y { - (true, .., true) => (), - (true, ..) => (), - (.., true) => (), - (..) => (), - (_,) => (), - (/* .. */ ..) => (), - (/* .. */ .., true) => (), - } -} diff --git a/tests/target/issue-1049.rs b/tests/target/issue-1049.rs deleted file mode 100644 index c788519ca9a..00000000000 --- a/tests/target/issue-1049.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Test overlong function signature -pub unsafe fn reborrow_mut( - &mut X: Abcde, -) -> Handle, HandleType> { -} - -pub fn merge( - mut X: Abcdef, -) -> Handle, K, V, marker::Internal>, marker::Edge> { -} - -impl Handle { - pub fn merge( - a: Abcd, - ) -> Handle, K, V, marker::Internal>, marker::Edge> { - } -} - -// Long function without return type that should not be reformatted. -fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} - -fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { -} - -fn veeeeeeeeeeeeeeeeeeeeeeery_long_name( - a: FirstTypeeeeeeeeee, - b: SecondTypeeeeeeeeeeeeeeeeeeeeeee, -) { -} diff --git a/tests/target/issue-1055.rs b/tests/target/issue-1055.rs deleted file mode 100644 index ee143e792b0..00000000000 --- a/tests/target/issue-1055.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn issue_1055() { - let foo = (|| {})(); -} diff --git a/tests/target/issue-1111.rs b/tests/target/issue-1111.rs deleted file mode 100644 index 2e1a89ad78e..00000000000 --- a/tests/target/issue-1111.rs +++ /dev/null @@ -1 +0,0 @@ -use bar; diff --git a/tests/target/issue-1113.rs b/tests/target/issue-1113.rs deleted file mode 100644 index 1245bcd057c..00000000000 --- a/tests/target/issue-1113.rs +++ /dev/null @@ -1,33 +0,0 @@ -pub fn foo() -> fmt::Result -//pub fn writeStringToken -{ - panic!() -} - -pub fn foo() -> fmt::Result // pub fn writeStringToken -{ - panic!() -} - -pub fn foo() -> fmt::Result /* pub fn writeStringToken */ { - panic!() -} - -pub fn foo() -> fmt::Result -/* pub fn writeStringToken */ { - panic!() -} - -pub fn foo() -> fmt::Result -/* pub fn writeStringToken */ -{ - panic!() -} - -pub fn foo() -> fmt::Result /* - * - * - */ -{ - panic!() -} diff --git a/tests/target/issue-1120.rs b/tests/target/issue-1120.rs deleted file mode 100644 index f44597e7d1e..00000000000 --- a/tests/target/issue-1120.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_imports: true - -// Ensure that a use at the start of an inline module is correctly formatted. -mod foo { - use bar; -} - -// Ensure that an indented `use` gets the correct indentation. -mod foo { - use bar; -} diff --git a/tests/target/issue-1124.rs b/tests/target/issue-1124.rs deleted file mode 100644 index d34870b2a28..00000000000 --- a/tests/target/issue-1124.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-normalize_comments: true - -use a; -use b; -use c; -use d; -// The previous line has a space after the `use a;` - -mod a { - use a; - use b; - use c; - use d; -} - -use a; -use x; -use y; -use z; diff --git a/tests/target/issue-1127.rs b/tests/target/issue-1127.rs deleted file mode 100644 index dbdd234b8e4..00000000000 --- a/tests/target/issue-1127.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-max_width:120 -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true - -fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { - 42 -} - -enum TestEnum { - AVeryVeryLongEnumName, - AnotherVeryLongEnumName, - TheLastVeryLongEnumName, -} - -fn main() { - let var = TestEnum::AVeryVeryLongEnumName; - let num = match var { - TestEnum::AVeryVeryLongEnumName => - a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::AnotherVeryLongEnumName => - a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::TheLastVeryLongEnumName => - a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - }; -} diff --git a/tests/target/issue-1158.rs b/tests/target/issue-1158.rs deleted file mode 100644 index 2abfa5a29f2..00000000000 --- a/tests/target/issue-1158.rs +++ /dev/null @@ -1,3 +0,0 @@ -trait T { - itemmacro!(this, is.now().formatted(yay)); -} diff --git a/tests/target/issue-1177.rs b/tests/target/issue-1177.rs deleted file mode 100644 index dcda3972814..00000000000 --- a/tests/target/issue-1177.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - // Line Comment - // Block Comment - - let d = 5; -} diff --git a/tests/target/issue-1192.rs b/tests/target/issue-1192.rs deleted file mode 100644 index 432fe8cce7c..00000000000 --- a/tests/target/issue-1192.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - assert!(true); -} diff --git a/tests/target/issue-1211.rs b/tests/target/issue-1211.rs deleted file mode 100644 index de4c5c87ee6..00000000000 --- a/tests/target/issue-1211.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn main() { - for iface in &ifaces { - match iface.addr { - get_if_addrs::IfAddr::V4(ref addr) => match addr.broadcast { - Some(ip) => { - sock.send_to(&buf, (ip, 8765)).expect("foobar"); - } - _ => (), - }, - _ => (), - }; - } -} diff --git a/tests/target/issue-1214.rs b/tests/target/issue-1214.rs deleted file mode 100644 index c622abb3a85..00000000000 --- a/tests/target/issue-1214.rs +++ /dev/null @@ -1,8 +0,0 @@ -/*! -# Example - -``` - // Here goes some example -``` - */ -struct Item; diff --git a/tests/target/issue-1216.rs b/tests/target/issue-1216.rs deleted file mode 100644 index d727c158ab8..00000000000 --- a/tests/target/issue-1216.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-normalize_comments: true -enum E { - A, //* I am not a block comment (caused panic) - B, -} diff --git a/tests/target/issue-1239.rs b/tests/target/issue-1239.rs deleted file mode 100644 index b10afb5cb6c..00000000000 --- a/tests/target/issue-1239.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn foo() { - let with_alignment = if condition__uses_alignment_for_first_if__0 - || condition__uses_alignment_for_first_if__1 - || condition__uses_alignment_for_first_if__2 - { - } else if condition__no_alignment_for_later_else__0 || condition__no_alignment_for_later_else__1 - || condition__no_alignment_for_later_else__2 - { - }; -} diff --git a/tests/target/issue-1247.rs b/tests/target/issue-1247.rs deleted file mode 100644 index 16c63e0f53d..00000000000 --- a/tests/target/issue-1247.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-max_width: 80 - -fn foo() { - polyfill::slice::fill( - &mut self.pending[padding_pos..(self.algorithm.block_len - 8)], - 0, - ); -} diff --git a/tests/target/issue-1255.rs b/tests/target/issue-1255.rs deleted file mode 100644 index 2d4633844a9..00000000000 --- a/tests/target/issue-1255.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Test for issue #1255 -// Default annotation incorrectly removed on associated types -#![feature(specialization)] - -trait Trait { - type Type; -} -impl Trait for T { - default type Type = u64; // 'default' should not be removed -} diff --git a/tests/target/issue-1278.rs b/tests/target/issue-1278.rs deleted file mode 100644 index e25376561a9..00000000000 --- a/tests/target/issue-1278.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style = "block" - -#![feature(pub_restricted)] - -mod inner_mode { - pub(super) fn func_name(abc: i32) -> i32 { - abc - } -} diff --git a/tests/target/issue-1350.rs b/tests/target/issue-1350.rs deleted file mode 100644 index 2cf65509c93..00000000000 --- a/tests/target/issue-1350.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-max_width: 120 -// rustfmt-comment_width: 110 - -impl Struct { - fn fun() { - let result = match ::deserialize(&json) { - Ok(v) => v, - Err(e) => match ::deserialize(&json) { - Ok(v) => return Err(Error::with_json(v)), - Err(e2) => return Err(Error::with_json(e)), - }, - }; - } -} diff --git a/tests/target/issue-1366.rs b/tests/target/issue-1366.rs deleted file mode 100644 index eee147baab9..00000000000 --- a/tests/target/issue-1366.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn main() { - fn f() -> Option { - Some("fffffffsssssssssddddssssfffffddddff") - .map(|s| s) - .map(|s| s.to_string()) - .map(|res| match Some(res) { - Some(ref s) if s == "" => 41, - Some(_) => 42, - _ => 43, - }) - } - println!("{:?}", f()) -} diff --git a/tests/target/issue-1397.rs b/tests/target/issue-1397.rs deleted file mode 100644 index 86b7a78411f..00000000000 --- a/tests/target/issue-1397.rs +++ /dev/null @@ -1,25 +0,0 @@ -pub enum TransactionState { - Committed(i64), -} - -pub enum Packet { - Transaction { state: TransactionState }, -} - -fn baz(p: Packet) { - loop { - loop { - loop { - loop { - if let Packet::Transaction { - state: TransactionState::Committed(ts, ..), - .. - } = p - { - unreachable!() - } - } - } - } - } -} diff --git a/tests/target/issue-1468.rs b/tests/target/issue-1468.rs deleted file mode 100644 index 4c14a0f746a..00000000000 --- a/tests/target/issue-1468.rs +++ /dev/null @@ -1,29 +0,0 @@ -fn issue1468() { - euc_jp_decoder_functions!({ - let trail_minus_offset = byte.wrapping_sub(0xA1); - // Fast-track Hiragana (60% according to Lunde) - // and Katakana (10% according to Lunde). - if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { - // Hiragana - handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) - } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 { - // Katakana - handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) - } else if trail_minus_offset > (0xFE - 0xA1) { - if byte < 0x80 { - return ( - DecoderResult::Malformed(1, 0), - unread_handle_trail.unread(), - handle.written(), - ); - } - return ( - DecoderResult::Malformed(2, 0), - unread_handle_trail.consumed(), - handle.written(), - ); - } else { - unreachable!(); - } - }); -} diff --git a/tests/target/issue-1598.rs b/tests/target/issue-1598.rs deleted file mode 100644 index c7e02c961a6..00000000000 --- a/tests/target/issue-1598.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - //foo - /* - */ - format!("hello"); -} diff --git a/tests/target/issue-1624.rs b/tests/target/issue-1624.rs deleted file mode 100644 index 477fc27353f..00000000000 --- a/tests/target/issue-1624.rs +++ /dev/null @@ -1,6 +0,0 @@ -// #1624 -pub unsafe fn some_long_function_name( - arg1: Type1, - arg2: Type2, -) -> (SomeLongTypeName, AnotherLongTypeName, AnotherLongTypeName) { -} diff --git a/tests/target/issue-1681.rs b/tests/target/issue-1681.rs deleted file mode 100644 index 5734fd5502d..00000000000 --- a/tests/target/issue-1681.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-max_width: 80 - -// We would like to surround closure body with block when overflowing the last -// argument of function call if the last argument has condition and without -// block it may go multi lines. -fn foo() { - refmut_map_result(self.cache.borrow_mut(), |cache| { - match cache.entry(cache_key) { - Occupied(entry) => Ok(entry.into_mut()), - Vacant(entry) => { - let statement = { - let sql = try!(entry.key().sql(source)); - prepare_fn(&sql) - }; - - Ok(entry.insert(try!(statement))) - } - } - }).map(MaybeCached::Cached) -} diff --git a/tests/target/issue-1693.rs b/tests/target/issue-1693.rs deleted file mode 100644 index 85421a123bb..00000000000 --- a/tests/target/issue-1693.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn issue1693() { - let pixel_data = vec![ - ( - f16::from_f32(0.82), - f16::from_f32(1.78), - f16::from_f32(0.21) - ); - 256 * 256 - ]; -} diff --git a/tests/target/issue-1703.rs b/tests/target/issue-1703.rs deleted file mode 100644 index 4079ef4cfca..00000000000 --- a/tests/target/issue-1703.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt should not remove doc comments or comments inside attributes. - -/** -This function has a block doc comment. - */ -fn test_function() {} - -#[foo /* do not remove this! */] -fn foo() {} diff --git a/tests/target/issue-1800.rs b/tests/target/issue-1800.rs deleted file mode 100644 index 06c5cfd0567..00000000000 --- a/tests/target/issue-1800.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![doc(html_root_url = "http://example.com")] -#[cfg(feature = "foo")] -fn a() {} diff --git a/tests/target/issue-1802.rs b/tests/target/issue-1802.rs deleted file mode 100644 index a4679463ba2..00000000000 --- a/tests/target/issue-1802.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-tab_spaces: 2 -// rustfmt-max_width: 30 -// rustfmt-error_on_line_overflow: false - -enum F { - X { - a: dddddddddddddd, - b: eeeeeeeeeeeeeee, - }, -} diff --git a/tests/target/issue-1824.rs b/tests/target/issue-1824.rs deleted file mode 100644 index 1c4c2db46dc..00000000000 --- a/tests/target/issue-1824.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub trait Ingredient -where - Self: Send, -{ -} diff --git a/tests/target/issue-1914.rs b/tests/target/issue-1914.rs deleted file mode 100644 index d2d532af1dc..00000000000 --- a/tests/target/issue-1914.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-max_width: 80 - -extern "C" { - #[link_name = "_ZN7MyClass26example_check_no_collisionE"] - pub static mut MyClass_example_check_no_collision: - *const ::std::os::raw::c_int; -} diff --git a/tests/target/issue-2025.rs b/tests/target/issue-2025.rs deleted file mode 100644 index 38bf369bea3..00000000000 --- a/tests/target/issue-2025.rs +++ /dev/null @@ -1,4 +0,0 @@ -// See if rustfmt removes empty lines on top of the file. -pub fn foo() { - println!("hello, world"); -} diff --git a/tests/target/issue-2103.rs b/tests/target/issue-2103.rs deleted file mode 100644 index 5a043d54b75..00000000000 --- a/tests/target/issue-2103.rs +++ /dev/null @@ -1,14 +0,0 @@ -struct X -where - i32: Sized, -{ - x: i32, -} - -struct X -// with comment -where - i32: Sized, -{ - x: i32, -} diff --git a/tests/target/issue-2111.rs b/tests/target/issue-2111.rs deleted file mode 100644 index 13303a736a3..00000000000 --- a/tests/target/issue-2111.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-normalize_comments: false - -// An import with single line comments. -use super::{DelayChoice, - Destinations, - Holding, - LodaModel, - MethodDescription, - ModelBehaviour, - ModelEdges, - ModelProperties, - ModelRequestGraph, - ModelSelector, - RequestDescription, - StringMap, - Switch, - // ModelMetaData, - // Generated, - // SecondsString, - // DateString, - // ModelConfiguration, - // ModelRequests, - // RestResponse, - // RestResponseCode, - // UniformHolding - SCHEMA_VERSIONS}; diff --git a/tests/target/issue-2123.rs b/tests/target/issue-2123.rs deleted file mode 100644 index 5e9917b4023..00000000000 --- a/tests/target/issue-2123.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-wrap_comments: true - -//hello -//world - -fn main() {} diff --git a/tests/target/issue-2164.rs b/tests/target/issue-2164.rs deleted file mode 100644 index ab1d7dfd37a..00000000000 --- a/tests/target/issue-2164.rs +++ /dev/null @@ -1,132 +0,0 @@ -// A stress test against code generated by bindgen. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct emacs_env_25 { - pub size: isize, - pub private_members: *mut emacs_env_private, - pub make_global_ref: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, any_reference: emacs_value) -> emacs_value, - >, - pub free_global_ref: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, global_reference: emacs_value), - >, - pub non_local_exit_check: - ::std::option::Option emacs_funcall_exit>, - pub non_local_exit_clear: ::std::option::Option, - pub non_local_exit_get: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - non_local_exit_symbol_out: *mut emacs_value, - non_local_exit_data_out: *mut emacs_value, - ) -> emacs_funcall_exit, - >, - pub non_local_exit_signal: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - non_local_exit_symbol: emacs_value, - non_local_exit_data: emacs_value, - ), - >, - pub non_local_exit_throw: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, tag: emacs_value, value: emacs_value), - >, - pub make_function: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - min_arity: isize, - max_arity: isize, - function: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - nargs: isize, - args: *mut emacs_value, - arg1: *mut ::libc::c_void, - ) -> emacs_value, - >, - documentation: *const ::libc::c_char, - data: *mut ::libc::c_void, - ) -> emacs_value, - >, - pub funcall: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - function: emacs_value, - nargs: isize, - args: *mut emacs_value, - ) -> emacs_value, - >, - pub intern: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, symbol_name: *const ::libc::c_char) - -> emacs_value, - >, - pub type_of: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> emacs_value, - >, - pub is_not_nil: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> bool, - >, - pub eq: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, a: emacs_value, b: emacs_value) -> bool, - >, - pub extract_integer: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> intmax_t, - >, - pub make_integer: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: intmax_t) -> emacs_value, - >, - pub extract_float: - ::std::option::Option f64>, - pub make_float: - ::std::option::Option emacs_value>, - pub copy_string_contents: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - value: emacs_value, - buffer: *mut ::libc::c_char, - size_inout: *mut isize, - ) -> bool, - >, - pub make_string: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, contents: *const ::libc::c_char, length: isize) - -> emacs_value, - >, - pub make_user_ptr: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - fin: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void), - >, - ptr: *mut ::libc::c_void, - ) -> emacs_value, - >, - pub get_user_ptr: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value) -> *mut ::libc::c_void, - >, - pub set_user_ptr: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value, ptr: *mut ::libc::c_void), - >, - pub get_user_finalizer: ::std::option::Option< - unsafe extern "C" fn( - arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value - ) -> ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value), - >, - >, - pub set_user_finalizer: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - uptr: emacs_value, - fin: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void), - >, - ), - >, - pub vec_get: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize) -> emacs_value, - >, - pub vec_set: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize, val: emacs_value), - >, - pub vec_size: - ::std::option::Option isize>, -} diff --git a/tests/target/issue-2179.rs b/tests/target/issue-2179.rs deleted file mode 100644 index db8f9c557b4..00000000000 --- a/tests/target/issue-2179.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -fn issue_2179() { - let (opts, rustflags, clear_env_rust_log) = { - // We mustn't lock configuration for the whole build process - let rls_config = rls_config.lock().unwrap(); - - let opts = CargoOptions::new(&rls_config); - trace!("Cargo compilation options:\n{:?}", opts); - let rustflags = prepare_cargo_rustflags(&rls_config); - - // Warn about invalid specified bin target or package depending on current mode - // TODO: Return client notifications along with diagnostics to inform the user - if !rls_config.workspace_mode { - let cur_pkg_targets = ws.current().unwrap().targets(); - - if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { - let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); - if let None = bins.find(|x| x.name() == build_bin) { - warn!( - "cargo - couldn't find binary `{}` specified in `build_bin` configuration", - build_bin - ); - } - } - } else { - for package in &opts.package { - if let None = ws.members().find(|x| x.name() == package) { - warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); - } - } - } - - (opts, rustflags, rls_config.clear_env_rust_log) - }; -} diff --git a/tests/target/issue-2197.rs b/tests/target/issue-2197.rs deleted file mode 100644 index 76dbbefc3a7..00000000000 --- a/tests/target/issue-2197.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-max_width: 79 -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false - -/// ```rust -/// unsafe fn sum_sse2(x: i32x4) -> i32 { -/// let x = vendor::_mm_add_epi32( -/// x, -/// vendor::_mm_srli_si128(x.into(), 8).into(), -/// ); -/// let x = vendor::_mm_add_epi32( -/// x, -/// vendor::_mm_srli_si128(x.into(), 4).into(), -/// ); -/// vendor::_mm_cvtsi128_si32(x) -/// } -/// ``` -fn foo() {} diff --git a/tests/target/issue-2256.rs b/tests/target/issue-2256.rs deleted file mode 100644 index 4b546223f94..00000000000 --- a/tests/target/issue-2256.rs +++ /dev/null @@ -1,7 +0,0 @@ -// こんにちは -use std::borrow::Cow; - -/* comment */ -/* comment */ - -/* comment */ diff --git a/tests/target/issue-2324.rs b/tests/target/issue-2324.rs deleted file mode 100644 index 9211b24d81f..00000000000 --- a/tests/target/issue-2324.rs +++ /dev/null @@ -1,7 +0,0 @@ -// nested function calls with cast. -fn main() { - self.ptr - .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T); - self.ptr - .set(intrinsics::arith_offset(self.ptr.get(), mem::size_of::() as isize) as *mut u8); -} diff --git a/tests/target/issue-2329.rs b/tests/target/issue-2329.rs deleted file mode 100644 index e36e9546b24..00000000000 --- a/tests/target/issue-2329.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Comments with characters which must be represented by multibyte. - -// フー -use foo; -// バー -use bar; - -impl MyStruct { - // コメント - fn f1() {} // こんにちは - fn f2() {} // ありがとう - // コメント -} - -trait MyTrait { - // コメント - fn f1() {} // こんにちは - fn f2() {} // ありがとう - // コメント -} - -fn main() { - // コメント - let x = 1; // X - println!( - "x = {}", // xの値 - x, // X - ); - // コメント -} diff --git a/tests/target/issue-2342.rs b/tests/target/issue-2342.rs deleted file mode 100644 index f9c26857e15..00000000000 --- a/tests/target/issue-2342.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-max_width: 80 - -struct Foo { - #[cfg(feature = "serde")] - bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN -} diff --git a/tests/target/issue-2401.rs b/tests/target/issue-2401.rs deleted file mode 100644 index ec8f27b732f..00000000000 --- a/tests/target/issue-2401.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-hard_tabs = true -// rustfmt-normalize_comments = true - -/// ``` -/// println!("Hello, World!"); -/// ``` -fn main() {} diff --git a/tests/target/issue-447.rs b/tests/target/issue-447.rs deleted file mode 100644 index d41cdb65cd0..00000000000 --- a/tests/target/issue-447.rs +++ /dev/null @@ -1,40 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - if - // shouldn't be dropped - // shouldn't be dropped - cond - // shouldn't be dropped - // shouldn't be dropped - { - } - // shouldn't be dropped - // shouldn't be dropped - else - // shouldn't be dropped - // shouldn't be dropped - if - // shouldn't be dropped - // shouldn't be dropped - cond - // shouldn't be dropped - // shouldn't be dropped - { - } - // shouldn't be dropped - // shouldn't be dropped - else - // shouldn't be dropped - // shouldn't be dropped - { - } - - if - // shouldn't be dropped - // shouldn't be dropped - let Some(x) = y - // shouldn't be dropped - // shouldn't be dropped - {} -} diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs deleted file mode 100644 index a166b68498f..00000000000 --- a/tests/target/issue-510.rs +++ /dev/null @@ -1,41 +0,0 @@ -impl ISizeAndMarginsComputer for AbsoluteNonReplaced { - fn solve_inline_size_constraints( - &self, - block: &mut BlockFlow, - input: &ISizeConstraintInput, - ) -> ISizeConstraintSolution { - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match ( - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - ) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size( - available_inline_size - (margin_start + margin_end), - ); - (Au(0), inline_size, margin_start, margin_end) - } - }; - - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_start, inline_end, computed_inline_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size( - available_inline_size - (margin_start + margin_end), - ); - (Au(0), inline_size, margin_start, margin_end) - } - }; - } -} diff --git a/tests/target/issue-64.rs b/tests/target/issue-64.rs deleted file mode 100644 index c0660630203..00000000000 --- a/tests/target/issue-64.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Regression test for issue 64 - -pub fn header_name() -> &'static str { - let name = ::header_name(); - let func = ::header_name; - name -} diff --git a/tests/target/issue-691.rs b/tests/target/issue-691.rs deleted file mode 100644 index 7473d070eff..00000000000 --- a/tests/target/issue-691.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-normalize_comments: true - -//! `std` or `core` and simply link to this library. In case the target -//! platform has no hardware -//! support for some operation, software implementations provided by this -//! library will be used automagically. -// TODO: provide instructions to override default libm link and how to link to -// this library. -fn foo() {} diff --git a/tests/target/issue-770.rs b/tests/target/issue-770.rs deleted file mode 100644 index 5fbedd7b734..00000000000 --- a/tests/target/issue-770.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - if false { - if false { - } else { - // A let binding here seems necessary to trigger it. - let _ = (); - } - } else if let false = false { - } -} diff --git a/tests/target/issue-811.rs b/tests/target/issue-811.rs deleted file mode 100644 index b7a89b5d0f9..00000000000 --- a/tests/target/issue-811.rs +++ /dev/null @@ -1,19 +0,0 @@ -trait FooTrait: Sized { - type Bar: BarTrait; -} - -trait BarTrait: Sized { - type Baz; - fn foo(); -} - -type Foo = <>::Bar as BarTrait>::Baz; -type Bar = >::Baz; - -fn some_func, U>() { - <>::Bar as BarTrait>::foo(); -} - -fn some_func>() { - >::foo(); -} diff --git a/tests/target/issue-831.rs b/tests/target/issue-831.rs deleted file mode 100644 index 1d6327c2158..00000000000 --- a/tests/target/issue-831.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - let y = a.iter().any(|x| { - println!("a"); - }) || b.iter().any(|x| { - println!("b"); - }) || c.iter().any(|x| { - println!("c"); - }); -} diff --git a/tests/target/issue-850.rs b/tests/target/issue-850.rs deleted file mode 100644 index c939716a6a8..00000000000 --- a/tests/target/issue-850.rs +++ /dev/null @@ -1 +0,0 @@ -const unsafe fn x() {} diff --git a/tests/target/issue-855.rs b/tests/target/issue-855.rs deleted file mode 100644 index 0430cc62954..00000000000 --- a/tests/target/issue-855.rs +++ /dev/null @@ -1,27 +0,0 @@ -fn main() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit { .. } - | Event::KeyDown { - keycode: Some(Keycode::Escape), - .. - } => break 'running, - } - } - } -} - -fn main2() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit { .. } - | Event::KeyDownXXXXXXXXXXXXX { - keycode: Some(Keycode::Escape), - .. - } => break 'running, - } - } - } -} diff --git a/tests/target/issue-913.rs b/tests/target/issue-913.rs deleted file mode 100644 index 2158b70a46f..00000000000 --- a/tests/target/issue-913.rs +++ /dev/null @@ -1,24 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -mod client { - impl Client { - fn test(self) -> Result<()> { - let next_state = match self.state { - State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { - let x = reformat.meeee(); - } - }; - - let next_state = match self.state { - State::V5(v5::State::Command(v5::comand::State::WriteVersion( - ref mut response, - ))) => { - // The pattern cannot be formatted in a way that the match stays - // within the column limit. The rewrite should therefore be - // skipped. - let x = dont.reformat.meeee(); - } - }; - } - } -} diff --git a/tests/target/issue-945.rs b/tests/target/issue-945.rs deleted file mode 100644 index d46c69a4f09..00000000000 --- a/tests/target/issue-945.rs +++ /dev/null @@ -1,17 +0,0 @@ -impl Bar { - default const unsafe fn foo() { - "hi" - } -} - -impl Baz { - default unsafe extern "C" fn foo() { - "hi" - } -} - -impl Foo for Bar { - default fn foo() { - "hi" - } -} diff --git a/tests/target/issue-977.rs b/tests/target/issue-977.rs deleted file mode 100644 index 9420054449d..00000000000 --- a/tests/target/issue-977.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-normalize_comments: true -// FIXME(#919) - -trait NameC { - // comment -} -struct FooC { /* comment */ } -enum MooC { - // comment -} -mod BarC { - // comment -} -extern "C" { - // comment -} diff --git a/tests/target/item-brace-style-always-next-line.rs b/tests/target/item-brace-style-always-next-line.rs deleted file mode 100644 index 531ac598683..00000000000 --- a/tests/target/item-brace-style-always-next-line.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine - -mod M -{ - enum A - { - A, - } - - struct B - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A - where - T: Copy, - { - A, - } - - struct B - where - T: Copy, - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C - where - T: Copy, {} - - struct D - where - T: Copy, {} -} diff --git a/tests/target/item-brace-style-prefer-same-line.rs b/tests/target/item-brace-style-prefer-same-line.rs deleted file mode 100644 index ef8dc028c2d..00000000000 --- a/tests/target/item-brace-style-prefer-same-line.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-brace_style: PreferSameLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - enum C {} - - struct D {} - - enum A - where - T: Copy, { - A, - } - - struct B - where - T: Copy, { - b: i32, - } - - enum C - where - T: Copy, {} - - struct D - where - T: Copy, {} -} diff --git a/tests/target/item-brace-style-same-line-where.rs b/tests/target/item-brace-style-same-line-where.rs deleted file mode 100644 index 9a275efc96e..00000000000 --- a/tests/target/item-brace-style-same-line-where.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-brace_style: SameLineWhere - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A - where - T: Copy, - { - A, - } - - struct B - where - T: Copy, - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C - where - T: Copy, {} - - struct D - where - T: Copy, {} -} diff --git a/tests/target/large-block.rs b/tests/target/large-block.rs deleted file mode 100644 index 09e9169f340..00000000000 --- a/tests/target/large-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn issue1351() { - std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ - static __STATIC_FMTSTR: &'static [&'static str] = &[]; - }); -} diff --git a/tests/target/large_vec.rs b/tests/target/large_vec.rs deleted file mode 100644 index 95d1fc43c03..00000000000 --- a/tests/target/large_vec.rs +++ /dev/null @@ -1,42 +0,0 @@ -// See #1470. - -impl Environment { - pub fn new_root() -> Rc> { - let mut env = Environment::new(); - let builtin_functions = &[ - ( - "println", - Function::NativeVoid( - CallSign { - num_params: 0, - variadic: true, - param_types: vec![], - }, - native_println, - ), - ), - ( - "run_http_server", - Function::NativeVoid( - CallSign { - num_params: 1, - variadic: false, - param_types: vec![Some(ConstraintType::Function)], - }, - native_run_http_server, - ), - ), - ( - "len", - Function::NativeReturning( - CallSign { - num_params: 1, - variadic: false, - param_types: vec![None], - }, - native_len, - ), - ), - ]; - } -} diff --git a/tests/target/long-fn-1.rs b/tests/target/long-fn-1.rs deleted file mode 100644 index c3d44de7c69..00000000000 --- a/tests/target/long-fn-1.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Tests that a function which is almost short enough, but not quite, gets -// formatted correctly. - -impl Foo { - fn some_input( - &mut self, - input: Input, - input_path: Option, - ) -> (Input, Option) { - } - - fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { - } -} - -// #1843 -#[allow(non_snake_case)] -pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash( -) -> bool { - false -} diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs deleted file mode 100644 index aeb384e7203..00000000000 --- a/tests/target/long-match-arms-brace-newline.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 80 -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - match x - { - aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) - if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => - { - Ok(()) - } - _ => Err(x), - } -} diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs deleted file mode 100644 index 349d2c2f639..00000000000 --- a/tests/target/long_field_access.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn f() { - block_flow.base.stacking_relative_position_of_display_port = - self.base.stacking_relative_position_of_display_port; -} diff --git a/tests/target/loop.rs b/tests/target/loop.rs deleted file mode 100644 index f669e7e2c58..00000000000 --- a/tests/target/loop.rs +++ /dev/null @@ -1,34 +0,0 @@ -fn main() { - loop { - return some_val; - } - - let x = loop { - do_forever(); - }; - - 'label: loop { - // Just comments - } - - 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value - { - } - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { - } - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { - } - - 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) - { - // do smth - } - - while let Some(i) = x.find('s') { - x.update(); - continue; - continue 'foo; - } -} diff --git a/tests/target/macro_not_expr.rs b/tests/target/macro_not_expr.rs deleted file mode 100644 index c76a6492a9d..00000000000 --- a/tests/target/macro_not_expr.rs +++ /dev/null @@ -1,7 +0,0 @@ -macro_rules! test { - ($($t: tt)*) => {}; -} - -fn main() { - test!( a : B => c d ); -} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs deleted file mode 100644 index 647d442034f..00000000000 --- a/tests/target/macro_rules.rs +++ /dev/null @@ -1,43 +0,0 @@ -macro_rules! m { - // a - ($expr: expr, $($func: ident)*) => {{ - let x = $expr; - $func(x) - }}; - - /* b */ - () => { - /* c */ - }; - - (@tag) => {}; - - // d - ($item: ident) => { - mod macro_item { - struct $item; - } - }; -} - -macro m2 { - // a - ($expr: expr, $($func: ident)*) => {{ - let x = $expr; - $func(x) - }} - - /* b */ - () => { - /* c */ - } - - (@tag) => {} - - // d - ($item: ident) => { - mod macro_item { - struct $item; - } - } -} diff --git a/tests/target/macros.rs b/tests/target/macros.rs deleted file mode 100644 index 9b32c6623bb..00000000000 --- a/tests/target/macros.rs +++ /dev/null @@ -1,913 +0,0 @@ -// rustfmt-normalize_comments: true -itemmacro!(this, is.now().formatted(yay)); - -itemmacro!( - really, - long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() - .is - .formatted() -); - -itemmacro!{this, is.bracket().formatted()} - -peg_file! modname("mygrammarfile.rustpeg"); - -fn main() { - foo!(); - - bar!(a, b, c); - - bar!(a, b, c,); - - baz!(1 + 2 + 3, quux.kaas()); - - quux!( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB - ); - - kaas!( - // comments - a, // post macro - b // another - ); - - trailingcomma!(a, b, c,); - // Preserve trailing comma only when necessary. - ok!(file.seek(SeekFrom::Start( - table.map(|table| fixture.offset(table)).unwrap_or(0), - ))); - - noexpr!( i am not an expression, OK? ); - - vec![a, b, c]; - - vec![ - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - BBBBB, - 5, - 100 - 30, - 1.33, - b, - b, - b, - ]; - - vec![a /* comment */]; - - // Trailing spaces after a comma - vec![a]; - - vec![a; b]; - vec![a; b]; - vec![a; b]; - - vec![a, b; c]; - vec![a; b, c]; - - vec![ - a; - (|x| { - let y = x + 1; - let z = y + 1; - z - })(2) - ]; - vec![ - a; - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - ]; - vec![a; unsafe { x + 1 }]; - - unknown_bracket_macro__comma_should_not_be_stripped![a,]; - - foo(makro!(1, 3)); - - hamkaas!{ () }; - - macrowithbraces! {dont, format, me} - - x!(fn); - - some_macro!(); - - some_macro![]; - - some_macro!{ - // comment - }; - - some_macro!{ - // comment - }; - - some_macro!( - // comment - not function like - ); - - // #1712 - let image = gray_image!( - 00, 01, 02; - 10, 11, 12; - 20, 21, 22); - - // #1092 - chain!(input, a: take!(max_size), || []); -} - -impl X { - empty_invoc!{} -} - -fn issue_1279() { - println!("dsfs"); // a comment -} - -fn issue_1555() { - let hello = &format!( - "HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", - "65454654654654654654654655464", "4" - ); -} - -fn issue1178() { - macro_rules! foo { - (#[$attr: meta] $name: ident) => {}; - } - - foo!( - #[doc = "bar"] - baz - ); -} - -fn issue1739() { - sql_function!( - add_rss_item, - add_rss_item_t, - ( - a: types::Integer, - b: types::Timestamptz, - c: types::Text, - d: types::Text, - e: types::Text - ) - ); - - w.slice_mut(s![ - .., - init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], - .. - ]).par_map_inplace(|el| *el = 0.); -} - -fn issue_1885() { - let threads = people - .into_iter() - .map(|name| { - chan_select! { - rx.recv() => {} - } - }) - .collect::>(); -} - -fn issue_1917() { - mod x { - quickcheck! { - fn test(a: String, s: String, b: String) -> TestResult { - if a.find(&s).is_none() { - - TestResult::from_bool(true) - } else { - TestResult::discard() - } - } - } - } -} - -fn issue_1921() { - // Macro with tabs. - lazy_static! { - static ref ONE: u32 = 1; - static ref TWO: u32 = 2; - static ref THREE: u32 = 3; - static ref FOUR: u32 = { - let mut acc = 1; - acc += 1; - acc += 2; - acc - } - } -} - -// #1577 -fn issue1577() { - let json = json!({ - "foo": "bar", - }); -} - -gfx_pipeline!(pipe { - vbuf: gfx::VertexBuffer = (), - out: gfx::RenderTarget = "Target0", -}); - -// #1919 -#[test] -fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(HandleWithDtor<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(HandleWithDtor<::std::os::raw::c_int>) - ) - ); -} - -// #878 -macro_rules! try_opt { - ($expr: expr) => { - match $expr { - Some(val) => val, - - None => { - return None; - } - } - }; -} - -// #2214 -// macro call whose argument is an array with trailing comma. -fn issue2214() { - make_test!( - str_searcher_ascii_haystack, - "bb", - "abbcbbd", - [ - Reject(0, 1), - Match(1, 3), - Reject(3, 4), - Match(4, 6), - Reject(6, 7), - ] - ); -} - -fn special_case_macros() { - let p = eprint!(); - let q = eprint!("{}", 1); - let r = eprint!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = eprint!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = eprintln!("{}", 1); - let r = eprintln!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = eprintln!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = format!("{}", 1); - let r = format!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = format!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = format_args!("{}", 1); - let r = format_args!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = format_args!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = print!("{}", 1); - let r = print!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = print!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = println!("{}", 1); - let r = println!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = println!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = unreachable!("{}", 1); - let r = unreachable!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = unreachable!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - debug!("{}", 1); - debug!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - debug!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - error!("{}", 1); - error!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - error!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - info!("{}", 1); - info!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - info!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - panic!("{}", 1); - panic!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - panic!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - warn!("{}", 1); - warn!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - warn!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - assert!(); - assert!(result == 42); - assert!(result == 42, "Ahoy there, {}!", target); - assert!( - result == 42, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, - input, - expected - ); - assert!( - result == 42, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - assert_eq!(); - assert_eq!(left); - assert_eq!(left, right); - assert_eq!(left, right, "Ahoy there, {}!", target); - assert_eq!( - left, right, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, input, expected - ); - assert_eq!( - first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, - second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, - input, - expected - ); - assert_eq!( - left + 42, - right, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, - input, - expected - ); - assert_eq!( - left, - right, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - write!(&mut s, "Ahoy there, {}!", target); - write!( - &mut s, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, input, expected - ); - write!( - &mut s, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - writeln!(&mut s, "Ahoy there, {}!", target); - writeln!( - &mut s, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, input, expected - ); - writeln!( - &mut s, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); -} - -// #1209 -impl Foo { - /// foo - pub fn foo(&self) -> Bar {} -} - -// #819 -fn macro_in_pattern_position() { - let x = match y { - foo!() => (), - bar!(a, b, c) => (), - bar!(a, b, c,) => (), - baz!(1 + 2 + 3, quux.kaas()) => (), - quux!( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB - ) => (), - }; -} - -macro foo() {} - -pub macro bar($x: ident + $y: expr;) { - fn foo($x: Foo) { - long_function( - a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), - $x.bar($y), - ); - } -} - -macro foo() { - // a comment - fn foo() { - // another comment - bar(); - } -} - -macro lex_err($kind: ident $(, $body: expr)*) { - Err(QlError::LexError(LexError::$kind($($body,)*))) -} diff --git a/tests/target/match-block-trailing-comma.rs b/tests/target/match-block-trailing-comma.rs deleted file mode 100644 index 44d1f289f8e..00000000000 --- a/tests/target/match-block-trailing-comma.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - }, - b => ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - } -} diff --git a/tests/target/match-nowrap-trailing-comma.rs b/tests/target/match-nowrap-trailing-comma.rs deleted file mode 100644 index 19ef2144822..00000000000 --- a/tests/target/match-nowrap-trailing-comma.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - }, - b => ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - } -} diff --git a/tests/target/match-nowrap.rs b/tests/target/match-nowrap.rs deleted file mode 100644 index 9e674b1e2f5..00000000000 --- a/tests/target/match-nowrap.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => foo(), - b => ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - } -} diff --git a/tests/target/match.rs b/tests/target/match.rs deleted file mode 100644 index 83ee4f97b73..00000000000 --- a/tests/target/match.rs +++ /dev/null @@ -1,485 +0,0 @@ -// rustfmt-normalize_comments: true -// Match expressions. - -fn foo() { - // A match expression. - match x { - // Some comment. - a => foo(), - b if 0 < 42 => foo(), - c => { - // Another comment. - // Comment. - an_expression; - foo() - } - Foo(ref bar) => { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } - Pattern1 | Pattern2 | Pattern3 => false, - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn - | Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => blah, - Patternnnnnnnnnnnnnnnnnnn - | Patternnnnnnnnnnnnnnnnnnn - | Patternnnnnnnnnnnnnnnnnnn - | Patternnnnnnnnnnnnnnnnnnn => meh, - - Patternnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => { - meh - } - - Patternnnnnnnnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnnnnnnnn - if looooooooooooooooooooooooooooooooooooooooong_guard => - { - meh - } - - // Test that earlier patterns can take the guard space - (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) - | Patternnnnnnnnnnnnnnnnnnnnnnnnn - if loooooooooooooooooooooooooooooooooooooooooong_guard => {} - - _ => {} - ast::PathParameters::AngleBracketedParameters(ref data) - if data.lifetimes.len() > 0 || data.types.len() > 0 || data.bindings.len() > 0 => {} - } - - let whatever = match something { - /// DOC COMMENT! - Some(_) => 42, - // Comment on an attribute. - #[an_attribute] - // Comment after an attribute. - None => 0, - #[rustfmt_skip] - Blurb => { } - }; -} - -// Test that a match on an overflow line is laid out properly. -fn main() { - let sub_span = - match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - Some(sub_span) => Some(sub_span), - None => sub_span, - }; -} - -// Test that one-line bodies align. -fn main() { - match r { - Variableeeeeeeeeeeeeeeeee => ( - "variable", - vec!["id", "name", "qualname", "value", "type", "scopeid"], - true, - true, - ), - Enummmmmmmmmmmmmmmmmmmmm => ( - "enum", - vec!["id", "qualname", "scopeid", "value"], - true, - true, - ), - Variantttttttttttttttttttttttt => ( - "variant", - vec!["id", "name", "qualname", "type", "value", "scopeid"], - true, - true, - ), - }; - - match x { - y => { /*Block with comment. Preserve me.*/ } - z => { - stmt(); - } - } -} - -fn matches() { - match 1 { - -1 => 10, - 1 => 1, // foo - 2 => 2, - // bar - 3 => 3, - _ => 0, // baz - } -} - -fn match_skip() { - let _ = match Some(1) { - #[rustfmt_skip] - Some( n ) => n, - None => 1, - }; -} - -fn issue339() { - match a { - b => {} - c => {} - d => {} - e => {} - // collapsing here is safe - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} - // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } - h => { - // comment above block - } - i => {} // comment below block - j => { - // comment inside block - } - j2 => { - // comments inside... - } // ... and after - // TODO uncomment when vertical whitespace is handled better - // k => { - // - // // comment with WS above - // } - // l => { - // // comment with ws below - // - // } - m => {} - n => {} - o => {} - p => { - // Dont collapse me - } - q => {} - r => {} - s => 0, // s comment - // t comment - t => 1, - u => 2, - v => {} /* funky block - * comment */ - /* final comment */ - } -} - -fn issue355() { - match mac { - a => println!("a", b), - b => vec![1, 2], - c => vec![3; 4], - d => println!("a", b), - e => vec![1, 2], - f => vec![3; 4], - h => println!("a", b), // h comment - i => vec![1, 2], // i comment - j => vec![3; 4], // j comment - // k comment - k => println!("a", b), - // l comment - l => vec![1, 2], - // m comment - m => vec![3; 4], - // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { - println!("a", b) - } - // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => { - vec![1, 2] - } - // Macro support fails to recognise this macro as splittable - // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { - vec![3; 4] - } - // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { - println!("a", b) - } - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => { - vec![1, 2] - } - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { - vec![3; 4] - } - // Funky bracketing styles - t => println!{"a", b}, - u => vec![1, 2], - v => vec![3; 4], - w => println!["a", b], - x => vec![1, 2], - y => vec![3; 4], - // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec![1, 2], // comment - vc => vec![3; 4], // comment - wc => println!["a", b], // comment - xc => vec![1, 2], // comment - yc => vec![3; 4], // comment - yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( - aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd, - ), - } -} - -fn issue280() { - { - match x { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => { - ch == '\n' - } - ast::ItemConst(ref typ, ref expr) => { - self.process_static_or_const_item(item, &typ, &expr) - } - } - } -} - -fn issue383() { - match resolution.last_private { - LastImport { .. } => false, - _ => true, - }; -} - -fn issue507() { - match 1 { - 1 => unsafe { std::intrinsics::abort() }, - _ => (), - } -} - -fn issue508() { - match s.type_id() { - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLCanvasElement, - ))) => true, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLObjectElement, - ))) => s.has_object_data(), - Some(NodeTypeId::Element(_)) => false, - } -} - -fn issue496() { - { - { - { - match def { - def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { - match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { - Some(const_expr) => x, - } - } - } - } - } - } -} - -fn issue494() { - { - match stmt.node { - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { - result.push(StmtRef::Mirror(Box::new(Stmt { - span: stmt.span, - kind: StmtKind::Expr { - scope: cx.tcx.region_maps.node_extent(id), - expr: expr.to_ref(), - }, - }))) - } - } - } -} - -fn issue386() { - match foo { - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, - BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr - | BiShl | BiShr => false, - } -} - -fn guards() { - match foo { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if fooooooooooooooooooooo - && (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - || cccccccccccccccccccccccccccccccccccccccc) => {} - } -} - -fn issue1371() { - Some(match type_ { - sfEvtClosed => Closed, - sfEvtResized => { - let e = unsafe { *event.size.as_ref() }; - - Resized { - width: e.width, - height: e.height, - } - } - sfEvtLostFocus => LostFocus, - sfEvtGainedFocus => GainedFocus, - sfEvtTextEntered => TextEntered { - unicode: unsafe { - ::std::char::from_u32((*event.text.as_ref()).unicode) - .expect("Invalid unicode encountered on TextEntered event") - }, - }, - sfEvtKeyPressed => { - let e = unsafe { event.key.as_ref() }; - - KeyPressed { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - sfEvtKeyReleased => { - let e = unsafe { event.key.as_ref() }; - - KeyReleased { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - }) -} - -fn issue1395() { - let bar = Some(true); - let foo = Some(true); - let mut x = false; - bar.and_then(|_| match foo { - None => None, - Some(b) => { - x = true; - Some(b) - } - }); -} - -fn issue1456() { - Ok(Recording { - artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { - Nodeset(nodeset) => { - let res: Result, ReadError> = nodeset - .iter() - .map(|node| { - XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) - }) - .collect(); - res? - } - _ => Vec::new(), - }, - }) -} - -fn issue1460() { - let _ = match foo { - REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => { - "internal_spec_insert_internal_spec_insert_internal_spec_insert" - } - _ => "reorder_something", - }; -} - -fn issue525() { - foobar( - f, - "{}", - match *self { - TaskState::Started => "started", - TaskState::Success => "success", - TaskState::Failed => "failed", - }, - ); -} - -// #1838, #1839 -fn match_with_near_max_width() { - let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { - _ => unimplemented!(), - }; - - let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { - _ => unimplemented!(), - }; - - let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression - { - _ => unimplemented!(), - }; - match m { - Variant::Tag - | Variant::Tag2 - | Variant::Tag3 - | Variant::Tag4 - | Variant::Tag5 - | Variant::Tag6 => {} - } -} - -fn match_with_trailing_spaces() { - match x { - #![allow(simple_match)] - Some(..) => 0, - None => 1, - } -} - -fn issue_2099() { - let a = match x {}; - let b = match x {}; - - match x {} -} - -// #2021 -impl<'tcx> Const<'tcx> { - pub fn from_constval<'a>() -> Const<'tcx> { - let val = match *cv { - ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!( - "MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", - cv - ), - }; - } -} - -// #2151 -fn issue_2151() { - match either { - x => {} - y => (), - } -} - -// #2152 -fn issue_2152() { - match m { - "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" - if true => {} - "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => { - true - } - } -} diff --git a/tests/target/max-line-length-in-chars.rs b/tests/target/max-line-length-in-chars.rs deleted file mode 100644 index d49fbb7e30e..00000000000 --- a/tests/target/max-line-length-in-chars.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-max_width: 25 - -// абвгдеёжзийклмнопрст -fn main() {} diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs deleted file mode 100644 index a5d186c5df7..00000000000 --- a/tests/target/mod-1.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Deeply indented modules. - -mod foo { - mod bar { - mod baz {} - } -} - -mod foo { - mod bar { - mod baz { - fn foo() { - bar() - } - } - } - - mod qux {} -} - -mod boxed { - pub use std::boxed::{Box, HEAP}; -} - -pub mod x { - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE, - ) -> *mut FILE { - } -} - -mod y { - // sup boooooiiii -} diff --git a/tests/target/mod-2.rs b/tests/target/mod-2.rs deleted file mode 100644 index 1a093bd5201..00000000000 --- a/tests/target/mod-2.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Some nested mods - -#[cfg(test)] -mod nestedmod; -pub mod no_new_line_beginning; diff --git a/tests/target/mod_skip_child.rs b/tests/target/mod_skip_child.rs deleted file mode 100644 index d48c4a37e81..00000000000 --- a/tests/target/mod_skip_child.rs +++ /dev/null @@ -1,2 +0,0 @@ -// rustfmt-skip_children: true -mod nested_skipped; diff --git a/tests/target/mulit-file.rs b/tests/target/mulit-file.rs deleted file mode 100644 index 1f829b36f3f..00000000000 --- a/tests/target/mulit-file.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Tests that where a single file is referred to in multiple places, we don't -// crash. - -#[cfg(all(foo))] -#[path = "closure.rs"] -pub mod imp; - -#[cfg(all(bar))] -#[path = "closure.rs"] -pub mod imp; diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs deleted file mode 100644 index 0c330d80a56..00000000000 --- a/tests/target/multiple.rs +++ /dev/null @@ -1,178 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-format_strings: true -// Test of lots of random stuff. -// FIXME split this into multiple, self-contained tests. - -#[attr1] -extern crate foo; -#[attr2] -#[attr3] -extern crate foo; -#[attr1] -extern crate foo; -#[attr2] -#[attr3] -extern crate foo; - -use std::cell::*; -use std::{self, any, ascii, borrow, borrow, borrow, borrow, borrow, borrow, borrow, borrow, - borrow, borrow, borrow, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, - boxed, char, char, char, char, char, char, char, char, char, char}; - -mod doc; -mod other; - -// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff -// ffffffffffffffffffffffffffffffffffffffffff - -fn foo(a: isize, b: u32 /* blah blah */, c: f64) {} - -fn foo() -> Box -where - 'a: 'b, - for<'a> D<'b>: 'a, -{ - hello!() -} - -fn baz< - 'a: 'b, // comment on 'a - T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, // comment on T ->( - a: A, - b: B, // comment on b - c: C, -) -> Bob { - #[attr1] - extern crate foo; - #[attr2] - #[attr3] - extern crate foo; - #[attr1] - extern crate foo; - #[attr2] - #[attr3] - extern crate foo; -} - -#[rustfmt_skip] -fn qux(a: dadsfa, // Comment 1 - b: sdfasdfa, // Comment 2 - c: dsfdsafa) // Comment 3 -{ - -} - -/// Blah blah blah. -impl Bar { - fn foo( - &mut self, - a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a - b: sdfasdfsdfasfs, // closing comment - ) -> isize { - } - - /// Blah blah blah. - pub fn f2(self) { - (foo, bar) - } - - #[an_attribute] - fn f3(self) -> Dog {} -} - -/// The `nodes` and `edges` method each return instantiations of -/// `Cow<[T]>` to leave implementers the freedom to create - -/// entirely new vectors or to pass back slices into internally owned -/// vectors. -pub trait GraphWalk<'a, N, E> { - /// Returns all the nodes in this graph. - fn nodes(&'a self) -> Nodes<'a, N>; - /// Returns all of the edges in this graph. - fn edges(&'a self) -> Edges<'a, E>; - /// The source node for `edge`. - fn source(&'a self, edge: &E) -> N; - /// The target node for `edge`. - fn target(&'a self, edge: &E) -> N; -} - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, -} - -struct Bar; - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -fn foo(ann: &'a (PpAnn + 'a)) {} - -fn main() { - for i in 0i32..4 { - println!("{}", i); - } - - while true { - hello(); - } - - let rc = Cell::new( - 42usize, - 42usize, - Cell::new( - 42usize, - remaining_widthremaining_widthremaining_widthremaining_width, - ), - 42usize, - ); - let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment - let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd"; - let s = expand(a, b); -} - -fn deconstruct() -> ( - SocketAddr, - Method, - Headers, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -) { -} - -fn deconstruct( - foo: Bar, -) -> ( - SocketAddr, - Method, - Headers, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -) { -} - -#[rustfmt_skip] -mod a{ -fn foo(x: T) { - let x: T = dfasdf; -} -} diff --git a/tests/target/nested-if-else.rs b/tests/target/nested-if-else.rs deleted file mode 100644 index 9a54789ddcd..00000000000 --- a/tests/target/nested-if-else.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn issue1518() { - Some(Object { - field: if a { - a_thing - } else if b { - b_thing - } else { - c_thing - }, - }) -} diff --git a/tests/target/nested-visual-block.rs b/tests/target/nested-visual-block.rs deleted file mode 100644 index 95b9bc2dea2..00000000000 --- a/tests/target/nested-visual-block.rs +++ /dev/null @@ -1,59 +0,0 @@ -fn main() { - // #1078 - let items = itemize_list( - context.codemap, - field_iter, - "}", - |item| match *item { - StructLitField::Regular(ref field) => field.span.lo(), - StructLitField::Base(ref expr) => { - let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - }, - |item| match *item { - StructLitField::Regular(ref field) => field.span.hi(), - StructLitField::Base(ref expr) => expr.span.hi(), - }, - |item| { - match *item { - StructLitField::Regular(ref field) => rewrite_field( - inner_context, - &field, - &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent), - ), - StructLitField::Base(ref expr) => { - // 2 = .. - expr.rewrite( - inner_context, - &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2), - ).map(|s| format!("..{}", s)) - } - } - }, - context.codemap.span_after(span, "{"), - span.hi(), - ); - - // #1580 - self.0.pool.execute(move || { - let _timer = segments.0.rotate_timer.time(); - if let Err(e) = segments.rotate_async(wal) { - error!("error compacting segment storage WAL", unsafe { error: e.display() }); - } - }); - - // #1581 - bootstrap.checks.register("PERSISTED_LOCATIONS", move || { - if locations2.0.inner_mut.lock().poisoned { - Check::new( - State::Error, - "Persisted location storage is poisoned due to a write failure", - ) - } else { - Check::new(State::Healthy, "Persisted location storage is healthy") - } - }); -} diff --git a/tests/target/nested_skipped/mod.rs b/tests/target/nested_skipped/mod.rs deleted file mode 100644 index 0ab6f081e44..00000000000 --- a/tests/target/nested_skipped/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn ugly() { - 92; -} diff --git a/tests/target/nestedmod/mod.rs b/tests/target/nestedmod/mod.rs deleted file mode 100644 index 1df46293184..00000000000 --- a/tests/target/nestedmod/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -mod mod2a; -mod mod2b; - -mod mymod1 { - use mod2a::{Bar, Foo}; - mod mod3a; -} - -#[path = "mod2c.rs"] -mod mymod2; - -mod submod2; diff --git a/tests/target/nestedmod/mod2a.rs b/tests/target/nestedmod/mod2a.rs deleted file mode 100644 index 5df457a8316..00000000000 --- a/tests/target/nestedmod/mod2a.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This is an empty file containing only -// comments - -// ................... diff --git a/tests/target/nestedmod/mod2b.rs b/tests/target/nestedmod/mod2b.rs deleted file mode 100644 index 9b6ea844e65..00000000000 --- a/tests/target/nestedmod/mod2b.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[path = "mod2a.rs"] -mod c; diff --git a/tests/target/nestedmod/mod2c.rs b/tests/target/nestedmod/mod2c.rs deleted file mode 100644 index 7db4572e777..00000000000 --- a/tests/target/nestedmod/mod2c.rs +++ /dev/null @@ -1,3 +0,0 @@ -// A standard mod - -fn a() {} diff --git a/tests/target/nestedmod/mymod1/mod3a.rs b/tests/target/nestedmod/mymod1/mod3a.rs deleted file mode 100644 index ae09d8ddac0..00000000000 --- a/tests/target/nestedmod/mymod1/mod3a.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Another mod -fn a() {} diff --git a/tests/target/nestedmod/submod2/a.rs b/tests/target/nestedmod/submod2/a.rs deleted file mode 100644 index 120b17145e3..00000000000 --- a/tests/target/nestedmod/submod2/a.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Yet Another mod -// Nested - -use c::a; - -fn foo() {} diff --git a/tests/target/nestedmod/submod2/mod.rs b/tests/target/nestedmod/submod2/mod.rs deleted file mode 100644 index 52f8be91022..00000000000 --- a/tests/target/nestedmod/submod2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Another mod - -mod a; - -use a::a; diff --git a/tests/target/no_new_line_beginning.rs b/tests/target/no_new_line_beginning.rs deleted file mode 100644 index f328e4d9d04..00000000000 --- a/tests/target/no_new_line_beginning.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} diff --git a/tests/target/other.rs b/tests/target/other.rs deleted file mode 100644 index dfce84fcdc4..00000000000 --- a/tests/target/other.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Part of multiple.rs - -fn bob() { - println!("hello other!"); -} diff --git a/tests/target/paths.rs b/tests/target/paths.rs deleted file mode 100644 index 0d2ba797eb7..00000000000 --- a/tests/target/paths.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - let constellation_chan = - Constellation::::start( - compositor_proxy, - resource_task, - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard, - ); - - Quux::< - ParamOne, // Comment 1 - ParamTwo, // Comment 2 - >::some_func(); - - <*mut JSObject>::relocate(entry); - - let x: Foo; - let x: Foo/*::*/; -} - -fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {} diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs deleted file mode 100644 index 39f99d9e123..00000000000 --- a/tests/target/pattern-condense-wildcards.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-condense_wildcard_suffixes: true - -fn main() { - match x { - Butt(..) => "hah", - Tup(_) => "nah", - Quad(_, _, x, _) => " also no rewrite", - Quad(x, ..) => "condense me pls", - Weird(x, _, _, /* dont condense before */ ..) => "pls work", - } -} diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs deleted file mode 100644 index 6c62affb848..00000000000 --- a/tests/target/pattern.rs +++ /dev/null @@ -1,77 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - let z = match x { - "pat1" => 1, - (ref x, ref mut y /* comment */) => 2, - }; - - if let ::CONST = ident { - do_smth(); - } - - let Some(ref xyz /* comment! */) = opt; - - if let None = opt2 { - panic!("oh noes"); - } - - let foo @ bar(f) = 42; - let a::foo(..) = 42; - let [] = 42; - let [a.., b, c] = 42; - let [a, b, c..] = 42; - let [a, b, c, d.., e, f, g] = 42; - let foo {} = 42; - let foo { .. } = 42; - let foo { x, y: ref foo, .. } = 42; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - .. - } = 42; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - } = 42; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - .. - }; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - }; -} - -impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { - fn mutate_fragment(&mut self, fragment: &mut Fragment) { - match **info { - GeneratedContentInfo::ContentItem(ContentItem::Counter( - ref counter_name, - counter_style, - )) => {} - } - } -} - -fn issue_1319() { - if let (Event { .. }, ..) = ev_state {} -} - -fn issue_1874() { - if let Some(()) = x { - y - } -} - -fn combine_patterns() { - let x = match y { - Some(Some(Foo { - z: Bar(..), - a: Bar(..), - b: Bar(..), - })) => z, - _ => return, - }; -} diff --git a/tests/target/pub-restricted.rs b/tests/target/pub-restricted.rs deleted file mode 100644 index 8cc2ade612a..00000000000 --- a/tests/target/pub-restricted.rs +++ /dev/null @@ -1,64 +0,0 @@ -pub(super) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(crate) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -crate enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(in global::path::to::some_mod) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(in local::path::to::some_mod) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} diff --git a/tests/target/remove_blank_lines.rs b/tests/target/remove_blank_lines.rs deleted file mode 100644 index 89b18e40b83..00000000000 --- a/tests/target/remove_blank_lines.rs +++ /dev/null @@ -1,28 +0,0 @@ -fn main() { - let x = 1; - - let y = 2; - - println!("x + y = {}", x + y); -} - -fn foo() { - #![attribute] - - let x = 1; - - // comment -} -// comment after item - -// comment before item -fn bar() { - let x = 1; - // comment after statement - - // comment before statment - let y = 2; - let z = 3; - - println!("x + y + z = {}", x + y + z); -} diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs deleted file mode 100644 index 98fd793cba2..00000000000 --- a/tests/target/single-line-if-else.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Format if-else expressions on a single line, when possible. - -fn main() { - let a = if 1 > 2 { unreachable!() } else { 10 }; - - let a = if x { - 1 - } else if y { - 2 - } else { - 3 - }; - - let b = if cond() { - 5 - } else { - // Brief comment. - 10 - }; - - let c = if cond() { - statement(); - - 5 - } else { - 10 - }; - - let d = if let Some(val) = turbo { - "cool" - } else { - "beans" - }; - - if cond() { - statement(); - } else { - other_statement(); - } - - if true { - do_something() - } - - let x = if veeeeeeeeery_loooooong_condition() { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } else { - bbbbbbbbbb - }; - - let x = if veeeeeeeeery_loooooong_condition() { - aaaaaaaaaaaaaaaaaaaaaaaaa - } else { - bbbbbbbbbb - }; - - funk(if test() { 1 } else { 2 }, arg2); -} diff --git a/tests/target/skip.rs b/tests/target/skip.rs deleted file mode 100644 index 28897ade56f..00000000000 --- a/tests/target/skip.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Test the skip attribute works - -#[rustfmt_skip] -fn foo() { badly; formatted; stuff -; } - -#[rustfmt_skip] -trait Foo -{ -fn foo( -); -} - -impl LateLintPass for UsedUnderscoreBinding { - #[cfg_attr(rustfmt, rustfmt_skip)] - fn check_expr() { // comment - } -} - -fn issue1346() { - #[cfg_attr(rustfmt, rustfmt_skip)] - Box::new(self.inner.call(req).then(move |result| { - match result { - Ok(resp) => Box::new(future::done(Ok(resp))), - Err(e) => { - try_error!(clo_stderr, "{}", e); - Box::new(future::err(e)) - } - } - })) -} - -fn skip_on_statements() { - // Outside block - #[rustfmt_skip] - { - foo; bar; - // junk - } - - { - // Inside block - #![rustfmt_skip] - foo; bar; - // junk - } - - // Semi - #[cfg_attr(rustfmt, rustfmt_skip)] - foo( - 1, 2, 3, 4, - 1, 2, - 1, 2, 3, - ); - - // Local - #[cfg_attr(rustfmt, rustfmt_skip)] - let x = foo( a, b , c); - - // Item - #[cfg_attr(rustfmt, rustfmt_skip)] - use foobar ; - - // Mac - #[cfg_attr(rustfmt, rustfmt_skip)] - vec![ - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, - 1, - 1, 2, - 1, - ]; - - // Expr - #[cfg_attr(rustfmt, rustfmt_skip)] - foo( a, b , c) -} - -// Check that the skip attribute applies to other attributes. -#[rustfmt_skip] -#[cfg -( a , b -)] -fn -main() {} diff --git a/tests/target/skip_mod.rs b/tests/target/skip_mod.rs deleted file mode 100644 index 38ece8f070d..00000000000 --- a/tests/target/skip_mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![rustfmt_skip] -use a :: b -; diff --git a/tests/target/soft-wrapping.rs b/tests/target/soft-wrapping.rs deleted file mode 100644 index 58f3557fbe2..00000000000 --- a/tests/target/soft-wrapping.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 80 -// Soft wrapping for comments. - -// #535, soft wrapping for comments -// Compare the lowest `f32` of both inputs for greater than or equal. The -// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits -// off the result are the upper 96 bits of `a`. - -/// Compare the lowest `f32` of both inputs for greater than or equal. The -/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits -/// off the result are the upper 96 bits of `a`. -fn foo() {} diff --git a/tests/target/space-not-before-newline.rs b/tests/target/space-not-before-newline.rs deleted file mode 100644 index 9d75b726aa0..00000000000 --- a/tests/target/space-not-before-newline.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo { - a: (), - // spaces ^^^ to be removed -} -enum Foo { - Bar, - // spaces ^^^ to be removed -} diff --git a/tests/target/spaces-around-ranges.rs b/tests/target/spaces-around-ranges.rs deleted file mode 100644 index b53e5b58b8c..00000000000 --- a/tests/target/spaces-around-ranges.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-spaces_around_ranges: true - -fn bar(v: &[u8]) {} - -fn foo() { - let a = vec![0; 20]; - for j in 0 ..= 20 { - for i in 0 .. 3 { - bar(a[i .. j]); - bar(a[i ..]); - bar(a[.. j]); - bar(a[..= (j + 1)]); - } - } -} diff --git a/tests/target/static.rs b/tests/target/static.rs deleted file mode 100644 index 5daccf3e7f7..00000000000 --- a/tests/target/static.rs +++ /dev/null @@ -1,27 +0,0 @@ -const FILE_GENERIC_READ: DWORD = - STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; - -static boolnames: &'static [&'static str] = &[ - "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", - "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", - "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", - "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr", -]; - -static mut name: SomeType = - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; - -pub static count: u8 = 10; - -pub const test: &Type = &val; - -impl Color { - pub const WHITE: u32 = 10; -} - -// #1391 -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = - 0 as usize; - -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: - Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/tests/target/string-lit-2.rs b/tests/target/string-lit-2.rs deleted file mode 100644 index 6b95e25a052..00000000000 --- a/tests/target/string-lit-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn main() -> &'static str { - let too_many_lines = "Hello"; - let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ - s - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; -} - -fn issue_1237() { - let msg = "eedadn\n\ - drvtee\n\ - eandsr\n\ - raavrd\n\ - atevrs\n\ - tsrnev\n\ - sdttsa\n\ - rasrtv\n\ - nssdts\n\ - ntnada\n\ - svetve\n\ - tesnvt\n\ - vntsnd\n\ - vrdear\n\ - dvrsen\n\ - enarar"; -} diff --git a/tests/target/string-lit-custom.rs b/tests/target/string-lit-custom.rs deleted file mode 100644 index 50ebb97491b..00000000000 --- a/tests/target/string-lit-custom.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-format_strings: false - -fn main() { - let expected = "; ModuleID = \'foo\' - -; Function Attrs: nounwind -declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 - -declare i32 @write(i32, i8*, i32) - -declare i32 @putchar(i32) - -declare i32 @getchar() - -define i32 @main() { -entry: - ret i32 0 -} - -attributes #0 = { nounwind } -"; -} diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs deleted file mode 100644 index f60002ac618..00000000000 --- a/tests/target/string-lit.rs +++ /dev/null @@ -1,64 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false -// Long string literals - -fn main() -> &'static str { - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let too_many_lines = "Hello"; - - // Make sure we don't break after an escape character. - let odd_length_name = - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - let even_length_name = - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - - let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let raw_string = r#"Do -not -remove -formatting"#; - - filename.replace(" ", "\\"); - - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = - funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); - - let unicode = "a̐éö̲\r\n"; - let unicode2 = "Löwe 老虎 Léopard"; - let unicode3 = "中华Việt Nam"; - let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; - - "stuffin'" -} - -fn issue682() { - let a = "hello \\ o/"; - let b = a.replace("\\ ", "\\"); -} - -fn issue716() { - println!( - "forall x. mult(e(), x) = x /\\ - forall x. mult(x, x) = e()" - ); -} - -fn issue_1282() { - { - match foo { - Permission::AndroidPermissionAccessLocationExtraCommands => { - "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" - } - } - } -} - -// #1987 -#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] \ - -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] -extern "C" {} diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs deleted file mode 100644 index 1cc73d14060..00000000000 --- a/tests/target/string_punctuation.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false - -fn main() { - println!( - "ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ - Likethisssssssssssss" - ); - format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); - println!( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ - adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ - ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea" - ); -} diff --git a/tests/target/struct-field-attributes.rs b/tests/target/struct-field-attributes.rs deleted file mode 100644 index 5d6e92a91d9..00000000000 --- a/tests/target/struct-field-attributes.rs +++ /dev/null @@ -1,56 +0,0 @@ -// #1535 -#![feature(struct_field_attributes)] - -struct Foo { - bar: u64, - - #[cfg(test)] - qux: u64, -} - -fn do_something() -> Foo { - Foo { - bar: 0, - - #[cfg(test)] - qux: 1, - } -} - -fn main() { - do_something(); -} - -// #1462 -struct Foo { - foo: usize, - #[cfg(feature = "include-bar")] - bar: usize, -} - -fn new_foo() -> Foo { - Foo { - foo: 0, - #[cfg(feature = "include-bar")] - bar: 0, - } -} - -// #2044 -pub enum State { - Closure( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] - GcPtr, - ), -} - -struct Fields( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] - Arc>, -); - -// #2309 -pub struct A { - #[doc = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] - pub foos: Vec, -} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs deleted file mode 100644 index 648c723d357..00000000000 --- a/tests/target/struct_lits.rs +++ /dev/null @@ -1,191 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: f(), - b: b(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a: Bar, b: f() }; - - Quux { - x: if cond { - bar(); - }, - y: baz(), - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { - // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, - } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { - memb: T, - } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S { a: 0, ..b }; -} - -fn issue201_2() { - let s = S { a: S2 { ..c }, ..b }; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo { a: 1, b: f(2) }; - Foo { - a: 1, - b: f(2), - ..g(3) - }; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { - ..base - }; - IntrinsicISizesContribution { - content_intrinsic_sizes: IntrinsicISizes { - minimum_inline_size: 0, - }, - }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { - a: bb, - c: dd, - e: ff, - }; - - Foo { - a: ddddddddddddddddddddd, - b: cccccccccccccccccccccccccccccccccccccc, - }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { - a: aaaaaaaaaa, - b: bbbbbbbb, - c: cccccccccc, - d: dddddddddd, // a comment - e: eeeeeeeee, - }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, ..base }; - Foo { - aaaaaaaaaa, - bbbbbbbb, - cccccccccc, - dddddddddd, // a comment - eeeeeeeee, - }; - Record { - ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; -} diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs deleted file mode 100644 index c831dc7a8ba..00000000000 --- a/tests/target/struct_lits_multiline.rs +++ /dev/null @@ -1,117 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-struct_lit_single_line: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { - a: x, - }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: foo(), - b: bar(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: foo(), - b: bar(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { - a: Bar, - b: foo(), - }; - - Quux { - x: if cond { - bar(); - }, - y: baz(), - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { - // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, - } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { - memb: T, - } - let foo = Foo:: { - memb: 10, - }; -} - -fn issue201() { - let s = S { - a: 0, - ..b - }; -} - -fn issue201_2() { - let s = S { - a: S2 { - ..c - }, - ..b - }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; -} diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs deleted file mode 100644 index 7e93b91d8c1..00000000000 --- a/tests/target/struct_lits_visual.rs +++ /dev/null @@ -1,50 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* Comment */ - // Comment - b: bar(), /* Comment */ }; - - Foo { a: Bar, b: f() }; - - Quux { x: if cond { - bar(); - }, - y: baz(), }; - - Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - z: zzzzz, /* test */ }; - - A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; - - Diagram { // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, } -} diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs deleted file mode 100644 index 2809d3a2612..00000000000 --- a/tests/target/struct_lits_visual_multiline.rs +++ /dev/null @@ -1,50 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-struct_lit_single_line: false -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* Comment */ - // Comment - b: bar(), /* Comment */ }; - - Foo { a: Bar, - b: foo(), }; - - Quux { x: if cond { - bar(); - }, - y: baz(), }; - - A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; - - Diagram { // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, } -} diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs deleted file mode 100644 index 369feae71d2..00000000000 --- a/tests/target/struct_tuple_visual.rs +++ /dev/null @@ -1,37 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual -fn foo() { - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment - foo(), /* Comment */ - // Comment - bar() /* Comment */); - - Foo(Bar, f()); - - Quux(if cond { - bar(); - }, - baz()); - - Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - zzzzz /* test */); - - A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - Item); - - Diagram(// o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - G) -} diff --git a/tests/target/structs.rs b/tests/target/structs.rs deleted file mode 100644 index 59a57a9b5b4..00000000000 --- a/tests/target/structs.rs +++ /dev/null @@ -1,332 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField, -} - -// #1095 -struct S { - t: T, -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] // only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct NewInt( - pub i32, - SomeType, // inline comment - T, // sup -); - -struct Qux< - 'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy, ->( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple( - // Comment 1 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - c: C, // Comment C -} - -struct Baz { - a: A, - - b: B, - c: C, - - d: D, -} - -struct Baz { - // Comment A - a: A, - - // Comment B - b: B, - // Comment C - c: C, -} - -// Will this be a one-liner? -struct Tuple( - A, // Comment - B, -); - -pub struct State time::Timespec> { - now: F, -} - -pub struct State ()> { - now: F, -} - -pub struct State { - now: F, -} - -struct Palette { - /// A map of indices in the palette to a count of pixels in approximately - /// that color - foo: i32, -} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ - // Another pre comment - #[attr1] - #[attr2] - pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC - * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(T); -struct Foo(T) -where - T: Copy, - T: Eq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -); -struct Foo( - TTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU, // Bar - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU, -); - -mod m { - struct X - where - T: Sized, - { - a: T, - } -} - -struct Foo( - TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU, -); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - -struct Foo {} -struct Foo {} -struct Foo { - // comment -} -struct Foo { - // trailing space -> -} -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -struct Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} - -// structs with long identifier -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{ - x: i32, -} - -// structs with visibility, do not duplicate visibility (#2110). -pub(self) struct Foo {} -pub(super) struct Foo {} -pub(crate) struct Foo {} -pub(self) struct Foo(); -pub(super) struct Foo(); -pub(crate) struct Foo(); - -// #2125 -pub struct ReadinessCheckRegistry( - Mutex, Box ReadinessCheck + Sync + Send>>>, -); - -// #2144 unit struct with generics -struct MyBox; -struct MyBoxx -where - T: ?Sized, - S: Clone; - -// #2208 -struct Test { - /// foo - #[serde(default)] - pub join: Vec, - #[serde(default)] - pub tls: bool, -} diff --git a/tests/target/trailing-comma-never.rs b/tests/target/trailing-comma-never.rs deleted file mode 100644 index 3df0c7950eb..00000000000 --- a/tests/target/trailing-comma-never.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-trailing_comma: Never - -enum X { - A, - B -} - -enum Y { - A, - B -} - -enum TupX { - A(u32), - B(i32, u16) -} - -enum TupY { - A(u32), - B(i32, u16) -} - -enum StructX { - A { s: u16 }, - B { u: u32, i: i32 } -} - -enum StructY { - A { s: u16 }, - B { u: u32, i: i32 } -} diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs deleted file mode 100644 index 61b82035450..00000000000 --- a/tests/target/trailing_commas.rs +++ /dev/null @@ -1,103 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// rustfmt-trailing_comma: Always - -fn main() { - match foo { - x => {}, - y => { - foo(); - }, - _ => x, - } -} - -fn f< - S, T, ->( - x: T, - y: S, -) -> T -where - T: P, - S: Q, -{ - x -} - -impl Trait for T -where - T: P, -{ - fn f(x: T) -> T - where - T: Q + R, - { - x - } -} - -struct Pair< - S, T, -> where - T: P, - S: P + Q, -{ - a: T, - b: S, -} - -struct TupPair< - S, T, ->(S, T,) -where - T: P, - S: P + Q; - -enum E< - S, T, -> where - S: P, - T: P, -{ - A { a: T, }, -} - -type Double< - T, -> where - T: P, - T: Q, -= Pair< - T, T, ->; - -extern "C" { - fn f< - S, T, - >( - x: T, - y: S, - ) -> T - where - T: P, - S: Q; -} - -trait Q< - S, T, -> where - T: P, - S: R, -{ - fn f< - U, V, - >( - self, - x: T, - y: S, - z: U, - ) -> Self - where - U: P, - V: P; -} diff --git a/tests/target/trait.rs b/tests/target/trait.rs deleted file mode 100644 index 133e8babedb..00000000000 --- a/tests/target/trait.rs +++ /dev/null @@ -1,132 +0,0 @@ -// Test traits - -trait Foo { - fn bar(x: i32) -> Baz { - Baz::new() - } - - fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; - - fn foo( - a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - ) -> RetType; // Some comment - - fn baz(&mut self) -> i32; - - fn increment(&mut self, x: i32); - - fn read(&mut self, x: BufReader /* Used to be MemReader */) - where - R: Read; -} - -pub trait WriteMessage { - fn write_message(&mut self, &FrontendMessage) -> io::Result<()>; -} - -trait Runnable { - fn handler(self: &Runnable); -} - -trait TraitWithExpr { - fn fn_with_expr(x: [i32; 1]); -} - -trait Test { - fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result - where - F: FnOnce(&mut Self) -> Result; -} - -trait T {} - -trait Foo { - type Bar: Baz; - type Inner: Foo = Box; -} - -trait ConstCheck: Foo -where - T: Baz, -{ - const J: i32; -} - -trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt -where - T: Foo, -{ -} - -trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt -where - T: Foo, -{ -} - -trait FooBar - : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt -where - J: Bar, -{ - fn test(); -} - -trait WhereList -where - T: Foo, - J: Bar, -{ -} - -trait X /* comment */ {} -trait Y // comment -{ -} - -// #2055 -pub trait Foo: -// A and C -A + C -// and B - + B -{} - -// #2158 -trait Foo { - type ItRev = > as UntypedTimeSeries>::IterRev; - type IteRev = - > as UntypedTimeSeries>::IterRev; -} - -// #2331 -trait MyTrait< - AAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBB, - CCCCCCCCCCCCCCCCCCCC, - DDDDDDDDDDDDDDDDDDDD, -> { - fn foo() {} -} - -// Trait aliases -trait FooBar = Foo + Bar; -trait FooBar = Foo + Bar; -trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAA = - BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAA = - BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = - FooBar; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA< - A, - B, - C, - D, - E, -> = FooBar; -#[rustfmt_skip] -trait FooBar = Foo - + Bar; diff --git a/tests/target/try-conversion.rs b/tests/target/try-conversion.rs deleted file mode 100644 index e16fba278d2..00000000000 --- a/tests/target/try-conversion.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-use_try_shorthand: true - -fn main() { - let x = some_expr()?; - - let y = a.very - .loooooooooooooooooooooooooooooooooooooong() - .chain() - .inside() - .weeeeeeeeeeeeeee()? - .test() - .0 - .x; -} - -fn test() { - a? -} - -fn issue1291() { - fs::create_dir_all(&gitfiledir).chain_err(|| { - format!( - "failed to create the {} submodule directory for the workarea", - name - ) - })?; -} diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs deleted file mode 100644 index a22586284dc..00000000000 --- a/tests/target/tuple.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Test tuple litterals - -fn foo() { - let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - ); - let aaaaaaaaaaaaaaaaaaaaaa = ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaa, - aaaa, - ); - let a = (a,); - - let b = ( - // This is a comment - b, // Comment - b, /* Trailing comment */ - ); - - // #1063 - foo(x.0 .0); -} - -fn a() { - (( - aaaaaaaa, - aaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - ),) -} - -fn b() { - ( - ( - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - bbbbbbbbbbbbbbbbbb, - ) -} - -fn issue550() { - self.visitor.visit_volume( - self.level.sector_id(sector), - ( - floor_y, - if is_sky_flat(ceil_tex) { - from_wad_height(self.height_range.1) - } else { - ceil_y - }, - ), - ); -} - -fn issue775() { - if indent { - let a = mk_object(&[ - ("a".to_string(), Boolean(true)), - ( - "b".to_string(), - Array(vec![ - mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), String("".to_string()))]), - ]), - ), - ]); - } -} - -fn issue1725() { - bench_antialiased_lines!( - bench_draw_antialiased_line_segment_diagonal, - (10, 10), - (450, 450) - ); - bench_antialiased_lines!( - bench_draw_antialiased_line_segment_shallow, - (10, 10), - (450, 80) - ); -} diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs deleted file mode 100644 index a2f082ba4b4..00000000000 --- a/tests/target/type-ascription.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; - - let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - x: u32 - 1u32 / 10f32: u32 -} diff --git a/tests/target/type-punctuation.rs b/tests/target/type-punctuation.rs deleted file mode 100644 index f35293de626..00000000000 --- a/tests/target/type-punctuation.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed - -struct Foo -where - U: Eq+Clone, { - // body -} - -trait Foo<'a, T=usize> -where - T: 'a+Eq+Clone, -{ - type Bar: Eq+Clone; -} - -trait Foo: Eq+Clone { - // body -} - -impl Foo<'a> for Bar -where - for<'a> T: 'a+Eq+Clone, -{ - // body -} - -fn foo<'a, 'b, 'c>() -where - 'a: 'b+'c, -{ - // body -} - -fn Foo+Foo>() { - let i = 6; -} diff --git a/tests/target/type.rs b/tests/target/type.rs deleted file mode 100644 index 2f35e796512..00000000000 --- a/tests/target/type.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-normalize_comments: true -fn types() { - let x: [Vec<_>] = []; - let y: *mut [SomeType; konst_funk()] = expr(); - let z: (/* #digits */ usize, /* exp */ i16) = funk(); - let z: (usize /* #digits */, i16 /* exp */) = funk(); -} - -struct F { - f: extern "C" fn(x: u8, ... /* comment */), - g: extern "C" fn(x: u8, /* comment */ ...), - h: extern "C" fn(x: u8, ...), - i: extern "C" fn( - x: u8, - // comment 4 - y: String, // comment 3 - z: Foo, - // comment - ... // comment 2 - ), -} - -fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} - -fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} - -fn impl_trait_fn_2() -> impl Future {} - -fn issue_1234() { - do_parse!(name: take_while1!(is_token) >> (Header)) -} diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs deleted file mode 100644 index 862f9ecbeec..00000000000 --- a/tests/target/type_alias.rs +++ /dev/null @@ -1,76 +0,0 @@ -// rustfmt-normalize_comments: true - -type PrivateTest<'a, I> = ( - Box + 'a>, - Box + 'a>, -); - -pub type PublicTest<'a, I, O> = Result< - Vec, - Box + 'a>, - Box + 'a>, ->; - -pub type LongGenericListTest< - 'a, - 'b, - 'c, - 'd, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - A, - B, - C, -> = Option>; - -pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; - -pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = - Vec; - -pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = - Vec; - -pub type GenericsFitButNotEqualTest< - 'a, - 'b, - 'c, - 'd, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - A1, - B, - C, -> = Vec; - -pub type CommentTest< - // Lifetime - 'a, - // Type - T, -> = (); - -pub type WithWhereClause -where - T: Clone, - LONGPARAMETERNAME: Clone + Eq + OtherTrait, -= Option; - -pub type Exactly100CharstoEqualWhereTest -where - T: Clone + Ord + Eq + SomeOtherTrait, -= Option; - -pub type Exactly101CharstoEqualWhereTest -where - T: Clone + Ord + Eq + SomeOtherTrait, -= Option; - -type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); - -// #1683 -pub type Between = - super::operators::Between, AsExpr>>; -pub type NotBetween = - super::operators::NotBetween, AsExpr>>; diff --git a/tests/target/unindent_if_else_cond_comment.rs b/tests/target/unindent_if_else_cond_comment.rs deleted file mode 100644 index 98621b1eed1..00000000000 --- a/tests/target/unindent_if_else_cond_comment.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Comments on else block. See #1575. - -fn example() { - // `if` comment - if x { - foo(); - // `else if` comment - } else if y { - foo(); - // Comment on `else if`. - // Comment on `else if`. - } else if z { - bar(); - /* - * Multi line comment on `else if` - */ - } else if xx { - bar(); - /* Single line comment on `else if` */ - } else if yy { - foo(); - // `else` comment - } else { - foo(); - // Comment at the end of `else` block - }; -} diff --git a/tests/target/unions.rs b/tests/target/unions.rs deleted file mode 100644 index eb6c3ae7e15..00000000000 --- a/tests/target/unions.rs +++ /dev/null @@ -1,196 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -/// A Doc comment -#[AnAttribute] -pub union Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField, -} - -// #1029 -pub union Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -union X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub union Writebatch { - #[allow(dead_code)] // only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -// With a where clause and generics. -pub union Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -union Baz { - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C -} - -union Baz { - a: A, // Comment A - - b: B, // Comment B - - c: C, // Comment C -} - -union Baz { - a: A, - - b: B, - c: C, - - d: D, -} - -union Baz { - // Comment A - a: A, - - // Comment B - b: B, - // Comment C - c: C, -} - -pub union State time::Timespec> { - now: F, -} - -pub union State ()> { - now: F, -} - -pub union State { - now: F, -} - -union Palette { - /// A map of indices in the palette to a count of pixels in approximately - /// that color - foo: i32, -} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -union FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ - // Another pre comment - #[attr1] - #[attr2] - pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC - * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -mod m { - union X - where - T: Sized, - { - a: T, - } -} - -union Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - -union Foo {} -union Foo {} -union Foo { - // comment -} -union Foo { - // trailing space -> -} -union Foo { /* comment */ } - -union LongUnion { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -union Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs deleted file mode 100644 index 1e83d5b3abc..00000000000 --- a/tests/target/where-clause-rfc.rs +++ /dev/null @@ -1,128 +0,0 @@ -// rustfmt-indent_style: Block - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -where - T: FOo, - U: Bar, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -where - T: FOo, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, - shape: &Shape, -) where - T: FOo, - U: Bar, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, - shape: &Shape, -) where - T: FOo, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, -) -> Option -where - T: FOo, - U: Bar, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, -) -> Option -where - T: FOo, -{ - let mut effects = HashMap::new(); -} - -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType - where - F: FnMut(Self::Item) -> bool; - - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType - where - F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType -where - F: FnMut(Self::Item) -> bool, -{ -} - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) -where - A: LongTrait; - -struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) -where - A: LongTrait1234; - -struct AlwaysOnNextLine -where - A: LongTrait, -{ - x: i32, -} - -pub trait SomeTrait -where - T: Something - + Sync - + Send - + Display - + Debug - + Copy - + Hash - + Debug - + Display - + Write - + Read - + FromStr, -{ -} - -// #2020 -impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { - fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) - where - F: for<'b> FnMut( - &mut ProbeContext<'b, 'gcx, 'tcx>, - ty::PolyTraitRef<'tcx>, - ty::AssociatedItem, - ), - { - // ... - } -} diff --git a/tests/target/where-clause.rs b/tests/target/where-clause.rs deleted file mode 100644 index 724f3b34bf0..00000000000 --- a/tests/target/where-clause.rs +++ /dev/null @@ -1,29 +0,0 @@ -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType - where - F: FnMut(Self::Item) -> bool; - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType - where - F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType -where - F: FnMut(Self::Item) -> bool, -{ -} - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) -where - A: LongTrait; - -struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) -where - A: LongTrait1234; - -struct AlwaysOnNextLine -where - A: LongTrait, -{ - x: i32, -} diff --git a/tests/writemode/source/fn-single-line.rs b/tests/writemode/source/fn-single-line.rs deleted file mode 100644 index 289dd9aa093..00000000000 --- a/tests/writemode/source/fn-single-line.rs +++ /dev/null @@ -1,80 +0,0 @@ -// rustfmt-fn_single_line: true -// rustfmt-write_mode: checkstyle -// Test single-line functions. - -fn foo_expr() { - 1 -} - -fn foo_stmt() { - foo(); -} - -fn foo_decl_local() { - let z = 5; - } - -fn foo_decl_item(x: &mut i32) { - x = 3; -} - - fn empty() { - -} - -fn foo_return() -> String { - "yay" -} - -fn foo_where() -> T where T: Sync { - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space () { - 1 -} - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) { - } -} - -trait CoolerTypes { fn dummy(&self) { -} -} - -fn Foo() where T: Bar { -} diff --git a/tests/writemode/target/checkstyle.xml b/tests/writemode/target/checkstyle.xml deleted file mode 100644 index 30ab5ad7579..00000000000 --- a/tests/writemode/target/checkstyle.xml +++ /dev/null @@ -1,2 +0,0 @@ - - -- cgit 1.4.1-3-g733a5 From 66b25f1b4a528d1e1db173dabd3f9fcfe103615b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 7 Feb 2018 22:48:52 +0900 Subject: Create rustfmt_config crate --- rustfmt-config/Cargo.toml | 16 + rustfmt-config/src/config_type.rs | 380 +++++++++++++++++++ rustfmt-config/src/file_lines.rs | 319 ++++++++++++++++ rustfmt-config/src/lib.rs | 252 ++++++++++++ rustfmt-config/src/lists.rs | 105 +++++ rustfmt-config/src/macros.rs | 10 + rustfmt-config/src/options.rs | 244 ++++++++++++ rustfmt-config/src/summary.rs | 144 +++++++ src/config.rs | 781 -------------------------------------- src/file_lines.rs | 306 --------------- src/summary.rs | 134 ------- 11 files changed, 1470 insertions(+), 1221 deletions(-) create mode 100644 rustfmt-config/Cargo.toml create mode 100644 rustfmt-config/src/config_type.rs create mode 100644 rustfmt-config/src/file_lines.rs create mode 100644 rustfmt-config/src/lib.rs create mode 100644 rustfmt-config/src/lists.rs create mode 100644 rustfmt-config/src/macros.rs create mode 100644 rustfmt-config/src/options.rs create mode 100644 rustfmt-config/src/summary.rs delete mode 100644 src/config.rs delete mode 100644 src/file_lines.rs delete mode 100644 src/summary.rs (limited to 'src') diff --git a/rustfmt-config/Cargo.toml b/rustfmt-config/Cargo.toml new file mode 100644 index 00000000000..c7e5c9d8315 --- /dev/null +++ b/rustfmt-config/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustfmt-config" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "A library for configuring and customizing rustfmt" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +categories = ["development-tools"] + +[dependencies] +rustc-ap-syntax = "29.0.0" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +toml = "0.4" \ No newline at end of file diff --git a/rustfmt-config/src/config_type.rs b/rustfmt-config/src/config_type.rs new file mode 100644 index 00000000000..51642570fdf --- /dev/null +++ b/rustfmt-config/src/config_type.rs @@ -0,0 +1,380 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use file_lines::FileLines; +use options::WidthHeuristics; + +/// Trait for types that can be used in `Config`. +pub trait ConfigType: Sized { + /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a + /// pipe-separated list of variants; for other types it returns "". + fn doc_hint() -> String; +} + +impl ConfigType for bool { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for usize { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for isize { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for String { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for FileLines { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for WidthHeuristics { + fn doc_hint() -> String { + String::new() + } +} + +/// Check if we're in a nightly build. +/// +/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap +/// to "stable", "beta", or "nightly" depending on what toolchain is being built. +/// If we are being built as part of the stable or beta toolchains, we want +/// to disable unstable configuration options. +/// +/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), +/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the +/// nightly compiler when installed from crates.io, default to nightly mode. +macro_rules! is_nightly_channel { + () => { + option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(true) + }; +} + +macro_rules! create_config { + ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( + #[derive(Clone)] + pub struct Config { + // For each config item, we store a bool indicating whether it has + // been accessed and the value, and a bool whether the option was + // manually initialised, or taken from the default, + $($i: (Cell, bool, $ty, bool)),+ + } + + // Just like the Config struct but with each property wrapped + // as Option. This is used to parse a rustfmt.toml that doesn't + // specify all properties of `Config`. + // We first parse into `PartialConfig`, then create a default `Config` + // and overwrite the properties with corresponding values from `PartialConfig`. + #[derive(Deserialize, Serialize, Clone)] + pub struct PartialConfig { + $(pub $i: Option<$ty>),+ + } + + impl PartialConfig { + pub fn to_toml(&self) -> Result { + // Non-user-facing options can't be specified in TOML + let mut cloned = self.clone(); + cloned.file_lines = None; + cloned.verbose = None; + cloned.width_heuristics = None; + + toml::to_string(&cloned) + .map_err(|e| format!("Could not output config: {}", e.to_string())) + } + } + + // Macro hygiene won't allow us to make `set_$i()` methods on Config + // for each item, so this struct is used to give the API to set values: + // `config.get().option(false)`. It's pretty ugly. Consider replacing + // with `config.set_option(false)` if we ever get a stable/usable + // `concat_idents!()`. + pub struct ConfigSetter<'a>(&'a mut Config); + + impl<'a> ConfigSetter<'a> { + $( + pub fn $i(&mut self, value: $ty) { + (self.0).$i.2 = value; + if stringify!($i) == "use_small_heuristics" { + self.0.set_heuristics(); + } + } + )+ + } + + // Query each option, returns true if the user set the option, false if + // a default was used. + pub struct ConfigWasSet<'a>(&'a Config); + + impl<'a> ConfigWasSet<'a> { + $( + pub fn $i(&self) -> bool { + (self.0).$i.1 + } + )+ + } + + impl Config { + pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool { + if self.was_set().required_version() { + let version = env!("CARGO_PKG_VERSION"); + let required_version = self.required_version(); + if version != required_version { + println!( + "Error: rustfmt version ({}) doesn't match the required version ({})", + version, + required_version, + ); + error_summary.add_formatting_error(); + return false; + } + } + + true + } + + $( + pub fn $i(&self) -> $ty { + self.$i.0.set(true); + self.$i.2.clone() + } + )+ + + pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { + ConfigSetter(self) + } + + pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { + ConfigWasSet(self) + } + + fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { + $( + if let Some(val) = parsed.$i { + if self.$i.3 { + self.$i.1 = true; + self.$i.2 = val; + } else { + if is_nightly_channel!() { + self.$i.1 = true; + self.$i.2 = val; + } else { + eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ + available in nightly channel.", stringify!($i), val); + } + } + } + )+ + self.set_heuristics(); + self + } + + pub fn from_toml(toml: &str) -> Result { + let parsed: toml::Value = + toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; + let mut err: String = String::new(); + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for key in table.keys() { + match &**key { + $( + stringify!($i) => (), + )+ + _ => { + let msg = + &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } + } + } + } + match parsed.try_into() { + Ok(parsed_config) => { + if !err.is_empty() { + eprint!("{}", err); + } + Ok(Config::default().fill_from_parsed_config(parsed_config)) + } + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); + err.push_str("Please check your config file."); + Err(err) + } + } + } + + pub fn used_options(&self) -> PartialConfig { + PartialConfig { + $( + $i: if self.$i.0.get() { + Some(self.$i.2.clone()) + } else { + None + }, + )+ + } + } + + pub fn all_options(&self) -> PartialConfig { + PartialConfig { + $( + $i: Some(self.$i.2.clone()), + )+ + } + } + + pub fn override_value(&mut self, key: &str, val: &str) + { + match key { + $( + stringify!($i) => { + self.$i.2 = val.parse::<$ty>() + .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", + stringify!($i), + val, + stringify!($ty))); + } + )+ + _ => panic!("Unknown config key in override: {}", key) + } + + if key == "use_small_heuristics" { + self.set_heuristics(); + } + } + + /// Construct a `Config` from the toml file specified at `file_path`. + /// + /// This method only looks at the provided path, for a method that + /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. + /// + /// Return a `Config` if the config could be read and parsed from + /// the file, Error otherwise. + pub fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + /// Resolve the config for input in `dir`. + /// + /// Searches for `rustfmt.toml` beginning with `dir`, and + /// recursively checking parents of `dir` if no config file is found. + /// If no config file exists in `dir` or in any parent, a + /// default `Config` will be returned (and the returned path will be empty). + /// + /// Returns the `Config` to use, and the path of the project file if there was + /// one. + pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + + /// Try to find a project file in the given directory and its parents. + /// Returns the path of a the nearest project file if one exists, + /// or `None` if no project file was found. + fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => () + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + return Ok(None); + } + } + } + + match resolve_project_file(dir)? { + None => Ok((Config::default(), None)), + Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + } + } + + + pub fn print_docs() { + use std::cmp; + const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"]; + let max = 0; + $( let max = cmp::max(max, stringify!($i).len()+1); )+ + let mut space_str = String::with_capacity(max); + for _ in 0..max { + space_str.push(' '); + } + println!("Configuration Options:"); + $( + let name_raw = stringify!($i); + + if !HIDE_OPTIONS.contains(&name_raw) { + let mut name_out = String::with_capacity(max); + for _ in name_raw.len()..max-1 { + name_out.push(' ') + } + name_out.push_str(name_raw); + name_out.push(' '); + println!("{}{} Default: {:?}", + name_out, + <$ty>::doc_hint(), + $def); + $( + println!("{}{}", space_str, $dstring); + )+ + println!(); + } + )+ + } + + fn set_heuristics(&mut self) { + if self.use_small_heuristics.2 { + self.set().width_heuristics(WidthHeuristics::default()); + } else { + self.set().width_heuristics(WidthHeuristics::null()); + } + } + } + + // Template for the default configuration + impl Default for Config { + fn default() -> Config { + Config { + $( + $i: (Cell::new(false), false, $def, $stb), + )+ + } + } + } + ) +} diff --git a/rustfmt-config/src/file_lines.rs b/rustfmt-config/src/file_lines.rs new file mode 100644 index 00000000000..87e201345de --- /dev/null +++ b/rustfmt-config/src/file_lines.rs @@ -0,0 +1,319 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains types and functions to support formatting specific line ranges. + +use std::{cmp, iter, str}; +use std::collections::HashMap; +use std::rc::Rc; + +use serde::de::{Deserialize, Deserializer}; +use serde_json as json; + +use syntax::codemap::{FileMap, FileName}; + +/// A range of lines in a file, inclusive of both ends. +pub struct LineRange { + pub file: Rc, + pub lo: usize, + pub hi: usize, +} + +impl LineRange { + pub fn file_name(&self) -> &FileName { + &self.file.name + } +} + +/// A range that is inclusive of both ends. +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] +pub struct Range { + lo: usize, + hi: usize, +} + +impl<'a> From<&'a LineRange> for Range { + fn from(range: &'a LineRange) -> Range { + Range::new(range.lo, range.hi) + } +} + +impl Range { + pub fn new(lo: usize, hi: usize) -> Range { + Range { lo, hi } + } + + fn is_empty(self) -> bool { + self.lo > self.hi + } + + fn contains(self, other: Range) -> bool { + if other.is_empty() { + true + } else { + !self.is_empty() && self.lo <= other.lo && self.hi >= other.hi + } + } + + fn intersects(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + (self.lo <= other.hi && other.hi <= self.hi) + || (other.lo <= self.hi && self.hi <= other.hi) + } + } + + fn adjacent_to(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + self.hi + 1 == other.lo || other.hi + 1 == self.lo + } + } + + /// Returns a new `Range` with lines from `self` and `other` if they were adjacent or + /// intersect; returns `None` otherwise. + fn merge(self, other: Range) -> Option { + if self.adjacent_to(other) || self.intersects(other) { + Some(Range::new( + cmp::min(self.lo, other.lo), + cmp::max(self.hi, other.hi), + )) + } else { + None + } + } +} + +/// A set of lines in files. +/// +/// It is represented as a multimap keyed on file names, with values a collection of +/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all +/// lines in all files. +#[derive(Clone, Debug, Default)] +pub struct FileLines(Option>>); + +/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, +/// and ordered by their start point. +fn normalize_ranges(ranges: &mut HashMap>) { + for ranges in ranges.values_mut() { + ranges.sort(); + let mut result = vec![]; + { + let mut iter = ranges.into_iter().peekable(); + while let Some(next) = iter.next() { + let mut next = *next; + while let Some(&&mut peek) = iter.peek() { + if let Some(merged) = next.merge(peek) { + iter.next().unwrap(); + next = merged; + } else { + break; + } + } + result.push(next) + } + } + *ranges = result; + } +} + +impl FileLines { + /// Creates a `FileLines` that contains all lines in all files. + pub fn all() -> FileLines { + FileLines(None) + } + + pub fn from_ranges(mut ranges: HashMap>) -> FileLines { + normalize_ranges(&mut ranges); + FileLines(Some(ranges)) + } + + /// Returns an iterator over the files contained in `self`. + pub fn files(&self) -> Files { + Files(self.0.as_ref().map(|m| m.keys())) + } + + /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in + /// the designated file (if any) and returns true if `f` ever does. + fn file_range_matches(&self, file_name: &FileName, f: F) -> bool + where + F: FnMut(&Range) -> bool, + { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) { + Some(ranges) => ranges.iter().any(f), + None => false, + } + } + + /// Returns true if `range` is fully contained in `self`. + pub fn contains(&self, range: &LineRange) -> bool { + self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) + } + + /// Returns true if any lines in `range` are in `self`. + pub fn intersects(&self, range: &LineRange) -> bool { + self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) + } + + /// Returns true if `line` from `file_name` is in `self`. + pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool { + self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) + } + + /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. + pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { + self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) + } +} + +/// `FileLines` files iterator. +pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec>>); + +impl<'a> iter::Iterator for Files<'a> { + type Item = &'a FileName; + + fn next(&mut self) -> Option<&'a FileName> { + self.0.as_mut().and_then(Iterator::next) + } +} + +fn canonicalize_path_string(file: &FileName) -> Option { + match *file { + FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real), + _ => Some(file.clone()), + } +} + +// This impl is needed for `Config::override_value` to work for use in tests. +impl str::FromStr for FileLines { + type Err = String; + + fn from_str(s: &str) -> Result { + let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; + let mut m = HashMap::new(); + for js in v { + let (s, r) = JsonSpan::into_tuple(js)?; + m.entry(s).or_insert_with(|| vec![]).push(r); + } + Ok(FileLines::from_ranges(m)) + } +} + +// For JSON decoding. +#[derive(Clone, Debug, Deserialize)] +struct JsonSpan { + #[serde(deserialize_with = "deserialize_filename")] + file: FileName, + range: (usize, usize), +} + +fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { + let s = String::deserialize(d)?; + if s == "stdin" { + Ok(FileName::Custom(s)) + } else { + Ok(FileName::Real(s.into())) + } +} + +impl JsonSpan { + fn into_tuple(self) -> Result<(FileName, Range), String> { + let (lo, hi) = self.range; + let canonical = canonicalize_path_string(&self.file) + .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; + Ok((canonical, Range::new(lo, hi))) + } +} + +// This impl is needed for inclusion in the `Config` struct. We don't have a toml representation +// for `FileLines`, so it will just panic instead. +impl<'de> ::serde::de::Deserialize<'de> for FileLines { + fn deserialize(_: D) -> Result + where + D: ::serde::de::Deserializer<'de>, + { + panic!( + "FileLines cannot be deserialized from a project rustfmt.toml file: please \ + specify it via the `--file-lines` option instead" + ); + } +} + +// We also want to avoid attempting to serialize a FileLines to toml. The +// `Config` struct should ensure this impl is never reached. +impl ::serde::ser::Serialize for FileLines { + fn serialize(&self, _: S) -> Result + where + S: ::serde::ser::Serializer, + { + unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); + } +} + +#[cfg(test)] +mod test { + use super::Range; + + #[test] + fn test_range_intersects() { + assert!(Range::new(1, 2).intersects(Range::new(1, 1))); + assert!(Range::new(1, 2).intersects(Range::new(2, 2))); + assert!(!Range::new(1, 2).intersects(Range::new(0, 0))); + assert!(!Range::new(1, 2).intersects(Range::new(3, 10))); + assert!(!Range::new(1, 3).intersects(Range::new(5, 5))); + } + + #[test] + fn test_range_adjacent_to() { + assert!(!Range::new(1, 2).adjacent_to(Range::new(1, 1))); + assert!(!Range::new(1, 2).adjacent_to(Range::new(2, 2))); + assert!(Range::new(1, 2).adjacent_to(Range::new(0, 0))); + assert!(Range::new(1, 2).adjacent_to(Range::new(3, 10))); + assert!(!Range::new(1, 3).adjacent_to(Range::new(5, 5))); + } + + #[test] + fn test_range_contains() { + assert!(Range::new(1, 2).contains(Range::new(1, 1))); + assert!(Range::new(1, 2).contains(Range::new(2, 2))); + assert!(!Range::new(1, 2).contains(Range::new(0, 0))); + assert!(!Range::new(1, 2).contains(Range::new(3, 10))); + } + + #[test] + fn test_range_merge() { + assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); + assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(4, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(5, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(6, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 7).merge(Range::new(4, 5)) + ); + } +} diff --git a/rustfmt-config/src/lib.rs b/rustfmt-config/src/lib.rs new file mode 100644 index 00000000000..cbfd236dc37 --- /dev/null +++ b/rustfmt-config/src/lib.rs @@ -0,0 +1,252 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; +extern crate syntax; +extern crate toml; + +use std::{env, fs}; +use std::cell::Cell; +use std::default::Default; +use std::fs::File; +use std::io::{Error, ErrorKind, Read}; +use std::path::{Path, PathBuf}; + +#[macro_use] +mod config_type; +#[macro_use] +mod options; + +pub mod file_lines; +pub mod lists; +pub mod summary; + +use config_type::ConfigType; +use file_lines::FileLines; +pub use lists::*; +pub use options::*; +use summary::Summary; + +/// This macro defines configuration options used in rustfmt. Each option +/// is defined as follows: +/// +/// `name: value type, default value, is stable, description;` +create_config! { + // Fundamental stuff + max_width: usize, 100, true, "Maximum width of each line"; + hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; + tab_spaces: usize, 4, true, "Number of spaces per tab"; + newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; + use_small_heuristics: bool, true, false, "Whether to use different formatting for items and\ + expressions if they satisfy a heuristic notion of 'small'."; + + // strings and comments + format_strings: bool, false, false, "Format string literals where necessary"; + wrap_comments: bool, false, true, "Break comments to fit on the line"; + comment_width: usize, 80, false, + "Maximum length of comments. No effect unless wrap_comments = true"; + normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; + + // Single line expressions and items. + empty_item_single_line: bool, true, false, + "Put empty-body functions and impls on a single line"; + struct_lit_single_line: bool, true, false, + "Put small struct literals on a single line"; + fn_single_line: bool, false, false, "Put single-expression functions on a single line"; + where_single_line: bool, false, false, "To force single line where layout"; + + // Imports + imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; + imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; + + // Ordering + reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; + reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; + reorder_imports: bool, false, false, "Reorder import statements alphabetically"; + reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; + reorder_imported_names: bool, true, false, + "Reorder lists of names in import statements alphabetically"; + reorder_modules: bool, false, false, "Reorder module statemtents alphabetically in group"; + + // Spaces around punctuation + binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + "Where to put a binary operator when a binary expression goes multiline."; + type_punctuation_density: TypeDensity, TypeDensity::Wide, false, + "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; + space_before_colon: bool, false, false, "Leave a space before the colon"; + space_after_colon: bool, true, false, "Leave a space after the colon"; + spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; + spaces_within_parens_and_brackets: bool, false, false, + "Put spaces within non-empty parentheses or brackets"; + + // Misc. + combine_control_expr: bool, true, false, "Combine control expressions with function calls."; + struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ + threshold."; + remove_blank_lines_at_start_or_end_of_block: bool, true, false, + "Remove blank lines at start or end of a block"; + match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ + the same line with the pattern of arms"; + force_multiline_blocks: bool, false, false, + "Force multiline closure bodies and match arms to be wrapped in a block"; + fn_args_density: Density, Density::Tall, false, "Argument density in functions"; + brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, + "Brace style for control flow constructs"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, + "How to handle trailing commas for lists"; + trailing_semicolon: bool, true, false, + "Add trailing semicolon after break, continue and return"; + match_block_trailing_comma: bool, false, false, + "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + blank_lines_upper_bound: usize, 1, false, + "Maximum number of blank lines which can be put between items."; + blank_lines_lower_bound: usize, 0, false, + "Minimum number of blank lines which must be put between items."; + + // Options that can change the source code beyond whitespace/blocks (somewhat linty things) + merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; + use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; + condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ + in tuple patterns"; + force_explicit_abi: bool, true, true, "Always print the abi for extern items"; + use_field_init_shorthand: bool, false, false, "Use field initialization shorthand if possible"; + + // Control options (changes the operation of rustfmt, rather than the formatting) + write_mode: WriteMode, WriteMode::Overwrite, false, + "What Write Mode to use when none is supplied: \ + Replace, Overwrite, Display, Plain, Diff, Coverage"; + color: Color, Color::Auto, false, + "What Color option to use when none is supplied: Always, Never, Auto"; + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, + "Require a specific version of rustfmt."; + unstable_features: bool, false, true, + "Enables unstable features. Only available on nightly channel"; + disable_all_formatting: bool, false, false, "Don't reformat anything"; + skip_children: bool, false, false, "Don't reformat out of line modules"; + hide_parse_errors: bool, false, false, "Hide errors from the parser"; + error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; + error_on_unformatted: bool, false, false, + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces"; + report_todo: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of TODO in source file comments"; + report_fixme: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of FIXME in source file comments"; + + // Not user-facing. + verbose: bool, false, false, "Use verbose output"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + width_heuristics: WidthHeuristics, WidthHeuristics::default(), false, + "'small' heuristic values"; +} + +/// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +/// +/// Return the path if a config file exists, empty if no file exists, and Error for IO errors +pub fn get_toml_path(dir: &Path) -> Result, Error> { + const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + for config_file_name in &CONFIG_FILE_NAMES { + let config_file = dir.join(config_file_name); + match fs::metadata(&config_file) { + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't + // find the project file yet, and continue searching. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e); + } + } + _ => {} + } + } + Ok(None) +} + +#[cfg(test)] +mod test { + use super::Config; + + #[test] + fn test_config_set() { + let mut config = Config::default(); + config.set().verbose(false); + assert_eq!(config.verbose(), false); + config.set().verbose(true); + assert_eq!(config.verbose(), true); + } + + #[test] + fn test_config_used_to_toml() { + let config = Config::default(); + + let merge_derives = config.merge_derives(); + let skip_children = config.skip_children(); + + let used_options = config.used_options(); + let toml = used_options.to_toml().unwrap(); + assert_eq!( + toml, + format!( + "merge_derives = {}\nskip_children = {}\n", + merge_derives, skip_children, + ) + ); + } + + #[test] + fn test_was_set() { + let config = Config::from_toml("hard_tabs = true").unwrap(); + + assert_eq!(config.was_set().hard_tabs(), true); + assert_eq!(config.was_set().verbose(), false); + } + + // FIXME(#2183) these tests cannot be run in parallel because they use env vars + // #[test] + // fn test_as_not_nightly_channel() { + // let mut config = Config::default(); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // } + + // #[test] + // fn test_as_nightly_channel() { + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // let mut config = Config::default(); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } + + // #[test] + // fn test_unstable_from_toml() { + // let mut config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), false); + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } +} diff --git a/rustfmt-config/src/lists.rs b/rustfmt-config/src/lists.rs new file mode 100644 index 00000000000..2ddc2e59261 --- /dev/null +++ b/rustfmt-config/src/lists.rs @@ -0,0 +1,105 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Configuration options related to rewriting a list. + +use IndentStyle; +use config_type::ConfigType; + +/// The definitive formatting tactic for lists. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum DefinitiveListTactic { + Vertical, + Horizontal, + Mixed, + /// Special case tactic for `format!()`, `write!()` style macros. + SpecialMacro(usize), +} + +impl DefinitiveListTactic { + pub fn ends_with_newline(&self, indent_style: IndentStyle) -> bool { + match indent_style { + IndentStyle::Block => *self != DefinitiveListTactic::Horizontal, + IndentStyle::Visual => false, + } + } +} + +/// Formatting tactic for lists. This will be cast down to a +/// `DefinitiveListTactic` depending on the number and length of the items and +/// their comments. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum ListTactic { + // One item per row. + Vertical, + // All items on one row. + Horizontal, + // Try Horizontal layout, if that fails then vertical. + HorizontalVertical, + // HorizontalVertical with a soft limit of n characters. + LimitedHorizontalVertical(usize), + // Pack as many items as possible per row over (possibly) many rows. + Mixed, +} + +impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorTactic { + Always, + Never, + Vertical, +} + +impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); + +impl SeparatorTactic { + pub fn from_bool(b: bool) -> SeparatorTactic { + if b { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } +} + +/// Where to put separator. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorPlace { + Front, + Back, +} + +impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); + +impl SeparatorPlace { + pub fn is_front(&self) -> bool { + *self == SeparatorPlace::Front + } + + pub fn is_back(&self) -> bool { + *self == SeparatorPlace::Back + } + + pub fn from_tactic( + default: SeparatorPlace, + tactic: DefinitiveListTactic, + sep: &str, + ) -> SeparatorPlace { + match tactic { + DefinitiveListTactic::Vertical => default, + _ => if sep == "," { + SeparatorPlace::Back + } else { + default + }, + } + } +} diff --git a/rustfmt-config/src/macros.rs b/rustfmt-config/src/macros.rs new file mode 100644 index 00000000000..6391db85dc5 --- /dev/null +++ b/rustfmt-config/src/macros.rs @@ -0,0 +1,10 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + diff --git a/rustfmt-config/src/options.rs b/rustfmt-config/src/options.rs new file mode 100644 index 00000000000..bff6d2298d3 --- /dev/null +++ b/rustfmt-config/src/options.rs @@ -0,0 +1,244 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config_type::ConfigType; +use lists::*; + +/// Macro for deriving implementations of Serialize/Deserialize for enums +#[macro_export] +macro_rules! impl_enum_serialize_and_deserialize { + ( $e:ident, $( $x:ident ),* ) => { + impl ::serde::ser::Serialize for $e { + fn serialize(&self, serializer: S) -> Result + where S: ::serde::ser::Serializer + { + use serde::ser::Error; + + // We don't know whether the user of the macro has given us all options. + #[allow(unreachable_patterns)] + match *self { + $( + $e::$x => serializer.serialize_str(stringify!($x)), + )* + _ => { + Err(S::Error::custom(format!("Cannot serialize {:?}", self))) + } + } + } + } + + impl<'de> ::serde::de::Deserialize<'de> for $e { + fn deserialize(d: D) -> Result + where D: ::serde::Deserializer<'de> { + use serde::de::{Error, Visitor}; + use std::marker::PhantomData; + use std::fmt; + struct StringOnly(PhantomData); + impl<'de, T> Visitor<'de> for StringOnly + where T: ::serde::Deserializer<'de> { + type Value = String; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("string") + } + fn visit_str(self, value: &str) -> Result { + Ok(String::from(value)) + } + } + let s = d.deserialize_string(StringOnly::(PhantomData))?; + $( + if stringify!($x).eq_ignore_ascii_case(&s) { + return Ok($e::$x); + } + )* + static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; + Err(D::Error::unknown_variant(&s, ALLOWED)) + } + } + + impl ::std::str::FromStr for $e { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + $( + if stringify!($x).eq_ignore_ascii_case(s) { + return Ok($e::$x); + } + )* + Err("Bad variant") + } + } + + impl ConfigType for $e { + fn doc_hint() -> String { + let mut variants = Vec::new(); + $( + variants.push(stringify!($x)); + )* + format!("[{}]", variants.join("|")) + } + } + }; +} + +macro_rules! configuration_option_enum{ + ($e:ident: $( $x:ident ),+ $(,)*) => { + #[derive(Copy, Clone, Eq, PartialEq, Debug)] + pub enum $e { + $( $x ),+ + } + + impl_enum_serialize_and_deserialize!($e, $( $x ),+); + } +} + +configuration_option_enum! { NewlineStyle: + Windows, // \r\n + Unix, // \n + Native, // \r\n in Windows, \n on other platforms +} + +configuration_option_enum! { BraceStyle: + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +configuration_option_enum! { ControlBraceStyle: + // K&R style, Rust community default + AlwaysSameLine, + // Stroustrup style + ClosingNextLine, + // Allman style + AlwaysNextLine, +} + +configuration_option_enum! { IndentStyle: + // First line on the same line as the opening brace, all lines aligned with + // the first line. + Visual, + // First line is on a new line and all lines align with block indent. + Block, +} + +configuration_option_enum! { Density: + // Fit as much on one line as possible. + Compressed, + // Use more lines. + Tall, + // Place every item on a separate line. + Vertical, +} + +configuration_option_enum! { TypeDensity: + // No spaces around "=" and "+" + Compressed, + // Spaces around " = " and " + " + Wide, +} + +impl Density { + pub fn to_list_tactic(self) -> ListTactic { + match self { + Density::Compressed => ListTactic::Mixed, + Density::Tall => ListTactic::HorizontalVertical, + Density::Vertical => ListTactic::Vertical, + } + } +} + +configuration_option_enum! { ReportTactic: + Always, + Unnumbered, + Never, +} + +configuration_option_enum! { WriteMode: + // Backs the original file up and overwrites the original. + Replace, + // Overwrites original file without backup. + Overwrite, + // Writes the output to stdout. + Display, + // Writes the diff to stdout. + Diff, + // Displays how much of the input file was processed + Coverage, + // Unfancy stdout + Plain, + // Outputs a checkstyle XML file. + Checkstyle, +} + +configuration_option_enum! { Color: + // Always use color, whether it is a piped or terminal output + Always, + // Never use color + Never, + // Automatically use color, if supported by terminal + Auto, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct WidthHeuristics { + // Maximum width of the args of a function call before falling back + // to vertical formatting. + pub fn_call_width: usize, + // Maximum width in the body of a struct lit before falling back to + // vertical formatting. + pub struct_lit_width: usize, + // Maximum width in the body of a struct variant before falling back + // to vertical formatting. + pub struct_variant_width: usize, + // Maximum width of an array literal before falling back to vertical + // formatting. + pub array_width: usize, + // Maximum length of a chain to fit on a single line. + pub chain_width: usize, + // Maximum line length for single line if-else expressions. A value + // of zero means always break if-else expressions. + pub single_line_if_else_max_width: usize, +} + +impl WidthHeuristics { + // Using this WidthHeuristics means we ignore heuristics. + pub fn null() -> WidthHeuristics { + WidthHeuristics { + fn_call_width: usize::max_value(), + struct_lit_width: 0, + struct_variant_width: 0, + array_width: usize::max_value(), + chain_width: usize::max_value(), + single_line_if_else_max_width: 0, + } + } +} + +impl Default for WidthHeuristics { + fn default() -> WidthHeuristics { + WidthHeuristics { + fn_call_width: 60, + struct_lit_width: 18, + struct_variant_width: 35, + array_width: 60, + chain_width: 60, + single_line_if_else_max_width: 50, + } + } +} + +impl ::std::str::FromStr for WidthHeuristics { + type Err = &'static str; + + fn from_str(_: &str) -> Result { + Err("WidthHeuristics is not parsable") + } +} diff --git a/rustfmt-config/src/summary.rs b/rustfmt-config/src/summary.rs new file mode 100644 index 00000000000..b0be5678a0b --- /dev/null +++ b/rustfmt-config/src/summary.rs @@ -0,0 +1,144 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::time::{Duration, Instant}; +use std::default::Default; + +#[must_use] +#[derive(Debug, Default, Clone, Copy)] +pub struct Summary { + // Encountered e.g. an IO error. + has_operational_errors: bool, + + // Failed to reformat code because of parsing errors. + has_parsing_errors: bool, + + // Code is valid, but it is impossible to format it properly. + has_formatting_errors: bool, + + // Formatted code differs from existing code (write-mode diff only). + pub has_diff: bool, + + // Keeps track of time spent in parsing and formatting steps. + timer: Timer, +} + +impl Summary { + pub fn mark_parse_time(&mut self) { + self.timer = self.timer.done_parsing(); + } + + pub fn mark_format_time(&mut self) { + self.timer = self.timer.done_formatting(); + } + + /// Returns the time it took to parse the source files in nanoseconds. + pub fn get_parse_time(&self) -> Option { + match self.timer { + Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { + // This should never underflow since `Instant::now()` guarantees monotonicity. + Some(parse_time.duration_since(init)) + } + Timer::Initialized(..) => None, + } + } + + /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is + /// not included. + pub fn get_format_time(&self) -> Option { + match self.timer { + Timer::DoneFormatting(_init, parse_time, format_time) => { + Some(format_time.duration_since(parse_time)) + } + Timer::DoneParsing(..) | Timer::Initialized(..) => None, + } + } + + pub fn has_operational_errors(&self) -> bool { + self.has_operational_errors + } + + pub fn has_parsing_errors(&self) -> bool { + self.has_parsing_errors + } + + pub fn has_formatting_errors(&self) -> bool { + self.has_formatting_errors + } + + pub fn add_operational_error(&mut self) { + self.has_operational_errors = true; + } + + pub fn add_parsing_error(&mut self) { + self.has_parsing_errors = true; + } + + pub fn add_formatting_error(&mut self) { + self.has_formatting_errors = true; + } + + pub fn add_diff(&mut self) { + self.has_diff = true; + } + + pub fn has_no_errors(&self) -> bool { + !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors + || self.has_diff) + } + + pub fn add(&mut self, other: Summary) { + self.has_operational_errors |= other.has_operational_errors; + self.has_formatting_errors |= other.has_formatting_errors; + self.has_parsing_errors |= other.has_parsing_errors; + self.has_diff |= other.has_diff; + } + + pub fn print_exit_codes() { + let exit_codes = r#"Exit Codes: + 0 = No errors + 1 = Encountered operational errors e.g. an IO error + 2 = Failed to reformat code because of parsing errors + 3 = Code is valid, but it is impossible to format it properly + 4 = Formatted code differs from existing code (write-mode diff only)"#; + println!("{}", exit_codes); + } +} + +#[derive(Clone, Copy, Debug)] +enum Timer { + Initialized(Instant), + DoneParsing(Instant, Instant), + DoneFormatting(Instant, Instant, Instant), +} + +impl Default for Timer { + fn default() -> Self { + Timer::Initialized(Instant::now()) + } +} + +impl Timer { + fn done_parsing(self) -> Self { + match self { + Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), + _ => panic!("Timer can only transition to DoneParsing from Initialized state"), + } + } + + fn done_formatting(self) -> Self { + match self { + Timer::DoneParsing(init_time, parse_time) => { + Timer::DoneFormatting(init_time, parse_time, Instant::now()) + } + _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), + } + } +} diff --git a/src/config.rs b/src/config.rs deleted file mode 100644 index cca1779a4a8..00000000000 --- a/src/config.rs +++ /dev/null @@ -1,781 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate toml; - -use std::{env, fs}; -use std::cell::Cell; -use std::default::Default; -use std::fs::File; -use std::io::{Error, ErrorKind, Read}; -use std::path::{Path, PathBuf}; - -use Summary; -use file_lines::FileLines; -use lists::{ListTactic, SeparatorPlace, SeparatorTactic}; - -/// Check if we're in a nightly build. -/// -/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap -/// to "stable", "beta", or "nightly" depending on what toolchain is being built. -/// If we are being built as part of the stable or beta toolchains, we want -/// to disable unstable configuration options. -/// -/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), -/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the -/// nightly compiler when installed from crates.io, default to nightly mode. -macro_rules! is_nightly_channel { - () => { - option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(true) - }; -} - -macro_rules! configuration_option_enum{ - ($e:ident: $( $x:ident ),+ $(,)*) => { - #[derive(Copy, Clone, Eq, PartialEq, Debug)] - pub enum $e { - $( $x ),+ - } - - impl_enum_serialize_and_deserialize!($e, $( $x ),+); - } -} - -configuration_option_enum! { NewlineStyle: - Windows, // \r\n - Unix, // \n - Native, // \r\n in Windows, \n on other platforms -} - -configuration_option_enum! { BraceStyle: - AlwaysNextLine, - PreferSameLine, - // Prefer same line except where there is a where clause, in which case force - // the brace to the next line. - SameLineWhere, -} - -configuration_option_enum! { ControlBraceStyle: - // K&R style, Rust community default - AlwaysSameLine, - // Stroustrup style - ClosingNextLine, - // Allman style - AlwaysNextLine, -} - -configuration_option_enum! { IndentStyle: - // First line on the same line as the opening brace, all lines aligned with - // the first line. - Visual, - // First line is on a new line and all lines align with block indent. - Block, -} - -configuration_option_enum! { Density: - // Fit as much on one line as possible. - Compressed, - // Use more lines. - Tall, - // Place every item on a separate line. - Vertical, -} - -configuration_option_enum! { TypeDensity: - // No spaces around "=" and "+" - Compressed, - // Spaces around " = " and " + " - Wide, -} - -impl Density { - pub fn to_list_tactic(self) -> ListTactic { - match self { - Density::Compressed => ListTactic::Mixed, - Density::Tall => ListTactic::HorizontalVertical, - Density::Vertical => ListTactic::Vertical, - } - } -} - -configuration_option_enum! { ReportTactic: - Always, - Unnumbered, - Never, -} - -configuration_option_enum! { WriteMode: - // Backs the original file up and overwrites the original. - Replace, - // Overwrites original file without backup. - Overwrite, - // Writes the output to stdout. - Display, - // Writes the diff to stdout. - Diff, - // Displays how much of the input file was processed - Coverage, - // Unfancy stdout - Plain, - // Outputs a checkstyle XML file. - Checkstyle, -} - -configuration_option_enum! { Color: - // Always use color, whether it is a piped or terminal output - Always, - // Never use color - Never, - // Automatically use color, if supported by terminal - Auto, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct WidthHeuristics { - // Maximum width of the args of a function call before falling back - // to vertical formatting. - pub fn_call_width: usize, - // Maximum width in the body of a struct lit before falling back to - // vertical formatting. - pub struct_lit_width: usize, - // Maximum width in the body of a struct variant before falling back - // to vertical formatting. - pub struct_variant_width: usize, - // Maximum width of an array literal before falling back to vertical - // formatting. - pub array_width: usize, - // Maximum length of a chain to fit on a single line. - pub chain_width: usize, - // Maximum line length for single line if-else expressions. A value - // of zero means always break if-else expressions. - pub single_line_if_else_max_width: usize, -} - -impl WidthHeuristics { - // Using this WidthHeuristics means we ignore heuristics. - fn null() -> WidthHeuristics { - WidthHeuristics { - fn_call_width: usize::max_value(), - struct_lit_width: 0, - struct_variant_width: 0, - array_width: usize::max_value(), - chain_width: usize::max_value(), - single_line_if_else_max_width: 0, - } - } -} - -impl Default for WidthHeuristics { - fn default() -> WidthHeuristics { - WidthHeuristics { - fn_call_width: 60, - struct_lit_width: 18, - struct_variant_width: 35, - array_width: 60, - chain_width: 60, - single_line_if_else_max_width: 50, - } - } -} - -impl ::std::str::FromStr for WidthHeuristics { - type Err = &'static str; - - fn from_str(_: &str) -> Result { - Err("WidthHeuristics is not parsable") - } -} - -impl ::config::ConfigType for WidthHeuristics { - fn doc_hint() -> String { - String::new() - } -} - -/// Trait for types that can be used in `Config`. -pub trait ConfigType: Sized { - /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a - /// pipe-separated list of variants; for other types it returns "". - fn doc_hint() -> String; -} - -impl ConfigType for bool { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for usize { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for isize { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for String { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for FileLines { - fn doc_hint() -> String { - String::from("") - } -} - -pub struct ConfigHelpItem { - option_name: &'static str, - doc_string: &'static str, - variant_names: String, - default: &'static str, -} - -impl ConfigHelpItem { - pub fn option_name(&self) -> &'static str { - self.option_name - } - - pub fn doc_string(&self) -> &'static str { - self.doc_string - } - - pub fn variant_names(&self) -> &String { - &self.variant_names - } - - pub fn default(&self) -> &'static str { - self.default - } -} - -macro_rules! create_config { - ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( - #[derive(Clone)] - pub struct Config { - // For each config item, we store a bool indicating whether it has - // been accessed and the value, and a bool whether the option was - // manually initialised, or taken from the default, - $($i: (Cell, bool, $ty, bool)),+ - } - - // Just like the Config struct but with each property wrapped - // as Option. This is used to parse a rustfmt.toml that doesn't - // specify all properties of `Config`. - // We first parse into `PartialConfig`, then create a default `Config` - // and overwrite the properties with corresponding values from `PartialConfig`. - #[derive(Deserialize, Serialize, Clone)] - pub struct PartialConfig { - $(pub $i: Option<$ty>),+ - } - - impl PartialConfig { - pub fn to_toml(&self) -> Result { - // Non-user-facing options can't be specified in TOML - let mut cloned = self.clone(); - cloned.file_lines = None; - cloned.verbose = None; - cloned.width_heuristics = None; - - toml::to_string(&cloned) - .map_err(|e| format!("Could not output config: {}", e.to_string())) - } - } - - // Macro hygiene won't allow us to make `set_$i()` methods on Config - // for each item, so this struct is used to give the API to set values: - // `config.get().option(false)`. It's pretty ugly. Consider replacing - // with `config.set_option(false)` if we ever get a stable/usable - // `concat_idents!()`. - pub struct ConfigSetter<'a>(&'a mut Config); - - impl<'a> ConfigSetter<'a> { - $( - pub fn $i(&mut self, value: $ty) { - (self.0).$i.2 = value; - if stringify!($i) == "use_small_heuristics" { - self.0.set_heuristics(); - } - } - )+ - } - - // Query each option, returns true if the user set the option, false if - // a default was used. - pub struct ConfigWasSet<'a>(&'a Config); - - impl<'a> ConfigWasSet<'a> { - $( - pub fn $i(&self) -> bool { - (self.0).$i.1 - } - )+ - } - - impl Config { - pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool { - if self.was_set().required_version() { - let version = env!("CARGO_PKG_VERSION"); - let required_version = self.required_version(); - if version != required_version { - println!( - "Error: rustfmt version ({}) doesn't match the required version ({})", - version, - required_version, - ); - error_summary.add_formatting_error(); - return false; - } - } - - true - } - - $( - pub fn $i(&self) -> $ty { - self.$i.0.set(true); - self.$i.2.clone() - } - )+ - - pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { - ConfigSetter(self) - } - - pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { - ConfigWasSet(self) - } - - fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { - $( - if let Some(val) = parsed.$i { - if self.$i.3 { - self.$i.1 = true; - self.$i.2 = val; - } else { - if is_nightly_channel!() { - self.$i.1 = true; - self.$i.2 = val; - } else { - eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ - available in nightly channel.", stringify!($i), val); - } - } - } - )+ - self.set_heuristics(); - self - } - - pub fn from_toml(toml: &str) -> Result { - let parsed: toml::Value = - toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; - let mut err: String = String::new(); - { - let table = parsed - .as_table() - .ok_or(String::from("Parsed config was not table"))?; - for key in table.keys() { - match &**key { - $( - stringify!($i) => (), - )+ - _ => { - let msg = - &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) - } - } - } - } - match parsed.try_into() { - Ok(parsed_config) => { - if !err.is_empty() { - eprint!("{}", err); - } - Ok(Config::default().fill_from_parsed_config(parsed_config)) - } - Err(e) => { - err.push_str("Error: Decoding config file failed:\n"); - err.push_str(format!("{}\n", e).as_str()); - err.push_str("Please check your config file."); - Err(err) - } - } - } - - pub fn used_options(&self) -> PartialConfig { - PartialConfig { - $( - $i: if self.$i.0.get() { - Some(self.$i.2.clone()) - } else { - None - }, - )+ - } - } - - pub fn all_options(&self) -> PartialConfig { - PartialConfig { - $( - $i: Some(self.$i.2.clone()), - )+ - } - } - - pub fn override_value(&mut self, key: &str, val: &str) - { - match key { - $( - stringify!($i) => { - self.$i.2 = val.parse::<$ty>() - .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", - stringify!($i), - val, - stringify!($ty))); - } - )+ - _ => panic!("Unknown config key in override: {}", key) - } - - if key == "use_small_heuristics" { - self.set_heuristics(); - } - } - - /// Construct a `Config` from the toml file specified at `file_path`. - /// - /// This method only looks at the provided path, for a method that - /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. - /// - /// Return a `Config` if the config could be read and parsed from - /// the file, Error otherwise. - pub fn from_toml_path(file_path: &Path) -> Result { - let mut file = File::open(&file_path)?; - let mut toml = String::new(); - file.read_to_string(&mut toml)?; - Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) - } - - /// Resolve the config for input in `dir`. - /// - /// Searches for `rustfmt.toml` beginning with `dir`, and - /// recursively checking parents of `dir` if no config file is found. - /// If no config file exists in `dir` or in any parent, a - /// default `Config` will be returned (and the returned path will be empty). - /// - /// Returns the `Config` to use, and the path of the project file if there was - /// one. - pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { - - /// Try to find a project file in the given directory and its parents. - /// Returns the path of a the nearest project file if one exists, - /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { - let mut current = if dir.is_relative() { - env::current_dir()?.join(dir) - } else { - dir.to_path_buf() - }; - - current = fs::canonicalize(current)?; - - loop { - match get_toml_path(¤t) { - Ok(Some(path)) => return Ok(Some(path)), - Err(e) => return Err(e), - _ => () - } - - // If the current directory has no parent, we're done searching. - if !current.pop() { - return Ok(None); - } - } - } - - match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), - } - } - - - pub fn print_docs() { - use std::cmp; - const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"]; - let max = 0; - $( let max = cmp::max(max, stringify!($i).len()+1); )+ - let mut space_str = String::with_capacity(max); - for _ in 0..max { - space_str.push(' '); - } - println!("Configuration Options:"); - $( - let name_raw = stringify!($i); - - if !HIDE_OPTIONS.contains(&name_raw) { - let mut name_out = String::with_capacity(max); - for _ in name_raw.len()..max-1 { - name_out.push(' ') - } - name_out.push_str(name_raw); - name_out.push(' '); - println!("{}{} Default: {:?}", - name_out, - <$ty>::doc_hint(), - $def); - $( - println!("{}{}", space_str, $dstring); - )+ - println!(); - } - )+ - } - - fn set_heuristics(&mut self) { - if self.use_small_heuristics.2 { - self.set().width_heuristics(WidthHeuristics::default()); - } else { - self.set().width_heuristics(WidthHeuristics::null()); - } - } - } - - // Template for the default configuration - impl Default for Config { - fn default() -> Config { - Config { - $( - $i: (Cell::new(false), false, $def, $stb), - )+ - } - } - } - ) -} - -/// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` -/// -/// Return the path if a config file exists, empty if no file exists, and Error for IO errors -pub fn get_toml_path(dir: &Path) -> Result, Error> { - const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; - for config_file_name in &CONFIG_FILE_NAMES { - let config_file = dir.join(config_file_name); - match fs::metadata(&config_file) { - // Only return if it's a file to handle the unlikely situation of a directory named - // `rustfmt.toml`. - Ok(ref md) if md.is_file() => return Ok(Some(config_file)), - // Return the error if it's something other than `NotFound`; otherwise we didn't - // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != ErrorKind::NotFound { - return Err(e); - } - } - _ => {} - } - } - Ok(None) -} - -create_config! { - // Fundamental stuff - max_width: usize, 100, true, "Maximum width of each line"; - hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; - tab_spaces: usize, 4, true, "Number of spaces per tab"; - newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; - use_small_heuristics: bool, true, false, "Whether to use different formatting for items and\ - expressions if they satisfy a heuristic notion of 'small'."; - - // strings and comments - format_strings: bool, false, false, "Format string literals where necessary"; - wrap_comments: bool, false, true, "Break comments to fit on the line"; - comment_width: usize, 80, false, - "Maximum length of comments. No effect unless wrap_comments = true"; - normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; - - // Single line expressions and items. - empty_item_single_line: bool, true, false, - "Put empty-body functions and impls on a single line"; - struct_lit_single_line: bool, true, false, - "Put small struct literals on a single line"; - fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - where_single_line: bool, false, false, "To force single line where layout"; - - // Imports - imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; - imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; - - // Ordering - reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; - reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; - reorder_imports: bool, false, false, "Reorder import statements alphabetically"; - reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; - reorder_imported_names: bool, true, false, - "Reorder lists of names in import statements alphabetically"; - reorder_modules: bool, false, false, "Reorder module statemtents alphabetically in group"; - - // Spaces around punctuation - binop_separator: SeparatorPlace, SeparatorPlace::Front, false, - "Where to put a binary operator when a binary expression goes multiline."; - type_punctuation_density: TypeDensity, TypeDensity::Wide, false, - "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - space_before_colon: bool, false, false, "Leave a space before the colon"; - space_after_colon: bool, true, false, "Leave a space after the colon"; - spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; - spaces_within_parens_and_brackets: bool, false, false, - "Put spaces within non-empty parentheses or brackets"; - - // Misc. - combine_control_expr: bool, true, false, "Combine control expressions with function calls."; - struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ - threshold."; - remove_blank_lines_at_start_or_end_of_block: bool, true, false, - "Remove blank lines at start or end of a block"; - match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ - the same line with the pattern of arms"; - force_multiline_blocks: bool, false, false, - "Force multiline closure bodies and match arms to be wrapped in a block"; - fn_args_density: Density, Density::Tall, false, "Argument density in functions"; - brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; - control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, - "Brace style for control flow constructs"; - trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, - "How to handle trailing commas for lists"; - trailing_semicolon: bool, true, false, - "Add trailing semicolon after break, continue and return"; - match_block_trailing_comma: bool, false, false, - "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - blank_lines_upper_bound: usize, 1, false, - "Maximum number of blank lines which can be put between items."; - blank_lines_lower_bound: usize, 0, false, - "Minimum number of blank lines which must be put between items."; - - // Options that can change the source code beyond whitespace/blocks (somewhat linty things) - merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; - use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; - condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ - in tuple patterns"; - force_explicit_abi: bool, true, true, "Always print the abi for extern items"; - use_field_init_shorthand: bool, false, false, "Use field initialization shorthand if possible"; - - // Control options (changes the operation of rustfmt, rather than the formatting) - write_mode: WriteMode, WriteMode::Overwrite, false, - "What Write Mode to use when none is supplied: \ - Replace, Overwrite, Display, Plain, Diff, Coverage"; - color: Color, Color::Auto, false, - "What Color option to use when none is supplied: Always, Never, Auto"; - required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, - "Require a specific version of rustfmt."; - unstable_features: bool, false, true, - "Enables unstable features. Only available on nightly channel"; - disable_all_formatting: bool, false, false, "Don't reformat anything"; - skip_children: bool, false, false, "Don't reformat out of line modules"; - hide_parse_errors: bool, false, false, "Hide errors from the parser"; - error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; - error_on_unformatted: bool, false, false, - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces"; - report_todo: ReportTactic, ReportTactic::Never, false, - "Report all, none or unnumbered occurrences of TODO in source file comments"; - report_fixme: ReportTactic, ReportTactic::Never, false, - "Report all, none or unnumbered occurrences of FIXME in source file comments"; - - // Not user-facing. - verbose: bool, false, false, "Use verbose output"; - file_lines: FileLines, FileLines::all(), false, - "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ - via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::default(), false, - "'small' heuristic values"; -} - -#[cfg(test)] -mod test { - use super::Config; - - #[test] - fn test_config_set() { - let mut config = Config::default(); - config.set().verbose(false); - assert_eq!(config.verbose(), false); - config.set().verbose(true); - assert_eq!(config.verbose(), true); - } - - #[test] - fn test_config_used_to_toml() { - let config = Config::default(); - - let merge_derives = config.merge_derives(); - let skip_children = config.skip_children(); - - let used_options = config.used_options(); - let toml = used_options.to_toml().unwrap(); - assert_eq!( - toml, - format!( - "merge_derives = {}\nskip_children = {}\n", - merge_derives, skip_children, - ) - ); - } - - #[test] - fn test_was_set() { - let config = Config::from_toml("hard_tabs = true").unwrap(); - - assert_eq!(config.was_set().hard_tabs(), true); - assert_eq!(config.was_set().verbose(), false); - } - - // FIXME(#2183) these tests cannot be run in parallel because they use env vars - // #[test] - // fn test_as_not_nightly_channel() { - // let mut config = Config::default(); - // assert_eq!(config.was_set().unstable_features(), false); - // config.set().unstable_features(true); - // assert_eq!(config.was_set().unstable_features(), false); - // } - - // #[test] - // fn test_as_nightly_channel() { - // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - // let mut config = Config::default(); - // config.set().unstable_features(true); - // assert_eq!(config.was_set().unstable_features(), false); - // config.set().unstable_features(true); - // assert_eq!(config.unstable_features(), true); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - // } - - // #[test] - // fn test_unstable_from_toml() { - // let mut config = Config::from_toml("unstable_features = true").unwrap(); - // assert_eq!(config.was_set().unstable_features(), false); - // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - // config = Config::from_toml("unstable_features = true").unwrap(); - // assert_eq!(config.was_set().unstable_features(), true); - // assert_eq!(config.unstable_features(), true); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - // } -} diff --git a/src/file_lines.rs b/src/file_lines.rs deleted file mode 100644 index 028c631b1b9..00000000000 --- a/src/file_lines.rs +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This module contains types and functions to support formatting specific line ranges. - -use std::{cmp, iter, str}; -use std::collections::HashMap; - -use serde::de::{Deserialize, Deserializer}; -use serde_json as json; - -use codemap::LineRange; -use syntax::codemap::FileName; - -/// A range that is inclusive of both ends. -#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] -pub struct Range { - lo: usize, - hi: usize, -} - -impl<'a> From<&'a LineRange> for Range { - fn from(range: &'a LineRange) -> Range { - Range::new(range.lo, range.hi) - } -} - -impl Range { - pub fn new(lo: usize, hi: usize) -> Range { - Range { lo, hi } - } - - fn is_empty(self) -> bool { - self.lo > self.hi - } - - fn contains(self, other: Range) -> bool { - if other.is_empty() { - true - } else { - !self.is_empty() && self.lo <= other.lo && self.hi >= other.hi - } - } - - fn intersects(self, other: Range) -> bool { - if self.is_empty() || other.is_empty() { - false - } else { - (self.lo <= other.hi && other.hi <= self.hi) - || (other.lo <= self.hi && self.hi <= other.hi) - } - } - - fn adjacent_to(self, other: Range) -> bool { - if self.is_empty() || other.is_empty() { - false - } else { - self.hi + 1 == other.lo || other.hi + 1 == self.lo - } - } - - /// Returns a new `Range` with lines from `self` and `other` if they were adjacent or - /// intersect; returns `None` otherwise. - fn merge(self, other: Range) -> Option { - if self.adjacent_to(other) || self.intersects(other) { - Some(Range::new( - cmp::min(self.lo, other.lo), - cmp::max(self.hi, other.hi), - )) - } else { - None - } - } -} - -/// A set of lines in files. -/// -/// It is represented as a multimap keyed on file names, with values a collection of -/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all -/// lines in all files. -#[derive(Clone, Debug, Default)] -pub struct FileLines(Option>>); - -/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, -/// and ordered by their start point. -fn normalize_ranges(ranges: &mut HashMap>) { - for ranges in ranges.values_mut() { - ranges.sort(); - let mut result = vec![]; - { - let mut iter = ranges.into_iter().peekable(); - while let Some(next) = iter.next() { - let mut next = *next; - while let Some(&&mut peek) = iter.peek() { - if let Some(merged) = next.merge(peek) { - iter.next().unwrap(); - next = merged; - } else { - break; - } - } - result.push(next) - } - } - *ranges = result; - } -} - -impl FileLines { - /// Creates a `FileLines` that contains all lines in all files. - pub fn all() -> FileLines { - FileLines(None) - } - - pub fn from_ranges(mut ranges: HashMap>) -> FileLines { - normalize_ranges(&mut ranges); - FileLines(Some(ranges)) - } - - /// Returns an iterator over the files contained in `self`. - pub fn files(&self) -> Files { - Files(self.0.as_ref().map(|m| m.keys())) - } - - /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in - /// the designated file (if any) and returns true if `f` ever does. - fn file_range_matches(&self, file_name: &FileName, f: F) -> bool - where - F: FnMut(&Range) -> bool, - { - let map = match self.0 { - // `None` means "all lines in all files". - None => return true, - Some(ref map) => map, - }; - - match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) { - Some(ranges) => ranges.iter().any(f), - None => false, - } - } - - /// Returns true if `range` is fully contained in `self`. - pub fn contains(&self, range: &LineRange) -> bool { - self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) - } - - /// Returns true if any lines in `range` are in `self`. - pub fn intersects(&self, range: &LineRange) -> bool { - self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) - } - - /// Returns true if `line` from `file_name` is in `self`. - pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool { - self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) - } - - /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. - pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { - self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) - } -} - -/// `FileLines` files iterator. -pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec>>); - -impl<'a> iter::Iterator for Files<'a> { - type Item = &'a FileName; - - fn next(&mut self) -> Option<&'a FileName> { - self.0.as_mut().and_then(Iterator::next) - } -} - -fn canonicalize_path_string(file: &FileName) -> Option { - match *file { - FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real), - _ => Some(file.clone()), - } -} - -// This impl is needed for `Config::override_value` to work for use in tests. -impl str::FromStr for FileLines { - type Err = String; - - fn from_str(s: &str) -> Result { - let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; - let mut m = HashMap::new(); - for js in v { - let (s, r) = JsonSpan::into_tuple(js)?; - m.entry(s).or_insert_with(|| vec![]).push(r); - } - Ok(FileLines::from_ranges(m)) - } -} - -// For JSON decoding. -#[derive(Clone, Debug, Deserialize)] -struct JsonSpan { - #[serde(deserialize_with = "deserialize_filename")] - file: FileName, - range: (usize, usize), -} - -fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { - let s = String::deserialize(d)?; - if s == "stdin" { - Ok(FileName::Custom(s)) - } else { - Ok(FileName::Real(s.into())) - } -} - -impl JsonSpan { - fn into_tuple(self) -> Result<(FileName, Range), String> { - let (lo, hi) = self.range; - let canonical = canonicalize_path_string(&self.file) - .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; - Ok((canonical, Range::new(lo, hi))) - } -} - -// This impl is needed for inclusion in the `Config` struct. We don't have a toml representation -// for `FileLines`, so it will just panic instead. -impl<'de> ::serde::de::Deserialize<'de> for FileLines { - fn deserialize(_: D) -> Result - where - D: ::serde::de::Deserializer<'de>, - { - panic!( - "FileLines cannot be deserialized from a project rustfmt.toml file: please \ - specify it via the `--file-lines` option instead" - ); - } -} - -// We also want to avoid attempting to serialize a FileLines to toml. The -// `Config` struct should ensure this impl is never reached. -impl ::serde::ser::Serialize for FileLines { - fn serialize(&self, _: S) -> Result - where - S: ::serde::ser::Serializer, - { - unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); - } -} - -#[cfg(test)] -mod test { - use super::Range; - - #[test] - fn test_range_intersects() { - assert!(Range::new(1, 2).intersects(Range::new(1, 1))); - assert!(Range::new(1, 2).intersects(Range::new(2, 2))); - assert!(!Range::new(1, 2).intersects(Range::new(0, 0))); - assert!(!Range::new(1, 2).intersects(Range::new(3, 10))); - assert!(!Range::new(1, 3).intersects(Range::new(5, 5))); - } - - #[test] - fn test_range_adjacent_to() { - assert!(!Range::new(1, 2).adjacent_to(Range::new(1, 1))); - assert!(!Range::new(1, 2).adjacent_to(Range::new(2, 2))); - assert!(Range::new(1, 2).adjacent_to(Range::new(0, 0))); - assert!(Range::new(1, 2).adjacent_to(Range::new(3, 10))); - assert!(!Range::new(1, 3).adjacent_to(Range::new(5, 5))); - } - - #[test] - fn test_range_contains() { - assert!(Range::new(1, 2).contains(Range::new(1, 1))); - assert!(Range::new(1, 2).contains(Range::new(2, 2))); - assert!(!Range::new(1, 2).contains(Range::new(0, 0))); - assert!(!Range::new(1, 2).contains(Range::new(3, 10))); - } - - #[test] - fn test_range_merge() { - assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); - assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(4, 7)) - ); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(5, 7)) - ); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(6, 7)) - ); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 7).merge(Range::new(4, 5)) - ); - } -} diff --git a/src/summary.rs b/src/summary.rs deleted file mode 100644 index 3e339fa4469..00000000000 --- a/src/summary.rs +++ /dev/null @@ -1,134 +0,0 @@ -use std::time::{Duration, Instant}; -use std::default::Default; - -#[must_use] -#[derive(Debug, Default, Clone, Copy)] -pub struct Summary { - // Encountered e.g. an IO error. - has_operational_errors: bool, - - // Failed to reformat code because of parsing errors. - has_parsing_errors: bool, - - // Code is valid, but it is impossible to format it properly. - has_formatting_errors: bool, - - // Formatted code differs from existing code (write-mode diff only). - pub has_diff: bool, - - // Keeps track of time spent in parsing and formatting steps. - timer: Timer, -} - -impl Summary { - pub fn mark_parse_time(&mut self) { - self.timer = self.timer.done_parsing(); - } - - pub fn mark_format_time(&mut self) { - self.timer = self.timer.done_formatting(); - } - - /// Returns the time it took to parse the source files in nanoseconds. - pub fn get_parse_time(&self) -> Option { - match self.timer { - Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { - // This should never underflow since `Instant::now()` guarantees monotonicity. - Some(parse_time.duration_since(init)) - } - Timer::Initialized(..) => None, - } - } - - /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is - /// not included. - pub fn get_format_time(&self) -> Option { - match self.timer { - Timer::DoneFormatting(_init, parse_time, format_time) => { - Some(format_time.duration_since(parse_time)) - } - Timer::DoneParsing(..) | Timer::Initialized(..) => None, - } - } - - pub fn has_operational_errors(&self) -> bool { - self.has_operational_errors - } - - pub fn has_parsing_errors(&self) -> bool { - self.has_parsing_errors - } - - pub fn has_formatting_errors(&self) -> bool { - self.has_formatting_errors - } - - pub fn add_operational_error(&mut self) { - self.has_operational_errors = true; - } - - pub fn add_parsing_error(&mut self) { - self.has_parsing_errors = true; - } - - pub fn add_formatting_error(&mut self) { - self.has_formatting_errors = true; - } - - pub fn add_diff(&mut self) { - self.has_diff = true; - } - - pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors - || self.has_diff) - } - - pub fn add(&mut self, other: Summary) { - self.has_operational_errors |= other.has_operational_errors; - self.has_formatting_errors |= other.has_formatting_errors; - self.has_parsing_errors |= other.has_parsing_errors; - self.has_diff |= other.has_diff; - } - - pub fn print_exit_codes() { - let exit_codes = r#"Exit Codes: - 0 = No errors - 1 = Encountered operational errors e.g. an IO error - 2 = Failed to reformat code because of parsing errors - 3 = Code is valid, but it is impossible to format it properly - 4 = Formatted code differs from existing code (write-mode diff only)"#; - println!("{}", exit_codes); - } -} - -#[derive(Clone, Copy, Debug)] -enum Timer { - Initialized(Instant), - DoneParsing(Instant, Instant), - DoneFormatting(Instant, Instant, Instant), -} - -impl Default for Timer { - fn default() -> Self { - Timer::Initialized(Instant::now()) - } -} - -impl Timer { - fn done_parsing(self) -> Self { - match self { - Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), - _ => panic!("Timer can only transition to DoneParsing from Initialized state"), - } - } - - fn done_formatting(self) -> Self { - match self { - Timer::DoneParsing(init_time, parse_time) => { - Timer::DoneFormatting(init_time, parse_time, Instant::now()) - } - _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), - } - } -} -- cgit 1.4.1-3-g733a5 From 3920282debba54d6a0c2c8115cfac878f10a7b3c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 7 Feb 2018 22:49:10 +0900 Subject: Create cargo-fmt crate --- cargo-fmt/Cargo.toml | 17 +++ cargo-fmt/src/main.rs | 373 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/cargo-fmt.rs | 373 -------------------------------------------------- 3 files changed, 390 insertions(+), 373 deletions(-) create mode 100644 cargo-fmt/Cargo.toml create mode 100644 cargo-fmt/src/main.rs delete mode 100644 src/bin/cargo-fmt.rs (limited to 'src') diff --git a/cargo-fmt/Cargo.toml b/cargo-fmt/Cargo.toml new file mode 100644 index 00000000000..87142657231 --- /dev/null +++ b/cargo-fmt/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "cargo-fmt" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "Cargo frontend for rustfmt" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +categories = ["development-tools"] + +[[bin]] +name = "cargo-fmt" + +[dependencies] +cargo_metadata = "0.4" +getopts = "0.2" +serde_json = "1.0" diff --git a/cargo-fmt/src/main.rs b/cargo-fmt/src/main.rs new file mode 100644 index 00000000000..1acad99688a --- /dev/null +++ b/cargo-fmt/src/main.rs @@ -0,0 +1,373 @@ +// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) + +#![cfg(not(test))] +#![deny(warnings)] + +extern crate cargo_metadata; +extern crate getopts; +extern crate serde_json as json; + +use std::collections::HashSet; +use std::env; +use std::fs; +use std::hash::{Hash, Hasher}; +use std::io::{self, Write}; +use std::iter::FromIterator; +use std::path::{Path, PathBuf}; +use std::process::{Command, ExitStatus}; +use std::str; + +use getopts::{Matches, Options}; + +fn main() { + let exit_status = execute(); + std::io::stdout().flush().unwrap(); + std::process::exit(exit_status); +} + +const SUCCESS: i32 = 0; +const FAILURE: i32 = 1; + +fn execute() -> i32 { + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("q", "quiet", "no output printed to stdout"); + opts.optflag("v", "verbose", "use verbose output"); + opts.optmulti( + "p", + "package", + "specify package to format (only usable in workspaces)", + "", + ); + opts.optflag("", "version", "print rustfmt version and exit"); + opts.optflag("", "all", "format all packages (only usable in workspaces)"); + + // If there is any invalid argument passed to `cargo fmt`, return without formatting. + let mut is_package_arg = false; + for arg in env::args().skip(2).take_while(|a| a != "--") { + if arg.starts_with('-') { + is_package_arg = arg.starts_with("--package"); + } else if !is_package_arg { + print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); + return FAILURE; + } else { + is_package_arg = false; + } + } + + let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { + Ok(m) => m, + Err(e) => { + print_usage_to_stderr(&opts, &e.to_string()); + return FAILURE; + } + }; + + let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { + (false, false) => Verbosity::Normal, + (false, true) => Verbosity::Quiet, + (true, false) => Verbosity::Verbose, + (true, true) => { + print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); + return FAILURE; + } + }; + + if matches.opt_present("h") { + print_usage_to_stdout(&opts, ""); + return SUCCESS; + } + + if matches.opt_present("version") { + return handle_command_status(get_version(verbosity), &opts); + } + + let strategy = CargoFmtStrategy::from_matches(&matches); + handle_command_status(format_crate(verbosity, &strategy), &opts) +} + +macro_rules! print_usage { + ($print: ident, $opts: ident, $reason: expr) => {{ + let msg = format!("{}\nusage: cargo fmt [options]", $reason); + $print!( + "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ + Arguments after `--` are passed to rustfmt.", + $opts.usage(&msg) + ); + }}; +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + print_usage!(println, opts, reason); +} + +fn print_usage_to_stderr(opts: &Options, reason: &str) { + print_usage!(eprintln, opts, reason); +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Verbosity { + Verbose, + Normal, + Quiet, +} + +fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { + match status { + Err(e) => { + print_usage_to_stderr(opts, &e.to_string()); + FAILURE + } + Ok(status) => { + if status.success() { + SUCCESS + } else { + status.code().unwrap_or(FAILURE) + } + } + } +} + +fn get_version(verbosity: Verbosity) -> Result { + run_rustfmt(&[], &[String::from("--version")], verbosity) +} + +fn format_crate( + verbosity: Verbosity, + strategy: &CargoFmtStrategy, +) -> Result { + let rustfmt_args = get_fmt_args(); + let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") { + HashSet::new() + } else { + get_targets(strategy)? + }; + + // Currently only bin and lib files get formatted + let files: Vec<_> = targets + .into_iter() + .inspect(|t| { + if verbosity == Verbosity::Verbose { + println!("[{}] {:?}", t.kind, t.path) + } + }) + .map(|t| t.path) + .collect(); + + run_rustfmt(&files, &rustfmt_args, verbosity) +} + +fn get_fmt_args() -> Vec { + // All arguments after -- are passed to rustfmt + env::args().skip_while(|a| a != "--").skip(1).collect() +} + +/// Target uses a `path` field for equality and hashing. +#[derive(Debug)] +pub struct Target { + /// A path to the main source file of the target. + path: PathBuf, + /// A kind of target (e.g. lib, bin, example, ...). + kind: String, +} + +impl Target { + pub fn from_target(target: &cargo_metadata::Target) -> Self { + let path = PathBuf::from(&target.src_path); + let canonicalized = fs::canonicalize(&path).unwrap_or(path); + + Target { + path: canonicalized, + kind: target.kind[0].clone(), + } + } +} + +impl PartialEq for Target { + fn eq(&self, other: &Target) -> bool { + self.path == other.path + } +} + +impl Eq for Target {} + +impl Hash for Target { + fn hash(&self, state: &mut H) { + self.path.hash(state); + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum CargoFmtStrategy { + /// Format every packages and dependencies. + All, + /// Format pacakges that are specified by the command line argument. + Some(Vec), + /// Format the root packages only. + Root, +} + +impl CargoFmtStrategy { + pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { + match (matches.opt_present("all"), matches.opt_present("p")) { + (false, false) => CargoFmtStrategy::Root, + (true, _) => CargoFmtStrategy::All, + (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), + } + } +} + +/// Based on the specified `CargoFmtStrategy`, returns a set of main source files. +fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { + let mut targets = HashSet::new(); + + match *strategy { + CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, + CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, + CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, + } + + if targets.is_empty() { + Err(io::Error::new( + io::ErrorKind::Other, + "Failed to find targets".to_owned(), + )) + } else { + Ok(targets) + } +} + +fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + + for package in metadata.packages { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } + } + + Ok(()) +} + +fn get_targets_recursive( + manifest_path: Option<&Path>, + mut targets: &mut HashSet, + visited: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(manifest_path)?; + + for package in metadata.packages { + add_targets(&package.targets, &mut targets); + + // Look for local dependencies. + for dependency in package.dependencies { + if dependency.source.is_some() || visited.contains(&dependency.name) { + continue; + } + + let mut manifest_path = PathBuf::from(&package.manifest_path); + + manifest_path.pop(); + manifest_path.push(&dependency.name); + manifest_path.push("Cargo.toml"); + + if manifest_path.exists() { + visited.insert(dependency.name); + get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; + } + } + } + + Ok(()) +} + +fn get_targets_with_hitlist( + hitlist: &[String], + targets: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + + let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); + + for package in metadata.packages { + if workspace_hitlist.remove(&package.name) { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } + } + } + + if workspace_hitlist.is_empty() { + Ok(()) + } else { + let package = workspace_hitlist.iter().next().unwrap(); + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("package `{}` is not a member of the workspace", package), + )) + } +} + +fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { + for target in target_paths { + targets.insert(Target::from_target(target)); + } +} + +fn run_rustfmt( + files: &[PathBuf], + fmt_args: &[String], + verbosity: Verbosity, +) -> Result { + let stdout = if verbosity == Verbosity::Quiet { + std::process::Stdio::null() + } else { + std::process::Stdio::inherit() + }; + + if verbosity == Verbosity::Verbose { + print!("rustfmt"); + for a in fmt_args { + print!(" {}", a); + } + for f in files { + print!(" {}", f.display()); + } + println!(); + } + + let mut command = Command::new("rustfmt") + .stdout(stdout) + .args(files) + .args(fmt_args) + .spawn() + .map_err(|e| match e.kind() { + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), + _ => e, + })?; + + command.wait() +} + +fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { + match cargo_metadata::metadata(manifest_path) { + Ok(metadata) => Ok(metadata), + Err(..) => Err(io::Error::new( + io::ErrorKind::Other, + "`cargo manifest` failed.", + )), + } +} diff --git a/src/bin/cargo-fmt.rs b/src/bin/cargo-fmt.rs deleted file mode 100644 index 1acad99688a..00000000000 --- a/src/bin/cargo-fmt.rs +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) - -#![cfg(not(test))] -#![deny(warnings)] - -extern crate cargo_metadata; -extern crate getopts; -extern crate serde_json as json; - -use std::collections::HashSet; -use std::env; -use std::fs; -use std::hash::{Hash, Hasher}; -use std::io::{self, Write}; -use std::iter::FromIterator; -use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus}; -use std::str; - -use getopts::{Matches, Options}; - -fn main() { - let exit_status = execute(); - std::io::stdout().flush().unwrap(); - std::process::exit(exit_status); -} - -const SUCCESS: i32 = 0; -const FAILURE: i32 = 1; - -fn execute() -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("q", "quiet", "no output printed to stdout"); - opts.optflag("v", "verbose", "use verbose output"); - opts.optmulti( - "p", - "package", - "specify package to format (only usable in workspaces)", - "", - ); - opts.optflag("", "version", "print rustfmt version and exit"); - opts.optflag("", "all", "format all packages (only usable in workspaces)"); - - // If there is any invalid argument passed to `cargo fmt`, return without formatting. - let mut is_package_arg = false; - for arg in env::args().skip(2).take_while(|a| a != "--") { - if arg.starts_with('-') { - is_package_arg = arg.starts_with("--package"); - } else if !is_package_arg { - print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); - return FAILURE; - } else { - is_package_arg = false; - } - } - - let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { - Ok(m) => m, - Err(e) => { - print_usage_to_stderr(&opts, &e.to_string()); - return FAILURE; - } - }; - - let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { - (false, false) => Verbosity::Normal, - (false, true) => Verbosity::Quiet, - (true, false) => Verbosity::Verbose, - (true, true) => { - print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); - return FAILURE; - } - }; - - if matches.opt_present("h") { - print_usage_to_stdout(&opts, ""); - return SUCCESS; - } - - if matches.opt_present("version") { - return handle_command_status(get_version(verbosity), &opts); - } - - let strategy = CargoFmtStrategy::from_matches(&matches); - handle_command_status(format_crate(verbosity, &strategy), &opts) -} - -macro_rules! print_usage { - ($print: ident, $opts: ident, $reason: expr) => {{ - let msg = format!("{}\nusage: cargo fmt [options]", $reason); - $print!( - "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ - Arguments after `--` are passed to rustfmt.", - $opts.usage(&msg) - ); - }}; -} - -fn print_usage_to_stdout(opts: &Options, reason: &str) { - print_usage!(println, opts, reason); -} - -fn print_usage_to_stderr(opts: &Options, reason: &str) { - print_usage!(eprintln, opts, reason); -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Verbosity { - Verbose, - Normal, - Quiet, -} - -fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { - match status { - Err(e) => { - print_usage_to_stderr(opts, &e.to_string()); - FAILURE - } - Ok(status) => { - if status.success() { - SUCCESS - } else { - status.code().unwrap_or(FAILURE) - } - } - } -} - -fn get_version(verbosity: Verbosity) -> Result { - run_rustfmt(&[], &[String::from("--version")], verbosity) -} - -fn format_crate( - verbosity: Verbosity, - strategy: &CargoFmtStrategy, -) -> Result { - let rustfmt_args = get_fmt_args(); - let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") { - HashSet::new() - } else { - get_targets(strategy)? - }; - - // Currently only bin and lib files get formatted - let files: Vec<_> = targets - .into_iter() - .inspect(|t| { - if verbosity == Verbosity::Verbose { - println!("[{}] {:?}", t.kind, t.path) - } - }) - .map(|t| t.path) - .collect(); - - run_rustfmt(&files, &rustfmt_args, verbosity) -} - -fn get_fmt_args() -> Vec { - // All arguments after -- are passed to rustfmt - env::args().skip_while(|a| a != "--").skip(1).collect() -} - -/// Target uses a `path` field for equality and hashing. -#[derive(Debug)] -pub struct Target { - /// A path to the main source file of the target. - path: PathBuf, - /// A kind of target (e.g. lib, bin, example, ...). - kind: String, -} - -impl Target { - pub fn from_target(target: &cargo_metadata::Target) -> Self { - let path = PathBuf::from(&target.src_path); - let canonicalized = fs::canonicalize(&path).unwrap_or(path); - - Target { - path: canonicalized, - kind: target.kind[0].clone(), - } - } -} - -impl PartialEq for Target { - fn eq(&self, other: &Target) -> bool { - self.path == other.path - } -} - -impl Eq for Target {} - -impl Hash for Target { - fn hash(&self, state: &mut H) { - self.path.hash(state); - } -} - -#[derive(Debug, PartialEq, Eq)] -pub enum CargoFmtStrategy { - /// Format every packages and dependencies. - All, - /// Format pacakges that are specified by the command line argument. - Some(Vec), - /// Format the root packages only. - Root, -} - -impl CargoFmtStrategy { - pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { - match (matches.opt_present("all"), matches.opt_present("p")) { - (false, false) => CargoFmtStrategy::Root, - (true, _) => CargoFmtStrategy::All, - (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), - } - } -} - -/// Based on the specified `CargoFmtStrategy`, returns a set of main source files. -fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { - let mut targets = HashSet::new(); - - match *strategy { - CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, - CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, - CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, - } - - if targets.is_empty() { - Err(io::Error::new( - io::ErrorKind::Other, - "Failed to find targets".to_owned(), - )) - } else { - Ok(targets) - } -} - -fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None)?; - - for package in metadata.packages { - for target in package.targets { - targets.insert(Target::from_target(&target)); - } - } - - Ok(()) -} - -fn get_targets_recursive( - manifest_path: Option<&Path>, - mut targets: &mut HashSet, - visited: &mut HashSet, -) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path)?; - - for package in metadata.packages { - add_targets(&package.targets, &mut targets); - - // Look for local dependencies. - for dependency in package.dependencies { - if dependency.source.is_some() || visited.contains(&dependency.name) { - continue; - } - - let mut manifest_path = PathBuf::from(&package.manifest_path); - - manifest_path.pop(); - manifest_path.push(&dependency.name); - manifest_path.push("Cargo.toml"); - - if manifest_path.exists() { - visited.insert(dependency.name); - get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; - } - } - } - - Ok(()) -} - -fn get_targets_with_hitlist( - hitlist: &[String], - targets: &mut HashSet, -) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None)?; - - let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); - - for package in metadata.packages { - if workspace_hitlist.remove(&package.name) { - for target in package.targets { - targets.insert(Target::from_target(&target)); - } - } - } - - if workspace_hitlist.is_empty() { - Ok(()) - } else { - let package = workspace_hitlist.iter().next().unwrap(); - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("package `{}` is not a member of the workspace", package), - )) - } -} - -fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { - for target in target_paths { - targets.insert(Target::from_target(target)); - } -} - -fn run_rustfmt( - files: &[PathBuf], - fmt_args: &[String], - verbosity: Verbosity, -) -> Result { - let stdout = if verbosity == Verbosity::Quiet { - std::process::Stdio::null() - } else { - std::process::Stdio::inherit() - }; - - if verbosity == Verbosity::Verbose { - print!("rustfmt"); - for a in fmt_args { - print!(" {}", a); - } - for f in files { - print!(" {}", f.display()); - } - println!(); - } - - let mut command = Command::new("rustfmt") - .stdout(stdout) - .args(files) - .args(fmt_args) - .spawn() - .map_err(|e| match e.kind() { - io::ErrorKind::NotFound => io::Error::new( - io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your PATH.", - ), - _ => e, - })?; - - command.wait() -} - -fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { - match cargo_metadata::metadata(manifest_path) { - Ok(metadata) => Ok(metadata), - Err(..) => Err(io::Error::new( - io::ErrorKind::Other, - "`cargo manifest` failed.", - )), - } -} -- cgit 1.4.1-3-g733a5 From d18cd1d11c4e54385063ff57d63b150819f4c946 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 7 Feb 2018 22:49:26 +0900 Subject: Create rustfmt-bin crate --- rustfmt-bin/Cargo.toml | 20 ++ rustfmt-bin/build.rs | 49 +++++ rustfmt-bin/src/main.rs | 477 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/rustfmt.rs | 476 ----------------------------------------------- 4 files changed, 546 insertions(+), 476 deletions(-) create mode 100644 rustfmt-bin/Cargo.toml create mode 100644 rustfmt-bin/build.rs create mode 100644 rustfmt-bin/src/main.rs delete mode 100644 src/bin/rustfmt.rs (limited to 'src') diff --git a/rustfmt-bin/Cargo.toml b/rustfmt-bin/Cargo.toml new file mode 100644 index 00000000000..c07146dcb01 --- /dev/null +++ b/rustfmt-bin/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "rustfmt-bin" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "Tool to find and fix Rust formatting issues" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +build = "build.rs" +categories = ["development-tools"] + +[[bin]] +name = "rustfmt" +path = "src/main.rs" + +[dependencies] +env_logger = "0.4" +getopts = "0.2" +rustfmt-config = { path = "../rustfmt-config" } +rustfmt-core = { path = "../rustfmt-core" } \ No newline at end of file diff --git a/rustfmt-bin/build.rs b/rustfmt-bin/build.rs new file mode 100644 index 00000000000..2643946236d --- /dev/null +++ b/rustfmt-bin/build.rs @@ -0,0 +1,49 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; +use std::process::Command; + +fn main() { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + File::create(out_dir.join("commit-info.txt")) + .unwrap() + .write_all(commit_info().as_bytes()) + .unwrap(); +} + +// Try to get hash and date of the last commit on a best effort basis. If anything goes wrong +// (git not installed or if this is not a git repository) just return an empty string. +fn commit_info() -> String { + match (commit_hash(), commit_date()) { + (Some(hash), Some(date)) => format!(" ({} {})", hash.trim_right(), date), + _ => String::new(), + } +} + +fn commit_hash() -> Option { + Command::new("git") + .args(&["rev-parse", "--short", "HEAD"]) + .output() + .ok() + .and_then(|r| String::from_utf8(r.stdout).ok()) +} + +fn commit_date() -> Option { + Command::new("git") + .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) + .output() + .ok() + .and_then(|r| String::from_utf8(r.stdout).ok()) +} diff --git a/rustfmt-bin/src/main.rs b/rustfmt-bin/src/main.rs new file mode 100644 index 00000000000..fbaacc69bdf --- /dev/null +++ b/rustfmt-bin/src/main.rs @@ -0,0 +1,477 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(not(test))] + +extern crate env_logger; +extern crate getopts; +extern crate rustfmt_config as config; +extern crate rustfmt_core as rustfmt; + +use std::{env, error}; +use std::fs::File; +use std::io::{self, Read, Write}; +use std::path::{Path, PathBuf}; + +use getopts::{Matches, Options}; + +use config::{get_toml_path, Color, Config, WriteMode}; +use config::file_lines::FileLines; +use rustfmt::{run, FileName, Input, Summary}; + +use std::str::FromStr; + +type FmtError = Box; +type FmtResult = std::result::Result; + +/// Rustfmt operations. +enum Operation { + /// Format files and their child modules. + Format { + files: Vec, + config_path: Option, + minimal_config_path: Option, + }, + /// Print the help message. + Help, + // Print version information + Version, + /// Print detailed configuration help. + ConfigHelp, + /// Output default config to a file, or stdout if None + ConfigOutputDefault { + path: Option, + }, + /// No file specified, read from stdin + Stdin { + input: String, + config_path: Option, + }, +} + +/// Parsed command line options. +#[derive(Clone, Debug, Default)] +struct CliOptions { + skip_children: bool, + verbose: bool, + write_mode: Option, + color: Option, + file_lines: FileLines, // Default is all lines in all files. + unstable_features: bool, + error_on_unformatted: bool, +} + +impl CliOptions { + fn from_matches(matches: &Matches) -> FmtResult { + let mut options = CliOptions::default(); + options.skip_children = matches.opt_present("skip-children"); + options.verbose = matches.opt_present("verbose"); + let unstable_features = matches.opt_present("unstable-features"); + let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false); + if unstable_features && !rust_nightly { + return Err(FmtError::from( + "Unstable features are only available on Nightly channel", + )); + } else { + options.unstable_features = unstable_features; + } + + if let Some(ref write_mode) = matches.opt_str("write-mode") { + if let Ok(write_mode) = WriteMode::from_str(write_mode) { + options.write_mode = Some(write_mode); + } else { + return Err(FmtError::from(format!( + "Invalid write-mode: {}", + write_mode + ))); + } + } + + if let Some(ref color) = matches.opt_str("color") { + match Color::from_str(color) { + Ok(color) => options.color = Some(color), + _ => return Err(FmtError::from(format!("Invalid color: {}", color))), + } + } + + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse()?; + } + + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = true; + } + + Ok(options) + } + + fn apply_to(self, config: &mut Config) { + config.set().skip_children(self.skip_children); + config.set().verbose(self.verbose); + config.set().file_lines(self.file_lines); + config.set().unstable_features(self.unstable_features); + config.set().error_on_unformatted(self.error_on_unformatted); + if let Some(write_mode) = self.write_mode { + config.set().write_mode(write_mode); + } + if let Some(color) = self.color { + config.set().color(color); + } + } +} + +/// read the given config file path recursively if present else read the project file path +fn match_cli_path_or_file( + config_path: Option, + input_file: &Path, +) -> FmtResult<(Config, Option)> { + if let Some(config_file) = config_path { + let toml = Config::from_toml_path(config_file.as_ref())?; + return Ok((toml, Some(config_file))); + } + Config::from_resolved_toml_path(input_file).map_err(FmtError::from) +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + + // Sorted in alphabetical order. + opts.optopt( + "", + "color", + "Use colored output (if supported)", + "[always|never|auto]", + ); + opts.optflag( + "", + "config-help", + "Show details of rustfmt configuration options", + ); + opts.optopt( + "", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ + found reverts to the input file path", + "[Path for the configuration file]", + ); + opts.optopt( + "", + "dump-default-config", + "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", + "PATH", + ); + opts.optopt( + "", + "dump-minimal-config", + "Dumps configuration options that were checked during formatting to a file.", + "PATH", + ); + opts.optflag( + "", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces", + ); + opts.optopt( + "", + "file-lines", + "Format specified line ranges. See README for more detail on the JSON format.", + "JSON", + ); + opts.optflag("h", "help", "Show this message"); + opts.optflag("", "skip-children", "Don't reformat child modules"); + opts.optflag( + "", + "unstable-features", + "Enables unstable features. Only available on nightly channel", + ); + opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("V", "version", "Show version information"); + opts.optopt( + "", + "write-mode", + "How to write output (not usable when piping from stdin)", + "[replace|overwrite|display|plain|diff|coverage|checkstyle]", + ); + + opts +} + +fn execute(opts: &Options) -> FmtResult { + let matches = opts.parse(env::args().skip(1))?; + + match determine_operation(&matches)? { + Operation::Help => { + print_usage_to_stdout(opts, ""); + Summary::print_exit_codes(); + Ok(Summary::default()) + } + Operation::Version => { + print_version(); + Ok(Summary::default()) + } + Operation::ConfigHelp => { + Config::print_docs(); + Ok(Summary::default()) + } + Operation::ConfigOutputDefault { path } => { + let toml = Config::default().all_options().to_toml()?; + if let Some(path) = path { + let mut file = File::create(path)?; + file.write_all(toml.as_bytes())?; + } else { + io::stdout().write_all(toml.as_bytes())?; + } + Ok(Summary::default()) + } + Operation::Stdin { input, config_path } => { + // try to read config from local directory + let (mut config, _) = + match_cli_path_or_file(config_path, &env::current_dir().unwrap())?; + + // write_mode is always Plain for Stdin. + config.set().write_mode(WriteMode::Plain); + + // parse file_lines + if let Some(ref file_lines) = matches.opt_str("file-lines") { + config.set().file_lines(file_lines.parse()?); + for f in config.file_lines().files() { + match *f { + FileName::Custom(ref f) if f == "stdin" => {} + _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), + } + } + } + + let mut error_summary = Summary::default(); + if config.version_meets_requirement(&mut error_summary) { + error_summary.add(run(Input::Text(input), &config)); + } + + Ok(error_summary) + } + Operation::Format { + files, + config_path, + minimal_config_path, + } => { + let options = CliOptions::from_matches(&matches)?; + + for f in options.file_lines.files() { + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) + } + _ => eprintln!("Warning: Not a file '{}'", f), + } + } + + let mut config = Config::default(); + // Load the config path file if provided + if let Some(config_file) = config_path.as_ref() { + config = Config::from_toml_path(config_file.as_ref())?; + }; + + if options.verbose { + if let Some(path) = config_path.as_ref() { + println!("Using rustfmt config file {}", path.display()); + } + } + + let mut error_summary = Summary::default(); + for file in files { + if !file.exists() { + eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else if file.is_dir() { + eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else { + // Check the file directory if the config-path could not be read or not provided + if config_path.is_none() { + let (config_tmp, path_tmp) = + Config::from_resolved_toml_path(file.parent().unwrap())?; + if options.verbose { + if let Some(path) = path_tmp.as_ref() { + println!( + "Using rustfmt config file {} for {}", + path.display(), + file.display() + ); + } + } + config = config_tmp; + } + + if !config.version_meets_requirement(&mut error_summary) { + break; + } + + options.clone().apply_to(&mut config); + error_summary.add(run(Input::File(file), &config)); + } + } + + // If we were given a path via dump-minimal-config, output any options + // that were used during formatting as TOML. + if let Some(path) = minimal_config_path { + let mut file = File::create(path)?; + let toml = config.used_options().to_toml()?; + file.write_all(toml.as_bytes())?; + } + + Ok(error_summary) + } + } +} + +fn main() { + let _ = env_logger::init(); + + let opts = make_opts(); + + let exit_code = match execute(&opts) { + Ok(summary) => { + if summary.has_operational_errors() { + 1 + } else if summary.has_parsing_errors() { + 2 + } else if summary.has_formatting_errors() { + 3 + } else if summary.has_diff { + // should only happen in diff mode + 4 + } else { + assert!(summary.has_no_errors()); + 0 + } + } + Err(e) => { + eprintln!("{}", e.to_string()); + 1 + } + }; + // Make sure standard output is flushed before we exit. + std::io::stdout().flush().unwrap(); + + // Exit with given exit code. + // + // NOTE: This immediately terminates the process without doing any cleanup, + // so make sure to finish all necessary cleanup before this is called. + std::process::exit(exit_code); +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + let sep = if reason.is_empty() { + String::new() + } else { + format!("{}\n\n", reason) + }; + let msg = format!( + "{}Format Rust code\n\nusage: {} [options] ...", + sep, + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&msg)); +} + +fn print_version() { + println!( + "{}-nightly{}", + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), + include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) + ) +} + +fn determine_operation(matches: &Matches) -> FmtResult { + if matches.opt_present("h") { + return Ok(Operation::Help); + } + + if matches.opt_present("config-help") { + return Ok(Operation::ConfigHelp); + } + + if matches.opt_present("dump-default-config") { + // NOTE for some reason when configured with HasArg::Maybe + Occur::Optional opt_default + // doesn't recognize `--foo bar` as a long flag with an argument but as a long flag with no + // argument *plus* a free argument. Thus we check for that case in this branch -- this is + // required for backward compatibility. + if let Some(path) = matches.free.get(0) { + return Ok(Operation::ConfigOutputDefault { + path: Some(path.clone()), + }); + } else { + return Ok(Operation::ConfigOutputDefault { + path: matches.opt_str("dump-default-config"), + }); + } + } + + if matches.opt_present("version") { + return Ok(Operation::Version); + } + + let config_path_not_found = |path: &str| -> FmtResult { + Err(FmtError::from(format!( + "Error: unable to find a config file for the given path: `{}`", + path + ))) + }; + + // Read the config_path and convert to parent dir if a file is provided. + // If a config file cannot be found from the given path, return error. + let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { + Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), + Some(ref path) if path.is_dir() => { + let config_file_path = get_toml_path(path)?; + if config_file_path.is_some() { + config_file_path + } else { + return config_path_not_found(path.to_str().unwrap()); + } + } + path => path, + }; + + // If no path is given, we won't output a minimal config. + let minimal_config_path = matches.opt_str("dump-minimal-config"); + + // if no file argument is supplied, read from stdin + if matches.free.is_empty() { + let mut buffer = String::new(); + io::stdin().read_to_string(&mut buffer)?; + + return Ok(Operation::Stdin { + input: buffer, + config_path, + }); + } + + let files: Vec<_> = matches + .free + .iter() + .map(|s| { + let p = PathBuf::from(s); + // we will do comparison later, so here tries to canonicalize first + // to get the expected behavior. + p.canonicalize().unwrap_or(p) + }) + .collect(); + + Ok(Operation::Format { + files, + config_path, + minimal_config_path, + }) +} diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs deleted file mode 100644 index 214c02f95a5..00000000000 --- a/src/bin/rustfmt.rs +++ /dev/null @@ -1,476 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(rustc_private)] -#![cfg(not(test))] - -extern crate env_logger; -extern crate getopts; -extern crate rustfmt_nightly as rustfmt; - -use std::{env, error}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::path::{Path, PathBuf}; -use std::str::FromStr; - -use getopts::{Matches, Options}; - -use rustfmt::{run, FileName, Input, Summary}; -use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; -use rustfmt::file_lines::FileLines; - -type FmtError = Box; -type FmtResult = std::result::Result; - -/// Rustfmt operations. -enum Operation { - /// Format files and their child modules. - Format { - files: Vec, - config_path: Option, - minimal_config_path: Option, - }, - /// Print the help message. - Help, - // Print version information - Version, - /// Print detailed configuration help. - ConfigHelp, - /// Output default config to a file, or stdout if None - ConfigOutputDefault { - path: Option, - }, - /// No file specified, read from stdin - Stdin { - input: String, - config_path: Option, - }, -} - -/// Parsed command line options. -#[derive(Clone, Debug, Default)] -struct CliOptions { - skip_children: bool, - verbose: bool, - write_mode: Option, - color: Option, - file_lines: FileLines, // Default is all lines in all files. - unstable_features: bool, - error_on_unformatted: bool, -} - -impl CliOptions { - fn from_matches(matches: &Matches) -> FmtResult { - let mut options = CliOptions::default(); - options.skip_children = matches.opt_present("skip-children"); - options.verbose = matches.opt_present("verbose"); - let unstable_features = matches.opt_present("unstable-features"); - let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(false); - if unstable_features && !rust_nightly { - return Err(FmtError::from( - "Unstable features are only available on Nightly channel", - )); - } else { - options.unstable_features = unstable_features; - } - - if let Some(ref write_mode) = matches.opt_str("write-mode") { - if let Ok(write_mode) = WriteMode::from_str(write_mode) { - options.write_mode = Some(write_mode); - } else { - return Err(FmtError::from(format!( - "Invalid write-mode: {}", - write_mode - ))); - } - } - - if let Some(ref color) = matches.opt_str("color") { - match Color::from_str(color) { - Ok(color) => options.color = Some(color), - _ => return Err(FmtError::from(format!("Invalid color: {}", color))), - } - } - - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse()?; - } - - if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = true; - } - - Ok(options) - } - - fn apply_to(self, config: &mut Config) { - config.set().skip_children(self.skip_children); - config.set().verbose(self.verbose); - config.set().file_lines(self.file_lines); - config.set().unstable_features(self.unstable_features); - config.set().error_on_unformatted(self.error_on_unformatted); - if let Some(write_mode) = self.write_mode { - config.set().write_mode(write_mode); - } - if let Some(color) = self.color { - config.set().color(color); - } - } -} - -/// read the given config file path recursively if present else read the project file path -fn match_cli_path_or_file( - config_path: Option, - input_file: &Path, -) -> FmtResult<(Config, Option)> { - if let Some(config_file) = config_path { - let toml = Config::from_toml_path(config_file.as_ref())?; - return Ok((toml, Some(config_file))); - } - Config::from_resolved_toml_path(input_file).map_err(FmtError::from) -} - -fn make_opts() -> Options { - let mut opts = Options::new(); - - // Sorted in alphabetical order. - opts.optopt( - "", - "color", - "Use colored output (if supported)", - "[always|never|auto]", - ); - opts.optflag( - "", - "config-help", - "Show details of rustfmt configuration options", - ); - opts.optopt( - "", - "config-path", - "Recursively searches the given path for the rustfmt.toml config file. If not \ - found reverts to the input file path", - "[Path for the configuration file]", - ); - opts.optopt( - "", - "dump-default-config", - "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", - "PATH", - ); - opts.optopt( - "", - "dump-minimal-config", - "Dumps configuration options that were checked during formatting to a file.", - "PATH", - ); - opts.optflag( - "", - "error-on-unformatted", - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces", - ); - opts.optopt( - "", - "file-lines", - "Format specified line ranges. See README for more detail on the JSON format.", - "JSON", - ); - opts.optflag("h", "help", "Show this message"); - opts.optflag("", "skip-children", "Don't reformat child modules"); - opts.optflag( - "", - "unstable-features", - "Enables unstable features. Only available on nightly channel", - ); - opts.optflag("v", "verbose", "Print verbose output"); - opts.optflag("V", "version", "Show version information"); - opts.optopt( - "", - "write-mode", - "How to write output (not usable when piping from stdin)", - "[replace|overwrite|display|plain|diff|coverage|checkstyle]", - ); - - opts -} - -fn execute(opts: &Options) -> FmtResult { - let matches = opts.parse(env::args().skip(1))?; - - match determine_operation(&matches)? { - Operation::Help => { - print_usage_to_stdout(opts, ""); - Summary::print_exit_codes(); - Ok(Summary::default()) - } - Operation::Version => { - print_version(); - Ok(Summary::default()) - } - Operation::ConfigHelp => { - Config::print_docs(); - Ok(Summary::default()) - } - Operation::ConfigOutputDefault { path } => { - let toml = Config::default().all_options().to_toml()?; - if let Some(path) = path { - let mut file = File::create(path)?; - file.write_all(toml.as_bytes())?; - } else { - io::stdout().write_all(toml.as_bytes())?; - } - Ok(Summary::default()) - } - Operation::Stdin { input, config_path } => { - // try to read config from local directory - let (mut config, _) = - match_cli_path_or_file(config_path, &env::current_dir().unwrap())?; - - // write_mode is always Plain for Stdin. - config.set().write_mode(WriteMode::Plain); - - // parse file_lines - if let Some(ref file_lines) = matches.opt_str("file-lines") { - config.set().file_lines(file_lines.parse()?); - for f in config.file_lines().files() { - match *f { - FileName::Custom(ref f) if f == "stdin" => {} - _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), - } - } - } - - let mut error_summary = Summary::default(); - if config.version_meets_requirement(&mut error_summary) { - error_summary.add(run(Input::Text(input), &config)); - } - - Ok(error_summary) - } - Operation::Format { - files, - config_path, - minimal_config_path, - } => { - let options = CliOptions::from_matches(&matches)?; - - for f in options.file_lines.files() { - match *f { - FileName::Real(ref f) if files.contains(f) => {} - FileName::Real(_) => { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f) - } - _ => eprintln!("Warning: Not a file '{}'", f), - } - } - - let mut config = Config::default(); - // Load the config path file if provided - if let Some(config_file) = config_path.as_ref() { - config = Config::from_toml_path(config_file.as_ref())?; - }; - - if options.verbose { - if let Some(path) = config_path.as_ref() { - println!("Using rustfmt config file {}", path.display()); - } - } - - let mut error_summary = Summary::default(); - for file in files { - if !file.exists() { - eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); - error_summary.add_operational_error(); - } else if file.is_dir() { - eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); - error_summary.add_operational_error(); - } else { - // Check the file directory if the config-path could not be read or not provided - if config_path.is_none() { - let (config_tmp, path_tmp) = - Config::from_resolved_toml_path(file.parent().unwrap())?; - if options.verbose { - if let Some(path) = path_tmp.as_ref() { - println!( - "Using rustfmt config file {} for {}", - path.display(), - file.display() - ); - } - } - config = config_tmp; - } - - if !config.version_meets_requirement(&mut error_summary) { - break; - } - - options.clone().apply_to(&mut config); - error_summary.add(run(Input::File(file), &config)); - } - } - - // If we were given a path via dump-minimal-config, output any options - // that were used during formatting as TOML. - if let Some(path) = minimal_config_path { - let mut file = File::create(path)?; - let toml = config.used_options().to_toml()?; - file.write_all(toml.as_bytes())?; - } - - Ok(error_summary) - } - } -} - -fn main() { - let _ = env_logger::init(); - - let opts = make_opts(); - - let exit_code = match execute(&opts) { - Ok(summary) => { - if summary.has_operational_errors() { - 1 - } else if summary.has_parsing_errors() { - 2 - } else if summary.has_formatting_errors() { - 3 - } else if summary.has_diff { - // should only happen in diff mode - 4 - } else { - assert!(summary.has_no_errors()); - 0 - } - } - Err(e) => { - eprintln!("{}", e.to_string()); - 1 - } - }; - // Make sure standard output is flushed before we exit. - std::io::stdout().flush().unwrap(); - - // Exit with given exit code. - // - // NOTE: This immediately terminates the process without doing any cleanup, - // so make sure to finish all necessary cleanup before this is called. - std::process::exit(exit_code); -} - -fn print_usage_to_stdout(opts: &Options, reason: &str) { - let sep = if reason.is_empty() { - String::new() - } else { - format!("{}\n\n", reason) - }; - let msg = format!( - "{}Format Rust code\n\nusage: {} [options] ...", - sep, - env::args_os().next().unwrap().to_string_lossy() - ); - println!("{}", opts.usage(&msg)); -} - -fn print_version() { - println!( - "{}-nightly{}", - option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), - include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) - ) -} - -fn determine_operation(matches: &Matches) -> FmtResult { - if matches.opt_present("h") { - return Ok(Operation::Help); - } - - if matches.opt_present("config-help") { - return Ok(Operation::ConfigHelp); - } - - if matches.opt_present("dump-default-config") { - // NOTE for some reason when configured with HasArg::Maybe + Occur::Optional opt_default - // doesn't recognize `--foo bar` as a long flag with an argument but as a long flag with no - // argument *plus* a free argument. Thus we check for that case in this branch -- this is - // required for backward compatibility. - if let Some(path) = matches.free.get(0) { - return Ok(Operation::ConfigOutputDefault { - path: Some(path.clone()), - }); - } else { - return Ok(Operation::ConfigOutputDefault { - path: matches.opt_str("dump-default-config"), - }); - } - } - - if matches.opt_present("version") { - return Ok(Operation::Version); - } - - let config_path_not_found = |path: &str| -> FmtResult { - Err(FmtError::from(format!( - "Error: unable to find a config file for the given path: `{}`", - path - ))) - }; - - // Read the config_path and convert to parent dir if a file is provided. - // If a config file cannot be found from the given path, return error. - let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { - Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), - Some(ref path) if path.is_dir() => { - let config_file_path = get_toml_path(path)?; - if config_file_path.is_some() { - config_file_path - } else { - return config_path_not_found(path.to_str().unwrap()); - } - } - path => path, - }; - - // If no path is given, we won't output a minimal config. - let minimal_config_path = matches.opt_str("dump-minimal-config"); - - // if no file argument is supplied, read from stdin - if matches.free.is_empty() { - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - - return Ok(Operation::Stdin { - input: buffer, - config_path, - }); - } - - let files: Vec<_> = matches - .free - .iter() - .map(|s| { - let p = PathBuf::from(s); - // we will do comparison later, so here tries to canonicalize first - // to get the expected behavior. - p.canonicalize().unwrap_or(p) - }) - .collect(); - - Ok(Operation::Format { - files, - config_path, - minimal_config_path, - }) -} -- cgit 1.4.1-3-g733a5 From d28d7fee89cf8d01f06dc8f450c1614fc830b948 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 7 Feb 2018 22:49:43 +0900 Subject: Create rustfmt-format-diff crate --- rustfmt-format-diff/Cargo.toml | 21 +++ rustfmt-format-diff/src/main.rs | 267 ++++++++++++++++++++++++++++++ rustfmt-format-diff/src/test/bindgen.diff | 67 ++++++++ src/bin/rustfmt-format-diff.rs | 267 ------------------------------ src/bin/test/bindgen.diff | 67 -------- 5 files changed, 355 insertions(+), 334 deletions(-) create mode 100644 rustfmt-format-diff/Cargo.toml create mode 100644 rustfmt-format-diff/src/main.rs create mode 100644 rustfmt-format-diff/src/test/bindgen.diff delete mode 100644 src/bin/rustfmt-format-diff.rs delete mode 100644 src/bin/test/bindgen.diff (limited to 'src') diff --git a/rustfmt-format-diff/Cargo.toml b/rustfmt-format-diff/Cargo.toml new file mode 100644 index 00000000000..a74c08616bd --- /dev/null +++ b/rustfmt-format-diff/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "rustfmt-format-diff" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "Run rustfmt against diff" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +categories = ["development-tools"] + +[[bin]] +name = "rustfmt-format-diff" + +[dependencies] +env_logger = "0.4" +getopts = "0.2" +log = "0.3" +regex = "0.2" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" \ No newline at end of file diff --git a/rustfmt-format-diff/src/main.rs b/rustfmt-format-diff/src/main.rs new file mode 100644 index 00000000000..c42fbb6f7cf --- /dev/null +++ b/rustfmt-format-diff/src/main.rs @@ -0,0 +1,267 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Clang's clang-format-diff: +// +// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py + +#![deny(warnings)] + +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate regex; +#[macro_use] +extern crate serde_derive; +extern crate serde_json as json; + +use std::{env, fmt, process}; +use std::collections::HashSet; +use std::error::Error; +use std::io::{self, BufRead}; + +use regex::Regex; + +/// The default pattern of files to format. +/// +/// We only want to format rust files by default. +const DEFAULT_PATTERN: &str = r".*\.rs"; + +#[derive(Debug)] +enum FormatDiffError { + IncorrectOptions(getopts::Fail), + IncorrectFilter(regex::Error), + IoError(io::Error), +} + +impl fmt::Display for FormatDiffError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fmt::Display::fmt(self.cause().unwrap(), f) + } +} + +impl Error for FormatDiffError { + fn description(&self) -> &str { + self.cause().unwrap().description() + } + + fn cause(&self) -> Option<&Error> { + Some(match *self { + FormatDiffError::IoError(ref e) => e, + FormatDiffError::IncorrectFilter(ref e) => e, + FormatDiffError::IncorrectOptions(ref e) => e, + }) + } +} + +impl From for FormatDiffError { + fn from(fail: getopts::Fail) -> Self { + FormatDiffError::IncorrectOptions(fail) + } +} + +impl From for FormatDiffError { + fn from(err: regex::Error) -> Self { + FormatDiffError::IncorrectFilter(err) + } +} + +impl From for FormatDiffError { + fn from(fail: io::Error) -> Self { + FormatDiffError::IoError(fail) + } +} + +fn main() { + let _ = env_logger::init(); + + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optopt( + "p", + "skip-prefix", + "skip the smallest prefix containing NUMBER slashes", + "NUMBER", + ); + opts.optopt( + "f", + "filter", + "custom pattern selecting file paths to reformat", + "PATTERN", + ); + + if let Err(e) = run(&opts) { + println!("{}", opts.usage(e.description())); + process::exit(1); + } +} + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +struct Range { + file: String, + range: [u32; 2], +} + +fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { + let matches = opts.parse(env::args().skip(1))?; + + if matches.opt_present("h") { + println!("{}", opts.usage("usage: ")); + return Ok(()); + } + + let filter = matches + .opt_str("f") + .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); + + let skip_prefix = matches + .opt_str("p") + .and_then(|p| p.parse::().ok()) + .unwrap_or(0); + + let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; + + run_rustfmt(&files, &ranges) +} + +fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDiffError> { + if files.is_empty() || ranges.is_empty() { + debug!("No files to format found"); + return Ok(()); + } + + let ranges_as_json = json::to_string(ranges).unwrap(); + + debug!("Files: {:?}", files); + debug!("Ranges: {:?}", ranges); + + let exit_status = process::Command::new("rustfmt") + .args(files) + .arg("--file-lines") + .arg(ranges_as_json) + .status()?; + + if !exit_status.success() { + return Err(FormatDiffError::IoError(io::Error::new( + io::ErrorKind::Other, + format!("rustfmt failed with {}", exit_status), + ))); + } + Ok(()) +} + +/// Scans a diff from `from`, and returns the set of files found, and the ranges +/// in those files. +fn scan_diff( + from: R, + skip_prefix: u32, + file_filter: &str, +) -> Result<(HashSet, Vec), FormatDiffError> +where + R: io::Read, +{ + let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix); + let diff_pattern = Regex::new(&diff_pattern).unwrap(); + + let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap(); + + let file_filter = Regex::new(&format!("^{}$", file_filter))?; + + let mut current_file = None; + + let mut files = HashSet::new(); + let mut ranges = vec![]; + for line in io::BufReader::new(from).lines() { + let line = line.unwrap(); + + if let Some(captures) = diff_pattern.captures(&line) { + current_file = Some(captures.get(1).unwrap().as_str().to_owned()); + } + + let file = match current_file { + Some(ref f) => &**f, + None => continue, + }; + + // TODO(emilio): We could avoid this most of the time if needed, but + // it's not clear it's worth it. + if !file_filter.is_match(file) { + continue; + } + + let lines_captures = match lines_pattern.captures(&line) { + Some(captures) => captures, + None => continue, + }; + + let start_line = lines_captures + .get(1) + .unwrap() + .as_str() + .parse::() + .unwrap(); + let line_count = match lines_captures.get(3) { + Some(line_count) => line_count.as_str().parse::().unwrap(), + None => 1, + }; + + if line_count == 0 { + continue; + } + + let end_line = start_line + line_count - 1; + files.insert(file.to_owned()); + ranges.push(Range { + file: file.to_owned(), + range: [start_line, end_line], + }); + } + + Ok((files, ranges)) +} + +#[test] +fn scan_simple_git_diff() { + const DIFF: &'static str = include_str!("test/bindgen.diff"); + let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); + + assert!( + files.contains("src/ir/traversal.rs"), + "Should've matched the filter" + ); + + assert!( + !files.contains("tests/headers/anon_enum.hpp"), + "Shouldn't have matched the filter" + ); + + assert_eq!( + &ranges, + &[ + Range { + file: "src/ir/item.rs".to_owned(), + range: [148, 158], + }, + Range { + file: "src/ir/item.rs".to_owned(), + range: [160, 170], + }, + Range { + file: "src/ir/traversal.rs".to_owned(), + range: [9, 16], + }, + Range { + file: "src/ir/traversal.rs".to_owned(), + range: [35, 43], + } + ] + ); +} diff --git a/rustfmt-format-diff/src/test/bindgen.diff b/rustfmt-format-diff/src/test/bindgen.diff new file mode 100644 index 00000000000..d2fd379f471 --- /dev/null +++ b/rustfmt-format-diff/src/test/bindgen.diff @@ -0,0 +1,67 @@ +diff --git a/src/ir/item.rs b/src/ir/item.rs +index 7f3afefb..90d15e96 100644 +--- a/src/ir/item.rs ++++ b/src/ir/item.rs +@@ -148,7 +148,11 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> + impl AsTemplateParam for ItemId { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + ctx.resolve_item(*self).as_template_param(ctx, &()) + } + } +@@ -156,7 +160,11 @@ impl AsTemplateParam for ItemId { + impl AsTemplateParam for Item { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + self.kind.as_template_param(ctx, self) + } + } +diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs +index 762a3e2d..b9c9dd4e 100644 +--- a/src/ir/traversal.rs ++++ b/src/ir/traversal.rs +@@ -9,6 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; + /// + /// from --> to + /// ++/// Random content to generate a diff. ++/// + /// The `from` is left implicit: it is the concrete `Trace` implementer which + /// yielded this outgoing edge. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +@@ -33,7 +35,9 @@ impl Into for Edge { + } + } + +-/// The kind of edge reference. This is useful when we wish to only consider ++/// The kind of edge reference. ++/// ++/// This is useful when we wish to only consider + /// certain kinds of edges for a particular traversal or analysis. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum EdgeKind { +diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp +index 1961fe6c..34759df3 100644 +--- a/tests/headers/anon_enum.hpp ++++ b/tests/headers/anon_enum.hpp +@@ -1,7 +1,7 @@ + struct Test { + int foo; + float bar; +- enum { T_NONE }; ++ enum { T_NONE, T_SOME }; + }; + + typedef enum { diff --git a/src/bin/rustfmt-format-diff.rs b/src/bin/rustfmt-format-diff.rs deleted file mode 100644 index c42fbb6f7cf..00000000000 --- a/src/bin/rustfmt-format-diff.rs +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Inspired by Clang's clang-format-diff: -// -// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py - -#![deny(warnings)] - -extern crate env_logger; -extern crate getopts; -#[macro_use] -extern crate log; -extern crate regex; -#[macro_use] -extern crate serde_derive; -extern crate serde_json as json; - -use std::{env, fmt, process}; -use std::collections::HashSet; -use std::error::Error; -use std::io::{self, BufRead}; - -use regex::Regex; - -/// The default pattern of files to format. -/// -/// We only want to format rust files by default. -const DEFAULT_PATTERN: &str = r".*\.rs"; - -#[derive(Debug)] -enum FormatDiffError { - IncorrectOptions(getopts::Fail), - IncorrectFilter(regex::Error), - IoError(io::Error), -} - -impl fmt::Display for FormatDiffError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt::Display::fmt(self.cause().unwrap(), f) - } -} - -impl Error for FormatDiffError { - fn description(&self) -> &str { - self.cause().unwrap().description() - } - - fn cause(&self) -> Option<&Error> { - Some(match *self { - FormatDiffError::IoError(ref e) => e, - FormatDiffError::IncorrectFilter(ref e) => e, - FormatDiffError::IncorrectOptions(ref e) => e, - }) - } -} - -impl From for FormatDiffError { - fn from(fail: getopts::Fail) -> Self { - FormatDiffError::IncorrectOptions(fail) - } -} - -impl From for FormatDiffError { - fn from(err: regex::Error) -> Self { - FormatDiffError::IncorrectFilter(err) - } -} - -impl From for FormatDiffError { - fn from(fail: io::Error) -> Self { - FormatDiffError::IoError(fail) - } -} - -fn main() { - let _ = env_logger::init(); - - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optopt( - "p", - "skip-prefix", - "skip the smallest prefix containing NUMBER slashes", - "NUMBER", - ); - opts.optopt( - "f", - "filter", - "custom pattern selecting file paths to reformat", - "PATTERN", - ); - - if let Err(e) = run(&opts) { - println!("{}", opts.usage(e.description())); - process::exit(1); - } -} - -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] -struct Range { - file: String, - range: [u32; 2], -} - -fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { - let matches = opts.parse(env::args().skip(1))?; - - if matches.opt_present("h") { - println!("{}", opts.usage("usage: ")); - return Ok(()); - } - - let filter = matches - .opt_str("f") - .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); - - let skip_prefix = matches - .opt_str("p") - .and_then(|p| p.parse::().ok()) - .unwrap_or(0); - - let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; - - run_rustfmt(&files, &ranges) -} - -fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDiffError> { - if files.is_empty() || ranges.is_empty() { - debug!("No files to format found"); - return Ok(()); - } - - let ranges_as_json = json::to_string(ranges).unwrap(); - - debug!("Files: {:?}", files); - debug!("Ranges: {:?}", ranges); - - let exit_status = process::Command::new("rustfmt") - .args(files) - .arg("--file-lines") - .arg(ranges_as_json) - .status()?; - - if !exit_status.success() { - return Err(FormatDiffError::IoError(io::Error::new( - io::ErrorKind::Other, - format!("rustfmt failed with {}", exit_status), - ))); - } - Ok(()) -} - -/// Scans a diff from `from`, and returns the set of files found, and the ranges -/// in those files. -fn scan_diff( - from: R, - skip_prefix: u32, - file_filter: &str, -) -> Result<(HashSet, Vec), FormatDiffError> -where - R: io::Read, -{ - let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix); - let diff_pattern = Regex::new(&diff_pattern).unwrap(); - - let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap(); - - let file_filter = Regex::new(&format!("^{}$", file_filter))?; - - let mut current_file = None; - - let mut files = HashSet::new(); - let mut ranges = vec![]; - for line in io::BufReader::new(from).lines() { - let line = line.unwrap(); - - if let Some(captures) = diff_pattern.captures(&line) { - current_file = Some(captures.get(1).unwrap().as_str().to_owned()); - } - - let file = match current_file { - Some(ref f) => &**f, - None => continue, - }; - - // TODO(emilio): We could avoid this most of the time if needed, but - // it's not clear it's worth it. - if !file_filter.is_match(file) { - continue; - } - - let lines_captures = match lines_pattern.captures(&line) { - Some(captures) => captures, - None => continue, - }; - - let start_line = lines_captures - .get(1) - .unwrap() - .as_str() - .parse::() - .unwrap(); - let line_count = match lines_captures.get(3) { - Some(line_count) => line_count.as_str().parse::().unwrap(), - None => 1, - }; - - if line_count == 0 { - continue; - } - - let end_line = start_line + line_count - 1; - files.insert(file.to_owned()); - ranges.push(Range { - file: file.to_owned(), - range: [start_line, end_line], - }); - } - - Ok((files, ranges)) -} - -#[test] -fn scan_simple_git_diff() { - const DIFF: &'static str = include_str!("test/bindgen.diff"); - let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); - - assert!( - files.contains("src/ir/traversal.rs"), - "Should've matched the filter" - ); - - assert!( - !files.contains("tests/headers/anon_enum.hpp"), - "Shouldn't have matched the filter" - ); - - assert_eq!( - &ranges, - &[ - Range { - file: "src/ir/item.rs".to_owned(), - range: [148, 158], - }, - Range { - file: "src/ir/item.rs".to_owned(), - range: [160, 170], - }, - Range { - file: "src/ir/traversal.rs".to_owned(), - range: [9, 16], - }, - Range { - file: "src/ir/traversal.rs".to_owned(), - range: [35, 43], - } - ] - ); -} diff --git a/src/bin/test/bindgen.diff b/src/bin/test/bindgen.diff deleted file mode 100644 index d2fd379f471..00000000000 --- a/src/bin/test/bindgen.diff +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/src/ir/item.rs b/src/ir/item.rs -index 7f3afefb..90d15e96 100644 ---- a/src/ir/item.rs -+++ b/src/ir/item.rs -@@ -148,7 +148,11 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> - impl AsTemplateParam for ItemId { - type Extra = (); - -- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { -+ fn as_template_param( -+ &self, -+ ctx: &BindgenContext, -+ _: &(), -+ ) -> Option { - ctx.resolve_item(*self).as_template_param(ctx, &()) - } - } -@@ -156,7 +160,11 @@ impl AsTemplateParam for ItemId { - impl AsTemplateParam for Item { - type Extra = (); - -- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { -+ fn as_template_param( -+ &self, -+ ctx: &BindgenContext, -+ _: &(), -+ ) -> Option { - self.kind.as_template_param(ctx, self) - } - } -diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs -index 762a3e2d..b9c9dd4e 100644 ---- a/src/ir/traversal.rs -+++ b/src/ir/traversal.rs -@@ -9,6 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; - /// - /// from --> to - /// -+/// Random content to generate a diff. -+/// - /// The `from` is left implicit: it is the concrete `Trace` implementer which - /// yielded this outgoing edge. - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -@@ -33,7 +35,9 @@ impl Into for Edge { - } - } - --/// The kind of edge reference. This is useful when we wish to only consider -+/// The kind of edge reference. -+/// -+/// This is useful when we wish to only consider - /// certain kinds of edges for a particular traversal or analysis. - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum EdgeKind { -diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp -index 1961fe6c..34759df3 100644 ---- a/tests/headers/anon_enum.hpp -+++ b/tests/headers/anon_enum.hpp -@@ -1,7 +1,7 @@ - struct Test { - int foo; - float bar; -- enum { T_NONE }; -+ enum { T_NONE, T_SOME }; - }; - - typedef enum { -- cgit 1.4.1-3-g733a5 From 9c9b31c13ba799857d58fcce7b679f18a1bfbc6a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 7 Feb 2018 22:49:56 +0900 Subject: Create git-rustfmt crate --- git-rustfmt/Cargo.toml | 19 +++++ git-rustfmt/src/main.rs | 206 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/git-rustfmt.rs | 196 --------------------------------------------- 3 files changed, 225 insertions(+), 196 deletions(-) create mode 100644 git-rustfmt/Cargo.toml create mode 100644 git-rustfmt/src/main.rs delete mode 100644 src/bin/git-rustfmt.rs (limited to 'src') diff --git a/git-rustfmt/Cargo.toml b/git-rustfmt/Cargo.toml new file mode 100644 index 00000000000..1fcd1ccc613 --- /dev/null +++ b/git-rustfmt/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "git-rustfmt" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "Run rustfmt against git diff" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +categories = ["development-tools"] + +[[bin]] +name = "git-rustfmt" + +[dependencies] +env_logger = "0.4" +getopts = "0.2" +log = "0.3" +rustfmt-config = { path = "../rustfmt-config" } +rustfmt-core = { path = "../rustfmt-core" } \ No newline at end of file diff --git a/git-rustfmt/src/main.rs b/git-rustfmt/src/main.rs new file mode 100644 index 00000000000..558efbf0c0f --- /dev/null +++ b/git-rustfmt/src/main.rs @@ -0,0 +1,206 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate rustfmt_config as config; +extern crate rustfmt_core as rustfmt; + +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::str::FromStr; + +use getopts::{Matches, Options}; + +use rustfmt::{run, Input}; + +fn prune_files(files: Vec<&str>) -> Vec<&str> { + let prefixes: Vec<_> = files + .iter() + .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) + .map(|f| &f[..f.len() - 6]) + .collect(); + + let mut pruned_prefixes = vec![]; + for p1 in prefixes { + let mut include = true; + if !p1.starts_with("src/bin/") { + for p2 in &pruned_prefixes { + if p1.starts_with(p2) { + include = false; + break; + } + } + } + if include { + pruned_prefixes.push(p1); + } + } + debug!("prefixes: {:?}", pruned_prefixes); + + files + .into_iter() + .filter(|f| { + let mut include = true; + if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { + return true; + } + for pp in &pruned_prefixes { + if f.starts_with(pp) { + include = false; + break; + } + } + include + }) + .collect() +} + +fn git_diff(commits: &str) -> String { + let mut cmd = Command::new("git"); + cmd.arg("diff"); + if commits != "0" { + cmd.arg(format!("HEAD~{}", commits)); + } + let output = cmd.output().expect("Couldn't execute `git diff`"); + String::from_utf8_lossy(&output.stdout).into_owned() +} + +fn get_files(input: &str) -> Vec<&str> { + input + .lines() + .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) + .map(|line| &line[6..]) + .collect() +} + +fn fmt_files(files: &[&str]) -> i32 { + let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) + .unwrap_or_else(|_| (config::Config::default(), None)); + + let mut exit_code = 0; + for file in files { + let summary = run(Input::File(PathBuf::from(file)), &config); + if !summary.has_no_errors() { + exit_code = 1; + } + } + exit_code +} + +fn uncommitted_files() -> Vec { + let mut cmd = Command::new("git"); + cmd.arg("ls-files"); + cmd.arg("--others"); + cmd.arg("--modified"); + cmd.arg("--exclude-standard"); + let output = cmd.output().expect("Couldn't execute Git"); + let stdout = String::from_utf8_lossy(&output.stdout); + stdout + .lines() + .filter(|s| s.ends_with(".rs")) + .map(|s| s.to_owned()) + .collect() +} + +fn check_uncommitted() { + let uncommitted = uncommitted_files(); + debug!("uncommitted files: {:?}", uncommitted); + if !uncommitted.is_empty() { + println!("Found untracked changes:"); + for f in &uncommitted { + println!(" {}", f); + } + println!("Commit your work, or run with `-u`."); + println!("Exiting."); + std::process::exit(1); + } +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("c", "check", "check only, don't format (unimplemented)"); + opts.optflag("u", "uncommitted", "format uncommitted files"); + opts +} + +struct Config { + commits: String, + uncommitted: bool, + check: bool, +} + +impl Config { + fn from_args(matches: &Matches, opts: &Options) -> Config { + // `--help` display help message and quit + if matches.opt_present("h") { + let message = format!( + "\nusage: {} [options]\n\n\ + commits: number of commits to format, default: 1", + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&message)); + std::process::exit(0); + } + + let mut config = Config { + commits: "1".to_owned(), + uncommitted: false, + check: false, + }; + + if matches.opt_present("c") { + config.check = true; + unimplemented!(); + } + + if matches.opt_present("u") { + config.uncommitted = true; + } + + if matches.free.len() > 1 { + panic!("unknown arguments, use `-h` for usage"); + } + if matches.free.len() == 1 { + let commits = matches.free[0].trim(); + if u32::from_str(commits).is_err() { + panic!("Couldn't parse number of commits"); + } + config.commits = commits.to_owned(); + } + + config + } +} + +fn main() { + let _ = env_logger::init(); + + let opts = make_opts(); + let matches = opts.parse(env::args().skip(1)) + .expect("Couldn't parse command line"); + let config = Config::from_args(&matches, &opts); + + if !config.uncommitted { + check_uncommitted(); + } + + let stdout = git_diff(&config.commits); + let files = get_files(&stdout); + debug!("files: {:?}", files); + let files = prune_files(files); + debug!("pruned files: {:?}", files); + let exit_code = fmt_files(&files); + std::process::exit(exit_code); +} diff --git a/src/bin/git-rustfmt.rs b/src/bin/git-rustfmt.rs deleted file mode 100644 index 5e7cb458649..00000000000 --- a/src/bin/git-rustfmt.rs +++ /dev/null @@ -1,196 +0,0 @@ -extern crate env_logger; -extern crate getopts; -#[macro_use] -extern crate log; -extern crate rustfmt_nightly as rustfmt; - -use std::env; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::str::FromStr; - -use getopts::{Matches, Options}; - -use rustfmt::{run, Input}; -use rustfmt::config; - -fn prune_files(files: Vec<&str>) -> Vec<&str> { - let prefixes: Vec<_> = files - .iter() - .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) - .map(|f| &f[..f.len() - 6]) - .collect(); - - let mut pruned_prefixes = vec![]; - for p1 in prefixes { - let mut include = true; - if !p1.starts_with("src/bin/") { - for p2 in &pruned_prefixes { - if p1.starts_with(p2) { - include = false; - break; - } - } - } - if include { - pruned_prefixes.push(p1); - } - } - debug!("prefixes: {:?}", pruned_prefixes); - - files - .into_iter() - .filter(|f| { - let mut include = true; - if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { - return true; - } - for pp in &pruned_prefixes { - if f.starts_with(pp) { - include = false; - break; - } - } - include - }) - .collect() -} - -fn git_diff(commits: &str) -> String { - let mut cmd = Command::new("git"); - cmd.arg("diff"); - if commits != "0" { - cmd.arg(format!("HEAD~{}", commits)); - } - let output = cmd.output().expect("Couldn't execute `git diff`"); - String::from_utf8_lossy(&output.stdout).into_owned() -} - -fn get_files(input: &str) -> Vec<&str> { - input - .lines() - .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) - .map(|line| &line[6..]) - .collect() -} - -fn fmt_files(files: &[&str]) -> i32 { - let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) - .unwrap_or_else(|_| (config::Config::default(), None)); - - let mut exit_code = 0; - for file in files { - let summary = run(Input::File(PathBuf::from(file)), &config); - if !summary.has_no_errors() { - exit_code = 1; - } - } - exit_code -} - -fn uncommitted_files() -> Vec { - let mut cmd = Command::new("git"); - cmd.arg("ls-files"); - cmd.arg("--others"); - cmd.arg("--modified"); - cmd.arg("--exclude-standard"); - let output = cmd.output().expect("Couldn't execute Git"); - let stdout = String::from_utf8_lossy(&output.stdout); - stdout - .lines() - .filter(|s| s.ends_with(".rs")) - .map(|s| s.to_owned()) - .collect() -} - -fn check_uncommitted() { - let uncommitted = uncommitted_files(); - debug!("uncommitted files: {:?}", uncommitted); - if !uncommitted.is_empty() { - println!("Found untracked changes:"); - for f in &uncommitted { - println!(" {}", f); - } - println!("Commit your work, or run with `-u`."); - println!("Exiting."); - std::process::exit(1); - } -} - -fn make_opts() -> Options { - let mut opts = Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("c", "check", "check only, don't format (unimplemented)"); - opts.optflag("u", "uncommitted", "format uncommitted files"); - opts -} - -struct Config { - commits: String, - uncommitted: bool, - check: bool, -} - -impl Config { - fn from_args(matches: &Matches, opts: &Options) -> Config { - // `--help` display help message and quit - if matches.opt_present("h") { - let message = format!( - "\nusage: {} [options]\n\n\ - commits: number of commits to format, default: 1", - env::args_os().next().unwrap().to_string_lossy() - ); - println!("{}", opts.usage(&message)); - std::process::exit(0); - } - - let mut config = Config { - commits: "1".to_owned(), - uncommitted: false, - check: false, - }; - - if matches.opt_present("c") { - config.check = true; - unimplemented!(); - } - - if matches.opt_present("u") { - config.uncommitted = true; - } - - if matches.free.len() > 1 { - panic!("unknown arguments, use `-h` for usage"); - } - if matches.free.len() == 1 { - let commits = matches.free[0].trim(); - if u32::from_str(commits).is_err() { - panic!("Couldn't parse number of commits"); - } - config.commits = commits.to_owned(); - } - - config - } -} - -fn main() { - let _ = env_logger::init(); - - let opts = make_opts(); - let matches = opts.parse(env::args().skip(1)) - .expect("Couldn't parse command line"); - let config = Config::from_args(&matches, &opts); - - if !config.uncommitted { - check_uncommitted(); - } - - let stdout = git_diff(&config.commits); - let files = get_files(&stdout); - debug!("files: {:?}", files); - let files = prune_files(files); - debug!("pruned files: {:?}", files); - let exit_code = fmt_files(&files); - std::process::exit(exit_code); -} -- cgit 1.4.1-3-g733a5 From 39301ae5f21b6d6c8155d3b46ec6bf21f92de864 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 2 Mar 2018 14:28:34 +1300 Subject: Go back to a non-workspace structure Kinda reverts https://github.com/rust-lang-nursery/rustfmt/pull/2419 --- Cargo.lock | 147 +- Cargo.toml | 71 +- cargo-fmt/src/main.rs | 373 ---- git-rustfmt/src/main.rs | 206 -- rustfmt-bin/src/main.rs | 480 ----- rustfmt-config/src/config_type.rs | 398 ---- rustfmt-config/src/file_lines.rs | 324 ---- rustfmt-config/src/lib.rs | 252 --- rustfmt-config/src/lists.rs | 105 - rustfmt-config/src/options.rs | 246 --- rustfmt-config/src/summary.rs | 144 -- rustfmt-core/src/attr.rs | 323 ---- rustfmt-core/src/chains.rs | 501 ----- rustfmt-core/src/checkstyle.rs | 85 - rustfmt-core/src/closures.rs | 392 ---- rustfmt-core/src/codemap.rs | 88 - rustfmt-core/src/comment.rs | 1277 ------------- rustfmt-core/src/expr.rs | 2975 ----------------------------- rustfmt-core/src/filemap.rs | 185 -- rustfmt-core/src/imports.rs | 399 ---- rustfmt-core/src/issues.rs | 327 ---- rustfmt-core/src/items.rs | 2891 ---------------------------- rustfmt-core/src/lib.rs | 937 --------- rustfmt-core/src/lists.rs | 771 -------- rustfmt-core/src/macros.rs | 979 ---------- rustfmt-core/src/missed_spans.rs | 312 --- rustfmt-core/src/modules.rs | 86 - rustfmt-core/src/patterns.rs | 380 ---- rustfmt-core/src/reorder.rs | 331 ---- rustfmt-core/src/rewrite.rs | 54 - rustfmt-core/src/rustfmt_diff.rs | 303 --- rustfmt-core/src/shape.rs | 364 ---- rustfmt-core/src/spanned.rs | 192 -- rustfmt-core/src/string.rs | 162 -- rustfmt-core/src/types.rs | 820 -------- rustfmt-core/src/utils.rs | 405 ---- rustfmt-core/src/vertical.rs | 290 --- rustfmt-core/src/visitor.rs | 700 ------- rustfmt-format-diff/src/main.rs | 267 --- rustfmt-format-diff/src/test/bindgen.diff | 67 - src/attr.rs | 323 ++++ src/bin/main.rs | 479 +++++ src/cargo-fmt/main.rs | 373 ++++ src/chains.rs | 501 +++++ src/checkstyle.rs | 85 + src/closures.rs | 392 ++++ src/codemap.rs | 88 + src/comment.rs | 1277 +++++++++++++ src/config/config_type.rs | 398 ++++ src/config/file_lines.rs | 324 ++++ src/config/lists.rs | 105 + src/config/mod.rs | 245 +++ src/config/options.rs | 246 +++ src/config/summary.rs | 144 ++ src/expr.rs | 2975 +++++++++++++++++++++++++++++ src/filemap.rs | 185 ++ src/format-diff/main.rs | 267 +++ src/format-diff/test/bindgen.diff | 67 + src/git-rustfmt/main.rs | 205 ++ src/imports.rs | 399 ++++ src/issues.rs | 327 ++++ src/items.rs | 2891 ++++++++++++++++++++++++++++ src/lib.rs | 943 +++++++++ src/lists.rs | 771 ++++++++ src/macros.rs | 979 ++++++++++ src/missed_spans.rs | 312 +++ src/modules.rs | 86 + src/patterns.rs | 380 ++++ src/reorder.rs | 331 ++++ src/rewrite.rs | 54 + src/rustfmt_diff.rs | 303 +++ src/shape.rs | 364 ++++ src/spanned.rs | 192 ++ src/string.rs | 162 ++ src/types.rs | 820 ++++++++ src/utils.rs | 405 ++++ src/vertical.rs | 290 +++ src/visitor.rs | 700 +++++++ 78 files changed, 19458 insertions(+), 19539 deletions(-) delete mode 100644 cargo-fmt/src/main.rs delete mode 100644 git-rustfmt/src/main.rs delete mode 100644 rustfmt-bin/src/main.rs delete mode 100644 rustfmt-config/src/config_type.rs delete mode 100644 rustfmt-config/src/file_lines.rs delete mode 100644 rustfmt-config/src/lib.rs delete mode 100644 rustfmt-config/src/lists.rs delete mode 100644 rustfmt-config/src/options.rs delete mode 100644 rustfmt-config/src/summary.rs delete mode 100644 rustfmt-core/src/attr.rs delete mode 100644 rustfmt-core/src/chains.rs delete mode 100644 rustfmt-core/src/checkstyle.rs delete mode 100644 rustfmt-core/src/closures.rs delete mode 100644 rustfmt-core/src/codemap.rs delete mode 100644 rustfmt-core/src/comment.rs delete mode 100644 rustfmt-core/src/expr.rs delete mode 100644 rustfmt-core/src/filemap.rs delete mode 100644 rustfmt-core/src/imports.rs delete mode 100644 rustfmt-core/src/issues.rs delete mode 100644 rustfmt-core/src/items.rs delete mode 100644 rustfmt-core/src/lib.rs delete mode 100644 rustfmt-core/src/lists.rs delete mode 100644 rustfmt-core/src/macros.rs delete mode 100644 rustfmt-core/src/missed_spans.rs delete mode 100644 rustfmt-core/src/modules.rs delete mode 100644 rustfmt-core/src/patterns.rs delete mode 100644 rustfmt-core/src/reorder.rs delete mode 100644 rustfmt-core/src/rewrite.rs delete mode 100644 rustfmt-core/src/rustfmt_diff.rs delete mode 100644 rustfmt-core/src/shape.rs delete mode 100644 rustfmt-core/src/spanned.rs delete mode 100644 rustfmt-core/src/string.rs delete mode 100644 rustfmt-core/src/types.rs delete mode 100644 rustfmt-core/src/utils.rs delete mode 100644 rustfmt-core/src/vertical.rs delete mode 100644 rustfmt-core/src/visitor.rs delete mode 100644 rustfmt-format-diff/src/main.rs delete mode 100644 rustfmt-format-diff/src/test/bindgen.diff create mode 100644 src/attr.rs create mode 100644 src/bin/main.rs create mode 100644 src/cargo-fmt/main.rs create mode 100644 src/chains.rs create mode 100644 src/checkstyle.rs create mode 100644 src/closures.rs create mode 100644 src/codemap.rs create mode 100644 src/comment.rs create mode 100644 src/config/config_type.rs create mode 100644 src/config/file_lines.rs create mode 100644 src/config/lists.rs create mode 100644 src/config/mod.rs create mode 100644 src/config/options.rs create mode 100644 src/config/summary.rs create mode 100644 src/expr.rs create mode 100644 src/filemap.rs create mode 100644 src/format-diff/main.rs create mode 100644 src/format-diff/test/bindgen.diff create mode 100644 src/git-rustfmt/main.rs create mode 100644 src/imports.rs create mode 100644 src/issues.rs create mode 100644 src/items.rs create mode 100644 src/lib.rs create mode 100644 src/lists.rs create mode 100644 src/macros.rs create mode 100644 src/missed_spans.rs create mode 100644 src/modules.rs create mode 100644 src/patterns.rs create mode 100644 src/reorder.rs create mode 100644 src/rewrite.rs create mode 100644 src/rustfmt_diff.rs create mode 100644 src/shape.rs create mode 100644 src/spanned.rs create mode 100644 src/string.rs create mode 100644 src/types.rs create mode 100644 src/utils.rs create mode 100644 src/vertical.rs create mode 100644 src/visitor.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 48768228d19..70f4ac551da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,16 +6,6 @@ dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "atty" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "backtrace" version = "0.3.5" @@ -42,15 +32,6 @@ name = "bitflags" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cargo-fmt" -version = "0.4.0" -dependencies = [ - "cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cargo_metadata" version = "0.4.1" @@ -101,18 +82,6 @@ dependencies = [ "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "env_logger" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "error-chain" version = "0.11.0" @@ -140,25 +109,6 @@ name = "getopts" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "git-rustfmt" -version = "0.4.0" -dependencies = [ - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-config 0.4.0", - "rustfmt-core 0.4.0", -] - -[[package]] -name = "humantime" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.3.4" @@ -240,11 +190,6 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "quick-error" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "quote" version = "0.3.15" @@ -260,19 +205,6 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "redox_syscall" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "0.2.6" @@ -362,32 +294,14 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rustfmt-bin" -version = "0.4.0" -dependencies = [ - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-config 0.4.0", - "rustfmt-core 0.4.0", -] - -[[package]] -name = "rustfmt-config" -version = "0.4.0" -dependencies = [ - "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustfmt-core" +name = "rustfmt-nightly" version = "0.4.0" dependencies = [ + "cargo_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -395,23 +309,13 @@ dependencies = [ "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-config 0.4.0", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustfmt-format-diff" -version = "0.4.0" -dependencies = [ - "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -500,24 +404,6 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "termcolor" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.5" @@ -597,17 +483,8 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "wincolor" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" -"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" @@ -618,12 +495,10 @@ dependencies = [ "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3cc21490995c841d68e00276eba02071ebb269ec24011d5728bd00eabd39e31" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" @@ -635,11 +510,8 @@ dependencies = [ "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" -"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524" @@ -660,8 +532,6 @@ dependencies = [ "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" -"checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" @@ -675,4 +545,3 @@ dependencies = [ "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" diff --git a/Cargo.toml b/Cargo.toml index 63d3c534221..0d796533dc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,62 @@ -[workspace] -members = [ - "cargo-fmt", - "git-rustfmt", - "rustfmt-bin", - "rustfmt-config", - "rustfmt-core", - "rustfmt-format-diff", -] +[package] + +name = "rustfmt-nightly" +version = "0.4.0" +authors = ["Nicholas Cameron ", "The Rustfmt developers"] +description = "Tool to find and fix Rust formatting issues" +repository = "https://github.com/rust-lang-nursery/rustfmt" +readme = "README.md" +license = "Apache-2.0/MIT" +build = "build.rs" +categories = ["development-tools"] + +[lib] +doctest = false + +[[bin]] +name = "rustfmt" +path = "src/bin/main.rs" + +[[bin]] +name = "cargo-fmt" +path = "src/cargo-fmt/main.rs" + +[[bin]] +name = "rustfmt-format-diff" +path = "src/format-diff/main.rs" + +[[bin]] +name = "git-rustfmt" +path = "src/git-rustfmt/main.rs" + +[features] +default = ["cargo-fmt", "rustfmt-format-diff"] +cargo-fmt = [] +rustfmt-format-diff = [] + +[dependencies] +toml = "0.4" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +unicode-segmentation = "1.0.0" +regex = "0.2" +term = "0.4" +diff = "0.1" +log = "0.3" +env_logger = "0.4" +getopts = "0.2" +derive-new = "0.5" +cargo_metadata = "0.4" +rustc-ap-syntax = "29.0.0" +rustc-ap-rustc_errors = "29.0.0" + +[dev-dependencies] +lazy_static = "1.0.0" + +[target.'cfg(unix)'.dependencies] +libc = "0.2.11" + +[target.'cfg(windows)'.dependencies] +kernel32-sys = "0.2.2" +winapi = "0.2.7" diff --git a/cargo-fmt/src/main.rs b/cargo-fmt/src/main.rs deleted file mode 100644 index 1acad99688a..00000000000 --- a/cargo-fmt/src/main.rs +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) - -#![cfg(not(test))] -#![deny(warnings)] - -extern crate cargo_metadata; -extern crate getopts; -extern crate serde_json as json; - -use std::collections::HashSet; -use std::env; -use std::fs; -use std::hash::{Hash, Hasher}; -use std::io::{self, Write}; -use std::iter::FromIterator; -use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus}; -use std::str; - -use getopts::{Matches, Options}; - -fn main() { - let exit_status = execute(); - std::io::stdout().flush().unwrap(); - std::process::exit(exit_status); -} - -const SUCCESS: i32 = 0; -const FAILURE: i32 = 1; - -fn execute() -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("q", "quiet", "no output printed to stdout"); - opts.optflag("v", "verbose", "use verbose output"); - opts.optmulti( - "p", - "package", - "specify package to format (only usable in workspaces)", - "", - ); - opts.optflag("", "version", "print rustfmt version and exit"); - opts.optflag("", "all", "format all packages (only usable in workspaces)"); - - // If there is any invalid argument passed to `cargo fmt`, return without formatting. - let mut is_package_arg = false; - for arg in env::args().skip(2).take_while(|a| a != "--") { - if arg.starts_with('-') { - is_package_arg = arg.starts_with("--package"); - } else if !is_package_arg { - print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); - return FAILURE; - } else { - is_package_arg = false; - } - } - - let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { - Ok(m) => m, - Err(e) => { - print_usage_to_stderr(&opts, &e.to_string()); - return FAILURE; - } - }; - - let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { - (false, false) => Verbosity::Normal, - (false, true) => Verbosity::Quiet, - (true, false) => Verbosity::Verbose, - (true, true) => { - print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); - return FAILURE; - } - }; - - if matches.opt_present("h") { - print_usage_to_stdout(&opts, ""); - return SUCCESS; - } - - if matches.opt_present("version") { - return handle_command_status(get_version(verbosity), &opts); - } - - let strategy = CargoFmtStrategy::from_matches(&matches); - handle_command_status(format_crate(verbosity, &strategy), &opts) -} - -macro_rules! print_usage { - ($print: ident, $opts: ident, $reason: expr) => {{ - let msg = format!("{}\nusage: cargo fmt [options]", $reason); - $print!( - "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ - Arguments after `--` are passed to rustfmt.", - $opts.usage(&msg) - ); - }}; -} - -fn print_usage_to_stdout(opts: &Options, reason: &str) { - print_usage!(println, opts, reason); -} - -fn print_usage_to_stderr(opts: &Options, reason: &str) { - print_usage!(eprintln, opts, reason); -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Verbosity { - Verbose, - Normal, - Quiet, -} - -fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { - match status { - Err(e) => { - print_usage_to_stderr(opts, &e.to_string()); - FAILURE - } - Ok(status) => { - if status.success() { - SUCCESS - } else { - status.code().unwrap_or(FAILURE) - } - } - } -} - -fn get_version(verbosity: Verbosity) -> Result { - run_rustfmt(&[], &[String::from("--version")], verbosity) -} - -fn format_crate( - verbosity: Verbosity, - strategy: &CargoFmtStrategy, -) -> Result { - let rustfmt_args = get_fmt_args(); - let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") { - HashSet::new() - } else { - get_targets(strategy)? - }; - - // Currently only bin and lib files get formatted - let files: Vec<_> = targets - .into_iter() - .inspect(|t| { - if verbosity == Verbosity::Verbose { - println!("[{}] {:?}", t.kind, t.path) - } - }) - .map(|t| t.path) - .collect(); - - run_rustfmt(&files, &rustfmt_args, verbosity) -} - -fn get_fmt_args() -> Vec { - // All arguments after -- are passed to rustfmt - env::args().skip_while(|a| a != "--").skip(1).collect() -} - -/// Target uses a `path` field for equality and hashing. -#[derive(Debug)] -pub struct Target { - /// A path to the main source file of the target. - path: PathBuf, - /// A kind of target (e.g. lib, bin, example, ...). - kind: String, -} - -impl Target { - pub fn from_target(target: &cargo_metadata::Target) -> Self { - let path = PathBuf::from(&target.src_path); - let canonicalized = fs::canonicalize(&path).unwrap_or(path); - - Target { - path: canonicalized, - kind: target.kind[0].clone(), - } - } -} - -impl PartialEq for Target { - fn eq(&self, other: &Target) -> bool { - self.path == other.path - } -} - -impl Eq for Target {} - -impl Hash for Target { - fn hash(&self, state: &mut H) { - self.path.hash(state); - } -} - -#[derive(Debug, PartialEq, Eq)] -pub enum CargoFmtStrategy { - /// Format every packages and dependencies. - All, - /// Format pacakges that are specified by the command line argument. - Some(Vec), - /// Format the root packages only. - Root, -} - -impl CargoFmtStrategy { - pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { - match (matches.opt_present("all"), matches.opt_present("p")) { - (false, false) => CargoFmtStrategy::Root, - (true, _) => CargoFmtStrategy::All, - (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), - } - } -} - -/// Based on the specified `CargoFmtStrategy`, returns a set of main source files. -fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { - let mut targets = HashSet::new(); - - match *strategy { - CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, - CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, - CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, - } - - if targets.is_empty() { - Err(io::Error::new( - io::ErrorKind::Other, - "Failed to find targets".to_owned(), - )) - } else { - Ok(targets) - } -} - -fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None)?; - - for package in metadata.packages { - for target in package.targets { - targets.insert(Target::from_target(&target)); - } - } - - Ok(()) -} - -fn get_targets_recursive( - manifest_path: Option<&Path>, - mut targets: &mut HashSet, - visited: &mut HashSet, -) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path)?; - - for package in metadata.packages { - add_targets(&package.targets, &mut targets); - - // Look for local dependencies. - for dependency in package.dependencies { - if dependency.source.is_some() || visited.contains(&dependency.name) { - continue; - } - - let mut manifest_path = PathBuf::from(&package.manifest_path); - - manifest_path.pop(); - manifest_path.push(&dependency.name); - manifest_path.push("Cargo.toml"); - - if manifest_path.exists() { - visited.insert(dependency.name); - get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; - } - } - } - - Ok(()) -} - -fn get_targets_with_hitlist( - hitlist: &[String], - targets: &mut HashSet, -) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None)?; - - let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); - - for package in metadata.packages { - if workspace_hitlist.remove(&package.name) { - for target in package.targets { - targets.insert(Target::from_target(&target)); - } - } - } - - if workspace_hitlist.is_empty() { - Ok(()) - } else { - let package = workspace_hitlist.iter().next().unwrap(); - Err(io::Error::new( - io::ErrorKind::InvalidInput, - format!("package `{}` is not a member of the workspace", package), - )) - } -} - -fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { - for target in target_paths { - targets.insert(Target::from_target(target)); - } -} - -fn run_rustfmt( - files: &[PathBuf], - fmt_args: &[String], - verbosity: Verbosity, -) -> Result { - let stdout = if verbosity == Verbosity::Quiet { - std::process::Stdio::null() - } else { - std::process::Stdio::inherit() - }; - - if verbosity == Verbosity::Verbose { - print!("rustfmt"); - for a in fmt_args { - print!(" {}", a); - } - for f in files { - print!(" {}", f.display()); - } - println!(); - } - - let mut command = Command::new("rustfmt") - .stdout(stdout) - .args(files) - .args(fmt_args) - .spawn() - .map_err(|e| match e.kind() { - io::ErrorKind::NotFound => io::Error::new( - io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your PATH.", - ), - _ => e, - })?; - - command.wait() -} - -fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { - match cargo_metadata::metadata(manifest_path) { - Ok(metadata) => Ok(metadata), - Err(..) => Err(io::Error::new( - io::ErrorKind::Other, - "`cargo manifest` failed.", - )), - } -} diff --git a/git-rustfmt/src/main.rs b/git-rustfmt/src/main.rs deleted file mode 100644 index 558efbf0c0f..00000000000 --- a/git-rustfmt/src/main.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate env_logger; -extern crate getopts; -#[macro_use] -extern crate log; -extern crate rustfmt_config as config; -extern crate rustfmt_core as rustfmt; - -use std::env; -use std::path::{Path, PathBuf}; -use std::process::Command; -use std::str::FromStr; - -use getopts::{Matches, Options}; - -use rustfmt::{run, Input}; - -fn prune_files(files: Vec<&str>) -> Vec<&str> { - let prefixes: Vec<_> = files - .iter() - .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) - .map(|f| &f[..f.len() - 6]) - .collect(); - - let mut pruned_prefixes = vec![]; - for p1 in prefixes { - let mut include = true; - if !p1.starts_with("src/bin/") { - for p2 in &pruned_prefixes { - if p1.starts_with(p2) { - include = false; - break; - } - } - } - if include { - pruned_prefixes.push(p1); - } - } - debug!("prefixes: {:?}", pruned_prefixes); - - files - .into_iter() - .filter(|f| { - let mut include = true; - if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { - return true; - } - for pp in &pruned_prefixes { - if f.starts_with(pp) { - include = false; - break; - } - } - include - }) - .collect() -} - -fn git_diff(commits: &str) -> String { - let mut cmd = Command::new("git"); - cmd.arg("diff"); - if commits != "0" { - cmd.arg(format!("HEAD~{}", commits)); - } - let output = cmd.output().expect("Couldn't execute `git diff`"); - String::from_utf8_lossy(&output.stdout).into_owned() -} - -fn get_files(input: &str) -> Vec<&str> { - input - .lines() - .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) - .map(|line| &line[6..]) - .collect() -} - -fn fmt_files(files: &[&str]) -> i32 { - let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) - .unwrap_or_else(|_| (config::Config::default(), None)); - - let mut exit_code = 0; - for file in files { - let summary = run(Input::File(PathBuf::from(file)), &config); - if !summary.has_no_errors() { - exit_code = 1; - } - } - exit_code -} - -fn uncommitted_files() -> Vec { - let mut cmd = Command::new("git"); - cmd.arg("ls-files"); - cmd.arg("--others"); - cmd.arg("--modified"); - cmd.arg("--exclude-standard"); - let output = cmd.output().expect("Couldn't execute Git"); - let stdout = String::from_utf8_lossy(&output.stdout); - stdout - .lines() - .filter(|s| s.ends_with(".rs")) - .map(|s| s.to_owned()) - .collect() -} - -fn check_uncommitted() { - let uncommitted = uncommitted_files(); - debug!("uncommitted files: {:?}", uncommitted); - if !uncommitted.is_empty() { - println!("Found untracked changes:"); - for f in &uncommitted { - println!(" {}", f); - } - println!("Commit your work, or run with `-u`."); - println!("Exiting."); - std::process::exit(1); - } -} - -fn make_opts() -> Options { - let mut opts = Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("c", "check", "check only, don't format (unimplemented)"); - opts.optflag("u", "uncommitted", "format uncommitted files"); - opts -} - -struct Config { - commits: String, - uncommitted: bool, - check: bool, -} - -impl Config { - fn from_args(matches: &Matches, opts: &Options) -> Config { - // `--help` display help message and quit - if matches.opt_present("h") { - let message = format!( - "\nusage: {} [options]\n\n\ - commits: number of commits to format, default: 1", - env::args_os().next().unwrap().to_string_lossy() - ); - println!("{}", opts.usage(&message)); - std::process::exit(0); - } - - let mut config = Config { - commits: "1".to_owned(), - uncommitted: false, - check: false, - }; - - if matches.opt_present("c") { - config.check = true; - unimplemented!(); - } - - if matches.opt_present("u") { - config.uncommitted = true; - } - - if matches.free.len() > 1 { - panic!("unknown arguments, use `-h` for usage"); - } - if matches.free.len() == 1 { - let commits = matches.free[0].trim(); - if u32::from_str(commits).is_err() { - panic!("Couldn't parse number of commits"); - } - config.commits = commits.to_owned(); - } - - config - } -} - -fn main() { - let _ = env_logger::init(); - - let opts = make_opts(); - let matches = opts.parse(env::args().skip(1)) - .expect("Couldn't parse command line"); - let config = Config::from_args(&matches, &opts); - - if !config.uncommitted { - check_uncommitted(); - } - - let stdout = git_diff(&config.commits); - let files = get_files(&stdout); - debug!("files: {:?}", files); - let files = prune_files(files); - debug!("pruned files: {:?}", files); - let exit_code = fmt_files(&files); - std::process::exit(exit_code); -} diff --git a/rustfmt-bin/src/main.rs b/rustfmt-bin/src/main.rs deleted file mode 100644 index a058887a696..00000000000 --- a/rustfmt-bin/src/main.rs +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![cfg(not(test))] - -extern crate env_logger; -extern crate getopts; -extern crate rustfmt_config as config; -extern crate rustfmt_core as rustfmt; - -use std::{env, error}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::path::{Path, PathBuf}; - -use getopts::{Matches, Options}; - -use config::{get_toml_path, Color, Config, WriteMode}; -use config::file_lines::FileLines; -use rustfmt::{run, FileName, Input, Summary}; - -use std::str::FromStr; - -type FmtError = Box; -type FmtResult = std::result::Result; - -/// Rustfmt operations. -enum Operation { - /// Format files and their child modules. - Format { - files: Vec, - config_path: Option, - minimal_config_path: Option, - }, - /// Print the help message. - Help, - // Print version information - Version, - /// Print detailed configuration help. - ConfigHelp, - /// Output default config to a file, or stdout if None - ConfigOutputDefault { - path: Option, - }, - /// No file specified, read from stdin - Stdin { - input: String, - config_path: Option, - }, -} - -/// Parsed command line options. -#[derive(Clone, Debug, Default)] -struct CliOptions { - skip_children: bool, - verbose: bool, - write_mode: Option, - color: Option, - file_lines: FileLines, // Default is all lines in all files. - unstable_features: bool, - error_on_unformatted: bool, -} - -impl CliOptions { - fn from_matches(matches: &Matches) -> FmtResult { - let mut options = CliOptions::default(); - options.skip_children = matches.opt_present("skip-children"); - options.verbose = matches.opt_present("verbose"); - let unstable_features = matches.opt_present("unstable-features"); - let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(false); - if unstable_features && !rust_nightly { - return Err(FmtError::from( - "Unstable features are only available on Nightly channel", - )); - } else { - options.unstable_features = unstable_features; - } - - if let Some(ref write_mode) = matches.opt_str("write-mode") { - if let Ok(write_mode) = WriteMode::from_str(write_mode) { - options.write_mode = Some(write_mode); - } else { - return Err(FmtError::from(format!( - "Invalid write-mode: {}", - write_mode - ))); - } - } - - if let Some(ref color) = matches.opt_str("color") { - match Color::from_str(color) { - Ok(color) => options.color = Some(color), - _ => return Err(FmtError::from(format!("Invalid color: {}", color))), - } - } - - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse()?; - } - - if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = true; - } - - Ok(options) - } - - fn apply_to(self, config: &mut Config) { - config.set().skip_children(self.skip_children); - config.set().verbose(self.verbose); - config.set().file_lines(self.file_lines); - config.set().unstable_features(self.unstable_features); - config.set().error_on_unformatted(self.error_on_unformatted); - if let Some(write_mode) = self.write_mode { - config.set().write_mode(write_mode); - } - if let Some(color) = self.color { - config.set().color(color); - } - } -} - -/// read the given config file path recursively if present else read the project file path -fn match_cli_path_or_file( - config_path: Option, - input_file: &Path, -) -> FmtResult<(Config, Option)> { - if let Some(config_file) = config_path { - let toml = Config::from_toml_path(config_file.as_ref())?; - return Ok((toml, Some(config_file))); - } - Config::from_resolved_toml_path(input_file).map_err(FmtError::from) -} - -fn make_opts() -> Options { - let mut opts = Options::new(); - - // Sorted in alphabetical order. - opts.optopt( - "", - "color", - "Use colored output (if supported)", - "[always|never|auto]", - ); - opts.optflag( - "", - "config-help", - "Show details of rustfmt configuration options", - ); - opts.optopt( - "", - "config-path", - "Recursively searches the given path for the rustfmt.toml config file. If not \ - found reverts to the input file path", - "[Path for the configuration file]", - ); - opts.optopt( - "", - "dump-default-config", - "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", - "PATH", - ); - opts.optopt( - "", - "dump-minimal-config", - "Dumps configuration options that were checked during formatting to a file.", - "PATH", - ); - opts.optflag( - "", - "error-on-unformatted", - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces", - ); - opts.optopt( - "", - "file-lines", - "Format specified line ranges. See README for more detail on the JSON format.", - "JSON", - ); - opts.optflag("h", "help", "Show this message"); - opts.optflag("", "skip-children", "Don't reformat child modules"); - opts.optflag( - "", - "unstable-features", - "Enables unstable features. Only available on nightly channel", - ); - opts.optflag("v", "verbose", "Print verbose output"); - opts.optflag("V", "version", "Show version information"); - opts.optopt( - "", - "write-mode", - "How to write output (not usable when piping from stdin)", - "[replace|overwrite|display|plain|diff|coverage|checkstyle]", - ); - - opts -} - -fn execute(opts: &Options) -> FmtResult { - let matches = opts.parse(env::args().skip(1))?; - - match determine_operation(&matches)? { - Operation::Help => { - print_usage_to_stdout(opts, ""); - Summary::print_exit_codes(); - Ok(Summary::default()) - } - Operation::Version => { - print_version(); - Ok(Summary::default()) - } - Operation::ConfigHelp => { - Config::print_docs(); - Ok(Summary::default()) - } - Operation::ConfigOutputDefault { path } => { - let toml = Config::default().all_options().to_toml()?; - if let Some(path) = path { - let mut file = File::create(path)?; - file.write_all(toml.as_bytes())?; - } else { - io::stdout().write_all(toml.as_bytes())?; - } - Ok(Summary::default()) - } - Operation::Stdin { input, config_path } => { - // try to read config from local directory - let (mut config, _) = - match_cli_path_or_file(config_path, &env::current_dir().unwrap())?; - - // write_mode is always Plain for Stdin. - config.set().write_mode(WriteMode::Plain); - - // parse file_lines - if let Some(ref file_lines) = matches.opt_str("file-lines") { - config.set().file_lines(file_lines.parse()?); - for f in config.file_lines().files() { - match *f { - FileName::Custom(ref f) if f == "stdin" => {} - _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), - } - } - } - - let mut error_summary = Summary::default(); - if config.version_meets_requirement(&mut error_summary) { - error_summary.add(run(Input::Text(input), &config)); - } - - Ok(error_summary) - } - Operation::Format { - files, - config_path, - minimal_config_path, - } => { - let options = CliOptions::from_matches(&matches)?; - - for f in options.file_lines.files() { - match *f { - FileName::Real(ref f) if files.contains(f) => {} - FileName::Real(_) => { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f) - } - _ => eprintln!("Warning: Not a file '{}'", f), - } - } - - let mut config = Config::default(); - // Load the config path file if provided - if let Some(config_file) = config_path.as_ref() { - config = Config::from_toml_path(config_file.as_ref())?; - }; - - if options.verbose { - if let Some(path) = config_path.as_ref() { - println!("Using rustfmt config file {}", path.display()); - } - } - - let mut error_summary = Summary::default(); - for file in files { - if !file.exists() { - eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); - error_summary.add_operational_error(); - } else if file.is_dir() { - eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); - error_summary.add_operational_error(); - } else { - // Check the file directory if the config-path could not be read or not provided - if config_path.is_none() { - let (config_tmp, path_tmp) = - Config::from_resolved_toml_path(file.parent().unwrap())?; - if options.verbose { - if let Some(path) = path_tmp.as_ref() { - println!( - "Using rustfmt config file {} for {}", - path.display(), - file.display() - ); - } - } - config = config_tmp; - } - - if !config.version_meets_requirement(&mut error_summary) { - break; - } - - options.clone().apply_to(&mut config); - error_summary.add(run(Input::File(file), &config)); - } - } - - // If we were given a path via dump-minimal-config, output any options - // that were used during formatting as TOML. - if let Some(path) = minimal_config_path { - let mut file = File::create(path)?; - let toml = config.used_options().to_toml()?; - file.write_all(toml.as_bytes())?; - } - - Ok(error_summary) - } - } -} - -fn main() { - let _ = env_logger::init(); - - let opts = make_opts(); - - let exit_code = match execute(&opts) { - Ok(summary) => { - if summary.has_operational_errors() { - 1 - } else if summary.has_parsing_errors() { - 2 - } else if summary.has_formatting_errors() { - 3 - } else if summary.has_diff { - // should only happen in diff mode - 4 - } else { - assert!(summary.has_no_errors()); - 0 - } - } - Err(e) => { - eprintln!("{}", e.to_string()); - 1 - } - }; - // Make sure standard output is flushed before we exit. - std::io::stdout().flush().unwrap(); - - // Exit with given exit code. - // - // NOTE: This immediately terminates the process without doing any cleanup, - // so make sure to finish all necessary cleanup before this is called. - std::process::exit(exit_code); -} - -fn print_usage_to_stdout(opts: &Options, reason: &str) { - let sep = if reason.is_empty() { - String::new() - } else { - format!("{}\n\n", reason) - }; - let msg = format!( - "{}Format Rust code\n\nusage: {} [options] ...", - sep, - env::args_os().next().unwrap().to_string_lossy() - ); - println!("{}", opts.usage(&msg)); -} - -fn print_version() { - let version_info = format!( - "{}{}{}", - option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), - "-", - include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) - ); - - println!("rustfmt {}", version_info); -} - -fn determine_operation(matches: &Matches) -> FmtResult { - if matches.opt_present("h") { - return Ok(Operation::Help); - } - - if matches.opt_present("config-help") { - return Ok(Operation::ConfigHelp); - } - - if matches.opt_present("dump-default-config") { - // NOTE for some reason when configured with HasArg::Maybe + Occur::Optional opt_default - // doesn't recognize `--foo bar` as a long flag with an argument but as a long flag with no - // argument *plus* a free argument. Thus we check for that case in this branch -- this is - // required for backward compatibility. - if let Some(path) = matches.free.get(0) { - return Ok(Operation::ConfigOutputDefault { - path: Some(path.clone()), - }); - } else { - return Ok(Operation::ConfigOutputDefault { - path: matches.opt_str("dump-default-config"), - }); - } - } - - if matches.opt_present("version") { - return Ok(Operation::Version); - } - - let config_path_not_found = |path: &str| -> FmtResult { - Err(FmtError::from(format!( - "Error: unable to find a config file for the given path: `{}`", - path - ))) - }; - - // Read the config_path and convert to parent dir if a file is provided. - // If a config file cannot be found from the given path, return error. - let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { - Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), - Some(ref path) if path.is_dir() => { - let config_file_path = get_toml_path(path)?; - if config_file_path.is_some() { - config_file_path - } else { - return config_path_not_found(path.to_str().unwrap()); - } - } - path => path, - }; - - // If no path is given, we won't output a minimal config. - let minimal_config_path = matches.opt_str("dump-minimal-config"); - - // if no file argument is supplied, read from stdin - if matches.free.is_empty() { - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - - return Ok(Operation::Stdin { - input: buffer, - config_path, - }); - } - - let files: Vec<_> = matches - .free - .iter() - .map(|s| { - let p = PathBuf::from(s); - // we will do comparison later, so here tries to canonicalize first - // to get the expected behavior. - p.canonicalize().unwrap_or(p) - }) - .collect(); - - Ok(Operation::Format { - files, - config_path, - minimal_config_path, - }) -} diff --git a/rustfmt-config/src/config_type.rs b/rustfmt-config/src/config_type.rs deleted file mode 100644 index bace9dba8ff..00000000000 --- a/rustfmt-config/src/config_type.rs +++ /dev/null @@ -1,398 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use file_lines::FileLines; -use options::WidthHeuristics; - -/// Trait for types that can be used in `Config`. -pub trait ConfigType: Sized { - /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a - /// pipe-separated list of variants; for other types it returns "". - fn doc_hint() -> String; -} - -impl ConfigType for bool { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for usize { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for isize { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for String { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for FileLines { - fn doc_hint() -> String { - String::from("") - } -} - -impl ConfigType for WidthHeuristics { - fn doc_hint() -> String { - String::new() - } -} - -/// Check if we're in a nightly build. -/// -/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap -/// to "stable", "beta", or "nightly" depending on what toolchain is being built. -/// If we are being built as part of the stable or beta toolchains, we want -/// to disable unstable configuration options. -/// -/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), -/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the -/// nightly compiler when installed from crates.io, default to nightly mode. -macro_rules! is_nightly_channel { - () => { - option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(true) - }; -} - -macro_rules! create_config { - ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( - use std::collections::HashSet; - - #[derive(Clone)] - pub struct Config { - // For each config item, we store a bool indicating whether it has - // been accessed and the value, and a bool whether the option was - // manually initialised, or taken from the default, - $($i: (Cell, bool, $ty, bool)),+ - } - - // Just like the Config struct but with each property wrapped - // as Option. This is used to parse a rustfmt.toml that doesn't - // specify all properties of `Config`. - // We first parse into `PartialConfig`, then create a default `Config` - // and overwrite the properties with corresponding values from `PartialConfig`. - #[derive(Deserialize, Serialize, Clone)] - pub struct PartialConfig { - $(pub $i: Option<$ty>),+ - } - - impl PartialConfig { - pub fn to_toml(&self) -> Result { - // Non-user-facing options can't be specified in TOML - let mut cloned = self.clone(); - cloned.file_lines = None; - cloned.verbose = None; - cloned.width_heuristics = None; - - toml::to_string(&cloned) - .map_err(|e| format!("Could not output config: {}", e.to_string())) - } - } - - // Macro hygiene won't allow us to make `set_$i()` methods on Config - // for each item, so this struct is used to give the API to set values: - // `config.set().option(false)`. It's pretty ugly. Consider replacing - // with `config.set_option(false)` if we ever get a stable/usable - // `concat_idents!()`. - pub struct ConfigSetter<'a>(&'a mut Config); - - impl<'a> ConfigSetter<'a> { - $( - pub fn $i(&mut self, value: $ty) { - (self.0).$i.2 = value; - if stringify!($i) == "use_small_heuristics" { - self.0.set_heuristics(); - } - } - )+ - } - - // Query each option, returns true if the user set the option, false if - // a default was used. - pub struct ConfigWasSet<'a>(&'a Config); - - impl<'a> ConfigWasSet<'a> { - $( - pub fn $i(&self) -> bool { - (self.0).$i.1 - } - )+ - } - - impl Config { - pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool { - if self.was_set().required_version() { - let version = env!("CARGO_PKG_VERSION"); - let required_version = self.required_version(); - if version != required_version { - println!( - "Error: rustfmt version ({}) doesn't match the required version ({})", - version, - required_version, - ); - error_summary.add_formatting_error(); - return false; - } - } - - true - } - - $( - pub fn $i(&self) -> $ty { - self.$i.0.set(true); - self.$i.2.clone() - } - )+ - - pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { - ConfigSetter(self) - } - - pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { - ConfigWasSet(self) - } - - fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { - $( - if let Some(val) = parsed.$i { - if self.$i.3 { - self.$i.1 = true; - self.$i.2 = val; - } else { - if is_nightly_channel!() { - self.$i.1 = true; - self.$i.2 = val; - } else { - eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ - available in nightly channel.", stringify!($i), val); - } - } - } - )+ - self.set_heuristics(); - self - } - - /// Returns a hash set initialized with every user-facing config option name. - pub fn hash_set() -> HashSet { - let mut hash_set = HashSet::new(); - $( - hash_set.insert(stringify!($i).to_owned()); - )+ - hash_set - } - - pub fn is_valid_name(name: &str) -> bool { - match name { - $( - stringify!($i) => true, - )+ - _ => false, - } - } - - pub fn from_toml(toml: &str) -> Result { - let parsed: toml::Value = - toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; - let mut err: String = String::new(); - { - let table = parsed - .as_table() - .ok_or(String::from("Parsed config was not table"))?; - for key in table.keys() { - if !Config::is_valid_name(key) { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) - } - } - } - match parsed.try_into() { - Ok(parsed_config) => { - if !err.is_empty() { - eprint!("{}", err); - } - Ok(Config::default().fill_from_parsed_config(parsed_config)) - } - Err(e) => { - err.push_str("Error: Decoding config file failed:\n"); - err.push_str(format!("{}\n", e).as_str()); - err.push_str("Please check your config file."); - Err(err) - } - } - } - - pub fn used_options(&self) -> PartialConfig { - PartialConfig { - $( - $i: if self.$i.0.get() { - Some(self.$i.2.clone()) - } else { - None - }, - )+ - } - } - - pub fn all_options(&self) -> PartialConfig { - PartialConfig { - $( - $i: Some(self.$i.2.clone()), - )+ - } - } - - pub fn override_value(&mut self, key: &str, val: &str) - { - match key { - $( - stringify!($i) => { - self.$i.2 = val.parse::<$ty>() - .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", - stringify!($i), - val, - stringify!($ty))); - } - )+ - _ => panic!("Unknown config key in override: {}", key) - } - - if key == "use_small_heuristics" { - self.set_heuristics(); - } - } - - /// Construct a `Config` from the toml file specified at `file_path`. - /// - /// This method only looks at the provided path, for a method that - /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. - /// - /// Return a `Config` if the config could be read and parsed from - /// the file, Error otherwise. - pub fn from_toml_path(file_path: &Path) -> Result { - let mut file = File::open(&file_path)?; - let mut toml = String::new(); - file.read_to_string(&mut toml)?; - Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) - } - - /// Resolve the config for input in `dir`. - /// - /// Searches for `rustfmt.toml` beginning with `dir`, and - /// recursively checking parents of `dir` if no config file is found. - /// If no config file exists in `dir` or in any parent, a - /// default `Config` will be returned (and the returned path will be empty). - /// - /// Returns the `Config` to use, and the path of the project file if there was - /// one. - pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { - - /// Try to find a project file in the given directory and its parents. - /// Returns the path of a the nearest project file if one exists, - /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { - let mut current = if dir.is_relative() { - env::current_dir()?.join(dir) - } else { - dir.to_path_buf() - }; - - current = fs::canonicalize(current)?; - - loop { - match get_toml_path(¤t) { - Ok(Some(path)) => return Ok(Some(path)), - Err(e) => return Err(e), - _ => () - } - - // If the current directory has no parent, we're done searching. - if !current.pop() { - return Ok(None); - } - } - } - - match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), - } - } - - pub fn is_hidden_option(name: &str) -> bool { - const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"]; - HIDE_OPTIONS.contains(&name) - } - - pub fn print_docs() { - use std::cmp; - let max = 0; - $( let max = cmp::max(max, stringify!($i).len()+1); )+ - let mut space_str = String::with_capacity(max); - for _ in 0..max { - space_str.push(' '); - } - println!("Configuration Options:"); - $( - let name_raw = stringify!($i); - - if !Config::is_hidden_option(name_raw) { - let mut name_out = String::with_capacity(max); - for _ in name_raw.len()..max-1 { - name_out.push(' ') - } - name_out.push_str(name_raw); - name_out.push(' '); - println!("{}{} Default: {:?}", - name_out, - <$ty>::doc_hint(), - $def); - $( - println!("{}{}", space_str, $dstring); - )+ - println!(); - } - )+ - } - - fn set_heuristics(&mut self) { - if self.use_small_heuristics.2 { - let max_width = self.max_width.2; - self.set().width_heuristics(WidthHeuristics::scaled(max_width)); - } else { - self.set().width_heuristics(WidthHeuristics::null()); - } - } - } - - // Template for the default configuration - impl Default for Config { - fn default() -> Config { - Config { - $( - $i: (Cell::new(false), false, $def, $stb), - )+ - } - } - } - ) -} diff --git a/rustfmt-config/src/file_lines.rs b/rustfmt-config/src/file_lines.rs deleted file mode 100644 index 714f33c03dc..00000000000 --- a/rustfmt-config/src/file_lines.rs +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This module contains types and functions to support formatting specific line ranges. - -use std::{cmp, iter, str}; -use std::collections::HashMap; -use std::rc::Rc; - -use serde::de::{Deserialize, Deserializer}; -use serde_json as json; - -use syntax::codemap::{FileMap, FileName}; - -/// A range of lines in a file, inclusive of both ends. -pub struct LineRange { - pub file: Rc, - pub lo: usize, - pub hi: usize, -} - -impl LineRange { - pub fn file_name(&self) -> &FileName { - &self.file.name - } -} - -/// A range that is inclusive of both ends. -#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] -pub struct Range { - lo: usize, - hi: usize, -} - -impl<'a> From<&'a LineRange> for Range { - fn from(range: &'a LineRange) -> Range { - Range::new(range.lo, range.hi) - } -} - -impl Range { - pub fn new(lo: usize, hi: usize) -> Range { - Range { lo, hi } - } - - fn is_empty(self) -> bool { - self.lo > self.hi - } - - fn contains(self, other: Range) -> bool { - if other.is_empty() { - true - } else { - !self.is_empty() && self.lo <= other.lo && self.hi >= other.hi - } - } - - fn intersects(self, other: Range) -> bool { - if self.is_empty() || other.is_empty() { - false - } else { - (self.lo <= other.hi && other.hi <= self.hi) - || (other.lo <= self.hi && self.hi <= other.hi) - } - } - - fn adjacent_to(self, other: Range) -> bool { - if self.is_empty() || other.is_empty() { - false - } else { - self.hi + 1 == other.lo || other.hi + 1 == self.lo - } - } - - /// Returns a new `Range` with lines from `self` and `other` if they were adjacent or - /// intersect; returns `None` otherwise. - fn merge(self, other: Range) -> Option { - if self.adjacent_to(other) || self.intersects(other) { - Some(Range::new( - cmp::min(self.lo, other.lo), - cmp::max(self.hi, other.hi), - )) - } else { - None - } - } -} - -/// A set of lines in files. -/// -/// It is represented as a multimap keyed on file names, with values a collection of -/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all -/// lines in all files. -#[derive(Clone, Debug, Default)] -pub struct FileLines(Option>>); - -/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, -/// and ordered by their start point. -fn normalize_ranges(ranges: &mut HashMap>) { - for ranges in ranges.values_mut() { - ranges.sort(); - let mut result = vec![]; - { - let mut iter = ranges.into_iter().peekable(); - while let Some(next) = iter.next() { - let mut next = *next; - while let Some(&&mut peek) = iter.peek() { - if let Some(merged) = next.merge(peek) { - iter.next().unwrap(); - next = merged; - } else { - break; - } - } - result.push(next) - } - } - *ranges = result; - } -} - -impl FileLines { - /// Creates a `FileLines` that contains all lines in all files. - pub fn all() -> FileLines { - FileLines(None) - } - - /// Returns true if this `FileLines` contains all lines in all files. - pub fn is_all(&self) -> bool { - self.0.is_none() - } - - pub fn from_ranges(mut ranges: HashMap>) -> FileLines { - normalize_ranges(&mut ranges); - FileLines(Some(ranges)) - } - - /// Returns an iterator over the files contained in `self`. - pub fn files(&self) -> Files { - Files(self.0.as_ref().map(|m| m.keys())) - } - - /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in - /// the designated file (if any) and returns true if `f` ever does. - fn file_range_matches(&self, file_name: &FileName, f: F) -> bool - where - F: FnMut(&Range) -> bool, - { - let map = match self.0 { - // `None` means "all lines in all files". - None => return true, - Some(ref map) => map, - }; - - match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) { - Some(ranges) => ranges.iter().any(f), - None => false, - } - } - - /// Returns true if `range` is fully contained in `self`. - pub fn contains(&self, range: &LineRange) -> bool { - self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) - } - - /// Returns true if any lines in `range` are in `self`. - pub fn intersects(&self, range: &LineRange) -> bool { - self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) - } - - /// Returns true if `line` from `file_name` is in `self`. - pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool { - self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) - } - - /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. - pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { - self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) - } -} - -/// `FileLines` files iterator. -pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec>>); - -impl<'a> iter::Iterator for Files<'a> { - type Item = &'a FileName; - - fn next(&mut self) -> Option<&'a FileName> { - self.0.as_mut().and_then(Iterator::next) - } -} - -fn canonicalize_path_string(file: &FileName) -> Option { - match *file { - FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real), - _ => Some(file.clone()), - } -} - -// This impl is needed for `Config::override_value` to work for use in tests. -impl str::FromStr for FileLines { - type Err = String; - - fn from_str(s: &str) -> Result { - let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; - let mut m = HashMap::new(); - for js in v { - let (s, r) = JsonSpan::into_tuple(js)?; - m.entry(s).or_insert_with(|| vec![]).push(r); - } - Ok(FileLines::from_ranges(m)) - } -} - -// For JSON decoding. -#[derive(Clone, Debug, Deserialize)] -struct JsonSpan { - #[serde(deserialize_with = "deserialize_filename")] - file: FileName, - range: (usize, usize), -} - -fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { - let s = String::deserialize(d)?; - if s == "stdin" { - Ok(FileName::Custom(s)) - } else { - Ok(FileName::Real(s.into())) - } -} - -impl JsonSpan { - fn into_tuple(self) -> Result<(FileName, Range), String> { - let (lo, hi) = self.range; - let canonical = canonicalize_path_string(&self.file) - .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; - Ok((canonical, Range::new(lo, hi))) - } -} - -// This impl is needed for inclusion in the `Config` struct. We don't have a toml representation -// for `FileLines`, so it will just panic instead. -impl<'de> ::serde::de::Deserialize<'de> for FileLines { - fn deserialize(_: D) -> Result - where - D: ::serde::de::Deserializer<'de>, - { - panic!( - "FileLines cannot be deserialized from a project rustfmt.toml file: please \ - specify it via the `--file-lines` option instead" - ); - } -} - -// We also want to avoid attempting to serialize a FileLines to toml. The -// `Config` struct should ensure this impl is never reached. -impl ::serde::ser::Serialize for FileLines { - fn serialize(&self, _: S) -> Result - where - S: ::serde::ser::Serializer, - { - unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); - } -} - -#[cfg(test)] -mod test { - use super::Range; - - #[test] - fn test_range_intersects() { - assert!(Range::new(1, 2).intersects(Range::new(1, 1))); - assert!(Range::new(1, 2).intersects(Range::new(2, 2))); - assert!(!Range::new(1, 2).intersects(Range::new(0, 0))); - assert!(!Range::new(1, 2).intersects(Range::new(3, 10))); - assert!(!Range::new(1, 3).intersects(Range::new(5, 5))); - } - - #[test] - fn test_range_adjacent_to() { - assert!(!Range::new(1, 2).adjacent_to(Range::new(1, 1))); - assert!(!Range::new(1, 2).adjacent_to(Range::new(2, 2))); - assert!(Range::new(1, 2).adjacent_to(Range::new(0, 0))); - assert!(Range::new(1, 2).adjacent_to(Range::new(3, 10))); - assert!(!Range::new(1, 3).adjacent_to(Range::new(5, 5))); - } - - #[test] - fn test_range_contains() { - assert!(Range::new(1, 2).contains(Range::new(1, 1))); - assert!(Range::new(1, 2).contains(Range::new(2, 2))); - assert!(!Range::new(1, 2).contains(Range::new(0, 0))); - assert!(!Range::new(1, 2).contains(Range::new(3, 10))); - } - - #[test] - fn test_range_merge() { - assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); - assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(4, 7)) - ); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(5, 7)) - ); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 5).merge(Range::new(6, 7)) - ); - assert_eq!( - Some(Range::new(3, 7)), - Range::new(3, 7).merge(Range::new(4, 5)) - ); - } -} diff --git a/rustfmt-config/src/lib.rs b/rustfmt-config/src/lib.rs deleted file mode 100644 index 0436cf2aae4..00000000000 --- a/rustfmt-config/src/lib.rs +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate serde; -#[macro_use] -extern crate serde_derive; -extern crate serde_json; -extern crate syntax; -extern crate toml; - -use std::{env, fs}; -use std::cell::Cell; -use std::default::Default; -use std::fs::File; -use std::io::{Error, ErrorKind, Read}; -use std::path::{Path, PathBuf}; - -#[macro_use] -mod config_type; -#[macro_use] -mod options; - -pub mod file_lines; -pub mod lists; -pub mod summary; - -use config_type::ConfigType; -use file_lines::FileLines; -pub use lists::*; -pub use options::*; -use summary::Summary; - -/// This macro defines configuration options used in rustfmt. Each option -/// is defined as follows: -/// -/// `name: value type, default value, is stable, description;` -create_config! { - // Fundamental stuff - max_width: usize, 100, true, "Maximum width of each line"; - hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; - tab_spaces: usize, 4, true, "Number of spaces per tab"; - newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; - use_small_heuristics: bool, true, false, "Whether to use different formatting for items and \ - expressions if they satisfy a heuristic notion of 'small'."; - - // strings and comments - format_strings: bool, false, false, "Format string literals where necessary"; - wrap_comments: bool, false, true, "Break comments to fit on the line"; - comment_width: usize, 80, false, - "Maximum length of comments. No effect unless wrap_comments = true"; - normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; - - // Single line expressions and items. - empty_item_single_line: bool, true, false, - "Put empty-body functions and impls on a single line"; - struct_lit_single_line: bool, true, false, - "Put small struct literals on a single line"; - fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - where_single_line: bool, false, false, "To force single line where layout"; - - // Imports - imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; - imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; - - // Ordering - reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; - reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; - reorder_imports: bool, false, false, "Reorder import statements alphabetically"; - reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; - reorder_imported_names: bool, true, false, - "Reorder lists of names in import statements alphabetically"; - reorder_modules: bool, false, false, "Reorder module statemtents alphabetically in group"; - - // Spaces around punctuation - binop_separator: SeparatorPlace, SeparatorPlace::Front, false, - "Where to put a binary operator when a binary expression goes multiline."; - type_punctuation_density: TypeDensity, TypeDensity::Wide, false, - "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; - space_before_colon: bool, false, false, "Leave a space before the colon"; - space_after_colon: bool, true, false, "Leave a space after the colon"; - spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; - spaces_within_parens_and_brackets: bool, false, false, - "Put spaces within non-empty parentheses or brackets"; - - // Misc. - combine_control_expr: bool, true, false, "Combine control expressions with function calls."; - struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ - threshold."; - remove_blank_lines_at_start_or_end_of_block: bool, true, false, - "Remove blank lines at start or end of a block"; - match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ - the same line with the pattern of arms"; - force_multiline_blocks: bool, false, false, - "Force multiline closure bodies and match arms to be wrapped in a block"; - fn_args_density: Density, Density::Tall, false, "Argument density in functions"; - brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; - control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, - "Brace style for control flow constructs"; - trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, - "How to handle trailing commas for lists"; - trailing_semicolon: bool, true, false, - "Add trailing semicolon after break, continue and return"; - match_block_trailing_comma: bool, false, false, - "Put a trailing comma after a block based match arm (non-block arms are not affected)"; - blank_lines_upper_bound: usize, 1, false, - "Maximum number of blank lines which can be put between items."; - blank_lines_lower_bound: usize, 0, false, - "Minimum number of blank lines which must be put between items."; - - // Options that can change the source code beyond whitespace/blocks (somewhat linty things) - merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; - use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; - condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ - in tuple patterns"; - force_explicit_abi: bool, true, true, "Always print the abi for extern items"; - use_field_init_shorthand: bool, false, false, "Use field initialization shorthand if possible"; - - // Control options (changes the operation of rustfmt, rather than the formatting) - write_mode: WriteMode, WriteMode::Overwrite, false, - "What Write Mode to use when none is supplied: \ - Replace, Overwrite, Display, Plain, Diff, Coverage"; - color: Color, Color::Auto, false, - "What Color option to use when none is supplied: Always, Never, Auto"; - required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, - "Require a specific version of rustfmt."; - unstable_features: bool, false, true, - "Enables unstable features. Only available on nightly channel"; - disable_all_formatting: bool, false, false, "Don't reformat anything"; - skip_children: bool, false, false, "Don't reformat out of line modules"; - hide_parse_errors: bool, false, false, "Hide errors from the parser"; - error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; - error_on_unformatted: bool, false, false, - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces"; - report_todo: ReportTactic, ReportTactic::Never, false, - "Report all, none or unnumbered occurrences of TODO in source file comments"; - report_fixme: ReportTactic, ReportTactic::Never, false, - "Report all, none or unnumbered occurrences of FIXME in source file comments"; - - // Not user-facing. - verbose: bool, false, false, "Use verbose output"; - file_lines: FileLines, FileLines::all(), false, - "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ - via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; -} - -/// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` -/// -/// Return the path if a config file exists, empty if no file exists, and Error for IO errors -pub fn get_toml_path(dir: &Path) -> Result, Error> { - const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; - for config_file_name in &CONFIG_FILE_NAMES { - let config_file = dir.join(config_file_name); - match fs::metadata(&config_file) { - // Only return if it's a file to handle the unlikely situation of a directory named - // `rustfmt.toml`. - Ok(ref md) if md.is_file() => return Ok(Some(config_file)), - // Return the error if it's something other than `NotFound`; otherwise we didn't - // find the project file yet, and continue searching. - Err(e) => { - if e.kind() != ErrorKind::NotFound { - return Err(e); - } - } - _ => {} - } - } - Ok(None) -} - -#[cfg(test)] -mod test { - use super::Config; - - #[test] - fn test_config_set() { - let mut config = Config::default(); - config.set().verbose(false); - assert_eq!(config.verbose(), false); - config.set().verbose(true); - assert_eq!(config.verbose(), true); - } - - #[test] - fn test_config_used_to_toml() { - let config = Config::default(); - - let merge_derives = config.merge_derives(); - let skip_children = config.skip_children(); - - let used_options = config.used_options(); - let toml = used_options.to_toml().unwrap(); - assert_eq!( - toml, - format!( - "merge_derives = {}\nskip_children = {}\n", - merge_derives, skip_children, - ) - ); - } - - #[test] - fn test_was_set() { - let config = Config::from_toml("hard_tabs = true").unwrap(); - - assert_eq!(config.was_set().hard_tabs(), true); - assert_eq!(config.was_set().verbose(), false); - } - - // FIXME(#2183) these tests cannot be run in parallel because they use env vars - // #[test] - // fn test_as_not_nightly_channel() { - // let mut config = Config::default(); - // assert_eq!(config.was_set().unstable_features(), false); - // config.set().unstable_features(true); - // assert_eq!(config.was_set().unstable_features(), false); - // } - - // #[test] - // fn test_as_nightly_channel() { - // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - // let mut config = Config::default(); - // config.set().unstable_features(true); - // assert_eq!(config.was_set().unstable_features(), false); - // config.set().unstable_features(true); - // assert_eq!(config.unstable_features(), true); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - // } - - // #[test] - // fn test_unstable_from_toml() { - // let mut config = Config::from_toml("unstable_features = true").unwrap(); - // assert_eq!(config.was_set().unstable_features(), false); - // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); - // config = Config::from_toml("unstable_features = true").unwrap(); - // assert_eq!(config.was_set().unstable_features(), true); - // assert_eq!(config.unstable_features(), true); - // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); - // } -} diff --git a/rustfmt-config/src/lists.rs b/rustfmt-config/src/lists.rs deleted file mode 100644 index 2ddc2e59261..00000000000 --- a/rustfmt-config/src/lists.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Configuration options related to rewriting a list. - -use IndentStyle; -use config_type::ConfigType; - -/// The definitive formatting tactic for lists. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum DefinitiveListTactic { - Vertical, - Horizontal, - Mixed, - /// Special case tactic for `format!()`, `write!()` style macros. - SpecialMacro(usize), -} - -impl DefinitiveListTactic { - pub fn ends_with_newline(&self, indent_style: IndentStyle) -> bool { - match indent_style { - IndentStyle::Block => *self != DefinitiveListTactic::Horizontal, - IndentStyle::Visual => false, - } - } -} - -/// Formatting tactic for lists. This will be cast down to a -/// `DefinitiveListTactic` depending on the number and length of the items and -/// their comments. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum ListTactic { - // One item per row. - Vertical, - // All items on one row. - Horizontal, - // Try Horizontal layout, if that fails then vertical. - HorizontalVertical, - // HorizontalVertical with a soft limit of n characters. - LimitedHorizontalVertical(usize), - // Pack as many items as possible per row over (possibly) many rows. - Mixed, -} - -impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); - -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum SeparatorTactic { - Always, - Never, - Vertical, -} - -impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); - -impl SeparatorTactic { - pub fn from_bool(b: bool) -> SeparatorTactic { - if b { - SeparatorTactic::Always - } else { - SeparatorTactic::Never - } - } -} - -/// Where to put separator. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum SeparatorPlace { - Front, - Back, -} - -impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); - -impl SeparatorPlace { - pub fn is_front(&self) -> bool { - *self == SeparatorPlace::Front - } - - pub fn is_back(&self) -> bool { - *self == SeparatorPlace::Back - } - - pub fn from_tactic( - default: SeparatorPlace, - tactic: DefinitiveListTactic, - sep: &str, - ) -> SeparatorPlace { - match tactic { - DefinitiveListTactic::Vertical => default, - _ => if sep == "," { - SeparatorPlace::Back - } else { - default - }, - } - } -} diff --git a/rustfmt-config/src/options.rs b/rustfmt-config/src/options.rs deleted file mode 100644 index 6aa3db4f3df..00000000000 --- a/rustfmt-config/src/options.rs +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use config_type::ConfigType; -use lists::*; - -/// Macro for deriving implementations of Serialize/Deserialize for enums -#[macro_export] -macro_rules! impl_enum_serialize_and_deserialize { - ( $e:ident, $( $x:ident ),* ) => { - impl ::serde::ser::Serialize for $e { - fn serialize(&self, serializer: S) -> Result - where S: ::serde::ser::Serializer - { - use serde::ser::Error; - - // We don't know whether the user of the macro has given us all options. - #[allow(unreachable_patterns)] - match *self { - $( - $e::$x => serializer.serialize_str(stringify!($x)), - )* - _ => { - Err(S::Error::custom(format!("Cannot serialize {:?}", self))) - } - } - } - } - - impl<'de> ::serde::de::Deserialize<'de> for $e { - fn deserialize(d: D) -> Result - where D: ::serde::Deserializer<'de> { - use serde::de::{Error, Visitor}; - use std::marker::PhantomData; - use std::fmt; - struct StringOnly(PhantomData); - impl<'de, T> Visitor<'de> for StringOnly - where T: ::serde::Deserializer<'de> { - type Value = String; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("string") - } - fn visit_str(self, value: &str) -> Result { - Ok(String::from(value)) - } - } - let s = d.deserialize_string(StringOnly::(PhantomData))?; - $( - if stringify!($x).eq_ignore_ascii_case(&s) { - return Ok($e::$x); - } - )* - static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; - Err(D::Error::unknown_variant(&s, ALLOWED)) - } - } - - impl ::std::str::FromStr for $e { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - $( - if stringify!($x).eq_ignore_ascii_case(s) { - return Ok($e::$x); - } - )* - Err("Bad variant") - } - } - - impl ConfigType for $e { - fn doc_hint() -> String { - let mut variants = Vec::new(); - $( - variants.push(stringify!($x)); - )* - format!("[{}]", variants.join("|")) - } - } - }; -} - -macro_rules! configuration_option_enum{ - ($e:ident: $( $x:ident ),+ $(,)*) => { - #[derive(Copy, Clone, Eq, PartialEq, Debug)] - pub enum $e { - $( $x ),+ - } - - impl_enum_serialize_and_deserialize!($e, $( $x ),+); - } -} - -configuration_option_enum! { NewlineStyle: - Windows, // \r\n - Unix, // \n - Native, // \r\n in Windows, \n on other platforms -} - -configuration_option_enum! { BraceStyle: - AlwaysNextLine, - PreferSameLine, - // Prefer same line except where there is a where clause, in which case force - // the brace to the next line. - SameLineWhere, -} - -configuration_option_enum! { ControlBraceStyle: - // K&R style, Rust community default - AlwaysSameLine, - // Stroustrup style - ClosingNextLine, - // Allman style - AlwaysNextLine, -} - -configuration_option_enum! { IndentStyle: - // First line on the same line as the opening brace, all lines aligned with - // the first line. - Visual, - // First line is on a new line and all lines align with block indent. - Block, -} - -configuration_option_enum! { Density: - // Fit as much on one line as possible. - Compressed, - // Use more lines. - Tall, - // Place every item on a separate line. - Vertical, -} - -configuration_option_enum! { TypeDensity: - // No spaces around "=" and "+" - Compressed, - // Spaces around " = " and " + " - Wide, -} - -impl Density { - pub fn to_list_tactic(self) -> ListTactic { - match self { - Density::Compressed => ListTactic::Mixed, - Density::Tall => ListTactic::HorizontalVertical, - Density::Vertical => ListTactic::Vertical, - } - } -} - -configuration_option_enum! { ReportTactic: - Always, - Unnumbered, - Never, -} - -configuration_option_enum! { WriteMode: - // Backs the original file up and overwrites the original. - Replace, - // Overwrites original file without backup. - Overwrite, - // Writes the output to stdout. - Display, - // Writes the diff to stdout. - Diff, - // Displays how much of the input file was processed - Coverage, - // Unfancy stdout - Plain, - // Outputs a checkstyle XML file. - Checkstyle, - // Output the changed lines (for internal value only) - Modified, -} - -configuration_option_enum! { Color: - // Always use color, whether it is a piped or terminal output - Always, - // Never use color - Never, - // Automatically use color, if supported by terminal - Auto, -} - -#[derive(Deserialize, Serialize, Clone, Debug)] -pub struct WidthHeuristics { - // Maximum width of the args of a function call before falling back - // to vertical formatting. - pub fn_call_width: usize, - // Maximum width in the body of a struct lit before falling back to - // vertical formatting. - pub struct_lit_width: usize, - // Maximum width in the body of a struct variant before falling back - // to vertical formatting. - pub struct_variant_width: usize, - // Maximum width of an array literal before falling back to vertical - // formatting. - pub array_width: usize, - // Maximum length of a chain to fit on a single line. - pub chain_width: usize, - // Maximum line length for single line if-else expressions. A value - // of zero means always break if-else expressions. - pub single_line_if_else_max_width: usize, -} - -impl WidthHeuristics { - // Using this WidthHeuristics means we ignore heuristics. - pub fn null() -> WidthHeuristics { - WidthHeuristics { - fn_call_width: usize::max_value(), - struct_lit_width: 0, - struct_variant_width: 0, - array_width: usize::max_value(), - chain_width: usize::max_value(), - single_line_if_else_max_width: 0, - } - } - // scale the default WidthHeuristics according to max_width - pub fn scaled(max_width: usize) -> WidthHeuristics { - let mut max_width_ratio: f32 = max_width as f32 / 100.0; // 100 is the default width -> default ratio is 1 - max_width_ratio = (max_width_ratio * 10.0).round() / 10.0; // round to the closest 0.1 - WidthHeuristics { - fn_call_width: (60.0 * max_width_ratio).round() as usize, - struct_lit_width: (18.0 * max_width_ratio).round() as usize, - struct_variant_width: (35.0 * max_width_ratio).round() as usize, - array_width: (60.0 * max_width_ratio).round() as usize, - chain_width: (60.0 * max_width_ratio).round() as usize, - single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize, - } - } -} - -impl ::std::str::FromStr for WidthHeuristics { - type Err = &'static str; - - fn from_str(_: &str) -> Result { - Err("WidthHeuristics is not parsable") - } -} diff --git a/rustfmt-config/src/summary.rs b/rustfmt-config/src/summary.rs deleted file mode 100644 index b0be5678a0b..00000000000 --- a/rustfmt-config/src/summary.rs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::time::{Duration, Instant}; -use std::default::Default; - -#[must_use] -#[derive(Debug, Default, Clone, Copy)] -pub struct Summary { - // Encountered e.g. an IO error. - has_operational_errors: bool, - - // Failed to reformat code because of parsing errors. - has_parsing_errors: bool, - - // Code is valid, but it is impossible to format it properly. - has_formatting_errors: bool, - - // Formatted code differs from existing code (write-mode diff only). - pub has_diff: bool, - - // Keeps track of time spent in parsing and formatting steps. - timer: Timer, -} - -impl Summary { - pub fn mark_parse_time(&mut self) { - self.timer = self.timer.done_parsing(); - } - - pub fn mark_format_time(&mut self) { - self.timer = self.timer.done_formatting(); - } - - /// Returns the time it took to parse the source files in nanoseconds. - pub fn get_parse_time(&self) -> Option { - match self.timer { - Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { - // This should never underflow since `Instant::now()` guarantees monotonicity. - Some(parse_time.duration_since(init)) - } - Timer::Initialized(..) => None, - } - } - - /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is - /// not included. - pub fn get_format_time(&self) -> Option { - match self.timer { - Timer::DoneFormatting(_init, parse_time, format_time) => { - Some(format_time.duration_since(parse_time)) - } - Timer::DoneParsing(..) | Timer::Initialized(..) => None, - } - } - - pub fn has_operational_errors(&self) -> bool { - self.has_operational_errors - } - - pub fn has_parsing_errors(&self) -> bool { - self.has_parsing_errors - } - - pub fn has_formatting_errors(&self) -> bool { - self.has_formatting_errors - } - - pub fn add_operational_error(&mut self) { - self.has_operational_errors = true; - } - - pub fn add_parsing_error(&mut self) { - self.has_parsing_errors = true; - } - - pub fn add_formatting_error(&mut self) { - self.has_formatting_errors = true; - } - - pub fn add_diff(&mut self) { - self.has_diff = true; - } - - pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors - || self.has_diff) - } - - pub fn add(&mut self, other: Summary) { - self.has_operational_errors |= other.has_operational_errors; - self.has_formatting_errors |= other.has_formatting_errors; - self.has_parsing_errors |= other.has_parsing_errors; - self.has_diff |= other.has_diff; - } - - pub fn print_exit_codes() { - let exit_codes = r#"Exit Codes: - 0 = No errors - 1 = Encountered operational errors e.g. an IO error - 2 = Failed to reformat code because of parsing errors - 3 = Code is valid, but it is impossible to format it properly - 4 = Formatted code differs from existing code (write-mode diff only)"#; - println!("{}", exit_codes); - } -} - -#[derive(Clone, Copy, Debug)] -enum Timer { - Initialized(Instant), - DoneParsing(Instant, Instant), - DoneFormatting(Instant, Instant, Instant), -} - -impl Default for Timer { - fn default() -> Self { - Timer::Initialized(Instant::now()) - } -} - -impl Timer { - fn done_parsing(self) -> Self { - match self { - Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), - _ => panic!("Timer can only transition to DoneParsing from Initialized state"), - } - } - - fn done_formatting(self) -> Self { - match self { - Timer::DoneParsing(init_time, parse_time) => { - Timer::DoneFormatting(init_time, parse_time, Instant::now()) - } - _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), - } - } -} diff --git a/rustfmt-core/src/attr.rs b/rustfmt-core/src/attr.rs deleted file mode 100644 index 5d22bd9ffe7..00000000000 --- a/rustfmt-core/src/attr.rs +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Format attributes and meta items. - -use config::lists::*; -use syntax::ast; -use syntax::codemap::Span; - -use comment::{combine_strs_with_missing_comments, contains_comment, rewrite_doc_comment}; -use expr::rewrite_literal; -use lists::{itemize_list, write_list, ListFormatting}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use utils::{count_newlines, mk_sp}; - -use std::cmp; - -/// Returns attributes on the given statement. -pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { - match stmt.node { - ast::StmtKind::Local(ref local) => &local.attrs, - ast::StmtKind::Item(ref item) => &item.attrs, - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, - ast::StmtKind::Mac(ref mac) => &mac.2, - } -} - -/// Returns attributes that are within `outer_span`. -pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { - attrs - .iter() - .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) - .cloned() - .collect() -} - -fn is_derive(attr: &ast::Attribute) -> bool { - attr.check_name("derive") -} - -/// Returns the arguments of `#[derive(...)]`. -fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { - attr.meta_item_list().map(|meta_item_list| { - meta_item_list - .iter() - .map(|nested_meta_item| context.snippet(nested_meta_item.span)) - .collect() - }) -} - -// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. -fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option { - let mut result = String::with_capacity(128); - result.push_str("#[derive("); - // 11 = `#[derive()]` - let initial_budget = shape.width.checked_sub(11)?; - let mut budget = initial_budget; - let num = derive_args.len(); - for (i, a) in derive_args.iter().enumerate() { - // 2 = `, ` or `)]` - let width = a.len() + 2; - if width > budget { - if i > 0 { - // Remove trailing whitespace. - result.pop(); - } - result.push('\n'); - // 9 = `#[derive(` - result.push_str(&(shape.indent + 9).to_string(context.config)); - budget = initial_budget; - } else { - budget = budget.checked_sub(width).unwrap_or(0); - } - result.push_str(a); - if i != num - 1 { - result.push_str(", ") - } - } - result.push_str(")]"); - Some(result) -} - -/// Returns the first group of attributes that fills the given predicate. -/// We consider two doc comments are in different group if they are separated by normal comments. -fn take_while_with_pred<'a, P>( - context: &RewriteContext, - attrs: &'a [ast::Attribute], - pred: P, -) -> &'a [ast::Attribute] -where - P: Fn(&ast::Attribute) -> bool, -{ - let mut last_index = 0; - let mut iter = attrs.iter().enumerate().peekable(); - while let Some((i, attr)) = iter.next() { - if !pred(attr) { - break; - } - if let Some(&(_, next_attr)) = iter.peek() { - // Extract comments between two attributes. - let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); - let snippet = context.snippet(span_between_attr); - if count_newlines(snippet) >= 2 || snippet.contains('/') { - break; - } - } - last_index = i; - } - if last_index == 0 { - &[] - } else { - &attrs[..last_index + 1] - } -} - -/// Rewrite the same kind of attributes at the same time. This includes doc -/// comments and derives. -fn rewrite_first_group_attrs( - context: &RewriteContext, - attrs: &[ast::Attribute], - shape: Shape, -) -> Option<(usize, String)> { - if attrs.is_empty() { - return Some((0, String::new())); - } - // Rewrite doc comments - let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); - if !sugared_docs.is_empty() { - let snippet = sugared_docs - .iter() - .map(|a| context.snippet(a.span)) - .collect::>() - .join("\n"); - return Some(( - sugared_docs.len(), - rewrite_doc_comment(&snippet, shape, context.config)?, - )); - } - // Rewrite `#[derive(..)]`s. - if context.config.merge_derives() { - let derives = take_while_with_pred(context, attrs, is_derive); - if !derives.is_empty() { - let mut derive_args = vec![]; - for derive in derives { - derive_args.append(&mut get_derive_args(context, derive)?); - } - return Some((derives.len(), format_derive(context, &derive_args, shape)?)); - } - } - // Rewrite the first attribute. - Some((1, attrs[0].rewrite(context, shape)?)) -} - -impl Rewrite for ast::NestedMetaItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), - ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), - } - } -} - -fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { - // Look at before and after comment and see if there are any empty lines. - let comment_begin = comment.chars().position(|c| c == '/'); - let len = comment_begin.unwrap_or_else(|| comment.len()); - let mlb = count_newlines(&comment[..len]) > 1; - let mla = if comment_begin.is_none() { - mlb - } else { - let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); - let len = comment_end.unwrap(); - comment - .chars() - .rev() - .take(len) - .filter(|c| *c == '\n') - .count() > 1 - }; - (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) -} - -impl Rewrite for ast::MetaItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - Some(match self.node { - ast::MetaItemKind::Word => String::from(&*self.name.as_str()), - ast::MetaItemKind::List(ref list) => { - let name = self.name.as_str(); - // 1 = `(`, 2 = `]` and `)` - let item_shape = shape - .visual_indent(0) - .shrink_left(name.len() + 1) - .and_then(|s| s.sub_width(2))?; - let items = itemize_list( - context.snippet_provider, - list.iter(), - ")", - ",", - |nested_meta_item| nested_meta_item.span.lo(), - |nested_meta_item| nested_meta_item.span.hi(), - |nested_meta_item| nested_meta_item.rewrite(context, item_shape), - self.span.lo(), - self.span.hi(), - false, - ); - let item_vec = items.collect::>(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Mixed, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: item_shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - format!("{}({})", name, write_list(&item_vec, &fmt)?) - } - ast::MetaItemKind::NameValue(ref literal) => { - let name = self.name.as_str(); - // 3 = ` = ` - let lit_shape = shape.shrink_left(name.len() + 3)?; - // `rewrite_literal` returns `None` when `literal` exceeds max - // width. Since a literal is basically unformattable unless it - // is a string literal (and only if `format_strings` is set), - // we might be better off ignoring the fact that the attribute - // is longer than the max width and contiue on formatting. - // See #2479 for example. - let value = rewrite_literal(context, literal, lit_shape) - .unwrap_or_else(|| context.snippet(literal.span).to_owned()); - format!("{} = {}", name, value) - } - }) - } -} - -impl Rewrite for ast::Attribute { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let prefix = match self.style { - ast::AttrStyle::Inner => "#!", - ast::AttrStyle::Outer => "#", - }; - let snippet = context.snippet(self.span); - if self.is_sugared_doc { - let doc_shape = Shape { - width: cmp::min(shape.width, context.config.comment_width()) - .checked_sub(shape.indent.width()) - .unwrap_or(0), - ..shape - }; - rewrite_doc_comment(snippet, doc_shape, context.config) - } else { - if contains_comment(snippet) { - return Some(snippet.to_owned()); - } - // 1 = `[` - let shape = shape.offset_left(prefix.len() + 1)?; - Some( - self.meta() - .and_then(|meta| meta.rewrite(context, shape)) - .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), - ) - } - } -} - -impl<'a> Rewrite for [ast::Attribute] { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if self.is_empty() { - return Some(String::new()); - } - let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?; - if self.len() == 1 || first_group_len == self.len() { - Some(first_group_str) - } else { - let rest_str = self[first_group_len..].rewrite(context, shape)?; - let missing_span = mk_sp( - self[first_group_len - 1].span.hi(), - self[first_group_len].span.lo(), - ); - // Preserve an empty line before/after doc comments. - if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { - let snippet = context.snippet(missing_span); - let (mla, mlb) = has_newlines_before_after_comment(snippet); - let comment = ::comment::recover_missing_comment_in_span( - missing_span, - shape.with_max_width(context.config), - context, - 0, - )?; - let comment = if comment.is_empty() { - format!("\n{}", mlb) - } else { - format!("{}{}\n{}", mla, comment, mlb) - }; - Some(format!( - "{}{}{}{}", - first_group_str, - comment, - shape.indent.to_string(context.config), - rest_str - )) - } else { - combine_strs_with_missing_comments( - context, - &first_group_str, - &rest_str, - missing_span, - shape, - false, - ) - } - } - } -} diff --git a/rustfmt-core/src/chains.rs b/rustfmt-core/src/chains.rs deleted file mode 100644 index 87100c7be41..00000000000 --- a/rustfmt-core/src/chains.rs +++ /dev/null @@ -1,501 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Formatting of chained expressions, i.e. expressions which are chained by -//! dots: struct and enum field access, method calls, and try shorthand (?). -//! -//! Instead of walking these subexpressions one-by-one, as is our usual strategy -//! for expression formatting, we collect maximal sequences of these expressions -//! and handle them simultaneously. -//! -//! Whenever possible, the entire chain is put on a single line. If that fails, -//! we put each subexpression on a separate, much like the (default) function -//! argument function argument strategy. -//! -//! Depends on config options: `chain_indent` is the indent to use for -//! blocks in the parent/root/base of the chain (and the rest of the chain's -//! alignment). -//! E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the -//! following values of `chain_indent`: -//! Block: -//! ``` -//! let foo = { -//! aaaa; -//! bbb; -//! ccc -//! }.bar -//! .baz(); -//! ``` -//! Visual: -//! ``` -//! let foo = { -//! aaaa; -//! bbb; -//! ccc -//! } -//! .bar -//! .baz(); -//! ``` -//! -//! If the first item in the chain is a block expression, we align the dots with -//! the braces. -//! Block: -//! ``` -//! let a = foo.bar -//! .baz() -//! .qux -//! ``` -//! Visual: -//! ``` -//! let a = foo.bar -//! .baz() -//! .qux -//! ``` - -use config::IndentStyle; -use expr::rewrite_call; -use macros::convert_try_mac; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, - trimmed_last_line_width, wrap_str}; - -use std::borrow::Cow; -use std::cmp::min; -use std::iter; - -use syntax::{ast, ptr}; -use syntax::codemap::Span; - -pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - debug!("rewrite_chain {:?}", shape); - let total_span = expr.span; - let (parent, subexpr_list) = make_subexpr_list(expr, context); - - // Bail out if the chain is just try sugar, i.e., an expression followed by - // any number of `?`s. - if chain_only_try(&subexpr_list) { - return rewrite_try(&parent, subexpr_list.len(), context, shape); - } - let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); - let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); - - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = if is_block_expr(context, &parent, "\n") { - match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape, - } - } else { - shape - }; - let parent_rewrite = parent - .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?; - let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); - let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); - - // Decide how to layout the rest of the chain. `extend` is true if we can - // put the first non-parent item on the same line as the parent. - let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.indent_style() == IndentStyle::Visual || is_small_parent, - ) - } else if is_block_expr(context, &parent, &parent_rewrite) { - match context.config.indent_style() { - // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), - // The parent is a block, so align the rest of the chain with the closing - // brace. - IndentStyle::Visual => (parent_shape, false), - } - } else { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - false, - ) - }; - - let other_child_shape = nested_shape.with_max_width(context.config); - - let first_child_shape = if extend { - let overhead = last_line_width(&parent_rewrite); - let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; - match context.config.indent_style() { - IndentStyle::Visual => parent_shape.offset_left(overhead)?, - IndentStyle::Block => parent_shape.offset_left(offset)?, - } - } else { - other_child_shape - }; - debug!( - "child_shapes {:?} {:?}", - first_child_shape, other_child_shape - ); - - let child_shape_iter = Some(first_child_shape) - .into_iter() - .chain(iter::repeat(other_child_shape)); - let subexpr_num = subexpr_list.len(); - let last_subexpr = &subexpr_list[suffix_try_num]; - let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; - let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); - let mut rewrites = iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) - .collect::>>()?; - - // Total of all items excluding the last. - let extend_last_subexpr = if is_small_parent { - rewrites.len() == 1 && last_line_extendable(&rewrites[0]) - } else { - rewrites.is_empty() && last_line_extendable(&parent_rewrite) - }; - let almost_total = if extend_last_subexpr { - last_line_width(&parent_rewrite) - } else { - rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() - } + suffix_try_num; - let one_line_budget = if rewrites.is_empty() { - shape.width - } else { - min(shape.width, context.config.width_heuristics().chain_width) - }; - let all_in_one_line = !parent_rewrite_contains_newline - && rewrites.iter().all(|s| !s.contains('\n')) - && almost_total < one_line_budget; - let last_shape = if rewrites.is_empty() { - first_child_shape - } else { - other_child_shape - }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; - - // Rewrite the last child. The last child of a chain requires special treatment. We need to - // know whether 'overflowing' the last child make a better formatting: - // - // A chain with overflowing the last child: - // ``` - // parent.child1.child2.last_child( - // a, - // b, - // c, - // ) - // ``` - // - // A chain without overflowing the last child (in vertical layout): - // ``` - // parent - // .child1 - // .child2 - // .last_child(a, b, c) - // ``` - // - // In particular, overflowing is effective when the last child is a method with a multi-lined - // block-like argument (e.g. closure): - // ``` - // parent.child1.child2.last_child(|a, b, c| { - // let x = foo(a, b, c); - // let y = bar(a, b, c); - // - // // ... - // - // result - // }) - // ``` - - // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of - // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); - let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { - // First we try to 'overflow' the last child and see if it looks better than using - // vertical layout. - parent_shape.offset_left(almost_total).map(|shape| { - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { - // We allow overflowing here only if both of the following conditions match: - // 1. The entire chain fits in a single line expect the last child. - // 2. `last_child_str.lines().count() >= 5`. - let line_count = rw.lines().count(); - let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if fits_single_line && line_count >= 5 { - (Some(rw), true) - } else { - // We could not know whether overflowing is better than using vertical layout, - // just by looking at the overflowed rewrite. Now we rewrite the last child - // on its own line, and compare two rewrites to choose which is better. - match rewrite_last() { - Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), - Some(ref new_rw) if new_rw.lines().count() >= line_count => { - (Some(rw), fits_single_line) - } - new_rw @ Some(..) => (new_rw, false), - _ => (Some(rw), fits_single_line), - } - } - } else { - (rewrite_last(), false) - } - })? - } else { - (rewrite_last(), false) - }; - rewrites.push(last_subexpr_str?); - - let connector = if fits_single_line && !parent_rewrite_contains_newline { - // Yay, we can put everything on one line. - Cow::from("") - } else { - // Use new lines. - if context.force_one_line_chain { - return None; - } - nested_shape.indent.to_string_with_newline(context.config) - }; - - let first_connector = if is_small_parent || fits_single_line - || last_line_extendable(&parent_rewrite) - || context.config.indent_style() == IndentStyle::Visual - { - "" - } else { - &connector - }; - - let result = if is_small_parent && rewrites.len() > 1 { - let second_connector = if fits_single_line || rewrites[1] == "?" - || last_line_extendable(&rewrites[0]) - || context.config.indent_style() == IndentStyle::Visual - { - "" - } else { - &connector - }; - format!( - "{}{}{}{}{}", - parent_rewrite, - first_connector, - rewrites[0], - second_connector, - join_rewrites(&rewrites[1..], &connector) - ) - } else { - format!( - "{}{}{}", - parent_rewrite, - first_connector, - join_rewrites(&rewrites, &connector) - ) - }; - let result = format!("{}{}", result, repeat_try(suffix_try_num)); - if context.config.indent_style() == IndentStyle::Visual { - wrap_str(result, context.config.max_width(), shape) - } else { - Some(result) - } -} - -// True if the chain is only `?`s. -fn chain_only_try(exprs: &[ast::Expr]) -> bool { - exprs.iter().all(|e| { - if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - } - }) -} - -// Try to rewrite and replace the last non-try child. Return `true` if -// replacing succeeds. -fn repeat_try(try_count: usize) -> String { - iter::repeat("?").take(try_count).collect::() -} - -fn rewrite_try( - expr: &ast::Expr, - try_count: usize, - context: &RewriteContext, - shape: Shape, -) -> Option { - let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; - Some(format!("{}{}", sub_expr, repeat_try(try_count))) -} - -fn join_rewrites(rewrites: &[String], connector: &str) -> String { - let mut rewrite_iter = rewrites.iter(); - let mut result = rewrite_iter.next().unwrap().clone(); - - for rewrite in rewrite_iter { - if rewrite != "?" { - result.push_str(connector); - } - result.push_str(&rewrite[..]); - } - - result -} - -// States whether an expression's last line exclusively consists of closing -// parens, braces, and brackets in its idiomatic formatting. -fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { - match expr.node { - ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { - context.use_block_indent() && repr.contains('\n') - } - ast::ExprKind::Struct(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Match(..) => repr.contains('\n'), - ast::ExprKind::Paren(ref expr) - | ast::ExprKind::Binary(_, _, ref expr) - | ast::ExprKind::Index(_, ref expr) - | ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), - _ => false, - } -} - -// Returns the root of the chain and a Vec of the prefixes of the rest of the chain. -// E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) -fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { - let mut subexpr_list = vec![expr.clone()]; - - while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { - subexpr_list.push(subexpr.clone()); - } - - let parent = subexpr_list.pop().unwrap(); - (parent, subexpr_list) -} - -fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), - } -} - -// Returns the expression's subexpression, if it exists. When the subexpr -// is a try! macro, we'll convert it to shorthand when the option is set. -fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { - match expr.node { - ast::ExprKind::MethodCall(_, ref expressions) => { - Some(convert_try(&expressions[0], context)) - } - ast::ExprKind::TupField(ref subexpr, _) - | ast::ExprKind::Field(ref subexpr, _) - | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), - _ => None, - } -} - -fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { - match expr.node { - ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { - if let Some(subexpr) = convert_try_mac(mac, context) { - subexpr - } else { - expr.clone() - } - } - _ => expr.clone(), - } -} - -// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite -// `.c`. -fn rewrite_chain_subexpr( - expr: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let rewrite_element = |expr_str: String| { - if expr_str.len() <= shape.width { - Some(expr_str) - } else { - None - } - }; - - match expr.node { - ast::ExprKind::MethodCall(ref segment, ref expressions) => { - let types = match segment.parameters { - Some(ref params) => match **params { - ast::PathParameters::AngleBracketed(ref data) => &data.types[..], - _ => &[], - }, - _ => &[], - }; - rewrite_method_call(segment.identifier, types, expressions, span, context, shape) - } - ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), - ast::ExprKind::TupField(ref expr, ref field) => { - let space = match expr.node { - ast::ExprKind::TupField(..) => " ", - _ => "", - }; - rewrite_element(format!("{}.{}", space, field.node)) - } - ast::ExprKind::Try(_) => rewrite_element(String::from("?")), - _ => unreachable!(), - } -} - -// Determines if we can continue formatting a given expression on the same line. -fn is_continuable(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Path(..) => true, - _ => false, - } -} - -fn is_try(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Try(..) => true, - _ => false, - } -} - -fn rewrite_method_call( - method_name: ast::Ident, - types: &[ptr::P], - args: &[ptr::P], - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let (lo, type_str) = if types.is_empty() { - (args[0].span.hi(), String::new()) - } else { - let type_list = types - .iter() - .map(|ty| ty.rewrite(context, shape)) - .collect::>>()?; - - let type_str = - if context.config.spaces_within_parens_and_brackets() && !type_list.is_empty() { - format!("::< {} >", type_list.join(", ")) - } else { - format!("::<{}>", type_list.join(", ")) - }; - - (types.last().unwrap().span.hi(), type_str) - }; - - let callee_str = format!(".{}{}", method_name, type_str); - let span = mk_sp(lo, span.hi()); - - rewrite_call(context, &callee_str, &args[1..], span, shape) -} diff --git a/rustfmt-core/src/checkstyle.rs b/rustfmt-core/src/checkstyle.rs deleted file mode 100644 index 7f6e650ad22..00000000000 --- a/rustfmt-core/src/checkstyle.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::io::{self, Write}; -use std::path::Path; - -use config::WriteMode; -use rustfmt_diff::{DiffLine, Mismatch}; - -pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> -where - T: Write, -{ - if mode == WriteMode::Checkstyle { - let mut xml_heading = String::new(); - xml_heading.push_str(""); - xml_heading.push_str("\n"); - xml_heading.push_str(""); - write!(out, "{}", xml_heading)?; - } - Ok(()) -} - -pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> -where - T: Write, -{ - if mode == WriteMode::Checkstyle { - let mut xml_tail = String::new(); - xml_tail.push_str("\n"); - write!(out, "{}", xml_tail)?; - } - Ok(()) -} - -pub fn output_checkstyle_file( - mut writer: T, - filename: &Path, - diff: Vec, -) -> Result<(), io::Error> -where - T: Write, -{ - write!(writer, "", filename.display())?; - for mismatch in diff { - for line in mismatch.lines { - // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. - if let DiffLine::Expected(ref str) = line { - let message = xml_escape_str(str); - write!( - writer, - "", - mismatch.line_number, message - )?; - } - } - } - write!(writer, "")?; - Ok(()) -} - -// Convert special characters into XML entities. -// This is needed for checkstyle output. -fn xml_escape_str(string: &str) -> String { - let mut out = String::new(); - for c in string.chars() { - match c { - '<' => out.push_str("<"), - '>' => out.push_str(">"), - '"' => out.push_str("""), - '\'' => out.push_str("'"), - '&' => out.push_str("&"), - _ => out.push(c), - } - } - out -} diff --git a/rustfmt-core/src/closures.rs b/rustfmt-core/src/closures.rs deleted file mode 100644 index 6097f6339ed..00000000000 --- a/rustfmt-core/src/closures.rs +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use config::lists::*; -use syntax::{ast, ptr}; -use syntax::codemap::Span; -use syntax::parse::classify; - -use codemap::SpanUtils; -use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; -use items::{span_hi_for_arg, span_lo_for_arg}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use utils::{last_line_width, left_most_sub_expr, stmt_expr}; - -// This module is pretty messy because of the rules around closures and blocks: -// FIXME - the below is probably no longer true in full. -// * if there is a return type, then there must be braces, -// * given a closure with braces, whether that is parsed to give an inner block -// or not depends on if there is a return type and if there are statements -// in that block, -// * if the first expression in the body ends with a block (i.e., is a -// statement without needing a semi-colon), then adding or removing braces -// can change whether it is treated as an expression or statement. - -pub fn rewrite_closure( - capture: ast::CaptureBy, - movability: ast::Movability, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - debug!("rewrite_closure {:?}", body); - - let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?; - // 1 = space between `|...|` and body. - let body_shape = shape.offset_left(extra_offset)?; - - if let ast::ExprKind::Block(ref block) = body.node { - // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return Some(format!("{} {{}}", prefix)); - } - - let result = match fn_decl.output { - ast::FunctionRetTy::Default(_) => { - try_rewrite_without_block(body, &prefix, context, shape, body_shape) - } - _ => None, - }; - - result.or_else(|| { - // Either we require a block, or tried without and failed. - rewrite_closure_block(block, &prefix, context, body_shape) - }) - } else { - rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { - // The closure originally had a non-block expression, but we can't fit on - // one line, so we'll insert a block. - rewrite_closure_with_block(body, &prefix, context, body_shape) - }) - } -} - -fn try_rewrite_without_block( - expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, - body_shape: Shape, -) -> Option { - let expr = get_inner_expr(expr, prefix, context); - - if is_block_closure_forced(context, expr) { - rewrite_closure_with_block(expr, prefix, context, shape) - } else { - rewrite_closure_expr(expr, prefix, context, body_shape) - } -} - -fn get_inner_expr<'a>( - expr: &'a ast::Expr, - prefix: &str, - context: &RewriteContext, -) -> &'a ast::Expr { - if let ast::ExprKind::Block(ref block) = expr.node { - if !needs_block(block, prefix, context) { - // block.stmts.len() == 1 - if let Some(expr) = stmt_expr(&block.stmts[0]) { - return get_inner_expr(expr, prefix, context); - } - } - } - - expr -} - -// Figure out if a block is necessary. -fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { - is_unsafe_block(block) || block.stmts.len() > 1 - || block_contains_comment(block, context.codemap) || prefix.contains('\n') -} - -// Rewrite closure with a single expression wrapping its body with block. -fn rewrite_closure_with_block( - body: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - let left_most = left_most_sub_expr(body); - let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most); - if veto_block { - return None; - } - - let block = ast::Block { - stmts: vec![ - ast::Stmt { - id: ast::NodeId::new(0), - node: ast::StmtKind::Expr(ptr::P(body.clone())), - span: body.span, - }, - ], - id: ast::NodeId::new(0), - rules: ast::BlockCheckMode::Default, - span: body.span, - recovered: false, - }; - let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; - Some(format!("{} {}", prefix, block)) -} - -// Rewrite closure with a single expression without wrapping its body with block. -fn rewrite_closure_expr( - expr: &ast::Expr, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - fn allow_multi_line(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Match(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Catch(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::Struct(..) => true, - - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), - - _ => false, - } - } - - // When rewriting closure's body without block, we require it to fit in a single line - // unless it is a block-like expression or we are inside macro call. - let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro) - || context.config.force_multiline_blocks(); - expr.rewrite(context, shape) - .and_then(|rw| { - if veto_multiline && rw.contains('\n') { - None - } else { - Some(rw) - } - }) - .map(|rw| format!("{} {}", prefix, rw)) -} - -// Rewrite closure whose body is block. -fn rewrite_closure_block( - block: &ast::Block, - prefix: &str, - context: &RewriteContext, - shape: Shape, -) -> Option { - Some(format!("{} {}", prefix, block.rewrite(context, shape)?)) -} - -// Return type is (prefix, extra_offset) -fn rewrite_closure_fn_decl( - capture: ast::CaptureBy, - movability: ast::Movability, - fn_decl: &ast::FnDecl, - body: &ast::Expr, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option<(String, usize)> { - let mover = if capture == ast::CaptureBy::Value { - "move " - } else { - "" - }; - - let immovable = if movability == ast::Movability::Static { - "static " - } else { - "" - }; - // 4 = "|| {".len(), which is overconservative when the closure consists of - // a single expression. - let nested_shape = shape - .shrink_left(mover.len() + immovable.len())? - .sub_width(4)?; - - // 1 = | - let argument_offset = nested_shape.indent + 1; - let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); - let ret_str = fn_decl.output.rewrite(context, arg_shape)?; - - let arg_items = itemize_list( - context.snippet_provider, - fn_decl.inputs.iter(), - "|", - ",", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(context, arg), - |arg| arg.rewrite(context, arg_shape), - context.snippet_provider.span_after(span, "|"), - body.span.lo(), - false, - ); - let item_vec = arg_items.collect::>(); - // 1 = space between arguments and return type. - let horizontal_budget = nested_shape - .width - .checked_sub(ret_str.len() + 1) - .unwrap_or(0); - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - horizontal_budget, - ); - let arg_shape = match tactic { - DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, - _ => arg_shape, - }; - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arg_shape, - ends_with_newline: false, - preserve_newline: true, - config: context.config, - }; - let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}{}|{}|", immovable, mover, list_str); - - if !ret_str.is_empty() { - if prefix.contains('\n') { - prefix.push('\n'); - prefix.push_str(&argument_offset.to_string(context.config)); - } else { - prefix.push(' '); - } - prefix.push_str(&ret_str); - } - // 1 = space between `|...|` and body. - let extra_offset = last_line_width(&prefix) + 1; - - Some((prefix, extra_offset)) -} - -// Rewriting closure which is placed at the end of the function call's arg. -// Returns `None` if the reformatted closure 'looks bad'. -pub fn rewrite_last_closure( - context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, -) -> Option { - if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { - let body = match body.node { - ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => - { - stmt_expr(&block.stmts[0]).unwrap_or(body) - } - _ => body, - }; - let (prefix, extra_offset) = rewrite_closure_fn_decl( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, - )?; - // If the closure goes multi line before its body, do not overflow the closure. - if prefix.contains('\n') { - return None; - } - - let body_shape = shape.offset_left(extra_offset)?; - - // We force to use block for the body of the closure for certain kinds of expressions. - if is_block_closure_forced(context, body) { - return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( - |body_str| { - // If the expression can fit in a single line, we need not force block closure. - if body_str.lines().count() <= 7 { - match rewrite_closure_expr(body, &prefix, context, shape) { - Some(ref single_line_body_str) - if !single_line_body_str.contains('\n') => - { - Some(single_line_body_str.clone()) - } - _ => Some(body_str), - } - } else { - Some(body_str) - } - }, - ); - } - - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - let is_multi_lined_cond = rewrite_cond(context, body, body_shape) - .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) - .unwrap_or(false); - if is_multi_lined_cond { - return rewrite_closure_with_block(body, &prefix, context, body_shape); - } - - // Seems fine, just format the closure in usual manner. - return expr.rewrite(context, shape); - } - None -} - -/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. -pub fn args_have_many_closure(args: &[&T]) -> bool -where - T: ToExpr, -{ - args.iter() - .filter(|arg| { - arg.to_expr() - .map(|e| match e.node { - ast::ExprKind::Closure(..) => true, - _ => false, - }) - .unwrap_or(false) - }) - .count() > 1 -} - -fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { - // If we are inside macro, we do not want to add or remove block from closure body. - if context.inside_macro { - false - } else { - is_block_closure_forced_inner(expr) - } -} - -fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::ForLoop(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr), - _ => false, - } -} diff --git a/rustfmt-core/src/codemap.rs b/rustfmt-core/src/codemap.rs deleted file mode 100644 index 224b2083561..00000000000 --- a/rustfmt-core/src/codemap.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This module contains utilities that work with the `CodeMap` from `libsyntax` / `syntex_syntax`. -//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. - -use config::file_lines::LineRange; -use visitor::SnippetProvider; -use syntax::codemap::{BytePos, CodeMap, Span}; - -use comment::FindUncommented; - -pub trait SpanUtils { - fn span_after(&self, original: Span, needle: &str) -> BytePos; - fn span_after_last(&self, original: Span, needle: &str) -> BytePos; - fn span_before(&self, original: Span, needle: &str) -> BytePos; - fn opt_span_after(&self, original: Span, needle: &str) -> Option; -} - -pub trait LineRangeUtils { - /// Returns the `LineRange` that corresponds to `span` in `self`. - /// - /// # Panics - /// - /// Panics if `span` crosses a file boundary, which shouldn't happen. - fn lookup_line_range(&self, span: Span) -> LineRange; -} - -impl<'a> SpanUtils for SnippetProvider<'a> { - fn span_after(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).expect("Bad snippet"); - let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len(); - - original.lo() + BytePos(offset as u32) - } - - fn span_after_last(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let mut offset = 0; - - while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { - offset += additional_offset + needle.len(); - } - - original.lo() + BytePos(offset as u32) - } - - fn span_before(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap(); - - original.lo() + BytePos(offset as u32) - } - - fn opt_span_after(&self, original: Span, needle: &str) -> Option { - let snippet = self.span_to_snippet(original)?; - let offset = snippet.find_uncommented(needle)? + needle.len(); - - Some(original.lo() + BytePos(offset as u32)) - } -} - -impl LineRangeUtils for CodeMap { - fn lookup_line_range(&self, span: Span) -> LineRange { - let lo = self.lookup_line(span.lo()).unwrap(); - let hi = self.lookup_line(span.hi()).unwrap(); - - debug_assert_eq!( - lo.fm.name, hi.fm.name, - "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, hi - ); - - // Line numbers start at 1 - LineRange { - file: lo.fm.clone(), - lo: lo.line + 1, - hi: hi.line + 1, - } - } -} diff --git a/rustfmt-core/src/comment.rs b/rustfmt-core/src/comment.rs deleted file mode 100644 index 8b148ccfc37..00000000000 --- a/rustfmt-core/src/comment.rs +++ /dev/null @@ -1,1277 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Formatting and tools for comments. - -use std::{self, iter, borrow::Cow}; - -use syntax::codemap::Span; - -use config::Config; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; -use string::{rewrite_string, StringFormat}; -use utils::{count_newlines, first_line_width, last_line_width}; - -fn is_custom_comment(comment: &str) -> bool { - if !comment.starts_with("//") { - false - } else if let Some(c) = comment.chars().nth(2) { - !c.is_alphanumeric() && !c.is_whitespace() - } else { - false - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum CommentStyle<'a> { - DoubleSlash, - TripleSlash, - Doc, - SingleBullet, - DoubleBullet, - Exclamation, - Custom(&'a str), -} - -fn custom_opener(s: &str) -> &str { - s.lines().next().map_or("", |first_line| { - first_line - .find(' ') - .map_or(first_line, |space_index| &first_line[0..space_index + 1]) - }) -} - -impl<'a> CommentStyle<'a> { - pub fn is_doc_comment(&self) -> bool { - match *self { - CommentStyle::TripleSlash | CommentStyle::Doc => true, - _ => false, - } - } - - pub fn opener(&self) -> &'a str { - match *self { - CommentStyle::DoubleSlash => "// ", - CommentStyle::TripleSlash => "/// ", - CommentStyle::Doc => "//! ", - CommentStyle::SingleBullet => "/* ", - CommentStyle::DoubleBullet => "/** ", - CommentStyle::Exclamation => "/*! ", - CommentStyle::Custom(opener) => opener, - } - } - - pub fn closer(&self) -> &'a str { - match *self { - CommentStyle::DoubleSlash - | CommentStyle::TripleSlash - | CommentStyle::Custom(..) - | CommentStyle::Doc => "", - CommentStyle::DoubleBullet => " **/", - CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", - } - } - - pub fn line_start(&self) -> &'a str { - match *self { - CommentStyle::DoubleSlash => "// ", - CommentStyle::TripleSlash => "/// ", - CommentStyle::Doc => "//! ", - CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", - CommentStyle::DoubleBullet => " ** ", - CommentStyle::Custom(opener) => opener, - } - } - - pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { - (self.opener(), self.closer(), self.line_start()) - } - - pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { - match *self { - CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { - line.trim_left().starts_with(self.line_start().trim_left()) - || comment_style(line, normalize_comments) == *self - } - CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { - line.trim_left().starts_with(self.closer().trim_left()) - || line.trim_left().starts_with(self.line_start().trim_left()) - || comment_style(line, normalize_comments) == *self - } - CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), - } - } -} - -fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { - if !normalize_comments { - if orig.starts_with("/**") && !orig.starts_with("/**/") { - CommentStyle::DoubleBullet - } else if orig.starts_with("/*!") { - CommentStyle::Exclamation - } else if orig.starts_with("/*") { - CommentStyle::SingleBullet - } else if orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/') { - CommentStyle::TripleSlash - } else if orig.starts_with("//!") { - CommentStyle::Doc - } else if is_custom_comment(orig) { - CommentStyle::Custom(custom_opener(orig)) - } else { - CommentStyle::DoubleSlash - } - } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) - || (orig.starts_with("/**") && !orig.starts_with("/**/")) - { - CommentStyle::TripleSlash - } else if orig.starts_with("//!") || orig.starts_with("/*!") { - CommentStyle::Doc - } else if is_custom_comment(orig) { - CommentStyle::Custom(custom_opener(orig)) - } else { - CommentStyle::DoubleSlash - } -} - -/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain -/// comments between two strings. If there are such comments, then that will be -/// recovered. If `allow_extend` is true and there is no comment between the two -/// strings, then they will be put on a single line as long as doing so does not -/// exceed max width. -pub fn combine_strs_with_missing_comments( - context: &RewriteContext, - prev_str: &str, - next_str: &str, - span: Span, - shape: Shape, - allow_extend: bool, -) -> Option { - let mut result = - String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128); - result.push_str(prev_str); - let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); - let first_sep = if prev_str.is_empty() || next_str.is_empty() { - "" - } else { - " " - }; - let mut one_line_width = - last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); - - let config = context.config; - let indent = shape.indent; - let missing_comment = rewrite_missing_comment(span, shape, context)?; - - if missing_comment.is_empty() { - if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { - result.push_str(first_sep); - } else if !prev_str.is_empty() { - result.push_str(&indent.to_string_with_newline(config)) - } - result.push_str(next_str); - return Some(result); - } - - // We have a missing comment between the first expression and the second expression. - - // Peek the the original source code and find out whether there is a newline between the first - // expression and the second expression or the missing comment. We will preserve the original - // layout whenever possible. - let original_snippet = context.snippet(span); - let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { - !original_snippet[..pos].contains('\n') - } else { - !original_snippet.contains('\n') - }; - - one_line_width -= first_sep.len(); - let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { - Cow::from("") - } else { - let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; - if prefer_same_line && one_line_width <= shape.width { - Cow::from(" ") - } else { - indent.to_string_with_newline(config) - } - }; - result.push_str(&first_sep); - result.push_str(&missing_comment); - - let second_sep = if missing_comment.is_empty() || next_str.is_empty() { - Cow::from("") - } else if missing_comment.starts_with("//") { - indent.to_string_with_newline(config) - } else { - one_line_width += missing_comment.len() + first_sep.len() + 1; - allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); - if prefer_same_line && allow_one_line && one_line_width <= shape.width { - Cow::from(" ") - } else { - indent.to_string_with_newline(config) - } - }; - result.push_str(&second_sep); - result.push_str(next_str); - - Some(result) -} - -pub fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { - _rewrite_comment(orig, false, shape, config, true) -} - -pub fn rewrite_comment( - orig: &str, - block_style: bool, - shape: Shape, - config: &Config, -) -> Option { - _rewrite_comment(orig, block_style, shape, config, false) -} - -fn _rewrite_comment( - orig: &str, - block_style: bool, - shape: Shape, - config: &Config, - is_doc_comment: bool, -) -> Option { - // If there are lines without a starting sigil, we won't format them correctly - // so in that case we won't even re-align (if !config.normalize_comments()) and - // we should stop now. - let num_bare_lines = orig.lines() - .map(|line| line.trim()) - .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) - .count(); - if num_bare_lines > 0 && !config.normalize_comments() { - return Some(orig.to_owned()); - } - if !config.normalize_comments() && !config.wrap_comments() { - return light_rewrite_comment(orig, shape.indent, config, is_doc_comment); - } - - identify_comment(orig, block_style, shape, config, is_doc_comment) -} - -fn identify_comment( - orig: &str, - block_style: bool, - shape: Shape, - config: &Config, - is_doc_comment: bool, -) -> Option { - let style = comment_style(orig, false); - let first_group = orig.lines() - .take_while(|l| style.line_with_same_comment_style(l, false)) - .collect::>() - .join("\n"); - let rest = orig.lines() - .skip(first_group.lines().count()) - .collect::>() - .join("\n"); - - let first_group_str = rewrite_comment_inner( - &first_group, - block_style, - style, - shape, - config, - is_doc_comment || style.is_doc_comment(), - )?; - if rest.is_empty() { - Some(first_group_str) - } else { - identify_comment(&rest, block_style, shape, config, is_doc_comment).map(|rest_str| { - format!( - "{}\n{}{}", - first_group_str, - shape.indent.to_string(config), - rest_str - ) - }) - } -} - -fn rewrite_comment_inner( - orig: &str, - block_style: bool, - style: CommentStyle, - shape: Shape, - config: &Config, - is_doc_comment: bool, -) -> Option { - let (opener, closer, line_start) = if block_style { - CommentStyle::SingleBullet.to_str_tuplet() - } else { - comment_style(orig, config.normalize_comments()).to_str_tuplet() - }; - - let max_chars = shape - .width - .checked_sub(closer.len() + opener.len()) - .unwrap_or(1); - let indent_str = shape.indent.to_string_with_newline(config); - let fmt_indent = shape.indent + (opener.len() - line_start.len()); - let mut fmt = StringFormat { - opener: "", - closer: "", - line_start, - line_end: "", - shape: Shape::legacy(max_chars, fmt_indent), - trim_end: true, - config, - }; - - let line_breaks = count_newlines(orig.trim_right()); - let lines = orig.lines() - .enumerate() - .map(|(i, mut line)| { - line = trim_right_unless_two_whitespaces(line.trim_left(), is_doc_comment); - // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = line[..(line.len() - 2)].trim_right(); - } - - line - }) - .map(|s| left_trim_comment_line(s, &style)) - .map(|(line, has_leading_whitespace)| { - if orig.starts_with("/*") && line_breaks == 0 { - ( - line.trim_left(), - has_leading_whitespace || config.normalize_comments(), - ) - } else { - (line, has_leading_whitespace || config.normalize_comments()) - } - }); - - let mut result = String::with_capacity(orig.len() * 2); - result.push_str(opener); - let mut code_block_buffer = String::with_capacity(128); - let mut is_prev_line_multi_line = false; - let mut inside_code_block = false; - let comment_line_separator = format!("{}{}", indent_str, line_start); - let join_code_block_with_comment_line_separator = |s: &str| { - let mut result = String::with_capacity(s.len() + 128); - let mut iter = s.lines().peekable(); - while let Some(line) = iter.next() { - result.push_str(line); - result.push_str(match iter.peek() { - Some(next_line) if next_line.is_empty() => comment_line_separator.trim_right(), - Some(..) => &comment_line_separator, - None => "", - }); - } - result - }; - - for (i, (line, has_leading_whitespace)) in lines.enumerate() { - let is_last = i == count_newlines(orig); - - if inside_code_block { - if line.starts_with("```") { - inside_code_block = false; - result.push_str(&comment_line_separator); - let code_block = ::format_code_block(&code_block_buffer, config) - .unwrap_or_else(|| code_block_buffer.to_owned()); - result.push_str(&join_code_block_with_comment_line_separator(&code_block)); - code_block_buffer.clear(); - result.push_str(&comment_line_separator); - result.push_str(line); - } else { - code_block_buffer.push_str(line); - code_block_buffer.push('\n'); - } - - continue; - } else { - inside_code_block = line.starts_with("```"); - - if result == opener { - let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; - if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - if line.is_empty() { - continue; - } - } else if is_prev_line_multi_line && !line.is_empty() { - result.push(' ') - } else if is_last && !closer.is_empty() && line.is_empty() { - result.push_str(&indent_str); - } else { - result.push_str(&comment_line_separator); - if !has_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - } - } - - if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { - match rewrite_string(line, &fmt, Some(max_chars)) { - Some(ref s) => { - is_prev_line_multi_line = s.contains('\n'); - result.push_str(s); - } - None if is_prev_line_multi_line => { - // We failed to put the current `line` next to the previous `line`. - // Remove the trailing space, then start rewrite on the next line. - result.pop(); - result.push_str(&comment_line_separator); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - match rewrite_string(line, &fmt, Some(max_chars)) { - Some(ref s) => { - is_prev_line_multi_line = s.contains('\n'); - result.push_str(s); - } - None => { - is_prev_line_multi_line = false; - result.push_str(line); - } - } - } - None => { - is_prev_line_multi_line = false; - result.push_str(line); - } - } - - fmt.shape = if is_prev_line_multi_line { - // 1 = " " - let offset = 1 + last_line_width(&result) - line_start.len(); - Shape { - width: max_chars.checked_sub(offset).unwrap_or(0), - indent: fmt_indent, - offset: fmt.shape.offset + offset, - } - } else { - Shape::legacy(max_chars, fmt_indent) - }; - } else { - if line.is_empty() && result.ends_with(' ') && !is_last { - // Remove space if this is an empty comment or a doc comment. - result.pop(); - } - result.push_str(line); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - is_prev_line_multi_line = false; - } - } - - result.push_str(closer); - if result.ends_with(opener) && opener.ends_with(' ') { - // Trailing space. - result.pop(); - } - - Some(result) -} - -/// Returns true if the given string MAY include URLs or alike. -fn has_url(s: &str) -> bool { - // This function may return false positive, but should get its job done in most cases. - s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") -} - -/// Given the span, rewrite the missing comment inside it if available. -/// Note that the given span must only include comments (or leading/trailing whitespaces). -pub fn rewrite_missing_comment( - span: Span, - shape: Shape, - context: &RewriteContext, -) -> Option { - let missing_snippet = context.snippet(span); - let trimmed_snippet = missing_snippet.trim(); - if !trimmed_snippet.is_empty() { - rewrite_comment(trimmed_snippet, false, shape, context.config) - } else { - Some(String::new()) - } -} - -/// Recover the missing comments in the specified span, if available. -/// The layout of the comments will be preserved as long as it does not break the code -/// and its total width does not exceed the max width. -pub fn recover_missing_comment_in_span( - span: Span, - shape: Shape, - context: &RewriteContext, - used_width: usize, -) -> Option { - let missing_comment = rewrite_missing_comment(span, shape, context)?; - if missing_comment.is_empty() { - Some(String::new()) - } else { - let missing_snippet = context.snippet(span); - let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); - // 1 = ` ` - let total_width = missing_comment.len() + used_width + 1; - let force_new_line_before_comment = - missing_snippet[..pos].contains('\n') || total_width > context.config.max_width(); - let sep = if force_new_line_before_comment { - shape.indent.to_string_with_newline(context.config) - } else { - Cow::from(" ") - }; - Some(format!("{}{}", sep, missing_comment)) - } -} - -/// Trim trailing whitespaces unless they consist of two or more whitespaces. -fn trim_right_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str { - if is_doc_comment && s.ends_with(" ") { - s - } else { - s.trim_right() - } -} - -/// Trims whitespace and aligns to indent, but otherwise does not change comments. -fn light_rewrite_comment( - orig: &str, - offset: Indent, - config: &Config, - is_doc_comment: bool, -) -> Option { - let lines: Vec<&str> = orig.lines() - .map(|l| { - // This is basically just l.trim(), but in the case that a line starts - // with `*` we want to leave one space before it, so it aligns with the - // `*` in `/*`. - let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); - let left_trimmed = if let Some(fnw) = first_non_whitespace { - if l.as_bytes()[fnw] == b'*' && fnw > 0 { - &l[fnw - 1..] - } else { - &l[fnw..] - } - } else { - "" - }; - // Preserve markdown's double-space line break syntax in doc comment. - trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) - }) - .collect(); - Some(lines.join(&format!("\n{}", offset.to_string(config)))) -} - -/// Trims comment characters and possibly a single space from the left of a string. -/// Does not trim all whitespace. If a single space is trimmed from the left of the string, -/// this function returns true. -fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { - if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") - || line.starts_with("/** ") - { - (&line[4..], true) - } else if let CommentStyle::Custom(opener) = *style { - if line.starts_with(opener) { - (&line[opener.len()..], true) - } else { - (&line[opener.trim_right().len()..], false) - } - } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") - || line.starts_with("///") || line.starts_with("** ") - || line.starts_with("/*!") - || (line.starts_with("/**") && !line.starts_with("/**/")) - { - (&line[3..], line.chars().nth(2).unwrap() == ' ') - } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") - || line.starts_with("**") - { - (&line[2..], line.chars().nth(1).unwrap() == ' ') - } else if line.starts_with('*') { - (&line[1..], false) - } else { - (line, line.starts_with(' ')) - } -} - -pub trait FindUncommented { - fn find_uncommented(&self, pat: &str) -> Option; -} - -impl FindUncommented for str { - fn find_uncommented(&self, pat: &str) -> Option { - let mut needle_iter = pat.chars(); - for (kind, (i, b)) in CharClasses::new(self.char_indices()) { - match needle_iter.next() { - None => { - return Some(i - pat.len()); - } - Some(c) => match kind { - FullCodeCharKind::Normal | FullCodeCharKind::InString if b == c => {} - _ => { - needle_iter = pat.chars(); - } - }, - } - } - - // Handle case where the pattern is a suffix of the search string - match needle_iter.next() { - Some(_) => None, - None => Some(self.len() - pat.len()), - } - } -} - -// Returns the first byte position after the first comment. The given string -// is expected to be prefixed by a comment, including delimiters. -// Good: "/* /* inner */ outer */ code();" -// Bad: "code(); // hello\n world!" -pub fn find_comment_end(s: &str) -> Option { - let mut iter = CharClasses::new(s.char_indices()); - for (kind, (i, _c)) in &mut iter { - if kind == FullCodeCharKind::Normal || kind == FullCodeCharKind::InString { - return Some(i); - } - } - - // Handle case where the comment ends at the end of s. - if iter.status == CharClassesStatus::Normal { - Some(s.len()) - } else { - None - } -} - -/// Returns true if text contains any comment. -pub fn contains_comment(text: &str) -> bool { - CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) -} - -/// Remove trailing spaces from the specified snippet. We do not remove spaces -/// inside strings or comments. -pub fn remove_trailing_white_spaces(text: &str) -> String { - let mut buffer = String::with_capacity(text.len()); - let mut space_buffer = String::with_capacity(128); - for (char_kind, c) in CharClasses::new(text.chars()) { - match c { - '\n' => { - if char_kind == FullCodeCharKind::InString { - buffer.push_str(&space_buffer); - } - space_buffer.clear(); - buffer.push('\n'); - } - _ if c.is_whitespace() => { - space_buffer.push(c); - } - _ => { - if !space_buffer.is_empty() { - buffer.push_str(&space_buffer); - space_buffer.clear(); - } - buffer.push(c); - } - } - } - buffer -} - -pub struct CharClasses -where - T: Iterator, - T::Item: RichChar, -{ - base: iter::Peekable, - status: CharClassesStatus, -} - -pub trait RichChar { - fn get_char(&self) -> char; -} - -impl RichChar for char { - fn get_char(&self) -> char { - *self - } -} - -impl RichChar for (usize, char) { - fn get_char(&self) -> char { - self.1 - } -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -enum CharClassesStatus { - Normal, - LitString, - LitStringEscape, - LitChar, - LitCharEscape, - // The u32 is the nesting deepness of the comment - BlockComment(u32), - // Status when the '/' has been consumed, but not yet the '*', deepness is - // the new deepness (after the comment opening). - BlockCommentOpening(u32), - // Status when the '*' has been consumed, but not yet the '/', deepness is - // the new deepness (after the comment closing). - BlockCommentClosing(u32), - LineComment, -} - -/// Distinguish between functional part of code and comments -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum CodeCharKind { - Normal, - Comment, -} - -/// Distinguish between functional part of code and comments, -/// describing opening and closing of comments for ease when chunking -/// code from tagged characters -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum FullCodeCharKind { - Normal, - /// The first character of a comment, there is only one for a comment (always '/') - StartComment, - /// Any character inside a comment including the second character of comment - /// marks ("//", "/*") - InComment, - /// Last character of a comment, '\n' for a line comment, '/' for a block comment. - EndComment, - /// Inside a string. - InString, -} - -impl FullCodeCharKind { - pub fn is_comment(&self) -> bool { - match *self { - FullCodeCharKind::StartComment - | FullCodeCharKind::InComment - | FullCodeCharKind::EndComment => true, - _ => false, - } - } - - pub fn is_string(&self) -> bool { - *self == FullCodeCharKind::InString - } - - fn to_codecharkind(&self) -> CodeCharKind { - if self.is_comment() { - CodeCharKind::Comment - } else { - CodeCharKind::Normal - } - } -} - -impl CharClasses -where - T: Iterator, - T::Item: RichChar, -{ - pub fn new(base: T) -> CharClasses { - CharClasses { - base: base.peekable(), - status: CharClassesStatus::Normal, - } - } -} - -impl Iterator for CharClasses -where - T: Iterator, - T::Item: RichChar, -{ - type Item = (FullCodeCharKind, T::Item); - - fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { - let item = self.base.next()?; - let chr = item.get_char(); - let mut char_kind = FullCodeCharKind::Normal; - self.status = match self.status { - CharClassesStatus::LitString => match chr { - '"' => CharClassesStatus::Normal, - '\\' => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitStringEscape - } - _ => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } - }, - CharClassesStatus::LitStringEscape => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } - CharClassesStatus::LitChar => match chr { - '\\' => CharClassesStatus::LitCharEscape, - '\'' => CharClassesStatus::Normal, - _ => CharClassesStatus::LitChar, - }, - CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, - CharClassesStatus::Normal => match chr { - '"' => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } - '\'' => CharClassesStatus::LitChar, - '/' => match self.base.peek() { - Some(next) if next.get_char() == '*' => { - self.status = CharClassesStatus::BlockCommentOpening(1); - return Some((FullCodeCharKind::StartComment, item)); - } - Some(next) if next.get_char() == '/' => { - self.status = CharClassesStatus::LineComment; - return Some((FullCodeCharKind::StartComment, item)); - } - _ => CharClassesStatus::Normal, - }, - _ => CharClassesStatus::Normal, - }, - CharClassesStatus::BlockComment(deepness) => { - assert_ne!(deepness, 0); - self.status = match self.base.peek() { - Some(next) if next.get_char() == '/' && chr == '*' => { - CharClassesStatus::BlockCommentClosing(deepness - 1) - } - Some(next) if next.get_char() == '*' && chr == '/' => { - CharClassesStatus::BlockCommentOpening(deepness + 1) - } - _ => CharClassesStatus::BlockComment(deepness), - }; - return Some((FullCodeCharKind::InComment, item)); - } - CharClassesStatus::BlockCommentOpening(deepness) => { - assert_eq!(chr, '*'); - self.status = CharClassesStatus::BlockComment(deepness); - return Some((FullCodeCharKind::InComment, item)); - } - CharClassesStatus::BlockCommentClosing(deepness) => { - assert_eq!(chr, '/'); - if deepness == 0 { - self.status = CharClassesStatus::Normal; - return Some((FullCodeCharKind::EndComment, item)); - } else { - self.status = CharClassesStatus::BlockComment(deepness); - return Some((FullCodeCharKind::InComment, item)); - } - } - CharClassesStatus::LineComment => match chr { - '\n' => { - self.status = CharClassesStatus::Normal; - return Some((FullCodeCharKind::EndComment, item)); - } - _ => { - self.status = CharClassesStatus::LineComment; - return Some((FullCodeCharKind::InComment, item)); - } - }, - }; - Some((char_kind, item)) - } -} - -/// Iterator over functional and commented parts of a string. Any part of a string is either -/// functional code, either *one* block comment, either *one* line comment. Whitespace between -/// comments is functional code. Line comments contain their ending newlines. -struct UngroupedCommentCodeSlices<'a> { - slice: &'a str, - iter: iter::Peekable>>, -} - -impl<'a> UngroupedCommentCodeSlices<'a> { - fn new(code: &'a str) -> UngroupedCommentCodeSlices<'a> { - UngroupedCommentCodeSlices { - slice: code, - iter: CharClasses::new(code.char_indices()).peekable(), - } - } -} - -impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { - type Item = (CodeCharKind, usize, &'a str); - - fn next(&mut self) -> Option { - let (kind, (start_idx, _)) = self.iter.next()?; - match kind { - FullCodeCharKind::Normal | FullCodeCharKind::InString => { - // Consume all the Normal code - while let Some(&(char_kind, _)) = self.iter.peek() { - if char_kind.is_comment() { - break; - } - let _ = self.iter.next(); - } - } - FullCodeCharKind::StartComment => { - // Consume the whole comment - while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {} - } - _ => panic!(), - } - let slice = match self.iter.peek() { - Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx], - None => &self.slice[start_idx..], - }; - Some(( - if kind.is_comment() { - CodeCharKind::Comment - } else { - CodeCharKind::Normal - }, - start_idx, - slice, - )) - } -} - -/// Iterator over an alternating sequence of functional and commented parts of -/// a string. The first item is always a, possibly zero length, subslice of -/// functional text. Line style comments contain their ending newlines. -pub struct CommentCodeSlices<'a> { - slice: &'a str, - last_slice_kind: CodeCharKind, - last_slice_end: usize, -} - -impl<'a> CommentCodeSlices<'a> { - pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { - CommentCodeSlices { - slice, - last_slice_kind: CodeCharKind::Comment, - last_slice_end: 0, - } - } -} - -impl<'a> Iterator for CommentCodeSlices<'a> { - type Item = (CodeCharKind, usize, &'a str); - - fn next(&mut self) -> Option { - if self.last_slice_end == self.slice.len() { - return None; - } - - let mut sub_slice_end = self.last_slice_end; - let mut first_whitespace = None; - let subslice = &self.slice[self.last_slice_end..]; - let mut iter = CharClasses::new(subslice.char_indices()); - - for (kind, (i, c)) in &mut iter { - let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal - && &subslice[..2] == "//" - && [' ', '\t'].contains(&c); - - if is_comment_connector && first_whitespace.is_none() { - first_whitespace = Some(i); - } - - if kind.to_codecharkind() == self.last_slice_kind && !is_comment_connector { - let last_index = match first_whitespace { - Some(j) => j, - None => i, - }; - sub_slice_end = self.last_slice_end + last_index; - break; - } - - if !is_comment_connector { - first_whitespace = None; - } - } - - if let (None, true) = (iter.next(), sub_slice_end == self.last_slice_end) { - // This was the last subslice. - sub_slice_end = match first_whitespace { - Some(i) => self.last_slice_end + i, - None => self.slice.len(), - }; - } - - let kind = match self.last_slice_kind { - CodeCharKind::Comment => CodeCharKind::Normal, - CodeCharKind::Normal => CodeCharKind::Comment, - }; - let res = ( - kind, - self.last_slice_end, - &self.slice[self.last_slice_end..sub_slice_end], - ); - self.last_slice_end = sub_slice_end; - self.last_slice_kind = kind; - - Some(res) - } -} - -/// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text -/// (if it fits in the width/offset, else return None), else return `new` -pub fn recover_comment_removed( - new: String, - span: Span, - context: &RewriteContext, -) -> Option { - let snippet = context.snippet(span); - if snippet != new && changed_comment_content(snippet, &new) { - // We missed some comments. Keep the original text. - Some(snippet.to_owned()) - } else { - Some(new) - } -} - -/// Return true if the two strings of code have the same payload of comments. -/// The payload of comments is everything in the string except: -/// - actual code (not comments) -/// - comment start/end marks -/// - whitespace -/// - '*' at the beginning of lines in block comments -fn changed_comment_content(orig: &str, new: &str) -> bool { - // Cannot write this as a fn since we cannot return types containing closures - let code_comment_content = |code| { - let slices = UngroupedCommentCodeSlices::new(code); - slices - .filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) - .flat_map(|(_, _, s)| CommentReducer::new(s)) - }; - let res = code_comment_content(orig).ne(code_comment_content(new)); - debug!( - "comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", - res, - orig, - new, - code_comment_content(orig).collect::(), - code_comment_content(new).collect::() - ); - res -} - -/// Iterator over the 'payload' characters of a comment. -/// It skips whitespace, comment start/end marks, and '*' at the beginning of lines. -/// The comment must be one comment, ie not more than one start mark (no multiple line comments, -/// for example). -struct CommentReducer<'a> { - is_block: bool, - at_start_line: bool, - iter: std::str::Chars<'a>, -} - -impl<'a> CommentReducer<'a> { - fn new(comment: &'a str) -> CommentReducer<'a> { - let is_block = comment.starts_with("/*"); - let comment = remove_comment_header(comment); - CommentReducer { - is_block, - at_start_line: false, // There are no supplementary '*' on the first line - iter: comment.chars(), - } - } -} - -impl<'a> Iterator for CommentReducer<'a> { - type Item = char; - fn next(&mut self) -> Option { - loop { - let mut c = self.iter.next()?; - if self.is_block && self.at_start_line { - while c.is_whitespace() { - c = self.iter.next()?; - } - // Ignore leading '*' - if c == '*' { - c = self.iter.next()?; - } - } else if c == '\n' { - self.at_start_line = true; - } - if !c.is_whitespace() { - return Some(c); - } - } - } -} - -fn remove_comment_header(comment: &str) -> &str { - if comment.starts_with("///") || comment.starts_with("//!") { - &comment[3..] - } else if comment.starts_with("//") { - &comment[2..] - } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) - || comment.starts_with("/*!") - { - &comment[3..comment.len() - 2] - } else { - assert!( - comment.starts_with("/*"), - format!("string '{}' is not a comment", comment) - ); - &comment[2..comment.len() - 2] - } -} - -#[cfg(test)] -mod test { - use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, - FindUncommented, FullCodeCharKind}; - use shape::{Indent, Shape}; - - #[test] - fn char_classes() { - let mut iter = CharClasses::new("//\n\n".chars()); - - assert_eq!((FullCodeCharKind::StartComment, '/'), iter.next().unwrap()); - assert_eq!((FullCodeCharKind::InComment, '/'), iter.next().unwrap()); - assert_eq!((FullCodeCharKind::EndComment, '\n'), iter.next().unwrap()); - assert_eq!((FullCodeCharKind::Normal, '\n'), iter.next().unwrap()); - assert_eq!(None, iter.next()); - } - - #[test] - fn comment_code_slices() { - let input = "code(); /* test */ 1 + 1"; - let mut iter = CommentCodeSlices::new(input); - - assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); - assert_eq!( - (CodeCharKind::Comment, 8, "/* test */"), - iter.next().unwrap() - ); - assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap()); - assert_eq!(None, iter.next()); - } - - #[test] - fn comment_code_slices_two() { - let input = "// comment\n test();"; - let mut iter = CommentCodeSlices::new(input); - - assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap()); - assert_eq!( - (CodeCharKind::Comment, 0, "// comment\n"), - iter.next().unwrap() - ); - assert_eq!( - (CodeCharKind::Normal, 11, " test();"), - iter.next().unwrap() - ); - assert_eq!(None, iter.next()); - } - - #[test] - fn comment_code_slices_three() { - let input = "1 // comment\n // comment2\n\n"; - let mut iter = CommentCodeSlices::new(input); - - assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap()); - assert_eq!( - (CodeCharKind::Comment, 2, "// comment\n // comment2\n"), - iter.next().unwrap() - ); - assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap()); - assert_eq!(None, iter.next()); - } - - #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] - fn format_comments() { - let mut config: ::config::Config = Default::default(); - config.set().wrap_comments(true); - config.set().normalize_comments(true); - - let comment = rewrite_comment(" //test", - true, - Shape::legacy(100, Indent::new(0, 100)), - &config).unwrap(); - assert_eq!("/* test */", comment); - - let comment = rewrite_comment("// comment on a", - false, - Shape::legacy(10, Indent::empty()), - &config).unwrap(); - assert_eq!("// comment\n// on a", comment); - - let comment = rewrite_comment("// A multi line comment\n // between args.", - false, - Shape::legacy(60, Indent::new(0, 12)), - &config).unwrap(); - assert_eq!("// A multi line comment\n // between args.", comment); - - let input = "// comment"; - let expected = - "/* comment */"; - let comment = rewrite_comment(input, - true, - Shape::legacy(9, Indent::new(0, 69)), - &config).unwrap(); - assert_eq!(expected, comment); - - let comment = rewrite_comment("/* trimmed */", - true, - Shape::legacy(100, Indent::new(0, 100)), - &config).unwrap(); - assert_eq!("/* trimmed */", comment); - } - - // This is probably intended to be a non-test fn, but it is not used. I'm - // keeping it around unless it helps us test stuff. - fn uncommented(text: &str) -> String { - CharClasses::new(text.chars()) - .filter_map(|(s, c)| match s { - FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), - _ => None, - }) - .collect() - } - - #[test] - fn test_uncommented() { - assert_eq!(&uncommented("abc/*...*/"), "abc"); - assert_eq!( - &uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), - "..ac\n" - ); - assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); - } - - #[test] - fn test_contains_comment() { - assert_eq!(contains_comment("abc"), false); - assert_eq!(contains_comment("abc // qsdf"), true); - assert_eq!(contains_comment("abc /* kqsdf"), true); - assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); - } - - #[test] - fn test_find_uncommented() { - fn check(haystack: &str, needle: &str, expected: Option) { - assert_eq!(expected, haystack.find_uncommented(needle)); - } - - check("/*/ */test", "test", Some(6)); - check("//test\ntest", "test", Some(7)); - check("/* comment only */", "whatever", None); - check( - "/* comment */ some text /* more commentary */ result", - "result", - Some(46), - ); - check("sup // sup", "p", Some(2)); - check("sup", "x", None); - check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); - check("/*sup yo? \n sup*/ sup", "p", Some(20)); - check("hel/*lohello*/lo", "hello", None); - check("acb", "ab", None); - check(",/*A*/ ", ",", Some(0)); - check("abc", "abc", Some(0)); - check("/* abc */", "abc", None); - check("/**/abc/* */", "abc", Some(4)); - check("\"/* abc */\"", "abc", Some(4)); - check("\"/* abc", "abc", Some(4)); - } -} diff --git a/rustfmt-core/src/expr.rs b/rustfmt-core/src/expr.rs deleted file mode 100644 index 8ce1166cfcd..00000000000 --- a/rustfmt-core/src/expr.rs +++ /dev/null @@ -1,2975 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; -use std::cmp::min; -use std::iter::repeat; - -use config::lists::*; -use syntax::{ast, ptr}; -use syntax::codemap::{BytePos, CodeMap, Span}; - -use chains::rewrite_chain; -use closures; -use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, FindUncommented}; -use config::{Config, ControlBraceStyle, IndentStyle}; -use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, - struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; -use macros::{rewrite_macro, MacroArg, MacroPosition}; -use patterns::{can_be_overflowed_pat, TuplePatField}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use string::{rewrite_string, StringFormat}; -use types::{can_be_overflowed_type, rewrite_path, PathContext}; -use utils::{colon_spaces, contains_skip, count_newlines, extra_offset, first_line_width, - inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, - paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, - wrap_str}; -use vertical::rewrite_with_alignment; -use visitor::FmtVisitor; - -impl Rewrite for ast::Expr { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - format_expr(self, ExprType::SubExpression, context, shape) - } -} - -#[derive(Copy, Clone, PartialEq)] -pub enum ExprType { - Statement, - SubExpression, -} - -pub fn format_expr( - expr: &ast::Expr, - expr_type: ExprType, - context: &RewriteContext, - shape: Shape, -) -> Option { - skip_out_of_file_lines_range!(context, expr.span); - - if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span()).to_owned()); - } - - let expr_rw = match expr.node { - ast::ExprKind::Array(ref expr_vec) => rewrite_array( - &ptr_vec_to_ref_vec(expr_vec), - mk_sp( - context.snippet_provider.span_after(expr.span, "["), - expr.span.hi(), - ), - context, - shape, - false, - ), - ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), - ast::ExprKind::Call(ref callee, ref args) => { - let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); - let callee_str = callee.rewrite(context, shape)?; - rewrite_call(context, &callee_str, args, inner_span, shape) - } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), - ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { - // FIXME: format comments between operands and operator - rewrite_pair( - &**lhs, - &**rhs, - PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), - context, - shape, - context.config.binop_separator(), - ) - } - ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( - context, - path, - fields, - base.as_ref().map(|e| &**e), - expr.span, - shape, - ), - ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) - } - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) - .and_then(|control_flow| control_flow.rewrite(context, shape)), - ast::ExprKind::Block(ref block) => { - match expr_type { - ExprType::Statement => { - if is_unsafe_block(block) { - block.rewrite(context, shape) - } else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { - // Rewrite block without trying to put it in a single line. - rw - } else { - let prefix = block_prefix(context, block, shape)?; - rewrite_block_with_visitor(context, &prefix, block, shape, true) - } - } - ExprType::SubExpression => block.rewrite(context, shape), - } - } - ast::ExprKind::Match(ref cond, ref arms) => { - rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs) - } - ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) - } - ast::ExprKind::Assign(ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, None, shape) - } - ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), shape) - } - ast::ExprKind::Continue(ref opt_label) => { - let id_str = match *opt_label { - Some(label) => format!(" {}", label.ident), - None => String::new(), - }; - Some(format!("continue{}", id_str)) - } - ast::ExprKind::Break(ref opt_label, ref opt_expr) => { - let id_str = match *opt_label { - Some(label) => format!(" {}", label.ident), - None => String::new(), - }; - - if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) - } else { - Some(format!("break{}", id_str)) - } - } - ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape) - } else { - Some("yield".to_string()) - }, - ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { - closures::rewrite_closure( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, - ) - } - ast::ExprKind::Try(..) - | ast::ExprKind::Field(..) - | ast::ExprKind::TupField(..) - | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), - ast::ExprKind::Mac(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - }) - } - ast::ExprKind::Ret(None) => Some("return".to_owned()), - ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, shape) - } - ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), - ast::ExprKind::AddrOf(mutability, ref expr) => { - rewrite_expr_addrof(context, mutability, expr, shape) - } - ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( - &**expr, - &**ty, - PairParts::new("", " as ", ""), - context, - shape, - SeparatorPlace::Front, - ), - ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( - &**expr, - &**ty, - PairParts::new("", ": ", ""), - context, - shape, - SeparatorPlace::Back, - ), - ast::ExprKind::Index(ref expr, ref index) => { - rewrite_index(&**expr, &**index, context, shape) - } - ast::ExprKind::Repeat(ref expr, ref repeats) => { - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - rewrite_pair( - &**expr, - &**repeats, - PairParts::new(lbr, "; ", rbr), - context, - shape, - SeparatorPlace::Back, - ) - } - ast::ExprKind::Range(ref lhs, ref rhs, limits) => { - let delim = match limits { - ast::RangeLimits::HalfOpen => "..", - ast::RangeLimits::Closed => "..=", - }; - - fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { - match lhs.node { - ast::ExprKind::Lit(ref lit) => match lit.node { - ast::LitKind::FloatUnsuffixed(..) => { - context.snippet(lit.span).ends_with('.') - } - _ => false, - }, - _ => false, - } - } - - match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { - (Some(lhs), Some(rhs)) => { - let sp_delim = if context.config.spaces_around_ranges() { - format!(" {} ", delim) - } else if needs_space_before_range(context, lhs) { - format!(" {}", delim) - } else { - delim.to_owned() - }; - rewrite_pair( - &*lhs, - &*rhs, - PairParts::new("", &sp_delim, ""), - context, - shape, - context.config.binop_separator(), - ) - } - (None, Some(rhs)) => { - let sp_delim = if context.config.spaces_around_ranges() { - format!("{} ", delim) - } else { - delim.to_owned() - }; - rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) - } - (Some(lhs), None) => { - let sp_delim = if context.config.spaces_around_ranges() { - format!(" {}", delim) - } else { - delim.to_owned() - }; - rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) - } - (None, None) => Some(delim.to_owned()), - } - } - // We do not format these expressions yet, but they should still - // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - Some(context.snippet(expr.span).to_owned()) - } - ast::ExprKind::Catch(ref block) => { - if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { - rw - } else { - // 9 = `do catch ` - let budget = shape.width.checked_sub(9).unwrap_or(0); - Some(format!( - "{}{}", - "do catch ", - block.rewrite(context, Shape::legacy(budget, shape.indent))? - )) - } - } - }; - - expr_rw - .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) - .and_then(|expr_str| { - let attrs = outer_attributes(&expr.attrs); - let attrs_str = attrs.rewrite(context, shape)?; - let span = mk_sp( - attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), - expr.span.lo(), - ); - combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) - }) -} - -#[derive(new, Clone, Copy)] -pub struct PairParts<'a> { - prefix: &'a str, - infix: &'a str, - suffix: &'a str, -} - -pub fn rewrite_pair( - lhs: &LHS, - rhs: &RHS, - pp: PairParts, - context: &RewriteContext, - shape: Shape, - separator_place: SeparatorPlace, -) -> Option -where - LHS: Rewrite, - RHS: Rewrite, -{ - let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), - SeparatorPlace::Front => shape.used_width(), - }; - let lhs_shape = Shape { - width: context.budget(lhs_overhead), - ..shape - }; - let lhs_result = lhs.rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; - - // Try to the both lhs and rhs on the same line. - let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + pp.infix.len()) - .and_then(|s| s.sub_width(pp.suffix.len())) - .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); - if let Some(ref rhs_result) = rhs_orig_result { - // If the rhs looks like block expression, we allow it to stay on the same line - // with the lhs even if it is multi-lined. - let allow_same_line = rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); - if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) + pp.infix.len() - + first_line_width(rhs_result) + pp.suffix.len(); - if one_line_width <= shape.width { - return Some(format!( - "{}{}{}{}", - lhs_result, pp.infix, rhs_result, pp.suffix - )); - } - } - } - - // We have to use multiple lines. - // Re-evaluate the rhs because we have more space now: - let mut rhs_shape = match context.config.indent_style() { - IndentStyle::Visual => shape - .sub_width(pp.suffix.len() + pp.prefix.len())? - .visual_indent(pp.prefix.len()), - IndentStyle::Block => { - // Try to calculate the initial constraint on the right hand side. - let rhs_overhead = shape.rhs_overhead(context.config); - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead)? - } - }; - let infix = match separator_place { - SeparatorPlace::Back => pp.infix.trim_right(), - SeparatorPlace::Front => pp.infix.trim_left(), - }; - if separator_place == SeparatorPlace::Front { - rhs_shape = rhs_shape.offset_left(infix.len())?; - } - let rhs_result = rhs.rewrite(context, rhs_shape)?; - let indent_str = rhs_shape.indent.to_string_with_newline(context.config); - let infix_with_sep = match separator_place { - SeparatorPlace::Back => format!("{}{}", infix, indent_str), - SeparatorPlace::Front => format!("{}{}", indent_str, infix), - }; - Some(format!( - "{}{}{}{}", - lhs_result, infix_with_sep, rhs_result, pp.suffix - )) -} - -pub fn rewrite_array( - exprs: &[&T], - span: Span, - context: &RewriteContext, - shape: Shape, - trailing_comma: bool, -) -> Option { - let bracket_size = if context.config.spaces_within_parens_and_brackets() { - 2 // "[ " - } else { - 1 // "[" - }; - - let nested_shape = match context.config.indent_style() { - IndentStyle::Block => shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1)?, - IndentStyle::Visual => shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2)?, - }; - - let items = itemize_list( - context.snippet_provider, - exprs.iter(), - "]", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - span.lo(), - span.hi(), - false, - ).collect::>(); - - if items.is_empty() { - if context.config.spaces_within_parens_and_brackets() { - return Some("[ ]".to_string()); - } else { - return Some("[]".to_string()); - } - } - - let tactic = array_tactic(context, shape, nested_shape, exprs, &items, bracket_size); - let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro && !exprs.is_empty() { - let ends_with_bracket = context.snippet(span).ends_with(']'); - let bracket_offset = if ends_with_bracket { 1 } else { 0 }; - let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); - let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?; - if &snippet[last_char_index..last_char_index + 1] == "," { - SeparatorTactic::Always - } else { - SeparatorTactic::Never - } - } else if context.config.indent_style() == IndentStyle::Visual { - SeparatorTactic::Never - } else { - SeparatorTactic::Vertical - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline, - preserve_newline: false, - config: context.config, - }; - let list_str = write_list(&items, &fmt)?; - - let result = if context.config.indent_style() == IndentStyle::Visual - || tactic == DefinitiveListTactic::Horizontal - { - if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { - format!("[ {} ]", list_str) - } else { - format!("[{}]", list_str) - } - } else { - format!( - "[{}{}{}]", - nested_shape.indent.to_string_with_newline(context.config), - list_str, - shape.block().indent.to_string_with_newline(context.config) - ) - }; - - Some(result) -} - -fn array_tactic( - context: &RewriteContext, - shape: Shape, - nested_shape: Shape, - exprs: &[&T], - items: &[ListItem], - bracket_size: usize, -) -> DefinitiveListTactic { - let has_long_item = items - .iter() - .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - - match context.config.indent_style() { - IndentStyle::Block => { - let tactic = match shape.width.checked_sub(2 * bracket_size) { - Some(width) => { - let tactic = ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ); - definitive_tactic(items, tactic, Separator::Comma, width) - } - None => DefinitiveListTactic::Vertical, - }; - if tactic == DefinitiveListTactic::Vertical && !has_long_item - && is_every_args_simple(exprs) - { - DefinitiveListTactic::Mixed - } else { - tactic - } - } - IndentStyle::Visual => { - if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic( - items, - ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ), - Separator::Comma, - nested_shape.width, - ) - } else { - DefinitiveListTactic::Mixed - } - } - } -} - -fn nop_block_collapse(block_str: Option, budget: usize) -> Option { - debug!("nop_block_collapse {:?} {}", block_str, budget); - block_str.map(|block_str| { - if block_str.starts_with('{') && budget >= 2 - && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) - { - "{}".to_owned() - } else { - block_str.to_owned() - } - }) -} - -fn rewrite_empty_block( - context: &RewriteContext, - block: &ast::Block, - shape: Shape, -) -> Option { - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 - { - return Some("{}".to_owned()); - } - - // If a block contains only a single-line comment, then leave it on one line. - let user_str = context.snippet(block.span); - let user_str = user_str.trim(); - if user_str.starts_with('{') && user_str.ends_with('}') { - let comment_str = user_str[1..user_str.len() - 1].trim(); - if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") - && comment_str.len() + 4 <= shape.width - { - return Some(format!("{{ {} }}", comment_str)); - } - } - - None -} - -fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> Option { - Some(match block.rules { - ast::BlockCheckMode::Unsafe(..) => { - let snippet = context.snippet(block.span); - let open_pos = snippet.find_uncommented("{")?; - // Extract comment between unsafe and block start. - let trimmed = &snippet[6..open_pos].trim(); - - if !trimmed.is_empty() { - // 9 = "unsafe {".len(), 7 = "unsafe ".len() - let budget = shape.width.checked_sub(9)?; - format!( - "unsafe {} ", - rewrite_comment( - trimmed, - true, - Shape::legacy(budget, shape.indent + 7), - context.config, - )? - ) - } else { - "unsafe ".to_owned() - } - } - ast::BlockCheckMode::Default => String::new(), - }) -} - -fn rewrite_single_line_block( - context: &RewriteContext, - prefix: &str, - block: &ast::Block, - shape: Shape, -) -> Option { - if is_simple_block(block, context.codemap) { - let expr_shape = shape.offset_left(last_line_width(prefix))?; - let expr_str = block.stmts[0].rewrite(context, expr_shape)?; - let result = format!("{}{{ {} }}", prefix, expr_str); - if result.len() <= shape.width && !result.contains('\n') { - return Some(result); - } - } - None -} - -pub fn rewrite_block_with_visitor( - context: &RewriteContext, - prefix: &str, - block: &ast::Block, - shape: Shape, - has_braces: bool, -) -> Option { - if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { - return rw; - } - - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = shape.indent; - visitor.is_if_else_block = context.is_if_else_block; - match block.rules { - ast::BlockCheckMode::Unsafe(..) => { - let snippet = context.snippet(block.span); - let open_pos = snippet.find_uncommented("{")?; - visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) - } - ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), - } - - visitor.visit_block(block, None, has_braces); - Some(format!("{}{}", prefix, visitor.buffer)) -} - -impl Rewrite for ast::Block { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - // shape.width is used only for the single line case: either the empty block `{}`, - // or an unsafe expression `unsafe { e }`. - if let rw @ Some(_) = rewrite_empty_block(context, self, shape) { - return rw; - } - - let prefix = block_prefix(context, self, shape)?; - - let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); - if let Some(ref result_str) = result { - if result_str.lines().count() <= 3 { - if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { - return rw; - } - } - } - - result - } -} - -impl Rewrite for ast::Stmt { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - skip_out_of_file_lines_range!(context, self.span()); - - let result = match self.node { - ast::StmtKind::Local(ref local) => local.rewrite(context, shape), - ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { - let suffix = if semicolon_for_stmt(context, self) { - ";" - } else { - "" - }; - - let shape = shape.sub_width(suffix.len())?; - format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) - } - ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, - }; - result.and_then(|res| recover_comment_removed(res, self.span(), context)) - } -} - -// Rewrite condition if the given expression has one. -pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { - match expr.node { - ast::ExprKind::Match(ref cond, _) => { - // `match `cond` {` - let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, - IndentStyle::Block => shape.offset_left(8)?, - }; - cond.rewrite(context, cond_shape) - } - _ => to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { - let alt_block_sep = - String::from("\n") + &shape.indent.block_only().to_string(context.config); - control_flow - .rewrite_cond(context, shape, &alt_block_sep) - .and_then(|rw| Some(rw.0)) - }), - } -} - -// Abstraction over control flow expressions -#[derive(Debug)] -struct ControlFlow<'a> { - cond: Option<&'a ast::Expr>, - block: &'a ast::Block, - else_block: Option<&'a ast::Expr>, - label: Option, - pat: Option<&'a ast::Pat>, - keyword: &'a str, - matcher: &'a str, - connector: &'a str, - allow_single_line: bool, - // True if this is an `if` expression in an `else if` :-( hacky - nested_if: bool, - span: Span, -} - -fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { - match expr.node { - ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( - cond, - None, - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - )), - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { - Some(ControlFlow::new_if( - cond, - Some(pat), - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - )) - } - ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { - Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) - } - ast::ExprKind::Loop(ref block, label) => { - Some(ControlFlow::new_loop(block, label, expr.span)) - } - ast::ExprKind::While(ref cond, ref block, label) => { - Some(ControlFlow::new_while(None, cond, block, label, expr.span)) - } - ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( - ControlFlow::new_while(Some(pat), cond, block, label, expr.span), - ), - _ => None, - } -} - -impl<'a> ControlFlow<'a> { - fn new_if( - cond: &'a ast::Expr, - pat: Option<&'a ast::Pat>, - block: &'a ast::Block, - else_block: Option<&'a ast::Expr>, - allow_single_line: bool, - nested_if: bool, - span: Span, - ) -> ControlFlow<'a> { - ControlFlow { - cond: Some(cond), - block, - else_block, - label: None, - pat, - keyword: "if", - matcher: match pat { - Some(..) => "let", - None => "", - }, - connector: " =", - allow_single_line, - nested_if, - span, - } - } - - fn new_loop(block: &'a ast::Block, label: Option, span: Span) -> ControlFlow<'a> { - ControlFlow { - cond: None, - block, - else_block: None, - label, - pat: None, - keyword: "loop", - matcher: "", - connector: "", - allow_single_line: false, - nested_if: false, - span, - } - } - - fn new_while( - pat: Option<&'a ast::Pat>, - cond: &'a ast::Expr, - block: &'a ast::Block, - label: Option, - span: Span, - ) -> ControlFlow<'a> { - ControlFlow { - cond: Some(cond), - block, - else_block: None, - label, - pat, - keyword: "while", - matcher: match pat { - Some(..) => "let", - None => "", - }, - connector: " =", - allow_single_line: false, - nested_if: false, - span, - } - } - - fn new_for( - pat: &'a ast::Pat, - cond: &'a ast::Expr, - block: &'a ast::Block, - label: Option, - span: Span, - ) -> ControlFlow<'a> { - ControlFlow { - cond: Some(cond), - block, - else_block: None, - label, - pat: Some(pat), - keyword: "for", - matcher: "", - connector: " in", - allow_single_line: false, - nested_if: false, - span, - } - } - - fn rewrite_single_line( - &self, - pat_expr_str: &str, - context: &RewriteContext, - width: usize, - ) -> Option { - assert!(self.allow_single_line); - let else_block = self.else_block?; - let fixed_cost = self.keyword.len() + " { } else { }".len(); - - if let ast::ExprKind::Block(ref else_node) = else_block.node { - if !is_simple_block(self.block, context.codemap) - || !is_simple_block(else_node, context.codemap) - || pat_expr_str.contains('\n') - { - return None; - } - - let new_width = width.checked_sub(pat_expr_str.len() + fixed_cost)?; - let expr = &self.block.stmts[0]; - let if_str = expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; - - let new_width = new_width.checked_sub(if_str.len())?; - let else_expr = &else_node.stmts[0]; - let else_str = else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; - - if if_str.contains('\n') || else_str.contains('\n') { - return None; - } - - let result = format!( - "{} {} {{ {} }} else {{ {} }}", - self.keyword, pat_expr_str, if_str, else_str - ); - - if result.len() <= width { - return Some(result); - } - } - - None - } -} - -impl<'a> ControlFlow<'a> { - fn rewrite_cond( - &self, - context: &RewriteContext, - shape: Shape, - alt_block_sep: &str, - ) -> Option<(String, usize)> { - // Do not take the rhs overhead from the upper expressions into account - // when rewriting pattern. - let new_width = context - .config - .max_width() - .checked_sub(shape.used_width()) - .unwrap_or(0); - let fresh_shape = Shape { - width: new_width, - ..shape - }; - let constr_shape = if self.nested_if { - // We are part of an if-elseif-else chain. Our constraints are tightened. - // 7 = "} else " .len() - fresh_shape.offset_left(7)? - } else { - fresh_shape - }; - - let label_string = rewrite_label(self.label); - // 1 = space after keyword. - let offset = self.keyword.len() + label_string.len() + 1; - - let pat_expr_string = match self.cond { - Some(cond) => rewrite_pat_expr( - context, - self.pat, - cond, - self.matcher, - self.connector, - self.keyword, - constr_shape, - offset, - )?, - None => String::new(), - }; - - let brace_overhead = - if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { - // 2 = ` {` - 2 - } else { - 0 - }; - let one_line_budget = context - .config - .max_width() - .checked_sub(constr_shape.used_width() + offset + brace_overhead) - .unwrap_or(0); - let force_newline_brace = (pat_expr_string.contains('\n') - || pat_expr_string.len() > one_line_budget) - && !last_line_extendable(&pat_expr_string); - - // Try to format if-else on single line. - if self.allow_single_line - && context - .config - .width_heuristics() - .single_line_if_else_max_width > 0 - { - let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); - - if let Some(cond_str) = trial { - if cond_str.len() - <= context - .config - .width_heuristics() - .single_line_if_else_max_width - { - return Some((cond_str, 0)); - } - } - } - - let cond_span = if let Some(cond) = self.cond { - cond.span - } else { - mk_sp(self.block.span.lo(), self.block.span.lo()) - }; - - // `for event in event` - // Do not include label in the span. - let lo = self.label.map_or(self.span.lo(), |label| label.span.hi()); - let between_kwd_cond = mk_sp( - context - .snippet_provider - .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), - self.pat.map_or(cond_span.lo(), |p| { - if self.matcher.is_empty() { - p.span.lo() - } else { - context - .snippet_provider - .span_before(self.span, self.matcher.trim()) - } - }), - ); - - let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); - - let after_cond_comment = - extract_comment(mk_sp(cond_span.hi(), self.block.span.lo()), context, shape); - - let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { - "" - } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine - || force_newline_brace - { - alt_block_sep - } else { - " " - }; - - let used_width = if pat_expr_string.contains('\n') { - last_line_width(&pat_expr_string) - } else { - // 2 = spaces after keyword and condition. - label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 - }; - - Some(( - format!( - "{}{}{}{}{}", - label_string, - self.keyword, - between_kwd_cond_comment.as_ref().map_or( - if pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { - "" - } else { - " " - }, - |s| &**s, - ), - pat_expr_string, - after_cond_comment.as_ref().map_or(block_sep, |s| &**s) - ), - used_width, - )) - } -} - -impl<'a> Rewrite for ControlFlow<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!("ControlFlow::rewrite {:?} {:?}", self, shape); - - let alt_block_sep = &shape.indent.to_string_with_newline(context.config); - let (cond_str, used_width) = self.rewrite_cond(context, shape, alt_block_sep)?; - // If `used_width` is 0, it indicates that whole control flow is written in a single line. - if used_width == 0 { - return Some(cond_str); - } - - let block_width = shape.width.checked_sub(used_width).unwrap_or(0); - // This is used only for the empty block case: `{}`. So, we use 1 if we know - // we should avoid the single line case. - let block_width = if self.else_block.is_some() || self.nested_if { - min(1, block_width) - } else { - block_width - }; - let block_shape = Shape { - width: block_width, - ..shape - }; - let mut block_context = context.clone(); - block_context.is_if_else_block = self.else_block.is_some(); - let block_str = - rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?; - - let mut result = format!("{}{}", cond_str, block_str); - - if let Some(else_block) = self.else_block { - let shape = Shape::indented(shape.indent, context.config); - let mut last_in_chain = false; - let rewrite = match else_block.node { - // If the else expression is another if-else expression, prevent it - // from being formatted on a single line. - // Note how we're passing the original shape, as the - // cost of "else" should not cascade. - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if( - cond, - Some(pat), - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) - } - ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if( - cond, - None, - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) - } - _ => { - last_in_chain = true; - // When rewriting a block, the width is only used for single line - // blocks, passing 1 lets us avoid that. - let else_shape = Shape { - width: min(1, shape.width), - ..shape - }; - format_expr(else_block, ExprType::Statement, context, else_shape) - } - }; - - let between_kwd_else_block = mk_sp( - self.block.span.hi(), - context - .snippet_provider - .span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), - ); - let between_kwd_else_block_comment = - extract_comment(between_kwd_else_block, context, shape); - - let after_else = mk_sp( - context - .snippet_provider - .span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), - else_block.span.lo(), - ); - let after_else_comment = extract_comment(after_else, context, shape); - - let between_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => { - &*alt_block_sep - } - ControlBraceStyle::AlwaysSameLine => " ", - }; - let after_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, - _ => " ", - }; - - result.push_str(&format!( - "{}else{}", - between_kwd_else_block_comment - .as_ref() - .map_or(between_sep, |s| &**s), - after_else_comment.as_ref().map_or(after_sep, |s| &**s), - )); - result.push_str(&rewrite?); - } - - Some(result) - } -} - -fn rewrite_label(opt_label: Option) -> Cow<'static, str> { - match opt_label { - Some(label) => Cow::from(format!("{}: ", label.ident)), - None => Cow::from(""), - } -} - -fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { - match rewrite_missing_comment(span, shape, context) { - Some(ref comment) if !comment.is_empty() => Some(format!( - "{indent}{}{indent}", - comment, - indent = shape.indent.to_string_with_newline(context.config) - )), - _ => None, - } -} - -pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { - let snippet = codemap.span_to_snippet(block.span).unwrap(); - contains_comment(&snippet) -} - -// Checks that a block contains no statements, an expression and no comments. -// FIXME: incorrectly returns false when comment is contained completely within -// the expression. -pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { - (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, codemap)) -} - -/// Checks whether a block contains at most one statement or expression, and no comments. -pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.len() <= 1 && !block_contains_comment(block, codemap) -} - -/// Checks whether a block contains no statements, expressions, or comments. -pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { - block.stmts.is_empty() && !block_contains_comment(block, codemap) -} - -pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::StmtKind::Expr(..) => true, - _ => false, - } -} - -pub fn is_unsafe_block(block: &ast::Block) -> bool { - if let ast::BlockCheckMode::Unsafe(..) = block.rules { - true - } else { - false - } -} - -// A simple wrapper type against ast::Arm. Used inside write_list(). -struct ArmWrapper<'a> { - pub arm: &'a ast::Arm, - // True if the arm is the last one in match expression. Used to decide on whether we should add - // trailing comma to the match arm when `config.trailing_comma() == Never`. - pub is_last: bool, -} - -impl<'a> ArmWrapper<'a> { - pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> { - ArmWrapper { arm, is_last } - } -} - -impl<'a> Rewrite for ArmWrapper<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) - } -} - -fn rewrite_match( - context: &RewriteContext, - cond: &ast::Expr, - arms: &[ast::Arm], - shape: Shape, - span: Span, - attrs: &[ast::Attribute], -) -> Option { - // Do not take the rhs overhead from the upper expressions into account - // when rewriting match condition. - let cond_shape = Shape { - width: context.budget(shape.used_width()), - ..shape - }; - // 6 = `match ` - let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => cond_shape.shrink_left(6)?, - IndentStyle::Block => cond_shape.offset_left(6)?, - }; - let cond_str = cond.rewrite(context, cond_shape)?; - let alt_block_sep = &shape.indent.to_string_with_newline(context.config); - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => alt_block_sep, - _ if last_line_extendable(&cond_str) => " ", - // 2 = ` {` - _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => alt_block_sep, - _ => " ", - }; - - let nested_indent_str = shape - .indent - .block_indent(context.config) - .to_string(context.config); - // Inner attributes. - let inner_attrs = &inner_attributes(attrs); - let inner_attrs_str = if inner_attrs.is_empty() { - String::new() - } else { - inner_attrs - .rewrite(context, shape) - .map(|s| format!("{}{}\n", nested_indent_str, s))? - }; - - let open_brace_pos = if inner_attrs.is_empty() { - let hi = if arms.is_empty() { - span.hi() - } else { - arms[0].span().lo() - }; - context - .snippet_provider - .span_after(mk_sp(cond.span.hi(), hi), "{") - } else { - inner_attrs[inner_attrs.len() - 1].span().hi() - }; - - if arms.is_empty() { - let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); - if snippet.trim().is_empty() { - Some(format!("match {} {{}}", cond_str)) - } else { - // Empty match with comments or inner attributes? We are not going to bother, sorry ;) - Some(context.snippet(span).to_owned()) - } - } else { - Some(format!( - "match {}{}{{\n{}{}{}\n{}}}", - cond_str, - block_sep, - inner_attrs_str, - nested_indent_str, - rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, - shape.indent.to_string(context.config), - )) - } -} - -fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { - if is_last && config.trailing_comma() == SeparatorTactic::Never { - "" - } else if config.match_block_trailing_comma() { - "," - } else if let ast::ExprKind::Block(ref block) = body.node { - if let ast::BlockCheckMode::Default = block.rules { - "" - } else { - "," - } - } else { - "," - } -} - -fn rewrite_match_arms( - context: &RewriteContext, - arms: &[ast::Arm], - shape: Shape, - span: Span, - open_brace_pos: BytePos, -) -> Option { - let arm_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - - let arm_len = arms.len(); - let is_last_iter = repeat(false) - .take(arm_len.checked_sub(1).unwrap_or(0)) - .chain(repeat(true)); - let items = itemize_list( - context.snippet_provider, - arms.iter() - .zip(is_last_iter) - .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), - "}", - "|", - |arm| arm.arm.span().lo(), - |arm| arm.arm.span().hi(), - |arm| arm.rewrite(context, arm_shape), - open_brace_pos, - span.hi(), - false, - ); - let arms_vec: Vec<_> = items.collect(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - - write_list(&arms_vec, &fmt) -} - -fn rewrite_match_arm( - context: &RewriteContext, - arm: &ast::Arm, - shape: Shape, - is_last: bool, -) -> Option { - let (missing_span, attrs_str) = if !arm.attrs.is_empty() { - if contains_skip(&arm.attrs) { - let (_, body) = flatten_arm_body(context, &arm.body); - // `arm.span()` does not include trailing comma, add it manually. - return Some(format!( - "{}{}", - context.snippet(arm.span()), - arm_comma(context.config, body, is_last), - )); - } - let missing_span = mk_sp( - arm.attrs[arm.attrs.len() - 1].span.hi(), - arm.pats[0].span.lo(), - ); - (missing_span, arm.attrs.rewrite(context, shape)?) - } else { - (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) - }; - let pats_str = rewrite_match_pattern( - context, - &arm.pats, - &arm.guard, - arm.beginning_vert.is_some(), - shape, - ).and_then(|pats_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &pats_str, - missing_span, - shape, - false, - ) - })?; - rewrite_match_body( - context, - &arm.body, - &pats_str, - shape, - arm.guard.is_some(), - is_last, - ) -} - -/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: -/// -/// [small, ntp]: -/// - single token -/// - `&[single-line, ntp]` -/// -/// [small]: -/// - `[small, ntp]` -/// - unary tuple constructor `([small, ntp])` -/// - `&[small]` -fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { - // We also require that the pattern is reasonably 'small' with its literal width. - pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) -} - -fn is_short_pattern_inner(pat: &ast::Pat) -> bool { - match pat.node { - ast::PatKind::Wild | ast::PatKind::Lit(_) => true, - ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), - ast::PatKind::Struct(..) - | ast::PatKind::Mac(..) - | ast::PatKind::Slice(..) - | ast::PatKind::Path(..) - | ast::PatKind::Range(..) => false, - ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, - ast::PatKind::TupleStruct(ref path, ref subpats, _) => { - path.segments.len() <= 1 && subpats.len() <= 1 - } - ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p), - } -} - -fn rewrite_match_pattern( - context: &RewriteContext, - pats: &[ptr::P], - guard: &Option>, - has_beginning_vert: bool, - shape: Shape, -) -> Option { - // Patterns - // 5 = ` => {` - // 2 = `| ` - let pat_shape = shape - .sub_width(5)? - .offset_left(if has_beginning_vert { 2 } else { 0 })?; - - let pat_strs = pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>()?; - - let use_mixed_layout = pats.iter() - .zip(pat_strs.iter()) - .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = if use_mixed_layout { - DefinitiveListTactic::Mixed - } else { - definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::VerticalBar, - pat_shape.width, - ) - }; - let fmt = ListFormatting { - tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - separator_place: context.config.binop_separator(), - shape: pat_shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - let pats_str = write_list(&items, &fmt)?; - let beginning_vert = if has_beginning_vert { "| " } else { "" }; - - // Guard - let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; - - Some(format!("{}{}{}", beginning_vert, pats_str, guard_str)) -} - -// (extend, body) -// @extend: true if the arm body can be put next to `=>` -// @body: flattened body, if the body is block with a single expression -fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { - match body.node { - ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => - { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - ( - !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), - &*expr, - ) - } else { - (false, &*body) - } - } - _ => ( - !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), - &*body, - ), - } -} - -fn rewrite_match_body( - context: &RewriteContext, - body: &ptr::P, - pats_str: &str, - shape: Shape, - has_guard: bool, - is_last: bool, -) -> Option { - let (extend, body) = flatten_arm_body(context, body); - let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { - (true, is_empty_block(block, context.codemap)) - } else { - (false, false) - }; - - let comma = arm_comma(context.config, body, is_last); - let alt_block_sep = &shape.indent.to_string_with_newline(context.config); - - let combine_orig_body = |body_str: &str| { - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, - _ => " ", - }; - - Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) - }; - - let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; - let next_line_indent = if !is_block || is_empty_block { - shape.indent.block_indent(context.config) - } else { - shape.indent - }; - let combine_next_line_body = |body_str: &str| { - if is_block { - return Some(format!( - "{} =>{}{}", - pats_str, - next_line_indent.to_string_with_newline(context.config), - body_str - )); - } - - let indent_str = shape.indent.to_string_with_newline(context.config); - let nested_indent_str = next_line_indent.to_string_with_newline(context.config); - let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { - let comma = if context.config.match_block_trailing_comma() { - "," - } else { - "" - }; - ("{", format!("{}}}{}", indent_str, comma)) - } else { - ("", String::from(",")) - }; - - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), - _ if body_prefix.is_empty() => "".to_owned(), - _ if forbid_same_line => format!("{}{}", alt_block_sep, body_prefix), - _ => format!(" {}", body_prefix), - } + &nested_indent_str; - - Some(format!( - "{} =>{}{}{}", - pats_str, block_sep, body_str, body_suffix - )) - }; - - // Let's try and get the arm body on the same line as the condition. - // 4 = ` => `.len() - let orig_body_shape = shape - .offset_left(extra_offset(pats_str, shape) + 4) - .and_then(|shape| shape.sub_width(comma.len())); - let orig_body = if let Some(body_shape) = orig_body_shape { - let rewrite = nop_block_collapse( - format_expr(body, ExprType::Statement, context, body_shape), - body_shape.width, - ); - - match rewrite { - Some(ref body_str) - if !forbid_same_line - && (is_block - || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => - { - return combine_orig_body(body_str); - } - _ => rewrite, - } - } else { - None - }; - let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); - - // Try putting body on the next line and see if it looks better. - let next_line_body_shape = Shape::indented(next_line_indent, context.config); - let next_line_body = nop_block_collapse( - format_expr(body, ExprType::Statement, context, next_line_body_shape), - next_line_body_shape.width, - ); - match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) - if forbid_same_line || prefer_next_line(orig_str, next_line_str) => - { - combine_next_line_body(next_line_str) - } - (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { - combine_orig_body(orig_str) - } - (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { - combine_next_line_body(next_line_str) - } - (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), - (None, None) => None, - (Some(ref orig_str), _) => combine_orig_body(orig_str), - } -} - -// The `if ...` guard on a match arm. -fn rewrite_guard( - context: &RewriteContext, - guard: &Option>, - shape: Shape, - // The amount of space used up on this line for the pattern in - // the arm (excludes offset). - pattern_width: usize, -) -> Option { - if let Some(ref guard) = *guard { - // First try to fit the guard string on the same line as the pattern. - // 4 = ` if `, 5 = ` => {` - let cond_shape = shape - .offset_left(pattern_width + 4) - .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { - return Some(format!(" if {}", cond_str)); - } - } - } - - // Not enough space to put the guard after the pattern, try a newline. - // 3 = `if `, 5 = ` => {` - let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) - .offset_left(3) - .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - return Some(format!( - "{}if {}", - cond_shape.indent.to_string_with_newline(context.config), - cond_str - )); - } - } - - None - } else { - Some(String::new()) - } -} - -fn rewrite_pat_expr( - context: &RewriteContext, - pat: Option<&ast::Pat>, - expr: &ast::Expr, - matcher: &str, - // Connecting piece between pattern and expression, - // *without* trailing space. - connector: &str, - keyword: &str, - shape: Shape, - offset: usize, -) -> Option { - debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); - let cond_shape = shape.offset_left(offset)?; - if let Some(pat) = pat { - let matcher = if matcher.is_empty() { - matcher.to_owned() - } else { - format!("{} ", matcher) - }; - let pat_shape = cond_shape - .offset_left(matcher.len())? - .sub_width(connector.len())?; - let pat_string = pat.rewrite(context, pat_shape)?; - let result = format!("{}{}{}", matcher, pat_string, connector); - return rewrite_assign_rhs(context, result, expr, cond_shape); - } - - let expr_rw = expr.rewrite(context, cond_shape); - // The expression may (partially) fit on the current line. - // We do not allow splitting between `if` and condition. - if keyword == "if" || expr_rw.is_some() { - return expr_rw; - } - - // The expression won't fit on the current line, jump to next. - let nested_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); - expr.rewrite(context, nested_shape) - .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw)) -} - -fn can_extend_match_arm_body(body: &ast::Expr) -> bool { - match body.node { - // We do not allow `if` to stay on the same line, since we could easily mistake - // `pat => if cond { ... }` and `pat if cond => { ... }`. - ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, - ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::Match(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Closure(..) - | ast::ExprKind::Array(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Mac(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::Tup(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), - _ => false, - } -} - -pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { - match l.node { - ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), - _ => wrap_str( - context.snippet(l.span).to_owned(), - context.config.max_width(), - shape, - ), - } -} - -fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { - let string_lit = context.snippet(span); - - if !context.config.format_strings() { - if string_lit - .lines() - .rev() - .skip(1) - .all(|line| line.ends_with('\\')) - { - let new_indent = shape.visual_indent(1).indent; - let indented_string_lit = String::from( - string_lit - .lines() - .map(|line| { - format!( - "{}{}", - new_indent.to_string(context.config), - line.trim_left() - ) - }) - .collect::>() - .join("\n") - .trim_left(), - ); - return wrap_str(indented_string_lit, context.config.max_width(), shape); - } else { - return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); - } - } - - // Remove the quote characters. - let str_lit = &string_lit[1..string_lit.len() - 1]; - - rewrite_string( - str_lit, - &StringFormat::new(shape.visual_indent(0), context.config), - None, - ) -} - -/// A list of `format!`-like macros, that take a long format string and a list of arguments to -/// format. -/// -/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of -/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, -/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). -const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ - // format! like macros - // From the Rust Standard Library. - ("eprint!", 0), - ("eprintln!", 0), - ("format!", 0), - ("format_args!", 0), - ("print!", 0), - ("println!", 0), - ("panic!", 0), - ("unreachable!", 0), - // From the `log` crate. - ("debug!", 0), - ("error!", 0), - ("info!", 0), - ("warn!", 0), - // write! like macros - ("assert!", 1), - ("debug_assert!", 1), - ("write!", 1), - ("writeln!", 1), - // assert_eq! like macros - ("assert_eq!", 2), - ("assert_ne!", 2), - ("debug_assert_eq!", 2), - ("debug_assert_ne!", 2), -]; - -pub fn rewrite_call( - context: &RewriteContext, - callee: &str, - args: &[ptr::P], - span: Span, - shape: Shape, -) -> Option { - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) - } else { - false - }; - rewrite_call_inner( - context, - callee, - &ptr_vec_to_ref_vec(args), - span, - shape, - context.config.width_heuristics().fn_call_width, - force_trailing_comma, - ) -} - -pub fn rewrite_call_inner<'a, T>( - context: &RewriteContext, - callee_str: &str, - args: &[&T], - span: Span, - shape: Shape, - args_max_width: usize, - force_trailing_comma: bool, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - // 2 = `( `, 1 = `(` - let paren_overhead = if context.config.spaces_within_parens_and_brackets() { - 2 - } else { - 1 - }; - let used_width = extra_offset(callee_str, shape); - let one_line_width = shape - .width - .checked_sub(used_width + 2 * paren_overhead) - .unwrap_or(0); - - // 1 = "(" or ")" - let one_line_shape = shape - .offset_left(last_line_width(callee_str) + 1) - .and_then(|shape| shape.sub_width(1)) - .unwrap_or(Shape { width: 0, ..shape }); - let nested_shape = shape_from_indent_style( - context, - shape, - used_width + 2 * paren_overhead, - used_width + paren_overhead, - )?; - - let span_lo = context.snippet_provider.span_after(span, "("); - let args_span = mk_sp(span_lo, span.hi()); - - let (extendable, list_str) = rewrite_call_args( - context, - args, - args_span, - one_line_shape, - nested_shape, - one_line_width, - args_max_width, - force_trailing_comma, - callee_str, - )?; - - if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { - let mut new_context = context.clone(); - new_context.use_block = true; - return rewrite_call_inner( - &new_context, - callee_str, - args, - span, - shape, - args_max_width, - force_trailing_comma, - ); - } - - let args_shape = Shape { - width: shape - .width - .checked_sub(last_line_width(callee_str)) - .unwrap_or(0), - ..shape - }; - Some(format!( - "{}{}", - callee_str, - wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) - )) -} - -fn need_block_indent(s: &str, shape: Shape) -> bool { - s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)) - .map_or(false, |w| w + 1 < shape.indent.width()) - }) -} - -fn rewrite_call_args<'a, T>( - context: &RewriteContext, - args: &[&T], - span: Span, - one_line_shape: Shape, - nested_shape: Shape, - one_line_width: usize, - args_max_width: usize, - force_trailing_comma: bool, - callee_str: &str, -) -> Option<(bool, String)> -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let items = itemize_list( - context.snippet_provider, - args.iter(), - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - span.lo(), - span.hi(), - true, - ); - let mut item_vec: Vec<_> = items.collect(); - - // Try letting the last argument overflow to the next line with block - // indentation. If its first line fits on one line with the other arguments, - // we format the function arguments horizontally. - let tactic = try_overflow_last_arg( - context, - &mut item_vec, - &args[..], - one_line_shape, - nested_shape, - one_line_width, - args_max_width, - callee_str, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if force_trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro || !context.use_block_indent() { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, - preserve_newline: false, - config: context.config, - }; - - write_list(&item_vec, &fmt) - .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str)) -} - -fn try_overflow_last_arg<'a, T>( - context: &RewriteContext, - item_vec: &mut Vec, - args: &[&T], - one_line_shape: Shape, - nested_shape: Shape, - one_line_width: usize, - args_max_width: usize, - callee_str: &str, -) -> DefinitiveListTactic -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - // 1 = "(" - let combine_arg_with_callee = - callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; - let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); - - // Replace the last item with its first line to see if it fits with - // first arguments. - let placeholder = if overflow_last { - let mut context = context.clone(); - if !combine_arg_with_callee { - if let Some(expr) = args[args.len() - 1].to_expr() { - if let ast::ExprKind::MethodCall(..) = expr.node { - context.force_one_line_chain = true; - } - } - } - last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { - rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) - }) - } else { - None - }; - - let mut tactic = definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ); - - // Replace the stub with the full overflowing last argument if the rewrite - // succeeded and its first line fits with the other arguments. - match (overflow_last, tactic, placeholder) { - (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) if args.len() == 1 => { - // When we are rewriting a nested function call, we restrict the - // bugdet for the inner function to avoid them being deeply nested. - // However, when the inner function has a prefix or a suffix - // (e.g. `foo() as u32`), this budget reduction may produce poorly - // formatted code, where a prefix or a suffix being left on its own - // line. Here we explicitlly check those cases. - if count_newlines(overflowed) == 1 { - let rw = args.last() - .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); - let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); - if no_newline { - item_vec[args.len() - 1].item = rw; - } else { - item_vec[args.len() - 1].item = Some(overflowed.to_owned()); - } - } else { - item_vec[args.len() - 1].item = Some(overflowed.to_owned()); - } - } - (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { - item_vec[args.len() - 1].item = placeholder; - } - _ if args.len() >= 1 => { - item_vec[args.len() - 1].item = args.last() - .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); - - let default_tactic = || { - definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ) - }; - - // Use horizontal layout for a function with a single argument as long as - // everything fits in a single line. - if args.len() == 1 - && args_max_width != 0 // Vertical layout is forced. - && !item_vec[0].has_comment() - && !item_vec[0].inner_as_ref().contains('\n') - && ::lists::total_item_width(&item_vec[0]) <= one_line_width - { - tactic = DefinitiveListTactic::Horizontal; - } else { - tactic = default_tactic(); - - if tactic == DefinitiveListTactic::Vertical { - if let Some((all_simple, num_args_before)) = - maybe_get_args_offset(callee_str, args) - { - let one_line = all_simple - && definitive_tactic( - &item_vec[..num_args_before], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ) == DefinitiveListTactic::Horizontal - && definitive_tactic( - &item_vec[num_args_before + 1..], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ) == DefinitiveListTactic::Horizontal; - - if one_line { - tactic = DefinitiveListTactic::SpecialMacro(num_args_before); - }; - } - } - } - } - _ => (), - } - - tactic -} - -fn is_simple_arg(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Lit(..) => true, - ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Cast(ref expr, _) - | ast::ExprKind::Field(ref expr, _) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::TupField(ref expr, _) - | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr), - ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { - is_simple_arg(lhs) && is_simple_arg(rhs) - } - _ => false, - } -} - -fn is_every_args_simple(lists: &[&T]) -> bool { - lists - .iter() - .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) -} - -/// In case special-case style is required, returns an offset from which we start horizontal layout. -fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { - if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST - .iter() - .find(|&&(s, _)| s == callee_str) - { - let all_simple = args.len() > num_args_before && is_every_args_simple(args); - - Some((all_simple, num_args_before)) - } else { - None - } -} - -/// Returns a shape for the last argument which is going to be overflowed. -fn last_arg_shape( - lists: &[&T], - items: &[ListItem], - shape: Shape, - args_max_width: usize, -) -> Option -where - T: Rewrite + Spanned + ToExpr, -{ - let is_nested_call = lists - .iter() - .next() - .and_then(|item| item.to_expr()) - .map_or(false, is_nested_call); - if items.len() == 1 && !is_nested_call { - return Some(shape); - } - let offset = items.iter().rev().skip(1).fold(0, |acc, i| { - // 2 = ", " - acc + 2 + i.inner_as_ref().len() - }); - Shape { - width: min(args_max_width, shape.width), - ..shape - }.offset_left(offset) -} - -fn rewrite_last_arg_with_overflow<'a, T>( - context: &RewriteContext, - args: &[&T], - last_item: &mut ListItem, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let last_arg = args[args.len() - 1]; - let rewrite = if let Some(expr) = last_arg.to_expr() { - match expr.node { - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - ast::ExprKind::Closure(..) => { - // If the argument consists of multiple closures, we do not overflow - // the last closure. - if closures::args_have_many_closure(args) { - None - } else { - closures::rewrite_last_closure(context, expr, shape) - } - } - _ => expr.rewrite(context, shape), - } - } else { - last_arg.rewrite(context, shape) - }; - - if let Some(rewrite) = rewrite { - let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); - last_item.item = rewrite_first_line; - Some(rewrite) - } else { - None - } -} - -fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - args.last() - .map_or(false, |x| x.can_be_overflowed(context, args.len())) -} - -pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { - match expr.node { - ast::ExprKind::Match(..) => { - (context.use_block_indent() && args_len == 1) - || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) - } - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => { - context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 - } - ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { - context.use_block_indent() - || context.config.indent_style() == IndentStyle::Visual && args_len > 1 - } - ast::ExprKind::Array(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::Mac(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), - _ => false, - } -} - -fn is_nested_call(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), - _ => false, - } -} - -pub fn wrap_args_with_parens( - context: &RewriteContext, - args_str: &str, - is_extendable: bool, - shape: Shape, - nested_shape: Shape, -) -> String { - let paren_overhead = paren_overhead(context); - let fits_one_line = args_str.len() + paren_overhead <= shape.width; - let extend_width = if args_str.is_empty() { - paren_overhead - } else { - paren_overhead / 2 - }; - if !context.use_block_indent() - || (context.inside_macro && !args_str.contains('\n') && fits_one_line) - || (is_extendable && extend_width <= shape.width) - { - let mut result = String::with_capacity(args_str.len() + 4); - if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() { - result.push_str("( "); - result.push_str(args_str); - result.push_str(" )"); - } else { - result.push_str("("); - result.push_str(args_str); - result.push_str(")"); - } - result - } else { - let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); - let indent_str = shape.block().indent.to_string_with_newline(context.config); - let mut result = - String::with_capacity(args_str.len() + 2 + indent_str.len() + nested_indent_str.len()); - result.push_str("("); - if !args_str.is_empty() { - result.push_str(&nested_indent_str); - result.push_str(args_str); - } - result.push_str(&indent_str); - result.push_str(")"); - result - } -} - -/// Return true if a function call or a method call represented by the given span ends with a -/// trailing comma. This function is used when rewriting macro, as adding or removing a trailing -/// comma from macro can potentially break the code. -fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { - let mut encountered_closing_paren = false; - for c in context.snippet(span).chars().rev() { - match c { - ',' => return true, - ')' => if encountered_closing_paren { - return false; - } else { - encountered_closing_paren = true; - }, - _ if c.is_whitespace() => continue, - _ => return false, - } - } - false -} - -fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { - debug!("rewrite_paren, shape: {:?}", shape); - let total_paren_overhead = paren_overhead(context); - let paren_overhead = total_paren_overhead / 2; - let sub_shape = shape - .offset_left(paren_overhead) - .and_then(|s| s.sub_width(paren_overhead))?; - - let paren_wrapper = |s: &str| { - if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { - format!("( {} )", s) - } else { - format!("({})", s) - } - }; - - let subexpr_str = subexpr.rewrite(context, sub_shape)?; - debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - - if subexpr_str.contains('\n') - || first_line_width(&subexpr_str) + total_paren_overhead <= shape.width - { - Some(paren_wrapper(&subexpr_str)) - } else { - None - } -} - -fn rewrite_index( - expr: &ast::Expr, - index: &ast::Expr, - context: &RewriteContext, - shape: Shape, -) -> Option { - let expr_str = expr.rewrite(context, shape)?; - - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - - let offset = last_line_width(&expr_str) + lbr.len(); - let rhs_overhead = shape.rhs_overhead(context.config); - let index_shape = if expr_str.contains('\n') { - Shape::legacy(context.config.max_width(), shape.indent) - .offset_left(offset) - .and_then(|shape| shape.sub_width(rbr.len() + rhs_overhead)) - } else { - shape.visual_indent(offset).sub_width(offset + rbr.len()) - }; - let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); - - // Return if index fits in a single line. - match orig_index_rw { - Some(ref index_str) if !index_str.contains('\n') => { - return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); - } - _ => (), - } - - // Try putting index on the next line and see if it fits in a single line. - let indent = shape.indent.block_indent(context.config); - let index_shape = Shape::indented(indent, context.config).offset_left(lbr.len())?; - let index_shape = index_shape.sub_width(rbr.len() + rhs_overhead)?; - let new_index_rw = index.rewrite(context, index_shape); - match (orig_index_rw, new_index_rw) { - (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( - "{}{}{}{}{}", - expr_str, - indent.to_string_with_newline(context.config), - lbr, - new_index_str, - rbr - )), - (None, Some(ref new_index_str)) => Some(format!( - "{}{}{}{}{}", - expr_str, - indent.to_string_with_newline(context.config), - lbr, - new_index_str, - rbr - )), - (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), - _ => None, - } -} - -fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { - if base.is_some() { - return false; - } - - fields.iter().all(|field| !field.is_shorthand) -} - -fn rewrite_struct_lit<'a>( - context: &RewriteContext, - path: &ast::Path, - fields: &'a [ast::Field], - base: Option<&'a ast::Expr>, - span: Span, - shape: Shape, -) -> Option { - debug!("rewrite_struct_lit: shape {:?}", shape); - - enum StructLitField<'a> { - Regular(&'a ast::Field), - Base(&'a ast::Expr), - } - - // 2 = " {".len() - let path_shape = shape.sub_width(2)?; - let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - - if fields.is_empty() && base.is_none() { - return Some(format!("{} {{}}", path_str)); - } - - // Foo { a: Foo } - indent is +3, width is -5. - let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; - - let one_line_width = h_shape.map_or(0, |shape| shape.width); - let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, &base) - && context.config.struct_field_align_threshold() > 0 - { - rewrite_with_alignment( - fields, - context, - shape, - mk_sp(body_lo, span.hi()), - one_line_width, - )? - } else { - let field_iter = fields - .into_iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); - - let span_lo = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span().lo(), - StructLitField::Base(expr) => { - let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - }; - let span_hi = |item: &StructLitField| match *item { - StructLitField::Regular(field) => field.span().hi(), - StructLitField::Base(expr) => expr.span.hi(), - }; - let rewrite = |item: &StructLitField| match *item { - StructLitField::Regular(field) => { - // The 1 taken from the v_budget is for the comma. - rewrite_field(context, field, v_shape.sub_width(1)?, 0) - } - StructLitField::Base(expr) => { - // 2 = .. - expr.rewrite(context, v_shape.offset_left(2)?) - .map(|s| format!("..{}", s)) - } - }; - - let items = itemize_list( - context.snippet_provider, - field_iter, - "}", - ",", - span_lo, - span_hi, - rewrite, - body_lo, - span.hi(), - false, - ); - let item_vec = items.collect::>(); - - let tactic = struct_lit_tactic(h_shape, context, &item_vec); - let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); - let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); - - write_list(&item_vec, &fmt)? - }; - - let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); - Some(format!("{} {{{}}}", path_str, fields_str)) - - // FIXME if context.config.indent_style() == Visual, but we run out - // of space, we should fall back to BlockIndent. -} - -pub fn wrap_struct_field( - context: &RewriteContext, - fields_str: &str, - shape: Shape, - nested_shape: Shape, - one_line_width: usize, -) -> String { - if context.config.indent_style() == IndentStyle::Block - && (fields_str.contains('\n') || !context.config.struct_lit_single_line() - || fields_str.len() > one_line_width) - { - format!( - "{}{}{}", - nested_shape.indent.to_string_with_newline(context.config), - fields_str, - shape.indent.to_string_with_newline(context.config) - ) - } else { - // One liner or visual indent. - format!(" {} ", fields_str) - } -} - -pub fn struct_lit_field_separator(config: &Config) -> &str { - colon_spaces(config.space_before_colon(), config.space_after_colon()) -} - -pub fn rewrite_field( - context: &RewriteContext, - field: &ast::Field, - shape: Shape, - prefix_max_width: usize, -) -> Option { - if contains_skip(&field.attrs) { - return Some(context.snippet(field.span()).to_owned()); - } - let mut attrs_str = field.attrs.rewrite(context, shape)?; - if !attrs_str.is_empty() { - attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); - }; - let name = field.ident.node.to_string(); - if field.is_shorthand { - Some(attrs_str + &name) - } else { - let mut separator = String::from(struct_lit_field_separator(context.config)); - for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { - separator.push(' '); - } - let overhead = name.len() + separator.len(); - let expr_shape = shape.offset_left(overhead)?; - let expr = field.expr.rewrite(context, expr_shape); - - match expr { - Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { - Some(attrs_str + &name) - } - Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), - None => { - let expr_offset = shape.indent.block_indent(context.config); - let expr = field - .expr - .rewrite(context, Shape::indented(expr_offset, context.config)); - expr.map(|s| { - format!( - "{}{}:\n{}{}", - attrs_str, - name, - expr_offset.to_string(context.config), - s - ) - }) - } - } - } -} - -fn shape_from_indent_style( - context: &RewriteContext, - shape: Shape, - overhead: usize, - offset: usize, -) -> Option { - if context.use_block_indent() { - // 1 = "," - shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1) - } else { - shape.visual_indent(offset).sub_width(overhead) - } -} - -fn rewrite_tuple_in_visual_indent_style<'a, T>( - context: &RewriteContext, - items: &[&T], - span: Span, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let mut items = items.iter(); - // In case of length 1, need a trailing comma - debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); - if items.len() == 1 { - // 3 = "(" + ",)" - let nested_shape = shape.sub_width(3)?.visual_indent(1); - return items - .next() - .unwrap() - .rewrite(context, nested_shape) - .map(|s| { - if context.config.spaces_within_parens_and_brackets() { - format!("( {}, )", s) - } else { - format!("({},)", s) - } - }); - } - - let list_lo = context.snippet_provider.span_after(span, "("); - let nested_shape = shape.sub_width(2)?.visual_indent(1); - let items = itemize_list( - context.snippet_provider, - items, - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - list_lo, - span.hi() - BytePos(1), - false, - ); - let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - let list_str = write_list(&item_vec, &fmt)?; - - if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { - Some(format!("( {} )", list_str)) - } else { - Some(format!("({})", list_str)) - } -} - -pub fn rewrite_tuple<'a, T>( - context: &RewriteContext, - items: &[&T], - span: Span, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - debug!("rewrite_tuple {:?}", shape); - if context.use_block_indent() { - // We use the same rule as function calls for rewriting tuples. - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) - } else { - items.len() == 1 - }; - rewrite_call_inner( - context, - &String::new(), - items, - span, - shape, - context.config.width_heuristics().fn_call_width, - force_trailing_comma, - ) - } else { - rewrite_tuple_in_visual_indent_style(context, items, span, shape) - } -} - -pub fn rewrite_unary_prefix( - context: &RewriteContext, - prefix: &str, - rewrite: &R, - shape: Shape, -) -> Option { - rewrite - .rewrite(context, shape.offset_left(prefix.len())?) - .map(|r| format!("{}{}", prefix, r)) -} - -// FIXME: this is probably not correct for multi-line Rewrites. we should -// subtract suffix.len() from the last line budget, not the first! -pub fn rewrite_unary_suffix( - context: &RewriteContext, - suffix: &str, - rewrite: &R, - shape: Shape, -) -> Option { - rewrite - .rewrite(context, shape.sub_width(suffix.len())?) - .map(|mut r| { - r.push_str(suffix); - r - }) -} - -fn rewrite_unary_op( - context: &RewriteContext, - op: &ast::UnOp, - expr: &ast::Expr, - shape: Shape, -) -> Option { - // For some reason, an UnOp is not spanned like BinOp! - let operator_str = match *op { - ast::UnOp::Deref => "*", - ast::UnOp::Not => "!", - ast::UnOp::Neg => "-", - }; - rewrite_unary_prefix(context, operator_str, expr, shape) -} - -fn rewrite_assignment( - context: &RewriteContext, - lhs: &ast::Expr, - rhs: &ast::Expr, - op: Option<&ast::BinOp>, - shape: Shape, -) -> Option { - let operator_str = match op { - Some(op) => context.snippet(op.span), - None => "=", - }; - - // 1 = space between lhs and operator. - let lhs_shape = shape.sub_width(operator_str.len() + 1)?; - let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); - - rewrite_assign_rhs(context, lhs_str, rhs, shape) -} - -// The left hand side must contain everything up to, and including, the -// assignment operator. -pub fn rewrite_assign_rhs, R: Rewrite>( - context: &RewriteContext, - lhs: S, - ex: &R, - shape: Shape, -) -> Option { - let lhs = lhs.into(); - let last_line_width = last_line_width(&lhs) - .checked_sub(if lhs.contains('\n') { - shape.indent.width() - } else { - 0 - }) - .unwrap_or(0); - // 1 = space between operator and rhs. - let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { - width: 0, - offset: shape.offset + last_line_width + 1, - ..shape - }); - let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; - Some(lhs + &rhs) -} - -pub fn choose_rhs( - context: &RewriteContext, - expr: &R, - shape: Shape, - orig_rhs: Option, -) -> Option { - match orig_rhs { - Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { - Some(format!(" {}", new_str)) - } - _ => { - // Expression did not fit on the same line as the identifier. - // Try splitting the line and see if that works better. - let new_shape = - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(shape.rhs_overhead(context.config))?; - let new_rhs = expr.rewrite(context, new_shape); - let new_indent_str = &new_shape.indent.to_string_with_newline(context.config); - - match (orig_rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref new_rhs)) - if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) - .is_none() => - { - Some(format!(" {}", orig_rhs)) - } - (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { - Some(format!("{}{}", new_indent_str, new_rhs)) - } - (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), - (None, None) => None, - (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), - } - } - } -} - -fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 -} - -fn rewrite_expr_addrof( - context: &RewriteContext, - mutability: ast::Mutability, - expr: &ast::Expr, - shape: Shape, -) -> Option { - let operator_str = match mutability { - ast::Mutability::Immutable => "&", - ast::Mutability::Mutable => "&mut ", - }; - rewrite_unary_prefix(context, operator_str, expr, shape) -} - -pub trait ToExpr { - fn to_expr(&self) -> Option<&ast::Expr>; - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool; -} - -impl ToExpr for ast::Expr { - fn to_expr(&self) -> Option<&ast::Expr> { - Some(self) - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_expr(context, self, len) - } -} - -impl ToExpr for ast::Ty { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_type(context, self, len) - } -} - -impl<'a> ToExpr for TuplePatField<'a> { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_pat(context, self, len) - } -} - -impl<'a> ToExpr for ast::StructField { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { - false - } -} - -impl<'a> ToExpr for MacroArg { - fn to_expr(&self) -> Option<&ast::Expr> { - match *self { - MacroArg::Expr(ref expr) => Some(expr), - _ => None, - } - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - match *self { - MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), - MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), - MacroArg::Pat(..) => false, - } - } -} diff --git a/rustfmt-core/src/filemap.rs b/rustfmt-core/src/filemap.rs deleted file mode 100644 index ee2253043a1..00000000000 --- a/rustfmt-core/src/filemap.rs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// TODO: add tests - -use std::fs::{self, File}; -use std::io::{self, BufWriter, Read, Write}; -use std::path::Path; - -use checkstyle::{output_checkstyle_file, output_footer, output_header}; -use config::{Config, NewlineStyle, WriteMode}; -use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; -use syntax::codemap::FileName; - -use FileRecord; - -// Append a newline to the end of each file. -pub fn append_newline(s: &mut String) { - s.push_str("\n"); -} - -pub fn write_all_files( - file_map: &[FileRecord], - out: &mut T, - config: &Config, -) -> Result<(), io::Error> -where - T: Write, -{ - output_header(out, config.write_mode()).ok(); - for &(ref filename, ref text) in file_map { - write_file(text, filename, out, config)?; - } - output_footer(out, config.write_mode()).ok(); - - Ok(()) -} - -// Prints all newlines either as `\n` or as `\r\n`. -pub fn write_system_newlines(writer: T, text: &str, config: &Config) -> Result<(), io::Error> -where - T: Write, -{ - // Buffer output, since we're writing a since char at a time. - let mut writer = BufWriter::new(writer); - - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; - - match style { - NewlineStyle::Unix => write!(writer, "{}", text), - NewlineStyle::Windows => { - for c in text.chars() { - match c { - '\n' => write!(writer, "\r\n")?, - '\r' => continue, - c => write!(writer, "{}", c)?, - } - } - Ok(()) - } - NewlineStyle::Native => unreachable!(), - } -} - -pub fn write_file( - text: &str, - filename: &FileName, - out: &mut T, - config: &Config, -) -> Result -where - T: Write, -{ - fn source_and_formatted_text( - text: &str, - filename: &Path, - config: &Config, - ) -> Result<(String, String), io::Error> { - let mut f = File::open(filename)?; - let mut ori_text = String::new(); - f.read_to_string(&mut ori_text)?; - let mut v = Vec::new(); - write_system_newlines(&mut v, text, config)?; - let fmt_text = String::from_utf8(v).unwrap(); - Ok((ori_text, fmt_text)) - } - - fn create_diff( - filename: &Path, - text: &str, - config: &Config, - ) -> Result, io::Error> { - let (ori, fmt) = source_and_formatted_text(text, filename, config)?; - Ok(make_diff(&ori, &fmt, 3)) - } - - let filename_to_path = || match *filename { - FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` with WriteMode::Replace", filename), - }; - - match config.write_mode() { - WriteMode::Replace => { - let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - if fmt != ori { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.with_extension("tmp"); - let bk_name = filename.with_extension("bk"); - { - // Write text to temp file - let tmp_file = File::create(&tmp_name)?; - write_system_newlines(tmp_file, text, config)?; - } - - fs::rename(filename, bk_name)?; - fs::rename(tmp_name, filename)?; - } - } - } - WriteMode::Overwrite => { - // Write text directly over original file if there is a diff. - let filename = filename_to_path(); - let (source, formatted) = source_and_formatted_text(text, filename, config)?; - if source != formatted { - let file = File::create(filename)?; - write_system_newlines(file, text, config)?; - } - } - WriteMode::Plain => { - write_system_newlines(out, text, config)?; - } - WriteMode::Display | WriteMode::Coverage => { - println!("{}:\n", filename); - write_system_newlines(out, text, config)?; - } - WriteMode::Diff => { - let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - let mismatch = make_diff(&ori, &fmt, 3); - let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config.color(), - ); - return Ok(has_diff); - } - } - WriteMode::Modified => { - let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - let mismatch = make_diff(&ori, &fmt, 0); - let has_diff = !mismatch.is_empty(); - output_modified(out, mismatch); - return Ok(has_diff); - } - } - WriteMode::Checkstyle => { - let filename = filename_to_path(); - let diff = create_diff(filename, text, config)?; - output_checkstyle_file(out, filename, diff)?; - } - } - - // when we are not in diff mode, don't indicate differing files - Ok(false) -} diff --git a/rustfmt-core/src/imports.rs b/rustfmt-core/src/imports.rs deleted file mode 100644 index 9a6af3f267c..00000000000 --- a/rustfmt-core/src/imports.rs +++ /dev/null @@ -1,399 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Ordering; - -use config::lists::*; -use syntax::ast; -use syntax::codemap::{BytePos, Span}; - -use codemap::SpanUtils; -use config::IndentStyle; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use types::{rewrite_path, PathContext}; -use utils::{format_visibility, mk_sp}; -use visitor::FmtVisitor; - -/// Returns a name imported by a `use` declaration. e.g. returns `Ordering` -/// for `std::cmp::Ordering` and `self` for `std::cmp::self`. -pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { - path.segments.last().unwrap().identifier -} - -fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { - if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { - let path = &ast::Path { - span: path.span, - segments: path.segments[..path.segments.len() - 1].to_owned(), - }; - rewrite_path(context, PathContext::Import, None, path, shape) - } else { - rewrite_path(context, PathContext::Import, None, path, shape) - } -} - -impl Rewrite for ast::UseTree { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.kind { - ast::UseTreeKind::Nested(ref items) => { - rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context) - } - ast::UseTreeKind::Glob => { - let prefix_shape = shape.sub_width(3)?; - - if !self.prefix.segments.is_empty() { - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; - Some(format!("{}::*", path_str)) - } else { - Some("*".to_owned()) - } - } - ast::UseTreeKind::Simple(ident) => { - let ident_str = ident.to_string(); - - // 4 = " as ".len() - let is_same_name_bind = path_to_imported_ident(&self.prefix) == ident; - let prefix_shape = if is_same_name_bind { - shape - } else { - shape.sub_width(ident_str.len() + 4)? - }; - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) - .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); - - if is_same_name_bind { - Some(path_str) - } else { - Some(format!("{} as {}", path_str, ident_str)) - } - } - } - } -} - -fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool { - attrs.is_empty() && is_unused_import_inner(tree) -} - -fn is_unused_import_inner(tree: &ast::UseTree) -> bool { - match tree.kind { - ast::UseTreeKind::Nested(ref items) => match items.len() { - 0 => true, - 1 => is_unused_import_inner(&items[0].0), - _ => false, - }, - _ => false, - } -} - -// Rewrite `use foo;` WITHOUT attributes. -pub fn rewrite_import( - context: &RewriteContext, - vis: &ast::Visibility, - tree: &ast::UseTree, - attrs: &[ast::Attribute], - shape: Shape, -) -> Option { - let vis = format_visibility(vis); - // 4 = `use `, 1 = `;` - let rw = shape - .offset_left(vis.len() + 4) - .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| { - // If we have an empty nested group with no attributes, we erase it - if is_unused_import(tree, attrs) { - Some("".to_owned()) - } else { - tree.rewrite(context, shape) - } - }); - match rw { - Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), - _ => rw, - } -} - -impl<'a> FmtVisitor<'a> { - pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { - let span = item.span; - let shape = self.shape(); - let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape); - match rw { - Some(ref s) if s.is_empty() => { - // Format up to last newline - let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); - let trimmed_snippet = self.snippet(prev_span).trim_right(); - let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32); - self.format_missing(span_end); - // We have an excessive newline from the removed import. - if self.buffer.ends_with('\n') { - self.buffer.pop(); - self.line_number -= 1; - } - self.last_pos = source!(self, span).hi(); - } - Some(ref s) => { - self.format_missing_with_indent(source!(self, span).lo()); - self.push_str(s); - self.last_pos = source!(self, span).hi(); - } - None => { - self.format_missing_with_indent(source!(self, span).lo()); - self.format_missing(source!(self, span).hi()); - } - } - } -} - -fn rewrite_nested_use_tree_single( - context: &RewriteContext, - path_str: &str, - tree: &ast::UseTree, - shape: Shape, -) -> Option { - match tree.kind { - ast::UseTreeKind::Simple(rename) => { - let ident = path_to_imported_ident(&tree.prefix); - let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; - if item_str == "self" { - item_str = "".to_owned(); - } - - let path_item_str = if path_str.is_empty() { - if item_str.is_empty() { - "self".to_owned() - } else { - item_str - } - } else if item_str.is_empty() { - path_str.to_owned() - } else { - format!("{}::{}", path_str, item_str) - }; - - Some(if ident == rename { - path_item_str - } else { - format!("{} as {}", path_item_str, rename) - }) - } - ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { - // 2 = "::" - let nested_shape = shape.offset_left(path_str.len() + 2)?; - tree.rewrite(context, nested_shape) - .map(|item| format!("{}::{}", path_str, item)) - } - } -} - -#[derive(Eq, PartialEq)] -enum ImportItem<'a> { - // `self` or `self as a` - SelfImport(&'a str), - // name_one, name_two, ... - SnakeCase(&'a str), - // NameOne, NameTwo, ... - CamelCase(&'a str), - // NAME_ONE, NAME_TWO, ... - AllCaps(&'a str), - // Failed to format the import item - Invalid, -} - -impl<'a> ImportItem<'a> { - fn from_str(s: &str) -> ImportItem { - if s == "self" || s.starts_with("self as") { - ImportItem::SelfImport(s) - } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') { - ImportItem::SnakeCase(s) - } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') { - ImportItem::AllCaps(s) - } else { - ImportItem::CamelCase(s) - } - } - - fn from_opt_str(s: Option<&String>) -> ImportItem { - s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s)) - } - - fn to_str(&self) -> Option<&str> { - match *self { - ImportItem::SelfImport(s) - | ImportItem::SnakeCase(s) - | ImportItem::CamelCase(s) - | ImportItem::AllCaps(s) => Some(s), - ImportItem::Invalid => None, - } - } - - fn to_u32(&self) -> u32 { - match *self { - ImportItem::SelfImport(..) => 0, - ImportItem::SnakeCase(..) => 1, - ImportItem::CamelCase(..) => 2, - ImportItem::AllCaps(..) => 3, - ImportItem::Invalid => 4, - } - } -} - -impl<'a> PartialOrd for ImportItem<'a> { - fn partial_cmp(&self, other: &ImportItem<'a>) -> Option { - Some(self.cmp(other)) - } -} - -impl<'a> Ord for ImportItem<'a> { - fn cmp(&self, other: &ImportItem<'a>) -> Ordering { - let res = self.to_u32().cmp(&other.to_u32()); - if res != Ordering::Equal { - return res; - } - self.to_str().map_or(Ordering::Greater, |self_str| { - other - .to_str() - .map_or(Ordering::Less, |other_str| self_str.cmp(other_str)) - }) - } -} - -// Pretty prints a multi-item import. -// If the path list is empty, it leaves the braces empty. -fn rewrite_nested_use_tree( - shape: Shape, - path: &ast::Path, - trees: &[(ast::UseTree, ast::NodeId)], - span: Span, - context: &RewriteContext, -) -> Option { - // Returns a different option to distinguish `::foo` and `foo` - let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; - - match trees.len() { - 0 => { - let shape = shape.offset_left(path_str.len() + 3)?; - return rewrite_path(context, PathContext::Import, None, path, shape) - .map(|path_str| format!("{}::{{}}", path_str)); - } - 1 => { - return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape); - } - _ => (), - } - - let path_str = if path_str.is_empty() { - path_str - } else { - format!("{}::", path_str) - }; - - // 2 = "{}" - let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); - let nested_indent = match context.config.imports_indent() { - IndentStyle::Block => shape.indent.block_indent(context.config), - // 1 = `{` - IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, - }; - - let nested_shape = match context.config.imports_indent() { - IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?, - IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), - }; - - let mut items = { - // Dummy value, see explanation below. - let mut items = vec![ListItem::from_str("")]; - let iter = itemize_list( - context.snippet_provider, - trees.iter().map(|tree| &tree.0), - "}", - ",", - |tree| tree.span.lo(), - |tree| tree.span.hi(), - |tree| tree.rewrite(context, nested_shape), - context.snippet_provider.span_after(span, "{"), - span.hi(), - false, - ); - items.extend(iter); - items - }; - - // We prefixed the item list with a dummy value so that we can - // potentially move "self" to the front of the vector without touching - // the rest of the items. - let has_self = move_self_to_front(&mut items); - let first_index = if has_self { 0 } else { 1 }; - - if context.config.reorder_imported_names() { - items[1..].sort_by(|a, b| { - let a = ImportItem::from_opt_str(a.item.as_ref()); - let b = ImportItem::from_opt_str(b.item.as_ref()); - a.cmp(&b) - }); - } - - let tactic = definitive_tactic( - &items[first_index..], - context.config.imports_layout(), - Separator::Comma, - remaining_width, - ); - - let ends_with_newline = context.config.imports_indent() == IndentStyle::Block - && tactic != DefinitiveListTactic::Horizontal; - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if ends_with_newline { - context.config.trailing_comma() - } else { - SeparatorTactic::Never - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline, - preserve_newline: true, - config: context.config, - }; - let list_str = write_list(&items[first_index..], &fmt)?; - - let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block - { - format!( - "{}{{\n{}{}\n{}}}", - path_str, - nested_shape.indent.to_string(context.config), - list_str, - shape.indent.to_string(context.config) - ) - } else { - format!("{}{{{}}}", path_str, list_str) - }; - Some(result) -} - -// Returns true when self item was found. -fn move_self_to_front(items: &mut Vec) -> bool { - match items - .iter() - .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) - { - Some(pos) => { - items[0] = items.remove(pos); - true - } - None => false, - } -} diff --git a/rustfmt-core/src/issues.rs b/rustfmt-core/src/issues.rs deleted file mode 100644 index 75ad30b6f2a..00000000000 --- a/rustfmt-core/src/issues.rs +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Objects for seeking through a char stream for occurrences of TODO and FIXME. -// Depending on the loaded configuration, may also check that these have an -// associated issue number. - -use std::fmt; - -use config::ReportTactic; - -const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o']; -const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e']; - -// Enabled implementation detail is here because it is -// irrelevant outside the issues module -fn is_enabled(report_tactic: ReportTactic) -> bool { - report_tactic != ReportTactic::Never -} - -#[derive(Clone, Copy)] -enum Seeking { - Issue { todo_idx: usize, fixme_idx: usize }, - Number { issue: Issue, part: NumberPart }, -} - -#[derive(Clone, Copy)] -enum NumberPart { - OpenParen, - Pound, - Number, - CloseParen, -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub struct Issue { - issue_type: IssueType, - // Indicates whether we're looking for issues with missing numbers, or - // all issues of this type. - missing_number: bool, -} - -impl fmt::Display for Issue { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let msg = match self.issue_type { - IssueType::Todo => "TODO", - IssueType::Fixme => "FIXME", - }; - let details = if self.missing_number { - " without issue number" - } else { - "" - }; - - write!(fmt, "{}{}", msg, details) - } -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -enum IssueType { - Todo, - Fixme, -} - -enum IssueClassification { - Good, - Bad(Issue), - None, -} - -pub struct BadIssueSeeker { - state: Seeking, - report_todo: ReportTactic, - report_fixme: ReportTactic, -} - -impl BadIssueSeeker { - pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { - BadIssueSeeker { - state: Seeking::Issue { - todo_idx: 0, - fixme_idx: 0, - }, - report_todo, - report_fixme, - } - } - - pub fn is_disabled(&self) -> bool { - !is_enabled(self.report_todo) && !is_enabled(self.report_fixme) - } - - // Check whether or not the current char is conclusive evidence for an - // unnumbered TO-DO or FIX-ME. - pub fn inspect(&mut self, c: char) -> Option { - match self.state { - Seeking::Issue { - todo_idx, - fixme_idx, - } => { - self.state = self.inspect_issue(c, todo_idx, fixme_idx); - } - Seeking::Number { issue, part } => { - let result = self.inspect_number(c, issue, part); - - if let IssueClassification::None = result { - return None; - } - - self.state = Seeking::Issue { - todo_idx: 0, - fixme_idx: 0, - }; - - if let IssueClassification::Bad(issue) = result { - return Some(issue); - } - } - } - - None - } - - fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking { - if let Some(lower_case_c) = c.to_lowercase().next() { - if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] { - todo_idx += 1; - if todo_idx == TO_DO_CHARS.len() { - return Seeking::Number { - issue: Issue { - issue_type: IssueType::Todo, - missing_number: if let ReportTactic::Unnumbered = self.report_todo { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; - } - fixme_idx = 0; - } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] { - // Exploit the fact that the character sets of todo and fixme - // are disjoint by adding else. - fixme_idx += 1; - if fixme_idx == FIX_ME_CHARS.len() { - return Seeking::Number { - issue: Issue { - issue_type: IssueType::Fixme, - missing_number: if let ReportTactic::Unnumbered = self.report_fixme { - true - } else { - false - }, - }, - part: NumberPart::OpenParen, - }; - } - todo_idx = 0; - } else { - todo_idx = 0; - fixme_idx = 0; - } - } - - Seeking::Issue { - todo_idx, - fixme_idx, - } - } - - fn inspect_number( - &mut self, - c: char, - issue: Issue, - mut part: NumberPart, - ) -> IssueClassification { - if !issue.missing_number || c == '\n' { - return IssueClassification::Bad(issue); - } else if c == ')' { - return if let NumberPart::CloseParen = part { - IssueClassification::Good - } else { - IssueClassification::Bad(issue) - }; - } - - match part { - NumberPart::OpenParen => { - if c != '(' { - return IssueClassification::Bad(issue); - } else { - part = NumberPart::Pound; - } - } - NumberPart::Pound => { - if c == '#' { - part = NumberPart::Number; - } - } - NumberPart::Number => { - if c >= '0' && c <= '9' { - part = NumberPart::CloseParen; - } else { - return IssueClassification::Bad(issue); - } - } - NumberPart::CloseParen => {} - } - - self.state = Seeking::Number { part, issue }; - - IssueClassification::None - } -} - -#[test] -fn find_unnumbered_issue() { - fn check_fail(text: &str, failing_pos: usize) { - let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!( - Some(failing_pos), - text.chars().position(|c| seeker.inspect(c).is_some()) - ); - } - - fn check_pass(text: &str) { - let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); - } - - check_fail("TODO\n", 4); - check_pass(" TO FIX DOME\n"); - check_fail(" \n FIXME\n", 8); - check_fail("FIXME(\n", 6); - check_fail("FIXME(#\n", 7); - check_fail("FIXME(#1\n", 8); - check_fail("FIXME(#)1\n", 7); - check_pass("FIXME(#1222)\n"); - check_fail("FIXME(#12\n22)\n", 9); - check_pass("FIXME(@maintainer, #1222, hello)\n"); - check_fail("TODO(#22) FIXME\n", 15); -} - -#[test] -fn find_issue() { - fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { - let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); - text.chars().any(|c| seeker.inspect(c).is_some()) - } - - assert!(is_bad_issue( - "TODO(@maintainer, #1222, hello)\n", - ReportTactic::Always, - ReportTactic::Never, - )); - - assert!(!is_bad_issue( - "TODO: no number\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(!is_bad_issue( - "Todo: mixed case\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(is_bad_issue( - "This is a FIXME(#1)\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(is_bad_issue( - "This is a FixMe(#1) mixed case\n", - ReportTactic::Never, - ReportTactic::Always, - )); - - assert!(!is_bad_issue( - "bad FIXME\n", - ReportTactic::Always, - ReportTactic::Never, - )); -} - -#[test] -fn issue_type() { - let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); - let expected = Some(Issue { - issue_type: IssueType::Todo, - missing_number: false, - }); - - assert_eq!( - expected, - "TODO(#100): more awesomeness" - .chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap() - ); - - let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); - let expected = Some(Issue { - issue_type: IssueType::Fixme, - missing_number: true, - }); - - assert_eq!( - expected, - "Test. FIXME: bad, bad, not good" - .chars() - .map(|c| seeker.inspect(c)) - .find(Option::is_some) - .unwrap() - ); -} diff --git a/rustfmt-core/src/items.rs b/rustfmt-core/src/items.rs deleted file mode 100644 index 3503546c010..00000000000 --- a/rustfmt-core/src/items.rs +++ /dev/null @@ -1,2891 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Formatting top-level items - functions, structs, enums, traits, impls. - -use std::borrow::Cow; -use std::cmp::min; - -use config::lists::*; -use regex::Regex; -use syntax::{abi, ast, ptr, symbol}; -use syntax::ast::{CrateSugar, ImplItem}; -use syntax::codemap::{BytePos, Span}; -use syntax::visit; - -use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; -use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, - rewrite_call_inner, ExprType}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use types::join_bounds; -use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, - format_defaultness, format_mutability, format_unsafety, format_visibility, - is_attributes_extendable, last_line_contains_single_line_comment, - last_line_extendable, last_line_used_width, last_line_width, mk_sp, - semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; -use vertical::rewrite_with_alignment; -use visitor::FmtVisitor; - -fn type_annotation_separator(config: &Config) -> &str { - colon_spaces(config.space_before_colon(), config.space_after_colon()) -} - -// Statements of the form -// let pat: ty = init; -impl Rewrite for ast::Local { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - debug!( - "Local::rewrite {:?} {} {:?}", - self, shape.width, shape.indent - ); - - skip_out_of_file_lines_range!(context, self.span); - - if contains_skip(&self.attrs) { - return None; - } - - let attrs_str = self.attrs.rewrite(context, shape)?; - let mut result = if attrs_str.is_empty() { - "let ".to_owned() - } else { - combine_strs_with_missing_comments( - context, - &attrs_str, - "let ", - mk_sp( - self.attrs.last().map(|a| a.span.hi()).unwrap(), - self.span.lo(), - ), - shape, - false, - )? - }; - - // 4 = "let ".len() - let pat_shape = shape.offset_left(4)?; - // 1 = ; - let pat_shape = pat_shape.sub_width(1)?; - let pat_str = self.pat.rewrite(context, pat_shape)?; - result.push_str(&pat_str); - - // String that is placed within the assignment pattern and expression. - let infix = { - let mut infix = String::with_capacity(32); - - if let Some(ref ty) = self.ty { - let separator = type_annotation_separator(context.config); - let indent = shape.indent + last_line_width(&result) + separator.len(); - // 1 = ; - let budget = shape.width.checked_sub(indent.width() + 1)?; - let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?; - - infix.push_str(separator); - infix.push_str(&rewrite); - } - - if self.init.is_some() { - infix.push_str(" ="); - } - - infix - }; - - result.push_str(&infix); - - if let Some(ref ex) = self.init { - // 1 = trailing semicolon; - let nested_shape = shape.sub_width(1)?; - - result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?; - } - - result.push(';'); - Some(result) - } -} - -// TODO convert to using rewrite style rather than visitor -// TODO format modules in this style -#[allow(dead_code)] -struct Item<'a> { - keyword: &'static str, - abi: Cow<'static, str>, - vis: Option<&'a ast::Visibility>, - body: Vec>, - span: Span, -} - -impl<'a> Item<'a> { - fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { - Item { - keyword: "", - abi: format_abi(fm.abi, config.force_explicit_abi(), true), - vis: None, - body: fm.items - .iter() - .map(|i| BodyElement::ForeignItem(i)) - .collect(), - span, - } - } -} - -enum BodyElement<'a> { - // Stmt(&'a ast::Stmt), - // Field(&'a ast::Field), - // Variant(&'a ast::Variant), - // Item(&'a ast::Item), - ForeignItem(&'a ast::ForeignItem), -} - -/// Represents a fn's signature. -pub struct FnSig<'a> { - decl: &'a ast::FnDecl, - generics: &'a ast::Generics, - abi: abi::Abi, - constness: ast::Constness, - defaultness: ast::Defaultness, - unsafety: ast::Unsafety, - visibility: ast::Visibility, -} - -impl<'a> FnSig<'a> { - pub fn new( - decl: &'a ast::FnDecl, - generics: &'a ast::Generics, - vis: ast::Visibility, - ) -> FnSig<'a> { - FnSig { - decl, - generics, - abi: abi::Abi::Rust, - constness: ast::Constness::NotConst, - defaultness: ast::Defaultness::Final, - unsafety: ast::Unsafety::Normal, - visibility: vis, - } - } - - pub fn from_method_sig( - method_sig: &'a ast::MethodSig, - generics: &'a ast::Generics, - ) -> FnSig<'a> { - FnSig { - unsafety: method_sig.unsafety, - constness: method_sig.constness.node, - defaultness: ast::Defaultness::Final, - abi: method_sig.abi, - decl: &*method_sig.decl, - generics, - visibility: ast::Visibility::Inherited, - } - } - - pub fn from_fn_kind( - fn_kind: &'a visit::FnKind, - generics: &'a ast::Generics, - decl: &'a ast::FnDecl, - defualtness: ast::Defaultness, - ) -> FnSig<'a> { - match *fn_kind { - visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { - decl, - generics, - abi, - constness: constness.node, - defaultness: defualtness, - unsafety, - visibility: visibility.clone(), - }, - visit::FnKind::Method(_, method_sig, vis, _) => { - let mut fn_sig = FnSig::from_method_sig(method_sig, generics); - fn_sig.defaultness = defualtness; - if let Some(vis) = vis { - fn_sig.visibility = vis.clone(); - } - fn_sig - } - _ => unreachable!(), - } - } - - fn to_str(&self, context: &RewriteContext) -> String { - let mut result = String::with_capacity(128); - // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(&self.visibility)); - result.push_str(format_defaultness(self.defaultness)); - result.push_str(format_constness(self.constness)); - result.push_str(format_unsafety(self.unsafety)); - result.push_str(&format_abi( - self.abi, - context.config.force_explicit_abi(), - false, - )); - result - } -} - -impl<'a> FmtVisitor<'a> { - fn format_item(&mut self, item: &Item) { - self.buffer.push_str(&item.abi); - - let snippet = self.snippet(item.span); - let brace_pos = snippet.find_uncommented("{").unwrap(); - - self.push_str("{"); - if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { - // FIXME: this skips comments between the extern keyword and the opening - // brace. - self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1); - self.block_indent = self.block_indent.block_indent(self.config); - - if item.body.is_empty() { - self.format_missing_no_indent(item.span.hi() - BytePos(1)); - self.block_indent = self.block_indent.block_unindent(self.config); - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - } else { - for item in &item.body { - self.format_body_element(item); - } - - self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(item.span.hi() - BytePos(1)); - } - } - - self.push_str("}"); - self.last_pos = item.span.hi(); - } - - fn format_body_element(&mut self, element: &BodyElement) { - match *element { - BodyElement::ForeignItem(item) => self.format_foreign_item(item), - } - } - - pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { - let item = Item::from_foreign_mod(fm, span, self.config); - self.format_item(&item); - } - - fn format_foreign_item(&mut self, item: &ast::ForeignItem) { - let rewrite = item.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(item.span(), rewrite); - self.last_pos = item.span.hi(); - } - - pub fn rewrite_fn( - &mut self, - indent: Indent, - ident: ast::Ident, - fn_sig: &FnSig, - span: Span, - block: &ast::Block, - ) -> Option { - let context = self.get_context(); - - let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause); - - let (mut result, force_newline_brace) = - rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; - - // 2 = ` {` - if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace - || last_line_width(&result) + 2 > self.shape().width - { - newline_brace = true; - } else if !result.contains('\n') { - newline_brace = false; - } - - // Prepare for the function body by possibly adding a newline and - // indent. - // FIXME we'll miss anything between the end of the signature and the - // start of the body, but we need more spans from the compiler to solve - // this. - if newline_brace { - result.push_str(&indent.to_string_with_newline(self.config)); - } else { - result.push(' '); - } - - self.single_line_fn(&result, block).or_else(|| Some(result)) - } - - pub fn rewrite_required_fn( - &mut self, - indent: Indent, - ident: ast::Ident, - sig: &ast::MethodSig, - generics: &ast::Generics, - span: Span, - ) -> Option { - // Drop semicolon or it will be interpreted as comment. - let span = mk_sp(span.lo(), span.hi() - BytePos(1)); - let context = self.get_context(); - - let (mut result, _) = rewrite_fn_base( - &context, - indent, - ident, - &FnSig::from_method_sig(sig, generics), - span, - false, - false, - )?; - - // Re-attach semicolon - result.push(';'); - - Some(result) - } - - fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { - if fn_str.contains('\n') { - return None; - } - - let codemap = self.get_context().codemap; - - if self.config.empty_item_single_line() && is_empty_block(block, codemap) - && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() - { - return Some(format!("{}{{}}", fn_str)); - } - - if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { - let rewrite = { - if let Some(stmt) = block.stmts.first() { - match stmt_expr(stmt) { - Some(e) => { - let suffix = if semicolon_for_expr(&self.get_context(), e) { - ";" - } else { - "" - }; - - format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) - .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span).to_owned())) - } - None => stmt.rewrite(&self.get_context(), self.shape()), - } - } else { - None - } - }; - - if let Some(res) = rewrite { - let width = self.block_indent.width() + fn_str.len() + res.len() + 4; - if !res.contains('\n') && width <= self.config.max_width() { - return Some(format!("{}{{ {} }}", fn_str, res)); - } - } - } - - None - } - - pub fn visit_static(&mut self, static_parts: &StaticParts) { - let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); - self.push_rewrite(static_parts.span, rewrite); - } - - pub fn visit_struct(&mut self, struct_parts: &StructParts) { - let is_tuple = struct_parts.def.is_tuple(); - let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) - .map(|s| if is_tuple { s + ";" } else { s }); - self.push_rewrite(struct_parts.span, rewrite); - } - - pub fn visit_enum( - &mut self, - ident: ast::Ident, - vis: &ast::Visibility, - enum_def: &ast::EnumDef, - generics: &ast::Generics, - span: Span, - ) { - let enum_header = format_header("enum ", ident, vis); - self.push_str(&enum_header); - - let enum_snippet = self.snippet(span); - let brace_pos = enum_snippet.find_uncommented("{").unwrap(); - let body_start = span.lo() + BytePos(brace_pos as u32 + 1); - let generics_str = format_generics( - &self.get_context(), - generics, - self.config.brace_style(), - if enum_def.variants.is_empty() { - BracePos::ForceSameLine - } else { - BracePos::Auto - }, - self.block_indent, - mk_sp(span.lo(), body_start), - last_line_width(&enum_header), - ).unwrap(); - self.push_str(&generics_str); - - self.last_pos = body_start; - - self.block_indent = self.block_indent.block_indent(self.config); - let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); - match variant_list { - Some(ref body_str) => self.push_str(body_str), - None => self.format_missing_no_indent(span.hi() - BytePos(1)), - } - self.block_indent = self.block_indent.block_unindent(self.config); - - if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - } - self.push_str("}"); - self.last_pos = span.hi(); - } - - // Format the body of an enum definition - fn format_variant_list( - &self, - enum_def: &ast::EnumDef, - body_lo: BytePos, - body_hi: BytePos, - ) -> Option { - if enum_def.variants.is_empty() { - return None; - } - let mut result = String::with_capacity(1024); - let indentation = self.block_indent.to_string_with_newline(self.config); - result.push_str(&indentation); - - let itemize_list_with = |one_line_width: usize| { - itemize_list( - self.snippet_provider, - enum_def.variants.iter(), - "}", - ",", - |f| { - if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo() - } else { - f.span.lo() - } - }, - |f| f.span.hi(), - |f| self.format_variant(f, one_line_width), - body_lo, - body_hi, - false, - ).collect() - }; - let mut items: Vec<_> = - itemize_list_with(self.config.width_heuristics().struct_variant_width); - // If one of the variants use multiple lines, use multi-lined formatting for all variants. - let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); - let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); - if has_multiline_variant && has_single_line_variant { - items = itemize_list_with(0); - } - - let shape = self.shape().sub_width(2)?; - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: ",", - trailing_separator: self.config.trailing_comma(), - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: true, - preserve_newline: true, - config: self.config, - }; - - let list = write_list(&items, &fmt)?; - result.push_str(&list); - result.push('\n'); - Some(result) - } - - // Variant of an enum. - fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option { - if contains_skip(&field.node.attrs) { - let lo = field.node.attrs[0].span.lo(); - let span = mk_sp(lo, field.span.hi()); - return Some(self.snippet(span).to_owned()); - } - - let context = self.get_context(); - // 1 = ',' - let shape = self.shape().sub_width(1)?; - let attrs_str = field.node.attrs.rewrite(&context, shape)?; - let lo = field - .node - .attrs - .last() - .map_or(field.span.lo(), |attr| attr.span.hi()); - let span = mk_sp(lo, field.span.lo()); - - let variant_body = match field.node.data { - ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( - &context, - &StructParts::from_variant(field), - self.block_indent, - Some(one_line_width), - )?, - ast::VariantData::Unit(..) => { - if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", field.node.name); - rewrite_assign_rhs(&context, lhs, &**expr, shape)? - } else { - field.node.name.to_string() - } - } - }; - - combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) - } -} - -pub fn format_impl( - context: &RewriteContext, - item: &ast::Item, - offset: Indent, - where_span_end: Option, -) -> Option { - if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { - let mut result = String::with_capacity(128); - let ref_and_type = format_impl_ref_and_type(context, item, offset)?; - let sep = offset.to_string_with_newline(context.config); - result.push_str(&ref_and_type); - - let where_budget = if result.contains('\n') { - context.config.max_width() - } else { - context.budget(last_line_width(&result)) - }; - let option = WhereClauseOption::snuggled(&ref_and_type); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - Density::Vertical, - "{", - where_span_end, - self_ty.span.hi(), - option, - false, - )?; - - // If there is no where clause, we may have missing comments between the trait name and - // the opening brace. - if generics.where_clause.predicates.is_empty() { - if let Some(hi) = where_span_end { - match recover_missing_comment_in_span( - mk_sp(self_ty.span.hi(), hi), - Shape::indented(offset, context.config), - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - } - _ => (), - } - } - } - - if is_impl_single_line(context, items, &result, &where_clause_str, item)? { - result.push_str(&where_clause_str); - if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { - result.push_str(&format!("{}{{{}}}", &sep, &sep)); - } else { - result.push_str(" {}"); - } - return Some(result); - } - - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string_with_newline(context.config)); - } - result.push_str(&where_clause_str); - - let need_newline = !last_line_extendable(&result) - && (last_line_contains_single_line_comment(&result) || result.contains('\n')); - match context.config.brace_style() { - _ if need_newline => result.push_str(&sep), - BraceStyle::AlwaysNextLine => result.push_str(&sep), - BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { - result.push_str(&sep); - } else { - result.push(' '); - } - } - } - - result.push('{'); - - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - - if !items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); - - visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); - for item in items { - visitor.visit_impl_item(item); - } - - visitor.format_missing(item.span.hi() - BytePos(1)); - - let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); - let outer_indent_str = offset.block_only().to_string_with_newline(context.config); - - result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.to_string().trim()); - result.push_str(&outer_indent_str); - } - - if result.ends_with('{') { - result.push_str(&sep); - } - result.push('}'); - - Some(result) - } else { - unreachable!(); - } -} - -fn is_impl_single_line( - context: &RewriteContext, - items: &[ImplItem], - result: &str, - where_clause_str: &str, - item: &ast::Item, -) -> Option { - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - - Some( - context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n') - && result.len() + where_clause_str.len() <= context.config.max_width() - && !contains_comment(&snippet[open_pos..]), - ) -} - -fn format_impl_ref_and_type( - context: &RewriteContext, - item: &ast::Item, - offset: Indent, -) -> Option { - if let ast::ItemKind::Impl( - unsafety, - polarity, - defaultness, - ref generics, - ref trait_ref, - ref self_ty, - _, - ) = item.node - { - let mut result = String::with_capacity(128); - - result.push_str(&format_visibility(&item.vis)); - result.push_str(format_defaultness(defaultness)); - result.push_str(format_unsafety(unsafety)); - result.push_str("impl"); - - let lo = context.snippet_provider.span_after(item.span, "impl"); - let hi = match *trait_ref { - Some(ref tr) => tr.path.span.lo(), - None => self_ty.span.lo(), - }; - let shape = generics_shape_from_config( - context.config, - Shape::indented(offset + last_line_width(&result), context.config), - 0, - )?; - let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?; - let generics_str = - rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?; - - let polarity_str = if polarity == ast::ImplPolarity::Negative { - "!" - } else { - "" - }; - - if let Some(ref trait_ref) = *trait_ref { - let result_len = result.len(); - if let Some(trait_ref_str) = rewrite_trait_ref( - context, - trait_ref, - offset, - &generics_str, - true, - polarity_str, - result_len, - ) { - result.push_str(&trait_ref_str); - } else { - let generics_str = - rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?; - result.push_str(&rewrite_trait_ref( - context, - trait_ref, - offset, - &generics_str, - false, - polarity_str, - result_len, - )?); - } - } else { - result.push_str(&generics_str); - } - - // Try to put the self type in a single line. - // ` for` - let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; - let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { - // If there is no where clause adapt budget for type formatting to take space and curly - // brace into account. - match context.config.brace_style() { - BraceStyle::AlwaysNextLine => 0, - _ => 2, - } - } else { - 0 - }; - let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; - // 1 = space before the type. - let budget = context.budget(used_space + 1); - if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { - if !self_ty_str.contains('\n') { - if trait_ref.is_some() { - result.push_str(" for "); - } else { - result.push(' '); - } - result.push_str(&self_ty_str); - return Some(result); - } - } - - // Couldn't fit the self type on a single line, put it on a new line. - result.push('\n'); - // Add indentation of one additional tab. - let new_line_offset = offset.block_indent(context.config); - result.push_str(&new_line_offset.to_string(context.config)); - if trait_ref.is_some() { - result.push_str("for "); - } - let budget = context.budget(last_line_width(&result)); - let type_offset = match context.config.indent_style() { - IndentStyle::Visual => new_line_offset + trait_ref_overhead, - IndentStyle::Block => new_line_offset, - }; - result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); - Some(result) - } else { - unreachable!(); - } -} - -fn rewrite_trait_ref( - context: &RewriteContext, - trait_ref: &ast::TraitRef, - offset: Indent, - generics_str: &str, - retry: bool, - polarity_str: &str, - result_len: usize, -) -> Option { - // 1 = space between generics and trait_ref - let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len); - let shape = Shape::indented(offset + used_space, context.config); - if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { - if !(retry && trait_ref_str.contains('\n')) { - return Some(format!( - "{} {}{}", - generics_str, polarity_str, &trait_ref_str - )); - } - } - // We could not make enough space for trait_ref, so put it on new line. - if !retry { - let offset = offset.block_indent(context.config); - let shape = Shape::indented(offset, context.config); - let trait_ref_str = trait_ref.rewrite(context, shape)?; - Some(format!( - "{}\n{}{}{}", - generics_str, - &offset.to_string(context.config), - polarity_str, - &trait_ref_str - )) - } else { - None - } -} - -pub struct StructParts<'a> { - prefix: &'a str, - ident: ast::Ident, - vis: &'a ast::Visibility, - def: &'a ast::VariantData, - generics: Option<&'a ast::Generics>, - span: Span, -} - -impl<'a> StructParts<'a> { - fn format_header(&self) -> String { - format_header(self.prefix, self.ident, self.vis) - } - - fn from_variant(variant: &'a ast::Variant) -> Self { - StructParts { - prefix: "", - ident: variant.node.name, - vis: &ast::Visibility::Inherited, - def: &variant.node.data, - generics: None, - span: variant.span, - } - } - - pub fn from_item(item: &'a ast::Item) -> Self { - let (prefix, def, generics) = match item.node { - ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), - ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), - _ => unreachable!(), - }; - StructParts { - prefix, - ident: item.ident, - vis: &item.vis, - def, - generics: Some(generics), - span: item.span, - } - } -} - -fn format_struct( - context: &RewriteContext, - struct_parts: &StructParts, - offset: Indent, - one_line_width: Option, -) -> Option { - match *struct_parts.def { - ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset), - ast::VariantData::Tuple(ref fields, _) => { - format_tuple_struct(context, struct_parts, fields, offset) - } - ast::VariantData::Struct(ref fields, _) => { - format_struct_struct(context, struct_parts, fields, offset, one_line_width) - } - } -} - -pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node - { - let mut result = String::with_capacity(128); - let header = format!( - "{}{}trait {}", - format_visibility(&item.vis), - format_unsafety(unsafety), - item.ident - ); - - result.push_str(&header); - - let body_lo = context.snippet_provider.span_after(item.span, "{"); - - let shape = Shape::indented(offset, context.config).offset_left(result.len())?; - let generics_str = - rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; - result.push_str(&generics_str); - - // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. - if !type_param_bounds.is_empty() { - let ident_hi = context - .snippet_provider - .span_after(item.span, &format!("{}", item.ident)); - let bound_hi = type_param_bounds.last().unwrap().span().hi(); - let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); - if contains_comment(snippet) { - return None; - } - } - let trait_bound_str = rewrite_trait_bounds( - context, - type_param_bounds, - Shape::indented(offset, context.config), - )?; - // If the trait, generics, and trait bound cannot fit on the same line, - // put the trait bounds on an indented new line - if offset.width() + last_line_width(&result) + trait_bound_str.len() - > context.config.comment_width() - { - let trait_indent = offset.block_only().block_indent(context.config); - result.push_str(&trait_indent.to_string_with_newline(context.config)); - } - result.push_str(&trait_bound_str); - - let where_density = - if context.config.indent_style() == IndentStyle::Block && result.is_empty() { - Density::Compressed - } else { - Density::Tall - }; - - let where_budget = context.budget(last_line_width(&result)); - let pos_before_where = if type_param_bounds.is_empty() { - generics.where_clause.span.lo() - } else { - type_param_bounds[type_param_bounds.len() - 1].span().hi() - }; - let option = WhereClauseOption::snuggled(&generics_str); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - where_density, - "{", - None, - pos_before_where, - option, - false, - )?; - // If the where clause cannot fit on the same line, - // put the where clause on a new line - if !where_clause_str.contains('\n') - && last_line_width(&result) + where_clause_str.len() + offset.width() - > context.config.comment_width() - { - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string_with_newline(context.config)); - } - result.push_str(&where_clause_str); - - if generics.where_clause.predicates.is_empty() { - let item_snippet = context.snippet(item.span); - if let Some(lo) = item_snippet.chars().position(|c| c == '/') { - // 1 = `{` - let comment_hi = body_lo - BytePos(1); - let comment_lo = item.span.lo() + BytePos(lo as u32); - if comment_lo < comment_hi { - match recover_missing_comment_in_span( - mk_sp(comment_lo, comment_hi), - Shape::indented(offset, context.config), - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - } - _ => (), - } - } - } - } - - match context.config.brace_style() { - _ if last_line_contains_single_line_comment(&result) => { - result.push_str(&offset.to_string_with_newline(context.config)); - } - BraceStyle::AlwaysNextLine => { - result.push_str(&offset.to_string_with_newline(context.config)); - } - BraceStyle::PreferSameLine => result.push(' '), - BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() - && (!trait_items.is_empty() || result.contains('\n')) - { - result.push_str(&offset.to_string_with_newline(context.config)); - } else { - result.push(' '); - } - } - } - result.push('{'); - - let snippet = context.snippet(item.span); - let open_pos = snippet.find_uncommented("{")? + 1; - - if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); - - for item in trait_items { - visitor.visit_trait_item(item); - } - - visitor.format_missing(item.span.hi() - BytePos(1)); - - let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); - let outer_indent_str = offset.block_only().to_string_with_newline(context.config); - - result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.to_string().trim()); - result.push_str(&outer_indent_str); - } else if result.contains('\n') { - result.push('\n'); - } - - result.push('}'); - Some(result) - } else { - unreachable!(); - } -} - -pub fn format_trait_alias( - context: &RewriteContext, - ident: ast::Ident, - generics: &ast::Generics, - ty_param_bounds: &ast::TyParamBounds, - shape: Shape, -) -> Option { - let alias = ident.name.as_str(); - // 6 = "trait ", 2 = " =" - let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?; - let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?; - let lhs = format!("trait {}{} =", alias, generics_str); - // 1 = ";" - rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") -} - -fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { - let header_str = format_header(p.prefix, p.ident, p.vis); - let generics_str = if let Some(generics) = p.generics { - let hi = if generics.where_clause.predicates.is_empty() { - generics.span.hi() - } else { - generics.where_clause.span.hi() - }; - format_generics( - context, - generics, - context.config.brace_style(), - BracePos::None, - offset, - mk_sp(generics.span.lo(), hi), - last_line_width(&header_str), - )? - } else { - String::new() - }; - Some(format!("{}{};", header_str, generics_str)) -} - -pub fn format_struct_struct( - context: &RewriteContext, - struct_parts: &StructParts, - fields: &[ast::StructField], - offset: Indent, - one_line_width: Option, -) -> Option { - let mut result = String::with_capacity(1024); - let span = struct_parts.span; - - let header_str = struct_parts.format_header(); - result.push_str(&header_str); - - let header_hi = span.lo() + BytePos(header_str.len() as u32); - let body_lo = context.snippet_provider.span_after(span, "{"); - - let generics_str = match struct_parts.generics { - Some(g) => format_generics( - context, - g, - context.config.brace_style(), - if fields.is_empty() { - BracePos::ForceSameLine - } else { - BracePos::Auto - }, - offset, - mk_sp(header_hi, body_lo), - last_line_width(&result), - )?, - None => { - // 3 = ` {}`, 2 = ` {`. - let overhead = if fields.is_empty() { 3 } else { 2 }; - if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty()) - || context.config.max_width() < overhead + result.len() - { - format!("\n{}{{", offset.block_only().to_string(context.config)) - } else { - " {".to_owned() - } - } - }; - // 1 = `}` - let overhead = if fields.is_empty() { 1 } else { 0 }; - let total_width = result.len() + generics_str.len() + overhead; - if !generics_str.is_empty() && !generics_str.contains('\n') - && total_width > context.config.max_width() - { - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - result.push_str(generics_str.trim_left()); - } else { - result.push_str(&generics_str); - } - - if fields.is_empty() { - let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1))); - if snippet.trim().is_empty() { - // `struct S {}` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - // fix indent - result.push_str(snippet.trim_right()); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push_str(snippet); - } - result.push('}'); - return Some(result); - } - - // 3 = ` ` and ` }` - let one_line_budget = context.budget(result.len() + 3 + offset.width()); - let one_line_budget = - one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); - - let items_str = rewrite_with_alignment( - fields, - context, - Shape::indented(offset, context.config).sub_width(1)?, - mk_sp(body_lo, span.hi()), - one_line_budget, - )?; - - if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget - && !last_line_contains_single_line_comment(&items_str) - { - Some(format!("{} {} }}", result, items_str)) - } else { - Some(format!( - "{}\n{}{}\n{}}}", - result, - offset - .block_indent(context.config) - .to_string(context.config), - items_str, - offset.to_string(context.config) - )) - } -} - -/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not -/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need -/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args. -fn get_bytepos_after_visibility( - context: &RewriteContext, - vis: &ast::Visibility, - default_span: Span, - terminator: &str, -) -> BytePos { - match *vis { - ast::Visibility::Crate(s, CrateSugar::PubCrate) => context - .snippet_provider - .span_after(mk_sp(s.hi(), default_span.hi()), terminator), - ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), - ast::Visibility::Restricted { ref path, .. } => path.span.hi(), - _ => default_span.lo(), - } -} - -fn format_tuple_struct( - context: &RewriteContext, - struct_parts: &StructParts, - fields: &[ast::StructField], - offset: Indent, -) -> Option { - let mut result = String::with_capacity(1024); - let span = struct_parts.span; - - let header_str = struct_parts.format_header(); - result.push_str(&header_str); - - let body_lo = if fields.is_empty() { - let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")"); - context - .snippet_provider - .span_after(mk_sp(lo, span.hi()), "(") - } else { - fields[0].span.lo() - }; - let body_hi = if fields.is_empty() { - context - .snippet_provider - .span_after(mk_sp(body_lo, span.hi()), ")") - } else { - // This is a dirty hack to work around a missing `)` from the span of the last field. - let last_arg_span = fields[fields.len() - 1].span; - if context.snippet(last_arg_span).ends_with(')') { - last_arg_span.hi() - } else { - context - .snippet_provider - .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") - } - }; - - let where_clause_str = match struct_parts.generics { - Some(generics) => { - let budget = context.budget(last_line_width(&header_str)); - let shape = Shape::legacy(budget, offset); - let g_span = mk_sp(span.lo(), body_lo); - let generics_str = rewrite_generics(context, generics, shape, g_span)?; - result.push_str(&generics_str); - - let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::new(true, false); - rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - Density::Compressed, - ";", - None, - body_hi, - option, - false, - )? - } - None => "".to_owned(), - }; - - if fields.is_empty() { - // 3 = `();` - let used_width = last_line_used_width(&result, offset.width()) + 3; - if used_width > context.config.max_width() { - result.push('\n'); - result.push_str(&offset - .block_indent(context.config) - .to_string(context.config)) - } - result.push('('); - let snippet = context.snippet(mk_sp( - body_lo, - context - .snippet_provider - .span_before(mk_sp(body_lo, span.hi()), ")"), - )); - if snippet.is_empty() { - // `struct S ()` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - result.push_str(snippet.trim_right()); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push_str(snippet); - } - result.push(')'); - } else { - let shape = Shape::indented(offset, context.config).sub_width(1)?; - let fields = &fields.iter().collect::>()[..]; - let one_line_width = context.config.width_heuristics().fn_call_width; - result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; - } - - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') - && (result.contains('\n') - || offset.block_indent + result.len() + where_clause_str.len() + 1 - > context.config.max_width()) - { - // We need to put the where clause on a new line, but we didn't - // know that earlier, so the where clause will not be indented properly. - result.push('\n'); - result - .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) - .to_string(context.config)); - } - result.push_str(&where_clause_str); - - Some(result) -} - -pub fn rewrite_type_alias( - context: &RewriteContext, - indent: Indent, - ident: ast::Ident, - ty: &ast::Ty, - generics: &ast::Generics, - vis: &ast::Visibility, - span: Span, -) -> Option { - let mut result = String::with_capacity(128); - - result.push_str(&format_visibility(vis)); - result.push_str("type "); - result.push_str(&ident.to_string()); - - // 2 = `= ` - let g_shape = Shape::indented(indent, context.config) - .offset_left(result.len())? - .sub_width(2)?; - let g_span = mk_sp( - context.snippet_provider.span_after(span, "type"), - ty.span.lo(), - ); - let generics_str = rewrite_generics(context, generics, g_shape, g_span)?; - result.push_str(&generics_str); - - let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::snuggled(&result); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, indent), - Density::Vertical, - "=", - Some(span.hi()), - generics.span.hi(), - option, - false, - )?; - result.push_str(&where_clause_str); - if where_clause_str.is_empty() { - result.push_str(" ="); - } else { - result.push_str(&format!( - "{}=", - indent.to_string_with_newline(context.config) - )); - } - - // 1 = ";" - let ty_shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";") -} - -fn type_annotation_spacing(config: &Config) -> (&str, &str) { - ( - if config.space_before_colon() { " " } else { "" }, - if config.space_after_colon() { " " } else { "" }, - ) -} - -pub fn rewrite_struct_field_prefix( - context: &RewriteContext, - field: &ast::StructField, -) -> Option { - let vis = format_visibility(&field.vis); - let type_annotation_spacing = type_annotation_spacing(context.config); - Some(match field.ident { - Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), - None => format!("{}", vis), - }) -} - -impl Rewrite for ast::StructField { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_struct_field(context, self, shape, 0) - } -} - -pub fn rewrite_struct_field( - context: &RewriteContext, - field: &ast::StructField, - shape: Shape, - lhs_max_width: usize, -) -> Option { - if contains_skip(&field.attrs) { - return Some(context.snippet(field.span()).to_owned()); - } - - let type_annotation_spacing = type_annotation_spacing(context.config); - let prefix = rewrite_struct_field_prefix(context, field)?; - - let attrs_str = field.attrs.rewrite(context, shape)?; - let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str); - let missing_span = if field.attrs.is_empty() { - mk_sp(field.span.lo(), field.span.lo()) - } else { - mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo()) - }; - let mut spacing = String::from(if field.ident.is_some() { - type_annotation_spacing.1 - } else { - "" - }); - // Try to put everything on a single line. - let attr_prefix = combine_strs_with_missing_comments( - context, - &attrs_str, - &prefix, - missing_span, - shape, - attrs_extendable, - )?; - let overhead = last_line_width(&attr_prefix); - let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); - for _ in 0..lhs_offset { - spacing.push(' '); - } - // In this extreme case we will be missing a space betweeen an attribute and a field. - if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { - spacing.push(' '); - } - let orig_ty = shape - .offset_left(overhead + spacing.len()) - .and_then(|ty_shape| field.ty.rewrite(context, ty_shape)); - if let Some(ref ty) = orig_ty { - if !ty.contains('\n') { - return Some(attr_prefix + &spacing + ty); - } - } - - let is_prefix_empty = prefix.is_empty(); - // We must use multiline. We are going to put attributes and a field on different lines. - let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; - // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. - let field_str = if is_prefix_empty { - field_str.trim_left() - } else { - &field_str - }; - combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) -} - -pub struct StaticParts<'a> { - prefix: &'a str, - vis: &'a ast::Visibility, - ident: ast::Ident, - ty: &'a ast::Ty, - mutability: ast::Mutability, - expr_opt: Option<&'a ptr::P>, - defaultness: Option, - span: Span, -} - -impl<'a> StaticParts<'a> { - pub fn from_item(item: &'a ast::Item) -> Self { - let (prefix, ty, mutability, expr) = match item.node { - ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), - ast::ItemKind::Const(ref ty, ref expr) => { - ("const", ty, ast::Mutability::Immutable, expr) - } - _ => unreachable!(), - }; - StaticParts { - prefix, - vis: &item.vis, - ident: item.ident, - ty, - mutability, - expr_opt: Some(expr), - defaultness: None, - span: item.span, - } - } - - pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self { - let (ty, expr_opt) = match ti.node { - ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), - _ => unreachable!(), - }; - StaticParts { - prefix: "const", - vis: &ast::Visibility::Inherited, - ident: ti.ident, - ty, - mutability: ast::Mutability::Immutable, - expr_opt: expr_opt.as_ref(), - defaultness: None, - span: ti.span, - } - } - - pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self { - let (ty, expr) = match ii.node { - ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), - _ => unreachable!(), - }; - StaticParts { - prefix: "const", - vis: &ii.vis, - ident: ii.ident, - ty, - mutability: ast::Mutability::Immutable, - expr_opt: Some(expr), - defaultness: Some(ii.defaultness), - span: ii.span, - } - } -} - -fn rewrite_static( - context: &RewriteContext, - static_parts: &StaticParts, - offset: Indent, -) -> Option { - let colon = colon_spaces( - context.config.space_before_colon(), - context.config.space_after_colon(), - ); - let mut prefix = format!( - "{}{}{} {}{}{}", - format_visibility(static_parts.vis), - static_parts.defaultness.map_or("", format_defaultness), - static_parts.prefix, - format_mutability(static_parts.mutability), - static_parts.ident, - colon, - ); - // 2 = " =".len() - let ty_shape = - Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; - let ty_str = match static_parts.ty.rewrite(context, ty_shape) { - Some(ty_str) => ty_str, - None => { - if prefix.ends_with(' ') { - prefix.pop(); - } - let nested_indent = offset.block_indent(context.config); - let nested_shape = Shape::indented(nested_indent, context.config); - let ty_str = static_parts.ty.rewrite(context, nested_shape)?; - format!( - "{}{}", - nested_indent.to_string_with_newline(context.config), - ty_str - ) - } - }; - - if let Some(expr) = static_parts.expr_opt { - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.budget(offset.block_indent + 1); - rewrite_assign_rhs( - context, - lhs, - &**expr, - Shape::legacy(remaining_width, offset.block_only()), - ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) - .map(|s| if s.ends_with(';') { s } else { s + ";" }) - } else { - Some(format!("{}{};", prefix, ty_str)) - } -} - -pub fn rewrite_associated_type( - ident: ast::Ident, - ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, - context: &RewriteContext, - indent: Indent, -) -> Option { - let prefix = format!("type {}", ident); - - let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { - // 2 = ": ".len() - let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - if !bounds.is_empty() { - format!(": {}", join_bounds(context, shape, &bound_str)) - } else { - String::new() - } - } else { - String::new() - }; - - if let Some(ty) = ty_opt { - // 1 = `;` - let shape = Shape::indented(indent, context.config).sub_width(1)?; - let lhs = format!("{}{} =", prefix, type_bounds_str); - rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") - } else { - Some(format!("{}{};", prefix, type_bounds_str)) - } -} - -pub fn rewrite_associated_impl_type( - ident: ast::Ident, - defaultness: ast::Defaultness, - ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, - context: &RewriteContext, - indent: Indent, -) -> Option { - let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?; - - match defaultness { - ast::Defaultness::Default => Some(format!("default {}", result)), - _ => Some(result), - } -} - -impl Rewrite for ast::FunctionRetTy { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::FunctionRetTy::Default(_) => Some(String::new()), - ast::FunctionRetTy::Ty(ref ty) => { - let inner_width = shape.width.checked_sub(3)?; - ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) - .map(|r| format!("-> {}", r)) - } - } - } -} - -fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { - match ty.node { - ast::TyKind::Infer => { - let original = context.snippet(ty.span); - original != "_" - } - _ => false, - } -} - -impl Rewrite for ast::Arg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if is_named_arg(self) { - let mut result = self.pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))?; - - if !is_empty_infer(context, &*self.ty) { - if context.config.space_before_colon() { - result.push_str(" "); - } - result.push_str(":"); - if context.config.space_after_colon() { - result.push_str(" "); - } - let overhead = last_line_width(&result); - let max_width = shape.width.checked_sub(overhead)?; - let ty_str = self.ty - .rewrite(context, Shape::legacy(max_width, shape.indent))?; - result.push_str(&ty_str); - } - - Some(result) - } else { - self.ty.rewrite(context, shape) - } - } -} - -fn rewrite_explicit_self( - explicit_self: &ast::ExplicitSelf, - args: &[ast::Arg], - context: &RewriteContext, -) -> Option { - match explicit_self.node { - ast::SelfKind::Region(lt, m) => { - let mut_str = format_mutability(m); - match lt { - Some(ref l) => { - let lifetime_str = l.rewrite( - context, - Shape::legacy(context.config.max_width(), Indent::empty()), - )?; - Some(format!("&{} {}self", lifetime_str, mut_str)) - } - None => Some(format!("&{}self", mut_str)), - } - } - ast::SelfKind::Explicit(ref ty, _) => { - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - - let mutability = explicit_self_mutability(&args[0]); - let type_str = ty.rewrite( - context, - Shape::legacy(context.config.max_width(), Indent::empty()), - )?; - - Some(format!( - "{}self: {}", - format_mutability(mutability), - type_str - )) - } - ast::SelfKind::Value(_) => { - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - - let mutability = explicit_self_mutability(&args[0]); - - Some(format!("{}self", format_mutability(mutability))) - } - } -} - -// Hacky solution caused by absence of `Mutability` in `SelfValue` and -// `SelfExplicit` variants of `ast::ExplicitSelf_`. -fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { - if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node { - mutability - } else { - unreachable!() - } -} - -pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { - if is_named_arg(arg) { - arg.pat.span.lo() - } else { - arg.ty.span.lo() - } -} - -pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { - match arg.ty.node { - ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), - ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), - _ => arg.ty.span.hi(), - } -} - -pub fn is_named_arg(arg: &ast::Arg) -> bool { - if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != symbol::keywords::Invalid.ident() - } else { - true - } -} - -// Return type is (result, force_new_line_for_brace) -fn rewrite_fn_base( - context: &RewriteContext, - indent: Indent, - ident: ast::Ident, - fn_sig: &FnSig, - span: Span, - newline_brace: bool, - has_body: bool, -) -> Option<(String, bool)> { - let mut force_new_line_for_brace = false; - - let where_clause = &fn_sig.generics.where_clause; - - let mut result = String::with_capacity(1024); - result.push_str(&fn_sig.to_str(context)); - - // fn foo - result.push_str("fn "); - result.push_str(&ident.to_string()); - - // Generics. - let overhead = if has_body && !newline_brace { - // 4 = `() {` - 4 - } else { - // 2 = `()` - 2 - }; - let used_width = last_line_used_width(&result, indent.width()); - let one_line_budget = context.budget(used_width + overhead); - let shape = Shape { - width: one_line_budget, - indent, - offset: used_width, - }; - let fd = fn_sig.decl; - let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?; - result.push_str(&generics_str); - - let snuggle_angle_bracket = generics_str - .lines() - .last() - .map_or(false, |l| l.trim_left().len() == 1); - - // Note that the width and indent don't really matter, we'll re-layout the - // return type later anyway. - let ret_str = fd.output - .rewrite(context, Shape::indented(indent, context.config))?; - - let multi_line_ret_str = ret_str.contains('\n'); - let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; - - // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args( - context, - &result, - indent, - ret_str_len, - newline_brace, - has_body, - multi_line_ret_str, - )?; - - debug!( - "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", - one_line_budget, multi_line_budget, arg_indent - ); - - // Check if vertical layout was forced. - if one_line_budget == 0 { - if snuggle_angle_bracket { - result.push('('); - } else { - result.push_str("("); - if context.config.indent_style() == IndentStyle::Visual { - result.push_str(&arg_indent.to_string_with_newline(context.config)); - } - } - } else { - result.push('('); - } - if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() - && result.ends_with('(') - { - result.push(' ') - } - - // Skip `pub(crate)`. - let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")"); - // A conservative estimation, to goal is to be over all parens in generics - let args_start = fn_sig - .generics - .params - .iter() - .last() - .map_or(lo_after_visibility, |param| param.span().hi()); - let args_end = if fd.inputs.is_empty() { - context - .snippet_provider - .span_after(mk_sp(args_start, span.hi()), ")") - } else { - let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); - context.snippet_provider.span_after(last_span, ")") - }; - let args_span = mk_sp( - context - .snippet_provider - .span_after(mk_sp(args_start, span.hi()), "("), - args_end, - ); - let arg_str = rewrite_args( - context, - &fd.inputs, - fd.get_self().as_ref(), - one_line_budget, - multi_line_budget, - indent, - arg_indent, - args_span, - fd.variadic, - generics_str.contains('\n'), - )?; - - let put_args_in_block = match context.config.indent_style() { - IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, - _ => false, - } && !fd.inputs.is_empty(); - - let mut args_last_line_contains_comment = false; - if put_args_in_block { - arg_indent = indent.block_indent(context.config); - result.push_str(&arg_indent.to_string_with_newline(context.config)); - result.push_str(&arg_str); - result.push_str(&indent.to_string_with_newline(context.config)); - result.push(')'); - } else { - result.push_str(&arg_str); - let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); - // Put the closing brace on the next line if it overflows the max width. - // 1 = `)` - if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { - result.push('\n'); - } - if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() { - result.push(' ') - } - // If the last line of args contains comment, we cannot put the closing paren - // on the same line. - if arg_str - .lines() - .last() - .map_or(false, |last_line| last_line.contains("//")) - { - args_last_line_contains_comment = true; - result.push_str(&arg_indent.to_string_with_newline(context.config)); - } - result.push(')'); - } - - // Return type. - if let ast::FunctionRetTy::Ty(..) = fd.output { - let ret_should_indent = match context.config.indent_style() { - // If our args are block layout then we surely must have space. - IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, - _ if args_last_line_contains_comment => false, - _ if result.contains('\n') || multi_line_ret_str => true, - _ => { - // If the return type would push over the max width, then put the return type on - // a new line. With the +1 for the signature length an additional space between - // the closing parenthesis of the argument and the arrow '->' is considered. - let mut sig_length = result.len() + indent.width() + ret_str_len + 1; - - // If there is no where clause, take into account the space after the return type - // and the brace. - if where_clause.predicates.is_empty() { - sig_length += 2; - } - - sig_length > context.config.max_width() - } - }; - let ret_indent = if ret_should_indent { - let indent = if arg_str.is_empty() { - // Aligning with non-existent args looks silly. - force_new_line_for_brace = true; - indent + 4 - } else { - // FIXME: we might want to check that using the arg indent - // doesn't blow our budget, and if it does, then fallback to - // the where clause indent. - arg_indent - }; - - result.push_str(&indent.to_string_with_newline(context.config)); - indent - } else { - result.push(' '); - Indent::new(indent.block_indent, last_line_width(&result)) - }; - - if multi_line_ret_str || ret_should_indent { - // Now that we know the proper indent and width, we need to - // re-layout the return type. - let ret_str = fd.output - .rewrite(context, Shape::indented(ret_indent, context.config))?; - result.push_str(&ret_str); - } else { - result.push_str(&ret_str); - } - - // Comment between return type and the end of the decl. - let snippet_lo = fd.output.span().hi(); - if where_clause.predicates.is_empty() { - let snippet_hi = span.hi(); - let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); - // Try to preserve the layout of the original snippet. - let original_starts_with_newline = snippet - .find(|c| c != ' ') - .map_or(false, |i| starts_with_newline(&snippet[i..])); - let original_ends_with_newline = snippet - .rfind(|c| c != ' ') - .map_or(false, |i| snippet[i..].ends_with('\n')); - let snippet = snippet.trim(); - if !snippet.is_empty() { - result.push(if original_starts_with_newline { - '\n' - } else { - ' ' - }); - result.push_str(snippet); - if original_ends_with_newline { - force_new_line_for_brace = true; - } - } - } - } - - let pos_before_where = match fd.output { - ast::FunctionRetTy::Default(..) => args_span.hi(), - ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), - }; - - let is_args_multi_lined = arg_str.contains('\n'); - - let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); - let where_clause_str = rewrite_where_clause( - context, - where_clause, - context.config.brace_style(), - Shape::indented(indent, context.config), - Density::Tall, - "{", - Some(span.hi()), - pos_before_where, - option, - is_args_multi_lined, - )?; - // If there are neither where clause nor return type, we may be missing comments between - // args and `{`. - if where_clause_str.is_empty() { - if let ast::FunctionRetTy::Default(ret_span) = fd.output { - match recover_missing_comment_in_span( - mk_sp(args_span.hi(), ret_span.hi()), - shape, - context, - last_line_width(&result), - ) { - Some(ref missing_comment) if !missing_comment.is_empty() => { - result.push_str(missing_comment); - force_new_line_for_brace = true; - } - _ => (), - } - } - } - - result.push_str(&where_clause_str); - - force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line(); - Some((result, force_new_line_for_brace)) -} - -#[derive(Copy, Clone)] -struct WhereClauseOption { - suppress_comma: bool, // Force no trailing comma - snuggle: bool, // Do not insert newline before `where` - compress_where: bool, // Try single line where clause instead of vertical layout -} - -impl WhereClauseOption { - pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { - WhereClauseOption { - suppress_comma, - snuggle, - compress_where: false, - } - } - - pub fn snuggled(current: &str) -> WhereClauseOption { - WhereClauseOption { - suppress_comma: false, - snuggle: trimmed_last_line_width(current) == 1, - compress_where: false, - } - } -} - -fn rewrite_args( - context: &RewriteContext, - args: &[ast::Arg], - explicit_self: Option<&ast::ExplicitSelf>, - one_line_budget: usize, - multi_line_budget: usize, - indent: Indent, - arg_indent: Indent, - span: Span, - variadic: bool, - generics_str_contains_newline: bool, -) -> Option { - let mut arg_item_strs = args.iter() - .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) - .collect::>>()?; - - // Account for sugary self. - // FIXME: the comment for the self argument is dropped. This is blocked - // on rust issue #27522. - let min_args = explicit_self - .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) - .map_or(1, |self_str| { - arg_item_strs[0] = self_str; - 2 - }); - - // Comments between args. - let mut arg_items = Vec::new(); - if min_args == 2 { - arg_items.push(ListItem::from_str("")); - } - - // FIXME(#21): if there are no args, there might still be a comment, but - // without spans for the comment or parens, there is no chance of - // getting it right. You also don't get to put a comment on self, unless - // it is explicit. - if args.len() >= min_args || variadic { - let comment_span_start = if min_args == 2 { - let second_arg_start = if arg_has_pattern(&args[1]) { - args[1].pat.span.lo() - } else { - args[1].ty.span.lo() - }; - let reduced_span = mk_sp(span.lo(), second_arg_start); - - context.snippet_provider.span_after_last(reduced_span, ",") - } else { - span.lo() - }; - - enum ArgumentKind<'a> { - Regular(&'a ast::Arg), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi()); - let variadic_start = - context.snippet_provider.span_after(variadic_span, "...") - BytePos(3); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - - let more_items = itemize_list( - context.snippet_provider, - args[min_args - 1..] - .iter() - .map(ArgumentKind::Regular) - .chain(variadic_arg), - ")", - ",", - |arg| match *arg { - ArgumentKind::Regular(arg) => span_lo_for_arg(arg), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi(), - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => Some("...".to_owned()), - }, - comment_span_start, - span.hi(), - false, - ); - - arg_items.extend(more_items); - } - - let fits_in_one_line = !generics_str_contains_newline - && (arg_items.is_empty() - || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); - - for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { - item.item = Some(arg); - } - - let last_line_ends_with_comment = arg_items - .iter() - .last() - .and_then(|item| item.post_comment.as_ref()) - .map_or(false, |s| s.trim().starts_with("//")); - - let (indent, trailing_comma) = match context.config.indent_style() { - IndentStyle::Block if fits_in_one_line => { - (indent.block_indent(context.config), SeparatorTactic::Never) - } - IndentStyle::Block => ( - indent.block_indent(context.config), - context.config.trailing_comma(), - ), - IndentStyle::Visual if last_line_ends_with_comment => { - (arg_indent, context.config.trailing_comma()) - } - IndentStyle::Visual => (arg_indent, SeparatorTactic::Never), - }; - - let tactic = definitive_tactic( - &arg_items, - context.config.fn_args_density().to_list_tactic(), - Separator::Comma, - one_line_budget, - ); - let budget = match tactic { - DefinitiveListTactic::Horizontal => one_line_budget, - _ => multi_line_budget, - }; - - debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if variadic { - SeparatorTactic::Never - } else { - trailing_comma - }, - separator_place: SeparatorPlace::Back, - shape: Shape::legacy(budget, indent), - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - write_list(&arg_items, &fmt) -} - -fn arg_has_pattern(arg: &ast::Arg) -> bool { - if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != symbol::keywords::Invalid.ident() - } else { - true - } -} - -fn compute_budgets_for_args( - context: &RewriteContext, - result: &str, - indent: Indent, - ret_str_len: usize, - newline_brace: bool, - has_braces: bool, - force_vertical_layout: bool, -) -> Option<((usize, usize, Indent))> { - debug!( - "compute_budgets_for_args {} {:?}, {}, {}", - result.len(), - indent, - ret_str_len, - newline_brace - ); - // Try keeping everything on the same line. - if !result.contains('\n') && !force_vertical_layout { - // 2 = `()`, 3 = `() `, space is before ret_string. - let overhead = if ret_str_len == 0 { 2 } else { 3 }; - let mut used_space = indent.width() + result.len() + ret_str_len + overhead; - if has_braces { - if !newline_brace { - // 2 = `{}` - used_space += 2; - } - } else { - // 1 = `;` - used_space += 1; - } - let one_line_budget = context.budget(used_space); - - if one_line_budget > 0 { - // 4 = "() {".len() - let (indent, multi_line_budget) = match context.config.indent_style() { - IndentStyle::Block => { - let indent = indent.block_indent(context.config); - (indent, context.budget(indent.width() + 1)) - } - IndentStyle::Visual => { - let indent = indent + result.len() + 1; - let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; - (indent, context.budget(multi_line_overhead)) - } - }; - - return Some((one_line_budget, multi_line_budget, indent)); - } - } - - // Didn't work. we must force vertical layout and put args on a newline. - let new_indent = indent.block_indent(context.config); - let used_space = match context.config.indent_style() { - // 1 = `,` - IndentStyle::Block => new_indent.width() + 1, - // Account for `)` and possibly ` {`. - IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, - }; - Some((0, context.budget(used_space), new_indent)) -} - -fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { - let predicate_count = where_clause.predicates.len(); - - if config.where_single_line() && predicate_count == 1 { - return false; - } - let brace_style = config.brace_style(); - - brace_style == BraceStyle::AlwaysNextLine - || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0) -} - -fn rewrite_generics( - context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - span: Span, -) -> Option { - let g_shape = generics_shape_from_config(context.config, shape, 0)?; - let one_line_width = shape.width.checked_sub(2).unwrap_or(0); - rewrite_generics_inner(context, generics, g_shape, one_line_width, span) - .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span)) -} - -fn rewrite_generics_inner( - context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - one_line_width: usize, - span: Span, -) -> Option { - // FIXME: convert bounds to where clauses where they get too big or if - // there is a where clause at all. - - if generics.params.is_empty() { - return Some(String::new()); - } - - let items = itemize_list( - context.snippet_provider, - generics.params.iter(), - ">", - ",", - |arg| arg.span().lo(), - |arg| arg.span().hi(), - |arg| arg.rewrite(context, shape), - context.snippet_provider.span_after(span, "<"), - span.hi(), - false, - ); - format_generics_item_list(context, items, shape, one_line_width) -} - -pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { - match config.indent_style() { - IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), - IndentStyle::Block => { - // 1 = "," - shape - .block() - .block_indent(config.tab_spaces()) - .with_max_width(config) - .sub_width(1) - } - } -} - -pub fn format_generics_item_list( - context: &RewriteContext, - items: I, - shape: Shape, - one_line_budget: usize, -) -> Option -where - I: Iterator, -{ - let item_vec = items.collect::>(); - - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - one_line_budget, - ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if context.config.indent_style() == IndentStyle::Visual { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - let list_str = write_list(&item_vec, &fmt)?; - - Some(wrap_generics_with_angle_brackets( - context, - &list_str, - shape.indent, - )) -} - -pub fn wrap_generics_with_angle_brackets( - context: &RewriteContext, - list_str: &str, - list_offset: Indent, -) -> String { - if context.config.indent_style() == IndentStyle::Block - && (list_str.contains('\n') || list_str.ends_with(',')) - { - format!( - "<\n{}{}\n{}>", - list_offset.to_string(context.config), - list_str, - list_offset - .block_unindent(context.config) - .to_string(context.config) - ) - } else if context.config.spaces_within_parens_and_brackets() { - format!("< {} >", list_str) - } else { - format!("<{}>", list_str) - } -} - -fn rewrite_trait_bounds( - context: &RewriteContext, - bounds: &[ast::TyParamBound], - shape: Shape, -) -> Option { - if bounds.is_empty() { - return Some(String::new()); - } - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - Some(format!(": {}", join_bounds(context, shape, &bound_str))) -} - -fn rewrite_where_clause_rfc_style( - context: &RewriteContext, - where_clause: &ast::WhereClause, - shape: Shape, - terminator: &str, - span_end: Option, - span_end_before_where: BytePos, - where_clause_option: WhereClauseOption, - is_args_multi_line: bool, -) -> Option { - let block_shape = shape.block().with_max_width(context.config); - - let (span_before, span_after) = - missing_span_before_after_where(span_end_before_where, where_clause); - let (comment_before, comment_after) = - rewrite_comments_before_after_where(context, span_before, span_after, shape)?; - - let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { - Cow::from(" ") - } else { - block_shape.indent.to_string_with_newline(context.config) - }; - - let clause_shape = block_shape.block_left(context.config.tab_spaces())?; - // 1 = `,` - let clause_shape = clause_shape.sub_width(1)?; - // each clause on one line, trailing comma (except if suppress_comma) - let span_start = where_clause.predicates[0].span().lo(); - // If we don't have the start of the next span, then use the end of the - // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi(); - let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list( - context.snippet_provider, - where_clause.predicates.iter(), - terminator, - ",", - |pred| pred.span().lo(), - |pred| pred.span().hi(), - |pred| pred.rewrite(context, clause_shape), - span_start, - span_end, - false, - ); - let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line; - let comma_tactic = if where_clause_option.suppress_comma || where_single_line { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }; - - // shape should be vertical only and only if we have `where_single_line` option enabled - // and the number of items of the where clause is equal to 1 - let shape_tactic = if where_single_line { - DefinitiveListTactic::Horizontal - } else { - DefinitiveListTactic::Vertical - }; - - let fmt = ListFormatting { - tactic: shape_tactic, - separator: ",", - trailing_separator: comma_tactic, - separator_place: SeparatorPlace::Back, - shape: clause_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - let preds_str = write_list(&items.collect::>(), &fmt)?; - - let comment_separator = |comment: &str, shape: Shape| { - if comment.is_empty() { - Cow::from("") - } else { - shape.indent.to_string_with_newline(context.config) - } - }; - let newline_before_where = comment_separator(&comment_before, shape); - let newline_after_where = comment_separator(&comment_after, clause_shape); - - // 6 = `where ` - let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() - && comment_after.is_empty() && !preds_str.contains('\n') - && 6 + preds_str.len() <= shape.width || where_single_line - { - Cow::from(" ") - } else { - clause_shape.indent.to_string_with_newline(context.config) - }; - Some(format!( - "{}{}{}where{}{}{}{}", - starting_newline, - comment_before, - newline_before_where, - newline_after_where, - comment_after, - clause_sep, - preds_str - )) -} - -fn rewrite_where_clause( - context: &RewriteContext, - where_clause: &ast::WhereClause, - brace_style: BraceStyle, - shape: Shape, - density: Density, - terminator: &str, - span_end: Option, - span_end_before_where: BytePos, - where_clause_option: WhereClauseOption, - is_args_multi_line: bool, -) -> Option { - if where_clause.predicates.is_empty() { - return Some(String::new()); - } - - if context.config.indent_style() == IndentStyle::Block { - return rewrite_where_clause_rfc_style( - context, - where_clause, - shape, - terminator, - span_end, - span_end_before_where, - where_clause_option, - is_args_multi_line, - ); - } - - let extra_indent = Indent::new(context.config.tab_spaces(), 0); - - let offset = match context.config.indent_style() { - IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), - // 6 = "where ".len() - IndentStyle::Visual => shape.indent + extra_indent + 6, - }; - // FIXME: if indent_style != Visual, then the budgets below might - // be out by a char or two. - - let budget = context.config.max_width() - offset.width(); - let span_start = where_clause.predicates[0].span().lo(); - // If we don't have the start of the next span, then use the end of the - // predicates, but that means we miss comments. - let len = where_clause.predicates.len(); - let end_of_preds = where_clause.predicates[len - 1].span().hi(); - let span_end = span_end.unwrap_or(end_of_preds); - let items = itemize_list( - context.snippet_provider, - where_clause.predicates.iter(), - terminator, - ",", - |pred| pred.span().lo(), - |pred| pred.span().hi(), - |pred| pred.rewrite(context, Shape::legacy(budget, offset)), - span_start, - span_end, - false, - ); - let item_vec = items.collect::>(); - // FIXME: we don't need to collect here - let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget); - - let mut comma_tactic = context.config.trailing_comma(); - // Kind of a hack because we don't usually have trailing commas in where clauses. - if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma { - comma_tactic = SeparatorTactic::Never; - } - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: comma_tactic, - separator_place: SeparatorPlace::Back, - shape: Shape::legacy(budget, offset), - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - let preds_str = write_list(&item_vec, &fmt)?; - - let end_length = if terminator == "{" { - // If the brace is on the next line we don't need to count it otherwise it needs two - // characters " {" - match brace_style { - BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0, - BraceStyle::PreferSameLine => 2, - } - } else if terminator == "=" { - 2 - } else { - terminator.len() - }; - if density == Density::Tall || preds_str.contains('\n') - || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width - { - Some(format!( - "\n{}where {}", - (shape.indent + extra_indent).to_string(context.config), - preds_str - )) - } else { - Some(format!(" where {}", preds_str)) - } -} - -fn missing_span_before_after_where( - before_item_span_end: BytePos, - where_clause: &ast::WhereClause, -) -> (Span, Span) { - let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo()); - // 5 = `where` - let pos_after_where = where_clause.span.lo() + BytePos(5); - let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo()); - (missing_span_before, missing_span_after) -} - -fn rewrite_comments_before_after_where( - context: &RewriteContext, - span_before_where: Span, - span_after_where: Span, - shape: Shape, -) -> Option<(String, String)> { - let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; - let after_comment = rewrite_missing_comment( - span_after_where, - shape.block_indent(context.config.tab_spaces()), - context, - )?; - Some((before_comment, after_comment)) -} - -fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, ident) -} - -#[derive(PartialEq, Eq, Clone, Copy)] -enum BracePos { - None, - Auto, - ForceSameLine, -} - -fn format_generics( - context: &RewriteContext, - generics: &ast::Generics, - brace_style: BraceStyle, - brace_pos: BracePos, - offset: Indent, - span: Span, - used_width: usize, -) -> Option { - let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = rewrite_generics(context, generics, shape, span)?; - - let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { - let budget = context.budget(last_line_used_width(&result, offset.width())); - let mut option = WhereClauseOption::snuggled(&result); - if brace_pos == BracePos::None { - option.suppress_comma = true; - } - // If the generics are not parameterized then generics.span.hi() == 0, - // so we use span.lo(), which is the position after `struct Foo`. - let span_end_before_where = if generics.is_parameterized() { - generics.span.hi() - } else { - span.lo() - }; - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - brace_style, - Shape::legacy(budget, offset.block_only()), - Density::Tall, - "{", - Some(span.hi()), - span_end_before_where, - option, - false, - )?; - result.push_str(&where_clause_str); - brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine - || (generics.where_clause.predicates.is_empty() - && trimmed_last_line_width(&result) == 1) - } else { - brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1 - || brace_style != BraceStyle::AlwaysNextLine - }; - if brace_pos == BracePos::None { - return Some(result); - } - let total_used_width = last_line_used_width(&result, used_width); - let remaining_budget = context.budget(total_used_width); - // If the same line brace if forced, it indicates that we are rewriting an item with empty body, - // and hence we take the closer into account as well for one line budget. - // We assume that the closer has the same length as the opener. - let overhead = if brace_pos == BracePos::ForceSameLine { - // 3 = ` {}` - 3 - } else { - // 2 = ` {` - 2 - }; - let forbid_same_line_brace = overhead > remaining_budget; - if !forbid_same_line_brace && same_line_brace { - result.push(' '); - } else { - result.push('\n'); - result.push_str(&offset.block_only().to_string(context.config)); - } - result.push('{'); - - Some(result) -} - -impl Rewrite for ast::ForeignItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; - // Drop semicolon or it will be interpreted as comment. - // FIXME: this may be a faulty span from libsyntax. - let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - - let item_str = match self.node { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { - rewrite_fn_base( - context, - shape.indent, - self.ident, - &FnSig::new(fn_decl, generics, self.vis.clone()), - span, - false, - false, - ).map(|(s, _)| format!("{};", s)) - } - ast::ForeignItemKind::Static(ref ty, is_mutable) => { - // FIXME(#21): we're dropping potential comments in between the - // function keywords here. - let vis = format_visibility(&self.vis); - let mut_str = if is_mutable { "mut " } else { "" }; - let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); - // 1 = ; - let shape = shape.sub_width(1)?; - ty.rewrite(context, shape).map(|ty_str| { - // 1 = space between prefix and type. - let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { - Cow::from(" ") - } else { - let nested_indent = shape.indent.block_indent(context.config); - nested_indent.to_string_with_newline(context.config) - }; - format!("{}{}{};", prefix, sep, ty_str) - }) - } - ast::ForeignItemKind::Ty => { - let vis = format_visibility(&self.vis); - Some(format!("{}type {};", vis, self.ident)) - } - }?; - - let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo(), self.span.lo()) - } else { - mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo()) - }; - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missing_span, - shape, - false, - ) - } -} - -impl Rewrite for ast::GenericParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape), - ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape), - } - } -} - -/// Rewrite an inline mod. -pub fn rewrite_mod(item: &ast::Item) -> String { - let mut result = String::with_capacity(32); - result.push_str(&*format_visibility(&item.vis)); - result.push_str("mod "); - result.push_str(&item.ident.to_string()); - result.push(';'); - result -} - -/// Rewrite `extern crate foo;` WITHOUT attributes. -pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { - assert!(is_extern_crate(item)); - let new_str = context.snippet(item.span); - Some(if contains_comment(new_str) { - new_str.to_owned() - } else { - let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); - String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) - }) -} - -/// Returns true for `mod foo;`, false for `mod foo { .. }`. -pub fn is_mod_decl(item: &ast::Item) -> bool { - match item.node { - ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), - _ => false, - } -} - -pub fn is_use_item(item: &ast::Item) -> bool { - match item.node { - ast::ItemKind::Use(_) => true, - _ => false, - } -} - -pub fn is_extern_crate(item: &ast::Item) -> bool { - match item.node { - ast::ItemKind::ExternCrate(..) => true, - _ => false, - } -} diff --git a/rustfmt-core/src/lib.rs b/rustfmt-core/src/lib.rs deleted file mode 100644 index 6e9554f6855..00000000000 --- a/rustfmt-core/src/lib.rs +++ /dev/null @@ -1,937 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(custom_attribute)] -#![feature(decl_macro)] -#![feature(match_default_bindings)] -#![feature(type_ascription)] - -#[macro_use] -extern crate derive_new; -extern crate diff; -#[macro_use] -extern crate log; -extern crate regex; -extern crate rustc_errors as errors; -extern crate rustfmt_config as config; -extern crate syntax; -extern crate term; -extern crate unicode_segmentation; - -use std::collections::HashMap; -use std::fmt; -use std::io::{self, stdout, BufRead, Write}; -use std::iter::repeat; -use std::path::PathBuf; -use std::rc::Rc; -use std::time::Duration; - -use errors::{DiagnosticBuilder, Handler}; -use errors::emitter::{ColorConfig, EmitterWriter}; -use syntax::ast; -use syntax::codemap::{CodeMap, FilePathMapping}; -pub use syntax::codemap::FileName; -use syntax::parse::{self, ParseSess}; - -use checkstyle::{output_footer, output_header}; -use comment::{CharClasses, FullCodeCharKind}; -use issues::{BadIssueSeeker, Issue}; -use shape::Indent; -use utils::use_colored_tty; -use visitor::{FmtVisitor, SnippetProvider}; - -pub use config::Config; -pub use config::summary::Summary; - -#[macro_use] -mod utils; - -mod attr; -mod chains; -mod checkstyle; -mod closures; -pub mod codemap; -mod comment; -mod expr; -pub mod filemap; -mod imports; -mod issues; -mod items; -mod lists; -mod macros; -mod missed_spans; -pub mod modules; -mod patterns; -mod reorder; -mod rewrite; -pub mod rustfmt_diff; -mod shape; -mod spanned; -mod string; -mod types; -mod vertical; -pub mod visitor; - -const STDIN: &str = ""; - -// A map of the files of a crate, with their new content -pub type FileMap = Vec; - -pub type FileRecord = (FileName, String); - -#[derive(Clone, Copy)] -pub enum ErrorKind { - // Line has exceeded character limit (found, maximum) - LineOverflow(usize, usize), - // Line ends in whitespace - TrailingWhitespace, - // TO-DO or FIX-ME item without an issue number - BadIssue(Issue), -} - -impl fmt::Display for ErrorKind { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - ErrorKind::LineOverflow(found, maximum) => write!( - fmt, - "line exceeded maximum width (maximum: {}, found: {})", - maximum, found - ), - ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), - ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), - } - } -} - -// Formatting errors that are identified *after* rustfmt has run. -pub struct FormattingError { - line: usize, - kind: ErrorKind, - is_comment: bool, - is_string: bool, - line_buffer: String, -} - -impl FormattingError { - fn msg_prefix(&self) -> &str { - match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "error:", - ErrorKind::BadIssue(_) => "WARNING:", - } - } - - fn msg_suffix(&self) -> &str { - if self.is_comment || self.is_string { - "set `error_on_unformatted = false` to suppress \ - the warning against comments or string literals\n" - } else { - "" - } - } - - // (space, target) - pub fn format_len(&self) -> (usize, usize) { - match self.kind { - ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace => { - let trailing_ws_len = self.line_buffer - .chars() - .rev() - .take_while(|c| c.is_whitespace()) - .count(); - (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) - } - _ => unreachable!(), - } - } -} - -pub struct FormatReport { - // Maps stringified file paths to their associated formatting errors. - file_error_map: HashMap>, -} - -impl FormatReport { - fn new() -> FormatReport { - FormatReport { - file_error_map: HashMap::new(), - } - } - - pub fn warning_count(&self) -> usize { - self.file_error_map - .iter() - .map(|(_, errors)| errors.len()) - .sum() - } - - pub fn has_warnings(&self) -> bool { - self.warning_count() > 0 - } - - pub fn print_warnings_fancy( - &self, - mut t: Box>, - ) -> Result<(), term::Error> { - for (file, errors) in &self.file_error_map { - for error in errors { - let prefix_space_len = error.line.to_string().len(); - let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); - - // First line: the overview of error - t.fg(term::color::RED)?; - t.attr(term::Attr::Bold)?; - write!(t, "{} ", error.msg_prefix())?; - t.reset()?; - t.attr(term::Attr::Bold)?; - write!(t, "{}\n", error.kind)?; - - // Second line: file info - write!(t, "{}--> ", &prefix_spaces[1..])?; - t.reset()?; - write!(t, "{}:{}\n", file, error.line)?; - - // Third to fifth lines: show the line which triggered error, if available. - if !error.line_buffer.is_empty() { - let (space_len, target_len) = error.format_len(); - t.attr(term::Attr::Bold)?; - write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; - t.reset()?; - write!(t, "{}\n", error.line_buffer)?; - t.attr(term::Attr::Bold)?; - write!(t, "{}| ", prefix_spaces)?; - t.fg(term::color::RED)?; - write!(t, "{}\n", target_str(space_len, target_len))?; - t.reset()?; - } - - // The last line: show note if available. - let msg_suffix = error.msg_suffix(); - if !msg_suffix.is_empty() { - t.attr(term::Attr::Bold)?; - write!(t, "{}= note: ", prefix_spaces)?; - t.reset()?; - write!(t, "{}\n", error.msg_suffix())?; - } else { - write!(t, "\n")?; - } - t.reset()?; - } - } - - if !self.file_error_map.is_empty() { - t.attr(term::Attr::Bold)?; - write!(t, "warning: ")?; - t.reset()?; - write!( - t, - "rustfmt may have failed to format. See previous {} errors.\n\n", - self.warning_count(), - )?; - } - - Ok(()) - } -} - -fn target_str(space_len: usize, target_len: usize) -> String { - let empty_line: String = repeat(" ").take(space_len).collect(); - let overflowed: String = repeat("^").take(target_len).collect(); - empty_line + &overflowed -} - -impl fmt::Display for FormatReport { - // Prints all the formatting errors. - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - for (file, errors) in &self.file_error_map { - for error in errors { - let prefix_space_len = error.line.to_string().len(); - let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); - - let error_line_buffer = if error.line_buffer.is_empty() { - String::from(" ") - } else { - let (space_len, target_len) = error.format_len(); - format!( - "{}|\n{} | {}\n{}| {}", - prefix_spaces, - error.line, - error.line_buffer, - prefix_spaces, - target_str(space_len, target_len) - ) - }; - - let error_info = format!("{} {}", error.msg_prefix(), error.kind); - let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line); - let msg_suffix = error.msg_suffix(); - let note = if msg_suffix.is_empty() { - String::new() - } else { - format!("{}note= ", prefix_spaces) - }; - - write!( - fmt, - "{}\n{}\n{}\n{}{}\n", - error_info, - file_info, - error_line_buffer, - note, - error.msg_suffix() - )?; - } - } - if !self.file_error_map.is_empty() { - write!( - fmt, - "warning: rustfmt may have failed to format. See previous {} errors.\n", - self.warning_count(), - )?; - } - Ok(()) - } -} - -fn should_emit_verbose(path: &FileName, config: &Config, f: F) -where - F: Fn(), -{ - if config.verbose() && path.to_string() != STDIN { - f(); - } -} - -// Formatting which depends on the AST. -fn format_ast( - krate: &ast::Crate, - parse_session: &mut ParseSess, - main_file: &FileName, - config: &Config, - mut after_file: F, -) -> Result<(FileMap, bool), io::Error> -where - F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result, -{ - let mut result = FileMap::new(); - // diff mode: check if any files are differing - let mut has_diff = false; - - // We always skip children for the "Plain" write mode, since there is - // nothing to distinguish the nested module contents. - let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; - for (path, module) in modules::list_files(krate, parse_session.codemap())? { - if skip_children && path != *main_file { - continue; - } - should_emit_verbose(&path, config, || println!("Formatting {}", path)); - let filemap = parse_session - .codemap() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == *main_file { - visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, &*filemap); - } - } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); - visitor.format_separate_mod(module, &*filemap); - }; - - debug_assert_eq!( - visitor.line_number, - ::utils::count_newlines(&format!("{}", visitor.buffer)) - ); - - let filename = path.clone(); - has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) { - Ok(result) => result, - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg)); - } - }; - - result.push((filename, visitor.buffer)); - } - - Ok((result, has_diff)) -} - -/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`. -fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { - skipped_range - .iter() - .any(|&(lo, hi)| lo <= line_number && line_number <= hi) -} - -fn should_report_error( - config: &Config, - char_kind: FullCodeCharKind, - is_string: bool, - error_kind: ErrorKind, -) -> bool { - let allow_error_report = if char_kind.is_comment() || is_string { - config.error_on_unformatted() - } else { - true - }; - - match error_kind { - ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, - ErrorKind::TrailingWhitespace => allow_error_report, - _ => true, - } -} - -// Formatting done on a char by char or line by line basis. -// FIXME(#209) warn on bad license -// FIXME(#20) other stuff for parity with make tidy -fn format_lines( - text: &mut String, - name: &FileName, - skipped_range: &[(usize, usize)], - config: &Config, - report: &mut FormatReport, -) { - // Iterate over the chars in the file map. - let mut trims = vec![]; - let mut last_wspace: Option = None; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); - let mut line_buffer = String::with_capacity(config.max_width() * 2); - let mut is_string = false; // true if the current line contains a string literal. - let mut format_line = config.file_lines().contains_line(name, cur_line); - let allow_issue_seek = !issue_seeker.is_disabled(); - - for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { - if c == '\r' { - continue; - } - - if allow_issue_seek && format_line { - // Add warnings for bad todos/ fixmes - if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } - } - - if c == '\n' { - if format_line { - // Check for (and record) trailing whitespace. - if let Some(..) = last_wspace { - if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) { - trims.push((cur_line, kind, line_buffer.clone())); - } - line_len -= 1; - } - - // Check for any line width errors we couldn't correct. - let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); - if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) - && should_report_error(config, kind, is_string, error_kind) - { - errors.push(FormattingError { - line: cur_line, - kind: error_kind, - is_comment: kind.is_comment(), - is_string, - line_buffer: line_buffer.clone(), - }); - } - } - - line_len = 0; - cur_line += 1; - format_line = config.file_lines().contains_line(name, cur_line); - newline_count += 1; - last_wspace = None; - line_buffer.clear(); - is_string = false; - } else { - newline_count = 0; - line_len += if c == '\t' { config.tab_spaces() } else { 1 }; - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(b); - } - } else { - last_wspace = None; - } - line_buffer.push(c); - if kind.is_string() { - is_string = true; - } - } - } - - if newline_count > 1 { - debug!("track truncate: {} {}", text.len(), newline_count); - let line = text.len() - newline_count + 1; - text.truncate(line); - } - - for &(l, kind, ref b) in &trims { - if !is_skipped_line(l, skipped_range) { - errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - is_comment: kind.is_comment(), - is_string: kind.is_string(), - line_buffer: b.clone(), - }); - } - } - - report.file_error_map.insert(name.clone(), errors); -} - -fn parse_input<'sess>( - input: Input, - parse_session: &'sess ParseSess, - config: &Config, -) -> Result>> { - let result = match input { - Input::File(file) => { - let mut parser = parse::new_parser_from_file(parse_session, &file); - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - parser.parse_crate_mod() - } - Input::Text(text) => { - let mut parser = parse::new_parser_from_source_str( - parse_session, - FileName::Custom("stdin".to_owned()), - text, - ); - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - parser.parse_crate_mod() - } - }; - - match result { - Ok(c) => { - if parse_session.span_diagnostic.has_errors() { - // Bail out if the parser recovered from an error. - Err(None) - } else { - Ok(c) - } - } - Err(e) => Err(Some(e)), - } -} - -/// Format the given snippet. The snippet is expected to be *complete* code. -/// When we cannot parse the given snippet, this function returns `None`. -pub fn format_snippet(snippet: &str, config: &Config) -> Option { - let mut out: Vec = Vec::with_capacity(snippet.len() * 2); - let input = Input::Text(snippet.into()); - let mut config = config.clone(); - config.set().write_mode(config::WriteMode::Plain); - config.set().hide_parse_errors(true); - match format_input(input, &config, Some(&mut out)) { - // `format_input()` returns an empty string on parsing error. - Ok(..) if out.is_empty() && !snippet.is_empty() => None, - Ok(..) => String::from_utf8(out).ok(), - Err(..) => None, - } -} - -/// Format the given code block. Mainly targeted for code block in comment. -/// The code block may be incomplete (i.e. parser may be unable to parse it). -/// To avoid panic in parser, we wrap the code block with a dummy function. -/// The returned code block does *not* end with newline. -pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { - // Wrap the given code block with `fn main()` if it does not have one. - let fn_main_prefix = "fn main() {\n"; - let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}"; - let mut result = String::with_capacity(snippet.len()); - let mut is_first = true; - - // Trim "fn main() {" on the first line and "}" on the last line, - // then unindent the whole code block. - let formatted = format_snippet(&snippet, config)?; - // 2 = "}\n" - let block_len = formatted.len().checked_sub(2).unwrap_or(0); - for line in formatted[fn_main_prefix.len()..block_len].lines() { - if !is_first { - result.push('\n'); - } else { - is_first = false; - } - let trimmed_line = if line.len() > config.max_width() { - // If there are lines that are larger than max width, we cannot tell - // whether we have succeeded but have some comments or strings that - // are too long, or we have failed to format code block. We will be - // conservative and just return `None` in this case. - return None; - } else if line.len() > config.tab_spaces() { - // Make sure that the line has leading whitespaces. - let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); - if line.starts_with(indent_str.as_ref()) { - let offset = if config.hard_tabs() { - 1 - } else { - config.tab_spaces() - }; - &line[offset..] - } else { - line - } - } else { - line - }; - result.push_str(trimmed_line); - } - Some(result) -} - -pub fn format_input( - input: Input, - config: &Config, - mut out: Option<&mut T>, -) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { - let mut summary = Summary::default(); - if config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err((e, summary)); - } - } - return Ok((summary, FileMap::new(), FormatReport::new())); - } - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - - let tty_handler = if config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - Handler::with_emitter(true, false, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) - }; - let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Custom("stdin".to_owned()), - }; - - let krate = match parse_input(input, &parse_session, config) { - Ok(krate) => krate, - Err(diagnostic) => { - if let Some(mut diagnostic) = diagnostic { - diagnostic.emit(); - } - summary.add_parsing_error(); - return Ok((summary, FileMap::new(), FormatReport::new())); - } - }; - - summary.mark_parse_time(); - - if parse_session.span_diagnostic.has_errors() { - summary.add_parsing_error(); - } - - // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - - let mut report = FormatReport::new(); - - let format_result = format_ast( - &krate, - &mut parse_session, - &main_file, - config, - |file_name, file, skipped_range| { - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(file); - - format_lines(file, file_name, skipped_range, config, &mut report); - - if let Some(ref mut out) = out { - return filemap::write_file(file, file_name, out, config); - } - Ok(false) - }, - ); - - summary.mark_format_time(); - - should_emit_verbose(&main_file, config, || { - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 - } - - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(summary.get_parse_time().unwrap()), - duration_to_f32(summary.get_format_time().unwrap()), - ) - }); - - match format_result { - Ok((file_map, has_diff)) => { - if report.has_warnings() { - summary.add_formatting_error(); - } - - if has_diff { - summary.add_diff(); - } - - Ok((summary, file_map, report)) - } - Err(e) => Err((e, summary)), - } -} - -/// A single span of changed lines, with 0 or more removed lines -/// and a vector of 0 or more inserted lines. -#[derive(Debug, PartialEq, Eq)] -pub struct ModifiedChunk { - /// The first to be removed from the original text - pub line_number_orig: u32, - /// The number of lines which have been replaced - pub lines_removed: u32, - /// The new lines - pub lines: Vec, -} - -/// Set of changed sections of a file. -#[derive(Debug, PartialEq, Eq)] -pub struct ModifiedLines { - /// The set of changed chunks. - pub chunks: Vec, -} - -/// The successful result of formatting via `get_modified_lines()`. -pub struct ModifiedLinesResult { - /// The high level summary details - pub summary: Summary, - /// The result Filemap - pub filemap: FileMap, - /// Map of formatting errors - pub report: FormatReport, - /// The sets of updated lines. - pub modified_lines: ModifiedLines, -} - -/// Format a file and return a `ModifiedLines` data structure describing -/// the changed ranges of lines. -pub fn get_modified_lines( - input: Input, - config: &Config, -) -> Result { - let mut data = Vec::new(); - - let mut config = config.clone(); - config.set().write_mode(config::WriteMode::Modified); - let (summary, filemap, formatreport) = format_input(input, &config, Some(&mut data))?; - - let mut lines = data.lines(); - let mut chunks = Vec::new(); - while let Some(Ok(header)) = lines.next() { - // Parse the header line - let values: Vec<_> = header - .split(' ') - .map(|s| s.parse::().unwrap()) - .collect(); - assert_eq!(values.len(), 3); - let line_number_orig = values[0]; - let lines_removed = values[1]; - let num_added = values[2]; - let mut added_lines = Vec::new(); - for _ in 0..num_added { - added_lines.push(lines.next().unwrap().unwrap()); - } - chunks.push(ModifiedChunk { - line_number_orig, - lines_removed, - lines: added_lines, - }); - } - Ok(ModifiedLinesResult { - summary: summary, - filemap: filemap, - report: formatreport, - modified_lines: ModifiedLines { chunks }, - }) -} - -#[derive(Debug)] -pub enum Input { - File(PathBuf), - Text(String), -} - -pub fn run(input: Input, config: &Config) -> Summary { - let out = &mut stdout(); - output_header(out, config.write_mode()).ok(); - match format_input(input, config, Some(out)) { - Ok((summary, _, report)) => { - output_footer(out, config.write_mode()).ok(); - - if report.has_warnings() { - match term::stderr() { - Some(ref t) - if use_colored_tty(config.color()) && t.supports_color() - && t.supports_attr(term::Attr::Bold) => - { - match report.print_warnings_fancy(term::stderr().unwrap()) { - Ok(..) => (), - Err(..) => panic!("Unable to write to stderr: {}", report), - } - } - _ => msg!("{}", report), - } - } - - summary - } - Err((msg, mut summary)) => { - msg!("Error writing files: {}", msg); - summary.add_operational_error(); - summary - } - } -} - -#[cfg(test)] -mod test { - use super::{format_code_block, format_snippet, Config}; - - #[test] - fn test_no_panic_on_format_snippet_and_format_code_block() { - // `format_snippet()` and `format_code_block()` should not panic - // even when we cannot parse the given snippet. - let snippet = "let"; - assert!(format_snippet(snippet, &Config::default()).is_none()); - assert!(format_code_block(snippet, &Config::default()).is_none()); - } - - fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool - where - F: Fn(&str, &Config) -> Option, - { - let output = formatter(input, &Config::default()); - output.is_some() && output.unwrap() == expected - } - - #[test] - fn test_format_snippet() { - let snippet = "fn main() { println!(\"hello, world\"); }"; - let expected = "fn main() {\n \ - println!(\"hello, world\");\n\ - }\n"; - assert!(test_format_inner(format_snippet, snippet, expected)); - } - - #[test] - fn test_format_code_block_fail() { - #[rustfmt_skip] - let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);"; - assert!(format_code_block(code_block, &Config::default()).is_none()); - } - - #[test] - fn test_format_code_block() { - // simple code block - let code_block = "let x=3;"; - let expected = "let x = 3;"; - assert!(test_format_inner(format_code_block, code_block, expected)); - - // more complex code block, taken from chains.rs. - let code_block = -"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { -( -chain_indent(context, shape.add_offset(parent_rewrite.len())), -context.config.indent_style() == IndentStyle::Visual || is_small_parent, -) -} else if is_block_expr(context, &parent, &parent_rewrite) { -match context.config.indent_style() { -// Try to put the first child on the same line with parent's last line -IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), -// The parent is a block, so align the rest of the chain with the closing -// brace. -IndentStyle::Visual => (parent_shape, false), -} -} else { -( -chain_indent(context, shape.add_offset(parent_rewrite.len())), -false, -) -}; -"; - let expected = -"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.indent_style() == IndentStyle::Visual || is_small_parent, - ) -} else if is_block_expr(context, &parent, &parent_rewrite) { - match context.config.indent_style() { - // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), - // The parent is a block, so align the rest of the chain with the closing - // brace. - IndentStyle::Visual => (parent_shape, false), - } -} else { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - false, - ) -};"; - assert!(test_format_inner(format_code_block, code_block, expected)); - } -} diff --git a/rustfmt-core/src/lists.rs b/rustfmt-core/src/lists.rs deleted file mode 100644 index 49797a785bb..00000000000 --- a/rustfmt-core/src/lists.rs +++ /dev/null @@ -1,771 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Format list-like expressions and items. - -use std::cmp; -use std::iter::Peekable; - -use config::lists::*; -use syntax::codemap::BytePos; - -use comment::{find_comment_end, rewrite_comment, FindUncommented}; -use config::{Config, IndentStyle}; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; -use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; -use visitor::SnippetProvider; - -pub struct ListFormatting<'a> { - pub tactic: DefinitiveListTactic, - pub separator: &'a str, - pub trailing_separator: SeparatorTactic, - pub separator_place: SeparatorPlace, - pub shape: Shape, - // Non-expressions, e.g. items, will have a new line at the end of the list. - // Important for comment styles. - pub ends_with_newline: bool, - // Remove newlines between list elements for expressions. - pub preserve_newline: bool, - pub config: &'a Config, -} - -impl<'a> ListFormatting<'a> { - pub fn needs_trailing_separator(&self) -> bool { - match self.trailing_separator { - // We always put separator in front. - SeparatorTactic::Always => true, - SeparatorTactic::Vertical => self.tactic == DefinitiveListTactic::Vertical, - SeparatorTactic::Never => { - self.tactic == DefinitiveListTactic::Vertical && self.separator_place.is_front() - } - } - } -} - -impl AsRef for ListItem { - fn as_ref(&self) -> &ListItem { - self - } -} - -#[derive(PartialEq, Eq)] -pub enum ListItemCommentStyle { - // Try to keep the comment on the same line with the item. - SameLine, - // Put the comment on the previous or the next line of the item. - DifferentLine, - // No comment available. - None, -} - -pub struct ListItem { - // None for comments mean that they are not present. - pub pre_comment: Option, - pub pre_comment_style: ListItemCommentStyle, - // Item should include attributes and doc comments. None indicates a failed - // rewrite. - pub item: Option, - pub post_comment: Option, - // Whether there is extra whitespace before this item. - pub new_lines: bool, -} - -impl ListItem { - pub fn inner_as_ref(&self) -> &str { - self.item.as_ref().map_or("", |s| s) - } - - pub fn is_different_group(&self) -> bool { - self.inner_as_ref().contains('\n') || self.pre_comment.is_some() - || self.post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) - } - - pub fn is_multiline(&self) -> bool { - self.inner_as_ref().contains('\n') - || self.pre_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) - || self.post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) - } - - pub fn has_comment(&self) -> bool { - self.pre_comment - .as_ref() - .map_or(false, |comment| comment.trim_left().starts_with("//")) - || self.post_comment - .as_ref() - .map_or(false, |comment| comment.trim_left().starts_with("//")) - } - - pub fn from_str>(s: S) -> ListItem { - ListItem { - pre_comment: None, - pre_comment_style: ListItemCommentStyle::None, - item: Some(s.into()), - post_comment: None, - new_lines: false, - } - } -} - -/// The type of separator for lists. -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum Separator { - Comma, - VerticalBar, -} - -impl Separator { - pub fn len(&self) -> usize { - match *self { - // 2 = `, ` - Separator::Comma => 2, - // 3 = ` | ` - Separator::VerticalBar => 3, - } - } -} - -pub fn definitive_tactic( - items: I, - tactic: ListTactic, - sep: Separator, - width: usize, -) -> DefinitiveListTactic -where - I: IntoIterator + Clone, - T: AsRef, -{ - let pre_line_comments = items - .clone() - .into_iter() - .any(|item| item.as_ref().has_comment()); - - let limit = match tactic { - _ if pre_line_comments => return DefinitiveListTactic::Vertical, - ListTactic::Mixed => return DefinitiveListTactic::Mixed, - ListTactic::Horizontal => return DefinitiveListTactic::Horizontal, - ListTactic::Vertical => return DefinitiveListTactic::Vertical, - ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit), - ListTactic::HorizontalVertical => width, - }; - - let (sep_count, total_width) = calculate_width(items.clone()); - let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); - let real_total = total_width + total_sep_len; - - if real_total <= limit && !pre_line_comments - && !items.into_iter().any(|item| item.as_ref().is_multiline()) - { - DefinitiveListTactic::Horizontal - } else { - DefinitiveListTactic::Vertical - } -} - -// Format a list of commented items into a string. -// TODO: add unit tests -pub fn write_list(items: I, formatting: &ListFormatting) -> Option -where - I: IntoIterator + Clone, - T: AsRef, -{ - let tactic = formatting.tactic; - let sep_len = formatting.separator.len(); - - // Now that we know how we will layout, we can decide for sure if there - // will be a trailing separator. - let mut trailing_separator = formatting.needs_trailing_separator(); - let mut result = String::with_capacity(128); - let cloned_items = items.clone(); - let mut iter = items.into_iter().enumerate().peekable(); - let mut item_max_width: Option = None; - let sep_place = - SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); - - let mut line_len = 0; - let indent_str = &formatting.shape.indent.to_string(formatting.config); - while let Some((i, item)) = iter.next() { - let item = item.as_ref(); - let inner_item = item.item.as_ref()?; - let first = i == 0; - let last = iter.peek().is_none(); - let mut separate = match sep_place { - SeparatorPlace::Front => !first, - SeparatorPlace::Back => !last || trailing_separator, - }; - let item_sep_len = if separate { sep_len } else { 0 }; - - // Item string may be multi-line. Its length (used for block comment alignment) - // should be only the length of the last line. - let item_last_line = if item.is_multiline() { - inner_item.lines().last().unwrap_or("") - } else { - inner_item.as_ref() - }; - let mut item_last_line_width = item_last_line.len() + item_sep_len; - if item_last_line.starts_with(&**indent_str) { - item_last_line_width -= indent_str.len(); - } - - match tactic { - DefinitiveListTactic::Horizontal if !first => { - result.push(' '); - } - DefinitiveListTactic::SpecialMacro(num_args_before) => { - if i == 0 { - // Nothing - } else if i < num_args_before { - result.push(' '); - } else if i <= num_args_before + 1 { - result.push('\n'); - result.push_str(indent_str); - } else { - result.push(' '); - } - } - DefinitiveListTactic::Vertical if !first => { - result.push('\n'); - result.push_str(indent_str); - } - DefinitiveListTactic::Mixed => { - let total_width = total_item_width(item) + item_sep_len; - - // 1 is space between separator and item. - if line_len > 0 && line_len + 1 + total_width > formatting.shape.width { - result.push('\n'); - result.push_str(indent_str); - line_len = 0; - if formatting.ends_with_newline { - if last { - separate = true; - } else { - trailing_separator = true; - } - } - } - - if line_len > 0 { - result.push(' '); - line_len += 1; - } - - line_len += total_width; - } - _ => {} - } - - // Pre-comments - if let Some(ref comment) = item.pre_comment { - // Block style in non-vertical mode. - let block_mode = tactic != DefinitiveListTactic::Vertical; - // Width restriction is only relevant in vertical mode. - let comment = - rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; - result.push_str(&comment); - - if tactic == DefinitiveListTactic::Vertical { - // We cannot keep pre-comments on the same line if the comment if normalized. - let keep_comment = if formatting.config.normalize_comments() - || item.pre_comment_style == ListItemCommentStyle::DifferentLine - { - false - } else { - // We will try to keep the comment on the same line with the item here. - // 1 = ` ` - let total_width = total_item_width(item) + item_sep_len + 1; - total_width <= formatting.shape.width - }; - if keep_comment { - result.push(' '); - } else { - result.push('\n'); - result.push_str(indent_str); - } - } else { - result.push(' '); - } - item_max_width = None; - } - - if separate && sep_place.is_front() && !first { - result.push_str(formatting.separator.trim()); - result.push(' '); - } - result.push_str(&inner_item[..]); - - // Post-comments - if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { - let comment = item.post_comment.as_ref().unwrap(); - let formatted_comment = rewrite_comment( - comment, - true, - Shape::legacy(formatting.shape.width, Indent::empty()), - formatting.config, - )?; - - result.push(' '); - result.push_str(&formatted_comment); - } - - if separate && sep_place.is_back() { - result.push_str(formatting.separator); - } - - if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { - let comment = item.post_comment.as_ref().unwrap(); - let overhead = last_line_width(&result) + first_line_width(comment.trim()); - - let rewrite_post_comment = |item_max_width: &mut Option| { - if item_max_width.is_none() && !last && !inner_item.contains('\n') { - *item_max_width = Some(max_width_of_item_with_post_comment( - &cloned_items, - i, - overhead, - formatting.config.max_width(), - )); - } - let overhead = if starts_with_newline(comment) { - 0 - } else if let Some(max_width) = *item_max_width { - max_width + 2 - } else { - // 1 = space between item and comment. - item_last_line_width + 1 - }; - let width = formatting.shape.width.checked_sub(overhead).unwrap_or(1); - let offset = formatting.shape.indent + overhead; - let comment_shape = Shape::legacy(width, offset); - - // Use block-style only for the last item or multiline comments. - let block_style = !formatting.ends_with_newline && last - || comment.trim().contains('\n') - || comment.trim().len() > width; - - rewrite_comment( - comment.trim_left(), - block_style, - comment_shape, - formatting.config, - ) - }; - - let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; - - if !starts_with_newline(comment) { - let mut comment_alignment = - post_comment_alignment(item_max_width, inner_item.len()); - if first_line_width(&formatted_comment) + last_line_width(&result) - + comment_alignment + 1 > formatting.config.max_width() - { - item_max_width = None; - formatted_comment = rewrite_post_comment(&mut item_max_width)?; - comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); - } - for _ in 0..(comment_alignment + 1) { - result.push(' '); - } - // An additional space for the missing trailing separator. - if last && item_max_width.is_some() && !separate && !formatting.separator.is_empty() - { - result.push(' '); - } - } else { - result.push('\n'); - result.push_str(indent_str); - } - if formatted_comment.contains('\n') { - item_max_width = None; - } - result.push_str(&formatted_comment); - } else { - item_max_width = None; - } - - if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical - && item.new_lines - { - item_max_width = None; - result.push('\n'); - } - } - - Some(result) -} - -fn max_width_of_item_with_post_comment( - items: &I, - i: usize, - overhead: usize, - max_budget: usize, -) -> usize -where - I: IntoIterator + Clone, - T: AsRef, -{ - let mut max_width = 0; - let mut first = true; - for item in items.clone().into_iter().skip(i) { - let item = item.as_ref(); - let inner_item_width = item.inner_as_ref().len(); - if !first - && (item.is_different_group() || !item.post_comment.is_some() - || inner_item_width + overhead > max_budget) - { - return max_width; - } - if max_width < inner_item_width { - max_width = inner_item_width; - } - if item.new_lines { - return max_width; - } - first = false; - } - max_width -} - -fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { - item_max_width - .and_then(|max_line_width| max_line_width.checked_sub(inner_item_len)) - .unwrap_or(0) -} - -pub struct ListItems<'a, I, F1, F2, F3> -where - I: Iterator, -{ - snippet_provider: &'a SnippetProvider<'a>, - inner: Peekable, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - prev_span_end: BytePos, - next_span_start: BytePos, - terminator: &'a str, - separator: &'a str, - leave_last: bool, -} - -impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> -where - I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option, -{ - type Item = ListItem; - - fn next(&mut self) -> Option { - let white_space: &[_] = &[' ', '\t']; - - self.inner.next().map(|item| { - let mut new_lines = false; - // Pre-comment - let pre_snippet = self.snippet_provider - .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) - .unwrap(); - let trimmed_pre_snippet = pre_snippet.trim(); - let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); - let has_block_comment = trimmed_pre_snippet.starts_with("/*"); - let (pre_comment, pre_comment_style) = if has_single_line_comment { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else if has_block_comment { - let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); - if pre_snippet - .chars() - .rev() - .take(comment_end + 1) - .any(|c| c == '\n') - { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::SameLine, - ) - } - } else { - (None, ListItemCommentStyle::None) - }; - - // Post-comment - let next_start = match self.inner.peek() { - Some(next_item) => (self.get_lo)(next_item), - None => self.next_span_start, - }; - let post_snippet = self.snippet_provider - .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) - .unwrap(); - - let comment_end = match self.inner.peek() { - Some(..) => { - let mut block_open_index = post_snippet.find("/*"); - // check if it really is a block comment (and not `//*` or a nested comment) - if let Some(i) = block_open_index { - match post_snippet.find('/') { - Some(j) if j < i => block_open_index = None, - _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, - _ => (), - } - } - let newline_index = post_snippet.find('\n'); - if let Some(separator_index) = post_snippet.find_uncommented(self.separator) { - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => separator_index + 1, - // Block-style post-comment before the separator. - (Some(i), None) => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Potential *single* line comment. - (_, Some(j)) if j > separator_index => j + 1, - _ => post_snippet.len(), - } - } else if let Some(newline_index) = newline_index { - // Match arms may not have trailing comma. In any case, for match arms, - // we will assume that the post comment belongs to the next arm if they - // do not end with trailing comma. - newline_index + 1 - } else { - 0 - } - } - None => post_snippet - .find_uncommented(self.terminator) - .unwrap_or_else(|| post_snippet.len()), - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet - .find('\n') - .unwrap_or_else(|| test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet - .find(|c: char| !c.is_whitespace()) - .unwrap_or_else(|| test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if count_newlines(test_snippet) > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; - } - } - - // Cleanup post-comment: strip separators and whitespace. - self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); - - let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { - post_snippet - }; - - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; - - ListItem { - pre_comment, - pre_comment_style, - item: if self.inner.peek().is_none() && self.leave_last { - None - } else { - (self.get_item_string)(&item) - }, - post_comment, - new_lines, - } - }) - } -} - -#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] -// Creates an iterator over a list's items with associated comments. -pub fn itemize_list<'a, T, I, F1, F2, F3>( - snippet_provider: &'a SnippetProvider, - inner: I, - terminator: &'a str, - separator: &'a str, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - prev_span_end: BytePos, - next_span_start: BytePos, - leave_last: bool, -) -> ListItems<'a, I, F1, F2, F3> -where - I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option, -{ - ListItems { - snippet_provider, - inner: inner.peekable(), - get_lo, - get_hi, - get_item_string, - prev_span_end, - next_span_start, - terminator, - separator, - leave_last, - } -} - -/// Returns the count and total width of the list items. -fn calculate_width(items: I) -> (usize, usize) -where - I: IntoIterator, - T: AsRef, -{ - items - .into_iter() - .map(|item| total_item_width(item.as_ref())) - .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) -} - -pub fn total_item_width(item: &ListItem) -> usize { - comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) - + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) - + item.item.as_ref().map_or(0, |str| str.len()) -} - -fn comment_len(comment: Option<&str>) -> usize { - match comment { - Some(s) => { - let text_len = s.trim().len(); - if text_len > 0 { - // We'll put " /*" before and " */" after inline comments. - text_len + 6 - } else { - text_len - } - } - None => 0, - } -} - -// Compute horizontal and vertical shapes for a struct-lit-like thing. -pub fn struct_lit_shape( - shape: Shape, - context: &RewriteContext, - prefix_width: usize, - suffix_width: usize, -) -> Option<(Option, Shape)> { - let v_shape = match context.config.indent_style() { - IndentStyle::Visual => shape - .visual_indent(0) - .shrink_left(prefix_width)? - .sub_width(suffix_width)?, - IndentStyle::Block => { - let shape = shape.block_indent(context.config.tab_spaces()); - Shape { - width: context.budget(shape.indent.width()), - ..shape - } - } - }; - let shape_width = shape.width.checked_sub(prefix_width + suffix_width); - if let Some(w) = shape_width { - let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); - Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) - } else { - Some((None, v_shape)) - } -} - -// Compute the tactic for the internals of a struct-lit-like thing. -pub fn struct_lit_tactic( - h_shape: Option, - context: &RewriteContext, - items: &[ListItem], -) -> DefinitiveListTactic { - if let Some(h_shape) = h_shape { - let prelim_tactic = match (context.config.indent_style(), items.len()) { - (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, - _ if context.config.struct_lit_single_line() => ListTactic::HorizontalVertical, - _ => ListTactic::Vertical, - }; - definitive_tactic(items, prelim_tactic, Separator::Comma, h_shape.width) - } else { - DefinitiveListTactic::Vertical - } -} - -// Given a tactic and possible shapes for horizontal and vertical layout, -// come up with the actual shape to use. -pub fn shape_for_tactic( - tactic: DefinitiveListTactic, - h_shape: Option, - v_shape: Shape, -) -> Shape { - match tactic { - DefinitiveListTactic::Horizontal => h_shape.unwrap(), - _ => v_shape, - } -} - -// Create a ListFormatting object for formatting the internals of a -// struct-lit-like thing, that is a series of fields. -pub fn struct_lit_formatting<'a>( - shape: Shape, - tactic: DefinitiveListTactic, - context: &'a RewriteContext, - force_no_trailing_comma: bool, -) -> ListFormatting<'a> { - let ends_with_newline = context.config.indent_style() != IndentStyle::Visual - && tactic == DefinitiveListTactic::Vertical; - ListFormatting { - tactic, - separator: ",", - trailing_separator: if force_no_trailing_comma { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline, - preserve_newline: true, - config: context.config, - } -} diff --git a/rustfmt-core/src/macros.rs b/rustfmt-core/src/macros.rs deleted file mode 100644 index e7238a314fc..00000000000 --- a/rustfmt-core/src/macros.rs +++ /dev/null @@ -1,979 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Format list-like macro invocations. These are invocations whose token trees -// can be interpreted as expressions and separated by commas. -// Note that these token trees do not actually have to be interpreted as -// expressions by the compiler. An example of an invocation we would reformat is -// foo!( x, y, z ). The token x may represent an identifier in the code, but we -// interpreted as an expression. -// Macro uses which are not-list like, such as bar!(key => val), will not be -// reformatted. -// List-like invocations with parentheses will be formatted as function calls, -// and those with brackets will be formatted as array literals. - -use std::collections::HashMap; - -use config::lists::*; -use syntax::ast; -use syntax::codemap::{BytePos, Span}; -use syntax::parse::new_parser_from_tts; -use syntax::parse::parser::Parser; -use syntax::parse::token::{BinOpToken, DelimToken, Token}; -use syntax::print::pprust; -use syntax::symbol; -use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; -use syntax::util::ThinVec; - -use codemap::SpanUtils; -use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; -use expr::{rewrite_array, rewrite_call_inner}; -use lists::{itemize_list, write_list, ListFormatting}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use utils::{format_visibility, mk_sp, wrap_str}; - -const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; - -// FIXME: use the enum from libsyntax? -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -enum MacroStyle { - Parens, - Brackets, - Braces, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum MacroPosition { - Item, - Statement, - Expression, - Pat, -} - -impl MacroStyle { - fn opener(&self) -> &'static str { - match *self { - MacroStyle::Parens => "(", - MacroStyle::Brackets => "[", - MacroStyle::Braces => "{", - } - } -} - -#[derive(Debug)] -pub enum MacroArg { - Expr(ast::Expr), - Ty(ast::Ty), - Pat(ast::Pat), -} - -impl Rewrite for MacroArg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - MacroArg::Expr(ref expr) => expr.rewrite(context, shape), - MacroArg::Ty(ref ty) => ty.rewrite(context, shape), - MacroArg::Pat(ref pat) => pat.rewrite(context, shape), - } - } -} - -fn parse_macro_arg(parser: &mut Parser) -> Option { - macro_rules! parse_macro_arg { - ($macro_arg: ident, $parser: ident) => { - let mut cloned_parser = (*parser).clone(); - match cloned_parser.$parser() { - Ok(x) => { - if parser.sess.span_diagnostic.has_errors() { - parser.sess.span_diagnostic.reset_err_count(); - } else { - // Parsing succeeded. - *parser = cloned_parser; - return Some(MacroArg::$macro_arg((*x).clone())); - } - } - Err(mut e) => { - e.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - } - } - }; - } - - parse_macro_arg!(Expr, parse_expr); - parse_macro_arg!(Ty, parse_ty); - parse_macro_arg!(Pat, parse_pat); - - None -} - -/// Rewrite macro name without using pretty-printer if possible. -fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> String { - let name = if path.segments.len() == 1 { - // Avoid using pretty-printer in the common case. - format!("{}!", path.segments[0].identifier) - } else { - format!("{}!", path) - }; - match extra_ident { - Some(ident) if ident != symbol::keywords::Invalid.ident() => format!("{} {}", name, ident), - _ => name, - } -} - -pub fn rewrite_macro( - mac: &ast::Mac, - extra_ident: Option, - context: &RewriteContext, - shape: Shape, - position: MacroPosition, -) -> Option { - let context = &mut context.clone(); - context.inside_macro = true; - if context.config.use_try_shorthand() { - if let Some(expr) = convert_try_mac(mac, context) { - context.inside_macro = false; - return expr.rewrite(context, shape); - } - } - - let original_style = macro_style(mac, context); - - let macro_name = rewrite_macro_name(&mac.node.path, extra_ident); - - let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { - MacroStyle::Brackets - } else { - original_style - }; - - let ts: TokenStream = mac.node.stream(); - let has_comment = contains_comment(context.snippet(mac.span)); - if ts.is_empty() && !has_comment { - return match style { - MacroStyle::Parens if position == MacroPosition::Item => { - Some(format!("{}();", macro_name)) - } - MacroStyle::Parens => Some(format!("{}()", macro_name)), - MacroStyle::Brackets => Some(format!("{}[]", macro_name)), - MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), - }; - } - // Format well-known macros which cannot be parsed as a valid AST. - // TODO: Maybe add more macros? - if macro_name == "lazy_static!" && !has_comment { - if let success @ Some(..) = format_lazy_static(context, shape, &ts) { - return success; - } - } - - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - let mut arg_vec = Vec::new(); - let mut vec_with_semi = false; - let mut trailing_comma = false; - - if MacroStyle::Braces != style { - loop { - match parse_macro_arg(&mut parser) { - Some(arg) => arg_vec.push(arg), - None => return Some(context.snippet(mac.span).to_owned()), - } - - match parser.token { - Token::Eof => break, - Token::Comma => (), - Token::Semi => { - // Try to parse `vec![expr; expr]` - if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { - parser.bump(); - if parser.token != Token::Eof { - match parse_macro_arg(&mut parser) { - Some(arg) => { - arg_vec.push(arg); - parser.bump(); - if parser.token == Token::Eof && arg_vec.len() == 2 { - vec_with_semi = true; - break; - } - } - None => return Some(context.snippet(mac.span).to_owned()), - } - } - } - return Some(context.snippet(mac.span).to_owned()); - } - _ => return Some(context.snippet(mac.span).to_owned()), - } - - parser.bump(); - - if parser.token == Token::Eof { - trailing_comma = true; - break; - } - } - } - - match style { - MacroStyle::Parens => { - // Format macro invocation as function call, forcing no trailing - // comma because not all macros support them. - rewrite_call_inner( - context, - ¯o_name, - &arg_vec.iter().map(|e| &*e).collect::>()[..], - mac.span, - shape, - context.config.width_heuristics().fn_call_width, - trailing_comma, - ).map(|rw| match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - }) - } - MacroStyle::Brackets => { - let mac_shape = shape.offset_left(macro_name.len())?; - // Handle special case: `vec![expr; expr]` - if vec_with_semi { - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - // 6 = `vec!` + `; ` - let total_overhead = lbr.len() + rbr.len() + 6; - let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = arg_vec[0].rewrite(context, nested_shape)?; - let rhs = arg_vec[1].rewrite(context, nested_shape)?; - if !lhs.contains('\n') && !rhs.contains('\n') - && lhs.len() + rhs.len() + total_overhead <= shape.width - { - Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) - } else { - Some(format!( - "{}{}{}{};{}{}{}{}", - macro_name, - lbr, - nested_shape.indent.to_string_with_newline(context.config), - lhs, - nested_shape.indent.to_string_with_newline(context.config), - rhs, - shape.indent.to_string_with_newline(context.config), - rbr - )) - } - } else { - // If we are rewriting `vec!` macro or other special macros, - // then we can rewrite this as an usual array literal. - // Otherwise, we must preserve the original existence of trailing comma. - if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { - context.inside_macro = false; - trailing_comma = false; - } - // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. - let sp = mk_sp( - context - .snippet_provider - .span_after(mac.span, original_style.opener()), - mac.span.hi() - BytePos(1), - ); - let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; - let rewrite = rewrite_array(arg_vec, sp, context, mac_shape, trailing_comma)?; - let comma = match position { - MacroPosition::Item => ";", - _ => "", - }; - - Some(format!("{}{}{}", macro_name, rewrite, comma)) - } - } - MacroStyle::Braces => { - // Skip macro invocations with braces, for now. - indent_macro_snippet(context, context.snippet(mac.span), shape.indent) - } - } -} - -pub fn rewrite_macro_def( - context: &RewriteContext, - shape: Shape, - indent: Indent, - def: &ast::MacroDef, - ident: ast::Ident, - vis: &ast::Visibility, - span: Span, -) -> Option { - let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); - if snippet.as_ref().map_or(true, |s| s.ends_with(';')) { - return snippet; - } - - let mut parser = MacroParser::new(def.stream().into_trees()); - let parsed_def = match parser.parse() { - Some(def) => def, - None => return snippet, - }; - - let mut result = if def.legacy { - String::from("macro_rules!") - } else { - format!("{}macro", format_visibility(vis)) - }; - - result += " "; - result += &ident.name.as_str(); - - let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; - - let arm_shape = if multi_branch_style { - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - } else { - shape - }; - - let branch_items = itemize_list( - context.snippet_provider, - parsed_def.branches.iter(), - "}", - ";", - |branch| branch.span.lo(), - |branch| branch.span.hi(), - |branch| branch.rewrite(context, arm_shape, multi_branch_style), - context.snippet_provider.span_after(span, "{"), - span.hi(), - false, - ).collect::>(); - - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: if def.legacy { ";" } else { "" }, - trailing_separator: SeparatorTactic::Always, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - - if multi_branch_style { - result += " {"; - result += &arm_shape.indent.to_string_with_newline(context.config); - } - - result += write_list(&branch_items, &fmt)?.as_str(); - - if multi_branch_style { - result += &indent.to_string_with_newline(context.config); - result += "}"; - } - - Some(result) -} - -// Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we -// aren't causing problems. -// This should also work for escaped `$` variables, where we leave earlier `$`s. -fn replace_names(input: &str) -> Option<(String, HashMap)> { - // Each substitution will require five or six extra bytes. - let mut result = String::with_capacity(input.len() + 64); - let mut substs = HashMap::new(); - let mut dollar_count = 0; - let mut cur_name = String::new(); - - for c in input.chars() { - if c == '$' { - dollar_count += 1; - } else if dollar_count == 0 { - result.push(c); - } else if !c.is_alphanumeric() && !cur_name.is_empty() { - // Terminates a name following one or more dollars. - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); - - result.push(c); - - dollar_count = 0; - cur_name = String::new(); - } else if c == '(' && cur_name.is_empty() { - // FIXME: Support macro def with repeat. - return None; - } else if c.is_alphanumeric() { - cur_name.push(c); - } - } - - // FIXME: duplicate code - if !cur_name.is_empty() { - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); - } - - debug!("replace_names `{}` {:?}", result, substs); - - Some((result, substs)) -} - -// This is a bit sketchy. The token rules probably need tweaking, but it works -// for some common cases. I hope the basic logic is sufficient. Note that the -// meaning of some tokens is a bit different here from usual Rust, e.g., `*` -// and `(`/`)` have special meaning. -// -// We always try and format on one line. -// FIXME: Use multi-line when every thing does not fit on one line. -fn format_macro_args(toks: ThinTokenStream, shape: Shape) -> Option { - let mut result = String::with_capacity(128); - let mut insert_space = SpaceState::Never; - - for tok in (toks.into(): TokenStream).trees() { - match tok { - TokenTree::Token(_, t) => { - if !result.is_empty() && force_space_before(&t) { - insert_space = SpaceState::Always; - } - if force_no_space_before(&t) { - insert_space = SpaceState::Never; - } - match (insert_space, ident_like(&t)) { - (SpaceState::Always, _) - | (SpaceState::Punctuation, false) - | (SpaceState::Ident, true) => { - result.push(' '); - } - _ => {} - } - result.push_str(&pprust::token_to_string(&t)); - insert_space = next_space(&t); - } - TokenTree::Delimited(_, d) => { - if let SpaceState::Always = insert_space { - result.push(' '); - } - let formatted = format_macro_args(d.tts, shape)?; - match d.delim { - DelimToken::Paren => { - result.push_str(&format!("({})", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::Bracket => { - result.push_str(&format!("[{}]", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::Brace => { - result.push_str(&format!(" {{ {} }}", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::NoDelim => { - result.push_str(&format!("{}", formatted)); - insert_space = SpaceState::Always; - } - } - } - } - } - - if result.len() <= shape.width { - Some(result) - } else { - None - } -} - -// We should insert a space if the next token is a: -#[derive(Copy, Clone)] -enum SpaceState { - Never, - Punctuation, - Ident, // Or ident/literal-like thing. - Always, -} - -fn force_space_before(tok: &Token) -> bool { - match *tok { - Token::Eq - | Token::Lt - | Token::Le - | Token::EqEq - | Token::Ne - | Token::Ge - | Token::Gt - | Token::AndAnd - | Token::OrOr - | Token::Not - | Token::Tilde - | Token::BinOpEq(_) - | Token::At - | Token::RArrow - | Token::LArrow - | Token::FatArrow - | Token::Pound - | Token::Dollar => true, - Token::BinOp(bot) => bot != BinOpToken::Star, - _ => false, - } -} - -fn force_no_space_before(tok: &Token) -> bool { - match *tok { - Token::Semi | Token::Comma | Token::Dot => true, - Token::BinOp(bot) => bot == BinOpToken::Star, - _ => false, - } -} -fn ident_like(tok: &Token) -> bool { - match *tok { - Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, - _ => false, - } -} - -fn next_space(tok: &Token) -> SpaceState { - match *tok { - Token::Not - | Token::Tilde - | Token::At - | Token::Comma - | Token::Dot - | Token::DotDot - | Token::DotDotDot - | Token::DotDotEq - | Token::DotEq - | Token::Question - | Token::Underscore - | Token::BinOp(_) => SpaceState::Punctuation, - - Token::ModSep - | Token::Pound - | Token::Dollar - | Token::OpenDelim(_) - | Token::CloseDelim(_) - | Token::Whitespace => SpaceState::Never, - - Token::Literal(..) | Token::Ident(_) | Token::Lifetime(_) => SpaceState::Ident, - - _ => SpaceState::Always, - } -} - -/// Tries to convert a macro use into a short hand try expression. Returns None -/// when the macro is not an instance of try! (or parsing the inner expression -/// failed). -pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { - if &format!("{}", mac.node.path)[..] == "try" { - let ts: TokenStream = mac.node.tts.clone().into(); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - - Some(ast::Expr { - id: ast::NodeId::new(0), // dummy value - node: ast::ExprKind::Try(parser.parse_expr().ok()?), - span: mac.span, // incorrect span, but shouldn't matter too much - attrs: ThinVec::new(), - }) - } else { - None - } -} - -fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { - let snippet = context.snippet(mac.span); - let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); - let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); - let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); - - if paren_pos < bracket_pos && paren_pos < brace_pos { - MacroStyle::Parens - } else if bracket_pos < brace_pos { - MacroStyle::Brackets - } else { - MacroStyle::Braces - } -} - -/// Indent each line according to the specified `indent`. -/// e.g. -/// ```rust -/// foo!{ -/// x, -/// y, -/// foo( -/// a, -/// b, -/// c, -/// ), -/// } -/// ``` -/// will become -/// ```rust -/// foo!{ -/// x, -/// y, -/// foo( -/// a, -/// b, -/// c, -/// ), -/// } -/// ``` -fn indent_macro_snippet( - context: &RewriteContext, - macro_str: &str, - indent: Indent, -) -> Option { - let mut lines = macro_str.lines(); - let first_line = lines.next().map(|s| s.trim_right())?; - let mut trimmed_lines = Vec::with_capacity(16); - - let min_prefix_space_width = lines - .filter_map(|line| { - let prefix_space_width = if is_empty_line(line) { - None - } else { - Some(get_prefix_space_width(context, line)) - }; - trimmed_lines.push((line.trim(), prefix_space_width)); - prefix_space_width - }) - .min()?; - - Some( - String::from(first_line) + "\n" - + &trimmed_lines - .iter() - .map(|&(line, prefix_space_width)| match prefix_space_width { - Some(original_indent_width) => { - let new_indent_width = indent.width() - + original_indent_width - .checked_sub(min_prefix_space_width) - .unwrap_or(0); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) - } - None => String::new(), - }) - .collect::>() - .join("\n"), - ) -} - -fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { - let mut width = 0; - for c in s.chars() { - match c { - ' ' => width += 1, - '\t' => width += context.config.tab_spaces(), - _ => return width, - } - } - width -} - -fn is_empty_line(s: &str) -> bool { - s.is_empty() || s.chars().all(char::is_whitespace) -} - -// A very simple parser that just parses a macros 2.0 definition into its branches. -// Currently we do not attempt to parse any further than that. -#[derive(new)] -struct MacroParser { - toks: Cursor, -} - -impl MacroParser { - // (`(` ... `)` `=>` `{` ... `}`)* - fn parse(&mut self) -> Option { - let mut branches = vec![]; - while self.toks.look_ahead(1).is_some() { - branches.push(self.parse_branch()?); - } - - Some(Macro { branches }) - } - - // `(` ... `)` `=>` `{` ... `}` - fn parse_branch(&mut self) -> Option { - let tok = self.toks.next()?; - let (lo, args_paren_kind) = match tok { - TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, ref d) => (sp.lo(), d.delim), - }; - let args = tok.joint().into(); - match self.toks.next()? { - TokenTree::Token(_, Token::FatArrow) => {} - _ => return None, - } - let (mut hi, body) = match self.toks.next()? { - TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, _) => { - let data = sp.data(); - ( - data.hi, - Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), - ) - } - }; - if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { - self.toks.next(); - hi = sp.hi(); - } - Some(MacroBranch { - span: mk_sp(lo, hi), - args_paren_kind, - args, - body, - }) - } -} - -// A parsed macros 2.0 macro definition. -struct Macro { - branches: Vec, -} - -// FIXME: it would be more efficient to use references to the token streams -// rather than clone them, if we can make the borrowing work out. -struct MacroBranch { - span: Span, - args_paren_kind: DelimToken, - args: ThinTokenStream, - body: Span, -} - -impl MacroBranch { - fn rewrite( - &self, - context: &RewriteContext, - shape: Shape, - multi_branch_style: bool, - ) -> Option { - // Only attempt to format function-like macros. - if self.args_paren_kind != DelimToken::Paren { - // FIXME(#1539): implement for non-sugared macros. - return None; - } - - // 5 = " => {" - let mut result = format_macro_args(self.args.clone(), shape.sub_width(5)?)?; - - if multi_branch_style { - result += " =>"; - } - - // The macro body is the most interesting part. It might end up as various - // AST nodes, but also has special variables (e.g, `$foo`) which can't be - // parsed as regular Rust code (and note that these can be escaped using - // `$$`). We'll try and format like an AST node, but we'll substitute - // variables for new names with the same length first. - - let old_body = context.snippet(self.body).trim(); - let (body_str, substs) = replace_names(old_body)?; - - let mut config = context.config.clone(); - config.set().hide_parse_errors(true); - - result += " {"; - - let has_block_body = old_body.starts_with('{'); - - let body_indent = if has_block_body { - shape.indent - } else { - // We'll hack the indent below, take this into account when formatting, - let body_indent = shape.indent.block_indent(&config); - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); - body_indent - }; - - // First try to format as items, then as statements. - let new_body = match ::format_snippet(&body_str, &config) { - Some(new_body) => new_body, - None => match ::format_code_block(&body_str, &config) { - Some(new_body) => new_body, - None => return None, - }, - }; - let new_body = wrap_str(new_body, config.max_width(), shape)?; - - // Indent the body since it is in a block. - let indent_str = body_indent.to_string(&config); - let mut new_body = new_body - .trim_right() - .lines() - .fold(String::new(), |mut s, l| { - if !l.is_empty() { - s += &indent_str; - } - s + l + "\n" - }); - - // Undo our replacement of macro variables. - // FIXME: this could be *much* more efficient. - for (old, new) in &substs { - if old_body.find(new).is_some() { - debug!("rewrite_macro_def: bailing matching variable: `{}`", new); - return None; - } - new_body = new_body.replace(new, old); - } - - if has_block_body { - result += new_body.trim(); - } else if !new_body.is_empty() { - result += "\n"; - result += &new_body; - result += &shape.indent.to_string(&config); - } - - result += "}"; - - Some(result) - } -} - -/// Format `lazy_static!` from https://crates.io/crates/lazy_static. -/// -/// # Expected syntax -/// -/// ``` -/// lazy_static! { -/// [pub] static ref NAME_1: TYPE_1 = EXPR_1; -/// [pub] static ref NAME_2: TYPE_2 = EXPR_2; -/// ... -/// [pub] static ref NAME_N: TYPE_N = EXPR_N; -/// } -/// ``` -fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) -> Option { - let mut result = String::with_capacity(1024); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - let nested_shape = shape.block_indent(context.config.tab_spaces()); - - result.push_str("lazy_static! {"); - result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); - - macro parse_or($method:ident $(,)* $($arg:expr),* $(,)*) { - match parser.$method($($arg,)*) { - Ok(val) => { - if parser.sess.span_diagnostic.has_errors() { - parser.sess.span_diagnostic.reset_err_count(); - return None; - } else { - val - } - } - Err(mut err) => { - err.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - return None; - } - } - } - - while parser.token != Token::Eof { - // Parse a `lazy_static!` item. - let vis = ::utils::format_visibility(&parse_or!(parse_visibility, false)); - parser.eat_keyword(symbol::keywords::Static); - parser.eat_keyword(symbol::keywords::Ref); - let id = parse_or!(parse_ident); - parser.eat(&Token::Colon); - let ty = parse_or!(parse_ty); - parser.eat(&Token::Eq); - let expr = parse_or!(parse_expr); - parser.eat(&Token::Semi); - - // Rewrite as a static item. - let mut stmt = String::with_capacity(128); - stmt.push_str(&format!( - "{}static ref {}: {} =", - vis, - id, - ty.rewrite(context, shape)? - )); - result.push_str(&::expr::rewrite_assign_rhs( - context, - stmt, - &*expr, - nested_shape.sub_width(1)?, - )?); - result.push(';'); - if parser.token != Token::Eof { - result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); - } - } - - result.push_str(&shape.indent.to_string_with_newline(context.config)); - result.push('}'); - - Some(result) -} - -#[cfg(test)] -mod test { - use super::*; - use syntax::parse::{parse_stream_from_source_str, ParseSess}; - use syntax::codemap::{FileName, FilePathMapping}; - - fn format_macro_args_str(s: &str) -> String { - let input = parse_stream_from_source_str( - FileName::Custom("stdin".to_owned()), - s.to_owned(), - &ParseSess::new(FilePathMapping::empty()), - None, - ); - let shape = Shape { - width: 100, - indent: Indent::empty(), - offset: 0, - }; - format_macro_args(input.into(), shape).unwrap() - } - - #[test] - fn test_format_macro_args() { - assert_eq!(format_macro_args_str(""), "".to_owned()); - assert_eq!(format_macro_args_str("$ x : ident"), "$x: ident".to_owned()); - assert_eq!( - format_macro_args_str("$ m1 : ident , $ m2 : ident , $ x : ident"), - "$m1: ident, $m2: ident, $x: ident".to_owned() - ); - assert_eq!( - format_macro_args_str("$($beginning:ident),*;$middle:ident;$($end:ident),*"), - "$($beginning: ident),*; $middle: ident; $($end: ident),*".to_owned() - ); - assert_eq!( - format_macro_args_str( - "$ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) *" - ), - "$name: ident($($dol: tt $var: ident)*) $($body: tt)*".to_owned() - ); - } -} diff --git a/rustfmt-core/src/missed_spans.rs b/rustfmt-core/src/missed_spans.rs deleted file mode 100644 index dff6b94bd75..00000000000 --- a/rustfmt-core/src/missed_spans.rs +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; -use std::iter::repeat; - -use syntax::codemap::{BytePos, FileName, Pos, Span}; - -use codemap::LineRangeUtils; -use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; -use config::WriteMode; -use shape::{Indent, Shape}; -use utils::{count_newlines, last_line_width, mk_sp}; -use visitor::FmtVisitor; - -struct SnippetStatus { - /// An offset to the current line from the beginnig of the original snippet. - line_start: usize, - /// A length of trailing whitespaces on the current line. - last_wspace: Option, - /// The current line number. - cur_line: usize, -} - -impl SnippetStatus { - fn new(cur_line: usize) -> Self { - SnippetStatus { - line_start: 0, - last_wspace: None, - cur_line, - } - } -} - -impl<'a> FmtVisitor<'a> { - fn output_at_start(&self) -> bool { - self.buffer.is_empty() - } - - // TODO these format_missing methods are ugly. Refactor and add unit tests - // for the central whitespace stripping loop. - pub fn format_missing(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) - } - - pub fn format_missing_with_indent(&mut self, end: BytePos) { - let config = self.config; - self.format_missing_inner(end, |this, last_snippet, snippet| { - this.push_str(last_snippet.trim_right()); - if last_snippet == snippet && !this.output_at_start() { - // No new lines in the snippet. - this.push_str("\n"); - } - let indent = this.block_indent.to_string(config); - this.push_str(&indent); - }) - } - - pub fn format_missing_no_indent(&mut self, end: BytePos) { - self.format_missing_inner(end, |this, last_snippet, _| { - this.push_str(last_snippet.trim_right()); - }) - } - - fn format_missing_inner( - &mut self, - end: BytePos, - process_last_snippet: F, - ) { - let start = self.last_pos; - - if start == end { - // Do nothing if this is the beginning of the file. - if !self.output_at_start() { - process_last_snippet(self, "", ""); - } - return; - } - - assert!( - start < end, - "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end) - ); - - self.last_pos = end; - let span = mk_sp(start, end); - let snippet = self.snippet(span); - if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { - // Keep vertical spaces within range. - self.push_vertical_spaces(count_newlines(snippet)); - process_last_snippet(self, "", snippet); - } else { - self.write_snippet(span, &process_last_snippet); - } - } - - fn push_vertical_spaces(&mut self, mut newline_count: usize) { - // The buffer already has a trailing newline. - let offset = if self.buffer.ends_with('\n') { 0 } else { 1 }; - let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; - let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; - if newline_count > newline_upper_bound { - newline_count = newline_upper_bound; - } else if newline_count < newline_lower_bound { - newline_count = newline_lower_bound; - } - let blank_lines: String = repeat('\n').take(newline_count).collect(); - self.push_str(&blank_lines); - } - - fn write_snippet(&mut self, span: Span, process_last_snippet: F) - where - F: Fn(&mut FmtVisitor, &str, &str), - { - // Get a snippet from the file start to the span's hi without allocating. - // We need it to determine what precedes the current comment. If the comment - // follows code on the same line, we won't touch it. - let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos; - let local_begin = self.codemap.lookup_byte_offset(big_span_lo); - let local_end = self.codemap.lookup_byte_offset(span.hi()); - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; - - let big_diff = (span.lo() - big_span_lo).to_usize(); - let snippet = self.snippet(span); - - debug!("write_snippet `{}`", snippet); - - self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); - } - - fn write_snippet_inner( - &mut self, - big_snippet: &str, - big_diff: usize, - old_snippet: &str, - span: Span, - process_last_snippet: F, - ) where - F: Fn(&mut FmtVisitor, &str, &str), - { - // Trim whitespace from the right hand side of each line. - // Annoyingly, the library functions for splitting by lines etc. are not - // quite right, so we must do it ourselves. - let char_pos = self.codemap.lookup_char_pos(span.lo()); - let file_name = &char_pos.file.name; - let mut status = SnippetStatus::new(char_pos.line); - - let snippet = &*match self.config.write_mode() { - WriteMode::Coverage => replace_chars(old_snippet), - _ => Cow::from(old_snippet), - }; - - for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { - debug!("{:?}: {:?}", kind, subslice); - - let newline_count = count_newlines(subslice); - let within_file_lines_range = self.config.file_lines().intersects_range( - file_name, - status.cur_line, - status.cur_line + newline_count, - ); - - if CodeCharKind::Comment == kind && within_file_lines_range { - // 1: comment. - self.process_comment( - &mut status, - snippet, - &big_snippet[..(offset + big_diff)], - offset, - subslice, - ); - } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range { - // 2: blank lines. - self.push_vertical_spaces(newline_count); - status.cur_line += newline_count; - status.line_start = offset + newline_count; - } else { - // 3: code which we failed to format or which is not within file-lines range. - self.process_missing_code(&mut status, snippet, subslice, offset, file_name); - } - } - - process_last_snippet(self, &snippet[status.line_start..], snippet); - } - - fn process_comment( - &mut self, - status: &mut SnippetStatus, - snippet: &str, - big_snippet: &str, - offset: usize, - subslice: &str, - ) { - let last_char = big_snippet - .chars() - .rev() - .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) - .next(); - - let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); - - let comment_indent = if fix_indent { - if let Some('{') = last_char { - self.push_str("\n"); - } - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - self.block_indent - } else { - self.push_str(" "); - Indent::from_width(self.config, last_line_width(&self.buffer)) - }; - - let comment_width = ::std::cmp::min( - self.config.comment_width(), - self.config.max_width() - self.block_indent.width(), - ); - let comment_shape = Shape::legacy(comment_width, comment_indent); - let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) - .unwrap_or_else(|| String::from(subslice)); - self.push_str(&comment_str); - - status.last_wspace = None; - status.line_start = offset + subslice.len(); - - if let Some('/') = subslice.chars().nth(1) { - // check that there are no contained block comments - if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() >= 2 && &s[0..2] == "/*") - { - // Add a newline after line comments - self.push_str("\n"); - } - } else if status.line_start <= snippet.len() { - // For other comments add a newline if there isn't one at the end already - match snippet[status.line_start..].chars().next() { - Some('\n') | Some('\r') => (), - _ => self.push_str("\n"), - } - } - - status.cur_line += count_newlines(subslice); - } - - fn process_missing_code( - &mut self, - status: &mut SnippetStatus, - snippet: &str, - subslice: &str, - offset: usize, - file_name: &FileName, - ) { - for (mut i, c) in subslice.char_indices() { - i += offset; - - if c == '\n' { - let skip_this_line = !self.config - .file_lines() - .contains_line(file_name, status.cur_line); - if skip_this_line { - status.last_wspace = None; - } - - if let Some(lw) = status.last_wspace { - self.push_str(&snippet[status.line_start..lw]); - self.push_str("\n"); - status.last_wspace = None; - } else { - self.push_str(&snippet[status.line_start..i + 1]); - } - - status.cur_line += 1; - status.line_start = i + 1; - } else if c.is_whitespace() && status.last_wspace.is_none() { - status.last_wspace = Some(i); - } else if c == ';' && status.last_wspace.is_some() { - status.line_start = i; - status.last_wspace = None; - } else { - status.last_wspace = None; - } - } - - let remaining = snippet[status.line_start..subslice.len() + offset].trim(); - if !remaining.is_empty() { - self.push_str(remaining); - status.line_start = subslice.len() + offset; - } - } -} - -fn replace_chars(string: &str) -> Cow { - Cow::from( - string - .chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect::(), - ) -} diff --git a/rustfmt-core/src/modules.rs b/rustfmt-core/src/modules.rs deleted file mode 100644 index 0f439910324..00000000000 --- a/rustfmt-core/src/modules.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::collections::BTreeMap; -use std::io; -use std::path::{Path, PathBuf}; - -use syntax::ast; -use syntax::codemap::{self, FileName}; -use syntax::parse::parser; - -use utils::contains_skip; - -/// List all the files containing modules of a crate. -/// If a file is used twice in a crate, it appears only once. -pub fn list_files<'a>( - krate: &'a ast::Crate, - codemap: &codemap::CodeMap, -) -> Result, io::Error> { - let mut result = BTreeMap::new(); // Enforce file order determinism - let root_filename = codemap.span_to_filename(krate.span); - { - let parent = match root_filename { - FileName::Real(ref path) => path.parent().unwrap(), - _ => Path::new(""), - }; - list_submodules(&krate.module, parent, codemap, &mut result)?; - } - result.insert(root_filename, &krate.module); - Ok(result) -} - -/// Recursively list all external modules included in a module. -fn list_submodules<'a>( - module: &'a ast::Mod, - search_dir: &Path, - codemap: &codemap::CodeMap, - result: &mut BTreeMap, -) -> Result<(), io::Error> { - debug!("list_submodules: search_dir: {:?}", search_dir); - for item in &module.items { - if let ast::ItemKind::Mod(ref sub_mod) = item.node { - if !contains_skip(&item.attrs) { - let is_internal = - codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); - let dir_path = if is_internal { - search_dir.join(&item.ident.to_string()) - } else { - let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; - let dir_path = mod_path.parent().unwrap().to_owned(); - result.insert(FileName::Real(mod_path), sub_mod); - dir_path - }; - list_submodules(sub_mod, &dir_path, codemap, result)?; - } - } - } - Ok(()) -} - -/// Find the file corresponding to an external mod -fn module_file( - id: ast::Ident, - attrs: &[ast::Attribute], - dir_path: &Path, - codemap: &codemap::CodeMap, -) -> Result { - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { - return Ok(path); - } - - match parser::Parser::default_submod_path(id, None, dir_path, codemap).result { - Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), - Err(_) => Err(io::Error::new( - io::ErrorKind::Other, - format!("Couldn't find module {}", id), - )), - } -} diff --git a/rustfmt-core/src/patterns.rs b/rustfmt-core/src/patterns.rs deleted file mode 100644 index 4bcf2890c35..00000000000 --- a/rustfmt-core/src/patterns.rs +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use config::lists::*; -use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; -use syntax::codemap::{self, BytePos, Span}; -use syntax::ptr; - -use codemap::SpanUtils; -use comment::FindUncommented; -use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, - wrap_struct_field, PairParts}; -use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list}; -use macros::{rewrite_macro, MacroPosition}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use spanned::Spanned; -use types::{rewrite_path, PathContext}; -use utils::{format_mutability, mk_sp}; - -impl Rewrite for Pat { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), - PatKind::Ident(binding_mode, ident, ref sub_pat) => { - let (prefix, mutability) = match binding_mode { - BindingMode::ByRef(mutability) => ("ref ", mutability), - BindingMode::ByValue(mutability) => ("", mutability), - }; - let mut_infix = format_mutability(mutability); - let id_str = ident.node.to_string(); - let sub_pat = match *sub_pat { - Some(ref p) => { - // 3 - ` @ `. - let width = shape - .width - .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?; - format!( - " @ {}", - p.rewrite(context, Shape::legacy(width, shape.indent))? - ) - } - None => "".to_owned(), - }; - - Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) - } - PatKind::Wild => { - if 1 <= shape.width { - Some("_".to_owned()) - } else { - None - } - } - PatKind::Range(ref lhs, ref rhs, ref end_kind) => { - let infix = match *end_kind { - RangeEnd::Included(RangeSyntax::DotDotDot) => "...", - RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", - RangeEnd::Excluded => "..", - }; - let infix = if context.config.spaces_around_ranges() { - format!(" {} ", infix) - } else { - infix.to_owned() - }; - rewrite_pair( - &**lhs, - &**rhs, - PairParts::new("", &infix, ""), - context, - shape, - SeparatorPlace::Front, - ) - } - PatKind::Ref(ref pat, mutability) => { - let prefix = format!("&{}", format_mutability(mutability)); - rewrite_unary_prefix(context, &prefix, &**pat, shape) - } - PatKind::Tuple(ref items, dotdot_pos) => { - rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) - } - PatKind::Path(ref q_self, ref path) => { - rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) - } - PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { - let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; - rewrite_tuple_pat( - pat_vec, - dotdot_pos, - Some(path_str), - self.span, - context, - shape, - ) - } - PatKind::Lit(ref expr) => expr.rewrite(context, shape), - PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { - // Rewrite all the sub-patterns. - let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = slice_pat - .as_ref() - .map(|p| Some(format!("{}..", p.rewrite(context, shape)?))); - let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); - - // Munge them together. - let pats: Option> = - prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); - - // Check that all the rewrites succeeded, and if not return None. - let pats = pats?; - - // Unwrap all the sub-strings and join them with commas. - let result = if context.config.spaces_within_parens_and_brackets() { - format!("[ {} ]", pats.join(", ")) - } else { - format!("[{}]", pats.join(", ")) - }; - Some(result) - } - PatKind::Struct(ref path, ref fields, ellipsis) => { - rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) - } - PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), - } - } -} - -fn rewrite_struct_pat( - path: &ast::Path, - fields: &[codemap::Spanned], - ellipsis: bool, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - // 2 = ` {` - let path_shape = shape.sub_width(2)?; - let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - - if fields.is_empty() && !ellipsis { - return Some(format!("{} {{}}", path_str)); - } - - let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") }; - - // 3 = ` { `, 2 = ` }`. - let (h_shape, v_shape) = - struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?; - - let items = itemize_list( - context.snippet_provider, - fields.iter(), - terminator, - ",", - |f| f.span.lo(), - |f| f.span.hi(), - |f| f.node.rewrite(context, v_shape), - context.snippet_provider.span_after(span, "{"), - span.hi(), - false, - ); - let item_vec = items.collect::>(); - - let tactic = struct_lit_tactic(h_shape, context, &item_vec); - let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); - let fmt = struct_lit_formatting(nested_shape, tactic, context, false); - - let mut fields_str = write_list(&item_vec, &fmt)?; - let one_line_width = h_shape.map_or(0, |shape| shape.width); - - if ellipsis { - if fields_str.contains('\n') || fields_str.len() > one_line_width { - // Add a missing trailing comma. - if fmt.trailing_separator == SeparatorTactic::Never { - fields_str.push_str(","); - } - fields_str.push_str("\n"); - fields_str.push_str(&nested_shape.indent.to_string(context.config)); - fields_str.push_str(".."); - } else { - if !fields_str.is_empty() { - // there are preceding struct fields being matched on - if fmt.tactic == DefinitiveListTactic::Vertical { - // if the tactic is Vertical, write_list already added a trailing , - fields_str.push_str(" "); - } else { - fields_str.push_str(", "); - } - } - fields_str.push_str(".."); - } - } - - let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); - Some(format!("{} {{{}}}", path_str, fields_str)) -} - -impl Rewrite for FieldPat { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let pat = self.pat.rewrite(context, shape); - if self.is_shorthand { - pat - } else { - let pat_str = pat?; - let id_str = self.ident.to_string(); - let one_line_width = id_str.len() + 2 + pat_str.len(); - if one_line_width <= shape.width { - Some(format!("{}: {}", id_str, pat_str)) - } else { - let nested_shape = shape.block_indent(context.config.tab_spaces()); - let pat_str = self.pat.rewrite(context, nested_shape)?; - Some(format!( - "{}:\n{}{}", - id_str, - nested_shape.indent.to_string(context.config), - pat_str, - )) - } - } - } -} - -pub enum TuplePatField<'a> { - Pat(&'a ptr::P), - Dotdot(Span), -} - -impl<'a> Rewrite for TuplePatField<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - TuplePatField::Pat(p) => p.rewrite(context, shape), - TuplePatField::Dotdot(_) => Some("..".to_string()), - } - } -} - -impl<'a> Spanned for TuplePatField<'a> { - fn span(&self) -> Span { - match *self { - TuplePatField::Pat(p) => p.span(), - TuplePatField::Dotdot(span) => span, - } - } -} - -pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { - match *pat { - TuplePatField::Pat(pat) => match pat.node { - ast::PatKind::Path(..) - | ast::PatKind::Tuple(..) - | ast::PatKind::Struct(..) - | ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, - ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { - can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) - } - ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), - _ => false, - }, - TuplePatField::Dotdot(..) => false, - } -} - -fn rewrite_tuple_pat( - pats: &[ptr::P], - dotdot_pos: Option, - path_str: Option, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); - - if let Some(pos) = dotdot_pos { - let prev = if pos == 0 { - span.lo() - } else { - pats[pos - 1].span().hi() - }; - let next = if pos + 1 >= pats.len() { - span.hi() - } else { - pats[pos + 1].span().lo() - }; - let dot_span = mk_sp(prev, next); - let snippet = context.snippet(dot_span); - let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32); - let dotdot = TuplePatField::Dotdot(Span::new( - lo, - // 2 == "..".len() - lo + BytePos(2), - codemap::NO_EXPANSION, - )); - pat_vec.insert(pos, dotdot); - } - - if pat_vec.is_empty() { - return Some(format!("{}()", path_str.unwrap_or_default())); - } - - let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); - let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 - { - let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; - let sp = pat_vec[new_item_count - 1].span(); - let snippet = context.snippet(sp); - let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); - ( - &pat_vec[..new_item_count], - mk_sp(span.lo(), lo + BytePos(1)), - ) - } else { - (&pat_vec[..], span) - }; - - // add comma if `(x,)` - let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); - let mut context = context.clone(); - if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { - context.inside_macro = true; - } - let path_str = path_str.unwrap_or_default(); - let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); - for pat in pat_vec { - pat_ref_vec.push(pat); - } - - rewrite_call_inner( - &context, - &path_str, - &pat_ref_vec[..], - span, - shape, - shape.width, - add_comma, - ) -} - -fn count_wildcard_suffix_len( - context: &RewriteContext, - patterns: &[TuplePatField], - span: Span, - shape: Shape, -) -> usize { - let mut suffix_len = 0; - - let items: Vec<_> = itemize_list( - context.snippet_provider, - patterns.iter(), - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, shape), - context.snippet_provider.span_after(span, "("), - span.hi() - BytePos(1), - false, - ).collect(); - - for item in items.iter().rev().take_while(|i| match i.item { - Some(ref internal_string) if internal_string == "_" => true, - _ => false, - }) { - suffix_len += 1; - - if item.pre_comment.is_some() || item.post_comment.is_some() { - break; - } - } - - suffix_len -} diff --git a/rustfmt-core/src/reorder.rs b/rustfmt-core/src/reorder.rs deleted file mode 100644 index d4bc36fc83f..00000000000 --- a/rustfmt-core/src/reorder.rs +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Reorder items. -//! -//! `mod`, `extern crate` and `use` declarations are reorderd in alphabetical -//! order. Trait items are reordered in pre-determined order (associated types -//! and constatns comes before methods). - -// TODO(#2455): Reorder trait items. - -use config::{Config, lists::*}; -use syntax::{ast, attr, codemap::Span}; - -use attr::filter_inline_attrs; -use codemap::LineRangeUtils; -use comment::combine_strs_with_missing_comments; -use imports::{path_to_imported_ident, rewrite_import}; -use items::{rewrite_extern_crate, rewrite_mod}; -use lists::{itemize_list, write_list, ListFormatting}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use spanned::Spanned; -use utils::mk_sp; -use visitor::FmtVisitor; - -use std::cmp::Ordering; - -fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { - a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) -} - -fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { - for segment in a.segments.iter().zip(b.segments.iter()) { - let ord = compare_path_segments(segment.0, segment.1); - if ord != Ordering::Equal { - return ord; - } - } - a.segments.len().cmp(&b.segments.len()) -} - -fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Ordering { - use ast::UseTreeKind::*; - - // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be - // fully added - if !nested { - let paths_cmp = compare_paths(&a.prefix, &b.prefix); - if paths_cmp != Ordering::Equal { - return paths_cmp; - } - } - - match (&a.kind, &b.kind) { - (&Simple(ident_a), &Simple(ident_b)) => { - let name_a = &*path_to_imported_ident(&a.prefix).name.as_str(); - let name_b = &*path_to_imported_ident(&b.prefix).name.as_str(); - let name_ordering = if name_a == "self" { - if name_b == "self" { - Ordering::Equal - } else { - Ordering::Less - } - } else if name_b == "self" { - Ordering::Greater - } else { - name_a.cmp(name_b) - }; - if name_ordering == Ordering::Equal { - if ident_a.name.as_str() != name_a { - if ident_b.name.as_str() != name_b { - ident_a.name.as_str().cmp(&ident_b.name.as_str()) - } else { - Ordering::Greater - } - } else { - Ordering::Less - } - } else { - name_ordering - } - } - (&Glob, &Glob) => Ordering::Equal, - (&Simple(_), _) | (&Glob, &Nested(_)) => Ordering::Less, - (&Nested(ref a_items), &Nested(ref b_items)) => { - let mut a = a_items - .iter() - .map(|&(ref tree, _)| tree.clone()) - .collect::>(); - let mut b = b_items - .iter() - .map(|&(ref tree, _)| tree.clone()) - .collect::>(); - a.sort_by(|a, b| compare_use_trees(a, b, true)); - b.sort_by(|a, b| compare_use_trees(a, b, true)); - for comparison_pair in a.iter().zip(b.iter()) { - let ord = compare_use_trees(comparison_pair.0, comparison_pair.1, true); - if ord != Ordering::Equal { - return ord; - } - } - a.len().cmp(&b.len()) - } - (&Glob, &Simple(_)) | (&Nested(_), _) => Ordering::Greater, - } -} - -/// Choose the ordering between the given two items. -fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { - match (&a.node, &b.node) { - (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { - a.ident.name.as_str().cmp(&b.ident.name.as_str()) - } - (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { - compare_use_trees(a_tree, b_tree, false) - } - (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { - // `extern crate foo as bar;` - // ^^^ Comparing this. - let a_orig_name = - a_name.map_or_else(|| a.ident.name.as_str(), |symbol| symbol.as_str()); - let b_orig_name = - b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); - let result = a_orig_name.cmp(&b_orig_name); - if result != Ordering::Equal { - return result; - } - - // `extern crate foo as bar;` - // ^^^ Comparing this. - match (a_name, b_name) { - (Some(..), None) => Ordering::Greater, - (None, Some(..)) => Ordering::Less, - (None, None) => Ordering::Equal, - (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), - } - } - _ => unreachable!(), - } -} - -/// Rewrite a list of items with reordering. Every item in `items` must have -/// the same `ast::ItemKind`. -// TODO (some day) remove unused imports, expand globs, compress many single -// imports into a list import. -fn rewrite_reorderable_items( - context: &RewriteContext, - reorderable_items: &[&ast::Item], - shape: Shape, - span: Span, -) -> Option { - let items = itemize_list( - context.snippet_provider, - reorderable_items.iter(), - "", - ";", - |item| item.span().lo(), - |item| item.span().hi(), - |item| { - let attrs = filter_inline_attrs(&item.attrs, item.span()); - let attrs_str = attrs.rewrite(context, shape)?; - - let missed_span = if attrs.is_empty() { - mk_sp(item.span.lo(), item.span.lo()) - } else { - mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) - }; - - let item_str = match item.node { - ast::ItemKind::Use(ref tree) => { - rewrite_import(context, &item.vis, tree, &item.attrs, shape)? - } - ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, - ast::ItemKind::Mod(..) => rewrite_mod(item), - _ => return None, - }; - - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missed_span, - shape, - false, - ) - }, - span.lo(), - span.hi(), - false, - ); - let mut item_pair_vec: Vec<_> = items.zip(reorderable_items.iter()).collect(); - item_pair_vec.sort_by(|a, b| compare_items(a.1, b.1)); - let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); - - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: true, - preserve_newline: false, - config: context.config, - }; - - write_list(&item_vec, &fmt) -} - -fn contains_macro_use_attr(item: &ast::Item) -> bool { - attr::contains_name(&filter_inline_attrs(&item.attrs, item.span()), "macro_use") -} - -/// A simplified version of `ast::ItemKind`. -#[derive(Debug, PartialEq, Eq, Copy, Clone)] -enum ReorderableItemKind { - ExternCrate, - Mod, - Use, - /// An item that cannot be reordered. Either has an unreorderable item kind - /// or an `macro_use` attribute. - Other, -} - -impl ReorderableItemKind { - pub fn from(item: &ast::Item) -> Self { - match item.node { - _ if contains_macro_use_attr(item) => ReorderableItemKind::Other, - ast::ItemKind::ExternCrate(..) => ReorderableItemKind::ExternCrate, - ast::ItemKind::Mod(..) => ReorderableItemKind::Mod, - ast::ItemKind::Use(..) => ReorderableItemKind::Use, - _ => ReorderableItemKind::Other, - } - } - - pub fn is_same_item_kind(&self, item: &ast::Item) -> bool { - ReorderableItemKind::from(item) == *self - } - - pub fn is_reorderable(&self, config: &Config) -> bool { - match *self { - ReorderableItemKind::ExternCrate => config.reorder_extern_crates(), - ReorderableItemKind::Mod => config.reorder_modules(), - ReorderableItemKind::Use => config.reorder_imports(), - ReorderableItemKind::Other => false, - } - } - - pub fn in_group(&self, config: &Config) -> bool { - match *self { - ReorderableItemKind::ExternCrate => config.reorder_extern_crates_in_group(), - ReorderableItemKind::Mod => config.reorder_modules(), - ReorderableItemKind::Use => config.reorder_imports_in_group(), - ReorderableItemKind::Other => false, - } - } -} - -impl<'b, 'a: 'b> FmtVisitor<'a> { - /// Format items with the same item kind and reorder them. If `in_group` is - /// `true`, then the items separated by an empty line will not be reordered - /// together. - fn walk_reorderable_items( - &mut self, - items: &[&ast::Item], - item_kind: ReorderableItemKind, - in_group: bool, - ) -> usize { - let mut last = self.codemap.lookup_line_range(items[0].span()); - let item_length = items - .iter() - .take_while(|ppi| { - item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) - }) - .count(); - let items = &items[..item_length]; - - let at_least_one_in_file_lines = items - .iter() - .any(|item| !out_of_file_lines_range!(self, item.span)); - - if at_least_one_in_file_lines && !items.is_empty() { - let lo = items.first().unwrap().span().lo(); - let hi = items.last().unwrap().span().hi(); - let span = mk_sp(lo, hi); - let rw = rewrite_reorderable_items(&self.get_context(), items, self.shape(), span); - self.push_rewrite(span, rw); - } else { - for item in items { - self.push_rewrite(item.span, None); - } - } - - item_length - } - - /// Visit and format the given items. Items are reordered If they are - /// consecutive and reorderable. - pub fn visit_items_with_reordering(&mut self, mut items: &[&ast::Item]) { - while !items.is_empty() { - // If the next item is a `use`, `extern crate` or `mod`, then extract it and any - // subsequent items that have the same item kind to be reordered within - // `walk_reorderable_items`. Otherwise, just format the next item for output. - let item_kind = ReorderableItemKind::from(items[0]); - if item_kind.is_reorderable(self.config) { - let visited_items_num = - self.walk_reorderable_items(items, item_kind, item_kind.in_group(self.config)); - let (_, rest) = items.split_at(visited_items_num); - items = rest; - } else { - // Reaching here means items were not reordered. There must be at least - // one item left in `items`, so calling `unwrap()` here is safe. - let (item, rest) = items.split_first().unwrap(); - self.visit_item(item); - items = rest; - } - } - } -} diff --git a/rustfmt-core/src/rewrite.rs b/rustfmt-core/src/rewrite.rs deleted file mode 100644 index 708e31d86dd..00000000000 --- a/rustfmt-core/src/rewrite.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A generic trait to abstract the rewriting of an element (of the AST). - -use syntax::codemap::{CodeMap, Span}; -use syntax::parse::ParseSess; - -use config::{Config, IndentStyle}; -use shape::Shape; -use visitor::SnippetProvider; - -pub trait Rewrite { - /// Rewrite self into shape. - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; -} - -#[derive(Clone)] -pub struct RewriteContext<'a> { - pub parse_session: &'a ParseSess, - pub codemap: &'a CodeMap, - pub config: &'a Config, - pub inside_macro: bool, - // Force block indent style even if we are using visual indent style. - pub use_block: bool, - // When `format_if_else_cond_comment` is true, unindent the comment on top - // of the `else` or `else if`. - pub is_if_else_block: bool, - // When rewriting chain, veto going multi line except the last element - pub force_one_line_chain: bool, - pub snippet_provider: &'a SnippetProvider<'a>, -} - -impl<'a> RewriteContext<'a> { - pub fn snippet(&self, span: Span) -> &str { - self.snippet_provider.span_to_snippet(span).unwrap() - } - - /// Return true if we should use block indent style for rewriting function call. - pub fn use_block_indent(&self) -> bool { - self.config.indent_style() == IndentStyle::Block || self.use_block - } - - pub fn budget(&self, used_width: usize) -> usize { - self.config.max_width().checked_sub(used_width).unwrap_or(0) - } -} diff --git a/rustfmt-core/src/rustfmt_diff.rs b/rustfmt-core/src/rustfmt_diff.rs deleted file mode 100644 index f9919157620..00000000000 --- a/rustfmt-core/src/rustfmt_diff.rs +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use config::Color; -use diff; -use std::collections::VecDeque; -use std::io; -use term; -use std::io::Write; -use utils::use_colored_tty; - -#[derive(Debug, PartialEq)] -pub enum DiffLine { - Context(String), - Expected(String), - Resulting(String), -} - -#[derive(Debug, PartialEq)] -pub struct Mismatch { - /// The line number in the formatted version. - pub line_number: u32, - /// The line number in the original version. - pub line_number_orig: u32, - /// The set of lines (context and old/new) in the mismatch. - pub lines: Vec, -} - -impl Mismatch { - fn new(line_number: u32, line_number_orig: u32) -> Mismatch { - Mismatch { - line_number, - line_number_orig, - lines: Vec::new(), - } - } -} - -// This struct handles writing output to stdout and abstracts away the logic -// of printing in color, if it's possible in the executing environment. -pub struct OutputWriter { - terminal: Option>>, -} - -impl OutputWriter { - // Create a new OutputWriter instance based on the caller's preference - // for colorized output and the capabilities of the terminal. - pub fn new(color: Color) -> Self { - if let Some(t) = term::stdout() { - if use_colored_tty(color) && t.supports_color() { - return OutputWriter { terminal: Some(t) }; - } - } - OutputWriter { terminal: None } - } - - // Write output in the optionally specified color. The output is written - // in the specified color if this OutputWriter instance contains a - // Terminal in its `terminal` field. - pub fn writeln(&mut self, msg: &str, color: Option) { - match &mut self.terminal { - Some(ref mut t) => { - if let Some(color) = color { - t.fg(color).unwrap(); - } - writeln!(t, "{}", msg).unwrap(); - if color.is_some() { - t.reset().unwrap(); - } - } - None => println!("{}", msg), - } - } -} - -// Produces a diff between the expected output and actual output of rustfmt. -pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { - let mut line_number = 1; - let mut line_number_orig = 1; - let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); - let mut lines_since_mismatch = context_size + 1; - let mut results = Vec::new(); - let mut mismatch = Mismatch::new(0, 0); - - for result in diff::lines(expected, actual) { - match result { - diff::Result::Left(str) => { - if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { - results.push(mismatch); - mismatch = Mismatch::new( - line_number - context_queue.len() as u32, - line_number_orig - context_queue.len() as u32, - ); - } - - while let Some(line) = context_queue.pop_front() { - mismatch.lines.push(DiffLine::Context(line.to_owned())); - } - - mismatch.lines.push(DiffLine::Resulting(str.to_owned())); - line_number_orig += 1; - lines_since_mismatch = 0; - } - diff::Result::Right(str) => { - if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { - results.push(mismatch); - mismatch = Mismatch::new( - line_number - context_queue.len() as u32, - line_number_orig - context_queue.len() as u32, - ); - } - - while let Some(line) = context_queue.pop_front() { - mismatch.lines.push(DiffLine::Context(line.to_owned())); - } - - mismatch.lines.push(DiffLine::Expected(str.to_owned())); - line_number += 1; - lines_since_mismatch = 0; - } - diff::Result::Both(str, _) => { - if context_queue.len() >= context_size { - let _ = context_queue.pop_front(); - } - - if lines_since_mismatch < context_size { - mismatch.lines.push(DiffLine::Context(str.to_owned())); - } else if context_size > 0 { - context_queue.push_back(str); - } - - line_number += 1; - line_number_orig += 1; - lines_since_mismatch += 1; - } - } - } - - results.push(mismatch); - results.remove(0); - - results -} - -pub fn print_diff(diff: Vec, get_section_title: F, color: Color) -where - F: Fn(u32) -> String, -{ - let mut writer = OutputWriter::new(color); - - for mismatch in diff { - let title = get_section_title(mismatch.line_number); - writer.writeln(&format!("{}", title), None); - - for line in mismatch.lines { - match line { - DiffLine::Context(ref str) => writer.writeln(&format!(" {}⏎", str), None), - DiffLine::Expected(ref str) => { - writer.writeln(&format!("+{}⏎", str), Some(term::color::GREEN)) - } - DiffLine::Resulting(ref str) => { - writer.writeln(&format!("-{}⏎", str), Some(term::color::RED)) - } - } - } - } -} - -/// Convert a Mismatch into a serialised form which just includes -/// enough information to modify the original file. -/// Each section starts with a line with three integers, space separated: -/// lineno num_removed num_added -/// followed by (num_added) lines of added text. The line numbers are -/// relative to the original file. -pub fn output_modified(mut out: W, diff: Vec) -where - W: Write, -{ - for mismatch in diff { - let (num_removed, num_added) = mismatch.lines.iter().fold((0, 0), |(rem, add), line| { - match *line { - DiffLine::Context(_) => panic!("No Context expected"), - DiffLine::Expected(_) => (rem, add + 1), - DiffLine::Resulting(_) => (rem + 1, add), - } - }); - // Write a header with enough information to separate the modified lines. - writeln!( - out, - "{} {} {}", - mismatch.line_number_orig, num_removed, num_added - ).unwrap(); - - for line in mismatch.lines { - match line { - DiffLine::Context(_) | DiffLine::Resulting(_) => (), - DiffLine::Expected(ref str) => { - writeln!(out, "{}", str).unwrap(); - } - } - } - } -} - -#[cfg(test)] -mod test { - use super::{make_diff, Mismatch}; - use super::DiffLine::*; - - #[test] - fn diff_simple() { - let src = "one\ntwo\nthree\nfour\nfive\n"; - let dest = "one\ntwo\ntrois\nfour\nfive\n"; - let diff = make_diff(src, dest, 1); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 2, - line_number_orig: 2, - lines: vec![ - Context("two".to_owned()), - Resulting("three".to_owned()), - Expected("trois".to_owned()), - Context("four".to_owned()), - ], - }, - ] - ); - } - - #[test] - fn diff_simple2() { - let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n"; - let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; - let diff = make_diff(src, dest, 1); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 2, - line_number_orig: 2, - lines: vec![ - Context("two".to_owned()), - Resulting("three".to_owned()), - Expected("trois".to_owned()), - Context("four".to_owned()), - ], - }, - Mismatch { - line_number: 5, - line_number_orig: 5, - lines: vec![ - Resulting("five".to_owned()), - Expected("cinq".to_owned()), - Context("six".to_owned()), - ], - }, - ] - ); - } - - #[test] - fn diff_zerocontext() { - let src = "one\ntwo\nthree\nfour\nfive\n"; - let dest = "one\ntwo\ntrois\nfour\nfive\n"; - let diff = make_diff(src, dest, 0); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 3, - line_number_orig: 3, - lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], - }, - ] - ); - } - - #[test] - fn diff_trailing_newline() { - let src = "one\ntwo\nthree\nfour\nfive"; - let dest = "one\ntwo\nthree\nfour\nfive\n"; - let diff = make_diff(src, dest, 1); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 5, - line_number_orig: 5, - lines: vec![Context("five".to_owned()), Expected("".to_owned())], - }, - ] - ); - } -} diff --git a/rustfmt-core/src/shape.rs b/rustfmt-core/src/shape.rs deleted file mode 100644 index 22d6a096efa..00000000000 --- a/rustfmt-core/src/shape.rs +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; -use std::ops::{Add, Sub}; - -use Config; - -#[derive(Copy, Clone, Debug)] -pub struct Indent { - // Width of the block indent, in characters. Must be a multiple of - // Config::tab_spaces. - pub block_indent: usize, - // Alignment in characters. - pub alignment: usize, -} - -// INDENT_BUFFER.len() = 80 -const INDENT_BUFFER_LEN: usize = 80; -const INDENT_BUFFER: &str = - "\n "; -impl Indent { - pub fn new(block_indent: usize, alignment: usize) -> Indent { - Indent { - block_indent, - alignment, - } - } - - pub fn from_width(config: &Config, width: usize) -> Indent { - if config.hard_tabs() { - let tab_num = width / config.tab_spaces(); - let alignment = width % config.tab_spaces(); - Indent::new(config.tab_spaces() * tab_num, alignment) - } else { - Indent::new(width, 0) - } - } - - pub fn empty() -> Indent { - Indent::new(0, 0) - } - - pub fn block_only(&self) -> Indent { - Indent { - block_indent: self.block_indent, - alignment: 0, - } - } - - pub fn block_indent(mut self, config: &Config) -> Indent { - self.block_indent += config.tab_spaces(); - self - } - - pub fn block_unindent(mut self, config: &Config) -> Indent { - if self.block_indent < config.tab_spaces() { - Indent::new(self.block_indent, 0) - } else { - self.block_indent -= config.tab_spaces(); - self - } - } - - pub fn width(&self) -> usize { - self.block_indent + self.alignment - } - - pub fn to_string(&self, config: &Config) -> Cow<'static, str> { - self.to_string_inner(config, 1) - } - - pub fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { - self.to_string_inner(config, 0) - } - - fn to_string_inner(&self, config: &Config, offset: usize) -> Cow<'static, str> { - let (num_tabs, num_spaces) = if config.hard_tabs() { - (self.block_indent / config.tab_spaces(), self.alignment) - } else { - (0, self.width()) - }; - let num_chars = num_tabs + num_spaces; - if num_tabs == 0 && num_chars + offset <= INDENT_BUFFER_LEN { - Cow::from(&INDENT_BUFFER[offset..num_chars + 1]) - } else { - let mut indent = String::with_capacity(num_chars + if offset == 0 { 1 } else { 0 }); - if offset == 0 { - indent.push('\n'); - } - for _ in 0..num_tabs { - indent.push('\t') - } - for _ in 0..num_spaces { - indent.push(' ') - } - Cow::from(indent) - } - } -} - -impl Add for Indent { - type Output = Indent; - - fn add(self, rhs: Indent) -> Indent { - Indent { - block_indent: self.block_indent + rhs.block_indent, - alignment: self.alignment + rhs.alignment, - } - } -} - -impl Sub for Indent { - type Output = Indent; - - fn sub(self, rhs: Indent) -> Indent { - Indent::new( - self.block_indent - rhs.block_indent, - self.alignment - rhs.alignment, - ) - } -} - -impl Add for Indent { - type Output = Indent; - - fn add(self, rhs: usize) -> Indent { - Indent::new(self.block_indent, self.alignment + rhs) - } -} - -impl Sub for Indent { - type Output = Indent; - - fn sub(self, rhs: usize) -> Indent { - Indent::new(self.block_indent, self.alignment - rhs) - } -} - -#[derive(Copy, Clone, Debug)] -pub struct Shape { - pub width: usize, - // The current indentation of code. - pub indent: Indent, - // Indentation + any already emitted text on the first line of the current - // statement. - pub offset: usize, -} - -impl Shape { - /// `indent` is the indentation of the first line. The next lines - /// should begin with at least `indent` spaces (except backwards - /// indentation). The first line should not begin with indentation. - /// `width` is the maximum number of characters on the last line - /// (excluding `indent`). The width of other lines is not limited by - /// `width`. - /// Note that in reality, we sometimes use width for lines other than the - /// last (i.e., we are conservative). - // .......*-------* - // | | - // | *-* - // *-----| - // |<------------>| max width - // |<---->| indent - // |<--->| width - pub fn legacy(width: usize, indent: Indent) -> Shape { - Shape { - width, - indent, - offset: indent.alignment, - } - } - - pub fn indented(indent: Indent, config: &Config) -> Shape { - Shape { - width: config.max_width().checked_sub(indent.width()).unwrap_or(0), - indent, - offset: indent.alignment, - } - } - - pub fn with_max_width(&self, config: &Config) -> Shape { - Shape { - width: config - .max_width() - .checked_sub(self.indent.width()) - .unwrap_or(0), - ..*self - } - } - - pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { - Shape { - width, - indent, - offset, - } - } - - pub fn visual_indent(&self, extra_width: usize) -> Shape { - let alignment = self.offset + extra_width; - Shape { - width: self.width, - indent: Indent::new(self.indent.block_indent, alignment), - offset: alignment, - } - } - - pub fn block_indent(&self, extra_width: usize) -> Shape { - if self.indent.alignment == 0 { - Shape { - width: self.width, - indent: Indent::new(self.indent.block_indent + extra_width, 0), - offset: 0, - } - } else { - Shape { - width: self.width, - indent: self.indent + extra_width, - offset: self.indent.alignment + extra_width, - } - } - } - - pub fn block_left(&self, width: usize) -> Option { - self.block_indent(width).sub_width(width) - } - - pub fn add_offset(&self, extra_width: usize) -> Shape { - Shape { - offset: self.offset + extra_width, - ..*self - } - } - - pub fn block(&self) -> Shape { - Shape { - indent: self.indent.block_only(), - ..*self - } - } - - pub fn sub_width(&self, width: usize) -> Option { - Some(Shape { - width: self.width.checked_sub(width)?, - ..*self - }) - } - - pub fn shrink_left(&self, width: usize) -> Option { - Some(Shape { - width: self.width.checked_sub(width)?, - indent: self.indent + width, - offset: self.offset + width, - }) - } - - pub fn offset_left(&self, width: usize) -> Option { - self.add_offset(width).sub_width(width) - } - - pub fn used_width(&self) -> usize { - self.indent.block_indent + self.offset - } - - pub fn rhs_overhead(&self, config: &Config) -> usize { - config - .max_width() - .checked_sub(self.used_width() + self.width) - .unwrap_or(0) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn indent_add_sub() { - let indent = Indent::new(4, 8) + Indent::new(8, 12); - assert_eq!(12, indent.block_indent); - assert_eq!(20, indent.alignment); - - let indent = indent - Indent::new(4, 4); - assert_eq!(8, indent.block_indent); - assert_eq!(16, indent.alignment); - } - - #[test] - fn indent_add_sub_alignment() { - let indent = Indent::new(4, 8) + 4; - assert_eq!(4, indent.block_indent); - assert_eq!(12, indent.alignment); - - let indent = indent - 4; - assert_eq!(4, indent.block_indent); - assert_eq!(8, indent.alignment); - } - - #[test] - fn indent_to_string_spaces() { - let config = Config::default(); - let indent = Indent::new(4, 8); - - // 12 spaces - assert_eq!(" ", indent.to_string(&config)); - } - - #[test] - fn indent_to_string_hard_tabs() { - let mut config = Config::default(); - config.set().hard_tabs(true); - let indent = Indent::new(8, 4); - - // 2 tabs + 4 spaces - assert_eq!("\t\t ", indent.to_string(&config)); - } - - #[test] - fn shape_visual_indent() { - let config = Config::default(); - let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.visual_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(4, shape.indent.block_indent); - assert_eq!(28, shape.indent.alignment); - assert_eq!(28, shape.offset); - } - - #[test] - fn shape_block_indent_without_alignment() { - let config = Config::default(); - let indent = Indent::new(4, 0); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.block_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(24, shape.indent.block_indent); - assert_eq!(0, shape.indent.alignment); - assert_eq!(0, shape.offset); - } - - #[test] - fn shape_block_indent_with_alignment() { - let config = Config::default(); - let indent = Indent::new(4, 8); - let shape = Shape::legacy(config.max_width(), indent); - let shape = shape.block_indent(20); - - assert_eq!(config.max_width(), shape.width); - assert_eq!(4, shape.indent.block_indent); - assert_eq!(28, shape.indent.alignment); - assert_eq!(28, shape.offset); - } -} diff --git a/rustfmt-core/src/spanned.rs b/rustfmt-core/src/spanned.rs deleted file mode 100644 index 20dd8438798..00000000000 --- a/rustfmt-core/src/spanned.rs +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::ast; -use syntax::codemap::Span; - -use macros::MacroArg; -use utils::{mk_sp, outer_attributes}; - -/// Spanned returns a span including attributes, if available. -pub trait Spanned { - fn span(&self) -> Span; -} - -macro_rules! span_with_attrs_lo_hi { - ($this: ident, $lo: expr, $hi: expr) => {{ - let attrs = outer_attributes(&$this.attrs); - if attrs.is_empty() { - mk_sp($lo, $hi) - } else { - mk_sp(attrs[0].span.lo(), $hi) - } - }}; -} - -macro_rules! span_with_attrs { - ($this: ident) => { - span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) - }; -} - -macro_rules! implement_spanned { - ($this: ty) => { - impl Spanned for $this { - fn span(&self) -> Span { - span_with_attrs!(self) - } - } - }; -} - -// Implement `Spanned` for structs with `attrs` field. -implement_spanned!(ast::Expr); -implement_spanned!(ast::Field); -implement_spanned!(ast::ForeignItem); -implement_spanned!(ast::Item); -implement_spanned!(ast::Local); -implement_spanned!(ast::TraitItem); -implement_spanned!(ast::ImplItem); - -impl Spanned for ast::Stmt { - fn span(&self) -> Span { - match self.node { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), - ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { - mk_sp(expr.span().lo(), self.span.hi()) - } - ast::StmtKind::Mac(ref mac) => { - let (_, _, ref attrs) = **mac; - if attrs.is_empty() { - self.span - } else { - mk_sp(attrs[0].span.lo(), self.span.hi()) - } - } - } - } -} - -impl Spanned for ast::Pat { - fn span(&self) -> Span { - self.span - } -} - -impl Spanned for ast::Ty { - fn span(&self) -> Span { - self.span - } -} - -impl Spanned for ast::Arm { - fn span(&self) -> Span { - let lo = if let Some(sp) = self.beginning_vert { - sp.lo() - } else { - self.pats[0].span.lo() - }; - span_with_attrs_lo_hi!(self, lo, self.body.span.hi()) - } -} - -impl Spanned for ast::Arg { - fn span(&self) -> Span { - if ::items::is_named_arg(self) { - mk_sp(self.pat.span.lo(), self.ty.span.hi()) - } else { - self.ty.span - } - } -} - -impl Spanned for ast::GenericParam { - fn span(&self) -> Span { - match *self { - ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(), - ast::GenericParam::Type(ref ty) => ty.span(), - } - } -} - -impl Spanned for ast::StructField { - fn span(&self) -> Span { - span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) - } -} - -impl Spanned for ast::WherePredicate { - fn span(&self) -> Span { - match *self { - ast::WherePredicate::BoundPredicate(ref p) => p.span, - ast::WherePredicate::RegionPredicate(ref p) => p.span, - ast::WherePredicate::EqPredicate(ref p) => p.span, - } - } -} - -impl Spanned for ast::FunctionRetTy { - fn span(&self) -> Span { - match *self { - ast::FunctionRetTy::Default(span) => span, - ast::FunctionRetTy::Ty(ref ty) => ty.span, - } - } -} - -impl Spanned for ast::TyParam { - fn span(&self) -> Span { - // Note that ty.span is the span for ty.ident, not the whole item. - let lo = if self.attrs.is_empty() { - self.span.lo() - } else { - self.attrs[0].span.lo() - }; - if let Some(ref def) = self.default { - return mk_sp(lo, def.span.hi()); - } - if self.bounds.is_empty() { - return mk_sp(lo, self.span.hi()); - } - let hi = self.bounds[self.bounds.len() - 1].span().hi(); - mk_sp(lo, hi) - } -} - -impl Spanned for ast::TyParamBound { - fn span(&self) -> Span { - match *self { - ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, - ast::TyParamBound::RegionTyParamBound(ref l) => l.span, - } - } -} - -impl Spanned for ast::LifetimeDef { - fn span(&self) -> Span { - let hi = if self.bounds.is_empty() { - self.lifetime.span.hi() - } else { - self.bounds[self.bounds.len() - 1].span.hi() - }; - mk_sp(self.lifetime.span.lo(), hi) - } -} - -impl Spanned for MacroArg { - fn span(&self) -> Span { - match *self { - MacroArg::Expr(ref expr) => expr.span(), - MacroArg::Ty(ref ty) => ty.span(), - MacroArg::Pat(ref pat) => pat.span(), - } - } -} diff --git a/rustfmt-core/src/string.rs b/rustfmt-core/src/string.rs deleted file mode 100644 index 8a6b0e685c4..00000000000 --- a/rustfmt-core/src/string.rs +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Format string literals. - -use regex::Regex; -use unicode_segmentation::UnicodeSegmentation; - -use config::Config; -use shape::Shape; -use utils::wrap_str; - -const MIN_STRING: usize = 10; - -pub struct StringFormat<'a> { - pub opener: &'a str, - pub closer: &'a str, - pub line_start: &'a str, - pub line_end: &'a str, - pub shape: Shape, - pub trim_end: bool, - pub config: &'a Config, -} - -impl<'a> StringFormat<'a> { - pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { - StringFormat { - opener: "\"", - closer: "\"", - line_start: " ", - line_end: "\\", - shape, - trim_end: false, - config, - } - } -} - -// FIXME: simplify this! -pub fn rewrite_string<'a>( - orig: &str, - fmt: &StringFormat<'a>, - max_width: Option, -) -> Option { - // Strip line breaks. - let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); - let stripped_str = re.replace_all(orig, "$1"); - - let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let shape = fmt.shape; - let indent = shape.indent.to_string_with_newline(fmt.config); - let punctuation = ":,;."; - - // `cur_start` is the position in `orig` of the start of the current line. - let mut cur_start = 0; - let mut result = String::with_capacity( - stripped_str - .len() - .checked_next_power_of_two() - .unwrap_or(usize::max_value()), - ); - result.push_str(fmt.opener); - - let ender_length = fmt.line_end.len(); - // If we cannot put at least a single character per line, the rewrite won't - // succeed. - let mut max_chars = shape - .width - .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; - - // Snip a line at a time from `orig` until it is used up. Push the snippet - // onto result. - 'outer: loop { - // `cur_end` will be where we break the line, as an offset into `orig`. - // Initialised to the maximum it could be (which may be beyond `orig`). - let mut cur_end = cur_start + max_chars; - - // We can fit the rest of the string on this line, so we're done. - if cur_end >= graphemes.len() { - let line = &graphemes[cur_start..].join(""); - result.push_str(line); - break 'outer; - } - - // Push cur_end left until we reach whitespace (or the line is too small). - while !graphemes[cur_end - 1].trim().is_empty() { - cur_end -= 1; - if cur_end < cur_start + MIN_STRING { - // We couldn't find whitespace before the string got too small. - // So start again at the max length and look for punctuation. - cur_end = cur_start + max_chars; - while !punctuation.contains(graphemes[cur_end - 1]) { - cur_end -= 1; - - // If we can't break at whitespace or punctuation, grow the string instead. - if cur_end < cur_start + MIN_STRING { - cur_end = cur_start + max_chars; - while !(punctuation.contains(graphemes[cur_end - 1]) - || graphemes[cur_end - 1].trim().is_empty()) - { - if cur_end >= graphemes.len() { - let line = &graphemes[cur_start..].join(""); - result.push_str(line); - break 'outer; - } - cur_end += 1; - } - break; - } - } - break; - } - } - // Make sure there is no whitespace to the right of the break. - while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { - cur_end += 1; - } - - // Make the current line and add it on to result. - let raw_line = graphemes[cur_start..cur_end].join(""); - let line = if fmt.trim_end { - raw_line.trim() - } else { - raw_line.as_str() - }; - - result.push_str(line); - result.push_str(fmt.line_end); - result.push_str(&indent); - result.push_str(fmt.line_start); - - // The next line starts where the current line ends. - cur_start = cur_end; - - if let Some(new_max_chars) = max_width { - max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; - } - } - - result.push_str(fmt.closer); - wrap_str(result, fmt.config.max_width(), fmt.shape) -} - -#[cfg(test)] -mod test { - use super::{rewrite_string, StringFormat}; - use shape::{Indent, Shape}; - - #[test] - fn issue343() { - let config = Default::default(); - let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); - rewrite_string("eq_", &fmt, None); - } -} diff --git a/rustfmt-core/src/types.rs b/rustfmt-core/src/types.rs deleted file mode 100644 index 7f96a2299a3..00000000000 --- a/rustfmt-core/src/types.rs +++ /dev/null @@ -1,820 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::iter::ExactSizeIterator; -use std::ops::Deref; - -use config::lists::*; -use syntax::ast::{self, FunctionRetTy, Mutability}; -use syntax::codemap::{self, BytePos, Span}; -use syntax::symbol::keywords; - -use codemap::SpanUtils; -use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; -use items::{format_generics_item_list, generics_shape_from_config}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use macros::{rewrite_macro, MacroPosition}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use spanned::Spanned; -use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, - last_line_width, mk_sp}; - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum PathContext { - Expr, - Type, - Import, -} - -// Does not wrap on simple segments. -pub fn rewrite_path( - context: &RewriteContext, - path_context: PathContext, - qself: Option<&ast::QSelf>, - path: &ast::Path, - shape: Shape, -) -> Option { - let skip_count = qself.map_or(0, |x| x.position); - - let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import { - "::".to_owned() - } else { - String::new() - }; - - let mut span_lo = path.span.lo(); - - if let Some(qself) = qself { - result.push('<'); - if context.config.spaces_within_parens_and_brackets() { - result.push_str(" ") - } - - let fmt_ty = qself.ty.rewrite(context, shape)?; - result.push_str(&fmt_ty); - - if skip_count > 0 { - result.push_str(" as "); - if path.is_global() && path_context != PathContext::Import { - result.push_str("::"); - } - - // 3 = ">::".len() - let shape = shape.sub_width(3)?; - - result = rewrite_path_segments( - PathContext::Type, - result, - path.segments.iter().take(skip_count), - span_lo, - path.span.hi(), - context, - shape, - )?; - } - - if context.config.spaces_within_parens_and_brackets() { - result.push_str(" ") - } - - result.push_str(">::"); - span_lo = qself.ty.span.hi() + BytePos(1); - } - - rewrite_path_segments( - path_context, - result, - path.segments.iter().skip(skip_count), - span_lo, - path.span.hi(), - context, - shape, - ) -} - -fn rewrite_path_segments<'a, I>( - path_context: PathContext, - mut buffer: String, - iter: I, - mut span_lo: BytePos, - span_hi: BytePos, - context: &RewriteContext, - shape: Shape, -) -> Option -where - I: Iterator, -{ - let mut first = true; - let shape = shape.visual_indent(0); - - for segment in iter { - // Indicates a global path, shouldn't be rendered. - if segment.identifier.name == keywords::CrateRoot.name() { - continue; - } - if first { - first = false; - } else { - buffer.push_str("::"); - } - - let extra_offset = extra_offset(&buffer, shape); - let new_shape = shape.shrink_left(extra_offset)?; - let segment_string = rewrite_segment( - path_context, - segment, - &mut span_lo, - span_hi, - context, - new_shape, - )?; - - buffer.push_str(&segment_string); - } - - Some(buffer) -} - -#[derive(Debug)] -enum SegmentParam<'a> { - LifeTime(&'a ast::Lifetime), - Type(&'a ast::Ty), - Binding(&'a ast::TypeBinding), -} - -impl<'a> SegmentParam<'a> { - fn get_span(&self) -> Span { - match *self { - SegmentParam::LifeTime(lt) => lt.span, - SegmentParam::Type(ty) => ty.span, - SegmentParam::Binding(binding) => binding.span, - } - } -} - -impl<'a> Rewrite for SegmentParam<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), - SegmentParam::Type(ty) => ty.rewrite(context, shape), - SegmentParam::Binding(binding) => { - let mut result = match context.config.type_punctuation_density() { - TypeDensity::Wide => format!("{} = ", binding.ident), - TypeDensity::Compressed => format!("{}=", binding.ident), - }; - let budget = shape.width.checked_sub(result.len())?; - let rewrite = binding - .ty - .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); - Some(result) - } - } - } -} - -// Formats a path segment. There are some hacks involved to correctly determine -// the segment's associated span since it's not part of the AST. -// -// The span_lo is assumed to be greater than the end of any previous segment's -// parameters and lesser or equal than the start of current segment. -// -// span_hi is assumed equal to the end of the entire path. -// -// When the segment contains a positive number of parameters, we update span_lo -// so that invariants described above will hold for the next segment. -fn rewrite_segment( - path_context: PathContext, - segment: &ast::PathSegment, - span_lo: &mut BytePos, - span_hi: BytePos, - context: &RewriteContext, - shape: Shape, -) -> Option { - let mut result = String::with_capacity(128); - result.push_str(&segment.identifier.name.as_str()); - - let ident_len = result.len(); - let shape = shape.shrink_left(ident_len)?; - - if let Some(ref params) = segment.parameters { - match **params { - ast::PathParameters::AngleBracketed(ref data) - if !data.lifetimes.is_empty() || !data.types.is_empty() - || !data.bindings.is_empty() => - { - let param_list = data.lifetimes - .iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) - .collect::>(); - - let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1); - let list_lo = context - .snippet_provider - .span_after(mk_sp(*span_lo, span_hi), "<"); - let separator = if path_context == PathContext::Expr { - "::" - } else { - "" - }; - result.push_str(separator); - - let generics_shape = - generics_shape_from_config(context.config, shape, separator.len())?; - let one_line_width = shape.width.checked_sub(separator.len() + 2)?; - let items = itemize_list( - context.snippet_provider, - param_list.into_iter(), - ">", - ",", - |param| param.get_span().lo(), - |param| param.get_span().hi(), - |seg| seg.rewrite(context, generics_shape), - list_lo, - span_hi, - false, - ); - let generics_str = - format_generics_item_list(context, items, generics_shape, one_line_width)?; - - // Update position of last bracket. - *span_lo = next_span_lo; - - result.push_str(&generics_str) - } - ast::PathParameters::Parenthesized(ref data) => { - let output = match data.output { - Some(ref ty) => FunctionRetTy::Ty(ty.clone()), - None => FunctionRetTy::Default(codemap::DUMMY_SP), - }; - result.push_str(&format_function_type( - data.inputs.iter().map(|x| &**x), - &output, - false, - data.span, - context, - shape, - )?); - } - _ => (), - } - } - - Some(result) -} - -fn format_function_type<'a, I>( - inputs: I, - output: &FunctionRetTy, - variadic: bool, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option -where - I: ExactSizeIterator, - ::Item: Deref, - ::Target: Rewrite + Spanned + 'a, -{ - // Code for handling variadics is somewhat duplicated for items, but they - // are different enough to need some serious refactoring to share code. - enum ArgumentKind - where - T: Deref, - ::Target: Rewrite + Spanned, - { - Regular(Box), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_start = context.snippet_provider.span_before(span, "..."); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - - // 2 for () - let budget = shape.width.checked_sub(2)?; - // 1 for ( - let offset = match context.config.indent_style() { - IndentStyle::Block => { - shape - .block() - .block_indent(context.config.tab_spaces()) - .indent - } - IndentStyle::Visual => shape.indent + 1, - }; - let list_shape = Shape::legacy(budget, offset); - let list_lo = context.snippet_provider.span_after(span, "("); - let items = itemize_list( - context.snippet_provider, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs - .map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), - ")", - ",", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo(), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi(), - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, - list_lo, - span.hi(), - false, - ); - - let item_vec: Vec<_> = items.collect(); - - let tactic = definitive_tactic( - &*item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - budget, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if !context.use_block_indent() || variadic { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape: list_shape, - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - let list_str = write_list(&item_vec, &fmt)?; - - let ty_shape = match context.config.indent_style() { - // 4 = " -> " - IndentStyle::Block => shape.offset_left(4)?, - IndentStyle::Visual => shape.block_left(4)?, - }; - let output = match *output { - FunctionRetTy::Ty(ref ty) => { - let type_str = ty.rewrite(context, ty_shape)?; - format!(" -> {}", type_str) - } - FunctionRetTy::Default(..) => String::new(), - }; - - let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n'); - let args = wrap_args_with_parens( - context, - &list_str, - extendable, - shape.sub_width(first_line_width(&output))?, - Shape::indented(offset, context.config), - ); - if last_line_width(&args) + first_line_width(&output) <= shape.width { - Some(format!("{}{}", args, output)) - } else { - Some(format!( - "{}\n{}{}", - args, - offset.to_string(context.config), - output.trim_left() - )) - } -} - -fn type_bound_colon(context: &RewriteContext) -> &'static str { - colon_spaces( - context.config.space_before_colon(), - context.config.space_after_colon(), - ) -} - -impl Rewrite for ast::WherePredicate { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - // TODO: dead spans? - let result = match *self { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_generic_params, - ref bounded_ty, - ref bounds, - .. - }) => { - let type_str = bounded_ty.rewrite(context, shape)?; - - let colon = type_bound_colon(context); - - if let Some(lifetime_str) = - rewrite_lifetime_param(context, shape, bound_generic_params) - { - // 6 = "for<> ".len() - let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let ty_shape = shape.offset_left(used_width)?; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let bounds_str = join_bounds(context, ty_shape, &bounds); - - if context.config.spaces_within_parens_and_brackets() - && !lifetime_str.is_empty() - { - format!( - "for< {} > {}{}{}", - lifetime_str, type_str, colon, bounds_str - ) - } else { - format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) - } - } else { - let used_width = type_str.len() + colon.len(); - let ty_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.block_left(used_width)?, - IndentStyle::Block => shape, - }; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let overhead = type_str.len() + colon.len(); - let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); - - format!("{}{}{}", type_str, colon, bounds_str) - } - } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - ref lifetime, - ref bounds, - .. - }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - let lhs_ty_str = lhs_ty.rewrite(context, shape)?; - // 3 = " = ".len() - let used_width = 3 + lhs_ty_str.len(); - let budget = shape.width.checked_sub(used_width)?; - let rhs_ty_str = - rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; - format!("{} = {}", lhs_ty_str, rhs_ty_str) - } - }; - - Some(result) - } -} - -impl Rewrite for ast::LifetimeDef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) - } -} - -fn rewrite_bounded_lifetime<'b, I>( - lt: &ast::Lifetime, - bounds: I, - context: &RewriteContext, - shape: Shape, -) -> Option -where - I: ExactSizeIterator, -{ - let result = lt.rewrite(context, shape)?; - - if bounds.len() == 0 { - Some(result) - } else { - let appendix = bounds - .into_iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - let colon = type_bound_colon(context); - let overhead = last_line_width(&result) + colon.len(); - let result = format!( - "{}{}{}", - result, - colon, - join_bounds(context, shape.sub_width(overhead)?, &appendix) - ); - Some(result) - } -} - -impl Rewrite for ast::TyParamBound { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { - tref.rewrite(context, shape) - } - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => Some( - format!("?{}", tref.rewrite(context, shape.offset_left(1)?)?), - ), - ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), - } - } -} - -impl Rewrite for ast::Lifetime { - fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { - Some(self.ident.to_string()) - } -} - -impl Rewrite for ast::TyParamBounds { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs = self.iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - Some(join_bounds(context, shape, &strs)) - } -} - -impl Rewrite for ast::TyParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let mut result = String::with_capacity(128); - // FIXME: If there are more than one attributes, this will force multiline. - match self.attrs.rewrite(context, shape) { - Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), - _ => (), - } - result.push_str(&self.ident.to_string()); - if !self.bounds.is_empty() { - result.push_str(type_bound_colon(context)); - let strs = self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - result.push_str(&join_bounds(context, shape, &strs)); - } - if let Some(ref def) = self.default { - let eq_str = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "=", - TypeDensity::Wide => " = ", - }; - result.push_str(eq_str); - let budget = shape.width.checked_sub(result.len())?; - let rewrite = def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; - result.push_str(&rewrite); - } - - Some(result) - } -} - -impl Rewrite for ast::PolyTraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - if let Some(lifetime_str) = - rewrite_lifetime_param(context, shape, &self.bound_generic_params) - { - // 6 is "for<> ".len() - let extra_offset = lifetime_str.len() + 6; - let path_str = self.trait_ref - .rewrite(context, shape.offset_left(extra_offset)?)?; - - Some( - if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }, - ) - } else { - self.trait_ref.rewrite(context, shape) - } - } -} - -impl Rewrite for ast::TraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_path(context, PathContext::Type, None, &self.path, shape) - } -} - -impl Rewrite for ast::Ty { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.node { - ast::TyKind::TraitObject(ref bounds, ..) => bounds.rewrite(context, shape), - ast::TyKind::Ptr(ref mt) => { - let prefix = match mt.mutbl { - Mutability::Mutable => "*mut ", - Mutability::Immutable => "*const ", - }; - - rewrite_unary_prefix(context, prefix, &*mt.ty, shape) - } - ast::TyKind::Rptr(ref lifetime, ref mt) => { - let mut_str = format_mutability(mt.mutbl); - let mut_len = mut_str.len(); - Some(match *lifetime { - Some(ref lifetime) => { - let lt_budget = shape.width.checked_sub(2 + mut_len)?; - let lt_str = lifetime.rewrite( - context, - Shape::legacy(lt_budget, shape.indent + 2 + mut_len), - )?; - let lt_len = lt_str.len(); - let budget = shape.width.checked_sub(2 + mut_len + lt_len)?; - format!( - "&{} {}{}", - lt_str, - mut_str, - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len) - )? - ) - } - None => { - let budget = shape.width.checked_sub(1 + mut_len)?; - format!( - "&{}{}", - mut_str, - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 1 + mut_len) - )? - ) - } - }) - } - // FIXME: we drop any comments here, even though it's a silly place to put - // comments. - ast::TyKind::Paren(ref ty) => { - let budget = shape.width.checked_sub(2)?; - ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| { - if context.config.spaces_within_parens_and_brackets() { - format!("( {} )", ty_str) - } else { - format!("({})", ty_str) - } - }) - } - ast::TyKind::Slice(ref ty) => { - let budget = if context.config.spaces_within_parens_and_brackets() { - shape.width.checked_sub(4)? - } else { - shape.width.checked_sub(2)? - }; - ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| { - if context.config.spaces_within_parens_and_brackets() { - format!("[ {} ]", ty_str) - } else { - format!("[{}]", ty_str) - } - }) - } - ast::TyKind::Tup(ref items) => rewrite_tuple( - context, - &::utils::ptr_vec_to_ref_vec(items), - self.span, - shape, - ), - ast::TyKind::Path(ref q_self, ref path) => { - rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) - } - ast::TyKind::Array(ref ty, ref repeats) => { - let use_spaces = context.config.spaces_within_parens_and_brackets(); - let lbr = if use_spaces { "[ " } else { "[" }; - let rbr = if use_spaces { " ]" } else { "]" }; - rewrite_pair( - &**ty, - &**repeats, - PairParts::new(lbr, "; ", rbr), - context, - shape, - SeparatorPlace::Back, - ) - } - ast::TyKind::Infer => { - if shape.width >= 1 { - Some("_".to_owned()) - } else { - None - } - } - ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), - ast::TyKind::Never => Some(String::from("!")), - ast::TyKind::Mac(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - } - ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) - .map(|it_str| format!("impl {}", it_str)), - ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), - } - } -} - -fn rewrite_bare_fn( - bare_fn: &ast::BareFnTy, - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let mut result = String::with_capacity(128); - - if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params) - { - result.push_str("for<"); - // 6 = "for<> ".len(), 4 = "for<". - // This doesn't work out so nicely for mutliline situation with lots of - // rightward drift. If that is a problem, we could use the list stuff. - result.push_str(lifetime_str); - result.push_str("> "); - } - - result.push_str(::utils::format_unsafety(bare_fn.unsafety)); - - result.push_str(&format_abi( - bare_fn.abi, - context.config.force_explicit_abi(), - false, - )); - - result.push_str("fn"); - - let func_ty_shape = shape.offset_left(result.len())?; - - let rewrite = format_function_type( - bare_fn.decl.inputs.iter(), - &bare_fn.decl.output, - bare_fn.decl.variadic, - span, - context, - func_ty_shape, - )?; - - result.push_str(&rewrite); - - Some(result) -} - -pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { - // Try to join types in a single line - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let result = type_strs.join(joiner); - if result.contains('\n') || result.len() > shape.width { - let joiner_indent = shape.indent.block_indent(context.config); - let joiner = format!("{}+ ", joiner_indent.to_string_with_newline(context.config)); - type_strs.join(&joiner) - } else { - result - } -} - -pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { - match ty.node { - ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { - can_be_overflowed_type(context, &*mutty.ty, len) - } - _ => false, - } -} - -/// Returns `None` if there is no `LifetimeDef` in the given generic parameters. -fn rewrite_lifetime_param( - context: &RewriteContext, - shape: Shape, - generic_params: &[ast::GenericParam], -) -> Option { - let result = generic_params - .iter() - .filter(|p| p.is_lifetime_param()) - .map(|lt| lt.rewrite(context, shape)) - .collect::>>()? - .join(", "); - if result.is_empty() { - None - } else { - Some(result) - } -} diff --git a/rustfmt-core/src/utils.rs b/rustfmt-core/src/utils.rs deleted file mode 100644 index 20b30089d70..00000000000 --- a/rustfmt-core/src/utils.rs +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::borrow::Cow; - -use syntax::{abi, ptr}; -use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, - NestedMetaItemKind, Path, Visibility}; -use syntax::codemap::{BytePos, Span, NO_EXPANSION}; - -use config::Color; -use rewrite::RewriteContext; -use shape::Shape; - -// When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &str = "rustfmt_skip"; - -// Computes the length of a string's last line, minus offset. -pub fn extra_offset(text: &str, shape: Shape) -> usize { - match text.rfind('\n') { - // 1 for newline character - Some(idx) => text.len() - .checked_sub(idx + 1 + shape.used_width()) - .unwrap_or(0), - None => text.len(), - } -} - -// Uses Cow to avoid allocating in the common cases. -pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { - match *vis { - Visibility::Public => Cow::from("pub "), - Visibility::Inherited => Cow::from(""), - Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "), - Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "), - Visibility::Restricted { ref path, .. } => { - let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); - if path.is_global() { - segments_iter - .next() - .expect("Non-global path in pub(restricted)?"); - } - let is_keyword = |s: &str| s == "self" || s == "super"; - let path = segments_iter.collect::>().join("::"); - let in_str = if is_keyword(&path) { "" } else { "in " }; - - Cow::from(format!("pub({}{}) ", in_str, path)) - } - } -} - -#[inline] -pub fn format_constness(constness: ast::Constness) -> &'static str { - match constness { - ast::Constness::Const => "const ", - ast::Constness::NotConst => "", - } -} - -#[inline] -pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { - match defaultness { - ast::Defaultness::Default => "default ", - ast::Defaultness::Final => "", - } -} - -#[inline] -pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { - match unsafety { - ast::Unsafety::Unsafe => "unsafe ", - ast::Unsafety::Normal => "", - } -} - -#[inline] -pub fn format_mutability(mutability: ast::Mutability) -> &'static str { - match mutability { - ast::Mutability::Mutable => "mut ", - ast::Mutability::Immutable => "", - } -} - -#[inline] -pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { - if abi == abi::Abi::Rust && !is_mod { - Cow::from("") - } else if abi == abi::Abi::C && !explicit_abi { - Cow::from("extern ") - } else { - Cow::from(format!("extern {} ", abi)) - } -} - -#[inline] -// Transform `Vec>` into `Vec<&T>` -pub fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { - vec.iter().map(|x| &**x).collect::>() -} - -#[inline] -pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { - attrs - .iter() - .filter(|a| a.style == style) - .cloned() - .collect::>() -} - -#[inline] -pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { - filter_attributes(attrs, ast::AttrStyle::Inner) -} - -#[inline] -pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { - filter_attributes(attrs, ast::AttrStyle::Outer) -} - -#[inline] -pub fn last_line_contains_single_line_comment(s: &str) -> bool { - s.lines().last().map_or(false, |l| l.contains("//")) -} - -#[inline] -pub fn is_attributes_extendable(attrs_str: &str) -> bool { - !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) -} - -// The width of the first line in s. -#[inline] -pub fn first_line_width(s: &str) -> usize { - match s.find('\n') { - Some(n) => n, - None => s.len(), - } -} - -// The width of the last line in s. -#[inline] -pub fn last_line_width(s: &str) -> usize { - match s.rfind('\n') { - Some(n) => s.len() - n - 1, - None => s.len(), - } -} - -// The total used width of the last line. -#[inline] -pub fn last_line_used_width(s: &str, offset: usize) -> usize { - if s.contains('\n') { - last_line_width(s) - } else { - offset + s.len() - } -} - -#[inline] -pub fn trimmed_last_line_width(s: &str) -> usize { - match s.rfind('\n') { - Some(n) => s[(n + 1)..].trim().len(), - None => s.trim().len(), - } -} - -#[inline] -pub fn last_line_extendable(s: &str) -> bool { - if s.ends_with("\"#") { - return true; - } - for c in s.chars().rev() { - match c { - '(' | ')' | ']' | '}' | '?' | '>' => continue, - '\n' => break, - _ if c.is_whitespace() => continue, - _ => return false, - } - } - true -} - -#[inline] -fn is_skip(meta_item: &MetaItem) -> bool { - match meta_item.node { - MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION, - MetaItemKind::List(ref l) => { - meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) - } - _ => false, - } -} - -#[inline] -fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { - match meta_item.node { - NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi), - NestedMetaItemKind::Literal(_) => false, - } -} - -#[inline] -pub fn contains_skip(attrs: &[Attribute]) -> bool { - attrs - .iter() - .any(|a| a.meta().map_or(false, |a| is_skip(&a))) -} - -#[inline] -pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { - context.config.trailing_semicolon() - } - _ => false, - } -} - -#[inline] -pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::StmtKind::Semi(ref expr) => match expr.node { - ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) => false, - ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { - context.config.trailing_semicolon() - } - _ => true, - }, - ast::StmtKind::Expr(..) => false, - _ => true, - } -} - -#[inline] -pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { - match stmt.node { - ast::StmtKind::Expr(ref expr) => Some(expr), - _ => None, - } -} - -#[inline] -pub fn count_newlines(input: &str) -> usize { - input.chars().filter(|&c| c == '\n').count() -} - -macro_rules! msg { - ($($arg:tt)*) => ( - match writeln!(&mut ::std::io::stderr(), $($arg)* ) { - Ok(_) => {}, - Err(x) => panic!("Unable to write to stderr: {}", x), - } - ) -} - -// For format_missing and last_pos, need to use the source callsite (if applicable). -// Required as generated code spans aren't guaranteed to follow on from the last span. -macro_rules! source { - ($this: ident, $sp: expr) => { - $sp.source_callsite() - }; -} - -pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { - Span::new(lo, hi, NO_EXPANSION) -} - -// Return true if the given span does not intersect with file lines. -macro_rules! out_of_file_lines_range { - ($self: ident, $span: expr) => { - !$self.config.file_lines().is_all() - && !$self - .config - .file_lines() - .intersects(&$self.codemap.lookup_line_range($span)) - }; -} - -macro_rules! skip_out_of_file_lines_range { - ($self: ident, $span: expr) => { - if out_of_file_lines_range!($self, $span) { - return None; - } - }; -} - -macro_rules! skip_out_of_file_lines_range_visitor { - ($self: ident, $span: expr) => { - if out_of_file_lines_range!($self, $span) { - $self.push_rewrite($span, None); - return; - } - }; -} - -// Wraps String in an Option. Returns Some when the string adheres to the -// Rewrite constraints defined for the Rewrite trait and else otherwise. -pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { - if is_valid_str(&s, max_width, shape) { - Some(s) - } else { - None - } -} - -fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { - if !snippet.is_empty() { - // First line must fits with `shape.width`. - if first_line_width(snippet) > shape.width { - return false; - } - // If the snippet does not include newline, we are done. - if first_line_width(snippet) == snippet.len() { - return true; - } - // The other lines must fit within the maximum width. - if snippet.lines().skip(1).any(|line| line.len() > max_width) { - return false; - } - // A special check for the last line, since the caller may - // place trailing characters on this line. - if last_line_width(snippet) > shape.used_width() + shape.width { - return false; - } - } - true -} - -#[inline] -pub fn colon_spaces(before: bool, after: bool) -> &'static str { - match (before, after) { - (true, true) => " : ", - (true, false) => " :", - (false, true) => ": ", - (false, false) => ":", - } -} - -#[inline] -pub fn paren_overhead(context: &RewriteContext) -> usize { - if context.config.spaces_within_parens_and_brackets() { - 4 - } else { - 2 - } -} - -pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { - match e.node { - ast::ExprKind::InPlace(ref e, _) - | ast::ExprKind::Call(ref e, _) - | ast::ExprKind::Binary(_, ref e, _) - | ast::ExprKind::Cast(ref e, _) - | ast::ExprKind::Type(ref e, _) - | ast::ExprKind::Assign(ref e, _) - | ast::ExprKind::AssignOp(_, ref e, _) - | ast::ExprKind::Field(ref e, _) - | ast::ExprKind::TupField(ref e, _) - | ast::ExprKind::Index(ref e, _) - | ast::ExprKind::Range(Some(ref e), _, _) - | ast::ExprKind::Try(ref e) => left_most_sub_expr(e), - _ => e, - } -} - -// isatty shamelessly adapted from cargo. -#[cfg(unix)] -pub fn isatty() -> bool { - extern crate libc; - - unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } -} -#[cfg(windows)] -pub fn isatty() -> bool { - extern crate kernel32; - extern crate winapi; - - unsafe { - let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); - let mut out = 0; - kernel32::GetConsoleMode(handle, &mut out) != 0 - } -} - -pub fn use_colored_tty(color: Color) -> bool { - match color { - Color::Always => true, - Color::Never => false, - Color::Auto => isatty(), - } -} - -pub fn starts_with_newline(s: &str) -> bool { - s.starts_with('\n') || s.starts_with("\r\n") -} diff --git a/rustfmt-core/src/vertical.rs b/rustfmt-core/src/vertical.rs deleted file mode 100644 index 887fefb2272..00000000000 --- a/rustfmt-core/src/vertical.rs +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Format with vertical alignment. - -use std::cmp; - -use config::lists::*; -use syntax::ast; -use syntax::codemap::{BytePos, Span}; - -use codemap::SpanUtils; -use comment::{combine_strs_with_missing_comments, contains_comment}; -use expr::rewrite_field; -use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use utils::{contains_skip, is_attributes_extendable, mk_sp}; - -pub trait AlignedItem { - fn skip(&self) -> bool; - fn get_span(&self) -> Span; - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option; - fn rewrite_aligned_item( - &self, - context: &RewriteContext, - shape: Shape, - prefix_max_width: usize, - ) -> Option; -} - -impl AlignedItem for ast::StructField { - fn skip(&self) -> bool { - contains_skip(&self.attrs) - } - - fn get_span(&self) -> Span { - self.span() - } - - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; - let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo(), self.span.lo()) - } else { - mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) - }; - let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str); - rewrite_struct_field_prefix(context, self).and_then(|field_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &field_str, - missing_span, - shape, - attrs_extendable, - ) - }) - } - - fn rewrite_aligned_item( - &self, - context: &RewriteContext, - shape: Shape, - prefix_max_width: usize, - ) -> Option { - rewrite_struct_field(context, self, shape, prefix_max_width) - } -} - -impl AlignedItem for ast::Field { - fn skip(&self) -> bool { - contains_skip(&self.attrs) - } - - fn get_span(&self) -> Span { - self.span() - } - - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; - let name = &self.ident.node.to_string(); - let missing_span = if self.attrs.is_empty() { - mk_sp(self.span.lo(), self.span.lo()) - } else { - mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) - }; - combine_strs_with_missing_comments( - context, - &attrs_str, - name, - missing_span, - shape, - is_attributes_extendable(&attrs_str), - ) - } - - fn rewrite_aligned_item( - &self, - context: &RewriteContext, - shape: Shape, - prefix_max_width: usize, - ) -> Option { - rewrite_field(context, self, shape, prefix_max_width) - } -} - -pub fn rewrite_with_alignment( - fields: &[T], - context: &RewriteContext, - shape: Shape, - span: Span, - one_line_width: usize, -) -> Option { - let (spaces, group_index) = if context.config.struct_field_align_threshold() > 0 { - group_aligned_items(context, fields) - } else { - ("", fields.len() - 1) - }; - let init = &fields[0..group_index + 1]; - let rest = &fields[group_index + 1..]; - let init_last_pos = if rest.is_empty() { - span.hi() - } else { - // Decide whether the missing comments should stick to init or rest. - let init_hi = init[init.len() - 1].get_span().hi(); - let rest_lo = rest[0].get_span().lo(); - let missing_span = mk_sp(init_hi, rest_lo); - let missing_span = mk_sp( - context.snippet_provider.span_after(missing_span, ","), - missing_span.hi(), - ); - - let snippet = context.snippet(missing_span); - if snippet.trim_left().starts_with("//") { - let offset = snippet.lines().next().map_or(0, |l| l.len()); - // 2 = "," + "\n" - init_hi + BytePos(offset as u32 + 2) - } else if snippet.trim_left().starts_with("/*") { - let comment_lines = snippet - .lines() - .position(|line| line.trim_right().ends_with("*/")) - .unwrap_or(0); - - let offset = snippet - .lines() - .take(comment_lines + 1) - .collect::>() - .join("\n") - .len(); - - init_hi + BytePos(offset as u32 + 2) - } else { - missing_span.lo() - } - }; - let init_span = mk_sp(span.lo(), init_last_pos); - let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; - let result = - rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?; - if rest.is_empty() { - Some(result + spaces) - } else { - let rest_span = mk_sp(init_last_pos, span.hi()); - let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; - Some( - result + spaces + "\n" - + &shape - .indent - .block_indent(context.config) - .to_string(context.config) + &rest_str, - ) - } -} - -fn struct_field_prefix_max_min_width( - context: &RewriteContext, - fields: &[T], - shape: Shape, -) -> (usize, usize) { - fields - .iter() - .map(|field| { - field.rewrite_prefix(context, shape).and_then(|field_str| { - if field_str.contains('\n') { - None - } else { - Some(field_str.len()) - } - }) - }) - .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { - (Some((max_len, min_len)), Some(len)) => { - Some((cmp::max(max_len, len), cmp::min(min_len, len))) - } - _ => None, - }) - .unwrap_or((0, 0)) -} - -fn rewrite_aligned_items_inner( - context: &RewriteContext, - fields: &[T], - span: Span, - offset: Indent, - one_line_width: usize, -) -> Option { - let item_indent = offset.block_indent(context.config); - // 1 = "," - let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; - let (mut field_prefix_max_width, field_prefix_min_width) = - struct_field_prefix_max_min_width(context, fields, item_shape); - let max_diff = field_prefix_max_width - .checked_sub(field_prefix_min_width) - .unwrap_or(0); - if max_diff > context.config.struct_field_align_threshold() { - field_prefix_max_width = 0; - } - - let items = itemize_list( - context.snippet_provider, - fields.iter(), - "}", - ",", - |field| field.get_span().lo(), - |field| field.get_span().hi(), - |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), - span.lo(), - span.hi(), - false, - ).collect::>(); - - let tactic = definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::Comma, - one_line_width, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: context.config.trailing_comma(), - separator_place: SeparatorPlace::Back, - shape: item_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - write_list(&items, &fmt) -} - -fn group_aligned_items( - context: &RewriteContext, - fields: &[T], -) -> (&'static str, usize) { - let mut index = 0; - for i in 0..fields.len() - 1 { - if fields[i].skip() { - return ("", index); - } - // See if there are comments or empty lines between fields. - let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo()); - let snippet = context - .snippet(span) - .lines() - .skip(1) - .collect::>() - .join("\n"); - let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) { - "\n" - } else { - "" - }; - if contains_comment(&snippet) || snippet.lines().count() > 1 { - return (spacings, index); - } - index += 1; - } - ("", index) -} diff --git a/rustfmt-core/src/visitor.rs b/rustfmt-core/src/visitor.rs deleted file mode 100644 index 35102f58609..00000000000 --- a/rustfmt-core/src/visitor.rs +++ /dev/null @@ -1,700 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use syntax::{ast, visit}; -use syntax::attr::HasAttrs; -use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; -use syntax::parse::ParseSess; - -use attr::*; -use codemap::{LineRangeUtils, SpanUtils}; -use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; -use config::{BraceStyle, Config}; -use items::{format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, - rewrite_type_alias, FnSig, StaticParts, StructParts}; -use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use spanned::Spanned; -use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; - -/// Creates a string slice corresponding to the specified span. -pub struct SnippetProvider<'a> { - /// A pointer to the content of the file we are formatting. - big_snippet: &'a str, - /// A position of the start of `big_snippet`, used as an offset. - start_pos: usize, -} - -impl<'a> SnippetProvider<'a> { - pub fn span_to_snippet(&self, span: Span) -> Option<&str> { - let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; - let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; - Some(&self.big_snippet[start_index..end_index]) - } - - pub fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { - let start_pos = start_pos.to_usize(); - SnippetProvider { - big_snippet, - start_pos, - } - } -} - -pub struct FmtVisitor<'a> { - pub parse_session: &'a ParseSess, - pub codemap: &'a CodeMap, - pub buffer: String, - pub last_pos: BytePos, - // FIXME: use an RAII util or closure for indenting - pub block_indent: Indent, - pub config: &'a Config, - pub is_if_else_block: bool, - pub snippet_provider: &'a SnippetProvider<'a>, - pub line_number: usize, - pub skipped_range: Vec<(usize, usize)>, -} - -impl<'b, 'a: 'b> FmtVisitor<'a> { - pub fn shape(&self) -> Shape { - Shape::indented(self.block_indent, self.config) - } - - fn visit_stmt(&mut self, stmt: &ast::Stmt) { - debug!( - "visit_stmt: {:?} {:?}", - self.codemap.lookup_char_pos(stmt.span.lo()), - self.codemap.lookup_char_pos(stmt.span.hi()) - ); - - match stmt.node { - ast::StmtKind::Item(ref item) => { - self.visit_item(item); - } - ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - if contains_skip(get_attrs_from_stmt(stmt)) { - self.push_skipped_with_span(stmt.span()); - } else { - let rewrite = stmt.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(stmt.span(), rewrite) - } - } - ast::StmtKind::Mac(ref mac) => { - let (ref mac, _macro_style, ref attrs) = **mac; - if self.visit_attrs(attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(stmt.span()); - } else { - self.visit_mac(mac, None, MacroPosition::Statement); - } - self.format_missing(stmt.span.hi()); - } - } - } - - pub fn visit_block( - &mut self, - b: &ast::Block, - inner_attrs: Option<&[ast::Attribute]>, - has_braces: bool, - ) { - debug!( - "visit_block: {:?} {:?}", - self.codemap.lookup_char_pos(b.span.lo()), - self.codemap.lookup_char_pos(b.span.hi()) - ); - - // Check if this block has braces. - let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); - - self.last_pos = self.last_pos + brace_compensation; - self.block_indent = self.block_indent.block_indent(self.config); - self.push_str("{"); - - if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(first_stmt) = b.stmts.first() { - let attr_lo = inner_attrs - .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) - .or_else(|| { - // Attributes for an item in a statement position - // do not belong to the statement. (rust-lang/rust#34459) - if let ast::StmtKind::Item(ref item) = first_stmt.node { - item.attrs.first() - } else { - first_stmt.attrs().first() - }.and_then(|attr| { - // Some stmts can have embedded attributes. - // e.g. `match { #![attr] ... }` - let attr_lo = attr.span.lo(); - if attr_lo < first_stmt.span.lo() { - Some(attr_lo) - } else { - None - } - }) - }); - - let snippet = self.snippet(mk_sp( - self.last_pos, - attr_lo.unwrap_or_else(|| first_stmt.span.lo()), - )); - let len = CommentCodeSlices::new(snippet) - .nth(0) - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal { - s.rfind('\n') - } else { - None - } - }); - if let Some(len) = len { - self.last_pos = self.last_pos + BytePos::from_usize(len); - } - } - } - - // Format inner attributes if available. - let skip_rewrite = if let Some(attrs) = inner_attrs { - self.visit_attrs(attrs, ast::AttrStyle::Inner) - } else { - false - }; - - if skip_rewrite { - self.push_rewrite(b.span, None); - self.close_block(false); - self.last_pos = source!(self, b.span).hi(); - return; - } - - self.walk_block_stmts(b); - - if !b.stmts.is_empty() { - if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { - if utils::semicolon_for_expr(&self.get_context(), expr) { - self.push_str(";"); - } - } - } - - let mut remove_len = BytePos(0); - if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(stmt) = b.stmts.last() { - let snippet = self.snippet(mk_sp( - stmt.span.hi(), - source!(self, b.span).hi() - brace_compensation, - )); - let len = CommentCodeSlices::new(snippet) - .last() - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal && s.trim().is_empty() { - Some(s.len()) - } else { - None - } - }); - if let Some(len) = len { - remove_len = BytePos::from_usize(len); - } - } - } - - let unindent_comment = (self.is_if_else_block && !b.stmts.is_empty()) && { - let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; - let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); - snippet.contains("//") || snippet.contains("/*") - }; - // FIXME: we should compress any newlines here to just one - if unindent_comment { - self.block_indent = self.block_indent.block_unindent(self.config); - } - self.format_missing_with_indent( - source!(self, b.span).hi() - brace_compensation - remove_len, - ); - if unindent_comment { - self.block_indent = self.block_indent.block_indent(self.config); - } - self.close_block(unindent_comment); - self.last_pos = source!(self, b.span).hi(); - } - - // FIXME: this is a terrible hack to indent the comments between the last - // item in the block and the closing brace to the block's level. - // The closing brace itself, however, should be indented at a shallower - // level. - fn close_block(&mut self, unindent_comment: bool) { - let total_len = self.buffer.len(); - let chars_too_many = if unindent_comment { - 0 - } else if self.config.hard_tabs() { - 1 - } else { - self.config.tab_spaces() - }; - self.buffer.truncate(total_len - chars_too_many); - self.push_str("}"); - self.block_indent = self.block_indent.block_unindent(self.config); - } - - // Note that this only gets called for function definitions. Required methods - // on traits do not get handled here. - fn visit_fn( - &mut self, - fk: visit::FnKind, - generics: &ast::Generics, - fd: &ast::FnDecl, - s: Span, - defaultness: ast::Defaultness, - inner_attrs: Option<&[ast::Attribute]>, - ) { - let indent = self.block_indent; - let block; - let rewrite = match fk { - visit::FnKind::ItemFn(ident, _, _, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { - block = b; - self.rewrite_fn( - indent, - ident, - &FnSig::from_fn_kind(&fk, generics, fd, defaultness), - mk_sp(s.lo(), b.span.lo()), - b, - ) - } - visit::FnKind::Closure(_) => unreachable!(), - }; - - if let Some(fn_str) = rewrite { - self.format_missing_with_indent(source!(self, s).lo()); - self.push_str(&fn_str); - if let Some(c) = fn_str.chars().last() { - if c == '}' { - self.last_pos = source!(self, block.span).hi(); - return; - } - } - } else { - self.format_missing(source!(self, block.span).lo()); - } - - self.last_pos = source!(self, block.span).lo(); - self.visit_block(block, inner_attrs, true) - } - - pub fn visit_item(&mut self, item: &ast::Item) { - skip_out_of_file_lines_range_visitor!(self, item.span); - - // This is where we bail out if there is a skip attribute. This is only - // complex in the module case. It is complex because the module could be - // in a separate file and there might be attributes in both files, but - // the AST lumps them all together. - let filtered_attrs; - let mut attrs = &item.attrs; - match item.node { - // Module is inline, in this case we treat it like any other item. - _ if !is_mod_decl(item) => { - if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); - return; - } - } - // Module is not inline, but should be skipped. - ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => { - return; - } - // Module is not inline and should not be skipped. We want - // to process only the attributes in the current file. - ast::ItemKind::Mod(..) => { - filtered_attrs = filter_inline_attrs(&item.attrs, item.span()); - // Assert because if we should skip it should be caught by - // the above case. - assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); - attrs = &filtered_attrs; - } - _ => { - if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); - return; - } - } - } - - match item.node { - ast::ItemKind::Use(ref tree) => self.format_import(item, tree), - ast::ItemKind::Impl(..) => { - let snippet = self.snippet(item.span); - let where_span_end = snippet - .find_uncommented("{") - .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); - let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::Trait(..) => { - let rw = format_trait(&self.get_context(), item, self.block_indent); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::TraitAlias(ref generics, ref ty_param_bounds) => { - let shape = Shape::indented(self.block_indent, self.config); - let rw = format_trait_alias( - &self.get_context(), - item.ident, - generics, - ty_param_bounds, - shape, - ); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::ExternCrate(_) => { - let rw = rewrite_extern_crate(&self.get_context(), item); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { - self.visit_struct(&StructParts::from_item(item)); - } - ast::ItemKind::Enum(ref def, ref generics) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - self.visit_enum(item.ident, &item.vis, def, generics, item.span); - self.last_pos = source!(self, item.span).hi(); - } - ast::ItemKind::Mod(ref module) => { - let is_inline = !is_mod_decl(item); - self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); - } - ast::ItemKind::Mac(ref mac) => { - self.visit_mac(mac, Some(item.ident), MacroPosition::Item); - } - ast::ItemKind::ForeignMod(ref foreign_mod) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_foreign_mod(foreign_mod, item.span); - } - ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { - self.visit_static(&StaticParts::from_item(item)); - } - ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { - self.visit_fn( - visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), - generics, - decl, - item.span, - ast::Defaultness::Final, - Some(&item.attrs), - ) - } - ast::ItemKind::Ty(ref ty, ref generics) => { - let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, - item.ident, - ty, - generics, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::GlobalAsm(..) => { - let snippet = Some(self.snippet(item.span).to_owned()); - self.push_rewrite(item.span, snippet); - } - ast::ItemKind::MacroDef(ref def) => { - let rewrite = rewrite_macro_def( - &self.get_context(), - self.shape(), - self.block_indent, - def, - item.ident, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } - } - } - - pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { - skip_out_of_file_lines_range_visitor!(self, ti.span); - - if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ti.span()); - return; - } - - match ti.node { - ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), - ast::TraitItemKind::Method(ref sig, None) => { - let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); - self.push_rewrite(ti.span, rewrite); - } - ast::TraitItemKind::Method(ref sig, Some(ref body)) => { - self.visit_fn( - visit::FnKind::Method(ti.ident, sig, None, body), - &ti.generics, - &sig.decl, - ti.span, - ast::Defaultness::Final, - Some(&ti.attrs), - ); - } - ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { - let rewrite = rewrite_associated_type( - ti.ident, - type_default.as_ref(), - Some(type_param_bounds), - &self.get_context(), - self.block_indent, - ); - self.push_rewrite(ti.span, rewrite); - } - ast::TraitItemKind::Macro(ref mac) => { - self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); - } - } - } - - pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { - skip_out_of_file_lines_range_visitor!(self, ii.span); - - if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ii.span()); - return; - } - - match ii.node { - ast::ImplItemKind::Method(ref sig, ref body) => { - self.visit_fn( - visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), - &ii.generics, - &sig.decl, - ii.span, - ii.defaultness, - Some(&ii.attrs), - ); - } - ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_impl_type( - ii.ident, - ii.defaultness, - Some(ty), - None, - &self.get_context(), - self.block_indent, - ); - self.push_rewrite(ii.span, rewrite); - } - ast::ImplItemKind::Macro(ref mac) => { - self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); - } - } - } - - fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { - skip_out_of_file_lines_range_visitor!(self, mac.span); - - // 1 = ; - let shape = self.shape().sub_width(1).unwrap(); - let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); - self.push_rewrite(mac.span, rewrite); - } - - pub fn push_str(&mut self, s: &str) { - self.line_number += count_newlines(s); - self.buffer.push_str(s); - } - - #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] - fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { - if let Some(ref s) = rewrite { - self.push_str(s); - } else { - let snippet = self.snippet(span); - self.push_str(snippet); - } - self.last_pos = source!(self, span).hi(); - } - - pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { - self.format_missing_with_indent(source!(self, span).lo()); - self.push_rewrite_inner(span, rewrite); - } - - pub fn push_skipped_with_span(&mut self, span: Span) { - self.format_missing_with_indent(source!(self, span).lo()); - let lo = self.line_number + 1; - self.push_rewrite_inner(span, None); - let hi = self.line_number + 1; - self.skipped_range.push((lo, hi)); - } - - pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { - FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) - } - - pub fn from_codemap( - parse_session: &'a ParseSess, - config: &'a Config, - snippet_provider: &'a SnippetProvider, - ) -> FmtVisitor<'a> { - FmtVisitor { - parse_session, - codemap: parse_session.codemap(), - buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), - last_pos: BytePos(0), - block_indent: Indent::empty(), - config, - is_if_else_block: false, - snippet_provider, - line_number: 0, - skipped_range: vec![], - } - } - - pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { - self.snippet_provider.span_to_snippet(span) - } - - pub fn snippet(&'b self, span: Span) -> &'a str { - self.opt_snippet(span).unwrap() - } - - // Returns true if we should skip the following item. - pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { - if contains_skip(attrs) { - return true; - } - - let attrs: Vec<_> = attrs.iter().filter(|a| a.style == style).cloned().collect(); - if attrs.is_empty() { - return false; - } - - let rewrite = attrs.rewrite(&self.get_context(), self.shape()); - let span = mk_sp(attrs[0].span.lo(), attrs[attrs.len() - 1].span.hi()); - self.push_rewrite(span, rewrite); - - false - } - - fn walk_mod_items(&mut self, m: &ast::Mod) { - self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); - } - - fn walk_stmts(&mut self, stmts: &[ast::Stmt]) { - fn to_stmt_item(stmt: &ast::Stmt) -> Option<&ast::Item> { - match stmt.node { - ast::StmtKind::Item(ref item) => Some(&**item), - _ => None, - } - } - - if stmts.is_empty() { - return; - } - - // Extract leading `use ...;`. - let items: Vec<_> = stmts - .iter() - .take_while(|stmt| to_stmt_item(stmt).map_or(false, is_use_item)) - .filter_map(|stmt| to_stmt_item(stmt)) - .collect(); - - if items.is_empty() { - self.visit_stmt(&stmts[0]); - self.walk_stmts(&stmts[1..]); - } else { - self.visit_items_with_reordering(&items); - self.walk_stmts(&stmts[items.len()..]); - } - } - - fn walk_block_stmts(&mut self, b: &ast::Block) { - self.walk_stmts(&b.stmts) - } - - fn format_mod( - &mut self, - m: &ast::Mod, - vis: &ast::Visibility, - s: Span, - ident: ast::Ident, - attrs: &[ast::Attribute], - is_internal: bool, - ) { - self.push_str(&*utils::format_visibility(vis)); - self.push_str("mod "); - self.push_str(&ident.to_string()); - - if is_internal { - match self.config.brace_style() { - BraceStyle::AlwaysNextLine => { - let indent_str = self.block_indent.to_string_with_newline(self.config); - self.push_str(&indent_str); - self.push_str("{"); - } - _ => self.push_str(" {"), - } - // Hackery to account for the closing }. - let mod_lo = self.snippet_provider.span_after(source!(self, s), "{"); - let body_snippet = - self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); - let body_snippet = body_snippet.trim(); - if body_snippet.is_empty() { - self.push_str("}"); - } else { - self.last_pos = mod_lo; - self.block_indent = self.block_indent.block_indent(self.config); - self.visit_attrs(attrs, ast::AttrStyle::Inner); - self.walk_mod_items(m); - self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); - self.close_block(false); - } - self.last_pos = source!(self, m.inner).hi(); - } else { - self.push_str(";"); - self.last_pos = source!(self, s).hi(); - } - } - - pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { - self.block_indent = Indent::empty(); - self.walk_mod_items(m); - self.format_missing_with_indent(filemap.end_pos); - } - - pub fn skip_empty_lines(&mut self, end_pos: BytePos) { - while let Some(pos) = self.snippet_provider - .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") - { - if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { - if snippet.trim().is_empty() { - self.last_pos = pos; - } else { - return; - } - } - } - } - - pub fn get_context(&self) -> RewriteContext { - RewriteContext { - parse_session: self.parse_session, - codemap: self.codemap, - config: self.config, - inside_macro: false, - use_block: false, - is_if_else_block: false, - force_one_line_chain: false, - snippet_provider: self.snippet_provider, - } - } -} diff --git a/rustfmt-format-diff/src/main.rs b/rustfmt-format-diff/src/main.rs deleted file mode 100644 index c42fbb6f7cf..00000000000 --- a/rustfmt-format-diff/src/main.rs +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Inspired by Clang's clang-format-diff: -// -// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py - -#![deny(warnings)] - -extern crate env_logger; -extern crate getopts; -#[macro_use] -extern crate log; -extern crate regex; -#[macro_use] -extern crate serde_derive; -extern crate serde_json as json; - -use std::{env, fmt, process}; -use std::collections::HashSet; -use std::error::Error; -use std::io::{self, BufRead}; - -use regex::Regex; - -/// The default pattern of files to format. -/// -/// We only want to format rust files by default. -const DEFAULT_PATTERN: &str = r".*\.rs"; - -#[derive(Debug)] -enum FormatDiffError { - IncorrectOptions(getopts::Fail), - IncorrectFilter(regex::Error), - IoError(io::Error), -} - -impl fmt::Display for FormatDiffError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt::Display::fmt(self.cause().unwrap(), f) - } -} - -impl Error for FormatDiffError { - fn description(&self) -> &str { - self.cause().unwrap().description() - } - - fn cause(&self) -> Option<&Error> { - Some(match *self { - FormatDiffError::IoError(ref e) => e, - FormatDiffError::IncorrectFilter(ref e) => e, - FormatDiffError::IncorrectOptions(ref e) => e, - }) - } -} - -impl From for FormatDiffError { - fn from(fail: getopts::Fail) -> Self { - FormatDiffError::IncorrectOptions(fail) - } -} - -impl From for FormatDiffError { - fn from(err: regex::Error) -> Self { - FormatDiffError::IncorrectFilter(err) - } -} - -impl From for FormatDiffError { - fn from(fail: io::Error) -> Self { - FormatDiffError::IoError(fail) - } -} - -fn main() { - let _ = env_logger::init(); - - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optopt( - "p", - "skip-prefix", - "skip the smallest prefix containing NUMBER slashes", - "NUMBER", - ); - opts.optopt( - "f", - "filter", - "custom pattern selecting file paths to reformat", - "PATTERN", - ); - - if let Err(e) = run(&opts) { - println!("{}", opts.usage(e.description())); - process::exit(1); - } -} - -#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] -struct Range { - file: String, - range: [u32; 2], -} - -fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { - let matches = opts.parse(env::args().skip(1))?; - - if matches.opt_present("h") { - println!("{}", opts.usage("usage: ")); - return Ok(()); - } - - let filter = matches - .opt_str("f") - .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); - - let skip_prefix = matches - .opt_str("p") - .and_then(|p| p.parse::().ok()) - .unwrap_or(0); - - let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; - - run_rustfmt(&files, &ranges) -} - -fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDiffError> { - if files.is_empty() || ranges.is_empty() { - debug!("No files to format found"); - return Ok(()); - } - - let ranges_as_json = json::to_string(ranges).unwrap(); - - debug!("Files: {:?}", files); - debug!("Ranges: {:?}", ranges); - - let exit_status = process::Command::new("rustfmt") - .args(files) - .arg("--file-lines") - .arg(ranges_as_json) - .status()?; - - if !exit_status.success() { - return Err(FormatDiffError::IoError(io::Error::new( - io::ErrorKind::Other, - format!("rustfmt failed with {}", exit_status), - ))); - } - Ok(()) -} - -/// Scans a diff from `from`, and returns the set of files found, and the ranges -/// in those files. -fn scan_diff( - from: R, - skip_prefix: u32, - file_filter: &str, -) -> Result<(HashSet, Vec), FormatDiffError> -where - R: io::Read, -{ - let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix); - let diff_pattern = Regex::new(&diff_pattern).unwrap(); - - let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap(); - - let file_filter = Regex::new(&format!("^{}$", file_filter))?; - - let mut current_file = None; - - let mut files = HashSet::new(); - let mut ranges = vec![]; - for line in io::BufReader::new(from).lines() { - let line = line.unwrap(); - - if let Some(captures) = diff_pattern.captures(&line) { - current_file = Some(captures.get(1).unwrap().as_str().to_owned()); - } - - let file = match current_file { - Some(ref f) => &**f, - None => continue, - }; - - // TODO(emilio): We could avoid this most of the time if needed, but - // it's not clear it's worth it. - if !file_filter.is_match(file) { - continue; - } - - let lines_captures = match lines_pattern.captures(&line) { - Some(captures) => captures, - None => continue, - }; - - let start_line = lines_captures - .get(1) - .unwrap() - .as_str() - .parse::() - .unwrap(); - let line_count = match lines_captures.get(3) { - Some(line_count) => line_count.as_str().parse::().unwrap(), - None => 1, - }; - - if line_count == 0 { - continue; - } - - let end_line = start_line + line_count - 1; - files.insert(file.to_owned()); - ranges.push(Range { - file: file.to_owned(), - range: [start_line, end_line], - }); - } - - Ok((files, ranges)) -} - -#[test] -fn scan_simple_git_diff() { - const DIFF: &'static str = include_str!("test/bindgen.diff"); - let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); - - assert!( - files.contains("src/ir/traversal.rs"), - "Should've matched the filter" - ); - - assert!( - !files.contains("tests/headers/anon_enum.hpp"), - "Shouldn't have matched the filter" - ); - - assert_eq!( - &ranges, - &[ - Range { - file: "src/ir/item.rs".to_owned(), - range: [148, 158], - }, - Range { - file: "src/ir/item.rs".to_owned(), - range: [160, 170], - }, - Range { - file: "src/ir/traversal.rs".to_owned(), - range: [9, 16], - }, - Range { - file: "src/ir/traversal.rs".to_owned(), - range: [35, 43], - } - ] - ); -} diff --git a/rustfmt-format-diff/src/test/bindgen.diff b/rustfmt-format-diff/src/test/bindgen.diff deleted file mode 100644 index d2fd379f471..00000000000 --- a/rustfmt-format-diff/src/test/bindgen.diff +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/src/ir/item.rs b/src/ir/item.rs -index 7f3afefb..90d15e96 100644 ---- a/src/ir/item.rs -+++ b/src/ir/item.rs -@@ -148,7 +148,11 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> - impl AsTemplateParam for ItemId { - type Extra = (); - -- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { -+ fn as_template_param( -+ &self, -+ ctx: &BindgenContext, -+ _: &(), -+ ) -> Option { - ctx.resolve_item(*self).as_template_param(ctx, &()) - } - } -@@ -156,7 +160,11 @@ impl AsTemplateParam for ItemId { - impl AsTemplateParam for Item { - type Extra = (); - -- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { -+ fn as_template_param( -+ &self, -+ ctx: &BindgenContext, -+ _: &(), -+ ) -> Option { - self.kind.as_template_param(ctx, self) - } - } -diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs -index 762a3e2d..b9c9dd4e 100644 ---- a/src/ir/traversal.rs -+++ b/src/ir/traversal.rs -@@ -9,6 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; - /// - /// from --> to - /// -+/// Random content to generate a diff. -+/// - /// The `from` is left implicit: it is the concrete `Trace` implementer which - /// yielded this outgoing edge. - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -@@ -33,7 +35,9 @@ impl Into for Edge { - } - } - --/// The kind of edge reference. This is useful when we wish to only consider -+/// The kind of edge reference. -+/// -+/// This is useful when we wish to only consider - /// certain kinds of edges for a particular traversal or analysis. - #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum EdgeKind { -diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp -index 1961fe6c..34759df3 100644 ---- a/tests/headers/anon_enum.hpp -+++ b/tests/headers/anon_enum.hpp -@@ -1,7 +1,7 @@ - struct Test { - int foo; - float bar; -- enum { T_NONE }; -+ enum { T_NONE, T_SOME }; - }; - - typedef enum { diff --git a/src/attr.rs b/src/attr.rs new file mode 100644 index 00000000000..5d22bd9ffe7 --- /dev/null +++ b/src/attr.rs @@ -0,0 +1,323 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Format attributes and meta items. + +use config::lists::*; +use syntax::ast; +use syntax::codemap::Span; + +use comment::{combine_strs_with_missing_comments, contains_comment, rewrite_doc_comment}; +use expr::rewrite_literal; +use lists::{itemize_list, write_list, ListFormatting}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{count_newlines, mk_sp}; + +use std::cmp; + +/// Returns attributes on the given statement. +pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { + match stmt.node { + ast::StmtKind::Local(ref local) => &local.attrs, + ast::StmtKind::Item(ref item) => &item.attrs, + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, + ast::StmtKind::Mac(ref mac) => &mac.2, + } +} + +/// Returns attributes that are within `outer_span`. +pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { + attrs + .iter() + .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) + .cloned() + .collect() +} + +fn is_derive(attr: &ast::Attribute) -> bool { + attr.check_name("derive") +} + +/// Returns the arguments of `#[derive(...)]`. +fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { + attr.meta_item_list().map(|meta_item_list| { + meta_item_list + .iter() + .map(|nested_meta_item| context.snippet(nested_meta_item.span)) + .collect() + }) +} + +// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. +fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option { + let mut result = String::with_capacity(128); + result.push_str("#[derive("); + // 11 = `#[derive()]` + let initial_budget = shape.width.checked_sub(11)?; + let mut budget = initial_budget; + let num = derive_args.len(); + for (i, a) in derive_args.iter().enumerate() { + // 2 = `, ` or `)]` + let width = a.len() + 2; + if width > budget { + if i > 0 { + // Remove trailing whitespace. + result.pop(); + } + result.push('\n'); + // 9 = `#[derive(` + result.push_str(&(shape.indent + 9).to_string(context.config)); + budget = initial_budget; + } else { + budget = budget.checked_sub(width).unwrap_or(0); + } + result.push_str(a); + if i != num - 1 { + result.push_str(", ") + } + } + result.push_str(")]"); + Some(result) +} + +/// Returns the first group of attributes that fills the given predicate. +/// We consider two doc comments are in different group if they are separated by normal comments. +fn take_while_with_pred<'a, P>( + context: &RewriteContext, + attrs: &'a [ast::Attribute], + pred: P, +) -> &'a [ast::Attribute] +where + P: Fn(&ast::Attribute) -> bool, +{ + let mut last_index = 0; + let mut iter = attrs.iter().enumerate().peekable(); + while let Some((i, attr)) = iter.next() { + if !pred(attr) { + break; + } + if let Some(&(_, next_attr)) = iter.peek() { + // Extract comments between two attributes. + let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); + let snippet = context.snippet(span_between_attr); + if count_newlines(snippet) >= 2 || snippet.contains('/') { + break; + } + } + last_index = i; + } + if last_index == 0 { + &[] + } else { + &attrs[..last_index + 1] + } +} + +/// Rewrite the same kind of attributes at the same time. This includes doc +/// comments and derives. +fn rewrite_first_group_attrs( + context: &RewriteContext, + attrs: &[ast::Attribute], + shape: Shape, +) -> Option<(usize, String)> { + if attrs.is_empty() { + return Some((0, String::new())); + } + // Rewrite doc comments + let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); + if !sugared_docs.is_empty() { + let snippet = sugared_docs + .iter() + .map(|a| context.snippet(a.span)) + .collect::>() + .join("\n"); + return Some(( + sugared_docs.len(), + rewrite_doc_comment(&snippet, shape, context.config)?, + )); + } + // Rewrite `#[derive(..)]`s. + if context.config.merge_derives() { + let derives = take_while_with_pred(context, attrs, is_derive); + if !derives.is_empty() { + let mut derive_args = vec![]; + for derive in derives { + derive_args.append(&mut get_derive_args(context, derive)?); + } + return Some((derives.len(), format_derive(context, &derive_args, shape)?)); + } + } + // Rewrite the first attribute. + Some((1, attrs[0].rewrite(context, shape)?)) +} + +impl Rewrite for ast::NestedMetaItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), + ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), + } + } +} + +fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { + // Look at before and after comment and see if there are any empty lines. + let comment_begin = comment.chars().position(|c| c == '/'); + let len = comment_begin.unwrap_or_else(|| comment.len()); + let mlb = count_newlines(&comment[..len]) > 1; + let mla = if comment_begin.is_none() { + mlb + } else { + let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); + let len = comment_end.unwrap(); + comment + .chars() + .rev() + .take(len) + .filter(|c| *c == '\n') + .count() > 1 + }; + (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) +} + +impl Rewrite for ast::MetaItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + Some(match self.node { + ast::MetaItemKind::Word => String::from(&*self.name.as_str()), + ast::MetaItemKind::List(ref list) => { + let name = self.name.as_str(); + // 1 = `(`, 2 = `]` and `)` + let item_shape = shape + .visual_indent(0) + .shrink_left(name.len() + 1) + .and_then(|s| s.sub_width(2))?; + let items = itemize_list( + context.snippet_provider, + list.iter(), + ")", + ",", + |nested_meta_item| nested_meta_item.span.lo(), + |nested_meta_item| nested_meta_item.span.hi(), + |nested_meta_item| nested_meta_item.rewrite(context, item_shape), + self.span.lo(), + self.span.hi(), + false, + ); + let item_vec = items.collect::>(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Mixed, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: item_shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + format!("{}({})", name, write_list(&item_vec, &fmt)?) + } + ast::MetaItemKind::NameValue(ref literal) => { + let name = self.name.as_str(); + // 3 = ` = ` + let lit_shape = shape.shrink_left(name.len() + 3)?; + // `rewrite_literal` returns `None` when `literal` exceeds max + // width. Since a literal is basically unformattable unless it + // is a string literal (and only if `format_strings` is set), + // we might be better off ignoring the fact that the attribute + // is longer than the max width and contiue on formatting. + // See #2479 for example. + let value = rewrite_literal(context, literal, lit_shape) + .unwrap_or_else(|| context.snippet(literal.span).to_owned()); + format!("{} = {}", name, value) + } + }) + } +} + +impl Rewrite for ast::Attribute { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let prefix = match self.style { + ast::AttrStyle::Inner => "#!", + ast::AttrStyle::Outer => "#", + }; + let snippet = context.snippet(self.span); + if self.is_sugared_doc { + let doc_shape = Shape { + width: cmp::min(shape.width, context.config.comment_width()) + .checked_sub(shape.indent.width()) + .unwrap_or(0), + ..shape + }; + rewrite_doc_comment(snippet, doc_shape, context.config) + } else { + if contains_comment(snippet) { + return Some(snippet.to_owned()); + } + // 1 = `[` + let shape = shape.offset_left(prefix.len() + 1)?; + Some( + self.meta() + .and_then(|meta| meta.rewrite(context, shape)) + .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), + ) + } + } +} + +impl<'a> Rewrite for [ast::Attribute] { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + if self.is_empty() { + return Some(String::new()); + } + let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?; + if self.len() == 1 || first_group_len == self.len() { + Some(first_group_str) + } else { + let rest_str = self[first_group_len..].rewrite(context, shape)?; + let missing_span = mk_sp( + self[first_group_len - 1].span.hi(), + self[first_group_len].span.lo(), + ); + // Preserve an empty line before/after doc comments. + if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { + let snippet = context.snippet(missing_span); + let (mla, mlb) = has_newlines_before_after_comment(snippet); + let comment = ::comment::recover_missing_comment_in_span( + missing_span, + shape.with_max_width(context.config), + context, + 0, + )?; + let comment = if comment.is_empty() { + format!("\n{}", mlb) + } else { + format!("{}{}\n{}", mla, comment, mlb) + }; + Some(format!( + "{}{}{}{}", + first_group_str, + comment, + shape.indent.to_string(context.config), + rest_str + )) + } else { + combine_strs_with_missing_comments( + context, + &first_group_str, + &rest_str, + missing_span, + shape, + false, + ) + } + } + } +} diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 00000000000..d58cb50ac68 --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,479 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(not(test))] + +extern crate env_logger; +extern crate getopts; +extern crate rustfmt_nightly as rustfmt; + +use std::{env, error}; +use std::fs::File; +use std::io::{self, Read, Write}; +use std::path::{Path, PathBuf}; + +use getopts::{Matches, Options}; + +use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; +use rustfmt::config::file_lines::FileLines; +use rustfmt::{run, FileName, Input, Summary}; + +use std::str::FromStr; + +type FmtError = Box; +type FmtResult = std::result::Result; + +/// Rustfmt operations. +enum Operation { + /// Format files and their child modules. + Format { + files: Vec, + config_path: Option, + minimal_config_path: Option, + }, + /// Print the help message. + Help, + // Print version information + Version, + /// Print detailed configuration help. + ConfigHelp, + /// Output default config to a file, or stdout if None + ConfigOutputDefault { + path: Option, + }, + /// No file specified, read from stdin + Stdin { + input: String, + config_path: Option, + }, +} + +/// Parsed command line options. +#[derive(Clone, Debug, Default)] +struct CliOptions { + skip_children: bool, + verbose: bool, + write_mode: Option, + color: Option, + file_lines: FileLines, // Default is all lines in all files. + unstable_features: bool, + error_on_unformatted: bool, +} + +impl CliOptions { + fn from_matches(matches: &Matches) -> FmtResult { + let mut options = CliOptions::default(); + options.skip_children = matches.opt_present("skip-children"); + options.verbose = matches.opt_present("verbose"); + let unstable_features = matches.opt_present("unstable-features"); + let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false); + if unstable_features && !rust_nightly { + return Err(FmtError::from( + "Unstable features are only available on Nightly channel", + )); + } else { + options.unstable_features = unstable_features; + } + + if let Some(ref write_mode) = matches.opt_str("write-mode") { + if let Ok(write_mode) = WriteMode::from_str(write_mode) { + options.write_mode = Some(write_mode); + } else { + return Err(FmtError::from(format!( + "Invalid write-mode: {}", + write_mode + ))); + } + } + + if let Some(ref color) = matches.opt_str("color") { + match Color::from_str(color) { + Ok(color) => options.color = Some(color), + _ => return Err(FmtError::from(format!("Invalid color: {}", color))), + } + } + + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse()?; + } + + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = true; + } + + Ok(options) + } + + fn apply_to(self, config: &mut Config) { + config.set().skip_children(self.skip_children); + config.set().verbose(self.verbose); + config.set().file_lines(self.file_lines); + config.set().unstable_features(self.unstable_features); + config.set().error_on_unformatted(self.error_on_unformatted); + if let Some(write_mode) = self.write_mode { + config.set().write_mode(write_mode); + } + if let Some(color) = self.color { + config.set().color(color); + } + } +} + +/// read the given config file path recursively if present else read the project file path +fn match_cli_path_or_file( + config_path: Option, + input_file: &Path, +) -> FmtResult<(Config, Option)> { + if let Some(config_file) = config_path { + let toml = Config::from_toml_path(config_file.as_ref())?; + return Ok((toml, Some(config_file))); + } + Config::from_resolved_toml_path(input_file).map_err(FmtError::from) +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + + // Sorted in alphabetical order. + opts.optopt( + "", + "color", + "Use colored output (if supported)", + "[always|never|auto]", + ); + opts.optflag( + "", + "config-help", + "Show details of rustfmt configuration options", + ); + opts.optopt( + "", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ + found reverts to the input file path", + "[Path for the configuration file]", + ); + opts.optopt( + "", + "dump-default-config", + "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", + "PATH", + ); + opts.optopt( + "", + "dump-minimal-config", + "Dumps configuration options that were checked during formatting to a file.", + "PATH", + ); + opts.optflag( + "", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces", + ); + opts.optopt( + "", + "file-lines", + "Format specified line ranges. See README for more detail on the JSON format.", + "JSON", + ); + opts.optflag("h", "help", "Show this message"); + opts.optflag("", "skip-children", "Don't reformat child modules"); + opts.optflag( + "", + "unstable-features", + "Enables unstable features. Only available on nightly channel", + ); + opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("V", "version", "Show version information"); + opts.optopt( + "", + "write-mode", + "How to write output (not usable when piping from stdin)", + "[replace|overwrite|display|plain|diff|coverage|checkstyle]", + ); + + opts +} + +fn execute(opts: &Options) -> FmtResult { + let matches = opts.parse(env::args().skip(1))?; + + match determine_operation(&matches)? { + Operation::Help => { + print_usage_to_stdout(opts, ""); + Summary::print_exit_codes(); + Ok(Summary::default()) + } + Operation::Version => { + print_version(); + Ok(Summary::default()) + } + Operation::ConfigHelp => { + Config::print_docs(); + Ok(Summary::default()) + } + Operation::ConfigOutputDefault { path } => { + let toml = Config::default().all_options().to_toml()?; + if let Some(path) = path { + let mut file = File::create(path)?; + file.write_all(toml.as_bytes())?; + } else { + io::stdout().write_all(toml.as_bytes())?; + } + Ok(Summary::default()) + } + Operation::Stdin { input, config_path } => { + // try to read config from local directory + let (mut config, _) = + match_cli_path_or_file(config_path, &env::current_dir().unwrap())?; + + // write_mode is always Plain for Stdin. + config.set().write_mode(WriteMode::Plain); + + // parse file_lines + if let Some(ref file_lines) = matches.opt_str("file-lines") { + config.set().file_lines(file_lines.parse()?); + for f in config.file_lines().files() { + match *f { + FileName::Custom(ref f) if f == "stdin" => {} + _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), + } + } + } + + let mut error_summary = Summary::default(); + if config.version_meets_requirement(&mut error_summary) { + error_summary.add(run(Input::Text(input), &config)); + } + + Ok(error_summary) + } + Operation::Format { + files, + config_path, + minimal_config_path, + } => { + let options = CliOptions::from_matches(&matches)?; + + for f in options.file_lines.files() { + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) + } + _ => eprintln!("Warning: Not a file '{}'", f), + } + } + + let mut config = Config::default(); + // Load the config path file if provided + if let Some(config_file) = config_path.as_ref() { + config = Config::from_toml_path(config_file.as_ref())?; + }; + + if options.verbose { + if let Some(path) = config_path.as_ref() { + println!("Using rustfmt config file {}", path.display()); + } + } + + let mut error_summary = Summary::default(); + for file in files { + if !file.exists() { + eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else if file.is_dir() { + eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else { + // Check the file directory if the config-path could not be read or not provided + if config_path.is_none() { + let (config_tmp, path_tmp) = + Config::from_resolved_toml_path(file.parent().unwrap())?; + if options.verbose { + if let Some(path) = path_tmp.as_ref() { + println!( + "Using rustfmt config file {} for {}", + path.display(), + file.display() + ); + } + } + config = config_tmp; + } + + if !config.version_meets_requirement(&mut error_summary) { + break; + } + + options.clone().apply_to(&mut config); + error_summary.add(run(Input::File(file), &config)); + } + } + + // If we were given a path via dump-minimal-config, output any options + // that were used during formatting as TOML. + if let Some(path) = minimal_config_path { + let mut file = File::create(path)?; + let toml = config.used_options().to_toml()?; + file.write_all(toml.as_bytes())?; + } + + Ok(error_summary) + } + } +} + +fn main() { + let _ = env_logger::init(); + + let opts = make_opts(); + + let exit_code = match execute(&opts) { + Ok(summary) => { + if summary.has_operational_errors() { + 1 + } else if summary.has_parsing_errors() { + 2 + } else if summary.has_formatting_errors() { + 3 + } else if summary.has_diff { + // should only happen in diff mode + 4 + } else { + assert!(summary.has_no_errors()); + 0 + } + } + Err(e) => { + eprintln!("{}", e.to_string()); + 1 + } + }; + // Make sure standard output is flushed before we exit. + std::io::stdout().flush().unwrap(); + + // Exit with given exit code. + // + // NOTE: This immediately terminates the process without doing any cleanup, + // so make sure to finish all necessary cleanup before this is called. + std::process::exit(exit_code); +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + let sep = if reason.is_empty() { + String::new() + } else { + format!("{}\n\n", reason) + }; + let msg = format!( + "{}Format Rust code\n\nusage: {} [options] ...", + sep, + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&msg)); +} + +fn print_version() { + let version_info = format!( + "{}{}{}", + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), + "-", + include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) + ); + + println!("rustfmt {}", version_info); +} + +fn determine_operation(matches: &Matches) -> FmtResult { + if matches.opt_present("h") { + return Ok(Operation::Help); + } + + if matches.opt_present("config-help") { + return Ok(Operation::ConfigHelp); + } + + if matches.opt_present("dump-default-config") { + // NOTE for some reason when configured with HasArg::Maybe + Occur::Optional opt_default + // doesn't recognize `--foo bar` as a long flag with an argument but as a long flag with no + // argument *plus* a free argument. Thus we check for that case in this branch -- this is + // required for backward compatibility. + if let Some(path) = matches.free.get(0) { + return Ok(Operation::ConfigOutputDefault { + path: Some(path.clone()), + }); + } else { + return Ok(Operation::ConfigOutputDefault { + path: matches.opt_str("dump-default-config"), + }); + } + } + + if matches.opt_present("version") { + return Ok(Operation::Version); + } + + let config_path_not_found = |path: &str| -> FmtResult { + Err(FmtError::from(format!( + "Error: unable to find a config file for the given path: `{}`", + path + ))) + }; + + // Read the config_path and convert to parent dir if a file is provided. + // If a config file cannot be found from the given path, return error. + let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { + Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), + Some(ref path) if path.is_dir() => { + let config_file_path = get_toml_path(path)?; + if config_file_path.is_some() { + config_file_path + } else { + return config_path_not_found(path.to_str().unwrap()); + } + } + path => path, + }; + + // If no path is given, we won't output a minimal config. + let minimal_config_path = matches.opt_str("dump-minimal-config"); + + // if no file argument is supplied, read from stdin + if matches.free.is_empty() { + let mut buffer = String::new(); + io::stdin().read_to_string(&mut buffer)?; + + return Ok(Operation::Stdin { + input: buffer, + config_path, + }); + } + + let files: Vec<_> = matches + .free + .iter() + .map(|s| { + let p = PathBuf::from(s); + // we will do comparison later, so here tries to canonicalize first + // to get the expected behavior. + p.canonicalize().unwrap_or(p) + }) + .collect(); + + Ok(Operation::Format { + files, + config_path, + minimal_config_path, + }) +} diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs new file mode 100644 index 00000000000..1acad99688a --- /dev/null +++ b/src/cargo-fmt/main.rs @@ -0,0 +1,373 @@ +// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) + +#![cfg(not(test))] +#![deny(warnings)] + +extern crate cargo_metadata; +extern crate getopts; +extern crate serde_json as json; + +use std::collections::HashSet; +use std::env; +use std::fs; +use std::hash::{Hash, Hasher}; +use std::io::{self, Write}; +use std::iter::FromIterator; +use std::path::{Path, PathBuf}; +use std::process::{Command, ExitStatus}; +use std::str; + +use getopts::{Matches, Options}; + +fn main() { + let exit_status = execute(); + std::io::stdout().flush().unwrap(); + std::process::exit(exit_status); +} + +const SUCCESS: i32 = 0; +const FAILURE: i32 = 1; + +fn execute() -> i32 { + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("q", "quiet", "no output printed to stdout"); + opts.optflag("v", "verbose", "use verbose output"); + opts.optmulti( + "p", + "package", + "specify package to format (only usable in workspaces)", + "", + ); + opts.optflag("", "version", "print rustfmt version and exit"); + opts.optflag("", "all", "format all packages (only usable in workspaces)"); + + // If there is any invalid argument passed to `cargo fmt`, return without formatting. + let mut is_package_arg = false; + for arg in env::args().skip(2).take_while(|a| a != "--") { + if arg.starts_with('-') { + is_package_arg = arg.starts_with("--package"); + } else if !is_package_arg { + print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); + return FAILURE; + } else { + is_package_arg = false; + } + } + + let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { + Ok(m) => m, + Err(e) => { + print_usage_to_stderr(&opts, &e.to_string()); + return FAILURE; + } + }; + + let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { + (false, false) => Verbosity::Normal, + (false, true) => Verbosity::Quiet, + (true, false) => Verbosity::Verbose, + (true, true) => { + print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); + return FAILURE; + } + }; + + if matches.opt_present("h") { + print_usage_to_stdout(&opts, ""); + return SUCCESS; + } + + if matches.opt_present("version") { + return handle_command_status(get_version(verbosity), &opts); + } + + let strategy = CargoFmtStrategy::from_matches(&matches); + handle_command_status(format_crate(verbosity, &strategy), &opts) +} + +macro_rules! print_usage { + ($print: ident, $opts: ident, $reason: expr) => {{ + let msg = format!("{}\nusage: cargo fmt [options]", $reason); + $print!( + "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ + Arguments after `--` are passed to rustfmt.", + $opts.usage(&msg) + ); + }}; +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + print_usage!(println, opts, reason); +} + +fn print_usage_to_stderr(opts: &Options, reason: &str) { + print_usage!(eprintln, opts, reason); +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Verbosity { + Verbose, + Normal, + Quiet, +} + +fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { + match status { + Err(e) => { + print_usage_to_stderr(opts, &e.to_string()); + FAILURE + } + Ok(status) => { + if status.success() { + SUCCESS + } else { + status.code().unwrap_or(FAILURE) + } + } + } +} + +fn get_version(verbosity: Verbosity) -> Result { + run_rustfmt(&[], &[String::from("--version")], verbosity) +} + +fn format_crate( + verbosity: Verbosity, + strategy: &CargoFmtStrategy, +) -> Result { + let rustfmt_args = get_fmt_args(); + let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") { + HashSet::new() + } else { + get_targets(strategy)? + }; + + // Currently only bin and lib files get formatted + let files: Vec<_> = targets + .into_iter() + .inspect(|t| { + if verbosity == Verbosity::Verbose { + println!("[{}] {:?}", t.kind, t.path) + } + }) + .map(|t| t.path) + .collect(); + + run_rustfmt(&files, &rustfmt_args, verbosity) +} + +fn get_fmt_args() -> Vec { + // All arguments after -- are passed to rustfmt + env::args().skip_while(|a| a != "--").skip(1).collect() +} + +/// Target uses a `path` field for equality and hashing. +#[derive(Debug)] +pub struct Target { + /// A path to the main source file of the target. + path: PathBuf, + /// A kind of target (e.g. lib, bin, example, ...). + kind: String, +} + +impl Target { + pub fn from_target(target: &cargo_metadata::Target) -> Self { + let path = PathBuf::from(&target.src_path); + let canonicalized = fs::canonicalize(&path).unwrap_or(path); + + Target { + path: canonicalized, + kind: target.kind[0].clone(), + } + } +} + +impl PartialEq for Target { + fn eq(&self, other: &Target) -> bool { + self.path == other.path + } +} + +impl Eq for Target {} + +impl Hash for Target { + fn hash(&self, state: &mut H) { + self.path.hash(state); + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum CargoFmtStrategy { + /// Format every packages and dependencies. + All, + /// Format pacakges that are specified by the command line argument. + Some(Vec), + /// Format the root packages only. + Root, +} + +impl CargoFmtStrategy { + pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { + match (matches.opt_present("all"), matches.opt_present("p")) { + (false, false) => CargoFmtStrategy::Root, + (true, _) => CargoFmtStrategy::All, + (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), + } + } +} + +/// Based on the specified `CargoFmtStrategy`, returns a set of main source files. +fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { + let mut targets = HashSet::new(); + + match *strategy { + CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, + CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, + CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, + } + + if targets.is_empty() { + Err(io::Error::new( + io::ErrorKind::Other, + "Failed to find targets".to_owned(), + )) + } else { + Ok(targets) + } +} + +fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + + for package in metadata.packages { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } + } + + Ok(()) +} + +fn get_targets_recursive( + manifest_path: Option<&Path>, + mut targets: &mut HashSet, + visited: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(manifest_path)?; + + for package in metadata.packages { + add_targets(&package.targets, &mut targets); + + // Look for local dependencies. + for dependency in package.dependencies { + if dependency.source.is_some() || visited.contains(&dependency.name) { + continue; + } + + let mut manifest_path = PathBuf::from(&package.manifest_path); + + manifest_path.pop(); + manifest_path.push(&dependency.name); + manifest_path.push("Cargo.toml"); + + if manifest_path.exists() { + visited.insert(dependency.name); + get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; + } + } + } + + Ok(()) +} + +fn get_targets_with_hitlist( + hitlist: &[String], + targets: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + + let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); + + for package in metadata.packages { + if workspace_hitlist.remove(&package.name) { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } + } + } + + if workspace_hitlist.is_empty() { + Ok(()) + } else { + let package = workspace_hitlist.iter().next().unwrap(); + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("package `{}` is not a member of the workspace", package), + )) + } +} + +fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { + for target in target_paths { + targets.insert(Target::from_target(target)); + } +} + +fn run_rustfmt( + files: &[PathBuf], + fmt_args: &[String], + verbosity: Verbosity, +) -> Result { + let stdout = if verbosity == Verbosity::Quiet { + std::process::Stdio::null() + } else { + std::process::Stdio::inherit() + }; + + if verbosity == Verbosity::Verbose { + print!("rustfmt"); + for a in fmt_args { + print!(" {}", a); + } + for f in files { + print!(" {}", f.display()); + } + println!(); + } + + let mut command = Command::new("rustfmt") + .stdout(stdout) + .args(files) + .args(fmt_args) + .spawn() + .map_err(|e| match e.kind() { + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), + _ => e, + })?; + + command.wait() +} + +fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { + match cargo_metadata::metadata(manifest_path) { + Ok(metadata) => Ok(metadata), + Err(..) => Err(io::Error::new( + io::ErrorKind::Other, + "`cargo manifest` failed.", + )), + } +} diff --git a/src/chains.rs b/src/chains.rs new file mode 100644 index 00000000000..87100c7be41 --- /dev/null +++ b/src/chains.rs @@ -0,0 +1,501 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Formatting of chained expressions, i.e. expressions which are chained by +//! dots: struct and enum field access, method calls, and try shorthand (?). +//! +//! Instead of walking these subexpressions one-by-one, as is our usual strategy +//! for expression formatting, we collect maximal sequences of these expressions +//! and handle them simultaneously. +//! +//! Whenever possible, the entire chain is put on a single line. If that fails, +//! we put each subexpression on a separate, much like the (default) function +//! argument function argument strategy. +//! +//! Depends on config options: `chain_indent` is the indent to use for +//! blocks in the parent/root/base of the chain (and the rest of the chain's +//! alignment). +//! E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the +//! following values of `chain_indent`: +//! Block: +//! ``` +//! let foo = { +//! aaaa; +//! bbb; +//! ccc +//! }.bar +//! .baz(); +//! ``` +//! Visual: +//! ``` +//! let foo = { +//! aaaa; +//! bbb; +//! ccc +//! } +//! .bar +//! .baz(); +//! ``` +//! +//! If the first item in the chain is a block expression, we align the dots with +//! the braces. +//! Block: +//! ``` +//! let a = foo.bar +//! .baz() +//! .qux +//! ``` +//! Visual: +//! ``` +//! let a = foo.bar +//! .baz() +//! .qux +//! ``` + +use config::IndentStyle; +use expr::rewrite_call; +use macros::convert_try_mac; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, + trimmed_last_line_width, wrap_str}; + +use std::borrow::Cow; +use std::cmp::min; +use std::iter; + +use syntax::{ast, ptr}; +use syntax::codemap::Span; + +pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { + debug!("rewrite_chain {:?}", shape); + let total_span = expr.span; + let (parent, subexpr_list) = make_subexpr_list(expr, context); + + // Bail out if the chain is just try sugar, i.e., an expression followed by + // any number of `?`s. + if chain_only_try(&subexpr_list) { + return rewrite_try(&parent, subexpr_list.len(), context, shape); + } + let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); + let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); + + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. + let parent_shape = if is_block_expr(context, &parent, "\n") { + match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape, + } + } else { + shape + }; + let parent_rewrite = parent + .rewrite(context, parent_shape) + .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?; + let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); + let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); + + // Decide how to layout the rest of the chain. `extend` is true if we can + // put the first non-parent item on the same line as the parent. + let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + context.config.indent_style() == IndentStyle::Visual || is_small_parent, + ) + } else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } + } else { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + false, + ) + }; + + let other_child_shape = nested_shape.with_max_width(context.config); + + let first_child_shape = if extend { + let overhead = last_line_width(&parent_rewrite); + let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; + match context.config.indent_style() { + IndentStyle::Visual => parent_shape.offset_left(overhead)?, + IndentStyle::Block => parent_shape.offset_left(offset)?, + } + } else { + other_child_shape + }; + debug!( + "child_shapes {:?} {:?}", + first_child_shape, other_child_shape + ); + + let child_shape_iter = Some(first_child_shape) + .into_iter() + .chain(iter::repeat(other_child_shape)); + let subexpr_num = subexpr_list.len(); + let last_subexpr = &subexpr_list[suffix_try_num]; + let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; + let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); + let mut rewrites = iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) + .collect::>>()?; + + // Total of all items excluding the last. + let extend_last_subexpr = if is_small_parent { + rewrites.len() == 1 && last_line_extendable(&rewrites[0]) + } else { + rewrites.is_empty() && last_line_extendable(&parent_rewrite) + }; + let almost_total = if extend_last_subexpr { + last_line_width(&parent_rewrite) + } else { + rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() + } + suffix_try_num; + let one_line_budget = if rewrites.is_empty() { + shape.width + } else { + min(shape.width, context.config.width_heuristics().chain_width) + }; + let all_in_one_line = !parent_rewrite_contains_newline + && rewrites.iter().all(|s| !s.contains('\n')) + && almost_total < one_line_budget; + let last_shape = if rewrites.is_empty() { + first_child_shape + } else { + other_child_shape + }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; + + // Rewrite the last child. The last child of a chain requires special treatment. We need to + // know whether 'overflowing' the last child make a better formatting: + // + // A chain with overflowing the last child: + // ``` + // parent.child1.child2.last_child( + // a, + // b, + // c, + // ) + // ``` + // + // A chain without overflowing the last child (in vertical layout): + // ``` + // parent + // .child1 + // .child2 + // .last_child(a, b, c) + // ``` + // + // In particular, overflowing is effective when the last child is a method with a multi-lined + // block-like argument (e.g. closure): + // ``` + // parent.child1.child2.last_child(|a, b, c| { + // let x = foo(a, b, c); + // let y = bar(a, b, c); + // + // // ... + // + // result + // }) + // ``` + + // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of + // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); + let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { + // First we try to 'overflow' the last child and see if it looks better than using + // vertical layout. + parent_shape.offset_left(almost_total).map(|shape| { + if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + // We allow overflowing here only if both of the following conditions match: + // 1. The entire chain fits in a single line expect the last child. + // 2. `last_child_str.lines().count() >= 5`. + let line_count = rw.lines().count(); + let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + if fits_single_line && line_count >= 5 { + (Some(rw), true) + } else { + // We could not know whether overflowing is better than using vertical layout, + // just by looking at the overflowed rewrite. Now we rewrite the last child + // on its own line, and compare two rewrites to choose which is better. + match rewrite_last() { + Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), + Some(ref new_rw) if new_rw.lines().count() >= line_count => { + (Some(rw), fits_single_line) + } + new_rw @ Some(..) => (new_rw, false), + _ => (Some(rw), fits_single_line), + } + } + } else { + (rewrite_last(), false) + } + })? + } else { + (rewrite_last(), false) + }; + rewrites.push(last_subexpr_str?); + + let connector = if fits_single_line && !parent_rewrite_contains_newline { + // Yay, we can put everything on one line. + Cow::from("") + } else { + // Use new lines. + if context.force_one_line_chain { + return None; + } + nested_shape.indent.to_string_with_newline(context.config) + }; + + let first_connector = if is_small_parent || fits_single_line + || last_line_extendable(&parent_rewrite) + || context.config.indent_style() == IndentStyle::Visual + { + "" + } else { + &connector + }; + + let result = if is_small_parent && rewrites.len() > 1 { + let second_connector = if fits_single_line || rewrites[1] == "?" + || last_line_extendable(&rewrites[0]) + || context.config.indent_style() == IndentStyle::Visual + { + "" + } else { + &connector + }; + format!( + "{}{}{}{}{}", + parent_rewrite, + first_connector, + rewrites[0], + second_connector, + join_rewrites(&rewrites[1..], &connector) + ) + } else { + format!( + "{}{}{}", + parent_rewrite, + first_connector, + join_rewrites(&rewrites, &connector) + ) + }; + let result = format!("{}{}", result, repeat_try(suffix_try_num)); + if context.config.indent_style() == IndentStyle::Visual { + wrap_str(result, context.config.max_width(), shape) + } else { + Some(result) + } +} + +// True if the chain is only `?`s. +fn chain_only_try(exprs: &[ast::Expr]) -> bool { + exprs.iter().all(|e| { + if let ast::ExprKind::Try(_) = e.node { + true + } else { + false + } + }) +} + +// Try to rewrite and replace the last non-try child. Return `true` if +// replacing succeeds. +fn repeat_try(try_count: usize) -> String { + iter::repeat("?").take(try_count).collect::() +} + +fn rewrite_try( + expr: &ast::Expr, + try_count: usize, + context: &RewriteContext, + shape: Shape, +) -> Option { + let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; + Some(format!("{}{}", sub_expr, repeat_try(try_count))) +} + +fn join_rewrites(rewrites: &[String], connector: &str) -> String { + let mut rewrite_iter = rewrites.iter(); + let mut result = rewrite_iter.next().unwrap().clone(); + + for rewrite in rewrite_iter { + if rewrite != "?" { + result.push_str(connector); + } + result.push_str(&rewrite[..]); + } + + result +} + +// States whether an expression's last line exclusively consists of closing +// parens, braces, and brackets in its idiomatic formatting. +fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { + match expr.node { + ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { + context.use_block_indent() && repr.contains('\n') + } + ast::ExprKind::Struct(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) + | ast::ExprKind::Binary(_, _, ref expr) + | ast::ExprKind::Index(_, ref expr) + | ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), + _ => false, + } +} + +// Returns the root of the chain and a Vec of the prefixes of the rest of the chain. +// E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) +fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { + let mut subexpr_list = vec![expr.clone()]; + + while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { + subexpr_list.push(subexpr.clone()); + } + + let parent = subexpr_list.pop().unwrap(); + (parent, subexpr_list) +} + +fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { + match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), + } +} + +// Returns the expression's subexpression, if it exists. When the subexpr +// is a try! macro, we'll convert it to shorthand when the option is set. +fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { + match expr.node { + ast::ExprKind::MethodCall(_, ref expressions) => { + Some(convert_try(&expressions[0], context)) + } + ast::ExprKind::TupField(ref subexpr, _) + | ast::ExprKind::Field(ref subexpr, _) + | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), + _ => None, + } +} + +fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { + match expr.node { + ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { + if let Some(subexpr) = convert_try_mac(mac, context) { + subexpr + } else { + expr.clone() + } + } + _ => expr.clone(), + } +} + +// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite +// `.c`. +fn rewrite_chain_subexpr( + expr: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let rewrite_element = |expr_str: String| { + if expr_str.len() <= shape.width { + Some(expr_str) + } else { + None + } + }; + + match expr.node { + ast::ExprKind::MethodCall(ref segment, ref expressions) => { + let types = match segment.parameters { + Some(ref params) => match **params { + ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + _ => &[], + }, + _ => &[], + }; + rewrite_method_call(segment.identifier, types, expressions, span, context, shape) + } + ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), + ast::ExprKind::TupField(ref expr, ref field) => { + let space = match expr.node { + ast::ExprKind::TupField(..) => " ", + _ => "", + }; + rewrite_element(format!("{}.{}", space, field.node)) + } + ast::ExprKind::Try(_) => rewrite_element(String::from("?")), + _ => unreachable!(), + } +} + +// Determines if we can continue formatting a given expression on the same line. +fn is_continuable(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Path(..) => true, + _ => false, + } +} + +fn is_try(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Try(..) => true, + _ => false, + } +} + +fn rewrite_method_call( + method_name: ast::Ident, + types: &[ptr::P], + args: &[ptr::P], + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let (lo, type_str) = if types.is_empty() { + (args[0].span.hi(), String::new()) + } else { + let type_list = types + .iter() + .map(|ty| ty.rewrite(context, shape)) + .collect::>>()?; + + let type_str = + if context.config.spaces_within_parens_and_brackets() && !type_list.is_empty() { + format!("::< {} >", type_list.join(", ")) + } else { + format!("::<{}>", type_list.join(", ")) + }; + + (types.last().unwrap().span.hi(), type_str) + }; + + let callee_str = format!(".{}{}", method_name, type_str); + let span = mk_sp(lo, span.hi()); + + rewrite_call(context, &callee_str, &args[1..], span, shape) +} diff --git a/src/checkstyle.rs b/src/checkstyle.rs new file mode 100644 index 00000000000..7f6e650ad22 --- /dev/null +++ b/src/checkstyle.rs @@ -0,0 +1,85 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io::{self, Write}; +use std::path::Path; + +use config::WriteMode; +use rustfmt_diff::{DiffLine, Mismatch}; + +pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> +where + T: Write, +{ + if mode == WriteMode::Checkstyle { + let mut xml_heading = String::new(); + xml_heading.push_str(""); + xml_heading.push_str("\n"); + xml_heading.push_str(""); + write!(out, "{}", xml_heading)?; + } + Ok(()) +} + +pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> +where + T: Write, +{ + if mode == WriteMode::Checkstyle { + let mut xml_tail = String::new(); + xml_tail.push_str("\n"); + write!(out, "{}", xml_tail)?; + } + Ok(()) +} + +pub fn output_checkstyle_file( + mut writer: T, + filename: &Path, + diff: Vec, +) -> Result<(), io::Error> +where + T: Write, +{ + write!(writer, "", filename.display())?; + for mismatch in diff { + for line in mismatch.lines { + // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. + if let DiffLine::Expected(ref str) = line { + let message = xml_escape_str(str); + write!( + writer, + "", + mismatch.line_number, message + )?; + } + } + } + write!(writer, "")?; + Ok(()) +} + +// Convert special characters into XML entities. +// This is needed for checkstyle output. +fn xml_escape_str(string: &str) -> String { + let mut out = String::new(); + for c in string.chars() { + match c { + '<' => out.push_str("<"), + '>' => out.push_str(">"), + '"' => out.push_str("""), + '\'' => out.push_str("'"), + '&' => out.push_str("&"), + _ => out.push(c), + } + } + out +} diff --git a/src/closures.rs b/src/closures.rs new file mode 100644 index 00000000000..6097f6339ed --- /dev/null +++ b/src/closures.rs @@ -0,0 +1,392 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::lists::*; +use syntax::{ast, ptr}; +use syntax::codemap::Span; +use syntax::parse::classify; + +use codemap::SpanUtils; +use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; +use items::{span_hi_for_arg, span_lo_for_arg}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{last_line_width, left_most_sub_expr, stmt_expr}; + +// This module is pretty messy because of the rules around closures and blocks: +// FIXME - the below is probably no longer true in full. +// * if there is a return type, then there must be braces, +// * given a closure with braces, whether that is parsed to give an inner block +// or not depends on if there is a return type and if there are statements +// in that block, +// * if the first expression in the body ends with a block (i.e., is a +// statement without needing a semi-colon), then adding or removing braces +// can change whether it is treated as an expression or statement. + +pub fn rewrite_closure( + capture: ast::CaptureBy, + movability: ast::Movability, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + debug!("rewrite_closure {:?}", body); + + let (prefix, extra_offset) = + rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?; + // 1 = space between `|...|` and body. + let body_shape = shape.offset_left(extra_offset)?; + + if let ast::ExprKind::Block(ref block) = body.node { + // The body of the closure is an empty block. + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + return Some(format!("{} {{}}", prefix)); + } + + let result = match fn_decl.output { + ast::FunctionRetTy::Default(_) => { + try_rewrite_without_block(body, &prefix, context, shape, body_shape) + } + _ => None, + }; + + result.or_else(|| { + // Either we require a block, or tried without and failed. + rewrite_closure_block(block, &prefix, context, body_shape) + }) + } else { + rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| { + // The closure originally had a non-block expression, but we can't fit on + // one line, so we'll insert a block. + rewrite_closure_with_block(body, &prefix, context, body_shape) + }) + } +} + +fn try_rewrite_without_block( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, + body_shape: Shape, +) -> Option { + let expr = get_inner_expr(expr, prefix, context); + + if is_block_closure_forced(context, expr) { + rewrite_closure_with_block(expr, prefix, context, shape) + } else { + rewrite_closure_expr(expr, prefix, context, body_shape) + } +} + +fn get_inner_expr<'a>( + expr: &'a ast::Expr, + prefix: &str, + context: &RewriteContext, +) -> &'a ast::Expr { + if let ast::ExprKind::Block(ref block) = expr.node { + if !needs_block(block, prefix, context) { + // block.stmts.len() == 1 + if let Some(expr) = stmt_expr(&block.stmts[0]) { + return get_inner_expr(expr, prefix, context); + } + } + } + + expr +} + +// Figure out if a block is necessary. +fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { + is_unsafe_block(block) || block.stmts.len() > 1 + || block_contains_comment(block, context.codemap) || prefix.contains('\n') +} + +// Rewrite closure with a single expression wrapping its body with block. +fn rewrite_closure_with_block( + body: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + let left_most = left_most_sub_expr(body); + let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most); + if veto_block { + return None; + } + + let block = ast::Block { + stmts: vec![ + ast::Stmt { + id: ast::NodeId::new(0), + node: ast::StmtKind::Expr(ptr::P(body.clone())), + span: body.span, + }, + ], + id: ast::NodeId::new(0), + rules: ast::BlockCheckMode::Default, + span: body.span, + recovered: false, + }; + let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; + Some(format!("{} {}", prefix, block)) +} + +// Rewrite closure with a single expression without wrapping its body with block. +fn rewrite_closure_expr( + expr: &ast::Expr, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + fn allow_multi_line(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Catch(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::Struct(..) => true, + + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => allow_multi_line(expr), + + _ => false, + } + } + + // When rewriting closure's body without block, we require it to fit in a single line + // unless it is a block-like expression or we are inside macro call. + let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro) + || context.config.force_multiline_blocks(); + expr.rewrite(context, shape) + .and_then(|rw| { + if veto_multiline && rw.contains('\n') { + None + } else { + Some(rw) + } + }) + .map(|rw| format!("{} {}", prefix, rw)) +} + +// Rewrite closure whose body is block. +fn rewrite_closure_block( + block: &ast::Block, + prefix: &str, + context: &RewriteContext, + shape: Shape, +) -> Option { + Some(format!("{} {}", prefix, block.rewrite(context, shape)?)) +} + +// Return type is (prefix, extra_offset) +fn rewrite_closure_fn_decl( + capture: ast::CaptureBy, + movability: ast::Movability, + fn_decl: &ast::FnDecl, + body: &ast::Expr, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option<(String, usize)> { + let mover = if capture == ast::CaptureBy::Value { + "move " + } else { + "" + }; + + let immovable = if movability == ast::Movability::Static { + "static " + } else { + "" + }; + // 4 = "|| {".len(), which is overconservative when the closure consists of + // a single expression. + let nested_shape = shape + .shrink_left(mover.len() + immovable.len())? + .sub_width(4)?; + + // 1 = | + let argument_offset = nested_shape.indent + 1; + let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); + let ret_str = fn_decl.output.rewrite(context, arg_shape)?; + + let arg_items = itemize_list( + context.snippet_provider, + fn_decl.inputs.iter(), + "|", + ",", + |arg| span_lo_for_arg(arg), + |arg| span_hi_for_arg(context, arg), + |arg| arg.rewrite(context, arg_shape), + context.snippet_provider.span_after(span, "|"), + body.span.lo(), + false, + ); + let item_vec = arg_items.collect::>(); + // 1 = space between arguments and return type. + let horizontal_budget = nested_shape + .width + .checked_sub(ret_str.len() + 1) + .unwrap_or(0); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + horizontal_budget, + ); + let arg_shape = match tactic { + DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, + _ => arg_shape, + }; + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arg_shape, + ends_with_newline: false, + preserve_newline: true, + config: context.config, + }; + let list_str = write_list(&item_vec, &fmt)?; + let mut prefix = format!("{}{}|{}|", immovable, mover, list_str); + + if !ret_str.is_empty() { + if prefix.contains('\n') { + prefix.push('\n'); + prefix.push_str(&argument_offset.to_string(context.config)); + } else { + prefix.push(' '); + } + prefix.push_str(&ret_str); + } + // 1 = space between `|...|` and body. + let extra_offset = last_line_width(&prefix) + 1; + + Some((prefix, extra_offset)) +} + +// Rewriting closure which is placed at the end of the function call's arg. +// Returns `None` if the reformatted closure 'looks bad'. +pub fn rewrite_last_closure( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, +) -> Option { + if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { + let body = match body.node { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + { + stmt_expr(&block.stmts[0]).unwrap_or(body) + } + _ => body, + }; + let (prefix, extra_offset) = rewrite_closure_fn_decl( + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, + )?; + // If the closure goes multi line before its body, do not overflow the closure. + if prefix.contains('\n') { + return None; + } + + let body_shape = shape.offset_left(extra_offset)?; + + // We force to use block for the body of the closure for certain kinds of expressions. + if is_block_closure_forced(context, body) { + return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( + |body_str| { + // If the expression can fit in a single line, we need not force block closure. + if body_str.lines().count() <= 7 { + match rewrite_closure_expr(body, &prefix, context, shape) { + Some(ref single_line_body_str) + if !single_line_body_str.contains('\n') => + { + Some(single_line_body_str.clone()) + } + _ => Some(body_str), + } + } else { + Some(body_str) + } + }, + ); + } + + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + let is_multi_lined_cond = rewrite_cond(context, body, body_shape) + .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) + .unwrap_or(false); + if is_multi_lined_cond { + return rewrite_closure_with_block(body, &prefix, context, body_shape); + } + + // Seems fine, just format the closure in usual manner. + return expr.rewrite(context, shape); + } + None +} + +/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. +pub fn args_have_many_closure(args: &[&T]) -> bool +where + T: ToExpr, +{ + args.iter() + .filter(|arg| { + arg.to_expr() + .map(|e| match e.node { + ast::ExprKind::Closure(..) => true, + _ => false, + }) + .unwrap_or(false) + }) + .count() > 1 +} + +fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { + // If we are inside macro, we do not want to add or remove block from closure body. + if context.inside_macro { + false + } else { + is_block_closure_forced_inner(expr) + } +} + +fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr), + _ => false, + } +} diff --git a/src/codemap.rs b/src/codemap.rs new file mode 100644 index 00000000000..224b2083561 --- /dev/null +++ b/src/codemap.rs @@ -0,0 +1,88 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains utilities that work with the `CodeMap` from `libsyntax` / `syntex_syntax`. +//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. + +use config::file_lines::LineRange; +use visitor::SnippetProvider; +use syntax::codemap::{BytePos, CodeMap, Span}; + +use comment::FindUncommented; + +pub trait SpanUtils { + fn span_after(&self, original: Span, needle: &str) -> BytePos; + fn span_after_last(&self, original: Span, needle: &str) -> BytePos; + fn span_before(&self, original: Span, needle: &str) -> BytePos; + fn opt_span_after(&self, original: Span, needle: &str) -> Option; +} + +pub trait LineRangeUtils { + /// Returns the `LineRange` that corresponds to `span` in `self`. + /// + /// # Panics + /// + /// Panics if `span` crosses a file boundary, which shouldn't happen. + fn lookup_line_range(&self, span: Span) -> LineRange; +} + +impl<'a> SpanUtils for SnippetProvider<'a> { + fn span_after(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).expect("Bad snippet"); + let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len(); + + original.lo() + BytePos(offset as u32) + } + + fn span_after_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo() + BytePos(offset as u32) + } + + fn span_before(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let offset = snippet.find_uncommented(needle).unwrap(); + + original.lo() + BytePos(offset as u32) + } + + fn opt_span_after(&self, original: Span, needle: &str) -> Option { + let snippet = self.span_to_snippet(original)?; + let offset = snippet.find_uncommented(needle)? + needle.len(); + + Some(original.lo() + BytePos(offset as u32)) + } +} + +impl LineRangeUtils for CodeMap { + fn lookup_line_range(&self, span: Span) -> LineRange { + let lo = self.lookup_line(span.lo()).unwrap(); + let hi = self.lookup_line(span.hi()).unwrap(); + + debug_assert_eq!( + lo.fm.name, hi.fm.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, hi + ); + + // Line numbers start at 1 + LineRange { + file: lo.fm.clone(), + lo: lo.line + 1, + hi: hi.line + 1, + } + } +} diff --git a/src/comment.rs b/src/comment.rs new file mode 100644 index 00000000000..8b148ccfc37 --- /dev/null +++ b/src/comment.rs @@ -0,0 +1,1277 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Formatting and tools for comments. + +use std::{self, iter, borrow::Cow}; + +use syntax::codemap::Span; + +use config::Config; +use rewrite::RewriteContext; +use shape::{Indent, Shape}; +use string::{rewrite_string, StringFormat}; +use utils::{count_newlines, first_line_width, last_line_width}; + +fn is_custom_comment(comment: &str) -> bool { + if !comment.starts_with("//") { + false + } else if let Some(c) = comment.chars().nth(2) { + !c.is_alphanumeric() && !c.is_whitespace() + } else { + false + } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum CommentStyle<'a> { + DoubleSlash, + TripleSlash, + Doc, + SingleBullet, + DoubleBullet, + Exclamation, + Custom(&'a str), +} + +fn custom_opener(s: &str) -> &str { + s.lines().next().map_or("", |first_line| { + first_line + .find(' ') + .map_or(first_line, |space_index| &first_line[0..space_index + 1]) + }) +} + +impl<'a> CommentStyle<'a> { + pub fn is_doc_comment(&self) -> bool { + match *self { + CommentStyle::TripleSlash | CommentStyle::Doc => true, + _ => false, + } + } + + pub fn opener(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash => "// ", + CommentStyle::TripleSlash => "/// ", + CommentStyle::Doc => "//! ", + CommentStyle::SingleBullet => "/* ", + CommentStyle::DoubleBullet => "/** ", + CommentStyle::Exclamation => "/*! ", + CommentStyle::Custom(opener) => opener, + } + } + + pub fn closer(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash + | CommentStyle::TripleSlash + | CommentStyle::Custom(..) + | CommentStyle::Doc => "", + CommentStyle::DoubleBullet => " **/", + CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", + } + } + + pub fn line_start(&self) -> &'a str { + match *self { + CommentStyle::DoubleSlash => "// ", + CommentStyle::TripleSlash => "/// ", + CommentStyle::Doc => "//! ", + CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", + CommentStyle::DoubleBullet => " ** ", + CommentStyle::Custom(opener) => opener, + } + } + + pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { + (self.opener(), self.closer(), self.line_start()) + } + + pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { + match *self { + CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { + line.trim_left().starts_with(self.line_start().trim_left()) + || comment_style(line, normalize_comments) == *self + } + CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { + line.trim_left().starts_with(self.closer().trim_left()) + || line.trim_left().starts_with(self.line_start().trim_left()) + || comment_style(line, normalize_comments) == *self + } + CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), + } + } +} + +fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { + if !normalize_comments { + if orig.starts_with("/**") && !orig.starts_with("/**/") { + CommentStyle::DoubleBullet + } else if orig.starts_with("/*!") { + CommentStyle::Exclamation + } else if orig.starts_with("/*") { + CommentStyle::SingleBullet + } else if orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/') { + CommentStyle::TripleSlash + } else if orig.starts_with("//!") { + CommentStyle::Doc + } else if is_custom_comment(orig) { + CommentStyle::Custom(custom_opener(orig)) + } else { + CommentStyle::DoubleSlash + } + } else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) + || (orig.starts_with("/**") && !orig.starts_with("/**/")) + { + CommentStyle::TripleSlash + } else if orig.starts_with("//!") || orig.starts_with("/*!") { + CommentStyle::Doc + } else if is_custom_comment(orig) { + CommentStyle::Custom(custom_opener(orig)) + } else { + CommentStyle::DoubleSlash + } +} + +/// Combine `prev_str` and `next_str` into a single `String`. `span` may contain +/// comments between two strings. If there are such comments, then that will be +/// recovered. If `allow_extend` is true and there is no comment between the two +/// strings, then they will be put on a single line as long as doing so does not +/// exceed max width. +pub fn combine_strs_with_missing_comments( + context: &RewriteContext, + prev_str: &str, + next_str: &str, + span: Span, + shape: Shape, + allow_extend: bool, +) -> Option { + let mut result = + String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128); + result.push_str(prev_str); + let mut allow_one_line = !prev_str.contains('\n') && !next_str.contains('\n'); + let first_sep = if prev_str.is_empty() || next_str.is_empty() { + "" + } else { + " " + }; + let mut one_line_width = + last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); + + let config = context.config; + let indent = shape.indent; + let missing_comment = rewrite_missing_comment(span, shape, context)?; + + if missing_comment.is_empty() { + if allow_extend && prev_str.len() + first_sep.len() + next_str.len() <= shape.width { + result.push_str(first_sep); + } else if !prev_str.is_empty() { + result.push_str(&indent.to_string_with_newline(config)) + } + result.push_str(next_str); + return Some(result); + } + + // We have a missing comment between the first expression and the second expression. + + // Peek the the original source code and find out whether there is a newline between the first + // expression and the second expression or the missing comment. We will preserve the original + // layout whenever possible. + let original_snippet = context.snippet(span); + let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { + !original_snippet[..pos].contains('\n') + } else { + !original_snippet.contains('\n') + }; + + one_line_width -= first_sep.len(); + let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { + Cow::from("") + } else { + let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; + if prefer_same_line && one_line_width <= shape.width { + Cow::from(" ") + } else { + indent.to_string_with_newline(config) + } + }; + result.push_str(&first_sep); + result.push_str(&missing_comment); + + let second_sep = if missing_comment.is_empty() || next_str.is_empty() { + Cow::from("") + } else if missing_comment.starts_with("//") { + indent.to_string_with_newline(config) + } else { + one_line_width += missing_comment.len() + first_sep.len() + 1; + allow_one_line &= !missing_comment.starts_with("//") && !missing_comment.contains('\n'); + if prefer_same_line && allow_one_line && one_line_width <= shape.width { + Cow::from(" ") + } else { + indent.to_string_with_newline(config) + } + }; + result.push_str(&second_sep); + result.push_str(next_str); + + Some(result) +} + +pub fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { + _rewrite_comment(orig, false, shape, config, true) +} + +pub fn rewrite_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, +) -> Option { + _rewrite_comment(orig, block_style, shape, config, false) +} + +fn _rewrite_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, + is_doc_comment: bool, +) -> Option { + // If there are lines without a starting sigil, we won't format them correctly + // so in that case we won't even re-align (if !config.normalize_comments()) and + // we should stop now. + let num_bare_lines = orig.lines() + .map(|line| line.trim()) + .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) + .count(); + if num_bare_lines > 0 && !config.normalize_comments() { + return Some(orig.to_owned()); + } + if !config.normalize_comments() && !config.wrap_comments() { + return light_rewrite_comment(orig, shape.indent, config, is_doc_comment); + } + + identify_comment(orig, block_style, shape, config, is_doc_comment) +} + +fn identify_comment( + orig: &str, + block_style: bool, + shape: Shape, + config: &Config, + is_doc_comment: bool, +) -> Option { + let style = comment_style(orig, false); + let first_group = orig.lines() + .take_while(|l| style.line_with_same_comment_style(l, false)) + .collect::>() + .join("\n"); + let rest = orig.lines() + .skip(first_group.lines().count()) + .collect::>() + .join("\n"); + + let first_group_str = rewrite_comment_inner( + &first_group, + block_style, + style, + shape, + config, + is_doc_comment || style.is_doc_comment(), + )?; + if rest.is_empty() { + Some(first_group_str) + } else { + identify_comment(&rest, block_style, shape, config, is_doc_comment).map(|rest_str| { + format!( + "{}\n{}{}", + first_group_str, + shape.indent.to_string(config), + rest_str + ) + }) + } +} + +fn rewrite_comment_inner( + orig: &str, + block_style: bool, + style: CommentStyle, + shape: Shape, + config: &Config, + is_doc_comment: bool, +) -> Option { + let (opener, closer, line_start) = if block_style { + CommentStyle::SingleBullet.to_str_tuplet() + } else { + comment_style(orig, config.normalize_comments()).to_str_tuplet() + }; + + let max_chars = shape + .width + .checked_sub(closer.len() + opener.len()) + .unwrap_or(1); + let indent_str = shape.indent.to_string_with_newline(config); + let fmt_indent = shape.indent + (opener.len() - line_start.len()); + let mut fmt = StringFormat { + opener: "", + closer: "", + line_start, + line_end: "", + shape: Shape::legacy(max_chars, fmt_indent), + trim_end: true, + config, + }; + + let line_breaks = count_newlines(orig.trim_right()); + let lines = orig.lines() + .enumerate() + .map(|(i, mut line)| { + line = trim_right_unless_two_whitespaces(line.trim_left(), is_doc_comment); + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = line[..(line.len() - 2)].trim_right(); + } + + line + }) + .map(|s| left_trim_comment_line(s, &style)) + .map(|(line, has_leading_whitespace)| { + if orig.starts_with("/*") && line_breaks == 0 { + ( + line.trim_left(), + has_leading_whitespace || config.normalize_comments(), + ) + } else { + (line, has_leading_whitespace || config.normalize_comments()) + } + }); + + let mut result = String::with_capacity(orig.len() * 2); + result.push_str(opener); + let mut code_block_buffer = String::with_capacity(128); + let mut is_prev_line_multi_line = false; + let mut inside_code_block = false; + let comment_line_separator = format!("{}{}", indent_str, line_start); + let join_code_block_with_comment_line_separator = |s: &str| { + let mut result = String::with_capacity(s.len() + 128); + let mut iter = s.lines().peekable(); + while let Some(line) = iter.next() { + result.push_str(line); + result.push_str(match iter.peek() { + Some(next_line) if next_line.is_empty() => comment_line_separator.trim_right(), + Some(..) => &comment_line_separator, + None => "", + }); + } + result + }; + + for (i, (line, has_leading_whitespace)) in lines.enumerate() { + let is_last = i == count_newlines(orig); + + if inside_code_block { + if line.starts_with("```") { + inside_code_block = false; + result.push_str(&comment_line_separator); + let code_block = ::format_code_block(&code_block_buffer, config) + .unwrap_or_else(|| code_block_buffer.to_owned()); + result.push_str(&join_code_block_with_comment_line_separator(&code_block)); + code_block_buffer.clear(); + result.push_str(&comment_line_separator); + result.push_str(line); + } else { + code_block_buffer.push_str(line); + code_block_buffer.push('\n'); + } + + continue; + } else { + inside_code_block = line.starts_with("```"); + + if result == opener { + let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; + if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + if line.is_empty() { + continue; + } + } else if is_prev_line_multi_line && !line.is_empty() { + result.push(' ') + } else if is_last && !closer.is_empty() && line.is_empty() { + result.push_str(&indent_str); + } else { + result.push_str(&comment_line_separator); + if !has_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + } + } + + if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { + match rewrite_string(line, &fmt, Some(max_chars)) { + Some(ref s) => { + is_prev_line_multi_line = s.contains('\n'); + result.push_str(s); + } + None if is_prev_line_multi_line => { + // We failed to put the current `line` next to the previous `line`. + // Remove the trailing space, then start rewrite on the next line. + result.pop(); + result.push_str(&comment_line_separator); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + match rewrite_string(line, &fmt, Some(max_chars)) { + Some(ref s) => { + is_prev_line_multi_line = s.contains('\n'); + result.push_str(s); + } + None => { + is_prev_line_multi_line = false; + result.push_str(line); + } + } + } + None => { + is_prev_line_multi_line = false; + result.push_str(line); + } + } + + fmt.shape = if is_prev_line_multi_line { + // 1 = " " + let offset = 1 + last_line_width(&result) - line_start.len(); + Shape { + width: max_chars.checked_sub(offset).unwrap_or(0), + indent: fmt_indent, + offset: fmt.shape.offset + offset, + } + } else { + Shape::legacy(max_chars, fmt_indent) + }; + } else { + if line.is_empty() && result.ends_with(' ') && !is_last { + // Remove space if this is an empty comment or a doc comment. + result.pop(); + } + result.push_str(line); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + is_prev_line_multi_line = false; + } + } + + result.push_str(closer); + if result.ends_with(opener) && opener.ends_with(' ') { + // Trailing space. + result.pop(); + } + + Some(result) +} + +/// Returns true if the given string MAY include URLs or alike. +fn has_url(s: &str) -> bool { + // This function may return false positive, but should get its job done in most cases. + s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") +} + +/// Given the span, rewrite the missing comment inside it if available. +/// Note that the given span must only include comments (or leading/trailing whitespaces). +pub fn rewrite_missing_comment( + span: Span, + shape: Shape, + context: &RewriteContext, +) -> Option { + let missing_snippet = context.snippet(span); + let trimmed_snippet = missing_snippet.trim(); + if !trimmed_snippet.is_empty() { + rewrite_comment(trimmed_snippet, false, shape, context.config) + } else { + Some(String::new()) + } +} + +/// Recover the missing comments in the specified span, if available. +/// The layout of the comments will be preserved as long as it does not break the code +/// and its total width does not exceed the max width. +pub fn recover_missing_comment_in_span( + span: Span, + shape: Shape, + context: &RewriteContext, + used_width: usize, +) -> Option { + let missing_comment = rewrite_missing_comment(span, shape, context)?; + if missing_comment.is_empty() { + Some(String::new()) + } else { + let missing_snippet = context.snippet(span); + let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); + // 1 = ` ` + let total_width = missing_comment.len() + used_width + 1; + let force_new_line_before_comment = + missing_snippet[..pos].contains('\n') || total_width > context.config.max_width(); + let sep = if force_new_line_before_comment { + shape.indent.to_string_with_newline(context.config) + } else { + Cow::from(" ") + }; + Some(format!("{}{}", sep, missing_comment)) + } +} + +/// Trim trailing whitespaces unless they consist of two or more whitespaces. +fn trim_right_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str { + if is_doc_comment && s.ends_with(" ") { + s + } else { + s.trim_right() + } +} + +/// Trims whitespace and aligns to indent, but otherwise does not change comments. +fn light_rewrite_comment( + orig: &str, + offset: Indent, + config: &Config, + is_doc_comment: bool, +) -> Option { + let lines: Vec<&str> = orig.lines() + .map(|l| { + // This is basically just l.trim(), but in the case that a line starts + // with `*` we want to leave one space before it, so it aligns with the + // `*` in `/*`. + let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); + let left_trimmed = if let Some(fnw) = first_non_whitespace { + if l.as_bytes()[fnw] == b'*' && fnw > 0 { + &l[fnw - 1..] + } else { + &l[fnw..] + } + } else { + "" + }; + // Preserve markdown's double-space line break syntax in doc comment. + trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) + }) + .collect(); + Some(lines.join(&format!("\n{}", offset.to_string(config)))) +} + +/// Trims comment characters and possibly a single space from the left of a string. +/// Does not trim all whitespace. If a single space is trimmed from the left of the string, +/// this function returns true. +fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { + if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") + || line.starts_with("/** ") + { + (&line[4..], true) + } else if let CommentStyle::Custom(opener) = *style { + if line.starts_with(opener) { + (&line[opener.len()..], true) + } else { + (&line[opener.trim_right().len()..], false) + } + } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") + || line.starts_with("///") || line.starts_with("** ") + || line.starts_with("/*!") + || (line.starts_with("/**") && !line.starts_with("/**/")) + { + (&line[3..], line.chars().nth(2).unwrap() == ' ') + } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") + || line.starts_with("**") + { + (&line[2..], line.chars().nth(1).unwrap() == ' ') + } else if line.starts_with('*') { + (&line[1..], false) + } else { + (line, line.starts_with(' ')) + } +} + +pub trait FindUncommented { + fn find_uncommented(&self, pat: &str) -> Option; +} + +impl FindUncommented for str { + fn find_uncommented(&self, pat: &str) -> Option { + let mut needle_iter = pat.chars(); + for (kind, (i, b)) in CharClasses::new(self.char_indices()) { + match needle_iter.next() { + None => { + return Some(i - pat.len()); + } + Some(c) => match kind { + FullCodeCharKind::Normal | FullCodeCharKind::InString if b == c => {} + _ => { + needle_iter = pat.chars(); + } + }, + } + } + + // Handle case where the pattern is a suffix of the search string + match needle_iter.next() { + Some(_) => None, + None => Some(self.len() - pat.len()), + } + } +} + +// Returns the first byte position after the first comment. The given string +// is expected to be prefixed by a comment, including delimiters. +// Good: "/* /* inner */ outer */ code();" +// Bad: "code(); // hello\n world!" +pub fn find_comment_end(s: &str) -> Option { + let mut iter = CharClasses::new(s.char_indices()); + for (kind, (i, _c)) in &mut iter { + if kind == FullCodeCharKind::Normal || kind == FullCodeCharKind::InString { + return Some(i); + } + } + + // Handle case where the comment ends at the end of s. + if iter.status == CharClassesStatus::Normal { + Some(s.len()) + } else { + None + } +} + +/// Returns true if text contains any comment. +pub fn contains_comment(text: &str) -> bool { + CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) +} + +/// Remove trailing spaces from the specified snippet. We do not remove spaces +/// inside strings or comments. +pub fn remove_trailing_white_spaces(text: &str) -> String { + let mut buffer = String::with_capacity(text.len()); + let mut space_buffer = String::with_capacity(128); + for (char_kind, c) in CharClasses::new(text.chars()) { + match c { + '\n' => { + if char_kind == FullCodeCharKind::InString { + buffer.push_str(&space_buffer); + } + space_buffer.clear(); + buffer.push('\n'); + } + _ if c.is_whitespace() => { + space_buffer.push(c); + } + _ => { + if !space_buffer.is_empty() { + buffer.push_str(&space_buffer); + space_buffer.clear(); + } + buffer.push(c); + } + } + } + buffer +} + +pub struct CharClasses +where + T: Iterator, + T::Item: RichChar, +{ + base: iter::Peekable, + status: CharClassesStatus, +} + +pub trait RichChar { + fn get_char(&self) -> char; +} + +impl RichChar for char { + fn get_char(&self) -> char { + *self + } +} + +impl RichChar for (usize, char) { + fn get_char(&self) -> char { + self.1 + } +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum CharClassesStatus { + Normal, + LitString, + LitStringEscape, + LitChar, + LitCharEscape, + // The u32 is the nesting deepness of the comment + BlockComment(u32), + // Status when the '/' has been consumed, but not yet the '*', deepness is + // the new deepness (after the comment opening). + BlockCommentOpening(u32), + // Status when the '*' has been consumed, but not yet the '/', deepness is + // the new deepness (after the comment closing). + BlockCommentClosing(u32), + LineComment, +} + +/// Distinguish between functional part of code and comments +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum CodeCharKind { + Normal, + Comment, +} + +/// Distinguish between functional part of code and comments, +/// describing opening and closing of comments for ease when chunking +/// code from tagged characters +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum FullCodeCharKind { + Normal, + /// The first character of a comment, there is only one for a comment (always '/') + StartComment, + /// Any character inside a comment including the second character of comment + /// marks ("//", "/*") + InComment, + /// Last character of a comment, '\n' for a line comment, '/' for a block comment. + EndComment, + /// Inside a string. + InString, +} + +impl FullCodeCharKind { + pub fn is_comment(&self) -> bool { + match *self { + FullCodeCharKind::StartComment + | FullCodeCharKind::InComment + | FullCodeCharKind::EndComment => true, + _ => false, + } + } + + pub fn is_string(&self) -> bool { + *self == FullCodeCharKind::InString + } + + fn to_codecharkind(&self) -> CodeCharKind { + if self.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + } + } +} + +impl CharClasses +where + T: Iterator, + T::Item: RichChar, +{ + pub fn new(base: T) -> CharClasses { + CharClasses { + base: base.peekable(), + status: CharClassesStatus::Normal, + } + } +} + +impl Iterator for CharClasses +where + T: Iterator, + T::Item: RichChar, +{ + type Item = (FullCodeCharKind, T::Item); + + fn next(&mut self) -> Option<(FullCodeCharKind, T::Item)> { + let item = self.base.next()?; + let chr = item.get_char(); + let mut char_kind = FullCodeCharKind::Normal; + self.status = match self.status { + CharClassesStatus::LitString => match chr { + '"' => CharClassesStatus::Normal, + '\\' => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitStringEscape + } + _ => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + }, + CharClassesStatus::LitStringEscape => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + CharClassesStatus::LitChar => match chr { + '\\' => CharClassesStatus::LitCharEscape, + '\'' => CharClassesStatus::Normal, + _ => CharClassesStatus::LitChar, + }, + CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, + CharClassesStatus::Normal => match chr { + '"' => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + '\'' => CharClassesStatus::LitChar, + '/' => match self.base.peek() { + Some(next) if next.get_char() == '*' => { + self.status = CharClassesStatus::BlockCommentOpening(1); + return Some((FullCodeCharKind::StartComment, item)); + } + Some(next) if next.get_char() == '/' => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::StartComment, item)); + } + _ => CharClassesStatus::Normal, + }, + _ => CharClassesStatus::Normal, + }, + CharClassesStatus::BlockComment(deepness) => { + assert_ne!(deepness, 0); + self.status = match self.base.peek() { + Some(next) if next.get_char() == '/' && chr == '*' => { + CharClassesStatus::BlockCommentClosing(deepness - 1) + } + Some(next) if next.get_char() == '*' && chr == '/' => { + CharClassesStatus::BlockCommentOpening(deepness + 1) + } + _ => CharClassesStatus::BlockComment(deepness), + }; + return Some((FullCodeCharKind::InComment, item)); + } + CharClassesStatus::BlockCommentOpening(deepness) => { + assert_eq!(chr, '*'); + self.status = CharClassesStatus::BlockComment(deepness); + return Some((FullCodeCharKind::InComment, item)); + } + CharClassesStatus::BlockCommentClosing(deepness) => { + assert_eq!(chr, '/'); + if deepness == 0 { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); + } else { + self.status = CharClassesStatus::BlockComment(deepness); + return Some((FullCodeCharKind::InComment, item)); + } + } + CharClassesStatus::LineComment => match chr { + '\n' => { + self.status = CharClassesStatus::Normal; + return Some((FullCodeCharKind::EndComment, item)); + } + _ => { + self.status = CharClassesStatus::LineComment; + return Some((FullCodeCharKind::InComment, item)); + } + }, + }; + Some((char_kind, item)) + } +} + +/// Iterator over functional and commented parts of a string. Any part of a string is either +/// functional code, either *one* block comment, either *one* line comment. Whitespace between +/// comments is functional code. Line comments contain their ending newlines. +struct UngroupedCommentCodeSlices<'a> { + slice: &'a str, + iter: iter::Peekable>>, +} + +impl<'a> UngroupedCommentCodeSlices<'a> { + fn new(code: &'a str) -> UngroupedCommentCodeSlices<'a> { + UngroupedCommentCodeSlices { + slice: code, + iter: CharClasses::new(code.char_indices()).peekable(), + } + } +} + +impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { + type Item = (CodeCharKind, usize, &'a str); + + fn next(&mut self) -> Option { + let (kind, (start_idx, _)) = self.iter.next()?; + match kind { + FullCodeCharKind::Normal | FullCodeCharKind::InString => { + // Consume all the Normal code + while let Some(&(char_kind, _)) = self.iter.peek() { + if char_kind.is_comment() { + break; + } + let _ = self.iter.next(); + } + } + FullCodeCharKind::StartComment => { + // Consume the whole comment + while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {} + } + _ => panic!(), + } + let slice = match self.iter.peek() { + Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx], + None => &self.slice[start_idx..], + }; + Some(( + if kind.is_comment() { + CodeCharKind::Comment + } else { + CodeCharKind::Normal + }, + start_idx, + slice, + )) + } +} + +/// Iterator over an alternating sequence of functional and commented parts of +/// a string. The first item is always a, possibly zero length, subslice of +/// functional text. Line style comments contain their ending newlines. +pub struct CommentCodeSlices<'a> { + slice: &'a str, + last_slice_kind: CodeCharKind, + last_slice_end: usize, +} + +impl<'a> CommentCodeSlices<'a> { + pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { + CommentCodeSlices { + slice, + last_slice_kind: CodeCharKind::Comment, + last_slice_end: 0, + } + } +} + +impl<'a> Iterator for CommentCodeSlices<'a> { + type Item = (CodeCharKind, usize, &'a str); + + fn next(&mut self) -> Option { + if self.last_slice_end == self.slice.len() { + return None; + } + + let mut sub_slice_end = self.last_slice_end; + let mut first_whitespace = None; + let subslice = &self.slice[self.last_slice_end..]; + let mut iter = CharClasses::new(subslice.char_indices()); + + for (kind, (i, c)) in &mut iter { + let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal + && &subslice[..2] == "//" + && [' ', '\t'].contains(&c); + + if is_comment_connector && first_whitespace.is_none() { + first_whitespace = Some(i); + } + + if kind.to_codecharkind() == self.last_slice_kind && !is_comment_connector { + let last_index = match first_whitespace { + Some(j) => j, + None => i, + }; + sub_slice_end = self.last_slice_end + last_index; + break; + } + + if !is_comment_connector { + first_whitespace = None; + } + } + + if let (None, true) = (iter.next(), sub_slice_end == self.last_slice_end) { + // This was the last subslice. + sub_slice_end = match first_whitespace { + Some(i) => self.last_slice_end + i, + None => self.slice.len(), + }; + } + + let kind = match self.last_slice_kind { + CodeCharKind::Comment => CodeCharKind::Normal, + CodeCharKind::Normal => CodeCharKind::Comment, + }; + let res = ( + kind, + self.last_slice_end, + &self.slice[self.last_slice_end..sub_slice_end], + ); + self.last_slice_end = sub_slice_end; + self.last_slice_kind = kind; + + Some(res) + } +} + +/// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text +/// (if it fits in the width/offset, else return None), else return `new` +pub fn recover_comment_removed( + new: String, + span: Span, + context: &RewriteContext, +) -> Option { + let snippet = context.snippet(span); + if snippet != new && changed_comment_content(snippet, &new) { + // We missed some comments. Keep the original text. + Some(snippet.to_owned()) + } else { + Some(new) + } +} + +/// Return true if the two strings of code have the same payload of comments. +/// The payload of comments is everything in the string except: +/// - actual code (not comments) +/// - comment start/end marks +/// - whitespace +/// - '*' at the beginning of lines in block comments +fn changed_comment_content(orig: &str, new: &str) -> bool { + // Cannot write this as a fn since we cannot return types containing closures + let code_comment_content = |code| { + let slices = UngroupedCommentCodeSlices::new(code); + slices + .filter(|&(ref kind, _, _)| *kind == CodeCharKind::Comment) + .flat_map(|(_, _, s)| CommentReducer::new(s)) + }; + let res = code_comment_content(orig).ne(code_comment_content(new)); + debug!( + "comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}", + res, + orig, + new, + code_comment_content(orig).collect::(), + code_comment_content(new).collect::() + ); + res +} + +/// Iterator over the 'payload' characters of a comment. +/// It skips whitespace, comment start/end marks, and '*' at the beginning of lines. +/// The comment must be one comment, ie not more than one start mark (no multiple line comments, +/// for example). +struct CommentReducer<'a> { + is_block: bool, + at_start_line: bool, + iter: std::str::Chars<'a>, +} + +impl<'a> CommentReducer<'a> { + fn new(comment: &'a str) -> CommentReducer<'a> { + let is_block = comment.starts_with("/*"); + let comment = remove_comment_header(comment); + CommentReducer { + is_block, + at_start_line: false, // There are no supplementary '*' on the first line + iter: comment.chars(), + } + } +} + +impl<'a> Iterator for CommentReducer<'a> { + type Item = char; + fn next(&mut self) -> Option { + loop { + let mut c = self.iter.next()?; + if self.is_block && self.at_start_line { + while c.is_whitespace() { + c = self.iter.next()?; + } + // Ignore leading '*' + if c == '*' { + c = self.iter.next()?; + } + } else if c == '\n' { + self.at_start_line = true; + } + if !c.is_whitespace() { + return Some(c); + } + } + } +} + +fn remove_comment_header(comment: &str) -> &str { + if comment.starts_with("///") || comment.starts_with("//!") { + &comment[3..] + } else if comment.starts_with("//") { + &comment[2..] + } else if (comment.starts_with("/**") && !comment.starts_with("/**/")) + || comment.starts_with("/*!") + { + &comment[3..comment.len() - 2] + } else { + assert!( + comment.starts_with("/*"), + format!("string '{}' is not a comment", comment) + ); + &comment[2..comment.len() - 2] + } +} + +#[cfg(test)] +mod test { + use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, + FindUncommented, FullCodeCharKind}; + use shape::{Indent, Shape}; + + #[test] + fn char_classes() { + let mut iter = CharClasses::new("//\n\n".chars()); + + assert_eq!((FullCodeCharKind::StartComment, '/'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::InComment, '/'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::EndComment, '\n'), iter.next().unwrap()); + assert_eq!((FullCodeCharKind::Normal, '\n'), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices() { + let input = "code(); /* test */ 1 + 1"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 8, "/* test */"), + iter.next().unwrap() + ); + assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices_two() { + let input = "// comment\n test();"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 0, "// comment\n"), + iter.next().unwrap() + ); + assert_eq!( + (CodeCharKind::Normal, 11, " test();"), + iter.next().unwrap() + ); + assert_eq!(None, iter.next()); + } + + #[test] + fn comment_code_slices_three() { + let input = "1 // comment\n // comment2\n\n"; + let mut iter = CommentCodeSlices::new(input); + + assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap()); + assert_eq!( + (CodeCharKind::Comment, 2, "// comment\n // comment2\n"), + iter.next().unwrap() + ); + assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap()); + assert_eq!(None, iter.next()); + } + + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn format_comments() { + let mut config: ::config::Config = Default::default(); + config.set().wrap_comments(true); + config.set().normalize_comments(true); + + let comment = rewrite_comment(" //test", + true, + Shape::legacy(100, Indent::new(0, 100)), + &config).unwrap(); + assert_eq!("/* test */", comment); + + let comment = rewrite_comment("// comment on a", + false, + Shape::legacy(10, Indent::empty()), + &config).unwrap(); + assert_eq!("// comment\n// on a", comment); + + let comment = rewrite_comment("// A multi line comment\n // between args.", + false, + Shape::legacy(60, Indent::new(0, 12)), + &config).unwrap(); + assert_eq!("// A multi line comment\n // between args.", comment); + + let input = "// comment"; + let expected = + "/* comment */"; + let comment = rewrite_comment(input, + true, + Shape::legacy(9, Indent::new(0, 69)), + &config).unwrap(); + assert_eq!(expected, comment); + + let comment = rewrite_comment("/* trimmed */", + true, + Shape::legacy(100, Indent::new(0, 100)), + &config).unwrap(); + assert_eq!("/* trimmed */", comment); + } + + // This is probably intended to be a non-test fn, but it is not used. I'm + // keeping it around unless it helps us test stuff. + fn uncommented(text: &str) -> String { + CharClasses::new(text.chars()) + .filter_map(|(s, c)| match s { + FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), + _ => None, + }) + .collect() + } + + #[test] + fn test_uncommented() { + assert_eq!(&uncommented("abc/*...*/"), "abc"); + assert_eq!( + &uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"), + "..ac\n" + ); + assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf"); + } + + #[test] + fn test_contains_comment() { + assert_eq!(contains_comment("abc"), false); + assert_eq!(contains_comment("abc // qsdf"), true); + assert_eq!(contains_comment("abc /* kqsdf"), true); + assert_eq!(contains_comment("abc \" /* */\" qsdf"), false); + } + + #[test] + fn test_find_uncommented() { + fn check(haystack: &str, needle: &str, expected: Option) { + assert_eq!(expected, haystack.find_uncommented(needle)); + } + + check("/*/ */test", "test", Some(6)); + check("//test\ntest", "test", Some(7)); + check("/* comment only */", "whatever", None); + check( + "/* comment */ some text /* more commentary */ result", + "result", + Some(46), + ); + check("sup // sup", "p", Some(2)); + check("sup", "x", None); + check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9)); + check("/*sup yo? \n sup*/ sup", "p", Some(20)); + check("hel/*lohello*/lo", "hello", None); + check("acb", "ab", None); + check(",/*A*/ ", ",", Some(0)); + check("abc", "abc", Some(0)); + check("/* abc */", "abc", None); + check("/**/abc/* */", "abc", Some(4)); + check("\"/* abc */\"", "abc", Some(4)); + check("\"/* abc", "abc", Some(4)); + } +} diff --git a/src/config/config_type.rs b/src/config/config_type.rs new file mode 100644 index 00000000000..950225679a5 --- /dev/null +++ b/src/config/config_type.rs @@ -0,0 +1,398 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::file_lines::FileLines; +use config::options::WidthHeuristics; + +/// Trait for types that can be used in `Config`. +pub trait ConfigType: Sized { + /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a + /// pipe-separated list of variants; for other types it returns "". + fn doc_hint() -> String; +} + +impl ConfigType for bool { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for usize { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for isize { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for String { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for FileLines { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for WidthHeuristics { + fn doc_hint() -> String { + String::new() + } +} + +/// Check if we're in a nightly build. +/// +/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap +/// to "stable", "beta", or "nightly" depending on what toolchain is being built. +/// If we are being built as part of the stable or beta toolchains, we want +/// to disable unstable configuration options. +/// +/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), +/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the +/// nightly compiler when installed from crates.io, default to nightly mode. +macro_rules! is_nightly_channel { + () => { + option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(true) + }; +} + +macro_rules! create_config { + ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( + use std::collections::HashSet; + + #[derive(Clone)] + pub struct Config { + // For each config item, we store a bool indicating whether it has + // been accessed and the value, and a bool whether the option was + // manually initialised, or taken from the default, + $($i: (Cell, bool, $ty, bool)),+ + } + + // Just like the Config struct but with each property wrapped + // as Option. This is used to parse a rustfmt.toml that doesn't + // specify all properties of `Config`. + // We first parse into `PartialConfig`, then create a default `Config` + // and overwrite the properties with corresponding values from `PartialConfig`. + #[derive(Deserialize, Serialize, Clone)] + pub struct PartialConfig { + $(pub $i: Option<$ty>),+ + } + + impl PartialConfig { + pub fn to_toml(&self) -> Result { + // Non-user-facing options can't be specified in TOML + let mut cloned = self.clone(); + cloned.file_lines = None; + cloned.verbose = None; + cloned.width_heuristics = None; + + ::toml::to_string(&cloned) + .map_err(|e| format!("Could not output config: {}", e.to_string())) + } + } + + // Macro hygiene won't allow us to make `set_$i()` methods on Config + // for each item, so this struct is used to give the API to set values: + // `config.set().option(false)`. It's pretty ugly. Consider replacing + // with `config.set_option(false)` if we ever get a stable/usable + // `concat_idents!()`. + pub struct ConfigSetter<'a>(&'a mut Config); + + impl<'a> ConfigSetter<'a> { + $( + pub fn $i(&mut self, value: $ty) { + (self.0).$i.2 = value; + if stringify!($i) == "use_small_heuristics" { + self.0.set_heuristics(); + } + } + )+ + } + + // Query each option, returns true if the user set the option, false if + // a default was used. + pub struct ConfigWasSet<'a>(&'a Config); + + impl<'a> ConfigWasSet<'a> { + $( + pub fn $i(&self) -> bool { + (self.0).$i.1 + } + )+ + } + + impl Config { + pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool { + if self.was_set().required_version() { + let version = env!("CARGO_PKG_VERSION"); + let required_version = self.required_version(); + if version != required_version { + println!( + "Error: rustfmt version ({}) doesn't match the required version ({})", + version, + required_version, + ); + error_summary.add_formatting_error(); + return false; + } + } + + true + } + + $( + pub fn $i(&self) -> $ty { + self.$i.0.set(true); + self.$i.2.clone() + } + )+ + + pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { + ConfigSetter(self) + } + + pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { + ConfigWasSet(self) + } + + fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { + $( + if let Some(val) = parsed.$i { + if self.$i.3 { + self.$i.1 = true; + self.$i.2 = val; + } else { + if is_nightly_channel!() { + self.$i.1 = true; + self.$i.2 = val; + } else { + eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ + available in nightly channel.", stringify!($i), val); + } + } + } + )+ + self.set_heuristics(); + self + } + + /// Returns a hash set initialized with every user-facing config option name. + pub fn hash_set() -> HashSet { + let mut hash_set = HashSet::new(); + $( + hash_set.insert(stringify!($i).to_owned()); + )+ + hash_set + } + + pub fn is_valid_name(name: &str) -> bool { + match name { + $( + stringify!($i) => true, + )+ + _ => false, + } + } + + pub fn from_toml(toml: &str) -> Result { + let parsed: ::toml::Value = + toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; + let mut err: String = String::new(); + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for key in table.keys() { + if !Config::is_valid_name(key) { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } + } + } + match parsed.try_into() { + Ok(parsed_config) => { + if !err.is_empty() { + eprint!("{}", err); + } + Ok(Config::default().fill_from_parsed_config(parsed_config)) + } + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); + err.push_str("Please check your config file."); + Err(err) + } + } + } + + pub fn used_options(&self) -> PartialConfig { + PartialConfig { + $( + $i: if self.$i.0.get() { + Some(self.$i.2.clone()) + } else { + None + }, + )+ + } + } + + pub fn all_options(&self) -> PartialConfig { + PartialConfig { + $( + $i: Some(self.$i.2.clone()), + )+ + } + } + + pub fn override_value(&mut self, key: &str, val: &str) + { + match key { + $( + stringify!($i) => { + self.$i.2 = val.parse::<$ty>() + .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", + stringify!($i), + val, + stringify!($ty))); + } + )+ + _ => panic!("Unknown config key in override: {}", key) + } + + if key == "use_small_heuristics" { + self.set_heuristics(); + } + } + + /// Construct a `Config` from the toml file specified at `file_path`. + /// + /// This method only looks at the provided path, for a method that + /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. + /// + /// Return a `Config` if the config could be read and parsed from + /// the file, Error otherwise. + pub fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + /// Resolve the config for input in `dir`. + /// + /// Searches for `rustfmt.toml` beginning with `dir`, and + /// recursively checking parents of `dir` if no config file is found. + /// If no config file exists in `dir` or in any parent, a + /// default `Config` will be returned (and the returned path will be empty). + /// + /// Returns the `Config` to use, and the path of the project file if there was + /// one. + pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + + /// Try to find a project file in the given directory and its parents. + /// Returns the path of a the nearest project file if one exists, + /// or `None` if no project file was found. + fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => () + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + return Ok(None); + } + } + } + + match resolve_project_file(dir)? { + None => Ok((Config::default(), None)), + Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + } + } + + pub fn is_hidden_option(name: &str) -> bool { + const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"]; + HIDE_OPTIONS.contains(&name) + } + + pub fn print_docs() { + use std::cmp; + let max = 0; + $( let max = cmp::max(max, stringify!($i).len()+1); )+ + let mut space_str = String::with_capacity(max); + for _ in 0..max { + space_str.push(' '); + } + println!("Configuration Options:"); + $( + let name_raw = stringify!($i); + + if !Config::is_hidden_option(name_raw) { + let mut name_out = String::with_capacity(max); + for _ in name_raw.len()..max-1 { + name_out.push(' ') + } + name_out.push_str(name_raw); + name_out.push(' '); + println!("{}{} Default: {:?}", + name_out, + <$ty>::doc_hint(), + $def); + $( + println!("{}{}", space_str, $dstring); + )+ + println!(); + } + )+ + } + + fn set_heuristics(&mut self) { + if self.use_small_heuristics.2 { + let max_width = self.max_width.2; + self.set().width_heuristics(WidthHeuristics::scaled(max_width)); + } else { + self.set().width_heuristics(WidthHeuristics::null()); + } + } + } + + // Template for the default configuration + impl Default for Config { + fn default() -> Config { + Config { + $( + $i: (Cell::new(false), false, $def, $stb), + )+ + } + } + } + ) +} diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs new file mode 100644 index 00000000000..714f33c03dc --- /dev/null +++ b/src/config/file_lines.rs @@ -0,0 +1,324 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains types and functions to support formatting specific line ranges. + +use std::{cmp, iter, str}; +use std::collections::HashMap; +use std::rc::Rc; + +use serde::de::{Deserialize, Deserializer}; +use serde_json as json; + +use syntax::codemap::{FileMap, FileName}; + +/// A range of lines in a file, inclusive of both ends. +pub struct LineRange { + pub file: Rc, + pub lo: usize, + pub hi: usize, +} + +impl LineRange { + pub fn file_name(&self) -> &FileName { + &self.file.name + } +} + +/// A range that is inclusive of both ends. +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] +pub struct Range { + lo: usize, + hi: usize, +} + +impl<'a> From<&'a LineRange> for Range { + fn from(range: &'a LineRange) -> Range { + Range::new(range.lo, range.hi) + } +} + +impl Range { + pub fn new(lo: usize, hi: usize) -> Range { + Range { lo, hi } + } + + fn is_empty(self) -> bool { + self.lo > self.hi + } + + fn contains(self, other: Range) -> bool { + if other.is_empty() { + true + } else { + !self.is_empty() && self.lo <= other.lo && self.hi >= other.hi + } + } + + fn intersects(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + (self.lo <= other.hi && other.hi <= self.hi) + || (other.lo <= self.hi && self.hi <= other.hi) + } + } + + fn adjacent_to(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + self.hi + 1 == other.lo || other.hi + 1 == self.lo + } + } + + /// Returns a new `Range` with lines from `self` and `other` if they were adjacent or + /// intersect; returns `None` otherwise. + fn merge(self, other: Range) -> Option { + if self.adjacent_to(other) || self.intersects(other) { + Some(Range::new( + cmp::min(self.lo, other.lo), + cmp::max(self.hi, other.hi), + )) + } else { + None + } + } +} + +/// A set of lines in files. +/// +/// It is represented as a multimap keyed on file names, with values a collection of +/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all +/// lines in all files. +#[derive(Clone, Debug, Default)] +pub struct FileLines(Option>>); + +/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, +/// and ordered by their start point. +fn normalize_ranges(ranges: &mut HashMap>) { + for ranges in ranges.values_mut() { + ranges.sort(); + let mut result = vec![]; + { + let mut iter = ranges.into_iter().peekable(); + while let Some(next) = iter.next() { + let mut next = *next; + while let Some(&&mut peek) = iter.peek() { + if let Some(merged) = next.merge(peek) { + iter.next().unwrap(); + next = merged; + } else { + break; + } + } + result.push(next) + } + } + *ranges = result; + } +} + +impl FileLines { + /// Creates a `FileLines` that contains all lines in all files. + pub fn all() -> FileLines { + FileLines(None) + } + + /// Returns true if this `FileLines` contains all lines in all files. + pub fn is_all(&self) -> bool { + self.0.is_none() + } + + pub fn from_ranges(mut ranges: HashMap>) -> FileLines { + normalize_ranges(&mut ranges); + FileLines(Some(ranges)) + } + + /// Returns an iterator over the files contained in `self`. + pub fn files(&self) -> Files { + Files(self.0.as_ref().map(|m| m.keys())) + } + + /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in + /// the designated file (if any) and returns true if `f` ever does. + fn file_range_matches(&self, file_name: &FileName, f: F) -> bool + where + F: FnMut(&Range) -> bool, + { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) { + Some(ranges) => ranges.iter().any(f), + None => false, + } + } + + /// Returns true if `range` is fully contained in `self`. + pub fn contains(&self, range: &LineRange) -> bool { + self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) + } + + /// Returns true if any lines in `range` are in `self`. + pub fn intersects(&self, range: &LineRange) -> bool { + self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) + } + + /// Returns true if `line` from `file_name` is in `self`. + pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool { + self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) + } + + /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. + pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { + self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) + } +} + +/// `FileLines` files iterator. +pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec>>); + +impl<'a> iter::Iterator for Files<'a> { + type Item = &'a FileName; + + fn next(&mut self) -> Option<&'a FileName> { + self.0.as_mut().and_then(Iterator::next) + } +} + +fn canonicalize_path_string(file: &FileName) -> Option { + match *file { + FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real), + _ => Some(file.clone()), + } +} + +// This impl is needed for `Config::override_value` to work for use in tests. +impl str::FromStr for FileLines { + type Err = String; + + fn from_str(s: &str) -> Result { + let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; + let mut m = HashMap::new(); + for js in v { + let (s, r) = JsonSpan::into_tuple(js)?; + m.entry(s).or_insert_with(|| vec![]).push(r); + } + Ok(FileLines::from_ranges(m)) + } +} + +// For JSON decoding. +#[derive(Clone, Debug, Deserialize)] +struct JsonSpan { + #[serde(deserialize_with = "deserialize_filename")] + file: FileName, + range: (usize, usize), +} + +fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { + let s = String::deserialize(d)?; + if s == "stdin" { + Ok(FileName::Custom(s)) + } else { + Ok(FileName::Real(s.into())) + } +} + +impl JsonSpan { + fn into_tuple(self) -> Result<(FileName, Range), String> { + let (lo, hi) = self.range; + let canonical = canonicalize_path_string(&self.file) + .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; + Ok((canonical, Range::new(lo, hi))) + } +} + +// This impl is needed for inclusion in the `Config` struct. We don't have a toml representation +// for `FileLines`, so it will just panic instead. +impl<'de> ::serde::de::Deserialize<'de> for FileLines { + fn deserialize(_: D) -> Result + where + D: ::serde::de::Deserializer<'de>, + { + panic!( + "FileLines cannot be deserialized from a project rustfmt.toml file: please \ + specify it via the `--file-lines` option instead" + ); + } +} + +// We also want to avoid attempting to serialize a FileLines to toml. The +// `Config` struct should ensure this impl is never reached. +impl ::serde::ser::Serialize for FileLines { + fn serialize(&self, _: S) -> Result + where + S: ::serde::ser::Serializer, + { + unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); + } +} + +#[cfg(test)] +mod test { + use super::Range; + + #[test] + fn test_range_intersects() { + assert!(Range::new(1, 2).intersects(Range::new(1, 1))); + assert!(Range::new(1, 2).intersects(Range::new(2, 2))); + assert!(!Range::new(1, 2).intersects(Range::new(0, 0))); + assert!(!Range::new(1, 2).intersects(Range::new(3, 10))); + assert!(!Range::new(1, 3).intersects(Range::new(5, 5))); + } + + #[test] + fn test_range_adjacent_to() { + assert!(!Range::new(1, 2).adjacent_to(Range::new(1, 1))); + assert!(!Range::new(1, 2).adjacent_to(Range::new(2, 2))); + assert!(Range::new(1, 2).adjacent_to(Range::new(0, 0))); + assert!(Range::new(1, 2).adjacent_to(Range::new(3, 10))); + assert!(!Range::new(1, 3).adjacent_to(Range::new(5, 5))); + } + + #[test] + fn test_range_contains() { + assert!(Range::new(1, 2).contains(Range::new(1, 1))); + assert!(Range::new(1, 2).contains(Range::new(2, 2))); + assert!(!Range::new(1, 2).contains(Range::new(0, 0))); + assert!(!Range::new(1, 2).contains(Range::new(3, 10))); + } + + #[test] + fn test_range_merge() { + assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); + assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(4, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(5, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(6, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 7).merge(Range::new(4, 5)) + ); + } +} diff --git a/src/config/lists.rs b/src/config/lists.rs new file mode 100644 index 00000000000..53cf7ca7083 --- /dev/null +++ b/src/config/lists.rs @@ -0,0 +1,105 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Configuration options related to rewriting a list. + +use config::IndentStyle; +use config::config_type::ConfigType; + +/// The definitive formatting tactic for lists. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum DefinitiveListTactic { + Vertical, + Horizontal, + Mixed, + /// Special case tactic for `format!()`, `write!()` style macros. + SpecialMacro(usize), +} + +impl DefinitiveListTactic { + pub fn ends_with_newline(&self, indent_style: IndentStyle) -> bool { + match indent_style { + IndentStyle::Block => *self != DefinitiveListTactic::Horizontal, + IndentStyle::Visual => false, + } + } +} + +/// Formatting tactic for lists. This will be cast down to a +/// `DefinitiveListTactic` depending on the number and length of the items and +/// their comments. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum ListTactic { + // One item per row. + Vertical, + // All items on one row. + Horizontal, + // Try Horizontal layout, if that fails then vertical. + HorizontalVertical, + // HorizontalVertical with a soft limit of n characters. + LimitedHorizontalVertical(usize), + // Pack as many items as possible per row over (possibly) many rows. + Mixed, +} + +impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorTactic { + Always, + Never, + Vertical, +} + +impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); + +impl SeparatorTactic { + pub fn from_bool(b: bool) -> SeparatorTactic { + if b { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } +} + +/// Where to put separator. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorPlace { + Front, + Back, +} + +impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); + +impl SeparatorPlace { + pub fn is_front(&self) -> bool { + *self == SeparatorPlace::Front + } + + pub fn is_back(&self) -> bool { + *self == SeparatorPlace::Back + } + + pub fn from_tactic( + default: SeparatorPlace, + tactic: DefinitiveListTactic, + sep: &str, + ) -> SeparatorPlace { + match tactic { + DefinitiveListTactic::Vertical => default, + _ => if sep == "," { + SeparatorPlace::Back + } else { + default + }, + } + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 00000000000..7e9fae81318 --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,245 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{env, fs}; +use std::cell::Cell; +use std::default::Default; +use std::fs::File; +use std::io::{Error, ErrorKind, Read}; +use std::path::{Path, PathBuf}; + +#[macro_use] +mod config_type; +#[macro_use] +mod options; + +pub mod file_lines; +pub mod lists; +pub mod summary; + +use config::config_type::ConfigType; +use config::file_lines::FileLines; +pub use config::lists::*; +pub use config::options::*; +use config::summary::Summary; + +/// This macro defines configuration options used in rustfmt. Each option +/// is defined as follows: +/// +/// `name: value type, default value, is stable, description;` +create_config! { + // Fundamental stuff + max_width: usize, 100, true, "Maximum width of each line"; + hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; + tab_spaces: usize, 4, true, "Number of spaces per tab"; + newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; + use_small_heuristics: bool, true, false, "Whether to use different formatting for items and \ + expressions if they satisfy a heuristic notion of 'small'."; + + // strings and comments + format_strings: bool, false, false, "Format string literals where necessary"; + wrap_comments: bool, false, true, "Break comments to fit on the line"; + comment_width: usize, 80, false, + "Maximum length of comments. No effect unless wrap_comments = true"; + normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; + + // Single line expressions and items. + empty_item_single_line: bool, true, false, + "Put empty-body functions and impls on a single line"; + struct_lit_single_line: bool, true, false, + "Put small struct literals on a single line"; + fn_single_line: bool, false, false, "Put single-expression functions on a single line"; + where_single_line: bool, false, false, "To force single line where layout"; + + // Imports + imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; + imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; + + // Ordering + reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; + reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; + reorder_imports: bool, false, false, "Reorder import statements alphabetically"; + reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; + reorder_imported_names: bool, true, false, + "Reorder lists of names in import statements alphabetically"; + reorder_modules: bool, false, false, "Reorder module statemtents alphabetically in group"; + + // Spaces around punctuation + binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + "Where to put a binary operator when a binary expression goes multiline."; + type_punctuation_density: TypeDensity, TypeDensity::Wide, false, + "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; + space_before_colon: bool, false, false, "Leave a space before the colon"; + space_after_colon: bool, true, false, "Leave a space after the colon"; + spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; + spaces_within_parens_and_brackets: bool, false, false, + "Put spaces within non-empty parentheses or brackets"; + + // Misc. + combine_control_expr: bool, true, false, "Combine control expressions with function calls."; + struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ + threshold."; + remove_blank_lines_at_start_or_end_of_block: bool, true, false, + "Remove blank lines at start or end of a block"; + match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ + the same line with the pattern of arms"; + force_multiline_blocks: bool, false, false, + "Force multiline closure bodies and match arms to be wrapped in a block"; + fn_args_density: Density, Density::Tall, false, "Argument density in functions"; + brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, + "Brace style for control flow constructs"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, + "How to handle trailing commas for lists"; + trailing_semicolon: bool, true, false, + "Add trailing semicolon after break, continue and return"; + match_block_trailing_comma: bool, false, false, + "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + blank_lines_upper_bound: usize, 1, false, + "Maximum number of blank lines which can be put between items."; + blank_lines_lower_bound: usize, 0, false, + "Minimum number of blank lines which must be put between items."; + + // Options that can change the source code beyond whitespace/blocks (somewhat linty things) + merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; + use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; + condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ + in tuple patterns"; + force_explicit_abi: bool, true, true, "Always print the abi for extern items"; + use_field_init_shorthand: bool, false, false, "Use field initialization shorthand if possible"; + + // Control options (changes the operation of rustfmt, rather than the formatting) + write_mode: WriteMode, WriteMode::Overwrite, false, + "What Write Mode to use when none is supplied: \ + Replace, Overwrite, Display, Plain, Diff, Coverage"; + color: Color, Color::Auto, false, + "What Color option to use when none is supplied: Always, Never, Auto"; + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, + "Require a specific version of rustfmt."; + unstable_features: bool, false, true, + "Enables unstable features. Only available on nightly channel"; + disable_all_formatting: bool, false, false, "Don't reformat anything"; + skip_children: bool, false, false, "Don't reformat out of line modules"; + hide_parse_errors: bool, false, false, "Hide errors from the parser"; + error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; + error_on_unformatted: bool, false, false, + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces"; + report_todo: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of TODO in source file comments"; + report_fixme: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of FIXME in source file comments"; + + // Not user-facing. + verbose: bool, false, false, "Use verbose output"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; +} + +/// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +/// +/// Return the path if a config file exists, empty if no file exists, and Error for IO errors +pub fn get_toml_path(dir: &Path) -> Result, Error> { + const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + for config_file_name in &CONFIG_FILE_NAMES { + let config_file = dir.join(config_file_name); + match fs::metadata(&config_file) { + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't + // find the project file yet, and continue searching. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e); + } + } + _ => {} + } + } + Ok(None) +} + +#[cfg(test)] +mod test { + use super::Config; + + #[test] + fn test_config_set() { + let mut config = Config::default(); + config.set().verbose(false); + assert_eq!(config.verbose(), false); + config.set().verbose(true); + assert_eq!(config.verbose(), true); + } + + #[test] + fn test_config_used_to_toml() { + let config = Config::default(); + + let merge_derives = config.merge_derives(); + let skip_children = config.skip_children(); + + let used_options = config.used_options(); + let toml = used_options.to_toml().unwrap(); + assert_eq!( + toml, + format!( + "merge_derives = {}\nskip_children = {}\n", + merge_derives, skip_children, + ) + ); + } + + #[test] + fn test_was_set() { + let config = Config::from_toml("hard_tabs = true").unwrap(); + + assert_eq!(config.was_set().hard_tabs(), true); + assert_eq!(config.was_set().verbose(), false); + } + + // FIXME(#2183) these tests cannot be run in parallel because they use env vars + // #[test] + // fn test_as_not_nightly_channel() { + // let mut config = Config::default(); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // } + + // #[test] + // fn test_as_nightly_channel() { + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // let mut config = Config::default(); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } + + // #[test] + // fn test_unstable_from_toml() { + // let mut config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), false); + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } +} diff --git a/src/config/options.rs b/src/config/options.rs new file mode 100644 index 00000000000..dcea4706ace --- /dev/null +++ b/src/config/options.rs @@ -0,0 +1,246 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::config_type::ConfigType; +use config::lists::*; + +/// Macro for deriving implementations of Serialize/Deserialize for enums +#[macro_export] +macro_rules! impl_enum_serialize_and_deserialize { + ( $e:ident, $( $x:ident ),* ) => { + impl ::serde::ser::Serialize for $e { + fn serialize(&self, serializer: S) -> Result + where S: ::serde::ser::Serializer + { + use serde::ser::Error; + + // We don't know whether the user of the macro has given us all options. + #[allow(unreachable_patterns)] + match *self { + $( + $e::$x => serializer.serialize_str(stringify!($x)), + )* + _ => { + Err(S::Error::custom(format!("Cannot serialize {:?}", self))) + } + } + } + } + + impl<'de> ::serde::de::Deserialize<'de> for $e { + fn deserialize(d: D) -> Result + where D: ::serde::Deserializer<'de> { + use serde::de::{Error, Visitor}; + use std::marker::PhantomData; + use std::fmt; + struct StringOnly(PhantomData); + impl<'de, T> Visitor<'de> for StringOnly + where T: ::serde::Deserializer<'de> { + type Value = String; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("string") + } + fn visit_str(self, value: &str) -> Result { + Ok(String::from(value)) + } + } + let s = d.deserialize_string(StringOnly::(PhantomData))?; + $( + if stringify!($x).eq_ignore_ascii_case(&s) { + return Ok($e::$x); + } + )* + static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; + Err(D::Error::unknown_variant(&s, ALLOWED)) + } + } + + impl ::std::str::FromStr for $e { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + $( + if stringify!($x).eq_ignore_ascii_case(s) { + return Ok($e::$x); + } + )* + Err("Bad variant") + } + } + + impl ConfigType for $e { + fn doc_hint() -> String { + let mut variants = Vec::new(); + $( + variants.push(stringify!($x)); + )* + format!("[{}]", variants.join("|")) + } + } + }; +} + +macro_rules! configuration_option_enum{ + ($e:ident: $( $x:ident ),+ $(,)*) => { + #[derive(Copy, Clone, Eq, PartialEq, Debug)] + pub enum $e { + $( $x ),+ + } + + impl_enum_serialize_and_deserialize!($e, $( $x ),+); + } +} + +configuration_option_enum! { NewlineStyle: + Windows, // \r\n + Unix, // \n + Native, // \r\n in Windows, \n on other platforms +} + +configuration_option_enum! { BraceStyle: + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +configuration_option_enum! { ControlBraceStyle: + // K&R style, Rust community default + AlwaysSameLine, + // Stroustrup style + ClosingNextLine, + // Allman style + AlwaysNextLine, +} + +configuration_option_enum! { IndentStyle: + // First line on the same line as the opening brace, all lines aligned with + // the first line. + Visual, + // First line is on a new line and all lines align with block indent. + Block, +} + +configuration_option_enum! { Density: + // Fit as much on one line as possible. + Compressed, + // Use more lines. + Tall, + // Place every item on a separate line. + Vertical, +} + +configuration_option_enum! { TypeDensity: + // No spaces around "=" and "+" + Compressed, + // Spaces around " = " and " + " + Wide, +} + +impl Density { + pub fn to_list_tactic(self) -> ListTactic { + match self { + Density::Compressed => ListTactic::Mixed, + Density::Tall => ListTactic::HorizontalVertical, + Density::Vertical => ListTactic::Vertical, + } + } +} + +configuration_option_enum! { ReportTactic: + Always, + Unnumbered, + Never, +} + +configuration_option_enum! { WriteMode: + // Backs the original file up and overwrites the original. + Replace, + // Overwrites original file without backup. + Overwrite, + // Writes the output to stdout. + Display, + // Writes the diff to stdout. + Diff, + // Displays how much of the input file was processed + Coverage, + // Unfancy stdout + Plain, + // Outputs a checkstyle XML file. + Checkstyle, + // Output the changed lines (for internal value only) + Modified, +} + +configuration_option_enum! { Color: + // Always use color, whether it is a piped or terminal output + Always, + // Never use color + Never, + // Automatically use color, if supported by terminal + Auto, +} + +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct WidthHeuristics { + // Maximum width of the args of a function call before falling back + // to vertical formatting. + pub fn_call_width: usize, + // Maximum width in the body of a struct lit before falling back to + // vertical formatting. + pub struct_lit_width: usize, + // Maximum width in the body of a struct variant before falling back + // to vertical formatting. + pub struct_variant_width: usize, + // Maximum width of an array literal before falling back to vertical + // formatting. + pub array_width: usize, + // Maximum length of a chain to fit on a single line. + pub chain_width: usize, + // Maximum line length for single line if-else expressions. A value + // of zero means always break if-else expressions. + pub single_line_if_else_max_width: usize, +} + +impl WidthHeuristics { + // Using this WidthHeuristics means we ignore heuristics. + pub fn null() -> WidthHeuristics { + WidthHeuristics { + fn_call_width: usize::max_value(), + struct_lit_width: 0, + struct_variant_width: 0, + array_width: usize::max_value(), + chain_width: usize::max_value(), + single_line_if_else_max_width: 0, + } + } + // scale the default WidthHeuristics according to max_width + pub fn scaled(max_width: usize) -> WidthHeuristics { + let mut max_width_ratio: f32 = max_width as f32 / 100.0; // 100 is the default width -> default ratio is 1 + max_width_ratio = (max_width_ratio * 10.0).round() / 10.0; // round to the closest 0.1 + WidthHeuristics { + fn_call_width: (60.0 * max_width_ratio).round() as usize, + struct_lit_width: (18.0 * max_width_ratio).round() as usize, + struct_variant_width: (35.0 * max_width_ratio).round() as usize, + array_width: (60.0 * max_width_ratio).round() as usize, + chain_width: (60.0 * max_width_ratio).round() as usize, + single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize, + } + } +} + +impl ::std::str::FromStr for WidthHeuristics { + type Err = &'static str; + + fn from_str(_: &str) -> Result { + Err("WidthHeuristics is not parsable") + } +} diff --git a/src/config/summary.rs b/src/config/summary.rs new file mode 100644 index 00000000000..b0be5678a0b --- /dev/null +++ b/src/config/summary.rs @@ -0,0 +1,144 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::time::{Duration, Instant}; +use std::default::Default; + +#[must_use] +#[derive(Debug, Default, Clone, Copy)] +pub struct Summary { + // Encountered e.g. an IO error. + has_operational_errors: bool, + + // Failed to reformat code because of parsing errors. + has_parsing_errors: bool, + + // Code is valid, but it is impossible to format it properly. + has_formatting_errors: bool, + + // Formatted code differs from existing code (write-mode diff only). + pub has_diff: bool, + + // Keeps track of time spent in parsing and formatting steps. + timer: Timer, +} + +impl Summary { + pub fn mark_parse_time(&mut self) { + self.timer = self.timer.done_parsing(); + } + + pub fn mark_format_time(&mut self) { + self.timer = self.timer.done_formatting(); + } + + /// Returns the time it took to parse the source files in nanoseconds. + pub fn get_parse_time(&self) -> Option { + match self.timer { + Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { + // This should never underflow since `Instant::now()` guarantees monotonicity. + Some(parse_time.duration_since(init)) + } + Timer::Initialized(..) => None, + } + } + + /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is + /// not included. + pub fn get_format_time(&self) -> Option { + match self.timer { + Timer::DoneFormatting(_init, parse_time, format_time) => { + Some(format_time.duration_since(parse_time)) + } + Timer::DoneParsing(..) | Timer::Initialized(..) => None, + } + } + + pub fn has_operational_errors(&self) -> bool { + self.has_operational_errors + } + + pub fn has_parsing_errors(&self) -> bool { + self.has_parsing_errors + } + + pub fn has_formatting_errors(&self) -> bool { + self.has_formatting_errors + } + + pub fn add_operational_error(&mut self) { + self.has_operational_errors = true; + } + + pub fn add_parsing_error(&mut self) { + self.has_parsing_errors = true; + } + + pub fn add_formatting_error(&mut self) { + self.has_formatting_errors = true; + } + + pub fn add_diff(&mut self) { + self.has_diff = true; + } + + pub fn has_no_errors(&self) -> bool { + !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors + || self.has_diff) + } + + pub fn add(&mut self, other: Summary) { + self.has_operational_errors |= other.has_operational_errors; + self.has_formatting_errors |= other.has_formatting_errors; + self.has_parsing_errors |= other.has_parsing_errors; + self.has_diff |= other.has_diff; + } + + pub fn print_exit_codes() { + let exit_codes = r#"Exit Codes: + 0 = No errors + 1 = Encountered operational errors e.g. an IO error + 2 = Failed to reformat code because of parsing errors + 3 = Code is valid, but it is impossible to format it properly + 4 = Formatted code differs from existing code (write-mode diff only)"#; + println!("{}", exit_codes); + } +} + +#[derive(Clone, Copy, Debug)] +enum Timer { + Initialized(Instant), + DoneParsing(Instant, Instant), + DoneFormatting(Instant, Instant, Instant), +} + +impl Default for Timer { + fn default() -> Self { + Timer::Initialized(Instant::now()) + } +} + +impl Timer { + fn done_parsing(self) -> Self { + match self { + Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), + _ => panic!("Timer can only transition to DoneParsing from Initialized state"), + } + } + + fn done_formatting(self) -> Self { + match self { + Timer::DoneParsing(init_time, parse_time) => { + Timer::DoneFormatting(init_time, parse_time, Instant::now()) + } + _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), + } + } +} diff --git a/src/expr.rs b/src/expr.rs new file mode 100644 index 00000000000..8ce1166cfcd --- /dev/null +++ b/src/expr.rs @@ -0,0 +1,2975 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::cmp::min; +use std::iter::repeat; + +use config::lists::*; +use syntax::{ast, ptr}; +use syntax::codemap::{BytePos, CodeMap, Span}; + +use chains::rewrite_chain; +use closures; +use codemap::{LineRangeUtils, SpanUtils}; +use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + rewrite_comment, rewrite_missing_comment, FindUncommented}; +use config::{Config, ControlBraceStyle, IndentStyle}; +use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, + struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; +use macros::{rewrite_macro, MacroArg, MacroPosition}; +use patterns::{can_be_overflowed_pat, TuplePatField}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use string::{rewrite_string, StringFormat}; +use types::{can_be_overflowed_type, rewrite_path, PathContext}; +use utils::{colon_spaces, contains_skip, count_newlines, extra_offset, first_line_width, + inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, + paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, + wrap_str}; +use vertical::rewrite_with_alignment; +use visitor::FmtVisitor; + +impl Rewrite for ast::Expr { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + format_expr(self, ExprType::SubExpression, context, shape) + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum ExprType { + Statement, + SubExpression, +} + +pub fn format_expr( + expr: &ast::Expr, + expr_type: ExprType, + context: &RewriteContext, + shape: Shape, +) -> Option { + skip_out_of_file_lines_range!(context, expr.span); + + if contains_skip(&*expr.attrs) { + return Some(context.snippet(expr.span()).to_owned()); + } + + let expr_rw = match expr.node { + ast::ExprKind::Array(ref expr_vec) => rewrite_array( + &ptr_vec_to_ref_vec(expr_vec), + mk_sp( + context.snippet_provider.span_after(expr.span, "["), + expr.span.hi(), + ), + context, + shape, + false, + ), + ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), + ast::ExprKind::Call(ref callee, ref args) => { + let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); + let callee_str = callee.rewrite(context, shape)?; + rewrite_call(context, &callee_str, args, inner_span, shape) + } + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), + ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { + // FIXME: format comments between operands and operator + rewrite_pair( + &**lhs, + &**rhs, + PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), + context, + shape, + context.config.binop_separator(), + ) + } + ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), + ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( + context, + path, + fields, + base.as_ref().map(|e| &**e), + expr.span, + shape, + ), + ast::ExprKind::Tup(ref items) => { + rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) + } + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) + .and_then(|control_flow| control_flow.rewrite(context, shape)), + ast::ExprKind::Block(ref block) => { + match expr_type { + ExprType::Statement => { + if is_unsafe_block(block) { + block.rewrite(context, shape) + } else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + // Rewrite block without trying to put it in a single line. + rw + } else { + let prefix = block_prefix(context, block, shape)?; + rewrite_block_with_visitor(context, &prefix, block, shape, true) + } + } + ExprType::SubExpression => block.rewrite(context, shape), + } + } + ast::ExprKind::Match(ref cond, ref arms) => { + rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs) + } + ast::ExprKind::Path(ref qself, ref path) => { + rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) + } + ast::ExprKind::Assign(ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, None, shape) + } + ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { + rewrite_assignment(context, lhs, rhs, Some(op), shape) + } + ast::ExprKind::Continue(ref opt_label) => { + let id_str = match *opt_label { + Some(label) => format!(" {}", label.ident), + None => String::new(), + }; + Some(format!("continue{}", id_str)) + } + ast::ExprKind::Break(ref opt_label, ref opt_expr) => { + let id_str = match *opt_label { + Some(label) => format!(" {}", label.ident), + None => String::new(), + }; + + if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape) + } else { + Some(format!("break{}", id_str)) + } + } + ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, "yield ", &**expr, shape) + } else { + Some("yield".to_string()) + }, + ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { + closures::rewrite_closure( + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, + ) + } + ast::ExprKind::Try(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::TupField(..) + | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), + ast::ExprKind::Mac(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + }) + } + ast::ExprKind::Ret(None) => Some("return".to_owned()), + ast::ExprKind::Ret(Some(ref expr)) => { + rewrite_unary_prefix(context, "return ", &**expr, shape) + } + ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), + ast::ExprKind::AddrOf(mutability, ref expr) => { + rewrite_expr_addrof(context, mutability, expr, shape) + } + ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( + &**expr, + &**ty, + PairParts::new("", " as ", ""), + context, + shape, + SeparatorPlace::Front, + ), + ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( + &**expr, + &**ty, + PairParts::new("", ": ", ""), + context, + shape, + SeparatorPlace::Back, + ), + ast::ExprKind::Index(ref expr, ref index) => { + rewrite_index(&**expr, &**index, context, shape) + } + ast::ExprKind::Repeat(ref expr, ref repeats) => { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + rewrite_pair( + &**expr, + &**repeats, + PairParts::new(lbr, "; ", rbr), + context, + shape, + SeparatorPlace::Back, + ) + } + ast::ExprKind::Range(ref lhs, ref rhs, limits) => { + let delim = match limits { + ast::RangeLimits::HalfOpen => "..", + ast::RangeLimits::Closed => "..=", + }; + + fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { + match lhs.node { + ast::ExprKind::Lit(ref lit) => match lit.node { + ast::LitKind::FloatUnsuffixed(..) => { + context.snippet(lit.span).ends_with('.') + } + _ => false, + }, + _ => false, + } + } + + match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { + (Some(lhs), Some(rhs)) => { + let sp_delim = if context.config.spaces_around_ranges() { + format!(" {} ", delim) + } else if needs_space_before_range(context, lhs) { + format!(" {}", delim) + } else { + delim.to_owned() + }; + rewrite_pair( + &*lhs, + &*rhs, + PairParts::new("", &sp_delim, ""), + context, + shape, + context.config.binop_separator(), + ) + } + (None, Some(rhs)) => { + let sp_delim = if context.config.spaces_around_ranges() { + format!("{} ", delim) + } else { + delim.to_owned() + }; + rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) + } + (Some(lhs), None) => { + let sp_delim = if context.config.spaces_around_ranges() { + format!(" {}", delim) + } else { + delim.to_owned() + }; + rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) + } + (None, None) => Some(delim.to_owned()), + } + } + // We do not format these expressions yet, but they should still + // satisfy our width restrictions. + ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { + Some(context.snippet(expr.span).to_owned()) + } + ast::ExprKind::Catch(ref block) => { + if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { + rw + } else { + // 9 = `do catch ` + let budget = shape.width.checked_sub(9).unwrap_or(0); + Some(format!( + "{}{}", + "do catch ", + block.rewrite(context, Shape::legacy(budget, shape.indent))? + )) + } + } + }; + + expr_rw + .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) + .and_then(|expr_str| { + let attrs = outer_attributes(&expr.attrs); + let attrs_str = attrs.rewrite(context, shape)?; + let span = mk_sp( + attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), + expr.span.lo(), + ); + combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) + }) +} + +#[derive(new, Clone, Copy)] +pub struct PairParts<'a> { + prefix: &'a str, + infix: &'a str, + suffix: &'a str, +} + +pub fn rewrite_pair( + lhs: &LHS, + rhs: &RHS, + pp: PairParts, + context: &RewriteContext, + shape: Shape, + separator_place: SeparatorPlace, +) -> Option +where + LHS: Rewrite, + RHS: Rewrite, +{ + let lhs_overhead = match separator_place { + SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), + SeparatorPlace::Front => shape.used_width(), + }; + let lhs_shape = Shape { + width: context.budget(lhs_overhead), + ..shape + }; + let lhs_result = lhs.rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; + + // Try to the both lhs and rhs on the same line. + let rhs_orig_result = shape + .offset_left(last_line_width(&lhs_result) + pp.infix.len()) + .and_then(|s| s.sub_width(pp.suffix.len())) + .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); + if let Some(ref rhs_result) = rhs_orig_result { + // If the rhs looks like block expression, we allow it to stay on the same line + // with the lhs even if it is multi-lined. + let allow_same_line = rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); + if !rhs_result.contains('\n') || allow_same_line { + let one_line_width = last_line_width(&lhs_result) + pp.infix.len() + + first_line_width(rhs_result) + pp.suffix.len(); + if one_line_width <= shape.width { + return Some(format!( + "{}{}{}{}", + lhs_result, pp.infix, rhs_result, pp.suffix + )); + } + } + } + + // We have to use multiple lines. + // Re-evaluate the rhs because we have more space now: + let mut rhs_shape = match context.config.indent_style() { + IndentStyle::Visual => shape + .sub_width(pp.suffix.len() + pp.prefix.len())? + .visual_indent(pp.prefix.len()), + IndentStyle::Block => { + // Try to calculate the initial constraint on the right hand side. + let rhs_overhead = shape.rhs_overhead(context.config); + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(rhs_overhead)? + } + }; + let infix = match separator_place { + SeparatorPlace::Back => pp.infix.trim_right(), + SeparatorPlace::Front => pp.infix.trim_left(), + }; + if separator_place == SeparatorPlace::Front { + rhs_shape = rhs_shape.offset_left(infix.len())?; + } + let rhs_result = rhs.rewrite(context, rhs_shape)?; + let indent_str = rhs_shape.indent.to_string_with_newline(context.config); + let infix_with_sep = match separator_place { + SeparatorPlace::Back => format!("{}{}", infix, indent_str), + SeparatorPlace::Front => format!("{}{}", indent_str, infix), + }; + Some(format!( + "{}{}{}{}", + lhs_result, infix_with_sep, rhs_result, pp.suffix + )) +} + +pub fn rewrite_array( + exprs: &[&T], + span: Span, + context: &RewriteContext, + shape: Shape, + trailing_comma: bool, +) -> Option { + let bracket_size = if context.config.spaces_within_parens_and_brackets() { + 2 // "[ " + } else { + 1 // "[" + }; + + let nested_shape = match context.config.indent_style() { + IndentStyle::Block => shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1)?, + IndentStyle::Visual => shape + .visual_indent(bracket_size) + .sub_width(bracket_size * 2)?, + }; + + let items = itemize_list( + context.snippet_provider, + exprs.iter(), + "]", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, nested_shape), + span.lo(), + span.hi(), + false, + ).collect::>(); + + if items.is_empty() { + if context.config.spaces_within_parens_and_brackets() { + return Some("[ ]".to_string()); + } else { + return Some("[]".to_string()); + } + } + + let tactic = array_tactic(context, shape, nested_shape, exprs, &items, bracket_size); + let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro && !exprs.is_empty() { + let ends_with_bracket = context.snippet(span).ends_with(']'); + let bracket_offset = if ends_with_bracket { 1 } else { 0 }; + let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); + let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?; + if &snippet[last_char_index..last_char_index + 1] == "," { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } else if context.config.indent_style() == IndentStyle::Visual { + SeparatorTactic::Never + } else { + SeparatorTactic::Vertical + }, + separator_place: SeparatorPlace::Back, + shape: nested_shape, + ends_with_newline, + preserve_newline: false, + config: context.config, + }; + let list_str = write_list(&items, &fmt)?; + + let result = if context.config.indent_style() == IndentStyle::Visual + || tactic == DefinitiveListTactic::Horizontal + { + if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { + format!("[ {} ]", list_str) + } else { + format!("[{}]", list_str) + } + } else { + format!( + "[{}{}{}]", + nested_shape.indent.to_string_with_newline(context.config), + list_str, + shape.block().indent.to_string_with_newline(context.config) + ) + }; + + Some(result) +} + +fn array_tactic( + context: &RewriteContext, + shape: Shape, + nested_shape: Shape, + exprs: &[&T], + items: &[ListItem], + bracket_size: usize, +) -> DefinitiveListTactic { + let has_long_item = items + .iter() + .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); + + match context.config.indent_style() { + IndentStyle::Block => { + let tactic = match shape.width.checked_sub(2 * bracket_size) { + Some(width) => { + let tactic = ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ); + definitive_tactic(items, tactic, Separator::Comma, width) + } + None => DefinitiveListTactic::Vertical, + }; + if tactic == DefinitiveListTactic::Vertical && !has_long_item + && is_every_args_simple(exprs) + { + DefinitiveListTactic::Mixed + } else { + tactic + } + } + IndentStyle::Visual => { + if has_long_item || items.iter().any(ListItem::is_multiline) { + definitive_tactic( + items, + ListTactic::LimitedHorizontalVertical( + context.config.width_heuristics().array_width, + ), + Separator::Comma, + nested_shape.width, + ) + } else { + DefinitiveListTactic::Mixed + } + } + } +} + +fn nop_block_collapse(block_str: Option, budget: usize) -> Option { + debug!("nop_block_collapse {:?} {}", block_str, budget); + block_str.map(|block_str| { + if block_str.starts_with('{') && budget >= 2 + && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + { + "{}".to_owned() + } else { + block_str.to_owned() + } + }) +} + +fn rewrite_empty_block( + context: &RewriteContext, + block: &ast::Block, + shape: Shape, +) -> Option { + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 + { + return Some("{}".to_owned()); + } + + // If a block contains only a single-line comment, then leave it on one line. + let user_str = context.snippet(block.span); + let user_str = user_str.trim(); + if user_str.starts_with('{') && user_str.ends_with('}') { + let comment_str = user_str[1..user_str.len() - 1].trim(); + if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") + && comment_str.len() + 4 <= shape.width + { + return Some(format!("{{ {} }}", comment_str)); + } + } + + None +} + +fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> Option { + Some(match block.rules { + ast::BlockCheckMode::Unsafe(..) => { + let snippet = context.snippet(block.span); + let open_pos = snippet.find_uncommented("{")?; + // Extract comment between unsafe and block start. + let trimmed = &snippet[6..open_pos].trim(); + + if !trimmed.is_empty() { + // 9 = "unsafe {".len(), 7 = "unsafe ".len() + let budget = shape.width.checked_sub(9)?; + format!( + "unsafe {} ", + rewrite_comment( + trimmed, + true, + Shape::legacy(budget, shape.indent + 7), + context.config, + )? + ) + } else { + "unsafe ".to_owned() + } + } + ast::BlockCheckMode::Default => String::new(), + }) +} + +fn rewrite_single_line_block( + context: &RewriteContext, + prefix: &str, + block: &ast::Block, + shape: Shape, +) -> Option { + if is_simple_block(block, context.codemap) { + let expr_shape = shape.offset_left(last_line_width(prefix))?; + let expr_str = block.stmts[0].rewrite(context, expr_shape)?; + let result = format!("{}{{ {} }}", prefix, expr_str); + if result.len() <= shape.width && !result.contains('\n') { + return Some(result); + } + } + None +} + +pub fn rewrite_block_with_visitor( + context: &RewriteContext, + prefix: &str, + block: &ast::Block, + shape: Shape, + has_braces: bool, +) -> Option { + if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + return rw; + } + + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = shape.indent; + visitor.is_if_else_block = context.is_if_else_block; + match block.rules { + ast::BlockCheckMode::Unsafe(..) => { + let snippet = context.snippet(block.span); + let open_pos = snippet.find_uncommented("{")?; + visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) + } + ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), + } + + visitor.visit_block(block, None, has_braces); + Some(format!("{}{}", prefix, visitor.buffer)) +} + +impl Rewrite for ast::Block { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + // shape.width is used only for the single line case: either the empty block `{}`, + // or an unsafe expression `unsafe { e }`. + if let rw @ Some(_) = rewrite_empty_block(context, self, shape) { + return rw; + } + + let prefix = block_prefix(context, self, shape)?; + + let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); + if let Some(ref result_str) = result { + if result_str.lines().count() <= 3 { + if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { + return rw; + } + } + } + + result + } +} + +impl Rewrite for ast::Stmt { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + skip_out_of_file_lines_range!(context, self.span()); + + let result = match self.node { + ast::StmtKind::Local(ref local) => local.rewrite(context, shape), + ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { + let suffix = if semicolon_for_stmt(context, self) { + ";" + } else { + "" + }; + + let shape = shape.sub_width(suffix.len())?; + format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) + } + ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, + }; + result.and_then(|res| recover_comment_removed(res, self.span(), context)) + } +} + +// Rewrite condition if the given expression has one. +pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { + match expr.node { + ast::ExprKind::Match(ref cond, _) => { + // `match `cond` {` + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?, + IndentStyle::Block => shape.offset_left(8)?, + }; + cond.rewrite(context, cond_shape) + } + _ => to_control_flow(expr, ExprType::SubExpression).and_then(|control_flow| { + let alt_block_sep = + String::from("\n") + &shape.indent.block_only().to_string(context.config); + control_flow + .rewrite_cond(context, shape, &alt_block_sep) + .and_then(|rw| Some(rw.0)) + }), + } +} + +// Abstraction over control flow expressions +#[derive(Debug)] +struct ControlFlow<'a> { + cond: Option<&'a ast::Expr>, + block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, + label: Option, + pat: Option<&'a ast::Pat>, + keyword: &'a str, + matcher: &'a str, + connector: &'a str, + allow_single_line: bool, + // True if this is an `if` expression in an `else if` :-( hacky + nested_if: bool, + span: Span, +} + +fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { + match expr.node { + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( + cond, + None, + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )), + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { + Some(ControlFlow::new_if( + cond, + Some(pat), + if_block, + else_block.as_ref().map(|e| &**e), + expr_type == ExprType::SubExpression, + false, + expr.span, + )) + } + ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { + Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) + } + ast::ExprKind::Loop(ref block, label) => { + Some(ControlFlow::new_loop(block, label, expr.span)) + } + ast::ExprKind::While(ref cond, ref block, label) => { + Some(ControlFlow::new_while(None, cond, block, label, expr.span)) + } + ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( + ControlFlow::new_while(Some(pat), cond, block, label, expr.span), + ), + _ => None, + } +} + +impl<'a> ControlFlow<'a> { + fn new_if( + cond: &'a ast::Expr, + pat: Option<&'a ast::Pat>, + block: &'a ast::Block, + else_block: Option<&'a ast::Expr>, + allow_single_line: bool, + nested_if: bool, + span: Span, + ) -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block, + else_block, + label: None, + pat, + keyword: "if", + matcher: match pat { + Some(..) => "let", + None => "", + }, + connector: " =", + allow_single_line, + nested_if, + span, + } + } + + fn new_loop(block: &'a ast::Block, label: Option, span: Span) -> ControlFlow<'a> { + ControlFlow { + cond: None, + block, + else_block: None, + label, + pat: None, + keyword: "loop", + matcher: "", + connector: "", + allow_single_line: false, + nested_if: false, + span, + } + } + + fn new_while( + pat: Option<&'a ast::Pat>, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block, + else_block: None, + label, + pat, + keyword: "while", + matcher: match pat { + Some(..) => "let", + None => "", + }, + connector: " =", + allow_single_line: false, + nested_if: false, + span, + } + } + + fn new_for( + pat: &'a ast::Pat, + cond: &'a ast::Expr, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { + ControlFlow { + cond: Some(cond), + block, + else_block: None, + label, + pat: Some(pat), + keyword: "for", + matcher: "", + connector: " in", + allow_single_line: false, + nested_if: false, + span, + } + } + + fn rewrite_single_line( + &self, + pat_expr_str: &str, + context: &RewriteContext, + width: usize, + ) -> Option { + assert!(self.allow_single_line); + let else_block = self.else_block?; + let fixed_cost = self.keyword.len() + " { } else { }".len(); + + if let ast::ExprKind::Block(ref else_node) = else_block.node { + if !is_simple_block(self.block, context.codemap) + || !is_simple_block(else_node, context.codemap) + || pat_expr_str.contains('\n') + { + return None; + } + + let new_width = width.checked_sub(pat_expr_str.len() + fixed_cost)?; + let expr = &self.block.stmts[0]; + let if_str = expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; + + let new_width = new_width.checked_sub(if_str.len())?; + let else_expr = &else_node.stmts[0]; + let else_str = else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty()))?; + + if if_str.contains('\n') || else_str.contains('\n') { + return None; + } + + let result = format!( + "{} {} {{ {} }} else {{ {} }}", + self.keyword, pat_expr_str, if_str, else_str + ); + + if result.len() <= width { + return Some(result); + } + } + + None + } +} + +impl<'a> ControlFlow<'a> { + fn rewrite_cond( + &self, + context: &RewriteContext, + shape: Shape, + alt_block_sep: &str, + ) -> Option<(String, usize)> { + // Do not take the rhs overhead from the upper expressions into account + // when rewriting pattern. + let new_width = context + .config + .max_width() + .checked_sub(shape.used_width()) + .unwrap_or(0); + let fresh_shape = Shape { + width: new_width, + ..shape + }; + let constr_shape = if self.nested_if { + // We are part of an if-elseif-else chain. Our constraints are tightened. + // 7 = "} else " .len() + fresh_shape.offset_left(7)? + } else { + fresh_shape + }; + + let label_string = rewrite_label(self.label); + // 1 = space after keyword. + let offset = self.keyword.len() + label_string.len() + 1; + + let pat_expr_string = match self.cond { + Some(cond) => rewrite_pat_expr( + context, + self.pat, + cond, + self.matcher, + self.connector, + self.keyword, + constr_shape, + offset, + )?, + None => String::new(), + }; + + let brace_overhead = + if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine { + // 2 = ` {` + 2 + } else { + 0 + }; + let one_line_budget = context + .config + .max_width() + .checked_sub(constr_shape.used_width() + offset + brace_overhead) + .unwrap_or(0); + let force_newline_brace = (pat_expr_string.contains('\n') + || pat_expr_string.len() > one_line_budget) + && !last_line_extendable(&pat_expr_string); + + // Try to format if-else on single line. + if self.allow_single_line + && context + .config + .width_heuristics() + .single_line_if_else_max_width > 0 + { + let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); + + if let Some(cond_str) = trial { + if cond_str.len() + <= context + .config + .width_heuristics() + .single_line_if_else_max_width + { + return Some((cond_str, 0)); + } + } + } + + let cond_span = if let Some(cond) = self.cond { + cond.span + } else { + mk_sp(self.block.span.lo(), self.block.span.lo()) + }; + + // `for event in event` + // Do not include label in the span. + let lo = self.label.map_or(self.span.lo(), |label| label.span.hi()); + let between_kwd_cond = mk_sp( + context + .snippet_provider + .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), + self.pat.map_or(cond_span.lo(), |p| { + if self.matcher.is_empty() { + p.span.lo() + } else { + context + .snippet_provider + .span_before(self.span, self.matcher.trim()) + } + }), + ); + + let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); + + let after_cond_comment = + extract_comment(mk_sp(cond_span.hi(), self.block.span.lo()), context, shape); + + let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() { + "" + } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine + || force_newline_brace + { + alt_block_sep + } else { + " " + }; + + let used_width = if pat_expr_string.contains('\n') { + last_line_width(&pat_expr_string) + } else { + // 2 = spaces after keyword and condition. + label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 + }; + + Some(( + format!( + "{}{}{}{}{}", + label_string, + self.keyword, + between_kwd_cond_comment.as_ref().map_or( + if pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { + "" + } else { + " " + }, + |s| &**s, + ), + pat_expr_string, + after_cond_comment.as_ref().map_or(block_sep, |s| &**s) + ), + used_width, + )) + } +} + +impl<'a> Rewrite for ControlFlow<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("ControlFlow::rewrite {:?} {:?}", self, shape); + + let alt_block_sep = &shape.indent.to_string_with_newline(context.config); + let (cond_str, used_width) = self.rewrite_cond(context, shape, alt_block_sep)?; + // If `used_width` is 0, it indicates that whole control flow is written in a single line. + if used_width == 0 { + return Some(cond_str); + } + + let block_width = shape.width.checked_sub(used_width).unwrap_or(0); + // This is used only for the empty block case: `{}`. So, we use 1 if we know + // we should avoid the single line case. + let block_width = if self.else_block.is_some() || self.nested_if { + min(1, block_width) + } else { + block_width + }; + let block_shape = Shape { + width: block_width, + ..shape + }; + let mut block_context = context.clone(); + block_context.is_if_else_block = self.else_block.is_some(); + let block_str = + rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?; + + let mut result = format!("{}{}", cond_str, block_str); + + if let Some(else_block) = self.else_block { + let shape = Shape::indented(shape.indent, context.config); + let mut last_in_chain = false; + let rewrite = match else_block.node { + // If the else expression is another if-else expression, prevent it + // from being formatted on a single line. + // Note how we're passing the original shape, as the + // cost of "else" should not cascade. + ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { + ControlFlow::new_if( + cond, + Some(pat), + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo(), self.span.hi()), + ).rewrite(context, shape) + } + ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { + ControlFlow::new_if( + cond, + None, + if_block, + next_else_block.as_ref().map(|e| &**e), + false, + true, + mk_sp(else_block.span.lo(), self.span.hi()), + ).rewrite(context, shape) + } + _ => { + last_in_chain = true; + // When rewriting a block, the width is only used for single line + // blocks, passing 1 lets us avoid that. + let else_shape = Shape { + width: min(1, shape.width), + ..shape + }; + format_expr(else_block, ExprType::Statement, context, else_shape) + } + }; + + let between_kwd_else_block = mk_sp( + self.block.span.hi(), + context + .snippet_provider + .span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), + ); + let between_kwd_else_block_comment = + extract_comment(between_kwd_else_block, context, shape); + + let after_else = mk_sp( + context + .snippet_provider + .span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"), + else_block.span.lo(), + ); + let after_else_comment = extract_comment(after_else, context, shape); + + let between_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine | ControlBraceStyle::ClosingNextLine => { + &*alt_block_sep + } + ControlBraceStyle::AlwaysSameLine => " ", + }; + let after_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep, + _ => " ", + }; + + result.push_str(&format!( + "{}else{}", + between_kwd_else_block_comment + .as_ref() + .map_or(between_sep, |s| &**s), + after_else_comment.as_ref().map_or(after_sep, |s| &**s), + )); + result.push_str(&rewrite?); + } + + Some(result) + } +} + +fn rewrite_label(opt_label: Option) -> Cow<'static, str> { + match opt_label { + Some(label) => Cow::from(format!("{}: ", label.ident)), + None => Cow::from(""), + } +} + +fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { + match rewrite_missing_comment(span, shape, context) { + Some(ref comment) if !comment.is_empty() => Some(format!( + "{indent}{}{indent}", + comment, + indent = shape.indent.to_string_with_newline(context.config) + )), + _ => None, + } +} + +pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { + let snippet = codemap.span_to_snippet(block.span).unwrap(); + contains_comment(&snippet) +} + +// Checks that a block contains no statements, an expression and no comments. +// FIXME: incorrectly returns false when comment is contained completely within +// the expression. +pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { + (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) + && !block_contains_comment(block, codemap)) +} + +/// Checks whether a block contains at most one statement or expression, and no comments. +pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { + block.stmts.len() <= 1 && !block_contains_comment(block, codemap) +} + +/// Checks whether a block contains no statements, expressions, or comments. +pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { + block.stmts.is_empty() && !block_contains_comment(block, codemap) +} + +pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::StmtKind::Expr(..) => true, + _ => false, + } +} + +pub fn is_unsafe_block(block: &ast::Block) -> bool { + if let ast::BlockCheckMode::Unsafe(..) = block.rules { + true + } else { + false + } +} + +// A simple wrapper type against ast::Arm. Used inside write_list(). +struct ArmWrapper<'a> { + pub arm: &'a ast::Arm, + // True if the arm is the last one in match expression. Used to decide on whether we should add + // trailing comma to the match arm when `config.trailing_comma() == Never`. + pub is_last: bool, +} + +impl<'a> ArmWrapper<'a> { + pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> { + ArmWrapper { arm, is_last } + } +} + +impl<'a> Rewrite for ArmWrapper<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_match_arm(context, self.arm, shape, self.is_last) + } +} + +fn rewrite_match( + context: &RewriteContext, + cond: &ast::Expr, + arms: &[ast::Arm], + shape: Shape, + span: Span, + attrs: &[ast::Attribute], +) -> Option { + // Do not take the rhs overhead from the upper expressions into account + // when rewriting match condition. + let cond_shape = Shape { + width: context.budget(shape.used_width()), + ..shape + }; + // 6 = `match ` + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => cond_shape.shrink_left(6)?, + IndentStyle::Block => cond_shape.offset_left(6)?, + }; + let cond_str = cond.rewrite(context, cond_shape)?; + let alt_block_sep = &shape.indent.to_string_with_newline(context.config); + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine => alt_block_sep, + _ if last_line_extendable(&cond_str) => " ", + // 2 = ` {` + _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => alt_block_sep, + _ => " ", + }; + + let nested_indent_str = shape + .indent + .block_indent(context.config) + .to_string(context.config); + // Inner attributes. + let inner_attrs = &inner_attributes(attrs); + let inner_attrs_str = if inner_attrs.is_empty() { + String::new() + } else { + inner_attrs + .rewrite(context, shape) + .map(|s| format!("{}{}\n", nested_indent_str, s))? + }; + + let open_brace_pos = if inner_attrs.is_empty() { + let hi = if arms.is_empty() { + span.hi() + } else { + arms[0].span().lo() + }; + context + .snippet_provider + .span_after(mk_sp(cond.span.hi(), hi), "{") + } else { + inner_attrs[inner_attrs.len() - 1].span().hi() + }; + + if arms.is_empty() { + let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); + if snippet.trim().is_empty() { + Some(format!("match {} {{}}", cond_str)) + } else { + // Empty match with comments or inner attributes? We are not going to bother, sorry ;) + Some(context.snippet(span).to_owned()) + } + } else { + Some(format!( + "match {}{}{{\n{}{}{}\n{}}}", + cond_str, + block_sep, + inner_attrs_str, + nested_indent_str, + rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, + shape.indent.to_string(context.config), + )) + } +} + +fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { + if is_last && config.trailing_comma() == SeparatorTactic::Never { + "" + } else if config.match_block_trailing_comma() { + "," + } else if let ast::ExprKind::Block(ref block) = body.node { + if let ast::BlockCheckMode::Default = block.rules { + "" + } else { + "," + } + } else { + "," + } +} + +fn rewrite_match_arms( + context: &RewriteContext, + arms: &[ast::Arm], + shape: Shape, + span: Span, + open_brace_pos: BytePos, +) -> Option { + let arm_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + + let arm_len = arms.len(); + let is_last_iter = repeat(false) + .take(arm_len.checked_sub(1).unwrap_or(0)) + .chain(repeat(true)); + let items = itemize_list( + context.snippet_provider, + arms.iter() + .zip(is_last_iter) + .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), + "}", + "|", + |arm| arm.arm.span().lo(), + |arm| arm.arm.span().hi(), + |arm| arm.rewrite(context, arm_shape), + open_brace_pos, + span.hi(), + false, + ); + let arms_vec: Vec<_> = items.collect(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arm_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + + write_list(&arms_vec, &fmt) +} + +fn rewrite_match_arm( + context: &RewriteContext, + arm: &ast::Arm, + shape: Shape, + is_last: bool, +) -> Option { + let (missing_span, attrs_str) = if !arm.attrs.is_empty() { + if contains_skip(&arm.attrs) { + let (_, body) = flatten_arm_body(context, &arm.body); + // `arm.span()` does not include trailing comma, add it manually. + return Some(format!( + "{}{}", + context.snippet(arm.span()), + arm_comma(context.config, body, is_last), + )); + } + let missing_span = mk_sp( + arm.attrs[arm.attrs.len() - 1].span.hi(), + arm.pats[0].span.lo(), + ); + (missing_span, arm.attrs.rewrite(context, shape)?) + } else { + (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) + }; + let pats_str = rewrite_match_pattern( + context, + &arm.pats, + &arm.guard, + arm.beginning_vert.is_some(), + shape, + ).and_then(|pats_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &pats_str, + missing_span, + shape, + false, + ) + })?; + rewrite_match_body( + context, + &arm.body, + &pats_str, + shape, + arm.guard.is_some(), + is_last, + ) +} + +/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: +/// +/// [small, ntp]: +/// - single token +/// - `&[single-line, ntp]` +/// +/// [small]: +/// - `[small, ntp]` +/// - unary tuple constructor `([small, ntp])` +/// - `&[small]` +fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { + // We also require that the pattern is reasonably 'small' with its literal width. + pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) +} + +fn is_short_pattern_inner(pat: &ast::Pat) -> bool { + match pat.node { + ast::PatKind::Wild | ast::PatKind::Lit(_) => true, + ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), + ast::PatKind::Struct(..) + | ast::PatKind::Mac(..) + | ast::PatKind::Slice(..) + | ast::PatKind::Path(..) + | ast::PatKind::Range(..) => false, + ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, + ast::PatKind::TupleStruct(ref path, ref subpats, _) => { + path.segments.len() <= 1 && subpats.len() <= 1 + } + ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p), + } +} + +fn rewrite_match_pattern( + context: &RewriteContext, + pats: &[ptr::P], + guard: &Option>, + has_beginning_vert: bool, + shape: Shape, +) -> Option { + // Patterns + // 5 = ` => {` + // 2 = `| ` + let pat_shape = shape + .sub_width(5)? + .offset_left(if has_beginning_vert { 2 } else { 0 })?; + + let pat_strs = pats.iter() + .map(|p| p.rewrite(context, pat_shape)) + .collect::>>()?; + + let use_mixed_layout = pats.iter() + .zip(pat_strs.iter()) + .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let tactic = if use_mixed_layout { + DefinitiveListTactic::Mixed + } else { + definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + pat_shape.width, + ) + }; + let fmt = ListFormatting { + tactic, + separator: " |", + trailing_separator: SeparatorTactic::Never, + separator_place: context.config.binop_separator(), + shape: pat_shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + let pats_str = write_list(&items, &fmt)?; + let beginning_vert = if has_beginning_vert { "| " } else { "" }; + + // Guard + let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; + + Some(format!("{}{}{}", beginning_vert, pats_str, guard_str)) +} + +// (extend, body) +// @extend: true if the arm body can be put next to `=>` +// @body: flattened body, if the body is block with a single expression +fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { + match body.node { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { + ( + !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), + &*expr, + ) + } else { + (false, &*body) + } + } + _ => ( + !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), + &*body, + ), + } +} + +fn rewrite_match_body( + context: &RewriteContext, + body: &ptr::P, + pats_str: &str, + shape: Shape, + has_guard: bool, + is_last: bool, +) -> Option { + let (extend, body) = flatten_arm_body(context, body); + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { + (true, is_empty_block(block, context.codemap)) + } else { + (false, false) + }; + + let comma = arm_comma(context.config, body, is_last); + let alt_block_sep = &shape.indent.to_string_with_newline(context.config); + + let combine_orig_body = |body_str: &str| { + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, + _ => " ", + }; + + Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) + }; + + let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; + let next_line_indent = if !is_block || is_empty_block { + shape.indent.block_indent(context.config) + } else { + shape.indent + }; + let combine_next_line_body = |body_str: &str| { + if is_block { + return Some(format!( + "{} =>{}{}", + pats_str, + next_line_indent.to_string_with_newline(context.config), + body_str + )); + } + + let indent_str = shape.indent.to_string_with_newline(context.config); + let nested_indent_str = next_line_indent.to_string_with_newline(context.config); + let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { + let comma = if context.config.match_block_trailing_comma() { + "," + } else { + "" + }; + ("{", format!("{}}}{}", indent_str, comma)) + } else { + ("", String::from(",")) + }; + + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), + _ if body_prefix.is_empty() => "".to_owned(), + _ if forbid_same_line => format!("{}{}", alt_block_sep, body_prefix), + _ => format!(" {}", body_prefix), + } + &nested_indent_str; + + Some(format!( + "{} =>{}{}{}", + pats_str, block_sep, body_str, body_suffix + )) + }; + + // Let's try and get the arm body on the same line as the condition. + // 4 = ` => `.len() + let orig_body_shape = shape + .offset_left(extra_offset(pats_str, shape) + 4) + .and_then(|shape| shape.sub_width(comma.len())); + let orig_body = if let Some(body_shape) = orig_body_shape { + let rewrite = nop_block_collapse( + format_expr(body, ExprType::Statement, context, body_shape), + body_shape.width, + ); + + match rewrite { + Some(ref body_str) + if !forbid_same_line + && (is_block + || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => + { + return combine_orig_body(body_str); + } + _ => rewrite, + } + } else { + None + }; + let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); + + // Try putting body on the next line and see if it looks better. + let next_line_body_shape = Shape::indented(next_line_indent, context.config); + let next_line_body = nop_block_collapse( + format_expr(body, ExprType::Statement, context, next_line_body_shape), + next_line_body_shape.width, + ); + match (orig_body, next_line_body) { + (Some(ref orig_str), Some(ref next_line_str)) + if forbid_same_line || prefer_next_line(orig_str, next_line_str) => + { + combine_next_line_body(next_line_str) + } + (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { + combine_orig_body(orig_str) + } + (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { + combine_next_line_body(next_line_str) + } + (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), + (None, None) => None, + (Some(ref orig_str), _) => combine_orig_body(orig_str), + } +} + +// The `if ...` guard on a match arm. +fn rewrite_guard( + context: &RewriteContext, + guard: &Option>, + shape: Shape, + // The amount of space used up on this line for the pattern in + // the arm (excludes offset). + pattern_width: usize, +) -> Option { + if let Some(ref guard) = *guard { + // First try to fit the guard string on the same line as the pattern. + // 4 = ` if `, 5 = ` => {` + let cond_shape = shape + .offset_left(pattern_width + 4) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { + return Some(format!(" if {}", cond_str)); + } + } + } + + // Not enough space to put the guard after the pattern, try a newline. + // 3 = `if `, 5 = ` => {` + let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) + .offset_left(3) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + return Some(format!( + "{}if {}", + cond_shape.indent.to_string_with_newline(context.config), + cond_str + )); + } + } + + None + } else { + Some(String::new()) + } +} + +fn rewrite_pat_expr( + context: &RewriteContext, + pat: Option<&ast::Pat>, + expr: &ast::Expr, + matcher: &str, + // Connecting piece between pattern and expression, + // *without* trailing space. + connector: &str, + keyword: &str, + shape: Shape, + offset: usize, +) -> Option { + debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); + let cond_shape = shape.offset_left(offset)?; + if let Some(pat) = pat { + let matcher = if matcher.is_empty() { + matcher.to_owned() + } else { + format!("{} ", matcher) + }; + let pat_shape = cond_shape + .offset_left(matcher.len())? + .sub_width(connector.len())?; + let pat_string = pat.rewrite(context, pat_shape)?; + let result = format!("{}{}{}", matcher, pat_string, connector); + return rewrite_assign_rhs(context, result, expr, cond_shape); + } + + let expr_rw = expr.rewrite(context, cond_shape); + // The expression may (partially) fit on the current line. + // We do not allow splitting between `if` and condition. + if keyword == "if" || expr_rw.is_some() { + return expr_rw; + } + + // The expression won't fit on the current line, jump to next. + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); + expr.rewrite(context, nested_shape) + .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw)) +} + +fn can_extend_match_arm_body(body: &ast::Expr) -> bool { + match body.node { + // We do not allow `if` to stay on the same line, since we could easily mistake + // `pat => if cond { ... }` and `pat if cond => { ... }`. + ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, + ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Closure(..) + | ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), + _ => false, + } +} + +pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { + match l.node { + ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), + _ => wrap_str( + context.snippet(l.span).to_owned(), + context.config.max_width(), + shape, + ), + } +} + +fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { + let string_lit = context.snippet(span); + + if !context.config.format_strings() { + if string_lit + .lines() + .rev() + .skip(1) + .all(|line| line.ends_with('\\')) + { + let new_indent = shape.visual_indent(1).indent; + let indented_string_lit = String::from( + string_lit + .lines() + .map(|line| { + format!( + "{}{}", + new_indent.to_string(context.config), + line.trim_left() + ) + }) + .collect::>() + .join("\n") + .trim_left(), + ); + return wrap_str(indented_string_lit, context.config.max_width(), shape); + } else { + return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); + } + } + + // Remove the quote characters. + let str_lit = &string_lit[1..string_lit.len() - 1]; + + rewrite_string( + str_lit, + &StringFormat::new(shape.visual_indent(0), context.config), + None, + ) +} + +/// A list of `format!`-like macros, that take a long format string and a list of arguments to +/// format. +/// +/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of +/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, +/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). +const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ + // format! like macros + // From the Rust Standard Library. + ("eprint!", 0), + ("eprintln!", 0), + ("format!", 0), + ("format_args!", 0), + ("print!", 0), + ("println!", 0), + ("panic!", 0), + ("unreachable!", 0), + // From the `log` crate. + ("debug!", 0), + ("error!", 0), + ("info!", 0), + ("warn!", 0), + // write! like macros + ("assert!", 1), + ("debug_assert!", 1), + ("write!", 1), + ("writeln!", 1), + // assert_eq! like macros + ("assert_eq!", 2), + ("assert_ne!", 2), + ("debug_assert_eq!", 2), + ("debug_assert_ne!", 2), +]; + +pub fn rewrite_call( + context: &RewriteContext, + callee: &str, + args: &[ptr::P], + span: Span, + shape: Shape, +) -> Option { + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + false + }; + rewrite_call_inner( + context, + callee, + &ptr_vec_to_ref_vec(args), + span, + shape, + context.config.width_heuristics().fn_call_width, + force_trailing_comma, + ) +} + +pub fn rewrite_call_inner<'a, T>( + context: &RewriteContext, + callee_str: &str, + args: &[&T], + span: Span, + shape: Shape, + args_max_width: usize, + force_trailing_comma: bool, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + // 2 = `( `, 1 = `(` + let paren_overhead = if context.config.spaces_within_parens_and_brackets() { + 2 + } else { + 1 + }; + let used_width = extra_offset(callee_str, shape); + let one_line_width = shape + .width + .checked_sub(used_width + 2 * paren_overhead) + .unwrap_or(0); + + // 1 = "(" or ")" + let one_line_shape = shape + .offset_left(last_line_width(callee_str) + 1) + .and_then(|shape| shape.sub_width(1)) + .unwrap_or(Shape { width: 0, ..shape }); + let nested_shape = shape_from_indent_style( + context, + shape, + used_width + 2 * paren_overhead, + used_width + paren_overhead, + )?; + + let span_lo = context.snippet_provider.span_after(span, "("); + let args_span = mk_sp(span_lo, span.hi()); + + let (extendable, list_str) = rewrite_call_args( + context, + args, + args_span, + one_line_shape, + nested_shape, + one_line_width, + args_max_width, + force_trailing_comma, + callee_str, + )?; + + if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { + let mut new_context = context.clone(); + new_context.use_block = true; + return rewrite_call_inner( + &new_context, + callee_str, + args, + span, + shape, + args_max_width, + force_trailing_comma, + ); + } + + let args_shape = Shape { + width: shape + .width + .checked_sub(last_line_width(callee_str)) + .unwrap_or(0), + ..shape + }; + Some(format!( + "{}{}", + callee_str, + wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) + )) +} + +fn need_block_indent(s: &str, shape: Shape) -> bool { + s.lines().skip(1).any(|s| { + s.find(|c| !char::is_whitespace(c)) + .map_or(false, |w| w + 1 < shape.indent.width()) + }) +} + +fn rewrite_call_args<'a, T>( + context: &RewriteContext, + args: &[&T], + span: Span, + one_line_shape: Shape, + nested_shape: Shape, + one_line_width: usize, + args_max_width: usize, + force_trailing_comma: bool, + callee_str: &str, +) -> Option<(bool, String)> +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + let items = itemize_list( + context.snippet_provider, + args.iter(), + ")", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, nested_shape), + span.lo(), + span.hi(), + true, + ); + let mut item_vec: Vec<_> = items.collect(); + + // Try letting the last argument overflow to the next line with block + // indentation. If its first line fits on one line with the other arguments, + // we format the function arguments horizontally. + let tactic = try_overflow_last_arg( + context, + &mut item_vec, + &args[..], + one_line_shape, + nested_shape, + one_line_width, + args_max_width, + callee_str, + ); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if force_trailing_comma { + SeparatorTactic::Always + } else if context.inside_macro || !context.use_block_indent() { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape: nested_shape, + ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, + preserve_newline: false, + config: context.config, + }; + + write_list(&item_vec, &fmt) + .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str)) +} + +fn try_overflow_last_arg<'a, T>( + context: &RewriteContext, + item_vec: &mut Vec, + args: &[&T], + one_line_shape: Shape, + nested_shape: Shape, + one_line_width: usize, + args_max_width: usize, + callee_str: &str, +) -> DefinitiveListTactic +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + // 1 = "(" + let combine_arg_with_callee = + callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; + let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); + + // Replace the last item with its first line to see if it fits with + // first arguments. + let placeholder = if overflow_last { + let mut context = context.clone(); + if !combine_arg_with_callee { + if let Some(expr) = args[args.len() - 1].to_expr() { + if let ast::ExprKind::MethodCall(..) = expr.node { + context.force_one_line_chain = true; + } + } + } + last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { + rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) + }) + } else { + None + }; + + let mut tactic = definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ); + + // Replace the stub with the full overflowing last argument if the rewrite + // succeeded and its first line fits with the other arguments. + match (overflow_last, tactic, placeholder) { + (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) if args.len() == 1 => { + // When we are rewriting a nested function call, we restrict the + // bugdet for the inner function to avoid them being deeply nested. + // However, when the inner function has a prefix or a suffix + // (e.g. `foo() as u32`), this budget reduction may produce poorly + // formatted code, where a prefix or a suffix being left on its own + // line. Here we explicitlly check those cases. + if count_newlines(overflowed) == 1 { + let rw = args.last() + .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); + let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); + if no_newline { + item_vec[args.len() - 1].item = rw; + } else { + item_vec[args.len() - 1].item = Some(overflowed.to_owned()); + } + } else { + item_vec[args.len() - 1].item = Some(overflowed.to_owned()); + } + } + (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { + item_vec[args.len() - 1].item = placeholder; + } + _ if args.len() >= 1 => { + item_vec[args.len() - 1].item = args.last() + .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); + + let default_tactic = || { + definitive_tactic( + &*item_vec, + ListTactic::LimitedHorizontalVertical(args_max_width), + Separator::Comma, + one_line_width, + ) + }; + + // Use horizontal layout for a function with a single argument as long as + // everything fits in a single line. + if args.len() == 1 + && args_max_width != 0 // Vertical layout is forced. + && !item_vec[0].has_comment() + && !item_vec[0].inner_as_ref().contains('\n') + && ::lists::total_item_width(&item_vec[0]) <= one_line_width + { + tactic = DefinitiveListTactic::Horizontal; + } else { + tactic = default_tactic(); + + if tactic == DefinitiveListTactic::Vertical { + if let Some((all_simple, num_args_before)) = + maybe_get_args_offset(callee_str, args) + { + let one_line = all_simple + && definitive_tactic( + &item_vec[..num_args_before], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ) == DefinitiveListTactic::Horizontal + && definitive_tactic( + &item_vec[num_args_before + 1..], + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ) == DefinitiveListTactic::Horizontal; + + if one_line { + tactic = DefinitiveListTactic::SpecialMacro(num_args_before); + }; + } + } + } + } + _ => (), + } + + tactic +} + +fn is_simple_arg(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Lit(..) => true, + ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Cast(ref expr, _) + | ast::ExprKind::Field(ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::TupField(ref expr, _) + | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr), + ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { + is_simple_arg(lhs) && is_simple_arg(rhs) + } + _ => false, + } +} + +fn is_every_args_simple(lists: &[&T]) -> bool { + lists + .iter() + .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) +} + +/// In case special-case style is required, returns an offset from which we start horizontal layout. +fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { + if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST + .iter() + .find(|&&(s, _)| s == callee_str) + { + let all_simple = args.len() > num_args_before && is_every_args_simple(args); + + Some((all_simple, num_args_before)) + } else { + None + } +} + +/// Returns a shape for the last argument which is going to be overflowed. +fn last_arg_shape( + lists: &[&T], + items: &[ListItem], + shape: Shape, + args_max_width: usize, +) -> Option +where + T: Rewrite + Spanned + ToExpr, +{ + let is_nested_call = lists + .iter() + .next() + .and_then(|item| item.to_expr()) + .map_or(false, is_nested_call); + if items.len() == 1 && !is_nested_call { + return Some(shape); + } + let offset = items.iter().rev().skip(1).fold(0, |acc, i| { + // 2 = ", " + acc + 2 + i.inner_as_ref().len() + }); + Shape { + width: min(args_max_width, shape.width), + ..shape + }.offset_left(offset) +} + +fn rewrite_last_arg_with_overflow<'a, T>( + context: &RewriteContext, + args: &[&T], + last_item: &mut ListItem, + shape: Shape, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + let last_arg = args[args.len() - 1]; + let rewrite = if let Some(expr) = last_arg.to_expr() { + match expr.node { + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + ast::ExprKind::Closure(..) => { + // If the argument consists of multiple closures, we do not overflow + // the last closure. + if closures::args_have_many_closure(args) { + None + } else { + closures::rewrite_last_closure(context, expr, shape) + } + } + _ => expr.rewrite(context, shape), + } + } else { + last_arg.rewrite(context, shape) + }; + + if let Some(rewrite) = rewrite { + let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); + last_item.item = rewrite_first_line; + Some(rewrite) + } else { + None + } +} + +fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + args.last() + .map_or(false, |x| x.can_be_overflowed(context, args.len())) +} + +pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { + match expr.node { + ast::ExprKind::Match(..) => { + (context.use_block_indent() && args_len == 1) + || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) + } + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) => { + context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 + } + ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { + context.use_block_indent() + || context.config.indent_style() == IndentStyle::Visual && args_len > 1 + } + ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len), + _ => false, + } +} + +fn is_nested_call(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr), + _ => false, + } +} + +pub fn wrap_args_with_parens( + context: &RewriteContext, + args_str: &str, + is_extendable: bool, + shape: Shape, + nested_shape: Shape, +) -> String { + let paren_overhead = paren_overhead(context); + let fits_one_line = args_str.len() + paren_overhead <= shape.width; + let extend_width = if args_str.is_empty() { + paren_overhead + } else { + paren_overhead / 2 + }; + if !context.use_block_indent() + || (context.inside_macro && !args_str.contains('\n') && fits_one_line) + || (is_extendable && extend_width <= shape.width) + { + let mut result = String::with_capacity(args_str.len() + 4); + if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() { + result.push_str("( "); + result.push_str(args_str); + result.push_str(" )"); + } else { + result.push_str("("); + result.push_str(args_str); + result.push_str(")"); + } + result + } else { + let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); + let indent_str = shape.block().indent.to_string_with_newline(context.config); + let mut result = + String::with_capacity(args_str.len() + 2 + indent_str.len() + nested_indent_str.len()); + result.push_str("("); + if !args_str.is_empty() { + result.push_str(&nested_indent_str); + result.push_str(args_str); + } + result.push_str(&indent_str); + result.push_str(")"); + result + } +} + +/// Return true if a function call or a method call represented by the given span ends with a +/// trailing comma. This function is used when rewriting macro, as adding or removing a trailing +/// comma from macro can potentially break the code. +fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { + let mut encountered_closing_paren = false; + for c in context.snippet(span).chars().rev() { + match c { + ',' => return true, + ')' => if encountered_closing_paren { + return false; + } else { + encountered_closing_paren = true; + }, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + false +} + +fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { + debug!("rewrite_paren, shape: {:?}", shape); + let total_paren_overhead = paren_overhead(context); + let paren_overhead = total_paren_overhead / 2; + let sub_shape = shape + .offset_left(paren_overhead) + .and_then(|s| s.sub_width(paren_overhead))?; + + let paren_wrapper = |s: &str| { + if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { + format!("( {} )", s) + } else { + format!("({})", s) + } + }; + + let subexpr_str = subexpr.rewrite(context, sub_shape)?; + debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); + + if subexpr_str.contains('\n') + || first_line_width(&subexpr_str) + total_paren_overhead <= shape.width + { + Some(paren_wrapper(&subexpr_str)) + } else { + None + } +} + +fn rewrite_index( + expr: &ast::Expr, + index: &ast::Expr, + context: &RewriteContext, + shape: Shape, +) -> Option { + let expr_str = expr.rewrite(context, shape)?; + + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + + let offset = last_line_width(&expr_str) + lbr.len(); + let rhs_overhead = shape.rhs_overhead(context.config); + let index_shape = if expr_str.contains('\n') { + Shape::legacy(context.config.max_width(), shape.indent) + .offset_left(offset) + .and_then(|shape| shape.sub_width(rbr.len() + rhs_overhead)) + } else { + shape.visual_indent(offset).sub_width(offset + rbr.len()) + }; + let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); + + // Return if index fits in a single line. + match orig_index_rw { + Some(ref index_str) if !index_str.contains('\n') => { + return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); + } + _ => (), + } + + // Try putting index on the next line and see if it fits in a single line. + let indent = shape.indent.block_indent(context.config); + let index_shape = Shape::indented(indent, context.config).offset_left(lbr.len())?; + let index_shape = index_shape.sub_width(rbr.len() + rhs_overhead)?; + let new_index_rw = index.rewrite(context, index_shape); + match (orig_index_rw, new_index_rw) { + (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( + "{}{}{}{}{}", + expr_str, + indent.to_string_with_newline(context.config), + lbr, + new_index_str, + rbr + )), + (None, Some(ref new_index_str)) => Some(format!( + "{}{}{}{}{}", + expr_str, + indent.to_string_with_newline(context.config), + lbr, + new_index_str, + rbr + )), + (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), + _ => None, + } +} + +fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { + if base.is_some() { + return false; + } + + fields.iter().all(|field| !field.is_shorthand) +} + +fn rewrite_struct_lit<'a>( + context: &RewriteContext, + path: &ast::Path, + fields: &'a [ast::Field], + base: Option<&'a ast::Expr>, + span: Span, + shape: Shape, +) -> Option { + debug!("rewrite_struct_lit: shape {:?}", shape); + + enum StructLitField<'a> { + Regular(&'a ast::Field), + Base(&'a ast::Expr), + } + + // 2 = " {".len() + let path_shape = shape.sub_width(2)?; + let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; + + if fields.is_empty() && base.is_none() { + return Some(format!("{} {{}}", path_str)); + } + + // Foo { a: Foo } - indent is +3, width is -5. + let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; + + let one_line_width = h_shape.map_or(0, |shape| shape.width); + let body_lo = context.snippet_provider.span_after(span, "{"); + let fields_str = if struct_lit_can_be_aligned(fields, &base) + && context.config.struct_field_align_threshold() > 0 + { + rewrite_with_alignment( + fields, + context, + shape, + mk_sp(body_lo, span.hi()), + one_line_width, + )? + } else { + let field_iter = fields + .into_iter() + .map(StructLitField::Regular) + .chain(base.into_iter().map(StructLitField::Base)); + + let span_lo = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span().lo(), + StructLitField::Base(expr) => { + let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }; + let span_hi = |item: &StructLitField| match *item { + StructLitField::Regular(field) => field.span().hi(), + StructLitField::Base(expr) => expr.span.hi(), + }; + let rewrite = |item: &StructLitField| match *item { + StructLitField::Regular(field) => { + // The 1 taken from the v_budget is for the comma. + rewrite_field(context, field, v_shape.sub_width(1)?, 0) + } + StructLitField::Base(expr) => { + // 2 = .. + expr.rewrite(context, v_shape.offset_left(2)?) + .map(|s| format!("..{}", s)) + } + }; + + let items = itemize_list( + context.snippet_provider, + field_iter, + "}", + ",", + span_lo, + span_hi, + rewrite, + body_lo, + span.hi(), + false, + ); + let item_vec = items.collect::>(); + + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); + + write_list(&item_vec, &fmt)? + }; + + let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + Some(format!("{} {{{}}}", path_str, fields_str)) + + // FIXME if context.config.indent_style() == Visual, but we run out + // of space, we should fall back to BlockIndent. +} + +pub fn wrap_struct_field( + context: &RewriteContext, + fields_str: &str, + shape: Shape, + nested_shape: Shape, + one_line_width: usize, +) -> String { + if context.config.indent_style() == IndentStyle::Block + && (fields_str.contains('\n') || !context.config.struct_lit_single_line() + || fields_str.len() > one_line_width) + { + format!( + "{}{}{}", + nested_shape.indent.to_string_with_newline(context.config), + fields_str, + shape.indent.to_string_with_newline(context.config) + ) + } else { + // One liner or visual indent. + format!(" {} ", fields_str) + } +} + +pub fn struct_lit_field_separator(config: &Config) -> &str { + colon_spaces(config.space_before_colon(), config.space_after_colon()) +} + +pub fn rewrite_field( + context: &RewriteContext, + field: &ast::Field, + shape: Shape, + prefix_max_width: usize, +) -> Option { + if contains_skip(&field.attrs) { + return Some(context.snippet(field.span()).to_owned()); + } + let mut attrs_str = field.attrs.rewrite(context, shape)?; + if !attrs_str.is_empty() { + attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); + }; + let name = field.ident.node.to_string(); + if field.is_shorthand { + Some(attrs_str + &name) + } else { + let mut separator = String::from(struct_lit_field_separator(context.config)); + for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { + separator.push(' '); + } + let overhead = name.len() + separator.len(); + let expr_shape = shape.offset_left(overhead)?; + let expr = field.expr.rewrite(context, expr_shape); + + match expr { + Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { + Some(attrs_str + &name) + } + Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), + None => { + let expr_offset = shape.indent.block_indent(context.config); + let expr = field + .expr + .rewrite(context, Shape::indented(expr_offset, context.config)); + expr.map(|s| { + format!( + "{}{}:\n{}{}", + attrs_str, + name, + expr_offset.to_string(context.config), + s + ) + }) + } + } + } +} + +fn shape_from_indent_style( + context: &RewriteContext, + shape: Shape, + overhead: usize, + offset: usize, +) -> Option { + if context.use_block_indent() { + // 1 = "," + shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1) + } else { + shape.visual_indent(offset).sub_width(overhead) + } +} + +fn rewrite_tuple_in_visual_indent_style<'a, T>( + context: &RewriteContext, + items: &[&T], + span: Span, + shape: Shape, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + let mut items = items.iter(); + // In case of length 1, need a trailing comma + debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); + if items.len() == 1 { + // 3 = "(" + ",)" + let nested_shape = shape.sub_width(3)?.visual_indent(1); + return items + .next() + .unwrap() + .rewrite(context, nested_shape) + .map(|s| { + if context.config.spaces_within_parens_and_brackets() { + format!("( {}, )", s) + } else { + format!("({},)", s) + } + }); + } + + let list_lo = context.snippet_provider.span_after(span, "("); + let nested_shape = shape.sub_width(2)?.visual_indent(1); + let items = itemize_list( + context.snippet_provider, + items, + ")", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, nested_shape), + list_lo, + span.hi() - BytePos(1), + false, + ); + let item_vec: Vec<_> = items.collect(); + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + nested_shape.width, + ); + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + let list_str = write_list(&item_vec, &fmt)?; + + if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { + Some(format!("( {} )", list_str)) + } else { + Some(format!("({})", list_str)) + } +} + +pub fn rewrite_tuple<'a, T>( + context: &RewriteContext, + items: &[&T], + span: Span, + shape: Shape, +) -> Option +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + debug!("rewrite_tuple {:?}", shape); + if context.use_block_indent() { + // We use the same rule as function calls for rewriting tuples. + let force_trailing_comma = if context.inside_macro { + span_ends_with_comma(context, span) + } else { + items.len() == 1 + }; + rewrite_call_inner( + context, + &String::new(), + items, + span, + shape, + context.config.width_heuristics().fn_call_width, + force_trailing_comma, + ) + } else { + rewrite_tuple_in_visual_indent_style(context, items, span, shape) + } +} + +pub fn rewrite_unary_prefix( + context: &RewriteContext, + prefix: &str, + rewrite: &R, + shape: Shape, +) -> Option { + rewrite + .rewrite(context, shape.offset_left(prefix.len())?) + .map(|r| format!("{}{}", prefix, r)) +} + +// FIXME: this is probably not correct for multi-line Rewrites. we should +// subtract suffix.len() from the last line budget, not the first! +pub fn rewrite_unary_suffix( + context: &RewriteContext, + suffix: &str, + rewrite: &R, + shape: Shape, +) -> Option { + rewrite + .rewrite(context, shape.sub_width(suffix.len())?) + .map(|mut r| { + r.push_str(suffix); + r + }) +} + +fn rewrite_unary_op( + context: &RewriteContext, + op: &ast::UnOp, + expr: &ast::Expr, + shape: Shape, +) -> Option { + // For some reason, an UnOp is not spanned like BinOp! + let operator_str = match *op { + ast::UnOp::Deref => "*", + ast::UnOp::Not => "!", + ast::UnOp::Neg => "-", + }; + rewrite_unary_prefix(context, operator_str, expr, shape) +} + +fn rewrite_assignment( + context: &RewriteContext, + lhs: &ast::Expr, + rhs: &ast::Expr, + op: Option<&ast::BinOp>, + shape: Shape, +) -> Option { + let operator_str = match op { + Some(op) => context.snippet(op.span), + None => "=", + }; + + // 1 = space between lhs and operator. + let lhs_shape = shape.sub_width(operator_str.len() + 1)?; + let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); + + rewrite_assign_rhs(context, lhs_str, rhs, shape) +} + +// The left hand side must contain everything up to, and including, the +// assignment operator. +pub fn rewrite_assign_rhs, R: Rewrite>( + context: &RewriteContext, + lhs: S, + ex: &R, + shape: Shape, +) -> Option { + let lhs = lhs.into(); + let last_line_width = last_line_width(&lhs) + .checked_sub(if lhs.contains('\n') { + shape.indent.width() + } else { + 0 + }) + .unwrap_or(0); + // 1 = space between operator and rhs. + let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { + width: 0, + offset: shape.offset + last_line_width + 1, + ..shape + }); + let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; + Some(lhs + &rhs) +} + +pub fn choose_rhs( + context: &RewriteContext, + expr: &R, + shape: Shape, + orig_rhs: Option, +) -> Option { + match orig_rhs { + Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { + Some(format!(" {}", new_str)) + } + _ => { + // Expression did not fit on the same line as the identifier. + // Try splitting the line and see if that works better. + let new_shape = + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(shape.rhs_overhead(context.config))?; + let new_rhs = expr.rewrite(context, new_shape); + let new_indent_str = &new_shape.indent.to_string_with_newline(context.config); + + match (orig_rhs, new_rhs) { + (Some(ref orig_rhs), Some(ref new_rhs)) + if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) + .is_none() => + { + Some(format!(" {}", orig_rhs)) + } + (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { + Some(format!("{}{}", new_indent_str, new_rhs)) + } + (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), + (None, None) => None, + (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), + } + } + } +} + +fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { + !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 +} + +fn rewrite_expr_addrof( + context: &RewriteContext, + mutability: ast::Mutability, + expr: &ast::Expr, + shape: Shape, +) -> Option { + let operator_str = match mutability { + ast::Mutability::Immutable => "&", + ast::Mutability::Mutable => "&mut ", + }; + rewrite_unary_prefix(context, operator_str, expr, shape) +} + +pub trait ToExpr { + fn to_expr(&self) -> Option<&ast::Expr>; + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool; +} + +impl ToExpr for ast::Expr { + fn to_expr(&self) -> Option<&ast::Expr> { + Some(self) + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_expr(context, self, len) + } +} + +impl ToExpr for ast::Ty { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_type(context, self, len) + } +} + +impl<'a> ToExpr for TuplePatField<'a> { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + can_be_overflowed_pat(context, self, len) + } +} + +impl<'a> ToExpr for ast::StructField { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { + false + } +} + +impl<'a> ToExpr for MacroArg { + fn to_expr(&self) -> Option<&ast::Expr> { + match *self { + MacroArg::Expr(ref expr) => Some(expr), + _ => None, + } + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + match *self { + MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), + MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), + MacroArg::Pat(..) => false, + } + } +} diff --git a/src/filemap.rs b/src/filemap.rs new file mode 100644 index 00000000000..ee2253043a1 --- /dev/null +++ b/src/filemap.rs @@ -0,0 +1,185 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// TODO: add tests + +use std::fs::{self, File}; +use std::io::{self, BufWriter, Read, Write}; +use std::path::Path; + +use checkstyle::{output_checkstyle_file, output_footer, output_header}; +use config::{Config, NewlineStyle, WriteMode}; +use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; +use syntax::codemap::FileName; + +use FileRecord; + +// Append a newline to the end of each file. +pub fn append_newline(s: &mut String) { + s.push_str("\n"); +} + +pub fn write_all_files( + file_map: &[FileRecord], + out: &mut T, + config: &Config, +) -> Result<(), io::Error> +where + T: Write, +{ + output_header(out, config.write_mode()).ok(); + for &(ref filename, ref text) in file_map { + write_file(text, filename, out, config)?; + } + output_footer(out, config.write_mode()).ok(); + + Ok(()) +} + +// Prints all newlines either as `\n` or as `\r\n`. +pub fn write_system_newlines(writer: T, text: &str, config: &Config) -> Result<(), io::Error> +where + T: Write, +{ + // Buffer output, since we're writing a since char at a time. + let mut writer = BufWriter::new(writer); + + let style = if config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + config.newline_style() + }; + + match style { + NewlineStyle::Unix => write!(writer, "{}", text), + NewlineStyle::Windows => { + for c in text.chars() { + match c { + '\n' => write!(writer, "\r\n")?, + '\r' => continue, + c => write!(writer, "{}", c)?, + } + } + Ok(()) + } + NewlineStyle::Native => unreachable!(), + } +} + +pub fn write_file( + text: &str, + filename: &FileName, + out: &mut T, + config: &Config, +) -> Result +where + T: Write, +{ + fn source_and_formatted_text( + text: &str, + filename: &Path, + config: &Config, + ) -> Result<(String, String), io::Error> { + let mut f = File::open(filename)?; + let mut ori_text = String::new(); + f.read_to_string(&mut ori_text)?; + let mut v = Vec::new(); + write_system_newlines(&mut v, text, config)?; + let fmt_text = String::from_utf8(v).unwrap(); + Ok((ori_text, fmt_text)) + } + + fn create_diff( + filename: &Path, + text: &str, + config: &Config, + ) -> Result, io::Error> { + let (ori, fmt) = source_and_formatted_text(text, filename, config)?; + Ok(make_diff(&ori, &fmt, 3)) + } + + let filename_to_path = || match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` with WriteMode::Replace", filename), + }; + + match config.write_mode() { + WriteMode::Replace => { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + if fmt != ori { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.with_extension("tmp"); + let bk_name = filename.with_extension("bk"); + { + // Write text to temp file + let tmp_file = File::create(&tmp_name)?; + write_system_newlines(tmp_file, text, config)?; + } + + fs::rename(filename, bk_name)?; + fs::rename(tmp_name, filename)?; + } + } + } + WriteMode::Overwrite => { + // Write text directly over original file if there is a diff. + let filename = filename_to_path(); + let (source, formatted) = source_and_formatted_text(text, filename, config)?; + if source != formatted { + let file = File::create(filename)?; + write_system_newlines(file, text, config)?; + } + } + WriteMode::Plain => { + write_system_newlines(out, text, config)?; + } + WriteMode::Display | WriteMode::Coverage => { + println!("{}:\n", filename); + write_system_newlines(out, text, config)?; + } + WriteMode::Diff => { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + let mismatch = make_diff(&ori, &fmt, 3); + let has_diff = !mismatch.is_empty(); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), + config.color(), + ); + return Ok(has_diff); + } + } + WriteMode::Modified => { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + let mismatch = make_diff(&ori, &fmt, 0); + let has_diff = !mismatch.is_empty(); + output_modified(out, mismatch); + return Ok(has_diff); + } + } + WriteMode::Checkstyle => { + let filename = filename_to_path(); + let diff = create_diff(filename, text, config)?; + output_checkstyle_file(out, filename, diff)?; + } + } + + // when we are not in diff mode, don't indicate differing files + Ok(false) +} diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs new file mode 100644 index 00000000000..c42fbb6f7cf --- /dev/null +++ b/src/format-diff/main.rs @@ -0,0 +1,267 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Clang's clang-format-diff: +// +// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py + +#![deny(warnings)] + +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate regex; +#[macro_use] +extern crate serde_derive; +extern crate serde_json as json; + +use std::{env, fmt, process}; +use std::collections::HashSet; +use std::error::Error; +use std::io::{self, BufRead}; + +use regex::Regex; + +/// The default pattern of files to format. +/// +/// We only want to format rust files by default. +const DEFAULT_PATTERN: &str = r".*\.rs"; + +#[derive(Debug)] +enum FormatDiffError { + IncorrectOptions(getopts::Fail), + IncorrectFilter(regex::Error), + IoError(io::Error), +} + +impl fmt::Display for FormatDiffError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fmt::Display::fmt(self.cause().unwrap(), f) + } +} + +impl Error for FormatDiffError { + fn description(&self) -> &str { + self.cause().unwrap().description() + } + + fn cause(&self) -> Option<&Error> { + Some(match *self { + FormatDiffError::IoError(ref e) => e, + FormatDiffError::IncorrectFilter(ref e) => e, + FormatDiffError::IncorrectOptions(ref e) => e, + }) + } +} + +impl From for FormatDiffError { + fn from(fail: getopts::Fail) -> Self { + FormatDiffError::IncorrectOptions(fail) + } +} + +impl From for FormatDiffError { + fn from(err: regex::Error) -> Self { + FormatDiffError::IncorrectFilter(err) + } +} + +impl From for FormatDiffError { + fn from(fail: io::Error) -> Self { + FormatDiffError::IoError(fail) + } +} + +fn main() { + let _ = env_logger::init(); + + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optopt( + "p", + "skip-prefix", + "skip the smallest prefix containing NUMBER slashes", + "NUMBER", + ); + opts.optopt( + "f", + "filter", + "custom pattern selecting file paths to reformat", + "PATTERN", + ); + + if let Err(e) = run(&opts) { + println!("{}", opts.usage(e.description())); + process::exit(1); + } +} + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +struct Range { + file: String, + range: [u32; 2], +} + +fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { + let matches = opts.parse(env::args().skip(1))?; + + if matches.opt_present("h") { + println!("{}", opts.usage("usage: ")); + return Ok(()); + } + + let filter = matches + .opt_str("f") + .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); + + let skip_prefix = matches + .opt_str("p") + .and_then(|p| p.parse::().ok()) + .unwrap_or(0); + + let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; + + run_rustfmt(&files, &ranges) +} + +fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDiffError> { + if files.is_empty() || ranges.is_empty() { + debug!("No files to format found"); + return Ok(()); + } + + let ranges_as_json = json::to_string(ranges).unwrap(); + + debug!("Files: {:?}", files); + debug!("Ranges: {:?}", ranges); + + let exit_status = process::Command::new("rustfmt") + .args(files) + .arg("--file-lines") + .arg(ranges_as_json) + .status()?; + + if !exit_status.success() { + return Err(FormatDiffError::IoError(io::Error::new( + io::ErrorKind::Other, + format!("rustfmt failed with {}", exit_status), + ))); + } + Ok(()) +} + +/// Scans a diff from `from`, and returns the set of files found, and the ranges +/// in those files. +fn scan_diff( + from: R, + skip_prefix: u32, + file_filter: &str, +) -> Result<(HashSet, Vec), FormatDiffError> +where + R: io::Read, +{ + let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix); + let diff_pattern = Regex::new(&diff_pattern).unwrap(); + + let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap(); + + let file_filter = Regex::new(&format!("^{}$", file_filter))?; + + let mut current_file = None; + + let mut files = HashSet::new(); + let mut ranges = vec![]; + for line in io::BufReader::new(from).lines() { + let line = line.unwrap(); + + if let Some(captures) = diff_pattern.captures(&line) { + current_file = Some(captures.get(1).unwrap().as_str().to_owned()); + } + + let file = match current_file { + Some(ref f) => &**f, + None => continue, + }; + + // TODO(emilio): We could avoid this most of the time if needed, but + // it's not clear it's worth it. + if !file_filter.is_match(file) { + continue; + } + + let lines_captures = match lines_pattern.captures(&line) { + Some(captures) => captures, + None => continue, + }; + + let start_line = lines_captures + .get(1) + .unwrap() + .as_str() + .parse::() + .unwrap(); + let line_count = match lines_captures.get(3) { + Some(line_count) => line_count.as_str().parse::().unwrap(), + None => 1, + }; + + if line_count == 0 { + continue; + } + + let end_line = start_line + line_count - 1; + files.insert(file.to_owned()); + ranges.push(Range { + file: file.to_owned(), + range: [start_line, end_line], + }); + } + + Ok((files, ranges)) +} + +#[test] +fn scan_simple_git_diff() { + const DIFF: &'static str = include_str!("test/bindgen.diff"); + let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); + + assert!( + files.contains("src/ir/traversal.rs"), + "Should've matched the filter" + ); + + assert!( + !files.contains("tests/headers/anon_enum.hpp"), + "Shouldn't have matched the filter" + ); + + assert_eq!( + &ranges, + &[ + Range { + file: "src/ir/item.rs".to_owned(), + range: [148, 158], + }, + Range { + file: "src/ir/item.rs".to_owned(), + range: [160, 170], + }, + Range { + file: "src/ir/traversal.rs".to_owned(), + range: [9, 16], + }, + Range { + file: "src/ir/traversal.rs".to_owned(), + range: [35, 43], + } + ] + ); +} diff --git a/src/format-diff/test/bindgen.diff b/src/format-diff/test/bindgen.diff new file mode 100644 index 00000000000..d2fd379f471 --- /dev/null +++ b/src/format-diff/test/bindgen.diff @@ -0,0 +1,67 @@ +diff --git a/src/ir/item.rs b/src/ir/item.rs +index 7f3afefb..90d15e96 100644 +--- a/src/ir/item.rs ++++ b/src/ir/item.rs +@@ -148,7 +148,11 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> + impl AsTemplateParam for ItemId { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + ctx.resolve_item(*self).as_template_param(ctx, &()) + } + } +@@ -156,7 +160,11 @@ impl AsTemplateParam for ItemId { + impl AsTemplateParam for Item { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + self.kind.as_template_param(ctx, self) + } + } +diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs +index 762a3e2d..b9c9dd4e 100644 +--- a/src/ir/traversal.rs ++++ b/src/ir/traversal.rs +@@ -9,6 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; + /// + /// from --> to + /// ++/// Random content to generate a diff. ++/// + /// The `from` is left implicit: it is the concrete `Trace` implementer which + /// yielded this outgoing edge. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +@@ -33,7 +35,9 @@ impl Into for Edge { + } + } + +-/// The kind of edge reference. This is useful when we wish to only consider ++/// The kind of edge reference. ++/// ++/// This is useful when we wish to only consider + /// certain kinds of edges for a particular traversal or analysis. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum EdgeKind { +diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp +index 1961fe6c..34759df3 100644 +--- a/tests/headers/anon_enum.hpp ++++ b/tests/headers/anon_enum.hpp +@@ -1,7 +1,7 @@ + struct Test { + int foo; + float bar; +- enum { T_NONE }; ++ enum { T_NONE, T_SOME }; + }; + + typedef enum { diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs new file mode 100644 index 00000000000..8811c1a5255 --- /dev/null +++ b/src/git-rustfmt/main.rs @@ -0,0 +1,205 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate rustfmt_nightly as rustfmt; + +use std::env; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::str::FromStr; + +use getopts::{Matches, Options}; + +use rustfmt::{config, run, Input}; + +fn prune_files(files: Vec<&str>) -> Vec<&str> { + let prefixes: Vec<_> = files + .iter() + .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) + .map(|f| &f[..f.len() - 6]) + .collect(); + + let mut pruned_prefixes = vec![]; + for p1 in prefixes { + let mut include = true; + if !p1.starts_with("src/bin/") { + for p2 in &pruned_prefixes { + if p1.starts_with(p2) { + include = false; + break; + } + } + } + if include { + pruned_prefixes.push(p1); + } + } + debug!("prefixes: {:?}", pruned_prefixes); + + files + .into_iter() + .filter(|f| { + let mut include = true; + if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { + return true; + } + for pp in &pruned_prefixes { + if f.starts_with(pp) { + include = false; + break; + } + } + include + }) + .collect() +} + +fn git_diff(commits: &str) -> String { + let mut cmd = Command::new("git"); + cmd.arg("diff"); + if commits != "0" { + cmd.arg(format!("HEAD~{}", commits)); + } + let output = cmd.output().expect("Couldn't execute `git diff`"); + String::from_utf8_lossy(&output.stdout).into_owned() +} + +fn get_files(input: &str) -> Vec<&str> { + input + .lines() + .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) + .map(|line| &line[6..]) + .collect() +} + +fn fmt_files(files: &[&str]) -> i32 { + let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) + .unwrap_or_else(|_| (config::Config::default(), None)); + + let mut exit_code = 0; + for file in files { + let summary = run(Input::File(PathBuf::from(file)), &config); + if !summary.has_no_errors() { + exit_code = 1; + } + } + exit_code +} + +fn uncommitted_files() -> Vec { + let mut cmd = Command::new("git"); + cmd.arg("ls-files"); + cmd.arg("--others"); + cmd.arg("--modified"); + cmd.arg("--exclude-standard"); + let output = cmd.output().expect("Couldn't execute Git"); + let stdout = String::from_utf8_lossy(&output.stdout); + stdout + .lines() + .filter(|s| s.ends_with(".rs")) + .map(|s| s.to_owned()) + .collect() +} + +fn check_uncommitted() { + let uncommitted = uncommitted_files(); + debug!("uncommitted files: {:?}", uncommitted); + if !uncommitted.is_empty() { + println!("Found untracked changes:"); + for f in &uncommitted { + println!(" {}", f); + } + println!("Commit your work, or run with `-u`."); + println!("Exiting."); + std::process::exit(1); + } +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("c", "check", "check only, don't format (unimplemented)"); + opts.optflag("u", "uncommitted", "format uncommitted files"); + opts +} + +struct Config { + commits: String, + uncommitted: bool, + check: bool, +} + +impl Config { + fn from_args(matches: &Matches, opts: &Options) -> Config { + // `--help` display help message and quit + if matches.opt_present("h") { + let message = format!( + "\nusage: {} [options]\n\n\ + commits: number of commits to format, default: 1", + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&message)); + std::process::exit(0); + } + + let mut config = Config { + commits: "1".to_owned(), + uncommitted: false, + check: false, + }; + + if matches.opt_present("c") { + config.check = true; + unimplemented!(); + } + + if matches.opt_present("u") { + config.uncommitted = true; + } + + if matches.free.len() > 1 { + panic!("unknown arguments, use `-h` for usage"); + } + if matches.free.len() == 1 { + let commits = matches.free[0].trim(); + if u32::from_str(commits).is_err() { + panic!("Couldn't parse number of commits"); + } + config.commits = commits.to_owned(); + } + + config + } +} + +fn main() { + let _ = env_logger::init(); + + let opts = make_opts(); + let matches = opts.parse(env::args().skip(1)) + .expect("Couldn't parse command line"); + let config = Config::from_args(&matches, &opts); + + if !config.uncommitted { + check_uncommitted(); + } + + let stdout = git_diff(&config.commits); + let files = get_files(&stdout); + debug!("files: {:?}", files); + let files = prune_files(files); + debug!("pruned files: {:?}", files); + let exit_code = fmt_files(&files); + std::process::exit(exit_code); +} diff --git a/src/imports.rs b/src/imports.rs new file mode 100644 index 00000000000..9a6af3f267c --- /dev/null +++ b/src/imports.rs @@ -0,0 +1,399 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp::Ordering; + +use config::lists::*; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; + +use codemap::SpanUtils; +use config::IndentStyle; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use types::{rewrite_path, PathContext}; +use utils::{format_visibility, mk_sp}; +use visitor::FmtVisitor; + +/// Returns a name imported by a `use` declaration. e.g. returns `Ordering` +/// for `std::cmp::Ordering` and `self` for `std::cmp::self`. +pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { + path.segments.last().unwrap().identifier +} + +fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { + if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { + let path = &ast::Path { + span: path.span, + segments: path.segments[..path.segments.len() - 1].to_owned(), + }; + rewrite_path(context, PathContext::Import, None, path, shape) + } else { + rewrite_path(context, PathContext::Import, None, path, shape) + } +} + +impl Rewrite for ast::UseTree { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.kind { + ast::UseTreeKind::Nested(ref items) => { + rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context) + } + ast::UseTreeKind::Glob => { + let prefix_shape = shape.sub_width(3)?; + + if !self.prefix.segments.is_empty() { + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; + Some(format!("{}::*", path_str)) + } else { + Some("*".to_owned()) + } + } + ast::UseTreeKind::Simple(ident) => { + let ident_str = ident.to_string(); + + // 4 = " as ".len() + let is_same_name_bind = path_to_imported_ident(&self.prefix) == ident; + let prefix_shape = if is_same_name_bind { + shape + } else { + shape.sub_width(ident_str.len() + 4)? + }; + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) + .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); + + if is_same_name_bind { + Some(path_str) + } else { + Some(format!("{} as {}", path_str, ident_str)) + } + } + } + } +} + +fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool { + attrs.is_empty() && is_unused_import_inner(tree) +} + +fn is_unused_import_inner(tree: &ast::UseTree) -> bool { + match tree.kind { + ast::UseTreeKind::Nested(ref items) => match items.len() { + 0 => true, + 1 => is_unused_import_inner(&items[0].0), + _ => false, + }, + _ => false, + } +} + +// Rewrite `use foo;` WITHOUT attributes. +pub fn rewrite_import( + context: &RewriteContext, + vis: &ast::Visibility, + tree: &ast::UseTree, + attrs: &[ast::Attribute], + shape: Shape, +) -> Option { + let vis = format_visibility(vis); + // 4 = `use `, 1 = `;` + let rw = shape + .offset_left(vis.len() + 4) + .and_then(|shape| shape.sub_width(1)) + .and_then(|shape| { + // If we have an empty nested group with no attributes, we erase it + if is_unused_import(tree, attrs) { + Some("".to_owned()) + } else { + tree.rewrite(context, shape) + } + }); + match rw { + Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), + _ => rw, + } +} + +impl<'a> FmtVisitor<'a> { + pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { + let span = item.span; + let shape = self.shape(); + let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape); + match rw { + Some(ref s) if s.is_empty() => { + // Format up to last newline + let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); + let trimmed_snippet = self.snippet(prev_span).trim_right(); + let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32); + self.format_missing(span_end); + // We have an excessive newline from the removed import. + if self.buffer.ends_with('\n') { + self.buffer.pop(); + self.line_number -= 1; + } + self.last_pos = source!(self, span).hi(); + } + Some(ref s) => { + self.format_missing_with_indent(source!(self, span).lo()); + self.push_str(s); + self.last_pos = source!(self, span).hi(); + } + None => { + self.format_missing_with_indent(source!(self, span).lo()); + self.format_missing(source!(self, span).hi()); + } + } + } +} + +fn rewrite_nested_use_tree_single( + context: &RewriteContext, + path_str: &str, + tree: &ast::UseTree, + shape: Shape, +) -> Option { + match tree.kind { + ast::UseTreeKind::Simple(rename) => { + let ident = path_to_imported_ident(&tree.prefix); + let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; + if item_str == "self" { + item_str = "".to_owned(); + } + + let path_item_str = if path_str.is_empty() { + if item_str.is_empty() { + "self".to_owned() + } else { + item_str + } + } else if item_str.is_empty() { + path_str.to_owned() + } else { + format!("{}::{}", path_str, item_str) + }; + + Some(if ident == rename { + path_item_str + } else { + format!("{} as {}", path_item_str, rename) + }) + } + ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { + // 2 = "::" + let nested_shape = shape.offset_left(path_str.len() + 2)?; + tree.rewrite(context, nested_shape) + .map(|item| format!("{}::{}", path_str, item)) + } + } +} + +#[derive(Eq, PartialEq)] +enum ImportItem<'a> { + // `self` or `self as a` + SelfImport(&'a str), + // name_one, name_two, ... + SnakeCase(&'a str), + // NameOne, NameTwo, ... + CamelCase(&'a str), + // NAME_ONE, NAME_TWO, ... + AllCaps(&'a str), + // Failed to format the import item + Invalid, +} + +impl<'a> ImportItem<'a> { + fn from_str(s: &str) -> ImportItem { + if s == "self" || s.starts_with("self as") { + ImportItem::SelfImport(s) + } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') { + ImportItem::SnakeCase(s) + } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') { + ImportItem::AllCaps(s) + } else { + ImportItem::CamelCase(s) + } + } + + fn from_opt_str(s: Option<&String>) -> ImportItem { + s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s)) + } + + fn to_str(&self) -> Option<&str> { + match *self { + ImportItem::SelfImport(s) + | ImportItem::SnakeCase(s) + | ImportItem::CamelCase(s) + | ImportItem::AllCaps(s) => Some(s), + ImportItem::Invalid => None, + } + } + + fn to_u32(&self) -> u32 { + match *self { + ImportItem::SelfImport(..) => 0, + ImportItem::SnakeCase(..) => 1, + ImportItem::CamelCase(..) => 2, + ImportItem::AllCaps(..) => 3, + ImportItem::Invalid => 4, + } + } +} + +impl<'a> PartialOrd for ImportItem<'a> { + fn partial_cmp(&self, other: &ImportItem<'a>) -> Option { + Some(self.cmp(other)) + } +} + +impl<'a> Ord for ImportItem<'a> { + fn cmp(&self, other: &ImportItem<'a>) -> Ordering { + let res = self.to_u32().cmp(&other.to_u32()); + if res != Ordering::Equal { + return res; + } + self.to_str().map_or(Ordering::Greater, |self_str| { + other + .to_str() + .map_or(Ordering::Less, |other_str| self_str.cmp(other_str)) + }) + } +} + +// Pretty prints a multi-item import. +// If the path list is empty, it leaves the braces empty. +fn rewrite_nested_use_tree( + shape: Shape, + path: &ast::Path, + trees: &[(ast::UseTree, ast::NodeId)], + span: Span, + context: &RewriteContext, +) -> Option { + // Returns a different option to distinguish `::foo` and `foo` + let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; + + match trees.len() { + 0 => { + let shape = shape.offset_left(path_str.len() + 3)?; + return rewrite_path(context, PathContext::Import, None, path, shape) + .map(|path_str| format!("{}::{{}}", path_str)); + } + 1 => { + return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape); + } + _ => (), + } + + let path_str = if path_str.is_empty() { + path_str + } else { + format!("{}::", path_str) + }; + + // 2 = "{}" + let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); + let nested_indent = match context.config.imports_indent() { + IndentStyle::Block => shape.indent.block_indent(context.config), + // 1 = `{` + IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, + }; + + let nested_shape = match context.config.imports_indent() { + IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?, + IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), + }; + + let mut items = { + // Dummy value, see explanation below. + let mut items = vec![ListItem::from_str("")]; + let iter = itemize_list( + context.snippet_provider, + trees.iter().map(|tree| &tree.0), + "}", + ",", + |tree| tree.span.lo(), + |tree| tree.span.hi(), + |tree| tree.rewrite(context, nested_shape), + context.snippet_provider.span_after(span, "{"), + span.hi(), + false, + ); + items.extend(iter); + items + }; + + // We prefixed the item list with a dummy value so that we can + // potentially move "self" to the front of the vector without touching + // the rest of the items. + let has_self = move_self_to_front(&mut items); + let first_index = if has_self { 0 } else { 1 }; + + if context.config.reorder_imported_names() { + items[1..].sort_by(|a, b| { + let a = ImportItem::from_opt_str(a.item.as_ref()); + let b = ImportItem::from_opt_str(b.item.as_ref()); + a.cmp(&b) + }); + } + + let tactic = definitive_tactic( + &items[first_index..], + context.config.imports_layout(), + Separator::Comma, + remaining_width, + ); + + let ends_with_newline = context.config.imports_indent() == IndentStyle::Block + && tactic != DefinitiveListTactic::Horizontal; + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if ends_with_newline { + context.config.trailing_comma() + } else { + SeparatorTactic::Never + }, + separator_place: SeparatorPlace::Back, + shape: nested_shape, + ends_with_newline, + preserve_newline: true, + config: context.config, + }; + let list_str = write_list(&items[first_index..], &fmt)?; + + let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block + { + format!( + "{}{{\n{}{}\n{}}}", + path_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.indent.to_string(context.config) + ) + } else { + format!("{}{{{}}}", path_str, list_str) + }; + Some(result) +} + +// Returns true when self item was found. +fn move_self_to_front(items: &mut Vec) -> bool { + match items + .iter() + .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) + { + Some(pos) => { + items[0] = items.remove(pos); + true + } + None => false, + } +} diff --git a/src/issues.rs b/src/issues.rs new file mode 100644 index 00000000000..75ad30b6f2a --- /dev/null +++ b/src/issues.rs @@ -0,0 +1,327 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Objects for seeking through a char stream for occurrences of TODO and FIXME. +// Depending on the loaded configuration, may also check that these have an +// associated issue number. + +use std::fmt; + +use config::ReportTactic; + +const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o']; +const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e']; + +// Enabled implementation detail is here because it is +// irrelevant outside the issues module +fn is_enabled(report_tactic: ReportTactic) -> bool { + report_tactic != ReportTactic::Never +} + +#[derive(Clone, Copy)] +enum Seeking { + Issue { todo_idx: usize, fixme_idx: usize }, + Number { issue: Issue, part: NumberPart }, +} + +#[derive(Clone, Copy)] +enum NumberPart { + OpenParen, + Pound, + Number, + CloseParen, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub struct Issue { + issue_type: IssueType, + // Indicates whether we're looking for issues with missing numbers, or + // all issues of this type. + missing_number: bool, +} + +impl fmt::Display for Issue { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let msg = match self.issue_type { + IssueType::Todo => "TODO", + IssueType::Fixme => "FIXME", + }; + let details = if self.missing_number { + " without issue number" + } else { + "" + }; + + write!(fmt, "{}{}", msg, details) + } +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +enum IssueType { + Todo, + Fixme, +} + +enum IssueClassification { + Good, + Bad(Issue), + None, +} + +pub struct BadIssueSeeker { + state: Seeking, + report_todo: ReportTactic, + report_fixme: ReportTactic, +} + +impl BadIssueSeeker { + pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { + BadIssueSeeker { + state: Seeking::Issue { + todo_idx: 0, + fixme_idx: 0, + }, + report_todo, + report_fixme, + } + } + + pub fn is_disabled(&self) -> bool { + !is_enabled(self.report_todo) && !is_enabled(self.report_fixme) + } + + // Check whether or not the current char is conclusive evidence for an + // unnumbered TO-DO or FIX-ME. + pub fn inspect(&mut self, c: char) -> Option { + match self.state { + Seeking::Issue { + todo_idx, + fixme_idx, + } => { + self.state = self.inspect_issue(c, todo_idx, fixme_idx); + } + Seeking::Number { issue, part } => { + let result = self.inspect_number(c, issue, part); + + if let IssueClassification::None = result { + return None; + } + + self.state = Seeking::Issue { + todo_idx: 0, + fixme_idx: 0, + }; + + if let IssueClassification::Bad(issue) = result { + return Some(issue); + } + } + } + + None + } + + fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking { + if let Some(lower_case_c) = c.to_lowercase().next() { + if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] { + todo_idx += 1; + if todo_idx == TO_DO_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Todo, + missing_number: if let ReportTactic::Unnumbered = self.report_todo { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; + } + fixme_idx = 0; + } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] { + // Exploit the fact that the character sets of todo and fixme + // are disjoint by adding else. + fixme_idx += 1; + if fixme_idx == FIX_ME_CHARS.len() { + return Seeking::Number { + issue: Issue { + issue_type: IssueType::Fixme, + missing_number: if let ReportTactic::Unnumbered = self.report_fixme { + true + } else { + false + }, + }, + part: NumberPart::OpenParen, + }; + } + todo_idx = 0; + } else { + todo_idx = 0; + fixme_idx = 0; + } + } + + Seeking::Issue { + todo_idx, + fixme_idx, + } + } + + fn inspect_number( + &mut self, + c: char, + issue: Issue, + mut part: NumberPart, + ) -> IssueClassification { + if !issue.missing_number || c == '\n' { + return IssueClassification::Bad(issue); + } else if c == ')' { + return if let NumberPart::CloseParen = part { + IssueClassification::Good + } else { + IssueClassification::Bad(issue) + }; + } + + match part { + NumberPart::OpenParen => { + if c != '(' { + return IssueClassification::Bad(issue); + } else { + part = NumberPart::Pound; + } + } + NumberPart::Pound => { + if c == '#' { + part = NumberPart::Number; + } + } + NumberPart::Number => { + if c >= '0' && c <= '9' { + part = NumberPart::CloseParen; + } else { + return IssueClassification::Bad(issue); + } + } + NumberPart::CloseParen => {} + } + + self.state = Seeking::Number { part, issue }; + + IssueClassification::None + } +} + +#[test] +fn find_unnumbered_issue() { + fn check_fail(text: &str, failing_pos: usize) { + let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); + assert_eq!( + Some(failing_pos), + text.chars().position(|c| seeker.inspect(c).is_some()) + ); + } + + fn check_pass(text: &str) { + let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); + assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); + } + + check_fail("TODO\n", 4); + check_pass(" TO FIX DOME\n"); + check_fail(" \n FIXME\n", 8); + check_fail("FIXME(\n", 6); + check_fail("FIXME(#\n", 7); + check_fail("FIXME(#1\n", 8); + check_fail("FIXME(#)1\n", 7); + check_pass("FIXME(#1222)\n"); + check_fail("FIXME(#12\n22)\n", 9); + check_pass("FIXME(@maintainer, #1222, hello)\n"); + check_fail("TODO(#22) FIXME\n", 15); +} + +#[test] +fn find_issue() { + fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool { + let mut seeker = BadIssueSeeker::new(report_todo, report_fixme); + text.chars().any(|c| seeker.inspect(c).is_some()) + } + + assert!(is_bad_issue( + "TODO(@maintainer, #1222, hello)\n", + ReportTactic::Always, + ReportTactic::Never, + )); + + assert!(!is_bad_issue( + "TODO: no number\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(!is_bad_issue( + "Todo: mixed case\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(is_bad_issue( + "This is a FIXME(#1)\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(is_bad_issue( + "This is a FixMe(#1) mixed case\n", + ReportTactic::Never, + ReportTactic::Always, + )); + + assert!(!is_bad_issue( + "bad FIXME\n", + ReportTactic::Always, + ReportTactic::Never, + )); +} + +#[test] +fn issue_type() { + let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never); + let expected = Some(Issue { + issue_type: IssueType::Todo, + missing_number: false, + }); + + assert_eq!( + expected, + "TODO(#100): more awesomeness" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap() + ); + + let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered); + let expected = Some(Issue { + issue_type: IssueType::Fixme, + missing_number: true, + }); + + assert_eq!( + expected, + "Test. FIXME: bad, bad, not good" + .chars() + .map(|c| seeker.inspect(c)) + .find(Option::is_some) + .unwrap() + ); +} diff --git a/src/items.rs b/src/items.rs new file mode 100644 index 00000000000..3503546c010 --- /dev/null +++ b/src/items.rs @@ -0,0 +1,2891 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Formatting top-level items - functions, structs, enums, traits, impls. + +use std::borrow::Cow; +use std::cmp::min; + +use config::lists::*; +use regex::Regex; +use syntax::{abi, ast, ptr, symbol}; +use syntax::ast::{CrateSugar, ImplItem}; +use syntax::codemap::{BytePos, Span}; +use syntax::visit; + +use codemap::{LineRangeUtils, SpanUtils}; +use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; +use config::{BraceStyle, Config, Density, IndentStyle}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_call_inner, ExprType}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use types::join_bounds; +use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, + format_defaultness, format_mutability, format_unsafety, format_visibility, + is_attributes_extendable, last_line_contains_single_line_comment, + last_line_extendable, last_line_used_width, last_line_width, mk_sp, + semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; +use vertical::rewrite_with_alignment; +use visitor::FmtVisitor; + +fn type_annotation_separator(config: &Config) -> &str { + colon_spaces(config.space_before_colon(), config.space_after_colon()) +} + +// Statements of the form +// let pat: ty = init; +impl Rewrite for ast::Local { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!( + "Local::rewrite {:?} {} {:?}", + self, shape.width, shape.indent + ); + + skip_out_of_file_lines_range!(context, self.span); + + if contains_skip(&self.attrs) { + return None; + } + + let attrs_str = self.attrs.rewrite(context, shape)?; + let mut result = if attrs_str.is_empty() { + "let ".to_owned() + } else { + combine_strs_with_missing_comments( + context, + &attrs_str, + "let ", + mk_sp( + self.attrs.last().map(|a| a.span.hi()).unwrap(), + self.span.lo(), + ), + shape, + false, + )? + }; + + // 4 = "let ".len() + let pat_shape = shape.offset_left(4)?; + // 1 = ; + let pat_shape = pat_shape.sub_width(1)?; + let pat_str = self.pat.rewrite(context, pat_shape)?; + result.push_str(&pat_str); + + // String that is placed within the assignment pattern and expression. + let infix = { + let mut infix = String::with_capacity(32); + + if let Some(ref ty) = self.ty { + let separator = type_annotation_separator(context.config); + let indent = shape.indent + last_line_width(&result) + separator.len(); + // 1 = ; + let budget = shape.width.checked_sub(indent.width() + 1)?; + let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?; + + infix.push_str(separator); + infix.push_str(&rewrite); + } + + if self.init.is_some() { + infix.push_str(" ="); + } + + infix + }; + + result.push_str(&infix); + + if let Some(ref ex) = self.init { + // 1 = trailing semicolon; + let nested_shape = shape.sub_width(1)?; + + result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?; + } + + result.push(';'); + Some(result) + } +} + +// TODO convert to using rewrite style rather than visitor +// TODO format modules in this style +#[allow(dead_code)] +struct Item<'a> { + keyword: &'static str, + abi: Cow<'static, str>, + vis: Option<&'a ast::Visibility>, + body: Vec>, + span: Span, +} + +impl<'a> Item<'a> { + fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { + Item { + keyword: "", + abi: format_abi(fm.abi, config.force_explicit_abi(), true), + vis: None, + body: fm.items + .iter() + .map(|i| BodyElement::ForeignItem(i)) + .collect(), + span, + } + } +} + +enum BodyElement<'a> { + // Stmt(&'a ast::Stmt), + // Field(&'a ast::Field), + // Variant(&'a ast::Variant), + // Item(&'a ast::Item), + ForeignItem(&'a ast::ForeignItem), +} + +/// Represents a fn's signature. +pub struct FnSig<'a> { + decl: &'a ast::FnDecl, + generics: &'a ast::Generics, + abi: abi::Abi, + constness: ast::Constness, + defaultness: ast::Defaultness, + unsafety: ast::Unsafety, + visibility: ast::Visibility, +} + +impl<'a> FnSig<'a> { + pub fn new( + decl: &'a ast::FnDecl, + generics: &'a ast::Generics, + vis: ast::Visibility, + ) -> FnSig<'a> { + FnSig { + decl, + generics, + abi: abi::Abi::Rust, + constness: ast::Constness::NotConst, + defaultness: ast::Defaultness::Final, + unsafety: ast::Unsafety::Normal, + visibility: vis, + } + } + + pub fn from_method_sig( + method_sig: &'a ast::MethodSig, + generics: &'a ast::Generics, + ) -> FnSig<'a> { + FnSig { + unsafety: method_sig.unsafety, + constness: method_sig.constness.node, + defaultness: ast::Defaultness::Final, + abi: method_sig.abi, + decl: &*method_sig.decl, + generics, + visibility: ast::Visibility::Inherited, + } + } + + pub fn from_fn_kind( + fn_kind: &'a visit::FnKind, + generics: &'a ast::Generics, + decl: &'a ast::FnDecl, + defualtness: ast::Defaultness, + ) -> FnSig<'a> { + match *fn_kind { + visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { + decl, + generics, + abi, + constness: constness.node, + defaultness: defualtness, + unsafety, + visibility: visibility.clone(), + }, + visit::FnKind::Method(_, method_sig, vis, _) => { + let mut fn_sig = FnSig::from_method_sig(method_sig, generics); + fn_sig.defaultness = defualtness; + if let Some(vis) = vis { + fn_sig.visibility = vis.clone(); + } + fn_sig + } + _ => unreachable!(), + } + } + + fn to_str(&self, context: &RewriteContext) -> String { + let mut result = String::with_capacity(128); + // Vis defaultness constness unsafety abi. + result.push_str(&*format_visibility(&self.visibility)); + result.push_str(format_defaultness(self.defaultness)); + result.push_str(format_constness(self.constness)); + result.push_str(format_unsafety(self.unsafety)); + result.push_str(&format_abi( + self.abi, + context.config.force_explicit_abi(), + false, + )); + result + } +} + +impl<'a> FmtVisitor<'a> { + fn format_item(&mut self, item: &Item) { + self.buffer.push_str(&item.abi); + + let snippet = self.snippet(item.span); + let brace_pos = snippet.find_uncommented("{").unwrap(); + + self.push_str("{"); + if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) { + // FIXME: this skips comments between the extern keyword and the opening + // brace. + self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1); + self.block_indent = self.block_indent.block_indent(self.config); + + if item.body.is_empty() { + self.format_missing_no_indent(item.span.hi() - BytePos(1)); + self.block_indent = self.block_indent.block_unindent(self.config); + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + } else { + for item in &item.body { + self.format_body_element(item); + } + + self.block_indent = self.block_indent.block_unindent(self.config); + self.format_missing_with_indent(item.span.hi() - BytePos(1)); + } + } + + self.push_str("}"); + self.last_pos = item.span.hi(); + } + + fn format_body_element(&mut self, element: &BodyElement) { + match *element { + BodyElement::ForeignItem(item) => self.format_foreign_item(item), + } + } + + pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { + let item = Item::from_foreign_mod(fm, span, self.config); + self.format_item(&item); + } + + fn format_foreign_item(&mut self, item: &ast::ForeignItem) { + let rewrite = item.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(item.span(), rewrite); + self.last_pos = item.span.hi(); + } + + pub fn rewrite_fn( + &mut self, + indent: Indent, + ident: ast::Ident, + fn_sig: &FnSig, + span: Span, + block: &ast::Block, + ) -> Option { + let context = self.get_context(); + + let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause); + + let (mut result, force_newline_brace) = + rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; + + // 2 = ` {` + if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace + || last_line_width(&result) + 2 > self.shape().width + { + newline_brace = true; + } else if !result.contains('\n') { + newline_brace = false; + } + + // Prepare for the function body by possibly adding a newline and + // indent. + // FIXME we'll miss anything between the end of the signature and the + // start of the body, but we need more spans from the compiler to solve + // this. + if newline_brace { + result.push_str(&indent.to_string_with_newline(self.config)); + } else { + result.push(' '); + } + + self.single_line_fn(&result, block).or_else(|| Some(result)) + } + + pub fn rewrite_required_fn( + &mut self, + indent: Indent, + ident: ast::Ident, + sig: &ast::MethodSig, + generics: &ast::Generics, + span: Span, + ) -> Option { + // Drop semicolon or it will be interpreted as comment. + let span = mk_sp(span.lo(), span.hi() - BytePos(1)); + let context = self.get_context(); + + let (mut result, _) = rewrite_fn_base( + &context, + indent, + ident, + &FnSig::from_method_sig(sig, generics), + span, + false, + false, + )?; + + // Re-attach semicolon + result.push(';'); + + Some(result) + } + + fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { + if fn_str.contains('\n') { + return None; + } + + let codemap = self.get_context().codemap; + + if self.config.empty_item_single_line() && is_empty_block(block, codemap) + && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() + { + return Some(format!("{}{{}}", fn_str)); + } + + if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { + let rewrite = { + if let Some(stmt) = block.stmts.first() { + match stmt_expr(stmt) { + Some(e) => { + let suffix = if semicolon_for_expr(&self.get_context(), e) { + ";" + } else { + "" + }; + + format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) + .map(|s| s + suffix) + .or_else(|| Some(self.snippet(e.span).to_owned())) + } + None => stmt.rewrite(&self.get_context(), self.shape()), + } + } else { + None + } + }; + + if let Some(res) = rewrite { + let width = self.block_indent.width() + fn_str.len() + res.len() + 4; + if !res.contains('\n') && width <= self.config.max_width() { + return Some(format!("{}{{ {} }}", fn_str, res)); + } + } + } + + None + } + + pub fn visit_static(&mut self, static_parts: &StaticParts) { + let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); + self.push_rewrite(static_parts.span, rewrite); + } + + pub fn visit_struct(&mut self, struct_parts: &StructParts) { + let is_tuple = struct_parts.def.is_tuple(); + let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) + .map(|s| if is_tuple { s + ";" } else { s }); + self.push_rewrite(struct_parts.span, rewrite); + } + + pub fn visit_enum( + &mut self, + ident: ast::Ident, + vis: &ast::Visibility, + enum_def: &ast::EnumDef, + generics: &ast::Generics, + span: Span, + ) { + let enum_header = format_header("enum ", ident, vis); + self.push_str(&enum_header); + + let enum_snippet = self.snippet(span); + let brace_pos = enum_snippet.find_uncommented("{").unwrap(); + let body_start = span.lo() + BytePos(brace_pos as u32 + 1); + let generics_str = format_generics( + &self.get_context(), + generics, + self.config.brace_style(), + if enum_def.variants.is_empty() { + BracePos::ForceSameLine + } else { + BracePos::Auto + }, + self.block_indent, + mk_sp(span.lo(), body_start), + last_line_width(&enum_header), + ).unwrap(); + self.push_str(&generics_str); + + self.last_pos = body_start; + + self.block_indent = self.block_indent.block_indent(self.config); + let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); + match variant_list { + Some(ref body_str) => self.push_str(body_str), + None => self.format_missing_no_indent(span.hi() - BytePos(1)), + } + self.block_indent = self.block_indent.block_unindent(self.config); + + if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + } + self.push_str("}"); + self.last_pos = span.hi(); + } + + // Format the body of an enum definition + fn format_variant_list( + &self, + enum_def: &ast::EnumDef, + body_lo: BytePos, + body_hi: BytePos, + ) -> Option { + if enum_def.variants.is_empty() { + return None; + } + let mut result = String::with_capacity(1024); + let indentation = self.block_indent.to_string_with_newline(self.config); + result.push_str(&indentation); + + let itemize_list_with = |one_line_width: usize| { + itemize_list( + self.snippet_provider, + enum_def.variants.iter(), + "}", + ",", + |f| { + if !f.node.attrs.is_empty() { + f.node.attrs[0].span.lo() + } else { + f.span.lo() + } + }, + |f| f.span.hi(), + |f| self.format_variant(f, one_line_width), + body_lo, + body_hi, + false, + ).collect() + }; + let mut items: Vec<_> = + itemize_list_with(self.config.width_heuristics().struct_variant_width); + // If one of the variants use multiple lines, use multi-lined formatting for all variants. + let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); + let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); + if has_multiline_variant && has_single_line_variant { + items = itemize_list_with(0); + } + + let shape = self.shape().sub_width(2)?; + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: self.config.trailing_comma(), + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: true, + preserve_newline: true, + config: self.config, + }; + + let list = write_list(&items, &fmt)?; + result.push_str(&list); + result.push('\n'); + Some(result) + } + + // Variant of an enum. + fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option { + if contains_skip(&field.node.attrs) { + let lo = field.node.attrs[0].span.lo(); + let span = mk_sp(lo, field.span.hi()); + return Some(self.snippet(span).to_owned()); + } + + let context = self.get_context(); + // 1 = ',' + let shape = self.shape().sub_width(1)?; + let attrs_str = field.node.attrs.rewrite(&context, shape)?; + let lo = field + .node + .attrs + .last() + .map_or(field.span.lo(), |attr| attr.span.hi()); + let span = mk_sp(lo, field.span.lo()); + + let variant_body = match field.node.data { + ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( + &context, + &StructParts::from_variant(field), + self.block_indent, + Some(one_line_width), + )?, + ast::VariantData::Unit(..) => { + if let Some(ref expr) = field.node.disr_expr { + let lhs = format!("{} =", field.node.name); + rewrite_assign_rhs(&context, lhs, &**expr, shape)? + } else { + field.node.name.to_string() + } + } + }; + + combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) + } +} + +pub fn format_impl( + context: &RewriteContext, + item: &ast::Item, + offset: Indent, + where_span_end: Option, +) -> Option { + if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { + let mut result = String::with_capacity(128); + let ref_and_type = format_impl_ref_and_type(context, item, offset)?; + let sep = offset.to_string_with_newline(context.config); + result.push_str(&ref_and_type); + + let where_budget = if result.contains('\n') { + context.config.max_width() + } else { + context.budget(last_line_width(&result)) + }; + let option = WhereClauseOption::snuggled(&ref_and_type); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + Density::Vertical, + "{", + where_span_end, + self_ty.span.hi(), + option, + false, + )?; + + // If there is no where clause, we may have missing comments between the trait name and + // the opening brace. + if generics.where_clause.predicates.is_empty() { + if let Some(hi) = where_span_end { + match recover_missing_comment_in_span( + mk_sp(self_ty.span.hi(), hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + } + _ => (), + } + } + } + + if is_impl_single_line(context, items, &result, &where_clause_str, item)? { + result.push_str(&where_clause_str); + if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { + result.push_str(&format!("{}{{{}}}", &sep, &sep)); + } else { + result.push_str(" {}"); + } + return Some(result); + } + + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { + let width = offset.block_indent + context.config.tab_spaces() - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string_with_newline(context.config)); + } + result.push_str(&where_clause_str); + + let need_newline = !last_line_extendable(&result) + && (last_line_contains_single_line_comment(&result) || result.contains('\n')); + match context.config.brace_style() { + _ if need_newline => result.push_str(&sep), + BraceStyle::AlwaysNextLine => result.push_str(&sep), + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() { + result.push_str(&sep); + } else { + result.push(' '); + } + } + } + + result.push('{'); + + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + + if !items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = offset.block_only().block_indent(context.config); + visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); + + visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); + for item in items { + visitor.visit_impl_item(item); + } + + visitor.format_missing(item.span.hi() - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); + let outer_indent_str = offset.block_only().to_string_with_newline(context.config); + + result.push_str(&inner_indent_str); + result.push_str(visitor.buffer.to_string().trim()); + result.push_str(&outer_indent_str); + } + + if result.ends_with('{') { + result.push_str(&sep); + } + result.push('}'); + + Some(result) + } else { + unreachable!(); + } +} + +fn is_impl_single_line( + context: &RewriteContext, + items: &[ImplItem], + result: &str, + where_clause_str: &str, + item: &ast::Item, +) -> Option { + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + + Some( + context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n') + && result.len() + where_clause_str.len() <= context.config.max_width() + && !contains_comment(&snippet[open_pos..]), + ) +} + +fn format_impl_ref_and_type( + context: &RewriteContext, + item: &ast::Item, + offset: Indent, +) -> Option { + if let ast::ItemKind::Impl( + unsafety, + polarity, + defaultness, + ref generics, + ref trait_ref, + ref self_ty, + _, + ) = item.node + { + let mut result = String::with_capacity(128); + + result.push_str(&format_visibility(&item.vis)); + result.push_str(format_defaultness(defaultness)); + result.push_str(format_unsafety(unsafety)); + result.push_str("impl"); + + let lo = context.snippet_provider.span_after(item.span, "impl"); + let hi = match *trait_ref { + Some(ref tr) => tr.path.span.lo(), + None => self_ty.span.lo(), + }; + let shape = generics_shape_from_config( + context.config, + Shape::indented(offset + last_line_width(&result), context.config), + 0, + )?; + let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?; + let generics_str = + rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?; + + let polarity_str = if polarity == ast::ImplPolarity::Negative { + "!" + } else { + "" + }; + + if let Some(ref trait_ref) = *trait_ref { + let result_len = result.len(); + if let Some(trait_ref_str) = rewrite_trait_ref( + context, + trait_ref, + offset, + &generics_str, + true, + polarity_str, + result_len, + ) { + result.push_str(&trait_ref_str); + } else { + let generics_str = + rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?; + result.push_str(&rewrite_trait_ref( + context, + trait_ref, + offset, + &generics_str, + false, + polarity_str, + result_len, + )?); + } + } else { + result.push_str(&generics_str); + } + + // Try to put the self type in a single line. + // ` for` + let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; + let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { + // If there is no where clause adapt budget for type formatting to take space and curly + // brace into account. + match context.config.brace_style() { + BraceStyle::AlwaysNextLine => 0, + _ => 2, + } + } else { + 0 + }; + let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; + // 1 = space before the type. + let budget = context.budget(used_space + 1); + if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { + if !self_ty_str.contains('\n') { + if trait_ref.is_some() { + result.push_str(" for "); + } else { + result.push(' '); + } + result.push_str(&self_ty_str); + return Some(result); + } + } + + // Couldn't fit the self type on a single line, put it on a new line. + result.push('\n'); + // Add indentation of one additional tab. + let new_line_offset = offset.block_indent(context.config); + result.push_str(&new_line_offset.to_string(context.config)); + if trait_ref.is_some() { + result.push_str("for "); + } + let budget = context.budget(last_line_width(&result)); + let type_offset = match context.config.indent_style() { + IndentStyle::Visual => new_line_offset + trait_ref_overhead, + IndentStyle::Block => new_line_offset, + }; + result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?); + Some(result) + } else { + unreachable!(); + } +} + +fn rewrite_trait_ref( + context: &RewriteContext, + trait_ref: &ast::TraitRef, + offset: Indent, + generics_str: &str, + retry: bool, + polarity_str: &str, + result_len: usize, +) -> Option { + // 1 = space between generics and trait_ref + let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len); + let shape = Shape::indented(offset + used_space, context.config); + if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { + if !(retry && trait_ref_str.contains('\n')) { + return Some(format!( + "{} {}{}", + generics_str, polarity_str, &trait_ref_str + )); + } + } + // We could not make enough space for trait_ref, so put it on new line. + if !retry { + let offset = offset.block_indent(context.config); + let shape = Shape::indented(offset, context.config); + let trait_ref_str = trait_ref.rewrite(context, shape)?; + Some(format!( + "{}\n{}{}{}", + generics_str, + &offset.to_string(context.config), + polarity_str, + &trait_ref_str + )) + } else { + None + } +} + +pub struct StructParts<'a> { + prefix: &'a str, + ident: ast::Ident, + vis: &'a ast::Visibility, + def: &'a ast::VariantData, + generics: Option<&'a ast::Generics>, + span: Span, +} + +impl<'a> StructParts<'a> { + fn format_header(&self) -> String { + format_header(self.prefix, self.ident, self.vis) + } + + fn from_variant(variant: &'a ast::Variant) -> Self { + StructParts { + prefix: "", + ident: variant.node.name, + vis: &ast::Visibility::Inherited, + def: &variant.node.data, + generics: None, + span: variant.span, + } + } + + pub fn from_item(item: &'a ast::Item) -> Self { + let (prefix, def, generics) = match item.node { + ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), + ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), + _ => unreachable!(), + }; + StructParts { + prefix, + ident: item.ident, + vis: &item.vis, + def, + generics: Some(generics), + span: item.span, + } + } +} + +fn format_struct( + context: &RewriteContext, + struct_parts: &StructParts, + offset: Indent, + one_line_width: Option, +) -> Option { + match *struct_parts.def { + ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset), + ast::VariantData::Tuple(ref fields, _) => { + format_tuple_struct(context, struct_parts, fields, offset) + } + ast::VariantData::Struct(ref fields, _) => { + format_struct_struct(context, struct_parts, fields, offset, one_line_width) + } + } +} + +pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = + item.node + { + let mut result = String::with_capacity(128); + let header = format!( + "{}{}trait {}", + format_visibility(&item.vis), + format_unsafety(unsafety), + item.ident + ); + + result.push_str(&header); + + let body_lo = context.snippet_provider.span_after(item.span, "{"); + + let shape = Shape::indented(offset, context.config).offset_left(result.len())?; + let generics_str = + rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; + result.push_str(&generics_str); + + // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. + if !type_param_bounds.is_empty() { + let ident_hi = context + .snippet_provider + .span_after(item.span, &format!("{}", item.ident)); + let bound_hi = type_param_bounds.last().unwrap().span().hi(); + let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); + if contains_comment(snippet) { + return None; + } + } + let trait_bound_str = rewrite_trait_bounds( + context, + type_param_bounds, + Shape::indented(offset, context.config), + )?; + // If the trait, generics, and trait bound cannot fit on the same line, + // put the trait bounds on an indented new line + if offset.width() + last_line_width(&result) + trait_bound_str.len() + > context.config.comment_width() + { + let trait_indent = offset.block_only().block_indent(context.config); + result.push_str(&trait_indent.to_string_with_newline(context.config)); + } + result.push_str(&trait_bound_str); + + let where_density = + if context.config.indent_style() == IndentStyle::Block && result.is_empty() { + Density::Compressed + } else { + Density::Tall + }; + + let where_budget = context.budget(last_line_width(&result)); + let pos_before_where = if type_param_bounds.is_empty() { + generics.where_clause.span.lo() + } else { + type_param_bounds[type_param_bounds.len() - 1].span().hi() + }; + let option = WhereClauseOption::snuggled(&generics_str); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + where_density, + "{", + None, + pos_before_where, + option, + false, + )?; + // If the where clause cannot fit on the same line, + // put the where clause on a new line + if !where_clause_str.contains('\n') + && last_line_width(&result) + where_clause_str.len() + offset.width() + > context.config.comment_width() + { + let width = offset.block_indent + context.config.tab_spaces() - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string_with_newline(context.config)); + } + result.push_str(&where_clause_str); + + if generics.where_clause.predicates.is_empty() { + let item_snippet = context.snippet(item.span); + if let Some(lo) = item_snippet.chars().position(|c| c == '/') { + // 1 = `{` + let comment_hi = body_lo - BytePos(1); + let comment_lo = item.span.lo() + BytePos(lo as u32); + if comment_lo < comment_hi { + match recover_missing_comment_in_span( + mk_sp(comment_lo, comment_hi), + Shape::indented(offset, context.config), + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + } + _ => (), + } + } + } + } + + match context.config.brace_style() { + _ if last_line_contains_single_line_comment(&result) => { + result.push_str(&offset.to_string_with_newline(context.config)); + } + BraceStyle::AlwaysNextLine => { + result.push_str(&offset.to_string_with_newline(context.config)); + } + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() + && (!trait_items.is_empty() || result.contains('\n')) + { + result.push_str(&offset.to_string_with_newline(context.config)); + } else { + result.push(' '); + } + } + } + result.push('{'); + + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + + if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = offset.block_only().block_indent(context.config); + visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); + + for item in trait_items { + visitor.visit_trait_item(item); + } + + visitor.format_missing(item.span.hi() - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); + let outer_indent_str = offset.block_only().to_string_with_newline(context.config); + + result.push_str(&inner_indent_str); + result.push_str(visitor.buffer.to_string().trim()); + result.push_str(&outer_indent_str); + } else if result.contains('\n') { + result.push('\n'); + } + + result.push('}'); + Some(result) + } else { + unreachable!(); + } +} + +pub fn format_trait_alias( + context: &RewriteContext, + ident: ast::Ident, + generics: &ast::Generics, + ty_param_bounds: &ast::TyParamBounds, + shape: Shape, +) -> Option { + let alias = ident.name.as_str(); + // 6 = "trait ", 2 = " =" + let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?; + let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?; + let lhs = format!("trait {}{} =", alias, generics_str); + // 1 = ";" + rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") +} + +fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { + let header_str = format_header(p.prefix, p.ident, p.vis); + let generics_str = if let Some(generics) = p.generics { + let hi = if generics.where_clause.predicates.is_empty() { + generics.span.hi() + } else { + generics.where_clause.span.hi() + }; + format_generics( + context, + generics, + context.config.brace_style(), + BracePos::None, + offset, + mk_sp(generics.span.lo(), hi), + last_line_width(&header_str), + )? + } else { + String::new() + }; + Some(format!("{}{};", header_str, generics_str)) +} + +pub fn format_struct_struct( + context: &RewriteContext, + struct_parts: &StructParts, + fields: &[ast::StructField], + offset: Indent, + one_line_width: Option, +) -> Option { + let mut result = String::with_capacity(1024); + let span = struct_parts.span; + + let header_str = struct_parts.format_header(); + result.push_str(&header_str); + + let header_hi = span.lo() + BytePos(header_str.len() as u32); + let body_lo = context.snippet_provider.span_after(span, "{"); + + let generics_str = match struct_parts.generics { + Some(g) => format_generics( + context, + g, + context.config.brace_style(), + if fields.is_empty() { + BracePos::ForceSameLine + } else { + BracePos::Auto + }, + offset, + mk_sp(header_hi, body_lo), + last_line_width(&result), + )?, + None => { + // 3 = ` {}`, 2 = ` {`. + let overhead = if fields.is_empty() { 3 } else { 2 }; + if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty()) + || context.config.max_width() < overhead + result.len() + { + format!("\n{}{{", offset.block_only().to_string(context.config)) + } else { + " {".to_owned() + } + } + }; + // 1 = `}` + let overhead = if fields.is_empty() { 1 } else { 0 }; + let total_width = result.len() + generics_str.len() + overhead; + if !generics_str.is_empty() && !generics_str.contains('\n') + && total_width > context.config.max_width() + { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + result.push_str(generics_str.trim_left()); + } else { + result.push_str(&generics_str); + } + + if fields.is_empty() { + let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1))); + if snippet.trim().is_empty() { + // `struct S {}` + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { + // fix indent + result.push_str(snippet.trim_right()); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push_str(snippet); + } + result.push('}'); + return Some(result); + } + + // 3 = ` ` and ` }` + let one_line_budget = context.budget(result.len() + 3 + offset.width()); + let one_line_budget = + one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget)); + + let items_str = rewrite_with_alignment( + fields, + context, + Shape::indented(offset, context.config).sub_width(1)?, + mk_sp(body_lo, span.hi()), + one_line_budget, + )?; + + if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget + && !last_line_contains_single_line_comment(&items_str) + { + Some(format!("{} {} }}", result, items_str)) + } else { + Some(format!( + "{}\n{}{}\n{}}}", + result, + offset + .block_indent(context.config) + .to_string(context.config), + items_str, + offset.to_string(context.config) + )) + } +} + +/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not +/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need +/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args. +fn get_bytepos_after_visibility( + context: &RewriteContext, + vis: &ast::Visibility, + default_span: Span, + terminator: &str, +) -> BytePos { + match *vis { + ast::Visibility::Crate(s, CrateSugar::PubCrate) => context + .snippet_provider + .span_after(mk_sp(s.hi(), default_span.hi()), terminator), + ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), + ast::Visibility::Restricted { ref path, .. } => path.span.hi(), + _ => default_span.lo(), + } +} + +fn format_tuple_struct( + context: &RewriteContext, + struct_parts: &StructParts, + fields: &[ast::StructField], + offset: Indent, +) -> Option { + let mut result = String::with_capacity(1024); + let span = struct_parts.span; + + let header_str = struct_parts.format_header(); + result.push_str(&header_str); + + let body_lo = if fields.is_empty() { + let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")"); + context + .snippet_provider + .span_after(mk_sp(lo, span.hi()), "(") + } else { + fields[0].span.lo() + }; + let body_hi = if fields.is_empty() { + context + .snippet_provider + .span_after(mk_sp(body_lo, span.hi()), ")") + } else { + // This is a dirty hack to work around a missing `)` from the span of the last field. + let last_arg_span = fields[fields.len() - 1].span; + if context.snippet(last_arg_span).ends_with(')') { + last_arg_span.hi() + } else { + context + .snippet_provider + .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") + } + }; + + let where_clause_str = match struct_parts.generics { + Some(generics) => { + let budget = context.budget(last_line_width(&header_str)); + let shape = Shape::legacy(budget, offset); + let g_span = mk_sp(span.lo(), body_lo); + let generics_str = rewrite_generics(context, generics, shape, g_span)?; + result.push_str(&generics_str); + + let where_budget = context.budget(last_line_width(&result)); + let option = WhereClauseOption::new(true, false); + rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + Density::Compressed, + ";", + None, + body_hi, + option, + false, + )? + } + None => "".to_owned(), + }; + + if fields.is_empty() { + // 3 = `();` + let used_width = last_line_used_width(&result, offset.width()) + 3; + if used_width > context.config.max_width() { + result.push('\n'); + result.push_str(&offset + .block_indent(context.config) + .to_string(context.config)) + } + result.push('('); + let snippet = context.snippet(mk_sp( + body_lo, + context + .snippet_provider + .span_before(mk_sp(body_lo, span.hi()), ")"), + )); + if snippet.is_empty() { + // `struct S ()` + } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { + result.push_str(snippet.trim_right()); + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push_str(snippet); + } + result.push(')'); + } else { + let shape = Shape::indented(offset, context.config).sub_width(1)?; + let fields = &fields.iter().collect::>()[..]; + let one_line_width = context.config.width_heuristics().fn_call_width; + result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; + } + + if !where_clause_str.is_empty() && !where_clause_str.contains('\n') + && (result.contains('\n') + || offset.block_indent + result.len() + where_clause_str.len() + 1 + > context.config.max_width()) + { + // We need to put the where clause on a new line, but we didn't + // know that earlier, so the where clause will not be indented properly. + result.push('\n'); + result + .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) + .to_string(context.config)); + } + result.push_str(&where_clause_str); + + Some(result) +} + +pub fn rewrite_type_alias( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + ty: &ast::Ty, + generics: &ast::Generics, + vis: &ast::Visibility, + span: Span, +) -> Option { + let mut result = String::with_capacity(128); + + result.push_str(&format_visibility(vis)); + result.push_str("type "); + result.push_str(&ident.to_string()); + + // 2 = `= ` + let g_shape = Shape::indented(indent, context.config) + .offset_left(result.len())? + .sub_width(2)?; + let g_span = mk_sp( + context.snippet_provider.span_after(span, "type"), + ty.span.lo(), + ); + let generics_str = rewrite_generics(context, generics, g_shape, g_span)?; + result.push_str(&generics_str); + + let where_budget = context.budget(last_line_width(&result)); + let option = WhereClauseOption::snuggled(&result); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, indent), + Density::Vertical, + "=", + Some(span.hi()), + generics.span.hi(), + option, + false, + )?; + result.push_str(&where_clause_str); + if where_clause_str.is_empty() { + result.push_str(" ="); + } else { + result.push_str(&format!( + "{}=", + indent.to_string_with_newline(context.config) + )); + } + + // 1 = ";" + let ty_shape = Shape::indented(indent, context.config).sub_width(1)?; + rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";") +} + +fn type_annotation_spacing(config: &Config) -> (&str, &str) { + ( + if config.space_before_colon() { " " } else { "" }, + if config.space_after_colon() { " " } else { "" }, + ) +} + +pub fn rewrite_struct_field_prefix( + context: &RewriteContext, + field: &ast::StructField, +) -> Option { + let vis = format_visibility(&field.vis); + let type_annotation_spacing = type_annotation_spacing(context.config); + Some(match field.ident { + Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), + None => format!("{}", vis), + }) +} + +impl Rewrite for ast::StructField { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_struct_field(context, self, shape, 0) + } +} + +pub fn rewrite_struct_field( + context: &RewriteContext, + field: &ast::StructField, + shape: Shape, + lhs_max_width: usize, +) -> Option { + if contains_skip(&field.attrs) { + return Some(context.snippet(field.span()).to_owned()); + } + + let type_annotation_spacing = type_annotation_spacing(context.config); + let prefix = rewrite_struct_field_prefix(context, field)?; + + let attrs_str = field.attrs.rewrite(context, shape)?; + let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str); + let missing_span = if field.attrs.is_empty() { + mk_sp(field.span.lo(), field.span.lo()) + } else { + mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo()) + }; + let mut spacing = String::from(if field.ident.is_some() { + type_annotation_spacing.1 + } else { + "" + }); + // Try to put everything on a single line. + let attr_prefix = combine_strs_with_missing_comments( + context, + &attrs_str, + &prefix, + missing_span, + shape, + attrs_extendable, + )?; + let overhead = last_line_width(&attr_prefix); + let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); + for _ in 0..lhs_offset { + spacing.push(' '); + } + // In this extreme case we will be missing a space betweeen an attribute and a field. + if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { + spacing.push(' '); + } + let orig_ty = shape + .offset_left(overhead + spacing.len()) + .and_then(|ty_shape| field.ty.rewrite(context, ty_shape)); + if let Some(ref ty) = orig_ty { + if !ty.contains('\n') { + return Some(attr_prefix + &spacing + ty); + } + } + + let is_prefix_empty = prefix.is_empty(); + // We must use multiline. We are going to put attributes and a field on different lines. + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; + // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. + let field_str = if is_prefix_empty { + field_str.trim_left() + } else { + &field_str + }; + combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) +} + +pub struct StaticParts<'a> { + prefix: &'a str, + vis: &'a ast::Visibility, + ident: ast::Ident, + ty: &'a ast::Ty, + mutability: ast::Mutability, + expr_opt: Option<&'a ptr::P>, + defaultness: Option, + span: Span, +} + +impl<'a> StaticParts<'a> { + pub fn from_item(item: &'a ast::Item) -> Self { + let (prefix, ty, mutability, expr) = match item.node { + ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), + ast::ItemKind::Const(ref ty, ref expr) => { + ("const", ty, ast::Mutability::Immutable, expr) + } + _ => unreachable!(), + }; + StaticParts { + prefix, + vis: &item.vis, + ident: item.ident, + ty, + mutability, + expr_opt: Some(expr), + defaultness: None, + span: item.span, + } + } + + pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self { + let (ty, expr_opt) = match ti.node { + ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), + _ => unreachable!(), + }; + StaticParts { + prefix: "const", + vis: &ast::Visibility::Inherited, + ident: ti.ident, + ty, + mutability: ast::Mutability::Immutable, + expr_opt: expr_opt.as_ref(), + defaultness: None, + span: ti.span, + } + } + + pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self { + let (ty, expr) = match ii.node { + ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), + _ => unreachable!(), + }; + StaticParts { + prefix: "const", + vis: &ii.vis, + ident: ii.ident, + ty, + mutability: ast::Mutability::Immutable, + expr_opt: Some(expr), + defaultness: Some(ii.defaultness), + span: ii.span, + } + } +} + +fn rewrite_static( + context: &RewriteContext, + static_parts: &StaticParts, + offset: Indent, +) -> Option { + let colon = colon_spaces( + context.config.space_before_colon(), + context.config.space_after_colon(), + ); + let mut prefix = format!( + "{}{}{} {}{}{}", + format_visibility(static_parts.vis), + static_parts.defaultness.map_or("", format_defaultness), + static_parts.prefix, + format_mutability(static_parts.mutability), + static_parts.ident, + colon, + ); + // 2 = " =".len() + let ty_shape = + Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?; + let ty_str = match static_parts.ty.rewrite(context, ty_shape) { + Some(ty_str) => ty_str, + None => { + if prefix.ends_with(' ') { + prefix.pop(); + } + let nested_indent = offset.block_indent(context.config); + let nested_shape = Shape::indented(nested_indent, context.config); + let ty_str = static_parts.ty.rewrite(context, nested_shape)?; + format!( + "{}{}", + nested_indent.to_string_with_newline(context.config), + ty_str + ) + } + }; + + if let Some(expr) = static_parts.expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.budget(offset.block_indent + 1); + rewrite_assign_rhs( + context, + lhs, + &**expr, + Shape::legacy(remaining_width, offset.block_only()), + ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) + .map(|s| if s.ends_with(';') { s } else { s + ";" }) + } else { + Some(format!("{}{};", prefix, ty_str)) + } +} + +pub fn rewrite_associated_type( + ident: ast::Ident, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent, +) -> Option { + let prefix = format!("type {}", ident); + + let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { + // 2 = ": ".len() + let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; + let bound_str = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; + if !bounds.is_empty() { + format!(": {}", join_bounds(context, shape, &bound_str)) + } else { + String::new() + } + } else { + String::new() + }; + + if let Some(ty) = ty_opt { + // 1 = `;` + let shape = Shape::indented(indent, context.config).sub_width(1)?; + let lhs = format!("{}{} =", prefix, type_bounds_str); + rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") + } else { + Some(format!("{}{};", prefix, type_bounds_str)) + } +} + +pub fn rewrite_associated_impl_type( + ident: ast::Ident, + defaultness: ast::Defaultness, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent, +) -> Option { + let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?; + + match defaultness { + ast::Defaultness::Default => Some(format!("default {}", result)), + _ => Some(result), + } +} + +impl Rewrite for ast::FunctionRetTy { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::FunctionRetTy::Default(_) => Some(String::new()), + ast::FunctionRetTy::Ty(ref ty) => { + let inner_width = shape.width.checked_sub(3)?; + ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) + .map(|r| format!("-> {}", r)) + } + } + } +} + +fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { + match ty.node { + ast::TyKind::Infer => { + let original = context.snippet(ty.span); + original != "_" + } + _ => false, + } +} + +impl Rewrite for ast::Arg { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + if is_named_arg(self) { + let mut result = self.pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))?; + + if !is_empty_infer(context, &*self.ty) { + if context.config.space_before_colon() { + result.push_str(" "); + } + result.push_str(":"); + if context.config.space_after_colon() { + result.push_str(" "); + } + let overhead = last_line_width(&result); + let max_width = shape.width.checked_sub(overhead)?; + let ty_str = self.ty + .rewrite(context, Shape::legacy(max_width, shape.indent))?; + result.push_str(&ty_str); + } + + Some(result) + } else { + self.ty.rewrite(context, shape) + } + } +} + +fn rewrite_explicit_self( + explicit_self: &ast::ExplicitSelf, + args: &[ast::Arg], + context: &RewriteContext, +) -> Option { + match explicit_self.node { + ast::SelfKind::Region(lt, m) => { + let mut_str = format_mutability(m); + match lt { + Some(ref l) => { + let lifetime_str = l.rewrite( + context, + Shape::legacy(context.config.max_width(), Indent::empty()), + )?; + Some(format!("&{} {}self", lifetime_str, mut_str)) + } + None => Some(format!("&{}self", mut_str)), + } + } + ast::SelfKind::Explicit(ref ty, _) => { + assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); + + let mutability = explicit_self_mutability(&args[0]); + let type_str = ty.rewrite( + context, + Shape::legacy(context.config.max_width(), Indent::empty()), + )?; + + Some(format!( + "{}self: {}", + format_mutability(mutability), + type_str + )) + } + ast::SelfKind::Value(_) => { + assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); + + let mutability = explicit_self_mutability(&args[0]); + + Some(format!("{}self", format_mutability(mutability))) + } + } +} + +// Hacky solution caused by absence of `Mutability` in `SelfValue` and +// `SelfExplicit` variants of `ast::ExplicitSelf_`. +fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { + if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node { + mutability + } else { + unreachable!() + } +} + +pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { + if is_named_arg(arg) { + arg.pat.span.lo() + } else { + arg.ty.span.lo() + } +} + +pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { + match arg.ty.node { + ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), + ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), + _ => arg.ty.span.hi(), + } +} + +pub fn is_named_arg(arg: &ast::Arg) -> bool { + if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { + ident.node != symbol::keywords::Invalid.ident() + } else { + true + } +} + +// Return type is (result, force_new_line_for_brace) +fn rewrite_fn_base( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + fn_sig: &FnSig, + span: Span, + newline_brace: bool, + has_body: bool, +) -> Option<(String, bool)> { + let mut force_new_line_for_brace = false; + + let where_clause = &fn_sig.generics.where_clause; + + let mut result = String::with_capacity(1024); + result.push_str(&fn_sig.to_str(context)); + + // fn foo + result.push_str("fn "); + result.push_str(&ident.to_string()); + + // Generics. + let overhead = if has_body && !newline_brace { + // 4 = `() {` + 4 + } else { + // 2 = `()` + 2 + }; + let used_width = last_line_used_width(&result, indent.width()); + let one_line_budget = context.budget(used_width + overhead); + let shape = Shape { + width: one_line_budget, + indent, + offset: used_width, + }; + let fd = fn_sig.decl; + let g_span = mk_sp(span.lo(), fd.output.span().lo()); + let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?; + result.push_str(&generics_str); + + let snuggle_angle_bracket = generics_str + .lines() + .last() + .map_or(false, |l| l.trim_left().len() == 1); + + // Note that the width and indent don't really matter, we'll re-layout the + // return type later anyway. + let ret_str = fd.output + .rewrite(context, Shape::indented(indent, context.config))?; + + let multi_line_ret_str = ret_str.contains('\n'); + let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; + + // Args. + let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args( + context, + &result, + indent, + ret_str_len, + newline_brace, + has_body, + multi_line_ret_str, + )?; + + debug!( + "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", + one_line_budget, multi_line_budget, arg_indent + ); + + // Check if vertical layout was forced. + if one_line_budget == 0 { + if snuggle_angle_bracket { + result.push('('); + } else { + result.push_str("("); + if context.config.indent_style() == IndentStyle::Visual { + result.push_str(&arg_indent.to_string_with_newline(context.config)); + } + } + } else { + result.push('('); + } + if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() + && result.ends_with('(') + { + result.push(' ') + } + + // Skip `pub(crate)`. + let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")"); + // A conservative estimation, to goal is to be over all parens in generics + let args_start = fn_sig + .generics + .params + .iter() + .last() + .map_or(lo_after_visibility, |param| param.span().hi()); + let args_end = if fd.inputs.is_empty() { + context + .snippet_provider + .span_after(mk_sp(args_start, span.hi()), ")") + } else { + let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); + context.snippet_provider.span_after(last_span, ")") + }; + let args_span = mk_sp( + context + .snippet_provider + .span_after(mk_sp(args_start, span.hi()), "("), + args_end, + ); + let arg_str = rewrite_args( + context, + &fd.inputs, + fd.get_self().as_ref(), + one_line_budget, + multi_line_budget, + indent, + arg_indent, + args_span, + fd.variadic, + generics_str.contains('\n'), + )?; + + let put_args_in_block = match context.config.indent_style() { + IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, + _ => false, + } && !fd.inputs.is_empty(); + + let mut args_last_line_contains_comment = false; + if put_args_in_block { + arg_indent = indent.block_indent(context.config); + result.push_str(&arg_indent.to_string_with_newline(context.config)); + result.push_str(&arg_str); + result.push_str(&indent.to_string_with_newline(context.config)); + result.push(')'); + } else { + result.push_str(&arg_str); + let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); + // Put the closing brace on the next line if it overflows the max width. + // 1 = `)` + if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { + result.push('\n'); + } + if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() { + result.push(' ') + } + // If the last line of args contains comment, we cannot put the closing paren + // on the same line. + if arg_str + .lines() + .last() + .map_or(false, |last_line| last_line.contains("//")) + { + args_last_line_contains_comment = true; + result.push_str(&arg_indent.to_string_with_newline(context.config)); + } + result.push(')'); + } + + // Return type. + if let ast::FunctionRetTy::Ty(..) = fd.output { + let ret_should_indent = match context.config.indent_style() { + // If our args are block layout then we surely must have space. + IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, + _ if args_last_line_contains_comment => false, + _ if result.contains('\n') || multi_line_ret_str => true, + _ => { + // If the return type would push over the max width, then put the return type on + // a new line. With the +1 for the signature length an additional space between + // the closing parenthesis of the argument and the arrow '->' is considered. + let mut sig_length = result.len() + indent.width() + ret_str_len + 1; + + // If there is no where clause, take into account the space after the return type + // and the brace. + if where_clause.predicates.is_empty() { + sig_length += 2; + } + + sig_length > context.config.max_width() + } + }; + let ret_indent = if ret_should_indent { + let indent = if arg_str.is_empty() { + // Aligning with non-existent args looks silly. + force_new_line_for_brace = true; + indent + 4 + } else { + // FIXME: we might want to check that using the arg indent + // doesn't blow our budget, and if it does, then fallback to + // the where clause indent. + arg_indent + }; + + result.push_str(&indent.to_string_with_newline(context.config)); + indent + } else { + result.push(' '); + Indent::new(indent.block_indent, last_line_width(&result)) + }; + + if multi_line_ret_str || ret_should_indent { + // Now that we know the proper indent and width, we need to + // re-layout the return type. + let ret_str = fd.output + .rewrite(context, Shape::indented(ret_indent, context.config))?; + result.push_str(&ret_str); + } else { + result.push_str(&ret_str); + } + + // Comment between return type and the end of the decl. + let snippet_lo = fd.output.span().hi(); + if where_clause.predicates.is_empty() { + let snippet_hi = span.hi(); + let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi)); + // Try to preserve the layout of the original snippet. + let original_starts_with_newline = snippet + .find(|c| c != ' ') + .map_or(false, |i| starts_with_newline(&snippet[i..])); + let original_ends_with_newline = snippet + .rfind(|c| c != ' ') + .map_or(false, |i| snippet[i..].ends_with('\n')); + let snippet = snippet.trim(); + if !snippet.is_empty() { + result.push(if original_starts_with_newline { + '\n' + } else { + ' ' + }); + result.push_str(snippet); + if original_ends_with_newline { + force_new_line_for_brace = true; + } + } + } + } + + let pos_before_where = match fd.output { + ast::FunctionRetTy::Default(..) => args_span.hi(), + ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), + }; + + let is_args_multi_lined = arg_str.contains('\n'); + + let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); + let where_clause_str = rewrite_where_clause( + context, + where_clause, + context.config.brace_style(), + Shape::indented(indent, context.config), + Density::Tall, + "{", + Some(span.hi()), + pos_before_where, + option, + is_args_multi_lined, + )?; + // If there are neither where clause nor return type, we may be missing comments between + // args and `{`. + if where_clause_str.is_empty() { + if let ast::FunctionRetTy::Default(ret_span) = fd.output { + match recover_missing_comment_in_span( + mk_sp(args_span.hi(), ret_span.hi()), + shape, + context, + last_line_width(&result), + ) { + Some(ref missing_comment) if !missing_comment.is_empty() => { + result.push_str(missing_comment); + force_new_line_for_brace = true; + } + _ => (), + } + } + } + + result.push_str(&where_clause_str); + + force_new_line_for_brace |= last_line_contains_single_line_comment(&result); + force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line(); + Some((result, force_new_line_for_brace)) +} + +#[derive(Copy, Clone)] +struct WhereClauseOption { + suppress_comma: bool, // Force no trailing comma + snuggle: bool, // Do not insert newline before `where` + compress_where: bool, // Try single line where clause instead of vertical layout +} + +impl WhereClauseOption { + pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { + WhereClauseOption { + suppress_comma, + snuggle, + compress_where: false, + } + } + + pub fn snuggled(current: &str) -> WhereClauseOption { + WhereClauseOption { + suppress_comma: false, + snuggle: trimmed_last_line_width(current) == 1, + compress_where: false, + } + } +} + +fn rewrite_args( + context: &RewriteContext, + args: &[ast::Arg], + explicit_self: Option<&ast::ExplicitSelf>, + one_line_budget: usize, + multi_line_budget: usize, + indent: Indent, + arg_indent: Indent, + span: Span, + variadic: bool, + generics_str_contains_newline: bool, +) -> Option { + let mut arg_item_strs = args.iter() + .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) + .collect::>>()?; + + // Account for sugary self. + // FIXME: the comment for the self argument is dropped. This is blocked + // on rust issue #27522. + let min_args = explicit_self + .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) + .map_or(1, |self_str| { + arg_item_strs[0] = self_str; + 2 + }); + + // Comments between args. + let mut arg_items = Vec::new(); + if min_args == 2 { + arg_items.push(ListItem::from_str("")); + } + + // FIXME(#21): if there are no args, there might still be a comment, but + // without spans for the comment or parens, there is no chance of + // getting it right. You also don't get to put a comment on self, unless + // it is explicit. + if args.len() >= min_args || variadic { + let comment_span_start = if min_args == 2 { + let second_arg_start = if arg_has_pattern(&args[1]) { + args[1].pat.span.lo() + } else { + args[1].ty.span.lo() + }; + let reduced_span = mk_sp(span.lo(), second_arg_start); + + context.snippet_provider.span_after_last(reduced_span, ",") + } else { + span.lo() + }; + + enum ArgumentKind<'a> { + Regular(&'a ast::Arg), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi()); + let variadic_start = + context.snippet_provider.span_after(variadic_span, "...") - BytePos(3); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + + let more_items = itemize_list( + context.snippet_provider, + args[min_args - 1..] + .iter() + .map(ArgumentKind::Regular) + .chain(variadic_arg), + ")", + ",", + |arg| match *arg { + ArgumentKind::Regular(arg) => span_lo_for_arg(arg), + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(arg) => arg.ty.span.hi(), + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(..) => None, + ArgumentKind::Variadic(..) => Some("...".to_owned()), + }, + comment_span_start, + span.hi(), + false, + ); + + arg_items.extend(more_items); + } + + let fits_in_one_line = !generics_str_contains_newline + && (arg_items.is_empty() + || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + + for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { + item.item = Some(arg); + } + + let last_line_ends_with_comment = arg_items + .iter() + .last() + .and_then(|item| item.post_comment.as_ref()) + .map_or(false, |s| s.trim().starts_with("//")); + + let (indent, trailing_comma) = match context.config.indent_style() { + IndentStyle::Block if fits_in_one_line => { + (indent.block_indent(context.config), SeparatorTactic::Never) + } + IndentStyle::Block => ( + indent.block_indent(context.config), + context.config.trailing_comma(), + ), + IndentStyle::Visual if last_line_ends_with_comment => { + (arg_indent, context.config.trailing_comma()) + } + IndentStyle::Visual => (arg_indent, SeparatorTactic::Never), + }; + + let tactic = definitive_tactic( + &arg_items, + context.config.fn_args_density().to_list_tactic(), + Separator::Comma, + one_line_budget, + ); + let budget = match tactic { + DefinitiveListTactic::Horizontal => one_line_budget, + _ => multi_line_budget, + }; + + debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if variadic { + SeparatorTactic::Never + } else { + trailing_comma + }, + separator_place: SeparatorPlace::Back, + shape: Shape::legacy(budget, indent), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + + write_list(&arg_items, &fmt) +} + +fn arg_has_pattern(arg: &ast::Arg) -> bool { + if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { + ident.node != symbol::keywords::Invalid.ident() + } else { + true + } +} + +fn compute_budgets_for_args( + context: &RewriteContext, + result: &str, + indent: Indent, + ret_str_len: usize, + newline_brace: bool, + has_braces: bool, + force_vertical_layout: bool, +) -> Option<((usize, usize, Indent))> { + debug!( + "compute_budgets_for_args {} {:?}, {}, {}", + result.len(), + indent, + ret_str_len, + newline_brace + ); + // Try keeping everything on the same line. + if !result.contains('\n') && !force_vertical_layout { + // 2 = `()`, 3 = `() `, space is before ret_string. + let overhead = if ret_str_len == 0 { 2 } else { 3 }; + let mut used_space = indent.width() + result.len() + ret_str_len + overhead; + if has_braces { + if !newline_brace { + // 2 = `{}` + used_space += 2; + } + } else { + // 1 = `;` + used_space += 1; + } + let one_line_budget = context.budget(used_space); + + if one_line_budget > 0 { + // 4 = "() {".len() + let (indent, multi_line_budget) = match context.config.indent_style() { + IndentStyle::Block => { + let indent = indent.block_indent(context.config); + (indent, context.budget(indent.width() + 1)) + } + IndentStyle::Visual => { + let indent = indent + result.len() + 1; + let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; + (indent, context.budget(multi_line_overhead)) + } + }; + + return Some((one_line_budget, multi_line_budget, indent)); + } + } + + // Didn't work. we must force vertical layout and put args on a newline. + let new_indent = indent.block_indent(context.config); + let used_space = match context.config.indent_style() { + // 1 = `,` + IndentStyle::Block => new_indent.width() + 1, + // Account for `)` and possibly ` {`. + IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, + }; + Some((0, context.budget(used_space), new_indent)) +} + +fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { + let predicate_count = where_clause.predicates.len(); + + if config.where_single_line() && predicate_count == 1 { + return false; + } + let brace_style = config.brace_style(); + + brace_style == BraceStyle::AlwaysNextLine + || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0) +} + +fn rewrite_generics( + context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + span: Span, +) -> Option { + let g_shape = generics_shape_from_config(context.config, shape, 0)?; + let one_line_width = shape.width.checked_sub(2).unwrap_or(0); + rewrite_generics_inner(context, generics, g_shape, one_line_width, span) + .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span)) +} + +fn rewrite_generics_inner( + context: &RewriteContext, + generics: &ast::Generics, + shape: Shape, + one_line_width: usize, + span: Span, +) -> Option { + // FIXME: convert bounds to where clauses where they get too big or if + // there is a where clause at all. + + if generics.params.is_empty() { + return Some(String::new()); + } + + let items = itemize_list( + context.snippet_provider, + generics.params.iter(), + ">", + ",", + |arg| arg.span().lo(), + |arg| arg.span().hi(), + |arg| arg.rewrite(context, shape), + context.snippet_provider.span_after(span, "<"), + span.hi(), + false, + ); + format_generics_item_list(context, items, shape, one_line_width) +} + +pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { + match config.indent_style() { + IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), + IndentStyle::Block => { + // 1 = "," + shape + .block() + .block_indent(config.tab_spaces()) + .with_max_width(config) + .sub_width(1) + } + } +} + +pub fn format_generics_item_list( + context: &RewriteContext, + items: I, + shape: Shape, + one_line_budget: usize, +) -> Option +where + I: Iterator, +{ + let item_vec = items.collect::>(); + + let tactic = definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + one_line_budget, + ); + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if context.config.indent_style() == IndentStyle::Visual { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + + let list_str = write_list(&item_vec, &fmt)?; + + Some(wrap_generics_with_angle_brackets( + context, + &list_str, + shape.indent, + )) +} + +pub fn wrap_generics_with_angle_brackets( + context: &RewriteContext, + list_str: &str, + list_offset: Indent, +) -> String { + if context.config.indent_style() == IndentStyle::Block + && (list_str.contains('\n') || list_str.ends_with(',')) + { + format!( + "<\n{}{}\n{}>", + list_offset.to_string(context.config), + list_str, + list_offset + .block_unindent(context.config) + .to_string(context.config) + ) + } else if context.config.spaces_within_parens_and_brackets() { + format!("< {} >", list_str) + } else { + format!("<{}>", list_str) + } +} + +fn rewrite_trait_bounds( + context: &RewriteContext, + bounds: &[ast::TyParamBound], + shape: Shape, +) -> Option { + if bounds.is_empty() { + return Some(String::new()); + } + let bound_str = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; + Some(format!(": {}", join_bounds(context, shape, &bound_str))) +} + +fn rewrite_where_clause_rfc_style( + context: &RewriteContext, + where_clause: &ast::WhereClause, + shape: Shape, + terminator: &str, + span_end: Option, + span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, + is_args_multi_line: bool, +) -> Option { + let block_shape = shape.block().with_max_width(context.config); + + let (span_before, span_after) = + missing_span_before_after_where(span_end_before_where, where_clause); + let (comment_before, comment_after) = + rewrite_comments_before_after_where(context, span_before, span_after, shape)?; + + let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { + Cow::from(" ") + } else { + block_shape.indent.to_string_with_newline(context.config) + }; + + let clause_shape = block_shape.block_left(context.config.tab_spaces())?; + // 1 = `,` + let clause_shape = clause_shape.sub_width(1)?; + // each clause on one line, trailing comma (except if suppress_comma) + let span_start = where_clause.predicates[0].span().lo(); + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = where_clause.predicates[len - 1].span().hi(); + let span_end = span_end.unwrap_or(end_of_preds); + let items = itemize_list( + context.snippet_provider, + where_clause.predicates.iter(), + terminator, + ",", + |pred| pred.span().lo(), + |pred| pred.span().hi(), + |pred| pred.rewrite(context, clause_shape), + span_start, + span_end, + false, + ); + let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line; + let comma_tactic = if where_clause_option.suppress_comma || where_single_line { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }; + + // shape should be vertical only and only if we have `where_single_line` option enabled + // and the number of items of the where clause is equal to 1 + let shape_tactic = if where_single_line { + DefinitiveListTactic::Horizontal + } else { + DefinitiveListTactic::Vertical + }; + + let fmt = ListFormatting { + tactic: shape_tactic, + separator: ",", + trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, + shape: clause_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + let preds_str = write_list(&items.collect::>(), &fmt)?; + + let comment_separator = |comment: &str, shape: Shape| { + if comment.is_empty() { + Cow::from("") + } else { + shape.indent.to_string_with_newline(context.config) + } + }; + let newline_before_where = comment_separator(&comment_before, shape); + let newline_after_where = comment_separator(&comment_after, clause_shape); + + // 6 = `where ` + let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() + && comment_after.is_empty() && !preds_str.contains('\n') + && 6 + preds_str.len() <= shape.width || where_single_line + { + Cow::from(" ") + } else { + clause_shape.indent.to_string_with_newline(context.config) + }; + Some(format!( + "{}{}{}where{}{}{}{}", + starting_newline, + comment_before, + newline_before_where, + newline_after_where, + comment_after, + clause_sep, + preds_str + )) +} + +fn rewrite_where_clause( + context: &RewriteContext, + where_clause: &ast::WhereClause, + brace_style: BraceStyle, + shape: Shape, + density: Density, + terminator: &str, + span_end: Option, + span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, + is_args_multi_line: bool, +) -> Option { + if where_clause.predicates.is_empty() { + return Some(String::new()); + } + + if context.config.indent_style() == IndentStyle::Block { + return rewrite_where_clause_rfc_style( + context, + where_clause, + shape, + terminator, + span_end, + span_end_before_where, + where_clause_option, + is_args_multi_line, + ); + } + + let extra_indent = Indent::new(context.config.tab_spaces(), 0); + + let offset = match context.config.indent_style() { + IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config), + // 6 = "where ".len() + IndentStyle::Visual => shape.indent + extra_indent + 6, + }; + // FIXME: if indent_style != Visual, then the budgets below might + // be out by a char or two. + + let budget = context.config.max_width() - offset.width(); + let span_start = where_clause.predicates[0].span().lo(); + // If we don't have the start of the next span, then use the end of the + // predicates, but that means we miss comments. + let len = where_clause.predicates.len(); + let end_of_preds = where_clause.predicates[len - 1].span().hi(); + let span_end = span_end.unwrap_or(end_of_preds); + let items = itemize_list( + context.snippet_provider, + where_clause.predicates.iter(), + terminator, + ",", + |pred| pred.span().lo(), + |pred| pred.span().hi(), + |pred| pred.rewrite(context, Shape::legacy(budget, offset)), + span_start, + span_end, + false, + ); + let item_vec = items.collect::>(); + // FIXME: we don't need to collect here + let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget); + + let mut comma_tactic = context.config.trailing_comma(); + // Kind of a hack because we don't usually have trailing commas in where clauses. + if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma { + comma_tactic = SeparatorTactic::Never; + } + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: comma_tactic, + separator_place: SeparatorPlace::Back, + shape: Shape::legacy(budget, offset), + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + let preds_str = write_list(&item_vec, &fmt)?; + + let end_length = if terminator == "{" { + // If the brace is on the next line we don't need to count it otherwise it needs two + // characters " {" + match brace_style { + BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0, + BraceStyle::PreferSameLine => 2, + } + } else if terminator == "=" { + 2 + } else { + terminator.len() + }; + if density == Density::Tall || preds_str.contains('\n') + || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width + { + Some(format!( + "\n{}where {}", + (shape.indent + extra_indent).to_string(context.config), + preds_str + )) + } else { + Some(format!(" where {}", preds_str)) + } +} + +fn missing_span_before_after_where( + before_item_span_end: BytePos, + where_clause: &ast::WhereClause, +) -> (Span, Span) { + let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo()); + // 5 = `where` + let pos_after_where = where_clause.span.lo() + BytePos(5); + let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo()); + (missing_span_before, missing_span_after) +} + +fn rewrite_comments_before_after_where( + context: &RewriteContext, + span_before_where: Span, + span_after_where: Span, + shape: Shape, +) -> Option<(String, String)> { + let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; + let after_comment = rewrite_missing_comment( + span_after_where, + shape.block_indent(context.config.tab_spaces()), + context, + )?; + Some((before_comment, after_comment)) +} + +fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { + format!("{}{}{}", format_visibility(vis), item_name, ident) +} + +#[derive(PartialEq, Eq, Clone, Copy)] +enum BracePos { + None, + Auto, + ForceSameLine, +} + +fn format_generics( + context: &RewriteContext, + generics: &ast::Generics, + brace_style: BraceStyle, + brace_pos: BracePos, + offset: Indent, + span: Span, + used_width: usize, +) -> Option { + let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); + let mut result = rewrite_generics(context, generics, shape, span)?; + + let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { + let budget = context.budget(last_line_used_width(&result, offset.width())); + let mut option = WhereClauseOption::snuggled(&result); + if brace_pos == BracePos::None { + option.suppress_comma = true; + } + // If the generics are not parameterized then generics.span.hi() == 0, + // so we use span.lo(), which is the position after `struct Foo`. + let span_end_before_where = if generics.is_parameterized() { + generics.span.hi() + } else { + span.lo() + }; + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + brace_style, + Shape::legacy(budget, offset.block_only()), + Density::Tall, + "{", + Some(span.hi()), + span_end_before_where, + option, + false, + )?; + result.push_str(&where_clause_str); + brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine + || (generics.where_clause.predicates.is_empty() + && trimmed_last_line_width(&result) == 1) + } else { + brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1 + || brace_style != BraceStyle::AlwaysNextLine + }; + if brace_pos == BracePos::None { + return Some(result); + } + let total_used_width = last_line_used_width(&result, used_width); + let remaining_budget = context.budget(total_used_width); + // If the same line brace if forced, it indicates that we are rewriting an item with empty body, + // and hence we take the closer into account as well for one line budget. + // We assume that the closer has the same length as the opener. + let overhead = if brace_pos == BracePos::ForceSameLine { + // 3 = ` {}` + 3 + } else { + // 2 = ` {` + 2 + }; + let forbid_same_line_brace = overhead > remaining_budget; + if !forbid_same_line_brace && same_line_brace { + result.push(' '); + } else { + result.push('\n'); + result.push_str(&offset.block_only().to_string(context.config)); + } + result.push('{'); + + Some(result) +} + +impl Rewrite for ast::ForeignItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = self.attrs.rewrite(context, shape)?; + // Drop semicolon or it will be interpreted as comment. + // FIXME: this may be a faulty span from libsyntax. + let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); + + let item_str = match self.node { + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { + rewrite_fn_base( + context, + shape.indent, + self.ident, + &FnSig::new(fn_decl, generics, self.vis.clone()), + span, + false, + false, + ).map(|(s, _)| format!("{};", s)) + } + ast::ForeignItemKind::Static(ref ty, is_mutable) => { + // FIXME(#21): we're dropping potential comments in between the + // function keywords here. + let vis = format_visibility(&self.vis); + let mut_str = if is_mutable { "mut " } else { "" }; + let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); + // 1 = ; + let shape = shape.sub_width(1)?; + ty.rewrite(context, shape).map(|ty_str| { + // 1 = space between prefix and type. + let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { + Cow::from(" ") + } else { + let nested_indent = shape.indent.block_indent(context.config); + nested_indent.to_string_with_newline(context.config) + }; + format!("{}{}{};", prefix, sep, ty_str) + }) + } + ast::ForeignItemKind::Ty => { + let vis = format_visibility(&self.vis); + Some(format!("{}type {};", vis, self.ident)) + } + }?; + + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo(), self.span.lo()) + } else { + mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo()) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missing_span, + shape, + false, + ) + } +} + +impl Rewrite for ast::GenericParam { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape), + ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape), + } + } +} + +/// Rewrite an inline mod. +pub fn rewrite_mod(item: &ast::Item) -> String { + let mut result = String::with_capacity(32); + result.push_str(&*format_visibility(&item.vis)); + result.push_str("mod "); + result.push_str(&item.ident.to_string()); + result.push(';'); + result +} + +/// Rewrite `extern crate foo;` WITHOUT attributes. +pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { + assert!(is_extern_crate(item)); + let new_str = context.snippet(item.span); + Some(if contains_comment(new_str) { + new_str.to_owned() + } else { + let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); + String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) + }) +} + +/// Returns true for `mod foo;`, false for `mod foo { .. }`. +pub fn is_mod_decl(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), + _ => false, + } +} + +pub fn is_use_item(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Use(_) => true, + _ => false, + } +} + +pub fn is_extern_crate(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::ExternCrate(..) => true, + _ => false, + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000000..7ef4931fbe3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,943 @@ +// Copyright 2015-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#![feature(custom_attribute)] +#![feature(decl_macro)] +#![feature(match_default_bindings)] +#![feature(type_ascription)] + +#[macro_use] +extern crate derive_new; +extern crate diff; +#[macro_use] +extern crate log; +extern crate regex; +extern crate rustc_errors as errors; +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; +extern crate syntax; +extern crate term; +extern crate toml; +extern crate unicode_segmentation; + +use std::collections::HashMap; +use std::fmt; +use std::io::{self, stdout, BufRead, Write}; +use std::iter::repeat; +use std::path::PathBuf; +use std::rc::Rc; +use std::time::Duration; + +use errors::{DiagnosticBuilder, Handler}; +use errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::ast; +use syntax::codemap::{CodeMap, FilePathMapping}; +pub use syntax::codemap::FileName; +use syntax::parse::{self, ParseSess}; + +use checkstyle::{output_footer, output_header}; +use comment::{CharClasses, FullCodeCharKind}; +use issues::{BadIssueSeeker, Issue}; +use shape::Indent; +use utils::use_colored_tty; +use visitor::{FmtVisitor, SnippetProvider}; + +pub use config::Config; +pub use config::summary::Summary; + +#[macro_use] +mod utils; + +mod attr; +mod chains; +mod checkstyle; +mod closures; +pub mod codemap; +mod comment; +pub mod config; +mod expr; +pub mod filemap; +mod imports; +mod issues; +mod items; +mod lists; +mod macros; +mod missed_spans; +pub mod modules; +mod patterns; +mod reorder; +mod rewrite; +pub mod rustfmt_diff; +mod shape; +mod spanned; +mod string; +mod types; +mod vertical; +pub mod visitor; + +const STDIN: &str = ""; + +// A map of the files of a crate, with their new content +pub type FileMap = Vec; + +pub type FileRecord = (FileName, String); + +#[derive(Clone, Copy)] +pub enum ErrorKind { + // Line has exceeded character limit (found, maximum) + LineOverflow(usize, usize), + // Line ends in whitespace + TrailingWhitespace, + // TO-DO or FIX-ME item without an issue number + BadIssue(Issue), +} + +impl fmt::Display for ErrorKind { + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + ErrorKind::LineOverflow(found, maximum) => write!( + fmt, + "line exceeded maximum width (maximum: {}, found: {})", + maximum, found + ), + ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), + ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), + } + } +} + +// Formatting errors that are identified *after* rustfmt has run. +pub struct FormattingError { + line: usize, + kind: ErrorKind, + is_comment: bool, + is_string: bool, + line_buffer: String, +} + +impl FormattingError { + fn msg_prefix(&self) -> &str { + match self.kind { + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "error:", + ErrorKind::BadIssue(_) => "WARNING:", + } + } + + fn msg_suffix(&self) -> &str { + if self.is_comment || self.is_string { + "set `error_on_unformatted = false` to suppress \ + the warning against comments or string literals\n" + } else { + "" + } + } + + // (space, target) + pub fn format_len(&self) -> (usize, usize) { + match self.kind { + ErrorKind::LineOverflow(found, max) => (max, found - max), + ErrorKind::TrailingWhitespace => { + let trailing_ws_len = self.line_buffer + .chars() + .rev() + .take_while(|c| c.is_whitespace()) + .count(); + (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) + } + _ => unreachable!(), + } + } +} + +pub struct FormatReport { + // Maps stringified file paths to their associated formatting errors. + file_error_map: HashMap>, +} + +impl FormatReport { + fn new() -> FormatReport { + FormatReport { + file_error_map: HashMap::new(), + } + } + + pub fn warning_count(&self) -> usize { + self.file_error_map + .iter() + .map(|(_, errors)| errors.len()) + .sum() + } + + pub fn has_warnings(&self) -> bool { + self.warning_count() > 0 + } + + pub fn print_warnings_fancy( + &self, + mut t: Box>, + ) -> Result<(), term::Error> { + for (file, errors) in &self.file_error_map { + for error in errors { + let prefix_space_len = error.line.to_string().len(); + let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + + // First line: the overview of error + t.fg(term::color::RED)?; + t.attr(term::Attr::Bold)?; + write!(t, "{} ", error.msg_prefix())?; + t.reset()?; + t.attr(term::Attr::Bold)?; + write!(t, "{}\n", error.kind)?; + + // Second line: file info + write!(t, "{}--> ", &prefix_spaces[1..])?; + t.reset()?; + write!(t, "{}:{}\n", file, error.line)?; + + // Third to fifth lines: show the line which triggered error, if available. + if !error.line_buffer.is_empty() { + let (space_len, target_len) = error.format_len(); + t.attr(term::Attr::Bold)?; + write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; + t.reset()?; + write!(t, "{}\n", error.line_buffer)?; + t.attr(term::Attr::Bold)?; + write!(t, "{}| ", prefix_spaces)?; + t.fg(term::color::RED)?; + write!(t, "{}\n", target_str(space_len, target_len))?; + t.reset()?; + } + + // The last line: show note if available. + let msg_suffix = error.msg_suffix(); + if !msg_suffix.is_empty() { + t.attr(term::Attr::Bold)?; + write!(t, "{}= note: ", prefix_spaces)?; + t.reset()?; + write!(t, "{}\n", error.msg_suffix())?; + } else { + write!(t, "\n")?; + } + t.reset()?; + } + } + + if !self.file_error_map.is_empty() { + t.attr(term::Attr::Bold)?; + write!(t, "warning: ")?; + t.reset()?; + write!( + t, + "rustfmt may have failed to format. See previous {} errors.\n\n", + self.warning_count(), + )?; + } + + Ok(()) + } +} + +fn target_str(space_len: usize, target_len: usize) -> String { + let empty_line: String = repeat(" ").take(space_len).collect(); + let overflowed: String = repeat("^").take(target_len).collect(); + empty_line + &overflowed +} + +impl fmt::Display for FormatReport { + // Prints all the formatting errors. + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + for (file, errors) in &self.file_error_map { + for error in errors { + let prefix_space_len = error.line.to_string().len(); + let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + + let error_line_buffer = if error.line_buffer.is_empty() { + String::from(" ") + } else { + let (space_len, target_len) = error.format_len(); + format!( + "{}|\n{} | {}\n{}| {}", + prefix_spaces, + error.line, + error.line_buffer, + prefix_spaces, + target_str(space_len, target_len) + ) + }; + + let error_info = format!("{} {}", error.msg_prefix(), error.kind); + let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line); + let msg_suffix = error.msg_suffix(); + let note = if msg_suffix.is_empty() { + String::new() + } else { + format!("{}note= ", prefix_spaces) + }; + + write!( + fmt, + "{}\n{}\n{}\n{}{}\n", + error_info, + file_info, + error_line_buffer, + note, + error.msg_suffix() + )?; + } + } + if !self.file_error_map.is_empty() { + write!( + fmt, + "warning: rustfmt may have failed to format. See previous {} errors.\n", + self.warning_count(), + )?; + } + Ok(()) + } +} + +fn should_emit_verbose(path: &FileName, config: &Config, f: F) +where + F: Fn(), +{ + if config.verbose() && path.to_string() != STDIN { + f(); + } +} + +// Formatting which depends on the AST. +fn format_ast( + krate: &ast::Crate, + parse_session: &mut ParseSess, + main_file: &FileName, + config: &Config, + mut after_file: F, +) -> Result<(FileMap, bool), io::Error> +where + F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result, +{ + let mut result = FileMap::new(); + // diff mode: check if any files are differing + let mut has_diff = false; + + // We always skip children for the "Plain" write mode, since there is + // nothing to distinguish the nested module contents. + let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; + for (path, module) in modules::list_files(krate, parse_session.codemap())? { + if skip_children && path != *main_file { + continue; + } + should_emit_verbose(&path, config, || println!("Formatting {}", path)); + let filemap = parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == *main_file { + visitor.skip_empty_lines(filemap.end_pos); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); + } else { + visitor.format_separate_mod(module, &*filemap); + } + } else { + visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); + visitor.format_separate_mod(module, &*filemap); + }; + + debug_assert_eq!( + visitor.line_number, + ::utils::count_newlines(&format!("{}", visitor.buffer)) + ); + + let filename = path.clone(); + has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) { + Ok(result) => result, + Err(e) => { + // Create a new error with path_str to help users see which files failed + let err_msg = format!("{}: {}", path, e); + return Err(io::Error::new(e.kind(), err_msg)); + } + }; + + result.push((filename, visitor.buffer)); + } + + Ok((result, has_diff)) +} + +/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`. +fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { + skipped_range + .iter() + .any(|&(lo, hi)| lo <= line_number && line_number <= hi) +} + +fn should_report_error( + config: &Config, + char_kind: FullCodeCharKind, + is_string: bool, + error_kind: ErrorKind, +) -> bool { + let allow_error_report = if char_kind.is_comment() || is_string { + config.error_on_unformatted() + } else { + true + }; + + match error_kind { + ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, + ErrorKind::TrailingWhitespace => allow_error_report, + _ => true, + } +} + +// Formatting done on a char by char or line by line basis. +// FIXME(#209) warn on bad license +// FIXME(#20) other stuff for parity with make tidy +fn format_lines( + text: &mut String, + name: &FileName, + skipped_range: &[(usize, usize)], + config: &Config, + report: &mut FormatReport, +) { + // Iterate over the chars in the file map. + let mut trims = vec![]; + let mut last_wspace: Option = None; + let mut line_len = 0; + let mut cur_line = 1; + let mut newline_count = 0; + let mut errors = vec![]; + let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); + let mut line_buffer = String::with_capacity(config.max_width() * 2); + let mut is_string = false; // true if the current line contains a string literal. + let mut format_line = config.file_lines().contains_line(name, cur_line); + let allow_issue_seek = !issue_seeker.is_disabled(); + + for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { + if c == '\r' { + continue; + } + + if allow_issue_seek && format_line { + // Add warnings for bad todos/ fixmes + if let Some(issue) = issue_seeker.inspect(c) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::BadIssue(issue), + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); + } + } + + if c == '\n' { + if format_line { + // Check for (and record) trailing whitespace. + if let Some(..) = last_wspace { + if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) { + trims.push((cur_line, kind, line_buffer.clone())); + } + line_len -= 1; + } + + // Check for any line width errors we couldn't correct. + let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); + if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) + && should_report_error(config, kind, is_string, error_kind) + { + errors.push(FormattingError { + line: cur_line, + kind: error_kind, + is_comment: kind.is_comment(), + is_string, + line_buffer: line_buffer.clone(), + }); + } + } + + line_len = 0; + cur_line += 1; + format_line = config.file_lines().contains_line(name, cur_line); + newline_count += 1; + last_wspace = None; + line_buffer.clear(); + is_string = false; + } else { + newline_count = 0; + line_len += if c == '\t' { config.tab_spaces() } else { 1 }; + if c.is_whitespace() { + if last_wspace.is_none() { + last_wspace = Some(b); + } + } else { + last_wspace = None; + } + line_buffer.push(c); + if kind.is_string() { + is_string = true; + } + } + } + + if newline_count > 1 { + debug!("track truncate: {} {}", text.len(), newline_count); + let line = text.len() - newline_count + 1; + text.truncate(line); + } + + for &(l, kind, ref b) in &trims { + if !is_skipped_line(l, skipped_range) { + errors.push(FormattingError { + line: l, + kind: ErrorKind::TrailingWhitespace, + is_comment: kind.is_comment(), + is_string: kind.is_string(), + line_buffer: b.clone(), + }); + } + } + + report.file_error_map.insert(name.clone(), errors); +} + +fn parse_input<'sess>( + input: Input, + parse_session: &'sess ParseSess, + config: &Config, +) -> Result>> { + let result = match input { + Input::File(file) => { + let mut parser = parse::new_parser_from_file(parse_session, &file); + parser.cfg_mods = false; + if config.skip_children() { + parser.recurse_into_file_modules = false; + } + parser.parse_crate_mod() + } + Input::Text(text) => { + let mut parser = parse::new_parser_from_source_str( + parse_session, + FileName::Custom("stdin".to_owned()), + text, + ); + parser.cfg_mods = false; + if config.skip_children() { + parser.recurse_into_file_modules = false; + } + parser.parse_crate_mod() + } + }; + + match result { + Ok(c) => { + if parse_session.span_diagnostic.has_errors() { + // Bail out if the parser recovered from an error. + Err(None) + } else { + Ok(c) + } + } + Err(e) => Err(Some(e)), + } +} + +/// Format the given snippet. The snippet is expected to be *complete* code. +/// When we cannot parse the given snippet, this function returns `None`. +pub fn format_snippet(snippet: &str, config: &Config) -> Option { + let mut out: Vec = Vec::with_capacity(snippet.len() * 2); + let input = Input::Text(snippet.into()); + let mut config = config.clone(); + config.set().write_mode(config::WriteMode::Plain); + config.set().hide_parse_errors(true); + match format_input(input, &config, Some(&mut out)) { + // `format_input()` returns an empty string on parsing error. + Ok(..) if out.is_empty() && !snippet.is_empty() => None, + Ok(..) => String::from_utf8(out).ok(), + Err(..) => None, + } +} + +/// Format the given code block. Mainly targeted for code block in comment. +/// The code block may be incomplete (i.e. parser may be unable to parse it). +/// To avoid panic in parser, we wrap the code block with a dummy function. +/// The returned code block does *not* end with newline. +pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { + // Wrap the given code block with `fn main()` if it does not have one. + let fn_main_prefix = "fn main() {\n"; + let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}"; + let mut result = String::with_capacity(snippet.len()); + let mut is_first = true; + + // Trim "fn main() {" on the first line and "}" on the last line, + // then unindent the whole code block. + let formatted = format_snippet(&snippet, config)?; + // 2 = "}\n" + let block_len = formatted.len().checked_sub(2).unwrap_or(0); + for line in formatted[fn_main_prefix.len()..block_len].lines() { + if !is_first { + result.push('\n'); + } else { + is_first = false; + } + let trimmed_line = if line.len() > config.max_width() { + // If there are lines that are larger than max width, we cannot tell + // whether we have succeeded but have some comments or strings that + // are too long, or we have failed to format code block. We will be + // conservative and just return `None` in this case. + return None; + } else if line.len() > config.tab_spaces() { + // Make sure that the line has leading whitespaces. + let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); + if line.starts_with(indent_str.as_ref()) { + let offset = if config.hard_tabs() { + 1 + } else { + config.tab_spaces() + }; + &line[offset..] + } else { + line + } + } else { + line + }; + result.push_str(trimmed_line); + } + Some(result) +} + +pub fn format_input( + input: Input, + config: &Config, + mut out: Option<&mut T>, +) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { + let mut summary = Summary::default(); + if config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err((e, summary)); + } + } + return Ok((summary, FileMap::new(), FormatReport::new())); + } + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + + let tty_handler = if config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; + let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + + let main_file = match input { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Custom("stdin".to_owned()), + }; + + let krate = match parse_input(input, &parse_session, config) { + Ok(krate) => krate, + Err(diagnostic) => { + if let Some(mut diagnostic) = diagnostic { + diagnostic.emit(); + } + summary.add_parsing_error(); + return Ok((summary, FileMap::new(), FormatReport::new())); + } + }; + + summary.mark_parse_time(); + + if parse_session.span_diagnostic.has_errors() { + summary.add_parsing_error(); + } + + // Suppress error output after parsing. + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + + let mut report = FormatReport::new(); + + let format_result = format_ast( + &krate, + &mut parse_session, + &main_file, + config, + |file_name, file, skipped_range| { + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(file); + + format_lines(file, file_name, skipped_range, config, &mut report); + + if let Some(ref mut out) = out { + return filemap::write_file(file, file_name, out, config); + } + Ok(false) + }, + ); + + summary.mark_format_time(); + + should_emit_verbose(&main_file, config, || { + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } + + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + duration_to_f32(summary.get_parse_time().unwrap()), + duration_to_f32(summary.get_format_time().unwrap()), + ) + }); + + match format_result { + Ok((file_map, has_diff)) => { + if report.has_warnings() { + summary.add_formatting_error(); + } + + if has_diff { + summary.add_diff(); + } + + Ok((summary, file_map, report)) + } + Err(e) => Err((e, summary)), + } +} + +/// A single span of changed lines, with 0 or more removed lines +/// and a vector of 0 or more inserted lines. +#[derive(Debug, PartialEq, Eq)] +pub struct ModifiedChunk { + /// The first to be removed from the original text + pub line_number_orig: u32, + /// The number of lines which have been replaced + pub lines_removed: u32, + /// The new lines + pub lines: Vec, +} + +/// Set of changed sections of a file. +#[derive(Debug, PartialEq, Eq)] +pub struct ModifiedLines { + /// The set of changed chunks. + pub chunks: Vec, +} + +/// The successful result of formatting via `get_modified_lines()`. +pub struct ModifiedLinesResult { + /// The high level summary details + pub summary: Summary, + /// The result Filemap + pub filemap: FileMap, + /// Map of formatting errors + pub report: FormatReport, + /// The sets of updated lines. + pub modified_lines: ModifiedLines, +} + +/// Format a file and return a `ModifiedLines` data structure describing +/// the changed ranges of lines. +pub fn get_modified_lines( + input: Input, + config: &Config, +) -> Result { + let mut data = Vec::new(); + + let mut config = config.clone(); + config.set().write_mode(config::WriteMode::Modified); + let (summary, filemap, formatreport) = format_input(input, &config, Some(&mut data))?; + + let mut lines = data.lines(); + let mut chunks = Vec::new(); + while let Some(Ok(header)) = lines.next() { + // Parse the header line + let values: Vec<_> = header + .split(' ') + .map(|s| s.parse::().unwrap()) + .collect(); + assert_eq!(values.len(), 3); + let line_number_orig = values[0]; + let lines_removed = values[1]; + let num_added = values[2]; + let mut added_lines = Vec::new(); + for _ in 0..num_added { + added_lines.push(lines.next().unwrap().unwrap()); + } + chunks.push(ModifiedChunk { + line_number_orig, + lines_removed, + lines: added_lines, + }); + } + Ok(ModifiedLinesResult { + summary: summary, + filemap: filemap, + report: formatreport, + modified_lines: ModifiedLines { chunks }, + }) +} + +#[derive(Debug)] +pub enum Input { + File(PathBuf), + Text(String), +} + +pub fn run(input: Input, config: &Config) -> Summary { + let out = &mut stdout(); + output_header(out, config.write_mode()).ok(); + match format_input(input, config, Some(out)) { + Ok((summary, _, report)) => { + output_footer(out, config.write_mode()).ok(); + + if report.has_warnings() { + match term::stderr() { + Some(ref t) + if use_colored_tty(config.color()) && t.supports_color() + && t.supports_attr(term::Attr::Bold) => + { + match report.print_warnings_fancy(term::stderr().unwrap()) { + Ok(..) => (), + Err(..) => panic!("Unable to write to stderr: {}", report), + } + } + _ => msg!("{}", report), + } + } + + summary + } + Err((msg, mut summary)) => { + msg!("Error writing files: {}", msg); + summary.add_operational_error(); + summary + } + } +} + +#[cfg(test)] +mod test { + use super::{format_code_block, format_snippet, Config}; + + #[test] + fn test_no_panic_on_format_snippet_and_format_code_block() { + // `format_snippet()` and `format_code_block()` should not panic + // even when we cannot parse the given snippet. + let snippet = "let"; + assert!(format_snippet(snippet, &Config::default()).is_none()); + assert!(format_code_block(snippet, &Config::default()).is_none()); + } + + fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool + where + F: Fn(&str, &Config) -> Option, + { + let output = formatter(input, &Config::default()); + output.is_some() && output.unwrap() == expected + } + + #[test] + fn test_format_snippet() { + let snippet = "fn main() { println!(\"hello, world\"); }"; + let expected = "fn main() {\n \ + println!(\"hello, world\");\n\ + }\n"; + assert!(test_format_inner(format_snippet, snippet, expected)); + } + + #[test] + fn test_format_code_block_fail() { + #[rustfmt_skip] + let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);"; + assert!(format_code_block(code_block, &Config::default()).is_none()); + } + + #[test] + fn test_format_code_block() { + // simple code block + let code_block = "let x=3;"; + let expected = "let x = 3;"; + assert!(test_format_inner(format_code_block, code_block, expected)); + + // more complex code block, taken from chains.rs. + let code_block = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +context.config.indent_style() == IndentStyle::Visual || is_small_parent, +) +} else if is_block_expr(context, &parent, &parent_rewrite) { +match context.config.indent_style() { +// Try to put the first child on the same line with parent's last line +IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), +// The parent is a block, so align the rest of the chain with the closing +// brace. +IndentStyle::Visual => (parent_shape, false), +} +} else { +( +chain_indent(context, shape.add_offset(parent_rewrite.len())), +false, +) +}; +"; + let expected = +"let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + context.config.indent_style() == IndentStyle::Visual || is_small_parent, + ) +} else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + // Try to put the first child on the same line with parent's last line + IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + // The parent is a block, so align the rest of the chain with the closing + // brace. + IndentStyle::Visual => (parent_shape, false), + } +} else { + ( + chain_indent(context, shape.add_offset(parent_rewrite.len())), + false, + ) +};"; + assert!(test_format_inner(format_code_block, code_block, expected)); + } +} diff --git a/src/lists.rs b/src/lists.rs new file mode 100644 index 00000000000..49797a785bb --- /dev/null +++ b/src/lists.rs @@ -0,0 +1,771 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Format list-like expressions and items. + +use std::cmp; +use std::iter::Peekable; + +use config::lists::*; +use syntax::codemap::BytePos; + +use comment::{find_comment_end, rewrite_comment, FindUncommented}; +use config::{Config, IndentStyle}; +use rewrite::RewriteContext; +use shape::{Indent, Shape}; +use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; +use visitor::SnippetProvider; + +pub struct ListFormatting<'a> { + pub tactic: DefinitiveListTactic, + pub separator: &'a str, + pub trailing_separator: SeparatorTactic, + pub separator_place: SeparatorPlace, + pub shape: Shape, + // Non-expressions, e.g. items, will have a new line at the end of the list. + // Important for comment styles. + pub ends_with_newline: bool, + // Remove newlines between list elements for expressions. + pub preserve_newline: bool, + pub config: &'a Config, +} + +impl<'a> ListFormatting<'a> { + pub fn needs_trailing_separator(&self) -> bool { + match self.trailing_separator { + // We always put separator in front. + SeparatorTactic::Always => true, + SeparatorTactic::Vertical => self.tactic == DefinitiveListTactic::Vertical, + SeparatorTactic::Never => { + self.tactic == DefinitiveListTactic::Vertical && self.separator_place.is_front() + } + } + } +} + +impl AsRef for ListItem { + fn as_ref(&self) -> &ListItem { + self + } +} + +#[derive(PartialEq, Eq)] +pub enum ListItemCommentStyle { + // Try to keep the comment on the same line with the item. + SameLine, + // Put the comment on the previous or the next line of the item. + DifferentLine, + // No comment available. + None, +} + +pub struct ListItem { + // None for comments mean that they are not present. + pub pre_comment: Option, + pub pre_comment_style: ListItemCommentStyle, + // Item should include attributes and doc comments. None indicates a failed + // rewrite. + pub item: Option, + pub post_comment: Option, + // Whether there is extra whitespace before this item. + pub new_lines: bool, +} + +impl ListItem { + pub fn inner_as_ref(&self) -> &str { + self.item.as_ref().map_or("", |s| s) + } + + pub fn is_different_group(&self) -> bool { + self.inner_as_ref().contains('\n') || self.pre_comment.is_some() + || self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + } + + pub fn is_multiline(&self) -> bool { + self.inner_as_ref().contains('\n') + || self.pre_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + || self.post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) + } + + pub fn has_comment(&self) -> bool { + self.pre_comment + .as_ref() + .map_or(false, |comment| comment.trim_left().starts_with("//")) + || self.post_comment + .as_ref() + .map_or(false, |comment| comment.trim_left().starts_with("//")) + } + + pub fn from_str>(s: S) -> ListItem { + ListItem { + pre_comment: None, + pre_comment_style: ListItemCommentStyle::None, + item: Some(s.into()), + post_comment: None, + new_lines: false, + } + } +} + +/// The type of separator for lists. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum Separator { + Comma, + VerticalBar, +} + +impl Separator { + pub fn len(&self) -> usize { + match *self { + // 2 = `, ` + Separator::Comma => 2, + // 3 = ` | ` + Separator::VerticalBar => 3, + } + } +} + +pub fn definitive_tactic( + items: I, + tactic: ListTactic, + sep: Separator, + width: usize, +) -> DefinitiveListTactic +where + I: IntoIterator + Clone, + T: AsRef, +{ + let pre_line_comments = items + .clone() + .into_iter() + .any(|item| item.as_ref().has_comment()); + + let limit = match tactic { + _ if pre_line_comments => return DefinitiveListTactic::Vertical, + ListTactic::Mixed => return DefinitiveListTactic::Mixed, + ListTactic::Horizontal => return DefinitiveListTactic::Horizontal, + ListTactic::Vertical => return DefinitiveListTactic::Vertical, + ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit), + ListTactic::HorizontalVertical => width, + }; + + let (sep_count, total_width) = calculate_width(items.clone()); + let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); + let real_total = total_width + total_sep_len; + + if real_total <= limit && !pre_line_comments + && !items.into_iter().any(|item| item.as_ref().is_multiline()) + { + DefinitiveListTactic::Horizontal + } else { + DefinitiveListTactic::Vertical + } +} + +// Format a list of commented items into a string. +// TODO: add unit tests +pub fn write_list(items: I, formatting: &ListFormatting) -> Option +where + I: IntoIterator + Clone, + T: AsRef, +{ + let tactic = formatting.tactic; + let sep_len = formatting.separator.len(); + + // Now that we know how we will layout, we can decide for sure if there + // will be a trailing separator. + let mut trailing_separator = formatting.needs_trailing_separator(); + let mut result = String::with_capacity(128); + let cloned_items = items.clone(); + let mut iter = items.into_iter().enumerate().peekable(); + let mut item_max_width: Option = None; + let sep_place = + SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); + + let mut line_len = 0; + let indent_str = &formatting.shape.indent.to_string(formatting.config); + while let Some((i, item)) = iter.next() { + let item = item.as_ref(); + let inner_item = item.item.as_ref()?; + let first = i == 0; + let last = iter.peek().is_none(); + let mut separate = match sep_place { + SeparatorPlace::Front => !first, + SeparatorPlace::Back => !last || trailing_separator, + }; + let item_sep_len = if separate { sep_len } else { 0 }; + + // Item string may be multi-line. Its length (used for block comment alignment) + // should be only the length of the last line. + let item_last_line = if item.is_multiline() { + inner_item.lines().last().unwrap_or("") + } else { + inner_item.as_ref() + }; + let mut item_last_line_width = item_last_line.len() + item_sep_len; + if item_last_line.starts_with(&**indent_str) { + item_last_line_width -= indent_str.len(); + } + + match tactic { + DefinitiveListTactic::Horizontal if !first => { + result.push(' '); + } + DefinitiveListTactic::SpecialMacro(num_args_before) => { + if i == 0 { + // Nothing + } else if i < num_args_before { + result.push(' '); + } else if i <= num_args_before + 1 { + result.push('\n'); + result.push_str(indent_str); + } else { + result.push(' '); + } + } + DefinitiveListTactic::Vertical if !first => { + result.push('\n'); + result.push_str(indent_str); + } + DefinitiveListTactic::Mixed => { + let total_width = total_item_width(item) + item_sep_len; + + // 1 is space between separator and item. + if line_len > 0 && line_len + 1 + total_width > formatting.shape.width { + result.push('\n'); + result.push_str(indent_str); + line_len = 0; + if formatting.ends_with_newline { + if last { + separate = true; + } else { + trailing_separator = true; + } + } + } + + if line_len > 0 { + result.push(' '); + line_len += 1; + } + + line_len += total_width; + } + _ => {} + } + + // Pre-comments + if let Some(ref comment) = item.pre_comment { + // Block style in non-vertical mode. + let block_mode = tactic != DefinitiveListTactic::Vertical; + // Width restriction is only relevant in vertical mode. + let comment = + rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; + result.push_str(&comment); + + if tactic == DefinitiveListTactic::Vertical { + // We cannot keep pre-comments on the same line if the comment if normalized. + let keep_comment = if formatting.config.normalize_comments() + || item.pre_comment_style == ListItemCommentStyle::DifferentLine + { + false + } else { + // We will try to keep the comment on the same line with the item here. + // 1 = ` ` + let total_width = total_item_width(item) + item_sep_len + 1; + total_width <= formatting.shape.width + }; + if keep_comment { + result.push(' '); + } else { + result.push('\n'); + result.push_str(indent_str); + } + } else { + result.push(' '); + } + item_max_width = None; + } + + if separate && sep_place.is_front() && !first { + result.push_str(formatting.separator.trim()); + result.push(' '); + } + result.push_str(&inner_item[..]); + + // Post-comments + if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { + let comment = item.post_comment.as_ref().unwrap(); + let formatted_comment = rewrite_comment( + comment, + true, + Shape::legacy(formatting.shape.width, Indent::empty()), + formatting.config, + )?; + + result.push(' '); + result.push_str(&formatted_comment); + } + + if separate && sep_place.is_back() { + result.push_str(formatting.separator); + } + + if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { + let comment = item.post_comment.as_ref().unwrap(); + let overhead = last_line_width(&result) + first_line_width(comment.trim()); + + let rewrite_post_comment = |item_max_width: &mut Option| { + if item_max_width.is_none() && !last && !inner_item.contains('\n') { + *item_max_width = Some(max_width_of_item_with_post_comment( + &cloned_items, + i, + overhead, + formatting.config.max_width(), + )); + } + let overhead = if starts_with_newline(comment) { + 0 + } else if let Some(max_width) = *item_max_width { + max_width + 2 + } else { + // 1 = space between item and comment. + item_last_line_width + 1 + }; + let width = formatting.shape.width.checked_sub(overhead).unwrap_or(1); + let offset = formatting.shape.indent + overhead; + let comment_shape = Shape::legacy(width, offset); + + // Use block-style only for the last item or multiline comments. + let block_style = !formatting.ends_with_newline && last + || comment.trim().contains('\n') + || comment.trim().len() > width; + + rewrite_comment( + comment.trim_left(), + block_style, + comment_shape, + formatting.config, + ) + }; + + let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; + + if !starts_with_newline(comment) { + let mut comment_alignment = + post_comment_alignment(item_max_width, inner_item.len()); + if first_line_width(&formatted_comment) + last_line_width(&result) + + comment_alignment + 1 > formatting.config.max_width() + { + item_max_width = None; + formatted_comment = rewrite_post_comment(&mut item_max_width)?; + comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); + } + for _ in 0..(comment_alignment + 1) { + result.push(' '); + } + // An additional space for the missing trailing separator. + if last && item_max_width.is_some() && !separate && !formatting.separator.is_empty() + { + result.push(' '); + } + } else { + result.push('\n'); + result.push_str(indent_str); + } + if formatted_comment.contains('\n') { + item_max_width = None; + } + result.push_str(&formatted_comment); + } else { + item_max_width = None; + } + + if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical + && item.new_lines + { + item_max_width = None; + result.push('\n'); + } + } + + Some(result) +} + +fn max_width_of_item_with_post_comment( + items: &I, + i: usize, + overhead: usize, + max_budget: usize, +) -> usize +where + I: IntoIterator + Clone, + T: AsRef, +{ + let mut max_width = 0; + let mut first = true; + for item in items.clone().into_iter().skip(i) { + let item = item.as_ref(); + let inner_item_width = item.inner_as_ref().len(); + if !first + && (item.is_different_group() || !item.post_comment.is_some() + || inner_item_width + overhead > max_budget) + { + return max_width; + } + if max_width < inner_item_width { + max_width = inner_item_width; + } + if item.new_lines { + return max_width; + } + first = false; + } + max_width +} + +fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { + item_max_width + .and_then(|max_line_width| max_line_width.checked_sub(inner_item_len)) + .unwrap_or(0) +} + +pub struct ListItems<'a, I, F1, F2, F3> +where + I: Iterator, +{ + snippet_provider: &'a SnippetProvider<'a>, + inner: Peekable, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos, + terminator: &'a str, + separator: &'a str, + leave_last: bool, +} + +impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, +{ + type Item = ListItem; + + fn next(&mut self) -> Option { + let white_space: &[_] = &[' ', '\t']; + + self.inner.next().map(|item| { + let mut new_lines = false; + // Pre-comment + let pre_snippet = self.snippet_provider + .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) + .unwrap(); + let trimmed_pre_snippet = pre_snippet.trim(); + let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); + let has_block_comment = trimmed_pre_snippet.starts_with("/*"); + let (pre_comment, pre_comment_style) = if has_single_line_comment { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else if has_block_comment { + let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); + if pre_snippet + .chars() + .rev() + .take(comment_end + 1) + .any(|c| c == '\n') + { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::SameLine, + ) + } + } else { + (None, ListItemCommentStyle::None) + }; + + // Post-comment + let next_start = match self.inner.peek() { + Some(next_item) => (self.get_lo)(next_item), + None => self.next_span_start, + }; + let post_snippet = self.snippet_provider + .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) + .unwrap(); + + let comment_end = match self.inner.peek() { + Some(..) => { + let mut block_open_index = post_snippet.find("/*"); + // check if it really is a block comment (and not `//*` or a nested comment) + if let Some(i) = block_open_index { + match post_snippet.find('/') { + Some(j) if j < i => block_open_index = None, + _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, + _ => (), + } + } + let newline_index = post_snippet.find('\n'); + if let Some(separator_index) = post_snippet.find_uncommented(self.separator) { + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => separator_index + 1, + // Block-style post-comment before the separator. + (Some(i), None) => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Potential *single* line comment. + (_, Some(j)) if j > separator_index => j + 1, + _ => post_snippet.len(), + } + } else if let Some(newline_index) = newline_index { + // Match arms may not have trailing comma. In any case, for match arms, + // we will assume that the post comment belongs to the next arm if they + // do not end with trailing comma. + newline_index + 1 + } else { + 0 + } + } + None => post_snippet + .find_uncommented(self.terminator) + .unwrap_or_else(|| post_snippet.len()), + }; + + if !post_snippet.is_empty() && comment_end > 0 { + // Account for extra whitespace between items. This is fiddly + // because of the way we divide pre- and post- comments. + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end - 1..]; + let first_newline = test_snippet + .find('\n') + .unwrap_or_else(|| test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet + .find(|c: char| !c.is_whitespace()) + .unwrap_or_else(|| test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + if count_newlines(test_snippet) > 1 { + // There were multiple line breaks which got trimmed to nothing. + new_lines = true; + } + } + + // Cleanup post-comment: strip separators and whitespace. + self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); + let post_snippet = post_snippet[..comment_end].trim(); + + let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.ends_with(',') { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; + + let post_comment = if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + }; + + ListItem { + pre_comment, + pre_comment_style, + item: if self.inner.peek().is_none() && self.leave_last { + None + } else { + (self.get_item_string)(&item) + }, + post_comment, + new_lines, + } + }) + } +} + +#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] +// Creates an iterator over a list's items with associated comments. +pub fn itemize_list<'a, T, I, F1, F2, F3>( + snippet_provider: &'a SnippetProvider, + inner: I, + terminator: &'a str, + separator: &'a str, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + prev_span_end: BytePos, + next_span_start: BytePos, + leave_last: bool, +) -> ListItems<'a, I, F1, F2, F3> +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, +{ + ListItems { + snippet_provider, + inner: inner.peekable(), + get_lo, + get_hi, + get_item_string, + prev_span_end, + next_span_start, + terminator, + separator, + leave_last, + } +} + +/// Returns the count and total width of the list items. +fn calculate_width(items: I) -> (usize, usize) +where + I: IntoIterator, + T: AsRef, +{ + items + .into_iter() + .map(|item| total_item_width(item.as_ref())) + .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) +} + +pub fn total_item_width(item: &ListItem) -> usize { + comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + + item.item.as_ref().map_or(0, |str| str.len()) +} + +fn comment_len(comment: Option<&str>) -> usize { + match comment { + Some(s) => { + let text_len = s.trim().len(); + if text_len > 0 { + // We'll put " /*" before and " */" after inline comments. + text_len + 6 + } else { + text_len + } + } + None => 0, + } +} + +// Compute horizontal and vertical shapes for a struct-lit-like thing. +pub fn struct_lit_shape( + shape: Shape, + context: &RewriteContext, + prefix_width: usize, + suffix_width: usize, +) -> Option<(Option, Shape)> { + let v_shape = match context.config.indent_style() { + IndentStyle::Visual => shape + .visual_indent(0) + .shrink_left(prefix_width)? + .sub_width(suffix_width)?, + IndentStyle::Block => { + let shape = shape.block_indent(context.config.tab_spaces()); + Shape { + width: context.budget(shape.indent.width()), + ..shape + } + } + }; + let shape_width = shape.width.checked_sub(prefix_width + suffix_width); + if let Some(w) = shape_width { + let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); + Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) + } else { + Some((None, v_shape)) + } +} + +// Compute the tactic for the internals of a struct-lit-like thing. +pub fn struct_lit_tactic( + h_shape: Option, + context: &RewriteContext, + items: &[ListItem], +) -> DefinitiveListTactic { + if let Some(h_shape) = h_shape { + let prelim_tactic = match (context.config.indent_style(), items.len()) { + (IndentStyle::Visual, 1) => ListTactic::HorizontalVertical, + _ if context.config.struct_lit_single_line() => ListTactic::HorizontalVertical, + _ => ListTactic::Vertical, + }; + definitive_tactic(items, prelim_tactic, Separator::Comma, h_shape.width) + } else { + DefinitiveListTactic::Vertical + } +} + +// Given a tactic and possible shapes for horizontal and vertical layout, +// come up with the actual shape to use. +pub fn shape_for_tactic( + tactic: DefinitiveListTactic, + h_shape: Option, + v_shape: Shape, +) -> Shape { + match tactic { + DefinitiveListTactic::Horizontal => h_shape.unwrap(), + _ => v_shape, + } +} + +// Create a ListFormatting object for formatting the internals of a +// struct-lit-like thing, that is a series of fields. +pub fn struct_lit_formatting<'a>( + shape: Shape, + tactic: DefinitiveListTactic, + context: &'a RewriteContext, + force_no_trailing_comma: bool, +) -> ListFormatting<'a> { + let ends_with_newline = context.config.indent_style() != IndentStyle::Visual + && tactic == DefinitiveListTactic::Vertical; + ListFormatting { + tactic, + separator: ",", + trailing_separator: if force_no_trailing_comma { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline, + preserve_newline: true, + config: context.config, + } +} diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 00000000000..e7238a314fc --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,979 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format list-like macro invocations. These are invocations whose token trees +// can be interpreted as expressions and separated by commas. +// Note that these token trees do not actually have to be interpreted as +// expressions by the compiler. An example of an invocation we would reformat is +// foo!( x, y, z ). The token x may represent an identifier in the code, but we +// interpreted as an expression. +// Macro uses which are not-list like, such as bar!(key => val), will not be +// reformatted. +// List-like invocations with parentheses will be formatted as function calls, +// and those with brackets will be formatted as array literals. + +use std::collections::HashMap; + +use config::lists::*; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; +use syntax::parse::new_parser_from_tts; +use syntax::parse::parser::Parser; +use syntax::parse::token::{BinOpToken, DelimToken, Token}; +use syntax::print::pprust; +use syntax::symbol; +use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; +use syntax::util::ThinVec; + +use codemap::SpanUtils; +use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; +use expr::{rewrite_array, rewrite_call_inner}; +use lists::{itemize_list, write_list, ListFormatting}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use utils::{format_visibility, mk_sp, wrap_str}; + +const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; + +// FIXME: use the enum from libsyntax? +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum MacroStyle { + Parens, + Brackets, + Braces, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum MacroPosition { + Item, + Statement, + Expression, + Pat, +} + +impl MacroStyle { + fn opener(&self) -> &'static str { + match *self { + MacroStyle::Parens => "(", + MacroStyle::Brackets => "[", + MacroStyle::Braces => "{", + } + } +} + +#[derive(Debug)] +pub enum MacroArg { + Expr(ast::Expr), + Ty(ast::Ty), + Pat(ast::Pat), +} + +impl Rewrite for MacroArg { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + MacroArg::Expr(ref expr) => expr.rewrite(context, shape), + MacroArg::Ty(ref ty) => ty.rewrite(context, shape), + MacroArg::Pat(ref pat) => pat.rewrite(context, shape), + } + } +} + +fn parse_macro_arg(parser: &mut Parser) -> Option { + macro_rules! parse_macro_arg { + ($macro_arg: ident, $parser: ident) => { + let mut cloned_parser = (*parser).clone(); + match cloned_parser.$parser() { + Ok(x) => { + if parser.sess.span_diagnostic.has_errors() { + parser.sess.span_diagnostic.reset_err_count(); + } else { + // Parsing succeeded. + *parser = cloned_parser; + return Some(MacroArg::$macro_arg((*x).clone())); + } + } + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + } + } + }; + } + + parse_macro_arg!(Expr, parse_expr); + parse_macro_arg!(Ty, parse_ty); + parse_macro_arg!(Pat, parse_pat); + + None +} + +/// Rewrite macro name without using pretty-printer if possible. +fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> String { + let name = if path.segments.len() == 1 { + // Avoid using pretty-printer in the common case. + format!("{}!", path.segments[0].identifier) + } else { + format!("{}!", path) + }; + match extra_ident { + Some(ident) if ident != symbol::keywords::Invalid.ident() => format!("{} {}", name, ident), + _ => name, + } +} + +pub fn rewrite_macro( + mac: &ast::Mac, + extra_ident: Option, + context: &RewriteContext, + shape: Shape, + position: MacroPosition, +) -> Option { + let context = &mut context.clone(); + context.inside_macro = true; + if context.config.use_try_shorthand() { + if let Some(expr) = convert_try_mac(mac, context) { + context.inside_macro = false; + return expr.rewrite(context, shape); + } + } + + let original_style = macro_style(mac, context); + + let macro_name = rewrite_macro_name(&mac.node.path, extra_ident); + + let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + MacroStyle::Brackets + } else { + original_style + }; + + let ts: TokenStream = mac.node.stream(); + let has_comment = contains_comment(context.snippet(mac.span)); + if ts.is_empty() && !has_comment { + return match style { + MacroStyle::Parens if position == MacroPosition::Item => { + Some(format!("{}();", macro_name)) + } + MacroStyle::Parens => Some(format!("{}()", macro_name)), + MacroStyle::Brackets => Some(format!("{}[]", macro_name)), + MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), + }; + } + // Format well-known macros which cannot be parsed as a valid AST. + // TODO: Maybe add more macros? + if macro_name == "lazy_static!" && !has_comment { + if let success @ Some(..) = format_lazy_static(context, shape, &ts) { + return success; + } + } + + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut arg_vec = Vec::new(); + let mut vec_with_semi = false; + let mut trailing_comma = false; + + if MacroStyle::Braces != style { + loop { + match parse_macro_arg(&mut parser) { + Some(arg) => arg_vec.push(arg), + None => return Some(context.snippet(mac.span).to_owned()), + } + + match parser.token { + Token::Eof => break, + Token::Comma => (), + Token::Semi => { + // Try to parse `vec![expr; expr]` + if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + parser.bump(); + if parser.token != Token::Eof { + match parse_macro_arg(&mut parser) { + Some(arg) => { + arg_vec.push(arg); + parser.bump(); + if parser.token == Token::Eof && arg_vec.len() == 2 { + vec_with_semi = true; + break; + } + } + None => return Some(context.snippet(mac.span).to_owned()), + } + } + } + return Some(context.snippet(mac.span).to_owned()); + } + _ => return Some(context.snippet(mac.span).to_owned()), + } + + parser.bump(); + + if parser.token == Token::Eof { + trailing_comma = true; + break; + } + } + } + + match style { + MacroStyle::Parens => { + // Format macro invocation as function call, forcing no trailing + // comma because not all macros support them. + rewrite_call_inner( + context, + ¯o_name, + &arg_vec.iter().map(|e| &*e).collect::>()[..], + mac.span, + shape, + context.config.width_heuristics().fn_call_width, + trailing_comma, + ).map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) + } + MacroStyle::Brackets => { + let mac_shape = shape.offset_left(macro_name.len())?; + // Handle special case: `vec![expr; expr]` + if vec_with_semi { + let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { + ("[ ", " ]") + } else { + ("[", "]") + }; + // 6 = `vec!` + `; ` + let total_overhead = lbr.len() + rbr.len() + 6; + let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); + let lhs = arg_vec[0].rewrite(context, nested_shape)?; + let rhs = arg_vec[1].rewrite(context, nested_shape)?; + if !lhs.contains('\n') && !rhs.contains('\n') + && lhs.len() + rhs.len() + total_overhead <= shape.width + { + Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) + } else { + Some(format!( + "{}{}{}{};{}{}{}{}", + macro_name, + lbr, + nested_shape.indent.to_string_with_newline(context.config), + lhs, + nested_shape.indent.to_string_with_newline(context.config), + rhs, + shape.indent.to_string_with_newline(context.config), + rbr + )) + } + } else { + // If we are rewriting `vec!` macro or other special macros, + // then we can rewrite this as an usual array literal. + // Otherwise, we must preserve the original existence of trailing comma. + if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { + context.inside_macro = false; + trailing_comma = false; + } + // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. + let sp = mk_sp( + context + .snippet_provider + .span_after(mac.span, original_style.opener()), + mac.span.hi() - BytePos(1), + ); + let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; + let rewrite = rewrite_array(arg_vec, sp, context, mac_shape, trailing_comma)?; + let comma = match position { + MacroPosition::Item => ";", + _ => "", + }; + + Some(format!("{}{}{}", macro_name, rewrite, comma)) + } + } + MacroStyle::Braces => { + // Skip macro invocations with braces, for now. + indent_macro_snippet(context, context.snippet(mac.span), shape.indent) + } + } +} + +pub fn rewrite_macro_def( + context: &RewriteContext, + shape: Shape, + indent: Indent, + def: &ast::MacroDef, + ident: ast::Ident, + vis: &ast::Visibility, + span: Span, +) -> Option { + let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); + if snippet.as_ref().map_or(true, |s| s.ends_with(';')) { + return snippet; + } + + let mut parser = MacroParser::new(def.stream().into_trees()); + let parsed_def = match parser.parse() { + Some(def) => def, + None => return snippet, + }; + + let mut result = if def.legacy { + String::from("macro_rules!") + } else { + format!("{}macro", format_visibility(vis)) + }; + + result += " "; + result += &ident.name.as_str(); + + let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; + + let arm_shape = if multi_branch_style { + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + } else { + shape + }; + + let branch_items = itemize_list( + context.snippet_provider, + parsed_def.branches.iter(), + "}", + ";", + |branch| branch.span.lo(), + |branch| branch.span.hi(), + |branch| branch.rewrite(context, arm_shape, multi_branch_style), + context.snippet_provider.span_after(span, "{"), + span.hi(), + false, + ).collect::>(); + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: if def.legacy { ";" } else { "" }, + trailing_separator: SeparatorTactic::Always, + separator_place: SeparatorPlace::Back, + shape: arm_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + + if multi_branch_style { + result += " {"; + result += &arm_shape.indent.to_string_with_newline(context.config); + } + + result += write_list(&branch_items, &fmt)?.as_str(); + + if multi_branch_style { + result += &indent.to_string_with_newline(context.config); + result += "}"; + } + + Some(result) +} + +// Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we +// aren't causing problems. +// This should also work for escaped `$` variables, where we leave earlier `$`s. +fn replace_names(input: &str) -> Option<(String, HashMap)> { + // Each substitution will require five or six extra bytes. + let mut result = String::with_capacity(input.len() + 64); + let mut substs = HashMap::new(); + let mut dollar_count = 0; + let mut cur_name = String::new(); + + for c in input.chars() { + if c == '$' { + dollar_count += 1; + } else if dollar_count == 0 { + result.push(c); + } else if !c.is_alphanumeric() && !cur_name.is_empty() { + // Terminates a name following one or more dollars. + let mut new_name = String::new(); + let mut old_name = String::new(); + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&cur_name); + old_name.push_str(&cur_name); + + result.push_str(&new_name); + substs.insert(old_name, new_name); + + result.push(c); + + dollar_count = 0; + cur_name = String::new(); + } else if c == '(' && cur_name.is_empty() { + // FIXME: Support macro def with repeat. + return None; + } else if c.is_alphanumeric() { + cur_name.push(c); + } + } + + // FIXME: duplicate code + if !cur_name.is_empty() { + let mut new_name = String::new(); + let mut old_name = String::new(); + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&cur_name); + old_name.push_str(&cur_name); + + result.push_str(&new_name); + substs.insert(old_name, new_name); + } + + debug!("replace_names `{}` {:?}", result, substs); + + Some((result, substs)) +} + +// This is a bit sketchy. The token rules probably need tweaking, but it works +// for some common cases. I hope the basic logic is sufficient. Note that the +// meaning of some tokens is a bit different here from usual Rust, e.g., `*` +// and `(`/`)` have special meaning. +// +// We always try and format on one line. +// FIXME: Use multi-line when every thing does not fit on one line. +fn format_macro_args(toks: ThinTokenStream, shape: Shape) -> Option { + let mut result = String::with_capacity(128); + let mut insert_space = SpaceState::Never; + + for tok in (toks.into(): TokenStream).trees() { + match tok { + TokenTree::Token(_, t) => { + if !result.is_empty() && force_space_before(&t) { + insert_space = SpaceState::Always; + } + if force_no_space_before(&t) { + insert_space = SpaceState::Never; + } + match (insert_space, ident_like(&t)) { + (SpaceState::Always, _) + | (SpaceState::Punctuation, false) + | (SpaceState::Ident, true) => { + result.push(' '); + } + _ => {} + } + result.push_str(&pprust::token_to_string(&t)); + insert_space = next_space(&t); + } + TokenTree::Delimited(_, d) => { + if let SpaceState::Always = insert_space { + result.push(' '); + } + let formatted = format_macro_args(d.tts, shape)?; + match d.delim { + DelimToken::Paren => { + result.push_str(&format!("({})", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::Bracket => { + result.push_str(&format!("[{}]", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::Brace => { + result.push_str(&format!(" {{ {} }}", formatted)); + insert_space = SpaceState::Always; + } + DelimToken::NoDelim => { + result.push_str(&format!("{}", formatted)); + insert_space = SpaceState::Always; + } + } + } + } + } + + if result.len() <= shape.width { + Some(result) + } else { + None + } +} + +// We should insert a space if the next token is a: +#[derive(Copy, Clone)] +enum SpaceState { + Never, + Punctuation, + Ident, // Or ident/literal-like thing. + Always, +} + +fn force_space_before(tok: &Token) -> bool { + match *tok { + Token::Eq + | Token::Lt + | Token::Le + | Token::EqEq + | Token::Ne + | Token::Ge + | Token::Gt + | Token::AndAnd + | Token::OrOr + | Token::Not + | Token::Tilde + | Token::BinOpEq(_) + | Token::At + | Token::RArrow + | Token::LArrow + | Token::FatArrow + | Token::Pound + | Token::Dollar => true, + Token::BinOp(bot) => bot != BinOpToken::Star, + _ => false, + } +} + +fn force_no_space_before(tok: &Token) -> bool { + match *tok { + Token::Semi | Token::Comma | Token::Dot => true, + Token::BinOp(bot) => bot == BinOpToken::Star, + _ => false, + } +} +fn ident_like(tok: &Token) -> bool { + match *tok { + Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, + _ => false, + } +} + +fn next_space(tok: &Token) -> SpaceState { + match *tok { + Token::Not + | Token::Tilde + | Token::At + | Token::Comma + | Token::Dot + | Token::DotDot + | Token::DotDotDot + | Token::DotDotEq + | Token::DotEq + | Token::Question + | Token::Underscore + | Token::BinOp(_) => SpaceState::Punctuation, + + Token::ModSep + | Token::Pound + | Token::Dollar + | Token::OpenDelim(_) + | Token::CloseDelim(_) + | Token::Whitespace => SpaceState::Never, + + Token::Literal(..) | Token::Ident(_) | Token::Lifetime(_) => SpaceState::Ident, + + _ => SpaceState::Always, + } +} + +/// Tries to convert a macro use into a short hand try expression. Returns None +/// when the macro is not an instance of try! (or parsing the inner expression +/// failed). +pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { + if &format!("{}", mac.node.path)[..] == "try" { + let ts: TokenStream = mac.node.tts.clone().into(); + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + + Some(ast::Expr { + id: ast::NodeId::new(0), // dummy value + node: ast::ExprKind::Try(parser.parse_expr().ok()?), + span: mac.span, // incorrect span, but shouldn't matter too much + attrs: ThinVec::new(), + }) + } else { + None + } +} + +fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { + let snippet = context.snippet(mac.span); + let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); + let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); + let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); + + if paren_pos < bracket_pos && paren_pos < brace_pos { + MacroStyle::Parens + } else if bracket_pos < brace_pos { + MacroStyle::Brackets + } else { + MacroStyle::Braces + } +} + +/// Indent each line according to the specified `indent`. +/// e.g. +/// ```rust +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +/// ), +/// } +/// ``` +/// will become +/// ```rust +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +/// ), +/// } +/// ``` +fn indent_macro_snippet( + context: &RewriteContext, + macro_str: &str, + indent: Indent, +) -> Option { + let mut lines = macro_str.lines(); + let first_line = lines.next().map(|s| s.trim_right())?; + let mut trimmed_lines = Vec::with_capacity(16); + + let min_prefix_space_width = lines + .filter_map(|line| { + let prefix_space_width = if is_empty_line(line) { + None + } else { + Some(get_prefix_space_width(context, line)) + }; + trimmed_lines.push((line.trim(), prefix_space_width)); + prefix_space_width + }) + .min()?; + + Some( + String::from(first_line) + "\n" + + &trimmed_lines + .iter() + .map(|&(line, prefix_space_width)| match prefix_space_width { + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width + .checked_sub(min_prefix_space_width) + .unwrap_or(0); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line.trim()) + } + None => String::new(), + }) + .collect::>() + .join("\n"), + ) +} + +fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { + let mut width = 0; + for c in s.chars() { + match c { + ' ' => width += 1, + '\t' => width += context.config.tab_spaces(), + _ => return width, + } + } + width +} + +fn is_empty_line(s: &str) -> bool { + s.is_empty() || s.chars().all(char::is_whitespace) +} + +// A very simple parser that just parses a macros 2.0 definition into its branches. +// Currently we do not attempt to parse any further than that. +#[derive(new)] +struct MacroParser { + toks: Cursor, +} + +impl MacroParser { + // (`(` ... `)` `=>` `{` ... `}`)* + fn parse(&mut self) -> Option { + let mut branches = vec![]; + while self.toks.look_ahead(1).is_some() { + branches.push(self.parse_branch()?); + } + + Some(Macro { branches }) + } + + // `(` ... `)` `=>` `{` ... `}` + fn parse_branch(&mut self) -> Option { + let tok = self.toks.next()?; + let (lo, args_paren_kind) = match tok { + TokenTree::Token(..) => return None, + TokenTree::Delimited(sp, ref d) => (sp.lo(), d.delim), + }; + let args = tok.joint().into(); + match self.toks.next()? { + TokenTree::Token(_, Token::FatArrow) => {} + _ => return None, + } + let (mut hi, body) = match self.toks.next()? { + TokenTree::Token(..) => return None, + TokenTree::Delimited(sp, _) => { + let data = sp.data(); + ( + data.hi, + Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), + ) + } + }; + if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { + self.toks.next(); + hi = sp.hi(); + } + Some(MacroBranch { + span: mk_sp(lo, hi), + args_paren_kind, + args, + body, + }) + } +} + +// A parsed macros 2.0 macro definition. +struct Macro { + branches: Vec, +} + +// FIXME: it would be more efficient to use references to the token streams +// rather than clone them, if we can make the borrowing work out. +struct MacroBranch { + span: Span, + args_paren_kind: DelimToken, + args: ThinTokenStream, + body: Span, +} + +impl MacroBranch { + fn rewrite( + &self, + context: &RewriteContext, + shape: Shape, + multi_branch_style: bool, + ) -> Option { + // Only attempt to format function-like macros. + if self.args_paren_kind != DelimToken::Paren { + // FIXME(#1539): implement for non-sugared macros. + return None; + } + + // 5 = " => {" + let mut result = format_macro_args(self.args.clone(), shape.sub_width(5)?)?; + + if multi_branch_style { + result += " =>"; + } + + // The macro body is the most interesting part. It might end up as various + // AST nodes, but also has special variables (e.g, `$foo`) which can't be + // parsed as regular Rust code (and note that these can be escaped using + // `$$`). We'll try and format like an AST node, but we'll substitute + // variables for new names with the same length first. + + let old_body = context.snippet(self.body).trim(); + let (body_str, substs) = replace_names(old_body)?; + + let mut config = context.config.clone(); + config.set().hide_parse_errors(true); + + result += " {"; + + let has_block_body = old_body.starts_with('{'); + + let body_indent = if has_block_body { + shape.indent + } else { + // We'll hack the indent below, take this into account when formatting, + let body_indent = shape.indent.block_indent(&config); + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); + body_indent + }; + + // First try to format as items, then as statements. + let new_body = match ::format_snippet(&body_str, &config) { + Some(new_body) => new_body, + None => match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return None, + }, + }; + let new_body = wrap_str(new_body, config.max_width(), shape)?; + + // Indent the body since it is in a block. + let indent_str = body_indent.to_string(&config); + let mut new_body = new_body + .trim_right() + .lines() + .fold(String::new(), |mut s, l| { + if !l.is_empty() { + s += &indent_str; + } + s + l + "\n" + }); + + // Undo our replacement of macro variables. + // FIXME: this could be *much* more efficient. + for (old, new) in &substs { + if old_body.find(new).is_some() { + debug!("rewrite_macro_def: bailing matching variable: `{}`", new); + return None; + } + new_body = new_body.replace(new, old); + } + + if has_block_body { + result += new_body.trim(); + } else if !new_body.is_empty() { + result += "\n"; + result += &new_body; + result += &shape.indent.to_string(&config); + } + + result += "}"; + + Some(result) + } +} + +/// Format `lazy_static!` from https://crates.io/crates/lazy_static. +/// +/// # Expected syntax +/// +/// ``` +/// lazy_static! { +/// [pub] static ref NAME_1: TYPE_1 = EXPR_1; +/// [pub] static ref NAME_2: TYPE_2 = EXPR_2; +/// ... +/// [pub] static ref NAME_N: TYPE_N = EXPR_N; +/// } +/// ``` +fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) -> Option { + let mut result = String::with_capacity(1024); + let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let nested_shape = shape.block_indent(context.config.tab_spaces()); + + result.push_str("lazy_static! {"); + result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); + + macro parse_or($method:ident $(,)* $($arg:expr),* $(,)*) { + match parser.$method($($arg,)*) { + Ok(val) => { + if parser.sess.span_diagnostic.has_errors() { + parser.sess.span_diagnostic.reset_err_count(); + return None; + } else { + val + } + } + Err(mut err) => { + err.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + return None; + } + } + } + + while parser.token != Token::Eof { + // Parse a `lazy_static!` item. + let vis = ::utils::format_visibility(&parse_or!(parse_visibility, false)); + parser.eat_keyword(symbol::keywords::Static); + parser.eat_keyword(symbol::keywords::Ref); + let id = parse_or!(parse_ident); + parser.eat(&Token::Colon); + let ty = parse_or!(parse_ty); + parser.eat(&Token::Eq); + let expr = parse_or!(parse_expr); + parser.eat(&Token::Semi); + + // Rewrite as a static item. + let mut stmt = String::with_capacity(128); + stmt.push_str(&format!( + "{}static ref {}: {} =", + vis, + id, + ty.rewrite(context, shape)? + )); + result.push_str(&::expr::rewrite_assign_rhs( + context, + stmt, + &*expr, + nested_shape.sub_width(1)?, + )?); + result.push(';'); + if parser.token != Token::Eof { + result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); + } + } + + result.push_str(&shape.indent.to_string_with_newline(context.config)); + result.push('}'); + + Some(result) +} + +#[cfg(test)] +mod test { + use super::*; + use syntax::parse::{parse_stream_from_source_str, ParseSess}; + use syntax::codemap::{FileName, FilePathMapping}; + + fn format_macro_args_str(s: &str) -> String { + let input = parse_stream_from_source_str( + FileName::Custom("stdin".to_owned()), + s.to_owned(), + &ParseSess::new(FilePathMapping::empty()), + None, + ); + let shape = Shape { + width: 100, + indent: Indent::empty(), + offset: 0, + }; + format_macro_args(input.into(), shape).unwrap() + } + + #[test] + fn test_format_macro_args() { + assert_eq!(format_macro_args_str(""), "".to_owned()); + assert_eq!(format_macro_args_str("$ x : ident"), "$x: ident".to_owned()); + assert_eq!( + format_macro_args_str("$ m1 : ident , $ m2 : ident , $ x : ident"), + "$m1: ident, $m2: ident, $x: ident".to_owned() + ); + assert_eq!( + format_macro_args_str("$($beginning:ident),*;$middle:ident;$($end:ident),*"), + "$($beginning: ident),*; $middle: ident; $($end: ident),*".to_owned() + ); + assert_eq!( + format_macro_args_str( + "$ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) *" + ), + "$name: ident($($dol: tt $var: ident)*) $($body: tt)*".to_owned() + ); + } +} diff --git a/src/missed_spans.rs b/src/missed_spans.rs new file mode 100644 index 00000000000..dff6b94bd75 --- /dev/null +++ b/src/missed_spans.rs @@ -0,0 +1,312 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::iter::repeat; + +use syntax::codemap::{BytePos, FileName, Pos, Span}; + +use codemap::LineRangeUtils; +use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use config::WriteMode; +use shape::{Indent, Shape}; +use utils::{count_newlines, last_line_width, mk_sp}; +use visitor::FmtVisitor; + +struct SnippetStatus { + /// An offset to the current line from the beginnig of the original snippet. + line_start: usize, + /// A length of trailing whitespaces on the current line. + last_wspace: Option, + /// The current line number. + cur_line: usize, +} + +impl SnippetStatus { + fn new(cur_line: usize) -> Self { + SnippetStatus { + line_start: 0, + last_wspace: None, + cur_line, + } + } +} + +impl<'a> FmtVisitor<'a> { + fn output_at_start(&self) -> bool { + self.buffer.is_empty() + } + + // TODO these format_missing methods are ugly. Refactor and add unit tests + // for the central whitespace stripping loop. + pub fn format_missing(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) + } + + pub fn format_missing_with_indent(&mut self, end: BytePos) { + let config = self.config; + self.format_missing_inner(end, |this, last_snippet, snippet| { + this.push_str(last_snippet.trim_right()); + if last_snippet == snippet && !this.output_at_start() { + // No new lines in the snippet. + this.push_str("\n"); + } + let indent = this.block_indent.to_string(config); + this.push_str(&indent); + }) + } + + pub fn format_missing_no_indent(&mut self, end: BytePos) { + self.format_missing_inner(end, |this, last_snippet, _| { + this.push_str(last_snippet.trim_right()); + }) + } + + fn format_missing_inner( + &mut self, + end: BytePos, + process_last_snippet: F, + ) { + let start = self.last_pos; + + if start == end { + // Do nothing if this is the beginning of the file. + if !self.output_at_start() { + process_last_snippet(self, "", ""); + } + return; + } + + assert!( + start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end) + ); + + self.last_pos = end; + let span = mk_sp(start, end); + let snippet = self.snippet(span); + if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { + // Keep vertical spaces within range. + self.push_vertical_spaces(count_newlines(snippet)); + process_last_snippet(self, "", snippet); + } else { + self.write_snippet(span, &process_last_snippet); + } + } + + fn push_vertical_spaces(&mut self, mut newline_count: usize) { + // The buffer already has a trailing newline. + let offset = if self.buffer.ends_with('\n') { 0 } else { 1 }; + let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; + let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; + if newline_count > newline_upper_bound { + newline_count = newline_upper_bound; + } else if newline_count < newline_lower_bound { + newline_count = newline_lower_bound; + } + let blank_lines: String = repeat('\n').take(newline_count).collect(); + self.push_str(&blank_lines); + } + + fn write_snippet(&mut self, span: Span, process_last_snippet: F) + where + F: Fn(&mut FmtVisitor, &str, &str), + { + // Get a snippet from the file start to the span's hi without allocating. + // We need it to determine what precedes the current comment. If the comment + // follows code on the same line, we won't touch it. + let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos; + let local_begin = self.codemap.lookup_byte_offset(big_span_lo); + let local_end = self.codemap.lookup_byte_offset(span.hi()); + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; + + let big_diff = (span.lo() - big_span_lo).to_usize(); + let snippet = self.snippet(span); + + debug!("write_snippet `{}`", snippet); + + self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); + } + + fn write_snippet_inner( + &mut self, + big_snippet: &str, + big_diff: usize, + old_snippet: &str, + span: Span, + process_last_snippet: F, + ) where + F: Fn(&mut FmtVisitor, &str, &str), + { + // Trim whitespace from the right hand side of each line. + // Annoyingly, the library functions for splitting by lines etc. are not + // quite right, so we must do it ourselves. + let char_pos = self.codemap.lookup_char_pos(span.lo()); + let file_name = &char_pos.file.name; + let mut status = SnippetStatus::new(char_pos.line); + + let snippet = &*match self.config.write_mode() { + WriteMode::Coverage => replace_chars(old_snippet), + _ => Cow::from(old_snippet), + }; + + for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { + debug!("{:?}: {:?}", kind, subslice); + + let newline_count = count_newlines(subslice); + let within_file_lines_range = self.config.file_lines().intersects_range( + file_name, + status.cur_line, + status.cur_line + newline_count, + ); + + if CodeCharKind::Comment == kind && within_file_lines_range { + // 1: comment. + self.process_comment( + &mut status, + snippet, + &big_snippet[..(offset + big_diff)], + offset, + subslice, + ); + } else if subslice.trim().is_empty() && newline_count > 0 && within_file_lines_range { + // 2: blank lines. + self.push_vertical_spaces(newline_count); + status.cur_line += newline_count; + status.line_start = offset + newline_count; + } else { + // 3: code which we failed to format or which is not within file-lines range. + self.process_missing_code(&mut status, snippet, subslice, offset, file_name); + } + } + + process_last_snippet(self, &snippet[status.line_start..], snippet); + } + + fn process_comment( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + big_snippet: &str, + offset: usize, + subslice: &str, + ) { + let last_char = big_snippet + .chars() + .rev() + .skip_while(|rev_c| [' ', '\t'].contains(rev_c)) + .next(); + + let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); + + let comment_indent = if fix_indent { + if let Some('{') = last_char { + self.push_str("\n"); + } + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); + self.block_indent + } else { + self.push_str(" "); + Indent::from_width(self.config, last_line_width(&self.buffer)) + }; + + let comment_width = ::std::cmp::min( + self.config.comment_width(), + self.config.max_width() - self.block_indent.width(), + ); + let comment_shape = Shape::legacy(comment_width, comment_indent); + let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) + .unwrap_or_else(|| String::from(subslice)); + self.push_str(&comment_str); + + status.last_wspace = None; + status.line_start = offset + subslice.len(); + + if let Some('/') = subslice.chars().nth(1) { + // check that there are no contained block comments + if !subslice + .split('\n') + .map(|s| s.trim_left()) + .any(|s| s.len() >= 2 && &s[0..2] == "/*") + { + // Add a newline after line comments + self.push_str("\n"); + } + } else if status.line_start <= snippet.len() { + // For other comments add a newline if there isn't one at the end already + match snippet[status.line_start..].chars().next() { + Some('\n') | Some('\r') => (), + _ => self.push_str("\n"), + } + } + + status.cur_line += count_newlines(subslice); + } + + fn process_missing_code( + &mut self, + status: &mut SnippetStatus, + snippet: &str, + subslice: &str, + offset: usize, + file_name: &FileName, + ) { + for (mut i, c) in subslice.char_indices() { + i += offset; + + if c == '\n' { + let skip_this_line = !self.config + .file_lines() + .contains_line(file_name, status.cur_line); + if skip_this_line { + status.last_wspace = None; + } + + if let Some(lw) = status.last_wspace { + self.push_str(&snippet[status.line_start..lw]); + self.push_str("\n"); + status.last_wspace = None; + } else { + self.push_str(&snippet[status.line_start..i + 1]); + } + + status.cur_line += 1; + status.line_start = i + 1; + } else if c.is_whitespace() && status.last_wspace.is_none() { + status.last_wspace = Some(i); + } else if c == ';' && status.last_wspace.is_some() { + status.line_start = i; + status.last_wspace = None; + } else { + status.last_wspace = None; + } + } + + let remaining = snippet[status.line_start..subslice.len() + offset].trim(); + if !remaining.is_empty() { + self.push_str(remaining); + status.line_start = subslice.len() + offset; + } + } +} + +fn replace_chars(string: &str) -> Cow { + Cow::from( + string + .chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect::(), + ) +} diff --git a/src/modules.rs b/src/modules.rs new file mode 100644 index 00000000000..0f439910324 --- /dev/null +++ b/src/modules.rs @@ -0,0 +1,86 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::BTreeMap; +use std::io; +use std::path::{Path, PathBuf}; + +use syntax::ast; +use syntax::codemap::{self, FileName}; +use syntax::parse::parser; + +use utils::contains_skip; + +/// List all the files containing modules of a crate. +/// If a file is used twice in a crate, it appears only once. +pub fn list_files<'a>( + krate: &'a ast::Crate, + codemap: &codemap::CodeMap, +) -> Result, io::Error> { + let mut result = BTreeMap::new(); // Enforce file order determinism + let root_filename = codemap.span_to_filename(krate.span); + { + let parent = match root_filename { + FileName::Real(ref path) => path.parent().unwrap(), + _ => Path::new(""), + }; + list_submodules(&krate.module, parent, codemap, &mut result)?; + } + result.insert(root_filename, &krate.module); + Ok(result) +} + +/// Recursively list all external modules included in a module. +fn list_submodules<'a>( + module: &'a ast::Mod, + search_dir: &Path, + codemap: &codemap::CodeMap, + result: &mut BTreeMap, +) -> Result<(), io::Error> { + debug!("list_submodules: search_dir: {:?}", search_dir); + for item in &module.items { + if let ast::ItemKind::Mod(ref sub_mod) = item.node { + if !contains_skip(&item.attrs) { + let is_internal = + codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); + let dir_path = if is_internal { + search_dir.join(&item.ident.to_string()) + } else { + let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; + let dir_path = mod_path.parent().unwrap().to_owned(); + result.insert(FileName::Real(mod_path), sub_mod); + dir_path + }; + list_submodules(sub_mod, &dir_path, codemap, result)?; + } + } + } + Ok(()) +} + +/// Find the file corresponding to an external mod +fn module_file( + id: ast::Ident, + attrs: &[ast::Attribute], + dir_path: &Path, + codemap: &codemap::CodeMap, +) -> Result { + if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { + return Ok(path); + } + + match parser::Parser::default_submod_path(id, None, dir_path, codemap).result { + Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), + Err(_) => Err(io::Error::new( + io::ErrorKind::Other, + format!("Couldn't find module {}", id), + )), + } +} diff --git a/src/patterns.rs b/src/patterns.rs new file mode 100644 index 00000000000..4bcf2890c35 --- /dev/null +++ b/src/patterns.rs @@ -0,0 +1,380 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::lists::*; +use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; +use syntax::codemap::{self, BytePos, Span}; +use syntax::ptr; + +use codemap::SpanUtils; +use comment::FindUncommented; +use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, + wrap_struct_field, PairParts}; +use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list}; +use macros::{rewrite_macro, MacroPosition}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use types::{rewrite_path, PathContext}; +use utils::{format_mutability, mk_sp}; + +impl Rewrite for Pat { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), + PatKind::Ident(binding_mode, ident, ref sub_pat) => { + let (prefix, mutability) = match binding_mode { + BindingMode::ByRef(mutability) => ("ref ", mutability), + BindingMode::ByValue(mutability) => ("", mutability), + }; + let mut_infix = format_mutability(mutability); + let id_str = ident.node.to_string(); + let sub_pat = match *sub_pat { + Some(ref p) => { + // 3 - ` @ `. + let width = shape + .width + .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?; + format!( + " @ {}", + p.rewrite(context, Shape::legacy(width, shape.indent))? + ) + } + None => "".to_owned(), + }; + + Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) + } + PatKind::Wild => { + if 1 <= shape.width { + Some("_".to_owned()) + } else { + None + } + } + PatKind::Range(ref lhs, ref rhs, ref end_kind) => { + let infix = match *end_kind { + RangeEnd::Included(RangeSyntax::DotDotDot) => "...", + RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", + RangeEnd::Excluded => "..", + }; + let infix = if context.config.spaces_around_ranges() { + format!(" {} ", infix) + } else { + infix.to_owned() + }; + rewrite_pair( + &**lhs, + &**rhs, + PairParts::new("", &infix, ""), + context, + shape, + SeparatorPlace::Front, + ) + } + PatKind::Ref(ref pat, mutability) => { + let prefix = format!("&{}", format_mutability(mutability)); + rewrite_unary_prefix(context, &prefix, &**pat, shape) + } + PatKind::Tuple(ref items, dotdot_pos) => { + rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) + } + PatKind::Path(ref q_self, ref path) => { + rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) + } + PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { + let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; + rewrite_tuple_pat( + pat_vec, + dotdot_pos, + Some(path_str), + self.span, + context, + shape, + ) + } + PatKind::Lit(ref expr) => expr.rewrite(context, shape), + PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { + // Rewrite all the sub-patterns. + let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); + let slice_pat = slice_pat + .as_ref() + .map(|p| Some(format!("{}..", p.rewrite(context, shape)?))); + let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); + + // Munge them together. + let pats: Option> = + prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); + + // Check that all the rewrites succeeded, and if not return None. + let pats = pats?; + + // Unwrap all the sub-strings and join them with commas. + let result = if context.config.spaces_within_parens_and_brackets() { + format!("[ {} ]", pats.join(", ")) + } else { + format!("[{}]", pats.join(", ")) + }; + Some(result) + } + PatKind::Struct(ref path, ref fields, ellipsis) => { + rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) + } + PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), + } + } +} + +fn rewrite_struct_pat( + path: &ast::Path, + fields: &[codemap::Spanned], + ellipsis: bool, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + // 2 = ` {` + let path_shape = shape.sub_width(2)?; + let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; + + if fields.is_empty() && !ellipsis { + return Some(format!("{} {{}}", path_str)); + } + + let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") }; + + // 3 = ` { `, 2 = ` }`. + let (h_shape, v_shape) = + struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?; + + let items = itemize_list( + context.snippet_provider, + fields.iter(), + terminator, + ",", + |f| f.span.lo(), + |f| f.span.hi(), + |f| f.node.rewrite(context, v_shape), + context.snippet_provider.span_after(span, "{"), + span.hi(), + false, + ); + let item_vec = items.collect::>(); + + let tactic = struct_lit_tactic(h_shape, context, &item_vec); + let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); + let fmt = struct_lit_formatting(nested_shape, tactic, context, false); + + let mut fields_str = write_list(&item_vec, &fmt)?; + let one_line_width = h_shape.map_or(0, |shape| shape.width); + + if ellipsis { + if fields_str.contains('\n') || fields_str.len() > one_line_width { + // Add a missing trailing comma. + if fmt.trailing_separator == SeparatorTactic::Never { + fields_str.push_str(","); + } + fields_str.push_str("\n"); + fields_str.push_str(&nested_shape.indent.to_string(context.config)); + fields_str.push_str(".."); + } else { + if !fields_str.is_empty() { + // there are preceding struct fields being matched on + if fmt.tactic == DefinitiveListTactic::Vertical { + // if the tactic is Vertical, write_list already added a trailing , + fields_str.push_str(" "); + } else { + fields_str.push_str(", "); + } + } + fields_str.push_str(".."); + } + } + + let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + Some(format!("{} {{{}}}", path_str, fields_str)) +} + +impl Rewrite for FieldPat { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let pat = self.pat.rewrite(context, shape); + if self.is_shorthand { + pat + } else { + let pat_str = pat?; + let id_str = self.ident.to_string(); + let one_line_width = id_str.len() + 2 + pat_str.len(); + if one_line_width <= shape.width { + Some(format!("{}: {}", id_str, pat_str)) + } else { + let nested_shape = shape.block_indent(context.config.tab_spaces()); + let pat_str = self.pat.rewrite(context, nested_shape)?; + Some(format!( + "{}:\n{}{}", + id_str, + nested_shape.indent.to_string(context.config), + pat_str, + )) + } + } + } +} + +pub enum TuplePatField<'a> { + Pat(&'a ptr::P), + Dotdot(Span), +} + +impl<'a> Rewrite for TuplePatField<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + TuplePatField::Pat(p) => p.rewrite(context, shape), + TuplePatField::Dotdot(_) => Some("..".to_string()), + } + } +} + +impl<'a> Spanned for TuplePatField<'a> { + fn span(&self) -> Span { + match *self { + TuplePatField::Pat(p) => p.span(), + TuplePatField::Dotdot(span) => span, + } + } +} + +pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { + match *pat { + TuplePatField::Pat(pat) => match pat.node { + ast::PatKind::Path(..) + | ast::PatKind::Tuple(..) + | ast::PatKind::Struct(..) + | ast::PatKind::TupleStruct(..) => context.use_block_indent() && len == 1, + ast::PatKind::Ref(ref p, _) | ast::PatKind::Box(ref p) => { + can_be_overflowed_pat(context, &TuplePatField::Pat(p), len) + } + ast::PatKind::Lit(ref expr) => can_be_overflowed_expr(context, expr, len), + _ => false, + }, + TuplePatField::Dotdot(..) => false, + } +} + +fn rewrite_tuple_pat( + pats: &[ptr::P], + dotdot_pos: Option, + path_str: Option, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); + + if let Some(pos) = dotdot_pos { + let prev = if pos == 0 { + span.lo() + } else { + pats[pos - 1].span().hi() + }; + let next = if pos + 1 >= pats.len() { + span.hi() + } else { + pats[pos + 1].span().lo() + }; + let dot_span = mk_sp(prev, next); + let snippet = context.snippet(dot_span); + let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32); + let dotdot = TuplePatField::Dotdot(Span::new( + lo, + // 2 == "..".len() + lo + BytePos(2), + codemap::NO_EXPANSION, + )); + pat_vec.insert(pos, dotdot); + } + + if pat_vec.is_empty() { + return Some(format!("{}()", path_str.unwrap_or_default())); + } + + let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); + let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 + { + let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; + let sp = pat_vec[new_item_count - 1].span(); + let snippet = context.snippet(sp); + let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + ( + &pat_vec[..new_item_count], + mk_sp(span.lo(), lo + BytePos(1)), + ) + } else { + (&pat_vec[..], span) + }; + + // add comma if `(x,)` + let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + let mut context = context.clone(); + if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { + context.inside_macro = true; + } + let path_str = path_str.unwrap_or_default(); + let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); + for pat in pat_vec { + pat_ref_vec.push(pat); + } + + rewrite_call_inner( + &context, + &path_str, + &pat_ref_vec[..], + span, + shape, + shape.width, + add_comma, + ) +} + +fn count_wildcard_suffix_len( + context: &RewriteContext, + patterns: &[TuplePatField], + span: Span, + shape: Shape, +) -> usize { + let mut suffix_len = 0; + + let items: Vec<_> = itemize_list( + context.snippet_provider, + patterns.iter(), + ")", + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(context, shape), + context.snippet_provider.span_after(span, "("), + span.hi() - BytePos(1), + false, + ).collect(); + + for item in items.iter().rev().take_while(|i| match i.item { + Some(ref internal_string) if internal_string == "_" => true, + _ => false, + }) { + suffix_len += 1; + + if item.pre_comment.is_some() || item.post_comment.is_some() { + break; + } + } + + suffix_len +} diff --git a/src/reorder.rs b/src/reorder.rs new file mode 100644 index 00000000000..d4bc36fc83f --- /dev/null +++ b/src/reorder.rs @@ -0,0 +1,331 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Reorder items. +//! +//! `mod`, `extern crate` and `use` declarations are reorderd in alphabetical +//! order. Trait items are reordered in pre-determined order (associated types +//! and constatns comes before methods). + +// TODO(#2455): Reorder trait items. + +use config::{Config, lists::*}; +use syntax::{ast, attr, codemap::Span}; + +use attr::filter_inline_attrs; +use codemap::LineRangeUtils; +use comment::combine_strs_with_missing_comments; +use imports::{path_to_imported_ident, rewrite_import}; +use items::{rewrite_extern_crate, rewrite_mod}; +use lists::{itemize_list, write_list, ListFormatting}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use utils::mk_sp; +use visitor::FmtVisitor; + +use std::cmp::Ordering; + +fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { + a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) +} + +fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { + for segment in a.segments.iter().zip(b.segments.iter()) { + let ord = compare_path_segments(segment.0, segment.1); + if ord != Ordering::Equal { + return ord; + } + } + a.segments.len().cmp(&b.segments.len()) +} + +fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Ordering { + use ast::UseTreeKind::*; + + // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be + // fully added + if !nested { + let paths_cmp = compare_paths(&a.prefix, &b.prefix); + if paths_cmp != Ordering::Equal { + return paths_cmp; + } + } + + match (&a.kind, &b.kind) { + (&Simple(ident_a), &Simple(ident_b)) => { + let name_a = &*path_to_imported_ident(&a.prefix).name.as_str(); + let name_b = &*path_to_imported_ident(&b.prefix).name.as_str(); + let name_ordering = if name_a == "self" { + if name_b == "self" { + Ordering::Equal + } else { + Ordering::Less + } + } else if name_b == "self" { + Ordering::Greater + } else { + name_a.cmp(name_b) + }; + if name_ordering == Ordering::Equal { + if ident_a.name.as_str() != name_a { + if ident_b.name.as_str() != name_b { + ident_a.name.as_str().cmp(&ident_b.name.as_str()) + } else { + Ordering::Greater + } + } else { + Ordering::Less + } + } else { + name_ordering + } + } + (&Glob, &Glob) => Ordering::Equal, + (&Simple(_), _) | (&Glob, &Nested(_)) => Ordering::Less, + (&Nested(ref a_items), &Nested(ref b_items)) => { + let mut a = a_items + .iter() + .map(|&(ref tree, _)| tree.clone()) + .collect::>(); + let mut b = b_items + .iter() + .map(|&(ref tree, _)| tree.clone()) + .collect::>(); + a.sort_by(|a, b| compare_use_trees(a, b, true)); + b.sort_by(|a, b| compare_use_trees(a, b, true)); + for comparison_pair in a.iter().zip(b.iter()) { + let ord = compare_use_trees(comparison_pair.0, comparison_pair.1, true); + if ord != Ordering::Equal { + return ord; + } + } + a.len().cmp(&b.len()) + } + (&Glob, &Simple(_)) | (&Nested(_), _) => Ordering::Greater, + } +} + +/// Choose the ordering between the given two items. +fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { + match (&a.node, &b.node) { + (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { + a.ident.name.as_str().cmp(&b.ident.name.as_str()) + } + (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { + compare_use_trees(a_tree, b_tree, false) + } + (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { + // `extern crate foo as bar;` + // ^^^ Comparing this. + let a_orig_name = + a_name.map_or_else(|| a.ident.name.as_str(), |symbol| symbol.as_str()); + let b_orig_name = + b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); + let result = a_orig_name.cmp(&b_orig_name); + if result != Ordering::Equal { + return result; + } + + // `extern crate foo as bar;` + // ^^^ Comparing this. + match (a_name, b_name) { + (Some(..), None) => Ordering::Greater, + (None, Some(..)) => Ordering::Less, + (None, None) => Ordering::Equal, + (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), + } + } + _ => unreachable!(), + } +} + +/// Rewrite a list of items with reordering. Every item in `items` must have +/// the same `ast::ItemKind`. +// TODO (some day) remove unused imports, expand globs, compress many single +// imports into a list import. +fn rewrite_reorderable_items( + context: &RewriteContext, + reorderable_items: &[&ast::Item], + shape: Shape, + span: Span, +) -> Option { + let items = itemize_list( + context.snippet_provider, + reorderable_items.iter(), + "", + ";", + |item| item.span().lo(), + |item| item.span().hi(), + |item| { + let attrs = filter_inline_attrs(&item.attrs, item.span()); + let attrs_str = attrs.rewrite(context, shape)?; + + let missed_span = if attrs.is_empty() { + mk_sp(item.span.lo(), item.span.lo()) + } else { + mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) + }; + + let item_str = match item.node { + ast::ItemKind::Use(ref tree) => { + rewrite_import(context, &item.vis, tree, &item.attrs, shape)? + } + ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, + ast::ItemKind::Mod(..) => rewrite_mod(item), + _ => return None, + }; + + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missed_span, + shape, + false, + ) + }, + span.lo(), + span.hi(), + false, + ); + let mut item_pair_vec: Vec<_> = items.zip(reorderable_items.iter()).collect(); + item_pair_vec.sort_by(|a, b| compare_items(a.1, b.1)); + let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); + + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: true, + preserve_newline: false, + config: context.config, + }; + + write_list(&item_vec, &fmt) +} + +fn contains_macro_use_attr(item: &ast::Item) -> bool { + attr::contains_name(&filter_inline_attrs(&item.attrs, item.span()), "macro_use") +} + +/// A simplified version of `ast::ItemKind`. +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +enum ReorderableItemKind { + ExternCrate, + Mod, + Use, + /// An item that cannot be reordered. Either has an unreorderable item kind + /// or an `macro_use` attribute. + Other, +} + +impl ReorderableItemKind { + pub fn from(item: &ast::Item) -> Self { + match item.node { + _ if contains_macro_use_attr(item) => ReorderableItemKind::Other, + ast::ItemKind::ExternCrate(..) => ReorderableItemKind::ExternCrate, + ast::ItemKind::Mod(..) => ReorderableItemKind::Mod, + ast::ItemKind::Use(..) => ReorderableItemKind::Use, + _ => ReorderableItemKind::Other, + } + } + + pub fn is_same_item_kind(&self, item: &ast::Item) -> bool { + ReorderableItemKind::from(item) == *self + } + + pub fn is_reorderable(&self, config: &Config) -> bool { + match *self { + ReorderableItemKind::ExternCrate => config.reorder_extern_crates(), + ReorderableItemKind::Mod => config.reorder_modules(), + ReorderableItemKind::Use => config.reorder_imports(), + ReorderableItemKind::Other => false, + } + } + + pub fn in_group(&self, config: &Config) -> bool { + match *self { + ReorderableItemKind::ExternCrate => config.reorder_extern_crates_in_group(), + ReorderableItemKind::Mod => config.reorder_modules(), + ReorderableItemKind::Use => config.reorder_imports_in_group(), + ReorderableItemKind::Other => false, + } + } +} + +impl<'b, 'a: 'b> FmtVisitor<'a> { + /// Format items with the same item kind and reorder them. If `in_group` is + /// `true`, then the items separated by an empty line will not be reordered + /// together. + fn walk_reorderable_items( + &mut self, + items: &[&ast::Item], + item_kind: ReorderableItemKind, + in_group: bool, + ) -> usize { + let mut last = self.codemap.lookup_line_range(items[0].span()); + let item_length = items + .iter() + .take_while(|ppi| { + item_kind.is_same_item_kind(&***ppi) && (!in_group || { + let current = self.codemap.lookup_line_range(ppi.span()); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) + }) + .count(); + let items = &items[..item_length]; + + let at_least_one_in_file_lines = items + .iter() + .any(|item| !out_of_file_lines_range!(self, item.span)); + + if at_least_one_in_file_lines && !items.is_empty() { + let lo = items.first().unwrap().span().lo(); + let hi = items.last().unwrap().span().hi(); + let span = mk_sp(lo, hi); + let rw = rewrite_reorderable_items(&self.get_context(), items, self.shape(), span); + self.push_rewrite(span, rw); + } else { + for item in items { + self.push_rewrite(item.span, None); + } + } + + item_length + } + + /// Visit and format the given items. Items are reordered If they are + /// consecutive and reorderable. + pub fn visit_items_with_reordering(&mut self, mut items: &[&ast::Item]) { + while !items.is_empty() { + // If the next item is a `use`, `extern crate` or `mod`, then extract it and any + // subsequent items that have the same item kind to be reordered within + // `walk_reorderable_items`. Otherwise, just format the next item for output. + let item_kind = ReorderableItemKind::from(items[0]); + if item_kind.is_reorderable(self.config) { + let visited_items_num = + self.walk_reorderable_items(items, item_kind, item_kind.in_group(self.config)); + let (_, rest) = items.split_at(visited_items_num); + items = rest; + } else { + // Reaching here means items were not reordered. There must be at least + // one item left in `items`, so calling `unwrap()` here is safe. + let (item, rest) = items.split_first().unwrap(); + self.visit_item(item); + items = rest; + } + } + } +} diff --git a/src/rewrite.rs b/src/rewrite.rs new file mode 100644 index 00000000000..708e31d86dd --- /dev/null +++ b/src/rewrite.rs @@ -0,0 +1,54 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// A generic trait to abstract the rewriting of an element (of the AST). + +use syntax::codemap::{CodeMap, Span}; +use syntax::parse::ParseSess; + +use config::{Config, IndentStyle}; +use shape::Shape; +use visitor::SnippetProvider; + +pub trait Rewrite { + /// Rewrite self into shape. + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; +} + +#[derive(Clone)] +pub struct RewriteContext<'a> { + pub parse_session: &'a ParseSess, + pub codemap: &'a CodeMap, + pub config: &'a Config, + pub inside_macro: bool, + // Force block indent style even if we are using visual indent style. + pub use_block: bool, + // When `format_if_else_cond_comment` is true, unindent the comment on top + // of the `else` or `else if`. + pub is_if_else_block: bool, + // When rewriting chain, veto going multi line except the last element + pub force_one_line_chain: bool, + pub snippet_provider: &'a SnippetProvider<'a>, +} + +impl<'a> RewriteContext<'a> { + pub fn snippet(&self, span: Span) -> &str { + self.snippet_provider.span_to_snippet(span).unwrap() + } + + /// Return true if we should use block indent style for rewriting function call. + pub fn use_block_indent(&self) -> bool { + self.config.indent_style() == IndentStyle::Block || self.use_block + } + + pub fn budget(&self, used_width: usize) -> usize { + self.config.max_width().checked_sub(used_width).unwrap_or(0) + } +} diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs new file mode 100644 index 00000000000..f9919157620 --- /dev/null +++ b/src/rustfmt_diff.rs @@ -0,0 +1,303 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::Color; +use diff; +use std::collections::VecDeque; +use std::io; +use term; +use std::io::Write; +use utils::use_colored_tty; + +#[derive(Debug, PartialEq)] +pub enum DiffLine { + Context(String), + Expected(String), + Resulting(String), +} + +#[derive(Debug, PartialEq)] +pub struct Mismatch { + /// The line number in the formatted version. + pub line_number: u32, + /// The line number in the original version. + pub line_number_orig: u32, + /// The set of lines (context and old/new) in the mismatch. + pub lines: Vec, +} + +impl Mismatch { + fn new(line_number: u32, line_number_orig: u32) -> Mismatch { + Mismatch { + line_number, + line_number_orig, + lines: Vec::new(), + } + } +} + +// This struct handles writing output to stdout and abstracts away the logic +// of printing in color, if it's possible in the executing environment. +pub struct OutputWriter { + terminal: Option>>, +} + +impl OutputWriter { + // Create a new OutputWriter instance based on the caller's preference + // for colorized output and the capabilities of the terminal. + pub fn new(color: Color) -> Self { + if let Some(t) = term::stdout() { + if use_colored_tty(color) && t.supports_color() { + return OutputWriter { terminal: Some(t) }; + } + } + OutputWriter { terminal: None } + } + + // Write output in the optionally specified color. The output is written + // in the specified color if this OutputWriter instance contains a + // Terminal in its `terminal` field. + pub fn writeln(&mut self, msg: &str, color: Option) { + match &mut self.terminal { + Some(ref mut t) => { + if let Some(color) = color { + t.fg(color).unwrap(); + } + writeln!(t, "{}", msg).unwrap(); + if color.is_some() { + t.reset().unwrap(); + } + } + None => println!("{}", msg), + } + } +} + +// Produces a diff between the expected output and actual output of rustfmt. +pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { + let mut line_number = 1; + let mut line_number_orig = 1; + let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); + let mut lines_since_mismatch = context_size + 1; + let mut results = Vec::new(); + let mut mismatch = Mismatch::new(0, 0); + + for result in diff::lines(expected, actual) { + match result { + diff::Result::Left(str) => { + if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { + results.push(mismatch); + mismatch = Mismatch::new( + line_number - context_queue.len() as u32, + line_number_orig - context_queue.len() as u32, + ); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Resulting(str.to_owned())); + line_number_orig += 1; + lines_since_mismatch = 0; + } + diff::Result::Right(str) => { + if lines_since_mismatch >= context_size && lines_since_mismatch > 0 { + results.push(mismatch); + mismatch = Mismatch::new( + line_number - context_queue.len() as u32, + line_number_orig - context_queue.len() as u32, + ); + } + + while let Some(line) = context_queue.pop_front() { + mismatch.lines.push(DiffLine::Context(line.to_owned())); + } + + mismatch.lines.push(DiffLine::Expected(str.to_owned())); + line_number += 1; + lines_since_mismatch = 0; + } + diff::Result::Both(str, _) => { + if context_queue.len() >= context_size { + let _ = context_queue.pop_front(); + } + + if lines_since_mismatch < context_size { + mismatch.lines.push(DiffLine::Context(str.to_owned())); + } else if context_size > 0 { + context_queue.push_back(str); + } + + line_number += 1; + line_number_orig += 1; + lines_since_mismatch += 1; + } + } + } + + results.push(mismatch); + results.remove(0); + + results +} + +pub fn print_diff(diff: Vec, get_section_title: F, color: Color) +where + F: Fn(u32) -> String, +{ + let mut writer = OutputWriter::new(color); + + for mismatch in diff { + let title = get_section_title(mismatch.line_number); + writer.writeln(&format!("{}", title), None); + + for line in mismatch.lines { + match line { + DiffLine::Context(ref str) => writer.writeln(&format!(" {}⏎", str), None), + DiffLine::Expected(ref str) => { + writer.writeln(&format!("+{}⏎", str), Some(term::color::GREEN)) + } + DiffLine::Resulting(ref str) => { + writer.writeln(&format!("-{}⏎", str), Some(term::color::RED)) + } + } + } + } +} + +/// Convert a Mismatch into a serialised form which just includes +/// enough information to modify the original file. +/// Each section starts with a line with three integers, space separated: +/// lineno num_removed num_added +/// followed by (num_added) lines of added text. The line numbers are +/// relative to the original file. +pub fn output_modified(mut out: W, diff: Vec) +where + W: Write, +{ + for mismatch in diff { + let (num_removed, num_added) = mismatch.lines.iter().fold((0, 0), |(rem, add), line| { + match *line { + DiffLine::Context(_) => panic!("No Context expected"), + DiffLine::Expected(_) => (rem, add + 1), + DiffLine::Resulting(_) => (rem + 1, add), + } + }); + // Write a header with enough information to separate the modified lines. + writeln!( + out, + "{} {} {}", + mismatch.line_number_orig, num_removed, num_added + ).unwrap(); + + for line in mismatch.lines { + match line { + DiffLine::Context(_) | DiffLine::Resulting(_) => (), + DiffLine::Expected(ref str) => { + writeln!(out, "{}", str).unwrap(); + } + } + } + } +} + +#[cfg(test)] +mod test { + use super::{make_diff, Mismatch}; + use super::DiffLine::*; + + #[test] + fn diff_simple() { + let src = "one\ntwo\nthree\nfour\nfive\n"; + let dest = "one\ntwo\ntrois\nfour\nfive\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 2, + line_number_orig: 2, + lines: vec![ + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), + ], + }, + ] + ); + } + + #[test] + fn diff_simple2() { + let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n"; + let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 2, + line_number_orig: 2, + lines: vec![ + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), + ], + }, + Mismatch { + line_number: 5, + line_number_orig: 5, + lines: vec![ + Resulting("five".to_owned()), + Expected("cinq".to_owned()), + Context("six".to_owned()), + ], + }, + ] + ); + } + + #[test] + fn diff_zerocontext() { + let src = "one\ntwo\nthree\nfour\nfive\n"; + let dest = "one\ntwo\ntrois\nfour\nfive\n"; + let diff = make_diff(src, dest, 0); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 3, + line_number_orig: 3, + lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], + }, + ] + ); + } + + #[test] + fn diff_trailing_newline() { + let src = "one\ntwo\nthree\nfour\nfive"; + let dest = "one\ntwo\nthree\nfour\nfive\n"; + let diff = make_diff(src, dest, 1); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 5, + line_number_orig: 5, + lines: vec![Context("five".to_owned()), Expected("".to_owned())], + }, + ] + ); + } +} diff --git a/src/shape.rs b/src/shape.rs new file mode 100644 index 00000000000..22d6a096efa --- /dev/null +++ b/src/shape.rs @@ -0,0 +1,364 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; +use std::ops::{Add, Sub}; + +use Config; + +#[derive(Copy, Clone, Debug)] +pub struct Indent { + // Width of the block indent, in characters. Must be a multiple of + // Config::tab_spaces. + pub block_indent: usize, + // Alignment in characters. + pub alignment: usize, +} + +// INDENT_BUFFER.len() = 80 +const INDENT_BUFFER_LEN: usize = 80; +const INDENT_BUFFER: &str = + "\n "; +impl Indent { + pub fn new(block_indent: usize, alignment: usize) -> Indent { + Indent { + block_indent, + alignment, + } + } + + pub fn from_width(config: &Config, width: usize) -> Indent { + if config.hard_tabs() { + let tab_num = width / config.tab_spaces(); + let alignment = width % config.tab_spaces(); + Indent::new(config.tab_spaces() * tab_num, alignment) + } else { + Indent::new(width, 0) + } + } + + pub fn empty() -> Indent { + Indent::new(0, 0) + } + + pub fn block_only(&self) -> Indent { + Indent { + block_indent: self.block_indent, + alignment: 0, + } + } + + pub fn block_indent(mut self, config: &Config) -> Indent { + self.block_indent += config.tab_spaces(); + self + } + + pub fn block_unindent(mut self, config: &Config) -> Indent { + if self.block_indent < config.tab_spaces() { + Indent::new(self.block_indent, 0) + } else { + self.block_indent -= config.tab_spaces(); + self + } + } + + pub fn width(&self) -> usize { + self.block_indent + self.alignment + } + + pub fn to_string(&self, config: &Config) -> Cow<'static, str> { + self.to_string_inner(config, 1) + } + + pub fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { + self.to_string_inner(config, 0) + } + + fn to_string_inner(&self, config: &Config, offset: usize) -> Cow<'static, str> { + let (num_tabs, num_spaces) = if config.hard_tabs() { + (self.block_indent / config.tab_spaces(), self.alignment) + } else { + (0, self.width()) + }; + let num_chars = num_tabs + num_spaces; + if num_tabs == 0 && num_chars + offset <= INDENT_BUFFER_LEN { + Cow::from(&INDENT_BUFFER[offset..num_chars + 1]) + } else { + let mut indent = String::with_capacity(num_chars + if offset == 0 { 1 } else { 0 }); + if offset == 0 { + indent.push('\n'); + } + for _ in 0..num_tabs { + indent.push('\t') + } + for _ in 0..num_spaces { + indent.push(' ') + } + Cow::from(indent) + } + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: Indent) -> Indent { + Indent { + block_indent: self.block_indent + rhs.block_indent, + alignment: self.alignment + rhs.alignment, + } + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: Indent) -> Indent { + Indent::new( + self.block_indent - rhs.block_indent, + self.alignment - rhs.alignment, + ) + } +} + +impl Add for Indent { + type Output = Indent; + + fn add(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment + rhs) + } +} + +impl Sub for Indent { + type Output = Indent; + + fn sub(self, rhs: usize) -> Indent { + Indent::new(self.block_indent, self.alignment - rhs) + } +} + +#[derive(Copy, Clone, Debug)] +pub struct Shape { + pub width: usize, + // The current indentation of code. + pub indent: Indent, + // Indentation + any already emitted text on the first line of the current + // statement. + pub offset: usize, +} + +impl Shape { + /// `indent` is the indentation of the first line. The next lines + /// should begin with at least `indent` spaces (except backwards + /// indentation). The first line should not begin with indentation. + /// `width` is the maximum number of characters on the last line + /// (excluding `indent`). The width of other lines is not limited by + /// `width`. + /// Note that in reality, we sometimes use width for lines other than the + /// last (i.e., we are conservative). + // .......*-------* + // | | + // | *-* + // *-----| + // |<------------>| max width + // |<---->| indent + // |<--->| width + pub fn legacy(width: usize, indent: Indent) -> Shape { + Shape { + width, + indent, + offset: indent.alignment, + } + } + + pub fn indented(indent: Indent, config: &Config) -> Shape { + Shape { + width: config.max_width().checked_sub(indent.width()).unwrap_or(0), + indent, + offset: indent.alignment, + } + } + + pub fn with_max_width(&self, config: &Config) -> Shape { + Shape { + width: config + .max_width() + .checked_sub(self.indent.width()) + .unwrap_or(0), + ..*self + } + } + + pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { + Shape { + width, + indent, + offset, + } + } + + pub fn visual_indent(&self, extra_width: usize) -> Shape { + let alignment = self.offset + extra_width; + Shape { + width: self.width, + indent: Indent::new(self.indent.block_indent, alignment), + offset: alignment, + } + } + + pub fn block_indent(&self, extra_width: usize) -> Shape { + if self.indent.alignment == 0 { + Shape { + width: self.width, + indent: Indent::new(self.indent.block_indent + extra_width, 0), + offset: 0, + } + } else { + Shape { + width: self.width, + indent: self.indent + extra_width, + offset: self.indent.alignment + extra_width, + } + } + } + + pub fn block_left(&self, width: usize) -> Option { + self.block_indent(width).sub_width(width) + } + + pub fn add_offset(&self, extra_width: usize) -> Shape { + Shape { + offset: self.offset + extra_width, + ..*self + } + } + + pub fn block(&self) -> Shape { + Shape { + indent: self.indent.block_only(), + ..*self + } + } + + pub fn sub_width(&self, width: usize) -> Option { + Some(Shape { + width: self.width.checked_sub(width)?, + ..*self + }) + } + + pub fn shrink_left(&self, width: usize) -> Option { + Some(Shape { + width: self.width.checked_sub(width)?, + indent: self.indent + width, + offset: self.offset + width, + }) + } + + pub fn offset_left(&self, width: usize) -> Option { + self.add_offset(width).sub_width(width) + } + + pub fn used_width(&self) -> usize { + self.indent.block_indent + self.offset + } + + pub fn rhs_overhead(&self, config: &Config) -> usize { + config + .max_width() + .checked_sub(self.used_width() + self.width) + .unwrap_or(0) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn indent_add_sub() { + let indent = Indent::new(4, 8) + Indent::new(8, 12); + assert_eq!(12, indent.block_indent); + assert_eq!(20, indent.alignment); + + let indent = indent - Indent::new(4, 4); + assert_eq!(8, indent.block_indent); + assert_eq!(16, indent.alignment); + } + + #[test] + fn indent_add_sub_alignment() { + let indent = Indent::new(4, 8) + 4; + assert_eq!(4, indent.block_indent); + assert_eq!(12, indent.alignment); + + let indent = indent - 4; + assert_eq!(4, indent.block_indent); + assert_eq!(8, indent.alignment); + } + + #[test] + fn indent_to_string_spaces() { + let config = Config::default(); + let indent = Indent::new(4, 8); + + // 12 spaces + assert_eq!(" ", indent.to_string(&config)); + } + + #[test] + fn indent_to_string_hard_tabs() { + let mut config = Config::default(); + config.set().hard_tabs(true); + let indent = Indent::new(8, 4); + + // 2 tabs + 4 spaces + assert_eq!("\t\t ", indent.to_string(&config)); + } + + #[test] + fn shape_visual_indent() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.visual_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } + + #[test] + fn shape_block_indent_without_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 0); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(24, shape.indent.block_indent); + assert_eq!(0, shape.indent.alignment); + assert_eq!(0, shape.offset); + } + + #[test] + fn shape_block_indent_with_alignment() { + let config = Config::default(); + let indent = Indent::new(4, 8); + let shape = Shape::legacy(config.max_width(), indent); + let shape = shape.block_indent(20); + + assert_eq!(config.max_width(), shape.width); + assert_eq!(4, shape.indent.block_indent); + assert_eq!(28, shape.indent.alignment); + assert_eq!(28, shape.offset); + } +} diff --git a/src/spanned.rs b/src/spanned.rs new file mode 100644 index 00000000000..20dd8438798 --- /dev/null +++ b/src/spanned.rs @@ -0,0 +1,192 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::ast; +use syntax::codemap::Span; + +use macros::MacroArg; +use utils::{mk_sp, outer_attributes}; + +/// Spanned returns a span including attributes, if available. +pub trait Spanned { + fn span(&self) -> Span; +} + +macro_rules! span_with_attrs_lo_hi { + ($this: ident, $lo: expr, $hi: expr) => {{ + let attrs = outer_attributes(&$this.attrs); + if attrs.is_empty() { + mk_sp($lo, $hi) + } else { + mk_sp(attrs[0].span.lo(), $hi) + } + }}; +} + +macro_rules! span_with_attrs { + ($this: ident) => { + span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) + }; +} + +macro_rules! implement_spanned { + ($this: ty) => { + impl Spanned for $this { + fn span(&self) -> Span { + span_with_attrs!(self) + } + } + }; +} + +// Implement `Spanned` for structs with `attrs` field. +implement_spanned!(ast::Expr); +implement_spanned!(ast::Field); +implement_spanned!(ast::ForeignItem); +implement_spanned!(ast::Item); +implement_spanned!(ast::Local); +implement_spanned!(ast::TraitItem); +implement_spanned!(ast::ImplItem); + +impl Spanned for ast::Stmt { + fn span(&self) -> Span { + match self.node { + ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { + mk_sp(expr.span().lo(), self.span.hi()) + } + ast::StmtKind::Mac(ref mac) => { + let (_, _, ref attrs) = **mac; + if attrs.is_empty() { + self.span + } else { + mk_sp(attrs[0].span.lo(), self.span.hi()) + } + } + } + } +} + +impl Spanned for ast::Pat { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Ty { + fn span(&self) -> Span { + self.span + } +} + +impl Spanned for ast::Arm { + fn span(&self) -> Span { + let lo = if let Some(sp) = self.beginning_vert { + sp.lo() + } else { + self.pats[0].span.lo() + }; + span_with_attrs_lo_hi!(self, lo, self.body.span.hi()) + } +} + +impl Spanned for ast::Arg { + fn span(&self) -> Span { + if ::items::is_named_arg(self) { + mk_sp(self.pat.span.lo(), self.ty.span.hi()) + } else { + self.ty.span + } + } +} + +impl Spanned for ast::GenericParam { + fn span(&self) -> Span { + match *self { + ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(), + ast::GenericParam::Type(ref ty) => ty.span(), + } + } +} + +impl Spanned for ast::StructField { + fn span(&self) -> Span { + span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) + } +} + +impl Spanned for ast::WherePredicate { + fn span(&self) -> Span { + match *self { + ast::WherePredicate::BoundPredicate(ref p) => p.span, + ast::WherePredicate::RegionPredicate(ref p) => p.span, + ast::WherePredicate::EqPredicate(ref p) => p.span, + } + } +} + +impl Spanned for ast::FunctionRetTy { + fn span(&self) -> Span { + match *self { + ast::FunctionRetTy::Default(span) => span, + ast::FunctionRetTy::Ty(ref ty) => ty.span, + } + } +} + +impl Spanned for ast::TyParam { + fn span(&self) -> Span { + // Note that ty.span is the span for ty.ident, not the whole item. + let lo = if self.attrs.is_empty() { + self.span.lo() + } else { + self.attrs[0].span.lo() + }; + if let Some(ref def) = self.default { + return mk_sp(lo, def.span.hi()); + } + if self.bounds.is_empty() { + return mk_sp(lo, self.span.hi()); + } + let hi = self.bounds[self.bounds.len() - 1].span().hi(); + mk_sp(lo, hi) + } +} + +impl Spanned for ast::TyParamBound { + fn span(&self) -> Span { + match *self { + ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, + ast::TyParamBound::RegionTyParamBound(ref l) => l.span, + } + } +} + +impl Spanned for ast::LifetimeDef { + fn span(&self) -> Span { + let hi = if self.bounds.is_empty() { + self.lifetime.span.hi() + } else { + self.bounds[self.bounds.len() - 1].span.hi() + }; + mk_sp(self.lifetime.span.lo(), hi) + } +} + +impl Spanned for MacroArg { + fn span(&self) -> Span { + match *self { + MacroArg::Expr(ref expr) => expr.span(), + MacroArg::Ty(ref ty) => ty.span(), + MacroArg::Pat(ref pat) => pat.span(), + } + } +} diff --git a/src/string.rs b/src/string.rs new file mode 100644 index 00000000000..8a6b0e685c4 --- /dev/null +++ b/src/string.rs @@ -0,0 +1,162 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format string literals. + +use regex::Regex; +use unicode_segmentation::UnicodeSegmentation; + +use config::Config; +use shape::Shape; +use utils::wrap_str; + +const MIN_STRING: usize = 10; + +pub struct StringFormat<'a> { + pub opener: &'a str, + pub closer: &'a str, + pub line_start: &'a str, + pub line_end: &'a str, + pub shape: Shape, + pub trim_end: bool, + pub config: &'a Config, +} + +impl<'a> StringFormat<'a> { + pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { + StringFormat { + opener: "\"", + closer: "\"", + line_start: " ", + line_end: "\\", + shape, + trim_end: false, + config, + } + } +} + +// FIXME: simplify this! +pub fn rewrite_string<'a>( + orig: &str, + fmt: &StringFormat<'a>, + max_width: Option, +) -> Option { + // Strip line breaks. + let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); + let stripped_str = re.replace_all(orig, "$1"); + + let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); + let shape = fmt.shape; + let indent = shape.indent.to_string_with_newline(fmt.config); + let punctuation = ":,;."; + + // `cur_start` is the position in `orig` of the start of the current line. + let mut cur_start = 0; + let mut result = String::with_capacity( + stripped_str + .len() + .checked_next_power_of_two() + .unwrap_or(usize::max_value()), + ); + result.push_str(fmt.opener); + + let ender_length = fmt.line_end.len(); + // If we cannot put at least a single character per line, the rewrite won't + // succeed. + let mut max_chars = shape + .width + .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + + // Snip a line at a time from `orig` until it is used up. Push the snippet + // onto result. + 'outer: loop { + // `cur_end` will be where we break the line, as an offset into `orig`. + // Initialised to the maximum it could be (which may be beyond `orig`). + let mut cur_end = cur_start + max_chars; + + // We can fit the rest of the string on this line, so we're done. + if cur_end >= graphemes.len() { + let line = &graphemes[cur_start..].join(""); + result.push_str(line); + break 'outer; + } + + // Push cur_end left until we reach whitespace (or the line is too small). + while !graphemes[cur_end - 1].trim().is_empty() { + cur_end -= 1; + if cur_end < cur_start + MIN_STRING { + // We couldn't find whitespace before the string got too small. + // So start again at the max length and look for punctuation. + cur_end = cur_start + max_chars; + while !punctuation.contains(graphemes[cur_end - 1]) { + cur_end -= 1; + + // If we can't break at whitespace or punctuation, grow the string instead. + if cur_end < cur_start + MIN_STRING { + cur_end = cur_start + max_chars; + while !(punctuation.contains(graphemes[cur_end - 1]) + || graphemes[cur_end - 1].trim().is_empty()) + { + if cur_end >= graphemes.len() { + let line = &graphemes[cur_start..].join(""); + result.push_str(line); + break 'outer; + } + cur_end += 1; + } + break; + } + } + break; + } + } + // Make sure there is no whitespace to the right of the break. + while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { + cur_end += 1; + } + + // Make the current line and add it on to result. + let raw_line = graphemes[cur_start..cur_end].join(""); + let line = if fmt.trim_end { + raw_line.trim() + } else { + raw_line.as_str() + }; + + result.push_str(line); + result.push_str(fmt.line_end); + result.push_str(&indent); + result.push_str(fmt.line_start); + + // The next line starts where the current line ends. + cur_start = cur_end; + + if let Some(new_max_chars) = max_width { + max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + } + } + + result.push_str(fmt.closer); + wrap_str(result, fmt.config.max_width(), fmt.shape) +} + +#[cfg(test)] +mod test { + use super::{rewrite_string, StringFormat}; + use shape::{Indent, Shape}; + + #[test] + fn issue343() { + let config = Default::default(); + let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); + rewrite_string("eq_", &fmt, None); + } +} diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 00000000000..7f96a2299a3 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,820 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::iter::ExactSizeIterator; +use std::ops::Deref; + +use config::lists::*; +use syntax::ast::{self, FunctionRetTy, Mutability}; +use syntax::codemap::{self, BytePos, Span}; +use syntax::symbol::keywords; + +use codemap::SpanUtils; +use config::{IndentStyle, TypeDensity}; +use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; +use items::{format_generics_item_list, generics_shape_from_config}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use macros::{rewrite_macro, MacroPosition}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, + last_line_width, mk_sp}; + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum PathContext { + Expr, + Type, + Import, +} + +// Does not wrap on simple segments. +pub fn rewrite_path( + context: &RewriteContext, + path_context: PathContext, + qself: Option<&ast::QSelf>, + path: &ast::Path, + shape: Shape, +) -> Option { + let skip_count = qself.map_or(0, |x| x.position); + + let mut result = if path.is_global() && qself.is_none() && path_context != PathContext::Import { + "::".to_owned() + } else { + String::new() + }; + + let mut span_lo = path.span.lo(); + + if let Some(qself) = qself { + result.push('<'); + if context.config.spaces_within_parens_and_brackets() { + result.push_str(" ") + } + + let fmt_ty = qself.ty.rewrite(context, shape)?; + result.push_str(&fmt_ty); + + if skip_count > 0 { + result.push_str(" as "); + if path.is_global() && path_context != PathContext::Import { + result.push_str("::"); + } + + // 3 = ">::".len() + let shape = shape.sub_width(3)?; + + result = rewrite_path_segments( + PathContext::Type, + result, + path.segments.iter().take(skip_count), + span_lo, + path.span.hi(), + context, + shape, + )?; + } + + if context.config.spaces_within_parens_and_brackets() { + result.push_str(" ") + } + + result.push_str(">::"); + span_lo = qself.ty.span.hi() + BytePos(1); + } + + rewrite_path_segments( + path_context, + result, + path.segments.iter().skip(skip_count), + span_lo, + path.span.hi(), + context, + shape, + ) +} + +fn rewrite_path_segments<'a, I>( + path_context: PathContext, + mut buffer: String, + iter: I, + mut span_lo: BytePos, + span_hi: BytePos, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: Iterator, +{ + let mut first = true; + let shape = shape.visual_indent(0); + + for segment in iter { + // Indicates a global path, shouldn't be rendered. + if segment.identifier.name == keywords::CrateRoot.name() { + continue; + } + if first { + first = false; + } else { + buffer.push_str("::"); + } + + let extra_offset = extra_offset(&buffer, shape); + let new_shape = shape.shrink_left(extra_offset)?; + let segment_string = rewrite_segment( + path_context, + segment, + &mut span_lo, + span_hi, + context, + new_shape, + )?; + + buffer.push_str(&segment_string); + } + + Some(buffer) +} + +#[derive(Debug)] +enum SegmentParam<'a> { + LifeTime(&'a ast::Lifetime), + Type(&'a ast::Ty), + Binding(&'a ast::TypeBinding), +} + +impl<'a> SegmentParam<'a> { + fn get_span(&self) -> Span { + match *self { + SegmentParam::LifeTime(lt) => lt.span, + SegmentParam::Type(ty) => ty.span, + SegmentParam::Binding(binding) => binding.span, + } + } +} + +impl<'a> Rewrite for SegmentParam<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), + SegmentParam::Type(ty) => ty.rewrite(context, shape), + SegmentParam::Binding(binding) => { + let mut result = match context.config.type_punctuation_density() { + TypeDensity::Wide => format!("{} = ", binding.ident), + TypeDensity::Compressed => format!("{}=", binding.ident), + }; + let budget = shape.width.checked_sub(result.len())?; + let rewrite = binding + .ty + .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; + result.push_str(&rewrite); + Some(result) + } + } + } +} + +// Formats a path segment. There are some hacks involved to correctly determine +// the segment's associated span since it's not part of the AST. +// +// The span_lo is assumed to be greater than the end of any previous segment's +// parameters and lesser or equal than the start of current segment. +// +// span_hi is assumed equal to the end of the entire path. +// +// When the segment contains a positive number of parameters, we update span_lo +// so that invariants described above will hold for the next segment. +fn rewrite_segment( + path_context: PathContext, + segment: &ast::PathSegment, + span_lo: &mut BytePos, + span_hi: BytePos, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut result = String::with_capacity(128); + result.push_str(&segment.identifier.name.as_str()); + + let ident_len = result.len(); + let shape = shape.shrink_left(ident_len)?; + + if let Some(ref params) = segment.parameters { + match **params { + ast::PathParameters::AngleBracketed(ref data) + if !data.lifetimes.is_empty() || !data.types.is_empty() + || !data.bindings.is_empty() => + { + let param_list = data.lifetimes + .iter() + .map(SegmentParam::LifeTime) + .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .collect::>(); + + let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1); + let list_lo = context + .snippet_provider + .span_after(mk_sp(*span_lo, span_hi), "<"); + let separator = if path_context == PathContext::Expr { + "::" + } else { + "" + }; + result.push_str(separator); + + let generics_shape = + generics_shape_from_config(context.config, shape, separator.len())?; + let one_line_width = shape.width.checked_sub(separator.len() + 2)?; + let items = itemize_list( + context.snippet_provider, + param_list.into_iter(), + ">", + ",", + |param| param.get_span().lo(), + |param| param.get_span().hi(), + |seg| seg.rewrite(context, generics_shape), + list_lo, + span_hi, + false, + ); + let generics_str = + format_generics_item_list(context, items, generics_shape, one_line_width)?; + + // Update position of last bracket. + *span_lo = next_span_lo; + + result.push_str(&generics_str) + } + ast::PathParameters::Parenthesized(ref data) => { + let output = match data.output { + Some(ref ty) => FunctionRetTy::Ty(ty.clone()), + None => FunctionRetTy::Default(codemap::DUMMY_SP), + }; + result.push_str(&format_function_type( + data.inputs.iter().map(|x| &**x), + &output, + false, + data.span, + context, + shape, + )?); + } + _ => (), + } + } + + Some(result) +} + +fn format_function_type<'a, I>( + inputs: I, + output: &FunctionRetTy, + variadic: bool, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, + ::Item: Deref, + ::Target: Rewrite + Spanned + 'a, +{ + // Code for handling variadics is somewhat duplicated for items, but they + // are different enough to need some serious refactoring to share code. + enum ArgumentKind + where + T: Deref, + ::Target: Rewrite + Spanned, + { + Regular(Box), + Variadic(BytePos), + } + + let variadic_arg = if variadic { + let variadic_start = context.snippet_provider.span_before(span, "..."); + Some(ArgumentKind::Variadic(variadic_start)) + } else { + None + }; + + // 2 for () + let budget = shape.width.checked_sub(2)?; + // 1 for ( + let offset = match context.config.indent_style() { + IndentStyle::Block => { + shape + .block() + .block_indent(context.config.tab_spaces()) + .indent + } + IndentStyle::Visual => shape.indent + 1, + }; + let list_shape = Shape::legacy(budget, offset); + let list_lo = context.snippet_provider.span_after(span, "("); + let items = itemize_list( + context.snippet_provider, + // FIXME Would be nice to avoid this allocation, + // but I couldn't get the types to work out. + inputs + .map(|i| ArgumentKind::Regular(Box::new(i))) + .chain(variadic_arg), + ")", + ",", + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().lo(), + ArgumentKind::Variadic(start) => start, + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.span().hi(), + ArgumentKind::Variadic(start) => start + BytePos(3), + }, + |arg| match *arg { + ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), + ArgumentKind::Variadic(_) => Some("...".to_owned()), + }, + list_lo, + span.hi(), + false, + ); + + let item_vec: Vec<_> = items.collect(); + + let tactic = definitive_tactic( + &*item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + budget, + ); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if !context.use_block_indent() || variadic { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape: list_shape, + ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), + preserve_newline: true, + config: context.config, + }; + + let list_str = write_list(&item_vec, &fmt)?; + + let ty_shape = match context.config.indent_style() { + // 4 = " -> " + IndentStyle::Block => shape.offset_left(4)?, + IndentStyle::Visual => shape.block_left(4)?, + }; + let output = match *output { + FunctionRetTy::Ty(ref ty) => { + let type_str = ty.rewrite(context, ty_shape)?; + format!(" -> {}", type_str) + } + FunctionRetTy::Default(..) => String::new(), + }; + + let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n'); + let args = wrap_args_with_parens( + context, + &list_str, + extendable, + shape.sub_width(first_line_width(&output))?, + Shape::indented(offset, context.config), + ); + if last_line_width(&args) + first_line_width(&output) <= shape.width { + Some(format!("{}{}", args, output)) + } else { + Some(format!( + "{}\n{}{}", + args, + offset.to_string(context.config), + output.trim_left() + )) + } +} + +fn type_bound_colon(context: &RewriteContext) -> &'static str { + colon_spaces( + context.config.space_before_colon(), + context.config.space_after_colon(), + ) +} + +impl Rewrite for ast::WherePredicate { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + // TODO: dead spans? + let result = match *self { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + ref bound_generic_params, + ref bounded_ty, + ref bounds, + .. + }) => { + let type_str = bounded_ty.rewrite(context, shape)?; + + let colon = type_bound_colon(context); + + if let Some(lifetime_str) = + rewrite_lifetime_param(context, shape, bound_generic_params) + { + // 6 = "for<> ".len() + let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; + let ty_shape = shape.offset_left(used_width)?; + let bounds = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect::>>()?; + let bounds_str = join_bounds(context, ty_shape, &bounds); + + if context.config.spaces_within_parens_and_brackets() + && !lifetime_str.is_empty() + { + format!( + "for< {} > {}{}{}", + lifetime_str, type_str, colon, bounds_str + ) + } else { + format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) + } + } else { + let used_width = type_str.len() + colon.len(); + let ty_shape = match context.config.indent_style() { + IndentStyle::Visual => shape.block_left(used_width)?, + IndentStyle::Block => shape, + }; + let bounds = bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) + .collect::>>()?; + let overhead = type_str.len() + colon.len(); + let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); + + format!("{}{}{}", type_str, colon, bounds_str) + } + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + ref lifetime, + ref bounds, + .. + }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + ref lhs_ty, + ref rhs_ty, + .. + }) => { + let lhs_ty_str = lhs_ty.rewrite(context, shape)?; + // 3 = " = ".len() + let used_width = 3 + lhs_ty_str.len(); + let budget = shape.width.checked_sub(used_width)?; + let rhs_ty_str = + rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; + format!("{} = {}", lhs_ty_str, rhs_ty_str) + } + }; + + Some(result) + } +} + +impl Rewrite for ast::LifetimeDef { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) + } +} + +fn rewrite_bounded_lifetime<'b, I>( + lt: &ast::Lifetime, + bounds: I, + context: &RewriteContext, + shape: Shape, +) -> Option +where + I: ExactSizeIterator, +{ + let result = lt.rewrite(context, shape)?; + + if bounds.len() == 0 { + Some(result) + } else { + let appendix = bounds + .into_iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; + let colon = type_bound_colon(context); + let overhead = last_line_width(&result) + colon.len(); + let result = format!( + "{}{}{}", + result, + colon, + join_bounds(context, shape.sub_width(overhead)?, &appendix) + ); + Some(result) + } +} + +impl Rewrite for ast::TyParamBound { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match *self { + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { + tref.rewrite(context, shape) + } + ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => Some( + format!("?{}", tref.rewrite(context, shape.offset_left(1)?)?), + ), + ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), + } + } +} + +impl Rewrite for ast::Lifetime { + fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { + Some(self.ident.to_string()) + } +} + +impl Rewrite for ast::TyParamBounds { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let strs = self.iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; + Some(join_bounds(context, shape, &strs)) + } +} + +impl Rewrite for ast::TyParam { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let mut result = String::with_capacity(128); + // FIXME: If there are more than one attributes, this will force multiline. + match self.attrs.rewrite(context, shape) { + Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), + _ => (), + } + result.push_str(&self.ident.to_string()); + if !self.bounds.is_empty() { + result.push_str(type_bound_colon(context)); + let strs = self.bounds + .iter() + .map(|ty_bound| ty_bound.rewrite(context, shape)) + .collect::>>()?; + result.push_str(&join_bounds(context, shape, &strs)); + } + if let Some(ref def) = self.default { + let eq_str = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "=", + TypeDensity::Wide => " = ", + }; + result.push_str(eq_str); + let budget = shape.width.checked_sub(result.len())?; + let rewrite = def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; + result.push_str(&rewrite); + } + + Some(result) + } +} + +impl Rewrite for ast::PolyTraitRef { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + if let Some(lifetime_str) = + rewrite_lifetime_param(context, shape, &self.bound_generic_params) + { + // 6 is "for<> ".len() + let extra_offset = lifetime_str.len() + 6; + let path_str = self.trait_ref + .rewrite(context, shape.offset_left(extra_offset)?)?; + + Some( + if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { + format!("for< {} > {}", lifetime_str, path_str) + } else { + format!("for<{}> {}", lifetime_str, path_str) + }, + ) + } else { + self.trait_ref.rewrite(context, shape) + } + } +} + +impl Rewrite for ast::TraitRef { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_path(context, PathContext::Type, None, &self.path, shape) + } +} + +impl Rewrite for ast::Ty { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self.node { + ast::TyKind::TraitObject(ref bounds, ..) => bounds.rewrite(context, shape), + ast::TyKind::Ptr(ref mt) => { + let prefix = match mt.mutbl { + Mutability::Mutable => "*mut ", + Mutability::Immutable => "*const ", + }; + + rewrite_unary_prefix(context, prefix, &*mt.ty, shape) + } + ast::TyKind::Rptr(ref lifetime, ref mt) => { + let mut_str = format_mutability(mt.mutbl); + let mut_len = mut_str.len(); + Some(match *lifetime { + Some(ref lifetime) => { + let lt_budget = shape.width.checked_sub(2 + mut_len)?; + let lt_str = lifetime.rewrite( + context, + Shape::legacy(lt_budget, shape.indent + 2 + mut_len), + )?; + let lt_len = lt_str.len(); + let budget = shape.width.checked_sub(2 + mut_len + lt_len)?; + format!( + "&{} {}{}", + lt_str, + mut_str, + mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len) + )? + ) + } + None => { + let budget = shape.width.checked_sub(1 + mut_len)?; + format!( + "&{}{}", + mut_str, + mt.ty.rewrite( + context, + Shape::legacy(budget, shape.indent + 1 + mut_len) + )? + ) + } + }) + } + // FIXME: we drop any comments here, even though it's a silly place to put + // comments. + ast::TyKind::Paren(ref ty) => { + let budget = shape.width.checked_sub(2)?; + ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) + .map(|ty_str| { + if context.config.spaces_within_parens_and_brackets() { + format!("( {} )", ty_str) + } else { + format!("({})", ty_str) + } + }) + } + ast::TyKind::Slice(ref ty) => { + let budget = if context.config.spaces_within_parens_and_brackets() { + shape.width.checked_sub(4)? + } else { + shape.width.checked_sub(2)? + }; + ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) + .map(|ty_str| { + if context.config.spaces_within_parens_and_brackets() { + format!("[ {} ]", ty_str) + } else { + format!("[{}]", ty_str) + } + }) + } + ast::TyKind::Tup(ref items) => rewrite_tuple( + context, + &::utils::ptr_vec_to_ref_vec(items), + self.span, + shape, + ), + ast::TyKind::Path(ref q_self, ref path) => { + rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) + } + ast::TyKind::Array(ref ty, ref repeats) => { + let use_spaces = context.config.spaces_within_parens_and_brackets(); + let lbr = if use_spaces { "[ " } else { "[" }; + let rbr = if use_spaces { " ]" } else { "]" }; + rewrite_pair( + &**ty, + &**repeats, + PairParts::new(lbr, "; ", rbr), + context, + shape, + SeparatorPlace::Back, + ) + } + ast::TyKind::Infer => { + if shape.width >= 1 { + Some("_".to_owned()) + } else { + None + } + } + ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), + ast::TyKind::Never => Some(String::from("!")), + ast::TyKind::Mac(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + } + ast::TyKind::ImplicitSelf => Some(String::from("")), + ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) + .map(|it_str| format!("impl {}", it_str)), + ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), + } + } +} + +fn rewrite_bare_fn( + bare_fn: &ast::BareFnTy, + span: Span, + context: &RewriteContext, + shape: Shape, +) -> Option { + let mut result = String::with_capacity(128); + + if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params) + { + result.push_str("for<"); + // 6 = "for<> ".len(), 4 = "for<". + // This doesn't work out so nicely for mutliline situation with lots of + // rightward drift. If that is a problem, we could use the list stuff. + result.push_str(lifetime_str); + result.push_str("> "); + } + + result.push_str(::utils::format_unsafety(bare_fn.unsafety)); + + result.push_str(&format_abi( + bare_fn.abi, + context.config.force_explicit_abi(), + false, + )); + + result.push_str("fn"); + + let func_ty_shape = shape.offset_left(result.len())?; + + let rewrite = format_function_type( + bare_fn.decl.inputs.iter(), + &bare_fn.decl.output, + bare_fn.decl.variadic, + span, + context, + func_ty_shape, + )?; + + result.push_str(&rewrite); + + Some(result) +} + +pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { + // Try to join types in a single line + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => "+", + TypeDensity::Wide => " + ", + }; + let result = type_strs.join(joiner); + if result.contains('\n') || result.len() > shape.width { + let joiner_indent = shape.indent.block_indent(context.config); + let joiner = format!("{}+ ", joiner_indent.to_string_with_newline(context.config)); + type_strs.join(&joiner) + } else { + result + } +} + +pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { + match ty.node { + ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, + ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { + can_be_overflowed_type(context, &*mutty.ty, len) + } + _ => false, + } +} + +/// Returns `None` if there is no `LifetimeDef` in the given generic parameters. +fn rewrite_lifetime_param( + context: &RewriteContext, + shape: Shape, + generic_params: &[ast::GenericParam], +) -> Option { + let result = generic_params + .iter() + .filter(|p| p.is_lifetime_param()) + .map(|lt| lt.rewrite(context, shape)) + .collect::>>()? + .join(", "); + if result.is_empty() { + None + } else { + Some(result) + } +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 00000000000..20b30089d70 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,405 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::borrow::Cow; + +use syntax::{abi, ptr}; +use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, + NestedMetaItemKind, Path, Visibility}; +use syntax::codemap::{BytePos, Span, NO_EXPANSION}; + +use config::Color; +use rewrite::RewriteContext; +use shape::Shape; + +// When we get scoped annotations, we should have rustfmt::skip. +const SKIP_ANNOTATION: &str = "rustfmt_skip"; + +// Computes the length of a string's last line, minus offset. +pub fn extra_offset(text: &str, shape: Shape) -> usize { + match text.rfind('\n') { + // 1 for newline character + Some(idx) => text.len() + .checked_sub(idx + 1 + shape.used_width()) + .unwrap_or(0), + None => text.len(), + } +} + +// Uses Cow to avoid allocating in the common cases. +pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { + match *vis { + Visibility::Public => Cow::from("pub "), + Visibility::Inherited => Cow::from(""), + Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "), + Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "), + Visibility::Restricted { ref path, .. } => { + let Path { ref segments, .. } = **path; + let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); + if path.is_global() { + segments_iter + .next() + .expect("Non-global path in pub(restricted)?"); + } + let is_keyword = |s: &str| s == "self" || s == "super"; + let path = segments_iter.collect::>().join("::"); + let in_str = if is_keyword(&path) { "" } else { "in " }; + + Cow::from(format!("pub({}{}) ", in_str, path)) + } + } +} + +#[inline] +pub fn format_constness(constness: ast::Constness) -> &'static str { + match constness { + ast::Constness::Const => "const ", + ast::Constness::NotConst => "", + } +} + +#[inline] +pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { + match defaultness { + ast::Defaultness::Default => "default ", + ast::Defaultness::Final => "", + } +} + +#[inline] +pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { + match unsafety { + ast::Unsafety::Unsafe => "unsafe ", + ast::Unsafety::Normal => "", + } +} + +#[inline] +pub fn format_mutability(mutability: ast::Mutability) -> &'static str { + match mutability { + ast::Mutability::Mutable => "mut ", + ast::Mutability::Immutable => "", + } +} + +#[inline] +pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { + if abi == abi::Abi::Rust && !is_mod { + Cow::from("") + } else if abi == abi::Abi::C && !explicit_abi { + Cow::from("extern ") + } else { + Cow::from(format!("extern {} ", abi)) + } +} + +#[inline] +// Transform `Vec>` into `Vec<&T>` +pub fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { + vec.iter().map(|x| &**x).collect::>() +} + +#[inline] +pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { + attrs + .iter() + .filter(|a| a.style == style) + .cloned() + .collect::>() +} + +#[inline] +pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Inner) +} + +#[inline] +pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { + filter_attributes(attrs, ast::AttrStyle::Outer) +} + +#[inline] +pub fn last_line_contains_single_line_comment(s: &str) -> bool { + s.lines().last().map_or(false, |l| l.contains("//")) +} + +#[inline] +pub fn is_attributes_extendable(attrs_str: &str) -> bool { + !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) +} + +// The width of the first line in s. +#[inline] +pub fn first_line_width(s: &str) -> usize { + match s.find('\n') { + Some(n) => n, + None => s.len(), + } +} + +// The width of the last line in s. +#[inline] +pub fn last_line_width(s: &str) -> usize { + match s.rfind('\n') { + Some(n) => s.len() - n - 1, + None => s.len(), + } +} + +// The total used width of the last line. +#[inline] +pub fn last_line_used_width(s: &str, offset: usize) -> usize { + if s.contains('\n') { + last_line_width(s) + } else { + offset + s.len() + } +} + +#[inline] +pub fn trimmed_last_line_width(s: &str) -> usize { + match s.rfind('\n') { + Some(n) => s[(n + 1)..].trim().len(), + None => s.trim().len(), + } +} + +#[inline] +pub fn last_line_extendable(s: &str) -> bool { + if s.ends_with("\"#") { + return true; + } + for c in s.chars().rev() { + match c { + '(' | ')' | ']' | '}' | '?' | '>' => continue, + '\n' => break, + _ if c.is_whitespace() => continue, + _ => return false, + } + } + true +} + +#[inline] +fn is_skip(meta_item: &MetaItem) -> bool { + match meta_item.node { + MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION, + MetaItemKind::List(ref l) => { + meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + } + _ => false, + } +} + +#[inline] +fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { + match meta_item.node { + NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi), + NestedMetaItemKind::Literal(_) => false, + } +} + +#[inline] +pub fn contains_skip(attrs: &[Attribute]) -> bool { + attrs + .iter() + .any(|a| a.meta().map_or(false, |a| is_skip(&a))) +} + +#[inline] +pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { + context.config.trailing_semicolon() + } + _ => false, + } +} + +#[inline] +pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::StmtKind::Semi(ref expr) => match expr.node { + ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) => false, + ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { + context.config.trailing_semicolon() + } + _ => true, + }, + ast::StmtKind::Expr(..) => false, + _ => true, + } +} + +#[inline] +pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { + match stmt.node { + ast::StmtKind::Expr(ref expr) => Some(expr), + _ => None, + } +} + +#[inline] +pub fn count_newlines(input: &str) -> usize { + input.chars().filter(|&c| c == '\n').count() +} + +macro_rules! msg { + ($($arg:tt)*) => ( + match writeln!(&mut ::std::io::stderr(), $($arg)* ) { + Ok(_) => {}, + Err(x) => panic!("Unable to write to stderr: {}", x), + } + ) +} + +// For format_missing and last_pos, need to use the source callsite (if applicable). +// Required as generated code spans aren't guaranteed to follow on from the last span. +macro_rules! source { + ($this: ident, $sp: expr) => { + $sp.source_callsite() + }; +} + +pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { + Span::new(lo, hi, NO_EXPANSION) +} + +// Return true if the given span does not intersect with file lines. +macro_rules! out_of_file_lines_range { + ($self: ident, $span: expr) => { + !$self.config.file_lines().is_all() + && !$self + .config + .file_lines() + .intersects(&$self.codemap.lookup_line_range($span)) + }; +} + +macro_rules! skip_out_of_file_lines_range { + ($self: ident, $span: expr) => { + if out_of_file_lines_range!($self, $span) { + return None; + } + }; +} + +macro_rules! skip_out_of_file_lines_range_visitor { + ($self: ident, $span: expr) => { + if out_of_file_lines_range!($self, $span) { + $self.push_rewrite($span, None); + return; + } + }; +} + +// Wraps String in an Option. Returns Some when the string adheres to the +// Rewrite constraints defined for the Rewrite trait and else otherwise. +pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { + if is_valid_str(&s, max_width, shape) { + Some(s) + } else { + None + } +} + +fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { + if !snippet.is_empty() { + // First line must fits with `shape.width`. + if first_line_width(snippet) > shape.width { + return false; + } + // If the snippet does not include newline, we are done. + if first_line_width(snippet) == snippet.len() { + return true; + } + // The other lines must fit within the maximum width. + if snippet.lines().skip(1).any(|line| line.len() > max_width) { + return false; + } + // A special check for the last line, since the caller may + // place trailing characters on this line. + if last_line_width(snippet) > shape.used_width() + shape.width { + return false; + } + } + true +} + +#[inline] +pub fn colon_spaces(before: bool, after: bool) -> &'static str { + match (before, after) { + (true, true) => " : ", + (true, false) => " :", + (false, true) => ": ", + (false, false) => ":", + } +} + +#[inline] +pub fn paren_overhead(context: &RewriteContext) -> usize { + if context.config.spaces_within_parens_and_brackets() { + 4 + } else { + 2 + } +} + +pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { + match e.node { + ast::ExprKind::InPlace(ref e, _) + | ast::ExprKind::Call(ref e, _) + | ast::ExprKind::Binary(_, ref e, _) + | ast::ExprKind::Cast(ref e, _) + | ast::ExprKind::Type(ref e, _) + | ast::ExprKind::Assign(ref e, _) + | ast::ExprKind::AssignOp(_, ref e, _) + | ast::ExprKind::Field(ref e, _) + | ast::ExprKind::TupField(ref e, _) + | ast::ExprKind::Index(ref e, _) + | ast::ExprKind::Range(Some(ref e), _, _) + | ast::ExprKind::Try(ref e) => left_most_sub_expr(e), + _ => e, + } +} + +// isatty shamelessly adapted from cargo. +#[cfg(unix)] +pub fn isatty() -> bool { + extern crate libc; + + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +pub fn isatty() -> bool { + extern crate kernel32; + extern crate winapi; + + unsafe { + let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); + let mut out = 0; + kernel32::GetConsoleMode(handle, &mut out) != 0 + } +} + +pub fn use_colored_tty(color: Color) -> bool { + match color { + Color::Always => true, + Color::Never => false, + Color::Auto => isatty(), + } +} + +pub fn starts_with_newline(s: &str) -> bool { + s.starts_with('\n') || s.starts_with("\r\n") +} diff --git a/src/vertical.rs b/src/vertical.rs new file mode 100644 index 00000000000..887fefb2272 --- /dev/null +++ b/src/vertical.rs @@ -0,0 +1,290 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Format with vertical alignment. + +use std::cmp; + +use config::lists::*; +use syntax::ast; +use syntax::codemap::{BytePos, Span}; + +use codemap::SpanUtils; +use comment::{combine_strs_with_missing_comments, contains_comment}; +use expr::rewrite_field; +use items::{rewrite_struct_field, rewrite_struct_field_prefix}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use utils::{contains_skip, is_attributes_extendable, mk_sp}; + +pub trait AlignedItem { + fn skip(&self) -> bool; + fn get_span(&self) -> Span; + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option; + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option; +} + +impl AlignedItem for ast::StructField { + fn skip(&self) -> bool { + contains_skip(&self.attrs) + } + + fn get_span(&self) -> Span { + self.span() + } + + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = self.attrs.rewrite(context, shape)?; + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo(), self.span.lo()) + } else { + mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) + }; + let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str); + rewrite_struct_field_prefix(context, self).and_then(|field_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &field_str, + missing_span, + shape, + attrs_extendable, + ) + }) + } + + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option { + rewrite_struct_field(context, self, shape, prefix_max_width) + } +} + +impl AlignedItem for ast::Field { + fn skip(&self) -> bool { + contains_skip(&self.attrs) + } + + fn get_span(&self) -> Span { + self.span() + } + + fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + let attrs_str = self.attrs.rewrite(context, shape)?; + let name = &self.ident.node.to_string(); + let missing_span = if self.attrs.is_empty() { + mk_sp(self.span.lo(), self.span.lo()) + } else { + mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo()) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + name, + missing_span, + shape, + is_attributes_extendable(&attrs_str), + ) + } + + fn rewrite_aligned_item( + &self, + context: &RewriteContext, + shape: Shape, + prefix_max_width: usize, + ) -> Option { + rewrite_field(context, self, shape, prefix_max_width) + } +} + +pub fn rewrite_with_alignment( + fields: &[T], + context: &RewriteContext, + shape: Shape, + span: Span, + one_line_width: usize, +) -> Option { + let (spaces, group_index) = if context.config.struct_field_align_threshold() > 0 { + group_aligned_items(context, fields) + } else { + ("", fields.len() - 1) + }; + let init = &fields[0..group_index + 1]; + let rest = &fields[group_index + 1..]; + let init_last_pos = if rest.is_empty() { + span.hi() + } else { + // Decide whether the missing comments should stick to init or rest. + let init_hi = init[init.len() - 1].get_span().hi(); + let rest_lo = rest[0].get_span().lo(); + let missing_span = mk_sp(init_hi, rest_lo); + let missing_span = mk_sp( + context.snippet_provider.span_after(missing_span, ","), + missing_span.hi(), + ); + + let snippet = context.snippet(missing_span); + if snippet.trim_left().starts_with("//") { + let offset = snippet.lines().next().map_or(0, |l| l.len()); + // 2 = "," + "\n" + init_hi + BytePos(offset as u32 + 2) + } else if snippet.trim_left().starts_with("/*") { + let comment_lines = snippet + .lines() + .position(|line| line.trim_right().ends_with("*/")) + .unwrap_or(0); + + let offset = snippet + .lines() + .take(comment_lines + 1) + .collect::>() + .join("\n") + .len(); + + init_hi + BytePos(offset as u32 + 2) + } else { + missing_span.lo() + } + }; + let init_span = mk_sp(span.lo(), init_last_pos); + let one_line_width = if rest.is_empty() { one_line_width } else { 0 }; + let result = + rewrite_aligned_items_inner(context, init, init_span, shape.indent, one_line_width)?; + if rest.is_empty() { + Some(result + spaces) + } else { + let rest_span = mk_sp(init_last_pos, span.hi()); + let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; + Some( + result + spaces + "\n" + + &shape + .indent + .block_indent(context.config) + .to_string(context.config) + &rest_str, + ) + } +} + +fn struct_field_prefix_max_min_width( + context: &RewriteContext, + fields: &[T], + shape: Shape, +) -> (usize, usize) { + fields + .iter() + .map(|field| { + field.rewrite_prefix(context, shape).and_then(|field_str| { + if field_str.contains('\n') { + None + } else { + Some(field_str.len()) + } + }) + }) + .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { + (Some((max_len, min_len)), Some(len)) => { + Some((cmp::max(max_len, len), cmp::min(min_len, len))) + } + _ => None, + }) + .unwrap_or((0, 0)) +} + +fn rewrite_aligned_items_inner( + context: &RewriteContext, + fields: &[T], + span: Span, + offset: Indent, + one_line_width: usize, +) -> Option { + let item_indent = offset.block_indent(context.config); + // 1 = "," + let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; + let (mut field_prefix_max_width, field_prefix_min_width) = + struct_field_prefix_max_min_width(context, fields, item_shape); + let max_diff = field_prefix_max_width + .checked_sub(field_prefix_min_width) + .unwrap_or(0); + if max_diff > context.config.struct_field_align_threshold() { + field_prefix_max_width = 0; + } + + let items = itemize_list( + context.snippet_provider, + fields.iter(), + "}", + ",", + |field| field.get_span().lo(), + |field| field.get_span().hi(), + |field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), + span.lo(), + span.hi(), + false, + ).collect::>(); + + let tactic = definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::Comma, + one_line_width, + ); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: context.config.trailing_comma(), + separator_place: SeparatorPlace::Back, + shape: item_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + write_list(&items, &fmt) +} + +fn group_aligned_items( + context: &RewriteContext, + fields: &[T], +) -> (&'static str, usize) { + let mut index = 0; + for i in 0..fields.len() - 1 { + if fields[i].skip() { + return ("", index); + } + // See if there are comments or empty lines between fields. + let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo()); + let snippet = context + .snippet(span) + .lines() + .skip(1) + .collect::>() + .join("\n"); + let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) { + "\n" + } else { + "" + }; + if contains_comment(&snippet) || snippet.lines().count() > 1 { + return (spacings, index); + } + index += 1; + } + ("", index) +} diff --git a/src/visitor.rs b/src/visitor.rs new file mode 100644 index 00000000000..35102f58609 --- /dev/null +++ b/src/visitor.rs @@ -0,0 +1,700 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax::{ast, visit}; +use syntax::attr::HasAttrs; +use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; +use syntax::parse::ParseSess; + +use attr::*; +use codemap::{LineRangeUtils, SpanUtils}; +use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; +use config::{BraceStyle, Config}; +use items::{format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, + rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, + rewrite_type_alias, FnSig, StaticParts, StructParts}; +use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; +use rewrite::{Rewrite, RewriteContext}; +use shape::{Indent, Shape}; +use spanned::Spanned; +use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; + +/// Creates a string slice corresponding to the specified span. +pub struct SnippetProvider<'a> { + /// A pointer to the content of the file we are formatting. + big_snippet: &'a str, + /// A position of the start of `big_snippet`, used as an offset. + start_pos: usize, +} + +impl<'a> SnippetProvider<'a> { + pub fn span_to_snippet(&self, span: Span) -> Option<&str> { + let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; + let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; + Some(&self.big_snippet[start_index..end_index]) + } + + pub fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { + let start_pos = start_pos.to_usize(); + SnippetProvider { + big_snippet, + start_pos, + } + } +} + +pub struct FmtVisitor<'a> { + pub parse_session: &'a ParseSess, + pub codemap: &'a CodeMap, + pub buffer: String, + pub last_pos: BytePos, + // FIXME: use an RAII util or closure for indenting + pub block_indent: Indent, + pub config: &'a Config, + pub is_if_else_block: bool, + pub snippet_provider: &'a SnippetProvider<'a>, + pub line_number: usize, + pub skipped_range: Vec<(usize, usize)>, +} + +impl<'b, 'a: 'b> FmtVisitor<'a> { + pub fn shape(&self) -> Shape { + Shape::indented(self.block_indent, self.config) + } + + fn visit_stmt(&mut self, stmt: &ast::Stmt) { + debug!( + "visit_stmt: {:?} {:?}", + self.codemap.lookup_char_pos(stmt.span.lo()), + self.codemap.lookup_char_pos(stmt.span.hi()) + ); + + match stmt.node { + ast::StmtKind::Item(ref item) => { + self.visit_item(item); + } + ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + if contains_skip(get_attrs_from_stmt(stmt)) { + self.push_skipped_with_span(stmt.span()); + } else { + let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + self.push_rewrite(stmt.span(), rewrite) + } + } + ast::StmtKind::Mac(ref mac) => { + let (ref mac, _macro_style, ref attrs) = **mac; + if self.visit_attrs(attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(stmt.span()); + } else { + self.visit_mac(mac, None, MacroPosition::Statement); + } + self.format_missing(stmt.span.hi()); + } + } + } + + pub fn visit_block( + &mut self, + b: &ast::Block, + inner_attrs: Option<&[ast::Attribute]>, + has_braces: bool, + ) { + debug!( + "visit_block: {:?} {:?}", + self.codemap.lookup_char_pos(b.span.lo()), + self.codemap.lookup_char_pos(b.span.hi()) + ); + + // Check if this block has braces. + let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); + + self.last_pos = self.last_pos + brace_compensation; + self.block_indent = self.block_indent.block_indent(self.config); + self.push_str("{"); + + if self.config.remove_blank_lines_at_start_or_end_of_block() { + if let Some(first_stmt) = b.stmts.first() { + let attr_lo = inner_attrs + .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) + .or_else(|| { + // Attributes for an item in a statement position + // do not belong to the statement. (rust-lang/rust#34459) + if let ast::StmtKind::Item(ref item) = first_stmt.node { + item.attrs.first() + } else { + first_stmt.attrs().first() + }.and_then(|attr| { + // Some stmts can have embedded attributes. + // e.g. `match { #![attr] ... }` + let attr_lo = attr.span.lo(); + if attr_lo < first_stmt.span.lo() { + Some(attr_lo) + } else { + None + } + }) + }); + + let snippet = self.snippet(mk_sp( + self.last_pos, + attr_lo.unwrap_or_else(|| first_stmt.span.lo()), + )); + let len = CommentCodeSlices::new(snippet) + .nth(0) + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal { + s.rfind('\n') + } else { + None + } + }); + if let Some(len) = len { + self.last_pos = self.last_pos + BytePos::from_usize(len); + } + } + } + + // Format inner attributes if available. + let skip_rewrite = if let Some(attrs) = inner_attrs { + self.visit_attrs(attrs, ast::AttrStyle::Inner) + } else { + false + }; + + if skip_rewrite { + self.push_rewrite(b.span, None); + self.close_block(false); + self.last_pos = source!(self, b.span).hi(); + return; + } + + self.walk_block_stmts(b); + + if !b.stmts.is_empty() { + if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { + if utils::semicolon_for_expr(&self.get_context(), expr) { + self.push_str(";"); + } + } + } + + let mut remove_len = BytePos(0); + if self.config.remove_blank_lines_at_start_or_end_of_block() { + if let Some(stmt) = b.stmts.last() { + let snippet = self.snippet(mk_sp( + stmt.span.hi(), + source!(self, b.span).hi() - brace_compensation, + )); + let len = CommentCodeSlices::new(snippet) + .last() + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal && s.trim().is_empty() { + Some(s.len()) + } else { + None + } + }); + if let Some(len) = len { + remove_len = BytePos::from_usize(len); + } + } + } + + let unindent_comment = (self.is_if_else_block && !b.stmts.is_empty()) && { + let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; + let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); + snippet.contains("//") || snippet.contains("/*") + }; + // FIXME: we should compress any newlines here to just one + if unindent_comment { + self.block_indent = self.block_indent.block_unindent(self.config); + } + self.format_missing_with_indent( + source!(self, b.span).hi() - brace_compensation - remove_len, + ); + if unindent_comment { + self.block_indent = self.block_indent.block_indent(self.config); + } + self.close_block(unindent_comment); + self.last_pos = source!(self, b.span).hi(); + } + + // FIXME: this is a terrible hack to indent the comments between the last + // item in the block and the closing brace to the block's level. + // The closing brace itself, however, should be indented at a shallower + // level. + fn close_block(&mut self, unindent_comment: bool) { + let total_len = self.buffer.len(); + let chars_too_many = if unindent_comment { + 0 + } else if self.config.hard_tabs() { + 1 + } else { + self.config.tab_spaces() + }; + self.buffer.truncate(total_len - chars_too_many); + self.push_str("}"); + self.block_indent = self.block_indent.block_unindent(self.config); + } + + // Note that this only gets called for function definitions. Required methods + // on traits do not get handled here. + fn visit_fn( + &mut self, + fk: visit::FnKind, + generics: &ast::Generics, + fd: &ast::FnDecl, + s: Span, + defaultness: ast::Defaultness, + inner_attrs: Option<&[ast::Attribute]>, + ) { + let indent = self.block_indent; + let block; + let rewrite = match fk { + visit::FnKind::ItemFn(ident, _, _, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { + block = b; + self.rewrite_fn( + indent, + ident, + &FnSig::from_fn_kind(&fk, generics, fd, defaultness), + mk_sp(s.lo(), b.span.lo()), + b, + ) + } + visit::FnKind::Closure(_) => unreachable!(), + }; + + if let Some(fn_str) = rewrite { + self.format_missing_with_indent(source!(self, s).lo()); + self.push_str(&fn_str); + if let Some(c) = fn_str.chars().last() { + if c == '}' { + self.last_pos = source!(self, block.span).hi(); + return; + } + } + } else { + self.format_missing(source!(self, block.span).lo()); + } + + self.last_pos = source!(self, block.span).lo(); + self.visit_block(block, inner_attrs, true) + } + + pub fn visit_item(&mut self, item: &ast::Item) { + skip_out_of_file_lines_range_visitor!(self, item.span); + + // This is where we bail out if there is a skip attribute. This is only + // complex in the module case. It is complex because the module could be + // in a separate file and there might be attributes in both files, but + // the AST lumps them all together. + let filtered_attrs; + let mut attrs = &item.attrs; + match item.node { + // Module is inline, in this case we treat it like any other item. + _ if !is_mod_decl(item) => { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(item.span()); + return; + } + } + // Module is not inline, but should be skipped. + ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => { + return; + } + // Module is not inline and should not be skipped. We want + // to process only the attributes in the current file. + ast::ItemKind::Mod(..) => { + filtered_attrs = filter_inline_attrs(&item.attrs, item.span()); + // Assert because if we should skip it should be caught by + // the above case. + assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); + attrs = &filtered_attrs; + } + _ => { + if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(item.span()); + return; + } + } + } + + match item.node { + ast::ItemKind::Use(ref tree) => self.format_import(item, tree), + ast::ItemKind::Impl(..) => { + let snippet = self.snippet(item.span); + let where_span_end = snippet + .find_uncommented("{") + .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); + let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::Trait(..) => { + let rw = format_trait(&self.get_context(), item, self.block_indent); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::TraitAlias(ref generics, ref ty_param_bounds) => { + let shape = Shape::indented(self.block_indent, self.config); + let rw = format_trait_alias( + &self.get_context(), + item.ident, + generics, + ty_param_bounds, + shape, + ); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::ExternCrate(_) => { + let rw = rewrite_extern_crate(&self.get_context(), item); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { + self.visit_struct(&StructParts::from_item(item)); + } + ast::ItemKind::Enum(ref def, ref generics) => { + self.format_missing_with_indent(source!(self, item.span).lo()); + self.visit_enum(item.ident, &item.vis, def, generics, item.span); + self.last_pos = source!(self, item.span).hi(); + } + ast::ItemKind::Mod(ref module) => { + let is_inline = !is_mod_decl(item); + self.format_missing_with_indent(source!(self, item.span).lo()); + self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); + } + ast::ItemKind::Mac(ref mac) => { + self.visit_mac(mac, Some(item.ident), MacroPosition::Item); + } + ast::ItemKind::ForeignMod(ref foreign_mod) => { + self.format_missing_with_indent(source!(self, item.span).lo()); + self.format_foreign_mod(foreign_mod, item.span); + } + ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { + self.visit_static(&StaticParts::from_item(item)); + } + ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { + self.visit_fn( + visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), + generics, + decl, + item.span, + ast::Defaultness::Final, + Some(&item.attrs), + ) + } + ast::ItemKind::Ty(ref ty, ref generics) => { + let rewrite = rewrite_type_alias( + &self.get_context(), + self.block_indent, + item.ident, + ty, + generics, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + ast::ItemKind::GlobalAsm(..) => { + let snippet = Some(self.snippet(item.span).to_owned()); + self.push_rewrite(item.span, snippet); + } + ast::ItemKind::MacroDef(ref def) => { + let rewrite = rewrite_macro_def( + &self.get_context(), + self.shape(), + self.block_indent, + def, + item.ident, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + } + } + + pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + skip_out_of_file_lines_range_visitor!(self, ti.span); + + if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(ti.span()); + return; + } + + match ti.node { + ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), + ast::TraitItemKind::Method(ref sig, None) => { + let indent = self.block_indent; + let rewrite = + self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); + self.push_rewrite(ti.span, rewrite); + } + ast::TraitItemKind::Method(ref sig, Some(ref body)) => { + self.visit_fn( + visit::FnKind::Method(ti.ident, sig, None, body), + &ti.generics, + &sig.decl, + ti.span, + ast::Defaultness::Final, + Some(&ti.attrs), + ); + } + ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { + let rewrite = rewrite_associated_type( + ti.ident, + type_default.as_ref(), + Some(type_param_bounds), + &self.get_context(), + self.block_indent, + ); + self.push_rewrite(ti.span, rewrite); + } + ast::TraitItemKind::Macro(ref mac) => { + self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); + } + } + } + + pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + skip_out_of_file_lines_range_visitor!(self, ii.span); + + if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { + self.push_skipped_with_span(ii.span()); + return; + } + + match ii.node { + ast::ImplItemKind::Method(ref sig, ref body) => { + self.visit_fn( + visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), + &ii.generics, + &sig.decl, + ii.span, + ii.defaultness, + Some(&ii.attrs), + ); + } + ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), + ast::ImplItemKind::Type(ref ty) => { + let rewrite = rewrite_associated_impl_type( + ii.ident, + ii.defaultness, + Some(ty), + None, + &self.get_context(), + self.block_indent, + ); + self.push_rewrite(ii.span, rewrite); + } + ast::ImplItemKind::Macro(ref mac) => { + self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); + } + } + } + + fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { + skip_out_of_file_lines_range_visitor!(self, mac.span); + + // 1 = ; + let shape = self.shape().sub_width(1).unwrap(); + let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); + self.push_rewrite(mac.span, rewrite); + } + + pub fn push_str(&mut self, s: &str) { + self.line_number += count_newlines(s); + self.buffer.push_str(s); + } + + #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] + fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { + if let Some(ref s) = rewrite { + self.push_str(s); + } else { + let snippet = self.snippet(span); + self.push_str(snippet); + } + self.last_pos = source!(self, span).hi(); + } + + pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { + self.format_missing_with_indent(source!(self, span).lo()); + self.push_rewrite_inner(span, rewrite); + } + + pub fn push_skipped_with_span(&mut self, span: Span) { + self.format_missing_with_indent(source!(self, span).lo()); + let lo = self.line_number + 1; + self.push_rewrite_inner(span, None); + let hi = self.line_number + 1; + self.skipped_range.push((lo, hi)); + } + + pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { + FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) + } + + pub fn from_codemap( + parse_session: &'a ParseSess, + config: &'a Config, + snippet_provider: &'a SnippetProvider, + ) -> FmtVisitor<'a> { + FmtVisitor { + parse_session, + codemap: parse_session.codemap(), + buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), + last_pos: BytePos(0), + block_indent: Indent::empty(), + config, + is_if_else_block: false, + snippet_provider, + line_number: 0, + skipped_range: vec![], + } + } + + pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { + self.snippet_provider.span_to_snippet(span) + } + + pub fn snippet(&'b self, span: Span) -> &'a str { + self.opt_snippet(span).unwrap() + } + + // Returns true if we should skip the following item. + pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { + if contains_skip(attrs) { + return true; + } + + let attrs: Vec<_> = attrs.iter().filter(|a| a.style == style).cloned().collect(); + if attrs.is_empty() { + return false; + } + + let rewrite = attrs.rewrite(&self.get_context(), self.shape()); + let span = mk_sp(attrs[0].span.lo(), attrs[attrs.len() - 1].span.hi()); + self.push_rewrite(span, rewrite); + + false + } + + fn walk_mod_items(&mut self, m: &ast::Mod) { + self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); + } + + fn walk_stmts(&mut self, stmts: &[ast::Stmt]) { + fn to_stmt_item(stmt: &ast::Stmt) -> Option<&ast::Item> { + match stmt.node { + ast::StmtKind::Item(ref item) => Some(&**item), + _ => None, + } + } + + if stmts.is_empty() { + return; + } + + // Extract leading `use ...;`. + let items: Vec<_> = stmts + .iter() + .take_while(|stmt| to_stmt_item(stmt).map_or(false, is_use_item)) + .filter_map(|stmt| to_stmt_item(stmt)) + .collect(); + + if items.is_empty() { + self.visit_stmt(&stmts[0]); + self.walk_stmts(&stmts[1..]); + } else { + self.visit_items_with_reordering(&items); + self.walk_stmts(&stmts[items.len()..]); + } + } + + fn walk_block_stmts(&mut self, b: &ast::Block) { + self.walk_stmts(&b.stmts) + } + + fn format_mod( + &mut self, + m: &ast::Mod, + vis: &ast::Visibility, + s: Span, + ident: ast::Ident, + attrs: &[ast::Attribute], + is_internal: bool, + ) { + self.push_str(&*utils::format_visibility(vis)); + self.push_str("mod "); + self.push_str(&ident.to_string()); + + if is_internal { + match self.config.brace_style() { + BraceStyle::AlwaysNextLine => { + let indent_str = self.block_indent.to_string_with_newline(self.config); + self.push_str(&indent_str); + self.push_str("{"); + } + _ => self.push_str(" {"), + } + // Hackery to account for the closing }. + let mod_lo = self.snippet_provider.span_after(source!(self, s), "{"); + let body_snippet = + self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); + let body_snippet = body_snippet.trim(); + if body_snippet.is_empty() { + self.push_str("}"); + } else { + self.last_pos = mod_lo; + self.block_indent = self.block_indent.block_indent(self.config); + self.visit_attrs(attrs, ast::AttrStyle::Inner); + self.walk_mod_items(m); + self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); + self.close_block(false); + } + self.last_pos = source!(self, m.inner).hi(); + } else { + self.push_str(";"); + self.last_pos = source!(self, s).hi(); + } + } + + pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { + self.block_indent = Indent::empty(); + self.walk_mod_items(m); + self.format_missing_with_indent(filemap.end_pos); + } + + pub fn skip_empty_lines(&mut self, end_pos: BytePos) { + while let Some(pos) = self.snippet_provider + .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") + { + if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { + if snippet.trim().is_empty() { + self.last_pos = pos; + } else { + return; + } + } + } + } + + pub fn get_context(&self) -> RewriteContext { + RewriteContext { + parse_session: self.parse_session, + codemap: self.codemap, + config: self.config, + inside_macro: false, + use_block: false, + is_if_else_block: false, + force_one_line_chain: false, + snippet_provider: self.snippet_provider, + } + } +} -- cgit 1.4.1-3-g733a5 From 4f522794ae0c536768908a4dd3e8292ada2c70a0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 2 Mar 2018 15:07:13 +1300 Subject: Tidy up and pass tests --- cargo-fmt/Cargo.toml | 17 - git-rustfmt/Cargo.toml | 19 - rustfmt-bin/Cargo.toml | 20 - rustfmt-bin/build.rs | 59 -- rustfmt-config/Cargo.toml | 16 - rustfmt-config/README.md | 3 - rustfmt-core/Cargo.toml | 33 - rustfmt-core/README.md | 3 - .../tests/config/disable_all_formatting.toml | 1 - rustfmt-core/tests/config/issue-1111.toml | 1 - rustfmt-core/tests/config/small_tabs.toml | 12 - rustfmt-core/tests/coverage/source/comments.rs | 7 - rustfmt-core/tests/coverage/target/comments.rs | 7 - rustfmt-core/tests/lib.rs | 873 -------------------- rustfmt-core/tests/source/assignment.rs | 30 - .../source/associated-types-bounds-wrapping.rs | 6 - rustfmt-core/tests/source/attrib.rs | 155 ---- rustfmt-core/tests/source/big-impl-block.rs | 125 --- rustfmt-core/tests/source/big-impl-visual.rs | 106 --- rustfmt-core/tests/source/break-and-continue.rs | 23 - rustfmt-core/tests/source/catch.rs | 27 - rustfmt-core/tests/source/chains-visual.rs | 159 ---- rustfmt-core/tests/source/chains.rs | 231 ------ .../tests/source/closure-block-inside-macro.rs | 11 - rustfmt-core/tests/source/closure.rs | 213 ----- rustfmt-core/tests/source/comment.rs | 90 -- rustfmt-core/tests/source/comment2.rs | 4 - rustfmt-core/tests/source/comment3.rs | 5 - rustfmt-core/tests/source/comment4.rs | 52 -- rustfmt-core/tests/source/comment5.rs | 14 - rustfmt-core/tests/source/comment_crlf_newline.rs | 4 - .../source/configs/blank_lines_lower_bound/1.rs | 13 - .../configs/brace_style/fn_always_next_line.rs | 14 - .../configs/brace_style/fn_prefer_same_line.rs | 14 - .../configs/brace_style/fn_same_line_where.rs | 14 - .../configs/brace_style/item_always_next_line.rs | 20 - .../configs/brace_style/item_prefer_same_line.rs | 16 - .../configs/brace_style/item_same_line_where.rs | 16 - .../tests/source/configs/comment_width/above.rs | 7 - .../tests/source/configs/comment_width/below.rs | 7 - .../tests/source/configs/comment_width/ignore.rs | 7 - .../configs/condense_wildcard_suffixes/false.rs | 6 - .../configs/condense_wildcard_suffixes/true.rs | 6 - .../control_brace_style/always_next_line.rs | 10 - .../control_brace_style/always_same_line.rs | 10 - .../control_brace_style/closing_next_line.rs | 10 - .../source/configs/disable_all_formatting/false.rs | 6 - .../source/configs/disable_all_formatting/true.rs | 6 - .../source/configs/empty_item_single_line/false.rs | 17 - .../source/configs/empty_item_single_line/true.rs | 17 - .../source/configs/error_on_line_overflow/false.rs | 6 - .../source/configs/fn_args_density/compressed.rs | 16 - .../tests/source/configs/fn_args_density/tall.rs | 16 - .../source/configs/fn_args_density/vertical.rs | 16 - .../tests/source/configs/fn_single_line/false.rs | 11 - .../tests/source/configs/fn_single_line/true.rs | 11 - .../source/configs/force_explicit_abi/false.rs | 6 - .../source/configs/force_explicit_abi/true.rs | 6 - .../source/configs/force_multiline_block/false.rs | 22 - .../source/configs/force_multiline_block/true.rs | 18 - .../tests/source/configs/format_strings/false.rs | 8 - .../tests/source/configs/format_strings/true.rs | 7 - .../tests/source/configs/hard_tabs/false.rs | 6 - .../tests/source/configs/hard_tabs/true.rs | 6 - .../source/configs/indent_style/block_args.rs | 26 - .../source/configs/indent_style/block_array.rs | 6 - .../source/configs/indent_style/block_call.rs | 133 --- .../source/configs/indent_style/block_chain.rs | 6 - .../source/configs/indent_style/block_generic.rs | 6 - .../configs/indent_style/block_struct_lit.rs | 6 - .../indent_style/block_trailing_comma_call.rs | 8 - .../configs/indent_style/block_where_pred.rs | 6 - .../tests/source/configs/indent_style/default.rs | 6 - .../tests/source/configs/indent_style/rfc_where.rs | 6 - .../source/configs/indent_style/visual_args.rs | 32 - .../source/configs/indent_style/visual_array.rs | 6 - .../source/configs/indent_style/visual_call.rs | 6 - .../source/configs/indent_style/visual_chain.rs | 6 - .../source/configs/indent_style/visual_generics.rs | 6 - .../configs/indent_style/visual_struct_lit.rs | 6 - .../configs/indent_style/visual_trailing_comma.rs | 7 - .../configs/indent_style/visual_where_pred.rs | 6 - .../tests/source/configs/match_arm_blocks/false.rs | 11 - .../tests/source/configs/match_arm_blocks/true.rs | 11 - .../configs/match_block_trailing_comma/false.rs | 11 - .../configs/match_block_trailing_comma/true.rs | 11 - .../tests/source/configs/merge_derives/true.rs | 46 -- .../source/configs/normalize_comments/false.rs | 13 - .../source/configs/normalize_comments/true.rs | 13 - .../source/configs/reorder_extern_crates/false.rs | 11 - .../source/configs/reorder_extern_crates/true.rs | 11 - .../source/configs/reorder_imported_names/false.rs | 4 - .../source/configs/reorder_imported_names/true.rs | 4 - .../tests/source/configs/reorder_imports/false.rs | 7 - .../tests/source/configs/reorder_imports/true.rs | 19 - .../configs/reorder_imports_in_group/false.rs | 13 - .../configs/reorder_imports_in_group/true.rs | 13 - .../source/configs/reorder_modules/dolor/mod.rs | 1 - .../tests/source/configs/reorder_modules/false.rs | 7 - .../source/configs/reorder_modules/ipsum/mod.rs | 1 - .../source/configs/reorder_modules/lorem/mod.rs | 1 - .../source/configs/reorder_modules/sit/mod.rs | 1 - .../tests/source/configs/reorder_modules/true.rs | 7 - .../tests/source/configs/skip_children/true.rs | 3 - .../source/configs/space_before_colon/true.rs | 11 - .../source/configs/spaces_around_ranges/false.rs | 22 - .../source/configs/spaces_around_ranges/true.rs | 22 - .../spaces_within_parens_and_brackets/false.rs | 7 - .../spaces_within_parens_and_brackets/true.rs | 133 --- .../configs/struct_field_align_threshold/20.rs | 383 --------- .../source/configs/struct_lit_single_line/false.rs | 6 - rustfmt-core/tests/source/configs/tab_spaces/2.rs | 11 - rustfmt-core/tests/source/configs/tab_spaces/4.rs | 11 - .../tests/source/configs/trailing_comma/always.rs | 7 - .../tests/source/configs/trailing_comma/never.rs | 23 - .../source/configs/trailing_comma/vertical.rs | 7 - .../configs/type_punctuation_density/compressed.rs | 37 - .../configs/type_punctuation_density/wide.rs | 37 - .../configs/use_field_init_shorthand/false.rs | 19 - .../configs/use_field_init_shorthand/true.rs | 19 - .../source/configs/use_try_shorthand/false.rs | 6 - .../tests/source/configs/use_try_shorthand/true.rs | 6 - .../tests/source/configs/where_single_line/true.rs | 24 - .../tests/source/configs/wrap_comments/false.rs | 8 - .../tests/source/configs/wrap_comments/true.rs | 15 - .../source/control-brace-style-always-next-line.rs | 44 - .../source/control-brace-style-always-same-line.rs | 44 - rustfmt-core/tests/source/doc.rs | 5 - .../source/else-if-brace-style-always-next-line.rs | 54 -- .../source/else-if-brace-style-always-same-line.rs | 54 -- .../else-if-brace-style-closing-next-line.rs | 54 -- rustfmt-core/tests/source/empty_file.rs | 0 rustfmt-core/tests/source/enum.rs | 194 ----- rustfmt-core/tests/source/expr-block.rs | 286 ------- rustfmt-core/tests/source/expr.rs | 372 --------- rustfmt-core/tests/source/extern.rs | 60 -- rustfmt-core/tests/source/extern_not_explicit.rs | 14 - rustfmt-core/tests/source/file-lines-1.rs | 29 - rustfmt-core/tests/source/file-lines-2.rs | 29 - rustfmt-core/tests/source/file-lines-3.rs | 30 - rustfmt-core/tests/source/file-lines-4.rs | 30 - rustfmt-core/tests/source/file-lines-5.rs | 17 - rustfmt-core/tests/source/file-lines-6.rs | 18 - rustfmt-core/tests/source/file-lines-item.rs | 22 - rustfmt-core/tests/source/fn-custom-2.rs | 36 - rustfmt-core/tests/source/fn-custom-3.rs | 32 - rustfmt-core/tests/source/fn-custom-4.rs | 14 - rustfmt-core/tests/source/fn-custom-6.rs | 41 - rustfmt-core/tests/source/fn-custom-7.rs | 25 - rustfmt-core/tests/source/fn-custom-8.rs | 49 -- rustfmt-core/tests/source/fn-custom.rs | 13 - rustfmt-core/tests/source/fn-simple.rs | 66 -- rustfmt-core/tests/source/fn-single-line.rs | 79 -- .../tests/source/fn_args_density-vertical.rs | 33 - rustfmt-core/tests/source/fn_args_indent-block.rs | 78 -- rustfmt-core/tests/source/hard-tabs.rs | 85 -- rustfmt-core/tests/source/hello.rs | 6 - rustfmt-core/tests/source/hello2.rs | 8 - rustfmt-core/tests/source/immovable_generators.rs | 7 - rustfmt-core/tests/source/impls.rs | 154 ---- .../source/imports-reorder-lines-and-items.rs | 10 - rustfmt-core/tests/source/imports-reorder-lines.rs | 34 - rustfmt-core/tests/source/imports-reorder.rs | 6 - rustfmt-core/tests/source/imports.rs | 89 -- rustfmt-core/tests/source/issue-1021.rs | 22 - rustfmt-core/tests/source/issue-1049.rs | 18 - rustfmt-core/tests/source/issue-1111.rs | 1 - rustfmt-core/tests/source/issue-1120.rs | 9 - rustfmt-core/tests/source/issue-1124.rs | 16 - rustfmt-core/tests/source/issue-1127.rs | 23 - rustfmt-core/tests/source/issue-1158.rs | 3 - rustfmt-core/tests/source/issue-1177.rs | 7 - rustfmt-core/tests/source/issue-1192.rs | 3 - rustfmt-core/tests/source/issue-1211.rs | 15 - rustfmt-core/tests/source/issue-1216.rs | 5 - rustfmt-core/tests/source/issue-1239.rs | 9 - rustfmt-core/tests/source/issue-1278.rs | 9 - rustfmt-core/tests/source/issue-1350.rs | 16 - rustfmt-core/tests/source/issue-1366.rs | 12 - rustfmt-core/tests/source/issue-1468.rs | 27 - rustfmt-core/tests/source/issue-1693.rs | 3 - rustfmt-core/tests/source/issue-1800.rs | 3 - rustfmt-core/tests/source/issue-1914.rs | 6 - rustfmt-core/tests/source/issue-2025.rs | 8 - rustfmt-core/tests/source/issue-2111.rs | 28 - rustfmt-core/tests/source/issue-2164.rs | 4 - rustfmt-core/tests/source/issue-2179.rs | 35 - rustfmt-core/tests/source/issue-2256.rs | 12 - rustfmt-core/tests/source/issue-2342.rs | 5 - rustfmt-core/tests/source/issue-2446.rs | 11 - rustfmt-core/tests/source/issue-2479.rs | 2 - rustfmt-core/tests/source/issue-447.rs | 39 - rustfmt-core/tests/source/issue-510.rs | 37 - rustfmt-core/tests/source/issue-811.rs | 19 - rustfmt-core/tests/source/issue-850.rs | 1 - rustfmt-core/tests/source/issue-855.rs | 20 - rustfmt-core/tests/source/issue-913.rs | 22 - rustfmt-core/tests/source/issue-945.rs | 5 - rustfmt-core/tests/source/issue-977.rs | 8 - .../source/item-brace-style-always-next-line.rs | 29 - .../source/item-brace-style-prefer-same-line.rs | 29 - .../source/item-brace-style-same-line-where.rs | 31 - rustfmt-core/tests/source/large-block.rs | 5 - rustfmt-core/tests/source/large_vec.rs | 29 - rustfmt-core/tests/source/lazy_static.rs | 37 - .../tests/source/long-match-arms-brace-newline.rs | 15 - rustfmt-core/tests/source/long_field_access.rs | 3 - rustfmt-core/tests/source/loop.rs | 29 - rustfmt-core/tests/source/macro_not_expr.rs | 7 - rustfmt-core/tests/source/macro_rules.rs | 114 --- rustfmt-core/tests/source/macros.rs | 342 -------- .../tests/source/markdown-comment-with-options.rs | 17 - rustfmt-core/tests/source/markdown-comment.rs | 15 - .../tests/source/match-block-trailing-comma.rs | 14 - .../tests/source/match-nowrap-trailing-comma.rs | 15 - rustfmt-core/tests/source/match-nowrap.rs | 12 - rustfmt-core/tests/source/match.rs | 464 ----------- .../tests/source/max-line-length-in-chars.rs | 4 - rustfmt-core/tests/source/mod-1.rs | 29 - rustfmt-core/tests/source/mod-2.rs | 4 - rustfmt-core/tests/source/mod_skip_child.rs | 2 - rustfmt-core/tests/source/multiple.rs | 134 --- rustfmt-core/tests/source/nested-if-else.rs | 11 - rustfmt-core/tests/source/nested_skipped/mod.rs | 3 - rustfmt-core/tests/source/nestedmod/mod.rs | 13 - rustfmt-core/tests/source/nestedmod/mod2a.rs | 4 - rustfmt-core/tests/source/nestedmod/mod2b.rs | 3 - rustfmt-core/tests/source/nestedmod/mod2c.rs | 3 - .../tests/source/nestedmod/mymod1/mod3a.rs | 2 - rustfmt-core/tests/source/nestedmod/submod2/a.rs | 6 - rustfmt-core/tests/source/nestedmod/submod2/mod.rs | 5 - rustfmt-core/tests/source/no_new_line_beginning.rs | 2 - rustfmt-core/tests/source/other.rs | 5 - rustfmt-core/tests/source/paths.rs | 25 - .../tests/source/pattern-condense-wildcards.rs | 12 - rustfmt-core/tests/source/pattern.rs | 65 -- rustfmt-core/tests/source/pub-restricted.rs | 64 -- rustfmt-core/tests/source/remove_blank_lines.rs | 44 - rustfmt-core/tests/source/single-line-if-else.rs | 49 -- rustfmt-core/tests/source/soft-wrapping.rs | 15 - .../tests/source/space-not-before-newline.rs | 8 - rustfmt-core/tests/source/spaces-around-ranges.rs | 15 - rustfmt-core/tests/source/static.rs | 23 - rustfmt-core/tests/source/string-lit-2.rs | 25 - rustfmt-core/tests/source/string-lit.rs | 62 -- rustfmt-core/tests/source/string_punctuation.rs | 8 - .../tests/source/struct-field-attributes.rs | 52 -- rustfmt-core/tests/source/struct_lits.rs | 144 ---- rustfmt-core/tests/source/struct_lits_multiline.rs | 81 -- rustfmt-core/tests/source/struct_lits_visual.rs | 47 -- .../tests/source/struct_lits_visual_multiline.rs | 45 - rustfmt-core/tests/source/struct_tuple_visual.rs | 37 - rustfmt-core/tests/source/structs.rs | 283 ------- rustfmt-core/tests/source/trailing-comma-never.rs | 41 - rustfmt-core/tests/source/trailing_commas.rs | 47 -- rustfmt-core/tests/source/trait.rs | 94 --- rustfmt-core/tests/source/try-conversion.rs | 18 - rustfmt-core/tests/source/tuple.rs | 52 -- rustfmt-core/tests/source/type-ascription.rs | 9 - rustfmt-core/tests/source/type.rs | 25 - rustfmt-core/tests/source/type_alias.rs | 34 - rustfmt-core/tests/source/unions.rs | 195 ----- rustfmt-core/tests/source/where-clause-rfc.rs | 58 -- rustfmt-core/tests/source/where-clause.rs | 58 -- rustfmt-core/tests/target/assignment.rs | 36 - rustfmt-core/tests/target/associated-items.rs | 3 - .../target/associated-types-bounds-wrapping.rs | 7 - .../tests/target/associated_type_defaults.rs | 4 - rustfmt-core/tests/target/attrib-extern-crate.rs | 17 - rustfmt-core/tests/target/attrib.rs | 160 ---- rustfmt-core/tests/target/big-impl-block.rs | 87 -- rustfmt-core/tests/target/big-impl-visual.rs | 73 -- rustfmt-core/tests/target/break-and-continue.rs | 23 - rustfmt-core/tests/target/catch.rs | 21 - rustfmt-core/tests/target/chains-visual.rs | 159 ---- rustfmt-core/tests/target/chains.rs | 261 ------ .../tests/target/closure-block-inside-macro.rs | 11 - rustfmt-core/tests/target/closure.rs | 248 ------ rustfmt-core/tests/target/comment-inside-const.rs | 9 - rustfmt-core/tests/target/comment-not-disappear.rs | 36 - rustfmt-core/tests/target/comment.rs | 95 --- rustfmt-core/tests/target/comment2.rs | 5 - rustfmt-core/tests/target/comment3.rs | 6 - rustfmt-core/tests/target/comment4.rs | 51 -- rustfmt-core/tests/target/comment5.rs | 16 - rustfmt-core/tests/target/comment_crlf_newline.rs | 4 - rustfmt-core/tests/target/comments-fn.rs | 39 - .../target/configs/blank_lines_lower_bound/1.rs | 16 - .../configs/brace_style/fn_always_next_line.rs | 19 - .../configs/brace_style/fn_prefer_same_line.rs | 16 - .../configs/brace_style/fn_same_line_where.rs | 17 - .../configs/brace_style/item_always_next_line.rs | 27 - .../configs/brace_style/item_prefer_same_line.rs | 18 - .../configs/brace_style/item_same_line_where.rs | 19 - .../target/configs/combine_control_expr/false.rs | 133 --- .../target/configs/combine_control_expr/true.rs | 121 --- .../tests/target/configs/comment_width/above.rs | 8 - .../tests/target/configs/comment_width/below.rs | 7 - .../tests/target/configs/comment_width/ignore.rs | 7 - .../configs/condense_wildcard_suffixes/false.rs | 6 - .../configs/condense_wildcard_suffixes/true.rs | 6 - .../control_brace_style/always_next_line.rs | 18 - .../control_brace_style/always_same_line.rs | 14 - .../control_brace_style/closing_next_line.rs | 15 - .../target/configs/disable_all_formatting/false.rs | 10 - .../target/configs/disable_all_formatting/true.rs | 6 - .../target/configs/empty_item_single_line/false.rs | 15 - .../target/configs/empty_item_single_line/true.rs | 10 - .../target/configs/error_on_line_overflow/false.rs | 6 - .../target/configs/error_on_unformatted/false.rs | 12 - .../target/configs/fn_args_density/compressed.rs | 22 - .../tests/target/configs/fn_args_density/tall.rs | 32 - .../target/configs/fn_args_density/vertical.rs | 42 - .../tests/target/configs/fn_single_line/false.rs | 11 - .../tests/target/configs/fn_single_line/true.rs | 9 - .../target/configs/force_explicit_abi/false.rs | 6 - .../target/configs/force_explicit_abi/true.rs | 6 - .../target/configs/force_multiline_block/false.rs | 20 - .../target/configs/force_multiline_block/true.rs | 22 - .../tests/target/configs/format_strings/false.rs | 8 - .../tests/target/configs/format_strings/true.rs | 9 - .../tests/target/configs/hard_tabs/false.rs | 6 - .../tests/target/configs/hard_tabs/true.rs | 6 - .../tests/target/configs/imports_indent/block.rs | 7 - .../configs/imports_layout/horizontal_vertical.rs | 18 - .../tests/target/configs/imports_layout/mixed.rs | 9 - .../target/configs/indent_style/block_args.rs | 47 -- .../target/configs/indent_style/block_array.rs | 14 - .../target/configs/indent_style/block_call.rs | 149 ---- .../target/configs/indent_style/block_chain.rs | 12 - .../target/configs/indent_style/block_generic.rs | 22 - .../configs/indent_style/block_struct_lit.rs | 9 - .../configs/indent_style/block_tab_spaces_call.rs | 14 - .../indent_style/block_trailing_comma_call.rs | 11 - .../configs/indent_style/block_where_pred.rs | 12 - .../tests/target/configs/indent_style/default.rs | 11 - .../target/configs/indent_style/rfc_control.rs | 39 - .../tests/target/configs/indent_style/rfc_where.rs | 12 - .../target/configs/indent_style/visual_args.rs | 40 - .../target/configs/indent_style/visual_array.rs | 12 - .../target/configs/indent_style/visual_call.rs | 13 - .../target/configs/indent_style/visual_chain.rs | 11 - .../target/configs/indent_style/visual_generics.rs | 20 - .../configs/indent_style/visual_struct_lit.rs | 7 - .../configs/indent_style/visual_trailing_comma.rs | 7 - .../configs/indent_style/visual_where_pred.rs | 11 - .../tests/target/configs/match_arm_blocks/false.rs | 10 - .../tests/target/configs/match_arm_blocks/true.rs | 11 - .../configs/match_block_trailing_comma/false.rs | 11 - .../configs/match_block_trailing_comma/true.rs | 11 - .../tests/target/configs/merge_derives/true.rs | 40 - .../target/configs/normalize_comments/false.rs | 13 - .../target/configs/normalize_comments/true.rs | 13 - .../target/configs/reorder_extern_crates/false.rs | 11 - .../target/configs/reorder_extern_crates/true.rs | 11 - .../target/configs/reorder_imported_names/false.rs | 4 - .../target/configs/reorder_imported_names/true.rs | 4 - .../tests/target/configs/reorder_imports/false.rs | 7 - .../tests/target/configs/reorder_imports/true.rs | 19 - .../configs/reorder_imports_in_group/false.rs | 12 - .../configs/reorder_imports_in_group/true.rs | 13 - .../target/configs/reorder_modules/dolor/mod.rs | 1 - .../tests/target/configs/reorder_modules/false.rs | 7 - .../target/configs/reorder_modules/ipsum/mod.rs | 1 - .../target/configs/reorder_modules/lorem/mod.rs | 1 - .../target/configs/reorder_modules/sit/mod.rs | 1 - .../tests/target/configs/reorder_modules/true.rs | 7 - .../tests/target/configs/skip_children/true.rs | 3 - .../target/configs/space_before_colon/true.rs | 11 - .../target/configs/spaces_around_ranges/false.rs | 22 - .../target/configs/spaces_around_ranges/true.rs | 22 - .../spaces_within_parens_and_brackets/false.rs | 7 - .../spaces_within_parens_and_brackets/true.rs | 145 ---- .../configs/struct_field_align_threshold/20.rs | 467 ----------- .../target/configs/struct_lit_single_line/false.rs | 9 - rustfmt-core/tests/target/configs/tab_spaces/2.rs | 14 - rustfmt-core/tests/target/configs/tab_spaces/4.rs | 14 - .../tests/target/configs/trailing_comma/always.rs | 14 - .../tests/target/configs/trailing_comma/never.rs | 35 - .../target/configs/trailing_comma/vertical.rs | 14 - .../target/configs/trailing_semicolon/false.rs | 27 - .../target/configs/trailing_semicolon/true.rs | 27 - .../configs/type_punctuation_density/compressed.rs | 41 - .../configs/type_punctuation_density/wide.rs | 41 - .../configs/use_field_init_shorthand/false.rs | 15 - .../configs/use_field_init_shorthand/true.rs | 15 - .../target/configs/use_try_shorthand/false.rs | 6 - .../tests/target/configs/use_try_shorthand/true.rs | 6 - .../tests/target/configs/where_single_line/true.rs | 28 - .../tests/target/configs/wrap_comments/false.rs | 8 - .../tests/target/configs/wrap_comments/true.rs | 20 - .../target/control-brace-style-always-next-line.rs | 50 -- .../target/control-brace-style-always-same-line.rs | 42 - rustfmt-core/tests/target/doc.rs | 5 - .../target/else-if-brace-style-always-next-line.rs | 53 -- .../target/else-if-brace-style-always-same-line.rs | 45 - .../else-if-brace-style-closing-next-line.rs | 49 -- .../empty-tuple-no-conversion-to-unit-struct.rs | 12 - rustfmt-core/tests/target/empty_file.rs | 1 - rustfmt-core/tests/target/enum.rs | 255 ------ rustfmt-core/tests/target/expr-block.rs | 299 ------- rustfmt-core/tests/target/expr.rs | 397 --------- rustfmt-core/tests/target/extern.rs | 73 -- rustfmt-core/tests/target/extern_not_explicit.rs | 18 - rustfmt-core/tests/target/file-lines-1.rs | 29 - rustfmt-core/tests/target/file-lines-2.rs | 24 - rustfmt-core/tests/target/file-lines-3.rs | 25 - rustfmt-core/tests/target/file-lines-4.rs | 30 - rustfmt-core/tests/target/file-lines-5.rs | 17 - rustfmt-core/tests/target/file-lines-6.rs | 18 - rustfmt-core/tests/target/file-lines-item.rs | 22 - .../tests/target/fn-args-with-last-line-comment.rs | 24 - rustfmt-core/tests/target/fn-custom-2.rs | 78 -- rustfmt-core/tests/target/fn-custom-3.rs | 72 -- rustfmt-core/tests/target/fn-custom-4.rs | 27 - rustfmt-core/tests/target/fn-custom-6.rs | 72 -- rustfmt-core/tests/target/fn-custom-7.rs | 41 - rustfmt-core/tests/target/fn-custom-8.rs | 78 -- rustfmt-core/tests/target/fn-custom.rs | 19 - rustfmt-core/tests/target/fn-simple.rs | 107 --- rustfmt-core/tests/target/fn-single-line.rs | 70 -- rustfmt-core/tests/target/fn-ty.rs | 14 - rustfmt-core/tests/target/fn.rs | 122 --- .../tests/target/fn_args_density-vertical.rs | 39 - rustfmt-core/tests/target/fn_args_indent-block.rs | 144 ---- rustfmt-core/tests/target/fn_once.rs | 8 - rustfmt-core/tests/target/hard-tabs.rs | 99 --- rustfmt-core/tests/target/hello.rs | 8 - rustfmt-core/tests/target/immovable_generators.rs | 7 - rustfmt-core/tests/target/impl.rs | 43 - rustfmt-core/tests/target/impls.rs | 219 ----- .../tests/target/import-fencepost-length.rs | 4 - .../target/imports-reorder-lines-and-items.rs | 10 - rustfmt-core/tests/target/imports-reorder-lines.rs | 33 - rustfmt-core/tests/target/imports-reorder.rs | 6 - rustfmt-core/tests/target/imports.rs | 88 -- rustfmt-core/tests/target/indented-impl.rs | 13 - rustfmt-core/tests/target/issue-1021.rs | 22 - rustfmt-core/tests/target/issue-1049.rs | 29 - rustfmt-core/tests/target/issue-1055.rs | 3 - rustfmt-core/tests/target/issue-1111.rs | 1 - rustfmt-core/tests/target/issue-1113.rs | 33 - rustfmt-core/tests/target/issue-1120.rs | 11 - rustfmt-core/tests/target/issue-1124.rs | 20 - rustfmt-core/tests/target/issue-1127.rs | 25 - rustfmt-core/tests/target/issue-1158.rs | 3 - rustfmt-core/tests/target/issue-1177.rs | 7 - rustfmt-core/tests/target/issue-1192.rs | 3 - rustfmt-core/tests/target/issue-1211.rs | 13 - rustfmt-core/tests/target/issue-1214.rs | 8 - rustfmt-core/tests/target/issue-1216.rs | 5 - rustfmt-core/tests/target/issue-1239.rs | 10 - rustfmt-core/tests/target/issue-1247.rs | 8 - rustfmt-core/tests/target/issue-1255.rs | 10 - rustfmt-core/tests/target/issue-1278.rs | 9 - rustfmt-core/tests/target/issue-1350.rs | 14 - rustfmt-core/tests/target/issue-1366.rs | 13 - rustfmt-core/tests/target/issue-1397.rs | 25 - rustfmt-core/tests/target/issue-1468.rs | 29 - rustfmt-core/tests/target/issue-1598.rs | 6 - rustfmt-core/tests/target/issue-1624.rs | 6 - rustfmt-core/tests/target/issue-1681.rs | 20 - rustfmt-core/tests/target/issue-1693.rs | 10 - rustfmt-core/tests/target/issue-1703.rs | 9 - rustfmt-core/tests/target/issue-1800.rs | 3 - rustfmt-core/tests/target/issue-1802.rs | 10 - rustfmt-core/tests/target/issue-1824.rs | 5 - rustfmt-core/tests/target/issue-1914.rs | 7 - rustfmt-core/tests/target/issue-2025.rs | 4 - rustfmt-core/tests/target/issue-2103.rs | 14 - rustfmt-core/tests/target/issue-2111.rs | 26 - rustfmt-core/tests/target/issue-2123.rs | 6 - rustfmt-core/tests/target/issue-2164.rs | 132 --- rustfmt-core/tests/target/issue-2179.rs | 36 - rustfmt-core/tests/target/issue-2197.rs | 18 - rustfmt-core/tests/target/issue-2256.rs | 7 - rustfmt-core/tests/target/issue-2324.rs | 7 - rustfmt-core/tests/target/issue-2329.rs | 30 - rustfmt-core/tests/target/issue-2342.rs | 6 - rustfmt-core/tests/target/issue-2346.rs | 4 - rustfmt-core/tests/target/issue-2401.rs | 7 - rustfmt-core/tests/target/issue-2446.rs | 9 - rustfmt-core/tests/target/issue-2479.rs | 12 - rustfmt-core/tests/target/issue-447.rs | 40 - rustfmt-core/tests/target/issue-510.rs | 41 - rustfmt-core/tests/target/issue-64.rs | 7 - rustfmt-core/tests/target/issue-691.rs | 9 - rustfmt-core/tests/target/issue-770.rs | 10 - rustfmt-core/tests/target/issue-811.rs | 19 - rustfmt-core/tests/target/issue-831.rs | 9 - rustfmt-core/tests/target/issue-850.rs | 1 - rustfmt-core/tests/target/issue-855.rs | 27 - rustfmt-core/tests/target/issue-913.rs | 24 - rustfmt-core/tests/target/issue-945.rs | 17 - rustfmt-core/tests/target/issue-977.rs | 16 - .../target/item-brace-style-always-next-line.rs | 42 - .../target/item-brace-style-prefer-same-line.rs | 35 - .../target/item-brace-style-same-line-where.rs | 39 - rustfmt-core/tests/target/large-block.rs | 5 - rustfmt-core/tests/target/large_vec.rs | 42 - rustfmt-core/tests/target/lazy_static.rs | 39 - rustfmt-core/tests/target/long-fn-1.rs | 21 - .../tests/target/long-match-arms-brace-newline.rs | 15 - rustfmt-core/tests/target/long_field_access.rs | 4 - rustfmt-core/tests/target/loop.rs | 34 - rustfmt-core/tests/target/macro_not_expr.rs | 7 - rustfmt-core/tests/target/macro_rules.rs | 105 --- rustfmt-core/tests/target/macros.rs | 917 --------------------- .../tests/target/markdown-comment-with-options.rs | 17 - rustfmt-core/tests/target/markdown-comment.rs | 15 - .../tests/target/match-block-trailing-comma.rs | 16 - .../tests/target/match-nowrap-trailing-comma.rs | 17 - rustfmt-core/tests/target/match-nowrap.rs | 13 - rustfmt-core/tests/target/match.rs | 495 ----------- .../tests/target/max-line-length-in-chars.rs | 4 - rustfmt-core/tests/target/mod-1.rs | 38 - rustfmt-core/tests/target/mod-2.rs | 5 - rustfmt-core/tests/target/mod_skip_child.rs | 2 - rustfmt-core/tests/target/mulit-file.rs | 10 - rustfmt-core/tests/target/multiple.rs | 178 ---- rustfmt-core/tests/target/nested-if-else.rs | 11 - rustfmt-core/tests/target/nested-visual-block.rs | 59 -- rustfmt-core/tests/target/nested_skipped/mod.rs | 3 - rustfmt-core/tests/target/nestedmod/mod.rs | 12 - rustfmt-core/tests/target/nestedmod/mod2a.rs | 4 - rustfmt-core/tests/target/nestedmod/mod2b.rs | 2 - rustfmt-core/tests/target/nestedmod/mod2c.rs | 3 - .../tests/target/nestedmod/mymod1/mod3a.rs | 2 - rustfmt-core/tests/target/nestedmod/submod2/a.rs | 6 - rustfmt-core/tests/target/nestedmod/submod2/mod.rs | 5 - rustfmt-core/tests/target/no_new_line_beginning.rs | 1 - rustfmt-core/tests/target/other.rs | 5 - rustfmt-core/tests/target/paths.rs | 28 - .../tests/target/pattern-condense-wildcards.rs | 12 - rustfmt-core/tests/target/pattern.rs | 77 -- rustfmt-core/tests/target/pub-restricted.rs | 64 -- rustfmt-core/tests/target/remove_blank_lines.rs | 28 - rustfmt-core/tests/target/single-line-if-else.rs | 58 -- rustfmt-core/tests/target/skip.rs | 87 -- rustfmt-core/tests/target/skip_mod.rs | 3 - rustfmt-core/tests/target/soft-wrapping.rs | 15 - .../tests/target/space-not-before-newline.rs | 8 - rustfmt-core/tests/target/spaces-around-ranges.rs | 15 - rustfmt-core/tests/target/static.rs | 27 - rustfmt-core/tests/target/string-lit-2.rs | 25 - rustfmt-core/tests/target/string-lit-custom.rs | 22 - rustfmt-core/tests/target/string-lit.rs | 64 -- rustfmt-core/tests/target/string_punctuation.rs | 15 - .../tests/target/struct-field-attributes.rs | 56 -- rustfmt-core/tests/target/struct_lits.rs | 191 ----- rustfmt-core/tests/target/struct_lits_multiline.rs | 117 --- rustfmt-core/tests/target/struct_lits_visual.rs | 50 -- .../tests/target/struct_lits_visual_multiline.rs | 50 -- rustfmt-core/tests/target/struct_tuple_visual.rs | 37 - rustfmt-core/tests/target/structs.rs | 332 -------- rustfmt-core/tests/target/trailing-comma-never.rs | 31 - rustfmt-core/tests/target/trailing_commas.rs | 103 --- rustfmt-core/tests/target/trait.rs | 132 --- rustfmt-core/tests/target/try-conversion.rs | 27 - rustfmt-core/tests/target/tuple.rs | 89 -- rustfmt-core/tests/target/type-ascription.rs | 12 - rustfmt-core/tests/target/type.rs | 31 - rustfmt-core/tests/target/type_alias.rs | 76 -- .../tests/target/unindent_if_else_cond_comment.rs | 27 - rustfmt-core/tests/target/unions.rs | 196 ----- rustfmt-core/tests/target/where-clause-rfc.rs | 128 --- rustfmt-core/tests/target/where-clause.rs | 107 --- .../tests/writemode/source/fn-single-line.rs | 80 -- rustfmt-core/tests/writemode/source/modified.rs | 14 - rustfmt-core/tests/writemode/target/checkstyle.xml | 2 - rustfmt-core/tests/writemode/target/modified.txt | 5 - rustfmt-format-diff/Cargo.toml | 21 - src/lib.rs | 1 - tests/config/disable_all_formatting.toml | 1 + tests/config/issue-1111.toml | 1 + tests/config/small_tabs.toml | 12 + tests/coverage/source/comments.rs | 7 + tests/coverage/target/comments.rs | 7 + tests/lib.rs | 861 +++++++++++++++++++ tests/source/assignment.rs | 30 + tests/source/associated-types-bounds-wrapping.rs | 6 + tests/source/attrib.rs | 155 ++++ tests/source/big-impl-block.rs | 125 +++ tests/source/big-impl-visual.rs | 106 +++ tests/source/break-and-continue.rs | 23 + tests/source/catch.rs | 27 + tests/source/chains-visual.rs | 159 ++++ tests/source/chains.rs | 231 ++++++ tests/source/closure-block-inside-macro.rs | 11 + tests/source/closure.rs | 213 +++++ tests/source/comment.rs | 90 ++ tests/source/comment2.rs | 4 + tests/source/comment3.rs | 5 + tests/source/comment4.rs | 52 ++ tests/source/comment5.rs | 14 + tests/source/comment_crlf_newline.rs | 4 + tests/source/configs/blank_lines_lower_bound/1.rs | 13 + .../configs/brace_style/fn_always_next_line.rs | 14 + .../configs/brace_style/fn_prefer_same_line.rs | 14 + .../configs/brace_style/fn_same_line_where.rs | 14 + .../configs/brace_style/item_always_next_line.rs | 20 + .../configs/brace_style/item_prefer_same_line.rs | 16 + .../configs/brace_style/item_same_line_where.rs | 16 + tests/source/configs/comment_width/above.rs | 7 + tests/source/configs/comment_width/below.rs | 7 + tests/source/configs/comment_width/ignore.rs | 7 + .../configs/condense_wildcard_suffixes/false.rs | 6 + .../configs/condense_wildcard_suffixes/true.rs | 6 + .../control_brace_style/always_next_line.rs | 10 + .../control_brace_style/always_same_line.rs | 10 + .../control_brace_style/closing_next_line.rs | 10 + .../source/configs/disable_all_formatting/false.rs | 6 + .../source/configs/disable_all_formatting/true.rs | 6 + .../source/configs/empty_item_single_line/false.rs | 17 + .../source/configs/empty_item_single_line/true.rs | 17 + .../source/configs/error_on_line_overflow/false.rs | 6 + tests/source/configs/fn_args_density/compressed.rs | 16 + tests/source/configs/fn_args_density/tall.rs | 16 + tests/source/configs/fn_args_density/vertical.rs | 16 + tests/source/configs/fn_single_line/false.rs | 11 + tests/source/configs/fn_single_line/true.rs | 11 + tests/source/configs/force_explicit_abi/false.rs | 6 + tests/source/configs/force_explicit_abi/true.rs | 6 + .../source/configs/force_multiline_block/false.rs | 22 + tests/source/configs/force_multiline_block/true.rs | 18 + tests/source/configs/format_strings/false.rs | 8 + tests/source/configs/format_strings/true.rs | 7 + tests/source/configs/hard_tabs/false.rs | 6 + tests/source/configs/hard_tabs/true.rs | 6 + tests/source/configs/indent_style/block_args.rs | 26 + tests/source/configs/indent_style/block_array.rs | 6 + tests/source/configs/indent_style/block_call.rs | 133 +++ tests/source/configs/indent_style/block_chain.rs | 6 + tests/source/configs/indent_style/block_generic.rs | 6 + .../configs/indent_style/block_struct_lit.rs | 6 + .../indent_style/block_trailing_comma_call.rs | 8 + .../configs/indent_style/block_where_pred.rs | 6 + tests/source/configs/indent_style/default.rs | 6 + tests/source/configs/indent_style/rfc_where.rs | 6 + tests/source/configs/indent_style/visual_args.rs | 32 + tests/source/configs/indent_style/visual_array.rs | 6 + tests/source/configs/indent_style/visual_call.rs | 6 + tests/source/configs/indent_style/visual_chain.rs | 6 + .../source/configs/indent_style/visual_generics.rs | 6 + .../configs/indent_style/visual_struct_lit.rs | 6 + .../configs/indent_style/visual_trailing_comma.rs | 7 + .../configs/indent_style/visual_where_pred.rs | 6 + tests/source/configs/match_arm_blocks/false.rs | 11 + tests/source/configs/match_arm_blocks/true.rs | 11 + .../configs/match_block_trailing_comma/false.rs | 11 + .../configs/match_block_trailing_comma/true.rs | 11 + tests/source/configs/merge_derives/true.rs | 46 ++ tests/source/configs/normalize_comments/false.rs | 13 + tests/source/configs/normalize_comments/true.rs | 13 + .../source/configs/reorder_extern_crates/false.rs | 11 + tests/source/configs/reorder_extern_crates/true.rs | 11 + .../source/configs/reorder_imported_names/false.rs | 4 + .../source/configs/reorder_imported_names/true.rs | 4 + tests/source/configs/reorder_imports/false.rs | 7 + tests/source/configs/reorder_imports/true.rs | 19 + .../configs/reorder_imports_in_group/false.rs | 13 + .../configs/reorder_imports_in_group/true.rs | 13 + tests/source/configs/reorder_modules/dolor/mod.rs | 1 + tests/source/configs/reorder_modules/false.rs | 7 + tests/source/configs/reorder_modules/ipsum/mod.rs | 1 + tests/source/configs/reorder_modules/lorem/mod.rs | 1 + tests/source/configs/reorder_modules/sit/mod.rs | 1 + tests/source/configs/reorder_modules/true.rs | 7 + tests/source/configs/skip_children/true.rs | 3 + tests/source/configs/space_before_colon/true.rs | 11 + tests/source/configs/spaces_around_ranges/false.rs | 22 + tests/source/configs/spaces_around_ranges/true.rs | 22 + .../spaces_within_parens_and_brackets/false.rs | 7 + .../spaces_within_parens_and_brackets/true.rs | 133 +++ .../configs/struct_field_align_threshold/20.rs | 383 +++++++++ .../source/configs/struct_lit_single_line/false.rs | 6 + tests/source/configs/tab_spaces/2.rs | 11 + tests/source/configs/tab_spaces/4.rs | 11 + tests/source/configs/trailing_comma/always.rs | 7 + tests/source/configs/trailing_comma/never.rs | 23 + tests/source/configs/trailing_comma/vertical.rs | 7 + .../configs/type_punctuation_density/compressed.rs | 37 + .../configs/type_punctuation_density/wide.rs | 37 + .../configs/use_field_init_shorthand/false.rs | 19 + .../configs/use_field_init_shorthand/true.rs | 19 + tests/source/configs/use_try_shorthand/false.rs | 6 + tests/source/configs/use_try_shorthand/true.rs | 6 + tests/source/configs/where_single_line/true.rs | 24 + tests/source/configs/wrap_comments/false.rs | 8 + tests/source/configs/wrap_comments/true.rs | 15 + .../source/control-brace-style-always-next-line.rs | 44 + .../source/control-brace-style-always-same-line.rs | 44 + tests/source/doc.rs | 5 + .../source/else-if-brace-style-always-next-line.rs | 54 ++ .../source/else-if-brace-style-always-same-line.rs | 54 ++ .../else-if-brace-style-closing-next-line.rs | 54 ++ tests/source/empty_file.rs | 0 tests/source/enum.rs | 194 +++++ tests/source/expr-block.rs | 286 +++++++ tests/source/expr.rs | 372 +++++++++ tests/source/extern.rs | 60 ++ tests/source/extern_not_explicit.rs | 14 + tests/source/file-lines-1.rs | 29 + tests/source/file-lines-2.rs | 29 + tests/source/file-lines-3.rs | 30 + tests/source/file-lines-4.rs | 30 + tests/source/file-lines-5.rs | 17 + tests/source/file-lines-6.rs | 18 + tests/source/file-lines-item.rs | 22 + tests/source/fn-custom-2.rs | 36 + tests/source/fn-custom-3.rs | 32 + tests/source/fn-custom-4.rs | 14 + tests/source/fn-custom-6.rs | 41 + tests/source/fn-custom-7.rs | 25 + tests/source/fn-custom-8.rs | 49 ++ tests/source/fn-custom.rs | 13 + tests/source/fn-simple.rs | 66 ++ tests/source/fn-single-line.rs | 79 ++ tests/source/fn_args_density-vertical.rs | 33 + tests/source/fn_args_indent-block.rs | 78 ++ tests/source/hard-tabs.rs | 85 ++ tests/source/hello.rs | 6 + tests/source/hello2.rs | 8 + tests/source/immovable_generators.rs | 7 + tests/source/impls.rs | 154 ++++ tests/source/imports-reorder-lines-and-items.rs | 10 + tests/source/imports-reorder-lines.rs | 34 + tests/source/imports-reorder.rs | 6 + tests/source/imports.rs | 89 ++ tests/source/issue-1021.rs | 22 + tests/source/issue-1049.rs | 18 + tests/source/issue-1111.rs | 1 + tests/source/issue-1120.rs | 9 + tests/source/issue-1124.rs | 16 + tests/source/issue-1127.rs | 23 + tests/source/issue-1158.rs | 3 + tests/source/issue-1177.rs | 7 + tests/source/issue-1192.rs | 3 + tests/source/issue-1211.rs | 15 + tests/source/issue-1216.rs | 5 + tests/source/issue-1239.rs | 9 + tests/source/issue-1278.rs | 9 + tests/source/issue-1350.rs | 16 + tests/source/issue-1366.rs | 12 + tests/source/issue-1468.rs | 27 + tests/source/issue-1693.rs | 3 + tests/source/issue-1800.rs | 3 + tests/source/issue-1914.rs | 6 + tests/source/issue-2025.rs | 8 + tests/source/issue-2111.rs | 28 + tests/source/issue-2164.rs | 4 + tests/source/issue-2179.rs | 35 + tests/source/issue-2256.rs | 12 + tests/source/issue-2342.rs | 5 + tests/source/issue-2446.rs | 11 + tests/source/issue-2479.rs | 2 + tests/source/issue-447.rs | 39 + tests/source/issue-510.rs | 37 + tests/source/issue-811.rs | 19 + tests/source/issue-850.rs | 1 + tests/source/issue-855.rs | 20 + tests/source/issue-913.rs | 22 + tests/source/issue-945.rs | 5 + tests/source/issue-977.rs | 8 + tests/source/item-brace-style-always-next-line.rs | 29 + tests/source/item-brace-style-prefer-same-line.rs | 29 + tests/source/item-brace-style-same-line-where.rs | 31 + tests/source/large-block.rs | 5 + tests/source/large_vec.rs | 29 + tests/source/lazy_static.rs | 37 + tests/source/long-match-arms-brace-newline.rs | 15 + tests/source/long_field_access.rs | 3 + tests/source/loop.rs | 29 + tests/source/macro_not_expr.rs | 7 + tests/source/macro_rules.rs | 114 +++ tests/source/macros.rs | 342 ++++++++ tests/source/markdown-comment-with-options.rs | 17 + tests/source/markdown-comment.rs | 15 + tests/source/match-block-trailing-comma.rs | 14 + tests/source/match-nowrap-trailing-comma.rs | 15 + tests/source/match-nowrap.rs | 12 + tests/source/match.rs | 464 +++++++++++ tests/source/max-line-length-in-chars.rs | 4 + tests/source/mod-1.rs | 29 + tests/source/mod-2.rs | 4 + tests/source/mod_skip_child.rs | 2 + tests/source/multiple.rs | 134 +++ tests/source/nested-if-else.rs | 11 + tests/source/nested_skipped/mod.rs | 3 + tests/source/nestedmod/mod.rs | 13 + tests/source/nestedmod/mod2a.rs | 4 + tests/source/nestedmod/mod2b.rs | 3 + tests/source/nestedmod/mod2c.rs | 3 + tests/source/nestedmod/mymod1/mod3a.rs | 2 + tests/source/nestedmod/submod2/a.rs | 6 + tests/source/nestedmod/submod2/mod.rs | 5 + tests/source/no_new_line_beginning.rs | 2 + tests/source/other.rs | 5 + tests/source/paths.rs | 25 + tests/source/pattern-condense-wildcards.rs | 12 + tests/source/pattern.rs | 65 ++ tests/source/pub-restricted.rs | 64 ++ tests/source/remove_blank_lines.rs | 44 + tests/source/single-line-if-else.rs | 49 ++ tests/source/soft-wrapping.rs | 15 + tests/source/space-not-before-newline.rs | 8 + tests/source/spaces-around-ranges.rs | 15 + tests/source/static.rs | 23 + tests/source/string-lit-2.rs | 25 + tests/source/string-lit.rs | 62 ++ tests/source/string_punctuation.rs | 8 + tests/source/struct-field-attributes.rs | 52 ++ tests/source/struct_lits.rs | 144 ++++ tests/source/struct_lits_multiline.rs | 81 ++ tests/source/struct_lits_visual.rs | 47 ++ tests/source/struct_lits_visual_multiline.rs | 45 + tests/source/struct_tuple_visual.rs | 37 + tests/source/structs.rs | 283 +++++++ tests/source/trailing-comma-never.rs | 41 + tests/source/trailing_commas.rs | 47 ++ tests/source/trait.rs | 94 +++ tests/source/try-conversion.rs | 18 + tests/source/tuple.rs | 52 ++ tests/source/type-ascription.rs | 9 + tests/source/type.rs | 25 + tests/source/type_alias.rs | 34 + tests/source/unions.rs | 195 +++++ tests/source/where-clause-rfc.rs | 58 ++ tests/source/where-clause.rs | 58 ++ tests/target/assignment.rs | 36 + tests/target/associated-items.rs | 3 + tests/target/associated-types-bounds-wrapping.rs | 7 + tests/target/associated_type_defaults.rs | 4 + tests/target/attrib-extern-crate.rs | 17 + tests/target/attrib.rs | 160 ++++ tests/target/big-impl-block.rs | 87 ++ tests/target/big-impl-visual.rs | 73 ++ tests/target/break-and-continue.rs | 23 + tests/target/catch.rs | 21 + tests/target/chains-visual.rs | 159 ++++ tests/target/chains.rs | 261 ++++++ tests/target/closure-block-inside-macro.rs | 11 + tests/target/closure.rs | 248 ++++++ tests/target/comment-inside-const.rs | 9 + tests/target/comment-not-disappear.rs | 36 + tests/target/comment.rs | 95 +++ tests/target/comment2.rs | 5 + tests/target/comment3.rs | 6 + tests/target/comment4.rs | 51 ++ tests/target/comment5.rs | 16 + tests/target/comment_crlf_newline.rs | 4 + tests/target/comments-fn.rs | 39 + tests/target/configs/blank_lines_lower_bound/1.rs | 16 + .../configs/brace_style/fn_always_next_line.rs | 19 + .../configs/brace_style/fn_prefer_same_line.rs | 16 + .../configs/brace_style/fn_same_line_where.rs | 17 + .../configs/brace_style/item_always_next_line.rs | 27 + .../configs/brace_style/item_prefer_same_line.rs | 18 + .../configs/brace_style/item_same_line_where.rs | 19 + tests/target/configs/combine_control_expr/false.rs | 133 +++ tests/target/configs/combine_control_expr/true.rs | 121 +++ tests/target/configs/comment_width/above.rs | 8 + tests/target/configs/comment_width/below.rs | 7 + tests/target/configs/comment_width/ignore.rs | 7 + .../configs/condense_wildcard_suffixes/false.rs | 6 + .../configs/condense_wildcard_suffixes/true.rs | 6 + .../control_brace_style/always_next_line.rs | 18 + .../control_brace_style/always_same_line.rs | 14 + .../control_brace_style/closing_next_line.rs | 15 + .../target/configs/disable_all_formatting/false.rs | 10 + .../target/configs/disable_all_formatting/true.rs | 6 + .../target/configs/empty_item_single_line/false.rs | 15 + .../target/configs/empty_item_single_line/true.rs | 10 + .../target/configs/error_on_line_overflow/false.rs | 6 + tests/target/configs/error_on_unformatted/false.rs | 12 + tests/target/configs/fn_args_density/compressed.rs | 22 + tests/target/configs/fn_args_density/tall.rs | 32 + tests/target/configs/fn_args_density/vertical.rs | 42 + tests/target/configs/fn_single_line/false.rs | 11 + tests/target/configs/fn_single_line/true.rs | 9 + tests/target/configs/force_explicit_abi/false.rs | 6 + tests/target/configs/force_explicit_abi/true.rs | 6 + .../target/configs/force_multiline_block/false.rs | 20 + tests/target/configs/force_multiline_block/true.rs | 22 + tests/target/configs/format_strings/false.rs | 8 + tests/target/configs/format_strings/true.rs | 9 + tests/target/configs/hard_tabs/false.rs | 6 + tests/target/configs/hard_tabs/true.rs | 6 + tests/target/configs/imports_indent/block.rs | 7 + .../configs/imports_layout/horizontal_vertical.rs | 18 + tests/target/configs/imports_layout/mixed.rs | 9 + tests/target/configs/indent_style/block_args.rs | 47 ++ tests/target/configs/indent_style/block_array.rs | 14 + tests/target/configs/indent_style/block_call.rs | 149 ++++ tests/target/configs/indent_style/block_chain.rs | 12 + tests/target/configs/indent_style/block_generic.rs | 22 + .../configs/indent_style/block_struct_lit.rs | 9 + .../configs/indent_style/block_tab_spaces_call.rs | 14 + .../indent_style/block_trailing_comma_call.rs | 11 + .../configs/indent_style/block_where_pred.rs | 12 + tests/target/configs/indent_style/default.rs | 11 + tests/target/configs/indent_style/rfc_control.rs | 39 + tests/target/configs/indent_style/rfc_where.rs | 12 + tests/target/configs/indent_style/visual_args.rs | 40 + tests/target/configs/indent_style/visual_array.rs | 12 + tests/target/configs/indent_style/visual_call.rs | 13 + tests/target/configs/indent_style/visual_chain.rs | 11 + .../target/configs/indent_style/visual_generics.rs | 20 + .../configs/indent_style/visual_struct_lit.rs | 7 + .../configs/indent_style/visual_trailing_comma.rs | 7 + .../configs/indent_style/visual_where_pred.rs | 11 + tests/target/configs/match_arm_blocks/false.rs | 10 + tests/target/configs/match_arm_blocks/true.rs | 11 + .../configs/match_block_trailing_comma/false.rs | 11 + .../configs/match_block_trailing_comma/true.rs | 11 + tests/target/configs/merge_derives/true.rs | 40 + tests/target/configs/normalize_comments/false.rs | 13 + tests/target/configs/normalize_comments/true.rs | 13 + .../target/configs/reorder_extern_crates/false.rs | 11 + tests/target/configs/reorder_extern_crates/true.rs | 11 + .../target/configs/reorder_imported_names/false.rs | 4 + .../target/configs/reorder_imported_names/true.rs | 4 + tests/target/configs/reorder_imports/false.rs | 7 + tests/target/configs/reorder_imports/true.rs | 19 + .../configs/reorder_imports_in_group/false.rs | 12 + .../configs/reorder_imports_in_group/true.rs | 13 + tests/target/configs/reorder_modules/dolor/mod.rs | 1 + tests/target/configs/reorder_modules/false.rs | 7 + tests/target/configs/reorder_modules/ipsum/mod.rs | 1 + tests/target/configs/reorder_modules/lorem/mod.rs | 1 + tests/target/configs/reorder_modules/sit/mod.rs | 1 + tests/target/configs/reorder_modules/true.rs | 7 + tests/target/configs/skip_children/true.rs | 3 + tests/target/configs/space_before_colon/true.rs | 11 + tests/target/configs/spaces_around_ranges/false.rs | 22 + tests/target/configs/spaces_around_ranges/true.rs | 22 + .../spaces_within_parens_and_brackets/false.rs | 7 + .../spaces_within_parens_and_brackets/true.rs | 145 ++++ .../configs/struct_field_align_threshold/20.rs | 467 +++++++++++ .../target/configs/struct_lit_single_line/false.rs | 9 + tests/target/configs/tab_spaces/2.rs | 14 + tests/target/configs/tab_spaces/4.rs | 14 + tests/target/configs/trailing_comma/always.rs | 14 + tests/target/configs/trailing_comma/never.rs | 35 + tests/target/configs/trailing_comma/vertical.rs | 14 + tests/target/configs/trailing_semicolon/false.rs | 27 + tests/target/configs/trailing_semicolon/true.rs | 27 + .../configs/type_punctuation_density/compressed.rs | 41 + .../configs/type_punctuation_density/wide.rs | 41 + .../configs/use_field_init_shorthand/false.rs | 15 + .../configs/use_field_init_shorthand/true.rs | 15 + tests/target/configs/use_try_shorthand/false.rs | 6 + tests/target/configs/use_try_shorthand/true.rs | 6 + tests/target/configs/where_single_line/true.rs | 28 + tests/target/configs/wrap_comments/false.rs | 8 + tests/target/configs/wrap_comments/true.rs | 20 + .../target/control-brace-style-always-next-line.rs | 50 ++ .../target/control-brace-style-always-same-line.rs | 42 + tests/target/doc.rs | 5 + .../target/else-if-brace-style-always-next-line.rs | 53 ++ .../target/else-if-brace-style-always-same-line.rs | 45 + .../else-if-brace-style-closing-next-line.rs | 49 ++ .../empty-tuple-no-conversion-to-unit-struct.rs | 12 + tests/target/empty_file.rs | 1 + tests/target/enum.rs | 255 ++++++ tests/target/expr-block.rs | 299 +++++++ tests/target/expr.rs | 397 +++++++++ tests/target/extern.rs | 73 ++ tests/target/extern_not_explicit.rs | 18 + tests/target/file-lines-1.rs | 29 + tests/target/file-lines-2.rs | 24 + tests/target/file-lines-3.rs | 25 + tests/target/file-lines-4.rs | 30 + tests/target/file-lines-5.rs | 17 + tests/target/file-lines-6.rs | 18 + tests/target/file-lines-item.rs | 22 + tests/target/fn-args-with-last-line-comment.rs | 24 + tests/target/fn-custom-2.rs | 78 ++ tests/target/fn-custom-3.rs | 72 ++ tests/target/fn-custom-4.rs | 27 + tests/target/fn-custom-6.rs | 72 ++ tests/target/fn-custom-7.rs | 41 + tests/target/fn-custom-8.rs | 78 ++ tests/target/fn-custom.rs | 19 + tests/target/fn-simple.rs | 107 +++ tests/target/fn-single-line.rs | 70 ++ tests/target/fn-ty.rs | 14 + tests/target/fn.rs | 122 +++ tests/target/fn_args_density-vertical.rs | 39 + tests/target/fn_args_indent-block.rs | 144 ++++ tests/target/fn_once.rs | 8 + tests/target/hard-tabs.rs | 99 +++ tests/target/hello.rs | 8 + tests/target/immovable_generators.rs | 7 + tests/target/impl.rs | 43 + tests/target/impls.rs | 219 +++++ tests/target/import-fencepost-length.rs | 4 + tests/target/imports-reorder-lines-and-items.rs | 10 + tests/target/imports-reorder-lines.rs | 33 + tests/target/imports-reorder.rs | 6 + tests/target/imports.rs | 88 ++ tests/target/indented-impl.rs | 13 + tests/target/issue-1021.rs | 22 + tests/target/issue-1049.rs | 29 + tests/target/issue-1055.rs | 3 + tests/target/issue-1111.rs | 1 + tests/target/issue-1113.rs | 33 + tests/target/issue-1120.rs | 11 + tests/target/issue-1124.rs | 20 + tests/target/issue-1127.rs | 25 + tests/target/issue-1158.rs | 3 + tests/target/issue-1177.rs | 7 + tests/target/issue-1192.rs | 3 + tests/target/issue-1211.rs | 13 + tests/target/issue-1214.rs | 8 + tests/target/issue-1216.rs | 5 + tests/target/issue-1239.rs | 10 + tests/target/issue-1247.rs | 8 + tests/target/issue-1255.rs | 10 + tests/target/issue-1278.rs | 9 + tests/target/issue-1350.rs | 14 + tests/target/issue-1366.rs | 13 + tests/target/issue-1397.rs | 25 + tests/target/issue-1468.rs | 29 + tests/target/issue-1598.rs | 6 + tests/target/issue-1624.rs | 6 + tests/target/issue-1681.rs | 20 + tests/target/issue-1693.rs | 10 + tests/target/issue-1703.rs | 9 + tests/target/issue-1800.rs | 3 + tests/target/issue-1802.rs | 10 + tests/target/issue-1824.rs | 5 + tests/target/issue-1914.rs | 7 + tests/target/issue-2025.rs | 4 + tests/target/issue-2103.rs | 14 + tests/target/issue-2111.rs | 26 + tests/target/issue-2123.rs | 6 + tests/target/issue-2164.rs | 132 +++ tests/target/issue-2179.rs | 36 + tests/target/issue-2197.rs | 18 + tests/target/issue-2256.rs | 7 + tests/target/issue-2324.rs | 7 + tests/target/issue-2329.rs | 30 + tests/target/issue-2342.rs | 6 + tests/target/issue-2346.rs | 4 + tests/target/issue-2401.rs | 7 + tests/target/issue-2446.rs | 9 + tests/target/issue-2479.rs | 12 + tests/target/issue-447.rs | 40 + tests/target/issue-510.rs | 41 + tests/target/issue-64.rs | 7 + tests/target/issue-691.rs | 9 + tests/target/issue-770.rs | 10 + tests/target/issue-811.rs | 19 + tests/target/issue-831.rs | 9 + tests/target/issue-850.rs | 1 + tests/target/issue-855.rs | 27 + tests/target/issue-913.rs | 24 + tests/target/issue-945.rs | 17 + tests/target/issue-977.rs | 16 + tests/target/item-brace-style-always-next-line.rs | 42 + tests/target/item-brace-style-prefer-same-line.rs | 35 + tests/target/item-brace-style-same-line-where.rs | 39 + tests/target/large-block.rs | 5 + tests/target/large_vec.rs | 42 + tests/target/lazy_static.rs | 39 + tests/target/long-fn-1.rs | 21 + tests/target/long-match-arms-brace-newline.rs | 15 + tests/target/long_field_access.rs | 4 + tests/target/loop.rs | 34 + tests/target/macro_not_expr.rs | 7 + tests/target/macro_rules.rs | 105 +++ tests/target/macros.rs | 917 +++++++++++++++++++++ tests/target/markdown-comment-with-options.rs | 17 + tests/target/markdown-comment.rs | 15 + tests/target/match-block-trailing-comma.rs | 16 + tests/target/match-nowrap-trailing-comma.rs | 17 + tests/target/match-nowrap.rs | 13 + tests/target/match.rs | 495 +++++++++++ tests/target/max-line-length-in-chars.rs | 4 + tests/target/mod-1.rs | 38 + tests/target/mod-2.rs | 5 + tests/target/mod_skip_child.rs | 2 + tests/target/mulit-file.rs | 10 + tests/target/multiple.rs | 178 ++++ tests/target/nested-if-else.rs | 11 + tests/target/nested-visual-block.rs | 59 ++ tests/target/nested_skipped/mod.rs | 3 + tests/target/nestedmod/mod.rs | 12 + tests/target/nestedmod/mod2a.rs | 4 + tests/target/nestedmod/mod2b.rs | 2 + tests/target/nestedmod/mod2c.rs | 3 + tests/target/nestedmod/mymod1/mod3a.rs | 2 + tests/target/nestedmod/submod2/a.rs | 6 + tests/target/nestedmod/submod2/mod.rs | 5 + tests/target/no_new_line_beginning.rs | 1 + tests/target/other.rs | 5 + tests/target/paths.rs | 28 + tests/target/pattern-condense-wildcards.rs | 12 + tests/target/pattern.rs | 77 ++ tests/target/pub-restricted.rs | 64 ++ tests/target/remove_blank_lines.rs | 28 + tests/target/single-line-if-else.rs | 58 ++ tests/target/skip.rs | 87 ++ tests/target/skip_mod.rs | 3 + tests/target/soft-wrapping.rs | 15 + tests/target/space-not-before-newline.rs | 8 + tests/target/spaces-around-ranges.rs | 15 + tests/target/static.rs | 27 + tests/target/string-lit-2.rs | 25 + tests/target/string-lit-custom.rs | 22 + tests/target/string-lit.rs | 64 ++ tests/target/string_punctuation.rs | 15 + tests/target/struct-field-attributes.rs | 56 ++ tests/target/struct_lits.rs | 191 +++++ tests/target/struct_lits_multiline.rs | 117 +++ tests/target/struct_lits_visual.rs | 50 ++ tests/target/struct_lits_visual_multiline.rs | 50 ++ tests/target/struct_tuple_visual.rs | 37 + tests/target/structs.rs | 332 ++++++++ tests/target/trailing-comma-never.rs | 31 + tests/target/trailing_commas.rs | 103 +++ tests/target/trait.rs | 132 +++ tests/target/try-conversion.rs | 27 + tests/target/tuple.rs | 89 ++ tests/target/type-ascription.rs | 12 + tests/target/type.rs | 31 + tests/target/type_alias.rs | 76 ++ tests/target/unindent_if_else_cond_comment.rs | 27 + tests/target/unions.rs | 196 +++++ tests/target/where-clause-rfc.rs | 128 +++ tests/target/where-clause.rs | 107 +++ tests/writemode/source/fn-single-line.rs | 80 ++ tests/writemode/source/modified.rs | 14 + tests/writemode/target/checkstyle.xml | 2 + tests/writemode/target/modified.txt | 5 + 1136 files changed, 22003 insertions(+), 22207 deletions(-) delete mode 100644 cargo-fmt/Cargo.toml delete mode 100644 git-rustfmt/Cargo.toml delete mode 100644 rustfmt-bin/Cargo.toml delete mode 100644 rustfmt-bin/build.rs delete mode 100644 rustfmt-config/Cargo.toml delete mode 100644 rustfmt-config/README.md delete mode 100644 rustfmt-core/Cargo.toml delete mode 100644 rustfmt-core/README.md delete mode 100644 rustfmt-core/tests/config/disable_all_formatting.toml delete mode 100755 rustfmt-core/tests/config/issue-1111.toml delete mode 100644 rustfmt-core/tests/config/small_tabs.toml delete mode 100644 rustfmt-core/tests/coverage/source/comments.rs delete mode 100644 rustfmt-core/tests/coverage/target/comments.rs delete mode 100644 rustfmt-core/tests/lib.rs delete mode 100644 rustfmt-core/tests/source/assignment.rs delete mode 100644 rustfmt-core/tests/source/associated-types-bounds-wrapping.rs delete mode 100644 rustfmt-core/tests/source/attrib.rs delete mode 100644 rustfmt-core/tests/source/big-impl-block.rs delete mode 100644 rustfmt-core/tests/source/big-impl-visual.rs delete mode 100644 rustfmt-core/tests/source/break-and-continue.rs delete mode 100644 rustfmt-core/tests/source/catch.rs delete mode 100644 rustfmt-core/tests/source/chains-visual.rs delete mode 100644 rustfmt-core/tests/source/chains.rs delete mode 100644 rustfmt-core/tests/source/closure-block-inside-macro.rs delete mode 100644 rustfmt-core/tests/source/closure.rs delete mode 100644 rustfmt-core/tests/source/comment.rs delete mode 100644 rustfmt-core/tests/source/comment2.rs delete mode 100644 rustfmt-core/tests/source/comment3.rs delete mode 100644 rustfmt-core/tests/source/comment4.rs delete mode 100644 rustfmt-core/tests/source/comment5.rs delete mode 100644 rustfmt-core/tests/source/comment_crlf_newline.rs delete mode 100644 rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs delete mode 100644 rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs delete mode 100644 rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs delete mode 100644 rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs delete mode 100644 rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs delete mode 100644 rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs delete mode 100644 rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs delete mode 100644 rustfmt-core/tests/source/configs/comment_width/above.rs delete mode 100644 rustfmt-core/tests/source/configs/comment_width/below.rs delete mode 100644 rustfmt-core/tests/source/configs/comment_width/ignore.rs delete mode 100644 rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs delete mode 100644 rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs delete mode 100644 rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs delete mode 100644 rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs delete mode 100644 rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs delete mode 100644 rustfmt-core/tests/source/configs/disable_all_formatting/false.rs delete mode 100644 rustfmt-core/tests/source/configs/disable_all_formatting/true.rs delete mode 100644 rustfmt-core/tests/source/configs/empty_item_single_line/false.rs delete mode 100644 rustfmt-core/tests/source/configs/empty_item_single_line/true.rs delete mode 100644 rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs delete mode 100644 rustfmt-core/tests/source/configs/fn_args_density/compressed.rs delete mode 100644 rustfmt-core/tests/source/configs/fn_args_density/tall.rs delete mode 100644 rustfmt-core/tests/source/configs/fn_args_density/vertical.rs delete mode 100644 rustfmt-core/tests/source/configs/fn_single_line/false.rs delete mode 100644 rustfmt-core/tests/source/configs/fn_single_line/true.rs delete mode 100644 rustfmt-core/tests/source/configs/force_explicit_abi/false.rs delete mode 100644 rustfmt-core/tests/source/configs/force_explicit_abi/true.rs delete mode 100644 rustfmt-core/tests/source/configs/force_multiline_block/false.rs delete mode 100644 rustfmt-core/tests/source/configs/force_multiline_block/true.rs delete mode 100644 rustfmt-core/tests/source/configs/format_strings/false.rs delete mode 100644 rustfmt-core/tests/source/configs/format_strings/true.rs delete mode 100644 rustfmt-core/tests/source/configs/hard_tabs/false.rs delete mode 100644 rustfmt-core/tests/source/configs/hard_tabs/true.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_args.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_array.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_call.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_chain.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_generic.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/default.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/rfc_where.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_args.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_array.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_call.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_chain.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_generics.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs delete mode 100644 rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs delete mode 100644 rustfmt-core/tests/source/configs/match_arm_blocks/false.rs delete mode 100644 rustfmt-core/tests/source/configs/match_arm_blocks/true.rs delete mode 100644 rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs delete mode 100644 rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs delete mode 100644 rustfmt-core/tests/source/configs/merge_derives/true.rs delete mode 100644 rustfmt-core/tests/source/configs/normalize_comments/false.rs delete mode 100644 rustfmt-core/tests/source/configs/normalize_comments/true.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_imported_names/false.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_imported_names/true.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_imports/false.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_imports/true.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_modules/false.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs delete mode 100644 rustfmt-core/tests/source/configs/reorder_modules/true.rs delete mode 100644 rustfmt-core/tests/source/configs/skip_children/true.rs delete mode 100644 rustfmt-core/tests/source/configs/space_before_colon/true.rs delete mode 100644 rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs delete mode 100644 rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs delete mode 100644 rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs delete mode 100644 rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs delete mode 100644 rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs delete mode 100644 rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs delete mode 100644 rustfmt-core/tests/source/configs/tab_spaces/2.rs delete mode 100644 rustfmt-core/tests/source/configs/tab_spaces/4.rs delete mode 100644 rustfmt-core/tests/source/configs/trailing_comma/always.rs delete mode 100644 rustfmt-core/tests/source/configs/trailing_comma/never.rs delete mode 100644 rustfmt-core/tests/source/configs/trailing_comma/vertical.rs delete mode 100644 rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs delete mode 100644 rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs delete mode 100644 rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs delete mode 100644 rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs delete mode 100644 rustfmt-core/tests/source/configs/use_try_shorthand/false.rs delete mode 100644 rustfmt-core/tests/source/configs/use_try_shorthand/true.rs delete mode 100644 rustfmt-core/tests/source/configs/where_single_line/true.rs delete mode 100644 rustfmt-core/tests/source/configs/wrap_comments/false.rs delete mode 100644 rustfmt-core/tests/source/configs/wrap_comments/true.rs delete mode 100644 rustfmt-core/tests/source/control-brace-style-always-next-line.rs delete mode 100644 rustfmt-core/tests/source/control-brace-style-always-same-line.rs delete mode 100644 rustfmt-core/tests/source/doc.rs delete mode 100644 rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs delete mode 100644 rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs delete mode 100644 rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs delete mode 100644 rustfmt-core/tests/source/empty_file.rs delete mode 100644 rustfmt-core/tests/source/enum.rs delete mode 100644 rustfmt-core/tests/source/expr-block.rs delete mode 100644 rustfmt-core/tests/source/expr.rs delete mode 100644 rustfmt-core/tests/source/extern.rs delete mode 100644 rustfmt-core/tests/source/extern_not_explicit.rs delete mode 100644 rustfmt-core/tests/source/file-lines-1.rs delete mode 100644 rustfmt-core/tests/source/file-lines-2.rs delete mode 100644 rustfmt-core/tests/source/file-lines-3.rs delete mode 100644 rustfmt-core/tests/source/file-lines-4.rs delete mode 100644 rustfmt-core/tests/source/file-lines-5.rs delete mode 100644 rustfmt-core/tests/source/file-lines-6.rs delete mode 100644 rustfmt-core/tests/source/file-lines-item.rs delete mode 100644 rustfmt-core/tests/source/fn-custom-2.rs delete mode 100644 rustfmt-core/tests/source/fn-custom-3.rs delete mode 100644 rustfmt-core/tests/source/fn-custom-4.rs delete mode 100644 rustfmt-core/tests/source/fn-custom-6.rs delete mode 100644 rustfmt-core/tests/source/fn-custom-7.rs delete mode 100644 rustfmt-core/tests/source/fn-custom-8.rs delete mode 100644 rustfmt-core/tests/source/fn-custom.rs delete mode 100644 rustfmt-core/tests/source/fn-simple.rs delete mode 100644 rustfmt-core/tests/source/fn-single-line.rs delete mode 100644 rustfmt-core/tests/source/fn_args_density-vertical.rs delete mode 100644 rustfmt-core/tests/source/fn_args_indent-block.rs delete mode 100644 rustfmt-core/tests/source/hard-tabs.rs delete mode 100644 rustfmt-core/tests/source/hello.rs delete mode 100644 rustfmt-core/tests/source/hello2.rs delete mode 100644 rustfmt-core/tests/source/immovable_generators.rs delete mode 100644 rustfmt-core/tests/source/impls.rs delete mode 100644 rustfmt-core/tests/source/imports-reorder-lines-and-items.rs delete mode 100644 rustfmt-core/tests/source/imports-reorder-lines.rs delete mode 100644 rustfmt-core/tests/source/imports-reorder.rs delete mode 100644 rustfmt-core/tests/source/imports.rs delete mode 100644 rustfmt-core/tests/source/issue-1021.rs delete mode 100644 rustfmt-core/tests/source/issue-1049.rs delete mode 100644 rustfmt-core/tests/source/issue-1111.rs delete mode 100644 rustfmt-core/tests/source/issue-1120.rs delete mode 100644 rustfmt-core/tests/source/issue-1124.rs delete mode 100644 rustfmt-core/tests/source/issue-1127.rs delete mode 100644 rustfmt-core/tests/source/issue-1158.rs delete mode 100644 rustfmt-core/tests/source/issue-1177.rs delete mode 100644 rustfmt-core/tests/source/issue-1192.rs delete mode 100644 rustfmt-core/tests/source/issue-1211.rs delete mode 100644 rustfmt-core/tests/source/issue-1216.rs delete mode 100644 rustfmt-core/tests/source/issue-1239.rs delete mode 100644 rustfmt-core/tests/source/issue-1278.rs delete mode 100644 rustfmt-core/tests/source/issue-1350.rs delete mode 100644 rustfmt-core/tests/source/issue-1366.rs delete mode 100644 rustfmt-core/tests/source/issue-1468.rs delete mode 100644 rustfmt-core/tests/source/issue-1693.rs delete mode 100644 rustfmt-core/tests/source/issue-1800.rs delete mode 100644 rustfmt-core/tests/source/issue-1914.rs delete mode 100644 rustfmt-core/tests/source/issue-2025.rs delete mode 100644 rustfmt-core/tests/source/issue-2111.rs delete mode 100644 rustfmt-core/tests/source/issue-2164.rs delete mode 100644 rustfmt-core/tests/source/issue-2179.rs delete mode 100644 rustfmt-core/tests/source/issue-2256.rs delete mode 100644 rustfmt-core/tests/source/issue-2342.rs delete mode 100644 rustfmt-core/tests/source/issue-2446.rs delete mode 100644 rustfmt-core/tests/source/issue-2479.rs delete mode 100644 rustfmt-core/tests/source/issue-447.rs delete mode 100644 rustfmt-core/tests/source/issue-510.rs delete mode 100644 rustfmt-core/tests/source/issue-811.rs delete mode 100644 rustfmt-core/tests/source/issue-850.rs delete mode 100644 rustfmt-core/tests/source/issue-855.rs delete mode 100644 rustfmt-core/tests/source/issue-913.rs delete mode 100644 rustfmt-core/tests/source/issue-945.rs delete mode 100644 rustfmt-core/tests/source/issue-977.rs delete mode 100644 rustfmt-core/tests/source/item-brace-style-always-next-line.rs delete mode 100644 rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs delete mode 100644 rustfmt-core/tests/source/item-brace-style-same-line-where.rs delete mode 100644 rustfmt-core/tests/source/large-block.rs delete mode 100644 rustfmt-core/tests/source/large_vec.rs delete mode 100644 rustfmt-core/tests/source/lazy_static.rs delete mode 100644 rustfmt-core/tests/source/long-match-arms-brace-newline.rs delete mode 100644 rustfmt-core/tests/source/long_field_access.rs delete mode 100644 rustfmt-core/tests/source/loop.rs delete mode 100644 rustfmt-core/tests/source/macro_not_expr.rs delete mode 100644 rustfmt-core/tests/source/macro_rules.rs delete mode 100644 rustfmt-core/tests/source/macros.rs delete mode 100644 rustfmt-core/tests/source/markdown-comment-with-options.rs delete mode 100644 rustfmt-core/tests/source/markdown-comment.rs delete mode 100644 rustfmt-core/tests/source/match-block-trailing-comma.rs delete mode 100644 rustfmt-core/tests/source/match-nowrap-trailing-comma.rs delete mode 100644 rustfmt-core/tests/source/match-nowrap.rs delete mode 100644 rustfmt-core/tests/source/match.rs delete mode 100644 rustfmt-core/tests/source/max-line-length-in-chars.rs delete mode 100644 rustfmt-core/tests/source/mod-1.rs delete mode 100644 rustfmt-core/tests/source/mod-2.rs delete mode 100644 rustfmt-core/tests/source/mod_skip_child.rs delete mode 100644 rustfmt-core/tests/source/multiple.rs delete mode 100644 rustfmt-core/tests/source/nested-if-else.rs delete mode 100644 rustfmt-core/tests/source/nested_skipped/mod.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/mod.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/mod2a.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/mod2b.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/mod2c.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/submod2/a.rs delete mode 100644 rustfmt-core/tests/source/nestedmod/submod2/mod.rs delete mode 100644 rustfmt-core/tests/source/no_new_line_beginning.rs delete mode 100644 rustfmt-core/tests/source/other.rs delete mode 100644 rustfmt-core/tests/source/paths.rs delete mode 100644 rustfmt-core/tests/source/pattern-condense-wildcards.rs delete mode 100644 rustfmt-core/tests/source/pattern.rs delete mode 100644 rustfmt-core/tests/source/pub-restricted.rs delete mode 100644 rustfmt-core/tests/source/remove_blank_lines.rs delete mode 100644 rustfmt-core/tests/source/single-line-if-else.rs delete mode 100644 rustfmt-core/tests/source/soft-wrapping.rs delete mode 100644 rustfmt-core/tests/source/space-not-before-newline.rs delete mode 100644 rustfmt-core/tests/source/spaces-around-ranges.rs delete mode 100644 rustfmt-core/tests/source/static.rs delete mode 100644 rustfmt-core/tests/source/string-lit-2.rs delete mode 100644 rustfmt-core/tests/source/string-lit.rs delete mode 100644 rustfmt-core/tests/source/string_punctuation.rs delete mode 100644 rustfmt-core/tests/source/struct-field-attributes.rs delete mode 100644 rustfmt-core/tests/source/struct_lits.rs delete mode 100644 rustfmt-core/tests/source/struct_lits_multiline.rs delete mode 100644 rustfmt-core/tests/source/struct_lits_visual.rs delete mode 100644 rustfmt-core/tests/source/struct_lits_visual_multiline.rs delete mode 100644 rustfmt-core/tests/source/struct_tuple_visual.rs delete mode 100644 rustfmt-core/tests/source/structs.rs delete mode 100644 rustfmt-core/tests/source/trailing-comma-never.rs delete mode 100644 rustfmt-core/tests/source/trailing_commas.rs delete mode 100644 rustfmt-core/tests/source/trait.rs delete mode 100644 rustfmt-core/tests/source/try-conversion.rs delete mode 100644 rustfmt-core/tests/source/tuple.rs delete mode 100644 rustfmt-core/tests/source/type-ascription.rs delete mode 100644 rustfmt-core/tests/source/type.rs delete mode 100644 rustfmt-core/tests/source/type_alias.rs delete mode 100644 rustfmt-core/tests/source/unions.rs delete mode 100644 rustfmt-core/tests/source/where-clause-rfc.rs delete mode 100644 rustfmt-core/tests/source/where-clause.rs delete mode 100644 rustfmt-core/tests/target/assignment.rs delete mode 100644 rustfmt-core/tests/target/associated-items.rs delete mode 100644 rustfmt-core/tests/target/associated-types-bounds-wrapping.rs delete mode 100644 rustfmt-core/tests/target/associated_type_defaults.rs delete mode 100644 rustfmt-core/tests/target/attrib-extern-crate.rs delete mode 100644 rustfmt-core/tests/target/attrib.rs delete mode 100644 rustfmt-core/tests/target/big-impl-block.rs delete mode 100644 rustfmt-core/tests/target/big-impl-visual.rs delete mode 100644 rustfmt-core/tests/target/break-and-continue.rs delete mode 100644 rustfmt-core/tests/target/catch.rs delete mode 100644 rustfmt-core/tests/target/chains-visual.rs delete mode 100644 rustfmt-core/tests/target/chains.rs delete mode 100644 rustfmt-core/tests/target/closure-block-inside-macro.rs delete mode 100644 rustfmt-core/tests/target/closure.rs delete mode 100644 rustfmt-core/tests/target/comment-inside-const.rs delete mode 100644 rustfmt-core/tests/target/comment-not-disappear.rs delete mode 100644 rustfmt-core/tests/target/comment.rs delete mode 100644 rustfmt-core/tests/target/comment2.rs delete mode 100644 rustfmt-core/tests/target/comment3.rs delete mode 100644 rustfmt-core/tests/target/comment4.rs delete mode 100644 rustfmt-core/tests/target/comment5.rs delete mode 100644 rustfmt-core/tests/target/comment_crlf_newline.rs delete mode 100644 rustfmt-core/tests/target/comments-fn.rs delete mode 100644 rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs delete mode 100644 rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs delete mode 100644 rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs delete mode 100644 rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs delete mode 100644 rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs delete mode 100644 rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs delete mode 100644 rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs delete mode 100644 rustfmt-core/tests/target/configs/combine_control_expr/false.rs delete mode 100644 rustfmt-core/tests/target/configs/combine_control_expr/true.rs delete mode 100644 rustfmt-core/tests/target/configs/comment_width/above.rs delete mode 100644 rustfmt-core/tests/target/configs/comment_width/below.rs delete mode 100644 rustfmt-core/tests/target/configs/comment_width/ignore.rs delete mode 100644 rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs delete mode 100644 rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs delete mode 100644 rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs delete mode 100644 rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs delete mode 100644 rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs delete mode 100644 rustfmt-core/tests/target/configs/disable_all_formatting/false.rs delete mode 100644 rustfmt-core/tests/target/configs/disable_all_formatting/true.rs delete mode 100644 rustfmt-core/tests/target/configs/empty_item_single_line/false.rs delete mode 100644 rustfmt-core/tests/target/configs/empty_item_single_line/true.rs delete mode 100644 rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs delete mode 100644 rustfmt-core/tests/target/configs/error_on_unformatted/false.rs delete mode 100644 rustfmt-core/tests/target/configs/fn_args_density/compressed.rs delete mode 100644 rustfmt-core/tests/target/configs/fn_args_density/tall.rs delete mode 100644 rustfmt-core/tests/target/configs/fn_args_density/vertical.rs delete mode 100644 rustfmt-core/tests/target/configs/fn_single_line/false.rs delete mode 100644 rustfmt-core/tests/target/configs/fn_single_line/true.rs delete mode 100644 rustfmt-core/tests/target/configs/force_explicit_abi/false.rs delete mode 100644 rustfmt-core/tests/target/configs/force_explicit_abi/true.rs delete mode 100644 rustfmt-core/tests/target/configs/force_multiline_block/false.rs delete mode 100644 rustfmt-core/tests/target/configs/force_multiline_block/true.rs delete mode 100644 rustfmt-core/tests/target/configs/format_strings/false.rs delete mode 100644 rustfmt-core/tests/target/configs/format_strings/true.rs delete mode 100644 rustfmt-core/tests/target/configs/hard_tabs/false.rs delete mode 100644 rustfmt-core/tests/target/configs/hard_tabs/true.rs delete mode 100644 rustfmt-core/tests/target/configs/imports_indent/block.rs delete mode 100644 rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs delete mode 100644 rustfmt-core/tests/target/configs/imports_layout/mixed.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_args.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_array.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_call.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_chain.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_generic.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/default.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/rfc_control.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/rfc_where.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_args.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_array.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_call.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_chain.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_generics.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs delete mode 100644 rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs delete mode 100644 rustfmt-core/tests/target/configs/match_arm_blocks/false.rs delete mode 100644 rustfmt-core/tests/target/configs/match_arm_blocks/true.rs delete mode 100644 rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs delete mode 100644 rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs delete mode 100644 rustfmt-core/tests/target/configs/merge_derives/true.rs delete mode 100644 rustfmt-core/tests/target/configs/normalize_comments/false.rs delete mode 100644 rustfmt-core/tests/target/configs/normalize_comments/true.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_imported_names/false.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_imported_names/true.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_imports/false.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_imports/true.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_modules/false.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs delete mode 100644 rustfmt-core/tests/target/configs/reorder_modules/true.rs delete mode 100644 rustfmt-core/tests/target/configs/skip_children/true.rs delete mode 100644 rustfmt-core/tests/target/configs/space_before_colon/true.rs delete mode 100644 rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs delete mode 100644 rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs delete mode 100644 rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs delete mode 100644 rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs delete mode 100644 rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs delete mode 100644 rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs delete mode 100644 rustfmt-core/tests/target/configs/tab_spaces/2.rs delete mode 100644 rustfmt-core/tests/target/configs/tab_spaces/4.rs delete mode 100644 rustfmt-core/tests/target/configs/trailing_comma/always.rs delete mode 100644 rustfmt-core/tests/target/configs/trailing_comma/never.rs delete mode 100644 rustfmt-core/tests/target/configs/trailing_comma/vertical.rs delete mode 100644 rustfmt-core/tests/target/configs/trailing_semicolon/false.rs delete mode 100644 rustfmt-core/tests/target/configs/trailing_semicolon/true.rs delete mode 100644 rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs delete mode 100644 rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs delete mode 100644 rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs delete mode 100644 rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs delete mode 100644 rustfmt-core/tests/target/configs/use_try_shorthand/false.rs delete mode 100644 rustfmt-core/tests/target/configs/use_try_shorthand/true.rs delete mode 100644 rustfmt-core/tests/target/configs/where_single_line/true.rs delete mode 100644 rustfmt-core/tests/target/configs/wrap_comments/false.rs delete mode 100644 rustfmt-core/tests/target/configs/wrap_comments/true.rs delete mode 100644 rustfmt-core/tests/target/control-brace-style-always-next-line.rs delete mode 100644 rustfmt-core/tests/target/control-brace-style-always-same-line.rs delete mode 100644 rustfmt-core/tests/target/doc.rs delete mode 100644 rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs delete mode 100644 rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs delete mode 100644 rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs delete mode 100644 rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs delete mode 100644 rustfmt-core/tests/target/empty_file.rs delete mode 100644 rustfmt-core/tests/target/enum.rs delete mode 100644 rustfmt-core/tests/target/expr-block.rs delete mode 100644 rustfmt-core/tests/target/expr.rs delete mode 100644 rustfmt-core/tests/target/extern.rs delete mode 100644 rustfmt-core/tests/target/extern_not_explicit.rs delete mode 100644 rustfmt-core/tests/target/file-lines-1.rs delete mode 100644 rustfmt-core/tests/target/file-lines-2.rs delete mode 100644 rustfmt-core/tests/target/file-lines-3.rs delete mode 100644 rustfmt-core/tests/target/file-lines-4.rs delete mode 100644 rustfmt-core/tests/target/file-lines-5.rs delete mode 100644 rustfmt-core/tests/target/file-lines-6.rs delete mode 100644 rustfmt-core/tests/target/file-lines-item.rs delete mode 100644 rustfmt-core/tests/target/fn-args-with-last-line-comment.rs delete mode 100644 rustfmt-core/tests/target/fn-custom-2.rs delete mode 100644 rustfmt-core/tests/target/fn-custom-3.rs delete mode 100644 rustfmt-core/tests/target/fn-custom-4.rs delete mode 100644 rustfmt-core/tests/target/fn-custom-6.rs delete mode 100644 rustfmt-core/tests/target/fn-custom-7.rs delete mode 100644 rustfmt-core/tests/target/fn-custom-8.rs delete mode 100644 rustfmt-core/tests/target/fn-custom.rs delete mode 100644 rustfmt-core/tests/target/fn-simple.rs delete mode 100644 rustfmt-core/tests/target/fn-single-line.rs delete mode 100644 rustfmt-core/tests/target/fn-ty.rs delete mode 100644 rustfmt-core/tests/target/fn.rs delete mode 100644 rustfmt-core/tests/target/fn_args_density-vertical.rs delete mode 100644 rustfmt-core/tests/target/fn_args_indent-block.rs delete mode 100644 rustfmt-core/tests/target/fn_once.rs delete mode 100644 rustfmt-core/tests/target/hard-tabs.rs delete mode 100644 rustfmt-core/tests/target/hello.rs delete mode 100644 rustfmt-core/tests/target/immovable_generators.rs delete mode 100644 rustfmt-core/tests/target/impl.rs delete mode 100644 rustfmt-core/tests/target/impls.rs delete mode 100644 rustfmt-core/tests/target/import-fencepost-length.rs delete mode 100644 rustfmt-core/tests/target/imports-reorder-lines-and-items.rs delete mode 100644 rustfmt-core/tests/target/imports-reorder-lines.rs delete mode 100644 rustfmt-core/tests/target/imports-reorder.rs delete mode 100644 rustfmt-core/tests/target/imports.rs delete mode 100644 rustfmt-core/tests/target/indented-impl.rs delete mode 100644 rustfmt-core/tests/target/issue-1021.rs delete mode 100644 rustfmt-core/tests/target/issue-1049.rs delete mode 100644 rustfmt-core/tests/target/issue-1055.rs delete mode 100644 rustfmt-core/tests/target/issue-1111.rs delete mode 100644 rustfmt-core/tests/target/issue-1113.rs delete mode 100644 rustfmt-core/tests/target/issue-1120.rs delete mode 100644 rustfmt-core/tests/target/issue-1124.rs delete mode 100644 rustfmt-core/tests/target/issue-1127.rs delete mode 100644 rustfmt-core/tests/target/issue-1158.rs delete mode 100644 rustfmt-core/tests/target/issue-1177.rs delete mode 100644 rustfmt-core/tests/target/issue-1192.rs delete mode 100644 rustfmt-core/tests/target/issue-1211.rs delete mode 100644 rustfmt-core/tests/target/issue-1214.rs delete mode 100644 rustfmt-core/tests/target/issue-1216.rs delete mode 100644 rustfmt-core/tests/target/issue-1239.rs delete mode 100644 rustfmt-core/tests/target/issue-1247.rs delete mode 100644 rustfmt-core/tests/target/issue-1255.rs delete mode 100644 rustfmt-core/tests/target/issue-1278.rs delete mode 100644 rustfmt-core/tests/target/issue-1350.rs delete mode 100644 rustfmt-core/tests/target/issue-1366.rs delete mode 100644 rustfmt-core/tests/target/issue-1397.rs delete mode 100644 rustfmt-core/tests/target/issue-1468.rs delete mode 100644 rustfmt-core/tests/target/issue-1598.rs delete mode 100644 rustfmt-core/tests/target/issue-1624.rs delete mode 100644 rustfmt-core/tests/target/issue-1681.rs delete mode 100644 rustfmt-core/tests/target/issue-1693.rs delete mode 100644 rustfmt-core/tests/target/issue-1703.rs delete mode 100644 rustfmt-core/tests/target/issue-1800.rs delete mode 100644 rustfmt-core/tests/target/issue-1802.rs delete mode 100644 rustfmt-core/tests/target/issue-1824.rs delete mode 100644 rustfmt-core/tests/target/issue-1914.rs delete mode 100644 rustfmt-core/tests/target/issue-2025.rs delete mode 100644 rustfmt-core/tests/target/issue-2103.rs delete mode 100644 rustfmt-core/tests/target/issue-2111.rs delete mode 100644 rustfmt-core/tests/target/issue-2123.rs delete mode 100644 rustfmt-core/tests/target/issue-2164.rs delete mode 100644 rustfmt-core/tests/target/issue-2179.rs delete mode 100644 rustfmt-core/tests/target/issue-2197.rs delete mode 100644 rustfmt-core/tests/target/issue-2256.rs delete mode 100644 rustfmt-core/tests/target/issue-2324.rs delete mode 100644 rustfmt-core/tests/target/issue-2329.rs delete mode 100644 rustfmt-core/tests/target/issue-2342.rs delete mode 100644 rustfmt-core/tests/target/issue-2346.rs delete mode 100644 rustfmt-core/tests/target/issue-2401.rs delete mode 100644 rustfmt-core/tests/target/issue-2446.rs delete mode 100644 rustfmt-core/tests/target/issue-2479.rs delete mode 100644 rustfmt-core/tests/target/issue-447.rs delete mode 100644 rustfmt-core/tests/target/issue-510.rs delete mode 100644 rustfmt-core/tests/target/issue-64.rs delete mode 100644 rustfmt-core/tests/target/issue-691.rs delete mode 100644 rustfmt-core/tests/target/issue-770.rs delete mode 100644 rustfmt-core/tests/target/issue-811.rs delete mode 100644 rustfmt-core/tests/target/issue-831.rs delete mode 100644 rustfmt-core/tests/target/issue-850.rs delete mode 100644 rustfmt-core/tests/target/issue-855.rs delete mode 100644 rustfmt-core/tests/target/issue-913.rs delete mode 100644 rustfmt-core/tests/target/issue-945.rs delete mode 100644 rustfmt-core/tests/target/issue-977.rs delete mode 100644 rustfmt-core/tests/target/item-brace-style-always-next-line.rs delete mode 100644 rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs delete mode 100644 rustfmt-core/tests/target/item-brace-style-same-line-where.rs delete mode 100644 rustfmt-core/tests/target/large-block.rs delete mode 100644 rustfmt-core/tests/target/large_vec.rs delete mode 100644 rustfmt-core/tests/target/lazy_static.rs delete mode 100644 rustfmt-core/tests/target/long-fn-1.rs delete mode 100644 rustfmt-core/tests/target/long-match-arms-brace-newline.rs delete mode 100644 rustfmt-core/tests/target/long_field_access.rs delete mode 100644 rustfmt-core/tests/target/loop.rs delete mode 100644 rustfmt-core/tests/target/macro_not_expr.rs delete mode 100644 rustfmt-core/tests/target/macro_rules.rs delete mode 100644 rustfmt-core/tests/target/macros.rs delete mode 100644 rustfmt-core/tests/target/markdown-comment-with-options.rs delete mode 100644 rustfmt-core/tests/target/markdown-comment.rs delete mode 100644 rustfmt-core/tests/target/match-block-trailing-comma.rs delete mode 100644 rustfmt-core/tests/target/match-nowrap-trailing-comma.rs delete mode 100644 rustfmt-core/tests/target/match-nowrap.rs delete mode 100644 rustfmt-core/tests/target/match.rs delete mode 100644 rustfmt-core/tests/target/max-line-length-in-chars.rs delete mode 100644 rustfmt-core/tests/target/mod-1.rs delete mode 100644 rustfmt-core/tests/target/mod-2.rs delete mode 100644 rustfmt-core/tests/target/mod_skip_child.rs delete mode 100644 rustfmt-core/tests/target/mulit-file.rs delete mode 100644 rustfmt-core/tests/target/multiple.rs delete mode 100644 rustfmt-core/tests/target/nested-if-else.rs delete mode 100644 rustfmt-core/tests/target/nested-visual-block.rs delete mode 100644 rustfmt-core/tests/target/nested_skipped/mod.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/mod.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/mod2a.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/mod2b.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/mod2c.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/submod2/a.rs delete mode 100644 rustfmt-core/tests/target/nestedmod/submod2/mod.rs delete mode 100644 rustfmt-core/tests/target/no_new_line_beginning.rs delete mode 100644 rustfmt-core/tests/target/other.rs delete mode 100644 rustfmt-core/tests/target/paths.rs delete mode 100644 rustfmt-core/tests/target/pattern-condense-wildcards.rs delete mode 100644 rustfmt-core/tests/target/pattern.rs delete mode 100644 rustfmt-core/tests/target/pub-restricted.rs delete mode 100644 rustfmt-core/tests/target/remove_blank_lines.rs delete mode 100644 rustfmt-core/tests/target/single-line-if-else.rs delete mode 100644 rustfmt-core/tests/target/skip.rs delete mode 100644 rustfmt-core/tests/target/skip_mod.rs delete mode 100644 rustfmt-core/tests/target/soft-wrapping.rs delete mode 100644 rustfmt-core/tests/target/space-not-before-newline.rs delete mode 100644 rustfmt-core/tests/target/spaces-around-ranges.rs delete mode 100644 rustfmt-core/tests/target/static.rs delete mode 100644 rustfmt-core/tests/target/string-lit-2.rs delete mode 100644 rustfmt-core/tests/target/string-lit-custom.rs delete mode 100644 rustfmt-core/tests/target/string-lit.rs delete mode 100644 rustfmt-core/tests/target/string_punctuation.rs delete mode 100644 rustfmt-core/tests/target/struct-field-attributes.rs delete mode 100644 rustfmt-core/tests/target/struct_lits.rs delete mode 100644 rustfmt-core/tests/target/struct_lits_multiline.rs delete mode 100644 rustfmt-core/tests/target/struct_lits_visual.rs delete mode 100644 rustfmt-core/tests/target/struct_lits_visual_multiline.rs delete mode 100644 rustfmt-core/tests/target/struct_tuple_visual.rs delete mode 100644 rustfmt-core/tests/target/structs.rs delete mode 100644 rustfmt-core/tests/target/trailing-comma-never.rs delete mode 100644 rustfmt-core/tests/target/trailing_commas.rs delete mode 100644 rustfmt-core/tests/target/trait.rs delete mode 100644 rustfmt-core/tests/target/try-conversion.rs delete mode 100644 rustfmt-core/tests/target/tuple.rs delete mode 100644 rustfmt-core/tests/target/type-ascription.rs delete mode 100644 rustfmt-core/tests/target/type.rs delete mode 100644 rustfmt-core/tests/target/type_alias.rs delete mode 100644 rustfmt-core/tests/target/unindent_if_else_cond_comment.rs delete mode 100644 rustfmt-core/tests/target/unions.rs delete mode 100644 rustfmt-core/tests/target/where-clause-rfc.rs delete mode 100644 rustfmt-core/tests/target/where-clause.rs delete mode 100644 rustfmt-core/tests/writemode/source/fn-single-line.rs delete mode 100644 rustfmt-core/tests/writemode/source/modified.rs delete mode 100644 rustfmt-core/tests/writemode/target/checkstyle.xml delete mode 100644 rustfmt-core/tests/writemode/target/modified.txt delete mode 100644 rustfmt-format-diff/Cargo.toml create mode 100644 tests/config/disable_all_formatting.toml create mode 100755 tests/config/issue-1111.toml create mode 100644 tests/config/small_tabs.toml create mode 100644 tests/coverage/source/comments.rs create mode 100644 tests/coverage/target/comments.rs create mode 100644 tests/lib.rs create mode 100644 tests/source/assignment.rs create mode 100644 tests/source/associated-types-bounds-wrapping.rs create mode 100644 tests/source/attrib.rs create mode 100644 tests/source/big-impl-block.rs create mode 100644 tests/source/big-impl-visual.rs create mode 100644 tests/source/break-and-continue.rs create mode 100644 tests/source/catch.rs create mode 100644 tests/source/chains-visual.rs create mode 100644 tests/source/chains.rs create mode 100644 tests/source/closure-block-inside-macro.rs create mode 100644 tests/source/closure.rs create mode 100644 tests/source/comment.rs create mode 100644 tests/source/comment2.rs create mode 100644 tests/source/comment3.rs create mode 100644 tests/source/comment4.rs create mode 100644 tests/source/comment5.rs create mode 100644 tests/source/comment_crlf_newline.rs create mode 100644 tests/source/configs/blank_lines_lower_bound/1.rs create mode 100644 tests/source/configs/brace_style/fn_always_next_line.rs create mode 100644 tests/source/configs/brace_style/fn_prefer_same_line.rs create mode 100644 tests/source/configs/brace_style/fn_same_line_where.rs create mode 100644 tests/source/configs/brace_style/item_always_next_line.rs create mode 100644 tests/source/configs/brace_style/item_prefer_same_line.rs create mode 100644 tests/source/configs/brace_style/item_same_line_where.rs create mode 100644 tests/source/configs/comment_width/above.rs create mode 100644 tests/source/configs/comment_width/below.rs create mode 100644 tests/source/configs/comment_width/ignore.rs create mode 100644 tests/source/configs/condense_wildcard_suffixes/false.rs create mode 100644 tests/source/configs/condense_wildcard_suffixes/true.rs create mode 100644 tests/source/configs/control_brace_style/always_next_line.rs create mode 100644 tests/source/configs/control_brace_style/always_same_line.rs create mode 100644 tests/source/configs/control_brace_style/closing_next_line.rs create mode 100644 tests/source/configs/disable_all_formatting/false.rs create mode 100644 tests/source/configs/disable_all_formatting/true.rs create mode 100644 tests/source/configs/empty_item_single_line/false.rs create mode 100644 tests/source/configs/empty_item_single_line/true.rs create mode 100644 tests/source/configs/error_on_line_overflow/false.rs create mode 100644 tests/source/configs/fn_args_density/compressed.rs create mode 100644 tests/source/configs/fn_args_density/tall.rs create mode 100644 tests/source/configs/fn_args_density/vertical.rs create mode 100644 tests/source/configs/fn_single_line/false.rs create mode 100644 tests/source/configs/fn_single_line/true.rs create mode 100644 tests/source/configs/force_explicit_abi/false.rs create mode 100644 tests/source/configs/force_explicit_abi/true.rs create mode 100644 tests/source/configs/force_multiline_block/false.rs create mode 100644 tests/source/configs/force_multiline_block/true.rs create mode 100644 tests/source/configs/format_strings/false.rs create mode 100644 tests/source/configs/format_strings/true.rs create mode 100644 tests/source/configs/hard_tabs/false.rs create mode 100644 tests/source/configs/hard_tabs/true.rs create mode 100644 tests/source/configs/indent_style/block_args.rs create mode 100644 tests/source/configs/indent_style/block_array.rs create mode 100644 tests/source/configs/indent_style/block_call.rs create mode 100644 tests/source/configs/indent_style/block_chain.rs create mode 100644 tests/source/configs/indent_style/block_generic.rs create mode 100644 tests/source/configs/indent_style/block_struct_lit.rs create mode 100644 tests/source/configs/indent_style/block_trailing_comma_call.rs create mode 100644 tests/source/configs/indent_style/block_where_pred.rs create mode 100644 tests/source/configs/indent_style/default.rs create mode 100644 tests/source/configs/indent_style/rfc_where.rs create mode 100644 tests/source/configs/indent_style/visual_args.rs create mode 100644 tests/source/configs/indent_style/visual_array.rs create mode 100644 tests/source/configs/indent_style/visual_call.rs create mode 100644 tests/source/configs/indent_style/visual_chain.rs create mode 100644 tests/source/configs/indent_style/visual_generics.rs create mode 100644 tests/source/configs/indent_style/visual_struct_lit.rs create mode 100644 tests/source/configs/indent_style/visual_trailing_comma.rs create mode 100644 tests/source/configs/indent_style/visual_where_pred.rs create mode 100644 tests/source/configs/match_arm_blocks/false.rs create mode 100644 tests/source/configs/match_arm_blocks/true.rs create mode 100644 tests/source/configs/match_block_trailing_comma/false.rs create mode 100644 tests/source/configs/match_block_trailing_comma/true.rs create mode 100644 tests/source/configs/merge_derives/true.rs create mode 100644 tests/source/configs/normalize_comments/false.rs create mode 100644 tests/source/configs/normalize_comments/true.rs create mode 100644 tests/source/configs/reorder_extern_crates/false.rs create mode 100644 tests/source/configs/reorder_extern_crates/true.rs create mode 100644 tests/source/configs/reorder_imported_names/false.rs create mode 100644 tests/source/configs/reorder_imported_names/true.rs create mode 100644 tests/source/configs/reorder_imports/false.rs create mode 100644 tests/source/configs/reorder_imports/true.rs create mode 100644 tests/source/configs/reorder_imports_in_group/false.rs create mode 100644 tests/source/configs/reorder_imports_in_group/true.rs create mode 100644 tests/source/configs/reorder_modules/dolor/mod.rs create mode 100644 tests/source/configs/reorder_modules/false.rs create mode 100644 tests/source/configs/reorder_modules/ipsum/mod.rs create mode 100644 tests/source/configs/reorder_modules/lorem/mod.rs create mode 100644 tests/source/configs/reorder_modules/sit/mod.rs create mode 100644 tests/source/configs/reorder_modules/true.rs create mode 100644 tests/source/configs/skip_children/true.rs create mode 100644 tests/source/configs/space_before_colon/true.rs create mode 100644 tests/source/configs/spaces_around_ranges/false.rs create mode 100644 tests/source/configs/spaces_around_ranges/true.rs create mode 100644 tests/source/configs/spaces_within_parens_and_brackets/false.rs create mode 100644 tests/source/configs/spaces_within_parens_and_brackets/true.rs create mode 100644 tests/source/configs/struct_field_align_threshold/20.rs create mode 100644 tests/source/configs/struct_lit_single_line/false.rs create mode 100644 tests/source/configs/tab_spaces/2.rs create mode 100644 tests/source/configs/tab_spaces/4.rs create mode 100644 tests/source/configs/trailing_comma/always.rs create mode 100644 tests/source/configs/trailing_comma/never.rs create mode 100644 tests/source/configs/trailing_comma/vertical.rs create mode 100644 tests/source/configs/type_punctuation_density/compressed.rs create mode 100644 tests/source/configs/type_punctuation_density/wide.rs create mode 100644 tests/source/configs/use_field_init_shorthand/false.rs create mode 100644 tests/source/configs/use_field_init_shorthand/true.rs create mode 100644 tests/source/configs/use_try_shorthand/false.rs create mode 100644 tests/source/configs/use_try_shorthand/true.rs create mode 100644 tests/source/configs/where_single_line/true.rs create mode 100644 tests/source/configs/wrap_comments/false.rs create mode 100644 tests/source/configs/wrap_comments/true.rs create mode 100644 tests/source/control-brace-style-always-next-line.rs create mode 100644 tests/source/control-brace-style-always-same-line.rs create mode 100644 tests/source/doc.rs create mode 100644 tests/source/else-if-brace-style-always-next-line.rs create mode 100644 tests/source/else-if-brace-style-always-same-line.rs create mode 100644 tests/source/else-if-brace-style-closing-next-line.rs create mode 100644 tests/source/empty_file.rs create mode 100644 tests/source/enum.rs create mode 100644 tests/source/expr-block.rs create mode 100644 tests/source/expr.rs create mode 100644 tests/source/extern.rs create mode 100644 tests/source/extern_not_explicit.rs create mode 100644 tests/source/file-lines-1.rs create mode 100644 tests/source/file-lines-2.rs create mode 100644 tests/source/file-lines-3.rs create mode 100644 tests/source/file-lines-4.rs create mode 100644 tests/source/file-lines-5.rs create mode 100644 tests/source/file-lines-6.rs create mode 100644 tests/source/file-lines-item.rs create mode 100644 tests/source/fn-custom-2.rs create mode 100644 tests/source/fn-custom-3.rs create mode 100644 tests/source/fn-custom-4.rs create mode 100644 tests/source/fn-custom-6.rs create mode 100644 tests/source/fn-custom-7.rs create mode 100644 tests/source/fn-custom-8.rs create mode 100644 tests/source/fn-custom.rs create mode 100644 tests/source/fn-simple.rs create mode 100644 tests/source/fn-single-line.rs create mode 100644 tests/source/fn_args_density-vertical.rs create mode 100644 tests/source/fn_args_indent-block.rs create mode 100644 tests/source/hard-tabs.rs create mode 100644 tests/source/hello.rs create mode 100644 tests/source/hello2.rs create mode 100644 tests/source/immovable_generators.rs create mode 100644 tests/source/impls.rs create mode 100644 tests/source/imports-reorder-lines-and-items.rs create mode 100644 tests/source/imports-reorder-lines.rs create mode 100644 tests/source/imports-reorder.rs create mode 100644 tests/source/imports.rs create mode 100644 tests/source/issue-1021.rs create mode 100644 tests/source/issue-1049.rs create mode 100644 tests/source/issue-1111.rs create mode 100644 tests/source/issue-1120.rs create mode 100644 tests/source/issue-1124.rs create mode 100644 tests/source/issue-1127.rs create mode 100644 tests/source/issue-1158.rs create mode 100644 tests/source/issue-1177.rs create mode 100644 tests/source/issue-1192.rs create mode 100644 tests/source/issue-1211.rs create mode 100644 tests/source/issue-1216.rs create mode 100644 tests/source/issue-1239.rs create mode 100644 tests/source/issue-1278.rs create mode 100644 tests/source/issue-1350.rs create mode 100644 tests/source/issue-1366.rs create mode 100644 tests/source/issue-1468.rs create mode 100644 tests/source/issue-1693.rs create mode 100644 tests/source/issue-1800.rs create mode 100644 tests/source/issue-1914.rs create mode 100644 tests/source/issue-2025.rs create mode 100644 tests/source/issue-2111.rs create mode 100644 tests/source/issue-2164.rs create mode 100644 tests/source/issue-2179.rs create mode 100644 tests/source/issue-2256.rs create mode 100644 tests/source/issue-2342.rs create mode 100644 tests/source/issue-2446.rs create mode 100644 tests/source/issue-2479.rs create mode 100644 tests/source/issue-447.rs create mode 100644 tests/source/issue-510.rs create mode 100644 tests/source/issue-811.rs create mode 100644 tests/source/issue-850.rs create mode 100644 tests/source/issue-855.rs create mode 100644 tests/source/issue-913.rs create mode 100644 tests/source/issue-945.rs create mode 100644 tests/source/issue-977.rs create mode 100644 tests/source/item-brace-style-always-next-line.rs create mode 100644 tests/source/item-brace-style-prefer-same-line.rs create mode 100644 tests/source/item-brace-style-same-line-where.rs create mode 100644 tests/source/large-block.rs create mode 100644 tests/source/large_vec.rs create mode 100644 tests/source/lazy_static.rs create mode 100644 tests/source/long-match-arms-brace-newline.rs create mode 100644 tests/source/long_field_access.rs create mode 100644 tests/source/loop.rs create mode 100644 tests/source/macro_not_expr.rs create mode 100644 tests/source/macro_rules.rs create mode 100644 tests/source/macros.rs create mode 100644 tests/source/markdown-comment-with-options.rs create mode 100644 tests/source/markdown-comment.rs create mode 100644 tests/source/match-block-trailing-comma.rs create mode 100644 tests/source/match-nowrap-trailing-comma.rs create mode 100644 tests/source/match-nowrap.rs create mode 100644 tests/source/match.rs create mode 100644 tests/source/max-line-length-in-chars.rs create mode 100644 tests/source/mod-1.rs create mode 100644 tests/source/mod-2.rs create mode 100644 tests/source/mod_skip_child.rs create mode 100644 tests/source/multiple.rs create mode 100644 tests/source/nested-if-else.rs create mode 100644 tests/source/nested_skipped/mod.rs create mode 100644 tests/source/nestedmod/mod.rs create mode 100644 tests/source/nestedmod/mod2a.rs create mode 100644 tests/source/nestedmod/mod2b.rs create mode 100644 tests/source/nestedmod/mod2c.rs create mode 100644 tests/source/nestedmod/mymod1/mod3a.rs create mode 100644 tests/source/nestedmod/submod2/a.rs create mode 100644 tests/source/nestedmod/submod2/mod.rs create mode 100644 tests/source/no_new_line_beginning.rs create mode 100644 tests/source/other.rs create mode 100644 tests/source/paths.rs create mode 100644 tests/source/pattern-condense-wildcards.rs create mode 100644 tests/source/pattern.rs create mode 100644 tests/source/pub-restricted.rs create mode 100644 tests/source/remove_blank_lines.rs create mode 100644 tests/source/single-line-if-else.rs create mode 100644 tests/source/soft-wrapping.rs create mode 100644 tests/source/space-not-before-newline.rs create mode 100644 tests/source/spaces-around-ranges.rs create mode 100644 tests/source/static.rs create mode 100644 tests/source/string-lit-2.rs create mode 100644 tests/source/string-lit.rs create mode 100644 tests/source/string_punctuation.rs create mode 100644 tests/source/struct-field-attributes.rs create mode 100644 tests/source/struct_lits.rs create mode 100644 tests/source/struct_lits_multiline.rs create mode 100644 tests/source/struct_lits_visual.rs create mode 100644 tests/source/struct_lits_visual_multiline.rs create mode 100644 tests/source/struct_tuple_visual.rs create mode 100644 tests/source/structs.rs create mode 100644 tests/source/trailing-comma-never.rs create mode 100644 tests/source/trailing_commas.rs create mode 100644 tests/source/trait.rs create mode 100644 tests/source/try-conversion.rs create mode 100644 tests/source/tuple.rs create mode 100644 tests/source/type-ascription.rs create mode 100644 tests/source/type.rs create mode 100644 tests/source/type_alias.rs create mode 100644 tests/source/unions.rs create mode 100644 tests/source/where-clause-rfc.rs create mode 100644 tests/source/where-clause.rs create mode 100644 tests/target/assignment.rs create mode 100644 tests/target/associated-items.rs create mode 100644 tests/target/associated-types-bounds-wrapping.rs create mode 100644 tests/target/associated_type_defaults.rs create mode 100644 tests/target/attrib-extern-crate.rs create mode 100644 tests/target/attrib.rs create mode 100644 tests/target/big-impl-block.rs create mode 100644 tests/target/big-impl-visual.rs create mode 100644 tests/target/break-and-continue.rs create mode 100644 tests/target/catch.rs create mode 100644 tests/target/chains-visual.rs create mode 100644 tests/target/chains.rs create mode 100644 tests/target/closure-block-inside-macro.rs create mode 100644 tests/target/closure.rs create mode 100644 tests/target/comment-inside-const.rs create mode 100644 tests/target/comment-not-disappear.rs create mode 100644 tests/target/comment.rs create mode 100644 tests/target/comment2.rs create mode 100644 tests/target/comment3.rs create mode 100644 tests/target/comment4.rs create mode 100644 tests/target/comment5.rs create mode 100644 tests/target/comment_crlf_newline.rs create mode 100644 tests/target/comments-fn.rs create mode 100644 tests/target/configs/blank_lines_lower_bound/1.rs create mode 100644 tests/target/configs/brace_style/fn_always_next_line.rs create mode 100644 tests/target/configs/brace_style/fn_prefer_same_line.rs create mode 100644 tests/target/configs/brace_style/fn_same_line_where.rs create mode 100644 tests/target/configs/brace_style/item_always_next_line.rs create mode 100644 tests/target/configs/brace_style/item_prefer_same_line.rs create mode 100644 tests/target/configs/brace_style/item_same_line_where.rs create mode 100644 tests/target/configs/combine_control_expr/false.rs create mode 100644 tests/target/configs/combine_control_expr/true.rs create mode 100644 tests/target/configs/comment_width/above.rs create mode 100644 tests/target/configs/comment_width/below.rs create mode 100644 tests/target/configs/comment_width/ignore.rs create mode 100644 tests/target/configs/condense_wildcard_suffixes/false.rs create mode 100644 tests/target/configs/condense_wildcard_suffixes/true.rs create mode 100644 tests/target/configs/control_brace_style/always_next_line.rs create mode 100644 tests/target/configs/control_brace_style/always_same_line.rs create mode 100644 tests/target/configs/control_brace_style/closing_next_line.rs create mode 100644 tests/target/configs/disable_all_formatting/false.rs create mode 100644 tests/target/configs/disable_all_formatting/true.rs create mode 100644 tests/target/configs/empty_item_single_line/false.rs create mode 100644 tests/target/configs/empty_item_single_line/true.rs create mode 100644 tests/target/configs/error_on_line_overflow/false.rs create mode 100644 tests/target/configs/error_on_unformatted/false.rs create mode 100644 tests/target/configs/fn_args_density/compressed.rs create mode 100644 tests/target/configs/fn_args_density/tall.rs create mode 100644 tests/target/configs/fn_args_density/vertical.rs create mode 100644 tests/target/configs/fn_single_line/false.rs create mode 100644 tests/target/configs/fn_single_line/true.rs create mode 100644 tests/target/configs/force_explicit_abi/false.rs create mode 100644 tests/target/configs/force_explicit_abi/true.rs create mode 100644 tests/target/configs/force_multiline_block/false.rs create mode 100644 tests/target/configs/force_multiline_block/true.rs create mode 100644 tests/target/configs/format_strings/false.rs create mode 100644 tests/target/configs/format_strings/true.rs create mode 100644 tests/target/configs/hard_tabs/false.rs create mode 100644 tests/target/configs/hard_tabs/true.rs create mode 100644 tests/target/configs/imports_indent/block.rs create mode 100644 tests/target/configs/imports_layout/horizontal_vertical.rs create mode 100644 tests/target/configs/imports_layout/mixed.rs create mode 100644 tests/target/configs/indent_style/block_args.rs create mode 100644 tests/target/configs/indent_style/block_array.rs create mode 100644 tests/target/configs/indent_style/block_call.rs create mode 100644 tests/target/configs/indent_style/block_chain.rs create mode 100644 tests/target/configs/indent_style/block_generic.rs create mode 100644 tests/target/configs/indent_style/block_struct_lit.rs create mode 100644 tests/target/configs/indent_style/block_tab_spaces_call.rs create mode 100644 tests/target/configs/indent_style/block_trailing_comma_call.rs create mode 100644 tests/target/configs/indent_style/block_where_pred.rs create mode 100644 tests/target/configs/indent_style/default.rs create mode 100644 tests/target/configs/indent_style/rfc_control.rs create mode 100644 tests/target/configs/indent_style/rfc_where.rs create mode 100644 tests/target/configs/indent_style/visual_args.rs create mode 100644 tests/target/configs/indent_style/visual_array.rs create mode 100644 tests/target/configs/indent_style/visual_call.rs create mode 100644 tests/target/configs/indent_style/visual_chain.rs create mode 100644 tests/target/configs/indent_style/visual_generics.rs create mode 100644 tests/target/configs/indent_style/visual_struct_lit.rs create mode 100644 tests/target/configs/indent_style/visual_trailing_comma.rs create mode 100644 tests/target/configs/indent_style/visual_where_pred.rs create mode 100644 tests/target/configs/match_arm_blocks/false.rs create mode 100644 tests/target/configs/match_arm_blocks/true.rs create mode 100644 tests/target/configs/match_block_trailing_comma/false.rs create mode 100644 tests/target/configs/match_block_trailing_comma/true.rs create mode 100644 tests/target/configs/merge_derives/true.rs create mode 100644 tests/target/configs/normalize_comments/false.rs create mode 100644 tests/target/configs/normalize_comments/true.rs create mode 100644 tests/target/configs/reorder_extern_crates/false.rs create mode 100644 tests/target/configs/reorder_extern_crates/true.rs create mode 100644 tests/target/configs/reorder_imported_names/false.rs create mode 100644 tests/target/configs/reorder_imported_names/true.rs create mode 100644 tests/target/configs/reorder_imports/false.rs create mode 100644 tests/target/configs/reorder_imports/true.rs create mode 100644 tests/target/configs/reorder_imports_in_group/false.rs create mode 100644 tests/target/configs/reorder_imports_in_group/true.rs create mode 100644 tests/target/configs/reorder_modules/dolor/mod.rs create mode 100644 tests/target/configs/reorder_modules/false.rs create mode 100644 tests/target/configs/reorder_modules/ipsum/mod.rs create mode 100644 tests/target/configs/reorder_modules/lorem/mod.rs create mode 100644 tests/target/configs/reorder_modules/sit/mod.rs create mode 100644 tests/target/configs/reorder_modules/true.rs create mode 100644 tests/target/configs/skip_children/true.rs create mode 100644 tests/target/configs/space_before_colon/true.rs create mode 100644 tests/target/configs/spaces_around_ranges/false.rs create mode 100644 tests/target/configs/spaces_around_ranges/true.rs create mode 100644 tests/target/configs/spaces_within_parens_and_brackets/false.rs create mode 100644 tests/target/configs/spaces_within_parens_and_brackets/true.rs create mode 100644 tests/target/configs/struct_field_align_threshold/20.rs create mode 100644 tests/target/configs/struct_lit_single_line/false.rs create mode 100644 tests/target/configs/tab_spaces/2.rs create mode 100644 tests/target/configs/tab_spaces/4.rs create mode 100644 tests/target/configs/trailing_comma/always.rs create mode 100644 tests/target/configs/trailing_comma/never.rs create mode 100644 tests/target/configs/trailing_comma/vertical.rs create mode 100644 tests/target/configs/trailing_semicolon/false.rs create mode 100644 tests/target/configs/trailing_semicolon/true.rs create mode 100644 tests/target/configs/type_punctuation_density/compressed.rs create mode 100644 tests/target/configs/type_punctuation_density/wide.rs create mode 100644 tests/target/configs/use_field_init_shorthand/false.rs create mode 100644 tests/target/configs/use_field_init_shorthand/true.rs create mode 100644 tests/target/configs/use_try_shorthand/false.rs create mode 100644 tests/target/configs/use_try_shorthand/true.rs create mode 100644 tests/target/configs/where_single_line/true.rs create mode 100644 tests/target/configs/wrap_comments/false.rs create mode 100644 tests/target/configs/wrap_comments/true.rs create mode 100644 tests/target/control-brace-style-always-next-line.rs create mode 100644 tests/target/control-brace-style-always-same-line.rs create mode 100644 tests/target/doc.rs create mode 100644 tests/target/else-if-brace-style-always-next-line.rs create mode 100644 tests/target/else-if-brace-style-always-same-line.rs create mode 100644 tests/target/else-if-brace-style-closing-next-line.rs create mode 100644 tests/target/empty-tuple-no-conversion-to-unit-struct.rs create mode 100644 tests/target/empty_file.rs create mode 100644 tests/target/enum.rs create mode 100644 tests/target/expr-block.rs create mode 100644 tests/target/expr.rs create mode 100644 tests/target/extern.rs create mode 100644 tests/target/extern_not_explicit.rs create mode 100644 tests/target/file-lines-1.rs create mode 100644 tests/target/file-lines-2.rs create mode 100644 tests/target/file-lines-3.rs create mode 100644 tests/target/file-lines-4.rs create mode 100644 tests/target/file-lines-5.rs create mode 100644 tests/target/file-lines-6.rs create mode 100644 tests/target/file-lines-item.rs create mode 100644 tests/target/fn-args-with-last-line-comment.rs create mode 100644 tests/target/fn-custom-2.rs create mode 100644 tests/target/fn-custom-3.rs create mode 100644 tests/target/fn-custom-4.rs create mode 100644 tests/target/fn-custom-6.rs create mode 100644 tests/target/fn-custom-7.rs create mode 100644 tests/target/fn-custom-8.rs create mode 100644 tests/target/fn-custom.rs create mode 100644 tests/target/fn-simple.rs create mode 100644 tests/target/fn-single-line.rs create mode 100644 tests/target/fn-ty.rs create mode 100644 tests/target/fn.rs create mode 100644 tests/target/fn_args_density-vertical.rs create mode 100644 tests/target/fn_args_indent-block.rs create mode 100644 tests/target/fn_once.rs create mode 100644 tests/target/hard-tabs.rs create mode 100644 tests/target/hello.rs create mode 100644 tests/target/immovable_generators.rs create mode 100644 tests/target/impl.rs create mode 100644 tests/target/impls.rs create mode 100644 tests/target/import-fencepost-length.rs create mode 100644 tests/target/imports-reorder-lines-and-items.rs create mode 100644 tests/target/imports-reorder-lines.rs create mode 100644 tests/target/imports-reorder.rs create mode 100644 tests/target/imports.rs create mode 100644 tests/target/indented-impl.rs create mode 100644 tests/target/issue-1021.rs create mode 100644 tests/target/issue-1049.rs create mode 100644 tests/target/issue-1055.rs create mode 100644 tests/target/issue-1111.rs create mode 100644 tests/target/issue-1113.rs create mode 100644 tests/target/issue-1120.rs create mode 100644 tests/target/issue-1124.rs create mode 100644 tests/target/issue-1127.rs create mode 100644 tests/target/issue-1158.rs create mode 100644 tests/target/issue-1177.rs create mode 100644 tests/target/issue-1192.rs create mode 100644 tests/target/issue-1211.rs create mode 100644 tests/target/issue-1214.rs create mode 100644 tests/target/issue-1216.rs create mode 100644 tests/target/issue-1239.rs create mode 100644 tests/target/issue-1247.rs create mode 100644 tests/target/issue-1255.rs create mode 100644 tests/target/issue-1278.rs create mode 100644 tests/target/issue-1350.rs create mode 100644 tests/target/issue-1366.rs create mode 100644 tests/target/issue-1397.rs create mode 100644 tests/target/issue-1468.rs create mode 100644 tests/target/issue-1598.rs create mode 100644 tests/target/issue-1624.rs create mode 100644 tests/target/issue-1681.rs create mode 100644 tests/target/issue-1693.rs create mode 100644 tests/target/issue-1703.rs create mode 100644 tests/target/issue-1800.rs create mode 100644 tests/target/issue-1802.rs create mode 100644 tests/target/issue-1824.rs create mode 100644 tests/target/issue-1914.rs create mode 100644 tests/target/issue-2025.rs create mode 100644 tests/target/issue-2103.rs create mode 100644 tests/target/issue-2111.rs create mode 100644 tests/target/issue-2123.rs create mode 100644 tests/target/issue-2164.rs create mode 100644 tests/target/issue-2179.rs create mode 100644 tests/target/issue-2197.rs create mode 100644 tests/target/issue-2256.rs create mode 100644 tests/target/issue-2324.rs create mode 100644 tests/target/issue-2329.rs create mode 100644 tests/target/issue-2342.rs create mode 100644 tests/target/issue-2346.rs create mode 100644 tests/target/issue-2401.rs create mode 100644 tests/target/issue-2446.rs create mode 100644 tests/target/issue-2479.rs create mode 100644 tests/target/issue-447.rs create mode 100644 tests/target/issue-510.rs create mode 100644 tests/target/issue-64.rs create mode 100644 tests/target/issue-691.rs create mode 100644 tests/target/issue-770.rs create mode 100644 tests/target/issue-811.rs create mode 100644 tests/target/issue-831.rs create mode 100644 tests/target/issue-850.rs create mode 100644 tests/target/issue-855.rs create mode 100644 tests/target/issue-913.rs create mode 100644 tests/target/issue-945.rs create mode 100644 tests/target/issue-977.rs create mode 100644 tests/target/item-brace-style-always-next-line.rs create mode 100644 tests/target/item-brace-style-prefer-same-line.rs create mode 100644 tests/target/item-brace-style-same-line-where.rs create mode 100644 tests/target/large-block.rs create mode 100644 tests/target/large_vec.rs create mode 100644 tests/target/lazy_static.rs create mode 100644 tests/target/long-fn-1.rs create mode 100644 tests/target/long-match-arms-brace-newline.rs create mode 100644 tests/target/long_field_access.rs create mode 100644 tests/target/loop.rs create mode 100644 tests/target/macro_not_expr.rs create mode 100644 tests/target/macro_rules.rs create mode 100644 tests/target/macros.rs create mode 100644 tests/target/markdown-comment-with-options.rs create mode 100644 tests/target/markdown-comment.rs create mode 100644 tests/target/match-block-trailing-comma.rs create mode 100644 tests/target/match-nowrap-trailing-comma.rs create mode 100644 tests/target/match-nowrap.rs create mode 100644 tests/target/match.rs create mode 100644 tests/target/max-line-length-in-chars.rs create mode 100644 tests/target/mod-1.rs create mode 100644 tests/target/mod-2.rs create mode 100644 tests/target/mod_skip_child.rs create mode 100644 tests/target/mulit-file.rs create mode 100644 tests/target/multiple.rs create mode 100644 tests/target/nested-if-else.rs create mode 100644 tests/target/nested-visual-block.rs create mode 100644 tests/target/nested_skipped/mod.rs create mode 100644 tests/target/nestedmod/mod.rs create mode 100644 tests/target/nestedmod/mod2a.rs create mode 100644 tests/target/nestedmod/mod2b.rs create mode 100644 tests/target/nestedmod/mod2c.rs create mode 100644 tests/target/nestedmod/mymod1/mod3a.rs create mode 100644 tests/target/nestedmod/submod2/a.rs create mode 100644 tests/target/nestedmod/submod2/mod.rs create mode 100644 tests/target/no_new_line_beginning.rs create mode 100644 tests/target/other.rs create mode 100644 tests/target/paths.rs create mode 100644 tests/target/pattern-condense-wildcards.rs create mode 100644 tests/target/pattern.rs create mode 100644 tests/target/pub-restricted.rs create mode 100644 tests/target/remove_blank_lines.rs create mode 100644 tests/target/single-line-if-else.rs create mode 100644 tests/target/skip.rs create mode 100644 tests/target/skip_mod.rs create mode 100644 tests/target/soft-wrapping.rs create mode 100644 tests/target/space-not-before-newline.rs create mode 100644 tests/target/spaces-around-ranges.rs create mode 100644 tests/target/static.rs create mode 100644 tests/target/string-lit-2.rs create mode 100644 tests/target/string-lit-custom.rs create mode 100644 tests/target/string-lit.rs create mode 100644 tests/target/string_punctuation.rs create mode 100644 tests/target/struct-field-attributes.rs create mode 100644 tests/target/struct_lits.rs create mode 100644 tests/target/struct_lits_multiline.rs create mode 100644 tests/target/struct_lits_visual.rs create mode 100644 tests/target/struct_lits_visual_multiline.rs create mode 100644 tests/target/struct_tuple_visual.rs create mode 100644 tests/target/structs.rs create mode 100644 tests/target/trailing-comma-never.rs create mode 100644 tests/target/trailing_commas.rs create mode 100644 tests/target/trait.rs create mode 100644 tests/target/try-conversion.rs create mode 100644 tests/target/tuple.rs create mode 100644 tests/target/type-ascription.rs create mode 100644 tests/target/type.rs create mode 100644 tests/target/type_alias.rs create mode 100644 tests/target/unindent_if_else_cond_comment.rs create mode 100644 tests/target/unions.rs create mode 100644 tests/target/where-clause-rfc.rs create mode 100644 tests/target/where-clause.rs create mode 100644 tests/writemode/source/fn-single-line.rs create mode 100644 tests/writemode/source/modified.rs create mode 100644 tests/writemode/target/checkstyle.xml create mode 100644 tests/writemode/target/modified.txt (limited to 'src') diff --git a/cargo-fmt/Cargo.toml b/cargo-fmt/Cargo.toml deleted file mode 100644 index 87142657231..00000000000 --- a/cargo-fmt/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "cargo-fmt" -version = "0.4.0" -authors = ["Nicholas Cameron ", "The Rustfmt developers"] -description = "Cargo frontend for rustfmt" -repository = "https://github.com/rust-lang-nursery/rustfmt" -readme = "README.md" -license = "Apache-2.0/MIT" -categories = ["development-tools"] - -[[bin]] -name = "cargo-fmt" - -[dependencies] -cargo_metadata = "0.4" -getopts = "0.2" -serde_json = "1.0" diff --git a/git-rustfmt/Cargo.toml b/git-rustfmt/Cargo.toml deleted file mode 100644 index 5bebeff2c84..00000000000 --- a/git-rustfmt/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "git-rustfmt" -version = "0.4.0" -authors = ["Nicholas Cameron ", "The Rustfmt developers"] -description = "Run rustfmt against git diff" -repository = "https://github.com/rust-lang-nursery/rustfmt" -readme = "README.md" -license = "Apache-2.0/MIT" -categories = ["development-tools"] - -[[bin]] -name = "git-rustfmt" - -[dependencies] -env_logger = "0.5" -getopts = "0.2" -log = "0.3" -rustfmt-config = { path = "../rustfmt-config" } -rustfmt-core = { path = "../rustfmt-core" } \ No newline at end of file diff --git a/rustfmt-bin/Cargo.toml b/rustfmt-bin/Cargo.toml deleted file mode 100644 index c07146dcb01..00000000000 --- a/rustfmt-bin/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "rustfmt-bin" -version = "0.4.0" -authors = ["Nicholas Cameron ", "The Rustfmt developers"] -description = "Tool to find and fix Rust formatting issues" -repository = "https://github.com/rust-lang-nursery/rustfmt" -readme = "README.md" -license = "Apache-2.0/MIT" -build = "build.rs" -categories = ["development-tools"] - -[[bin]] -name = "rustfmt" -path = "src/main.rs" - -[dependencies] -env_logger = "0.4" -getopts = "0.2" -rustfmt-config = { path = "../rustfmt-config" } -rustfmt-core = { path = "../rustfmt-core" } \ No newline at end of file diff --git a/rustfmt-bin/build.rs b/rustfmt-bin/build.rs deleted file mode 100644 index d72b44eb7f3..00000000000 --- a/rustfmt-bin/build.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; -use std::process::Command; - -fn main() { - let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - - File::create(out_dir.join("commit-info.txt")) - .unwrap() - .write_all(commit_info().as_bytes()) - .unwrap(); -} - -// Try to get hash and date of the last commit on a best effort basis. If anything goes wrong -// (git not installed or if this is not a git repository) just return an empty string. -fn commit_info() -> String { - match (channel(), commit_hash(), commit_date()) { - (channel, Some(hash), Some(date)) => { - format!("{} ({} {})", channel, hash.trim_right(), date) - } - _ => String::new(), - } -} - -fn channel() -> String { - if let Ok(channel) = env::var("CFG_RELEASE_CHANNEL") { - channel - } else { - "nightly".to_owned() - } -} - -fn commit_hash() -> Option { - Command::new("git") - .args(&["rev-parse", "--short", "HEAD"]) - .output() - .ok() - .and_then(|r| String::from_utf8(r.stdout).ok()) -} - -fn commit_date() -> Option { - Command::new("git") - .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) - .output() - .ok() - .and_then(|r| String::from_utf8(r.stdout).ok()) -} diff --git a/rustfmt-config/Cargo.toml b/rustfmt-config/Cargo.toml deleted file mode 100644 index 7996fca67d7..00000000000 --- a/rustfmt-config/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "rustfmt-config" -version = "0.4.0" -authors = ["Nicholas Cameron ", "The Rustfmt developers"] -description = "A library for configuring and customizing rustfmt" -repository = "https://github.com/rust-lang-nursery/rustfmt" -readme = "README.md" -license = "Apache-2.0/MIT" -categories = ["development-tools"] - -[dependencies] -rustc-ap-syntax = "29.0.0" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" -toml = "0.4" diff --git a/rustfmt-config/README.md b/rustfmt-config/README.md deleted file mode 100644 index 840b230d115..00000000000 --- a/rustfmt-config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# rustfmt-config - -Configuration for Rustfmt diff --git a/rustfmt-core/Cargo.toml b/rustfmt-core/Cargo.toml deleted file mode 100644 index 2cf72e3f210..00000000000 --- a/rustfmt-core/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "rustfmt-core" -version = "0.4.0" -authors = ["Nicholas Cameron ", "The Rustfmt developers"] -description = "A core library of rustfmt" -repository = "https://github.com/rust-lang-nursery/rustfmt" -readme = "README.md" -license = "Apache-2.0/MIT" -categories = ["development-tools"] - -[lib] -doctest = false - -[dependencies] -derive-new = "0.5" -diff = "0.1" -log = "0.3" -regex = "0.2" -rustc-ap-syntax = "29.0.0" -rustc-ap-rustc_errors = "29.0.0" -rustfmt-config = { path = "../rustfmt-config" } -term = "0.4" -unicode-segmentation = "1.0.0" - -[dev-dependencies] -lazy_static = "1.0.0" - -[target.'cfg(unix)'.dependencies] -libc = "0.2.11" - -[target.'cfg(windows)'.dependencies] -kernel32-sys = "0.2.2" -winapi = "0.2.7" diff --git a/rustfmt-core/README.md b/rustfmt-core/README.md deleted file mode 100644 index 7421de1fe90..00000000000 --- a/rustfmt-core/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# rustfmt-core - -Core formatting functionality for Rustfmt diff --git a/rustfmt-core/tests/config/disable_all_formatting.toml b/rustfmt-core/tests/config/disable_all_formatting.toml deleted file mode 100644 index c7ad93bafe3..00000000000 --- a/rustfmt-core/tests/config/disable_all_formatting.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/rustfmt-core/tests/config/issue-1111.toml b/rustfmt-core/tests/config/issue-1111.toml deleted file mode 100755 index 44148a2d3c3..00000000000 --- a/rustfmt-core/tests/config/issue-1111.toml +++ /dev/null @@ -1 +0,0 @@ -reorder_imports = true diff --git a/rustfmt-core/tests/config/small_tabs.toml b/rustfmt-core/tests/config/small_tabs.toml deleted file mode 100644 index d03ac281acb..00000000000 --- a/rustfmt-core/tests/config/small_tabs.toml +++ /dev/null @@ -1,12 +0,0 @@ -max_width = 100 -comment_width = 80 -tab_spaces = 2 -newline_style = "Unix" -brace_style = "SameLineWhere" -fn_args_density = "Tall" -trailing_comma = "Vertical" -indent_style = "Block" -report_todo = "Always" -report_fixme = "Never" -reorder_imports = false -format_strings = true diff --git a/rustfmt-core/tests/coverage/source/comments.rs b/rustfmt-core/tests/coverage/source/comments.rs deleted file mode 100644 index e79557af713..00000000000 --- a/rustfmt-core/tests/coverage/source/comments.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-write_mode: coverage -/// Here's a doc comment! -fn main() { - // foo is bar - let foo = "bar"; - // loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment!!!!! -} diff --git a/rustfmt-core/tests/coverage/target/comments.rs b/rustfmt-core/tests/coverage/target/comments.rs deleted file mode 100644 index 8f9c223aef2..00000000000 --- a/rustfmt-core/tests/coverage/target/comments.rs +++ /dev/null @@ -1,7 +0,0 @@ -XX XXXXXXXXXXXXXXXXXXX XXXXXXXX -/// Here's a doc comment! -fn main() { - XX XXX XX XXX - let foo = "bar"; - XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX -} diff --git a/rustfmt-core/tests/lib.rs b/rustfmt-core/tests/lib.rs deleted file mode 100644 index aab37b91d55..00000000000 --- a/rustfmt-core/tests/lib.rs +++ /dev/null @@ -1,873 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; -extern crate regex; -extern crate rustfmt_config as config; -extern crate rustfmt_core as rustfmt; -extern crate term; - -use std::collections::{HashMap, HashSet}; -use std::fs; -use std::io::{self, BufRead, BufReader, Read}; -use std::iter::{Enumerate, Peekable}; -use std::path::{Path, PathBuf}; -use std::str::Chars; - -use rustfmt::*; -use config::{Color, Config, ReportTactic}; -use config::summary::Summary; -use rustfmt::filemap::write_system_newlines; -use rustfmt::rustfmt_diff::*; - -const DIFF_CONTEXT_SIZE: usize = 3; -const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; - -// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the -// given path. The `recursive` argument controls if files from subdirectories -// are also returned. -fn get_test_files(path: &Path, recursive: bool) -> Vec { - let mut files = vec![]; - if path.is_dir() { - for entry in fs::read_dir(path).expect(&format!( - "Couldn't read directory {}", - path.to_str().unwrap() - )) { - let entry = entry.expect("Couldn't get DirEntry"); - let path = entry.path(); - if path.is_dir() && recursive { - files.append(&mut get_test_files(&path, recursive)); - } else if path.extension().map_or(false, |f| f == "rs") { - files.push(path); - } - } - } - files -} - -fn verify_config_used(path: &Path, config_name: &str) { - for entry in fs::read_dir(path).expect(&format!( - "Couldn't read {} directory", - path.to_str().unwrap() - )) { - let entry = entry.expect("Couldn't get directory entry"); - let path = entry.path(); - if path.extension().map_or(false, |f| f == "rs") { - // check if "// rustfmt-:" appears in the file. - let filebuf = BufReader::new( - fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), - ); - assert!( - filebuf - .lines() - .map(|l| l.unwrap()) - .take_while(|l| l.starts_with("//")) - .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), - format!( - "config option file {} does not contain expected config name", - path.display() - ) - ); - } - } -} - -#[test] -fn verify_config_test_names() { - for path in &[ - Path::new("tests/source/configs"), - Path::new("tests/target/configs"), - ] { - for entry in fs::read_dir(path).expect("Couldn't read configs directory") { - let entry = entry.expect("Couldn't get directory entry"); - let path = entry.path(); - if path.is_dir() { - let config_name = path.file_name().unwrap().to_str().unwrap(); - - // Make sure that config name is used in the files in the directory. - verify_config_used(&path, config_name); - } - } - } -} - -// This writes to the terminal using the same approach (via term::stdout or -// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing -// using only one or the other will cause the output order to differ when -// `print_diff` selects the approach not used. -fn write_message(msg: &str) { - let mut writer = OutputWriter::new(Color::Auto); - writer.writeln(&format!("{}", msg), None); -} - -// Integration tests. The files in the tests/source are formatted and compared -// to their equivalent in tests/target. The target file and config can be -// overridden by annotations in the source file. The input and output must match -// exactly. -#[test] -fn system_tests() { - // Get all files in the tests/source directory. - let files = get_test_files(Path::new("tests/source"), true); - let (_reports, count, fails) = check_files(files); - - // Display results. - println!("Ran {} system tests.", count); - assert_eq!(fails, 0, "{} system tests failed", fails); -} - -// Do the same for tests/coverage-source directory -// the only difference is the coverage mode -#[test] -fn coverage_tests() { - let files = get_test_files(Path::new("tests/coverage/source"), true); - let (_reports, count, fails) = check_files(files); - - println!("Ran {} tests in coverage mode.", count); - assert_eq!(fails, 0, "{} tests failed", fails); -} - -#[test] -fn checkstyle_test() { - let filename = "tests/writemode/source/fn-single-line.rs"; - let expected_filename = "tests/writemode/target/checkstyle.xml"; - assert_output(Path::new(filename), Path::new(expected_filename)); -} - -#[test] -fn modified_test() { - // Test "modified" output - let filename = "tests/writemode/source/modified.rs"; - let result = get_modified_lines(Input::File(filename.into()), &Config::default()).unwrap(); - assert_eq!( - result.modified_lines, - ModifiedLines { - chunks: vec![ - ModifiedChunk { - line_number_orig: 4, - lines_removed: 4, - lines: vec!["fn blah() {}".into()], - }, - ModifiedChunk { - line_number_orig: 9, - lines_removed: 6, - lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], - }, - ], - } - ); -} - -// Helper function for comparing the results of rustfmt -// to a known output file generated by one of the write modes. -fn assert_output(source: &Path, expected_filename: &Path) { - let config = read_config(source); - let (_error_summary, file_map, _report) = format_file(source, &config); - - // Populate output by writing to a vec. - let mut out = vec![]; - let _ = filemap::write_all_files(&file_map, &mut out, &config); - let output = String::from_utf8(out).unwrap(); - - let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); - let mut expected_text = String::new(); - expected_file - .read_to_string(&mut expected_text) - .expect("Failed reading target"); - - let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - let mut failures = HashMap::new(); - failures.insert(source.to_owned(), compare); - print_mismatches_default_message(failures); - assert!(false, "Text does not match expected output"); - } -} - -// Idempotence tests. Files in tests/target are checked to be unaltered by -// rustfmt. -#[test] -fn idempotence_tests() { - // Get all files in the tests/target directory. - let files = get_test_files(Path::new("tests/target"), true); - let (_reports, count, fails) = check_files(files); - - // Display results. - println!("Ran {} idempotent tests.", count); - assert_eq!(fails, 0, "{} idempotent tests failed", fails); -} - -// Run rustfmt on itself. This operation must be idempotent. We also check that -// no warnings are emitted. -#[test] -fn self_tests() { - let mut files = get_test_files(Path::new("tests"), false); - let bin_directories = vec![ - "cargo-fmt", - "git-rustfmt", - "rustfmt-bin", - "rustfmt-format-diff", - ]; - for dir in bin_directories { - let mut path = PathBuf::from(".."); - path.push(dir); - path.push("src/main.rs"); - files.push(path); - } - let lib_directories = vec!["rustfmt-core", "rustfmt-config"]; - for dir in lib_directories { - let mut path = PathBuf::from(".."); - path.push(dir); - path.push("src/lib.rs"); - files.push(path); - } - - let (reports, count, fails) = check_files(files); - let mut warnings = 0; - - // Display results. - println!("Ran {} self tests.", count); - assert_eq!(fails, 0, "{} self tests failed", fails); - - for format_report in reports { - println!("{}", format_report); - warnings += format_report.warning_count(); - } - - assert_eq!( - warnings, 0, - "Rustfmt's code generated {} warnings", - warnings - ); -} - -#[test] -fn stdin_formatting_smoke_test() { - let input = Input::Text("fn main () {}".to_owned()); - let config = Config::default(); - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_no_errors()); - for &(ref file_name, ref text) in &file_map { - if let FileName::Custom(ref file_name) = *file_name { - if file_name == "stdin" { - assert_eq!(text.to_string(), "fn main() {}\n"); - return; - } - } - } - panic!("no stdin"); -} - -// FIXME(#1990) restore this test -// #[test] -// fn stdin_disable_all_formatting_test() { -// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); -// let mut child = Command::new("./target/debug/rustfmt") -// .stdin(Stdio::piped()) -// .stdout(Stdio::piped()) -// .arg("--config-path=./tests/config/disable_all_formatting.toml") -// .spawn() -// .expect("failed to execute child"); - -// { -// let stdin = child.stdin.as_mut().expect("failed to get stdin"); -// stdin -// .write_all(input.as_bytes()) -// .expect("failed to write stdin"); -// } -// let output = child.wait_with_output().expect("failed to wait on child"); -// assert!(output.status.success()); -// assert!(output.stderr.is_empty()); -// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); -// } - -#[test] -fn format_lines_errors_are_reported() { - let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); - let input = Input::Text(format!("fn {}() {{}}", long_identifier)); - let config = Config::default(); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); -} - -#[test] -fn format_lines_errors_are_reported_with_tabs() { - let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); - let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); - let config = Config::from_toml("hard_tabs = true").unwrap(); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); -} - -// For each file, run rustfmt and collect the output. -// Returns the number of files checked and the number of failures. -fn check_files(files: Vec) -> (Vec, u32, u32) { - let mut count = 0; - let mut fails = 0; - let mut reports = vec![]; - - for file_name in files { - debug!("Testing '{}'...", file_name.display()); - - match idempotent_check(&file_name) { - Ok(ref report) if report.has_warnings() => { - print!("{}", report); - fails += 1; - } - Ok(report) => reports.push(report), - Err(err) => { - if let IdempotentCheckError::Mismatch(msg) = err { - print_mismatches_default_message(msg); - } - fails += 1; - } - } - - count += 1; - } - - (reports, count, fails) -} - -fn print_mismatches_default_message(result: HashMap>) { - let mut t = term::stdout().unwrap(); - for (file_name, diff) in result { - let mismatch_msg_formatter = - |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); - print_diff(diff, &mismatch_msg_formatter, Color::Auto); - } - - t.reset().unwrap(); -} - -fn print_mismatches String>( - result: HashMap>, - mismatch_msg_formatter: T, -) { - let mut t = term::stdout().unwrap(); - for (_file_name, diff) in result { - print_diff(diff, &mismatch_msg_formatter, Color::Auto); - } - - t.reset().unwrap(); -} - -fn read_config(filename: &Path) -> Config { - let sig_comments = read_significant_comments(filename); - // Look for a config file... If there is a 'config' property in the significant comments, use - // that. Otherwise, if there are no significant comments at all, look for a config file with - // the same name as the test file. - let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(Path::new)) - } else { - get_config(filename.with_extension("toml").file_name().map(Path::new)) - }; - - for (key, val) in &sig_comments { - if key != "target" && key != "config" { - config.override_value(key, val); - } - } - - // Don't generate warnings for to-do items. - config.set().report_todo(ReportTactic::Never); - - config -} - -fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { - let filepath = filepath.into(); - let input = Input::File(filepath); - format_input::(input, config, None).unwrap() -} - -pub enum IdempotentCheckError { - Mismatch(HashMap>), - Parse, -} - -pub fn idempotent_check(filename: &PathBuf) -> Result { - let sig_comments = read_significant_comments(filename); - let config = read_config(filename); - let (error_summary, file_map, format_report) = format_file(filename, &config); - if error_summary.has_parsing_errors() { - return Err(IdempotentCheckError::Parse); - } - - let mut write_result = HashMap::new(); - for &(ref filename, ref text) in &file_map { - let mut v = Vec::new(); - // Won't panic, as we're not doing any IO. - write_system_newlines(&mut v, text, &config).unwrap(); - // Won't panic, we are writing correct utf8. - let one_result = String::from_utf8(v).unwrap(); - if let FileName::Real(ref filename) = *filename { - write_result.insert(filename.to_owned(), one_result); - } - } - - let target = sig_comments.get("target").map(|x| &(*x)[..]); - - handle_result(write_result, target).map(|_| format_report) -} - -// Reads test config file using the supplied (optional) file name. If there's no file name or the -// file doesn't exist, just return the default config. Otherwise, the file must be read -// successfully. -fn get_config(config_file: Option<&Path>) -> Config { - let config_file_name = match config_file { - None => return Default::default(), - Some(file_name) => { - let mut full_path = PathBuf::from("tests/config/"); - full_path.push(file_name); - if !full_path.exists() { - return Default::default(); - }; - full_path - } - }; - - let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); - let mut def_config = String::new(); - def_config_file - .read_to_string(&mut def_config) - .expect("Couldn't read config"); - - Config::from_toml(&def_config).expect("Invalid toml") -} - -// Reads significant comments of the form: // rustfmt-key: value -// into a hash map. -fn read_significant_comments(file_name: &Path) -> HashMap { - let file = - fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); - let reader = BufReader::new(file); - let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; - let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); - - // Matches lines containing significant comments or whitespace. - let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") - .expect("Failed creating pattern 2"); - - reader - .lines() - .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(line)) - .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { - ( - capture - .get(1) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - capture - .get(2) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - ) - }) - }) - .collect() -} - -// Compare output to input. -// TODO: needs a better name, more explanation. -fn handle_result( - result: HashMap, - target: Option<&str>, -) -> Result<(), IdempotentCheckError> { - let mut failures = HashMap::new(); - - for (file_name, fmt_text) in result { - // If file is in tests/source, compare to file with same name in tests/target. - let target = get_target(&file_name, target); - let open_error = format!("Couldn't open target {:?}", &target); - let mut f = fs::File::open(&target).expect(&open_error); - - let mut text = String::new(); - let read_error = format!("Failed reading target {:?}", &target); - f.read_to_string(&mut text).expect(&read_error); - - // Ignore LF and CRLF difference for Windows. - if !string_eq_ignore_newline_repr(&fmt_text, &text) { - let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); - assert!( - !diff.is_empty(), - "Empty diff? Maybe due to a missing a newline at the end of a file?" - ); - failures.insert(file_name, diff); - } - } - - if failures.is_empty() { - Ok(()) - } else { - Err(IdempotentCheckError::Mismatch(failures)) - } -} - -// Map source file paths to their target paths. -fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { - if let Some(n) = file_name - .components() - .position(|c| c.as_os_str() == "source") - { - let mut target_file_name = PathBuf::new(); - for (i, c) in file_name.components().enumerate() { - if i == n { - target_file_name.push("target"); - } else { - target_file_name.push(c.as_os_str()); - } - } - if let Some(replace_name) = target { - target_file_name.with_file_name(replace_name) - } else { - target_file_name - } - } else { - // This is either and idempotence check or a self check - file_name.to_owned() - } -} - -#[test] -fn rustfmt_diff_make_diff_tests() { - let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); - assert_eq!( - diff, - vec![ - Mismatch { - line_number: 1, - line_number_orig: 1, - lines: vec![ - DiffLine::Context("a".into()), - DiffLine::Resulting("b".into()), - DiffLine::Expected("e".into()), - DiffLine::Context("c".into()), - DiffLine::Context("d".into()), - ], - }, - ] - ); -} - -#[test] -fn rustfmt_diff_no_diff_test() { - let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); - assert_eq!(diff, vec![]); -} - -// Compare strings without distinguishing between CRLF and LF -fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { - let left = CharsIgnoreNewlineRepr(left.chars().peekable()); - let right = CharsIgnoreNewlineRepr(right.chars().peekable()); - left.eq(right) -} - -struct CharsIgnoreNewlineRepr<'a>(Peekable>); - -impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { - type Item = char; - fn next(&mut self) -> Option { - self.0.next().map(|c| { - if c == '\r' { - if *self.0.peek().unwrap_or(&'\0') == '\n' { - self.0.next(); - '\n' - } else { - '\r' - } - } else { - c - } - }) - } -} - -#[test] -fn string_eq_ignore_newline_repr_test() { - assert!(string_eq_ignore_newline_repr("", "")); - assert!(!string_eq_ignore_newline_repr("", "abc")); - assert!(!string_eq_ignore_newline_repr("abc", "")); - assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); - assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); - assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); -} - -// This enum is used to represent one of three text features in Configurations.md: a block of code -// with its starting line number, the name of a rustfmt configuration option, or the value of a -// rustfmt configuration option. -enum ConfigurationSection { - CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) - ConfigName(String), - ConfigValue(String), -} - -impl ConfigurationSection { - fn get_section>( - file: &mut Enumerate, - ) -> Option { - lazy_static! { - static ref CONFIG_NAME_REGEX: regex::Regex = - regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); - static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) - .expect("Failed creating configuration value pattern"); - } - - loop { - match file.next() { - Some((i, line)) => { - if line.starts_with("```rust") { - // Get the lines of the code block. - let lines: Vec = file.map(|(_i, l)| l) - .take_while(|l| !l.starts_with("```")) - .collect(); - let block = format!("{}\n", lines.join("\n")); - - // +1 to translate to one-based indexing - // +1 to get to first line of code (line after "```") - let start_line = (i + 2) as u32; - - return Some(ConfigurationSection::CodeBlock((block, start_line))); - } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); - } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); - } - } - None => return None, // reached the end of the file - } - } - } -} - -// This struct stores the information about code blocks in the configurations -// file, formats the code blocks, and prints formatting errors. -struct ConfigCodeBlock { - config_name: Option, - config_value: Option, - code_block: Option, - code_block_start: Option, -} - -impl ConfigCodeBlock { - fn new() -> ConfigCodeBlock { - ConfigCodeBlock { - config_name: None, - config_value: None, - code_block: None, - code_block_start: None, - } - } - - fn set_config_name(&mut self, name: Option) { - self.config_name = name; - self.config_value = None; - } - - fn set_config_value(&mut self, value: Option) { - self.config_value = value; - } - - fn set_code_block(&mut self, code_block: String, code_block_start: u32) { - self.code_block = Some(code_block); - self.code_block_start = Some(code_block_start); - } - - fn get_block_config(&self) -> Config { - let mut config = Config::default(); - if self.config_value.is_some() && self.config_value.is_some() { - config.override_value( - self.config_name.as_ref().unwrap(), - self.config_value.as_ref().unwrap(), - ); - } - config - } - - fn code_block_valid(&self) -> bool { - // We never expect to not have a code block. - assert!(self.code_block.is_some() && self.code_block_start.is_some()); - - // See if code block begins with #![rustfmt_skip]. - let fmt_skip = self.code_block - .as_ref() - .unwrap() - .split('\n') - .nth(0) - .unwrap_or("") == "#![rustfmt_skip]"; - - if self.config_name.is_none() && !fmt_skip { - write_message(&format!( - "No configuration name for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - if self.config_value.is_none() && !fmt_skip { - write_message(&format!( - "No configuration value for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - true - } - - fn has_parsing_errors(&self, error_summary: Summary) -> bool { - if error_summary.has_parsing_errors() { - write_message(&format!( - "\u{261d}\u{1f3fd} Cannot format {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return true; - } - - false - } - - fn print_diff(&self, compare: Vec) { - let mut mismatches = HashMap::new(); - mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); - print_mismatches(mismatches, |line_num| { - format!( - "\nMismatch at {}:{}:", - CONFIGURATIONS_FILE_NAME, - line_num + self.code_block_start.unwrap() - 1 - ) - }); - } - - fn formatted_has_diff(&self, file_map: &FileMap) -> bool { - let &(ref _file_name, ref text) = file_map.first().unwrap(); - let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - self.print_diff(compare); - return true; - } - - false - } - - // Return a bool indicating if formatting this code block is an idempotent - // operation. This function also triggers printing any formatting failure - // messages. - fn formatted_is_idempotent(&self) -> bool { - // Verify that we have all of the expected information. - if !self.code_block_valid() { - return false; - } - - let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); - let config = self.get_block_config(); - - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); - - !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) - } - - // Extract a code block from the iterator. Behavior: - // - Rust code blocks are identifed by lines beginning with "```rust". - // - One explicit configuration setting is supported per code block. - // - Rust code blocks with no configuration setting are illegal and cause an - // assertion failure, unless the snippet begins with #![rustfmt_skip]. - // - Configuration names in Configurations.md must be in the form of - // "## `NAME`". - // - Configuration values in Configurations.md must be in the form of - // "#### `VALUE`". - fn extract>( - file: &mut Enumerate, - prev: Option<&ConfigCodeBlock>, - hash_set: &mut HashSet, - ) -> Option { - let mut code_block = ConfigCodeBlock::new(); - code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); - - loop { - match ConfigurationSection::get_section(file) { - Some(ConfigurationSection::CodeBlock((block, start_line))) => { - code_block.set_code_block(block, start_line); - break; - } - Some(ConfigurationSection::ConfigName(name)) => { - assert!( - Config::is_valid_name(&name), - "an unknown configuration option was found: {}", - name - ); - assert!( - hash_set.remove(&name), - "multiple configuration guides found for option {}", - name - ); - code_block.set_config_name(Some(name)); - } - Some(ConfigurationSection::ConfigValue(value)) => { - code_block.set_config_value(Some(value)); - } - None => return None, // end of file was reached - } - } - - Some(code_block) - } -} - -#[test] -fn configuration_snippet_tests() { - // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one - // entry for each Rust code block found. - fn get_code_blocks() -> Vec { - let mut file_iter = BufReader::new( - fs::File::open(Path::new("..").join(CONFIGURATIONS_FILE_NAME)) - .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), - ).lines() - .map(|l| l.unwrap()) - .enumerate(); - let mut code_blocks: Vec = Vec::new(); - let mut hash_set = Config::hash_set(); - - while let Some(cb) = - ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) - { - code_blocks.push(cb); - } - - for name in hash_set { - if !Config::is_hidden_option(&name) { - panic!("{} does not have a configuration guide", name); - } - } - - code_blocks - } - - let blocks = get_code_blocks(); - let failures = blocks - .iter() - .map(|b| b.formatted_is_idempotent()) - .fold(0, |acc, r| acc + (!r as u32)); - - // Display results. - println!("Ran {} configurations tests.", blocks.len()); - assert_eq!(failures, 0, "{} configurations tests failed", failures); -} diff --git a/rustfmt-core/tests/source/assignment.rs b/rustfmt-core/tests/source/assignment.rs deleted file mode 100644 index d5860532086..00000000000 --- a/rustfmt-core/tests/source/assignment.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Test assignment - -fn main() { - let some_var : Type ; - - let mut mutable; - - let variable = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; - - variable = LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; - - let single_line_fit = - DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; - - single_line_fit = 5;single_lit_fit >>= 10; -} - -fn break_meee() { - { - (block_start, block_size, margin_block_start, margin_block_end) = match (block_start, - block_end, - block_size) { - x => 1, - _ => 2, - }; - } -} - -// #2018 -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/rustfmt-core/tests/source/associated-types-bounds-wrapping.rs b/rustfmt-core/tests/source/associated-types-bounds-wrapping.rs deleted file mode 100644 index 8f5e2172569..00000000000 --- a/rustfmt-core/tests/source/associated-types-bounds-wrapping.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-max_width: 100 -// Test proper wrapping of long associated type bounds - -pub trait HttpService { - type WsService: 'static + Service; -} diff --git a/rustfmt-core/tests/source/attrib.rs b/rustfmt-core/tests/source/attrib.rs deleted file mode 100644 index bffe0f3f16d..00000000000 --- a/rustfmt-core/tests/source/attrib.rs +++ /dev/null @@ -1,155 +0,0 @@ -// rustfmt-wrap_comments: true -// Test attributes and doc comments are preserved. - -//! Doc comment - -#![attribute] - -//! Crate doc comment - -// Comment - -// Comment on attribute -#![the(attribute)] - -// Another comment - -#[invalid attribute] -fn foo() {} - -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. - -/// Blah blah blah. -impl Bar { - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - #[an_attribute] - fn foo(&mut self) -> isize { - } - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - pub fn f2(self) { - (foo, bar) - } - - #[another_attribute] - fn f3(self) -> Dog { - } - - /// Blah blah bing. - - #[attrib1] - /// Blah blah bing. - #[attrib2] - // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo loooooooooooong. - /// Blah blah bing. - fn f4(self) -> Cat { - } - - // We want spaces around `=` - #[cfg(feature="nightly")] - fn f5(self) -> Monkey {} -} - -// #984 -struct Foo { - # [ derive ( Clone , PartialEq , Debug , Deserialize , Serialize ) ] - foo: usize, -} - -// #1668 - -/// Default path (*nix) -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -fn foo() { - #[cfg(target_os = "freertos")] - match port_id { - 'a' | 'A' => GpioPort { port_address: GPIO_A }, - 'b' | 'B' => GpioPort { port_address: GPIO_B }, - _ => panic!(), - } - - #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] - let x = 3; -} - -// #1777 -#[test] -#[should_panic(expected = "(")] -#[should_panic(expected = /* ( */ "(")] -#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] -#[should_panic( - /* (((((((( *//* - (((((((((()(((((((( */ - expected = "(" - // (((((((( -)] -fn foo() {} - -// #1799 -fn issue_1799() { - #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 - Some( Err(error) ) ; - - #[allow(unreachable_code)] - // https://github.com/rust-lang/rust/issues/43336 - Some( Err(error) ) ; -} - -// Formatting inner attributes -fn inner_attributes() { - #![ this_is_an_inner_attribute ( foo ) ] - - foo(); -} - -impl InnerAttributes() { - #![ this_is_an_inner_attribute ( foo ) ] - - fn foo() {} -} - -mod InnerAttributes { - #![ this_is_an_inner_attribute ( foo ) ] -} - -fn attributes_on_statements() { - // Local - # [ attr ( on ( local ) ) ] - let x = 3; - - // Item - # [ attr ( on ( item ) ) ] - use foo; - - // Expr - # [ attr ( on ( expr ) ) ] - {} - - // Semi - # [ attr ( on ( semi ) ) ] - foo(); - - // Mac - # [ attr ( on ( mac ) ) ] - foo!(); -} - -// Large derive -#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] -pub struct HP(pub u8); - -// Long `#[doc = "..."]` -struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } diff --git a/rustfmt-core/tests/source/big-impl-block.rs b/rustfmt-core/tests/source/big-impl-block.rs deleted file mode 100644 index 737dd5aeb6a..00000000000 --- a/rustfmt-core/tests/source/big-impl-block.rs +++ /dev/null @@ -1,125 +0,0 @@ -// rustfmt-indent_style: Block - -// #1357 -impl< - 'a, - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - Groupby, - DB, -> InternalBoxedDsl<'a, DB> - for SelectStatement< - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - GroupBy, - > where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} - -// #1689 -impl SubSelectDirect - where - M: select::Selector, - S: event::Stream, - F: for<'t> FnMut(transform::Api< - 't, - Stream>, - >) - -> transform::Api<'t, X>, - X: event::Stream, -{ -} diff --git a/rustfmt-core/tests/source/big-impl-visual.rs b/rustfmt-core/tests/source/big-impl-visual.rs deleted file mode 100644 index 7d906ac37f9..00000000000 --- a/rustfmt-core/tests/source/big-impl-visual.rs +++ /dev/null @@ -1,106 +0,0 @@ -// rustfmt-indent_style: Visual - -// #1357 -impl< - 'a, - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - Groupby, - DB, -> InternalBoxedDsl<'a, DB> - for SelectStatement< - Select, - From, - Distinct, - Where, - Order, - Limit, - Offset, - GroupBy, - > where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl Foo< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> { - fn foo() {} -} -impl Foo - for Bar { - fn foo() {} -} diff --git a/rustfmt-core/tests/source/break-and-continue.rs b/rustfmt-core/tests/source/break-and-continue.rs deleted file mode 100644 index c01d8a07845..00000000000 --- a/rustfmt-core/tests/source/break-and-continue.rs +++ /dev/null @@ -1,23 +0,0 @@ -// break and continue formatting - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a; - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b; - } - - let x = loop { - break 5; - }; - - let x = 'c: loop { - break 'c 5; - }; -} diff --git a/rustfmt-core/tests/source/catch.rs b/rustfmt-core/tests/source/catch.rs deleted file mode 100644 index 64cc9e7a207..00000000000 --- a/rustfmt-core/tests/source/catch.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![feature(catch_expr)] - -fn main() { - let x = do catch { - foo()? - }; - - let x = do catch /* Invisible comment */ { foo()? }; - - let x = do catch { - unsafe { foo()? } - }; - - let y = match (do catch { - foo()? - }) { - _ => (), - }; - - do catch { - foo()?; - }; - - do catch { - // Regular do catch block - }; -} diff --git a/rustfmt-core/tests/source/chains-visual.rs b/rustfmt-core/tests/source/chains-visual.rs deleted file mode 100644 index 466f6840887..00000000000 --- a/rustfmt-core/tests/source/chains-visual.rs +++ /dev/null @@ -1,159 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Visual -// Test chain formatting. - -fn main() { - // Don't put chains on a single line if it wasn't so in source. - let a = b .c - .d.1 - .foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x() - .y(|| match cond() { true => (), false => () }); - - loong_func() - .quux(move || if true { - 1 - } else { - 2 - }); - - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }).method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx - .map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }).filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { - field1: val1, - field2: val2, - }; - - let x = Foo { - field1: val1, - field2: val2, - }.method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } - - if cond { some(); } else { none(); } - .bar() - .baz(); - - Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); - - Foo { y: i_am_multi_line, z: ok } - .baz(|| { - force(); multiline(); - }) - .quux(); - - a + match x { true => "yay!", false => "boo!" }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained( - self.id, constraints)).unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn issue_1389() { - let names = String::from_utf8(names)?.split('|').map(str::to_owned).collect(); -} - -fn issue1217() -> Result { -let random_chars: String = OsRng::new()? - .gen_ascii_chars() - .take(self.bit_length) - .collect(); - - Ok(Mnemonic::new(&random_chars)) -} - -fn issue1236(options: Vec) -> Result> { -let process = Command::new("dmenu").stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .chain_err(|| "failed to spawn dmenu")?; -} - -fn issue1434() { - for _ in 0..100 { - let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { - format!("could not read prototype ID at offset {:#010x}", - current_offset) - })?; - } -} - -fn issue2264() { - { - something.function() - .map(|| { - if let a_very_very_very_very_very_very_very_very_long_variable = - compute_this_variable() - { - println!("Hello"); - } - }) - .collect(); - } -} diff --git a/rustfmt-core/tests/source/chains.rs b/rustfmt-core/tests/source/chains.rs deleted file mode 100644 index 0ed52ae61be..00000000000 --- a/rustfmt-core/tests/source/chains.rs +++ /dev/null @@ -1,231 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-use_small_heuristics: false -// Test chain formatting. - -fn main() { - let a = b .c - .d.1 - .foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); - - let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x() - .y(|| match cond() { true => (), false => () }); - - loong_func() - .quux(move || if true { - 1 - } else { - 2 - }); - - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }).method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx - .map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - body.fold(Body::new(), |mut body, chunk| { - body.extend(chunk); - Ok(body) - }).and_then(move |body| { - let req = Request::from_parts(parts, body); - f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) - }); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }).filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { - field1: val1, - field2: val2, - }; - - let x = Foo { - field1: val1, - field2: val2, - }.method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } - - if cond { some(); } else { none(); } - .bar() - .baz(); - - Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); - - Foo { y: i_am_multi_line, z: ok } - .baz(|| { - force(); multiline(); - }) - .quux(); - - a + match x { true => "yay!", false => "boo!" }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained( - self.id, constraints)).unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn try_shorthand() { - let x = expr?; - let y = expr.kaas()?.test(); - let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; - let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); - let zzzz = expr?.another?.another?.another?.another?; - let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??; - - let y = a.very .loooooooooooooooooooooooooooooooooooooong() .chain() - .inside() .weeeeeeeeeeeeeee()? .test() .0 - .x; - - parameterized(f, - substs, - def_id, - Ns::Value, - &[], - |tcx| tcx.lookup_item_type(def_id).generics)?; - fooooooooooooooooooooooooooo()?.bar()?.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; -} - -fn issue_1004() { - match *self { - ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), - } - ?; - - ty::tls::with(|tcx| { - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - }) - ?; -} - -fn issue1392() { - test_method(r#" - if foo { - a(); - } - else { - b(); - } - "#.trim()); -} - -// #2067 -impl Settings { - fn save(&self) -> Result<()> { - let mut file = File::create(&settings_path).chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; - } -} - -fn issue2126() { - { - { - { - { - { - let x = self.span_from(sub_span.expect("No span found for struct arant variant")); - self.sspanpan_from_span(sub_span.expect("No span found for struct variant")); - let x = self.spanpan_from_span(sub_span.expect("No span found for struct variant"))?; - } - } - } - } - } -} - -// #2200 -impl Foo { - pub fn from_ast(diagnostic: &::errors::Handler, - attrs: &[ast::Attribute]) -> Attributes { - let other_attrs = attrs.iter().filter_map(|attr| { - attr.with_desugared_doc(|attr| { - if attr.check_name("doc") { - if let Some(mi) = attr.meta() { - if let Some(value) = mi.value_str() { - doc_strings.push(DocFragment::Include(line, - attr.span, - filename, - contents)); - } - } - } - }) - }).collect(); - } -} - -// #2415 -// Avoid orphan in chain -fn issue2415() { - let base_url = (|| { - // stuff - - Ok((|| { - // stuff - Some(value.to_string()) - })() - .ok_or("")?) - })() - .unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); -} diff --git a/rustfmt-core/tests/source/closure-block-inside-macro.rs b/rustfmt-core/tests/source/closure-block-inside-macro.rs deleted file mode 100644 index c1260592083..00000000000 --- a/rustfmt-core/tests/source/closure-block-inside-macro.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Block - -// #1547 -fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { - let index = *first as usize; - if index >= ENCODINGS.len() { - return; - } - let encoding = ENCODINGS[index]; - dispatch_test(encoding, &data[1..]); -}); diff --git a/rustfmt-core/tests/source/closure.rs b/rustfmt-core/tests/source/closure.rs deleted file mode 100644 index e93cc3fb40f..00000000000 --- a/rustfmt-core/tests/source/closure.rs +++ /dev/null @@ -1,213 +0,0 @@ -// rustfmt-normalize_comments: true -// Closures - -fn main() { - let square = ( |i: i32 | i * i ); - - let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); - - let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - }; - - let loooooooooooooong_name = |field| { - // format comments. - if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo() - } else { - field.span.lo() - }}; - - let unblock_me = |trivial| { - closure() - }; - - let empty = |arg| {}; - - let simple = |arg| { /* comment formatting */ foo(arg) }; - - let test = | | { do_something(); do_something_else(); }; - - let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - - let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; - - let simple_closure = move || -> () {}; - - let closure = |input: Ty| -> Option { - foo() - }; - - let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; - - |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; - arg2 * arg1 - temp }; - - let block_body_with_comment = args.iter() - .map(|a| { - // Emitting only dep-info is possible only for final crate type, as - // as others may emit required metadata for dependent crate types - if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { - "--emit=dep-info" - } else { a } - }); -} - -fn issue311() { - let func = |x| println!("{}", x); - - (func)(0.0); -} - -fn issue863() { - let closure = |x| match x { - 0 => true, - _ => false, - } == true; -} - -fn issue934() { - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; - - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish(); - }; -} - -impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { - pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { - match (&left.node, &right.node) { - (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || - swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) - } - } - } -} - -fn foo() { - lifetimes_iter___map(|lasdfasfd| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi() - }; - }); -} - -fn issue1405() { - open_raw_fd(fd, b'r') - .and_then(|file| Capture::new_raw(None, |_, err| unsafe { - raw::pcap_fopen_offline(file, err) - })); -} - -fn issue1466() { - let vertex_buffer = frame.scope(|ctx| { - let buffer = - ctx.create_host_visible_buffer::>(&vertices); - ctx.create_device_local_buffer(buffer) - }); -} - -fn issue470() { - {{{ - let explicit_arg_decls = - explicit_arguments.into_iter() - .enumerate() - .map(|(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); - block = this.pattern(block, - argument_extent, - hair::PatternRef::Hair(pattern), - &lvalue); - ArgDecl { ty: ty } - }); - }}} -} - -// #1509 -impl Foo { - pub fn bar(&self) { - Some(SomeType { - push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { - Ok(f) - })), - }) - } -} - -fn issue1329() { - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter -} - -fn issue325() { - let f = || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; -} - -fn issue1697() { - Test.func_a(A_VERY_LONG_CONST_VARIABLE_NAME, move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4) -} - -fn issue1694() { - foooooo(|_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| format!("refs/pull/{}/merge", pr_id)) -} - -fn issue1713() { - rayon::join( - || recurse(left, is_less, pred, limit), - || recurse(right, is_less, Some(pivot), limit), - ); - - rayon::join( - 1, - || recurse(left, is_less, pred, limit), - 2, - || recurse(right, is_less, Some(pivot), limit), - ); -} - -fn issue2063() { - |ctx: Ctx<(String, String)>| -> io::Result { - Ok(Response::new().with_body(ctx.params.0)) - } -} - -fn issue1524() { - let f = |x| {{{{x}}}}; - let f = |x| {{{x}}}; - let f = |x| {{x}}; - let f = |x| {x}; - let f = |x| x; -} - -fn issue2171() { - foo(|| unsafe { - if PERIPHERALS { - loop {} - } else { - PERIPHERALS = true; - } - }) -} - -fn issue2207() { - a.map(|_| unsafe { - a_very_very_very_very_very_very_very_long_function_name_or_anything_else() - }.to_string()) -} - -fn issue2262() { - result.init(&mut result.slave.borrow_mut(), &mut (result.strategy)()).map_err(|factory| Error { - factory, - slave: None, - })?; -} diff --git a/rustfmt-core/tests/source/comment.rs b/rustfmt-core/tests/source/comment.rs deleted file mode 100644 index b6ce5267fcb..00000000000 --- a/rustfmt-core/tests/source/comment.rs +++ /dev/null @@ -1,90 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//! Doc comment -fn test() { - /*! - * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam */ - -// comment - // comment2 - - code(); /* leave this comment alone! - * ok? */ - - /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - * viverra nec consectetur ante hendrerit. Donec et mollis dolor. - * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - * felis, pulvinar a semper sed, adipiscing id dolor. */ - - // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); //dontchangeme - // or me - - // #1388 - const EXCEPTION_PATHS: &'static [&'static str] = - &[// std crates - "src/libstd/sys/", // Platform-specific code for std lives here. - "src/bootstrap"]; -} - - /// test123 -fn doc_comment() { -} - -fn chains() { - foo.bar(|| { - let x = 10; - /* comment */ x }) -} - -fn issue_1086() { - /**/ -} - -/* - * random comment */ - -fn main() {/* Test */} - -// #1643 -fn some_fn() /* some comment */ -{ -} - -fn some_fn1() -// some comment -{ -} - -fn some_fn2() // some comment -{ -} - -fn some_fn3() /* some comment some comment some comment some comment some comment some comment so */ -{ -} - -fn some_fn4() -/* some comment some comment some comment some comment some comment some comment some comment */ -{ -} - -// #1603 -pub enum Foo { - A, // `/** **/` - B, // `/*!` - C, -} diff --git a/rustfmt-core/tests/source/comment2.rs b/rustfmt-core/tests/source/comment2.rs deleted file mode 100644 index d68bb5483dc..00000000000 --- a/rustfmt-core/tests/source/comment2.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-wrap_comments: true - -/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. -pub mod foo {} diff --git a/rustfmt-core/tests/source/comment3.rs b/rustfmt-core/tests/source/comment3.rs deleted file mode 100644 index f19a8586334..00000000000 --- a/rustfmt-core/tests/source/comment3.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-wrap_comments: true - -//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. - -pub mod foo {} diff --git a/rustfmt-core/tests/source/comment4.rs b/rustfmt-core/tests/source/comment4.rs deleted file mode 100644 index ff1445378d7..00000000000 --- a/rustfmt-core/tests/source/comment4.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow(dead_code)] // bar - -//! Doc comment -fn test() { -// comment - // comment2 - - code(); /* leave this comment alone! - * ok? */ - - /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - * viverra nec consectetur ante hendrerit. Donec et mollis dolor. - * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - * felis, pulvinar a semper sed, adipiscing id dolor. */ - - // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); //dontchangeme - // or me -} - - /// test123 -fn doc_comment() { -} - -/* -Regression test for issue #956 - -(some very important text) -*/ - -/* -fn debug_function() { - println!("hello"); -} -// */ - -#[link_section=".vectors"] -#[no_mangle] // Test this attribute is preserved. -#[cfg_attr(rustfmt, rustfmt_skip)] -pub static ISSUE_1284: [i32; 16] = []; diff --git a/rustfmt-core/tests/source/comment5.rs b/rustfmt-core/tests/source/comment5.rs deleted file mode 100644 index 2835d8b2578..00000000000 --- a/rustfmt-core/tests/source/comment5.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//@ special comment -//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@ -//@foo -fn test() {} - -//@@@ another special comment -//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@@@ -//@@@foo -fn bar() {} diff --git a/rustfmt-core/tests/source/comment_crlf_newline.rs b/rustfmt-core/tests/source/comment_crlf_newline.rs deleted file mode 100644 index 7a65f762f6c..00000000000 --- a/rustfmt-core/tests/source/comment_crlf_newline.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true -/* Block comments followed by CRLF newlines should not an extra newline at the end */ - -/* Something else */ diff --git a/rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs b/rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs deleted file mode 100644 index c6058a55b0a..00000000000 --- a/rustfmt-core/tests/source/configs/blank_lines_lower_bound/1.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-blank_lines_lower_bound: 1 - -fn foo() {} -fn bar() {} -// comment -fn foobar() {} - -fn foo1() {} -fn bar1() {} - -// comment - -fn foobar1() {} diff --git a/rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs b/rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs deleted file mode 100644 index d3bd9ac09aa..00000000000 --- a/rustfmt-core/tests/source/configs/brace_style/fn_always_next_line.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { - // body -} diff --git a/rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs b/rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs deleted file mode 100644 index 78a4495243d..00000000000 --- a/rustfmt-core/tests/source/configs/brace_style/fn_prefer_same_line.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { - // body -} diff --git a/rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs b/rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs deleted file mode 100644 index 3b78932e177..00000000000 --- a/rustfmt-core/tests/source/configs/brace_style/fn_same_line_where.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { - // body -} diff --git a/rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs b/rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs deleted file mode 100644 index 0cc19b34da7..00000000000 --- a/rustfmt-core/tests/source/configs/brace_style/item_always_next_line.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Item brace style - -enum Foo {} - -struct Bar {} - -struct Lorem { - ipsum: bool, -} - -struct Dolor where T: Eq { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs b/rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs deleted file mode 100644 index 4412bc869a2..00000000000 --- a/rustfmt-core/tests/source/configs/brace_style/item_prefer_same_line.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor where T: Eq { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs b/rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs deleted file mode 100644 index b8e69147dc5..00000000000 --- a/rustfmt-core/tests/source/configs/brace_style/item_same_line_where.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor where T: Eq { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/rustfmt-core/tests/source/configs/comment_width/above.rs b/rustfmt-core/tests/source/configs/comment_width/above.rs deleted file mode 100644 index 36187ce0af4..00000000000 --- a/rustfmt-core/tests/source/configs/comment_width/above.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/rustfmt-core/tests/source/configs/comment_width/below.rs b/rustfmt-core/tests/source/configs/comment_width/below.rs deleted file mode 100644 index abbc5930c4c..00000000000 --- a/rustfmt-core/tests/source/configs/comment_width/below.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 80 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/rustfmt-core/tests/source/configs/comment_width/ignore.rs b/rustfmt-core/tests/source/configs/comment_width/ignore.rs deleted file mode 100644 index c86e71c2898..00000000000 --- a/rustfmt-core/tests/source/configs/comment_width/ignore.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: false -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs b/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs deleted file mode 100644 index 3b967f35a8e..00000000000 --- a/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: false -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, _, _) = (1, 2, 3, 4); -} diff --git a/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs b/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs deleted file mode 100644 index 3798a6b9902..00000000000 --- a/rustfmt-core/tests/source/configs/condense_wildcard_suffixes/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: true -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, _, _) = (1, 2, 3, 4); -} diff --git a/rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs b/rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs deleted file mode 100644 index c4ddad9ce27..00000000000 --- a/rustfmt-core/tests/source/configs/control_brace_style/always_next_line.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine -// Control brace style - -fn main() { - if lorem { println!("ipsum!"); } else { println!("dolor!"); } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs b/rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs deleted file mode 100644 index a9c699d27e3..00000000000 --- a/rustfmt-core/tests/source/configs/control_brace_style/always_same_line.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine -// Control brace style - -fn main() { - if lorem { println!("ipsum!"); } else { println!("dolor!"); } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs b/rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs deleted file mode 100644 index 1a74a28f26a..00000000000 --- a/rustfmt-core/tests/source/configs/control_brace_style/closing_next_line.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine -// Control brace style - -fn main() { - if lorem { println!("ipsum!"); } else { println!("dolor!"); } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/rustfmt-core/tests/source/configs/disable_all_formatting/false.rs b/rustfmt-core/tests/source/configs/disable_all_formatting/false.rs deleted file mode 100644 index 834ca7a3c89..00000000000 --- a/rustfmt-core/tests/source/configs/disable_all_formatting/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: false -// Disable all formatting - -fn main() { - if lorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/rustfmt-core/tests/source/configs/disable_all_formatting/true.rs b/rustfmt-core/tests/source/configs/disable_all_formatting/true.rs deleted file mode 100644 index 56955bf384d..00000000000 --- a/rustfmt-core/tests/source/configs/disable_all_formatting/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: true -// Disable all formatting - -fn main() { - iflorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/rustfmt-core/tests/source/configs/empty_item_single_line/false.rs b/rustfmt-core/tests/source/configs/empty_item_single_line/false.rs deleted file mode 100644 index 8fa74f28802..00000000000 --- a/rustfmt-core/tests/source/configs/empty_item_single_line/false.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-empty_item_single_line: false -// Empty impl on single line - -impl Lorem { - -} - -impl Ipsum { - -} - -fn lorem() { -} - -fn lorem() { - -} diff --git a/rustfmt-core/tests/source/configs/empty_item_single_line/true.rs b/rustfmt-core/tests/source/configs/empty_item_single_line/true.rs deleted file mode 100644 index 02e703d1904..00000000000 --- a/rustfmt-core/tests/source/configs/empty_item_single_line/true.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-empty_item_single_line: true -// Empty impl on single line - -impl Lorem { - -} - -impl Ipsum { - -} - -fn lorem() { -} - -fn lorem() { - -} diff --git a/rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs b/rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs deleted file mode 100644 index fa70ae78352..00000000000 --- a/rustfmt-core/tests/source/configs/error_on_line_overflow/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// Error on line overflow - -fn main() { - let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; -} diff --git a/rustfmt-core/tests/source/configs/fn_args_density/compressed.rs b/rustfmt-core/tests/source/configs/fn_args_density/compressed.rs deleted file mode 100644 index 86c0b42e53c..00000000000 --- a/rustfmt-core/tests/source/configs/fn_args_density/compressed.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/rustfmt-core/tests/source/configs/fn_args_density/tall.rs b/rustfmt-core/tests/source/configs/fn_args_density/tall.rs deleted file mode 100644 index fc400e1c113..00000000000 --- a/rustfmt-core/tests/source/configs/fn_args_density/tall.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Tall -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/rustfmt-core/tests/source/configs/fn_args_density/vertical.rs b/rustfmt-core/tests/source/configs/fn_args_density/vertical.rs deleted file mode 100644 index 20b1427d83d..00000000000 --- a/rustfmt-core/tests/source/configs/fn_args_density/vertical.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Vertical -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/rustfmt-core/tests/source/configs/fn_single_line/false.rs b/rustfmt-core/tests/source/configs/fn_single_line/false.rs deleted file mode 100644 index 3d092f0c0bf..00000000000 --- a/rustfmt-core/tests/source/configs/fn_single_line/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_single_line: false -// Single-expression function on single line - -fn lorem() -> usize { - 42 -} - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/rustfmt-core/tests/source/configs/fn_single_line/true.rs b/rustfmt-core/tests/source/configs/fn_single_line/true.rs deleted file mode 100644 index 3cb0fdedf0b..00000000000 --- a/rustfmt-core/tests/source/configs/fn_single_line/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_single_line: true -// Single-expression function on single line - -fn lorem() -> usize { - 42 -} - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/rustfmt-core/tests/source/configs/force_explicit_abi/false.rs b/rustfmt-core/tests/source/configs/force_explicit_abi/false.rs deleted file mode 100644 index 3c48f8e0c78..00000000000 --- a/rustfmt-core/tests/source/configs/force_explicit_abi/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: false -// Force explicit abi - -extern { - pub static lorem: c_int; -} diff --git a/rustfmt-core/tests/source/configs/force_explicit_abi/true.rs b/rustfmt-core/tests/source/configs/force_explicit_abi/true.rs deleted file mode 100644 index e5ff6cf7dd7..00000000000 --- a/rustfmt-core/tests/source/configs/force_explicit_abi/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: true -// Force explicit abi - -extern { - pub static lorem: c_int; -} diff --git a/rustfmt-core/tests/source/configs/force_multiline_block/false.rs b/rustfmt-core/tests/source/configs/force_multiline_block/false.rs deleted file mode 100644 index b97e348e5da..00000000000 --- a/rustfmt-core/tests/source/configs/force_multiline_block/false.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-force_multiline_blocks: false -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| { - match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - } - }); -} diff --git a/rustfmt-core/tests/source/configs/force_multiline_block/true.rs b/rustfmt-core/tests/source/configs/force_multiline_block/true.rs deleted file mode 100644 index db9d3de4614..00000000000 --- a/rustfmt-core/tests/source/configs/force_multiline_block/true.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-force_multiline_blocks: true -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => if ipsum { - println!("dolor"); - }, - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - }); -} diff --git a/rustfmt-core/tests/source/configs/format_strings/false.rs b/rustfmt-core/tests/source/configs/format_strings/false.rs deleted file mode 100644 index ecca0d7d1fc..00000000000 --- a/rustfmt-core/tests/source/configs/format_strings/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/rustfmt-core/tests/source/configs/format_strings/true.rs b/rustfmt-core/tests/source/configs/format_strings/true.rs deleted file mode 100644 index 33731447821..00000000000 --- a/rustfmt-core/tests/source/configs/format_strings/true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 50 -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/rustfmt-core/tests/source/configs/hard_tabs/false.rs b/rustfmt-core/tests/source/configs/hard_tabs/false.rs deleted file mode 100644 index bf92162b424..00000000000 --- a/rustfmt-core/tests/source/configs/hard_tabs/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: false -// Hard tabs - -fn lorem() -> usize { -42 // spaces before 42 -} diff --git a/rustfmt-core/tests/source/configs/hard_tabs/true.rs b/rustfmt-core/tests/source/configs/hard_tabs/true.rs deleted file mode 100644 index 738922a4dfb..00000000000 --- a/rustfmt-core/tests/source/configs/hard_tabs/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: true -// Hard tabs - -fn lorem() -> usize { -42 // spaces before 42 -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_args.rs b/rustfmt-core/tests/source/configs/indent_style/block_args.rs deleted file mode 100644 index 4d2d280a16b..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_args.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-indent_style: Block -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { - // body -} - -// #1441 -extern "system" { - pub fn GetConsoleHistoryInfo(console_history_info: *mut ConsoleHistoryInfo) -> Boooooooooooooool; -} - -// rustfmt should not add trailing comma for variadic function. See #1623. -extern "C" { - pub fn variadic_fn(first_parameter: FirstParameterType, - second_parameter: SecondParameterType, - ...); -} - -// #1652 -fn deconstruct(foo: Bar) -> (SocketAddr, Header, Method, RequestUri, HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_array.rs b/rustfmt-core/tests/source/configs/indent_style/block_array.rs deleted file mode 100644 index 8404f65f471..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_array.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Array layout - -fn main() { - let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_call.rs b/rustfmt-core/tests/source/configs/indent_style/block_call.rs deleted file mode 100644 index c82b6b8e38f..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_call.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-indent_style: Block -// Function call style - -fn main() { - lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); - // #1501 - let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); - - // chain - let x = yooooooooooooo.fooooooooooooooo.baaaaaaaaaaaaar(hello, world); - - // #1380 - { - { - let creds = self.client - .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; - } - } - - // nesting macro and function call - try!(foo(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)); - try!(foo(try!(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx))); -} - -// #1521 -impl Foo { - fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { - unsafe { - Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw())) - } - } -} - -fn issue1420() { - given( - r#" - # Getting started - ... - "#, - ) - .running(waltz) -} - -// #1563 -fn query(conn: &Connection) -> Result<()> { - conn.query_row( - r#" - SELECT title, date - FROM posts, - WHERE DATE(date) = $1 - "#, - &[], - |row| { - Post { - title: row.get(0), - date: row.get(1), - } - }, - )?; - - Ok(()) -} - -// #1449 -fn future_rayon_wait_1_thread() { - // run with only 1 worker thread; this would deadlock if we couldn't make progress - let mut result = None; - ThreadPool::new(Configuration::new().num_threads(1)) - .unwrap() - .install( - || { - scope( - |s| { - use std::sync::mpsc::channel; - let (tx, rx) = channel(); - let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); - // ^^^^ FIXME: why is this needed? - let b = s.spawn_future(a.map(|v| v + 1)); - let c = s.spawn_future(b.map(|v| v + 1)); - s.spawn(move |_| tx.send(20).unwrap()); - result = Some(c.rayon_wait().unwrap()); - }, - ); - }, - ); - assert_eq!(result, Some(22)); -} - -// #1494 -impl Cursor { - fn foo() { - self.cur_type() - .num_template_args() - .or_else(|| { - let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; - - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - }) - .or_else(|| { - let canonical = self.canonical(); - if canonical != *self { - canonical.num_template_args() - } else { - None - } - }); - } -} - -fn issue1581() { - bootstrap.checks.register( - "PERSISTED_LOCATIONS", - move || if locations2.0.inner_mut.lock().poisoned { - Check::new( - State::Error, - "Persisted location storage is poisoned due to a write failure", - ) - } else { - Check::new(State::Healthy, "Persisted location storage is healthy") - }, - ); -} - -fn issue1651() { - { - let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); - } -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_chain.rs b/rustfmt-core/tests/source/configs/indent_style/block_chain.rs deleted file mode 100644 index 41d91469114..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_chain.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Chain indent - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_generic.rs b/rustfmt-core/tests/source/configs/indent_style/block_generic.rs deleted file mode 100644 index 2cf17be56ef..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_generic.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Generics indent - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { - // body -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs b/rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs deleted file mode 100644 index 47a6994f40c..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_struct_lit.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs b/rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs deleted file mode 100644 index c907ec50d45..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_trailing_comma_call.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Block - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); -} diff --git a/rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs b/rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs deleted file mode 100644 index 450491f0270..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/block_where_pred.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Where predicate indent - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/rustfmt-core/tests/source/configs/indent_style/default.rs b/rustfmt-core/tests/source/configs/indent_style/default.rs deleted file mode 100644 index f08f5c64460..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/default.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Where style - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/rustfmt-core/tests/source/configs/indent_style/rfc_where.rs b/rustfmt-core/tests/source/configs/indent_style/rfc_where.rs deleted file mode 100644 index 012840be28d..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/rfc_where.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Block -// Where style - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_args.rs b/rustfmt-core/tests/source/configs/indent_style/visual_args.rs deleted file mode 100644 index 5aa28a62b9c..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_args.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-indent_style: Visual -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { - // body -} - -// #1922 -extern "C" { - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - a: *const lapack_complex_float, - lda: lapack_int, ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int - )-> lapack_int; - - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - lda: lapack_int, ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int - ) -> lapack_int; -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_array.rs b/rustfmt-core/tests/source/configs/indent_style/visual_array.rs deleted file mode 100644 index 05bbf00b1d2..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_array.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Array layout - -fn main() { - let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_call.rs b/rustfmt-core/tests/source/configs/indent_style/visual_call.rs deleted file mode 100644 index 9a679d6bb4c..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_call.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Function call style - -fn main() { - lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_chain.rs b/rustfmt-core/tests/source/configs/indent_style/visual_chain.rs deleted file mode 100644 index b7494875398..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_chain.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Chain indent - -fn main() { - let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_generics.rs b/rustfmt-core/tests/source/configs/indent_style/visual_generics.rs deleted file mode 100644 index 1f910d32d87..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_generics.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Generics indent - -fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { - // body -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs b/rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs deleted file mode 100644 index 45538e70482..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_struct_lit.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs b/rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs deleted file mode 100644 index 9738d397dbf..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_trailing_comma.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); -} diff --git a/rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs b/rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs deleted file mode 100644 index 055806b6862..00000000000 --- a/rustfmt-core/tests/source/configs/indent_style/visual_where_pred.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-indent_style: Visual -// Where predicate indent - -fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { - // body -} diff --git a/rustfmt-core/tests/source/configs/match_arm_blocks/false.rs b/rustfmt-core/tests/source/configs/match_arm_blocks/false.rs deleted file mode 100644 index 53e37e13c4f..00000000000 --- a/rustfmt-core/tests/source/configs/match_arm_blocks/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Wrap match-arms - -fn main() { - match lorem { - true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => { - println!("{}", sit) - } - } -} diff --git a/rustfmt-core/tests/source/configs/match_arm_blocks/true.rs b/rustfmt-core/tests/source/configs/match_arm_blocks/true.rs deleted file mode 100644 index a452b13cd27..00000000000 --- a/rustfmt-core/tests/source/configs/match_arm_blocks/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_arm_blocks: true -// Wrap match-arms - -fn main() { - match lorem { - true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => { - println!("{}", sit) - } - } -} diff --git a/rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs b/rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs deleted file mode 100644 index 70e02955fb0..00000000000 --- a/rustfmt-core/tests/source/configs/match_block_trailing_comma/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: false -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - } - Lorem::Dolor => println!("dolor"), - } -} diff --git a/rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs b/rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs deleted file mode 100644 index b9af3d47202..00000000000 --- a/rustfmt-core/tests/source/configs/match_block_trailing_comma/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - } - Lorem::Dolor => println!("dolor"), - } -} diff --git a/rustfmt-core/tests/source/configs/merge_derives/true.rs b/rustfmt-core/tests/source/configs/merge_derives/true.rs deleted file mode 100644 index 18b8443f0d7..00000000000 --- a/rustfmt-core/tests/source/configs/merge_derives/true.rs +++ /dev/null @@ -1,46 +0,0 @@ -// rustfmt-merge_derives: true -// Merge multiple derives to a single one. - -#[bar] -#[derive(Eq, PartialEq)] -#[foo] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Foo {} - -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Bar {} - -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[derive(Copy, Clone)] -pub enum FooBar {} - -mod foo { -#[bar] -#[derive(Eq, PartialEq)] -#[foo] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Foo {} -} - -mod bar { -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Bar {} -} - -mod foobar { -#[derive(Eq, PartialEq)] -#[derive(Debug)] -#[derive(Copy, Clone)] -pub enum FooBar {} -} diff --git a/rustfmt-core/tests/source/configs/normalize_comments/false.rs b/rustfmt-core/tests/source/configs/normalize_comments/false.rs deleted file mode 100644 index 488962ed936..00000000000 --- a/rustfmt-core/tests/source/configs/normalize_comments/false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: false -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -/* sit amet: */ -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/source/configs/normalize_comments/true.rs b/rustfmt-core/tests/source/configs/normalize_comments/true.rs deleted file mode 100644 index c74a9808e61..00000000000 --- a/rustfmt-core/tests/source/configs/normalize_comments/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: true -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -/* sit amet: */ -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs b/rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs deleted file mode 100644 index 6bef132e5c3..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_extern_crates/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: false - -extern crate foo; -extern crate bar; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs b/rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs deleted file mode 100644 index bdf00f57cda..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_extern_crates/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: true - -extern crate foo; -extern crate bar; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/rustfmt-core/tests/source/configs/reorder_imported_names/false.rs b/rustfmt-core/tests/source/configs/reorder_imported_names/false.rs deleted file mode 100644 index 91db89ceeaa..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_imported_names/false.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: false -// Reorder imported names - -use super::{lorem, ipsum, dolor, sit}; diff --git a/rustfmt-core/tests/source/configs/reorder_imported_names/true.rs b/rustfmt-core/tests/source/configs/reorder_imported_names/true.rs deleted file mode 100644 index 69da6186d5a..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_imported_names/true.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: true -// Reorder imported names - -use super::{lorem, ipsum, dolor, sit}; diff --git a/rustfmt-core/tests/source/configs/reorder_imports/false.rs b/rustfmt-core/tests/source/configs/reorder_imports/false.rs deleted file mode 100644 index 4b85684dc01..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_imports/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_imports: false -// Reorder imports - -use lorem; -use ipsum; -use dolor; -use sit; diff --git a/rustfmt-core/tests/source/configs/reorder_imports/true.rs b/rustfmt-core/tests/source/configs/reorder_imports/true.rs deleted file mode 100644 index 2a40f6d069f..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_imports/true.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-reorder_imports: true -// Reorder imports - -use lorem; -use ipsum; -use dolor; -use sit; - -fn foo() { - use C; - use B; - use A; - - bar(); - - use F; - use E; - use D; -} diff --git a/rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs b/rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs deleted file mode 100644 index 87711bb142b..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_imports_in_group/false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: false -// Reorder imports in group - -/// This comment should stay with `use std::mem;` -use std::mem; -use std::io; - -use lorem; -/// This comment should stay with `use ipsum;` -use ipsum; -use dolor; -use sit; diff --git a/rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs b/rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs deleted file mode 100644 index b5690b89cc0..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_imports_in_group/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: true -// Reorder imports in group - -/// This comment should stay with `use std::mem;` -use std::mem; -use std::io; - -use lorem; -/// This comment should stay with `use ipsum;` -use ipsum; -use dolor; -use sit; diff --git a/rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_modules/dolor/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/source/configs/reorder_modules/false.rs b/rustfmt-core/tests/source/configs/reorder_modules/false.rs deleted file mode 100644 index 56b1aa03ed7..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_modules/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: false -// Reorder modules - -mod lorem; -mod ipsum; -mod dolor; -mod sit; diff --git a/rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_modules/ipsum/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_modules/lorem/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs b/rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_modules/sit/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/source/configs/reorder_modules/true.rs b/rustfmt-core/tests/source/configs/reorder_modules/true.rs deleted file mode 100644 index 79b0ab1e355..00000000000 --- a/rustfmt-core/tests/source/configs/reorder_modules/true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: true -// Reorder modules - -mod lorem; -mod ipsum; -mod dolor; -mod sit; diff --git a/rustfmt-core/tests/source/configs/skip_children/true.rs b/rustfmt-core/tests/source/configs/skip_children/true.rs deleted file mode 100644 index cb2b6fce2d2..00000000000 --- a/rustfmt-core/tests/source/configs/skip_children/true.rs +++ /dev/null @@ -1,3 +0,0 @@ -// rustfmt-skip_children: true - -mod foo ; diff --git a/rustfmt-core/tests/source/configs/space_before_colon/true.rs b/rustfmt-core/tests/source/configs/space_before_colon/true.rs deleted file mode 100644 index 0a597602528..00000000000 --- a/rustfmt-core/tests/source/configs/space_before_colon/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-space_before_colon: true -// Space before colon - -fn lorem(t : T) { - let ipsum: Dolor = sit; -} - -const LOREM : Lorem = Lorem { - ipsum : dolor, - sit : amet, -}; diff --git a/rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs b/rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs deleted file mode 100644 index 11ca76b1345..00000000000 --- a/rustfmt-core/tests/source/configs/spaces_around_ranges/false.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: false -// Spaces around ranges - -fn main() { - let lorem = 0 .. 10; - let ipsum = 0 ..= 10; - - match lorem { - 1 .. 5 => foo(), - _ => bar, - } - - match lorem { - 1 ..= 5 => foo(), - _ => bar, - } - - match lorem { - 1 ... 5 => foo(), - _ => bar, - } -} diff --git a/rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs b/rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs deleted file mode 100644 index 50170892130..00000000000 --- a/rustfmt-core/tests/source/configs/spaces_around_ranges/true.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: true -// Spaces around ranges - -fn main() { - let lorem = 0..10; - let ipsum = 0..=10; - - match lorem { - 1..5 => foo(), - _ => bar, - } - - match lorem { - 1..=5 => foo(), - _ => bar, - } - - match lorem { - 1...5 => foo(), - _ => bar, - } -} diff --git a/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs b/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs deleted file mode 100644 index 908373ca9b0..00000000000 --- a/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: false -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} diff --git a/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs b/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs deleted file mode 100644 index 2e3c92da2fc..00000000000 --- a/rustfmt-core/tests/source/configs/spaces_within_parens_and_brackets/true.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: true -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} - -enum E { - A(u32), - B(u32, u32), - C(u32, u32, u32), - D(), -} - -struct TupleStruct0(); -struct TupleStruct1(u32); -struct TupleStruct2(u32, u32); - -fn fooEmpty() {} - -fn foo(e: E, _: u32) -> (u32, u32) { - // Tuples - let t1 = (); - let t2 = (1,); - let t3 = (1, 2); - - let ts0 = TupleStruct0(); - let ts1 = TupleStruct1(1); - let ts2 = TupleStruct2(1, 2); - - // Tuple pattern - let (a,b,c) = (1,2,3); - - // Expressions - let x = (1 + 2) * (3); - - // Function call - fooEmpty(); - foo(1, 2); - - // Pattern matching - match e { - A(_) => (), - B(_, _) => (), - C(..) => (), - D => (), - } - - (1,2) -} - -struct Foo { - i: T, -} - -struct Bar { - i: T, - e: E, -} - -struct Foo<'a> { - i: &'a str, -} - -enum E { - T(T), -} - -enum E { - T(T), - S(S), -} - -fn foo(a: T) { - foo::(10); -} - -fn foo(a: T, b: E) { - foo::(10, "bar"); -} - -fn foo(a: T, b: E) { - foo::(10, "bar"); - - let opt: Option; - let res: Result; -} - -fn foo<'a>(a: &'a str) { - foo("foo"); -} - -fn foo<'a, 'b>(a: &'a str, b: &'b str) { - foo("foo", "bar"); -} - -impl Foo { - fn bar() { - ::bar(); - } -} - -trait MyTrait {} -impl MyTrait for Foo {} - -fn foo() where for<'a> u32: 'a {} - -fn main() { - let arr: [i32; 5] = [1, 2, 3, 4, 5]; - let arr: [i32; 500] = [0; 500]; - - let v = vec![1, 2, 3]; - assert_eq!(arr, [1, 2, 3]); - - let i = arr[0]; - - let slice = &arr[1..2]; - - let line100_________________________________________________________________________ = [1, 2]; - let line101__________________________________________________________________________ = [1, 2]; - let line102___________________________________________________________________________ = [1, 2]; - let line103____________________________________________________________________________ = [1, 2]; - let line104_____________________________________________________________________________ = [1, 2]; - - let line100_____________________________________________________________________ = vec![1, 2]; - let line101______________________________________________________________________ = vec![1, 2]; - let line102_______________________________________________________________________ = vec![1, 2]; - let line103________________________________________________________________________ = vec![1, 2]; - let line104_________________________________________________________________________ = vec![1, 2]; -} - -fn f(slice: &[i32]) {} diff --git a/rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs b/rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs deleted file mode 100644 index e68340b027d..00000000000 --- a/rustfmt-core/tests/source/configs/struct_field_align_threshold/20.rs +++ /dev/null @@ -1,383 +0,0 @@ -// rustfmt-struct_field_align_threshold: 20 -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false - -struct Foo { - x: u32, - yy: u32, // comment - zzz: u32, -} - -pub struct Bar { - x: u32, - yy: u32, - zzz: u32, - - xxxxxxx: u32, -} - -fn main() { - let foo = Foo { - x: 0, - yy: 1, - zzz: 2, - }; - - let bar = Bar { - x: 0, - yy: 1, - zzz: 2, - - xxxxxxx: 3, - }; -} - - /// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] //only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct -NewInt (pub i32, SomeType /* inline comment */, T /* sup */ - - - ); - -struct Qux<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy> -( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C - -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - - - - c: C, // Comment C -} - -struct Baz { - - a: A, - - b: B, - c: C, - - - - - d: D - -} - -struct Baz -{ - // Comment A - a: A, - - // Comment B -b: B, - // Comment C - c: C,} - -// Will this be a one-liner? -struct Tuple( - A, //Comment - B -); - -pub struct State time::Timespec> { now: F } - -pub struct State ()> { now: F } - -pub struct State { now: F } - -struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color - foo: i32} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB - //Another pre comment - #[attr1] - #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(T); -struct Foo(T) where T: Copy, T: Eq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU); - -mod m { - struct X where T: Sized { - a: T, - } -} - -struct Foo(TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn( obj: - *const libc::c_void, tracer : *mut JSTracer ), -} - -struct Foo {} -struct Foo { - } -struct Foo { - // comment - } -struct Foo { - // trailing space -> - - - } -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:f() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { memb: T } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S{a:0, .. b}; -} - -fn issue201_2() { - let s = S{a: S2{ .. c}, .. b}; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo - { a : 1, b:f( 2)}; - Foo{a:1,b:f(2),..g(3)}; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; - IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { a: bb, c: dd, e: ff }; - - Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ - e: eeeeeeeee }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, .. base }; - Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ - eeeeeeeee }; - Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; -} diff --git a/rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs b/rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs deleted file mode 100644 index 17cad8dde29..00000000000 --- a/rustfmt-core/tests/source/configs/struct_lit_single_line/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-struct_lit_single_line: false -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { ipsum: dolor, sit: amet }; -} diff --git a/rustfmt-core/tests/source/configs/tab_spaces/2.rs b/rustfmt-core/tests/source/configs/tab_spaces/2.rs deleted file mode 100644 index 5c2667bc2c7..00000000000 --- a/rustfmt-core/tests/source/configs/tab_spaces/2.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-tab_spaces: 2 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { -let ipsum = dolor(); -let sit = vec![ -"amet", "consectetur", "adipiscing", "elit." -]; -} diff --git a/rustfmt-core/tests/source/configs/tab_spaces/4.rs b/rustfmt-core/tests/source/configs/tab_spaces/4.rs deleted file mode 100644 index da61bbd42a7..00000000000 --- a/rustfmt-core/tests/source/configs/tab_spaces/4.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-tab_spaces: 4 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { -let ipsum = dolor(); -let sit = vec![ -"amet", "consectetur", "adipiscing", "elit." -]; -} diff --git a/rustfmt-core/tests/source/configs/trailing_comma/always.rs b/rustfmt-core/tests/source/configs/trailing_comma/always.rs deleted file mode 100644 index 57e874cd822..00000000000 --- a/rustfmt-core/tests/source/configs/trailing_comma/always.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-trailing_comma: Always -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; -} diff --git a/rustfmt-core/tests/source/configs/trailing_comma/never.rs b/rustfmt-core/tests/source/configs/trailing_comma/never.rs deleted file mode 100644 index 4da3b996f29..00000000000 --- a/rustfmt-core/tests/source/configs/trailing_comma/never.rs +++ /dev/null @@ -1,23 +0,0 @@ -// rustfmt-trailing_comma: Never -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; - - // #1544 - if let VrMsg::ClientReply {request_num: reply_req_num, value, ..} = msg { - let _ = safe_assert_eq!(reply_req_num, request_num, op); - return Ok((request_num, op, value)); - } - - // #1710 - pub struct FileInput { - input: StringInput, - file_name: OsString, - } - match len { - Some(len) => Ok(new(self.input, self.pos + len)), - None => Err(self), - } -} diff --git a/rustfmt-core/tests/source/configs/trailing_comma/vertical.rs b/rustfmt-core/tests/source/configs/trailing_comma/vertical.rs deleted file mode 100644 index c903e822158..00000000000 --- a/rustfmt-core/tests/source/configs/trailing_comma/vertical.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-trailing_comma: Vertical -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; -} diff --git a/rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs b/rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs deleted file mode 100644 index 223b9a2f0f0..00000000000 --- a/rustfmt-core/tests/source/configs/type_punctuation_density/compressed.rs +++ /dev/null @@ -1,37 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed -// Type punctuation density - -fn lorem() { - // body -} - -struct Foo -where U: Eq + Clone { - // body -} - -trait Foo<'a, T = usize> -where T: 'a + Eq + Clone -{ - type Bar: Eq + Clone; -} - -trait Foo: Eq + Clone { - // body -} - -impl Foo<'a> for Bar -where for<'a> T: 'a + Eq + Clone -{ - // body -} - -fn foo<'a, 'b, 'c>() -where 'a: 'b + 'c -{ - // body -} - -fn Foo + Foo>() { - let i = 6; -} diff --git a/rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs b/rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs deleted file mode 100644 index fe0c0816701..00000000000 --- a/rustfmt-core/tests/source/configs/type_punctuation_density/wide.rs +++ /dev/null @@ -1,37 +0,0 @@ -// rustfmt-type_punctuation_density: Wide -// Type punctuation density - -fn lorem() { - // body -} - -struct Foo -where U: Eq + Clone { - // body -} - -trait Foo<'a, T = usize> -where T: 'a + Eq + Clone -{ - type Bar: Eq + Clone; -} - -trait Foo: Eq + Clone { - // body -} - -impl Foo<'a> for Bar -where for<'a> T: 'a + Eq + Clone -{ - // body -} - -fn foo<'a, 'b, 'c>() -where 'a: 'b + 'c -{ - // body -} - -fn Foo + Foo>() { - let i = 6; -} diff --git a/rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs b/rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs deleted file mode 100644 index 16ce740f1b9..00000000000 --- a/rustfmt-core/tests/source/configs/use_field_init_shorthand/false.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-use_field_init_shorthand: false -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { - x: x, - y: y, - z: z, - }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs b/rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs deleted file mode 100644 index 1e36c6cff35..00000000000 --- a/rustfmt-core/tests/source/configs/use_field_init_shorthand/true.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-use_field_init_shorthand: true -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { - x: x, - y: y, - z: z, - }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/rustfmt-core/tests/source/configs/use_try_shorthand/false.rs b/rustfmt-core/tests/source/configs/use_try_shorthand/false.rs deleted file mode 100644 index de7f8b4a5e2..00000000000 --- a/rustfmt-core/tests/source/configs/use_try_shorthand/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: false -// Use try! shorthand - -fn main() { - let lorem = try!(ipsum.map(|dolor| dolor.sit())); -} diff --git a/rustfmt-core/tests/source/configs/use_try_shorthand/true.rs b/rustfmt-core/tests/source/configs/use_try_shorthand/true.rs deleted file mode 100644 index 9015ec41e5e..00000000000 --- a/rustfmt-core/tests/source/configs/use_try_shorthand/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: true -// Use try! shorthand - -fn main() { - let lorem = try!(ipsum.map(|dolor| dolor.sit())); -} diff --git a/rustfmt-core/tests/source/configs/where_single_line/true.rs b/rustfmt-core/tests/source/configs/where_single_line/true.rs deleted file mode 100644 index daaab865af2..00000000000 --- a/rustfmt-core/tests/source/configs/where_single_line/true.rs +++ /dev/null @@ -1,24 +0,0 @@ -// rustfmt-where_single_line: true -// Where style - - -fn lorem_two_items() -> T where Ipsum: Eq, Lorem: Eq { - // body -} - -fn lorem_multi_line( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) -> T -where - Ipsum: Eq, -{ - // body -} - -fn lorem() -> T where Ipsum: Eq { - // body -} diff --git a/rustfmt-core/tests/source/configs/wrap_comments/false.rs b/rustfmt-core/tests/source/configs/wrap_comments/false.rs deleted file mode 100644 index 48ecd88accb..00000000000 --- a/rustfmt-core/tests/source/configs/wrap_comments/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-wrap_comments: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -} diff --git a/rustfmt-core/tests/source/configs/wrap_comments/true.rs b/rustfmt-core/tests/source/configs/wrap_comments/true.rs deleted file mode 100644 index 39a79a4cacc..00000000000 --- a/rustfmt-core/tests/source/configs/wrap_comments/true.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 50 -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -} - -fn code_block() { - // ```rust - // let x = 3; - // - // println!("x = {}", x); - // ``` -} diff --git a/rustfmt-core/tests/source/control-brace-style-always-next-line.rs b/rustfmt-core/tests/source/control-brace-style-always-next-line.rs deleted file mode 100644 index 9079fb46c0c..00000000000 --- a/rustfmt-core/tests/source/control-brace-style-always-next-line.rs +++ /dev/null @@ -1,44 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - loop { - (); - (); - } - - - 'label: loop // loop comment - { - (); - } - - - cond = true; - while cond { - (); - } - - - 'while_label: while cond { // while comment - (); - } - - - for obj in iter { - for sub_obj in obj - { - 'nested_while_label: while cond { - (); - } - } - } - - match some_var { // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => { - do_stuff(); - val2 - }, - }; -} diff --git a/rustfmt-core/tests/source/control-brace-style-always-same-line.rs b/rustfmt-core/tests/source/control-brace-style-always-same-line.rs deleted file mode 100644 index 1c8f487e7cd..00000000000 --- a/rustfmt-core/tests/source/control-brace-style-always-same-line.rs +++ /dev/null @@ -1,44 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - loop { - (); - (); - } - - - 'label: loop // loop comment - { - (); - } - - - cond = true; - while cond { - (); - } - - - 'while_label: while cond { // while comment - (); - } - - - for obj in iter { - for sub_obj in obj - { - 'nested_while_label: while cond { - (); - } - } - } - - match some_var { // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => { - do_stuff(); - val2 - }, - }; -} diff --git a/rustfmt-core/tests/source/doc.rs b/rustfmt-core/tests/source/doc.rs deleted file mode 100644 index 3b25918b12e..00000000000 --- a/rustfmt-core/tests/source/doc.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-normalize_comments: true -// Part of multiple.rs - -// sadfsdfa -//sdffsdfasdf diff --git a/rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs b/rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs deleted file mode 100644 index 7b4870fc65a..00000000000 --- a/rustfmt-core/tests/source/else-if-brace-style-always-next-line.rs +++ /dev/null @@ -1,54 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - if false - { - (); - (); - } - - if false // lone if comment - { - (); - (); - } - - - let a = - if 0 > 1 { - unreachable!() - } - else - { - 0x0 - }; - - - if true - { - (); - } else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true // else-if-chain if comment - { - (); - } - else if false // else-if-chain else-if comment - { - (); - (); - } else // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs b/rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs deleted file mode 100644 index 41f5305bf8c..00000000000 --- a/rustfmt-core/tests/source/else-if-brace-style-always-same-line.rs +++ /dev/null @@ -1,54 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - if false - { - (); - (); - } - - if false // lone if comment - { - (); - (); - } - - - let a = - if 0 > 1 { - unreachable!() - } - else - { - 0x0 - }; - - - if true - { - (); - } else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true // else-if-chain if comment - { - (); - } - else if false // else-if-chain else-if comment - { - (); - (); - } else // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs b/rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs deleted file mode 100644 index 3b885b3faaa..00000000000 --- a/rustfmt-core/tests/source/else-if-brace-style-closing-next-line.rs +++ /dev/null @@ -1,54 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine - -fn main() { - if false - { - (); - (); - } - - if false // lone if comment - { - (); - (); - } - - - let a = - if 0 > 1 { - unreachable!() - } - else - { - 0x0 - }; - - - if true - { - (); - } else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true // else-if-chain if comment - { - (); - } - else if false // else-if-chain else-if comment - { - (); - (); - } else // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/rustfmt-core/tests/source/empty_file.rs b/rustfmt-core/tests/source/empty_file.rs deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/rustfmt-core/tests/source/enum.rs b/rustfmt-core/tests/source/enum.rs deleted file mode 100644 index f3dbae4b84d..00000000000 --- a/rustfmt-core/tests/source/enum.rs +++ /dev/null @@ -1,194 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Enums test - -#[atrr] -pub enum Test { - A, B(u32, - A /* comment */, - SomeType), - /// Doc comment - C, -} - -pub enum Foo<'a, Y: Baz> where X: Whatever -{ A, } - -enum EmtpyWithComment { - // Some comment -} - -// C-style enum -enum Bar { - A = 1, - #[someAttr(test)] - B = 2, // comment - C, -} - -enum LongVariants { -First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment -VARIANT), - // This is the second variant - Second -} - -enum StructLikeVariants { - Normal(u32, String, ), - StructLike { x: i32, // Test comment - // Pre-comment - #[Attr50] y: SomeType, // Aanother Comment - }, SL { a: A } -} - -enum X { - CreateWebGLPaintTask(Size2D, GLContextAttributes, IpcSender, usize), String>>), // This is a post comment -} - -pub enum EnumWithAttributes { - //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - // Pre Comment - #[rustfmt_skip] - SkippedItem(String,String,), // Post-comment - #[another_attr] - #[attr2] - ItemStruct {x: usize, y: usize}, // Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - // And another - ForcedPreflight // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -} - -pub enum SingleTuple { - // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - Match(usize, usize, String) // Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -} - -pub enum SingleStruct { - Match {name: String, loc: usize} // Post-comment -} - -pub enum GenericEnum -where I: Iterator { - // Pre Comment - Left {list: I, root: T}, // Post-comment - Right {list: I, root: T} // Post Comment -} - - -enum EmtpyWithComment { - // Some comment -} - -enum TestFormatFails { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -} - -fn nested_enum_test() { - if true { - enum TestEnum { - One(usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize,), // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA - Two // AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA - } - enum TestNestedFormatFail { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - } - } -} - - pub struct EmtpyWithComment { - // FIXME: Implement this struct -} - -// #1115 -pub enum Bencoding<'i> { - Str(&'i [u8]), - Int(i64), - List(Vec>), - /// A bencoded dict value. The first element the slice of bytes in the source that the dict is - /// composed of. The second is the dict, decoded into an ordered map. - // TODO make Dict "structlike" AKA name the two values. - Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), -} - -// #1261 -pub enum CoreResourceMsg { - SetCookieForUrl( - ServoUrl, - #[serde(deserialize_with = "::hyper_serde::deserialize", - serialize_with = "::hyper_serde::serialize")] - Cookie, - CookieSource - ), -} - -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { Foo } - -// #1046 -pub enum Entry<'a, K: 'a, V: 'a> { - Vacant( - #[ stable( feature = "rust1", since = "1.0.0" ) ] VacantEntry<'a, K, V>, - ), - Occupied( - #[ stable( feature = "rust1", since = "1.0.0" ) ] - OccupiedEntry<'a, K, V>, - ), -} - -// #2081 -pub enum ForegroundColor { - CYAN = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, -} - -// #2098 -pub enum E<'a> { - V ( < std::slice::Iter<'a, Xxxxxxxxxxxxxx> as Iterator> :: Item ) , -} - -// #1809 -enum State { - TryRecv { - pos: usize, - lap: u8, - closed_count: usize, - }, - Subscribe { pos: usize }, - IsReady { pos: usize, ready: bool }, - Unsubscribe { - pos: usize, - lap: u8, - id_woken: usize, - }, - FinalTryRecv { pos: usize, id_woken: usize }, - TimedOut, - Disconnected, -} - -// #2190 -#[derive(Debug, Fail)] -enum AnError { - #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - UnexpectedSingleToken { token: syn::Token }, -} - -// #2193 -enum WidthOf101 { - #[fail(display = ".....................................................")] Io(::std::io::Error), - #[fail(display = ".....................................................")] Ioo(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), -} - -// #2389 -pub enum QlError { - #[fail(display = "Parsing error: {}", 0)] LexError(parser::lexer::LexError), - #[fail(display = "Parsing error: {:?}", 0)] ParseError(parser::ParseError), - #[fail(display = "Validation error: {:?}", 0)] ValidationError(Vec), - #[fail(display = "Execution error: {}", 0)] ExecutionError(String), - // (from, to) - #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), - // (kind, input, expected) - #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), -} diff --git a/rustfmt-core/tests/source/expr-block.rs b/rustfmt-core/tests/source/expr-block.rs deleted file mode 100644 index a2e7ac8fc44..00000000000 --- a/rustfmt-core/tests/source/expr-block.rs +++ /dev/null @@ -1,286 +0,0 @@ -// rustfmt-indent_style: Block -// Test expressions with block formatting. - -fn arrays() { - [ ]; - let empty = []; - - let foo = [a_long_name, a_very_lng_name, a_long_name]; - - let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name]; - - vec![a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name]; - - [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name] -} - -fn arrays() { - let x = [0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; - - let a =WeightedChoice::new(&mut [Weighted { - weight: x, - item: 0, - }, - Weighted { - weight: 1, - item: 1, - }, - Weighted { - weight: x, - item: 2, - }, - Weighted { - weight: 1, - item: 3, - }]); - - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; - - [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] -} - -fn function_calls() { - let items = itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite(context, - Shape { - width: remaining_width, - ..nested_shape - }) - }, - span.lo(), - span.hi()); - - itemize_list(context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite(context, - Shape { - width: remaining_width, - ..nested_shape - }) - }, - span.lo(), - span.hi()) -} - -fn macros() { - baz!(do_not, add, trailing, commas, inside, of, function, like, macros, even, if_they, are, long); - - baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); - - let _ = match option { - None => baz!(function, like, macro_as, expression, which, is, loooooooooooooooong), - Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), - }; -} - -fn issue_1450() { - if selfstate - .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( - STATE_PARKED, - STATE_UNPARKED, - Release, - Relaxed, - Release, - Relaxed, - ) - .is_ok() { - return; - } -} - -fn foo() { - if real_total <= limit && !pre_line_comments && - !items.into_iter().any(|item| item.as_ref().is_multiline()) { - DefinitiveListTactic::Horizontal - } -} - -fn combine_block() { - foo( - Bar { - x: value, - y: value2, - }, - ); - - foo((Bar { - x: value, - y: value2, - },)); - - foo((1, 2, 3, Bar { - x: value, - y: value2, - })); - - foo((1, 2, 3, |x| { - let y = x + 1; - let z = y + 1; - z - })); - - let opt = Some( - Struct( - long_argument_one, - long_argument_two, - long_argggggggg, - ), - ); - - do_thing( - |param| { - action(); - foo(param) - }, - ); - - do_thing( - x, - |param| { - action(); - foo(param) - }, - ); - - do_thing( - x, - ( - 1, - 2, - 3, - |param| { - action(); - foo(param) - }, - ), - ); - - Ok( - some_function( - lllllllllong_argument_one, - lllllllllong_argument_two, - lllllllllllllllllllllllllllllong_argument_three, - ), - ); - - foo( - thing, - bar( - param2, - pparam1param1param1param1param1param1param1param1param1param1aram1, - param3, - ), - ); - - foo.map_or( - || { - Ok( - SomeStruct { - f1: 0, - f2: 0, - f3: 0, - }, - ) - }, - ); - - match opt { - Some(x) => somefunc(anotherfunc( - long_argument_one, - long_argument_two, - long_argument_three, - )), - Some(x) => |x| { - let y = x + 1; - let z = y + 1; - z - }, - Some(x) => (1, 2, |x| { - let y = x + 1; - let z = y + 1; - z - }), - Some(x) => SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }, - None => Ok(SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }), - }; - - match x { - y => func( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - ), - _ => func( - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzz, - ), - } -} - -fn issue_1862() { - foo( - /* bar = */ None , - something_something, - /* baz = */ None , - /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ None , - /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , - ) -} - -fn issue_1878() { - let channel: &str = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; -} diff --git a/rustfmt-core/tests/source/expr.rs b/rustfmt-core/tests/source/expr.rs deleted file mode 100644 index f87c950735f..00000000000 --- a/rustfmt-core/tests/source/expr.rs +++ /dev/null @@ -1,372 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// Test expressions - -fn foo() -> bool { - let boxed: Box = box 5; - let referenced = &5 ; - - let very_long_variable_name = ( a + first + simple + test ); - let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - - let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); - - let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - - function_call(x, *very_long_pointer, y)) - + 1000 ; - -some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 - - 50000 * sqrt(-1), - trivial_value); - (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; - - { for _ in 0..10 {} } - - {{{{}}}} - - if 1 + 2 > 0 { let result = 5; result } else { 4}; - - if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { - // Nothing - } - - if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} - - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 - + 2 + 3 { - } - - if let (some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} - - if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 - + 2 + 3 { - } - - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = item.node - { - // nothing - } - - let test = if true { 5 } else { 3 }; - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - // Check subformatting - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } -} - -fn bar() { - let range = ( 111111111 + 333333333333333333 + 1111 + 400000000000000000) .. (2222 + 2333333333333333); - - let another_range = 5..some_func( a , b /* comment */); - - for _ in 1 ..{ call_forever(); } - - syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 }); - - let third = ..10; - let infi_range = .. ; - let foo = 1..; - let bar = 5 ; - let nonsense = (10 .. 0)..(0..10); - - loop{if true {break}} - - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - a); -} - -fn baz() { - unsafe /* {}{}{}{{{{}} */ { - let foo = 1u32; - } - - unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} - - unsafe // So this is a very long comment. - // Multi-line, too. - // Will it still format correctly? - { - } - - unsafe { - // Regular unsafe block - } - - unsafe { - foo() - } - - unsafe { - foo(); - } - - // #2289 - let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; - let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; - let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; - let identifier_3 = unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; -} - -// Test some empty blocks. -fn qux() { - {} - // FIXME this one could be done better. - { /* a block with a comment */ } - { - - } - { - // A block with a comment. - } -} - -fn issue227() { - { - let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - -fn issue184(source: &str) { - for c in source.chars() { - if index < 'a' { - continue; - } - } -} - -fn arrays() { - let x = [0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0, - 7, - 8, - 9, - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 0]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; - - let a =WeightedChoice::new(&mut [Weighted { - weightweight: x, - item: 0, - }, - Weighted { - weightweight: 1, - item: 1, - }, - Weighted { - weightweight: x, - item: 2, - }, - Weighted { - weightweight: 1, - item: 3, - }]); - - let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; - - [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] -} - -fn returns() { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && return; - - return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -} - -fn addrof() { - & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); - & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); -} - -fn casts() { - fn unpack(packed: u32) -> [u16; 2] { - [ - (packed >> 16) as u16, - (packed >> 0) as u16, - ] - } - - let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx - as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; -} - -fn indices() { - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; - let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; - let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; - let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; -} - -fn repeats() { - let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc; x + y + z ]; - let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz ]; -} - -fn blocks() { - if 1 + 1 == 2 { - println!("yay arithmetix!"); - }; -} - -fn issue767() { - if false { - if false { - } else { - // A let binding here seems necessary to trigger it. - let _ = (); - } - } else if let false = false { - } -} - -fn ranges() { - let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ..= bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let z = ..= x ; - - // #1766 - let x = [0. ..10.0]; - let x = [0. ..=10.0]; - - a ..= b - - // the expr below won't compile because inclusive ranges need a defined end - // let a = 0 ..= ; -} - -fn if_else() { - let exact = diff / - (if size == 0 { - 1 -} else { - size -}); - - let cx = tp1.x + - any * radius * - if anticlockwise { - 1.0 - } else { - -1.0 - }; -} - -fn complex_if_else() { - if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { - yo(); - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { - yo(); - } -} - -fn issue1106() { - { - if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map.expect_item(enum_node_id).node { - } - } - - for entry in - WalkDir::new(path) - .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) { - } -} - -fn issue1570() { - a_very_long_function_name({some_func(1, {1})}) -} - -fn issue1714() { - v = &mut {v}[mid..]; - let (left, right) = {v}.split_at_mut(mid); -} - -// Multi-lined index should be put on the next line if it fits in one line. -fn issue1749() { - { - { - { - if self.shape[(r as f32 + self.x_offset) as usize][(c as f32 + self.y_offset) as usize] != 0 { - // hello - } - } - } - } -} - -// #1172 -fn newlines_between_list_like_expr() { - foo( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ); - - vec![ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ]; - - match x { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | - - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy | - - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), - _ => bar(), - }; -} - -fn issue2178() { - Ok(result.iter().map(|item| ls_util::rls_to_location(item)).collect()) -} diff --git a/rustfmt-core/tests/source/extern.rs b/rustfmt-core/tests/source/extern.rs deleted file mode 100644 index 187e698607a..00000000000 --- a/rustfmt-core/tests/source/extern.rs +++ /dev/null @@ -1,60 +0,0 @@ -// rustfmt-normalize_comments: true - - extern crate foo ; - extern crate foo as bar ; - -extern crate futures; -extern crate dotenv; -extern crate chrono; - -extern crate foo; -extern crate bar; - -// #2315 -extern crate proc_macro2; -extern crate proc_macro; - - extern "C" { - fn c_func(x: *mut *mut libc::c_void); - - fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); - - #[test123] - fn foo() -> uint64_t; - -pub fn bar() ; - } - -extern { - fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, devNr: c_uint, wildcard: c_char) -> TDMR_ERROR; - - fn quux() -> (); // Post comment - - pub type - Foo; - - type Bar; -} - -extern "Rust" { static ext: u32; - // Some comment. - pub static mut var : SomeType ; } - -extern "C" { - fn syscall(number: libc::c_long /* comment 1 */, /* comm 2 */ ... /* sup? */) -> libc::c_long; - - fn foo (x: *const c_char , ... ) -> -libc::c_long; - } - - extern { - pub fn freopen(filename: *const c_char, mode: *const c_char - , mode2: *const c_char - , mode3: *const c_char, - file: *mut FILE) - -> *mut FILE; - } - -extern { - -} diff --git a/rustfmt-core/tests/source/extern_not_explicit.rs b/rustfmt-core/tests/source/extern_not_explicit.rs deleted file mode 100644 index 9d6c4c2a1cd..00000000000 --- a/rustfmt-core/tests/source/extern_not_explicit.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-force_explicit_abi: false - - extern "C" { - fn some_fn() -> (); - } - - extern "C" fn sup() { - - } - -type funky_func = extern "C" fn (unsafe extern "rust-call" fn(*const JSJitInfo, *mut JSContext, - HandleObject, *mut libc::c_void, u32, - *mut JSVal) - -> u8); diff --git a/rustfmt-core/tests/source/file-lines-1.rs b/rustfmt-core/tests/source/file-lines-1.rs deleted file mode 100644 index 0164e30a854..00000000000 --- a/rustfmt-core/tests/source/file-lines-1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/source/file-lines-2.rs b/rustfmt-core/tests/source/file-lines-2.rs deleted file mode 100644 index 6f44ec6e69d..00000000000 --- a/rustfmt-core/tests/source/file-lines-2.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/source/file-lines-3.rs b/rustfmt-core/tests/source/file-lines-3.rs deleted file mode 100644 index c4f3e21b1ae..00000000000 --- a/rustfmt-core/tests/source/file-lines-3.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] -// rustfmt-error_on_line_overflow: false - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/source/file-lines-4.rs b/rustfmt-core/tests/source/file-lines-4.rs deleted file mode 100644 index 83928bf6fec..00000000000 --- a/rustfmt-core/tests/source/file-lines-4.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-file_lines: [] -// (Test that nothing is formatted if an empty array is specified.) - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - // aaaaaaaaaaaaa - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/source/file-lines-5.rs b/rustfmt-core/tests/source/file-lines-5.rs deleted file mode 100644 index 8ec2c67bc44..00000000000 --- a/rustfmt-core/tests/source/file-lines-5.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] - -struct A { -t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - fn baz() { - let j = 15; - } -} diff --git a/rustfmt-core/tests/source/file-lines-6.rs b/rustfmt-core/tests/source/file-lines-6.rs deleted file mode 100644 index 2eacc8a0e75..00000000000 --- a/rustfmt-core/tests/source/file-lines-6.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] - -struct A { - t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - - fn baz() { -/// - let j = 15; - } -} diff --git a/rustfmt-core/tests/source/file-lines-item.rs b/rustfmt-core/tests/source/file-lines-item.rs deleted file mode 100644 index 0ed4b93df5f..00000000000 --- a/rustfmt-core/tests/source/file-lines-item.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] -// rustfmt-reorder_imports: true - -use foo::{c, b, a}; -use bar; - -fn foo() { - bar ( ) ; -} - -impl Drop for Context { - fn drop(&mut self) { - } -} - -impl Bar for Baz { - fn foo() { - bar( - baz, // Who knows? - ) - } -} diff --git a/rustfmt-core/tests/source/fn-custom-2.rs b/rustfmt-core/tests/source/fn-custom-2.rs deleted file mode 100644 index 72d841544a8..00000000000 --- a/rustfmt-core/tests/source/fn-custom-2.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); -} - -fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); -} - -fn baz() where X: TTTTTTTT { - baz(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); - } - - fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); - } - - fn baz() where X: TTTTTTTT { - baz(); - } -} - -struct Foo { - foo: Foo, -} diff --git a/rustfmt-core/tests/source/fn-custom-3.rs b/rustfmt-core/tests/source/fn-custom-3.rs deleted file mode 100644 index 9934fb61efd..00000000000 --- a/rustfmt-core/tests/source/fn-custom-3.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); -} - -fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); - } - - fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { - bar(); - } -} - -struct Foo { - foo: Foo, -} diff --git a/rustfmt-core/tests/source/fn-custom-4.rs b/rustfmt-core/tests/source/fn-custom-4.rs deleted file mode 100644 index 01c00aecb86..00000000000 --- a/rustfmt-core/tests/source/fn-custom-4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} - -fn qux(a: Aaaaaaaaaaaaaaaaa) where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { - baz(); -} diff --git a/rustfmt-core/tests/source/fn-custom-6.rs b/rustfmt-core/tests/source/fn-custom-6.rs deleted file mode 100644 index 8e8bb6c274e..00000000000 --- a/rustfmt-core/tests/source/fn-custom-6.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/rustfmt-core/tests/source/fn-custom-7.rs b/rustfmt-core/tests/source/fn-custom-7.rs deleted file mode 100644 index f7670e07fc8..00000000000 --- a/rustfmt-core/tests/source/fn-custom-7.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block -// rustfmt-fn_args_density: Vertical -// rustfmt-brace_style: AlwaysNextLine - -// Case with only one variable. -fn foo(a: u8) -> u8 { - bar() -} - -// Case with 2 variables and some pre-comments. -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -// Case with 2 variables and some post-comments. -fn foo(/* Comment 1 */ a: u8, /* Comment 2 */ b: u8) -> u8 { - bar() -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/rustfmt-core/tests/source/fn-custom-8.rs b/rustfmt-core/tests/source/fn-custom-8.rs deleted file mode 100644 index d3deb20a51c..00000000000 --- a/rustfmt-core/tests/source/fn-custom-8.rs +++ /dev/null @@ -1,49 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { - bar(); -} - -trait Test { - fn foo( - a: u8) { - - } - - fn bar(a: u8) - -> String { - - } - - fn bar(a: u8) -> String where Foo: foooo, Bar: barrr {} -} diff --git a/rustfmt-core/tests/source/fn-custom.rs b/rustfmt-core/tests/source/fn-custom.rs deleted file mode 100644 index b8d734bfbaf..00000000000 --- a/rustfmt-core/tests/source/fn-custom.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Test some of the ways function signatures can be customised. - -// Test compressed layout of args. -fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); -} - -impl Foo { - fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { - foo(); - } -} diff --git a/rustfmt-core/tests/source/fn-simple.rs b/rustfmt-core/tests/source/fn-simple.rs deleted file mode 100644 index f1ce503ab0a..00000000000 --- a/rustfmt-core/tests/source/fn-simple.rs +++ /dev/null @@ -1,66 +0,0 @@ -// rustfmt-normalize_comments: true - -fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ - ,response: NoWay /* hose */) { -fn op(x: Typ, key : &[u8], upd : Box) -> (memcache::Status, Result>)>) -> MapResult {} - - "cool"} - - -fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* triple, even */*/*/, -// Does this work? -y: World -) { - simple(/* does this preserve comments now? */ 42, NoWay) -} - -fn generic(arg: T) -> &SomeType - where T: Fn(// First arg - A, - // Second argument - B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { - arg(a, b, c, d, e) -} - -fn foo() -> ! {} - -pub fn http_fetch_async(listener:Box< AsyncCORSResponseListener+Send >, script_chan: Box) { -} - -fn some_func>(val:T){} - -fn zzzzzzzzzzzzzzzzzzzz - (selff: Type, mut handle: node::Handle>, Type, NodeType>) - -> SearchStack<'a, K, V, Type, NodeType>{ -} - -unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, - is_lenient: bool, - call: unsafe extern fn(*const JSJitInfo, *mut JSContext, - HandleObject, *mut libc::c_void, u32, - *mut JSVal) - -> u8) { - let f: fn ( _ , _ ) -> _ = panic!() ; -} - -pub fn start_export_thread(database: &Database, crypto_scheme: &C, block_size: usize, source_path: &Path) -> BonzoResult> {} - -pub fn waltz(cwd: &Path) -> CliAssert { - { - { - formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig); - } - } -} - -// #2003 -mod foo { - fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() { - foo(); - } -} - -// #2082 -pub(crate) fn init() {} - -crate fn init() {} diff --git a/rustfmt-core/tests/source/fn-single-line.rs b/rustfmt-core/tests/source/fn-single-line.rs deleted file mode 100644 index 6d7f764d280..00000000000 --- a/rustfmt-core/tests/source/fn-single-line.rs +++ /dev/null @@ -1,79 +0,0 @@ -// rustfmt-fn_single_line: true -// Test single-line functions. - -fn foo_expr() { - 1 -} - -fn foo_stmt() { - foo(); -} - -fn foo_decl_local() { - let z = 5; - } - -fn foo_decl_item(x: &mut i32) { - x = 3; -} - - fn empty() { - -} - -fn foo_return() -> String { - "yay" -} - -fn foo_where() -> T where T: Sync { - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space () { - 1 -} - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) { - } -} - -trait CoolerTypes { fn dummy(&self) { -} -} - -fn Foo() where T: Bar { -} diff --git a/rustfmt-core/tests/source/fn_args_density-vertical.rs b/rustfmt-core/tests/source/fn_args_density-vertical.rs deleted file mode 100644 index b61c337dfb9..00000000000 --- a/rustfmt-core/tests/source/fn_args_density-vertical.rs +++ /dev/null @@ -1,33 +0,0 @@ -// rustfmt-fn_args_density: Vertical - -// Empty list should stay on one line. -fn do_bar( - -) -> u8 { - bar() -} - -// A single argument should stay on the same line. -fn do_bar( - a: u8) -> u8 { - bar() -} - -// Multiple arguments should each get their own line. -fn do_bar(a: u8, mut b: u8, c: &u8, d: &mut u8, closure: &Fn(i32) -> i32) -> i32 { - // This feature should not affect closures. - let bar = |x: i32, y: i32| -> i32 { x + y }; - bar(a, b) -} - -// If the first argument doesn't fit on the same line with the function name, -// the whole list should probably be pushed to the next line with hanging -// indent. That's not what happens though, so check current behaviour instead. -// In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, c: u8, d: u8) { - this(); - that(); - the_other_thing(); -} diff --git a/rustfmt-core/tests/source/fn_args_indent-block.rs b/rustfmt-core/tests/source/fn_args_indent-block.rs deleted file mode 100644 index b056fcb56fe..00000000000 --- a/rustfmt-core/tests/source/fn_args_indent-block.rs +++ /dev/null @@ -1,78 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { - bar(); -} - -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { - bar() -} - -fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { - bar(); -} - -fn foo() -> T { - foo(); -} - -fn foo() -> T where X: Foooo, Y: Baaar { - foo(); -} - -fn foo() where X: Foooo { -} - -fn foo() where X: Foooo, Y: Baaar { -} - -fn foo() -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) { - foo(); -} - -fn foo() { - foo(); -} - -fn foo() { - foo(); -} - -fn foo() { - foo(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} -} - -fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { - foo(); -} - -fn foo() -> (Looooooooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiiiiiiis, Loooooooooooooooooooooong) { - foo(); -} diff --git a/rustfmt-core/tests/source/hard-tabs.rs b/rustfmt-core/tests/source/hard-tabs.rs deleted file mode 100644 index b8fd09f8792..00000000000 --- a/rustfmt-core/tests/source/hard-tabs.rs +++ /dev/null @@ -1,85 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-hard_tabs: true -// rustfmt-error_on_line_overflow: false - -fn main() { -let x = Bar; - -let y = Foo {a: x }; - -Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - -fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) {} - -let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - -if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 -+ 2 + 3 { -} - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } - -unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} - -unsafe // So this is a very long comment. - // Multi-line, too. - // Will it still format correctly? -{ -} - -let chain = funktion_kall().go_to_next_line_with_tab().go_to_next_line_with_tab().go_to_next_line_with_tab(); - -let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; - -fn generic(arg: T) -> &SomeType - where T: Fn(// First arg - A, - // Second argument - B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { - arg(a, b, c, d, e) -} - - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } - }); - - fffffffffffffffffffffffffffffffffff(a, - { - SCRIPT_TASK_ROOT - .with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - a.b - .c - .d(); - - x().y(|| { - match cond() { - true => (), - false => (), - } - }); -} - -// #2296 -impl Foo { - // a comment - // on multiple lines - fn foo() { - // another comment - // on multiple lines - let x = true; - } -} diff --git a/rustfmt-core/tests/source/hello.rs b/rustfmt-core/tests/source/hello.rs deleted file mode 100644 index f892e6debb1..00000000000 --- a/rustfmt-core/tests/source/hello.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-config: small_tabs.toml -// rustfmt-target: hello.rs - -// Smoke test - hello world. - -fn main() { println!("Hello world!"); } diff --git a/rustfmt-core/tests/source/hello2.rs b/rustfmt-core/tests/source/hello2.rs deleted file mode 100644 index 48af7de3887..00000000000 --- a/rustfmt-core/tests/source/hello2.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-config: small_tabs.toml -// rustfmt-target: hello.rs - -// Smoke test - hello world. - -fn main( ) { -println!("Hello world!"); -} diff --git a/rustfmt-core/tests/source/immovable_generators.rs b/rustfmt-core/tests/source/immovable_generators.rs deleted file mode 100644 index c57a1e14483..00000000000 --- a/rustfmt-core/tests/source/immovable_generators.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(generators)] - -unsafe fn foo() { - let mut ga = static || { - yield 1; - }; -} diff --git a/rustfmt-core/tests/source/impls.rs b/rustfmt-core/tests/source/impls.rs deleted file mode 100644 index ca8e486646a..00000000000 --- a/rustfmt-core/tests/source/impls.rs +++ /dev/null @@ -1,154 +0,0 @@ -// rustfmt-normalize_comments: true -impl Foo for Bar { fn foo() { "hi" } } - -pub impl Foo for Bar { - // Associated Constants - const Baz: i32 = 16; - // Associated Types - type FooBar = usize; - // Comment 1 - fn foo() { "hi" } - // Comment 2 - fn foo() { "hi" } - // Comment 3 -} - -pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { - fn foo() { "hi" } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> -{ - fn foo() { "hi" } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> -{ - fn foo() { "hi" } -} - -impl Foo for Bar where T: Baz -{ -} - -impl Foo for Bar where T: Baz { /* Comment */ } - -impl Foo { - fn foo() {} -} - -impl Boo { - - // BOO - fn boo() {} - // FOO - - - -} - -mod a { - impl Foo { - // Hello! - fn foo() {} - } -} - - -mod b { - mod a { - impl Foo { - fn foo() {} - } - } -} - -impl Foo { add_fun!(); } - -impl Blah { - fn boop() {} - add_fun!(); -} - -impl X { fn do_parse( mut self : X ) {} } - -impl Y5000 { - fn bar(self: X< 'a , 'b >, y: Y) {} - - fn bad(&self, ( x, y): CoorT) {} - - fn turbo_bad(self: X< 'a , 'b > , ( x, y): CoorT) { - - } -} - -pub impl Foo for Bar where T: Foo -{ - fn foo() { "hi" } -} - -pub impl Foo for Bar where T: Foo, Z: Baz {} - -mod m { - impl PartialEq for S where T: PartialEq { - fn eq(&self, other: &Self) { - true - } - } - - impl PartialEq for S where T: PartialEq { } - } - -impl Handle, HandleType> { -} - -impl PartialEq for Handle, HandleType> { -} - -mod x { - impl Foo - where A: 'static, - B: 'static, - C: 'static, - D: 'static { } -} - -impl Issue1249 { - // Creates a new flow constructor. - fn foo() {} -} - -// #1600 -impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { - fn drop() {} -} - -// #1168 -pub trait Number: Copy + Eq + Not + Shl + - Shr + - BitAnd + BitOr + BitAndAssign + BitOrAssign - - - -{ - // test - fn zero() -> Self; -} - -// #1642 -pub trait SomeTrait : Clone + Eq + PartialEq + Ord + PartialOrd + Default + Hash + Debug + Display + Write + Read + FromStr { - // comment -} - -// #1995 -impl Foo { - fn f( - S { - aaaaaaaaaa: aaaaaaaaaa, - bbbbbbbbbb: bbbbbbbbbb, - cccccccccc: cccccccccc, - }: S - ) -> u32{ - 1 - } -} diff --git a/rustfmt-core/tests/source/imports-reorder-lines-and-items.rs b/rustfmt-core/tests/source/imports-reorder-lines-and-items.rs deleted file mode 100644 index 3c71f9984fe..00000000000 --- a/rustfmt-core/tests/source/imports-reorder-lines-and-items.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imported_names: true - -/// This comment should stay with `use std::str;` -use std::str; -use std::cmp::{d, c, b, a}; -use std::ddd::aaa; -use std::ddd::{d as p, c as g, b, a}; -// This comment should stay with `use std::ddd:bbb;` -use std::ddd::bbb; diff --git a/rustfmt-core/tests/source/imports-reorder-lines.rs b/rustfmt-core/tests/source/imports-reorder-lines.rs deleted file mode 100644 index a855a964235..00000000000 --- a/rustfmt-core/tests/source/imports-reorder-lines.rs +++ /dev/null @@ -1,34 +0,0 @@ -// rustfmt-reorder_imports: true - -use std::str; -use std::cmp::{d, c, b, a}; -use std::cmp::{b, e, g, f}; -use std::ddd::aaa; -// This comment should stay with `use std::ddd;` -use std::ddd; -use std::ddd::bbb; - -mod test { -} - -use aaa::bbb; -use aaa; -use aaa::*; - -mod test {} -// If item names are equal, order by rename - -use test::{a as bb, b}; -use test::{a as aa, c}; - -mod test {} -// If item names are equal, order by rename - no rename comes before a rename - -use test::{a as bb, b}; -use test::{a, c}; - -mod test {} -// `self` always comes first - -use test::{a as aa, c}; -use test::{self as bb, b}; diff --git a/rustfmt-core/tests/source/imports-reorder.rs b/rustfmt-core/tests/source/imports-reorder.rs deleted file mode 100644 index 200cad2d13c..00000000000 --- a/rustfmt-core/tests/source/imports-reorder.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-reorder_imported_names: true - -use path::{C,/*A*/ A, B /* B */, self /* self */}; - -use {ab, ac, aa, Z, b}; diff --git a/rustfmt-core/tests/source/imports.rs b/rustfmt-core/tests/source/imports.rs deleted file mode 100644 index 73d1419f47d..00000000000 --- a/rustfmt-core/tests/source/imports.rs +++ /dev/null @@ -1,89 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-error_on_line_overflow: false - -// Imports. - -// Long import. -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; -use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; - -use list::{ - // Some item - SomeItem /* Comment */, /* Another item */ AnotherItem /* Another Comment */, // Last Item - LastItem -}; - -use test::{ Other /* C */ , /* A */ self /* B */ }; - -use syntax::{self}; -use {/* Pre-comment! */ - Foo, Bar /* comment */}; -use Foo::{Bar, Baz}; -pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; -use syntax::some::{}; - -use self; -use std::io::{self}; -use std::io::self; - -mod Foo { - pub use syntax::ast::{ - ItemForeignMod, - ItemImpl, - ItemMac, - ItemMod, - ItemStatic, - ItemDefaultImpl - }; - - mod Foo2 { - pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; - } -} - -fn test() { -use Baz::*; - use Qux; -} - -// Simple imports -use foo::bar::baz as baz ; -use bar::quux as kaas; -use foo; - -// With aliases. -use foo::{self as bar, baz}; -use foo::{self as bar}; -use foo::{qux as bar}; -use foo::{baz, qux as bar}; - -// With absolute paths -use ::foo; -use ::foo::{Bar}; -use ::foo::{Bar, Baz}; -use ::{Foo}; -use ::{Bar, Baz}; - -// Root globs -use *; -use ::*; - -// spaces used to cause glob imports to disappear (#1356) -use super:: * ; -use foo::issue_1356:: * ; - -// We shouldn't remove imports which have attributes attached (#1858) -#[cfg(unix)] -use self::unix::{}; - -// nested imports -use foo::{a, bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}, b, boo, c,}; - -use fooo::{baar::{foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}}, z, bar, bar::*, x, y}; - -// nested imports with a single sub-tree. -use a::{b::{c::*}}; -use a::{b::{c::{}}}; -use a::{b::{c::d}}; -use a::{b::{c::{xxx, yyy, zzz}}}; diff --git a/rustfmt-core/tests/source/issue-1021.rs b/rustfmt-core/tests/source/issue-1021.rs deleted file mode 100644 index 380e24cc0b0..00000000000 --- a/rustfmt-core/tests/source/issue-1021.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - match x { - S(true , .., true ) => (), - S(true , .. ) => (), - S(.., true ) => (), - S( .. ) => (), - S(_) => (), - S(/* .. */ .. ) => (), - S(/* .. */ .., true ) => (), - } - - match y { - (true , .., true ) => (), - (true , .. ) => (), - (.., true ) => (), - ( .. ) => (), - (_,) => (), - (/* .. */ .. ) => (), - (/* .. */ .., true ) => (), - } -} diff --git a/rustfmt-core/tests/source/issue-1049.rs b/rustfmt-core/tests/source/issue-1049.rs deleted file mode 100644 index bcfba41e768..00000000000 --- a/rustfmt-core/tests/source/issue-1049.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Test overlong function signature -pub unsafe fn reborrow_mut(&mut X: Abcde) -> Handle, HandleType> { -} - -pub fn merge(mut X: Abcdef) -> Handle, K, V, marker::Internal>, marker::Edge> { -} - -impl Handle { - pub fn merge(a: Abcd) -> Handle, K, V, marker::Internal>, marker::Edge> { - } -} - -// Long function without return type that should not be reformatted. -fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} - -fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} - -fn veeeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} diff --git a/rustfmt-core/tests/source/issue-1111.rs b/rustfmt-core/tests/source/issue-1111.rs deleted file mode 100644 index 2e1a89ad78e..00000000000 --- a/rustfmt-core/tests/source/issue-1111.rs +++ /dev/null @@ -1 +0,0 @@ -use bar; diff --git a/rustfmt-core/tests/source/issue-1120.rs b/rustfmt-core/tests/source/issue-1120.rs deleted file mode 100644 index e85c9af99d4..00000000000 --- a/rustfmt-core/tests/source/issue-1120.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-reorder_imports: true - -// Ensure that a use at the start of an inline module is correctly formatted. -mod foo {use bar;} - -// Ensure that an indented `use` gets the correct indentation. -mod foo { - use bar; -} diff --git a/rustfmt-core/tests/source/issue-1124.rs b/rustfmt-core/tests/source/issue-1124.rs deleted file mode 100644 index 69aa1bb1c59..00000000000 --- a/rustfmt-core/tests/source/issue-1124.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-normalize_comments: true - -use d; use c; use b; use a; -// The previous line has a space after the `use a;` - -mod a { use d; use c; use b; use a; } - -use z; - -use y; - - - -use x; -use a; \ No newline at end of file diff --git a/rustfmt-core/tests/source/issue-1127.rs b/rustfmt-core/tests/source/issue-1127.rs deleted file mode 100644 index 9996c194818..00000000000 --- a/rustfmt-core/tests/source/issue-1127.rs +++ /dev/null @@ -1,23 +0,0 @@ -// rustfmt-max_width:120 -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true - -fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { - 42 -} - -enum TestEnum { - AVeryVeryLongEnumName, - AnotherVeryLongEnumName, - TheLastVeryLongEnumName, -} - -fn main() { - let var = TestEnum::AVeryVeryLongEnumName; - let num = match var { - TestEnum::AVeryVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::AnotherVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::TheLastVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - }; -} - diff --git a/rustfmt-core/tests/source/issue-1158.rs b/rustfmt-core/tests/source/issue-1158.rs deleted file mode 100644 index 6742e17459e..00000000000 --- a/rustfmt-core/tests/source/issue-1158.rs +++ /dev/null @@ -1,3 +0,0 @@ -trait T { - itemmacro!(this, is.now() .formatted(yay)); -} diff --git a/rustfmt-core/tests/source/issue-1177.rs b/rustfmt-core/tests/source/issue-1177.rs deleted file mode 100644 index 3ac423c5aef..00000000000 --- a/rustfmt-core/tests/source/issue-1177.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - // Line Comment - /* Block Comment */ - - let d = 5; -} diff --git a/rustfmt-core/tests/source/issue-1192.rs b/rustfmt-core/tests/source/issue-1192.rs deleted file mode 100644 index 4e39fbf9a36..00000000000 --- a/rustfmt-core/tests/source/issue-1192.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - assert!(true) ; -} diff --git a/rustfmt-core/tests/source/issue-1211.rs b/rustfmt-core/tests/source/issue-1211.rs deleted file mode 100644 index 5818736bf6b..00000000000 --- a/rustfmt-core/tests/source/issue-1211.rs +++ /dev/null @@ -1,15 +0,0 @@ -fn main() { - for iface in &ifaces { - match iface.addr { - get_if_addrs::IfAddr::V4(ref addr) => { - match addr.broadcast { - Some(ip) => { - sock.send_to(&buf, (ip, 8765)).expect("foobar"); - } - _ => () - } - } - _ => () - }; - } -} diff --git a/rustfmt-core/tests/source/issue-1216.rs b/rustfmt-core/tests/source/issue-1216.rs deleted file mode 100644 index d727c158ab8..00000000000 --- a/rustfmt-core/tests/source/issue-1216.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-normalize_comments: true -enum E { - A, //* I am not a block comment (caused panic) - B, -} diff --git a/rustfmt-core/tests/source/issue-1239.rs b/rustfmt-core/tests/source/issue-1239.rs deleted file mode 100644 index 913058257ed..00000000000 --- a/rustfmt-core/tests/source/issue-1239.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn foo() { - let with_alignment = if condition__uses_alignment_for_first_if__0 || - condition__uses_alignment_for_first_if__1 || - condition__uses_alignment_for_first_if__2 { - } else if condition__no_alignment_for_later_else__0 || - condition__no_alignment_for_later_else__1 || - condition__no_alignment_for_later_else__2 { - }; -} diff --git a/rustfmt-core/tests/source/issue-1278.rs b/rustfmt-core/tests/source/issue-1278.rs deleted file mode 100644 index e25376561a9..00000000000 --- a/rustfmt-core/tests/source/issue-1278.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style = "block" - -#![feature(pub_restricted)] - -mod inner_mode { - pub(super) fn func_name(abc: i32) -> i32 { - abc - } -} diff --git a/rustfmt-core/tests/source/issue-1350.rs b/rustfmt-core/tests/source/issue-1350.rs deleted file mode 100644 index 1baa1985a7e..00000000000 --- a/rustfmt-core/tests/source/issue-1350.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-max_width: 120 -// rustfmt-comment_width: 110 - -impl Struct { - fn fun() { - let result = match ::deserialize(&json) { - Ok(v) => v, - Err(e) => { - match ::deserialize(&json) { - Ok(v) => return Err(Error::with_json(v)), - Err(e2) => return Err(Error::with_json(e)), - } - } - }; - } -} diff --git a/rustfmt-core/tests/source/issue-1366.rs b/rustfmt-core/tests/source/issue-1366.rs deleted file mode 100644 index 9d2964fc77c..00000000000 --- a/rustfmt-core/tests/source/issue-1366.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - fn f() -> Option { - Some("fffffffsssssssssddddssssfffffddddff").map(|s| s).map(|s| s.to_string()).map(|res| { - match Some(res) { - Some(ref s) if s == "" => 41, - Some(_) => 42, - _ => 43, - } - }) - } - println!("{:?}", f()) -} diff --git a/rustfmt-core/tests/source/issue-1468.rs b/rustfmt-core/tests/source/issue-1468.rs deleted file mode 100644 index 4d0d4f0eb98..00000000000 --- a/rustfmt-core/tests/source/issue-1468.rs +++ /dev/null @@ -1,27 +0,0 @@ -fn issue1468() { -euc_jp_decoder_functions!({ -let trail_minus_offset = byte.wrapping_sub(0xA1); -// Fast-track Hiragana (60% according to Lunde) -// and Katakana (10% according to Lunde). -if jis0208_lead_minus_offset == 0x03 && -trail_minus_offset < 0x53 { -// Hiragana -handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) -} else if jis0208_lead_minus_offset == 0x04 && -trail_minus_offset < 0x56 { -// Katakana -handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) -} else if trail_minus_offset > (0xFE - 0xA1) { -if byte < 0x80 { -return (DecoderResult::Malformed(1, 0), -unread_handle_trail.unread(), -handle.written()); -} -return (DecoderResult::Malformed(2, 0), -unread_handle_trail.consumed(), -handle.written()); -} else { -unreachable!(); -} -}); -} diff --git a/rustfmt-core/tests/source/issue-1693.rs b/rustfmt-core/tests/source/issue-1693.rs deleted file mode 100644 index 0622ce50235..00000000000 --- a/rustfmt-core/tests/source/issue-1693.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn issue1693() { - let pixel_data = vec![(f16::from_f32(0.82), f16::from_f32(1.78), f16::from_f32(0.21)); 256 * 256]; -} diff --git a/rustfmt-core/tests/source/issue-1800.rs b/rustfmt-core/tests/source/issue-1800.rs deleted file mode 100644 index eae22653258..00000000000 --- a/rustfmt-core/tests/source/issue-1800.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![doc(html_root_url = "http://example.com")] -#[cfg(feature = "foo")] -fn a() {} diff --git a/rustfmt-core/tests/source/issue-1914.rs b/rustfmt-core/tests/source/issue-1914.rs deleted file mode 100644 index 447296c4b87..00000000000 --- a/rustfmt-core/tests/source/issue-1914.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-max_width: 80 - -extern "C" { -#[link_name = "_ZN7MyClass26example_check_no_collisionE"] - pub static mut MyClass_example_check_no_collision : * const :: std :: os :: raw :: c_int ; -} diff --git a/rustfmt-core/tests/source/issue-2025.rs b/rustfmt-core/tests/source/issue-2025.rs deleted file mode 100644 index c6f61b4e3e1..00000000000 --- a/rustfmt-core/tests/source/issue-2025.rs +++ /dev/null @@ -1,8 +0,0 @@ - - - - -// See if rustfmt removes empty lines on top of the file. -pub fn foo() { - println!("hello, world"); -} diff --git a/rustfmt-core/tests/source/issue-2111.rs b/rustfmt-core/tests/source/issue-2111.rs deleted file mode 100644 index d1b02053e2a..00000000000 --- a/rustfmt-core/tests/source/issue-2111.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-normalize_comments: false - -// An import with single line comments. -use super::{ - SCHEMA_VERSIONS, - LodaModel, - ModelProperties, - StringMap, - ModelSelector, - RequestDescription, - MethodDescription, - ModelBehaviour, - ModelRequestGraph, - DelayChoice, - Holding, - Destinations, - ModelEdges, - Switch, - // ModelMetaData, - // Generated, - // SecondsString, - // DateString, - // ModelConfiguration, - // ModelRequests, - // RestResponse, - // RestResponseCode, - // UniformHolding -}; diff --git a/rustfmt-core/tests/source/issue-2164.rs b/rustfmt-core/tests/source/issue-2164.rs deleted file mode 100644 index 6c288e1bd62..00000000000 --- a/rustfmt-core/tests/source/issue-2164.rs +++ /dev/null @@ -1,4 +0,0 @@ -// A stress test against code generated by bindgen. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct emacs_env_25 { pub size : isize , pub private_members : * mut emacs_env_private , pub make_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , any_reference : emacs_value ) -> emacs_value > , pub free_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , global_reference : emacs_value ) > , pub non_local_exit_check : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) -> emacs_funcall_exit > , pub non_local_exit_clear : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) > , pub non_local_exit_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol_out : * mut emacs_value , non_local_exit_data_out : * mut emacs_value ) -> emacs_funcall_exit > , pub non_local_exit_signal : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol : emacs_value , non_local_exit_data : emacs_value ) > , pub non_local_exit_throw : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , tag : emacs_value , value : emacs_value ) > , pub make_function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , min_arity : isize , max_arity : isize , function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , nargs : isize , args : * mut emacs_value , arg1 : * mut ::libc :: c_void ) -> emacs_value > , documentation : * const ::libc :: c_char , data : * mut ::libc :: c_void ) -> emacs_value > , pub funcall : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , function : emacs_value , nargs : isize , args : * mut emacs_value ) -> emacs_value > , pub intern : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , symbol_name : * const ::libc :: c_char ) -> emacs_value > , pub type_of : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> emacs_value > , pub is_not_nil : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> bool > , pub eq : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , a : emacs_value , b : emacs_value ) -> bool > , pub extract_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> intmax_t > , pub make_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : intmax_t ) -> emacs_value > , pub extract_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> f64 > , pub make_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : f64 ) -> emacs_value > , pub copy_string_contents : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value , buffer : * mut ::libc :: c_char , size_inout : * mut isize ) -> bool > , pub make_string : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , contents : * const ::libc :: c_char , length : isize ) -> emacs_value > , pub make_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > , ptr : * mut ::libc :: c_void ) -> emacs_value > , pub get_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value ) -> * mut ::libc :: c_void > , pub set_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , ptr : * mut ::libc :: c_void ) > , pub get_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) -> :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) > > , pub set_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > ) > , pub vec_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize ) -> emacs_value > , pub vec_set : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize , val : emacs_value ) > , pub vec_size : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value ) -> isize > , } diff --git a/rustfmt-core/tests/source/issue-2179.rs b/rustfmt-core/tests/source/issue-2179.rs deleted file mode 100644 index ade953971ec..00000000000 --- a/rustfmt-core/tests/source/issue-2179.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -fn issue_2179() { - let (opts, rustflags, clear_env_rust_log) = - { - // We mustn't lock configuration for the whole build process - let rls_config = rls_config.lock().unwrap(); - - let opts = CargoOptions::new(&rls_config); - trace!("Cargo compilation options:\n{:?}", opts); - let rustflags = prepare_cargo_rustflags(&rls_config); - - // Warn about invalid specified bin target or package depending on current mode - // TODO: Return client notifications along with diagnostics to inform the user - if !rls_config.workspace_mode { - let cur_pkg_targets = ws.current().unwrap().targets(); - - if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { - let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); - if let None = bins.find(|x| x.name() == build_bin) { - warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); - } - } - } else { - for package in &opts.package { - if let None = ws.members().find(|x| x.name() == package) { - warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); - } - } - } - - (opts, rustflags, rls_config.clear_env_rust_log) - }; - -} diff --git a/rustfmt-core/tests/source/issue-2256.rs b/rustfmt-core/tests/source/issue-2256.rs deleted file mode 100644 index b505b96e2b3..00000000000 --- a/rustfmt-core/tests/source/issue-2256.rs +++ /dev/null @@ -1,12 +0,0 @@ -// こんにちは -use std::{}; -use std::borrow::Cow; - -/* comment */ use std::{}; -/* comment */ use std::{}; - - - - - -/* comment */ use std::{}; diff --git a/rustfmt-core/tests/source/issue-2342.rs b/rustfmt-core/tests/source/issue-2342.rs deleted file mode 100644 index f86d24a146b..00000000000 --- a/rustfmt-core/tests/source/issue-2342.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-max_width: 80 - -struct Foo { - #[cfg(feature = "serde")] bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN -} diff --git a/rustfmt-core/tests/source/issue-2446.rs b/rustfmt-core/tests/source/issue-2446.rs deleted file mode 100644 index ad649d95c54..00000000000 --- a/rustfmt-core/tests/source/issue-2446.rs +++ /dev/null @@ -1,11 +0,0 @@ -enum Issue2446 { - V { - f: u8, // x - }, -} - -enum Issue2446TrailingCommentsOnly { - V { - f: u8, /* */ - } -} diff --git a/rustfmt-core/tests/source/issue-2479.rs b/rustfmt-core/tests/source/issue-2479.rs deleted file mode 100644 index df50236d05d..00000000000 --- a/rustfmt-core/tests/source/issue-2479.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Long attributes. -# [ derive ( Clone , Copy , Debug , PartialEq ) ] pub enum POLARITYR { # [ doc = "Task mode: No effect on pin from OUT[n] task. Event mode: no IN[n] event generated on pin activity." ] NONE , # [ doc = "Task mode: Set pin from OUT[n] task. Event mode: Generate IN[n] event when rising edge on pin." ] LOTOHI , # [ doc = "Task mode: Clear pin from OUT[n] task. Event mode: Generate IN[n] event when falling edge on pin." ] HITOLO , # [ doc = "Task mode: Toggle pin from OUT[n]. Event mode: Generate IN[n] when any change on pin." ] TOGGLE } diff --git a/rustfmt-core/tests/source/issue-447.rs b/rustfmt-core/tests/source/issue-447.rs deleted file mode 100644 index 7c542cb58c2..00000000000 --- a/rustfmt-core/tests/source/issue-447.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - if /* shouldn't be dropped - shouldn't be dropped */ - - cond /* shouldn't be dropped - shouldn't be dropped */ - - { - } /* shouldn't be dropped - shouldn't be dropped */ - - else /* shouldn't be dropped - shouldn't be dropped */ - - if /* shouldn't be dropped - shouldn't be dropped */ - - cond /* shouldn't be dropped - shouldn't be dropped */ - - { - } /* shouldn't be dropped - shouldn't be dropped */ - - else /* shouldn't be dropped - shouldn't be dropped */ - - { - } - - if /* shouldn't be dropped - shouldn't be dropped */ - let Some(x) = y/* shouldn't be dropped - shouldn't be dropped */ - { - } -} diff --git a/rustfmt-core/tests/source/issue-510.rs b/rustfmt-core/tests/source/issue-510.rs deleted file mode 100644 index 4c60859e6cf..00000000000 --- a/rustfmt-core/tests/source/issue-510.rs +++ /dev/null @@ -1,37 +0,0 @@ -impl ISizeAndMarginsComputer for AbsoluteNonReplaced { -fn solve_inline_size_constraints(&self, -block: &mut BlockFlow, -input: &ISizeConstraintInput) --> ISizeConstraintSolution { -let (inline_start,inline_size,margin_inline_start,margin_inline_end) = -match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { -(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { -let margin_start = inline_start_margin.specified_or_zero(); -let margin_end = inline_end_margin.specified_or_zero(); -// Now it is the same situation as inline-start Specified and inline-end -// and inline-size Auto. -// -// Set inline-end to zero to calculate inline-size. -let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - -(margin_start + margin_end)); -(Au(0), inline_size, margin_start, margin_end) -} -}; - - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_start, inline_end, computed_inline_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = - block.get_shrink_to_fit_inline_size(available_inline_size - - (margin_start + margin_end)); - (Au(0), inline_size, margin_start, margin_end) - } - }; -} -} diff --git a/rustfmt-core/tests/source/issue-811.rs b/rustfmt-core/tests/source/issue-811.rs deleted file mode 100644 index b7a89b5d0f9..00000000000 --- a/rustfmt-core/tests/source/issue-811.rs +++ /dev/null @@ -1,19 +0,0 @@ -trait FooTrait: Sized { - type Bar: BarTrait; -} - -trait BarTrait: Sized { - type Baz; - fn foo(); -} - -type Foo = <>::Bar as BarTrait>::Baz; -type Bar = >::Baz; - -fn some_func, U>() { - <>::Bar as BarTrait>::foo(); -} - -fn some_func>() { - >::foo(); -} diff --git a/rustfmt-core/tests/source/issue-850.rs b/rustfmt-core/tests/source/issue-850.rs deleted file mode 100644 index c939716a6a8..00000000000 --- a/rustfmt-core/tests/source/issue-850.rs +++ /dev/null @@ -1 +0,0 @@ -const unsafe fn x() {} diff --git a/rustfmt-core/tests/source/issue-855.rs b/rustfmt-core/tests/source/issue-855.rs deleted file mode 100644 index 8f33fa685ae..00000000000 --- a/rustfmt-core/tests/source/issue-855.rs +++ /dev/null @@ -1,20 +0,0 @@ -fn main() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, - } - } - } -} - -fn main2() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit {..} | - Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => break 'running, - } - } - } -} diff --git a/rustfmt-core/tests/source/issue-913.rs b/rustfmt-core/tests/source/issue-913.rs deleted file mode 100644 index e1c1b225fa5..00000000000 --- a/rustfmt-core/tests/source/issue-913.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -mod client { - impl Client { - fn test(self) -> Result<()> { - let next_state = match self.state { - State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { - let x = reformat . meeee() ; - } - }; - - let next_state = match self.state { - State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { - // The pattern cannot be formatted in a way that the match stays - // within the column limit. The rewrite should therefore be - // skipped. - let x = dont . reformat . meeee(); - } - }; - } - } -} diff --git a/rustfmt-core/tests/source/issue-945.rs b/rustfmt-core/tests/source/issue-945.rs deleted file mode 100644 index 37d703c4679..00000000000 --- a/rustfmt-core/tests/source/issue-945.rs +++ /dev/null @@ -1,5 +0,0 @@ -impl Bar { default const unsafe fn foo() { "hi" } } - -impl Baz { default unsafe extern "C" fn foo() { "hi" } } - -impl Foo for Bar { default fn foo() { "hi" } } diff --git a/rustfmt-core/tests/source/issue-977.rs b/rustfmt-core/tests/source/issue-977.rs deleted file mode 100644 index b028b36a055..00000000000 --- a/rustfmt-core/tests/source/issue-977.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-normalize_comments: true -// FIXME(#919) - -trait NameC { /* comment */ } -struct FooC { /* comment */ } -enum MooC { /* comment */ } -mod BarC { /* comment */ } -extern { /* comment */ } diff --git a/rustfmt-core/tests/source/item-brace-style-always-next-line.rs b/rustfmt-core/tests/source/item-brace-style-always-next-line.rs deleted file mode 100644 index 38094d67a77..00000000000 --- a/rustfmt-core/tests/source/item-brace-style-always-next-line.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs b/rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs deleted file mode 100644 index dff89b8b66b..00000000000 --- a/rustfmt-core/tests/source/item-brace-style-prefer-same-line.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-brace_style: PreferSameLine - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/rustfmt-core/tests/source/item-brace-style-same-line-where.rs b/rustfmt-core/tests/source/item-brace-style-same-line-where.rs deleted file mode 100644 index ee4a7c5daad..00000000000 --- a/rustfmt-core/tests/source/item-brace-style-same-line-where.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-brace_style: SameLineWhere - -mod M { - enum A - { - A, - } - - struct B - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A where T: Copy { - A, - } - - struct B where T: Copy { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C where T: Copy {} - - struct D where T: Copy {} -} diff --git a/rustfmt-core/tests/source/large-block.rs b/rustfmt-core/tests/source/large-block.rs deleted file mode 100644 index 09e9169f340..00000000000 --- a/rustfmt-core/tests/source/large-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn issue1351() { - std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ - static __STATIC_FMTSTR: &'static [&'static str] = &[]; - }); -} diff --git a/rustfmt-core/tests/source/large_vec.rs b/rustfmt-core/tests/source/large_vec.rs deleted file mode 100644 index 34d5bf39954..00000000000 --- a/rustfmt-core/tests/source/large_vec.rs +++ /dev/null @@ -1,29 +0,0 @@ -// See #1470. - -impl Environment { - pub fn new_root() -> Rc> { - let mut env = Environment::new(); - let builtin_functions = &[("println", - Function::NativeVoid(CallSign { - num_params: 0, - variadic: true, - param_types: vec![], - }, - native_println)), - ("run_http_server", - Function::NativeVoid(CallSign { - num_params: 1, - variadic: false, - param_types: - vec![Some(ConstraintType::Function)], - }, - native_run_http_server)), - ("len", - Function::NativeReturning(CallSign { - num_params: 1, - variadic: false, - param_types: vec![None], - }, - native_len))]; - } -} diff --git a/rustfmt-core/tests/source/lazy_static.rs b/rustfmt-core/tests/source/lazy_static.rs deleted file mode 100644 index c1c74fb8307..00000000000 --- a/rustfmt-core/tests/source/lazy_static.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Format `lazy_static!`. - -lazy_static! { -static ref CONFIG_NAME_REGEX: regex::Regex = -regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); -static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) -.expect("Failed creating configuration value pattern"); -} - -// We need to be able to format `lazy_static!` without known syntax. -lazy_static!( - xxx, -yyyy , - zzzzz -); - -lazy_static!{ -} - -// #2354 -lazy_static ! { -pub static ref Sbase64_encode_string : :: lisp :: LispSubrRef = { -let subr = :: remacs_sys :: Lisp_Subr { -header : :: remacs_sys :: Lisp_Vectorlike_Header { -size : ( -( :: remacs_sys :: PseudovecType :: PVEC_SUBR as :: libc :: ptrdiff_t ) << :: -remacs_sys :: PSEUDOVECTOR_AREA_BITS ) , } , function : self :: -Fbase64_encode_string as * const :: libc :: c_void , min_args : 1i16 , -max_args : 2i16 , symbol_name : ( b"base64-encode-string\x00" ) . as_ptr ( ) -as * const :: libc :: c_char , intspec : :: std :: ptr :: null ( ) , doc : :: -std :: ptr :: null ( ) , lang : :: remacs_sys :: Lisp_Subr_Lang_Rust , } ; -unsafe { -let ptr = :: remacs_sys :: xmalloc ( -:: std :: mem :: size_of :: < :: remacs_sys :: Lisp_Subr > ( ) ) as * mut :: -remacs_sys :: Lisp_Subr ; :: std :: ptr :: copy_nonoverlapping ( -& subr , ptr , 1 ) ; :: std :: mem :: forget ( subr ) ; :: lisp :: ExternalPtr -:: new ( ptr ) } } ; } diff --git a/rustfmt-core/tests/source/long-match-arms-brace-newline.rs b/rustfmt-core/tests/source/long-match-arms-brace-newline.rs deleted file mode 100644 index 927ada0ffb2..00000000000 --- a/rustfmt-core/tests/source/long-match-arms-brace-newline.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 80 -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - match x { - aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == - "aaaaaaaaaaa \ - aaaaaaa \ - aaaaaa" => { - Ok(()) - } - _ => Err(x), - } -} diff --git a/rustfmt-core/tests/source/long_field_access.rs b/rustfmt-core/tests/source/long_field_access.rs deleted file mode 100644 index 7aa626221ae..00000000000 --- a/rustfmt-core/tests/source/long_field_access.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn f() { - block_flow.base.stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; -} diff --git a/rustfmt-core/tests/source/loop.rs b/rustfmt-core/tests/source/loop.rs deleted file mode 100644 index 6e92cdc6c2c..00000000000 --- a/rustfmt-core/tests/source/loop.rs +++ /dev/null @@ -1,29 +0,0 @@ - -fn main() { - loop - { return some_val;} - -let x = loop { do_forever(); }; - - 'label : loop { - // Just comments - } - - 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value{} - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { - } - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {} - - 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { - // do smth - } - - while let Some(i) = x.find('s') - { - x.update(); - continue; - continue 'foo; - } -} diff --git a/rustfmt-core/tests/source/macro_not_expr.rs b/rustfmt-core/tests/source/macro_not_expr.rs deleted file mode 100644 index d8de4dce38f..00000000000 --- a/rustfmt-core/tests/source/macro_not_expr.rs +++ /dev/null @@ -1,7 +0,0 @@ -macro_rules! test { - ($($t:tt)*) => {} -} - -fn main() { - test!( a : B => c d ); -} diff --git a/rustfmt-core/tests/source/macro_rules.rs b/rustfmt-core/tests/source/macro_rules.rs deleted file mode 100644 index dba1d78f0dd..00000000000 --- a/rustfmt-core/tests/source/macro_rules.rs +++ /dev/null @@ -1,114 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -macro_rules! m { - // a - ($expr :expr, $( $func : ident ) * ) => { - { - let x = $expr; - $func ( - x - ) - } - }; - - /* b */ - - () => {/* c */}; - - (@tag) => - { - - }; - -// d -( $item:ident ) => { - mod macro_item { struct $item ; } -}; -} - -macro m2 { - // a - ($expr :expr, $( $func : ident ) * ) => { - { - let x = $expr; - $func ( - x - ) - } - } - - /* b */ - - () => {/* c */} - - (@tag) => - { - - } - -// d -( $item:ident ) => { - mod macro_item { struct $item ; } -} -} - -// #2438, #2476 -macro_rules! m { - () => { - fn foo() { - this_line_is_98_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ); - } - } -} -macro_rules! m { - () => { - fn foo() { - this_line_is_99_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( -); - } - }; -} -macro_rules! m { - () => { - fn foo() { - this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( -); - } - }; -} -macro_rules! m { - () => { - fn foo() { - this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ); - } - }; -} - -// #2439 -macro_rules! m { - ( - $line0_xxxxxxxxxxxxxxxxx: expr, - $line1_xxxxxxxxxxxxxxxxx: expr, - $line2_xxxxxxxxxxxxxxxxx: expr, - $line3_xxxxxxxxxxxxxxxxx: expr, - ) => {}; -} - -// #2466 -// Skip formatting `macro_rules!` that are not using `{}`. -macro_rules! m ( - () => () -); -macro_rules! m [ - () => () -]; - -// #2470 -macro foo($type_name: ident, $docs: expr) { - #[allow(non_camel_case_types)] - #[doc=$docs] - #[derive(Debug, Clone, Copy)] - pub struct $type_name; -} diff --git a/rustfmt-core/tests/source/macros.rs b/rustfmt-core/tests/source/macros.rs deleted file mode 100644 index 11e6d52c6c8..00000000000 --- a/rustfmt-core/tests/source/macros.rs +++ /dev/null @@ -1,342 +0,0 @@ -// rustfmt-normalize_comments: true -itemmacro!(this, is.now() .formatted(yay)); - -itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); - -itemmacro!{this, is.bracket().formatted()} - -peg_file! modname ("mygrammarfile.rustpeg"); - -fn main() { - foo! ( ); - - bar!( a , b , c ); - - bar!( a , b , c , ); - - baz!(1+2+3, quux. kaas()); - - quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); - - kaas!(/* comments */ a /* post macro */, b /* another */); - - trailingcomma!( a , b , c , ); - // Preserve trailing comma only when necessary. - ok!(file.seek( - SeekFrom::Start( - table.map(|table| fixture.offset(table)).unwrap_or(0), - ) - )); - - noexpr!( i am not an expression, OK? ); - - vec! [ a , b , c]; - - vec! [AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, - BBBBB, 5, 100-30, 1.33, b, b, b]; - - vec! [a /* comment */]; - - // Trailing spaces after a comma - vec![ - a, - ]; - - vec![a; b]; - vec!(a; b); - vec!{a; b}; - - vec![a, b; c]; - vec![a; b, c]; - - vec![a; (|x| { let y = x + 1; let z = y + 1; z })(2)]; - vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; - vec![a; unsafe { - x + 1 - }]; - - unknown_bracket_macro__comma_should_not_be_stripped![ - a, - ]; - - foo(makro!(1, 3)); - - hamkaas!{ () }; - - macrowithbraces! {dont, format, me} - - x!(fn); - - some_macro!( - - ); - - some_macro![ - ]; - - some_macro!{ - // comment - }; - - some_macro!{ - // comment - }; - - some_macro!( - // comment - not function like - ); - - // #1712 - let image = gray_image!( - 00, 01, 02; - 10, 11, 12; - 20, 21, 22); - - // #1092 - chain!(input, a:take!(max_size), || []); -} - -impl X { - empty_invoc!{} -} - -fn issue_1279() { - println!("dsfs"); // a comment -} - -fn issue_1555() { - let hello = &format!("HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", - "65454654654654654654654655464", - "4"); -} - -fn issue1178() { - macro_rules! foo { - (#[$attr:meta] $name:ident) => {} - } - - foo!(#[doc = "bar"] baz); -} - -fn issue1739() { - sql_function!(add_rss_item, - add_rss_item_t, - (a: types::Integer, - b: types::Timestamptz, - c: types::Text, - d: types::Text, - e: types::Text)); - - w.slice_mut(s![.., init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], ..]) - .par_map_inplace(|el| *el = 0.); -} - -fn issue_1885() { - let threads = people.into_iter().map(|name| { - chan_select! { - rx.recv() => {} - } - }).collect::>(); -} - -fn issue_1917() { - mod x { - quickcheck! { - fn test(a: String, s: String, b: String) -> TestResult { - if a.find(&s).is_none() { - - TestResult::from_bool(true) - } else { - TestResult::discard() - } - } - } - } -} - -fn issue_1921() { - // Macro with tabs. - lazy_static! { - static ref ONE: u32 = 1; - static ref TWO: u32 = 2; - static ref THREE: u32 = 3; - static ref FOUR: u32 = { - let mut acc = 1; - acc += 1; - acc += 2; - acc - } -} -} - -// #1577 -fn issue1577() { - let json = json!({ - "foo": "bar", - }); -} - -gfx_pipeline!(pipe { - vbuf: gfx::VertexBuffer = (), - out: gfx::RenderTarget = "Target0", -}); - -// #1919 -#[test] -fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) - ) - ); - assert_eq ! ( :: std :: mem :: align_of :: < HandleWithDtor < :: std :: os :: raw :: c_int > > ( ) , 8usize , concat ! ( "Alignment of template specialization: " , stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) ) ); -} - -// #878 -macro_rules! try_opt { - ($expr:expr) => (match $expr { - Some(val) => val, - - None => { return None; } - }) -} - -// #2214 -// macro call whose argument is an array with trailing comma. -fn issue2214() { -make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [ - Reject(0, 1), - Match (1, 3), - Reject(3, 4), - Match (4, 6), - Reject(6, 7), -]); -} - -fn special_case_macros() { - let p = eprint!(); - let q = eprint!("{}", 1); - let r = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = eprintln!("{}", 1); - let r = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = format!("{}", 1); - let r = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = format_args!("{}", 1); - let r = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = print!("{}", 1); - let r = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = println!("{}", 1); - let r = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - let q = unreachable!("{}", 1); - let r = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - let s = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - debug!("{}", 1); - debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - error!("{}", 1); - error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - info!("{}", 1); - info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - panic!("{}", 1); - panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - warn!("{}", 1); - warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); - warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - assert!(); - assert!(result == 42); - assert!(result == 42, "Ahoy there, {}!", target); - assert!(result == 42, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - assert_eq!(); - assert_eq!(left); - assert_eq!(left, right); - assert_eq!(left, right, "Ahoy there, {}!", target); - assert_eq!(left, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert_eq!(left + 42, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - write!(&mut s, "Ahoy there, {}!", target); - write!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - write!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); - - writeln!(&mut s, "Ahoy there, {}!", target); - writeln!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); - writeln!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); -} - -// #1209 -impl Foo { - /// foo - pub fn foo(&self) -> Bar {} -} - -// #819 -fn macro_in_pattern_position () { - let x = match y { - foo!( ) => (), - bar!( a, b, - c) => (), - bar!(a - , b - , c - ,) => (), - baz!( 1 + 2 + 3, quux.kaas( ) - ) => (), - quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) => (), - }; -} - -macro foo() { - - -} - -pub macro bar($x:ident+$y:expr; ) { - fn foo($x: Foo) { - long_function(a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), - $x.bar($y)); - } -} - -macro foo() { - // a comment - fn foo() { - // another comment - bar(); - } -} - -macro lex_err($kind: ident $(, $body: expr)*) { - Err(QlError::LexError(LexError::$kind($($body,)*))) -} - -// Preserve trailing comma on item-level macro with `()` or `[]`. -methods![ get, post, delete, ]; -methods!( get, post, delete, ); diff --git a/rustfmt-core/tests/source/markdown-comment-with-options.rs b/rustfmt-core/tests/source/markdown-comment-with-options.rs deleted file mode 100644 index 2c4d6a5cc2b..00000000000 --- a/rustfmt-core/tests/source/markdown-comment-with-options.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-wrap_comments: true - -// Preserve two trailing whitespaces in doc comment, -// but trim any whitespaces in normal comment. - -//! hello world -//! hello world - -/// hello world -/// hello world -/// hello world -fn foo() { - // hello world - // hello world - let x = 3; - println!("x = {}", x); -} diff --git a/rustfmt-core/tests/source/markdown-comment.rs b/rustfmt-core/tests/source/markdown-comment.rs deleted file mode 100644 index 1ec26562fe2..00000000000 --- a/rustfmt-core/tests/source/markdown-comment.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Preserve two trailing whitespaces in doc comment, -// but trim any whitespaces in normal comment. - -//! hello world -//! hello world - -/// hello world -/// hello world -/// hello world -fn foo() { - // hello world - // hello world - let x = 3; - println!("x = {}", x); -} diff --git a/rustfmt-core/tests/source/match-block-trailing-comma.rs b/rustfmt-core/tests/source/match-block-trailing-comma.rs deleted file mode 100644 index e9daac13bf9..00000000000 --- a/rustfmt-core/tests/source/match-block-trailing-comma.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - } - b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - } -} diff --git a/rustfmt-core/tests/source/match-nowrap-trailing-comma.rs b/rustfmt-core/tests/source/match-nowrap-trailing-comma.rs deleted file mode 100644 index 134d2fdf9a4..00000000000 --- a/rustfmt-core/tests/source/match-nowrap-trailing-comma.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - } - b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - } -} diff --git a/rustfmt-core/tests/source/match-nowrap.rs b/rustfmt-core/tests/source/match-nowrap.rs deleted file mode 100644 index db22cd9f010..00000000000 --- a/rustfmt-core/tests/source/match-nowrap.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { foo() } - b => - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - } -} diff --git a/rustfmt-core/tests/source/match.rs b/rustfmt-core/tests/source/match.rs deleted file mode 100644 index f38bf7cca97..00000000000 --- a/rustfmt-core/tests/source/match.rs +++ /dev/null @@ -1,464 +0,0 @@ -// rustfmt-normalize_comments: true -// Match expressions. - -fn foo() { - // A match expression. - match x { - // Some comment. - a => foo(), - b if 0 < 42 => foo(), - c => { // Another comment. - // Comment. - an_expression; - foo() - } - Foo(ref bar) => - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - Pattern1 | Pattern2 | Pattern3 => false, - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { - blah - } - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn => meh, - - Patternnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, - - Patternnnnnnnnnnnnnnnnnnnnnnnnn | - Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => - meh, - - // Test that earlier patterns can take the guard space - (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | - Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} - - _ => {} - ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || - data.types.len() > 0 || - data.bindings.len() > 0 => {} - } - - let whatever = match something { - /// DOC COMMENT! - Some(_) => 42, - // Comment on an attribute. - #[an_attribute] - // Comment after an attribute. - None => 0, - #[rustfmt_skip] - Blurb => { } - }; -} - -// Test that a match on an overflow line is laid out properly. -fn main() { - let sub_span = - match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - Some(sub_span) => Some(sub_span), - None => sub_span, - }; -} - -// Test that one-line bodies align. -fn main() { - match r { - Variableeeeeeeeeeeeeeeeee => ( "variable", - vec!("id", "name", "qualname", - "value", "type", "scopeid"), - true, - true), - Enummmmmmmmmmmmmmmmmmmmm => ("enum", - vec!("id","qualname","scopeid","value"), - true, - true), - Variantttttttttttttttttttttttt => ("variant", - vec!("id", - "name", - "qualname", - "type", - "value", - "scopeid"), - true, - true), - }; - - match x{ - y=>{/*Block with comment. Preserve me.*/ } - z=>{stmt();} } -} - -fn matches() { - match 1 { - -1 => 10, - 1 => 1, // foo - 2 => 2, - // bar - 3 => 3, - _ => 0 // baz - } -} - -fn match_skip() { - let _ = match Some(1) { - #[rustfmt_skip] - Some( n ) => n, - None => 1, - }; -} - -fn issue339() { - match a { - b => {} - c => { } - d => { - } - e => { - - - - } - // collapsing here is safe - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { - } - // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } - h => { // comment above block - } - i => { - } // comment below block - j => { - // comment inside block - } - j2 => { - // comments inside... - } // ... and after - // TODO uncomment when vertical whitespace is handled better - // k => { - // - // // comment with WS above - // } - // l => { - // // comment with ws below - // - // } - m => { - } n => { } o => - { - - } - p => { // Dont collapse me - } q => { } r => - { - - } - s => 0, // s comment - // t comment - t => 1, - u => 2, - v => { - } /* funky block - * comment */ - // final comment - } -} - -fn issue355() { - match mac { - a => println!("a", b), - b => vec!(1, 2), - c => vec!(3; 4), - d => { - println!("a", b) - } - e => { - vec!(1, 2) - } - f => { - vec!(3; 4) - } - h => println!("a", b), // h comment - i => vec!(1, 2), // i comment - j => vec!(3; 4), // j comment - // k comment - k => println!("a", b), - // l comment - l => vec!(1, 2), - // m comment - m => vec!(3; 4), - // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), - // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), - // Macro support fails to recognise this macro as splittable - // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), - // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), - // Funky bracketing styles - t => println!{"a", b}, - u => vec!{1, 2}, - v => vec!{3; 4}, - w => println!["a", b], - x => vec![1, 2], - y =>vec![3; 4], - // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec!{1, 2}, // comment - vc =>vec!{3; 4}, // comment - wc =>println!["a", b], // comment - xc => vec![1,2], // comment - yc => vec![3; 4], // comment - yd => - looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd), - } -} - -fn issue280() { - { - match x { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == - '\n', - ast::ItemConst(ref typ, ref expr) => self.process_static_or_const_item(item, - &typ, - &expr), - } - } -} - -fn issue383() { - match resolution.last_private {LastImport{..} => false, _ => true}; -} - -fn issue507() { - match 1 { - 1 => unsafe { std::intrinsics::abort() }, - _ => (), - } -} - -fn issue508() { - match s.type_id() { - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLCanvasElement))) => true, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), - Some(NodeTypeId::Element(_)) => false, - } -} - -fn issue496() {{{{ - match def { - def::DefConst(def_id) | def::DefAssociatedConst(def_id) => - match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { - Some(const_expr) => { x }}}}}}} - -fn issue494() { - { - match stmt.node { - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => - result.push( - StmtRef::Mirror( - Box::new(Stmt { span: stmt.span, - kind: StmtKind::Expr { - scope: cx.tcx.region_maps.node_extent(id), - expr: expr.to_ref() } }))), - } - } -} - -fn issue386() { - match foo { - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => - true, - BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | - BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => - false, - } -} - -fn guards() { - match foo { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if fooooooooooooooooooooo && - (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {} - } -} - -fn issue1371() { - Some(match type_ { - sfEvtClosed => Closed, - sfEvtResized => { - let e = unsafe { *event.size.as_ref() }; - - Resized { - width: e.width, - height: e.height, - } - } - sfEvtLostFocus => LostFocus, - sfEvtGainedFocus => GainedFocus, - sfEvtTextEntered => { - TextEntered { - unicode: unsafe { - ::std::char::from_u32((*event.text.as_ref()).unicode) - .expect("Invalid unicode encountered on TextEntered event") - }, - } - } - sfEvtKeyPressed => { - let e = unsafe { event.key.as_ref() }; - - KeyPressed { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - sfEvtKeyReleased => { - let e = unsafe { event.key.as_ref() }; - - KeyReleased { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - }) -} - -fn issue1395() { - let bar = Some(true); - let foo = Some(true); - let mut x = false; - bar.and_then(|_| { - match foo { - None => None, - Some(b) => { - x = true; - Some(b) - } - } - }); -} - -fn issue1456() { - Ok(Recording { - artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { - Nodeset(nodeset) => { - let res: Result, ReadError> = nodeset - .iter() - .map(|node| { - XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) - }) - .collect(); - res? - } - _ => Vec::new(), - }, - }) -} - -fn issue1460() { - let _ = match foo { - REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => "internal_spec_insert_internal_spec_insert_internal_spec_insert", - _ => "reorder_something", - }; -} - -fn issue525() { - foobar(f, "{}", match *self { - TaskState::Started => "started", - TaskState::Success => "success", - TaskState::Failed => "failed", - }); -} - -// #1838, #1839 -fn match_with_near_max_width() { - let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { - _ => unimplemented!(), - }; - - let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { - _ => unimplemented!(), - }; - - let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression - { - _ => unimplemented!(), - }; - match m { - Variant::Tag | Variant::Tag2 | Variant::Tag3 | Variant::Tag4 | Variant::Tag5 | Variant::Tag6 => - {} - } -} - -fn match_with_trailing_spaces() { - match x { - #![allow(simple_match)] - Some(..) => 0, - None => 1, - } -} - -fn issue_2099() { - let a = match x { -}; - let b = match x { - - }; - - match x {} -} - -// #2021 -impl<'tcx> Const<'tcx> { - pub fn from_constval<'a>() -> Const<'tcx> { - let val = match *cv { - ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv), - }; - } -} - -// #2151 -fn issue_2151() { - match either { - x => { - - }y => () - } -} - -// #2152 -fn issue_2152() { - match m { - "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" if true => {} - "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => true, - } -} - -// #2462 -// Preserve a `|` at the beginning of a match arm. -fn match_with_beginning_vert() { - let x = Foo::A; - match x { - | Foo::A - | Foo::B => println!("AB"), - | Foo::C => println!("C"), - } -} diff --git a/rustfmt-core/tests/source/max-line-length-in-chars.rs b/rustfmt-core/tests/source/max-line-length-in-chars.rs deleted file mode 100644 index d49fbb7e30e..00000000000 --- a/rustfmt-core/tests/source/max-line-length-in-chars.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-max_width: 25 - -// абвгдеёжзийклмнопрст -fn main() {} diff --git a/rustfmt-core/tests/source/mod-1.rs b/rustfmt-core/tests/source/mod-1.rs deleted file mode 100644 index 427a355b6be..00000000000 --- a/rustfmt-core/tests/source/mod-1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Deeply indented modules. - - mod foo { mod bar { mod baz {} } } - -mod foo { - mod bar { - mod baz { - fn foo() { bar() } - } - } - - mod qux { - - } -} - -mod boxed { pub use std::boxed::{Box, HEAP}; } - -pub mod x { - pub fn freopen(filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE) - -> *mut FILE{} -} - - mod y { // sup boooooiiii - } diff --git a/rustfmt-core/tests/source/mod-2.rs b/rustfmt-core/tests/source/mod-2.rs deleted file mode 100644 index 7202e00203e..00000000000 --- a/rustfmt-core/tests/source/mod-2.rs +++ /dev/null @@ -1,4 +0,0 @@ -// Some nested mods - -#[cfg(test)] mod nestedmod ; -pub mod no_new_line_beginning; diff --git a/rustfmt-core/tests/source/mod_skip_child.rs b/rustfmt-core/tests/source/mod_skip_child.rs deleted file mode 100644 index d48c4a37e81..00000000000 --- a/rustfmt-core/tests/source/mod_skip_child.rs +++ /dev/null @@ -1,2 +0,0 @@ -// rustfmt-skip_children: true -mod nested_skipped; diff --git a/rustfmt-core/tests/source/multiple.rs b/rustfmt-core/tests/source/multiple.rs deleted file mode 100644 index 68cfacfcb4b..00000000000 --- a/rustfmt-core/tests/source/multiple.rs +++ /dev/null @@ -1,134 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-format_strings: true -// Test of lots of random stuff. -// FIXME split this into multiple, self-contained tests. - - -#[attr1] extern crate foo; -#[attr2] #[attr3] extern crate foo; -#[attr1]extern crate foo; -#[attr2]#[attr3]extern crate foo; - -use std::cell::*; -use std::{any, ascii, self, borrow, boxed, char, borrow, boxed, char, borrow, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char}; - -mod doc; -mod other; - - -// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff - - fn foo(a: isize, - b: u32, /* blah blah */ - c: f64) { - -} - -fn foo()->Box where 'a: 'b, for<'a> D<'b>: 'a { - hello!() -} - -fn baz<'a: 'b /* comment on 'a */, T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */>(a: A, b: B /* comment on b */, c: C) -> Bob { - #[attr1] extern crate foo; - #[attr2] #[attr3] extern crate foo; - #[attr1]extern crate foo; - #[attr2]#[attr3]extern crate foo; -} - -#[rustfmt_skip] -fn qux(a: dadsfa, // Comment 1 - b: sdfasdfa, // Comment 2 - c: dsfdsafa) // Comment 3 -{ - -} - -/// Blah blah blah. -impl Bar { - fn foo(&mut self, a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a - b: sdfasdfsdfasfs /*closing comment*/ ) -> isize {} - - /// Blah blah blah. - pub fn f2(self) { - (foo, bar) - } - - #[an_attribute] - fn f3(self) -> Dog { - } -} - -/// The `nodes` and `edges` method each return instantiations of -/// `Cow<[T]>` to leave implementers the freedom to create - -/// entirely new vectors or to pass back slices into internally owned -/// vectors. -pub trait GraphWalk<'a, N, E> { - /// Returns all the nodes in this graph. - fn nodes(&'a self) -> Nodes<'a, N>; - /// Returns all of the edges in this graph. - fn edges(&'a self) -> Edges<'a, E>; - /// The source node for `edge`. - fn source(&'a self, edge: &E) -> N; - /// The target node for `edge`. - fn target(&'a self, edge: &E) -> N; -} - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f : SomeType, // Comment beside a field - // Comment on a field - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType,} - -struct Bar; - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -fn foo(ann: &'a (PpAnn+'a)) {} - -fn main() { - for i in 0i32..4 { - println!("{}", i); - } - - - while true { - hello(); - } - - let rc = Cell::new(42usize,42usize, Cell::new(42usize, remaining_widthremaining_widthremaining_widthremaining_width), 42usize); - let rc = RefCell::new(42usize,remaining_width, remaining_width); // a comment - let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; - let s = expand(a - , - b); } - -fn deconstruct() -> (SocketAddr, Method, Headers, - RequestUri, HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { -} - -fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, - RequestUri, HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { -} - -#[rustfmt_skip] -mod a{ -fn foo(x: T) { - let x: T = dfasdf; -} -} diff --git a/rustfmt-core/tests/source/nested-if-else.rs b/rustfmt-core/tests/source/nested-if-else.rs deleted file mode 100644 index 9a54789ddcd..00000000000 --- a/rustfmt-core/tests/source/nested-if-else.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn issue1518() { - Some(Object { - field: if a { - a_thing - } else if b { - b_thing - } else { - c_thing - }, - }) -} diff --git a/rustfmt-core/tests/source/nested_skipped/mod.rs b/rustfmt-core/tests/source/nested_skipped/mod.rs deleted file mode 100644 index 44b25ca8797..00000000000 --- a/rustfmt-core/tests/source/nested_skipped/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn ugly() { -92; -} diff --git a/rustfmt-core/tests/source/nestedmod/mod.rs b/rustfmt-core/tests/source/nestedmod/mod.rs deleted file mode 100644 index d04e49570a4..00000000000 --- a/rustfmt-core/tests/source/nestedmod/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ - -mod mod2a; -mod mod2b; - -mod mymod1 { - use mod2a::{Foo,Bar}; -mod mod3a; -} - -#[path="mod2c.rs"] -mod mymod2; - -mod submod2; diff --git a/rustfmt-core/tests/source/nestedmod/mod2a.rs b/rustfmt-core/tests/source/nestedmod/mod2a.rs deleted file mode 100644 index 5df457a8316..00000000000 --- a/rustfmt-core/tests/source/nestedmod/mod2a.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This is an empty file containing only -// comments - -// ................... diff --git a/rustfmt-core/tests/source/nestedmod/mod2b.rs b/rustfmt-core/tests/source/nestedmod/mod2b.rs deleted file mode 100644 index f128e2da6db..00000000000 --- a/rustfmt-core/tests/source/nestedmod/mod2b.rs +++ /dev/null @@ -1,3 +0,0 @@ - -#[path="mod2a.rs"] -mod c; diff --git a/rustfmt-core/tests/source/nestedmod/mod2c.rs b/rustfmt-core/tests/source/nestedmod/mod2c.rs deleted file mode 100644 index eda6b233e4b..00000000000 --- a/rustfmt-core/tests/source/nestedmod/mod2c.rs +++ /dev/null @@ -1,3 +0,0 @@ -// A standard mod - -fn a( ) {} diff --git a/rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs b/rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs deleted file mode 100644 index f28bde5e56d..00000000000 --- a/rustfmt-core/tests/source/nestedmod/mymod1/mod3a.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Another mod -fn a( ) { } diff --git a/rustfmt-core/tests/source/nestedmod/submod2/a.rs b/rustfmt-core/tests/source/nestedmod/submod2/a.rs deleted file mode 100644 index 0eaf08f0d2c..00000000000 --- a/rustfmt-core/tests/source/nestedmod/submod2/a.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Yet Another mod -// Nested - -use c::a; - -fn foo( ) { } diff --git a/rustfmt-core/tests/source/nestedmod/submod2/mod.rs b/rustfmt-core/tests/source/nestedmod/submod2/mod.rs deleted file mode 100644 index 52f8be91022..00000000000 --- a/rustfmt-core/tests/source/nestedmod/submod2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Another mod - -mod a; - -use a::a; diff --git a/rustfmt-core/tests/source/no_new_line_beginning.rs b/rustfmt-core/tests/source/no_new_line_beginning.rs deleted file mode 100644 index f79c691f085..00000000000 --- a/rustfmt-core/tests/source/no_new_line_beginning.rs +++ /dev/null @@ -1,2 +0,0 @@ -fn main() { -} diff --git a/rustfmt-core/tests/source/other.rs b/rustfmt-core/tests/source/other.rs deleted file mode 100644 index dfce84fcdc4..00000000000 --- a/rustfmt-core/tests/source/other.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Part of multiple.rs - -fn bob() { - println!("hello other!"); -} diff --git a/rustfmt-core/tests/source/paths.rs b/rustfmt-core/tests/source/paths.rs deleted file mode 100644 index ebc26f146e4..00000000000 --- a/rustfmt-core/tests/source/paths.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - let constellation_chan = Constellation:: ::start( - compositor_proxy, - resource_task, - image_cache_task,font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard - ); - - Quux::::some_func(); - - < *mut JSObject >:: relocate(entry); - - let x: Foo; - let x: Foo/*::*/; -} - -fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/rustfmt-core/tests/source/pattern-condense-wildcards.rs b/rustfmt-core/tests/source/pattern-condense-wildcards.rs deleted file mode 100644 index 244e935639a..00000000000 --- a/rustfmt-core/tests/source/pattern-condense-wildcards.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-condense_wildcard_suffixes: true - -fn main() { - match x { - Butt (_,_) => "hah", - Tup (_) => "nah", - Quad (_,_, x,_) => " also no rewrite", - Quad (x, _, _, _) => "condense me pls", - Weird (x, _, _, /* dont condense before */ _, _, _) => "pls work", - } -} diff --git a/rustfmt-core/tests/source/pattern.rs b/rustfmt-core/tests/source/pattern.rs deleted file mode 100644 index 7c052c87bc4..00000000000 --- a/rustfmt-core/tests/source/pattern.rs +++ /dev/null @@ -1,65 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - let z = match x { - "pat1" => 1, - ( ref x, ref mut y /*comment*/) => 2, - }; - - if let < T as Trait > :: CONST = ident { - do_smth(); - } - - let Some ( ref xyz /* comment! */) = opt; - - if let None = opt2 { panic!("oh noes"); } - - let foo@bar (f) = 42; - let a::foo ( ..) = 42; - let [ ] = 42; - let [a.., b,c ] = 42; - let [ a,b,c.. ] = 42; - let [a, b, c, d..,e,f, g] = 42; - let foo { } = 42; - let foo {..} = 42; - let foo { x, y: ref foo, .. } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; - let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; -} - -impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { - fn mutate_fragment(&mut self, fragment: &mut Fragment) { - match **info { - GeneratedContentInfo::ContentItem( - ContentItem::Counter( - ref counter_name, - counter_style - ) - ) => {}}} -} - -fn issue_1319() { - if let (Event { .. }, .. ) = ev_state {} -} - -fn issue_1874() { - if let Some(()) = x { -y - } -} - -fn combine_patterns() { - let x = match y { - Some( - Some( - Foo { - z: Bar(..), - a: Bar(..), - b: Bar(..), - }, - ), - ) => z, - _ => return, - }; -} diff --git a/rustfmt-core/tests/source/pub-restricted.rs b/rustfmt-core/tests/source/pub-restricted.rs deleted file mode 100644 index 30051fa72ee..00000000000 --- a/rustfmt-core/tests/source/pub-restricted.rs +++ /dev/null @@ -1,64 +0,0 @@ -pub( super ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub( crate ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - - crate enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(in ::global:: path :: to::some_mod ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub( in local:: path :: to::some_mod ) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} diff --git a/rustfmt-core/tests/source/remove_blank_lines.rs b/rustfmt-core/tests/source/remove_blank_lines.rs deleted file mode 100644 index 7466e21eed8..00000000000 --- a/rustfmt-core/tests/source/remove_blank_lines.rs +++ /dev/null @@ -1,44 +0,0 @@ -fn main() { - - - - - let x = 1; - - - let y = 2; - - - println!("x + y = {}", x + y); - - - -} - - -fn foo() { - - #![attribute] - - let x = 1; - - // comment - - -} -// comment after item - - -// comment before item -fn bar() { - let x = 1; - // comment after statement - - - // comment before statment - let y = 2; - let z = 3; - - - println!("x + y + z = {}", x + y + z); -} diff --git a/rustfmt-core/tests/source/single-line-if-else.rs b/rustfmt-core/tests/source/single-line-if-else.rs deleted file mode 100644 index bcde390d116..00000000000 --- a/rustfmt-core/tests/source/single-line-if-else.rs +++ /dev/null @@ -1,49 +0,0 @@ - -// Format if-else expressions on a single line, when possible. - -fn main() { - let a = if 1 > 2 { - unreachable!() - } else { - 10 - }; - - let a = if x { 1 } else if y { 2 } else { 3 }; - - let b = if cond() { - 5 - } else { - // Brief comment. - 10 - }; - - let c = if cond() { - statement(); - - 5 - } else { - 10 - }; - - let d = if let Some(val) = turbo - { "cool" } else { - "beans" }; - - if cond() { statement(); } else { other_statement(); } - - if true { - do_something() - } - - let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; - - let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { - bbbbbbbbbb }; - - funk(if test() { - 1 - } else { - 2 - }, - arg2); -} diff --git a/rustfmt-core/tests/source/soft-wrapping.rs b/rustfmt-core/tests/source/soft-wrapping.rs deleted file mode 100644 index ace8359409c..00000000000 --- a/rustfmt-core/tests/source/soft-wrapping.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 80 -// Soft wrapping for comments. - -// #535, soft wrapping for comments -// Compare the lowest `f32` of both inputs for greater than or equal. The -// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off -// the result are the upper 96 bits of `a`. - -/// Compare the lowest `f32` of both inputs for greater than or equal. The -/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off -/// the result are the upper 96 bits of `a`. -fn foo() {} diff --git a/rustfmt-core/tests/source/space-not-before-newline.rs b/rustfmt-core/tests/source/space-not-before-newline.rs deleted file mode 100644 index 2a1e1856908..00000000000 --- a/rustfmt-core/tests/source/space-not-before-newline.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo { - a: (), - // spaces ^^^ to be removed -} -enum Foo { - Bar, - // spaces ^^^ to be removed -} diff --git a/rustfmt-core/tests/source/spaces-around-ranges.rs b/rustfmt-core/tests/source/spaces-around-ranges.rs deleted file mode 100644 index 1936b5e161f..00000000000 --- a/rustfmt-core/tests/source/spaces-around-ranges.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-spaces_around_ranges: true - -fn bar(v: &[u8]) {} - -fn foo() { - let a = vec![0; 20]; - for j in 0..=20 { - for i in 0..3 { - bar(a[i..j]); - bar(a[i..]); - bar(a[..j]); - bar(a[..=(j + 1)]); - } - } -} diff --git a/rustfmt-core/tests/source/static.rs b/rustfmt-core/tests/source/static.rs deleted file mode 100644 index 970786381cc..00000000000 --- a/rustfmt-core/tests/source/static.rs +++ /dev/null @@ -1,23 +0,0 @@ -const FILE_GENERIC_READ: DWORD = - STANDARD_RIGHTS_READ | FILE_READ_DATA | - FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; - -static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", - "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", - "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", - "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; - -static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; - - pub static count : u8 = 10 ; - -pub const test: &Type = &val; - -impl Color { - pub const WHITE: u32 = 10; -} - -// #1391 -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; - -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/rustfmt-core/tests/source/string-lit-2.rs b/rustfmt-core/tests/source/string-lit-2.rs deleted file mode 100644 index 6b95e25a052..00000000000 --- a/rustfmt-core/tests/source/string-lit-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn main() -> &'static str { - let too_many_lines = "Hello"; - let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ - s - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; -} - -fn issue_1237() { - let msg = "eedadn\n\ - drvtee\n\ - eandsr\n\ - raavrd\n\ - atevrs\n\ - tsrnev\n\ - sdttsa\n\ - rasrtv\n\ - nssdts\n\ - ntnada\n\ - svetve\n\ - tesnvt\n\ - vntsnd\n\ - vrdear\n\ - dvrsen\n\ - enarar"; -} diff --git a/rustfmt-core/tests/source/string-lit.rs b/rustfmt-core/tests/source/string-lit.rs deleted file mode 100644 index e86f65f9f52..00000000000 --- a/rustfmt-core/tests/source/string-lit.rs +++ /dev/null @@ -1,62 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false -// Long string literals - -fn main() -> &'static str { - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let too_many_lines = "H\ - e\ - l\ - l\ - o"; - - // Make sure we don't break after an escape character. - let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - - let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let raw_string = r#"Do -not -remove -formatting"#; - - filename.replace(" ", "\\" ); - - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = - funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); - - let unicode = "a̐éö̲\r\n"; - let unicode2 = "Löwe 老虎 Léopard"; - let unicode3 = "中华Việt Nam"; - let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; - - "stuffin'" -} - -fn issue682() { - let a = "hello \\ o/"; - let b = a.replace("\\ ", "\\"); -} - -fn issue716() { - println!("forall x. mult(e(), x) = x /\\ - forall x. mult(x, x) = e()"); -} - -fn issue_1282() { - { - match foo { - Permission::AndroidPermissionAccessLocationExtraCommands => { - "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" - } - } - } -} - -// #1987 -#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] -extern "C" {} diff --git a/rustfmt-core/tests/source/string_punctuation.rs b/rustfmt-core/tests/source/string_punctuation.rs deleted file mode 100644 index 6a0afd45e5a..00000000000 --- a/rustfmt-core/tests/source/string_punctuation.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false - -fn main() { - println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); - format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); - println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); -} diff --git a/rustfmt-core/tests/source/struct-field-attributes.rs b/rustfmt-core/tests/source/struct-field-attributes.rs deleted file mode 100644 index 76d6eda8853..00000000000 --- a/rustfmt-core/tests/source/struct-field-attributes.rs +++ /dev/null @@ -1,52 +0,0 @@ -// #1535 -#![feature(struct_field_attributes)] - -struct Foo { - bar: u64, - - #[cfg(test)] - qux: u64, -} - -fn do_something() -> Foo { - Foo { - bar: 0, - - #[cfg(test)] - qux: 1, - } -} - -fn main() { - do_something(); -} - -// #1462 -struct Foo { - foo: usize, - #[cfg(feature="include-bar")] - bar: usize, -} - -fn new_foo() -> Foo { - Foo { - foo: 0, - #[cfg(feature="include-bar")] - bar: 0, - } -} - -// #2044 -pub enum State { - Closure(#[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] GcPtr), -} - -struct Fields( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] Arc>, -); - -// #2309 -pub struct A { -#[doc="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] -pub foos:Vec -} diff --git a/rustfmt-core/tests/source/struct_lits.rs b/rustfmt-core/tests/source/struct_lits.rs deleted file mode 100644 index 3a8016367b6..00000000000 --- a/rustfmt-core/tests/source/struct_lits.rs +++ /dev/null @@ -1,144 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:f() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { memb: T } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S{a:0, .. b}; -} - -fn issue201_2() { - let s = S{a: S2{ .. c}, .. b}; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo - { a : 1, b:f( 2)}; - Foo{a:1,b:f(2),..g(3)}; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; - IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { a: bb, c: dd, e: ff }; - - Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ - e: eeeeeeeee }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, .. base }; - Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ - eeeeeeeee }; - Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; -} diff --git a/rustfmt-core/tests/source/struct_lits_multiline.rs b/rustfmt-core/tests/source/struct_lits_multiline.rs deleted file mode 100644 index 256ba1bbda3..00000000000 --- a/rustfmt-core/tests/source/struct_lits_multiline.rs +++ /dev/null @@ -1,81 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-struct_lit_single_line: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:foo() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { memb: T } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S{a:0, .. b}; -} - -fn issue201_2() { - let s = S{a: S2{ .. c}, .. b}; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; -} diff --git a/rustfmt-core/tests/source/struct_lits_visual.rs b/rustfmt-core/tests/source/struct_lits_visual.rs deleted file mode 100644 index 2c6cc674960..00000000000 --- a/rustfmt-core/tests/source/struct_lits_visual.rs +++ /dev/null @@ -1,47 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:f() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, z: zzzzz // test - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} diff --git a/rustfmt-core/tests/source/struct_lits_visual_multiline.rs b/rustfmt-core/tests/source/struct_lits_visual_multiline.rs deleted file mode 100644 index d0b5ea6efba..00000000000 --- a/rustfmt-core/tests/source/struct_lits_visual_multiline.rs +++ /dev/null @@ -1,45 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-struct_lit_single_line: false -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo {a: x }; - - Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a:Bar, - b:foo() }; - - Quux { x: if cond { bar(); }, y: baz() }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item - }; - - Diagram { /* o This graph demonstrates how - * / \ significant whitespace is - * o o preserved. - * /|\ \ - * o o o o */ - graph: G, } -} diff --git a/rustfmt-core/tests/source/struct_tuple_visual.rs b/rustfmt-core/tests/source/struct_tuple_visual.rs deleted file mode 100644 index 369feae71d2..00000000000 --- a/rustfmt-core/tests/source/struct_tuple_visual.rs +++ /dev/null @@ -1,37 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual -fn foo() { - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment - foo(), /* Comment */ - // Comment - bar() /* Comment */); - - Foo(Bar, f()); - - Quux(if cond { - bar(); - }, - baz()); - - Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - zzzzz /* test */); - - A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - Item); - - Diagram(// o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - G) -} diff --git a/rustfmt-core/tests/source/structs.rs b/rustfmt-core/tests/source/structs.rs deleted file mode 100644 index 25070aef34c..00000000000 --- a/rustfmt-core/tests/source/structs.rs +++ /dev/null @@ -1,283 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - - /// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField -} - -// #1095 -struct S { - t: T, -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] //only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct -NewInt (pub i32, SomeType /* inline comment */, T /* sup */ - - - ); - -struct Qux<'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy> -( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C - -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - - - - c: C, // Comment C -} - -struct Baz { - - a: A, - - b: B, - c: C, - - - - - d: D - -} - -struct Baz -{ - // Comment A - a: A, - - // Comment B -b: B, - // Comment C - c: C,} - -// Will this be a one-liner? -struct Tuple( - A, //Comment - B -); - -pub struct State time::Timespec> { now: F } - -pub struct State ()> { now: F } - -pub struct State { now: F } - -struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color - foo: i32} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB - //Another pre comment - #[attr1] - #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(T); -struct Foo(T) where T: Copy, T: Eq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); -struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; -struct Foo(TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU); - -mod m { - struct X where T: Sized { - a: T, - } -} - -struct Foo(TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn( obj: - *const libc::c_void, tracer : *mut JSTracer ), -} - -struct Foo {} -struct Foo { - } -struct Foo { - // comment - } -struct Foo { - // trailing space -> - - - } -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -struct Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} - -// structs with long identifier -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { x: i32 } - -// structs with visibility, do not duplicate visibility (#2110). -pub(in self) struct Foo{} -pub(super) struct Foo{} -pub(crate) struct Foo{} -pub(in self) struct Foo(); -pub(super) struct Foo(); -pub(crate) struct Foo(); - -// #2125 -pub struct ReadinessCheckRegistry(Mutex, Box ReadinessCheck + Sync + Send>>>); - -// #2144 unit struct with generics -struct MyBox; -struct MyBoxx where T: ?Sized, S: Clone; - -// #2208 -struct Test { - /// foo - #[serde(default)] - pub join: Vec, - #[serde(default)] pub tls: bool, -} diff --git a/rustfmt-core/tests/source/trailing-comma-never.rs b/rustfmt-core/tests/source/trailing-comma-never.rs deleted file mode 100644 index 5985b514724..00000000000 --- a/rustfmt-core/tests/source/trailing-comma-never.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-trailing_comma: Never - -enum X { - A, - B, -} - -enum Y { - A, - B -} - -enum TupX { - A(u32), - B(i32, u16), -} - -enum TupY { - A(u32), - B(i32, u16) -} - -enum StructX { - A { - s: u16, - }, - B { - u: u32, - i: i32, - }, -} - -enum StructY { - A { - s: u16, - }, - B { - u: u32, - i: i32, - } -} diff --git a/rustfmt-core/tests/source/trailing_commas.rs b/rustfmt-core/tests/source/trailing_commas.rs deleted file mode 100644 index 3e5fcc8080f..00000000000 --- a/rustfmt-core/tests/source/trailing_commas.rs +++ /dev/null @@ -1,47 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// rustfmt-trailing_comma: Always - -fn main() { - match foo { - x => {} - y => { - foo(); - } - _ => x - } -} - -fn f(x: T, y: S) -> T where T: P, S: Q -{ - x -} - -impl Trait for T where T: P -{ - fn f(x: T) -> T where T: Q + R - { - x - } -} - -struct Pair where T: P, S: P + Q { - a: T, - b: S -} - -struct TupPair (S, T) where T: P, S: P + Q; - -enum E where S: P, T: P { - A {a: T}, -} - -type Double where T: P, T: Q = Pair; - -extern "C" { - fn f(x: T, y: S) -> T where T: P, S: Q; -} - -trait Q where T: P, S: R -{ - fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; -} diff --git a/rustfmt-core/tests/source/trait.rs b/rustfmt-core/tests/source/trait.rs deleted file mode 100644 index e8de36db35e..00000000000 --- a/rustfmt-core/tests/source/trait.rs +++ /dev/null @@ -1,94 +0,0 @@ -// Test traits - -trait Foo { - fn bar(x: i32 ) -> Baz< U> { Baz::new() - } - - fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, -b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) --> RetType; - - fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment -b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) - -> RetType ; // Some comment - - fn baz(&mut self ) -> i32 ; - -fn increment(& mut self, x: i32 ); - - fn read(&mut self, x: BufReader /* Used to be MemReader */) - where R: Read; -} - -pub trait WriteMessage { - fn write_message (&mut self, &FrontendMessage) -> io::Result<()>; -} - -trait Runnable { - fn handler(self: & Runnable ); -} - -trait TraitWithExpr { - fn fn_with_expr(x: [i32; 1]); -} - -trait Test { - fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; -} - -trait T<> {} - -trait Foo { type Bar: Baz; type Inner: Foo = Box< Foo >; } - -trait ConstCheck:Foo where T: Baz { - const J: i32; -} - -trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt - where T: Foo {} - -trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} - -trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } - -trait WhereList where T: Foo, J: Bar {} - -trait X /* comment */ {} -trait Y // comment -{ -} - -// #2055 -pub trait Foo: -// A and C -A + C -// and B - + B -{} - -// #2158 -trait Foo { - type ItRev = > as UntypedTimeSeries>::IterRev; - type IteRev = > as UntypedTimeSeries>::IterRev; -} - -// #2331 -trait MyTrait { - fn foo() {} -} - -// Trait aliases -trait FooBar = - Foo - + Bar; -trait FooBar = - Foo - + Bar; -trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; -#[rustfmt_skip] -trait FooBar = Foo - + Bar; diff --git a/rustfmt-core/tests/source/try-conversion.rs b/rustfmt-core/tests/source/try-conversion.rs deleted file mode 100644 index ed83ee9e101..00000000000 --- a/rustfmt-core/tests/source/try-conversion.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-use_try_shorthand: true - -fn main() { - let x = try!(some_expr()); - - let y = try!(a.very.loooooooooooooooooooooooooooooooooooooong().chain().inside().weeeeeeeeeeeeeee()).test().0.x; -} - -fn test() { - a? -} - -fn issue1291() { - try!(fs::create_dir_all(&gitfiledir).chain_err(|| { - format!("failed to create the {} submodule directory for the workarea", - name) - })); -} diff --git a/rustfmt-core/tests/source/tuple.rs b/rustfmt-core/tests/source/tuple.rs deleted file mode 100644 index 6c3ec8f1115..00000000000 --- a/rustfmt-core/tests/source/tuple.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Test tuple litterals - -fn foo() { - let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); - let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaa, - aaaa); - let a = (a,); - - let b = (// This is a comment - b, // Comment - b /* Trailing comment */); - - // #1063 - foo(x.0 .0); -} - -fn a() { - ((aaaaaaaa, - aaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa),) -} - -fn b() { - ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), - bbbbbbbbbbbbbbbbbb) -} - -fn issue550() { - self.visitor.visit_volume(self.level.sector_id(sector), (floor_y, - if is_sky_flat(ceil_tex) {from_wad_height(self.height_range.1)} else {ceil_y})); -} - -fn issue775() { - if indent { - let a = mk_object(&[("a".to_string(), Boolean(true)), - ("b".to_string(), - Array(vec![mk_object(&[("c".to_string(), - String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), String("".to_string()))])]))]); - } -} - -fn issue1725() { - bench_antialiased_lines!(bench_draw_antialiased_line_segment_diagonal, (10, 10), (450, 450)); - bench_antialiased_lines!(bench_draw_antialiased_line_segment_shallow, (10, 10), (450, 80)); -} diff --git a/rustfmt-core/tests/source/type-ascription.rs b/rustfmt-core/tests/source/type-ascription.rs deleted file mode 100644 index 3b761f4fc78..00000000000 --- a/rustfmt-core/tests/source/type-ascription.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; - - let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - x : u32 - 1u32 / 10f32 : u32 -} diff --git a/rustfmt-core/tests/source/type.rs b/rustfmt-core/tests/source/type.rs deleted file mode 100644 index 0a46ffb2ee4..00000000000 --- a/rustfmt-core/tests/source/type.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-normalize_comments: true -fn types() { - let x: [ Vec < _ > ] = []; - let y: * mut [ SomeType ; konst_funk() ] = expr(); - let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); - let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk(); -} - -struct F { - f: extern "C" fn(x: u8, ... /* comment */), - g: extern "C" fn(x: u8,/* comment */ ...), - h: extern "C" fn(x: u8, ... ), - i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3 - z: Foo, /* comment */ .../* comment 2*/ ), -} - -fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} - -fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} - -fn impl_trait_fn_2() -> impl Future {} - -fn issue_1234() { - do_parse!(name: take_while1!(is_token) >> (Header)) -} diff --git a/rustfmt-core/tests/source/type_alias.rs b/rustfmt-core/tests/source/type_alias.rs deleted file mode 100644 index 58c807f4029..00000000000 --- a/rustfmt-core/tests/source/type_alias.rs +++ /dev/null @@ -1,34 +0,0 @@ -// rustfmt-normalize_comments: true - -type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); - -pub type PublicTest<'a, I, O> = Result, Box + 'a>, Box + 'a>>; - -pub type LongGenericListTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Option>; - -pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; - -pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; - -pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; - -pub type GenericsFitButNotEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A1, B, C> = Vec; - -pub type CommentTest< /* Lifetime */ 'a - , - // Type - T - > = (); - - -pub type WithWhereClause where T: Clone, LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; - -pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; - -pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; - -type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); - -// #1683 -pub type Between = super::operators::Between, AsExpr>>; -pub type NotBetween = super::operators::NotBetween, AsExpr>>; diff --git a/rustfmt-core/tests/source/unions.rs b/rustfmt-core/tests/source/unions.rs deleted file mode 100644 index fc2908e2d9e..00000000000 --- a/rustfmt-core/tests/source/unions.rs +++ /dev/null @@ -1,195 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - - /// A Doc comment -#[AnAttribute] -pub union Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField -} - -// #1029 -pub union Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -union X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub union Writebatch { - #[allow(dead_code)] //only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -// With a where clause and generics. -pub union Foo<'a, Y: Baz> - where X: Whatever -{ - f: SomeType, // Comment beside a field -} - -union Baz { - - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C - -} - -union Baz { - a: A, // Comment A - - b: B, // Comment B - - - - - c: C, // Comment C -} - -union Baz { - - a: A, - - b: B, - c: C, - - - - - d: D - -} - -union Baz -{ - // Comment A - a: A, - - // Comment B -b: B, - // Comment C - c: C,} - -pub union State time::Timespec> { now: F } - -pub union State ()> { now: F } - -pub union State { now: F } - -union Palette { /// A map of indices in the palette to a count of pixels in approximately that color - foo: i32} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -union FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB - //Another pre comment - #[attr1] - #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -mod m { - union X where T: Sized { - a: T, - } -} - -union Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn( obj: - *const libc::c_void, tracer : *mut JSTracer ), -} - -union Foo {} -union Foo { - } -union Foo { - // comment - } -union Foo { - // trailing space -> - - - } -union Foo { /* comment */ } - -union LongUnion { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, - Type, - NodeType>, -} - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -union Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} diff --git a/rustfmt-core/tests/source/where-clause-rfc.rs b/rustfmt-core/tests/source/where-clause-rfc.rs deleted file mode 100644 index e41e9a6cea1..00000000000 --- a/rustfmt-core/tests/source/where-clause-rfc.rs +++ /dev/null @@ -1,58 +0,0 @@ -// rustfmt-indent_style: Block - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { - let mut effects = HashMap::new(); -} - -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; - - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; - -struct Exactly100CharsToSemicolon - (LongLongTypename, i32, i32) - where A: LongTrait1234; - -struct AlwaysOnNextLine where A: LongTrait { - x: i32 -} - -pub trait SomeTrait - where - T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr -{ -} - -// #2020 -impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { - fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) - where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssociatedItem), - { - // ... - } -} diff --git a/rustfmt-core/tests/source/where-clause.rs b/rustfmt-core/tests/source/where-clause.rs deleted file mode 100644 index 2a916082548..00000000000 --- a/rustfmt-core/tests/source/where-clause.rs +++ /dev/null @@ -1,58 +0,0 @@ -// rustfmt-indent_style: Visual - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { - let mut effects = HashMap::new(); -} - -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; - - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; - -struct Exactly100CharsToSemicolon - (LongLongTypename, i32, i32) - where A: LongTrait1234; - -struct AlwaysOnNextLine where A: LongTrait { - x: i32 -} - -pub trait SomeTrait - where - T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr -{ -} - -// #2020 -impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { - fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) - where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssociatedItem), - { - // ... - } -} diff --git a/rustfmt-core/tests/target/assignment.rs b/rustfmt-core/tests/target/assignment.rs deleted file mode 100644 index 4e8689ed23e..00000000000 --- a/rustfmt-core/tests/target/assignment.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Test assignment - -fn main() { - let some_var: Type; - - let mut mutable; - - let variable = - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; - - variable = - LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; - - let single_line_fit = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; - - single_line_fit = 5; - single_lit_fit >>= 10; -} - -fn break_meee() { - { - ( - block_start, - block_size, - margin_block_start, - margin_block_end, - ) = match (block_start, block_end, block_size) { - x => 1, - _ => 2, - }; - } -} - -// #2018 -pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = - "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/rustfmt-core/tests/target/associated-items.rs b/rustfmt-core/tests/target/associated-items.rs deleted file mode 100644 index 1b0a828d029..00000000000 --- a/rustfmt-core/tests/target/associated-items.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("{}", ::default()); -} diff --git a/rustfmt-core/tests/target/associated-types-bounds-wrapping.rs b/rustfmt-core/tests/target/associated-types-bounds-wrapping.rs deleted file mode 100644 index d5b94a5e869..00000000000 --- a/rustfmt-core/tests/target/associated-types-bounds-wrapping.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-max_width: 100 -// Test proper wrapping of long associated type bounds - -pub trait HttpService { - type WsService: 'static - + Service; -} diff --git a/rustfmt-core/tests/target/associated_type_defaults.rs b/rustfmt-core/tests/target/associated_type_defaults.rs deleted file mode 100644 index d0a08133725..00000000000 --- a/rustfmt-core/tests/target/associated_type_defaults.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![feature(associated_type_defaults)] -trait Foo { - type Bar = (); -} diff --git a/rustfmt-core/tests/target/attrib-extern-crate.rs b/rustfmt-core/tests/target/attrib-extern-crate.rs deleted file mode 100644 index ed64a0aeb07..00000000000 --- a/rustfmt-core/tests/target/attrib-extern-crate.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Attributes on extern crate. - -#[Attr1] -extern crate Bar; -#[Attr2] -#[Attr2] -extern crate Baz; -extern crate Foo; - -fn foo() { - #[Attr1] - extern crate Bar; - #[Attr2] - #[Attr2] - extern crate Baz; - extern crate Foo; -} diff --git a/rustfmt-core/tests/target/attrib.rs b/rustfmt-core/tests/target/attrib.rs deleted file mode 100644 index 0a3d2bc0b81..00000000000 --- a/rustfmt-core/tests/target/attrib.rs +++ /dev/null @@ -1,160 +0,0 @@ -// rustfmt-wrap_comments: true -// Test attributes and doc comments are preserved. - -//! Doc comment - -#![attribute] - -//! Crate doc comment - -// Comment - -// Comment on attribute -#![the(attribute)] - -// Another comment - -#[invalid attribute] -fn foo() {} - -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. -/// Blah blah blah. - -/// Blah blah blah. -impl Bar { - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - /// Blah blah blooo. - #[an_attribute] - fn foo(&mut self) -> isize {} - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - - /// Blah blah bing. - /// Blah blah bing. - /// Blah blah bing. - pub fn f2(self) { - (foo, bar) - } - - #[another_attribute] - fn f3(self) -> Dog {} - - /// Blah blah bing. - - #[attrib1] - /// Blah blah bing. - #[attrib2] - // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo - // loooooooooooong. - /// Blah blah bing. - fn f4(self) -> Cat {} - - // We want spaces around `=` - #[cfg(feature = "nightly")] - fn f5(self) -> Monkey {} -} - -// #984 -struct Foo { - #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] - foo: usize, -} - -// #1668 - -/// Default path (*nix) -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] -fn foo() { - #[cfg(target_os = "freertos")] - match port_id { - 'a' | 'A' => GpioPort { - port_address: GPIO_A, - }, - 'b' | 'B' => GpioPort { - port_address: GPIO_B, - }, - _ => panic!(), - } - - #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] - let x = 3; -} - -// #1777 -#[test] -#[should_panic(expected = "(")] -#[should_panic(expected = /* ( */ "(")] -#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] -#[should_panic( - /* (((((((( *//* - (((((((((()(((((((( */ - expected = "(" - // (((((((( -)] -fn foo() {} - -// #1799 -fn issue_1799() { - #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 - Some(Err(error)); - - #[allow(unreachable_code)] - // https://github.com/rust-lang/rust/issues/43336 - Some(Err(error)); -} - -// Formatting inner attributes -fn inner_attributes() { - #![this_is_an_inner_attribute(foo)] - - foo(); -} - -impl InnerAttributes() { - #![this_is_an_inner_attribute(foo)] - - fn foo() {} -} - -mod InnerAttributes { - #![this_is_an_inner_attribute(foo)] -} - -fn attributes_on_statements() { - // Local - #[attr(on(local))] - let x = 3; - - // Item - #[attr(on(item))] - use foo; - - // Expr - #[attr(on(expr))] - {} - - // Semi - #[attr(on(semi))] - foo(); - - // Mac - #[attr(on(mac))] - foo!(); -} - -// Large derive -#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, - Deserialize)] -pub struct HP(pub u8); - -// Long `#[doc = "..."]` -struct A { - #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] - b: i32, -} diff --git a/rustfmt-core/tests/target/big-impl-block.rs b/rustfmt-core/tests/target/big-impl-block.rs deleted file mode 100644 index bc16f12c9d7..00000000000 --- a/rustfmt-core/tests/target/big-impl-block.rs +++ /dev/null @@ -1,87 +0,0 @@ -// rustfmt-indent_style: Block - -// #1357 -impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> - for SelectStatement -where - DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a, -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new( - Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset), - ) - } -} - -// #1369 -impl Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} -impl Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} -impl< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, -> Foo - for Bar< - ExcessivelyLongGenericName, - ExcessivelyLongGenericName, - AnotherExcessivelyLongGenericName, - > { - fn foo() {} -} - -// #1689 -impl SubSelectDirect -where - M: select::Selector, - S: event::Stream, - F: for<'t> FnMut(transform::Api<'t, Stream>>) -> transform::Api<'t, X>, - X: event::Stream, -{ -} diff --git a/rustfmt-core/tests/target/big-impl-visual.rs b/rustfmt-core/tests/target/big-impl-visual.rs deleted file mode 100644 index 91e7cb5b983..00000000000 --- a/rustfmt-core/tests/target/big-impl-visual.rs +++ /dev/null @@ -1,73 +0,0 @@ -// rustfmt-indent_style: Visual - -// #1357 -impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> - for SelectStatement - where DB: Backend, - Select: QueryFragment + SelectableExpression + 'a, - Distinct: QueryFragment + 'a, - Where: Into + 'a>>>, - Order: QueryFragment + 'a, - Limit: QueryFragment + 'a, - Offset: QueryFragment + 'a -{ - type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; - - fn internal_into_boxed(self) -> Self::Output { - BoxedSelectStatement::new(Box::new(self.select), - self.from, - Box::new(self.distinct), - self.where_clause.into(), - Box::new(self.order), - Box::new(self.limit), - Box::new(self.offset)) - } -} - -// #1369 -impl Foo for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} -impl Foo for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} -impl Foo - for Bar -{ - fn foo() {} -} diff --git a/rustfmt-core/tests/target/break-and-continue.rs b/rustfmt-core/tests/target/break-and-continue.rs deleted file mode 100644 index c01d8a07845..00000000000 --- a/rustfmt-core/tests/target/break-and-continue.rs +++ /dev/null @@ -1,23 +0,0 @@ -// break and continue formatting - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a; - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b; - } - - let x = loop { - break 5; - }; - - let x = 'c: loop { - break 'c 5; - }; -} diff --git a/rustfmt-core/tests/target/catch.rs b/rustfmt-core/tests/target/catch.rs deleted file mode 100644 index 640f9bade49..00000000000 --- a/rustfmt-core/tests/target/catch.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(catch_expr)] - -fn main() { - let x = do catch { foo()? }; - - let x = do catch /* Invisible comment */ { foo()? }; - - let x = do catch { unsafe { foo()? } }; - - let y = match (do catch { foo()? }) { - _ => (), - }; - - do catch { - foo()?; - }; - - do catch { - // Regular do catch block - }; -} diff --git a/rustfmt-core/tests/target/chains-visual.rs b/rustfmt-core/tests/target/chains-visual.rs deleted file mode 100644 index b842d73c99f..00000000000 --- a/rustfmt-core/tests/target/chains-visual.rs +++ /dev/null @@ -1,159 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Visual -// Test chain formatting. - -fn main() { - // Don't put chains on a single line if it wasn't so in source. - let a = b.c.d.1.foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x().y(|| match cond() { - true => (), - false => (), - }); - - loong_func().quux(move || if true { 1 } else { 2 }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }) - .method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = - xxxxxxx.map(|x| x + 5) - .map(|x| x / 2) - .fold(0, |acc, x| acc + x); - - aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { field1: val1, - field2: val2, }; - - let x = Foo { field1: val1, - field2: val2, }.method_call() - .method_call(); - - let y = if cond { val1 } else { val2 }.method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }].clone()); - } - } - } - - if cond { - some(); - } else { - none(); - }.bar() - .baz(); - - Foo { x: val }.baz(|| { - force(); - multiline(); - }) - .quux(); - - Foo { y: i_am_multi_line, - z: ok, }.baz(|| { - force(); - multiline(); - }) - .quux(); - - a + match x { - true => "yay!", - false => "boo!", - }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) - .unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn issue_1389() { - let names = String::from_utf8(names)?.split('|') - .map(str::to_owned) - .collect(); -} - -fn issue1217() -> Result { - let random_chars: String = OsRng::new()?.gen_ascii_chars() - .take(self.bit_length) - .collect(); - - Ok(Mnemonic::new(&random_chars)) -} - -fn issue1236(options: Vec) -> Result> { - let process = Command::new("dmenu").stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .chain_err(|| "failed to spawn dmenu")?; -} - -fn issue1434() { - for _ in 0..100 { - let prototype_id = - PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { - format!("could not read prototype ID at offset {:#010x}", - current_offset) - })?; - } -} - -fn issue2264() { - { - something.function() - .map(|| { - if let a_very_very_very_very_very_very_very_very_long_variable = - compute_this_variable() - { - println!("Hello"); - } - }) - .collect(); - } -} diff --git a/rustfmt-core/tests/target/chains.rs b/rustfmt-core/tests/target/chains.rs deleted file mode 100644 index 8a41eec2bde..00000000000 --- a/rustfmt-core/tests/target/chains.rs +++ /dev/null @@ -1,261 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-use_small_heuristics: false -// Test chain formatting. - -fn main() { - let a = b.c.d.1.foo(|x| x + 1); - - bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); - - bbbbbbbbbbbbbbbbbbb - .ccccccccccccccccccccccccccccccccccccc - .ddddddddddddddddddddddddddd - .eeeeeeee(); - - let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo - .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; - - // Test case where first chain element isn't a path, but is shorter than - // the size of a tab. - x().y(|| match cond() { - true => (), - false => (), - }); - - loong_func().quux(move || { - if true { - 1 - } else { - 2 - } - }); - - some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - some_fuuuuuuuuunction() - .method_call_a(aaaaa, bbbbb, |c| { - let x = c; - x - }) - .method_call_b(aaaaa, bbbbb, |c| { - let x = c; - x - }); - - fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - - let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = - xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x); - - body.fold(Body::new(), |mut body, chunk| { - body.extend(chunk); - Ok(body) - }).and_then(move |body| { - let req = Request::from_parts(parts, body); - f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) - }); - - aaaaaaaaaaaaaaaa - .map(|x| { - x += 1; - x - }) - .filter(some_mod::some_filter) -} - -fn floaters() { - let z = Foo { - field1: val1, - field2: val2, - }; - - let x = Foo { - field1: val1, - field2: val2, - }.method_call() - .method_call(); - - let y = if cond { - val1 - } else { - val2 - }.method_call(); - - { - match x { - PushParam => { - // params are 1-indexed - stack.push( - mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }].clone(), - ); - } - } - } - - if cond { - some(); - } else { - none(); - }.bar() - .baz(); - - Foo { - x: val, - }.baz(|| { - force(); - multiline(); - }) - .quux(); - - Foo { - y: i_am_multi_line, - z: ok, - }.baz(|| { - force(); - multiline(); - }) - .quux(); - - a + match x { - true => "yay!", - false => "boo!", - }.bar() -} - -fn is_replaced_content() -> bool { - constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); -} - -fn issue587() { - a.b::<()>(c); - - std::mem::transmute(dl.symbol::<()>("init").unwrap()) -} - -fn try_shorthand() { - let x = expr?; - let y = expr.kaas()?.test(); - let loooooooooooooooooooooooooooooooooooooooooong = - does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; - let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); - let zzzz = expr?.another?.another?.another?.another?; - let aaa = x??????????????????????????????????????????????????????????????????????????; - - let y = a.very - .loooooooooooooooooooooooooooooooooooooong() - .chain() - .inside() - .weeeeeeeeeeeeeee()? - .test() - .0 - .x; - - parameterized(f, substs, def_id, Ns::Value, &[], |tcx| tcx.lookup_item_type(def_id).generics)?; - fooooooooooooooooooooooooooo()? - .bar()? - .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; -} - -fn issue_1004() { - match *self { - ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), - }?; - - ty::tls::with(|tcx| { - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - })?; -} - -fn issue1392() { - test_method( - r#" - if foo { - a(); - } - else { - b(); - } - "#.trim(), - ); -} - -// #2067 -impl Settings { - fn save(&self) -> Result<()> { - let mut file = File::create(&settings_path) - .chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; - } -} - -fn issue2126() { - { - { - { - { - { - let x = self.span_from( - sub_span.expect("No span found for struct arant variant"), - ); - self.sspanpan_from_span( - sub_span.expect("No span found for struct variant"), - ); - let x = self.spanpan_from_span( - sub_span.expect("No span found for struct variant"), - )?; - } - } - } - } - } -} - -// #2200 -impl Foo { - pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes { - let other_attrs = attrs - .iter() - .filter_map(|attr| { - attr.with_desugared_doc(|attr| { - if attr.check_name("doc") { - if let Some(mi) = attr.meta() { - if let Some(value) = mi.value_str() { - doc_strings.push(DocFragment::Include( - line, - attr.span, - filename, - contents, - )); - } - } - } - }) - }) - .collect(); - } -} - -// #2415 -// Avoid orphan in chain -fn issue2415() { - let base_url = (|| { - // stuff - - Ok((|| { - // stuff - Some(value.to_string()) - })().ok_or("")?) - })().unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); -} diff --git a/rustfmt-core/tests/target/closure-block-inside-macro.rs b/rustfmt-core/tests/target/closure-block-inside-macro.rs deleted file mode 100644 index c1260592083..00000000000 --- a/rustfmt-core/tests/target/closure-block-inside-macro.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Block - -// #1547 -fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { - let index = *first as usize; - if index >= ENCODINGS.len() { - return; - } - let encoding = ENCODINGS[index]; - dispatch_test(encoding, &data[1..]); -}); diff --git a/rustfmt-core/tests/target/closure.rs b/rustfmt-core/tests/target/closure.rs deleted file mode 100644 index 5bc89d58222..00000000000 --- a/rustfmt-core/tests/target/closure.rs +++ /dev/null @@ -1,248 +0,0 @@ -// rustfmt-normalize_comments: true -// Closures - -fn main() { - let square = (|i: i32| i * i); - - let commented = |// first - a, // argument - // second - b: WithType, // argument - // ignored - _| { - ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ) - }; - - let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - }; - - let loooooooooooooong_name = |field| { - // format comments. - if field.node.attrs.len() > 0 { - field.node.attrs[0].span.lo() - } else { - field.span.lo() - } - }; - - let unblock_me = |trivial| closure(); - - let empty = |arg| {}; - - let simple = |arg| { - // comment formatting - foo(arg) - }; - - let test = || { - do_something(); - do_something_else(); - }; - - let arg_test = - |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - - let arg_test = - |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); - - let simple_closure = move || -> () {}; - - let closure = |input: Ty| -> Option { foo() }; - - let closure_with_return_type = - |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; - - |arg1, arg2, _, _, arg3, arg4| { - let temp = arg4 + arg3; - arg2 * arg1 - temp - }; - - let block_body_with_comment = args.iter().map(|a| { - // Emitting only dep-info is possible only for final crate type, as - // as others may emit required metadata for dependent crate types - if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { - "--emit=dep-info" - } else { - a - } - }); -} - -fn issue311() { - let func = |x| println!("{}", x); - - (func)(0.0); -} - -fn issue863() { - let closure = |x| match x { - 0 => true, - _ => false, - } == true; -} - -fn issue934() { - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish() - }; - - let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { - let mut h = SpanlessHash::new(cx); - h.hash_block(block); - h.finish(); - }; -} - -impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { - pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { - match (&left.node, &right.node) { - (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { - l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { - l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) - }) - } - } - } -} - -fn foo() { - lifetimes_iter___map(|lasdfasfd| { - let hi = if l.bounds.is_empty() { - l.lifetime.span.hi() - }; - }); -} - -fn issue1405() { - open_raw_fd(fd, b'r').and_then(|file| { - Capture::new_raw(None, |_, err| unsafe { raw::pcap_fopen_offline(file, err) }) - }); -} - -fn issue1466() { - let vertex_buffer = frame.scope(|ctx| { - let buffer = ctx.create_host_visible_buffer::>(&vertices); - ctx.create_device_local_buffer(buffer) - }); -} - -fn issue470() { - { - { - { - let explicit_arg_decls = explicit_arguments.into_iter().enumerate().map( - |(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); - block = this.pattern( - block, - argument_extent, - hair::PatternRef::Hair(pattern), - &lvalue, - ); - ArgDecl { ty: ty } - }, - ); - } - } - } -} - -// #1509 -impl Foo { - pub fn bar(&self) { - Some(SomeType { - push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| Ok(f))), - }) - } -} - -fn issue1329() { - aaaaaaaaaaaaaaaa - .map(|x| { - x += 1; - x - }) - .filter -} - -fn issue325() { - let f = - || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; -} - -fn issue1697() { - Test.func_a( - A_VERY_LONG_CONST_VARIABLE_NAME, - move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4, - ) -} - -fn issue1694() { - foooooo( - |_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| { - format!("refs/pull/{}/merge", pr_id) - }, - ) -} - -fn issue1713() { - rayon::join( - || recurse(left, is_less, pred, limit), - || recurse(right, is_less, Some(pivot), limit), - ); - - rayon::join( - 1, - || recurse(left, is_less, pred, limit), - 2, - || recurse(right, is_less, Some(pivot), limit), - ); -} - -fn issue2063() { - |ctx: Ctx<(String, String)>| -> io::Result { - Ok(Response::new().with_body(ctx.params.0)) - } -} - -fn issue1524() { - let f = |x| x; - let f = |x| x; - let f = |x| x; - let f = |x| x; - let f = |x| x; -} - -fn issue2171() { - foo(|| unsafe { - if PERIPHERALS { - loop {} - } else { - PERIPHERALS = true; - } - }) -} - -fn issue2207() { - a.map(|_| { - unsafe { a_very_very_very_very_very_very_very_long_function_name_or_anything_else() } - .to_string() - }) -} - -fn issue2262() { - result - .init(&mut result.slave.borrow_mut(), &mut (result.strategy)()) - .map_err(|factory| Error { - factory, - slave: None, - })?; -} diff --git a/rustfmt-core/tests/target/comment-inside-const.rs b/rustfmt-core/tests/target/comment-inside-const.rs deleted file mode 100644 index f847f2c69de..00000000000 --- a/rustfmt-core/tests/target/comment-inside-const.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn issue982() { - const SOME_CONSTANT: u32 = - // Explanation why SOME_CONSTANT needs FLAG_A to be set. - FLAG_A | - // Explanation why SOME_CONSTANT needs FLAG_B to be set. - FLAG_B | - // Explanation why SOME_CONSTANT needs FLAG_C to be set. - FLAG_C; -} diff --git a/rustfmt-core/tests/target/comment-not-disappear.rs b/rustfmt-core/tests/target/comment-not-disappear.rs deleted file mode 100644 index 646b37e46e2..00000000000 --- a/rustfmt-core/tests/target/comment-not-disappear.rs +++ /dev/null @@ -1,36 +0,0 @@ -// All the comments here should not disappear. - -fn a() { - match x { - X | - // A comment - Y => {} - }; -} - -fn b() { - match x { - X => - // A comment - y - } -} - -fn c() { - a() /* ... */; -} - -fn foo() -> Vec { - (0..11) - .map(|x| - // This comment disappears. - if x % 2 == 0 { x } else { x * 2 }) - .collect() -} - -fn calc_page_len(prefix_len: usize, sofar: usize) -> usize { - 2 // page type and flags - + 1 // stored depth - + 2 // stored count - + prefix_len + sofar // sum of size of all the actual items -} diff --git a/rustfmt-core/tests/target/comment.rs b/rustfmt-core/tests/target/comment.rs deleted file mode 100644 index 5abf5369066..00000000000 --- a/rustfmt-core/tests/target/comment.rs +++ /dev/null @@ -1,95 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//! Doc comment -fn test() { - //! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam - //! lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - - // comment - // comment2 - - code(); // leave this comment alone! - // ok? - - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - // viverra nec consectetur ante hendrerit. Donec et mollis dolor. - // Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - // tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - // libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - // amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - // felis, pulvinar a semper sed, adipiscing id dolor. - - // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment - // that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); // dontchangeme - // or me - - // #1388 - const EXCEPTION_PATHS: &'static [&'static str] = &[ - // std crates - "src/libstd/sys/", // Platform-specific code for std lives here. - "src/bootstrap", - ]; -} - -/// test123 -fn doc_comment() {} - -fn chains() { - foo.bar(|| { - let x = 10; - // comment - x - }) -} - -fn issue_1086() { - // -} - -// random comment - -fn main() { - // Test -} - -// #1643 -fn some_fn() // some comment -{ -} - -fn some_fn1() -// some comment -{ -} - -fn some_fn2() // some comment -{ -} - -fn some_fn3() // some comment some comment some comment some comment some comment some comment so -{ -} - -fn some_fn4() -// some comment some comment some comment some comment some comment some comment -// some comment -{ -} - -// #1603 -pub enum Foo { - A, // `/** **/` - B, // `/*!` - C, -} diff --git a/rustfmt-core/tests/target/comment2.rs b/rustfmt-core/tests/target/comment2.rs deleted file mode 100644 index 04f84a15c95..00000000000 --- a/rustfmt-core/tests/target/comment2.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-wrap_comments: true - -/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly -/// and justly. -pub mod foo {} diff --git a/rustfmt-core/tests/target/comment3.rs b/rustfmt-core/tests/target/comment3.rs deleted file mode 100644 index 3a810590d7b..00000000000 --- a/rustfmt-core/tests/target/comment3.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-wrap_comments: true - -//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly -//! and justly. - -pub mod foo {} diff --git a/rustfmt-core/tests/target/comment4.rs b/rustfmt-core/tests/target/comment4.rs deleted file mode 100644 index e07abf74a81..00000000000 --- a/rustfmt-core/tests/target/comment4.rs +++ /dev/null @@ -1,51 +0,0 @@ -#![allow(dead_code)] // bar - -//! Doc comment -fn test() { - // comment - // comment2 - - code(); /* leave this comment alone! - * ok? */ - - /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a - * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam - * viverra nec consectetur ante hendrerit. Donec et mollis dolor. - * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam - * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut - * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit - * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis - * felis, pulvinar a semper sed, adipiscing id dolor. */ - - // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split - - // println!("{:?}", rewrite_comment(subslice, - // false, - // comment_width, - // self.block_indent, - // self.config) - // .unwrap()); - - funk(); //dontchangeme - // or me -} - -/// test123 -fn doc_comment() {} - -/* -Regression test for issue #956 - -(some very important text) -*/ - -/* -fn debug_function() { - println!("hello"); -} -// */ - -#[link_section=".vectors"] -#[no_mangle] // Test this attribute is preserved. -#[cfg_attr(rustfmt, rustfmt_skip)] -pub static ISSUE_1284: [i32; 16] = []; diff --git a/rustfmt-core/tests/target/comment5.rs b/rustfmt-core/tests/target/comment5.rs deleted file mode 100644 index c52f9b38977..00000000000 --- a/rustfmt-core/tests/target/comment5.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -//@ special comment -//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam -//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@ -//@ foo -fn test() {} - -//@@@ another special comment -//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam -//@@@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam -//@@@ -//@@@ foo -fn bar() {} diff --git a/rustfmt-core/tests/target/comment_crlf_newline.rs b/rustfmt-core/tests/target/comment_crlf_newline.rs deleted file mode 100644 index aab9e94d9e6..00000000000 --- a/rustfmt-core/tests/target/comment_crlf_newline.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true -// Block comments followed by CRLF newlines should not an extra newline at the end - -// Something else diff --git a/rustfmt-core/tests/target/comments-fn.rs b/rustfmt-core/tests/target/comments-fn.rs deleted file mode 100644 index 39af3fd064e..00000000000 --- a/rustfmt-core/tests/target/comments-fn.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Test comments on functions are preserved. - -// Comment on foo. -fn foo( - a: aaaaaaaaaaaaa, // A comment - b: bbbbbbbbbbbbb, // a second comment - c: ccccccccccccc, - // Newline comment - d: ddddddddddddd, - // A multi line comment - // between args. - e: eeeeeeeeeeeee, /* comment before paren */ -) -> bar -where - F: Foo, // COmment after where clause - G: Goo, // final comment -{ - -} - -fn bar() {} - -fn baz() -> Baz /* Comment after return type */ {} - -fn some_fn() -where - T: Eq, // some comment -{ -} - -fn issue458(a: &str, f: F) -// comment1 -where - // comment2 - F: FnOnce(&str) -> bool, -{ - f(a); - () -} diff --git a/rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs b/rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs deleted file mode 100644 index 9706699dc7a..00000000000 --- a/rustfmt-core/tests/target/configs/blank_lines_lower_bound/1.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-blank_lines_lower_bound: 1 - -fn foo() {} - -fn bar() {} - -// comment -fn foobar() {} - -fn foo1() {} - -fn bar1() {} - -// comment - -fn foobar1() {} diff --git a/rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs b/rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs deleted file mode 100644 index 2755a264689..00000000000 --- a/rustfmt-core/tests/target/configs/brace_style/fn_always_next_line.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Function brace style - -fn lorem() -{ - // body -} - -fn lorem(ipsum: usize) -{ - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, -{ - // body -} diff --git a/rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs b/rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs deleted file mode 100644 index 23f98b6dd7a..00000000000 --- a/rustfmt-core/tests/target/configs/brace_style/fn_prefer_same_line.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, { - // body -} diff --git a/rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs b/rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs deleted file mode 100644 index 2afe59943a3..00000000000 --- a/rustfmt-core/tests/target/configs/brace_style/fn_same_line_where.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Function brace style - -fn lorem() { - // body -} - -fn lorem(ipsum: usize) { - // body -} - -fn lorem(ipsum: T) -where - T: Add + Sub + Mul + Div, -{ - // body -} diff --git a/rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs b/rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs deleted file mode 100644 index 38ed449d178..00000000000 --- a/rustfmt-core/tests/target/configs/brace_style/item_always_next_line.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -// Item brace style - -enum Foo {} - -struct Bar {} - -struct Lorem -{ - ipsum: bool, -} - -struct Dolor -where - T: Eq, -{ - sit: T, -} - -#[cfg(test)] -mod tests -{ - #[test] - fn it_works() - { - } -} diff --git a/rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs b/rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs deleted file mode 100644 index 5143d7517c7..00000000000 --- a/rustfmt-core/tests/target/configs/brace_style/item_prefer_same_line.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-brace_style: PreferSameLine -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor -where - T: Eq, { - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs b/rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs deleted file mode 100644 index 8a3b2852654..00000000000 --- a/rustfmt-core/tests/target/configs/brace_style/item_same_line_where.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-brace_style: SameLineWhere -// Item brace style - -struct Lorem { - ipsum: bool, -} - -struct Dolor -where - T: Eq, -{ - sit: T, -} - -#[cfg(test)] -mod tests { - #[test] - fn it_works() {} -} diff --git a/rustfmt-core/tests/target/configs/combine_control_expr/false.rs b/rustfmt-core/tests/target/configs/combine_control_expr/false.rs deleted file mode 100644 index 81eff08660d..00000000000 --- a/rustfmt-core/tests/target/configs/combine_control_expr/false.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-combine_control_expr: false -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. - -fn main() { - // Call - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Mac - foo(foo!( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // MethodCall - foo(x.foo::( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Block - foo!({ - foo(); - bar(); - }); - - // Closure - foo(|x| { - let y = x + 1; - y - }); - - // Match - foo(match opt { - Some(x) => x, - None => y, - }); - - // Struct - foo(Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // If - foo!( - if x { - foo(); - } else { - bar(); - } - ); - - // IfLet - foo!( - if let Some(..) = x { - foo(); - } else { - bar(); - } - ); - - // While - foo!( - while x { - foo(); - bar(); - } - ); - - // WhileLet - foo!( - while let Some(..) = x { - foo(); - bar(); - } - ); - - // ForLoop - foo!( - for x in y { - foo(); - bar(); - } - ); - - // Loop - foo!( - loop { - foo(); - bar(); - } - ); - - // Tuple - foo(( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // AddrOf - foo(&bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // Unary - foo(!bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Try - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )?); - - // Cast - foo(Bar { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - } as i64); -} diff --git a/rustfmt-core/tests/target/configs/combine_control_expr/true.rs b/rustfmt-core/tests/target/configs/combine_control_expr/true.rs deleted file mode 100644 index c5372c2ff37..00000000000 --- a/rustfmt-core/tests/target/configs/combine_control_expr/true.rs +++ /dev/null @@ -1,121 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-combine_control_expr: true -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. - -fn main() { - // Call - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Mac - foo(foo!( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // MethodCall - foo(x.foo::( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Block - foo!({ - foo(); - bar(); - }); - - // Closure - foo(|x| { - let y = x + 1; - y - }); - - // Match - foo(match opt { - Some(x) => x, - None => y, - }); - - // Struct - foo(Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // If - foo!(if x { - foo(); - } else { - bar(); - }); - - // IfLet - foo!(if let Some(..) = x { - foo(); - } else { - bar(); - }); - - // While - foo!(while x { - foo(); - bar(); - }); - - // WhileLet - foo!(while let Some(..) = x { - foo(); - bar(); - }); - - // ForLoop - foo!(for x in y { - foo(); - bar(); - }); - - // Loop - foo!(loop { - foo(); - bar(); - }); - - // Tuple - foo(( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // AddrOf - foo(&bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Box - foo(box Bar { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - }); - - // Unary - foo(!bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )); - - // Try - foo(bar( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - )?); - - // Cast - foo(Bar { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - } as i64); -} diff --git a/rustfmt-core/tests/target/configs/comment_width/above.rs b/rustfmt-core/tests/target/configs/comment_width/above.rs deleted file mode 100644 index ddfecda65c1..00000000000 --- a/rustfmt-core/tests/target/configs/comment_width/above.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, - // consectetur adipiscing elit. -} diff --git a/rustfmt-core/tests/target/configs/comment_width/below.rs b/rustfmt-core/tests/target/configs/comment_width/below.rs deleted file mode 100644 index abbc5930c4c..00000000000 --- a/rustfmt-core/tests/target/configs/comment_width/below.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 80 -// rustfmt-wrap_comments: true -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/rustfmt-core/tests/target/configs/comment_width/ignore.rs b/rustfmt-core/tests/target/configs/comment_width/ignore.rs deleted file mode 100644 index c86e71c2898..00000000000 --- a/rustfmt-core/tests/target/configs/comment_width/ignore.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-comment_width: 40 -// rustfmt-wrap_comments: false -// Comment width - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. -} diff --git a/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs b/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs deleted file mode 100644 index 3b967f35a8e..00000000000 --- a/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: false -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, _, _) = (1, 2, 3, 4); -} diff --git a/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs b/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs deleted file mode 100644 index 4f880abe80e..00000000000 --- a/rustfmt-core/tests/target/configs/condense_wildcard_suffixes/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-condense_wildcard_suffixes: true -// Condense wildcard suffixes - -fn main() { - let (lorem, ipsum, ..) = (1, 2, 3, 4); -} diff --git a/rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs b/rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs deleted file mode 100644 index 7dc06f207fe..00000000000 --- a/rustfmt-core/tests/target/configs/control_brace_style/always_next_line.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine -// Control brace style - -fn main() { - if lorem - { - println!("ipsum!"); - } - else - { - println!("dolor!"); - } - match magi - { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs b/rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs deleted file mode 100644 index 993b6b681fe..00000000000 --- a/rustfmt-core/tests/target/configs/control_brace_style/always_same_line.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine -// Control brace style - -fn main() { - if lorem { - println!("ipsum!"); - } else { - println!("dolor!"); - } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs b/rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs deleted file mode 100644 index 013852ee79a..00000000000 --- a/rustfmt-core/tests/target/configs/control_brace_style/closing_next_line.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine -// Control brace style - -fn main() { - if lorem { - println!("ipsum!"); - } - else { - println!("dolor!"); - } - match magi { - Homura => "Akemi", - Madoka => "Kaname", - } -} diff --git a/rustfmt-core/tests/target/configs/disable_all_formatting/false.rs b/rustfmt-core/tests/target/configs/disable_all_formatting/false.rs deleted file mode 100644 index 1a0477ddb39..00000000000 --- a/rustfmt-core/tests/target/configs/disable_all_formatting/false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-disable_all_formatting: false -// Disable all formatting - -fn main() { - if lorem { - println!("ipsum!"); - } else { - println!("dolor!"); - } -} diff --git a/rustfmt-core/tests/target/configs/disable_all_formatting/true.rs b/rustfmt-core/tests/target/configs/disable_all_formatting/true.rs deleted file mode 100644 index 736ccf56942..00000000000 --- a/rustfmt-core/tests/target/configs/disable_all_formatting/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-disable_all_formatting: true -// Disable all formatting - -fn main() { - if lorem{println!("ipsum!");}else{println!("dolor!");} -} diff --git a/rustfmt-core/tests/target/configs/empty_item_single_line/false.rs b/rustfmt-core/tests/target/configs/empty_item_single_line/false.rs deleted file mode 100644 index b7886df2aa8..00000000000 --- a/rustfmt-core/tests/target/configs/empty_item_single_line/false.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-empty_item_single_line: false -// Empty impl on single line - -impl Lorem { -} - -impl Ipsum { -} - -fn lorem() { -} - -fn lorem() { - -} diff --git a/rustfmt-core/tests/target/configs/empty_item_single_line/true.rs b/rustfmt-core/tests/target/configs/empty_item_single_line/true.rs deleted file mode 100644 index 0755485fea9..00000000000 --- a/rustfmt-core/tests/target/configs/empty_item_single_line/true.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-empty_item_single_line: true -// Empty impl on single line - -impl Lorem {} - -impl Ipsum {} - -fn lorem() {} - -fn lorem() {} diff --git a/rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs b/rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs deleted file mode 100644 index fa70ae78352..00000000000 --- a/rustfmt-core/tests/target/configs/error_on_line_overflow/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// Error on line overflow - -fn main() { - let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; -} diff --git a/rustfmt-core/tests/target/configs/error_on_unformatted/false.rs b/rustfmt-core/tests/target/configs/error_on_unformatted/false.rs deleted file mode 100644 index 6a78374e2a2..00000000000 --- a/rustfmt-core/tests/target/configs/error_on_unformatted/false.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-error_on_unformatted: false -// Error on line overflow comment or string literals. - -// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -fn main() { - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - - let x = " "; - let a = " - -"; -} diff --git a/rustfmt-core/tests/target/configs/fn_args_density/compressed.rs b/rustfmt-core/tests/target/configs/fn_args_density/compressed.rs deleted file mode 100644 index 99283722bee..00000000000 --- a/rustfmt-core/tests/target/configs/fn_args_density/compressed.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit, - ) { - // body - } -} diff --git a/rustfmt-core/tests/target/configs/fn_args_density/tall.rs b/rustfmt-core/tests/target/configs/fn_args_density/tall.rs deleted file mode 100644 index 6ee43b41a19..00000000000 --- a/rustfmt-core/tests/target/configs/fn_args_density/tall.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-fn_args_density: Tall -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} diff --git a/rustfmt-core/tests/target/configs/fn_args_density/vertical.rs b/rustfmt-core/tests/target/configs/fn_args_density/vertical.rs deleted file mode 100644 index d48b3492452..00000000000 --- a/rustfmt-core/tests/target/configs/fn_args_density/vertical.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-fn_args_density: Vertical -// Function arguments density - -trait Lorem { - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - ) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} diff --git a/rustfmt-core/tests/target/configs/fn_single_line/false.rs b/rustfmt-core/tests/target/configs/fn_single_line/false.rs deleted file mode 100644 index 3d092f0c0bf..00000000000 --- a/rustfmt-core/tests/target/configs/fn_single_line/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-fn_single_line: false -// Single-expression function on single line - -fn lorem() -> usize { - 42 -} - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/rustfmt-core/tests/target/configs/fn_single_line/true.rs b/rustfmt-core/tests/target/configs/fn_single_line/true.rs deleted file mode 100644 index 10d94e02f16..00000000000 --- a/rustfmt-core/tests/target/configs/fn_single_line/true.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-fn_single_line: true -// Single-expression function on single line - -fn lorem() -> usize { 42 } - -fn lorem() -> usize { - let ipsum = 42; - ipsum -} diff --git a/rustfmt-core/tests/target/configs/force_explicit_abi/false.rs b/rustfmt-core/tests/target/configs/force_explicit_abi/false.rs deleted file mode 100644 index 3c48f8e0c78..00000000000 --- a/rustfmt-core/tests/target/configs/force_explicit_abi/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: false -// Force explicit abi - -extern { - pub static lorem: c_int; -} diff --git a/rustfmt-core/tests/target/configs/force_explicit_abi/true.rs b/rustfmt-core/tests/target/configs/force_explicit_abi/true.rs deleted file mode 100644 index 90f5a8c4ecb..00000000000 --- a/rustfmt-core/tests/target/configs/force_explicit_abi/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-force_explicit_abi: true -// Force explicit abi - -extern "C" { - pub static lorem: c_int; -} diff --git a/rustfmt-core/tests/target/configs/force_multiline_block/false.rs b/rustfmt-core/tests/target/configs/force_multiline_block/false.rs deleted file mode 100644 index 7cb4cac1d69..00000000000 --- a/rustfmt-core/tests/target/configs/force_multiline_block/false.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-force_multiline_blocks: false -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - }); -} diff --git a/rustfmt-core/tests/target/configs/force_multiline_block/true.rs b/rustfmt-core/tests/target/configs/force_multiline_block/true.rs deleted file mode 100644 index aec50afe5a8..00000000000 --- a/rustfmt-core/tests/target/configs/force_multiline_block/true.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-force_multiline_blocks: true -// Option forces multiline match arm and closure bodies to be wrapped in a block - -fn main() { - match lorem { - Lorem::Ipsum => { - if ipsum { - println!("dolor"); - } - } - Lorem::Dolor => println!("amet"), - } -} - -fn main() { - result.and_then(|maybe_value| { - match maybe_value { - None => Err("oops"), - Some(value) => Ok(1), - } - }); -} diff --git a/rustfmt-core/tests/target/configs/format_strings/false.rs b/rustfmt-core/tests/target/configs/format_strings/false.rs deleted file mode 100644 index ecca0d7d1fc..00000000000 --- a/rustfmt-core/tests/target/configs/format_strings/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-format_strings: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; -} diff --git a/rustfmt-core/tests/target/configs/format_strings/true.rs b/rustfmt-core/tests/target/configs/format_strings/true.rs deleted file mode 100644 index fdd5ab2c97d..00000000000 --- a/rustfmt-core/tests/target/configs/format_strings/true.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 50 -// Force format strings - -fn main() { - let lorem = "ipsum dolor sit amet \ - consectetur adipiscing elit \ - lorem ipsum dolor sit"; -} diff --git a/rustfmt-core/tests/target/configs/hard_tabs/false.rs b/rustfmt-core/tests/target/configs/hard_tabs/false.rs deleted file mode 100644 index ccfb53d8c86..00000000000 --- a/rustfmt-core/tests/target/configs/hard_tabs/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: false -// Hard tabs - -fn lorem() -> usize { - 42 // spaces before 42 -} diff --git a/rustfmt-core/tests/target/configs/hard_tabs/true.rs b/rustfmt-core/tests/target/configs/hard_tabs/true.rs deleted file mode 100644 index 3ed4e4f20aa..00000000000 --- a/rustfmt-core/tests/target/configs/hard_tabs/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-hard_tabs: true -// Hard tabs - -fn lorem() -> usize { - 42 // spaces before 42 -} diff --git a/rustfmt-core/tests/target/configs/imports_indent/block.rs b/rustfmt-core/tests/target/configs/imports_indent/block.rs deleted file mode 100644 index 84c3b26bd6e..00000000000 --- a/rustfmt-core/tests/target/configs/imports_indent/block.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-imports_indent: Block - -use lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, - SeparatorTactic, -}; diff --git a/rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs b/rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs deleted file mode 100644 index 4a63556d45b..00000000000 --- a/rustfmt-core/tests/target/configs/imports_layout/horizontal_vertical.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-imports_indent: Block -// rustfmt-imports_layout: HorizontalVertical - -use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; -use lists::{ - definitive_tactic, - itemize_list, - shape_for_tactic, - struct_lit_formatting, - struct_lit_shape, - struct_lit_tactic, - write_list, - DefinitiveListTactic, - ListFormatting, - ListItem, - ListTactic, - SeparatorTactic, -}; diff --git a/rustfmt-core/tests/target/configs/imports_layout/mixed.rs b/rustfmt-core/tests/target/configs/imports_layout/mixed.rs deleted file mode 100644 index 5d3349a01bb..00000000000 --- a/rustfmt-core/tests/target/configs/imports_layout/mixed.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-imports_indent: Block -// rustfmt-imports_layout: Mixed - -use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; -use lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, - SeparatorTactic, -}; diff --git a/rustfmt-core/tests/target/configs/indent_style/block_args.rs b/rustfmt-core/tests/target/configs/indent_style/block_args.rs deleted file mode 100644 index 80f4e133356..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_args.rs +++ /dev/null @@ -1,47 +0,0 @@ -// rustfmt-indent_style: Block -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem( - ipsum: usize, - dolor: usize, - sit: usize, - amet: usize, - consectetur: usize, - adipiscing: usize, - elit: usize, -) { - // body -} - -// #1441 -extern "system" { - pub fn GetConsoleHistoryInfo( - console_history_info: *mut ConsoleHistoryInfo, - ) -> Boooooooooooooool; -} - -// rustfmt should not add trailing comma for variadic function. See #1623. -extern "C" { - pub fn variadic_fn( - first_parameter: FirstParameterType, - second_parameter: SecondParameterType, - ... - ); -} - -// #1652 -fn deconstruct( - foo: Bar, -) -> ( - SocketAddr, - Header, - Method, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -) { -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_array.rs b/rustfmt-core/tests/target/configs/indent_style/block_array.rs deleted file mode 100644 index 5d458248c0b..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_array.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-indent_style: Block -// Array layout - -fn main() { - let lorem = vec![ - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ]; -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_call.rs b/rustfmt-core/tests/target/configs/indent_style/block_call.rs deleted file mode 100644 index 4e4c9465fe8..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_call.rs +++ /dev/null @@ -1,149 +0,0 @@ -// rustfmt-indent_style: Block -// Function call style - -fn main() { - lorem( - "lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ); - // #1501 - let hyper = Arc::new(Client::with_connector( - HttpsConnector::new(TlsClient::new()), - )); - - // chain - let x = yooooooooooooo - .fooooooooooooooo - .baaaaaaaaaaaaar(hello, world); - - // #1380 - { - { - let creds = self.client - .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; - } - } - - // nesting macro and function call - try!(foo( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - )); - try!(foo(try!( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - ))); -} - -// #1521 -impl Foo { - fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { - unsafe { - Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords( - self.render_texture, - point.raw(), - view.raw(), - )) - } - } -} - -fn issue1420() { - given( - r#" - # Getting started - ... - "#, - ).running(waltz) -} - -// #1563 -fn query(conn: &Connection) -> Result<()> { - conn.query_row( - r#" - SELECT title, date - FROM posts, - WHERE DATE(date) = $1 - "#, - &[], - |row| Post { - title: row.get(0), - date: row.get(1), - }, - )?; - - Ok(()) -} - -// #1449 -fn future_rayon_wait_1_thread() { - // run with only 1 worker thread; this would deadlock if we couldn't make progress - let mut result = None; - ThreadPool::new(Configuration::new().num_threads(1)) - .unwrap() - .install(|| { - scope(|s| { - use std::sync::mpsc::channel; - let (tx, rx) = channel(); - let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); - // ^^^^ FIXME: why is this needed? - let b = s.spawn_future(a.map(|v| v + 1)); - let c = s.spawn_future(b.map(|v| v + 1)); - s.spawn(move |_| tx.send(20).unwrap()); - result = Some(c.rayon_wait().unwrap()); - }); - }); - assert_eq!(result, Some(22)); -} - -// #1494 -impl Cursor { - fn foo() { - self.cur_type() - .num_template_args() - .or_else(|| { - let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; - - if n >= 0 { - Some(n as u32) - } else { - debug_assert_eq!(n, -1); - None - } - }) - .or_else(|| { - let canonical = self.canonical(); - if canonical != *self { - canonical.num_template_args() - } else { - None - } - }); - } -} - -fn issue1581() { - bootstrap.checks.register("PERSISTED_LOCATIONS", move || { - if locations2.0.inner_mut.lock().poisoned { - Check::new( - State::Error, - "Persisted location storage is poisoned due to a write failure", - ) - } else { - Check::new(State::Healthy, "Persisted location storage is healthy") - } - }); -} - -fn issue1651() { - { - let type_list: Vec<_> = - try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); - } -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_chain.rs b/rustfmt-core/tests/target/configs/indent_style/block_chain.rs deleted file mode 100644 index 23340a4aba2..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_chain.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Block -// Chain indent - -fn main() { - let lorem = ipsum - .dolor() - .sit() - .amet() - .consectetur() - .adipiscing() - .elite(); -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_generic.rs b/rustfmt-core/tests/target/configs/indent_style/block_generic.rs deleted file mode 100644 index c4fcaaf65d1..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_generic.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-indent_style: Block -// Generics indent - -fn lorem< - Ipsum: Eq = usize, - Dolor: Eq = usize, - Sit: Eq = usize, - Amet: Eq = usize, - Adipiscing: Eq = usize, - Consectetur: Eq = usize, - Elit: Eq = usize, ->( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - adipiscing: Adipiscing, - consectetur: Consectetur, - elit: Elit, -) -> T { - // body -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs b/rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs deleted file mode 100644 index 656b562266f..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_struct_lit.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style: Block -// Struct literal-style - -fn main() { - let lorem = Lorem { - ipsum: dolor, - sit: amet, - }; -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs b/rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs deleted file mode 100644 index 5531e61ddc8..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_tab_spaces_call.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-max_width: 80 -// rustfmt-tab_spaces: 2 - -// #1427 -fn main() { - exceptaions::config(move || { - ( - NmiConfig {}, - HardFaultConfig {}, - SysTickConfig { gpio_sbsrr }, - ) - }); -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs b/rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs deleted file mode 100644 index a7e8590ed97..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_trailing_comma_call.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Block - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo( - a, - oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), - ); -} diff --git a/rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs b/rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs deleted file mode 100644 index ad7e0b8f363..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/block_where_pred.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Block -// Where predicate indent - -fn lorem() -> T -where - Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq, -{ - // body -} diff --git a/rustfmt-core/tests/target/configs/indent_style/default.rs b/rustfmt-core/tests/target/configs/indent_style/default.rs deleted file mode 100644 index a8f0902b34e..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/default.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Visual -// Where style - -fn lorem() -> T - where Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq -{ - // body -} diff --git a/rustfmt-core/tests/target/configs/indent_style/rfc_control.rs b/rustfmt-core/tests/target/configs/indent_style/rfc_control.rs deleted file mode 100644 index 6619d8b2630..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/rfc_control.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-indent_style: Block - -// #1618 -fn main() { - loop { - if foo { - if ((right_paddle_speed < 0.) && (right_paddle.position().y - paddle_size.y / 2. > 5.)) - || ((right_paddle_speed > 0.) - && (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) - { - foo - } - if ai_timer.elapsed_time().as_microseconds() > ai_time.as_microseconds() { - if ball.position().y + ball_radius > right_paddle.position().y + paddle_size.y / 2. - { - foo - } - } - } - } -} - -fn issue1656() { - { - { - match rewrite { - Some(ref body_str) - if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) - || !context.config.match_arm_blocks() - || (extend && first_line_width(body_str) <= arm_shape.width) - || is_block => - { - return None; - } - _ => {} - } - } - } -} diff --git a/rustfmt-core/tests/target/configs/indent_style/rfc_where.rs b/rustfmt-core/tests/target/configs/indent_style/rfc_where.rs deleted file mode 100644 index a7b9a4f02b3..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/rfc_where.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Block -// Where style - -fn lorem() -> T -where - Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq, -{ - // body -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_args.rs b/rustfmt-core/tests/target/configs/indent_style/visual_args.rs deleted file mode 100644 index 04c2eaee3cf..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_args.rs +++ /dev/null @@ -1,40 +0,0 @@ -// rustfmt-indent_style: Visual -// Function arguments layout - -fn lorem() {} - -fn lorem(ipsum: usize) {} - -fn lorem(ipsum: usize, - dolor: usize, - sit: usize, - amet: usize, - consectetur: usize, - adipiscing: usize, - elit: usize) { - // body -} - -// #1922 -extern "C" { - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - a: *const lapack_complex_float, - lda: lapack_int, - ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int) - -> lapack_int; - - pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, - uplo: c_char, - n: lapack_int, - nrhs: lapack_int, - lda: lapack_int, - ipiv: *const lapack_int, - b: *mut lapack_complex_float, - ldb: lapack_int) - -> lapack_int; -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_array.rs b/rustfmt-core/tests/target/configs/indent_style/visual_array.rs deleted file mode 100644 index 1da6ff23738..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_array.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-indent_style: Visual -// Array layout - -fn main() { - let lorem = vec!["ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit"]; -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_call.rs b/rustfmt-core/tests/target/configs/indent_style/visual_call.rs deleted file mode 100644 index 5454c44ef96..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_call.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-indent_style: Visual -// Function call style - -fn main() { - lorem("lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit"); -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_chain.rs b/rustfmt-core/tests/target/configs/indent_style/visual_chain.rs deleted file mode 100644 index 569f3d8b81d..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_chain.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Visual -// Chain indent - -fn main() { - let lorem = ipsum.dolor() - .sit() - .amet() - .consectetur() - .adipiscing() - .elite(); -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_generics.rs b/rustfmt-core/tests/target/configs/indent_style/visual_generics.rs deleted file mode 100644 index 491075a146d..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_generics.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-indent_style: Visual -// Generics indent - -fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - adipiscing: Adipiscing, - consectetur: Consectetur, - elit: Elit) - -> T { - // body -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs b/rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs deleted file mode 100644 index b4effba0e8a..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_struct_lit.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-indent_style: Visual -// Struct literal-style - -fn main() { - let lorem = Lorem { ipsum: dolor, - sit: amet, }; -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs b/rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs deleted file mode 100644 index 9738d397dbf..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_trailing_comma.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); -} diff --git a/rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs b/rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs deleted file mode 100644 index 45799dcd5fc..00000000000 --- a/rustfmt-core/tests/target/configs/indent_style/visual_where_pred.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-indent_style: Visual -// Where predicate indent - -fn lorem() -> T - where Ipsum: Eq, - Dolor: Eq, - Sit: Eq, - Amet: Eq -{ - // body -} diff --git a/rustfmt-core/tests/target/configs/match_arm_blocks/false.rs b/rustfmt-core/tests/target/configs/match_arm_blocks/false.rs deleted file mode 100644 index 4d53a96a7b7..00000000000 --- a/rustfmt-core/tests/target/configs/match_arm_blocks/false.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Wrap match-arms - -fn main() { - match lorem { - true => - foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => println!("{}", sit), - } -} diff --git a/rustfmt-core/tests/target/configs/match_arm_blocks/true.rs b/rustfmt-core/tests/target/configs/match_arm_blocks/true.rs deleted file mode 100644 index d75ef03397a..00000000000 --- a/rustfmt-core/tests/target/configs/match_arm_blocks/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_arm_blocks: true -// Wrap match-arms - -fn main() { - match lorem { - true => { - foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) - } - false => println!("{}", sit), - } -} diff --git a/rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs b/rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs deleted file mode 100644 index 70e02955fb0..00000000000 --- a/rustfmt-core/tests/target/configs/match_block_trailing_comma/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: false -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - } - Lorem::Dolor => println!("dolor"), - } -} diff --git a/rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs b/rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs deleted file mode 100644 index b78b046dc1c..00000000000 --- a/rustfmt-core/tests/target/configs/match_block_trailing_comma/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match block trailing comma - -fn main() { - match lorem { - Lorem::Ipsum => { - println!("ipsum"); - }, - Lorem::Dolor => println!("dolor"), - } -} diff --git a/rustfmt-core/tests/target/configs/merge_derives/true.rs b/rustfmt-core/tests/target/configs/merge_derives/true.rs deleted file mode 100644 index 4d0148b1c6e..00000000000 --- a/rustfmt-core/tests/target/configs/merge_derives/true.rs +++ /dev/null @@ -1,40 +0,0 @@ -// rustfmt-merge_derives: true -// Merge multiple derives to a single one. - -#[bar] -#[derive(Eq, PartialEq)] -#[foo] -#[derive(Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Foo {} - -#[derive(Eq, PartialEq, Debug)] -#[foobar] -#[derive(Copy, Clone)] -pub enum Bar {} - -#[derive(Eq, PartialEq, Debug, Copy, Clone)] -pub enum FooBar {} - -mod foo { - #[bar] - #[derive(Eq, PartialEq)] - #[foo] - #[derive(Debug)] - #[foobar] - #[derive(Copy, Clone)] - pub enum Foo {} -} - -mod bar { - #[derive(Eq, PartialEq, Debug)] - #[foobar] - #[derive(Copy, Clone)] - pub enum Bar {} -} - -mod foobar { - #[derive(Eq, PartialEq, Debug, Copy, Clone)] - pub enum FooBar {} -} diff --git a/rustfmt-core/tests/target/configs/normalize_comments/false.rs b/rustfmt-core/tests/target/configs/normalize_comments/false.rs deleted file mode 100644 index 488962ed936..00000000000 --- a/rustfmt-core/tests/target/configs/normalize_comments/false.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: false -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -/* sit amet: */ -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/target/configs/normalize_comments/true.rs b/rustfmt-core/tests/target/configs/normalize_comments/true.rs deleted file mode 100644 index 0bdbe08ab4f..00000000000 --- a/rustfmt-core/tests/target/configs/normalize_comments/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-normalize_comments: true -// Normalize comments - -// Lorem ipsum: -fn dolor() -> usize {} - -// sit amet: -fn adipiscing() -> usize {} - -// #652 -//////////////////////////////////////////////////////////////////////////////// -// Basic slice extension methods -//////////////////////////////////////////////////////////////////////////////// diff --git a/rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs b/rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs deleted file mode 100644 index 6bef132e5c3..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_extern_crates/false.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: false - -extern crate foo; -extern crate bar; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs b/rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs deleted file mode 100644 index 86aba38b5d1..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_extern_crates/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_extern_crates: true - -extern crate bar; -extern crate foo; -extern crate foobar; - -#[macro_use] -extern crate nom; -extern crate regex; -#[macro_use] -extern crate log; diff --git a/rustfmt-core/tests/target/configs/reorder_imported_names/false.rs b/rustfmt-core/tests/target/configs/reorder_imported_names/false.rs deleted file mode 100644 index 91db89ceeaa..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_imported_names/false.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: false -// Reorder imported names - -use super::{lorem, ipsum, dolor, sit}; diff --git a/rustfmt-core/tests/target/configs/reorder_imported_names/true.rs b/rustfmt-core/tests/target/configs/reorder_imported_names/true.rs deleted file mode 100644 index 59f55f4718a..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_imported_names/true.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-reorder_imported_names: true -// Reorder imported names - -use super::{dolor, ipsum, lorem, sit}; diff --git a/rustfmt-core/tests/target/configs/reorder_imports/false.rs b/rustfmt-core/tests/target/configs/reorder_imports/false.rs deleted file mode 100644 index 4b85684dc01..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_imports/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_imports: false -// Reorder imports - -use lorem; -use ipsum; -use dolor; -use sit; diff --git a/rustfmt-core/tests/target/configs/reorder_imports/true.rs b/rustfmt-core/tests/target/configs/reorder_imports/true.rs deleted file mode 100644 index e4ff7295fd0..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_imports/true.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-reorder_imports: true -// Reorder imports - -use dolor; -use ipsum; -use lorem; -use sit; - -fn foo() { - use A; - use B; - use C; - - bar(); - - use D; - use E; - use F; -} diff --git a/rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs b/rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs deleted file mode 100644 index 29460da50aa..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_imports_in_group/false.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: false -// Reorder imports in group - -use dolor; -/// This comment should stay with `use ipsum;` -use ipsum; -use lorem; -use sit; -use std::io; -/// This comment should stay with `use std::mem;` -use std::mem; diff --git a/rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs b/rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs deleted file mode 100644 index c5e353662b5..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_imports_in_group/true.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imports_in_group: true -// Reorder imports in group - -use std::io; -/// This comment should stay with `use std::mem;` -use std::mem; - -use dolor; -/// This comment should stay with `use ipsum;` -use ipsum; -use lorem; -use sit; diff --git a/rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_modules/dolor/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/target/configs/reorder_modules/false.rs b/rustfmt-core/tests/target/configs/reorder_modules/false.rs deleted file mode 100644 index 56b1aa03ed7..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_modules/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: false -// Reorder modules - -mod lorem; -mod ipsum; -mod dolor; -mod sit; diff --git a/rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_modules/ipsum/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_modules/lorem/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs b/rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_modules/sit/mod.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/target/configs/reorder_modules/true.rs b/rustfmt-core/tests/target/configs/reorder_modules/true.rs deleted file mode 100644 index 18361e88b5f..00000000000 --- a/rustfmt-core/tests/target/configs/reorder_modules/true.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-reorder_modules: true -// Reorder modules - -mod dolor; -mod ipsum; -mod lorem; -mod sit; diff --git a/rustfmt-core/tests/target/configs/skip_children/true.rs b/rustfmt-core/tests/target/configs/skip_children/true.rs deleted file mode 100644 index 3ea9f46fdf2..00000000000 --- a/rustfmt-core/tests/target/configs/skip_children/true.rs +++ /dev/null @@ -1,3 +0,0 @@ -// rustfmt-skip_children: true - -mod foo; diff --git a/rustfmt-core/tests/target/configs/space_before_colon/true.rs b/rustfmt-core/tests/target/configs/space_before_colon/true.rs deleted file mode 100644 index e2895b5d77b..00000000000 --- a/rustfmt-core/tests/target/configs/space_before_colon/true.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-space_before_colon: true -// Space before colon - -fn lorem(t : T) { - let ipsum : Dolor = sit; -} - -const LOREM : Lorem = Lorem { - ipsum : dolor, - sit : amet, -}; diff --git a/rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs b/rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs deleted file mode 100644 index 6319da98572..00000000000 --- a/rustfmt-core/tests/target/configs/spaces_around_ranges/false.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: false -// Spaces around ranges - -fn main() { - let lorem = 0..10; - let ipsum = 0..=10; - - match lorem { - 1..5 => foo(), - _ => bar, - } - - match lorem { - 1..=5 => foo(), - _ => bar, - } - - match lorem { - 1...5 => foo(), - _ => bar, - } -} diff --git a/rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs b/rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs deleted file mode 100644 index 7bfcc23c8ea..00000000000 --- a/rustfmt-core/tests/target/configs/spaces_around_ranges/true.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-spaces_around_ranges: true -// Spaces around ranges - -fn main() { - let lorem = 0 .. 10; - let ipsum = 0 ..= 10; - - match lorem { - 1 .. 5 => foo(), - _ => bar, - } - - match lorem { - 1 ..= 5 => foo(), - _ => bar, - } - - match lorem { - 1 ... 5 => foo(), - _ => bar, - } -} diff --git a/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs b/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs deleted file mode 100644 index 908373ca9b0..00000000000 --- a/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: false -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} diff --git a/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs b/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs deleted file mode 100644 index 7aff7131506..00000000000 --- a/rustfmt-core/tests/target/configs/spaces_within_parens_and_brackets/true.rs +++ /dev/null @@ -1,145 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: true -// Spaces within parens and brackets - -fn lorem< T: Eq >( t: T ) { - let lorem = ( ipsum, dolor ); - let lorem: [ usize; 2 ] = [ ipsum, dolor ]; -} - -enum E { - A( u32 ), - B( u32, u32 ), - C( u32, u32, u32 ), - D(), -} - -struct TupleStruct0(); -struct TupleStruct1( u32 ); -struct TupleStruct2( u32, u32 ); - -fn fooEmpty() {} - -fn foo( e: E, _: u32 ) -> ( u32, u32 ) { - // Tuples - let t1 = (); - let t2 = ( 1, ); - let t3 = ( 1, 2 ); - - let ts0 = TupleStruct0(); - let ts1 = TupleStruct1( 1 ); - let ts2 = TupleStruct2( 1, 2 ); - - // Tuple pattern - let ( a, b, c ) = ( 1, 2, 3 ); - - // Expressions - let x = ( 1 + 2 ) * ( 3 ); - - // Function call - fooEmpty(); - foo( 1, 2 ); - - // Pattern matching - match e { - A( _ ) => (), - B( _, _ ) => (), - C( .. ) => (), - D => (), - } - - ( 1, 2 ) -} - -struct Foo< T > { - i: T, -} - -struct Bar< T, E > { - i: T, - e: E, -} - -struct Foo< 'a > { - i: &'a str, -} - -enum E< T > { - T( T ), -} - -enum E< T, S > { - T( T ), - S( S ), -} - -fn foo< T >( a: T ) { - foo::< u32 >( 10 ); -} - -fn foo< T, E >( a: T, b: E ) { - foo::< u32, str >( 10, "bar" ); -} - -fn foo< T: Send, E: Send >( a: T, b: E ) { - foo::< u32, str >( 10, "bar" ); - - let opt: Option< u32 >; - let res: Result< u32, String >; -} - -fn foo< 'a >( a: &'a str ) { - foo( "foo" ); -} - -fn foo< 'a, 'b >( a: &'a str, b: &'b str ) { - foo( "foo", "bar" ); -} - -impl Foo { - fn bar() { - < Foo as Foo >::bar(); - } -} - -trait MyTrait< A, D > {} -impl< A: Send, D: Send > MyTrait< A, D > for Foo {} - -fn foo() -where - for< 'a > u32: 'a, -{ -} - -fn main() { - let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; - let arr: [ i32; 500 ] = [ 0; 500 ]; - - let v = vec![ 1, 2, 3 ]; - assert_eq!( arr, [ 1, 2, 3 ] ); - - let i = arr[ 0 ]; - - let slice = &arr[ 1..2 ]; - - let line100_________________________________________________________________________ = [ 1, 2 ]; - let line101__________________________________________________________________________ = - [ 1, 2 ]; - let line102___________________________________________________________________________ = - [ 1, 2 ]; - let line103____________________________________________________________________________ = - [ 1, 2 ]; - let line104_____________________________________________________________________________ = - [ 1, 2 ]; - - let line100_____________________________________________________________________ = vec![ 1, 2 ]; - let line101______________________________________________________________________ = - vec![ 1, 2 ]; - let line102_______________________________________________________________________ = - vec![ 1, 2 ]; - let line103________________________________________________________________________ = - vec![ 1, 2 ]; - let line104_________________________________________________________________________ = - vec![ 1, 2 ]; -} - -fn f( slice: &[ i32 ] ) {} diff --git a/rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs b/rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs deleted file mode 100644 index b84afc56835..00000000000 --- a/rustfmt-core/tests/target/configs/struct_field_align_threshold/20.rs +++ /dev/null @@ -1,467 +0,0 @@ -// rustfmt-struct_field_align_threshold: 20 -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false - -struct Foo { - x: u32, - yy: u32, // comment - zzz: u32, -} - -pub struct Bar { - x: u32, - yy: u32, - zzz: u32, - - xxxxxxx: u32, -} - -fn main() { - let foo = Foo { - x: 0, - yy: 1, - zzz: 2, - }; - - let bar = Bar { - x: 0, - yy: 1, - zzz: 2, - - xxxxxxx: 3, - }; -} - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField, -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] // only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct NewInt( - pub i32, - SomeType, // inline comment - T, // sup -); - -struct Qux< - 'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy, ->( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple( - // Comment 1 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - c: C, // Comment C -} - -struct Baz { - a: A, - - b: B, - c: C, - - d: D, -} - -struct Baz { - // Comment A - a: A, - - // Comment B - b: B, - // Comment C - c: C, -} - -// Will this be a one-liner? -struct Tuple( - A, // Comment - B, -); - -pub struct State time::Timespec> { - now: F, -} - -pub struct State ()> { - now: F, -} - -pub struct State { - now: F, -} - -struct Palette { - /// A map of indices in the palette to a count of pixels in approximately - /// that color - foo: i32, -} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ - // Another pre comment - #[attr1] - #[attr2] - pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC - * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(T); -struct Foo(T) -where - T: Copy, - T: Eq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -); -struct Foo( - TTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU, // Bar - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU, -); - -mod m { - struct X - where - T: Sized, - { - a: T, - } -} - -struct Foo( - TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU, -); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - -struct Foo {} -struct Foo {} -struct Foo { - // comment -} -struct Foo { - // trailing space -> -} -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: f(), - b: b(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a: Bar, b: f() }; - - Quux { - x: if cond { - bar(); - }, - y: baz(), - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { - // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, - } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { - memb: T, - } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S { a: 0, ..b }; -} - -fn issue201_2() { - let s = S { a: S2 { ..c }, ..b }; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo { a: 1, b: f(2) }; - Foo { - a: 1, - b: f(2), - ..g(3) - }; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { - ..base - }; - IntrinsicISizesContribution { - content_intrinsic_sizes: IntrinsicISizes { - minimum_inline_size: 0, - }, - }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { - a: bb, - c: dd, - e: ff, - }; - - Foo { - a: ddddddddddddddddddddd, - b: cccccccccccccccccccccccccccccccccccccc, - }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { - a: aaaaaaaaaa, - b: bbbbbbbb, - c: cccccccccc, - d: dddddddddd, // a comment - e: eeeeeeeee, - }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, ..base }; - Foo { - aaaaaaaaaa, - bbbbbbbb, - cccccccccc, - dddddddddd, // a comment - eeeeeeeee, - }; - Record { - ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; -} diff --git a/rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs b/rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs deleted file mode 100644 index e2732b5a7c9..00000000000 --- a/rustfmt-core/tests/target/configs/struct_lit_single_line/false.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-struct_lit_single_line: false -// Struct literal multiline-style - -fn main() { - let lorem = Lorem { - ipsum: dolor, - sit: amet, - }; -} diff --git a/rustfmt-core/tests/target/configs/tab_spaces/2.rs b/rustfmt-core/tests/target/configs/tab_spaces/2.rs deleted file mode 100644 index 85961706ea7..00000000000 --- a/rustfmt-core/tests/target/configs/tab_spaces/2.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-tab_spaces: 2 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { - let ipsum = dolor(); - let sit = vec![ - "amet", - "consectetur", - "adipiscing", - "elit.", - ]; -} diff --git a/rustfmt-core/tests/target/configs/tab_spaces/4.rs b/rustfmt-core/tests/target/configs/tab_spaces/4.rs deleted file mode 100644 index 524a55121e4..00000000000 --- a/rustfmt-core/tests/target/configs/tab_spaces/4.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-tab_spaces: 4 -// rustfmt-max_width: 30 -// rustfmt-indent_style: Block -// Tab spaces - -fn lorem() { - let ipsum = dolor(); - let sit = vec![ - "amet", - "consectetur", - "adipiscing", - "elit.", - ]; -} diff --git a/rustfmt-core/tests/target/configs/trailing_comma/always.rs b/rustfmt-core/tests/target/configs/trailing_comma/always.rs deleted file mode 100644 index 951dc680912..00000000000 --- a/rustfmt-core/tests/target/configs/trailing_comma/always.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-trailing_comma: Always -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit, } = amet; - let Lorem { - ipsum, - dolor, - sit, - amet, - consectetur, - adipiscing, - } = elit; -} diff --git a/rustfmt-core/tests/target/configs/trailing_comma/never.rs b/rustfmt-core/tests/target/configs/trailing_comma/never.rs deleted file mode 100644 index ae0e50f96d1..00000000000 --- a/rustfmt-core/tests/target/configs/trailing_comma/never.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-trailing_comma: Never -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit } = amet; - let Lorem { - ipsum, - dolor, - sit, - amet, - consectetur, - adipiscing - } = elit; - - // #1544 - if let VrMsg::ClientReply { - request_num: reply_req_num, - value, - .. - } = msg - { - let _ = safe_assert_eq!(reply_req_num, request_num, op); - return Ok((request_num, op, value)); - } - - // #1710 - pub struct FileInput { - input: StringInput, - file_name: OsString - } - match len { - Some(len) => Ok(new(self.input, self.pos + len)), - None => Err(self) - } -} diff --git a/rustfmt-core/tests/target/configs/trailing_comma/vertical.rs b/rustfmt-core/tests/target/configs/trailing_comma/vertical.rs deleted file mode 100644 index 7283cde8d06..00000000000 --- a/rustfmt-core/tests/target/configs/trailing_comma/vertical.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-trailing_comma: Vertical -// Trailing comma - -fn main() { - let Lorem { ipsum, dolor, sit } = amet; - let Lorem { - ipsum, - dolor, - sit, - amet, - consectetur, - adipiscing, - } = elit; -} diff --git a/rustfmt-core/tests/target/configs/trailing_semicolon/false.rs b/rustfmt-core/tests/target/configs/trailing_semicolon/false.rs deleted file mode 100644 index 9fa746e9c0f..00000000000 --- a/rustfmt-core/tests/target/configs/trailing_semicolon/false.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-trailing_semicolon: false - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b - } - - let x = loop { - break 5 - }; - - let x = 'c: loop { - break 'c 5 - }; -} - -fn foo() -> usize { - return 0 -} diff --git a/rustfmt-core/tests/target/configs/trailing_semicolon/true.rs b/rustfmt-core/tests/target/configs/trailing_semicolon/true.rs deleted file mode 100644 index 61b6843d677..00000000000 --- a/rustfmt-core/tests/target/configs/trailing_semicolon/true.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-trailing_semicolon: true - -#![feature(loop_break_value)] - -fn main() { - 'a: loop { - break 'a; - } - - let mut done = false; - 'b: while !done { - done = true; - continue 'b; - } - - let x = loop { - break 5; - }; - - let x = 'c: loop { - break 'c 5; - }; -} - -fn foo() -> usize { - return 0; -} diff --git a/rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs b/rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs deleted file mode 100644 index 6571e448e44..00000000000 --- a/rustfmt-core/tests/target/configs/type_punctuation_density/compressed.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-type_punctuation_density: Compressed -// Type punctuation density - -fn lorem() { - // body -} - -struct Foo -where - U: Eq+Clone, { - // body -} - -trait Foo<'a, T=usize> -where - T: 'a+Eq+Clone, -{ - type Bar: Eq+Clone; -} - -trait Foo: Eq+Clone { - // body -} - -impl Foo<'a> for Bar -where - for<'a> T: 'a+Eq+Clone, -{ - // body -} - -fn foo<'a, 'b, 'c>() -where - 'a: 'b+'c, -{ - // body -} - -fn Foo+Foo>() { - let i = 6; -} diff --git a/rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs b/rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs deleted file mode 100644 index 01546c7b0a5..00000000000 --- a/rustfmt-core/tests/target/configs/type_punctuation_density/wide.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-type_punctuation_density: Wide -// Type punctuation density - -fn lorem() { - // body -} - -struct Foo -where - U: Eq + Clone, { - // body -} - -trait Foo<'a, T = usize> -where - T: 'a + Eq + Clone, -{ - type Bar: Eq + Clone; -} - -trait Foo: Eq + Clone { - // body -} - -impl Foo<'a> for Bar -where - for<'a> T: 'a + Eq + Clone, -{ - // body -} - -fn foo<'a, 'b, 'c>() -where - 'a: 'b + 'c, -{ - // body -} - -fn Foo + Foo>() { - let i = 6; -} diff --git a/rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs b/rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs deleted file mode 100644 index dcebe0b6f1d..00000000000 --- a/rustfmt-core/tests/target/configs/use_field_init_shorthand/false.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-use_field_init_shorthand: false -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { x: x, y: y, z: z }; - - let b = Bar { - x: x, - y: y, - #[attr] - z: z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs b/rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs deleted file mode 100644 index ad78093ee8e..00000000000 --- a/rustfmt-core/tests/target/configs/use_field_init_shorthand/true.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-use_field_init_shorthand: true -// Use field initialization shorthand if possible. - -fn main() { - let a = Foo { x, y, z }; - - let b = Bar { - x, - y, - #[attr] - z, - #[rustfmt_skip] - skipped: skipped, - }; -} diff --git a/rustfmt-core/tests/target/configs/use_try_shorthand/false.rs b/rustfmt-core/tests/target/configs/use_try_shorthand/false.rs deleted file mode 100644 index de7f8b4a5e2..00000000000 --- a/rustfmt-core/tests/target/configs/use_try_shorthand/false.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: false -// Use try! shorthand - -fn main() { - let lorem = try!(ipsum.map(|dolor| dolor.sit())); -} diff --git a/rustfmt-core/tests/target/configs/use_try_shorthand/true.rs b/rustfmt-core/tests/target/configs/use_try_shorthand/true.rs deleted file mode 100644 index d3aa035792c..00000000000 --- a/rustfmt-core/tests/target/configs/use_try_shorthand/true.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-use_try_shorthand: true -// Use try! shorthand - -fn main() { - let lorem = ipsum.map(|dolor| dolor.sit())?; -} diff --git a/rustfmt-core/tests/target/configs/where_single_line/true.rs b/rustfmt-core/tests/target/configs/where_single_line/true.rs deleted file mode 100644 index c4a7f5d3802..00000000000 --- a/rustfmt-core/tests/target/configs/where_single_line/true.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-where_single_line: true -// Where style - -fn lorem_two_items() -> T -where - Ipsum: Eq, - Lorem: Eq, -{ - // body -} - -fn lorem_multi_line( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) -> T -where - Ipsum: Eq, -{ - // body -} - -fn lorem() -> T -where Ipsum: Eq { - // body -} diff --git a/rustfmt-core/tests/target/configs/wrap_comments/false.rs b/rustfmt-core/tests/target/configs/wrap_comments/false.rs deleted file mode 100644 index 48ecd88accb..00000000000 --- a/rustfmt-core/tests/target/configs/wrap_comments/false.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-wrap_comments: false -// rustfmt-max_width: 50 -// rustfmt-error_on_line_overflow: false -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -} diff --git a/rustfmt-core/tests/target/configs/wrap_comments/true.rs b/rustfmt-core/tests/target/configs/wrap_comments/true.rs deleted file mode 100644 index 4096fd4d89d..00000000000 --- a/rustfmt-core/tests/target/configs/wrap_comments/true.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 50 -// Wrap comments - -fn main() { - // Lorem ipsum dolor sit amet, consectetur - // adipiscing elit, sed do eiusmod tempor - // incididunt ut labore et dolore magna - // aliqua. Ut enim ad minim veniam, quis - // nostrud exercitation ullamco laboris nisi - // ut aliquip ex ea commodo consequat. -} - -fn code_block() { - // ```rust - // let x = 3; - // - // println!("x = {}", x); - // ``` -} diff --git a/rustfmt-core/tests/target/control-brace-style-always-next-line.rs b/rustfmt-core/tests/target/control-brace-style-always-next-line.rs deleted file mode 100644 index 054a3075ca0..00000000000 --- a/rustfmt-core/tests/target/control-brace-style-always-next-line.rs +++ /dev/null @@ -1,50 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - loop - { - (); - (); - } - - 'label: loop - // loop comment - { - (); - } - - cond = true; - while cond - { - (); - } - - 'while_label: while cond - { - // while comment - (); - } - - for obj in iter - { - for sub_obj in obj - { - 'nested_while_label: while cond - { - (); - } - } - } - - match some_var - { - // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => - { - do_stuff(); - val2 - } - }; -} diff --git a/rustfmt-core/tests/target/control-brace-style-always-same-line.rs b/rustfmt-core/tests/target/control-brace-style-always-same-line.rs deleted file mode 100644 index ae6bf4a5682..00000000000 --- a/rustfmt-core/tests/target/control-brace-style-always-same-line.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - loop { - (); - (); - } - - 'label: loop - // loop comment - { - (); - } - - cond = true; - while cond { - (); - } - - 'while_label: while cond { - // while comment - (); - } - - for obj in iter { - for sub_obj in obj { - 'nested_while_label: while cond { - (); - } - } - } - - match some_var { - // match comment - pattern0 => val0, - pattern1 => val1, - pattern2 | pattern3 => { - do_stuff(); - val2 - } - }; -} diff --git a/rustfmt-core/tests/target/doc.rs b/rustfmt-core/tests/target/doc.rs deleted file mode 100644 index 0f9e2d21c1f..00000000000 --- a/rustfmt-core/tests/target/doc.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-normalize_comments: true -// Part of multiple.rs - -// sadfsdfa -// sdffsdfasdf diff --git a/rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs b/rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs deleted file mode 100644 index 31e12cfa0d0..00000000000 --- a/rustfmt-core/tests/target/else-if-brace-style-always-next-line.rs +++ /dev/null @@ -1,53 +0,0 @@ -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - if false - { - (); - (); - } - - if false - // lone if comment - { - (); - (); - } - - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - - if true - { - (); - } - else if false - { - (); - (); - } - else - { - (); - (); - (); - } - - if true - // else-if-chain if comment - { - (); - } - else if false - // else-if-chain else-if comment - { - (); - (); - } - else - // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs b/rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs deleted file mode 100644 index 5e5ab21a0d8..00000000000 --- a/rustfmt-core/tests/target/else-if-brace-style-always-same-line.rs +++ /dev/null @@ -1,45 +0,0 @@ -// rustfmt-control_brace_style: AlwaysSameLine - -fn main() { - if false { - (); - (); - } - - if false - // lone if comment - { - (); - (); - } - - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - - if true { - (); - } else if false { - (); - (); - } else { - (); - (); - (); - } - - if true - // else-if-chain if comment - { - (); - } else if false - // else-if-chain else-if comment - { - (); - (); - } else - // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs b/rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs deleted file mode 100644 index c99807dc06d..00000000000 --- a/rustfmt-core/tests/target/else-if-brace-style-closing-next-line.rs +++ /dev/null @@ -1,49 +0,0 @@ -// rustfmt-control_brace_style: ClosingNextLine - -fn main() { - if false { - (); - (); - } - - if false - // lone if comment - { - (); - (); - } - - let a = if 0 > 1 { unreachable!() } else { 0x0 }; - - if true { - (); - } - else if false { - (); - (); - } - else { - (); - (); - (); - } - - if true - // else-if-chain if comment - { - (); - } - else if false - // else-if-chain else-if comment - { - (); - (); - } - else - // else-if-chain else comment - { - (); - (); - (); - } -} diff --git a/rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs deleted file mode 100644 index 0b9a15e8a92..00000000000 --- a/rustfmt-core/tests/target/empty-tuple-no-conversion-to-unit-struct.rs +++ /dev/null @@ -1,12 +0,0 @@ -enum TestEnum { - Arm1(), - Arm2, -} - -fn foo() { - let test = TestEnum::Arm1; - match test { - TestEnum::Arm1() => {} - TestEnum::Arm2 => {} - } -} diff --git a/rustfmt-core/tests/target/empty_file.rs b/rustfmt-core/tests/target/empty_file.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/rustfmt-core/tests/target/empty_file.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rustfmt-core/tests/target/enum.rs b/rustfmt-core/tests/target/enum.rs deleted file mode 100644 index de88f610b6a..00000000000 --- a/rustfmt-core/tests/target/enum.rs +++ /dev/null @@ -1,255 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Enums test - -#[atrr] -pub enum Test { - A, - B(u32, A /* comment */, SomeType), - /// Doc comment - C, -} - -pub enum Foo<'a, Y: Baz> -where - X: Whatever, -{ - A, -} - -enum EmtpyWithComment { - // Some comment -} - -// C-style enum -enum Bar { - A = 1, - #[someAttr(test)] - B = 2, // comment - C, -} - -enum LongVariants { - First( - LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment - VARIANT, - ), - // This is the second variant - Second, -} - -enum StructLikeVariants { - Normal(u32, String), - StructLike { - x: i32, // Test comment - // Pre-comment - #[Attr50] - y: SomeType, // Aanother Comment - }, - SL { - a: A, - }, -} - -enum X { - CreateWebGLPaintTask( - Size2D, - GLContextAttributes, - IpcSender, usize), String>>, - ), // This is a post comment -} - -pub enum EnumWithAttributes { - //This is a pre comment - // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ - // Pre Comment - #[rustfmt_skip] - SkippedItem(String,String,), // Post-comment - #[another_attr] - #[attr2] - ItemStruct { - x: usize, - y: usize, - }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ - // And another - ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ -} - -pub enum SingleTuple { - // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - Match(usize, usize, String), /* Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ -} - -pub enum SingleStruct { - Match { name: String, loc: usize }, // Post-comment -} - -pub enum GenericEnum -where - I: Iterator, -{ - // Pre Comment - Left { list: I, root: T }, // Post-comment - Right { list: I, root: T }, // Post Comment -} - -enum EmtpyWithComment { - // Some comment -} - -enum TestFormatFails { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -fn nested_enum_test() { - if true { - enum TestEnum { - One( - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - ), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAAAAAA */ - Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - * AAAAAAAAAAAAAAAAAA */ - } - enum TestNestedFormatFail { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - } - } -} - -pub struct EmtpyWithComment { - // FIXME: Implement this struct -} - -// #1115 -pub enum Bencoding<'i> { - Str(&'i [u8]), - Int(i64), - List(Vec>), - /// A bencoded dict value. The first element the slice of bytes in the source that the dict is - /// composed of. The second is the dict, decoded into an ordered map. - // TODO make Dict "structlike" AKA name the two values. - Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), -} - -// #1261 -pub enum CoreResourceMsg { - SetCookieForUrl( - ServoUrl, - #[serde(deserialize_with = "::hyper_serde::deserialize", - serialize_with = "::hyper_serde::serialize")] - Cookie, - CookieSource, - ), -} - -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{ - Foo, -} - -// #1046 -pub enum Entry<'a, K: 'a, V: 'a> { - Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), - Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), -} - -// #2081 -pub enum ForegroundColor { - CYAN = - (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, -} - -// #2098 -pub enum E<'a> { - V( as Iterator>::Item), -} - -// #1809 -enum State { - TryRecv { - pos: usize, - lap: u8, - closed_count: usize, - }, - Subscribe { - pos: usize, - }, - IsReady { - pos: usize, - ready: bool, - }, - Unsubscribe { - pos: usize, - lap: u8, - id_woken: usize, - }, - FinalTryRecv { - pos: usize, - id_woken: usize, - }, - TimedOut, - Disconnected, -} - -// #2190 -#[derive(Debug, Fail)] -enum AnError { - #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] - UnexpectedSingleToken { token: syn::Token }, -} - -// #2193 -enum WidthOf101 { - #[fail(display = ".....................................................")] - Io(::std::io::Error), - #[fail(display = ".....................................................")] - Ioo(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), - Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ::std::io::Error, - ), -} - -// #2389 -pub enum QlError { - #[fail(display = "Parsing error: {}", 0)] - LexError(parser::lexer::LexError), - #[fail(display = "Parsing error: {:?}", 0)] - ParseError(parser::ParseError), - #[fail(display = "Validation error: {:?}", 0)] - ValidationError(Vec), - #[fail(display = "Execution error: {}", 0)] - ExecutionError(String), - // (from, to) - #[fail(display = "Translation error: from {} to {}", 0, 1)] - TranslationError(String, String), - // (kind, input, expected) - #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] - ResolveError(&'static str, String, Option), -} diff --git a/rustfmt-core/tests/target/expr-block.rs b/rustfmt-core/tests/target/expr-block.rs deleted file mode 100644 index 277990c5a60..00000000000 --- a/rustfmt-core/tests/target/expr-block.rs +++ /dev/null @@ -1,299 +0,0 @@ -// rustfmt-indent_style: Block -// Test expressions with block formatting. - -fn arrays() { - []; - let empty = []; - - let foo = [a_long_name, a_very_lng_name, a_long_name]; - - let foo = [ - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - ]; - - vec![ - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_very_lng_name, - ]; - - [ - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_long_name, - a_very_lng_name, - a_very_lng_name, - ] -} - -fn arrays() { - let x = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 0, - ]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ - strukt { - test123: value_one_two_three_four, - turbo: coolio(), - }, - /* comment */ 1, - ]; - - let a = WeightedChoice::new(&mut [ - Weighted { weight: x, item: 0 }, - Weighted { weight: 1, item: 1 }, - Weighted { weight: x, item: 2 }, - Weighted { weight: 1, item: 3 }, - ]); - - let z = [ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzz, - q, - ]; - - [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] -} - -fn function_calls() { - let items = itemize_list( - context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite( - context, - Shape { - width: remaining_width, - ..nested_shape - }, - ) - }, - span.lo(), - span.hi(), - ); - - itemize_list( - context.codemap, - args.iter(), - ")", - |item| item.span.lo(), - |item| item.span.hi(), - |item| { - item.rewrite( - context, - Shape { - width: remaining_width, - ..nested_shape - }, - ) - }, - span.lo(), - span.hi(), - ) -} - -fn macros() { - baz!( - do_not, - add, - trailing, - commas, - inside, - of, - function, - like, - macros, - even, - if_they, - are, - long - ); - - baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); - - let _ = match option { - None => baz!( - function, - like, - macro_as, - expression, - which, - is, - loooooooooooooooong - ), - Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), - }; -} - -fn issue_1450() { - if selfstate - .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( - STATE_PARKED, - STATE_UNPARKED, - Release, - Relaxed, - Release, - Relaxed, - ) - .is_ok() - { - return; - } -} - -fn foo() { - if real_total <= limit && !pre_line_comments - && !items.into_iter().any(|item| item.as_ref().is_multiline()) - { - DefinitiveListTactic::Horizontal - } -} - -fn combine_block() { - foo(Bar { - x: value, - y: value2, - }); - - foo((Bar { - x: value, - y: value2, - },)); - - foo(( - 1, - 2, - 3, - Bar { - x: value, - y: value2, - }, - )); - - foo((1, 2, 3, |x| { - let y = x + 1; - let z = y + 1; - z - })); - - let opt = Some(Struct( - long_argument_one, - long_argument_two, - long_argggggggg, - )); - - do_thing(|param| { - action(); - foo(param) - }); - - do_thing(x, |param| { - action(); - foo(param) - }); - - do_thing( - x, - (1, 2, 3, |param| { - action(); - foo(param) - }), - ); - - Ok(some_function( - lllllllllong_argument_one, - lllllllllong_argument_two, - lllllllllllllllllllllllllllllong_argument_three, - )); - - foo( - thing, - bar( - param2, - pparam1param1param1param1param1param1param1param1param1param1aram1, - param3, - ), - ); - - foo.map_or(|| { - Ok(SomeStruct { - f1: 0, - f2: 0, - f3: 0, - }) - }); - - match opt { - Some(x) => somefunc(anotherfunc( - long_argument_one, - long_argument_two, - long_argument_three, - )), - Some(x) => |x| { - let y = x + 1; - let z = y + 1; - z - }, - Some(x) => (1, 2, |x| { - let y = x + 1; - let z = y + 1; - z - }), - Some(x) => SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }, - None => Ok(SomeStruct { - f1: long_argument_one, - f2: long_argument_two, - f3: long_argument_three, - }), - }; - - match x { - y => func(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), - _ => func( - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzz, - ), - } -} - -fn issue_1862() { - foo( - /* bar = */ None, - something_something, - /* baz = */ None, - /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ - None, - /* com */ - this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, - ) -} - -fn issue_1878() { - let channel: &str = seq.next_element()? - .ok_or_else(|| de::Error::invalid_length(2, &self))?; -} diff --git a/rustfmt-core/tests/target/expr.rs b/rustfmt-core/tests/target/expr.rs deleted file mode 100644 index 3c5d85b7d76..00000000000 --- a/rustfmt-core/tests/target/expr.rs +++ /dev/null @@ -1,397 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// Test expressions - -fn foo() -> bool { - let boxed: Box = box 5; - let referenced = &5; - - let very_long_variable_name = (a + first + simple + test); - let very_long_variable_name = - (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - - let is_internalxxxx = - self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); - - let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb - / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; - - some_ridiculously_loooooooooooooooooooooong_function( - 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), - trivial_value, - ); - (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + a - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaa))))))))); - - { - for _ in 0..10 {} - } - - { - { - { - {} - } - } - } - - if 1 + 2 > 0 { - let result = 5; - result - } else { - 4 - }; - - if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { - // Nothing - } - - if let Some(x) = - (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) - {} - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1 + 2 + 3 - {} - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1111 + 2222 - {} - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1 + 2 + 3 - {} - - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node - { - // nothing - } - - let test = if true { 5 } else { 3 }; - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - // Check subformatting - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } -} - -fn bar() { - let range = - (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + 2333333333333333); - - let another_range = 5..some_func(a, b /* comment */); - - for _ in 1.. { - call_forever(); - } - - syntactically_correct( - loop { - sup('?'); - }, - if cond { 0 } else { 1 }, - ); - - let third = ..10; - let infi_range = ..; - let foo = 1..; - let bar = 5; - let nonsense = (10..0)..(0..10); - - loop { - if true { - break; - } - } - - let x = ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - a, - ); -} - -fn baz() { - unsafe /* {}{}{}{{{{}} */ { - let foo = 1u32; - } - - unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong - * comment */ { - } - - unsafe /* So this is a very long comment. - * Multi-line, too. - * Will it still format correctly? */ { - } - - unsafe { - // Regular unsafe block - } - - unsafe { foo() } - - unsafe { - foo(); - } - - // #2289 - let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; - let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; - let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; - let identifier_3 = - unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; -} - -// Test some empty blocks. -fn qux() { - {} - // FIXME this one could be done better. - { /* a block with a comment */ } - {} - { - // A block with a comment. - } -} - -fn issue227() { - { - let handler = - box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); - } -} - -fn issue184(source: &str) { - for c in source.chars() { - if index < 'a' { - continue; - } - } -} - -fn arrays() { - let x = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 0, - ]; - - let y = [/* comment */ 1, 2 /* post comment */, 3]; - - let xy = [ - strukt { - test123: value_one_two_three_four, - turbo: coolio(), - }, - // comment - 1, - ]; - - let a = WeightedChoice::new(&mut [ - Weighted { - weightweight: x, - item: 0, - }, - Weighted { - weightweight: 1, - item: 1, - }, - Weighted { - weightweight: x, - item: 2, - }, - Weighted { - weightweight: 1, - item: 3, - }, - ]); - - let z = [ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q, - ]; - - [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] -} - -fn returns() { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - && return; - - return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -} - -fn addrof() { - &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); - &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); -} - -fn casts() { - fn unpack(packed: u32) -> [u16; 2] { - [(packed >> 16) as u16, (packed >> 0) as u16] - } - - let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; - let slightly_longer_trait = - yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; -} - -fn indices() { - let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) - [x + y + z]; - let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) - [xxxxx + yyyyy + zzzzz]; - let z = xxxxxxxxxx - .x() - .y() - .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; - let z = xxxxxxxxxx - .x() - .y() - .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz() - [aaaaa]; -} - -fn repeats() { - let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; - x + y + z]; - let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; - xxxxx + yyyyy + zzzzz]; -} - -fn blocks() { - if 1 + 1 == 2 { - println!("yay arithmetix!"); - }; -} - -fn issue767() { - if false { - if false { - } else { - // A let binding here seems necessary to trigger it. - let _ = (); - } - } else if let false = false { - } -} - -fn ranges() { - let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let y = - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; - let z = ..=x; - - // #1766 - let x = [0. ..10.0]; - let x = [0. ..=10.0]; - - a..=b - - // the expr below won't compile because inclusive ranges need a defined end - // let a = 0 ..= ; -} - -fn if_else() { - let exact = diff / (if size == 0 { 1 } else { size }); - - let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; -} - -fn complex_if_else() { - if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { - yo(); - } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - { - ha(); - } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx - { - yo(); - } -} - -fn issue1106() { - { - if let hir::ItemEnum(ref enum_def, ref generics) = - self.ast_map.expect_item(enum_node_id).node - {} - } - - for entry in WalkDir::new(path) - .into_iter() - .filter_entry(|entry| exclusions.filter_entry(entry)) - {} -} - -fn issue1570() { - a_very_long_function_name({ some_func(1, { 1 }) }) -} - -fn issue1714() { - v = &mut { v }[mid..]; - let (left, right) = { v }.split_at_mut(mid); -} - -// Multi-lined index should be put on the next line if it fits in one line. -fn issue1749() { - { - { - { - if self.shape[(r as f32 + self.x_offset) as usize] - [(c as f32 + self.y_offset) as usize] != 0 - { - // hello - } - } - } - } -} - -// #1172 -fn newlines_between_list_like_expr() { - foo( - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ); - - vec![ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, - ]; - - match x { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - | zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), - _ => bar(), - }; -} - -fn issue2178() { - Ok(result - .iter() - .map(|item| ls_util::rls_to_location(item)) - .collect()) -} diff --git a/rustfmt-core/tests/target/extern.rs b/rustfmt-core/tests/target/extern.rs deleted file mode 100644 index b0aa51127d5..00000000000 --- a/rustfmt-core/tests/target/extern.rs +++ /dev/null @@ -1,73 +0,0 @@ -// rustfmt-normalize_comments: true - -extern crate foo; -extern crate foo as bar; - -extern crate chrono; -extern crate dotenv; -extern crate futures; - -extern crate bar; -extern crate foo; - -// #2315 -extern crate proc_macro; -extern crate proc_macro2; - -extern "C" { - fn c_func(x: *mut *mut libc::c_void); - - fn c_func( - x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, - y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY, - ); - - #[test123] - fn foo() -> uint64_t; - - pub fn bar(); -} - -extern "C" { - fn DMR_GetDevice( - pHDev: *mut HDEV, - searchMode: DeviceSearchMode, - pSearchString: *const c_char, - devNr: c_uint, - wildcard: c_char, - ) -> TDMR_ERROR; - - fn quux() -> (); // Post comment - - pub type Foo; - - type Bar; -} - -extern "Rust" { - static ext: u32; - // Some comment. - pub static mut var: SomeType; -} - -extern "C" { - fn syscall( - number: libc::c_long, // comment 1 - // comm 2 - ... // sup? - ) -> libc::c_long; - - fn foo(x: *const c_char, ...) -> libc::c_long; -} - -extern "C" { - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE, - ) -> *mut FILE; -} - -extern "C" {} diff --git a/rustfmt-core/tests/target/extern_not_explicit.rs b/rustfmt-core/tests/target/extern_not_explicit.rs deleted file mode 100644 index b55b64d05b3..00000000000 --- a/rustfmt-core/tests/target/extern_not_explicit.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-force_explicit_abi: false - -extern { - fn some_fn() -> (); -} - -extern fn sup() {} - -type funky_func = extern fn( - unsafe extern "rust-call" fn( - *const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal, - ) -> u8, -); diff --git a/rustfmt-core/tests/target/file-lines-1.rs b/rustfmt-core/tests/target/file-lines-1.rs deleted file mode 100644 index 2601ca9fc94..00000000000 --- a/rustfmt-core/tests/target/file-lines-1.rs +++ /dev/null @@ -1,29 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - }.method_call() - .method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/target/file-lines-2.rs b/rustfmt-core/tests/target/file-lines-2.rs deleted file mode 100644 index bc25698c2ed..00000000000 --- a/rustfmt-core/tests/target/file-lines-2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { val1 } else { val2 }.method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/target/file-lines-3.rs b/rustfmt-core/tests/target/file-lines-3.rs deleted file mode 100644 index fe465750ae1..00000000000 --- a/rustfmt-core/tests/target/file-lines-3.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] -// rustfmt-error_on_line_overflow: false - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - }.method_call() - .method_call(); - - let y = if cond { val1 } else { val2 }.method_call(); - - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/target/file-lines-4.rs b/rustfmt-core/tests/target/file-lines-4.rs deleted file mode 100644 index 83928bf6fec..00000000000 --- a/rustfmt-core/tests/target/file-lines-4.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-file_lines: [] -// (Test that nothing is formatted if an empty array is specified.) - -fn floaters() { - let x = Foo { - field1: val1, - field2: val2, - } - .method_call().method_call(); - - let y = if cond { - val1 - } else { - val2 - } - .method_call(); - // aaaaaaaaaaaaa - { - match x { - PushParam => { - // comment - stack.push(mparams[match cur.to_digit(10) { - Some(d) => d as usize - 1, - None => return Err("bad param number".to_owned()), - }] - .clone()); - } - } - } -} diff --git a/rustfmt-core/tests/target/file-lines-5.rs b/rustfmt-core/tests/target/file-lines-5.rs deleted file mode 100644 index 3966dc06303..00000000000 --- a/rustfmt-core/tests/target/file-lines-5.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] - -struct A { - t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - fn baz() { - let j = 15; - } -} diff --git a/rustfmt-core/tests/target/file-lines-6.rs b/rustfmt-core/tests/target/file-lines-6.rs deleted file mode 100644 index 8a092df869a..00000000000 --- a/rustfmt-core/tests/target/file-lines-6.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] - -struct A { - t: i64, -} - -mod foo { - fn bar() { - // test - let i = 12; - // test - } - - fn baz() { -/// - let j = 15; - } -} diff --git a/rustfmt-core/tests/target/file-lines-item.rs b/rustfmt-core/tests/target/file-lines-item.rs deleted file mode 100644 index e155e75f34c..00000000000 --- a/rustfmt-core/tests/target/file-lines-item.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] -// rustfmt-reorder_imports: true - -use foo::{c, b, a}; -use bar; - -fn foo() { - bar(); -} - -impl Drop for Context { - fn drop(&mut self) { - } -} - -impl Bar for Baz { - fn foo() { - bar( - baz, // Who knows? - ) - } -} diff --git a/rustfmt-core/tests/target/fn-args-with-last-line-comment.rs b/rustfmt-core/tests/target/fn-args-with-last-line-comment.rs deleted file mode 100644 index 27e0e09653e..00000000000 --- a/rustfmt-core/tests/target/fn-args-with-last-line-comment.rs +++ /dev/null @@ -1,24 +0,0 @@ -// #1587 -pub trait X { - fn a(&self) -> &'static str; - fn bcd( - &self, - c: &str, // comment on this arg - d: u16, // comment on this arg - e: &Vec, // comment on this arg - ) -> Box; -} - -// #1595 -fn foo( - arg1: LongTypeName, - arg2: LongTypeName, - arg3: LongTypeName, - arg4: LongTypeName, - arg5: LongTypeName, - arg6: LongTypeName, - arg7: LongTypeName, - //arg8: LongTypeName, -) { - // do stuff -} diff --git a/rustfmt-core/tests/target/fn-custom-2.rs b/rustfmt-core/tests/target/fn-custom-2.rs deleted file mode 100644 index c2b3580c668..00000000000 --- a/rustfmt-core/tests/target/fn-custom-2.rs +++ /dev/null @@ -1,78 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) { - foo(); -} - -fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, ->( - a: Aaaaaaaaaaaaaaa, -) { - bar(); -} - -fn baz() -where - X: TTTTTTTT, -{ - baz(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -impl Foo { - fn foo( - self, - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, - ) { - foo(); - } - - fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, - >( - a: Aaaaaaaaaaaaaaa, - ) { - bar(); - } - - fn baz() - where - X: TTTTTTTT, - { - baz(); - } -} - -struct Foo< - TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUU, - VVVVVVVVVVVVVVVVVVVVVVVVVVV, - WWWWWWWWWWWWWWWWWWWWWWWW, -> { - foo: Foo, -} diff --git a/rustfmt-core/tests/target/fn-custom-3.rs b/rustfmt-core/tests/target/fn-custom-3.rs deleted file mode 100644 index baa1e39231b..00000000000 --- a/rustfmt-core/tests/target/fn-custom-3.rs +++ /dev/null @@ -1,72 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn foo( - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) { - foo(); -} - -fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, ->( - a: Aaaaaaaaaaaaaaa, -) { - bar(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -impl Foo { - fn foo( - self, - a: Aaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbb, - c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, - ) { - foo(); - } - - fn bar< - 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, - TTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, - >( - a: Aaaaaaaaaaaaaaa, - ) { - bar(); - } -} - -struct Foo< - TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUU, - VVVVVVVVVVVVVVVVVVVVVVVVVVV, - WWWWWWWWWWWWWWWWWWWWWWWW, -> { - foo: Foo, -} diff --git a/rustfmt-core/tests/target/fn-custom-4.rs b/rustfmt-core/tests/target/fn-custom-4.rs deleted file mode 100644 index 0a223ef5fac..00000000000 --- a/rustfmt-core/tests/target/fn-custom-4.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-indent_style: Block -// Test different indents. - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -fn qux() -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} - -fn qux(a: Aaaaaaaaaaaaaaaaa) -where - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, - X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, -{ - baz(); -} diff --git a/rustfmt-core/tests/target/fn-custom-6.rs b/rustfmt-core/tests/target/fn-custom-6.rs deleted file mode 100644 index 720d4288c41..00000000000 --- a/rustfmt-core/tests/target/fn-custom-6.rs +++ /dev/null @@ -1,72 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) where - T: UUUUUUUUUUU, { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String -where - T: UUUUUUUUUUU, { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} -} diff --git a/rustfmt-core/tests/target/fn-custom-7.rs b/rustfmt-core/tests/target/fn-custom-7.rs deleted file mode 100644 index ec113c30d53..00000000000 --- a/rustfmt-core/tests/target/fn-custom-7.rs +++ /dev/null @@ -1,41 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block -// rustfmt-fn_args_density: Vertical -// rustfmt-brace_style: AlwaysNextLine - -// Case with only one variable. -fn foo(a: u8) -> u8 -{ - bar() -} - -// Case with 2 variables and some pre-comments. -fn foo( - a: u8, // Comment 1 - b: u8, // Comment 2 -) -> u8 -{ - bar() -} - -// Case with 2 variables and some post-comments. -fn foo( - // Comment 1 - a: u8, - // Comment 2 - b: u8, -) -> u8 -{ - bar() -} - -trait Test -{ - fn foo(a: u8) - { - } - - fn bar(a: u8) -> String - { - } -} diff --git a/rustfmt-core/tests/target/fn-custom-8.rs b/rustfmt-core/tests/target/fn-custom-8.rs deleted file mode 100644 index 290557b979d..00000000000 --- a/rustfmt-core/tests/target/fn-custom-8.rs +++ /dev/null @@ -1,78 +0,0 @@ -// rustfmt-indent_style: Block -// rustfmt-brace_style: PreferSameLine -// Test different indents. - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) where - T: UUUUUUUUUUU, { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String -where - T: UUUUUUUUUUU, { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String -where - T: UUUUUUUUUUU, { - bar(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar(a: u8) -> String {} - - fn bar(a: u8) -> String - where - Foo: foooo, - Bar: barrr, { - } -} diff --git a/rustfmt-core/tests/target/fn-custom.rs b/rustfmt-core/tests/target/fn-custom.rs deleted file mode 100644 index bf87553dedc..00000000000 --- a/rustfmt-core/tests/target/fn-custom.rs +++ /dev/null @@ -1,19 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Test some of the ways function signatures can be customised. - -// Test compressed layout of args. -fn foo( - a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, - e: Eeeeeeeeeeeeeeeeeee, -) { - foo(); -} - -impl Foo { - fn foo( - self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, - d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee, - ) { - foo(); - } -} diff --git a/rustfmt-core/tests/target/fn-simple.rs b/rustfmt-core/tests/target/fn-simple.rs deleted file mode 100644 index 4e6e6493835..00000000000 --- a/rustfmt-core/tests/target/fn-simple.rs +++ /dev/null @@ -1,107 +0,0 @@ -// rustfmt-normalize_comments: true - -fn simple( - // pre-comment on a function!? - i: i32, // yes, it's possible! - response: NoWay, // hose -) { - fn op( - x: Typ, - key: &[u8], - upd: Box< - Fn(Option<&memcache::Item>) - -> (memcache::Status, Result>), - >, - ) -> MapResult { - } - - "cool" -} - -fn weird_comment( - // /*/ double level */ comment - x: Hello, // /*/* triple, even */*/ - // Does this work? - y: World, -) { - simple(/* does this preserve comments now? */ 42, NoWay) -} - -fn generic(arg: T) -> &SomeType -where - T: Fn( - // First arg - A, - // Second argument - B, - C, - D, - // pre comment - E, // last comment - ) -> &SomeType, -{ - arg(a, b, c, d, e) -} - -fn foo() -> ! {} - -pub fn http_fetch_async( - listener: Box, - script_chan: Box, -) { -} - -fn some_func>(val: T) {} - -fn zzzzzzzzzzzzzzzzzzzz( - selff: Type, - mut handle: node::Handle>, Type, NodeType>, -) -> SearchStack<'a, K, V, Type, NodeType> { -} - -unsafe fn generic_call( - cx: *mut JSContext, - argc: libc::c_uint, - vp: *mut JSVal, - is_lenient: bool, - call: unsafe extern "C" fn( - *const JSJitInfo, - *mut JSContext, - HandleObject, - *mut libc::c_void, - u32, - *mut JSVal, - ) -> u8, -) { - let f: fn(_, _) -> _ = panic!(); -} - -pub fn start_export_thread( - database: &Database, - crypto_scheme: &C, - block_size: usize, - source_path: &Path, -) -> BonzoResult> { -} - -pub fn waltz(cwd: &Path) -> CliAssert { - { - { - formatted_comment = - rewrite_comment(comment, block_style, width, offset, formatting_fig); - } - } -} - -// #2003 -mod foo { - fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() - { - foo(); - } -} - -// #2082 -pub(crate) fn init() {} - -crate fn init() {} diff --git a/rustfmt-core/tests/target/fn-single-line.rs b/rustfmt-core/tests/target/fn-single-line.rs deleted file mode 100644 index 3617506d89a..00000000000 --- a/rustfmt-core/tests/target/fn-single-line.rs +++ /dev/null @@ -1,70 +0,0 @@ -// rustfmt-fn_single_line: true -// Test single-line functions. - -fn foo_expr() { 1 } - -fn foo_stmt() { foo(); } - -fn foo_decl_local() { let z = 5; } - -fn foo_decl_item(x: &mut i32) { x = 3; } - -fn empty() {} - -fn foo_return() -> String { "yay" } - -fn foo_where() -> T -where - T: Sync, -{ - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space() { 1 } - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) {} -} - -trait CoolerTypes { - fn dummy(&self) {} -} - -fn Foo() -where - T: Bar, -{ -} diff --git a/rustfmt-core/tests/target/fn-ty.rs b/rustfmt-core/tests/target/fn-ty.rs deleted file mode 100644 index 7d48f3b32db..00000000000 --- a/rustfmt-core/tests/target/fn-ty.rs +++ /dev/null @@ -1,14 +0,0 @@ -fn f( - xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, - xxxxxxxxxxxxxxxxxx: fn() -> a, - xxxxxxxxxxxxxxxxxx: fn(a, b, b), - xxxxxxxxxxxxxxxxxx: fn(), - xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, - xxxxxxxxxxxxxxxxxx: fn() -> !, -) where - F1: Fn(a, b, b) -> a, - F2: Fn(a, b, b), - F3: Fn(), - F4: Fn() -> u32, -{ -} diff --git a/rustfmt-core/tests/target/fn.rs b/rustfmt-core/tests/target/fn.rs deleted file mode 100644 index b78a8b5b21e..00000000000 --- a/rustfmt-core/tests/target/fn.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Tests different fns - -fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} - -fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType -where - T: Blah, -{ -} - -fn foo(a: AAA /* (comment) */) -where - T: Blah, -{ -} - -fn foo( - a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -) -> RetType -where - T: Blah, -{ - -} - -fn foo( - a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -) -> RetType -where - T: Blah, - U: dsfasdfasdfasd, -{ - -} - -fn foo B /* paren inside generics */>() {} - -impl Foo { - fn with_no_errors(&mut self, f: F) -> T - where - F: FnOnce(&mut Resolver) -> T, - { - } - - fn foo(mut self, mut bar: u32) {} - - fn bar(self, mut bazz: u32) {} -} - -pub fn render< - 'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write, ->( - g: &'a G, - w: &mut W, -) -> io::Result<()> { - render_opts(g, w, &[]) -} - -const fn foo() { - x; -} - -pub const fn foo() { - x; -} - -impl Foo { - const fn foo() { - x; - } -} - -fn homura>(_: T) {} - -fn issue377() -> (Box, Box) {} - -fn main() { - let _ = function(move || 5); - let _ = move || 42; - let _ = || unsafe { abort() }; -} - -// With inner attributes. -fn inner() { - #![inline] - x -} - -#[cfg_attr(rustfmt, rustfmt_skip)] -fn foo(a: i32) -> i32 { - // comment - if a > 0 { 1 } else { 2 } -} - -fn ______________________baz( - a: i32, -) -> *mut ::std::option::Option< - extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) -> (), -> { -} - -pub fn check_path<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - path: &hir::Path, - id: ast::NodeId, - cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), -) { -} - -pub fn check_path<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - path: &hir::Path, - id: ast::NodeId, - cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), -) { -} diff --git a/rustfmt-core/tests/target/fn_args_density-vertical.rs b/rustfmt-core/tests/target/fn_args_density-vertical.rs deleted file mode 100644 index 477a48cc35f..00000000000 --- a/rustfmt-core/tests/target/fn_args_density-vertical.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-fn_args_density: Vertical - -// Empty list should stay on one line. -fn do_bar() -> u8 { - bar() -} - -// A single argument should stay on the same line. -fn do_bar(a: u8) -> u8 { - bar() -} - -// Multiple arguments should each get their own line. -fn do_bar( - a: u8, - mut b: u8, - c: &u8, - d: &mut u8, - closure: &Fn(i32) -> i32, -) -> i32 { - // This feature should not affect closures. - let bar = |x: i32, y: i32| -> i32 { x + y }; - bar(a, b) -} - -// If the first argument doesn't fit on the same line with the function name, -// the whole list should probably be pushed to the next line with hanging -// indent. That's not what happens though, so check current behaviour instead. -// In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, - c: u8, - d: u8, -) { - this(); - that(); - the_other_thing(); -} diff --git a/rustfmt-core/tests/target/fn_args_indent-block.rs b/rustfmt-core/tests/target/fn_args_indent-block.rs deleted file mode 100644 index 04c18816d0b..00000000000 --- a/rustfmt-core/tests/target/fn_args_indent-block.rs +++ /dev/null @@ -1,144 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-indent_style: Block - -fn foo() { - foo(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) { - bar(); -} - -fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { - foo(); -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String { - bar(); -} - -fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { - bar() -} - -fn foo( - a: u8, // Comment 1 - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, // Comment 2 -) -> u8 { - bar() -} - -fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, -) -> String -where - X: Fooooo, - Y: Baaar, -{ - bar(); -} - -fn foo() -> T { - foo(); -} - -fn foo() -> T -where - X: Foooo, - Y: Baaar, -{ - foo(); -} - -fn foo() -where - X: Foooo, -{ -} - -fn foo() -where - X: Foooo, - Y: Baaar, -{ -} - -fn foo() -> ( - Loooooooooooooooooooooong, - Reeeeeeeeeeeeeeeeeeeeeeeeturn, - iiiiiiiiis, - Looooooooooooooooong, -) { - foo(); -} - -fn foo() { - foo(); -} - -fn foo< - L: Loooooooooooooooooooooong, - G: Geeeeeeeeeeeneric, - I: iiiiiiiiis, - L: Looooooooooooooooong, ->() { - foo(); -} - -fn foo() { - foo(); -} - -trait Test { - fn foo(a: u8) {} - - fn bar( - a: Aaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, - e: Eeeeeeeeeeeeeee, - ) -> String { - } -} - -fn foo( - a: Aaaaaaaaaaaaaaaaaaaa, - b: Bbbbbbbbbbbbbbbbb, - c: Cccccccccccccccccc, - d: Dddddddddddddddd, -) { - foo(); -} - -fn foo() -> ( - Looooooooooooooooooooooooooong, - Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, - iiiiiiiiiiiiiis, - Loooooooooooooooooooooong, -) { - foo(); -} diff --git a/rustfmt-core/tests/target/fn_once.rs b/rustfmt-core/tests/target/fn_once.rs deleted file mode 100644 index 42b8f98e78a..00000000000 --- a/rustfmt-core/tests/target/fn_once.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Add(usize); - -impl FnOnce<(usize,)> for Add { - type Output = Add; - extern "rust-call" fn call_once(self, to: (usize,)) -> Add { - Add(self.0 + to.0) - } -} diff --git a/rustfmt-core/tests/target/hard-tabs.rs b/rustfmt-core/tests/target/hard-tabs.rs deleted file mode 100644 index 90be4d6b367..00000000000 --- a/rustfmt-core/tests/target/hard-tabs.rs +++ /dev/null @@ -1,99 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-hard_tabs: true -// rustfmt-error_on_line_overflow: false - -fn main() { - let x = Bar; - - let y = Foo { a: x }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) { - } - - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - - if let ( - some_very_large, - tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, - ) = 1 + 2 + 3 - {} - - if cond() { - something(); - } else if different_cond() { - something_else(); - } else { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } - - unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong - * comment */ { - } - - unsafe /* So this is a very long comment. - * Multi-line, too. - * Will it still format correctly? */ { - } - - let chain = funktion_kall() - .go_to_next_line_with_tab() - .go_to_next_line_with_tab() - .go_to_next_line_with_tab(); - - let z = [ - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - yyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzz, - q, - ]; - - fn generic(arg: T) -> &SomeType - where - T: Fn( - // First arg - A, - // Second argument - B, - C, - D, - // pre comment - E, // last comment - ) -> &SomeType, - { - arg(a, b, c, d, e) - } - - loong_func().quux(move || if true { 1 } else { 2 }); - - fffffffffffffffffffffffffffffffffff(a, { - SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); - }); - a.b.c.d(); - - x().y(|| match cond() { - true => (), - false => (), - }); -} - -// #2296 -impl Foo { - // a comment - // on multiple lines - fn foo() { - // another comment - // on multiple lines - let x = true; - } -} diff --git a/rustfmt-core/tests/target/hello.rs b/rustfmt-core/tests/target/hello.rs deleted file mode 100644 index d9f90b0b5e8..00000000000 --- a/rustfmt-core/tests/target/hello.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-config: small_tabs.toml -// rustfmt-target: hello.rs - -// Smoke test - hello world. - -fn main() { - println!("Hello world!"); -} diff --git a/rustfmt-core/tests/target/immovable_generators.rs b/rustfmt-core/tests/target/immovable_generators.rs deleted file mode 100644 index 0bf7a2d91ba..00000000000 --- a/rustfmt-core/tests/target/immovable_generators.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(generators)] - -unsafe fn foo() { - let mut ga = static || { - yield 1; - }; -} diff --git a/rustfmt-core/tests/target/impl.rs b/rustfmt-core/tests/target/impl.rs deleted file mode 100644 index 5895c74bcc9..00000000000 --- a/rustfmt-core/tests/target/impl.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Test impls - -impl JSTraceable for SmallVec<[T; 1]> {} - -impl>> Handle { - // Keep this. -} - -impl Test -where - V: Clone, // This comment is NOT removed by formating! -{ - pub fn new(value: V) -> Self { - Test { - cloned_value: value.clone(), - value, - } - } -} - -impl X /* comment */ {} -impl Y // comment -{ -} - -impl Foo for T -// comment1 -where - // comment2 - // blah - T: Clone, -{ -} - -// #1823 -default impl Trait for X {} -default unsafe impl Trait for Y {} -pub default unsafe impl Trait for Z {} - -// #2212 -impl ConstWithDefault { - default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; -} diff --git a/rustfmt-core/tests/target/impls.rs b/rustfmt-core/tests/target/impls.rs deleted file mode 100644 index 91172b39fe5..00000000000 --- a/rustfmt-core/tests/target/impls.rs +++ /dev/null @@ -1,219 +0,0 @@ -// rustfmt-normalize_comments: true -impl Foo for Bar { - fn foo() { - "hi" - } -} - -pub impl Foo for Bar { - // Associated Constants - const Baz: i32 = 16; - // Associated Types - type FooBar = usize; - // Comment 1 - fn foo() { - "hi" - } - // Comment 2 - fn foo() { - "hi" - } - // Comment 3 -} - -pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> -where - X: Foo<'a, Z>, -{ - fn foo() { - "hi" - } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> -where - X: Fooooooooooooooooooooooooooooo<'a, Z>, -{ - fn foo() { - "hi" - } -} - -impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> -where - X: Foooooooooooooooooooooooooooo<'a, Z>, -{ - fn foo() { - "hi" - } -} - -impl Foo for Bar -where - T: Baz, -{ -} - -impl Foo for Bar -where - T: Baz, -{ - // Comment -} - -impl Foo { - fn foo() {} -} - -impl Boo { - // BOO - fn boo() {} - // FOO -} - -mod a { - impl Foo { - // Hello! - fn foo() {} - } -} - -mod b { - mod a { - impl Foo { - fn foo() {} - } - } -} - -impl Foo { - add_fun!(); -} - -impl Blah { - fn boop() {} - add_fun!(); -} - -impl X { - fn do_parse(mut self: X) {} -} - -impl Y5000 { - fn bar(self: X<'a, 'b>, y: Y) {} - - fn bad(&self, (x, y): CoorT) {} - - fn turbo_bad(self: X<'a, 'b>, (x, y): CoorT) {} -} - -pub impl Foo for Bar -where - T: Foo, -{ - fn foo() { - "hi" - } -} - -pub impl Foo for Bar -where - T: Foo, - Z: Baz, -{ -} - -mod m { - impl PartialEq for S - where - T: PartialEq, - { - fn eq(&self, other: &Self) { - true - } - } - - impl PartialEq for S - where - T: PartialEq, - { - } -} - -impl - Handle, HandleType> -{ -} - -impl PartialEq - for Handle, HandleType> -{ -} - -mod x { - impl Foo - where - A: 'static, - B: 'static, - C: 'static, - D: 'static, - { - } -} - -impl - Issue1249 -{ - // Creates a new flow constructor. - fn foo() {} -} - -// #1600 -impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { - fn drop() {} -} - -// #1168 -pub trait Number - : Copy - + Eq - + Not - + Shl - + Shr - + BitAnd - + BitOr - + BitAndAssign - + BitOrAssign { - // test - fn zero() -> Self; -} - -// #1642 -pub trait SomeTrait - : Clone - + Eq - + PartialEq - + Ord - + PartialOrd - + Default - + Hash - + Debug - + Display - + Write - + Read - + FromStr { - // comment -} - -// #1995 -impl Foo { - fn f( - S { - aaaaaaaaaa: aaaaaaaaaa, - bbbbbbbbbb: bbbbbbbbbb, - cccccccccc: cccccccccc, - }: S, - ) -> u32 { - 1 - } -} diff --git a/rustfmt-core/tests/target/import-fencepost-length.rs b/rustfmt-core/tests/target/import-fencepost-length.rs deleted file mode 100644 index e4f885c09b1..00000000000 --- a/rustfmt-core/tests/target/import-fencepost-length.rs +++ /dev/null @@ -1,4 +0,0 @@ -use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; -use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; -use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, - ddddddddd}; diff --git a/rustfmt-core/tests/target/imports-reorder-lines-and-items.rs b/rustfmt-core/tests/target/imports-reorder-lines-and-items.rs deleted file mode 100644 index f395710b186..00000000000 --- a/rustfmt-core/tests/target/imports-reorder-lines-and-items.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-reorder_imported_names: true - -use std::cmp::{a, b, c, d}; -use std::ddd::{a, b, c as g, d as p}; -use std::ddd::aaa; -// This comment should stay with `use std::ddd:bbb;` -use std::ddd::bbb; -/// This comment should stay with `use std::str;` -use std::str; diff --git a/rustfmt-core/tests/target/imports-reorder-lines.rs b/rustfmt-core/tests/target/imports-reorder-lines.rs deleted file mode 100644 index 3695d6b4913..00000000000 --- a/rustfmt-core/tests/target/imports-reorder-lines.rs +++ /dev/null @@ -1,33 +0,0 @@ -// rustfmt-reorder_imports: true - -use std::cmp::{a, b, c, d}; -use std::cmp::{b, e, f, g}; -// This comment should stay with `use std::ddd;` -use std::ddd; -use std::ddd::aaa; -use std::ddd::bbb; -use std::str; - -mod test {} - -use aaa; -use aaa::*; -use aaa::bbb; - -mod test {} -// If item names are equal, order by rename - -use test::{a as aa, c}; -use test::{a as bb, b}; - -mod test {} -// If item names are equal, order by rename - no rename comes before a rename - -use test::{a, c}; -use test::{a as bb, b}; - -mod test {} -// `self` always comes first - -use test::{self as bb, b}; -use test::{a as aa, c}; diff --git a/rustfmt-core/tests/target/imports-reorder.rs b/rustfmt-core/tests/target/imports-reorder.rs deleted file mode 100644 index fbb56e3aa0c..00000000000 --- a/rustfmt-core/tests/target/imports-reorder.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-reorder_imported_names: true - -use path::{self /* self */, /* A */ A, B /* B */, C}; - -use {aa, ab, ac, b, Z}; diff --git a/rustfmt-core/tests/target/imports.rs b/rustfmt-core/tests/target/imports.rs deleted file mode 100644 index 2b825526199..00000000000 --- a/rustfmt-core/tests/target/imports.rs +++ /dev/null @@ -1,88 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-error_on_line_overflow: false - -// Imports. - -// Long import. -use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; -use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; - -use list::{// Another item - AnotherItem, // Another Comment - // Last Item - LastItem, - // Some item - SomeItem /* Comment */}; - -use test::{/* A */ self /* B */, Other /* C */}; - -use syntax; -use {Bar /* comment */, /* Pre-comment! */ Foo}; -use Foo::{Bar, Baz}; -pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; - -use self; -use std::io; -use std::io; - -mod Foo { - pub use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; - - mod Foo2 { - pub use syntax::ast::{self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, - ItemStatic}; - } -} - -fn test() { - use Baz::*; - use Qux; -} - -// Simple imports -use foo::bar::baz; -use bar::quux as kaas; -use foo; - -// With aliases. -use foo::{self as bar, baz}; -use foo as bar; -use foo::qux as bar; -use foo::{baz, qux as bar}; - -// With absolute paths -use foo; -use foo::Bar; -use foo::{Bar, Baz}; -use Foo; -use {Bar, Baz}; - -// Root globs -use ::*; -use ::*; - -// spaces used to cause glob imports to disappear (#1356) -use super::*; -use foo::issue_1356::*; - -// We shouldn't remove imports which have attributes attached (#1858) -#[cfg(unix)] -use self::unix::{}; - -// nested imports -use foo::{a, b, boo, c, - bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, - foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}}; - -use fooo::{bar, x, y, z, - baar::foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, - zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}, - bar::*}; - -// nested imports with a single sub-tree. -use a::b::c::*; -use a::b::c::d; -use a::b::c::{xxx, yyy, zzz}; diff --git a/rustfmt-core/tests/target/indented-impl.rs b/rustfmt-core/tests/target/indented-impl.rs deleted file mode 100644 index eff579dddac..00000000000 --- a/rustfmt-core/tests/target/indented-impl.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine -mod x -{ - struct X(i8); - - impl Y for X - { - fn y(self) -> () - { - println!("ok"); - } - } -} diff --git a/rustfmt-core/tests/target/issue-1021.rs b/rustfmt-core/tests/target/issue-1021.rs deleted file mode 100644 index ba1029d4e61..00000000000 --- a/rustfmt-core/tests/target/issue-1021.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - match x { - S(true, .., true) => (), - S(true, ..) => (), - S(.., true) => (), - S(..) => (), - S(_) => (), - S(/* .. */ ..) => (), - S(/* .. */ .., true) => (), - } - - match y { - (true, .., true) => (), - (true, ..) => (), - (.., true) => (), - (..) => (), - (_,) => (), - (/* .. */ ..) => (), - (/* .. */ .., true) => (), - } -} diff --git a/rustfmt-core/tests/target/issue-1049.rs b/rustfmt-core/tests/target/issue-1049.rs deleted file mode 100644 index c788519ca9a..00000000000 --- a/rustfmt-core/tests/target/issue-1049.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Test overlong function signature -pub unsafe fn reborrow_mut( - &mut X: Abcde, -) -> Handle, HandleType> { -} - -pub fn merge( - mut X: Abcdef, -) -> Handle, K, V, marker::Internal>, marker::Edge> { -} - -impl Handle { - pub fn merge( - a: Abcd, - ) -> Handle, K, V, marker::Internal>, marker::Edge> { - } -} - -// Long function without return type that should not be reformatted. -fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} - -fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { -} - -fn veeeeeeeeeeeeeeeeeeeeeeery_long_name( - a: FirstTypeeeeeeeeee, - b: SecondTypeeeeeeeeeeeeeeeeeeeeeee, -) { -} diff --git a/rustfmt-core/tests/target/issue-1055.rs b/rustfmt-core/tests/target/issue-1055.rs deleted file mode 100644 index ee143e792b0..00000000000 --- a/rustfmt-core/tests/target/issue-1055.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn issue_1055() { - let foo = (|| {})(); -} diff --git a/rustfmt-core/tests/target/issue-1111.rs b/rustfmt-core/tests/target/issue-1111.rs deleted file mode 100644 index 2e1a89ad78e..00000000000 --- a/rustfmt-core/tests/target/issue-1111.rs +++ /dev/null @@ -1 +0,0 @@ -use bar; diff --git a/rustfmt-core/tests/target/issue-1113.rs b/rustfmt-core/tests/target/issue-1113.rs deleted file mode 100644 index 1245bcd057c..00000000000 --- a/rustfmt-core/tests/target/issue-1113.rs +++ /dev/null @@ -1,33 +0,0 @@ -pub fn foo() -> fmt::Result -//pub fn writeStringToken -{ - panic!() -} - -pub fn foo() -> fmt::Result // pub fn writeStringToken -{ - panic!() -} - -pub fn foo() -> fmt::Result /* pub fn writeStringToken */ { - panic!() -} - -pub fn foo() -> fmt::Result -/* pub fn writeStringToken */ { - panic!() -} - -pub fn foo() -> fmt::Result -/* pub fn writeStringToken */ -{ - panic!() -} - -pub fn foo() -> fmt::Result /* - * - * - */ -{ - panic!() -} diff --git a/rustfmt-core/tests/target/issue-1120.rs b/rustfmt-core/tests/target/issue-1120.rs deleted file mode 100644 index f44597e7d1e..00000000000 --- a/rustfmt-core/tests/target/issue-1120.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-reorder_imports: true - -// Ensure that a use at the start of an inline module is correctly formatted. -mod foo { - use bar; -} - -// Ensure that an indented `use` gets the correct indentation. -mod foo { - use bar; -} diff --git a/rustfmt-core/tests/target/issue-1124.rs b/rustfmt-core/tests/target/issue-1124.rs deleted file mode 100644 index d34870b2a28..00000000000 --- a/rustfmt-core/tests/target/issue-1124.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-reorder_imports: true -// rustfmt-normalize_comments: true - -use a; -use b; -use c; -use d; -// The previous line has a space after the `use a;` - -mod a { - use a; - use b; - use c; - use d; -} - -use a; -use x; -use y; -use z; diff --git a/rustfmt-core/tests/target/issue-1127.rs b/rustfmt-core/tests/target/issue-1127.rs deleted file mode 100644 index dbdd234b8e4..00000000000 --- a/rustfmt-core/tests/target/issue-1127.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-max_width:120 -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true - -fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { - 42 -} - -enum TestEnum { - AVeryVeryLongEnumName, - AnotherVeryLongEnumName, - TheLastVeryLongEnumName, -} - -fn main() { - let var = TestEnum::AVeryVeryLongEnumName; - let num = match var { - TestEnum::AVeryVeryLongEnumName => - a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::AnotherVeryLongEnumName => - a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - TestEnum::TheLastVeryLongEnumName => - a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), - }; -} diff --git a/rustfmt-core/tests/target/issue-1158.rs b/rustfmt-core/tests/target/issue-1158.rs deleted file mode 100644 index 2abfa5a29f2..00000000000 --- a/rustfmt-core/tests/target/issue-1158.rs +++ /dev/null @@ -1,3 +0,0 @@ -trait T { - itemmacro!(this, is.now().formatted(yay)); -} diff --git a/rustfmt-core/tests/target/issue-1177.rs b/rustfmt-core/tests/target/issue-1177.rs deleted file mode 100644 index dcda3972814..00000000000 --- a/rustfmt-core/tests/target/issue-1177.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - // Line Comment - // Block Comment - - let d = 5; -} diff --git a/rustfmt-core/tests/target/issue-1192.rs b/rustfmt-core/tests/target/issue-1192.rs deleted file mode 100644 index 432fe8cce7c..00000000000 --- a/rustfmt-core/tests/target/issue-1192.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - assert!(true); -} diff --git a/rustfmt-core/tests/target/issue-1211.rs b/rustfmt-core/tests/target/issue-1211.rs deleted file mode 100644 index de4c5c87ee6..00000000000 --- a/rustfmt-core/tests/target/issue-1211.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn main() { - for iface in &ifaces { - match iface.addr { - get_if_addrs::IfAddr::V4(ref addr) => match addr.broadcast { - Some(ip) => { - sock.send_to(&buf, (ip, 8765)).expect("foobar"); - } - _ => (), - }, - _ => (), - }; - } -} diff --git a/rustfmt-core/tests/target/issue-1214.rs b/rustfmt-core/tests/target/issue-1214.rs deleted file mode 100644 index c622abb3a85..00000000000 --- a/rustfmt-core/tests/target/issue-1214.rs +++ /dev/null @@ -1,8 +0,0 @@ -/*! -# Example - -``` - // Here goes some example -``` - */ -struct Item; diff --git a/rustfmt-core/tests/target/issue-1216.rs b/rustfmt-core/tests/target/issue-1216.rs deleted file mode 100644 index d727c158ab8..00000000000 --- a/rustfmt-core/tests/target/issue-1216.rs +++ /dev/null @@ -1,5 +0,0 @@ -// rustfmt-normalize_comments: true -enum E { - A, //* I am not a block comment (caused panic) - B, -} diff --git a/rustfmt-core/tests/target/issue-1239.rs b/rustfmt-core/tests/target/issue-1239.rs deleted file mode 100644 index b10afb5cb6c..00000000000 --- a/rustfmt-core/tests/target/issue-1239.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn foo() { - let with_alignment = if condition__uses_alignment_for_first_if__0 - || condition__uses_alignment_for_first_if__1 - || condition__uses_alignment_for_first_if__2 - { - } else if condition__no_alignment_for_later_else__0 || condition__no_alignment_for_later_else__1 - || condition__no_alignment_for_later_else__2 - { - }; -} diff --git a/rustfmt-core/tests/target/issue-1247.rs b/rustfmt-core/tests/target/issue-1247.rs deleted file mode 100644 index 16c63e0f53d..00000000000 --- a/rustfmt-core/tests/target/issue-1247.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-max_width: 80 - -fn foo() { - polyfill::slice::fill( - &mut self.pending[padding_pos..(self.algorithm.block_len - 8)], - 0, - ); -} diff --git a/rustfmt-core/tests/target/issue-1255.rs b/rustfmt-core/tests/target/issue-1255.rs deleted file mode 100644 index 2d4633844a9..00000000000 --- a/rustfmt-core/tests/target/issue-1255.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Test for issue #1255 -// Default annotation incorrectly removed on associated types -#![feature(specialization)] - -trait Trait { - type Type; -} -impl Trait for T { - default type Type = u64; // 'default' should not be removed -} diff --git a/rustfmt-core/tests/target/issue-1278.rs b/rustfmt-core/tests/target/issue-1278.rs deleted file mode 100644 index e25376561a9..00000000000 --- a/rustfmt-core/tests/target/issue-1278.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-indent_style = "block" - -#![feature(pub_restricted)] - -mod inner_mode { - pub(super) fn func_name(abc: i32) -> i32 { - abc - } -} diff --git a/rustfmt-core/tests/target/issue-1350.rs b/rustfmt-core/tests/target/issue-1350.rs deleted file mode 100644 index 2cf65509c93..00000000000 --- a/rustfmt-core/tests/target/issue-1350.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-max_width: 120 -// rustfmt-comment_width: 110 - -impl Struct { - fn fun() { - let result = match ::deserialize(&json) { - Ok(v) => v, - Err(e) => match ::deserialize(&json) { - Ok(v) => return Err(Error::with_json(v)), - Err(e2) => return Err(Error::with_json(e)), - }, - }; - } -} diff --git a/rustfmt-core/tests/target/issue-1366.rs b/rustfmt-core/tests/target/issue-1366.rs deleted file mode 100644 index eee147baab9..00000000000 --- a/rustfmt-core/tests/target/issue-1366.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn main() { - fn f() -> Option { - Some("fffffffsssssssssddddssssfffffddddff") - .map(|s| s) - .map(|s| s.to_string()) - .map(|res| match Some(res) { - Some(ref s) if s == "" => 41, - Some(_) => 42, - _ => 43, - }) - } - println!("{:?}", f()) -} diff --git a/rustfmt-core/tests/target/issue-1397.rs b/rustfmt-core/tests/target/issue-1397.rs deleted file mode 100644 index 86b7a78411f..00000000000 --- a/rustfmt-core/tests/target/issue-1397.rs +++ /dev/null @@ -1,25 +0,0 @@ -pub enum TransactionState { - Committed(i64), -} - -pub enum Packet { - Transaction { state: TransactionState }, -} - -fn baz(p: Packet) { - loop { - loop { - loop { - loop { - if let Packet::Transaction { - state: TransactionState::Committed(ts, ..), - .. - } = p - { - unreachable!() - } - } - } - } - } -} diff --git a/rustfmt-core/tests/target/issue-1468.rs b/rustfmt-core/tests/target/issue-1468.rs deleted file mode 100644 index 4c14a0f746a..00000000000 --- a/rustfmt-core/tests/target/issue-1468.rs +++ /dev/null @@ -1,29 +0,0 @@ -fn issue1468() { - euc_jp_decoder_functions!({ - let trail_minus_offset = byte.wrapping_sub(0xA1); - // Fast-track Hiragana (60% according to Lunde) - // and Katakana (10% according to Lunde). - if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { - // Hiragana - handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) - } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 { - // Katakana - handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) - } else if trail_minus_offset > (0xFE - 0xA1) { - if byte < 0x80 { - return ( - DecoderResult::Malformed(1, 0), - unread_handle_trail.unread(), - handle.written(), - ); - } - return ( - DecoderResult::Malformed(2, 0), - unread_handle_trail.consumed(), - handle.written(), - ); - } else { - unreachable!(); - } - }); -} diff --git a/rustfmt-core/tests/target/issue-1598.rs b/rustfmt-core/tests/target/issue-1598.rs deleted file mode 100644 index c7e02c961a6..00000000000 --- a/rustfmt-core/tests/target/issue-1598.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - //foo - /* - */ - format!("hello"); -} diff --git a/rustfmt-core/tests/target/issue-1624.rs b/rustfmt-core/tests/target/issue-1624.rs deleted file mode 100644 index 477fc27353f..00000000000 --- a/rustfmt-core/tests/target/issue-1624.rs +++ /dev/null @@ -1,6 +0,0 @@ -// #1624 -pub unsafe fn some_long_function_name( - arg1: Type1, - arg2: Type2, -) -> (SomeLongTypeName, AnotherLongTypeName, AnotherLongTypeName) { -} diff --git a/rustfmt-core/tests/target/issue-1681.rs b/rustfmt-core/tests/target/issue-1681.rs deleted file mode 100644 index 5734fd5502d..00000000000 --- a/rustfmt-core/tests/target/issue-1681.rs +++ /dev/null @@ -1,20 +0,0 @@ -// rustfmt-max_width: 80 - -// We would like to surround closure body with block when overflowing the last -// argument of function call if the last argument has condition and without -// block it may go multi lines. -fn foo() { - refmut_map_result(self.cache.borrow_mut(), |cache| { - match cache.entry(cache_key) { - Occupied(entry) => Ok(entry.into_mut()), - Vacant(entry) => { - let statement = { - let sql = try!(entry.key().sql(source)); - prepare_fn(&sql) - }; - - Ok(entry.insert(try!(statement))) - } - } - }).map(MaybeCached::Cached) -} diff --git a/rustfmt-core/tests/target/issue-1693.rs b/rustfmt-core/tests/target/issue-1693.rs deleted file mode 100644 index 85421a123bb..00000000000 --- a/rustfmt-core/tests/target/issue-1693.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn issue1693() { - let pixel_data = vec![ - ( - f16::from_f32(0.82), - f16::from_f32(1.78), - f16::from_f32(0.21) - ); - 256 * 256 - ]; -} diff --git a/rustfmt-core/tests/target/issue-1703.rs b/rustfmt-core/tests/target/issue-1703.rs deleted file mode 100644 index 4079ef4cfca..00000000000 --- a/rustfmt-core/tests/target/issue-1703.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt should not remove doc comments or comments inside attributes. - -/** -This function has a block doc comment. - */ -fn test_function() {} - -#[foo /* do not remove this! */] -fn foo() {} diff --git a/rustfmt-core/tests/target/issue-1800.rs b/rustfmt-core/tests/target/issue-1800.rs deleted file mode 100644 index 06c5cfd0567..00000000000 --- a/rustfmt-core/tests/target/issue-1800.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![doc(html_root_url = "http://example.com")] -#[cfg(feature = "foo")] -fn a() {} diff --git a/rustfmt-core/tests/target/issue-1802.rs b/rustfmt-core/tests/target/issue-1802.rs deleted file mode 100644 index a4679463ba2..00000000000 --- a/rustfmt-core/tests/target/issue-1802.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-tab_spaces: 2 -// rustfmt-max_width: 30 -// rustfmt-error_on_line_overflow: false - -enum F { - X { - a: dddddddddddddd, - b: eeeeeeeeeeeeeee, - }, -} diff --git a/rustfmt-core/tests/target/issue-1824.rs b/rustfmt-core/tests/target/issue-1824.rs deleted file mode 100644 index 1c4c2db46dc..00000000000 --- a/rustfmt-core/tests/target/issue-1824.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub trait Ingredient -where - Self: Send, -{ -} diff --git a/rustfmt-core/tests/target/issue-1914.rs b/rustfmt-core/tests/target/issue-1914.rs deleted file mode 100644 index d2d532af1dc..00000000000 --- a/rustfmt-core/tests/target/issue-1914.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-max_width: 80 - -extern "C" { - #[link_name = "_ZN7MyClass26example_check_no_collisionE"] - pub static mut MyClass_example_check_no_collision: - *const ::std::os::raw::c_int; -} diff --git a/rustfmt-core/tests/target/issue-2025.rs b/rustfmt-core/tests/target/issue-2025.rs deleted file mode 100644 index 38bf369bea3..00000000000 --- a/rustfmt-core/tests/target/issue-2025.rs +++ /dev/null @@ -1,4 +0,0 @@ -// See if rustfmt removes empty lines on top of the file. -pub fn foo() { - println!("hello, world"); -} diff --git a/rustfmt-core/tests/target/issue-2103.rs b/rustfmt-core/tests/target/issue-2103.rs deleted file mode 100644 index 5a043d54b75..00000000000 --- a/rustfmt-core/tests/target/issue-2103.rs +++ /dev/null @@ -1,14 +0,0 @@ -struct X -where - i32: Sized, -{ - x: i32, -} - -struct X -// with comment -where - i32: Sized, -{ - x: i32, -} diff --git a/rustfmt-core/tests/target/issue-2111.rs b/rustfmt-core/tests/target/issue-2111.rs deleted file mode 100644 index 13303a736a3..00000000000 --- a/rustfmt-core/tests/target/issue-2111.rs +++ /dev/null @@ -1,26 +0,0 @@ -// rustfmt-normalize_comments: false - -// An import with single line comments. -use super::{DelayChoice, - Destinations, - Holding, - LodaModel, - MethodDescription, - ModelBehaviour, - ModelEdges, - ModelProperties, - ModelRequestGraph, - ModelSelector, - RequestDescription, - StringMap, - Switch, - // ModelMetaData, - // Generated, - // SecondsString, - // DateString, - // ModelConfiguration, - // ModelRequests, - // RestResponse, - // RestResponseCode, - // UniformHolding - SCHEMA_VERSIONS}; diff --git a/rustfmt-core/tests/target/issue-2123.rs b/rustfmt-core/tests/target/issue-2123.rs deleted file mode 100644 index 5e9917b4023..00000000000 --- a/rustfmt-core/tests/target/issue-2123.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-wrap_comments: true - -//hello -//world - -fn main() {} diff --git a/rustfmt-core/tests/target/issue-2164.rs b/rustfmt-core/tests/target/issue-2164.rs deleted file mode 100644 index ab1d7dfd37a..00000000000 --- a/rustfmt-core/tests/target/issue-2164.rs +++ /dev/null @@ -1,132 +0,0 @@ -// A stress test against code generated by bindgen. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct emacs_env_25 { - pub size: isize, - pub private_members: *mut emacs_env_private, - pub make_global_ref: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, any_reference: emacs_value) -> emacs_value, - >, - pub free_global_ref: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, global_reference: emacs_value), - >, - pub non_local_exit_check: - ::std::option::Option emacs_funcall_exit>, - pub non_local_exit_clear: ::std::option::Option, - pub non_local_exit_get: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - non_local_exit_symbol_out: *mut emacs_value, - non_local_exit_data_out: *mut emacs_value, - ) -> emacs_funcall_exit, - >, - pub non_local_exit_signal: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - non_local_exit_symbol: emacs_value, - non_local_exit_data: emacs_value, - ), - >, - pub non_local_exit_throw: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, tag: emacs_value, value: emacs_value), - >, - pub make_function: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - min_arity: isize, - max_arity: isize, - function: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - nargs: isize, - args: *mut emacs_value, - arg1: *mut ::libc::c_void, - ) -> emacs_value, - >, - documentation: *const ::libc::c_char, - data: *mut ::libc::c_void, - ) -> emacs_value, - >, - pub funcall: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - function: emacs_value, - nargs: isize, - args: *mut emacs_value, - ) -> emacs_value, - >, - pub intern: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, symbol_name: *const ::libc::c_char) - -> emacs_value, - >, - pub type_of: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> emacs_value, - >, - pub is_not_nil: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> bool, - >, - pub eq: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, a: emacs_value, b: emacs_value) -> bool, - >, - pub extract_integer: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> intmax_t, - >, - pub make_integer: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, value: intmax_t) -> emacs_value, - >, - pub extract_float: - ::std::option::Option f64>, - pub make_float: - ::std::option::Option emacs_value>, - pub copy_string_contents: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - value: emacs_value, - buffer: *mut ::libc::c_char, - size_inout: *mut isize, - ) -> bool, - >, - pub make_string: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, contents: *const ::libc::c_char, length: isize) - -> emacs_value, - >, - pub make_user_ptr: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - fin: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void), - >, - ptr: *mut ::libc::c_void, - ) -> emacs_value, - >, - pub get_user_ptr: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value) -> *mut ::libc::c_void, - >, - pub set_user_ptr: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value, ptr: *mut ::libc::c_void), - >, - pub get_user_finalizer: ::std::option::Option< - unsafe extern "C" fn( - arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value - ) -> ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value), - >, - >, - pub set_user_finalizer: ::std::option::Option< - unsafe extern "C" fn( - env: *mut emacs_env, - uptr: emacs_value, - fin: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void), - >, - ), - >, - pub vec_get: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize) -> emacs_value, - >, - pub vec_set: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize, val: emacs_value), - >, - pub vec_size: - ::std::option::Option isize>, -} diff --git a/rustfmt-core/tests/target/issue-2179.rs b/rustfmt-core/tests/target/issue-2179.rs deleted file mode 100644 index db8f9c557b4..00000000000 --- a/rustfmt-core/tests/target/issue-2179.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -fn issue_2179() { - let (opts, rustflags, clear_env_rust_log) = { - // We mustn't lock configuration for the whole build process - let rls_config = rls_config.lock().unwrap(); - - let opts = CargoOptions::new(&rls_config); - trace!("Cargo compilation options:\n{:?}", opts); - let rustflags = prepare_cargo_rustflags(&rls_config); - - // Warn about invalid specified bin target or package depending on current mode - // TODO: Return client notifications along with diagnostics to inform the user - if !rls_config.workspace_mode { - let cur_pkg_targets = ws.current().unwrap().targets(); - - if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { - let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); - if let None = bins.find(|x| x.name() == build_bin) { - warn!( - "cargo - couldn't find binary `{}` specified in `build_bin` configuration", - build_bin - ); - } - } - } else { - for package in &opts.package { - if let None = ws.members().find(|x| x.name() == package) { - warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); - } - } - } - - (opts, rustflags, rls_config.clear_env_rust_log) - }; -} diff --git a/rustfmt-core/tests/target/issue-2197.rs b/rustfmt-core/tests/target/issue-2197.rs deleted file mode 100644 index 76dbbefc3a7..00000000000 --- a/rustfmt-core/tests/target/issue-2197.rs +++ /dev/null @@ -1,18 +0,0 @@ -// rustfmt-max_width: 79 -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false - -/// ```rust -/// unsafe fn sum_sse2(x: i32x4) -> i32 { -/// let x = vendor::_mm_add_epi32( -/// x, -/// vendor::_mm_srli_si128(x.into(), 8).into(), -/// ); -/// let x = vendor::_mm_add_epi32( -/// x, -/// vendor::_mm_srli_si128(x.into(), 4).into(), -/// ); -/// vendor::_mm_cvtsi128_si32(x) -/// } -/// ``` -fn foo() {} diff --git a/rustfmt-core/tests/target/issue-2256.rs b/rustfmt-core/tests/target/issue-2256.rs deleted file mode 100644 index 4b546223f94..00000000000 --- a/rustfmt-core/tests/target/issue-2256.rs +++ /dev/null @@ -1,7 +0,0 @@ -// こんにちは -use std::borrow::Cow; - -/* comment */ -/* comment */ - -/* comment */ diff --git a/rustfmt-core/tests/target/issue-2324.rs b/rustfmt-core/tests/target/issue-2324.rs deleted file mode 100644 index 9211b24d81f..00000000000 --- a/rustfmt-core/tests/target/issue-2324.rs +++ /dev/null @@ -1,7 +0,0 @@ -// nested function calls with cast. -fn main() { - self.ptr - .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T); - self.ptr - .set(intrinsics::arith_offset(self.ptr.get(), mem::size_of::() as isize) as *mut u8); -} diff --git a/rustfmt-core/tests/target/issue-2329.rs b/rustfmt-core/tests/target/issue-2329.rs deleted file mode 100644 index e36e9546b24..00000000000 --- a/rustfmt-core/tests/target/issue-2329.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Comments with characters which must be represented by multibyte. - -// フー -use foo; -// バー -use bar; - -impl MyStruct { - // コメント - fn f1() {} // こんにちは - fn f2() {} // ありがとう - // コメント -} - -trait MyTrait { - // コメント - fn f1() {} // こんにちは - fn f2() {} // ありがとう - // コメント -} - -fn main() { - // コメント - let x = 1; // X - println!( - "x = {}", // xの値 - x, // X - ); - // コメント -} diff --git a/rustfmt-core/tests/target/issue-2342.rs b/rustfmt-core/tests/target/issue-2342.rs deleted file mode 100644 index f9c26857e15..00000000000 --- a/rustfmt-core/tests/target/issue-2342.rs +++ /dev/null @@ -1,6 +0,0 @@ -// rustfmt-max_width: 80 - -struct Foo { - #[cfg(feature = "serde")] - bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN -} diff --git a/rustfmt-core/tests/target/issue-2346.rs b/rustfmt-core/tests/target/issue-2346.rs deleted file mode 100644 index 07817221a51..00000000000 --- a/rustfmt-core/tests/target/issue-2346.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-normalize_comments: true -// the following empty comment should not have any trailing space added. -// -fn main() {} diff --git a/rustfmt-core/tests/target/issue-2401.rs b/rustfmt-core/tests/target/issue-2401.rs deleted file mode 100644 index ec8f27b732f..00000000000 --- a/rustfmt-core/tests/target/issue-2401.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-hard_tabs = true -// rustfmt-normalize_comments = true - -/// ``` -/// println!("Hello, World!"); -/// ``` -fn main() {} diff --git a/rustfmt-core/tests/target/issue-2446.rs b/rustfmt-core/tests/target/issue-2446.rs deleted file mode 100644 index be62e9c9c31..00000000000 --- a/rustfmt-core/tests/target/issue-2446.rs +++ /dev/null @@ -1,9 +0,0 @@ -enum Issue2446 { - V { - f: u8, // x - }, -} - -enum Issue2446TrailingCommentsOnly { - V { f: u8 /* */ }, -} diff --git a/rustfmt-core/tests/target/issue-2479.rs b/rustfmt-core/tests/target/issue-2479.rs deleted file mode 100644 index 3683ab22089..00000000000 --- a/rustfmt-core/tests/target/issue-2479.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Long attributes. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum POLARITYR { - #[doc = "Task mode: No effect on pin from OUT[n] task. Event mode: no IN[n] event generated on pin activity."] - NONE, - #[doc = "Task mode: Set pin from OUT[n] task. Event mode: Generate IN[n] event when rising edge on pin."] - LOTOHI, - #[doc = "Task mode: Clear pin from OUT[n] task. Event mode: Generate IN[n] event when falling edge on pin."] - HITOLO, - #[doc = "Task mode: Toggle pin from OUT[n]. Event mode: Generate IN[n] when any change on pin."] - TOGGLE, -} diff --git a/rustfmt-core/tests/target/issue-447.rs b/rustfmt-core/tests/target/issue-447.rs deleted file mode 100644 index d41cdb65cd0..00000000000 --- a/rustfmt-core/tests/target/issue-447.rs +++ /dev/null @@ -1,40 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - if - // shouldn't be dropped - // shouldn't be dropped - cond - // shouldn't be dropped - // shouldn't be dropped - { - } - // shouldn't be dropped - // shouldn't be dropped - else - // shouldn't be dropped - // shouldn't be dropped - if - // shouldn't be dropped - // shouldn't be dropped - cond - // shouldn't be dropped - // shouldn't be dropped - { - } - // shouldn't be dropped - // shouldn't be dropped - else - // shouldn't be dropped - // shouldn't be dropped - { - } - - if - // shouldn't be dropped - // shouldn't be dropped - let Some(x) = y - // shouldn't be dropped - // shouldn't be dropped - {} -} diff --git a/rustfmt-core/tests/target/issue-510.rs b/rustfmt-core/tests/target/issue-510.rs deleted file mode 100644 index a166b68498f..00000000000 --- a/rustfmt-core/tests/target/issue-510.rs +++ /dev/null @@ -1,41 +0,0 @@ -impl ISizeAndMarginsComputer for AbsoluteNonReplaced { - fn solve_inline_size_constraints( - &self, - block: &mut BlockFlow, - input: &ISizeConstraintInput, - ) -> ISizeConstraintSolution { - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match ( - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, - ) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size( - available_inline_size - (margin_start + margin_end), - ); - (Au(0), inline_size, margin_start, margin_end) - } - }; - - let (inline_start, inline_size, margin_inline_start, margin_inline_end) = - match (inline_start, inline_end, computed_inline_size) { - (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { - let margin_start = inline_start_margin.specified_or_zero(); - let margin_end = inline_end_margin.specified_or_zero(); - // Now it is the same situation as inline-start Specified and inline-end - // and inline-size Auto. - // - // Set inline-end to zero to calculate inline-size. - let inline_size = block.get_shrink_to_fit_inline_size( - available_inline_size - (margin_start + margin_end), - ); - (Au(0), inline_size, margin_start, margin_end) - } - }; - } -} diff --git a/rustfmt-core/tests/target/issue-64.rs b/rustfmt-core/tests/target/issue-64.rs deleted file mode 100644 index c0660630203..00000000000 --- a/rustfmt-core/tests/target/issue-64.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Regression test for issue 64 - -pub fn header_name() -> &'static str { - let name = ::header_name(); - let func = ::header_name; - name -} diff --git a/rustfmt-core/tests/target/issue-691.rs b/rustfmt-core/tests/target/issue-691.rs deleted file mode 100644 index 7473d070eff..00000000000 --- a/rustfmt-core/tests/target/issue-691.rs +++ /dev/null @@ -1,9 +0,0 @@ -// rustfmt-normalize_comments: true - -//! `std` or `core` and simply link to this library. In case the target -//! platform has no hardware -//! support for some operation, software implementations provided by this -//! library will be used automagically. -// TODO: provide instructions to override default libm link and how to link to -// this library. -fn foo() {} diff --git a/rustfmt-core/tests/target/issue-770.rs b/rustfmt-core/tests/target/issue-770.rs deleted file mode 100644 index 5fbedd7b734..00000000000 --- a/rustfmt-core/tests/target/issue-770.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - if false { - if false { - } else { - // A let binding here seems necessary to trigger it. - let _ = (); - } - } else if let false = false { - } -} diff --git a/rustfmt-core/tests/target/issue-811.rs b/rustfmt-core/tests/target/issue-811.rs deleted file mode 100644 index b7a89b5d0f9..00000000000 --- a/rustfmt-core/tests/target/issue-811.rs +++ /dev/null @@ -1,19 +0,0 @@ -trait FooTrait: Sized { - type Bar: BarTrait; -} - -trait BarTrait: Sized { - type Baz; - fn foo(); -} - -type Foo = <>::Bar as BarTrait>::Baz; -type Bar = >::Baz; - -fn some_func, U>() { - <>::Bar as BarTrait>::foo(); -} - -fn some_func>() { - >::foo(); -} diff --git a/rustfmt-core/tests/target/issue-831.rs b/rustfmt-core/tests/target/issue-831.rs deleted file mode 100644 index 1d6327c2158..00000000000 --- a/rustfmt-core/tests/target/issue-831.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - let y = a.iter().any(|x| { - println!("a"); - }) || b.iter().any(|x| { - println!("b"); - }) || c.iter().any(|x| { - println!("c"); - }); -} diff --git a/rustfmt-core/tests/target/issue-850.rs b/rustfmt-core/tests/target/issue-850.rs deleted file mode 100644 index c939716a6a8..00000000000 --- a/rustfmt-core/tests/target/issue-850.rs +++ /dev/null @@ -1 +0,0 @@ -const unsafe fn x() {} diff --git a/rustfmt-core/tests/target/issue-855.rs b/rustfmt-core/tests/target/issue-855.rs deleted file mode 100644 index 0430cc62954..00000000000 --- a/rustfmt-core/tests/target/issue-855.rs +++ /dev/null @@ -1,27 +0,0 @@ -fn main() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit { .. } - | Event::KeyDown { - keycode: Some(Keycode::Escape), - .. - } => break 'running, - } - } - } -} - -fn main2() { - 'running: loop { - for event in event_pump.poll_iter() { - match event { - Event::Quit { .. } - | Event::KeyDownXXXXXXXXXXXXX { - keycode: Some(Keycode::Escape), - .. - } => break 'running, - } - } - } -} diff --git a/rustfmt-core/tests/target/issue-913.rs b/rustfmt-core/tests/target/issue-913.rs deleted file mode 100644 index 2158b70a46f..00000000000 --- a/rustfmt-core/tests/target/issue-913.rs +++ /dev/null @@ -1,24 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -mod client { - impl Client { - fn test(self) -> Result<()> { - let next_state = match self.state { - State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { - let x = reformat.meeee(); - } - }; - - let next_state = match self.state { - State::V5(v5::State::Command(v5::comand::State::WriteVersion( - ref mut response, - ))) => { - // The pattern cannot be formatted in a way that the match stays - // within the column limit. The rewrite should therefore be - // skipped. - let x = dont.reformat.meeee(); - } - }; - } - } -} diff --git a/rustfmt-core/tests/target/issue-945.rs b/rustfmt-core/tests/target/issue-945.rs deleted file mode 100644 index d46c69a4f09..00000000000 --- a/rustfmt-core/tests/target/issue-945.rs +++ /dev/null @@ -1,17 +0,0 @@ -impl Bar { - default const unsafe fn foo() { - "hi" - } -} - -impl Baz { - default unsafe extern "C" fn foo() { - "hi" - } -} - -impl Foo for Bar { - default fn foo() { - "hi" - } -} diff --git a/rustfmt-core/tests/target/issue-977.rs b/rustfmt-core/tests/target/issue-977.rs deleted file mode 100644 index 9420054449d..00000000000 --- a/rustfmt-core/tests/target/issue-977.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-normalize_comments: true -// FIXME(#919) - -trait NameC { - // comment -} -struct FooC { /* comment */ } -enum MooC { - // comment -} -mod BarC { - // comment -} -extern "C" { - // comment -} diff --git a/rustfmt-core/tests/target/item-brace-style-always-next-line.rs b/rustfmt-core/tests/target/item-brace-style-always-next-line.rs deleted file mode 100644 index 531ac598683..00000000000 --- a/rustfmt-core/tests/target/item-brace-style-always-next-line.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-brace_style: AlwaysNextLine - -mod M -{ - enum A - { - A, - } - - struct B - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A - where - T: Copy, - { - A, - } - - struct B - where - T: Copy, - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C - where - T: Copy, {} - - struct D - where - T: Copy, {} -} diff --git a/rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs b/rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs deleted file mode 100644 index ef8dc028c2d..00000000000 --- a/rustfmt-core/tests/target/item-brace-style-prefer-same-line.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-brace_style: PreferSameLine - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - enum C {} - - struct D {} - - enum A - where - T: Copy, { - A, - } - - struct B - where - T: Copy, { - b: i32, - } - - enum C - where - T: Copy, {} - - struct D - where - T: Copy, {} -} diff --git a/rustfmt-core/tests/target/item-brace-style-same-line-where.rs b/rustfmt-core/tests/target/item-brace-style-same-line-where.rs deleted file mode 100644 index 9a275efc96e..00000000000 --- a/rustfmt-core/tests/target/item-brace-style-same-line-where.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-brace_style: SameLineWhere - -mod M { - enum A { - A, - } - - struct B { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C {} - - struct D {} - - enum A - where - T: Copy, - { - A, - } - - struct B - where - T: Copy, - { - b: i32, - } - - // For empty enums and structs, the brace remains on the same line. - enum C - where - T: Copy, {} - - struct D - where - T: Copy, {} -} diff --git a/rustfmt-core/tests/target/large-block.rs b/rustfmt-core/tests/target/large-block.rs deleted file mode 100644 index 09e9169f340..00000000000 --- a/rustfmt-core/tests/target/large-block.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn issue1351() { - std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ - static __STATIC_FMTSTR: &'static [&'static str] = &[]; - }); -} diff --git a/rustfmt-core/tests/target/large_vec.rs b/rustfmt-core/tests/target/large_vec.rs deleted file mode 100644 index 95d1fc43c03..00000000000 --- a/rustfmt-core/tests/target/large_vec.rs +++ /dev/null @@ -1,42 +0,0 @@ -// See #1470. - -impl Environment { - pub fn new_root() -> Rc> { - let mut env = Environment::new(); - let builtin_functions = &[ - ( - "println", - Function::NativeVoid( - CallSign { - num_params: 0, - variadic: true, - param_types: vec![], - }, - native_println, - ), - ), - ( - "run_http_server", - Function::NativeVoid( - CallSign { - num_params: 1, - variadic: false, - param_types: vec![Some(ConstraintType::Function)], - }, - native_run_http_server, - ), - ), - ( - "len", - Function::NativeReturning( - CallSign { - num_params: 1, - variadic: false, - param_types: vec![None], - }, - native_len, - ), - ), - ]; - } -} diff --git a/rustfmt-core/tests/target/lazy_static.rs b/rustfmt-core/tests/target/lazy_static.rs deleted file mode 100644 index edce6e7b894..00000000000 --- a/rustfmt-core/tests/target/lazy_static.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Format `lazy_static!`. - -lazy_static! { - static ref CONFIG_NAME_REGEX: regex::Regex = - regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); - static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) - .expect("Failed creating configuration value pattern"); -} - -// We need to be able to format `lazy_static!` without known syntax. -lazy_static!(xxx, yyyy, zzzzz); - -lazy_static!{} - -// #2354 -lazy_static! { - pub static ref Sbase64_encode_string: ::lisp::LispSubrRef = { - let subr = ::remacs_sys::Lisp_Subr { - header: ::remacs_sys::Lisp_Vectorlike_Header { - size: ((::remacs_sys::PseudovecType::PVEC_SUBR as ::libc::ptrdiff_t) - << ::remacs_sys::PSEUDOVECTOR_AREA_BITS), - }, - function: self::Fbase64_encode_string as *const ::libc::c_void, - min_args: 1i16, - max_args: 2i16, - symbol_name: (b"base64-encode-string\x00").as_ptr() as *const ::libc::c_char, - intspec: ::std::ptr::null(), - doc: ::std::ptr::null(), - lang: ::remacs_sys::Lisp_Subr_Lang_Rust, - }; - unsafe { - let ptr = ::remacs_sys::xmalloc(::std::mem::size_of::<::remacs_sys::Lisp_Subr>()) - as *mut ::remacs_sys::Lisp_Subr; - ::std::ptr::copy_nonoverlapping(&subr, ptr, 1); - ::std::mem::forget(subr); - ::lisp::ExternalPtr::new(ptr) - } - }; -} diff --git a/rustfmt-core/tests/target/long-fn-1.rs b/rustfmt-core/tests/target/long-fn-1.rs deleted file mode 100644 index c3d44de7c69..00000000000 --- a/rustfmt-core/tests/target/long-fn-1.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Tests that a function which is almost short enough, but not quite, gets -// formatted correctly. - -impl Foo { - fn some_input( - &mut self, - input: Input, - input_path: Option, - ) -> (Input, Option) { - } - - fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { - } -} - -// #1843 -#[allow(non_snake_case)] -pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash( -) -> bool { - false -} diff --git a/rustfmt-core/tests/target/long-match-arms-brace-newline.rs b/rustfmt-core/tests/target/long-match-arms-brace-newline.rs deleted file mode 100644 index aeb384e7203..00000000000 --- a/rustfmt-core/tests/target/long-match-arms-brace-newline.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-max_width: 80 -// rustfmt-control_brace_style: AlwaysNextLine - -fn main() { - match x - { - aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) - if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => - { - Ok(()) - } - _ => Err(x), - } -} diff --git a/rustfmt-core/tests/target/long_field_access.rs b/rustfmt-core/tests/target/long_field_access.rs deleted file mode 100644 index 349d2c2f639..00000000000 --- a/rustfmt-core/tests/target/long_field_access.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn f() { - block_flow.base.stacking_relative_position_of_display_port = - self.base.stacking_relative_position_of_display_port; -} diff --git a/rustfmt-core/tests/target/loop.rs b/rustfmt-core/tests/target/loop.rs deleted file mode 100644 index f669e7e2c58..00000000000 --- a/rustfmt-core/tests/target/loop.rs +++ /dev/null @@ -1,34 +0,0 @@ -fn main() { - loop { - return some_val; - } - - let x = loop { - do_forever(); - }; - - 'label: loop { - // Just comments - } - - 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value - { - } - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { - } - - while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { - } - - 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) - { - // do smth - } - - while let Some(i) = x.find('s') { - x.update(); - continue; - continue 'foo; - } -} diff --git a/rustfmt-core/tests/target/macro_not_expr.rs b/rustfmt-core/tests/target/macro_not_expr.rs deleted file mode 100644 index c76a6492a9d..00000000000 --- a/rustfmt-core/tests/target/macro_not_expr.rs +++ /dev/null @@ -1,7 +0,0 @@ -macro_rules! test { - ($($t: tt)*) => {}; -} - -fn main() { - test!( a : B => c d ); -} diff --git a/rustfmt-core/tests/target/macro_rules.rs b/rustfmt-core/tests/target/macro_rules.rs deleted file mode 100644 index 2136784dec7..00000000000 --- a/rustfmt-core/tests/target/macro_rules.rs +++ /dev/null @@ -1,105 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -macro_rules! m { - // a - ($expr: expr, $($func: ident)*) => {{ - let x = $expr; - $func(x) - }}; - - /* b */ - () => { - /* c */ - }; - - (@tag) => {}; - - // d - ($item: ident) => { - mod macro_item { - struct $item; - } - }; -} - -macro m2 { - // a - ($expr: expr, $($func: ident)*) => {{ - let x = $expr; - $func(x) - }} - - /* b */ - () => { - /* c */ - } - - (@tag) => {} - - // d - ($item: ident) => { - mod macro_item { - struct $item; - } - } -} - -// #2438, #2476 -macro_rules! m { - () => { - fn foo() { - this_line_is_98_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(); - } - }; -} -macro_rules! m { - () => { - fn foo() { - this_line_is_99_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ); - } - }; -} -macro_rules! m { - () => { - fn foo() { - this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ); - } - }; -} -macro_rules! m { - () => { - fn foo() { - this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( - ); - } - }; -} - -// #2439 -macro_rules! m { - ( - $line0_xxxxxxxxxxxxxxxxx: expr, - $line1_xxxxxxxxxxxxxxxxx: expr, - $line2_xxxxxxxxxxxxxxxxx: expr, - $line3_xxxxxxxxxxxxxxxxx: expr, - ) => {}; -} - -// #2466 -// Skip formatting `macro_rules!` that are not using `{}`. -macro_rules! m ( - () => () -); -macro_rules! m [ - () => () -]; - -// #2470 -macro foo($type_name: ident, $docs: expr) { - #[allow(non_camel_case_types)] - #[doc=$docs] - #[derive(Debug, Clone, Copy)] - pub struct $type_name; -} diff --git a/rustfmt-core/tests/target/macros.rs b/rustfmt-core/tests/target/macros.rs deleted file mode 100644 index 8db2fbb60ee..00000000000 --- a/rustfmt-core/tests/target/macros.rs +++ /dev/null @@ -1,917 +0,0 @@ -// rustfmt-normalize_comments: true -itemmacro!(this, is.now().formatted(yay)); - -itemmacro!( - really, - long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() - .is - .formatted() -); - -itemmacro!{this, is.bracket().formatted()} - -peg_file! modname("mygrammarfile.rustpeg"); - -fn main() { - foo!(); - - bar!(a, b, c); - - bar!(a, b, c,); - - baz!(1 + 2 + 3, quux.kaas()); - - quux!( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB - ); - - kaas!( - // comments - a, // post macro - b // another - ); - - trailingcomma!(a, b, c,); - // Preserve trailing comma only when necessary. - ok!(file.seek(SeekFrom::Start( - table.map(|table| fixture.offset(table)).unwrap_or(0), - ))); - - noexpr!( i am not an expression, OK? ); - - vec![a, b, c]; - - vec![ - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - AAAAAA, - BBBBB, - 5, - 100 - 30, - 1.33, - b, - b, - b, - ]; - - vec![a /* comment */]; - - // Trailing spaces after a comma - vec![a]; - - vec![a; b]; - vec![a; b]; - vec![a; b]; - - vec![a, b; c]; - vec![a; b, c]; - - vec![ - a; - (|x| { - let y = x + 1; - let z = y + 1; - z - })(2) - ]; - vec![ - a; - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - ]; - vec![a; unsafe { x + 1 }]; - - unknown_bracket_macro__comma_should_not_be_stripped![a,]; - - foo(makro!(1, 3)); - - hamkaas!{ () }; - - macrowithbraces! {dont, format, me} - - x!(fn); - - some_macro!(); - - some_macro![]; - - some_macro!{ - // comment - }; - - some_macro!{ - // comment - }; - - some_macro!( - // comment - not function like - ); - - // #1712 - let image = gray_image!( - 00, 01, 02; - 10, 11, 12; - 20, 21, 22); - - // #1092 - chain!(input, a: take!(max_size), || []); -} - -impl X { - empty_invoc!{} -} - -fn issue_1279() { - println!("dsfs"); // a comment -} - -fn issue_1555() { - let hello = &format!( - "HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", - "65454654654654654654654655464", "4" - ); -} - -fn issue1178() { - macro_rules! foo { - (#[$attr: meta] $name: ident) => {}; - } - - foo!( - #[doc = "bar"] - baz - ); -} - -fn issue1739() { - sql_function!( - add_rss_item, - add_rss_item_t, - ( - a: types::Integer, - b: types::Timestamptz, - c: types::Text, - d: types::Text, - e: types::Text - ) - ); - - w.slice_mut(s![ - .., - init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], - .. - ]).par_map_inplace(|el| *el = 0.); -} - -fn issue_1885() { - let threads = people - .into_iter() - .map(|name| { - chan_select! { - rx.recv() => {} - } - }) - .collect::>(); -} - -fn issue_1917() { - mod x { - quickcheck! { - fn test(a: String, s: String, b: String) -> TestResult { - if a.find(&s).is_none() { - - TestResult::from_bool(true) - } else { - TestResult::discard() - } - } - } - } -} - -fn issue_1921() { - // Macro with tabs. - lazy_static! { - static ref ONE: u32 = 1; - static ref TWO: u32 = 2; - static ref THREE: u32 = 3; - static ref FOUR: u32 = { - let mut acc = 1; - acc += 1; - acc += 2; - acc - }; - } -} - -// #1577 -fn issue1577() { - let json = json!({ - "foo": "bar", - }); -} - -gfx_pipeline!(pipe { - vbuf: gfx::VertexBuffer = (), - out: gfx::RenderTarget = "Target0", -}); - -// #1919 -#[test] -fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { - assert_eq!( - ::std::mem::size_of::>(), - 8usize, - concat!( - "Size of template specialization: ", - stringify!(HandleWithDtor<::std::os::raw::c_int>) - ) - ); - assert_eq!( - ::std::mem::align_of::>(), - 8usize, - concat!( - "Alignment of template specialization: ", - stringify!(HandleWithDtor<::std::os::raw::c_int>) - ) - ); -} - -// #878 -macro_rules! try_opt { - ($expr: expr) => { - match $expr { - Some(val) => val, - - None => { - return None; - } - } - }; -} - -// #2214 -// macro call whose argument is an array with trailing comma. -fn issue2214() { - make_test!( - str_searcher_ascii_haystack, - "bb", - "abbcbbd", - [ - Reject(0, 1), - Match(1, 3), - Reject(3, 4), - Match(4, 6), - Reject(6, 7), - ] - ); -} - -fn special_case_macros() { - let p = eprint!(); - let q = eprint!("{}", 1); - let r = eprint!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = eprint!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = eprintln!("{}", 1); - let r = eprintln!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = eprintln!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = format!("{}", 1); - let r = format!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = format!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = format_args!("{}", 1); - let r = format_args!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = format_args!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = print!("{}", 1); - let r = print!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = print!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = println!("{}", 1); - let r = println!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = println!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - let q = unreachable!("{}", 1); - let r = unreachable!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - let s = unreachable!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - debug!("{}", 1); - debug!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - debug!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - error!("{}", 1); - error!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - error!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - info!("{}", 1); - info!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - info!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - panic!("{}", 1); - panic!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - panic!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - warn!("{}", 1); - warn!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - ); - warn!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - assert!(); - assert!(result == 42); - assert!(result == 42, "Ahoy there, {}!", target); - assert!( - result == 42, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, - input, - expected - ); - assert!( - result == 42, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - assert_eq!(); - assert_eq!(left); - assert_eq!(left, right); - assert_eq!(left, right, "Ahoy there, {}!", target); - assert_eq!( - left, right, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, input, expected - ); - assert_eq!( - first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, - second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, - input, - expected - ); - assert_eq!( - left + 42, - right, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, - input, - expected - ); - assert_eq!( - left, - right, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - write!(&mut s, "Ahoy there, {}!", target); - write!( - &mut s, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, input, expected - ); - write!( - &mut s, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); - - writeln!(&mut s, "Ahoy there, {}!", target); - writeln!( - &mut s, - "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", - result, input, expected - ); - writeln!( - &mut s, - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26 - ); -} - -// #1209 -impl Foo { - /// foo - pub fn foo(&self) -> Bar {} -} - -// #819 -fn macro_in_pattern_position() { - let x = match y { - foo!() => (), - bar!(a, b, c) => (), - bar!(a, b, c,) => (), - baz!(1 + 2 + 3, quux.kaas()) => (), - quux!( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB - ) => (), - }; -} - -macro foo() {} - -pub macro bar($x: ident + $y: expr;) { - fn foo($x: Foo) { - long_function( - a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), - $x.bar($y), - ); - } -} - -macro foo() { - // a comment - fn foo() { - // another comment - bar(); - } -} - -macro lex_err($kind: ident $(, $body: expr)*) { - Err(QlError::LexError(LexError::$kind($($body,)*))) -} - -// Preserve trailing comma on item-level macro with `()` or `[]`. -methods![get, post, delete,]; -methods!(get, post, delete,); diff --git a/rustfmt-core/tests/target/markdown-comment-with-options.rs b/rustfmt-core/tests/target/markdown-comment-with-options.rs deleted file mode 100644 index ede2bc0d035..00000000000 --- a/rustfmt-core/tests/target/markdown-comment-with-options.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-wrap_comments: true - -// Preserve two trailing whitespaces in doc comment, -// but trim any whitespaces in normal comment. - -//! hello world -//! hello world - -/// hello world -/// hello world -/// hello world -fn foo() { - // hello world - // hello world - let x = 3; - println!("x = {}", x); -} diff --git a/rustfmt-core/tests/target/markdown-comment.rs b/rustfmt-core/tests/target/markdown-comment.rs deleted file mode 100644 index 71a9921d286..00000000000 --- a/rustfmt-core/tests/target/markdown-comment.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Preserve two trailing whitespaces in doc comment, -// but trim any whitespaces in normal comment. - -//! hello world -//! hello world - -/// hello world -/// hello world -/// hello world -fn foo() { - // hello world - // hello world - let x = 3; - println!("x = {}", x); -} diff --git a/rustfmt-core/tests/target/match-block-trailing-comma.rs b/rustfmt-core/tests/target/match-block-trailing-comma.rs deleted file mode 100644 index 44d1f289f8e..00000000000 --- a/rustfmt-core/tests/target/match-block-trailing-comma.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - }, - b => ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - } -} diff --git a/rustfmt-core/tests/target/match-nowrap-trailing-comma.rs b/rustfmt-core/tests/target/match-nowrap-trailing-comma.rs deleted file mode 100644 index 19ef2144822..00000000000 --- a/rustfmt-core/tests/target/match-nowrap-trailing-comma.rs +++ /dev/null @@ -1,17 +0,0 @@ -// rustfmt-match_arm_blocks: false -// rustfmt-match_block_trailing_comma: true -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => { - "line1"; - "line2" - }, - b => ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - } -} diff --git a/rustfmt-core/tests/target/match-nowrap.rs b/rustfmt-core/tests/target/match-nowrap.rs deleted file mode 100644 index 9e674b1e2f5..00000000000 --- a/rustfmt-core/tests/target/match-nowrap.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-match_arm_blocks: false -// Match expressions, no unwrapping of block arms or wrapping of multiline -// expressions. - -fn foo() { - match x { - a => foo(), - b => ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - } -} diff --git a/rustfmt-core/tests/target/match.rs b/rustfmt-core/tests/target/match.rs deleted file mode 100644 index 72ffa966c01..00000000000 --- a/rustfmt-core/tests/target/match.rs +++ /dev/null @@ -1,495 +0,0 @@ -// rustfmt-normalize_comments: true -// Match expressions. - -fn foo() { - // A match expression. - match x { - // Some comment. - a => foo(), - b if 0 < 42 => foo(), - c => { - // Another comment. - // Comment. - an_expression; - foo() - } - Foo(ref bar) => { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } - Pattern1 | Pattern2 | Pattern3 => false, - Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn - | Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => blah, - Patternnnnnnnnnnnnnnnnnnn - | Patternnnnnnnnnnnnnnnnnnn - | Patternnnnnnnnnnnnnnnnnnn - | Patternnnnnnnnnnnnnnnnnnn => meh, - - Patternnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => { - meh - } - - Patternnnnnnnnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnnnnnnnn - if looooooooooooooooooooooooooooooooooooooooong_guard => - { - meh - } - - // Test that earlier patterns can take the guard space - (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) - | Patternnnnnnnnnnnnnnnnnnnnnnnnn - if loooooooooooooooooooooooooooooooooooooooooong_guard => {} - - _ => {} - ast::PathParameters::AngleBracketedParameters(ref data) - if data.lifetimes.len() > 0 || data.types.len() > 0 || data.bindings.len() > 0 => {} - } - - let whatever = match something { - /// DOC COMMENT! - Some(_) => 42, - // Comment on an attribute. - #[an_attribute] - // Comment after an attribute. - None => 0, - #[rustfmt_skip] - Blurb => { } - }; -} - -// Test that a match on an overflow line is laid out properly. -fn main() { - let sub_span = - match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { - Some(sub_span) => Some(sub_span), - None => sub_span, - }; -} - -// Test that one-line bodies align. -fn main() { - match r { - Variableeeeeeeeeeeeeeeeee => ( - "variable", - vec!["id", "name", "qualname", "value", "type", "scopeid"], - true, - true, - ), - Enummmmmmmmmmmmmmmmmmmmm => ( - "enum", - vec!["id", "qualname", "scopeid", "value"], - true, - true, - ), - Variantttttttttttttttttttttttt => ( - "variant", - vec!["id", "name", "qualname", "type", "value", "scopeid"], - true, - true, - ), - }; - - match x { - y => { /*Block with comment. Preserve me.*/ } - z => { - stmt(); - } - } -} - -fn matches() { - match 1 { - -1 => 10, - 1 => 1, // foo - 2 => 2, - // bar - 3 => 3, - _ => 0, // baz - } -} - -fn match_skip() { - let _ = match Some(1) { - #[rustfmt_skip] - Some( n ) => n, - None => 1, - }; -} - -fn issue339() { - match a { - b => {} - c => {} - d => {} - e => {} - // collapsing here is safe - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} - // collapsing here exceeds line length - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { - } - h => { - // comment above block - } - i => {} // comment below block - j => { - // comment inside block - } - j2 => { - // comments inside... - } // ... and after - // TODO uncomment when vertical whitespace is handled better - // k => { - // - // // comment with WS above - // } - // l => { - // // comment with ws below - // - // } - m => {} - n => {} - o => {} - p => { - // Dont collapse me - } - q => {} - r => {} - s => 0, // s comment - // t comment - t => 1, - u => 2, - v => {} /* funky block - * comment */ - /* final comment */ - } -} - -fn issue355() { - match mac { - a => println!("a", b), - b => vec![1, 2], - c => vec![3; 4], - d => println!("a", b), - e => vec![1, 2], - f => vec![3; 4], - h => println!("a", b), // h comment - i => vec![1, 2], // i comment - j => vec![3; 4], // j comment - // k comment - k => println!("a", b), - // l comment - l => vec![1, 2], - // m comment - m => vec![3; 4], - // Rewrite splits macro - nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { - println!("a", b) - } - // Rewrite splits macro - oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => { - vec![1, 2] - } - // Macro support fails to recognise this macro as splittable - // We push the whole expr to a new line, TODO split this macro as well - pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { - vec![3; 4] - } - // q, r and s: Rewrite splits match arm - qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { - println!("a", b) - } - rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => { - vec![1, 2] - } - ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { - vec![3; 4] - } - // Funky bracketing styles - t => println!{"a", b}, - u => vec![1, 2], - v => vec![3; 4], - w => println!["a", b], - x => vec![1, 2], - y => vec![3; 4], - // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec![1, 2], // comment - vc => vec![3; 4], // comment - wc => println!["a", b], // comment - xc => vec![1, 2], // comment - yc => vec![3; 4], // comment - yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( - aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd, - ), - } -} - -fn issue280() { - { - match x { - CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => { - ch == '\n' - } - ast::ItemConst(ref typ, ref expr) => { - self.process_static_or_const_item(item, &typ, &expr) - } - } - } -} - -fn issue383() { - match resolution.last_private { - LastImport { .. } => false, - _ => true, - }; -} - -fn issue507() { - match 1 { - 1 => unsafe { std::intrinsics::abort() }, - _ => (), - } -} - -fn issue508() { - match s.type_id() { - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLCanvasElement, - ))) => true, - Some(NodeTypeId::Element(ElementTypeId::HTMLElement( - HTMLElementTypeId::HTMLObjectElement, - ))) => s.has_object_data(), - Some(NodeTypeId::Element(_)) => false, - } -} - -fn issue496() { - { - { - { - match def { - def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { - match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { - Some(const_expr) => x, - } - } - } - } - } - } -} - -fn issue494() { - { - match stmt.node { - hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { - result.push(StmtRef::Mirror(Box::new(Stmt { - span: stmt.span, - kind: StmtKind::Expr { - scope: cx.tcx.region_maps.node_extent(id), - expr: expr.to_ref(), - }, - }))) - } - } - } -} - -fn issue386() { - match foo { - BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, - BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr - | BiShl | BiShr => false, - } -} - -fn guards() { - match foo { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if foooooooooooooo && barrrrrrrrrrrr => {} - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if fooooooooooooooooooooo - && (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - || cccccccccccccccccccccccccccccccccccccccc) => {} - } -} - -fn issue1371() { - Some(match type_ { - sfEvtClosed => Closed, - sfEvtResized => { - let e = unsafe { *event.size.as_ref() }; - - Resized { - width: e.width, - height: e.height, - } - } - sfEvtLostFocus => LostFocus, - sfEvtGainedFocus => GainedFocus, - sfEvtTextEntered => TextEntered { - unicode: unsafe { - ::std::char::from_u32((*event.text.as_ref()).unicode) - .expect("Invalid unicode encountered on TextEntered event") - }, - }, - sfEvtKeyPressed => { - let e = unsafe { event.key.as_ref() }; - - KeyPressed { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - sfEvtKeyReleased => { - let e = unsafe { event.key.as_ref() }; - - KeyReleased { - code: unsafe { ::std::mem::transmute(e.code) }, - alt: e.alt.to_bool(), - ctrl: e.control.to_bool(), - shift: e.shift.to_bool(), - system: e.system.to_bool(), - } - } - }) -} - -fn issue1395() { - let bar = Some(true); - let foo = Some(true); - let mut x = false; - bar.and_then(|_| match foo { - None => None, - Some(b) => { - x = true; - Some(b) - } - }); -} - -fn issue1456() { - Ok(Recording { - artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { - Nodeset(nodeset) => { - let res: Result, ReadError> = nodeset - .iter() - .map(|node| { - XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) - }) - .collect(); - res? - } - _ => Vec::new(), - }, - }) -} - -fn issue1460() { - let _ = match foo { - REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => { - "internal_spec_insert_internal_spec_insert_internal_spec_insert" - } - _ => "reorder_something", - }; -} - -fn issue525() { - foobar( - f, - "{}", - match *self { - TaskState::Started => "started", - TaskState::Success => "success", - TaskState::Failed => "failed", - }, - ); -} - -// #1838, #1839 -fn match_with_near_max_width() { - let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { - _ => unimplemented!(), - }; - - let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { - _ => unimplemented!(), - }; - - let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression - { - _ => unimplemented!(), - }; - match m { - Variant::Tag - | Variant::Tag2 - | Variant::Tag3 - | Variant::Tag4 - | Variant::Tag5 - | Variant::Tag6 => {} - } -} - -fn match_with_trailing_spaces() { - match x { - #![allow(simple_match)] - Some(..) => 0, - None => 1, - } -} - -fn issue_2099() { - let a = match x {}; - let b = match x {}; - - match x {} -} - -// #2021 -impl<'tcx> Const<'tcx> { - pub fn from_constval<'a>() -> Const<'tcx> { - let val = match *cv { - ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!( - "MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", - cv - ), - }; - } -} - -// #2151 -fn issue_2151() { - match either { - x => {} - y => (), - } -} - -// #2152 -fn issue_2152() { - match m { - "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" - if true => {} - "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => { - true - } - } -} - -// #2462 -// Preserve a `|` at the beginning of a match arm. -fn match_with_beginning_vert() { - let x = Foo::A; - match x { - | Foo::A | Foo::B => println!("AB"), - | Foo::C => println!("C"), - } -} diff --git a/rustfmt-core/tests/target/max-line-length-in-chars.rs b/rustfmt-core/tests/target/max-line-length-in-chars.rs deleted file mode 100644 index d49fbb7e30e..00000000000 --- a/rustfmt-core/tests/target/max-line-length-in-chars.rs +++ /dev/null @@ -1,4 +0,0 @@ -// rustfmt-max_width: 25 - -// абвгдеёжзийклмнопрст -fn main() {} diff --git a/rustfmt-core/tests/target/mod-1.rs b/rustfmt-core/tests/target/mod-1.rs deleted file mode 100644 index a5d186c5df7..00000000000 --- a/rustfmt-core/tests/target/mod-1.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Deeply indented modules. - -mod foo { - mod bar { - mod baz {} - } -} - -mod foo { - mod bar { - mod baz { - fn foo() { - bar() - } - } - } - - mod qux {} -} - -mod boxed { - pub use std::boxed::{Box, HEAP}; -} - -pub mod x { - pub fn freopen( - filename: *const c_char, - mode: *const c_char, - mode2: *const c_char, - mode3: *const c_char, - file: *mut FILE, - ) -> *mut FILE { - } -} - -mod y { - // sup boooooiiii -} diff --git a/rustfmt-core/tests/target/mod-2.rs b/rustfmt-core/tests/target/mod-2.rs deleted file mode 100644 index 1a093bd5201..00000000000 --- a/rustfmt-core/tests/target/mod-2.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Some nested mods - -#[cfg(test)] -mod nestedmod; -pub mod no_new_line_beginning; diff --git a/rustfmt-core/tests/target/mod_skip_child.rs b/rustfmt-core/tests/target/mod_skip_child.rs deleted file mode 100644 index d48c4a37e81..00000000000 --- a/rustfmt-core/tests/target/mod_skip_child.rs +++ /dev/null @@ -1,2 +0,0 @@ -// rustfmt-skip_children: true -mod nested_skipped; diff --git a/rustfmt-core/tests/target/mulit-file.rs b/rustfmt-core/tests/target/mulit-file.rs deleted file mode 100644 index 1f829b36f3f..00000000000 --- a/rustfmt-core/tests/target/mulit-file.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Tests that where a single file is referred to in multiple places, we don't -// crash. - -#[cfg(all(foo))] -#[path = "closure.rs"] -pub mod imp; - -#[cfg(all(bar))] -#[path = "closure.rs"] -pub mod imp; diff --git a/rustfmt-core/tests/target/multiple.rs b/rustfmt-core/tests/target/multiple.rs deleted file mode 100644 index 0c330d80a56..00000000000 --- a/rustfmt-core/tests/target/multiple.rs +++ /dev/null @@ -1,178 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-format_strings: true -// Test of lots of random stuff. -// FIXME split this into multiple, self-contained tests. - -#[attr1] -extern crate foo; -#[attr2] -#[attr3] -extern crate foo; -#[attr1] -extern crate foo; -#[attr2] -#[attr3] -extern crate foo; - -use std::cell::*; -use std::{self, any, ascii, borrow, borrow, borrow, borrow, borrow, borrow, borrow, borrow, - borrow, borrow, borrow, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, - boxed, char, char, char, char, char, char, char, char, char, char}; - -mod doc; -mod other; - -// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff -// ffffffffffffffffffffffffffffffffffffffffff - -fn foo(a: isize, b: u32 /* blah blah */, c: f64) {} - -fn foo() -> Box -where - 'a: 'b, - for<'a> D<'b>: 'a, -{ - hello!() -} - -fn baz< - 'a: 'b, // comment on 'a - T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, // comment on T ->( - a: A, - b: B, // comment on b - c: C, -) -> Bob { - #[attr1] - extern crate foo; - #[attr2] - #[attr3] - extern crate foo; - #[attr1] - extern crate foo; - #[attr2] - #[attr3] - extern crate foo; -} - -#[rustfmt_skip] -fn qux(a: dadsfa, // Comment 1 - b: sdfasdfa, // Comment 2 - c: dsfdsafa) // Comment 3 -{ - -} - -/// Blah blah blah. -impl Bar { - fn foo( - &mut self, - a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a - b: sdfasdfsdfasfs, // closing comment - ) -> isize { - } - - /// Blah blah blah. - pub fn f2(self) { - (foo, bar) - } - - #[an_attribute] - fn f3(self) -> Dog {} -} - -/// The `nodes` and `edges` method each return instantiations of -/// `Cow<[T]>` to leave implementers the freedom to create - -/// entirely new vectors or to pass back slices into internally owned -/// vectors. -pub trait GraphWalk<'a, N, E> { - /// Returns all the nodes in this graph. - fn nodes(&'a self) -> Nodes<'a, N>; - /// Returns all of the edges in this graph. - fn edges(&'a self) -> Edges<'a, E>; - /// The source node for `edge`. - fn source(&'a self, edge: &E) -> N; - /// The target node for `edge`. - fn target(&'a self, edge: &E) -> N; -} - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, -} - -struct Bar; - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -fn foo(ann: &'a (PpAnn + 'a)) {} - -fn main() { - for i in 0i32..4 { - println!("{}", i); - } - - while true { - hello(); - } - - let rc = Cell::new( - 42usize, - 42usize, - Cell::new( - 42usize, - remaining_widthremaining_widthremaining_widthremaining_width, - ), - 42usize, - ); - let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment - let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ - abcd abcd"; - let s = expand(a, b); -} - -fn deconstruct() -> ( - SocketAddr, - Method, - Headers, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -) { -} - -fn deconstruct( - foo: Bar, -) -> ( - SocketAddr, - Method, - Headers, - RequestUri, - HttpVersion, - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -) { -} - -#[rustfmt_skip] -mod a{ -fn foo(x: T) { - let x: T = dfasdf; -} -} diff --git a/rustfmt-core/tests/target/nested-if-else.rs b/rustfmt-core/tests/target/nested-if-else.rs deleted file mode 100644 index 9a54789ddcd..00000000000 --- a/rustfmt-core/tests/target/nested-if-else.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn issue1518() { - Some(Object { - field: if a { - a_thing - } else if b { - b_thing - } else { - c_thing - }, - }) -} diff --git a/rustfmt-core/tests/target/nested-visual-block.rs b/rustfmt-core/tests/target/nested-visual-block.rs deleted file mode 100644 index 95b9bc2dea2..00000000000 --- a/rustfmt-core/tests/target/nested-visual-block.rs +++ /dev/null @@ -1,59 +0,0 @@ -fn main() { - // #1078 - let items = itemize_list( - context.codemap, - field_iter, - "}", - |item| match *item { - StructLitField::Regular(ref field) => field.span.lo(), - StructLitField::Base(ref expr) => { - let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); - let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); - let pos = snippet.find_uncommented("..").unwrap(); - last_field_hi + BytePos(pos as u32) - } - }, - |item| match *item { - StructLitField::Regular(ref field) => field.span.hi(), - StructLitField::Base(ref expr) => expr.span.hi(), - }, - |item| { - match *item { - StructLitField::Regular(ref field) => rewrite_field( - inner_context, - &field, - &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent), - ), - StructLitField::Base(ref expr) => { - // 2 = .. - expr.rewrite( - inner_context, - &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2), - ).map(|s| format!("..{}", s)) - } - } - }, - context.codemap.span_after(span, "{"), - span.hi(), - ); - - // #1580 - self.0.pool.execute(move || { - let _timer = segments.0.rotate_timer.time(); - if let Err(e) = segments.rotate_async(wal) { - error!("error compacting segment storage WAL", unsafe { error: e.display() }); - } - }); - - // #1581 - bootstrap.checks.register("PERSISTED_LOCATIONS", move || { - if locations2.0.inner_mut.lock().poisoned { - Check::new( - State::Error, - "Persisted location storage is poisoned due to a write failure", - ) - } else { - Check::new(State::Healthy, "Persisted location storage is healthy") - } - }); -} diff --git a/rustfmt-core/tests/target/nested_skipped/mod.rs b/rustfmt-core/tests/target/nested_skipped/mod.rs deleted file mode 100644 index 0ab6f081e44..00000000000 --- a/rustfmt-core/tests/target/nested_skipped/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn ugly() { - 92; -} diff --git a/rustfmt-core/tests/target/nestedmod/mod.rs b/rustfmt-core/tests/target/nestedmod/mod.rs deleted file mode 100644 index 1df46293184..00000000000 --- a/rustfmt-core/tests/target/nestedmod/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -mod mod2a; -mod mod2b; - -mod mymod1 { - use mod2a::{Bar, Foo}; - mod mod3a; -} - -#[path = "mod2c.rs"] -mod mymod2; - -mod submod2; diff --git a/rustfmt-core/tests/target/nestedmod/mod2a.rs b/rustfmt-core/tests/target/nestedmod/mod2a.rs deleted file mode 100644 index 5df457a8316..00000000000 --- a/rustfmt-core/tests/target/nestedmod/mod2a.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This is an empty file containing only -// comments - -// ................... diff --git a/rustfmt-core/tests/target/nestedmod/mod2b.rs b/rustfmt-core/tests/target/nestedmod/mod2b.rs deleted file mode 100644 index 9b6ea844e65..00000000000 --- a/rustfmt-core/tests/target/nestedmod/mod2b.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[path = "mod2a.rs"] -mod c; diff --git a/rustfmt-core/tests/target/nestedmod/mod2c.rs b/rustfmt-core/tests/target/nestedmod/mod2c.rs deleted file mode 100644 index 7db4572e777..00000000000 --- a/rustfmt-core/tests/target/nestedmod/mod2c.rs +++ /dev/null @@ -1,3 +0,0 @@ -// A standard mod - -fn a() {} diff --git a/rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs b/rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs deleted file mode 100644 index ae09d8ddac0..00000000000 --- a/rustfmt-core/tests/target/nestedmod/mymod1/mod3a.rs +++ /dev/null @@ -1,2 +0,0 @@ -// Another mod -fn a() {} diff --git a/rustfmt-core/tests/target/nestedmod/submod2/a.rs b/rustfmt-core/tests/target/nestedmod/submod2/a.rs deleted file mode 100644 index 120b17145e3..00000000000 --- a/rustfmt-core/tests/target/nestedmod/submod2/a.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Yet Another mod -// Nested - -use c::a; - -fn foo() {} diff --git a/rustfmt-core/tests/target/nestedmod/submod2/mod.rs b/rustfmt-core/tests/target/nestedmod/submod2/mod.rs deleted file mode 100644 index 52f8be91022..00000000000 --- a/rustfmt-core/tests/target/nestedmod/submod2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Another mod - -mod a; - -use a::a; diff --git a/rustfmt-core/tests/target/no_new_line_beginning.rs b/rustfmt-core/tests/target/no_new_line_beginning.rs deleted file mode 100644 index f328e4d9d04..00000000000 --- a/rustfmt-core/tests/target/no_new_line_beginning.rs +++ /dev/null @@ -1 +0,0 @@ -fn main() {} diff --git a/rustfmt-core/tests/target/other.rs b/rustfmt-core/tests/target/other.rs deleted file mode 100644 index dfce84fcdc4..00000000000 --- a/rustfmt-core/tests/target/other.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Part of multiple.rs - -fn bob() { - println!("hello other!"); -} diff --git a/rustfmt-core/tests/target/paths.rs b/rustfmt-core/tests/target/paths.rs deleted file mode 100644 index 0d2ba797eb7..00000000000 --- a/rustfmt-core/tests/target/paths.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-normalize_comments: true - -fn main() { - let constellation_chan = - Constellation::::start( - compositor_proxy, - resource_task, - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - devtools_chan, - storage_task, - supports_clipboard, - ); - - Quux::< - ParamOne, // Comment 1 - ParamTwo, // Comment 2 - >::some_func(); - - <*mut JSObject>::relocate(entry); - - let x: Foo; - let x: Foo/*::*/; -} - -fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {} diff --git a/rustfmt-core/tests/target/pattern-condense-wildcards.rs b/rustfmt-core/tests/target/pattern-condense-wildcards.rs deleted file mode 100644 index 39f99d9e123..00000000000 --- a/rustfmt-core/tests/target/pattern-condense-wildcards.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-condense_wildcard_suffixes: true - -fn main() { - match x { - Butt(..) => "hah", - Tup(_) => "nah", - Quad(_, _, x, _) => " also no rewrite", - Quad(x, ..) => "condense me pls", - Weird(x, _, _, /* dont condense before */ ..) => "pls work", - } -} diff --git a/rustfmt-core/tests/target/pattern.rs b/rustfmt-core/tests/target/pattern.rs deleted file mode 100644 index 6c62affb848..00000000000 --- a/rustfmt-core/tests/target/pattern.rs +++ /dev/null @@ -1,77 +0,0 @@ -// rustfmt-normalize_comments: true -fn main() { - let z = match x { - "pat1" => 1, - (ref x, ref mut y /* comment */) => 2, - }; - - if let ::CONST = ident { - do_smth(); - } - - let Some(ref xyz /* comment! */) = opt; - - if let None = opt2 { - panic!("oh noes"); - } - - let foo @ bar(f) = 42; - let a::foo(..) = 42; - let [] = 42; - let [a.., b, c] = 42; - let [a, b, c..] = 42; - let [a, b, c, d.., e, f, g] = 42; - let foo {} = 42; - let foo { .. } = 42; - let foo { x, y: ref foo, .. } = 42; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - .. - } = 42; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - } = 42; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - .. - }; - let foo { - x, - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, - }; -} - -impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { - fn mutate_fragment(&mut self, fragment: &mut Fragment) { - match **info { - GeneratedContentInfo::ContentItem(ContentItem::Counter( - ref counter_name, - counter_style, - )) => {} - } - } -} - -fn issue_1319() { - if let (Event { .. }, ..) = ev_state {} -} - -fn issue_1874() { - if let Some(()) = x { - y - } -} - -fn combine_patterns() { - let x = match y { - Some(Some(Foo { - z: Bar(..), - a: Bar(..), - b: Bar(..), - })) => z, - _ => return, - }; -} diff --git a/rustfmt-core/tests/target/pub-restricted.rs b/rustfmt-core/tests/target/pub-restricted.rs deleted file mode 100644 index 8cc2ade612a..00000000000 --- a/rustfmt-core/tests/target/pub-restricted.rs +++ /dev/null @@ -1,64 +0,0 @@ -pub(super) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(crate) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -crate enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(in global::path::to::some_mod) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} - -pub(in local::path::to::some_mod) enum WriteState { - WriteId { - id: U64Writer, - size: U64Writer, - payload: Option>, - }, - WriteSize { - size: U64Writer, - payload: Option>, - }, - WriteData(Writer), -} diff --git a/rustfmt-core/tests/target/remove_blank_lines.rs b/rustfmt-core/tests/target/remove_blank_lines.rs deleted file mode 100644 index 89b18e40b83..00000000000 --- a/rustfmt-core/tests/target/remove_blank_lines.rs +++ /dev/null @@ -1,28 +0,0 @@ -fn main() { - let x = 1; - - let y = 2; - - println!("x + y = {}", x + y); -} - -fn foo() { - #![attribute] - - let x = 1; - - // comment -} -// comment after item - -// comment before item -fn bar() { - let x = 1; - // comment after statement - - // comment before statment - let y = 2; - let z = 3; - - println!("x + y + z = {}", x + y + z); -} diff --git a/rustfmt-core/tests/target/single-line-if-else.rs b/rustfmt-core/tests/target/single-line-if-else.rs deleted file mode 100644 index 98fd793cba2..00000000000 --- a/rustfmt-core/tests/target/single-line-if-else.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Format if-else expressions on a single line, when possible. - -fn main() { - let a = if 1 > 2 { unreachable!() } else { 10 }; - - let a = if x { - 1 - } else if y { - 2 - } else { - 3 - }; - - let b = if cond() { - 5 - } else { - // Brief comment. - 10 - }; - - let c = if cond() { - statement(); - - 5 - } else { - 10 - }; - - let d = if let Some(val) = turbo { - "cool" - } else { - "beans" - }; - - if cond() { - statement(); - } else { - other_statement(); - } - - if true { - do_something() - } - - let x = if veeeeeeeeery_loooooong_condition() { - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - } else { - bbbbbbbbbb - }; - - let x = if veeeeeeeeery_loooooong_condition() { - aaaaaaaaaaaaaaaaaaaaaaaaa - } else { - bbbbbbbbbb - }; - - funk(if test() { 1 } else { 2 }, arg2); -} diff --git a/rustfmt-core/tests/target/skip.rs b/rustfmt-core/tests/target/skip.rs deleted file mode 100644 index 28897ade56f..00000000000 --- a/rustfmt-core/tests/target/skip.rs +++ /dev/null @@ -1,87 +0,0 @@ -// Test the skip attribute works - -#[rustfmt_skip] -fn foo() { badly; formatted; stuff -; } - -#[rustfmt_skip] -trait Foo -{ -fn foo( -); -} - -impl LateLintPass for UsedUnderscoreBinding { - #[cfg_attr(rustfmt, rustfmt_skip)] - fn check_expr() { // comment - } -} - -fn issue1346() { - #[cfg_attr(rustfmt, rustfmt_skip)] - Box::new(self.inner.call(req).then(move |result| { - match result { - Ok(resp) => Box::new(future::done(Ok(resp))), - Err(e) => { - try_error!(clo_stderr, "{}", e); - Box::new(future::err(e)) - } - } - })) -} - -fn skip_on_statements() { - // Outside block - #[rustfmt_skip] - { - foo; bar; - // junk - } - - { - // Inside block - #![rustfmt_skip] - foo; bar; - // junk - } - - // Semi - #[cfg_attr(rustfmt, rustfmt_skip)] - foo( - 1, 2, 3, 4, - 1, 2, - 1, 2, 3, - ); - - // Local - #[cfg_attr(rustfmt, rustfmt_skip)] - let x = foo( a, b , c); - - // Item - #[cfg_attr(rustfmt, rustfmt_skip)] - use foobar ; - - // Mac - #[cfg_attr(rustfmt, rustfmt_skip)] - vec![ - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, 4, - 1, 2, 3, - 1, - 1, 2, - 1, - ]; - - // Expr - #[cfg_attr(rustfmt, rustfmt_skip)] - foo( a, b , c) -} - -// Check that the skip attribute applies to other attributes. -#[rustfmt_skip] -#[cfg -( a , b -)] -fn -main() {} diff --git a/rustfmt-core/tests/target/skip_mod.rs b/rustfmt-core/tests/target/skip_mod.rs deleted file mode 100644 index 38ece8f070d..00000000000 --- a/rustfmt-core/tests/target/skip_mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![rustfmt_skip] -use a :: b -; diff --git a/rustfmt-core/tests/target/soft-wrapping.rs b/rustfmt-core/tests/target/soft-wrapping.rs deleted file mode 100644 index 58f3557fbe2..00000000000 --- a/rustfmt-core/tests/target/soft-wrapping.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-wrap_comments: true -// rustfmt-max_width: 80 -// Soft wrapping for comments. - -// #535, soft wrapping for comments -// Compare the lowest `f32` of both inputs for greater than or equal. The -// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits -// off the result are the upper 96 bits of `a`. - -/// Compare the lowest `f32` of both inputs for greater than or equal. The -/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is -/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits -/// off the result are the upper 96 bits of `a`. -fn foo() {} diff --git a/rustfmt-core/tests/target/space-not-before-newline.rs b/rustfmt-core/tests/target/space-not-before-newline.rs deleted file mode 100644 index 9d75b726aa0..00000000000 --- a/rustfmt-core/tests/target/space-not-before-newline.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Foo { - a: (), - // spaces ^^^ to be removed -} -enum Foo { - Bar, - // spaces ^^^ to be removed -} diff --git a/rustfmt-core/tests/target/spaces-around-ranges.rs b/rustfmt-core/tests/target/spaces-around-ranges.rs deleted file mode 100644 index b53e5b58b8c..00000000000 --- a/rustfmt-core/tests/target/spaces-around-ranges.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-spaces_around_ranges: true - -fn bar(v: &[u8]) {} - -fn foo() { - let a = vec![0; 20]; - for j in 0 ..= 20 { - for i in 0 .. 3 { - bar(a[i .. j]); - bar(a[i ..]); - bar(a[.. j]); - bar(a[..= (j + 1)]); - } - } -} diff --git a/rustfmt-core/tests/target/static.rs b/rustfmt-core/tests/target/static.rs deleted file mode 100644 index 5daccf3e7f7..00000000000 --- a/rustfmt-core/tests/target/static.rs +++ /dev/null @@ -1,27 +0,0 @@ -const FILE_GENERIC_READ: DWORD = - STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; - -static boolnames: &'static [&'static str] = &[ - "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", - "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", - "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", - "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr", -]; - -static mut name: SomeType = - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; - -pub static count: u8 = 10; - -pub const test: &Type = &val; - -impl Color { - pub const WHITE: u32 = 10; -} - -// #1391 -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = - 0 as usize; - -pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: - Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/rustfmt-core/tests/target/string-lit-2.rs b/rustfmt-core/tests/target/string-lit-2.rs deleted file mode 100644 index 6b95e25a052..00000000000 --- a/rustfmt-core/tests/target/string-lit-2.rs +++ /dev/null @@ -1,25 +0,0 @@ -fn main() -> &'static str { - let too_many_lines = "Hello"; - let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ - s - jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; -} - -fn issue_1237() { - let msg = "eedadn\n\ - drvtee\n\ - eandsr\n\ - raavrd\n\ - atevrs\n\ - tsrnev\n\ - sdttsa\n\ - rasrtv\n\ - nssdts\n\ - ntnada\n\ - svetve\n\ - tesnvt\n\ - vntsnd\n\ - vrdear\n\ - dvrsen\n\ - enarar"; -} diff --git a/rustfmt-core/tests/target/string-lit-custom.rs b/rustfmt-core/tests/target/string-lit-custom.rs deleted file mode 100644 index 50ebb97491b..00000000000 --- a/rustfmt-core/tests/target/string-lit-custom.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-format_strings: false - -fn main() { - let expected = "; ModuleID = \'foo\' - -; Function Attrs: nounwind -declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 - -declare i32 @write(i32, i8*, i32) - -declare i32 @putchar(i32) - -declare i32 @getchar() - -define i32 @main() { -entry: - ret i32 0 -} - -attributes #0 = { nounwind } -"; -} diff --git a/rustfmt-core/tests/target/string-lit.rs b/rustfmt-core/tests/target/string-lit.rs deleted file mode 100644 index f60002ac618..00000000000 --- a/rustfmt-core/tests/target/string-lit.rs +++ /dev/null @@ -1,64 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false -// Long string literals - -fn main() -> &'static str { - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \ - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; - let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let too_many_lines = "Hello"; - - // Make sure we don't break after an escape character. - let odd_length_name = - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - let even_length_name = - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; - - let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; - - let raw_string = r#"Do -not -remove -formatting"#; - - filename.replace(" ", "\\"); - - let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = - funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); - - let unicode = "a̐éö̲\r\n"; - let unicode2 = "Löwe 老虎 Léopard"; - let unicode3 = "中华Việt Nam"; - let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; - - "stuffin'" -} - -fn issue682() { - let a = "hello \\ o/"; - let b = a.replace("\\ ", "\\"); -} - -fn issue716() { - println!( - "forall x. mult(e(), x) = x /\\ - forall x. mult(x, x) = e()" - ); -} - -fn issue_1282() { - { - match foo { - Permission::AndroidPermissionAccessLocationExtraCommands => { - "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" - } - } - } -} - -// #1987 -#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] \ - -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] -extern "C" {} diff --git a/rustfmt-core/tests/target/string_punctuation.rs b/rustfmt-core/tests/target/string_punctuation.rs deleted file mode 100644 index 1cc73d14060..00000000000 --- a/rustfmt-core/tests/target/string_punctuation.rs +++ /dev/null @@ -1,15 +0,0 @@ -// rustfmt-format_strings: true -// rustfmt-error_on_line_overflow: false - -fn main() { - println!( - "ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ - Likethisssssssssssss" - ); - format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); - println!( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ - adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ - ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea" - ); -} diff --git a/rustfmt-core/tests/target/struct-field-attributes.rs b/rustfmt-core/tests/target/struct-field-attributes.rs deleted file mode 100644 index 5d6e92a91d9..00000000000 --- a/rustfmt-core/tests/target/struct-field-attributes.rs +++ /dev/null @@ -1,56 +0,0 @@ -// #1535 -#![feature(struct_field_attributes)] - -struct Foo { - bar: u64, - - #[cfg(test)] - qux: u64, -} - -fn do_something() -> Foo { - Foo { - bar: 0, - - #[cfg(test)] - qux: 1, - } -} - -fn main() { - do_something(); -} - -// #1462 -struct Foo { - foo: usize, - #[cfg(feature = "include-bar")] - bar: usize, -} - -fn new_foo() -> Foo { - Foo { - foo: 0, - #[cfg(feature = "include-bar")] - bar: 0, - } -} - -// #2044 -pub enum State { - Closure( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] - GcPtr, - ), -} - -struct Fields( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] - Arc>, -); - -// #2309 -pub struct A { - #[doc = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] - pub foos: Vec, -} diff --git a/rustfmt-core/tests/target/struct_lits.rs b/rustfmt-core/tests/target/struct_lits.rs deleted file mode 100644 index 648c723d357..00000000000 --- a/rustfmt-core/tests/target/struct_lits.rs +++ /dev/null @@ -1,191 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: f(), - b: b(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { a: Bar, b: f() }; - - Quux { - x: if cond { - bar(); - }, - y: baz(), - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { - // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, - } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { - memb: T, - } - let foo = Foo:: { memb: 10 }; -} - -fn issue201() { - let s = S { a: 0, ..b }; -} - -fn issue201_2() { - let s = S { a: S2 { ..c }, ..b }; -} - -fn issue278() { - let s = S { - a: 0, - // - b: 0, - }; - let s1 = S { - a: 0, - // foo - // - // bar - b: 0, - }; -} - -fn struct_exprs() { - Foo { a: 1, b: f(2) }; - Foo { - a: 1, - b: f(2), - ..g(3) - }; - LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { - ..base - }; - IntrinsicISizesContribution { - content_intrinsic_sizes: IntrinsicISizes { - minimum_inline_size: 0, - }, - }; -} - -fn issue123() { - Foo { a: b, c: d, e: f }; - - Foo { - a: bb, - c: dd, - e: ff, - }; - - Foo { - a: ddddddddddddddddddddd, - b: cccccccccccccccccccccccccccccccccccccc, - }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; - - Foo { - arm: 0, // Comment - }; - - Foo { - a: aaaaaaaaaa, - b: bbbbbbbb, - c: cccccccccc, - d: dddddddddd, // a comment - e: eeeeeeeee, - }; -} - -fn issue698() { - Record { - ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; - Record { - ffffffffffffffffffffffffffields: - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - } -} - -fn issue835() { - MyStruct {}; - MyStruct { /* a comment */ }; - MyStruct { - // Another comment - }; - MyStruct {} -} - -fn field_init_shorthand() { - MyStruct { x, y, z }; - MyStruct { x, y, z, ..base }; - Foo { - aaaaaaaaaa, - bbbbbbbb, - cccccccccc, - dddddddddd, // a comment - eeeeeeeee, - }; - Record { - ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - }; -} diff --git a/rustfmt-core/tests/target/struct_lits_multiline.rs b/rustfmt-core/tests/target/struct_lits_multiline.rs deleted file mode 100644 index c831dc7a8ba..00000000000 --- a/rustfmt-core/tests/target/struct_lits_multiline.rs +++ /dev/null @@ -1,117 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-struct_lit_single_line: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { - a: x, - }; - - Foo { - a: foo(), // comment - // comment - b: bar(), - ..something - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: foo(), - b: bar(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - a: foo(), - b: bar(), - }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { - // Comment - a: foo(), // Comment - // Comment - b: bar(), // Comment - }; - - Foo { - a: Bar, - b: foo(), - }; - - Quux { - x: if cond { - bar(); - }, - y: baz(), - }; - - A { - // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, - }; - - Some(Data::MethodCallData(MethodCallData { - span: sub_span.unwrap(), - scope: self.enclosing_scope(id), - ref_id: def_id, - decl_id: Some(decl_id), - })); - - Diagram { - // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, - } -} - -fn matcher() { - TagTerminatedByteMatcher { - matcher: ByteMatcher { - pattern: b" { - memb: T, - } - let foo = Foo:: { - memb: 10, - }; -} - -fn issue201() { - let s = S { - a: 0, - ..b - }; -} - -fn issue201_2() { - let s = S { - a: S2 { - ..c - }, - ..b - }; -} - -fn issue491() { - Foo { - guard: None, - arm: 0, // Comment - }; -} diff --git a/rustfmt-core/tests/target/struct_lits_visual.rs b/rustfmt-core/tests/target/struct_lits_visual.rs deleted file mode 100644 index 7e93b91d8c1..00000000000 --- a/rustfmt-core/tests/target/struct_lits_visual.rs +++ /dev/null @@ -1,50 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* Comment */ - // Comment - b: bar(), /* Comment */ }; - - Foo { a: Bar, b: f() }; - - Quux { x: if cond { - bar(); - }, - y: baz(), }; - - Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - z: zzzzz, /* test */ }; - - A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; - - Diagram { // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, } -} diff --git a/rustfmt-core/tests/target/struct_lits_visual_multiline.rs b/rustfmt-core/tests/target/struct_lits_visual_multiline.rs deleted file mode 100644 index 2809d3a2612..00000000000 --- a/rustfmt-core/tests/target/struct_lits_visual_multiline.rs +++ /dev/null @@ -1,50 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-indent_style: Visual -// rustfmt-struct_lit_single_line: false -// rustfmt-error_on_line_overflow: false - -// Struct literal expressions. - -fn main() { - let x = Bar; - - // Comment - let y = Foo { a: x }; - - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; - - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* Comment */ - // Comment - b: bar(), /* Comment */ }; - - Foo { a: Bar, - b: foo(), }; - - Quux { x: if cond { - bar(); - }, - y: baz(), }; - - A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - first: item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; - - Diagram { // o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - graph: G, } -} diff --git a/rustfmt-core/tests/target/struct_tuple_visual.rs b/rustfmt-core/tests/target/struct_tuple_visual.rs deleted file mode 100644 index 369feae71d2..00000000000 --- a/rustfmt-core/tests/target/struct_tuple_visual.rs +++ /dev/null @@ -1,37 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Visual -fn foo() { - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); - - Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment - foo(), /* Comment */ - // Comment - bar() /* Comment */); - - Foo(Bar, f()); - - Quux(if cond { - bar(); - }, - baz()); - - Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - zzzzz /* test */); - - A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. - item(), - // Praesent et diam eget libero egestas mattis sit amet vitae augue. - // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - Item); - - Diagram(// o This graph demonstrates how - // / \ significant whitespace is - // o o preserved. - // /|\ \ - // o o o o - G) -} diff --git a/rustfmt-core/tests/target/structs.rs b/rustfmt-core/tests/target/structs.rs deleted file mode 100644 index 59a57a9b5b4..00000000000 --- a/rustfmt-core/tests/target/structs.rs +++ /dev/null @@ -1,332 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -/// A Doc comment -#[AnAttribute] -pub struct Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField, -} - -// #1095 -struct S { - t: T, -} - -// #1029 -pub struct Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -struct X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub struct Writebatch { - #[allow(dead_code)] // only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -struct Bar; - -struct NewType(Type, OtherType); - -struct NewInt( - pub i32, - SomeType, // inline comment - T, // sup -); - -struct Qux< - 'a, - N: Clone + 'a, - E: Clone + 'a, - G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, - W: Write + Copy, ->( - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - #[AnAttr] - // Comment - /// Testdoc - G, - pub W, -); - -struct Tuple( - // Comment 1 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - // Comment 2 - BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, -); - -// With a where clause and generics. -pub struct Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -struct Baz { - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C -} - -struct Baz { - a: A, // Comment A - - b: B, // Comment B - - c: C, // Comment C -} - -struct Baz { - a: A, - - b: B, - c: C, - - d: D, -} - -struct Baz { - // Comment A - a: A, - - // Comment B - b: B, - // Comment C - c: C, -} - -// Will this be a one-liner? -struct Tuple( - A, // Comment - B, -); - -pub struct State time::Timespec> { - now: F, -} - -pub struct State ()> { - now: F, -} - -pub struct State { - now: F, -} - -struct Palette { - /// A map of indices in the palette to a count of pixels in approximately - /// that color - foo: i32, -} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -struct FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ - // Another pre comment - #[attr1] - #[attr2] - pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC - * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(T); -struct Foo(T) -where - T: Copy, - T: Eq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -); -struct Foo( - TTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTTTT, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUUUUUUU, - TTTTTTTTTTTTTTTTTTT, - UUUUUUUUUUUUUUUUUUU, -) -where - T: PartialEq; -struct Foo( - TTTTTTTTTTTTTTTTT, // Foo - UUUUUUUUUUUUUUUUUUUUUUUU, // Bar - // Baz - TTTTTTTTTTTTTTTTTTT, - // Qux (FIXME #572 - doc comment) - UUUUUUUUUUUUUUUUUUU, -); - -mod m { - struct X - where - T: Sized, - { - a: T, - } -} - -struct Foo( - TTTTTTTTTTTTTTTTTTT, - /// Qux - UUUUUUUUUUUUUUUUUUU, -); - -struct Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - -struct Foo {} -struct Foo {} -struct Foo { - // comment -} -struct Foo { - // trailing space -> -} -struct Foo { /* comment */ } -struct Foo( /* comment */ ); - -struct LongStruct { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -struct Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -struct Foo(String); - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -struct Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} - -// structs with long identifier -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{} -struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -{ - x: i32, -} - -// structs with visibility, do not duplicate visibility (#2110). -pub(self) struct Foo {} -pub(super) struct Foo {} -pub(crate) struct Foo {} -pub(self) struct Foo(); -pub(super) struct Foo(); -pub(crate) struct Foo(); - -// #2125 -pub struct ReadinessCheckRegistry( - Mutex, Box ReadinessCheck + Sync + Send>>>, -); - -// #2144 unit struct with generics -struct MyBox; -struct MyBoxx -where - T: ?Sized, - S: Clone; - -// #2208 -struct Test { - /// foo - #[serde(default)] - pub join: Vec, - #[serde(default)] - pub tls: bool, -} diff --git a/rustfmt-core/tests/target/trailing-comma-never.rs b/rustfmt-core/tests/target/trailing-comma-never.rs deleted file mode 100644 index 3df0c7950eb..00000000000 --- a/rustfmt-core/tests/target/trailing-comma-never.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-trailing_comma: Never - -enum X { - A, - B -} - -enum Y { - A, - B -} - -enum TupX { - A(u32), - B(i32, u16) -} - -enum TupY { - A(u32), - B(i32, u16) -} - -enum StructX { - A { s: u16 }, - B { u: u32, i: i32 } -} - -enum StructY { - A { s: u16 }, - B { u: u32, i: i32 } -} diff --git a/rustfmt-core/tests/target/trailing_commas.rs b/rustfmt-core/tests/target/trailing_commas.rs deleted file mode 100644 index 61b82035450..00000000000 --- a/rustfmt-core/tests/target/trailing_commas.rs +++ /dev/null @@ -1,103 +0,0 @@ -// rustfmt-match_block_trailing_comma: true -// rustfmt-trailing_comma: Always - -fn main() { - match foo { - x => {}, - y => { - foo(); - }, - _ => x, - } -} - -fn f< - S, T, ->( - x: T, - y: S, -) -> T -where - T: P, - S: Q, -{ - x -} - -impl Trait for T -where - T: P, -{ - fn f(x: T) -> T - where - T: Q + R, - { - x - } -} - -struct Pair< - S, T, -> where - T: P, - S: P + Q, -{ - a: T, - b: S, -} - -struct TupPair< - S, T, ->(S, T,) -where - T: P, - S: P + Q; - -enum E< - S, T, -> where - S: P, - T: P, -{ - A { a: T, }, -} - -type Double< - T, -> where - T: P, - T: Q, -= Pair< - T, T, ->; - -extern "C" { - fn f< - S, T, - >( - x: T, - y: S, - ) -> T - where - T: P, - S: Q; -} - -trait Q< - S, T, -> where - T: P, - S: R, -{ - fn f< - U, V, - >( - self, - x: T, - y: S, - z: U, - ) -> Self - where - U: P, - V: P; -} diff --git a/rustfmt-core/tests/target/trait.rs b/rustfmt-core/tests/target/trait.rs deleted file mode 100644 index 133e8babedb..00000000000 --- a/rustfmt-core/tests/target/trait.rs +++ /dev/null @@ -1,132 +0,0 @@ -// Test traits - -trait Foo { - fn bar(x: i32) -> Baz { - Baz::new() - } - - fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; - - fn foo( - a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment - b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, - ) -> RetType; // Some comment - - fn baz(&mut self) -> i32; - - fn increment(&mut self, x: i32); - - fn read(&mut self, x: BufReader /* Used to be MemReader */) - where - R: Read; -} - -pub trait WriteMessage { - fn write_message(&mut self, &FrontendMessage) -> io::Result<()>; -} - -trait Runnable { - fn handler(self: &Runnable); -} - -trait TraitWithExpr { - fn fn_with_expr(x: [i32; 1]); -} - -trait Test { - fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result - where - F: FnOnce(&mut Self) -> Result; -} - -trait T {} - -trait Foo { - type Bar: Baz; - type Inner: Foo = Box; -} - -trait ConstCheck: Foo -where - T: Baz, -{ - const J: i32; -} - -trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt -where - T: Foo, -{ -} - -trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt -where - T: Foo, -{ -} - -trait FooBar - : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt -where - J: Bar, -{ - fn test(); -} - -trait WhereList -where - T: Foo, - J: Bar, -{ -} - -trait X /* comment */ {} -trait Y // comment -{ -} - -// #2055 -pub trait Foo: -// A and C -A + C -// and B - + B -{} - -// #2158 -trait Foo { - type ItRev = > as UntypedTimeSeries>::IterRev; - type IteRev = - > as UntypedTimeSeries>::IterRev; -} - -// #2331 -trait MyTrait< - AAAAAAAAAAAAAAAAAAAA, - BBBBBBBBBBBBBBBBBBBB, - CCCCCCCCCCCCCCCCCCCC, - DDDDDDDDDDDDDDDDDDDD, -> { - fn foo() {} -} - -// Trait aliases -trait FooBar = Foo + Bar; -trait FooBar = Foo + Bar; -trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAA = - BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAA = - BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = - FooBar; -trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA< - A, - B, - C, - D, - E, -> = FooBar; -#[rustfmt_skip] -trait FooBar = Foo - + Bar; diff --git a/rustfmt-core/tests/target/try-conversion.rs b/rustfmt-core/tests/target/try-conversion.rs deleted file mode 100644 index e16fba278d2..00000000000 --- a/rustfmt-core/tests/target/try-conversion.rs +++ /dev/null @@ -1,27 +0,0 @@ -// rustfmt-use_try_shorthand: true - -fn main() { - let x = some_expr()?; - - let y = a.very - .loooooooooooooooooooooooooooooooooooooong() - .chain() - .inside() - .weeeeeeeeeeeeeee()? - .test() - .0 - .x; -} - -fn test() { - a? -} - -fn issue1291() { - fs::create_dir_all(&gitfiledir).chain_err(|| { - format!( - "failed to create the {} submodule directory for the workarea", - name - ) - })?; -} diff --git a/rustfmt-core/tests/target/tuple.rs b/rustfmt-core/tests/target/tuple.rs deleted file mode 100644 index a22586284dc..00000000000 --- a/rustfmt-core/tests/target/tuple.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Test tuple litterals - -fn foo() { - let a = (a, a, a, a, a); - let aaaaaaaaaaaaaaaa = ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - ); - let aaaaaaaaaaaaaaaaaaaaaa = ( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaaaaaaaaaa, - aaaa, - ); - let a = (a,); - - let b = ( - // This is a comment - b, // Comment - b, /* Trailing comment */ - ); - - // #1063 - foo(x.0 .0); -} - -fn a() { - (( - aaaaaaaa, - aaaaaaaaaaaaa, - aaaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - aaaaaaaaaaaaaaaa, - aaaaaaaaaaaaaa, - ),) -} - -fn b() { - ( - ( - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, - ), - bbbbbbbbbbbbbbbbbb, - ) -} - -fn issue550() { - self.visitor.visit_volume( - self.level.sector_id(sector), - ( - floor_y, - if is_sky_flat(ceil_tex) { - from_wad_height(self.height_range.1) - } else { - ceil_y - }, - ), - ); -} - -fn issue775() { - if indent { - let a = mk_object(&[ - ("a".to_string(), Boolean(true)), - ( - "b".to_string(), - Array(vec![ - mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), - mk_object(&[("d".to_string(), String("".to_string()))]), - ]), - ), - ]); - } -} - -fn issue1725() { - bench_antialiased_lines!( - bench_draw_antialiased_line_segment_diagonal, - (10, 10), - (450, 450) - ); - bench_antialiased_lines!( - bench_draw_antialiased_line_segment_shallow, - (10, 10), - (450, 80) - ); -} diff --git a/rustfmt-core/tests/target/type-ascription.rs b/rustfmt-core/tests/target/type-ascription.rs deleted file mode 100644 index a2f082ba4b4..00000000000 --- a/rustfmt-core/tests/target/type-ascription.rs +++ /dev/null @@ -1,12 +0,0 @@ -fn main() { - let xxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; - - let xxxxxxxxxxxxxxx = - yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - - x: u32 - 1u32 / 10f32: u32 -} diff --git a/rustfmt-core/tests/target/type.rs b/rustfmt-core/tests/target/type.rs deleted file mode 100644 index 2f35e796512..00000000000 --- a/rustfmt-core/tests/target/type.rs +++ /dev/null @@ -1,31 +0,0 @@ -// rustfmt-normalize_comments: true -fn types() { - let x: [Vec<_>] = []; - let y: *mut [SomeType; konst_funk()] = expr(); - let z: (/* #digits */ usize, /* exp */ i16) = funk(); - let z: (usize /* #digits */, i16 /* exp */) = funk(); -} - -struct F { - f: extern "C" fn(x: u8, ... /* comment */), - g: extern "C" fn(x: u8, /* comment */ ...), - h: extern "C" fn(x: u8, ...), - i: extern "C" fn( - x: u8, - // comment 4 - y: String, // comment 3 - z: Foo, - // comment - ... // comment 2 - ), -} - -fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} - -fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} - -fn impl_trait_fn_2() -> impl Future {} - -fn issue_1234() { - do_parse!(name: take_while1!(is_token) >> (Header)) -} diff --git a/rustfmt-core/tests/target/type_alias.rs b/rustfmt-core/tests/target/type_alias.rs deleted file mode 100644 index 862f9ecbeec..00000000000 --- a/rustfmt-core/tests/target/type_alias.rs +++ /dev/null @@ -1,76 +0,0 @@ -// rustfmt-normalize_comments: true - -type PrivateTest<'a, I> = ( - Box + 'a>, - Box + 'a>, -); - -pub type PublicTest<'a, I, O> = Result< - Vec, - Box + 'a>, - Box + 'a>, ->; - -pub type LongGenericListTest< - 'a, - 'b, - 'c, - 'd, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - A, - B, - C, -> = Option>; - -pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; - -pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = - Vec; - -pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = - Vec; - -pub type GenericsFitButNotEqualTest< - 'a, - 'b, - 'c, - 'd, - LONGPARAMETERNAME, - LONGPARAMETERNAME, - A1, - B, - C, -> = Vec; - -pub type CommentTest< - // Lifetime - 'a, - // Type - T, -> = (); - -pub type WithWhereClause -where - T: Clone, - LONGPARAMETERNAME: Clone + Eq + OtherTrait, -= Option; - -pub type Exactly100CharstoEqualWhereTest -where - T: Clone + Ord + Eq + SomeOtherTrait, -= Option; - -pub type Exactly101CharstoEqualWhereTest -where - T: Clone + Ord + Eq + SomeOtherTrait, -= Option; - -type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); - -// #1683 -pub type Between = - super::operators::Between, AsExpr>>; -pub type NotBetween = - super::operators::NotBetween, AsExpr>>; diff --git a/rustfmt-core/tests/target/unindent_if_else_cond_comment.rs b/rustfmt-core/tests/target/unindent_if_else_cond_comment.rs deleted file mode 100644 index 98621b1eed1..00000000000 --- a/rustfmt-core/tests/target/unindent_if_else_cond_comment.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Comments on else block. See #1575. - -fn example() { - // `if` comment - if x { - foo(); - // `else if` comment - } else if y { - foo(); - // Comment on `else if`. - // Comment on `else if`. - } else if z { - bar(); - /* - * Multi line comment on `else if` - */ - } else if xx { - bar(); - /* Single line comment on `else if` */ - } else if yy { - foo(); - // `else` comment - } else { - foo(); - // Comment at the end of `else` block - }; -} diff --git a/rustfmt-core/tests/target/unions.rs b/rustfmt-core/tests/target/unions.rs deleted file mode 100644 index eb6c3ae7e15..00000000000 --- a/rustfmt-core/tests/target/unions.rs +++ /dev/null @@ -1,196 +0,0 @@ -// rustfmt-normalize_comments: true -// rustfmt-wrap_comments: true - -/// A Doc comment -#[AnAttribute] -pub union Foo { - #[rustfmt_skip] - f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field - // Comment on a field - #[AnAttribute] - g: SomeOtherType, - /// A doc comment on a field - h: AThirdType, - pub i: TypeForPublicField, -} - -// #1029 -pub union Foo { - #[doc(hidden)] - // This will NOT get deleted! - bar: String, // hi -} - -// #1029 -union X { - // `x` is an important number. - #[allow(unused)] // TODO: use - x: u32, -} - -// #410 -#[allow(missing_docs)] -pub union Writebatch { - #[allow(dead_code)] // only used for holding the internal pointer - writebatch: RawWritebatch, - marker: PhantomData, -} - -// With a where clause and generics. -pub union Foo<'a, Y: Baz> -where - X: Whatever, -{ - f: SomeType, // Comment beside a field -} - -union Baz { - a: A, // Comment A - b: B, // Comment B - c: C, // Comment C -} - -union Baz { - a: A, // Comment A - - b: B, // Comment B - - c: C, // Comment C -} - -union Baz { - a: A, - - b: B, - c: C, - - d: D, -} - -union Baz { - // Comment A - a: A, - - // Comment B - b: B, - // Comment C - c: C, -} - -pub union State time::Timespec> { - now: F, -} - -pub union State ()> { - now: F, -} - -pub union State { - now: F, -} - -union Palette { - /// A map of indices in the palette to a count of pixels in approximately - /// that color - foo: i32, -} - -// Splitting a single line comment into a block previously had a misalignment -// when the field had attributes -union FieldsWithAttributes { - // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ - // Another pre comment - #[attr1] - #[attr2] - pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC - * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -mod m { - union X - where - T: Sized, - { - a: T, - } -} - -union Issue677 { - pub ptr: *const libc::c_void, - pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - -union Foo {} -union Foo {} -union Foo { - // comment -} -union Foo { - // trailing space -> -} -union Foo { /* comment */ } - -union LongUnion { - a: A, - the_quick_brown_fox_jumps_over_the_lazy_dog: - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, -} - -union Deep { - deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: - node::Handle>, Type, NodeType>, -} - -// #1364 -fn foo() { - convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); - convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); - convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); - convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); -} - -// Vertical alignment -union Foo { - aaaaa: u32, // a - - b: u32, // b - cc: u32, // cc - - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 - yy: u32, // comment2 - zzz: u32, // comment3 - - aaaaaa: u32, // comment4 - bb: u32, // comment5 - // separate - dd: u32, // comment7 - c: u32, // comment6 - - aaaaaaa: u32, /* multi - * line - * comment - */ - b: u32, // hi - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - // separate - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - please_do_not_push_this_comment3: u32, // comment3 - - do_not_push_this_comment1: u32, // comment1 - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 - // separate - please_do_not_push_this_comment3: u32, // comment3 -} diff --git a/rustfmt-core/tests/target/where-clause-rfc.rs b/rustfmt-core/tests/target/where-clause-rfc.rs deleted file mode 100644 index 1e83d5b3abc..00000000000 --- a/rustfmt-core/tests/target/where-clause-rfc.rs +++ /dev/null @@ -1,128 +0,0 @@ -// rustfmt-indent_style: Block - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -where - T: FOo, - U: Bar, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -where - T: FOo, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, - shape: &Shape, -) where - T: FOo, - U: Bar, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, - shape: &Shape, -) where - T: FOo, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, -) -> Option -where - T: FOo, - U: Bar, -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule( - node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, -) -> Option -where - T: FOo, -{ - let mut effects = HashMap::new(); -} - -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType - where - F: FnMut(Self::Item) -> bool; - - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType - where - F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType -where - F: FnMut(Self::Item) -> bool, -{ -} - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) -where - A: LongTrait; - -struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) -where - A: LongTrait1234; - -struct AlwaysOnNextLine -where - A: LongTrait, -{ - x: i32, -} - -pub trait SomeTrait -where - T: Something - + Sync - + Send - + Display - + Debug - + Copy - + Hash - + Debug - + Display - + Write - + Read - + FromStr, -{ -} - -// #2020 -impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { - fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) - where - F: for<'b> FnMut( - &mut ProbeContext<'b, 'gcx, 'tcx>, - ty::PolyTraitRef<'tcx>, - ty::AssociatedItem, - ), - { - // ... - } -} diff --git a/rustfmt-core/tests/target/where-clause.rs b/rustfmt-core/tests/target/where-clause.rs deleted file mode 100644 index def18a0c11a..00000000000 --- a/rustfmt-core/tests/target/where-clause.rs +++ /dev/null @@ -1,107 +0,0 @@ -// rustfmt-indent_style: Visual - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) - where T: FOo, - U: Bar -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) - where T: FOo -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, - shape: &Shape) - where T: FOo, - U: Bar -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape, - shape: &Shape) - where T: FOo -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape) - -> Option - where T: FOo, - U: Bar -{ - let mut effects = HashMap::new(); -} - -fn reflow_list_node_with_rule(node: &CompoundNode, - rule: &Rule, - args: &[Arg], - shape: &Shape) - -> Option - where T: FOo -{ - let mut effects = HashMap::new(); -} - -pub trait Test { - fn very_long_method_name(self, f: F) -> MyVeryLongReturnType - where F: FnMut(Self::Item) -> bool; - - fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType - where F: FnMut(Self::Item) -> bool; -} - -fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType - where F: FnMut(Self::Item) -> bool -{ -} - -struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) - where A: LongTrait; - -struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) where A: LongTrait1234; - -struct AlwaysOnNextLine - where A: LongTrait -{ - x: i32, -} - -pub trait SomeTrait - where T: Something - + Sync - + Send - + Display - + Debug - + Copy - + Hash - + Debug - + Display - + Write - + Read - + FromStr -{ -} - -// #2020 -impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { - fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) - where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, - ty::PolyTraitRef<'tcx>, - ty::AssociatedItem) - { - // ... - } -} diff --git a/rustfmt-core/tests/writemode/source/fn-single-line.rs b/rustfmt-core/tests/writemode/source/fn-single-line.rs deleted file mode 100644 index 289dd9aa093..00000000000 --- a/rustfmt-core/tests/writemode/source/fn-single-line.rs +++ /dev/null @@ -1,80 +0,0 @@ -// rustfmt-fn_single_line: true -// rustfmt-write_mode: checkstyle -// Test single-line functions. - -fn foo_expr() { - 1 -} - -fn foo_stmt() { - foo(); -} - -fn foo_decl_local() { - let z = 5; - } - -fn foo_decl_item(x: &mut i32) { - x = 3; -} - - fn empty() { - -} - -fn foo_return() -> String { - "yay" -} - -fn foo_where() -> T where T: Sync { - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space () { - 1 -} - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) { - } -} - -trait CoolerTypes { fn dummy(&self) { -} -} - -fn Foo() where T: Bar { -} diff --git a/rustfmt-core/tests/writemode/source/modified.rs b/rustfmt-core/tests/writemode/source/modified.rs deleted file mode 100644 index 948beb348db..00000000000 --- a/rustfmt-core/tests/writemode/source/modified.rs +++ /dev/null @@ -1,14 +0,0 @@ -// rustfmt-write_mode: modified -// Test "modified" output - -fn -blah -() -{ } - - -#[cfg -( a , b -)] -fn -main() {} diff --git a/rustfmt-core/tests/writemode/target/checkstyle.xml b/rustfmt-core/tests/writemode/target/checkstyle.xml deleted file mode 100644 index 30ab5ad7579..00000000000 --- a/rustfmt-core/tests/writemode/target/checkstyle.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/rustfmt-core/tests/writemode/target/modified.txt b/rustfmt-core/tests/writemode/target/modified.txt deleted file mode 100644 index 5c0539a665e..00000000000 --- a/rustfmt-core/tests/writemode/target/modified.txt +++ /dev/null @@ -1,5 +0,0 @@ -4 4 1 -fn blah() {} -10 5 2 -#[cfg(a, b)] -fn main() {} diff --git a/rustfmt-format-diff/Cargo.toml b/rustfmt-format-diff/Cargo.toml deleted file mode 100644 index cdace2c9b37..00000000000 --- a/rustfmt-format-diff/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "rustfmt-format-diff" -version = "0.4.0" -authors = ["Nicholas Cameron ", "The Rustfmt developers"] -description = "Run rustfmt against diff" -repository = "https://github.com/rust-lang-nursery/rustfmt" -readme = "README.md" -license = "Apache-2.0/MIT" -categories = ["development-tools"] - -[[bin]] -name = "rustfmt-format-diff" - -[dependencies] -env_logger = "0.5" -getopts = "0.2" -log = "0.3" -regex = "0.2" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 7ef4931fbe3..a3302a86a0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(custom_attribute)] #![feature(decl_macro)] #![feature(match_default_bindings)] diff --git a/tests/config/disable_all_formatting.toml b/tests/config/disable_all_formatting.toml new file mode 100644 index 00000000000..c7ad93bafe3 --- /dev/null +++ b/tests/config/disable_all_formatting.toml @@ -0,0 +1 @@ +disable_all_formatting = true diff --git a/tests/config/issue-1111.toml b/tests/config/issue-1111.toml new file mode 100755 index 00000000000..44148a2d3c3 --- /dev/null +++ b/tests/config/issue-1111.toml @@ -0,0 +1 @@ +reorder_imports = true diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml new file mode 100644 index 00000000000..d03ac281acb --- /dev/null +++ b/tests/config/small_tabs.toml @@ -0,0 +1,12 @@ +max_width = 100 +comment_width = 80 +tab_spaces = 2 +newline_style = "Unix" +brace_style = "SameLineWhere" +fn_args_density = "Tall" +trailing_comma = "Vertical" +indent_style = "Block" +report_todo = "Always" +report_fixme = "Never" +reorder_imports = false +format_strings = true diff --git a/tests/coverage/source/comments.rs b/tests/coverage/source/comments.rs new file mode 100644 index 00000000000..e79557af713 --- /dev/null +++ b/tests/coverage/source/comments.rs @@ -0,0 +1,7 @@ +// rustfmt-write_mode: coverage +/// Here's a doc comment! +fn main() { + // foo is bar + let foo = "bar"; + // loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment!!!!! +} diff --git a/tests/coverage/target/comments.rs b/tests/coverage/target/comments.rs new file mode 100644 index 00000000000..8f9c223aef2 --- /dev/null +++ b/tests/coverage/target/comments.rs @@ -0,0 +1,7 @@ +XX XXXXXXXXXXXXXXXXXXX XXXXXXXX +/// Here's a doc comment! +fn main() { + XX XXX XX XXX + let foo = "bar"; + XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXX +} diff --git a/tests/lib.rs b/tests/lib.rs new file mode 100644 index 00000000000..9abe08ba9e0 --- /dev/null +++ b/tests/lib.rs @@ -0,0 +1,861 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; +extern crate regex; +extern crate rustfmt_nightly as rustfmt; +extern crate term; + +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::io::{self, BufRead, BufReader, Read}; +use std::iter::{Enumerate, Peekable}; +use std::path::{Path, PathBuf}; +use std::str::Chars; + +use rustfmt::*; +use rustfmt::config::{Color, Config, ReportTactic}; +use rustfmt::config::summary::Summary; +use rustfmt::filemap::write_system_newlines; +use rustfmt::rustfmt_diff::*; + +const DIFF_CONTEXT_SIZE: usize = 3; +const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; + +// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the +// given path. The `recursive` argument controls if files from subdirectories +// are also returned. +fn get_test_files(path: &Path, recursive: bool) -> Vec { + let mut files = vec![]; + if path.is_dir() { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read directory {}", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get DirEntry"); + let path = entry.path(); + if path.is_dir() && recursive { + files.append(&mut get_test_files(&path, recursive)); + } else if path.extension().map_or(false, |f| f == "rs") { + files.push(path); + } + } + } + files +} + +fn verify_config_used(path: &Path, config_name: &str) { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read {} directory", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.extension().map_or(false, |f| f == "rs") { + // check if "// rustfmt-:" appears in the file. + let filebuf = BufReader::new( + fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), + ); + assert!( + filebuf + .lines() + .map(|l| l.unwrap()) + .take_while(|l| l.starts_with("//")) + .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), + format!( + "config option file {} does not contain expected config name", + path.display() + ) + ); + } + } +} + +#[test] +fn verify_config_test_names() { + for path in &[ + Path::new("tests/source/configs"), + Path::new("tests/target/configs"), + ] { + for entry in fs::read_dir(path).expect("Couldn't read configs directory") { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.is_dir() { + let config_name = path.file_name().unwrap().to_str().unwrap(); + + // Make sure that config name is used in the files in the directory. + verify_config_used(&path, config_name); + } + } + } +} + +// This writes to the terminal using the same approach (via term::stdout or +// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing +// using only one or the other will cause the output order to differ when +// `print_diff` selects the approach not used. +fn write_message(msg: &str) { + let mut writer = OutputWriter::new(Color::Auto); + writer.writeln(&format!("{}", msg), None); +} + +// Integration tests. The files in the tests/source are formatted and compared +// to their equivalent in tests/target. The target file and config can be +// overridden by annotations in the source file. The input and output must match +// exactly. +#[test] +fn system_tests() { + // Get all files in the tests/source directory. + let files = get_test_files(Path::new("tests/source"), true); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} system tests.", count); + assert_eq!(fails, 0, "{} system tests failed", fails); +} + +// Do the same for tests/coverage-source directory +// the only difference is the coverage mode +#[test] +fn coverage_tests() { + let files = get_test_files(Path::new("tests/coverage/source"), true); + let (_reports, count, fails) = check_files(files); + + println!("Ran {} tests in coverage mode.", count); + assert_eq!(fails, 0, "{} tests failed", fails); +} + +#[test] +fn checkstyle_test() { + let filename = "tests/writemode/source/fn-single-line.rs"; + let expected_filename = "tests/writemode/target/checkstyle.xml"; + assert_output(Path::new(filename), Path::new(expected_filename)); +} + +#[test] +fn modified_test() { + // Test "modified" output + let filename = "tests/writemode/source/modified.rs"; + let result = get_modified_lines(Input::File(filename.into()), &Config::default()).unwrap(); + assert_eq!( + result.modified_lines, + ModifiedLines { + chunks: vec![ + ModifiedChunk { + line_number_orig: 4, + lines_removed: 4, + lines: vec!["fn blah() {}".into()], + }, + ModifiedChunk { + line_number_orig: 9, + lines_removed: 6, + lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], + }, + ], + } + ); +} + +// Helper function for comparing the results of rustfmt +// to a known output file generated by one of the write modes. +fn assert_output(source: &Path, expected_filename: &Path) { + let config = read_config(source); + let (_error_summary, file_map, _report) = format_file(source, &config); + + // Populate output by writing to a vec. + let mut out = vec![]; + let _ = filemap::write_all_files(&file_map, &mut out, &config); + let output = String::from_utf8(out).unwrap(); + + let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); + let mut expected_text = String::new(); + expected_file + .read_to_string(&mut expected_text) + .expect("Failed reading target"); + + let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + let mut failures = HashMap::new(); + failures.insert(source.to_owned(), compare); + print_mismatches_default_message(failures); + assert!(false, "Text does not match expected output"); + } +} + +// Idempotence tests. Files in tests/target are checked to be unaltered by +// rustfmt. +#[test] +fn idempotence_tests() { + // Get all files in the tests/target directory. + let files = get_test_files(Path::new("tests/target"), true); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} idempotent tests.", count); + assert_eq!(fails, 0, "{} idempotent tests failed", fails); +} + +// Run rustfmt on itself. This operation must be idempotent. We also check that +// no warnings are emitted. +#[test] +fn self_tests() { + let mut files = get_test_files(Path::new("tests"), false); + let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; + for dir in bin_directories { + let mut path = PathBuf::from("src"); + path.push(dir); + path.push("main.rs"); + files.push(path); + } + files.push(PathBuf::from("src/lib.rs")); + + let (reports, count, fails) = check_files(files); + let mut warnings = 0; + + // Display results. + println!("Ran {} self tests.", count); + assert_eq!(fails, 0, "{} self tests failed", fails); + + for format_report in reports { + println!("{}", format_report); + warnings += format_report.warning_count(); + } + + assert_eq!( + warnings, 0, + "Rustfmt's code generated {} warnings", + warnings + ); +} + +#[test] +fn stdin_formatting_smoke_test() { + let input = Input::Text("fn main () {}".to_owned()); + let config = Config::default(); + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_no_errors()); + for &(ref file_name, ref text) in &file_map { + if let FileName::Custom(ref file_name) = *file_name { + if file_name == "stdin" { + assert_eq!(text.to_string(), "fn main() {}\n"); + return; + } + } + } + panic!("no stdin"); +} + +// FIXME(#1990) restore this test +// #[test] +// fn stdin_disable_all_formatting_test() { +// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); +// let mut child = Command::new("./target/debug/rustfmt") +// .stdin(Stdio::piped()) +// .stdout(Stdio::piped()) +// .arg("--config-path=./tests/config/disable_all_formatting.toml") +// .spawn() +// .expect("failed to execute child"); + +// { +// let stdin = child.stdin.as_mut().expect("failed to get stdin"); +// stdin +// .write_all(input.as_bytes()) +// .expect("failed to write stdin"); +// } +// let output = child.wait_with_output().expect("failed to wait on child"); +// assert!(output.status.success()); +// assert!(output.stderr.is_empty()); +// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); +// } + +#[test] +fn format_lines_errors_are_reported() { + let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); + let input = Input::Text(format!("fn {}() {{}}", long_identifier)); + let config = Config::default(); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + +#[test] +fn format_lines_errors_are_reported_with_tabs() { + let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); + let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); + let config = Config::from_toml("hard_tabs = true").unwrap(); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + +// For each file, run rustfmt and collect the output. +// Returns the number of files checked and the number of failures. +fn check_files(files: Vec) -> (Vec, u32, u32) { + let mut count = 0; + let mut fails = 0; + let mut reports = vec![]; + + for file_name in files { + debug!("Testing '{}'...", file_name.display()); + + match idempotent_check(&file_name) { + Ok(ref report) if report.has_warnings() => { + print!("{}", report); + fails += 1; + } + Ok(report) => reports.push(report), + Err(err) => { + if let IdempotentCheckError::Mismatch(msg) = err { + print_mismatches_default_message(msg); + } + fails += 1; + } + } + + count += 1; + } + + (reports, count, fails) +} + +fn print_mismatches_default_message(result: HashMap>) { + let mut t = term::stdout().unwrap(); + for (file_name, diff) in result { + let mismatch_msg_formatter = + |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); + print_diff(diff, &mismatch_msg_formatter, Color::Auto); + } + + t.reset().unwrap(); +} + +fn print_mismatches String>( + result: HashMap>, + mismatch_msg_formatter: T, +) { + let mut t = term::stdout().unwrap(); + for (_file_name, diff) in result { + print_diff(diff, &mismatch_msg_formatter, Color::Auto); + } + + t.reset().unwrap(); +} + +fn read_config(filename: &Path) -> Config { + let sig_comments = read_significant_comments(filename); + // Look for a config file... If there is a 'config' property in the significant comments, use + // that. Otherwise, if there are no significant comments at all, look for a config file with + // the same name as the test file. + let mut config = if !sig_comments.is_empty() { + get_config(sig_comments.get("config").map(Path::new)) + } else { + get_config(filename.with_extension("toml").file_name().map(Path::new)) + }; + + for (key, val) in &sig_comments { + if key != "target" && key != "config" { + config.override_value(key, val); + } + } + + // Don't generate warnings for to-do items. + config.set().report_todo(ReportTactic::Never); + + config +} + +fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { + let filepath = filepath.into(); + let input = Input::File(filepath); + format_input::(input, config, None).unwrap() +} + +pub enum IdempotentCheckError { + Mismatch(HashMap>), + Parse, +} + +pub fn idempotent_check(filename: &PathBuf) -> Result { + let sig_comments = read_significant_comments(filename); + let config = read_config(filename); + let (error_summary, file_map, format_report) = format_file(filename, &config); + if error_summary.has_parsing_errors() { + return Err(IdempotentCheckError::Parse); + } + + let mut write_result = HashMap::new(); + for &(ref filename, ref text) in &file_map { + let mut v = Vec::new(); + // Won't panic, as we're not doing any IO. + write_system_newlines(&mut v, text, &config).unwrap(); + // Won't panic, we are writing correct utf8. + let one_result = String::from_utf8(v).unwrap(); + if let FileName::Real(ref filename) = *filename { + write_result.insert(filename.to_owned(), one_result); + } + } + + let target = sig_comments.get("target").map(|x| &(*x)[..]); + + handle_result(write_result, target).map(|_| format_report) +} + +// Reads test config file using the supplied (optional) file name. If there's no file name or the +// file doesn't exist, just return the default config. Otherwise, the file must be read +// successfully. +fn get_config(config_file: Option<&Path>) -> Config { + let config_file_name = match config_file { + None => return Default::default(), + Some(file_name) => { + let mut full_path = PathBuf::from("tests/config/"); + full_path.push(file_name); + if !full_path.exists() { + return Default::default(); + }; + full_path + } + }; + + let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); + let mut def_config = String::new(); + def_config_file + .read_to_string(&mut def_config) + .expect("Couldn't read config"); + + Config::from_toml(&def_config).expect("Invalid toml") +} + +// Reads significant comments of the form: // rustfmt-key: value +// into a hash map. +fn read_significant_comments(file_name: &Path) -> HashMap { + let file = + fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); + let reader = BufReader::new(file); + let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; + let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); + + // Matches lines containing significant comments or whitespace. + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") + .expect("Failed creating pattern 2"); + + reader + .lines() + .map(|line| line.expect("Failed getting line")) + .take_while(|line| line_regex.is_match(line)) + .filter_map(|line| { + regex.captures_iter(&line).next().map(|capture| { + ( + capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + ) + }) + }) + .collect() +} + +// Compare output to input. +// TODO: needs a better name, more explanation. +fn handle_result( + result: HashMap, + target: Option<&str>, +) -> Result<(), IdempotentCheckError> { + let mut failures = HashMap::new(); + + for (file_name, fmt_text) in result { + // If file is in tests/source, compare to file with same name in tests/target. + let target = get_target(&file_name, target); + let open_error = format!("Couldn't open target {:?}", &target); + let mut f = fs::File::open(&target).expect(&open_error); + + let mut text = String::new(); + let read_error = format!("Failed reading target {:?}", &target); + f.read_to_string(&mut text).expect(&read_error); + + // Ignore LF and CRLF difference for Windows. + if !string_eq_ignore_newline_repr(&fmt_text, &text) { + let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); + assert!( + !diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?" + ); + failures.insert(file_name, diff); + } + } + + if failures.is_empty() { + Ok(()) + } else { + Err(IdempotentCheckError::Mismatch(failures)) + } +} + +// Map source file paths to their target paths. +fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { + if let Some(n) = file_name + .components() + .position(|c| c.as_os_str() == "source") + { + let mut target_file_name = PathBuf::new(); + for (i, c) in file_name.components().enumerate() { + if i == n { + target_file_name.push("target"); + } else { + target_file_name.push(c.as_os_str()); + } + } + if let Some(replace_name) = target { + target_file_name.with_file_name(replace_name) + } else { + target_file_name + } + } else { + // This is either and idempotence check or a self check + file_name.to_owned() + } +} + +#[test] +fn rustfmt_diff_make_diff_tests() { + let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); + assert_eq!( + diff, + vec![ + Mismatch { + line_number: 1, + line_number_orig: 1, + lines: vec![ + DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into()), + ], + }, + ] + ); +} + +#[test] +fn rustfmt_diff_no_diff_test() { + let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); + assert_eq!(diff, vec![]); +} + +// Compare strings without distinguishing between CRLF and LF +fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { + let left = CharsIgnoreNewlineRepr(left.chars().peekable()); + let right = CharsIgnoreNewlineRepr(right.chars().peekable()); + left.eq(right) +} + +struct CharsIgnoreNewlineRepr<'a>(Peekable>); + +impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { + type Item = char; + fn next(&mut self) -> Option { + self.0.next().map(|c| { + if c == '\r' { + if *self.0.peek().unwrap_or(&'\0') == '\n' { + self.0.next(); + '\n' + } else { + '\r' + } + } else { + c + } + }) + } +} + +#[test] +fn string_eq_ignore_newline_repr_test() { + assert!(string_eq_ignore_newline_repr("", "")); + assert!(!string_eq_ignore_newline_repr("", "abc")); + assert!(!string_eq_ignore_newline_repr("abc", "")); + assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); + assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); + assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); +} + +// This enum is used to represent one of three text features in Configurations.md: a block of code +// with its starting line number, the name of a rustfmt configuration option, or the value of a +// rustfmt configuration option. +enum ConfigurationSection { + CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) + ConfigName(String), + ConfigValue(String), +} + +impl ConfigurationSection { + fn get_section>( + file: &mut Enumerate, + ) -> Option { + lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = + regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) + .expect("Failed creating configuration value pattern"); + } + + loop { + match file.next() { + Some((i, line)) => { + if line.starts_with("```rust") { + // Get the lines of the code block. + let lines: Vec = file.map(|(_i, l)| l) + .take_while(|l| !l.starts_with("```")) + .collect(); + let block = format!("{}\n", lines.join("\n")); + + // +1 to translate to one-based indexing + // +1 to get to first line of code (line after "```") + let start_line = (i + 2) as u32; + + return Some(ConfigurationSection::CodeBlock((block, start_line))); + } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); + } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); + } + } + None => return None, // reached the end of the file + } + } + } +} + +// This struct stores the information about code blocks in the configurations +// file, formats the code blocks, and prints formatting errors. +struct ConfigCodeBlock { + config_name: Option, + config_value: Option, + code_block: Option, + code_block_start: Option, +} + +impl ConfigCodeBlock { + fn new() -> ConfigCodeBlock { + ConfigCodeBlock { + config_name: None, + config_value: None, + code_block: None, + code_block_start: None, + } + } + + fn set_config_name(&mut self, name: Option) { + self.config_name = name; + self.config_value = None; + } + + fn set_config_value(&mut self, value: Option) { + self.config_value = value; + } + + fn set_code_block(&mut self, code_block: String, code_block_start: u32) { + self.code_block = Some(code_block); + self.code_block_start = Some(code_block_start); + } + + fn get_block_config(&self) -> Config { + let mut config = Config::default(); + if self.config_value.is_some() && self.config_value.is_some() { + config.override_value( + self.config_name.as_ref().unwrap(), + self.config_value.as_ref().unwrap(), + ); + } + config + } + + fn code_block_valid(&self) -> bool { + // We never expect to not have a code block. + assert!(self.code_block.is_some() && self.code_block_start.is_some()); + + // See if code block begins with #![rustfmt_skip]. + let fmt_skip = self.code_block + .as_ref() + .unwrap() + .split('\n') + .nth(0) + .unwrap_or("") == "#![rustfmt_skip]"; + + if self.config_name.is_none() && !fmt_skip { + write_message(&format!( + "No configuration name for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + if self.config_value.is_none() && !fmt_skip { + write_message(&format!( + "No configuration value for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + true + } + + fn has_parsing_errors(&self, error_summary: Summary) -> bool { + if error_summary.has_parsing_errors() { + write_message(&format!( + "\u{261d}\u{1f3fd} Cannot format {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return true; + } + + false + } + + fn print_diff(&self, compare: Vec) { + let mut mismatches = HashMap::new(); + mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); + print_mismatches(mismatches, |line_num| { + format!( + "\nMismatch at {}:{}:", + CONFIGURATIONS_FILE_NAME, + line_num + self.code_block_start.unwrap() - 1 + ) + }); + } + + fn formatted_has_diff(&self, file_map: &FileMap) -> bool { + let &(ref _file_name, ref text) = file_map.first().unwrap(); + let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + self.print_diff(compare); + return true; + } + + false + } + + // Return a bool indicating if formatting this code block is an idempotent + // operation. This function also triggers printing any formatting failure + // messages. + fn formatted_is_idempotent(&self) -> bool { + // Verify that we have all of the expected information. + if !self.code_block_valid() { + return false; + } + + let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); + let config = self.get_block_config(); + + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + + !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) + } + + // Extract a code block from the iterator. Behavior: + // - Rust code blocks are identifed by lines beginning with "```rust". + // - One explicit configuration setting is supported per code block. + // - Rust code blocks with no configuration setting are illegal and cause an + // assertion failure, unless the snippet begins with #![rustfmt_skip]. + // - Configuration names in Configurations.md must be in the form of + // "## `NAME`". + // - Configuration values in Configurations.md must be in the form of + // "#### `VALUE`". + fn extract>( + file: &mut Enumerate, + prev: Option<&ConfigCodeBlock>, + hash_set: &mut HashSet, + ) -> Option { + let mut code_block = ConfigCodeBlock::new(); + code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); + + loop { + match ConfigurationSection::get_section(file) { + Some(ConfigurationSection::CodeBlock((block, start_line))) => { + code_block.set_code_block(block, start_line); + break; + } + Some(ConfigurationSection::ConfigName(name)) => { + assert!( + Config::is_valid_name(&name), + "an unknown configuration option was found: {}", + name + ); + assert!( + hash_set.remove(&name), + "multiple configuration guides found for option {}", + name + ); + code_block.set_config_name(Some(name)); + } + Some(ConfigurationSection::ConfigValue(value)) => { + code_block.set_config_value(Some(value)); + } + None => return None, // end of file was reached + } + } + + Some(code_block) + } +} + +#[test] +fn configuration_snippet_tests() { + // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one + // entry for each Rust code block found. + fn get_code_blocks() -> Vec { + let mut file_iter = BufReader::new( + fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) + .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + ).lines() + .map(|l| l.unwrap()) + .enumerate(); + let mut code_blocks: Vec = Vec::new(); + let mut hash_set = Config::hash_set(); + + while let Some(cb) = + ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) + { + code_blocks.push(cb); + } + + for name in hash_set { + if !Config::is_hidden_option(&name) { + panic!("{} does not have a configuration guide", name); + } + } + + code_blocks + } + + let blocks = get_code_blocks(); + let failures = blocks + .iter() + .map(|b| b.formatted_is_idempotent()) + .fold(0, |acc, r| acc + (!r as u32)); + + // Display results. + println!("Ran {} configurations tests.", blocks.len()); + assert_eq!(failures, 0, "{} configurations tests failed", failures); +} diff --git a/tests/source/assignment.rs b/tests/source/assignment.rs new file mode 100644 index 00000000000..d5860532086 --- /dev/null +++ b/tests/source/assignment.rs @@ -0,0 +1,30 @@ +// Test assignment + +fn main() { + let some_var : Type ; + + let mut mutable; + + let variable = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; + + variable = LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; + + let single_line_fit = + DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + single_line_fit = 5;single_lit_fit >>= 10; +} + +fn break_meee() { + { + (block_start, block_size, margin_block_start, margin_block_end) = match (block_start, + block_end, + block_size) { + x => 1, + _ => 2, + }; + } +} + +// #2018 +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/tests/source/associated-types-bounds-wrapping.rs b/tests/source/associated-types-bounds-wrapping.rs new file mode 100644 index 00000000000..8f5e2172569 --- /dev/null +++ b/tests/source/associated-types-bounds-wrapping.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 100 +// Test proper wrapping of long associated type bounds + +pub trait HttpService { + type WsService: 'static + Service; +} diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs new file mode 100644 index 00000000000..bffe0f3f16d --- /dev/null +++ b/tests/source/attrib.rs @@ -0,0 +1,155 @@ +// rustfmt-wrap_comments: true +// Test attributes and doc comments are preserved. + +//! Doc comment + +#![attribute] + +//! Crate doc comment + +// Comment + +// Comment on attribute +#![the(attribute)] + +// Another comment + +#[invalid attribute] +fn foo() {} + +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. + +/// Blah blah blah. +impl Bar { + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + #[an_attribute] + fn foo(&mut self) -> isize { + } + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + pub fn f2(self) { + (foo, bar) + } + + #[another_attribute] + fn f3(self) -> Dog { + } + + /// Blah blah bing. + + #[attrib1] + /// Blah blah bing. + #[attrib2] + // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo loooooooooooong. + /// Blah blah bing. + fn f4(self) -> Cat { + } + + // We want spaces around `=` + #[cfg(feature="nightly")] + fn f5(self) -> Monkey {} +} + +// #984 +struct Foo { + # [ derive ( Clone , PartialEq , Debug , Deserialize , Serialize ) ] + foo: usize, +} + +// #1668 + +/// Default path (*nix) +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] +fn foo() { + #[cfg(target_os = "freertos")] + match port_id { + 'a' | 'A' => GpioPort { port_address: GPIO_A }, + 'b' | 'B' => GpioPort { port_address: GPIO_B }, + _ => panic!(), + } + + #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] + let x = 3; +} + +// #1777 +#[test] +#[should_panic(expected = "(")] +#[should_panic(expected = /* ( */ "(")] +#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] +#[should_panic( + /* (((((((( *//* + (((((((((()(((((((( */ + expected = "(" + // (((((((( +)] +fn foo() {} + +// #1799 +fn issue_1799() { + #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 + Some( Err(error) ) ; + + #[allow(unreachable_code)] + // https://github.com/rust-lang/rust/issues/43336 + Some( Err(error) ) ; +} + +// Formatting inner attributes +fn inner_attributes() { + #![ this_is_an_inner_attribute ( foo ) ] + + foo(); +} + +impl InnerAttributes() { + #![ this_is_an_inner_attribute ( foo ) ] + + fn foo() {} +} + +mod InnerAttributes { + #![ this_is_an_inner_attribute ( foo ) ] +} + +fn attributes_on_statements() { + // Local + # [ attr ( on ( local ) ) ] + let x = 3; + + // Item + # [ attr ( on ( item ) ) ] + use foo; + + // Expr + # [ attr ( on ( expr ) ) ] + {} + + // Semi + # [ attr ( on ( semi ) ) ] + foo(); + + // Mac + # [ attr ( on ( mac ) ) ] + foo!(); +} + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] +pub struct HP(pub u8); + +// Long `#[doc = "..."]` +struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } diff --git a/tests/source/big-impl-block.rs b/tests/source/big-impl-block.rs new file mode 100644 index 00000000000..737dd5aeb6a --- /dev/null +++ b/tests/source/big-impl-block.rs @@ -0,0 +1,125 @@ +// rustfmt-indent_style: Block + +// #1357 +impl< + 'a, + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + Groupby, + DB, +> InternalBoxedDsl<'a, DB> + for SelectStatement< + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + GroupBy, + > where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} + +// #1689 +impl SubSelectDirect + where + M: select::Selector, + S: event::Stream, + F: for<'t> FnMut(transform::Api< + 't, + Stream>, + >) + -> transform::Api<'t, X>, + X: event::Stream, +{ +} diff --git a/tests/source/big-impl-visual.rs b/tests/source/big-impl-visual.rs new file mode 100644 index 00000000000..7d906ac37f9 --- /dev/null +++ b/tests/source/big-impl-visual.rs @@ -0,0 +1,106 @@ +// rustfmt-indent_style: Visual + +// #1357 +impl< + 'a, + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + Groupby, + DB, +> InternalBoxedDsl<'a, DB> + for SelectStatement< + Select, + From, + Distinct, + Where, + Order, + Limit, + Offset, + GroupBy, + > where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> { + fn foo() {} +} +impl Foo + for Bar { + fn foo() {} +} diff --git a/tests/source/break-and-continue.rs b/tests/source/break-and-continue.rs new file mode 100644 index 00000000000..c01d8a07845 --- /dev/null +++ b/tests/source/break-and-continue.rs @@ -0,0 +1,23 @@ +// break and continue formatting + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} diff --git a/tests/source/catch.rs b/tests/source/catch.rs new file mode 100644 index 00000000000..64cc9e7a207 --- /dev/null +++ b/tests/source/catch.rs @@ -0,0 +1,27 @@ +#![feature(catch_expr)] + +fn main() { + let x = do catch { + foo()? + }; + + let x = do catch /* Invisible comment */ { foo()? }; + + let x = do catch { + unsafe { foo()? } + }; + + let y = match (do catch { + foo()? + }) { + _ => (), + }; + + do catch { + foo()?; + }; + + do catch { + // Regular do catch block + }; +} diff --git a/tests/source/chains-visual.rs b/tests/source/chains-visual.rs new file mode 100644 index 00000000000..466f6840887 --- /dev/null +++ b/tests/source/chains-visual.rs @@ -0,0 +1,159 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Visual +// Test chain formatting. + +fn main() { + // Don't put chains on a single line if it wasn't so in source. + let a = b .c + .d.1 + .foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x() + .y(|| match cond() { true => (), false => () }); + + loong_func() + .quux(move || if true { + 1 + } else { + 2 + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }).method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }).filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } + + if cond { some(); } else { none(); } + .bar() + .baz(); + + Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); + + Foo { y: i_am_multi_line, z: ok } + .baz(|| { + force(); multiline(); + }) + .quux(); + + a + match x { true => "yay!", false => "boo!" }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained( + self.id, constraints)).unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn issue_1389() { + let names = String::from_utf8(names)?.split('|').map(str::to_owned).collect(); +} + +fn issue1217() -> Result { +let random_chars: String = OsRng::new()? + .gen_ascii_chars() + .take(self.bit_length) + .collect(); + + Ok(Mnemonic::new(&random_chars)) +} + +fn issue1236(options: Vec) -> Result> { +let process = Command::new("dmenu").stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; +} + +fn issue1434() { + for _ in 0..100 { + let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; + } +} + +fn issue2264() { + { + something.function() + .map(|| { + if let a_very_very_very_very_very_very_very_very_long_variable = + compute_this_variable() + { + println!("Hello"); + } + }) + .collect(); + } +} diff --git a/tests/source/chains.rs b/tests/source/chains.rs new file mode 100644 index 00000000000..0ed52ae61be --- /dev/null +++ b/tests/source/chains.rs @@ -0,0 +1,231 @@ +// rustfmt-normalize_comments: true +// rustfmt-use_small_heuristics: false +// Test chain formatting. + +fn main() { + let a = b .c + .d.1 + .foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd.eeeeeeee(); + + let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x() + .y(|| match cond() { true => (), false => () }); + + loong_func() + .quux(move || if true { + 1 + } else { + 2 + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }).method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = xxxxxxx + .map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + body.fold(Body::new(), |mut body, chunk| { + body.extend(chunk); + Ok(body) + }).and_then(move |body| { + let req = Request::from_parts(parts, body); + f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) + }); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }).filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } + + if cond { some(); } else { none(); } + .bar() + .baz(); + + Foo { x: val } .baz(|| { force(); multiline(); }) .quux(); + + Foo { y: i_am_multi_line, z: ok } + .baz(|| { + force(); multiline(); + }) + .quux(); + + a + match x { true => "yay!", false => "boo!" }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained( + self.id, constraints)).unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + let x = expr?; + let y = expr.kaas()?.test(); + let loooooooooooooooooooooooooooooooooooooooooong = does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); + let zzzz = expr?.another?.another?.another?.another?; + let aaa = x ???????????? ?????????????? ???? ????? ?????????????? ????????? ?????????????? ??; + + let y = a.very .loooooooooooooooooooooooooooooooooooooong() .chain() + .inside() .weeeeeeeeeeeeeee()? .test() .0 + .x; + + parameterized(f, + substs, + def_id, + Ns::Value, + &[], + |tcx| tcx.lookup_item_type(def_id).generics)?; + fooooooooooooooooooooooooooo()?.bar()?.baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; +} + +fn issue_1004() { + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), + } + ?; + + ty::tls::with(|tcx| { + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + }) + ?; +} + +fn issue1392() { + test_method(r#" + if foo { + a(); + } + else { + b(); + } + "#.trim()); +} + +// #2067 +impl Settings { + fn save(&self) -> Result<()> { + let mut file = File::create(&settings_path).chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; + } +} + +fn issue2126() { + { + { + { + { + { + let x = self.span_from(sub_span.expect("No span found for struct arant variant")); + self.sspanpan_from_span(sub_span.expect("No span found for struct variant")); + let x = self.spanpan_from_span(sub_span.expect("No span found for struct variant"))?; + } + } + } + } + } +} + +// #2200 +impl Foo { + pub fn from_ast(diagnostic: &::errors::Handler, + attrs: &[ast::Attribute]) -> Attributes { + let other_attrs = attrs.iter().filter_map(|attr| { + attr.with_desugared_doc(|attr| { + if attr.check_name("doc") { + if let Some(mi) = attr.meta() { + if let Some(value) = mi.value_str() { + doc_strings.push(DocFragment::Include(line, + attr.span, + filename, + contents)); + } + } + } + }) + }).collect(); + } +} + +// #2415 +// Avoid orphan in chain +fn issue2415() { + let base_url = (|| { + // stuff + + Ok((|| { + // stuff + Some(value.to_string()) + })() + .ok_or("")?) + })() + .unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); +} diff --git a/tests/source/closure-block-inside-macro.rs b/tests/source/closure-block-inside-macro.rs new file mode 100644 index 00000000000..c1260592083 --- /dev/null +++ b/tests/source/closure-block-inside-macro.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Block + +// #1547 +fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; + } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); +}); diff --git a/tests/source/closure.rs b/tests/source/closure.rs new file mode 100644 index 00000000000..e93cc3fb40f --- /dev/null +++ b/tests/source/closure.rs @@ -0,0 +1,213 @@ +// rustfmt-normalize_comments: true +// Closures + +fn main() { + let square = ( |i: i32 | i * i ); + + let commented = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // format comments. + if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo() + } else { + field.span.lo() + }}; + + let unblock_me = |trivial| { + closure() + }; + + let empty = |arg| {}; + + let simple = |arg| { /* comment formatting */ foo(arg) }; + + let test = | | { do_something(); do_something_else(); }; + + let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; + + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { + foo() + }; + + let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; + arg2 * arg1 - temp }; + + let block_body_with_comment = args.iter() + .map(|a| { + // Emitting only dep-info is possible only for final crate type, as + // as others may emit required metadata for dependent crate types + if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { + "--emit=dep-info" + } else { a } + }); +} + +fn issue311() { + let func = |x| println!("{}", x); + + (func)(0.0); +} + +fn issue863() { + let closure = |x| match x { + 0 => true, + _ => false, + } == true; +} + +fn issue934() { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) || + swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)) + } + } + } +} + +fn foo() { + lifetimes_iter___map(|lasdfasfd| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi() + }; + }); +} + +fn issue1405() { + open_raw_fd(fd, b'r') + .and_then(|file| Capture::new_raw(None, |_, err| unsafe { + raw::pcap_fopen_offline(file, err) + })); +} + +fn issue1466() { + let vertex_buffer = frame.scope(|ctx| { + let buffer = + ctx.create_host_visible_buffer::>(&vertices); + ctx.create_device_local_buffer(buffer) + }); +} + +fn issue470() { + {{{ + let explicit_arg_decls = + explicit_arguments.into_iter() + .enumerate() + .map(|(index, (ty, pattern))| { + let lvalue = Lvalue::Arg(index as u32); + block = this.pattern(block, + argument_extent, + hair::PatternRef::Hair(pattern), + &lvalue); + ArgDecl { ty: ty } + }); + }}} +} + +// #1509 +impl Foo { + pub fn bar(&self) { + Some(SomeType { + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| { + Ok(f) + })), + }) + } +} + +fn issue1329() { + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }) + .filter +} + +fn issue325() { + let f = || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; +} + +fn issue1697() { + Test.func_a(A_VERY_LONG_CONST_VARIABLE_NAME, move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4) +} + +fn issue1694() { + foooooo(|_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| format!("refs/pull/{}/merge", pr_id)) +} + +fn issue1713() { + rayon::join( + || recurse(left, is_less, pred, limit), + || recurse(right, is_less, Some(pivot), limit), + ); + + rayon::join( + 1, + || recurse(left, is_less, pred, limit), + 2, + || recurse(right, is_less, Some(pivot), limit), + ); +} + +fn issue2063() { + |ctx: Ctx<(String, String)>| -> io::Result { + Ok(Response::new().with_body(ctx.params.0)) + } +} + +fn issue1524() { + let f = |x| {{{{x}}}}; + let f = |x| {{{x}}}; + let f = |x| {{x}}; + let f = |x| {x}; + let f = |x| x; +} + +fn issue2171() { + foo(|| unsafe { + if PERIPHERALS { + loop {} + } else { + PERIPHERALS = true; + } + }) +} + +fn issue2207() { + a.map(|_| unsafe { + a_very_very_very_very_very_very_very_long_function_name_or_anything_else() + }.to_string()) +} + +fn issue2262() { + result.init(&mut result.slave.borrow_mut(), &mut (result.strategy)()).map_err(|factory| Error { + factory, + slave: None, + })?; +} diff --git a/tests/source/comment.rs b/tests/source/comment.rs new file mode 100644 index 00000000000..b6ce5267fcb --- /dev/null +++ b/tests/source/comment.rs @@ -0,0 +1,90 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//! Doc comment +fn test() { + /*! + * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam */ + +// comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me + + // #1388 + const EXCEPTION_PATHS: &'static [&'static str] = + &[// std crates + "src/libstd/sys/", // Platform-specific code for std lives here. + "src/bootstrap"]; +} + + /// test123 +fn doc_comment() { +} + +fn chains() { + foo.bar(|| { + let x = 10; + /* comment */ x }) +} + +fn issue_1086() { + /**/ +} + +/* + * random comment */ + +fn main() {/* Test */} + +// #1643 +fn some_fn() /* some comment */ +{ +} + +fn some_fn1() +// some comment +{ +} + +fn some_fn2() // some comment +{ +} + +fn some_fn3() /* some comment some comment some comment some comment some comment some comment so */ +{ +} + +fn some_fn4() +/* some comment some comment some comment some comment some comment some comment some comment */ +{ +} + +// #1603 +pub enum Foo { + A, // `/** **/` + B, // `/*!` + C, +} diff --git a/tests/source/comment2.rs b/tests/source/comment2.rs new file mode 100644 index 00000000000..d68bb5483dc --- /dev/null +++ b/tests/source/comment2.rs @@ -0,0 +1,4 @@ +// rustfmt-wrap_comments: true + +/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. +pub mod foo {} diff --git a/tests/source/comment3.rs b/tests/source/comment3.rs new file mode 100644 index 00000000000..f19a8586334 --- /dev/null +++ b/tests/source/comment3.rs @@ -0,0 +1,5 @@ +// rustfmt-wrap_comments: true + +//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly and justly. + +pub mod foo {} diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs new file mode 100644 index 00000000000..ff1445378d7 --- /dev/null +++ b/tests/source/comment4.rs @@ -0,0 +1,52 @@ +#![allow(dead_code)] // bar + +//! Doc comment +fn test() { +// comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + + /// test123 +fn doc_comment() { +} + +/* +Regression test for issue #956 + +(some very important text) +*/ + +/* +fn debug_function() { + println!("hello"); +} +// */ + +#[link_section=".vectors"] +#[no_mangle] // Test this attribute is preserved. +#[cfg_attr(rustfmt, rustfmt_skip)] +pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/source/comment5.rs b/tests/source/comment5.rs new file mode 100644 index 00000000000..2835d8b2578 --- /dev/null +++ b/tests/source/comment5.rs @@ -0,0 +1,14 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//@ special comment +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ +//@foo +fn test() {} + +//@@@ another special comment +//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@@@ +//@@@foo +fn bar() {} diff --git a/tests/source/comment_crlf_newline.rs b/tests/source/comment_crlf_newline.rs new file mode 100644 index 00000000000..7a65f762f6c --- /dev/null +++ b/tests/source/comment_crlf_newline.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true +/* Block comments followed by CRLF newlines should not an extra newline at the end */ + +/* Something else */ diff --git a/tests/source/configs/blank_lines_lower_bound/1.rs b/tests/source/configs/blank_lines_lower_bound/1.rs new file mode 100644 index 00000000000..c6058a55b0a --- /dev/null +++ b/tests/source/configs/blank_lines_lower_bound/1.rs @@ -0,0 +1,13 @@ +// rustfmt-blank_lines_lower_bound: 1 + +fn foo() {} +fn bar() {} +// comment +fn foobar() {} + +fn foo1() {} +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/tests/source/configs/brace_style/fn_always_next_line.rs b/tests/source/configs/brace_style/fn_always_next_line.rs new file mode 100644 index 00000000000..d3bd9ac09aa --- /dev/null +++ b/tests/source/configs/brace_style/fn_always_next_line.rs @@ -0,0 +1,14 @@ +// rustfmt-brace_style: AlwaysNextLine +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { + // body +} diff --git a/tests/source/configs/brace_style/fn_prefer_same_line.rs b/tests/source/configs/brace_style/fn_prefer_same_line.rs new file mode 100644 index 00000000000..78a4495243d --- /dev/null +++ b/tests/source/configs/brace_style/fn_prefer_same_line.rs @@ -0,0 +1,14 @@ +// rustfmt-brace_style: PreferSameLine +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { + // body +} diff --git a/tests/source/configs/brace_style/fn_same_line_where.rs b/tests/source/configs/brace_style/fn_same_line_where.rs new file mode 100644 index 00000000000..3b78932e177 --- /dev/null +++ b/tests/source/configs/brace_style/fn_same_line_where.rs @@ -0,0 +1,14 @@ +// rustfmt-brace_style: SameLineWhere +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) where T: Add + Sub + Mul + Div { + // body +} diff --git a/tests/source/configs/brace_style/item_always_next_line.rs b/tests/source/configs/brace_style/item_always_next_line.rs new file mode 100644 index 00000000000..0cc19b34da7 --- /dev/null +++ b/tests/source/configs/brace_style/item_always_next_line.rs @@ -0,0 +1,20 @@ +// rustfmt-brace_style: AlwaysNextLine +// Item brace style + +enum Foo {} + +struct Bar {} + +struct Lorem { + ipsum: bool, +} + +struct Dolor where T: Eq { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/tests/source/configs/brace_style/item_prefer_same_line.rs b/tests/source/configs/brace_style/item_prefer_same_line.rs new file mode 100644 index 00000000000..4412bc869a2 --- /dev/null +++ b/tests/source/configs/brace_style/item_prefer_same_line.rs @@ -0,0 +1,16 @@ +// rustfmt-brace_style: PreferSameLine +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor where T: Eq { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/tests/source/configs/brace_style/item_same_line_where.rs b/tests/source/configs/brace_style/item_same_line_where.rs new file mode 100644 index 00000000000..b8e69147dc5 --- /dev/null +++ b/tests/source/configs/brace_style/item_same_line_where.rs @@ -0,0 +1,16 @@ +// rustfmt-brace_style: SameLineWhere +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor where T: Eq { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/tests/source/configs/comment_width/above.rs b/tests/source/configs/comment_width/above.rs new file mode 100644 index 00000000000..36187ce0af4 --- /dev/null +++ b/tests/source/configs/comment_width/above.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/tests/source/configs/comment_width/below.rs b/tests/source/configs/comment_width/below.rs new file mode 100644 index 00000000000..abbc5930c4c --- /dev/null +++ b/tests/source/configs/comment_width/below.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 80 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/tests/source/configs/comment_width/ignore.rs b/tests/source/configs/comment_width/ignore.rs new file mode 100644 index 00000000000..c86e71c2898 --- /dev/null +++ b/tests/source/configs/comment_width/ignore.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: false +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/tests/source/configs/condense_wildcard_suffixes/false.rs b/tests/source/configs/condense_wildcard_suffixes/false.rs new file mode 100644 index 00000000000..3b967f35a8e --- /dev/null +++ b/tests/source/configs/condense_wildcard_suffixes/false.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: false +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, _, _) = (1, 2, 3, 4); +} diff --git a/tests/source/configs/condense_wildcard_suffixes/true.rs b/tests/source/configs/condense_wildcard_suffixes/true.rs new file mode 100644 index 00000000000..3798a6b9902 --- /dev/null +++ b/tests/source/configs/condense_wildcard_suffixes/true.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: true +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, _, _) = (1, 2, 3, 4); +} diff --git a/tests/source/configs/control_brace_style/always_next_line.rs b/tests/source/configs/control_brace_style/always_next_line.rs new file mode 100644 index 00000000000..c4ddad9ce27 --- /dev/null +++ b/tests/source/configs/control_brace_style/always_next_line.rs @@ -0,0 +1,10 @@ +// rustfmt-control_brace_style: AlwaysNextLine +// Control brace style + +fn main() { + if lorem { println!("ipsum!"); } else { println!("dolor!"); } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/tests/source/configs/control_brace_style/always_same_line.rs b/tests/source/configs/control_brace_style/always_same_line.rs new file mode 100644 index 00000000000..a9c699d27e3 --- /dev/null +++ b/tests/source/configs/control_brace_style/always_same_line.rs @@ -0,0 +1,10 @@ +// rustfmt-control_brace_style: AlwaysSameLine +// Control brace style + +fn main() { + if lorem { println!("ipsum!"); } else { println!("dolor!"); } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/tests/source/configs/control_brace_style/closing_next_line.rs b/tests/source/configs/control_brace_style/closing_next_line.rs new file mode 100644 index 00000000000..1a74a28f26a --- /dev/null +++ b/tests/source/configs/control_brace_style/closing_next_line.rs @@ -0,0 +1,10 @@ +// rustfmt-control_brace_style: ClosingNextLine +// Control brace style + +fn main() { + if lorem { println!("ipsum!"); } else { println!("dolor!"); } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/tests/source/configs/disable_all_formatting/false.rs b/tests/source/configs/disable_all_formatting/false.rs new file mode 100644 index 00000000000..834ca7a3c89 --- /dev/null +++ b/tests/source/configs/disable_all_formatting/false.rs @@ -0,0 +1,6 @@ +// rustfmt-disable_all_formatting: false +// Disable all formatting + +fn main() { + if lorem{println!("ipsum!");}else{println!("dolor!");} +} diff --git a/tests/source/configs/disable_all_formatting/true.rs b/tests/source/configs/disable_all_formatting/true.rs new file mode 100644 index 00000000000..56955bf384d --- /dev/null +++ b/tests/source/configs/disable_all_formatting/true.rs @@ -0,0 +1,6 @@ +// rustfmt-disable_all_formatting: true +// Disable all formatting + +fn main() { + iflorem{println!("ipsum!");}else{println!("dolor!");} +} diff --git a/tests/source/configs/empty_item_single_line/false.rs b/tests/source/configs/empty_item_single_line/false.rs new file mode 100644 index 00000000000..8fa74f28802 --- /dev/null +++ b/tests/source/configs/empty_item_single_line/false.rs @@ -0,0 +1,17 @@ +// rustfmt-empty_item_single_line: false +// Empty impl on single line + +impl Lorem { + +} + +impl Ipsum { + +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/tests/source/configs/empty_item_single_line/true.rs b/tests/source/configs/empty_item_single_line/true.rs new file mode 100644 index 00000000000..02e703d1904 --- /dev/null +++ b/tests/source/configs/empty_item_single_line/true.rs @@ -0,0 +1,17 @@ +// rustfmt-empty_item_single_line: true +// Empty impl on single line + +impl Lorem { + +} + +impl Ipsum { + +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/tests/source/configs/error_on_line_overflow/false.rs b/tests/source/configs/error_on_line_overflow/false.rs new file mode 100644 index 00000000000..fa70ae78352 --- /dev/null +++ b/tests/source/configs/error_on_line_overflow/false.rs @@ -0,0 +1,6 @@ +// rustfmt-error_on_line_overflow: false +// Error on line overflow + +fn main() { + let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; +} diff --git a/tests/source/configs/fn_args_density/compressed.rs b/tests/source/configs/fn_args_density/compressed.rs new file mode 100644 index 00000000000..86c0b42e53c --- /dev/null +++ b/tests/source/configs/fn_args_density/compressed.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_density: Compressed +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/tests/source/configs/fn_args_density/tall.rs b/tests/source/configs/fn_args_density/tall.rs new file mode 100644 index 00000000000..fc400e1c113 --- /dev/null +++ b/tests/source/configs/fn_args_density/tall.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_density: Tall +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/tests/source/configs/fn_args_density/vertical.rs b/tests/source/configs/fn_args_density/vertical.rs new file mode 100644 index 00000000000..20b1427d83d --- /dev/null +++ b/tests/source/configs/fn_args_density/vertical.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_density: Vertical +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/tests/source/configs/fn_single_line/false.rs b/tests/source/configs/fn_single_line/false.rs new file mode 100644 index 00000000000..3d092f0c0bf --- /dev/null +++ b/tests/source/configs/fn_single_line/false.rs @@ -0,0 +1,11 @@ +// rustfmt-fn_single_line: false +// Single-expression function on single line + +fn lorem() -> usize { + 42 +} + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/tests/source/configs/fn_single_line/true.rs b/tests/source/configs/fn_single_line/true.rs new file mode 100644 index 00000000000..3cb0fdedf0b --- /dev/null +++ b/tests/source/configs/fn_single_line/true.rs @@ -0,0 +1,11 @@ +// rustfmt-fn_single_line: true +// Single-expression function on single line + +fn lorem() -> usize { + 42 +} + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/tests/source/configs/force_explicit_abi/false.rs b/tests/source/configs/force_explicit_abi/false.rs new file mode 100644 index 00000000000..3c48f8e0c78 --- /dev/null +++ b/tests/source/configs/force_explicit_abi/false.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: false +// Force explicit abi + +extern { + pub static lorem: c_int; +} diff --git a/tests/source/configs/force_explicit_abi/true.rs b/tests/source/configs/force_explicit_abi/true.rs new file mode 100644 index 00000000000..e5ff6cf7dd7 --- /dev/null +++ b/tests/source/configs/force_explicit_abi/true.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: true +// Force explicit abi + +extern { + pub static lorem: c_int; +} diff --git a/tests/source/configs/force_multiline_block/false.rs b/tests/source/configs/force_multiline_block/false.rs new file mode 100644 index 00000000000..b97e348e5da --- /dev/null +++ b/tests/source/configs/force_multiline_block/false.rs @@ -0,0 +1,22 @@ +// rustfmt-force_multiline_blocks: false +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/tests/source/configs/force_multiline_block/true.rs b/tests/source/configs/force_multiline_block/true.rs new file mode 100644 index 00000000000..db9d3de4614 --- /dev/null +++ b/tests/source/configs/force_multiline_block/true.rs @@ -0,0 +1,18 @@ +// rustfmt-force_multiline_blocks: true +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => if ipsum { + println!("dolor"); + }, + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/tests/source/configs/format_strings/false.rs b/tests/source/configs/format_strings/false.rs new file mode 100644 index 00000000000..ecca0d7d1fc --- /dev/null +++ b/tests/source/configs/format_strings/false.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; +} diff --git a/tests/source/configs/format_strings/true.rs b/tests/source/configs/format_strings/true.rs new file mode 100644 index 00000000000..33731447821 --- /dev/null +++ b/tests/source/configs/format_strings/true.rs @@ -0,0 +1,7 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; +} diff --git a/tests/source/configs/hard_tabs/false.rs b/tests/source/configs/hard_tabs/false.rs new file mode 100644 index 00000000000..bf92162b424 --- /dev/null +++ b/tests/source/configs/hard_tabs/false.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: false +// Hard tabs + +fn lorem() -> usize { +42 // spaces before 42 +} diff --git a/tests/source/configs/hard_tabs/true.rs b/tests/source/configs/hard_tabs/true.rs new file mode 100644 index 00000000000..738922a4dfb --- /dev/null +++ b/tests/source/configs/hard_tabs/true.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: true +// Hard tabs + +fn lorem() -> usize { +42 // spaces before 42 +} diff --git a/tests/source/configs/indent_style/block_args.rs b/tests/source/configs/indent_style/block_args.rs new file mode 100644 index 00000000000..4d2d280a16b --- /dev/null +++ b/tests/source/configs/indent_style/block_args.rs @@ -0,0 +1,26 @@ +// rustfmt-indent_style: Block +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { + // body +} + +// #1441 +extern "system" { + pub fn GetConsoleHistoryInfo(console_history_info: *mut ConsoleHistoryInfo) -> Boooooooooooooool; +} + +// rustfmt should not add trailing comma for variadic function. See #1623. +extern "C" { + pub fn variadic_fn(first_parameter: FirstParameterType, + second_parameter: SecondParameterType, + ...); +} + +// #1652 +fn deconstruct(foo: Bar) -> (SocketAddr, Header, Method, RequestUri, HttpVersion, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} diff --git a/tests/source/configs/indent_style/block_array.rs b/tests/source/configs/indent_style/block_array.rs new file mode 100644 index 00000000000..8404f65f471 --- /dev/null +++ b/tests/source/configs/indent_style/block_array.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Array layout + +fn main() { + let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; +} diff --git a/tests/source/configs/indent_style/block_call.rs b/tests/source/configs/indent_style/block_call.rs new file mode 100644 index 00000000000..c82b6b8e38f --- /dev/null +++ b/tests/source/configs/indent_style/block_call.rs @@ -0,0 +1,133 @@ +// rustfmt-indent_style: Block +// Function call style + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); + // #1501 + let hyper = Arc::new(Client::with_connector(HttpsConnector::new(TlsClient::new()))); + + // chain + let x = yooooooooooooo.fooooooooooooooo.baaaaaaaaaaaaar(hello, world); + + // #1380 + { + { + let creds = self.client + .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; + } + } + + // nesting macro and function call + try!(foo(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)); + try!(foo(try!(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx))); +} + +// #1521 +impl Foo { + fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { + unsafe { + Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords(self.render_texture, point.raw(), view.raw())) + } + } +} + +fn issue1420() { + given( + r#" + # Getting started + ... + "#, + ) + .running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| { + Post { + title: row.get(0), + date: row.get(1), + } + }, + )?; + + Ok(()) +} + +// #1449 +fn future_rayon_wait_1_thread() { + // run with only 1 worker thread; this would deadlock if we couldn't make progress + let mut result = None; + ThreadPool::new(Configuration::new().num_threads(1)) + .unwrap() + .install( + || { + scope( + |s| { + use std::sync::mpsc::channel; + let (tx, rx) = channel(); + let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); + // ^^^^ FIXME: why is this needed? + let b = s.spawn_future(a.map(|v| v + 1)); + let c = s.spawn_future(b.map(|v| v + 1)); + s.spawn(move |_| tx.send(20).unwrap()); + result = Some(c.rayon_wait().unwrap()); + }, + ); + }, + ); + assert_eq!(result, Some(22)); +} + +// #1494 +impl Cursor { + fn foo() { + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical != *self { + canonical.num_template_args() + } else { + None + } + }); + } +} + +fn issue1581() { + bootstrap.checks.register( + "PERSISTED_LOCATIONS", + move || if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + }, + ); +} + +fn issue1651() { + { + let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + } +} diff --git a/tests/source/configs/indent_style/block_chain.rs b/tests/source/configs/indent_style/block_chain.rs new file mode 100644 index 00000000000..41d91469114 --- /dev/null +++ b/tests/source/configs/indent_style/block_chain.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Chain indent + +fn main() { + let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); +} diff --git a/tests/source/configs/indent_style/block_generic.rs b/tests/source/configs/indent_style/block_generic.rs new file mode 100644 index 00000000000..2cf17be56ef --- /dev/null +++ b/tests/source/configs/indent_style/block_generic.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Generics indent + +fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { + // body +} diff --git a/tests/source/configs/indent_style/block_struct_lit.rs b/tests/source/configs/indent_style/block_struct_lit.rs new file mode 100644 index 00000000000..47a6994f40c --- /dev/null +++ b/tests/source/configs/indent_style/block_struct_lit.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Struct literal-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/tests/source/configs/indent_style/block_trailing_comma_call.rs b/tests/source/configs/indent_style/block_trailing_comma_call.rs new file mode 100644 index 00000000000..c907ec50d45 --- /dev/null +++ b/tests/source/configs/indent_style/block_trailing_comma_call.rs @@ -0,0 +1,8 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); +} diff --git a/tests/source/configs/indent_style/block_where_pred.rs b/tests/source/configs/indent_style/block_where_pred.rs new file mode 100644 index 00000000000..450491f0270 --- /dev/null +++ b/tests/source/configs/indent_style/block_where_pred.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Where predicate indent + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/tests/source/configs/indent_style/default.rs b/tests/source/configs/indent_style/default.rs new file mode 100644 index 00000000000..f08f5c64460 --- /dev/null +++ b/tests/source/configs/indent_style/default.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Where style + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/tests/source/configs/indent_style/rfc_where.rs b/tests/source/configs/indent_style/rfc_where.rs new file mode 100644 index 00000000000..012840be28d --- /dev/null +++ b/tests/source/configs/indent_style/rfc_where.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Block +// Where style + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/tests/source/configs/indent_style/visual_args.rs b/tests/source/configs/indent_style/visual_args.rs new file mode 100644 index 00000000000..5aa28a62b9c --- /dev/null +++ b/tests/source/configs/indent_style/visual_args.rs @@ -0,0 +1,32 @@ +// rustfmt-indent_style: Visual +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem(ipsum: usize, dolor: usize, sit: usize, amet: usize, consectetur: usize, adipiscing: usize, elit: usize) { + // body +} + +// #1922 +extern "C" { + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + a: *const lapack_complex_float, + lda: lapack_int, ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int + )-> lapack_int; + + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + lda: lapack_int, ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int + ) -> lapack_int; +} diff --git a/tests/source/configs/indent_style/visual_array.rs b/tests/source/configs/indent_style/visual_array.rs new file mode 100644 index 00000000000..05bbf00b1d2 --- /dev/null +++ b/tests/source/configs/indent_style/visual_array.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Array layout + +fn main() { + let lorem = vec!["ipsum","dolor","sit","amet","consectetur","adipiscing","elit"]; +} diff --git a/tests/source/configs/indent_style/visual_call.rs b/tests/source/configs/indent_style/visual_call.rs new file mode 100644 index 00000000000..9a679d6bb4c --- /dev/null +++ b/tests/source/configs/indent_style/visual_call.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Function call style + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit"); +} diff --git a/tests/source/configs/indent_style/visual_chain.rs b/tests/source/configs/indent_style/visual_chain.rs new file mode 100644 index 00000000000..b7494875398 --- /dev/null +++ b/tests/source/configs/indent_style/visual_chain.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Chain indent + +fn main() { + let lorem = ipsum.dolor().sit().amet().consectetur().adipiscing().elite(); +} diff --git a/tests/source/configs/indent_style/visual_generics.rs b/tests/source/configs/indent_style/visual_generics.rs new file mode 100644 index 00000000000..1f910d32d87 --- /dev/null +++ b/tests/source/configs/indent_style/visual_generics.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Generics indent + +fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, adipiscing: Adipiscing, consectetur: Consectetur, elit: Elit) -> T { + // body +} diff --git a/tests/source/configs/indent_style/visual_struct_lit.rs b/tests/source/configs/indent_style/visual_struct_lit.rs new file mode 100644 index 00000000000..45538e70482 --- /dev/null +++ b/tests/source/configs/indent_style/visual_struct_lit.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Struct literal-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/tests/source/configs/indent_style/visual_trailing_comma.rs b/tests/source/configs/indent_style/visual_trailing_comma.rs new file mode 100644 index 00000000000..9738d397dbf --- /dev/null +++ b/tests/source/configs/indent_style/visual_trailing_comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/tests/source/configs/indent_style/visual_where_pred.rs b/tests/source/configs/indent_style/visual_where_pred.rs new file mode 100644 index 00000000000..055806b6862 --- /dev/null +++ b/tests/source/configs/indent_style/visual_where_pred.rs @@ -0,0 +1,6 @@ +// rustfmt-indent_style: Visual +// Where predicate indent + +fn lorem() -> T where Ipsum: Eq, Dolor: Eq, Sit: Eq, Amet: Eq { + // body +} diff --git a/tests/source/configs/match_arm_blocks/false.rs b/tests/source/configs/match_arm_blocks/false.rs new file mode 100644 index 00000000000..53e37e13c4f --- /dev/null +++ b/tests/source/configs/match_arm_blocks/false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: false +// Wrap match-arms + +fn main() { + match lorem { + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => { + println!("{}", sit) + } + } +} diff --git a/tests/source/configs/match_arm_blocks/true.rs b/tests/source/configs/match_arm_blocks/true.rs new file mode 100644 index 00000000000..a452b13cd27 --- /dev/null +++ b/tests/source/configs/match_arm_blocks/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: true +// Wrap match-arms + +fn main() { + match lorem { + true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => { + println!("{}", sit) + } + } +} diff --git a/tests/source/configs/match_block_trailing_comma/false.rs b/tests/source/configs/match_block_trailing_comma/false.rs new file mode 100644 index 00000000000..70e02955fb0 --- /dev/null +++ b/tests/source/configs/match_block_trailing_comma/false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: false +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + } + Lorem::Dolor => println!("dolor"), + } +} diff --git a/tests/source/configs/match_block_trailing_comma/true.rs b/tests/source/configs/match_block_trailing_comma/true.rs new file mode 100644 index 00000000000..b9af3d47202 --- /dev/null +++ b/tests/source/configs/match_block_trailing_comma/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: true +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + } + Lorem::Dolor => println!("dolor"), + } +} diff --git a/tests/source/configs/merge_derives/true.rs b/tests/source/configs/merge_derives/true.rs new file mode 100644 index 00000000000..18b8443f0d7 --- /dev/null +++ b/tests/source/configs/merge_derives/true.rs @@ -0,0 +1,46 @@ +// rustfmt-merge_derives: true +// Merge multiple derives to a single one. + +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} + +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} + +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum FooBar {} + +mod foo { +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} +} + +mod bar { +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} +} + +mod foobar { +#[derive(Eq, PartialEq)] +#[derive(Debug)] +#[derive(Copy, Clone)] +pub enum FooBar {} +} diff --git a/tests/source/configs/normalize_comments/false.rs b/tests/source/configs/normalize_comments/false.rs new file mode 100644 index 00000000000..488962ed936 --- /dev/null +++ b/tests/source/configs/normalize_comments/false.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: false +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +/* sit amet: */ +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/source/configs/normalize_comments/true.rs b/tests/source/configs/normalize_comments/true.rs new file mode 100644 index 00000000000..c74a9808e61 --- /dev/null +++ b/tests/source/configs/normalize_comments/true.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: true +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +/* sit amet: */ +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/source/configs/reorder_extern_crates/false.rs b/tests/source/configs/reorder_extern_crates/false.rs new file mode 100644 index 00000000000..6bef132e5c3 --- /dev/null +++ b/tests/source/configs/reorder_extern_crates/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: false + +extern crate foo; +extern crate bar; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/tests/source/configs/reorder_extern_crates/true.rs b/tests/source/configs/reorder_extern_crates/true.rs new file mode 100644 index 00000000000..bdf00f57cda --- /dev/null +++ b/tests/source/configs/reorder_extern_crates/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: true + +extern crate foo; +extern crate bar; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/tests/source/configs/reorder_imported_names/false.rs b/tests/source/configs/reorder_imported_names/false.rs new file mode 100644 index 00000000000..91db89ceeaa --- /dev/null +++ b/tests/source/configs/reorder_imported_names/false.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: false +// Reorder imported names + +use super::{lorem, ipsum, dolor, sit}; diff --git a/tests/source/configs/reorder_imported_names/true.rs b/tests/source/configs/reorder_imported_names/true.rs new file mode 100644 index 00000000000..69da6186d5a --- /dev/null +++ b/tests/source/configs/reorder_imported_names/true.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: true +// Reorder imported names + +use super::{lorem, ipsum, dolor, sit}; diff --git a/tests/source/configs/reorder_imports/false.rs b/tests/source/configs/reorder_imports/false.rs new file mode 100644 index 00000000000..4b85684dc01 --- /dev/null +++ b/tests/source/configs/reorder_imports/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_imports: false +// Reorder imports + +use lorem; +use ipsum; +use dolor; +use sit; diff --git a/tests/source/configs/reorder_imports/true.rs b/tests/source/configs/reorder_imports/true.rs new file mode 100644 index 00000000000..2a40f6d069f --- /dev/null +++ b/tests/source/configs/reorder_imports/true.rs @@ -0,0 +1,19 @@ +// rustfmt-reorder_imports: true +// Reorder imports + +use lorem; +use ipsum; +use dolor; +use sit; + +fn foo() { + use C; + use B; + use A; + + bar(); + + use F; + use E; + use D; +} diff --git a/tests/source/configs/reorder_imports_in_group/false.rs b/tests/source/configs/reorder_imports_in_group/false.rs new file mode 100644 index 00000000000..87711bb142b --- /dev/null +++ b/tests/source/configs/reorder_imports_in_group/false.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: false +// Reorder imports in group + +/// This comment should stay with `use std::mem;` +use std::mem; +use std::io; + +use lorem; +/// This comment should stay with `use ipsum;` +use ipsum; +use dolor; +use sit; diff --git a/tests/source/configs/reorder_imports_in_group/true.rs b/tests/source/configs/reorder_imports_in_group/true.rs new file mode 100644 index 00000000000..b5690b89cc0 --- /dev/null +++ b/tests/source/configs/reorder_imports_in_group/true.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: true +// Reorder imports in group + +/// This comment should stay with `use std::mem;` +use std::mem; +use std::io; + +use lorem; +/// This comment should stay with `use ipsum;` +use ipsum; +use dolor; +use sit; diff --git a/tests/source/configs/reorder_modules/dolor/mod.rs b/tests/source/configs/reorder_modules/dolor/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/dolor/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/false.rs b/tests/source/configs/reorder_modules/false.rs new file mode 100644 index 00000000000..56b1aa03ed7 --- /dev/null +++ b/tests/source/configs/reorder_modules/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: false +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/tests/source/configs/reorder_modules/ipsum/mod.rs b/tests/source/configs/reorder_modules/ipsum/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/ipsum/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/lorem/mod.rs b/tests/source/configs/reorder_modules/lorem/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/lorem/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/sit/mod.rs b/tests/source/configs/reorder_modules/sit/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/source/configs/reorder_modules/sit/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/source/configs/reorder_modules/true.rs b/tests/source/configs/reorder_modules/true.rs new file mode 100644 index 00000000000..79b0ab1e355 --- /dev/null +++ b/tests/source/configs/reorder_modules/true.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: true +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/tests/source/configs/skip_children/true.rs b/tests/source/configs/skip_children/true.rs new file mode 100644 index 00000000000..cb2b6fce2d2 --- /dev/null +++ b/tests/source/configs/skip_children/true.rs @@ -0,0 +1,3 @@ +// rustfmt-skip_children: true + +mod foo ; diff --git a/tests/source/configs/space_before_colon/true.rs b/tests/source/configs/space_before_colon/true.rs new file mode 100644 index 00000000000..0a597602528 --- /dev/null +++ b/tests/source/configs/space_before_colon/true.rs @@ -0,0 +1,11 @@ +// rustfmt-space_before_colon: true +// Space before colon + +fn lorem(t : T) { + let ipsum: Dolor = sit; +} + +const LOREM : Lorem = Lorem { + ipsum : dolor, + sit : amet, +}; diff --git a/tests/source/configs/spaces_around_ranges/false.rs b/tests/source/configs/spaces_around_ranges/false.rs new file mode 100644 index 00000000000..11ca76b1345 --- /dev/null +++ b/tests/source/configs/spaces_around_ranges/false.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: false +// Spaces around ranges + +fn main() { + let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } +} diff --git a/tests/source/configs/spaces_around_ranges/true.rs b/tests/source/configs/spaces_around_ranges/true.rs new file mode 100644 index 00000000000..50170892130 --- /dev/null +++ b/tests/source/configs/spaces_around_ranges/true.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: true +// Spaces around ranges + +fn main() { + let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } +} diff --git a/tests/source/configs/spaces_within_parens_and_brackets/false.rs b/tests/source/configs/spaces_within_parens_and_brackets/false.rs new file mode 100644 index 00000000000..908373ca9b0 --- /dev/null +++ b/tests/source/configs/spaces_within_parens_and_brackets/false.rs @@ -0,0 +1,7 @@ +// rustfmt-spaces_within_parens_and_brackets: false +// Spaces within parens and brackets + +fn lorem(t: T) { + let lorem = (ipsum, dolor); + let lorem: [usize; 2] = [ipsum, dolor]; +} diff --git a/tests/source/configs/spaces_within_parens_and_brackets/true.rs b/tests/source/configs/spaces_within_parens_and_brackets/true.rs new file mode 100644 index 00000000000..2e3c92da2fc --- /dev/null +++ b/tests/source/configs/spaces_within_parens_and_brackets/true.rs @@ -0,0 +1,133 @@ +// rustfmt-spaces_within_parens_and_brackets: true +// Spaces within parens and brackets + +fn lorem(t: T) { + let lorem = (ipsum, dolor); + let lorem: [usize; 2] = [ipsum, dolor]; +} + +enum E { + A(u32), + B(u32, u32), + C(u32, u32, u32), + D(), +} + +struct TupleStruct0(); +struct TupleStruct1(u32); +struct TupleStruct2(u32, u32); + +fn fooEmpty() {} + +fn foo(e: E, _: u32) -> (u32, u32) { + // Tuples + let t1 = (); + let t2 = (1,); + let t3 = (1, 2); + + let ts0 = TupleStruct0(); + let ts1 = TupleStruct1(1); + let ts2 = TupleStruct2(1, 2); + + // Tuple pattern + let (a,b,c) = (1,2,3); + + // Expressions + let x = (1 + 2) * (3); + + // Function call + fooEmpty(); + foo(1, 2); + + // Pattern matching + match e { + A(_) => (), + B(_, _) => (), + C(..) => (), + D => (), + } + + (1,2) +} + +struct Foo { + i: T, +} + +struct Bar { + i: T, + e: E, +} + +struct Foo<'a> { + i: &'a str, +} + +enum E { + T(T), +} + +enum E { + T(T), + S(S), +} + +fn foo(a: T) { + foo::(10); +} + +fn foo(a: T, b: E) { + foo::(10, "bar"); +} + +fn foo(a: T, b: E) { + foo::(10, "bar"); + + let opt: Option; + let res: Result; +} + +fn foo<'a>(a: &'a str) { + foo("foo"); +} + +fn foo<'a, 'b>(a: &'a str, b: &'b str) { + foo("foo", "bar"); +} + +impl Foo { + fn bar() { + ::bar(); + } +} + +trait MyTrait {} +impl MyTrait for Foo {} + +fn foo() where for<'a> u32: 'a {} + +fn main() { + let arr: [i32; 5] = [1, 2, 3, 4, 5]; + let arr: [i32; 500] = [0; 500]; + + let v = vec![1, 2, 3]; + assert_eq!(arr, [1, 2, 3]); + + let i = arr[0]; + + let slice = &arr[1..2]; + + let line100_________________________________________________________________________ = [1, 2]; + let line101__________________________________________________________________________ = [1, 2]; + let line102___________________________________________________________________________ = [1, 2]; + let line103____________________________________________________________________________ = [1, 2]; + let line104_____________________________________________________________________________ = [1, 2]; + + let line100_____________________________________________________________________ = vec![1, 2]; + let line101______________________________________________________________________ = vec![1, 2]; + let line102_______________________________________________________________________ = vec![1, 2]; + let line103________________________________________________________________________ = vec![1, 2]; + let line104_________________________________________________________________________ = vec![1, 2]; +} + +fn f(slice: &[i32]) {} diff --git a/tests/source/configs/struct_field_align_threshold/20.rs b/tests/source/configs/struct_field_align_threshold/20.rs new file mode 100644 index 00000000000..e68340b027d --- /dev/null +++ b/tests/source/configs/struct_field_align_threshold/20.rs @@ -0,0 +1,383 @@ +// rustfmt-struct_field_align_threshold: 20 +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false + +struct Foo { + x: u32, + yy: u32, // comment + zzz: u32, +} + +pub struct Bar { + x: u32, + yy: u32, + zzz: u32, + + xxxxxxx: u32, +} + +fn main() { + let foo = Foo { + x: 0, + yy: 1, + zzz: 2, + }; + + let bar = Bar { + x: 0, + yy: 1, + zzz: 2, + + xxxxxxx: 3, + }; +} + + /// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct +NewInt (pub i32, SomeType /* inline comment */, T /* sup */ + + + ); + +struct Qux<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy> +( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +struct Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +struct Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +// Will this be a one-liner? +struct Tuple( + A, //Comment + B +); + +pub struct State time::Timespec> { now: F } + +pub struct State ()> { now: F } + +pub struct State { now: F } + +struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(T); +struct Foo(T) where T: Copy, T: Eq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU); + +mod m { + struct X where T: Sized { + a: T, + } +} + +struct Foo(TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +struct Foo {} +struct Foo { + } +struct Foo { + // comment + } +struct Foo { + // trailing space -> + + + } +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:f() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo + { a : 1, b:f( 2)}; + Foo{a:1,b:f(2),..g(3)}; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; + IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { a: bb, c: dd, e: ff }; + + Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ + e: eeeeeeeee }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, .. base }; + Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ + eeeeeeeee }; + Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; +} diff --git a/tests/source/configs/struct_lit_single_line/false.rs b/tests/source/configs/struct_lit_single_line/false.rs new file mode 100644 index 00000000000..17cad8dde29 --- /dev/null +++ b/tests/source/configs/struct_lit_single_line/false.rs @@ -0,0 +1,6 @@ +// rustfmt-struct_lit_single_line: false +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { ipsum: dolor, sit: amet }; +} diff --git a/tests/source/configs/tab_spaces/2.rs b/tests/source/configs/tab_spaces/2.rs new file mode 100644 index 00000000000..5c2667bc2c7 --- /dev/null +++ b/tests/source/configs/tab_spaces/2.rs @@ -0,0 +1,11 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { +let ipsum = dolor(); +let sit = vec![ +"amet", "consectetur", "adipiscing", "elit." +]; +} diff --git a/tests/source/configs/tab_spaces/4.rs b/tests/source/configs/tab_spaces/4.rs new file mode 100644 index 00000000000..da61bbd42a7 --- /dev/null +++ b/tests/source/configs/tab_spaces/4.rs @@ -0,0 +1,11 @@ +// rustfmt-tab_spaces: 4 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { +let ipsum = dolor(); +let sit = vec![ +"amet", "consectetur", "adipiscing", "elit." +]; +} diff --git a/tests/source/configs/trailing_comma/always.rs b/tests/source/configs/trailing_comma/always.rs new file mode 100644 index 00000000000..57e874cd822 --- /dev/null +++ b/tests/source/configs/trailing_comma/always.rs @@ -0,0 +1,7 @@ +// rustfmt-trailing_comma: Always +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; +} diff --git a/tests/source/configs/trailing_comma/never.rs b/tests/source/configs/trailing_comma/never.rs new file mode 100644 index 00000000000..4da3b996f29 --- /dev/null +++ b/tests/source/configs/trailing_comma/never.rs @@ -0,0 +1,23 @@ +// rustfmt-trailing_comma: Never +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; + + // #1544 + if let VrMsg::ClientReply {request_num: reply_req_num, value, ..} = msg { + let _ = safe_assert_eq!(reply_req_num, request_num, op); + return Ok((request_num, op, value)); + } + + // #1710 + pub struct FileInput { + input: StringInput, + file_name: OsString, + } + match len { + Some(len) => Ok(new(self.input, self.pos + len)), + None => Err(self), + } +} diff --git a/tests/source/configs/trailing_comma/vertical.rs b/tests/source/configs/trailing_comma/vertical.rs new file mode 100644 index 00000000000..c903e822158 --- /dev/null +++ b/tests/source/configs/trailing_comma/vertical.rs @@ -0,0 +1,7 @@ +// rustfmt-trailing_comma: Vertical +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { ipsum, dolor, sit, amet, consectetur, adipiscing } = elit; +} diff --git a/tests/source/configs/type_punctuation_density/compressed.rs b/tests/source/configs/type_punctuation_density/compressed.rs new file mode 100644 index 00000000000..223b9a2f0f0 --- /dev/null +++ b/tests/source/configs/type_punctuation_density/compressed.rs @@ -0,0 +1,37 @@ +// rustfmt-type_punctuation_density: Compressed +// Type punctuation density + +fn lorem() { + // body +} + +struct Foo +where U: Eq + Clone { + // body +} + +trait Foo<'a, T = usize> +where T: 'a + Eq + Clone +{ + type Bar: Eq + Clone; +} + +trait Foo: Eq + Clone { + // body +} + +impl Foo<'a> for Bar +where for<'a> T: 'a + Eq + Clone +{ + // body +} + +fn foo<'a, 'b, 'c>() +where 'a: 'b + 'c +{ + // body +} + +fn Foo + Foo>() { + let i = 6; +} diff --git a/tests/source/configs/type_punctuation_density/wide.rs b/tests/source/configs/type_punctuation_density/wide.rs new file mode 100644 index 00000000000..fe0c0816701 --- /dev/null +++ b/tests/source/configs/type_punctuation_density/wide.rs @@ -0,0 +1,37 @@ +// rustfmt-type_punctuation_density: Wide +// Type punctuation density + +fn lorem() { + // body +} + +struct Foo +where U: Eq + Clone { + // body +} + +trait Foo<'a, T = usize> +where T: 'a + Eq + Clone +{ + type Bar: Eq + Clone; +} + +trait Foo: Eq + Clone { + // body +} + +impl Foo<'a> for Bar +where for<'a> T: 'a + Eq + Clone +{ + // body +} + +fn foo<'a, 'b, 'c>() +where 'a: 'b + 'c +{ + // body +} + +fn Foo + Foo>() { + let i = 6; +} diff --git a/tests/source/configs/use_field_init_shorthand/false.rs b/tests/source/configs/use_field_init_shorthand/false.rs new file mode 100644 index 00000000000..16ce740f1b9 --- /dev/null +++ b/tests/source/configs/use_field_init_shorthand/false.rs @@ -0,0 +1,19 @@ +// rustfmt-use_field_init_shorthand: false +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { + x: x, + y: y, + z: z, + }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/source/configs/use_field_init_shorthand/true.rs b/tests/source/configs/use_field_init_shorthand/true.rs new file mode 100644 index 00000000000..1e36c6cff35 --- /dev/null +++ b/tests/source/configs/use_field_init_shorthand/true.rs @@ -0,0 +1,19 @@ +// rustfmt-use_field_init_shorthand: true +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { + x: x, + y: y, + z: z, + }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/source/configs/use_try_shorthand/false.rs b/tests/source/configs/use_try_shorthand/false.rs new file mode 100644 index 00000000000..de7f8b4a5e2 --- /dev/null +++ b/tests/source/configs/use_try_shorthand/false.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: false +// Use try! shorthand + +fn main() { + let lorem = try!(ipsum.map(|dolor| dolor.sit())); +} diff --git a/tests/source/configs/use_try_shorthand/true.rs b/tests/source/configs/use_try_shorthand/true.rs new file mode 100644 index 00000000000..9015ec41e5e --- /dev/null +++ b/tests/source/configs/use_try_shorthand/true.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: true +// Use try! shorthand + +fn main() { + let lorem = try!(ipsum.map(|dolor| dolor.sit())); +} diff --git a/tests/source/configs/where_single_line/true.rs b/tests/source/configs/where_single_line/true.rs new file mode 100644 index 00000000000..daaab865af2 --- /dev/null +++ b/tests/source/configs/where_single_line/true.rs @@ -0,0 +1,24 @@ +// rustfmt-where_single_line: true +// Where style + + +fn lorem_two_items() -> T where Ipsum: Eq, Lorem: Eq { + // body +} + +fn lorem_multi_line( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T +where + Ipsum: Eq, +{ + // body +} + +fn lorem() -> T where Ipsum: Eq { + // body +} diff --git a/tests/source/configs/wrap_comments/false.rs b/tests/source/configs/wrap_comments/false.rs new file mode 100644 index 00000000000..48ecd88accb --- /dev/null +++ b/tests/source/configs/wrap_comments/false.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +} diff --git a/tests/source/configs/wrap_comments/true.rs b/tests/source/configs/wrap_comments/true.rs new file mode 100644 index 00000000000..39a79a4cacc --- /dev/null +++ b/tests/source/configs/wrap_comments/true.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +} + +fn code_block() { + // ```rust + // let x = 3; + // + // println!("x = {}", x); + // ``` +} diff --git a/tests/source/control-brace-style-always-next-line.rs b/tests/source/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..9079fb46c0c --- /dev/null +++ b/tests/source/control-brace-style-always-next-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop { + (); + (); + } + + + 'label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/tests/source/control-brace-style-always-same-line.rs b/tests/source/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..1c8f487e7cd --- /dev/null +++ b/tests/source/control-brace-style-always-same-line.rs @@ -0,0 +1,44 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + + 'label: loop // loop comment + { + (); + } + + + cond = true; + while cond { + (); + } + + + 'while_label: while cond { // while comment + (); + } + + + for obj in iter { + for sub_obj in obj + { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + }, + }; +} diff --git a/tests/source/doc.rs b/tests/source/doc.rs new file mode 100644 index 00000000000..3b25918b12e --- /dev/null +++ b/tests/source/doc.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +// Part of multiple.rs + +// sadfsdfa +//sdffsdfasdf diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/tests/source/else-if-brace-style-always-next-line.rs new file mode 100644 index 00000000000..7b4870fc65a --- /dev/null +++ b/tests/source/else-if-brace-style-always-next-line.rs @@ -0,0 +1,54 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/tests/source/else-if-brace-style-always-same-line.rs new file mode 100644 index 00000000000..41f5305bf8c --- /dev/null +++ b/tests/source/else-if-brace-style-always-same-line.rs @@ -0,0 +1,54 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/tests/source/else-if-brace-style-closing-next-line.rs new file mode 100644 index 00000000000..3b885b3faaa --- /dev/null +++ b/tests/source/else-if-brace-style-closing-next-line.rs @@ -0,0 +1,54 @@ +// rustfmt-control_brace_style: ClosingNextLine + +fn main() { + if false + { + (); + (); + } + + if false // lone if comment + { + (); + (); + } + + + let a = + if 0 > 1 { + unreachable!() + } + else + { + 0x0 + }; + + + if true + { + (); + } else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true // else-if-chain if comment + { + (); + } + else if false // else-if-chain else-if comment + { + (); + (); + } else // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/source/empty_file.rs b/tests/source/empty_file.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/source/enum.rs b/tests/source/enum.rs new file mode 100644 index 00000000000..f3dbae4b84d --- /dev/null +++ b/tests/source/enum.rs @@ -0,0 +1,194 @@ +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Enums test + +#[atrr] +pub enum Test { + A, B(u32, + A /* comment */, + SomeType), + /// Doc comment + C, +} + +pub enum Foo<'a, Y: Baz> where X: Whatever +{ A, } + +enum EmtpyWithComment { + // Some comment +} + +// C-style enum +enum Bar { + A = 1, + #[someAttr(test)] + B = 2, // comment + C, +} + +enum LongVariants { +First(LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment +VARIANT), + // This is the second variant + Second +} + +enum StructLikeVariants { + Normal(u32, String, ), + StructLike { x: i32, // Test comment + // Pre-comment + #[Attr50] y: SomeType, // Aanother Comment + }, SL { a: A } +} + +enum X { + CreateWebGLPaintTask(Size2D, GLContextAttributes, IpcSender, usize), String>>), // This is a post comment +} + +pub enum EnumWithAttributes { + //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // Pre Comment + #[rustfmt_skip] + SkippedItem(String,String,), // Post-comment + #[another_attr] + #[attr2] + ItemStruct {x: usize, y: usize}, // Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // And another + ForcedPreflight // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +pub enum SingleTuple { + // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + Match(usize, usize, String) // Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +pub enum SingleStruct { + Match {name: String, loc: usize} // Post-comment +} + +pub enum GenericEnum +where I: Iterator { + // Pre Comment + Left {list: I, root: T}, // Post-comment + Right {list: I, root: T} // Post Comment +} + + +enum EmtpyWithComment { + // Some comment +} + +enum TestFormatFails { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +} + +fn nested_enum_test() { + if true { + enum TestEnum { + One(usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize, usize,), // AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA + Two // AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAA + } + enum TestNestedFormatFail { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + } +} + + pub struct EmtpyWithComment { + // FIXME: Implement this struct +} + +// #1115 +pub enum Bencoding<'i> { + Str(&'i [u8]), + Int(i64), + List(Vec>), + /// A bencoded dict value. The first element the slice of bytes in the source that the dict is + /// composed of. The second is the dict, decoded into an ordered map. + // TODO make Dict "structlike" AKA name the two values. + Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), +} + +// #1261 +pub enum CoreResourceMsg { + SetCookieForUrl( + ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource + ), +} + +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { Foo } + +// #1046 +pub enum Entry<'a, K: 'a, V: 'a> { + Vacant( + #[ stable( feature = "rust1", since = "1.0.0" ) ] VacantEntry<'a, K, V>, + ), + Occupied( + #[ stable( feature = "rust1", since = "1.0.0" ) ] + OccupiedEntry<'a, K, V>, + ), +} + +// #2081 +pub enum ForegroundColor { + CYAN = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, +} + +// #2098 +pub enum E<'a> { + V ( < std::slice::Iter<'a, Xxxxxxxxxxxxxx> as Iterator> :: Item ) , +} + +// #1809 +enum State { + TryRecv { + pos: usize, + lap: u8, + closed_count: usize, + }, + Subscribe { pos: usize }, + IsReady { pos: usize, ready: bool }, + Unsubscribe { + pos: usize, + lap: u8, + id_woken: usize, + }, + FinalTryRecv { pos: usize, id_woken: usize }, + TimedOut, + Disconnected, +} + +// #2190 +#[derive(Debug, Fail)] +enum AnError { + #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] + UnexpectedSingleToken { token: syn::Token }, +} + +// #2193 +enum WidthOf101 { + #[fail(display = ".....................................................")] Io(::std::io::Error), + #[fail(display = ".....................................................")] Ioo(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), +} + +// #2389 +pub enum QlError { + #[fail(display = "Parsing error: {}", 0)] LexError(parser::lexer::LexError), + #[fail(display = "Parsing error: {:?}", 0)] ParseError(parser::ParseError), + #[fail(display = "Validation error: {:?}", 0)] ValidationError(Vec), + #[fail(display = "Execution error: {}", 0)] ExecutionError(String), + // (from, to) + #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), + // (kind, input, expected) + #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), +} diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs new file mode 100644 index 00000000000..a2e7ac8fc44 --- /dev/null +++ b/tests/source/expr-block.rs @@ -0,0 +1,286 @@ +// rustfmt-indent_style: Block +// Test expressions with block formatting. + +fn arrays() { + [ ]; + let empty = []; + + let foo = [a_long_name, a_very_lng_name, a_long_name]; + + let foo = [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name]; + + vec![a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name]; + + [a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_long_name, a_very_lng_name, a_very_lng_name] +} + +fn arrays() { + let x = [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; + + let a =WeightedChoice::new(&mut [Weighted { + weight: x, + item: 0, + }, + Weighted { + weight: 1, + item: 1, + }, + Weighted { + weight: x, + item: 2, + }, + Weighted { + weight: 1, + item: 3, + }]); + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; + + [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] +} + +fn function_calls() { + let items = itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo(), + span.hi()); + + itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo(), + span.hi()) +} + +fn macros() { + baz!(do_not, add, trailing, commas, inside, of, function, like, macros, even, if_they, are, long); + + baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); + + let _ = match option { + None => baz!(function, like, macro_as, expression, which, is, loooooooooooooooong), + Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), + }; +} + +fn issue_1450() { + if selfstate + .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( + STATE_PARKED, + STATE_UNPARKED, + Release, + Relaxed, + Release, + Relaxed, + ) + .is_ok() { + return; + } +} + +fn foo() { + if real_total <= limit && !pre_line_comments && + !items.into_iter().any(|item| item.as_ref().is_multiline()) { + DefinitiveListTactic::Horizontal + } +} + +fn combine_block() { + foo( + Bar { + x: value, + y: value2, + }, + ); + + foo((Bar { + x: value, + y: value2, + },)); + + foo((1, 2, 3, Bar { + x: value, + y: value2, + })); + + foo((1, 2, 3, |x| { + let y = x + 1; + let z = y + 1; + z + })); + + let opt = Some( + Struct( + long_argument_one, + long_argument_two, + long_argggggggg, + ), + ); + + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); + + Ok( + some_function( + lllllllllong_argument_one, + lllllllllong_argument_two, + lllllllllllllllllllllllllllllong_argument_three, + ), + ); + + foo( + thing, + bar( + param2, + pparam1param1param1param1param1param1param1param1param1param1aram1, + param3, + ), + ); + + foo.map_or( + || { + Ok( + SomeStruct { + f1: 0, + f2: 0, + f3: 0, + }, + ) + }, + ); + + match opt { + Some(x) => somefunc(anotherfunc( + long_argument_one, + long_argument_two, + long_argument_three, + )), + Some(x) => |x| { + let y = x + 1; + let z = y + 1; + z + }, + Some(x) => (1, 2, |x| { + let y = x + 1; + let z = y + 1; + z + }), + Some(x) => SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }, + None => Ok(SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }), + }; + + match x { + y => func( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ), + _ => func( + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzz, + ), + } +} + +fn issue_1862() { + foo( + /* bar = */ None , + something_something, + /* baz = */ None , + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ None , + /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , + ) +} + +fn issue_1878() { + let channel: &str = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; +} diff --git a/tests/source/expr.rs b/tests/source/expr.rs new file mode 100644 index 00000000000..f87c950735f --- /dev/null +++ b/tests/source/expr.rs @@ -0,0 +1,372 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// Test expressions + +fn foo() -> bool { + let boxed: Box = box 5; + let referenced = &5 ; + + let very_long_variable_name = ( a + first + simple + test ); + let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + + let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - + function_call(x, *very_long_pointer, y)) + + 1000 ; + +some_ridiculously_loooooooooooooooooooooong_function(10000 * 30000000000 + 40000 / 1002200000000 + - 50000 * sqrt(-1), + trivial_value); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa))))))))) ; + + { for _ in 0..10 {} } + + {{{{}}}} + + if 1 + 2 > 0 { let result = 5; result } else { 4}; + + if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + // Nothing + } + + if let Some(x) = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {} + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + + 2 + 3 { + } + + if let (some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1111 + 2222 {} + + if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 + + 2 + 3 { + } + + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = item.node + { + // nothing + } + + let test = if true { 5 } else { 3 }; + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + // Check subformatting + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } +} + +fn bar() { + let range = ( 111111111 + 333333333333333333 + 1111 + 400000000000000000) .. (2222 + 2333333333333333); + + let another_range = 5..some_func( a , b /* comment */); + + for _ in 1 ..{ call_forever(); } + + syntactically_correct(loop { sup( '?'); }, if cond { 0 } else { 1 }); + + let third = ..10; + let infi_range = .. ; + let foo = 1..; + let bar = 5 ; + let nonsense = (10 .. 0)..(0..10); + + loop{if true {break}} + + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + a); +} + +fn baz() { + unsafe /* {}{}{}{{{{}} */ { + let foo = 1u32; + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} + + unsafe // So this is a very long comment. + // Multi-line, too. + // Will it still format correctly? + { + } + + unsafe { + // Regular unsafe block + } + + unsafe { + foo() + } + + unsafe { + foo(); + } + + // #2289 + let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; + let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; + let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; + let identifier_3 = unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; +} + +// Test some empty blocks. +fn qux() { + {} + // FIXME this one could be done better. + { /* a block with a comment */ } + { + + } + { + // A block with a comment. + } +} + +fn issue227() { + { + let handler = box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); + } +} + +fn issue184(source: &str) { + for c in source.chars() { + if index < 'a' { + continue; + } + } +} + +fn arrays() { + let x = [0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 7, + 8, + 9, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ strukt { test123: value_one_two_three_four, turbo: coolio(), } , /* comment */ 1 ]; + + let a =WeightedChoice::new(&mut [Weighted { + weightweight: x, + item: 0, + }, + Weighted { + weightweight: 1, + item: 1, + }, + Weighted { + weightweight: x, + item: 2, + }, + Weighted { + weightweight: 1, + item: 3, + }]); + + let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; + + [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] +} + +fn returns() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && return; + + return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +} + +fn addrof() { + & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); +} + +fn casts() { + fn unpack(packed: u32) -> [u16; 2] { + [ + (packed >> 16) as u16, + (packed >> 0) as u16, + ] + } + + let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx + as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; + let slightly_longer_trait = yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; +} + +fn indices() { + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc) [ x + y + z ]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc)[ xxxxx + yyyyy + zzzzz ]; + let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; + let z = xxxxxxxxxx.x().y().zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; +} + +fn repeats() { + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+cccccccccccccccc; x + y + z ]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; xxxxx + yyyyy + zzzzz ]; +} + +fn blocks() { + if 1 + 1 == 2 { + println!("yay arithmetix!"); + }; +} + +fn issue767() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} + +fn ranges() { + let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa .. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ..= bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let z = ..= x ; + + // #1766 + let x = [0. ..10.0]; + let x = [0. ..=10.0]; + + a ..= b + + // the expr below won't compile because inclusive ranges need a defined end + // let a = 0 ..= ; +} + +fn if_else() { + let exact = diff / + (if size == 0 { + 1 +} else { + size +}); + + let cx = tp1.x + + any * radius * + if anticlockwise { + 1.0 + } else { + -1.0 + }; +} + +fn complex_if_else() { + if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { + yo(); + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx { + yo(); + } +} + +fn issue1106() { + { + if let hir::ItemEnum(ref enum_def, ref generics) = self.ast_map.expect_item(enum_node_id).node { + } + } + + for entry in + WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) { + } +} + +fn issue1570() { + a_very_long_function_name({some_func(1, {1})}) +} + +fn issue1714() { + v = &mut {v}[mid..]; + let (left, right) = {v}.split_at_mut(mid); +} + +// Multi-lined index should be put on the next line if it fits in one line. +fn issue1749() { + { + { + { + if self.shape[(r as f32 + self.x_offset) as usize][(c as f32 + self.y_offset) as usize] != 0 { + // hello + } + } + } + } +} + +// #1172 +fn newlines_between_list_like_expr() { + foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ); + + vec![ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ]; + + match x { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | + + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy | + + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), + _ => bar(), + }; +} + +fn issue2178() { + Ok(result.iter().map(|item| ls_util::rls_to_location(item)).collect()) +} diff --git a/tests/source/extern.rs b/tests/source/extern.rs new file mode 100644 index 00000000000..187e698607a --- /dev/null +++ b/tests/source/extern.rs @@ -0,0 +1,60 @@ +// rustfmt-normalize_comments: true + + extern crate foo ; + extern crate foo as bar ; + +extern crate futures; +extern crate dotenv; +extern crate chrono; + +extern crate foo; +extern crate bar; + +// #2315 +extern crate proc_macro2; +extern crate proc_macro; + + extern "C" { + fn c_func(x: *mut *mut libc::c_void); + + fn c_func(x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY); + + #[test123] + fn foo() -> uint64_t; + +pub fn bar() ; + } + +extern { + fn DMR_GetDevice(pHDev: *mut HDEV, searchMode: DeviceSearchMode, pSearchString: *const c_char, devNr: c_uint, wildcard: c_char) -> TDMR_ERROR; + + fn quux() -> (); // Post comment + + pub type + Foo; + + type Bar; +} + +extern "Rust" { static ext: u32; + // Some comment. + pub static mut var : SomeType ; } + +extern "C" { + fn syscall(number: libc::c_long /* comment 1 */, /* comm 2 */ ... /* sup? */) -> libc::c_long; + + fn foo (x: *const c_char , ... ) -> +libc::c_long; + } + + extern { + pub fn freopen(filename: *const c_char, mode: *const c_char + , mode2: *const c_char + , mode3: *const c_char, + file: *mut FILE) + -> *mut FILE; + } + +extern { + +} diff --git a/tests/source/extern_not_explicit.rs b/tests/source/extern_not_explicit.rs new file mode 100644 index 00000000000..9d6c4c2a1cd --- /dev/null +++ b/tests/source/extern_not_explicit.rs @@ -0,0 +1,14 @@ +// rustfmt-force_explicit_abi: false + + extern "C" { + fn some_fn() -> (); + } + + extern "C" fn sup() { + + } + +type funky_func = extern "C" fn (unsafe extern "rust-call" fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8); diff --git a/tests/source/file-lines-1.rs b/tests/source/file-lines-1.rs new file mode 100644 index 00000000000..0164e30a854 --- /dev/null +++ b/tests/source/file-lines-1.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-2.rs b/tests/source/file-lines-2.rs new file mode 100644 index 00000000000..6f44ec6e69d --- /dev/null +++ b/tests/source/file-lines-2.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-3.rs b/tests/source/file-lines-3.rs new file mode 100644 index 00000000000..c4f3e21b1ae --- /dev/null +++ b/tests/source/file-lines-3.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] +// rustfmt-error_on_line_overflow: false + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-4.rs b/tests/source/file-lines-4.rs new file mode 100644 index 00000000000..83928bf6fec --- /dev/null +++ b/tests/source/file-lines-4.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [] +// (Test that nothing is formatted if an empty array is specified.) + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + // aaaaaaaaaaaaa + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/source/file-lines-5.rs b/tests/source/file-lines-5.rs new file mode 100644 index 00000000000..8ec2c67bc44 --- /dev/null +++ b/tests/source/file-lines-5.rs @@ -0,0 +1,17 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] + +struct A { +t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + fn baz() { + let j = 15; + } +} diff --git a/tests/source/file-lines-6.rs b/tests/source/file-lines-6.rs new file mode 100644 index 00000000000..2eacc8a0e75 --- /dev/null +++ b/tests/source/file-lines-6.rs @@ -0,0 +1,18 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + + fn baz() { +/// + let j = 15; + } +} diff --git a/tests/source/file-lines-item.rs b/tests/source/file-lines-item.rs new file mode 100644 index 00000000000..0ed4b93df5f --- /dev/null +++ b/tests/source/file-lines-item.rs @@ -0,0 +1,22 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] +// rustfmt-reorder_imports: true + +use foo::{c, b, a}; +use bar; + +fn foo() { + bar ( ) ; +} + +impl Drop for Context { + fn drop(&mut self) { + } +} + +impl Bar for Baz { + fn foo() { + bar( + baz, // Who knows? + ) + } +} diff --git a/tests/source/fn-custom-2.rs b/tests/source/fn-custom-2.rs new file mode 100644 index 00000000000..72d841544a8 --- /dev/null +++ b/tests/source/fn-custom-2.rs @@ -0,0 +1,36 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); +} + +fn baz() where X: TTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); + } + + fn baz() where X: TTTTTTTT { + baz(); + } +} + +struct Foo { + foo: Foo, +} diff --git a/tests/source/fn-custom-3.rs b/tests/source/fn-custom-3.rs new file mode 100644 index 00000000000..9934fb61efd --- /dev/null +++ b/tests/source/fn-custom-3.rs @@ -0,0 +1,32 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } + + fn bar<'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, TTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW>(a: Aaaaaaaaaaaaaaa) { + bar(); + } +} + +struct Foo { + foo: Foo, +} diff --git a/tests/source/fn-custom-4.rs b/tests/source/fn-custom-4.rs new file mode 100644 index 00000000000..01c00aecb86 --- /dev/null +++ b/tests/source/fn-custom-4.rs @@ -0,0 +1,14 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux() where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} + +fn qux(a: Aaaaaaaaaaaaaaaaa) where X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT { + baz(); +} diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs new file mode 100644 index 00000000000..8e8bb6c274e --- /dev/null +++ b/tests/source/fn-custom-6.rs @@ -0,0 +1,41 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs new file mode 100644 index 00000000000..f7670e07fc8 --- /dev/null +++ b/tests/source/fn-custom-7.rs @@ -0,0 +1,25 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block +// rustfmt-fn_args_density: Vertical +// rustfmt-brace_style: AlwaysNextLine + +// Case with only one variable. +fn foo(a: u8) -> u8 { + bar() +} + +// Case with 2 variables and some pre-comments. +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +// Case with 2 variables and some post-comments. +fn foo(/* Comment 1 */ a: u8, /* Comment 2 */ b: u8) -> u8 { + bar() +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/source/fn-custom-8.rs b/tests/source/fn-custom-8.rs new file mode 100644 index 00000000000..d3deb20a51c --- /dev/null +++ b/tests/source/fn-custom-8.rs @@ -0,0 +1,49 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} + +trait Test { + fn foo( + a: u8) { + + } + + fn bar(a: u8) + -> String { + + } + + fn bar(a: u8) -> String where Foo: foooo, Bar: barrr {} +} diff --git a/tests/source/fn-custom.rs b/tests/source/fn-custom.rs new file mode 100644 index 00000000000..b8d734bfbaf --- /dev/null +++ b/tests/source/fn-custom.rs @@ -0,0 +1,13 @@ +// rustfmt-fn_args_density: Compressed +// Test some of the ways function signatures can be customised. + +// Test compressed layout of args. +fn foo(a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); +} + +impl Foo { + fn foo(self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee) { + foo(); + } +} diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs new file mode 100644 index 00000000000..f1ce503ab0a --- /dev/null +++ b/tests/source/fn-simple.rs @@ -0,0 +1,66 @@ +// rustfmt-normalize_comments: true + +fn simple(/*pre-comment on a function!?*/ i: i32/*yes, it's possible! */ + ,response: NoWay /* hose */) { +fn op(x: Typ, key : &[u8], upd : Box) -> (memcache::Status, Result>)>) -> MapResult {} + + "cool"} + + +fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* triple, even */*/*/, +// Does this work? +y: World +) { + simple(/* does this preserve comments now? */ 42, NoWay) +} + +fn generic(arg: T) -> &SomeType + where T: Fn(// First arg + A, + // Second argument + B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { + arg(a, b, c, d, e) +} + +fn foo() -> ! {} + +pub fn http_fetch_async(listener:Box< AsyncCORSResponseListener+Send >, script_chan: Box) { +} + +fn some_func>(val:T){} + +fn zzzzzzzzzzzzzzzzzzzz + (selff: Type, mut handle: node::Handle>, Type, NodeType>) + -> SearchStack<'a, K, V, Type, NodeType>{ +} + +unsafe fn generic_call(cx: *mut JSContext, argc: libc::c_uint, vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern fn(*const JSJitInfo, *mut JSContext, + HandleObject, *mut libc::c_void, u32, + *mut JSVal) + -> u8) { + let f: fn ( _ , _ ) -> _ = panic!() ; +} + +pub fn start_export_thread(database: &Database, crypto_scheme: &C, block_size: usize, source_path: &Path) -> BonzoResult> {} + +pub fn waltz(cwd: &Path) -> CliAssert { + { + { + formatted_comment = rewrite_comment(comment, block_style, width, offset, formatting_fig); + } + } +} + +// #2003 +mod foo { + fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() { + foo(); + } +} + +// #2082 +pub(crate) fn init() {} + +crate fn init() {} diff --git a/tests/source/fn-single-line.rs b/tests/source/fn-single-line.rs new file mode 100644 index 00000000000..6d7f764d280 --- /dev/null +++ b/tests/source/fn-single-line.rs @@ -0,0 +1,79 @@ +// rustfmt-fn_single_line: true +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/tests/source/fn_args_density-vertical.rs b/tests/source/fn_args_density-vertical.rs new file mode 100644 index 00000000000..b61c337dfb9 --- /dev/null +++ b/tests/source/fn_args_density-vertical.rs @@ -0,0 +1,33 @@ +// rustfmt-fn_args_density: Vertical + +// Empty list should stay on one line. +fn do_bar( + +) -> u8 { + bar() +} + +// A single argument should stay on the same line. +fn do_bar( + a: u8) -> u8 { + bar() +} + +// Multiple arguments should each get their own line. +fn do_bar(a: u8, mut b: u8, c: &u8, d: &mut u8, closure: &Fn(i32) -> i32) -> i32 { + // This feature should not affect closures. + let bar = |x: i32, y: i32| -> i32 { x + y }; + bar(a, b) +} + +// If the first argument doesn't fit on the same line with the function name, +// the whole list should probably be pushed to the next line with hanging +// indent. That's not what happens though, so check current behaviour instead. +// In any case, it should maintain single argument per line. +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, c: u8, d: u8) { + this(); + that(); + the_other_thing(); +} diff --git a/tests/source/fn_args_indent-block.rs b/tests/source/fn_args_indent-block.rs new file mode 100644 index 00000000000..b056fcb56fe --- /dev/null +++ b/tests/source/fn_args_indent-block.rs @@ -0,0 +1,78 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo(a: u8 /* Comment 1 */, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee /* Comment 2 */) -> u8 { + bar() +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where X: Fooooo, Y: Baaar { + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T where X: Foooo, Y: Baaar { + foo(); +} + +fn foo() where X: Foooo { +} + +fn foo() where X: Foooo, Y: Baaar { +} + +fn foo() -> (Loooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiis, Looooooooooooooooong) { + foo(); +} + +fn foo() { + foo(); +} + +fn foo() { + foo(); +} + +fn foo() { + foo(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String {} +} + +fn foo(a: Aaaaaaaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd) { + foo(); +} + +fn foo() -> (Looooooooooooooooooooooooooong, Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, iiiiiiiiiiiiiis, Loooooooooooooooooooooong) { + foo(); +} diff --git a/tests/source/hard-tabs.rs b/tests/source/hard-tabs.rs new file mode 100644 index 00000000000..b8fd09f8792 --- /dev/null +++ b/tests/source/hard-tabs.rs @@ -0,0 +1,85 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-hard_tabs: true +// rustfmt-error_on_line_overflow: false + +fn main() { +let x = Bar; + +let y = Foo {a: x }; + +Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + +fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) {} + +let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + +if let (some_very_large, tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple) = 1 ++ 2 + 3 { +} + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } + +unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment */ {} + +unsafe // So this is a very long comment. + // Multi-line, too. + // Will it still format correctly? +{ +} + +let chain = funktion_kall().go_to_next_line_with_tab().go_to_next_line_with_tab().go_to_next_line_with_tab(); + +let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz, q]; + +fn generic(arg: T) -> &SomeType + where T: Fn(// First arg + A, + // Second argument + B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { + arg(a, b, c, d, e) +} + + loong_func().quux(move || { + if true { + 1 + } else { + 2 + } + }); + + fffffffffffffffffffffffffffffffffff(a, + { + SCRIPT_TASK_ROOT + .with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + a.b + .c + .d(); + + x().y(|| { + match cond() { + true => (), + false => (), + } + }); +} + +// #2296 +impl Foo { + // a comment + // on multiple lines + fn foo() { + // another comment + // on multiple lines + let x = true; + } +} diff --git a/tests/source/hello.rs b/tests/source/hello.rs new file mode 100644 index 00000000000..f892e6debb1 --- /dev/null +++ b/tests/source/hello.rs @@ -0,0 +1,6 @@ +// rustfmt-config: small_tabs.toml +// rustfmt-target: hello.rs + +// Smoke test - hello world. + +fn main() { println!("Hello world!"); } diff --git a/tests/source/hello2.rs b/tests/source/hello2.rs new file mode 100644 index 00000000000..48af7de3887 --- /dev/null +++ b/tests/source/hello2.rs @@ -0,0 +1,8 @@ +// rustfmt-config: small_tabs.toml +// rustfmt-target: hello.rs + +// Smoke test - hello world. + +fn main( ) { +println!("Hello world!"); +} diff --git a/tests/source/immovable_generators.rs b/tests/source/immovable_generators.rs new file mode 100644 index 00000000000..c57a1e14483 --- /dev/null +++ b/tests/source/immovable_generators.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +unsafe fn foo() { + let mut ga = static || { + yield 1; + }; +} diff --git a/tests/source/impls.rs b/tests/source/impls.rs new file mode 100644 index 00000000000..ca8e486646a --- /dev/null +++ b/tests/source/impls.rs @@ -0,0 +1,154 @@ +// rustfmt-normalize_comments: true +impl Foo for Bar { fn foo() { "hi" } } + +pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; + // Comment 1 + fn foo() { "hi" } + // Comment 2 + fn foo() { "hi" } + // Comment 3 +} + +pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { + fn foo() { "hi" } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> +{ + fn foo() { "hi" } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> +{ + fn foo() { "hi" } +} + +impl Foo for Bar where T: Baz +{ +} + +impl Foo for Bar where T: Baz { /* Comment */ } + +impl Foo { + fn foo() {} +} + +impl Boo { + + // BOO + fn boo() {} + // FOO + + + +} + +mod a { + impl Foo { + // Hello! + fn foo() {} + } +} + + +mod b { + mod a { + impl Foo { + fn foo() {} + } + } +} + +impl Foo { add_fun!(); } + +impl Blah { + fn boop() {} + add_fun!(); +} + +impl X { fn do_parse( mut self : X ) {} } + +impl Y5000 { + fn bar(self: X< 'a , 'b >, y: Y) {} + + fn bad(&self, ( x, y): CoorT) {} + + fn turbo_bad(self: X< 'a , 'b > , ( x, y): CoorT) { + + } +} + +pub impl Foo for Bar where T: Foo +{ + fn foo() { "hi" } +} + +pub impl Foo for Bar where T: Foo, Z: Baz {} + +mod m { + impl PartialEq for S where T: PartialEq { + fn eq(&self, other: &Self) { + true + } + } + + impl PartialEq for S where T: PartialEq { } + } + +impl Handle, HandleType> { +} + +impl PartialEq for Handle, HandleType> { +} + +mod x { + impl Foo + where A: 'static, + B: 'static, + C: 'static, + D: 'static { } +} + +impl Issue1249 { + // Creates a new flow constructor. + fn foo() {} +} + +// #1600 +impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { + fn drop() {} +} + +// #1168 +pub trait Number: Copy + Eq + Not + Shl + + Shr + + BitAnd + BitOr + BitAndAssign + BitOrAssign + + + +{ + // test + fn zero() -> Self; +} + +// #1642 +pub trait SomeTrait : Clone + Eq + PartialEq + Ord + PartialOrd + Default + Hash + Debug + Display + Write + Read + FromStr { + // comment +} + +// #1995 +impl Foo { + fn f( + S { + aaaaaaaaaa: aaaaaaaaaa, + bbbbbbbbbb: bbbbbbbbbb, + cccccccccc: cccccccccc, + }: S + ) -> u32{ + 1 + } +} diff --git a/tests/source/imports-reorder-lines-and-items.rs b/tests/source/imports-reorder-lines-and-items.rs new file mode 100644 index 00000000000..3c71f9984fe --- /dev/null +++ b/tests/source/imports-reorder-lines-and-items.rs @@ -0,0 +1,10 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true + +/// This comment should stay with `use std::str;` +use std::str; +use std::cmp::{d, c, b, a}; +use std::ddd::aaa; +use std::ddd::{d as p, c as g, b, a}; +// This comment should stay with `use std::ddd:bbb;` +use std::ddd::bbb; diff --git a/tests/source/imports-reorder-lines.rs b/tests/source/imports-reorder-lines.rs new file mode 100644 index 00000000000..a855a964235 --- /dev/null +++ b/tests/source/imports-reorder-lines.rs @@ -0,0 +1,34 @@ +// rustfmt-reorder_imports: true + +use std::str; +use std::cmp::{d, c, b, a}; +use std::cmp::{b, e, g, f}; +use std::ddd::aaa; +// This comment should stay with `use std::ddd;` +use std::ddd; +use std::ddd::bbb; + +mod test { +} + +use aaa::bbb; +use aaa; +use aaa::*; + +mod test {} +// If item names are equal, order by rename + +use test::{a as bb, b}; +use test::{a as aa, c}; + +mod test {} +// If item names are equal, order by rename - no rename comes before a rename + +use test::{a as bb, b}; +use test::{a, c}; + +mod test {} +// `self` always comes first + +use test::{a as aa, c}; +use test::{self as bb, b}; diff --git a/tests/source/imports-reorder.rs b/tests/source/imports-reorder.rs new file mode 100644 index 00000000000..200cad2d13c --- /dev/null +++ b/tests/source/imports-reorder.rs @@ -0,0 +1,6 @@ +// rustfmt-normalize_comments: true +// rustfmt-reorder_imported_names: true + +use path::{C,/*A*/ A, B /* B */, self /* self */}; + +use {ab, ac, aa, Z, b}; diff --git a/tests/source/imports.rs b/tests/source/imports.rs new file mode 100644 index 00000000000..73d1419f47d --- /dev/null +++ b/tests/source/imports.rs @@ -0,0 +1,89 @@ +// rustfmt-normalize_comments: true +// rustfmt-error_on_line_overflow: false + +// Imports. + +// Long import. +use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; +use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; + +use list::{ + // Some item + SomeItem /* Comment */, /* Another item */ AnotherItem /* Another Comment */, // Last Item + LastItem +}; + +use test::{ Other /* C */ , /* A */ self /* B */ }; + +use syntax::{self}; +use {/* Pre-comment! */ + Foo, Bar /* comment */}; +use Foo::{Bar, Baz}; +pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; +use syntax::some::{}; + +use self; +use std::io::{self}; +use std::io::self; + +mod Foo { + pub use syntax::ast::{ + ItemForeignMod, + ItemImpl, + ItemMac, + ItemMod, + ItemStatic, + ItemDefaultImpl + }; + + mod Foo2 { + pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; + } +} + +fn test() { +use Baz::*; + use Qux; +} + +// Simple imports +use foo::bar::baz as baz ; +use bar::quux as kaas; +use foo; + +// With aliases. +use foo::{self as bar, baz}; +use foo::{self as bar}; +use foo::{qux as bar}; +use foo::{baz, qux as bar}; + +// With absolute paths +use ::foo; +use ::foo::{Bar}; +use ::foo::{Bar, Baz}; +use ::{Foo}; +use ::{Bar, Baz}; + +// Root globs +use *; +use ::*; + +// spaces used to cause glob imports to disappear (#1356) +use super:: * ; +use foo::issue_1356:: * ; + +// We shouldn't remove imports which have attributes attached (#1858) +#[cfg(unix)] +use self::unix::{}; + +// nested imports +use foo::{a, bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}, b, boo, c,}; + +use fooo::{baar::{foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}}, z, bar, bar::*, x, y}; + +// nested imports with a single sub-tree. +use a::{b::{c::*}}; +use a::{b::{c::{}}}; +use a::{b::{c::d}}; +use a::{b::{c::{xxx, yyy, zzz}}}; diff --git a/tests/source/issue-1021.rs b/tests/source/issue-1021.rs new file mode 100644 index 00000000000..380e24cc0b0 --- /dev/null +++ b/tests/source/issue-1021.rs @@ -0,0 +1,22 @@ +// rustfmt-normalize_comments: true +fn main() { + match x { + S(true , .., true ) => (), + S(true , .. ) => (), + S(.., true ) => (), + S( .. ) => (), + S(_) => (), + S(/* .. */ .. ) => (), + S(/* .. */ .., true ) => (), + } + + match y { + (true , .., true ) => (), + (true , .. ) => (), + (.., true ) => (), + ( .. ) => (), + (_,) => (), + (/* .. */ .. ) => (), + (/* .. */ .., true ) => (), + } +} diff --git a/tests/source/issue-1049.rs b/tests/source/issue-1049.rs new file mode 100644 index 00000000000..bcfba41e768 --- /dev/null +++ b/tests/source/issue-1049.rs @@ -0,0 +1,18 @@ +// Test overlong function signature +pub unsafe fn reborrow_mut(&mut X: Abcde) -> Handle, HandleType> { +} + +pub fn merge(mut X: Abcdef) -> Handle, K, V, marker::Internal>, marker::Edge> { +} + +impl Handle { + pub fn merge(a: Abcd) -> Handle, K, V, marker::Internal>, marker::Edge> { + } +} + +// Long function without return type that should not be reformatted. +fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} diff --git a/tests/source/issue-1111.rs b/tests/source/issue-1111.rs new file mode 100644 index 00000000000..2e1a89ad78e --- /dev/null +++ b/tests/source/issue-1111.rs @@ -0,0 +1 @@ +use bar; diff --git a/tests/source/issue-1120.rs b/tests/source/issue-1120.rs new file mode 100644 index 00000000000..e85c9af99d4 --- /dev/null +++ b/tests/source/issue-1120.rs @@ -0,0 +1,9 @@ +// rustfmt-reorder_imports: true + +// Ensure that a use at the start of an inline module is correctly formatted. +mod foo {use bar;} + +// Ensure that an indented `use` gets the correct indentation. +mod foo { + use bar; +} diff --git a/tests/source/issue-1124.rs b/tests/source/issue-1124.rs new file mode 100644 index 00000000000..69aa1bb1c59 --- /dev/null +++ b/tests/source/issue-1124.rs @@ -0,0 +1,16 @@ +// rustfmt-reorder_imports: true +// rustfmt-normalize_comments: true + +use d; use c; use b; use a; +// The previous line has a space after the `use a;` + +mod a { use d; use c; use b; use a; } + +use z; + +use y; + + + +use x; +use a; \ No newline at end of file diff --git a/tests/source/issue-1127.rs b/tests/source/issue-1127.rs new file mode 100644 index 00000000000..9996c194818 --- /dev/null +++ b/tests/source/issue-1127.rs @@ -0,0 +1,23 @@ +// rustfmt-max_width:120 +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true + +fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { + 42 +} + +enum TestEnum { + AVeryVeryLongEnumName, + AnotherVeryLongEnumName, + TheLastVeryLongEnumName, +} + +fn main() { + let var = TestEnum::AVeryVeryLongEnumName; + let num = match var { + TestEnum::AVeryVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::AnotherVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::TheLastVeryLongEnumName => a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + }; +} + diff --git a/tests/source/issue-1158.rs b/tests/source/issue-1158.rs new file mode 100644 index 00000000000..6742e17459e --- /dev/null +++ b/tests/source/issue-1158.rs @@ -0,0 +1,3 @@ +trait T { + itemmacro!(this, is.now() .formatted(yay)); +} diff --git a/tests/source/issue-1177.rs b/tests/source/issue-1177.rs new file mode 100644 index 00000000000..3ac423c5aef --- /dev/null +++ b/tests/source/issue-1177.rs @@ -0,0 +1,7 @@ +// rustfmt-normalize_comments: true +fn main() { + // Line Comment + /* Block Comment */ + + let d = 5; +} diff --git a/tests/source/issue-1192.rs b/tests/source/issue-1192.rs new file mode 100644 index 00000000000..4e39fbf9a36 --- /dev/null +++ b/tests/source/issue-1192.rs @@ -0,0 +1,3 @@ +fn main() { + assert!(true) ; +} diff --git a/tests/source/issue-1211.rs b/tests/source/issue-1211.rs new file mode 100644 index 00000000000..5818736bf6b --- /dev/null +++ b/tests/source/issue-1211.rs @@ -0,0 +1,15 @@ +fn main() { + for iface in &ifaces { + match iface.addr { + get_if_addrs::IfAddr::V4(ref addr) => { + match addr.broadcast { + Some(ip) => { + sock.send_to(&buf, (ip, 8765)).expect("foobar"); + } + _ => () + } + } + _ => () + }; + } +} diff --git a/tests/source/issue-1216.rs b/tests/source/issue-1216.rs new file mode 100644 index 00000000000..d727c158ab8 --- /dev/null +++ b/tests/source/issue-1216.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +enum E { + A, //* I am not a block comment (caused panic) + B, +} diff --git a/tests/source/issue-1239.rs b/tests/source/issue-1239.rs new file mode 100644 index 00000000000..913058257ed --- /dev/null +++ b/tests/source/issue-1239.rs @@ -0,0 +1,9 @@ +fn foo() { + let with_alignment = if condition__uses_alignment_for_first_if__0 || + condition__uses_alignment_for_first_if__1 || + condition__uses_alignment_for_first_if__2 { + } else if condition__no_alignment_for_later_else__0 || + condition__no_alignment_for_later_else__1 || + condition__no_alignment_for_later_else__2 { + }; +} diff --git a/tests/source/issue-1278.rs b/tests/source/issue-1278.rs new file mode 100644 index 00000000000..e25376561a9 --- /dev/null +++ b/tests/source/issue-1278.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style = "block" + +#![feature(pub_restricted)] + +mod inner_mode { + pub(super) fn func_name(abc: i32) -> i32 { + abc + } +} diff --git a/tests/source/issue-1350.rs b/tests/source/issue-1350.rs new file mode 100644 index 00000000000..1baa1985a7e --- /dev/null +++ b/tests/source/issue-1350.rs @@ -0,0 +1,16 @@ +// rustfmt-max_width: 120 +// rustfmt-comment_width: 110 + +impl Struct { + fn fun() { + let result = match ::deserialize(&json) { + Ok(v) => v, + Err(e) => { + match ::deserialize(&json) { + Ok(v) => return Err(Error::with_json(v)), + Err(e2) => return Err(Error::with_json(e)), + } + } + }; + } +} diff --git a/tests/source/issue-1366.rs b/tests/source/issue-1366.rs new file mode 100644 index 00000000000..9d2964fc77c --- /dev/null +++ b/tests/source/issue-1366.rs @@ -0,0 +1,12 @@ +fn main() { + fn f() -> Option { + Some("fffffffsssssssssddddssssfffffddddff").map(|s| s).map(|s| s.to_string()).map(|res| { + match Some(res) { + Some(ref s) if s == "" => 41, + Some(_) => 42, + _ => 43, + } + }) + } + println!("{:?}", f()) +} diff --git a/tests/source/issue-1468.rs b/tests/source/issue-1468.rs new file mode 100644 index 00000000000..4d0d4f0eb98 --- /dev/null +++ b/tests/source/issue-1468.rs @@ -0,0 +1,27 @@ +fn issue1468() { +euc_jp_decoder_functions!({ +let trail_minus_offset = byte.wrapping_sub(0xA1); +// Fast-track Hiragana (60% according to Lunde) +// and Katakana (10% according to Lunde). +if jis0208_lead_minus_offset == 0x03 && +trail_minus_offset < 0x53 { +// Hiragana +handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) +} else if jis0208_lead_minus_offset == 0x04 && +trail_minus_offset < 0x56 { +// Katakana +handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) +} else if trail_minus_offset > (0xFE - 0xA1) { +if byte < 0x80 { +return (DecoderResult::Malformed(1, 0), +unread_handle_trail.unread(), +handle.written()); +} +return (DecoderResult::Malformed(2, 0), +unread_handle_trail.consumed(), +handle.written()); +} else { +unreachable!(); +} +}); +} diff --git a/tests/source/issue-1693.rs b/tests/source/issue-1693.rs new file mode 100644 index 00000000000..0622ce50235 --- /dev/null +++ b/tests/source/issue-1693.rs @@ -0,0 +1,3 @@ +fn issue1693() { + let pixel_data = vec![(f16::from_f32(0.82), f16::from_f32(1.78), f16::from_f32(0.21)); 256 * 256]; +} diff --git a/tests/source/issue-1800.rs b/tests/source/issue-1800.rs new file mode 100644 index 00000000000..eae22653258 --- /dev/null +++ b/tests/source/issue-1800.rs @@ -0,0 +1,3 @@ +#![doc(html_root_url = "http://example.com")] +#[cfg(feature = "foo")] +fn a() {} diff --git a/tests/source/issue-1914.rs b/tests/source/issue-1914.rs new file mode 100644 index 00000000000..447296c4b87 --- /dev/null +++ b/tests/source/issue-1914.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 80 + +extern "C" { +#[link_name = "_ZN7MyClass26example_check_no_collisionE"] + pub static mut MyClass_example_check_no_collision : * const :: std :: os :: raw :: c_int ; +} diff --git a/tests/source/issue-2025.rs b/tests/source/issue-2025.rs new file mode 100644 index 00000000000..c6f61b4e3e1 --- /dev/null +++ b/tests/source/issue-2025.rs @@ -0,0 +1,8 @@ + + + + +// See if rustfmt removes empty lines on top of the file. +pub fn foo() { + println!("hello, world"); +} diff --git a/tests/source/issue-2111.rs b/tests/source/issue-2111.rs new file mode 100644 index 00000000000..d1b02053e2a --- /dev/null +++ b/tests/source/issue-2111.rs @@ -0,0 +1,28 @@ +// rustfmt-normalize_comments: false + +// An import with single line comments. +use super::{ + SCHEMA_VERSIONS, + LodaModel, + ModelProperties, + StringMap, + ModelSelector, + RequestDescription, + MethodDescription, + ModelBehaviour, + ModelRequestGraph, + DelayChoice, + Holding, + Destinations, + ModelEdges, + Switch, + // ModelMetaData, + // Generated, + // SecondsString, + // DateString, + // ModelConfiguration, + // ModelRequests, + // RestResponse, + // RestResponseCode, + // UniformHolding +}; diff --git a/tests/source/issue-2164.rs b/tests/source/issue-2164.rs new file mode 100644 index 00000000000..6c288e1bd62 --- /dev/null +++ b/tests/source/issue-2164.rs @@ -0,0 +1,4 @@ +// A stress test against code generated by bindgen. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct emacs_env_25 { pub size : isize , pub private_members : * mut emacs_env_private , pub make_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , any_reference : emacs_value ) -> emacs_value > , pub free_global_ref : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , global_reference : emacs_value ) > , pub non_local_exit_check : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) -> emacs_funcall_exit > , pub non_local_exit_clear : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env ) > , pub non_local_exit_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol_out : * mut emacs_value , non_local_exit_data_out : * mut emacs_value ) -> emacs_funcall_exit > , pub non_local_exit_signal : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , non_local_exit_symbol : emacs_value , non_local_exit_data : emacs_value ) > , pub non_local_exit_throw : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , tag : emacs_value , value : emacs_value ) > , pub make_function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , min_arity : isize , max_arity : isize , function : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , nargs : isize , args : * mut emacs_value , arg1 : * mut ::libc :: c_void ) -> emacs_value > , documentation : * const ::libc :: c_char , data : * mut ::libc :: c_void ) -> emacs_value > , pub funcall : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , function : emacs_value , nargs : isize , args : * mut emacs_value ) -> emacs_value > , pub intern : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , symbol_name : * const ::libc :: c_char ) -> emacs_value > , pub type_of : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> emacs_value > , pub is_not_nil : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> bool > , pub eq : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , a : emacs_value , b : emacs_value ) -> bool > , pub extract_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> intmax_t > , pub make_integer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : intmax_t ) -> emacs_value > , pub extract_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value ) -> f64 > , pub make_float : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : f64 ) -> emacs_value > , pub copy_string_contents : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , value : emacs_value , buffer : * mut ::libc :: c_char , size_inout : * mut isize ) -> bool > , pub make_string : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , contents : * const ::libc :: c_char , length : isize ) -> emacs_value > , pub make_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > , ptr : * mut ::libc :: c_void ) -> emacs_value > , pub get_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value ) -> * mut ::libc :: c_void > , pub set_user_ptr : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , ptr : * mut ::libc :: c_void ) > , pub get_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) -> :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void , env : * mut emacs_env , uptr : emacs_value ) > > , pub set_user_finalizer : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , uptr : emacs_value , fin : :: std :: option :: Option < unsafe extern "C" fn ( arg1 : * mut ::libc :: c_void ) > ) > , pub vec_get : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize ) -> emacs_value > , pub vec_set : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value , i : isize , val : emacs_value ) > , pub vec_size : :: std :: option :: Option < unsafe extern "C" fn ( env : * mut emacs_env , vec : emacs_value ) -> isize > , } diff --git a/tests/source/issue-2179.rs b/tests/source/issue-2179.rs new file mode 100644 index 00000000000..ade953971ec --- /dev/null +++ b/tests/source/issue-2179.rs @@ -0,0 +1,35 @@ +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = + { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; + +} diff --git a/tests/source/issue-2256.rs b/tests/source/issue-2256.rs new file mode 100644 index 00000000000..b505b96e2b3 --- /dev/null +++ b/tests/source/issue-2256.rs @@ -0,0 +1,12 @@ +// こんにちは +use std::{}; +use std::borrow::Cow; + +/* comment */ use std::{}; +/* comment */ use std::{}; + + + + + +/* comment */ use std::{}; diff --git a/tests/source/issue-2342.rs b/tests/source/issue-2342.rs new file mode 100644 index 00000000000..f86d24a146b --- /dev/null +++ b/tests/source/issue-2342.rs @@ -0,0 +1,5 @@ +// rustfmt-max_width: 80 + +struct Foo { + #[cfg(feature = "serde")] bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN +} diff --git a/tests/source/issue-2446.rs b/tests/source/issue-2446.rs new file mode 100644 index 00000000000..ad649d95c54 --- /dev/null +++ b/tests/source/issue-2446.rs @@ -0,0 +1,11 @@ +enum Issue2446 { + V { + f: u8, // x + }, +} + +enum Issue2446TrailingCommentsOnly { + V { + f: u8, /* */ + } +} diff --git a/tests/source/issue-2479.rs b/tests/source/issue-2479.rs new file mode 100644 index 00000000000..df50236d05d --- /dev/null +++ b/tests/source/issue-2479.rs @@ -0,0 +1,2 @@ +// Long attributes. +# [ derive ( Clone , Copy , Debug , PartialEq ) ] pub enum POLARITYR { # [ doc = "Task mode: No effect on pin from OUT[n] task. Event mode: no IN[n] event generated on pin activity." ] NONE , # [ doc = "Task mode: Set pin from OUT[n] task. Event mode: Generate IN[n] event when rising edge on pin." ] LOTOHI , # [ doc = "Task mode: Clear pin from OUT[n] task. Event mode: Generate IN[n] event when falling edge on pin." ] HITOLO , # [ doc = "Task mode: Toggle pin from OUT[n]. Event mode: Generate IN[n] when any change on pin." ] TOGGLE } diff --git a/tests/source/issue-447.rs b/tests/source/issue-447.rs new file mode 100644 index 00000000000..7c542cb58c2 --- /dev/null +++ b/tests/source/issue-447.rs @@ -0,0 +1,39 @@ +// rustfmt-normalize_comments: true + +fn main() { + if /* shouldn't be dropped + shouldn't be dropped */ + + cond /* shouldn't be dropped + shouldn't be dropped */ + + { + } /* shouldn't be dropped + shouldn't be dropped */ + + else /* shouldn't be dropped + shouldn't be dropped */ + + if /* shouldn't be dropped + shouldn't be dropped */ + + cond /* shouldn't be dropped + shouldn't be dropped */ + + { + } /* shouldn't be dropped + shouldn't be dropped */ + + else /* shouldn't be dropped + shouldn't be dropped */ + + { + } + + if /* shouldn't be dropped + shouldn't be dropped */ + let Some(x) = y/* shouldn't be dropped + shouldn't be dropped */ + { + } +} diff --git a/tests/source/issue-510.rs b/tests/source/issue-510.rs new file mode 100644 index 00000000000..4c60859e6cf --- /dev/null +++ b/tests/source/issue-510.rs @@ -0,0 +1,37 @@ +impl ISizeAndMarginsComputer for AbsoluteNonReplaced { +fn solve_inline_size_constraints(&self, +block: &mut BlockFlow, +input: &ISizeConstraintInput) +-> ISizeConstraintSolution { +let (inline_start,inline_size,margin_inline_start,margin_inline_end) = +match (inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx,inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx) { +(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { +let margin_start = inline_start_margin.specified_or_zero(); +let margin_end = inline_end_margin.specified_or_zero(); +// Now it is the same situation as inline-start Specified and inline-end +// and inline-size Auto. +// +// Set inline-end to zero to calculate inline-size. +let inline_size = block.get_shrink_to_fit_inline_size(available_inline_size - +(margin_start + margin_end)); +(Au(0), inline_size, margin_start, margin_end) +} +}; + + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = + block.get_shrink_to_fit_inline_size(available_inline_size - + (margin_start + margin_end)); + (Au(0), inline_size, margin_start, margin_end) + } + }; +} +} diff --git a/tests/source/issue-811.rs b/tests/source/issue-811.rs new file mode 100644 index 00000000000..b7a89b5d0f9 --- /dev/null +++ b/tests/source/issue-811.rs @@ -0,0 +1,19 @@ +trait FooTrait: Sized { + type Bar: BarTrait; +} + +trait BarTrait: Sized { + type Baz; + fn foo(); +} + +type Foo = <>::Bar as BarTrait>::Baz; +type Bar = >::Baz; + +fn some_func, U>() { + <>::Bar as BarTrait>::foo(); +} + +fn some_func>() { + >::foo(); +} diff --git a/tests/source/issue-850.rs b/tests/source/issue-850.rs new file mode 100644 index 00000000000..c939716a6a8 --- /dev/null +++ b/tests/source/issue-850.rs @@ -0,0 +1 @@ +const unsafe fn x() {} diff --git a/tests/source/issue-855.rs b/tests/source/issue-855.rs new file mode 100644 index 00000000000..8f33fa685ae --- /dev/null +++ b/tests/source/issue-855.rs @@ -0,0 +1,20 @@ +fn main() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} + +fn main2() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | + Event::KeyDownXXXXXXXXXXXXX { keycode: Some(Keycode::Escape), .. } => break 'running, + } + } + } +} diff --git a/tests/source/issue-913.rs b/tests/source/issue-913.rs new file mode 100644 index 00000000000..e1c1b225fa5 --- /dev/null +++ b/tests/source/issue-913.rs @@ -0,0 +1,22 @@ +// rustfmt-error_on_line_overflow: false + +mod client { + impl Client { + fn test(self) -> Result<()> { + let next_state = match self.state { + State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { + let x = reformat . meeee() ; + } + }; + + let next_state = match self.state { + State::V5(v5::State::Command(v5::comand::State::WriteVersion(ref mut response))) => { + // The pattern cannot be formatted in a way that the match stays + // within the column limit. The rewrite should therefore be + // skipped. + let x = dont . reformat . meeee(); + } + }; + } + } +} diff --git a/tests/source/issue-945.rs b/tests/source/issue-945.rs new file mode 100644 index 00000000000..37d703c4679 --- /dev/null +++ b/tests/source/issue-945.rs @@ -0,0 +1,5 @@ +impl Bar { default const unsafe fn foo() { "hi" } } + +impl Baz { default unsafe extern "C" fn foo() { "hi" } } + +impl Foo for Bar { default fn foo() { "hi" } } diff --git a/tests/source/issue-977.rs b/tests/source/issue-977.rs new file mode 100644 index 00000000000..b028b36a055 --- /dev/null +++ b/tests/source/issue-977.rs @@ -0,0 +1,8 @@ +// rustfmt-normalize_comments: true +// FIXME(#919) + +trait NameC { /* comment */ } +struct FooC { /* comment */ } +enum MooC { /* comment */ } +mod BarC { /* comment */ } +extern { /* comment */ } diff --git a/tests/source/item-brace-style-always-next-line.rs b/tests/source/item-brace-style-always-next-line.rs new file mode 100644 index 00000000000..38094d67a77 --- /dev/null +++ b/tests/source/item-brace-style-always-next-line.rs @@ -0,0 +1,29 @@ +// rustfmt-brace_style: AlwaysNextLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style-prefer-same-line.rs b/tests/source/item-brace-style-prefer-same-line.rs new file mode 100644 index 00000000000..dff89b8b66b --- /dev/null +++ b/tests/source/item-brace-style-prefer-same-line.rs @@ -0,0 +1,29 @@ +// rustfmt-brace_style: PreferSameLine + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/item-brace-style-same-line-where.rs b/tests/source/item-brace-style-same-line-where.rs new file mode 100644 index 00000000000..ee4a7c5daad --- /dev/null +++ b/tests/source/item-brace-style-same-line-where.rs @@ -0,0 +1,31 @@ +// rustfmt-brace_style: SameLineWhere + +mod M { + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A where T: Copy { + A, + } + + struct B where T: Copy { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C where T: Copy {} + + struct D where T: Copy {} +} diff --git a/tests/source/large-block.rs b/tests/source/large-block.rs new file mode 100644 index 00000000000..09e9169f340 --- /dev/null +++ b/tests/source/large-block.rs @@ -0,0 +1,5 @@ +fn issue1351() { + std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ + static __STATIC_FMTSTR: &'static [&'static str] = &[]; + }); +} diff --git a/tests/source/large_vec.rs b/tests/source/large_vec.rs new file mode 100644 index 00000000000..34d5bf39954 --- /dev/null +++ b/tests/source/large_vec.rs @@ -0,0 +1,29 @@ +// See #1470. + +impl Environment { + pub fn new_root() -> Rc> { + let mut env = Environment::new(); + let builtin_functions = &[("println", + Function::NativeVoid(CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println)), + ("run_http_server", + Function::NativeVoid(CallSign { + num_params: 1, + variadic: false, + param_types: + vec![Some(ConstraintType::Function)], + }, + native_run_http_server)), + ("len", + Function::NativeReturning(CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len))]; + } +} diff --git a/tests/source/lazy_static.rs b/tests/source/lazy_static.rs new file mode 100644 index 00000000000..c1c74fb8307 --- /dev/null +++ b/tests/source/lazy_static.rs @@ -0,0 +1,37 @@ +// Format `lazy_static!`. + +lazy_static! { +static ref CONFIG_NAME_REGEX: regex::Regex = +regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); +static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) +.expect("Failed creating configuration value pattern"); +} + +// We need to be able to format `lazy_static!` without known syntax. +lazy_static!( + xxx, +yyyy , + zzzzz +); + +lazy_static!{ +} + +// #2354 +lazy_static ! { +pub static ref Sbase64_encode_string : :: lisp :: LispSubrRef = { +let subr = :: remacs_sys :: Lisp_Subr { +header : :: remacs_sys :: Lisp_Vectorlike_Header { +size : ( +( :: remacs_sys :: PseudovecType :: PVEC_SUBR as :: libc :: ptrdiff_t ) << :: +remacs_sys :: PSEUDOVECTOR_AREA_BITS ) , } , function : self :: +Fbase64_encode_string as * const :: libc :: c_void , min_args : 1i16 , +max_args : 2i16 , symbol_name : ( b"base64-encode-string\x00" ) . as_ptr ( ) +as * const :: libc :: c_char , intspec : :: std :: ptr :: null ( ) , doc : :: +std :: ptr :: null ( ) , lang : :: remacs_sys :: Lisp_Subr_Lang_Rust , } ; +unsafe { +let ptr = :: remacs_sys :: xmalloc ( +:: std :: mem :: size_of :: < :: remacs_sys :: Lisp_Subr > ( ) ) as * mut :: +remacs_sys :: Lisp_Subr ; :: std :: ptr :: copy_nonoverlapping ( +& subr , ptr , 1 ) ; :: std :: mem :: forget ( subr ) ; :: lisp :: ExternalPtr +:: new ( ptr ) } } ; } diff --git a/tests/source/long-match-arms-brace-newline.rs b/tests/source/long-match-arms-brace-newline.rs new file mode 100644 index 00000000000..927ada0ffb2 --- /dev/null +++ b/tests/source/long-match-arms-brace-newline.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 80 +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + match x { + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) if x == + "aaaaaaaaaaa \ + aaaaaaa \ + aaaaaa" => { + Ok(()) + } + _ => Err(x), + } +} diff --git a/tests/source/long_field_access.rs b/tests/source/long_field_access.rs new file mode 100644 index 00000000000..7aa626221ae --- /dev/null +++ b/tests/source/long_field_access.rs @@ -0,0 +1,3 @@ +fn f() { + block_flow.base.stacking_relative_position_of_display_port = self.base.stacking_relative_position_of_display_port; +} diff --git a/tests/source/loop.rs b/tests/source/loop.rs new file mode 100644 index 00000000000..6e92cdc6c2c --- /dev/null +++ b/tests/source/loop.rs @@ -0,0 +1,29 @@ + +fn main() { + loop + { return some_val;} + +let x = loop { do_forever(); }; + + 'label : loop { + // Just comments + } + + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value{} + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {} + + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) { + // do smth + } + + while let Some(i) = x.find('s') + { + x.update(); + continue; + continue 'foo; + } +} diff --git a/tests/source/macro_not_expr.rs b/tests/source/macro_not_expr.rs new file mode 100644 index 00000000000..d8de4dce38f --- /dev/null +++ b/tests/source/macro_not_expr.rs @@ -0,0 +1,7 @@ +macro_rules! test { + ($($t:tt)*) => {} +} + +fn main() { + test!( a : B => c d ); +} diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs new file mode 100644 index 00000000000..dba1d78f0dd --- /dev/null +++ b/tests/source/macro_rules.rs @@ -0,0 +1,114 @@ +// rustfmt-error_on_line_overflow: false + +macro_rules! m { + // a + ($expr :expr, $( $func : ident ) * ) => { + { + let x = $expr; + $func ( + x + ) + } + }; + + /* b */ + + () => {/* c */}; + + (@tag) => + { + + }; + +// d +( $item:ident ) => { + mod macro_item { struct $item ; } +}; +} + +macro m2 { + // a + ($expr :expr, $( $func : ident ) * ) => { + { + let x = $expr; + $func ( + x + ) + } + } + + /* b */ + + () => {/* c */} + + (@tag) => + { + + } + +// d +( $item:ident ) => { + mod macro_item { struct $item ; } +} +} + +// #2438, #2476 +macro_rules! m { + () => { + fn foo() { + this_line_is_98_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ); + } + } +} +macro_rules! m { + () => { + fn foo() { + this_line_is_99_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( +); + } + }; +} +macro_rules! m { + () => { + fn foo() { + this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( +); + } + }; +} +macro_rules! m { + () => { + fn foo() { + this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ); + } + }; +} + +// #2439 +macro_rules! m { + ( + $line0_xxxxxxxxxxxxxxxxx: expr, + $line1_xxxxxxxxxxxxxxxxx: expr, + $line2_xxxxxxxxxxxxxxxxx: expr, + $line3_xxxxxxxxxxxxxxxxx: expr, + ) => {}; +} + +// #2466 +// Skip formatting `macro_rules!` that are not using `{}`. +macro_rules! m ( + () => () +); +macro_rules! m [ + () => () +]; + +// #2470 +macro foo($type_name: ident, $docs: expr) { + #[allow(non_camel_case_types)] + #[doc=$docs] + #[derive(Debug, Clone, Copy)] + pub struct $type_name; +} diff --git a/tests/source/macros.rs b/tests/source/macros.rs new file mode 100644 index 00000000000..11e6d52c6c8 --- /dev/null +++ b/tests/source/macros.rs @@ -0,0 +1,342 @@ +// rustfmt-normalize_comments: true +itemmacro!(this, is.now() .formatted(yay)); + +itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); + +itemmacro!{this, is.bracket().formatted()} + +peg_file! modname ("mygrammarfile.rustpeg"); + +fn main() { + foo! ( ); + + bar!( a , b , c ); + + bar!( a , b , c , ); + + baz!(1+2+3, quux. kaas()); + + quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + + kaas!(/* comments */ a /* post macro */, b /* another */); + + trailingcomma!( a , b , c , ); + // Preserve trailing comma only when necessary. + ok!(file.seek( + SeekFrom::Start( + table.map(|table| fixture.offset(table)).unwrap_or(0), + ) + )); + + noexpr!( i am not an expression, OK? ); + + vec! [ a , b , c]; + + vec! [AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, AAAAAA, + BBBBB, 5, 100-30, 1.33, b, b, b]; + + vec! [a /* comment */]; + + // Trailing spaces after a comma + vec![ + a, + ]; + + vec![a; b]; + vec!(a; b); + vec!{a; b}; + + vec![a, b; c]; + vec![a; b, c]; + + vec![a; (|x| { let y = x + 1; let z = y + 1; z })(2)]; + vec![a; xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]; + vec![a; unsafe { + x + 1 + }]; + + unknown_bracket_macro__comma_should_not_be_stripped![ + a, + ]; + + foo(makro!(1, 3)); + + hamkaas!{ () }; + + macrowithbraces! {dont, format, me} + + x!(fn); + + some_macro!( + + ); + + some_macro![ + ]; + + some_macro!{ + // comment + }; + + some_macro!{ + // comment + }; + + some_macro!( + // comment + not function like + ); + + // #1712 + let image = gray_image!( + 00, 01, 02; + 10, 11, 12; + 20, 21, 22); + + // #1092 + chain!(input, a:take!(max_size), || []); +} + +impl X { + empty_invoc!{} +} + +fn issue_1279() { + println!("dsfs"); // a comment +} + +fn issue_1555() { + let hello = &format!("HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", + "65454654654654654654654655464", + "4"); +} + +fn issue1178() { + macro_rules! foo { + (#[$attr:meta] $name:ident) => {} + } + + foo!(#[doc = "bar"] baz); +} + +fn issue1739() { + sql_function!(add_rss_item, + add_rss_item_t, + (a: types::Integer, + b: types::Timestamptz, + c: types::Text, + d: types::Text, + e: types::Text)); + + w.slice_mut(s![.., init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], ..]) + .par_map_inplace(|el| *el = 0.); +} + +fn issue_1885() { + let threads = people.into_iter().map(|name| { + chan_select! { + rx.recv() => {} + } + }).collect::>(); +} + +fn issue_1917() { + mod x { + quickcheck! { + fn test(a: String, s: String, b: String) -> TestResult { + if a.find(&s).is_none() { + + TestResult::from_bool(true) + } else { + TestResult::discard() + } + } + } + } +} + +fn issue_1921() { + // Macro with tabs. + lazy_static! { + static ref ONE: u32 = 1; + static ref TWO: u32 = 2; + static ref THREE: u32 = 3; + static ref FOUR: u32 = { + let mut acc = 1; + acc += 1; + acc += 2; + acc + } +} +} + +// #1577 +fn issue1577() { + let json = json!({ + "foo": "bar", + }); +} + +gfx_pipeline!(pipe { + vbuf: gfx::VertexBuffer = (), + out: gfx::RenderTarget = "Target0", +}); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) + ) + ); + assert_eq ! ( :: std :: mem :: align_of :: < HandleWithDtor < :: std :: os :: raw :: c_int > > ( ) , 8usize , concat ! ( "Alignment of template specialization: " , stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) ) ); +} + +// #878 +macro_rules! try_opt { + ($expr:expr) => (match $expr { + Some(val) => val, + + None => { return None; } + }) +} + +// #2214 +// macro call whose argument is an array with trailing comma. +fn issue2214() { +make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [ + Reject(0, 1), + Match (1, 3), + Reject(3, 4), + Match (4, 6), + Reject(6, 7), +]); +} + +fn special_case_macros() { + let p = eprint!(); + let q = eprint!("{}", 1); + let r = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = eprint!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = eprintln!("{}", 1); + let r = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = eprintln!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = format!("{}", 1); + let r = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = format!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = format_args!("{}", 1); + let r = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = format_args!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = print!("{}", 1); + let r = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = print!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = println!("{}", 1); + let r = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = println!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + let q = unreachable!("{}", 1); + let r = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + let s = unreachable!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + debug!("{}", 1); + debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + debug!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + error!("{}", 1); + error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + error!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + info!("{}", 1); + info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + info!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + panic!("{}", 1); + panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + panic!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + warn!("{}", 1); + warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + warn!("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + assert!(); + assert!(result == 42); + assert!(result == 42, "Ahoy there, {}!", target); + assert!(result == 42, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert!(result == 42, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + assert_eq!(); + assert_eq!(left); + assert_eq!(left, right); + assert_eq!(left, right, "Ahoy there, {}!", target); + assert_eq!(left, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(left + 42, right, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + assert_eq!(left, right, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + write!(&mut s, "Ahoy there, {}!", target); + write!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + write!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); + + writeln!(&mut s, "Ahoy there, {}!", target); + writeln!(&mut s, "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", result, input, expected); + writeln!(&mut s, "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26); +} + +// #1209 +impl Foo { + /// foo + pub fn foo(&self) -> Bar {} +} + +// #819 +fn macro_in_pattern_position () { + let x = match y { + foo!( ) => (), + bar!( a, b, + c) => (), + bar!(a + , b + , c + ,) => (), + baz!( 1 + 2 + 3, quux.kaas( ) + ) => (), + quux!(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) => (), + }; +} + +macro foo() { + + +} + +pub macro bar($x:ident+$y:expr; ) { + fn foo($x: Foo) { + long_function(a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), + $x.bar($y)); + } +} + +macro foo() { + // a comment + fn foo() { + // another comment + bar(); + } +} + +macro lex_err($kind: ident $(, $body: expr)*) { + Err(QlError::LexError(LexError::$kind($($body,)*))) +} + +// Preserve trailing comma on item-level macro with `()` or `[]`. +methods![ get, post, delete, ]; +methods!( get, post, delete, ); diff --git a/tests/source/markdown-comment-with-options.rs b/tests/source/markdown-comment-with-options.rs new file mode 100644 index 00000000000..2c4d6a5cc2b --- /dev/null +++ b/tests/source/markdown-comment-with-options.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: true + +// Preserve two trailing whitespaces in doc comment, +// but trim any whitespaces in normal comment. + +//! hello world +//! hello world + +/// hello world +/// hello world +/// hello world +fn foo() { + // hello world + // hello world + let x = 3; + println!("x = {}", x); +} diff --git a/tests/source/markdown-comment.rs b/tests/source/markdown-comment.rs new file mode 100644 index 00000000000..1ec26562fe2 --- /dev/null +++ b/tests/source/markdown-comment.rs @@ -0,0 +1,15 @@ +// Preserve two trailing whitespaces in doc comment, +// but trim any whitespaces in normal comment. + +//! hello world +//! hello world + +/// hello world +/// hello world +/// hello world +fn foo() { + // hello world + // hello world + let x = 3; + println!("x = {}", x); +} diff --git a/tests/source/match-block-trailing-comma.rs b/tests/source/match-block-trailing-comma.rs new file mode 100644 index 00000000000..e9daac13bf9 --- /dev/null +++ b/tests/source/match-block-trailing-comma.rs @@ -0,0 +1,14 @@ +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + } + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/tests/source/match-nowrap-trailing-comma.rs b/tests/source/match-nowrap-trailing-comma.rs new file mode 100644 index 00000000000..134d2fdf9a4 --- /dev/null +++ b/tests/source/match-nowrap-trailing-comma.rs @@ -0,0 +1,15 @@ +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + } + b => (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/tests/source/match-nowrap.rs b/tests/source/match-nowrap.rs new file mode 100644 index 00000000000..db22cd9f010 --- /dev/null +++ b/tests/source/match-nowrap.rs @@ -0,0 +1,12 @@ +// rustfmt-match_arm_blocks: false +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { foo() } + b => + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + } +} diff --git a/tests/source/match.rs b/tests/source/match.rs new file mode 100644 index 00000000000..f38bf7cca97 --- /dev/null +++ b/tests/source/match.rs @@ -0,0 +1,464 @@ +// rustfmt-normalize_comments: true +// Match expressions. + +fn foo() { + // A match expression. + match x { + // Some comment. + a => foo(), + b if 0 < 42 => foo(), + c => { // Another comment. + // Comment. + an_expression; + foo() + } + Foo(ref bar) => + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + Pattern1 | Pattern2 | Pattern3 => false, + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn | + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + blah + } + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn => meh, + + Patternnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => meh, + + Patternnnnnnnnnnnnnnnnnnnnnnnnn | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if looooooooooooooooooooooooooooooooooooooooong_guard => + meh, + + // Test that earlier patterns can take the guard space + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) | + Patternnnnnnnnnnnnnnnnnnnnnnnnn if loooooooooooooooooooooooooooooooooooooooooong_guard => {} + + _ => {} + ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 || + data.types.len() > 0 || + data.bindings.len() > 0 => {} + } + + let whatever = match something { + /// DOC COMMENT! + Some(_) => 42, + // Comment on an attribute. + #[an_attribute] + // Comment after an attribute. + None => 0, + #[rustfmt_skip] + Blurb => { } + }; +} + +// Test that a match on an overflow line is laid out properly. +fn main() { + let sub_span = + match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; +} + +// Test that one-line bodies align. +fn main() { + match r { + Variableeeeeeeeeeeeeeeeee => ( "variable", + vec!("id", "name", "qualname", + "value", "type", "scopeid"), + true, + true), + Enummmmmmmmmmmmmmmmmmmmm => ("enum", + vec!("id","qualname","scopeid","value"), + true, + true), + Variantttttttttttttttttttttttt => ("variant", + vec!("id", + "name", + "qualname", + "type", + "value", + "scopeid"), + true, + true), + }; + + match x{ + y=>{/*Block with comment. Preserve me.*/ } + z=>{stmt();} } +} + +fn matches() { + match 1 { + -1 => 10, + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0 // baz + } +} + +fn match_skip() { + let _ = match Some(1) { + #[rustfmt_skip] + Some( n ) => n, + None => 1, + }; +} + +fn issue339() { + match a { + b => {} + c => { } + d => { + } + e => { + + + + } + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => { + } + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { // comment above block + } + i => { + } // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => { + } n => { } o => + { + + } + p => { // Dont collapse me + } q => { } r => + { + + } + s => 0, // s comment + // t comment + t => 1, + u => 2, + v => { + } /* funky block + * comment */ + // final comment + } +} + +fn issue355() { + match mac { + a => println!("a", b), + b => vec!(1, 2), + c => vec!(3; 4), + d => { + println!("a", b) + } + e => { + vec!(1, 2) + } + f => { + vec!(3; 4) + } + h => println!("a", b), // h comment + i => vec!(1, 2), // i comment + j => vec!(3; 4), // j comment + // k comment + k => println!("a", b), + // l comment + l => vec!(1, 2), + // m comment + m => vec!(3; 4), + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => println!("a", b), + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => vec!(1, 2), + // Macro support fails to recognise this macro as splittable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => vec!(3; 4), + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => println!("a", b), + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => vec!(1, 2), + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => vec!(3; 4), + // Funky bracketing styles + t => println!{"a", b}, + u => vec!{1, 2}, + v => vec!{3; 4}, + w => println!["a", b], + x => vec![1, 2], + y =>vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec!{1, 2}, // comment + vc =>vec!{3; 4}, // comment + wc =>println!["a", b], // comment + xc => vec![1,2], // comment + yc => vec![3; 4], // comment + yd => + looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func(aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd), + } +} + +fn issue280() { + { + match x { + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => ch == + '\n', + ast::ItemConst(ref typ, ref expr) => self.process_static_or_const_item(item, + &typ, + &expr), + } + } +} + +fn issue383() { + match resolution.last_private {LastImport{..} => false, _ => true}; +} + +fn issue507() { + match 1 { + 1 => unsafe { std::intrinsics::abort() }, + _ => (), + } +} + +fn issue508() { + match s.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement))) => true, + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement))) => s.has_object_data(), + Some(NodeTypeId::Element(_)) => false, + } +} + +fn issue496() {{{{ + match def { + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => + match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + Some(const_expr) => { x }}}}}}} + +fn issue494() { + { + match stmt.node { + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => + result.push( + StmtRef::Mirror( + Box::new(Stmt { span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref() } }))), + } + } +} + +fn issue386() { + match foo { + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => + true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | + BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => + false, + } +} + +fn guards() { + match foo { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if fooooooooooooooooooooo && + (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb || cccccccccccccccccccccccccccccccccccccccc) => {} + } +} + +fn issue1371() { + Some(match type_ { + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; + + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => { + TextEntered { + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + } + } + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; + + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; + + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) +} + +fn issue1395() { + let bar = Some(true); + let foo = Some(true); + let mut x = false; + bar.and_then(|_| { + match foo { + None => None, + Some(b) => { + x = true; + Some(b) + } + } + }); +} + +fn issue1456() { + Ok(Recording { + artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) +} + +fn issue1460() { + let _ = match foo { + REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => "internal_spec_insert_internal_spec_insert_internal_spec_insert", + _ => "reorder_something", + }; +} + +fn issue525() { + foobar(f, "{}", match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }); +} + +// #1838, #1839 +fn match_with_near_max_width() { + let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { + _ => unimplemented!(), + }; + + let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { + _ => unimplemented!(), + }; + + let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression + { + _ => unimplemented!(), + }; + match m { + Variant::Tag | Variant::Tag2 | Variant::Tag3 | Variant::Tag4 | Variant::Tag5 | Variant::Tag6 => + {} + } +} + +fn match_with_trailing_spaces() { + match x { + #![allow(simple_match)] + Some(..) => 0, + None => 1, + } +} + +fn issue_2099() { + let a = match x { +}; + let b = match x { + + }; + + match x {} +} + +// #2021 +impl<'tcx> Const<'tcx> { + pub fn from_constval<'a>() -> Const<'tcx> { + let val = match *cv { + ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv), + }; + } +} + +// #2151 +fn issue_2151() { + match either { + x => { + + }y => () + } +} + +// #2152 +fn issue_2152() { + match m { + "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" if true => {} + "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => true, + } +} + +// #2462 +// Preserve a `|` at the beginning of a match arm. +fn match_with_beginning_vert() { + let x = Foo::A; + match x { + | Foo::A + | Foo::B => println!("AB"), + | Foo::C => println!("C"), + } +} diff --git a/tests/source/max-line-length-in-chars.rs b/tests/source/max-line-length-in-chars.rs new file mode 100644 index 00000000000..d49fbb7e30e --- /dev/null +++ b/tests/source/max-line-length-in-chars.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 25 + +// абвгдеёжзийклмнопрст +fn main() {} diff --git a/tests/source/mod-1.rs b/tests/source/mod-1.rs new file mode 100644 index 00000000000..427a355b6be --- /dev/null +++ b/tests/source/mod-1.rs @@ -0,0 +1,29 @@ +// Deeply indented modules. + + mod foo { mod bar { mod baz {} } } + +mod foo { + mod bar { + mod baz { + fn foo() { bar() } + } + } + + mod qux { + + } +} + +mod boxed { pub use std::boxed::{Box, HEAP}; } + +pub mod x { + pub fn freopen(filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE) + -> *mut FILE{} +} + + mod y { // sup boooooiiii + } diff --git a/tests/source/mod-2.rs b/tests/source/mod-2.rs new file mode 100644 index 00000000000..7202e00203e --- /dev/null +++ b/tests/source/mod-2.rs @@ -0,0 +1,4 @@ +// Some nested mods + +#[cfg(test)] mod nestedmod ; +pub mod no_new_line_beginning; diff --git a/tests/source/mod_skip_child.rs b/tests/source/mod_skip_child.rs new file mode 100644 index 00000000000..d48c4a37e81 --- /dev/null +++ b/tests/source/mod_skip_child.rs @@ -0,0 +1,2 @@ +// rustfmt-skip_children: true +mod nested_skipped; diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs new file mode 100644 index 00000000000..68cfacfcb4b --- /dev/null +++ b/tests/source/multiple.rs @@ -0,0 +1,134 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-format_strings: true +// Test of lots of random stuff. +// FIXME split this into multiple, self-contained tests. + + +#[attr1] extern crate foo; +#[attr2] #[attr3] extern crate foo; +#[attr1]extern crate foo; +#[attr2]#[attr3]extern crate foo; + +use std::cell::*; +use std::{any, ascii, self, borrow, boxed, char, borrow, boxed, char, borrow, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char}; + +mod doc; +mod other; + + +// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff + + fn foo(a: isize, + b: u32, /* blah blah */ + c: f64) { + +} + +fn foo()->Box where 'a: 'b, for<'a> D<'b>: 'a { + hello!() +} + +fn baz<'a: 'b /* comment on 'a */, T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType /* comment on T */>(a: A, b: B /* comment on b */, c: C) -> Bob { + #[attr1] extern crate foo; + #[attr2] #[attr3] extern crate foo; + #[attr1]extern crate foo; + #[attr2]#[attr3]extern crate foo; +} + +#[rustfmt_skip] +fn qux(a: dadsfa, // Comment 1 + b: sdfasdfa, // Comment 2 + c: dsfdsafa) // Comment 3 +{ + +} + +/// Blah blah blah. +impl Bar { + fn foo(&mut self, a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a + b: sdfasdfsdfasfs /*closing comment*/ ) -> isize {} + + /// Blah blah blah. + pub fn f2(self) { + (foo, bar) + } + + #[an_attribute] + fn f3(self) -> Dog { + } +} + +/// The `nodes` and `edges` method each return instantiations of +/// `Cow<[T]>` to leave implementers the freedom to create + +/// entirely new vectors or to pass back slices into internally owned +/// vectors. +pub trait GraphWalk<'a, N, E> { + /// Returns all the nodes in this graph. + fn nodes(&'a self) -> Nodes<'a, N>; + /// Returns all of the edges in this graph. + fn edges(&'a self) -> Edges<'a, E>; + /// The source node for `edge`. + fn source(&'a self, edge: &E) -> N; + /// The target node for `edge`. + fn target(&'a self, edge: &E) -> N; +} + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f : SomeType, // Comment beside a field + // Comment on a field + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType,} + +struct Bar; + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +fn foo(ann: &'a (PpAnn+'a)) {} + +fn main() { + for i in 0i32..4 { + println!("{}", i); + } + + + while true { + hello(); + } + + let rc = Cell::new(42usize,42usize, Cell::new(42usize, remaining_widthremaining_widthremaining_widthremaining_width), 42usize); + let rc = RefCell::new(42usize,remaining_width, remaining_width); // a comment + let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; + let s = expand(a + , + b); } + +fn deconstruct() -> (SocketAddr, Method, Headers, + RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} + +fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, + RequestUri, HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { +} + +#[rustfmt_skip] +mod a{ +fn foo(x: T) { + let x: T = dfasdf; +} +} diff --git a/tests/source/nested-if-else.rs b/tests/source/nested-if-else.rs new file mode 100644 index 00000000000..9a54789ddcd --- /dev/null +++ b/tests/source/nested-if-else.rs @@ -0,0 +1,11 @@ +fn issue1518() { + Some(Object { + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) +} diff --git a/tests/source/nested_skipped/mod.rs b/tests/source/nested_skipped/mod.rs new file mode 100644 index 00000000000..44b25ca8797 --- /dev/null +++ b/tests/source/nested_skipped/mod.rs @@ -0,0 +1,3 @@ +fn ugly() { +92; +} diff --git a/tests/source/nestedmod/mod.rs b/tests/source/nestedmod/mod.rs new file mode 100644 index 00000000000..d04e49570a4 --- /dev/null +++ b/tests/source/nestedmod/mod.rs @@ -0,0 +1,13 @@ + +mod mod2a; +mod mod2b; + +mod mymod1 { + use mod2a::{Foo,Bar}; +mod mod3a; +} + +#[path="mod2c.rs"] +mod mymod2; + +mod submod2; diff --git a/tests/source/nestedmod/mod2a.rs b/tests/source/nestedmod/mod2a.rs new file mode 100644 index 00000000000..5df457a8316 --- /dev/null +++ b/tests/source/nestedmod/mod2a.rs @@ -0,0 +1,4 @@ +// This is an empty file containing only +// comments + +// ................... diff --git a/tests/source/nestedmod/mod2b.rs b/tests/source/nestedmod/mod2b.rs new file mode 100644 index 00000000000..f128e2da6db --- /dev/null +++ b/tests/source/nestedmod/mod2b.rs @@ -0,0 +1,3 @@ + +#[path="mod2a.rs"] +mod c; diff --git a/tests/source/nestedmod/mod2c.rs b/tests/source/nestedmod/mod2c.rs new file mode 100644 index 00000000000..eda6b233e4b --- /dev/null +++ b/tests/source/nestedmod/mod2c.rs @@ -0,0 +1,3 @@ +// A standard mod + +fn a( ) {} diff --git a/tests/source/nestedmod/mymod1/mod3a.rs b/tests/source/nestedmod/mymod1/mod3a.rs new file mode 100644 index 00000000000..f28bde5e56d --- /dev/null +++ b/tests/source/nestedmod/mymod1/mod3a.rs @@ -0,0 +1,2 @@ +// Another mod +fn a( ) { } diff --git a/tests/source/nestedmod/submod2/a.rs b/tests/source/nestedmod/submod2/a.rs new file mode 100644 index 00000000000..0eaf08f0d2c --- /dev/null +++ b/tests/source/nestedmod/submod2/a.rs @@ -0,0 +1,6 @@ +// Yet Another mod +// Nested + +use c::a; + +fn foo( ) { } diff --git a/tests/source/nestedmod/submod2/mod.rs b/tests/source/nestedmod/submod2/mod.rs new file mode 100644 index 00000000000..52f8be91022 --- /dev/null +++ b/tests/source/nestedmod/submod2/mod.rs @@ -0,0 +1,5 @@ +// Another mod + +mod a; + +use a::a; diff --git a/tests/source/no_new_line_beginning.rs b/tests/source/no_new_line_beginning.rs new file mode 100644 index 00000000000..f79c691f085 --- /dev/null +++ b/tests/source/no_new_line_beginning.rs @@ -0,0 +1,2 @@ +fn main() { +} diff --git a/tests/source/other.rs b/tests/source/other.rs new file mode 100644 index 00000000000..dfce84fcdc4 --- /dev/null +++ b/tests/source/other.rs @@ -0,0 +1,5 @@ +// Part of multiple.rs + +fn bob() { + println!("hello other!"); +} diff --git a/tests/source/paths.rs b/tests/source/paths.rs new file mode 100644 index 00000000000..ebc26f146e4 --- /dev/null +++ b/tests/source/paths.rs @@ -0,0 +1,25 @@ +// rustfmt-normalize_comments: true + +fn main() { + let constellation_chan = Constellation:: ::start( + compositor_proxy, + resource_task, + image_cache_task,font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard + ); + + Quux::::some_func(); + + < *mut JSObject >:: relocate(entry); + + let x: Foo; + let x: Foo/*::*/; +} + +fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {} diff --git a/tests/source/pattern-condense-wildcards.rs b/tests/source/pattern-condense-wildcards.rs new file mode 100644 index 00000000000..244e935639a --- /dev/null +++ b/tests/source/pattern-condense-wildcards.rs @@ -0,0 +1,12 @@ +// rustfmt-normalize_comments: true +// rustfmt-condense_wildcard_suffixes: true + +fn main() { + match x { + Butt (_,_) => "hah", + Tup (_) => "nah", + Quad (_,_, x,_) => " also no rewrite", + Quad (x, _, _, _) => "condense me pls", + Weird (x, _, _, /* dont condense before */ _, _, _) => "pls work", + } +} diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs new file mode 100644 index 00000000000..7c052c87bc4 --- /dev/null +++ b/tests/source/pattern.rs @@ -0,0 +1,65 @@ +// rustfmt-normalize_comments: true +fn main() { + let z = match x { + "pat1" => 1, + ( ref x, ref mut y /*comment*/) => 2, + }; + + if let < T as Trait > :: CONST = ident { + do_smth(); + } + + let Some ( ref xyz /* comment! */) = opt; + + if let None = opt2 { panic!("oh noes"); } + + let foo@bar (f) = 42; + let a::foo ( ..) = 42; + let [ ] = 42; + let [a.., b,c ] = 42; + let [ a,b,c.. ] = 42; + let [a, b, c, d..,e,f, g] = 42; + let foo { } = 42; + let foo {..} = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; + let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; +} + +impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { + fn mutate_fragment(&mut self, fragment: &mut Fragment) { + match **info { + GeneratedContentInfo::ContentItem( + ContentItem::Counter( + ref counter_name, + counter_style + ) + ) => {}}} +} + +fn issue_1319() { + if let (Event { .. }, .. ) = ev_state {} +} + +fn issue_1874() { + if let Some(()) = x { +y + } +} + +fn combine_patterns() { + let x = match y { + Some( + Some( + Foo { + z: Bar(..), + a: Bar(..), + b: Bar(..), + }, + ), + ) => z, + _ => return, + }; +} diff --git a/tests/source/pub-restricted.rs b/tests/source/pub-restricted.rs new file mode 100644 index 00000000000..30051fa72ee --- /dev/null +++ b/tests/source/pub-restricted.rs @@ -0,0 +1,64 @@ +pub( super ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( crate ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + + crate enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(in ::global:: path :: to::some_mod ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub( in local:: path :: to::some_mod ) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} diff --git a/tests/source/remove_blank_lines.rs b/tests/source/remove_blank_lines.rs new file mode 100644 index 00000000000..7466e21eed8 --- /dev/null +++ b/tests/source/remove_blank_lines.rs @@ -0,0 +1,44 @@ +fn main() { + + + + + let x = 1; + + + let y = 2; + + + println!("x + y = {}", x + y); + + + +} + + +fn foo() { + + #![attribute] + + let x = 1; + + // comment + + +} +// comment after item + + +// comment before item +fn bar() { + let x = 1; + // comment after statement + + + // comment before statment + let y = 2; + let z = 3; + + + println!("x + y + z = {}", x + y + z); +} diff --git a/tests/source/single-line-if-else.rs b/tests/source/single-line-if-else.rs new file mode 100644 index 00000000000..bcde390d116 --- /dev/null +++ b/tests/source/single-line-if-else.rs @@ -0,0 +1,49 @@ + +// Format if-else expressions on a single line, when possible. + +fn main() { + let a = if 1 > 2 { + unreachable!() + } else { + 10 + }; + + let a = if x { 1 } else if y { 2 } else { 3 }; + + let b = if cond() { + 5 + } else { + // Brief comment. + 10 + }; + + let c = if cond() { + statement(); + + 5 + } else { + 10 + }; + + let d = if let Some(val) = turbo + { "cool" } else { + "beans" }; + + if cond() { statement(); } else { other_statement(); } + + if true { + do_something() + } + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa } else { bbbbbbbbbb }; + + let x = if veeeeeeeeery_loooooong_condition() { aaaaaaaaaaaaaaaaaaaaaaaaa } else { + bbbbbbbbbb }; + + funk(if test() { + 1 + } else { + 2 + }, + arg2); +} diff --git a/tests/source/soft-wrapping.rs b/tests/source/soft-wrapping.rs new file mode 100644 index 00000000000..ace8359409c --- /dev/null +++ b/tests/source/soft-wrapping.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 80 +// Soft wrapping for comments. + +// #535, soft wrapping for comments +// Compare the lowest `f32` of both inputs for greater than or equal. The +// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off +// the result are the upper 96 bits of `a`. + +/// Compare the lowest `f32` of both inputs for greater than or equal. The +/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off +/// the result are the upper 96 bits of `a`. +fn foo() {} diff --git a/tests/source/space-not-before-newline.rs b/tests/source/space-not-before-newline.rs new file mode 100644 index 00000000000..2a1e1856908 --- /dev/null +++ b/tests/source/space-not-before-newline.rs @@ -0,0 +1,8 @@ +struct Foo { + a: (), + // spaces ^^^ to be removed +} +enum Foo { + Bar, + // spaces ^^^ to be removed +} diff --git a/tests/source/spaces-around-ranges.rs b/tests/source/spaces-around-ranges.rs new file mode 100644 index 00000000000..1936b5e161f --- /dev/null +++ b/tests/source/spaces-around-ranges.rs @@ -0,0 +1,15 @@ +// rustfmt-spaces_around_ranges: true + +fn bar(v: &[u8]) {} + +fn foo() { + let a = vec![0; 20]; + for j in 0..=20 { + for i in 0..3 { + bar(a[i..j]); + bar(a[i..]); + bar(a[..j]); + bar(a[..=(j + 1)]); + } + } +} diff --git a/tests/source/static.rs b/tests/source/static.rs new file mode 100644 index 00000000000..970786381cc --- /dev/null +++ b/tests/source/static.rs @@ -0,0 +1,23 @@ +const FILE_GENERIC_READ: DWORD = + STANDARD_RIGHTS_READ | FILE_READ_DATA | + FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; + +static boolnames: &'static[&'static str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", + "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", + "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", + "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; + +static mut name: SomeType = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + + pub static count : u8 = 10 ; + +pub const test: &Type = &val; + +impl Color { + pub const WHITE: u32 = 10; +} + +// #1391 +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = 0 as usize; + +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/tests/source/string-lit-2.rs b/tests/source/string-lit-2.rs new file mode 100644 index 00000000000..6b95e25a052 --- /dev/null +++ b/tests/source/string-lit-2.rs @@ -0,0 +1,25 @@ +fn main() -> &'static str { + let too_many_lines = "Hello"; + let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} + +fn issue_1237() { + let msg = "eedadn\n\ + drvtee\n\ + eandsr\n\ + raavrd\n\ + atevrs\n\ + tsrnev\n\ + sdttsa\n\ + rasrtv\n\ + nssdts\n\ + ntnada\n\ + svetve\n\ + tesnvt\n\ + vntsnd\n\ + vrdear\n\ + dvrsen\n\ + enarar"; +} diff --git a/tests/source/string-lit.rs b/tests/source/string-lit.rs new file mode 100644 index 00000000000..e86f65f9f52 --- /dev/null +++ b/tests/source/string-lit.rs @@ -0,0 +1,62 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false +// Long string literals + +fn main() -> &'static str { + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let too_many_lines = "H\ + e\ + l\ + l\ + o"; + + // Make sure we don't break after an escape character. + let odd_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let even_length_name = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + + let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let raw_string = r#"Do +not +remove +formatting"#; + + filename.replace(" ", "\\" ); + + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + let unicode = "a̐éö̲\r\n"; + let unicode2 = "Löwe 老虎 Léopard"; + let unicode3 = "中华Việt Nam"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + + "stuffin'" +} + +fn issue682() { + let a = "hello \\ o/"; + let b = a.replace("\\ ", "\\"); +} + +fn issue716() { + println!("forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()"); +} + +fn issue_1282() { + { + match foo { + Permission::AndroidPermissionAccessLocationExtraCommands => { + "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" + } + } + } +} + +// #1987 +#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] +extern "C" {} diff --git a/tests/source/string_punctuation.rs b/tests/source/string_punctuation.rs new file mode 100644 index 00000000000..6a0afd45e5a --- /dev/null +++ b/tests/source/string_punctuation.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false + +fn main() { + println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); + println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); +} diff --git a/tests/source/struct-field-attributes.rs b/tests/source/struct-field-attributes.rs new file mode 100644 index 00000000000..76d6eda8853 --- /dev/null +++ b/tests/source/struct-field-attributes.rs @@ -0,0 +1,52 @@ +// #1535 +#![feature(struct_field_attributes)] + +struct Foo { + bar: u64, + + #[cfg(test)] + qux: u64, +} + +fn do_something() -> Foo { + Foo { + bar: 0, + + #[cfg(test)] + qux: 1, + } +} + +fn main() { + do_something(); +} + +// #1462 +struct Foo { + foo: usize, + #[cfg(feature="include-bar")] + bar: usize, +} + +fn new_foo() -> Foo { + Foo { + foo: 0, + #[cfg(feature="include-bar")] + bar: 0, + } +} + +// #2044 +pub enum State { + Closure(#[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] GcPtr), +} + +struct Fields( + #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] Arc>, +); + +// #2309 +pub struct A { +#[doc="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] +pub foos:Vec +} diff --git a/tests/source/struct_lits.rs b/tests/source/struct_lits.rs new file mode 100644 index 00000000000..3a8016367b6 --- /dev/null +++ b/tests/source/struct_lits.rs @@ -0,0 +1,144 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:f() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo + { a : 1, b:f( 2)}; + Foo{a:1,b:f(2),..g(3)}; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { ..base }; + IntrinsicISizesContribution { content_intrinsic_sizes: IntrinsicISizes { minimum_inline_size: 0, }, }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { a: bb, c: dd, e: ff }; + + Foo { a: ddddddddddddddddddddd, b: cccccccccccccccccccccccccccccccccccccc }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { a: aaaaaaaaaa, b: bbbbbbbb, c: cccccccccc, d: dddddddddd, /* a comment */ + e: eeeeeeeee }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, .. base }; + Foo { aaaaaaaaaa, bbbbbbbb, cccccccccc, dddddddddd, /* a comment */ + eeeeeeeee }; + Record { ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa }; +} diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs new file mode 100644 index 00000000000..256ba1bbda3 --- /dev/null +++ b/tests/source/struct_lits_multiline.rs @@ -0,0 +1,81 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-struct_lit_single_line: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { memb: T } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S{a:0, .. b}; +} + +fn issue201_2() { + let s = S{a: S2{ .. c}, .. b}; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; +} diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs new file mode 100644 index 00000000000..2c6cc674960 --- /dev/null +++ b/tests/source/struct_lits_visual.rs @@ -0,0 +1,47 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:f() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, z: zzzzz // test + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs new file mode 100644 index 00000000000..d0b5ea6efba --- /dev/null +++ b/tests/source/struct_lits_visual_multiline.rs @@ -0,0 +1,45 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-struct_lit_single_line: false +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + Quux { x: if cond { bar(); }, y: baz() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/tests/source/struct_tuple_visual.rs b/tests/source/struct_tuple_visual.rs new file mode 100644 index 00000000000..369feae71d2 --- /dev/null +++ b/tests/source/struct_tuple_visual.rs @@ -0,0 +1,37 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual +fn foo() { + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment + foo(), /* Comment */ + // Comment + bar() /* Comment */); + + Foo(Bar, f()); + + Quux(if cond { + bar(); + }, + baz()); + + Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + zzzzz /* test */); + + A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + Item); + + Diagram(// o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + G) +} diff --git a/tests/source/structs.rs b/tests/source/structs.rs new file mode 100644 index 00000000000..25070aef34c --- /dev/null +++ b/tests/source/structs.rs @@ -0,0 +1,283 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + + /// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1095 +struct S { + t: T, +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct +NewInt (pub i32, SomeType /* inline comment */, T /* sup */ + + + ); + +struct Qux<'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy> +( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +struct Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +struct Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +// Will this be a one-liner? +struct Tuple( + A, //Comment + B +); + +pub struct State time::Timespec> { now: F } + +pub struct State ()> { now: F } + +pub struct State { now: F } + +struct Palette { /// A map of indices in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(T); +struct Foo(T) where T: Copy, T: Eq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU); +struct Foo(TTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTTTT) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUUUUUUU, TTTTTTTTTTTTTTTTTTT, UUUUUUUUUUUUUUUUUUU) where T: PartialEq; +struct Foo(TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU /* Bar */, + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU); + +mod m { + struct X where T: Sized { + a: T, + } +} + +struct Foo(TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +struct Foo {} +struct Foo { + } +struct Foo { + // comment + } +struct Foo { + // trailing space -> + + + } +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +struct Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} + +// structs with long identifier +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong {} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong { x: i32 } + +// structs with visibility, do not duplicate visibility (#2110). +pub(in self) struct Foo{} +pub(super) struct Foo{} +pub(crate) struct Foo{} +pub(in self) struct Foo(); +pub(super) struct Foo(); +pub(crate) struct Foo(); + +// #2125 +pub struct ReadinessCheckRegistry(Mutex, Box ReadinessCheck + Sync + Send>>>); + +// #2144 unit struct with generics +struct MyBox; +struct MyBoxx where T: ?Sized, S: Clone; + +// #2208 +struct Test { + /// foo + #[serde(default)] + pub join: Vec, + #[serde(default)] pub tls: bool, +} diff --git a/tests/source/trailing-comma-never.rs b/tests/source/trailing-comma-never.rs new file mode 100644 index 00000000000..5985b514724 --- /dev/null +++ b/tests/source/trailing-comma-never.rs @@ -0,0 +1,41 @@ +// rustfmt-trailing_comma: Never + +enum X { + A, + B, +} + +enum Y { + A, + B +} + +enum TupX { + A(u32), + B(i32, u16), +} + +enum TupY { + A(u32), + B(i32, u16) +} + +enum StructX { + A { + s: u16, + }, + B { + u: u32, + i: i32, + }, +} + +enum StructY { + A { + s: u16, + }, + B { + u: u32, + i: i32, + } +} diff --git a/tests/source/trailing_commas.rs b/tests/source/trailing_commas.rs new file mode 100644 index 00000000000..3e5fcc8080f --- /dev/null +++ b/tests/source/trailing_commas.rs @@ -0,0 +1,47 @@ +// rustfmt-match_block_trailing_comma: true +// rustfmt-trailing_comma: Always + +fn main() { + match foo { + x => {} + y => { + foo(); + } + _ => x + } +} + +fn f(x: T, y: S) -> T where T: P, S: Q +{ + x +} + +impl Trait for T where T: P +{ + fn f(x: T) -> T where T: Q + R + { + x + } +} + +struct Pair where T: P, S: P + Q { + a: T, + b: S +} + +struct TupPair (S, T) where T: P, S: P + Q; + +enum E where S: P, T: P { + A {a: T}, +} + +type Double where T: P, T: Q = Pair; + +extern "C" { + fn f(x: T, y: S) -> T where T: P, S: Q; +} + +trait Q where T: P, S: R +{ + fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; +} diff --git a/tests/source/trait.rs b/tests/source/trait.rs new file mode 100644 index 00000000000..e8de36db35e --- /dev/null +++ b/tests/source/trait.rs @@ -0,0 +1,94 @@ +// Test traits + +trait Foo { + fn bar(x: i32 ) -> Baz< U> { Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, +b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) +-> RetType; + + fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment +b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType ; // Some comment + + fn baz(&mut self ) -> i32 ; + +fn increment(& mut self, x: i32 ); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where R: Read; +} + +pub trait WriteMessage { + fn write_message (&mut self, &FrontendMessage) -> io::Result<()>; +} + +trait Runnable { + fn handler(self: & Runnable ); +} + +trait TraitWithExpr { + fn fn_with_expr(x: [i32; 1]); +} + +trait Test { + fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; +} + +trait T<> {} + +trait Foo { type Bar: Baz; type Inner: Foo = Box< Foo >; } + +trait ConstCheck:Foo where T: Baz { + const J: i32; +} + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } + +trait WhereList where T: Foo, J: Bar {} + +trait X /* comment */ {} +trait Y // comment +{ +} + +// #2055 +pub trait Foo: +// A and C +A + C +// and B + + B +{} + +// #2158 +trait Foo { + type ItRev = > as UntypedTimeSeries>::IterRev; + type IteRev = > as UntypedTimeSeries>::IterRev; +} + +// #2331 +trait MyTrait { + fn foo() {} +} + +// Trait aliases +trait FooBar = + Foo + + Bar; +trait FooBar = + Foo + + Bar; +trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; +#[rustfmt_skip] +trait FooBar = Foo + + Bar; diff --git a/tests/source/try-conversion.rs b/tests/source/try-conversion.rs new file mode 100644 index 00000000000..ed83ee9e101 --- /dev/null +++ b/tests/source/try-conversion.rs @@ -0,0 +1,18 @@ +// rustfmt-use_try_shorthand: true + +fn main() { + let x = try!(some_expr()); + + let y = try!(a.very.loooooooooooooooooooooooooooooooooooooong().chain().inside().weeeeeeeeeeeeeee()).test().0.x; +} + +fn test() { + a? +} + +fn issue1291() { + try!(fs::create_dir_all(&gitfiledir).chain_err(|| { + format!("failed to create the {} submodule directory for the workarea", + name) + })); +} diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs new file mode 100644 index 00000000000..6c3ec8f1115 --- /dev/null +++ b/tests/source/tuple.rs @@ -0,0 +1,52 @@ +// Test tuple litterals + +fn foo() { + let a = (a, a, a, a, a); + let aaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaa, aaaaaaaaaaaaaa); + let aaaaaaaaaaaaaaaaaaaaaa = (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa); + let a = (a,); + + let b = (// This is a comment + b, // Comment + b /* Trailing comment */); + + // #1063 + foo(x.0 .0); +} + +fn a() { + ((aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa),) +} + +fn b() { + ((bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb), + bbbbbbbbbbbbbbbbbb) +} + +fn issue550() { + self.visitor.visit_volume(self.level.sector_id(sector), (floor_y, + if is_sky_flat(ceil_tex) {from_wad_height(self.height_range.1)} else {ceil_y})); +} + +fn issue775() { + if indent { + let a = mk_object(&[("a".to_string(), Boolean(true)), + ("b".to_string(), + Array(vec![mk_object(&[("c".to_string(), + String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))])]))]); + } +} + +fn issue1725() { + bench_antialiased_lines!(bench_draw_antialiased_line_segment_diagonal, (10, 10), (450, 450)); + bench_antialiased_lines!(bench_draw_antialiased_line_segment_shallow, (10, 10), (450, 80)); +} diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs new file mode 100644 index 00000000000..3b761f4fc78 --- /dev/null +++ b/tests/source/type-ascription.rs @@ -0,0 +1,9 @@ +fn main() { + let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; + + let xxxxxxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + x : u32 - 1u32 / 10f32 : u32 +} diff --git a/tests/source/type.rs b/tests/source/type.rs new file mode 100644 index 00000000000..0a46ffb2ee4 --- /dev/null +++ b/tests/source/type.rs @@ -0,0 +1,25 @@ +// rustfmt-normalize_comments: true +fn types() { + let x: [ Vec < _ > ] = []; + let y: * mut [ SomeType ; konst_funk() ] = expr(); + let z: (/*#digits*/ usize, /*exp*/ i16) = funk(); + let z: ( usize /*#digits*/ , i16 /*exp*/ ) = funk(); +} + +struct F { + f: extern "C" fn(x: u8, ... /* comment */), + g: extern "C" fn(x: u8,/* comment */ ...), + h: extern "C" fn(x: u8, ... ), + i: extern "C" fn(x: u8, /* comment 4*/ y: String, // comment 3 + z: Foo, /* comment */ .../* comment 2*/ ), +} + +fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} + +fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} + +fn impl_trait_fn_2() -> impl Future {} + +fn issue_1234() { + do_parse!(name: take_while1!(is_token) >> (Header)) +} diff --git a/tests/source/type_alias.rs b/tests/source/type_alias.rs new file mode 100644 index 00000000000..58c807f4029 --- /dev/null +++ b/tests/source/type_alias.rs @@ -0,0 +1,34 @@ +// rustfmt-normalize_comments: true + +type PrivateTest<'a, I> = (Box + 'a>, Box + 'a>); + +pub type PublicTest<'a, I, O> = Result, Box + 'a>, Box + 'a>>; + +pub type LongGenericListTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Option>; + +pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = Vec; + +pub type GenericsFitButNotEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A1, B, C> = Vec; + +pub type CommentTest< /* Lifetime */ 'a + , + // Type + T + > = (); + + +pub type WithWhereClause where T: Clone, LONGPARAMETERNAME: Clone + Eq + OtherTrait = Option; + +pub type Exactly100CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +pub type Exactly101CharstoEqualWhereTest where T: Clone + Ord + Eq + SomeOtherTrait = Option; + +type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); + +// #1683 +pub type Between = super::operators::Between, AsExpr>>; +pub type NotBetween = super::operators::NotBetween, AsExpr>>; diff --git a/tests/source/unions.rs b/tests/source/unions.rs new file mode 100644 index 00000000000..fc2908e2d9e --- /dev/null +++ b/tests/source/unions.rs @@ -0,0 +1,195 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + + /// A Doc comment +#[AnAttribute] +pub union Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField +} + +// #1029 +pub union Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +union X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub union Writebatch { + #[allow(dead_code)] //only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +// With a where clause and generics. +pub union Foo<'a, Y: Baz> + where X: Whatever +{ + f: SomeType, // Comment beside a field +} + +union Baz { + + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C + +} + +union Baz { + a: A, // Comment A + + b: B, // Comment B + + + + + c: C, // Comment C +} + +union Baz { + + a: A, + + b: B, + c: C, + + + + + d: D + +} + +union Baz +{ + // Comment A + a: A, + + // Comment B +b: B, + // Comment C + c: C,} + +pub union State time::Timespec> { now: F } + +pub union State ()> { now: F } + +pub union State { now: F } + +union Palette { /// A map of indices in the palette to a count of pixels in approximately that color + foo: i32} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +union FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + //Another pre comment + #[attr1] + #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +mod m { + union X where T: Sized { + a: T, + } +} + +union Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn( obj: + *const libc::c_void, tracer : *mut JSTracer ), +} + +union Foo {} +union Foo { + } +union Foo { + // comment + } +union Foo { + // trailing space -> + + + } +union Foo { /* comment */ } + +union LongUnion { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: node::Handle>, + Type, + NodeType>, +} + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +union Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs new file mode 100644 index 00000000000..e41e9a6cea1 --- /dev/null +++ b/tests/source/where-clause-rfc.rs @@ -0,0 +1,58 @@ +// rustfmt-indent_style: Block + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; + +struct Exactly100CharsToSemicolon + (LongLongTypename, i32, i32) + where A: LongTrait1234; + +struct AlwaysOnNextLine where A: LongTrait { + x: i32 +} + +pub trait SomeTrait + where + T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr +{ +} + +// #2020 +impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { + fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) + where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssociatedItem), + { + // ... + } +} diff --git a/tests/source/where-clause.rs b/tests/source/where-clause.rs new file mode 100644 index 00000000000..2a916082548 --- /dev/null +++ b/tests/source/where-clause.rs @@ -0,0 +1,58 @@ +// rustfmt-indent_style: Visual + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape, shape: &Shape) where T: FOo { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo, U: Bar { + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) -> Option where T: FOo { + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType where F: FnMut(Self::Item) -> bool { } + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) where A: LongTrait; + +struct Exactly100CharsToSemicolon + (LongLongTypename, i32, i32) + where A: LongTrait1234; + +struct AlwaysOnNextLine where A: LongTrait { + x: i32 +} + +pub trait SomeTrait + where + T: Something + Sync + Send + Display + Debug + Copy + Hash + Debug + Display + Write + Read + FromStr +{ +} + +// #2020 +impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { + fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) + where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssociatedItem), + { + // ... + } +} diff --git a/tests/target/assignment.rs b/tests/target/assignment.rs new file mode 100644 index 00000000000..4e8689ed23e --- /dev/null +++ b/tests/target/assignment.rs @@ -0,0 +1,36 @@ +// Test assignment + +fn main() { + let some_var: Type; + + let mut mutable; + + let variable = + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::EEEEEE; + + variable = + LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG; + + let single_line_fit = DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; + + single_line_fit = 5; + single_lit_fit >>= 10; +} + +fn break_meee() { + { + ( + block_start, + block_size, + margin_block_start, + margin_block_end, + ) = match (block_start, block_end, block_size) { + x => 1, + _ => 2, + }; + } +} + +// #2018 +pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = + "Unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/tests/target/associated-items.rs b/tests/target/associated-items.rs new file mode 100644 index 00000000000..1b0a828d029 --- /dev/null +++ b/tests/target/associated-items.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}", ::default()); +} diff --git a/tests/target/associated-types-bounds-wrapping.rs b/tests/target/associated-types-bounds-wrapping.rs new file mode 100644 index 00000000000..d5b94a5e869 --- /dev/null +++ b/tests/target/associated-types-bounds-wrapping.rs @@ -0,0 +1,7 @@ +// rustfmt-max_width: 100 +// Test proper wrapping of long associated type bounds + +pub trait HttpService { + type WsService: 'static + + Service; +} diff --git a/tests/target/associated_type_defaults.rs b/tests/target/associated_type_defaults.rs new file mode 100644 index 00000000000..d0a08133725 --- /dev/null +++ b/tests/target/associated_type_defaults.rs @@ -0,0 +1,4 @@ +#![feature(associated_type_defaults)] +trait Foo { + type Bar = (); +} diff --git a/tests/target/attrib-extern-crate.rs b/tests/target/attrib-extern-crate.rs new file mode 100644 index 00000000000..ed64a0aeb07 --- /dev/null +++ b/tests/target/attrib-extern-crate.rs @@ -0,0 +1,17 @@ +// Attributes on extern crate. + +#[Attr1] +extern crate Bar; +#[Attr2] +#[Attr2] +extern crate Baz; +extern crate Foo; + +fn foo() { + #[Attr1] + extern crate Bar; + #[Attr2] + #[Attr2] + extern crate Baz; + extern crate Foo; +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs new file mode 100644 index 00000000000..0a3d2bc0b81 --- /dev/null +++ b/tests/target/attrib.rs @@ -0,0 +1,160 @@ +// rustfmt-wrap_comments: true +// Test attributes and doc comments are preserved. + +//! Doc comment + +#![attribute] + +//! Crate doc comment + +// Comment + +// Comment on attribute +#![the(attribute)] + +// Another comment + +#[invalid attribute] +fn foo() {} + +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. +/// Blah blah blah. + +/// Blah blah blah. +impl Bar { + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + /// Blah blah blooo. + #[an_attribute] + fn foo(&mut self) -> isize {} + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + + /// Blah blah bing. + /// Blah blah bing. + /// Blah blah bing. + pub fn f2(self) { + (foo, bar) + } + + #[another_attribute] + fn f3(self) -> Dog {} + + /// Blah blah bing. + + #[attrib1] + /// Blah blah bing. + #[attrib2] + // Another comment that needs rewrite because it's tooooooooooooooooooooooooooooooo + // loooooooooooong. + /// Blah blah bing. + fn f4(self) -> Cat {} + + // We want spaces around `=` + #[cfg(feature = "nightly")] + fn f5(self) -> Monkey {} +} + +// #984 +struct Foo { + #[derive(Clone, PartialEq, Debug, Deserialize, Serialize)] + foo: usize, +} + +// #1668 + +/// Default path (*nix) +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] +fn foo() { + #[cfg(target_os = "freertos")] + match port_id { + 'a' | 'A' => GpioPort { + port_address: GPIO_A, + }, + 'b' | 'B' => GpioPort { + port_address: GPIO_B, + }, + _ => panic!(), + } + + #[cfg_attr(not(target_os = "freertos"), allow(unused_variables))] + let x = 3; +} + +// #1777 +#[test] +#[should_panic(expected = "(")] +#[should_panic(expected = /* ( */ "(")] +#[should_panic(/* ((((( */expected /* ((((( */= /* ((((( */ "("/* ((((( */)] +#[should_panic( + /* (((((((( *//* + (((((((((()(((((((( */ + expected = "(" + // (((((((( +)] +fn foo() {} + +// #1799 +fn issue_1799() { + #[allow(unreachable_code)] // https://github.com/rust-lang/rust/issues/43336 + Some(Err(error)); + + #[allow(unreachable_code)] + // https://github.com/rust-lang/rust/issues/43336 + Some(Err(error)); +} + +// Formatting inner attributes +fn inner_attributes() { + #![this_is_an_inner_attribute(foo)] + + foo(); +} + +impl InnerAttributes() { + #![this_is_an_inner_attribute(foo)] + + fn foo() {} +} + +mod InnerAttributes { + #![this_is_an_inner_attribute(foo)] +} + +fn attributes_on_statements() { + // Local + #[attr(on(local))] + let x = 3; + + // Item + #[attr(on(item))] + use foo; + + // Expr + #[attr(on(expr))] + {} + + // Semi + #[attr(on(semi))] + foo(); + + // Mac + #[attr(on(mac))] + foo!(); +} + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, + Deserialize)] +pub struct HP(pub u8); + +// Long `#[doc = "..."]` +struct A { + #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] + b: i32, +} diff --git a/tests/target/big-impl-block.rs b/tests/target/big-impl-block.rs new file mode 100644 index 00000000000..bc16f12c9d7 --- /dev/null +++ b/tests/target/big-impl-block.rs @@ -0,0 +1,87 @@ +// rustfmt-indent_style: Block + +// #1357 +impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> + for SelectStatement +where + DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a, +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new( + Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset), + ) + } +} + +// #1369 +impl Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} +impl Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} +impl< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, +> Foo + for Bar< + ExcessivelyLongGenericName, + ExcessivelyLongGenericName, + AnotherExcessivelyLongGenericName, + > { + fn foo() {} +} + +// #1689 +impl SubSelectDirect +where + M: select::Selector, + S: event::Stream, + F: for<'t> FnMut(transform::Api<'t, Stream>>) -> transform::Api<'t, X>, + X: event::Stream, +{ +} diff --git a/tests/target/big-impl-visual.rs b/tests/target/big-impl-visual.rs new file mode 100644 index 00000000000..91e7cb5b983 --- /dev/null +++ b/tests/target/big-impl-visual.rs @@ -0,0 +1,73 @@ +// rustfmt-indent_style: Visual + +// #1357 +impl<'a, Select, From, Distinct, Where, Order, Limit, Offset, Groupby, DB> InternalBoxedDsl<'a, DB> + for SelectStatement + where DB: Backend, + Select: QueryFragment + SelectableExpression + 'a, + Distinct: QueryFragment + 'a, + Where: Into + 'a>>>, + Order: QueryFragment + 'a, + Limit: QueryFragment + 'a, + Offset: QueryFragment + 'a +{ + type Output = BoxedSelectStatement<'a, Select::SqlTypeForSelect, From, DB>; + + fn internal_into_boxed(self) -> Self::Output { + BoxedSelectStatement::new(Box::new(self.select), + self.from, + Box::new(self.distinct), + self.where_clause.into(), + Box::new(self.order), + Box::new(self.limit), + Box::new(self.offset)) + } +} + +// #1369 +impl Foo for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} +impl Foo for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} +impl Foo + for Bar +{ + fn foo() {} +} diff --git a/tests/target/break-and-continue.rs b/tests/target/break-and-continue.rs new file mode 100644 index 00000000000..c01d8a07845 --- /dev/null +++ b/tests/target/break-and-continue.rs @@ -0,0 +1,23 @@ +// break and continue formatting + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} diff --git a/tests/target/catch.rs b/tests/target/catch.rs new file mode 100644 index 00000000000..640f9bade49 --- /dev/null +++ b/tests/target/catch.rs @@ -0,0 +1,21 @@ +#![feature(catch_expr)] + +fn main() { + let x = do catch { foo()? }; + + let x = do catch /* Invisible comment */ { foo()? }; + + let x = do catch { unsafe { foo()? } }; + + let y = match (do catch { foo()? }) { + _ => (), + }; + + do catch { + foo()?; + }; + + do catch { + // Regular do catch block + }; +} diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs new file mode 100644 index 00000000000..b842d73c99f --- /dev/null +++ b/tests/target/chains-visual.rs @@ -0,0 +1,159 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Visual +// Test chain formatting. + +fn main() { + // Don't put chains on a single line if it wasn't so in source. + let a = b.c.d.1.foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd + .eeeeeeee(); + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x().y(|| match cond() { + true => (), + false => (), + }); + + loong_func().quux(move || if true { 1 } else { 2 }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }) + .method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = + xxxxxxx.map(|x| x + 5) + .map(|x| x / 2) + .fold(0, |acc, x| acc + x); + + aaaaaaaaaaaaaaaa.map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { field1: val1, + field2: val2, }; + + let x = Foo { field1: val1, + field2: val2, }.method_call() + .method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone()); + } + } + } + + if cond { + some(); + } else { + none(); + }.bar() + .baz(); + + Foo { x: val }.baz(|| { + force(); + multiline(); + }) + .quux(); + + Foo { y: i_am_multi_line, + z: ok, }.baz(|| { + force(); + multiline(); + }) + .quux(); + + a + match x { + true => "yay!", + false => "boo!", + }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)) + .unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn issue_1389() { + let names = String::from_utf8(names)?.split('|') + .map(str::to_owned) + .collect(); +} + +fn issue1217() -> Result { + let random_chars: String = OsRng::new()?.gen_ascii_chars() + .take(self.bit_length) + .collect(); + + Ok(Mnemonic::new(&random_chars)) +} + +fn issue1236(options: Vec) -> Result> { + let process = Command::new("dmenu").stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .chain_err(|| "failed to spawn dmenu")?; +} + +fn issue1434() { + for _ in 0..100 { + let prototype_id = + PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; + } +} + +fn issue2264() { + { + something.function() + .map(|| { + if let a_very_very_very_very_very_very_very_very_long_variable = + compute_this_variable() + { + println!("Hello"); + } + }) + .collect(); + } +} diff --git a/tests/target/chains.rs b/tests/target/chains.rs new file mode 100644 index 00000000000..8a41eec2bde --- /dev/null +++ b/tests/target/chains.rs @@ -0,0 +1,261 @@ +// rustfmt-normalize_comments: true +// rustfmt-use_small_heuristics: false +// Test chain formatting. + +fn main() { + let a = b.c.d.1.foo(|x| x + 1); + + bbbbbbbbbbbbbbbbbbb.ccccccccccccccccccccccccccccccccccccc.ddddddddddddddddddddddddddd(); + + bbbbbbbbbbbbbbbbbbb + .ccccccccccccccccccccccccccccccccccccc + .ddddddddddddddddddddddddddd + .eeeeeeee(); + + let f = fooooooooooooooooooooooooooooooooooooooooooooooooooo + .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar; + + // Test case where first chain element isn't a path, but is shorter than + // the size of a tab. + x().y(|| match cond() { + true => (), + false => (), + }); + + loong_func().quux(move || { + if true { + 1 + } else { + 2 + } + }); + + some_fuuuuuuuuunction().method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + some_fuuuuuuuuunction() + .method_call_a(aaaaa, bbbbb, |c| { + let x = c; + x + }) + .method_call_b(aaaaa, bbbbb, |c| { + let x = c; + x + }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + + let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = + xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x); + + body.fold(Body::new(), |mut body, chunk| { + body.extend(chunk); + Ok(body) + }).and_then(move |body| { + let req = Request::from_parts(parts, body); + f(req).map_err(|_| io::Error::new(io::ErrorKind::Other, "")) + }); + + aaaaaaaaaaaaaaaa + .map(|x| { + x += 1; + x + }) + .filter(some_mod::some_filter) +} + +fn floaters() { + let z = Foo { + field1: val1, + field2: val2, + }; + + let x = Foo { + field1: val1, + field2: val2, + }.method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + }.method_call(); + + { + match x { + PushParam => { + // params are 1-indexed + stack.push( + mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }].clone(), + ); + } + } + } + + if cond { + some(); + } else { + none(); + }.bar() + .baz(); + + Foo { + x: val, + }.baz(|| { + force(); + multiline(); + }) + .quux(); + + Foo { + y: i_am_multi_line, + z: ok, + }.baz(|| { + force(); + multiline(); + }) + .quux(); + + a + match x { + true => "yay!", + false => "boo!", + }.bar() +} + +fn is_replaced_content() -> bool { + constellat.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); +} + +fn issue587() { + a.b::<()>(c); + + std::mem::transmute(dl.symbol::<()>("init").unwrap()) +} + +fn try_shorthand() { + let x = expr?; + let y = expr.kaas()?.test(); + let loooooooooooooooooooooooooooooooooooooooooong = + does_this?.look?.good?.should_we_break?.after_the_first_question_mark?; + let yyyy = expr?.another?.another?.another?.another?.another?.another?.another?.another?.test(); + let zzzz = expr?.another?.another?.another?.another?; + let aaa = x??????????????????????????????????????????????????????????????????????????; + + let y = a.very + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; + + parameterized(f, substs, def_id, Ns::Value, &[], |tcx| tcx.lookup_item_type(def_id).generics)?; + fooooooooooooooooooooooooooo()? + .bar()? + .baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz()?; +} + +fn issue_1004() { + match *self { + ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), + ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), + }?; + + ty::tls::with(|tcx| { + let tap = ty::Binder(TraitAndProjections(principal, projections)); + in_binder(f, tcx, &ty::Binder(""), Some(tap)) + })?; +} + +fn issue1392() { + test_method( + r#" + if foo { + a(); + } + else { + b(); + } + "#.trim(), + ); +} + +// #2067 +impl Settings { + fn save(&self) -> Result<()> { + let mut file = File::create(&settings_path) + .chain_err(|| ErrorKind::WriteError(settings_path.clone()))?; + } +} + +fn issue2126() { + { + { + { + { + { + let x = self.span_from( + sub_span.expect("No span found for struct arant variant"), + ); + self.sspanpan_from_span( + sub_span.expect("No span found for struct variant"), + ); + let x = self.spanpan_from_span( + sub_span.expect("No span found for struct variant"), + )?; + } + } + } + } + } +} + +// #2200 +impl Foo { + pub fn from_ast(diagnostic: &::errors::Handler, attrs: &[ast::Attribute]) -> Attributes { + let other_attrs = attrs + .iter() + .filter_map(|attr| { + attr.with_desugared_doc(|attr| { + if attr.check_name("doc") { + if let Some(mi) = attr.meta() { + if let Some(value) = mi.value_str() { + doc_strings.push(DocFragment::Include( + line, + attr.span, + filename, + contents, + )); + } + } + } + }) + }) + .collect(); + } +} + +// #2415 +// Avoid orphan in chain +fn issue2415() { + let base_url = (|| { + // stuff + + Ok((|| { + // stuff + Some(value.to_string()) + })().ok_or("")?) + })().unwrap_or_else(|_: Box<::std::error::Error>| String::from("")); +} diff --git a/tests/target/closure-block-inside-macro.rs b/tests/target/closure-block-inside-macro.rs new file mode 100644 index 00000000000..c1260592083 --- /dev/null +++ b/tests/target/closure-block-inside-macro.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Block + +// #1547 +fuzz_target!(|data: &[u8]| if let Some(first) = data.first() { + let index = *first as usize; + if index >= ENCODINGS.len() { + return; + } + let encoding = ENCODINGS[index]; + dispatch_test(encoding, &data[1..]); +}); diff --git a/tests/target/closure.rs b/tests/target/closure.rs new file mode 100644 index 00000000000..5bc89d58222 --- /dev/null +++ b/tests/target/closure.rs @@ -0,0 +1,248 @@ +// rustfmt-normalize_comments: true +// Closures + +fn main() { + let square = (|i: i32| i * i); + + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| { + ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ) + }; + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // format comments. + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo() + } else { + field.span.lo() + } + }; + + let unblock_me = |trivial| closure(); + + let empty = |arg| {}; + + let simple = |arg| { + // comment formatting + foo(arg) + }; + + let test = || { + do_something(); + do_something_else(); + }; + + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { foo() }; + + let closure_with_return_type = + |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + + |arg1, arg2, _, _, arg3, arg4| { + let temp = arg4 + arg3; + arg2 * arg1 - temp + }; + + let block_body_with_comment = args.iter().map(|a| { + // Emitting only dep-info is possible only for final crate type, as + // as others may emit required metadata for dependent crate types + if a.starts_with("--emit") && is_final_crate_type && !self.workspace_mode { + "--emit=dep-info" + } else { + a + } + }); +} + +fn issue311() { + let func = |x| println!("{}", x); + + (func)(0.0); +} + +fn issue863() { + let closure = |x| match x { + 0 => true, + _ => false, + } == true; +} + +fn issue934() { + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish() + }; + + let hash: &Fn(&&Block) -> u64 = &|block| -> u64 { + let mut h = SpanlessHash::new(cx); + h.hash_block(block); + h.finish(); + }; +} + +impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { + pub fn eq_expr(&self, left: &Expr, right: &Expr) -> bool { + match (&left.node, &right.node) { + (&ExprBinary(l_op, ref ll, ref lr), &ExprBinary(r_op, ref rl, ref rr)) => { + l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| { + l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) + }) + } + } + } +} + +fn foo() { + lifetimes_iter___map(|lasdfasfd| { + let hi = if l.bounds.is_empty() { + l.lifetime.span.hi() + }; + }); +} + +fn issue1405() { + open_raw_fd(fd, b'r').and_then(|file| { + Capture::new_raw(None, |_, err| unsafe { raw::pcap_fopen_offline(file, err) }) + }); +} + +fn issue1466() { + let vertex_buffer = frame.scope(|ctx| { + let buffer = ctx.create_host_visible_buffer::>(&vertices); + ctx.create_device_local_buffer(buffer) + }); +} + +fn issue470() { + { + { + { + let explicit_arg_decls = explicit_arguments.into_iter().enumerate().map( + |(index, (ty, pattern))| { + let lvalue = Lvalue::Arg(index as u32); + block = this.pattern( + block, + argument_extent, + hair::PatternRef::Hair(pattern), + &lvalue, + ); + ArgDecl { ty: ty } + }, + ); + } + } + } +} + +// #1509 +impl Foo { + pub fn bar(&self) { + Some(SomeType { + push_closure_out_to_100_chars: iter(otherwise_it_works_ok.into_iter().map(|f| Ok(f))), + }) + } +} + +fn issue1329() { + aaaaaaaaaaaaaaaa + .map(|x| { + x += 1; + x + }) + .filter +} + +fn issue325() { + let f = + || unsafe { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }; +} + +fn issue1697() { + Test.func_a( + A_VERY_LONG_CONST_VARIABLE_NAME, + move |arg1, arg2, arg3, arg4| arg1 + arg2 + arg3 + arg4, + ) +} + +fn issue1694() { + foooooo( + |_referencefffffffff: _, _target_reference: _, _oid: _, _target_oid: _| { + format!("refs/pull/{}/merge", pr_id) + }, + ) +} + +fn issue1713() { + rayon::join( + || recurse(left, is_less, pred, limit), + || recurse(right, is_less, Some(pivot), limit), + ); + + rayon::join( + 1, + || recurse(left, is_less, pred, limit), + 2, + || recurse(right, is_less, Some(pivot), limit), + ); +} + +fn issue2063() { + |ctx: Ctx<(String, String)>| -> io::Result { + Ok(Response::new().with_body(ctx.params.0)) + } +} + +fn issue1524() { + let f = |x| x; + let f = |x| x; + let f = |x| x; + let f = |x| x; + let f = |x| x; +} + +fn issue2171() { + foo(|| unsafe { + if PERIPHERALS { + loop {} + } else { + PERIPHERALS = true; + } + }) +} + +fn issue2207() { + a.map(|_| { + unsafe { a_very_very_very_very_very_very_very_long_function_name_or_anything_else() } + .to_string() + }) +} + +fn issue2262() { + result + .init(&mut result.slave.borrow_mut(), &mut (result.strategy)()) + .map_err(|factory| Error { + factory, + slave: None, + })?; +} diff --git a/tests/target/comment-inside-const.rs b/tests/target/comment-inside-const.rs new file mode 100644 index 00000000000..f847f2c69de --- /dev/null +++ b/tests/target/comment-inside-const.rs @@ -0,0 +1,9 @@ +fn issue982() { + const SOME_CONSTANT: u32 = + // Explanation why SOME_CONSTANT needs FLAG_A to be set. + FLAG_A | + // Explanation why SOME_CONSTANT needs FLAG_B to be set. + FLAG_B | + // Explanation why SOME_CONSTANT needs FLAG_C to be set. + FLAG_C; +} diff --git a/tests/target/comment-not-disappear.rs b/tests/target/comment-not-disappear.rs new file mode 100644 index 00000000000..646b37e46e2 --- /dev/null +++ b/tests/target/comment-not-disappear.rs @@ -0,0 +1,36 @@ +// All the comments here should not disappear. + +fn a() { + match x { + X | + // A comment + Y => {} + }; +} + +fn b() { + match x { + X => + // A comment + y + } +} + +fn c() { + a() /* ... */; +} + +fn foo() -> Vec { + (0..11) + .map(|x| + // This comment disappears. + if x % 2 == 0 { x } else { x * 2 }) + .collect() +} + +fn calc_page_len(prefix_len: usize, sofar: usize) -> usize { + 2 // page type and flags + + 1 // stored depth + + 2 // stored count + + prefix_len + sofar // sum of size of all the actual items +} diff --git a/tests/target/comment.rs b/tests/target/comment.rs new file mode 100644 index 00000000000..5abf5369066 --- /dev/null +++ b/tests/target/comment.rs @@ -0,0 +1,95 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//! Doc comment +fn test() { + //! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam + //! lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + + // comment + // comment2 + + code(); // leave this comment alone! + // ok? + + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + // diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + // viverra nec consectetur ante hendrerit. Donec et mollis dolor. + // Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + // tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + // libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + // amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + // felis, pulvinar a semper sed, adipiscing id dolor. + + // Very looooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment + // that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); // dontchangeme + // or me + + // #1388 + const EXCEPTION_PATHS: &'static [&'static str] = &[ + // std crates + "src/libstd/sys/", // Platform-specific code for std lives here. + "src/bootstrap", + ]; +} + +/// test123 +fn doc_comment() {} + +fn chains() { + foo.bar(|| { + let x = 10; + // comment + x + }) +} + +fn issue_1086() { + // +} + +// random comment + +fn main() { + // Test +} + +// #1643 +fn some_fn() // some comment +{ +} + +fn some_fn1() +// some comment +{ +} + +fn some_fn2() // some comment +{ +} + +fn some_fn3() // some comment some comment some comment some comment some comment some comment so +{ +} + +fn some_fn4() +// some comment some comment some comment some comment some comment some comment +// some comment +{ +} + +// #1603 +pub enum Foo { + A, // `/** **/` + B, // `/*!` + C, +} diff --git a/tests/target/comment2.rs b/tests/target/comment2.rs new file mode 100644 index 00000000000..04f84a15c95 --- /dev/null +++ b/tests/target/comment2.rs @@ -0,0 +1,5 @@ +// rustfmt-wrap_comments: true + +/// This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly +/// and justly. +pub mod foo {} diff --git a/tests/target/comment3.rs b/tests/target/comment3.rs new file mode 100644 index 00000000000..3a810590d7b --- /dev/null +++ b/tests/target/comment3.rs @@ -0,0 +1,6 @@ +// rustfmt-wrap_comments: true + +//! This is a long line that angers rustfmt. Rustfmt shall deal with it swiftly +//! and justly. + +pub mod foo {} diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs new file mode 100644 index 00000000000..e07abf74a81 --- /dev/null +++ b/tests/target/comment4.rs @@ -0,0 +1,51 @@ +#![allow(dead_code)] // bar + +//! Doc comment +fn test() { + // comment + // comment2 + + code(); /* leave this comment alone! + * ok? */ + + /* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a + * diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam + * viverra nec consectetur ante hendrerit. Donec et mollis dolor. + * Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam + * tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut + * libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit + * amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis + * felis, pulvinar a semper sed, adipiscing id dolor. */ + + // Very loooooooooooooooooooooooooooooooooooooooooooooooooooooooong comment that should be split + + // println!("{:?}", rewrite_comment(subslice, + // false, + // comment_width, + // self.block_indent, + // self.config) + // .unwrap()); + + funk(); //dontchangeme + // or me +} + +/// test123 +fn doc_comment() {} + +/* +Regression test for issue #956 + +(some very important text) +*/ + +/* +fn debug_function() { + println!("hello"); +} +// */ + +#[link_section=".vectors"] +#[no_mangle] // Test this attribute is preserved. +#[cfg_attr(rustfmt, rustfmt_skip)] +pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/target/comment5.rs b/tests/target/comment5.rs new file mode 100644 index 00000000000..c52f9b38977 --- /dev/null +++ b/tests/target/comment5.rs @@ -0,0 +1,16 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +//@ special comment +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam +//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ +//@ foo +fn test() {} + +//@@@ another special comment +//@@@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam +//@@@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@@@ +//@@@ foo +fn bar() {} diff --git a/tests/target/comment_crlf_newline.rs b/tests/target/comment_crlf_newline.rs new file mode 100644 index 00000000000..aab9e94d9e6 --- /dev/null +++ b/tests/target/comment_crlf_newline.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true +// Block comments followed by CRLF newlines should not an extra newline at the end + +// Something else diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs new file mode 100644 index 00000000000..39af3fd064e --- /dev/null +++ b/tests/target/comments-fn.rs @@ -0,0 +1,39 @@ +// Test comments on functions are preserved. + +// Comment on foo. +fn foo( + a: aaaaaaaaaaaaa, // A comment + b: bbbbbbbbbbbbb, // a second comment + c: ccccccccccccc, + // Newline comment + d: ddddddddddddd, + // A multi line comment + // between args. + e: eeeeeeeeeeeee, /* comment before paren */ +) -> bar +where + F: Foo, // COmment after where clause + G: Goo, // final comment +{ + +} + +fn bar() {} + +fn baz() -> Baz /* Comment after return type */ {} + +fn some_fn() +where + T: Eq, // some comment +{ +} + +fn issue458(a: &str, f: F) +// comment1 +where + // comment2 + F: FnOnce(&str) -> bool, +{ + f(a); + () +} diff --git a/tests/target/configs/blank_lines_lower_bound/1.rs b/tests/target/configs/blank_lines_lower_bound/1.rs new file mode 100644 index 00000000000..9706699dc7a --- /dev/null +++ b/tests/target/configs/blank_lines_lower_bound/1.rs @@ -0,0 +1,16 @@ +// rustfmt-blank_lines_lower_bound: 1 + +fn foo() {} + +fn bar() {} + +// comment +fn foobar() {} + +fn foo1() {} + +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/tests/target/configs/brace_style/fn_always_next_line.rs b/tests/target/configs/brace_style/fn_always_next_line.rs new file mode 100644 index 00000000000..2755a264689 --- /dev/null +++ b/tests/target/configs/brace_style/fn_always_next_line.rs @@ -0,0 +1,19 @@ +// rustfmt-brace_style: AlwaysNextLine +// Function brace style + +fn lorem() +{ + // body +} + +fn lorem(ipsum: usize) +{ + // body +} + +fn lorem(ipsum: T) +where + T: Add + Sub + Mul + Div, +{ + // body +} diff --git a/tests/target/configs/brace_style/fn_prefer_same_line.rs b/tests/target/configs/brace_style/fn_prefer_same_line.rs new file mode 100644 index 00000000000..23f98b6dd7a --- /dev/null +++ b/tests/target/configs/brace_style/fn_prefer_same_line.rs @@ -0,0 +1,16 @@ +// rustfmt-brace_style: PreferSameLine +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) +where + T: Add + Sub + Mul + Div, { + // body +} diff --git a/tests/target/configs/brace_style/fn_same_line_where.rs b/tests/target/configs/brace_style/fn_same_line_where.rs new file mode 100644 index 00000000000..2afe59943a3 --- /dev/null +++ b/tests/target/configs/brace_style/fn_same_line_where.rs @@ -0,0 +1,17 @@ +// rustfmt-brace_style: SameLineWhere +// Function brace style + +fn lorem() { + // body +} + +fn lorem(ipsum: usize) { + // body +} + +fn lorem(ipsum: T) +where + T: Add + Sub + Mul + Div, +{ + // body +} diff --git a/tests/target/configs/brace_style/item_always_next_line.rs b/tests/target/configs/brace_style/item_always_next_line.rs new file mode 100644 index 00000000000..38ed449d178 --- /dev/null +++ b/tests/target/configs/brace_style/item_always_next_line.rs @@ -0,0 +1,27 @@ +// rustfmt-brace_style: AlwaysNextLine +// Item brace style + +enum Foo {} + +struct Bar {} + +struct Lorem +{ + ipsum: bool, +} + +struct Dolor +where + T: Eq, +{ + sit: T, +} + +#[cfg(test)] +mod tests +{ + #[test] + fn it_works() + { + } +} diff --git a/tests/target/configs/brace_style/item_prefer_same_line.rs b/tests/target/configs/brace_style/item_prefer_same_line.rs new file mode 100644 index 00000000000..5143d7517c7 --- /dev/null +++ b/tests/target/configs/brace_style/item_prefer_same_line.rs @@ -0,0 +1,18 @@ +// rustfmt-brace_style: PreferSameLine +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor +where + T: Eq, { + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/tests/target/configs/brace_style/item_same_line_where.rs b/tests/target/configs/brace_style/item_same_line_where.rs new file mode 100644 index 00000000000..8a3b2852654 --- /dev/null +++ b/tests/target/configs/brace_style/item_same_line_where.rs @@ -0,0 +1,19 @@ +// rustfmt-brace_style: SameLineWhere +// Item brace style + +struct Lorem { + ipsum: bool, +} + +struct Dolor +where + T: Eq, +{ + sit: T, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() {} +} diff --git a/tests/target/configs/combine_control_expr/false.rs b/tests/target/configs/combine_control_expr/false.rs new file mode 100644 index 00000000000..81eff08660d --- /dev/null +++ b/tests/target/configs/combine_control_expr/false.rs @@ -0,0 +1,133 @@ +// rustfmt-indent_style: Block +// rustfmt-combine_control_expr: false +// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. + +fn main() { + // Call + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Mac + foo(foo!( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // MethodCall + foo(x.foo::( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Block + foo!({ + foo(); + bar(); + }); + + // Closure + foo(|x| { + let y = x + 1; + y + }); + + // Match + foo(match opt { + Some(x) => x, + None => y, + }); + + // Struct + foo(Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // If + foo!( + if x { + foo(); + } else { + bar(); + } + ); + + // IfLet + foo!( + if let Some(..) = x { + foo(); + } else { + bar(); + } + ); + + // While + foo!( + while x { + foo(); + bar(); + } + ); + + // WhileLet + foo!( + while let Some(..) = x { + foo(); + bar(); + } + ); + + // ForLoop + foo!( + for x in y { + foo(); + bar(); + } + ); + + // Loop + foo!( + loop { + foo(); + bar(); + } + ); + + // Tuple + foo(( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // AddrOf + foo(&bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Box + foo(box Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // Unary + foo(!bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Try + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )?); + + // Cast + foo(Bar { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + } as i64); +} diff --git a/tests/target/configs/combine_control_expr/true.rs b/tests/target/configs/combine_control_expr/true.rs new file mode 100644 index 00000000000..c5372c2ff37 --- /dev/null +++ b/tests/target/configs/combine_control_expr/true.rs @@ -0,0 +1,121 @@ +// rustfmt-indent_style: Block +// rustfmt-combine_control_expr: true +// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. + +fn main() { + // Call + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Mac + foo(foo!( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // MethodCall + foo(x.foo::( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Block + foo!({ + foo(); + bar(); + }); + + // Closure + foo(|x| { + let y = x + 1; + y + }); + + // Match + foo(match opt { + Some(x) => x, + None => y, + }); + + // Struct + foo(Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // If + foo!(if x { + foo(); + } else { + bar(); + }); + + // IfLet + foo!(if let Some(..) = x { + foo(); + } else { + bar(); + }); + + // While + foo!(while x { + foo(); + bar(); + }); + + // WhileLet + foo!(while let Some(..) = x { + foo(); + bar(); + }); + + // ForLoop + foo!(for x in y { + foo(); + bar(); + }); + + // Loop + foo!(loop { + foo(); + bar(); + }); + + // Tuple + foo(( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // AddrOf + foo(&bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Box + foo(box Bar { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + }); + + // Unary + foo(!bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )); + + // Try + foo(bar( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + )?); + + // Cast + foo(Bar { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + } as i64); +} diff --git a/tests/target/configs/comment_width/above.rs b/tests/target/configs/comment_width/above.rs new file mode 100644 index 00000000000..ddfecda65c1 --- /dev/null +++ b/tests/target/configs/comment_width/above.rs @@ -0,0 +1,8 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, + // consectetur adipiscing elit. +} diff --git a/tests/target/configs/comment_width/below.rs b/tests/target/configs/comment_width/below.rs new file mode 100644 index 00000000000..abbc5930c4c --- /dev/null +++ b/tests/target/configs/comment_width/below.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 80 +// rustfmt-wrap_comments: true +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/tests/target/configs/comment_width/ignore.rs b/tests/target/configs/comment_width/ignore.rs new file mode 100644 index 00000000000..c86e71c2898 --- /dev/null +++ b/tests/target/configs/comment_width/ignore.rs @@ -0,0 +1,7 @@ +// rustfmt-comment_width: 40 +// rustfmt-wrap_comments: false +// Comment width + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. +} diff --git a/tests/target/configs/condense_wildcard_suffixes/false.rs b/tests/target/configs/condense_wildcard_suffixes/false.rs new file mode 100644 index 00000000000..3b967f35a8e --- /dev/null +++ b/tests/target/configs/condense_wildcard_suffixes/false.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: false +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, _, _) = (1, 2, 3, 4); +} diff --git a/tests/target/configs/condense_wildcard_suffixes/true.rs b/tests/target/configs/condense_wildcard_suffixes/true.rs new file mode 100644 index 00000000000..4f880abe80e --- /dev/null +++ b/tests/target/configs/condense_wildcard_suffixes/true.rs @@ -0,0 +1,6 @@ +// rustfmt-condense_wildcard_suffixes: true +// Condense wildcard suffixes + +fn main() { + let (lorem, ipsum, ..) = (1, 2, 3, 4); +} diff --git a/tests/target/configs/control_brace_style/always_next_line.rs b/tests/target/configs/control_brace_style/always_next_line.rs new file mode 100644 index 00000000000..7dc06f207fe --- /dev/null +++ b/tests/target/configs/control_brace_style/always_next_line.rs @@ -0,0 +1,18 @@ +// rustfmt-control_brace_style: AlwaysNextLine +// Control brace style + +fn main() { + if lorem + { + println!("ipsum!"); + } + else + { + println!("dolor!"); + } + match magi + { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/tests/target/configs/control_brace_style/always_same_line.rs b/tests/target/configs/control_brace_style/always_same_line.rs new file mode 100644 index 00000000000..993b6b681fe --- /dev/null +++ b/tests/target/configs/control_brace_style/always_same_line.rs @@ -0,0 +1,14 @@ +// rustfmt-control_brace_style: AlwaysSameLine +// Control brace style + +fn main() { + if lorem { + println!("ipsum!"); + } else { + println!("dolor!"); + } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/tests/target/configs/control_brace_style/closing_next_line.rs b/tests/target/configs/control_brace_style/closing_next_line.rs new file mode 100644 index 00000000000..013852ee79a --- /dev/null +++ b/tests/target/configs/control_brace_style/closing_next_line.rs @@ -0,0 +1,15 @@ +// rustfmt-control_brace_style: ClosingNextLine +// Control brace style + +fn main() { + if lorem { + println!("ipsum!"); + } + else { + println!("dolor!"); + } + match magi { + Homura => "Akemi", + Madoka => "Kaname", + } +} diff --git a/tests/target/configs/disable_all_formatting/false.rs b/tests/target/configs/disable_all_formatting/false.rs new file mode 100644 index 00000000000..1a0477ddb39 --- /dev/null +++ b/tests/target/configs/disable_all_formatting/false.rs @@ -0,0 +1,10 @@ +// rustfmt-disable_all_formatting: false +// Disable all formatting + +fn main() { + if lorem { + println!("ipsum!"); + } else { + println!("dolor!"); + } +} diff --git a/tests/target/configs/disable_all_formatting/true.rs b/tests/target/configs/disable_all_formatting/true.rs new file mode 100644 index 00000000000..736ccf56942 --- /dev/null +++ b/tests/target/configs/disable_all_formatting/true.rs @@ -0,0 +1,6 @@ +// rustfmt-disable_all_formatting: true +// Disable all formatting + +fn main() { + if lorem{println!("ipsum!");}else{println!("dolor!");} +} diff --git a/tests/target/configs/empty_item_single_line/false.rs b/tests/target/configs/empty_item_single_line/false.rs new file mode 100644 index 00000000000..b7886df2aa8 --- /dev/null +++ b/tests/target/configs/empty_item_single_line/false.rs @@ -0,0 +1,15 @@ +// rustfmt-empty_item_single_line: false +// Empty impl on single line + +impl Lorem { +} + +impl Ipsum { +} + +fn lorem() { +} + +fn lorem() { + +} diff --git a/tests/target/configs/empty_item_single_line/true.rs b/tests/target/configs/empty_item_single_line/true.rs new file mode 100644 index 00000000000..0755485fea9 --- /dev/null +++ b/tests/target/configs/empty_item_single_line/true.rs @@ -0,0 +1,10 @@ +// rustfmt-empty_item_single_line: true +// Empty impl on single line + +impl Lorem {} + +impl Ipsum {} + +fn lorem() {} + +fn lorem() {} diff --git a/tests/target/configs/error_on_line_overflow/false.rs b/tests/target/configs/error_on_line_overflow/false.rs new file mode 100644 index 00000000000..fa70ae78352 --- /dev/null +++ b/tests/target/configs/error_on_line_overflow/false.rs @@ -0,0 +1,6 @@ +// rustfmt-error_on_line_overflow: false +// Error on line overflow + +fn main() { + let lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit; +} diff --git a/tests/target/configs/error_on_unformatted/false.rs b/tests/target/configs/error_on_unformatted/false.rs new file mode 100644 index 00000000000..6a78374e2a2 --- /dev/null +++ b/tests/target/configs/error_on_unformatted/false.rs @@ -0,0 +1,12 @@ +// rustfmt-error_on_unformatted: false +// Error on line overflow comment or string literals. + +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn main() { + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + let x = " "; + let a = " + +"; +} diff --git a/tests/target/configs/fn_args_density/compressed.rs b/tests/target/configs/fn_args_density/compressed.rs new file mode 100644 index 00000000000..99283722bee --- /dev/null +++ b/tests/target/configs/fn_args_density/compressed.rs @@ -0,0 +1,22 @@ +// rustfmt-fn_args_density: Compressed +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit, + ) { + // body + } +} diff --git a/tests/target/configs/fn_args_density/tall.rs b/tests/target/configs/fn_args_density/tall.rs new file mode 100644 index 00000000000..6ee43b41a19 --- /dev/null +++ b/tests/target/configs/fn_args_density/tall.rs @@ -0,0 +1,32 @@ +// rustfmt-fn_args_density: Tall +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} diff --git a/tests/target/configs/fn_args_density/vertical.rs b/tests/target/configs/fn_args_density/vertical.rs new file mode 100644 index 00000000000..d48b3492452 --- /dev/null +++ b/tests/target/configs/fn_args_density/vertical.rs @@ -0,0 +1,42 @@ +// rustfmt-fn_args_density: Vertical +// Function arguments density + +trait Lorem { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} diff --git a/tests/target/configs/fn_single_line/false.rs b/tests/target/configs/fn_single_line/false.rs new file mode 100644 index 00000000000..3d092f0c0bf --- /dev/null +++ b/tests/target/configs/fn_single_line/false.rs @@ -0,0 +1,11 @@ +// rustfmt-fn_single_line: false +// Single-expression function on single line + +fn lorem() -> usize { + 42 +} + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/tests/target/configs/fn_single_line/true.rs b/tests/target/configs/fn_single_line/true.rs new file mode 100644 index 00000000000..10d94e02f16 --- /dev/null +++ b/tests/target/configs/fn_single_line/true.rs @@ -0,0 +1,9 @@ +// rustfmt-fn_single_line: true +// Single-expression function on single line + +fn lorem() -> usize { 42 } + +fn lorem() -> usize { + let ipsum = 42; + ipsum +} diff --git a/tests/target/configs/force_explicit_abi/false.rs b/tests/target/configs/force_explicit_abi/false.rs new file mode 100644 index 00000000000..3c48f8e0c78 --- /dev/null +++ b/tests/target/configs/force_explicit_abi/false.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: false +// Force explicit abi + +extern { + pub static lorem: c_int; +} diff --git a/tests/target/configs/force_explicit_abi/true.rs b/tests/target/configs/force_explicit_abi/true.rs new file mode 100644 index 00000000000..90f5a8c4ecb --- /dev/null +++ b/tests/target/configs/force_explicit_abi/true.rs @@ -0,0 +1,6 @@ +// rustfmt-force_explicit_abi: true +// Force explicit abi + +extern "C" { + pub static lorem: c_int; +} diff --git a/tests/target/configs/force_multiline_block/false.rs b/tests/target/configs/force_multiline_block/false.rs new file mode 100644 index 00000000000..7cb4cac1d69 --- /dev/null +++ b/tests/target/configs/force_multiline_block/false.rs @@ -0,0 +1,20 @@ +// rustfmt-force_multiline_blocks: false +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + }); +} diff --git a/tests/target/configs/force_multiline_block/true.rs b/tests/target/configs/force_multiline_block/true.rs new file mode 100644 index 00000000000..aec50afe5a8 --- /dev/null +++ b/tests/target/configs/force_multiline_block/true.rs @@ -0,0 +1,22 @@ +// rustfmt-force_multiline_blocks: true +// Option forces multiline match arm and closure bodies to be wrapped in a block + +fn main() { + match lorem { + Lorem::Ipsum => { + if ipsum { + println!("dolor"); + } + } + Lorem::Dolor => println!("amet"), + } +} + +fn main() { + result.and_then(|maybe_value| { + match maybe_value { + None => Err("oops"), + Some(value) => Ok(1), + } + }); +} diff --git a/tests/target/configs/format_strings/false.rs b/tests/target/configs/format_strings/false.rs new file mode 100644 index 00000000000..ecca0d7d1fc --- /dev/null +++ b/tests/target/configs/format_strings/false.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit"; +} diff --git a/tests/target/configs/format_strings/true.rs b/tests/target/configs/format_strings/true.rs new file mode 100644 index 00000000000..fdd5ab2c97d --- /dev/null +++ b/tests/target/configs/format_strings/true.rs @@ -0,0 +1,9 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 +// Force format strings + +fn main() { + let lorem = "ipsum dolor sit amet \ + consectetur adipiscing elit \ + lorem ipsum dolor sit"; +} diff --git a/tests/target/configs/hard_tabs/false.rs b/tests/target/configs/hard_tabs/false.rs new file mode 100644 index 00000000000..ccfb53d8c86 --- /dev/null +++ b/tests/target/configs/hard_tabs/false.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: false +// Hard tabs + +fn lorem() -> usize { + 42 // spaces before 42 +} diff --git a/tests/target/configs/hard_tabs/true.rs b/tests/target/configs/hard_tabs/true.rs new file mode 100644 index 00000000000..3ed4e4f20aa --- /dev/null +++ b/tests/target/configs/hard_tabs/true.rs @@ -0,0 +1,6 @@ +// rustfmt-hard_tabs: true +// Hard tabs + +fn lorem() -> usize { + 42 // spaces before 42 +} diff --git a/tests/target/configs/imports_indent/block.rs b/tests/target/configs/imports_indent/block.rs new file mode 100644 index 00000000000..84c3b26bd6e --- /dev/null +++ b/tests/target/configs/imports_indent/block.rs @@ -0,0 +1,7 @@ +// rustfmt-imports_indent: Block + +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, + SeparatorTactic, +}; diff --git a/tests/target/configs/imports_layout/horizontal_vertical.rs b/tests/target/configs/imports_layout/horizontal_vertical.rs new file mode 100644 index 00000000000..4a63556d45b --- /dev/null +++ b/tests/target/configs/imports_layout/horizontal_vertical.rs @@ -0,0 +1,18 @@ +// rustfmt-imports_indent: Block +// rustfmt-imports_layout: HorizontalVertical + +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use lists::{ + definitive_tactic, + itemize_list, + shape_for_tactic, + struct_lit_formatting, + struct_lit_shape, + struct_lit_tactic, + write_list, + DefinitiveListTactic, + ListFormatting, + ListItem, + ListTactic, + SeparatorTactic, +}; diff --git a/tests/target/configs/imports_layout/mixed.rs b/tests/target/configs/imports_layout/mixed.rs new file mode 100644 index 00000000000..5d3349a01bb --- /dev/null +++ b/tests/target/configs/imports_layout/mixed.rs @@ -0,0 +1,9 @@ +// rustfmt-imports_indent: Block +// rustfmt-imports_layout: Mixed + +use comment::{contains_comment, recover_comment_removed, rewrite_comment, FindUncommented}; +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, + SeparatorTactic, +}; diff --git a/tests/target/configs/indent_style/block_args.rs b/tests/target/configs/indent_style/block_args.rs new file mode 100644 index 00000000000..80f4e133356 --- /dev/null +++ b/tests/target/configs/indent_style/block_args.rs @@ -0,0 +1,47 @@ +// rustfmt-indent_style: Block +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem( + ipsum: usize, + dolor: usize, + sit: usize, + amet: usize, + consectetur: usize, + adipiscing: usize, + elit: usize, +) { + // body +} + +// #1441 +extern "system" { + pub fn GetConsoleHistoryInfo( + console_history_info: *mut ConsoleHistoryInfo, + ) -> Boooooooooooooool; +} + +// rustfmt should not add trailing comma for variadic function. See #1623. +extern "C" { + pub fn variadic_fn( + first_parameter: FirstParameterType, + second_parameter: SecondParameterType, + ... + ); +} + +// #1652 +fn deconstruct( + foo: Bar, +) -> ( + SocketAddr, + Header, + Method, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { +} diff --git a/tests/target/configs/indent_style/block_array.rs b/tests/target/configs/indent_style/block_array.rs new file mode 100644 index 00000000000..5d458248c0b --- /dev/null +++ b/tests/target/configs/indent_style/block_array.rs @@ -0,0 +1,14 @@ +// rustfmt-indent_style: Block +// Array layout + +fn main() { + let lorem = vec![ + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ]; +} diff --git a/tests/target/configs/indent_style/block_call.rs b/tests/target/configs/indent_style/block_call.rs new file mode 100644 index 00000000000..4e4c9465fe8 --- /dev/null +++ b/tests/target/configs/indent_style/block_call.rs @@ -0,0 +1,149 @@ +// rustfmt-indent_style: Block +// Function call style + +fn main() { + lorem( + "lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ); + // #1501 + let hyper = Arc::new(Client::with_connector( + HttpsConnector::new(TlsClient::new()), + )); + + // chain + let x = yooooooooooooo + .fooooooooooooooo + .baaaaaaaaaaaaar(hello, world); + + // #1380 + { + { + let creds = self.client + .client_credentials(&self.config.auth.oauth2.id, &self.config.auth.oauth2.secret)?; + } + } + + // nesting macro and function call + try!(foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + )); + try!(foo(try!( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ))); +} + +// #1521 +impl Foo { + fn map_pixel_to_coords(&self, point: &Vector2i, view: &View) -> Vector2f { + unsafe { + Vector2f::from_raw(ffi::sfRenderTexture_mapPixelToCoords( + self.render_texture, + point.raw(), + view.raw(), + )) + } + } +} + +fn issue1420() { + given( + r#" + # Getting started + ... + "#, + ).running(waltz) +} + +// #1563 +fn query(conn: &Connection) -> Result<()> { + conn.query_row( + r#" + SELECT title, date + FROM posts, + WHERE DATE(date) = $1 + "#, + &[], + |row| Post { + title: row.get(0), + date: row.get(1), + }, + )?; + + Ok(()) +} + +// #1449 +fn future_rayon_wait_1_thread() { + // run with only 1 worker thread; this would deadlock if we couldn't make progress + let mut result = None; + ThreadPool::new(Configuration::new().num_threads(1)) + .unwrap() + .install(|| { + scope(|s| { + use std::sync::mpsc::channel; + let (tx, rx) = channel(); + let a = s.spawn_future(lazy(move || Ok::(rx.recv().unwrap()))); + // ^^^^ FIXME: why is this needed? + let b = s.spawn_future(a.map(|v| v + 1)); + let c = s.spawn_future(b.map(|v| v + 1)); + s.spawn(move |_| tx.send(20).unwrap()); + result = Some(c.rayon_wait().unwrap()); + }); + }); + assert_eq!(result, Some(22)); +} + +// #1494 +impl Cursor { + fn foo() { + self.cur_type() + .num_template_args() + .or_else(|| { + let n: c_int = unsafe { clang_Cursor_getNumTemplateArguments(self.x) }; + + if n >= 0 { + Some(n as u32) + } else { + debug_assert_eq!(n, -1); + None + } + }) + .or_else(|| { + let canonical = self.canonical(); + if canonical != *self { + canonical.num_template_args() + } else { + None + } + }); + } +} + +fn issue1581() { + bootstrap.checks.register("PERSISTED_LOCATIONS", move || { + if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + } + }); +} + +fn issue1651() { + { + let type_list: Vec<_> = + try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect()); + } +} diff --git a/tests/target/configs/indent_style/block_chain.rs b/tests/target/configs/indent_style/block_chain.rs new file mode 100644 index 00000000000..23340a4aba2 --- /dev/null +++ b/tests/target/configs/indent_style/block_chain.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Block +// Chain indent + +fn main() { + let lorem = ipsum + .dolor() + .sit() + .amet() + .consectetur() + .adipiscing() + .elite(); +} diff --git a/tests/target/configs/indent_style/block_generic.rs b/tests/target/configs/indent_style/block_generic.rs new file mode 100644 index 00000000000..c4fcaaf65d1 --- /dev/null +++ b/tests/target/configs/indent_style/block_generic.rs @@ -0,0 +1,22 @@ +// rustfmt-indent_style: Block +// Generics indent + +fn lorem< + Ipsum: Eq = usize, + Dolor: Eq = usize, + Sit: Eq = usize, + Amet: Eq = usize, + Adipiscing: Eq = usize, + Consectetur: Eq = usize, + Elit: Eq = usize, +>( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + adipiscing: Adipiscing, + consectetur: Consectetur, + elit: Elit, +) -> T { + // body +} diff --git a/tests/target/configs/indent_style/block_struct_lit.rs b/tests/target/configs/indent_style/block_struct_lit.rs new file mode 100644 index 00000000000..656b562266f --- /dev/null +++ b/tests/target/configs/indent_style/block_struct_lit.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style: Block +// Struct literal-style + +fn main() { + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; +} diff --git a/tests/target/configs/indent_style/block_tab_spaces_call.rs b/tests/target/configs/indent_style/block_tab_spaces_call.rs new file mode 100644 index 00000000000..5531e61ddc8 --- /dev/null +++ b/tests/target/configs/indent_style/block_tab_spaces_call.rs @@ -0,0 +1,14 @@ +// rustfmt-indent_style: Block +// rustfmt-max_width: 80 +// rustfmt-tab_spaces: 2 + +// #1427 +fn main() { + exceptaions::config(move || { + ( + NmiConfig {}, + HardFaultConfig {}, + SysTickConfig { gpio_sbsrr }, + ) + }); +} diff --git a/tests/target/configs/indent_style/block_trailing_comma_call.rs b/tests/target/configs/indent_style/block_trailing_comma_call.rs new file mode 100644 index 00000000000..a7e8590ed97 --- /dev/null +++ b/tests/target/configs/indent_style/block_trailing_comma_call.rs @@ -0,0 +1,11 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo( + a, + oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), + ); +} diff --git a/tests/target/configs/indent_style/block_where_pred.rs b/tests/target/configs/indent_style/block_where_pred.rs new file mode 100644 index 00000000000..ad7e0b8f363 --- /dev/null +++ b/tests/target/configs/indent_style/block_where_pred.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Block +// Where predicate indent + +fn lorem() -> T +where + Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq, +{ + // body +} diff --git a/tests/target/configs/indent_style/default.rs b/tests/target/configs/indent_style/default.rs new file mode 100644 index 00000000000..a8f0902b34e --- /dev/null +++ b/tests/target/configs/indent_style/default.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Visual +// Where style + +fn lorem() -> T + where Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq +{ + // body +} diff --git a/tests/target/configs/indent_style/rfc_control.rs b/tests/target/configs/indent_style/rfc_control.rs new file mode 100644 index 00000000000..6619d8b2630 --- /dev/null +++ b/tests/target/configs/indent_style/rfc_control.rs @@ -0,0 +1,39 @@ +// rustfmt-indent_style: Block + +// #1618 +fn main() { + loop { + if foo { + if ((right_paddle_speed < 0.) && (right_paddle.position().y - paddle_size.y / 2. > 5.)) + || ((right_paddle_speed > 0.) + && (right_paddle.position().y + paddle_size.y / 2. < game_height as f32 - 5.)) + { + foo + } + if ai_timer.elapsed_time().as_microseconds() > ai_time.as_microseconds() { + if ball.position().y + ball_radius > right_paddle.position().y + paddle_size.y / 2. + { + foo + } + } + } + } +} + +fn issue1656() { + { + { + match rewrite { + Some(ref body_str) + if (!body_str.contains('\n') && body_str.len() <= arm_shape.width) + || !context.config.match_arm_blocks() + || (extend && first_line_width(body_str) <= arm_shape.width) + || is_block => + { + return None; + } + _ => {} + } + } + } +} diff --git a/tests/target/configs/indent_style/rfc_where.rs b/tests/target/configs/indent_style/rfc_where.rs new file mode 100644 index 00000000000..a7b9a4f02b3 --- /dev/null +++ b/tests/target/configs/indent_style/rfc_where.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Block +// Where style + +fn lorem() -> T +where + Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq, +{ + // body +} diff --git a/tests/target/configs/indent_style/visual_args.rs b/tests/target/configs/indent_style/visual_args.rs new file mode 100644 index 00000000000..04c2eaee3cf --- /dev/null +++ b/tests/target/configs/indent_style/visual_args.rs @@ -0,0 +1,40 @@ +// rustfmt-indent_style: Visual +// Function arguments layout + +fn lorem() {} + +fn lorem(ipsum: usize) {} + +fn lorem(ipsum: usize, + dolor: usize, + sit: usize, + amet: usize, + consectetur: usize, + adipiscing: usize, + elit: usize) { + // body +} + +// #1922 +extern "C" { + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + a: *const lapack_complex_float, + lda: lapack_int, + ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int) + -> lapack_int; + + pub fn LAPACKE_csytrs_rook_work(matrix_layout: c_int, + uplo: c_char, + n: lapack_int, + nrhs: lapack_int, + lda: lapack_int, + ipiv: *const lapack_int, + b: *mut lapack_complex_float, + ldb: lapack_int) + -> lapack_int; +} diff --git a/tests/target/configs/indent_style/visual_array.rs b/tests/target/configs/indent_style/visual_array.rs new file mode 100644 index 00000000000..1da6ff23738 --- /dev/null +++ b/tests/target/configs/indent_style/visual_array.rs @@ -0,0 +1,12 @@ +// rustfmt-indent_style: Visual +// Array layout + +fn main() { + let lorem = vec!["ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit"]; +} diff --git a/tests/target/configs/indent_style/visual_call.rs b/tests/target/configs/indent_style/visual_call.rs new file mode 100644 index 00000000000..5454c44ef96 --- /dev/null +++ b/tests/target/configs/indent_style/visual_call.rs @@ -0,0 +1,13 @@ +// rustfmt-indent_style: Visual +// Function call style + +fn main() { + lorem("lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit"); +} diff --git a/tests/target/configs/indent_style/visual_chain.rs b/tests/target/configs/indent_style/visual_chain.rs new file mode 100644 index 00000000000..569f3d8b81d --- /dev/null +++ b/tests/target/configs/indent_style/visual_chain.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Visual +// Chain indent + +fn main() { + let lorem = ipsum.dolor() + .sit() + .amet() + .consectetur() + .adipiscing() + .elite(); +} diff --git a/tests/target/configs/indent_style/visual_generics.rs b/tests/target/configs/indent_style/visual_generics.rs new file mode 100644 index 00000000000..491075a146d --- /dev/null +++ b/tests/target/configs/indent_style/visual_generics.rs @@ -0,0 +1,20 @@ +// rustfmt-indent_style: Visual +// Generics indent + +fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + adipiscing: Adipiscing, + consectetur: Consectetur, + elit: Elit) + -> T { + // body +} diff --git a/tests/target/configs/indent_style/visual_struct_lit.rs b/tests/target/configs/indent_style/visual_struct_lit.rs new file mode 100644 index 00000000000..b4effba0e8a --- /dev/null +++ b/tests/target/configs/indent_style/visual_struct_lit.rs @@ -0,0 +1,7 @@ +// rustfmt-indent_style: Visual +// Struct literal-style + +fn main() { + let lorem = Lorem { ipsum: dolor, + sit: amet, }; +} diff --git a/tests/target/configs/indent_style/visual_trailing_comma.rs b/tests/target/configs/indent_style/visual_trailing_comma.rs new file mode 100644 index 00000000000..9738d397dbf --- /dev/null +++ b/tests/target/configs/indent_style/visual_trailing_comma.rs @@ -0,0 +1,7 @@ +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); +} diff --git a/tests/target/configs/indent_style/visual_where_pred.rs b/tests/target/configs/indent_style/visual_where_pred.rs new file mode 100644 index 00000000000..45799dcd5fc --- /dev/null +++ b/tests/target/configs/indent_style/visual_where_pred.rs @@ -0,0 +1,11 @@ +// rustfmt-indent_style: Visual +// Where predicate indent + +fn lorem() -> T + where Ipsum: Eq, + Dolor: Eq, + Sit: Eq, + Amet: Eq +{ + // body +} diff --git a/tests/target/configs/match_arm_blocks/false.rs b/tests/target/configs/match_arm_blocks/false.rs new file mode 100644 index 00000000000..4d53a96a7b7 --- /dev/null +++ b/tests/target/configs/match_arm_blocks/false.rs @@ -0,0 +1,10 @@ +// rustfmt-match_arm_blocks: false +// Wrap match-arms + +fn main() { + match lorem { + true => + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), + false => println!("{}", sit), + } +} diff --git a/tests/target/configs/match_arm_blocks/true.rs b/tests/target/configs/match_arm_blocks/true.rs new file mode 100644 index 00000000000..d75ef03397a --- /dev/null +++ b/tests/target/configs/match_arm_blocks/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_arm_blocks: true +// Wrap match-arms + +fn main() { + match lorem { + true => { + foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) + } + false => println!("{}", sit), + } +} diff --git a/tests/target/configs/match_block_trailing_comma/false.rs b/tests/target/configs/match_block_trailing_comma/false.rs new file mode 100644 index 00000000000..70e02955fb0 --- /dev/null +++ b/tests/target/configs/match_block_trailing_comma/false.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: false +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + } + Lorem::Dolor => println!("dolor"), + } +} diff --git a/tests/target/configs/match_block_trailing_comma/true.rs b/tests/target/configs/match_block_trailing_comma/true.rs new file mode 100644 index 00000000000..b78b046dc1c --- /dev/null +++ b/tests/target/configs/match_block_trailing_comma/true.rs @@ -0,0 +1,11 @@ +// rustfmt-match_block_trailing_comma: true +// Match block trailing comma + +fn main() { + match lorem { + Lorem::Ipsum => { + println!("ipsum"); + }, + Lorem::Dolor => println!("dolor"), + } +} diff --git a/tests/target/configs/merge_derives/true.rs b/tests/target/configs/merge_derives/true.rs new file mode 100644 index 00000000000..4d0148b1c6e --- /dev/null +++ b/tests/target/configs/merge_derives/true.rs @@ -0,0 +1,40 @@ +// rustfmt-merge_derives: true +// Merge multiple derives to a single one. + +#[bar] +#[derive(Eq, PartialEq)] +#[foo] +#[derive(Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Foo {} + +#[derive(Eq, PartialEq, Debug)] +#[foobar] +#[derive(Copy, Clone)] +pub enum Bar {} + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum FooBar {} + +mod foo { + #[bar] + #[derive(Eq, PartialEq)] + #[foo] + #[derive(Debug)] + #[foobar] + #[derive(Copy, Clone)] + pub enum Foo {} +} + +mod bar { + #[derive(Eq, PartialEq, Debug)] + #[foobar] + #[derive(Copy, Clone)] + pub enum Bar {} +} + +mod foobar { + #[derive(Eq, PartialEq, Debug, Copy, Clone)] + pub enum FooBar {} +} diff --git a/tests/target/configs/normalize_comments/false.rs b/tests/target/configs/normalize_comments/false.rs new file mode 100644 index 00000000000..488962ed936 --- /dev/null +++ b/tests/target/configs/normalize_comments/false.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: false +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +/* sit amet: */ +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/target/configs/normalize_comments/true.rs b/tests/target/configs/normalize_comments/true.rs new file mode 100644 index 00000000000..0bdbe08ab4f --- /dev/null +++ b/tests/target/configs/normalize_comments/true.rs @@ -0,0 +1,13 @@ +// rustfmt-normalize_comments: true +// Normalize comments + +// Lorem ipsum: +fn dolor() -> usize {} + +// sit amet: +fn adipiscing() -> usize {} + +// #652 +//////////////////////////////////////////////////////////////////////////////// +// Basic slice extension methods +//////////////////////////////////////////////////////////////////////////////// diff --git a/tests/target/configs/reorder_extern_crates/false.rs b/tests/target/configs/reorder_extern_crates/false.rs new file mode 100644 index 00000000000..6bef132e5c3 --- /dev/null +++ b/tests/target/configs/reorder_extern_crates/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: false + +extern crate foo; +extern crate bar; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/tests/target/configs/reorder_extern_crates/true.rs b/tests/target/configs/reorder_extern_crates/true.rs new file mode 100644 index 00000000000..86aba38b5d1 --- /dev/null +++ b/tests/target/configs/reorder_extern_crates/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_extern_crates: true + +extern crate bar; +extern crate foo; +extern crate foobar; + +#[macro_use] +extern crate nom; +extern crate regex; +#[macro_use] +extern crate log; diff --git a/tests/target/configs/reorder_imported_names/false.rs b/tests/target/configs/reorder_imported_names/false.rs new file mode 100644 index 00000000000..91db89ceeaa --- /dev/null +++ b/tests/target/configs/reorder_imported_names/false.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: false +// Reorder imported names + +use super::{lorem, ipsum, dolor, sit}; diff --git a/tests/target/configs/reorder_imported_names/true.rs b/tests/target/configs/reorder_imported_names/true.rs new file mode 100644 index 00000000000..59f55f4718a --- /dev/null +++ b/tests/target/configs/reorder_imported_names/true.rs @@ -0,0 +1,4 @@ +// rustfmt-reorder_imported_names: true +// Reorder imported names + +use super::{dolor, ipsum, lorem, sit}; diff --git a/tests/target/configs/reorder_imports/false.rs b/tests/target/configs/reorder_imports/false.rs new file mode 100644 index 00000000000..4b85684dc01 --- /dev/null +++ b/tests/target/configs/reorder_imports/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_imports: false +// Reorder imports + +use lorem; +use ipsum; +use dolor; +use sit; diff --git a/tests/target/configs/reorder_imports/true.rs b/tests/target/configs/reorder_imports/true.rs new file mode 100644 index 00000000000..e4ff7295fd0 --- /dev/null +++ b/tests/target/configs/reorder_imports/true.rs @@ -0,0 +1,19 @@ +// rustfmt-reorder_imports: true +// Reorder imports + +use dolor; +use ipsum; +use lorem; +use sit; + +fn foo() { + use A; + use B; + use C; + + bar(); + + use D; + use E; + use F; +} diff --git a/tests/target/configs/reorder_imports_in_group/false.rs b/tests/target/configs/reorder_imports_in_group/false.rs new file mode 100644 index 00000000000..29460da50aa --- /dev/null +++ b/tests/target/configs/reorder_imports_in_group/false.rs @@ -0,0 +1,12 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: false +// Reorder imports in group + +use dolor; +/// This comment should stay with `use ipsum;` +use ipsum; +use lorem; +use sit; +use std::io; +/// This comment should stay with `use std::mem;` +use std::mem; diff --git a/tests/target/configs/reorder_imports_in_group/true.rs b/tests/target/configs/reorder_imports_in_group/true.rs new file mode 100644 index 00000000000..c5e353662b5 --- /dev/null +++ b/tests/target/configs/reorder_imports_in_group/true.rs @@ -0,0 +1,13 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imports_in_group: true +// Reorder imports in group + +use std::io; +/// This comment should stay with `use std::mem;` +use std::mem; + +use dolor; +/// This comment should stay with `use ipsum;` +use ipsum; +use lorem; +use sit; diff --git a/tests/target/configs/reorder_modules/dolor/mod.rs b/tests/target/configs/reorder_modules/dolor/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/dolor/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/false.rs b/tests/target/configs/reorder_modules/false.rs new file mode 100644 index 00000000000..56b1aa03ed7 --- /dev/null +++ b/tests/target/configs/reorder_modules/false.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: false +// Reorder modules + +mod lorem; +mod ipsum; +mod dolor; +mod sit; diff --git a/tests/target/configs/reorder_modules/ipsum/mod.rs b/tests/target/configs/reorder_modules/ipsum/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/ipsum/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/lorem/mod.rs b/tests/target/configs/reorder_modules/lorem/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/lorem/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/sit/mod.rs b/tests/target/configs/reorder_modules/sit/mod.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/configs/reorder_modules/sit/mod.rs @@ -0,0 +1 @@ + diff --git a/tests/target/configs/reorder_modules/true.rs b/tests/target/configs/reorder_modules/true.rs new file mode 100644 index 00000000000..18361e88b5f --- /dev/null +++ b/tests/target/configs/reorder_modules/true.rs @@ -0,0 +1,7 @@ +// rustfmt-reorder_modules: true +// Reorder modules + +mod dolor; +mod ipsum; +mod lorem; +mod sit; diff --git a/tests/target/configs/skip_children/true.rs b/tests/target/configs/skip_children/true.rs new file mode 100644 index 00000000000..3ea9f46fdf2 --- /dev/null +++ b/tests/target/configs/skip_children/true.rs @@ -0,0 +1,3 @@ +// rustfmt-skip_children: true + +mod foo; diff --git a/tests/target/configs/space_before_colon/true.rs b/tests/target/configs/space_before_colon/true.rs new file mode 100644 index 00000000000..e2895b5d77b --- /dev/null +++ b/tests/target/configs/space_before_colon/true.rs @@ -0,0 +1,11 @@ +// rustfmt-space_before_colon: true +// Space before colon + +fn lorem(t : T) { + let ipsum : Dolor = sit; +} + +const LOREM : Lorem = Lorem { + ipsum : dolor, + sit : amet, +}; diff --git a/tests/target/configs/spaces_around_ranges/false.rs b/tests/target/configs/spaces_around_ranges/false.rs new file mode 100644 index 00000000000..6319da98572 --- /dev/null +++ b/tests/target/configs/spaces_around_ranges/false.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: false +// Spaces around ranges + +fn main() { + let lorem = 0..10; + let ipsum = 0..=10; + + match lorem { + 1..5 => foo(), + _ => bar, + } + + match lorem { + 1..=5 => foo(), + _ => bar, + } + + match lorem { + 1...5 => foo(), + _ => bar, + } +} diff --git a/tests/target/configs/spaces_around_ranges/true.rs b/tests/target/configs/spaces_around_ranges/true.rs new file mode 100644 index 00000000000..7bfcc23c8ea --- /dev/null +++ b/tests/target/configs/spaces_around_ranges/true.rs @@ -0,0 +1,22 @@ +// rustfmt-spaces_around_ranges: true +// Spaces around ranges + +fn main() { + let lorem = 0 .. 10; + let ipsum = 0 ..= 10; + + match lorem { + 1 .. 5 => foo(), + _ => bar, + } + + match lorem { + 1 ..= 5 => foo(), + _ => bar, + } + + match lorem { + 1 ... 5 => foo(), + _ => bar, + } +} diff --git a/tests/target/configs/spaces_within_parens_and_brackets/false.rs b/tests/target/configs/spaces_within_parens_and_brackets/false.rs new file mode 100644 index 00000000000..908373ca9b0 --- /dev/null +++ b/tests/target/configs/spaces_within_parens_and_brackets/false.rs @@ -0,0 +1,7 @@ +// rustfmt-spaces_within_parens_and_brackets: false +// Spaces within parens and brackets + +fn lorem(t: T) { + let lorem = (ipsum, dolor); + let lorem: [usize; 2] = [ipsum, dolor]; +} diff --git a/tests/target/configs/spaces_within_parens_and_brackets/true.rs b/tests/target/configs/spaces_within_parens_and_brackets/true.rs new file mode 100644 index 00000000000..7aff7131506 --- /dev/null +++ b/tests/target/configs/spaces_within_parens_and_brackets/true.rs @@ -0,0 +1,145 @@ +// rustfmt-spaces_within_parens_and_brackets: true +// Spaces within parens and brackets + +fn lorem< T: Eq >( t: T ) { + let lorem = ( ipsum, dolor ); + let lorem: [ usize; 2 ] = [ ipsum, dolor ]; +} + +enum E { + A( u32 ), + B( u32, u32 ), + C( u32, u32, u32 ), + D(), +} + +struct TupleStruct0(); +struct TupleStruct1( u32 ); +struct TupleStruct2( u32, u32 ); + +fn fooEmpty() {} + +fn foo( e: E, _: u32 ) -> ( u32, u32 ) { + // Tuples + let t1 = (); + let t2 = ( 1, ); + let t3 = ( 1, 2 ); + + let ts0 = TupleStruct0(); + let ts1 = TupleStruct1( 1 ); + let ts2 = TupleStruct2( 1, 2 ); + + // Tuple pattern + let ( a, b, c ) = ( 1, 2, 3 ); + + // Expressions + let x = ( 1 + 2 ) * ( 3 ); + + // Function call + fooEmpty(); + foo( 1, 2 ); + + // Pattern matching + match e { + A( _ ) => (), + B( _, _ ) => (), + C( .. ) => (), + D => (), + } + + ( 1, 2 ) +} + +struct Foo< T > { + i: T, +} + +struct Bar< T, E > { + i: T, + e: E, +} + +struct Foo< 'a > { + i: &'a str, +} + +enum E< T > { + T( T ), +} + +enum E< T, S > { + T( T ), + S( S ), +} + +fn foo< T >( a: T ) { + foo::< u32 >( 10 ); +} + +fn foo< T, E >( a: T, b: E ) { + foo::< u32, str >( 10, "bar" ); +} + +fn foo< T: Send, E: Send >( a: T, b: E ) { + foo::< u32, str >( 10, "bar" ); + + let opt: Option< u32 >; + let res: Result< u32, String >; +} + +fn foo< 'a >( a: &'a str ) { + foo( "foo" ); +} + +fn foo< 'a, 'b >( a: &'a str, b: &'b str ) { + foo( "foo", "bar" ); +} + +impl Foo { + fn bar() { + < Foo as Foo >::bar(); + } +} + +trait MyTrait< A, D > {} +impl< A: Send, D: Send > MyTrait< A, D > for Foo {} + +fn foo() +where + for< 'a > u32: 'a, +{ +} + +fn main() { + let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; + let arr: [ i32; 500 ] = [ 0; 500 ]; + + let v = vec![ 1, 2, 3 ]; + assert_eq!( arr, [ 1, 2, 3 ] ); + + let i = arr[ 0 ]; + + let slice = &arr[ 1..2 ]; + + let line100_________________________________________________________________________ = [ 1, 2 ]; + let line101__________________________________________________________________________ = + [ 1, 2 ]; + let line102___________________________________________________________________________ = + [ 1, 2 ]; + let line103____________________________________________________________________________ = + [ 1, 2 ]; + let line104_____________________________________________________________________________ = + [ 1, 2 ]; + + let line100_____________________________________________________________________ = vec![ 1, 2 ]; + let line101______________________________________________________________________ = + vec![ 1, 2 ]; + let line102_______________________________________________________________________ = + vec![ 1, 2 ]; + let line103________________________________________________________________________ = + vec![ 1, 2 ]; + let line104_________________________________________________________________________ = + vec![ 1, 2 ]; +} + +fn f( slice: &[ i32 ] ) {} diff --git a/tests/target/configs/struct_field_align_threshold/20.rs b/tests/target/configs/struct_field_align_threshold/20.rs new file mode 100644 index 00000000000..b84afc56835 --- /dev/null +++ b/tests/target/configs/struct_field_align_threshold/20.rs @@ -0,0 +1,467 @@ +// rustfmt-struct_field_align_threshold: 20 +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false + +struct Foo { + x: u32, + yy: u32, // comment + zzz: u32, +} + +pub struct Bar { + x: u32, + yy: u32, + zzz: u32, + + xxxxxxx: u32, +} + +fn main() { + let foo = Foo { + x: 0, + yy: 1, + zzz: 2, + }; + + let bar = Bar { + x: 0, + yy: 1, + zzz: 2, + + xxxxxxx: 3, + }; +} + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct NewInt( + pub i32, + SomeType, // inline comment + T, // sup +); + +struct Qux< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy, +>( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple( + // Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +struct Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +struct Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +// Will this be a one-liner? +struct Tuple( + A, // Comment + B, +); + +pub struct State time::Timespec> { + now: F, +} + +pub struct State ()> { + now: F, +} + +pub struct State { + now: F, +} + +struct Palette { + /// A map of indices in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(T); +struct Foo(T) +where + T: Copy, + T: Eq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +); +struct Foo( + TTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU, // Bar + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU, +); + +mod m { + struct X + where + T: Sized, + { + a: T, + } +} + +struct Foo( + TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU, +); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +struct Foo {} +struct Foo {} +struct Foo { + // comment +} +struct Foo { + // trailing space -> +} +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: f(), + b: b(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a: Bar, b: f() }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S { a: 0, ..b }; +} + +fn issue201_2() { + let s = S { a: S2 { ..c }, ..b }; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo { a: 1, b: f(2) }; + Foo { + a: 1, + b: f(2), + ..g(3) + }; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { + ..base + }; + IntrinsicISizesContribution { + content_intrinsic_sizes: IntrinsicISizes { + minimum_inline_size: 0, + }, + }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { + a: bb, + c: dd, + e: ff, + }; + + Foo { + a: ddddddddddddddddddddd, + b: cccccccccccccccccccccccccccccccccccccc, + }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { + a: aaaaaaaaaa, + b: bbbbbbbb, + c: cccccccccc, + d: dddddddddd, // a comment + e: eeeeeeeee, + }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, ..base }; + Foo { + aaaaaaaaaa, + bbbbbbbb, + cccccccccc, + dddddddddd, // a comment + eeeeeeeee, + }; + Record { + ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; +} diff --git a/tests/target/configs/struct_lit_single_line/false.rs b/tests/target/configs/struct_lit_single_line/false.rs new file mode 100644 index 00000000000..e2732b5a7c9 --- /dev/null +++ b/tests/target/configs/struct_lit_single_line/false.rs @@ -0,0 +1,9 @@ +// rustfmt-struct_lit_single_line: false +// Struct literal multiline-style + +fn main() { + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; +} diff --git a/tests/target/configs/tab_spaces/2.rs b/tests/target/configs/tab_spaces/2.rs new file mode 100644 index 00000000000..85961706ea7 --- /dev/null +++ b/tests/target/configs/tab_spaces/2.rs @@ -0,0 +1,14 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { + let ipsum = dolor(); + let sit = vec![ + "amet", + "consectetur", + "adipiscing", + "elit.", + ]; +} diff --git a/tests/target/configs/tab_spaces/4.rs b/tests/target/configs/tab_spaces/4.rs new file mode 100644 index 00000000000..524a55121e4 --- /dev/null +++ b/tests/target/configs/tab_spaces/4.rs @@ -0,0 +1,14 @@ +// rustfmt-tab_spaces: 4 +// rustfmt-max_width: 30 +// rustfmt-indent_style: Block +// Tab spaces + +fn lorem() { + let ipsum = dolor(); + let sit = vec![ + "amet", + "consectetur", + "adipiscing", + "elit.", + ]; +} diff --git a/tests/target/configs/trailing_comma/always.rs b/tests/target/configs/trailing_comma/always.rs new file mode 100644 index 00000000000..951dc680912 --- /dev/null +++ b/tests/target/configs/trailing_comma/always.rs @@ -0,0 +1,14 @@ +// rustfmt-trailing_comma: Always +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit, } = amet; + let Lorem { + ipsum, + dolor, + sit, + amet, + consectetur, + adipiscing, + } = elit; +} diff --git a/tests/target/configs/trailing_comma/never.rs b/tests/target/configs/trailing_comma/never.rs new file mode 100644 index 00000000000..ae0e50f96d1 --- /dev/null +++ b/tests/target/configs/trailing_comma/never.rs @@ -0,0 +1,35 @@ +// rustfmt-trailing_comma: Never +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit } = amet; + let Lorem { + ipsum, + dolor, + sit, + amet, + consectetur, + adipiscing + } = elit; + + // #1544 + if let VrMsg::ClientReply { + request_num: reply_req_num, + value, + .. + } = msg + { + let _ = safe_assert_eq!(reply_req_num, request_num, op); + return Ok((request_num, op, value)); + } + + // #1710 + pub struct FileInput { + input: StringInput, + file_name: OsString + } + match len { + Some(len) => Ok(new(self.input, self.pos + len)), + None => Err(self) + } +} diff --git a/tests/target/configs/trailing_comma/vertical.rs b/tests/target/configs/trailing_comma/vertical.rs new file mode 100644 index 00000000000..7283cde8d06 --- /dev/null +++ b/tests/target/configs/trailing_comma/vertical.rs @@ -0,0 +1,14 @@ +// rustfmt-trailing_comma: Vertical +// Trailing comma + +fn main() { + let Lorem { ipsum, dolor, sit } = amet; + let Lorem { + ipsum, + dolor, + sit, + amet, + consectetur, + adipiscing, + } = elit; +} diff --git a/tests/target/configs/trailing_semicolon/false.rs b/tests/target/configs/trailing_semicolon/false.rs new file mode 100644 index 00000000000..9fa746e9c0f --- /dev/null +++ b/tests/target/configs/trailing_semicolon/false.rs @@ -0,0 +1,27 @@ +// rustfmt-trailing_semicolon: false + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b + } + + let x = loop { + break 5 + }; + + let x = 'c: loop { + break 'c 5 + }; +} + +fn foo() -> usize { + return 0 +} diff --git a/tests/target/configs/trailing_semicolon/true.rs b/tests/target/configs/trailing_semicolon/true.rs new file mode 100644 index 00000000000..61b6843d677 --- /dev/null +++ b/tests/target/configs/trailing_semicolon/true.rs @@ -0,0 +1,27 @@ +// rustfmt-trailing_semicolon: true + +#![feature(loop_break_value)] + +fn main() { + 'a: loop { + break 'a; + } + + let mut done = false; + 'b: while !done { + done = true; + continue 'b; + } + + let x = loop { + break 5; + }; + + let x = 'c: loop { + break 'c 5; + }; +} + +fn foo() -> usize { + return 0; +} diff --git a/tests/target/configs/type_punctuation_density/compressed.rs b/tests/target/configs/type_punctuation_density/compressed.rs new file mode 100644 index 00000000000..6571e448e44 --- /dev/null +++ b/tests/target/configs/type_punctuation_density/compressed.rs @@ -0,0 +1,41 @@ +// rustfmt-type_punctuation_density: Compressed +// Type punctuation density + +fn lorem() { + // body +} + +struct Foo +where + U: Eq+Clone, { + // body +} + +trait Foo<'a, T=usize> +where + T: 'a+Eq+Clone, +{ + type Bar: Eq+Clone; +} + +trait Foo: Eq+Clone { + // body +} + +impl Foo<'a> for Bar +where + for<'a> T: 'a+Eq+Clone, +{ + // body +} + +fn foo<'a, 'b, 'c>() +where + 'a: 'b+'c, +{ + // body +} + +fn Foo+Foo>() { + let i = 6; +} diff --git a/tests/target/configs/type_punctuation_density/wide.rs b/tests/target/configs/type_punctuation_density/wide.rs new file mode 100644 index 00000000000..01546c7b0a5 --- /dev/null +++ b/tests/target/configs/type_punctuation_density/wide.rs @@ -0,0 +1,41 @@ +// rustfmt-type_punctuation_density: Wide +// Type punctuation density + +fn lorem() { + // body +} + +struct Foo +where + U: Eq + Clone, { + // body +} + +trait Foo<'a, T = usize> +where + T: 'a + Eq + Clone, +{ + type Bar: Eq + Clone; +} + +trait Foo: Eq + Clone { + // body +} + +impl Foo<'a> for Bar +where + for<'a> T: 'a + Eq + Clone, +{ + // body +} + +fn foo<'a, 'b, 'c>() +where + 'a: 'b + 'c, +{ + // body +} + +fn Foo + Foo>() { + let i = 6; +} diff --git a/tests/target/configs/use_field_init_shorthand/false.rs b/tests/target/configs/use_field_init_shorthand/false.rs new file mode 100644 index 00000000000..dcebe0b6f1d --- /dev/null +++ b/tests/target/configs/use_field_init_shorthand/false.rs @@ -0,0 +1,15 @@ +// rustfmt-use_field_init_shorthand: false +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { x: x, y: y, z: z }; + + let b = Bar { + x: x, + y: y, + #[attr] + z: z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/target/configs/use_field_init_shorthand/true.rs b/tests/target/configs/use_field_init_shorthand/true.rs new file mode 100644 index 00000000000..ad78093ee8e --- /dev/null +++ b/tests/target/configs/use_field_init_shorthand/true.rs @@ -0,0 +1,15 @@ +// rustfmt-use_field_init_shorthand: true +// Use field initialization shorthand if possible. + +fn main() { + let a = Foo { x, y, z }; + + let b = Bar { + x, + y, + #[attr] + z, + #[rustfmt_skip] + skipped: skipped, + }; +} diff --git a/tests/target/configs/use_try_shorthand/false.rs b/tests/target/configs/use_try_shorthand/false.rs new file mode 100644 index 00000000000..de7f8b4a5e2 --- /dev/null +++ b/tests/target/configs/use_try_shorthand/false.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: false +// Use try! shorthand + +fn main() { + let lorem = try!(ipsum.map(|dolor| dolor.sit())); +} diff --git a/tests/target/configs/use_try_shorthand/true.rs b/tests/target/configs/use_try_shorthand/true.rs new file mode 100644 index 00000000000..d3aa035792c --- /dev/null +++ b/tests/target/configs/use_try_shorthand/true.rs @@ -0,0 +1,6 @@ +// rustfmt-use_try_shorthand: true +// Use try! shorthand + +fn main() { + let lorem = ipsum.map(|dolor| dolor.sit())?; +} diff --git a/tests/target/configs/where_single_line/true.rs b/tests/target/configs/where_single_line/true.rs new file mode 100644 index 00000000000..c4a7f5d3802 --- /dev/null +++ b/tests/target/configs/where_single_line/true.rs @@ -0,0 +1,28 @@ +// rustfmt-where_single_line: true +// Where style + +fn lorem_two_items() -> T +where + Ipsum: Eq, + Lorem: Eq, +{ + // body +} + +fn lorem_multi_line( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T +where + Ipsum: Eq, +{ + // body +} + +fn lorem() -> T +where Ipsum: Eq { + // body +} diff --git a/tests/target/configs/wrap_comments/false.rs b/tests/target/configs/wrap_comments/false.rs new file mode 100644 index 00000000000..48ecd88accb --- /dev/null +++ b/tests/target/configs/wrap_comments/false.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: false +// rustfmt-max_width: 50 +// rustfmt-error_on_line_overflow: false +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +} diff --git a/tests/target/configs/wrap_comments/true.rs b/tests/target/configs/wrap_comments/true.rs new file mode 100644 index 00000000000..4096fd4d89d --- /dev/null +++ b/tests/target/configs/wrap_comments/true.rs @@ -0,0 +1,20 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 +// Wrap comments + +fn main() { + // Lorem ipsum dolor sit amet, consectetur + // adipiscing elit, sed do eiusmod tempor + // incididunt ut labore et dolore magna + // aliqua. Ut enim ad minim veniam, quis + // nostrud exercitation ullamco laboris nisi + // ut aliquip ex ea commodo consequat. +} + +fn code_block() { + // ```rust + // let x = 3; + // + // println!("x = {}", x); + // ``` +} diff --git a/tests/target/control-brace-style-always-next-line.rs b/tests/target/control-brace-style-always-next-line.rs new file mode 100644 index 00000000000..054a3075ca0 --- /dev/null +++ b/tests/target/control-brace-style-always-next-line.rs @@ -0,0 +1,50 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + loop + { + (); + (); + } + + 'label: loop + // loop comment + { + (); + } + + cond = true; + while cond + { + (); + } + + 'while_label: while cond + { + // while comment + (); + } + + for obj in iter + { + for sub_obj in obj + { + 'nested_while_label: while cond + { + (); + } + } + } + + match some_var + { + // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => + { + do_stuff(); + val2 + } + }; +} diff --git a/tests/target/control-brace-style-always-same-line.rs b/tests/target/control-brace-style-always-same-line.rs new file mode 100644 index 00000000000..ae6bf4a5682 --- /dev/null +++ b/tests/target/control-brace-style-always-same-line.rs @@ -0,0 +1,42 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + loop { + (); + (); + } + + 'label: loop + // loop comment + { + (); + } + + cond = true; + while cond { + (); + } + + 'while_label: while cond { + // while comment + (); + } + + for obj in iter { + for sub_obj in obj { + 'nested_while_label: while cond { + (); + } + } + } + + match some_var { + // match comment + pattern0 => val0, + pattern1 => val1, + pattern2 | pattern3 => { + do_stuff(); + val2 + } + }; +} diff --git a/tests/target/doc.rs b/tests/target/doc.rs new file mode 100644 index 00000000000..0f9e2d21c1f --- /dev/null +++ b/tests/target/doc.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +// Part of multiple.rs + +// sadfsdfa +// sdffsdfasdf diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/tests/target/else-if-brace-style-always-next-line.rs new file mode 100644 index 00000000000..31e12cfa0d0 --- /dev/null +++ b/tests/target/else-if-brace-style-always-next-line.rs @@ -0,0 +1,53 @@ +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + if false + { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { unreachable!() } else { 0x0 }; + + if true + { + (); + } + else if false + { + (); + (); + } + else + { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } + else if false + // else-if-chain else-if comment + { + (); + (); + } + else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/tests/target/else-if-brace-style-always-same-line.rs new file mode 100644 index 00000000000..5e5ab21a0d8 --- /dev/null +++ b/tests/target/else-if-brace-style-always-same-line.rs @@ -0,0 +1,45 @@ +// rustfmt-control_brace_style: AlwaysSameLine + +fn main() { + if false { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { unreachable!() } else { 0x0 }; + + if true { + (); + } else if false { + (); + (); + } else { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } else if false + // else-if-chain else-if comment + { + (); + (); + } else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/tests/target/else-if-brace-style-closing-next-line.rs new file mode 100644 index 00000000000..c99807dc06d --- /dev/null +++ b/tests/target/else-if-brace-style-closing-next-line.rs @@ -0,0 +1,49 @@ +// rustfmt-control_brace_style: ClosingNextLine + +fn main() { + if false { + (); + (); + } + + if false + // lone if comment + { + (); + (); + } + + let a = if 0 > 1 { unreachable!() } else { 0x0 }; + + if true { + (); + } + else if false { + (); + (); + } + else { + (); + (); + (); + } + + if true + // else-if-chain if comment + { + (); + } + else if false + // else-if-chain else-if comment + { + (); + (); + } + else + // else-if-chain else comment + { + (); + (); + (); + } +} diff --git a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs new file mode 100644 index 00000000000..0b9a15e8a92 --- /dev/null +++ b/tests/target/empty-tuple-no-conversion-to-unit-struct.rs @@ -0,0 +1,12 @@ +enum TestEnum { + Arm1(), + Arm2, +} + +fn foo() { + let test = TestEnum::Arm1; + match test { + TestEnum::Arm1() => {} + TestEnum::Arm2 => {} + } +} diff --git a/tests/target/empty_file.rs b/tests/target/empty_file.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/empty_file.rs @@ -0,0 +1 @@ + diff --git a/tests/target/enum.rs b/tests/target/enum.rs new file mode 100644 index 00000000000..de88f610b6a --- /dev/null +++ b/tests/target/enum.rs @@ -0,0 +1,255 @@ +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Enums test + +#[atrr] +pub enum Test { + A, + B(u32, A /* comment */, SomeType), + /// Doc comment + C, +} + +pub enum Foo<'a, Y: Baz> +where + X: Whatever, +{ + A, +} + +enum EmtpyWithComment { + // Some comment +} + +// C-style enum +enum Bar { + A = 1, + #[someAttr(test)] + B = 2, // comment + C, +} + +enum LongVariants { + First( + LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG, // comment + VARIANT, + ), + // This is the second variant + Second, +} + +enum StructLikeVariants { + Normal(u32, String), + StructLike { + x: i32, // Test comment + // Pre-comment + #[Attr50] + y: SomeType, // Aanother Comment + }, + SL { + a: A, + }, +} + +enum X { + CreateWebGLPaintTask( + Size2D, + GLContextAttributes, + IpcSender, usize), String>>, + ), // This is a post comment +} + +pub enum EnumWithAttributes { + //This is a pre comment + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + // Pre Comment + #[rustfmt_skip] + SkippedItem(String,String,), // Post-comment + #[another_attr] + #[attr2] + ItemStruct { + x: usize, + y: usize, + }, /* Comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ + // And another + ForcedPreflight, /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ +} + +pub enum SingleTuple { + // Pre Comment AAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + Match(usize, usize, String), /* Post-comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ +} + +pub enum SingleStruct { + Match { name: String, loc: usize }, // Post-comment +} + +pub enum GenericEnum +where + I: Iterator, +{ + // Pre Comment + Left { list: I, root: T }, // Post-comment + Right { list: I, root: T }, // Post Comment +} + +enum EmtpyWithComment { + // Some comment +} + +enum TestFormatFails { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +fn nested_enum_test() { + if true { + enum TestEnum { + One( + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + usize, + ), /* AAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAAAAAA */ + Two, /* AAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + * AAAAAAAAAAAAAAAAAA */ + } + enum TestNestedFormatFail { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + } + } +} + +pub struct EmtpyWithComment { + // FIXME: Implement this struct +} + +// #1115 +pub enum Bencoding<'i> { + Str(&'i [u8]), + Int(i64), + List(Vec>), + /// A bencoded dict value. The first element the slice of bytes in the source that the dict is + /// composed of. The second is the dict, decoded into an ordered map. + // TODO make Dict "structlike" AKA name the two values. + Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), +} + +// #1261 +pub enum CoreResourceMsg { + SetCookieForUrl( + ServoUrl, + #[serde(deserialize_with = "::hyper_serde::deserialize", + serialize_with = "::hyper_serde::serialize")] + Cookie, + CookieSource, + ), +} + +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +enum Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +enum Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{ + Foo, +} + +// #1046 +pub enum Entry<'a, K: 'a, V: 'a> { + Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>), + Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>), +} + +// #2081 +pub enum ForegroundColor { + CYAN = + (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16, +} + +// #2098 +pub enum E<'a> { + V( as Iterator>::Item), +} + +// #1809 +enum State { + TryRecv { + pos: usize, + lap: u8, + closed_count: usize, + }, + Subscribe { + pos: usize, + }, + IsReady { + pos: usize, + ready: bool, + }, + Unsubscribe { + pos: usize, + lap: u8, + id_woken: usize, + }, + FinalTryRecv { + pos: usize, + id_woken: usize, + }, + TimedOut, + Disconnected, +} + +// #2190 +#[derive(Debug, Fail)] +enum AnError { + #[fail(display = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")] + UnexpectedSingleToken { token: syn::Token }, +} + +// #2193 +enum WidthOf101 { + #[fail(display = ".....................................................")] + Io(::std::io::Error), + #[fail(display = ".....................................................")] + Ioo(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(::std::io::Error), + Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ::std::io::Error, + ), +} + +// #2389 +pub enum QlError { + #[fail(display = "Parsing error: {}", 0)] + LexError(parser::lexer::LexError), + #[fail(display = "Parsing error: {:?}", 0)] + ParseError(parser::ParseError), + #[fail(display = "Validation error: {:?}", 0)] + ValidationError(Vec), + #[fail(display = "Execution error: {}", 0)] + ExecutionError(String), + // (from, to) + #[fail(display = "Translation error: from {} to {}", 0, 1)] + TranslationError(String, String), + // (kind, input, expected) + #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] + ResolveError(&'static str, String, Option), +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs new file mode 100644 index 00000000000..277990c5a60 --- /dev/null +++ b/tests/target/expr-block.rs @@ -0,0 +1,299 @@ +// rustfmt-indent_style: Block +// Test expressions with block formatting. + +fn arrays() { + []; + let empty = []; + + let foo = [a_long_name, a_very_lng_name, a_long_name]; + + let foo = [ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + ]; + + vec![ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_very_lng_name, + ]; + + [ + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_long_name, + a_very_lng_name, + a_very_lng_name, + ] +} + +fn arrays() { + let x = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, + ]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ + strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + /* comment */ 1, + ]; + + let a = WeightedChoice::new(&mut [ + Weighted { weight: x, item: 0 }, + Weighted { weight: 1, item: 1 }, + Weighted { weight: x, item: 2 }, + Weighted { weight: 1, item: 3 }, + ]); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzz, + q, + ]; + + [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] +} + +fn function_calls() { + let items = itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo(), + span.hi(), + ); + + itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo(), + |item| item.span.hi(), + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo(), + span.hi(), + ) +} + +fn macros() { + baz!( + do_not, + add, + trailing, + commas, + inside, + of, + function, + like, + macros, + even, + if_they, + are, + long + ); + + baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); + + let _ = match option { + None => baz!( + function, + like, + macro_as, + expression, + which, + is, + loooooooooooooooong + ), + Some(p) => baz!(one_item_macro_as_expression_which_is_also_loooooooooooooooong), + }; +} + +fn issue_1450() { + if selfstate + .compare_exchandsfasdsdfgsdgsdfgsdfgsdfgsdfgsdfgfsfdsage_weak( + STATE_PARKED, + STATE_UNPARKED, + Release, + Relaxed, + Release, + Relaxed, + ) + .is_ok() + { + return; + } +} + +fn foo() { + if real_total <= limit && !pre_line_comments + && !items.into_iter().any(|item| item.as_ref().is_multiline()) + { + DefinitiveListTactic::Horizontal + } +} + +fn combine_block() { + foo(Bar { + x: value, + y: value2, + }); + + foo((Bar { + x: value, + y: value2, + },)); + + foo(( + 1, + 2, + 3, + Bar { + x: value, + y: value2, + }, + )); + + foo((1, 2, 3, |x| { + let y = x + 1; + let z = y + 1; + z + })); + + let opt = Some(Struct( + long_argument_one, + long_argument_two, + long_argggggggg, + )); + + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); + + Ok(some_function( + lllllllllong_argument_one, + lllllllllong_argument_two, + lllllllllllllllllllllllllllllong_argument_three, + )); + + foo( + thing, + bar( + param2, + pparam1param1param1param1param1param1param1param1param1param1aram1, + param3, + ), + ); + + foo.map_or(|| { + Ok(SomeStruct { + f1: 0, + f2: 0, + f3: 0, + }) + }); + + match opt { + Some(x) => somefunc(anotherfunc( + long_argument_one, + long_argument_two, + long_argument_three, + )), + Some(x) => |x| { + let y = x + 1; + let z = y + 1; + z + }, + Some(x) => (1, 2, |x| { + let y = x + 1; + let z = y + 1; + z + }), + Some(x) => SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }, + None => Ok(SomeStruct { + f1: long_argument_one, + f2: long_argument_two, + f3: long_argument_three, + }), + }; + + match x { + y => func(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx), + _ => func( + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzz, + ), + } +} + +fn issue_1862() { + foo( + /* bar = */ None, + something_something, + /* baz = */ None, + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ + None, + /* com */ + this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, + ) +} + +fn issue_1878() { + let channel: &str = seq.next_element()? + .ok_or_else(|| de::Error::invalid_length(2, &self))?; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs new file mode 100644 index 00000000000..3c5d85b7d76 --- /dev/null +++ b/tests/target/expr.rs @@ -0,0 +1,397 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// Test expressions + +fn foo() -> bool { + let boxed: Box = box 5; + let referenced = &5; + + let very_long_variable_name = (a + first + simple + test); + let very_long_variable_name = + (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); + + let is_internalxxxx = + self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + + let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb + / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; + + some_ridiculously_loooooooooooooooooooooong_function( + 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), + trivial_value, + ); + (((((((((aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaa))))))))); + + { + for _ in 0..10 {} + } + + { + { + { + {} + } + } + } + + if 1 + 2 > 0 { + let result = 5; + result + } else { + 4 + }; + + if let Some(x) = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + // Nothing + } + + if let Some(x) = + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) + {} + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1111 + 2222 + {} + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} + + if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = + item.node + { + // nothing + } + + let test = if true { 5 } else { 3 }; + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + // Check subformatting + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } +} + +fn bar() { + let range = + (111111111 + 333333333333333333 + 1111 + 400000000000000000)..(2222 + 2333333333333333); + + let another_range = 5..some_func(a, b /* comment */); + + for _ in 1.. { + call_forever(); + } + + syntactically_correct( + loop { + sup('?'); + }, + if cond { 0 } else { 1 }, + ); + + let third = ..10; + let infi_range = ..; + let foo = 1..; + let bar = 5; + let nonsense = (10..0)..(0..10); + + loop { + if true { + break; + } + } + + let x = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + a, + ); +} + +fn baz() { + unsafe /* {}{}{}{{{{}} */ { + let foo = 1u32; + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + * comment */ { + } + + unsafe /* So this is a very long comment. + * Multi-line, too. + * Will it still format correctly? */ { + } + + unsafe { + // Regular unsafe block + } + + unsafe { foo() } + + unsafe { + foo(); + } + + // #2289 + let identifier_0 = unsafe { this_is_58_chars_long_and_line_is_93_chars_long_xxxxxxxxxx }; + let identifier_1 = unsafe { this_is_59_chars_long_and_line_is_94_chars_long_xxxxxxxxxxx }; + let identifier_2 = unsafe { this_is_65_chars_long_and_line_is_100_chars_long_xxxxxxxxxxxxxxxx }; + let identifier_3 = + unsafe { this_is_66_chars_long_and_line_is_101_chars_long_xxxxxxxxxxxxxxxxx }; +} + +// Test some empty blocks. +fn qux() { + {} + // FIXME this one could be done better. + { /* a block with a comment */ } + {} + { + // A block with a comment. + } +} + +fn issue227() { + { + let handler = + box DocumentProgressHandler::new(addr, DocumentProgressTask::DOMContentLoaded); + } +} + +fn issue184(source: &str) { + for c in source.chars() { + if index < 'a' { + continue; + } + } +} + +fn arrays() { + let x = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, + ]; + + let y = [/* comment */ 1, 2 /* post comment */, 3]; + + let xy = [ + strukt { + test123: value_one_two_three_four, + turbo: coolio(), + }, + // comment + 1, + ]; + + let a = WeightedChoice::new(&mut [ + Weighted { + weightweight: x, + item: 0, + }, + Weighted { + weightweight: 1, + item: 1, + }, + Weighted { + weightweight: x, + item: 2, + }, + Weighted { + weightweight: 1, + item: 3, + }, + ]); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q, + ]; + + [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] +} + +fn returns() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + && return; + + return aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +} + +fn addrof() { + &mut (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); +} + +fn casts() { + fn unpack(packed: u32) -> [u16; 2] { + [(packed >> 16) as u16, (packed >> 0) as u16] + } + + let some_trait_xxx = xxxxxxxxxxx + xxxxxxxxxxxxx as SomeTraitXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; + let slightly_longer_trait = + yyyyyyyyy + yyyyyyyyyyy as SomeTraitYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY; +} + +fn indices() { + let x = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) + [x + y + z]; + let y = (aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc) + [xxxxx + yyyyy + zzzzz]; + let z = xxxxxxxxxx + .x() + .y() + .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz()[aaaaa]; + let z = xxxxxxxxxx + .x() + .y() + .zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz() + [aaaaa]; +} + +fn repeats() { + let x = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; + x + y + z]; + let y = [aaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccc; + xxxxx + yyyyy + zzzzz]; +} + +fn blocks() { + if 1 + 1 == 2 { + println!("yay arithmetix!"); + }; +} + +fn issue767() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} + +fn ranges() { + let x = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let y = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa..=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let z = ..=x; + + // #1766 + let x = [0. ..10.0]; + let x = [0. ..=10.0]; + + a..=b + + // the expr below won't compile because inclusive ranges need a defined end + // let a = 0 ..= ; +} + +fn if_else() { + let exact = diff / (if size == 0 { 1 } else { size }); + + let cx = tp1.x + any * radius * if anticlockwise { 1.0 } else { -1.0 }; +} + +fn complex_if_else() { + if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxx { + yo(); + } else if let Some(x) = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + { + ha(); + } else if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxx + { + yo(); + } +} + +fn issue1106() { + { + if let hir::ItemEnum(ref enum_def, ref generics) = + self.ast_map.expect_item(enum_node_id).node + {} + } + + for entry in WalkDir::new(path) + .into_iter() + .filter_entry(|entry| exclusions.filter_entry(entry)) + {} +} + +fn issue1570() { + a_very_long_function_name({ some_func(1, { 1 }) }) +} + +fn issue1714() { + v = &mut { v }[mid..]; + let (left, right) = { v }.split_at_mut(mid); +} + +// Multi-lined index should be put on the next line if it fits in one line. +fn issue1749() { + { + { + { + if self.shape[(r as f32 + self.x_offset) as usize] + [(c as f32 + self.y_offset) as usize] != 0 + { + // hello + } + } + } + } +} + +// #1172 +fn newlines_between_list_like_expr() { + foo( + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ); + + vec![ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, + ]; + + match x { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + | yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + | zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz => foo(a, b, c), + _ => bar(), + }; +} + +fn issue2178() { + Ok(result + .iter() + .map(|item| ls_util::rls_to_location(item)) + .collect()) +} diff --git a/tests/target/extern.rs b/tests/target/extern.rs new file mode 100644 index 00000000000..b0aa51127d5 --- /dev/null +++ b/tests/target/extern.rs @@ -0,0 +1,73 @@ +// rustfmt-normalize_comments: true + +extern crate foo; +extern crate foo as bar; + +extern crate chrono; +extern crate dotenv; +extern crate futures; + +extern crate bar; +extern crate foo; + +// #2315 +extern crate proc_macro; +extern crate proc_macro2; + +extern "C" { + fn c_func(x: *mut *mut libc::c_void); + + fn c_func( + x: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX, + y: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY, + ); + + #[test123] + fn foo() -> uint64_t; + + pub fn bar(); +} + +extern "C" { + fn DMR_GetDevice( + pHDev: *mut HDEV, + searchMode: DeviceSearchMode, + pSearchString: *const c_char, + devNr: c_uint, + wildcard: c_char, + ) -> TDMR_ERROR; + + fn quux() -> (); // Post comment + + pub type Foo; + + type Bar; +} + +extern "Rust" { + static ext: u32; + // Some comment. + pub static mut var: SomeType; +} + +extern "C" { + fn syscall( + number: libc::c_long, // comment 1 + // comm 2 + ... // sup? + ) -> libc::c_long; + + fn foo(x: *const c_char, ...) -> libc::c_long; +} + +extern "C" { + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE, + ) -> *mut FILE; +} + +extern "C" {} diff --git a/tests/target/extern_not_explicit.rs b/tests/target/extern_not_explicit.rs new file mode 100644 index 00000000000..b55b64d05b3 --- /dev/null +++ b/tests/target/extern_not_explicit.rs @@ -0,0 +1,18 @@ +// rustfmt-force_explicit_abi: false + +extern { + fn some_fn() -> (); +} + +extern fn sup() {} + +type funky_func = extern fn( + unsafe extern "rust-call" fn( + *const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal, + ) -> u8, +); diff --git a/tests/target/file-lines-1.rs b/tests/target/file-lines-1.rs new file mode 100644 index 00000000000..2601ca9fc94 --- /dev/null +++ b/tests/target/file-lines-1.rs @@ -0,0 +1,29 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-1.rs","range":[4,8]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + }.method_call() + .method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-2.rs b/tests/target/file-lines-2.rs new file mode 100644 index 00000000000..bc25698c2ed --- /dev/null +++ b/tests/target/file-lines-2.rs @@ -0,0 +1,24 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-2.rs","range":[10,15]}] + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-3.rs b/tests/target/file-lines-3.rs new file mode 100644 index 00000000000..fe465750ae1 --- /dev/null +++ b/tests/target/file-lines-3.rs @@ -0,0 +1,25 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-3.rs","range":[5,9]},{"file":"tests/source/file-lines-3.rs","range":[11,16]}] +// rustfmt-error_on_line_overflow: false + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + }.method_call() + .method_call(); + + let y = if cond { val1 } else { val2 }.method_call(); + + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-4.rs b/tests/target/file-lines-4.rs new file mode 100644 index 00000000000..83928bf6fec --- /dev/null +++ b/tests/target/file-lines-4.rs @@ -0,0 +1,30 @@ +// rustfmt-file_lines: [] +// (Test that nothing is formatted if an empty array is specified.) + +fn floaters() { + let x = Foo { + field1: val1, + field2: val2, + } + .method_call().method_call(); + + let y = if cond { + val1 + } else { + val2 + } + .method_call(); + // aaaaaaaaaaaaa + { + match x { + PushParam => { + // comment + stack.push(mparams[match cur.to_digit(10) { + Some(d) => d as usize - 1, + None => return Err("bad param number".to_owned()), + }] + .clone()); + } + } + } +} diff --git a/tests/target/file-lines-5.rs b/tests/target/file-lines-5.rs new file mode 100644 index 00000000000..3966dc06303 --- /dev/null +++ b/tests/target/file-lines-5.rs @@ -0,0 +1,17 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-5.rs","range":[3,5]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + fn baz() { + let j = 15; + } +} diff --git a/tests/target/file-lines-6.rs b/tests/target/file-lines-6.rs new file mode 100644 index 00000000000..8a092df869a --- /dev/null +++ b/tests/target/file-lines-6.rs @@ -0,0 +1,18 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-6.rs","range":[9,10]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + + fn baz() { +/// + let j = 15; + } +} diff --git a/tests/target/file-lines-item.rs b/tests/target/file-lines-item.rs new file mode 100644 index 00000000000..e155e75f34c --- /dev/null +++ b/tests/target/file-lines-item.rs @@ -0,0 +1,22 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-item.rs","range":[7,9]}] +// rustfmt-reorder_imports: true + +use foo::{c, b, a}; +use bar; + +fn foo() { + bar(); +} + +impl Drop for Context { + fn drop(&mut self) { + } +} + +impl Bar for Baz { + fn foo() { + bar( + baz, // Who knows? + ) + } +} diff --git a/tests/target/fn-args-with-last-line-comment.rs b/tests/target/fn-args-with-last-line-comment.rs new file mode 100644 index 00000000000..27e0e09653e --- /dev/null +++ b/tests/target/fn-args-with-last-line-comment.rs @@ -0,0 +1,24 @@ +// #1587 +pub trait X { + fn a(&self) -> &'static str; + fn bcd( + &self, + c: &str, // comment on this arg + d: u16, // comment on this arg + e: &Vec, // comment on this arg + ) -> Box; +} + +// #1595 +fn foo( + arg1: LongTypeName, + arg2: LongTypeName, + arg3: LongTypeName, + arg4: LongTypeName, + arg5: LongTypeName, + arg6: LongTypeName, + arg7: LongTypeName, + //arg8: LongTypeName, +) { + // do stuff +} diff --git a/tests/target/fn-custom-2.rs b/tests/target/fn-custom-2.rs new file mode 100644 index 00000000000..c2b3580c668 --- /dev/null +++ b/tests/target/fn-custom-2.rs @@ -0,0 +1,78 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + foo(); +} + +fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, +>( + a: Aaaaaaaaaaaaaaa, +) { + bar(); +} + +fn baz() +where + X: TTTTTTTT, +{ + baz(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +impl Foo { + fn foo( + self, + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, + ) { + foo(); + } + + fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, + >( + a: Aaaaaaaaaaaaaaa, + ) { + bar(); + } + + fn baz() + where + X: TTTTTTTT, + { + baz(); + } +} + +struct Foo< + TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUU, + VVVVVVVVVVVVVVVVVVVVVVVVVVV, + WWWWWWWWWWWWWWWWWWWWWWWW, +> { + foo: Foo, +} diff --git a/tests/target/fn-custom-3.rs b/tests/target/fn-custom-3.rs new file mode 100644 index 00000000000..baa1e39231b --- /dev/null +++ b/tests/target/fn-custom-3.rs @@ -0,0 +1,72 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn foo( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + foo(); +} + +fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, +>( + a: Aaaaaaaaaaaaaaa, +) { + bar(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +impl Foo { + fn foo( + self, + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, + ) { + foo(); + } + + fn bar< + 'a: 'bbbbbbbbbbbbbbbbbbbbbbbbbbb, + TTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUU: WWWWWWWWWWWWWWWWWWWWWWWW, + >( + a: Aaaaaaaaaaaaaaa, + ) { + bar(); + } +} + +struct Foo< + TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUU, + VVVVVVVVVVVVVVVVVVVVVVVVVVV, + WWWWWWWWWWWWWWWWWWWWWWWW, +> { + foo: Foo, +} diff --git a/tests/target/fn-custom-4.rs b/tests/target/fn-custom-4.rs new file mode 100644 index 00000000000..0a223ef5fac --- /dev/null +++ b/tests/target/fn-custom-4.rs @@ -0,0 +1,27 @@ +// rustfmt-indent_style: Block +// Test different indents. + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +fn qux() +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} + +fn qux(a: Aaaaaaaaaaaaaaaaa) +where + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, + X: TTTTTTTTTTTTTTTTTTTTTTTTTTTT, +{ + baz(); +} diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs new file mode 100644 index 00000000000..720d4288c41 --- /dev/null +++ b/tests/target/fn-custom-6.rs @@ -0,0 +1,72 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) where + T: UUUUUUUUUUU, { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String +where + T: UUUUUUUUUUU, { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} +} diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs new file mode 100644 index 00000000000..ec113c30d53 --- /dev/null +++ b/tests/target/fn-custom-7.rs @@ -0,0 +1,41 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block +// rustfmt-fn_args_density: Vertical +// rustfmt-brace_style: AlwaysNextLine + +// Case with only one variable. +fn foo(a: u8) -> u8 +{ + bar() +} + +// Case with 2 variables and some pre-comments. +fn foo( + a: u8, // Comment 1 + b: u8, // Comment 2 +) -> u8 +{ + bar() +} + +// Case with 2 variables and some post-comments. +fn foo( + // Comment 1 + a: u8, + // Comment 2 + b: u8, +) -> u8 +{ + bar() +} + +trait Test +{ + fn foo(a: u8) + { + } + + fn bar(a: u8) -> String + { + } +} diff --git a/tests/target/fn-custom-8.rs b/tests/target/fn-custom-8.rs new file mode 100644 index 00000000000..290557b979d --- /dev/null +++ b/tests/target/fn-custom-8.rs @@ -0,0 +1,78 @@ +// rustfmt-indent_style: Block +// rustfmt-brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) where + T: UUUUUUUUUUU, { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String +where + T: UUUUUUUUUUU, { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String +where + T: UUUUUUUUUUU, { + bar(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar(a: u8) -> String {} + + fn bar(a: u8) -> String + where + Foo: foooo, + Bar: barrr, { + } +} diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs new file mode 100644 index 00000000000..bf87553dedc --- /dev/null +++ b/tests/target/fn-custom.rs @@ -0,0 +1,19 @@ +// rustfmt-fn_args_density: Compressed +// Test some of the ways function signatures can be customised. + +// Test compressed layout of args. +fn foo( + a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + foo(); +} + +impl Foo { + fn foo( + self, a: Aaaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbbbb, c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, e: Eeeeeeeeeeeeeeeeeee, + ) { + foo(); + } +} diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs new file mode 100644 index 00000000000..4e6e6493835 --- /dev/null +++ b/tests/target/fn-simple.rs @@ -0,0 +1,107 @@ +// rustfmt-normalize_comments: true + +fn simple( + // pre-comment on a function!? + i: i32, // yes, it's possible! + response: NoWay, // hose +) { + fn op( + x: Typ, + key: &[u8], + upd: Box< + Fn(Option<&memcache::Item>) + -> (memcache::Status, Result>), + >, + ) -> MapResult { + } + + "cool" +} + +fn weird_comment( + // /*/ double level */ comment + x: Hello, // /*/* triple, even */*/ + // Does this work? + y: World, +) { + simple(/* does this preserve comments now? */ 42, NoWay) +} + +fn generic(arg: T) -> &SomeType +where + T: Fn( + // First arg + A, + // Second argument + B, + C, + D, + // pre comment + E, // last comment + ) -> &SomeType, +{ + arg(a, b, c, d, e) +} + +fn foo() -> ! {} + +pub fn http_fetch_async( + listener: Box, + script_chan: Box, +) { +} + +fn some_func>(val: T) {} + +fn zzzzzzzzzzzzzzzzzzzz( + selff: Type, + mut handle: node::Handle>, Type, NodeType>, +) -> SearchStack<'a, K, V, Type, NodeType> { +} + +unsafe fn generic_call( + cx: *mut JSContext, + argc: libc::c_uint, + vp: *mut JSVal, + is_lenient: bool, + call: unsafe extern "C" fn( + *const JSJitInfo, + *mut JSContext, + HandleObject, + *mut libc::c_void, + u32, + *mut JSVal, + ) -> u8, +) { + let f: fn(_, _) -> _ = panic!(); +} + +pub fn start_export_thread( + database: &Database, + crypto_scheme: &C, + block_size: usize, + source_path: &Path, +) -> BonzoResult> { +} + +pub fn waltz(cwd: &Path) -> CliAssert { + { + { + formatted_comment = + rewrite_comment(comment, block_style, width, offset, formatting_fig); + } + } +} + +// #2003 +mod foo { + fn __bindgen_test_layout_i_open0_c_open1_char_a_open2_char_close2_close1_close0_instantiation() + { + foo(); + } +} + +// #2082 +pub(crate) fn init() {} + +crate fn init() {} diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs new file mode 100644 index 00000000000..3617506d89a --- /dev/null +++ b/tests/target/fn-single-line.rs @@ -0,0 +1,70 @@ +// rustfmt-fn_single_line: true +// Test single-line functions. + +fn foo_expr() { 1 } + +fn foo_stmt() { foo(); } + +fn foo_decl_local() { let z = 5; } + +fn foo_decl_item(x: &mut i32) { x = 3; } + +fn empty() {} + +fn foo_return() -> String { "yay" } + +fn foo_where() -> T +where + T: Sync, +{ + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space() { 1 } + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) {} +} + +trait CoolerTypes { + fn dummy(&self) {} +} + +fn Foo() +where + T: Bar, +{ +} diff --git a/tests/target/fn-ty.rs b/tests/target/fn-ty.rs new file mode 100644 index 00000000000..7d48f3b32db --- /dev/null +++ b/tests/target/fn-ty.rs @@ -0,0 +1,14 @@ +fn f( + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a, + xxxxxxxxxxxxxxxxxx: fn() -> a, + xxxxxxxxxxxxxxxxxx: fn(a, b, b), + xxxxxxxxxxxxxxxxxx: fn(), + xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !, + xxxxxxxxxxxxxxxxxx: fn() -> !, +) where + F1: Fn(a, b, b) -> a, + F2: Fn(a, b, b), + F3: Fn(), + F4: Fn() -> u32, +{ +} diff --git a/tests/target/fn.rs b/tests/target/fn.rs new file mode 100644 index 00000000000..b78a8b5b21e --- /dev/null +++ b/tests/target/fn.rs @@ -0,0 +1,122 @@ +// Tests different fns + +fn foo(a: AAAA, b: BBB, c: CCC) -> RetType {} + +fn foo(a: AAAA, b: BBB /* some, weird, inline comment */, c: CCC) -> RetType +where + T: Blah, +{ +} + +fn foo(a: AAA /* (comment) */) +where + T: Blah, +{ +} + +fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +) -> RetType +where + T: Blah, +{ + +} + +fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +) -> RetType +where + T: Blah, + U: dsfasdfasdfasd, +{ + +} + +fn foo B /* paren inside generics */>() {} + +impl Foo { + fn with_no_errors(&mut self, f: F) -> T + where + F: FnOnce(&mut Resolver) -> T, + { + } + + fn foo(mut self, mut bar: u32) {} + + fn bar(self, mut bazz: u32) {} +} + +pub fn render< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write, +>( + g: &'a G, + w: &mut W, +) -> io::Result<()> { + render_opts(g, w, &[]) +} + +const fn foo() { + x; +} + +pub const fn foo() { + x; +} + +impl Foo { + const fn foo() { + x; + } +} + +fn homura>(_: T) {} + +fn issue377() -> (Box, Box) {} + +fn main() { + let _ = function(move || 5); + let _ = move || 42; + let _ = || unsafe { abort() }; +} + +// With inner attributes. +fn inner() { + #![inline] + x +} + +#[cfg_attr(rustfmt, rustfmt_skip)] +fn foo(a: i32) -> i32 { + // comment + if a > 0 { 1 } else { 2 } +} + +fn ______________________baz( + a: i32, +) -> *mut ::std::option::Option< + extern "C" fn(arg1: i32, _____________________a: i32, arg3: i32) -> (), +> { +} + +pub fn check_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), +) { +} + +pub fn check_path<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: &hir::Path, + id: ast::NodeId, + cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option), +) { +} diff --git a/tests/target/fn_args_density-vertical.rs b/tests/target/fn_args_density-vertical.rs new file mode 100644 index 00000000000..477a48cc35f --- /dev/null +++ b/tests/target/fn_args_density-vertical.rs @@ -0,0 +1,39 @@ +// rustfmt-fn_args_density: Vertical + +// Empty list should stay on one line. +fn do_bar() -> u8 { + bar() +} + +// A single argument should stay on the same line. +fn do_bar(a: u8) -> u8 { + bar() +} + +// Multiple arguments should each get their own line. +fn do_bar( + a: u8, + mut b: u8, + c: &u8, + d: &mut u8, + closure: &Fn(i32) -> i32, +) -> i32 { + // This feature should not affect closures. + let bar = |x: i32, y: i32| -> i32 { x + y }; + bar(a, b) +} + +// If the first argument doesn't fit on the same line with the function name, +// the whole list should probably be pushed to the next line with hanging +// indent. That's not what happens though, so check current behaviour instead. +// In any case, it should maintain single argument per line. +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, + c: u8, + d: u8, +) { + this(); + that(); + the_other_thing(); +} diff --git a/tests/target/fn_args_indent-block.rs b/tests/target/fn_args_indent-block.rs new file mode 100644 index 00000000000..04c18816d0b --- /dev/null +++ b/tests/target/fn_args_indent-block.rs @@ -0,0 +1,144 @@ +// rustfmt-normalize_comments: true +// rustfmt-indent_style: Block + +fn foo() { + foo(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String { + bar(); +} + +fn foo(a: u8 /* Comment 1 */, b: u8 /* Comment 2 */) -> u8 { + bar() +} + +fn foo( + a: u8, // Comment 1 + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, // Comment 2 +) -> u8 { + bar() +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, +) -> String +where + X: Fooooo, + Y: Baaar, +{ + bar(); +} + +fn foo() -> T { + foo(); +} + +fn foo() -> T +where + X: Foooo, + Y: Baaar, +{ + foo(); +} + +fn foo() +where + X: Foooo, +{ +} + +fn foo() +where + X: Foooo, + Y: Baaar, +{ +} + +fn foo() -> ( + Loooooooooooooooooooooong, + Reeeeeeeeeeeeeeeeeeeeeeeeturn, + iiiiiiiiis, + Looooooooooooooooong, +) { + foo(); +} + +fn foo() { + foo(); +} + +fn foo< + L: Loooooooooooooooooooooong, + G: Geeeeeeeeeeeneric, + I: iiiiiiiiis, + L: Looooooooooooooooong, +>() { + foo(); +} + +fn foo() { + foo(); +} + +trait Test { + fn foo(a: u8) {} + + fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee, + ) -> String { + } +} + +fn foo( + a: Aaaaaaaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, +) { + foo(); +} + +fn foo() -> ( + Looooooooooooooooooooooooooong, + Reeeeeeeeeeeeeeeeeeeeeeeeeeeeeturn, + iiiiiiiiiiiiiis, + Loooooooooooooooooooooong, +) { + foo(); +} diff --git a/tests/target/fn_once.rs b/tests/target/fn_once.rs new file mode 100644 index 00000000000..42b8f98e78a --- /dev/null +++ b/tests/target/fn_once.rs @@ -0,0 +1,8 @@ +struct Add(usize); + +impl FnOnce<(usize,)> for Add { + type Output = Add; + extern "rust-call" fn call_once(self, to: (usize,)) -> Add { + Add(self.0 + to.0) + } +} diff --git a/tests/target/hard-tabs.rs b/tests/target/hard-tabs.rs new file mode 100644 index 00000000000..90be4d6b367 --- /dev/null +++ b/tests/target/hard-tabs.rs @@ -0,0 +1,99 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-hard_tabs: true +// rustfmt-error_on_line_overflow: false + +fn main() { + let x = Bar; + + let y = Foo { a: x }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + fn foo(a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32, a: i32) { + } + + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + + if let ( + some_very_large, + tuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuple, + ) = 1 + 2 + 3 + {} + + if cond() { + something(); + } else if different_cond() { + something_else(); + } else { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } + + unsafe /* very looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong + * comment */ { + } + + unsafe /* So this is a very long comment. + * Multi-line, too. + * Will it still format correctly? */ { + } + + let chain = funktion_kall() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab() + .go_to_next_line_with_tab(); + + let z = [ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + yyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzz, + q, + ]; + + fn generic(arg: T) -> &SomeType + where + T: Fn( + // First arg + A, + // Second argument + B, + C, + D, + // pre comment + E, // last comment + ) -> &SomeType, + { + arg(a, b, c, d, e) + } + + loong_func().quux(move || if true { 1 } else { 2 }); + + fffffffffffffffffffffffffffffffffff(a, { + SCRIPT_TASK_ROOT.with(|root| { + *root.borrow_mut() = Some(&script_task); + }); + }); + a.b.c.d(); + + x().y(|| match cond() { + true => (), + false => (), + }); +} + +// #2296 +impl Foo { + // a comment + // on multiple lines + fn foo() { + // another comment + // on multiple lines + let x = true; + } +} diff --git a/tests/target/hello.rs b/tests/target/hello.rs new file mode 100644 index 00000000000..d9f90b0b5e8 --- /dev/null +++ b/tests/target/hello.rs @@ -0,0 +1,8 @@ +// rustfmt-config: small_tabs.toml +// rustfmt-target: hello.rs + +// Smoke test - hello world. + +fn main() { + println!("Hello world!"); +} diff --git a/tests/target/immovable_generators.rs b/tests/target/immovable_generators.rs new file mode 100644 index 00000000000..0bf7a2d91ba --- /dev/null +++ b/tests/target/immovable_generators.rs @@ -0,0 +1,7 @@ +#![feature(generators)] + +unsafe fn foo() { + let mut ga = static || { + yield 1; + }; +} diff --git a/tests/target/impl.rs b/tests/target/impl.rs new file mode 100644 index 00000000000..5895c74bcc9 --- /dev/null +++ b/tests/target/impl.rs @@ -0,0 +1,43 @@ +// Test impls + +impl JSTraceable for SmallVec<[T; 1]> {} + +impl>> Handle { + // Keep this. +} + +impl Test +where + V: Clone, // This comment is NOT removed by formating! +{ + pub fn new(value: V) -> Self { + Test { + cloned_value: value.clone(), + value, + } + } +} + +impl X /* comment */ {} +impl Y // comment +{ +} + +impl Foo for T +// comment1 +where + // comment2 + // blah + T: Clone, +{ +} + +// #1823 +default impl Trait for X {} +default unsafe impl Trait for Y {} +pub default unsafe impl Trait for Z {} + +// #2212 +impl ConstWithDefault { + default const CAN_RECONSTRUCT_QUERY_KEY: bool = false; +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs new file mode 100644 index 00000000000..91172b39fe5 --- /dev/null +++ b/tests/target/impls.rs @@ -0,0 +1,219 @@ +// rustfmt-normalize_comments: true +impl Foo for Bar { + fn foo() { + "hi" + } +} + +pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; + // Comment 1 + fn foo() { + "hi" + } + // Comment 2 + fn foo() { + "hi" + } + // Comment 3 +} + +pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> +where + X: Foo<'a, Z>, +{ + fn foo() { + "hi" + } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> +where + X: Fooooooooooooooooooooooooooooo<'a, Z>, +{ + fn foo() { + "hi" + } +} + +impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> +where + X: Foooooooooooooooooooooooooooo<'a, Z>, +{ + fn foo() { + "hi" + } +} + +impl Foo for Bar +where + T: Baz, +{ +} + +impl Foo for Bar +where + T: Baz, +{ + // Comment +} + +impl Foo { + fn foo() {} +} + +impl Boo { + // BOO + fn boo() {} + // FOO +} + +mod a { + impl Foo { + // Hello! + fn foo() {} + } +} + +mod b { + mod a { + impl Foo { + fn foo() {} + } + } +} + +impl Foo { + add_fun!(); +} + +impl Blah { + fn boop() {} + add_fun!(); +} + +impl X { + fn do_parse(mut self: X) {} +} + +impl Y5000 { + fn bar(self: X<'a, 'b>, y: Y) {} + + fn bad(&self, (x, y): CoorT) {} + + fn turbo_bad(self: X<'a, 'b>, (x, y): CoorT) {} +} + +pub impl Foo for Bar +where + T: Foo, +{ + fn foo() { + "hi" + } +} + +pub impl Foo for Bar +where + T: Foo, + Z: Baz, +{ +} + +mod m { + impl PartialEq for S + where + T: PartialEq, + { + fn eq(&self, other: &Self) { + true + } + } + + impl PartialEq for S + where + T: PartialEq, + { + } +} + +impl + Handle, HandleType> +{ +} + +impl PartialEq + for Handle, HandleType> +{ +} + +mod x { + impl Foo + where + A: 'static, + B: 'static, + C: 'static, + D: 'static, + { + } +} + +impl + Issue1249 +{ + // Creates a new flow constructor. + fn foo() {} +} + +// #1600 +impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { + fn drop() {} +} + +// #1168 +pub trait Number + : Copy + + Eq + + Not + + Shl + + Shr + + BitAnd + + BitOr + + BitAndAssign + + BitOrAssign { + // test + fn zero() -> Self; +} + +// #1642 +pub trait SomeTrait + : Clone + + Eq + + PartialEq + + Ord + + PartialOrd + + Default + + Hash + + Debug + + Display + + Write + + Read + + FromStr { + // comment +} + +// #1995 +impl Foo { + fn f( + S { + aaaaaaaaaa: aaaaaaaaaa, + bbbbbbbbbb: bbbbbbbbbb, + cccccccccc: cccccccccc, + }: S, + ) -> u32 { + 1 + } +} diff --git a/tests/target/import-fencepost-length.rs b/tests/target/import-fencepost-length.rs new file mode 100644 index 00000000000..e4f885c09b1 --- /dev/null +++ b/tests/target/import-fencepost-length.rs @@ -0,0 +1,4 @@ +use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; +use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; +use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, + ddddddddd}; diff --git a/tests/target/imports-reorder-lines-and-items.rs b/tests/target/imports-reorder-lines-and-items.rs new file mode 100644 index 00000000000..f395710b186 --- /dev/null +++ b/tests/target/imports-reorder-lines-and-items.rs @@ -0,0 +1,10 @@ +// rustfmt-reorder_imports: true +// rustfmt-reorder_imported_names: true + +use std::cmp::{a, b, c, d}; +use std::ddd::{a, b, c as g, d as p}; +use std::ddd::aaa; +// This comment should stay with `use std::ddd:bbb;` +use std::ddd::bbb; +/// This comment should stay with `use std::str;` +use std::str; diff --git a/tests/target/imports-reorder-lines.rs b/tests/target/imports-reorder-lines.rs new file mode 100644 index 00000000000..3695d6b4913 --- /dev/null +++ b/tests/target/imports-reorder-lines.rs @@ -0,0 +1,33 @@ +// rustfmt-reorder_imports: true + +use std::cmp::{a, b, c, d}; +use std::cmp::{b, e, f, g}; +// This comment should stay with `use std::ddd;` +use std::ddd; +use std::ddd::aaa; +use std::ddd::bbb; +use std::str; + +mod test {} + +use aaa; +use aaa::*; +use aaa::bbb; + +mod test {} +// If item names are equal, order by rename + +use test::{a as aa, c}; +use test::{a as bb, b}; + +mod test {} +// If item names are equal, order by rename - no rename comes before a rename + +use test::{a, c}; +use test::{a as bb, b}; + +mod test {} +// `self` always comes first + +use test::{self as bb, b}; +use test::{a as aa, c}; diff --git a/tests/target/imports-reorder.rs b/tests/target/imports-reorder.rs new file mode 100644 index 00000000000..fbb56e3aa0c --- /dev/null +++ b/tests/target/imports-reorder.rs @@ -0,0 +1,6 @@ +// rustfmt-normalize_comments: true +// rustfmt-reorder_imported_names: true + +use path::{self /* self */, /* A */ A, B /* B */, C}; + +use {aa, ab, ac, b, Z}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs new file mode 100644 index 00000000000..2b825526199 --- /dev/null +++ b/tests/target/imports.rs @@ -0,0 +1,88 @@ +// rustfmt-normalize_comments: true +// rustfmt-error_on_line_overflow: false + +// Imports. + +// Long import. +use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; +use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; + +use list::{// Another item + AnotherItem, // Another Comment + // Last Item + LastItem, + // Some item + SomeItem /* Comment */}; + +use test::{/* A */ self /* B */, Other /* C */}; + +use syntax; +use {Bar /* comment */, /* Pre-comment! */ Foo}; +use Foo::{Bar, Baz}; +pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; + +use self; +use std::io; +use std::io; + +mod Foo { + pub use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; + + mod Foo2 { + pub use syntax::ast::{self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, + ItemStatic}; + } +} + +fn test() { + use Baz::*; + use Qux; +} + +// Simple imports +use foo::bar::baz; +use bar::quux as kaas; +use foo; + +// With aliases. +use foo::{self as bar, baz}; +use foo as bar; +use foo::qux as bar; +use foo::{baz, qux as bar}; + +// With absolute paths +use foo; +use foo::Bar; +use foo::{Bar, Baz}; +use Foo; +use {Bar, Baz}; + +// Root globs +use ::*; +use ::*; + +// spaces used to cause glob imports to disappear (#1356) +use super::*; +use foo::issue_1356::*; + +// We shouldn't remove imports which have attributes attached (#1858) +#[cfg(unix)] +use self::unix::{}; + +// nested imports +use foo::{a, b, boo, c, + bar::{baz, qux, xxxxxxxxxxx, yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, + foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}}}; + +use fooo::{bar, x, y, z, + baar::foobar::{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz}, + bar::*}; + +// nested imports with a single sub-tree. +use a::b::c::*; +use a::b::c::d; +use a::b::c::{xxx, yyy, zzz}; diff --git a/tests/target/indented-impl.rs b/tests/target/indented-impl.rs new file mode 100644 index 00000000000..eff579dddac --- /dev/null +++ b/tests/target/indented-impl.rs @@ -0,0 +1,13 @@ +// rustfmt-brace_style: AlwaysNextLine +mod x +{ + struct X(i8); + + impl Y for X + { + fn y(self) -> () + { + println!("ok"); + } + } +} diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs new file mode 100644 index 00000000000..ba1029d4e61 --- /dev/null +++ b/tests/target/issue-1021.rs @@ -0,0 +1,22 @@ +// rustfmt-normalize_comments: true +fn main() { + match x { + S(true, .., true) => (), + S(true, ..) => (), + S(.., true) => (), + S(..) => (), + S(_) => (), + S(/* .. */ ..) => (), + S(/* .. */ .., true) => (), + } + + match y { + (true, .., true) => (), + (true, ..) => (), + (.., true) => (), + (..) => (), + (_,) => (), + (/* .. */ ..) => (), + (/* .. */ .., true) => (), + } +} diff --git a/tests/target/issue-1049.rs b/tests/target/issue-1049.rs new file mode 100644 index 00000000000..c788519ca9a --- /dev/null +++ b/tests/target/issue-1049.rs @@ -0,0 +1,29 @@ +// Test overlong function signature +pub unsafe fn reborrow_mut( + &mut X: Abcde, +) -> Handle, HandleType> { +} + +pub fn merge( + mut X: Abcdef, +) -> Handle, K, V, marker::Internal>, marker::Edge> { +} + +impl Handle { + pub fn merge( + a: Abcd, + ) -> Handle, K, V, marker::Internal>, marker::Edge> { + } +} + +// Long function without return type that should not be reformatted. +fn veeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) {} + +fn veeeeeeeeeeeeeeeeeeeeeery_long_name(a: FirstTypeeeeeeeeee, b: SecondTypeeeeeeeeeeeeeeeeeeeeeee) { +} + +fn veeeeeeeeeeeeeeeeeeeeeeery_long_name( + a: FirstTypeeeeeeeeee, + b: SecondTypeeeeeeeeeeeeeeeeeeeeeee, +) { +} diff --git a/tests/target/issue-1055.rs b/tests/target/issue-1055.rs new file mode 100644 index 00000000000..ee143e792b0 --- /dev/null +++ b/tests/target/issue-1055.rs @@ -0,0 +1,3 @@ +fn issue_1055() { + let foo = (|| {})(); +} diff --git a/tests/target/issue-1111.rs b/tests/target/issue-1111.rs new file mode 100644 index 00000000000..2e1a89ad78e --- /dev/null +++ b/tests/target/issue-1111.rs @@ -0,0 +1 @@ +use bar; diff --git a/tests/target/issue-1113.rs b/tests/target/issue-1113.rs new file mode 100644 index 00000000000..1245bcd057c --- /dev/null +++ b/tests/target/issue-1113.rs @@ -0,0 +1,33 @@ +pub fn foo() -> fmt::Result +//pub fn writeStringToken +{ + panic!() +} + +pub fn foo() -> fmt::Result // pub fn writeStringToken +{ + panic!() +} + +pub fn foo() -> fmt::Result /* pub fn writeStringToken */ { + panic!() +} + +pub fn foo() -> fmt::Result +/* pub fn writeStringToken */ { + panic!() +} + +pub fn foo() -> fmt::Result +/* pub fn writeStringToken */ +{ + panic!() +} + +pub fn foo() -> fmt::Result /* + * + * + */ +{ + panic!() +} diff --git a/tests/target/issue-1120.rs b/tests/target/issue-1120.rs new file mode 100644 index 00000000000..f44597e7d1e --- /dev/null +++ b/tests/target/issue-1120.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_imports: true + +// Ensure that a use at the start of an inline module is correctly formatted. +mod foo { + use bar; +} + +// Ensure that an indented `use` gets the correct indentation. +mod foo { + use bar; +} diff --git a/tests/target/issue-1124.rs b/tests/target/issue-1124.rs new file mode 100644 index 00000000000..d34870b2a28 --- /dev/null +++ b/tests/target/issue-1124.rs @@ -0,0 +1,20 @@ +// rustfmt-reorder_imports: true +// rustfmt-normalize_comments: true + +use a; +use b; +use c; +use d; +// The previous line has a space after the `use a;` + +mod a { + use a; + use b; + use c; + use d; +} + +use a; +use x; +use y; +use z; diff --git a/tests/target/issue-1127.rs b/tests/target/issue-1127.rs new file mode 100644 index 00000000000..dbdd234b8e4 --- /dev/null +++ b/tests/target/issue-1127.rs @@ -0,0 +1,25 @@ +// rustfmt-max_width:120 +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true + +fn a_very_very_very_very_very_very_very_very_very_very_very_long_function_name() -> i32 { + 42 +} + +enum TestEnum { + AVeryVeryLongEnumName, + AnotherVeryLongEnumName, + TheLastVeryLongEnumName, +} + +fn main() { + let var = TestEnum::AVeryVeryLongEnumName; + let num = match var { + TestEnum::AVeryVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::AnotherVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + TestEnum::TheLastVeryLongEnumName => + a_very_very_very_very_very_very_very_very_very_very_very_long_function_name(), + }; +} diff --git a/tests/target/issue-1158.rs b/tests/target/issue-1158.rs new file mode 100644 index 00000000000..2abfa5a29f2 --- /dev/null +++ b/tests/target/issue-1158.rs @@ -0,0 +1,3 @@ +trait T { + itemmacro!(this, is.now().formatted(yay)); +} diff --git a/tests/target/issue-1177.rs b/tests/target/issue-1177.rs new file mode 100644 index 00000000000..dcda3972814 --- /dev/null +++ b/tests/target/issue-1177.rs @@ -0,0 +1,7 @@ +// rustfmt-normalize_comments: true +fn main() { + // Line Comment + // Block Comment + + let d = 5; +} diff --git a/tests/target/issue-1192.rs b/tests/target/issue-1192.rs new file mode 100644 index 00000000000..432fe8cce7c --- /dev/null +++ b/tests/target/issue-1192.rs @@ -0,0 +1,3 @@ +fn main() { + assert!(true); +} diff --git a/tests/target/issue-1211.rs b/tests/target/issue-1211.rs new file mode 100644 index 00000000000..de4c5c87ee6 --- /dev/null +++ b/tests/target/issue-1211.rs @@ -0,0 +1,13 @@ +fn main() { + for iface in &ifaces { + match iface.addr { + get_if_addrs::IfAddr::V4(ref addr) => match addr.broadcast { + Some(ip) => { + sock.send_to(&buf, (ip, 8765)).expect("foobar"); + } + _ => (), + }, + _ => (), + }; + } +} diff --git a/tests/target/issue-1214.rs b/tests/target/issue-1214.rs new file mode 100644 index 00000000000..c622abb3a85 --- /dev/null +++ b/tests/target/issue-1214.rs @@ -0,0 +1,8 @@ +/*! +# Example + +``` + // Here goes some example +``` + */ +struct Item; diff --git a/tests/target/issue-1216.rs b/tests/target/issue-1216.rs new file mode 100644 index 00000000000..d727c158ab8 --- /dev/null +++ b/tests/target/issue-1216.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +enum E { + A, //* I am not a block comment (caused panic) + B, +} diff --git a/tests/target/issue-1239.rs b/tests/target/issue-1239.rs new file mode 100644 index 00000000000..b10afb5cb6c --- /dev/null +++ b/tests/target/issue-1239.rs @@ -0,0 +1,10 @@ +fn foo() { + let with_alignment = if condition__uses_alignment_for_first_if__0 + || condition__uses_alignment_for_first_if__1 + || condition__uses_alignment_for_first_if__2 + { + } else if condition__no_alignment_for_later_else__0 || condition__no_alignment_for_later_else__1 + || condition__no_alignment_for_later_else__2 + { + }; +} diff --git a/tests/target/issue-1247.rs b/tests/target/issue-1247.rs new file mode 100644 index 00000000000..16c63e0f53d --- /dev/null +++ b/tests/target/issue-1247.rs @@ -0,0 +1,8 @@ +// rustfmt-max_width: 80 + +fn foo() { + polyfill::slice::fill( + &mut self.pending[padding_pos..(self.algorithm.block_len - 8)], + 0, + ); +} diff --git a/tests/target/issue-1255.rs b/tests/target/issue-1255.rs new file mode 100644 index 00000000000..2d4633844a9 --- /dev/null +++ b/tests/target/issue-1255.rs @@ -0,0 +1,10 @@ +// Test for issue #1255 +// Default annotation incorrectly removed on associated types +#![feature(specialization)] + +trait Trait { + type Type; +} +impl Trait for T { + default type Type = u64; // 'default' should not be removed +} diff --git a/tests/target/issue-1278.rs b/tests/target/issue-1278.rs new file mode 100644 index 00000000000..e25376561a9 --- /dev/null +++ b/tests/target/issue-1278.rs @@ -0,0 +1,9 @@ +// rustfmt-indent_style = "block" + +#![feature(pub_restricted)] + +mod inner_mode { + pub(super) fn func_name(abc: i32) -> i32 { + abc + } +} diff --git a/tests/target/issue-1350.rs b/tests/target/issue-1350.rs new file mode 100644 index 00000000000..2cf65509c93 --- /dev/null +++ b/tests/target/issue-1350.rs @@ -0,0 +1,14 @@ +// rustfmt-max_width: 120 +// rustfmt-comment_width: 110 + +impl Struct { + fn fun() { + let result = match ::deserialize(&json) { + Ok(v) => v, + Err(e) => match ::deserialize(&json) { + Ok(v) => return Err(Error::with_json(v)), + Err(e2) => return Err(Error::with_json(e)), + }, + }; + } +} diff --git a/tests/target/issue-1366.rs b/tests/target/issue-1366.rs new file mode 100644 index 00000000000..eee147baab9 --- /dev/null +++ b/tests/target/issue-1366.rs @@ -0,0 +1,13 @@ +fn main() { + fn f() -> Option { + Some("fffffffsssssssssddddssssfffffddddff") + .map(|s| s) + .map(|s| s.to_string()) + .map(|res| match Some(res) { + Some(ref s) if s == "" => 41, + Some(_) => 42, + _ => 43, + }) + } + println!("{:?}", f()) +} diff --git a/tests/target/issue-1397.rs b/tests/target/issue-1397.rs new file mode 100644 index 00000000000..86b7a78411f --- /dev/null +++ b/tests/target/issue-1397.rs @@ -0,0 +1,25 @@ +pub enum TransactionState { + Committed(i64), +} + +pub enum Packet { + Transaction { state: TransactionState }, +} + +fn baz(p: Packet) { + loop { + loop { + loop { + loop { + if let Packet::Transaction { + state: TransactionState::Committed(ts, ..), + .. + } = p + { + unreachable!() + } + } + } + } + } +} diff --git a/tests/target/issue-1468.rs b/tests/target/issue-1468.rs new file mode 100644 index 00000000000..4c14a0f746a --- /dev/null +++ b/tests/target/issue-1468.rs @@ -0,0 +1,29 @@ +fn issue1468() { + euc_jp_decoder_functions!({ + let trail_minus_offset = byte.wrapping_sub(0xA1); + // Fast-track Hiragana (60% according to Lunde) + // and Katakana (10% according to Lunde). + if jis0208_lead_minus_offset == 0x03 && trail_minus_offset < 0x53 { + // Hiragana + handle.write_upper_bmp(0x3041 + trail_minus_offset as u16) + } else if jis0208_lead_minus_offset == 0x04 && trail_minus_offset < 0x56 { + // Katakana + handle.write_upper_bmp(0x30A1 + trail_minus_offset as u16) + } else if trail_minus_offset > (0xFE - 0xA1) { + if byte < 0x80 { + return ( + DecoderResult::Malformed(1, 0), + unread_handle_trail.unread(), + handle.written(), + ); + } + return ( + DecoderResult::Malformed(2, 0), + unread_handle_trail.consumed(), + handle.written(), + ); + } else { + unreachable!(); + } + }); +} diff --git a/tests/target/issue-1598.rs b/tests/target/issue-1598.rs new file mode 100644 index 00000000000..c7e02c961a6 --- /dev/null +++ b/tests/target/issue-1598.rs @@ -0,0 +1,6 @@ +fn main() { + //foo + /* + */ + format!("hello"); +} diff --git a/tests/target/issue-1624.rs b/tests/target/issue-1624.rs new file mode 100644 index 00000000000..477fc27353f --- /dev/null +++ b/tests/target/issue-1624.rs @@ -0,0 +1,6 @@ +// #1624 +pub unsafe fn some_long_function_name( + arg1: Type1, + arg2: Type2, +) -> (SomeLongTypeName, AnotherLongTypeName, AnotherLongTypeName) { +} diff --git a/tests/target/issue-1681.rs b/tests/target/issue-1681.rs new file mode 100644 index 00000000000..5734fd5502d --- /dev/null +++ b/tests/target/issue-1681.rs @@ -0,0 +1,20 @@ +// rustfmt-max_width: 80 + +// We would like to surround closure body with block when overflowing the last +// argument of function call if the last argument has condition and without +// block it may go multi lines. +fn foo() { + refmut_map_result(self.cache.borrow_mut(), |cache| { + match cache.entry(cache_key) { + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => { + let statement = { + let sql = try!(entry.key().sql(source)); + prepare_fn(&sql) + }; + + Ok(entry.insert(try!(statement))) + } + } + }).map(MaybeCached::Cached) +} diff --git a/tests/target/issue-1693.rs b/tests/target/issue-1693.rs new file mode 100644 index 00000000000..85421a123bb --- /dev/null +++ b/tests/target/issue-1693.rs @@ -0,0 +1,10 @@ +fn issue1693() { + let pixel_data = vec![ + ( + f16::from_f32(0.82), + f16::from_f32(1.78), + f16::from_f32(0.21) + ); + 256 * 256 + ]; +} diff --git a/tests/target/issue-1703.rs b/tests/target/issue-1703.rs new file mode 100644 index 00000000000..4079ef4cfca --- /dev/null +++ b/tests/target/issue-1703.rs @@ -0,0 +1,9 @@ +// rustfmt should not remove doc comments or comments inside attributes. + +/** +This function has a block doc comment. + */ +fn test_function() {} + +#[foo /* do not remove this! */] +fn foo() {} diff --git a/tests/target/issue-1800.rs b/tests/target/issue-1800.rs new file mode 100644 index 00000000000..06c5cfd0567 --- /dev/null +++ b/tests/target/issue-1800.rs @@ -0,0 +1,3 @@ +#![doc(html_root_url = "http://example.com")] +#[cfg(feature = "foo")] +fn a() {} diff --git a/tests/target/issue-1802.rs b/tests/target/issue-1802.rs new file mode 100644 index 00000000000..a4679463ba2 --- /dev/null +++ b/tests/target/issue-1802.rs @@ -0,0 +1,10 @@ +// rustfmt-tab_spaces: 2 +// rustfmt-max_width: 30 +// rustfmt-error_on_line_overflow: false + +enum F { + X { + a: dddddddddddddd, + b: eeeeeeeeeeeeeee, + }, +} diff --git a/tests/target/issue-1824.rs b/tests/target/issue-1824.rs new file mode 100644 index 00000000000..1c4c2db46dc --- /dev/null +++ b/tests/target/issue-1824.rs @@ -0,0 +1,5 @@ +pub trait Ingredient +where + Self: Send, +{ +} diff --git a/tests/target/issue-1914.rs b/tests/target/issue-1914.rs new file mode 100644 index 00000000000..d2d532af1dc --- /dev/null +++ b/tests/target/issue-1914.rs @@ -0,0 +1,7 @@ +// rustfmt-max_width: 80 + +extern "C" { + #[link_name = "_ZN7MyClass26example_check_no_collisionE"] + pub static mut MyClass_example_check_no_collision: + *const ::std::os::raw::c_int; +} diff --git a/tests/target/issue-2025.rs b/tests/target/issue-2025.rs new file mode 100644 index 00000000000..38bf369bea3 --- /dev/null +++ b/tests/target/issue-2025.rs @@ -0,0 +1,4 @@ +// See if rustfmt removes empty lines on top of the file. +pub fn foo() { + println!("hello, world"); +} diff --git a/tests/target/issue-2103.rs b/tests/target/issue-2103.rs new file mode 100644 index 00000000000..5a043d54b75 --- /dev/null +++ b/tests/target/issue-2103.rs @@ -0,0 +1,14 @@ +struct X +where + i32: Sized, +{ + x: i32, +} + +struct X +// with comment +where + i32: Sized, +{ + x: i32, +} diff --git a/tests/target/issue-2111.rs b/tests/target/issue-2111.rs new file mode 100644 index 00000000000..13303a736a3 --- /dev/null +++ b/tests/target/issue-2111.rs @@ -0,0 +1,26 @@ +// rustfmt-normalize_comments: false + +// An import with single line comments. +use super::{DelayChoice, + Destinations, + Holding, + LodaModel, + MethodDescription, + ModelBehaviour, + ModelEdges, + ModelProperties, + ModelRequestGraph, + ModelSelector, + RequestDescription, + StringMap, + Switch, + // ModelMetaData, + // Generated, + // SecondsString, + // DateString, + // ModelConfiguration, + // ModelRequests, + // RestResponse, + // RestResponseCode, + // UniformHolding + SCHEMA_VERSIONS}; diff --git a/tests/target/issue-2123.rs b/tests/target/issue-2123.rs new file mode 100644 index 00000000000..5e9917b4023 --- /dev/null +++ b/tests/target/issue-2123.rs @@ -0,0 +1,6 @@ +// rustfmt-wrap_comments: true + +//hello +//world + +fn main() {} diff --git a/tests/target/issue-2164.rs b/tests/target/issue-2164.rs new file mode 100644 index 00000000000..ab1d7dfd37a --- /dev/null +++ b/tests/target/issue-2164.rs @@ -0,0 +1,132 @@ +// A stress test against code generated by bindgen. +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct emacs_env_25 { + pub size: isize, + pub private_members: *mut emacs_env_private, + pub make_global_ref: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, any_reference: emacs_value) -> emacs_value, + >, + pub free_global_ref: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, global_reference: emacs_value), + >, + pub non_local_exit_check: + ::std::option::Option emacs_funcall_exit>, + pub non_local_exit_clear: ::std::option::Option, + pub non_local_exit_get: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + non_local_exit_symbol_out: *mut emacs_value, + non_local_exit_data_out: *mut emacs_value, + ) -> emacs_funcall_exit, + >, + pub non_local_exit_signal: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + non_local_exit_symbol: emacs_value, + non_local_exit_data: emacs_value, + ), + >, + pub non_local_exit_throw: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, tag: emacs_value, value: emacs_value), + >, + pub make_function: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + min_arity: isize, + max_arity: isize, + function: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + nargs: isize, + args: *mut emacs_value, + arg1: *mut ::libc::c_void, + ) -> emacs_value, + >, + documentation: *const ::libc::c_char, + data: *mut ::libc::c_void, + ) -> emacs_value, + >, + pub funcall: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + function: emacs_value, + nargs: isize, + args: *mut emacs_value, + ) -> emacs_value, + >, + pub intern: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, symbol_name: *const ::libc::c_char) + -> emacs_value, + >, + pub type_of: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> emacs_value, + >, + pub is_not_nil: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> bool, + >, + pub eq: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, a: emacs_value, b: emacs_value) -> bool, + >, + pub extract_integer: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> intmax_t, + >, + pub make_integer: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, value: intmax_t) -> emacs_value, + >, + pub extract_float: + ::std::option::Option f64>, + pub make_float: + ::std::option::Option emacs_value>, + pub copy_string_contents: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + value: emacs_value, + buffer: *mut ::libc::c_char, + size_inout: *mut isize, + ) -> bool, + >, + pub make_string: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, contents: *const ::libc::c_char, length: isize) + -> emacs_value, + >, + pub make_user_ptr: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + fin: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::libc::c_void), + >, + ptr: *mut ::libc::c_void, + ) -> emacs_value, + >, + pub get_user_ptr: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value) -> *mut ::libc::c_void, + >, + pub set_user_ptr: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, uptr: emacs_value, ptr: *mut ::libc::c_void), + >, + pub get_user_finalizer: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value + ) -> ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value), + >, + >, + pub set_user_finalizer: ::std::option::Option< + unsafe extern "C" fn( + env: *mut emacs_env, + uptr: emacs_value, + fin: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::libc::c_void), + >, + ), + >, + pub vec_get: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize) -> emacs_value, + >, + pub vec_set: ::std::option::Option< + unsafe extern "C" fn(env: *mut emacs_env, vec: emacs_value, i: isize, val: emacs_value), + >, + pub vec_size: + ::std::option::Option isize>, +} diff --git a/tests/target/issue-2179.rs b/tests/target/issue-2179.rs new file mode 100644 index 00000000000..db8f9c557b4 --- /dev/null +++ b/tests/target/issue-2179.rs @@ -0,0 +1,36 @@ +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!( + "cargo - couldn't find binary `{}` specified in `build_bin` configuration", + build_bin + ); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; +} diff --git a/tests/target/issue-2197.rs b/tests/target/issue-2197.rs new file mode 100644 index 00000000000..76dbbefc3a7 --- /dev/null +++ b/tests/target/issue-2197.rs @@ -0,0 +1,18 @@ +// rustfmt-max_width: 79 +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false + +/// ```rust +/// unsafe fn sum_sse2(x: i32x4) -> i32 { +/// let x = vendor::_mm_add_epi32( +/// x, +/// vendor::_mm_srli_si128(x.into(), 8).into(), +/// ); +/// let x = vendor::_mm_add_epi32( +/// x, +/// vendor::_mm_srli_si128(x.into(), 4).into(), +/// ); +/// vendor::_mm_cvtsi128_si32(x) +/// } +/// ``` +fn foo() {} diff --git a/tests/target/issue-2256.rs b/tests/target/issue-2256.rs new file mode 100644 index 00000000000..4b546223f94 --- /dev/null +++ b/tests/target/issue-2256.rs @@ -0,0 +1,7 @@ +// こんにちは +use std::borrow::Cow; + +/* comment */ +/* comment */ + +/* comment */ diff --git a/tests/target/issue-2324.rs b/tests/target/issue-2324.rs new file mode 100644 index 00000000000..9211b24d81f --- /dev/null +++ b/tests/target/issue-2324.rs @@ -0,0 +1,7 @@ +// nested function calls with cast. +fn main() { + self.ptr + .set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T); + self.ptr + .set(intrinsics::arith_offset(self.ptr.get(), mem::size_of::() as isize) as *mut u8); +} diff --git a/tests/target/issue-2329.rs b/tests/target/issue-2329.rs new file mode 100644 index 00000000000..e36e9546b24 --- /dev/null +++ b/tests/target/issue-2329.rs @@ -0,0 +1,30 @@ +// Comments with characters which must be represented by multibyte. + +// フー +use foo; +// バー +use bar; + +impl MyStruct { + // コメント + fn f1() {} // こんにちは + fn f2() {} // ありがとう + // コメント +} + +trait MyTrait { + // コメント + fn f1() {} // こんにちは + fn f2() {} // ありがとう + // コメント +} + +fn main() { + // コメント + let x = 1; // X + println!( + "x = {}", // xの値 + x, // X + ); + // コメント +} diff --git a/tests/target/issue-2342.rs b/tests/target/issue-2342.rs new file mode 100644 index 00000000000..f9c26857e15 --- /dev/null +++ b/tests/target/issue-2342.rs @@ -0,0 +1,6 @@ +// rustfmt-max_width: 80 + +struct Foo { + #[cfg(feature = "serde")] + bytes: [[u8; 17]; 5], // Same size as signature::ED25519_PKCS8_V2_LEN +} diff --git a/tests/target/issue-2346.rs b/tests/target/issue-2346.rs new file mode 100644 index 00000000000..07817221a51 --- /dev/null +++ b/tests/target/issue-2346.rs @@ -0,0 +1,4 @@ +// rustfmt-normalize_comments: true +// the following empty comment should not have any trailing space added. +// +fn main() {} diff --git a/tests/target/issue-2401.rs b/tests/target/issue-2401.rs new file mode 100644 index 00000000000..ec8f27b732f --- /dev/null +++ b/tests/target/issue-2401.rs @@ -0,0 +1,7 @@ +// rustfmt-hard_tabs = true +// rustfmt-normalize_comments = true + +/// ``` +/// println!("Hello, World!"); +/// ``` +fn main() {} diff --git a/tests/target/issue-2446.rs b/tests/target/issue-2446.rs new file mode 100644 index 00000000000..be62e9c9c31 --- /dev/null +++ b/tests/target/issue-2446.rs @@ -0,0 +1,9 @@ +enum Issue2446 { + V { + f: u8, // x + }, +} + +enum Issue2446TrailingCommentsOnly { + V { f: u8 /* */ }, +} diff --git a/tests/target/issue-2479.rs b/tests/target/issue-2479.rs new file mode 100644 index 00000000000..3683ab22089 --- /dev/null +++ b/tests/target/issue-2479.rs @@ -0,0 +1,12 @@ +// Long attributes. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum POLARITYR { + #[doc = "Task mode: No effect on pin from OUT[n] task. Event mode: no IN[n] event generated on pin activity."] + NONE, + #[doc = "Task mode: Set pin from OUT[n] task. Event mode: Generate IN[n] event when rising edge on pin."] + LOTOHI, + #[doc = "Task mode: Clear pin from OUT[n] task. Event mode: Generate IN[n] event when falling edge on pin."] + HITOLO, + #[doc = "Task mode: Toggle pin from OUT[n]. Event mode: Generate IN[n] when any change on pin."] + TOGGLE, +} diff --git a/tests/target/issue-447.rs b/tests/target/issue-447.rs new file mode 100644 index 00000000000..d41cdb65cd0 --- /dev/null +++ b/tests/target/issue-447.rs @@ -0,0 +1,40 @@ +// rustfmt-normalize_comments: true + +fn main() { + if + // shouldn't be dropped + // shouldn't be dropped + cond + // shouldn't be dropped + // shouldn't be dropped + { + } + // shouldn't be dropped + // shouldn't be dropped + else + // shouldn't be dropped + // shouldn't be dropped + if + // shouldn't be dropped + // shouldn't be dropped + cond + // shouldn't be dropped + // shouldn't be dropped + { + } + // shouldn't be dropped + // shouldn't be dropped + else + // shouldn't be dropped + // shouldn't be dropped + { + } + + if + // shouldn't be dropped + // shouldn't be dropped + let Some(x) = y + // shouldn't be dropped + // shouldn't be dropped + {} +} diff --git a/tests/target/issue-510.rs b/tests/target/issue-510.rs new file mode 100644 index 00000000000..a166b68498f --- /dev/null +++ b/tests/target/issue-510.rs @@ -0,0 +1,41 @@ +impl ISizeAndMarginsComputer for AbsoluteNonReplaced { + fn solve_inline_size_constraints( + &self, + block: &mut BlockFlow, + input: &ISizeConstraintInput, + ) -> ISizeConstraintSolution { + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = match ( + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + inline_startssssssxxxxxxsssssxxxxxxxxxssssssxxx, + ) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); + (Au(0), inline_size, margin_start, margin_end) + } + }; + + let (inline_start, inline_size, margin_inline_start, margin_inline_end) = + match (inline_start, inline_end, computed_inline_size) { + (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => { + let margin_start = inline_start_margin.specified_or_zero(); + let margin_end = inline_end_margin.specified_or_zero(); + // Now it is the same situation as inline-start Specified and inline-end + // and inline-size Auto. + // + // Set inline-end to zero to calculate inline-size. + let inline_size = block.get_shrink_to_fit_inline_size( + available_inline_size - (margin_start + margin_end), + ); + (Au(0), inline_size, margin_start, margin_end) + } + }; + } +} diff --git a/tests/target/issue-64.rs b/tests/target/issue-64.rs new file mode 100644 index 00000000000..c0660630203 --- /dev/null +++ b/tests/target/issue-64.rs @@ -0,0 +1,7 @@ +// Regression test for issue 64 + +pub fn header_name() -> &'static str { + let name = ::header_name(); + let func = ::header_name; + name +} diff --git a/tests/target/issue-691.rs b/tests/target/issue-691.rs new file mode 100644 index 00000000000..7473d070eff --- /dev/null +++ b/tests/target/issue-691.rs @@ -0,0 +1,9 @@ +// rustfmt-normalize_comments: true + +//! `std` or `core` and simply link to this library. In case the target +//! platform has no hardware +//! support for some operation, software implementations provided by this +//! library will be used automagically. +// TODO: provide instructions to override default libm link and how to link to +// this library. +fn foo() {} diff --git a/tests/target/issue-770.rs b/tests/target/issue-770.rs new file mode 100644 index 00000000000..5fbedd7b734 --- /dev/null +++ b/tests/target/issue-770.rs @@ -0,0 +1,10 @@ +fn main() { + if false { + if false { + } else { + // A let binding here seems necessary to trigger it. + let _ = (); + } + } else if let false = false { + } +} diff --git a/tests/target/issue-811.rs b/tests/target/issue-811.rs new file mode 100644 index 00000000000..b7a89b5d0f9 --- /dev/null +++ b/tests/target/issue-811.rs @@ -0,0 +1,19 @@ +trait FooTrait: Sized { + type Bar: BarTrait; +} + +trait BarTrait: Sized { + type Baz; + fn foo(); +} + +type Foo = <>::Bar as BarTrait>::Baz; +type Bar = >::Baz; + +fn some_func, U>() { + <>::Bar as BarTrait>::foo(); +} + +fn some_func>() { + >::foo(); +} diff --git a/tests/target/issue-831.rs b/tests/target/issue-831.rs new file mode 100644 index 00000000000..1d6327c2158 --- /dev/null +++ b/tests/target/issue-831.rs @@ -0,0 +1,9 @@ +fn main() { + let y = a.iter().any(|x| { + println!("a"); + }) || b.iter().any(|x| { + println!("b"); + }) || c.iter().any(|x| { + println!("c"); + }); +} diff --git a/tests/target/issue-850.rs b/tests/target/issue-850.rs new file mode 100644 index 00000000000..c939716a6a8 --- /dev/null +++ b/tests/target/issue-850.rs @@ -0,0 +1 @@ +const unsafe fn x() {} diff --git a/tests/target/issue-855.rs b/tests/target/issue-855.rs new file mode 100644 index 00000000000..0430cc62954 --- /dev/null +++ b/tests/target/issue-855.rs @@ -0,0 +1,27 @@ +fn main() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Some(Keycode::Escape), + .. + } => break 'running, + } + } + } +} + +fn main2() { + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDownXXXXXXXXXXXXX { + keycode: Some(Keycode::Escape), + .. + } => break 'running, + } + } + } +} diff --git a/tests/target/issue-913.rs b/tests/target/issue-913.rs new file mode 100644 index 00000000000..2158b70a46f --- /dev/null +++ b/tests/target/issue-913.rs @@ -0,0 +1,24 @@ +// rustfmt-error_on_line_overflow: false + +mod client { + impl Client { + fn test(self) -> Result<()> { + let next_state = match self.state { + State::V5(v5::State::Command(v5::coand::State::WriteVersion(ref mut response))) => { + let x = reformat.meeee(); + } + }; + + let next_state = match self.state { + State::V5(v5::State::Command(v5::comand::State::WriteVersion( + ref mut response, + ))) => { + // The pattern cannot be formatted in a way that the match stays + // within the column limit. The rewrite should therefore be + // skipped. + let x = dont.reformat.meeee(); + } + }; + } + } +} diff --git a/tests/target/issue-945.rs b/tests/target/issue-945.rs new file mode 100644 index 00000000000..d46c69a4f09 --- /dev/null +++ b/tests/target/issue-945.rs @@ -0,0 +1,17 @@ +impl Bar { + default const unsafe fn foo() { + "hi" + } +} + +impl Baz { + default unsafe extern "C" fn foo() { + "hi" + } +} + +impl Foo for Bar { + default fn foo() { + "hi" + } +} diff --git a/tests/target/issue-977.rs b/tests/target/issue-977.rs new file mode 100644 index 00000000000..9420054449d --- /dev/null +++ b/tests/target/issue-977.rs @@ -0,0 +1,16 @@ +// rustfmt-normalize_comments: true +// FIXME(#919) + +trait NameC { + // comment +} +struct FooC { /* comment */ } +enum MooC { + // comment +} +mod BarC { + // comment +} +extern "C" { + // comment +} diff --git a/tests/target/item-brace-style-always-next-line.rs b/tests/target/item-brace-style-always-next-line.rs new file mode 100644 index 00000000000..531ac598683 --- /dev/null +++ b/tests/target/item-brace-style-always-next-line.rs @@ -0,0 +1,42 @@ +// rustfmt-brace_style: AlwaysNextLine + +mod M +{ + enum A + { + A, + } + + struct B + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where + T: Copy, + { + A, + } + + struct B + where + T: Copy, + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where + T: Copy, {} + + struct D + where + T: Copy, {} +} diff --git a/tests/target/item-brace-style-prefer-same-line.rs b/tests/target/item-brace-style-prefer-same-line.rs new file mode 100644 index 00000000000..ef8dc028c2d --- /dev/null +++ b/tests/target/item-brace-style-prefer-same-line.rs @@ -0,0 +1,35 @@ +// rustfmt-brace_style: PreferSameLine + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + enum C {} + + struct D {} + + enum A + where + T: Copy, { + A, + } + + struct B + where + T: Copy, { + b: i32, + } + + enum C + where + T: Copy, {} + + struct D + where + T: Copy, {} +} diff --git a/tests/target/item-brace-style-same-line-where.rs b/tests/target/item-brace-style-same-line-where.rs new file mode 100644 index 00000000000..9a275efc96e --- /dev/null +++ b/tests/target/item-brace-style-same-line-where.rs @@ -0,0 +1,39 @@ +// rustfmt-brace_style: SameLineWhere + +mod M { + enum A { + A, + } + + struct B { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C {} + + struct D {} + + enum A + where + T: Copy, + { + A, + } + + struct B + where + T: Copy, + { + b: i32, + } + + // For empty enums and structs, the brace remains on the same line. + enum C + where + T: Copy, {} + + struct D + where + T: Copy, {} +} diff --git a/tests/target/large-block.rs b/tests/target/large-block.rs new file mode 100644 index 00000000000..09e9169f340 --- /dev/null +++ b/tests/target/large-block.rs @@ -0,0 +1,5 @@ +fn issue1351() { + std_fmt_Arguments_new_v1_std_rt_begin_panic_fmt_sdfasfasdfasdf({ + static __STATIC_FMTSTR: &'static [&'static str] = &[]; + }); +} diff --git a/tests/target/large_vec.rs b/tests/target/large_vec.rs new file mode 100644 index 00000000000..95d1fc43c03 --- /dev/null +++ b/tests/target/large_vec.rs @@ -0,0 +1,42 @@ +// See #1470. + +impl Environment { + pub fn new_root() -> Rc> { + let mut env = Environment::new(); + let builtin_functions = &[ + ( + "println", + Function::NativeVoid( + CallSign { + num_params: 0, + variadic: true, + param_types: vec![], + }, + native_println, + ), + ), + ( + "run_http_server", + Function::NativeVoid( + CallSign { + num_params: 1, + variadic: false, + param_types: vec![Some(ConstraintType::Function)], + }, + native_run_http_server, + ), + ), + ( + "len", + Function::NativeReturning( + CallSign { + num_params: 1, + variadic: false, + param_types: vec![None], + }, + native_len, + ), + ), + ]; + } +} diff --git a/tests/target/lazy_static.rs b/tests/target/lazy_static.rs new file mode 100644 index 00000000000..edce6e7b894 --- /dev/null +++ b/tests/target/lazy_static.rs @@ -0,0 +1,39 @@ +// Format `lazy_static!`. + +lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = + regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) + .expect("Failed creating configuration value pattern"); +} + +// We need to be able to format `lazy_static!` without known syntax. +lazy_static!(xxx, yyyy, zzzzz); + +lazy_static!{} + +// #2354 +lazy_static! { + pub static ref Sbase64_encode_string: ::lisp::LispSubrRef = { + let subr = ::remacs_sys::Lisp_Subr { + header: ::remacs_sys::Lisp_Vectorlike_Header { + size: ((::remacs_sys::PseudovecType::PVEC_SUBR as ::libc::ptrdiff_t) + << ::remacs_sys::PSEUDOVECTOR_AREA_BITS), + }, + function: self::Fbase64_encode_string as *const ::libc::c_void, + min_args: 1i16, + max_args: 2i16, + symbol_name: (b"base64-encode-string\x00").as_ptr() as *const ::libc::c_char, + intspec: ::std::ptr::null(), + doc: ::std::ptr::null(), + lang: ::remacs_sys::Lisp_Subr_Lang_Rust, + }; + unsafe { + let ptr = ::remacs_sys::xmalloc(::std::mem::size_of::<::remacs_sys::Lisp_Subr>()) + as *mut ::remacs_sys::Lisp_Subr; + ::std::ptr::copy_nonoverlapping(&subr, ptr, 1); + ::std::mem::forget(subr); + ::lisp::ExternalPtr::new(ptr) + } + }; +} diff --git a/tests/target/long-fn-1.rs b/tests/target/long-fn-1.rs new file mode 100644 index 00000000000..c3d44de7c69 --- /dev/null +++ b/tests/target/long-fn-1.rs @@ -0,0 +1,21 @@ +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input( + &mut self, + input: Input, + input_path: Option, + ) -> (Input, Option) { + } + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { + } +} + +// #1843 +#[allow(non_snake_case)] +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash( +) -> bool { + false +} diff --git a/tests/target/long-match-arms-brace-newline.rs b/tests/target/long-match-arms-brace-newline.rs new file mode 100644 index 00000000000..aeb384e7203 --- /dev/null +++ b/tests/target/long-match-arms-brace-newline.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 80 +// rustfmt-control_brace_style: AlwaysNextLine + +fn main() { + match x + { + aaaaaaaa::Bbbbb::Ccccccccccccc(_, Some(ref x)) + if x == "aaaaaaaaaaa aaaaaaa aaaaaa" => + { + Ok(()) + } + _ => Err(x), + } +} diff --git a/tests/target/long_field_access.rs b/tests/target/long_field_access.rs new file mode 100644 index 00000000000..349d2c2f639 --- /dev/null +++ b/tests/target/long_field_access.rs @@ -0,0 +1,4 @@ +fn f() { + block_flow.base.stacking_relative_position_of_display_port = + self.base.stacking_relative_position_of_display_port; +} diff --git a/tests/target/loop.rs b/tests/target/loop.rs new file mode 100644 index 00000000000..f669e7e2c58 --- /dev/null +++ b/tests/target/loop.rs @@ -0,0 +1,34 @@ +fn main() { + loop { + return some_val; + } + + let x = loop { + do_forever(); + }; + + 'label: loop { + // Just comments + } + + 'a: while loooooooooooooooooooooooooooooooooong_variable_name + another_value > some_other_value + { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb { + } + + while aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { + } + + 'b: for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in some_iter(arg1, arg2) + { + // do smth + } + + while let Some(i) = x.find('s') { + x.update(); + continue; + continue 'foo; + } +} diff --git a/tests/target/macro_not_expr.rs b/tests/target/macro_not_expr.rs new file mode 100644 index 00000000000..c76a6492a9d --- /dev/null +++ b/tests/target/macro_not_expr.rs @@ -0,0 +1,7 @@ +macro_rules! test { + ($($t: tt)*) => {}; +} + +fn main() { + test!( a : B => c d ); +} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs new file mode 100644 index 00000000000..2136784dec7 --- /dev/null +++ b/tests/target/macro_rules.rs @@ -0,0 +1,105 @@ +// rustfmt-error_on_line_overflow: false + +macro_rules! m { + // a + ($expr: expr, $($func: ident)*) => {{ + let x = $expr; + $func(x) + }}; + + /* b */ + () => { + /* c */ + }; + + (@tag) => {}; + + // d + ($item: ident) => { + mod macro_item { + struct $item; + } + }; +} + +macro m2 { + // a + ($expr: expr, $($func: ident)*) => {{ + let x = $expr; + $func(x) + }} + + /* b */ + () => { + /* c */ + } + + (@tag) => {} + + // d + ($item: ident) => { + mod macro_item { + struct $item; + } + } +} + +// #2438, #2476 +macro_rules! m { + () => { + fn foo() { + this_line_is_98_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(); + } + }; +} +macro_rules! m { + () => { + fn foo() { + this_line_is_99_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ); + } + }; +} +macro_rules! m { + () => { + fn foo() { + this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ); + } + }; +} +macro_rules! m { + () => { + fn foo() { + this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx( + ); + } + }; +} + +// #2439 +macro_rules! m { + ( + $line0_xxxxxxxxxxxxxxxxx: expr, + $line1_xxxxxxxxxxxxxxxxx: expr, + $line2_xxxxxxxxxxxxxxxxx: expr, + $line3_xxxxxxxxxxxxxxxxx: expr, + ) => {}; +} + +// #2466 +// Skip formatting `macro_rules!` that are not using `{}`. +macro_rules! m ( + () => () +); +macro_rules! m [ + () => () +]; + +// #2470 +macro foo($type_name: ident, $docs: expr) { + #[allow(non_camel_case_types)] + #[doc=$docs] + #[derive(Debug, Clone, Copy)] + pub struct $type_name; +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs new file mode 100644 index 00000000000..8db2fbb60ee --- /dev/null +++ b/tests/target/macros.rs @@ -0,0 +1,917 @@ +// rustfmt-normalize_comments: true +itemmacro!(this, is.now().formatted(yay)); + +itemmacro!( + really, + long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() + .is + .formatted() +); + +itemmacro!{this, is.bracket().formatted()} + +peg_file! modname("mygrammarfile.rustpeg"); + +fn main() { + foo!(); + + bar!(a, b, c); + + bar!(a, b, c,); + + baz!(1 + 2 + 3, quux.kaas()); + + quux!( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + ); + + kaas!( + // comments + a, // post macro + b // another + ); + + trailingcomma!(a, b, c,); + // Preserve trailing comma only when necessary. + ok!(file.seek(SeekFrom::Start( + table.map(|table| fixture.offset(table)).unwrap_or(0), + ))); + + noexpr!( i am not an expression, OK? ); + + vec![a, b, c]; + + vec![ + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + AAAAAA, + BBBBB, + 5, + 100 - 30, + 1.33, + b, + b, + b, + ]; + + vec![a /* comment */]; + + // Trailing spaces after a comma + vec![a]; + + vec![a; b]; + vec![a; b]; + vec![a; b]; + + vec![a, b; c]; + vec![a; b, c]; + + vec![ + a; + (|x| { + let y = x + 1; + let z = y + 1; + z + })(2) + ]; + vec![ + a; + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + ]; + vec![a; unsafe { x + 1 }]; + + unknown_bracket_macro__comma_should_not_be_stripped![a,]; + + foo(makro!(1, 3)); + + hamkaas!{ () }; + + macrowithbraces! {dont, format, me} + + x!(fn); + + some_macro!(); + + some_macro![]; + + some_macro!{ + // comment + }; + + some_macro!{ + // comment + }; + + some_macro!( + // comment + not function like + ); + + // #1712 + let image = gray_image!( + 00, 01, 02; + 10, 11, 12; + 20, 21, 22); + + // #1092 + chain!(input, a: take!(max_size), || []); +} + +impl X { + empty_invoc!{} +} + +fn issue_1279() { + println!("dsfs"); // a comment +} + +fn issue_1555() { + let hello = &format!( + "HTTP/1.1 200 OK\r\nServer: {}\r\n\r\n{}", + "65454654654654654654654655464", "4" + ); +} + +fn issue1178() { + macro_rules! foo { + (#[$attr: meta] $name: ident) => {}; + } + + foo!( + #[doc = "bar"] + baz + ); +} + +fn issue1739() { + sql_function!( + add_rss_item, + add_rss_item_t, + ( + a: types::Integer, + b: types::Timestamptz, + c: types::Text, + d: types::Text, + e: types::Text + ) + ); + + w.slice_mut(s![ + .., + init_size[1] - extreeeeeeeeeeeeeeeeeeeeeeeem..init_size[1], + .. + ]).par_map_inplace(|el| *el = 0.); +} + +fn issue_1885() { + let threads = people + .into_iter() + .map(|name| { + chan_select! { + rx.recv() => {} + } + }) + .collect::>(); +} + +fn issue_1917() { + mod x { + quickcheck! { + fn test(a: String, s: String, b: String) -> TestResult { + if a.find(&s).is_none() { + + TestResult::from_bool(true) + } else { + TestResult::discard() + } + } + } + } +} + +fn issue_1921() { + // Macro with tabs. + lazy_static! { + static ref ONE: u32 = 1; + static ref TWO: u32 = 2; + static ref THREE: u32 = 3; + static ref FOUR: u32 = { + let mut acc = 1; + acc += 1; + acc += 2; + acc + }; + } +} + +// #1577 +fn issue1577() { + let json = json!({ + "foo": "bar", + }); +} + +gfx_pipeline!(pipe { + vbuf: gfx::VertexBuffer = (), + out: gfx::RenderTarget = "Target0", +}); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); + assert_eq!( + ::std::mem::align_of::>(), + 8usize, + concat!( + "Alignment of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); +} + +// #878 +macro_rules! try_opt { + ($expr: expr) => { + match $expr { + Some(val) => val, + + None => { + return None; + } + } + }; +} + +// #2214 +// macro call whose argument is an array with trailing comma. +fn issue2214() { + make_test!( + str_searcher_ascii_haystack, + "bb", + "abbcbbd", + [ + Reject(0, 1), + Match(1, 3), + Reject(3, 4), + Match(4, 6), + Reject(6, 7), + ] + ); +} + +fn special_case_macros() { + let p = eprint!(); + let q = eprint!("{}", 1); + let r = eprint!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = eprint!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = eprintln!("{}", 1); + let r = eprintln!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = eprintln!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = format!("{}", 1); + let r = format!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = format!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = format_args!("{}", 1); + let r = format_args!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = format_args!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = print!("{}", 1); + let r = print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = print!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = println!("{}", 1); + let r = println!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = println!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + let q = unreachable!("{}", 1); + let r = unreachable!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + let s = unreachable!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + debug!("{}", 1); + debug!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + debug!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + error!("{}", 1); + error!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + error!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + info!("{}", 1); + info!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + info!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + panic!("{}", 1); + panic!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + panic!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + warn!("{}", 1); + warn!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 + ); + warn!( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + assert!(); + assert!(result == 42); + assert!(result == 42, "Ahoy there, {}!", target); + assert!( + result == 42, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected + ); + assert!( + result == 42, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + assert_eq!(); + assert_eq!(left); + assert_eq!(left, right); + assert_eq!(left, right, "Ahoy there, {}!", target); + assert_eq!( + left, right, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, input, expected + ); + assert_eq!( + first_realllllllllllly_long_variable_that_doesnt_fit_one_one_line, + second_reallllllllllly_long_variable_that_doesnt_fit_one_one_line, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected + ); + assert_eq!( + left + 42, + right, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, + input, + expected + ); + assert_eq!( + left, + right, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + write!(&mut s, "Ahoy there, {}!", target); + write!( + &mut s, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, input, expected + ); + write!( + &mut s, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); + + writeln!(&mut s, "Ahoy there, {}!", target); + writeln!( + &mut s, + "Arr! While plunderin' the hold, we got '{}' when given '{}' (we expected '{}')", + result, input, expected + ); + writeln!( + &mut s, + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ); +} + +// #1209 +impl Foo { + /// foo + pub fn foo(&self) -> Bar {} +} + +// #819 +fn macro_in_pattern_position() { + let x = match y { + foo!() => (), + bar!(a, b, c) => (), + bar!(a, b, c,) => (), + baz!(1 + 2 + 3, quux.kaas()) => (), + quux!( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + ) => (), + }; +} + +macro foo() {} + +pub macro bar($x: ident + $y: expr;) { + fn foo($x: Foo) { + long_function( + a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), + $x.bar($y), + ); + } +} + +macro foo() { + // a comment + fn foo() { + // another comment + bar(); + } +} + +macro lex_err($kind: ident $(, $body: expr)*) { + Err(QlError::LexError(LexError::$kind($($body,)*))) +} + +// Preserve trailing comma on item-level macro with `()` or `[]`. +methods![get, post, delete,]; +methods!(get, post, delete,); diff --git a/tests/target/markdown-comment-with-options.rs b/tests/target/markdown-comment-with-options.rs new file mode 100644 index 00000000000..ede2bc0d035 --- /dev/null +++ b/tests/target/markdown-comment-with-options.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: true + +// Preserve two trailing whitespaces in doc comment, +// but trim any whitespaces in normal comment. + +//! hello world +//! hello world + +/// hello world +/// hello world +/// hello world +fn foo() { + // hello world + // hello world + let x = 3; + println!("x = {}", x); +} diff --git a/tests/target/markdown-comment.rs b/tests/target/markdown-comment.rs new file mode 100644 index 00000000000..71a9921d286 --- /dev/null +++ b/tests/target/markdown-comment.rs @@ -0,0 +1,15 @@ +// Preserve two trailing whitespaces in doc comment, +// but trim any whitespaces in normal comment. + +//! hello world +//! hello world + +/// hello world +/// hello world +/// hello world +fn foo() { + // hello world + // hello world + let x = 3; + println!("x = {}", x); +} diff --git a/tests/target/match-block-trailing-comma.rs b/tests/target/match-block-trailing-comma.rs new file mode 100644 index 00000000000..44d1f289f8e --- /dev/null +++ b/tests/target/match-block-trailing-comma.rs @@ -0,0 +1,16 @@ +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + }, + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + } +} diff --git a/tests/target/match-nowrap-trailing-comma.rs b/tests/target/match-nowrap-trailing-comma.rs new file mode 100644 index 00000000000..19ef2144822 --- /dev/null +++ b/tests/target/match-nowrap-trailing-comma.rs @@ -0,0 +1,17 @@ +// rustfmt-match_arm_blocks: false +// rustfmt-match_block_trailing_comma: true +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => { + "line1"; + "line2" + }, + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + } +} diff --git a/tests/target/match-nowrap.rs b/tests/target/match-nowrap.rs new file mode 100644 index 00000000000..9e674b1e2f5 --- /dev/null +++ b/tests/target/match-nowrap.rs @@ -0,0 +1,13 @@ +// rustfmt-match_arm_blocks: false +// Match expressions, no unwrapping of block arms or wrapping of multiline +// expressions. + +fn foo() { + match x { + a => foo(), + b => ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs new file mode 100644 index 00000000000..72ffa966c01 --- /dev/null +++ b/tests/target/match.rs @@ -0,0 +1,495 @@ +// rustfmt-normalize_comments: true +// Match expressions. + +fn foo() { + // A match expression. + match x { + // Some comment. + a => foo(), + b if 0 < 42 => foo(), + c => { + // Another comment. + // Comment. + an_expression; + foo() + } + Foo(ref bar) => { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } + Pattern1 | Pattern2 | Pattern3 => false, + Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + | Paternnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => blah, + Patternnnnnnnnnnnnnnnnnnn + | Patternnnnnnnnnnnnnnnnnnn + | Patternnnnnnnnnnnnnnnnnnn + | Patternnnnnnnnnnnnnnnnnnn => meh, + + Patternnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnn if looooooooooooooooooong_guard => { + meh + } + + Patternnnnnnnnnnnnnnnnnnnnnnnnn | Patternnnnnnnnnnnnnnnnnnnnnnnnn + if looooooooooooooooooooooooooooooooooooooooong_guard => + { + meh + } + + // Test that earlier patterns can take the guard space + (aaaa, bbbbb, ccccccc, aaaaa, bbbbbbbb, cccccc, aaaa, bbbbbbbb, cccccc, dddddd) + | Patternnnnnnnnnnnnnnnnnnnnnnnnn + if loooooooooooooooooooooooooooooooooooooooooong_guard => {} + + _ => {} + ast::PathParameters::AngleBracketedParameters(ref data) + if data.lifetimes.len() > 0 || data.types.len() > 0 || data.bindings.len() > 0 => {} + } + + let whatever = match something { + /// DOC COMMENT! + Some(_) => 42, + // Comment on an attribute. + #[an_attribute] + // Comment after an attribute. + None => 0, + #[rustfmt_skip] + Blurb => { } + }; +} + +// Test that a match on an overflow line is laid out properly. +fn main() { + let sub_span = + match xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { + Some(sub_span) => Some(sub_span), + None => sub_span, + }; +} + +// Test that one-line bodies align. +fn main() { + match r { + Variableeeeeeeeeeeeeeeeee => ( + "variable", + vec!["id", "name", "qualname", "value", "type", "scopeid"], + true, + true, + ), + Enummmmmmmmmmmmmmmmmmmmm => ( + "enum", + vec!["id", "qualname", "scopeid", "value"], + true, + true, + ), + Variantttttttttttttttttttttttt => ( + "variant", + vec!["id", "name", "qualname", "type", "value", "scopeid"], + true, + true, + ), + }; + + match x { + y => { /*Block with comment. Preserve me.*/ } + z => { + stmt(); + } + } +} + +fn matches() { + match 1 { + -1 => 10, + 1 => 1, // foo + 2 => 2, + // bar + 3 => 3, + _ => 0, // baz + } +} + +fn match_skip() { + let _ = match Some(1) { + #[rustfmt_skip] + Some( n ) => n, + None => 1, + }; +} + +fn issue339() { + match a { + b => {} + c => {} + d => {} + e => {} + // collapsing here is safe + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff => {} + // collapsing here exceeds line length + ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { + } + h => { + // comment above block + } + i => {} // comment below block + j => { + // comment inside block + } + j2 => { + // comments inside... + } // ... and after + // TODO uncomment when vertical whitespace is handled better + // k => { + // + // // comment with WS above + // } + // l => { + // // comment with ws below + // + // } + m => {} + n => {} + o => {} + p => { + // Dont collapse me + } + q => {} + r => {} + s => 0, // s comment + // t comment + t => 1, + u => 2, + v => {} /* funky block + * comment */ + /* final comment */ + } +} + +fn issue355() { + match mac { + a => println!("a", b), + b => vec![1, 2], + c => vec![3; 4], + d => println!("a", b), + e => vec![1, 2], + f => vec![3; 4], + h => println!("a", b), // h comment + i => vec![1, 2], // i comment + j => vec![3; 4], // j comment + // k comment + k => println!("a", b), + // l comment + l => vec![1, 2], + // m comment + m => vec![3; 4], + // Rewrite splits macro + nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn => { + println!("a", b) + } + // Rewrite splits macro + oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo => { + vec![1, 2] + } + // Macro support fails to recognise this macro as splittable + // We push the whole expr to a new line, TODO split this macro as well + pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp => { + vec![3; 4] + } + // q, r and s: Rewrite splits match arm + qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq => { + println!("a", b) + } + rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr => { + vec![1, 2] + } + ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss => { + vec![3; 4] + } + // Funky bracketing styles + t => println!{"a", b}, + u => vec![1, 2], + v => vec![3; 4], + w => println!["a", b], + x => vec![1, 2], + y => vec![3; 4], + // Brackets with comments + tc => println!{"a", b}, // comment + uc => vec![1, 2], // comment + vc => vec![3; 4], // comment + wc => println!["a", b], // comment + xc => vec![1, 2], // comment + yc => vec![3; 4], // comment + yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( + aaaaaaaaaa, + bbbbbbbbbb, + cccccccccc, + dddddddddd, + ), + } +} + +fn issue280() { + { + match x { + CompressionMode::DiscardNewline | CompressionMode::CompressWhitespaceNewline => { + ch == '\n' + } + ast::ItemConst(ref typ, ref expr) => { + self.process_static_or_const_item(item, &typ, &expr) + } + } + } +} + +fn issue383() { + match resolution.last_private { + LastImport { .. } => false, + _ => true, + }; +} + +fn issue507() { + match 1 { + 1 => unsafe { std::intrinsics::abort() }, + _ => (), + } +} + +fn issue508() { + match s.type_id() { + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLCanvasElement, + ))) => true, + Some(NodeTypeId::Element(ElementTypeId::HTMLElement( + HTMLElementTypeId::HTMLObjectElement, + ))) => s.has_object_data(), + Some(NodeTypeId::Element(_)) => false, + } +} + +fn issue496() { + { + { + { + match def { + def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { + match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) { + Some(const_expr) => x, + } + } + } + } + } + } +} + +fn issue494() { + { + match stmt.node { + hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { + result.push(StmtRef::Mirror(Box::new(Stmt { + span: stmt.span, + kind: StmtKind::Expr { + scope: cx.tcx.region_maps.node_extent(id), + expr: expr.to_ref(), + }, + }))) + } + } + } +} + +fn issue386() { + match foo { + BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true, + BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr + | BiShl | BiShr => false, + } +} + +fn guards() { + match foo { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if foooooooooooooo && barrrrrrrrrrrr => {} + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + if fooooooooooooooooooooo + && (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + || cccccccccccccccccccccccccccccccccccccccc) => {} + } +} + +fn issue1371() { + Some(match type_ { + sfEvtClosed => Closed, + sfEvtResized => { + let e = unsafe { *event.size.as_ref() }; + + Resized { + width: e.width, + height: e.height, + } + } + sfEvtLostFocus => LostFocus, + sfEvtGainedFocus => GainedFocus, + sfEvtTextEntered => TextEntered { + unicode: unsafe { + ::std::char::from_u32((*event.text.as_ref()).unicode) + .expect("Invalid unicode encountered on TextEntered event") + }, + }, + sfEvtKeyPressed => { + let e = unsafe { event.key.as_ref() }; + + KeyPressed { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + sfEvtKeyReleased => { + let e = unsafe { event.key.as_ref() }; + + KeyReleased { + code: unsafe { ::std::mem::transmute(e.code) }, + alt: e.alt.to_bool(), + ctrl: e.control.to_bool(), + shift: e.shift.to_bool(), + system: e.system.to_bool(), + } + } + }) +} + +fn issue1395() { + let bar = Some(true); + let foo = Some(true); + let mut x = false; + bar.and_then(|_| match foo { + None => None, + Some(b) => { + x = true; + Some(b) + } + }); +} + +fn issue1456() { + Ok(Recording { + artists: match reader.evaluate(".//mb:recording/mb:artist-credit/mb:name-credit")? { + Nodeset(nodeset) => { + let res: Result, ReadError> = nodeset + .iter() + .map(|node| { + XPathNodeReader::new(node, &context).and_then(|r| ArtistRef::from_xml(&r)) + }) + .collect(); + res? + } + _ => Vec::new(), + }, + }) +} + +fn issue1460() { + let _ = match foo { + REORDER_BUFFER_CHANGE_INTERNAL_SPEC_INSERT => { + "internal_spec_insert_internal_spec_insert_internal_spec_insert" + } + _ => "reorder_something", + }; +} + +fn issue525() { + foobar( + f, + "{}", + match *self { + TaskState::Started => "started", + TaskState::Success => "success", + TaskState::Failed => "failed", + }, + ); +} + +// #1838, #1839 +fn match_with_near_max_width() { + let (this_line_uses_99_characters_and_is_formatted_properly, x012345) = match some_expression { + _ => unimplemented!(), + }; + + let (should_be_formatted_like_the_line_above_using_100_characters, x0) = match some_expression { + _ => unimplemented!(), + }; + + let (should_put_the_brace_on_the_next_line_using_101_characters, x0000) = match some_expression + { + _ => unimplemented!(), + }; + match m { + Variant::Tag + | Variant::Tag2 + | Variant::Tag3 + | Variant::Tag4 + | Variant::Tag5 + | Variant::Tag6 => {} + } +} + +fn match_with_trailing_spaces() { + match x { + #![allow(simple_match)] + Some(..) => 0, + None => 1, + } +} + +fn issue_2099() { + let a = match x {}; + let b = match x {}; + + match x {} +} + +// #2021 +impl<'tcx> Const<'tcx> { + pub fn from_constval<'a>() -> Const<'tcx> { + let val = match *cv { + ConstVal::Variant(_) | ConstVal::Aggregate(..) | ConstVal::Unevaluated(..) => bug!( + "MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", + cv + ), + }; + } +} + +// #2151 +fn issue_2151() { + match either { + x => {} + y => (), + } +} + +// #2152 +fn issue_2152() { + match m { + "aaaaaaaaaaaaa" | "bbbbbbbbbbbbb" | "cccccccccccccccccccccccccccccccccccccccccccc" + if true => {} + "bind" | "writev" | "readv" | "sendmsg" | "recvmsg" if android && (aarch64 || x86_64) => { + true + } + } +} + +// #2462 +// Preserve a `|` at the beginning of a match arm. +fn match_with_beginning_vert() { + let x = Foo::A; + match x { + | Foo::A | Foo::B => println!("AB"), + | Foo::C => println!("C"), + } +} diff --git a/tests/target/max-line-length-in-chars.rs b/tests/target/max-line-length-in-chars.rs new file mode 100644 index 00000000000..d49fbb7e30e --- /dev/null +++ b/tests/target/max-line-length-in-chars.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 25 + +// абвгдеёжзийклмнопрст +fn main() {} diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs new file mode 100644 index 00000000000..a5d186c5df7 --- /dev/null +++ b/tests/target/mod-1.rs @@ -0,0 +1,38 @@ +// Deeply indented modules. + +mod foo { + mod bar { + mod baz {} + } +} + +mod foo { + mod bar { + mod baz { + fn foo() { + bar() + } + } + } + + mod qux {} +} + +mod boxed { + pub use std::boxed::{Box, HEAP}; +} + +pub mod x { + pub fn freopen( + filename: *const c_char, + mode: *const c_char, + mode2: *const c_char, + mode3: *const c_char, + file: *mut FILE, + ) -> *mut FILE { + } +} + +mod y { + // sup boooooiiii +} diff --git a/tests/target/mod-2.rs b/tests/target/mod-2.rs new file mode 100644 index 00000000000..1a093bd5201 --- /dev/null +++ b/tests/target/mod-2.rs @@ -0,0 +1,5 @@ +// Some nested mods + +#[cfg(test)] +mod nestedmod; +pub mod no_new_line_beginning; diff --git a/tests/target/mod_skip_child.rs b/tests/target/mod_skip_child.rs new file mode 100644 index 00000000000..d48c4a37e81 --- /dev/null +++ b/tests/target/mod_skip_child.rs @@ -0,0 +1,2 @@ +// rustfmt-skip_children: true +mod nested_skipped; diff --git a/tests/target/mulit-file.rs b/tests/target/mulit-file.rs new file mode 100644 index 00000000000..1f829b36f3f --- /dev/null +++ b/tests/target/mulit-file.rs @@ -0,0 +1,10 @@ +// Tests that where a single file is referred to in multiple places, we don't +// crash. + +#[cfg(all(foo))] +#[path = "closure.rs"] +pub mod imp; + +#[cfg(all(bar))] +#[path = "closure.rs"] +pub mod imp; diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs new file mode 100644 index 00000000000..0c330d80a56 --- /dev/null +++ b/tests/target/multiple.rs @@ -0,0 +1,178 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-format_strings: true +// Test of lots of random stuff. +// FIXME split this into multiple, self-contained tests. + +#[attr1] +extern crate foo; +#[attr2] +#[attr3] +extern crate foo; +#[attr1] +extern crate foo; +#[attr2] +#[attr3] +extern crate foo; + +use std::cell::*; +use std::{self, any, ascii, borrow, borrow, borrow, borrow, borrow, borrow, borrow, borrow, + borrow, borrow, borrow, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, boxed, + boxed, char, char, char, char, char, char, char, char, char, char}; + +mod doc; +mod other; + +// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff +// ffffffffffffffffffffffffffffffffffffffffff + +fn foo(a: isize, b: u32 /* blah blah */, c: f64) {} + +fn foo() -> Box +where + 'a: 'b, + for<'a> D<'b>: 'a, +{ + hello!() +} + +fn baz< + 'a: 'b, // comment on 'a + T: SomsssssssssssssssssssssssssssssssssssssssssssssssssssssseType, // comment on T +>( + a: A, + b: B, // comment on b + c: C, +) -> Bob { + #[attr1] + extern crate foo; + #[attr2] + #[attr3] + extern crate foo; + #[attr1] + extern crate foo; + #[attr2] + #[attr3] + extern crate foo; +} + +#[rustfmt_skip] +fn qux(a: dadsfa, // Comment 1 + b: sdfasdfa, // Comment 2 + c: dsfdsafa) // Comment 3 +{ + +} + +/// Blah blah blah. +impl Bar { + fn foo( + &mut self, + a: sdfsdfcccccccccccccccccccccccccccccccccccccccccccccccccc, // comment on a + b: sdfasdfsdfasfs, // closing comment + ) -> isize { + } + + /// Blah blah blah. + pub fn f2(self) { + (foo, bar) + } + + #[an_attribute] + fn f3(self) -> Dog {} +} + +/// The `nodes` and `edges` method each return instantiations of +/// `Cow<[T]>` to leave implementers the freedom to create + +/// entirely new vectors or to pass back slices into internally owned +/// vectors. +pub trait GraphWalk<'a, N, E> { + /// Returns all the nodes in this graph. + fn nodes(&'a self) -> Nodes<'a, N>; + /// Returns all of the edges in this graph. + fn edges(&'a self) -> Edges<'a, E>; + /// The source node for `edge`. + fn source(&'a self, edge: &E) -> N; + /// The target node for `edge`. + fn target(&'a self, edge: &E) -> N; +} + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, +} + +struct Bar; + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +fn foo(ann: &'a (PpAnn + 'a)) {} + +fn main() { + for i in 0i32..4 { + println!("{}", i); + } + + while true { + hello(); + } + + let rc = Cell::new( + 42usize, + 42usize, + Cell::new( + 42usize, + remaining_widthremaining_widthremaining_widthremaining_width, + ), + 42usize, + ); + let rc = RefCell::new(42usize, remaining_width, remaining_width); // a comment + let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \ + abcd abcd"; + let s = expand(a, b); +} + +fn deconstruct() -> ( + SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { +} + +fn deconstruct( + foo: Bar, +) -> ( + SocketAddr, + Method, + Headers, + RequestUri, + HttpVersion, + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +) { +} + +#[rustfmt_skip] +mod a{ +fn foo(x: T) { + let x: T = dfasdf; +} +} diff --git a/tests/target/nested-if-else.rs b/tests/target/nested-if-else.rs new file mode 100644 index 00000000000..9a54789ddcd --- /dev/null +++ b/tests/target/nested-if-else.rs @@ -0,0 +1,11 @@ +fn issue1518() { + Some(Object { + field: if a { + a_thing + } else if b { + b_thing + } else { + c_thing + }, + }) +} diff --git a/tests/target/nested-visual-block.rs b/tests/target/nested-visual-block.rs new file mode 100644 index 00000000000..95b9bc2dea2 --- /dev/null +++ b/tests/target/nested-visual-block.rs @@ -0,0 +1,59 @@ +fn main() { + // #1078 + let items = itemize_list( + context.codemap, + field_iter, + "}", + |item| match *item { + StructLitField::Regular(ref field) => field.span.lo(), + StructLitField::Base(ref expr) => { + let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); + let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo())); + let pos = snippet.find_uncommented("..").unwrap(); + last_field_hi + BytePos(pos as u32) + } + }, + |item| match *item { + StructLitField::Regular(ref field) => field.span.hi(), + StructLitField::Base(ref expr) => expr.span.hi(), + }, + |item| { + match *item { + StructLitField::Regular(ref field) => rewrite_field( + inner_context, + &field, + &Constraints::new(v_budget.checked_sub(1).unwrap_or(0), indent), + ), + StructLitField::Base(ref expr) => { + // 2 = .. + expr.rewrite( + inner_context, + &Constraints::new(try_opt!(v_budget.checked_sub(2)), indent + 2), + ).map(|s| format!("..{}", s)) + } + } + }, + context.codemap.span_after(span, "{"), + span.hi(), + ); + + // #1580 + self.0.pool.execute(move || { + let _timer = segments.0.rotate_timer.time(); + if let Err(e) = segments.rotate_async(wal) { + error!("error compacting segment storage WAL", unsafe { error: e.display() }); + } + }); + + // #1581 + bootstrap.checks.register("PERSISTED_LOCATIONS", move || { + if locations2.0.inner_mut.lock().poisoned { + Check::new( + State::Error, + "Persisted location storage is poisoned due to a write failure", + ) + } else { + Check::new(State::Healthy, "Persisted location storage is healthy") + } + }); +} diff --git a/tests/target/nested_skipped/mod.rs b/tests/target/nested_skipped/mod.rs new file mode 100644 index 00000000000..0ab6f081e44 --- /dev/null +++ b/tests/target/nested_skipped/mod.rs @@ -0,0 +1,3 @@ +fn ugly() { + 92; +} diff --git a/tests/target/nestedmod/mod.rs b/tests/target/nestedmod/mod.rs new file mode 100644 index 00000000000..1df46293184 --- /dev/null +++ b/tests/target/nestedmod/mod.rs @@ -0,0 +1,12 @@ +mod mod2a; +mod mod2b; + +mod mymod1 { + use mod2a::{Bar, Foo}; + mod mod3a; +} + +#[path = "mod2c.rs"] +mod mymod2; + +mod submod2; diff --git a/tests/target/nestedmod/mod2a.rs b/tests/target/nestedmod/mod2a.rs new file mode 100644 index 00000000000..5df457a8316 --- /dev/null +++ b/tests/target/nestedmod/mod2a.rs @@ -0,0 +1,4 @@ +// This is an empty file containing only +// comments + +// ................... diff --git a/tests/target/nestedmod/mod2b.rs b/tests/target/nestedmod/mod2b.rs new file mode 100644 index 00000000000..9b6ea844e65 --- /dev/null +++ b/tests/target/nestedmod/mod2b.rs @@ -0,0 +1,2 @@ +#[path = "mod2a.rs"] +mod c; diff --git a/tests/target/nestedmod/mod2c.rs b/tests/target/nestedmod/mod2c.rs new file mode 100644 index 00000000000..7db4572e777 --- /dev/null +++ b/tests/target/nestedmod/mod2c.rs @@ -0,0 +1,3 @@ +// A standard mod + +fn a() {} diff --git a/tests/target/nestedmod/mymod1/mod3a.rs b/tests/target/nestedmod/mymod1/mod3a.rs new file mode 100644 index 00000000000..ae09d8ddac0 --- /dev/null +++ b/tests/target/nestedmod/mymod1/mod3a.rs @@ -0,0 +1,2 @@ +// Another mod +fn a() {} diff --git a/tests/target/nestedmod/submod2/a.rs b/tests/target/nestedmod/submod2/a.rs new file mode 100644 index 00000000000..120b17145e3 --- /dev/null +++ b/tests/target/nestedmod/submod2/a.rs @@ -0,0 +1,6 @@ +// Yet Another mod +// Nested + +use c::a; + +fn foo() {} diff --git a/tests/target/nestedmod/submod2/mod.rs b/tests/target/nestedmod/submod2/mod.rs new file mode 100644 index 00000000000..52f8be91022 --- /dev/null +++ b/tests/target/nestedmod/submod2/mod.rs @@ -0,0 +1,5 @@ +// Another mod + +mod a; + +use a::a; diff --git a/tests/target/no_new_line_beginning.rs b/tests/target/no_new_line_beginning.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/target/no_new_line_beginning.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/target/other.rs b/tests/target/other.rs new file mode 100644 index 00000000000..dfce84fcdc4 --- /dev/null +++ b/tests/target/other.rs @@ -0,0 +1,5 @@ +// Part of multiple.rs + +fn bob() { + println!("hello other!"); +} diff --git a/tests/target/paths.rs b/tests/target/paths.rs new file mode 100644 index 00000000000..0d2ba797eb7 --- /dev/null +++ b/tests/target/paths.rs @@ -0,0 +1,28 @@ +// rustfmt-normalize_comments: true + +fn main() { + let constellation_chan = + Constellation::::start( + compositor_proxy, + resource_task, + image_cache_task, + font_cache_task, + time_profiler_chan, + mem_profiler_chan, + devtools_chan, + storage_task, + supports_clipboard, + ); + + Quux::< + ParamOne, // Comment 1 + ParamTwo, // Comment 2 + >::some_func(); + + <*mut JSObject>::relocate(entry); + + let x: Foo; + let x: Foo/*::*/; +} + +fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {} diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs new file mode 100644 index 00000000000..39f99d9e123 --- /dev/null +++ b/tests/target/pattern-condense-wildcards.rs @@ -0,0 +1,12 @@ +// rustfmt-normalize_comments: true +// rustfmt-condense_wildcard_suffixes: true + +fn main() { + match x { + Butt(..) => "hah", + Tup(_) => "nah", + Quad(_, _, x, _) => " also no rewrite", + Quad(x, ..) => "condense me pls", + Weird(x, _, _, /* dont condense before */ ..) => "pls work", + } +} diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs new file mode 100644 index 00000000000..6c62affb848 --- /dev/null +++ b/tests/target/pattern.rs @@ -0,0 +1,77 @@ +// rustfmt-normalize_comments: true +fn main() { + let z = match x { + "pat1" => 1, + (ref x, ref mut y /* comment */) => 2, + }; + + if let ::CONST = ident { + do_smth(); + } + + let Some(ref xyz /* comment! */) = opt; + + if let None = opt2 { + panic!("oh noes"); + } + + let foo @ bar(f) = 42; + let a::foo(..) = 42; + let [] = 42; + let [a.., b, c] = 42; + let [a, b, c..] = 42; + let [a, b, c, d.., e, f, g] = 42; + let foo {} = 42; + let foo { .. } = 42; + let foo { x, y: ref foo, .. } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. + } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + } = 42; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + .. + }; + let foo { + x, + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, + }; +} + +impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { + fn mutate_fragment(&mut self, fragment: &mut Fragment) { + match **info { + GeneratedContentInfo::ContentItem(ContentItem::Counter( + ref counter_name, + counter_style, + )) => {} + } + } +} + +fn issue_1319() { + if let (Event { .. }, ..) = ev_state {} +} + +fn issue_1874() { + if let Some(()) = x { + y + } +} + +fn combine_patterns() { + let x = match y { + Some(Some(Foo { + z: Bar(..), + a: Bar(..), + b: Bar(..), + })) => z, + _ => return, + }; +} diff --git a/tests/target/pub-restricted.rs b/tests/target/pub-restricted.rs new file mode 100644 index 00000000000..8cc2ade612a --- /dev/null +++ b/tests/target/pub-restricted.rs @@ -0,0 +1,64 @@ +pub(super) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(crate) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +crate enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(in global::path::to::some_mod) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} + +pub(in local::path::to::some_mod) enum WriteState { + WriteId { + id: U64Writer, + size: U64Writer, + payload: Option>, + }, + WriteSize { + size: U64Writer, + payload: Option>, + }, + WriteData(Writer), +} diff --git a/tests/target/remove_blank_lines.rs b/tests/target/remove_blank_lines.rs new file mode 100644 index 00000000000..89b18e40b83 --- /dev/null +++ b/tests/target/remove_blank_lines.rs @@ -0,0 +1,28 @@ +fn main() { + let x = 1; + + let y = 2; + + println!("x + y = {}", x + y); +} + +fn foo() { + #![attribute] + + let x = 1; + + // comment +} +// comment after item + +// comment before item +fn bar() { + let x = 1; + // comment after statement + + // comment before statment + let y = 2; + let z = 3; + + println!("x + y + z = {}", x + y + z); +} diff --git a/tests/target/single-line-if-else.rs b/tests/target/single-line-if-else.rs new file mode 100644 index 00000000000..98fd793cba2 --- /dev/null +++ b/tests/target/single-line-if-else.rs @@ -0,0 +1,58 @@ +// Format if-else expressions on a single line, when possible. + +fn main() { + let a = if 1 > 2 { unreachable!() } else { 10 }; + + let a = if x { + 1 + } else if y { + 2 + } else { + 3 + }; + + let b = if cond() { + 5 + } else { + // Brief comment. + 10 + }; + + let c = if cond() { + statement(); + + 5 + } else { + 10 + }; + + let d = if let Some(val) = turbo { + "cool" + } else { + "beans" + }; + + if cond() { + statement(); + } else { + other_statement(); + } + + if true { + do_something() + } + + let x = if veeeeeeeeery_loooooong_condition() { + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + } else { + bbbbbbbbbb + }; + + let x = if veeeeeeeeery_loooooong_condition() { + aaaaaaaaaaaaaaaaaaaaaaaaa + } else { + bbbbbbbbbb + }; + + funk(if test() { 1 } else { 2 }, arg2); +} diff --git a/tests/target/skip.rs b/tests/target/skip.rs new file mode 100644 index 00000000000..28897ade56f --- /dev/null +++ b/tests/target/skip.rs @@ -0,0 +1,87 @@ +// Test the skip attribute works + +#[rustfmt_skip] +fn foo() { badly; formatted; stuff +; } + +#[rustfmt_skip] +trait Foo +{ +fn foo( +); +} + +impl LateLintPass for UsedUnderscoreBinding { + #[cfg_attr(rustfmt, rustfmt_skip)] + fn check_expr() { // comment + } +} + +fn issue1346() { + #[cfg_attr(rustfmt, rustfmt_skip)] + Box::new(self.inner.call(req).then(move |result| { + match result { + Ok(resp) => Box::new(future::done(Ok(resp))), + Err(e) => { + try_error!(clo_stderr, "{}", e); + Box::new(future::err(e)) + } + } + })) +} + +fn skip_on_statements() { + // Outside block + #[rustfmt_skip] + { + foo; bar; + // junk + } + + { + // Inside block + #![rustfmt_skip] + foo; bar; + // junk + } + + // Semi + #[cfg_attr(rustfmt, rustfmt_skip)] + foo( + 1, 2, 3, 4, + 1, 2, + 1, 2, 3, + ); + + // Local + #[cfg_attr(rustfmt, rustfmt_skip)] + let x = foo( a, b , c); + + // Item + #[cfg_attr(rustfmt, rustfmt_skip)] + use foobar ; + + // Mac + #[cfg_attr(rustfmt, rustfmt_skip)] + vec![ + 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, 4, + 1, 2, 3, + 1, + 1, 2, + 1, + ]; + + // Expr + #[cfg_attr(rustfmt, rustfmt_skip)] + foo( a, b , c) +} + +// Check that the skip attribute applies to other attributes. +#[rustfmt_skip] +#[cfg +( a , b +)] +fn +main() {} diff --git a/tests/target/skip_mod.rs b/tests/target/skip_mod.rs new file mode 100644 index 00000000000..38ece8f070d --- /dev/null +++ b/tests/target/skip_mod.rs @@ -0,0 +1,3 @@ +#![rustfmt_skip] +use a :: b +; diff --git a/tests/target/soft-wrapping.rs b/tests/target/soft-wrapping.rs new file mode 100644 index 00000000000..58f3557fbe2 --- /dev/null +++ b/tests/target/soft-wrapping.rs @@ -0,0 +1,15 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 80 +// Soft wrapping for comments. + +// #535, soft wrapping for comments +// Compare the lowest `f32` of both inputs for greater than or equal. The +// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +// ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits +// off the result are the upper 96 bits of `a`. + +/// Compare the lowest `f32` of both inputs for greater than or equal. The +/// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is +/// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits +/// off the result are the upper 96 bits of `a`. +fn foo() {} diff --git a/tests/target/space-not-before-newline.rs b/tests/target/space-not-before-newline.rs new file mode 100644 index 00000000000..9d75b726aa0 --- /dev/null +++ b/tests/target/space-not-before-newline.rs @@ -0,0 +1,8 @@ +struct Foo { + a: (), + // spaces ^^^ to be removed +} +enum Foo { + Bar, + // spaces ^^^ to be removed +} diff --git a/tests/target/spaces-around-ranges.rs b/tests/target/spaces-around-ranges.rs new file mode 100644 index 00000000000..b53e5b58b8c --- /dev/null +++ b/tests/target/spaces-around-ranges.rs @@ -0,0 +1,15 @@ +// rustfmt-spaces_around_ranges: true + +fn bar(v: &[u8]) {} + +fn foo() { + let a = vec![0; 20]; + for j in 0 ..= 20 { + for i in 0 .. 3 { + bar(a[i .. j]); + bar(a[i ..]); + bar(a[.. j]); + bar(a[..= (j + 1)]); + } + } +} diff --git a/tests/target/static.rs b/tests/target/static.rs new file mode 100644 index 00000000000..5daccf3e7f7 --- /dev/null +++ b/tests/target/static.rs @@ -0,0 +1,27 @@ +const FILE_GENERIC_READ: DWORD = + STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; + +static boolnames: &'static [&'static str] = &[ + "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", + "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", + "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", + "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr", +]; + +static mut name: SomeType = + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + +pub static count: u8 = 10; + +pub const test: &Type = &val; + +impl Color { + pub const WHITE: u32 = 10; +} + +// #1391 +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: NTSTATUS = + 0 as usize; + +pub const XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX: + Yyyyyyyyyyyyyyyyyyyyyyyyyyyy = 1; diff --git a/tests/target/string-lit-2.rs b/tests/target/string-lit-2.rs new file mode 100644 index 00000000000..6b95e25a052 --- /dev/null +++ b/tests/target/string-lit-2.rs @@ -0,0 +1,25 @@ +fn main() -> &'static str { + let too_many_lines = "Hello"; + let leave_me = "sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\ + s + jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"; +} + +fn issue_1237() { + let msg = "eedadn\n\ + drvtee\n\ + eandsr\n\ + raavrd\n\ + atevrs\n\ + tsrnev\n\ + sdttsa\n\ + rasrtv\n\ + nssdts\n\ + ntnada\n\ + svetve\n\ + tesnvt\n\ + vntsnd\n\ + vrdear\n\ + dvrsen\n\ + enarar"; +} diff --git a/tests/target/string-lit-custom.rs b/tests/target/string-lit-custom.rs new file mode 100644 index 00000000000..50ebb97491b --- /dev/null +++ b/tests/target/string-lit-custom.rs @@ -0,0 +1,22 @@ +// rustfmt-format_strings: false + +fn main() { + let expected = "; ModuleID = \'foo\' + +; Function Attrs: nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 + +declare i32 @write(i32, i8*, i32) + +declare i32 @putchar(i32) + +declare i32 @getchar() + +define i32 @main() { +entry: + ret i32 0 +} + +attributes #0 = { nounwind } +"; +} diff --git a/tests/target/string-lit.rs b/tests/target/string-lit.rs new file mode 100644 index 00000000000..f60002ac618 --- /dev/null +++ b/tests/target/string-lit.rs @@ -0,0 +1,64 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false +// Long string literals + +fn main() -> &'static str { + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAaAA \ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaAa"; + let str = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let too_many_lines = "Hello"; + + // Make sure we don't break after an escape character. + let odd_length_name = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + let even_length_name = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; + + let really_long_variable_name = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + + let raw_string = r#"Do +not +remove +formatting"#; + + filename.replace(" ", "\\"); + + let xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx = + funktion("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); + + let unicode = "a̐éö̲\r\n"; + let unicode2 = "Löwe 老虎 Léopard"; + let unicode3 = "中华Việt Nam"; + let unicode4 = "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + + "stuffin'" +} + +fn issue682() { + let a = "hello \\ o/"; + let b = a.replace("\\ ", "\\"); +} + +fn issue716() { + println!( + "forall x. mult(e(), x) = x /\\ + forall x. mult(x, x) = e()" + ); +} + +fn issue_1282() { + { + match foo { + Permission::AndroidPermissionAccessLocationExtraCommands => { + "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" + } + } + } +} + +// #1987 +#[link_args = "-s NO_FILESYSTEM=1 -s NO_EXIT_RUNTIME=1 -s EXPORTED_RUNTIME_METHODS=[\"_malloc\"] \ + -s NO_DYNAMIC_EXECUTION=1 -s ELIMINATE_DUPLICATE_FUNCTIONS=1 -s EVAL_CTORS=1"] +extern "C" {} diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs new file mode 100644 index 00000000000..1cc73d14060 --- /dev/null +++ b/tests/target/string_punctuation.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-error_on_line_overflow: false + +fn main() { + println!( + "ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:\ + Likethisssssssssssss" + ); + format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); + println!( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;\ + adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ + ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea" + ); +} diff --git a/tests/target/struct-field-attributes.rs b/tests/target/struct-field-attributes.rs new file mode 100644 index 00000000000..5d6e92a91d9 --- /dev/null +++ b/tests/target/struct-field-attributes.rs @@ -0,0 +1,56 @@ +// #1535 +#![feature(struct_field_attributes)] + +struct Foo { + bar: u64, + + #[cfg(test)] + qux: u64, +} + +fn do_something() -> Foo { + Foo { + bar: 0, + + #[cfg(test)] + qux: 1, + } +} + +fn main() { + do_something(); +} + +// #1462 +struct Foo { + foo: usize, + #[cfg(feature = "include-bar")] + bar: usize, +} + +fn new_foo() -> Foo { + Foo { + foo: 0, + #[cfg(feature = "include-bar")] + bar: 0, + } +} + +// #2044 +pub enum State { + Closure( + #[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] + GcPtr, + ), +} + +struct Fields( + #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] + Arc>, +); + +// #2309 +pub struct A { + #[doc = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"] + pub foos: Vec, +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs new file mode 100644 index 00000000000..648c723d357 --- /dev/null +++ b/tests/target/struct_lits.rs @@ -0,0 +1,191 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: f(), + b: b(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a: Bar, b: f() }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { memb: 10 }; +} + +fn issue201() { + let s = S { a: 0, ..b }; +} + +fn issue201_2() { + let s = S { a: S2 { ..c }, ..b }; +} + +fn issue278() { + let s = S { + a: 0, + // + b: 0, + }; + let s1 = S { + a: 0, + // foo + // + // bar + b: 0, + }; +} + +fn struct_exprs() { + Foo { a: 1, b: f(2) }; + Foo { + a: 1, + b: f(2), + ..g(3) + }; + LoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongStruct { + ..base + }; + IntrinsicISizesContribution { + content_intrinsic_sizes: IntrinsicISizes { + minimum_inline_size: 0, + }, + }; +} + +fn issue123() { + Foo { a: b, c: d, e: f }; + + Foo { + a: bb, + c: dd, + e: ff, + }; + + Foo { + a: ddddddddddddddddddddd, + b: cccccccccccccccccccccccccccccccccccccc, + }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; + + Foo { + arm: 0, // Comment + }; + + Foo { + a: aaaaaaaaaa, + b: bbbbbbbb, + c: cccccccccc, + d: dddddddddd, // a comment + e: eeeeeeeee, + }; +} + +fn issue698() { + Record { + ffffffffffffffffffffffffffields: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; + Record { + ffffffffffffffffffffffffffields: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + } +} + +fn issue835() { + MyStruct {}; + MyStruct { /* a comment */ }; + MyStruct { + // Another comment + }; + MyStruct {} +} + +fn field_init_shorthand() { + MyStruct { x, y, z }; + MyStruct { x, y, z, ..base }; + Foo { + aaaaaaaaaa, + bbbbbbbb, + cccccccccc, + dddddddddd, // a comment + eeeeeeeee, + }; + Record { + ffffffffffffffffffffffffffieldsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + }; +} diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs new file mode 100644 index 00000000000..c831dc7a8ba --- /dev/null +++ b/tests/target/struct_lits_multiline.rs @@ -0,0 +1,117 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-struct_lit_single_line: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { + a: x, + }; + + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { + a: Bar, + b: foo(), + }; + + Quux { + x: if cond { + bar(); + }, + y: baz(), + }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, + }; + + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + })); + + Diagram { + // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, + } +} + +fn matcher() { + TagTerminatedByteMatcher { + matcher: ByteMatcher { + pattern: b" { + memb: T, + } + let foo = Foo:: { + memb: 10, + }; +} + +fn issue201() { + let s = S { + a: 0, + ..b + }; +} + +fn issue201_2() { + let s = S { + a: S2 { + ..c + }, + ..b + }; +} + +fn issue491() { + Foo { + guard: None, + arm: 0, // Comment + }; +} diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs new file mode 100644 index 00000000000..7e93b91d8c1 --- /dev/null +++ b/tests/target/struct_lits_visual.rs @@ -0,0 +1,50 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: f(), b: b() }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* Comment */ + // Comment + b: bar(), /* Comment */ }; + + Foo { a: Bar, b: f() }; + + Quux { x: if cond { + bar(); + }, + y: baz(), }; + + Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + z: zzzzz, /* test */ }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +} diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs new file mode 100644 index 00000000000..2809d3a2612 --- /dev/null +++ b/tests/target/struct_lits_visual_multiline.rs @@ -0,0 +1,50 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-indent_style: Visual +// rustfmt-struct_lit_single_line: false +// rustfmt-error_on_line_overflow: false + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* Comment */ + // Comment + b: bar(), /* Comment */ }; + + Foo { a: Bar, + b: foo(), }; + + Quux { x: if cond { + bar(); + }, + y: baz(), }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +} diff --git a/tests/target/struct_tuple_visual.rs b/tests/target/struct_tuple_visual.rs new file mode 100644 index 00000000000..369feae71d2 --- /dev/null +++ b/tests/target/struct_tuple_visual.rs @@ -0,0 +1,37 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Visual +fn foo() { + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(f(), b()); + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(// Comment + foo(), /* Comment */ + // Comment + bar() /* Comment */); + + Foo(Bar, f()); + + Quux(if cond { + bar(); + }, + baz()); + + Baz(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + zzzzz /* test */); + + A(// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + Item); + + Diagram(// o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + G) +} diff --git a/tests/target/structs.rs b/tests/target/structs.rs new file mode 100644 index 00000000000..59a57a9b5b4 --- /dev/null +++ b/tests/target/structs.rs @@ -0,0 +1,332 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +/// A Doc comment +#[AnAttribute] +pub struct Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1095 +struct S { + t: T, +} + +// #1029 +pub struct Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +struct X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub struct Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +struct Bar; + +struct NewType(Type, OtherType); + +struct NewInt( + pub i32, + SomeType, // inline comment + T, // sup +); + +struct Qux< + 'a, + N: Clone + 'a, + E: Clone + 'a, + G: Labeller<'a, N, E> + GraphWalk<'a, N, E>, + W: Write + Copy, +>( + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Comment + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + #[AnAttr] + // Comment + /// Testdoc + G, + pub W, +); + +struct Tuple( + // Comment 1 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + // Comment 2 + BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, +); + +// With a where clause and generics. +pub struct Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +struct Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +struct Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +struct Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +struct Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +// Will this be a one-liner? +struct Tuple( + A, // Comment + B, +); + +pub struct State time::Timespec> { + now: F, +} + +pub struct State ()> { + now: F, +} + +pub struct State { + now: F, +} + +struct Palette { + /// A map of indices in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +struct FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(T); +struct Foo(T) +where + T: Copy, + T: Eq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +); +struct Foo( + TTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTTTT, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUUUUUUU, + TTTTTTTTTTTTTTTTTTT, + UUUUUUUUUUUUUUUUUUU, +) +where + T: PartialEq; +struct Foo( + TTTTTTTTTTTTTTTTT, // Foo + UUUUUUUUUUUUUUUUUUUUUUUU, // Bar + // Baz + TTTTTTTTTTTTTTTTTTT, + // Qux (FIXME #572 - doc comment) + UUUUUUUUUUUUUUUUUUU, +); + +mod m { + struct X + where + T: Sized, + { + a: T, + } +} + +struct Foo( + TTTTTTTTTTTTTTTTTTT, + /// Qux + UUUUUUUUUUUUUUUUUUU, +); + +struct Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +struct Foo {} +struct Foo {} +struct Foo { + // comment +} +struct Foo { + // trailing space -> +} +struct Foo { /* comment */ } +struct Foo( /* comment */ ); + +struct LongStruct { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +struct Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +struct Foo(String); + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +struct Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} + +// structs with long identifier +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +struct Looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{} +struct Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong +{ + x: i32, +} + +// structs with visibility, do not duplicate visibility (#2110). +pub(self) struct Foo {} +pub(super) struct Foo {} +pub(crate) struct Foo {} +pub(self) struct Foo(); +pub(super) struct Foo(); +pub(crate) struct Foo(); + +// #2125 +pub struct ReadinessCheckRegistry( + Mutex, Box ReadinessCheck + Sync + Send>>>, +); + +// #2144 unit struct with generics +struct MyBox; +struct MyBoxx +where + T: ?Sized, + S: Clone; + +// #2208 +struct Test { + /// foo + #[serde(default)] + pub join: Vec, + #[serde(default)] + pub tls: bool, +} diff --git a/tests/target/trailing-comma-never.rs b/tests/target/trailing-comma-never.rs new file mode 100644 index 00000000000..3df0c7950eb --- /dev/null +++ b/tests/target/trailing-comma-never.rs @@ -0,0 +1,31 @@ +// rustfmt-trailing_comma: Never + +enum X { + A, + B +} + +enum Y { + A, + B +} + +enum TupX { + A(u32), + B(i32, u16) +} + +enum TupY { + A(u32), + B(i32, u16) +} + +enum StructX { + A { s: u16 }, + B { u: u32, i: i32 } +} + +enum StructY { + A { s: u16 }, + B { u: u32, i: i32 } +} diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs new file mode 100644 index 00000000000..61b82035450 --- /dev/null +++ b/tests/target/trailing_commas.rs @@ -0,0 +1,103 @@ +// rustfmt-match_block_trailing_comma: true +// rustfmt-trailing_comma: Always + +fn main() { + match foo { + x => {}, + y => { + foo(); + }, + _ => x, + } +} + +fn f< + S, T, +>( + x: T, + y: S, +) -> T +where + T: P, + S: Q, +{ + x +} + +impl Trait for T +where + T: P, +{ + fn f(x: T) -> T + where + T: Q + R, + { + x + } +} + +struct Pair< + S, T, +> where + T: P, + S: P + Q, +{ + a: T, + b: S, +} + +struct TupPair< + S, T, +>(S, T,) +where + T: P, + S: P + Q; + +enum E< + S, T, +> where + S: P, + T: P, +{ + A { a: T, }, +} + +type Double< + T, +> where + T: P, + T: Q, += Pair< + T, T, +>; + +extern "C" { + fn f< + S, T, + >( + x: T, + y: S, + ) -> T + where + T: P, + S: Q; +} + +trait Q< + S, T, +> where + T: P, + S: R, +{ + fn f< + U, V, + >( + self, + x: T, + y: S, + z: U, + ) -> Self + where + U: P, + V: P; +} diff --git a/tests/target/trait.rs b/tests/target/trait.rs new file mode 100644 index 00000000000..133e8babedb --- /dev/null +++ b/tests/target/trait.rs @@ -0,0 +1,132 @@ +// Test traits + +trait Foo { + fn bar(x: i32) -> Baz { + Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; + + fn foo( + a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, + ) -> RetType; // Some comment + + fn baz(&mut self) -> i32; + + fn increment(&mut self, x: i32); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where + R: Read; +} + +pub trait WriteMessage { + fn write_message(&mut self, &FrontendMessage) -> io::Result<()>; +} + +trait Runnable { + fn handler(self: &Runnable); +} + +trait TraitWithExpr { + fn fn_with_expr(x: [i32; 1]); +} + +trait Test { + fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result + where + F: FnOnce(&mut Self) -> Result; +} + +trait T {} + +trait Foo { + type Bar: Baz; + type Inner: Foo = Box; +} + +trait ConstCheck: Foo +where + T: Baz, +{ + const J: i32; +} + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + T: Foo, +{ +} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + T: Foo, +{ +} + +trait FooBar + : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +where + J: Bar, +{ + fn test(); +} + +trait WhereList +where + T: Foo, + J: Bar, +{ +} + +trait X /* comment */ {} +trait Y // comment +{ +} + +// #2055 +pub trait Foo: +// A and C +A + C +// and B + + B +{} + +// #2158 +trait Foo { + type ItRev = > as UntypedTimeSeries>::IterRev; + type IteRev = + > as UntypedTimeSeries>::IterRev; +} + +// #2331 +trait MyTrait< + AAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBB, + CCCCCCCCCCCCCCCCCCCC, + DDDDDDDDDDDDDDDDDDDD, +> { + fn foo() {} +} + +// Trait aliases +trait FooBar = Foo + Bar; +trait FooBar = Foo + Bar; +trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAA = + BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAA = + BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = + FooBar; +trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA< + A, + B, + C, + D, + E, +> = FooBar; +#[rustfmt_skip] +trait FooBar = Foo + + Bar; diff --git a/tests/target/try-conversion.rs b/tests/target/try-conversion.rs new file mode 100644 index 00000000000..e16fba278d2 --- /dev/null +++ b/tests/target/try-conversion.rs @@ -0,0 +1,27 @@ +// rustfmt-use_try_shorthand: true + +fn main() { + let x = some_expr()?; + + let y = a.very + .loooooooooooooooooooooooooooooooooooooong() + .chain() + .inside() + .weeeeeeeeeeeeeee()? + .test() + .0 + .x; +} + +fn test() { + a? +} + +fn issue1291() { + fs::create_dir_all(&gitfiledir).chain_err(|| { + format!( + "failed to create the {} submodule directory for the workarea", + name + ) + })?; +} diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs new file mode 100644 index 00000000000..a22586284dc --- /dev/null +++ b/tests/target/tuple.rs @@ -0,0 +1,89 @@ +// Test tuple litterals + +fn foo() { + let a = (a, a, a, a, a); + let aaaaaaaaaaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + ); + let aaaaaaaaaaaaaaaaaaaaaa = ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaaaaaaaaaa, + aaaa, + ); + let a = (a,); + + let b = ( + // This is a comment + b, // Comment + b, /* Trailing comment */ + ); + + // #1063 + foo(x.0 .0); +} + +fn a() { + (( + aaaaaaaa, + aaaaaaaaaaaaa, + aaaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + aaaaaaaaaaaaaaaa, + aaaaaaaaaaaaaa, + ),) +} + +fn b() { + ( + ( + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ), + bbbbbbbbbbbbbbbbbb, + ) +} + +fn issue550() { + self.visitor.visit_volume( + self.level.sector_id(sector), + ( + floor_y, + if is_sky_flat(ceil_tex) { + from_wad_height(self.height_range.1) + } else { + ceil_y + }, + ), + ); +} + +fn issue775() { + if indent { + let a = mk_object(&[ + ("a".to_string(), Boolean(true)), + ( + "b".to_string(), + Array(vec![ + mk_object(&[("c".to_string(), String("\x0c\r".to_string()))]), + mk_object(&[("d".to_string(), String("".to_string()))]), + ]), + ), + ]); + } +} + +fn issue1725() { + bench_antialiased_lines!( + bench_draw_antialiased_line_segment_diagonal, + (10, 10), + (450, 450) + ); + bench_antialiased_lines!( + bench_draw_antialiased_line_segment_shallow, + (10, 10), + (450, 80) + ); +} diff --git a/tests/target/type-ascription.rs b/tests/target/type-ascription.rs new file mode 100644 index 00000000000..a2f082ba4b4 --- /dev/null +++ b/tests/target/type-ascription.rs @@ -0,0 +1,12 @@ +fn main() { + let xxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: SomeTrait; + + let xxxxxxxxxxxxxxx = + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + + x: u32 - 1u32 / 10f32: u32 +} diff --git a/tests/target/type.rs b/tests/target/type.rs new file mode 100644 index 00000000000..2f35e796512 --- /dev/null +++ b/tests/target/type.rs @@ -0,0 +1,31 @@ +// rustfmt-normalize_comments: true +fn types() { + let x: [Vec<_>] = []; + let y: *mut [SomeType; konst_funk()] = expr(); + let z: (/* #digits */ usize, /* exp */ i16) = funk(); + let z: (usize /* #digits */, i16 /* exp */) = funk(); +} + +struct F { + f: extern "C" fn(x: u8, ... /* comment */), + g: extern "C" fn(x: u8, /* comment */ ...), + h: extern "C" fn(x: u8, ...), + i: extern "C" fn( + x: u8, + // comment 4 + y: String, // comment 3 + z: Foo, + // comment + ... // comment 2 + ), +} + +fn issue_1006(def_id_to_string: for<'a, 'b> unsafe fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String) {} + +fn impl_trait_fn_1() -> impl Fn(i32) -> Option {} + +fn impl_trait_fn_2() -> impl Future {} + +fn issue_1234() { + do_parse!(name: take_while1!(is_token) >> (Header)) +} diff --git a/tests/target/type_alias.rs b/tests/target/type_alias.rs new file mode 100644 index 00000000000..862f9ecbeec --- /dev/null +++ b/tests/target/type_alias.rs @@ -0,0 +1,76 @@ +// rustfmt-normalize_comments: true + +type PrivateTest<'a, I> = ( + Box + 'a>, + Box + 'a>, +); + +pub type PublicTest<'a, I, O> = Result< + Vec, + Box + 'a>, + Box + 'a>, +>; + +pub type LongGenericListTest< + 'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A, + B, + C, +> = Option>; + +pub type Exactly100CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = Vec; + +pub type Exactly101CharsTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B> = + Vec; + +pub type Exactly100CharsToEqualTest<'a, 'b, 'c, 'd, LONGPARAMETERNAME, LONGPARAMETERNAME, A, B, C> = + Vec; + +pub type GenericsFitButNotEqualTest< + 'a, + 'b, + 'c, + 'd, + LONGPARAMETERNAME, + LONGPARAMETERNAME, + A1, + B, + C, +> = Vec; + +pub type CommentTest< + // Lifetime + 'a, + // Type + T, +> = (); + +pub type WithWhereClause +where + T: Clone, + LONGPARAMETERNAME: Clone + Eq + OtherTrait, += Option; + +pub type Exactly100CharstoEqualWhereTest +where + T: Clone + Ord + Eq + SomeOtherTrait, += Option; + +pub type Exactly101CharstoEqualWhereTest +where + T: Clone + Ord + Eq + SomeOtherTrait, += Option; + +type RegisterPlugin = unsafe fn(pt: *const c_char, plugin: *mut c_void, data: *mut CallbackData); + +// #1683 +pub type Between = + super::operators::Between, AsExpr>>; +pub type NotBetween = + super::operators::NotBetween, AsExpr>>; diff --git a/tests/target/unindent_if_else_cond_comment.rs b/tests/target/unindent_if_else_cond_comment.rs new file mode 100644 index 00000000000..98621b1eed1 --- /dev/null +++ b/tests/target/unindent_if_else_cond_comment.rs @@ -0,0 +1,27 @@ +// Comments on else block. See #1575. + +fn example() { + // `if` comment + if x { + foo(); + // `else if` comment + } else if y { + foo(); + // Comment on `else if`. + // Comment on `else if`. + } else if z { + bar(); + /* + * Multi line comment on `else if` + */ + } else if xx { + bar(); + /* Single line comment on `else if` */ + } else if yy { + foo(); + // `else` comment + } else { + foo(); + // Comment at the end of `else` block + }; +} diff --git a/tests/target/unions.rs b/tests/target/unions.rs new file mode 100644 index 00000000000..eb6c3ae7e15 --- /dev/null +++ b/tests/target/unions.rs @@ -0,0 +1,196 @@ +// rustfmt-normalize_comments: true +// rustfmt-wrap_comments: true + +/// A Doc comment +#[AnAttribute] +pub union Foo { + #[rustfmt_skip] + f : SomeType, // Comment beside a field + f: SomeType, // Comment beside a field + // Comment on a field + #[AnAttribute] + g: SomeOtherType, + /// A doc comment on a field + h: AThirdType, + pub i: TypeForPublicField, +} + +// #1029 +pub union Foo { + #[doc(hidden)] + // This will NOT get deleted! + bar: String, // hi +} + +// #1029 +union X { + // `x` is an important number. + #[allow(unused)] // TODO: use + x: u32, +} + +// #410 +#[allow(missing_docs)] +pub union Writebatch { + #[allow(dead_code)] // only used for holding the internal pointer + writebatch: RawWritebatch, + marker: PhantomData, +} + +// With a where clause and generics. +pub union Foo<'a, Y: Baz> +where + X: Whatever, +{ + f: SomeType, // Comment beside a field +} + +union Baz { + a: A, // Comment A + b: B, // Comment B + c: C, // Comment C +} + +union Baz { + a: A, // Comment A + + b: B, // Comment B + + c: C, // Comment C +} + +union Baz { + a: A, + + b: B, + c: C, + + d: D, +} + +union Baz { + // Comment A + a: A, + + // Comment B + b: B, + // Comment C + c: C, +} + +pub union State time::Timespec> { + now: F, +} + +pub union State ()> { + now: F, +} + +pub union State { + now: F, +} + +union Palette { + /// A map of indices in the palette to a count of pixels in approximately + /// that color + foo: i32, +} + +// Splitting a single line comment into a block previously had a misalignment +// when the field had attributes +union FieldsWithAttributes { + // Pre Comment + #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + // Another pre comment + #[attr1] + #[attr2] + pub id: usize, /* CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC + * CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC */ +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +mod m { + union X + where + T: Sized, + { + a: T, + } +} + +union Issue677 { + pub ptr: *const libc::c_void, + pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer), +} + +union Foo {} +union Foo {} +union Foo { + // comment +} +union Foo { + // trailing space -> +} +union Foo { /* comment */ } + +union LongUnion { + a: A, + the_quick_brown_fox_jumps_over_the_lazy_dog: + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, +} + +union Deep { + deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeep: + node::Handle>, Type, NodeType>, +} + +// #1364 +fn foo() { + convex_shape.set_point(0, &Vector2f { x: 400.0, y: 100.0 }); + convex_shape.set_point(1, &Vector2f { x: 500.0, y: 70.0 }); + convex_shape.set_point(2, &Vector2f { x: 450.0, y: 100.0 }); + convex_shape.set_point(3, &Vector2f { x: 580.0, y: 150.0 }); +} + +// Vertical alignment +union Foo { + aaaaa: u32, // a + + b: u32, // b + cc: u32, // cc + + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 1 + yy: u32, // comment2 + zzz: u32, // comment3 + + aaaaaa: u32, // comment4 + bb: u32, // comment5 + // separate + dd: u32, // comment7 + c: u32, // comment6 + + aaaaaaa: u32, /* multi + * line + * comment + */ + b: u32, // hi + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + // separate + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + please_do_not_push_this_comment3: u32, // comment3 + + do_not_push_this_comment1: u32, // comment1 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: u32, // 2 + // separate + please_do_not_push_this_comment3: u32, // comment3 +} diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs new file mode 100644 index 00000000000..1e83d5b3abc --- /dev/null +++ b/tests/target/where-clause-rfc.rs @@ -0,0 +1,128 @@ +// rustfmt-indent_style: Block + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) +where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) +where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape, +) where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape, +) where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, +) -> Option +where + T: FOo, + U: Bar, +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule( + node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, +) -> Option +where + T: FOo, +{ + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType + where + F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType +where + F: FnMut(Self::Item) -> bool, +{ +} + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) +where + A: LongTrait; + +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) +where + A: LongTrait1234; + +struct AlwaysOnNextLine +where + A: LongTrait, +{ + x: i32, +} + +pub trait SomeTrait +where + T: Something + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read + + FromStr, +{ +} + +// #2020 +impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { + fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) + where + F: for<'b> FnMut( + &mut ProbeContext<'b, 'gcx, 'tcx>, + ty::PolyTraitRef<'tcx>, + ty::AssociatedItem, + ), + { + // ... + } +} diff --git a/tests/target/where-clause.rs b/tests/target/where-clause.rs new file mode 100644 index 00000000000..def18a0c11a --- /dev/null +++ b/tests/target/where-clause.rs @@ -0,0 +1,107 @@ +// rustfmt-indent_style: Visual + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) + where T: FOo, + U: Bar +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, rule: &Rule, args: &[Arg], shape: &Shape) + where T: FOo +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape) + where T: FOo, + U: Bar +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape, + shape: &Shape) + where T: FOo +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape) + -> Option + where T: FOo, + U: Bar +{ + let mut effects = HashMap::new(); +} + +fn reflow_list_node_with_rule(node: &CompoundNode, + rule: &Rule, + args: &[Arg], + shape: &Shape) + -> Option + where T: FOo +{ + let mut effects = HashMap::new(); +} + +pub trait Test { + fn very_long_method_name(self, f: F) -> MyVeryLongReturnType + where F: FnMut(Self::Item) -> bool; + + fn exactly_100_chars1(self, f: F) -> MyVeryLongReturnType + where F: FnMut(Self::Item) -> bool; +} + +fn very_long_function_name(very_long_argument: F) -> MyVeryLongReturnType + where F: FnMut(Self::Item) -> bool +{ +} + +struct VeryLongTupleStructName(LongLongTypename, LongLongTypename, i32, i32) + where A: LongTrait; + +struct Exactly100CharsToSemicolon(LongLongTypename, i32, i32) where A: LongTrait1234; + +struct AlwaysOnNextLine + where A: LongTrait +{ + x: i32, +} + +pub trait SomeTrait + where T: Something + + Sync + + Send + + Display + + Debug + + Copy + + Hash + + Debug + + Display + + Write + + Read + + FromStr +{ +} + +// #2020 +impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { + fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) + where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, + ty::PolyTraitRef<'tcx>, + ty::AssociatedItem) + { + // ... + } +} diff --git a/tests/writemode/source/fn-single-line.rs b/tests/writemode/source/fn-single-line.rs new file mode 100644 index 00000000000..289dd9aa093 --- /dev/null +++ b/tests/writemode/source/fn-single-line.rs @@ -0,0 +1,80 @@ +// rustfmt-fn_single_line: true +// rustfmt-write_mode: checkstyle +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/tests/writemode/source/modified.rs b/tests/writemode/source/modified.rs new file mode 100644 index 00000000000..948beb348db --- /dev/null +++ b/tests/writemode/source/modified.rs @@ -0,0 +1,14 @@ +// rustfmt-write_mode: modified +// Test "modified" output + +fn +blah +() +{ } + + +#[cfg +( a , b +)] +fn +main() {} diff --git a/tests/writemode/target/checkstyle.xml b/tests/writemode/target/checkstyle.xml new file mode 100644 index 00000000000..30ab5ad7579 --- /dev/null +++ b/tests/writemode/target/checkstyle.xml @@ -0,0 +1,2 @@ + + diff --git a/tests/writemode/target/modified.txt b/tests/writemode/target/modified.txt new file mode 100644 index 00000000000..5c0539a665e --- /dev/null +++ b/tests/writemode/target/modified.txt @@ -0,0 +1,5 @@ +4 4 1 +fn blah() {} +10 5 2 +#[cfg(a, b)] +fn main() {} -- cgit 1.4.1-3-g733a5 From 0bd77f2681540123dcfc22590358a6619431022c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 2 Mar 2018 21:53:24 +0900 Subject: Do not reorder inline modules --- src/reorder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index d4bc36fc83f..a43f56d595b 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -23,7 +23,7 @@ use attr::filter_inline_attrs; use codemap::LineRangeUtils; use comment::combine_strs_with_missing_comments; use imports::{path_to_imported_ident, rewrite_import}; -use items::{rewrite_extern_crate, rewrite_mod}; +use items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; @@ -234,7 +234,7 @@ impl ReorderableItemKind { match item.node { _ if contains_macro_use_attr(item) => ReorderableItemKind::Other, ast::ItemKind::ExternCrate(..) => ReorderableItemKind::ExternCrate, - ast::ItemKind::Mod(..) => ReorderableItemKind::Mod, + ast::ItemKind::Mod(..) if is_mod_decl(item) => ReorderableItemKind::Mod, ast::ItemKind::Use(..) => ReorderableItemKind::Use, _ => ReorderableItemKind::Other, } -- cgit 1.4.1-3-g733a5 From 64f6372f3224f77a2ceb1eb9c0eefdcd3bfbe1e6 Mon Sep 17 00:00:00 2001 From: Bastien Orivel Date: Fri, 2 Mar 2018 15:20:26 +0100 Subject: Bump winapi to 0.3 --- Cargo.lock | 3 +-- Cargo.toml | 3 +-- src/utils.rs | 5 ++--- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 4d954128544..488b2bb52a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,7 +333,6 @@ dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,7 +345,7 @@ dependencies = [ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 74542c565c3..dfaf38876db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,5 +58,4 @@ lazy_static = "1.0.0" libc = "0.2.11" [target.'cfg(windows)'.dependencies] -kernel32-sys = "0.2.2" -winapi = "0.2.7" +winapi = { version = "0.3" } diff --git a/src/utils.rs b/src/utils.rs index 20b30089d70..5ec5ee18009 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -382,13 +382,12 @@ pub fn isatty() -> bool { } #[cfg(windows)] pub fn isatty() -> bool { - extern crate kernel32; extern crate winapi; unsafe { - let handle = kernel32::GetStdHandle(winapi::winbase::STD_OUTPUT_HANDLE); + let handle = winapi::um::processenv::GetStdHandle(winapi::um::winbase::STD_OUTPUT_HANDLE); let mut out = 0; - kernel32::GetConsoleMode(handle, &mut out) != 0 + winapi::um::consoleapi::GetConsoleMode(handle, &mut out) != 0 } } -- cgit 1.4.1-3-g733a5 From 078fbb0819281628e3768c88c6efc77b8c3732b0 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Mon, 5 Mar 2018 16:57:22 +0900 Subject: support dyn keyword(2506) --- src/types.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 7f96a2299a3..75c8f3eabd8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -616,7 +616,15 @@ impl Rewrite for ast::TraitRef { impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { - ast::TyKind::TraitObject(ref bounds, ..) => bounds.rewrite(context, shape), + ast::TyKind::TraitObject(ref bounds, tobj_syntax) => { + let res = bounds.rewrite(context, shape)?; + // we have to consider 'dyn' keyword is used or not!!! + if tobj_syntax == ast::TraitObjectSyntax::Dyn { + Some(format!("dyn {}", res)) + } else { + Some(res) + } + } ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { Mutability::Mutable => "*mut ", -- cgit 1.4.1-3-g733a5 From 93d454aed7996c7c66a2f7cfb7599de3ca6053d2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 5 Mar 2018 19:30:08 +0900 Subject: Only format code blocks in comments with rust syntax notation --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 8b148ccfc37..74a14511be8 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -395,7 +395,7 @@ fn rewrite_comment_inner( continue; } else { - inside_code_block = line.starts_with("```"); + inside_code_block = line.starts_with("```rust"); if result == opener { let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; -- cgit 1.4.1-3-g733a5 From 2eebe614c7ce829cf158e33ca4cce7c7cdda2217 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Fri, 16 Feb 2018 23:21:57 +0100 Subject: Attempt at checking for license (#209) I'm not quite sure how best to handle loading the license template from a path -- I mean obviously I know *how* to do it, but I'm not sure where to fit it in the codebase :) So this first attempt puts the license template directly into the config file. These are my misgivings about the license template config option as a path to a file (I'd love feedback if some of these are wrong or can be easily circumvented!): 1. I thought the obvious choice for the type of `license_template` in `create_config!` should be `PathBuf`, but `PathBuf` doesn't implement `FromStr` (yet? see https://github.com/rust-lang/rust/issues/44431), so it would have to be wrapped in a tuple struct, and I went down that road for a little while but then it seemed like too much ceremony for too little gain. 2. So a plain `String` then (which, mind you, also means the same `doc_hint()`, i.e. ``, not `` or something like that). The fact that it's a valid path will be checked once we try to read the file. 3. But where in the code should the license template be read? The obvious choice for me would be somewhere in `Config::from_toml()`, but since `Config` is defined via the `create_config!` macro, that would mean tight coupling between the macro invocation (which defines the configuration option `license_template`) and its definition (which would rely on the existence of that option to run the template loading code). 4. `license_template` could also be made a special option which is hardwired into the macro. This gets rid of the tight coupling, but special-casing one of the config options would make the code harder to navigate. 5. Instead, the macro could maybe be rewritten to allow for config options that load additional resources from files when the config is being parsed, but that's beyond my skill level I'm afraid (and probably overengineering the problem if it's only ever going to be used for this one option). 6. Finally, the file can be loaded at some later point in time, e.g. in `format_lines()`, right before `check_license()` is called. But to face a potential *IO* error at so late a stage, when the source files have already been parsed... I don't know, it doesn't feel right. BTW I don't like that I'm actually parsing the license template as late as inside `check_license()` either, but for much the same reasons, I don't know where else to put it. If the `Config` were hand-rolled instead of a macro, I'd just define a custom `license_template` option and load and parse the template in the `Config`'s init. But the way things are, I'm a bit at a loss. However, if someone more familiar with the project would kindly provide a few hints as to how the path approach can be done in a way that is as clean as possible in the context of the codebase, I'll be more than happy to implement it! :) --- src/config/mod.rs | 1 + src/lib.rs | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index 7e9fae81318..c16d5bb6799 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -50,6 +50,7 @@ create_config! { comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; + license_template: String, String::default(), false, "Check for license"; // Single line expressions and items. empty_item_single_line: bool, true, false, diff --git a/src/lib.rs b/src/lib.rs index a3302a86a0f..858a273a1e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,7 @@ use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping}; pub use syntax::codemap::FileName; use syntax::parse::{self, ParseSess}; +use regex::{Regex, RegexBuilder}; use checkstyle::{output_footer, output_header}; use comment::{CharClasses, FullCodeCharKind}; @@ -99,6 +100,10 @@ pub enum ErrorKind { TrailingWhitespace, // TO-DO or FIX-ME item without an issue number BadIssue(Issue), + // License check has failed + LicenseCheck, + // License template could not be parsed + ParsingLicense, } impl fmt::Display for ErrorKind { @@ -111,6 +116,8 @@ impl fmt::Display for ErrorKind { ), ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), + ErrorKind::LicenseCheck => write!(fmt, "license check failed"), + ErrorKind::ParsingLicense => write!(fmt, "parsing regex in license template failed"), } } } @@ -127,7 +134,10 @@ pub struct FormattingError { impl FormattingError { fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "error:", + ErrorKind::LineOverflow(..) + | ErrorKind::TrailingWhitespace + | ErrorKind::LicenseCheck + | ErrorKind::ParsingLicense => "error:", ErrorKind::BadIssue(_) => "WARNING:", } } @@ -405,8 +415,39 @@ fn should_report_error( } } +fn check_license(text: &str, license_template: &str) -> Result { + let mut template_re = String::from("^"); + // the template is parsed as a series of pairs of capture groups of (1) lazy whatever, which + // will be matched literally, followed by (2) a {}-delimited block, which will be matched as a + // regex + let template_parser = RegexBuilder::new(r"(.*?)\{(.*?)\}") + .dot_matches_new_line(true) + .build() + .unwrap(); + // keep track of the last matched offset and ultimately append the tail of the template (if any) + // after the last {} block + let mut last_matched_offset = 0; + for caps in template_parser.captures_iter(license_template) { + if let Some(mat) = caps.get(0) { + last_matched_offset = mat.end() + } + if let Some(mat) = caps.get(1) { + template_re.push_str(®ex::escape(mat.as_str())) + } + if let Some(mat) = caps.get(2) { + let mut re = mat.as_str(); + if re.is_empty() { + re = ".*?"; + } + template_re.push_str(re) + } + } + template_re.push_str(®ex::escape(&license_template[last_matched_offset..])); + let template_re = Regex::new(&template_re)?; + Ok(template_re.is_match(text)) +} + // Formatting done on a char by char or line by line basis. -// FIXME(#209) warn on bad license // FIXME(#20) other stuff for parity with make tidy fn format_lines( text: &mut String, @@ -415,7 +456,6 @@ fn format_lines( config: &Config, report: &mut FormatReport, ) { - // Iterate over the chars in the file map. let mut trims = vec![]; let mut last_wspace: Option = None; let mut line_len = 0; @@ -428,6 +468,33 @@ fn format_lines( let mut format_line = config.file_lines().contains_line(name, cur_line); let allow_issue_seek = !issue_seeker.is_disabled(); + // Check license. + if config.was_set().license_template() { + match check_license(text, &config.license_template()) { + Ok(check) => { + if !check { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::LicenseCheck, + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); + } + } + Err(_) => { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::ParsingLicense, + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); + } + } + } + + // Iterate over the chars in the file map. for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { if c == '\r' { continue; @@ -853,7 +920,7 @@ pub fn run(input: Input, config: &Config) -> Summary { #[cfg(test)] mod test { - use super::{format_code_block, format_snippet, Config}; + use super::{check_license, format_code_block, format_snippet, Config}; #[test] fn test_no_panic_on_format_snippet_and_format_code_block() { @@ -939,4 +1006,38 @@ false, };"; assert!(test_format_inner(format_code_block, code_block, expected)); } + + #[test] + fn test_check_license() { + assert!(check_license("literal matching", "literal matching").unwrap()); + assert!(!check_license("literal no match", "literal matching").unwrap()); + assert!( + check_license( + "Regex start and end: 2018", + r"{[Rr]egex} start {} end: {\d+}" + ).unwrap() + ); + assert!(!check_license( + "Regex start and end no match: 2018", + r"{[Rr]egex} start {} end: {\d+}" + ).unwrap()); + assert!( + check_license( + "Regex in the middle: 2018 (tm)", + r"Regex {} middle: {\d+} (tm)" + ).unwrap() + ); + assert!(!check_license( + "Regex in the middle no match: 2018 (tm)", + r"Regex {} middle: {\d+} (tm)" + ).unwrap()); + assert!(!check_license("default doesn't match\nacross lines", "default {} lines").unwrap()); + assert!(check_license("", "this is not a valid {[regex}").is_err()); + assert!( + check_license( + "can't parse nested delimiters with regex", + r"can't parse nested delimiters with regex{\.{3}}" + ).is_err() + ); + } } -- cgit 1.4.1-3-g733a5 From d012d52b4da4286932a43587d8072d149dc9454a Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 19 Feb 2018 11:00:07 +0100 Subject: Parse template with state machine instead of regex This allows occurrences of `{` and `}` within `{}` placeholders in the template, and also for having literal `{` and `}` in the template by means of escaping (`\{`). Unbalanced, unescaped `}` at the toplevel is a syntax error which currently triggers a panic; I'll add proper error handling as I move the license template parsing code into the config parsing phase. --- src/lib.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 858a273a1e5..6771a2ab794 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping}; pub use syntax::codemap::FileName; use syntax::parse::{self, ParseSess}; -use regex::{Regex, RegexBuilder}; +use regex::Regex; use checkstyle::{output_footer, output_header}; use comment::{CharClasses, FullCodeCharKind}; @@ -416,33 +416,77 @@ fn should_report_error( } fn check_license(text: &str, license_template: &str) -> Result { + // the template is parsed using a state machine + enum State { + Lit, + LitEsc, + // the u32 keeps track of brace nesting + Re(u32), + ReEsc(u32), + } + let mut template_re = String::from("^"); - // the template is parsed as a series of pairs of capture groups of (1) lazy whatever, which - // will be matched literally, followed by (2) a {}-delimited block, which will be matched as a - // regex - let template_parser = RegexBuilder::new(r"(.*?)\{(.*?)\}") - .dot_matches_new_line(true) - .build() - .unwrap(); - // keep track of the last matched offset and ultimately append the tail of the template (if any) - // after the last {} block - let mut last_matched_offset = 0; - for caps in template_parser.captures_iter(license_template) { - if let Some(mat) = caps.get(0) { - last_matched_offset = mat.end() - } - if let Some(mat) = caps.get(1) { - template_re.push_str(®ex::escape(mat.as_str())) - } - if let Some(mat) = caps.get(2) { - let mut re = mat.as_str(); - if re.is_empty() { - re = ".*?"; + let mut buffer = String::new(); + let mut state = State::Lit; + for chr in license_template.chars() { + state = match state { + State::Lit => match chr { + '{' => { + template_re.push_str(®ex::escape(&buffer)); + buffer.clear(); + State::Re(1) + } + '}' => panic!("license template syntax error"), + '\\' => State::LitEsc, + _ => { + buffer.push(chr); + State::Lit + } + }, + State::LitEsc => { + buffer.push(chr); + State::Lit + } + State::Re(brace_nesting) => { + match chr { + '{' => { + buffer.push(chr); + State::Re(brace_nesting + 1) + } + '}' => { + match brace_nesting { + 1 => { + // default regex for empty placeholder {} + if buffer.is_empty() { + buffer = ".*?".to_string(); + } + template_re.push_str(&buffer); + buffer.clear(); + State::Lit + } + _ => { + buffer.push(chr); + State::Re(brace_nesting - 1) + } + } + } + '\\' => { + buffer.push(chr); + State::ReEsc(brace_nesting) + } + _ => { + buffer.push(chr); + State::Re(brace_nesting) + } + } + } + State::ReEsc(brace_nesting) => { + buffer.push(chr); + State::Re(brace_nesting) } - template_re.push_str(re) } } - template_re.push_str(®ex::escape(&license_template[last_matched_offset..])); + template_re.push_str(®ex::escape(&buffer)); let template_re = Regex::new(&template_re)?; Ok(template_re.is_match(text)) } @@ -1035,9 +1079,10 @@ false, assert!(check_license("", "this is not a valid {[regex}").is_err()); assert!( check_license( - "can't parse nested delimiters with regex", - r"can't parse nested delimiters with regex{\.{3}}" - ).is_err() + "parse unbalanced nested delimiters{{{", + r"parse unbalanced nested delimiters{\{{3}}" + ).unwrap() ); + assert!(check_license("escaping }", r"escaping \}").unwrap()); } } -- cgit 1.4.1-3-g733a5 From ad76741bca51d169d0e167223435bcc08fc2a3af Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 19 Feb 2018 17:26:29 +0100 Subject: Move license template parsing into config phase --- src/config/config_type.rs | 54 ++++++++++++-- src/config/mod.rs | 179 +++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 151 +++----------------------------------- 3 files changed, 238 insertions(+), 146 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 950225679a5..02e9b2d1078 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -78,6 +78,9 @@ macro_rules! create_config { #[derive(Clone)] pub struct Config { + // if a license_template_path has been specified, successfully read, parsed and compiled + // into a regex, it will be stored here + pub license_template: Option, // For each config item, we store a bool indicating whether it has // been accessed and the value, and a bool whether the option was // manually initialised, or taken from the default, @@ -118,8 +121,10 @@ macro_rules! create_config { $( pub fn $i(&mut self, value: $ty) { (self.0).$i.2 = value; - if stringify!($i) == "use_small_heuristics" { - self.0.set_heuristics(); + match stringify!($i) { + "use_small_heuristics" => self.0.set_heuristics(), + "license_template_path" => self.0.set_license_template(), + &_ => (), } } )+ @@ -189,6 +194,7 @@ macro_rules! create_config { } )+ self.set_heuristics(); + self.set_license_template(); self } @@ -276,8 +282,10 @@ macro_rules! create_config { _ => panic!("Unknown config key in override: {}", key) } - if key == "use_small_heuristics" { - self.set_heuristics(); + match key { + "use_small_heuristics" => self.set_heuristics(), + "license_template_path" => self.set_license_template(), + &_ => (), } } @@ -382,12 +390,50 @@ macro_rules! create_config { self.set().width_heuristics(WidthHeuristics::null()); } } + + fn set_license_template(&mut self) { + let license_template_path = self.license_template_path(); + let mut license_template_file = match File::open(&license_template_path) { + Ok(file) => file, + Err(e) => { + eprintln!("Warning: unable to open license template file {:?}: {}", + license_template_path, e); + return; + } + }; + let mut license_template_str = String::new(); + match license_template_file.read_to_string(&mut license_template_str) { + Ok(_) => (), + Err(e) => { + eprintln!("Warning: unable to read from license template file {:?}: {}", + license_template_path, e); + return; + } + } + let license_template_parsed = match parse_license_template(&license_template_str) { + Ok(string) => string, + Err(e) => { + eprintln!("Warning: unable to parse license template file {:?}: {}", + license_template_path, e); + return; + } + }; + self.license_template = match Regex::new(&license_template_parsed) { + Ok(re) => Some(re), + Err(e) => { + eprintln!("Warning: regex syntax error in placeholder, unable to compile \ + license template from file {:?}: {}", license_template_path, e); + return; + } + } + } } // Template for the default configuration impl Default for Config { fn default() -> Config { Config { + license_template: None, $( $i: (Cell::new(false), false, $def, $stb), )+ diff --git a/src/config/mod.rs b/src/config/mod.rs index c16d5bb6799..53078716414 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -15,6 +15,8 @@ use std::fs::File; use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; +use regex::Regex; + #[macro_use] mod config_type; #[macro_use] @@ -50,7 +52,7 @@ create_config! { comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; - license_template: String, String::default(), false, "Check for license"; + license_template_path: String, String::default(), false, "Beginning of file must match license template"; // Single line expressions and items. empty_item_single_line: bool, true, false, @@ -172,9 +174,145 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { Ok(None) } +/// Convert the license template into a string which can be turned into a regex. +/// +/// The license template could use regex syntax directly, but that would require a lot of manual +/// escaping, which is inconvenient. It is therefore literal by default, with optional regex +/// subparts delimited by `{` and `}`. Additionally: +/// +/// - to insert literal `{`, `}` or `\`, escape it with `\` +/// - an empty regex placeholder (`{}`) is shorthand for `{.*?}` +/// +/// This function parses this input format and builds a properly escaped *string* representation of +/// the equivalent regular expression. It **does not** however guarantee that the returned string is +/// a syntactically valid regular expression. +/// +/// # Examples +/// +/// ``` +/// assert_eq!( +/// rustfmt_config::parse_license_template( +/// r" +/// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)} +/// // file at the top-level directory of this distribution and at +/// // {}. +/// // +/// // Licensed under the Apache License, Version 2.0 or the MIT license +/// // , at your +/// // option. This file may not be copied, modified, or distributed +/// // except according to those terms. +/// " +/// ).unwrap(), +/// r"^ +/// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+) +/// // file at the top\-level directory of this distribution and at +/// // .*?\. +/// // +/// // Licensed under the Apache License, Version 2\.0 or the MIT license +/// // , at your +/// // option\. This file may not be copied, modified, or distributed +/// // except according to those terms\. +/// " +/// ); +/// ``` +pub fn parse_license_template(template: &str) -> Result { + // the template is parsed using a state machine + enum State { + Lit, + LitEsc, + // the u32 keeps track of brace nesting + Re(u32), + ReEsc(u32), + } + + let mut parsed = String::from("^"); + let mut buffer = String::new(); + let mut state = State::Lit; + let mut linum = 1; + // keeps track of last line on which a regex placeholder was started + let mut open_brace_line = 0; + for chr in template.chars() { + if chr == '\n' { + linum += 1; + } + state = match state { + State::Lit => match chr { + '{' => { + parsed.push_str(®ex::escape(&buffer)); + buffer.clear(); + open_brace_line = linum; + State::Re(1) + } + '}' => return Err(format!("escape or balance closing brace on l. {}", linum)), + '\\' => State::LitEsc, + _ => { + buffer.push(chr); + State::Lit + } + }, + State::LitEsc => { + buffer.push(chr); + State::Lit + } + State::Re(brace_nesting) => { + match chr { + '{' => { + buffer.push(chr); + State::Re(brace_nesting + 1) + } + '}' => { + match brace_nesting { + 1 => { + // default regex for empty placeholder {} + if buffer.is_empty() { + buffer = ".*?".to_string(); + } + parsed.push_str(&buffer); + buffer.clear(); + State::Lit + } + _ => { + buffer.push(chr); + State::Re(brace_nesting - 1) + } + } + } + '\\' => { + buffer.push(chr); + State::ReEsc(brace_nesting) + } + _ => { + buffer.push(chr); + State::Re(brace_nesting) + } + } + } + State::ReEsc(brace_nesting) => { + buffer.push(chr); + State::Re(brace_nesting) + } + } + } + match state { + State::Re(_) | State::ReEsc(_) => { + return Err(format!( + "escape or balance opening brace on l. {}", + open_brace_line + )); + } + State::LitEsc => return Err(format!("incomplete escape sequence on l. {}", linum)), + _ => (), + } + parsed.push_str(®ex::escape(&buffer)); + + Ok(parsed) +} + #[cfg(test)] mod test { - use super::Config; + use super::{parse_license_template, Config}; #[test] fn test_config_set() { @@ -211,6 +349,43 @@ mod test { assert_eq!(config.was_set().verbose(), false); } + #[test] + fn test_parse_license_template() { + assert_eq!( + parse_license_template("literal (.*)").unwrap(), + r"^literal \(\.\*\)" + ); + assert_eq!( + parse_license_template(r"escaping \}").unwrap(), + r"^escaping \}" + ); + assert!(parse_license_template("unbalanced } without escape").is_err()); + assert_eq!( + parse_license_template(r"{\d+} place{-?}holder{s?}").unwrap(), + r"^\d+ place-?holders?" + ); + assert_eq!( + parse_license_template("default {}").unwrap(), + "^default .*?" + ); + assert_eq!( + parse_license_template(r"unbalanced nested braces {\{{3}}").unwrap(), + r"^unbalanced nested braces \{{3}" + ); + assert_eq!( + parse_license_template("parsing error }").unwrap_err(), + "escape or balance closing brace on l. 1" + ); + assert_eq!( + parse_license_template("parsing error {\nsecond line").unwrap_err(), + "escape or balance opening brace on l. 1" + ); + assert_eq!( + parse_license_template(r"parsing error \").unwrap_err(), + "incomplete escape sequence on l. 1" + ); + } + // FIXME(#2183) these tests cannot be run in parallel because they use env vars // #[test] // fn test_as_not_nightly_channel() { diff --git a/src/lib.rs b/src/lib.rs index 6771a2ab794..e53f8bfb907 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,6 @@ use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping}; pub use syntax::codemap::FileName; use syntax::parse::{self, ParseSess}; -use regex::Regex; use checkstyle::{output_footer, output_header}; use comment::{CharClasses, FullCodeCharKind}; @@ -102,8 +101,6 @@ pub enum ErrorKind { BadIssue(Issue), // License check has failed LicenseCheck, - // License template could not be parsed - ParsingLicense, } impl fmt::Display for ErrorKind { @@ -117,7 +114,6 @@ impl fmt::Display for ErrorKind { ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), ErrorKind::LicenseCheck => write!(fmt, "license check failed"), - ErrorKind::ParsingLicense => write!(fmt, "parsing regex in license template failed"), } } } @@ -136,8 +132,7 @@ impl FormattingError { match self.kind { ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace - | ErrorKind::LicenseCheck - | ErrorKind::ParsingLicense => "error:", + | ErrorKind::LicenseCheck => "error:", ErrorKind::BadIssue(_) => "WARNING:", } } @@ -415,82 +410,6 @@ fn should_report_error( } } -fn check_license(text: &str, license_template: &str) -> Result { - // the template is parsed using a state machine - enum State { - Lit, - LitEsc, - // the u32 keeps track of brace nesting - Re(u32), - ReEsc(u32), - } - - let mut template_re = String::from("^"); - let mut buffer = String::new(); - let mut state = State::Lit; - for chr in license_template.chars() { - state = match state { - State::Lit => match chr { - '{' => { - template_re.push_str(®ex::escape(&buffer)); - buffer.clear(); - State::Re(1) - } - '}' => panic!("license template syntax error"), - '\\' => State::LitEsc, - _ => { - buffer.push(chr); - State::Lit - } - }, - State::LitEsc => { - buffer.push(chr); - State::Lit - } - State::Re(brace_nesting) => { - match chr { - '{' => { - buffer.push(chr); - State::Re(brace_nesting + 1) - } - '}' => { - match brace_nesting { - 1 => { - // default regex for empty placeholder {} - if buffer.is_empty() { - buffer = ".*?".to_string(); - } - template_re.push_str(&buffer); - buffer.clear(); - State::Lit - } - _ => { - buffer.push(chr); - State::Re(brace_nesting - 1) - } - } - } - '\\' => { - buffer.push(chr); - State::ReEsc(brace_nesting) - } - _ => { - buffer.push(chr); - State::Re(brace_nesting) - } - } - } - State::ReEsc(brace_nesting) => { - buffer.push(chr); - State::Re(brace_nesting) - } - } - } - template_re.push_str(®ex::escape(&buffer)); - let template_re = Regex::new(&template_re)?; - Ok(template_re.is_match(text)) -} - // Formatting done on a char by char or line by line basis. // FIXME(#20) other stuff for parity with make tidy fn format_lines( @@ -513,28 +432,15 @@ fn format_lines( let allow_issue_seek = !issue_seeker.is_disabled(); // Check license. - if config.was_set().license_template() { - match check_license(text, &config.license_template()) { - Ok(check) => { - if !check { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LicenseCheck, - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } - } - Err(_) => { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::ParsingLicense, - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } + if let Some(ref license_template) = config.license_template { + if !license_template.is_match(text) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::LicenseCheck, + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); } } @@ -964,7 +870,7 @@ pub fn run(input: Input, config: &Config) -> Summary { #[cfg(test)] mod test { - use super::{check_license, format_code_block, format_snippet, Config}; + use super::{format_code_block, format_snippet, Config}; #[test] fn test_no_panic_on_format_snippet_and_format_code_block() { @@ -1050,39 +956,4 @@ false, };"; assert!(test_format_inner(format_code_block, code_block, expected)); } - - #[test] - fn test_check_license() { - assert!(check_license("literal matching", "literal matching").unwrap()); - assert!(!check_license("literal no match", "literal matching").unwrap()); - assert!( - check_license( - "Regex start and end: 2018", - r"{[Rr]egex} start {} end: {\d+}" - ).unwrap() - ); - assert!(!check_license( - "Regex start and end no match: 2018", - r"{[Rr]egex} start {} end: {\d+}" - ).unwrap()); - assert!( - check_license( - "Regex in the middle: 2018 (tm)", - r"Regex {} middle: {\d+} (tm)" - ).unwrap() - ); - assert!(!check_license( - "Regex in the middle no match: 2018 (tm)", - r"Regex {} middle: {\d+} (tm)" - ).unwrap()); - assert!(!check_license("default doesn't match\nacross lines", "default {} lines").unwrap()); - assert!(check_license("", "this is not a valid {[regex}").is_err()); - assert!( - check_license( - "parse unbalanced nested delimiters{{{", - r"parse unbalanced nested delimiters{\{{3}}" - ).unwrap() - ); - assert!(check_license("escaping }", r"escaping \}").unwrap()); - } } -- cgit 1.4.1-3-g733a5 From ead81205cc1f3597a3f7ecdde993d81f0d859e03 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 12:23:15 +0100 Subject: Simplify match → if let MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/config_type.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 02e9b2d1078..ad2ae6f7422 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -402,14 +402,11 @@ macro_rules! create_config { } }; let mut license_template_str = String::new(); - match license_template_file.read_to_string(&mut license_template_str) { - Ok(_) => (), - Err(e) => { - eprintln!("Warning: unable to read from license template file {:?}: {}", - license_template_path, e); - return; - } - } + if let Err(e) = license_template_file.read_to_string(&mut license_template_str) { + eprintln!("Warning: unable to read from license template file {:?}: {}", + license_template_path, e); + return; + }; let license_template_parsed = match parse_license_template(&license_template_str) { Ok(string) => string, Err(e) => { -- cgit 1.4.1-3-g733a5 From e48d7f3ebb3ee16d24ec8351f16768ea8f6ed9b0 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 12:31:09 +0100 Subject: Account for possibly empty license_template_path Don't attempt to load license_template if the path wasn't specified. --- src/config/config_type.rs | 58 ++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index ad2ae6f7422..e6e5c5ef540 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -392,35 +392,37 @@ macro_rules! create_config { } fn set_license_template(&mut self) { - let license_template_path = self.license_template_path(); - let mut license_template_file = match File::open(&license_template_path) { - Ok(file) => file, - Err(e) => { - eprintln!("Warning: unable to open license template file {:?}: {}", - license_template_path, e); - return; - } - }; - let mut license_template_str = String::new(); - if let Err(e) = license_template_file.read_to_string(&mut license_template_str) { - eprintln!("Warning: unable to read from license template file {:?}: {}", - license_template_path, e); - return; - }; - let license_template_parsed = match parse_license_template(&license_template_str) { - Ok(string) => string, - Err(e) => { - eprintln!("Warning: unable to parse license template file {:?}: {}", - license_template_path, e); - return; - } - }; - self.license_template = match Regex::new(&license_template_parsed) { - Ok(re) => Some(re), - Err(e) => { - eprintln!("Warning: regex syntax error in placeholder, unable to compile \ - license template from file {:?}: {}", license_template_path, e); + if self.was_set().license_template_path() { + let license_template_path = self.license_template_path(); + let mut license_template_file = match File::open(&license_template_path) { + Ok(file) => file, + Err(e) => { + eprintln!("Warning: unable to open license template file {:?}: {}", + license_template_path, e); + return; + } + }; + let mut license_template_str = String::new(); + if let Err(e) = license_template_file.read_to_string(&mut license_template_str) { + eprintln!("Warning: unable to read from license template file {:?}: {}", + license_template_path, e); return; + }; + let license_template_parsed = match parse_license_template(&license_template_str) { + Ok(string) => string, + Err(e) => { + eprintln!("Warning: unable to parse license template file {:?}: {}", + license_template_path, e); + return; + } + }; + self.license_template = match Regex::new(&license_template_parsed) { + Ok(re) => Some(re), + Err(e) => { + eprintln!("Warning: regex syntax error in placeholder, unable to compile \ + license template from file {:?}: {}", license_template_path, e); + return; + } } } } -- cgit 1.4.1-3-g733a5 From 310c1146f28eab02595e3308cdb2c3d8dbbeb3a7 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 12:49:12 +0100 Subject: Move license template parsing into submodule --- rustfmt-config/src/license.rs | 174 +++++++++++++++++++++++++++++++++++++++++ src/config/config_type.rs | 2 +- src/config/mod.rs | 176 +----------------------------------------- 3 files changed, 177 insertions(+), 175 deletions(-) create mode 100644 rustfmt-config/src/license.rs (limited to 'src') diff --git a/rustfmt-config/src/license.rs b/rustfmt-config/src/license.rs new file mode 100644 index 00000000000..4563f8a7809 --- /dev/null +++ b/rustfmt-config/src/license.rs @@ -0,0 +1,174 @@ +use regex; + +/// Convert the license template into a string which can be turned into a regex. +/// +/// The license template could use regex syntax directly, but that would require a lot of manual +/// escaping, which is inconvenient. It is therefore literal by default, with optional regex +/// subparts delimited by `{` and `}`. Additionally: +/// +/// - to insert literal `{`, `}` or `\`, escape it with `\` +/// - an empty regex placeholder (`{}`) is shorthand for `{.*?}` +/// +/// This function parses this input format and builds a properly escaped *string* representation of +/// the equivalent regular expression. It **does not** however guarantee that the returned string is +/// a syntactically valid regular expression. +/// +/// # Examples +/// +/// ``` +/// # use rustfmt_config::license; +/// assert_eq!( +/// license::parse_template( +/// r" +/// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)} +/// // file at the top-level directory of this distribution and at +/// // {}. +/// // +/// // Licensed under the Apache License, Version 2.0 or the MIT license +/// // , at your +/// // option. This file may not be copied, modified, or distributed +/// // except according to those terms. +/// " +/// ).unwrap(), +/// r"^ +/// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+) +/// // file at the top\-level directory of this distribution and at +/// // .*?\. +/// // +/// // Licensed under the Apache License, Version 2\.0 or the MIT license +/// // , at your +/// // option\. This file may not be copied, modified, or distributed +/// // except according to those terms\. +/// " +/// ); +/// ``` +pub fn parse_template(template: &str) -> Result { + // the template is parsed using a state machine + enum State { + Lit, + LitEsc, + // the u32 keeps track of brace nesting + Re(u32), + ReEsc(u32), + } + + let mut parsed = String::from("^"); + let mut buffer = String::new(); + let mut state = State::Lit; + let mut linum = 1; + // keeps track of last line on which a regex placeholder was started + let mut open_brace_line = 0; + for chr in template.chars() { + if chr == '\n' { + linum += 1; + } + state = match state { + State::Lit => match chr { + '{' => { + parsed.push_str(®ex::escape(&buffer)); + buffer.clear(); + open_brace_line = linum; + State::Re(1) + } + '}' => return Err(format!("escape or balance closing brace on l. {}", linum)), + '\\' => State::LitEsc, + _ => { + buffer.push(chr); + State::Lit + } + }, + State::LitEsc => { + buffer.push(chr); + State::Lit + } + State::Re(brace_nesting) => { + match chr { + '{' => { + buffer.push(chr); + State::Re(brace_nesting + 1) + } + '}' => { + match brace_nesting { + 1 => { + // default regex for empty placeholder {} + if buffer.is_empty() { + buffer = ".*?".to_string(); + } + parsed.push_str(&buffer); + buffer.clear(); + State::Lit + } + _ => { + buffer.push(chr); + State::Re(brace_nesting - 1) + } + } + } + '\\' => { + buffer.push(chr); + State::ReEsc(brace_nesting) + } + _ => { + buffer.push(chr); + State::Re(brace_nesting) + } + } + } + State::ReEsc(brace_nesting) => { + buffer.push(chr); + State::Re(brace_nesting) + } + } + } + match state { + State::Re(_) | State::ReEsc(_) => { + return Err(format!( + "escape or balance opening brace on l. {}", + open_brace_line + )); + } + State::LitEsc => return Err(format!("incomplete escape sequence on l. {}", linum)), + _ => (), + } + parsed.push_str(®ex::escape(&buffer)); + + Ok(parsed) +} + +#[cfg(test)] +mod test { + use super::parse_template; + + #[test] + fn test_parse_license_template() { + assert_eq!( + parse_template("literal (.*)").unwrap(), + r"^literal \(\.\*\)" + ); + assert_eq!(parse_template(r"escaping \}").unwrap(), r"^escaping \}"); + assert!(parse_template("unbalanced } without escape").is_err()); + assert_eq!( + parse_template(r"{\d+} place{-?}holder{s?}").unwrap(), + r"^\d+ place-?holders?" + ); + assert_eq!(parse_template("default {}").unwrap(), "^default .*?"); + assert_eq!( + parse_template(r"unbalanced nested braces {\{{3}}").unwrap(), + r"^unbalanced nested braces \{{3}" + ); + assert_eq!( + parse_template("parsing error }").unwrap_err(), + "escape or balance closing brace on l. 1" + ); + assert_eq!( + parse_template("parsing error {\nsecond line").unwrap_err(), + "escape or balance opening brace on l. 1" + ); + assert_eq!( + parse_template(r"parsing error \").unwrap_err(), + "incomplete escape sequence on l. 1" + ); + } +} diff --git a/src/config/config_type.rs b/src/config/config_type.rs index e6e5c5ef540..fe0e4c309e2 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -408,7 +408,7 @@ macro_rules! create_config { license_template_path, e); return; }; - let license_template_parsed = match parse_license_template(&license_template_str) { + let license_template_parsed = match license::parse_template(&license_template_str) { Ok(string) => string, Err(e) => { eprintln!("Warning: unable to parse license template file {:?}: {}", diff --git a/src/config/mod.rs b/src/config/mod.rs index 53078716414..0d4ec8557d3 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -25,6 +25,7 @@ mod options; pub mod file_lines; pub mod lists; pub mod summary; +pub mod license; use config::config_type::ConfigType; use config::file_lines::FileLines; @@ -174,145 +175,9 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { Ok(None) } -/// Convert the license template into a string which can be turned into a regex. -/// -/// The license template could use regex syntax directly, but that would require a lot of manual -/// escaping, which is inconvenient. It is therefore literal by default, with optional regex -/// subparts delimited by `{` and `}`. Additionally: -/// -/// - to insert literal `{`, `}` or `\`, escape it with `\` -/// - an empty regex placeholder (`{}`) is shorthand for `{.*?}` -/// -/// This function parses this input format and builds a properly escaped *string* representation of -/// the equivalent regular expression. It **does not** however guarantee that the returned string is -/// a syntactically valid regular expression. -/// -/// # Examples -/// -/// ``` -/// assert_eq!( -/// rustfmt_config::parse_license_template( -/// r" -/// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)} -/// // file at the top-level directory of this distribution and at -/// // {}. -/// // -/// // Licensed under the Apache License, Version 2.0 or the MIT license -/// // , at your -/// // option. This file may not be copied, modified, or distributed -/// // except according to those terms. -/// " -/// ).unwrap(), -/// r"^ -/// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+) -/// // file at the top\-level directory of this distribution and at -/// // .*?\. -/// // -/// // Licensed under the Apache License, Version 2\.0 or the MIT license -/// // , at your -/// // option\. This file may not be copied, modified, or distributed -/// // except according to those terms\. -/// " -/// ); -/// ``` -pub fn parse_license_template(template: &str) -> Result { - // the template is parsed using a state machine - enum State { - Lit, - LitEsc, - // the u32 keeps track of brace nesting - Re(u32), - ReEsc(u32), - } - - let mut parsed = String::from("^"); - let mut buffer = String::new(); - let mut state = State::Lit; - let mut linum = 1; - // keeps track of last line on which a regex placeholder was started - let mut open_brace_line = 0; - for chr in template.chars() { - if chr == '\n' { - linum += 1; - } - state = match state { - State::Lit => match chr { - '{' => { - parsed.push_str(®ex::escape(&buffer)); - buffer.clear(); - open_brace_line = linum; - State::Re(1) - } - '}' => return Err(format!("escape or balance closing brace on l. {}", linum)), - '\\' => State::LitEsc, - _ => { - buffer.push(chr); - State::Lit - } - }, - State::LitEsc => { - buffer.push(chr); - State::Lit - } - State::Re(brace_nesting) => { - match chr { - '{' => { - buffer.push(chr); - State::Re(brace_nesting + 1) - } - '}' => { - match brace_nesting { - 1 => { - // default regex for empty placeholder {} - if buffer.is_empty() { - buffer = ".*?".to_string(); - } - parsed.push_str(&buffer); - buffer.clear(); - State::Lit - } - _ => { - buffer.push(chr); - State::Re(brace_nesting - 1) - } - } - } - '\\' => { - buffer.push(chr); - State::ReEsc(brace_nesting) - } - _ => { - buffer.push(chr); - State::Re(brace_nesting) - } - } - } - State::ReEsc(brace_nesting) => { - buffer.push(chr); - State::Re(brace_nesting) - } - } - } - match state { - State::Re(_) | State::ReEsc(_) => { - return Err(format!( - "escape or balance opening brace on l. {}", - open_brace_line - )); - } - State::LitEsc => return Err(format!("incomplete escape sequence on l. {}", linum)), - _ => (), - } - parsed.push_str(®ex::escape(&buffer)); - - Ok(parsed) -} - #[cfg(test)] mod test { - use super::{parse_license_template, Config}; + use super::Config; #[test] fn test_config_set() { @@ -349,43 +214,6 @@ mod test { assert_eq!(config.was_set().verbose(), false); } - #[test] - fn test_parse_license_template() { - assert_eq!( - parse_license_template("literal (.*)").unwrap(), - r"^literal \(\.\*\)" - ); - assert_eq!( - parse_license_template(r"escaping \}").unwrap(), - r"^escaping \}" - ); - assert!(parse_license_template("unbalanced } without escape").is_err()); - assert_eq!( - parse_license_template(r"{\d+} place{-?}holder{s?}").unwrap(), - r"^\d+ place-?holders?" - ); - assert_eq!( - parse_license_template("default {}").unwrap(), - "^default .*?" - ); - assert_eq!( - parse_license_template(r"unbalanced nested braces {\{{3}}").unwrap(), - r"^unbalanced nested braces \{{3}" - ); - assert_eq!( - parse_license_template("parsing error }").unwrap_err(), - "escape or balance closing brace on l. 1" - ); - assert_eq!( - parse_license_template("parsing error {\nsecond line").unwrap_err(), - "escape or balance opening brace on l. 1" - ); - assert_eq!( - parse_license_template(r"parsing error \").unwrap_err(), - "incomplete escape sequence on l. 1" - ); - } - // FIXME(#2183) these tests cannot be run in parallel because they use env vars // #[test] // fn test_as_not_nightly_channel() { -- cgit 1.4.1-3-g733a5 From bbd6d9cd555d9b35677086bc93e66212ea173cc5 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 15:41:38 +0100 Subject: Refactor parsing code into struct This also splits the giant state machine match expression into separate methods. --- rustfmt-config/src/license.rs | 174 ---------------------------------- src/config/config_type.rs | 2 +- src/config/license.rs | 213 ++++++++++++++++++++++++++++++++++++++++++ src/config/mod.rs | 1 + 4 files changed, 215 insertions(+), 175 deletions(-) delete mode 100644 rustfmt-config/src/license.rs create mode 100644 src/config/license.rs (limited to 'src') diff --git a/rustfmt-config/src/license.rs b/rustfmt-config/src/license.rs deleted file mode 100644 index 4563f8a7809..00000000000 --- a/rustfmt-config/src/license.rs +++ /dev/null @@ -1,174 +0,0 @@ -use regex; - -/// Convert the license template into a string which can be turned into a regex. -/// -/// The license template could use regex syntax directly, but that would require a lot of manual -/// escaping, which is inconvenient. It is therefore literal by default, with optional regex -/// subparts delimited by `{` and `}`. Additionally: -/// -/// - to insert literal `{`, `}` or `\`, escape it with `\` -/// - an empty regex placeholder (`{}`) is shorthand for `{.*?}` -/// -/// This function parses this input format and builds a properly escaped *string* representation of -/// the equivalent regular expression. It **does not** however guarantee that the returned string is -/// a syntactically valid regular expression. -/// -/// # Examples -/// -/// ``` -/// # use rustfmt_config::license; -/// assert_eq!( -/// license::parse_template( -/// r" -/// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)} -/// // file at the top-level directory of this distribution and at -/// // {}. -/// // -/// // Licensed under the Apache License, Version 2.0 or the MIT license -/// // , at your -/// // option. This file may not be copied, modified, or distributed -/// // except according to those terms. -/// " -/// ).unwrap(), -/// r"^ -/// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+) -/// // file at the top\-level directory of this distribution and at -/// // .*?\. -/// // -/// // Licensed under the Apache License, Version 2\.0 or the MIT license -/// // , at your -/// // option\. This file may not be copied, modified, or distributed -/// // except according to those terms\. -/// " -/// ); -/// ``` -pub fn parse_template(template: &str) -> Result { - // the template is parsed using a state machine - enum State { - Lit, - LitEsc, - // the u32 keeps track of brace nesting - Re(u32), - ReEsc(u32), - } - - let mut parsed = String::from("^"); - let mut buffer = String::new(); - let mut state = State::Lit; - let mut linum = 1; - // keeps track of last line on which a regex placeholder was started - let mut open_brace_line = 0; - for chr in template.chars() { - if chr == '\n' { - linum += 1; - } - state = match state { - State::Lit => match chr { - '{' => { - parsed.push_str(®ex::escape(&buffer)); - buffer.clear(); - open_brace_line = linum; - State::Re(1) - } - '}' => return Err(format!("escape or balance closing brace on l. {}", linum)), - '\\' => State::LitEsc, - _ => { - buffer.push(chr); - State::Lit - } - }, - State::LitEsc => { - buffer.push(chr); - State::Lit - } - State::Re(brace_nesting) => { - match chr { - '{' => { - buffer.push(chr); - State::Re(brace_nesting + 1) - } - '}' => { - match brace_nesting { - 1 => { - // default regex for empty placeholder {} - if buffer.is_empty() { - buffer = ".*?".to_string(); - } - parsed.push_str(&buffer); - buffer.clear(); - State::Lit - } - _ => { - buffer.push(chr); - State::Re(brace_nesting - 1) - } - } - } - '\\' => { - buffer.push(chr); - State::ReEsc(brace_nesting) - } - _ => { - buffer.push(chr); - State::Re(brace_nesting) - } - } - } - State::ReEsc(brace_nesting) => { - buffer.push(chr); - State::Re(brace_nesting) - } - } - } - match state { - State::Re(_) | State::ReEsc(_) => { - return Err(format!( - "escape or balance opening brace on l. {}", - open_brace_line - )); - } - State::LitEsc => return Err(format!("incomplete escape sequence on l. {}", linum)), - _ => (), - } - parsed.push_str(®ex::escape(&buffer)); - - Ok(parsed) -} - -#[cfg(test)] -mod test { - use super::parse_template; - - #[test] - fn test_parse_license_template() { - assert_eq!( - parse_template("literal (.*)").unwrap(), - r"^literal \(\.\*\)" - ); - assert_eq!(parse_template(r"escaping \}").unwrap(), r"^escaping \}"); - assert!(parse_template("unbalanced } without escape").is_err()); - assert_eq!( - parse_template(r"{\d+} place{-?}holder{s?}").unwrap(), - r"^\d+ place-?holders?" - ); - assert_eq!(parse_template("default {}").unwrap(), "^default .*?"); - assert_eq!( - parse_template(r"unbalanced nested braces {\{{3}}").unwrap(), - r"^unbalanced nested braces \{{3}" - ); - assert_eq!( - parse_template("parsing error }").unwrap_err(), - "escape or balance closing brace on l. 1" - ); - assert_eq!( - parse_template("parsing error {\nsecond line").unwrap_err(), - "escape or balance opening brace on l. 1" - ); - assert_eq!( - parse_template(r"parsing error \").unwrap_err(), - "incomplete escape sequence on l. 1" - ); - } -} diff --git a/src/config/config_type.rs b/src/config/config_type.rs index fe0e4c309e2..8b9a6b2d84d 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -408,7 +408,7 @@ macro_rules! create_config { license_template_path, e); return; }; - let license_template_parsed = match license::parse_template(&license_template_str) { + let license_template_parsed = match TemplateParser::parse(&license_template_str) { Ok(string) => string, Err(e) => { eprintln!("Warning: unable to parse license template file {:?}: {}", diff --git a/src/config/license.rs b/src/config/license.rs new file mode 100644 index 00000000000..3de04599129 --- /dev/null +++ b/src/config/license.rs @@ -0,0 +1,213 @@ +use regex; + +// the template is parsed using a state machine +enum ParsingState { + Lit, + LitEsc, + // the u32 keeps track of brace nesting + Re(u32), + ReEsc(u32), + Abort(String), +} + +use self::ParsingState::*; + +pub struct TemplateParser { + parsed: String, + buffer: String, + state: ParsingState, + linum: u32, + open_brace_line: u32, +} + +impl TemplateParser { + fn new() -> Self { + Self { + parsed: "^".to_owned(), + buffer: String::new(), + state: Lit, + linum: 1, + // keeps track of last line on which a regex placeholder was started + open_brace_line: 0, + } + } + + /// Convert a license template into a string which can be turned into a regex. + /// + /// The license template could use regex syntax directly, but that would require a lot of manual + /// escaping, which is inconvenient. It is therefore literal by default, with optional regex + /// subparts delimited by `{` and `}`. Additionally: + /// + /// - to insert literal `{`, `}` or `\`, escape it with `\` + /// - an empty regex placeholder (`{}`) is shorthand for `{.*?}` + /// + /// This function parses this input format and builds a properly escaped *string* representation + /// of the equivalent regular expression. It **does not** however guarantee that the returned + /// string is a syntactically valid regular expression. + /// + /// # Examples + /// + /// ``` + /// # use rustfmt_config::license::TemplateParser; + /// assert_eq!( + /// TemplateParser::parse( + /// r" + /// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)} + /// // file at the top-level directory of this distribution and at + /// // {}. + /// // + /// // Licensed under the Apache License, Version 2.0 or the MIT license + /// // , at your + /// // option. This file may not be copied, modified, or distributed + /// // except according to those terms. + /// " + /// ).unwrap(), + /// r"^ + /// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+) + /// // file at the top\-level directory of this distribution and at + /// // .*?\. + /// // + /// // Licensed under the Apache License, Version 2\.0 or the MIT license + /// // , at your + /// // option\. This file may not be copied, modified, or distributed + /// // except according to those terms\. + /// " + /// ); + /// ``` + pub fn parse(template: &str) -> Result { + let mut parser = Self::new(); + for chr in template.chars() { + if chr == '\n' { + parser.linum += 1; + } + parser.state = match parser.state { + Lit => parser.trans_from_lit(chr), + LitEsc => parser.trans_from_litesc(chr), + Re(brace_nesting) => parser.trans_from_re(chr, brace_nesting), + ReEsc(brace_nesting) => parser.trans_from_reesc(chr, brace_nesting), + Abort(msg) => return Err(msg), + }; + } + // check if we've ended parsing in a valid state + match parser.state { + Abort(msg) => return Err(msg), + Re(_) | ReEsc(_) => { + return Err(format!( + "escape or balance opening brace on l. {}", + parser.open_brace_line + )); + } + LitEsc => return Err(format!("incomplete escape sequence on l. {}", parser.linum)), + _ => (), + } + parser.parsed.push_str(®ex::escape(&parser.buffer)); + + Ok(parser.parsed) + } + + fn trans_from_lit(&mut self, chr: char) -> ParsingState { + match chr { + '{' => { + self.parsed.push_str(®ex::escape(&self.buffer)); + self.buffer.clear(); + self.open_brace_line = self.linum; + Re(1) + } + '}' => Abort(format!( + "escape or balance closing brace on l. {}", + self.linum + )), + '\\' => LitEsc, + _ => { + self.buffer.push(chr); + Lit + } + } + } + + fn trans_from_litesc(&mut self, chr: char) -> ParsingState { + self.buffer.push(chr); + Lit + } + + fn trans_from_re(&mut self, chr: char, brace_nesting: u32) -> ParsingState { + match chr { + '{' => { + self.buffer.push(chr); + Re(brace_nesting + 1) + } + '}' => { + match brace_nesting { + 1 => { + // default regex for empty placeholder {} + if self.buffer.is_empty() { + self.parsed.push_str(".*?"); + } else { + self.parsed.push_str(&self.buffer); + } + self.buffer.clear(); + Lit + } + _ => { + self.buffer.push(chr); + Re(brace_nesting - 1) + } + } + } + '\\' => { + self.buffer.push(chr); + ReEsc(brace_nesting) + } + _ => { + self.buffer.push(chr); + Re(brace_nesting) + } + } + } + + fn trans_from_reesc(&mut self, chr: char, brace_nesting: u32) -> ParsingState { + self.buffer.push(chr); + Re(brace_nesting) + } +} + +#[cfg(test)] +mod test { + use super::TemplateParser; + + #[test] + fn test_parse_license_template() { + assert_eq!( + TemplateParser::parse("literal (.*)").unwrap(), + r"^literal \(\.\*\)" + ); + assert_eq!( + TemplateParser::parse(r"escaping \}").unwrap(), + r"^escaping \}" + ); + assert!(TemplateParser::parse("unbalanced } without escape").is_err()); + assert_eq!( + TemplateParser::parse(r"{\d+} place{-?}holder{s?}").unwrap(), + r"^\d+ place-?holders?" + ); + assert_eq!(TemplateParser::parse("default {}").unwrap(), "^default .*?"); + assert_eq!( + TemplateParser::parse(r"unbalanced nested braces {\{{3}}").unwrap(), + r"^unbalanced nested braces \{{3}" + ); + assert_eq!( + TemplateParser::parse("parsing error }").unwrap_err(), + "escape or balance closing brace on l. 1" + ); + assert_eq!( + TemplateParser::parse("parsing error {\nsecond line").unwrap_err(), + "escape or balance opening brace on l. 1" + ); + assert_eq!( + TemplateParser::parse(r"parsing error \").unwrap_err(), + "incomplete escape sequence on l. 1" + ); + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 0d4ec8557d3..8b93743ec4d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -29,6 +29,7 @@ pub mod license; use config::config_type::ConfigType; use config::file_lines::FileLines; +use config::license::TemplateParser; pub use config::lists::*; pub use config::options::*; use config::summary::Summary; -- cgit 1.4.1-3-g733a5 From b33451b4ede7f1114641928a06bb908551613637 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 15:50:33 +0100 Subject: Fix indentation in create_config macro definition --- src/config/config_type.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 8b9a6b2d84d..4c2e4c3d5bb 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -398,21 +398,21 @@ macro_rules! create_config { Ok(file) => file, Err(e) => { eprintln!("Warning: unable to open license template file {:?}: {}", - license_template_path, e); + license_template_path, e); return; } }; let mut license_template_str = String::new(); if let Err(e) = license_template_file.read_to_string(&mut license_template_str) { eprintln!("Warning: unable to read from license template file {:?}: {}", - license_template_path, e); + license_template_path, e); return; }; let license_template_parsed = match TemplateParser::parse(&license_template_str) { Ok(string) => string, Err(e) => { eprintln!("Warning: unable to parse license template file {:?}: {}", - license_template_path, e); + license_template_path, e); return; } }; @@ -420,7 +420,7 @@ macro_rules! create_config { Ok(re) => Some(re), Err(e) => { eprintln!("Warning: regex syntax error in placeholder, unable to compile \ - license template from file {:?}: {}", license_template_path, e); + license template from file {:?}: {}", license_template_path, e); return; } } -- cgit 1.4.1-3-g733a5 From 533d185f49af8434e44fd0f24bf4f1f1be8fb8d9 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 15:57:31 +0100 Subject: Shorten var names to comply with line len reqs --- src/config/config_type.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 4c2e4c3d5bb..0dcd377bffd 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -393,34 +393,34 @@ macro_rules! create_config { fn set_license_template(&mut self) { if self.was_set().license_template_path() { - let license_template_path = self.license_template_path(); - let mut license_template_file = match File::open(&license_template_path) { + let lt_path = self.license_template_path(); + let mut lt_file = match File::open(<_path) { Ok(file) => file, Err(e) => { eprintln!("Warning: unable to open license template file {:?}: {}", - license_template_path, e); + lt_path, e); return; } }; - let mut license_template_str = String::new(); - if let Err(e) = license_template_file.read_to_string(&mut license_template_str) { + let mut lt_str = String::new(); + if let Err(e) = lt_file.read_to_string(&mut lt_str) { eprintln!("Warning: unable to read from license template file {:?}: {}", - license_template_path, e); + lt_path, e); return; }; - let license_template_parsed = match TemplateParser::parse(&license_template_str) { + let lt_parsed = match TemplateParser::parse(<_str) { Ok(string) => string, Err(e) => { eprintln!("Warning: unable to parse license template file {:?}: {}", - license_template_path, e); + lt_path, e); return; } }; - self.license_template = match Regex::new(&license_template_parsed) { + self.license_template = match Regex::new(<_parsed) { Ok(re) => Some(re), Err(e) => { eprintln!("Warning: regex syntax error in placeholder, unable to compile \ - license template from file {:?}: {}", license_template_path, e); + license template from file {:?}: {}", lt_path, e); return; } } -- cgit 1.4.1-3-g733a5 From 1db84a3ec5ba40792f549bd815559f7d0c1ba234 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 26 Feb 2018 18:53:46 +0100 Subject: Wrap license-related errors in enum --- src/config/config_type.rs | 47 +++++++++++---------------------- src/config/license.rs | 67 ++++++++++++++++++++++++++++++++++++++--------- src/config/mod.rs | 2 +- 3 files changed, 71 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 0dcd377bffd..314a1a26b4e 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -392,39 +392,22 @@ macro_rules! create_config { } fn set_license_template(&mut self) { - if self.was_set().license_template_path() { - let lt_path = self.license_template_path(); - let mut lt_file = match File::open(<_path) { - Ok(file) => file, - Err(e) => { - eprintln!("Warning: unable to open license template file {:?}: {}", - lt_path, e); - return; - } - }; - let mut lt_str = String::new(); - if let Err(e) = lt_file.read_to_string(&mut lt_str) { - eprintln!("Warning: unable to read from license template file {:?}: {}", - lt_path, e); - return; - }; - let lt_parsed = match TemplateParser::parse(<_str) { - Ok(string) => string, - Err(e) => { - eprintln!("Warning: unable to parse license template file {:?}: {}", - lt_path, e); - return; - } - }; - self.license_template = match Regex::new(<_parsed) { - Ok(re) => Some(re), - Err(e) => { - eprintln!("Warning: regex syntax error in placeholder, unable to compile \ - license template from file {:?}: {}", lt_path, e); - return; - } - } + if !self.was_set().license_template_path() { + return; } + let lt_path = self.license_template_path(); + let try = || -> Result { + let mut lt_file = File::open(<_path)?; + let mut lt_str = String::new(); + lt_file.read_to_string(&mut lt_str)?; + let lt_parsed = TemplateParser::parse(<_str)?; + Ok(Regex::new(<_parsed)?) + }; + match try() { + Ok(re) => self.license_template = Some(re), + Err(msg) => eprintln!("Warning for license template file {:?}: {}", + lt_path, msg), + }; } } diff --git a/src/config/license.rs b/src/config/license.rs index 3de04599129..ce05634b876 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -1,5 +1,37 @@ +use std::io; +use std::fmt; + use regex; +#[derive(Debug)] +pub enum LicenseError { + IO(io::Error), + Regex(regex::Error), + Parse(String), +} + +impl fmt::Display for LicenseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + LicenseError::IO(ref err) => err.fmt(f), + LicenseError::Regex(ref err) => err.fmt(f), + LicenseError::Parse(ref err) => write!(f, "parsing failed, {}", err), + } + } +} + +impl From for LicenseError { + fn from(err: io::Error) -> LicenseError { + LicenseError::IO(err) + } +} + +impl From for LicenseError { + fn from(err: regex::Error) -> LicenseError { + LicenseError::Regex(err) + } +} + // the template is parsed using a state machine enum ParsingState { Lit, @@ -76,7 +108,7 @@ impl TemplateParser { /// " /// ); /// ``` - pub fn parse(template: &str) -> Result { + pub fn parse(template: &str) -> Result { let mut parser = Self::new(); for chr in template.chars() { if chr == '\n' { @@ -87,19 +119,24 @@ impl TemplateParser { LitEsc => parser.trans_from_litesc(chr), Re(brace_nesting) => parser.trans_from_re(chr, brace_nesting), ReEsc(brace_nesting) => parser.trans_from_reesc(chr, brace_nesting), - Abort(msg) => return Err(msg), + Abort(msg) => return Err(LicenseError::Parse(msg)), }; } // check if we've ended parsing in a valid state match parser.state { - Abort(msg) => return Err(msg), + Abort(msg) => return Err(LicenseError::Parse(msg)), Re(_) | ReEsc(_) => { - return Err(format!( + return Err(LicenseError::Parse(format!( "escape or balance opening brace on l. {}", parser.open_brace_line - )); + ))); + } + LitEsc => { + return Err(LicenseError::Parse(format!( + "incomplete escape sequence on l. {}", + parser.linum + ))) } - LitEsc => return Err(format!("incomplete escape sequence on l. {}", parser.linum)), _ => (), } parser.parsed.push_str(®ex::escape(&parser.buffer)); @@ -198,16 +235,22 @@ mod test { r"^unbalanced nested braces \{{3}" ); assert_eq!( - TemplateParser::parse("parsing error }").unwrap_err(), - "escape or balance closing brace on l. 1" + &TemplateParser::parse("parsing error }") + .unwrap_err() + .to_string(), + "parsing failed, escape or balance closing brace on l. 1" ); assert_eq!( - TemplateParser::parse("parsing error {\nsecond line").unwrap_err(), - "escape or balance opening brace on l. 1" + &TemplateParser::parse("parsing error {\nsecond line") + .unwrap_err() + .to_string(), + "parsing failed, escape or balance opening brace on l. 1" ); assert_eq!( - TemplateParser::parse(r"parsing error \").unwrap_err(), - "incomplete escape sequence on l. 1" + &TemplateParser::parse(r"parsing error \") + .unwrap_err() + .to_string(), + "parsing failed, incomplete escape sequence on l. 1" ); } } diff --git a/src/config/mod.rs b/src/config/mod.rs index 8b93743ec4d..8142b5034fb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -29,7 +29,7 @@ pub mod license; use config::config_type::ConfigType; use config::file_lines::FileLines; -use config::license::TemplateParser; +use config::license::{LicenseError, TemplateParser}; pub use config::lists::*; pub use config::options::*; use config::summary::Summary; -- cgit 1.4.1-3-g733a5 From 085cc90599bea1c31f565f1495c4ce79d177ce49 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Tue, 27 Feb 2018 15:00:29 +0100 Subject: Load and compile template in proper function Get rid of the unncessary closure. --- src/config/config_type.rs | 22 +++++++--------------- src/config/license.rs | 11 +++++++++++ src/config/mod.rs | 1 - 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 314a1a26b4e..dc768490fbb 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -392,22 +392,14 @@ macro_rules! create_config { } fn set_license_template(&mut self) { - if !self.was_set().license_template_path() { - return; + if self.was_set().license_template_path() { + let lt_path = self.license_template_path(); + match license::load_and_compile_template(<_path) { + Ok(re) => self.license_template = Some(re), + Err(msg) => eprintln!("Warning for license template file {:?}: {}", + lt_path, msg), + } } - let lt_path = self.license_template_path(); - let try = || -> Result { - let mut lt_file = File::open(<_path)?; - let mut lt_str = String::new(); - lt_file.read_to_string(&mut lt_str)?; - let lt_parsed = TemplateParser::parse(<_str)?; - Ok(Regex::new(<_parsed)?) - }; - match try() { - Ok(re) => self.license_template = Some(re), - Err(msg) => eprintln!("Warning for license template file {:?}: {}", - lt_path, msg), - }; } } diff --git a/src/config/license.rs b/src/config/license.rs index ce05634b876..1830fcb3cf2 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -1,7 +1,10 @@ use std::io; use std::fmt; +use std::fs::File; +use std::io::Read; use regex; +use regex::Regex; #[derive(Debug)] pub enum LicenseError { @@ -210,6 +213,14 @@ impl TemplateParser { } } +pub fn load_and_compile_template(path: &str) -> Result { + let mut lt_file = File::open(&path)?; + let mut lt_str = String::new(); + lt_file.read_to_string(&mut lt_str)?; + let lt_parsed = TemplateParser::parse(<_str)?; + Ok(Regex::new(<_parsed)?) +} + #[cfg(test)] mod test { use super::TemplateParser; diff --git a/src/config/mod.rs b/src/config/mod.rs index 8142b5034fb..0d4ec8557d3 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -29,7 +29,6 @@ pub mod license; use config::config_type::ConfigType; use config::file_lines::FileLines; -use config::license::{LicenseError, TemplateParser}; pub use config::lists::*; pub use config::options::*; use config::summary::Summary; -- cgit 1.4.1-3-g733a5 From 01f652799d94140493e97a7af9ad3b696fdba5e1 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Mon, 5 Mar 2018 13:39:30 +0100 Subject: Make license doctest pass again --- src/config/license.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/license.rs b/src/config/license.rs index 1830fcb3cf2..b2babd5ac19 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -83,7 +83,7 @@ impl TemplateParser { /// # Examples /// /// ``` - /// # use rustfmt_config::license::TemplateParser; + /// # use rustfmt_nightly::config::license::TemplateParser; /// assert_eq!( /// TemplateParser::parse( /// r" -- cgit 1.4.1-3-g733a5 From 8ea79aa0259c497006bdd56e0690c1420b6d8514 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Mon, 5 Mar 2018 22:45:40 +0900 Subject: add offset_left(4) for 'dyn ' --- src/types.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 75c8f3eabd8..fd6b6e3ca56 100644 --- a/src/types.rs +++ b/src/types.rs @@ -617,9 +617,12 @@ impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { ast::TyKind::TraitObject(ref bounds, tobj_syntax) => { - let res = bounds.rewrite(context, shape)?; // we have to consider 'dyn' keyword is used or not!!! - if tobj_syntax == ast::TraitObjectSyntax::Dyn { + let is_dyn = tobj_syntax == ast::TraitObjectSyntax::Dyn; + // 4 is length of 'dyn ' + let shape = if is_dyn { shape.offset_left(4)? } else { shape }; + let res = bounds.rewrite(context, shape)?; + if is_dyn { Some(format!("dyn {}", res)) } else { Some(res) -- cgit 1.4.1-3-g733a5 From d316eba54d6778593ec87cdeffc32a89d0064ae9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 6 Mar 2018 19:46:03 +0900 Subject: Add opt_span_before() to SpanUtils trait With some refactorings to avoid duplicated code. --- src/codemap.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/codemap.rs b/src/codemap.rs index 224b2083561..f6c05f5be40 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -22,6 +22,7 @@ pub trait SpanUtils { fn span_after_last(&self, original: Span, needle: &str) -> BytePos; fn span_before(&self, original: Span, needle: &str) -> BytePos; fn opt_span_after(&self, original: Span, needle: &str) -> Option; + fn opt_span_before(&self, original: Span, needle: &str) -> Option; } pub trait LineRangeUtils { @@ -35,10 +36,7 @@ pub trait LineRangeUtils { impl<'a> SpanUtils for SnippetProvider<'a> { fn span_after(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).expect("Bad snippet"); - let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len(); - - original.lo() + BytePos(offset as u32) + self.opt_span_after(original, needle).expect("bad span") } fn span_after_last(&self, original: Span, needle: &str) -> BytePos { @@ -53,15 +51,17 @@ impl<'a> SpanUtils for SnippetProvider<'a> { } fn span_before(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let offset = snippet.find_uncommented(needle).unwrap(); - - original.lo() + BytePos(offset as u32) + self.opt_span_before(original, needle).expect("bad span") } fn opt_span_after(&self, original: Span, needle: &str) -> Option { + self.opt_span_before(original, needle) + .map(|bytepos| bytepos + BytePos(needle.len() as u32)) + } + + fn opt_span_before(&self, original: Span, needle: &str) -> Option { let snippet = self.span_to_snippet(original)?; - let offset = snippet.find_uncommented(needle)? + needle.len(); + let offset = snippet.find_uncommented(needle)?; Some(original.lo() + BytePos(offset as u32)) } -- cgit 1.4.1-3-g733a5 From 5416c4df76e07d4eb4c70abf39c5c1c0cad7315c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 6 Mar 2018 19:47:28 +0900 Subject: Modify code around ast::Visibility `ast::Visibility` is changed to `codemap::Spanned` whose node is `ast::VisibilityKind`. This commit fixes it. Closes #2398. --- src/items.rs | 38 +++++++++++++++----------------------- src/utils.rs | 14 +++++++------- 2 files changed, 22 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3503546c010..ce1bc1ae318 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,8 +16,7 @@ use std::cmp::min; use config::lists::*; use regex::Regex; use syntax::{abi, ast, ptr, symbol}; -use syntax::ast::{CrateSugar, ImplItem}; -use syntax::codemap::{BytePos, Span}; +use syntax::codemap::{self, BytePos, Span}; use syntax::visit; use codemap::{LineRangeUtils, SpanUtils}; @@ -39,6 +38,11 @@ use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_co use vertical::rewrite_with_alignment; use visitor::FmtVisitor; +const DEFAULT_VISIBILITY: ast::Visibility = codemap::Spanned { + node: ast::VisibilityKind::Inherited, + span: codemap::DUMMY_SP, +}; + fn type_annotation_separator(config: &Config) -> &str { colon_spaces(config.space_before_colon(), config.space_after_colon()) } @@ -191,7 +195,7 @@ impl<'a> FnSig<'a> { abi: method_sig.abi, decl: &*method_sig.decl, generics, - visibility: ast::Visibility::Inherited, + visibility: DEFAULT_VISIBILITY, } } @@ -680,7 +684,7 @@ pub fn format_impl( fn is_impl_single_line( context: &RewriteContext, - items: &[ImplItem], + items: &[ast::ImplItem], result: &str, where_clause_str: &str, item: &ast::Item, @@ -869,7 +873,7 @@ impl<'a> StructParts<'a> { StructParts { prefix: "", ident: variant.node.name, - vis: &ast::Visibility::Inherited, + vis: &DEFAULT_VISIBILITY, def: &variant.node.data, generics: None, span: variant.span, @@ -1208,21 +1212,9 @@ pub fn format_struct_struct( } } -/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not -/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need -/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args. -fn get_bytepos_after_visibility( - context: &RewriteContext, - vis: &ast::Visibility, - default_span: Span, - terminator: &str, -) -> BytePos { - match *vis { - ast::Visibility::Crate(s, CrateSugar::PubCrate) => context - .snippet_provider - .span_after(mk_sp(s.hi(), default_span.hi()), terminator), - ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(), - ast::Visibility::Restricted { ref path, .. } => path.span.hi(), +fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> BytePos { + match vis.node { + ast::VisibilityKind::Crate(..) | ast::VisibilityKind::Restricted { .. } => vis.span.hi(), _ => default_span.lo(), } } @@ -1240,7 +1232,7 @@ fn format_tuple_struct( result.push_str(&header_str); let body_lo = if fields.is_empty() { - let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")"); + let lo = get_bytepos_after_visibility(struct_parts.vis, span); context .snippet_provider .span_after(mk_sp(lo, span.hi()), "(") @@ -1522,7 +1514,7 @@ impl<'a> StaticParts<'a> { }; StaticParts { prefix: "const", - vis: &ast::Visibility::Inherited, + vis: &DEFAULT_VISIBILITY, ident: ti.ident, ty, mutability: ast::Mutability::Immutable, @@ -1874,7 +1866,7 @@ fn rewrite_fn_base( } // Skip `pub(crate)`. - let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")"); + let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span); // A conservative estimation, to goal is to be over all parens in generics let args_start = fn_sig .generics diff --git a/src/utils.rs b/src/utils.rs index 5ec5ee18009..f6d2ff23c34 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -12,7 +12,7 @@ use std::borrow::Cow; use syntax::{abi, ptr}; use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, - NestedMetaItemKind, Path, Visibility}; + NestedMetaItemKind, Path, Visibility, VisibilityKind}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use config::Color; @@ -35,12 +35,12 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize { // Uses Cow to avoid allocating in the common cases. pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { - match *vis { - Visibility::Public => Cow::from("pub "), - Visibility::Inherited => Cow::from(""), - Visibility::Crate(_, CrateSugar::PubCrate) => Cow::from("pub(crate) "), - Visibility::Crate(_, CrateSugar::JustCrate) => Cow::from("crate "), - Visibility::Restricted { ref path, .. } => { + match vis.node { + VisibilityKind::Public => Cow::from("pub "), + VisibilityKind::Inherited => Cow::from(""), + VisibilityKind::Crate(CrateSugar::PubCrate) => Cow::from("pub(crate) "), + VisibilityKind::Crate(CrateSugar::JustCrate) => Cow::from("crate "), + VisibilityKind::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); if path.is_global() { -- cgit 1.4.1-3-g733a5 From d7495324bcd0671070ec1f651df27778fea63afe Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 6 Mar 2018 19:56:49 +0900 Subject: Work around removal of beginning_vert field from ast::Arm `ast::Arm` used to have `beginning_vert` field whose type is `Option` and holds a span of the beginning `|` if available. This field is now removed. This commit works around that. Since we only need a `BytePos` of the `|`, the type of `beginning_vert` in `ArmWrapper` is `Option`. --- src/expr.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++---------- src/spanned.rs | 6 +++--- 2 files changed, 53 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8ce1166cfcd..31bab9672b0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1231,23 +1231,43 @@ pub fn is_unsafe_block(block: &ast::Block) -> bool { } } -// A simple wrapper type against ast::Arm. Used inside write_list(). +/// A simple wrapper type against ast::Arm. Used inside write_list(). struct ArmWrapper<'a> { pub arm: &'a ast::Arm, - // True if the arm is the last one in match expression. Used to decide on whether we should add - // trailing comma to the match arm when `config.trailing_comma() == Never`. + /// True if the arm is the last one in match expression. Used to decide on whether we should add + /// trailing comma to the match arm when `config.trailing_comma() == Never`. pub is_last: bool, + /// Holds a byte position of `|` at the beginning of the arm pattern, if available. + pub beginning_vert: Option, } impl<'a> ArmWrapper<'a> { - pub fn new(arm: &'a ast::Arm, is_last: bool) -> ArmWrapper<'a> { - ArmWrapper { arm, is_last } + pub fn new( + arm: &'a ast::Arm, + is_last: bool, + beginning_vert: Option, + ) -> ArmWrapper<'a> { + ArmWrapper { + arm, + is_last, + beginning_vert, + } + } +} + +impl<'a> Spanned for ArmWrapper<'a> { + fn span(&self) -> Span { + if let Some(lo) = self.beginning_vert { + mk_sp(lo, self.arm.span().hi()) + } else { + self.arm.span() + } } } impl<'a> Rewrite for ArmWrapper<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) + rewrite_match_arm(context, self.arm, shape, self.is_last, self.beginning_vert) } } @@ -1344,6 +1364,23 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { } } +/// Collect a byte position of the beginning `|` for each arm, if available. +fn collect_beginning_verts( + context: &RewriteContext, + arms: &[ast::Arm], + span: Span, +) -> Vec> { + let mut beginning_verts = Vec::with_capacity(arms.len()); + let mut lo = context.snippet_provider.span_after(span, "{"); + for arm in arms { + let hi = arm.pats[0].span.lo(); + let missing_span = mk_sp(lo, hi); + beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); + lo = arm.span().hi(); + } + beginning_verts +} + fn rewrite_match_arms( context: &RewriteContext, arms: &[ast::Arm], @@ -1359,15 +1396,17 @@ fn rewrite_match_arms( let is_last_iter = repeat(false) .take(arm_len.checked_sub(1).unwrap_or(0)) .chain(repeat(true)); + let beginning_verts = collect_beginning_verts(context, arms, span); let items = itemize_list( context.snippet_provider, arms.iter() .zip(is_last_iter) - .map(|(arm, is_last)| ArmWrapper::new(arm, is_last)), + .zip(beginning_verts.into_iter()) + .map(|((arm, is_last), beginning_vert)| ArmWrapper::new(arm, is_last, beginning_vert)), "}", "|", - |arm| arm.arm.span().lo(), - |arm| arm.arm.span().hi(), + |arm| arm.span().lo(), + |arm| arm.span().hi(), |arm| arm.rewrite(context, arm_shape), open_brace_pos, span.hi(), @@ -1394,6 +1433,7 @@ fn rewrite_match_arm( arm: &ast::Arm, shape: Shape, is_last: bool, + beginning_vert: Option, ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { @@ -1417,7 +1457,7 @@ fn rewrite_match_arm( context, &arm.pats, &arm.guard, - arm.beginning_vert.is_some(), + beginning_vert.is_some(), shape, ).and_then(|pats_str| { combine_strs_with_missing_comments( diff --git a/src/spanned.rs b/src/spanned.rs index 20dd8438798..d1f4865dead 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -89,10 +89,10 @@ impl Spanned for ast::Ty { impl Spanned for ast::Arm { fn span(&self) -> Span { - let lo = if let Some(sp) = self.beginning_vert { - sp.lo() - } else { + let lo = if self.attrs.is_empty() { self.pats[0].span.lo() + } else { + self.attrs[0].span.lo() }; span_with_attrs_lo_hi!(self, lo, self.body.span.hi()) } -- cgit 1.4.1-3-g733a5 From 520f0d65ef884df7e1d8b46d3cab16d304685562 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 6 Mar 2018 20:02:04 +0900 Subject: Format multiple patterns in 'if let' and `while let' Closes #2511. --- src/expr.rs | 202 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 97 insertions(+), 105 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 31bab9672b0..337080f6c99 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -730,7 +730,7 @@ struct ControlFlow<'a> { block: &'a ast::Block, else_block: Option<&'a ast::Expr>, label: Option, - pat: Option<&'a ast::Pat>, + pats: Option>, keyword: &'a str, matcher: &'a str, connector: &'a str, @@ -754,7 +754,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { Some(ControlFlow::new_if( cond, - Some(pat), + Some(ptr_vec_to_ref_vec(pat)), if_block, else_block.as_ref().map(|e| &**e), expr_type == ExprType::SubExpression, @@ -772,7 +772,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option Some(ControlFlow::new_while(None, cond, block, label, expr.span)) } ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( - ControlFlow::new_while(Some(pat), cond, block, label, expr.span), + ControlFlow::new_while(Some(ptr_vec_to_ref_vec(pat)), cond, block, label, expr.span), ), _ => None, } @@ -781,24 +781,25 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option impl<'a> ControlFlow<'a> { fn new_if( cond: &'a ast::Expr, - pat: Option<&'a ast::Pat>, + pats: Option>, block: &'a ast::Block, else_block: Option<&'a ast::Expr>, allow_single_line: bool, nested_if: bool, span: Span, ) -> ControlFlow<'a> { + let matcher = match pats { + Some(..) => "let", + None => "", + }; ControlFlow { cond: Some(cond), block, else_block, label: None, - pat, + pats, keyword: "if", - matcher: match pat { - Some(..) => "let", - None => "", - }, + matcher, connector: " =", allow_single_line, nested_if, @@ -812,7 +813,7 @@ impl<'a> ControlFlow<'a> { block, else_block: None, label, - pat: None, + pats: None, keyword: "loop", matcher: "", connector: "", @@ -823,23 +824,24 @@ impl<'a> ControlFlow<'a> { } fn new_while( - pat: Option<&'a ast::Pat>, + pats: Option>, cond: &'a ast::Expr, block: &'a ast::Block, label: Option, span: Span, ) -> ControlFlow<'a> { + let matcher = match pats { + Some(..) => "let", + None => "", + }; ControlFlow { cond: Some(cond), block, else_block: None, label, - pat, + pats, keyword: "while", - matcher: match pat { - Some(..) => "let", - None => "", - }, + matcher, connector: " =", allow_single_line: false, nested_if: false, @@ -859,7 +861,7 @@ impl<'a> ControlFlow<'a> { block, else_block: None, label, - pat: Some(pat), + pats: Some(vec![pat]), keyword: "for", matcher: "", connector: " in", @@ -914,6 +916,46 @@ impl<'a> ControlFlow<'a> { } impl<'a> ControlFlow<'a> { + fn rewrite_pat_expr( + &self, + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, + offset: usize, + ) -> Option { + debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pats, expr); + + let cond_shape = shape.offset_left(offset)?; + if let Some(ref pat) = self.pats { + let matcher = if self.matcher.is_empty() { + self.matcher.to_owned() + } else { + format!("{} ", self.matcher) + }; + let pat_shape = cond_shape + .offset_left(matcher.len())? + .sub_width(self.connector.len())?; + let pat_string = rewrite_multiple_patterns(context, pat, pat_shape)?; + let result = format!("{}{}{}", matcher, pat_string, self.connector); + return rewrite_assign_rhs(context, result, expr, cond_shape); + } + + let expr_rw = expr.rewrite(context, cond_shape); + // The expression may (partially) fit on the current line. + // We do not allow splitting between `if` and condition. + if self.keyword == "if" || expr_rw.is_some() { + return expr_rw; + } + + // The expression won't fit on the current line, jump to next. + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); + expr.rewrite(context, nested_shape) + .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw)) + } + fn rewrite_cond( &self, context: &RewriteContext, @@ -922,11 +964,7 @@ impl<'a> ControlFlow<'a> { ) -> Option<(String, usize)> { // Do not take the rhs overhead from the upper expressions into account // when rewriting pattern. - let new_width = context - .config - .max_width() - .checked_sub(shape.used_width()) - .unwrap_or(0); + let new_width = context.budget(shape.used_width()); let fresh_shape = Shape { width: new_width, ..shape @@ -944,16 +982,7 @@ impl<'a> ControlFlow<'a> { let offset = self.keyword.len() + label_string.len() + 1; let pat_expr_string = match self.cond { - Some(cond) => rewrite_pat_expr( - context, - self.pat, - cond, - self.matcher, - self.connector, - self.keyword, - constr_shape, - offset, - )?, + Some(cond) => self.rewrite_pat_expr(context, cond, constr_shape, offset)?, None => String::new(), }; @@ -1007,9 +1036,9 @@ impl<'a> ControlFlow<'a> { context .snippet_provider .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), - self.pat.map_or(cond_span.lo(), |p| { + self.pats.as_ref().map_or(cond_span.lo(), |p| { if self.matcher.is_empty() { - p.span.lo() + p[0].span.lo() } else { context .snippet_provider @@ -1102,7 +1131,7 @@ impl<'a> Rewrite for ControlFlow<'a> { ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if( cond, - Some(pat), + Some(ptr_vec_to_ref_vec(pat)), if_block, next_else_block.as_ref().map(|e| &**e), false, @@ -1455,7 +1484,7 @@ fn rewrite_match_arm( }; let pats_str = rewrite_match_pattern( context, - &arm.pats, + &ptr_vec_to_ref_vec(&arm.pats), &arm.guard, beginning_vert.is_some(), shape, @@ -1513,7 +1542,7 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { fn rewrite_match_pattern( context: &RewriteContext, - pats: &[ptr::P], + pats: &[&ast::Pat], guard: &Option>, has_beginning_vert: bool, shape: Shape, @@ -1524,36 +1553,7 @@ fn rewrite_match_pattern( let pat_shape = shape .sub_width(5)? .offset_left(if has_beginning_vert { 2 } else { 0 })?; - - let pat_strs = pats.iter() - .map(|p| p.rewrite(context, pat_shape)) - .collect::>>()?; - - let use_mixed_layout = pats.iter() - .zip(pat_strs.iter()) - .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = if use_mixed_layout { - DefinitiveListTactic::Mixed - } else { - definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::VerticalBar, - pat_shape.width, - ) - }; - let fmt = ListFormatting { - tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - separator_place: context.config.binop_separator(), - shape: pat_shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; - let pats_str = write_list(&items, &fmt)?; + let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?; let beginning_vert = if has_beginning_vert { "| " } else { "" }; // Guard @@ -1749,48 +1749,40 @@ fn rewrite_guard( } } -fn rewrite_pat_expr( +fn rewrite_multiple_patterns( context: &RewriteContext, - pat: Option<&ast::Pat>, - expr: &ast::Expr, - matcher: &str, - // Connecting piece between pattern and expression, - // *without* trailing space. - connector: &str, - keyword: &str, + pats: &[&ast::Pat], shape: Shape, - offset: usize, ) -> Option { - debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr); - let cond_shape = shape.offset_left(offset)?; - if let Some(pat) = pat { - let matcher = if matcher.is_empty() { - matcher.to_owned() - } else { - format!("{} ", matcher) - }; - let pat_shape = cond_shape - .offset_left(matcher.len())? - .sub_width(connector.len())?; - let pat_string = pat.rewrite(context, pat_shape)?; - let result = format!("{}{}{}", matcher, pat_string, connector); - return rewrite_assign_rhs(context, result, expr, cond_shape); - } - - let expr_rw = expr.rewrite(context, cond_shape); - // The expression may (partially) fit on the current line. - // We do not allow splitting between `if` and condition. - if keyword == "if" || expr_rw.is_some() { - return expr_rw; - } + let pat_strs = pats.iter() + .map(|p| p.rewrite(context, shape)) + .collect::>>()?; - // The expression won't fit on the current line, jump to next. - let nested_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); - expr.rewrite(context, nested_shape) - .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw)) + let use_mixed_layout = pats.iter() + .zip(pat_strs.iter()) + .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let tactic = if use_mixed_layout { + DefinitiveListTactic::Mixed + } else { + definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + shape.width, + ) + }; + let fmt = ListFormatting { + tactic, + separator: " |", + trailing_separator: SeparatorTactic::Never, + separator_place: context.config.binop_separator(), + shape: shape, + ends_with_newline: false, + preserve_newline: false, + config: context.config, + }; + write_list(&items, &fmt) } fn can_extend_match_arm_body(body: &ast::Expr) -> bool { -- cgit 1.4.1-3-g733a5 From 3f0b630845b7d083db8a7a195f6aa019ab7bf51b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 6 Mar 2018 20:05:47 +0900 Subject: Support parentheses in patterns --- src/expr.rs | 4 +++- src/patterns.rs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 337080f6c99..0179d00b919 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1536,7 +1536,9 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { ast::PatKind::TupleStruct(ref path, ref subpats, _) => { path.segments.len() <= 1 && subpats.len() <= 1 } - ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p), + ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => { + is_short_pattern_inner(&*p) + } } } diff --git a/src/patterns.rs b/src/patterns.rs index 4bcf2890c35..e94f13b9daf 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -129,6 +129,8 @@ impl Rewrite for Pat { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), + PatKind::Paren(ref pat) => pat.rewrite(context, shape.offset_left(1)?.sub_width(1)?) + .map(|inner_pat| format!("({})", inner_pat)), } } } -- cgit 1.4.1-3-g733a5 From b3fa50db7320aa23e94ec15d774ad47c856757b5 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 7 Mar 2018 10:51:28 +0900 Subject: Use nested_shape for indenting types of lazy_static --- src/macros.rs | 2 +- tests/source/lazy_static.rs | 8 ++++++++ tests/target/lazy_static.rs | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index e7238a314fc..6be6a1f2664 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -916,7 +916,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) "{}static ref {}: {} =", vis, id, - ty.rewrite(context, shape)? + ty.rewrite(context, nested_shape)? )); result.push_str(&::expr::rewrite_assign_rhs( context, diff --git a/tests/source/lazy_static.rs b/tests/source/lazy_static.rs index c1c74fb8307..38fefbcbef5 100644 --- a/tests/source/lazy_static.rs +++ b/tests/source/lazy_static.rs @@ -35,3 +35,11 @@ let ptr = :: remacs_sys :: xmalloc ( remacs_sys :: Lisp_Subr ; :: std :: ptr :: copy_nonoverlapping ( & subr , ptr , 1 ) ; :: std :: mem :: forget ( subr ) ; :: lisp :: ExternalPtr :: new ( ptr ) } } ; } + + +lazy_static! { +static ref FOO: HashMap Result, Either> +),> = HashMap::new(); +} diff --git a/tests/target/lazy_static.rs b/tests/target/lazy_static.rs index edce6e7b894..0aed6d38ccf 100644 --- a/tests/target/lazy_static.rs +++ b/tests/target/lazy_static.rs @@ -37,3 +37,13 @@ lazy_static! { } }; } + +lazy_static! { + static ref FOO: HashMap< + String, + ( + &'static str, + fn(Foo) -> Result, Either> + ), + > = HashMap::new(); +} -- cgit 1.4.1-3-g733a5 From 9889678f56e61e158195d6097626adc0374db619 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 8 Mar 2018 12:56:28 +0900 Subject: Replace Option> with Vec<&'a ast::Pat> --- src/expr.rs | 60 ++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 0179d00b919..2945f03a535 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -730,7 +730,7 @@ struct ControlFlow<'a> { block: &'a ast::Block, else_block: Option<&'a ast::Expr>, label: Option, - pats: Option>, + pats: Vec<&'a ast::Pat>, keyword: &'a str, matcher: &'a str, connector: &'a str, @@ -744,7 +744,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option match expr.node { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( cond, - None, + vec![], if_block, else_block.as_ref().map(|e| &**e), expr_type == ExprType::SubExpression, @@ -754,7 +754,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { Some(ControlFlow::new_if( cond, - Some(ptr_vec_to_ref_vec(pat)), + ptr_vec_to_ref_vec(pat), if_block, else_block.as_ref().map(|e| &**e), expr_type == ExprType::SubExpression, @@ -768,30 +768,39 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option ast::ExprKind::Loop(ref block, label) => { Some(ControlFlow::new_loop(block, label, expr.span)) } - ast::ExprKind::While(ref cond, ref block, label) => { - Some(ControlFlow::new_while(None, cond, block, label, expr.span)) - } + ast::ExprKind::While(ref cond, ref block, label) => Some(ControlFlow::new_while( + vec![], + cond, + block, + label, + expr.span, + )), ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( - ControlFlow::new_while(Some(ptr_vec_to_ref_vec(pat)), cond, block, label, expr.span), + ControlFlow::new_while(ptr_vec_to_ref_vec(pat), cond, block, label, expr.span), ), _ => None, } } +fn choose_matcher(pats: &[&ast::Pat]) -> &'static str { + if pats.is_empty() { + "" + } else { + "let" + } +} + impl<'a> ControlFlow<'a> { fn new_if( cond: &'a ast::Expr, - pats: Option>, + pats: Vec<&'a ast::Pat>, block: &'a ast::Block, else_block: Option<&'a ast::Expr>, allow_single_line: bool, nested_if: bool, span: Span, ) -> ControlFlow<'a> { - let matcher = match pats { - Some(..) => "let", - None => "", - }; + let matcher = choose_matcher(&pats); ControlFlow { cond: Some(cond), block, @@ -813,7 +822,7 @@ impl<'a> ControlFlow<'a> { block, else_block: None, label, - pats: None, + pats: vec![], keyword: "loop", matcher: "", connector: "", @@ -824,16 +833,13 @@ impl<'a> ControlFlow<'a> { } fn new_while( - pats: Option>, + pats: Vec<&'a ast::Pat>, cond: &'a ast::Expr, block: &'a ast::Block, label: Option, span: Span, ) -> ControlFlow<'a> { - let matcher = match pats { - Some(..) => "let", - None => "", - }; + let matcher = choose_matcher(&pats); ControlFlow { cond: Some(cond), block, @@ -861,7 +867,7 @@ impl<'a> ControlFlow<'a> { block, else_block: None, label, - pats: Some(vec![pat]), + pats: vec![pat], keyword: "for", matcher: "", connector: " in", @@ -926,7 +932,7 @@ impl<'a> ControlFlow<'a> { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pats, expr); let cond_shape = shape.offset_left(offset)?; - if let Some(ref pat) = self.pats { + if !self.pats.is_empty() { let matcher = if self.matcher.is_empty() { self.matcher.to_owned() } else { @@ -935,7 +941,7 @@ impl<'a> ControlFlow<'a> { let pat_shape = cond_shape .offset_left(matcher.len())? .sub_width(self.connector.len())?; - let pat_string = rewrite_multiple_patterns(context, pat, pat_shape)?; + let pat_string = rewrite_multiple_patterns(context, &self.pats, pat_shape)?; let result = format!("{}{}{}", matcher, pat_string, self.connector); return rewrite_assign_rhs(context, result, expr, cond_shape); } @@ -1036,15 +1042,17 @@ impl<'a> ControlFlow<'a> { context .snippet_provider .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), - self.pats.as_ref().map_or(cond_span.lo(), |p| { + if self.pats.is_empty() { + cond_span.lo() + } else { if self.matcher.is_empty() { - p[0].span.lo() + self.pats[0].span.lo() } else { context .snippet_provider .span_before(self.span, self.matcher.trim()) } - }), + }, ); let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape); @@ -1131,7 +1139,7 @@ impl<'a> Rewrite for ControlFlow<'a> { ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if( cond, - Some(ptr_vec_to_ref_vec(pat)), + ptr_vec_to_ref_vec(pat), if_block, next_else_block.as_ref().map(|e| &**e), false, @@ -1142,7 +1150,7 @@ impl<'a> Rewrite for ControlFlow<'a> { ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if( cond, - None, + vec![], if_block, next_else_block.as_ref().map(|e| &**e), false, -- cgit 1.4.1-3-g733a5 From 822dd41ad907b2147340541ffc3d28b6eb6109db Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 8 Mar 2018 17:21:30 +0900 Subject: Put lhs and rhs of binop on the same line if lhs is short --- src/expr.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2945f03a535..d6603659c7f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -352,13 +352,15 @@ where .and_then(|s| s.sub_width(pp.suffix.len())) .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); if let Some(ref rhs_result) = rhs_orig_result { - // If the rhs looks like block expression, we allow it to stay on the same line - // with the lhs even if it is multi-lined. - let allow_same_line = rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); + // If the length of the lhs is equal to or shorter than the tab width or + // the rhs looks like block expression, we put the rhs on the same + // line with the lhs even if the rhs is multi-lined. + let allow_same_line = lhs_result.len() <= context.config.tab_spaces() + || rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { let one_line_width = last_line_width(&lhs_result) + pp.infix.len() + first_line_width(rhs_result) + pp.suffix.len(); -- cgit 1.4.1-3-g733a5 From a2f861730e5b33391c97fe7ec91470d1c9b96ba9 Mon Sep 17 00:00:00 2001 From: moe <35686186+csmoe@users.noreply.github.com> Date: Thu, 8 Mar 2018 17:05:39 +0800 Subject: fix adds a trailing comma to struct-like macro (#2490) * fix adds a trailing comma to struct-like macro --- src/expr.rs | 39 ++++++++++++++++++++++++++------------- tests/source/issue-2445.rs | 21 +++++++++++++++++++++ tests/target/issue-2445.rs | 21 +++++++++++++++++++++ 3 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 tests/source/issue-2445.rs create mode 100644 tests/target/issue-2445.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2945f03a535..481baa80de6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -20,7 +20,7 @@ use chains::rewrite_chain; use closures; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, FindUncommented}; + rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented}; use config::{Config, ControlBraceStyle, IndentStyle}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; @@ -2411,20 +2411,20 @@ pub fn wrap_args_with_parens( /// trailing comma. This function is used when rewriting macro, as adding or removing a trailing /// comma from macro can potentially break the code. fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { - let mut encountered_closing_paren = false; - for c in context.snippet(span).chars().rev() { + let mut result: bool = Default::default(); + let mut prev_char: char = Default::default(); + + for (kind, c) in CharClasses::new(context.snippet(span).chars()) { match c { - ',' => return true, - ')' => if encountered_closing_paren { - return false; - } else { - encountered_closing_paren = true; - }, - _ if c.is_whitespace() => continue, - _ => return false, + _ if kind.is_comment() || c.is_whitespace() => continue, + ')' | '}' => result = result && prev_char != c, + ',' => result = true, + _ => result = false, } + prev_char = c; } - false + + result } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { @@ -2608,7 +2608,20 @@ fn rewrite_struct_lit<'a>( let tactic = struct_lit_tactic(h_shape, context, &item_vec); let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); - let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some()); + + let ends_with_comma = span_ends_with_comma(context, span); + let force_no_trailing_comma = if context.inside_macro && !ends_with_comma { + true + } else { + false + }; + + let fmt = struct_lit_formatting( + nested_shape, + tactic, + context, + force_no_trailing_comma || base.is_some(), + ); write_list(&item_vec, &fmt)? }; diff --git a/tests/source/issue-2445.rs b/tests/source/issue-2445.rs new file mode 100644 index 00000000000..84ce6e647b8 --- /dev/null +++ b/tests/source/issue-2445.rs @@ -0,0 +1,21 @@ +test!(RunPassPretty { + // comment + path: "src/test/run-pass/pretty", + mode: "pretty", + suite: "run-pass", + default: false, + host: true // should, force, , no trailing comma here +}); + +test!(RunPassPretty { + // comment + path: "src/test/run-pass/pretty", + mode: "pretty", + suite: "run-pass", + default: false, + host: true, // should, , preserve, the trailing comma +}); + +test!(Test{ + field: i32, // comment +}); diff --git a/tests/target/issue-2445.rs b/tests/target/issue-2445.rs new file mode 100644 index 00000000000..1bc7752fd16 --- /dev/null +++ b/tests/target/issue-2445.rs @@ -0,0 +1,21 @@ +test!(RunPassPretty { + // comment + path: "src/test/run-pass/pretty", + mode: "pretty", + suite: "run-pass", + default: false, + host: true // should, force, , no trailing comma here +}); + +test!(RunPassPretty { + // comment + path: "src/test/run-pass/pretty", + mode: "pretty", + suite: "run-pass", + default: false, + host: true, // should, , preserve, the trailing comma +}); + +test!(Test { + field: i32, // comment +}); -- cgit 1.4.1-3-g733a5 From a6b574bfa7a301405b64d54e7576d001fb22b7db Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 8 Mar 2018 16:29:00 +0900 Subject: Cargo update and cargo clippy --- Cargo.lock | 79 +++++++++++++++++++++++++++---------------------- Cargo.toml | 4 +-- src/bin/main.rs | 2 +- src/expr.rs | 16 +++++----- src/format-diff/main.rs | 2 +- src/git-rustfmt/main.rs | 2 +- src/lib.rs | 8 ++--- 7 files changed, 60 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index c92b7cb9b23..e865f2d1b53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -102,10 +102,10 @@ name = "env_logger" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -268,24 +268,27 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "57.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -294,7 +297,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "57.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -302,50 +305,50 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "57.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "57.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "57.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "57.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -367,9 +370,9 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -519,6 +522,11 @@ dependencies = [ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-segmentation" version = "1.2.0" @@ -596,7 +604,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" -"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" +"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" @@ -631,14 +639,14 @@ dependencies = [ "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" -"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" -"checksum rustc-ap-rustc_cratesio_shim 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cec17c61275586dc539c662c72a34cd907c2a3284656c1c7a73de43c38fb1c4a" -"checksum rustc-ap-rustc_data_structures 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8358567a8a378e34b5ffcd2e266b02a524ba8189374f6e90f788c1aae748cb63" -"checksum rustc-ap-rustc_errors 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8e3ed225d3531044c1ddcbf31e79eaa00387451440a485818fec8e6a9e25d03" -"checksum rustc-ap-serialize 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8415efe18266da2aa1b68dc386128485f5f360d6f6e5a4c4ad8d48e6f757c858" -"checksum rustc-ap-syntax 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afd0049fc03db2c516e50c3089304d21de7ff0c38ed282a8ec655cc012c12145" -"checksum rustc-ap-syntax_pos 57.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d51e454e21f66e41737d9294254ec8f7be392699834570a45d0155be30dda75" +"checksum regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a62bf8bb734ab90b7f234b681b01af396e5d39b028906c210dc04fa1d5e9e5b3" +"checksum regex-syntax 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48d7391e7e90e06eaf3aefbe4652464153ecfec64806f3bf77ffc59638a63e77" +"checksum rustc-ap-rustc_cratesio_shim 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdab515774981bbc3bc25e2100e338d7536ada96a0f8b3b73b95843d2832001" +"checksum rustc-ap-rustc_data_structures 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc20957dcf8cb9a585299fa1428a37b8e64de5f8810060fef22c7079a9de4b01" +"checksum rustc-ap-rustc_errors 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "765b7063bfd56d7d57b5883b97c1ec381b64d0d7b85d4d131c4b4b319dc61ea2" +"checksum rustc-ap-serialize 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "733ade6fd9bb57e3cf26c0185af1930c4d2f67c2049b95f99973e143744c4eb6" +"checksum rustc-ap-syntax 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e06967572c333febd3834874cb56d6442b894d9e5a41d28e9a42f09869cc5bc" +"checksum rustc-ap-syntax_pos 60.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8aebf406db73579363faa50cd85d8111fe9c17004a89d9c9fe78bb6f5d949e1" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -657,6 +665,7 @@ dependencies = [ "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/Cargo.toml b/Cargo.toml index 3758862da67..3be0c4ff7a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,8 +48,8 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5" -rustc-ap-syntax = "57.0.0" -rustc-ap-rustc_errors = "57.0.0" +rustc-ap-syntax = "60.0.0" +rustc-ap-rustc_errors = "60.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/bin/main.rs b/src/bin/main.rs index d58cb50ac68..b9d413bbed0 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -335,7 +335,7 @@ fn execute(opts: &Options) -> FmtResult { } fn main() { - let _ = env_logger::init(); + env_logger::init(); let opts = make_opts(); diff --git a/src/expr.rs b/src/expr.rs index 481baa80de6..2cbeaaa584b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1044,14 +1044,12 @@ impl<'a> ControlFlow<'a> { .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), if self.pats.is_empty() { cond_span.lo() + } else if self.matcher.is_empty() { + self.pats[0].span.lo() } else { - if self.matcher.is_empty() { - self.pats[0].span.lo() - } else { - context - .snippet_provider - .span_before(self.span, self.matcher.trim()) - } + context + .snippet_provider + .span_before(self.span, self.matcher.trim()) }, ); @@ -1268,7 +1266,7 @@ pub fn is_unsafe_block(block: &ast::Block) -> bool { } } -/// A simple wrapper type against ast::Arm. Used inside write_list(). +/// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. struct ArmWrapper<'a> { pub arm: &'a ast::Arm, /// True if the arm is the last one in match expression. Used to decide on whether we should add @@ -1787,7 +1785,7 @@ fn rewrite_multiple_patterns( separator: " |", trailing_separator: SeparatorTactic::Never, separator_place: context.config.binop_separator(), - shape: shape, + shape, ends_with_newline: false, preserve_newline: false, config: context.config, diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index c42fbb6f7cf..6633da208e8 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -81,7 +81,7 @@ impl From for FormatDiffError { } fn main() { - let _ = env_logger::init(); + env_logger::init(); let mut opts = getopts::Options::new(); opts.optflag("h", "help", "show this message"); diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 8811c1a5255..41e4ee2931d 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -184,7 +184,7 @@ impl Config { } fn main() { - let _ = env_logger::init(); + env_logger::init(); let opts = make_opts(); let matches = opts.parse(env::args().skip(1)) diff --git a/src/lib.rs b/src/lib.rs index e53f8bfb907..9447155ee92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -798,7 +798,7 @@ pub fn get_modified_lines( let mut config = config.clone(); config.set().write_mode(config::WriteMode::Modified); - let (summary, filemap, formatreport) = format_input(input, &config, Some(&mut data))?; + let (summary, filemap, report) = format_input(input, &config, Some(&mut data))?; let mut lines = data.lines(); let mut chunks = Vec::new(); @@ -823,9 +823,9 @@ pub fn get_modified_lines( }); } Ok(ModifiedLinesResult { - summary: summary, - filemap: filemap, - report: formatreport, + summary, + filemap, + report, modified_lines: ModifiedLines { chunks }, }) } -- cgit 1.4.1-3-g733a5 From 71ca21fc23ee0c2ea52d5440dca758bf1344b476 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 8 Mar 2018 19:08:38 +0900 Subject: Disallow combining parens and brackets in impl --- src/items.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ce1bc1ae318..3793ae36577 100644 --- a/src/items.rs +++ b/src/items.rs @@ -33,8 +33,8 @@ use types::join_bounds; use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, - last_line_extendable, last_line_used_width, last_line_width, mk_sp, - semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; + last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, + stmt_expr, trimmed_last_line_width}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -631,8 +631,7 @@ pub fn format_impl( } result.push_str(&where_clause_str); - let need_newline = !last_line_extendable(&result) - && (last_line_contains_single_line_comment(&result) || result.contains('\n')); + let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n'); match context.config.brace_style() { _ if need_newline => result.push_str(&sep), BraceStyle::AlwaysNextLine => result.push_str(&sep), -- cgit 1.4.1-3-g733a5 From d45aa55bd6f8a3d46e1044b8be697d24623e5a58 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 8 Mar 2018 20:25:18 +0900 Subject: Remove nested parens And make sure that we do not remove comments within parens. --- src/expr.rs | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2cbeaaa584b..85a2e658ef2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -79,7 +79,7 @@ pub fn format_expr( let callee_str = callee.rewrite(context, shape)?; rewrite_call(context, &callee_str, args, inner_span, shape) } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape), + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span), ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator rewrite_pair( @@ -2425,8 +2425,36 @@ fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { result } -fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { +fn rewrite_paren( + context: &RewriteContext, + mut subexpr: &ast::Expr, + shape: Shape, + mut span: Span, +) -> Option { debug!("rewrite_paren, shape: {:?}", shape); + + // Extract comments within parens. + let mut pre_comment; + let mut post_comment; + loop { + // 1 = "(" or ")" + let pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span.lo()); + let post_span = mk_sp(subexpr.span.hi(), span.hi() - BytePos(1)); + pre_comment = rewrite_missing_comment(pre_span, shape, context)?; + post_comment = rewrite_missing_comment(post_span, shape, context)?; + + // Remove nested parens if there are no comments. + if let ast::ExprKind::Paren(ref subsubexpr) = subexpr.node { + if pre_comment.is_empty() && post_comment.is_empty() { + span = subexpr.span; + subexpr = subsubexpr; + continue; + } + } + + break; + } + let total_paren_overhead = paren_overhead(context); let paren_overhead = total_paren_overhead / 2; let sub_shape = shape @@ -2435,9 +2463,9 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> let paren_wrapper = |s: &str| { if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { - format!("( {} )", s) + format!("( {}{}{} )", pre_comment, s, post_comment) } else { - format!("({})", s) + format!("({}{}{})", pre_comment, s, post_comment) } }; -- cgit 1.4.1-3-g733a5 From 9344d2ca83dd9159aaa13cbd48929fe038009a27 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 9 Mar 2018 09:29:08 +0900 Subject: Fix a bug in attr::take_while_with_pred Closes #2520. --- src/attr.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 5d22bd9ffe7..7dedc65b0e0 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -98,13 +98,16 @@ fn take_while_with_pred<'a, P>( where P: Fn(&ast::Attribute) -> bool, { - let mut last_index = 0; - let mut iter = attrs.iter().enumerate().peekable(); - while let Some((i, attr)) = iter.next() { - if !pred(attr) { + let mut len = 0; + let mut iter = attrs.iter().peekable(); + + while let Some(attr) = iter.next() { + if pred(attr) { + len += 1; + } else { break; } - if let Some(&(_, next_attr)) = iter.peek() { + if let Some(next_attr) = iter.peek() { // Extract comments between two attributes. let span_between_attr = mk_sp(attr.span.hi(), next_attr.span.lo()); let snippet = context.snippet(span_between_attr); @@ -112,13 +115,9 @@ where break; } } - last_index = i; - } - if last_index == 0 { - &[] - } else { - &attrs[..last_index + 1] } + + &attrs[..len] } /// Rewrite the same kind of attributes at the same time. This includes doc -- cgit 1.4.1-3-g733a5 From 67fa394e4ed4f4a933c09f0cbd50a1e5b1af56e5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 9 Mar 2018 09:30:47 +0900 Subject: Restrict the width of doc comments with comment_width See the diff in tests/target/enum.rs for an example. --- src/attr.rs | 12 ++---------- src/shape.rs | 12 ++++++++++++ tests/target/enum.rs | 5 +++-- 3 files changed, 17 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 7dedc65b0e0..2e4a4632620 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -21,8 +21,6 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use utils::{count_newlines, mk_sp}; -use std::cmp; - /// Returns attributes on the given statement. pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { match stmt.node { @@ -140,7 +138,7 @@ fn rewrite_first_group_attrs( .join("\n"); return Some(( sugared_docs.len(), - rewrite_doc_comment(&snippet, shape, context.config)?, + rewrite_doc_comment(&snippet, shape.comment(context.config), context.config)?, )); } // Rewrite `#[derive(..)]`s. @@ -249,13 +247,7 @@ impl Rewrite for ast::Attribute { }; let snippet = context.snippet(self.span); if self.is_sugared_doc { - let doc_shape = Shape { - width: cmp::min(shape.width, context.config.comment_width()) - .checked_sub(shape.indent.width()) - .unwrap_or(0), - ..shape - }; - rewrite_doc_comment(snippet, doc_shape, context.config) + rewrite_doc_comment(snippet, shape.comment(context.config), context.config) } else { if contains_comment(snippet) { return Some(snippet.to_owned()); diff --git a/src/shape.rs b/src/shape.rs index 22d6a096efa..047a50340eb 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::borrow::Cow; +use std::cmp::min; use std::ops::{Add, Sub}; use Config; @@ -276,6 +277,17 @@ impl Shape { .checked_sub(self.used_width() + self.width) .unwrap_or(0) } + + pub fn comment(&self, config: &Config) -> Shape { + let width = min( + self.width, + config + .comment_width() + .checked_sub(self.indent.width()) + .unwrap_or(0), + ); + Shape { width, ..*self } + } } #[cfg(test)] diff --git a/tests/target/enum.rs b/tests/target/enum.rs index de88f610b6a..50d1037fe09 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -145,8 +145,9 @@ pub enum Bencoding<'i> { Str(&'i [u8]), Int(i64), List(Vec>), - /// A bencoded dict value. The first element the slice of bytes in the source that the dict is - /// composed of. The second is the dict, decoded into an ordered map. + /// A bencoded dict value. The first element the slice of bytes in the + /// source that the dict is composed of. The second is the dict, + /// decoded into an ordered map. // TODO make Dict "structlike" AKA name the two values. Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), } -- cgit 1.4.1-3-g733a5 From 484469899b1dc99c55826aa6c261fb3d3b1d7570 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 9 Mar 2018 09:46:43 +0900 Subject: Keep code block without correct backticks enclosing --- src/comment.rs | 9 +++++++++ tests/source/issue-2520.rs | 5 +++++ tests/target/issue-2520.rs | 5 +++++ 3 files changed, 19 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 74a14511be8..b0cdadaddd7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -391,6 +391,15 @@ fn rewrite_comment_inner( } else { code_block_buffer.push_str(line); code_block_buffer.push('\n'); + + if is_last { + // There is an code block that is not properly enclosed by backticks. + // We will leave them untouched. + result.push_str(&comment_line_separator); + result.push_str(&join_code_block_with_comment_line_separator( + &code_block_buffer, + )); + } } continue; diff --git a/tests/source/issue-2520.rs b/tests/source/issue-2520.rs index a6557340eab..d8ecf1f7d69 100644 --- a/tests/source/issue-2520.rs +++ b/tests/source/issue-2520.rs @@ -5,3 +5,8 @@ //! ``` #![deny( missing_docs )] + +//! ```rust +//! println!("hello, world"); + +#![deny( missing_docs )] diff --git a/tests/target/issue-2520.rs b/tests/target/issue-2520.rs index f3d4561dc67..012921f441c 100644 --- a/tests/target/issue-2520.rs +++ b/tests/target/issue-2520.rs @@ -5,3 +5,8 @@ //! ``` #![deny(missing_docs)] + +//! ```rust +//! println!("hello, world"); + +#![deny(missing_docs)] -- cgit 1.4.1-3-g733a5 From 1780d68761c840e69f039857c410cc3fcead068d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 9 Mar 2018 14:51:27 +1300 Subject: Catch panics in the parser before they crash rustfmt Closes #753 --- src/lib.rs | 75 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 9447155ee92..fe08b68c782 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, BufRead, Write}; use std::iter::repeat; +use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::PathBuf; use std::rc::Rc; use std::time::Duration; @@ -537,43 +538,48 @@ fn parse_input<'sess>( input: Input, parse_session: &'sess ParseSess, config: &Config, -) -> Result>> { - let result = match input { - Input::File(file) => { - let mut parser = parse::new_parser_from_file(parse_session, &file); - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - parser.parse_crate_mod() - } - Input::Text(text) => { - let mut parser = parse::new_parser_from_source_str( - parse_session, - FileName::Custom("stdin".to_owned()), - text, - ); - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - parser.parse_crate_mod() - } +) -> Result> { + let mut parser = match input { + Input::File(file) => parse::new_parser_from_file(parse_session, &file), + Input::Text(text) => parse::new_parser_from_source_str( + parse_session, + FileName::Custom("stdin".to_owned()), + text, + ), }; + parser.cfg_mods = false; + if config.skip_children() { + parser.recurse_into_file_modules = false; + } + + let mut parser = AssertUnwindSafe(parser); + let result = catch_unwind(move || parser.0.parse_crate_mod()); + match result { - Ok(c) => { + Ok(Ok(c)) => { if parse_session.span_diagnostic.has_errors() { // Bail out if the parser recovered from an error. - Err(None) + Err(ParseError::Recovered) } else { Ok(c) } } - Err(e) => Err(Some(e)), + Ok(Err(e)) => Err(ParseError::Error(e)), + Err(_) => Err(ParseError::Panic), } } +/// All the ways that parsing can fail. +enum ParseError<'sess> { + /// There was an error, but the parser recovered. + Recovered, + /// There was an error (supplied) and parsing failed. + Error(DiagnosticBuilder<'sess>), + /// The parser panicked. + Panic, +} + /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. pub fn format_snippet(snippet: &str, config: &Config) -> Option { @@ -682,9 +688,18 @@ pub fn format_input( let krate = match parse_input(input, &parse_session, config) { Ok(krate) => krate, - Err(diagnostic) => { - if let Some(mut diagnostic) = diagnostic { - diagnostic.emit(); + Err(err) => { + match err { + ParseError::Error(mut diagnostic) => diagnostic.emit(), + ParseError::Panic => { + // Note that if you see this message and want more information, + // then go to `parse_input` and run the parse function without + // `catch_unwind` so rustfmt panics and you can get a backtrace. + should_emit_verbose(&main_file, config, || { + println!("The Rust parser panicked") + }); + } + ParseError::Recovered => {} } summary.add_parsing_error(); return Ok((summary, FileMap::new(), FormatReport::new())); @@ -693,10 +708,6 @@ pub fn format_input( summary.mark_parse_time(); - if parse_session.span_diagnostic.has_errors() { - summary.add_parsing_error(); - } - // Suppress error output after parsing. let silent_emitter = Box::new(EmitterWriter::new( Box::new(Vec::new()), -- cgit 1.4.1-3-g733a5 From 84ad70c1517f49e8881c9fffbdceaeee39c48bd4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 9 Mar 2018 13:27:43 +0900 Subject: Add ignore config option For example, with the following config file, rustfmt will ignore `src/types.rs`, `src/foo/bar.rs` and every file under `examples/` directory. ```toml [ignore] files = [ "src/types.rs", "src/foo/bar.rs", ] directories = [ "examples", ] ``` --- Configurations.md | 29 ++++++++++++++++++++ src/bin/main.rs | 3 +- src/config/config_type.rs | 22 +++++++++++---- src/config/mod.rs | 5 +++- src/config/options.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- tests/lib.rs | 4 +-- 7 files changed, 124 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 8540bc36383..0b2048958e1 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2135,3 +2135,32 @@ Copyright 2018 The Rust Project Developers.`, etc.: ``` `\{`, `\}` and `\\` match literal braces / backslashes. + +## `ignore` + +Skip formatting the specified files and directories. + +- **Default value**: format every files +- **Possible values**: See an example below +- **Stable**: No + +### Example + +If you want to ignore specific files, put the following to your config file: + +```toml +[ignore] +files = [ + "src/types.rs", + "src/foo/bar.rs", +] +``` + +If you want to ignore every file under `examples/`, put the following to your config file: + +```toml +[ignore] +directories = [ + "examples", +] +``` diff --git a/src/bin/main.rs b/src/bin/main.rs index b9d413bbed0..4a49ce5a2e6 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -18,6 +18,7 @@ use std::{env, error}; use std::fs::File; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; +use std::str::FromStr; use getopts::{Matches, Options}; @@ -25,8 +26,6 @@ use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; use rustfmt::config::file_lines::FileLines; use rustfmt::{run, FileName, Input, Summary}; -use std::str::FromStr; - type FmtError = Box; type FmtResult = std::result::Result; diff --git a/src/config/config_type.rs b/src/config/config_type.rs index dc768490fbb..53a4fdb8e57 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -9,7 +9,7 @@ // except according to those terms. use config::file_lines::FileLines; -use config::options::WidthHeuristics; +use config::options::{IgnoreList, WidthHeuristics}; /// Trait for types that can be used in `Config`. pub trait ConfigType: Sized { @@ -54,6 +54,12 @@ impl ConfigType for WidthHeuristics { } } +impl ConfigType for IgnoreList { + fn doc_hint() -> String { + String::from("[,..]") + } +} + /// Check if we're in a nightly build. /// /// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap @@ -176,7 +182,7 @@ macro_rules! create_config { ConfigWasSet(self) } - fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { + fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config { $( if let Some(val) = parsed.$i { if self.$i.3 { @@ -195,6 +201,7 @@ macro_rules! create_config { )+ self.set_heuristics(); self.set_license_template(); + self.set_ignore(dir); self } @@ -216,7 +223,7 @@ macro_rules! create_config { } } - pub fn from_toml(toml: &str) -> Result { + pub fn from_toml(toml: &str, dir: &Path) -> Result { let parsed: ::toml::Value = toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; let mut err: String = String::new(); @@ -236,7 +243,7 @@ macro_rules! create_config { if !err.is_empty() { eprint!("{}", err); } - Ok(Config::default().fill_from_parsed_config(parsed_config)) + Ok(Config::default().fill_from_parsed_config(parsed_config, dir: &Path)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -300,7 +307,8 @@ macro_rules! create_config { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; - Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) + Config::from_toml(&toml, file_path.parent().unwrap()) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolve the config for input in `dir`. @@ -401,6 +409,10 @@ macro_rules! create_config { } } } + + fn set_ignore(&mut self, dir: &Path) { + self.ignore.2.add_prefix(dir); + } } // Template for the default configuration diff --git a/src/config/mod.rs b/src/config/mod.rs index 0d4ec8557d3..301b9e06b01 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -141,6 +141,8 @@ create_config! { "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; + ignore: IgnoreList, IgnoreList::default(), false, + "Skip formatting the specified files and directories."; // Not user-facing. verbose: bool, false, false, "Use verbose output"; @@ -208,7 +210,8 @@ mod test { #[test] fn test_was_set() { - let config = Config::from_toml("hard_tabs = true").unwrap(); + use std::path::Path; + let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); assert_eq!(config.was_set().hard_tabs(), true); assert_eq!(config.was_set().verbose(), false); diff --git a/src/config/options.rs b/src/config/options.rs index dcea4706ace..7a5f9785b9b 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use syntax::codemap::FileName; + use config::config_type::ConfigType; use config::lists::*; +use std::collections::HashSet; +use std::path::{Path, PathBuf}; + /// Macro for deriving implementations of Serialize/Deserialize for enums #[macro_export] macro_rules! impl_enum_serialize_and_deserialize { @@ -244,3 +249,68 @@ impl ::std::str::FromStr for WidthHeuristics { Err("WidthHeuristics is not parsable") } } + +/// A set of directories, files and modules that rustfmt should ignore. +#[derive(Default, Deserialize, Serialize, Clone, Debug)] +pub struct IgnoreList { + directories: Option>, + files: Option>, +} + +impl IgnoreList { + fn add_prefix_inner(set: &HashSet, dir: &Path) -> HashSet { + set.iter() + .map(|s| { + if s.has_root() { + s.clone() + } else { + let mut path = PathBuf::from(dir); + path.push(s); + path + } + }) + .collect() + } + + pub fn add_prefix(&mut self, dir: &Path) { + macro add_prefix_inner_with ($($field: ident),* $(,)*) { + $(if let Some(set) = self.$field.as_mut() { + *set = IgnoreList::add_prefix_inner(set, dir); + })* + } + + add_prefix_inner_with!(directories, files); + } + + fn is_ignore_file(&self, path: &Path) -> bool { + self.files.as_ref().map_or(false, |set| set.contains(path)) + } + + fn is_under_ignore_dir(&self, path: &Path) -> bool { + if let Some(ref dirs) = self.directories { + for dir in dirs { + if path.starts_with(dir) { + return true; + } + } + } + + false + } + + pub fn skip_file(&self, file: &FileName) -> bool { + if let FileName::Real(ref path) = file { + self.is_ignore_file(path) || self.is_under_ignore_dir(path) + } else { + false + } + } +} + +impl ::std::str::FromStr for IgnoreList { + type Err = &'static str; + + fn from_str(_: &str) -> Result { + Err("IgnoreList is not parsable") + } +} diff --git a/src/lib.rs b/src/lib.rs index 9447155ee92..ebd94e1b3d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -338,7 +338,7 @@ where // nothing to distinguish the nested module contents. let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; for (path, module) in modules::list_files(krate, parse_session.codemap())? { - if skip_children && path != *main_file { + if (skip_children && path != *main_file) || config.ignore().skip_file(&path) { continue; } should_emit_verbose(&path, config, || println!("Formatting {}", path)); diff --git a/tests/lib.rs b/tests/lib.rs index 9abe08ba9e0..9309941983d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -293,7 +293,7 @@ fn format_lines_errors_are_reported() { fn format_lines_errors_are_reported_with_tabs() { let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); - let config = Config::from_toml("hard_tabs = true").unwrap(); + let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); let (error_summary, _file_map, _report) = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); @@ -433,7 +433,7 @@ fn get_config(config_file: Option<&Path>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config).expect("Invalid toml") + Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml") } // Reads significant comments of the form: // rustfmt-key: value -- cgit 1.4.1-3-g733a5 From 8943c376bc7bdaf252c173aaf1b0f4f37de3f820 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 7 Mar 2018 15:37:44 +0900 Subject: Use RefCell for RewriteContext fields --- src/chains.rs | 2 +- src/rewrite.rs | 8 +++++--- src/visitor.rs | 6 ++++-- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 87100c7be41..f65a6916af5 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -251,7 +251,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - Cow::from("") } else { // Use new lines. - if context.force_one_line_chain { + if *context.force_one_line_chain.borrow() { return None; } nested_shape.indent.to_string_with_newline(context.config) diff --git a/src/rewrite.rs b/src/rewrite.rs index 708e31d86dd..01671227e39 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -17,6 +17,8 @@ use config::{Config, IndentStyle}; use shape::Shape; use visitor::SnippetProvider; +use std::cell::RefCell; + pub trait Rewrite { /// Rewrite self into shape. fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; @@ -29,12 +31,12 @@ pub struct RewriteContext<'a> { pub config: &'a Config, pub inside_macro: bool, // Force block indent style even if we are using visual indent style. - pub use_block: bool, + pub use_block: RefCell, // When `format_if_else_cond_comment` is true, unindent the comment on top // of the `else` or `else if`. pub is_if_else_block: bool, // When rewriting chain, veto going multi line except the last element - pub force_one_line_chain: bool, + pub force_one_line_chain: RefCell, pub snippet_provider: &'a SnippetProvider<'a>, } @@ -45,7 +47,7 @@ impl<'a> RewriteContext<'a> { /// Return true if we should use block indent style for rewriting function call. pub fn use_block_indent(&self) -> bool { - self.config.indent_style() == IndentStyle::Block || self.use_block + self.config.indent_style() == IndentStyle::Block || *self.use_block.borrow() } pub fn budget(&self, used_width: usize) -> usize { diff --git a/src/visitor.rs b/src/visitor.rs index 35102f58609..f1b50e19b61 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -26,6 +26,8 @@ use shape::{Indent, Shape}; use spanned::Spanned; use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; +use std::cell::RefCell; + /// Creates a string slice corresponding to the specified span. pub struct SnippetProvider<'a> { /// A pointer to the content of the file we are formatting. @@ -691,9 +693,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { codemap: self.codemap, config: self.config, inside_macro: false, - use_block: false, + use_block: RefCell::new(false), is_if_else_block: false, - force_one_line_chain: false, + force_one_line_chain: RefCell::new(false), snippet_provider: self.snippet_provider, } } -- cgit 1.4.1-3-g733a5 From ae629abc41fd1d0f28a1733b6deb17f9b9026579 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 7 Mar 2018 15:40:52 +0900 Subject: Add overflow module This commit adds `overflow` module. This module provides two APIs. `rewrite_with_parens` is basically the same as `rewrite_call_inner`. `rewrite_with_angle_brackets` is used for rewriting generics and types. --- src/expr.rs | 475 ++++-------------------------------------------------- src/items.rs | 15 +- src/lib.rs | 1 + src/macros.rs | 9 +- src/overflow.rs | 491 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/patterns.rs | 11 +- src/types.rs | 20 ++- 7 files changed, 558 insertions(+), 464 deletions(-) create mode 100644 src/overflow.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 85a2e658ef2..e69dd15aa0e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -25,6 +25,7 @@ use config::{Config, ControlBraceStyle, IndentStyle}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; use macros::{rewrite_macro, MacroArg, MacroPosition}; +use overflow; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; @@ -523,7 +524,7 @@ fn array_tactic( None => DefinitiveListTactic::Vertical, }; if tactic == DefinitiveListTactic::Vertical && !has_long_item - && is_every_args_simple(exprs) + && is_every_expr_simple(exprs) { DefinitiveListTactic::Mixed } else { @@ -1872,6 +1873,20 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } +/// In case special-case style is required, returns an offset from which we start horizontal layout. +pub fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { + if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST + .iter() + .find(|&&(s, _)| s == callee_str) + { + let all_simple = args.len() > num_args_before && is_every_expr_simple(args); + + Some((all_simple, num_args_before)) + } else { + None + } +} + /// A list of `format!`-like macros, that take a long format string and a list of arguments to /// format. /// @@ -1913,297 +1928,22 @@ pub fn rewrite_call( span: Span, shape: Shape, ) -> Option { - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) - } else { - false - }; - rewrite_call_inner( + overflow::rewrite_with_parens( context, callee, &ptr_vec_to_ref_vec(args), - span, shape, + span, context.config.width_heuristics().fn_call_width, - force_trailing_comma, - ) -} - -pub fn rewrite_call_inner<'a, T>( - context: &RewriteContext, - callee_str: &str, - args: &[&T], - span: Span, - shape: Shape, - args_max_width: usize, - force_trailing_comma: bool, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - // 2 = `( `, 1 = `(` - let paren_overhead = if context.config.spaces_within_parens_and_brackets() { - 2 - } else { - 1 - }; - let used_width = extra_offset(callee_str, shape); - let one_line_width = shape - .width - .checked_sub(used_width + 2 * paren_overhead) - .unwrap_or(0); - - // 1 = "(" or ")" - let one_line_shape = shape - .offset_left(last_line_width(callee_str) + 1) - .and_then(|shape| shape.sub_width(1)) - .unwrap_or(Shape { width: 0, ..shape }); - let nested_shape = shape_from_indent_style( - context, - shape, - used_width + 2 * paren_overhead, - used_width + paren_overhead, - )?; - - let span_lo = context.snippet_provider.span_after(span, "("); - let args_span = mk_sp(span_lo, span.hi()); - - let (extendable, list_str) = rewrite_call_args( - context, - args, - args_span, - one_line_shape, - nested_shape, - one_line_width, - args_max_width, - force_trailing_comma, - callee_str, - )?; - - if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable { - let mut new_context = context.clone(); - new_context.use_block = true; - return rewrite_call_inner( - &new_context, - callee_str, - args, - span, - shape, - args_max_width, - force_trailing_comma, - ); - } - - let args_shape = Shape { - width: shape - .width - .checked_sub(last_line_width(callee_str)) - .unwrap_or(0), - ..shape - }; - Some(format!( - "{}{}", - callee_str, - wrap_args_with_parens(context, &list_str, extendable, args_shape, nested_shape) - )) -} - -fn need_block_indent(s: &str, shape: Shape) -> bool { - s.lines().skip(1).any(|s| { - s.find(|c| !char::is_whitespace(c)) - .map_or(false, |w| w + 1 < shape.indent.width()) - }) -} - -fn rewrite_call_args<'a, T>( - context: &RewriteContext, - args: &[&T], - span: Span, - one_line_shape: Shape, - nested_shape: Shape, - one_line_width: usize, - args_max_width: usize, - force_trailing_comma: bool, - callee_str: &str, -) -> Option<(bool, String)> -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let items = itemize_list( - context.snippet_provider, - args.iter(), - ")", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - span.lo(), - span.hi(), - true, - ); - let mut item_vec: Vec<_> = items.collect(); - - // Try letting the last argument overflow to the next line with block - // indentation. If its first line fits on one line with the other arguments, - // we format the function arguments horizontally. - let tactic = try_overflow_last_arg( - context, - &mut item_vec, - &args[..], - one_line_shape, - nested_shape, - one_line_width, - args_max_width, - callee_str, - ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if force_trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro || !context.use_block_indent() { - SeparatorTactic::Never + if context.inside_macro { + span_ends_with_comma(context, span) } else { - context.config.trailing_comma() + false }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical, - preserve_newline: false, - config: context.config, - }; - - write_list(&item_vec, &fmt) - .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str)) -} - -fn try_overflow_last_arg<'a, T>( - context: &RewriteContext, - item_vec: &mut Vec, - args: &[&T], - one_line_shape: Shape, - nested_shape: Shape, - one_line_width: usize, - args_max_width: usize, - callee_str: &str, -) -> DefinitiveListTactic -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - // 1 = "(" - let combine_arg_with_callee = - callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1; - let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args); - - // Replace the last item with its first line to see if it fits with - // first arguments. - let placeholder = if overflow_last { - let mut context = context.clone(); - if !combine_arg_with_callee { - if let Some(expr) = args[args.len() - 1].to_expr() { - if let ast::ExprKind::MethodCall(..) = expr.node { - context.force_one_line_chain = true; - } - } - } - last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| { - rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape) - }) - } else { - None - }; - - let mut tactic = definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ); - - // Replace the stub with the full overflowing last argument if the rewrite - // succeeded and its first line fits with the other arguments. - match (overflow_last, tactic, placeholder) { - (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) if args.len() == 1 => { - // When we are rewriting a nested function call, we restrict the - // bugdet for the inner function to avoid them being deeply nested. - // However, when the inner function has a prefix or a suffix - // (e.g. `foo() as u32`), this budget reduction may produce poorly - // formatted code, where a prefix or a suffix being left on its own - // line. Here we explicitlly check those cases. - if count_newlines(overflowed) == 1 { - let rw = args.last() - .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); - let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); - if no_newline { - item_vec[args.len() - 1].item = rw; - } else { - item_vec[args.len() - 1].item = Some(overflowed.to_owned()); - } - } else { - item_vec[args.len() - 1].item = Some(overflowed.to_owned()); - } - } - (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { - item_vec[args.len() - 1].item = placeholder; - } - _ if args.len() >= 1 => { - item_vec[args.len() - 1].item = args.last() - .and_then(|last_arg| last_arg.rewrite(context, nested_shape)); - - let default_tactic = || { - definitive_tactic( - &*item_vec, - ListTactic::LimitedHorizontalVertical(args_max_width), - Separator::Comma, - one_line_width, - ) - }; - - // Use horizontal layout for a function with a single argument as long as - // everything fits in a single line. - if args.len() == 1 - && args_max_width != 0 // Vertical layout is forced. - && !item_vec[0].has_comment() - && !item_vec[0].inner_as_ref().contains('\n') - && ::lists::total_item_width(&item_vec[0]) <= one_line_width - { - tactic = DefinitiveListTactic::Horizontal; - } else { - tactic = default_tactic(); - - if tactic == DefinitiveListTactic::Vertical { - if let Some((all_simple, num_args_before)) = - maybe_get_args_offset(callee_str, args) - { - let one_line = all_simple - && definitive_tactic( - &item_vec[..num_args_before], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ) == DefinitiveListTactic::Horizontal - && definitive_tactic( - &item_vec[num_args_before + 1..], - ListTactic::HorizontalVertical, - Separator::Comma, - nested_shape.width, - ) == DefinitiveListTactic::Horizontal; - - if one_line { - tactic = DefinitiveListTactic::SpecialMacro(num_args_before); - }; - } - } - } - } - _ => (), - } - - tactic + ) } -fn is_simple_arg(expr: &ast::Expr) -> bool { +fn is_simple_expr(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, @@ -2213,106 +1953,18 @@ fn is_simple_arg(expr: &ast::Expr) -> bool { | ast::ExprKind::Field(ref expr, _) | ast::ExprKind::Try(ref expr) | ast::ExprKind::TupField(ref expr, _) - | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr), + | ast::ExprKind::Unary(_, ref expr) => is_simple_expr(expr), ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { - is_simple_arg(lhs) && is_simple_arg(rhs) + is_simple_expr(lhs) && is_simple_expr(rhs) } _ => false, } } -fn is_every_args_simple(lists: &[&T]) -> bool { +fn is_every_expr_simple(lists: &[&T]) -> bool { lists .iter() - .all(|arg| arg.to_expr().map_or(false, is_simple_arg)) -} - -/// In case special-case style is required, returns an offset from which we start horizontal layout. -fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { - if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST - .iter() - .find(|&&(s, _)| s == callee_str) - { - let all_simple = args.len() > num_args_before && is_every_args_simple(args); - - Some((all_simple, num_args_before)) - } else { - None - } -} - -/// Returns a shape for the last argument which is going to be overflowed. -fn last_arg_shape( - lists: &[&T], - items: &[ListItem], - shape: Shape, - args_max_width: usize, -) -> Option -where - T: Rewrite + Spanned + ToExpr, -{ - let is_nested_call = lists - .iter() - .next() - .and_then(|item| item.to_expr()) - .map_or(false, is_nested_call); - if items.len() == 1 && !is_nested_call { - return Some(shape); - } - let offset = items.iter().rev().skip(1).fold(0, |acc, i| { - // 2 = ", " - acc + 2 + i.inner_as_ref().len() - }); - Shape { - width: min(args_max_width, shape.width), - ..shape - }.offset_left(offset) -} - -fn rewrite_last_arg_with_overflow<'a, T>( - context: &RewriteContext, - args: &[&T], - last_item: &mut ListItem, - shape: Shape, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - let last_arg = args[args.len() - 1]; - let rewrite = if let Some(expr) = last_arg.to_expr() { - match expr.node { - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - ast::ExprKind::Closure(..) => { - // If the argument consists of multiple closures, we do not overflow - // the last closure. - if closures::args_have_many_closure(args) { - None - } else { - closures::rewrite_last_closure(context, expr, shape) - } - } - _ => expr.rewrite(context, shape), - } - } else { - last_arg.rewrite(context, shape) - }; - - if let Some(rewrite) = rewrite { - let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); - last_item.item = rewrite_first_line; - Some(rewrite) - } else { - None - } -} - -fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool -where - T: Rewrite + Spanned + ToExpr + 'a, -{ - args.last() - .map_or(false, |x| x.can_be_overflowed(context, args.len())) + .all(|arg| arg.to_expr().map_or(false, is_simple_expr)) } pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { @@ -2348,7 +2000,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l } } -fn is_nested_call(expr: &ast::Expr) -> bool { +pub fn is_nested_call(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, ast::ExprKind::AddrOf(_, ref expr) @@ -2360,55 +2012,10 @@ fn is_nested_call(expr: &ast::Expr) -> bool { } } -pub fn wrap_args_with_parens( - context: &RewriteContext, - args_str: &str, - is_extendable: bool, - shape: Shape, - nested_shape: Shape, -) -> String { - let paren_overhead = paren_overhead(context); - let fits_one_line = args_str.len() + paren_overhead <= shape.width; - let extend_width = if args_str.is_empty() { - paren_overhead - } else { - paren_overhead / 2 - }; - if !context.use_block_indent() - || (context.inside_macro && !args_str.contains('\n') && fits_one_line) - || (is_extendable && extend_width <= shape.width) - { - let mut result = String::with_capacity(args_str.len() + 4); - if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() { - result.push_str("( "); - result.push_str(args_str); - result.push_str(" )"); - } else { - result.push_str("("); - result.push_str(args_str); - result.push_str(")"); - } - result - } else { - let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); - let indent_str = shape.block().indent.to_string_with_newline(context.config); - let mut result = - String::with_capacity(args_str.len() + 2 + indent_str.len() + nested_indent_str.len()); - result.push_str("("); - if !args_str.is_empty() { - result.push_str(&nested_indent_str); - result.push_str(args_str); - } - result.push_str(&indent_str); - result.push_str(")"); - result - } -} - /// Return true if a function call or a method call represented by the given span ends with a /// trailing comma. This function is used when rewriting macro, as adding or removing a trailing /// comma from macro can potentially break the code. -fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { +pub fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { let mut result: bool = Default::default(); let mut prev_char: char = Default::default(); @@ -2735,24 +2342,6 @@ pub fn rewrite_field( } } -fn shape_from_indent_style( - context: &RewriteContext, - shape: Shape, - overhead: usize, - offset: usize, -) -> Option { - if context.use_block_indent() { - // 1 = "," - shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1) - } else { - shape.visual_indent(offset).sub_width(overhead) - } -} - fn rewrite_tuple_in_visual_indent_style<'a, T>( context: &RewriteContext, items: &[&T], @@ -2838,12 +2427,12 @@ where } else { items.len() == 1 }; - rewrite_call_inner( + overflow::rewrite_with_parens( context, - &String::new(), + "", items, - span, shape, + span, context.config.width_heuristics().fn_call_width, force_trailing_comma, ) diff --git a/src/items.rs b/src/items.rs index 3793ae36577..ac392ccf62e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,10 +23,10 @@ use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, - rewrite_call_inner, ExprType}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, ExprType}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; +use overflow; use shape::{Indent, Shape}; use spanned::Spanned; use types::join_bounds; @@ -1309,8 +1309,15 @@ fn format_tuple_struct( } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; let fields = &fields.iter().collect::>()[..]; - let one_line_width = context.config.width_heuristics().fn_call_width; - result = rewrite_call_inner(context, &result, fields, span, shape, one_line_width, false)?; + result = overflow::rewrite_with_parens( + context, + &result, + fields, + shape, + span, + context.config.width_heuristics().fn_call_width, + false, + )?; } if !where_clause_str.is_empty() && !where_clause_str.contains('\n') diff --git a/src/lib.rs b/src/lib.rs index fe08b68c782..6f18094661c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,7 @@ mod lists; mod macros; mod missed_spans; pub mod modules; +mod overflow; mod patterns; mod reorder; mod rewrite; diff --git a/src/macros.rs b/src/macros.rs index 6be6a1f2664..db79fb9d576 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -34,8 +34,9 @@ use syntax::util::ThinVec; use codemap::SpanUtils; use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; -use expr::{rewrite_array, rewrite_call_inner}; +use expr::rewrite_array; use lists::{itemize_list, write_list, ListFormatting}; +use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use utils::{format_visibility, mk_sp, wrap_str}; @@ -223,14 +224,14 @@ pub fn rewrite_macro( match style { MacroStyle::Parens => { - // Format macro invocation as function call, forcing no trailing + // Format macro invocation as function call, preserve the trailing // comma because not all macros support them. - rewrite_call_inner( + overflow::rewrite_with_parens( context, ¯o_name, &arg_vec.iter().map(|e| &*e).collect::>()[..], - mac.span, shape, + mac.span, context.config.width_heuristics().fn_call_width, trailing_comma, ).map(|rw| match position { diff --git a/src/overflow.rs b/src/overflow.rs new file mode 100644 index 00000000000..b5634def086 --- /dev/null +++ b/src/overflow.rs @@ -0,0 +1,491 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Rewrite a list some items with overflow. +// FIXME: Replace `ToExpr` with some enum. + +use config::lists::*; +use syntax::ast; +use syntax::codemap::Span; + +use closures; +use codemap::SpanUtils; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use rewrite::{Rewrite, RewriteContext}; +use expr::{is_nested_call, maybe_get_args_offset, ToExpr}; +use shape::Shape; +use spanned::Spanned; +use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp, paren_overhead}; + +use std::cmp::min; + +pub fn rewrite_with_parens( + context: &RewriteContext, + ident: &str, + items: &[&T], + shape: Shape, + span: Span, + item_max_width: usize, + force_trailing_comma: bool, +) -> Option +where + T: Rewrite + ToExpr + Spanned, +{ + Context::new( + context, + items, + ident, + shape, + span, + "(", + ")", + item_max_width, + force_trailing_comma, + ).rewrite(shape) +} + +pub fn rewrite_with_angle_brackets( + context: &RewriteContext, + ident: &str, + items: &[&T], + shape: Shape, + span: Span, +) -> Option +where + T: Rewrite + ToExpr + Spanned, +{ + Context::new( + context, + items, + ident, + shape, + span, + "<", + ">", + context.config.max_width(), + false, + ).rewrite(shape) +} + +struct Context<'a, T: 'a> { + context: &'a RewriteContext<'a>, + items: &'a [&'a T], + ident: &'a str, + prefix: &'static str, + suffix: &'static str, + one_line_shape: Shape, + nested_shape: Shape, + span: Span, + item_max_width: usize, + one_line_width: usize, + force_trailing_comma: bool, +} + +impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { + pub fn new( + context: &'a RewriteContext, + items: &'a [&'a T], + ident: &'a str, + shape: Shape, + span: Span, + prefix: &'static str, + suffix: &'static str, + item_max_width: usize, + force_trailing_comma: bool, + ) -> Context<'a, T> { + // 2 = `( `, 1 = `(` + let paren_overhead = if context.config.spaces_within_parens_and_brackets() { + 2 + } else { + 1 + }; + let used_width = extra_offset(ident, shape); + let one_line_width = shape + .width + .checked_sub(used_width + 2 * paren_overhead) + .unwrap_or(0); + + // 1 = "(" or ")" + let one_line_shape = shape + .offset_left(last_line_width(ident) + 1) + .and_then(|shape| shape.sub_width(1)) + .unwrap_or(Shape { width: 0, ..shape }); + let nested_shape = shape_from_indent_style( + context, + shape, + used_width + 2 * paren_overhead, + used_width + paren_overhead, + ); + Context { + context, + items, + ident, + one_line_shape, + nested_shape, + span, + prefix, + suffix, + item_max_width, + one_line_width, + force_trailing_comma, + } + } + + fn last_item(&self) -> Option<&&T> { + self.items.last() + } + + fn items_span(&self) -> Span { + let span_lo = self.context + .snippet_provider + .span_after(self.span, self.prefix); + mk_sp(span_lo, self.span.hi()) + } + + fn rewrite_last_item_with_overflow( + &self, + last_list_item: &mut ListItem, + shape: Shape, + ) -> Option { + let last_item = self.last_item()?; + let rewrite = if let Some(expr) = last_item.to_expr() { + match expr.node { + // When overflowing the closure which consists of a single control flow expression, + // force to use block if its condition uses multi line. + ast::ExprKind::Closure(..) => { + // If the argument consists of multiple closures, we do not overflow + // the last closure. + if closures::args_have_many_closure(self.items) { + None + } else { + closures::rewrite_last_closure(self.context, expr, shape) + } + } + _ => expr.rewrite(self.context, shape), + } + } else { + last_item.rewrite(self.context, shape) + }; + + if let Some(rewrite) = rewrite { + let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); + last_list_item.item = rewrite_first_line; + Some(rewrite) + } else { + None + } + } + + fn try_overflow_last_item(&self, list_items: &mut Vec) -> DefinitiveListTactic { + // 1 = "(" + let combine_arg_with_callee = self.items.len() == 1 && self.items[0].to_expr().is_some() + && self.ident.len() + 1 <= self.context.config.tab_spaces(); + let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, self.items); + + // Replace the last item with its first line to see if it fits with + // first arguments. + let placeholder = if overflow_last { + let old_value = *self.context.force_one_line_chain.borrow(); + if !combine_arg_with_callee { + if let Some(expr) = self.last_item().and_then(|item| item.to_expr()) { + if let ast::ExprKind::MethodCall(..) = expr.node { + self.context.force_one_line_chain.replace(true); + } + } + } + let result = last_item_shape( + self.items, + list_items, + self.one_line_shape, + self.item_max_width, + ).and_then(|arg_shape| { + self.rewrite_last_item_with_overflow( + &mut list_items[self.items.len() - 1], + arg_shape, + ) + }); + self.context.force_one_line_chain.replace(old_value); + result + } else { + None + }; + + let mut tactic = definitive_tactic( + &*list_items, + ListTactic::LimitedHorizontalVertical(self.item_max_width), + Separator::Comma, + self.one_line_width, + ); + + // Replace the stub with the full overflowing last argument if the rewrite + // succeeded and its first line fits with the other arguments. + match (overflow_last, tactic, placeholder) { + (true, DefinitiveListTactic::Horizontal, Some(ref overflowed)) + if self.items.len() == 1 => + { + // When we are rewriting a nested function call, we restrict the + // bugdet for the inner function to avoid them being deeply nested. + // However, when the inner function has a prefix or a suffix + // (e.g. `foo() as u32`), this budget reduction may produce poorly + // formatted code, where a prefix or a suffix being left on its own + // line. Here we explicitlly check those cases. + if count_newlines(overflowed) == 1 { + let rw = self.items + .last() + .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape)); + let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); + if no_newline { + list_items[self.items.len() - 1].item = rw; + } else { + list_items[self.items.len() - 1].item = Some(overflowed.to_owned()); + } + } else { + list_items[self.items.len() - 1].item = Some(overflowed.to_owned()); + } + } + (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { + list_items[self.items.len() - 1].item = placeholder; + } + _ if self.items.len() >= 1 => { + list_items[self.items.len() - 1].item = self.items + .last() + .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape)); + + let default_tactic = || { + definitive_tactic( + &*list_items, + ListTactic::LimitedHorizontalVertical(self.item_max_width), + Separator::Comma, + self.one_line_width, + ) + }; + + // Use horizontal layout for a function with a single argument as long as + // everything fits in a single line. + if self.items.len() == 1 + && self.one_line_width != 0 // Vertical layout is forced. + && !list_items[0].has_comment() + && !list_items[0].inner_as_ref().contains('\n') + && ::lists::total_item_width(&list_items[0]) <= self.one_line_width + { + tactic = DefinitiveListTactic::Horizontal; + } else { + tactic = default_tactic(); + + if tactic == DefinitiveListTactic::Vertical { + if let Some((all_simple, num_args_before)) = + maybe_get_args_offset(self.ident, self.items) + { + let one_line = all_simple + && definitive_tactic( + &list_items[..num_args_before], + ListTactic::HorizontalVertical, + Separator::Comma, + self.nested_shape.width, + ) + == DefinitiveListTactic::Horizontal + && definitive_tactic( + &list_items[num_args_before + 1..], + ListTactic::HorizontalVertical, + Separator::Comma, + self.nested_shape.width, + ) + == DefinitiveListTactic::Horizontal; + + if one_line { + tactic = DefinitiveListTactic::SpecialMacro(num_args_before); + }; + } + } + } + } + _ => (), + } + + tactic + } + + fn rewrite_items(&self) -> Option<(bool, String)> { + let span = self.items_span(); + let items = itemize_list( + self.context.snippet_provider, + self.items.iter(), + self.suffix, + ",", + |item| item.span().lo(), + |item| item.span().hi(), + |item| item.rewrite(self.context, self.nested_shape), + span.lo(), + span.hi(), + true, + ); + let mut list_items: Vec<_> = items.collect(); + + // Try letting the last argument overflow to the next line with block + // indentation. If its first line fits on one line with the other arguments, + // we format the function arguments horizontally. + let tactic = self.try_overflow_last_item(&mut list_items); + + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: if self.force_trailing_comma { + SeparatorTactic::Always + } else if self.context.inside_macro || !self.context.use_block_indent() { + SeparatorTactic::Never + } else { + self.context.config.trailing_comma() + }, + separator_place: SeparatorPlace::Back, + shape: self.nested_shape, + ends_with_newline: self.context.use_block_indent() + && tactic == DefinitiveListTactic::Vertical, + preserve_newline: false, + config: self.context.config, + }; + + write_list(&list_items, &fmt) + .map(|items_str| (tactic == DefinitiveListTactic::Horizontal, items_str)) + } + + fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> String { + let shape = Shape { + width: shape + .width + .checked_sub(last_line_width(self.ident)) + .unwrap_or(0), + ..shape + }; + + let paren_overhead = paren_overhead(self.context); + let fits_one_line = items_str.len() + paren_overhead <= shape.width; + let extend_width = if items_str.is_empty() { + paren_overhead + } else { + paren_overhead / 2 + }; + let nested_indent_str = self.nested_shape + .indent + .to_string_with_newline(self.context.config); + let indent_str = shape + .block() + .indent + .to_string_with_newline(self.context.config); + let mut result = String::with_capacity( + self.ident.len() + items_str.len() + 2 + indent_str.len() + nested_indent_str.len(), + ); + result.push_str(self.ident); + result.push_str(self.prefix); + if !self.context.use_block_indent() + || (self.context.inside_macro && !items_str.contains('\n') && fits_one_line) + || (is_extendable && extend_width <= shape.width) + { + if self.context.config.spaces_within_parens_and_brackets() && !items_str.is_empty() { + result.push(' '); + result.push_str(items_str); + result.push(' '); + } else { + result.push_str(items_str); + } + } else { + if !items_str.is_empty() { + result.push_str(&nested_indent_str); + result.push_str(items_str); + } + result.push_str(&indent_str); + } + result.push_str(self.suffix); + result + } + + fn rewrite(&self, shape: Shape) -> Option { + let (extendable, items_str) = self.rewrite_items()?; + + // If we are using visual indent style and failed to format, retry with block indent. + if !self.context.use_block_indent() && need_block_indent(&items_str, self.nested_shape) + && !extendable + { + self.context.use_block.replace(true); + let result = self.rewrite(shape); + self.context.use_block.replace(false); + return result; + } + + Some(self.wrap_items(&items_str, shape, extendable)) + } +} + +fn need_block_indent(s: &str, shape: Shape) -> bool { + s.lines().skip(1).any(|s| { + s.find(|c| !char::is_whitespace(c)) + .map_or(false, |w| w + 1 < shape.indent.width()) + }) +} + +fn can_be_overflowed<'a, T>(context: &RewriteContext, items: &[&T]) -> bool +where + T: Rewrite + Spanned + ToExpr + 'a, +{ + items + .last() + .map_or(false, |x| x.can_be_overflowed(context, items.len())) +} + +/// Returns a shape for the last argument which is going to be overflowed. +fn last_item_shape( + lists: &[&T], + items: &[ListItem], + shape: Shape, + args_max_width: usize, +) -> Option +where + T: Rewrite + Spanned + ToExpr, +{ + let is_nested_call = lists + .iter() + .next() + .and_then(|item| item.to_expr()) + .map_or(false, is_nested_call); + if items.len() == 1 && !is_nested_call { + return Some(shape); + } + let offset = items.iter().rev().skip(1).fold(0, |acc, i| { + // 2 = ", " + acc + 2 + i.inner_as_ref().len() + }); + Shape { + width: min(args_max_width, shape.width), + ..shape + }.offset_left(offset) +} + +fn shape_from_indent_style( + context: &RewriteContext, + shape: Shape, + overhead: usize, + offset: usize, +) -> Shape { + if context.use_block_indent() { + // 1 = "," + shape + .block() + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1) + .unwrap() + } else { + let shape = shape.visual_indent(offset); + if let Some(shape) = shape.sub_width(overhead) { + shape + } else { + Shape { width: 0, ..shape } + } + } +} diff --git a/src/patterns.rs b/src/patterns.rs index e94f13b9daf..c6cacc8bff5 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,11 +15,12 @@ use syntax::ptr; use codemap::SpanUtils; use comment::FindUncommented; -use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix, - wrap_struct_field, PairParts}; +use expr::{can_be_overflowed_expr, rewrite_pair, rewrite_unary_prefix, wrap_struct_field, + PairParts}; use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list}; use macros::{rewrite_macro, MacroPosition}; +use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; @@ -335,13 +336,13 @@ fn rewrite_tuple_pat( pat_ref_vec.push(pat); } - rewrite_call_inner( + overflow::rewrite_with_parens( &context, &path_str, &pat_ref_vec[..], - span, shape, - shape.width, + span, + context.config.max_width(), add_comma, ) } diff --git a/src/types.rs b/src/types.rs index fd6b6e3ca56..e52648e575c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -384,14 +384,18 @@ where FunctionRetTy::Default(..) => String::new(), }; - let extendable = (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n'); - let args = wrap_args_with_parens( - context, - &list_str, - extendable, - shape.sub_width(first_line_width(&output))?, - Shape::indented(offset, context.config), - ); + let args = if (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n') + || !context.use_block_indent() + { + format!("({})", list_str) + } else { + format!( + "({}{}{})", + offset.to_string_with_newline(context.config), + list_str, + shape.block().indent.to_string_with_newline(context.config), + ) + }; if last_line_width(&args) + first_line_width(&output) <= shape.width { Some(format!("{}{}", args, output)) } else { -- cgit 1.4.1-3-g733a5 From 2a99d9704f5d2c5c268675cb9cb7ac397c13c518 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 7 Mar 2018 15:48:47 +0900 Subject: Use overflow::rewrite_with_angle_brackets to rewrite generics --- src/expr.rs | 10 ++++ src/items.rs | 188 ++++++++++++----------------------------------------------- src/types.rs | 61 ++++++++++--------- 3 files changed, 80 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e69dd15aa0e..647b81830d4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2643,3 +2643,13 @@ impl<'a> ToExpr for MacroArg { } } } + +impl ToExpr for ast::GenericParam { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { + false + } +} diff --git a/src/items.rs b/src/items.rs index ac392ccf62e..23f96358d8e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -718,7 +718,6 @@ fn format_impl_ref_and_type( result.push_str(&format_visibility(&item.vis)); result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); - result.push_str("impl"); let lo = context.snippet_provider.span_after(item.span, "impl"); let hi = match *trait_ref { @@ -730,9 +729,8 @@ fn format_impl_ref_and_type( Shape::indented(offset + last_line_width(&result), context.config), 0, )?; - let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?; - let generics_str = - rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?; + let generics_str = rewrite_generics(context, "impl", generics, shape, mk_sp(lo, hi))?; + result.push_str(&generics_str); let polarity_str = if polarity == ast::ImplPolarity::Negative { "!" @@ -741,32 +739,14 @@ fn format_impl_ref_and_type( }; if let Some(ref trait_ref) = *trait_ref { - let result_len = result.len(); - if let Some(trait_ref_str) = rewrite_trait_ref( + let result_len = last_line_width(&result); + result.push_str(&rewrite_trait_ref( context, trait_ref, offset, - &generics_str, - true, polarity_str, result_len, - ) { - result.push_str(&trait_ref_str); - } else { - let generics_str = - rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?; - result.push_str(&rewrite_trait_ref( - context, - trait_ref, - offset, - &generics_str, - false, - polarity_str, - result_len, - )?); - } - } else { - result.push_str(&generics_str); + )?); } // Try to put the self type in a single line. @@ -821,37 +801,27 @@ fn rewrite_trait_ref( context: &RewriteContext, trait_ref: &ast::TraitRef, offset: Indent, - generics_str: &str, - retry: bool, polarity_str: &str, result_len: usize, ) -> Option { // 1 = space between generics and trait_ref - let used_space = 1 + polarity_str.len() + last_line_used_width(generics_str, result_len); + let used_space = 1 + polarity_str.len() + result_len; let shape = Shape::indented(offset + used_space, context.config); if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { - if !(retry && trait_ref_str.contains('\n')) { - return Some(format!( - "{} {}{}", - generics_str, polarity_str, &trait_ref_str - )); + if !trait_ref_str.contains('\n') { + return Some(format!(" {}{}", polarity_str, &trait_ref_str)); } } // We could not make enough space for trait_ref, so put it on new line. - if !retry { - let offset = offset.block_indent(context.config); - let shape = Shape::indented(offset, context.config); - let trait_ref_str = trait_ref.rewrite(context, shape)?; - Some(format!( - "{}\n{}{}{}", - generics_str, - &offset.to_string(context.config), - polarity_str, - &trait_ref_str - )) - } else { - None - } + let offset = offset.block_indent(context.config); + let shape = Shape::indented(offset, context.config); + let trait_ref_str = trait_ref.rewrite(context, shape)?; + Some(format!( + "{}{}{}", + &offset.to_string_with_newline(context.config), + polarity_str, + &trait_ref_str + )) } pub struct StructParts<'a> { @@ -919,10 +889,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) { let mut result = String::with_capacity(128); let header = format!( - "{}{}trait {}", + "{}{}trait ", format_visibility(&item.vis), format_unsafety(unsafety), - item.ident ); result.push_str(&header); @@ -930,8 +899,13 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.snippet_provider.span_after(item.span, "{"); let shape = Shape::indented(offset, context.config).offset_left(result.len())?; - let generics_str = - rewrite_generics(context, generics, shape, mk_sp(item.span.lo(), body_lo))?; + let generics_str = rewrite_generics( + context, + &item.ident.to_string(), + generics, + shape, + mk_sp(item.span.lo(), body_lo), + )?; result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. @@ -1080,9 +1054,9 @@ pub fn format_trait_alias( ) -> Option { let alias = ident.name.as_str(); // 6 = "trait ", 2 = " =" - let g_shape = shape.offset_left(6 + alias.len())?.sub_width(2)?; - let generics_str = rewrite_generics(context, generics, g_shape, generics.span)?; - let lhs = format!("trait {}{} =", alias, generics_str); + let g_shape = shape.offset_left(6)?.sub_width(2)?; + let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?; + let lhs = format!("trait {} =", generics_str); // 1 = ";" rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") } @@ -1259,7 +1233,7 @@ fn format_tuple_struct( let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); let g_span = mk_sp(span.lo(), body_lo); - let generics_str = rewrite_generics(context, generics, shape, g_span)?; + let generics_str = rewrite_generics(context, "", generics, shape, g_span)?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1350,7 +1324,6 @@ pub fn rewrite_type_alias( result.push_str(&format_visibility(vis)); result.push_str("type "); - result.push_str(&ident.to_string()); // 2 = `= ` let g_shape = Shape::indented(indent, context.config) @@ -1360,7 +1333,7 @@ pub fn rewrite_type_alias( context.snippet_provider.span_after(span, "type"), ty.span.lo(), ); - let generics_str = rewrite_generics(context, generics, g_shape, g_span)?; + let generics_str = rewrite_generics(context, &ident.to_string(), generics, g_shape, g_span)?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1801,7 +1774,6 @@ fn rewrite_fn_base( // fn foo result.push_str("fn "); - result.push_str(&ident.to_string()); // Generics. let overhead = if has_body && !newline_brace { @@ -1820,7 +1792,8 @@ fn rewrite_fn_base( }; let fd = fn_sig.decl; let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?; + let generics_str = + rewrite_generics(context, &ident.to_string(), fn_sig.generics, shape, g_span)?; result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -2326,43 +2299,20 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { fn rewrite_generics( context: &RewriteContext, + ident: &str, generics: &ast::Generics, shape: Shape, span: Span, -) -> Option { - let g_shape = generics_shape_from_config(context.config, shape, 0)?; - let one_line_width = shape.width.checked_sub(2).unwrap_or(0); - rewrite_generics_inner(context, generics, g_shape, one_line_width, span) - .or_else(|| rewrite_generics_inner(context, generics, g_shape, 0, span)) -} - -fn rewrite_generics_inner( - context: &RewriteContext, - generics: &ast::Generics, - shape: Shape, - one_line_width: usize, - span: Span, ) -> Option { // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. if generics.params.is_empty() { - return Some(String::new()); + return Some(ident.to_owned()); } - let items = itemize_list( - context.snippet_provider, - generics.params.iter(), - ">", - ",", - |arg| arg.span().lo(), - |arg| arg.span().hi(), - |arg| arg.rewrite(context, shape), - context.snippet_provider.span_after(span, "<"), - span.hi(), - false, - ); - format_generics_item_list(context, items, shape, one_line_width) + let params = &generics.params.iter().map(|e| &*e).collect::>()[..]; + overflow::rewrite_with_angle_brackets(context, ident, params, shape, span) } pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { @@ -2379,70 +2329,6 @@ pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) } } -pub fn format_generics_item_list( - context: &RewriteContext, - items: I, - shape: Shape, - one_line_budget: usize, -) -> Option -where - I: Iterator, -{ - let item_vec = items.collect::>(); - - let tactic = definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - one_line_budget, - ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if context.config.indent_style() == IndentStyle::Visual { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - config: context.config, - }; - - let list_str = write_list(&item_vec, &fmt)?; - - Some(wrap_generics_with_angle_brackets( - context, - &list_str, - shape.indent, - )) -} - -pub fn wrap_generics_with_angle_brackets( - context: &RewriteContext, - list_str: &str, - list_offset: Indent, -) -> String { - if context.config.indent_style() == IndentStyle::Block - && (list_str.contains('\n') || list_str.ends_with(',')) - { - format!( - "<\n{}{}\n{}>", - list_offset.to_string(context.config), - list_str, - list_offset - .block_unindent(context.config) - .to_string(context.config) - ) - } else if context.config.spaces_within_parens_and_brackets() { - format!("< {} >", list_str) - } else { - format!("<{}>", list_str) - } -} - fn rewrite_trait_bounds( context: &RewriteContext, bounds: &[ast::TyParamBound], @@ -2713,7 +2599,7 @@ fn format_generics( used_width: usize, ) -> Option { let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = rewrite_generics(context, generics, shape, span)?; + let mut result = rewrite_generics(context, "", generics, shape, span)?; let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = context.budget(last_line_used_width(&result, offset.width())); diff --git a/src/types.rs b/src/types.rs index e52648e575c..ac7990b9c0b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,10 +18,10 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, wrap_args_with_parens, PairParts}; -use items::{format_generics_item_list, generics_shape_from_config}; +use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; +use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; @@ -151,8 +151,8 @@ enum SegmentParam<'a> { Binding(&'a ast::TypeBinding), } -impl<'a> SegmentParam<'a> { - fn get_span(&self) -> Span { +impl<'a> Spanned for SegmentParam<'a> { + fn span(&self) -> Span { match *self { SegmentParam::LifeTime(lt) => lt.span, SegmentParam::Type(ty) => ty.span, @@ -161,6 +161,19 @@ impl<'a> SegmentParam<'a> { } } +impl<'a> ToExpr for SegmentParam<'a> { + fn to_expr(&self) -> Option<&ast::Expr> { + None + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + match *self { + SegmentParam::Type(ty) => ty.can_be_overflowed(context, len), + _ => false, + } + } +} + impl<'a> Rewrite for SegmentParam<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { @@ -204,7 +217,11 @@ fn rewrite_segment( result.push_str(&segment.identifier.name.as_str()); let ident_len = result.len(); - let shape = shape.shrink_left(ident_len)?; + let shape = if context.use_block_indent() { + shape.offset_left(ident_len)? + } else { + shape.shrink_left(ident_len)? + }; if let Some(ref params) = segment.parameters { match **params { @@ -219,10 +236,6 @@ fn rewrite_segment( .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1); - let list_lo = context - .snippet_provider - .span_after(mk_sp(*span_lo, span_hi), "<"); let separator = if path_context == PathContext::Expr { "::" } else { @@ -230,26 +243,18 @@ fn rewrite_segment( }; result.push_str(separator); - let generics_shape = - generics_shape_from_config(context.config, shape, separator.len())?; - let one_line_width = shape.width.checked_sub(separator.len() + 2)?; - let items = itemize_list( - context.snippet_provider, - param_list.into_iter(), - ">", - ",", - |param| param.get_span().lo(), - |param| param.get_span().hi(), - |seg| seg.rewrite(context, generics_shape), - list_lo, - span_hi, - false, - ); - let generics_str = - format_generics_item_list(context, items, generics_shape, one_line_width)?; + let generics_str = overflow::rewrite_with_angle_brackets( + context, + "", + ¶m_list.iter().map(|e| &*e).collect::>()[..], + shape, + mk_sp(*span_lo, span_hi), + )?; // Update position of last bracket. - *span_lo = next_span_lo; + *span_lo = context + .snippet_provider + .span_after(mk_sp(*span_lo, span_hi), "<"); result.push_str(&generics_str) } @@ -807,7 +812,7 @@ pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { match ty.node { - ast::TyKind::Path(..) | ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, + ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { can_be_overflowed_type(context, &*mutty.ty, len) } -- cgit 1.4.1-3-g733a5 From 466caa77bb23ed8c7fd39d1fc62a83ce192b7f0a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 7 Mar 2018 15:49:55 +0900 Subject: Make INDENT_BUFFER longer Avoid panicking when indent whose width is 80 called `to_string()`. --- src/shape.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/shape.rs b/src/shape.rs index 047a50340eb..c6a183216b8 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -23,10 +23,10 @@ pub struct Indent { pub alignment: usize, } -// INDENT_BUFFER.len() = 80 +// INDENT_BUFFER.len() = 81 const INDENT_BUFFER_LEN: usize = 80; const INDENT_BUFFER: &str = - "\n "; + "\n "; impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { Indent { -- cgit 1.4.1-3-g733a5 From 6ba7c34433ef62f25e566fe2f8729a674d57aa00 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 7 Mar 2018 19:29:42 +0900 Subject: Use Option over bool to control trailing comma --- src/expr.rs | 24 ++++++++++++++++++------ src/items.rs | 2 +- src/macros.rs | 6 +++++- src/overflow.rs | 18 +++++++++--------- src/patterns.rs | 6 +++++- 5 files changed, 38 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 647b81830d4..a38e9b0b8f8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1936,9 +1936,13 @@ pub fn rewrite_call( span, context.config.width_heuristics().fn_call_width, if context.inside_macro { - span_ends_with_comma(context, span) + if span_ends_with_comma(context, span) { + Some(SeparatorTactic::Always) + } else { + Some(SeparatorTactic::Never) + } } else { - false + None }, ) } @@ -2422,10 +2426,18 @@ where debug!("rewrite_tuple {:?}", shape); if context.use_block_indent() { // We use the same rule as function calls for rewriting tuples. - let force_trailing_comma = if context.inside_macro { - span_ends_with_comma(context, span) + let force_tactic = if context.inside_macro { + if span_ends_with_comma(context, span) { + Some(SeparatorTactic::Always) + } else { + Some(SeparatorTactic::Never) + } } else { - items.len() == 1 + if items.len() == 1 { + Some(SeparatorTactic::Always) + } else { + None + } }; overflow::rewrite_with_parens( context, @@ -2434,7 +2446,7 @@ where shape, span, context.config.width_heuristics().fn_call_width, - force_trailing_comma, + force_tactic, ) } else { rewrite_tuple_in_visual_indent_style(context, items, span, shape) diff --git a/src/items.rs b/src/items.rs index 23f96358d8e..d3286864ce7 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1290,7 +1290,7 @@ fn format_tuple_struct( shape, span, context.config.width_heuristics().fn_call_width, - false, + None, )?; } diff --git a/src/macros.rs b/src/macros.rs index db79fb9d576..bb870e589ee 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -233,7 +233,11 @@ pub fn rewrite_macro( shape, mac.span, context.config.width_heuristics().fn_call_width, - trailing_comma, + if trailing_comma { + Some(SeparatorTactic::Always) + } else { + Some(SeparatorTactic::Never) + }, ).map(|rw| match position { MacroPosition::Item => format!("{};", rw), _ => rw, diff --git a/src/overflow.rs b/src/overflow.rs index b5634def086..294c257d31f 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -33,7 +33,7 @@ pub fn rewrite_with_parens( shape: Shape, span: Span, item_max_width: usize, - force_trailing_comma: bool, + force_separator_tactic: Option, ) -> Option where T: Rewrite + ToExpr + Spanned, @@ -47,7 +47,7 @@ where "(", ")", item_max_width, - force_trailing_comma, + force_separator_tactic, ).rewrite(shape) } @@ -70,7 +70,7 @@ where "<", ">", context.config.max_width(), - false, + None, ).rewrite(shape) } @@ -85,7 +85,7 @@ struct Context<'a, T: 'a> { span: Span, item_max_width: usize, one_line_width: usize, - force_trailing_comma: bool, + force_separator_tactic: Option, } impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { @@ -98,7 +98,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { prefix: &'static str, suffix: &'static str, item_max_width: usize, - force_trailing_comma: bool, + force_separator_tactic: Option, ) -> Context<'a, T> { // 2 = `( `, 1 = `(` let paren_overhead = if context.config.spaces_within_parens_and_brackets() { @@ -134,7 +134,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { suffix, item_max_width, one_line_width, - force_trailing_comma, + force_separator_tactic, } } @@ -336,9 +336,9 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let fmt = ListFormatting { tactic, separator: ",", - trailing_separator: if self.force_trailing_comma { - SeparatorTactic::Always - } else if self.context.inside_macro || !self.context.use_block_indent() { + trailing_separator: if let Some(tactic) = self.force_separator_tactic { + tactic + } else if !self.context.use_block_indent() { SeparatorTactic::Never } else { self.context.config.trailing_comma() diff --git a/src/patterns.rs b/src/patterns.rs index c6cacc8bff5..54b7e0f9a4c 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -343,7 +343,11 @@ fn rewrite_tuple_pat( shape, span, context.config.max_width(), - add_comma, + if add_comma { + Some(SeparatorTactic::Always) + } else { + None + }, ) } -- cgit 1.4.1-3-g733a5 From eaab592cb80c8b32b5f047955ca2cec073e6ace2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 9 Mar 2018 17:10:20 +0900 Subject: Avoid unindenting code block in comment with unformattable macro `format_code_block` formats the given `code_snippet` by enclosing it inside `fn main` block. Previously we did not add indentation to the `code_snippet` before formatting it. This works fine as long as we can format the given `code_snippet`, but when the code block has unformattable macro, they gets unindented. This commit fixes it by adding proper indentation before formatting the `code_snippet`. For example, when formatting the following code block, ```rust some_macro!(pub fn foo() { println!("Don't unindent me!"); }); ``` previously we enclosed it like this: ```rust fn main() { some_macro!(pub fn foo() { println!("Don't unindent me!"); }); } ``` with this PR, we will enclose it like this: ```rust fn main() { some_macro!(pub fn foo() { println!("Don't unindent me!"); }); } ``` Closes #2523. --- src/lib.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index fe08b68c782..310cce4bbec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -596,14 +596,23 @@ pub fn format_snippet(snippet: &str, config: &Config) -> Option { } } +const FN_MAIN_PREFIX: &str = "fn main() {\n"; + +fn enclose_in_main_block(s: &str, config: &Config) -> String { + let indent = Indent::from_width(config, config.tab_spaces()); + FN_MAIN_PREFIX.to_owned() + &indent.to_string(config) + + &s.lines() + .collect::>() + .join(&indent.to_string_with_newline(config)) + "\n}" +} + /// Format the given code block. Mainly targeted for code block in comment. /// The code block may be incomplete (i.e. parser may be unable to parse it). /// To avoid panic in parser, we wrap the code block with a dummy function. /// The returned code block does *not* end with newline. pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { // Wrap the given code block with `fn main()` if it does not have one. - let fn_main_prefix = "fn main() {\n"; - let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}"; + let snippet = enclose_in_main_block(code_snippet, config); let mut result = String::with_capacity(snippet.len()); let mut is_first = true; @@ -612,7 +621,7 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option let formatted = format_snippet(&snippet, config)?; // 2 = "}\n" let block_len = formatted.len().checked_sub(2).unwrap_or(0); - for line in formatted[fn_main_prefix.len()..block_len].lines() { + for line in formatted[FN_MAIN_PREFIX.len()..block_len].lines() { if !is_first { result.push('\n'); } else { -- cgit 1.4.1-3-g733a5 From 2188b464b0c5e22661bc488815f8b46b0b31cc26 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 9 Mar 2018 17:17:55 +0900 Subject: Format macro call with item arguments --- src/expr.rs | 1 + src/macros.rs | 25 ++++++++++++++++++++----- src/spanned.rs | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 85a2e658ef2..b4968d12a0a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -3051,6 +3051,7 @@ impl<'a> ToExpr for MacroArg { MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), MacroArg::Pat(..) => false, + MacroArg::Item(..) => len == 1, } } } diff --git a/src/macros.rs b/src/macros.rs index 6be6a1f2664..ac4b0db7266 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,7 +22,7 @@ use std::collections::HashMap; use config::lists::*; -use syntax::ast; +use syntax::{ast, ptr}; use syntax::codemap::{BytePos, Span}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; @@ -38,6 +38,7 @@ use expr::{rewrite_array, rewrite_call_inner}; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use spanned::Spanned; use utils::{format_visibility, mk_sp, wrap_str}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -70,9 +71,21 @@ impl MacroStyle { #[derive(Debug)] pub enum MacroArg { - Expr(ast::Expr), - Ty(ast::Ty), - Pat(ast::Pat), + Expr(ptr::P), + Ty(ptr::P), + Pat(ptr::P), + // `parse_item` returns `Option>`. + Item(Option>), +} + +impl Rewrite for ast::Item { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let mut visitor = ::visitor::FmtVisitor::from_context(context); + visitor.block_indent = shape.indent; + visitor.last_pos = self.span().lo(); + visitor.visit_item(self); + Some(visitor.buffer) + } } impl Rewrite for MacroArg { @@ -81,6 +94,7 @@ impl Rewrite for MacroArg { MacroArg::Expr(ref expr) => expr.rewrite(context, shape), MacroArg::Ty(ref ty) => ty.rewrite(context, shape), MacroArg::Pat(ref pat) => pat.rewrite(context, shape), + MacroArg::Item(ref item) => item.as_ref().and_then(|item| item.rewrite(context, shape)), } } } @@ -96,7 +110,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { } else { // Parsing succeeded. *parser = cloned_parser; - return Some(MacroArg::$macro_arg((*x).clone())); + return Some(MacroArg::$macro_arg(x.clone())); } } Err(mut e) => { @@ -110,6 +124,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { parse_macro_arg!(Expr, parse_expr); parse_macro_arg!(Ty, parse_ty); parse_macro_arg!(Pat, parse_pat); + parse_macro_arg!(Item, parse_item); None } diff --git a/src/spanned.rs b/src/spanned.rs index d1f4865dead..6f5a4b1721f 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -187,6 +187,7 @@ impl Spanned for MacroArg { MacroArg::Expr(ref expr) => expr.span(), MacroArg::Ty(ref ty) => ty.span(), MacroArg::Pat(ref pat) => pat.span(), + MacroArg::Item(ref item) => item.as_ref().unwrap().span(), } } } -- cgit 1.4.1-3-g733a5 From 53dcb0d09d5fd2138764148433962309f7c6e1c8 Mon Sep 17 00:00:00 2001 From: Rob Tsuk Date: Tue, 6 Mar 2018 07:28:08 -0700 Subject: Restore cargo fmt behavior in workspaces Previously, cargo fmt invoked without parameters would only format the crate in the current directory, even if the crate was part of a workspace. This patch restores that behavior. --- src/cargo-fmt/main.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 1acad99688a..02c19525edb 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -249,10 +249,16 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { let metadata = get_cargo_metadata(None)?; + let current_dir = env::current_dir()?; + let current_dir_manifest = current_dir.join("Cargo.toml"); + let workspace_root_path = PathBuf::from(&metadata.workspace_root); + let in_workspace_root = workspace_root_path == current_dir; for package in metadata.packages { - for target in package.targets { - targets.insert(Target::from_target(&target)); + if in_workspace_root || PathBuf::from(&package.manifest_path) == current_dir_manifest { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } } } -- cgit 1.4.1-3-g733a5 From ba10a4c48dc1f586863c56e36ef71201d3bea1db Mon Sep 17 00:00:00 2001 From: Rob Tsuk Date: Thu, 8 Mar 2018 07:26:03 -0700 Subject: Canonicalise the paths --- src/cargo-fmt/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 02c19525edb..855a45568b7 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -249,9 +249,9 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { let metadata = get_cargo_metadata(None)?; - let current_dir = env::current_dir()?; + let current_dir = env::current_dir()?.canonicalize()?; let current_dir_manifest = current_dir.join("Cargo.toml"); - let workspace_root_path = PathBuf::from(&metadata.workspace_root); + let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; let in_workspace_root = workspace_root_path == current_dir; for package in metadata.packages { -- cgit 1.4.1-3-g733a5 From 86a427fe32e0a4f3696f55c9f7a04a768e8ced68 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 01:19:38 +0900 Subject: Check whether '\\'' is char literal or lifetime --- Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 1 + src/comment.rs | 21 ++++++++++++++++++--- src/lib.rs | 1 + 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index e865f2d1b53..e4e9a9ddd75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,11 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "either" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ena" version = "0.9.2" @@ -144,6 +149,14 @@ dependencies = [ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.3.4" @@ -367,6 +380,7 @@ dependencies = [ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -615,6 +629,7 @@ dependencies = [ "checksum derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92f8b8e1d6c8a5f5ea0849a0e4c55941576115c62d3fc425e96918bbbeb3d3c2" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834" "checksum env_logger 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3cc21490995c841d68e00276eba02071ebb269ec24011d5728bd00eabd39e31" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" @@ -622,6 +637,7 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum itertools 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "23d53b4c7394338044c3b9c8c5b2caaf7b40ae049ecd321578ebdc2e13738cd1" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" diff --git a/Cargo.toml b/Cargo.toml index 3be0c4ff7a8..ecd8db0b2be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ cargo-fmt = [] rustfmt-format-diff = [] [dependencies] +itertools = "0.7" toml = "0.4" serde = "1.0" serde_derive = "1.0" diff --git a/src/comment.rs b/src/comment.rs index 74a14511be8..e3e52eda815 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -12,6 +12,7 @@ use std::{self, iter, borrow::Cow}; +use itertools::{multipeek, MultiPeek}; use syntax::codemap::Span; use config::Config; @@ -684,7 +685,7 @@ where T: Iterator, T::Item: RichChar, { - base: iter::Peekable, + base: MultiPeek, status: CharClassesStatus, } @@ -776,7 +777,7 @@ where { pub fn new(base: T) -> CharClasses { CharClasses { - base: base.peekable(), + base: multipeek(base), status: CharClassesStatus::Normal, } } @@ -820,7 +821,21 @@ where char_kind = FullCodeCharKind::InString; CharClassesStatus::LitString } - '\'' => CharClassesStatus::LitChar, + '\'' => { + // HACK: Work around mut borrow. + match self.base.peek() { + Some(next) if next.get_char() == '\\' => { + self.status = CharClassesStatus::LitChar; + return Some((char_kind, item)); + } + _ => (), + } + + match self.base.peek() { + Some(next) if next.get_char() == '\'' => CharClassesStatus::LitChar, + _ => CharClassesStatus::Normal, + } + } '/' => match self.base.peek() { Some(next) if next.get_char() == '*' => { self.status = CharClassesStatus::BlockCommentOpening(1); diff --git a/src/lib.rs b/src/lib.rs index 9447155ee92..b70c6e6663c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ #[macro_use] extern crate derive_new; extern crate diff; +extern crate itertools; #[macro_use] extern crate log; extern crate regex; -- cgit 1.4.1-3-g733a5 From a41947cd7d6ea1786fe699bdb8c51737f9e239f4 Mon Sep 17 00:00:00 2001 From: David Lukes Date: Sat, 10 Mar 2018 09:57:01 +0100 Subject: Enable doctests Doctests were disabled globally because up until #2456, they were just formatting examples which were not supposed to compile. Now that there is one runnable doctest, I disabled the other ones individually (by adding the ignore directive). I also added some empty lines around the code blocks to avoid the following warning and instead ignore the code blocks cleanly: WARNING: ... Code block is not currently run as a test, but will in future versions of rustdoc. Please ensure this code block is a runnable test, or use the `ignore` directive. See rust-lang/rust#28712 for further details. --- Cargo.toml | 3 --- src/chains.rs | 14 ++++++++++---- src/macros.rs | 9 ++++++--- 3 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 3be0c4ff7a8..4c4f7b450f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,6 @@ license = "Apache-2.0/MIT" build = "build.rs" categories = ["development-tools"] -[lib] -doctest = false - [[bin]] name = "rustfmt" path = "src/bin/main.rs" diff --git a/src/chains.rs b/src/chains.rs index 87100c7be41..de7b8334548 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -25,7 +25,8 @@ //! E.g., `let foo = { aaaa; bbb; ccc }.bar.baz();`, we would layout for the //! following values of `chain_indent`: //! Block: -//! ``` +//! +//! ```ignore //! let foo = { //! aaaa; //! bbb; @@ -33,8 +34,10 @@ //! }.bar //! .baz(); //! ``` +//! //! Visual: -//! ``` +//! +//! ```ignore //! let foo = { //! aaaa; //! bbb; @@ -47,13 +50,16 @@ //! If the first item in the chain is a block expression, we align the dots with //! the braces. //! Block: -//! ``` +//! +//! ```ignore //! let a = foo.bar //! .baz() //! .qux //! ``` +//! //! Visual: -//! ``` +//! +//! ```ignore //! let a = foo.bar //! .baz() //! .qux diff --git a/src/macros.rs b/src/macros.rs index 6be6a1f2664..01eaa807d97 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -621,7 +621,8 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { /// Indent each line according to the specified `indent`. /// e.g. -/// ```rust +/// +/// ```rust,ignore /// foo!{ /// x, /// y, @@ -632,8 +633,10 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle { /// ), /// } /// ``` +/// /// will become -/// ```rust +/// +/// ```rust,ignore /// foo!{ /// x, /// y, @@ -864,7 +867,7 @@ impl MacroBranch { /// /// # Expected syntax /// -/// ``` +/// ```ignore /// lazy_static! { /// [pub] static ref NAME_1: TYPE_1 = EXPR_1; /// [pub] static ref NAME_2: TYPE_2 = EXPR_2; -- cgit 1.4.1-3-g733a5 From 8f7a90fbefd68a919cd6f4214829208798583199 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:35:53 +0900 Subject: Add rewrite_assign_rhs_with It is like `rewrite_assign_rhs` but lets us force to put the rhs on the next line if it uses multiple lines. This lets us avoid duplicating logic for choosing whether to put stuff on the same line or the next line. --- src/expr.rs | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6e740f43f82..0e6b8f1bc1e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1698,7 +1698,8 @@ fn rewrite_match_body( ); match (orig_body, next_line_body) { (Some(ref orig_str), Some(ref next_line_str)) - if forbid_same_line || prefer_next_line(orig_str, next_line_str) => + if forbid_same_line + || prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { combine_next_line_body(next_line_str) } @@ -2514,6 +2515,15 @@ fn rewrite_assignment( rewrite_assign_rhs(context, lhs_str, rhs, shape) } +/// Controls where to put the rhs. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum RhsTactics { + /// Use heuristics. + Default, + /// Put the rhs on the next line if it uses multiple line. + ForceNextLine, +} + // The left hand side must contain everything up to, and including, the // assignment operator. pub fn rewrite_assign_rhs, R: Rewrite>( @@ -2521,6 +2531,16 @@ pub fn rewrite_assign_rhs, R: Rewrite>( lhs: S, ex: &R, shape: Shape, +) -> Option { + rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default) +} + +pub fn rewrite_assign_rhs_with, R: Rewrite>( + context: &RewriteContext, + lhs: S, + ex: &R, + shape: Shape, + rhs_tactics: RhsTactics, ) -> Option { let lhs = lhs.into(); let last_line_width = last_line_width(&lhs) @@ -2536,15 +2556,22 @@ pub fn rewrite_assign_rhs, R: Rewrite>( offset: shape.offset + last_line_width + 1, ..shape }); - let rhs = choose_rhs(context, ex, orig_shape, ex.rewrite(context, orig_shape))?; + let rhs = choose_rhs( + context, + ex, + orig_shape, + ex.rewrite(context, orig_shape), + rhs_tactics, + )?; Some(lhs + &rhs) } -pub fn choose_rhs( +fn choose_rhs( context: &RewriteContext, expr: &R, shape: Shape, orig_rhs: Option, + rhs_tactics: RhsTactics, ) -> Option { match orig_rhs { Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { @@ -2566,7 +2593,9 @@ pub fn choose_rhs( { Some(format!(" {}", orig_rhs)) } - (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => { + (Some(ref orig_rhs), Some(ref new_rhs)) + if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => + { Some(format!("{}{}", new_indent_str, new_rhs)) } (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), @@ -2577,8 +2606,9 @@ pub fn choose_rhs( } } -fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str) -> bool { - !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 +fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { + rhs_tactics == RhsTactics::ForceNextLine || !next_line_rhs.contains('\n') + || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } fn rewrite_expr_addrof( -- cgit 1.4.1-3-g733a5 From f56039c7e584bb5b9b5453056a3f4c5197615629 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:54:13 +0900 Subject: Use rewrite_assign_rhs for rewriting bounds --- src/items.rs | 59 ++++++++++----------------- src/types.rs | 128 ++++++++++++++++++++++++++++++----------------------------- 2 files changed, 85 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d3286864ce7..2484756fc56 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,13 +23,14 @@ use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, ExprType}; +use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_assign_rhs_with, ExprType, RhsTactics}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use overflow; use shape::{Indent, Shape}; use spanned::Spanned; -use types::join_bounds; +use types::TraitTyParamBounds; use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, format_defaultness, format_mutability, format_unsafety, format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, @@ -919,20 +920,19 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) return None; } } - let trait_bound_str = rewrite_trait_bounds( - context, - type_param_bounds, - Shape::indented(offset, context.config), - )?; - // If the trait, generics, and trait bound cannot fit on the same line, - // put the trait bounds on an indented new line - if offset.width() + last_line_width(&result) + trait_bound_str.len() - > context.config.comment_width() - { - let trait_indent = offset.block_only().block_indent(context.config); - result.push_str(&trait_indent.to_string_with_newline(context.config)); + if !type_param_bounds.is_empty() { + let shape = Shape { + indent: shape.indent.block_unindent(context.config), + ..shape + }; + result = rewrite_assign_rhs_with( + context, + result + ":", + &TraitTyParamBounds::new(type_param_bounds), + shape, + RhsTactics::ForceNextLine, + )?; } - result.push_str(&trait_bound_str); let where_density = if context.config.indent_style() == IndentStyle::Block && result.is_empty() { @@ -1585,16 +1585,12 @@ pub fn rewrite_associated_type( let prefix = format!("type {}", ident); let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { - // 2 = ": ".len() - let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - if !bounds.is_empty() { - format!(": {}", join_bounds(context, shape, &bound_str)) - } else { + if bounds.is_empty() { String::new() + } else { + // 2 = ": ".len() + let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; + bounds.rewrite(context, shape).map(|s| format!(": {}", s))? } } else { String::new() @@ -2329,21 +2325,6 @@ pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) } } -fn rewrite_trait_bounds( - context: &RewriteContext, - bounds: &[ast::TyParamBound], - shape: Shape, -) -> Option { - if bounds.is_empty() { - return Some(String::new()); - } - let bound_str = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - Some(format!(": {}", join_bounds(context, shape, &bound_str))) -} - fn rewrite_where_clause_rfc_style( context: &RewriteContext, where_clause: &ast::WhereClause, diff --git a/src/types.rs b/src/types.rs index ac7990b9c0b..80ff8ce498a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,7 +18,8 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, ToExpr}; +use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, + PairParts, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; @@ -431,64 +432,35 @@ impl Rewrite for ast::WherePredicate { .. }) => { let type_str = bounded_ty.rewrite(context, shape)?; - - let colon = type_bound_colon(context); - - if let Some(lifetime_str) = + let colon = type_bound_colon(context).trim_right(); + let lhs = if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, bound_generic_params) { - // 6 = "for<> ".len() - let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6; - let ty_shape = shape.offset_left(used_width)?; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let bounds_str = join_bounds(context, ty_shape, &bounds); - if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { - format!( - "for< {} > {}{}{}", - lifetime_str, type_str, colon, bounds_str - ) + format!("for< {} > {}{}", lifetime_str, type_str, colon) } else { - format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str) + format!("for<{}> {}{}", lifetime_str, type_str, colon) } } else { - let used_width = type_str.len() + colon.len(); - let ty_shape = match context.config.indent_style() { - IndentStyle::Visual => shape.block_left(used_width)?, - IndentStyle::Block => shape, - }; - let bounds = bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, ty_shape)) - .collect::>>()?; - let overhead = type_str.len() + colon.len(); - let bounds_str = join_bounds(context, ty_shape.sub_width(overhead)?, &bounds); - - format!("{}{}{}", type_str, colon, bounds_str) - } + format!("{}{}", type_str, colon) + }; + + rewrite_assign_rhs(context, lhs, bounds, shape)? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, .. - }) => rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape)?, + }) => rewrite_bounded_lifetime(lifetime, bounds, context, shape)?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { - let lhs_ty_str = lhs_ty.rewrite(context, shape)?; - // 3 = " = ".len() - let used_width = 3 + lhs_ty_str.len(); - let budget = shape.width.checked_sub(used_width)?; - let rhs_ty_str = - rhs_ty.rewrite(context, Shape::legacy(budget, shape.indent + used_width))?; - format!("{} = {}", lhs_ty_str, rhs_ty_str) + let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, shape)? } }; @@ -498,26 +470,23 @@ impl Rewrite for ast::WherePredicate { impl Rewrite for ast::LifetimeDef { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_bounded_lifetime(&self.lifetime, self.bounds.iter(), context, shape) + rewrite_bounded_lifetime(&self.lifetime, &self.bounds, context, shape) } } -fn rewrite_bounded_lifetime<'b, I>( +fn rewrite_bounded_lifetime( lt: &ast::Lifetime, - bounds: I, + bounds: &[ast::Lifetime], context: &RewriteContext, shape: Shape, -) -> Option -where - I: ExactSizeIterator, -{ +) -> Option { let result = lt.rewrite(context, shape)?; if bounds.len() == 0 { Some(result) } else { let appendix = bounds - .into_iter() + .iter() .map(|b| b.rewrite(context, shape)) .collect::>>()?; let colon = type_bound_colon(context); @@ -526,7 +495,7 @@ where "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, &appendix) + join_bounds(context, shape.sub_width(overhead)?, bounds, &appendix, true)? ); Some(result) } @@ -552,12 +521,28 @@ impl Rewrite for ast::Lifetime { } } +/// A simple wrapper over type param bounds in trait. +#[derive(new)] +pub struct TraitTyParamBounds<'a> { + inner: &'a ast::TyParamBounds, +} + +impl<'a> Rewrite for TraitTyParamBounds<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let strs = self.inner + .iter() + .map(|b| b.rewrite(context, shape)) + .collect::>>()?; + join_bounds(context, shape, self.inner, &strs, false) + } +} + impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let strs = self.iter() .map(|b| b.rewrite(context, shape)) .collect::>>()?; - Some(join_bounds(context, shape, &strs)) + join_bounds(context, shape, self, &strs, true) } } @@ -572,11 +557,7 @@ impl Rewrite for ast::TyParam { result.push_str(&self.ident.to_string()); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); - let strs = self.bounds - .iter() - .map(|ty_bound| ty_bound.rewrite(context, shape)) - .collect::>>()?; - result.push_str(&join_bounds(context, shape, &strs)); + result.push_str(&self.bounds.rewrite(context, shape)?) } if let Some(ref def) = self.default { let eq_str = match context.config.type_punctuation_density() { @@ -794,20 +775,41 @@ fn rewrite_bare_fn( Some(result) } -pub fn join_bounds(context: &RewriteContext, shape: Shape, type_strs: &[String]) -> String { +fn join_bounds( + context: &RewriteContext, + shape: Shape, + items: &[T], + type_strs: &[String], + need_indent: bool, +) -> Option +where + T: Rewrite, +{ // Try to join types in a single line let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; let result = type_strs.join(joiner); - if result.contains('\n') || result.len() > shape.width { - let joiner_indent = shape.indent.block_indent(context.config); - let joiner = format!("{}+ ", joiner_indent.to_string_with_newline(context.config)); - type_strs.join(&joiner) - } else { - result + if items.len() == 1 || (!result.contains('\n') && result.len() <= shape.width) { + return Some(result); } + + // We need to use multiple lines. + let (type_strs, offset) = if need_indent { + // Rewrite with additional indentation. + let nested_shape = shape.block_indent(context.config.tab_spaces()); + let type_strs = items + .iter() + .map(|item| item.rewrite(context, nested_shape)) + .collect::>>()?; + (type_strs, nested_shape.indent) + } else { + (type_strs.to_vec(), shape.indent) + }; + + let joiner = format!("{}+ ", offset.to_string_with_newline(context.config)); + Some(type_strs.join(&joiner)) } pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { -- cgit 1.4.1-3-g733a5 From b077297179b41420701e36f55b507bd2299811b5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 14:55:30 +0900 Subject: Modify the placement of the opening brace of trait Put the opening brace on the next line if 1. putting it one the current line exceeds max width. 2. trait bounds uses multiple lines. --- src/items.rs | 74 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2484756fc56..1d02ba653ce 100644 --- a/src/items.rs +++ b/src/items.rs @@ -934,45 +934,45 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) )?; } - let where_density = - if context.config.indent_style() == IndentStyle::Block && result.is_empty() { + // Rewrite where clause. + if !generics.where_clause.predicates.is_empty() { + let where_density = if context.config.indent_style() == IndentStyle::Block { Density::Compressed } else { Density::Tall }; - let where_budget = context.budget(last_line_width(&result)); - let pos_before_where = if type_param_bounds.is_empty() { - generics.where_clause.span.lo() + let where_budget = context.budget(last_line_width(&result)); + let pos_before_where = if type_param_bounds.is_empty() { + generics.where_clause.span.lo() + } else { + type_param_bounds[type_param_bounds.len() - 1].span().hi() + }; + let option = WhereClauseOption::snuggled(&generics_str); + let where_clause_str = rewrite_where_clause( + context, + &generics.where_clause, + context.config.brace_style(), + Shape::legacy(where_budget, offset.block_only()), + where_density, + "{", + None, + pos_before_where, + option, + false, + )?; + // If the where clause cannot fit on the same line, + // put the where clause on a new line + if !where_clause_str.contains('\n') + && last_line_width(&result) + where_clause_str.len() + offset.width() + > context.config.comment_width() + { + let width = offset.block_indent + context.config.tab_spaces() - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string_with_newline(context.config)); + } + result.push_str(&where_clause_str); } else { - type_param_bounds[type_param_bounds.len() - 1].span().hi() - }; - let option = WhereClauseOption::snuggled(&generics_str); - let where_clause_str = rewrite_where_clause( - context, - &generics.where_clause, - context.config.brace_style(), - Shape::legacy(where_budget, offset.block_only()), - where_density, - "{", - None, - pos_before_where, - option, - false, - )?; - // If the where clause cannot fit on the same line, - // put the where clause on a new line - if !where_clause_str.contains('\n') - && last_line_width(&result) + where_clause_str.len() + offset.width() - > context.config.comment_width() - { - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string_with_newline(context.config)); - } - result.push_str(&where_clause_str); - - if generics.where_clause.predicates.is_empty() { let item_snippet = context.snippet(item.span); if let Some(lo) = item_snippet.chars().position(|c| c == '/') { // 1 = `{` @@ -995,7 +995,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } match context.config.brace_style() { - _ if last_line_contains_single_line_comment(&result) => { + _ if last_line_contains_single_line_comment(&result) + || last_line_width(&result) + 2 > context.budget(offset.width()) => + { result.push_str(&offset.to_string_with_newline(context.config)); } BraceStyle::AlwaysNextLine => { @@ -1003,8 +1005,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() - && (!trait_items.is_empty() || result.contains('\n')) + if result.contains('\n') + || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty()) { result.push_str(&offset.to_string_with_newline(context.config)); } else { -- cgit 1.4.1-3-g733a5 From ccd134ed75f8c7f039040e9bdf60b8d904ff4fbc Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 15:11:49 +0900 Subject: Add a test for #2497 Closes #2497. --- src/items.rs | 4 ---- tests/source/where-clause-rfc.rs | 17 +++++++++++++++++ tests/target/where-clause-rfc.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1d02ba653ce..b639697194b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -921,10 +921,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } } if !type_param_bounds.is_empty() { - let shape = Shape { - indent: shape.indent.block_unindent(context.config), - ..shape - }; result = rewrite_assign_rhs_with( context, result + ":", diff --git a/tests/source/where-clause-rfc.rs b/tests/source/where-clause-rfc.rs index e41e9a6cea1..d915fccf1a0 100644 --- a/tests/source/where-clause-rfc.rs +++ b/tests/source/where-clause-rfc.rs @@ -56,3 +56,20 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // ... } } + +// #2497 +fn handle_update<'a, Tab, Conn, R, C>(executor: &Executor>>, change_set: &'a C) -> ExecutionResult +where &'a C: Identifiable + AsChangeset + HasTable, + <&'a C as AsChangeset>::Changeset: QueryFragment, + Tab: Table + HasTable
, + Tab::PrimaryKey: EqAll<<&'a C as Identifiable>::Id>, + Tab::FromClause: QueryFragment, + Tab: FindDsl<<&'a C as Identifiable>::Id>, + Find::Id>: IntoUpdateTarget
, + ::Id> as IntoUpdateTarget>::WhereClause: QueryFragment, + Tab::Query: FilterDsl<::Id>>::Output>, + Filter::Id>>::Output>: LimitDsl, + Limit::Id>>::Output>>: QueryDsl + BoxedDsl< 'a, Conn::Backend, Output = BoxedSelectStatement<'a, R::SqlType, Tab, Conn::Backend>>, + R: LoadingHandler + GraphQLType, { + unimplemented!() +} diff --git a/tests/target/where-clause-rfc.rs b/tests/target/where-clause-rfc.rs index 1e83d5b3abc..a41d82c8e41 100644 --- a/tests/target/where-clause-rfc.rs +++ b/tests/target/where-clause-rfc.rs @@ -126,3 +126,33 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // ... } } + +// #2497 +fn handle_update<'a, Tab, Conn, R, C>( + executor: &Executor>>, + change_set: &'a C, +) -> ExecutionResult +where + &'a C: Identifiable + AsChangeset + HasTable
, + <&'a C as AsChangeset>::Changeset: QueryFragment, + Tab: Table + HasTable
, + Tab::PrimaryKey: EqAll<<&'a C as Identifiable>::Id>, + Tab::FromClause: QueryFragment, + Tab: FindDsl<<&'a C as Identifiable>::Id>, + Find::Id>: IntoUpdateTarget
, + ::Id> as IntoUpdateTarget>::WhereClause: + QueryFragment, + Tab::Query: FilterDsl<::Id>>::Output>, + Filter::Id>>::Output>: LimitDsl, + Limit::Id>>::Output>>: + QueryDsl + + BoxedDsl< + 'a, + Conn::Backend, + Output = BoxedSelectStatement<'a, R::SqlType, Tab, Conn::Backend>, + >, + R: LoadingHandler + + GraphQLType, +{ + unimplemented!() +} -- cgit 1.4.1-3-g733a5 From 182b46e0ed29621f4cd29f39b8dd82f5a9b63e3f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 10 Mar 2018 15:23:42 +0900 Subject: Simplify join_bounds() --- src/types.rs | 28 ++++++++++------------------ tests/target/trait.rs | 3 +-- 2 files changed, 11 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 80ff8ce498a..676095ff4ce 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,8 +18,8 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, - PairParts, ToExpr}; +use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, + ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; @@ -485,17 +485,13 @@ fn rewrite_bounded_lifetime( if bounds.len() == 0 { Some(result) } else { - let appendix = bounds - .iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); let result = format!( "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, &appendix, true)? + join_bounds(context, shape.sub_width(overhead)?, bounds, true)? ); Some(result) } @@ -529,20 +525,13 @@ pub struct TraitTyParamBounds<'a> { impl<'a> Rewrite for TraitTyParamBounds<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs = self.inner - .iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - join_bounds(context, shape, self.inner, &strs, false) + join_bounds(context, shape, self.inner, false) } } impl Rewrite for ast::TyParamBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let strs = self.iter() - .map(|b| b.rewrite(context, shape)) - .collect::>>()?; - join_bounds(context, shape, self, &strs, true) + join_bounds(context, shape, self, true) } } @@ -779,7 +768,6 @@ fn join_bounds( context: &RewriteContext, shape: Shape, items: &[T], - type_strs: &[String], need_indent: bool, ) -> Option where @@ -790,6 +778,10 @@ where TypeDensity::Compressed => "+", TypeDensity::Wide => " + ", }; + let type_strs = items + .iter() + .map(|item| item.rewrite(context, shape)) + .collect::>>()?; let result = type_strs.join(joiner); if items.len() == 1 || (!result.contains('\n') && result.len() <= shape.width) { return Some(result); @@ -805,7 +797,7 @@ where .collect::>>()?; (type_strs, nested_shape.indent) } else { - (type_strs.to_vec(), shape.indent) + (type_strs, shape.indent) }; let joiner = format!("{}+ ", offset.to_string_with_newline(context.config)); diff --git a/tests/target/trait.rs b/tests/target/trait.rs index fa54b1d2df1..d1ee43f4e3f 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -65,8 +65,7 @@ where { } -trait FooBar: - Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt +trait FooBar: Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar, { -- cgit 1.4.1-3-g733a5 From 3999d64f12d8b211371a8adb9f1ce39f162a60f0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 12 Mar 2018 08:41:19 +0900 Subject: Simplify IgnoreList --- Configurations.md | 6 ++---- src/config/options.rs | 38 ++++++++++---------------------------- 2 files changed, 12 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 0b2048958e1..2b9cd13ad33 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2149,8 +2149,7 @@ Skip formatting the specified files and directories. If you want to ignore specific files, put the following to your config file: ```toml -[ignore] -files = [ +ignore = [ "src/types.rs", "src/foo/bar.rs", ] @@ -2159,8 +2158,7 @@ files = [ If you want to ignore every file under `examples/`, put the following to your config file: ```toml -[ignore] -directories = [ +ignore [ "examples", ] ``` diff --git a/src/config/options.rs b/src/config/options.rs index 7a5f9785b9b..31f7d106d1a 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -252,14 +252,12 @@ impl ::std::str::FromStr for WidthHeuristics { /// A set of directories, files and modules that rustfmt should ignore. #[derive(Default, Deserialize, Serialize, Clone, Debug)] -pub struct IgnoreList { - directories: Option>, - files: Option>, -} +pub struct IgnoreList(HashSet); impl IgnoreList { - fn add_prefix_inner(set: &HashSet, dir: &Path) -> HashSet { - set.iter() + pub fn add_prefix(&mut self, dir: &Path) { + self.0 = self.0 + .iter() .map(|s| { if s.has_root() { s.clone() @@ -269,29 +267,13 @@ impl IgnoreList { path } }) - .collect() - } - - pub fn add_prefix(&mut self, dir: &Path) { - macro add_prefix_inner_with ($($field: ident),* $(,)*) { - $(if let Some(set) = self.$field.as_mut() { - *set = IgnoreList::add_prefix_inner(set, dir); - })* - } - - add_prefix_inner_with!(directories, files); + .collect(); } - fn is_ignore_file(&self, path: &Path) -> bool { - self.files.as_ref().map_or(false, |set| set.contains(path)) - } - - fn is_under_ignore_dir(&self, path: &Path) -> bool { - if let Some(ref dirs) = self.directories { - for dir in dirs { - if path.starts_with(dir) { - return true; - } + fn skip_file_inner(&self, file: &Path) -> bool { + for path in &self.0 { + if file.starts_with(path) { + return true; } } @@ -300,7 +282,7 @@ impl IgnoreList { pub fn skip_file(&self, file: &FileName) -> bool { if let FileName::Real(ref path) = file { - self.is_ignore_file(path) || self.is_under_ignore_dir(path) + self.skip_file_inner(path) } else { false } -- cgit 1.4.1-3-g733a5 From c5168405b0a730cd101b04a4892c14808487e6c2 Mon Sep 17 00:00:00 2001 From: Matthew McAllister Date: Fri, 20 Oct 2017 22:09:45 -0700 Subject: Format attributes on block expressions --- src/closures.rs | 8 ++- src/expr.rs | 131 +++++++++++++++++++++++++++----------- src/items.rs | 17 +++-- src/visitor.rs | 10 ++- tests/target/attrib-block-expr.rs | 58 +++++++++++++++++ 5 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 tests/target/attrib-block-expr.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 6097f6339ed..65052d766eb 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -50,7 +50,8 @@ pub fn rewrite_closure( if let ast::ExprKind::Block(ref block) = body.node { // The body of the closure is an empty block. if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return Some(format!("{} {{}}", prefix)); + return body.rewrite(context, shape) + .map(|s| format!("{} {}", prefix, s)); } let result = match fn_decl.output { @@ -138,7 +139,7 @@ fn rewrite_closure_with_block( span: body.span, recovered: false, }; - let block = ::expr::rewrite_block_with_visitor(context, "", &block, shape, false)?; + let block = ::expr::rewrite_block_with_visitor(context, "", &block, None, shape, false)?; Some(format!("{} {}", prefix, block)) } @@ -291,7 +292,8 @@ pub fn rewrite_last_closure( if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { let body = match body.node { ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + if !is_unsafe_block(block) + && is_simple_block(block, Some(&body.attrs), context.codemap) => { stmt_expr(&block.stmts[0]).unwrap_or(body) } diff --git a/src/expr.rs b/src/expr.rs index 0e6b8f1bc1e..c959edd2fd7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -115,16 +115,25 @@ pub fn format_expr( match expr_type { ExprType::Statement => { if is_unsafe_block(block) { - block.rewrite(context, shape) - } else if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + rewrite_block(block, Some(&expr.attrs), context, shape) + } else if let rw @ Some(_) = + rewrite_empty_block(context, block, Some(&expr.attrs), "", shape) + { // Rewrite block without trying to put it in a single line. rw } else { let prefix = block_prefix(context, block, shape)?; - rewrite_block_with_visitor(context, &prefix, block, shape, true) + rewrite_block_with_visitor( + context, + &prefix, + block, + Some(&expr.attrs), + shape, + true, + ) } } - ExprType::SubExpression => block.rewrite(context, shape), + ExprType::SubExpression => rewrite_block(block, Some(&expr.attrs), context, shape), } } ast::ExprKind::Match(ref cond, ref arms) => { @@ -290,7 +299,9 @@ pub fn format_expr( Some(context.snippet(expr.span).to_owned()) } ast::ExprKind::Catch(ref block) => { - if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, shape) { + if let rw @ Some(_) = + rewrite_single_line_block(context, "do catch ", block, Some(&expr.attrs), shape) + { rw } else { // 9 = `do catch ` @@ -298,7 +309,12 @@ pub fn format_expr( Some(format!( "{}{}", "do catch ", - block.rewrite(context, Shape::legacy(budget, shape.indent))? + rewrite_block( + block, + Some(&expr.attrs), + context, + Shape::legacy(budget, shape.indent) + )? )) } } @@ -347,7 +363,7 @@ where let lhs_result = lhs.rewrite(context, lhs_shape) .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; - // Try to the both lhs and rhs on the same line. + // Try to put both lhs and rhs on the same line. let rhs_orig_result = shape .offset_left(last_line_width(&lhs_result) + pp.infix.len()) .and_then(|s| s.sub_width(pp.suffix.len())) @@ -564,11 +580,17 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option, + prefix: &str, shape: Shape, ) -> Option { + if attrs.map_or(false, |a| !inner_attributes(a).is_empty()) { + return None; + } + if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 { - return Some("{}".to_owned()); + return Some(format!("{}{{}}", prefix)); } // If a block contains only a single-line comment, then leave it on one line. @@ -579,7 +601,7 @@ fn rewrite_empty_block( if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") && comment_str.len() + 4 <= shape.width { - return Some(format!("{{ {} }}", comment_str)); + return Some(format!("{}{{ {} }}", prefix, comment_str)); } } @@ -618,9 +640,10 @@ fn rewrite_single_line_block( context: &RewriteContext, prefix: &str, block: &ast::Block, + attrs: Option<&[ast::Attribute]>, shape: Shape, ) -> Option { - if is_simple_block(block, context.codemap) { + if is_simple_block(block, attrs, context.codemap) { let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; let result = format!("{}{{ {} }}", prefix, expr_str); @@ -635,10 +658,11 @@ pub fn rewrite_block_with_visitor( context: &RewriteContext, prefix: &str, block: &ast::Block, + attrs: Option<&[ast::Attribute]>, shape: Shape, has_braces: bool, ) -> Option { - if let rw @ Some(_) = rewrite_empty_block(context, block, shape) { + if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, prefix, shape) { return rw; } @@ -654,31 +678,41 @@ pub fn rewrite_block_with_visitor( ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), } - visitor.visit_block(block, None, has_braces); + let inner_attrs = attrs.map(inner_attributes); + visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); Some(format!("{}{}", prefix, visitor.buffer)) } impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - // shape.width is used only for the single line case: either the empty block `{}`, - // or an unsafe expression `unsafe { e }`. - if let rw @ Some(_) = rewrite_empty_block(context, self, shape) { - return rw; - } + rewrite_block(self, None, context, shape) + } +} - let prefix = block_prefix(context, self, shape)?; +fn rewrite_block( + block: &ast::Block, + attrs: Option<&[ast::Attribute]>, + context: &RewriteContext, + shape: Shape, +) -> Option { + let prefix = block_prefix(context, block, shape)?; - let result = rewrite_block_with_visitor(context, &prefix, self, shape, true); - if let Some(ref result_str) = result { - if result_str.lines().count() <= 3 { - if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) { - return rw; - } + // shape.width is used only for the single line case: either the empty block `{}`, + // or an unsafe expression `unsafe { e }`. + if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, &prefix, shape) { + return rw; + } + + let result = rewrite_block_with_visitor(context, &prefix, block, attrs, shape, true); + if let Some(ref result_str) = result { + if result_str.lines().count() <= 3 { + if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, block, attrs, shape) { + return rw; } } - - result } + + result } impl Rewrite for ast::Stmt { @@ -889,8 +923,8 @@ impl<'a> ControlFlow<'a> { let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node) = else_block.node { - if !is_simple_block(self.block, context.codemap) - || !is_simple_block(else_node, context.codemap) + if !is_simple_block(self.block, None, context.codemap) + || !is_simple_block(else_node, None, context.codemap) || pat_expr_str.contains('\n') { return None; @@ -1123,7 +1157,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let mut block_context = context.clone(); block_context.is_if_else_block = self.else_block.is_some(); let block_str = - rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?; + rewrite_block_with_visitor(&block_context, "", self.block, None, block_shape, true)?; let mut result = format!("{}{}", cond_str, block_str); @@ -1234,22 +1268,39 @@ pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { contains_comment(&snippet) } -// Checks that a block contains no statements, an expression and no comments. +// Checks that a block contains no statements, an expression and no comments or +// attributes. // FIXME: incorrectly returns false when comment is contained completely within // the expression. -pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool { +pub fn is_simple_block( + block: &ast::Block, + attrs: Option<&[ast::Attribute]>, + codemap: &CodeMap, +) -> bool { (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, codemap)) + && !block_contains_comment(block, codemap) && attrs.map_or(true, |a| a.is_empty())) } -/// Checks whether a block contains at most one statement or expression, and no comments. -pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool { +/// Checks whether a block contains at most one statement or expression, and no +/// comments or attributes. +pub fn is_simple_block_stmt( + block: &ast::Block, + attrs: Option<&[ast::Attribute]>, + codemap: &CodeMap, +) -> bool { block.stmts.len() <= 1 && !block_contains_comment(block, codemap) + && attrs.map_or(true, |a| a.is_empty()) } -/// Checks whether a block contains no statements, expressions, or comments. -pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool { +/// Checks whether a block contains no statements, expressions, comments, or +/// inner attributes. +pub fn is_empty_block( + block: &ast::Block, + attrs: Option<&[ast::Attribute]>, + codemap: &CodeMap, +) -> bool { block.stmts.is_empty() && !block_contains_comment(block, codemap) + && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { @@ -1577,7 +1628,8 @@ fn rewrite_match_pattern( fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { match body.node { ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) && is_simple_block(block, context.codemap) => + if !is_unsafe_block(block) + && is_simple_block(block, Some(&body.attrs), context.codemap) => { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( @@ -1605,7 +1657,10 @@ fn rewrite_match_body( ) -> Option { let (extend, body) = flatten_arm_body(context, body); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { - (true, is_empty_block(block, context.codemap)) + ( + true, + is_empty_block(block, Some(&body.attrs), context.codemap), + ) } else { (false, false) }; diff --git a/src/items.rs b/src/items.rs index b639697194b..6306767f00c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -301,6 +301,7 @@ impl<'a> FmtVisitor<'a> { fn_sig: &FnSig, span: Span, block: &ast::Block, + inner_attrs: Option<&[ast::Attribute]>, ) -> Option { let context = self.get_context(); @@ -329,7 +330,8 @@ impl<'a> FmtVisitor<'a> { result.push(' '); } - self.single_line_fn(&result, block).or_else(|| Some(result)) + self.single_line_fn(&result, block, inner_attrs) + .or_else(|| Some(result)) } pub fn rewrite_required_fn( @@ -360,20 +362,25 @@ impl<'a> FmtVisitor<'a> { Some(result) } - fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option { - if fn_str.contains('\n') { + fn single_line_fn( + &self, + fn_str: &str, + block: &ast::Block, + inner_attrs: Option<&[ast::Attribute]>, + ) -> Option { + if fn_str.contains('\n') || inner_attrs.map_or(false, |a| !a.is_empty()) { return None; } let codemap = self.get_context().codemap; - if self.config.empty_item_single_line() && is_empty_block(block, codemap) + if self.config.empty_item_single_line() && is_empty_block(block, None, codemap) && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { return Some(format!("{}{{}}", fn_str)); } - if self.config.fn_single_line() && is_simple_block_stmt(block, codemap) { + if self.config.fn_single_line() && is_simple_block_stmt(block, None, codemap) { let rewrite = { if let Some(stmt) = block.stmts.first() { match stmt_expr(stmt) { diff --git a/src/visitor.rs b/src/visitor.rs index f1b50e19b61..81f35d787ab 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -268,6 +268,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &FnSig::from_fn_kind(&fk, generics, fd, defaultness), mk_sp(s.lo(), b.span.lo()), b, + inner_attrs, ) } visit::FnKind::Closure(_) => unreachable!(), @@ -381,13 +382,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_static(&StaticParts::from_item(item)); } ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { + let inner_attrs = inner_attributes(&item.attrs); self.visit_fn( visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), generics, decl, item.span, ast::Defaultness::Final, - Some(&item.attrs), + Some(&inner_attrs), ) } ast::ItemKind::Ty(ref ty, ref generics) => { @@ -438,13 +440,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, Some(ref body)) => { + let inner_attrs = inner_attributes(&ti.attrs); self.visit_fn( visit::FnKind::Method(ti.ident, sig, None, body), &ti.generics, &sig.decl, ti.span, ast::Defaultness::Final, - Some(&ti.attrs), + Some(&inner_attrs), ); } ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { @@ -473,13 +476,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { match ii.node { ast::ImplItemKind::Method(ref sig, ref body) => { + let inner_attrs = inner_attributes(&ii.attrs); self.visit_fn( visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), &ii.generics, &sig.decl, ii.span, ii.defaultness, - Some(&ii.attrs), + Some(&inner_attrs), ); } ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), diff --git a/tests/target/attrib-block-expr.rs b/tests/target/attrib-block-expr.rs new file mode 100644 index 00000000000..1e9557dc039 --- /dev/null +++ b/tests/target/attrib-block-expr.rs @@ -0,0 +1,58 @@ +fn issue_2073() { + let x = { + #![my_attr] + do_something() + }; + + let x = #[my_attr] + { + do_something() + }; + + let x = #[my_attr] + {}; + + { + #![just_an_attribute] + }; + + let z = #[attr1] + #[attr2] + { + body() + }; + + x = |y| { + #![inner] + }; + + x = |y| #[outer] + {}; + + x = |y| { + //! ynot + }; + + x = |y| #[outer] + unsafe {}; + + let x = unsafe { + #![my_attr] + do_something() + }; + + let x = #[my_attr] + unsafe { + do_something() + }; + + // This is a dumb but possible case + let x = #[my_attr] + unsafe {}; + + x = |y| #[outer] + #[outer2] + unsafe { + //! Comment + }; +} -- cgit 1.4.1-3-g733a5 From eda626cfc9659658a89cc28680066f69aef11b0e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 15 Mar 2018 18:55:52 +0900 Subject: Call syntax::with_globals before using a parser --- src/lib.rs | 8 ++++++++ src/macros.rs | 29 +++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 9857abe2b52..37cf29196ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -657,6 +657,14 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option } pub fn format_input( + input: Input, + config: &Config, + out: Option<&mut T>, +) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { + syntax::with_globals(|| format_input_inner(input, config, out)) +} + +fn format_input_inner( input: Input, config: &Config, mut out: Option<&mut T>, diff --git a/src/macros.rs b/src/macros.rs index 78a8f0c0b31..b260e15501f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -962,22 +962,27 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) #[cfg(test)] mod test { use super::*; + use syntax; use syntax::parse::{parse_stream_from_source_str, ParseSess}; use syntax::codemap::{FileName, FilePathMapping}; fn format_macro_args_str(s: &str) -> String { - let input = parse_stream_from_source_str( - FileName::Custom("stdin".to_owned()), - s.to_owned(), - &ParseSess::new(FilePathMapping::empty()), - None, - ); - let shape = Shape { - width: 100, - indent: Indent::empty(), - offset: 0, - }; - format_macro_args(input.into(), shape).unwrap() + let mut result = String::new(); + syntax::with_globals(|| { + let input = parse_stream_from_source_str( + FileName::Custom("stdin".to_owned()), + s.to_owned(), + &ParseSess::new(FilePathMapping::empty()), + None, + ); + let shape = Shape { + width: 100, + indent: Indent::empty(), + offset: 0, + }; + result = format_macro_args(input.into(), shape).unwrap(); + }); + result } #[test] -- cgit 1.4.1-3-g733a5 From a03b3b7d6fc11f0ecd3a3bd7596ef7120e3b8192 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 16 Mar 2018 08:52:30 +0900 Subject: Cargo update Remove `rustc-ap-rustc_errors` from dependencies since it is re-exported from `rustc-ap-syntax`. --- Cargo.lock | 29 ++++++++++++++--------------- Cargo.toml | 1 - src/lib.rs | 5 ++--- 3 files changed, 16 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 6d9204881c7..fd94eadface 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,8 +54,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -384,10 +384,9 @@ dependencies = [ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -406,7 +405,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -416,23 +415,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -447,7 +446,7 @@ dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -520,7 +519,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -648,9 +647,9 @@ dependencies = [ "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c73f63e08b33f6e59dfb3365b009897ebc3a3edc4af6e4f3ce8e483cf3d80ce7" -"checksum serde_derive 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9cd9e89b8be5b611971734eaf887f1da0ce1a5b51491f04b09fe855649a84f3b" -"checksum serde_derive_internals 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a79b781fe5c4a7037a10a485249a499ea02927046360afe7e04885aad2f9c10c" +"checksum serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe95aa0d46f04ce5c3a88bdcd4114ecd6144ed0b2725ebca2f1127744357807" +"checksum serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "23b163a6ce7e1aa897919f9d8e40bd1f8a6f95342ed57727ae31387a01a7a356" +"checksum serde_derive_internals 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "370aa477297975243dc914d0b0e1234927520ec311de507a560fbd1c80f7ab8c" "checksum serde_json 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fab6c4d75bedcf880711c85e39ebf8ccc70d0eba259899047ec5d7436643ee17" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" diff --git a/Cargo.toml b/Cargo.toml index 528513fca92..d3eebea4db7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,6 @@ getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" rustc-ap-syntax = "67.0.0" -rustc-ap-rustc_errors = "67.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/lib.rs b/src/lib.rs index 37cf29196ac..eff414b5708 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,6 @@ extern crate itertools; #[macro_use] extern crate log; extern crate regex; -extern crate rustc_errors as errors; extern crate serde; #[macro_use] extern crate serde_derive; @@ -39,8 +38,8 @@ use std::path::PathBuf; use std::rc::Rc; use std::time::Duration; -use errors::{DiagnosticBuilder, Handler}; -use errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::errors::{DiagnosticBuilder, Handler}; +use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping}; pub use syntax::codemap::FileName; -- cgit 1.4.1-3-g733a5 From ca6fc67e6015b14efba03a0b580ee40ffaff2a29 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 17 Mar 2018 12:16:15 +0900 Subject: Fix print_version --- build.rs | 14 ++++++++++++-- src/bin/main.rs | 3 +-- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index 2643946236d..d72b44eb7f3 100644 --- a/build.rs +++ b/build.rs @@ -26,12 +26,22 @@ fn main() { // Try to get hash and date of the last commit on a best effort basis. If anything goes wrong // (git not installed or if this is not a git repository) just return an empty string. fn commit_info() -> String { - match (commit_hash(), commit_date()) { - (Some(hash), Some(date)) => format!(" ({} {})", hash.trim_right(), date), + match (channel(), commit_hash(), commit_date()) { + (channel, Some(hash), Some(date)) => { + format!("{} ({} {})", channel, hash.trim_right(), date) + } _ => String::new(), } } +fn channel() -> String { + if let Ok(channel) = env::var("CFG_RELEASE_CHANNEL") { + channel + } else { + "nightly".to_owned() + } +} + fn commit_hash() -> Option { Command::new("git") .args(&["rev-parse", "--short", "HEAD"]) diff --git a/src/bin/main.rs b/src/bin/main.rs index 4a49ce5a2e6..c89c25a90fe 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -385,9 +385,8 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) { fn print_version() { let version_info = format!( - "{}{}{}", + "{}-{}", option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), - "-", include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) ); -- cgit 1.4.1-3-g733a5 From d7188654ea4a0299525caf4196ef366d38c9eb98 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 17 Mar 2018 14:59:26 +0900 Subject: Skip name replacement in comments and strings --- src/macros.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b260e15501f..03f73789310 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,8 @@ use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::util::ThinVec; use codemap::SpanUtils; -use comment::{contains_comment, remove_trailing_white_spaces, FindUncommented}; +use comment::{contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, + FullCodeCharKind}; use expr::rewrite_array; use lists::{itemize_list, write_list, ListFormatting}; use overflow; @@ -409,8 +410,10 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { let mut dollar_count = 0; let mut cur_name = String::new(); - for c in input.chars() { - if c == '$' { + for (kind, c) in CharClasses::new(input.chars()) { + if kind != FullCodeCharKind::Normal { + result.push(c); + } else if c == '$' { dollar_count += 1; } else if dollar_count == 0 { result.push(c); -- cgit 1.4.1-3-g733a5 From 1a969cff7fe3dc5cef4f36e1786db5dc22b6ed6a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 17 Mar 2018 14:59:39 +0900 Subject: Remove FIXME about duplicated code --- src/macros.rs | 54 +++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 03f73789310..030988e5195 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -400,6 +400,28 @@ pub fn rewrite_macro_def( Some(result) } +fn register_metavariable( + map: &mut HashMap, + result: &mut String, + name: &str, + dollar_count: usize, +) { + let mut new_name = String::new(); + let mut old_name = String::new(); + + old_name.push('$'); + for _ in 0..(dollar_count - 1) { + new_name.push('$'); + old_name.push('$'); + } + new_name.push('z'); + new_name.push_str(&name); + old_name.push_str(&name); + + result.push_str(&new_name); + map.insert(old_name, new_name); +} + // Replaces `$foo` with `zfoo`. We must check for name overlap to ensure we // aren't causing problems. // This should also work for escaped `$` variables, where we leave earlier `$`s. @@ -419,24 +441,11 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { result.push(c); } else if !c.is_alphanumeric() && !cur_name.is_empty() { // Terminates a name following one or more dollars. - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); + register_metavariable(&mut substs, &mut result, &cur_name, dollar_count); result.push(c); - dollar_count = 0; - cur_name = String::new(); + cur_name.clear(); } else if c == '(' && cur_name.is_empty() { // FIXME: Support macro def with repeat. return None; @@ -445,21 +454,8 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { } } - // FIXME: duplicate code if !cur_name.is_empty() { - let mut new_name = String::new(); - let mut old_name = String::new(); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } - new_name.push('z'); - new_name.push_str(&cur_name); - old_name.push_str(&cur_name); - - result.push_str(&new_name); - substs.insert(old_name, new_name); + register_metavariable(&mut substs, &mut result, &cur_name, dollar_count); } debug!("replace_names `{}` {:?}", result, substs); -- cgit 1.4.1-3-g733a5 From 84ea306d32f0b9950346108c51c10d2e763530ae Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 01:08:10 +0900 Subject: Remove unit tests --- src/macros.rs | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 030988e5195..1b26c61a820 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -957,50 +957,3 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) Some(result) } - -#[cfg(test)] -mod test { - use super::*; - use syntax; - use syntax::parse::{parse_stream_from_source_str, ParseSess}; - use syntax::codemap::{FileName, FilePathMapping}; - - fn format_macro_args_str(s: &str) -> String { - let mut result = String::new(); - syntax::with_globals(|| { - let input = parse_stream_from_source_str( - FileName::Custom("stdin".to_owned()), - s.to_owned(), - &ParseSess::new(FilePathMapping::empty()), - None, - ); - let shape = Shape { - width: 100, - indent: Indent::empty(), - offset: 0, - }; - result = format_macro_args(input.into(), shape).unwrap(); - }); - result - } - - #[test] - fn test_format_macro_args() { - assert_eq!(format_macro_args_str(""), "".to_owned()); - assert_eq!(format_macro_args_str("$ x : ident"), "$x: ident".to_owned()); - assert_eq!( - format_macro_args_str("$ m1 : ident , $ m2 : ident , $ x : ident"), - "$m1: ident, $m2: ident, $x: ident".to_owned() - ); - assert_eq!( - format_macro_args_str("$($beginning:ident),*;$middle:ident;$($end:ident),*"), - "$($beginning: ident),*; $middle: ident; $($end: ident),*".to_owned() - ); - assert_eq!( - format_macro_args_str( - "$ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) *" - ), - "$name: ident($($dol: tt $var: ident)*) $($body: tt)*".to_owned() - ); - } -} -- cgit 1.4.1-3-g733a5 From ec71459c44045c867bad055d3c954d46fd587a03 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 01:08:18 +0900 Subject: Format macro arguments with vertical layout --- src/macros.rs | 443 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 384 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 1b26c61a820..d6420af764b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -463,73 +463,401 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { Some((result, substs)) } -// This is a bit sketchy. The token rules probably need tweaking, but it works -// for some common cases. I hope the basic logic is sufficient. Note that the -// meaning of some tokens is a bit different here from usual Rust, e.g., `*` -// and `(`/`)` have special meaning. -// -// We always try and format on one line. -// FIXME: Use multi-line when every thing does not fit on one line. -fn format_macro_args(toks: ThinTokenStream, shape: Shape) -> Option { - let mut result = String::with_capacity(128); - let mut insert_space = SpaceState::Never; +#[derive(Debug, Clone)] +enum MacroArgKind { + MetaVariable(ast::Ident, String), + Repeat( + DelimToken, + Vec, + Option>, + Token, + ), + Delimited(DelimToken, Vec), + Separator(String, String), + Other(String, String), +} - for tok in (toks.into(): TokenStream).trees() { - match tok { - TokenTree::Token(_, t) => { - if !result.is_empty() && force_space_before(&t) { - insert_space = SpaceState::Always; - } - if force_no_space_before(&t) { - insert_space = SpaceState::Never; - } - match (insert_space, ident_like(&t)) { - (SpaceState::Always, _) - | (SpaceState::Punctuation, false) - | (SpaceState::Ident, true) => { - result.push(' '); +fn delim_token_to_str( + context: &RewriteContext, + delim_token: &DelimToken, + shape: Shape, + use_multiple_lines: bool, +) -> (String, String) { + let (lhs, rhs) = match *delim_token { + DelimToken::Paren => ("(", ")"), + DelimToken::Bracket => ("[", "]"), + DelimToken::Brace => ("{", "}"), + DelimToken::NoDelim => ("", ""), + }; + if use_multiple_lines { + let indent_str = shape.indent.to_string_with_newline(context.config); + let nested_indent_str = shape + .indent + .block_indent(context.config) + .to_string_with_newline(context.config); + ( + format!("{}{}", lhs, nested_indent_str), + format!("{}{}", indent_str, rhs), + ) + } else { + (lhs.to_owned(), rhs.to_owned()) + } +} + +impl MacroArgKind { + fn starts_with_dollar(&self) -> bool { + match *self { + MacroArgKind::Repeat(..) | MacroArgKind::MetaVariable(..) => true, + _ => false, + } + } + + fn ends_with_space(&self) -> bool { + match *self { + MacroArgKind::Separator(..) => true, + _ => false, + } + } + + fn has_prefix_space(&self) -> bool { + match *self { + MacroArgKind::Separator(_, ref prefix) | MacroArgKind::Other(_, ref prefix) => { + prefix.starts_with(" ") + } + _ => false, + } + } + + fn rewrite( + &self, + context: &RewriteContext, + shape: Shape, + use_multiple_lines: bool, + ) -> Option { + let rewrite_delimited_inner = |delim_tok, args| -> Option<(String, String, String)> { + let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false); + let inner = wrap_macro_args(context, args, shape)?; + if lhs.len() + inner.len() + rhs.len() <= shape.width { + return Some((lhs, inner, rhs)); + } + + let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true); + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let inner = wrap_macro_args(context, args, nested_shape)?; + Some((lhs, inner, rhs)) + }; + + match *self { + MacroArgKind::MetaVariable(ty, ref name) => { + Some(format!("${}: {}", name, ty.name.as_str())) + } + MacroArgKind::Repeat(ref delim_tok, ref args, ref another, ref tok) => { + let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?; + let another = another + .as_ref() + .and_then(|a| a.rewrite(context, shape, use_multiple_lines)) + .unwrap_or("".to_owned()); + let repeat_tok = pprust::token_to_string(tok); + + Some(format!("${}{}{}{}{}", lhs, inner, rhs, another, repeat_tok)) + } + MacroArgKind::Delimited(ref delim_tok, ref args) => { + rewrite_delimited_inner(delim_tok, args) + .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs)) + } + MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{}{} ", prefix, sep)), + MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{}{}", prefix, inner)), + } + } +} + +#[derive(Debug, Clone)] +struct ParsedMacroArg { + kind: MacroArgKind, + span: Span, +} + +impl ParsedMacroArg { + pub fn rewrite( + &self, + context: &RewriteContext, + shape: Shape, + use_multiple_lines: bool, + ) -> Option { + self.kind.rewrite(context, shape, use_multiple_lines) + } +} + +struct MacroArgParser { + lo: BytePos, + hi: BytePos, + buf: String, + is_arg: bool, + last_tok: Token, + start_tok: Token, + result: Vec, +} + +fn last_tok(tt: &TokenTree) -> Token { + match *tt { + TokenTree::Token(_, ref t) => t.clone(), + TokenTree::Delimited(_, ref d) => d.close_token(), + } +} + +impl MacroArgParser { + pub fn new() -> MacroArgParser { + MacroArgParser { + lo: BytePos(0), + hi: BytePos(0), + buf: String::new(), + is_arg: false, + last_tok: Token::Eof, + start_tok: Token::Eof, + result: vec![], + } + } + + fn set_last_tok(&mut self, tok: &TokenTree) { + self.hi = tok.span().hi(); + self.last_tok = last_tok(tok); + } + + fn add_separator(&mut self) { + let prefix = if self.need_space_prefix() { + " ".to_owned() + } else { + "".to_owned() + }; + self.result.push(ParsedMacroArg { + kind: MacroArgKind::Separator(self.buf.clone(), prefix), + span: mk_sp(self.lo, self.hi), + }); + self.buf.clear(); + } + + fn add_other(&mut self) { + let prefix = if self.need_space_prefix() { + " ".to_owned() + } else { + "".to_owned() + }; + self.result.push(ParsedMacroArg { + kind: MacroArgKind::Other(self.buf.clone(), prefix), + span: mk_sp(self.lo, self.hi), + }); + self.buf.clear(); + } + + fn add_meta_variable(&mut self, iter: &mut Cursor) { + match iter.next() { + Some(TokenTree::Token(sp, Token::Ident(ref ident))) => { + self.result.push(ParsedMacroArg { + kind: MacroArgKind::MetaVariable(ident.clone(), self.buf.clone()), + span: mk_sp(self.lo, sp.hi()), + }); + + self.buf.clear(); + self.is_arg = false; + } + _ => unreachable!(), + } + } + + fn update_buffer(&mut self, lo: BytePos, t: &Token) { + if self.buf.is_empty() { + self.lo = lo; + self.start_tok = t.clone(); + } else if force_space_before(t) { + self.buf.push(' '); + } + + self.buf.push_str(&pprust::token_to_string(t)); + } + + fn need_space_prefix(&self) -> bool { + if self.result.is_empty() { + return false; + } + + let last_arg = self.result.last().unwrap(); + if let MacroArgKind::MetaVariable(..) = last_arg.kind { + if ident_like(&self.start_tok) { + return true; + } + } + + if force_space_before(&self.start_tok) { + return true; + } + + false + } + + /// Returns a collection of parsed macro def's arguments. + pub fn parse(mut self, tokens: ThinTokenStream) -> Vec { + let mut iter = (tokens.into(): TokenStream).trees(); + + while let Some(ref tok) = iter.next() { + match tok { + TokenTree::Token(sp, Token::Dollar) => { + // We always want to add a separator before meta variables. + if !self.buf.is_empty() { + self.add_separator(); } - _ => {} + + // Start keeping the name of this metavariable in the buffer. + self.is_arg = true; + self.lo = sp.lo(); + self.start_tok = Token::Dollar; } - result.push_str(&pprust::token_to_string(&t)); - insert_space = next_space(&t); - } - TokenTree::Delimited(_, d) => { - if let SpaceState::Always = insert_space { - result.push(' '); + TokenTree::Token(_, Token::Colon) if self.is_arg => { + self.add_meta_variable(&mut iter); } - let formatted = format_macro_args(d.tts, shape)?; - match d.delim { - DelimToken::Paren => { - result.push_str(&format!("({})", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::Bracket => { - result.push_str(&format!("[{}]", formatted)); - insert_space = SpaceState::Always; - } - DelimToken::Brace => { - result.push_str(&format!(" {{ {} }}", formatted)); - insert_space = SpaceState::Always; + TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t), + TokenTree::Delimited(sp, ref delimited) => { + if !self.buf.is_empty() { + if next_space(&self.last_tok) == SpaceState::Always { + self.add_separator(); + } else { + self.add_other(); + } } - DelimToken::NoDelim => { - result.push_str(&format!("{}", formatted)); - insert_space = SpaceState::Always; + + let mut parser = MacroArgParser::new(); + parser.lo = sp.lo(); + let mut delimited_arg = parser.parse(delimited.tts.clone()); + + if self.is_arg { + // Parse '*' or '+'. + let mut buffer = String::new(); + let mut first = false; + let mut lo = sp.lo(); + + while let Some(ref next_tok) = iter.next() { + self.set_last_tok(next_tok); + if first { + first = false; + lo = next_tok.span().lo(); + } + + match next_tok { + TokenTree::Token(_, Token::BinOp(BinOpToken::Plus)) + | TokenTree::Token(_, Token::Question) + | TokenTree::Token(_, Token::BinOp(BinOpToken::Star)) => { + break; + } + TokenTree::Token(_, ref t) => { + buffer.push_str(&pprust::token_to_string(t)) + } + _ => unreachable!(), + } + } + + let another = if buffer.trim().is_empty() { + None + } else { + Some(Box::new(ParsedMacroArg { + kind: MacroArgKind::Other(buffer, "".to_owned()), + span: mk_sp(lo, self.hi), + })) + }; + + self.result.push(ParsedMacroArg { + kind: MacroArgKind::Repeat( + delimited.delim, + delimited_arg, + another, + self.last_tok.clone(), + ), + span: mk_sp(self.lo, self.hi), + }); + } else { + self.result.push(ParsedMacroArg { + kind: MacroArgKind::Delimited(delimited.delim, delimited_arg), + span: *sp, + }); } } } + + self.set_last_tok(tok); + } + + if !self.buf.is_empty() { + self.add_other(); + } + + self.result + } +} + +fn wrap_macro_args( + context: &RewriteContext, + args: &[ParsedMacroArg], + shape: Shape, +) -> Option { + wrap_macro_args_inner(context, args, shape, false) + .or_else(|| wrap_macro_args_inner(context, args, shape, true)) +} + +fn wrap_macro_args_inner( + context: &RewriteContext, + args: &[ParsedMacroArg], + shape: Shape, + use_multiple_lines: bool, +) -> Option { + let mut result = String::with_capacity(128); + let mut iter = args.iter().peekable(); + let indent_str = shape.indent.to_string_with_newline(context.config); + + while let Some(ref arg) = iter.next() { + let nested_shape = if use_multiple_lines { + shape.with_max_width(context.config) + } else { + shape + }; + result.push_str(&arg.rewrite(context, nested_shape, use_multiple_lines)?); + + if use_multiple_lines && arg.kind.ends_with_space() { + result.pop(); + result.push_str(&indent_str); + } else if let Some(ref next_arg) = iter.peek() { + let space_before_dollar = + !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar(); + if space_before_dollar { + result.push(' '); + } } } - if result.len() <= shape.width { - Some(result) - } else { + if !use_multiple_lines && result.len() >= shape.width { None + } else { + Some(result) } } +// This is a bit sketchy. The token rules probably need tweaking, but it works +// for some common cases. I hope the basic logic is sufficient. Note that the +// meaning of some tokens is a bit different here from usual Rust, e.g., `*` +// and `(`/`)` have special meaning. +// +// We always try and format on one line. +// FIXME: Use multi-line when every thing does not fit on one line. +fn format_macro_args( + context: &RewriteContext, + toks: ThinTokenStream, + shape: Shape, +) -> Option { + let parsed_args = MacroArgParser::new().parse(toks); + wrap_macro_args(context, &parsed_args, shape) +} + // We should insert a space if the next token is a: -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] enum SpaceState { Never, Punctuation, @@ -538,6 +866,8 @@ enum SpaceState { } fn force_space_before(tok: &Token) -> bool { + debug!("tok: force_space_before {:?}", tok); + match *tok { Token::Eq | Token::Lt @@ -562,13 +892,6 @@ fn force_space_before(tok: &Token) -> bool { } } -fn force_no_space_before(tok: &Token) -> bool { - match *tok { - Token::Semi | Token::Comma | Token::Dot => true, - Token::BinOp(bot) => bot == BinOpToken::Star, - _ => false, - } -} fn ident_like(tok: &Token) -> bool { match *tok { Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, @@ -577,6 +900,8 @@ fn ident_like(tok: &Token) -> bool { } fn next_space(tok: &Token) -> SpaceState { + debug!("next_space: {:?}", tok); + match *tok { Token::Not | Token::Tilde @@ -804,7 +1129,7 @@ impl MacroBranch { } // 5 = " => {" - let mut result = format_macro_args(self.args.clone(), shape.sub_width(5)?)?; + let mut result = format_macro_args(context, self.args.clone(), shape.sub_width(5)?)?; if multi_branch_style { result += " =>"; -- cgit 1.4.1-3-g733a5 From 95507e3a4369404443787ac835b2c377c685472b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 12:33:30 +0900 Subject: Remove has_prefix_space --- src/macros.rs | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index d6420af764b..e600b119678 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -519,15 +519,6 @@ impl MacroArgKind { } } - fn has_prefix_space(&self) -> bool { - match *self { - MacroArgKind::Separator(_, ref prefix) | MacroArgKind::Other(_, ref prefix) => { - prefix.starts_with(" ") - } - _ => false, - } - } - fn rewrite( &self, context: &RewriteContext, -- cgit 1.4.1-3-g733a5 From 3f7b59ca2b3f3eaa5659743dfa28dce9f7302a74 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 12:33:59 +0900 Subject: Break before meta variables when using multiple lines --- src/macros.rs | 16 ++++++++++++++-- tests/source/macro_rules.rs | 3 +++ tests/target/macro_rules.rs | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index e600b119678..f71c648baac 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -519,6 +519,14 @@ impl MacroArgKind { } } + fn has_meta_var(&self) -> bool { + match *self { + MacroArgKind::MetaVariable(..) => true, + MacroArgKind::Repeat(_, ref args, _, _) => args.iter().any(|a| a.kind.has_meta_var()), + _ => false, + } + } + fn rewrite( &self, context: &RewriteContext, @@ -812,8 +820,12 @@ fn wrap_macro_args_inner( }; result.push_str(&arg.rewrite(context, nested_shape, use_multiple_lines)?); - if use_multiple_lines && arg.kind.ends_with_space() { - result.pop(); + if use_multiple_lines + && (arg.kind.ends_with_space() || iter.peek().map_or(false, |a| a.kind.has_meta_var())) + { + if arg.kind.ends_with_space() { + result.pop(); + } result.push_str(&indent_str); } else if let Some(ref next_arg) = iter.peek() { let space_before_dollar = diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index 17bb3067869..2d0d0e80a6b 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -7,6 +7,9 @@ macro_rules! m { ( $($beginning:ident),*;$middle:ident;$($end:ident),* ) => (); ( $($beginning: ident),*; $middle: ident; $($end: ident),*; $($beginning: ident),*; $middle: ident; $($end: ident),* ) => {}; ( $ name : ident ( $ ( $ dol : tt $ var : ident ) * ) $ ( $ body : tt ) * ) => (); + ( $( $ i : ident : $ ty : ty , $def : expr , $stb : expr , $ ( $ dstring : tt ) , + ) ; + $ ( ; ) * + $( $ i : ident : $ ty : ty , $def : expr , $stb : expr , $ ( $ dstring : tt ) , + ) ; + $ ( ; ) * + ) => {}; } macro_rules! m { diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 5bedc2a8258..54d7dde6842 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -14,6 +14,10 @@ macro_rules! m { $($end: ident),* ) => {}; ($name: ident($($dol: tt $var: ident)*) $($body: tt)*) => {}; + ( + $($i: ident: $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* + $($i: ident: $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* + ) => {}; } macro_rules! m { -- cgit 1.4.1-3-g733a5 From 0fd174d5f1e51a03b6454617c780f2ea6cd4cb6b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 13:12:16 +0900 Subject: Handle binary operators and lifetimes --- src/macros.rs | 18 +++++++++++++----- tests/source/macro_rules.rs | 7 +++++++ tests/target/macro_rules.rs | 7 +++++++ 3 files changed, 27 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index f71c648baac..9b5fda2c1ec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -669,8 +669,16 @@ impl MacroArgParser { if self.buf.is_empty() { self.lo = lo; self.start_tok = t.clone(); - } else if force_space_before(t) { - self.buf.push(' '); + } else { + let needs_space = match next_space(&self.last_tok) { + SpaceState::Ident => ident_like(t), + SpaceState::Punctuation => !ident_like(t), + SpaceState::Always => true, + SpaceState::Never => false, + }; + if force_space_before(t) || needs_space { + self.buf.push(' '); + } } self.buf.push_str(&pprust::token_to_string(t)); @@ -888,9 +896,9 @@ fn force_space_before(tok: &Token) -> bool { | Token::RArrow | Token::LArrow | Token::FatArrow + | Token::BinOp(_) | Token::Pound | Token::Dollar => true, - Token::BinOp(bot) => bot != BinOpToken::Star, _ => false, } } @@ -907,6 +915,7 @@ fn next_space(tok: &Token) -> SpaceState { match *tok { Token::Not + | Token::BinOp(BinOpToken::And) | Token::Tilde | Token::At | Token::Comma @@ -916,8 +925,7 @@ fn next_space(tok: &Token) -> SpaceState { | Token::DotDotEq | Token::DotEq | Token::Question - | Token::Underscore - | Token::BinOp(_) => SpaceState::Punctuation, + | Token::Underscore => SpaceState::Punctuation, Token::ModSep | Token::Pound diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index 2d0d0e80a6b..1a4d8131600 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -10,6 +10,13 @@ macro_rules! m { ( $( $ i : ident : $ ty : ty , $def : expr , $stb : expr , $ ( $ dstring : tt ) , + ) ; + $ ( ; ) * $( $ i : ident : $ ty : ty , $def : expr , $stb : expr , $ ( $ dstring : tt ) , + ) ; + $ ( ; ) * ) => {}; + ( $foo: tt foo [$ attr : meta] $name: ident ) => {}; + ( $foo: tt [$ attr: meta] $name: ident ) => {}; + ( $foo: tt &'a [$attr : meta] $name: ident ) => {}; + ( $foo: tt foo # [ $attr : meta] $name: ident ) => {}; + ( $foo: tt # [ $attr : meta] $name: ident) => {}; + ( $foo: tt &'a # [ $attr : meta] $name: ident ) => {}; + ( $ x : tt foo bar foo bar foo bar $ y : tt => x*y*z $ z : tt , $ ( $a: tt ) , * ) => {}; } macro_rules! m { diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 54d7dde6842..ece16399184 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -18,6 +18,13 @@ macro_rules! m { $($i: ident: $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* $($i: ident: $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* ) => {}; + ($foo: tt foo[$attr: meta] $name: ident) => {}; + ($foo: tt[$attr: meta] $name: ident) => {}; + ($foo: tt &'a[$attr: meta] $name: ident) => {}; + ($foo: tt foo #[$attr: meta] $name: ident) => {}; + ($foo: tt #[$attr: meta] $name: ident) => {}; + ($foo: tt &'a #[$attr: meta] $name: ident) => {}; + ($x: tt foo bar foo bar foo bar $y: tt => x * y * z $z: tt, $($a: tt),*) => {}; } macro_rules! m { -- cgit 1.4.1-3-g733a5 From 96a83b57e51793de579dc90dc82525cd9f018148 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 13:49:06 +0900 Subject: Add some doc comments and factor out add_repeat and add_delimited --- src/macros.rs | 148 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 9b5fda2c1ec..9c7a7177ea1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -465,15 +465,25 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { #[derive(Debug, Clone)] enum MacroArgKind { + /// e.g. `$x: expr`. MetaVariable(ast::Ident, String), + /// e.g. `$($foo: expr),*` Repeat( + /// `()`, `[]` or `{}`. DelimToken, + /// Inner arguments inside delimiters. Vec, + /// Something after the closing delimiter and the repeat token, if available. Option>, + /// The repeat token. This could be one of `*`, `+` or `?`. Token, ), + /// e.g. `[derive(Debug)]` Delimited(DelimToken, Vec), + /// A possible separator. e.g. `,` or `;`. Separator(String, String), + /// Other random stuff that does not fit to other kinds. + /// e.g. `== foo` in `($x: expr == foo)`. Other(String, String), } @@ -589,13 +599,21 @@ impl ParsedMacroArg { } } +/// Parses macro arguments on macro def. struct MacroArgParser { + /// Holds either a name of the next metavariable, a separator or a junk. + buf: String, + /// The start position on the current buffer. lo: BytePos, + /// The first token of the current buffer. + start_tok: Token, + /// Set to true if we are parsing a metavariable or a repeat. + is_meta_var: bool, + /// The position of the last token. hi: BytePos, - buf: String, - is_arg: bool, + /// The last token parsed. last_tok: Token, - start_tok: Token, + /// Holds the parsed arguments. result: Vec, } @@ -612,7 +630,7 @@ impl MacroArgParser { lo: BytePos(0), hi: BytePos(0), buf: String::new(), - is_arg: false, + is_meta_var: false, last_tok: Token::Eof, start_tok: Token::Eof, result: vec![], @@ -659,12 +677,70 @@ impl MacroArgParser { }); self.buf.clear(); - self.is_arg = false; + self.is_meta_var = false; } _ => unreachable!(), } } + fn add_delimited(&mut self, inner: Vec, delim: DelimToken, span: Span) { + self.result.push(ParsedMacroArg { + kind: MacroArgKind::Delimited(delim, inner), + span, + }); + } + + // $($foo: expr),? + fn add_repeat( + &mut self, + inner: Vec, + delim: DelimToken, + iter: &mut Cursor, + span: Span, + ) { + let mut buffer = String::new(); + let mut first = false; + let mut lo = span.lo(); + let mut hi = span.hi(); + + // Parse '*', '+' or '?. + while let Some(ref tok) = iter.next() { + self.set_last_tok(tok); + if first { + first = false; + lo = tok.span().lo(); + } + + match tok { + TokenTree::Token(_, Token::BinOp(BinOpToken::Plus)) + | TokenTree::Token(_, Token::Question) + | TokenTree::Token(_, Token::BinOp(BinOpToken::Star)) => { + break; + } + TokenTree::Token(sp, ref t) => { + buffer.push_str(&pprust::token_to_string(t)); + hi = sp.hi(); + } + _ => unreachable!(), + } + } + + // There could be some random stuff between ')' and '*', '+' or '?'. + let another = if buffer.trim().is_empty() { + None + } else { + Some(Box::new(ParsedMacroArg { + kind: MacroArgKind::Other(buffer, "".to_owned()), + span: mk_sp(lo, hi), + })) + }; + + self.result.push(ParsedMacroArg { + kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()), + span: mk_sp(self.lo, self.hi), + }); + } + fn update_buffer(&mut self, lo: BytePos, t: &Token) { if self.buf.is_empty() { self.lo = lo; @@ -716,15 +792,15 @@ impl MacroArgParser { } // Start keeping the name of this metavariable in the buffer. - self.is_arg = true; + self.is_meta_var = true; self.lo = sp.lo(); self.start_tok = Token::Dollar; } - TokenTree::Token(_, Token::Colon) if self.is_arg => { + TokenTree::Token(_, Token::Colon) if self.is_meta_var => { self.add_meta_variable(&mut iter); } TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t), - TokenTree::Delimited(sp, ref delimited) => { + TokenTree::Delimited(sp, delimited) => { if !self.buf.is_empty() { if next_space(&self.last_tok) == SpaceState::Always { self.add_separator(); @@ -733,59 +809,15 @@ impl MacroArgParser { } } + // Parse the stuff inside delimiters. let mut parser = MacroArgParser::new(); parser.lo = sp.lo(); - let mut delimited_arg = parser.parse(delimited.tts.clone()); - - if self.is_arg { - // Parse '*' or '+'. - let mut buffer = String::new(); - let mut first = false; - let mut lo = sp.lo(); - - while let Some(ref next_tok) = iter.next() { - self.set_last_tok(next_tok); - if first { - first = false; - lo = next_tok.span().lo(); - } - - match next_tok { - TokenTree::Token(_, Token::BinOp(BinOpToken::Plus)) - | TokenTree::Token(_, Token::Question) - | TokenTree::Token(_, Token::BinOp(BinOpToken::Star)) => { - break; - } - TokenTree::Token(_, ref t) => { - buffer.push_str(&pprust::token_to_string(t)) - } - _ => unreachable!(), - } - } + let delimited_arg = parser.parse(delimited.tts.clone()); - let another = if buffer.trim().is_empty() { - None - } else { - Some(Box::new(ParsedMacroArg { - kind: MacroArgKind::Other(buffer, "".to_owned()), - span: mk_sp(lo, self.hi), - })) - }; - - self.result.push(ParsedMacroArg { - kind: MacroArgKind::Repeat( - delimited.delim, - delimited_arg, - another, - self.last_tok.clone(), - ), - span: mk_sp(self.lo, self.hi), - }); + if self.is_meta_var { + self.add_repeat(delimited_arg, delimited.delim, &mut iter, *sp); } else { - self.result.push(ParsedMacroArg { - kind: MacroArgKind::Delimited(delimited.delim, delimited_arg), - span: *sp, - }); + self.add_delimited(delimited_arg, delimited.delim, *sp); } } } @@ -793,6 +825,8 @@ impl MacroArgParser { self.set_last_tok(tok); } + // We are left with some stuff in the buffer. Since there is nothing + // left to separate, add this as `Other`. if !self.buf.is_empty() { self.add_other(); } -- cgit 1.4.1-3-g733a5 From f8109f8e9c9a460dcb3176bd002985d8a27afc32 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 14:08:24 +0900 Subject: Put spaces around braces --- src/macros.rs | 19 ++++++++++-------- tests/source/macro_rules.rs | 20 ++++++++++++++++++ tests/target/macro_rules.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 9c7a7177ea1..e36b4c51993 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -496,7 +496,7 @@ fn delim_token_to_str( let (lhs, rhs) = match *delim_token { DelimToken::Paren => ("(", ")"), DelimToken::Bracket => ("[", "]"), - DelimToken::Brace => ("{", "}"), + DelimToken::Brace => ("{ ", " }"), DelimToken::NoDelim => ("", ""), }; if use_multiple_lines { @@ -515,6 +515,13 @@ fn delim_token_to_str( } impl MacroArgKind { + fn starts_with_brace(&self) -> bool { + match *self { + MacroArgKind::Repeat(DelimToken::Brace, _, _, _) + | MacroArgKind::Delimited(DelimToken::Brace, _) => true, + _ => false, + } + } fn starts_with_dollar(&self) -> bool { match *self { MacroArgKind::Repeat(..) | MacroArgKind::MetaVariable(..) => true, @@ -855,12 +862,7 @@ fn wrap_macro_args_inner( let indent_str = shape.indent.to_string_with_newline(context.config); while let Some(ref arg) = iter.next() { - let nested_shape = if use_multiple_lines { - shape.with_max_width(context.config) - } else { - shape - }; - result.push_str(&arg.rewrite(context, nested_shape, use_multiple_lines)?); + result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?); if use_multiple_lines && (arg.kind.ends_with_space() || iter.peek().map_or(false, |a| a.kind.has_meta_var())) @@ -872,7 +874,8 @@ fn wrap_macro_args_inner( } else if let Some(ref next_arg) = iter.peek() { let space_before_dollar = !arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar(); - if space_before_dollar { + let space_before_brace = next_arg.kind.starts_with_brace(); + if space_before_dollar || space_before_brace { result.push(' '); } } diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index 1a4d8131600..de927afc831 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -19,6 +19,26 @@ macro_rules! m { ( $ x : tt foo bar foo bar foo bar $ y : tt => x*y*z $ z : tt , $ ( $a: tt ) , * ) => {}; } + +macro_rules! impl_a_method { + ($n:ident ( $a:ident : $ta:ty ) -> $ret:ty { $body:expr }) => { + fn $n($a:$ta) -> $ret { $body } + macro_rules! $n { ($va:expr) => { $n($va) } } + }; + ($n:ident ( $a:ident : $ta:ty, $b:ident : $tb:ty ) -> $ret:ty { $body:expr }) => { + fn $n($a:$ta, $b:$tb) -> $ret { $body } + macro_rules! $n { ($va:expr, $vb:expr) => { $n($va, $vb) } } + }; + ($n:ident ( $a:ident : $ta:ty, $b:ident : $tb:ty, $c:ident : $tc:ty ) -> $ret:ty { $body:expr }) => { + fn $n($a:$ta, $b:$tb, $c:$tc) -> $ret { $body } + macro_rules! $n { ($va:expr, $vb:expr, $vc:expr) => { $n($va, $vb, $vc) } } + }; + ($n:ident ( $a:ident : $ta:ty, $b:ident : $tb:ty, $c:ident : $tc:ty, $d:ident : $td:ty ) -> $ret:ty { $body:expr }) => { + fn $n($a:$ta, $b:$tb, $c:$tc, $d:$td) -> $ret { $body } + macro_rules! $n { ($va:expr, $vb:expr, $vc:expr, $vd:expr) => { $n($va, $vb, $vc, $vd) } } + }; +} + macro_rules! m { // a ($expr :expr, $( $func : ident ) * ) => { diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index ece16399184..22fed940685 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -27,6 +27,55 @@ macro_rules! m { ($x: tt foo bar foo bar foo bar $y: tt => x * y * z $z: tt, $($a: tt),*) => {}; } +macro_rules! impl_a_method { + ($n: ident($a: ident: $ta: ty) -> $ret: ty { $body: expr }) => { + fn $n($a: $ta) -> $ret { + $body + } + macro_rules! $n { + ($va: expr) => { + $n($va) + }; + } + }; + ($n: ident($a: ident: $ta: ty, $b: ident: $tb: ty) -> $ret: ty { $body: expr }) => { + fn $n($a: $ta, $b: $tb) -> $ret { + $body + } + macro_rules! $n { + ($va: expr,$vb: expr) => { + $n($va, $vb) + }; + } + }; + ( + $n: ident($a: ident: $ta: ty, $b: ident: $tb: ty, $c: ident: $tc: ty) -> + $ret: ty { $body: expr } + ) => { + fn $n($a: $ta, $b: $tb, $c: $tc) -> $ret { + $body + } + macro_rules! $n { + ($va: expr,$vb: expr,$vc: expr) => { + $n($va, $vb, $vc) + }; + } + }; + ( + $n: ident($a: ident: $ta: ty, $b: ident: $tb: ty, $c: ident: $tc: ty, $d: ident: $td: ty) -> + $ret: ty { $body: expr } + ) => { + fn $n($a: $ta, $b: $tb, $c: $tc, $d: $td) -> $ret { + $body + } + macro_rules! $n { + ($va: expr,$vb: expr,$vc: expr,$vd: expr) => { + $n($va, $vb, $vc, $vd) + }; + } + }; +} + macro_rules! m { // a ($expr: expr, $($func: ident)*) => {{ -- cgit 1.4.1-3-g733a5 From adc257f4b3b2a9a971dfd19721d9ad97fae5d37a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Mar 2018 14:29:36 +0900 Subject: Put a space before colon that appears after a meta variable Closes #2534. --- src/macros.rs | 4 ++++ tests/source/macro_rules.rs | 6 ++++++ tests/target/macro_rules.rs | 18 ++++++++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index e36b4c51993..784e6c5798b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -522,6 +522,7 @@ impl MacroArgKind { _ => false, } } + fn starts_with_dollar(&self) -> bool { match *self { MacroArgKind::Repeat(..) | MacroArgKind::MetaVariable(..) => true, @@ -777,6 +778,9 @@ impl MacroArgParser { if ident_like(&self.start_tok) { return true; } + if self.start_tok == Token::Colon { + return true; + } } if force_space_before(&self.start_tok) { diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index de927afc831..f390b426317 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -147,6 +147,12 @@ macro foo($type_name: ident, $docs: expr) { pub struct $type_name; } +// #2534 +macro_rules! foo { + ($a:ident : $b:ty) => {}; + ($a:ident $b:ident $c:ident) => {}; +} + // #2538 macro_rules! add_message_to_notes { ($msg:expr) => {{ diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 22fed940685..793efcb6b0c 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -15,8 +15,8 @@ macro_rules! m { ) => {}; ($name: ident($($dol: tt $var: ident)*) $($body: tt)*) => {}; ( - $($i: ident: $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* - $($i: ident: $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* + $($i: ident : $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* + $($i: ident : $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* ) => {}; ($foo: tt foo[$attr: meta] $name: ident) => {}; ($foo: tt[$attr: meta] $name: ident) => {}; @@ -28,7 +28,7 @@ macro_rules! m { } macro_rules! impl_a_method { - ($n: ident($a: ident: $ta: ty) -> $ret: ty { $body: expr }) => { + ($n: ident($a: ident : $ta: ty) -> $ret: ty { $body: expr }) => { fn $n($a: $ta) -> $ret { $body } @@ -38,7 +38,7 @@ macro_rules! impl_a_method { }; } }; - ($n: ident($a: ident: $ta: ty, $b: ident: $tb: ty) -> $ret: ty { $body: expr }) => { + ($n: ident($a: ident : $ta: ty, $b: ident : $tb: ty) -> $ret: ty { $body: expr }) => { fn $n($a: $ta, $b: $tb) -> $ret { $body } @@ -49,7 +49,7 @@ macro_rules! impl_a_method { } }; ( - $n: ident($a: ident: $ta: ty, $b: ident: $tb: ty, $c: ident: $tc: ty) -> + $n: ident($a: ident : $ta: ty, $b: ident : $tb: ty, $c: ident : $tc: ty) -> $ret: ty { $body: expr } ) => { fn $n($a: $ta, $b: $tb, $c: $tc) -> $ret { @@ -62,7 +62,7 @@ macro_rules! impl_a_method { } }; ( - $n: ident($a: ident: $ta: ty, $b: ident: $tb: ty, $c: ident: $tc: ty, $d: ident: $td: ty) -> + $n: ident($a: ident : $ta: ty, $b: ident : $tb: ty, $c: ident : $tc: ty, $d: ident : $td: ty) -> $ret: ty { $body: expr } ) => { fn $n($a: $ta, $b: $tb, $c: $tc, $d: $td) -> $ret { @@ -180,6 +180,12 @@ macro foo($type_name: ident, $docs: expr) { pub struct $type_name; } +// #2534 +macro_rules! foo { + ($a: ident : $b: ty) => {}; + ($a: ident $b: ident $c: ident) => {}; +} + // #2538 macro_rules! add_message_to_notes { ($msg: expr) => {{ -- cgit 1.4.1-3-g733a5 From 164cf7d6c95d3184eb678ccb97007116e9ba7ca0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Mar 2018 16:53:06 +1300 Subject: Reorder imports by default --- src/config/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index 301b9e06b01..8af2814ec21 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -70,11 +70,11 @@ create_config! { // Ordering reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; - reorder_imports: bool, false, false, "Reorder import statements alphabetically"; - reorder_imports_in_group: bool, false, false, "Reorder import statements in group"; + reorder_imports: bool, true, false, "Reorder import statements alphabetically"; + reorder_imports_in_group: bool, true, false, "Reorder import statements in group"; reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; - reorder_modules: bool, false, false, "Reorder module statemtents alphabetically in group"; + reorder_modules: bool, true, false, "Reorder module statemtents alphabetically in group"; // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, -- cgit 1.4.1-3-g733a5 From a76d9b529a75780690aa0978471f18da81676dd4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Mar 2018 17:24:04 +1300 Subject: format code and tests --- bootstrap.sh | 5 ++--- src/bin/main.rs | 2 +- src/codemap.rs | 2 +- src/config/license.rs | 2 +- src/config/mod.rs | 4 ++-- src/config/summary.rs | 2 +- src/items.rs | 2 +- src/overflow.rs | 2 +- src/rustfmt_diff.rs | 2 +- tests/target/extern.rs | 13 +++++-------- tests/target/import-fencepost-length.rs | 2 +- tests/target/imports.rs | 8 ++++---- tests/target/skip.rs | 2 +- 13 files changed, 22 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/bootstrap.sh b/bootstrap.sh index d3878d9d61c..ae37b043c05 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -7,9 +7,8 @@ cargo build --release target/release/rustfmt --write-mode=overwrite src/lib.rs -target/release/rustfmt --write-mode=overwrite src/bin/rustfmt.rs -target/release/rustfmt --write-mode=overwrite src/bin/cargo-fmt.rs -target/release/rustfmt --write-mode=overwrite tests/system.rs +target/release/rustfmt --write-mode=overwrite src/bin/main.rs +target/release/rustfmt --write-mode=overwrite src/cargo-fmt/main.rs for filename in tests/target/*.rs; do if ! grep -q "rustfmt-" "$filename"; then diff --git a/src/bin/main.rs b/src/bin/main.rs index c89c25a90fe..914b2cee1af 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -22,9 +22,9 @@ use std::str::FromStr; use getopts::{Matches, Options}; +use rustfmt::{run, FileName, Input, Summary}; use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; use rustfmt::config::file_lines::FileLines; -use rustfmt::{run, FileName, Input, Summary}; type FmtError = Box; type FmtResult = std::result::Result; diff --git a/src/codemap.rs b/src/codemap.rs index f6c05f5be40..c5f24004fcf 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -12,8 +12,8 @@ //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. use config::file_lines::LineRange; -use visitor::SnippetProvider; use syntax::codemap::{BytePos, CodeMap, Span}; +use visitor::SnippetProvider; use comment::FindUncommented; diff --git a/src/config/license.rs b/src/config/license.rs index b2babd5ac19..d49fdbe7eba 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -1,6 +1,6 @@ -use std::io; use std::fmt; use std::fs::File; +use std::io; use std::io::Read; use regex; diff --git a/src/config/mod.rs b/src/config/mod.rs index 8af2814ec21..056cd26151f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -23,9 +23,9 @@ mod config_type; mod options; pub mod file_lines; +pub mod license; pub mod lists; pub mod summary; -pub mod license; use config::config_type::ConfigType; use config::file_lines::FileLines; @@ -69,7 +69,7 @@ create_config! { // Ordering reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; - reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; + reorder_extern_crates_in_group: bool, false, false, "Reorder extern crate statements in group"; reorder_imports: bool, true, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, true, false, "Reorder import statements in group"; reorder_imported_names: bool, true, false, diff --git a/src/config/summary.rs b/src/config/summary.rs index b0be5678a0b..99bf752f2b9 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::time::{Duration, Instant}; use std::default::Default; +use std::time::{Duration, Instant}; #[must_use] #[derive(Debug, Default, Clone, Copy)] diff --git a/src/items.rs b/src/items.rs index 6306767f00c..273e5b36d6f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -26,8 +26,8 @@ use config::{BraceStyle, Config, Density, IndentStyle}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, ExprType, RhsTactics}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use rewrite::{Rewrite, RewriteContext}; use overflow; +use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; use types::TraitTyParamBounds; diff --git a/src/overflow.rs b/src/overflow.rs index 294c257d31f..c76b67c461e 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -17,9 +17,9 @@ use syntax::codemap::Span; use closures; use codemap::SpanUtils; +use expr::{is_nested_call, maybe_get_args_offset, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; -use expr::{is_nested_call, maybe_get_args_offset, ToExpr}; use shape::Shape; use spanned::Spanned; use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp, paren_overhead}; diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index f9919157620..ca847656562 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -12,8 +12,8 @@ use config::Color; use diff; use std::collections::VecDeque; use std::io; -use term; use std::io::Write; +use term; use utils::use_colored_tty; #[derive(Debug, PartialEq)] diff --git a/tests/target/extern.rs b/tests/target/extern.rs index b0aa51127d5..61989cace75 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,17 +1,14 @@ // rustfmt-normalize_comments: true -extern crate foo; -extern crate foo as bar; - +extern crate bar; extern crate chrono; extern crate dotenv; -extern crate futures; - -extern crate bar; extern crate foo; - -// #2315 +extern crate foo; +extern crate foo as bar; +extern crate futures; extern crate proc_macro; +// #2315 extern crate proc_macro2; extern "C" { diff --git a/tests/target/import-fencepost-length.rs b/tests/target/import-fencepost-length.rs index e4f885c09b1..9d247aaf6df 100644 --- a/tests/target/import-fencepost-length.rs +++ b/tests/target/import-fencepost-length.rs @@ -1,4 +1,4 @@ -use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, ddddddddd}; +use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 2b825526199..34573b48937 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -4,11 +4,11 @@ // Imports. // Long import. -use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; -use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, - ItemB}; use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; +use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, + ItemB}; +use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; use list::{// Another item AnotherItem, // Another Comment @@ -19,9 +19,9 @@ use list::{// Another item use test::{/* A */ self /* B */, Other /* C */}; -use syntax; use {Bar /* comment */, /* Pre-comment! */ Foo}; use Foo::{Bar, Baz}; +use syntax; pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; use self; diff --git a/tests/target/skip.rs b/tests/target/skip.rs index 28897ade56f..11d1d69e91a 100644 --- a/tests/target/skip.rs +++ b/tests/target/skip.rs @@ -59,7 +59,7 @@ fn skip_on_statements() { // Item #[cfg_attr(rustfmt, rustfmt_skip)] - use foobar ; + use foobar; // Mac #[cfg_attr(rustfmt, rustfmt_skip)] -- cgit 1.4.1-3-g733a5 From 4cfffbd0a8ee33cf99a36ed133f18d2a3157dbdf Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Mar 2018 20:56:02 +1300 Subject: Reimplement import reordering. --- src/reorder.rs | 485 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 403 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index a43f56d595b..0a33177d72f 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -17,6 +17,7 @@ // TODO(#2455): Reorder trait items. use config::{Config, lists::*}; +use syntax::ast::UseTreeKind; use syntax::{ast, attr, codemap::Span}; use attr::filter_inline_attrs; @@ -31,86 +32,12 @@ use spanned::Spanned; use utils::mk_sp; use visitor::FmtVisitor; -use std::cmp::Ordering; +use std::cmp::{Ord, Ordering, PartialOrd}; -fn compare_path_segments(a: &ast::PathSegment, b: &ast::PathSegment) -> Ordering { - a.identifier.name.as_str().cmp(&b.identifier.name.as_str()) -} - -fn compare_paths(a: &ast::Path, b: &ast::Path) -> Ordering { - for segment in a.segments.iter().zip(b.segments.iter()) { - let ord = compare_path_segments(segment.0, segment.1); - if ord != Ordering::Equal { - return ord; - } - } - a.segments.len().cmp(&b.segments.len()) -} - -fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree, nested: bool) -> Ordering { - use ast::UseTreeKind::*; - - // `use_nested_groups` is not yet supported, remove the `if !nested` when support will be - // fully added - if !nested { - let paths_cmp = compare_paths(&a.prefix, &b.prefix); - if paths_cmp != Ordering::Equal { - return paths_cmp; - } - } - - match (&a.kind, &b.kind) { - (&Simple(ident_a), &Simple(ident_b)) => { - let name_a = &*path_to_imported_ident(&a.prefix).name.as_str(); - let name_b = &*path_to_imported_ident(&b.prefix).name.as_str(); - let name_ordering = if name_a == "self" { - if name_b == "self" { - Ordering::Equal - } else { - Ordering::Less - } - } else if name_b == "self" { - Ordering::Greater - } else { - name_a.cmp(name_b) - }; - if name_ordering == Ordering::Equal { - if ident_a.name.as_str() != name_a { - if ident_b.name.as_str() != name_b { - ident_a.name.as_str().cmp(&ident_b.name.as_str()) - } else { - Ordering::Greater - } - } else { - Ordering::Less - } - } else { - name_ordering - } - } - (&Glob, &Glob) => Ordering::Equal, - (&Simple(_), _) | (&Glob, &Nested(_)) => Ordering::Less, - (&Nested(ref a_items), &Nested(ref b_items)) => { - let mut a = a_items - .iter() - .map(|&(ref tree, _)| tree.clone()) - .collect::>(); - let mut b = b_items - .iter() - .map(|&(ref tree, _)| tree.clone()) - .collect::>(); - a.sort_by(|a, b| compare_use_trees(a, b, true)); - b.sort_by(|a, b| compare_use_trees(a, b, true)); - for comparison_pair in a.iter().zip(b.iter()) { - let ord = compare_use_trees(comparison_pair.0, comparison_pair.1, true); - if ord != Ordering::Equal { - return ord; - } - } - a.len().cmp(&b.len()) - } - (&Glob, &Simple(_)) | (&Nested(_), _) => Ordering::Greater, - } +fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree) -> Ordering { + let aa = UseTree::from_ast(a).normalize(); + let bb = UseTree::from_ast(b).normalize(); + aa.cmp(&bb) } /// Choose the ordering between the given two items. @@ -120,7 +47,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { a.ident.name.as_str().cmp(&b.ident.name.as_str()) } (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { - compare_use_trees(a_tree, b_tree, false) + compare_use_trees(a_tree, b_tree) } (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` @@ -149,8 +76,6 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { /// Rewrite a list of items with reordering. Every item in `items` must have /// the same `ast::ItemKind`. -// TODO (some day) remove unused imports, expand globs, compress many single -// imports into a list import. fn rewrite_reorderable_items( context: &RewriteContext, reorderable_items: &[&ast::Item], @@ -329,3 +254,399 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } } + +// Ordering of imports + +// We order imports by translating to our own representation and then sorting. +// The Rust AST data structures are really bad for this. Rustfmt applies a bunch +// of normalisations to imports and since we want to sort based on the result +// of these (and to maintain idempotence) we must apply the same normalisations +// to the data structures for sorting. +// +// We sort `self` and `super` before other imports, then identifier imports, +// then glob imports, then lists of imports. We do not take aliases into account +// when ordering unless the imports are identical except for the alias (rare in +// practice). + +// FIXME(#2531) - we should unify the comparison code here with the formatting +// code elsewhere since we are essentially string-ifying twice. Furthermore, by +// parsing to our own format on comparison, we repeat a lot of work when +// sorting. + +// FIXME we do a lot of allocation to make our own representation. +#[derive(Debug, Clone, Eq, PartialEq)] +enum UseSegment { + Ident(String, Option), + Slf(Option), + Super(Option), + Glob, + List(Vec), +} + +#[derive(Debug, Clone, Eq, PartialEq)] +struct UseTree { + path: Vec, +} + +impl UseSegment { + // Clone a version of self with any top-level alias removed. + fn remove_alias(&self) -> UseSegment { + match *self { + UseSegment::Ident(ref s, _) => UseSegment::Ident(s.clone(), None), + UseSegment::Slf(_) => UseSegment::Slf(None), + UseSegment::Super(_) => UseSegment::Super(None), + _ => self.clone(), + } + } +} + +impl UseTree { + fn from_ast(a: &ast::UseTree) -> UseTree { + let mut result = UseTree { path: vec![] }; + for p in &a.prefix.segments { + result.path.push(UseSegment::Ident( + (*p.identifier.name.as_str()).to_owned(), + None, + )); + } + match a.kind { + UseTreeKind::Glob => { + result.path.push(UseSegment::Glob); + } + UseTreeKind::Nested(ref list) => { + result.path.push(UseSegment::List( + list.iter().map(|t| Self::from_ast(&t.0)).collect(), + )); + } + UseTreeKind::Simple(ref rename) => { + let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); + let alias = if &name == &*rename.name.as_str() { + None + } else { + Some((&*rename.name.as_str()).to_owned()) + }; + + let segment = if &name == "self" { + UseSegment::Slf(alias) + } else if &name == "super" { + UseSegment::Super(alias) + } else { + UseSegment::Ident(name, alias) + }; + + // `name` is already in result. + result.path.pop(); + result.path.push(segment); + } + } + result + } + + // Do the adjustments that rustfmt does elsewhere to use paths. + fn normalize(mut self) -> UseTree { + let mut last = self.path.pop().expect("Empty use tree?"); + // Hack around borrow checker. + let mut normalize_sole_list = false; + let mut aliased_self = false; + + // Normalise foo::self -> foo. + if let UseSegment::Slf(None) = last { + return self; + } + + // Normalise foo::self as bar -> foo as bar. + if let UseSegment::Slf(_) = last { + match self.path.last() { + None => {} + Some(UseSegment::Ident(_, None)) => { + aliased_self = true; + } + _ => unreachable!(), + } + } + + if aliased_self { + match self.path.last() { + Some(UseSegment::Ident(_, ref mut old_rename)) => { + assert!(old_rename.is_none()); + if let UseSegment::Slf(Some(rename)) = last { + *old_rename = Some(rename); + return self; + } + } + _ => unreachable!(), + } + } + + // Normalise foo::{bar} -> foo::bar + if let UseSegment::List(ref list) = last { + if list.len() == 1 && list[0].path.len() == 1 { + normalize_sole_list = true; + } + } + + if normalize_sole_list { + match last { + UseSegment::List(list) => { + self.path.push(list[0].path[0].clone()); + return self.normalize(); + } + _ => unreachable!(), + } + } + + // Recursively normalize elements of a list use (including sorting the list). + if let UseSegment::List(list) = last { + let mut list: Vec<_> = list.into_iter().map(|ut| ut.normalize()).collect(); + list.sort(); + last = UseSegment::List(list); + } + + self.path.push(last); + self + } +} + +impl PartialOrd for UseSegment { + fn partial_cmp(&self, other: &UseSegment) -> Option { + Some(self.cmp(other)) + } +} +impl PartialOrd for UseTree { + fn partial_cmp(&self, other: &UseTree) -> Option { + Some(self.cmp(other)) + } +} +impl Ord for UseSegment { + fn cmp(&self, other: &UseSegment) -> Ordering { + use self::UseSegment::*; + + match (self, other) { + (&Slf(ref a), &Slf(ref b)) | (&Super(ref a), &Super(ref b)) => a.cmp(b), + (&Glob, &Glob) => Ordering::Equal, + (&Ident(ref ia, ref aa), &Ident(ref ib, ref ab)) => { + let ident_ord = ia.cmp(ib); + if ident_ord != Ordering::Equal { + return ident_ord; + } + if aa.is_none() && ab.is_some() { + return Ordering::Less; + } + if aa.is_some() && ab.is_none() { + return Ordering::Greater; + } + aa.cmp(ab) + } + (&List(ref a), &List(ref b)) => { + for (a, b) in a.iter().zip(b.iter()) { + let ord = a.cmp(b); + if ord != Ordering::Equal { + return ord; + } + } + + a.len().cmp(&b.len()) + } + (&Slf(_), _) => Ordering::Less, + (_, &Slf(_)) => Ordering::Greater, + (&Super(_), _) => Ordering::Less, + (_, &Super(_)) => Ordering::Greater, + (&Ident(..), _) => Ordering::Less, + (_, &Ident(..)) => Ordering::Greater, + (&Glob, _) => Ordering::Less, + (_, &Glob) => Ordering::Greater, + } + } +} +impl Ord for UseTree { + fn cmp(&self, other: &UseTree) -> Ordering { + for (a, b) in self.path.iter().zip(other.path.iter()) { + let ord = a.cmp(b); + // The comparison without aliases is a hack to avoid situations like + // comparing `a::b` to `a as c` - where the latter should be ordered + // first since it is shorter. + if ord != Ordering::Equal && a.remove_alias().cmp(&b.remove_alias()) != Ordering::Equal + { + return ord; + } + } + + self.path.len().cmp(&other.path.len()) + } +} + +#[cfg(test)] +mod test { + use super::*; + + // Parse the path part of an import. This parser is not robust and is only + // suitable for use in a test harness. + fn parse_use_tree(s: &str) -> UseTree { + use std::iter::Peekable; + use std::mem::swap; + use std::str::Chars; + + struct Parser<'a> { + input: Peekable>, + } + + impl<'a> Parser<'a> { + fn bump(&mut self) { + self.input.next().unwrap(); + } + fn eat(&mut self, c: char) { + assert!(self.input.next().unwrap() == c); + } + fn push_segment( + result: &mut Vec, + buf: &mut String, + alias_buf: &mut Option, + ) { + if !buf.is_empty() { + let mut alias = None; + swap(alias_buf, &mut alias); + if buf == "self" { + result.push(UseSegment::Slf(alias)); + *buf = String::new(); + *alias_buf = None; + } else if buf == "super" { + result.push(UseSegment::Super(alias)); + *buf = String::new(); + *alias_buf = None; + } else { + let mut name = String::new(); + swap(buf, &mut name); + result.push(UseSegment::Ident(name, alias)); + } + } + } + fn parse_in_list(&mut self) -> UseTree { + let mut result = vec![]; + let mut buf = String::new(); + let mut alias_buf = None; + while let Some(&c) = self.input.peek() { + match c { + '{' => { + assert!(buf.is_empty()); + self.bump(); + result.push(UseSegment::List(self.parse_list())); + self.eat('}'); + } + '*' => { + assert!(buf.is_empty()); + self.bump(); + result.push(UseSegment::Glob); + } + ':' => { + self.bump(); + self.eat(':'); + Self::push_segment(&mut result, &mut buf, &mut alias_buf); + } + '}' | ',' => { + Self::push_segment(&mut result, &mut buf, &mut alias_buf); + return UseTree { path: result }; + } + ' ' => { + self.bump(); + self.eat('a'); + self.eat('s'); + self.eat(' '); + alias_buf = Some(String::new()); + } + c => { + self.bump(); + if let Some(ref mut buf) = alias_buf { + buf.push(c); + } else { + buf.push(c); + } + } + } + } + Self::push_segment(&mut result, &mut buf, &mut alias_buf); + UseTree { path: result } + } + + fn parse_list(&mut self) -> Vec { + let mut result = vec![]; + loop { + match self.input.peek().unwrap() { + ',' | ' ' => self.bump(), + '}' => { + return result; + } + _ => result.push(self.parse_in_list()), + } + } + } + } + + let mut parser = Parser { + input: s.chars().peekable(), + }; + parser.parse_in_list() + } + + #[test] + fn test_use_tree_normalize() { + assert_eq!(parse_use_tree("a::self").normalize(), parse_use_tree("a")); + assert_eq!( + parse_use_tree("a::self as foo").normalize(), + parse_use_tree("a as foo") + ); + assert_eq!(parse_use_tree("a::{self}").normalize(), parse_use_tree("a")); + assert_eq!(parse_use_tree("a::{b}").normalize(), parse_use_tree("a::b")); + assert_eq!( + parse_use_tree("a::{b, c::self}").normalize(), + parse_use_tree("a::{b, c}") + ); + assert_eq!( + parse_use_tree("a::{b as bar, c::self}").normalize(), + parse_use_tree("a::{b as bar, c}") + ); + } + + #[test] + fn test_use_tree_ord() { + assert!(parse_use_tree("a").normalize() < parse_use_tree("aa").normalize()); + assert!(parse_use_tree("a").normalize() < parse_use_tree("a::a").normalize()); + assert!(parse_use_tree("a").normalize() < parse_use_tree("*").normalize()); + assert!(parse_use_tree("a").normalize() < parse_use_tree("{a, b}").normalize()); + assert!(parse_use_tree("*").normalize() < parse_use_tree("{a, b}").normalize()); + + assert!( + parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, dddddddd}").normalize() + < parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, ddddddddd}").normalize() + ); + assert!( + parse_use_tree("serde::de::{Deserialize}").normalize() + < parse_use_tree("serde_json").normalize() + ); + assert!(parse_use_tree("a::b::c").normalize() < parse_use_tree("a::b::*").normalize()); + assert!( + parse_use_tree("foo::{Bar, Baz}").normalize() + < parse_use_tree("{Bar, Baz}").normalize() + ); + + assert!( + parse_use_tree("foo::{self as bar}").normalize() + < parse_use_tree("foo::{qux as bar}").normalize() + ); + assert!( + parse_use_tree("foo::{qux as bar}").normalize() + < parse_use_tree("foo::{baz, qux as bar}").normalize() + ); + assert!( + parse_use_tree("foo::{self as bar, baz}").normalize() + < parse_use_tree("foo::{baz, qux as bar}").normalize() + ); + + assert!(parse_use_tree("Foo").normalize() < parse_use_tree("foo").normalize()); + assert!(parse_use_tree("foo").normalize() < parse_use_tree("foo::Bar").normalize()); + + assert!( + parse_use_tree("std::cmp::{d, c, b, a}").normalize() + < parse_use_tree("std::cmp::{b, e, g, f}").normalize() + ); + } +} -- cgit 1.4.1-3-g733a5 From 50c95a074a051f9ea2e9a474289a41081bdf4e0f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 14 Mar 2018 20:43:01 +1300 Subject: cargo fmt --- Configurations.md | 9 ++++----- src/bin/main.rs | 6 +++--- src/chains.rs | 2 +- src/closures.rs | 2 +- src/config/file_lines.rs | 2 +- src/config/mod.rs | 2 +- src/expr.rs | 2 +- src/format-diff/main.rs | 2 +- src/items.rs | 2 +- src/lib.rs | 6 +++--- src/macros.rs | 2 +- src/rustfmt_diff.rs | 2 +- src/utils.rs | 2 +- src/visitor.rs | 2 +- tests/target/imports.rs | 9 +++++---- 15 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 2b9cd13ad33..975cb890ed7 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1300,13 +1300,12 @@ Reorder import statements in group #### `false` (default): ```rust -use std::mem; -use std::io; - -use lorem; -use ipsum; use dolor; +use ipsum; +use lorem; use sit; +use std::io; +use std::mem; ``` #### `true`: diff --git a/src/bin/main.rs b/src/bin/main.rs index 914b2cee1af..b59e47930e0 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -14,17 +14,17 @@ extern crate env_logger; extern crate getopts; extern crate rustfmt_nightly as rustfmt; -use std::{env, error}; use std::fs::File; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; +use std::{env, error}; use getopts::{Matches, Options}; -use rustfmt::{run, FileName, Input, Summary}; -use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; use rustfmt::config::file_lines::FileLines; +use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; +use rustfmt::{run, FileName, Input, Summary}; type FmtError = Box; type FmtResult = std::result::Result; diff --git a/src/chains.rs b/src/chains.rs index e26f4966628..d798981415e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -77,8 +77,8 @@ use std::borrow::Cow; use std::cmp::min; use std::iter; -use syntax::{ast, ptr}; use syntax::codemap::Span; +use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { debug!("rewrite_chain {:?}", shape); diff --git a/src/closures.rs b/src/closures.rs index 65052d766eb..2ec31afa391 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -9,9 +9,9 @@ // except according to those terms. use config::lists::*; -use syntax::{ast, ptr}; use syntax::codemap::Span; use syntax::parse::classify; +use syntax::{ast, ptr}; use codemap::SpanUtils; use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 714f33c03dc..cf3f827c00d 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -10,9 +10,9 @@ //! This module contains types and functions to support formatting specific line ranges. -use std::{cmp, iter, str}; use std::collections::HashMap; use std::rc::Rc; +use std::{cmp, iter, str}; use serde::de::{Deserialize, Deserializer}; use serde_json as json; diff --git a/src/config/mod.rs b/src/config/mod.rs index 056cd26151f..b28592e613b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{env, fs}; use std::cell::Cell; use std::default::Default; use std::fs::File; use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; +use std::{env, fs}; use regex::Regex; diff --git a/src/expr.rs b/src/expr.rs index e144c8307b6..d364da20128 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -13,8 +13,8 @@ use std::cmp::min; use std::iter::repeat; use config::lists::*; -use syntax::{ast, ptr}; use syntax::codemap::{BytePos, CodeMap, Span}; +use syntax::{ast, ptr}; use chains::rewrite_chain; use closures; diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 6633da208e8..c871395f72a 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -23,10 +23,10 @@ extern crate regex; extern crate serde_derive; extern crate serde_json as json; -use std::{env, fmt, process}; use std::collections::HashSet; use std::error::Error; use std::io::{self, BufRead}; +use std::{env, fmt, process}; use regex::Regex; diff --git a/src/items.rs b/src/items.rs index 273e5b36d6f..2e0e869d12a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,9 +15,9 @@ use std::cmp::min; use config::lists::*; use regex::Regex; -use syntax::{abi, ast, ptr, symbol}; use syntax::codemap::{self, BytePos, Span}; use syntax::visit; +use syntax::{abi, ast, ptr, symbol}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, diff --git a/src/lib.rs b/src/lib.rs index eff414b5708..c080f1396cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,11 +38,11 @@ use std::path::PathBuf; use std::rc::Rc; use std::time::Duration; -use syntax::errors::{DiagnosticBuilder, Handler}; -use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::ast; -use syntax::codemap::{CodeMap, FilePathMapping}; pub use syntax::codemap::FileName; +use syntax::codemap::{CodeMap, FilePathMapping}; +use syntax::errors::{DiagnosticBuilder, Handler}; +use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; diff --git a/src/macros.rs b/src/macros.rs index 784e6c5798b..ec1ca29d173 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,7 +22,6 @@ use std::collections::HashMap; use config::lists::*; -use syntax::{ast, ptr}; use syntax::codemap::{BytePos, Span}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; @@ -31,6 +30,7 @@ use syntax::print::pprust; use syntax::symbol; use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::util::ThinVec; +use syntax::{ast, ptr}; use codemap::SpanUtils; use comment::{contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index ca847656562..db72a775f41 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -211,8 +211,8 @@ where #[cfg(test)] mod test { - use super::{make_diff, Mismatch}; use super::DiffLine::*; + use super::{make_diff, Mismatch}; #[test] fn diff_simple() { diff --git a/src/utils.rs b/src/utils.rs index f6d2ff23c34..d1d526efe36 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,10 +10,10 @@ use std::borrow::Cow; -use syntax::{abi, ptr}; use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, Visibility, VisibilityKind}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; +use syntax::{abi, ptr}; use config::Color; use rewrite::RewriteContext; diff --git a/src/visitor.rs b/src/visitor.rs index 81f35d787ab..54a85062d43 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::{ast, visit}; use syntax::attr::HasAttrs; use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; use syntax::parse::ParseSess; +use syntax::{ast, visit}; use attr::*; use codemap::{LineRangeUtils, SpanUtils}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 34573b48937..5845669e868 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -43,21 +43,21 @@ fn test() { } // Simple imports -use foo::bar::baz; use bar::quux as kaas; use foo; +use foo::bar::baz; // With aliases. -use foo::{self as bar, baz}; use foo as bar; use foo::qux as bar; +use foo::{self as bar, baz}; use foo::{baz, qux as bar}; // With absolute paths use foo; +use Foo; use foo::Bar; use foo::{Bar, Baz}; -use Foo; use {Bar, Baz}; // Root globs @@ -83,6 +83,7 @@ use fooo::{bar, x, y, z, bar::*}; // nested imports with a single sub-tree. -use a::b::c::*; use a::b::c::d; +use a::b::c::*; + use a::b::c::{xxx, yyy, zzz}; -- cgit 1.4.1-3-g733a5 From 0cf80dcce7dd4ed0e82b3c7c0adeae433c3063fc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 16 Mar 2018 08:18:56 +1300 Subject: Better handle comments and newlines around erased imports --- src/lists.rs | 57 ++++++++++++++++++++++++++++++++----------------- src/missed_spans.rs | 35 +++++++++++++++++++++++------- src/reorder.rs | 1 + tests/target/imports.rs | 1 - 4 files changed, 66 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 49797a785bb..fdb022db077 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -56,7 +56,7 @@ impl AsRef for ListItem { } } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Debug)] pub enum ListItemCommentStyle { // Try to keep the comment on the same line with the item. SameLine, @@ -66,6 +66,7 @@ pub enum ListItemCommentStyle { None, } +#[derive(Debug)] pub struct ListItem { // None for comments mean that they are not present. pub pre_comment: Option, @@ -118,6 +119,18 @@ impl ListItem { new_lines: false, } } + + // true if the item causes something to be written. + fn is_substantial(&self) -> bool { + fn empty(s: &Option) -> bool { + match *s { + Some(ref s) if !s.is_empty() => false, + _ => true, + } + } + + !(empty(&self.pre_comment) && empty(&self.item) && empty(&self.post_comment)) + } } /// The type of separator for lists. @@ -220,6 +233,10 @@ where item_last_line_width -= indent_str.len(); } + if !item.is_substantial() { + continue; + } + match tactic { DefinitiveListTactic::Horizontal if !first => { result.push(' '); @@ -276,26 +293,28 @@ where rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; result.push_str(&comment); - if tactic == DefinitiveListTactic::Vertical { - // We cannot keep pre-comments on the same line if the comment if normalized. - let keep_comment = if formatting.config.normalize_comments() - || item.pre_comment_style == ListItemCommentStyle::DifferentLine - { - false + if !inner_item.is_empty() { + if tactic == DefinitiveListTactic::Vertical { + // We cannot keep pre-comments on the same line if the comment if normalized. + let keep_comment = if formatting.config.normalize_comments() + || item.pre_comment_style == ListItemCommentStyle::DifferentLine + { + false + } else { + // We will try to keep the comment on the same line with the item here. + // 1 = ` ` + let total_width = total_item_width(item) + item_sep_len + 1; + total_width <= formatting.shape.width + }; + if keep_comment { + result.push(' '); + } else { + result.push('\n'); + result.push_str(indent_str); + } } else { - // We will try to keep the comment on the same line with the item here. - // 1 = ` ` - let total_width = total_item_width(item) + item_sep_len + 1; - total_width <= formatting.shape.width - }; - if keep_comment { result.push(' '); - } else { - result.push('\n'); - result.push_str(indent_str); } - } else { - result.push(' '); } item_max_width = None; } @@ -304,7 +323,7 @@ where result.push_str(formatting.separator.trim()); result.push(' '); } - result.push_str(&inner_item[..]); + result.push_str(inner_item); // Post-comments if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index dff6b94bd75..f5794c65c4c 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -104,19 +104,38 @@ impl<'a> FmtVisitor<'a> { } fn push_vertical_spaces(&mut self, mut newline_count: usize) { - // The buffer already has a trailing newline. - let offset = if self.buffer.ends_with('\n') { 0 } else { 1 }; - let newline_upper_bound = self.config.blank_lines_upper_bound() + offset; - let newline_lower_bound = self.config.blank_lines_lower_bound() + offset; - if newline_count > newline_upper_bound { - newline_count = newline_upper_bound; - } else if newline_count < newline_lower_bound { - newline_count = newline_lower_bound; + let offset = self.count_trailing_newlines(); + let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; + let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; + + if newline_count + offset > newline_upper_bound { + if offset >= newline_upper_bound { + newline_count = 0; + } else { + newline_count = newline_upper_bound - offset; + } + } else if newline_count + offset < newline_lower_bound { + if offset >= newline_lower_bound { + newline_count = 0; + } else { + newline_count = newline_lower_bound - offset; + } } + let blank_lines: String = repeat('\n').take(newline_count).collect(); self.push_str(&blank_lines); } + fn count_trailing_newlines(&self) -> usize { + let mut buf = &*self.buffer; + let mut result = 0; + while buf.ends_with('\n') { + buf = &buf[..buf.len() - 1]; + result += 1; + } + result + } + fn write_snippet(&mut self, span: Span, process_last_snippet: F) where F: Fn(&mut FmtVisitor, &str, &str), diff --git a/src/reorder.rs b/src/reorder.rs index 0a33177d72f..5595fa5b237 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -121,6 +121,7 @@ fn rewrite_reorderable_items( span.hi(), false, ); + let mut item_pair_vec: Vec<_> = items.zip(reorderable_items.iter()).collect(); item_pair_vec.sort_by(|a, b| compare_items(a.1, b.1)); let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 86dbfc08020..af5f1ee7bcf 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -85,5 +85,4 @@ use fooo::{bar, x, y, z, // nested imports with a single sub-tree. use a::b::c::d; use a::b::c::*; - use a::b::c::{xxx, yyy, zzz}; -- cgit 1.4.1-3-g733a5 From bf9f17533636f580de9b5971d17d3d5fa6d2bc16 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 16 Mar 2018 20:57:35 +1300 Subject: reviewer comments and rebase fallout --- Configurations.md | 27 ++++++++++++++------------- src/lib.rs | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 975cb890ed7..f7fa88b61f2 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1297,27 +1297,28 @@ Reorder import statements in group **Note:** This option takes effect only when [`reorder_imports`](#reorder_imports) is set to `true`. -#### `false` (default): +#### `true` (default): ```rust +use std::io; +use std::mem; + use dolor; use ipsum; use lorem; use sit; -use std::io; -use std::mem; ``` -#### `true`: +#### `false`: -```rust -use std::io; -use std::mem; +```rust use dolor; use ipsum; use lorem; use sit; +use std::io; +use std::mem; ``` See also [`reorder_imports`](#reorder_imports). @@ -1359,7 +1360,11 @@ Reorder `extern crate` statements in group - **Possible values**: `true`, `false` - **Stable**: No -#### `true` (default): +#### `false` (default): + +This value has no influence beyond the effect of the [`reorder_extern_crates`](#reorder_extern_crates) option. Set [`reorder_extern_crates`](#reorder_extern_crates) to `false` if you do not want `extern crate` groups to be collapsed and ordered. + +#### `true`: **Note:** This only takes effect when [`reorder_extern_crates`](#reorder_extern_crates) is set to `true`. @@ -1373,10 +1378,6 @@ extern crate lorem; extern crate sit; ``` -#### `false`: - -This value has no influence beyond the effect of the [`reorder_extern_crates`](#reorder_extern_crates) option. Set [`reorder_extern_crates`](#reorder_extern_crates) to `false` if you do not want `extern crate` groups to be collapsed and ordered. - ## `reorder_modules` Reorder `mod` declarations alphabetically in group. @@ -1385,7 +1386,7 @@ Reorder `mod` declarations alphabetically in group. - **Possible values**: `true`, `false` - **Stable**: No -#### `true` +#### `true` (default) ```rust mod a; diff --git a/src/lib.rs b/src/lib.rs index c080f1396cb..4fdb7d0f47d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,8 @@ use std::time::Duration; use syntax::ast; pub use syntax::codemap::FileName; use syntax::codemap::{CodeMap, FilePathMapping}; -use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; -- cgit 1.4.1-3-g733a5 From 3a138a24a32d382670dfe55f744f902c9e1e2658 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 20 Mar 2018 09:54:00 +1300 Subject: Return grouping `extern crate` to true by default --- src/config/mod.rs | 2 +- tests/target/extern.rs | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index b28592e613b..5d5e91ebaed 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -69,7 +69,7 @@ create_config! { // Ordering reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; - reorder_extern_crates_in_group: bool, false, false, "Reorder extern crate statements in group"; + reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; reorder_imports: bool, true, false, "Reorder import statements alphabetically"; reorder_imports_in_group: bool, true, false, "Reorder import statements in group"; reorder_imported_names: bool, true, false, diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 61989cace75..b0aa51127d5 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,14 +1,17 @@ // rustfmt-normalize_comments: true -extern crate bar; -extern crate chrono; -extern crate dotenv; -extern crate foo; extern crate foo; extern crate foo as bar; + +extern crate chrono; +extern crate dotenv; extern crate futures; -extern crate proc_macro; + +extern crate bar; +extern crate foo; + // #2315 +extern crate proc_macro; extern crate proc_macro2; extern "C" { -- cgit 1.4.1-3-g733a5 From 88589f2ad891f115e44cab2f37993885c82c40d8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 21 Mar 2018 22:02:18 +0900 Subject: Add matches module `matches` module contains `rewrite_match` and related stuffs. --- src/expr.rs | 551 +------------------------------------------------------- src/lib.rs | 1 + src/matches.rs | 531 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/patterns.rs | 34 ++++ 4 files changed, 573 insertions(+), 544 deletions(-) create mode 100644 src/matches.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e144c8307b6..e6cd6ee046f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -10,7 +10,6 @@ use std::borrow::Cow; use std::cmp::min; -use std::iter::repeat; use config::lists::*; use syntax::{ast, ptr}; @@ -25,17 +24,17 @@ use config::{Config, ControlBraceStyle, IndentStyle}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; use macros::{rewrite_macro, MacroArg, MacroPosition}; +use matches::rewrite_match; use overflow; -use patterns::{can_be_overflowed_pat, TuplePatField}; +use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; -use utils::{colon_spaces, contains_skip, count_newlines, extra_offset, first_line_width, - inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, - paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, - wrap_str}; +use utils::{colon_spaces, contains_skip, count_newlines, first_line_width, inner_attributes, + last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead, + ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -566,19 +565,6 @@ fn array_tactic( } } -fn nop_block_collapse(block_str: Option, budget: usize) -> Option { - debug!("nop_block_collapse {:?} {}", block_str, budget); - block_str.map(|block_str| { - if block_str.starts_with('{') && budget >= 2 - && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) - { - "{}".to_owned() - } else { - block_str.to_owned() - } - }) -} - fn rewrite_empty_block( context: &RewriteContext, block: &ast::Block, @@ -1320,503 +1306,7 @@ pub fn is_unsafe_block(block: &ast::Block) -> bool { } } -/// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. -struct ArmWrapper<'a> { - pub arm: &'a ast::Arm, - /// True if the arm is the last one in match expression. Used to decide on whether we should add - /// trailing comma to the match arm when `config.trailing_comma() == Never`. - pub is_last: bool, - /// Holds a byte position of `|` at the beginning of the arm pattern, if available. - pub beginning_vert: Option, -} - -impl<'a> ArmWrapper<'a> { - pub fn new( - arm: &'a ast::Arm, - is_last: bool, - beginning_vert: Option, - ) -> ArmWrapper<'a> { - ArmWrapper { - arm, - is_last, - beginning_vert, - } - } -} - -impl<'a> Spanned for ArmWrapper<'a> { - fn span(&self) -> Span { - if let Some(lo) = self.beginning_vert { - mk_sp(lo, self.arm.span().hi()) - } else { - self.arm.span() - } - } -} - -impl<'a> Rewrite for ArmWrapper<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last, self.beginning_vert) - } -} - -fn rewrite_match( - context: &RewriteContext, - cond: &ast::Expr, - arms: &[ast::Arm], - shape: Shape, - span: Span, - attrs: &[ast::Attribute], -) -> Option { - // Do not take the rhs overhead from the upper expressions into account - // when rewriting match condition. - let cond_shape = Shape { - width: context.budget(shape.used_width()), - ..shape - }; - // 6 = `match ` - let cond_shape = match context.config.indent_style() { - IndentStyle::Visual => cond_shape.shrink_left(6)?, - IndentStyle::Block => cond_shape.offset_left(6)?, - }; - let cond_str = cond.rewrite(context, cond_shape)?; - let alt_block_sep = &shape.indent.to_string_with_newline(context.config); - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => alt_block_sep, - _ if last_line_extendable(&cond_str) => " ", - // 2 = ` {` - _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => alt_block_sep, - _ => " ", - }; - - let nested_indent_str = shape - .indent - .block_indent(context.config) - .to_string(context.config); - // Inner attributes. - let inner_attrs = &inner_attributes(attrs); - let inner_attrs_str = if inner_attrs.is_empty() { - String::new() - } else { - inner_attrs - .rewrite(context, shape) - .map(|s| format!("{}{}\n", nested_indent_str, s))? - }; - - let open_brace_pos = if inner_attrs.is_empty() { - let hi = if arms.is_empty() { - span.hi() - } else { - arms[0].span().lo() - }; - context - .snippet_provider - .span_after(mk_sp(cond.span.hi(), hi), "{") - } else { - inner_attrs[inner_attrs.len() - 1].span().hi() - }; - - if arms.is_empty() { - let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); - if snippet.trim().is_empty() { - Some(format!("match {} {{}}", cond_str)) - } else { - // Empty match with comments or inner attributes? We are not going to bother, sorry ;) - Some(context.snippet(span).to_owned()) - } - } else { - Some(format!( - "match {}{}{{\n{}{}{}\n{}}}", - cond_str, - block_sep, - inner_attrs_str, - nested_indent_str, - rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, - shape.indent.to_string(context.config), - )) - } -} - -fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { - if is_last && config.trailing_comma() == SeparatorTactic::Never { - "" - } else if config.match_block_trailing_comma() { - "," - } else if let ast::ExprKind::Block(ref block) = body.node { - if let ast::BlockCheckMode::Default = block.rules { - "" - } else { - "," - } - } else { - "," - } -} - -/// Collect a byte position of the beginning `|` for each arm, if available. -fn collect_beginning_verts( - context: &RewriteContext, - arms: &[ast::Arm], - span: Span, -) -> Vec> { - let mut beginning_verts = Vec::with_capacity(arms.len()); - let mut lo = context.snippet_provider.span_after(span, "{"); - for arm in arms { - let hi = arm.pats[0].span.lo(); - let missing_span = mk_sp(lo, hi); - beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); - lo = arm.span().hi(); - } - beginning_verts -} - -fn rewrite_match_arms( - context: &RewriteContext, - arms: &[ast::Arm], - shape: Shape, - span: Span, - open_brace_pos: BytePos, -) -> Option { - let arm_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - - let arm_len = arms.len(); - let is_last_iter = repeat(false) - .take(arm_len.checked_sub(1).unwrap_or(0)) - .chain(repeat(true)); - let beginning_verts = collect_beginning_verts(context, arms, span); - let items = itemize_list( - context.snippet_provider, - arms.iter() - .zip(is_last_iter) - .zip(beginning_verts.into_iter()) - .map(|((arm, is_last), beginning_vert)| ArmWrapper::new(arm, is_last, beginning_vert)), - "}", - "|", - |arm| arm.span().lo(), - |arm| arm.span().hi(), - |arm| arm.rewrite(context, arm_shape), - open_brace_pos, - span.hi(), - false, - ); - let arms_vec: Vec<_> = items.collect(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - config: context.config, - }; - - write_list(&arms_vec, &fmt) -} - -fn rewrite_match_arm( - context: &RewriteContext, - arm: &ast::Arm, - shape: Shape, - is_last: bool, - beginning_vert: Option, -) -> Option { - let (missing_span, attrs_str) = if !arm.attrs.is_empty() { - if contains_skip(&arm.attrs) { - let (_, body) = flatten_arm_body(context, &arm.body); - // `arm.span()` does not include trailing comma, add it manually. - return Some(format!( - "{}{}", - context.snippet(arm.span()), - arm_comma(context.config, body, is_last), - )); - } - let missing_span = mk_sp( - arm.attrs[arm.attrs.len() - 1].span.hi(), - arm.pats[0].span.lo(), - ); - (missing_span, arm.attrs.rewrite(context, shape)?) - } else { - (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) - }; - let pats_str = rewrite_match_pattern( - context, - &ptr_vec_to_ref_vec(&arm.pats), - &arm.guard, - beginning_vert.is_some(), - shape, - ).and_then(|pats_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &pats_str, - missing_span, - shape, - false, - ) - })?; - rewrite_match_body( - context, - &arm.body, - &pats_str, - shape, - arm.guard.is_some(), - is_last, - ) -} - -/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: -/// -/// [small, ntp]: -/// - single token -/// - `&[single-line, ntp]` -/// -/// [small]: -/// - `[small, ntp]` -/// - unary tuple constructor `([small, ntp])` -/// - `&[small]` -fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { - // We also require that the pattern is reasonably 'small' with its literal width. - pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) -} - -fn is_short_pattern_inner(pat: &ast::Pat) -> bool { - match pat.node { - ast::PatKind::Wild | ast::PatKind::Lit(_) => true, - ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), - ast::PatKind::Struct(..) - | ast::PatKind::Mac(..) - | ast::PatKind::Slice(..) - | ast::PatKind::Path(..) - | ast::PatKind::Range(..) => false, - ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, - ast::PatKind::TupleStruct(ref path, ref subpats, _) => { - path.segments.len() <= 1 && subpats.len() <= 1 - } - ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => { - is_short_pattern_inner(&*p) - } - } -} - -fn rewrite_match_pattern( - context: &RewriteContext, - pats: &[&ast::Pat], - guard: &Option>, - has_beginning_vert: bool, - shape: Shape, -) -> Option { - // Patterns - // 5 = ` => {` - // 2 = `| ` - let pat_shape = shape - .sub_width(5)? - .offset_left(if has_beginning_vert { 2 } else { 0 })?; - let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?; - let beginning_vert = if has_beginning_vert { "| " } else { "" }; - - // Guard - let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; - - Some(format!("{}{}{}", beginning_vert, pats_str, guard_str)) -} - -// (extend, body) -// @extend: true if the arm body can be put next to `=>` -// @body: flattened body, if the body is block with a single expression -fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { - match body.node { - ast::ExprKind::Block(ref block) - if !is_unsafe_block(block) - && is_simple_block(block, Some(&body.attrs), context.codemap) => - { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - ( - !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), - &*expr, - ) - } else { - (false, &*body) - } - } - _ => ( - !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), - &*body, - ), - } -} - -fn rewrite_match_body( - context: &RewriteContext, - body: &ptr::P, - pats_str: &str, - shape: Shape, - has_guard: bool, - is_last: bool, -) -> Option { - let (extend, body) = flatten_arm_body(context, body); - let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { - ( - true, - is_empty_block(block, Some(&body.attrs), context.codemap), - ) - } else { - (false, false) - }; - - let comma = arm_comma(context.config, body, is_last); - let alt_block_sep = &shape.indent.to_string_with_newline(context.config); - - let combine_orig_body = |body_str: &str| { - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, - _ => " ", - }; - - Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) - }; - - let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; - let next_line_indent = if !is_block || is_empty_block { - shape.indent.block_indent(context.config) - } else { - shape.indent - }; - let combine_next_line_body = |body_str: &str| { - if is_block { - return Some(format!( - "{} =>{}{}", - pats_str, - next_line_indent.to_string_with_newline(context.config), - body_str - )); - } - - let indent_str = shape.indent.to_string_with_newline(context.config); - let nested_indent_str = next_line_indent.to_string_with_newline(context.config); - let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { - let comma = if context.config.match_block_trailing_comma() { - "," - } else { - "" - }; - ("{", format!("{}}}{}", indent_str, comma)) - } else { - ("", String::from(",")) - }; - - let block_sep = match context.config.control_brace_style() { - ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), - _ if body_prefix.is_empty() => "".to_owned(), - _ if forbid_same_line => format!("{}{}", alt_block_sep, body_prefix), - _ => format!(" {}", body_prefix), - } + &nested_indent_str; - - Some(format!( - "{} =>{}{}{}", - pats_str, block_sep, body_str, body_suffix - )) - }; - - // Let's try and get the arm body on the same line as the condition. - // 4 = ` => `.len() - let orig_body_shape = shape - .offset_left(extra_offset(pats_str, shape) + 4) - .and_then(|shape| shape.sub_width(comma.len())); - let orig_body = if let Some(body_shape) = orig_body_shape { - let rewrite = nop_block_collapse( - format_expr(body, ExprType::Statement, context, body_shape), - body_shape.width, - ); - - match rewrite { - Some(ref body_str) - if !forbid_same_line - && (is_block - || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => - { - return combine_orig_body(body_str); - } - _ => rewrite, - } - } else { - None - }; - let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); - - // Try putting body on the next line and see if it looks better. - let next_line_body_shape = Shape::indented(next_line_indent, context.config); - let next_line_body = nop_block_collapse( - format_expr(body, ExprType::Statement, context, next_line_body_shape), - next_line_body_shape.width, - ); - match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) - if forbid_same_line - || prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => - { - combine_next_line_body(next_line_str) - } - (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { - combine_orig_body(orig_str) - } - (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { - combine_next_line_body(next_line_str) - } - (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), - (None, None) => None, - (Some(ref orig_str), _) => combine_orig_body(orig_str), - } -} - -// The `if ...` guard on a match arm. -fn rewrite_guard( - context: &RewriteContext, - guard: &Option>, - shape: Shape, - // The amount of space used up on this line for the pattern in - // the arm (excludes offset). - pattern_width: usize, -) -> Option { - if let Some(ref guard) = *guard { - // First try to fit the guard string on the same line as the pattern. - // 4 = ` if `, 5 = ` => {` - let cond_shape = shape - .offset_left(pattern_width + 4) - .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { - return Some(format!(" if {}", cond_str)); - } - } - } - - // Not enough space to put the guard after the pattern, try a newline. - // 3 = `if `, 5 = ` => {` - let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) - .offset_left(3) - .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - return Some(format!( - "{}if {}", - cond_shape.indent.to_string_with_newline(context.config), - cond_str - )); - } - } - - None - } else { - Some(String::new()) - } -} - -fn rewrite_multiple_patterns( +pub fn rewrite_multiple_patterns( context: &RewriteContext, pats: &[&ast::Pat], shape: Shape, @@ -1852,33 +1342,6 @@ fn rewrite_multiple_patterns( write_list(&items, &fmt) } -fn can_extend_match_arm_body(body: &ast::Expr) -> bool { - match body.node { - // We do not allow `if` to stay on the same line, since we could easily mistake - // `pat => if cond { ... }` and `pat if cond => { ... }`. - ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, - ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::Match(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Closure(..) - | ast::ExprKind::Array(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Mac(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::Tup(..) => true, - ast::ExprKind::AddrOf(_, ref expr) - | ast::ExprKind::Box(ref expr) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), - _ => false, - } -} - pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), @@ -2663,7 +2126,7 @@ fn choose_rhs( } } -fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { +pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { rhs_tactics == RhsTactics::ForceNextLine || !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } diff --git a/src/lib.rs b/src/lib.rs index eff414b5708..683a75cb32a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,7 @@ mod issues; mod items; mod lists; mod macros; +mod matches; mod missed_spans; pub mod modules; mod overflow; diff --git a/src/matches.rs b/src/matches.rs new file mode 100644 index 00000000000..b97fbd87417 --- /dev/null +++ b/src/matches.rs @@ -0,0 +1,531 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Format match expression. + +use std::iter::repeat; + +use config::lists::*; +use syntax::{ast, ptr}; +use syntax::codemap::{BytePos, Span}; + +use codemap::SpanUtils; +use comment::combine_strs_with_missing_comments; +use config::{Config, ControlBraceStyle, IndentStyle}; +use expr::{format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, + rewrite_multiple_patterns, ExprType, RhsTactics, ToExpr}; +use lists::{itemize_list, write_list, ListFormatting}; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use spanned::Spanned; +use utils::{contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, + mk_sp, ptr_vec_to_ref_vec, trimmed_last_line_width}; + +/// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. +struct ArmWrapper<'a> { + pub arm: &'a ast::Arm, + /// True if the arm is the last one in match expression. Used to decide on whether we should add + /// trailing comma to the match arm when `config.trailing_comma() == Never`. + pub is_last: bool, + /// Holds a byte position of `|` at the beginning of the arm pattern, if available. + pub beginning_vert: Option, +} + +impl<'a> ArmWrapper<'a> { + pub fn new( + arm: &'a ast::Arm, + is_last: bool, + beginning_vert: Option, + ) -> ArmWrapper<'a> { + ArmWrapper { + arm, + is_last, + beginning_vert, + } + } +} + +impl<'a> Spanned for ArmWrapper<'a> { + fn span(&self) -> Span { + if let Some(lo) = self.beginning_vert { + mk_sp(lo, self.arm.span().hi()) + } else { + self.arm.span() + } + } +} + +impl<'a> Rewrite for ArmWrapper<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + rewrite_match_arm(context, self.arm, shape, self.is_last, self.beginning_vert) + } +} + +pub fn rewrite_match( + context: &RewriteContext, + cond: &ast::Expr, + arms: &[ast::Arm], + shape: Shape, + span: Span, + attrs: &[ast::Attribute], +) -> Option { + // Do not take the rhs overhead from the upper expressions into account + // when rewriting match condition. + let cond_shape = Shape { + width: context.budget(shape.used_width()), + ..shape + }; + // 6 = `match ` + let cond_shape = match context.config.indent_style() { + IndentStyle::Visual => cond_shape.shrink_left(6)?, + IndentStyle::Block => cond_shape.offset_left(6)?, + }; + let cond_str = cond.rewrite(context, cond_shape)?; + let alt_block_sep = &shape.indent.to_string_with_newline(context.config); + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine => alt_block_sep, + _ if last_line_extendable(&cond_str) => " ", + // 2 = ` {` + _ if cond_str.contains('\n') || cond_str.len() + 2 > cond_shape.width => alt_block_sep, + _ => " ", + }; + + let nested_indent_str = shape + .indent + .block_indent(context.config) + .to_string(context.config); + // Inner attributes. + let inner_attrs = &inner_attributes(attrs); + let inner_attrs_str = if inner_attrs.is_empty() { + String::new() + } else { + inner_attrs + .rewrite(context, shape) + .map(|s| format!("{}{}\n", nested_indent_str, s))? + }; + + let open_brace_pos = if inner_attrs.is_empty() { + let hi = if arms.is_empty() { + span.hi() + } else { + arms[0].span().lo() + }; + context + .snippet_provider + .span_after(mk_sp(cond.span.hi(), hi), "{") + } else { + inner_attrs[inner_attrs.len() - 1].span().hi() + }; + + if arms.is_empty() { + let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1))); + if snippet.trim().is_empty() { + Some(format!("match {} {{}}", cond_str)) + } else { + // Empty match with comments or inner attributes? We are not going to bother, sorry ;) + Some(context.snippet(span).to_owned()) + } + } else { + Some(format!( + "match {}{}{{\n{}{}{}\n{}}}", + cond_str, + block_sep, + inner_attrs_str, + nested_indent_str, + rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, + shape.indent.to_string(context.config), + )) + } +} + +fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { + if is_last && config.trailing_comma() == SeparatorTactic::Never { + "" + } else if config.match_block_trailing_comma() { + "," + } else if let ast::ExprKind::Block(ref block) = body.node { + if let ast::BlockCheckMode::Default = block.rules { + "" + } else { + "," + } + } else { + "," + } +} + +/// Collect a byte position of the beginning `|` for each arm, if available. +fn collect_beginning_verts( + context: &RewriteContext, + arms: &[ast::Arm], + span: Span, +) -> Vec> { + let mut beginning_verts = Vec::with_capacity(arms.len()); + let mut lo = context.snippet_provider.span_after(span, "{"); + for arm in arms { + let hi = arm.pats[0].span.lo(); + let missing_span = mk_sp(lo, hi); + beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); + lo = arm.span().hi(); + } + beginning_verts +} + +fn rewrite_match_arms( + context: &RewriteContext, + arms: &[ast::Arm], + shape: Shape, + span: Span, + open_brace_pos: BytePos, +) -> Option { + let arm_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + + let arm_len = arms.len(); + let is_last_iter = repeat(false) + .take(arm_len.checked_sub(1).unwrap_or(0)) + .chain(repeat(true)); + let beginning_verts = collect_beginning_verts(context, arms, span); + let items = itemize_list( + context.snippet_provider, + arms.iter() + .zip(is_last_iter) + .zip(beginning_verts.into_iter()) + .map(|((arm, is_last), beginning_vert)| ArmWrapper::new(arm, is_last, beginning_vert)), + "}", + "|", + |arm| arm.span().lo(), + |arm| arm.span().hi(), + |arm| arm.rewrite(context, arm_shape), + open_brace_pos, + span.hi(), + false, + ); + let arms_vec: Vec<_> = items.collect(); + let fmt = ListFormatting { + tactic: DefinitiveListTactic::Vertical, + // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. + separator: "", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape: arm_shape, + ends_with_newline: true, + preserve_newline: true, + config: context.config, + }; + + write_list(&arms_vec, &fmt) +} + +fn rewrite_match_arm( + context: &RewriteContext, + arm: &ast::Arm, + shape: Shape, + is_last: bool, + beginning_vert: Option, +) -> Option { + let (missing_span, attrs_str) = if !arm.attrs.is_empty() { + if contains_skip(&arm.attrs) { + let (_, body) = flatten_arm_body(context, &arm.body); + // `arm.span()` does not include trailing comma, add it manually. + return Some(format!( + "{}{}", + context.snippet(arm.span()), + arm_comma(context.config, body, is_last), + )); + } + let missing_span = mk_sp( + arm.attrs[arm.attrs.len() - 1].span.hi(), + arm.pats[0].span.lo(), + ); + (missing_span, arm.attrs.rewrite(context, shape)?) + } else { + (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) + }; + let pats_str = rewrite_match_pattern( + context, + &ptr_vec_to_ref_vec(&arm.pats), + &arm.guard, + beginning_vert.is_some(), + shape, + ).and_then(|pats_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &pats_str, + missing_span, + shape, + false, + ) + })?; + rewrite_match_body( + context, + &arm.body, + &pats_str, + shape, + arm.guard.is_some(), + is_last, + ) +} + +fn rewrite_match_pattern( + context: &RewriteContext, + pats: &[&ast::Pat], + guard: &Option>, + has_beginning_vert: bool, + shape: Shape, +) -> Option { + // Patterns + // 5 = ` => {` + // 2 = `| ` + let pat_shape = shape + .sub_width(5)? + .offset_left(if has_beginning_vert { 2 } else { 0 })?; + let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?; + let beginning_vert = if has_beginning_vert { "| " } else { "" }; + + // Guard + let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; + + Some(format!("{}{}{}", beginning_vert, pats_str, guard_str)) +} + +// (extend, body) +// @extend: true if the arm body can be put next to `=>` +// @body: flattened body, if the body is block with a single expression +fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { + match body.node { + ast::ExprKind::Block(ref block) + if !is_unsafe_block(block) + && is_simple_block(block, Some(&body.attrs), context.codemap) => + { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { + ( + !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), + &*expr, + ) + } else { + (false, &*body) + } + } + _ => ( + !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), + &*body, + ), + } +} + +fn rewrite_match_body( + context: &RewriteContext, + body: &ptr::P, + pats_str: &str, + shape: Shape, + has_guard: bool, + is_last: bool, +) -> Option { + let (extend, body) = flatten_arm_body(context, body); + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { + ( + true, + is_empty_block(block, Some(&body.attrs), context.codemap), + ) + } else { + (false, false) + }; + + let comma = arm_comma(context.config, body, is_last); + let alt_block_sep = &shape.indent.to_string_with_newline(context.config); + + let combine_orig_body = |body_str: &str| { + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep, + _ => " ", + }; + + Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) + }; + + let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; + let next_line_indent = if !is_block || is_empty_block { + shape.indent.block_indent(context.config) + } else { + shape.indent + }; + let combine_next_line_body = |body_str: &str| { + if is_block { + return Some(format!( + "{} =>{}{}", + pats_str, + next_line_indent.to_string_with_newline(context.config), + body_str + )); + } + + let indent_str = shape.indent.to_string_with_newline(context.config); + let nested_indent_str = next_line_indent.to_string_with_newline(context.config); + let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { + let comma = if context.config.match_block_trailing_comma() { + "," + } else { + "" + }; + ("{", format!("{}}}{}", indent_str, comma)) + } else { + ("", String::from(",")) + }; + + let block_sep = match context.config.control_brace_style() { + ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), + _ if body_prefix.is_empty() => "".to_owned(), + _ if forbid_same_line => format!("{}{}", alt_block_sep, body_prefix), + _ => format!(" {}", body_prefix), + } + &nested_indent_str; + + Some(format!( + "{} =>{}{}{}", + pats_str, block_sep, body_str, body_suffix + )) + }; + + // Let's try and get the arm body on the same line as the condition. + // 4 = ` => `.len() + let orig_body_shape = shape + .offset_left(extra_offset(pats_str, shape) + 4) + .and_then(|shape| shape.sub_width(comma.len())); + let orig_body = if let Some(body_shape) = orig_body_shape { + let rewrite = nop_block_collapse( + format_expr(body, ExprType::Statement, context, body_shape), + body_shape.width, + ); + + match rewrite { + Some(ref body_str) + if !forbid_same_line + && (is_block + || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => + { + return combine_orig_body(body_str); + } + _ => rewrite, + } + } else { + None + }; + let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); + + // Try putting body on the next line and see if it looks better. + let next_line_body_shape = Shape::indented(next_line_indent, context.config); + let next_line_body = nop_block_collapse( + format_expr(body, ExprType::Statement, context, next_line_body_shape), + next_line_body_shape.width, + ); + match (orig_body, next_line_body) { + (Some(ref orig_str), Some(ref next_line_str)) + if forbid_same_line + || prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => + { + combine_next_line_body(next_line_str) + } + (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { + combine_orig_body(orig_str) + } + (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { + combine_next_line_body(next_line_str) + } + (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), + (None, None) => None, + (Some(ref orig_str), _) => combine_orig_body(orig_str), + } +} + +// The `if ...` guard on a match arm. +fn rewrite_guard( + context: &RewriteContext, + guard: &Option>, + shape: Shape, + // The amount of space used up on this line for the pattern in + // the arm (excludes offset). + pattern_width: usize, +) -> Option { + if let Some(ref guard) = *guard { + // First try to fit the guard string on the same line as the pattern. + // 4 = ` if `, 5 = ` => {` + let cond_shape = shape + .offset_left(pattern_width + 4) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { + return Some(format!(" if {}", cond_str)); + } + } + } + + // Not enough space to put the guard after the pattern, try a newline. + // 3 = `if `, 5 = ` => {` + let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config) + .offset_left(3) + .and_then(|s| s.sub_width(5)); + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + return Some(format!( + "{}if {}", + cond_shape.indent.to_string_with_newline(context.config), + cond_str + )); + } + } + + None + } else { + Some(String::new()) + } +} + +fn nop_block_collapse(block_str: Option, budget: usize) -> Option { + debug!("nop_block_collapse {:?} {}", block_str, budget); + block_str.map(|block_str| { + if block_str.starts_with('{') && budget >= 2 + && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) + { + "{}".to_owned() + } else { + block_str.to_owned() + } + }) +} + +fn can_extend_match_arm_body(body: &ast::Expr) -> bool { + match body.node { + // We do not allow `if` to stay on the same line, since we could easily mistake + // `pat => if cond { ... }` and `pat if cond => { ... }`. + ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, + ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Closure(..) + | ast::ExprKind::Array(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Mac(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::Tup(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), + _ => false, + } +} diff --git a/src/patterns.rs b/src/patterns.rs index 54b7e0f9a4c..cfff023bafc 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -27,6 +27,40 @@ use spanned::Spanned; use types::{rewrite_path, PathContext}; use utils::{format_mutability, mk_sp}; +/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: +/// +/// [small, ntp]: +/// - single token +/// - `&[single-line, ntp]` +/// +/// [small]: +/// - `[small, ntp]` +/// - unary tuple constructor `([small, ntp])` +/// - `&[small]` +pub fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { + // We also require that the pattern is reasonably 'small' with its literal width. + pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) +} + +fn is_short_pattern_inner(pat: &ast::Pat) -> bool { + match pat.node { + ast::PatKind::Wild | ast::PatKind::Lit(_) => true, + ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), + ast::PatKind::Struct(..) + | ast::PatKind::Mac(..) + | ast::PatKind::Slice(..) + | ast::PatKind::Path(..) + | ast::PatKind::Range(..) => false, + ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, + ast::PatKind::TupleStruct(ref path, ref subpats, _) => { + path.segments.len() <= 1 && subpats.len() <= 1 + } + ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => { + is_short_pattern_inner(&*p) + } + } +} + impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match self.node { -- cgit 1.4.1-3-g733a5 From 5b9b7d5b9f357252e7f8c42afcfcc073f110968c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 21 Mar 2018 22:20:03 +0900 Subject: Do not collapse block around expr with condition on match arm Closes #2376. --- src/matches.rs | 16 +++++++++------- tests/source/match.rs | 23 +++++++++++++++++++++++ tests/target/match.rs | 23 +++++++++++++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index b97fbd87417..83ff70ea196 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -309,7 +309,7 @@ fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bo { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { ( - !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr), + !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr), &*expr, ) } else { @@ -503,15 +503,17 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option bool { +fn can_flatten_block_around_this(body: &ast::Expr) -> bool { match body.node { // We do not allow `if` to stay on the same line, since we could easily mistake // `pat => if cond { ... }` and `pat if cond => { ... }`. ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, - ast::ExprKind::ForLoop(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) + // We do not allow collapsing a block around expression with condition + // to avoid it being cluttered with match arm. + ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => { + false + } + ast::ExprKind::Loop(..) | ast::ExprKind::Match(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) @@ -525,7 +527,7 @@ fn can_extend_match_arm_body(body: &ast::Expr) -> bool { | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr), + | ast::ExprKind::Cast(ref expr, _) => can_flatten_block_around_this(expr), _ => false, } } diff --git a/tests/source/match.rs b/tests/source/match.rs index f38bf7cca97..31034f49402 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -462,3 +462,26 @@ fn match_with_beginning_vert() { | Foo::C => println!("C"), } } + +// #2376 +// Preserve block around expressions with condition. +fn issue_2376() { + let mut x = None; + match x { + Some(0) => { + for i in 1..11 { + x = Some(i); + } + } + Some(ref mut y) => { + while *y < 10 { + *y += 1; + } + } + None => { + while let None = x { + x = Some(10); + } + } + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 72ffa966c01..087fb80ef09 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -493,3 +493,26 @@ fn match_with_beginning_vert() { | Foo::C => println!("C"), } } + +// #2376 +// Preserve block around expressions with condition. +fn issue_2376() { + let mut x = None; + match x { + Some(0) => { + for i in 1..11 { + x = Some(i); + } + } + Some(ref mut y) => { + while *y < 10 { + *y += 1; + } + } + None => { + while let None = x { + x = Some(10); + } + } + } +} -- cgit 1.4.1-3-g733a5 From 4757321277c8090f80b0665c23807e0cdbbe1557 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 22 Mar 2018 08:32:42 +0900 Subject: Don't index a string with `chars().count()` --- src/attr.rs | 2 +- src/comment.rs | 4 ++-- src/issues.rs | 4 ++-- src/items.rs | 2 +- src/lib.rs | 14 ++++++++------ 5 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 2e4a4632620..167bbe29408 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -167,7 +167,7 @@ impl Rewrite for ast::NestedMetaItem { fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { // Look at before and after comment and see if there are any empty lines. - let comment_begin = comment.chars().position(|c| c == '/'); + let comment_begin = comment.find('/'); let len = comment_begin.unwrap_or_else(|| comment.len()); let mlb = count_newlines(&comment[..len]) > 1; let mla = if comment_begin.is_none() { diff --git a/src/comment.rs b/src/comment.rs index d53d5a9d4aa..05b423d1898 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -187,7 +187,7 @@ pub fn combine_strs_with_missing_comments( // expression and the second expression or the missing comment. We will preserve the original // layout whenever possible. let original_snippet = context.snippet(span); - let prefer_same_line = if let Some(pos) = original_snippet.chars().position(|c| c == '/') { + let prefer_same_line = if let Some(pos) = original_snippet.find('/') { !original_snippet[..pos].contains('\n') } else { !original_snippet.contains('\n') @@ -523,7 +523,7 @@ pub fn recover_missing_comment_in_span( Some(String::new()) } else { let missing_snippet = context.snippet(span); - let pos = missing_snippet.chars().position(|c| c == '/').unwrap_or(0); + let pos = missing_snippet.find('/').unwrap_or(0); // 1 = ` ` let total_width = missing_comment.len() + used_width + 1; let force_new_line_before_comment = diff --git a/src/issues.rs b/src/issues.rs index 75ad30b6f2a..ad7babca118 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -227,13 +227,13 @@ fn find_unnumbered_issue() { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); assert_eq!( Some(failing_pos), - text.chars().position(|c| seeker.inspect(c).is_some()) + text.find(|c| seeker.inspect(c).is_some()) ); } fn check_pass(text: &str) { let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered); - assert_eq!(None, text.chars().position(|c| seeker.inspect(c).is_some())); + assert_eq!(None, text.find(|c| seeker.inspect(c).is_some())); } check_fail("TODO\n", 4); diff --git a/src/items.rs b/src/items.rs index 6306767f00c..0ef264b7f16 100644 --- a/src/items.rs +++ b/src/items.rs @@ -977,7 +977,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&where_clause_str); } else { let item_snippet = context.snippet(item.span); - if let Some(lo) = item_snippet.chars().position(|c| c == '/') { + if let Some(lo) = item_snippet.find('/') { // 1 = `{` let comment_hi = body_lo - BytePos(1); let comment_lo = item.span.lo() + BytePos(lo as u32); diff --git a/src/lib.rs b/src/lib.rs index eff414b5708..b2ed8946879 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -153,12 +153,14 @@ impl FormattingError { match self.kind { ErrorKind::LineOverflow(found, max) => (max, found - max), ErrorKind::TrailingWhitespace => { - let trailing_ws_len = self.line_buffer - .chars() - .rev() - .take_while(|c| c.is_whitespace()) - .count(); - (self.line_buffer.len() - trailing_ws_len, trailing_ws_len) + let trailing_ws_start = self.line_buffer + .rfind(|c: char| !c.is_whitespace()) + .map(|pos| pos + 1) + .unwrap_or(0); + ( + trailing_ws_start, + self.line_buffer.len() - trailing_ws_start, + ) } _ => unreachable!(), } -- cgit 1.4.1-3-g733a5 From e5572bbb66efa31fb1aa66c34270cd966dbdf0f0 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 22 Mar 2018 08:34:36 +0900 Subject: Use take_while --- src/attr.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 167bbe29408..409a61ab544 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -173,13 +173,11 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { let mla = if comment_begin.is_none() { mlb } else { - let comment_end = comment.chars().rev().position(|c| !c.is_whitespace()); - let len = comment_end.unwrap(); comment .chars() .rev() - .take(len) - .filter(|c| *c == '\n') + .take_while(|c| c.is_whitespace()) + .filter(|&c| c == '\n') .count() > 1 }; (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) -- cgit 1.4.1-3-g733a5 From 83c8d23cc27fa3ce1597edb78d5ae6f3c99fc4bb Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 21 Mar 2018 23:58:23 +0900 Subject: Omit unnecessary UTF-8 decoding --- src/utils.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index f6d2ff23c34..ddf6ff755ee 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -251,7 +251,8 @@ pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { #[inline] pub fn count_newlines(input: &str) -> usize { - input.chars().filter(|&c| c == '\n').count() + // Using `as_bytes` to omit UTF-8 decoding + input.as_bytes().iter().filter(|&&c| c == b'\n').count() } macro_rules! msg { -- cgit 1.4.1-3-g733a5 From d8723aaa8ca8c827b1bbaf1e73923404169b9cfc Mon Sep 17 00:00:00 2001 From: Alan Du Date: Thu, 22 Mar 2018 00:01:09 -0400 Subject: Fix build --- src/matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 83ff70ea196..42f46608b52 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -13,8 +13,8 @@ use std::iter::repeat; use config::lists::*; -use syntax::{ast, ptr}; use syntax::codemap::{BytePos, Span}; +use syntax::{ast, ptr}; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; -- cgit 1.4.1-3-g733a5 From d402cd20a8be72ce0eaad08f10d44360aae3506a Mon Sep 17 00:00:00 2001 From: Alan Du Date: Thu, 22 Mar 2018 00:57:22 -0400 Subject: Close #2551 --- src/expr.rs | 2 +- tests/target/issue-2551.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-2551.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a1fe1153e55..9aafd71dd22 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1547,7 +1547,7 @@ pub fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { for (kind, c) in CharClasses::new(context.snippet(span).chars()) { match c { _ if kind.is_comment() || c.is_whitespace() => continue, - ')' | '}' => result = result && prev_char != c, + ')' | '}' => result = result && prev_char != ')' && prev_char != '}', ',' => result = true, _ => result = false, } diff --git a/tests/target/issue-2551.rs b/tests/target/issue-2551.rs new file mode 100644 index 00000000000..d7b0d625b9e --- /dev/null +++ b/tests/target/issue-2551.rs @@ -0,0 +1,3 @@ +mcro!(func(A { + a: 12345667800111111111111, +})); -- cgit 1.4.1-3-g733a5 From 51d5696977c644bd7e3107d6329354642f617f5e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 22 Mar 2018 15:53:43 +0900 Subject: Fix libsyntax update Underscore is now one of keywords. --- src/macros.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index ec1ca29d173..38fb3973e6f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -965,8 +965,7 @@ fn next_space(tok: &Token) -> SpaceState { | Token::DotDotDot | Token::DotDotEq | Token::DotEq - | Token::Question - | Token::Underscore => SpaceState::Punctuation, + | Token::Question => SpaceState::Punctuation, Token::ModSep | Token::Pound -- cgit 1.4.1-3-g733a5 From 846f4f21db34b252b5e42c7a841f14624c643280 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 22 Mar 2018 15:55:14 +0900 Subject: Fix libsyntax updates `ast::UseTreeKind::Simple` now takes `Option` instead of `ast::Ident`. --- src/imports.rs | 35 ++++++++++++++++------------------- src/reorder.rs | 12 +++++++----- 2 files changed, 23 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9a6af3f267c..f631f4b9c26 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -29,6 +29,10 @@ pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { path.segments.last().unwrap().identifier } +pub fn same_rename(opt_ident: &Option, path: &ast::Path) -> bool { + opt_ident.map_or(true, |ident| path_to_imported_ident(path) == ident) +} + fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { let path = &ast::Path { @@ -57,22 +61,16 @@ impl Rewrite for ast::UseTree { Some("*".to_owned()) } } - ast::UseTreeKind::Simple(ident) => { - let ident_str = ident.to_string(); - - // 4 = " as ".len() - let is_same_name_bind = path_to_imported_ident(&self.prefix) == ident; - let prefix_shape = if is_same_name_bind { - shape - } else { - shape.sub_width(ident_str.len() + 4)? - }; - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) - .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); - - if is_same_name_bind { - Some(path_str) + ast::UseTreeKind::Simple(opt_ident) => { + if same_rename(&opt_ident, &self.prefix) { + rewrite_prefix(&self.prefix, context, shape) + .or_else(|| Some(context.snippet(self.prefix.span).to_owned())) } else { + let ident_str = opt_ident?.to_string(); + // 4 = " as ".len() + let prefix_shape = shape.sub_width(ident_str.len() + 4)?; + let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) + .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); Some(format!("{} as {}", path_str, ident_str)) } } @@ -161,8 +159,7 @@ fn rewrite_nested_use_tree_single( shape: Shape, ) -> Option { match tree.kind { - ast::UseTreeKind::Simple(rename) => { - let ident = path_to_imported_ident(&tree.prefix); + ast::UseTreeKind::Simple(opt_rename) => { let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; if item_str == "self" { item_str = "".to_owned(); @@ -180,10 +177,10 @@ fn rewrite_nested_use_tree_single( format!("{}::{}", path_str, item_str) }; - Some(if ident == rename { + Some(if same_rename(&opt_rename, &tree.prefix) { path_item_str } else { - format!("{} as {}", path_item_str, rename) + format!("{} as {}", path_item_str, opt_rename?) }) } ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { diff --git a/src/reorder.rs b/src/reorder.rs index 5595fa5b237..b216313f3b0 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -321,11 +321,13 @@ impl UseTree { } UseTreeKind::Simple(ref rename) => { let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); - let alias = if &name == &*rename.name.as_str() { - None - } else { - Some((&*rename.name.as_str()).to_owned()) - }; + let alias = rename.and_then(|ident| { + if ident == path_to_imported_ident(&a.prefix) { + None + } else { + Some(ident.to_string()) + } + }); let segment = if &name == "self" { UseSegment::Slf(alias) -- cgit 1.4.1-3-g733a5 From b58a1133700c3887a1c2c1285dbf309b5a1f8702 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 22 Mar 2018 15:56:51 +0900 Subject: Use `UseSegment::Slf` or `UseSegment::Super` when appropriate Currently we `UseSegment::Ident` for all of the segments except the last. E.g. `use super::foo::bar::self;` will be `[Ident("super"), Ident("foo"), Ident("bar"), Self(None)]`. in the current implementation. I think that this should be `[Super(None), Ident("foo"), Ident("bar"), Self(None)]`. instead. I noticed this because some tests failed after updating `rustc-ap-syntax` to 73.0.0. --- src/reorder.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index b216313f3b0..38d2a09bd08 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -299,16 +299,24 @@ impl UseSegment { _ => self.clone(), } } + + fn from_path_segment(path_seg: &ast::PathSegment) -> UseSegment { + let name = path_seg.identifier.name.as_str(); + if name == "self" { + UseSegment::Slf(None) + } else if name == "super" { + UseSegment::Super(None) + } else { + UseSegment::Ident((*name).to_owned(), None) + } + } } impl UseTree { fn from_ast(a: &ast::UseTree) -> UseTree { let mut result = UseTree { path: vec![] }; for p in &a.prefix.segments { - result.path.push(UseSegment::Ident( - (*p.identifier.name.as_str()).to_owned(), - None, - )); + result.path.push(UseSegment::from_path_segment(p)); } match a.kind { UseTreeKind::Glob => { -- cgit 1.4.1-3-g733a5 From 6115dcdbdcd6ec0087172829851dfce9a33c59b6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 22 Mar 2018 16:08:57 +0900 Subject: Remove a space after a colon of metavariable def in macro def --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 784e6c5798b..c8fc0c72ea7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -568,7 +568,7 @@ impl MacroArgKind { match *self { MacroArgKind::MetaVariable(ty, ref name) => { - Some(format!("${}: {}", name, ty.name.as_str())) + Some(format!("${}:{}", name, ty.name.as_str())) } MacroArgKind::Repeat(ref delim_tok, ref args, ref another, ref tok) => { let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?; -- cgit 1.4.1-3-g733a5 From ccec777f929c9a3094caa37842367c21387d95a0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 22 Mar 2018 16:09:21 +0900 Subject: Cargo fmt and update tests --- src/cargo-fmt/main.rs | 2 +- src/macros.rs | 2 +- src/spanned.rs | 6 ++-- src/utils.rs | 8 ++--- tests/target/macro_not_expr.rs | 2 +- tests/target/macro_rules.rs | 73 +++++++++++++++++++++--------------------- tests/target/macros.rs | 6 ++-- 7 files changed, 49 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 855a45568b7..990e2596660 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -97,7 +97,7 @@ fn execute() -> i32 { } macro_rules! print_usage { - ($print: ident, $opts: ident, $reason: expr) => {{ + ($print:ident, $opts:ident, $reason:expr) => {{ let msg = format!("{}\nusage: cargo fmt [options]", $reason); $print!( "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ diff --git a/src/macros.rs b/src/macros.rs index c8fc0c72ea7..d1679fb9e4f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -103,7 +103,7 @@ impl Rewrite for MacroArg { fn parse_macro_arg(parser: &mut Parser) -> Option { macro_rules! parse_macro_arg { - ($macro_arg: ident, $parser: ident) => { + ($macro_arg:ident, $parser:ident) => { let mut cloned_parser = (*parser).clone(); match cloned_parser.$parser() { Ok(x) => { diff --git a/src/spanned.rs b/src/spanned.rs index 6f5a4b1721f..bcbf6bd6060 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -20,7 +20,7 @@ pub trait Spanned { } macro_rules! span_with_attrs_lo_hi { - ($this: ident, $lo: expr, $hi: expr) => {{ + ($this:ident, $lo:expr, $hi:expr) => {{ let attrs = outer_attributes(&$this.attrs); if attrs.is_empty() { mk_sp($lo, $hi) @@ -31,13 +31,13 @@ macro_rules! span_with_attrs_lo_hi { } macro_rules! span_with_attrs { - ($this: ident) => { + ($this:ident) => { span_with_attrs_lo_hi!($this, $this.span.lo(), $this.span.hi()) }; } macro_rules! implement_spanned { - ($this: ty) => { + ($this:ty) => { impl Spanned for $this { fn span(&self) -> Span { span_with_attrs!(self) diff --git a/src/utils.rs b/src/utils.rs index f6d2ff23c34..43ddaedefbe 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -266,7 +266,7 @@ macro_rules! msg { // For format_missing and last_pos, need to use the source callsite (if applicable). // Required as generated code spans aren't guaranteed to follow on from the last span. macro_rules! source { - ($this: ident, $sp: expr) => { + ($this:ident, $sp:expr) => { $sp.source_callsite() }; } @@ -277,7 +277,7 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { // Return true if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { - ($self: ident, $span: expr) => { + ($self:ident, $span:expr) => { !$self.config.file_lines().is_all() && !$self .config @@ -287,7 +287,7 @@ macro_rules! out_of_file_lines_range { } macro_rules! skip_out_of_file_lines_range { - ($self: ident, $span: expr) => { + ($self:ident, $span:expr) => { if out_of_file_lines_range!($self, $span) { return None; } @@ -295,7 +295,7 @@ macro_rules! skip_out_of_file_lines_range { } macro_rules! skip_out_of_file_lines_range_visitor { - ($self: ident, $span: expr) => { + ($self:ident, $span:expr) => { if out_of_file_lines_range!($self, $span) { $self.push_rewrite($span, None); return; diff --git a/tests/target/macro_not_expr.rs b/tests/target/macro_not_expr.rs index c76a6492a9d..45f85ff2c93 100644 --- a/tests/target/macro_not_expr.rs +++ b/tests/target/macro_not_expr.rs @@ -1,5 +1,5 @@ macro_rules! test { - ($($t: tt)*) => {}; + ($($t:tt)*) => {}; } fn main() { diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 793efcb6b0c..12fdb7b026e 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -2,33 +2,33 @@ macro_rules! m { () => {}; - ($x: ident) => {}; - ($m1: ident, $m2: ident, $x: ident) => {}; - ($($beginning: ident),*; $middle: ident; $($end: ident),*) => {}; + ($x:ident) => {}; + ($m1:ident, $m2:ident, $x:ident) => {}; + ($($beginning:ident),*; $middle:ident; $($end:ident),*) => {}; ( - $($beginning: ident),*; - $middle: ident; - $($end: ident),*; - $($beginning: ident),*; - $middle: ident; - $($end: ident),* + $($beginning:ident),*; + $middle:ident; + $($end:ident),*; + $($beginning:ident),*; + $middle:ident; + $($end:ident),* ) => {}; - ($name: ident($($dol: tt $var: ident)*) $($body: tt)*) => {}; + ($name:ident($($dol:tt $var:ident)*) $($body:tt)*) => {}; ( - $($i: ident : $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* - $($i: ident : $ty: ty, $def: expr, $stb: expr, $($dstring: tt),+);+ $(;)* + $($i:ident : $ty:ty, $def:expr, $stb:expr, $($dstring:tt),+);+ $(;)* + $($i:ident : $ty:ty, $def:expr, $stb:expr, $($dstring:tt),+);+ $(;)* ) => {}; - ($foo: tt foo[$attr: meta] $name: ident) => {}; - ($foo: tt[$attr: meta] $name: ident) => {}; - ($foo: tt &'a[$attr: meta] $name: ident) => {}; - ($foo: tt foo #[$attr: meta] $name: ident) => {}; - ($foo: tt #[$attr: meta] $name: ident) => {}; - ($foo: tt &'a #[$attr: meta] $name: ident) => {}; - ($x: tt foo bar foo bar foo bar $y: tt => x * y * z $z: tt, $($a: tt),*) => {}; + ($foo:tt foo[$attr:meta] $name:ident) => {}; + ($foo:tt[$attr:meta] $name:ident) => {}; + ($foo:tt &'a[$attr:meta] $name:ident) => {}; + ($foo:tt foo #[$attr:meta] $name:ident) => {}; + ($foo:tt #[$attr:meta] $name:ident) => {}; + ($foo:tt &'a #[$attr:meta] $name:ident) => {}; + ($x:tt foo bar foo bar foo bar $y:tt => x * y * z $z:tt, $($a:tt),*) => {}; } macro_rules! impl_a_method { - ($n: ident($a: ident : $ta: ty) -> $ret: ty { $body: expr }) => { + ($n:ident($a:ident : $ta:ty) -> $ret:ty { $body:expr }) => { fn $n($a: $ta) -> $ret { $body } @@ -38,7 +38,7 @@ macro_rules! impl_a_method { }; } }; - ($n: ident($a: ident : $ta: ty, $b: ident : $tb: ty) -> $ret: ty { $body: expr }) => { + ($n:ident($a:ident : $ta:ty, $b:ident : $tb:ty) -> $ret:ty { $body:expr }) => { fn $n($a: $ta, $b: $tb) -> $ret { $body } @@ -49,8 +49,7 @@ macro_rules! impl_a_method { } }; ( - $n: ident($a: ident : $ta: ty, $b: ident : $tb: ty, $c: ident : $tc: ty) -> - $ret: ty { $body: expr } + $n:ident($a:ident : $ta:ty, $b:ident : $tb:ty, $c:ident : $tc:ty) -> $ret:ty { $body:expr } ) => { fn $n($a: $ta, $b: $tb, $c: $tc) -> $ret { $body @@ -62,8 +61,8 @@ macro_rules! impl_a_method { } }; ( - $n: ident($a: ident : $ta: ty, $b: ident : $tb: ty, $c: ident : $tc: ty, $d: ident : $td: ty) -> - $ret: ty { $body: expr } + $n:ident($a:ident : $ta:ty, $b:ident : $tb:ty, $c:ident : $tc:ty, $d:ident : $td:ty) -> + $ret:ty { $body:expr } ) => { fn $n($a: $ta, $b: $tb, $c: $tc, $d: $td) -> $ret { $body @@ -78,7 +77,7 @@ macro_rules! impl_a_method { macro_rules! m { // a - ($expr: expr, $($func: ident)*) => {{ + ($expr:expr, $($func:ident)*) => {{ let x = $expr; $func(x) }}; @@ -91,7 +90,7 @@ macro_rules! m { (@tag) => {}; // d - ($item: ident) => { + ($item:ident) => { mod macro_item { struct $item; } @@ -100,7 +99,7 @@ macro_rules! m { macro m2 { // a - ($expr: expr, $($func: ident)*) => {{ + ($expr:expr, $($func:ident)*) => {{ let x = $expr; $func(x) }} @@ -113,7 +112,7 @@ macro m2 { (@tag) => {} // d - ($item: ident) => { + ($item:ident) => { mod macro_item { struct $item; } @@ -156,10 +155,10 @@ macro_rules! m { // #2439 macro_rules! m { ( - $line0_xxxxxxxxxxxxxxxxx: expr, - $line1_xxxxxxxxxxxxxxxxx: expr, - $line2_xxxxxxxxxxxxxxxxx: expr, - $line3_xxxxxxxxxxxxxxxxx: expr, + $line0_xxxxxxxxxxxxxxxxx:expr, + $line1_xxxxxxxxxxxxxxxxx:expr, + $line2_xxxxxxxxxxxxxxxxx:expr, + $line3_xxxxxxxxxxxxxxxxx:expr, ) => {}; } @@ -173,7 +172,7 @@ macro_rules! m [ ]; // #2470 -macro foo($type_name: ident, $docs: expr) { +macro foo($type_name:ident, $docs:expr) { #[allow(non_camel_case_types)] #[doc=$docs] #[derive(Debug, Clone, Copy)] @@ -182,13 +181,13 @@ macro foo($type_name: ident, $docs: expr) { // #2534 macro_rules! foo { - ($a: ident : $b: ty) => {}; - ($a: ident $b: ident $c: ident) => {}; + ($a:ident : $b:ty) => {}; + ($a:ident $b:ident $c:ident) => {}; } // #2538 macro_rules! add_message_to_notes { - ($msg: expr) => {{ + ($msg:expr) => {{ let mut lines = message.lines(); notes.push_str(&format!("\n{}: {}", level, lines.next().unwrap())); for line in lines { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 8db2fbb60ee..f5d8e11e35e 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -141,7 +141,7 @@ fn issue_1555() { fn issue1178() { macro_rules! foo { - (#[$attr: meta] $name: ident) => {}; + (#[$attr:meta] $name:ident) => {}; } foo!( @@ -246,7 +246,7 @@ fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { // #878 macro_rules! try_opt { - ($expr: expr) => { + ($expr:expr) => { match $expr { Some(val) => val, @@ -891,7 +891,7 @@ fn macro_in_pattern_position() { macro foo() {} -pub macro bar($x: ident + $y: expr;) { +pub macro bar($x:ident + $y:expr;) { fn foo($x: Foo) { long_function( a_long_argument_to_a_long_function_is_what_this_is(AAAAAAAAAAAAAAAAAAAAAAAAAAAA), -- cgit 1.4.1-3-g733a5 From 1e1d9d4afe59fc6ec8d39148acb2f99b715c0285 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 23 Mar 2018 19:59:38 +0900 Subject: Do not add the beginning vert to the match arm Pass the span after the match's condition expression. Closes #2554. --- src/matches.rs | 3 ++- tests/target/issue-2554.rs | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-2554.rs (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 42f46608b52..65bf7f579d4 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -133,13 +133,14 @@ pub fn rewrite_match( Some(context.snippet(span).to_owned()) } } else { + let span_after_cond = mk_sp(cond.span.hi(), span.hi()); Some(format!( "match {}{}{{\n{}{}{}\n{}}}", cond_str, block_sep, inner_attrs_str, nested_indent_str, - rewrite_match_arms(context, arms, shape, span, open_brace_pos)?, + rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?, shape.indent.to_string(context.config), )) } diff --git a/tests/target/issue-2554.rs b/tests/target/issue-2554.rs new file mode 100644 index 00000000000..d5f0563a6f1 --- /dev/null +++ b/tests/target/issue-2554.rs @@ -0,0 +1,13 @@ +// #2554 +// Do not add the beginning vert to the first match arm's pattern. + +fn main() { + match foo(|_| { + bar(|_| { + // + }) + }) { + Ok(()) => (), + Err(_) => (), + } +} -- cgit 1.4.1-3-g733a5 From c77708ff9a66724f28546c2de133461bdf0e1e8d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 25 Mar 2018 15:17:41 +0900 Subject: Use vertical layout for complex attributes --- src/attr.rs | 25 ++++++++++++++++++++++++- tests/source/attrib.rs | 4 ++++ tests/target/attrib.rs | 5 +++++ 3 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 409a61ab544..04bbcdfbbcd 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -183,6 +183,19 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) } +fn allow_mixed_tactic_for_nested_metaitem_list(list: &[ast::NestedMetaItem]) -> bool { + list.iter().all(|nested_metaitem| { + if let ast::NestedMetaItemKind::MetaItem(ref inner_metaitem) = nested_metaitem.node { + match inner_metaitem.node { + ast::MetaItemKind::List(..) | ast::MetaItemKind::NameValue(..) => false, + _ => true, + } + } else { + true + } + }) +} + impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { @@ -207,8 +220,18 @@ impl Rewrite for ast::MetaItem { false, ); let item_vec = items.collect::>(); + let tactic = if allow_mixed_tactic_for_nested_metaitem_list(list) { + DefinitiveListTactic::Mixed + } else { + ::lists::definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + ::lists::Separator::Comma, + item_shape.width, + ) + }; let fmt = ListFormatting { - tactic: DefinitiveListTactic::Mixed, + tactic, separator: ",", trailing_separator: SeparatorTactic::Never, separator_place: SeparatorPlace::Back, diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index bffe0f3f16d..552dd2b9442 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -1,5 +1,9 @@ // rustfmt-wrap_comments: true // Test attributes and doc comments are preserved. +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/", + html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] //! Doc comment diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 0a3d2bc0b81..071b9fbcb61 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -1,5 +1,10 @@ // rustfmt-wrap_comments: true // Test attributes and doc comments are preserved. +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://doc.rust-lang.org/favicon.ico", + html_root_url = "https://doc.rust-lang.org/nightly/", + html_playground_url = "https://play.rust-lang.org/", + test(attr(deny(warnings))))] //! Doc comment -- cgit 1.4.1-3-g733a5 From 903de92dae924f65821abe446f7ef1ebe29a945e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 25 Mar 2018 20:20:50 +0900 Subject: Avoid cloning RewriteContext --- src/closures.rs | 4 ++-- src/expr.rs | 21 ++++++++++++--------- src/macros.rs | 19 +++++++++++++++---- src/overflow.rs | 2 +- src/patterns.rs | 4 ---- src/rewrite.rs | 12 ++++++++++-- src/visitor.rs | 4 ++-- 7 files changed, 42 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 2ec31afa391..7fdc0e85686 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -170,7 +170,7 @@ fn rewrite_closure_expr( // When rewriting closure's body without block, we require it to fit in a single line // unless it is a block-like expression or we are inside macro call. - let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro) + let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro()) || context.config.force_multiline_blocks(); expr.rewrite(context, shape) .and_then(|rw| { @@ -370,7 +370,7 @@ where fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { // If we are inside macro, we do not want to add or remove block from closure body. - if context.inside_macro { + if context.inside_macro() { false } else { is_block_closure_forced_inner(expr) diff --git a/src/expr.rs b/src/expr.rs index 9aafd71dd22..10f2cd2aba7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -474,7 +474,7 @@ pub fn rewrite_array( separator: ",", trailing_separator: if trailing_comma { SeparatorTactic::Always - } else if context.inside_macro && !exprs.is_empty() { + } else if context.inside_macro() && !exprs.is_empty() { let ends_with_bracket = context.snippet(span).ends_with(']'); let bracket_offset = if ends_with_bracket { 1 } else { 0 }; let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); @@ -656,7 +656,7 @@ pub fn rewrite_block_with_visitor( let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; - visitor.is_if_else_block = context.is_if_else_block; + visitor.is_if_else_block = context.is_if_else_block(); match block.rules { ast::BlockCheckMode::Unsafe(..) => { let snippet = context.snippet(block.span); @@ -1142,10 +1142,13 @@ impl<'a> Rewrite for ControlFlow<'a> { width: block_width, ..shape }; - let mut block_context = context.clone(); - block_context.is_if_else_block = self.else_block.is_some(); - let block_str = - rewrite_block_with_visitor(&block_context, "", self.block, None, block_shape, true)?; + let block_str = { + let old_val = context.is_if_else_block.replace(self.else_block.is_some()); + let result = + rewrite_block_with_visitor(context, "", self.block, None, block_shape, true); + context.is_if_else_block.replace(old_val); + result? + }; let mut result = format!("{}{}", cond_str, block_str); @@ -1456,7 +1459,7 @@ pub fn rewrite_call( shape, span, context.config.width_heuristics().fn_call_width, - if context.inside_macro { + if context.inside_macro() { if span_ends_with_comma(context, span) { Some(SeparatorTactic::Always) } else { @@ -1768,7 +1771,7 @@ fn rewrite_struct_lit<'a>( let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); let ends_with_comma = span_ends_with_comma(context, span); - let force_no_trailing_comma = if context.inside_macro && !ends_with_comma { + let force_no_trailing_comma = if context.inside_macro() && !ends_with_comma { true } else { false @@ -1947,7 +1950,7 @@ where debug!("rewrite_tuple {:?}", shape); if context.use_block_indent() { // We use the same rule as function calls for rewriting tuples. - let force_tactic = if context.inside_macro { + let force_tactic = if context.inside_macro() { if span_ends_with_comma(context, span) { Some(SeparatorTactic::Always) } else { diff --git a/src/macros.rs b/src/macros.rs index 9c2b77e5c39..b3f443a628e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -152,11 +152,22 @@ pub fn rewrite_macro( shape: Shape, position: MacroPosition, ) -> Option { - let context = &mut context.clone(); - context.inside_macro = true; + context.inside_macro.replace(true); + let result = rewrite_macro_inner(mac, extra_ident, context, shape, position); + context.inside_macro.replace(false); + result +} + +pub fn rewrite_macro_inner( + mac: &ast::Mac, + extra_ident: Option, + context: &RewriteContext, + shape: Shape, + position: MacroPosition, +) -> Option { if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { - context.inside_macro = false; + context.inside_macro.replace(false); return expr.rewrite(context, shape); } } @@ -295,7 +306,7 @@ pub fn rewrite_macro( // then we can rewrite this as an usual array literal. // Otherwise, we must preserve the original existence of trailing comma. if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { - context.inside_macro = false; + context.inside_macro.replace(false); trailing_comma = false; } // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. diff --git a/src/overflow.rs b/src/overflow.rs index c76b67c461e..79f93899fa3 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -384,7 +384,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { result.push_str(self.ident); result.push_str(self.prefix); if !self.context.use_block_indent() - || (self.context.inside_macro && !items_str.contains('\n') && fits_one_line) + || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line) || (is_extendable && extend_width <= shape.width) { if self.context.config.spaces_within_parens_and_brackets() && !items_str.is_empty() { diff --git a/src/patterns.rs b/src/patterns.rs index cfff023bafc..44e32462a8d 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -360,10 +360,6 @@ fn rewrite_tuple_pat( // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); - let mut context = context.clone(); - if let Some(&TuplePatField::Dotdot(..)) = pat_vec.last() { - context.inside_macro = true; - } let path_str = path_str.unwrap_or_default(); let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); for pat in pat_vec { diff --git a/src/rewrite.rs b/src/rewrite.rs index 01671227e39..7eb8c18bbe6 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -29,12 +29,12 @@ pub struct RewriteContext<'a> { pub parse_session: &'a ParseSess, pub codemap: &'a CodeMap, pub config: &'a Config, - pub inside_macro: bool, + pub inside_macro: RefCell, // Force block indent style even if we are using visual indent style. pub use_block: RefCell, // When `format_if_else_cond_comment` is true, unindent the comment on top // of the `else` or `else if`. - pub is_if_else_block: bool, + pub is_if_else_block: RefCell, // When rewriting chain, veto going multi line except the last element pub force_one_line_chain: RefCell, pub snippet_provider: &'a SnippetProvider<'a>, @@ -53,4 +53,12 @@ impl<'a> RewriteContext<'a> { pub fn budget(&self, used_width: usize) -> usize { self.config.max_width().checked_sub(used_width).unwrap_or(0) } + + pub fn inside_macro(&self) -> bool { + *self.inside_macro.borrow() + } + + pub fn is_if_else_block(&self) -> bool { + *self.is_if_else_block.borrow() + } } diff --git a/src/visitor.rs b/src/visitor.rs index 54a85062d43..22f892d4fb4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -696,9 +696,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { parse_session: self.parse_session, codemap: self.codemap, config: self.config, - inside_macro: false, + inside_macro: RefCell::new(false), use_block: RefCell::new(false), - is_if_else_block: false, + is_if_else_block: RefCell::new(false), force_one_line_chain: RefCell::new(false), snippet_provider: self.snippet_provider, } -- cgit 1.4.1-3-g733a5 From cf6c67e1a6645dca9bb053b5bd7541f7b4885e54 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 26 Mar 2018 07:32:48 +0900 Subject: Replace MacroStyle with ast::DelimToken --- src/macros.rs | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b3f443a628e..0387fb3a963 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -45,14 +45,6 @@ use utils::{format_visibility, mk_sp, wrap_str}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; -// FIXME: use the enum from libsyntax? -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -enum MacroStyle { - Parens, - Brackets, - Braces, -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MacroPosition { Item, @@ -61,16 +53,6 @@ pub enum MacroPosition { Pat, } -impl MacroStyle { - fn opener(&self) -> &'static str { - match *self { - MacroStyle::Parens => "(", - MacroStyle::Brackets => "[", - MacroStyle::Braces => "{", - } - } -} - #[derive(Debug)] pub enum MacroArg { Expr(ptr::P), @@ -177,7 +159,7 @@ pub fn rewrite_macro_inner( let macro_name = rewrite_macro_name(&mac.node.path, extra_ident); let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { - MacroStyle::Brackets + DelimToken::Bracket } else { original_style }; @@ -186,12 +168,13 @@ pub fn rewrite_macro_inner( let has_comment = contains_comment(context.snippet(mac.span)); if ts.is_empty() && !has_comment { return match style { - MacroStyle::Parens if position == MacroPosition::Item => { + DelimToken::Paren if position == MacroPosition::Item => { Some(format!("{}();", macro_name)) } - MacroStyle::Parens => Some(format!("{}()", macro_name)), - MacroStyle::Brackets => Some(format!("{}[]", macro_name)), - MacroStyle::Braces => Some(format!("{}{{}}", macro_name)), + DelimToken::Paren => Some(format!("{}()", macro_name)), + DelimToken::Bracket => Some(format!("{}[]", macro_name)), + DelimToken::Brace => Some(format!("{}{{}}", macro_name)), + _ => unreachable!(), }; } // Format well-known macros which cannot be parsed as a valid AST. @@ -207,7 +190,7 @@ pub fn rewrite_macro_inner( let mut vec_with_semi = false; let mut trailing_comma = false; - if MacroStyle::Braces != style { + if DelimToken::Brace != style { loop { match parse_macro_arg(&mut parser) { Some(arg) => arg_vec.push(arg), @@ -250,7 +233,7 @@ pub fn rewrite_macro_inner( } match style { - MacroStyle::Parens => { + DelimToken::Paren => { // Format macro invocation as function call, preserve the trailing // comma because not all macros support them. overflow::rewrite_with_parens( @@ -270,8 +253,7 @@ pub fn rewrite_macro_inner( _ => rw, }) } - MacroStyle::Brackets => { - let mac_shape = shape.offset_left(macro_name.len())?; + DelimToken::Bracket => { // Handle special case: `vec![expr; expr]` if vec_with_semi { let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { @@ -326,10 +308,11 @@ pub fn rewrite_macro_inner( Some(format!("{}{}{}", macro_name, rewrite, comma)) } } - MacroStyle::Braces => { + DelimToken::Brace => { // Skip macro invocations with braces, for now. indent_macro_snippet(context, context.snippet(mac.span), shape.indent) } + _ => unreachable!(), } } @@ -1010,18 +993,18 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option MacroStyle { +fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> DelimToken { let snippet = context.snippet(mac.span); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); if paren_pos < bracket_pos && paren_pos < brace_pos { - MacroStyle::Parens + DelimToken::Paren } else if bracket_pos < brace_pos { - MacroStyle::Brackets + DelimToken::Bracket } else { - MacroStyle::Braces + DelimToken::Brace } } -- cgit 1.4.1-3-g733a5 From affa4ce1ecdcfd031122004417afa5b2ccaa92f7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 26 Mar 2018 07:34:17 +0900 Subject: Factor out default_tactic and fix indentation rustfmt fails to handle binary expressions with comments in-between. --- src/overflow.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index 79f93899fa3..9d586c0ffa4 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -183,6 +183,15 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { } } + fn default_tactic(&self, list_items: &[ListItem]) -> DefinitiveListTactic { + definitive_tactic( + list_items, + ListTactic::LimitedHorizontalVertical(self.item_max_width), + Separator::Comma, + self.one_line_width, + ) + } + fn try_overflow_last_item(&self, list_items: &mut Vec) -> DefinitiveListTactic { // 1 = "(" let combine_arg_with_callee = self.items.len() == 1 && self.items[0].to_expr().is_some() @@ -258,26 +267,16 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { .last() .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape)); - let default_tactic = || { - definitive_tactic( - &*list_items, - ListTactic::LimitedHorizontalVertical(self.item_max_width), - Separator::Comma, - self.one_line_width, - ) - }; - // Use horizontal layout for a function with a single argument as long as // everything fits in a single line. - if self.items.len() == 1 - && self.one_line_width != 0 // Vertical layout is forced. - && !list_items[0].has_comment() + // `self.one_line_width == 0` means vertical layout is forced. + if self.items.len() == 1 && self.one_line_width != 0 && !list_items[0].has_comment() && !list_items[0].inner_as_ref().contains('\n') && ::lists::total_item_width(&list_items[0]) <= self.one_line_width { tactic = DefinitiveListTactic::Horizontal; } else { - tactic = default_tactic(); + tactic = self.default_tactic(list_items); if tactic == DefinitiveListTactic::Vertical { if let Some((all_simple, num_args_before)) = -- cgit 1.4.1-3-g733a5 From 98c6f7b7313c0053f822a10ab473f31bf1f480ef Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 26 Mar 2018 07:36:44 +0900 Subject: Format array using overflow module This commit applies heuristics used for function calls to array and vice versa. --- src/expr.rs | 160 +++++++------------------------------------------------- src/lists.rs | 22 +++++--- src/macros.rs | 31 +++++++---- src/overflow.rs | 67 ++++++++++++++++++++++-- 4 files changed, 116 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 10f2cd2aba7..c719f9938ee 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -13,6 +13,7 @@ use std::cmp::min; use config::lists::*; use syntax::codemap::{BytePos, CodeMap, Span}; +use syntax::parse::token::DelimToken; use syntax::{ast, ptr}; use chains::rewrite_chain; @@ -64,14 +65,13 @@ pub fn format_expr( let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( + "", &ptr_vec_to_ref_vec(expr_vec), - mk_sp( - context.snippet_provider.span_after(expr.span, "["), - expr.span.hi(), - ), + expr.span, context, shape, - false, + None, + None, ), ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), ast::ExprKind::Call(ref callee, ref args) => { @@ -422,147 +422,23 @@ where } pub fn rewrite_array( + name: &str, exprs: &[&T], span: Span, context: &RewriteContext, shape: Shape, - trailing_comma: bool, + force_separator_tactic: Option, + delim_token: Option, ) -> Option { - let bracket_size = if context.config.spaces_within_parens_and_brackets() { - 2 // "[ " - } else { - 1 // "[" - }; - - let nested_shape = match context.config.indent_style() { - IndentStyle::Block => shape - .block() - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1)?, - IndentStyle::Visual => shape - .visual_indent(bracket_size) - .sub_width(bracket_size * 2)?, - }; - - let items = itemize_list( - context.snippet_provider, - exprs.iter(), - "]", - ",", - |item| item.span().lo(), - |item| item.span().hi(), - |item| item.rewrite(context, nested_shape), - span.lo(), - span.hi(), - false, - ).collect::>(); - - if items.is_empty() { - if context.config.spaces_within_parens_and_brackets() { - return Some("[ ]".to_string()); - } else { - return Some("[]".to_string()); - } - } - - let tactic = array_tactic(context, shape, nested_shape, exprs, &items, bracket_size); - let ends_with_newline = tactic.ends_with_newline(context.config.indent_style()); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if trailing_comma { - SeparatorTactic::Always - } else if context.inside_macro() && !exprs.is_empty() { - let ends_with_bracket = context.snippet(span).ends_with(']'); - let bracket_offset = if ends_with_bracket { 1 } else { 0 }; - let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset))); - let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?; - if &snippet[last_char_index..last_char_index + 1] == "," { - SeparatorTactic::Always - } else { - SeparatorTactic::Never - } - } else if context.config.indent_style() == IndentStyle::Visual { - SeparatorTactic::Never - } else { - SeparatorTactic::Vertical - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline, - preserve_newline: false, - config: context.config, - }; - let list_str = write_list(&items, &fmt)?; - - let result = if context.config.indent_style() == IndentStyle::Visual - || tactic == DefinitiveListTactic::Horizontal - { - if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { - format!("[ {} ]", list_str) - } else { - format!("[{}]", list_str) - } - } else { - format!( - "[{}{}{}]", - nested_shape.indent.to_string_with_newline(context.config), - list_str, - shape.block().indent.to_string_with_newline(context.config) - ) - }; - - Some(result) -} - -fn array_tactic( - context: &RewriteContext, - shape: Shape, - nested_shape: Shape, - exprs: &[&T], - items: &[ListItem], - bracket_size: usize, -) -> DefinitiveListTactic { - let has_long_item = items - .iter() - .any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false)); - - match context.config.indent_style() { - IndentStyle::Block => { - let tactic = match shape.width.checked_sub(2 * bracket_size) { - Some(width) => { - let tactic = ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ); - definitive_tactic(items, tactic, Separator::Comma, width) - } - None => DefinitiveListTactic::Vertical, - }; - if tactic == DefinitiveListTactic::Vertical && !has_long_item - && is_every_expr_simple(exprs) - { - DefinitiveListTactic::Mixed - } else { - tactic - } - } - IndentStyle::Visual => { - if has_long_item || items.iter().any(ListItem::is_multiline) { - definitive_tactic( - items, - ListTactic::LimitedHorizontalVertical( - context.config.width_heuristics().array_width, - ), - Separator::Comma, - nested_shape.width, - ) - } else { - DefinitiveListTactic::Mixed - } - } - } + overflow::rewrite_with_square_brackets( + context, + name, + exprs, + shape, + span, + force_separator_tactic, + delim_token, + ) } fn rewrite_empty_block( @@ -1489,7 +1365,7 @@ fn is_simple_expr(expr: &ast::Expr) -> bool { } } -fn is_every_expr_simple(lists: &[&T]) -> bool { +pub fn is_every_expr_simple(lists: &[&T]) -> bool { lists .iter() .all(|arg| arg.to_expr().map_or(false, is_simple_expr)) diff --git a/src/lists.rs b/src/lists.rs index fdb022db077..05b1a7ce296 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -101,7 +101,7 @@ impl ListItem { .map_or(false, |s| s.contains('\n')) } - pub fn has_comment(&self) -> bool { + pub fn has_single_line_comment(&self) -> bool { self.pre_comment .as_ref() .map_or(false, |comment| comment.trim_left().starts_with("//")) @@ -110,6 +110,10 @@ impl ListItem { .map_or(false, |comment| comment.trim_left().starts_with("//")) } + pub fn has_comment(&self) -> bool { + self.pre_comment.is_some() || self.post_comment.is_some() + } + pub fn from_str>(s: S) -> ListItem { ListItem { pre_comment: None, @@ -164,7 +168,7 @@ where let pre_line_comments = items .clone() .into_iter() - .any(|item| item.as_ref().has_comment()); + .any(|item| item.as_ref().has_single_line_comment()); let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, @@ -266,11 +270,15 @@ where result.push_str(indent_str); line_len = 0; if formatting.ends_with_newline { - if last { - separate = true; - } else { - trailing_separator = true; - } + trailing_separator = true; + } + } + + if last && formatting.ends_with_newline { + match formatting.trailing_separator { + SeparatorTactic::Always => separate = true, + SeparatorTactic::Vertical if result.contains('\n') => separate = true, + _ => (), } } diff --git a/src/macros.rs b/src/macros.rs index 0387fb3a963..c65cc74b5f4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -256,6 +256,7 @@ pub fn rewrite_macro_inner( DelimToken::Bracket => { // Handle special case: `vec![expr; expr]` if vec_with_semi { + let mac_shape = shape.offset_left(macro_name.len())?; let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { ("[ ", " ]") } else { @@ -287,25 +288,35 @@ pub fn rewrite_macro_inner( // If we are rewriting `vec!` macro or other special macros, // then we can rewrite this as an usual array literal. // Otherwise, we must preserve the original existence of trailing comma. - if FORCED_BRACKET_MACROS.contains(¯o_name.as_str()) { + let macro_name = ¯o_name.as_str(); + let mut force_trailing_comma = if trailing_comma { + Some(SeparatorTactic::Always) + } else { + Some(SeparatorTactic::Never) + }; + if FORCED_BRACKET_MACROS.contains(macro_name) { context.inside_macro.replace(false); - trailing_comma = false; + if context.use_block_indent() { + force_trailing_comma = Some(SeparatorTactic::Vertical); + }; } // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. - let sp = mk_sp( - context - .snippet_provider - .span_after(mac.span, original_style.opener()), - mac.span.hi() - BytePos(1), - ); let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; - let rewrite = rewrite_array(arg_vec, sp, context, mac_shape, trailing_comma)?; + let rewrite = rewrite_array( + macro_name, + arg_vec, + mac.span, + context, + shape, + force_trailing_comma, + Some(original_style), + )?; let comma = match position { MacroPosition::Item => ";", _ => "", }; - Some(format!("{}{}{}", macro_name, rewrite, comma)) + Some(format!("{}{}", rewrite, comma)) } } DelimToken::Brace => { diff --git a/src/overflow.rs b/src/overflow.rs index 9d586c0ffa4..6383d032273 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -14,10 +14,11 @@ use config::lists::*; use syntax::ast; use syntax::codemap::Span; +use syntax::parse::token::DelimToken; use closures; use codemap::SpanUtils; -use expr::{is_nested_call, maybe_get_args_offset, ToExpr}; +use expr::{is_every_expr_simple, is_nested_call, maybe_get_args_offset, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; @@ -26,6 +27,8 @@ use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_ use std::cmp::min; +const SHORT_ITEM_THRESHOLD: usize = 10; + pub fn rewrite_with_parens( context: &RewriteContext, ident: &str, @@ -48,6 +51,7 @@ where ")", item_max_width, force_separator_tactic, + None, ).rewrite(shape) } @@ -71,6 +75,38 @@ where ">", context.config.max_width(), None, + None, + ).rewrite(shape) +} + +pub fn rewrite_with_square_brackets( + context: &RewriteContext, + name: &str, + items: &[&T], + shape: Shape, + span: Span, + force_separator_tactic: Option, + delim_token: Option, +) -> Option +where + T: Rewrite + ToExpr + Spanned, +{ + let (lhs, rhs) = match delim_token { + Some(DelimToken::Paren) => ("(", ")"), + Some(DelimToken::Brace) => ("{", "}"), + _ => ("[", "]"), + }; + Context::new( + context, + items, + name, + shape, + span, + lhs, + rhs, + context.config.width_heuristics().array_width, + force_separator_tactic, + Some(("[", "]")), ).rewrite(shape) } @@ -86,6 +122,7 @@ struct Context<'a, T: 'a> { item_max_width: usize, one_line_width: usize, force_separator_tactic: Option, + custom_delims: Option<(&'a str, &'a str)>, } impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { @@ -99,6 +136,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { suffix: &'static str, item_max_width: usize, force_separator_tactic: Option, + custom_delims: Option<(&'a str, &'a str)>, ) -> Context<'a, T> { // 2 = `( `, 1 = `(` let paren_overhead = if context.config.spaces_within_parens_and_brackets() { @@ -135,6 +173,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { item_max_width, one_line_width, force_separator_tactic, + custom_delims, } } @@ -301,6 +340,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { if one_line { tactic = DefinitiveListTactic::SpecialMacro(num_args_before); }; + } else if is_every_expr_simple(self.items) && no_long_items(list_items) { + tactic = DefinitiveListTactic::Mixed; } } } @@ -339,13 +380,20 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { tactic } else if !self.context.use_block_indent() { SeparatorTactic::Never + } else if tactic == DefinitiveListTactic::Mixed { + // We are using mixed layout because everything did not fit within a single line. + SeparatorTactic::Always } else { self.context.config.trailing_comma() }, separator_place: SeparatorPlace::Back, shape: self.nested_shape, - ends_with_newline: self.context.use_block_indent() - && tactic == DefinitiveListTactic::Vertical, + ends_with_newline: match tactic { + DefinitiveListTactic::Vertical | DefinitiveListTactic::Mixed => { + self.context.use_block_indent() + } + _ => false, + }, preserve_newline: false, config: self.context.config, }; @@ -363,6 +411,10 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { ..shape }; + let (prefix, suffix) = match self.custom_delims { + Some((lhs, rhs)) => (lhs, rhs), + _ => (self.prefix, self.suffix), + }; let paren_overhead = paren_overhead(self.context); let fits_one_line = items_str.len() + paren_overhead <= shape.width; let extend_width = if items_str.is_empty() { @@ -381,7 +433,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { self.ident.len() + items_str.len() + 2 + indent_str.len() + nested_indent_str.len(), ); result.push_str(self.ident); - result.push_str(self.prefix); + result.push_str(prefix); if !self.context.use_block_indent() || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line) || (is_extendable && extend_width <= shape.width) @@ -400,7 +452,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { } result.push_str(&indent_str); } - result.push_str(self.suffix); + result.push_str(suffix); result } @@ -488,3 +540,8 @@ fn shape_from_indent_style( } } } + +fn no_long_items(list: &[ListItem]) -> bool { + list.iter() + .all(|item| !item.has_comment() && item.inner_as_ref().len() <= SHORT_ITEM_THRESHOLD) +} -- cgit 1.4.1-3-g733a5 From 48424ea7654bbf1a0b3d747be05b45f799c7e28d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 26 Mar 2018 07:38:39 +0900 Subject: Update tests and cargo fmt --- Configurations.md | 6 ++++-- src/closures.rs | 20 ++++++-------------- src/expr.rs | 8 +------- src/format-diff/main.rs | 2 +- src/rustfmt_diff.rs | 46 ++++++++++++++++++++-------------------------- tests/lib.rs | 24 +++++++++++------------- tests/target/chains.rs | 5 +---- tests/target/expr-block.rs | 14 +------------- tests/target/match.rs | 5 +---- 9 files changed, 46 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index f7fa88b61f2..da027d10e70 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1688,7 +1688,8 @@ Number of spaces per tab fn lorem() { let ipsum = dolor(); let sit = vec![ - "amet consectetur adipiscing elit amet consectetur adipiscing elit amet consectetur.", + "amet consectetur adipiscing elit amet", + "consectetur adipiscing elit amet consectetur.", ]; } ``` @@ -1699,7 +1700,8 @@ fn lorem() { fn lorem() { let ipsum = dolor(); let sit = vec![ - "amet consectetur adipiscing elit amet consectetur adipiscing elit amet consectetur.", + "amet consectetur adipiscing elit amet", + "consectetur adipiscing elit amet consectetur.", ]; } ``` diff --git a/src/closures.rs b/src/closures.rs index 7fdc0e85686..20ba0118f5f 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -127,13 +127,11 @@ fn rewrite_closure_with_block( } let block = ast::Block { - stmts: vec![ - ast::Stmt { - id: ast::NodeId::new(0), - node: ast::StmtKind::Expr(ptr::P(body.clone())), - span: body.span, - }, - ], + stmts: vec![ast::Stmt { + id: ast::NodeId::new(0), + node: ast::StmtKind::Expr(ptr::P(body.clone())), + span: body.span, + }], id: ast::NodeId::new(0), rules: ast::BlockCheckMode::Default, span: body.span, @@ -300,13 +298,7 @@ pub fn rewrite_last_closure( _ => body, }; let (prefix, extra_offset) = rewrite_closure_fn_decl( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, + capture, movability, fn_decl, body, expr.span, context, shape, )?; // If the closure goes multi line before its body, do not overflow the closure. if prefix.contains('\n') { diff --git a/src/expr.rs b/src/expr.rs index c719f9938ee..14ba8d0f7a0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -173,13 +173,7 @@ pub fn format_expr( }, ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, + capture, movability, fn_decl, body, expr.span, context, shape, ) } ast::ExprKind::Try(..) diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index c871395f72a..402f7ab507a 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -261,7 +261,7 @@ fn scan_simple_git_diff() { Range { file: "src/ir/traversal.rs".to_owned(), range: [35, 43], - } + }, ] ); } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index db72a775f41..d5c97b95560 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -221,18 +221,16 @@ mod test { let diff = make_diff(src, dest, 1); assert_eq!( diff, - vec![ - Mismatch { - line_number: 2, - line_number_orig: 2, - lines: vec![ - Context("two".to_owned()), - Resulting("three".to_owned()), - Expected("trois".to_owned()), - Context("four".to_owned()), - ], - }, - ] + vec![Mismatch { + line_number: 2, + line_number_orig: 2, + lines: vec![ + Context("two".to_owned()), + Resulting("three".to_owned()), + Expected("trois".to_owned()), + Context("four".to_owned()), + ], + }] ); } @@ -274,13 +272,11 @@ mod test { let diff = make_diff(src, dest, 0); assert_eq!( diff, - vec![ - Mismatch { - line_number: 3, - line_number_orig: 3, - lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], - }, - ] + vec![Mismatch { + line_number: 3, + line_number_orig: 3, + lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())], + }] ); } @@ -291,13 +287,11 @@ mod test { let diff = make_diff(src, dest, 1); assert_eq!( diff, - vec![ - Mismatch { - line_number: 5, - line_number_orig: 5, - lines: vec![Context("five".to_owned()), Expected("".to_owned())], - }, - ] + vec![Mismatch { + line_number: 5, + line_number_orig: 5, + lines: vec![Context("five".to_owned()), Expected("".to_owned())], + }] ); } } diff --git a/tests/lib.rs b/tests/lib.rs index 8c4d67575dc..3b73247f7f8 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -540,19 +540,17 @@ fn rustfmt_diff_make_diff_tests() { let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); assert_eq!( diff, - vec![ - Mismatch { - line_number: 1, - line_number_orig: 1, - lines: vec![ - DiffLine::Context("a".into()), - DiffLine::Resulting("b".into()), - DiffLine::Expected("e".into()), - DiffLine::Context("c".into()), - DiffLine::Context("d".into()), - ], - }, - ] + vec![Mismatch { + line_number: 1, + line_number_orig: 1, + lines: vec![ + DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into()), + ], + }] ); } diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 8a41eec2bde..d3e3cad5ebb 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -233,10 +233,7 @@ impl Foo { if let Some(mi) = attr.meta() { if let Some(value) = mi.value_str() { doc_strings.push(DocFragment::Include( - line, - attr.span, - filename, - contents, + line, attr.span, filename, contents, )); } } diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 277990c5a60..2bec429e8c8 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -114,19 +114,7 @@ fn function_calls() { fn macros() { baz!( - do_not, - add, - trailing, - commas, - inside, - of, - function, - like, - macros, - even, - if_they, - are, - long + do_not, add, trailing, commas, inside, of, function, like, macros, even, if_they, are, long ); baz!(one_item_macro_which_is_also_loooooooooooooooooooooooooooooooooooooooooooooooong); diff --git a/tests/target/match.rs b/tests/target/match.rs index 087fb80ef09..fe565f4c154 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -218,10 +218,7 @@ fn issue355() { xc => vec![1, 2], // comment yc => vec![3; 4], // comment yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( - aaaaaaaaaa, - bbbbbbbbbb, - cccccccccc, - dddddddddd, + aaaaaaaaaa, bbbbbbbbbb, cccccccccc, dddddddddd, ), } } -- cgit 1.4.1-3-g733a5 From 72d8c9143b0ed59b12e721d81ee7719ab2ffa48f Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 26 Mar 2018 22:29:01 +0200 Subject: Allow stabilization of match_default_bindings --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3f4b96b0b6b..77589038c66 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,8 @@ #![feature(custom_attribute)] #![feature(decl_macro)] +// FIXME(cramertj) remove after match_default_bindings merges +#![allow(stable_features)] #![feature(match_default_bindings)] #![feature(type_ascription)] -- cgit 1.4.1-3-g733a5 From bf3bf8c235af8a9f0267782cddfa0ac99f4895bf Mon Sep 17 00:00:00 2001 From: rleungx Date: Mon, 26 Mar 2018 20:45:39 +0800 Subject: allow underscore --- src/macros.rs | 2 +- tests/source/macro_rules.rs | 20 ++++++++++++++++++++ tests/target/macro_rules.rs | 20 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b3f443a628e..bd8b86a49d4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -460,7 +460,7 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { } else if c == '(' && cur_name.is_empty() { // FIXME: Support macro def with repeat. return None; - } else if c.is_alphanumeric() { + } else if c.is_alphanumeric() || c == '_' { cur_name.push(c); } } diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index f390b426317..3f7f5d621c3 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -168,3 +168,23 @@ macro_rules! add_message_to_notes { } }} } + +// #2560 +macro_rules! binary { + ($_self:ident,$expr:expr, $lhs:expr,$func:ident) => { + while $_self.matched($expr) { + let op = $_self.get_binary_op()?; + + let rhs = Box::new($_self.$func()?); + + $lhs = Spanned { + span: $lhs.get_span().to(rhs.get_span()), + value: Expression::Binary { + lhs: Box::new($lhs), + op, + rhs, + }, + } + } + }; +} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 12fdb7b026e..7d527b0c3fd 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -200,3 +200,23 @@ macro_rules! add_message_to_notes { } }}; } + +// #2560 +macro_rules! binary { + ($_self:ident, $expr:expr, $lhs:expr, $func:ident) => { + while $_self.matched($expr) { + let op = $_self.get_binary_op()?; + + let rhs = Box::new($_self.$func()?); + + $lhs = Spanned { + span: $lhs.get_span().to(rhs.get_span()), + value: Expression::Binary { + lhs: Box::new($lhs), + op, + rhs, + }, + } + } + }; +} -- cgit 1.4.1-3-g733a5 From efd295a4e10395436286d99b911e6822cd381ed9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 28 Mar 2018 16:56:39 +0900 Subject: Follow indent style config when formatting attrs --- src/attr.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 04bbcdfbbcd..3c4cc390e78 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,6 +10,7 @@ //! Format attributes and meta items. +use config::IndentStyle; use config::lists::*; use syntax::ast; use syntax::codemap::Span; @@ -202,11 +203,16 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::Word => String::from(&*self.name.as_str()), ast::MetaItemKind::List(ref list) => { let name = self.name.as_str(); - // 1 = `(`, 2 = `]` and `)` - let item_shape = shape - .visual_indent(0) - .shrink_left(name.len() + 1) - .and_then(|s| s.sub_width(2))?; + let item_shape = match context.config.indent_style() { + IndentStyle::Block => shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), + // 1 = `(`, 2 = `]` and `)` + IndentStyle::Visual => shape + .visual_indent(0) + .shrink_left(name.len() + 1) + .and_then(|s| s.sub_width(2))?, + }; let items = itemize_list( context.snippet_provider, list.iter(), @@ -240,7 +246,17 @@ impl Rewrite for ast::MetaItem { preserve_newline: false, config: context.config, }; - format!("{}({})", name, write_list(&item_vec, &fmt)?) + let item_str = write_list(&item_vec, &fmt)?; + let one_line_budget = shape.offset_left(name.len())?.sub_width(2)?.width; + if context.config.indent_style() == IndentStyle::Visual + || (!item_str.contains('\n') && item_str.len() <= one_line_budget) + { + format!("{}({})", name, item_str) + } else { + let indent = shape.indent.to_string_with_newline(context.config); + let nested_indent = item_shape.indent.to_string_with_newline(context.config); + format!("{}({}{}{})", name, nested_indent, item_str, indent) + } } ast::MetaItemKind::NameValue(ref literal) => { let name = self.name.as_str(); -- cgit 1.4.1-3-g733a5 From a49e00b4d7132dea8004de74b3580f369debd32a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 28 Mar 2018 18:14:51 +0900 Subject: Avoid panicking on macro call with a single comma `parse_item` from libsyntax may return `None`, so we need to discard the result in that case. --- src/macros.rs | 18 +++++++++--------- src/spanned.rs | 2 +- tests/source/macros.rs | 2 ++ tests/target/macros.rs | 2 ++ 4 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index bd8b86a49d4..649abdca3e7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -76,8 +76,7 @@ pub enum MacroArg { Expr(ptr::P), Ty(ptr::P), Pat(ptr::P), - // `parse_item` returns `Option>`. - Item(Option>), + Item(ptr::P), } impl Rewrite for ast::Item { @@ -96,14 +95,14 @@ impl Rewrite for MacroArg { MacroArg::Expr(ref expr) => expr.rewrite(context, shape), MacroArg::Ty(ref ty) => ty.rewrite(context, shape), MacroArg::Pat(ref pat) => pat.rewrite(context, shape), - MacroArg::Item(ref item) => item.as_ref().and_then(|item| item.rewrite(context, shape)), + MacroArg::Item(ref item) => item.rewrite(context, shape), } } } fn parse_macro_arg(parser: &mut Parser) -> Option { macro_rules! parse_macro_arg { - ($macro_arg:ident, $parser:ident) => { + ($macro_arg:ident, $parser:ident, $f:expr) => { let mut cloned_parser = (*parser).clone(); match cloned_parser.$parser() { Ok(x) => { @@ -112,7 +111,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { } else { // Parsing succeeded. *parser = cloned_parser; - return Some(MacroArg::$macro_arg(x.clone())); + return Some(MacroArg::$macro_arg($f(x)?)); } } Err(mut e) => { @@ -123,10 +122,11 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { }; } - parse_macro_arg!(Expr, parse_expr); - parse_macro_arg!(Ty, parse_ty); - parse_macro_arg!(Pat, parse_pat); - parse_macro_arg!(Item, parse_item); + parse_macro_arg!(Expr, parse_expr, |x: ptr::P| Some(x)); + parse_macro_arg!(Ty, parse_ty, |x: ptr::P| Some(x)); + parse_macro_arg!(Pat, parse_pat, |x: ptr::P| Some(x)); + // `parse_item` returns `Option>`. + parse_macro_arg!(Item, parse_item, |x: Option>| x); None } diff --git a/src/spanned.rs b/src/spanned.rs index bcbf6bd6060..41fa0da8dd1 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -187,7 +187,7 @@ impl Spanned for MacroArg { MacroArg::Expr(ref expr) => expr.span(), MacroArg::Ty(ref ty) => ty.span(), MacroArg::Pat(ref pat) => pat.span(), - MacroArg::Item(ref item) => item.as_ref().unwrap().span(), + MacroArg::Item(ref item) => item.span(), } } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 11e6d52c6c8..030c56b5f82 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -10,6 +10,8 @@ peg_file! modname ("mygrammarfile.rustpeg"); fn main() { foo! ( ); + foo!(,); + bar!( a , b , c ); bar!( a , b , c , ); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index f5d8e11e35e..0a103d5d61b 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -15,6 +15,8 @@ peg_file! modname("mygrammarfile.rustpeg"); fn main() { foo!(); + foo!(,); + bar!(a, b, c); bar!(a, b, c,); -- cgit 1.4.1-3-g733a5 From e68682f6dba57fedb32ae2219bdf4d237f229786 Mon Sep 17 00:00:00 2001 From: codeworm96 Date: Wed, 28 Mar 2018 23:38:34 +0800 Subject: Remove unreachable! from macros.rs replaced unreachable! with error handling using Option. Closes #2558 --- src/macros.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index bd8b86a49d4..61889f5764a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -687,7 +687,7 @@ impl MacroArgParser { self.buf.clear(); } - fn add_meta_variable(&mut self, iter: &mut Cursor) { + fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { match iter.next() { Some(TokenTree::Token(sp, Token::Ident(ref ident))) => { self.result.push(ParsedMacroArg { @@ -697,8 +697,9 @@ impl MacroArgParser { self.buf.clear(); self.is_meta_var = false; + Some(()) } - _ => unreachable!(), + _ => None, } } @@ -716,7 +717,7 @@ impl MacroArgParser { delim: DelimToken, iter: &mut Cursor, span: Span, - ) { + ) -> Option<()> { let mut buffer = String::new(); let mut first = false; let mut lo = span.lo(); @@ -740,7 +741,7 @@ impl MacroArgParser { buffer.push_str(&pprust::token_to_string(t)); hi = sp.hi(); } - _ => unreachable!(), + _ => return None, } } @@ -758,6 +759,7 @@ impl MacroArgParser { kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()), span: mk_sp(self.lo, self.hi), }); + Some(()) } fn update_buffer(&mut self, lo: BytePos, t: &Token) { @@ -802,7 +804,7 @@ impl MacroArgParser { } /// Returns a collection of parsed macro def's arguments. - pub fn parse(mut self, tokens: ThinTokenStream) -> Vec { + pub fn parse(mut self, tokens: ThinTokenStream) -> Option> { let mut iter = (tokens.into(): TokenStream).trees(); while let Some(ref tok) = iter.next() { @@ -819,7 +821,7 @@ impl MacroArgParser { self.start_tok = Token::Dollar; } TokenTree::Token(_, Token::Colon) if self.is_meta_var => { - self.add_meta_variable(&mut iter); + self.add_meta_variable(&mut iter)?; } TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t), TokenTree::Delimited(sp, delimited) => { @@ -834,10 +836,10 @@ impl MacroArgParser { // Parse the stuff inside delimiters. let mut parser = MacroArgParser::new(); parser.lo = sp.lo(); - let delimited_arg = parser.parse(delimited.tts.clone()); + let delimited_arg = parser.parse(delimited.tts.clone())?; if self.is_meta_var { - self.add_repeat(delimited_arg, delimited.delim, &mut iter, *sp); + self.add_repeat(delimited_arg, delimited.delim, &mut iter, *sp)?; } else { self.add_delimited(delimited_arg, delimited.delim, *sp); } @@ -853,7 +855,7 @@ impl MacroArgParser { self.add_other(); } - self.result + Some(self.result) } } @@ -915,7 +917,7 @@ fn format_macro_args( toks: ThinTokenStream, shape: Shape, ) -> Option { - let parsed_args = MacroArgParser::new().parse(toks); + let parsed_args = MacroArgParser::new().parse(toks)?; wrap_macro_args(context, &parsed_args, shape) } -- cgit 1.4.1-3-g733a5 From 73e7235317bf82a37c6ed2113edfc3af21a9288f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 30 Mar 2018 17:52:09 +0900 Subject: Cargo update (#2575) Update `rustc-ap-syntax` to 82.0.0. --- Cargo.lock | 138 +++++++++++++++++++++++++++++----------------------------- Cargo.toml | 2 +- src/macros.rs | 6 +-- 3 files changed, 73 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ca7d8f46527..535fa3b0a3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ name = "atty" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -23,7 +23,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -34,7 +34,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -49,13 +49,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -76,7 +76,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -91,7 +91,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "either" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -111,7 +111,7 @@ dependencies = [ "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -151,15 +151,15 @@ dependencies = [ [[package]] name = "itertools" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -178,7 +178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.39" +version = "0.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -194,7 +194,7 @@ name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -224,7 +224,7 @@ name = "parking_lot_core" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -257,7 +257,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -296,7 +296,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "73.0.0" +version = "82.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -305,7 +305,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "73.0.0" +version = "82.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -313,53 +313,53 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "73.0.0" +version = "82.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "73.0.0" +version = "82.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "73.0.0" +version = "82.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "73.0.0" +version = "82.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -374,19 +374,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "rustfmt-nightly" version = "0.4.1" dependencies = [ - "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -405,7 +405,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -415,27 +415,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.21.0" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -444,9 +444,9 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -461,7 +461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -489,7 +489,7 @@ dependencies = [ [[package]] name = "termcolor" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -500,7 +500,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -519,7 +519,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -604,13 +604,13 @@ dependencies = [ "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" -"checksum cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5caae26de3704081ef638f87f05a6891b04f2b7d5ce9429a3de21095528ae22" +"checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3" "checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" -"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" +"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834" "checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" @@ -618,11 +618,11 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum itertools 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "23d53b4c7394338044c3b9c8c5b2caaf7b40ae049ecd321578ebdc2e13738cd1" -"checksum itoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92a9df60778f789c37f76778ae8d0a2471c41baa8b059d98a5873c978f549587" +"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" +"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff" +"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" @@ -637,26 +637,26 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" -"checksum rustc-ap-rustc_cratesio_shim 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "421262e22426c06306e46057a75048f883dbc43886f78dbe1e750397a9c9b8e6" -"checksum rustc-ap-rustc_data_structures 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8460c1207f9abb48a9720aee8be418bcfac018b6eee7b740b98a410e7799d24a" -"checksum rustc-ap-rustc_errors 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad2077469162e52fcd84543334e18632088b9e342fe54e3b78c37d7077d09714" -"checksum rustc-ap-serialize 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69943901ae255dca5f63faeae2ff08b402d34a56d1eb50d34fbff6e83e6ace60" -"checksum rustc-ap-syntax 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a44363359a43df753e26a4d4fef72720af183de635ebae8699686cb5d5de813" -"checksum rustc-ap-syntax_pos 73.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "413f464657e8d5f3864de308dba1867526f21a44809b6f338b34e8c0caf88fb0" +"checksum rustc-ap-rustc_cratesio_shim 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7908267659b1b2f7cd380347b346131221c94146268ffe881913ba9022266493" +"checksum rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d783ebb12feb92af2f6611c32a8547c3af4955ecc4e07650fc746443275b0de" +"checksum rustc-ap-rustc_errors 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b6ca3d305e47ce828e7d96b512ddf9e56c4e04798e6a71c2d4615826d7b9231" +"checksum rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce8ff65713a3b610d7f80ee968246d4a8d0ea2cb7ffb23e363a0bba1380c88ad" +"checksum rustc-ap-syntax 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1b0af2c744b1e1fe8711c51dc4ecfc5d5c0a1e76dc9c1512254930d335a141" +"checksum rustc-ap-syntax_pos 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eebbc4112cc9dcc0de5369b1af40ec0f4077c92c6aa6596384c2599c80293c96" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe95aa0d46f04ce5c3a88bdcd4114ecd6144ed0b2725ebca2f1127744357807" -"checksum serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "23b163a6ce7e1aa897919f9d8e40bd1f8a6f95342ed57727ae31387a01a7a356" -"checksum serde_derive_internals 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "370aa477297975243dc914d0b0e1234927520ec311de507a560fbd1c80f7ab8c" +"checksum serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c70142ae874a42c70e03c63c6a49abe2ea0079b090bf6e136e99252fc1974bd6" +"checksum serde_derive 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "6fffe22d41dbddcead5b2c380c4714d44f2eb39292f7e7a0d966d2d45bf56408" +"checksum serde_derive_internals 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2f04ed291686ce195a5c8f554aaf36e50a721fbf829ee3b6151e6f85eccf945" "checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" -"checksum syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5bc2d6ff27891209efa5f63e9de78648d7801f085e4653701a692ce938d6fd" +"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" -"checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1" +"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" diff --git a/Cargo.toml b/Cargo.toml index f691a4c32db..a5f84370845 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-syntax = "73.0.0" +rustc-ap-syntax = "82.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/macros.rs b/src/macros.rs index d37b0a6a05a..c5671911936 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -683,7 +683,7 @@ impl MacroArgParser { fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { match iter.next() { - Some(TokenTree::Token(sp, Token::Ident(ref ident))) => { + Some(TokenTree::Token(sp, Token::Ident(ref ident, _))) => { self.result.push(ParsedMacroArg { kind: MacroArgKind::MetaVariable(ident.clone(), self.buf.clone()), span: mk_sp(self.lo, sp.hi()), @@ -953,7 +953,7 @@ fn force_space_before(tok: &Token) -> bool { fn ident_like(tok: &Token) -> bool { match *tok { - Token::Ident(_) | Token::Literal(..) | Token::Lifetime(_) => true, + Token::Ident(..) | Token::Literal(..) | Token::Lifetime(_) => true, _ => false, } } @@ -981,7 +981,7 @@ fn next_space(tok: &Token) -> SpaceState { | Token::CloseDelim(_) | Token::Whitespace => SpaceState::Never, - Token::Literal(..) | Token::Ident(_) | Token::Lifetime(_) => SpaceState::Ident, + Token::Literal(..) | Token::Ident(..) | Token::Lifetime(_) => SpaceState::Ident, _ => SpaceState::Always, } -- cgit 1.4.1-3-g733a5 From a8022f38621b7c8c71b225cf1782fb796a9a0e37 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 31 Mar 2018 13:18:53 +0900 Subject: Do not insert newline when item is empty This change is necessary when we remove unused imports (`use std::{};`). --- src/lists.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 05b1a7ce296..de39d03356f 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -257,7 +257,9 @@ where result.push(' '); } } - DefinitiveListTactic::Vertical if !first => { + DefinitiveListTactic::Vertical + if !first && !inner_item.is_empty() && !result.is_empty() => + { result.push('\n'); result.push_str(indent_str); } -- cgit 1.4.1-3-g733a5 From 2b682b8ed5331986b13c6f9ef8a0ff2933d098b5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 31 Mar 2018 13:19:55 +0900 Subject: Do not include separator to post comment This prevents the trailing `;` on use item to be treated as comment. --- src/lists.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index de39d03356f..61c9c413ac2 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -619,6 +619,8 @@ where let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { post_snippet[1..].trim_matches(white_space) + } else if post_snippet.starts_with(self.separator) { + post_snippet[self.separator.len()..].trim_matches(white_space) } else if post_snippet.ends_with(',') { post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) } else { -- cgit 1.4.1-3-g733a5 From 01311c63ec14f2a323a9e4819ab713f195ac4109 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 31 Mar 2018 13:21:13 +0900 Subject: Format normalized use item This commit implements `Rewrite` trait on `UseTree`, which is a normalized form of `ast::UseTree` for rustfmt. --- src/imports.rs | 901 ++++++++++++++++++++++++++++++++++++++++----------------- src/lists.rs | 4 +- src/reorder.rs | 567 +++++++----------------------------- 3 files changed, 727 insertions(+), 745 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index f631f4b9c26..8054fbdd451 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -11,7 +11,7 @@ use std::cmp::Ordering; use config::lists::*; -use syntax::ast; +use syntax::ast::{self, UseTreeKind}; use syntax::codemap::{BytePos, Span}; use codemap::SpanUtils; @@ -19,112 +19,30 @@ use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use types::{rewrite_path, PathContext}; -use utils::{format_visibility, mk_sp}; +use spanned::Spanned; +use utils::mk_sp; use visitor::FmtVisitor; +use std::borrow::Cow; + /// Returns a name imported by a `use` declaration. e.g. returns `Ordering` /// for `std::cmp::Ordering` and `self` for `std::cmp::self`. pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { path.segments.last().unwrap().identifier } -pub fn same_rename(opt_ident: &Option, path: &ast::Path) -> bool { - opt_ident.map_or(true, |ident| path_to_imported_ident(path) == ident) -} - -fn rewrite_prefix(path: &ast::Path, context: &RewriteContext, shape: Shape) -> Option { - if path.segments.len() > 1 && path_to_imported_ident(path).to_string() == "self" { - let path = &ast::Path { - span: path.span, - segments: path.segments[..path.segments.len() - 1].to_owned(), - }; - rewrite_path(context, PathContext::Import, None, path, shape) - } else { - rewrite_path(context, PathContext::Import, None, path, shape) - } -} - -impl Rewrite for ast::UseTree { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match self.kind { - ast::UseTreeKind::Nested(ref items) => { - rewrite_nested_use_tree(shape, &self.prefix, items, self.span, context) - } - ast::UseTreeKind::Glob => { - let prefix_shape = shape.sub_width(3)?; - - if !self.prefix.segments.is_empty() { - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape)?; - Some(format!("{}::*", path_str)) - } else { - Some("*".to_owned()) - } - } - ast::UseTreeKind::Simple(opt_ident) => { - if same_rename(&opt_ident, &self.prefix) { - rewrite_prefix(&self.prefix, context, shape) - .or_else(|| Some(context.snippet(self.prefix.span).to_owned())) - } else { - let ident_str = opt_ident?.to_string(); - // 4 = " as ".len() - let prefix_shape = shape.sub_width(ident_str.len() + 4)?; - let path_str = rewrite_prefix(&self.prefix, context, prefix_shape) - .unwrap_or_else(|| context.snippet(self.prefix.span).to_owned()); - Some(format!("{} as {}", path_str, ident_str)) - } - } - } - } -} - -fn is_unused_import(tree: &ast::UseTree, attrs: &[ast::Attribute]) -> bool { - attrs.is_empty() && is_unused_import_inner(tree) -} - -fn is_unused_import_inner(tree: &ast::UseTree) -> bool { - match tree.kind { - ast::UseTreeKind::Nested(ref items) => match items.len() { - 0 => true, - 1 => is_unused_import_inner(&items[0].0), - _ => false, - }, - _ => false, - } -} - -// Rewrite `use foo;` WITHOUT attributes. -pub fn rewrite_import( - context: &RewriteContext, - vis: &ast::Visibility, - tree: &ast::UseTree, - attrs: &[ast::Attribute], - shape: Shape, -) -> Option { - let vis = format_visibility(vis); - // 4 = `use `, 1 = `;` - let rw = shape - .offset_left(vis.len() + 4) - .and_then(|shape| shape.sub_width(1)) - .and_then(|shape| { - // If we have an empty nested group with no attributes, we erase it - if is_unused_import(tree, attrs) { - Some("".to_owned()) - } else { - tree.rewrite(context, shape) - } - }); - match rw { - Some(ref s) if !s.is_empty() => Some(format!("{}use {};", vis, s)), - _ => rw, - } -} - impl<'a> FmtVisitor<'a> { pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { let span = item.span; let shape = self.shape(); - let rw = rewrite_import(&self.get_context(), &item.vis, tree, &item.attrs, shape); + let rw = UseTree::from_ast( + &self.get_context(), + tree, + None, + Some(item.vis.clone()), + Some(item.span.lo()), + Some(item.attrs.clone()), + ).rewrite_top_level(&self.get_context(), shape); match rw { Some(ref s) if s.is_empty() => { // Format up to last newline @@ -152,204 +70,416 @@ impl<'a> FmtVisitor<'a> { } } -fn rewrite_nested_use_tree_single( - context: &RewriteContext, - path_str: &str, - tree: &ast::UseTree, - shape: Shape, -) -> Option { - match tree.kind { - ast::UseTreeKind::Simple(opt_rename) => { - let mut item_str = rewrite_prefix(&tree.prefix, context, shape)?; - if item_str == "self" { - item_str = "".to_owned(); - } +// Ordering of imports - let path_item_str = if path_str.is_empty() { - if item_str.is_empty() { - "self".to_owned() - } else { - item_str - } - } else if item_str.is_empty() { - path_str.to_owned() - } else { - format!("{}::{}", path_str, item_str) - }; - - Some(if same_rename(&opt_rename, &tree.prefix) { - path_item_str - } else { - format!("{} as {}", path_item_str, opt_rename?) - }) - } - ast::UseTreeKind::Glob | ast::UseTreeKind::Nested(..) => { - // 2 = "::" - let nested_shape = shape.offset_left(path_str.len() + 2)?; - tree.rewrite(context, nested_shape) - .map(|item| format!("{}::{}", path_str, item)) - } - } +// We order imports by translating to our own representation and then sorting. +// The Rust AST data structures are really bad for this. Rustfmt applies a bunch +// of normalisations to imports and since we want to sort based on the result +// of these (and to maintain idempotence) we must apply the same normalisations +// to the data structures for sorting. +// +// We sort `self` and `super` before other imports, then identifier imports, +// then glob imports, then lists of imports. We do not take aliases into account +// when ordering unless the imports are identical except for the alias (rare in +// practice). + +// FIXME(#2531) - we should unify the comparison code here with the formatting +// code elsewhere since we are essentially string-ifying twice. Furthermore, by +// parsing to our own format on comparison, we repeat a lot of work when +// sorting. + +// FIXME we do a lot of allocation to make our own representation. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum UseSegment { + Ident(String, Option), + Slf(Option), + Super(Option), + Glob, + List(Vec), } -#[derive(Eq, PartialEq)] -enum ImportItem<'a> { - // `self` or `self as a` - SelfImport(&'a str), - // name_one, name_two, ... - SnakeCase(&'a str), - // NameOne, NameTwo, ... - CamelCase(&'a str), - // NAME_ONE, NAME_TWO, ... - AllCaps(&'a str), - // Failed to format the import item - Invalid, +#[derive(Debug, Clone)] +pub struct UseTree { + pub path: Vec, + pub span: Span, + // Comment information within nested use tree. + list_item: Option, + // Additional fields for top level use items. + // Should we have another struct for top-level use items rather than reusing this? + visibility: Option, + attrs: Option>, +} + +impl PartialEq for UseTree { + fn eq(&self, other: &UseTree) -> bool { + self.path == other.path + } } +impl Eq for UseTree {} -impl<'a> ImportItem<'a> { - fn from_str(s: &str) -> ImportItem { - if s == "self" || s.starts_with("self as") { - ImportItem::SelfImport(s) - } else if s.chars().all(|c| c.is_lowercase() || c == '_' || c == ' ') { - ImportItem::SnakeCase(s) - } else if s.chars().all(|c| c.is_uppercase() || c == '_' || c == ' ') { - ImportItem::AllCaps(s) +impl UseSegment { + // Clone a version of self with any top-level alias removed. + fn remove_alias(&self) -> UseSegment { + match *self { + UseSegment::Ident(ref s, _) => UseSegment::Ident(s.clone(), None), + UseSegment::Slf(_) => UseSegment::Slf(None), + UseSegment::Super(_) => UseSegment::Super(None), + _ => self.clone(), + } + } + + fn from_path_segment(path_seg: &ast::PathSegment) -> Option { + let name = path_seg.identifier.name.as_str(); + if name == "{{root}}" { + return None; + } + Some(if name == "self" { + UseSegment::Slf(None) + } else if name == "super" { + UseSegment::Super(None) } else { - ImportItem::CamelCase(s) + UseSegment::Ident((*name).to_owned(), None) + }) + } +} + +impl UseTree { + // Rewrite use tree with `use ` and a trailing `;`. + pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { + let mut result = String::with_capacity(256); + if let Some(ref attrs) = self.attrs { + result.push_str(&attrs.rewrite(context, shape)?); + if !result.is_empty() { + result.push_str(&shape.indent.to_string_with_newline(context.config)); + } } + + let vis = self.visibility + .as_ref() + .map_or(Cow::from(""), |vis| ::utils::format_visibility(&vis)); + result.push_str(&self.rewrite(context, shape.offset_left(vis.len())?) + .map(|s| { + if s.is_empty() { + s.to_owned() + } else { + format!("{}use {};", vis, s) + } + })?); + Some(result) } - fn from_opt_str(s: Option<&String>) -> ImportItem { - s.map_or(ImportItem::Invalid, |s| ImportItem::from_str(s)) + pub fn from_ast_with_normalization( + context: &RewriteContext, + item: &ast::Item, + ) -> Option { + match item.node { + ast::ItemKind::Use(ref use_tree) => Some( + UseTree::from_ast( + context, + use_tree, + None, + Some(item.vis.clone()), + Some(item.span().lo()), + if item.attrs.is_empty() { + None + } else { + Some(item.attrs.clone()) + }, + ).normalize(context.config.reorder_imported_names()), + ), + _ => None, + } } - fn to_str(&self) -> Option<&str> { - match *self { - ImportItem::SelfImport(s) - | ImportItem::SnakeCase(s) - | ImportItem::CamelCase(s) - | ImportItem::AllCaps(s) => Some(s), - ImportItem::Invalid => None, + fn from_ast( + context: &RewriteContext, + a: &ast::UseTree, + list_item: Option, + visibility: Option, + opt_lo: Option, + attrs: Option>, + ) -> UseTree { + let span = if let Some(lo) = opt_lo { + mk_sp(lo, a.span.hi()) + } else { + a.span + }; + let mut result = UseTree { + path: vec![], + span, + list_item, + visibility, + attrs, + }; + for p in &a.prefix.segments { + if let Some(use_segment) = UseSegment::from_path_segment(p) { + result.path.push(use_segment); + } + } + match a.kind { + UseTreeKind::Glob => { + result.path.push(UseSegment::Glob); + } + UseTreeKind::Nested(ref list) => { + // Extract comments between nested use items. + // This needs to be done before sorting use items. + let items: Vec<_> = itemize_list( + context.snippet_provider, + list.iter().map(|(tree, _)| tree), + "}", + ",", + |tree| tree.span.lo(), + |tree| tree.span.hi(), + |_| Some("".to_owned()), // We only need comments for now. + context.snippet_provider.span_after(a.span, "{"), + a.span.hi(), + false, + ).collect(); + result.path.push(UseSegment::List( + list.iter() + .zip(items.into_iter()) + .map(|(t, list_item)| { + Self::from_ast(context, &t.0, Some(list_item), None, None, None) + }) + .collect(), + )); + } + UseTreeKind::Simple(ref rename) => { + let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); + let alias = rename.and_then(|ident| { + if ident == path_to_imported_ident(&a.prefix) { + None + } else { + Some(ident.to_string()) + } + }); + + let segment = if &name == "self" { + UseSegment::Slf(alias) + } else if &name == "super" { + UseSegment::Super(alias) + } else { + UseSegment::Ident(name, alias) + }; + + // `name` is already in result. + result.path.pop(); + result.path.push(segment); + } } + result } - fn to_u32(&self) -> u32 { - match *self { - ImportItem::SelfImport(..) => 0, - ImportItem::SnakeCase(..) => 1, - ImportItem::CamelCase(..) => 2, - ImportItem::AllCaps(..) => 3, - ImportItem::Invalid => 4, + // Do the adjustments that rustfmt does elsewhere to use paths. + pub fn normalize(mut self, do_sort: bool) -> UseTree { + let mut last = self.path.pop().expect("Empty use tree?"); + // Hack around borrow checker. + let mut normalize_sole_list = false; + let mut aliased_self = false; + + // Remove foo::{} or self without attributes. + match last { + _ if self.attrs.is_some() => (), + UseSegment::List(ref list) if list.is_empty() => { + self.path = vec![]; + return self; + } + UseSegment::Slf(None) if self.path.is_empty() && self.visibility.is_some() => { + self.path = vec![]; + return self; + } + _ => (), + } + + // Normalise foo::self -> foo. + if let UseSegment::Slf(None) = last { + if self.path.len() > 0 { + return self; + } + } + + // Normalise foo::self as bar -> foo as bar. + if let UseSegment::Slf(_) = last { + match self.path.last() { + None => {} + Some(UseSegment::Ident(_, None)) => { + aliased_self = true; + } + _ => unreachable!(), + } + } + + if aliased_self { + match self.path.last() { + Some(UseSegment::Ident(_, ref mut old_rename)) => { + assert!(old_rename.is_none()); + if let UseSegment::Slf(Some(rename)) = last { + *old_rename = Some(rename); + return self; + } + } + _ => unreachable!(), + } + } + + // Normalise foo::{bar} -> foo::bar + if let UseSegment::List(ref list) = last { + if list.len() == 1 { + normalize_sole_list = true; + } + } + + if normalize_sole_list { + match last { + UseSegment::List(list) => { + for seg in &list[0].path { + self.path.push(seg.clone()); + } + return self.normalize(do_sort); + } + _ => unreachable!(), + } + } + + // Recursively normalize elements of a list use (including sorting the list). + if let UseSegment::List(list) = last { + let mut list = list.into_iter() + .map(|ut| ut.normalize(do_sort)) + .collect::>(); + if do_sort { + list.sort(); + } + last = UseSegment::List(list); } + + self.path.push(last); + self } } -impl<'a> PartialOrd for ImportItem<'a> { - fn partial_cmp(&self, other: &ImportItem<'a>) -> Option { +impl PartialOrd for UseSegment { + fn partial_cmp(&self, other: &UseSegment) -> Option { Some(self.cmp(other)) } } - -impl<'a> Ord for ImportItem<'a> { - fn cmp(&self, other: &ImportItem<'a>) -> Ordering { - let res = self.to_u32().cmp(&other.to_u32()); - if res != Ordering::Equal { - return res; - } - self.to_str().map_or(Ordering::Greater, |self_str| { - other - .to_str() - .map_or(Ordering::Less, |other_str| self_str.cmp(other_str)) - }) +impl PartialOrd for UseTree { + fn partial_cmp(&self, other: &UseTree) -> Option { + Some(self.cmp(other)) } } +impl Ord for UseSegment { + fn cmp(&self, other: &UseSegment) -> Ordering { + use self::UseSegment::*; -// Pretty prints a multi-item import. -// If the path list is empty, it leaves the braces empty. -fn rewrite_nested_use_tree( - shape: Shape, - path: &ast::Path, - trees: &[(ast::UseTree, ast::NodeId)], - span: Span, - context: &RewriteContext, -) -> Option { - // Returns a different option to distinguish `::foo` and `foo` - let path_str = rewrite_path(context, PathContext::Import, None, path, shape)?; - - match trees.len() { - 0 => { - let shape = shape.offset_left(path_str.len() + 3)?; - return rewrite_path(context, PathContext::Import, None, path, shape) - .map(|path_str| format!("{}::{{}}", path_str)); + fn is_upper_snake_case(s: &str) -> bool { + s.chars().all(|c| c.is_uppercase() || c == '_') } - 1 => { - return rewrite_nested_use_tree_single(context, &path_str, &trees[0].0, shape); + + match (self, other) { + (&Slf(ref a), &Slf(ref b)) | (&Super(ref a), &Super(ref b)) => a.cmp(b), + (&Glob, &Glob) => Ordering::Equal, + (&Ident(ref ia, ref aa), &Ident(ref ib, ref ab)) => { + // snake_case < CamelCase < UPPER_SNAKE_CASE + if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) { + return Ordering::Greater; + } + if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) { + return Ordering::Less; + } + if is_upper_snake_case(ia) && !is_upper_snake_case(ib) { + return Ordering::Greater; + } + if !is_upper_snake_case(ia) && is_upper_snake_case(ib) { + return Ordering::Less; + } + let ident_ord = ia.cmp(ib); + if ident_ord != Ordering::Equal { + return ident_ord; + } + if aa.is_none() && ab.is_some() { + return Ordering::Less; + } + if aa.is_some() && ab.is_none() { + return Ordering::Greater; + } + aa.cmp(ab) + } + (&List(ref a), &List(ref b)) => { + for (a, b) in a.iter().zip(b.iter()) { + let ord = a.cmp(b); + if ord != Ordering::Equal { + return ord; + } + } + + a.len().cmp(&b.len()) + } + (&Slf(_), _) => Ordering::Less, + (_, &Slf(_)) => Ordering::Greater, + (&Super(_), _) => Ordering::Less, + (_, &Super(_)) => Ordering::Greater, + (&Ident(..), _) => Ordering::Less, + (_, &Ident(..)) => Ordering::Greater, + (&Glob, _) => Ordering::Less, + (_, &Glob) => Ordering::Greater, } - _ => (), } +} +impl Ord for UseTree { + fn cmp(&self, other: &UseTree) -> Ordering { + for (a, b) in self.path.iter().zip(other.path.iter()) { + let ord = a.cmp(b); + // The comparison without aliases is a hack to avoid situations like + // comparing `a::b` to `a as c` - where the latter should be ordered + // first since it is shorter. + if ord != Ordering::Equal && a.remove_alias().cmp(&b.remove_alias()) != Ordering::Equal + { + return ord; + } + } - let path_str = if path_str.is_empty() { - path_str - } else { - format!("{}::", path_str) - }; - - // 2 = "{}" - let remaining_width = shape.width.checked_sub(path_str.len() + 2).unwrap_or(0); - let nested_indent = match context.config.imports_indent() { - IndentStyle::Block => shape.indent.block_indent(context.config), - // 1 = `{` - IndentStyle::Visual => shape.visual_indent(path_str.len() + 1).indent, - }; + self.path.len().cmp(&other.path.len()) + } +} +fn rewrite_nested_use_tree( + context: &RewriteContext, + use_tree_list: &[UseTree], + shape: Shape, +) -> Option { + let mut list_items = Vec::with_capacity(use_tree_list.len()); let nested_shape = match context.config.imports_indent() { - IndentStyle::Block => Shape::indented(nested_indent, context.config).sub_width(1)?, - IndentStyle::Visual => Shape::legacy(remaining_width, nested_indent), - }; - - let mut items = { - // Dummy value, see explanation below. - let mut items = vec![ListItem::from_str("")]; - let iter = itemize_list( - context.snippet_provider, - trees.iter().map(|tree| &tree.0), - "}", - ",", - |tree| tree.span.lo(), - |tree| tree.span.hi(), - |tree| tree.rewrite(context, nested_shape), - context.snippet_provider.span_after(span, "{"), - span.hi(), - false, - ); - items.extend(iter); - items + IndentStyle::Block => shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + .sub_width(1)?, + IndentStyle::Visual => shape.visual_indent(0), }; - - // We prefixed the item list with a dummy value so that we can - // potentially move "self" to the front of the vector without touching - // the rest of the items. - let has_self = move_self_to_front(&mut items); - let first_index = if has_self { 0 } else { 1 }; - - if context.config.reorder_imported_names() { - items[1..].sort_by(|a, b| { - let a = ImportItem::from_opt_str(a.item.as_ref()); - let b = ImportItem::from_opt_str(b.item.as_ref()); - a.cmp(&b) - }); + for use_tree in use_tree_list { + let mut list_item = use_tree.list_item.clone()?; + list_item.item = use_tree.rewrite(context, nested_shape); + list_items.push(list_item); } - - let tactic = definitive_tactic( - &items[first_index..], - context.config.imports_layout(), - Separator::Comma, - remaining_width, - ); - + let tactic = if use_tree_list.iter().any(|use_segment| { + use_segment + .path + .last() + .map_or(false, |last_segment| match last_segment { + UseSegment::List(..) => true, + _ => false, + }) + }) { + DefinitiveListTactic::Vertical + } else { + definitive_tactic( + &list_items, + context.config.imports_layout(), + Separator::Comma, + shape.width.checked_sub(2).unwrap_or(0), + ) + }; let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; - let fmt = ListFormatting { tactic, separator: ",", @@ -364,33 +494,258 @@ fn rewrite_nested_use_tree( preserve_newline: true, config: context.config, }; - let list_str = write_list(&items[first_index..], &fmt)?; + + let list_str = write_list(&list_items, &fmt)?; let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block { format!( - "{}{{\n{}{}\n{}}}", - path_str, + "{{\n{}{}\n{}}}", nested_shape.indent.to_string(context.config), list_str, shape.indent.to_string(context.config) ) } else { - format!("{}{{{}}}", path_str, list_str) + format!("{{{}}}", list_str) }; + Some(result) } -// Returns true when self item was found. -fn move_self_to_front(items: &mut Vec) -> bool { - match items - .iter() - .position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) - { - Some(pos) => { - items[0] = items.remove(pos); - true +impl Rewrite for UseSegment { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + Some(match *self { + UseSegment::Ident(ref ident, Some(ref rename)) => format!("{} as {}", ident, rename), + UseSegment::Ident(ref ident, None) => ident.clone(), + UseSegment::Slf(Some(ref rename)) => format!("self as {}", rename), + UseSegment::Slf(None) => "self".to_owned(), + UseSegment::Super(Some(ref rename)) => format!("super as {}", rename), + UseSegment::Super(None) => "super".to_owned(), + UseSegment::Glob => "*".to_owned(), + UseSegment::List(ref use_tree_list) => rewrite_nested_use_tree( + context, + use_tree_list, + // 1 = "{" and "}" + shape.offset_left(1)?.sub_width(1)?, + )?, + }) + } +} + +impl Rewrite for UseTree { + // This does NOT format attributes and visibility or add a trailing `;`. + fn rewrite(&self, context: &RewriteContext, mut shape: Shape) -> Option { + let mut result = String::with_capacity(256); + let mut iter = self.path.iter().peekable(); + while let Some(ref segment) = iter.next() { + let segment_str = segment.rewrite(context, shape)?; + result.push_str(&segment_str); + if iter.peek().is_some() { + result.push_str("::"); + // 2 = "::" + shape = shape.offset_left(2 + segment_str.len())?; + } + } + Some(result) + } +} + +#[cfg(test)] +mod test { + use super::*; + use syntax::codemap::DUMMY_SP; + + // Parse the path part of an import. This parser is not robust and is only + // suitable for use in a test harness. + fn parse_use_tree(s: &str) -> UseTree { + use std::iter::Peekable; + use std::mem::swap; + use std::str::Chars; + + struct Parser<'a> { + input: Peekable>, + } + + impl<'a> Parser<'a> { + fn bump(&mut self) { + self.input.next().unwrap(); + } + fn eat(&mut self, c: char) { + assert!(self.input.next().unwrap() == c); + } + fn push_segment( + result: &mut Vec, + buf: &mut String, + alias_buf: &mut Option, + ) { + if !buf.is_empty() { + let mut alias = None; + swap(alias_buf, &mut alias); + if buf == "self" { + result.push(UseSegment::Slf(alias)); + *buf = String::new(); + *alias_buf = None; + } else if buf == "super" { + result.push(UseSegment::Super(alias)); + *buf = String::new(); + *alias_buf = None; + } else { + let mut name = String::new(); + swap(buf, &mut name); + result.push(UseSegment::Ident(name, alias)); + } + } + } + fn parse_in_list(&mut self) -> UseTree { + let mut result = vec![]; + let mut buf = String::new(); + let mut alias_buf = None; + while let Some(&c) = self.input.peek() { + match c { + '{' => { + assert!(buf.is_empty()); + self.bump(); + result.push(UseSegment::List(self.parse_list())); + self.eat('}'); + } + '*' => { + assert!(buf.is_empty()); + self.bump(); + result.push(UseSegment::Glob); + } + ':' => { + self.bump(); + self.eat(':'); + Self::push_segment(&mut result, &mut buf, &mut alias_buf); + } + '}' | ',' => { + Self::push_segment(&mut result, &mut buf, &mut alias_buf); + return UseTree { + path: result, + span: DUMMY_SP, + list_item: None, + visibility: None, + attrs: None, + }; + } + ' ' => { + self.bump(); + self.eat('a'); + self.eat('s'); + self.eat(' '); + alias_buf = Some(String::new()); + } + c => { + self.bump(); + if let Some(ref mut buf) = alias_buf { + buf.push(c); + } else { + buf.push(c); + } + } + } + } + Self::push_segment(&mut result, &mut buf, &mut alias_buf); + UseTree { + path: result, + span: DUMMY_SP, + list_item: None, + visibility: None, + attrs: None, + } + } + + fn parse_list(&mut self) -> Vec { + let mut result = vec![]; + loop { + match self.input.peek().unwrap() { + ',' | ' ' => self.bump(), + '}' => { + return result; + } + _ => result.push(self.parse_in_list()), + } + } + } } - None => false, + + let mut parser = Parser { + input: s.chars().peekable(), + }; + parser.parse_in_list() + } + + #[test] + fn test_use_tree_normalize() { + assert_eq!( + parse_use_tree("a::self").normalize(true), + parse_use_tree("a") + ); + assert_eq!( + parse_use_tree("a::self as foo").normalize(true), + parse_use_tree("a as foo") + ); + assert_eq!( + parse_use_tree("a::{self}").normalize(true), + parse_use_tree("a") + ); + assert_eq!( + parse_use_tree("a::{b}").normalize(true), + parse_use_tree("a::b") + ); + assert_eq!( + parse_use_tree("a::{b, c::self}").normalize(true), + parse_use_tree("a::{b, c}") + ); + assert_eq!( + parse_use_tree("a::{b as bar, c::self}").normalize(true), + parse_use_tree("a::{b as bar, c}") + ); + } + + #[test] + fn test_use_tree_ord() { + assert!(parse_use_tree("a").normalize(true) < parse_use_tree("aa").normalize(true)); + assert!(parse_use_tree("a").normalize(true) < parse_use_tree("a::a").normalize(true)); + assert!(parse_use_tree("a").normalize(true) < parse_use_tree("*").normalize(true)); + assert!(parse_use_tree("a").normalize(true) < parse_use_tree("{a, b}").normalize(true)); + assert!(parse_use_tree("*").normalize(true) < parse_use_tree("{a, b}").normalize(true)); + + assert!( + parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, dddddddd}").normalize(true) + < parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, ddddddddd}").normalize(true) + ); + assert!( + parse_use_tree("serde::de::{Deserialize}").normalize(true) + < parse_use_tree("serde_json").normalize(true) + ); + assert!( + parse_use_tree("a::b::c").normalize(true) < parse_use_tree("a::b::*").normalize(true) + ); + assert!( + parse_use_tree("foo::{Bar, Baz}").normalize(true) + < parse_use_tree("{Bar, Baz}").normalize(true) + ); + + assert!( + parse_use_tree("foo::{self as bar}").normalize(true) + < parse_use_tree("foo::{qux as bar}").normalize(true) + ); + assert!( + parse_use_tree("foo::{qux as bar}").normalize(true) + < parse_use_tree("foo::{baz, qux as bar}").normalize(true) + ); + assert!( + parse_use_tree("foo::{self as bar, baz}").normalize(true) + < parse_use_tree("foo::{baz, qux as bar}").normalize(true) + ); + + assert!(parse_use_tree("foo").normalize(true) < parse_use_tree("Foo").normalize(true)); + assert!(parse_use_tree("foo").normalize(true) < parse_use_tree("foo::Bar").normalize(true)); + + assert!( + parse_use_tree("std::cmp::{d, c, b, a}").normalize(true) + < parse_use_tree("std::cmp::{b, e, g, f}").normalize(true) + ); } } diff --git a/src/lists.rs b/src/lists.rs index 61c9c413ac2..43ba7f9d673 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -56,7 +56,7 @@ impl AsRef for ListItem { } } -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum ListItemCommentStyle { // Try to keep the comment on the same line with the item. SameLine, @@ -66,7 +66,7 @@ pub enum ListItemCommentStyle { None, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ListItem { // None for comments mean that they are not present. pub pre_comment: Option, diff --git a/src/reorder.rs b/src/reorder.rs index 38d2a09bd08..ae9cada01d2 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -16,29 +16,22 @@ // TODO(#2455): Reorder trait items. -use config::{Config, lists::*}; -use syntax::ast::UseTreeKind; +use config::{lists::*, Config}; use syntax::{ast, attr, codemap::Span}; use attr::filter_inline_attrs; use codemap::LineRangeUtils; use comment::combine_strs_with_missing_comments; -use imports::{path_to_imported_ident, rewrite_import}; +use imports::UseTree; use items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; -use lists::{itemize_list, write_list, ListFormatting}; +use lists::{itemize_list, write_list, ListFormatting, ListItem}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; use utils::mk_sp; use visitor::FmtVisitor; -use std::cmp::{Ord, Ordering, PartialOrd}; - -fn compare_use_trees(a: &ast::UseTree, b: &ast::UseTree) -> Ordering { - let aa = UseTree::from_ast(a).normalize(); - let bb = UseTree::from_ast(b).normalize(); - aa.cmp(&bb) -} +use std::cmp::{Ord, Ordering}; /// Choose the ordering between the given two items. fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { @@ -46,9 +39,6 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { a.ident.name.as_str().cmp(&b.ident.name.as_str()) } - (&ast::ItemKind::Use(ref a_tree), &ast::ItemKind::Use(ref b_tree)) => { - compare_use_trees(a_tree, b_tree) - } (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` // ^^^ Comparing this. @@ -74,58 +64,11 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { } } -/// Rewrite a list of items with reordering. Every item in `items` must have -/// the same `ast::ItemKind`. -fn rewrite_reorderable_items( +fn wrap_reorderable_items( context: &RewriteContext, - reorderable_items: &[&ast::Item], + list_items: &[ListItem], shape: Shape, - span: Span, ) -> Option { - let items = itemize_list( - context.snippet_provider, - reorderable_items.iter(), - "", - ";", - |item| item.span().lo(), - |item| item.span().hi(), - |item| { - let attrs = filter_inline_attrs(&item.attrs, item.span()); - let attrs_str = attrs.rewrite(context, shape)?; - - let missed_span = if attrs.is_empty() { - mk_sp(item.span.lo(), item.span.lo()) - } else { - mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) - }; - - let item_str = match item.node { - ast::ItemKind::Use(ref tree) => { - rewrite_import(context, &item.vis, tree, &item.attrs, shape)? - } - ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, - ast::ItemKind::Mod(..) => rewrite_mod(item), - _ => return None, - }; - - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missed_span, - shape, - false, - ) - }, - span.lo(), - span.hi(), - false, - ); - - let mut item_pair_vec: Vec<_> = items.zip(reorderable_items.iter()).collect(); - item_pair_vec.sort_by(|a, b| compare_items(a.1, b.1)); - let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); - let fmt = ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: "", @@ -137,7 +80,97 @@ fn rewrite_reorderable_items( config: context.config, }; - write_list(&item_vec, &fmt) + write_list(list_items, &fmt) +} + +fn rewrite_reorderable_item( + context: &RewriteContext, + item: &ast::Item, + shape: Shape, +) -> Option { + let attrs = filter_inline_attrs(&item.attrs, item.span()); + let attrs_str = attrs.rewrite(context, shape)?; + + let missed_span = if attrs.is_empty() { + mk_sp(item.span.lo(), item.span.lo()) + } else { + mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) + }; + + let item_str = match item.node { + ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, + ast::ItemKind::Mod(..) => rewrite_mod(item), + _ => return None, + }; + + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missed_span, + shape, + false, + ) +} + +/// Rewrite a list of items with reordering. Every item in `items` must have +/// the same `ast::ItemKind`. +fn rewrite_reorderable_items( + context: &RewriteContext, + reorderable_items: &[&ast::Item], + shape: Shape, + span: Span, +) -> Option { + match reorderable_items[0].node { + // FIXME: Remove duplicated code. + ast::ItemKind::Use(..) => { + let normalized_items: Vec<_> = reorderable_items + .iter() + .filter_map(|item| UseTree::from_ast_with_normalization(context, item)) + .collect(); + + // 4 = "use ", 1 = ";" + let nested_shape = shape.offset_left(4)?.sub_width(1)?; + let list_items = itemize_list( + context.snippet_provider, + normalized_items.iter(), + "", + ";", + |item| item.span.lo(), + |item| item.span.hi(), + |item| item.rewrite_top_level(context, nested_shape), + span.lo(), + span.hi(), + false, + ); + + let mut item_pair_vec: Vec<_> = list_items.zip(&normalized_items).collect(); + item_pair_vec.sort_by(|a, b| a.1.cmp(b.1)); + let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); + + wrap_reorderable_items(context, &item_vec, nested_shape) + } + _ => { + let list_items = itemize_list( + context.snippet_provider, + reorderable_items.iter(), + "", + ";", + |item| item.span().lo(), + |item| item.span().hi(), + |item| rewrite_reorderable_item(context, item, shape), + span.lo(), + span.hi(), + false, + ); + + let mut item_pair_vec: Vec<_> = list_items.zip(reorderable_items.iter()).collect(); + item_pair_vec.sort_by(|a, b| compare_items(a.1, b.1)); + let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); + + wrap_reorderable_items(context, &item_vec, shape) + } + } } fn contains_macro_use_attr(item: &ast::Item) -> bool { @@ -255,409 +288,3 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } } - -// Ordering of imports - -// We order imports by translating to our own representation and then sorting. -// The Rust AST data structures are really bad for this. Rustfmt applies a bunch -// of normalisations to imports and since we want to sort based on the result -// of these (and to maintain idempotence) we must apply the same normalisations -// to the data structures for sorting. -// -// We sort `self` and `super` before other imports, then identifier imports, -// then glob imports, then lists of imports. We do not take aliases into account -// when ordering unless the imports are identical except for the alias (rare in -// practice). - -// FIXME(#2531) - we should unify the comparison code here with the formatting -// code elsewhere since we are essentially string-ifying twice. Furthermore, by -// parsing to our own format on comparison, we repeat a lot of work when -// sorting. - -// FIXME we do a lot of allocation to make our own representation. -#[derive(Debug, Clone, Eq, PartialEq)] -enum UseSegment { - Ident(String, Option), - Slf(Option), - Super(Option), - Glob, - List(Vec), -} - -#[derive(Debug, Clone, Eq, PartialEq)] -struct UseTree { - path: Vec, -} - -impl UseSegment { - // Clone a version of self with any top-level alias removed. - fn remove_alias(&self) -> UseSegment { - match *self { - UseSegment::Ident(ref s, _) => UseSegment::Ident(s.clone(), None), - UseSegment::Slf(_) => UseSegment::Slf(None), - UseSegment::Super(_) => UseSegment::Super(None), - _ => self.clone(), - } - } - - fn from_path_segment(path_seg: &ast::PathSegment) -> UseSegment { - let name = path_seg.identifier.name.as_str(); - if name == "self" { - UseSegment::Slf(None) - } else if name == "super" { - UseSegment::Super(None) - } else { - UseSegment::Ident((*name).to_owned(), None) - } - } -} - -impl UseTree { - fn from_ast(a: &ast::UseTree) -> UseTree { - let mut result = UseTree { path: vec![] }; - for p in &a.prefix.segments { - result.path.push(UseSegment::from_path_segment(p)); - } - match a.kind { - UseTreeKind::Glob => { - result.path.push(UseSegment::Glob); - } - UseTreeKind::Nested(ref list) => { - result.path.push(UseSegment::List( - list.iter().map(|t| Self::from_ast(&t.0)).collect(), - )); - } - UseTreeKind::Simple(ref rename) => { - let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); - let alias = rename.and_then(|ident| { - if ident == path_to_imported_ident(&a.prefix) { - None - } else { - Some(ident.to_string()) - } - }); - - let segment = if &name == "self" { - UseSegment::Slf(alias) - } else if &name == "super" { - UseSegment::Super(alias) - } else { - UseSegment::Ident(name, alias) - }; - - // `name` is already in result. - result.path.pop(); - result.path.push(segment); - } - } - result - } - - // Do the adjustments that rustfmt does elsewhere to use paths. - fn normalize(mut self) -> UseTree { - let mut last = self.path.pop().expect("Empty use tree?"); - // Hack around borrow checker. - let mut normalize_sole_list = false; - let mut aliased_self = false; - - // Normalise foo::self -> foo. - if let UseSegment::Slf(None) = last { - return self; - } - - // Normalise foo::self as bar -> foo as bar. - if let UseSegment::Slf(_) = last { - match self.path.last() { - None => {} - Some(UseSegment::Ident(_, None)) => { - aliased_self = true; - } - _ => unreachable!(), - } - } - - if aliased_self { - match self.path.last() { - Some(UseSegment::Ident(_, ref mut old_rename)) => { - assert!(old_rename.is_none()); - if let UseSegment::Slf(Some(rename)) = last { - *old_rename = Some(rename); - return self; - } - } - _ => unreachable!(), - } - } - - // Normalise foo::{bar} -> foo::bar - if let UseSegment::List(ref list) = last { - if list.len() == 1 && list[0].path.len() == 1 { - normalize_sole_list = true; - } - } - - if normalize_sole_list { - match last { - UseSegment::List(list) => { - self.path.push(list[0].path[0].clone()); - return self.normalize(); - } - _ => unreachable!(), - } - } - - // Recursively normalize elements of a list use (including sorting the list). - if let UseSegment::List(list) = last { - let mut list: Vec<_> = list.into_iter().map(|ut| ut.normalize()).collect(); - list.sort(); - last = UseSegment::List(list); - } - - self.path.push(last); - self - } -} - -impl PartialOrd for UseSegment { - fn partial_cmp(&self, other: &UseSegment) -> Option { - Some(self.cmp(other)) - } -} -impl PartialOrd for UseTree { - fn partial_cmp(&self, other: &UseTree) -> Option { - Some(self.cmp(other)) - } -} -impl Ord for UseSegment { - fn cmp(&self, other: &UseSegment) -> Ordering { - use self::UseSegment::*; - - match (self, other) { - (&Slf(ref a), &Slf(ref b)) | (&Super(ref a), &Super(ref b)) => a.cmp(b), - (&Glob, &Glob) => Ordering::Equal, - (&Ident(ref ia, ref aa), &Ident(ref ib, ref ab)) => { - let ident_ord = ia.cmp(ib); - if ident_ord != Ordering::Equal { - return ident_ord; - } - if aa.is_none() && ab.is_some() { - return Ordering::Less; - } - if aa.is_some() && ab.is_none() { - return Ordering::Greater; - } - aa.cmp(ab) - } - (&List(ref a), &List(ref b)) => { - for (a, b) in a.iter().zip(b.iter()) { - let ord = a.cmp(b); - if ord != Ordering::Equal { - return ord; - } - } - - a.len().cmp(&b.len()) - } - (&Slf(_), _) => Ordering::Less, - (_, &Slf(_)) => Ordering::Greater, - (&Super(_), _) => Ordering::Less, - (_, &Super(_)) => Ordering::Greater, - (&Ident(..), _) => Ordering::Less, - (_, &Ident(..)) => Ordering::Greater, - (&Glob, _) => Ordering::Less, - (_, &Glob) => Ordering::Greater, - } - } -} -impl Ord for UseTree { - fn cmp(&self, other: &UseTree) -> Ordering { - for (a, b) in self.path.iter().zip(other.path.iter()) { - let ord = a.cmp(b); - // The comparison without aliases is a hack to avoid situations like - // comparing `a::b` to `a as c` - where the latter should be ordered - // first since it is shorter. - if ord != Ordering::Equal && a.remove_alias().cmp(&b.remove_alias()) != Ordering::Equal - { - return ord; - } - } - - self.path.len().cmp(&other.path.len()) - } -} - -#[cfg(test)] -mod test { - use super::*; - - // Parse the path part of an import. This parser is not robust and is only - // suitable for use in a test harness. - fn parse_use_tree(s: &str) -> UseTree { - use std::iter::Peekable; - use std::mem::swap; - use std::str::Chars; - - struct Parser<'a> { - input: Peekable>, - } - - impl<'a> Parser<'a> { - fn bump(&mut self) { - self.input.next().unwrap(); - } - fn eat(&mut self, c: char) { - assert!(self.input.next().unwrap() == c); - } - fn push_segment( - result: &mut Vec, - buf: &mut String, - alias_buf: &mut Option, - ) { - if !buf.is_empty() { - let mut alias = None; - swap(alias_buf, &mut alias); - if buf == "self" { - result.push(UseSegment::Slf(alias)); - *buf = String::new(); - *alias_buf = None; - } else if buf == "super" { - result.push(UseSegment::Super(alias)); - *buf = String::new(); - *alias_buf = None; - } else { - let mut name = String::new(); - swap(buf, &mut name); - result.push(UseSegment::Ident(name, alias)); - } - } - } - fn parse_in_list(&mut self) -> UseTree { - let mut result = vec![]; - let mut buf = String::new(); - let mut alias_buf = None; - while let Some(&c) = self.input.peek() { - match c { - '{' => { - assert!(buf.is_empty()); - self.bump(); - result.push(UseSegment::List(self.parse_list())); - self.eat('}'); - } - '*' => { - assert!(buf.is_empty()); - self.bump(); - result.push(UseSegment::Glob); - } - ':' => { - self.bump(); - self.eat(':'); - Self::push_segment(&mut result, &mut buf, &mut alias_buf); - } - '}' | ',' => { - Self::push_segment(&mut result, &mut buf, &mut alias_buf); - return UseTree { path: result }; - } - ' ' => { - self.bump(); - self.eat('a'); - self.eat('s'); - self.eat(' '); - alias_buf = Some(String::new()); - } - c => { - self.bump(); - if let Some(ref mut buf) = alias_buf { - buf.push(c); - } else { - buf.push(c); - } - } - } - } - Self::push_segment(&mut result, &mut buf, &mut alias_buf); - UseTree { path: result } - } - - fn parse_list(&mut self) -> Vec { - let mut result = vec![]; - loop { - match self.input.peek().unwrap() { - ',' | ' ' => self.bump(), - '}' => { - return result; - } - _ => result.push(self.parse_in_list()), - } - } - } - } - - let mut parser = Parser { - input: s.chars().peekable(), - }; - parser.parse_in_list() - } - - #[test] - fn test_use_tree_normalize() { - assert_eq!(parse_use_tree("a::self").normalize(), parse_use_tree("a")); - assert_eq!( - parse_use_tree("a::self as foo").normalize(), - parse_use_tree("a as foo") - ); - assert_eq!(parse_use_tree("a::{self}").normalize(), parse_use_tree("a")); - assert_eq!(parse_use_tree("a::{b}").normalize(), parse_use_tree("a::b")); - assert_eq!( - parse_use_tree("a::{b, c::self}").normalize(), - parse_use_tree("a::{b, c}") - ); - assert_eq!( - parse_use_tree("a::{b as bar, c::self}").normalize(), - parse_use_tree("a::{b as bar, c}") - ); - } - - #[test] - fn test_use_tree_ord() { - assert!(parse_use_tree("a").normalize() < parse_use_tree("aa").normalize()); - assert!(parse_use_tree("a").normalize() < parse_use_tree("a::a").normalize()); - assert!(parse_use_tree("a").normalize() < parse_use_tree("*").normalize()); - assert!(parse_use_tree("a").normalize() < parse_use_tree("{a, b}").normalize()); - assert!(parse_use_tree("*").normalize() < parse_use_tree("{a, b}").normalize()); - - assert!( - parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, dddddddd}").normalize() - < parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, ddddddddd}").normalize() - ); - assert!( - parse_use_tree("serde::de::{Deserialize}").normalize() - < parse_use_tree("serde_json").normalize() - ); - assert!(parse_use_tree("a::b::c").normalize() < parse_use_tree("a::b::*").normalize()); - assert!( - parse_use_tree("foo::{Bar, Baz}").normalize() - < parse_use_tree("{Bar, Baz}").normalize() - ); - - assert!( - parse_use_tree("foo::{self as bar}").normalize() - < parse_use_tree("foo::{qux as bar}").normalize() - ); - assert!( - parse_use_tree("foo::{qux as bar}").normalize() - < parse_use_tree("foo::{baz, qux as bar}").normalize() - ); - assert!( - parse_use_tree("foo::{self as bar, baz}").normalize() - < parse_use_tree("foo::{baz, qux as bar}").normalize() - ); - - assert!(parse_use_tree("Foo").normalize() < parse_use_tree("foo").normalize()); - assert!(parse_use_tree("foo").normalize() < parse_use_tree("foo::Bar").normalize()); - - assert!( - parse_use_tree("std::cmp::{d, c, b, a}").normalize() - < parse_use_tree("std::cmp::{b, e, g, f}").normalize() - ); - } -} -- cgit 1.4.1-3-g733a5 From f6c0a0f4ed16699af45af618e35ab0d18fb7d711 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 31 Mar 2018 14:23:20 +0900 Subject: Cargo fmt --- src/attr.rs | 2 +- src/comment.rs | 2 +- src/config/lists.rs | 2 +- src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 3c4cc390e78..68d6a288896 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,8 +10,8 @@ //! Format attributes and meta items. -use config::IndentStyle; use config::lists::*; +use config::IndentStyle; use syntax::ast; use syntax::codemap::Span; diff --git a/src/comment.rs b/src/comment.rs index 05b423d1898..431be847678 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -10,7 +10,7 @@ // Formatting and tools for comments. -use std::{self, iter, borrow::Cow}; +use std::{self, borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; use syntax::codemap::Span; diff --git a/src/config/lists.rs b/src/config/lists.rs index 53cf7ca7083..04406e8d566 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -10,8 +10,8 @@ //! Configuration options related to rewriting a list. -use config::IndentStyle; use config::config_type::ConfigType; +use config::IndentStyle; /// The definitive formatting tactic for lists. #[derive(Eq, PartialEq, Debug, Copy, Clone)] diff --git a/src/lib.rs b/src/lib.rs index 77589038c66..31cb49dd0d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,8 +54,8 @@ use shape::Indent; use utils::use_colored_tty; use visitor::{FmtVisitor, SnippetProvider}; -pub use config::Config; pub use config::summary::Summary; +pub use config::Config; #[macro_use] mod utils; -- cgit 1.4.1-3-g733a5 From 78e09bd05cff61edbee139eda3c8bc57d00f68ff Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 31 Mar 2018 14:47:50 +0900 Subject: Cargo fmt --- src/reorder.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index ae9cada01d2..7cff6fd5719 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -103,14 +103,7 @@ fn rewrite_reorderable_item( _ => return None, }; - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missed_span, - shape, - false, - ) + combine_strs_with_missing_comments(context, &attrs_str, &item_str, missed_span, shape, false) } /// Rewrite a list of items with reordering. Every item in `items` must have -- cgit 1.4.1-3-g733a5 From 37ee9c20aafe260f4f61595ab196bbe819af62d3 Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Sat, 31 Mar 2018 18:51:41 -0400 Subject: Improve where_single_line help --- Configurations.md | 2 +- src/config/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 13c7acaed4f..f11c9b95d03 100644 --- a/Configurations.md +++ b/Configurations.md @@ -889,7 +889,7 @@ See also [`control_brace_style`](#control_brace_style). ## `where_single_line` -To force single line where layout +Forces the `where` clause to be laid out on a single line. - **Default value**: `false` - **Possible values**: `true`, `false` diff --git a/src/config/mod.rs b/src/config/mod.rs index 5d5e91ebaed..87f6a86a526 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -61,7 +61,7 @@ create_config! { struct_lit_single_line: bool, true, false, "Put small struct literals on a single line"; fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - where_single_line: bool, false, false, "To force single line where layout"; + where_single_line: bool, false, false, "Force where clauses to be on a single line"; // Imports imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; -- cgit 1.4.1-3-g733a5 From ed46a777c8f2fdd54811f8af1660fd55f7869d05 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 16:20:46 +0900 Subject: Use str::repeat --- src/chains.rs | 10 +++------- src/lib.rs | 9 ++++----- src/missed_spans.rs | 3 +-- 3 files changed, 8 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index d798981415e..0e674f77108 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -104,7 +104,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; let parent_rewrite = parent .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &repeat_try(prefix_try_num))?; + .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); @@ -297,7 +297,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - join_rewrites(&rewrites, &connector) ) }; - let result = format!("{}{}", result, repeat_try(suffix_try_num)); + let result = format!("{}{}", result, "?".repeat(suffix_try_num)); if context.config.indent_style() == IndentStyle::Visual { wrap_str(result, context.config.max_width(), shape) } else { @@ -318,10 +318,6 @@ fn chain_only_try(exprs: &[ast::Expr]) -> bool { // Try to rewrite and replace the last non-try child. Return `true` if // replacing succeeds. -fn repeat_try(try_count: usize) -> String { - iter::repeat("?").take(try_count).collect::() -} - fn rewrite_try( expr: &ast::Expr, try_count: usize, @@ -329,7 +325,7 @@ fn rewrite_try( shape: Shape, ) -> Option { let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; - Some(format!("{}{}", sub_expr, repeat_try(try_count))) + Some(format!("{}{}", sub_expr, "?".repeat(try_count))) } fn join_rewrites(rewrites: &[String], connector: &str) -> String { diff --git a/src/lib.rs b/src/lib.rs index 77589038c66..151b3acada2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,6 @@ extern crate unicode_segmentation; use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, BufRead, Write}; -use std::iter::repeat; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::PathBuf; use std::rc::Rc; @@ -200,7 +199,7 @@ impl FormatReport { for (file, errors) in &self.file_error_map { for error in errors { let prefix_space_len = error.line.to_string().len(); - let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + let prefix_spaces = " ".repeat(1 + prefix_space_len); // First line: the overview of error t.fg(term::color::RED)?; @@ -259,8 +258,8 @@ impl FormatReport { } fn target_str(space_len: usize, target_len: usize) -> String { - let empty_line: String = repeat(" ").take(space_len).collect(); - let overflowed: String = repeat("^").take(target_len).collect(); + let empty_line = " ".repeat(space_len); + let overflowed = "^".repeat(target_len); empty_line + &overflowed } @@ -270,7 +269,7 @@ impl fmt::Display for FormatReport { for (file, errors) in &self.file_error_map { for error in errors { let prefix_space_len = error.line.to_string().len(); - let prefix_spaces: String = repeat(" ").take(1 + prefix_space_len).collect(); + let prefix_spaces = " ".repeat(1 + prefix_space_len); let error_line_buffer = if error.line_buffer.is_empty() { String::from(" ") diff --git a/src/missed_spans.rs b/src/missed_spans.rs index f5794c65c4c..5140ac35be9 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::borrow::Cow; -use std::iter::repeat; use syntax::codemap::{BytePos, FileName, Pos, Span}; @@ -122,7 +121,7 @@ impl<'a> FmtVisitor<'a> { } } - let blank_lines: String = repeat('\n').take(newline_count).collect(); + let blank_lines = "\n".repeat(newline_count); self.push_str(&blank_lines); } -- cgit 1.4.1-3-g733a5 From 6b3811a3587cc9d9d0734c44e24b969319a7fab5 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 18:43:52 +0900 Subject: Use Iterator methods --- src/config/options.rs | 8 +------- src/git-rustfmt/main.rs | 20 ++------------------ 2 files changed, 3 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index 31f7d106d1a..eca206a75fe 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -271,13 +271,7 @@ impl IgnoreList { } fn skip_file_inner(&self, file: &Path) -> bool { - for path in &self.0 { - if file.starts_with(path) { - return true; - } - } - - false + self.0.iter().any(|path| file.starts_with(path)) } pub fn skip_file(&self, file: &FileName) -> bool { diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 41e4ee2931d..3ff9455d5f7 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -32,16 +32,7 @@ fn prune_files(files: Vec<&str>) -> Vec<&str> { let mut pruned_prefixes = vec![]; for p1 in prefixes { - let mut include = true; - if !p1.starts_with("src/bin/") { - for p2 in &pruned_prefixes { - if p1.starts_with(p2) { - include = false; - break; - } - } - } - if include { + if p1.starts_with("src/bin/") || pruned_prefixes.iter().all(|p2| !p1.starts_with(p2)) { pruned_prefixes.push(p1); } } @@ -50,17 +41,10 @@ fn prune_files(files: Vec<&str>) -> Vec<&str> { files .into_iter() .filter(|f| { - let mut include = true; if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { return true; } - for pp in &pruned_prefixes { - if f.starts_with(pp) { - include = false; - break; - } - } - include + pruned_prefixes.iter().all(|pp| !f.starts_with(pp)) }) .collect() } -- cgit 1.4.1-3-g733a5 From 89200f40ff7c0b4e896dd9d87ab2655c623b196e Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 18:12:50 +0900 Subject: Remove unnecessary `[..]`s --- src/chains.rs | 2 +- src/items.rs | 4 ++-- src/macros.rs | 6 +++--- src/patterns.rs | 2 +- src/types.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 0e674f77108..8326f735e21 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -336,7 +336,7 @@ fn join_rewrites(rewrites: &[String], connector: &str) -> String { if rewrite != "?" { result.push_str(connector); } - result.push_str(&rewrite[..]); + result.push_str(&rewrite); } result diff --git a/src/items.rs b/src/items.rs index 377d777c409..be21e1fd787 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1287,7 +1287,7 @@ fn format_tuple_struct( result.push(')'); } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; - let fields = &fields.iter().collect::>()[..]; + let fields = &fields.iter().collect::>(); result = overflow::rewrite_with_parens( context, &result, @@ -2312,7 +2312,7 @@ fn rewrite_generics( return Some(ident.to_owned()); } - let params = &generics.params.iter().map(|e| &*e).collect::>()[..]; + let params = &generics.params.iter().map(|e| &*e).collect::>(); overflow::rewrite_with_angle_brackets(context, ident, params, shape, span) } diff --git a/src/macros.rs b/src/macros.rs index c5671911936..aded2508aaa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -239,7 +239,7 @@ pub fn rewrite_macro_inner( overflow::rewrite_with_parens( context, ¯o_name, - &arg_vec.iter().map(|e| &*e).collect::>()[..], + &arg_vec.iter().map(|e| &*e).collect::>(), shape, mac.span, context.config.width_heuristics().fn_call_width, @@ -301,7 +301,7 @@ pub fn rewrite_macro_inner( }; } // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. - let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>()[..]; + let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>(); let rewrite = rewrite_array( macro_name, arg_vec, @@ -991,7 +991,7 @@ fn next_space(tok: &Token) -> SpaceState { /// when the macro is not an instance of try! (or parsing the inner expression /// failed). pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { - if &format!("{}", mac.node.path)[..] == "try" { + if &format!("{}", mac.node.path) == "try" { let ts: TokenStream = mac.node.tts.clone().into(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); diff --git a/src/patterns.rs b/src/patterns.rs index 44e32462a8d..9923eea418a 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -369,7 +369,7 @@ fn rewrite_tuple_pat( overflow::rewrite_with_parens( &context, &path_str, - &pat_ref_vec[..], + &pat_ref_vec, shape, span, context.config.max_width(), diff --git a/src/types.rs b/src/types.rs index 676095ff4ce..5be96348129 100644 --- a/src/types.rs +++ b/src/types.rs @@ -247,7 +247,7 @@ fn rewrite_segment( let generics_str = overflow::rewrite_with_angle_brackets( context, "", - ¶m_list.iter().map(|e| &*e).collect::>()[..], + ¶m_list.iter().map(|e| &*e).collect::>(), shape, mk_sp(*span_lo, span_hi), )?; -- cgit 1.4.1-3-g733a5 From a2325375ed2a18af8b41e9d5147646511c582aab Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 19:35:00 +0900 Subject: Do not collect into a Vec by hand --- src/patterns.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 9923eea418a..53051c71ba7 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -361,10 +361,7 @@ fn rewrite_tuple_pat( // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); let path_str = path_str.unwrap_or_default(); - let mut pat_ref_vec = Vec::with_capacity(pat_vec.len()); - for pat in pat_vec { - pat_ref_vec.push(pat); - } + let pat_ref_vec = pat_vec.iter().collect::>(); overflow::rewrite_with_parens( &context, -- cgit 1.4.1-3-g733a5 From 39e85281f33f40742041fd8e1d8ef1cd7fa760b1 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 21:10:31 +0900 Subject: Remove stray comment Its pointee was removed in 04a6d16c7b68587f8e9fa8a1e6715f80408b023b --- src/chains.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 8326f735e21..6c3b6d1033d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -316,8 +316,6 @@ fn chain_only_try(exprs: &[ast::Expr]) -> bool { }) } -// Try to rewrite and replace the last non-try child. Return `true` if -// replacing succeeds. fn rewrite_try( expr: &ast::Expr, try_count: usize, -- cgit 1.4.1-3-g733a5 From 71448ff3c25db6cba8dc40191416e9e1490e7964 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 21:21:52 +0900 Subject: Return String instead of always returing Cow::Owned --- src/missed_spans.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 5140ac35be9..db4f01fa688 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -175,7 +175,7 @@ impl<'a> FmtVisitor<'a> { let mut status = SnippetStatus::new(char_pos.line); let snippet = &*match self.config.write_mode() { - WriteMode::Coverage => replace_chars(old_snippet), + WriteMode::Coverage => Cow::from(replace_chars(old_snippet)), _ => Cow::from(old_snippet), }; @@ -320,11 +320,9 @@ impl<'a> FmtVisitor<'a> { } } -fn replace_chars(string: &str) -> Cow { - Cow::from( - string - .chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect::(), - ) +fn replace_chars(string: &str) -> String { + string + .chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect() } -- cgit 1.4.1-3-g733a5 From ba792a7fa2410fdb488ffa90ef6aa69269ee38c6 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 21:35:51 +0900 Subject: Remove redudant parens --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 22f892d4fb4..d15d2ad7aef 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -335,7 +335,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let snippet = self.snippet(item.span); let where_span_end = snippet .find_uncommented("{") - .map(|x| (BytePos(x as u32)) + source!(self, item.span).lo()); + .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); self.push_rewrite(item.span, rw); } -- cgit 1.4.1-3-g733a5 From 3467b4dafebc6e9a52d1cf7051abc057e23defe7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 21:43:01 +0900 Subject: Use ListItem::has_comment --- src/patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 53051c71ba7..bbfe55ec6e9 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -405,7 +405,7 @@ fn count_wildcard_suffix_len( }) { suffix_len += 1; - if item.pre_comment.is_some() || item.post_comment.is_some() { + if item.has_comment() { break; } } -- cgit 1.4.1-3-g733a5 From 56e10aa6e9aca94a61ff2eeaee6416ee374115cd Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 21:47:55 +0900 Subject: Fix typo --- src/items.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index be21e1fd787..621b2a2074d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -204,7 +204,7 @@ impl<'a> FnSig<'a> { fn_kind: &'a visit::FnKind, generics: &'a ast::Generics, decl: &'a ast::FnDecl, - defualtness: ast::Defaultness, + defaultness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { @@ -212,13 +212,13 @@ impl<'a> FnSig<'a> { generics, abi, constness: constness.node, - defaultness: defualtness, + defaultness, unsafety, visibility: visibility.clone(), }, visit::FnKind::Method(_, method_sig, vis, _) => { let mut fn_sig = FnSig::from_method_sig(method_sig, generics); - fn_sig.defaultness = defualtness; + fn_sig.defaultness = defaultness; if let Some(vis) = vis { fn_sig.visibility = vis.clone(); } -- cgit 1.4.1-3-g733a5 From e2d801f11e9e7a2de5481e46ee458d0746b9e906 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 1 Apr 2018 23:09:53 +0900 Subject: Do not turn spaces in the beginning of the file into a newline (#2583) --- src/missed_spans.rs | 6 ++++++ tests/source/issue-2582.rs | 1 + tests/target/issue-2582.rs | 1 + 3 files changed, 8 insertions(+) create mode 100644 tests/source/issue-2582.rs create mode 100644 tests/target/issue-2582.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index f5794c65c4c..20cd5e6dca1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -94,6 +94,12 @@ impl<'a> FmtVisitor<'a> { self.last_pos = end; let span = mk_sp(start, end); let snippet = self.snippet(span); + + // Do nothing for spaces in the beginning of the file + if start == BytePos(0) && end.0 as usize == snippet.len() && snippet.trim().is_empty() { + return; + } + if snippet.trim().is_empty() && !out_of_file_lines_range!(self, span) { // Keep vertical spaces within range. self.push_vertical_spaces(count_newlines(snippet)); diff --git a/tests/source/issue-2582.rs b/tests/source/issue-2582.rs new file mode 100644 index 00000000000..bba8ce1504c --- /dev/null +++ b/tests/source/issue-2582.rs @@ -0,0 +1 @@ + fn main() {} diff --git a/tests/target/issue-2582.rs b/tests/target/issue-2582.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/target/issue-2582.rs @@ -0,0 +1 @@ +fn main() {} -- cgit 1.4.1-3-g733a5 From bc05621f9b6bc685ae5973a835cfbbbff1a621ce Mon Sep 17 00:00:00 2001 From: Marthog Date: Sun, 1 Apr 2018 16:15:25 +0200 Subject: Let --dump-default-config default to stdout #2579 (#2586) --- src/bin/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index b59e47930e0..109bc90aadd 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -161,11 +161,13 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); - opts.optopt( + opts.opt( "", "dump-default-config", "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", "PATH", + getopts::HasArg::Maybe, + getopts::Occur::Optional, ); opts.optopt( "", -- cgit 1.4.1-3-g733a5 From d48cbedfe45e667d57573f147415d11c85fcb26a Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Thu, 5 Apr 2018 05:47:09 +0200 Subject: typo (#2598) * typo * more typos --- src/cargo-fmt/main.rs | 2 +- src/overflow.rs | 2 +- src/reorder.rs | 2 +- src/types.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 990e2596660..c31caa1447d 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -211,7 +211,7 @@ impl Hash for Target { pub enum CargoFmtStrategy { /// Format every packages and dependencies. All, - /// Format pacakges that are specified by the command line argument. + /// Format packages that are specified by the command line argument. Some(Vec), /// Format the root packages only. Root, diff --git a/src/overflow.rs b/src/overflow.rs index 6383d032273..cc68f3e1ec2 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -279,7 +279,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { if self.items.len() == 1 => { // When we are rewriting a nested function call, we restrict the - // bugdet for the inner function to avoid them being deeply nested. + // budget for the inner function to avoid them being deeply nested. // However, when the inner function has a prefix or a suffix // (e.g. `foo() as u32`), this budget reduction may produce poorly // formatted code, where a prefix or a suffix being left on its own diff --git a/src/reorder.rs b/src/reorder.rs index 38d2a09bd08..dbb2097535e 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -12,7 +12,7 @@ //! //! `mod`, `extern crate` and `use` declarations are reorderd in alphabetical //! order. Trait items are reordered in pre-determined order (associated types -//! and constatns comes before methods). +//! and constants comes before methods). // TODO(#2455): Reorder trait items. diff --git a/src/types.rs b/src/types.rs index 5be96348129..615dc53fc4e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -732,7 +732,7 @@ fn rewrite_bare_fn( { result.push_str("for<"); // 6 = "for<> ".len(), 4 = "for<". - // This doesn't work out so nicely for mutliline situation with lots of + // This doesn't work out so nicely for multiline situation with lots of // rightward drift. If that is a problem, we could use the list stuff. result.push_str(lifetime_str); result.push_str("> "); -- cgit 1.4.1-3-g733a5 From 94f5a05a6a7e786692dcc6862cb396c1a8803b98 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 4 Apr 2018 14:57:30 +0900 Subject: Add reorder_impl_items config option --- Configurations.md | 36 ++++++++++++++++++++++++ src/config/mod.rs | 1 + tests/source/configs/reorder_impl_items/false.rs | 11 ++++++++ tests/source/configs/reorder_impl_items/true.rs | 11 ++++++++ tests/target/configs/reorder_impl_items/false.rs | 11 ++++++++ tests/target/configs/reorder_impl_items/true.rs | 11 ++++++++ 6 files changed, 81 insertions(+) create mode 100644 tests/source/configs/reorder_impl_items/false.rs create mode 100644 tests/source/configs/reorder_impl_items/true.rs create mode 100644 tests/target/configs/reorder_impl_items/false.rs create mode 100644 tests/target/configs/reorder_impl_items/true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 13c7acaed4f..e10a20e59f5 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1413,6 +1413,42 @@ mod sit; **Note** `mod` with `#[macro_export]` will not be reordered since that could change the semantic of the original source code. +## `reorder_impl_items` + +Reorder impl items. `type` and `const` are put first, then macros and methods. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default) + +```rust +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} +``` + +#### `true` + +```rust +struct Dummy; + +impl Iterator for Dummy { + type Item = i32; + + fn next(&mut self) -> Option { + None + } +} +``` + ## `report_todo` Report `TODO` items in comments. diff --git a/src/config/mod.rs b/src/config/mod.rs index 5d5e91ebaed..4c571c8c813 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -75,6 +75,7 @@ create_config! { reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; reorder_modules: bool, true, false, "Reorder module statemtents alphabetically in group"; + reorder_impl_items: bool, false, false, "Reorder impl items"; // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, diff --git a/tests/source/configs/reorder_impl_items/false.rs b/tests/source/configs/reorder_impl_items/false.rs new file mode 100644 index 00000000000..beb99f0fb8e --- /dev/null +++ b/tests/source/configs/reorder_impl_items/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: false + +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} diff --git a/tests/source/configs/reorder_impl_items/true.rs b/tests/source/configs/reorder_impl_items/true.rs new file mode 100644 index 00000000000..612b1c84abd --- /dev/null +++ b/tests/source/configs/reorder_impl_items/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: true + +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} diff --git a/tests/target/configs/reorder_impl_items/false.rs b/tests/target/configs/reorder_impl_items/false.rs new file mode 100644 index 00000000000..beb99f0fb8e --- /dev/null +++ b/tests/target/configs/reorder_impl_items/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: false + +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} diff --git a/tests/target/configs/reorder_impl_items/true.rs b/tests/target/configs/reorder_impl_items/true.rs new file mode 100644 index 00000000000..f2294412a99 --- /dev/null +++ b/tests/target/configs/reorder_impl_items/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: true + +struct Dummy; + +impl Iterator for Dummy { + type Item = i32; + + fn next(&mut self) -> Option { + None + } +} -- cgit 1.4.1-3-g733a5 From fa80ddf876c9a8a5aa205b1bbbe370ef2996e7c7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 4 Apr 2018 14:57:55 +0900 Subject: Reorder impl items based on its kind The ordering is defined as follows: type < cosnt < macro < method Items that are same kind will not be reordered: that is, the item that an user has put first comes first. --- src/items.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 621b2a2074d..940cd245523 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use std::borrow::Cow; -use std::cmp::min; +use std::cmp::{min, Ordering}; use config::lists::*; use regex::Regex; @@ -660,12 +660,55 @@ pub fn format_impl( if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = offset.block_only().block_indent(context.config); + let item_indent = offset.block_only().block_indent(context.config); + visitor.block_indent = item_indent; visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); - for item in items { - visitor.visit_impl_item(item); + if context.config.reorder_impl_items() { + // Create visitor for each items, then reorder them. + let mut buffer = vec![]; + for item in items { + visitor.visit_impl_item(item); + buffer.push((visitor.buffer.clone(), item.clone())); + visitor.buffer.clear(); + } + // type -> const -> macro -> method + use ast::ImplItemKind::*; + fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { + match (a, b) { + (Type(..), Type(..)) | (Const(..), Const(..)) => false, + _ => true, + } + } + + buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { + (Type(..), _) => Ordering::Less, + (_, Type(..)) => Ordering::Greater, + (Const(..), _) => Ordering::Less, + (_, Const(..)) => Ordering::Greater, + (Macro(..), _) => Ordering::Less, + (_, Macro(..)) => Ordering::Greater, + _ => Ordering::Less, + }); + let mut prev_kind = None; + for (buf, item) in buffer { + // Make sure that there are at least a single empty line between + // different impl items. + if prev_kind + .as_ref() + .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node)) + { + visitor.push_str("\n"); + } + visitor.push_str(&item_indent.to_string_with_newline(context.config)); + visitor.push_str(buf.trim()); + prev_kind = Some(item.node.clone()); + } + } else { + for item in items { + visitor.visit_impl_item(item); + } } visitor.format_missing(item.span.hi() - BytePos(1)); -- cgit 1.4.1-3-g733a5 From 89070a2244c9e9f93ef3b7e2e8e36cf0bf336133 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 2 Apr 2018 22:53:16 +0900 Subject: Implement LineClasses --- src/comment.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 05b423d1898..9d5543258f6 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -901,6 +901,45 @@ where } } +/// An iterator over the lines of a string, paired with the char kind at the +/// end of the line. +pub struct LineClasses<'a> { + base: iter::Peekable>>, + kind: FullCodeCharKind, +} + +impl<'a> LineClasses<'a> { + pub fn new(s: &'a str) -> Self { + LineClasses { + base: CharClasses::new(s.chars()).peekable(), + kind: FullCodeCharKind::Normal, + } + } +} + +impl<'a> Iterator for LineClasses<'a> { + type Item = (FullCodeCharKind, String); + + fn next(&mut self) -> Option { + if self.base.peek().is_none() { + return None; + } + + let mut line = String::new(); + + while let Some((kind, c)) = self.base.next() { + self.kind = kind; + if c == '\n' { + break; + } else { + line.push(c); + } + } + + Some((self.kind, line)) + } +} + /// Iterator over functional and commented parts of a string. Any part of a string is either /// functional code, either *one* block comment, either *one* line comment. Whitespace between /// comments is functional code. Line comments contain their ending newlines. @@ -1141,8 +1180,7 @@ fn remove_comment_header(comment: &str) -> &str { #[cfg(test)] mod test { - use super::{contains_comment, rewrite_comment, CharClasses, CodeCharKind, CommentCodeSlices, - FindUncommented, FullCodeCharKind}; + use super::*; use shape::{Indent, Shape}; #[test] @@ -1298,4 +1336,10 @@ mod test { check("\"/* abc */\"", "abc", Some(4)); check("\"/* abc", "abc", Some(4)); } + + #[test] + fn test_remove_trailing_white_spaces() { + let s = format!(" r#\"\n test\n \"#"); + assert_eq!(remove_trailing_white_spaces(&s), s); + } } -- cgit 1.4.1-3-g733a5 From ec1907b2a473a2f34dd854304ead822e9becef51 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 2 Apr 2018 23:10:37 +0900 Subject: Do not indent or unindent inside string literal Closes #2588. --- src/lib.rs | 27 ++++++++++++++++++------ src/macros.rs | 68 +++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 151b3acada2..6aa9f7f3107 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,7 @@ use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; -use comment::{CharClasses, FullCodeCharKind}; +use comment::{CharClasses, FullCodeCharKind, LineClasses}; use issues::{BadIssueSeeker, Issue}; use shape::Indent; use utils::use_colored_tty; @@ -605,10 +605,19 @@ const FN_MAIN_PREFIX: &str = "fn main() {\n"; fn enclose_in_main_block(s: &str, config: &Config) -> String { let indent = Indent::from_width(config, config.tab_spaces()); - FN_MAIN_PREFIX.to_owned() + &indent.to_string(config) - + &s.lines() - .collect::>() - .join(&indent.to_string_with_newline(config)) + "\n}" + let mut result = String::with_capacity(s.len() * 2); + result.push_str(FN_MAIN_PREFIX); + let mut need_indent = true; + for (kind, line) in LineClasses::new(s) { + if need_indent { + result.push_str(&indent.to_string(config)); + } + result.push_str(&line); + result.push('\n'); + need_indent = !(kind.is_string() && !line.ends_with('\\')); + } + result.push('}'); + result } /// Format the given code block. Mainly targeted for code block in comment. @@ -626,13 +635,16 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option let formatted = format_snippet(&snippet, config)?; // 2 = "}\n" let block_len = formatted.len().checked_sub(2).unwrap_or(0); - for line in formatted[FN_MAIN_PREFIX.len()..block_len].lines() { + let mut is_indented = true; + for (kind, ref line) in LineClasses::new(&formatted[FN_MAIN_PREFIX.len()..block_len]) { if !is_first { result.push('\n'); } else { is_first = false; } - let trimmed_line = if line.len() > config.max_width() { + let trimmed_line = if !is_indented { + line + } else if line.len() > config.max_width() { // If there are lines that are larger than max width, we cannot tell // whether we have succeeded but have some comments or strings that // are too long, or we have failed to format code block. We will be @@ -655,6 +667,7 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option line }; result.push_str(trimmed_line); + is_indented = !(kind.is_string() && !line.ends_with('\\')); } Some(result) } diff --git a/src/macros.rs b/src/macros.rs index aded2508aaa..3769c97845b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -34,7 +34,7 @@ use syntax::{ast, ptr}; use codemap::SpanUtils; use comment::{contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, - FullCodeCharKind}; + FullCodeCharKind, LineClasses}; use expr::rewrite_array; use lists::{itemize_list, write_list, ListFormatting}; use overflow; @@ -1054,18 +1054,27 @@ fn indent_macro_snippet( macro_str: &str, indent: Indent, ) -> Option { - let mut lines = macro_str.lines(); - let first_line = lines.next().map(|s| s.trim_right())?; + let mut lines = LineClasses::new(macro_str); + let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?; let mut trimmed_lines = Vec::with_capacity(16); + let mut veto_trim = false; let min_prefix_space_width = lines - .filter_map(|line| { - let prefix_space_width = if is_empty_line(line) { + .filter_map(|(kind, line)| { + let mut trimmed = true; + let prefix_space_width = if is_empty_line(&line) { None } else { - Some(get_prefix_space_width(context, line)) + Some(get_prefix_space_width(context, &line)) }; - trimmed_lines.push((line.trim(), prefix_space_width)); + let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) { + veto_trim = kind.is_string() && !line.ends_with('\\'); + trimmed = false; + line + } else { + line.trim().to_owned() + }; + trimmed_lines.push((trimmed, line, prefix_space_width)); prefix_space_width }) .min()?; @@ -1074,17 +1083,20 @@ fn indent_macro_snippet( String::from(first_line) + "\n" + &trimmed_lines .iter() - .map(|&(line, prefix_space_width)| match prefix_space_width { - Some(original_indent_width) => { - let new_indent_width = indent.width() - + original_indent_width - .checked_sub(min_prefix_space_width) - .unwrap_or(0); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) - } - None => String::new(), - }) + .map( + |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { + _ if !trimmed => line.to_owned(), + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width + .checked_sub(min_prefix_space_width) + .unwrap_or(0); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line.trim()) + } + None => String::new(), + }, + ) .collect::>() .join("\n"), ) @@ -1231,15 +1243,17 @@ impl MacroBranch { // Indent the body since it is in a block. let indent_str = body_indent.to_string(&config); - let mut new_body = new_body - .trim_right() - .lines() - .fold(String::new(), |mut s, l| { - if !l.is_empty() { - s += &indent_str; - } - s + l + "\n" - }); + let mut new_body = LineClasses::new(new_body.trim_right()) + .fold( + (String::new(), true), + |(mut s, need_indent), (kind, ref l)| { + if !l.is_empty() && need_indent { + s += &indent_str; + } + (s + l + "\n", !(kind.is_string() && !l.ends_with('\\'))) + }, + ) + .0; // Undo our replacement of macro variables. // FIXME: this could be *much* more efficient. -- cgit 1.4.1-3-g733a5 From 636de8313d27d459b36a208326f9907b41da1c16 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 5 Apr 2018 13:24:18 +0900 Subject: Put imports list on the next line if it exceeds max width --- src/imports.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index f631f4b9c26..5b7c16ecc75 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -366,7 +366,8 @@ fn rewrite_nested_use_tree( }; let list_str = write_list(&items[first_index..], &fmt)?; - let result = if list_str.contains('\n') && context.config.imports_indent() == IndentStyle::Block + let result = if (list_str.contains('\n') || list_str.len() > remaining_width) + && context.config.imports_indent() == IndentStyle::Block { format!( "{}{{\n{}{}\n{}}}", -- cgit 1.4.1-3-g733a5 From 97ec417e74485526992d1abf5fe709d434834898 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 5 Apr 2018 13:27:42 +0900 Subject: Add trailing comma when using mixed layout with block indent --- src/lists.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 05b1a7ce296..d0e9863f2f4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -172,11 +172,10 @@ where let limit = match tactic { _ if pre_line_comments => return DefinitiveListTactic::Vertical, - ListTactic::Mixed => return DefinitiveListTactic::Mixed, ListTactic::Horizontal => return DefinitiveListTactic::Horizontal, ListTactic::Vertical => return DefinitiveListTactic::Vertical, ListTactic::LimitedHorizontalVertical(limit) => ::std::cmp::min(width, limit), - ListTactic::HorizontalVertical => width, + ListTactic::Mixed | ListTactic::HorizontalVertical => width, }; let (sep_count, total_width) = calculate_width(items.clone()); @@ -188,7 +187,10 @@ where { DefinitiveListTactic::Horizontal } else { - DefinitiveListTactic::Vertical + match tactic { + ListTactic::Mixed => DefinitiveListTactic::Mixed, + _ => DefinitiveListTactic::Vertical, + } } } @@ -276,8 +278,7 @@ where if last && formatting.ends_with_newline { match formatting.trailing_separator { - SeparatorTactic::Always => separate = true, - SeparatorTactic::Vertical if result.contains('\n') => separate = true, + SeparatorTactic::Always | SeparatorTactic::Vertical => separate = true, _ => (), } } -- cgit 1.4.1-3-g733a5 From 3fe2233fd3281f80bf3109b4aebb2323fdf58649 Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Sat, 31 Mar 2018 14:27:39 +0200 Subject: Fix error_on_unformatted and skip_children override Currently, error_on_unformatted and skip_children options specified in the config file are discarded. This happens because CLI options have a higher priority, but we coerce an absence of a `bool` option to `false`. In this scenario, an absence of a `bool` option is indistinguishable from explicetely set as `false`. We should coerce it to `None` instead, so it does not override the one in the config file. --- src/bin/main.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 109bc90aadd..3ad2d3088f0 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -57,19 +57,18 @@ enum Operation { /// Parsed command line options. #[derive(Clone, Debug, Default)] struct CliOptions { - skip_children: bool, + skip_children: Option, verbose: bool, write_mode: Option, color: Option, file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, - error_on_unformatted: bool, + error_on_unformatted: Option, } impl CliOptions { fn from_matches(matches: &Matches) -> FmtResult { let mut options = CliOptions::default(); - options.skip_children = matches.opt_present("skip-children"); options.verbose = matches.opt_present("verbose"); let unstable_features = matches.opt_present("unstable-features"); let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") @@ -105,19 +104,26 @@ impl CliOptions { options.file_lines = file_lines.parse()?; } + if matches.opt_present("skip-children") { + options.skip_children = Some(true); + } if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = true; + options.error_on_unformatted = Some(true); } Ok(options) } fn apply_to(self, config: &mut Config) { - config.set().skip_children(self.skip_children); config.set().verbose(self.verbose); config.set().file_lines(self.file_lines); config.set().unstable_features(self.unstable_features); - config.set().error_on_unformatted(self.error_on_unformatted); + if let Some(skip_children) = self.skip_children { + config.set().skip_children(skip_children); + } + if let Some(error_on_unformatted) = self.error_on_unformatted { + config.set().error_on_unformatted(error_on_unformatted); + } if let Some(write_mode) = self.write_mode { config.set().write_mode(write_mode); } -- cgit 1.4.1-3-g733a5 From 04227a7d300817402b08ad4681054c3a122bf200 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Apr 2018 10:31:57 +0900 Subject: Fix up merge mess --- src/imports.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9bd1ccb86c2..b9625a66e1e 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -460,7 +460,7 @@ fn rewrite_nested_use_tree( list_item.item = use_tree.rewrite(context, nested_shape); list_items.push(list_item); } - let tactic = if use_tree_list.iter().any(|use_segment| { + let (tactic, remaining_width) = if use_tree_list.iter().any(|use_segment| { use_segment .path .last() @@ -469,14 +469,16 @@ fn rewrite_nested_use_tree( _ => false, }) }) { - DefinitiveListTactic::Vertical + (DefinitiveListTactic::Vertical, 0) } else { - definitive_tactic( + let remaining_width = shape.width.checked_sub(2).unwrap_or(0); + let tactic = definitive_tactic( &list_items, context.config.imports_layout(), Separator::Comma, - shape.width.checked_sub(2).unwrap_or(0), - ) + remaining_width, + ); + (tactic, remaining_width) }; let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; -- cgit 1.4.1-3-g733a5 From edcc7b69ebe7f13223bd0e44f766a050df859eaa Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Apr 2018 23:09:45 +0900 Subject: Cargo update (#2602) Update `rustc-ap-syntax` to 89.0.0 and fix up breaking changes. --- Cargo.lock | 127 ++++++++++++++++++++++++++++++++++++----------------------- Cargo.toml | 2 +- src/expr.rs | 4 +- src/items.rs | 4 ++ src/utils.rs | 3 +- 5 files changed, 85 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 535fa3b0a3f..514e3b55f84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,7 +44,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -54,8 +54,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -238,6 +238,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.1" @@ -251,6 +259,14 @@ dependencies = [ "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.2" @@ -296,7 +312,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "82.0.0" +version = "89.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -305,7 +321,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "82.0.0" +version = "89.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -313,20 +329,20 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "82.0.0" +version = "89.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -334,32 +350,32 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "82.0.0" +version = "89.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "82.0.0" +version = "89.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "82.0.0" +version = "89.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -384,12 +400,12 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -405,7 +421,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -415,27 +431,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.22.2" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -446,7 +462,7 @@ dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -469,6 +485,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "term" version = "0.4.6" @@ -483,7 +509,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -516,10 +542,10 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -603,7 +629,7 @@ dependencies = [ "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" -"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3" "checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" @@ -630,36 +656,39 @@ dependencies = [ "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" +"checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" +"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" -"checksum rustc-ap-rustc_cratesio_shim 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7908267659b1b2f7cd380347b346131221c94146268ffe881913ba9022266493" -"checksum rustc-ap-rustc_data_structures 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d783ebb12feb92af2f6611c32a8547c3af4955ecc4e07650fc746443275b0de" -"checksum rustc-ap-rustc_errors 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b6ca3d305e47ce828e7d96b512ddf9e56c4e04798e6a71c2d4615826d7b9231" -"checksum rustc-ap-serialize 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce8ff65713a3b610d7f80ee968246d4a8d0ea2cb7ffb23e363a0bba1380c88ad" -"checksum rustc-ap-syntax 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1b0af2c744b1e1fe8711c51dc4ecfc5d5c0a1e76dc9c1512254930d335a141" -"checksum rustc-ap-syntax_pos 82.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eebbc4112cc9dcc0de5369b1af40ec0f4077c92c6aa6596384c2599c80293c96" +"checksum rustc-ap-rustc_cratesio_shim 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78bda69468474cd71e758ae38e6941e85f836024621134f302d1186c0e8dc24" +"checksum rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f5888f20a213def17eae391dc1ccc35d45bdafb55a50f6ede64366309928adf" +"checksum rustc-ap-rustc_errors 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec73f8e6d50d8354f8c73a8933c7247c1da0c83c165e43a6453586ece2f1fc44" +"checksum rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4c01e2e699c5218cd6a4259d0b361f260300c74b48389a968868e902c7dbc5" +"checksum rustc-ap-syntax 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb3954b2f98d9c05ea0cbe8d4d72352552ed20f22de7083c04576cdd6f8b432f" +"checksum rustc-ap-syntax_pos 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6efc72a1191597fbaf780158b2bad3922820557606607a26d8088852fc416f5" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "c70142ae874a42c70e03c63c6a49abe2ea0079b090bf6e136e99252fc1974bd6" -"checksum serde_derive 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "6fffe22d41dbddcead5b2c380c4714d44f2eb39292f7e7a0d966d2d45bf56408" -"checksum serde_derive_internals 0.22.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2f04ed291686ce195a5c8f554aaf36e50a721fbf829ee3b6151e6f85eccf945" +"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" +"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" +"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" "checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" +"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" -"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" +"checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" diff --git a/Cargo.toml b/Cargo.toml index a5f84370845..d75a0a773b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-syntax = "82.0.0" +rustc-ap-syntax = "89.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/expr.rs b/src/expr.rs index 14ba8d0f7a0..d2ae5ba94e1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -288,9 +288,7 @@ pub fn format_expr( } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::ExprKind::InPlace(..) | ast::ExprKind::InlineAsm(..) => { - Some(context.snippet(expr.span).to_owned()) - } + ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::Catch(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "do catch ", block, Some(&expr.attrs), shape) diff --git a/src/items.rs b/src/items.rs index 940cd245523..eabd234b0ee 100644 --- a/src/items.rs +++ b/src/items.rs @@ -26,6 +26,7 @@ use config::{BraceStyle, Config, Density, IndentStyle}; use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, ExprType, RhsTactics}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use macros::{rewrite_macro, MacroPosition}; use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; @@ -2732,6 +2733,9 @@ impl Rewrite for ast::ForeignItem { let vis = format_visibility(&self.vis); Some(format!("{}type {};", vis, self.ident)) } + ast::ForeignItemKind::Macro(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Item) + } }?; let missing_span = if self.attrs.is_empty() { diff --git a/src/utils.rs b/src/utils.rs index 522c066b02f..055f75b4609 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -358,8 +358,7 @@ pub fn paren_overhead(context: &RewriteContext) -> usize { pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { match e.node { - ast::ExprKind::InPlace(ref e, _) - | ast::ExprKind::Call(ref e, _) + ast::ExprKind::Call(ref e, _) | ast::ExprKind::Binary(_, ref e, _) | ast::ExprKind::Cast(ref e, _) | ast::ExprKind::Type(ref e, _) -- cgit 1.4.1-3-g733a5 From 84d36597671982900dc10f4d1940d40b290106eb Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 8 Apr 2018 22:18:18 +0800 Subject: update rustc syntax 91.0.0 --- Cargo.lock | 48 ++++++++++++++++++++++++------------------------ Cargo.toml | 2 +- src/attr.rs | 6 +++--- src/chains.rs | 4 ++-- src/expr.rs | 13 ++++++++++--- src/imports.rs | 4 ++-- src/items.rs | 10 +++++----- src/macros.rs | 2 +- src/patterns.rs | 2 +- src/spanned.rs | 12 ++++++------ src/types.rs | 6 +++--- src/utils.rs | 6 +++--- src/vertical.rs | 2 +- 13 files changed, 62 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 514e3b55f84..357e80e1403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -312,7 +312,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "89.0.0" +version = "91.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "89.0.0" +version = "91.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -329,20 +329,20 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "89.0.0" +version = "91.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -350,32 +350,32 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "89.0.0" +version = "91.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "89.0.0" +version = "91.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "89.0.0" +version = "91.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -400,7 +400,7 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -665,12 +665,12 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" -"checksum rustc-ap-rustc_cratesio_shim 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78bda69468474cd71e758ae38e6941e85f836024621134f302d1186c0e8dc24" -"checksum rustc-ap-rustc_data_structures 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f5888f20a213def17eae391dc1ccc35d45bdafb55a50f6ede64366309928adf" -"checksum rustc-ap-rustc_errors 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec73f8e6d50d8354f8c73a8933c7247c1da0c83c165e43a6453586ece2f1fc44" -"checksum rustc-ap-serialize 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4c01e2e699c5218cd6a4259d0b361f260300c74b48389a968868e902c7dbc5" -"checksum rustc-ap-syntax 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb3954b2f98d9c05ea0cbe8d4d72352552ed20f22de7083c04576cdd6f8b432f" -"checksum rustc-ap-syntax_pos 89.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6efc72a1191597fbaf780158b2bad3922820557606607a26d8088852fc416f5" +"checksum rustc-ap-rustc_cratesio_shim 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd7571780b3232786f538b4e72f4a8d7fcffbb4a951d3861e18142d3cf2f0ac" +"checksum rustc-ap-rustc_data_structures 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae9ebbcbe26ea53eb0f3162c109892cd69ebb5efc986f3a21bce4891adf628f" +"checksum rustc-ap-rustc_errors 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c8385e5cf62344a4c6b2446723da0a82dad7ec97b2988b6494a197f231fc4b9" +"checksum rustc-ap-serialize 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d08a7e3ce1d87fda88fdf51bdfec5886f42bfd93ce7fcf1d69fcd0a23d1ab4ea" +"checksum rustc-ap-syntax 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06b7a6da9b99e9a2e31f9325216dc5d477eb5d9bd88c7bb05b5e97e88d06d675" +"checksum rustc-ap-syntax_pos 91.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "582d30a1308f6598b3636bc244efacd8551c825ed6be2aa594257fbf772d1161" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" diff --git a/Cargo.toml b/Cargo.toml index d75a0a773b7..ee5b1ebc99a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-syntax = "89.0.0" +rustc-ap-syntax = "91.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/attr.rs b/src/attr.rs index 68d6a288896..e17b89e5c9e 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -200,9 +200,9 @@ fn allow_mixed_tactic_for_nested_metaitem_list(list: &[ast::NestedMetaItem]) -> impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { - ast::MetaItemKind::Word => String::from(&*self.name.as_str()), + ast::MetaItemKind::Word => String::from(&*self.ident.name.as_str()), ast::MetaItemKind::List(ref list) => { - let name = self.name.as_str(); + let name = self.ident.name.as_str(); let item_shape = match context.config.indent_style() { IndentStyle::Block => shape .block_indent(context.config.tab_spaces()) @@ -259,7 +259,7 @@ impl Rewrite for ast::MetaItem { } } ast::MetaItemKind::NameValue(ref literal) => { - let name = self.name.as_str(); + let name = self.ident.name.as_str(); // 3 = ` = ` let lit_shape = shape.shrink_left(name.len() + 3)?; // `rewrite_literal` returns `None` when `literal` exceeds max diff --git a/src/chains.rs b/src/chains.rs index 6c3b6d1033d..15ecd6034f3 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -438,9 +438,9 @@ fn rewrite_chain_subexpr( }, _ => &[], }; - rewrite_method_call(segment.identifier, types, expressions, span, context, shape) + rewrite_method_call(segment.ident, types, expressions, span, context, shape) } - ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.node)), + ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.name)), ast::ExprKind::TupField(ref expr, ref field) => { let space = match expr.node { ast::ExprKind::TupField(..) => " ", diff --git a/src/expr.rs b/src/expr.rs index d2ae5ba94e1..b738d4ccb16 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -173,7 +173,13 @@ pub fn format_expr( }, ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( - capture, movability, fn_decl, body, expr.span, context, shape, + capture, + movability, + fn_decl, + body, + expr.span, + context, + shape, ) } ast::ExprKind::Try(..) @@ -928,7 +934,8 @@ impl<'a> ControlFlow<'a> { // `for event in event` // Do not include label in the span. - let lo = self.label.map_or(self.span.lo(), |label| label.span.hi()); + let lo = self.label + .map_or(self.span.lo(), |label| label.ident.span.hi()); let between_kwd_cond = mk_sp( context .snippet_provider @@ -1702,7 +1709,7 @@ pub fn rewrite_field( if !attrs_str.is_empty() { attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); }; - let name = field.ident.node.to_string(); + let name = &field.ident.name.to_string(); if field.is_shorthand { Some(attrs_str + &name) } else { diff --git a/src/imports.rs b/src/imports.rs index b9625a66e1e..a66bcbd3e94 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -28,7 +28,7 @@ use std::borrow::Cow; /// Returns a name imported by a `use` declaration. e.g. returns `Ordering` /// for `std::cmp::Ordering` and `self` for `std::cmp::self`. pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { - path.segments.last().unwrap().identifier + path.segments.last().unwrap().ident } impl<'a> FmtVisitor<'a> { @@ -129,7 +129,7 @@ impl UseSegment { } fn from_path_segment(path_seg: &ast::PathSegment) -> Option { - let name = path_seg.identifier.name.as_str(); + let name = path_seg.ident.name.as_str(); if name == "{{root}}" { return None; } diff --git a/src/items.rs b/src/items.rs index eabd234b0ee..6d474a3ccd6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -562,10 +562,10 @@ impl<'a> FmtVisitor<'a> { )?, ast::VariantData::Unit(..) => { if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", field.node.name); + let lhs = format!("{} =", field.node.ident.name); rewrite_assign_rhs(&context, lhs, &**expr, shape)? } else { - field.node.name.to_string() + field.node.ident.name.to_string() } } }; @@ -893,7 +893,7 @@ impl<'a> StructParts<'a> { fn from_variant(variant: &'a ast::Variant) -> Self { StructParts { prefix: "", - ident: variant.node.name, + ident: variant.node.ident, vis: &DEFAULT_VISIBILITY, def: &variant.node.data, generics: None, @@ -1794,7 +1794,7 @@ pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { pub fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != symbol::keywords::Invalid.ident() + ident != symbol::keywords::Invalid.ident() } else { true } @@ -2263,7 +2263,7 @@ fn rewrite_args( fn arg_has_pattern(arg: &ast::Arg) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident.node != symbol::keywords::Invalid.ident() + ident != symbol::keywords::Invalid.ident() } else { true } diff --git a/src/macros.rs b/src/macros.rs index 3769c97845b..9cf033e9693 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -117,7 +117,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> String { let name = if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. - format!("{}!", path.segments[0].identifier) + format!("{}!", path.segments[0].ident) } else { format!("{}!", path) }; diff --git a/src/patterns.rs b/src/patterns.rs index bbfe55ec6e9..243b85e4267 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -71,7 +71,7 @@ impl Rewrite for Pat { BindingMode::ByValue(mutability) => ("", mutability), }; let mut_infix = format_mutability(mutability); - let id_str = ident.node.to_string(); + let id_str = ident.name.to_string(); let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. diff --git a/src/spanned.rs b/src/spanned.rs index 41fa0da8dd1..237624ab8fe 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -146,7 +146,7 @@ impl Spanned for ast::TyParam { fn span(&self) -> Span { // Note that ty.span is the span for ty.ident, not the whole item. let lo = if self.attrs.is_empty() { - self.span.lo() + self.ident.span.lo() } else { self.attrs[0].span.lo() }; @@ -154,7 +154,7 @@ impl Spanned for ast::TyParam { return mk_sp(lo, def.span.hi()); } if self.bounds.is_empty() { - return mk_sp(lo, self.span.hi()); + return mk_sp(lo, self.ident.span.hi()); } let hi = self.bounds[self.bounds.len() - 1].span().hi(); mk_sp(lo, hi) @@ -165,7 +165,7 @@ impl Spanned for ast::TyParamBound { fn span(&self) -> Span { match *self { ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, - ast::TyParamBound::RegionTyParamBound(ref l) => l.span, + ast::TyParamBound::RegionTyParamBound(ref l) => l.ident.span, } } } @@ -173,11 +173,11 @@ impl Spanned for ast::TyParamBound { impl Spanned for ast::LifetimeDef { fn span(&self) -> Span { let hi = if self.bounds.is_empty() { - self.lifetime.span.hi() + self.lifetime.ident.span.hi() } else { - self.bounds[self.bounds.len() - 1].span.hi() + self.bounds[self.bounds.len() - 1].ident.span.hi() }; - mk_sp(self.lifetime.span.lo(), hi) + mk_sp(self.lifetime.ident.span.lo(), hi) } } diff --git a/src/types.rs b/src/types.rs index 615dc53fc4e..0c0cad8244b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -119,7 +119,7 @@ where for segment in iter { // Indicates a global path, shouldn't be rendered. - if segment.identifier.name == keywords::CrateRoot.name() { + if segment.ident.name == keywords::CrateRoot.name() { continue; } if first { @@ -155,7 +155,7 @@ enum SegmentParam<'a> { impl<'a> Spanned for SegmentParam<'a> { fn span(&self) -> Span { match *self { - SegmentParam::LifeTime(lt) => lt.span, + SegmentParam::LifeTime(lt) => lt.ident.span, SegmentParam::Type(ty) => ty.span, SegmentParam::Binding(binding) => binding.span, } @@ -215,7 +215,7 @@ fn rewrite_segment( shape: Shape, ) -> Option { let mut result = String::with_capacity(128); - result.push_str(&segment.identifier.name.as_str()); + result.push_str(&segment.ident.name.as_str()); let ident_len = result.len(); let shape = if context.use_block_indent() { diff --git a/src/utils.rs b/src/utils.rs index 055f75b4609..dae57882a35 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -42,7 +42,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { VisibilityKind::Crate(CrateSugar::JustCrate) => Cow::from("crate "), VisibilityKind::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string()); + let mut segments_iter = segments.iter().map(|seg| seg.ident.name.to_string()); if path.is_global() { segments_iter .next() @@ -190,9 +190,9 @@ pub fn last_line_extendable(s: &str) -> bool { #[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { - MetaItemKind::Word => meta_item.name == SKIP_ANNOTATION, + MetaItemKind::Word => meta_item.ident.name == SKIP_ANNOTATION, MetaItemKind::List(ref l) => { - meta_item.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + meta_item.ident.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) } _ => false, } diff --git a/src/vertical.rs b/src/vertical.rs index 887fefb2272..6cdaaafeb36 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -88,7 +88,7 @@ impl AlignedItem for ast::Field { fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; - let name = &self.ident.node.to_string(); + let name = &self.ident.name.to_string(); let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) } else { -- cgit 1.4.1-3-g733a5 From 7822d0c921af16dafa6134b00a20fdf49e63f99c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Apr 2018 09:54:07 +1200 Subject: Fix test --- src/expr.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b738d4ccb16..af51ae2ebc1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -173,13 +173,7 @@ pub fn format_expr( }, ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( - capture, - movability, - fn_decl, - body, - expr.span, - context, - shape, + capture, movability, fn_decl, body, expr.span, context, shape, ) } ast::ExprKind::Try(..) -- cgit 1.4.1-3-g733a5 From 48e5bc198829e23ef85a87f4ef2cb5c7fdf353f9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Apr 2018 16:31:53 +1200 Subject: Reorder config options cc #1974 --- src/config/mod.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index 75ee8e95835..6680c76aa64 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -43,19 +43,19 @@ create_config! { hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; tab_spaces: usize, 4, true, "Number of spaces per tab"; newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; use_small_heuristics: bool, true, false, "Whether to use different formatting for items and \ expressions if they satisfy a heuristic notion of 'small'."; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; - // strings and comments - format_strings: bool, false, false, "Format string literals where necessary"; + // Comments and strings wrap_comments: bool, false, true, "Break comments to fit on the line"; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; license_template_path: String, String::default(), false, "Beginning of file must match license template"; + format_strings: bool, false, false, "Format string literals where necessary"; - // Single line expressions and items. + // Single line expressions and items empty_item_single_line: bool, true, false, "Put empty-body functions and impls on a single line"; struct_lit_single_line: bool, true, false, @@ -78,8 +78,6 @@ create_config! { reorder_impl_items: bool, false, false, "Reorder impl items"; // Spaces around punctuation - binop_separator: SeparatorPlace, SeparatorPlace::Front, false, - "Where to put a binary operator when a binary expression goes multiline."; type_punctuation_density: TypeDensity, TypeDensity::Wide, false, "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; space_before_colon: bool, false, false, "Leave a space before the colon"; @@ -87,13 +85,15 @@ create_config! { spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; spaces_within_parens_and_brackets: bool, false, false, "Put spaces within non-empty parentheses or brackets"; + binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + "Where to put a binary operator when a binary expression goes multiline."; // Misc. + remove_blank_lines_at_start_or_end_of_block: bool, true, false, + "Remove blank lines at start or end of a block"; combine_control_expr: bool, true, false, "Combine control expressions with function calls."; struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ threshold."; - remove_blank_lines_at_start_or_end_of_block: bool, true, false, - "Remove blank lines at start or end of a block"; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; force_multiline_blocks: bool, false, false, @@ -102,10 +102,10 @@ create_config! { brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; - trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, - "How to handle trailing commas for lists"; trailing_semicolon: bool, true, false, "Add trailing semicolon after break, continue and return"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, + "How to handle trailing commas for lists"; match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; blank_lines_upper_bound: usize, 1, false, @@ -145,7 +145,7 @@ create_config! { ignore: IgnoreList, IgnoreList::default(), false, "Skip formatting the specified files and directories."; - // Not user-facing. + // Not user-facing verbose: bool, false, false, "Use verbose output"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ -- cgit 1.4.1-3-g733a5 From f14671131ed919659b534d5e86c7055995fa3f71 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Apr 2018 16:47:55 +1200 Subject: Make `error_on_line_overflow` false by default And improve docs, the error message, etc. I think false is the better default since such errors should only occur due to a bug in Rustfmt and therefore most users should not be notified of it happening (although to be clear, it might be a 'bug' which only occurs with pathological input and therefore we won't fix it). The error has proven to be confusing and annoying in the past. Closes #1080 --- Configurations.md | 7 +++++-- src/config/mod.rs | 2 +- src/lib.rs | 13 ++++++------- tests/lib.rs | 7 +++++-- 4 files changed, 17 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 1c6a8048017..ca804b2f7f2 100644 --- a/Configurations.md +++ b/Configurations.md @@ -579,9 +579,12 @@ Don't reformat anything ## `error_on_line_overflow` -Error if unable to get all lines within `max_width`, except for comments and string literals. +Error if Rustfmt is unable to get all lines within `max_width`, except for comments and string +literals. If this happens, then it is a bug in Rustfmt. You might be able to work around the bug by +refactoring your code to avoid long/complex expressions, usually by extracting a local variable or +using a shorter name. -- **Default value**: `true` +- **Default value**: `false` - **Possible values**: `true`, `false` - **Stable**: No diff --git a/src/config/mod.rs b/src/config/mod.rs index 6680c76aa64..7b96c2f671e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -134,7 +134,7 @@ create_config! { disable_all_formatting: bool, false, false, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; hide_parse_errors: bool, false, false, "Hide errors from the parser"; - error_on_line_overflow: bool, true, false, "Error if unable to get all lines within max_width"; + error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; error_on_unformatted: bool, false, false, "Error if unable to get comments or string literals within max_width, \ or they are left with trailing whitespaces"; diff --git a/src/lib.rs b/src/lib.rs index 6129dd494b9..9a7d0d2f881 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,7 +101,7 @@ pub enum ErrorKind { LineOverflow(usize, usize), // Line ends in whitespace TrailingWhitespace, - // TO-DO or FIX-ME item without an issue number + // TODO or FIXME item without an issue number BadIssue(Issue), // License check has failed LicenseCheck, @@ -112,8 +112,8 @@ impl fmt::Display for ErrorKind { match *self { ErrorKind::LineOverflow(found, maximum) => write!( fmt, - "line exceeded maximum width (maximum: {}, found: {})", - maximum, found + "line formatted, but exceeded maximum width (maximum: {} (see `max_width` option), found: {})", + maximum, found, ), ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), @@ -134,10 +134,9 @@ pub struct FormattingError { impl FormattingError { fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) - | ErrorKind::TrailingWhitespace - | ErrorKind::LicenseCheck => "error:", - ErrorKind::BadIssue(_) => "WARNING:", + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "internal error:", + ErrorKind::LicenseCheck => "error:", + ErrorKind::BadIssue(_) => "warning:", } } diff --git a/tests/lib.rs b/tests/lib.rs index 3b73247f7f8..3e388af0022 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -283,7 +283,8 @@ fn stdin_formatting_smoke_test() { fn format_lines_errors_are_reported() { let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); let input = Input::Text(format!("fn {}() {{}}", long_identifier)); - let config = Config::default(); + let mut config = Config::default(); + config.set().error_on_line_overflow(true); let (error_summary, _file_map, _report) = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); @@ -293,7 +294,9 @@ fn format_lines_errors_are_reported() { fn format_lines_errors_are_reported_with_tabs() { let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); - let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); + let mut config = Config::default(); + config.set().error_on_line_overflow(true); + config.set().hard_tabs(true); let (error_summary, _file_map, _report) = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); -- cgit 1.4.1-3-g733a5 From e784712f09d4978b5331ceaf96476bcf4b1b0b1b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Apr 2018 21:07:49 +1200 Subject: Try to fix a build regression before it happens --- src/imports.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index a66bcbd3e94..9a02ee64fb7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -309,19 +309,24 @@ impl UseTree { } } + let mut done = false; if aliased_self { - match self.path.last() { + match self.path.last_mut() { Some(UseSegment::Ident(_, ref mut old_rename)) => { assert!(old_rename.is_none()); - if let UseSegment::Slf(Some(rename)) = last { + if let UseSegment::Slf(Some(rename)) = last.clone() { *old_rename = Some(rename); - return self; + done = true; } } _ => unreachable!(), } } + if done { + return self; + } + // Normalise foo::{bar} -> foo::bar if let UseSegment::List(ref list) = last { if list.len() == 1 { -- cgit 1.4.1-3-g733a5 From 8208f8aa01a53ae681a6ff2b63cbb4547f3704f7 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Mon, 9 Apr 2018 00:43:17 -0700 Subject: Suppress unstable config options by default. This commit suppresses the output of unstable config options by default. Users can specify the `--unstable-features` option to show the config options that are unstable. Fixes #2611. --- src/bin/main.rs | 4 ++-- src/config/config_type.rs | 41 +++++++++++++++++++++---------------- src/config/mod.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 3ad2d3088f0..34c1bc59745 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -15,7 +15,7 @@ extern crate getopts; extern crate rustfmt_nightly as rustfmt; use std::fs::File; -use std::io::{self, Read, Write}; +use std::io::{self, stdout, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{env, error}; @@ -226,7 +226,7 @@ fn execute(opts: &Options) -> FmtResult { Ok(Summary::default()) } Operation::ConfigHelp => { - Config::print_docs(); + Config::print_docs(&mut stdout(), matches.opt_present("unstable-features")); Ok(Summary::default()) } Operation::ConfigOutputDefault { path } => { diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 53a4fdb8e57..0c38b6d28ad 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -81,6 +81,7 @@ macro_rules! is_nightly_channel { macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( use std::collections::HashSet; + use std::io::Write; #[derive(Clone)] pub struct Config { @@ -359,7 +360,7 @@ macro_rules! create_config { HIDE_OPTIONS.contains(&name) } - pub fn print_docs() { + pub fn print_docs(out: &mut Write, include_unstable: bool) { use std::cmp; let max = 0; $( let max = cmp::max(max, stringify!($i).len()+1); )+ @@ -367,25 +368,29 @@ macro_rules! create_config { for _ in 0..max { space_str.push(' '); } - println!("Configuration Options:"); + writeln!(out, "Configuration Options:").unwrap(); $( - let name_raw = stringify!($i); - - if !Config::is_hidden_option(name_raw) { - let mut name_out = String::with_capacity(max); - for _ in name_raw.len()..max-1 { - name_out.push(' ') + if $stb || include_unstable { + let name_raw = stringify!($i); + + if !Config::is_hidden_option(name_raw) { + let mut name_out = String::with_capacity(max); + for _ in name_raw.len()..max-1 { + name_out.push(' ') + } + name_out.push_str(name_raw); + name_out.push(' '); + writeln!(out, + "{}{} Default: {:?}{}", + name_out, + <$ty>::doc_hint(), + $def, + if !$stb { " (unstable)" } else { "" }).unwrap(); + $( + writeln!(out, "{}{}", space_str, $dstring).unwrap(); + )+ + writeln!(out).unwrap(); } - name_out.push_str(name_raw); - name_out.push(' '); - println!("{}{} Default: {:?}", - name_out, - <$ty>::doc_hint(), - $def); - $( - println!("{}{}", space_str, $dstring); - )+ - println!(); } )+ } diff --git a/src/config/mod.rs b/src/config/mod.rs index 7b96c2f671e..3676aed4ba9 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -181,6 +181,31 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { #[cfg(test)] mod test { use super::Config; + use std::str; + + #[allow(dead_code)] + mod mock { + use super::super::*; + + create_config! { + // Options that are used by the generated functions + max_width: usize, 100, true, "Maximum width of each line"; + use_small_heuristics: bool, true, false, "Whether to use different formatting for items and \ + expressions if they satisfy a heuristic notion of 'small'."; + license_template_path: String, String::default(), false, "Beginning of file must match license template"; + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, "Require a specific version of rustfmt."; + ignore: IgnoreList, IgnoreList::default(), false, "Skip formatting the specified files and directories."; + verbose: bool, false, false, "Use verbose output"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, "'small' heuristic values"; + + // Options that are used by the tests + stable_option: bool, false, true, "A stable option"; + unstable_option: bool, false, false, "An unstable option"; + } + } #[test] fn test_config_set() { @@ -218,6 +243,33 @@ mod test { assert_eq!(config.was_set().verbose(), false); } + #[test] + fn test_print_docs_exclude_unstable() { + use self::mock::Config; + + let mut output = Vec::new(); + Config::print_docs(&mut output, false); + + let s = str::from_utf8(&output).unwrap(); + + assert_eq!(s.contains("stable_option"), true); + assert_eq!(s.contains("unstable_option"), false); + assert_eq!(s.contains("(unstable)"), false); + } + + #[test] + fn test_print_docs_include_unstable() { + use self::mock::Config; + + let mut output = Vec::new(); + Config::print_docs(&mut output, true); + + let s = str::from_utf8(&output).unwrap(); + assert_eq!(s.contains("stable_option"), true); + assert_eq!(s.contains("unstable_option"), true); + assert_eq!(s.contains("(unstable)"), true); + } + // FIXME(#2183) these tests cannot be run in parallel because they use env vars // #[test] // fn test_as_not_nightly_channel() { -- cgit 1.4.1-3-g733a5 From 5dd203eabe747903c3374c1edf5b8e3baaa6a886 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Apr 2018 22:34:41 +0900 Subject: Add merge_imports config option --- Configurations.md | 22 ++++++++++++++++++++++ src/config/mod.rs | 1 + 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ca804b2f7f2..3122275e300 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1084,6 +1084,28 @@ use foo::{aaa, fff}; ``` +## `merge_imports` + +Merge multiple imports into a single nested import. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): + +```rust +use foo::{a, c, d}; +use foo::{b, g}; +use foo::{e, f}; +``` + +#### `true`: + +```rust +use foo::{a, b, c, d, e, f, g}; +``` + ## `match_block_trailing_comma` diff --git a/src/config/mod.rs b/src/config/mod.rs index 3676aed4ba9..292b2cd6915 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -66,6 +66,7 @@ create_config! { // Imports imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; + merge_imports: bool, false, false, "Merge imports"; // Ordering reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; -- cgit 1.4.1-3-g733a5 From 1954513ace66d81b62692f208fdaa91ab48c9757 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Apr 2018 22:35:04 +0900 Subject: Merge imports with the same prefix into a single nested import --- src/imports.rs | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/lists.rs | 10 ++ src/reorder.rs | 32 +++++-- 3 files changed, 306 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9a02ee64fb7..76fa7816f0d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -12,7 +12,7 @@ use std::cmp::Ordering; use config::lists::*; use syntax::ast::{self, UseTreeKind}; -use syntax::codemap::{BytePos, Span}; +use syntax::codemap::{self, BytePos, Span, DUMMY_SP}; use codemap::SpanUtils; use config::IndentStyle; @@ -24,6 +24,7 @@ use utils::mk_sp; use visitor::FmtVisitor; use std::borrow::Cow; +use std::fmt; /// Returns a name imported by a `use` declaration. e.g. returns `Ordering` /// for `std::cmp::Ordering` and `self` for `std::cmp::self`. @@ -89,7 +90,7 @@ impl<'a> FmtVisitor<'a> { // sorting. // FIXME we do a lot of allocation to make our own representation. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq)] pub enum UseSegment { Ident(String, Option), Slf(Option), @@ -98,12 +99,12 @@ pub enum UseSegment { List(Vec), } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct UseTree { pub path: Vec, pub span: Span, // Comment information within nested use tree. - list_item: Option, + pub list_item: Option, // Additional fields for top level use items. // Should we have another struct for top-level use items rather than reusing this? visibility: Option, @@ -143,12 +144,84 @@ impl UseSegment { } } +pub fn merge_use_trees(use_trees: Vec) -> Vec { + let mut result = Vec::with_capacity(use_trees.len()); + for use_tree in use_trees { + if use_tree.has_comment() || use_tree.attrs.is_some() { + result.push(use_tree); + continue; + } + + for flattened in use_tree.flatten() { + merge_use_trees_inner(&mut result, flattened); + } + } + result +} + +fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree) { + for tree in trees.iter_mut() { + if tree.share_prefix(&use_tree) { + tree.merge(use_tree); + return; + } + } + + trees.push(use_tree); +} + +impl fmt::Debug for UseTree { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl fmt::Debug for UseSegment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl fmt::Display for UseSegment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + UseSegment::Glob => write!(f, "*"), + UseSegment::Ident(ref s, _) => write!(f, "{}", s), + UseSegment::Slf(..) => write!(f, "self"), + UseSegment::Super(..) => write!(f, "super"), + UseSegment::List(ref list) => { + write!(f, "{{")?; + for (i, item) in list.iter().enumerate() { + let is_last = i == list.len() - 1; + write!(f, "{}", item)?; + if !is_last { + write!(f, ", ")?; + } + } + write!(f, "}}") + } + } + } +} +impl fmt::Display for UseTree { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for (i, segment) in self.path.iter().enumerate() { + let is_last = i == self.path.len() - 1; + write!(f, "{}", segment)?; + if !is_last { + write!(f, "::")?; + } + } + write!(f, "") + } +} + impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::with_capacity(256); if let Some(ref attrs) = self.attrs { - result.push_str(&attrs.rewrite(context, shape)?); + result.push_str(&attrs.rewrite(context, shape).expect("rewrite attr")); if !result.is_empty() { result.push_str(&shape.indent.to_string_with_newline(context.config)); } @@ -168,6 +241,17 @@ impl UseTree { Some(result) } + // FIXME: Use correct span? + fn from_path(path: Vec, span: Span) -> UseTree { + UseTree { + path, + span, + list_item: None, + visibility: None, + attrs: None, + } + } + pub fn from_ast_with_normalization( context: &RewriteContext, item: &ast::Item, @@ -360,6 +444,131 @@ impl UseTree { self.path.push(last); self } + + fn has_comment(&self) -> bool { + self.list_item.as_ref().map_or(false, |list_item| { + list_item.pre_comment.is_some() || list_item.post_comment.is_some() + }) + } + + fn same_visibility(&self, other: &UseTree) -> bool { + match (&self.visibility, &other.visibility) { + ( + Some(codemap::Spanned { + node: ast::VisibilityKind::Inherited, + .. + }), + None, + ) + | ( + None, + Some(codemap::Spanned { + node: ast::VisibilityKind::Inherited, + .. + }), + ) + | (None, None) => true, + ( + Some(codemap::Spanned { node: lnode, .. }), + Some(codemap::Spanned { node: rnode, .. }), + ) => lnode == rnode, + _ => false, + } + } + + fn share_prefix(&self, other: &UseTree) -> bool { + if self.path.is_empty() || other.path.is_empty() || self.attrs.is_some() + || !self.same_visibility(other) + { + false + } else { + self.path[0] == other.path[0] + } + } + + fn flatten(self) -> Vec { + if self.path.is_empty() { + return vec![self]; + } + match self.path.clone().last().unwrap() { + UseSegment::List(list) => { + let prefix = &self.path[..self.path.len() - 1]; + let mut result = vec![]; + for nested_use_tree in list.into_iter() { + for mut flattend in nested_use_tree.clone().flatten().iter_mut() { + let mut new_path = prefix.to_vec(); + new_path.append(&mut flattend.path); + result.push(UseTree { + path: new_path, + span: self.span, + list_item: None, + visibility: self.visibility.clone(), + attrs: None, + }); + } + } + + result + } + _ => vec![self], + } + } + + fn merge(&mut self, other: UseTree) { + let mut new_path = vec![]; + let mut len = 0; + for (i, (mut a, b)) in self.path + .clone() + .iter_mut() + .zip(other.path.clone().into_iter()) + .enumerate() + { + if *a == b { + len = i + 1; + new_path.push(b); + continue; + } else { + len = i; + break; + } + } + if let Some(merged) = merge_rest(&self.path, &other.path, len) { + new_path.push(merged); + self.span = self.span.to(other.span); + } + self.path = new_path; + } +} + +fn merge_rest(a: &[UseSegment], b: &[UseSegment], len: usize) -> Option { + let a_rest = &a[len..]; + let b_rest = &b[len..]; + if a_rest.is_empty() && b_rest.is_empty() { + return None; + } + if a_rest.is_empty() { + return Some(UseSegment::List(vec![ + UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), + UseTree::from_path(b_rest.to_vec(), DUMMY_SP), + ])); + } + if b_rest.is_empty() { + return Some(UseSegment::List(vec![ + UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), + UseTree::from_path(a_rest.to_vec(), DUMMY_SP), + ])); + } + if let UseSegment::List(mut list) = a_rest[0].clone() { + merge_use_trees_inner(&mut list, UseTree::from_path(b_rest.to_vec(), DUMMY_SP)); + list.sort(); + return Some(UseSegment::List(list.clone())); + } + let mut list = vec![ + UseTree::from_path(a_rest.to_vec(), DUMMY_SP), + UseTree::from_path(b_rest.to_vec(), DUMMY_SP), + ]; + list.sort(); + Some(UseSegment::List(list)) } impl PartialOrd for UseSegment { @@ -461,9 +670,12 @@ fn rewrite_nested_use_tree( IndentStyle::Visual => shape.visual_indent(0), }; for use_tree in use_tree_list { - let mut list_item = use_tree.list_item.clone()?; - list_item.item = use_tree.rewrite(context, nested_shape); - list_items.push(list_item); + if let Some(mut list_item) = use_tree.list_item.clone() { + list_item.item = use_tree.rewrite(context, nested_shape); + list_items.push(list_item); + } else { + list_items.push(ListItem::from_str(use_tree.rewrite(context, nested_shape)?)); + } } let (tactic, remaining_width) = if use_tree_list.iter().any(|use_segment| { use_segment @@ -683,6 +895,60 @@ mod test { parser.parse_in_list() } + macro parse_use_trees($($s:expr),* $(,)*) { + vec![ + $(parse_use_tree($s),)* + ] + } + + #[test] + fn test_use_tree_merge() { + macro test_merge([$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) { + assert_eq!( + merge_use_trees(parse_use_trees!($($input,)*)), + parse_use_trees!($($output,)*), + ); + } + + test_merge!(["a::b::{c, d}", "a::b::{e, f}"], ["a::b::{c, d, e, f}"]); + test_merge!(["a::b::c", "a::b"], ["a::b::{self, c}"]); + test_merge!(["a::b", "a::b"], ["a::b"]); + test_merge!(["a", "a::b", "a::b::c"], ["a::{self, b::{self, c}}"]); + test_merge!( + ["a::{b::{self, c}, d::e}", "a::d::f"], + ["a::{b::{self, c}, d::{e, f}}"] + ); + test_merge!( + ["a::d::f", "a::{b::{self, c}, d::e}"], + ["a::{b::{self, c}, d::{e, f}}"] + ); + test_merge!( + ["a::{c, d, b}", "a::{d, e, b, a, f}", "a::{f, g, c}"], + ["a::{a, b, c, d, e, f, g}"] + ); + } + + #[test] + fn test_use_tree_flatten() { + assert_eq!( + parse_use_tree("a::b::{c, d, e, f}").flatten(), + parse_use_trees!("a::b::c", "a::b::d", "a::b::e", "a::b::f",) + ); + + assert_eq!( + parse_use_tree("a::b::{c::{d, e, f}, g, h::{i, j, k}}").flatten(), + parse_use_trees![ + "a::b::c::d", + "a::b::c::e", + "a::b::c::f", + "a::b::g", + "a::b::h::i", + "a::b::h::j", + "a::b::h::k", + ] + ); + } + #[test] fn test_use_tree_normalize() { assert_eq!( diff --git a/src/lists.rs b/src/lists.rs index c4bd21869fb..266cd1b472b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -80,6 +80,16 @@ pub struct ListItem { } impl ListItem { + pub fn empty() -> ListItem { + ListItem { + pre_comment: None, + pre_comment_style: ListItemCommentStyle::None, + item: None, + post_comment: None, + new_lines: false, + } + } + pub fn inner_as_ref(&self) -> &str { self.item.as_ref().map_or("", |s| s) } diff --git a/src/reorder.rs b/src/reorder.rs index 15191995d02..099c25cfd9b 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -22,7 +22,7 @@ use syntax::{ast, attr, codemap::Span}; use attr::filter_inline_attrs; use codemap::LineRangeUtils; use comment::combine_strs_with_missing_comments; -use imports::UseTree; +use imports::{merge_use_trees, UseTree}; use items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use lists::{itemize_list, write_list, ListFormatting, ListItem}; use rewrite::{Rewrite, RewriteContext}; @@ -117,29 +117,41 @@ fn rewrite_reorderable_items( match reorderable_items[0].node { // FIXME: Remove duplicated code. ast::ItemKind::Use(..) => { - let normalized_items: Vec<_> = reorderable_items + let mut normalized_items: Vec<_> = reorderable_items .iter() .filter_map(|item| UseTree::from_ast_with_normalization(context, item)) .collect(); - - // 4 = "use ", 1 = ";" - let nested_shape = shape.offset_left(4)?.sub_width(1)?; + let cloned = normalized_items.clone(); + // Add comments before merging. let list_items = itemize_list( context.snippet_provider, - normalized_items.iter(), + cloned.iter(), "", ";", |item| item.span.lo(), |item| item.span.hi(), - |item| item.rewrite_top_level(context, nested_shape), + |_item| Some("".to_owned()), span.lo(), span.hi(), false, ); + for (item, list_item) in normalized_items.iter_mut().zip(list_items) { + item.list_item = Some(list_item.clone()); + } + if context.config.merge_imports() { + normalized_items = merge_use_trees(normalized_items); + } + normalized_items.sort(); - let mut item_pair_vec: Vec<_> = list_items.zip(&normalized_items).collect(); - item_pair_vec.sort_by(|a, b| a.1.cmp(b.1)); - let item_vec: Vec<_> = item_pair_vec.into_iter().map(|pair| pair.0).collect(); + // 4 = "use ", 1 = ";" + let nested_shape = shape.offset_left(4)?.sub_width(1)?; + let item_vec: Vec<_> = normalized_items + .into_iter() + .map(|use_tree| ListItem { + item: use_tree.rewrite_top_level(context, nested_shape), + ..use_tree.list_item.unwrap_or_else(|| ListItem::empty()) + }) + .collect(); wrap_reorderable_items(context, &item_vec, nested_shape) } -- cgit 1.4.1-3-g733a5 From 4a7e45ec28fcbee14cd143402c1129d30cef39f0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Apr 2018 23:03:11 +0900 Subject: Simplify UseTree::has_comment --- src/imports.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 76fa7816f0d..03df4aed6af 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -446,9 +446,7 @@ impl UseTree { } fn has_comment(&self) -> bool { - self.list_item.as_ref().map_or(false, |list_item| { - list_item.pre_comment.is_some() || list_item.post_comment.is_some() - }) + self.list_item.as_ref().map_or(false, ListItem::has_comment) } fn same_visibility(&self, other: &UseTree) -> bool { @@ -526,7 +524,6 @@ impl UseTree { if *a == b { len = i + 1; new_path.push(b); - continue; } else { len = i; break; -- cgit 1.4.1-3-g733a5 From 8820a59bd55d51ab4d30d7f215eb1993cae5aeaa Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 10 Apr 2018 12:36:41 +0900 Subject: Resolve review comments --- src/imports.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 03df4aed6af..c889ece4d07 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -172,13 +172,13 @@ fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree) { impl fmt::Debug for UseTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) + fmt::Display::fmt(self, f) } } impl fmt::Debug for UseSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self) + fmt::Display::fmt(self, f) } } @@ -221,7 +221,7 @@ impl UseTree { pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::with_capacity(256); if let Some(ref attrs) = self.attrs { - result.push_str(&attrs.rewrite(context, shape).expect("rewrite attr")); + result.push_str(&attrs.rewrite(context, shape)?); if !result.is_empty() { result.push_str(&shape.indent.to_string_with_newline(context.config)); } @@ -242,6 +242,10 @@ impl UseTree { } // FIXME: Use correct span? + // The given span is essentially incorrect, since we are reconstructing + // use statements. This should not be a problem, though, since we have + // already tried to extract comment and observed that there are no comment + // around the given use item, and the span will not be used afterward. fn from_path(path: Vec, span: Span) -> UseTree { UseTree { path, @@ -514,22 +518,18 @@ impl UseTree { fn merge(&mut self, other: UseTree) { let mut new_path = vec![]; - let mut len = 0; - for (i, (mut a, b)) in self.path + for (mut a, b) in self.path .clone() .iter_mut() .zip(other.path.clone().into_iter()) - .enumerate() { if *a == b { - len = i + 1; new_path.push(b); } else { - len = i; break; } } - if let Some(merged) = merge_rest(&self.path, &other.path, len) { + if let Some(merged) = merge_rest(&self.path, &other.path, new_path.len()) { new_path.push(merged); self.span = self.span.to(other.span); } -- cgit 1.4.1-3-g733a5 From 911395a45198fa18708da6622b11c4c16a5e52a2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 12 Mar 2018 17:24:04 +1300 Subject: Squash the various 'reorder imports' option into one cc #2185 --- Configurations.md | 117 +------------------------------- src/config/mod.rs | 9 +-- src/imports.rs | 1 + src/lib.rs | 2 +- src/reorder.rs | 12 ++-- tests/target/extern.rs | 13 ++-- tests/target/import-fencepost-length.rs | 2 +- tests/target/imports.rs | 2 +- 8 files changed, 19 insertions(+), 139 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ca804b2f7f2..8ace886a98f 100644 --- a/Configurations.md +++ b/Configurations.md @@ -6,7 +6,7 @@ A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this: ```toml indent_style = "Block" -reorder_imported_names = true +reorder_imports = false ``` Each configuration option is either stable or unstable. @@ -1240,31 +1240,10 @@ fn dolor() -> usize {} fn adipiscing() -> usize {} ``` -## `reorder_imported_names` - -Reorder lists of names in import statements alphabetically - -- **Default value**: `false` -- **Possible values**: `true`, `false` -- **Stable**: No - -#### `false` (default): - -```rust -use super::{lorem, ipsum, dolor, sit}; -``` - -#### `true`: - -```rust -use super::{dolor, ipsum, lorem, sit}; -``` - -See also [`reorder_imports`](#reorder_imports). ## `reorder_imports` -Reorder import statements alphabetically +Reorder import and extern crate statements alphabetically - **Default value**: `false` - **Possible values**: `true`, `false` @@ -1288,98 +1267,6 @@ use lorem; use sit; ``` -See also [`reorder_imported_names`](#reorder_imported_names), [`reorder_imports_in_group`](#reorder_imports_in_group). - -## `reorder_imports_in_group` - -Reorder import statements in group - -- **Default value**: `false` -- **Possible values**: `true`, `false` -- **Stable**: No - -**Note:** This option takes effect only when [`reorder_imports`](#reorder_imports) is set to `true`. - -#### `true` (default): - -```rust -use std::io; -use std::mem; - -use dolor; -use ipsum; -use lorem; -use sit; -``` - -#### `false`: - - -```rust -use dolor; -use ipsum; -use lorem; -use sit; -use std::io; -use std::mem; -``` - -See also [`reorder_imports`](#reorder_imports). - -## `reorder_extern_crates` - -Reorder `extern crate` statements alphabetically - -- **Default value**: `true` -- **Possible values**: `true`, `false` -- **Stable**: No - -#### `true` (default): - -```rust -extern crate dolor; -extern crate ipsum; -extern crate lorem; -extern crate sit; -``` - -#### `false`: - -```rust -extern crate lorem; -extern crate ipsum; - -extern crate dolor; -extern crate sit; -``` - -See also [`reorder_extern_crates_in_group`](#reorder_extern_crates_in_group). - -## `reorder_extern_crates_in_group` - -Reorder `extern crate` statements in group - -- **Default value**: `true` -- **Possible values**: `true`, `false` -- **Stable**: No - -#### `false` (default): - -This value has no influence beyond the effect of the [`reorder_extern_crates`](#reorder_extern_crates) option. Set [`reorder_extern_crates`](#reorder_extern_crates) to `false` if you do not want `extern crate` groups to be collapsed and ordered. - -#### `true`: - -**Note:** This only takes effect when [`reorder_extern_crates`](#reorder_extern_crates) is set to `true`. - -```rust -extern crate a; -extern crate b; - -extern crate dolor; -extern crate ipsum; -extern crate lorem; -extern crate sit; -``` ## `reorder_modules` diff --git a/src/config/mod.rs b/src/config/mod.rs index 3676aed4ba9..63a75f880b6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -68,14 +68,9 @@ create_config! { imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; // Ordering - reorder_extern_crates: bool, true, false, "Reorder extern crate statements alphabetically"; - reorder_extern_crates_in_group: bool, true, false, "Reorder extern crate statements in group"; - reorder_imports: bool, true, false, "Reorder import statements alphabetically"; - reorder_imports_in_group: bool, true, false, "Reorder import statements in group"; - reorder_imported_names: bool, true, false, - "Reorder lists of names in import statements alphabetically"; - reorder_modules: bool, true, false, "Reorder module statemtents alphabetically in group"; reorder_impl_items: bool, false, false, "Reorder impl items"; + reorder_imports: bool, true, false, "Reorder import and extern crate statements alphabetically"; + reorder_modules: bool, true, false, "Reorder module statements alphabetically in group"; // Spaces around punctuation type_punctuation_density: TypeDensity, TypeDensity::Wide, false, diff --git a/src/imports.rs b/src/imports.rs index 9a02ee64fb7..62273a86596 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -485,6 +485,7 @@ fn rewrite_nested_use_tree( ); (tactic, remaining_width) }; + let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; let fmt = ListFormatting { diff --git a/src/lib.rs b/src/lib.rs index 9a7d0d2f881..61eeb9332a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,8 +42,8 @@ use std::time::Duration; use syntax::ast; pub use syntax::codemap::FileName; use syntax::codemap::{CodeMap, FilePathMapping}; -use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::{DiagnosticBuilder, Handler}; +use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; diff --git a/src/reorder.rs b/src/reorder.rs index 15191995d02..273f20c9254 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -198,18 +198,18 @@ impl ReorderableItemKind { pub fn is_reorderable(&self, config: &Config) -> bool { match *self { - ReorderableItemKind::ExternCrate => config.reorder_extern_crates(), + ReorderableItemKind::ExternCrate => config.reorder_imports(), ReorderableItemKind::Mod => config.reorder_modules(), ReorderableItemKind::Use => config.reorder_imports(), ReorderableItemKind::Other => false, } } - pub fn in_group(&self, config: &Config) -> bool { + pub fn in_group(&self) -> bool { match *self { - ReorderableItemKind::ExternCrate => config.reorder_extern_crates_in_group(), - ReorderableItemKind::Mod => config.reorder_modules(), - ReorderableItemKind::Use => config.reorder_imports_in_group(), + ReorderableItemKind::ExternCrate => false, + ReorderableItemKind::Mod => true, + ReorderableItemKind::Use => true, ReorderableItemKind::Other => false, } } @@ -268,7 +268,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let item_kind = ReorderableItemKind::from(items[0]); if item_kind.is_reorderable(self.config) { let visited_items_num = - self.walk_reorderable_items(items, item_kind, item_kind.in_group(self.config)); + self.walk_reorderable_items(items, item_kind, item_kind.in_group()); let (_, rest) = items.split_at(visited_items_num); items = rest; } else { diff --git a/tests/target/extern.rs b/tests/target/extern.rs index b0aa51127d5..61989cace75 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,17 +1,14 @@ // rustfmt-normalize_comments: true -extern crate foo; -extern crate foo as bar; - +extern crate bar; extern crate chrono; extern crate dotenv; -extern crate futures; - -extern crate bar; extern crate foo; - -// #2315 +extern crate foo; +extern crate foo as bar; +extern crate futures; extern crate proc_macro; +// #2315 extern crate proc_macro2; extern "C" { diff --git a/tests/target/import-fencepost-length.rs b/tests/target/import-fencepost-length.rs index e4f885c09b1..9d247aaf6df 100644 --- a/tests/target/import-fencepost-length.rs +++ b/tests/target/import-fencepost-length.rs @@ -1,4 +1,4 @@ -use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, ddddddddd}; +use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 236fee95e82..b6d939fc125 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -54,9 +54,9 @@ use foo::{baz, qux as bar}; // With absolute paths use foo; +use Foo; use foo::Bar; use foo::{Bar, Baz}; -use Foo; use {Bar, Baz}; // Root globs -- cgit 1.4.1-3-g733a5 From 1c17dbbf74ada52bed7545251e7da94e82b6e520 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 Apr 2018 21:11:50 +1200 Subject: rebasing --- src/imports.rs | 79 ++++++++++++++------------------- src/lib.rs | 2 +- src/reorder.rs | 2 +- tests/target/extern.rs | 13 +++--- tests/target/import-fencepost-length.rs | 2 +- tests/target/imports.rs | 2 +- 6 files changed, 45 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 62273a86596..48b6af7fd46 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -185,7 +185,7 @@ impl UseTree { } else { Some(item.attrs.clone()) }, - ).normalize(context.config.reorder_imported_names()), + ).normalize(), ), _ => None, } @@ -271,7 +271,7 @@ impl UseTree { } // Do the adjustments that rustfmt does elsewhere to use paths. - pub fn normalize(mut self, do_sort: bool) -> UseTree { + pub fn normalize(mut self) -> UseTree { let mut last = self.path.pop().expect("Empty use tree?"); // Hack around borrow checker. let mut normalize_sole_list = false; @@ -340,7 +340,7 @@ impl UseTree { for seg in &list[0].path { self.path.push(seg.clone()); } - return self.normalize(do_sort); + return self.normalize(); } _ => unreachable!(), } @@ -349,11 +349,9 @@ impl UseTree { // Recursively normalize elements of a list use (including sorting the list). if let UseSegment::List(list) = last { let mut list = list.into_iter() - .map(|ut| ut.normalize(do_sort)) + .map(|ut| ut.normalize()) .collect::>(); - if do_sort { - list.sort(); - } + list.sort(); last = UseSegment::List(list); } @@ -686,75 +684,64 @@ mod test { #[test] fn test_use_tree_normalize() { + assert_eq!(parse_use_tree("a::self").normalize(), parse_use_tree("a")); assert_eq!( - parse_use_tree("a::self").normalize(true), - parse_use_tree("a") - ); - assert_eq!( - parse_use_tree("a::self as foo").normalize(true), + parse_use_tree("a::self as foo").normalize(), parse_use_tree("a as foo") ); + assert_eq!(parse_use_tree("a::{self}").normalize(), parse_use_tree("a")); + assert_eq!(parse_use_tree("a::{b}").normalize(), parse_use_tree("a::b")); assert_eq!( - parse_use_tree("a::{self}").normalize(true), - parse_use_tree("a") - ); - assert_eq!( - parse_use_tree("a::{b}").normalize(true), - parse_use_tree("a::b") - ); - assert_eq!( - parse_use_tree("a::{b, c::self}").normalize(true), + parse_use_tree("a::{b, c::self}").normalize(), parse_use_tree("a::{b, c}") ); assert_eq!( - parse_use_tree("a::{b as bar, c::self}").normalize(true), + parse_use_tree("a::{b as bar, c::self}").normalize(), parse_use_tree("a::{b as bar, c}") ); } #[test] fn test_use_tree_ord() { - assert!(parse_use_tree("a").normalize(true) < parse_use_tree("aa").normalize(true)); - assert!(parse_use_tree("a").normalize(true) < parse_use_tree("a::a").normalize(true)); - assert!(parse_use_tree("a").normalize(true) < parse_use_tree("*").normalize(true)); - assert!(parse_use_tree("a").normalize(true) < parse_use_tree("{a, b}").normalize(true)); - assert!(parse_use_tree("*").normalize(true) < parse_use_tree("{a, b}").normalize(true)); + assert!(parse_use_tree("a").normalize() < parse_use_tree("aa").normalize()); + assert!(parse_use_tree("a").normalize() < parse_use_tree("a::a").normalize()); + assert!(parse_use_tree("a").normalize() < parse_use_tree("*").normalize()); + assert!(parse_use_tree("a").normalize() < parse_use_tree("{a, b}").normalize()); + assert!(parse_use_tree("*").normalize() < parse_use_tree("{a, b}").normalize()); assert!( - parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, dddddddd}").normalize(true) - < parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, ddddddddd}").normalize(true) - ); - assert!( - parse_use_tree("serde::de::{Deserialize}").normalize(true) - < parse_use_tree("serde_json").normalize(true) + parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, dddddddd}").normalize() + < parse_use_tree("aaaaaaaaaaaaaaa::{bb, cc, ddddddddd}").normalize() ); assert!( - parse_use_tree("a::b::c").normalize(true) < parse_use_tree("a::b::*").normalize(true) + parse_use_tree("serde::de::{Deserialize}").normalize() + < parse_use_tree("serde_json").normalize() ); + assert!(parse_use_tree("a::b::c").normalize() < parse_use_tree("a::b::*").normalize()); assert!( - parse_use_tree("foo::{Bar, Baz}").normalize(true) - < parse_use_tree("{Bar, Baz}").normalize(true) + parse_use_tree("foo::{Bar, Baz}").normalize() + < parse_use_tree("{Bar, Baz}").normalize() ); assert!( - parse_use_tree("foo::{self as bar}").normalize(true) - < parse_use_tree("foo::{qux as bar}").normalize(true) + parse_use_tree("foo::{self as bar}").normalize() + < parse_use_tree("foo::{qux as bar}").normalize() ); assert!( - parse_use_tree("foo::{qux as bar}").normalize(true) - < parse_use_tree("foo::{baz, qux as bar}").normalize(true) + parse_use_tree("foo::{qux as bar}").normalize() + < parse_use_tree("foo::{baz, qux as bar}").normalize() ); assert!( - parse_use_tree("foo::{self as bar, baz}").normalize(true) - < parse_use_tree("foo::{baz, qux as bar}").normalize(true) + parse_use_tree("foo::{self as bar, baz}").normalize() + < parse_use_tree("foo::{baz, qux as bar}").normalize() ); - assert!(parse_use_tree("foo").normalize(true) < parse_use_tree("Foo").normalize(true)); - assert!(parse_use_tree("foo").normalize(true) < parse_use_tree("foo::Bar").normalize(true)); + assert!(parse_use_tree("foo").normalize() < parse_use_tree("Foo").normalize()); + assert!(parse_use_tree("foo").normalize() < parse_use_tree("foo::Bar").normalize()); assert!( - parse_use_tree("std::cmp::{d, c, b, a}").normalize(true) - < parse_use_tree("std::cmp::{b, e, g, f}").normalize(true) + parse_use_tree("std::cmp::{d, c, b, a}").normalize() + < parse_use_tree("std::cmp::{b, e, g, f}").normalize() ); } } diff --git a/src/lib.rs b/src/lib.rs index 61eeb9332a6..9a7d0d2f881 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,8 +42,8 @@ use std::time::Duration; use syntax::ast; pub use syntax::codemap::FileName; use syntax::codemap::{CodeMap, FilePathMapping}; -use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use checkstyle::{output_footer, output_header}; diff --git a/src/reorder.rs b/src/reorder.rs index 273f20c9254..e4065146cc6 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -207,7 +207,7 @@ impl ReorderableItemKind { pub fn in_group(&self) -> bool { match *self { - ReorderableItemKind::ExternCrate => false, + ReorderableItemKind::ExternCrate => true, ReorderableItemKind::Mod => true, ReorderableItemKind::Use => true, ReorderableItemKind::Other => false, diff --git a/tests/target/extern.rs b/tests/target/extern.rs index 61989cace75..b0aa51127d5 100644 --- a/tests/target/extern.rs +++ b/tests/target/extern.rs @@ -1,14 +1,17 @@ // rustfmt-normalize_comments: true -extern crate bar; -extern crate chrono; -extern crate dotenv; -extern crate foo; extern crate foo; extern crate foo as bar; + +extern crate chrono; +extern crate dotenv; extern crate futures; -extern crate proc_macro; + +extern crate bar; +extern crate foo; + // #2315 +extern crate proc_macro; extern crate proc_macro2; extern "C" { diff --git a/tests/target/import-fencepost-length.rs b/tests/target/import-fencepost-length.rs index 9d247aaf6df..e4f885c09b1 100644 --- a/tests/target/import-fencepost-length.rs +++ b/tests/target/import-fencepost-length.rs @@ -1,4 +1,4 @@ +use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, dddddddd}; use aaaaaaaaaaaaaaa::{bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccccccccccccc, ddddddddd}; -use aaaaaaaaaaaaaaa::bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index b6d939fc125..236fee95e82 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -54,9 +54,9 @@ use foo::{baz, qux as bar}; // With absolute paths use foo; -use Foo; use foo::Bar; use foo::{Bar, Baz}; +use Foo; use {Bar, Baz}; // Root globs -- cgit 1.4.1-3-g733a5 From 305c6405534f9b33f44ccb5b9de87bd00f006ef3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Apr 2018 10:50:19 +1200 Subject: Review changes --- Configurations.md | 5 +++-- src/config/mod.rs | 2 +- src/reorder.rs | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 8ace886a98f..26d540b70b5 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1243,9 +1243,10 @@ fn adipiscing() -> usize {} ## `reorder_imports` -Reorder import and extern crate statements alphabetically +Reorder import and extern crate statements alphabetically in groups (a group is +separated by a newline). -- **Default value**: `false` +- **Default value**: `true` - **Possible values**: `true`, `false` - **Stable**: No diff --git a/src/config/mod.rs b/src/config/mod.rs index 63a75f880b6..62d025ad5a1 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -68,9 +68,9 @@ create_config! { imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; // Ordering - reorder_impl_items: bool, false, false, "Reorder impl items"; reorder_imports: bool, true, false, "Reorder import and extern crate statements alphabetically"; reorder_modules: bool, true, false, "Reorder module statements alphabetically in group"; + reorder_impl_items: bool, false, false, "Reorder impl items"; // Spaces around punctuation type_punctuation_density: TypeDensity, TypeDensity::Wide, false, diff --git a/src/reorder.rs b/src/reorder.rs index e4065146cc6..ed307e679dd 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -207,9 +207,9 @@ impl ReorderableItemKind { pub fn in_group(&self) -> bool { match *self { - ReorderableItemKind::ExternCrate => true, - ReorderableItemKind::Mod => true, - ReorderableItemKind::Use => true, + ReorderableItemKind::ExternCrate + | ReorderableItemKind::Mod + | ReorderableItemKind::Use => true, ReorderableItemKind::Other => false, } } -- cgit 1.4.1-3-g733a5 From e58e97783ee865a0603e5be59e7116cc19f5ae2b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 12 Apr 2018 09:54:00 +0900 Subject: Preserve trailing comma on macro call when using mixed layout --- src/lists.rs | 5 +---- tests/source/macros.rs | 7 +++++++ tests/target/macros.rs | 13 +++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index c4bd21869fb..a14d1907a8c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -279,10 +279,7 @@ where } if last && formatting.ends_with_newline { - match formatting.trailing_separator { - SeparatorTactic::Always | SeparatorTactic::Vertical => separate = true, - _ => (), - } + separate = formatting.trailing_separator != SeparatorTactic::Never; } if line_len > 0 { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 6e730fffbf6..cd45b7a5d3f 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -373,3 +373,10 @@ fn foo() { fn foo() { let _ = column!(/* here */); } + +// #2616 +// Preserve trailing comma when using mixed layout for macro call. +fn foo() { + foo!(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + foo!(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,); +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index d430f5711dd..76e538bb85d 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -948,3 +948,16 @@ fn foo() { fn foo() { let _ = column!(/* here */); } + +// #2616 +// Preserve trailing comma when using mixed layout for macro call. +fn foo() { + foo!( + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + ); + foo!( + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + ); +} -- cgit 1.4.1-3-g733a5 From 8b731db6ba15babda5f70cb2f93a18504f8a772d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 12 Apr 2018 13:45:12 +0900 Subject: Output xml header and footer only once --- src/bin/main.rs | 15 ++++++++++++--- src/lib.rs | 6 +----- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 34c1bc59745..330bec55588 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -22,6 +22,7 @@ use std::{env, error}; use getopts::{Matches, Options}; +use rustfmt::checkstyle; use rustfmt::config::file_lines::FileLines; use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; use rustfmt::{run, FileName, Input, Summary}; @@ -29,6 +30,8 @@ use rustfmt::{run, FileName, Input, Summary}; type FmtError = Box; type FmtResult = std::result::Result; +const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle]"; + /// Rustfmt operations. enum Operation { /// Format files and their child modules. @@ -87,8 +90,8 @@ impl CliOptions { options.write_mode = Some(write_mode); } else { return Err(FmtError::from(format!( - "Invalid write-mode: {}", - write_mode + "Invalid write-mode: {}, expected one of {}", + write_mode, WRITE_MODE_LIST ))); } } @@ -206,7 +209,7 @@ fn make_opts() -> Options { "", "write-mode", "How to write output (not usable when piping from stdin)", - "[replace|overwrite|display|plain|diff|coverage|checkstyle]", + WRITE_MODE_LIST, ); opts @@ -260,7 +263,10 @@ fn execute(opts: &Options) -> FmtResult { let mut error_summary = Summary::default(); if config.version_meets_requirement(&mut error_summary) { + let mut out = &mut stdout(); + checkstyle::output_header(&mut out, config.write_mode())?; error_summary.add(run(Input::Text(input), &config)); + checkstyle::output_footer(&mut out, config.write_mode())?; } Ok(error_summary) @@ -294,6 +300,8 @@ fn execute(opts: &Options) -> FmtResult { } } + let mut out = &mut stdout(); + checkstyle::output_header(&mut out, config.write_mode())?; let mut error_summary = Summary::default(); for file in files { if !file.exists() { @@ -327,6 +335,7 @@ fn execute(opts: &Options) -> FmtResult { error_summary.add(run(Input::File(file), &config)); } } + checkstyle::output_footer(&mut out, config.write_mode())?; // If we were given a path via dump-minimal-config, output any options // that were used during formatting as TOML. diff --git a/src/lib.rs b/src/lib.rs index 9a7d0d2f881..c14737a8ebf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,6 @@ use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; -use checkstyle::{output_footer, output_header}; use comment::{CharClasses, FullCodeCharKind, LineClasses}; use issues::{BadIssueSeeker, Issue}; use shape::Indent; @@ -61,7 +60,7 @@ mod utils; mod attr; mod chains; -mod checkstyle; +pub mod checkstyle; mod closures; pub mod codemap; mod comment; @@ -883,11 +882,8 @@ pub enum Input { pub fn run(input: Input, config: &Config) -> Summary { let out = &mut stdout(); - output_header(out, config.write_mode()).ok(); match format_input(input, config, Some(out)) { Ok((summary, _, report)) => { - output_footer(out, config.write_mode()).ok(); - if report.has_warnings() { match term::stderr() { Some(ref t) -- cgit 1.4.1-3-g733a5 From 01c1f99e3991caddabf9e90e6c5d3db6edf87f30 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 14 Apr 2018 10:15:39 +1200 Subject: Fallout from removing TupField --- src/chains.rs | 22 +++++++++++++++------- src/expr.rs | 2 -- src/utils.rs | 1 - 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 15ecd6034f3..50e8ba6cdef 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -393,7 +393,6 @@ fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { Some(convert_try(&expressions[0], context)) } - ast::ExprKind::TupField(ref subexpr, _) | ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), _ => None, @@ -440,19 +439,28 @@ fn rewrite_chain_subexpr( }; rewrite_method_call(segment.ident, types, expressions, span, context, shape) } - ast::ExprKind::Field(_, ref field) => rewrite_element(format!(".{}", field.name)), - ast::ExprKind::TupField(ref expr, ref field) => { - let space = match expr.node { - ast::ExprKind::TupField(..) => " ", - _ => "", + ast::ExprKind::Field(ref nested, ref field) => { + let space = if is_tup_field_access(expr) && is_tup_field_access(nested) { + " " + } else { + "" }; - rewrite_element(format!("{}.{}", space, field.node)) + rewrite_element(format!("{}.{}", space, field.name)) } ast::ExprKind::Try(_) => rewrite_element(String::from("?")), _ => unreachable!(), } } +fn is_tup_field_access(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Field(_, ref field) => { + field.name.to_string().chars().all(|c| c.is_digit(10)) + } + _ => false, + } +} + // Determines if we can continue formatting a given expression on the same line. fn is_continuable(expr: &ast::Expr) -> bool { match expr.node { diff --git a/src/expr.rs b/src/expr.rs index af51ae2ebc1..7c4c16178a7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -178,7 +178,6 @@ pub fn format_expr( } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) - | ast::ExprKind::TupField(..) | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), ast::ExprKind::Mac(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { @@ -1349,7 +1348,6 @@ fn is_simple_expr(expr: &ast::Expr) -> bool { | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Field(ref expr, _) | ast::ExprKind::Try(ref expr) - | ast::ExprKind::TupField(ref expr, _) | ast::ExprKind::Unary(_, ref expr) => is_simple_expr(expr), ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { is_simple_expr(lhs) && is_simple_expr(rhs) diff --git a/src/utils.rs b/src/utils.rs index dae57882a35..00d6cf8ed08 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -365,7 +365,6 @@ pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { | ast::ExprKind::Assign(ref e, _) | ast::ExprKind::AssignOp(_, ref e, _) | ast::ExprKind::Field(ref e, _) - | ast::ExprKind::TupField(ref e, _) | ast::ExprKind::Index(ref e, _) | ast::ExprKind::Range(Some(ref e), _, _) | ast::ExprKind::Try(ref e) => left_most_sub_expr(e), -- cgit 1.4.1-3-g733a5 From 1415a4dc23f28644cb197b6bb69c311245c216e2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 14 Apr 2018 10:20:08 +1200 Subject: Fix tests --- src/chains.rs | 5 +++-- src/expr.rs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 50e8ba6cdef..94099002f73 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -393,8 +393,9 @@ fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { Some(convert_try(&expressions[0], context)) } - | ast::ExprKind::Field(ref subexpr, _) - | ast::ExprKind::Try(ref subexpr) => Some(convert_try(subexpr, context)), + ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) => { + Some(convert_try(subexpr, context)) + } _ => None, } } diff --git a/src/expr.rs b/src/expr.rs index 7c4c16178a7..5f786f96500 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -176,9 +176,9 @@ pub fn format_expr( capture, movability, fn_decl, body, expr.span, context, shape, ) } - ast::ExprKind::Try(..) - | ast::ExprKind::Field(..) - | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape), + ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => { + rewrite_chain(expr, context, shape) + } ast::ExprKind::Mac(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( -- cgit 1.4.1-3-g733a5 From 61d29eb70c14806e0a28c70a1ab6f162c2c0ef82 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 16 Apr 2018 17:11:50 +0900 Subject: Add spaces between consecutive `..` `..=` --- src/expr.rs | 33 ++++++++++++++++++++++++++++----- tests/source/expr.rs | 6 ++++++ tests/target/expr.rs | 6 ++++++ 3 files changed, 40 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 5f786f96500..84ecbb57184 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -248,14 +248,37 @@ pub fn format_expr( } } + fn needs_space_after_range(rhs: &ast::Expr) -> bool { + match rhs.node { + // Don't format `.. ..` into `....`, which is invalid. + // + // This check is unnecessary for `lhs`, because a range + // starting from another range needs parentheses as `(x ..) ..` + // (`x .. ..` is a range from `x` to `..`). + ast::ExprKind::Range(None, _, _) => true, + _ => false, + } + } + + let default_sp_delim = |lhs: Option<&ast::Expr>, rhs: Option<&ast::Expr>| { + let space_if = |b: bool| if b { " " } else { "" }; + + format!( + "{}{}{}", + lhs.map(|lhs| space_if(needs_space_before_range(context, lhs))) + .unwrap_or(""), + delim, + rhs.map(|rhs| space_if(needs_space_after_range(rhs))) + .unwrap_or(""), + ) + }; + match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) { (Some(lhs), Some(rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { format!(" {} ", delim) - } else if needs_space_before_range(context, lhs) { - format!(" {}", delim) } else { - delim.to_owned() + default_sp_delim(Some(lhs), Some(rhs)) }; rewrite_pair( &*lhs, @@ -270,7 +293,7 @@ pub fn format_expr( let sp_delim = if context.config.spaces_around_ranges() { format!("{} ", delim) } else { - delim.to_owned() + default_sp_delim(None, Some(rhs)) }; rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) } @@ -278,7 +301,7 @@ pub fn format_expr( let sp_delim = if context.config.spaces_around_ranges() { format!(" {}", delim) } else { - delim.to_owned() + default_sp_delim(Some(lhs), None) }; rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 6367dbc95b8..d5b0babc5bb 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -384,3 +384,9 @@ fn bar(&self) { } } } + +fn dots() { + .. .. ..; // (.. (.. (..))) + ..= ..= ..; + (..) .. ..; // ((..) .. (..)) +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 09e1e8afd1a..911a44f0630 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -409,3 +409,9 @@ impl Foo { } } } + +fn dots() { + .. .. ..; // (.. (.. (..))) + ..= ..= ..; + (..).. ..; // ((..) .. (..)) +} -- cgit 1.4.1-3-g733a5 From f9532ba8d7ffec4bbd2698c048c383910fe714c4 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Thu, 19 Apr 2018 19:14:11 -0400 Subject: Implemented rough draft of `check` write mode. (#2539) * Add rough draft of `check` mode. Not unit tested. * Added assert-cli; simple test case for `--write-mode=check` * Lightly documented `check` WriteMode * wrote clearer phrasing for config::options::WriteMode::Check * Implemented default for WriteMode where default is Overwrite * Simplified exit code handling * updated README.md as per @nrc' comment * collapsed exit-code handling * Removed write_mode from Summary, introduced partial option parsing earlier * Handle write-mode parsing in a slightly better way. --- Cargo.lock | 237 +++++++++++++++++++++++++++++++++++++------------- Cargo.toml | 1 + README.md | 5 +- src/bin/main.rs | 27 +++--- src/config/mod.rs | 2 +- src/config/options.rs | 9 ++ src/config/summary.rs | 5 +- src/filemap.rs | 13 +++ src/lib.rs | 1 + tests/lib.rs | 27 ++++++ 10 files changed, 252 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 8f1414166e1..ee76b020476 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,19 @@ dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "assert_cli" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.8" @@ -18,7 +31,7 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -33,20 +46,42 @@ name = "backtrace-sys" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytecount" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cargo_metadata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cargo_metadata" version = "0.5.4" @@ -54,14 +89,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -69,14 +104,22 @@ name = "cfg-if" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "colored" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive-new" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -84,6 +127,11 @@ name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "difference" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "dtoa" version = "0.4.2" @@ -104,7 +152,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -114,12 +162,17 @@ dependencies = [ "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "environment" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -141,6 +194,11 @@ name = "getopts" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "humantime" version = "1.1.1" @@ -171,6 +229,11 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lazy_static" version = "1.0.0" @@ -232,18 +295,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.2.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "proc-macro2" -version = "0.3.6" +name = "pulldown-cmark" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -251,14 +314,6 @@ name = "quick-error" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "quote" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quote" version = "0.5.1" @@ -297,19 +352,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "remove_dir_all" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_cratesio_shim" version = "103.0.0" @@ -390,10 +453,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "rustfmt-nightly" version = "0.4.2" dependencies = [ + "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -401,27 +465,45 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "same-file" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scoped-tls" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "semver" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -431,23 +513,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.37" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.37" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -456,13 +538,28 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "skeptic" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytecount 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -477,22 +574,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.12.15" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "syn" -version = "0.13.1" +name = "tempdir" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -545,7 +641,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -586,6 +682,16 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -625,28 +731,37 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930" "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" -"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum bytecount 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af27422163679dea46a1a7239dffff64d3dcdc3ba5fe9c49c789fbfe0eb949de" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" +"checksum cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f56ec3e469bca7c276f2eea015aa05c5e381356febdbb0683c2580189604537" "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3" -"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" +"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71" +"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" +"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" +"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834" -"checksum env_logger 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0f475037312b91d34dbc3142a1ad3980ef0d070c7a855ce238afdd5e987cfecc" +"checksum env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "be27f8ea102a7182093a80d98f0b78623b580eda8791cbe8e2345fe6e57567a6" +"checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" @@ -655,16 +770,16 @@ dependencies = [ "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" -"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" -"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" "checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" -"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" +"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" +"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" "checksum rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "463834ac5ea777cb56c073586675fac37292f8425aafb3757efca7e6a76545aa" "checksum rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d256eeab1b8639c2a1fd341e54f3613f8150bc262e4ec9361a29bbcb162906d" "checksum rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6dd73033bb512845a6df347174c65ad430c92ecd35527e24d8bb186f5664ee" @@ -672,17 +787,20 @@ dependencies = [ "checksum rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f02edede4ba70963a7dac2308876f03f76f9edd48a035e5abc8fa37c57a77c8" "checksum rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8e50d4c38121fa8ded3ffbf94926ec74c95f24316c3b80de84fbfb42c005cf" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" +"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" +"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" -"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" -"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" -"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" +"checksum serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "53e6b6859395f46cf528414659ce43e70902b2277519707c3bd91797b3320330" +"checksum serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "16e97f8dc5b2dabc0183e0cde24b1a53835e5bb3d2c9e0fdb077f895bba7f2a9" +"checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" +"checksum serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7bf1cbb1387028a13739cb018ee0d9b3db534f22ca3c84a5904f7eadfde14e75" +"checksum skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c8431f8fca168e2db4be547bd8329eac70d095dff1444fee4b0fa0fabc7df75a" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" -"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" @@ -696,6 +814,7 @@ dependencies = [ "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 719f56667f5..e989e123dbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ rustc-ap-syntax = "103.0.0" [dev-dependencies] lazy_static = "1.0.0" +assert_cli = "0.5" [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/README.md b/README.md index 49fedfdb286..020d6bf3b20 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ read data from stdin. Alternatively, you can use `cargo fmt` to format all binary and library targets of your crate. You'll probably want to specify the write mode. Currently, there are modes for -`diff`, `replace`, `overwrite`, `display`, `coverage`, `checkstyle`, and `plain`. +`check`, `diff`, `replace`, `overwrite`, `display`, `coverage`, `checkstyle`, and `plain`. * `overwrite` Is the default and overwrites the original files _without_ creating backups. * `replace` Overwrites the original files after creating backups of the files. @@ -114,6 +114,9 @@ You'll probably want to specify the write mode. Currently, there are modes for * `plain` Also writes to stdout, but with no metadata. * `diff` Will print a diff between the original files and formatted files to stdout. Will also exit with an error code if there are any differences. +* `check` Checks if the program's formatting matches what rustfmt would do. Silently exits + with code 0 if so, emits a diff and exits with code 1 if not. This option is + designed to be run in CI-like where a non-zero exit signifies incorrect formatting. * `checkstyle` Will output the lines that need to be corrected as a checkstyle XML file, that can be used by tools like Jenkins. diff --git a/src/bin/main.rs b/src/bin/main.rs index 330bec55588..ff0961fd2e2 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -30,7 +30,7 @@ use rustfmt::{run, FileName, Input, Summary}; type FmtError = Box; type FmtResult = std::result::Result; -const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle]"; +const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle|check]"; /// Rustfmt operations. enum Operation { @@ -303,6 +303,7 @@ fn execute(opts: &Options) -> FmtResult { let mut out = &mut stdout(); checkstyle::output_header(&mut out, config.write_mode())?; let mut error_summary = Summary::default(); + for file in files { if !file.exists() { eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); @@ -350,22 +351,28 @@ fn execute(opts: &Options) -> FmtResult { } } +fn determine_write_mode(opts: &Options) -> WriteMode { + let matches = opts.parse(env::args().skip(1)).unwrap(); + let options = CliOptions::from_matches(&matches).unwrap(); + match options.write_mode { + Some(m) => m, + None => WriteMode::default(), + } +} + fn main() { env_logger::init(); - let opts = make_opts(); + // Only handles arguments passed in through the CLI. + let write_mode = determine_write_mode(&opts); let exit_code = match execute(&opts) { Ok(summary) => { - if summary.has_operational_errors() { + if summary.has_operational_errors() + || summary.has_diff && write_mode == WriteMode::Check + || summary.has_parsing_errors() || summary.has_formatting_errors() + { 1 - } else if summary.has_parsing_errors() { - 2 - } else if summary.has_formatting_errors() { - 3 - } else if summary.has_diff { - // should only happen in diff mode - 4 } else { assert!(summary.has_no_errors()); 0 diff --git a/src/config/mod.rs b/src/config/mod.rs index 8cc55ebac4b..274a40a2ae7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -120,7 +120,7 @@ create_config! { // Control options (changes the operation of rustfmt, rather than the formatting) write_mode: WriteMode, WriteMode::Overwrite, false, "What Write Mode to use when none is supplied: \ - Replace, Overwrite, Display, Plain, Diff, Coverage"; + Replace, Overwrite, Display, Plain, Diff, Coverage, Check"; color: Color, Color::Auto, false, "What Color option to use when none is supplied: Always, Never, Auto"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, diff --git a/src/config/options.rs b/src/config/options.rs index eca206a75fe..0bb53f046ac 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -183,6 +183,9 @@ configuration_option_enum! { WriteMode: Checkstyle, // Output the changed lines (for internal value only) Modified, + // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. + // This option is designed to be run in CI where a non-zero exit signifies non-standard code formatting. + Check, } configuration_option_enum! { Color: @@ -250,6 +253,12 @@ impl ::std::str::FromStr for WidthHeuristics { } } +impl Default for WriteMode { + fn default() -> WriteMode { + WriteMode::Overwrite + } +} + /// A set of directories, files and modules that rustfmt should ignore. #[derive(Default, Deserialize, Serialize, Clone, Debug)] pub struct IgnoreList(HashSet); diff --git a/src/config/summary.rs b/src/config/summary.rs index 99bf752f2b9..3654ea89df4 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -104,10 +104,7 @@ impl Summary { pub fn print_exit_codes() { let exit_codes = r#"Exit Codes: 0 = No errors - 1 = Encountered operational errors e.g. an IO error - 2 = Failed to reformat code because of parsing errors - 3 = Code is valid, but it is impossible to format it properly - 4 = Formatted code differs from existing code (write-mode diff only)"#; + 1 = Encountered error in formatting code"#; println!("{}", exit_codes); } } diff --git a/src/filemap.rs b/src/filemap.rs index ee2253043a1..ce9134b131e 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -178,6 +178,19 @@ where let diff = create_diff(filename, text, config)?; output_checkstyle_file(out, filename, diff)?; } + WriteMode::Check => { + let filename = filename_to_path(); + if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { + let mismatch = make_diff(&ori, &fmt, 3); + let has_diff = !mismatch.is_empty(); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), + config.color(), + ); + return Ok(has_diff); + } + } } // when we are not in diff mode, don't indicate differing files diff --git a/src/lib.rs b/src/lib.rs index c14737a8ebf..ddb3ebeb2e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![allow(stable_features)] #![feature(match_default_bindings)] #![feature(type_ascription)] +#![feature(unicode_internals)] #[macro_use] extern crate derive_new; diff --git a/tests/lib.rs b/tests/lib.rs index 3e388af0022..b9b51853a2d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate assert_cli; #[macro_use] extern crate lazy_static; #[macro_use] @@ -862,3 +863,29 @@ fn configuration_snippet_tests() { println!("Ran {} configurations tests.", blocks.len()); assert_eq!(failures, 0, "{} configurations tests failed", failures); } + +#[test] +fn verify_check_works() { + assert_cli::Assert::command(&[ + "cargo", + "run", + "--bin=rustfmt", + "--", + "--write-mode=check", + "src/bin/main.rs", + ]).succeeds() + .unwrap(); +} + +#[test] +fn verify_diff_works() { + assert_cli::Assert::command(&[ + "cargo", + "run", + "--bin=rustfmt", + "--", + "--write-mode=diff", + "src/bin/main.rs", + ]).succeeds() + .unwrap(); +} -- cgit 1.4.1-3-g733a5 From a73f14aa9563738b9de12c612e6add412a36dd40 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Apr 2018 13:24:45 +1200 Subject: Trivial refactoring in bin --- src/bin/main.rs | 192 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 100 insertions(+), 92 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index ff0961fd2e2..9411ccde41f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -32,6 +32,39 @@ type FmtResult = std::result::Result; const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle|check]"; +fn main() { + env_logger::init(); + let opts = make_opts(); + // Only handles arguments passed in through the CLI. + let write_mode = determine_write_mode(&opts); + + let exit_code = match execute(&opts) { + Ok(summary) => { + if summary.has_operational_errors() + || summary.has_diff && write_mode == WriteMode::Check + || summary.has_parsing_errors() || summary.has_formatting_errors() + { + 1 + } else { + assert!(summary.has_no_errors()); + 0 + } + } + Err(e) => { + eprintln!("{}", e.to_string()); + 1 + } + }; + // Make sure standard output is flushed before we exit. + std::io::stdout().flush().unwrap(); + + // Exit with given exit code. + // + // NOTE: This immediately terminates the process without doing any cleanup, + // so make sure to finish all necessary cleanup before this is called. + std::process::exit(exit_code); +} + /// Rustfmt operations. enum Operation { /// Format files and their child modules. @@ -277,78 +310,86 @@ fn execute(opts: &Options) -> FmtResult { minimal_config_path, } => { let options = CliOptions::from_matches(&matches)?; + format(files, config_path, minimal_config_path, options) + } + } +} - for f in options.file_lines.files() { - match *f { - FileName::Real(ref f) if files.contains(f) => {} - FileName::Real(_) => { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f) - } - _ => eprintln!("Warning: Not a file '{}'", f), - } - } - - let mut config = Config::default(); - // Load the config path file if provided - if let Some(config_file) = config_path.as_ref() { - config = Config::from_toml_path(config_file.as_ref())?; - }; - - if options.verbose { - if let Some(path) = config_path.as_ref() { - println!("Using rustfmt config file {}", path.display()); - } +fn format( + files: Vec, + config_path: Option, + minimal_config_path: Option, + options: CliOptions, +) -> FmtResult { + for f in options.file_lines.files() { + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) } + _ => eprintln!("Warning: Not a file '{}'", f), + } + } - let mut out = &mut stdout(); - checkstyle::output_header(&mut out, config.write_mode())?; - let mut error_summary = Summary::default(); + let mut config = Config::default(); + // Load the config path file if provided + if let Some(config_file) = config_path.as_ref() { + config = Config::from_toml_path(config_file.as_ref())?; + }; - for file in files { - if !file.exists() { - eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); - error_summary.add_operational_error(); - } else if file.is_dir() { - eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); - error_summary.add_operational_error(); - } else { - // Check the file directory if the config-path could not be read or not provided - if config_path.is_none() { - let (config_tmp, path_tmp) = - Config::from_resolved_toml_path(file.parent().unwrap())?; - if options.verbose { - if let Some(path) = path_tmp.as_ref() { - println!( - "Using rustfmt config file {} for {}", - path.display(), - file.display() - ); - } - } - config = config_tmp; - } + if options.verbose { + if let Some(path) = config_path.as_ref() { + println!("Using rustfmt config file {}", path.display()); + } + } - if !config.version_meets_requirement(&mut error_summary) { - break; + let mut out = &mut stdout(); + checkstyle::output_header(&mut out, config.write_mode())?; + let mut error_summary = Summary::default(); + + for file in files { + if !file.exists() { + eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else if file.is_dir() { + eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); + error_summary.add_operational_error(); + } else { + // Check the file directory if the config-path could not be read or not provided + if config_path.is_none() { + let (config_tmp, path_tmp) = + Config::from_resolved_toml_path(file.parent().unwrap())?; + if options.verbose { + if let Some(path) = path_tmp.as_ref() { + println!( + "Using rustfmt config file {} for {}", + path.display(), + file.display() + ); } - - options.clone().apply_to(&mut config); - error_summary.add(run(Input::File(file), &config)); } + config = config_tmp; } - checkstyle::output_footer(&mut out, config.write_mode())?; - // If we were given a path via dump-minimal-config, output any options - // that were used during formatting as TOML. - if let Some(path) = minimal_config_path { - let mut file = File::create(path)?; - let toml = config.used_options().to_toml()?; - file.write_all(toml.as_bytes())?; + if !config.version_meets_requirement(&mut error_summary) { + break; } - Ok(error_summary) + options.clone().apply_to(&mut config); + error_summary.add(run(Input::File(file), &config)); } } + checkstyle::output_footer(&mut out, config.write_mode())?; + + // If we were given a path via dump-minimal-config, output any options + // that were used during formatting as TOML. + if let Some(path) = minimal_config_path { + let mut file = File::create(path)?; + let toml = config.used_options().to_toml()?; + file.write_all(toml.as_bytes())?; + } + + Ok(error_summary) } fn determine_write_mode(opts: &Options) -> WriteMode { @@ -360,39 +401,6 @@ fn determine_write_mode(opts: &Options) -> WriteMode { } } -fn main() { - env_logger::init(); - let opts = make_opts(); - // Only handles arguments passed in through the CLI. - let write_mode = determine_write_mode(&opts); - - let exit_code = match execute(&opts) { - Ok(summary) => { - if summary.has_operational_errors() - || summary.has_diff && write_mode == WriteMode::Check - || summary.has_parsing_errors() || summary.has_formatting_errors() - { - 1 - } else { - assert!(summary.has_no_errors()); - 0 - } - } - Err(e) => { - eprintln!("{}", e.to_string()); - 1 - } - }; - // Make sure standard output is flushed before we exit. - std::io::stdout().flush().unwrap(); - - // Exit with given exit code. - // - // NOTE: This immediately terminates the process without doing any cleanup, - // so make sure to finish all necessary cleanup before this is called. - std::process::exit(exit_code); -} - fn print_usage_to_stdout(opts: &Options, reason: &str) { let sep = if reason.is_empty() { String::new() -- cgit 1.4.1-3-g733a5 From 7a886e8fe5f3551b9614c8131709267256eaa229 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Apr 2018 13:42:27 +1200 Subject: Refactoring around write mode in main --- src/bin/main.rs | 34 ++++++++++++---------------------- src/config/options.rs | 2 ++ src/filemap.rs | 1 + 3 files changed, 15 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 9411ccde41f..abc313ab8ed 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -35,11 +35,9 @@ const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|ch fn main() { env_logger::init(); let opts = make_opts(); - // Only handles arguments passed in through the CLI. - let write_mode = determine_write_mode(&opts); let exit_code = match execute(&opts) { - Ok(summary) => { + Ok((write_mode, summary)) => { if summary.has_operational_errors() || summary.has_diff && write_mode == WriteMode::Check || summary.has_parsing_errors() || summary.has_formatting_errors() @@ -248,22 +246,22 @@ fn make_opts() -> Options { opts } -fn execute(opts: &Options) -> FmtResult { +fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { let matches = opts.parse(env::args().skip(1))?; match determine_operation(&matches)? { Operation::Help => { print_usage_to_stdout(opts, ""); Summary::print_exit_codes(); - Ok(Summary::default()) + Ok((WriteMode::None, Summary::default())) } Operation::Version => { print_version(); - Ok(Summary::default()) + Ok((WriteMode::None, Summary::default())) } Operation::ConfigHelp => { Config::print_docs(&mut stdout(), matches.opt_present("unstable-features")); - Ok(Summary::default()) + Ok((WriteMode::None, Summary::default())) } Operation::ConfigOutputDefault { path } => { let toml = Config::default().all_options().to_toml()?; @@ -273,7 +271,7 @@ fn execute(opts: &Options) -> FmtResult { } else { io::stdout().write_all(toml.as_bytes())?; } - Ok(Summary::default()) + Ok((WriteMode::None, Summary::default())) } Operation::Stdin { input, config_path } => { // try to read config from local directory @@ -302,7 +300,7 @@ fn execute(opts: &Options) -> FmtResult { checkstyle::output_footer(&mut out, config.write_mode())?; } - Ok(error_summary) + Ok((WriteMode::Plain, error_summary)) } Operation::Format { files, @@ -320,7 +318,7 @@ fn format( config_path: Option, minimal_config_path: Option, options: CliOptions, -) -> FmtResult { +) -> FmtResult<(WriteMode, Summary)> { for f in options.file_lines.files() { match *f { FileName::Real(ref f) if files.contains(f) => {} @@ -343,8 +341,9 @@ fn format( } } + let write_mode = config.write_mode(); let mut out = &mut stdout(); - checkstyle::output_header(&mut out, config.write_mode())?; + checkstyle::output_header(&mut out, write_mode)?; let mut error_summary = Summary::default(); for file in files { @@ -379,7 +378,7 @@ fn format( error_summary.add(run(Input::File(file), &config)); } } - checkstyle::output_footer(&mut out, config.write_mode())?; + checkstyle::output_footer(&mut out, write_mode)?; // If we were given a path via dump-minimal-config, output any options // that were used during formatting as TOML. @@ -389,16 +388,7 @@ fn format( file.write_all(toml.as_bytes())?; } - Ok(error_summary) -} - -fn determine_write_mode(opts: &Options) -> WriteMode { - let matches = opts.parse(env::args().skip(1)).unwrap(); - let options = CliOptions::from_matches(&matches).unwrap(); - match options.write_mode { - Some(m) => m, - None => WriteMode::default(), - } + Ok((write_mode, error_summary)) } fn print_usage_to_stdout(opts: &Options, reason: &str) { diff --git a/src/config/options.rs b/src/config/options.rs index 0bb53f046ac..2992bf48a80 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -186,6 +186,8 @@ configuration_option_enum! { WriteMode: // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. // This option is designed to be run in CI where a non-zero exit signifies non-standard code formatting. Check, + // Rustfmt shouldn't output anything formatting-like (e.g., emit a help message). + None, } configuration_option_enum! { Color: diff --git a/src/filemap.rs b/src/filemap.rs index ce9134b131e..6d2f5da44de 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -191,6 +191,7 @@ where return Ok(has_diff); } } + WriteMode::None => {} } // when we are not in diff mode, don't indicate differing files -- cgit 1.4.1-3-g733a5 From 5194984812bf38d73094da36e1932f503958effc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Apr 2018 14:02:44 +1200 Subject: Add a verbose-diff option And don't print end of line characters by default in diffs cc #2536 --- src/bin/main.rs | 9 +++++++++ src/config/config_type.rs | 3 ++- src/config/mod.rs | 1 + src/filemap.rs | 4 ++-- src/rustfmt_diff.rs | 23 +++++++++++++++-------- tests/lib.rs | 4 ++-- 6 files changed, 31 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index abc313ab8ed..024c41370a5 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -93,6 +93,7 @@ enum Operation { struct CliOptions { skip_children: Option, verbose: bool, + verbose_diff: bool, write_mode: Option, color: Option, file_lines: FileLines, // Default is all lines in all files. @@ -104,6 +105,8 @@ impl CliOptions { fn from_matches(matches: &Matches) -> FmtResult { let mut options = CliOptions::default(); options.verbose = matches.opt_present("verbose"); + options.verbose_diff = matches.opt_present("verbose-diff"); + let unstable_features = matches.opt_present("unstable-features"); let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") .map(|c| c == "nightly") @@ -150,6 +153,7 @@ impl CliOptions { fn apply_to(self, config: &mut Config) { config.set().verbose(self.verbose); + config.set().verbose_diff(self.verbose_diff); config.set().file_lines(self.file_lines); config.set().unstable_features(self.unstable_features); if let Some(skip_children) = self.skip_children { @@ -227,6 +231,11 @@ fn make_opts() -> Options { "Format specified line ranges. See README for more detail on the JSON format.", "JSON", ); + opts.optflag( + "", + "verbose-diff", + "Emit a more verbose diff, indicating the end of lines.", + ); opts.optflag("h", "help", "Show this message"); opts.optflag("", "skip-children", "Don't reformat child modules"); opts.optflag( diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 0c38b6d28ad..5fc03286955 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -356,7 +356,8 @@ macro_rules! create_config { } pub fn is_hidden_option(name: &str) -> bool { - const HIDE_OPTIONS: [&str; 3] = ["verbose", "file_lines", "width_heuristics"]; + const HIDE_OPTIONS: [&str; 4] = + ["verbose", "verbose_diff", "file_lines", "width_heuristics"]; HIDE_OPTIONS.contains(&name) } diff --git a/src/config/mod.rs b/src/config/mod.rs index 274a40a2ae7..f81bbfccd1e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -143,6 +143,7 @@ create_config! { // Not user-facing verbose: bool, false, false, "Use verbose output"; + verbose_diff: bool, false, false, "Emit verbose diffs"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; diff --git a/src/filemap.rs b/src/filemap.rs index 6d2f5da44de..54bfe7996b1 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -159,7 +159,7 @@ where print_diff( mismatch, |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config.color(), + config, ); return Ok(has_diff); } @@ -186,7 +186,7 @@ where print_diff( mismatch, |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config.color(), + config, ); return Ok(has_diff); } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index d5c97b95560..426f7da96a2 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::Color; +use config::{Color, Config}; use diff; use std::collections::VecDeque; use std::io; @@ -149,10 +149,13 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F, color: Color) +pub fn print_diff(diff: Vec, get_section_title: F, config: &Config) where F: Fn(u32) -> String, { + let color = config.color(); + let line_terminator = if config.verbose_diff() { "⏎" } else { "" }; + let mut writer = OutputWriter::new(color); for mismatch in diff { @@ -161,13 +164,17 @@ where for line in mismatch.lines { match line { - DiffLine::Context(ref str) => writer.writeln(&format!(" {}⏎", str), None), - DiffLine::Expected(ref str) => { - writer.writeln(&format!("+{}⏎", str), Some(term::color::GREEN)) - } - DiffLine::Resulting(ref str) => { - writer.writeln(&format!("-{}⏎", str), Some(term::color::RED)) + DiffLine::Context(ref str) => { + writer.writeln(&format!(" {}{}", str, line_terminator), None) } + DiffLine::Expected(ref str) => writer.writeln( + &format!("+{}{}", str, line_terminator), + Some(term::color::GREEN), + ), + DiffLine::Resulting(ref str) => writer.writeln( + &format!("-{}{}", str, line_terminator), + Some(term::color::RED), + ), } } } diff --git a/tests/lib.rs b/tests/lib.rs index b9b51853a2d..7e2947929de 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -337,7 +337,7 @@ fn print_mismatches_default_message(result: HashMap>) { for (file_name, diff) in result { let mismatch_msg_formatter = |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); - print_diff(diff, &mismatch_msg_formatter, Color::Auto); + print_diff(diff, &mismatch_msg_formatter, &Default::default()); } if let Some(mut t) = term::stdout() { @@ -350,7 +350,7 @@ fn print_mismatches String>( mismatch_msg_formatter: T, ) { for (_file_name, diff) in result { - print_diff(diff, &mismatch_msg_formatter, Color::Auto); + print_diff(diff, &mismatch_msg_formatter, &Default::default()); } if let Some(mut t) = term::stdout() { -- cgit 1.4.1-3-g733a5 From 6a31741eaa638953f10352f27beba081d58e1a6f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Apr 2018 14:17:56 +1200 Subject: Get exit codes right --- src/bin/main.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 024c41370a5..8d95dbb209f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -38,13 +38,11 @@ fn main() { let exit_code = match execute(&opts) { Ok((write_mode, summary)) => { - if summary.has_operational_errors() - || summary.has_diff && write_mode == WriteMode::Check - || summary.has_parsing_errors() || summary.has_formatting_errors() + if summary.has_operational_errors() || summary.has_parsing_errors() + || (summary.has_diff && write_mode == WriteMode::Check) { 1 } else { - assert!(summary.has_no_errors()); 0 } } -- cgit 1.4.1-3-g733a5 From ca610d35b3a78b9b2e9d8444eaf0296a1a242277 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Apr 2018 21:08:20 +1200 Subject: Refactor to make a sensible public API 0.5 - lots of breaking changes cc #2639 --- Cargo.lock | 2 +- Cargo.toml | 4 +- src/bin/main.rs | 218 ++---------- src/checkstyle.rs | 27 +- src/config/config_type.rs | 15 +- src/config/file_lines.rs | 14 +- src/config/license.rs | 3 +- src/config/mod.rs | 77 +++- src/config/options.rs | 103 ++++++ src/config/summary.rs | 14 +- src/filemap.rs | 14 +- src/git-rustfmt/main.rs | 7 +- src/lib.rs | 75 ++-- src/shape.rs | 8 - src/test/mod.rs | 884 +++++++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 9 - tests/lib.rs | 891 ---------------------------------------------- 17 files changed, 1192 insertions(+), 1173 deletions(-) create mode 100644 src/test/mod.rs delete mode 100644 tests/lib.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ee76b020476..4ce2fae6a3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,7 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustfmt-nightly" -version = "0.4.2" +version = "0.5.0" dependencies = [ "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index e989e123dbb..bacde50ce77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.4.2" +version = "0.5.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" @@ -49,8 +49,8 @@ cargo_metadata = "0.5.1" rustc-ap-syntax = "103.0.0" [dev-dependencies] -lazy_static = "1.0.0" assert_cli = "0.5" +lazy_static = "1.0.0" [target.'cfg(unix)'.dependencies] libc = "0.2.11" diff --git a/src/bin/main.rs b/src/bin/main.rs index 8d95dbb209f..453c7806d23 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -14,23 +14,16 @@ extern crate env_logger; extern crate getopts; extern crate rustfmt_nightly as rustfmt; +use std::env; use std::fs::File; use std::io::{self, stdout, Read, Write}; -use std::path::{Path, PathBuf}; -use std::str::FromStr; -use std::{env, error}; +use std::path::PathBuf; use getopts::{Matches, Options}; -use rustfmt::checkstyle; -use rustfmt::config::file_lines::FileLines; -use rustfmt::config::{get_toml_path, Color, Config, WriteMode}; -use rustfmt::{run, FileName, Input, Summary}; - -type FmtError = Box; -type FmtResult = std::result::Result; - -const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle|check]"; +use rustfmt::{emit_post_matter, emit_pre_matter, load_config, CliOptions, Config, FmtResult, + WriteMode, WRITE_MODE_LIST}; +use rustfmt::{format_and_emit_report, FileName, Input, Summary}; fn main() { env_logger::init(); @@ -66,7 +59,6 @@ enum Operation { /// Format files and their child modules. Format { files: Vec, - config_path: Option, minimal_config_path: Option, }, /// Print the help message. @@ -82,105 +74,9 @@ enum Operation { /// No file specified, read from stdin Stdin { input: String, - config_path: Option, }, } -/// Parsed command line options. -#[derive(Clone, Debug, Default)] -struct CliOptions { - skip_children: Option, - verbose: bool, - verbose_diff: bool, - write_mode: Option, - color: Option, - file_lines: FileLines, // Default is all lines in all files. - unstable_features: bool, - error_on_unformatted: Option, -} - -impl CliOptions { - fn from_matches(matches: &Matches) -> FmtResult { - let mut options = CliOptions::default(); - options.verbose = matches.opt_present("verbose"); - options.verbose_diff = matches.opt_present("verbose-diff"); - - let unstable_features = matches.opt_present("unstable-features"); - let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(false); - if unstable_features && !rust_nightly { - return Err(FmtError::from( - "Unstable features are only available on Nightly channel", - )); - } else { - options.unstable_features = unstable_features; - } - - if let Some(ref write_mode) = matches.opt_str("write-mode") { - if let Ok(write_mode) = WriteMode::from_str(write_mode) { - options.write_mode = Some(write_mode); - } else { - return Err(FmtError::from(format!( - "Invalid write-mode: {}, expected one of {}", - write_mode, WRITE_MODE_LIST - ))); - } - } - - if let Some(ref color) = matches.opt_str("color") { - match Color::from_str(color) { - Ok(color) => options.color = Some(color), - _ => return Err(FmtError::from(format!("Invalid color: {}", color))), - } - } - - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse()?; - } - - if matches.opt_present("skip-children") { - options.skip_children = Some(true); - } - if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = Some(true); - } - - Ok(options) - } - - fn apply_to(self, config: &mut Config) { - config.set().verbose(self.verbose); - config.set().verbose_diff(self.verbose_diff); - config.set().file_lines(self.file_lines); - config.set().unstable_features(self.unstable_features); - if let Some(skip_children) = self.skip_children { - config.set().skip_children(skip_children); - } - if let Some(error_on_unformatted) = self.error_on_unformatted { - config.set().error_on_unformatted(error_on_unformatted); - } - if let Some(write_mode) = self.write_mode { - config.set().write_mode(write_mode); - } - if let Some(color) = self.color { - config.set().color(color); - } - } -} - -/// read the given config file path recursively if present else read the project file path -fn match_cli_path_or_file( - config_path: Option, - input_file: &Path, -) -> FmtResult<(Config, Option)> { - if let Some(config_file) = config_path { - let toml = Config::from_toml_path(config_file.as_ref())?; - return Ok((toml, Some(config_file))); - } - Config::from_resolved_toml_path(input_file).map_err(FmtError::from) -} - fn make_opts() -> Options { let mut opts = Options::new(); @@ -280,10 +176,10 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { } Ok((WriteMode::None, Summary::default())) } - Operation::Stdin { input, config_path } => { + Operation::Stdin { input } => { // try to read config from local directory - let (mut config, _) = - match_cli_path_or_file(config_path, &env::current_dir().unwrap())?; + let options = CliOptions::from_matches(&matches)?; + let (mut config, _) = load_config(None, Some(&options))?; // write_mode is always Plain for Stdin. config.set().write_mode(WriteMode::Plain); @@ -300,57 +196,40 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { } let mut error_summary = Summary::default(); - if config.version_meets_requirement(&mut error_summary) { - let mut out = &mut stdout(); - checkstyle::output_header(&mut out, config.write_mode())?; - error_summary.add(run(Input::Text(input), &config)); - checkstyle::output_footer(&mut out, config.write_mode())?; + emit_pre_matter(&config)?; + match format_and_emit_report(Input::Text(input), &config) { + Ok(summary) => error_summary.add(summary), + Err(_) => error_summary.add_operational_error(), } + emit_post_matter(&config)?; Ok((WriteMode::Plain, error_summary)) } Operation::Format { files, - config_path, minimal_config_path, } => { let options = CliOptions::from_matches(&matches)?; - format(files, config_path, minimal_config_path, options) + format(files, minimal_config_path, options) } } } fn format( files: Vec, - config_path: Option, minimal_config_path: Option, options: CliOptions, ) -> FmtResult<(WriteMode, Summary)> { - for f in options.file_lines.files() { - match *f { - FileName::Real(ref f) if files.contains(f) => {} - FileName::Real(_) => { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f) - } - _ => eprintln!("Warning: Not a file '{}'", f), - } - } - - let mut config = Config::default(); - // Load the config path file if provided - if let Some(config_file) = config_path.as_ref() { - config = Config::from_toml_path(config_file.as_ref())?; - }; + options.verify_file_lines(&files); + let (config, config_path) = load_config(None, Some(&options))?; - if options.verbose { + if config.verbose() { if let Some(path) = config_path.as_ref() { println!("Using rustfmt config file {}", path.display()); } } - let write_mode = config.write_mode(); - let mut out = &mut stdout(); - checkstyle::output_header(&mut out, write_mode)?; + emit_pre_matter(&config)?; let mut error_summary = Summary::default(); for file in files { @@ -362,11 +241,11 @@ fn format( error_summary.add_operational_error(); } else { // Check the file directory if the config-path could not be read or not provided - if config_path.is_none() { - let (config_tmp, path_tmp) = - Config::from_resolved_toml_path(file.parent().unwrap())?; - if options.verbose { - if let Some(path) = path_tmp.as_ref() { + let local_config = if config_path.is_none() { + let (local_config, config_path) = + load_config(Some(file.parent().unwrap()), Some(&options))?; + if local_config.verbose() { + if let Some(path) = config_path { println!( "Using rustfmt config file {} for {}", path.display(), @@ -374,18 +253,21 @@ fn format( ); } } - config = config_tmp; - } - - if !config.version_meets_requirement(&mut error_summary) { - break; + local_config + } else { + config.clone() + }; + + match format_and_emit_report(Input::File(file), &local_config) { + Ok(summary) => error_summary.add(summary), + Err(_) => { + error_summary.add_operational_error(); + break; + } } - - options.clone().apply_to(&mut config); - error_summary.add(run(Input::File(file), &config)); } } - checkstyle::output_footer(&mut out, write_mode)?; + emit_post_matter(&config)?; // If we were given a path via dump-minimal-config, output any options // that were used during formatting as TOML. @@ -395,7 +277,7 @@ fn format( file.write_all(toml.as_bytes())?; } - Ok((write_mode, error_summary)) + Ok((config.write_mode(), error_summary)) } fn print_usage_to_stdout(opts: &Options, reason: &str) { @@ -451,28 +333,6 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::Version); } - let config_path_not_found = |path: &str| -> FmtResult { - Err(FmtError::from(format!( - "Error: unable to find a config file for the given path: `{}`", - path - ))) - }; - - // Read the config_path and convert to parent dir if a file is provided. - // If a config file cannot be found from the given path, return error. - let config_path: Option = match matches.opt_str("config-path").map(PathBuf::from) { - Some(ref path) if !path.exists() => return config_path_not_found(path.to_str().unwrap()), - Some(ref path) if path.is_dir() => { - let config_file_path = get_toml_path(path)?; - if config_file_path.is_some() { - config_file_path - } else { - return config_path_not_found(path.to_str().unwrap()); - } - } - path => path, - }; - // If no path is given, we won't output a minimal config. let minimal_config_path = matches.opt_str("dump-minimal-config"); @@ -481,10 +341,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { let mut buffer = String::new(); io::stdin().read_to_string(&mut buffer)?; - return Ok(Operation::Stdin { - input: buffer, - config_path, - }); + return Ok(Operation::Stdin { input: buffer }); } let files: Vec<_> = matches @@ -500,7 +357,6 @@ fn determine_operation(matches: &Matches) -> FmtResult { Ok(Operation::Format { files, - config_path, minimal_config_path, }) } diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 7f6e650ad22..19d737cd4c2 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -11,33 +11,26 @@ use std::io::{self, Write}; use std::path::Path; -use config::WriteMode; use rustfmt_diff::{DiffLine, Mismatch}; -pub fn output_header(out: &mut T, mode: WriteMode) -> Result<(), io::Error> +pub fn output_header(out: &mut T) -> Result<(), io::Error> where T: Write, { - if mode == WriteMode::Checkstyle { - let mut xml_heading = String::new(); - xml_heading.push_str(""); - xml_heading.push_str("\n"); - xml_heading.push_str(""); - write!(out, "{}", xml_heading)?; - } - Ok(()) + let mut xml_heading = String::new(); + xml_heading.push_str(""); + xml_heading.push_str("\n"); + xml_heading.push_str(""); + write!(out, "{}", xml_heading) } -pub fn output_footer(out: &mut T, mode: WriteMode) -> Result<(), io::Error> +pub fn output_footer(out: &mut T) -> Result<(), io::Error> where T: Write, { - if mode == WriteMode::Checkstyle { - let mut xml_tail = String::new(); - xml_tail.push_str("\n"); - write!(out, "{}", xml_tail)?; - } - Ok(()) + let mut xml_tail = String::new(); + xml_tail.push_str("\n"); + write!(out, "{}", xml_tail) } pub fn output_checkstyle_file( diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 5fc03286955..3b9ca90350c 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -80,6 +80,7 @@ macro_rules! is_nightly_channel { macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( + #[cfg(test)] use std::collections::HashSet; use std::io::Write; @@ -150,7 +151,7 @@ macro_rules! create_config { } impl Config { - pub fn version_meets_requirement(&self, error_summary: &mut Summary) -> bool { + pub(crate) fn version_meets_requirement(&self) -> bool { if self.was_set().required_version() { let version = env!("CARGO_PKG_VERSION"); let required_version = self.required_version(); @@ -160,7 +161,6 @@ macro_rules! create_config { version, required_version, ); - error_summary.add_formatting_error(); return false; } } @@ -207,7 +207,8 @@ macro_rules! create_config { } /// Returns a hash set initialized with every user-facing config option name. - pub fn hash_set() -> HashSet { + #[cfg(test)] + pub(crate) fn hash_set() -> HashSet { let mut hash_set = HashSet::new(); $( hash_set.insert(stringify!($i).to_owned()); @@ -215,7 +216,7 @@ macro_rules! create_config { hash_set } - pub fn is_valid_name(name: &str) -> bool { + pub(crate) fn is_valid_name(name: &str) -> bool { match name { $( stringify!($i) => true, @@ -224,7 +225,7 @@ macro_rules! create_config { } } - pub fn from_toml(toml: &str, dir: &Path) -> Result { + pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { let parsed: ::toml::Value = toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; let mut err: String = String::new(); @@ -304,7 +305,7 @@ macro_rules! create_config { /// /// Return a `Config` if the config could be read and parsed from /// the file, Error otherwise. - pub fn from_toml_path(file_path: &Path) -> Result { + pub(super) fn from_toml_path(file_path: &Path) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; @@ -321,7 +322,7 @@ macro_rules! create_config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of a the nearest project file if one exists, diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index cf3f827c00d..5e29e0ff965 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -54,6 +54,7 @@ impl Range { self.lo > self.hi } + #[allow(dead_code)] fn contains(self, other: Range) -> bool { if other.is_empty() { true @@ -128,12 +129,12 @@ fn normalize_ranges(ranges: &mut HashMap>) { impl FileLines { /// Creates a `FileLines` that contains all lines in all files. - pub fn all() -> FileLines { + pub(crate) fn all() -> FileLines { FileLines(None) } /// Returns true if this `FileLines` contains all lines in all files. - pub fn is_all(&self) -> bool { + pub(crate) fn is_all(&self) -> bool { self.0.is_none() } @@ -166,22 +167,23 @@ impl FileLines { } /// Returns true if `range` is fully contained in `self`. - pub fn contains(&self, range: &LineRange) -> bool { + #[allow(dead_code)] + pub(crate) fn contains(&self, range: &LineRange) -> bool { self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) } /// Returns true if any lines in `range` are in `self`. - pub fn intersects(&self, range: &LineRange) -> bool { + pub(crate) fn intersects(&self, range: &LineRange) -> bool { self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) } /// Returns true if `line` from `file_name` is in `self`. - pub fn contains_line(&self, file_name: &FileName, line: usize) -> bool { + pub(crate) fn contains_line(&self, file_name: &FileName, line: usize) -> bool { self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) } /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. - pub fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { + pub(crate) fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) } } diff --git a/src/config/license.rs b/src/config/license.rs index d49fdbe7eba..630399319c1 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -82,8 +82,7 @@ impl TemplateParser { /// /// # Examples /// - /// ``` - /// # use rustfmt_nightly::config::license::TemplateParser; + /// ```ignore /// assert_eq!( /// TemplateParser::parse( /// r" diff --git a/src/config/mod.rs b/src/config/mod.rs index f81bbfccd1e..8dde1e05c3d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use regex::Regex; use std::cell::Cell; use std::default::Default; use std::fs::File; @@ -15,24 +16,23 @@ use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; use std::{env, fs}; -use regex::Regex; +use {FmtError, FmtResult}; + +use config::config_type::ConfigType; +use config::file_lines::FileLines; +pub use config::lists::*; +pub use config::options::*; #[macro_use] -mod config_type; +pub mod config_type; #[macro_use] -mod options; +pub mod options; pub mod file_lines; pub mod license; pub mod lists; pub mod summary; -use config::config_type::ConfigType; -use config::file_lines::FileLines; -pub use config::lists::*; -pub use config::options::*; -use config::summary::Summary; - /// This macro defines configuration options used in rustfmt. Each option /// is defined as follows: /// @@ -151,10 +151,37 @@ create_config! { "'small' heuristic values"; } -/// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` -/// -/// Return the path if a config file exists, empty if no file exists, and Error for IO errors -pub fn get_toml_path(dir: &Path) -> Result, Error> { +pub fn load_config( + file_path: Option<&Path>, + options: Option<&CliOptions>, +) -> FmtResult<(Config, Option)> { + let over_ride = match options { + Some(opts) => config_path(opts)?, + None => None, + }; + + let result = if let Some(over_ride) = over_ride { + Config::from_toml_path(over_ride.as_ref()) + .map(|p| (p, Some(over_ride.to_owned()))) + .map_err(FmtError::from) + } else if let Some(file_path) = file_path { + Config::from_resolved_toml_path(file_path).map_err(FmtError::from) + } else { + Ok((Config::default(), None)) + }; + + result.map(|(mut c, p)| { + if let Some(options) = options { + options.clone().apply_to(&mut c); + } + (c, p) + }) +} + +// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +// +// Return the path if a config file exists, empty if no file exists, and Error for IO errors +fn get_toml_path(dir: &Path) -> Result, Error> { const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; for config_file_name in &CONFIG_FILE_NAMES { let config_file = dir.join(config_file_name); @@ -175,6 +202,30 @@ pub fn get_toml_path(dir: &Path) -> Result, Error> { Ok(None) } +fn config_path(options: &CliOptions) -> FmtResult> { + let config_path_not_found = |path: &str| -> FmtResult> { + Err(FmtError::from(format!( + "Error: unable to find a config file for the given path: `{}`", + path + ))) + }; + + // Read the config_path and convert to parent dir if a file is provided. + // If a config file cannot be found from the given path, return error. + match options.config_path { + Some(ref path) if !path.exists() => config_path_not_found(path.to_str().unwrap()), + Some(ref path) if path.is_dir() => { + let config_file_path = get_toml_path(path)?; + if config_file_path.is_some() { + Ok(config_file_path) + } else { + config_path_not_found(path.to_str().unwrap()) + } + } + ref path => Ok(path.to_owned()), + } +} + #[cfg(test)] mod test { use super::Config; diff --git a/src/config/options.rs b/src/config/options.rs index 2992bf48a80..73dbdb88663 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -11,10 +11,15 @@ use syntax::codemap::FileName; use config::config_type::ConfigType; +use config::file_lines::FileLines; use config::lists::*; +use config::Config; +use {FmtError, FmtResult, WRITE_MODE_LIST}; +use getopts::Matches; use std::collections::HashSet; use std::path::{Path, PathBuf}; +use std::str::FromStr; /// Macro for deriving implementations of Serialize/Deserialize for enums #[macro_export] @@ -301,3 +306,101 @@ impl ::std::str::FromStr for IgnoreList { Err("IgnoreList is not parsable") } } + +/// Parsed command line options. +#[derive(Clone, Debug, Default)] +pub struct CliOptions { + skip_children: Option, + verbose: bool, + verbose_diff: bool, + pub(super) config_path: Option, + write_mode: Option, + color: Option, + file_lines: FileLines, // Default is all lines in all files. + unstable_features: bool, + error_on_unformatted: Option, +} + +impl CliOptions { + pub fn from_matches(matches: &Matches) -> FmtResult { + let mut options = CliOptions::default(); + options.verbose = matches.opt_present("verbose"); + options.verbose_diff = matches.opt_present("verbose-diff"); + + let unstable_features = matches.opt_present("unstable-features"); + let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false); + if unstable_features && !rust_nightly { + return Err(FmtError::from( + "Unstable features are only available on Nightly channel", + )); + } else { + options.unstable_features = unstable_features; + } + + options.config_path = matches.opt_str("config-path").map(PathBuf::from); + + if let Some(ref write_mode) = matches.opt_str("write-mode") { + if let Ok(write_mode) = WriteMode::from_str(write_mode) { + options.write_mode = Some(write_mode); + } else { + return Err(FmtError::from(format!( + "Invalid write-mode: {}, expected one of {}", + write_mode, WRITE_MODE_LIST + ))); + } + } + + if let Some(ref color) = matches.opt_str("color") { + match Color::from_str(color) { + Ok(color) => options.color = Some(color), + _ => return Err(FmtError::from(format!("Invalid color: {}", color))), + } + } + + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse()?; + } + + if matches.opt_present("skip-children") { + options.skip_children = Some(true); + } + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = Some(true); + } + + Ok(options) + } + + pub fn apply_to(self, config: &mut Config) { + config.set().verbose(self.verbose); + config.set().verbose_diff(self.verbose_diff); + config.set().file_lines(self.file_lines); + config.set().unstable_features(self.unstable_features); + if let Some(skip_children) = self.skip_children { + config.set().skip_children(skip_children); + } + if let Some(error_on_unformatted) = self.error_on_unformatted { + config.set().error_on_unformatted(error_on_unformatted); + } + if let Some(write_mode) = self.write_mode { + config.set().write_mode(write_mode); + } + if let Some(color) = self.color { + config.set().color(color); + } + } + + pub fn verify_file_lines(&self, files: &[PathBuf]) { + for f in self.file_lines.files() { + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) + } + _ => eprintln!("Warning: Not a file '{}'", f), + } + } + } +} diff --git a/src/config/summary.rs b/src/config/summary.rs index 3654ea89df4..c906c77506f 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -31,16 +31,16 @@ pub struct Summary { } impl Summary { - pub fn mark_parse_time(&mut self) { + pub(crate) fn mark_parse_time(&mut self) { self.timer = self.timer.done_parsing(); } - pub fn mark_format_time(&mut self) { + pub(crate) fn mark_format_time(&mut self) { self.timer = self.timer.done_formatting(); } /// Returns the time it took to parse the source files in nanoseconds. - pub fn get_parse_time(&self) -> Option { + pub(crate) fn get_parse_time(&self) -> Option { match self.timer { Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { // This should never underflow since `Instant::now()` guarantees monotonicity. @@ -52,7 +52,7 @@ impl Summary { /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is /// not included. - pub fn get_format_time(&self) -> Option { + pub(crate) fn get_format_time(&self) -> Option { match self.timer { Timer::DoneFormatting(_init, parse_time, format_time) => { Some(format_time.duration_since(parse_time)) @@ -77,15 +77,15 @@ impl Summary { self.has_operational_errors = true; } - pub fn add_parsing_error(&mut self) { + pub(crate) fn add_parsing_error(&mut self) { self.has_parsing_errors = true; } - pub fn add_formatting_error(&mut self) { + pub(crate) fn add_formatting_error(&mut self) { self.has_formatting_errors = true; } - pub fn add_diff(&mut self) { + pub(crate) fn add_diff(&mut self) { self.has_diff = true; } diff --git a/src/filemap.rs b/src/filemap.rs index 54bfe7996b1..f7491893512 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -14,11 +14,12 @@ use std::fs::{self, File}; use std::io::{self, BufWriter, Read, Write}; use std::path::Path; -use checkstyle::{output_checkstyle_file, output_footer, output_header}; +use checkstyle::output_checkstyle_file; use config::{Config, NewlineStyle, WriteMode}; use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; use syntax::codemap::FileName; +#[cfg(test)] use FileRecord; // Append a newline to the end of each file. @@ -26,7 +27,8 @@ pub fn append_newline(s: &mut String) { s.push_str("\n"); } -pub fn write_all_files( +#[cfg(test)] +pub(crate) fn write_all_files( file_map: &[FileRecord], out: &mut T, config: &Config, @@ -34,11 +36,15 @@ pub fn write_all_files( where T: Write, { - output_header(out, config.write_mode()).ok(); + if config.write_mode() == WriteMode::Checkstyle { + ::checkstyle::output_header(out)?; + } for &(ref filename, ref text) in file_map { write_file(text, filename, out, config)?; } - output_footer(out, config.write_mode()).ok(); + if config.write_mode() == WriteMode::Checkstyle { + ::checkstyle::output_footer(out)?; + } Ok(()) } diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 3ff9455d5f7..390eeb4149a 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -21,7 +21,7 @@ use std::str::FromStr; use getopts::{Matches, Options}; -use rustfmt::{config, run, Input}; +use rustfmt::{format_and_emit_report, load_config, Input}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -68,12 +68,11 @@ fn get_files(input: &str) -> Vec<&str> { } fn fmt_files(files: &[&str]) -> i32 { - let (config, _) = config::Config::from_resolved_toml_path(Path::new(".")) - .unwrap_or_else(|_| (config::Config::default(), None)); + let (config, _) = load_config(Some(Path::new(".")), None).expect("couldn't load config"); let mut exit_code = 0; for file in files { - let summary = run(Input::File(PathBuf::from(file)), &config); + let summary = format_and_emit_report(Input::File(PathBuf::from(file)), &config).unwrap(); if !summary.has_no_errors() { exit_code = 1; } diff --git a/src/lib.rs b/src/lib.rs index ddb3ebeb2e9..506defad30e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,11 @@ #[macro_use] extern crate derive_new; extern crate diff; +extern crate getopts; extern crate itertools; +#[cfg(test)] +#[macro_use] +extern crate lazy_static; #[macro_use] extern crate log; extern crate regex; @@ -33,6 +37,7 @@ extern crate toml; extern crate unicode_segmentation; use std::collections::HashMap; +use std::error; use std::fmt; use std::io::{self, stdout, BufRead, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -53,21 +58,28 @@ use shape::Indent; use utils::use_colored_tty; use visitor::{FmtVisitor, SnippetProvider}; +pub use config::options::CliOptions; pub use config::summary::Summary; -pub use config::Config; +pub use config::{file_lines, load_config, Config, WriteMode}; + +pub type FmtError = Box; +pub type FmtResult = std::result::Result; + +pub const WRITE_MODE_LIST: &str = + "[replace|overwrite|display|plain|diff|coverage|checkstyle|check]"; #[macro_use] mod utils; mod attr; mod chains; -pub mod checkstyle; +pub(crate) mod checkstyle; mod closures; -pub mod codemap; +pub(crate) mod codemap; mod comment; -pub mod config; +pub(crate) mod config; mod expr; -pub mod filemap; +pub(crate) mod filemap; mod imports; mod issues; mod items; @@ -75,25 +87,27 @@ mod lists; mod macros; mod matches; mod missed_spans; -pub mod modules; +pub(crate) mod modules; mod overflow; mod patterns; mod reorder; mod rewrite; -pub mod rustfmt_diff; +pub(crate) mod rustfmt_diff; mod shape; mod spanned; mod string; +#[cfg(test)] +mod test; mod types; mod vertical; -pub mod visitor; +pub(crate) mod visitor; const STDIN: &str = ""; // A map of the files of a crate, with their new content -pub type FileMap = Vec; +pub(crate) type FileMap = Vec; -pub type FileRecord = (FileName, String); +pub(crate) type FileRecord = (FileName, String); #[derive(Clone, Copy)] pub enum ErrorKind { @@ -123,7 +137,7 @@ impl fmt::Display for ErrorKind { } // Formatting errors that are identified *after* rustfmt has run. -pub struct FormattingError { +struct FormattingError { line: usize, kind: ErrorKind, is_comment: bool, @@ -150,7 +164,7 @@ impl FormattingError { } // (space, target) - pub fn format_len(&self) -> (usize, usize) { + fn format_len(&self) -> (usize, usize) { match self.kind { ErrorKind::LineOverflow(found, max) => (max, found - max), ErrorKind::TrailingWhitespace => { @@ -180,18 +194,18 @@ impl FormatReport { } } - pub fn warning_count(&self) -> usize { + fn warning_count(&self) -> usize { self.file_error_map .iter() .map(|(_, errors)| errors.len()) .sum() } - pub fn has_warnings(&self) -> bool { + fn has_warnings(&self) -> bool { self.warning_count() > 0 } - pub fn print_warnings_fancy( + fn print_warnings_fancy( &self, mut t: Box>, ) -> Result<(), term::Error> { @@ -881,7 +895,10 @@ pub enum Input { Text(String), } -pub fn run(input: Input, config: &Config) -> Summary { +pub fn format_and_emit_report(input: Input, config: &Config) -> FmtResult { + if !config.version_meets_requirement() { + return Err(FmtError::from("Version mismatch")); + } let out = &mut stdout(); match format_input(input, config, Some(out)) { Ok((summary, _, report)) => { @@ -896,22 +913,38 @@ pub fn run(input: Input, config: &Config) -> Summary { Err(..) => panic!("Unable to write to stderr: {}", report), } } - _ => msg!("{}", report), + _ => eprintln!("{}", report), } } - summary + Ok(summary) } Err((msg, mut summary)) => { - msg!("Error writing files: {}", msg); + eprintln!("Error writing files: {}", msg); summary.add_operational_error(); - summary + Ok(summary) } } } +pub fn emit_pre_matter(config: &Config) -> FmtResult<()> { + if config.write_mode() == WriteMode::Checkstyle { + let mut out = &mut stdout(); + checkstyle::output_header(&mut out)?; + } + Ok(()) +} + +pub fn emit_post_matter(config: &Config) -> FmtResult<()> { + if config.write_mode() == WriteMode::Checkstyle { + let mut out = &mut stdout(); + checkstyle::output_footer(&mut out)?; + } + Ok(()) +} + #[cfg(test)] -mod test { +mod unit_tests { use super::{format_code_block, format_snippet, Config}; #[test] diff --git a/src/shape.rs b/src/shape.rs index c6a183216b8..8a17389672f 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -197,14 +197,6 @@ impl Shape { } } - pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape { - Shape { - width, - indent, - offset, - } - } - pub fn visual_indent(&self, extra_width: usize) -> Shape { let alignment = self.offset + extra_width; Shape { diff --git a/src/test/mod.rs b/src/test/mod.rs new file mode 100644 index 00000000000..b0971136352 --- /dev/null +++ b/src/test/mod.rs @@ -0,0 +1,884 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate assert_cli; + +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::io::{self, BufRead, BufReader, Read}; +use std::iter::{Enumerate, Peekable}; +use std::path::{Path, PathBuf}; +use std::str::Chars; + +use config::summary::Summary; +use config::{Color, Config, ReportTactic}; +use filemap::write_system_newlines; +use rustfmt_diff::*; +use *; + +const DIFF_CONTEXT_SIZE: usize = 3; +const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; + +// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the +// given path. The `recursive` argument controls if files from subdirectories +// are also returned. +fn get_test_files(path: &Path, recursive: bool) -> Vec { + let mut files = vec![]; + if path.is_dir() { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read directory {}", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get DirEntry"); + let path = entry.path(); + if path.is_dir() && recursive { + files.append(&mut get_test_files(&path, recursive)); + } else if path.extension().map_or(false, |f| f == "rs") { + files.push(path); + } + } + } + files +} + +fn verify_config_used(path: &Path, config_name: &str) { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read {} directory", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.extension().map_or(false, |f| f == "rs") { + // check if "// rustfmt-:" appears in the file. + let filebuf = BufReader::new( + fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), + ); + assert!( + filebuf + .lines() + .map(|l| l.unwrap()) + .take_while(|l| l.starts_with("//")) + .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), + format!( + "config option file {} does not contain expected config name", + path.display() + ) + ); + } + } +} + +#[test] +fn verify_config_test_names() { + for path in &[ + Path::new("tests/source/configs"), + Path::new("tests/target/configs"), + ] { + for entry in fs::read_dir(path).expect("Couldn't read configs directory") { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.is_dir() { + let config_name = path.file_name().unwrap().to_str().unwrap(); + + // Make sure that config name is used in the files in the directory. + verify_config_used(&path, config_name); + } + } + } +} + +// This writes to the terminal using the same approach (via term::stdout or +// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing +// using only one or the other will cause the output order to differ when +// `print_diff` selects the approach not used. +fn write_message(msg: &str) { + let mut writer = OutputWriter::new(Color::Auto); + writer.writeln(&format!("{}", msg), None); +} + +// Integration tests. The files in the tests/source are formatted and compared +// to their equivalent in tests/target. The target file and config can be +// overridden by annotations in the source file. The input and output must match +// exactly. +#[test] +fn system_tests() { + // Get all files in the tests/source directory. + let files = get_test_files(Path::new("tests/source"), true); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} system tests.", count); + assert_eq!(fails, 0, "{} system tests failed", fails); +} + +// Do the same for tests/coverage-source directory +// the only difference is the coverage mode +#[test] +fn coverage_tests() { + let files = get_test_files(Path::new("tests/coverage/source"), true); + let (_reports, count, fails) = check_files(files); + + println!("Ran {} tests in coverage mode.", count); + assert_eq!(fails, 0, "{} tests failed", fails); +} + +#[test] +fn checkstyle_test() { + let filename = "tests/writemode/source/fn-single-line.rs"; + let expected_filename = "tests/writemode/target/checkstyle.xml"; + assert_output(Path::new(filename), Path::new(expected_filename)); +} + +#[test] +fn modified_test() { + // Test "modified" output + let filename = "tests/writemode/source/modified.rs"; + let result = get_modified_lines(Input::File(filename.into()), &Config::default()).unwrap(); + assert_eq!( + result.modified_lines, + ModifiedLines { + chunks: vec![ + ModifiedChunk { + line_number_orig: 4, + lines_removed: 4, + lines: vec!["fn blah() {}".into()], + }, + ModifiedChunk { + line_number_orig: 9, + lines_removed: 6, + lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], + }, + ], + } + ); +} + +// Helper function for comparing the results of rustfmt +// to a known output file generated by one of the write modes. +fn assert_output(source: &Path, expected_filename: &Path) { + let config = read_config(source); + let (_error_summary, file_map, _report) = format_file(source, &config); + + // Populate output by writing to a vec. + let mut out = vec![]; + let _ = filemap::write_all_files(&file_map, &mut out, &config); + let output = String::from_utf8(out).unwrap(); + + let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); + let mut expected_text = String::new(); + expected_file + .read_to_string(&mut expected_text) + .expect("Failed reading target"); + + let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + let mut failures = HashMap::new(); + failures.insert(source.to_owned(), compare); + print_mismatches_default_message(failures); + assert!(false, "Text does not match expected output"); + } +} + +// Idempotence tests. Files in tests/target are checked to be unaltered by +// rustfmt. +#[test] +fn idempotence_tests() { + // Get all files in the tests/target directory. + let files = get_test_files(Path::new("tests/target"), true); + let (_reports, count, fails) = check_files(files); + + // Display results. + println!("Ran {} idempotent tests.", count); + assert_eq!(fails, 0, "{} idempotent tests failed", fails); +} + +// Run rustfmt on itself. This operation must be idempotent. We also check that +// no warnings are emitted. +#[test] +fn self_tests() { + let mut files = get_test_files(Path::new("tests"), false); + let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; + for dir in bin_directories { + let mut path = PathBuf::from("src"); + path.push(dir); + path.push("main.rs"); + files.push(path); + } + files.push(PathBuf::from("src/lib.rs")); + + let (reports, count, fails) = check_files(files); + let mut warnings = 0; + + // Display results. + println!("Ran {} self tests.", count); + assert_eq!(fails, 0, "{} self tests failed", fails); + + for format_report in reports { + println!("{}", format_report); + warnings += format_report.warning_count(); + } + + assert_eq!( + warnings, 0, + "Rustfmt's code generated {} warnings", + warnings + ); +} + +#[test] +fn stdin_formatting_smoke_test() { + let input = Input::Text("fn main () {}".to_owned()); + let config = Config::default(); + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_no_errors()); + for &(ref file_name, ref text) in &file_map { + if let FileName::Custom(ref file_name) = *file_name { + if file_name == "stdin" { + assert_eq!(text.to_string(), "fn main() {}\n"); + return; + } + } + } + panic!("no stdin"); +} + +// FIXME(#1990) restore this test +// #[test] +// fn stdin_disable_all_formatting_test() { +// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); +// let mut child = Command::new("./target/debug/rustfmt") +// .stdin(Stdio::piped()) +// .stdout(Stdio::piped()) +// .arg("--config-path=./tests/config/disable_all_formatting.toml") +// .spawn() +// .expect("failed to execute child"); + +// { +// let stdin = child.stdin.as_mut().expect("failed to get stdin"); +// stdin +// .write_all(input.as_bytes()) +// .expect("failed to write stdin"); +// } +// let output = child.wait_with_output().expect("failed to wait on child"); +// assert!(output.status.success()); +// assert!(output.stderr.is_empty()); +// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); +// } + +#[test] +fn format_lines_errors_are_reported() { + let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); + let input = Input::Text(format!("fn {}() {{}}", long_identifier)); + let mut config = Config::default(); + config.set().error_on_line_overflow(true); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + +#[test] +fn format_lines_errors_are_reported_with_tabs() { + let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); + let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); + let mut config = Config::default(); + config.set().error_on_line_overflow(true); + config.set().hard_tabs(true); + let (error_summary, _file_map, _report) = + format_input::(input, &config, None).unwrap(); + assert!(error_summary.has_formatting_errors()); +} + +// For each file, run rustfmt and collect the output. +// Returns the number of files checked and the number of failures. +fn check_files(files: Vec) -> (Vec, u32, u32) { + let mut count = 0; + let mut fails = 0; + let mut reports = vec![]; + + for file_name in files { + debug!("Testing '{}'...", file_name.display()); + + match idempotent_check(&file_name) { + Ok(ref report) if report.has_warnings() => { + print!("{}", report); + fails += 1; + } + Ok(report) => reports.push(report), + Err(err) => { + if let IdempotentCheckError::Mismatch(msg) = err { + print_mismatches_default_message(msg); + } + fails += 1; + } + } + + count += 1; + } + + (reports, count, fails) +} + +fn print_mismatches_default_message(result: HashMap>) { + for (file_name, diff) in result { + let mismatch_msg_formatter = + |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); + print_diff(diff, &mismatch_msg_formatter, &Default::default()); + } + + if let Some(mut t) = term::stdout() { + t.reset().unwrap_or(()); + } +} + +fn print_mismatches String>( + result: HashMap>, + mismatch_msg_formatter: T, +) { + for (_file_name, diff) in result { + print_diff(diff, &mismatch_msg_formatter, &Default::default()); + } + + if let Some(mut t) = term::stdout() { + t.reset().unwrap_or(()); + } +} + +fn read_config(filename: &Path) -> Config { + let sig_comments = read_significant_comments(filename); + // Look for a config file... If there is a 'config' property in the significant comments, use + // that. Otherwise, if there are no significant comments at all, look for a config file with + // the same name as the test file. + let mut config = if !sig_comments.is_empty() { + get_config(sig_comments.get("config").map(Path::new)) + } else { + get_config(filename.with_extension("toml").file_name().map(Path::new)) + }; + + for (key, val) in &sig_comments { + if key != "target" && key != "config" { + config.override_value(key, val); + } + } + + // Don't generate warnings for to-do items. + config.set().report_todo(ReportTactic::Never); + + config +} + +fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { + let filepath = filepath.into(); + let input = Input::File(filepath); + format_input::(input, config, None).unwrap() +} + +pub enum IdempotentCheckError { + Mismatch(HashMap>), + Parse, +} + +pub fn idempotent_check(filename: &PathBuf) -> Result { + let sig_comments = read_significant_comments(filename); + let config = read_config(filename); + let (error_summary, file_map, format_report) = format_file(filename, &config); + if error_summary.has_parsing_errors() { + return Err(IdempotentCheckError::Parse); + } + + let mut write_result = HashMap::new(); + for &(ref filename, ref text) in &file_map { + let mut v = Vec::new(); + // Won't panic, as we're not doing any IO. + write_system_newlines(&mut v, text, &config).unwrap(); + // Won't panic, we are writing correct utf8. + let one_result = String::from_utf8(v).unwrap(); + if let FileName::Real(ref filename) = *filename { + write_result.insert(filename.to_owned(), one_result); + } + } + + let target = sig_comments.get("target").map(|x| &(*x)[..]); + + handle_result(write_result, target).map(|_| format_report) +} + +// Reads test config file using the supplied (optional) file name. If there's no file name or the +// file doesn't exist, just return the default config. Otherwise, the file must be read +// successfully. +fn get_config(config_file: Option<&Path>) -> Config { + let config_file_name = match config_file { + None => return Default::default(), + Some(file_name) => { + let mut full_path = PathBuf::from("tests/config/"); + full_path.push(file_name); + if !full_path.exists() { + return Default::default(); + }; + full_path + } + }; + + let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); + let mut def_config = String::new(); + def_config_file + .read_to_string(&mut def_config) + .expect("Couldn't read config"); + + Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml") +} + +// Reads significant comments of the form: // rustfmt-key: value +// into a hash map. +fn read_significant_comments(file_name: &Path) -> HashMap { + let file = + fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); + let reader = BufReader::new(file); + let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; + let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); + + // Matches lines containing significant comments or whitespace. + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") + .expect("Failed creating pattern 2"); + + reader + .lines() + .map(|line| line.expect("Failed getting line")) + .take_while(|line| line_regex.is_match(line)) + .filter_map(|line| { + regex.captures_iter(&line).next().map(|capture| { + ( + capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + ) + }) + }) + .collect() +} + +// Compare output to input. +// TODO: needs a better name, more explanation. +fn handle_result( + result: HashMap, + target: Option<&str>, +) -> Result<(), IdempotentCheckError> { + let mut failures = HashMap::new(); + + for (file_name, fmt_text) in result { + // If file is in tests/source, compare to file with same name in tests/target. + let target = get_target(&file_name, target); + let open_error = format!("Couldn't open target {:?}", &target); + let mut f = fs::File::open(&target).expect(&open_error); + + let mut text = String::new(); + let read_error = format!("Failed reading target {:?}", &target); + f.read_to_string(&mut text).expect(&read_error); + + // Ignore LF and CRLF difference for Windows. + if !string_eq_ignore_newline_repr(&fmt_text, &text) { + let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); + assert!( + !diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?" + ); + failures.insert(file_name, diff); + } + } + + if failures.is_empty() { + Ok(()) + } else { + Err(IdempotentCheckError::Mismatch(failures)) + } +} + +// Map source file paths to their target paths. +fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { + if let Some(n) = file_name + .components() + .position(|c| c.as_os_str() == "source") + { + let mut target_file_name = PathBuf::new(); + for (i, c) in file_name.components().enumerate() { + if i == n { + target_file_name.push("target"); + } else { + target_file_name.push(c.as_os_str()); + } + } + if let Some(replace_name) = target { + target_file_name.with_file_name(replace_name) + } else { + target_file_name + } + } else { + // This is either and idempotence check or a self check + file_name.to_owned() + } +} + +#[test] +fn rustfmt_diff_make_diff_tests() { + let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); + assert_eq!( + diff, + vec![Mismatch { + line_number: 1, + line_number_orig: 1, + lines: vec![ + DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into()), + ], + }] + ); +} + +#[test] +fn rustfmt_diff_no_diff_test() { + let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); + assert_eq!(diff, vec![]); +} + +// Compare strings without distinguishing between CRLF and LF +fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { + let left = CharsIgnoreNewlineRepr(left.chars().peekable()); + let right = CharsIgnoreNewlineRepr(right.chars().peekable()); + left.eq(right) +} + +struct CharsIgnoreNewlineRepr<'a>(Peekable>); + +impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { + type Item = char; + fn next(&mut self) -> Option { + self.0.next().map(|c| { + if c == '\r' { + if *self.0.peek().unwrap_or(&'\0') == '\n' { + self.0.next(); + '\n' + } else { + '\r' + } + } else { + c + } + }) + } +} + +#[test] +fn string_eq_ignore_newline_repr_test() { + assert!(string_eq_ignore_newline_repr("", "")); + assert!(!string_eq_ignore_newline_repr("", "abc")); + assert!(!string_eq_ignore_newline_repr("abc", "")); + assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); + assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); + assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); +} + +// This enum is used to represent one of three text features in Configurations.md: a block of code +// with its starting line number, the name of a rustfmt configuration option, or the value of a +// rustfmt configuration option. +enum ConfigurationSection { + CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) + ConfigName(String), + ConfigValue(String), +} + +impl ConfigurationSection { + fn get_section>( + file: &mut Enumerate, + ) -> Option { + lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = + regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) + .expect("Failed creating configuration value pattern"); + } + + loop { + match file.next() { + Some((i, line)) => { + if line.starts_with("```rust") { + // Get the lines of the code block. + let lines: Vec = file.map(|(_i, l)| l) + .take_while(|l| !l.starts_with("```")) + .collect(); + let block = format!("{}\n", lines.join("\n")); + + // +1 to translate to one-based indexing + // +1 to get to first line of code (line after "```") + let start_line = (i + 2) as u32; + + return Some(ConfigurationSection::CodeBlock((block, start_line))); + } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); + } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); + } + } + None => return None, // reached the end of the file + } + } + } +} + +// This struct stores the information about code blocks in the configurations +// file, formats the code blocks, and prints formatting errors. +struct ConfigCodeBlock { + config_name: Option, + config_value: Option, + code_block: Option, + code_block_start: Option, +} + +impl ConfigCodeBlock { + fn new() -> ConfigCodeBlock { + ConfigCodeBlock { + config_name: None, + config_value: None, + code_block: None, + code_block_start: None, + } + } + + fn set_config_name(&mut self, name: Option) { + self.config_name = name; + self.config_value = None; + } + + fn set_config_value(&mut self, value: Option) { + self.config_value = value; + } + + fn set_code_block(&mut self, code_block: String, code_block_start: u32) { + self.code_block = Some(code_block); + self.code_block_start = Some(code_block_start); + } + + fn get_block_config(&self) -> Config { + let mut config = Config::default(); + if self.config_value.is_some() && self.config_value.is_some() { + config.override_value( + self.config_name.as_ref().unwrap(), + self.config_value.as_ref().unwrap(), + ); + } + config + } + + fn code_block_valid(&self) -> bool { + // We never expect to not have a code block. + assert!(self.code_block.is_some() && self.code_block_start.is_some()); + + // See if code block begins with #![rustfmt_skip]. + let fmt_skip = self.code_block + .as_ref() + .unwrap() + .split('\n') + .nth(0) + .unwrap_or("") == "#![rustfmt_skip]"; + + if self.config_name.is_none() && !fmt_skip { + write_message(&format!( + "No configuration name for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + if self.config_value.is_none() && !fmt_skip { + write_message(&format!( + "No configuration value for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + true + } + + fn has_parsing_errors(&self, error_summary: Summary) -> bool { + if error_summary.has_parsing_errors() { + write_message(&format!( + "\u{261d}\u{1f3fd} Cannot format {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return true; + } + + false + } + + fn print_diff(&self, compare: Vec) { + let mut mismatches = HashMap::new(); + mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); + print_mismatches(mismatches, |line_num| { + format!( + "\nMismatch at {}:{}:", + CONFIGURATIONS_FILE_NAME, + line_num + self.code_block_start.unwrap() - 1 + ) + }); + } + + fn formatted_has_diff(&self, file_map: &FileMap) -> bool { + let &(ref _file_name, ref text) = file_map.first().unwrap(); + let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + self.print_diff(compare); + return true; + } + + false + } + + // Return a bool indicating if formatting this code block is an idempotent + // operation. This function also triggers printing any formatting failure + // messages. + fn formatted_is_idempotent(&self) -> bool { + // Verify that we have all of the expected information. + if !self.code_block_valid() { + return false; + } + + let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); + let config = self.get_block_config(); + + let (error_summary, file_map, _report) = + format_input::(input, &config, None).unwrap(); + + !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) + } + + // Extract a code block from the iterator. Behavior: + // - Rust code blocks are identifed by lines beginning with "```rust". + // - One explicit configuration setting is supported per code block. + // - Rust code blocks with no configuration setting are illegal and cause an + // assertion failure, unless the snippet begins with #![rustfmt_skip]. + // - Configuration names in Configurations.md must be in the form of + // "## `NAME`". + // - Configuration values in Configurations.md must be in the form of + // "#### `VALUE`". + fn extract>( + file: &mut Enumerate, + prev: Option<&ConfigCodeBlock>, + hash_set: &mut HashSet, + ) -> Option { + let mut code_block = ConfigCodeBlock::new(); + code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); + + loop { + match ConfigurationSection::get_section(file) { + Some(ConfigurationSection::CodeBlock((block, start_line))) => { + code_block.set_code_block(block, start_line); + break; + } + Some(ConfigurationSection::ConfigName(name)) => { + assert!( + Config::is_valid_name(&name), + "an unknown configuration option was found: {}", + name + ); + assert!( + hash_set.remove(&name), + "multiple configuration guides found for option {}", + name + ); + code_block.set_config_name(Some(name)); + } + Some(ConfigurationSection::ConfigValue(value)) => { + code_block.set_config_value(Some(value)); + } + None => return None, // end of file was reached + } + } + + Some(code_block) + } +} + +#[test] +fn configuration_snippet_tests() { + // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one + // entry for each Rust code block found. + fn get_code_blocks() -> Vec { + let mut file_iter = BufReader::new( + fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) + .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + ).lines() + .map(|l| l.unwrap()) + .enumerate(); + let mut code_blocks: Vec = Vec::new(); + let mut hash_set = Config::hash_set(); + + while let Some(cb) = + ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) + { + code_blocks.push(cb); + } + + for name in hash_set { + if !Config::is_hidden_option(&name) { + panic!("{} does not have a configuration guide", name); + } + } + + code_blocks + } + + let blocks = get_code_blocks(); + let failures = blocks + .iter() + .map(|b| b.formatted_is_idempotent()) + .fold(0, |acc, r| acc + (!r as u32)); + + // Display results. + println!("Ran {} configurations tests.", blocks.len()); + assert_eq!(failures, 0, "{} configurations tests failed", failures); +} + +#[test] +fn verify_check_works() { + assert_cli::Assert::command(&[ + "cargo", + "run", + "--bin=rustfmt", + "--", + "--write-mode=check", + "src/bin/main.rs", + ]).succeeds() + .unwrap(); +} + +#[test] +fn verify_diff_works() { + assert_cli::Assert::command(&[ + "cargo", + "run", + "--bin=rustfmt", + "--", + "--write-mode=diff", + "src/bin/main.rs", + ]).succeeds() + .unwrap(); +} diff --git a/src/utils.rs b/src/utils.rs index 00d6cf8ed08..2ede562e79d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -255,15 +255,6 @@ pub fn count_newlines(input: &str) -> usize { input.as_bytes().iter().filter(|&&c| c == b'\n').count() } -macro_rules! msg { - ($($arg:tt)*) => ( - match writeln!(&mut ::std::io::stderr(), $($arg)* ) { - Ok(_) => {}, - Err(x) => panic!("Unable to write to stderr: {}", x), - } - ) -} - // For format_missing and last_pos, need to use the source callsite (if applicable). // Required as generated code spans aren't guaranteed to follow on from the last span. macro_rules! source { diff --git a/tests/lib.rs b/tests/lib.rs deleted file mode 100644 index 7e2947929de..00000000000 --- a/tests/lib.rs +++ /dev/null @@ -1,891 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate assert_cli; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; -extern crate regex; -extern crate rustfmt_nightly as rustfmt; -extern crate term; - -use std::collections::{HashMap, HashSet}; -use std::fs; -use std::io::{self, BufRead, BufReader, Read}; -use std::iter::{Enumerate, Peekable}; -use std::path::{Path, PathBuf}; -use std::str::Chars; - -use rustfmt::config::summary::Summary; -use rustfmt::config::{Color, Config, ReportTactic}; -use rustfmt::filemap::write_system_newlines; -use rustfmt::rustfmt_diff::*; -use rustfmt::*; - -const DIFF_CONTEXT_SIZE: usize = 3; -const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; - -// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the -// given path. The `recursive` argument controls if files from subdirectories -// are also returned. -fn get_test_files(path: &Path, recursive: bool) -> Vec { - let mut files = vec![]; - if path.is_dir() { - for entry in fs::read_dir(path).expect(&format!( - "Couldn't read directory {}", - path.to_str().unwrap() - )) { - let entry = entry.expect("Couldn't get DirEntry"); - let path = entry.path(); - if path.is_dir() && recursive { - files.append(&mut get_test_files(&path, recursive)); - } else if path.extension().map_or(false, |f| f == "rs") { - files.push(path); - } - } - } - files -} - -fn verify_config_used(path: &Path, config_name: &str) { - for entry in fs::read_dir(path).expect(&format!( - "Couldn't read {} directory", - path.to_str().unwrap() - )) { - let entry = entry.expect("Couldn't get directory entry"); - let path = entry.path(); - if path.extension().map_or(false, |f| f == "rs") { - // check if "// rustfmt-:" appears in the file. - let filebuf = BufReader::new( - fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), - ); - assert!( - filebuf - .lines() - .map(|l| l.unwrap()) - .take_while(|l| l.starts_with("//")) - .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), - format!( - "config option file {} does not contain expected config name", - path.display() - ) - ); - } - } -} - -#[test] -fn verify_config_test_names() { - for path in &[ - Path::new("tests/source/configs"), - Path::new("tests/target/configs"), - ] { - for entry in fs::read_dir(path).expect("Couldn't read configs directory") { - let entry = entry.expect("Couldn't get directory entry"); - let path = entry.path(); - if path.is_dir() { - let config_name = path.file_name().unwrap().to_str().unwrap(); - - // Make sure that config name is used in the files in the directory. - verify_config_used(&path, config_name); - } - } - } -} - -// This writes to the terminal using the same approach (via term::stdout or -// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing -// using only one or the other will cause the output order to differ when -// `print_diff` selects the approach not used. -fn write_message(msg: &str) { - let mut writer = OutputWriter::new(Color::Auto); - writer.writeln(&format!("{}", msg), None); -} - -// Integration tests. The files in the tests/source are formatted and compared -// to their equivalent in tests/target. The target file and config can be -// overridden by annotations in the source file. The input and output must match -// exactly. -#[test] -fn system_tests() { - // Get all files in the tests/source directory. - let files = get_test_files(Path::new("tests/source"), true); - let (_reports, count, fails) = check_files(files); - - // Display results. - println!("Ran {} system tests.", count); - assert_eq!(fails, 0, "{} system tests failed", fails); -} - -// Do the same for tests/coverage-source directory -// the only difference is the coverage mode -#[test] -fn coverage_tests() { - let files = get_test_files(Path::new("tests/coverage/source"), true); - let (_reports, count, fails) = check_files(files); - - println!("Ran {} tests in coverage mode.", count); - assert_eq!(fails, 0, "{} tests failed", fails); -} - -#[test] -fn checkstyle_test() { - let filename = "tests/writemode/source/fn-single-line.rs"; - let expected_filename = "tests/writemode/target/checkstyle.xml"; - assert_output(Path::new(filename), Path::new(expected_filename)); -} - -#[test] -fn modified_test() { - // Test "modified" output - let filename = "tests/writemode/source/modified.rs"; - let result = get_modified_lines(Input::File(filename.into()), &Config::default()).unwrap(); - assert_eq!( - result.modified_lines, - ModifiedLines { - chunks: vec![ - ModifiedChunk { - line_number_orig: 4, - lines_removed: 4, - lines: vec!["fn blah() {}".into()], - }, - ModifiedChunk { - line_number_orig: 9, - lines_removed: 6, - lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], - }, - ], - } - ); -} - -// Helper function for comparing the results of rustfmt -// to a known output file generated by one of the write modes. -fn assert_output(source: &Path, expected_filename: &Path) { - let config = read_config(source); - let (_error_summary, file_map, _report) = format_file(source, &config); - - // Populate output by writing to a vec. - let mut out = vec![]; - let _ = filemap::write_all_files(&file_map, &mut out, &config); - let output = String::from_utf8(out).unwrap(); - - let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); - let mut expected_text = String::new(); - expected_file - .read_to_string(&mut expected_text) - .expect("Failed reading target"); - - let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - let mut failures = HashMap::new(); - failures.insert(source.to_owned(), compare); - print_mismatches_default_message(failures); - assert!(false, "Text does not match expected output"); - } -} - -// Idempotence tests. Files in tests/target are checked to be unaltered by -// rustfmt. -#[test] -fn idempotence_tests() { - // Get all files in the tests/target directory. - let files = get_test_files(Path::new("tests/target"), true); - let (_reports, count, fails) = check_files(files); - - // Display results. - println!("Ran {} idempotent tests.", count); - assert_eq!(fails, 0, "{} idempotent tests failed", fails); -} - -// Run rustfmt on itself. This operation must be idempotent. We also check that -// no warnings are emitted. -#[test] -fn self_tests() { - let mut files = get_test_files(Path::new("tests"), false); - let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; - for dir in bin_directories { - let mut path = PathBuf::from("src"); - path.push(dir); - path.push("main.rs"); - files.push(path); - } - files.push(PathBuf::from("src/lib.rs")); - - let (reports, count, fails) = check_files(files); - let mut warnings = 0; - - // Display results. - println!("Ran {} self tests.", count); - assert_eq!(fails, 0, "{} self tests failed", fails); - - for format_report in reports { - println!("{}", format_report); - warnings += format_report.warning_count(); - } - - assert_eq!( - warnings, 0, - "Rustfmt's code generated {} warnings", - warnings - ); -} - -#[test] -fn stdin_formatting_smoke_test() { - let input = Input::Text("fn main () {}".to_owned()); - let config = Config::default(); - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_no_errors()); - for &(ref file_name, ref text) in &file_map { - if let FileName::Custom(ref file_name) = *file_name { - if file_name == "stdin" { - assert_eq!(text.to_string(), "fn main() {}\n"); - return; - } - } - } - panic!("no stdin"); -} - -// FIXME(#1990) restore this test -// #[test] -// fn stdin_disable_all_formatting_test() { -// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); -// let mut child = Command::new("./target/debug/rustfmt") -// .stdin(Stdio::piped()) -// .stdout(Stdio::piped()) -// .arg("--config-path=./tests/config/disable_all_formatting.toml") -// .spawn() -// .expect("failed to execute child"); - -// { -// let stdin = child.stdin.as_mut().expect("failed to get stdin"); -// stdin -// .write_all(input.as_bytes()) -// .expect("failed to write stdin"); -// } -// let output = child.wait_with_output().expect("failed to wait on child"); -// assert!(output.status.success()); -// assert!(output.stderr.is_empty()); -// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); -// } - -#[test] -fn format_lines_errors_are_reported() { - let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); - let input = Input::Text(format!("fn {}() {{}}", long_identifier)); - let mut config = Config::default(); - config.set().error_on_line_overflow(true); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); -} - -#[test] -fn format_lines_errors_are_reported_with_tabs() { - let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); - let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); - let mut config = Config::default(); - config.set().error_on_line_overflow(true); - config.set().hard_tabs(true); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); -} - -// For each file, run rustfmt and collect the output. -// Returns the number of files checked and the number of failures. -fn check_files(files: Vec) -> (Vec, u32, u32) { - let mut count = 0; - let mut fails = 0; - let mut reports = vec![]; - - for file_name in files { - debug!("Testing '{}'...", file_name.display()); - - match idempotent_check(&file_name) { - Ok(ref report) if report.has_warnings() => { - print!("{}", report); - fails += 1; - } - Ok(report) => reports.push(report), - Err(err) => { - if let IdempotentCheckError::Mismatch(msg) = err { - print_mismatches_default_message(msg); - } - fails += 1; - } - } - - count += 1; - } - - (reports, count, fails) -} - -fn print_mismatches_default_message(result: HashMap>) { - for (file_name, diff) in result { - let mismatch_msg_formatter = - |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); - print_diff(diff, &mismatch_msg_formatter, &Default::default()); - } - - if let Some(mut t) = term::stdout() { - t.reset().unwrap_or(()); - } -} - -fn print_mismatches String>( - result: HashMap>, - mismatch_msg_formatter: T, -) { - for (_file_name, diff) in result { - print_diff(diff, &mismatch_msg_formatter, &Default::default()); - } - - if let Some(mut t) = term::stdout() { - t.reset().unwrap_or(()); - } -} - -fn read_config(filename: &Path) -> Config { - let sig_comments = read_significant_comments(filename); - // Look for a config file... If there is a 'config' property in the significant comments, use - // that. Otherwise, if there are no significant comments at all, look for a config file with - // the same name as the test file. - let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(Path::new)) - } else { - get_config(filename.with_extension("toml").file_name().map(Path::new)) - }; - - for (key, val) in &sig_comments { - if key != "target" && key != "config" { - config.override_value(key, val); - } - } - - // Don't generate warnings for to-do items. - config.set().report_todo(ReportTactic::Never); - - config -} - -fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { - let filepath = filepath.into(); - let input = Input::File(filepath); - format_input::(input, config, None).unwrap() -} - -pub enum IdempotentCheckError { - Mismatch(HashMap>), - Parse, -} - -pub fn idempotent_check(filename: &PathBuf) -> Result { - let sig_comments = read_significant_comments(filename); - let config = read_config(filename); - let (error_summary, file_map, format_report) = format_file(filename, &config); - if error_summary.has_parsing_errors() { - return Err(IdempotentCheckError::Parse); - } - - let mut write_result = HashMap::new(); - for &(ref filename, ref text) in &file_map { - let mut v = Vec::new(); - // Won't panic, as we're not doing any IO. - write_system_newlines(&mut v, text, &config).unwrap(); - // Won't panic, we are writing correct utf8. - let one_result = String::from_utf8(v).unwrap(); - if let FileName::Real(ref filename) = *filename { - write_result.insert(filename.to_owned(), one_result); - } - } - - let target = sig_comments.get("target").map(|x| &(*x)[..]); - - handle_result(write_result, target).map(|_| format_report) -} - -// Reads test config file using the supplied (optional) file name. If there's no file name or the -// file doesn't exist, just return the default config. Otherwise, the file must be read -// successfully. -fn get_config(config_file: Option<&Path>) -> Config { - let config_file_name = match config_file { - None => return Default::default(), - Some(file_name) => { - let mut full_path = PathBuf::from("tests/config/"); - full_path.push(file_name); - if !full_path.exists() { - return Default::default(); - }; - full_path - } - }; - - let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); - let mut def_config = String::new(); - def_config_file - .read_to_string(&mut def_config) - .expect("Couldn't read config"); - - Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml") -} - -// Reads significant comments of the form: // rustfmt-key: value -// into a hash map. -fn read_significant_comments(file_name: &Path) -> HashMap { - let file = - fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); - let reader = BufReader::new(file); - let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; - let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); - - // Matches lines containing significant comments or whitespace. - let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") - .expect("Failed creating pattern 2"); - - reader - .lines() - .map(|line| line.expect("Failed getting line")) - .take_while(|line| line_regex.is_match(line)) - .filter_map(|line| { - regex.captures_iter(&line).next().map(|capture| { - ( - capture - .get(1) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - capture - .get(2) - .expect("Couldn't unwrap capture") - .as_str() - .to_owned(), - ) - }) - }) - .collect() -} - -// Compare output to input. -// TODO: needs a better name, more explanation. -fn handle_result( - result: HashMap, - target: Option<&str>, -) -> Result<(), IdempotentCheckError> { - let mut failures = HashMap::new(); - - for (file_name, fmt_text) in result { - // If file is in tests/source, compare to file with same name in tests/target. - let target = get_target(&file_name, target); - let open_error = format!("Couldn't open target {:?}", &target); - let mut f = fs::File::open(&target).expect(&open_error); - - let mut text = String::new(); - let read_error = format!("Failed reading target {:?}", &target); - f.read_to_string(&mut text).expect(&read_error); - - // Ignore LF and CRLF difference for Windows. - if !string_eq_ignore_newline_repr(&fmt_text, &text) { - let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); - assert!( - !diff.is_empty(), - "Empty diff? Maybe due to a missing a newline at the end of a file?" - ); - failures.insert(file_name, diff); - } - } - - if failures.is_empty() { - Ok(()) - } else { - Err(IdempotentCheckError::Mismatch(failures)) - } -} - -// Map source file paths to their target paths. -fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { - if let Some(n) = file_name - .components() - .position(|c| c.as_os_str() == "source") - { - let mut target_file_name = PathBuf::new(); - for (i, c) in file_name.components().enumerate() { - if i == n { - target_file_name.push("target"); - } else { - target_file_name.push(c.as_os_str()); - } - } - if let Some(replace_name) = target { - target_file_name.with_file_name(replace_name) - } else { - target_file_name - } - } else { - // This is either and idempotence check or a self check - file_name.to_owned() - } -} - -#[test] -fn rustfmt_diff_make_diff_tests() { - let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); - assert_eq!( - diff, - vec![Mismatch { - line_number: 1, - line_number_orig: 1, - lines: vec![ - DiffLine::Context("a".into()), - DiffLine::Resulting("b".into()), - DiffLine::Expected("e".into()), - DiffLine::Context("c".into()), - DiffLine::Context("d".into()), - ], - }] - ); -} - -#[test] -fn rustfmt_diff_no_diff_test() { - let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); - assert_eq!(diff, vec![]); -} - -// Compare strings without distinguishing between CRLF and LF -fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { - let left = CharsIgnoreNewlineRepr(left.chars().peekable()); - let right = CharsIgnoreNewlineRepr(right.chars().peekable()); - left.eq(right) -} - -struct CharsIgnoreNewlineRepr<'a>(Peekable>); - -impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { - type Item = char; - fn next(&mut self) -> Option { - self.0.next().map(|c| { - if c == '\r' { - if *self.0.peek().unwrap_or(&'\0') == '\n' { - self.0.next(); - '\n' - } else { - '\r' - } - } else { - c - } - }) - } -} - -#[test] -fn string_eq_ignore_newline_repr_test() { - assert!(string_eq_ignore_newline_repr("", "")); - assert!(!string_eq_ignore_newline_repr("", "abc")); - assert!(!string_eq_ignore_newline_repr("abc", "")); - assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); - assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); - assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); -} - -// This enum is used to represent one of three text features in Configurations.md: a block of code -// with its starting line number, the name of a rustfmt configuration option, or the value of a -// rustfmt configuration option. -enum ConfigurationSection { - CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) - ConfigName(String), - ConfigValue(String), -} - -impl ConfigurationSection { - fn get_section>( - file: &mut Enumerate, - ) -> Option { - lazy_static! { - static ref CONFIG_NAME_REGEX: regex::Regex = - regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); - static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) - .expect("Failed creating configuration value pattern"); - } - - loop { - match file.next() { - Some((i, line)) => { - if line.starts_with("```rust") { - // Get the lines of the code block. - let lines: Vec = file.map(|(_i, l)| l) - .take_while(|l| !l.starts_with("```")) - .collect(); - let block = format!("{}\n", lines.join("\n")); - - // +1 to translate to one-based indexing - // +1 to get to first line of code (line after "```") - let start_line = (i + 2) as u32; - - return Some(ConfigurationSection::CodeBlock((block, start_line))); - } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); - } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); - } - } - None => return None, // reached the end of the file - } - } - } -} - -// This struct stores the information about code blocks in the configurations -// file, formats the code blocks, and prints formatting errors. -struct ConfigCodeBlock { - config_name: Option, - config_value: Option, - code_block: Option, - code_block_start: Option, -} - -impl ConfigCodeBlock { - fn new() -> ConfigCodeBlock { - ConfigCodeBlock { - config_name: None, - config_value: None, - code_block: None, - code_block_start: None, - } - } - - fn set_config_name(&mut self, name: Option) { - self.config_name = name; - self.config_value = None; - } - - fn set_config_value(&mut self, value: Option) { - self.config_value = value; - } - - fn set_code_block(&mut self, code_block: String, code_block_start: u32) { - self.code_block = Some(code_block); - self.code_block_start = Some(code_block_start); - } - - fn get_block_config(&self) -> Config { - let mut config = Config::default(); - if self.config_value.is_some() && self.config_value.is_some() { - config.override_value( - self.config_name.as_ref().unwrap(), - self.config_value.as_ref().unwrap(), - ); - } - config - } - - fn code_block_valid(&self) -> bool { - // We never expect to not have a code block. - assert!(self.code_block.is_some() && self.code_block_start.is_some()); - - // See if code block begins with #![rustfmt_skip]. - let fmt_skip = self.code_block - .as_ref() - .unwrap() - .split('\n') - .nth(0) - .unwrap_or("") == "#![rustfmt_skip]"; - - if self.config_name.is_none() && !fmt_skip { - write_message(&format!( - "No configuration name for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - if self.config_value.is_none() && !fmt_skip { - write_message(&format!( - "No configuration value for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - true - } - - fn has_parsing_errors(&self, error_summary: Summary) -> bool { - if error_summary.has_parsing_errors() { - write_message(&format!( - "\u{261d}\u{1f3fd} Cannot format {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return true; - } - - false - } - - fn print_diff(&self, compare: Vec) { - let mut mismatches = HashMap::new(); - mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); - print_mismatches(mismatches, |line_num| { - format!( - "\nMismatch at {}:{}:", - CONFIGURATIONS_FILE_NAME, - line_num + self.code_block_start.unwrap() - 1 - ) - }); - } - - fn formatted_has_diff(&self, file_map: &FileMap) -> bool { - let &(ref _file_name, ref text) = file_map.first().unwrap(); - let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - self.print_diff(compare); - return true; - } - - false - } - - // Return a bool indicating if formatting this code block is an idempotent - // operation. This function also triggers printing any formatting failure - // messages. - fn formatted_is_idempotent(&self) -> bool { - // Verify that we have all of the expected information. - if !self.code_block_valid() { - return false; - } - - let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); - let config = self.get_block_config(); - - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); - - !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) - } - - // Extract a code block from the iterator. Behavior: - // - Rust code blocks are identifed by lines beginning with "```rust". - // - One explicit configuration setting is supported per code block. - // - Rust code blocks with no configuration setting are illegal and cause an - // assertion failure, unless the snippet begins with #![rustfmt_skip]. - // - Configuration names in Configurations.md must be in the form of - // "## `NAME`". - // - Configuration values in Configurations.md must be in the form of - // "#### `VALUE`". - fn extract>( - file: &mut Enumerate, - prev: Option<&ConfigCodeBlock>, - hash_set: &mut HashSet, - ) -> Option { - let mut code_block = ConfigCodeBlock::new(); - code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); - - loop { - match ConfigurationSection::get_section(file) { - Some(ConfigurationSection::CodeBlock((block, start_line))) => { - code_block.set_code_block(block, start_line); - break; - } - Some(ConfigurationSection::ConfigName(name)) => { - assert!( - Config::is_valid_name(&name), - "an unknown configuration option was found: {}", - name - ); - assert!( - hash_set.remove(&name), - "multiple configuration guides found for option {}", - name - ); - code_block.set_config_name(Some(name)); - } - Some(ConfigurationSection::ConfigValue(value)) => { - code_block.set_config_value(Some(value)); - } - None => return None, // end of file was reached - } - } - - Some(code_block) - } -} - -#[test] -fn configuration_snippet_tests() { - // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one - // entry for each Rust code block found. - fn get_code_blocks() -> Vec { - let mut file_iter = BufReader::new( - fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) - .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), - ).lines() - .map(|l| l.unwrap()) - .enumerate(); - let mut code_blocks: Vec = Vec::new(); - let mut hash_set = Config::hash_set(); - - while let Some(cb) = - ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) - { - code_blocks.push(cb); - } - - for name in hash_set { - if !Config::is_hidden_option(&name) { - panic!("{} does not have a configuration guide", name); - } - } - - code_blocks - } - - let blocks = get_code_blocks(); - let failures = blocks - .iter() - .map(|b| b.formatted_is_idempotent()) - .fold(0, |acc, r| acc + (!r as u32)); - - // Display results. - println!("Ran {} configurations tests.", blocks.len()); - assert_eq!(failures, 0, "{} configurations tests failed", failures); -} - -#[test] -fn verify_check_works() { - assert_cli::Assert::command(&[ - "cargo", - "run", - "--bin=rustfmt", - "--", - "--write-mode=check", - "src/bin/main.rs", - ]).succeeds() - .unwrap(); -} - -#[test] -fn verify_diff_works() { - assert_cli::Assert::command(&[ - "cargo", - "run", - "--bin=rustfmt", - "--", - "--write-mode=diff", - "src/bin/main.rs", - ]).succeeds() - .unwrap(); -} -- cgit 1.4.1-3-g733a5 From 866900449aee9281c88076076b8bc558a8aa5140 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Apr 2018 22:10:48 +1200 Subject: Make some more stuff private 0.6 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/lib.rs | 14 +++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 4ce2fae6a3f..a15fd217409 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,7 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustfmt-nightly" -version = "0.5.0" +version = "0.6.0" dependencies = [ "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index bacde50ce77..4b5a2e00586 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.5.0" +version = "0.6.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/src/lib.rs b/src/lib.rs index 506defad30e..9386c72f077 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ extern crate unicode_segmentation; use std::collections::HashMap; use std::error; use std::fmt; -use std::io::{self, stdout, BufRead, Write}; +use std::io::{self, stdout, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::PathBuf; use std::rc::Rc; @@ -819,7 +819,7 @@ fn format_input_inner( /// A single span of changed lines, with 0 or more removed lines /// and a vector of 0 or more inserted lines. #[derive(Debug, PartialEq, Eq)] -pub struct ModifiedChunk { +struct ModifiedChunk { /// The first to be removed from the original text pub line_number_orig: u32, /// The number of lines which have been replaced @@ -830,13 +830,14 @@ pub struct ModifiedChunk { /// Set of changed sections of a file. #[derive(Debug, PartialEq, Eq)] -pub struct ModifiedLines { +struct ModifiedLines { /// The set of changed chunks. pub chunks: Vec, } /// The successful result of formatting via `get_modified_lines()`. -pub struct ModifiedLinesResult { +#[cfg(test)] +struct ModifiedLinesResult { /// The high level summary details pub summary: Summary, /// The result Filemap @@ -849,10 +850,13 @@ pub struct ModifiedLinesResult { /// Format a file and return a `ModifiedLines` data structure describing /// the changed ranges of lines. -pub fn get_modified_lines( +#[cfg(test)] +fn get_modified_lines( input: Input, config: &Config, ) -> Result { + use std::io::BufRead; + let mut data = Vec::new(); let mut config = config.clone(); -- cgit 1.4.1-3-g733a5 From 5b5a72c840aebd8dfdfbd2a125bc910d8094736a Mon Sep 17 00:00:00 2001 From: Roman Stoliar Date: Fri, 20 Apr 2018 17:31:31 +0300 Subject: keep auto trait --- src/items.rs | 19 ++++++++++++------- src/utils.rs | 8 ++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6d474a3ccd6..91db82cd9ed 100644 --- a/src/items.rs +++ b/src/items.rs @@ -32,9 +32,9 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; use types::TraitTyParamBounds; -use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_constness, - format_defaultness, format_mutability, format_unsafety, format_visibility, - is_attributes_extendable, last_line_contains_single_line_comment, +use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_auto, + format_constness, format_defaultness, format_mutability, format_unsafety, + format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, stmt_expr, trimmed_last_line_width}; use vertical::rewrite_with_alignment; @@ -936,16 +936,21 @@ fn format_struct( } pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { - if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) = - item.node + if let ast::ItemKind::Trait( + is_auto, + unsafety, + ref generics, + ref type_param_bounds, + ref trait_items, + ) = item.node { let mut result = String::with_capacity(128); let header = format!( - "{}{}trait ", + "{}{}{}trait ", + format_auto(is_auto), format_visibility(&item.vis), format_unsafety(unsafety), ); - result.push_str(&header); let body_lo = context.snippet_provider.span_after(item.span, "{"); diff --git a/src/utils.rs b/src/utils.rs index 2ede562e79d..2493c9a5c74 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -81,6 +81,14 @@ pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { } } +#[inline] +pub fn format_auto(is_auto: ast::IsAuto) -> &'static str { + match is_auto { + ast::IsAuto::Yes => "auto ", + ast::IsAuto::No => "", + } +} + #[inline] pub fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { -- cgit 1.4.1-3-g733a5 From ac8ae0062544743aaea1719a34f299b66f2b7dc9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Apr 2018 07:21:23 +0900 Subject: Cargo update and clippy (#2643) --- Cargo.lock | 147 +++++++++++++++++++++++++--------------------------- Cargo.toml | 2 +- src/expr.rs | 14 ++--- src/imports.rs | 11 ++-- src/items.rs | 12 +---- src/lib.rs | 26 +++++----- src/lists.rs | 2 +- src/macros.rs | 10 ++-- src/reorder.rs | 2 +- src/rustfmt_diff.rs | 2 +- src/types.rs | 2 +- 11 files changed, 104 insertions(+), 126 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index a15fd217409..fdee0b8ebe8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,13 +15,13 @@ dependencies = [ "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "atty" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -77,9 +77,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -89,9 +89,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -117,8 +117,8 @@ name = "derive-new" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -152,10 +152,10 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -260,11 +260,6 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-traits" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.3.3" @@ -289,13 +284,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -316,10 +311,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -367,7 +362,7 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -375,7 +370,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -384,7 +379,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -392,20 +387,20 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -413,32 +408,32 @@ dependencies = [ [[package]] name = "rustc-ap-serialize" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "103.0.0" +version = "110.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -457,17 +452,17 @@ dependencies = [ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -494,7 +489,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -503,7 +498,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -513,16 +508,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -532,19 +527,18 @@ name = "serde_derive_internals" version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -557,14 +551,14 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -577,8 +571,8 @@ name = "syn" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -588,7 +582,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -641,7 +635,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -732,7 +726,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930" -"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" +"checksum atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6609a866dd1a1b2d0ee1362195bf3e4f6438abb2d80120b83b1e1f4fb6476dd0" "checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" @@ -750,7 +744,7 @@ dependencies = [ "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834" -"checksum env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "be27f8ea102a7182093a80d98f0b78623b580eda8791cbe8e2345fe6e57567a6" +"checksum env_logger 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "00c45cec4cde3daac5f036c74098b4956151525cdf360cff5ee0092c98823e54" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" @@ -766,38 +760,37 @@ dependencies = [ "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" -"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" "checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" -"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b16749538926f394755373f0dfec0852d79b3bd512a5906ceaeb72ee64a4eaa0" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" -"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" -"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" -"checksum rustc-ap-rustc_cratesio_shim 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "463834ac5ea777cb56c073586675fac37292f8425aafb3757efca7e6a76545aa" -"checksum rustc-ap-rustc_data_structures 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d256eeab1b8639c2a1fd341e54f3613f8150bc262e4ec9361a29bbcb162906d" -"checksum rustc-ap-rustc_errors 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6dd73033bb512845a6df347174c65ad430c92ecd35527e24d8bb186f5664ee" -"checksum rustc-ap-serialize 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356d338dbe538c7d6428296872d5d68da8f091e34eb89bca3b3f245ed0785e5e" -"checksum rustc-ap-syntax 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f02edede4ba70963a7dac2308876f03f76f9edd48a035e5abc8fa37c57a77c8" -"checksum rustc-ap-syntax_pos 103.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8e50d4c38121fa8ded3ffbf94926ec74c95f24316c3b80de84fbfb42c005cf" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0256e318ad99c467d24bd7188f2d4a3028360621bb92d769b4b65fc44717d514" +"checksum rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83430df7f76ea85c1f70fe145041576eee8fd5d77053bf426df24b480918d185" +"checksum rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b03f874277103039816f6467b1ff30a81b1d6a29d4de6efccefe4c488f6535a" +"checksum rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2e47cf949f06b0c7ab7566c2f69d49f28cb3ecf1bb8bf0bda48b1ba5b7945ae" +"checksum rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "625e6fb41fde299082cda3bceb08f81c9ba56b14a2ec737b4366f9c3c9be07d8" +"checksum rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474a23ef1a1245ae02c5fd6a1e9a0725ce6fd25ca2294703c03bddce041f867b" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "53e6b6859395f46cf528414659ce43e70902b2277519707c3bd91797b3320330" -"checksum serde_derive 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "16e97f8dc5b2dabc0183e0cde24b1a53835e5bb3d2c9e0fdb077f895bba7f2a9" +"checksum serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)" = "0c855d888276f20d140223bd06515e5bf1647fd6d02593cb5792466d9a8ec2d0" +"checksum serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)" = "aa113e5fc4b008a626ba2bbd41330b56c9987d667f79f7b243e5a2d03d91ed1c" "checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" -"checksum serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7bf1cbb1387028a13739cb018ee0d9b3db534f22ca3c84a5904f7eadfde14e75" +"checksum serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6c4e049dc657a99e394bd85c22acbf97356feeec6dbf44150f2dcf79fb3118" "checksum skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c8431f8fca168e2db4be547bd8329eac70d095dff1444fee4b0fa0fabc7df75a" -"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" +"checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" diff --git a/Cargo.toml b/Cargo.toml index 4b5a2e00586..0924527f372 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-syntax = "103.0.0" +rustc-ap-syntax = "110.0.0" [dev-dependencies] assert_cli = "0.5" diff --git a/src/expr.rs b/src/expr.rs index 84ecbb57184..cd8bfa8a72b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1661,11 +1661,7 @@ fn rewrite_struct_lit<'a>( let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); let ends_with_comma = span_ends_with_comma(context, span); - let force_no_trailing_comma = if context.inside_macro() && !ends_with_comma { - true - } else { - false - }; + let force_no_trailing_comma = context.inside_macro() && !ends_with_comma; let fmt = struct_lit_formatting( nested_shape, @@ -1846,12 +1842,10 @@ where } else { Some(SeparatorTactic::Never) } + } else if items.len() == 1 { + Some(SeparatorTactic::Always) } else { - if items.len() == 1 { - Some(SeparatorTactic::Always) - } else { - None - } + None }; overflow::rewrite_with_parens( context, diff --git a/src/imports.rs b/src/imports.rs index 85ea119af95..f7286fc3b43 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -381,7 +381,7 @@ impl UseTree { // Normalise foo::self -> foo. if let UseSegment::Slf(None) = last { - if self.path.len() > 0 { + if !self.path.is_empty() { return self; } } @@ -494,8 +494,8 @@ impl UseTree { UseSegment::List(list) => { let prefix = &self.path[..self.path.len() - 1]; let mut result = vec![]; - for nested_use_tree in list.into_iter() { - for mut flattend in nested_use_tree.clone().flatten().iter_mut() { + for nested_use_tree in list { + for mut flattend in &mut nested_use_tree.clone().flatten() { let mut new_path = prefix.to_vec(); new_path.append(&mut flattend.path); result.push(UseTree { @@ -672,7 +672,7 @@ fn rewrite_nested_use_tree( list_items.push(ListItem::from_str(use_tree.rewrite(context, nested_shape)?)); } } - let (tactic, remaining_width) = if use_tree_list.iter().any(|use_segment| { + let has_nested_list = use_tree_list.iter().any(|use_segment| { use_segment .path .last() @@ -680,7 +680,8 @@ fn rewrite_nested_use_tree( UseSegment::List(..) => true, _ => false, }) - }) { + }); + let (tactic, remaining_width) = if has_nested_list { (DefinitiveListTactic::Vertical, 0) } else { let remaining_width = shape.width.checked_sub(2).unwrap_or(0); diff --git a/src/items.rs b/src/items.rs index 91db82cd9ed..80e837ed904 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2722,17 +2722,7 @@ impl Rewrite for ast::ForeignItem { let mut_str = if is_mutable { "mut " } else { "" }; let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); // 1 = ; - let shape = shape.sub_width(1)?; - ty.rewrite(context, shape).map(|ty_str| { - // 1 = space between prefix and type. - let sep = if prefix.len() + ty_str.len() + 1 <= shape.width { - Cow::from(" ") - } else { - let nested_indent = shape.indent.block_indent(context.config); - nested_indent.to_string_with_newline(context.config) - }; - format!("{}{}{};", prefix, sep, ty_str) - }) + rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } ast::ForeignItemKind::Ty => { let vis = format_visibility(&self.vis); diff --git a/src/lib.rs b/src/lib.rs index 9386c72f077..0a5c7307e4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -220,12 +220,12 @@ impl FormatReport { write!(t, "{} ", error.msg_prefix())?; t.reset()?; t.attr(term::Attr::Bold)?; - write!(t, "{}\n", error.kind)?; + writeln!(t, "{}", error.kind)?; // Second line: file info write!(t, "{}--> ", &prefix_spaces[1..])?; t.reset()?; - write!(t, "{}:{}\n", file, error.line)?; + writeln!(t, "{}:{}", file, error.line)?; // Third to fifth lines: show the line which triggered error, if available. if !error.line_buffer.is_empty() { @@ -233,11 +233,11 @@ impl FormatReport { t.attr(term::Attr::Bold)?; write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; t.reset()?; - write!(t, "{}\n", error.line_buffer)?; + writeln!(t, "{}", error.line_buffer)?; t.attr(term::Attr::Bold)?; write!(t, "{}| ", prefix_spaces)?; t.fg(term::color::RED)?; - write!(t, "{}\n", target_str(space_len, target_len))?; + writeln!(t, "{}", target_str(space_len, target_len))?; t.reset()?; } @@ -247,9 +247,9 @@ impl FormatReport { t.attr(term::Attr::Bold)?; write!(t, "{}= note: ", prefix_spaces)?; t.reset()?; - write!(t, "{}\n", error.msg_suffix())?; + writeln!(t, "{}", error.msg_suffix())?; } else { - write!(t, "\n")?; + writeln!(t)?; } t.reset()?; } @@ -307,9 +307,9 @@ impl fmt::Display for FormatReport { format!("{}note= ", prefix_spaces) }; - write!( + writeln!( fmt, - "{}\n{}\n{}\n{}{}\n", + "{}\n{}\n{}\n{}{}", error_info, file_info, error_line_buffer, @@ -319,9 +319,9 @@ impl fmt::Display for FormatReport { } } if !self.file_error_map.is_empty() { - write!( + writeln!( fmt, - "warning: rustfmt may have failed to format. See previous {} errors.\n", + "warning: rustfmt may have failed to format. See previous {} errors.", self.warning_count(), )?; } @@ -384,7 +384,7 @@ where debug_assert_eq!( visitor.line_number, - ::utils::count_newlines(&format!("{}", visitor.buffer)) + ::utils::count_newlines(&visitor.buffer) ); let filename = path.clone(); @@ -627,7 +627,7 @@ fn enclose_in_main_block(s: &str, config: &Config) -> String { } result.push_str(&line); result.push('\n'); - need_indent = !(kind.is_string() && !line.ends_with('\\')); + need_indent = !kind.is_string() || line.ends_with('\\'); } result.push('}'); result @@ -680,7 +680,7 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option line }; result.push_str(trimmed_line); - is_indented = !(kind.is_string() && !line.ends_with('\\')); + is_indented = !kind.is_string() || line.ends_with('\\'); } Some(result) } diff --git a/src/lists.rs b/src/lists.rs index 8b75e68f6f5..9e5ea33d296 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -458,7 +458,7 @@ where let item = item.as_ref(); let inner_item_width = item.inner_as_ref().len(); if !first - && (item.is_different_group() || !item.post_comment.is_some() + && (item.is_different_group() || item.post_comment.is_none() || inner_item_width + overhead > max_budget) { return max_width; diff --git a/src/macros.rs b/src/macros.rs index 9cf033e9693..a76520c8fe6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -580,7 +580,7 @@ impl MacroArgKind { let another = another .as_ref() .and_then(|a| a.rewrite(context, shape, use_multiple_lines)) - .unwrap_or("".to_owned()); + .unwrap_or_else(|| "".to_owned()); let repeat_tok = pprust::token_to_string(tok); Some(format!("${}{}{}{}{}", lhs, inner, rhs, another, repeat_tok)) @@ -685,7 +685,7 @@ impl MacroArgParser { match iter.next() { Some(TokenTree::Token(sp, Token::Ident(ref ident, _))) => { self.result.push(ParsedMacroArg { - kind: MacroArgKind::MetaVariable(ident.clone(), self.buf.clone()), + kind: MacroArgKind::MetaVariable(*ident, self.buf.clone()), span: mk_sp(self.lo, sp.hi()), }); @@ -718,7 +718,7 @@ impl MacroArgParser { let mut hi = span.hi(); // Parse '*', '+' or '?. - while let Some(ref tok) = iter.next() { + for ref tok in iter { self.set_last_tok(tok); if first { first = false; @@ -1080,7 +1080,7 @@ fn indent_macro_snippet( .min()?; Some( - String::from(first_line) + "\n" + first_line + "\n" + &trimmed_lines .iter() .map( @@ -1250,7 +1250,7 @@ impl MacroBranch { if !l.is_empty() && need_indent { s += &indent_str; } - (s + l + "\n", !(kind.is_string() && !l.ends_with('\\'))) + (s + l + "\n", !kind.is_string() || l.ends_with('\\')) }, ) .0; diff --git a/src/reorder.rs b/src/reorder.rs index fb1716379b1..7d7c1ff8d32 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -149,7 +149,7 @@ fn rewrite_reorderable_items( .into_iter() .map(|use_tree| ListItem { item: use_tree.rewrite_top_level(context, nested_shape), - ..use_tree.list_item.unwrap_or_else(|| ListItem::empty()) + ..use_tree.list_item.unwrap_or_else(ListItem::empty) }) .collect(); diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 426f7da96a2..178ed99f696 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -160,7 +160,7 @@ where for mismatch in diff { let title = get_section_title(mismatch.line_number); - writer.writeln(&format!("{}", title), None); + writer.writeln(&title, None); for line in mismatch.lines { match line { diff --git a/src/types.rs b/src/types.rs index 0c0cad8244b..4bde91f67f1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -482,7 +482,7 @@ fn rewrite_bounded_lifetime( ) -> Option { let result = lt.rewrite(context, shape)?; - if bounds.len() == 0 { + if bounds.is_empty() { Some(result) } else { let colon = type_bound_colon(context); -- cgit 1.4.1-3-g733a5 From efb8069cfc8b587994d842936b4d14d257f480c4 Mon Sep 17 00:00:00 2001 From: Tibo Date: Tue, 24 Apr 2018 15:45:28 +1000 Subject: Replace std::Error with failure for FormatDiff --- Cargo.lock | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/format-diff/main.rs | 38 +++++++++-------------------- 3 files changed, 76 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index fdee0b8ebe8..3d1d1cb200b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,6 +175,25 @@ dependencies = [ "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "failure" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -309,6 +328,11 @@ name = "quick-error" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.5.2" @@ -453,6 +477,7 @@ dependencies = [ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -566,6 +591,16 @@ name = "stable_deref_trait" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.13.1" @@ -576,6 +611,23 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -653,6 +705,11 @@ name = "unicode-width" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -747,6 +804,8 @@ dependencies = [ "checksum env_logger 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "00c45cec4cde3daac5f036c74098b4956151525cdf360cff5ee0092c98823e54" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" +"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" @@ -766,6 +825,7 @@ dependencies = [ "checksum proc-macro2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b16749538926f394755373f0dfec0852d79b3bd512a5906ceaeb72ee64a4eaa0" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" @@ -792,7 +852,10 @@ dependencies = [ "checksum skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c8431f8fca168e2db4be547bd8329eac70d095dff1444fee4b0fa0fabc7df75a" "checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" @@ -803,6 +866,7 @@ dependencies = [ "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" diff --git a/Cargo.toml b/Cargo.toml index 0924527f372..4074f67b875 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" rustc-ap-syntax = "110.0.0" +failure = "0.1.1" [dev-dependencies] assert_cli = "0.5" diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 402f7ab507a..fe528a6c0ea 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -15,6 +15,8 @@ #![deny(warnings)] extern crate env_logger; +#[macro_use] +extern crate failure; extern crate getopts; #[macro_use] extern crate log; @@ -24,9 +26,8 @@ extern crate serde_derive; extern crate serde_json as json; use std::collections::HashSet; -use std::error::Error; use std::io::{self, BufRead}; -use std::{env, fmt, process}; +use std::{env, process}; use regex::Regex; @@ -35,31 +36,14 @@ use regex::Regex; /// We only want to format rust files by default. const DEFAULT_PATTERN: &str = r".*\.rs"; -#[derive(Debug)] +#[derive(Fail, Debug)] enum FormatDiffError { - IncorrectOptions(getopts::Fail), - IncorrectFilter(regex::Error), - IoError(io::Error), -} - -impl fmt::Display for FormatDiffError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt::Display::fmt(self.cause().unwrap(), f) - } -} - -impl Error for FormatDiffError { - fn description(&self) -> &str { - self.cause().unwrap().description() - } - - fn cause(&self) -> Option<&Error> { - Some(match *self { - FormatDiffError::IoError(ref e) => e, - FormatDiffError::IncorrectFilter(ref e) => e, - FormatDiffError::IncorrectOptions(ref e) => e, - }) - } + #[fail(display = "{}", _0)] + IncorrectOptions(#[cause] getopts::Fail), + #[fail(display = "{}", _0)] + IncorrectFilter(#[cause] regex::Error), + #[fail(display = "{}", _0)] + IoError(#[cause] io::Error), } impl From for FormatDiffError { @@ -99,7 +83,7 @@ fn main() { ); if let Err(e) = run(&opts) { - println!("{}", opts.usage(e.description())); + println!("{}", opts.usage(&format!("{}", e))); process::exit(1); } } -- cgit 1.4.1-3-g733a5 From 5581be26162fb34275538a7c4660b5f4e69a5d2a Mon Sep 17 00:00:00 2001 From: Tibo Date: Tue, 24 Apr 2018 18:10:09 +1000 Subject: Use failure for FormattingError --- src/lib.rs | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 0a5c7307e4f..9b1168f5d12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ #[macro_use] extern crate derive_new; extern crate diff; +extern crate failure; extern crate getopts; extern crate itertools; #[cfg(test)] @@ -53,6 +54,7 @@ use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use comment::{CharClasses, FullCodeCharKind, LineClasses}; +use failure::Fail; use issues::{BadIssueSeeker, Issue}; use shape::Indent; use utils::use_colored_tty; @@ -109,33 +111,26 @@ pub(crate) type FileMap = Vec; pub(crate) type FileRecord = (FileName, String); -#[derive(Clone, Copy)] +#[derive(Fail, Debug, Clone, Copy)] pub enum ErrorKind { // Line has exceeded character limit (found, maximum) + #[fail( + display = "line formatted, but exceeded maximum width (maximum: {} (see `max_width` option), found: {})", + _0, + _1 + )] LineOverflow(usize, usize), // Line ends in whitespace + #[fail(display = "left behind trailing whitespace")] TrailingWhitespace, // TODO or FIXME item without an issue number + #[fail(display = "found {}", _0)] BadIssue(Issue), // License check has failed + #[fail(display = "license check failed")] LicenseCheck, } -impl fmt::Display for ErrorKind { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - ErrorKind::LineOverflow(found, maximum) => write!( - fmt, - "line formatted, but exceeded maximum width (maximum: {} (see `max_width` option), found: {})", - maximum, found, - ), - ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"), - ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue), - ErrorKind::LicenseCheck => write!(fmt, "license check failed"), - } - } -} - // Formatting errors that are identified *after* rustfmt has run. struct FormattingError { line: usize, -- cgit 1.4.1-3-g733a5 From b7df23c3d5a3950ea6432acd71d34cd847a3be89 Mon Sep 17 00:00:00 2001 From: Tibo Date: Thu, 26 Apr 2018 13:48:48 +1000 Subject: Replace completely std::error with failure crate --- src/bin/main.rs | 11 ++++++++--- src/config/config_type.rs | 8 ++++---- src/config/mod.rs | 19 +++++++++---------- src/config/options.rs | 19 +++++++++++-------- src/lib.rs | 7 +++---- 5 files changed, 35 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 453c7806d23..0ddf2f8c3df 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -11,6 +11,7 @@ #![cfg(not(test))] extern crate env_logger; +extern crate failure; extern crate getopts; extern crate rustfmt_nightly as rustfmt; @@ -19,6 +20,8 @@ use std::fs::File; use std::io::{self, stdout, Read, Write}; use std::path::PathBuf; +use failure::err_msg; + use getopts::{Matches, Options}; use rustfmt::{emit_post_matter, emit_pre_matter, load_config, CliOptions, Config, FmtResult, @@ -167,7 +170,7 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { Ok((WriteMode::None, Summary::default())) } Operation::ConfigOutputDefault { path } => { - let toml = Config::default().all_options().to_toml()?; + let toml = Config::default().all_options().to_toml().map_err(err_msg)?; if let Some(path) = path { let mut file = File::create(path)?; file.write_all(toml.as_bytes())?; @@ -186,7 +189,9 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { // parse file_lines if let Some(ref file_lines) = matches.opt_str("file-lines") { - config.set().file_lines(file_lines.parse()?); + config + .set() + .file_lines(file_lines.parse().map_err(err_msg)?); for f in config.file_lines().files() { match *f { FileName::Custom(ref f) if f == "stdin" => {} @@ -273,7 +278,7 @@ fn format( // that were used during formatting as TOML. if let Some(path) = minimal_config_path { let mut file = File::create(path)?; - let toml = config.used_options().to_toml()?; + let toml = config.used_options().to_toml().map_err(err_msg)?; file.write_all(toml.as_bytes())?; } diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 3b9ca90350c..828dfe8b024 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -305,12 +305,12 @@ macro_rules! create_config { /// /// Return a `Config` if the config could be read and parsed from /// the file, Error otherwise. - pub(super) fn from_toml_path(file_path: &Path) -> Result { + pub(super) fn from_toml_path(file_path: &Path) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + .map_err(::failure::err_msg) } /// Resolve the config for input in `dir`. @@ -322,12 +322,12 @@ macro_rules! create_config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), ::failure::Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of a the nearest project file if one exists, /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { + fn resolve_project_file(dir: &Path) -> Result, ::failure::Error> { let mut current = if dir.is_relative() { env::current_dir()?.join(dir) } else { diff --git a/src/config/mod.rs b/src/config/mod.rs index 8dde1e05c3d..8c90c556b4d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -12,16 +12,17 @@ use regex::Regex; use std::cell::Cell; use std::default::Default; use std::fs::File; -use std::io::{Error, ErrorKind, Read}; +use std::io::{ErrorKind, Read}; use std::path::{Path, PathBuf}; use std::{env, fs}; -use {FmtError, FmtResult}; +use FmtResult; use config::config_type::ConfigType; use config::file_lines::FileLines; pub use config::lists::*; pub use config::options::*; +use failure::Error; #[macro_use] pub mod config_type; @@ -161,11 +162,9 @@ pub fn load_config( }; let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref()) - .map(|p| (p, Some(over_ride.to_owned()))) - .map_err(FmtError::from) + Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned()))) } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path).map_err(FmtError::from) + Config::from_resolved_toml_path(file_path) } else { Ok((Config::default(), None)) }; @@ -181,7 +180,7 @@ pub fn load_config( // Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` // // Return the path if a config file exists, empty if no file exists, and Error for IO errors -fn get_toml_path(dir: &Path) -> Result, Error> { +fn get_toml_path(dir: &Path) -> FmtResult> { const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; for config_file_name in &CONFIG_FILE_NAMES { let config_file = dir.join(config_file_name); @@ -193,7 +192,7 @@ fn get_toml_path(dir: &Path) -> Result, Error> { // find the project file yet, and continue searching. Err(e) => { if e.kind() != ErrorKind::NotFound { - return Err(e); + return Err(Error::from(e)); } } _ => {} @@ -204,10 +203,10 @@ fn get_toml_path(dir: &Path) -> Result, Error> { fn config_path(options: &CliOptions) -> FmtResult> { let config_path_not_found = |path: &str| -> FmtResult> { - Err(FmtError::from(format!( + Err(format_err!( "Error: unable to find a config file for the given path: `{}`", path - ))) + )) }; // Read the config_path and convert to parent dir if a file is provided. diff --git a/src/config/options.rs b/src/config/options.rs index 73dbdb88663..9721815eeee 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -14,7 +14,9 @@ use config::config_type::ConfigType; use config::file_lines::FileLines; use config::lists::*; use config::Config; -use {FmtError, FmtResult, WRITE_MODE_LIST}; +use {FmtResult, WRITE_MODE_LIST}; + +use failure::err_msg; use getopts::Matches; use std::collections::HashSet; @@ -332,8 +334,8 @@ impl CliOptions { .map(|c| c == "nightly") .unwrap_or(false); if unstable_features && !rust_nightly { - return Err(FmtError::from( - "Unstable features are only available on Nightly channel", + return Err(format_err!( + "Unstable features are only available on Nightly channel" )); } else { options.unstable_features = unstable_features; @@ -345,22 +347,23 @@ impl CliOptions { if let Ok(write_mode) = WriteMode::from_str(write_mode) { options.write_mode = Some(write_mode); } else { - return Err(FmtError::from(format!( + return Err(format_err!( "Invalid write-mode: {}, expected one of {}", - write_mode, WRITE_MODE_LIST - ))); + write_mode, + WRITE_MODE_LIST + )); } } if let Some(ref color) = matches.opt_str("color") { match Color::from_str(color) { Ok(color) => options.color = Some(color), - _ => return Err(FmtError::from(format!("Invalid color: {}", color))), + _ => return Err(format_err!("Invalid color: {}", color)), } } if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse()?; + options.file_lines = file_lines.parse().map_err(err_msg)?; } if matches.opt_present("skip-children") { diff --git a/src/lib.rs b/src/lib.rs index 9b1168f5d12..b272402b20f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ #[macro_use] extern crate derive_new; extern crate diff; +#[macro_use] extern crate failure; extern crate getopts; extern crate itertools; @@ -38,7 +39,6 @@ extern crate toml; extern crate unicode_segmentation; use std::collections::HashMap; -use std::error; use std::fmt; use std::io::{self, stdout, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -64,8 +64,7 @@ pub use config::options::CliOptions; pub use config::summary::Summary; pub use config::{file_lines, load_config, Config, WriteMode}; -pub type FmtError = Box; -pub type FmtResult = std::result::Result; +pub type FmtResult = std::result::Result; pub const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle|check]"; @@ -896,7 +895,7 @@ pub enum Input { pub fn format_and_emit_report(input: Input, config: &Config) -> FmtResult { if !config.version_meets_requirement() { - return Err(FmtError::from("Version mismatch")); + return Err(format_err!("Version mismatch")); } let out = &mut stdout(); match format_input(input, config, Some(out)) { -- cgit 1.4.1-3-g733a5 From e06c9c8c5304d1d187e3adb603446bfb63afdd6d Mon Sep 17 00:00:00 2001 From: Tibo Date: Thu, 26 Apr 2018 14:20:06 +1000 Subject: Allow `io::Error` to live longer before being wrapped in a `failure::Error` --- src/config/config_type.rs | 8 ++++---- src/config/mod.rs | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 828dfe8b024..3b9ca90350c 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -305,12 +305,12 @@ macro_rules! create_config { /// /// Return a `Config` if the config could be read and parsed from /// the file, Error otherwise. - pub(super) fn from_toml_path(file_path: &Path) -> Result { + pub(super) fn from_toml_path(file_path: &Path) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(::failure::err_msg) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolve the config for input in `dir`. @@ -322,12 +322,12 @@ macro_rules! create_config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), ::failure::Error> { + pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of a the nearest project file if one exists, /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, ::failure::Error> { + fn resolve_project_file(dir: &Path) -> Result, Error> { let mut current = if dir.is_relative() { env::current_dir()?.join(dir) } else { diff --git a/src/config/mod.rs b/src/config/mod.rs index 8c90c556b4d..23897f3cc32 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -12,17 +12,14 @@ use regex::Regex; use std::cell::Cell; use std::default::Default; use std::fs::File; -use std::io::{ErrorKind, Read}; +use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; use std::{env, fs}; -use FmtResult; - use config::config_type::ConfigType; use config::file_lines::FileLines; pub use config::lists::*; pub use config::options::*; -use failure::Error; #[macro_use] pub mod config_type; @@ -155,7 +152,7 @@ create_config! { pub fn load_config( file_path: Option<&Path>, options: Option<&CliOptions>, -) -> FmtResult<(Config, Option)> { +) -> Result<(Config, Option), Error> { let over_ride = match options { Some(opts) => config_path(opts)?, None => None, @@ -180,7 +177,7 @@ pub fn load_config( // Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` // // Return the path if a config file exists, empty if no file exists, and Error for IO errors -fn get_toml_path(dir: &Path) -> FmtResult> { +fn get_toml_path(dir: &Path) -> Result, Error> { const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; for config_file_name in &CONFIG_FILE_NAMES { let config_file = dir.join(config_file_name); @@ -192,7 +189,7 @@ fn get_toml_path(dir: &Path) -> FmtResult> { // find the project file yet, and continue searching. Err(e) => { if e.kind() != ErrorKind::NotFound { - return Err(Error::from(e)); + return Err(e); } } _ => {} @@ -201,11 +198,14 @@ fn get_toml_path(dir: &Path) -> FmtResult> { Ok(None) } -fn config_path(options: &CliOptions) -> FmtResult> { - let config_path_not_found = |path: &str| -> FmtResult> { - Err(format_err!( - "Error: unable to find a config file for the given path: `{}`", - path +fn config_path(options: &CliOptions) -> Result, Error> { + let config_path_not_found = |path: &str| -> Result, Error> { + Err(Error::new( + ErrorKind::NotFound, + format!( + "Error: unable to find a config file for the given path: `{}`", + path + ), )) }; -- cgit 1.4.1-3-g733a5 From 0f4ed08d0e3d180d66e46904126c3792f57668a9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 Apr 2018 11:12:25 +1200 Subject: Harden tests to not rely on CWD --- src/test/mod.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index b0971136352..cd746a6486b 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -857,28 +857,53 @@ fn configuration_snippet_tests() { assert_eq!(failures, 0, "{} configurations tests failed", failures); } +struct TempFile { + file_name: &'static str, +} + +fn make_temp_file(file_name: &'static str) -> TempFile { + use std::fs::File; + + let mut file = File::create(file_name).expect("Couldn't create temp file"); + let content = "fn main() {}\n"; + file.write_all(content.as_bytes()) + .expect("Couldn't write temp file"); + TempFile { file_name } +} + +impl Drop for TempFile { + fn drop(&mut self) { + use std::fs::remove_file; + remove_file(self.file_name).expect("Couldn't delete temp file"); + } +} + #[test] fn verify_check_works() { + let file_name = "temp_check.rs"; + let _temp_file = make_temp_file(file_name); assert_cli::Assert::command(&[ "cargo", "run", "--bin=rustfmt", "--", "--write-mode=check", - "src/bin/main.rs", + file_name, ]).succeeds() .unwrap(); } #[test] fn verify_diff_works() { + let file_name = "temp_diff.rs"; + let _temp_file = make_temp_file(file_name); assert_cli::Assert::command(&[ "cargo", "run", "--bin=rustfmt", "--", "--write-mode=diff", - "src/bin/main.rs", + file_name, ]).succeeds() .unwrap(); } -- cgit 1.4.1-3-g733a5 From a9553654592fa9508c4a42b9c47a04fc3b4357d8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 13:24:05 +0900 Subject: Use a glob import for import utils --- src/items.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 80e837ed904..1924d881127 100644 --- a/src/items.rs +++ b/src/items.rs @@ -32,11 +32,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; use types::TraitTyParamBounds; -use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_auto, - format_constness, format_defaultness, format_mutability, format_unsafety, - format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, - last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, - stmt_expr, trimmed_last_line_width}; +use utils::*; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; -- cgit 1.4.1-3-g733a5 From 82d8dd2f4bdcd61b08c6952e4e6ebdf4db70b299 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 13:59:03 +0900 Subject: Factor out a formatting routine for empty struct and tuple --- src/items.rs | 35 +++++++++++++++++++++++++++++++++++ src/utils.rs | 10 ++++++++++ 2 files changed, 45 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1924d881127..e6351a3aa15 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1242,6 +1242,41 @@ fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> By } } +// Format tuple or struct without any fields. We need to make sure that the comments +// inside the delimiters are preserved. +fn format_empty_struct_or_tuple( + context: &RewriteContext, + span: Span, + offset: Indent, + result: &mut String, + opener: &str, + closer: &str, +) { + // 3 = " {}" or "();" + let used_width = last_line_used_width(&result, offset.width()) + 3; + if used_width > context.config.max_width() { + result.push_str(&offset.to_string_with_newline(context.config)) + } + result.push_str(opener); + match rewrite_missing_comment(span, Shape::indented(offset, context.config), context) { + Some(ref s) if s.is_empty() => (), + Some(ref s) => { + if !is_single_line(s) || first_line_contains_single_line_comment(s) { + let nested_indent_str = offset + .block_indent(context.config) + .to_string_with_newline(context.config); + result.push_str(&nested_indent_str); + } + result.push_str(s); + if last_line_contains_single_line_comment(s) { + result.push_str(&offset.to_string_with_newline(context.config)); + } + } + None => result.push_str(context.snippet(span)), + } + result.push_str(closer); +} + fn format_tuple_struct( context: &RewriteContext, struct_parts: &StructParts, diff --git a/src/utils.rs b/src/utils.rs index 2493c9a5c74..9ed1df35a42 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -133,6 +133,16 @@ pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { filter_attributes(attrs, ast::AttrStyle::Outer) } +#[inline] +pub fn is_single_line(s: &str) -> bool { + s.chars().find(|&c| c == '\n').is_none() +} + +#[inline] +pub fn first_line_contains_single_line_comment(s: &str) -> bool { + s.lines().next().map_or(false, |l| l.contains("//")) +} + #[inline] pub fn last_line_contains_single_line_comment(s: &str) -> bool { s.lines().last().map_or(false, |l| l.contains("//")) -- cgit 1.4.1-3-g733a5 From fb0c6affa5b76001af2ea04c41c2204f6724fc63 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 13:59:54 +0900 Subject: Use format_empty_struct_or_tuple --- src/items.rs | 44 +++++++------------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e6351a3aa15..341cce8a71f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1190,18 +1190,8 @@ pub fn format_struct_struct( } if fields.is_empty() { - let snippet = context.snippet(mk_sp(body_lo, span.hi() - BytePos(1))); - if snippet.trim().is_empty() { - // `struct S {}` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - // fix indent - result.push_str(snippet.trim_right()); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push_str(snippet); - } - result.push('}'); + let inner_span = mk_sp(body_lo, span.hi() - BytePos(1)); + format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "", "}"); return Some(result); } @@ -1340,31 +1330,11 @@ fn format_tuple_struct( }; if fields.is_empty() { - // 3 = `();` - let used_width = last_line_used_width(&result, offset.width()) + 3; - if used_width > context.config.max_width() { - result.push('\n'); - result.push_str(&offset - .block_indent(context.config) - .to_string(context.config)) - } - result.push('('); - let snippet = context.snippet(mk_sp( - body_lo, - context - .snippet_provider - .span_before(mk_sp(body_lo, span.hi()), ")"), - )); - if snippet.is_empty() { - // `struct S ()` - } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') { - result.push_str(snippet.trim_right()); - result.push('\n'); - result.push_str(&offset.to_string(context.config)); - } else { - result.push_str(snippet); - } - result.push(')'); + let body_hi = context + .snippet_provider + .span_before(mk_sp(body_lo, span.hi()), ")"); + let inner_span = mk_sp(body_lo, body_hi); + format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")"); } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; let fields = &fields.iter().collect::>(); -- cgit 1.4.1-3-g733a5 From e512c19ed5451a4f0e9f17eac488b1414c1c6aed Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 14:03:14 +0900 Subject: Use format_empty_struct_or_tuple over format_missing_no_indent Closes #2594. --- src/items.rs | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 341cce8a71f..c2a2d0d2180 100644 --- a/src/items.rs +++ b/src/items.rs @@ -453,35 +453,39 @@ impl<'a> FmtVisitor<'a> { self.last_pos = body_start; - self.block_indent = self.block_indent.block_indent(self.config); - let variant_list = self.format_variant_list(enum_def, body_start, span.hi() - BytePos(1)); - match variant_list { - Some(ref body_str) => self.push_str(body_str), - None => self.format_missing_no_indent(span.hi() - BytePos(1)), - } - self.block_indent = self.block_indent.block_unindent(self.config); - - if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) { - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); + match self.format_variant_list(enum_def, body_start, span.hi()) { + Some(ref s) if enum_def.variants.is_empty() => self.push_str(s), + rw => { + self.push_rewrite(mk_sp(body_start, span.hi()), rw); + self.block_indent = self.block_indent.block_unindent(self.config); + } } - self.push_str("}"); - self.last_pos = span.hi(); } // Format the body of an enum definition fn format_variant_list( - &self, + &mut self, enum_def: &ast::EnumDef, body_lo: BytePos, body_hi: BytePos, ) -> Option { if enum_def.variants.is_empty() { - return None; + let mut buffer = String::with_capacity(128); + // 1 = "}" + let span = mk_sp(body_lo, body_hi - BytePos(1)); + format_empty_struct_or_tuple( + &self.get_context(), + span, + self.block_indent, + &mut buffer, + "", + "}", + ); + return Some(buffer); } let mut result = String::with_capacity(1024); - let indentation = self.block_indent.to_string_with_newline(self.config); - result.push_str(&indentation); + let original_offset = self.block_indent; + self.block_indent = self.block_indent.block_indent(self.config); let itemize_list_with = |one_line_width: usize| { itemize_list( @@ -526,7 +530,8 @@ impl<'a> FmtVisitor<'a> { let list = write_list(&items, &fmt)?; result.push_str(&list); - result.push('\n'); + result.push_str(&original_offset.to_string_with_newline(self.config)); + result.push('}'); Some(result) } -- cgit 1.4.1-3-g733a5 From 43890cff6b8e1a93d8d6c4189af7b0fbeb70eab7 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 15:09:54 +0900 Subject: Preserve trailing comma inside array Closes #2652. --- src/expr.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index cd8bfa8a72b..7ca74c6ef0e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -70,7 +70,7 @@ pub fn format_expr( expr.span, context, shape, - None, + choose_separator_tactic(context, expr.span), None, ), ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), @@ -1336,6 +1336,18 @@ const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ ("debug_assert_ne!", 2), ]; +fn choose_separator_tactic(context: &RewriteContext, span: Span) -> Option { + if context.inside_macro() { + if span_ends_with_comma(context, span) { + Some(SeparatorTactic::Always) + } else { + Some(SeparatorTactic::Never) + } + } else { + None + } +} + pub fn rewrite_call( context: &RewriteContext, callee: &str, @@ -1350,15 +1362,7 @@ pub fn rewrite_call( shape, span, context.config.width_heuristics().fn_call_width, - if context.inside_macro() { - if span_ends_with_comma(context, span) { - Some(SeparatorTactic::Always) - } else { - Some(SeparatorTactic::Never) - } - } else { - None - }, + choose_separator_tactic(context, span), ) } @@ -1436,11 +1440,14 @@ pub fn is_nested_call(expr: &ast::Expr) -> bool { pub fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { let mut result: bool = Default::default(); let mut prev_char: char = Default::default(); + let closing_delimiters = &[')', '}', ']']; for (kind, c) in CharClasses::new(context.snippet(span).chars()) { match c { _ if kind.is_comment() || c.is_whitespace() => continue, - ')' | '}' => result = result && prev_char != ')' && prev_char != '}', + c if closing_delimiters.contains(&c) => { + result &= !closing_delimiters.contains(&prev_char); + } ',' => result = true, _ => result = false, } -- cgit 1.4.1-3-g733a5 From a159b64b0aea1b09ec0d677acebd3f666426e6bc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 16:04:09 +0900 Subject: Preserve comments between attribute and use item --- src/imports.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index f7286fc3b43..9fd844a2c35 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -15,6 +15,7 @@ use syntax::ast::{self, UseTreeKind}; use syntax::codemap::{self, BytePos, Span, DUMMY_SP}; use codemap::SpanUtils; +use comment::combine_strs_with_missing_comments; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; @@ -219,26 +220,26 @@ impl fmt::Display for UseTree { impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { - let mut result = String::with_capacity(256); - if let Some(ref attrs) = self.attrs { - result.push_str(&attrs.rewrite(context, shape)?); - if !result.is_empty() { - result.push_str(&shape.indent.to_string_with_newline(context.config)); - } - } - let vis = self.visibility .as_ref() .map_or(Cow::from(""), |vis| ::utils::format_visibility(&vis)); - result.push_str(&self.rewrite(context, shape.offset_left(vis.len())?) + let use_str = self.rewrite(context, shape.offset_left(vis.len())?) .map(|s| { if s.is_empty() { s.to_owned() } else { format!("{}use {};", vis, s) } - })?); - Some(result) + })?; + if let Some(ref attrs) = self.attrs { + let attr_str = attrs.rewrite(context, shape)?; + let lo = attrs.last().as_ref()?.span().hi(); + let hi = self.span.lo(); + let span = mk_sp(lo, hi); + combine_strs_with_missing_comments(context, &attr_str, &use_str, span, shape, false) + } else { + Some(use_str) + } } // FIXME: Use correct span? -- cgit 1.4.1-3-g733a5 From 0c5631e4c1032bf8bc1a5b9e6c1517e9f261a58f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 28 Apr 2018 16:05:02 +0900 Subject: Use correct span for UseTree --- src/imports.rs | 13 ++++++++++++- src/reorder.rs | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9fd844a2c35..8963f62748b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -119,6 +119,17 @@ impl PartialEq for UseTree { } impl Eq for UseTree {} +impl Spanned for UseTree { + fn span(&self) -> Span { + let lo = if let Some(ref attrs) = self.attrs { + attrs.iter().next().map_or(self.span.lo(), |a| a.span.lo()) + } else { + self.span.lo() + }; + mk_sp(lo, self.span.hi()) + } +} + impl UseSegment { // Clone a version of self with any top-level alias removed. fn remove_alias(&self) -> UseSegment { @@ -268,7 +279,7 @@ impl UseTree { use_tree, None, Some(item.vis.clone()), - Some(item.span().lo()), + Some(item.span.lo()), if item.attrs.is_empty() { None } else { diff --git a/src/reorder.rs b/src/reorder.rs index 7d7c1ff8d32..027b64e8317 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -128,8 +128,8 @@ fn rewrite_reorderable_items( cloned.iter(), "", ";", - |item| item.span.lo(), - |item| item.span.hi(), + |item| item.span().lo(), + |item| item.span().hi(), |_item| Some("".to_owned()), span.lo(), span.hi(), -- cgit 1.4.1-3-g733a5 From fb9a5add9b651d64ecf365ade61d83d76fd6b307 Mon Sep 17 00:00:00 2001 From: Ryan Leung Date: Sat, 28 Apr 2018 15:08:58 +0800 Subject: add rustc_target to dependencies (#2660) --- Cargo.lock | 64 +++++++++++++++++++++++++++++++++++++----------------------- Cargo.toml | 3 ++- src/items.rs | 3 ++- src/lib.rs | 1 + src/utils.rs | 3 ++- 5 files changed, 47 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 3d1d1cb200b..7ab6d640066 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -394,16 +394,17 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -411,53 +412,66 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_target" +version = "113.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-serialize" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -484,7 +498,8 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -833,12 +848,13 @@ dependencies = [ "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0256e318ad99c467d24bd7188f2d4a3028360621bb92d769b4b65fc44717d514" -"checksum rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83430df7f76ea85c1f70fe145041576eee8fd5d77053bf426df24b480918d185" -"checksum rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b03f874277103039816f6467b1ff30a81b1d6a29d4de6efccefe4c488f6535a" -"checksum rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2e47cf949f06b0c7ab7566c2f69d49f28cb3ecf1bb8bf0bda48b1ba5b7945ae" -"checksum rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "625e6fb41fde299082cda3bceb08f81c9ba56b14a2ec737b4366f9c3c9be07d8" -"checksum rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474a23ef1a1245ae02c5fd6a1e9a0725ce6fd25ca2294703c03bddce041f867b" +"checksum rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a01334797c5c4cf56cc40bb9636d7b4c4a076665b9b9b7f100fd666cf0a02ffc" +"checksum rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03d6f8f7da0de905f6ef80dc14dce3bbc372430622b6aeb421cf13190bc70e8a" +"checksum rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dfd6183804a685c48601651d8c8c7b0daa8f83b0b5e24edfbcb6a0337085127" +"checksum rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f223157f51bf0e0621bef099de862468892ee4c4b83056f48f63e1bc00ccb72" +"checksum rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2104a55a87d65cba8a845656f1f19a35da52af403863cd2a4bd5876ba522d879" +"checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323" +"checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" diff --git a/Cargo.toml b/Cargo.toml index 4074f67b875..75416b54d82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,8 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-syntax = "110.0.0" +rustc-ap-rustc_target = "113.0.0" +rustc-ap-syntax = "113.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/items.rs b/src/items.rs index 80e837ed904..f68fb890961 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,9 +15,10 @@ use std::cmp::{min, Ordering}; use config::lists::*; use regex::Regex; +use rustc_target::spec::abi; use syntax::codemap::{self, BytePos, Span}; use syntax::visit; -use syntax::{abi, ast, ptr, symbol}; +use syntax::{ast, ptr, symbol}; use codemap::{LineRangeUtils, SpanUtils}; use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, diff --git a/src/lib.rs b/src/lib.rs index b272402b20f..f43056df408 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ extern crate lazy_static; #[macro_use] extern crate log; extern crate regex; +extern crate rustc_target; extern crate serde; #[macro_use] extern crate serde_derive; diff --git a/src/utils.rs b/src/utils.rs index 2493c9a5c74..115aee7dd2b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,10 +10,11 @@ use std::borrow::Cow; +use rustc_target::spec::abi; use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, Visibility, VisibilityKind}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; -use syntax::{abi, ptr}; +use syntax::ptr; use config::Color; use rewrite::RewriteContext; -- cgit 1.4.1-3-g733a5 From c9cef5db170bc0ac2eb0cc42dff2013a4ad3d0c5 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 29 Apr 2018 19:57:49 +0800 Subject: import_indent to Block --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index 23897f3cc32..a4c0e1630a8 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -62,7 +62,7 @@ create_config! { where_single_line: bool, false, false, "Force where clauses to be on a single line"; // Imports - imports_indent: IndentStyle, IndentStyle::Visual, false, "Indent of imports"; + imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; merge_imports: bool, false, false, "Merge imports"; -- cgit 1.4.1-3-g733a5 From f7415bcea235cab84b775d59dab3b9a0cb68dd01 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 29 Apr 2018 20:22:48 +0800 Subject: update self format --- Configurations.md | 44 ++++++++++++++++++++++++++------------------ src/bin/main.rs | 6 ++++-- src/chains.rs | 6 ++++-- src/expr.rs | 20 +++++++++++++------- src/items.rs | 24 +++++++++++++++--------- src/macros.rs | 6 ++++-- src/matches.rs | 12 ++++++++---- src/overflow.rs | 4 +++- src/patterns.rs | 11 +++++++---- src/types.rs | 11 +++++++---- src/utils.rs | 6 ++++-- src/visitor.rs | 8 +++++--- 12 files changed, 100 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index cd0fdb23def..110925f8e02 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1042,8 +1042,10 @@ Item layout inside a imports block ```rust use foo::{xxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz}; -use foo::{aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd, - eeeeeeeeeeeeeeeeee, ffffffffffffffffff}; +use foo::{ + aaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbb, cccccccccccccccccc, dddddddddddddddddd, + eeeeeeeeeeeeeeeeee, ffffffffffffffffff, +}; ``` #### `"Horizontal"`: @@ -1061,27 +1063,33 @@ use foo::{aaa, bbb, ccc, ddd, eee, fff}; ```rust use foo::{xxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzz}; -use foo::{aaaaaaaaaaaaaaaaaa, - bbbbbbbbbbbbbbbbbb, - cccccccccccccccccc, - dddddddddddddddddd, - eeeeeeeeeeeeeeeeee, - ffffffffffffffffff}; +use foo::{ + aaaaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbbbb, + cccccccccccccccccc, + dddddddddddddddddd, + eeeeeeeeeeeeeeeeee, + ffffffffffffffffff, +}; ``` #### `"Vertical"`: ```rust -use foo::{xxx, - yyy, - zzz}; +use foo::{ + xxx, + yyy, + zzz, +}; -use foo::{aaa, - bbb, - ccc, - ddd, - eee, - fff}; +use foo::{ + aaa, + bbb, + ccc, + ddd, + eee, + fff, +}; ``` ## `merge_imports` @@ -2036,7 +2044,7 @@ fn foo() { ## `required_version` -Require a specific version of rustfmt. If you want to make sure that the +Require a specific version of rustfmt. If you want to make sure that the specific version of rustfmt is used in your CI, use this option. - **Default value**: `CARGO_PKG_VERSION` diff --git a/src/bin/main.rs b/src/bin/main.rs index 0ddf2f8c3df..46e18864d30 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -24,8 +24,10 @@ use failure::err_msg; use getopts::{Matches, Options}; -use rustfmt::{emit_post_matter, emit_pre_matter, load_config, CliOptions, Config, FmtResult, - WriteMode, WRITE_MODE_LIST}; +use rustfmt::{ + emit_post_matter, emit_pre_matter, load_config, CliOptions, Config, FmtResult, WriteMode, + WRITE_MODE_LIST, +}; use rustfmt::{format_and_emit_report, FileName, Input, Summary}; fn main() { diff --git a/src/chains.rs b/src/chains.rs index 94099002f73..2f05f4a2c46 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -70,8 +70,10 @@ use expr::rewrite_call; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, - trimmed_last_line_width, wrap_str}; +use utils::{ + first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, + wrap_str, +}; use std::borrow::Cow; use std::cmp::min; diff --git a/src/expr.rs b/src/expr.rs index cd8bfa8a72b..a048b1896c8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -19,11 +19,15 @@ use syntax::{ast, ptr}; use chains::rewrite_chain; use closures; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented}; +use comment::{ + combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, + rewrite_missing_comment, CharClasses, FindUncommented, +}; use config::{Config, ControlBraceStyle, IndentStyle}; -use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, - struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator}; +use lists::{ + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, +}; use macros::{rewrite_macro, MacroArg, MacroPosition}; use matches::rewrite_match; use overflow; @@ -33,9 +37,11 @@ use shape::{Indent, Shape}; use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; -use utils::{colon_spaces, contains_skip, count_newlines, first_line_width, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead, - ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str}; +use utils::{ + colon_spaces, contains_skip, count_newlines, first_line_width, inner_attributes, + last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead, + ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str, +}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; diff --git a/src/items.rs b/src/items.rs index f68fb890961..d6985c5b554 100644 --- a/src/items.rs +++ b/src/items.rs @@ -21,11 +21,15 @@ use syntax::visit; use syntax::{ast, ptr, symbol}; use codemap::{LineRangeUtils, SpanUtils}; -use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented}; +use comment::{ + combine_strs_with_missing_comments, contains_comment, recover_comment_removed, + recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented, +}; use config::{BraceStyle, Config, Density, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, - rewrite_assign_rhs_with, ExprType, RhsTactics}; +use expr::{ + format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, + ExprType, RhsTactics, +}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; @@ -33,11 +37,13 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; use types::TraitTyParamBounds; -use utils::{colon_spaces, contains_skip, first_line_width, format_abi, format_auto, - format_constness, format_defaultness, format_mutability, format_unsafety, - format_visibility, is_attributes_extendable, last_line_contains_single_line_comment, - last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, - stmt_expr, trimmed_last_line_width}; +use utils::{ + colon_spaces, contains_skip, first_line_width, format_abi, format_auto, format_constness, + format_defaultness, format_mutability, format_unsafety, format_visibility, + is_attributes_extendable, last_line_contains_single_line_comment, last_line_used_width, + last_line_width, mk_sp, semicolon_for_expr, starts_with_newline, stmt_expr, + trimmed_last_line_width, +}; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; diff --git a/src/macros.rs b/src/macros.rs index a76520c8fe6..1fc150e1256 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,8 +33,10 @@ use syntax::util::ThinVec; use syntax::{ast, ptr}; use codemap::SpanUtils; -use comment::{contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, - FullCodeCharKind, LineClasses}; +use comment::{ + contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, FullCodeCharKind, + LineClasses, +}; use expr::rewrite_array; use lists::{itemize_list, write_list, ListFormatting}; use overflow; diff --git a/src/matches.rs b/src/matches.rs index 65bf7f579d4..bc092b1a718 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -19,14 +19,18 @@ use syntax::{ast, ptr}; use codemap::SpanUtils; use comment::combine_strs_with_missing_comments; use config::{Config, ControlBraceStyle, IndentStyle}; -use expr::{format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, - rewrite_multiple_patterns, ExprType, RhsTactics, ToExpr}; +use expr::{ + format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, + rewrite_multiple_patterns, ExprType, RhsTactics, ToExpr, +}; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, - mk_sp, ptr_vec_to_ref_vec, trimmed_last_line_width}; +use utils::{ + contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, + ptr_vec_to_ref_vec, trimmed_last_line_width, +}; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. struct ArmWrapper<'a> { diff --git a/src/overflow.rs b/src/overflow.rs index cc68f3e1ec2..b42c6be90ca 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -23,7 +23,9 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListIte use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp, paren_overhead}; +use utils::{ + count_newlines, extra_offset, first_line_width, last_line_width, mk_sp, paren_overhead, +}; use std::cmp::min; diff --git a/src/patterns.rs b/src/patterns.rs index 243b85e4267..b4865ad329e 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,10 +15,13 @@ use syntax::ptr; use codemap::SpanUtils; use comment::FindUncommented; -use expr::{can_be_overflowed_expr, rewrite_pair, rewrite_unary_prefix, wrap_struct_field, - PairParts}; -use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list}; +use expr::{ + can_be_overflowed_expr, rewrite_pair, rewrite_unary_prefix, wrap_struct_field, PairParts, +}; +use lists::{ + itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, + write_list, +}; use macros::{rewrite_macro, MacroPosition}; use overflow; use rewrite::{Rewrite, RewriteContext}; diff --git a/src/types.rs b/src/types.rs index 4bde91f67f1..149769c5df7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,16 +18,19 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, - ToExpr}; +use expr::{ + rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, ToExpr, +}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, - last_line_width, mk_sp}; +use utils::{ + colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_width, + mk_sp, +}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum PathContext { diff --git a/src/utils.rs b/src/utils.rs index 115aee7dd2b..78efbf1159d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -11,8 +11,10 @@ use std::borrow::Cow; use rustc_target::spec::abi; -use syntax::ast::{self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, - NestedMetaItemKind, Path, Visibility, VisibilityKind}; +use syntax::ast::{ + self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, + Visibility, VisibilityKind, +}; use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use syntax::ptr; diff --git a/src/visitor.rs b/src/visitor.rs index d15d2ad7aef..05f2e7e5cc1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,9 +17,11 @@ use attr::*; use codemap::{LineRangeUtils, SpanUtils}; use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; use config::{BraceStyle, Config}; -use items::{format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, - rewrite_type_alias, FnSig, StaticParts, StructParts}; +use items::{ + format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, + rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, + rewrite_type_alias, FnSig, StaticParts, StructParts, +}; use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; -- cgit 1.4.1-3-g733a5 From be3be582cc55eed27c3baf0f976dbc3f11209b10 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 29 Apr 2018 21:40:37 +0800 Subject: set stdin default config path to curr --- src/bin/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 0ddf2f8c3df..3cb34fb0a42 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -18,7 +18,7 @@ extern crate rustfmt_nightly as rustfmt; use std::env; use std::fs::File; use std::io::{self, stdout, Read, Write}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use failure::err_msg; @@ -182,7 +182,7 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { Operation::Stdin { input } => { // try to read config from local directory let options = CliOptions::from_matches(&matches)?; - let (mut config, _) = load_config(None, Some(&options))?; + let (mut config, _) = load_config(Some(Path::new(".")), Some(&options))?; // write_mode is always Plain for Stdin. config.set().write_mode(WriteMode::Plain); -- cgit 1.4.1-3-g733a5 From 61a401ae5147312daf1ccbe92156e47d3580e7cb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 30 Apr 2018 15:49:32 +0900 Subject: Use correct one line width for list attribute Closes #2647. --- src/attr.rs | 3 ++- tests/source/attrib.rs | 4 ++++ tests/target/attrib.rs | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index e17b89e5c9e..83de61c5e25 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -247,7 +247,8 @@ impl Rewrite for ast::MetaItem { config: context.config, }; let item_str = write_list(&item_vec, &fmt)?; - let one_line_budget = shape.offset_left(name.len())?.sub_width(2)?.width; + // 3 = "()" and "]" + let one_line_budget = shape.offset_left(name.len())?.sub_width(3)?.width; if context.config.indent_style() == IndentStyle::Visual || (!item_str.contains('\n') && item_str.len() <= one_line_budget) { diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 552dd2b9442..d5c244a9bf8 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -157,3 +157,7 @@ pub struct HP(pub u8); // Long `#[doc = "..."]` struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } + +// #2647 +#[cfg(feature = "this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")] +pub fn foo() {} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 13ba8bd64db..45dc4ea8ba9 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -165,3 +165,9 @@ struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32, } + +// #2647 +#[cfg( + feature = "this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +)] +pub fn foo() {} -- cgit 1.4.1-3-g733a5 From 48e193c7f65b32e2cf2ed2181ba87bd2f8b95bfb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 30 Apr 2018 16:13:51 +0900 Subject: Factor out visit_impl_items --- src/items.rs | 95 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 0e6d17119bc..1ac8e2553e8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -578,6 +578,55 @@ impl<'a> FmtVisitor<'a> { combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) } + + fn visit_impl_items(&mut self, items: &[ast::ImplItem]) { + if self.get_context().config.reorder_impl_items() { + // Create visitor for each items, then reorder them. + let mut buffer = vec![]; + for item in items { + self.visit_impl_item(item); + buffer.push((self.buffer.clone(), item.clone())); + self.buffer.clear(); + } + // type -> const -> macro -> method + use ast::ImplItemKind::*; + fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { + match (a, b) { + (Type(..), Type(..)) | (Const(..), Const(..)) => false, + _ => true, + } + } + + buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { + (Type(..), _) => Ordering::Less, + (_, Type(..)) => Ordering::Greater, + (Const(..), _) => Ordering::Less, + (_, Const(..)) => Ordering::Greater, + (Macro(..), _) => Ordering::Less, + (_, Macro(..)) => Ordering::Greater, + _ => Ordering::Less, + }); + let mut prev_kind = None; + for (buf, item) in buffer { + // Make sure that there are at least a single empty line between + // different impl items. + if prev_kind + .as_ref() + .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node)) + { + self.push_str("\n"); + } + let indent_str = self.block_indent.to_string_with_newline(self.config); + self.push_str(&indent_str); + self.push_str(buf.trim()); + prev_kind = Some(item.node.clone()); + } + } else { + for item in items { + self.visit_impl_item(item); + } + } + } } pub fn format_impl( @@ -672,51 +721,7 @@ pub fn format_impl( visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); - if context.config.reorder_impl_items() { - // Create visitor for each items, then reorder them. - let mut buffer = vec![]; - for item in items { - visitor.visit_impl_item(item); - buffer.push((visitor.buffer.clone(), item.clone())); - visitor.buffer.clear(); - } - // type -> const -> macro -> method - use ast::ImplItemKind::*; - fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { - match (a, b) { - (Type(..), Type(..)) | (Const(..), Const(..)) => false, - _ => true, - } - } - - buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { - (Type(..), _) => Ordering::Less, - (_, Type(..)) => Ordering::Greater, - (Const(..), _) => Ordering::Less, - (_, Const(..)) => Ordering::Greater, - (Macro(..), _) => Ordering::Less, - (_, Macro(..)) => Ordering::Greater, - _ => Ordering::Less, - }); - let mut prev_kind = None; - for (buf, item) in buffer { - // Make sure that there are at least a single empty line between - // different impl items. - if prev_kind - .as_ref() - .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node)) - { - visitor.push_str("\n"); - } - visitor.push_str(&item_indent.to_string_with_newline(context.config)); - visitor.push_str(buf.trim()); - prev_kind = Some(item.node.clone()); - } - } else { - for item in items { - visitor.visit_impl_item(item); - } - } + visitor.visit_impl_items(items); visitor.format_missing(item.span.hi() - BytePos(1)); -- cgit 1.4.1-3-g733a5 From 37c216c50f1f049407d5dc656de39ea1bf5ce299 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 30 Apr 2018 16:19:52 +0900 Subject: Use bytepos to compare impl items --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1ac8e2553e8..08bdfe0295f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -604,7 +604,7 @@ impl<'a> FmtVisitor<'a> { (_, Const(..)) => Ordering::Greater, (Macro(..), _) => Ordering::Less, (_, Macro(..)) => Ordering::Greater, - _ => Ordering::Less, + _ => a.span.lo().cmp(&b.span.lo()), }); let mut prev_kind = None; for (buf, item) in buffer { -- cgit 1.4.1-3-g733a5 From 43df7dcb0e9aaf33ec041a079f3e9117b7f592cb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 30 Apr 2018 16:24:01 +0900 Subject: Run cargo fmt with reorder_impl_items set to true --- src/comment.rs | 1 + src/config/options.rs | 1 + src/imports.rs | 3 +++ src/test/mod.rs | 1 + 4 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 378fe40d569..4a0abc2b099 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1139,6 +1139,7 @@ impl<'a> CommentReducer<'a> { impl<'a> Iterator for CommentReducer<'a> { type Item = char; + fn next(&mut self) -> Option { loop { let mut c = self.iter.next()?; diff --git a/src/config/options.rs b/src/config/options.rs index 9721815eeee..7bd3a51a9b4 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -239,6 +239,7 @@ impl WidthHeuristics { single_line_if_else_max_width: 0, } } + // scale the default WidthHeuristics according to max_width pub fn scaled(max_width: usize) -> WidthHeuristics { let mut max_width_ratio: f32 = max_width as f32 / 100.0; // 100 is the default width -> default ratio is 1 diff --git a/src/imports.rs b/src/imports.rs index 8963f62748b..669cf795bc7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -799,9 +799,11 @@ mod test { fn bump(&mut self) { self.input.next().unwrap(); } + fn eat(&mut self, c: char) { assert!(self.input.next().unwrap() == c); } + fn push_segment( result: &mut Vec, buf: &mut String, @@ -825,6 +827,7 @@ mod test { } } } + fn parse_in_list(&mut self) -> UseTree { let mut result = vec![]; let mut buf = String::new(); diff --git a/src/test/mod.rs b/src/test/mod.rs index cd746a6486b..4a02bf73e1a 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -568,6 +568,7 @@ struct CharsIgnoreNewlineRepr<'a>(Peekable>); impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { type Item = char; + fn next(&mut self) -> Option { self.0.next().map(|c| { if c == '\r' { -- cgit 1.4.1-3-g733a5 From d8982e5efe8fda1d6f64e88a67da2f05b6af225e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 May 2018 10:18:14 +1200 Subject: Suppress warning about unused attribute --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index f43056df408..ec8646acc1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ #![feature(decl_macro)] // FIXME(cramertj) remove after match_default_bindings merges #![allow(stable_features)] +#![allow(unused_attributes)] #![feature(match_default_bindings)] #![feature(type_ascription)] #![feature(unicode_internals)] -- cgit 1.4.1-3-g733a5 From 9b36156020f3c4eaad41268ae7f318954e4ccea1 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 2 May 2018 10:36:02 +0200 Subject: Do not scale WidthHeuristics when max_width less than 100 --- src/config/options.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index 7bd3a51a9b4..c350aac8d96 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -242,8 +242,14 @@ impl WidthHeuristics { // scale the default WidthHeuristics according to max_width pub fn scaled(max_width: usize) -> WidthHeuristics { - let mut max_width_ratio: f32 = max_width as f32 / 100.0; // 100 is the default width -> default ratio is 1 - max_width_ratio = (max_width_ratio * 10.0).round() / 10.0; // round to the closest 0.1 + const DEFAULT_MAX_WIDTH: usize = 100; + let max_width_ratio = if max_width > DEFAULT_MAX_WIDTH { + let ratio = max_width as f32 / DEFAULT_MAX_WIDTH as f32; + // round to the closest 0.1 + (ratio * 10.0).round() / 10.0 + } else { + 1.0 + }; WidthHeuristics { fn_call_width: (60.0 * max_width_ratio).round() as usize, struct_lit_width: (18.0 * max_width_ratio).round() as usize, -- cgit 1.4.1-3-g733a5 From 48df8f8dc07e40eddc2ce5c3c6a9304d0bb9ac10 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Wed, 2 May 2018 11:38:23 +0200 Subject: Add test for width heuristics --- src/config/config_type.rs | 4 ++-- tests/source/width-heuristics.rs | 28 ++++++++++++++++++++++++++++ tests/target/width-heuristics.rs | 24 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/source/width-heuristics.rs create mode 100644 tests/target/width-heuristics.rs (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 3b9ca90350c..06c05bb9355 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -130,7 +130,7 @@ macro_rules! create_config { pub fn $i(&mut self, value: $ty) { (self.0).$i.2 = value; match stringify!($i) { - "use_small_heuristics" => self.0.set_heuristics(), + "max_width" | "use_small_heuristics" => self.0.set_heuristics(), "license_template_path" => self.0.set_license_template(), &_ => (), } @@ -292,7 +292,7 @@ macro_rules! create_config { } match key { - "use_small_heuristics" => self.set_heuristics(), + "max_width" | "use_small_heuristics" => self.set_heuristics(), "license_template_path" => self.set_license_template(), &_ => (), } diff --git a/tests/source/width-heuristics.rs b/tests/source/width-heuristics.rs new file mode 100644 index 00000000000..a591218b4cc --- /dev/null +++ b/tests/source/width-heuristics.rs @@ -0,0 +1,28 @@ +// rustfmt-max_width: 120 + +// elems on multiple lines for max_width 100, but same line for max_width 120 +fn foo(e: Enum) { + match e { + Enum::Var { + elem1, + elem2, + elem3, + } => { + return; + } + } +} + +// elems not on same line for either max_width 100 or 120 +fn bar(e: Enum) { + match e { + Enum::Var { + elem1, + elem2, + elem3, + elem4, + } => { + return; + } + } +} diff --git a/tests/target/width-heuristics.rs b/tests/target/width-heuristics.rs new file mode 100644 index 00000000000..e177a2152e8 --- /dev/null +++ b/tests/target/width-heuristics.rs @@ -0,0 +1,24 @@ +// rustfmt-max_width: 120 + +// elems on multiple lines for max_width 100, but same line for max_width 120 +fn foo(e: Enum) { + match e { + Enum::Var { elem1, elem2, elem3 } => { + return; + } + } +} + +// elems not on same line for either max_width 100 or 120 +fn bar(e: Enum) { + match e { + Enum::Var { + elem1, + elem2, + elem3, + elem4, + } => { + return; + } + } +} -- cgit 1.4.1-3-g733a5 From 4a4916920fed8221251d1942d01f17ce5f5a0fa0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 3 May 2018 11:14:01 +1200 Subject: Make test temp files in the Cargo target directory, if known --- src/test/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 4a02bf73e1a..ba0c75a1834 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -859,23 +859,27 @@ fn configuration_snippet_tests() { } struct TempFile { - file_name: &'static str, + path: PathBuf, } fn make_temp_file(file_name: &'static str) -> TempFile { + use std::env::var; use std::fs::File; - let mut file = File::create(file_name).expect("Couldn't create temp file"); + let target_dir = var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".to_owned()); + let path = Path::new(&target_dir).join(file_name); + + let mut file = File::create(&path).expect("Couldn't create temp file"); let content = "fn main() {}\n"; file.write_all(content.as_bytes()) .expect("Couldn't write temp file"); - TempFile { file_name } + TempFile { path } } impl Drop for TempFile { fn drop(&mut self) { use std::fs::remove_file; - remove_file(self.file_name).expect("Couldn't delete temp file"); + remove_file(&self.path).expect("Couldn't delete temp file"); } } -- cgit 1.4.1-3-g733a5 From 8c8676cd30009a028fc8ea2cceea563abc451b53 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Wed, 2 May 2018 22:11:50 +0800 Subject: fix merge_mix --- src/imports.rs | 21 +++++++++++---------- tests/source/configs/imports_layout/merge_mixed.rs | 6 ++++++ tests/target/configs/imports_layout/merge_mixed.rs | 7 +++++++ tests/target/imports.rs | 20 +++++--------------- 4 files changed, 29 insertions(+), 25 deletions(-) create mode 100644 tests/source/configs/imports_layout/merge_mixed.rs create mode 100644 tests/target/configs/imports_layout/merge_mixed.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 669cf795bc7..05b10519d45 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -693,19 +693,20 @@ fn rewrite_nested_use_tree( _ => false, }) }); - let (tactic, remaining_width) = if has_nested_list { - (DefinitiveListTactic::Vertical, 0) + + let remaining_width = if has_nested_list { + 0 } else { - let remaining_width = shape.width.checked_sub(2).unwrap_or(0); - let tactic = definitive_tactic( - &list_items, - context.config.imports_layout(), - Separator::Comma, - remaining_width, - ); - (tactic, remaining_width) + shape.width.checked_sub(2).unwrap_or(0) }; + let tactic = definitive_tactic( + &list_items, + context.config.imports_layout(), + Separator::Comma, + remaining_width, + ); + let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; let fmt = ListFormatting { diff --git a/tests/source/configs/imports_layout/merge_mixed.rs b/tests/source/configs/imports_layout/merge_mixed.rs new file mode 100644 index 00000000000..bd09079a595 --- /dev/null +++ b/tests/source/configs/imports_layout/merge_mixed.rs @@ -0,0 +1,6 @@ +// rustfmt-imports_indent: Block +// rustfmt-merge_imports: true +// rustfmt-imports_layout: Mixed + +use std::{fmt, io, str}; +use std::str::FromStr; diff --git a/tests/target/configs/imports_layout/merge_mixed.rs b/tests/target/configs/imports_layout/merge_mixed.rs new file mode 100644 index 00000000000..d67979840d0 --- /dev/null +++ b/tests/target/configs/imports_layout/merge_mixed.rs @@ -0,0 +1,7 @@ +// rustfmt-imports_indent: Block +// rustfmt-merge_imports: true +// rustfmt-imports_layout: Mixed + +use std::{ + fmt, io, str::{self, FromStr}, +}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 2e195520a06..b3d78e609fe 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -80,18 +80,12 @@ use self::unix::{}; // nested imports use foo::{ - a, - b, + a, b, bar::{ - baz, - foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}, - qux, - xxxxxxxxxxx, - yyyyyyyyyyyyy, - zzzzzzzzzzzzzzzz, + baz, foo::{a, b, cxxxxxxxxxxxxx, yyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz}, qux, xxxxxxxxxxx, + yyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, }, - boo, - c, + boo, c, }; use fooo::{ @@ -99,11 +93,7 @@ use fooo::{ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, }, - bar, - bar::*, - x, - y, - z, + bar, bar::*, x, y, z, }; // nested imports with a single sub-tree. -- cgit 1.4.1-3-g733a5 From b6cd17f28ae314f2484ff05d3ce57652d51c5e85 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 4 May 2018 09:35:56 +1200 Subject: Fix test bug (again) --- src/test/mod.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index ba0c75a1834..4afbf74ae83 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -885,30 +885,28 @@ impl Drop for TempFile { #[test] fn verify_check_works() { - let file_name = "temp_check.rs"; - let _temp_file = make_temp_file(file_name); + let temp_file = make_temp_file("temp_check.rs"); assert_cli::Assert::command(&[ "cargo", "run", "--bin=rustfmt", "--", "--write-mode=check", - file_name, + temp_file.path.to_str().unwrap(), ]).succeeds() .unwrap(); } #[test] fn verify_diff_works() { - let file_name = "temp_diff.rs"; - let _temp_file = make_temp_file(file_name); + let temp_file = make_temp_file("temp_diff.rs"); assert_cli::Assert::command(&[ "cargo", "run", "--bin=rustfmt", "--", "--write-mode=diff", - file_name, + temp_file.path.to_str().unwrap(), ]).succeeds() .unwrap(); } -- cgit 1.4.1-3-g733a5 From 7c246344f887358d129ec2451d47d46eb4f60cda Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 5 May 2018 23:13:49 +0800 Subject: remove nested parens option --- Configurations.md | 22 ++++++++++++++++++++++ src/config/mod.rs | 2 ++ src/expr.rs | 3 ++- tests/source/expr.rs | 1 + tests/source/paren.rs | 2 +- tests/target/expr.rs | 1 + tests/target/paren.rs | 2 +- 7 files changed, 30 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 110925f8e02..428cdfd8516 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1270,6 +1270,28 @@ fn dolor() -> usize {} fn adipiscing() -> usize {} ``` +## `remove_nested_parens` + +Remove nested parens. + +- **Defalut value**: `false`, +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): +```rust +fn main() { + ((((foo())))); +} +``` + +### `true`: +```rust +fn main() { + (foo()); +} +``` + ## `reorder_imports` diff --git a/src/config/mod.rs b/src/config/mod.rs index a4c0e1630a8..abfdb8049a2 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -106,6 +106,8 @@ create_config! { "Maximum number of blank lines which can be put between items."; blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items."; + remove_nested_parens: bool, false, false, + "Remove nested parens."; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/src/expr.rs b/src/expr.rs index 55fe2aa571b..f6dfb43b8a0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1474,6 +1474,7 @@ fn rewrite_paren( // Extract comments within parens. let mut pre_comment; let mut post_comment; + let remove_nested_parens = context.config.remove_nested_parens(); loop { // 1 = "(" or ")" let pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span.lo()); @@ -1483,7 +1484,7 @@ fn rewrite_paren( // Remove nested parens if there are no comments. if let ast::ExprKind::Paren(ref subsubexpr) = subexpr.node { - if pre_comment.is_empty() && post_comment.is_empty() { + if remove_nested_parens && pre_comment.is_empty() && post_comment.is_empty() { span = subexpr.span; subexpr = subsubexpr; continue; diff --git a/tests/source/expr.rs b/tests/source/expr.rs index d5b0babc5bb..91e8e300b98 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -1,5 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true +// rustfmt-remove_nested_parens: true // Test expressions fn foo() -> bool { diff --git a/tests/source/paren.rs b/tests/source/paren.rs index 09ac6b19e9e..ac5de236d8d 100644 --- a/tests/source/paren.rs +++ b/tests/source/paren.rs @@ -1,4 +1,4 @@ -// Remove nested parens. +// rustfmt-remove_nested_parens: true fn main() { let x = (((1))); diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 911a44f0630..977c7f2331b 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -1,5 +1,6 @@ // rustfmt-normalize_comments: true // rustfmt-wrap_comments: true +// rustfmt-remove_nested_parens: true // Test expressions fn foo() -> bool { diff --git a/tests/target/paren.rs b/tests/target/paren.rs index 38569919403..3ffa2ceb474 100644 --- a/tests/target/paren.rs +++ b/tests/target/paren.rs @@ -1,4 +1,4 @@ -// Remove nested parens. +// rustfmt-remove_nested_parens: true fn main() { let x = (1); -- cgit 1.4.1-3-g733a5 From 0f8029f251b569a010cb5cfc5a8bff8bf3c949ac Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 6 May 2018 08:23:26 +1200 Subject: Use a different env var for the test directory --- src/test/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 4afbf74ae83..2680830f065 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -866,7 +866,8 @@ fn make_temp_file(file_name: &'static str) -> TempFile { use std::env::var; use std::fs::File; - let target_dir = var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".to_owned()); + // Used in the Rust build system. + let target_dir = var("RUSTFMT_TEST_DIR").unwrap_or_else(|_| ".".to_owned()); let path = Path::new(&target_dir).join(file_name); let mut file = File::create(&path).expect("Couldn't create temp file"); -- cgit 1.4.1-3-g733a5 From 0cc4a8d848f46cf71cf067b4004ac6d9714339f3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 6 May 2018 09:57:26 +1200 Subject: Update rustc_ap_syntax --- Cargo.lock | 60 ++++++++++++++++++++++++++++++------------------------------ Cargo.toml | 4 ++-- src/attr.rs | 6 +++--- src/utils.rs | 4 ++-- 4 files changed, 37 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d9fc1fdf1bc..98d9d1a5c93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -394,7 +394,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -404,7 +404,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -412,21 +412,21 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -434,44 +434,44 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "113.0.0" +version = "121.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -498,8 +498,8 @@ dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -848,13 +848,13 @@ dependencies = [ "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a01334797c5c4cf56cc40bb9636d7b4c4a076665b9b9b7f100fd666cf0a02ffc" -"checksum rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03d6f8f7da0de905f6ef80dc14dce3bbc372430622b6aeb421cf13190bc70e8a" -"checksum rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dfd6183804a685c48601651d8c8c7b0daa8f83b0b5e24edfbcb6a0337085127" -"checksum rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f223157f51bf0e0621bef099de862468892ee4c4b83056f48f63e1bc00ccb72" -"checksum rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2104a55a87d65cba8a845656f1f19a35da52af403863cd2a4bd5876ba522d879" -"checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323" -"checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63" +"checksum rustc-ap-rustc_cratesio_shim 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ef7efbe957ee3b1ebecb6a260f7b0bad2286c9c20da614eab669a74da5b5fa7" +"checksum rustc-ap-rustc_data_structures 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b168f552c0d3ee3cca0e1ec693649d05d6ea4c0203fe292edc40f82db96dac" +"checksum rustc-ap-rustc_errors 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c5fc02aa44c4d4d42c9d1e026f526f9d2db01dd1387161c9bcae468a7e147c2" +"checksum rustc-ap-rustc_target 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e309c073c612668f0a7b87719073b904c22e8e6df99ee40309eef7f5ec2e14f8" +"checksum rustc-ap-serialize 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef7721a58ba33a1aa296b527348cefc6170c66ce2bbc248b8ea0b2b49ebbc457" +"checksum rustc-ap-syntax 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d22e392afa778785b1ce243b006b7fde6708cd8dbc332a33821169626c4e5a6" +"checksum rustc-ap-syntax_pos 121.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d897ddf75e2d60a4c78edccf84c072b0905ee0acb6dd566882aaca2103594419" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" diff --git a/Cargo.toml b/Cargo.toml index e51c195da71..0bdbd2b4c95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,8 +46,8 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-rustc_target = "113.0.0" -rustc-ap-syntax = "113.0.0" +rustc-ap-rustc_target = "121.0.0" +rustc-ap-syntax = "121.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/attr.rs b/src/attr.rs index 83de61c5e25..894b99815b4 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -200,9 +200,9 @@ fn allow_mixed_tactic_for_nested_metaitem_list(list: &[ast::NestedMetaItem]) -> impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { - ast::MetaItemKind::Word => String::from(&*self.ident.name.as_str()), + ast::MetaItemKind::Word => String::from(&*self.name().as_str()), ast::MetaItemKind::List(ref list) => { - let name = self.ident.name.as_str(); + let name = self.name().as_str(); let item_shape = match context.config.indent_style() { IndentStyle::Block => shape .block_indent(context.config.tab_spaces()) @@ -260,7 +260,7 @@ impl Rewrite for ast::MetaItem { } } ast::MetaItemKind::NameValue(ref literal) => { - let name = self.ident.name.as_str(); + let name = self.name().as_str(); // 3 = ` = ` let lit_shape = shape.shrink_left(name.len() + 3)?; // `rewrite_literal` returns `None` when `literal` exceeds max diff --git a/src/utils.rs b/src/utils.rs index c1d614e885a..f2bdc45b831 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -211,9 +211,9 @@ pub fn last_line_extendable(s: &str) -> bool { #[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { - MetaItemKind::Word => meta_item.ident.name == SKIP_ANNOTATION, + MetaItemKind::Word => meta_item.name() == SKIP_ANNOTATION, MetaItemKind::List(ref l) => { - meta_item.ident.name == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + meta_item.name() == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) } _ => false, } -- cgit 1.4.1-3-g733a5 From f885039e6c2ba75bf50127d4e8e15bc79b772119 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 6 May 2018 12:12:16 +0900 Subject: Do not overflow a long item Take the first line's width of a single item into account when trying to overflow something. Closes #2676. --- src/overflow.rs | 2 +- tests/source/expr.rs | 7 +++++++ tests/target/expr.rs | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index b42c6be90ca..96bebc50bfd 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -422,7 +422,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let extend_width = if items_str.is_empty() { paren_overhead } else { - paren_overhead / 2 + first_line_width(items_str) + (paren_overhead / 2) }; let nested_indent_str = self.nested_shape .indent diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 91e8e300b98..5c7c02a4b82 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -391,3 +391,10 @@ fn dots() { ..= ..= ..; (..) .. ..; // ((..) .. (..)) } + +// #2676 +// A function call with a large single argument. +fn foo() { + let my_var = + Mutex::new(RpcClientType::connect(server_iddd).chain_err(|| "Unable to create RPC client")?); +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 977c7f2331b..50387731d14 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -416,3 +416,11 @@ fn dots() { ..= ..= ..; (..).. ..; // ((..) .. (..)) } + +// #2676 +// A function call with a large single argument. +fn foo() { + let my_var = Mutex::new( + RpcClientType::connect(server_iddd).chain_err(|| "Unable to create RPC client")? + ); +} -- cgit 1.4.1-3-g733a5 From f8439ce8fe1a9f46525d91fb4c7b11b8a1f809fc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 6 May 2018 15:22:17 +0900 Subject: Put operands on its own line when each fits in a single line --- src/expr.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f6dfb43b8a0..2116ef03fd2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -86,16 +86,18 @@ pub fn format_expr( rewrite_call(context, &callee_str, args, inner_span, shape) } ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span), - ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => { + ast::ExprKind::Binary(op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator - rewrite_pair( - &**lhs, - &**rhs, - PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), - context, - shape, - context.config.binop_separator(), - ) + rewrite_simple_binaries(context, expr, shape, op).or_else(|| { + rewrite_pair( + &**lhs, + &**rhs, + PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), + context, + shape, + context.config.binop_separator(), + ) + }) } ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( @@ -352,6 +354,80 @@ pub fn format_expr( }) } +/// Collect operands that appears in the given binary operator in the opposite order. +/// e.g. `collect_binary_items(e, ||)` for `a && b || c || d` returns `[d, c, a && b]`. +fn collect_binary_items<'a>(mut expr: &'a ast::Expr, binop: ast::BinOp) -> Vec<&'a ast::Expr> { + let mut result = vec![]; + let mut prev_lhs = None; + loop { + match expr.node { + ast::ExprKind::Binary(inner_binop, ref lhs, ref rhs) + if inner_binop.node == binop.node => + { + result.push(&**rhs); + expr = lhs; + prev_lhs = Some(lhs); + } + _ => { + if let Some(lhs) = prev_lhs { + result.push(lhs); + } + break; + } + } + } + result +} + +/// Rewrites a binary expression whose operands fits within a single line. +fn rewrite_simple_binaries( + context: &RewriteContext, + expr: &ast::Expr, + shape: Shape, + op: ast::BinOp, +) -> Option { + let op_str = context.snippet(op.span); + + // 2 = spaces around a binary operator. + let sep_overhead = op_str.len() + 2; + let nested_overhead = sep_overhead - 1; + + let nested_shape = (match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), + }).with_max_width(context.config); + let nested_shape = match context.config.binop_separator() { + SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?, + SeparatorPlace::Front => nested_shape.offset_left(nested_overhead)?, + }; + + let opt_rewrites: Option> = collect_binary_items(expr, op) + .iter() + .rev() + .map(|e| e.rewrite(context, nested_shape)) + .collect(); + if let Some(rewrites) = opt_rewrites { + if rewrites.iter().all(|e| ::utils::is_single_line(e)) { + let total_width = rewrites.iter().map(|s| s.len()).sum::() + + sep_overhead * (rewrites.len() - 1); + + let sep_str = if total_width <= shape.width { + format!(" {} ", op_str) + } else { + let indent_str = nested_shape.indent.to_string_with_newline(context.config); + match context.config.binop_separator() { + SeparatorPlace::Back => format!(" {}{}", op_str.trim_right(), indent_str), + SeparatorPlace::Front => format!("{}{} ", indent_str, op_str.trim_left()), + } + }; + + return wrap_str(rewrites.join(&sep_str), context.config.max_width(), shape); + } + } + + None +} + #[derive(new, Clone, Copy)] pub struct PairParts<'a> { prefix: &'a str, -- cgit 1.4.1-3-g733a5 From 1f738ea208cba72bfb433993fd88ad92ce6dada1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 6 May 2018 15:22:29 +0900 Subject: Cargo fmt --- src/bin/main.rs | 3 ++- src/chains.rs | 6 ++++-- src/closures.rs | 6 ++++-- src/comment.rs | 15 +++++++++++---- src/config/summary.rs | 4 +++- src/expr.rs | 28 +++++++++++++++++++--------- src/imports.rs | 4 +++- src/items.rs | 32 ++++++++++++++++++++++---------- src/lib.rs | 6 ++++-- src/lists.rs | 16 +++++++++++----- src/macros.rs | 3 ++- src/matches.rs | 3 ++- src/overflow.rs | 10 +++++++--- src/types.rs | 3 ++- 14 files changed, 96 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 962b315de05..b7bb92c858f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -36,7 +36,8 @@ fn main() { let exit_code = match execute(&opts) { Ok((write_mode, summary)) => { - if summary.has_operational_errors() || summary.has_parsing_errors() + if summary.has_operational_errors() + || summary.has_parsing_errors() || (summary.has_diff && write_mode == WriteMode::Check) { 1 diff --git a/src/chains.rs b/src/chains.rs index 2f05f4a2c46..c602ed7b3e5 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -265,7 +265,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - nested_shape.indent.to_string_with_newline(context.config) }; - let first_connector = if is_small_parent || fits_single_line + let first_connector = if is_small_parent + || fits_single_line || last_line_extendable(&parent_rewrite) || context.config.indent_style() == IndentStyle::Visual { @@ -275,7 +276,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - }; let result = if is_small_parent && rewrites.len() > 1 { - let second_connector = if fits_single_line || rewrites[1] == "?" + let second_connector = if fits_single_line + || rewrites[1] == "?" || last_line_extendable(&rewrites[0]) || context.config.indent_style() == IndentStyle::Visual { diff --git a/src/closures.rs b/src/closures.rs index 20ba0118f5f..c9372248f05 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -109,8 +109,10 @@ fn get_inner_expr<'a>( // Figure out if a block is necessary. fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { - is_unsafe_block(block) || block.stmts.len() > 1 - || block_contains_comment(block, context.codemap) || prefix.contains('\n') + is_unsafe_block(block) + || block.stmts.len() > 1 + || block_contains_comment(block, context.codemap) + || prefix.contains('\n') } // Rewrite closure with a single expression wrapping its body with block. diff --git a/src/comment.rs b/src/comment.rs index 4a0abc2b099..49f8d1698e1 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -579,7 +579,9 @@ fn light_rewrite_comment( /// Does not trim all whitespace. If a single space is trimmed from the left of the string, /// this function returns true. fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { - if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") + if line.starts_with("//! ") + || line.starts_with("/// ") + || line.starts_with("/*! ") || line.starts_with("/** ") { (&line[4..], true) @@ -589,13 +591,18 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, } else { (&line[opener.trim_right().len()..], false) } - } else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") - || line.starts_with("///") || line.starts_with("** ") + } else if line.starts_with("/* ") + || line.starts_with("// ") + || line.starts_with("//!") + || line.starts_with("///") + || line.starts_with("** ") || line.starts_with("/*!") || (line.starts_with("/**") && !line.starts_with("/**/")) { (&line[3..], line.chars().nth(2).unwrap() == ' ') - } else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") + } else if line.starts_with("/*") + || line.starts_with("* ") + || line.starts_with("//") || line.starts_with("**") { (&line[2..], line.chars().nth(1).unwrap() == ' ') diff --git a/src/config/summary.rs b/src/config/summary.rs index c906c77506f..9f339b61be7 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -90,7 +90,9 @@ impl Summary { } pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors + !(self.has_operational_errors + || self.has_parsing_errors + || self.has_formatting_errors || self.has_diff) } diff --git a/src/expr.rs b/src/expr.rs index 2116ef03fd2..4ca1bbb22e3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -474,8 +474,10 @@ where .map(|first_line| first_line.ends_with('{')) .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) + pp.infix.len() - + first_line_width(rhs_result) + pp.suffix.len(); + let one_line_width = last_line_width(&lhs_result) + + pp.infix.len() + + first_line_width(rhs_result) + + pp.suffix.len(); if one_line_width <= shape.width { return Some(format!( "{}{}{}{}", @@ -558,7 +560,9 @@ fn rewrite_empty_block( let user_str = user_str.trim(); if user_str.starts_with('{') && user_str.ends_with('}') { let comment_str = user_str[1..user_str.len() - 1].trim(); - if block.stmts.is_empty() && !comment_str.contains('\n') && !comment_str.starts_with("//") + if block.stmts.is_empty() + && !comment_str.contains('\n') + && !comment_str.starts_with("//") && comment_str.len() + 4 <= shape.width { return Some(format!("{}{{ {} }}", prefix, comment_str)); @@ -1241,8 +1245,10 @@ pub fn is_simple_block( attrs: Option<&[ast::Attribute]>, codemap: &CodeMap, ) -> bool { - (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, codemap) && attrs.map_or(true, |a| a.is_empty())) + (block.stmts.len() == 1 + && stmt_is_expr(&block.stmts[0]) + && !block_contains_comment(block, codemap) + && attrs.map_or(true, |a| a.is_empty())) } /// Checks whether a block contains at most one statement or expression, and no @@ -1252,7 +1258,8 @@ pub fn is_simple_block_stmt( attrs: Option<&[ast::Attribute]>, codemap: &CodeMap, ) -> bool { - block.stmts.len() <= 1 && !block_contains_comment(block, codemap) + block.stmts.len() <= 1 + && !block_contains_comment(block, codemap) && attrs.map_or(true, |a| a.is_empty()) } @@ -1263,7 +1270,8 @@ pub fn is_empty_block( attrs: Option<&[ast::Attribute]>, codemap: &CodeMap, ) -> bool { - block.stmts.is_empty() && !block_contains_comment(block, codemap) + block.stmts.is_empty() + && !block_contains_comment(block, codemap) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } @@ -1778,7 +1786,8 @@ pub fn wrap_struct_field( one_line_width: usize, ) -> String { if context.config.indent_style() == IndentStyle::Block - && (fields_str.contains('\n') || !context.config.struct_lit_single_line() + && (fields_str.contains('\n') + || !context.config.struct_lit_single_line() || fields_str.len() > one_line_width) { format!( @@ -2104,7 +2113,8 @@ fn choose_rhs( } pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { - rhs_tactics == RhsTactics::ForceNextLine || !next_line_rhs.contains('\n') + rhs_tactics == RhsTactics::ForceNextLine + || !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } diff --git a/src/imports.rs b/src/imports.rs index 05b10519d45..3d7ad0ab1b5 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -489,7 +489,9 @@ impl UseTree { } fn share_prefix(&self, other: &UseTree) -> bool { - if self.path.is_empty() || other.path.is_empty() || self.attrs.is_some() + if self.path.is_empty() + || other.path.is_empty() + || self.attrs.is_some() || !self.same_visibility(other) { false diff --git a/src/items.rs b/src/items.rs index 08bdfe0295f..72954513908 100644 --- a/src/items.rs +++ b/src/items.rs @@ -313,7 +313,8 @@ impl<'a> FmtVisitor<'a> { rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; // 2 = ` {` - if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace + if self.config.brace_style() == BraceStyle::AlwaysNextLine + || force_newline_brace || last_line_width(&result) + 2 > self.shape().width { newline_brace = true; @@ -376,7 +377,8 @@ impl<'a> FmtVisitor<'a> { let codemap = self.get_context().codemap; - if self.config.empty_item_single_line() && is_empty_block(block, None, codemap) + if self.config.empty_item_single_line() + && is_empty_block(block, None, codemap) && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { return Some(format!("{}{{}}", fn_str)); @@ -755,7 +757,9 @@ fn is_impl_single_line( let open_pos = snippet.find_uncommented("{")? + 1; Some( - context.config.empty_item_single_line() && items.is_empty() && !result.contains('\n') + context.config.empty_item_single_line() + && items.is_empty() + && !result.contains('\n') && result.len() + where_clause_str.len() <= context.config.max_width() && !contains_comment(&snippet[open_pos..]), ) @@ -1194,7 +1198,8 @@ pub fn format_struct_struct( // 1 = `}` let overhead = if fields.is_empty() { 1 } else { 0 }; let total_width = result.len() + generics_str.len() + overhead; - if !generics_str.is_empty() && !generics_str.contains('\n') + if !generics_str.is_empty() + && !generics_str.contains('\n') && total_width > context.config.max_width() { result.push('\n'); @@ -1223,7 +1228,9 @@ pub fn format_struct_struct( one_line_budget, )?; - if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget + if !items_str.contains('\n') + && !result.contains('\n') + && items_str.len() <= one_line_budget && !last_line_contains_single_line_comment(&items_str) { Some(format!("{} {} }}", result, items_str)) @@ -1904,7 +1911,8 @@ fn rewrite_fn_base( } else { result.push('('); } - if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() + if context.config.spaces_within_parens_and_brackets() + && !fd.inputs.is_empty() && result.ends_with('(') { result.push(' ') @@ -2478,8 +2486,10 @@ fn rewrite_where_clause_rfc_style( let newline_after_where = comment_separator(&comment_after, clause_shape); // 6 = `where ` - let clause_sep = if where_clause_option.compress_where && comment_before.is_empty() - && comment_after.is_empty() && !preds_str.contains('\n') + let clause_sep = if where_clause_option.compress_where + && comment_before.is_empty() + && comment_after.is_empty() + && !preds_str.contains('\n') && 6 + preds_str.len() <= shape.width || where_single_line { Cow::from(" ") @@ -2590,7 +2600,8 @@ fn rewrite_where_clause( } else { terminator.len() }; - if density == Density::Tall || preds_str.contains('\n') + if density == Density::Tall + || preds_str.contains('\n') || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { Some(format!( @@ -2682,7 +2693,8 @@ fn format_generics( || (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1) } else { - brace_pos == BracePos::ForceSameLine || trimmed_last_line_width(&result) == 1 + brace_pos == BracePos::ForceSameLine + || trimmed_last_line_width(&result) == 1 || brace_style != BraceStyle::AlwaysNextLine }; if brace_pos == BracePos::None { diff --git a/src/lib.rs b/src/lib.rs index ec8646acc1c..71cf74f6022 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -490,7 +490,8 @@ fn format_lines( // Check for any line width errors we couldn't correct. let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); - if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) + if line_len > config.max_width() + && !is_skipped_line(cur_line, skipped_range) && should_report_error(config, kind, is_string, error_kind) { errors.push(FormattingError { @@ -905,7 +906,8 @@ pub fn format_and_emit_report(input: Input, config: &Config) -> FmtResult { match report.print_warnings_fancy(term::stderr().unwrap()) { diff --git a/src/lists.rs b/src/lists.rs index 9e5ea33d296..433beac44ee 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -192,7 +192,8 @@ where let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); let real_total = total_width + total_sep_len; - if real_total <= limit && !pre_line_comments + if real_total <= limit + && !pre_line_comments && !items.into_iter().any(|item| item.as_ref().is_multiline()) { DefinitiveListTactic::Horizontal @@ -404,8 +405,10 @@ where if !starts_with_newline(comment) { let mut comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); - if first_line_width(&formatted_comment) + last_line_width(&result) - + comment_alignment + 1 > formatting.config.max_width() + if first_line_width(&formatted_comment) + + last_line_width(&result) + + comment_alignment + + 1 > formatting.config.max_width() { item_max_width = None; formatted_comment = rewrite_post_comment(&mut item_max_width)?; @@ -431,7 +434,9 @@ where item_max_width = None; } - if formatting.preserve_newline && !last && tactic == DefinitiveListTactic::Vertical + if formatting.preserve_newline + && !last + && tactic == DefinitiveListTactic::Vertical && item.new_lines { item_max_width = None; @@ -458,7 +463,8 @@ where let item = item.as_ref(); let inner_item_width = item.inner_as_ref().len(); if !first - && (item.is_different_group() || item.post_comment.is_none() + && (item.is_different_group() + || item.post_comment.is_none() || inner_item_width + overhead > max_budget) { return max_width; diff --git a/src/macros.rs b/src/macros.rs index 1fc150e1256..3da0a4a5c3a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -269,7 +269,8 @@ pub fn rewrite_macro_inner( let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); let lhs = arg_vec[0].rewrite(context, nested_shape)?; let rhs = arg_vec[1].rewrite(context, nested_shape)?; - if !lhs.contains('\n') && !rhs.contains('\n') + if !lhs.contains('\n') + && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) diff --git a/src/matches.rs b/src/matches.rs index bc092b1a718..0bbdbe62017 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -498,7 +498,8 @@ fn rewrite_guard( fn nop_block_collapse(block_str: Option, budget: usize) -> Option { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| { - if block_str.starts_with('{') && budget >= 2 + if block_str.starts_with('{') + && budget >= 2 && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { "{}".to_owned() diff --git a/src/overflow.rs b/src/overflow.rs index 96bebc50bfd..977dbbbb5f4 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -235,7 +235,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { fn try_overflow_last_item(&self, list_items: &mut Vec) -> DefinitiveListTactic { // 1 = "(" - let combine_arg_with_callee = self.items.len() == 1 && self.items[0].to_expr().is_some() + let combine_arg_with_callee = self.items.len() == 1 + && self.items[0].to_expr().is_some() && self.ident.len() + 1 <= self.context.config.tab_spaces(); let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, self.items); @@ -311,7 +312,9 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { // Use horizontal layout for a function with a single argument as long as // everything fits in a single line. // `self.one_line_width == 0` means vertical layout is forced. - if self.items.len() == 1 && self.one_line_width != 0 && !list_items[0].has_comment() + if self.items.len() == 1 + && self.one_line_width != 0 + && !list_items[0].has_comment() && !list_items[0].inner_as_ref().contains('\n') && ::lists::total_item_width(&list_items[0]) <= self.one_line_width { @@ -462,7 +465,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let (extendable, items_str) = self.rewrite_items()?; // If we are using visual indent style and failed to format, retry with block indent. - if !self.context.use_block_indent() && need_block_indent(&items_str, self.nested_shape) + if !self.context.use_block_indent() + && need_block_indent(&items_str, self.nested_shape) && !extendable { self.context.use_block.replace(true); diff --git a/src/types.rs b/src/types.rs index 149769c5df7..6ffb9cd5c7e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -230,7 +230,8 @@ fn rewrite_segment( if let Some(ref params) = segment.parameters { match **params { ast::PathParameters::AngleBracketed(ref data) - if !data.lifetimes.is_empty() || !data.types.is_empty() + if !data.lifetimes.is_empty() + || !data.types.is_empty() || !data.bindings.is_empty() => { let param_list = data.lifetimes -- cgit 1.4.1-3-g733a5 From 5f05987211a76ea549f9d163f9084f88e4a52f8f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 6 May 2018 16:16:58 +0900 Subject: Use rustfmt.toml when running self_tests --- src/config/config_type.rs | 5 +++-- src/test/mod.rs | 23 +++++++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 06c05bb9355..f12d1864728 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -322,8 +322,9 @@ macro_rules! create_config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { - + pub(super) fn from_resolved_toml_path( + dir: &Path, + ) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of a the nearest project file if one exists, /// or `None` if no project file was found. diff --git a/src/test/mod.rs b/src/test/mod.rs index 2680830f065..d1e7cbd5a64 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -111,7 +111,7 @@ fn write_message(msg: &str) { fn system_tests() { // Get all files in the tests/source directory. let files = get_test_files(Path::new("tests/source"), true); - let (_reports, count, fails) = check_files(files); + let (_reports, count, fails) = check_files(files, None); // Display results. println!("Ran {} system tests.", count); @@ -123,7 +123,7 @@ fn system_tests() { #[test] fn coverage_tests() { let files = get_test_files(Path::new("tests/coverage/source"), true); - let (_reports, count, fails) = check_files(files); + let (_reports, count, fails) = check_files(files, None); println!("Ran {} tests in coverage mode.", count); assert_eq!(fails, 0, "{} tests failed", fails); @@ -192,7 +192,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { fn idempotence_tests() { // Get all files in the tests/target directory. let files = get_test_files(Path::new("tests/target"), true); - let (_reports, count, fails) = check_files(files); + let (_reports, count, fails) = check_files(files, None); // Display results. println!("Ran {} idempotent tests.", count); @@ -213,7 +213,7 @@ fn self_tests() { } files.push(PathBuf::from("src/lib.rs")); - let (reports, count, fails) = check_files(files); + let (reports, count, fails) = check_files(files, Some(PathBuf::from("rustfmt.toml"))); let mut warnings = 0; // Display results. @@ -298,7 +298,7 @@ fn format_lines_errors_are_reported_with_tabs() { // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. -fn check_files(files: Vec) -> (Vec, u32, u32) { +fn check_files(files: Vec, opt_config: Option) -> (Vec, u32, u32) { let mut count = 0; let mut fails = 0; let mut reports = vec![]; @@ -306,7 +306,7 @@ fn check_files(files: Vec) -> (Vec, u32, u32) { for file_name in files { debug!("Testing '{}'...", file_name.display()); - match idempotent_check(&file_name) { + match idempotent_check(&file_name, &opt_config) { Ok(ref report) if report.has_warnings() => { print!("{}", report); fails += 1; @@ -385,9 +385,16 @@ pub enum IdempotentCheckError { Parse, } -pub fn idempotent_check(filename: &PathBuf) -> Result { +pub fn idempotent_check( + filename: &PathBuf, + opt_config: &Option, +) -> Result { let sig_comments = read_significant_comments(filename); - let config = read_config(filename); + let config = if let Some(ref config_file_path) = opt_config { + Config::from_toml_path(config_file_path).expect("rustfmt.toml not found") + } else { + read_config(filename) + }; let (error_summary, file_map, format_report) = format_file(filename, &config); if error_summary.has_parsing_errors() { return Err(IdempotentCheckError::Parse); -- cgit 1.4.1-3-g733a5 From 51c07f43353c269ce2790cad7398d9fa465da4a0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 6 May 2018 16:17:09 +0900 Subject: Fix up lines exceeding max width --- src/config/mod.rs | 20 +++++++++++++------- src/config/options.rs | 3 ++- src/lib.rs | 3 ++- src/macros.rs | 4 +++- src/test/mod.rs | 5 +++-- 5 files changed, 23 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index abfdb8049a2..382e7e7cc92 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -50,7 +50,8 @@ create_config! { comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; - license_template_path: String, String::default(), false, "Beginning of file must match license template"; + license_template_path: String, String::default(), false, + "Beginning of file must match license template"; format_strings: bool, false, false, "Format string literals where necessary"; // Single line expressions and items @@ -239,16 +240,21 @@ mod test { create_config! { // Options that are used by the generated functions max_width: usize, 100, true, "Maximum width of each line"; - use_small_heuristics: bool, true, false, "Whether to use different formatting for items and \ - expressions if they satisfy a heuristic notion of 'small'."; - license_template_path: String, String::default(), false, "Beginning of file must match license template"; - required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, "Require a specific version of rustfmt."; - ignore: IgnoreList, IgnoreList::default(), false, "Skip formatting the specified files and directories."; + use_small_heuristics: bool, true, false, + "Whether to use different formatting for items and \ + expressions if they satisfy a heuristic notion of 'small'."; + license_template_path: String, String::default(), false, + "Beginning of file must match license template"; + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, + "Require a specific version of rustfmt."; + ignore: IgnoreList, IgnoreList::default(), false, + "Skip formatting the specified files and directories."; verbose: bool, false, false, "Use verbose output"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, "'small' heuristic values"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; // Options that are used by the tests stable_option: bool, false, true, "A stable option"; diff --git a/src/config/options.rs b/src/config/options.rs index c350aac8d96..272acef2b3a 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -191,7 +191,8 @@ configuration_option_enum! { WriteMode: // Output the changed lines (for internal value only) Modified, // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. - // This option is designed to be run in CI where a non-zero exit signifies non-standard code formatting. + // This option is designed to be run in CI where a non-zero exit signifies non-standard code + // formatting. Check, // Rustfmt shouldn't output anything formatting-like (e.g., emit a help message). None, diff --git a/src/lib.rs b/src/lib.rs index ec8646acc1c..bae548a4b2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,7 +116,8 @@ pub(crate) type FileRecord = (FileName, String); pub enum ErrorKind { // Line has exceeded character limit (found, maximum) #[fail( - display = "line formatted, but exceeded maximum width (maximum: {} (see `max_width` option), found: {})", + display = "line formatted, but exceeded maximum width \ + (maximum: {} (see `max_width` option), found: {})", _0, _1 )] diff --git a/src/macros.rs b/src/macros.rs index 1fc150e1256..cbc42dae0a9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1296,7 +1296,9 @@ impl MacroBranch { fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) -> Option { let mut result = String::with_capacity(1024); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - let nested_shape = shape.block_indent(context.config.tab_spaces()); + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); result.push_str("lazy_static! {"); result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); diff --git a/src/test/mod.rs b/src/test/mod.rs index d1e7cbd5a64..06fd1e5a98f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -618,8 +618,9 @@ impl ConfigurationSection { lazy_static! { static ref CONFIG_NAME_REGEX: regex::Regex = regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); - static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) - .expect("Failed creating configuration value pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = + regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) + .expect("Failed creating configuration value pattern"); } loop { -- cgit 1.4.1-3-g733a5 From cf573e815712e1e617e895621a4faa859aa3d86e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 4 May 2018 11:51:06 +0200 Subject: Fix handling of modules in non_modrs_mods style We need to keep track of the module relative to which we're resolving paths, instead of always passing None. Fixes #2673. --- src/modules.rs | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 0f439910324..8426a751daa 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -14,7 +14,7 @@ use std::path::{Path, PathBuf}; use syntax::ast; use syntax::codemap::{self, FileName}; -use syntax::parse::parser; +use syntax::parse::{parser, DirectoryOwnership}; use utils::contains_skip; @@ -31,7 +31,7 @@ pub fn list_files<'a>( FileName::Real(ref path) => path.parent().unwrap(), _ => Path::new(""), }; - list_submodules(&krate.module, parent, codemap, &mut result)?; + list_submodules(&krate.module, parent, None, codemap, &mut result)?; } result.insert(root_filename, &krate.module); Ok(result) @@ -41,6 +41,7 @@ pub fn list_files<'a>( fn list_submodules<'a>( module: &'a ast::Mod, search_dir: &Path, + relative: Option, codemap: &codemap::CodeMap, result: &mut BTreeMap, ) -> Result<(), io::Error> { @@ -50,15 +51,16 @@ fn list_submodules<'a>( if !contains_skip(&item.attrs) { let is_internal = codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); - let dir_path = if is_internal { - search_dir.join(&item.ident.to_string()) + let (dir_path, relative) = if is_internal { + (search_dir.join(&item.ident.to_string()), None) } else { - let mod_path = module_file(item.ident, &item.attrs, search_dir, codemap)?; + let (mod_path, relative) = + module_file(item.ident, &item.attrs, search_dir, relative, codemap)?; let dir_path = mod_path.parent().unwrap().to_owned(); result.insert(FileName::Real(mod_path), sub_mod); - dir_path + (dir_path, relative) }; - list_submodules(sub_mod, &dir_path, codemap, result)?; + list_submodules(sub_mod, &dir_path, relative, codemap, result)?; } } } @@ -70,14 +72,27 @@ fn module_file( id: ast::Ident, attrs: &[ast::Attribute], dir_path: &Path, + relative: Option, codemap: &codemap::CodeMap, -) -> Result { +) -> Result<(PathBuf, Option), io::Error> { + eprintln!("module_file {:?} {:?} {:?}", id, attrs, dir_path); if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { - return Ok(path); + return Ok((path, None)); } - match parser::Parser::default_submod_path(id, None, dir_path, codemap).result { - Ok(parser::ModulePathSuccess { path, .. }) => Ok(path), + match parser::Parser::default_submod_path(id, relative, dir_path, codemap).result { + Ok(parser::ModulePathSuccess { + path, + directory_ownership, + .. + }) => { + let relative = if let DirectoryOwnership::Owned { relative } = directory_ownership { + relative + } else { + None + }; + Ok((path, relative)) + } Err(_) => Err(io::Error::new( io::ErrorKind::Other, format!("Couldn't find module {}", id), -- cgit 1.4.1-3-g733a5 From 215baae2238971361c5f92accfae35ba0ad6c634 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 4 May 2018 20:12:06 +0200 Subject: Add a test for non-mod.rs mods --- src/modules.rs | 1 - src/test/mod.rs | 17 +++++++++++++++++ tests/issue-2673-nonmodrs-mods/foo.rs | 3 +++ tests/issue-2673-nonmodrs-mods/foo/bar.rs | 1 + tests/issue-2673-nonmodrs-mods/lib.rs | 3 +++ 5 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/issue-2673-nonmodrs-mods/foo.rs create mode 100644 tests/issue-2673-nonmodrs-mods/foo/bar.rs create mode 100644 tests/issue-2673-nonmodrs-mods/lib.rs (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 8426a751daa..80a7e85c71d 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -75,7 +75,6 @@ fn module_file( relative: Option, codemap: &codemap::CodeMap, ) -> Result<(PathBuf, Option), io::Error> { - eprintln!("module_file {:?} {:?} {:?}", id, attrs, dir_path); if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { return Ok((path, None)); } diff --git a/src/test/mod.rs b/src/test/mod.rs index 2680830f065..c5898950813 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -232,6 +232,23 @@ fn self_tests() { ); } +#[test] +fn issue_2673_non_modrs_mods() { + match idempotent_check(&PathBuf::from("tests/issue-2673-nonmodrs-mods/lib.rs")) { + Ok(ref report) if report.has_warnings() => { + print!("{}", report); + panic!("had warnings"); + } + Ok(_report) => {} + Err(err) => { + if let IdempotentCheckError::Mismatch(msg) = err { + print_mismatches_default_message(msg); + } + panic!("had errors"); + } + } +} + #[test] fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); diff --git a/tests/issue-2673-nonmodrs-mods/foo.rs b/tests/issue-2673-nonmodrs-mods/foo.rs new file mode 100644 index 00000000000..c9fb22cf1a6 --- /dev/null +++ b/tests/issue-2673-nonmodrs-mods/foo.rs @@ -0,0 +1,3 @@ +mod bar; + +mod baz {} diff --git a/tests/issue-2673-nonmodrs-mods/foo/bar.rs b/tests/issue-2673-nonmodrs-mods/foo/bar.rs new file mode 100644 index 00000000000..9ceacd59d86 --- /dev/null +++ b/tests/issue-2673-nonmodrs-mods/foo/bar.rs @@ -0,0 +1 @@ +fn dummy() {} diff --git a/tests/issue-2673-nonmodrs-mods/lib.rs b/tests/issue-2673-nonmodrs-mods/lib.rs new file mode 100644 index 00000000000..e2025a5449d --- /dev/null +++ b/tests/issue-2673-nonmodrs-mods/lib.rs @@ -0,0 +1,3 @@ +#![feature(non_modrs_mods)] + +mod foo; -- cgit 1.4.1-3-g733a5 From e59ceaf95460c3fd430651d015f9c3bb276ed97f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 6 May 2018 17:01:14 +0900 Subject: Do not duplicate attributes on use items --- src/imports.rs | 2 +- src/visitor.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 05b10519d45..ec81d99b0f9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -35,7 +35,7 @@ pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { impl<'a> FmtVisitor<'a> { pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { - let span = item.span; + let span = item.span(); let shape = self.shape(); let rw = UseTree::from_ast( &self.get_context(), diff --git a/src/visitor.rs b/src/visitor.rs index 05f2e7e5cc1..71a279d93aa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -303,6 +303,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let filtered_attrs; let mut attrs = &item.attrs; match item.node { + // For use items, skip rewriting attributes. Just check for a skip attribute. + ast::ItemKind::Use(..) => { + if contains_skip(attrs) { + self.push_skipped_with_span(item.span()); + return; + } + } // Module is inline, in this case we treat it like any other item. _ if !is_mod_decl(item) => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { -- cgit 1.4.1-3-g733a5 From e65aa302d34da29839fc72cf3363e85ccd71b2ee Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 6 May 2018 13:03:11 +0200 Subject: Turn the nonmodrs-mods test into a standard idempotence test We need to skip children on foo.rs, since the parser will not find bar from that file, but with that, the test works fine. --- src/test/mod.rs | 17 ----------------- tests/config/skip_children.toml | 1 + tests/issue-2673-nonmodrs-mods/foo.rs | 3 --- tests/issue-2673-nonmodrs-mods/foo/bar.rs | 1 - tests/issue-2673-nonmodrs-mods/lib.rs | 3 --- tests/target/issue-2673-nonmodrs-mods/foo.rs | 4 ++++ tests/target/issue-2673-nonmodrs-mods/foo/bar.rs | 1 + tests/target/issue-2673-nonmodrs-mods/lib.rs | 6 ++++++ 8 files changed, 12 insertions(+), 24 deletions(-) create mode 100644 tests/config/skip_children.toml delete mode 100644 tests/issue-2673-nonmodrs-mods/foo.rs delete mode 100644 tests/issue-2673-nonmodrs-mods/foo/bar.rs delete mode 100644 tests/issue-2673-nonmodrs-mods/lib.rs create mode 100644 tests/target/issue-2673-nonmodrs-mods/foo.rs create mode 100644 tests/target/issue-2673-nonmodrs-mods/foo/bar.rs create mode 100644 tests/target/issue-2673-nonmodrs-mods/lib.rs (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index c5898950813..2680830f065 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -232,23 +232,6 @@ fn self_tests() { ); } -#[test] -fn issue_2673_non_modrs_mods() { - match idempotent_check(&PathBuf::from("tests/issue-2673-nonmodrs-mods/lib.rs")) { - Ok(ref report) if report.has_warnings() => { - print!("{}", report); - panic!("had warnings"); - } - Ok(_report) => {} - Err(err) => { - if let IdempotentCheckError::Mismatch(msg) = err { - print_mismatches_default_message(msg); - } - panic!("had errors"); - } - } -} - #[test] fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); diff --git a/tests/config/skip_children.toml b/tests/config/skip_children.toml new file mode 100644 index 00000000000..49f37a88dfb --- /dev/null +++ b/tests/config/skip_children.toml @@ -0,0 +1 @@ +skip_children = true \ No newline at end of file diff --git a/tests/issue-2673-nonmodrs-mods/foo.rs b/tests/issue-2673-nonmodrs-mods/foo.rs deleted file mode 100644 index c9fb22cf1a6..00000000000 --- a/tests/issue-2673-nonmodrs-mods/foo.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod bar; - -mod baz {} diff --git a/tests/issue-2673-nonmodrs-mods/foo/bar.rs b/tests/issue-2673-nonmodrs-mods/foo/bar.rs deleted file mode 100644 index 9ceacd59d86..00000000000 --- a/tests/issue-2673-nonmodrs-mods/foo/bar.rs +++ /dev/null @@ -1 +0,0 @@ -fn dummy() {} diff --git a/tests/issue-2673-nonmodrs-mods/lib.rs b/tests/issue-2673-nonmodrs-mods/lib.rs deleted file mode 100644 index e2025a5449d..00000000000 --- a/tests/issue-2673-nonmodrs-mods/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![feature(non_modrs_mods)] - -mod foo; diff --git a/tests/target/issue-2673-nonmodrs-mods/foo.rs b/tests/target/issue-2673-nonmodrs-mods/foo.rs new file mode 100644 index 00000000000..5340816d61e --- /dev/null +++ b/tests/target/issue-2673-nonmodrs-mods/foo.rs @@ -0,0 +1,4 @@ +// rustfmt-config: skip_children.toml +mod bar; + +mod baz {} diff --git a/tests/target/issue-2673-nonmodrs-mods/foo/bar.rs b/tests/target/issue-2673-nonmodrs-mods/foo/bar.rs new file mode 100644 index 00000000000..9ceacd59d86 --- /dev/null +++ b/tests/target/issue-2673-nonmodrs-mods/foo/bar.rs @@ -0,0 +1 @@ +fn dummy() {} diff --git a/tests/target/issue-2673-nonmodrs-mods/lib.rs b/tests/target/issue-2673-nonmodrs-mods/lib.rs new file mode 100644 index 00000000000..82425de565a --- /dev/null +++ b/tests/target/issue-2673-nonmodrs-mods/lib.rs @@ -0,0 +1,6 @@ +#![feature(non_modrs_mods)] + +// Test that submodules in non-mod.rs files work. This is just an idempotence +// test since we just want to verify that rustfmt doesn't fail. + +mod foo; -- cgit 1.4.1-3-g733a5 From 0ec311ee078bea2e0d91f0f0cf821173a246110b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 8 May 2018 06:25:06 +0900 Subject: Apply small parent rule only when there is small offset --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c602ed7b3e5..e1f101915e6 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -108,7 +108,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .rewrite(context, parent_shape) .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); - let is_small_parent = parent_rewrite.len() <= context.config.tab_spaces(); + let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. -- cgit 1.4.1-3-g733a5 From bd25c7d0f73a5b6bf888593e717be391eaeb3e58 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 8 May 2018 06:25:48 +0900 Subject: Cargo fmt --- src/chains.rs | 3 ++- src/closures.rs | 3 ++- src/comment.rs | 15 ++++++++++----- src/config/options.rs | 3 ++- src/expr.rs | 12 ++++++++---- src/git-rustfmt/main.rs | 3 ++- src/imports.rs | 12 ++++++++---- src/items.rs | 18 ++++++++++++------ src/lib.rs | 3 ++- src/lists.rs | 18 ++++++++++++------ src/missed_spans.rs | 3 ++- src/overflow.rs | 12 ++++++++---- src/patterns.rs | 3 ++- src/test/mod.rs | 6 ++++-- src/types.rs | 9 ++++++--- src/utils.rs | 3 ++- src/visitor.rs | 3 ++- 17 files changed, 86 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index e1f101915e6..a411f904fe9 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -156,7 +156,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let last_subexpr = &subexpr_list[suffix_try_num]; let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); - let mut rewrites = iter.map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) + let mut rewrites = iter + .map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) .collect::>>()?; // Total of all items excluding the last. diff --git a/src/closures.rs b/src/closures.rs index c9372248f05..0d5cf63a197 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -50,7 +50,8 @@ pub fn rewrite_closure( if let ast::ExprKind::Block(ref block) = body.node { // The body of the closure is an empty block. if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { - return body.rewrite(context, shape) + return body + .rewrite(context, shape) .map(|s| format!("{} {}", prefix, s)); } diff --git a/src/comment.rs b/src/comment.rs index 49f8d1698e1..0b6c818e59e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -249,7 +249,8 @@ fn _rewrite_comment( // If there are lines without a starting sigil, we won't format them correctly // so in that case we won't even re-align (if !config.normalize_comments()) and // we should stop now. - let num_bare_lines = orig.lines() + let num_bare_lines = orig + .lines() .map(|line| line.trim()) .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) .count(); @@ -271,11 +272,13 @@ fn identify_comment( is_doc_comment: bool, ) -> Option { let style = comment_style(orig, false); - let first_group = orig.lines() + let first_group = orig + .lines() .take_while(|l| style.line_with_same_comment_style(l, false)) .collect::>() .join("\n"); - let rest = orig.lines() + let rest = orig + .lines() .skip(first_group.lines().count()) .collect::>() .join("\n"); @@ -333,7 +336,8 @@ fn rewrite_comment_inner( }; let line_breaks = count_newlines(orig.trim_right()); - let lines = orig.lines() + let lines = orig + .lines() .enumerate() .map(|(i, mut line)| { line = trim_right_unless_two_whitespaces(line.trim_left(), is_doc_comment); @@ -553,7 +557,8 @@ fn light_rewrite_comment( config: &Config, is_doc_comment: bool, ) -> Option { - let lines: Vec<&str> = orig.lines() + let lines: Vec<&str> = orig + .lines() .map(|l| { // This is basically just l.trim(), but in the case that a line starts // with `*` we want to leave one space before it, so it aligns with the diff --git a/src/config/options.rs b/src/config/options.rs index 272acef2b3a..bd8823f9ce4 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -282,7 +282,8 @@ pub struct IgnoreList(HashSet); impl IgnoreList { pub fn add_prefix(&mut self, dir: &Path) { - self.0 = self.0 + self.0 = self + .0 .iter() .map(|s| { if s.has_root() { diff --git a/src/expr.rs b/src/expr.rs index 4ca1bbb22e3..429fbc3cf9a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -455,7 +455,8 @@ where width: context.budget(lhs_overhead), ..shape }; - let lhs_result = lhs.rewrite(context, lhs_shape) + let lhs_result = lhs + .rewrite(context, lhs_shape) .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; // Try to put both lhs and rhs on the same line. @@ -1036,7 +1037,8 @@ impl<'a> ControlFlow<'a> { // `for event in event` // Do not include label in the span. - let lo = self.label + let lo = self + .label .map_or(self.span.lo(), |label| label.ident.span.hi()); let between_kwd_cond = mk_sp( context @@ -1295,11 +1297,13 @@ pub fn rewrite_multiple_patterns( pats: &[&ast::Pat], shape: Shape, ) -> Option { - let pat_strs = pats.iter() + let pat_strs = pats + .iter() .map(|p| p.rewrite(context, shape)) .collect::>>()?; - let use_mixed_layout = pats.iter() + let use_mixed_layout = pats + .iter() .zip(pat_strs.iter()) .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 390eeb4149a..41b16969dc2 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -170,7 +170,8 @@ fn main() { env_logger::init(); let opts = make_opts(); - let matches = opts.parse(env::args().skip(1)) + let matches = opts + .parse(env::args().skip(1)) .expect("Couldn't parse command line"); let config = Config::from_args(&matches, &opts); diff --git a/src/imports.rs b/src/imports.rs index fc7f5e87e36..83121b04213 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -231,10 +231,12 @@ impl fmt::Display for UseTree { impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { - let vis = self.visibility + let vis = self + .visibility .as_ref() .map_or(Cow::from(""), |vis| ::utils::format_visibility(&vis)); - let use_str = self.rewrite(context, shape.offset_left(vis.len())?) + let use_str = self + .rewrite(context, shape.offset_left(vis.len())?) .map(|s| { if s.is_empty() { s.to_owned() @@ -448,7 +450,8 @@ impl UseTree { // Recursively normalize elements of a list use (including sorting the list). if let UseSegment::List(list) = last { - let mut list = list.into_iter() + let mut list = list + .into_iter() .map(|ut| ut.normalize()) .collect::>(); list.sort(); @@ -530,7 +533,8 @@ impl UseTree { fn merge(&mut self, other: UseTree) { let mut new_path = vec![]; - for (mut a, b) in self.path + for (mut a, b) in self + .path .clone() .iter_mut() .zip(other.path.clone().into_iter()) diff --git a/src/items.rs b/src/items.rs index 72954513908..bd1a83d5a66 100644 --- a/src/items.rs +++ b/src/items.rs @@ -142,7 +142,8 @@ impl<'a> Item<'a> { keyword: "", abi: format_abi(fm.abi, config.force_explicit_abi(), true), vis: None, - body: fm.items + body: fm + .items .iter() .map(|i| BodyElement::ForeignItem(i)) .collect(), @@ -1725,7 +1726,8 @@ fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { if is_named_arg(self) { - let mut result = self.pat + let mut result = self + .pat .rewrite(context, Shape::legacy(shape.width, shape.indent))?; if !is_empty_infer(context, &*self.ty) { @@ -1738,7 +1740,8 @@ impl Rewrite for ast::Arg { } let overhead = last_line_width(&result); let max_width = shape.width.checked_sub(overhead)?; - let ty_str = self.ty + let ty_str = self + .ty .rewrite(context, Shape::legacy(max_width, shape.indent))?; result.push_str(&ty_str); } @@ -1876,7 +1879,8 @@ fn rewrite_fn_base( // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. - let ret_str = fd.output + let ret_str = fd + .output .rewrite(context, Shape::indented(indent, context.config))?; let multi_line_ret_str = ret_str.contains('\n'); @@ -2034,7 +2038,8 @@ fn rewrite_fn_base( if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = fd.output + let ret_str = fd + .output .rewrite(context, Shape::indented(ret_indent, context.config))?; result.push_str(&ret_str); } else { @@ -2151,7 +2156,8 @@ fn rewrite_args( variadic: bool, generics_str_contains_newline: bool, ) -> Option { - let mut arg_item_strs = args.iter() + let mut arg_item_strs = args + .iter() .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) .collect::>>()?; diff --git a/src/lib.rs b/src/lib.rs index e8bd331f968..73c3fdd48c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -165,7 +165,8 @@ impl FormattingError { match self.kind { ErrorKind::LineOverflow(found, max) => (max, found - max), ErrorKind::TrailingWhitespace => { - let trailing_ws_start = self.line_buffer + let trailing_ws_start = self + .line_buffer .rfind(|c: char| !c.is_whitespace()) .map(|pos| pos + 1) .unwrap_or(0); diff --git a/src/lists.rs b/src/lists.rs index 433beac44ee..b3264487cfe 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -96,17 +96,20 @@ impl ListItem { pub fn is_different_group(&self) -> bool { self.inner_as_ref().contains('\n') || self.pre_comment.is_some() - || self.post_comment + || self + .post_comment .as_ref() .map_or(false, |s| s.contains('\n')) } pub fn is_multiline(&self) -> bool { self.inner_as_ref().contains('\n') - || self.pre_comment + || self + .pre_comment .as_ref() .map_or(false, |s| s.contains('\n')) - || self.post_comment + || self + .post_comment .as_ref() .map_or(false, |s| s.contains('\n')) } @@ -115,7 +118,8 @@ impl ListItem { self.pre_comment .as_ref() .map_or(false, |comment| comment.trim_left().starts_with("//")) - || self.post_comment + || self + .post_comment .as_ref() .map_or(false, |comment| comment.trim_left().starts_with("//")) } @@ -517,7 +521,8 @@ where self.inner.next().map(|item| { let mut new_lines = false; // Pre-comment - let pre_snippet = self.snippet_provider + let pre_snippet = self + .snippet_provider .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap(); let trimmed_pre_snippet = pre_snippet.trim(); @@ -555,7 +560,8 @@ where Some(next_item) => (self.get_lo)(next_item), None => self.next_span_start, }; - let post_snippet = self.snippet_provider + let post_snippet = self + .snippet_provider .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) .unwrap(); diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b27ef9b8769..1a5c6d4f2e6 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -291,7 +291,8 @@ impl<'a> FmtVisitor<'a> { i += offset; if c == '\n' { - let skip_this_line = !self.config + let skip_this_line = !self + .config .file_lines() .contains_line(file_name, status.cur_line); if skip_this_line { diff --git a/src/overflow.rs b/src/overflow.rs index 977dbbbb5f4..a8ef66b0e3c 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -184,7 +184,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { } fn items_span(&self) -> Span { - let span_lo = self.context + let span_lo = self + .context .snippet_provider .span_after(self.span, self.prefix); mk_sp(span_lo, self.span.hi()) @@ -288,7 +289,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { // formatted code, where a prefix or a suffix being left on its own // line. Here we explicitlly check those cases. if count_newlines(overflowed) == 1 { - let rw = self.items + let rw = self + .items .last() .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape)); let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n')); @@ -305,7 +307,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { list_items[self.items.len() - 1].item = placeholder; } _ if self.items.len() >= 1 => { - list_items[self.items.len() - 1].item = self.items + list_items[self.items.len() - 1].item = self + .items .last() .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape)); @@ -427,7 +430,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { } else { first_line_width(items_str) + (paren_overhead / 2) }; - let nested_indent_str = self.nested_shape + let nested_indent_str = self + .nested_shape .indent .to_string_with_newline(self.context.config); let indent_str = shape diff --git a/src/patterns.rs b/src/patterns.rs index b4865ad329e..99edf9ba774 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -167,7 +167,8 @@ impl Rewrite for Pat { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), - PatKind::Paren(ref pat) => pat.rewrite(context, shape.offset_left(1)?.sub_width(1)?) + PatKind::Paren(ref pat) => pat + .rewrite(context, shape.offset_left(1)?.sub_width(1)?) .map(|inner_pat| format!("({})", inner_pat)), } } diff --git a/src/test/mod.rs b/src/test/mod.rs index 06fd1e5a98f..e57a94af8c3 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -628,7 +628,8 @@ impl ConfigurationSection { Some((i, line)) => { if line.starts_with("```rust") { // Get the lines of the code block. - let lines: Vec = file.map(|(_i, l)| l) + let lines: Vec = file + .map(|(_i, l)| l) .take_while(|l| !l.starts_with("```")) .collect(); let block = format!("{}\n", lines.join("\n")); @@ -699,7 +700,8 @@ impl ConfigCodeBlock { assert!(self.code_block.is_some() && self.code_block_start.is_some()); // See if code block begins with #![rustfmt_skip]. - let fmt_skip = self.code_block + let fmt_skip = self + .code_block .as_ref() .unwrap() .split('\n') diff --git a/src/types.rs b/src/types.rs index 6ffb9cd5c7e..47a52281e28 100644 --- a/src/types.rs +++ b/src/types.rs @@ -234,7 +234,8 @@ fn rewrite_segment( || !data.types.is_empty() || !data.bindings.is_empty() => { - let param_list = data.lifetimes + let param_list = data + .lifetimes .iter() .map(SegmentParam::LifeTime) .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) @@ -574,7 +575,8 @@ impl Rewrite for ast::PolyTraitRef { { // 6 is "for<> ".len() let extra_offset = lifetime_str.len() + 6; - let path_str = self.trait_ref + let path_str = self + .trait_ref .rewrite(context, shape.offset_left(extra_offset)?)?; Some( @@ -717,7 +719,8 @@ impl Rewrite for ast::Ty { rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(ref it) => it.rewrite(context, shape) + ast::TyKind::ImplTrait(ref it) => it + .rewrite(context, shape) .map(|it_str| format!("impl {}", it_str)), ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), } diff --git a/src/utils.rs b/src/utils.rs index f2bdc45b831..ca8a7ad7814 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -29,7 +29,8 @@ const SKIP_ANNOTATION: &str = "rustfmt_skip"; pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => text.len() + Some(idx) => text + .len() .checked_sub(idx + 1 + shape.used_width()) .unwrap_or(0), None => text.len(), diff --git a/src/visitor.rs b/src/visitor.rs index 71a279d93aa..7f042b1a11b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -687,7 +687,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub fn skip_empty_lines(&mut self, end_pos: BytePos) { - while let Some(pos) = self.snippet_provider + while let Some(pos) = self + .snippet_provider .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") { if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { -- cgit 1.4.1-3-g733a5 From a72be170d7048e4f9d8c14d35b93b05f1cb98dd1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 May 2018 07:32:00 -0700 Subject: Fix rustfmt tests in the Rust repo Two tests were executing `cargo run` but `cargo` is not ambiently available to execute. Instead it's best to execute the rustfmt binary directly, which is always assembled as part of `cargo test`. --- src/test/mod.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 06fd1e5a98f..e2b371c611d 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -11,6 +11,7 @@ extern crate assert_cli; use std::collections::{HashMap, HashSet}; +use std::env; use std::fs; use std::io::{self, BufRead, BufReader, Read}; use std::iter::{Enumerate, Peekable}; @@ -892,14 +893,19 @@ impl Drop for TempFile { } } +fn rustfmt() -> PathBuf { + let mut me = env::current_exe().expect("failed to get current executable"); + me.pop(); // chop of the test name + me.pop(); // chop off `deps` + me.push("rustfmt"); + return me; +} + #[test] fn verify_check_works() { let temp_file = make_temp_file("temp_check.rs"); assert_cli::Assert::command(&[ - "cargo", - "run", - "--bin=rustfmt", - "--", + rustfmt().to_str().unwrap(), "--write-mode=check", temp_file.path.to_str().unwrap(), ]).succeeds() @@ -910,10 +916,7 @@ fn verify_check_works() { fn verify_diff_works() { let temp_file = make_temp_file("temp_diff.rs"); assert_cli::Assert::command(&[ - "cargo", - "run", - "--bin=rustfmt", - "--", + rustfmt().to_str().unwrap(), "--write-mode=diff", temp_file.path.to_str().unwrap(), ]).succeeds() -- cgit 1.4.1-3-g733a5 From 4c9ef93df7e7984bbe1077aa3c24ae538fa0a42c Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Tue, 8 May 2018 20:31:33 +0200 Subject: fix: Don't insert an extra brace in macros with native newlines Due to `format_snippet` formatting the input with \r\n the subtraction would wouldn't give a length that removed the } Fixes #2641 --- src/lib.rs | 2 +- tests/config/issue-2641.toml | 1 + tests/source/issue-2641.rs | 3 +++ tests/target/issue-2641.rs | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/config/issue-2641.toml create mode 100644 tests/source/issue-2641.rs create mode 100644 tests/target/issue-2641.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index e8bd331f968..80b0764e513 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -645,7 +645,7 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option // then unindent the whole code block. let formatted = format_snippet(&snippet, config)?; // 2 = "}\n" - let block_len = formatted.len().checked_sub(2).unwrap_or(0); + let block_len = formatted.rfind('}').unwrap_or(formatted.len()); let mut is_indented = true; for (kind, ref line) in LineClasses::new(&formatted[FN_MAIN_PREFIX.len()..block_len]) { if !is_first { diff --git a/tests/config/issue-2641.toml b/tests/config/issue-2641.toml new file mode 100644 index 00000000000..11c9dca8a06 --- /dev/null +++ b/tests/config/issue-2641.toml @@ -0,0 +1 @@ +newline_style = "Windows" diff --git a/tests/source/issue-2641.rs b/tests/source/issue-2641.rs new file mode 100644 index 00000000000..c7ad60674fd --- /dev/null +++ b/tests/source/issue-2641.rs @@ -0,0 +1,3 @@ +macro_rules! a { + () => {{}} +} diff --git a/tests/target/issue-2641.rs b/tests/target/issue-2641.rs new file mode 100644 index 00000000000..fbf5326c330 --- /dev/null +++ b/tests/target/issue-2641.rs @@ -0,0 +1,3 @@ +macro_rules! a { + () => {{}}; +} -- cgit 1.4.1-3-g733a5 From 47742807f7c4078d8f78d752b647239b6b136117 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 8 May 2018 18:04:43 -0700 Subject: Ensure tests pass on the beta compiler Also add a travis matrix entry for emulating the beta tests --- .travis.yml | 5 +++++ src/test/mod.rs | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'src') diff --git a/.travis.yml b/.travis.yml index 90faaaf1746..47f5e4eb25d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,11 @@ cache: directories: - $HOME/.cargo +matrix: + include: + # Make sure tests will pass on beta + - env: CFG_RELEASE_CHANNEL=beta + addons: apt: packages: diff --git a/src/test/mod.rs b/src/test/mod.rs index e2b371c611d..28161e89f35 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -191,6 +191,10 @@ fn assert_output(source: &Path, expected_filename: &Path) { // rustfmt. #[test] fn idempotence_tests() { + match option_env!("CFG_RELEASE_CHANNEL") { + None | Some("nightly") => {} + _ => return, // these tests require nightly + } // Get all files in the tests/target directory. let files = get_test_files(Path::new("tests/target"), true); let (_reports, count, fails) = check_files(files, None); -- cgit 1.4.1-3-g733a5 From 55ac062da038a4bd160cfc875dc92e6d888be2db Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 May 2018 13:50:30 +1200 Subject: Add `--quiet` flag, remove `Plain` write mode cc #1976 --- src/bin/main.rs | 17 +++++++++-------- src/config/mod.rs | 15 ++++++++------- src/config/options.rs | 23 ++++++++++++++++++++--- src/filemap.rs | 9 ++++----- src/lib.rs | 11 +++++------ 5 files changed, 46 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index b7bb92c858f..9577d041388 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -25,10 +25,9 @@ use failure::err_msg; use getopts::{Matches, Options}; use rustfmt::{ - emit_post_matter, emit_pre_matter, load_config, CliOptions, Config, FmtResult, WriteMode, - WRITE_MODE_LIST, + emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Config, + FileName, FmtResult, Input, Summary, Verbosity, WriteMode, WRITE_MODE_LIST, }; -use rustfmt::{format_and_emit_report, FileName, Input, Summary}; fn main() { env_logger::init(); @@ -144,6 +143,7 @@ fn make_opts() -> Options { "Enables unstable features. Only available on nightly channel", ); opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("q", "quiet", "Print less output"); opts.optflag("V", "version", "Show version information"); opts.optopt( "", @@ -187,8 +187,9 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { let options = CliOptions::from_matches(&matches)?; let (mut config, _) = load_config(Some(Path::new(".")), Some(&options))?; - // write_mode is always Plain for Stdin. - config.set().write_mode(WriteMode::Plain); + // write_mode is always Display for Stdin. + config.set().write_mode(WriteMode::Display); + config.set().verbose(Verbosity::Quiet); // parse file_lines if let Some(ref file_lines) = matches.opt_str("file-lines") { @@ -211,7 +212,7 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { } emit_post_matter(&config)?; - Ok((WriteMode::Plain, error_summary)) + Ok((WriteMode::Display, error_summary)) } Operation::Format { files, @@ -231,7 +232,7 @@ fn format( options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(&options))?; - if config.verbose() { + if config.verbose() == Verbosity::Verbose { if let Some(path) = config_path.as_ref() { println!("Using rustfmt config file {}", path.display()); } @@ -252,7 +253,7 @@ fn format( let local_config = if config_path.is_none() { let (local_config, config_path) = load_config(Some(file.parent().unwrap()), Some(&options))?; - if local_config.verbose() { + if local_config.verbose() == Verbosity::Verbose { if let Some(path) = config_path { println!( "Using rustfmt config file {} for {}", diff --git a/src/config/mod.rs b/src/config/mod.rs index 382e7e7cc92..5f6d9082ce8 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -143,7 +143,7 @@ create_config! { "Skip formatting the specified files and directories."; // Not user-facing - verbose: bool, false, false, "Use verbose output"; + verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user"; verbose_diff: bool, false, false, "Emit verbose diffs"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ @@ -230,7 +230,7 @@ fn config_path(options: &CliOptions) -> Result, Error> { #[cfg(test)] mod test { - use super::Config; + use super::*; use std::str; #[allow(dead_code)] @@ -249,7 +249,8 @@ mod test { "Require a specific version of rustfmt."; ignore: IgnoreList, IgnoreList::default(), false, "Skip formatting the specified files and directories."; - verbose: bool, false, false, "Use verbose output"; + verbose: Verbosity, Verbosity::Normal, false, + "How much to information to emit to the user"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; @@ -265,10 +266,10 @@ mod test { #[test] fn test_config_set() { let mut config = Config::default(); - config.set().verbose(false); - assert_eq!(config.verbose(), false); - config.set().verbose(true); - assert_eq!(config.verbose(), true); + config.set().verbose(Verbosity::Quiet); + assert_eq!(config.verbose(), Verbosity::Quiet); + config.set().verbose(Verbosity::Normal); + assert_eq!(config.verbose(), Verbosity::Normal); } #[test] diff --git a/src/config/options.rs b/src/config/options.rs index bd8823f9ce4..e18c88c3027 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -185,8 +185,6 @@ configuration_option_enum! { WriteMode: // Displays how much of the input file was processed Coverage, // Unfancy stdout - Plain, - // Outputs a checkstyle XML file. Checkstyle, // Output the changed lines (for internal value only) Modified, @@ -207,6 +205,14 @@ configuration_option_enum! { Color: Auto, } +configuration_option_enum! { Verbosity: + // Emit more. + Verbose, + Normal, + // Emit as little as possible. + Quiet, +} + #[derive(Deserialize, Serialize, Clone, Debug)] pub struct WidthHeuristics { // Maximum width of the args of a function call before falling back @@ -322,6 +328,7 @@ impl ::std::str::FromStr for IgnoreList { #[derive(Clone, Debug, Default)] pub struct CliOptions { skip_children: Option, + quiet: bool, verbose: bool, verbose_diff: bool, pub(super) config_path: Option, @@ -336,6 +343,10 @@ impl CliOptions { pub fn from_matches(matches: &Matches) -> FmtResult { let mut options = CliOptions::default(); options.verbose = matches.opt_present("verbose"); + options.quiet = matches.opt_present("quiet"); + if options.verbose && options.quiet { + return Err(format_err!("Can't use both `--verbose` and `--quiet`")); + } options.verbose_diff = matches.opt_present("verbose-diff"); let unstable_features = matches.opt_present("unstable-features"); @@ -386,7 +397,13 @@ impl CliOptions { } pub fn apply_to(self, config: &mut Config) { - config.set().verbose(self.verbose); + if self.verbose { + config.set().verbose(Verbosity::Verbose); + } else if self.quiet { + config.set().verbose(Verbosity::Quiet); + } else { + config.set().verbose(Verbosity::Normal); + } config.set().verbose_diff(self.verbose_diff); config.set().file_lines(self.file_lines); config.set().unstable_features(self.unstable_features); diff --git a/src/filemap.rs b/src/filemap.rs index f7491893512..fc86beeede4 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -15,7 +15,7 @@ use std::io::{self, BufWriter, Read, Write}; use std::path::Path; use checkstyle::output_checkstyle_file; -use config::{Config, NewlineStyle, WriteMode}; +use config::{Config, NewlineStyle, Verbosity, WriteMode}; use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; use syntax::codemap::FileName; @@ -150,11 +150,10 @@ where write_system_newlines(file, text, config)?; } } - WriteMode::Plain => { - write_system_newlines(out, text, config)?; - } WriteMode::Display | WriteMode::Coverage => { - println!("{}:\n", filename); + if config.verbose() != Verbosity::Quiet { + println!("{}:\n", filename); + } write_system_newlines(out, text, config)?; } WriteMode::Diff => { diff --git a/src/lib.rs b/src/lib.rs index 48c9295c4f9..115b21f4b11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,7 +64,7 @@ use visitor::{FmtVisitor, SnippetProvider}; pub use config::options::CliOptions; pub use config::summary::Summary; -pub use config::{file_lines, load_config, Config, WriteMode}; +pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; pub type FmtResult = std::result::Result; @@ -331,7 +331,7 @@ fn should_emit_verbose(path: &FileName, config: &Config, f: F) where F: Fn(), { - if config.verbose() && path.to_string() != STDIN { + if config.verbose() == Verbosity::Verbose && path.to_string() != STDIN { f(); } } @@ -351,9 +351,7 @@ where // diff mode: check if any files are differing let mut has_diff = false; - // We always skip children for the "Plain" write mode, since there is - // nothing to distinguish the nested module contents. - let skip_children = config.skip_children() || config.write_mode() == config::WriteMode::Plain; + let skip_children = config.skip_children(); for (path, module) in modules::list_files(krate, parse_session.codemap())? { if (skip_children && path != *main_file) || config.ignore().skip_file(&path) { continue; @@ -603,7 +601,8 @@ pub fn format_snippet(snippet: &str, config: &Config) -> Option { let mut out: Vec = Vec::with_capacity(snippet.len() * 2); let input = Input::Text(snippet.into()); let mut config = config.clone(); - config.set().write_mode(config::WriteMode::Plain); + config.set().write_mode(config::WriteMode::Display); + config.set().verbose(Verbosity::Quiet); config.set().hide_parse_errors(true); match format_input(input, &config, Some(&mut out)) { // `format_input()` returns an empty string on parsing error. -- cgit 1.4.1-3-g733a5 From 1869888b1aac51d2d0fa423869b7e76967b7f2c7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 May 2018 13:58:34 +1200 Subject: Remove `--verbose-diff` Use `--verbose` instead cc #1976 --- src/bin/main.rs | 5 ----- src/config/mod.rs | 1 - src/config/options.rs | 3 --- src/rustfmt_diff.rs | 8 ++++++-- 4 files changed, 6 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 9577d041388..dba319f44af 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -130,11 +130,6 @@ fn make_opts() -> Options { "Format specified line ranges. See README for more detail on the JSON format.", "JSON", ); - opts.optflag( - "", - "verbose-diff", - "Emit a more verbose diff, indicating the end of lines.", - ); opts.optflag("h", "help", "Show this message"); opts.optflag("", "skip-children", "Don't reformat child modules"); opts.optflag( diff --git a/src/config/mod.rs b/src/config/mod.rs index 5f6d9082ce8..ac81ded5f76 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -144,7 +144,6 @@ create_config! { // Not user-facing verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user"; - verbose_diff: bool, false, false, "Emit verbose diffs"; file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; diff --git a/src/config/options.rs b/src/config/options.rs index e18c88c3027..a11e1f01eaf 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -330,7 +330,6 @@ pub struct CliOptions { skip_children: Option, quiet: bool, verbose: bool, - verbose_diff: bool, pub(super) config_path: Option, write_mode: Option, color: Option, @@ -347,7 +346,6 @@ impl CliOptions { if options.verbose && options.quiet { return Err(format_err!("Can't use both `--verbose` and `--quiet`")); } - options.verbose_diff = matches.opt_present("verbose-diff"); let unstable_features = matches.opt_present("unstable-features"); let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") @@ -404,7 +402,6 @@ impl CliOptions { } else { config.set().verbose(Verbosity::Normal); } - config.set().verbose_diff(self.verbose_diff); config.set().file_lines(self.file_lines); config.set().unstable_features(self.unstable_features); if let Some(skip_children) = self.skip_children { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 178ed99f696..f2acc96a8de 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::{Color, Config}; +use config::{Color, Config, Verbosity}; use diff; use std::collections::VecDeque; use std::io; @@ -154,7 +154,11 @@ where F: Fn(u32) -> String, { let color = config.color(); - let line_terminator = if config.verbose_diff() { "⏎" } else { "" }; + let line_terminator = if config.verbose() == Verbosity::Verbose { + "⏎" + } else { + "" + }; let mut writer = OutputWriter::new(color); -- cgit 1.4.1-3-g733a5 From 798bffb8b1e24b05a93745db14ce287d5ecddef6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 May 2018 20:12:16 +1200 Subject: `--help` options cc #1976 --- src/bin/main.rs | 74 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index dba319f44af..2dc9657a020 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -67,11 +67,9 @@ enum Operation { minimal_config_path: Option, }, /// Print the help message. - Help, + Help(HelpOp), // Print version information Version, - /// Print detailed configuration help. - ConfigHelp, /// Output default config to a file, or stdout if None ConfigOutputDefault { path: Option, @@ -82,6 +80,13 @@ enum Operation { }, } +/// Arguments to `--help` +enum HelpOp { + None, + Config, + FileLines, +} + fn make_opts() -> Options { let mut opts = Options::new(); @@ -92,11 +97,6 @@ fn make_opts() -> Options { "Use colored output (if supported)", "[always|never|auto]", ); - opts.optflag( - "", - "config-help", - "Show details of rustfmt configuration options", - ); opts.optopt( "", "config-path", @@ -130,7 +130,12 @@ fn make_opts() -> Options { "Format specified line ranges. See README for more detail on the JSON format.", "JSON", ); - opts.optflag("h", "help", "Show this message"); + opts.optflagopt( + "h", + "help", + "Show this message or help about a specific topic: config or file-lines", + "=TOPIC", + ); opts.optflag("", "skip-children", "Don't reformat child modules"); opts.optflag( "", @@ -154,17 +159,21 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { let matches = opts.parse(env::args().skip(1))?; match determine_operation(&matches)? { - Operation::Help => { + Operation::Help(HelpOp::None) => { print_usage_to_stdout(opts, ""); Summary::print_exit_codes(); Ok((WriteMode::None, Summary::default())) } - Operation::Version => { - print_version(); + Operation::Help(HelpOp::Config) => { + Config::print_docs(&mut stdout(), matches.opt_present("unstable-features")); Ok((WriteMode::None, Summary::default())) } - Operation::ConfigHelp => { - Config::print_docs(&mut stdout(), matches.opt_present("unstable-features")); + Operation::Help(HelpOp::FileLines) => { + print_help_file_lines(); + Ok((WriteMode::None, Summary::default())) + } + Operation::Version => { + print_version(); Ok((WriteMode::None, Summary::default())) } Operation::ConfigOutputDefault { path } => { @@ -298,6 +307,27 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) { println!("{}", opts.usage(&msg)); } +fn print_help_file_lines() { + println!("If you want to restrict reformatting to specific sets of lines, you can +use the `--file-lines` option. Its argument is a JSON array of objects +with `file` and `range` properties, where `file` is a file name, and +`range` is an array representing a range of lines like `[7,13]`. Ranges +are 1-based and inclusive of both end points. Specifying an empty array +will result in no files being formatted. For example, + +``` +rustfmt --file-lines '[ + {{\"file\":\"src/lib.rs\",\"range\":[7,13]}}, + {{\"file\":\"src/lib.rs\",\"range\":[21,29]}}, + {{\"file\":\"src/foo.rs\",\"range\":[10,11]}}, + {{\"file\":\"src/foo.rs\",\"range\":[15,15]}}]' +``` + +would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`, +and `15` of `src/foo.rs`. No other files would be formatted, even if they +are included as out of line modules from `src/lib.rs`."); +} + fn print_version() { let version_info = format!( "{}-{}", @@ -310,11 +340,17 @@ fn print_version() { fn determine_operation(matches: &Matches) -> FmtResult { if matches.opt_present("h") { - return Ok(Operation::Help); - } - - if matches.opt_present("config-help") { - return Ok(Operation::ConfigHelp); + let topic = matches.opt_str("h"); + if topic == None { + return Ok(Operation::Help(HelpOp::None)); + } else if topic == Some("config".to_owned()) { + return Ok(Operation::Help(HelpOp::Config)); + } else if topic == Some("file-lines".to_owned()) { + return Ok(Operation::Help(HelpOp::FileLines)); + } else { + println!("Unknown help topic: `{}`\n", topic.unwrap()); + return Ok(Operation::Help(HelpOp::None)); + } } if matches.opt_present("dump-default-config") { -- cgit 1.4.1-3-g733a5 From 4d9de48e06e5448136d216a5bb60f53568e1a9d0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 May 2018 20:26:00 +1200 Subject: Add `--check` flag. cc #1976 --- src/bin/main.rs | 12 ++++++++++-- src/config/options.rs | 9 ++++++++- src/lib.rs | 3 +-- 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 2dc9657a020..f01c260adff 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -91,6 +91,12 @@ fn make_opts() -> Options { let mut opts = Options::new(); // Sorted in alphabetical order. + opts.optflag( + "", + "check", + "Run in 'check' mode. Exits with 0 if input if formatted correctly. Exits \ + with 1 and prints a diff if formatting is required.", + ); opts.optopt( "", "color", @@ -308,7 +314,8 @@ fn print_usage_to_stdout(opts: &Options, reason: &str) { } fn print_help_file_lines() { - println!("If you want to restrict reformatting to specific sets of lines, you can + println!( + "If you want to restrict reformatting to specific sets of lines, you can use the `--file-lines` option. Its argument is a JSON array of objects with `file` and `range` properties, where `file` is a file name, and `range` is an array representing a range of lines like `[7,13]`. Ranges @@ -325,7 +332,8 @@ rustfmt --file-lines '[ would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`, and `15` of `src/foo.rs`. No other files would be formatted, even if they -are included as out of line modules from `src/lib.rs`."); +are included as out of line modules from `src/lib.rs`." + ); } fn print_version() { diff --git a/src/config/options.rs b/src/config/options.rs index a11e1f01eaf..be3aa1f13d4 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -332,6 +332,7 @@ pub struct CliOptions { verbose: bool, pub(super) config_path: Option, write_mode: Option, + check: bool, color: Option, file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, @@ -361,7 +362,11 @@ impl CliOptions { options.config_path = matches.opt_str("config-path").map(PathBuf::from); + options.check = matches.opt_present("check"); if let Some(ref write_mode) = matches.opt_str("write-mode") { + if options.check { + return Err(format_err!("Invalid to set write-mode and `--check`")); + } if let Ok(write_mode) = WriteMode::from_str(write_mode) { options.write_mode = Some(write_mode); } else { @@ -410,7 +415,9 @@ impl CliOptions { if let Some(error_on_unformatted) = self.error_on_unformatted { config.set().error_on_unformatted(error_on_unformatted); } - if let Some(write_mode) = self.write_mode { + if self.check { + config.set().write_mode(WriteMode::Check); + } else if let Some(write_mode) = self.write_mode { config.set().write_mode(write_mode); } if let Some(color) = self.color { diff --git a/src/lib.rs b/src/lib.rs index 115b21f4b11..98983da1164 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,8 +68,7 @@ pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; pub type FmtResult = std::result::Result; -pub const WRITE_MODE_LIST: &str = - "[replace|overwrite|display|plain|diff|coverage|checkstyle|check]"; +pub const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle]"; #[macro_use] mod utils; -- cgit 1.4.1-3-g733a5 From eca7796fb1cd8866189e273f7e5d1df5585b269e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 May 2018 20:43:08 +1200 Subject: Replace `--dump-minimal-config` and `--dump-default-config` with `--print-config` cc #1976 --- src/bin/main.rs | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index f01c260adff..ee17c024e69 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -110,20 +110,6 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); - opts.opt( - "", - "dump-default-config", - "Dumps default configuration to PATH. PATH defaults to stdout, if omitted.", - "PATH", - getopts::HasArg::Maybe, - getopts::Occur::Optional, - ); - opts.optopt( - "", - "dump-minimal-config", - "Dumps configuration options that were checked during formatting to a file.", - "PATH", - ); opts.optflag( "", "error-on-unformatted", @@ -142,6 +128,13 @@ fn make_opts() -> Options { "Show this message or help about a specific topic: config or file-lines", "=TOPIC", ); + opts.optopt( + "", + "print-config", + "Dumps a default or minimal config to PATH. A minimal config is the \ + subset of the current config file used for formatting the current program.", + "[minimal|default] PATH", + ); opts.optflag("", "skip-children", "Don't reformat child modules"); opts.optflag( "", @@ -361,19 +354,17 @@ fn determine_operation(matches: &Matches) -> FmtResult { } } - if matches.opt_present("dump-default-config") { - // NOTE for some reason when configured with HasArg::Maybe + Occur::Optional opt_default - // doesn't recognize `--foo bar` as a long flag with an argument but as a long flag with no - // argument *plus* a free argument. Thus we check for that case in this branch -- this is - // required for backward compatibility. - if let Some(path) = matches.free.get(0) { - return Ok(Operation::ConfigOutputDefault { - path: Some(path.clone()), - }); - } else { - return Ok(Operation::ConfigOutputDefault { - path: matches.opt_str("dump-default-config"), - }); + let mut minimal_config_path = None; + if matches.opt_present("print-config") { + let kind = matches.opt_str("print-config"); + let path = matches.free.get(0); + if kind == "default" { + return Ok(Operation::ConfigOutputDefault { path: path.clone() }); + } else if kind = "minimal" { + minimal_config_path = path; + if minimal_config_path.is_none() { + println!("WARNING: PATH required for `--print-config minimal`"); + } } } @@ -381,9 +372,6 @@ fn determine_operation(matches: &Matches) -> FmtResult { return Ok(Operation::Version); } - // If no path is given, we won't output a minimal config. - let minimal_config_path = matches.opt_str("dump-minimal-config"); - // if no file argument is supplied, read from stdin if matches.free.is_empty() { let mut buffer = String::new(); -- cgit 1.4.1-3-g733a5 From 1b1eccc5535ba61204af6bc9e29fc2be5a4aec03 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 12 May 2018 10:36:34 +0900 Subject: Fix build failure (#2699) --- src/bin/main.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index ee17c024e69..00a582cb3cb 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -355,12 +355,11 @@ fn determine_operation(matches: &Matches) -> FmtResult { } let mut minimal_config_path = None; - if matches.opt_present("print-config") { - let kind = matches.opt_str("print-config"); - let path = matches.free.get(0); + if let Some(ref kind) = matches.opt_str("print-config") { + let path = matches.free.get(0).cloned(); if kind == "default" { - return Ok(Operation::ConfigOutputDefault { path: path.clone() }); - } else if kind = "minimal" { + return Ok(Operation::ConfigOutputDefault { path }); + } else if kind == "minimal" { minimal_config_path = path; if minimal_config_path.is_none() { println!("WARNING: PATH required for `--print-config minimal`"); -- cgit 1.4.1-3-g733a5 From 1c1763c7ae2deb740dd58d5832ccb5c2c6c54472 Mon Sep 17 00:00:00 2001 From: Pazzaz Date: Sat, 12 May 2018 10:53:06 +0200 Subject: Remove unnecessary use of Box in `format_function_type` --- src/types.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 47a52281e28..3c2a2287d5c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -305,7 +305,7 @@ where T: Deref, ::Target: Rewrite + Spanned, { - Regular(Box), + Regular(T), Variadic(BytePos), } @@ -332,11 +332,7 @@ where let list_lo = context.snippet_provider.span_after(span, "("); let items = itemize_list( context.snippet_provider, - // FIXME Would be nice to avoid this allocation, - // but I couldn't get the types to work out. - inputs - .map(|i| ArgumentKind::Regular(Box::new(i))) - .chain(variadic_arg), + inputs.map(ArgumentKind::Regular).chain(variadic_arg), ")", ",", |arg| match *arg { -- cgit 1.4.1-3-g733a5 From 8396da188251ae8d6d2970a497ecdf07bf4ef04f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 13 May 2018 13:18:08 +1200 Subject: Add `--backup` flag --- src/bin/main.rs | 1 + src/config/options.rs | 6 +++++- src/lib.rs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 00a582cb3cb..c903ba18561 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -91,6 +91,7 @@ fn make_opts() -> Options { let mut opts = Options::new(); // Sorted in alphabetical order. + opts.optflag("", "backup", "Backup any modified files."); opts.optflag( "", "check", diff --git a/src/config/options.rs b/src/config/options.rs index be3aa1f13d4..b3c0acb854e 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -368,7 +368,11 @@ impl CliOptions { return Err(format_err!("Invalid to set write-mode and `--check`")); } if let Ok(write_mode) = WriteMode::from_str(write_mode) { - options.write_mode = Some(write_mode); + if write_mode == WriteMode::Overwrite && matches.opt_present("backup") { + options.write_mode = Some(WriteMode::Replace); + } else { + options.write_mode = Some(write_mode); + } } else { return Err(format_err!( "Invalid write-mode: {}, expected one of {}", diff --git a/src/lib.rs b/src/lib.rs index 98983da1164..e30f4d586bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,7 +68,7 @@ pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; pub type FmtResult = std::result::Result; -pub const WRITE_MODE_LIST: &str = "[replace|overwrite|display|plain|diff|coverage|checkstyle]"; +pub const WRITE_MODE_LIST: &str = "[overwrite|display|plain|diff|coverage|checkstyle]"; #[macro_use] mod utils; -- cgit 1.4.1-3-g733a5 From 5d9f5aa05a668e7dfef87b46d89dad2884df9d41 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sun, 13 May 2018 14:13:24 +1200 Subject: Replace `--write-mode` with `--emit` cc #1976 --- README.md | 51 ++++++--------------------------------------------- bootstrap.sh | 8 ++++---- src/bin/main.rs | 11 +++-------- src/config/options.rs | 20 +++++++++++++++----- src/config/summary.rs | 2 +- src/lib.rs | 3 ++- src/test/mod.rs | 13 +------------ 7 files changed, 32 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 4322901d18a..6dc437fd27f 100644 --- a/README.md +++ b/README.md @@ -105,53 +105,14 @@ just need to run on the root file (usually mod.rs or lib.rs). Rustfmt can also read data from stdin. Alternatively, you can use `cargo fmt` to format all binary and library targets of your crate. -You'll probably want to specify the write mode. Currently, there are modes for -`check`, `diff`, `replace`, `overwrite`, `display`, `coverage`, `checkstyle`, and `plain`. - -* `overwrite` Is the default and overwrites the original files _without_ creating backups. -* `replace` Overwrites the original files after creating backups of the files. -* `display` Will print the formatted files to stdout. -* `plain` Also writes to stdout, but with no metadata. -* `diff` Will print a diff between the original files and formatted files to stdout. -* `check` Checks if the program's formatting matches what rustfmt would do. Silently exits - with code 0 if so, emits a diff and exits with code 1 if not. This option is - designed to be run in CI-like where a non-zero exit signifies incorrect formatting. -* `checkstyle` Will output the lines that need to be corrected as a checkstyle XML file, - that can be used by tools like Jenkins. - -The write mode can be set by passing the `--write-mode` flag on -the command line. For example `rustfmt --write-mode=display src/filename.rs` - -`cargo fmt` uses `--write-mode=overwrite` by default. - -If you want to restrict reformatting to specific sets of lines, you can -use the `--file-lines` option. Its argument is a JSON array of objects -with `file` and `range` properties, where `file` is a file name, and -`range` is an array representing a range of lines like `[7,13]`. Ranges -are 1-based and inclusive of both end points. Specifying an empty array -will result in no files being formatted. For example, +You can run `rustfmt --help` for information about argument. -``` -rustfmt --file-lines '[ - {"file":"src/lib.rs","range":[7,13]}, - {"file":"src/lib.rs","range":[21,29]}, - {"file":"src/foo.rs","range":[10,11]}, - {"file":"src/foo.rs","range":[15,15]}]' -``` - -would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`, -and `15` of `src/foo.rs`. No other files would be formatted, even if they -are included as out of line modules from `src/lib.rs`. - -If `rustfmt` successfully reformatted the code it will exit with `0` exit -status. Exit status `1` signals some unexpected error, like an unknown option or -a failure to read a file. Exit status `2` is returned if there are syntax errors -in the input files. `rustfmt` can't format syntactically invalid code. Finally, -exit status `3` is returned if there are some issues which can't be resolved -automatically. For example, if you have a very long comment line `rustfmt` -doesn't split it. Instead it prints a warning and exits with `3`. +When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not +make any formatting changes to the input, and `1` if Rustfmt would make changes. +In other modes, Rustfmt will exit with `1` if there was some error during +formatting (for example a parsing or internal error) and `0` if formatting +completed without error (whether or not changes were made). -You can run `rustfmt --help` for more information. ## Running Rustfmt from your editor diff --git a/bootstrap.sh b/bootstrap.sh index ae37b043c05..05ac0ce2f30 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -6,12 +6,12 @@ cargo build --release -target/release/rustfmt --write-mode=overwrite src/lib.rs -target/release/rustfmt --write-mode=overwrite src/bin/main.rs -target/release/rustfmt --write-mode=overwrite src/cargo-fmt/main.rs +target/release/rustfmt src/lib.rs +target/release/rustfmt src/bin/main.rs +target/release/rustfmt src/cargo-fmt/main.rs for filename in tests/target/*.rs; do if ! grep -q "rustfmt-" "$filename"; then - target/release/rustfmt --write-mode=overwrite $filename + target/release/rustfmt $filename fi done diff --git a/src/bin/main.rs b/src/bin/main.rs index c903ba18561..b8f5225633f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -111,6 +111,7 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); + opts.optopt("", "emit", "What data to emit and how", WRITE_MODE_LIST); opts.optflag( "", "error-on-unformatted", @@ -120,13 +121,13 @@ fn make_opts() -> Options { opts.optopt( "", "file-lines", - "Format specified line ranges. See README for more detail on the JSON format.", + "Format specified line ranges. Run with `--help file-lines` for more detail.", "JSON", ); opts.optflagopt( "h", "help", - "Show this message or help about a specific topic: config or file-lines", + "Show this message or help about a specific topic: `config` or `file-lines`", "=TOPIC", ); opts.optopt( @@ -145,12 +146,6 @@ fn make_opts() -> Options { opts.optflag("v", "verbose", "Print verbose output"); opts.optflag("q", "quiet", "Print less output"); opts.optflag("V", "version", "Show version information"); - opts.optopt( - "", - "write-mode", - "How to write output (not usable when piping from stdin)", - WRITE_MODE_LIST, - ); opts } diff --git a/src/config/options.rs b/src/config/options.rs index b3c0acb854e..e4ba87a88f8 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -363,11 +363,11 @@ impl CliOptions { options.config_path = matches.opt_str("config-path").map(PathBuf::from); options.check = matches.opt_present("check"); - if let Some(ref write_mode) = matches.opt_str("write-mode") { + if let Some(ref emit_str) = matches.opt_str("emit") { if options.check { - return Err(format_err!("Invalid to set write-mode and `--check`")); + return Err(format_err!("Invalid to use `--emit` and `--check`")); } - if let Ok(write_mode) = WriteMode::from_str(write_mode) { + if let Ok(write_mode) = write_mode_from_emit_str(emit_str) { if write_mode == WriteMode::Overwrite && matches.opt_present("backup") { options.write_mode = Some(WriteMode::Replace); } else { @@ -375,8 +375,8 @@ impl CliOptions { } } else { return Err(format_err!( - "Invalid write-mode: {}, expected one of {}", - write_mode, + "Invalid value for `--emit`: {}, expected one of {}", + emit_str, WRITE_MODE_LIST )); } @@ -441,3 +441,13 @@ impl CliOptions { } } } + +fn write_mode_from_emit_str(emit_str: &str) -> FmtResult { + match emit_str { + "files" => Ok(WriteMode::Overwrite), + "stdout" => Ok(WriteMode::Display), + "coverage" => Ok(WriteMode::Coverage), + "checkstyle" => Ok(WriteMode::Checkstyle), + _ => Err(format_err!("Invalid value for `--emit`")), + } +} diff --git a/src/config/summary.rs b/src/config/summary.rs index 9f339b61be7..e436856d286 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -23,7 +23,7 @@ pub struct Summary { // Code is valid, but it is impossible to format it properly. has_formatting_errors: bool, - // Formatted code differs from existing code (write-mode diff only). + // Formatted code differs from existing code (--check only). pub has_diff: bool, // Keeps track of time spent in parsing and formatting steps. diff --git a/src/lib.rs b/src/lib.rs index e30f4d586bd..5fb3e4b03e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,7 +68,8 @@ pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; pub type FmtResult = std::result::Result; -pub const WRITE_MODE_LIST: &str = "[overwrite|display|plain|diff|coverage|checkstyle]"; +// FIXME: this is badly named since the user-facing name is `emit` not `write-mode`. +pub const WRITE_MODE_LIST: &str = "[files|stdout|coverage|checkstyle]"; #[macro_use] mod utils; diff --git a/src/test/mod.rs b/src/test/mod.rs index 631c8076ca7..4de69296e9f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -912,18 +912,7 @@ fn verify_check_works() { let temp_file = make_temp_file("temp_check.rs"); assert_cli::Assert::command(&[ rustfmt().to_str().unwrap(), - "--write-mode=check", - temp_file.path.to_str().unwrap(), - ]).succeeds() - .unwrap(); -} - -#[test] -fn verify_diff_works() { - let temp_file = make_temp_file("temp_diff.rs"); - assert_cli::Assert::command(&[ - rustfmt().to_str().unwrap(), - "--write-mode=diff", + "--check", temp_file.path.to_str().unwrap(), ]).succeeds() .unwrap(); -- cgit 1.4.1-3-g733a5 From 3b23a98d00e753a11fbfa1a43db4e87aed249ce7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 10:20:51 +1200 Subject: Support unstable options cc #1976 --- src/bin/main.rs | 73 ++++++++++++++++++++++++++++----------------------- src/config/options.rs | 52 +++++++++++++++++------------------- 2 files changed, 64 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index b8f5225633f..1b1c1d412c8 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -112,18 +112,6 @@ fn make_opts() -> Options { "[Path for the configuration file]", ); opts.optopt("", "emit", "What data to emit and how", WRITE_MODE_LIST); - opts.optflag( - "", - "error-on-unformatted", - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces", - ); - opts.optopt( - "", - "file-lines", - "Format specified line ranges. Run with `--help file-lines` for more detail.", - "JSON", - ); opts.optflagopt( "h", "help", @@ -137,21 +125,48 @@ fn make_opts() -> Options { subset of the current config file used for formatting the current program.", "[minimal|default] PATH", ); - opts.optflag("", "skip-children", "Don't reformat child modules"); - opts.optflag( - "", - "unstable-features", - "Enables unstable features. Only available on nightly channel", - ); opts.optflag("v", "verbose", "Print verbose output"); opts.optflag("q", "quiet", "Print less output"); opts.optflag("V", "version", "Show version information"); + if is_nightly() { + opts.optflag( + "", + "unstable-features", + "Enables unstable features. Only available on nightly channel.", + ); + opts.optflag( + "", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces (unstable).", + ); + opts.optopt( + "", + "file-lines", + "Format specified line ranges. Run with `--help file-lines` for \ + more detail (unstable).", + "JSON", + ); + opts.optflag( + "", + "skip-children", + "Don't reformat child modules (unstable).", + ); + } + opts } +fn is_nightly() -> bool { + option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false) +} + fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { let matches = opts.parse(env::args().skip(1))?; + let options = CliOptions::from_matches(&matches)?; match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { @@ -160,7 +175,7 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { Ok((WriteMode::None, Summary::default())) } Operation::Help(HelpOp::Config) => { - Config::print_docs(&mut stdout(), matches.opt_present("unstable-features")); + Config::print_docs(&mut stdout(), options.unstable_features); Ok((WriteMode::None, Summary::default())) } Operation::Help(HelpOp::FileLines) => { @@ -183,7 +198,6 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { } Operation::Stdin { input } => { // try to read config from local directory - let options = CliOptions::from_matches(&matches)?; let (mut config, _) = load_config(Some(Path::new(".")), Some(&options))?; // write_mode is always Display for Stdin. @@ -191,15 +205,11 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { config.set().verbose(Verbosity::Quiet); // parse file_lines - if let Some(ref file_lines) = matches.opt_str("file-lines") { - config - .set() - .file_lines(file_lines.parse().map_err(err_msg)?); - for f in config.file_lines().files() { - match *f { - FileName::Custom(ref f) if f == "stdin" => {} - _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), - } + config.set().file_lines(options.file_lines); + for f in config.file_lines().files() { + match *f { + FileName::Custom(ref f) if f == "stdin" => {} + _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), } } @@ -216,10 +226,7 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { Operation::Format { files, minimal_config_path, - } => { - let options = CliOptions::from_matches(&matches)?; - format(files, minimal_config_path, options) - } + } => format(files, minimal_config_path, options), } } diff --git a/src/config/options.rs b/src/config/options.rs index e4ba87a88f8..15915bb9976 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -327,16 +327,16 @@ impl ::std::str::FromStr for IgnoreList { /// Parsed command line options. #[derive(Clone, Debug, Default)] pub struct CliOptions { - skip_children: Option, - quiet: bool, - verbose: bool, - pub(super) config_path: Option, - write_mode: Option, - check: bool, - color: Option, - file_lines: FileLines, // Default is all lines in all files. - unstable_features: bool, - error_on_unformatted: Option, + pub skip_children: Option, + pub quiet: bool, + pub verbose: bool, + pub config_path: Option, + pub write_mode: Option, + pub check: bool, + pub color: Option, + pub file_lines: FileLines, // Default is all lines in all files. + pub unstable_features: bool, + pub error_on_unformatted: Option, } impl CliOptions { @@ -348,16 +348,23 @@ impl CliOptions { return Err(format_err!("Can't use both `--verbose` and `--quiet`")); } - let unstable_features = matches.opt_present("unstable-features"); let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") .map(|c| c == "nightly") .unwrap_or(false); - if unstable_features && !rust_nightly { - return Err(format_err!( - "Unstable features are only available on Nightly channel" - )); - } else { - options.unstable_features = unstable_features; + if rust_nightly { + options.unstable_features = matches.opt_present("unstable-features"); + } + + if options.unstable_features { + if matches.opt_present("skip-children") { + options.skip_children = Some(true); + } + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = Some(true); + } + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse().map_err(err_msg)?; + } } options.config_path = matches.opt_str("config-path").map(PathBuf::from); @@ -389,17 +396,6 @@ impl CliOptions { } } - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse().map_err(err_msg)?; - } - - if matches.opt_present("skip-children") { - options.skip_children = Some(true); - } - if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = Some(true); - } - Ok(options) } -- cgit 1.4.1-3-g733a5 From 6d0695303a97edbf94a7ed605247806af4a9e262 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 10:41:15 +1200 Subject: Make some write modes unstable --- src/bin/main.rs | 12 +++++++++--- src/config/options.rs | 44 +++++++++++++++++++++++++++----------------- src/filemap.rs | 13 ------------- src/lib.rs | 3 --- 4 files changed, 36 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 1b1c1d412c8..03105a90220 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -26,7 +26,7 @@ use getopts::{Matches, Options}; use rustfmt::{ emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Config, - FileName, FmtResult, Input, Summary, Verbosity, WriteMode, WRITE_MODE_LIST, + FileName, FmtResult, Input, Summary, Verbosity, WriteMode, }; fn main() { @@ -111,7 +111,13 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); - opts.optopt("", "emit", "What data to emit and how", WRITE_MODE_LIST); + let is_nightly = is_nightly(); + let emit_opts = if is_nightly { + "[files|stdout|coverage|checkstyle]" + } else { + "[files|stdout]" + }; + opts.optopt("", "emit", "What data to emit and how", emit_opts); opts.optflagopt( "h", "help", @@ -129,7 +135,7 @@ fn make_opts() -> Options { opts.optflag("q", "quiet", "Print less output"); opts.optflag("V", "version", "Show version information"); - if is_nightly() { + if is_nightly { opts.optflag( "", "unstable-features", diff --git a/src/config/options.rs b/src/config/options.rs index 15915bb9976..65915225860 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -14,7 +14,7 @@ use config::config_type::ConfigType; use config::file_lines::FileLines; use config::lists::*; use config::Config; -use {FmtResult, WRITE_MODE_LIST}; +use FmtResult; use failure::err_msg; @@ -174,14 +174,12 @@ configuration_option_enum! { ReportTactic: } configuration_option_enum! { WriteMode: - // Backs the original file up and overwrites the original. - Replace, // Overwrites original file without backup. Overwrite, + // Backs the original file up and overwrites the original. + Replace, // Writes the output to stdout. Display, - // Writes the diff to stdout. - Diff, // Displays how much of the input file was processed Coverage, // Unfancy stdout @@ -196,6 +194,13 @@ configuration_option_enum! { WriteMode: None, } +const STABLE_WRITE_MODES: [WriteMode; 4] = [ + WriteMode::Replace, + WriteMode::Overwrite, + WriteMode::Display, + WriteMode::Check, +]; + configuration_option_enum! { Color: // Always use color, whether it is a piped or terminal output Always, @@ -331,7 +336,7 @@ pub struct CliOptions { pub quiet: bool, pub verbose: bool, pub config_path: Option, - pub write_mode: Option, + pub write_mode: WriteMode, pub check: bool, pub color: Option, pub file_lines: FileLines, // Default is all lines in all files. @@ -355,7 +360,7 @@ impl CliOptions { options.unstable_features = matches.opt_present("unstable-features"); } - if options.unstable_features { + if !options.unstable_features { if matches.opt_present("skip-children") { options.skip_children = Some(true); } @@ -375,16 +380,21 @@ impl CliOptions { return Err(format_err!("Invalid to use `--emit` and `--check`")); } if let Ok(write_mode) = write_mode_from_emit_str(emit_str) { - if write_mode == WriteMode::Overwrite && matches.opt_present("backup") { - options.write_mode = Some(WriteMode::Replace); - } else { - options.write_mode = Some(write_mode); - } + options.write_mode = write_mode; } else { + return Err(format_err!("Invalid value for `--emit`")); + } + } + + if options.write_mode == WriteMode::Overwrite && matches.opt_present("backup") { + options.write_mode = WriteMode::Replace; + } + + if !rust_nightly { + if !STABLE_WRITE_MODES.contains(&options.write_mode) { return Err(format_err!( - "Invalid value for `--emit`: {}, expected one of {}", - emit_str, - WRITE_MODE_LIST + "Invalid value for `--emit` - using an unstable \ + value without `--unstable-features`", )); } } @@ -417,8 +427,8 @@ impl CliOptions { } if self.check { config.set().write_mode(WriteMode::Check); - } else if let Some(write_mode) = self.write_mode { - config.set().write_mode(write_mode); + } else { + config.set().write_mode(self.write_mode); } if let Some(color) = self.color { config.set().color(color); diff --git a/src/filemap.rs b/src/filemap.rs index fc86beeede4..d61a3aa2a74 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -156,19 +156,6 @@ where } write_system_newlines(out, text, config)?; } - WriteMode::Diff => { - let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - let mismatch = make_diff(&ori, &fmt, 3); - let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config, - ); - return Ok(has_diff); - } - } WriteMode::Modified => { let filename = filename_to_path(); if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { diff --git a/src/lib.rs b/src/lib.rs index 5fb3e4b03e3..c50c45fbd36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,9 +68,6 @@ pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; pub type FmtResult = std::result::Result; -// FIXME: this is badly named since the user-facing name is `emit` not `write-mode`. -pub const WRITE_MODE_LIST: &str = "[files|stdout|coverage|checkstyle]"; - #[macro_use] mod utils; -- cgit 1.4.1-3-g733a5 From a3c85cdc41e3622c85a54284c497815a49906eb2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 11:07:54 +1200 Subject: Reorder the --help message --- rustfmt.toml | 2 -- src/bin/main.rs | 59 +++++++++++++++++++++++++-------------------------- src/config/options.rs | 2 +- src/config/summary.rs | 7 ------ 4 files changed, 30 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/rustfmt.toml b/rustfmt.toml index 9b935b0a287..e69de29bb2d 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +0,0 @@ -error_on_line_overflow = true -error_on_unformatted = true diff --git a/src/bin/main.rs b/src/bin/main.rs index 03105a90220..2c7bf5a2445 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -90,27 +90,12 @@ enum HelpOp { fn make_opts() -> Options { let mut opts = Options::new(); - // Sorted in alphabetical order. - opts.optflag("", "backup", "Backup any modified files."); opts.optflag( "", "check", "Run in 'check' mode. Exits with 0 if input if formatted correctly. Exits \ with 1 and prints a diff if formatting is required.", ); - opts.optopt( - "", - "color", - "Use colored output (if supported)", - "[always|never|auto]", - ); - opts.optopt( - "", - "config-path", - "Recursively searches the given path for the rustfmt.toml config file. If not \ - found reverts to the input file path", - "[Path for the configuration file]", - ); let is_nightly = is_nightly(); let emit_opts = if is_nightly { "[files|stdout|coverage|checkstyle]" @@ -118,11 +103,19 @@ fn make_opts() -> Options { "[files|stdout]" }; opts.optopt("", "emit", "What data to emit and how", emit_opts); - opts.optflagopt( - "h", - "help", - "Show this message or help about a specific topic: `config` or `file-lines`", - "=TOPIC", + opts.optflag("", "backup", "Backup any modified files."); + opts.optopt( + "", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ + found reverts to the input file path", + "[Path for the configuration file]", + ); + opts.optopt( + "", + "color", + "Use colored output (if supported)", + "[always|never|auto]", ); opts.optopt( "", @@ -131,9 +124,6 @@ fn make_opts() -> Options { subset of the current config file used for formatting the current program.", "[minimal|default] PATH", ); - opts.optflag("v", "verbose", "Print verbose output"); - opts.optflag("q", "quiet", "Print less output"); - opts.optflag("V", "version", "Show version information"); if is_nightly { opts.optflag( @@ -141,12 +131,6 @@ fn make_opts() -> Options { "unstable-features", "Enables unstable features. Only available on nightly channel.", ); - opts.optflag( - "", - "error-on-unformatted", - "Error if unable to get comments or string literals within max_width, \ - or they are left with trailing whitespaces (unstable).", - ); opts.optopt( "", "file-lines", @@ -154,6 +138,12 @@ fn make_opts() -> Options { more detail (unstable).", "JSON", ); + opts.optflag( + "", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces (unstable).", + ); opts.optflag( "", "skip-children", @@ -161,6 +151,16 @@ fn make_opts() -> Options { ); } + opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("q", "quiet", "Print less output"); + opts.optflag("V", "version", "Show version information"); + opts.optflagopt( + "h", + "help", + "Show this message or help about a specific topic: `config` or `file-lines`", + "=TOPIC", + ); + opts } @@ -177,7 +177,6 @@ fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { print_usage_to_stdout(opts, ""); - Summary::print_exit_codes(); Ok((WriteMode::None, Summary::default())) } Operation::Help(HelpOp::Config) => { diff --git a/src/config/options.rs b/src/config/options.rs index 65915225860..06580339d9e 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -360,7 +360,7 @@ impl CliOptions { options.unstable_features = matches.opt_present("unstable-features"); } - if !options.unstable_features { + if options.unstable_features { if matches.opt_present("skip-children") { options.skip_children = Some(true); } diff --git a/src/config/summary.rs b/src/config/summary.rs index e436856d286..d44c69b04a6 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -102,13 +102,6 @@ impl Summary { self.has_parsing_errors |= other.has_parsing_errors; self.has_diff |= other.has_diff; } - - pub fn print_exit_codes() { - let exit_codes = r#"Exit Codes: - 0 = No errors - 1 = Encountered error in formatting code"#; - println!("{}", exit_codes); - } } #[derive(Clone, Copy, Debug)] -- cgit 1.4.1-3-g733a5 From 7eb8bdbbd29bfc8c781948215e9291d64aa69cf4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 16:04:15 +1200 Subject: Format attributes with paths --- src/attr.rs | 21 ++++++++++++--------- tests/source/attrib.rs | 7 +++++++ tests/target/attrib.rs | 6 ++++++ 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 894b99815b4..e754144a727 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -20,6 +20,7 @@ use expr::rewrite_literal; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use types::{rewrite_path, PathContext}; use utils::{count_newlines, mk_sp}; /// Returns attributes on the given statement. @@ -200,9 +201,11 @@ fn allow_mixed_tactic_for_nested_metaitem_list(list: &[ast::NestedMetaItem]) -> impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { - ast::MetaItemKind::Word => String::from(&*self.name().as_str()), + ast::MetaItemKind::Word => { + rewrite_path(context, PathContext::Type, None, &self.ident, shape)? + } ast::MetaItemKind::List(ref list) => { - let name = self.name().as_str(); + let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; let item_shape = match context.config.indent_style() { IndentStyle::Block => shape .block_indent(context.config.tab_spaces()) @@ -210,7 +213,7 @@ impl Rewrite for ast::MetaItem { // 1 = `(`, 2 = `]` and `)` IndentStyle::Visual => shape .visual_indent(0) - .shrink_left(name.len() + 1) + .shrink_left(path.len() + 1) .and_then(|s| s.sub_width(2))?, }; let items = itemize_list( @@ -248,21 +251,21 @@ impl Rewrite for ast::MetaItem { }; let item_str = write_list(&item_vec, &fmt)?; // 3 = "()" and "]" - let one_line_budget = shape.offset_left(name.len())?.sub_width(3)?.width; + let one_line_budget = shape.offset_left(path.len())?.sub_width(3)?.width; if context.config.indent_style() == IndentStyle::Visual || (!item_str.contains('\n') && item_str.len() <= one_line_budget) { - format!("{}({})", name, item_str) + format!("{}({})", path, item_str) } else { let indent = shape.indent.to_string_with_newline(context.config); let nested_indent = item_shape.indent.to_string_with_newline(context.config); - format!("{}({}{}{})", name, nested_indent, item_str, indent) + format!("{}({}{}{})", path, nested_indent, item_str, indent) } } ast::MetaItemKind::NameValue(ref literal) => { - let name = self.name().as_str(); + let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; // 3 = ` = ` - let lit_shape = shape.shrink_left(name.len() + 3)?; + let lit_shape = shape.shrink_left(path.len() + 3)?; // `rewrite_literal` returns `None` when `literal` exceeds max // width. Since a literal is basically unformattable unless it // is a string literal (and only if `format_strings` is set), @@ -271,7 +274,7 @@ impl Rewrite for ast::MetaItem { // See #2479 for example. let value = rewrite_literal(context, literal, lit_shape) .unwrap_or_else(|| context.snippet(literal.span).to_owned()); - format!("{} = {}", name, value) + format!("{} = {}", path, value) } }) } diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index d5c244a9bf8..409e5f5a4a9 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -161,3 +161,10 @@ struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // #2647 #[cfg(feature = "this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")] pub fn foo() {} + +// path attrs +#[clippy::bar] +#[clippy::bar=foo] +#[clippy::bar(a, b, c)] +pub fn foo() {} + diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 45dc4ea8ba9..b0b8ea89f82 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -171,3 +171,9 @@ struct A { feature = "this_line_is_101_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" )] pub fn foo() {} + +// path attrs +#[clippy::bar] +#[clippy::bar=foo] +#[clippy::bar(a, b, c)] +pub fn foo() {} -- cgit 1.4.1-3-g733a5 From de950c2973e20be37159952ded06a8d8aeff261d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 16:11:55 +1200 Subject: Skip on `rustfmt::skip` as well as `rustfmt_skip` --- README.md | 2 +- rustfmt.toml | 2 ++ src/utils.rs | 9 ++++++--- tests/target/skip.rs | 10 +++++----- 4 files changed, 14 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 6dc437fd27f..b5a4bc7bbc5 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ See [Configurations.md](Configurations.md) for details. * For things you do not want rustfmt to mangle, use one of ```rust - #[rustfmt_skip] // requires nightly and #![feature(custom_attribute)] in crate root + #[rustfmt::skip] // requires nightly Rust and #![feature(tool_attributes)] in crate root #[cfg_attr(rustfmt, rustfmt_skip)] // works in stable ``` * When you run rustfmt, place a file named `rustfmt.toml` or `.rustfmt.toml` in diff --git a/rustfmt.toml b/rustfmt.toml index e69de29bb2d..9b935b0a287 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -0,0 +1,2 @@ +error_on_line_overflow = true +error_on_unformatted = true diff --git a/src/utils.rs b/src/utils.rs index ca8a7ad7814..2556fa2c97f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -22,8 +22,8 @@ use config::Color; use rewrite::RewriteContext; use shape::Shape; -// When we get scoped annotations, we should have rustfmt::skip. -const SKIP_ANNOTATION: &str = "rustfmt_skip"; +const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; +const SKIP_ANNOTATION: &str = "rustfmt::skip"; // Computes the length of a string's last line, minus offset. pub fn extra_offset(text: &str, shape: Shape) -> usize { @@ -212,7 +212,10 @@ pub fn last_line_extendable(s: &str) -> bool { #[inline] fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { - MetaItemKind::Word => meta_item.name() == SKIP_ANNOTATION, + MetaItemKind::Word => { + let path_str = meta_item.ident.to_string(); + path_str == SKIP_ANNOTATION || path_str == DEPR_SKIP_ANNOTATION + } MetaItemKind::List(ref l) => { meta_item.name() == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) } diff --git a/tests/target/skip.rs b/tests/target/skip.rs index 11d1d69e91a..ee2094151cf 100644 --- a/tests/target/skip.rs +++ b/tests/target/skip.rs @@ -1,10 +1,10 @@ // Test the skip attribute works -#[rustfmt_skip] +#[rustfmt::skip] fn foo() { badly; formatted; stuff ; } -#[rustfmt_skip] +#[rustfmt::skip] trait Foo { fn foo( @@ -32,7 +32,7 @@ fn issue1346() { fn skip_on_statements() { // Outside block - #[rustfmt_skip] + #[rustfmt::skip] { foo; bar; // junk @@ -40,7 +40,7 @@ fn skip_on_statements() { { // Inside block - #![rustfmt_skip] + #![rustfmt::skip] foo; bar; // junk } @@ -79,7 +79,7 @@ fn skip_on_statements() { } // Check that the skip attribute applies to other attributes. -#[rustfmt_skip] +#[rustfmt::skip] #[cfg ( a , b )] -- cgit 1.4.1-3-g733a5 From 51f566062fefc2262dd3b56f7e385f1dd749bd8b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 16:25:10 +1200 Subject: Update uses of `rustfmt_skip` to `rustfmt::skip` --- Configurations.md | 4 ++-- src/comment.rs | 2 +- src/lib.rs | 9 +++------ src/test/mod.rs | 6 +++--- tests/config/skip_children.toml | 2 +- tests/source/comment4.rs | 2 +- tests/source/configs/struct_field_align_threshold/20.rs | 4 ++-- tests/source/configs/use_field_init_shorthand/false.rs | 2 +- tests/source/configs/use_field_init_shorthand/true.rs | 2 +- tests/source/enum.rs | 2 +- tests/source/issue-1124.rs | 2 +- tests/source/match.rs | 4 ++-- tests/source/multiple.rs | 6 +++--- tests/source/structs.rs | 4 ++-- tests/source/trait.rs | 2 +- tests/source/unions.rs | 4 ++-- tests/target/comment4.rs | 2 +- tests/target/configs/struct_field_align_threshold/20.rs | 6 +++--- tests/target/configs/use_field_init_shorthand/false.rs | 2 +- tests/target/configs/use_field_init_shorthand/true.rs | 2 +- tests/target/enum.rs | 2 +- tests/target/fn.rs | 2 +- tests/target/match.rs | 4 ++-- tests/target/multiple.rs | 6 +++--- tests/target/skip.rs | 14 +++++++------- tests/target/skip_mod.rs | 2 +- tests/target/structs.rs | 6 +++--- tests/target/trait.rs | 2 +- tests/target/unions.rs | 6 +++--- 29 files changed, 55 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 07a336d93fa..9c0d9481b50 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1951,7 +1951,7 @@ lines are found, they are trimmed down to match this integer. Original Code: ```rust -#![rustfmt_skip] +#![rustfmt::skip] fn foo() { println!("a"); @@ -2010,7 +2010,7 @@ them, additional blank lines are inserted. Original Code (rustfmt will not change it with the default value of `0`): ```rust -#![rustfmt_skip] +#![rustfmt::skip] fn foo() { println!("a"); diff --git a/src/comment.rs b/src/comment.rs index 0b6c818e59e..f850c0bba44 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1253,7 +1253,7 @@ mod test { } #[test] - #[cfg_attr(rustfmt, rustfmt_skip)] + #[rustfmt::skip] fn format_comments() { let mut config: ::config::Config = Default::default(); config.set().wrap_comments(true); diff --git a/src/lib.rs b/src/lib.rs index c50c45fbd36..1045841ad0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(custom_attribute)] +#![feature(tool_attributes)] #![feature(decl_macro)] -// FIXME(cramertj) remove after match_default_bindings merges -#![allow(stable_features)] #![allow(unused_attributes)] -#![feature(match_default_bindings)] #![feature(type_ascription)] #![feature(unicode_internals)] @@ -396,7 +393,7 @@ where Ok((result, has_diff)) } -/// Returns true if the line with the given line number was skipped by `#[rustfmt_skip]`. +/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { skipped_range .iter() @@ -975,7 +972,7 @@ mod unit_tests { #[test] fn test_format_code_block_fail() { - #[rustfmt_skip] + #[rustfmt::skip] let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);"; assert!(format_code_block(code_block, &Config::default()).is_none()); } diff --git a/src/test/mod.rs b/src/test/mod.rs index 4de69296e9f..b538519ec0b 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -704,14 +704,14 @@ impl ConfigCodeBlock { // We never expect to not have a code block. assert!(self.code_block.is_some() && self.code_block_start.is_some()); - // See if code block begins with #![rustfmt_skip]. + // See if code block begins with #![rustfmt::skip]. let fmt_skip = self .code_block .as_ref() .unwrap() .split('\n') .nth(0) - .unwrap_or("") == "#![rustfmt_skip]"; + .unwrap_or("") == "#![rustfmt::skip]"; if self.config_name.is_none() && !fmt_skip { write_message(&format!( @@ -790,7 +790,7 @@ impl ConfigCodeBlock { // - Rust code blocks are identifed by lines beginning with "```rust". // - One explicit configuration setting is supported per code block. // - Rust code blocks with no configuration setting are illegal and cause an - // assertion failure, unless the snippet begins with #![rustfmt_skip]. + // assertion failure, unless the snippet begins with #![rustfmt::skip]. // - Configuration names in Configurations.md must be in the form of // "## `NAME`". // - Configuration values in Configurations.md must be in the form of diff --git a/tests/config/skip_children.toml b/tests/config/skip_children.toml index 49f37a88dfb..f52930d50b6 100644 --- a/tests/config/skip_children.toml +++ b/tests/config/skip_children.toml @@ -1 +1 @@ -skip_children = true \ No newline at end of file +skip_children = true diff --git a/tests/source/comment4.rs b/tests/source/comment4.rs index ff1445378d7..f53a8a4a1fe 100644 --- a/tests/source/comment4.rs +++ b/tests/source/comment4.rs @@ -48,5 +48,5 @@ fn debug_function() { #[link_section=".vectors"] #[no_mangle] // Test this attribute is preserved. -#[cfg_attr(rustfmt, rustfmt_skip)] +#[cfg_attr(rustfmt, rustfmt::skip)] pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/source/configs/struct_field_align_threshold/20.rs b/tests/source/configs/struct_field_align_threshold/20.rs index e68340b027d..229817e1405 100644 --- a/tests/source/configs/struct_field_align_threshold/20.rs +++ b/tests/source/configs/struct_field_align_threshold/20.rs @@ -36,7 +36,7 @@ fn main() { /// A Doc comment #[AnAttribute] pub struct Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -166,7 +166,7 @@ struct Palette { /// A map of indices in the palette to a count of pixels in app // when the field had attributes struct FieldsWithAttributes { // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + #[rustfmt::skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB //Another pre comment #[attr1] #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC diff --git a/tests/source/configs/use_field_init_shorthand/false.rs b/tests/source/configs/use_field_init_shorthand/false.rs index 16ce740f1b9..4c2eb1de179 100644 --- a/tests/source/configs/use_field_init_shorthand/false.rs +++ b/tests/source/configs/use_field_init_shorthand/false.rs @@ -13,7 +13,7 @@ fn main() { y: y, #[attr] z: z, - #[rustfmt_skip] + #[rustfmt::skip] skipped: skipped, }; } diff --git a/tests/source/configs/use_field_init_shorthand/true.rs b/tests/source/configs/use_field_init_shorthand/true.rs index 1e36c6cff35..dcde28d74e0 100644 --- a/tests/source/configs/use_field_init_shorthand/true.rs +++ b/tests/source/configs/use_field_init_shorthand/true.rs @@ -13,7 +13,7 @@ fn main() { y: y, #[attr] z: z, - #[rustfmt_skip] + #[rustfmt::skip] skipped: skipped, }; } diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 64e15110609..654fc3a836d 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -49,7 +49,7 @@ pub enum EnumWithAttributes { //This is a pre comment AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA TupleVar(usize, usize, usize), // AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA // Pre Comment - #[rustfmt_skip] + #[rustfmt::skip] SkippedItem(String,String,), // Post-comment #[another_attr] #[attr2] diff --git a/tests/source/issue-1124.rs b/tests/source/issue-1124.rs index 69aa1bb1c59..5c5eb369161 100644 --- a/tests/source/issue-1124.rs +++ b/tests/source/issue-1124.rs @@ -13,4 +13,4 @@ use y; use x; -use a; \ No newline at end of file +use a; diff --git a/tests/source/match.rs b/tests/source/match.rs index 31034f49402..d1664ca9f37 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -48,7 +48,7 @@ fn foo() { #[an_attribute] // Comment after an attribute. None => 0, - #[rustfmt_skip] + #[rustfmt::skip] Blurb => { } }; } @@ -103,7 +103,7 @@ fn matches() { fn match_skip() { let _ = match Some(1) { - #[rustfmt_skip] + #[rustfmt::skip] Some( n ) => n, None => 1, }; diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index 68cfacfcb4b..c26df03edda 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -36,7 +36,7 @@ fn baz<'a: 'b /* comment on 'a */, T: Somsssssssssssssssssssssssssssssssssssssss #[attr2]#[attr3]extern crate foo; } -#[rustfmt_skip] +#[rustfmt::skip] fn qux(a: dadsfa, // Comment 1 b: sdfasdfa, // Comment 2 c: dsfdsafa) // Comment 3 @@ -78,7 +78,7 @@ pub trait GraphWalk<'a, N, E> { /// A Doc comment #[AnAttribute] pub struct Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f : SomeType, // Comment beside a field // Comment on a field @@ -126,7 +126,7 @@ fn deconstruct(foo: Bar) -> (SocketAddr, Method, Headers, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) { } -#[rustfmt_skip] +#[rustfmt::skip] mod a{ fn foo(x: T) { let x: T = dfasdf; diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 25070aef34c..56471f1d7e4 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -4,7 +4,7 @@ /// A Doc comment #[AnAttribute] pub struct Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -139,7 +139,7 @@ struct Palette { /// A map of indices in the palette to a count of pixels in app // when the field had attributes struct FieldsWithAttributes { // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + #[rustfmt::skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB //Another pre comment #[attr1] #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC diff --git a/tests/source/trait.rs b/tests/source/trait.rs index b3cf4dae721..9f0c73694bf 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -89,7 +89,7 @@ trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; -#[rustfmt_skip] +#[rustfmt::skip] trait FooBar = Foo + Bar; diff --git a/tests/source/unions.rs b/tests/source/unions.rs index fc2908e2d9e..730ba980abb 100644 --- a/tests/source/unions.rs +++ b/tests/source/unions.rs @@ -4,7 +4,7 @@ /// A Doc comment #[AnAttribute] pub union Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -100,7 +100,7 @@ union Palette { /// A map of indices in the palette to a count of pixels in appr // when the field had attributes union FieldsWithAttributes { // Pre Comment - #[rustfmt_skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB + #[rustfmt::skip] pub host:String, // Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB //Another pre comment #[attr1] #[attr2] pub id: usize // CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCC CCCCCCCCCCCC diff --git a/tests/target/comment4.rs b/tests/target/comment4.rs index e07abf74a81..e2ef7de978f 100644 --- a/tests/target/comment4.rs +++ b/tests/target/comment4.rs @@ -47,5 +47,5 @@ fn debug_function() { #[link_section=".vectors"] #[no_mangle] // Test this attribute is preserved. -#[cfg_attr(rustfmt, rustfmt_skip)] +#[cfg_attr(rustfmt, rustfmt::skip)] pub static ISSUE_1284: [i32; 16] = []; diff --git a/tests/target/configs/struct_field_align_threshold/20.rs b/tests/target/configs/struct_field_align_threshold/20.rs index f6ee4ed1f0a..f952775f5f2 100644 --- a/tests/target/configs/struct_field_align_threshold/20.rs +++ b/tests/target/configs/struct_field_align_threshold/20.rs @@ -36,7 +36,7 @@ fn main() { /// A Doc comment #[AnAttribute] pub struct Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -171,8 +171,8 @@ struct Palette { // when the field had attributes struct FieldsWithAttributes { // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + #[rustfmt::skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ // Another pre comment #[attr1] #[attr2] diff --git a/tests/target/configs/use_field_init_shorthand/false.rs b/tests/target/configs/use_field_init_shorthand/false.rs index dcebe0b6f1d..74330446886 100644 --- a/tests/target/configs/use_field_init_shorthand/false.rs +++ b/tests/target/configs/use_field_init_shorthand/false.rs @@ -9,7 +9,7 @@ fn main() { y: y, #[attr] z: z, - #[rustfmt_skip] + #[rustfmt::skip] skipped: skipped, }; } diff --git a/tests/target/configs/use_field_init_shorthand/true.rs b/tests/target/configs/use_field_init_shorthand/true.rs index ad78093ee8e..8b80e81534b 100644 --- a/tests/target/configs/use_field_init_shorthand/true.rs +++ b/tests/target/configs/use_field_init_shorthand/true.rs @@ -9,7 +9,7 @@ fn main() { y, #[attr] z, - #[rustfmt_skip] + #[rustfmt::skip] skipped: skipped, }; } diff --git a/tests/target/enum.rs b/tests/target/enum.rs index e429e45287e..b19b6997826 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -65,7 +65,7 @@ pub enum EnumWithAttributes { TupleVar(usize, usize, usize), /* AAAA AAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA * AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA */ // Pre Comment - #[rustfmt_skip] + #[rustfmt::skip] SkippedItem(String,String,), // Post-comment #[another_attr] #[attr2] diff --git a/tests/target/fn.rs b/tests/target/fn.rs index b78a8b5b21e..66a6e9082de 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -92,7 +92,7 @@ fn inner() { x } -#[cfg_attr(rustfmt, rustfmt_skip)] +#[cfg_attr(rustfmt, rustfmt::skip)] fn foo(a: i32) -> i32 { // comment if a > 0 { 1 } else { 2 } diff --git a/tests/target/match.rs b/tests/target/match.rs index fe565f4c154..7ed49c61f1d 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -51,7 +51,7 @@ fn foo() { #[an_attribute] // Comment after an attribute. None => 0, - #[rustfmt_skip] + #[rustfmt::skip] Blurb => { } }; } @@ -109,7 +109,7 @@ fn matches() { fn match_skip() { let _ = match Some(1) { - #[rustfmt_skip] + #[rustfmt::skip] Some( n ) => n, None => 1, }; diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 446b4357de3..832567fdf7e 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -58,7 +58,7 @@ fn baz< extern crate foo; } -#[rustfmt_skip] +#[rustfmt::skip] fn qux(a: dadsfa, // Comment 1 b: sdfasdfa, // Comment 2 c: dsfdsafa) // Comment 3 @@ -103,7 +103,7 @@ pub trait GraphWalk<'a, N, E> { /// A Doc comment #[AnAttribute] pub struct Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -172,7 +172,7 @@ fn deconstruct( ) { } -#[rustfmt_skip] +#[rustfmt::skip] mod a{ fn foo(x: T) { let x: T = dfasdf; diff --git a/tests/target/skip.rs b/tests/target/skip.rs index ee2094151cf..6c9737a3377 100644 --- a/tests/target/skip.rs +++ b/tests/target/skip.rs @@ -12,13 +12,13 @@ fn foo( } impl LateLintPass for UsedUnderscoreBinding { - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] fn check_expr() { // comment } } fn issue1346() { - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] Box::new(self.inner.call(req).then(move |result| { match result { Ok(resp) => Box::new(future::done(Ok(resp))), @@ -46,7 +46,7 @@ fn skip_on_statements() { } // Semi - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] foo( 1, 2, 3, 4, 1, 2, @@ -54,15 +54,15 @@ fn skip_on_statements() { ); // Local - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] let x = foo( a, b , c); // Item - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] use foobar; // Mac - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] vec![ 1, 2, 3, 4, 1, 2, 3, 4, @@ -74,7 +74,7 @@ fn skip_on_statements() { ]; // Expr - #[cfg_attr(rustfmt, rustfmt_skip)] + #[cfg_attr(rustfmt, rustfmt::skip)] foo( a, b , c) } diff --git a/tests/target/skip_mod.rs b/tests/target/skip_mod.rs index 38ece8f070d..d770ab349f4 100644 --- a/tests/target/skip_mod.rs +++ b/tests/target/skip_mod.rs @@ -1,3 +1,3 @@ -#![rustfmt_skip] +#![rustfmt::skip] use a :: b ; diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 7f9ef1e6164..368650bb6a8 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -4,7 +4,7 @@ /// A Doc comment #[AnAttribute] pub struct Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -144,8 +144,8 @@ struct Palette { // when the field had attributes struct FieldsWithAttributes { // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + #[rustfmt::skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ // Another pre comment #[attr1] #[attr2] diff --git a/tests/target/trait.rs b/tests/target/trait.rs index ed7d3bc56f1..a6bc2d89689 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -127,7 +127,7 @@ trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA D, E, > = FooBar; -#[rustfmt_skip] +#[rustfmt::skip] trait FooBar = Foo + Bar; diff --git a/tests/target/unions.rs b/tests/target/unions.rs index 6de682297af..386ceb3836c 100644 --- a/tests/target/unions.rs +++ b/tests/target/unions.rs @@ -4,7 +4,7 @@ /// A Doc comment #[AnAttribute] pub union Foo { - #[rustfmt_skip] + #[rustfmt::skip] f : SomeType, // Comment beside a field f: SomeType, // Comment beside a field // Comment on a field @@ -100,8 +100,8 @@ union Palette { // when the field had attributes union FieldsWithAttributes { // Pre Comment - #[rustfmt_skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB - * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ + #[rustfmt::skip] pub host:String, /* Post comment BBBBBBBBBBBBBB BBBBBBBBBBBBBBBB + * BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBB BBBBBBBBBBB */ // Another pre comment #[attr1] #[attr2] -- cgit 1.4.1-3-g733a5 From 390a28485159a9bd165fa5101b7537b34493341e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 14 May 2018 18:01:53 +1200 Subject: Give a deprecation warning on `rustfmt_skip` and an error on `rustfmt::` other than `skip` --- src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++++++++---------------- src/rewrite.rs | 2 ++ src/utils.rs | 4 +-- src/visitor.rs | 44 +++++++++++++++++++++++++++++++-- 4 files changed, 102 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 1045841ad0d..46cb952a0cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ extern crate term; extern crate toml; extern crate unicode_segmentation; +use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::io::{self, stdout, Write}; @@ -47,7 +48,7 @@ use std::time::Duration; use syntax::ast; pub use syntax::codemap::FileName; -use syntax::codemap::{CodeMap, FilePathMapping}; +use syntax::codemap::{CodeMap, FilePathMapping, Span}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; @@ -125,9 +126,14 @@ pub enum ErrorKind { // License check has failed #[fail(display = "license check failed")] LicenseCheck, + // Used deprecated skip attribute + #[fail(display = "`rustfmt_skip` is deprecated; use `rustfmt::skip`")] + DeprecatedAttr, + // Used a rustfmt:: attribute other than skip + #[fail(display = "invalid attribute")] + BadAttr, } -// Formatting errors that are identified *after* rustfmt has run. struct FormattingError { line: usize, kind: ErrorKind, @@ -137,11 +143,28 @@ struct FormattingError { } impl FormattingError { + fn from_span(span: &Span, codemap: &CodeMap, kind: ErrorKind) -> FormattingError { + FormattingError { + line: codemap.lookup_char_pos(span.lo()).line, + kind, + is_comment: false, + is_string: false, + line_buffer: codemap + .span_to_lines(*span) + .ok() + .and_then(|fl| { + fl.file + .get_line(fl.lines[0].line_index) + .map(|l| l.into_owned()) + }) + .unwrap_or_else(|| String::new()), + } + } fn msg_prefix(&self) -> &str { match self.kind { ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "internal error:", - ErrorKind::LicenseCheck => "error:", - ErrorKind::BadIssue(_) => "warning:", + ErrorKind::LicenseCheck | ErrorKind::BadAttr => "error:", + ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", } } @@ -158,7 +181,7 @@ impl FormattingError { fn format_len(&self) -> (usize, usize) { match self.kind { ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace => { + ErrorKind::TrailingWhitespace | ErrorKind::DeprecatedAttr | ErrorKind::BadAttr => { let trailing_ws_start = self .line_buffer .rfind(|c: char| !c.is_whitespace()) @@ -174,20 +197,30 @@ impl FormattingError { } } +#[derive(Clone)] pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. - file_error_map: HashMap>, + file_error_map: Rc>>>, } impl FormatReport { fn new() -> FormatReport { FormatReport { - file_error_map: HashMap::new(), + file_error_map: Rc::new(RefCell::new(HashMap::new())), } } + fn append(&self, f: FileName, mut v: Vec) { + self.file_error_map + .borrow_mut() + .entry(f) + .and_modify(|fe| fe.append(&mut v)) + .or_insert(v); + } + fn warning_count(&self) -> usize { self.file_error_map + .borrow() .iter() .map(|(_, errors)| errors.len()) .sum() @@ -201,7 +234,7 @@ impl FormatReport { &self, mut t: Box>, ) -> Result<(), term::Error> { - for (file, errors) in &self.file_error_map { + for (file, errors) in &*self.file_error_map.borrow() { for error in errors { let prefix_space_len = error.line.to_string().len(); let prefix_spaces = " ".repeat(1 + prefix_space_len); @@ -247,7 +280,7 @@ impl FormatReport { } } - if !self.file_error_map.is_empty() { + if !self.file_error_map.borrow().is_empty() { t.attr(term::Attr::Bold)?; write!(t, "warning: ")?; t.reset()?; @@ -271,7 +304,7 @@ fn target_str(space_len: usize, target_len: usize) -> String { impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - for (file, errors) in &self.file_error_map { + for (file, errors) in &*self.file_error_map.borrow() { for error in errors { let prefix_space_len = error.line.to_string().len(); let prefix_spaces = " ".repeat(1 + prefix_space_len); @@ -310,7 +343,7 @@ impl fmt::Display for FormatReport { )?; } } - if !self.file_error_map.is_empty() { + if !self.file_error_map.borrow().is_empty() { writeln!( fmt, "warning: rustfmt may have failed to format. See previous {} errors.", @@ -336,10 +369,11 @@ fn format_ast( parse_session: &mut ParseSess, main_file: &FileName, config: &Config, + report: FormatReport, mut after_file: F, ) -> Result<(FileMap, bool), io::Error> where - F: FnMut(&FileName, &mut String, &[(usize, usize)]) -> Result, + F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result, { let mut result = FileMap::new(); // diff mode: check if any files are differing @@ -357,7 +391,8 @@ where .file; let big_snippet = filemap.src.as_ref().unwrap(); let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider); + let mut visitor = + FmtVisitor::from_codemap(parse_session, config, &snippet_provider, report.clone()); // Format inner attributes if available. if !krate.attrs.is_empty() && path == *main_file { visitor.skip_empty_lines(filemap.end_pos); @@ -377,8 +412,7 @@ where ::utils::count_newlines(&visitor.buffer) ); - let filename = path.clone(); - has_diff |= match after_file(&filename, &mut visitor.buffer, &visitor.skipped_range) { + has_diff |= match after_file(&path, &mut visitor.buffer, &visitor.skipped_range, &report) { Ok(result) => result, Err(e) => { // Create a new error with path_str to help users see which files failed @@ -387,7 +421,7 @@ where } }; - result.push((filename, visitor.buffer)); + result.push((path.clone(), visitor.buffer)); } Ok((result, has_diff)) @@ -426,7 +460,7 @@ fn format_lines( name: &FileName, skipped_range: &[(usize, usize)], config: &Config, - report: &mut FormatReport, + report: &FormatReport, ) { let mut trims = vec![]; let mut last_wspace: Option = None; @@ -540,7 +574,7 @@ fn format_lines( } } - report.file_error_map.insert(name.clone(), errors); + report.append(name.clone(), errors); } fn parse_input<'sess>( @@ -757,19 +791,20 @@ fn format_input_inner( )); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - let mut report = FormatReport::new(); + let report = FormatReport::new(); let format_result = format_ast( &krate, &mut parse_session, &main_file, config, - |file_name, file, skipped_range| { + report.clone(), + |file_name, file, skipped_range, report| { // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. filemap::append_newline(file); - format_lines(file, file_name, skipped_range, config, &mut report); + format_lines(file, file_name, skipped_range, config, report); if let Some(ref mut out) = out { return filemap::write_file(file, file_name, out, config); diff --git a/src/rewrite.rs b/src/rewrite.rs index 7eb8c18bbe6..7c7bb060fd3 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -16,6 +16,7 @@ use syntax::parse::ParseSess; use config::{Config, IndentStyle}; use shape::Shape; use visitor::SnippetProvider; +use FormatReport; use std::cell::RefCell; @@ -38,6 +39,7 @@ pub struct RewriteContext<'a> { // When rewriting chain, veto going multi line except the last element pub force_one_line_chain: RefCell, pub snippet_provider: &'a SnippetProvider<'a>, + pub report: FormatReport, } impl<'a> RewriteContext<'a> { diff --git a/src/utils.rs b/src/utils.rs index 2556fa2c97f..991ebf16bf2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -22,8 +22,8 @@ use config::Color; use rewrite::RewriteContext; use shape::Shape; -const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; -const SKIP_ANNOTATION: &str = "rustfmt::skip"; +pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; +pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; // Computes the length of a string's last line, minus offset. pub fn extra_offset(text: &str, shape: Shape) -> usize { diff --git a/src/visitor.rs b/src/visitor.rs index 7f042b1a11b..ec1890035a7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -26,7 +26,11 @@ use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; -use utils::{self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec}; +use utils::{ + self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, + DEPR_SKIP_ANNOTATION, +}; +use {ErrorKind, FormatReport, FormattingError}; use std::cell::RefCell; @@ -66,6 +70,7 @@ pub struct FmtVisitor<'a> { pub snippet_provider: &'a SnippetProvider<'a>, pub line_number: usize, pub skipped_range: Vec<(usize, usize)>, + pub report: FormatReport, } impl<'b, 'a: 'b> FmtVisitor<'a> { @@ -552,13 +557,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { - FmtVisitor::from_codemap(ctx.parse_session, ctx.config, ctx.snippet_provider) + FmtVisitor::from_codemap( + ctx.parse_session, + ctx.config, + ctx.snippet_provider, + ctx.report.clone(), + ) } pub fn from_codemap( parse_session: &'a ParseSess, config: &'a Config, snippet_provider: &'a SnippetProvider, + report: FormatReport, ) -> FmtVisitor<'a> { FmtVisitor { parse_session, @@ -571,6 +582,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider, line_number: 0, skipped_range: vec![], + report, } } @@ -584,6 +596,33 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Returns true if we should skip the following item. pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { + for attr in attrs { + if attr.name() == DEPR_SKIP_ANNOTATION { + let file_name = self.codemap.span_to_filename(attr.span); + self.report.append( + file_name, + vec![FormattingError::from_span( + &attr.span, + &self.codemap, + ErrorKind::DeprecatedAttr, + )], + ); + } else if attr.path.segments[0].ident.to_string() == "rustfmt" { + if attr.path.segments.len() == 1 + || attr.path.segments[1].ident.to_string() != "skip" + { + let file_name = self.codemap.span_to_filename(attr.span); + self.report.append( + file_name, + vec![FormattingError::from_span( + &attr.span, + &self.codemap, + ErrorKind::BadAttr, + )], + ); + } + } + } if contains_skip(attrs) { return true; } @@ -711,6 +750,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { is_if_else_block: RefCell::new(false), force_one_line_chain: RefCell::new(false), snippet_provider: self.snippet_provider, + report: self.report.clone(), } } } -- cgit 1.4.1-3-g733a5 From d1e2b80fb9d3e48a63f7c3c97fc966869da60a2c Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 14 May 2018 21:58:57 +0900 Subject: Use saturating_sub --- src/attr.rs | 2 +- src/closures.rs | 5 +---- src/comment.rs | 2 +- src/expr.rs | 21 +++++++++------------ src/imports.rs | 2 +- src/items.rs | 2 +- src/lists.rs | 6 ++---- src/macros.rs | 4 +--- src/matches.rs | 2 +- src/overflow.rs | 10 ++-------- src/rewrite.rs | 2 +- src/shape.rs | 15 ++++----------- src/utils.rs | 5 +---- src/vertical.rs | 4 +--- 14 files changed, 27 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index e754144a727..28e3e24ea09 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -77,7 +77,7 @@ fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) - result.push_str(&(shape.indent + 9).to_string(context.config)); budget = initial_budget; } else { - budget = budget.checked_sub(width).unwrap_or(0); + budget = budget.saturating_sub(width); } result.push_str(a); if i != num - 1 { diff --git a/src/closures.rs b/src/closures.rs index 0d5cf63a197..aec7d34b60a 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -240,10 +240,7 @@ fn rewrite_closure_fn_decl( ); let item_vec = arg_items.collect::>(); // 1 = space between arguments and return type. - let horizontal_budget = nested_shape - .width - .checked_sub(ret_str.len() + 1) - .unwrap_or(0); + let horizontal_budget = nested_shape.width.saturating_sub(ret_str.len() + 1); let tactic = definitive_tactic( &item_vec, ListTactic::HorizontalVertical, diff --git a/src/comment.rs b/src/comment.rs index f850c0bba44..044a76e3599 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -464,7 +464,7 @@ fn rewrite_comment_inner( // 1 = " " let offset = 1 + last_line_width(&result) - line_start.len(); Shape { - width: max_chars.checked_sub(offset).unwrap_or(0), + width: max_chars.saturating_sub(offset), indent: fmt_indent, offset: fmt.shape.offset + offset, } diff --git a/src/expr.rs b/src/expr.rs index 429fbc3cf9a..12605af25ae 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -326,7 +326,7 @@ pub fn format_expr( rw } else { // 9 = `do catch ` - let budget = shape.width.checked_sub(9).unwrap_or(0); + let budget = shape.width.saturating_sub(9); Some(format!( "{}{}", "do catch ", @@ -1002,8 +1002,7 @@ impl<'a> ControlFlow<'a> { let one_line_budget = context .config .max_width() - .checked_sub(constr_shape.used_width() + offset + brace_overhead) - .unwrap_or(0); + .saturating_sub(constr_shape.used_width() + offset + brace_overhead); let force_newline_brace = (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) && !last_line_extendable(&pat_expr_string); @@ -1109,7 +1108,7 @@ impl<'a> Rewrite for ControlFlow<'a> { return Some(cond_str); } - let block_width = shape.width.checked_sub(used_width).unwrap_or(0); + let block_width = shape.width.saturating_sub(used_width); // This is used only for the empty block case: `{}`. So, we use 1 if we know // we should avoid the single line case. let block_width = if self.else_block.is_some() || self.nested_if { @@ -1828,7 +1827,7 @@ pub fn rewrite_field( Some(attrs_str + &name) } else { let mut separator = String::from(struct_lit_field_separator(context.config)); - for _ in 0..prefix_max_width.checked_sub(name.len()).unwrap_or(0) { + for _ in 0..prefix_max_width.saturating_sub(name.len()) { separator.push(' '); } let overhead = name.len() + separator.len(); @@ -2053,13 +2052,11 @@ pub fn rewrite_assign_rhs_with, R: Rewrite>( rhs_tactics: RhsTactics, ) -> Option { let lhs = lhs.into(); - let last_line_width = last_line_width(&lhs) - .checked_sub(if lhs.contains('\n') { - shape.indent.width() - } else { - 0 - }) - .unwrap_or(0); + let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') { + shape.indent.width() + } else { + 0 + }); // 1 = space between operator and rhs. let orig_shape = shape.offset_left(last_line_width + 1).unwrap_or(Shape { width: 0, diff --git a/src/imports.rs b/src/imports.rs index 83121b04213..4740921c525 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -703,7 +703,7 @@ fn rewrite_nested_use_tree( let remaining_width = if has_nested_list { 0 } else { - shape.width.checked_sub(2).unwrap_or(0) + shape.width.saturating_sub(2) }; let tactic = definitive_tactic( diff --git a/src/items.rs b/src/items.rs index bd1a83d5a66..8c90d73cff3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1503,7 +1503,7 @@ pub fn rewrite_struct_field( attrs_extendable, )?; let overhead = last_line_width(&attr_prefix); - let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0); + let lhs_offset = lhs_max_width.saturating_sub(overhead); for _ in 0..lhs_offset { spacing.push(' '); } diff --git a/src/lists.rs b/src/lists.rs index b3264487cfe..7d612913361 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -193,7 +193,7 @@ where }; let (sep_count, total_width) = calculate_width(items.clone()); - let total_sep_len = sep.len() * sep_count.checked_sub(1).unwrap_or(0); + let total_sep_len = sep.len() * sep_count.saturating_sub(1); let real_total = total_width + total_sep_len; if real_total <= limit @@ -485,9 +485,7 @@ where } fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) -> usize { - item_max_width - .and_then(|max_line_width| max_line_width.checked_sub(inner_item_len)) - .unwrap_or(0) + item_max_width.unwrap_or(0).saturating_sub(inner_item_len) } pub struct ListItems<'a, I, F1, F2, F3> diff --git a/src/macros.rs b/src/macros.rs index 4c1b0baff12..7205c39da48 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1091,9 +1091,7 @@ fn indent_macro_snippet( _ if !trimmed => line.to_owned(), Some(original_indent_width) => { let new_indent_width = indent.width() - + original_indent_width - .checked_sub(min_prefix_space_width) - .unwrap_or(0); + + original_indent_width.saturating_sub(min_prefix_space_width); let new_indent = Indent::from_width(context.config, new_indent_width); format!("{}{}", new_indent.to_string(context.config), line.trim()) } diff --git a/src/matches.rs b/src/matches.rs index 0bbdbe62017..5a6aa6c6aac 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -196,7 +196,7 @@ fn rewrite_match_arms( let arm_len = arms.len(); let is_last_iter = repeat(false) - .take(arm_len.checked_sub(1).unwrap_or(0)) + .take(arm_len.saturating_sub(1)) .chain(repeat(true)); let beginning_verts = collect_beginning_verts(context, arms, span); let items = itemize_list( diff --git a/src/overflow.rs b/src/overflow.rs index a8ef66b0e3c..aeb528bf2e0 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -147,10 +147,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { 1 }; let used_width = extra_offset(ident, shape); - let one_line_width = shape - .width - .checked_sub(used_width + 2 * paren_overhead) - .unwrap_or(0); + let one_line_width = shape.width.saturating_sub(used_width + 2 * paren_overhead); // 1 = "(" or ")" let one_line_shape = shape @@ -412,10 +409,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> String { let shape = Shape { - width: shape - .width - .checked_sub(last_line_width(self.ident)) - .unwrap_or(0), + width: shape.width.saturating_sub(last_line_width(self.ident)), ..shape }; diff --git a/src/rewrite.rs b/src/rewrite.rs index 7c7bb060fd3..0dfae84bfc2 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -53,7 +53,7 @@ impl<'a> RewriteContext<'a> { } pub fn budget(&self, used_width: usize) -> usize { - self.config.max_width().checked_sub(used_width).unwrap_or(0) + self.config.max_width().saturating_sub(used_width) } pub fn inside_macro(&self) -> bool { diff --git a/src/shape.rs b/src/shape.rs index 8a17389672f..6cf0e8ea890 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -181,7 +181,7 @@ impl Shape { pub fn indented(indent: Indent, config: &Config) -> Shape { Shape { - width: config.max_width().checked_sub(indent.width()).unwrap_or(0), + width: config.max_width().saturating_sub(indent.width()), indent, offset: indent.alignment, } @@ -189,10 +189,7 @@ impl Shape { pub fn with_max_width(&self, config: &Config) -> Shape { Shape { - width: config - .max_width() - .checked_sub(self.indent.width()) - .unwrap_or(0), + width: config.max_width().saturating_sub(self.indent.width()), ..*self } } @@ -266,17 +263,13 @@ impl Shape { pub fn rhs_overhead(&self, config: &Config) -> usize { config .max_width() - .checked_sub(self.used_width() + self.width) - .unwrap_or(0) + .saturating_sub(self.used_width() + self.width) } pub fn comment(&self, config: &Config) -> Shape { let width = min( self.width, - config - .comment_width() - .checked_sub(self.indent.width()) - .unwrap_or(0), + config.comment_width().saturating_sub(self.indent.width()), ); Shape { width, ..*self } } diff --git a/src/utils.rs b/src/utils.rs index 991ebf16bf2..6c8862b9bf5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -29,10 +29,7 @@ pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { // 1 for newline character - Some(idx) => text - .len() - .checked_sub(idx + 1 + shape.used_width()) - .unwrap_or(0), + Some(idx) => text.len().saturating_sub(idx + 1 + shape.used_width()), None => text.len(), } } diff --git a/src/vertical.rs b/src/vertical.rs index 6cdaaafeb36..1595b22c5c4 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -219,9 +219,7 @@ fn rewrite_aligned_items_inner( let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; let (mut field_prefix_max_width, field_prefix_min_width) = struct_field_prefix_max_min_width(context, fields, item_shape); - let max_diff = field_prefix_max_width - .checked_sub(field_prefix_min_width) - .unwrap_or(0); + let max_diff = field_prefix_max_width.saturating_sub(field_prefix_min_width); if max_diff > context.config.struct_field_align_threshold() { field_prefix_max_width = 0; } -- cgit 1.4.1-3-g733a5 From 14523499660866bd664f464d2f9a2757b6b35d50 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 15:30:32 +1200 Subject: Exit with 1 for license check in `--check` mode Closes #2707 --- src/bin/main.rs | 6 +++--- src/config/summary.rs | 12 +++++++++++ src/lib.rs | 57 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 64 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 2c7bf5a2445..2d00d22f492 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -35,9 +35,9 @@ fn main() { let exit_code = match execute(&opts) { Ok((write_mode, summary)) => { - if summary.has_operational_errors() - || summary.has_parsing_errors() - || (summary.has_diff && write_mode == WriteMode::Check) + if summary.has_operational_errors() || summary.has_parsing_errors() + || ((summary.has_diff || summary.has_check_errors()) + && write_mode == WriteMode::Check) { 1 } else { diff --git a/src/config/summary.rs b/src/config/summary.rs index d44c69b04a6..7b6c25d498b 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -23,6 +23,9 @@ pub struct Summary { // Code is valid, but it is impossible to format it properly. has_formatting_errors: bool, + // Failed a check, such as the license check or other opt-in checking. + has_check_errors: bool, + // Formatted code differs from existing code (--check only). pub has_diff: bool, @@ -73,6 +76,10 @@ impl Summary { self.has_formatting_errors } + pub fn has_check_errors(&self) -> bool { + self.has_check_errors + } + pub fn add_operational_error(&mut self) { self.has_operational_errors = true; } @@ -85,6 +92,10 @@ impl Summary { self.has_formatting_errors = true; } + pub(crate) fn add_check_error(&mut self) { + self.has_check_errors = true; + } + pub(crate) fn add_diff(&mut self) { self.has_diff = true; } @@ -100,6 +111,7 @@ impl Summary { self.has_operational_errors |= other.has_operational_errors; self.has_formatting_errors |= other.has_formatting_errors; self.has_parsing_errors |= other.has_parsing_errors; + self.has_check_errors |= other.has_check_errors; self.has_diff |= other.has_diff; } } diff --git a/src/lib.rs b/src/lib.rs index 46cb952a0cb..57e007bf6cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -200,27 +200,58 @@ impl FormattingError { #[derive(Clone)] pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. - file_error_map: Rc>>>, + internal: Rc>, +} + +type FormatErrorMap = HashMap>; + +#[derive(Default, Debug)] +struct ReportedErrors { + has_operational_errors: bool, + has_check_errors: bool, } impl FormatReport { fn new() -> FormatReport { FormatReport { - file_error_map: Rc::new(RefCell::new(HashMap::new())), + internal: Rc::new(RefCell::new((HashMap::new(), ReportedErrors::default()))), } } fn append(&self, f: FileName, mut v: Vec) { - self.file_error_map + self.track_errors(&v); + self.internal .borrow_mut() + .0 .entry(f) .and_modify(|fe| fe.append(&mut v)) .or_insert(v); } + fn track_errors(&self, new_errors: &[FormattingError]) { + let errs = &mut self.internal.borrow_mut().1; + if errs.has_operational_errors && errs.has_check_errors { + return; + } + for err in new_errors { + match err.kind { + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => { + errs.has_operational_errors = true; + } + ErrorKind::BadIssue(_) + | ErrorKind::LicenseCheck + | ErrorKind::DeprecatedAttr + | ErrorKind::BadAttr => { + errs.has_check_errors = true; + } + } + } + } + fn warning_count(&self) -> usize { - self.file_error_map + self.internal .borrow() + .0 .iter() .map(|(_, errors)| errors.len()) .sum() @@ -234,7 +265,7 @@ impl FormatReport { &self, mut t: Box>, ) -> Result<(), term::Error> { - for (file, errors) in &*self.file_error_map.borrow() { + for (file, errors) in &self.internal.borrow().0 { for error in errors { let prefix_space_len = error.line.to_string().len(); let prefix_spaces = " ".repeat(1 + prefix_space_len); @@ -280,7 +311,7 @@ impl FormatReport { } } - if !self.file_error_map.borrow().is_empty() { + if !self.internal.borrow().0.is_empty() { t.attr(term::Attr::Bold)?; write!(t, "warning: ")?; t.reset()?; @@ -304,7 +335,7 @@ fn target_str(space_len: usize, target_len: usize) -> String { impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - for (file, errors) in &*self.file_error_map.borrow() { + for (file, errors) in &self.internal.borrow().0 { for error in errors { let prefix_space_len = error.line.to_string().len(); let prefix_spaces = " ".repeat(1 + prefix_space_len); @@ -343,7 +374,7 @@ impl fmt::Display for FormatReport { )?; } } - if !self.file_error_map.borrow().is_empty() { + if !self.internal.borrow().0.is_empty() { writeln!( fmt, "warning: rustfmt may have failed to format. See previous {} errors.", @@ -827,6 +858,16 @@ fn format_input_inner( ) }); + { + let report_errs = &report.internal.borrow().1; + if report_errs.has_check_errors { + summary.add_check_error(); + } + if report_errs.has_operational_errors { + summary.add_operational_error(); + } + } + match format_result { Ok((file_map, has_diff)) => { if report.has_warnings() { -- cgit 1.4.1-3-g733a5 From 416bc4c35331f67d82c052d40b1d0d524d092eb2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:02:05 +1200 Subject: Unstabilise comments options cc #1974 --- src/config/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index ac81ded5f76..b903a4e5804 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -46,10 +46,10 @@ create_config! { indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; // Comments and strings - wrap_comments: bool, false, true, "Break comments to fit on the line"; + wrap_comments: bool, false, false, "Break comments to fit on the line"; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; - normalize_comments: bool, false, true, "Convert /* */ comments to // comments where possible"; + normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; license_template_path: String, String::default(), false, "Beginning of file must match license template"; format_strings: bool, false, false, "Format string literals where necessary"; -- cgit 1.4.1-3-g733a5 From 7b6d2b4699303e9b4f966b7a3db65b979ca4a6fe Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:04:09 +1200 Subject: Stabilise reorder_imports and reorder_modules --- src/config/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index b903a4e5804..7d57ab14313 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -68,8 +68,8 @@ create_config! { merge_imports: bool, false, false, "Merge imports"; // Ordering - reorder_imports: bool, true, false, "Reorder import and extern crate statements alphabetically"; - reorder_modules: bool, true, false, "Reorder module statements alphabetically in group"; + reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically"; + reorder_modules: bool, true, true, "Reorder module statements alphabetically in group"; reorder_impl_items: bool, false, false, "Reorder impl items"; // Spaces around punctuation -- cgit 1.4.1-3-g733a5 From d726492e65eb597eb7f8eef5d428a9bce4ba4eed Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:35:09 +1200 Subject: Remove spaces_within_parens_and_brackets cc #1974 --- Configurations.md | 46 ------- src/chains.rs | 7 +- src/config/mod.rs | 4 +- src/expr.rs | 91 ++++--------- src/items.rs | 9 -- src/macros.rs | 15 +-- src/overflow.rs | 37 ++---- src/patterns.rs | 7 +- src/types.rs | 66 ++-------- src/utils.rs | 9 -- .../spaces_within_parens_and_brackets/false.rs | 7 - .../spaces_within_parens_and_brackets/true.rs | 133 ------------------- .../spaces_within_parens_and_brackets/false.rs | 7 - .../spaces_within_parens_and_brackets/true.rs | 145 --------------------- 14 files changed, 56 insertions(+), 527 deletions(-) delete mode 100644 tests/source/configs/spaces_within_parens_and_brackets/false.rs delete mode 100644 tests/source/configs/spaces_within_parens_and_brackets/true.rs delete mode 100644 tests/target/configs/spaces_within_parens_and_brackets/false.rs delete mode 100644 tests/target/configs/spaces_within_parens_and_brackets/true.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 9c0d9481b50..bd52d9d7379 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1589,52 +1589,6 @@ fn main() { } ``` -## `spaces_within_parens_and_brackets` - -Put spaces within non-empty generic arguments, parentheses, and square brackets - -- **Default value**: `false` -- **Possible values**: `true`, `false` -- **Stable**: No - -#### `false` (default): - -```rust -// generic arguments -fn lorem(t: T) { - // body -} - -// non-empty parentheses -fn lorem(t: T) { - let lorem = (ipsum, dolor); -} - -// non-empty square brackets -fn lorem(t: T) { - let lorem: [usize; 2] = [ipsum, dolor]; -} -``` - -#### `true`: - -```rust -// generic arguments -fn lorem< T: Eq >( t: T ) { - // body -} - -// non-empty parentheses -fn lorem< T: Eq >( t: T ) { - let lorem = ( ipsum, dolor ); -} - -// non-empty square brackets -fn lorem< T: Eq >( t: T ) { - let lorem: [ usize; 2 ] = [ ipsum, dolor ]; -} -``` - ## `struct_lit_single_line` Put small struct literals on a single line diff --git a/src/chains.rs b/src/chains.rs index a411f904fe9..c0dafc4f0f2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -498,12 +498,7 @@ fn rewrite_method_call( .map(|ty| ty.rewrite(context, shape)) .collect::>>()?; - let type_str = - if context.config.spaces_within_parens_and_brackets() && !type_list.is_empty() { - format!("::< {} >", type_list.join(", ")) - } else { - format!("::<{}>", type_list.join(", ")) - }; + let type_str = format!("::<{}>", type_list.join(", ")); (types.last().unwrap().span.hi(), type_str) }; diff --git a/src/config/mod.rs b/src/config/mod.rs index 7d57ab14313..ed480aa9fa1 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -77,9 +77,7 @@ create_config! { "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; space_before_colon: bool, false, false, "Leave a space before the colon"; space_after_colon: bool, true, false, "Leave a space after the colon"; - spaces_around_ranges: bool, false, false, "Put spaces around the .. and ... range operators"; - spaces_within_parens_and_brackets: bool, false, false, - "Put spaces within non-empty parentheses or brackets"; + spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators"; binop_separator: SeparatorPlace, SeparatorPlace::Front, false, "Where to put a binary operator when a binary expression goes multiline."; diff --git a/src/expr.rs b/src/expr.rs index 12605af25ae..17d9b95d841 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -39,8 +39,8 @@ use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{ colon_spaces, contains_skip, count_newlines, first_line_width, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead, - ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str, + last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, + semicolon_for_stmt, wrap_str, }; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -223,21 +223,14 @@ pub fn format_expr( ast::ExprKind::Index(ref expr, ref index) => { rewrite_index(&**expr, &**index, context, shape) } - ast::ExprKind::Repeat(ref expr, ref repeats) => { - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - rewrite_pair( - &**expr, - &**repeats, - PairParts::new(lbr, "; ", rbr), - context, - shape, - SeparatorPlace::Back, - ) - } + ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair( + &**expr, + &**repeats, + PairParts::new("[", "; ", "]"), + context, + shape, + SeparatorPlace::Back, + ), ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { ast::RangeLimits::HalfOpen => "..", @@ -1581,27 +1574,15 @@ fn rewrite_paren( break; } - let total_paren_overhead = paren_overhead(context); - let paren_overhead = total_paren_overhead / 2; - let sub_shape = shape - .offset_left(paren_overhead) - .and_then(|s| s.sub_width(paren_overhead))?; - - let paren_wrapper = |s: &str| { - if context.config.spaces_within_parens_and_brackets() && !s.is_empty() { - format!("( {}{}{} )", pre_comment, s, post_comment) - } else { - format!("({}{}{})", pre_comment, s, post_comment) - } - }; + // 1 `(` + let sub_shape = shape.offset_left(1).and_then(|s| s.sub_width(1))?; let subexpr_str = subexpr.rewrite(context, sub_shape)?; debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - if subexpr_str.contains('\n') - || first_line_width(&subexpr_str) + total_paren_overhead <= shape.width - { - Some(paren_wrapper(&subexpr_str)) + // 2 = `()` + if subexpr_str.contains('\n') || first_line_width(&subexpr_str) + 2 <= shape.width { + Some(format!("({}{}{})", pre_comment, &subexpr_str, post_comment)) } else { None } @@ -1615,54 +1596,44 @@ fn rewrite_index( ) -> Option { let expr_str = expr.rewrite(context, shape)?; - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - - let offset = last_line_width(&expr_str) + lbr.len(); + let offset = last_line_width(&expr_str) + 1; let rhs_overhead = shape.rhs_overhead(context.config); let index_shape = if expr_str.contains('\n') { Shape::legacy(context.config.max_width(), shape.indent) .offset_left(offset) - .and_then(|shape| shape.sub_width(rbr.len() + rhs_overhead)) + .and_then(|shape| shape.sub_width(1 + rhs_overhead)) } else { - shape.visual_indent(offset).sub_width(offset + rbr.len()) + shape.visual_indent(offset).sub_width(offset + 1) }; let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); // Return if index fits in a single line. match orig_index_rw { Some(ref index_str) if !index_str.contains('\n') => { - return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)); + return Some(format!("{}[{}]", expr_str, index_str)); } _ => (), } // Try putting index on the next line and see if it fits in a single line. let indent = shape.indent.block_indent(context.config); - let index_shape = Shape::indented(indent, context.config).offset_left(lbr.len())?; - let index_shape = index_shape.sub_width(rbr.len() + rhs_overhead)?; + let index_shape = Shape::indented(indent, context.config).offset_left(1)?; + let index_shape = index_shape.sub_width(1 + rhs_overhead)?; let new_index_rw = index.rewrite(context, index_shape); match (orig_index_rw, new_index_rw) { (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( - "{}{}{}{}{}", + "{}{}[{}]", expr_str, indent.to_string_with_newline(context.config), - lbr, new_index_str, - rbr )), (None, Some(ref new_index_str)) => Some(format!( - "{}{}{}{}{}", + "{}{}[{}]", expr_str, indent.to_string_with_newline(context.config), - lbr, new_index_str, - rbr )), - (Some(ref index_str), _) => Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr)), + (Some(ref index_str), _) => Some(format!("{}[{}]", expr_str, index_str)), _ => None, } } @@ -1877,13 +1848,7 @@ where .next() .unwrap() .rewrite(context, nested_shape) - .map(|s| { - if context.config.spaces_within_parens_and_brackets() { - format!("( {}, )", s) - } else { - format!("({},)", s) - } - }); + .map(|s| format!("({},)", s)); } let list_lo = context.snippet_provider.span_after(span, "("); @@ -1919,11 +1884,7 @@ where }; let list_str = write_list(&item_vec, &fmt)?; - if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() { - Some(format!("( {} )", list_str)) - } else { - Some(format!("({})", list_str)) - } + Some(format!("({})", list_str)) } pub fn rewrite_tuple<'a, T>( diff --git a/src/items.rs b/src/items.rs index 8c90d73cff3..820470ed35c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1915,12 +1915,6 @@ fn rewrite_fn_base( } else { result.push('('); } - if context.config.spaces_within_parens_and_brackets() - && !fd.inputs.is_empty() - && result.ends_with('(') - { - result.push(' ') - } // Skip `pub(crate)`. let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span); @@ -1978,9 +1972,6 @@ fn rewrite_fn_base( if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { result.push('\n'); } - if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() { - result.push(' ') - } // If the last line of args contains comment, we cannot put the closing paren // on the same line. if arg_str diff --git a/src/macros.rs b/src/macros.rs index 7205c39da48..c176b009f70 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -259,13 +259,8 @@ pub fn rewrite_macro_inner( // Handle special case: `vec![expr; expr]` if vec_with_semi { let mac_shape = shape.offset_left(macro_name.len())?; - let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() { - ("[ ", " ]") - } else { - ("[", "]") - }; - // 6 = `vec!` + `; ` - let total_overhead = lbr.len() + rbr.len() + 6; + // 8 = `vec![]` + `; ` + let total_overhead = 8; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); let lhs = arg_vec[0].rewrite(context, nested_shape)?; let rhs = arg_vec[1].rewrite(context, nested_shape)?; @@ -273,18 +268,16 @@ pub fn rewrite_macro_inner( && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { - Some(format!("{}{}{}; {}{}", macro_name, lbr, lhs, rhs, rbr)) + Some(format!("{}[{}; {}]", macro_name, lhs, rhs)) } else { Some(format!( - "{}{}{}{};{}{}{}{}", + "{}[{}{};{}{}{}]", macro_name, - lbr, nested_shape.indent.to_string_with_newline(context.config), lhs, nested_shape.indent.to_string_with_newline(context.config), rhs, shape.indent.to_string_with_newline(context.config), - rbr )) } } else { diff --git a/src/overflow.rs b/src/overflow.rs index aeb528bf2e0..d555086cda7 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -23,9 +23,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListIte use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{ - count_newlines, extra_offset, first_line_width, last_line_width, mk_sp, paren_overhead, -}; +use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; use std::cmp::min; @@ -140,26 +138,16 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { force_separator_tactic: Option, custom_delims: Option<(&'a str, &'a str)>, ) -> Context<'a, T> { - // 2 = `( `, 1 = `(` - let paren_overhead = if context.config.spaces_within_parens_and_brackets() { - 2 - } else { - 1 - }; let used_width = extra_offset(ident, shape); - let one_line_width = shape.width.saturating_sub(used_width + 2 * paren_overhead); + // 1 = `()` + let one_line_width = shape.width.saturating_sub(used_width + 2); // 1 = "(" or ")" let one_line_shape = shape .offset_left(last_line_width(ident) + 1) .and_then(|shape| shape.sub_width(1)) .unwrap_or(Shape { width: 0, ..shape }); - let nested_shape = shape_from_indent_style( - context, - shape, - used_width + 2 * paren_overhead, - used_width + paren_overhead, - ); + let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1); Context { context, items, @@ -417,12 +405,13 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { Some((lhs, rhs)) => (lhs, rhs), _ => (self.prefix, self.suffix), }; - let paren_overhead = paren_overhead(self.context); - let fits_one_line = items_str.len() + paren_overhead <= shape.width; + + // 2 = `()` + let fits_one_line = items_str.len() + 2 <= shape.width; let extend_width = if items_str.is_empty() { - paren_overhead + 2 } else { - first_line_width(items_str) + (paren_overhead / 2) + first_line_width(items_str) + 1 }; let nested_indent_str = self .nested_shape @@ -441,13 +430,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line) || (is_extendable && extend_width <= shape.width) { - if self.context.config.spaces_within_parens_and_brackets() && !items_str.is_empty() { - result.push(' '); - result.push_str(items_str); - result.push(' '); - } else { - result.push_str(items_str); - } + result.push_str(items_str); } else { if !items_str.is_empty() { result.push_str(&nested_indent_str); diff --git a/src/patterns.rs b/src/patterns.rs index 99edf9ba774..fcab484287c 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -156,12 +156,7 @@ impl Rewrite for Pat { let pats = pats?; // Unwrap all the sub-strings and join them with commas. - let result = if context.config.spaces_within_parens_and_brackets() { - format!("[ {} ]", pats.join(", ")) - } else { - format!("[{}]", pats.join(", ")) - }; - Some(result) + Some(format!("[{}]", pats.join(", "))) } PatKind::Struct(ref path, ref fields, ellipsis) => { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) diff --git a/src/types.rs b/src/types.rs index 3c2a2287d5c..07b3986f70e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -59,9 +59,6 @@ pub fn rewrite_path( if let Some(qself) = qself { result.push('<'); - if context.config.spaces_within_parens_and_brackets() { - result.push_str(" ") - } let fmt_ty = qself.ty.rewrite(context, shape)?; result.push_str(&fmt_ty); @@ -86,10 +83,6 @@ pub fn rewrite_path( )?; } - if context.config.spaces_within_parens_and_brackets() { - result.push_str(" ") - } - result.push_str(">::"); span_lo = qself.ty.span.hi() + BytePos(1); } @@ -437,13 +430,7 @@ impl Rewrite for ast::WherePredicate { let lhs = if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, bound_generic_params) { - if context.config.spaces_within_parens_and_brackets() - && !lifetime_str.is_empty() - { - format!("for< {} > {}{}", lifetime_str, type_str, colon) - } else { - format!("for<{}> {}{}", lifetime_str, type_str, colon) - } + format!("for<{}> {}{}", lifetime_str, type_str, colon) } else { format!("{}{}", type_str, colon) }; @@ -575,13 +562,7 @@ impl Rewrite for ast::PolyTraitRef { .trait_ref .rewrite(context, shape.offset_left(extra_offset)?)?; - Some( - if context.config.spaces_within_parens_and_brackets() && !lifetime_str.is_empty() { - format!("for< {} > {}", lifetime_str, path_str) - } else { - format!("for<{}> {}", lifetime_str, path_str) - }, - ) + Some(format!("for<{}> {}", lifetime_str, path_str)) } else { self.trait_ref.rewrite(context, shape) } @@ -657,28 +638,12 @@ impl Rewrite for ast::Ty { ast::TyKind::Paren(ref ty) => { let budget = shape.width.checked_sub(2)?; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| { - if context.config.spaces_within_parens_and_brackets() { - format!("( {} )", ty_str) - } else { - format!("({})", ty_str) - } - }) + .map(|ty_str| format!("({})", ty_str)) } ast::TyKind::Slice(ref ty) => { - let budget = if context.config.spaces_within_parens_and_brackets() { - shape.width.checked_sub(4)? - } else { - shape.width.checked_sub(2)? - }; + let budget = shape.width.checked_sub(4)?; ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| { - if context.config.spaces_within_parens_and_brackets() { - format!("[ {} ]", ty_str) - } else { - format!("[{}]", ty_str) - } - }) + .map(|ty_str| format!("[{}]", ty_str)) } ast::TyKind::Tup(ref items) => rewrite_tuple( context, @@ -689,19 +654,14 @@ impl Rewrite for ast::Ty { ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } - ast::TyKind::Array(ref ty, ref repeats) => { - let use_spaces = context.config.spaces_within_parens_and_brackets(); - let lbr = if use_spaces { "[ " } else { "[" }; - let rbr = if use_spaces { " ]" } else { "]" }; - rewrite_pair( - &**ty, - &**repeats, - PairParts::new(lbr, "; ", rbr), - context, - shape, - SeparatorPlace::Back, - ) - } + ast::TyKind::Array(ref ty, ref repeats) => rewrite_pair( + &**ty, + &**repeats, + PairParts::new("[", "; ", "]"), + context, + shape, + SeparatorPlace::Back, + ), ast::TyKind::Infer => { if shape.width >= 1 { Some("_".to_owned()) diff --git a/src/utils.rs b/src/utils.rs index 6c8862b9bf5..961989b3f5d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -360,15 +360,6 @@ pub fn colon_spaces(before: bool, after: bool) -> &'static str { } } -#[inline] -pub fn paren_overhead(context: &RewriteContext) -> usize { - if context.config.spaces_within_parens_and_brackets() { - 4 - } else { - 2 - } -} - pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { match e.node { ast::ExprKind::Call(ref e, _) diff --git a/tests/source/configs/spaces_within_parens_and_brackets/false.rs b/tests/source/configs/spaces_within_parens_and_brackets/false.rs deleted file mode 100644 index 908373ca9b0..00000000000 --- a/tests/source/configs/spaces_within_parens_and_brackets/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: false -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} diff --git a/tests/source/configs/spaces_within_parens_and_brackets/true.rs b/tests/source/configs/spaces_within_parens_and_brackets/true.rs deleted file mode 100644 index 2e3c92da2fc..00000000000 --- a/tests/source/configs/spaces_within_parens_and_brackets/true.rs +++ /dev/null @@ -1,133 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: true -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} - -enum E { - A(u32), - B(u32, u32), - C(u32, u32, u32), - D(), -} - -struct TupleStruct0(); -struct TupleStruct1(u32); -struct TupleStruct2(u32, u32); - -fn fooEmpty() {} - -fn foo(e: E, _: u32) -> (u32, u32) { - // Tuples - let t1 = (); - let t2 = (1,); - let t3 = (1, 2); - - let ts0 = TupleStruct0(); - let ts1 = TupleStruct1(1); - let ts2 = TupleStruct2(1, 2); - - // Tuple pattern - let (a,b,c) = (1,2,3); - - // Expressions - let x = (1 + 2) * (3); - - // Function call - fooEmpty(); - foo(1, 2); - - // Pattern matching - match e { - A(_) => (), - B(_, _) => (), - C(..) => (), - D => (), - } - - (1,2) -} - -struct Foo { - i: T, -} - -struct Bar { - i: T, - e: E, -} - -struct Foo<'a> { - i: &'a str, -} - -enum E { - T(T), -} - -enum E { - T(T), - S(S), -} - -fn foo(a: T) { - foo::(10); -} - -fn foo(a: T, b: E) { - foo::(10, "bar"); -} - -fn foo(a: T, b: E) { - foo::(10, "bar"); - - let opt: Option; - let res: Result; -} - -fn foo<'a>(a: &'a str) { - foo("foo"); -} - -fn foo<'a, 'b>(a: &'a str, b: &'b str) { - foo("foo", "bar"); -} - -impl Foo { - fn bar() { - ::bar(); - } -} - -trait MyTrait {} -impl MyTrait for Foo {} - -fn foo() where for<'a> u32: 'a {} - -fn main() { - let arr: [i32; 5] = [1, 2, 3, 4, 5]; - let arr: [i32; 500] = [0; 500]; - - let v = vec![1, 2, 3]; - assert_eq!(arr, [1, 2, 3]); - - let i = arr[0]; - - let slice = &arr[1..2]; - - let line100_________________________________________________________________________ = [1, 2]; - let line101__________________________________________________________________________ = [1, 2]; - let line102___________________________________________________________________________ = [1, 2]; - let line103____________________________________________________________________________ = [1, 2]; - let line104_____________________________________________________________________________ = [1, 2]; - - let line100_____________________________________________________________________ = vec![1, 2]; - let line101______________________________________________________________________ = vec![1, 2]; - let line102_______________________________________________________________________ = vec![1, 2]; - let line103________________________________________________________________________ = vec![1, 2]; - let line104_________________________________________________________________________ = vec![1, 2]; -} - -fn f(slice: &[i32]) {} diff --git a/tests/target/configs/spaces_within_parens_and_brackets/false.rs b/tests/target/configs/spaces_within_parens_and_brackets/false.rs deleted file mode 100644 index 908373ca9b0..00000000000 --- a/tests/target/configs/spaces_within_parens_and_brackets/false.rs +++ /dev/null @@ -1,7 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: false -// Spaces within parens and brackets - -fn lorem(t: T) { - let lorem = (ipsum, dolor); - let lorem: [usize; 2] = [ipsum, dolor]; -} diff --git a/tests/target/configs/spaces_within_parens_and_brackets/true.rs b/tests/target/configs/spaces_within_parens_and_brackets/true.rs deleted file mode 100644 index 7aff7131506..00000000000 --- a/tests/target/configs/spaces_within_parens_and_brackets/true.rs +++ /dev/null @@ -1,145 +0,0 @@ -// rustfmt-spaces_within_parens_and_brackets: true -// Spaces within parens and brackets - -fn lorem< T: Eq >( t: T ) { - let lorem = ( ipsum, dolor ); - let lorem: [ usize; 2 ] = [ ipsum, dolor ]; -} - -enum E { - A( u32 ), - B( u32, u32 ), - C( u32, u32, u32 ), - D(), -} - -struct TupleStruct0(); -struct TupleStruct1( u32 ); -struct TupleStruct2( u32, u32 ); - -fn fooEmpty() {} - -fn foo( e: E, _: u32 ) -> ( u32, u32 ) { - // Tuples - let t1 = (); - let t2 = ( 1, ); - let t3 = ( 1, 2 ); - - let ts0 = TupleStruct0(); - let ts1 = TupleStruct1( 1 ); - let ts2 = TupleStruct2( 1, 2 ); - - // Tuple pattern - let ( a, b, c ) = ( 1, 2, 3 ); - - // Expressions - let x = ( 1 + 2 ) * ( 3 ); - - // Function call - fooEmpty(); - foo( 1, 2 ); - - // Pattern matching - match e { - A( _ ) => (), - B( _, _ ) => (), - C( .. ) => (), - D => (), - } - - ( 1, 2 ) -} - -struct Foo< T > { - i: T, -} - -struct Bar< T, E > { - i: T, - e: E, -} - -struct Foo< 'a > { - i: &'a str, -} - -enum E< T > { - T( T ), -} - -enum E< T, S > { - T( T ), - S( S ), -} - -fn foo< T >( a: T ) { - foo::< u32 >( 10 ); -} - -fn foo< T, E >( a: T, b: E ) { - foo::< u32, str >( 10, "bar" ); -} - -fn foo< T: Send, E: Send >( a: T, b: E ) { - foo::< u32, str >( 10, "bar" ); - - let opt: Option< u32 >; - let res: Result< u32, String >; -} - -fn foo< 'a >( a: &'a str ) { - foo( "foo" ); -} - -fn foo< 'a, 'b >( a: &'a str, b: &'b str ) { - foo( "foo", "bar" ); -} - -impl Foo { - fn bar() { - < Foo as Foo >::bar(); - } -} - -trait MyTrait< A, D > {} -impl< A: Send, D: Send > MyTrait< A, D > for Foo {} - -fn foo() -where - for< 'a > u32: 'a, -{ -} - -fn main() { - let arr: [ i32; 5 ] = [ 1, 2, 3, 4, 5 ]; - let arr: [ i32; 500 ] = [ 0; 500 ]; - - let v = vec![ 1, 2, 3 ]; - assert_eq!( arr, [ 1, 2, 3 ] ); - - let i = arr[ 0 ]; - - let slice = &arr[ 1..2 ]; - - let line100_________________________________________________________________________ = [ 1, 2 ]; - let line101__________________________________________________________________________ = - [ 1, 2 ]; - let line102___________________________________________________________________________ = - [ 1, 2 ]; - let line103____________________________________________________________________________ = - [ 1, 2 ]; - let line104_____________________________________________________________________________ = - [ 1, 2 ]; - - let line100_____________________________________________________________________ = vec![ 1, 2 ]; - let line101______________________________________________________________________ = - vec![ 1, 2 ]; - let line102_______________________________________________________________________ = - vec![ 1, 2 ]; - let line103________________________________________________________________________ = - vec![ 1, 2 ]; - let line104_________________________________________________________________________ = - vec![ 1, 2 ]; -} - -fn f( slice: &[ i32 ] ) {} -- cgit 1.4.1-3-g733a5 From 8afe367510b7434f11f95cff2e62ebb544325de5 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:37:55 +1200 Subject: stabilise shorthand options cc #1974 --- src/config/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index ed480aa9fa1..6f9a5fdec78 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -110,11 +110,11 @@ create_config! { // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; - use_try_shorthand: bool, false, false, "Replace uses of the try! macro by the ? shorthand"; + use_try_shorthand: bool, false, true, "Replace uses of the try! macro by the ? shorthand"; + use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible"; + force_explicit_abi: bool, true, true, "Always print the abi for extern items"; condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ in tuple patterns"; - force_explicit_abi: bool, true, true, "Always print the abi for extern items"; - use_field_init_shorthand: bool, false, false, "Use field initialization shorthand if possible"; // Control options (changes the operation of rustfmt, rather than the formatting) write_mode: WriteMode, WriteMode::Overwrite, false, -- cgit 1.4.1-3-g733a5 From a70f71610c65fea32ff4157e2fa23156dc89e3b8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:41:21 +1200 Subject: stabilise `remove_nested_parens` and set default to true --- Configurations.md | 25 +++++++++++++------------ src/config/mod.rs | 3 +-- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index bd52d9d7379..da07adc6ca0 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1260,7 +1260,7 @@ Convert /* */ comments to // comments where possible - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: Yes +- **Stable**: No #### `false` (default): @@ -1286,21 +1286,22 @@ fn adipiscing() -> usize {} Remove nested parens. -- **Defalut value**: `false`, +- **Default value**: `true`, - **Possible values**: `true`, `false` -- **Stable**: No +- **Stable**: Yes -#### `false` (default): + +#### `true` (default): ```rust fn main() { - ((((foo())))); + (foo()); } ``` -#### `true`: +#### `false`: ```rust fn main() { - (foo()); + ((((foo())))); } ``` @@ -1312,7 +1313,7 @@ separated by a newline). - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No +- **Stable**: Yes #### `true` (default): @@ -1339,7 +1340,7 @@ Reorder `mod` declarations alphabetically in group. - **Default value**: `true` - **Possible values**: `true`, `false` -- **Stable**: No +- **Stable**: Yes #### `true` (default) @@ -1764,7 +1765,7 @@ Use field initialize shorthand if possible. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No +- **Stable**: Yes #### `false` (default): @@ -1806,7 +1807,7 @@ Replace uses of the try! macro by the ? shorthand - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No +- **Stable**: Yes #### `false` (default): @@ -1831,7 +1832,7 @@ Break comments to fit on the line - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: Yes +- **Stable**: No #### `false` (default): diff --git a/src/config/mod.rs b/src/config/mod.rs index 6f9a5fdec78..ac39ae2652f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -82,6 +82,7 @@ create_config! { "Where to put a binary operator when a binary expression goes multiline."; // Misc. + remove_nested_parens: bool, true, true, "Remove nested parens."; remove_blank_lines_at_start_or_end_of_block: bool, true, false, "Remove blank lines at start or end of a block"; combine_control_expr: bool, true, false, "Combine control expressions with function calls."; @@ -105,8 +106,6 @@ create_config! { "Maximum number of blank lines which can be put between items."; blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items."; - remove_nested_parens: bool, false, false, - "Remove nested parens."; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; -- cgit 1.4.1-3-g733a5 From dd9c15ad01f0412194ba670ec2a0b38fbecdf46f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:53:08 +1200 Subject: Unstabilise `unstable_features` cc #1974 --- Configurations.md | 2 +- src/config/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index da07adc6ca0..713ecbdab37 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2062,7 +2062,7 @@ Enable unstable features on stable channel. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: Yes +- **Stable**: No ## `license_template_path` diff --git a/src/config/mod.rs b/src/config/mod.rs index ac39ae2652f..1d76a06e3b5 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -123,7 +123,7 @@ create_config! { "What Color option to use when none is supplied: Always, Never, Auto"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, "Require a specific version of rustfmt."; - unstable_features: bool, false, true, + unstable_features: bool, false, false, "Enables unstable features. Only available on nightly channel"; disable_all_formatting: bool, false, false, "Don't reformat anything"; skip_children: bool, false, false, "Don't reformat out of line modules"; -- cgit 1.4.1-3-g733a5 From 2ee8b0e4c533dfa07e25a03a84b28452d68c52eb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 18 May 2018 16:56:55 +1200 Subject: Remove `remove_blank_lines_at_start_or_end_of_block` cc #1974 --- Configurations.md | 39 -------------------- src/config/mod.rs | 2 -- src/visitor.rs | 104 ++++++++++++++++++++++++++---------------------------- 3 files changed, 50 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 713ecbdab37..8c893f98d43 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1991,45 +1991,6 @@ fn bar() { } ``` -## `remove_blank_lines_at_start_or_end_of_block` - -Remove blank lines at the start or the end of a block. - -- **Default value**: `true` -- **Possible values**: `true`, `false` -- **Stable**: No - -#### `true` - -```rust -fn foo() { - let msg = { - let mut str = String::new(); - str.push_str("hello, "); - str.push_str("world!"); - str - }; - println!("{}", msg); -} -``` - -#### `false` - -```rust -fn foo() { - - let msg = { - - let mut str = String::new(); - str.push_str("hello, "); - str.push_str("world!"); - str - - }; - println!("{}", msg); - -} -``` ## `required_version` diff --git a/src/config/mod.rs b/src/config/mod.rs index 1d76a06e3b5..e97a351a52a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -83,8 +83,6 @@ create_config! { // Misc. remove_nested_parens: bool, true, true, "Remove nested parens."; - remove_blank_lines_at_start_or_end_of_block: bool, true, false, - "Remove blank lines at start or end of a block"; combine_control_expr: bool, true, false, "Combine control expressions with function calls."; struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ threshold."; diff --git a/src/visitor.rs b/src/visitor.rs index ec1890035a7..a5f0c4441f6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -128,45 +128,43 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.push_str("{"); - if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(first_stmt) = b.stmts.first() { - let attr_lo = inner_attrs - .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) - .or_else(|| { - // Attributes for an item in a statement position - // do not belong to the statement. (rust-lang/rust#34459) - if let ast::StmtKind::Item(ref item) = first_stmt.node { - item.attrs.first() - } else { - first_stmt.attrs().first() - }.and_then(|attr| { - // Some stmts can have embedded attributes. - // e.g. `match { #![attr] ... }` - let attr_lo = attr.span.lo(); - if attr_lo < first_stmt.span.lo() { - Some(attr_lo) - } else { - None - } - }) - }); - - let snippet = self.snippet(mk_sp( - self.last_pos, - attr_lo.unwrap_or_else(|| first_stmt.span.lo()), - )); - let len = CommentCodeSlices::new(snippet) - .nth(0) - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal { - s.rfind('\n') + if let Some(first_stmt) = b.stmts.first() { + let attr_lo = inner_attrs + .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) + .or_else(|| { + // Attributes for an item in a statement position + // do not belong to the statement. (rust-lang/rust#34459) + if let ast::StmtKind::Item(ref item) = first_stmt.node { + item.attrs.first() + } else { + first_stmt.attrs().first() + }.and_then(|attr| { + // Some stmts can have embedded attributes. + // e.g. `match { #![attr] ... }` + let attr_lo = attr.span.lo(); + if attr_lo < first_stmt.span.lo() { + Some(attr_lo) } else { None } - }); - if let Some(len) = len { - self.last_pos = self.last_pos + BytePos::from_usize(len); - } + }) + }); + + let snippet = self.snippet(mk_sp( + self.last_pos, + attr_lo.unwrap_or_else(|| first_stmt.span.lo()), + )); + let len = CommentCodeSlices::new(snippet) + .nth(0) + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal { + s.rfind('\n') + } else { + None + } + }); + if let Some(len) = len { + self.last_pos = self.last_pos + BytePos::from_usize(len); } } @@ -195,24 +193,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } let mut remove_len = BytePos(0); - if self.config.remove_blank_lines_at_start_or_end_of_block() { - if let Some(stmt) = b.stmts.last() { - let snippet = self.snippet(mk_sp( - stmt.span.hi(), - source!(self, b.span).hi() - brace_compensation, - )); - let len = CommentCodeSlices::new(snippet) - .last() - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal && s.trim().is_empty() { - Some(s.len()) - } else { - None - } - }); - if let Some(len) = len { - remove_len = BytePos::from_usize(len); - } + if let Some(stmt) = b.stmts.last() { + let snippet = self.snippet(mk_sp( + stmt.span.hi(), + source!(self, b.span).hi() - brace_compensation, + )); + let len = CommentCodeSlices::new(snippet) + .last() + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal && s.trim().is_empty() { + Some(s.len()) + } else { + None + } + }); + if let Some(len) = len { + remove_len = BytePos::from_usize(len); } } -- cgit 1.4.1-3-g733a5 From 5d56adb10cd2510594d47fec587c6f54c585f266 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 18 May 2018 17:25:33 -0400 Subject: Fix position of auto in auto trait declaration --- src/items.rs | 2 +- tests/source/trait.rs | 2 ++ tests/target/trait.rs | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 820470ed35c..7da3f8c14d4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -963,9 +963,9 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let mut result = String::with_capacity(128); let header = format!( "{}{}{}trait ", - format_auto(is_auto), format_visibility(&item.vis), format_unsafety(unsafety), + format_auto(is_auto), ); result.push_str(&header); diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 9f0c73694bf..1d1faf2d475 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -95,3 +95,5 @@ trait FooBar = Foo // #2637 auto trait Example {} +pub auto trait PubExample {} +pub unsafe auto trait PubUnsafeExample {} diff --git a/tests/target/trait.rs b/tests/target/trait.rs index a6bc2d89689..b60244f8e4f 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -133,3 +133,5 @@ trait FooBar = Foo // #2637 auto trait Example {} +pub auto trait PubExample {} +pub unsafe auto trait PubUnsafeExample {} -- cgit 1.4.1-3-g733a5 From 912e4bdc905e03f110f02d851a7932b4c7d60f1e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 19 May 2018 08:38:50 +0900 Subject: Fix breaking changes from rustc-ap-syntax cc https://github.com/rust-lang/rust/pull/50045. --- src/closures.rs | 6 +++--- src/expr.rs | 5 +++-- src/matches.rs | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index aec7d34b60a..dc811ea95ad 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -47,7 +47,7 @@ pub fn rewrite_closure( // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; - if let ast::ExprKind::Block(ref block) = body.node { + if let ast::ExprKind::Block(ref block, _) = body.node { // The body of the closure is an empty block. if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { return body @@ -96,7 +96,7 @@ fn get_inner_expr<'a>( prefix: &str, context: &RewriteContext, ) -> &'a ast::Expr { - if let ast::ExprKind::Block(ref block) = expr.node { + if let ast::ExprKind::Block(ref block, _) = expr.node { if !needs_block(block, prefix, context) { // block.stmts.len() == 1 if let Some(expr) = stmt_expr(&block.stmts[0]) { @@ -289,7 +289,7 @@ pub fn rewrite_last_closure( ) -> Option { if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { let body = match body.node { - ast::ExprKind::Block(ref block) + ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && is_simple_block(block, Some(&body.attrs), context.codemap) => { diff --git a/src/expr.rs b/src/expr.rs index 17d9b95d841..8961cec4240 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -118,7 +118,8 @@ pub fn format_expr( | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), - ast::ExprKind::Block(ref block) => { + // FIXME(topecongiro): Handle label on a block (#2722). + ast::ExprKind::Block(ref block, _) => { match expr_type { ExprType::Statement => { if is_unsafe_block(block) { @@ -880,7 +881,7 @@ impl<'a> ControlFlow<'a> { let else_block = self.else_block?; let fixed_cost = self.keyword.len() + " { } else { }".len(); - if let ast::ExprKind::Block(ref else_node) = else_block.node { + if let ast::ExprKind::Block(ref else_node, _) = else_block.node { if !is_simple_block(self.block, None, context.codemap) || !is_simple_block(else_node, None, context.codemap) || pat_expr_str.contains('\n') diff --git a/src/matches.rs b/src/matches.rs index 5a6aa6c6aac..9551dc36002 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -155,7 +155,7 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { "" } else if config.match_block_trailing_comma() { "," - } else if let ast::ExprKind::Block(ref block) = body.node { + } else if let ast::ExprKind::Block(ref block, _) = body.node { if let ast::BlockCheckMode::Default = block.rules { "" } else { @@ -308,7 +308,7 @@ fn rewrite_match_pattern( // @body: flattened body, if the body is block with a single expression fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { match body.node { - ast::ExprKind::Block(ref block) + ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && is_simple_block(block, Some(&body.attrs), context.codemap) => { @@ -337,7 +337,7 @@ fn rewrite_match_body( is_last: bool, ) -> Option { let (extend, body) = flatten_arm_body(context, body); - let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block) = body.node { + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.node { ( true, is_empty_block(block, Some(&body.attrs), context.codemap), -- cgit 1.4.1-3-g733a5 From 760af6cfc9fc0278b1438ac4a4aa8a195db6cbf8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 19 May 2018 15:43:29 +1200 Subject: Make `format_snippet` and `format_code_block` private cc #2639 --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 57e007bf6cd..37d9db2459f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -656,7 +656,7 @@ enum ParseError<'sess> { /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. -pub fn format_snippet(snippet: &str, config: &Config) -> Option { +fn format_snippet(snippet: &str, config: &Config) -> Option { let mut out: Vec = Vec::with_capacity(snippet.len() * 2); let input = Input::Text(snippet.into()); let mut config = config.clone(); @@ -694,7 +694,7 @@ fn enclose_in_main_block(s: &str, config: &Config) -> String { /// The code block may be incomplete (i.e. parser may be unable to parse it). /// To avoid panic in parser, we wrap the code block with a dummy function. /// The returned code block does *not* end with newline. -pub fn format_code_block(code_snippet: &str, config: &Config) -> Option { +fn format_code_block(code_snippet: &str, config: &Config) -> Option { // Wrap the given code block with `fn main()` if it does not have one. let snippet = enclose_in_main_block(code_snippet, config); let mut result = String::with_capacity(snippet.len()); -- cgit 1.4.1-3-g733a5 From 432b1cb253f2b95f3fde4c79d65824efe64aeaf4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 19 May 2018 16:11:30 +1200 Subject: Rationalise error types cc #2639 --- src/bin/main.rs | 8 ++++---- src/config/options.rs | 7 +++---- src/lib.rs | 30 ++++++++++++++++++++---------- 3 files changed, 27 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 2d00d22f492..f6e5c9991eb 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -26,7 +26,7 @@ use getopts::{Matches, Options}; use rustfmt::{ emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Config, - FileName, FmtResult, Input, Summary, Verbosity, WriteMode, + ErrorKind, FileName, Input, Summary, Verbosity, WriteMode, }; fn main() { @@ -170,7 +170,7 @@ fn is_nightly() -> bool { .unwrap_or(false) } -fn execute(opts: &Options) -> FmtResult<(WriteMode, Summary)> { +fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { let matches = opts.parse(env::args().skip(1))?; let options = CliOptions::from_matches(&matches)?; @@ -239,7 +239,7 @@ fn format( files: Vec, minimal_config_path: Option, options: CliOptions, -) -> FmtResult<(WriteMode, Summary)> { +) -> Result<(WriteMode, Summary), failure::Error> { options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(&options))?; @@ -347,7 +347,7 @@ fn print_version() { println!("rustfmt {}", version_info); } -fn determine_operation(matches: &Matches) -> FmtResult { +fn determine_operation(matches: &Matches) -> Result { if matches.opt_present("h") { let topic = matches.opt_str("h"); if topic == None { diff --git a/src/config/options.rs b/src/config/options.rs index 06580339d9e..56587dbce90 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -14,9 +14,8 @@ use config::config_type::ConfigType; use config::file_lines::FileLines; use config::lists::*; use config::Config; -use FmtResult; -use failure::err_msg; +use failure::{self, err_msg}; use getopts::Matches; use std::collections::HashSet; @@ -345,7 +344,7 @@ pub struct CliOptions { } impl CliOptions { - pub fn from_matches(matches: &Matches) -> FmtResult { + pub fn from_matches(matches: &Matches) -> Result { let mut options = CliOptions::default(); options.verbose = matches.opt_present("verbose"); options.quiet = matches.opt_present("quiet"); @@ -448,7 +447,7 @@ impl CliOptions { } } -fn write_mode_from_emit_str(emit_str: &str) -> FmtResult { +fn write_mode_from_emit_str(emit_str: &str) -> Result { match emit_str { "files" => Ok(WriteMode::Overwrite), "stdout" => Ok(WriteMode::Display), diff --git a/src/lib.rs b/src/lib.rs index 37d9db2459f..5a44074c845 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,8 +64,6 @@ pub use config::options::CliOptions; pub use config::summary::Summary; pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; -pub type FmtResult = std::result::Result; - #[macro_use] mod utils; @@ -107,7 +105,7 @@ pub(crate) type FileMap = Vec; pub(crate) type FileRecord = (FileName, String); -#[derive(Fail, Debug, Clone, Copy)] +#[derive(Fail, Debug)] pub enum ErrorKind { // Line has exceeded character limit (found, maximum) #[fail( @@ -132,6 +130,14 @@ pub enum ErrorKind { // Used a rustfmt:: attribute other than skip #[fail(display = "invalid attribute")] BadAttr, + #[fail(display = "io error: {}", _0)] + IoError(io::Error), +} + +impl From for ErrorKind { + fn from(e: io::Error) -> ErrorKind { + ErrorKind::IoError(e) + } } struct FormattingError { @@ -162,7 +168,9 @@ impl FormattingError { } fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => "internal error:", + ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace | ErrorKind::IoError(_) => { + "internal error:" + } ErrorKind::LicenseCheck | ErrorKind::BadAttr => "error:", ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", } @@ -244,6 +252,7 @@ impl FormatReport { | ErrorKind::BadAttr => { errs.has_check_errors = true; } + _ => {} } } } @@ -469,7 +478,7 @@ fn should_report_error( config: &Config, char_kind: FullCodeCharKind, is_string: bool, - error_kind: ErrorKind, + error_kind: &ErrorKind, ) -> bool { let allow_error_report = if char_kind.is_comment() || is_string { config.error_on_unformatted() @@ -541,7 +550,8 @@ fn format_lines( if format_line { // Check for (and record) trailing whitespace. if let Some(..) = last_wspace { - if should_report_error(config, kind, is_string, ErrorKind::TrailingWhitespace) { + if should_report_error(config, kind, is_string, &ErrorKind::TrailingWhitespace) + { trims.push((cur_line, kind, line_buffer.clone())); } line_len -= 1; @@ -551,7 +561,7 @@ fn format_lines( let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); if line_len > config.max_width() && !is_skipped_line(cur_line, skipped_range) - && should_report_error(config, kind, is_string, error_kind) + && should_report_error(config, kind, is_string, &error_kind) { errors.push(FormattingError { line: cur_line, @@ -967,7 +977,7 @@ pub enum Input { Text(String), } -pub fn format_and_emit_report(input: Input, config: &Config) -> FmtResult { +pub fn format_and_emit_report(input: Input, config: &Config) -> Result { if !config.version_meets_requirement() { return Err(format_err!("Version mismatch")); } @@ -1000,7 +1010,7 @@ pub fn format_and_emit_report(input: Input, config: &Config) -> FmtResult FmtResult<()> { +pub fn emit_pre_matter(config: &Config) -> Result<(), ErrorKind> { if config.write_mode() == WriteMode::Checkstyle { let mut out = &mut stdout(); checkstyle::output_header(&mut out)?; @@ -1008,7 +1018,7 @@ pub fn emit_pre_matter(config: &Config) -> FmtResult<()> { Ok(()) } -pub fn emit_post_matter(config: &Config) -> FmtResult<()> { +pub fn emit_post_matter(config: &Config) -> Result<(), ErrorKind> { if config.write_mode() == WriteMode::Checkstyle { let mut out = &mut stdout(); checkstyle::output_footer(&mut out)?; -- cgit 1.4.1-3-g733a5 From abb253df8b8bb8638eaa7ac44d06a042882e5f22 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 19 May 2018 16:44:48 +1200 Subject: Rationalise result and error types --- src/config/summary.rs | 1 - src/lib.rs | 38 ++++++++++---------------------------- src/rewrite.rs | 2 +- src/test/mod.rs | 44 ++++++++++++++++++++------------------------ src/visitor.rs | 4 ++-- 5 files changed, 33 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/config/summary.rs b/src/config/summary.rs index 7b6c25d498b..c7f8124c1c7 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -11,7 +11,6 @@ use std::default::Default; use std::time::{Duration, Instant}; -#[must_use] #[derive(Debug, Default, Clone, Copy)] pub struct Summary { // Encountered e.g. an IO error. diff --git a/src/lib.rs b/src/lib.rs index 5a44074c845..a5e1ada8902 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -206,7 +206,7 @@ impl FormattingError { } #[derive(Clone)] -pub struct FormatReport { +struct FormatReport { // Maps stringified file paths to their associated formatting errors. internal: Rc>, } @@ -756,21 +756,21 @@ pub fn format_input( input: Input, config: &Config, out: Option<&mut T>, -) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { - syntax::with_globals(|| format_input_inner(input, config, out)) +) -> Result { + syntax::with_globals(|| format_input_inner(input, config, out)).map(|tup| tup.0) } fn format_input_inner( input: Input, config: &Config, mut out: Option<&mut T>, -) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> { +) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> { let mut summary = Summary::default(); if config.disable_all_formatting() { // When the input is from stdin, echo back the input. if let Input::Text(ref buf) = input { if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err((e, summary)); + return Err((From::from(e), summary)); } } return Ok((summary, FileMap::new(), FormatReport::new())); @@ -890,7 +890,7 @@ fn format_input_inner( Ok((summary, file_map, report)) } - Err(e) => Err((e, summary)), + Err(e) => Err((From::from(e), summary)), } } @@ -913,33 +913,20 @@ struct ModifiedLines { pub chunks: Vec, } -/// The successful result of formatting via `get_modified_lines()`. -#[cfg(test)] -struct ModifiedLinesResult { - /// The high level summary details - pub summary: Summary, - /// The result Filemap - pub filemap: FileMap, - /// Map of formatting errors - pub report: FormatReport, - /// The sets of updated lines. - pub modified_lines: ModifiedLines, -} - /// Format a file and return a `ModifiedLines` data structure describing /// the changed ranges of lines. #[cfg(test)] fn get_modified_lines( input: Input, config: &Config, -) -> Result { +) -> Result { use std::io::BufRead; let mut data = Vec::new(); let mut config = config.clone(); config.set().write_mode(config::WriteMode::Modified); - let (summary, filemap, report) = format_input(input, &config, Some(&mut data))?; + format_input(input, &config, Some(&mut data))?; let mut lines = data.lines(); let mut chunks = Vec::new(); @@ -963,12 +950,7 @@ fn get_modified_lines( lines: added_lines, }); } - Ok(ModifiedLinesResult { - summary, - filemap, - report, - modified_lines: ModifiedLines { chunks }, - }) + Ok(ModifiedLines { chunks }) } #[derive(Debug)] @@ -982,7 +964,7 @@ pub fn format_and_emit_report(input: Input, config: &Config) -> Result { if report.has_warnings() { match term::stderr() { diff --git a/src/rewrite.rs b/src/rewrite.rs index 0dfae84bfc2..00c03a3c879 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -39,7 +39,7 @@ pub struct RewriteContext<'a> { // When rewriting chain, veto going multi line except the last element pub force_one_line_chain: RefCell, pub snippet_provider: &'a SnippetProvider<'a>, - pub report: FormatReport, + pub(crate) report: FormatReport, } impl<'a> RewriteContext<'a> { diff --git a/src/test/mod.rs b/src/test/mod.rs index b538519ec0b..b4089cc1cfe 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -10,6 +10,8 @@ extern crate assert_cli; +use syntax; + use std::collections::{HashMap, HashSet}; use std::env; use std::fs; @@ -143,7 +145,7 @@ fn modified_test() { let filename = "tests/writemode/source/modified.rs"; let result = get_modified_lines(Input::File(filename.into()), &Config::default()).unwrap(); assert_eq!( - result.modified_lines, + result, ModifiedLines { chunks: vec![ ModifiedChunk { @@ -240,19 +242,13 @@ fn self_tests() { #[test] fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); - let config = Config::default(); - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); + let mut config = Config::default(); + config.set().write_mode(WriteMode::Display); + let mut buf: Vec = vec![]; + let error_summary = format_input(input, &config, Some(&mut buf)).unwrap(); assert!(error_summary.has_no_errors()); - for &(ref file_name, ref text) in &file_map { - if let FileName::Custom(ref file_name) = *file_name { - if file_name == "stdin" { - assert_eq!(text.to_string(), "fn main() {}\n"); - return; - } - } - } - panic!("no stdin"); + //eprintln!("{:?}", ); + assert_eq!(buf, "fn main() {}\n".as_bytes()); } // FIXME(#1990) restore this test @@ -284,8 +280,7 @@ fn format_lines_errors_are_reported() { let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let mut config = Config::default(); config.set().error_on_line_overflow(true); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); + let error_summary = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); } @@ -296,8 +291,7 @@ fn format_lines_errors_are_reported_with_tabs() { let mut config = Config::default(); config.set().error_on_line_overflow(true); config.set().hard_tabs(true); - let (error_summary, _file_map, _report) = - format_input::(input, &config, None).unwrap(); + let error_summary = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); } @@ -382,7 +376,8 @@ fn read_config(filename: &Path) -> Config { fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { let filepath = filepath.into(); let input = Input::File(filepath); - format_input::(input, config, None).unwrap() + //format_input::(input, config, None).unwrap() + syntax::with_globals(|| format_input_inner::(input, config, None)).unwrap() } pub enum IdempotentCheckError { @@ -757,8 +752,7 @@ impl ConfigCodeBlock { }); } - fn formatted_has_diff(&self, file_map: &FileMap) -> bool { - let &(ref _file_name, ref text) = file_map.first().unwrap(); + fn formatted_has_diff(&self, text: &str) -> bool { let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); if !compare.is_empty() { self.print_diff(compare); @@ -778,12 +772,14 @@ impl ConfigCodeBlock { } let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); - let config = self.get_block_config(); + let mut config = self.get_block_config(); + config.set().write_mode(WriteMode::Display); + let mut buf: Vec = vec![]; - let (error_summary, file_map, _report) = - format_input::(input, &config, None).unwrap(); + let error_summary = format_input(input, &config, Some(&mut buf)).unwrap(); - !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&file_map) + !self.has_parsing_errors(error_summary) + && !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) } // Extract a code block from the iterator. Behavior: diff --git a/src/visitor.rs b/src/visitor.rs index a5f0c4441f6..bf1f95381d9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -70,7 +70,7 @@ pub struct FmtVisitor<'a> { pub snippet_provider: &'a SnippetProvider<'a>, pub line_number: usize, pub skipped_range: Vec<(usize, usize)>, - pub report: FormatReport, + pub(crate) report: FormatReport, } impl<'b, 'a: 'b> FmtVisitor<'a> { @@ -561,7 +561,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) } - pub fn from_codemap( + pub(crate) fn from_codemap( parse_session: &'a ParseSess, config: &'a Config, snippet_provider: &'a SnippetProvider, -- cgit 1.4.1-3-g733a5 From 539d4d96651b3516a92d2590aa276a121311b3c5 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 May 2018 11:16:05 +1200 Subject: Refactor CliOptions --- src/bin/main.rs | 158 +++++++++++++++++++++++++++++++++++++++++++++--- src/config/mod.rs | 18 +++--- src/config/options.rs | 142 +------------------------------------------ src/git-rustfmt/main.rs | 16 ++++- src/lib.rs | 3 +- src/test/mod.rs | 4 +- 6 files changed, 180 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index f6e5c9991eb..681e677488c 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -11,6 +11,7 @@ #![cfg(not(test))] extern crate env_logger; +#[macro_use] extern crate failure; extern crate getopts; extern crate rustfmt_nightly as rustfmt; @@ -19,14 +20,15 @@ use std::env; use std::fs::File; use std::io::{self, stdout, Read, Write}; use std::path::{Path, PathBuf}; +use std::str::FromStr; use failure::err_msg; use getopts::{Matches, Options}; use rustfmt::{ - emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Config, - ErrorKind, FileName, Input, Summary, Verbosity, WriteMode, + emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Color, + Config, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, WriteMode, }; fn main() { @@ -172,7 +174,7 @@ fn is_nightly() -> bool { fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { let matches = opts.parse(env::args().skip(1))?; - let options = CliOptions::from_matches(&matches)?; + let options = GetOptsOptions::from_matches(&matches)?; match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { @@ -203,7 +205,7 @@ fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { } Operation::Stdin { input } => { // try to read config from local directory - let (mut config, _) = load_config(Some(Path::new(".")), Some(&options))?; + let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; // write_mode is always Display for Stdin. config.set().write_mode(WriteMode::Display); @@ -238,10 +240,10 @@ fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { fn format( files: Vec, minimal_config_path: Option, - options: CliOptions, + options: GetOptsOptions, ) -> Result<(WriteMode, Summary), failure::Error> { options.verify_file_lines(&files); - let (config, config_path) = load_config(None, Some(&options))?; + let (config, config_path) = load_config(None, Some(options.clone()))?; if config.verbose() == Verbosity::Verbose { if let Some(path) = config_path.as_ref() { @@ -263,7 +265,7 @@ fn format( // Check the file directory if the config-path could not be read or not provided let local_config = if config_path.is_none() { let (local_config, config_path) = - load_config(Some(file.parent().unwrap()), Some(&options))?; + load_config(Some(file.parent().unwrap()), Some(options.clone()))?; if local_config.verbose() == Verbosity::Verbose { if let Some(path) = config_path { println!( @@ -403,3 +405,145 @@ fn determine_operation(matches: &Matches) -> Result { minimal_config_path, }) } + +const STABLE_WRITE_MODES: [WriteMode; 4] = [ + WriteMode::Replace, + WriteMode::Overwrite, + WriteMode::Display, + WriteMode::Check, +]; + +/// Parsed command line options. +#[derive(Clone, Debug, Default)] +struct GetOptsOptions { + skip_children: Option, + quiet: bool, + verbose: bool, + config_path: Option, + write_mode: WriteMode, + check: bool, + color: Option, + file_lines: FileLines, // Default is all lines in all files. + unstable_features: bool, + error_on_unformatted: Option, +} + +impl GetOptsOptions { + pub fn from_matches(matches: &Matches) -> Result { + let mut options = GetOptsOptions::default(); + options.verbose = matches.opt_present("verbose"); + options.quiet = matches.opt_present("quiet"); + if options.verbose && options.quiet { + return Err(format_err!("Can't use both `--verbose` and `--quiet`")); + } + + let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly") + .unwrap_or(false); + if rust_nightly { + options.unstable_features = matches.opt_present("unstable-features"); + } + + if options.unstable_features { + if matches.opt_present("skip-children") { + options.skip_children = Some(true); + } + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = Some(true); + } + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse().map_err(err_msg)?; + } + } + + options.config_path = matches.opt_str("config-path").map(PathBuf::from); + + options.check = matches.opt_present("check"); + if let Some(ref emit_str) = matches.opt_str("emit") { + if options.check { + return Err(format_err!("Invalid to use `--emit` and `--check`")); + } + if let Ok(write_mode) = write_mode_from_emit_str(emit_str) { + options.write_mode = write_mode; + } else { + return Err(format_err!("Invalid value for `--emit`")); + } + } + + if options.write_mode == WriteMode::Overwrite && matches.opt_present("backup") { + options.write_mode = WriteMode::Replace; + } + + if !rust_nightly { + if !STABLE_WRITE_MODES.contains(&options.write_mode) { + return Err(format_err!( + "Invalid value for `--emit` - using an unstable \ + value without `--unstable-features`", + )); + } + } + + if let Some(ref color) = matches.opt_str("color") { + match Color::from_str(color) { + Ok(color) => options.color = Some(color), + _ => return Err(format_err!("Invalid color: {}", color)), + } + } + + Ok(options) + } + + fn verify_file_lines(&self, files: &[PathBuf]) { + for f in self.file_lines.files() { + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) + } + _ => eprintln!("Warning: Not a file '{}'", f), + } + } + } +} + +impl CliOptions for GetOptsOptions { + fn apply_to(self, config: &mut Config) { + if self.verbose { + config.set().verbose(Verbosity::Verbose); + } else if self.quiet { + config.set().verbose(Verbosity::Quiet); + } else { + config.set().verbose(Verbosity::Normal); + } + config.set().file_lines(self.file_lines); + config.set().unstable_features(self.unstable_features); + if let Some(skip_children) = self.skip_children { + config.set().skip_children(skip_children); + } + if let Some(error_on_unformatted) = self.error_on_unformatted { + config.set().error_on_unformatted(error_on_unformatted); + } + if self.check { + config.set().write_mode(WriteMode::Check); + } else { + config.set().write_mode(self.write_mode); + } + if let Some(color) = self.color { + config.set().color(color); + } + } + + fn config_path(&self) -> Option<&Path> { + self.config_path.as_ref().map(|p| &**p) + } +} + +fn write_mode_from_emit_str(emit_str: &str) -> Result { + match emit_str { + "files" => Ok(WriteMode::Overwrite), + "stdout" => Ok(WriteMode::Display), + "coverage" => Ok(WriteMode::Coverage), + "checkstyle" => Ok(WriteMode::Checkstyle), + _ => Err(format_err!("Invalid value for `--emit`")), + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index e97a351a52a..6168c56ef38 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; use std::{env, fs}; use config::config_type::ConfigType; -use config::file_lines::FileLines; +pub use config::file_lines::FileLines; pub use config::lists::*; pub use config::options::*; @@ -146,12 +146,12 @@ create_config! { "'small' heuristic values"; } -pub fn load_config( +pub fn load_config( file_path: Option<&Path>, - options: Option<&CliOptions>, + options: Option, ) -> Result<(Config, Option), Error> { let over_ride = match options { - Some(opts) => config_path(opts)?, + Some(ref opts) => config_path(opts)?, None => None, }; @@ -165,7 +165,7 @@ pub fn load_config( result.map(|(mut c, p)| { if let Some(options) = options { - options.clone().apply_to(&mut c); + options.apply_to(&mut c); } (c, p) }) @@ -208,9 +208,9 @@ fn config_path(options: &CliOptions) -> Result, Error> { // Read the config_path and convert to parent dir if a file is provided. // If a config file cannot be found from the given path, return error. - match options.config_path { - Some(ref path) if !path.exists() => config_path_not_found(path.to_str().unwrap()), - Some(ref path) if path.is_dir() => { + match options.config_path() { + Some(path) if !path.exists() => config_path_not_found(path.to_str().unwrap()), + Some(path) if path.is_dir() => { let config_file_path = get_toml_path(path)?; if config_file_path.is_some() { Ok(config_file_path) @@ -218,7 +218,7 @@ fn config_path(options: &CliOptions) -> Result, Error> { config_path_not_found(path.to_str().unwrap()) } } - ref path => Ok(path.to_owned()), + path => Ok(path.map(|p| p.to_owned())), } } diff --git a/src/config/options.rs b/src/config/options.rs index 56587dbce90..9bf6c380919 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -11,16 +11,11 @@ use syntax::codemap::FileName; use config::config_type::ConfigType; -use config::file_lines::FileLines; use config::lists::*; use config::Config; -use failure::{self, err_msg}; - -use getopts::Matches; use std::collections::HashSet; use std::path::{Path, PathBuf}; -use std::str::FromStr; /// Macro for deriving implementations of Serialize/Deserialize for enums #[macro_export] @@ -193,13 +188,6 @@ configuration_option_enum! { WriteMode: None, } -const STABLE_WRITE_MODES: [WriteMode; 4] = [ - WriteMode::Replace, - WriteMode::Overwrite, - WriteMode::Display, - WriteMode::Check, -]; - configuration_option_enum! { Color: // Always use color, whether it is a piped or terminal output Always, @@ -328,131 +316,7 @@ impl ::std::str::FromStr for IgnoreList { } } -/// Parsed command line options. -#[derive(Clone, Debug, Default)] -pub struct CliOptions { - pub skip_children: Option, - pub quiet: bool, - pub verbose: bool, - pub config_path: Option, - pub write_mode: WriteMode, - pub check: bool, - pub color: Option, - pub file_lines: FileLines, // Default is all lines in all files. - pub unstable_features: bool, - pub error_on_unformatted: Option, -} - -impl CliOptions { - pub fn from_matches(matches: &Matches) -> Result { - let mut options = CliOptions::default(); - options.verbose = matches.opt_present("verbose"); - options.quiet = matches.opt_present("quiet"); - if options.verbose && options.quiet { - return Err(format_err!("Can't use both `--verbose` and `--quiet`")); - } - - let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(false); - if rust_nightly { - options.unstable_features = matches.opt_present("unstable-features"); - } - - if options.unstable_features { - if matches.opt_present("skip-children") { - options.skip_children = Some(true); - } - if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = Some(true); - } - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse().map_err(err_msg)?; - } - } - - options.config_path = matches.opt_str("config-path").map(PathBuf::from); - - options.check = matches.opt_present("check"); - if let Some(ref emit_str) = matches.opt_str("emit") { - if options.check { - return Err(format_err!("Invalid to use `--emit` and `--check`")); - } - if let Ok(write_mode) = write_mode_from_emit_str(emit_str) { - options.write_mode = write_mode; - } else { - return Err(format_err!("Invalid value for `--emit`")); - } - } - - if options.write_mode == WriteMode::Overwrite && matches.opt_present("backup") { - options.write_mode = WriteMode::Replace; - } - - if !rust_nightly { - if !STABLE_WRITE_MODES.contains(&options.write_mode) { - return Err(format_err!( - "Invalid value for `--emit` - using an unstable \ - value without `--unstable-features`", - )); - } - } - - if let Some(ref color) = matches.opt_str("color") { - match Color::from_str(color) { - Ok(color) => options.color = Some(color), - _ => return Err(format_err!("Invalid color: {}", color)), - } - } - - Ok(options) - } - - pub fn apply_to(self, config: &mut Config) { - if self.verbose { - config.set().verbose(Verbosity::Verbose); - } else if self.quiet { - config.set().verbose(Verbosity::Quiet); - } else { - config.set().verbose(Verbosity::Normal); - } - config.set().file_lines(self.file_lines); - config.set().unstable_features(self.unstable_features); - if let Some(skip_children) = self.skip_children { - config.set().skip_children(skip_children); - } - if let Some(error_on_unformatted) = self.error_on_unformatted { - config.set().error_on_unformatted(error_on_unformatted); - } - if self.check { - config.set().write_mode(WriteMode::Check); - } else { - config.set().write_mode(self.write_mode); - } - if let Some(color) = self.color { - config.set().color(color); - } - } - - pub fn verify_file_lines(&self, files: &[PathBuf]) { - for f in self.file_lines.files() { - match *f { - FileName::Real(ref f) if files.contains(f) => {} - FileName::Real(_) => { - eprintln!("Warning: Extra file listed in file_lines option '{}'", f) - } - _ => eprintln!("Warning: Not a file '{}'", f), - } - } - } -} - -fn write_mode_from_emit_str(emit_str: &str) -> Result { - match emit_str { - "files" => Ok(WriteMode::Overwrite), - "stdout" => Ok(WriteMode::Display), - "coverage" => Ok(WriteMode::Coverage), - "checkstyle" => Ok(WriteMode::Checkstyle), - _ => Err(format_err!("Invalid value for `--emit`")), - } +pub trait CliOptions { + fn apply_to(self, config: &mut Config); + fn config_path(&self) -> Option<&Path>; } diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 41b16969dc2..3eae7cdeabd 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -21,7 +21,7 @@ use std::str::FromStr; use getopts::{Matches, Options}; -use rustfmt::{format_and_emit_report, load_config, Input}; +use rustfmt::{format_and_emit_report, load_config, CliOptions, Input}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -68,7 +68,8 @@ fn get_files(input: &str) -> Vec<&str> { } fn fmt_files(files: &[&str]) -> i32 { - let (config, _) = load_config(Some(Path::new(".")), None).expect("couldn't load config"); + let (config, _) = + load_config::(Some(Path::new(".")), None).expect("couldn't load config"); let mut exit_code = 0; for file in files { @@ -80,6 +81,17 @@ fn fmt_files(files: &[&str]) -> i32 { exit_code } +struct NullOptions; + +impl CliOptions for NullOptions { + fn apply_to(self, _: &mut rustfmt::Config) { + unreachable!(); + } + fn config_path(&self) -> Option<&Path> { + unreachable!(); + } +} + fn uncommitted_files() -> Vec { let mut cmd = Command::new("git"); cmd.arg("ls-files"); diff --git a/src/lib.rs b/src/lib.rs index a5e1ada8902..c3fe0db3155 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,6 @@ extern crate derive_new; extern crate diff; #[macro_use] extern crate failure; -extern crate getopts; extern crate itertools; #[cfg(test)] #[macro_use] @@ -62,7 +61,7 @@ use visitor::{FmtVisitor, SnippetProvider}; pub use config::options::CliOptions; pub use config::summary::Summary; -pub use config::{file_lines, load_config, Config, Verbosity, WriteMode}; +pub use config::{load_config, Color, Config, FileLines, Verbosity, WriteMode}; #[macro_use] mod utils; diff --git a/src/test/mod.rs b/src/test/mod.rs index b4089cc1cfe..7507b2de9aa 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -380,12 +380,12 @@ fn format_file>(filepath: P, config: &Config) -> (Summary, File syntax::with_globals(|| format_input_inner::(input, config, None)).unwrap() } -pub enum IdempotentCheckError { +enum IdempotentCheckError { Mismatch(HashMap>), Parse, } -pub fn idempotent_check( +fn idempotent_check( filename: &PathBuf, opt_config: &Option, ) -> Result { -- cgit 1.4.1-3-g733a5 From 843c12601a63961c185c479e258313e568f3a7d8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 May 2018 12:01:31 +1200 Subject: Use our own `FileName` struct rather than exporting libsyntax's --- src/bin/main.rs | 4 ++-- src/config/file_lines.rs | 40 +++++++++++++++++++++++++++++++++------- src/config/mod.rs | 2 +- src/config/options.rs | 4 +--- src/filemap.rs | 3 +-- src/lib.rs | 14 ++++++-------- src/missed_spans.rs | 6 +++--- src/modules.rs | 7 ++++--- src/visitor.rs | 4 ++-- 9 files changed, 53 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 681e677488c..3d86404e029 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -215,7 +215,7 @@ fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { config.set().file_lines(options.file_lines); for f in config.file_lines().files() { match *f { - FileName::Custom(ref f) if f == "stdin" => {} + FileName::Stdin => {} _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), } } @@ -500,7 +500,7 @@ impl GetOptsOptions { FileName::Real(_) => { eprintln!("Warning: Extra file listed in file_lines option '{}'", f) } - _ => eprintln!("Warning: Not a file '{}'", f), + FileName::Stdin => eprintln!("Warning: Not a file '{}'", f), } } } diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 5e29e0ff965..8fbd1e02ca0 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -11,13 +11,14 @@ //! This module contains types and functions to support formatting specific line ranges. use std::collections::HashMap; +use std::path::PathBuf; use std::rc::Rc; -use std::{cmp, iter, str}; +use std::{cmp, fmt, iter, str}; use serde::de::{Deserialize, Deserializer}; use serde_json as json; -use syntax::codemap::{FileMap, FileName}; +use syntax::codemap::{self, FileMap}; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { @@ -26,9 +27,34 @@ pub struct LineRange { pub hi: usize, } +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum FileName { + Real(PathBuf), + Stdin, +} + +impl From for FileName { + fn from(name: codemap::FileName) -> FileName { + match name { + codemap::FileName::Real(p) => FileName::Real(p), + codemap::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, + _ => unreachable!(), + } + } +} + +impl fmt::Display for FileName { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + FileName::Real(p) => write!(f, "{}", p.to_str().unwrap()), + FileName::Stdin => write!(f, "stdin"), + } + } +} + impl LineRange { - pub fn file_name(&self) -> &FileName { - &self.file.name + pub fn file_name(&self) -> FileName { + self.file.name.clone().into() } } @@ -169,12 +195,12 @@ impl FileLines { /// Returns true if `range` is fully contained in `self`. #[allow(dead_code)] pub(crate) fn contains(&self, range: &LineRange) -> bool { - self.file_range_matches(range.file_name(), |r| r.contains(Range::from(range))) + self.file_range_matches(&range.file_name(), |r| r.contains(Range::from(range))) } /// Returns true if any lines in `range` are in `self`. pub(crate) fn intersects(&self, range: &LineRange) -> bool { - self.file_range_matches(range.file_name(), |r| r.intersects(Range::from(range))) + self.file_range_matches(&range.file_name(), |r| r.intersects(Range::from(range))) } /// Returns true if `line` from `file_name` is in `self`. @@ -232,7 +258,7 @@ struct JsonSpan { fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { let s = String::deserialize(d)?; if s == "stdin" { - Ok(FileName::Custom(s)) + Ok(FileName::Stdin) } else { Ok(FileName::Real(s.into())) } diff --git a/src/config/mod.rs b/src/config/mod.rs index 6168c56ef38..3724b120228 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; use std::{env, fs}; use config::config_type::ConfigType; -pub use config::file_lines::FileLines; +pub use config::file_lines::{FileLines, FileName}; pub use config::lists::*; pub use config::options::*; diff --git a/src/config/options.rs b/src/config/options.rs index 9bf6c380919..5ba2b23b6cf 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::codemap::FileName; - use config::config_type::ConfigType; use config::lists::*; -use config::Config; +use config::{Config, FileName}; use std::collections::HashSet; use std::path::{Path, PathBuf}; diff --git a/src/filemap.rs b/src/filemap.rs index d61a3aa2a74..8cb992e2b8d 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -15,9 +15,8 @@ use std::io::{self, BufWriter, Read, Write}; use std::path::Path; use checkstyle::output_checkstyle_file; -use config::{Config, NewlineStyle, Verbosity, WriteMode}; +use config::{Config, FileName, NewlineStyle, Verbosity, WriteMode}; use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; -use syntax::codemap::FileName; #[cfg(test)] use FileRecord; diff --git a/src/lib.rs b/src/lib.rs index c3fe0db3155..066411e4d67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,6 @@ use std::rc::Rc; use std::time::Duration; use syntax::ast; -pub use syntax::codemap::FileName; use syntax::codemap::{CodeMap, FilePathMapping, Span}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::{DiagnosticBuilder, Handler}; @@ -59,9 +58,10 @@ use shape::Indent; use utils::use_colored_tty; use visitor::{FmtVisitor, SnippetProvider}; -pub use config::options::CliOptions; pub use config::summary::Summary; -pub use config::{load_config, Color, Config, FileLines, Verbosity, WriteMode}; +pub use config::{ + load_config, CliOptions, Color, Config, FileLines, FileName, Verbosity, WriteMode, +}; #[macro_use] mod utils; @@ -97,8 +97,6 @@ mod types; mod vertical; pub(crate) mod visitor; -const STDIN: &str = ""; - // A map of the files of a crate, with their new content pub(crate) type FileMap = Vec; @@ -397,7 +395,7 @@ fn should_emit_verbose(path: &FileName, config: &Config, f: F) where F: Fn(), { - if config.verbose() == Verbosity::Verbose && path.to_string() != STDIN { + if config.verbose() == Verbosity::Verbose && path != &FileName::Stdin { f(); } } @@ -626,7 +624,7 @@ fn parse_input<'sess>( Input::File(file) => parse::new_parser_from_file(parse_session, &file), Input::Text(text) => parse::new_parser_from_source_str( parse_session, - FileName::Custom("stdin".to_owned()), + syntax::codemap::FileName::Custom("stdin".to_owned()), text, ), }; @@ -797,7 +795,7 @@ fn format_input_inner( let main_file = match input { Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Custom("stdin".to_owned()), + Input::Text(..) => FileName::Stdin, }; let krate = match parse_input(input, &parse_session, config) { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 1a5c6d4f2e6..fbead850eaa 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -10,11 +10,11 @@ use std::borrow::Cow; -use syntax::codemap::{BytePos, FileName, Pos, Span}; +use syntax::codemap::{BytePos, Pos, Span}; use codemap::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; -use config::WriteMode; +use config::{FileName, WriteMode}; use shape::{Indent, Shape}; use utils::{count_newlines, last_line_width, mk_sp}; use visitor::FmtVisitor; @@ -177,7 +177,7 @@ impl<'a> FmtVisitor<'a> { // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. let char_pos = self.codemap.lookup_char_pos(span.lo()); - let file_name = &char_pos.file.name; + let file_name = &char_pos.file.name.clone().into(); let mut status = SnippetStatus::new(char_pos.line); let snippet = &*match self.config.write_mode() { diff --git a/src/modules.rs b/src/modules.rs index 80a7e85c71d..d94b2dd1333 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -13,9 +13,10 @@ use std::io; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::codemap::{self, FileName}; +use syntax::codemap; use syntax::parse::{parser, DirectoryOwnership}; +use config::FileName; use utils::contains_skip; /// List all the files containing modules of a crate. @@ -28,12 +29,12 @@ pub fn list_files<'a>( let root_filename = codemap.span_to_filename(krate.span); { let parent = match root_filename { - FileName::Real(ref path) => path.parent().unwrap(), + codemap::FileName::Real(ref path) => path.parent().unwrap(), _ => Path::new(""), }; list_submodules(&krate.module, parent, None, codemap, &mut result)?; } - result.insert(root_filename, &krate.module); + result.insert(root_filename.into(), &krate.module); Ok(result) } diff --git a/src/visitor.rs b/src/visitor.rs index bf1f95381d9..4a0ce4399a4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -594,7 +594,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { if attr.name() == DEPR_SKIP_ANNOTATION { - let file_name = self.codemap.span_to_filename(attr.span); + let file_name = self.codemap.span_to_filename(attr.span).into(); self.report.append( file_name, vec![FormattingError::from_span( @@ -607,7 +607,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if attr.path.segments.len() == 1 || attr.path.segments[1].ident.to_string() != "skip" { - let file_name = self.codemap.span_to_filename(attr.span); + let file_name = self.codemap.span_to_filename(attr.span).into(); self.report.append( file_name, vec![FormattingError::from_span( -- cgit 1.4.1-3-g733a5 From 95d6b648293b417309d0857b2a93c0cace70c53d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 May 2018 14:11:15 +1200 Subject: Replace WriteMode with EmitMode and backup bool --- Configurations.md | 15 ++++--- src/bin/main.rs | 76 ++++++++++++++++++-------------- src/config/mod.rs | 6 +-- src/config/options.rs | 22 ++++----- src/filemap.rs | 23 +++++----- src/lib.rs | 10 ++--- src/missed_spans.rs | 6 +-- src/test/mod.rs | 4 +- tests/coverage/source/comments.rs | 2 +- tests/coverage/target/comments.rs | 2 +- tests/writemode/source/fn-single-line.rs | 2 +- 11 files changed, 87 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 8c893f98d43..6c4e7dc7760 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1885,13 +1885,6 @@ fn main() { See also: [`match_block_trailing_comma`](#match_block_trailing_comma). -## `write_mode` - -What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage - -- **Default value**: `"Overwrite"` -- **Possible values**: `"Checkstyle"`, `"Coverage"`, `"Diff"`, `"Display"`, `"Overwrite"`, `"Plain"`, `"Replace"` -- **Stable**: No ## `blank_lines_upper_bound` @@ -2071,3 +2064,11 @@ ignore [ "examples", ] ``` + +## `emit_mode` + +Internal option + +## `make_backup` + +Internal option, use `--backup` diff --git a/src/bin/main.rs b/src/bin/main.rs index 3d86404e029..19b93ca0d50 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -28,7 +28,7 @@ use getopts::{Matches, Options}; use rustfmt::{ emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Color, - Config, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, WriteMode, + Config, EmitMode, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, }; fn main() { @@ -36,10 +36,10 @@ fn main() { let opts = make_opts(); let exit_code = match execute(&opts) { - Ok((write_mode, summary)) => { + Ok((exit_mode, summary)) => { if summary.has_operational_errors() || summary.has_parsing_errors() || ((summary.has_diff || summary.has_check_errors()) - && write_mode == WriteMode::Check) + && exit_mode == ExitCodeMode::Check) { 1 } else { @@ -172,26 +172,26 @@ fn is_nightly() -> bool { .unwrap_or(false) } -fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { +fn execute(opts: &Options) -> Result<(ExitCodeMode, Summary), failure::Error> { let matches = opts.parse(env::args().skip(1))?; let options = GetOptsOptions::from_matches(&matches)?; match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { print_usage_to_stdout(opts, ""); - Ok((WriteMode::None, Summary::default())) + Ok((ExitCodeMode::Normal, Summary::default())) } Operation::Help(HelpOp::Config) => { Config::print_docs(&mut stdout(), options.unstable_features); - Ok((WriteMode::None, Summary::default())) + Ok((ExitCodeMode::Normal, Summary::default())) } Operation::Help(HelpOp::FileLines) => { print_help_file_lines(); - Ok((WriteMode::None, Summary::default())) + Ok((ExitCodeMode::Normal, Summary::default())) } Operation::Version => { print_version(); - Ok((WriteMode::None, Summary::default())) + Ok((ExitCodeMode::Normal, Summary::default())) } Operation::ConfigOutputDefault { path } => { let toml = Config::default().all_options().to_toml().map_err(err_msg)?; @@ -201,14 +201,14 @@ fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { } else { io::stdout().write_all(toml.as_bytes())?; } - Ok((WriteMode::None, Summary::default())) + Ok((ExitCodeMode::Normal, Summary::default())) } Operation::Stdin { input } => { // try to read config from local directory let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; - // write_mode is always Display for Stdin. - config.set().write_mode(WriteMode::Display); + // emit mode is always Stdout for Stdin. + config.set().emit_mode(EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); // parse file_lines @@ -228,7 +228,7 @@ fn execute(opts: &Options) -> Result<(WriteMode, Summary), failure::Error> { } emit_post_matter(&config)?; - Ok((WriteMode::Display, error_summary)) + Ok((ExitCodeMode::Normal, error_summary)) } Operation::Format { files, @@ -241,7 +241,7 @@ fn format( files: Vec, minimal_config_path: Option, options: GetOptsOptions, -) -> Result<(WriteMode, Summary), failure::Error> { +) -> Result<(ExitCodeMode, Summary), failure::Error> { options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(options.clone()))?; @@ -299,7 +299,12 @@ fn format( file.write_all(toml.as_bytes())?; } - Ok((config.write_mode(), error_summary)) + let exit_mode = if options.check { + ExitCodeMode::Check + } else { + ExitCodeMode::Normal + }; + Ok((exit_mode, error_summary)) } fn print_usage_to_stdout(opts: &Options, reason: &str) { @@ -406,12 +411,13 @@ fn determine_operation(matches: &Matches) -> Result { }) } -const STABLE_WRITE_MODES: [WriteMode; 4] = [ - WriteMode::Replace, - WriteMode::Overwrite, - WriteMode::Display, - WriteMode::Check, -]; +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +enum ExitCodeMode { + Normal, + Check, +} + +const STABLE_EMIT_MODES: [EmitMode; 3] = [EmitMode::Files, EmitMode::Stdout, EmitMode::Diff]; /// Parsed command line options. #[derive(Clone, Debug, Default)] @@ -420,7 +426,8 @@ struct GetOptsOptions { quiet: bool, verbose: bool, config_path: Option, - write_mode: WriteMode, + emit_mode: EmitMode, + backup: bool, check: bool, color: Option, file_lines: FileLines, // Default is all lines in all files. @@ -463,19 +470,19 @@ impl GetOptsOptions { if options.check { return Err(format_err!("Invalid to use `--emit` and `--check`")); } - if let Ok(write_mode) = write_mode_from_emit_str(emit_str) { - options.write_mode = write_mode; + if let Ok(emit_mode) = emit_mode_from_emit_str(emit_str) { + options.emit_mode = emit_mode; } else { return Err(format_err!("Invalid value for `--emit`")); } } - if options.write_mode == WriteMode::Overwrite && matches.opt_present("backup") { - options.write_mode = WriteMode::Replace; + if matches.opt_present("backup") { + options.backup = true; } if !rust_nightly { - if !STABLE_WRITE_MODES.contains(&options.write_mode) { + if !STABLE_EMIT_MODES.contains(&options.emit_mode) { return Err(format_err!( "Invalid value for `--emit` - using an unstable \ value without `--unstable-features`", @@ -524,9 +531,12 @@ impl CliOptions for GetOptsOptions { config.set().error_on_unformatted(error_on_unformatted); } if self.check { - config.set().write_mode(WriteMode::Check); + config.set().emit_mode(EmitMode::Diff); } else { - config.set().write_mode(self.write_mode); + config.set().emit_mode(self.emit_mode); + } + if self.backup { + config.set().make_backup(true); } if let Some(color) = self.color { config.set().color(color); @@ -538,12 +548,12 @@ impl CliOptions for GetOptsOptions { } } -fn write_mode_from_emit_str(emit_str: &str) -> Result { +fn emit_mode_from_emit_str(emit_str: &str) -> Result { match emit_str { - "files" => Ok(WriteMode::Overwrite), - "stdout" => Ok(WriteMode::Display), - "coverage" => Ok(WriteMode::Coverage), - "checkstyle" => Ok(WriteMode::Checkstyle), + "files" => Ok(EmitMode::Files), + "stdout" => Ok(EmitMode::Stdout), + "coverage" => Ok(EmitMode::Coverage), + "checkstyle" => Ok(EmitMode::Checkstyle), _ => Err(format_err!("Invalid value for `--emit`")), } } diff --git a/src/config/mod.rs b/src/config/mod.rs index 3724b120228..05531a7e2e7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -114,9 +114,6 @@ create_config! { in tuple patterns"; // Control options (changes the operation of rustfmt, rather than the formatting) - write_mode: WriteMode, WriteMode::Overwrite, false, - "What Write Mode to use when none is supplied: \ - Replace, Overwrite, Display, Plain, Diff, Coverage, Check"; color: Color, Color::Auto, false, "What Color option to use when none is supplied: Always, Never, Auto"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, @@ -144,6 +141,9 @@ create_config! { via the --file-lines option"; width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, "'small' heuristic values"; + emit_mode: EmitMode, EmitMode::Files, false, + "What emit Mode to use when none is supplied"; + make_backup: bool, false, false, "Backup changed files"; } pub fn load_config( diff --git a/src/config/options.rs b/src/config/options.rs index 5ba2b23b6cf..9b4b57a7bfd 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -165,25 +165,21 @@ configuration_option_enum! { ReportTactic: Never, } -configuration_option_enum! { WriteMode: - // Overwrites original file without backup. - Overwrite, - // Backs the original file up and overwrites the original. - Replace, +configuration_option_enum! { EmitMode: + // Emits to files. + Files, // Writes the output to stdout. - Display, + Stdout, // Displays how much of the input file was processed Coverage, // Unfancy stdout Checkstyle, // Output the changed lines (for internal value only) - Modified, + ModifiedLines, // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. // This option is designed to be run in CI where a non-zero exit signifies non-standard code // formatting. - Check, - // Rustfmt shouldn't output anything formatting-like (e.g., emit a help message). - None, + Diff, } configuration_option_enum! { Color: @@ -266,9 +262,9 @@ impl ::std::str::FromStr for WidthHeuristics { } } -impl Default for WriteMode { - fn default() -> WriteMode { - WriteMode::Overwrite +impl Default for EmitMode { + fn default() -> EmitMode { + EmitMode::Files } } diff --git a/src/filemap.rs b/src/filemap.rs index 8cb992e2b8d..7e0c7101643 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -15,7 +15,7 @@ use std::io::{self, BufWriter, Read, Write}; use std::path::Path; use checkstyle::output_checkstyle_file; -use config::{Config, FileName, NewlineStyle, Verbosity, WriteMode}; +use config::{Config, EmitMode, FileName, NewlineStyle, Verbosity}; use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; #[cfg(test)] @@ -35,13 +35,13 @@ pub(crate) fn write_all_files( where T: Write, { - if config.write_mode() == WriteMode::Checkstyle { + if config.emit_mode() == EmitMode::Checkstyle { ::checkstyle::output_header(out)?; } for &(ref filename, ref text) in file_map { write_file(text, filename, out, config)?; } - if config.write_mode() == WriteMode::Checkstyle { + if config.emit_mode() == EmitMode::Checkstyle { ::checkstyle::output_footer(out)?; } @@ -116,11 +116,11 @@ where let filename_to_path = || match *filename { FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` with WriteMode::Replace", filename), + _ => panic!("cannot format `{}` and emit to files", filename), }; - match config.write_mode() { - WriteMode::Replace => { + match config.emit_mode() { + EmitMode::Files if config.make_backup() => { let filename = filename_to_path(); if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { if fmt != ori { @@ -140,7 +140,7 @@ where } } } - WriteMode::Overwrite => { + EmitMode::Files => { // Write text directly over original file if there is a diff. let filename = filename_to_path(); let (source, formatted) = source_and_formatted_text(text, filename, config)?; @@ -149,13 +149,13 @@ where write_system_newlines(file, text, config)?; } } - WriteMode::Display | WriteMode::Coverage => { + EmitMode::Stdout | EmitMode::Coverage => { if config.verbose() != Verbosity::Quiet { println!("{}:\n", filename); } write_system_newlines(out, text, config)?; } - WriteMode::Modified => { + EmitMode::ModifiedLines => { let filename = filename_to_path(); if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { let mismatch = make_diff(&ori, &fmt, 0); @@ -164,12 +164,12 @@ where return Ok(has_diff); } } - WriteMode::Checkstyle => { + EmitMode::Checkstyle => { let filename = filename_to_path(); let diff = create_diff(filename, text, config)?; output_checkstyle_file(out, filename, diff)?; } - WriteMode::Check => { + EmitMode::Diff => { let filename = filename_to_path(); if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { let mismatch = make_diff(&ori, &fmt, 3); @@ -182,7 +182,6 @@ where return Ok(has_diff); } } - WriteMode::None => {} } // when we are not in diff mode, don't indicate differing files diff --git a/src/lib.rs b/src/lib.rs index 066411e4d67..1048e295d2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ use visitor::{FmtVisitor, SnippetProvider}; pub use config::summary::Summary; pub use config::{ - load_config, CliOptions, Color, Config, FileLines, FileName, Verbosity, WriteMode, + load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, Verbosity, }; #[macro_use] @@ -667,7 +667,7 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { let mut out: Vec = Vec::with_capacity(snippet.len() * 2); let input = Input::Text(snippet.into()); let mut config = config.clone(); - config.set().write_mode(config::WriteMode::Display); + config.set().emit_mode(config::EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); config.set().hide_parse_errors(true); match format_input(input, &config, Some(&mut out)) { @@ -922,7 +922,7 @@ fn get_modified_lines( let mut data = Vec::new(); let mut config = config.clone(); - config.set().write_mode(config::WriteMode::Modified); + config.set().emit_mode(config::EmitMode::ModifiedLines); format_input(input, &config, Some(&mut data))?; let mut lines = data.lines(); @@ -990,7 +990,7 @@ pub fn format_and_emit_report(input: Input, config: &Config) -> Result Result<(), ErrorKind> { - if config.write_mode() == WriteMode::Checkstyle { + if config.emit_mode() == EmitMode::Checkstyle { let mut out = &mut stdout(); checkstyle::output_header(&mut out)?; } @@ -998,7 +998,7 @@ pub fn emit_pre_matter(config: &Config) -> Result<(), ErrorKind> { } pub fn emit_post_matter(config: &Config) -> Result<(), ErrorKind> { - if config.write_mode() == WriteMode::Checkstyle { + if config.emit_mode() == EmitMode::Checkstyle { let mut out = &mut stdout(); checkstyle::output_footer(&mut out)?; } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index fbead850eaa..7adc53bde84 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -14,7 +14,7 @@ use syntax::codemap::{BytePos, Pos, Span}; use codemap::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; -use config::{FileName, WriteMode}; +use config::{EmitMode, FileName}; use shape::{Indent, Shape}; use utils::{count_newlines, last_line_width, mk_sp}; use visitor::FmtVisitor; @@ -180,8 +180,8 @@ impl<'a> FmtVisitor<'a> { let file_name = &char_pos.file.name.clone().into(); let mut status = SnippetStatus::new(char_pos.line); - let snippet = &*match self.config.write_mode() { - WriteMode::Coverage => Cow::from(replace_chars(old_snippet)), + let snippet = &*match self.config.emit_mode() { + EmitMode::Coverage => Cow::from(replace_chars(old_snippet)), _ => Cow::from(old_snippet), }; diff --git a/src/test/mod.rs b/src/test/mod.rs index 7507b2de9aa..c151fa3def7 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -243,7 +243,7 @@ fn self_tests() { fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); let mut config = Config::default(); - config.set().write_mode(WriteMode::Display); + config.set().emit_mode(EmitMode::Stdout); let mut buf: Vec = vec![]; let error_summary = format_input(input, &config, Some(&mut buf)).unwrap(); assert!(error_summary.has_no_errors()); @@ -773,7 +773,7 @@ impl ConfigCodeBlock { let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); let mut config = self.get_block_config(); - config.set().write_mode(WriteMode::Display); + config.set().emit_mode(EmitMode::Stdout); let mut buf: Vec = vec![]; let error_summary = format_input(input, &config, Some(&mut buf)).unwrap(); diff --git a/tests/coverage/source/comments.rs b/tests/coverage/source/comments.rs index e79557af713..10940039e8e 100644 --- a/tests/coverage/source/comments.rs +++ b/tests/coverage/source/comments.rs @@ -1,4 +1,4 @@ -// rustfmt-write_mode: coverage +// rustfmt-emit_mode: coverage /// Here's a doc comment! fn main() { // foo is bar diff --git a/tests/coverage/target/comments.rs b/tests/coverage/target/comments.rs index 8f9c223aef2..95e7b4705e3 100644 --- a/tests/coverage/target/comments.rs +++ b/tests/coverage/target/comments.rs @@ -1,4 +1,4 @@ -XX XXXXXXXXXXXXXXXXXXX XXXXXXXX +XX XXXXXXXXXXXXXXXXXX XXXXXXXX /// Here's a doc comment! fn main() { XX XXX XX XXX diff --git a/tests/writemode/source/fn-single-line.rs b/tests/writemode/source/fn-single-line.rs index 289dd9aa093..ab1e13e17a7 100644 --- a/tests/writemode/source/fn-single-line.rs +++ b/tests/writemode/source/fn-single-line.rs @@ -1,5 +1,5 @@ // rustfmt-fn_single_line: true -// rustfmt-write_mode: checkstyle +// rustfmt-emit_mode: checkstyle // Test single-line functions. fn foo_expr() { -- cgit 1.4.1-3-g733a5 From 9a7fac63c8867fc5cf45b3f262f2e385f6992fb3 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 May 2018 15:09:17 +1200 Subject: Remove `format_and_emit_report` from the API Also changes the header/footer stuff --- src/bin/main.rs | 56 ++++++++++++++++++++++++++---- src/checkstyle.rs | 16 +++------ src/filemap.rs | 4 +-- src/git-rustfmt/main.rs | 12 +++++-- src/lib.rs | 90 +++++++++++++------------------------------------ src/rustfmt_diff.rs | 1 - src/test/mod.rs | 8 ++--- 7 files changed, 94 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 19b93ca0d50..737eaa93670 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -9,6 +9,7 @@ // except according to those terms. #![cfg(not(test))] +#![feature(extern_prelude)] extern crate env_logger; #[macro_use] @@ -27,8 +28,8 @@ use failure::err_msg; use getopts::{Matches, Options}; use rustfmt::{ - emit_post_matter, emit_pre_matter, format_and_emit_report, load_config, CliOptions, Color, - Config, EmitMode, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, + checkstyle_footer, checkstyle_header, format_input, load_config, use_colored_tty, CliOptions, + Color, Config, EmitMode, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, }; fn main() { @@ -221,12 +222,12 @@ fn execute(opts: &Options) -> Result<(ExitCodeMode, Summary), failure::Error> { } let mut error_summary = Summary::default(); - emit_pre_matter(&config)?; + emit_pre_matter(&config); match format_and_emit_report(Input::Text(input), &config) { Ok(summary) => error_summary.add(summary), Err(_) => error_summary.add_operational_error(), } - emit_post_matter(&config)?; + emit_post_matter(&config); Ok((ExitCodeMode::Normal, error_summary)) } @@ -251,7 +252,7 @@ fn format( } } - emit_pre_matter(&config)?; + emit_pre_matter(&config); let mut error_summary = Summary::default(); for file in files { @@ -289,7 +290,7 @@ fn format( } } } - emit_post_matter(&config)?; + emit_post_matter(&config); // If we were given a path via dump-minimal-config, output any options // that were used during formatting as TOML. @@ -307,6 +308,49 @@ fn format( Ok((exit_mode, error_summary)) } +fn format_and_emit_report(input: Input, config: &Config) -> Result { + let out = &mut stdout(); + + match format_input(input, config, Some(out)) { + Ok((summary, report)) => { + if report.has_warnings() { + match term::stderr() { + Some(ref t) + if use_colored_tty(config.color()) + && t.supports_color() + && t.supports_attr(term::Attr::Bold) => + { + match report.fancy_print(term::stderr().unwrap()) { + Ok(..) => (), + Err(..) => panic!("Unable to write to stderr: {}", report), + } + } + _ => eprintln!("{}", report), + } + } + + Ok(summary) + } + Err((msg, mut summary)) => { + eprintln!("Error writing files: {}", msg); + summary.add_operational_error(); + Ok(summary) + } + } +} + +fn emit_pre_matter(config: &Config) { + if config.emit_mode() == EmitMode::Checkstyle { + println!("{}", checkstyle_header()); + } +} + +fn emit_post_matter(config: &Config) { + if config.emit_mode() == EmitMode::Checkstyle { + println!("{}", checkstyle_footer()); + } +} + fn print_usage_to_stdout(opts: &Options, reason: &str) { let sep = if reason.is_empty() { String::new() diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 19d737cd4c2..7e8f83eaad5 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -13,24 +13,16 @@ use std::path::Path; use rustfmt_diff::{DiffLine, Mismatch}; -pub fn output_header(out: &mut T) -> Result<(), io::Error> -where - T: Write, -{ +pub fn header() -> String { let mut xml_heading = String::new(); xml_heading.push_str(""); xml_heading.push_str("\n"); xml_heading.push_str(""); - write!(out, "{}", xml_heading) + xml_heading } -pub fn output_footer(out: &mut T) -> Result<(), io::Error> -where - T: Write, -{ - let mut xml_tail = String::new(); - xml_tail.push_str("\n"); - write!(out, "{}", xml_tail) +pub fn footer() -> String { + "\n".to_owned() } pub fn output_checkstyle_file( diff --git a/src/filemap.rs b/src/filemap.rs index 7e0c7101643..96d9abc2a35 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -36,13 +36,13 @@ where T: Write, { if config.emit_mode() == EmitMode::Checkstyle { - ::checkstyle::output_header(out)?; + write!(out, "{}", ::checkstyle::header())?; } for &(ref filename, ref text) in file_map { write_file(text, filename, out, config)?; } if config.emit_mode() == EmitMode::Checkstyle { - ::checkstyle::output_footer(out)?; + write!(out, "{}", ::checkstyle::footer())?; } Ok(()) diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 3eae7cdeabd..545756576c9 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -15,13 +15,14 @@ extern crate log; extern crate rustfmt_nightly as rustfmt; use std::env; +use std::io::stdout; use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; use getopts::{Matches, Options}; -use rustfmt::{format_and_emit_report, load_config, CliOptions, Input}; +use rustfmt::{format_input, load_config, CliOptions, Input}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -73,7 +74,14 @@ fn fmt_files(files: &[&str]) -> i32 { let mut exit_code = 0; for file in files { - let summary = format_and_emit_report(Input::File(PathBuf::from(file)), &config).unwrap(); + let (summary, report) = format_input( + Input::File(PathBuf::from(file)), + &config, + Some(&mut stdout()), + ).unwrap(); + if report.has_warnings() { + eprintln!("{}", report); + } if !summary.has_no_errors() { exit_code = 1; } diff --git a/src/lib.rs b/src/lib.rs index 1048e295d2a..e84d2021f41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,11 +13,11 @@ #![allow(unused_attributes)] #![feature(type_ascription)] #![feature(unicode_internals)] +#![feature(extern_prelude)] #[macro_use] extern crate derive_new; extern crate diff; -#[macro_use] extern crate failure; extern crate itertools; #[cfg(test)] @@ -32,14 +32,13 @@ extern crate serde; extern crate serde_derive; extern crate serde_json; extern crate syntax; -extern crate term; extern crate toml; extern crate unicode_segmentation; use std::cell::RefCell; use std::collections::HashMap; use std::fmt; -use std::io::{self, stdout, Write}; +use std::io::{self, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::PathBuf; use std::rc::Rc; @@ -55,13 +54,14 @@ use comment::{CharClasses, FullCodeCharKind, LineClasses}; use failure::Fail; use issues::{BadIssueSeeker, Issue}; use shape::Indent; -use utils::use_colored_tty; use visitor::{FmtVisitor, SnippetProvider}; +pub use checkstyle::{footer as checkstyle_footer, header as checkstyle_header}; pub use config::summary::Summary; pub use config::{ load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, Verbosity, }; +pub use utils::use_colored_tty; #[macro_use] mod utils; @@ -129,6 +129,8 @@ pub enum ErrorKind { BadAttr, #[fail(display = "io error: {}", _0)] IoError(io::Error), + #[fail(display = "Version mismatch")] + VersionMismatch, } impl From for ErrorKind { @@ -168,7 +170,7 @@ impl FormattingError { ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace | ErrorKind::IoError(_) => { "internal error:" } - ErrorKind::LicenseCheck | ErrorKind::BadAttr => "error:", + ErrorKind::LicenseCheck | ErrorKind::BadAttr | ErrorKind::VersionMismatch => "error:", ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", } } @@ -203,7 +205,7 @@ impl FormattingError { } #[derive(Clone)] -struct FormatReport { +pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. internal: Rc>, } @@ -246,7 +248,8 @@ impl FormatReport { ErrorKind::BadIssue(_) | ErrorKind::LicenseCheck | ErrorKind::DeprecatedAttr - | ErrorKind::BadAttr => { + | ErrorKind::BadAttr + | ErrorKind::VersionMismatch => { errs.has_check_errors = true; } _ => {} @@ -263,11 +266,11 @@ impl FormatReport { .sum() } - fn has_warnings(&self) -> bool { + pub fn has_warnings(&self) -> bool { self.warning_count() > 0 } - fn print_warnings_fancy( + pub fn fancy_print( &self, mut t: Box>, ) -> Result<(), term::Error> { @@ -749,12 +752,22 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { Some(result) } +#[derive(Debug)] +pub enum Input { + File(PathBuf), + Text(String), +} + pub fn format_input( input: Input, config: &Config, out: Option<&mut T>, -) -> Result { - syntax::with_globals(|| format_input_inner(input, config, out)).map(|tup| tup.0) +) -> Result<(Summary, FormatReport), (ErrorKind, Summary)> { + if !config.version_meets_requirement() { + return Err((ErrorKind::VersionMismatch, Summary::default())); + } + + syntax::with_globals(|| format_input_inner(input, config, out)).map(|tup| (tup.0, tup.2)) } fn format_input_inner( @@ -950,61 +963,6 @@ fn get_modified_lines( Ok(ModifiedLines { chunks }) } -#[derive(Debug)] -pub enum Input { - File(PathBuf), - Text(String), -} - -pub fn format_and_emit_report(input: Input, config: &Config) -> Result { - if !config.version_meets_requirement() { - return Err(format_err!("Version mismatch")); - } - let out = &mut stdout(); - match syntax::with_globals(|| format_input_inner(input, config, Some(out))) { - Ok((summary, _, report)) => { - if report.has_warnings() { - match term::stderr() { - Some(ref t) - if use_colored_tty(config.color()) - && t.supports_color() - && t.supports_attr(term::Attr::Bold) => - { - match report.print_warnings_fancy(term::stderr().unwrap()) { - Ok(..) => (), - Err(..) => panic!("Unable to write to stderr: {}", report), - } - } - _ => eprintln!("{}", report), - } - } - - Ok(summary) - } - Err((msg, mut summary)) => { - eprintln!("Error writing files: {}", msg); - summary.add_operational_error(); - Ok(summary) - } - } -} - -pub fn emit_pre_matter(config: &Config) -> Result<(), ErrorKind> { - if config.emit_mode() == EmitMode::Checkstyle { - let mut out = &mut stdout(); - checkstyle::output_header(&mut out)?; - } - Ok(()) -} - -pub fn emit_post_matter(config: &Config) -> Result<(), ErrorKind> { - if config.emit_mode() == EmitMode::Checkstyle { - let mut out = &mut stdout(); - checkstyle::output_footer(&mut out)?; - } - Ok(()) -} - #[cfg(test)] mod unit_tests { use super::{format_code_block, format_snippet, Config}; diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index f2acc96a8de..33d7febbd64 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -13,7 +13,6 @@ use diff; use std::collections::VecDeque; use std::io; use std::io::Write; -use term; use utils::use_colored_tty; #[derive(Debug, PartialEq)] diff --git a/src/test/mod.rs b/src/test/mod.rs index c151fa3def7..d5c0533fde6 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -245,7 +245,7 @@ fn stdin_formatting_smoke_test() { let mut config = Config::default(); config.set().emit_mode(EmitMode::Stdout); let mut buf: Vec = vec![]; - let error_summary = format_input(input, &config, Some(&mut buf)).unwrap(); + let (error_summary, _) = format_input(input, &config, Some(&mut buf)).unwrap(); assert!(error_summary.has_no_errors()); //eprintln!("{:?}", ); assert_eq!(buf, "fn main() {}\n".as_bytes()); @@ -280,7 +280,7 @@ fn format_lines_errors_are_reported() { let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let mut config = Config::default(); config.set().error_on_line_overflow(true); - let error_summary = format_input::(input, &config, None).unwrap(); + let (error_summary, _) = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); } @@ -291,7 +291,7 @@ fn format_lines_errors_are_reported_with_tabs() { let mut config = Config::default(); config.set().error_on_line_overflow(true); config.set().hard_tabs(true); - let error_summary = format_input::(input, &config, None).unwrap(); + let (error_summary, _) = format_input::(input, &config, None).unwrap(); assert!(error_summary.has_formatting_errors()); } @@ -776,7 +776,7 @@ impl ConfigCodeBlock { config.set().emit_mode(EmitMode::Stdout); let mut buf: Vec = vec![]; - let error_summary = format_input(input, &config, Some(&mut buf)).unwrap(); + let (error_summary, _) = format_input(input, &config, Some(&mut buf)).unwrap(); !self.has_parsing_errors(error_summary) && !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) -- cgit 1.4.1-3-g733a5 From 6541be3c6f2a8f4f5f5ccd29a793f8ea700a5786 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 May 2018 15:32:27 +1200 Subject: Replace `use_colored_tty` with iatty crate --- Cargo.lock | 37 +++++++++++++++++++++++++++++++++++-- Cargo.toml | 7 +------ src/bin/main.rs | 6 +++--- src/config/options.rs | 12 ++++++++++++ src/lib.rs | 2 +- src/rustfmt_diff.rs | 3 +-- src/utils.rs | 27 --------------------------- 7 files changed, 53 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 123276b776e..47291420043 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -238,6 +238,17 @@ dependencies = [ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "isatty" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools" version = "0.7.8" @@ -251,6 +262,15 @@ name = "itoa" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "0.2.11" @@ -523,9 +543,9 @@ dependencies = [ "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "isatty 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-rustc_target 134.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -536,7 +556,6 @@ dependencies = [ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -722,6 +741,11 @@ name = "void" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.4" @@ -731,6 +755,11 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -780,8 +809,10 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum isatty 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a118a53ba42790ef25c82bb481ecf36e2da892646cccd361e69a6bb881e19398" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" @@ -839,7 +870,9 @@ dependencies = [ "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" diff --git a/Cargo.toml b/Cargo.toml index ec7550e8d9b..369b963a39c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ cargo-fmt = [] rustfmt-format-diff = [] [dependencies] +isatty = "0.1" itertools = "0.7" toml = "0.4" serde = "1.0" @@ -53,9 +54,3 @@ failure = "0.1.1" [dev-dependencies] assert_cli = "0.6" lazy_static = "1.0.0" - -[target.'cfg(unix)'.dependencies] -libc = "0.2.11" - -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3" } diff --git a/src/bin/main.rs b/src/bin/main.rs index 737eaa93670..fad9eeae6bb 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -28,8 +28,8 @@ use failure::err_msg; use getopts::{Matches, Options}; use rustfmt::{ - checkstyle_footer, checkstyle_header, format_input, load_config, use_colored_tty, CliOptions, - Color, Config, EmitMode, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, + checkstyle_footer, checkstyle_header, format_input, load_config, CliOptions, Color, Config, + EmitMode, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, }; fn main() { @@ -316,7 +316,7 @@ fn format_and_emit_report(input: Input, config: &Config) -> Result { diff --git a/src/config/options.rs b/src/config/options.rs index 9b4b57a7bfd..8d3b332e8e6 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -12,6 +12,8 @@ use config::config_type::ConfigType; use config::lists::*; use config::{Config, FileName}; +use isatty::stdout_isatty; + use std::collections::HashSet; use std::path::{Path, PathBuf}; @@ -191,6 +193,16 @@ configuration_option_enum! { Color: Auto, } +impl Color { + pub fn use_colored_tty(&self) -> bool { + match self { + Color::Always => true, + Color::Never => false, + Color::Auto => stdout_isatty(), + } + } +} + configuration_option_enum! { Verbosity: // Emit more. Verbose, diff --git a/src/lib.rs b/src/lib.rs index e84d2021f41..38b169c5170 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ extern crate derive_new; extern crate diff; extern crate failure; +extern crate isatty; extern crate itertools; #[cfg(test)] #[macro_use] @@ -61,7 +62,6 @@ pub use config::summary::Summary; pub use config::{ load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, Verbosity, }; -pub use utils::use_colored_tty; #[macro_use] mod utils; diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 33d7febbd64..de52b28c08b 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -13,7 +13,6 @@ use diff; use std::collections::VecDeque; use std::io; use std::io::Write; -use utils::use_colored_tty; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -53,7 +52,7 @@ impl OutputWriter { // for colorized output and the capabilities of the terminal. pub fn new(color: Color) -> Self { if let Some(t) = term::stdout() { - if use_colored_tty(color) && t.supports_color() { + if color.use_colored_tty() && t.supports_color() { return OutputWriter { terminal: Some(t) }; } } diff --git a/src/utils.rs b/src/utils.rs index 961989b3f5d..127a7ddb59e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,7 +18,6 @@ use syntax::ast::{ use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use syntax::ptr; -use config::Color; use rewrite::RewriteContext; use shape::Shape; @@ -376,32 +375,6 @@ pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { } } -// isatty shamelessly adapted from cargo. -#[cfg(unix)] -pub fn isatty() -> bool { - extern crate libc; - - unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } -} -#[cfg(windows)] -pub fn isatty() -> bool { - extern crate winapi; - - unsafe { - let handle = winapi::um::processenv::GetStdHandle(winapi::um::winbase::STD_OUTPUT_HANDLE); - let mut out = 0; - winapi::um::consoleapi::GetConsoleMode(handle, &mut out) != 0 - } -} - -pub fn use_colored_tty(color: Color) -> bool { - match color { - Color::Always => true, - Color::Never => false, - Color::Auto => isatty(), - } -} - pub fn starts_with_newline(s: &str) -> bool { s.starts_with('\n') || s.starts_with("\r\n") } -- cgit 1.4.1-3-g733a5 From 632fab4c954b2b5d213d972652f900c25ad918aa Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 21 May 2018 15:54:56 +1200 Subject: documentation --- src/checkstyle.rs | 8 ++++++++ src/config/file_lines.rs | 1 + src/config/mod.rs | 2 ++ src/config/options.rs | 9 ++++++++- src/config/summary.rs | 4 +++- src/lib.rs | 25 +++++++++++++++++++------ 6 files changed, 41 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 7e8f83eaad5..e252e71f829 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -13,6 +13,10 @@ use std::path::Path; use rustfmt_diff::{DiffLine, Mismatch}; +/// The checkstyle header - should be emitted before the output of Rustfmt. +/// +/// Note that emitting checkstyle output is not stable and may removed in a +/// future version of Rustfmt. pub fn header() -> String { let mut xml_heading = String::new(); xml_heading.push_str(""); @@ -21,6 +25,10 @@ pub fn header() -> String { xml_heading } +/// The checkstyle footer - should be emitted after the output of Rustfmt. +/// +/// Note that emitting checkstyle output is not stable and may removed in a +/// future version of Rustfmt. pub fn footer() -> String { "\n".to_owned() } diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 8fbd1e02ca0..ffe4b11486e 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -27,6 +27,7 @@ pub struct LineRange { pub hi: usize, } +/// Defines the name of an input - either a file or stdin. #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] pub enum FileName { Real(PathBuf), diff --git a/src/config/mod.rs b/src/config/mod.rs index 05531a7e2e7..992bd749b29 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -146,6 +146,8 @@ create_config! { make_backup: bool, false, false, "Backup changed files"; } +/// Load a config by checking the client-supplied options and if appropriate, the +/// file system (including searching the file system for overrides). pub fn load_config( file_path: Option<&Path>, options: Option, diff --git a/src/config/options.rs b/src/config/options.rs index 8d3b332e8e6..8f16e57d468 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -167,6 +167,8 @@ configuration_option_enum! { ReportTactic: Never, } +// What Rustfmt should emit. Mostly corresponds to the `--emit` command line +// option. configuration_option_enum! { EmitMode: // Emits to files. Files, @@ -180,10 +182,11 @@ configuration_option_enum! { EmitMode: ModifiedLines, // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. // This option is designed to be run in CI where a non-zero exit signifies non-standard code - // formatting. + // formatting. Used for `--check`. Diff, } +// Client-preference for coloured output. configuration_option_enum! { Color: // Always use color, whether it is a piped or terminal output Always, @@ -194,6 +197,7 @@ configuration_option_enum! { Color: } impl Color { + /// Whether we should use a coloured terminal. pub fn use_colored_tty(&self) -> bool { match self { Color::Always => true, @@ -203,6 +207,7 @@ impl Color { } } +// How chatty should Rustfmt be? configuration_option_enum! { Verbosity: // Emit more. Verbose, @@ -322,6 +327,8 @@ impl ::std::str::FromStr for IgnoreList { } } +/// Maps client-supplied options to Rustfmt's internals, mostly overriding +/// values in a config with values from the command line. pub trait CliOptions { fn apply_to(self, config: &mut Config); fn config_path(&self) -> Option<&Path>; diff --git a/src/config/summary.rs b/src/config/summary.rs index c7f8124c1c7..53d2c0a2f20 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -11,6 +11,7 @@ use std::default::Default; use std::time::{Duration, Instant}; +/// A summary of a Rustfmt run. #[derive(Debug, Default, Clone, Copy)] pub struct Summary { // Encountered e.g. an IO error. @@ -25,7 +26,7 @@ pub struct Summary { // Failed a check, such as the license check or other opt-in checking. has_check_errors: bool, - // Formatted code differs from existing code (--check only). + /// Formatted code differs from existing code (--check only). pub has_diff: bool, // Keeps track of time spent in parsing and formatting steps. @@ -106,6 +107,7 @@ impl Summary { || self.has_diff) } + /// Combine two summaries together. pub fn add(&mut self, other: Summary) { self.has_operational_errors |= other.has_operational_errors; self.has_formatting_errors |= other.has_formatting_errors; diff --git a/src/lib.rs b/src/lib.rs index 38b169c5170..8de2e3bcad3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,9 +102,11 @@ pub(crate) type FileMap = Vec; pub(crate) type FileRecord = (FileName, String); +/// The various errors that can occur during formatting. Note that not all of +/// these can currently be propagated to clients. #[derive(Fail, Debug)] pub enum ErrorKind { - // Line has exceeded character limit (found, maximum) + /// Line has exceeded character limit (found, maximum). #[fail( display = "line formatted, but exceeded maximum width \ (maximum: {} (see `max_width` option), found: {})", @@ -112,23 +114,26 @@ pub enum ErrorKind { _1 )] LineOverflow(usize, usize), - // Line ends in whitespace + /// Line ends in whitespace. #[fail(display = "left behind trailing whitespace")] TrailingWhitespace, - // TODO or FIXME item without an issue number + /// TODO or FIXME item without an issue number. #[fail(display = "found {}", _0)] BadIssue(Issue), - // License check has failed + /// License check has failed. #[fail(display = "license check failed")] LicenseCheck, - // Used deprecated skip attribute + /// Used deprecated skip attribute. #[fail(display = "`rustfmt_skip` is deprecated; use `rustfmt::skip`")] DeprecatedAttr, - // Used a rustfmt:: attribute other than skip + /// Used a rustfmt:: attribute other than skip. #[fail(display = "invalid attribute")] BadAttr, + /// An io error during reading or writing. #[fail(display = "io error: {}", _0)] IoError(io::Error), + /// The user mandated a version and the current version of Rustfmt does not + /// satisfy that requirement. #[fail(display = "Version mismatch")] VersionMismatch, } @@ -204,6 +209,9 @@ impl FormattingError { } } +/// Reports on any issues that occurred during a run of Rustfmt. +/// +/// Can be reported to the user via its `Display` implementation of `print_fancy`. #[derive(Clone)] pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. @@ -266,10 +274,13 @@ impl FormatReport { .sum() } + /// Whether any warnings or errors are present in the report. pub fn has_warnings(&self) -> bool { self.warning_count() > 0 } + /// Print the report to a terminal using colours and potentially other + /// fancy output. pub fn fancy_print( &self, mut t: Box>, @@ -758,6 +769,8 @@ pub enum Input { Text(String), } +/// The main entry point for Rustfmt. Formats the given input according to the +/// given config. `out` is only necessary if required by the configuration. pub fn format_input( input: Input, config: &Config, -- cgit 1.4.1-3-g733a5 From 150765d755fdfcab5d6f2949be7ad9df37e36e86 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Mon, 21 May 2018 12:18:06 +0800 Subject: format label break --- src/expr.rs | 7 ++++--- tests/source/label_break.rs | 16 ++++++++++++++++ tests/target/label_break.rs | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 tests/source/label_break.rs create mode 100644 tests/target/label_break.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8961cec4240..f1cfe8b4c4c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -118,8 +118,7 @@ pub fn format_expr( | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), - // FIXME(topecongiro): Handle label on a block (#2722). - ast::ExprKind::Block(ref block, _) => { + ast::ExprKind::Block(ref block, opt_label) => { match expr_type { ExprType::Statement => { if is_unsafe_block(block) { @@ -131,9 +130,11 @@ pub fn format_expr( rw } else { let prefix = block_prefix(context, block, shape)?; + let label_string = rewrite_label(opt_label); + rewrite_block_with_visitor( context, - &prefix, + &format!("{}{}", &prefix, &label_string), block, Some(&expr.attrs), shape, diff --git a/tests/source/label_break.rs b/tests/source/label_break.rs new file mode 100644 index 00000000000..d1e34bce4d4 --- /dev/null +++ b/tests/source/label_break.rs @@ -0,0 +1,16 @@ +// format with label break value. +fn main() { + +'empty_block: {} + +let result = 'block: { + if foo() { + // comment + break 'block 1; + } + if bar() { /* comment */ + break 'block 2; + } + 3 +}; +} \ No newline at end of file diff --git a/tests/target/label_break.rs b/tests/target/label_break.rs new file mode 100644 index 00000000000..2e05159de39 --- /dev/null +++ b/tests/target/label_break.rs @@ -0,0 +1,16 @@ +// format with label break value. +fn main() { + {} + + let result = { + if foo() { + // comment + break 'block 1; + } + if bar() { + /* comment */ + break 'block 2; + } + 3 + }; +} -- cgit 1.4.1-3-g733a5 From 64768cf93208cec8ad29768c36d9bd2ac4e772a1 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Mon, 21 May 2018 22:19:26 +0800 Subject: fix label prefix --- src/expr.rs | 17 +++++++++++------ tests/source/label_break.rs | 14 +++++++++++++- tests/target/label_break.rs | 14 +++++++++++++- 3 files changed, 37 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f1cfe8b4c4c..ea3ac5f58f2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -122,7 +122,7 @@ pub fn format_expr( match expr_type { ExprType::Statement => { if is_unsafe_block(block) { - rewrite_block(block, Some(&expr.attrs), context, shape) + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) } else if let rw @ Some(_) = rewrite_empty_block(context, block, Some(&expr.attrs), "", shape) { @@ -130,11 +130,10 @@ pub fn format_expr( rw } else { let prefix = block_prefix(context, block, shape)?; - let label_string = rewrite_label(opt_label); rewrite_block_with_visitor( context, - &format!("{}{}", &prefix, &label_string), + &prefix, block, Some(&expr.attrs), shape, @@ -142,7 +141,9 @@ pub fn format_expr( ) } } - ExprType::SubExpression => rewrite_block(block, Some(&expr.attrs), context, shape), + ExprType::SubExpression => { + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) + } } } ast::ExprKind::Match(ref cond, ref arms) => { @@ -328,6 +329,7 @@ pub fn format_expr( rewrite_block( block, Some(&expr.attrs), + None, context, Shape::legacy(budget, shape.indent) )? @@ -645,17 +647,20 @@ pub fn rewrite_block_with_visitor( impl Rewrite for ast::Block { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_block(self, None, context, shape) + rewrite_block(self, None, None, context, shape) } } fn rewrite_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, context: &RewriteContext, shape: Shape, ) -> Option { - let prefix = block_prefix(context, block, shape)?; + let unsafe_string = block_prefix(context, block, shape)?; + let label_string = rewrite_label(label); + let prefix = format!("{}{}", unsafe_string, label_string); // shape.width is used only for the single line case: either the empty block `{}`, // or an unsafe expression `unsafe { e }`. diff --git a/tests/source/label_break.rs b/tests/source/label_break.rs index d1e34bce4d4..2c79fd35e70 100644 --- a/tests/source/label_break.rs +++ b/tests/source/label_break.rs @@ -3,10 +3,22 @@ fn main() { 'empty_block: {} +'block: { + do_thing(); + if condition_not_met() { + break 'block; + } + do_next_thing(); + if condition_not_met() { + break 'block; + } + do_last_thing(); +} + let result = 'block: { if foo() { // comment - break 'block 1; + break 'block 1; } if bar() { /* comment */ break 'block 2; diff --git a/tests/target/label_break.rs b/tests/target/label_break.rs index 2e05159de39..afbd8e6fcdf 100644 --- a/tests/target/label_break.rs +++ b/tests/target/label_break.rs @@ -2,7 +2,19 @@ fn main() { {} - let result = { + { + do_thing(); + if condition_not_met() { + break 'block; + } + do_next_thing(); + if condition_not_met() { + break 'block; + } + do_last_thing(); + } + + let result = 'block: { if foo() { // comment break 'block 1; -- cgit 1.4.1-3-g733a5 From a6b32d944c71f33ac30f6532d4a1ab9304858e87 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 May 2018 06:04:14 +0900 Subject: Fix breaking changes from introducing AnonConst --- src/expr.rs | 7 ++++--- src/items.rs | 2 +- src/types.rs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ea3ac5f58f2..2f5e53ef062 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -228,7 +228,7 @@ pub fn format_expr( } ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair( &**expr, - &**repeats, + &*repeats.value, PairParts::new("[", "; ", "]"), context, shape, @@ -1469,8 +1469,9 @@ fn is_simple_expr(expr: &ast::Expr) -> bool { | ast::ExprKind::Field(ref expr, _) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) => is_simple_expr(expr), - ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => { - is_simple_expr(lhs) && is_simple_expr(rhs) + ast::ExprKind::Index(ref lhs, ref rhs) => is_simple_expr(lhs) && is_simple_expr(rhs), + ast::ExprKind::Repeat(ref lhs, ref rhs) => { + is_simple_expr(lhs) && is_simple_expr(&*rhs.value) } _ => false, } diff --git a/src/items.rs b/src/items.rs index 7da3f8c14d4..345d60e3517 100644 --- a/src/items.rs +++ b/src/items.rs @@ -572,7 +572,7 @@ impl<'a> FmtVisitor<'a> { ast::VariantData::Unit(..) => { if let Some(ref expr) = field.node.disr_expr { let lhs = format!("{} =", field.node.ident.name); - rewrite_assign_rhs(&context, lhs, &**expr, shape)? + rewrite_assign_rhs(&context, lhs, &*expr.value, shape)? } else { field.node.ident.name.to_string() } diff --git a/src/types.rs b/src/types.rs index 07b3986f70e..46d48e72763 100644 --- a/src/types.rs +++ b/src/types.rs @@ -656,7 +656,7 @@ impl Rewrite for ast::Ty { } ast::TyKind::Array(ref ty, ref repeats) => rewrite_pair( &**ty, - &**repeats, + &*repeats.value, PairParts::new("[", "; ", "]"), context, shape, -- cgit 1.4.1-3-g733a5 From fbcc886338e581d156c76249b14d01f0117499cc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 May 2018 07:22:42 +0900 Subject: Disallow combining a method call with prefix or suffix --- src/expr.rs | 12 ++++++++++++ src/overflow.rs | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index ea3ac5f58f2..ca2d78b03c4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2172,3 +2172,15 @@ impl ToExpr for ast::GenericParam { false } } + +pub fn is_method_call(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::MethodCall(..) => true, + ast::ExprKind::AddrOf(_, ref expr) + | ast::ExprKind::Box(ref expr) + | ast::ExprKind::Cast(ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Unary(_, ref expr) => is_method_call(expr), + _ => false, + } +} diff --git a/src/overflow.rs b/src/overflow.rs index d555086cda7..f2f05d835ff 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -18,7 +18,7 @@ use syntax::parse::token::DelimToken; use closures; use codemap::SpanUtils; -use expr::{is_every_expr_simple, is_nested_call, maybe_get_args_offset, ToExpr}; +use expr::{is_every_expr_simple, is_method_call, is_nested_call, maybe_get_args_offset, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; @@ -231,8 +231,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let placeholder = if overflow_last { let old_value = *self.context.force_one_line_chain.borrow(); if !combine_arg_with_callee { - if let Some(expr) = self.last_item().and_then(|item| item.to_expr()) { - if let ast::ExprKind::MethodCall(..) = expr.node { + if let Some(ref expr) = self.last_item().and_then(|item| item.to_expr()) { + if is_method_call(expr) { self.context.force_one_line_chain.replace(true); } } -- cgit 1.4.1-3-g733a5 From 8cb2b8e909455f74e1afa3417743d9d87bbb92ca Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 May 2018 07:22:59 +0900 Subject: Cargo fmt --- src/items.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7da3f8c14d4..1bcd8b3da78 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1380,9 +1380,9 @@ fn format_tuple_struct( // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); - result - .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) - .to_string(context.config)); + result.push_str( + &(offset.block_only() + (context.config.tab_spaces() - 1)).to_string(context.config), + ); } result.push_str(&where_clause_str); -- cgit 1.4.1-3-g733a5 From f1974e2209092ed69d99144ab14fae036c50c72d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 May 2018 23:29:28 +0900 Subject: Handle code block in doc comment without rust prefix --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 044a76e3599..255eb6df9cf 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -409,7 +409,7 @@ fn rewrite_comment_inner( continue; } else { - inside_code_block = line.starts_with("```rust"); + inside_code_block = line.starts_with("```"); if result == opener { let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; -- cgit 1.4.1-3-g733a5 From 5d067f16e096d306b1ebdbb9228425294c9e6718 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 May 2018 23:30:07 +0900 Subject: Format code block with sharp prefix by hiding lines with a leading `#` behind a custom comment. --- src/comment.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 255eb6df9cf..cbb1bd36f00 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -387,14 +387,18 @@ fn rewrite_comment_inner( if line.starts_with("```") { inside_code_block = false; result.push_str(&comment_line_separator); - let code_block = ::format_code_block(&code_block_buffer, config) - .unwrap_or_else(|| code_block_buffer.to_owned()); + let code_block = { + let mut config = config.clone(); + config.set().wrap_comments(false); + ::format_code_block(&code_block_buffer, &config) + .map_or_else(|| code_block_buffer.to_owned(), trim_custom_comment_prefix) + }; result.push_str(&join_code_block_with_comment_line_separator(&code_block)); code_block_buffer.clear(); result.push_str(&comment_line_separator); result.push_str(line); } else { - code_block_buffer.push_str(line); + code_block_buffer.push_str(&hide_sharp_behind_comment(line)); code_block_buffer.push('\n'); if is_last { @@ -491,6 +495,23 @@ fn rewrite_comment_inner( Some(result) } +const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; + +fn hide_sharp_behind_comment<'a>(s: &'a str) -> Cow<'a, str> { + if s.trim_left().starts_with('#') { + Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s)) + } else { + Cow::from(s) + } +} + +fn trim_custom_comment_prefix(s: String) -> String { + s.lines() + .map(|line| line.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX)) + .collect::>() + .join("\n") +} + /// Returns true if the given string MAY include URLs or alike. fn has_url(s: &str) -> bool { // This function may return false positive, but should get its job done in most cases. -- cgit 1.4.1-3-g733a5 From eedd275cd9e727073c5b5a4b1661a43701f2a179 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 24 May 2018 00:14:05 +0900 Subject: Do not call format_missing_inner in a common case We use `format_missing()` to extract a missing comment between a macro (or alike) and a trailing semicolon. This commit just tries to avoid calling `format_missing_inner` in the common case where there is no such comment. This is a hack, ideally we should fix a possible bug in `format_missing_inner` or refactor `visit_mac` and `rewrite_macro`, but this should suffice to fix the issue. --- src/missed_spans.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7adc53bde84..1797760d774 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -46,6 +46,13 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { + // HACK + let missing_snippet = self.snippet(mk_sp(self.last_pos, end)); + if missing_snippet.trim() == ";" { + self.push_str(";"); + self.last_pos = end; + return; + } self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) } -- cgit 1.4.1-3-g733a5 From a1d137116bc616f9bbf78aba3546da489091c9e6 Mon Sep 17 00:00:00 2001 From: Pazzaz Date: Thu, 24 May 2018 19:50:34 +0200 Subject: Avoid unnecessary comparisons with cur_end --- src/string.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 8a6b0e685c4..f683eab7dc7 100644 --- a/src/string.rs +++ b/src/string.rs @@ -105,12 +105,12 @@ pub fn rewrite_string<'a>( while !(punctuation.contains(graphemes[cur_end - 1]) || graphemes[cur_end - 1].trim().is_empty()) { - if cur_end >= graphemes.len() { + cur_end += 1; + if cur_end == graphemes.len() { let line = &graphemes[cur_start..].join(""); result.push_str(line); break 'outer; } - cur_end += 1; } break; } -- cgit 1.4.1-3-g733a5 From f711078126f95bd580c69c39af9fc16e3f83c859 Mon Sep 17 00:00:00 2001 From: Pazzaz Date: Thu, 24 May 2018 20:08:29 +0200 Subject: Seperate and optimize grapheme conditions --- src/string.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index f683eab7dc7..a5453c0a8ed 100644 --- a/src/string.rs +++ b/src/string.rs @@ -56,7 +56,6 @@ pub fn rewrite_string<'a>( let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); let shape = fmt.shape; let indent = shape.indent.to_string_with_newline(fmt.config); - let punctuation = ":,;."; // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; @@ -90,20 +89,20 @@ pub fn rewrite_string<'a>( } // Push cur_end left until we reach whitespace (or the line is too small). - while !graphemes[cur_end - 1].trim().is_empty() { + while !is_whitespace(graphemes[cur_end - 1]) { cur_end -= 1; if cur_end < cur_start + MIN_STRING { // We couldn't find whitespace before the string got too small. // So start again at the max length and look for punctuation. cur_end = cur_start + max_chars; - while !punctuation.contains(graphemes[cur_end - 1]) { + while !is_punctuation(graphemes[cur_end - 1]) { cur_end -= 1; // If we can't break at whitespace or punctuation, grow the string instead. if cur_end < cur_start + MIN_STRING { cur_end = cur_start + max_chars; - while !(punctuation.contains(graphemes[cur_end - 1]) - || graphemes[cur_end - 1].trim().is_empty()) + while !(is_punctuation(graphemes[cur_end - 1]) + || is_whitespace(graphemes[cur_end - 1])) { cur_end += 1; if cur_end == graphemes.len() { @@ -119,7 +118,7 @@ pub fn rewrite_string<'a>( } } // Make sure there is no whitespace to the right of the break. - while cur_end < stripped_str.len() && graphemes[cur_end].trim().is_empty() { + while cur_end < stripped_str.len() && is_whitespace(graphemes[cur_end]) { cur_end += 1; } @@ -148,6 +147,17 @@ pub fn rewrite_string<'a>( wrap_str(result, fmt.config.max_width(), fmt.shape) } +fn is_whitespace(grapheme: &str) -> bool { + grapheme.chars().all(|c| c.is_whitespace()) +} + +fn is_punctuation(grapheme: &str) -> bool { + match grapheme.as_bytes()[0] { + b':' | b',' | b';' | b'.' => true, + _ => false, + } +} + #[cfg(test)] mod test { use super::{rewrite_string, StringFormat}; -- cgit 1.4.1-3-g733a5 From 33a46581f79497da88aa31d48750f76bf7f7cf93 Mon Sep 17 00:00:00 2001 From: Tibo Date: Sun, 27 May 2018 03:15:26 +1000 Subject: Fix test failing on windows due to crlf --- src/config/file_lines.rs | 6 +++--- src/missed_spans.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index ffe4b11486e..d776dbb6a79 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -209,9 +209,9 @@ impl FileLines { self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) } - /// Returns true if any of the lines between `lo` and `hi` from `file_name` are in `self`. - pub(crate) fn intersects_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { - self.file_range_matches(file_name, |r| r.intersects(Range::new(lo, hi))) + /// Returns true if all the lines between `lo` and `hi` from `file_name` are in `self`. + pub(crate) fn contains_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { + self.file_range_matches(file_name, |r| r.contains(Range::new(lo, hi))) } } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7adc53bde84..6ff2efa487f 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -189,7 +189,7 @@ impl<'a> FmtVisitor<'a> { debug!("{:?}: {:?}", kind, subslice); let newline_count = count_newlines(subslice); - let within_file_lines_range = self.config.file_lines().intersects_range( + let within_file_lines_range = self.config.file_lines().contains_range( file_name, status.cur_line, status.cur_line + newline_count, -- cgit 1.4.1-3-g733a5 From 8fea1fcfe5acf235296b5e5c2f499205dccddaa6 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 28 May 2018 06:44:52 +0900 Subject: Add a comment to describe hack --- src/missed_spans.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 1797760d774..01c359299b2 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -46,7 +46,13 @@ impl<'a> FmtVisitor<'a> { // TODO these format_missing methods are ugly. Refactor and add unit tests // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { - // HACK + // HACK(topecongiro) + // We use `format_missing()` to extract a missing comment between a macro + // (or alike) and a trailing semicolon. Here we just try to avoid calling + // `format_missing_inner` in the common case where there is no such comment. + // This is a hack, ideally we should fix a possible bug in `format_missing_inner` + // or refactor `visit_mac` and `rewrite_macro`, but this should suffice to fix the + // issue (#2727). let missing_snippet = self.snippet(mk_sp(self.last_pos, end)); if missing_snippet.trim() == ";" { self.push_str(";"); -- cgit 1.4.1-3-g733a5 From 8674ab9a4299263c0980613283ae5efb0ffbc001 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 28 May 2018 11:15:15 +1200 Subject: FIXME for <- --- src/expr.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4a877ad2487..f23eb617e9d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -336,6 +336,8 @@ pub fn format_expr( )) } } + // FIXME(#2743) + ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), }; expr_rw -- cgit 1.4.1-3-g733a5 From d930617cbed8ee10b62cf4d89797c66396272b33 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 28 May 2018 11:30:58 +1200 Subject: Make Range public 0.8.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 0cc5ff3f78c..652b8538c2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -552,7 +552,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.8.0" +version = "0.8.1" dependencies = [ "assert_cli 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index bae27c87aa2..db7bd6cac73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.8.0" +version = "0.8.1" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index 992bd749b29..31da2820167 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; use std::{env, fs}; use config::config_type::ConfigType; -pub use config::file_lines::{FileLines, FileName}; +pub use config::file_lines::{FileLines, FileName, Range}; pub use config::lists::*; pub use config::options::*; -- cgit 1.4.1-3-g733a5 From 173ae0d7b92227c7fec4bce67c944dce953256dc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 28 May 2018 11:47:21 +1200 Subject: 0.8.2 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 652b8538c2a..e774929565f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -552,7 +552,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.8.1" +version = "0.8.2" dependencies = [ "assert_cli 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index db7bd6cac73..5987d960112 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.8.1" +version = "0.8.2" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/src/lib.rs b/src/lib.rs index 8de2e3bcad3..02307a8dc6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,7 @@ use visitor::{FmtVisitor, SnippetProvider}; pub use checkstyle::{footer as checkstyle_footer, header as checkstyle_header}; pub use config::summary::Summary; pub use config::{ - load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, Verbosity, + load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, Range, Verbosity, }; #[macro_use] -- cgit 1.4.1-3-g733a5 From 5473c3fd92ab7cde61d1421dc27fea7c66d7c1d3 Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Mon, 28 May 2018 23:41:08 +0100 Subject: Update rustc-ap-* -> 148 --- Cargo.lock | 68 ++++++++++++++++++++++++++++++------------------------------- Cargo.toml | 4 ++-- src/expr.rs | 2 -- 3 files changed, 36 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index e774929565f..cb49e283a66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -431,15 +431,15 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -448,7 +448,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -456,8 +456,8 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -465,56 +465,56 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "147.0.0" +version = "148.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-arena 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -566,8 +566,8 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -853,14 +853,14 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" -"checksum rustc-ap-arena 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1304956fbbdd070e4478672d040f0453374604a12a0938aaba4b38a2bd124667" -"checksum rustc-ap-rustc_cratesio_shim 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d1dcd0fafa3c7875b76e33feaf69b332870180475ba3eb8dd003bcc2a2dc069" -"checksum rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76c1a3fe4a0104b922ffc8080bd7c703dc20f2874b7c982638f6adb6c378b77a" -"checksum rustc-ap-rustc_errors 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2812e295d2930bf3b3c22dbe8ef0bb8ae98a497ae6ad379d0709434387a9004b" -"checksum rustc-ap-rustc_target 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bd371121f16da666f6d6d5e6ff57cd972cc8206cc80377ba411b99607d49cbd" -"checksum rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bde493c1c16d724e42536117c385b69f2eae9b2ec38bab841c45373bce4a9d8f" -"checksum rustc-ap-syntax 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402c1f402e6d47defcd884d3f715aaa8c6f2cbdd5f13cb06fea70486d512426b" -"checksum rustc-ap-syntax_pos 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb707a229093791dc3fc35aca61d9bf0e3708f23da4536683527857bc624b061" +"checksum rustc-ap-arena 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89c2a221b0cb3e2c2d5a2e859faae3a85aeb1fab95b4d3e45e4f0548ec49b7f0" +"checksum rustc-ap-rustc_cratesio_shim 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2cae068110cb4e680e090fc13125cb14c541926e292399b174a748948d00b792" +"checksum rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28de435ff768428adb0ca7fd7f59d2b5004938fa9d7e9141f3164a0a331d5a5c" +"checksum rustc-ap-rustc_errors 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4de5e8148449a9efc071163e90d8a69960f6bb972df080ac9da7f6b64158a355" +"checksum rustc-ap-rustc_target 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5bfe5b3c407ca2ab4506968f7eba87e7fa53489ab2b51face7bfedeb9832b56" +"checksum rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc6f7bb6ad4c1fc58d2ff1ac6143ac53326ee6aba2df5e2917122e8f98ab2c8" +"checksum rustc-ap-syntax 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef4cb1ce41bb681391fd23fc2428ce4b010cac36b3f995625223f30f3e672de" +"checksum rustc-ap-syntax_pos 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "084db1cd5eb33d47612728292a165efbff6086d5a8275e51558514d2cdedcc9e" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum rustc-hash 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06ddba37baa245040f932b15403071a46681d7e0e4158e230741943c4718b84" "checksum rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1aa5cd8c3a706edb19b6ec6aa7b056bdc635b6e99c5cf7014f9af9d92f15e99" diff --git a/Cargo.toml b/Cargo.toml index 5987d960112..22ef4f6f772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,8 +47,8 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-rustc_target = "147.0.0" -rustc-ap-syntax = "147.0.0" +rustc-ap-rustc_target = "148.0.0" +rustc-ap-syntax = "148.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/expr.rs b/src/expr.rs index f23eb617e9d..4a877ad2487 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -336,8 +336,6 @@ pub fn format_expr( )) } } - // FIXME(#2743) - ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), }; expr_rw -- cgit 1.4.1-3-g733a5 From cd925f01404454db06cb7aa89a5fa407f175f09f Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Tue, 29 May 2018 00:38:47 +0100 Subject: Add mercy for devs that run `cargo test` without building --- src/test/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index d5c0533fde6..3ac8caae291 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -900,6 +900,10 @@ fn rustfmt() -> PathBuf { me.pop(); // chop of the test name me.pop(); // chop off `deps` me.push("rustfmt"); + assert!( + me.is_file() || me.with_extension("exe").is_file(), + "no rustfmt bin, try running `cargo build` before testing" + ); return me; } -- cgit 1.4.1-3-g733a5 From f390626778c1bbb13911556d585850eb2fa67923 Mon Sep 17 00:00:00 2001 From: Alex Butler Date: Wed, 30 May 2018 00:22:49 +0100 Subject: Update rustc-ap-* -> 149 (#2748) --- Cargo.lock | 135 +++++++++++++++++++++++++++++++----------------------------- Cargo.toml | 4 +- src/expr.rs | 2 + 3 files changed, 73 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index cb49e283a66..e870a0e5267 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,8 +76,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -116,7 +116,7 @@ dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -269,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -354,7 +354,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -380,10 +380,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -431,15 +431,15 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -448,7 +448,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -456,65 +456,65 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "148.0.0" +version = "149.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-arena 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -526,8 +526,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-hash" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-rayon" @@ -544,7 +547,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -563,13 +566,13 @@ dependencies = [ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -592,7 +595,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -602,17 +605,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -622,7 +625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -657,11 +660,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -714,7 +717,7 @@ name = "thread_local" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -723,7 +726,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -831,7 +834,7 @@ dependencies = [ "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" @@ -843,40 +846,40 @@ dependencies = [ "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a45f2f0ae0b5757f6fe9e68745ba25f5246aea3598984ed81d013865873c1f84" +"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" -"checksum quote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e53eeda07ddbd8b057dde66d9beded11d0dfda13f0db0769e6b71d6bcf2074e" +"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "0a12d51a5b5fd700e6c757f15877685bfa04fd7eb60c108f01d045cafa0073c2" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" -"checksum rustc-ap-arena 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89c2a221b0cb3e2c2d5a2e859faae3a85aeb1fab95b4d3e45e4f0548ec49b7f0" -"checksum rustc-ap-rustc_cratesio_shim 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2cae068110cb4e680e090fc13125cb14c541926e292399b174a748948d00b792" -"checksum rustc-ap-rustc_data_structures 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28de435ff768428adb0ca7fd7f59d2b5004938fa9d7e9141f3164a0a331d5a5c" -"checksum rustc-ap-rustc_errors 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4de5e8148449a9efc071163e90d8a69960f6bb972df080ac9da7f6b64158a355" -"checksum rustc-ap-rustc_target 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5bfe5b3c407ca2ab4506968f7eba87e7fa53489ab2b51face7bfedeb9832b56" -"checksum rustc-ap-serialize 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc6f7bb6ad4c1fc58d2ff1ac6143ac53326ee6aba2df5e2917122e8f98ab2c8" -"checksum rustc-ap-syntax 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef4cb1ce41bb681391fd23fc2428ce4b010cac36b3f995625223f30f3e672de" -"checksum rustc-ap-syntax_pos 148.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "084db1cd5eb33d47612728292a165efbff6086d5a8275e51558514d2cdedcc9e" +"checksum rustc-ap-arena 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e794b25832224eea9252ebfa9f94ab7070d0a60c977793112c611501cb56b48d" +"checksum rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78241b2ecb82ebb9221b4b7d37c024ff1f2e43f1b099f38a997f030fc7894b0" +"checksum rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5529c3927f32b0b56d1f6449a34f2218dc2160c6a6dde0cf47954d83a9a45764" +"checksum rustc-ap-rustc_errors 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1fef44a7d63f5d204c981adb26a14e85fe7ee5962050a4f664df6f425f9b48" +"checksum rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3939a9f7bf063536dd646894ca43b1378ec6a56ac5b2698cc6ba0b42bfadbdc" +"checksum rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "692169d0bac8a4547f9778039460799e162664477a1eaec15d31507705f8c736" +"checksum rustc-ap-syntax 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22e93ee3817b007d56b5c5b151e6cd7c7063455a1facaf9e0ca01f9d9365b716" +"checksum rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe5d24a137d6e202cd6eb96cb74f8cb4a2b257c42b74dd624e136b4e19f0a47d" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" -"checksum rustc-hash 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06ddba37baa245040f932b15403071a46681d7e0e4158e230741943c4718b84" +"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1aa5cd8c3a706edb19b6ec6aa7b056bdc635b6e99c5cf7014f9af9d92f15e99" "checksum rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d69983f8613a9c3ba1a3bbf5e8bdf2fd5c42317b1d8dd8623ca8030173bf8a6b" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)" = "44d9552562673a8ea8757f5b77ccd794b54dd6841d2def71e9936f293ee81c72" -"checksum serde_derive 1.0.62 (registry+https://github.com/rust-lang/crates.io-index)" = "9503e0851dc4398d7f7ee1da227f9c9b9cf82718eb239ab10847b1de6e2a5777" +"checksum serde 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)" = "6f4a07014dd9a6845448a9e62f6f27595847f09828caabf1b1d50bb6755fa4d2" +"checksum serde_derive 1.0.63 (registry+https://github.com/rust-lang/crates.io-index)" = "d68003d21ef20c5c48354638c2e5c0d4ce4a056fdbf973839e0e86054eae7794" "checksum serde_json 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "ee382a792fabc5d720630aeafe1a4c69abe3d32aaaa5dbba6762fd8246d1bbe3" "checksum smallvec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03dab98ab5ded3a8b43b2c80751194608d0b2aa0f1d46cf95d1c35e192844aa7" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" -"checksum syn 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99d991a9e7c33123925e511baab68f7ec25c3795962fe326a2395e5a42a614f0" +"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" diff --git a/Cargo.toml b/Cargo.toml index 22ef4f6f772..37c697a9920 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,8 +47,8 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-rustc_target = "148.0.0" -rustc-ap-syntax = "148.0.0" +rustc-ap-rustc_target = "149.0.0" +rustc-ap-syntax = "149.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/expr.rs b/src/expr.rs index 4a877ad2487..f23eb617e9d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -336,6 +336,8 @@ pub fn format_expr( )) } } + // FIXME(#2743) + ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), }; expr_rw -- cgit 1.4.1-3-g733a5 From 966fe8d7052238f3c662a4f02d1cb7b96c644293 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 30 May 2018 08:17:50 +0900 Subject: Fix treating the delimiter right after repeat as repeat as well --- src/macros.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index c176b009f70..300f95c301d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -830,6 +830,7 @@ impl MacroArgParser { if self.is_meta_var { self.add_repeat(delimited_arg, delimited.delim, &mut iter, *sp)?; + self.is_meta_var = false; } else { self.add_delimited(delimited_arg, delimited.delim, *sp); } -- cgit 1.4.1-3-g733a5 From 2f658529463c631256397011bd53a373a96de790 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 30 May 2018 08:20:34 +0900 Subject: Do not insert spaces around braces with empty body or multiple lines --- src/macros.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 300f95c301d..ae95acaf301 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -493,11 +493,18 @@ fn delim_token_to_str( delim_token: &DelimToken, shape: Shape, use_multiple_lines: bool, + inner_is_empty: bool, ) -> (String, String) { let (lhs, rhs) = match *delim_token { DelimToken::Paren => ("(", ")"), DelimToken::Bracket => ("[", "]"), - DelimToken::Brace => ("{ ", " }"), + DelimToken::Brace => { + if inner_is_empty || use_multiple_lines { + ("{", "}") + } else { + ("{ ", " }") + } + } DelimToken::NoDelim => ("", ""), }; if use_multiple_lines { @@ -553,13 +560,13 @@ impl MacroArgKind { use_multiple_lines: bool, ) -> Option { let rewrite_delimited_inner = |delim_tok, args| -> Option<(String, String, String)> { - let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false); let inner = wrap_macro_args(context, args, shape)?; + let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false, inner.is_empty()); if lhs.len() + inner.len() + rhs.len() <= shape.width { return Some((lhs, inner, rhs)); } - let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true); + let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true, false); let nested_shape = shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config); -- cgit 1.4.1-3-g733a5 From 8536c288f206445395375cfd06932ef74cf9877d Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 31 May 2018 17:58:48 +0800 Subject: suppress and compress --- src/items.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 60673d4ebde..2aa53a1632b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -649,8 +649,14 @@ pub fn format_impl( } else { context.budget(last_line_width(&result)) }; - let option = WhereClauseOption::snuggled(&ref_and_type); - let where_clause_str = rewrite_where_clause( + + let mut option = WhereClauseOption::snuggled(&ref_and_type); + if items.is_empty() && generics.where_clause.predicates.len() == 1 { + option.compress_where(); + option.suppress_comma(); + } + + let mut where_clause_str = rewrite_where_clause( context, &generics.where_clause, context.config.brace_style(), @@ -1380,9 +1386,9 @@ fn format_tuple_struct( // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); - result.push_str( - &(offset.block_only() + (context.config.tab_spaces() - 1)).to_string(context.config), - ); + result + .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) + .to_string(context.config)); } result.push_str(&where_clause_str); @@ -2133,6 +2139,14 @@ impl WhereClauseOption { compress_where: false, } } + + pub fn suppress_comma(&mut self) { + self.suppress_comma = true + } + + pub fn compress_where(&mut self) { + self.compress_where = true + } } fn rewrite_args( -- cgit 1.4.1-3-g733a5 From 0468c134f4d1fd72452a55a8a09eeaf93b70e557 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 31 May 2018 18:33:45 +0800 Subject: snuggle where --- src/items.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2aa53a1632b..872d736f15f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -651,9 +651,15 @@ pub fn format_impl( }; let mut option = WhereClauseOption::snuggled(&ref_and_type); - if items.is_empty() && generics.where_clause.predicates.len() == 1 { - option.compress_where(); + let snippet = context.snippet(item.span); + let open_pos = snippet.find_uncommented("{")? + 1; + if !contains_comment(&snippet[open_pos..]) + && items.is_empty() + && generics.where_clause.predicates.len() == 1 + { option.suppress_comma(); + option.snuggle(); + option.compress_where(); } let mut where_clause_str = rewrite_where_clause( @@ -1386,9 +1392,9 @@ fn format_tuple_struct( // We need to put the where clause on a new line, but we didn't // know that earlier, so the where clause will not be indented properly. result.push('\n'); - result - .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1)) - .to_string(context.config)); + result.push_str( + &(offset.block_only() + (context.config.tab_spaces() - 1)).to_string(context.config), + ); } result.push_str(&where_clause_str); @@ -2147,6 +2153,10 @@ impl WhereClauseOption { pub fn compress_where(&mut self) { self.compress_where = true } + + pub fn snuggle(&mut self) { + self.snuggle = true + } } fn rewrite_args( -- cgit 1.4.1-3-g733a5 From 8874c95a00c5c16ac6dbdeb1b3539d3fb8a7e021 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Mon, 4 Jun 2018 19:10:09 +0800 Subject: recover suppressed comma --- src/items.rs | 5 +++++ tests/target/impl.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 872d736f15f..2e776087aee 100644 --- a/src/items.rs +++ b/src/items.rs @@ -696,6 +696,11 @@ pub fn format_impl( if is_impl_single_line(context, items, &result, &where_clause_str, item)? { result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { + // if the where_clause contains extra comments AND there is only one where clause predicate + // recover the suppressed comma in single line where_clause formatting + if generics.where_clause.predicates.len() == 1 { + result.push_str(","); + } result.push_str(&format!("{}{{{}}}", &sep, &sep)); } else { result.push_str(" {}"); diff --git a/tests/target/impl.rs b/tests/target/impl.rs index b5ab07d623e..5895c74bcc9 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -28,7 +28,7 @@ impl Foo for T where // comment2 // blah - T: Clone + T: Clone, { } -- cgit 1.4.1-3-g733a5 From faa41168a96c40e1e3c9134c2bf915e8cebf8833 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Tue, 5 Jun 2018 07:35:51 +0800 Subject: format exceeded comments --- src/items.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2e776087aee..81e86b72196 100644 --- a/src/items.rs +++ b/src/items.rs @@ -696,7 +696,8 @@ pub fn format_impl( if is_impl_single_line(context, items, &result, &where_clause_str, item)? { result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { - // if the where_clause contains extra comments AND there is only one where clause predicate + // if the where_clause contains extra comments AND + // there is only one where clause predicate // recover the suppressed comma in single line where_clause formatting if generics.where_clause.predicates.len() == 1 { result.push_str(","); -- cgit 1.4.1-3-g733a5 From b4987d848b72a1cd6b74ebda3699e6927fa49956 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Jun 2018 13:41:13 +0900 Subject: Allow using mixed layout with comments --- src/lists.rs | 16 +++++++++++----- src/overflow.rs | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 7d612913361..24779e1667e 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -228,6 +228,7 @@ where let mut item_max_width: Option = None; let sep_place = SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); + let mut prev_item_had_post_comment = false; let mut line_len = 0; let indent_str = &formatting.shape.indent.to_string(formatting.config); @@ -284,7 +285,9 @@ where let total_width = total_item_width(item) + item_sep_len; // 1 is space between separator and item. - if line_len > 0 && line_len + 1 + total_width > formatting.shape.width { + if (line_len > 0 && line_len + 1 + total_width > formatting.shape.width) + || prev_item_had_post_comment + { result.push('\n'); result.push_str(indent_str); line_len = 0; @@ -310,14 +313,15 @@ where // Pre-comments if let Some(ref comment) = item.pre_comment { // Block style in non-vertical mode. - let block_mode = tactic != DefinitiveListTactic::Vertical; + let block_mode = tactic == DefinitiveListTactic::Horizontal; // Width restriction is only relevant in vertical mode. let comment = rewrite_comment(comment, block_mode, formatting.shape, formatting.config)?; result.push_str(&comment); if !inner_item.is_empty() { - if tactic == DefinitiveListTactic::Vertical { + if tactic == DefinitiveListTactic::Vertical || tactic == DefinitiveListTactic::Mixed + { // We cannot keep pre-comments on the same line if the comment if normalized. let keep_comment = if formatting.config.normalize_comments() || item.pre_comment_style == ListItemCommentStyle::DifferentLine @@ -349,7 +353,7 @@ where result.push_str(inner_item); // Post-comments - if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() { + if tactic == DefinitiveListTactic::Horizontal && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); let formatted_comment = rewrite_comment( comment, @@ -366,7 +370,7 @@ where result.push_str(formatting.separator); } - if tactic == DefinitiveListTactic::Vertical && item.post_comment.is_some() { + if tactic != DefinitiveListTactic::Horizontal && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); let overhead = last_line_width(&result) + first_line_width(comment.trim()); @@ -446,6 +450,8 @@ where item_max_width = None; result.push('\n'); } + + prev_item_had_post_comment = item.post_comment.is_some(); } Some(result) diff --git a/src/overflow.rs b/src/overflow.rs index f2f05d835ff..62675b4002c 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -530,5 +530,5 @@ fn shape_from_indent_style( fn no_long_items(list: &[ListItem]) -> bool { list.iter() - .all(|item| !item.has_comment() && item.inner_as_ref().len() <= SHORT_ITEM_THRESHOLD) + .all(|item| item.inner_as_ref().len() <= SHORT_ITEM_THRESHOLD) } -- cgit 1.4.1-3-g733a5 From a70213b00991cb72db090418f650702c8e9681e4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Jun 2018 15:57:03 +0900 Subject: Trim custom comment prefixes from code block without closing backticks --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index cbb1bd36f00..4ca96f54c02 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -406,7 +406,7 @@ fn rewrite_comment_inner( // We will leave them untouched. result.push_str(&comment_line_separator); result.push_str(&join_code_block_with_comment_line_separator( - &code_block_buffer, + &trim_custom_comment_prefix(&code_block_buffer), )); } } -- cgit 1.4.1-3-g733a5 From 1b4778d0bcd6b7b7f7b44cbe25ca8ba95c4fabb0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Jun 2018 15:57:49 +0900 Subject: Handle code block with indented escapce character --- src/comment.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4ca96f54c02..0a729c53127 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -505,9 +505,16 @@ fn hide_sharp_behind_comment<'a>(s: &'a str) -> Cow<'a, str> { } } -fn trim_custom_comment_prefix(s: String) -> String { +fn trim_custom_comment_prefix(s: &str) -> String { s.lines() - .map(|line| line.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX)) + .map(|line| { + let left_trimmed = line.trim_left(); + if left_trimmed.starts_with(RUSTFMT_CUSTOM_COMMENT_PREFIX) { + left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX) + } else { + line + } + }) .collect::>() .join("\n") } -- cgit 1.4.1-3-g733a5 From 604764abe15c2742af85c1461e6f8055083e3c0b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Jun 2018 15:58:14 +0900 Subject: Trim custom comment prefix even when we failed to format code block --- src/comment.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0a729c53127..f684a6291ff 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -390,8 +390,10 @@ fn rewrite_comment_inner( let code_block = { let mut config = config.clone(); config.set().wrap_comments(false); - ::format_code_block(&code_block_buffer, &config) - .map_or_else(|| code_block_buffer.to_owned(), trim_custom_comment_prefix) + match ::format_code_block(&code_block_buffer, &config) { + Some(ref s) => trim_custom_comment_prefix(s), + None => trim_custom_comment_prefix(&code_block_buffer), + } }; result.push_str(&join_code_block_with_comment_line_separator(&code_block)); code_block_buffer.clear(); -- cgit 1.4.1-3-g733a5 From 56a3d039ce3276ddb9d275b54439be12723ea9a8 Mon Sep 17 00:00:00 2001 From: king6cong Date: Tue, 5 Jun 2018 15:34:53 +0800 Subject: update rustfmt flags that should work without targets --- src/cargo-fmt/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index c31caa1447d..fa735dc2b65 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -147,7 +147,11 @@ fn format_crate( strategy: &CargoFmtStrategy, ) -> Result { let rustfmt_args = get_fmt_args(); - let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") { + let targets = if rustfmt_args + .iter() + .any(|s| ["--print-config", "-h", "--help", "-V", "--verison"] + .contains(&s.as_str())) + { HashSet::new() } else { get_targets(strategy)? -- cgit 1.4.1-3-g733a5 From f545dfe95eca33dfc753bd9b57bd2753efddf3e8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 5 Jun 2018 20:58:02 +1200 Subject: Fix tests --- src/cargo-fmt/main.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index fa735dc2b65..3246908e20c 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -149,8 +149,7 @@ fn format_crate( let rustfmt_args = get_fmt_args(); let targets = if rustfmt_args .iter() - .any(|s| ["--print-config", "-h", "--help", "-V", "--verison"] - .contains(&s.as_str())) + .any(|s| ["--print-config", "-h", "--help", "-V", "--verison"].contains(&s.as_str())) { HashSet::new() } else { -- cgit 1.4.1-3-g733a5 From 42ab258757167abcc067433aa15945f5c51a1e8e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 5 Jun 2018 19:58:44 +0900 Subject: Put each nested import on its own line while putting non-nested imports on the same line as much as possible. --- src/config/lists.rs | 2 ++ src/imports.rs | 16 ++++++++++------ src/lists.rs | 6 +++++- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/config/lists.rs b/src/config/lists.rs index 04406e8d566..a9846a1cc74 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -19,6 +19,8 @@ pub enum DefinitiveListTactic { Vertical, Horizontal, Mixed, + /// Tactic for nested import. + NestedImport, /// Special case tactic for `format!()`, `write!()` style macros. SpecialMacro(usize), } diff --git a/src/imports.rs b/src/imports.rs index 4740921c525..a1cf6a83f07 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -706,12 +706,16 @@ fn rewrite_nested_use_tree( shape.width.saturating_sub(2) }; - let tactic = definitive_tactic( - &list_items, - context.config.imports_layout(), - Separator::Comma, - remaining_width, - ); + let tactic = if has_nested_list { + DefinitiveListTactic::NestedImport + } else { + definitive_tactic( + &list_items, + context.config.imports_layout(), + Separator::Comma, + remaining_width, + ) + }; let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; diff --git a/src/lists.rs b/src/lists.rs index 24779e1667e..6e867918864 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -229,6 +229,7 @@ where let sep_place = SeparatorPlace::from_tactic(formatting.separator_place, tactic, formatting.separator); let mut prev_item_had_post_comment = false; + let mut prev_item_is_nested_import = false; let mut line_len = 0; let indent_str = &formatting.shape.indent.to_string(formatting.config); @@ -281,12 +282,14 @@ where result.push('\n'); result.push_str(indent_str); } - DefinitiveListTactic::Mixed => { + DefinitiveListTactic::Mixed | DefinitiveListTactic::NestedImport => { let total_width = total_item_width(item) + item_sep_len; // 1 is space between separator and item. if (line_len > 0 && line_len + 1 + total_width > formatting.shape.width) || prev_item_had_post_comment + || (tactic == DefinitiveListTactic::NestedImport + && (prev_item_is_nested_import || (!first && inner_item.contains("::")))) { result.push('\n'); result.push_str(indent_str); @@ -452,6 +455,7 @@ where } prev_item_had_post_comment = item.post_comment.is_some(); + prev_item_is_nested_import = inner_item.contains("::"); } Some(result) -- cgit 1.4.1-3-g733a5 From 8d01496c9e40045e29f7685e6f2abd7a2ca1ff26 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Jun 2018 10:46:18 +0900 Subject: Remove unreachable lines --- src/items.rs | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 81e86b72196..cc5825048e4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -709,11 +709,6 @@ pub fn format_impl( return Some(result); } - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') { - let width = offset.block_indent + context.config.tab_spaces() - 1; - let where_indent = Indent::new(0, width); - result.push_str(&where_indent.to_string_with_newline(context.config)); - } result.push_str(&where_clause_str); let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n'); -- cgit 1.4.1-3-g733a5 From 2e4376d29c61cb6c470ec836cb341d060aae6074 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Jun 2018 10:46:49 +0900 Subject: Do not put where clause on a single with multi-lined type --- src/items.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cc5825048e4..321a74df7cc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -656,6 +656,7 @@ pub fn format_impl( if !contains_comment(&snippet[open_pos..]) && items.is_empty() && generics.where_clause.predicates.len() == 1 + && !result.contains('\n') { option.suppress_comma(); option.snuggle(); -- cgit 1.4.1-3-g733a5 From d51b99f5d7129767bdc6bbbba78b155df83eb3cd Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Jun 2018 10:54:40 +0900 Subject: Put the where clause next to the closing bracket only when it is not indented --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 321a74df7cc..a45d41842de 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2143,7 +2143,7 @@ impl WhereClauseOption { pub fn snuggled(current: &str) -> WhereClauseOption { WhereClauseOption { suppress_comma: false, - snuggle: trimmed_last_line_width(current) == 1, + snuggle: last_line_width(current) == 1, compress_where: false, } } -- cgit 1.4.1-3-g733a5 From a4db62368bb3c1049981e5565bc6e7ba75910248 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Jun 2018 10:55:25 +0900 Subject: Respect empty_item_single_line config option when formatting empty impls --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a45d41842de..38311abcba0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -750,7 +750,7 @@ pub fn format_impl( result.push_str(&outer_indent_str); } - if result.ends_with('{') { + if result.ends_with('{') && !context.config.empty_item_single_line() { result.push_str(&sep); } result.push('}'); -- cgit 1.4.1-3-g733a5 From c791a54ff4ac27d8d2126a36993756f0a78ef43c Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 7 Jun 2018 11:15:59 +0800 Subject: repair break_label format --- src/closures.rs | 2 +- src/expr.rs | 44 ++++++++++++++++++++++++++++---------------- tests/target/label_break.rs | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index dc811ea95ad..3d0a52de0dc 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -140,7 +140,7 @@ fn rewrite_closure_with_block( span: body.span, recovered: false, }; - let block = ::expr::rewrite_block_with_visitor(context, "", &block, None, shape, false)?; + let block = ::expr::rewrite_block_with_visitor(context, "", &block, None, None, shape, false)?; Some(format!("{} {}", prefix, block)) } diff --git a/src/expr.rs b/src/expr.rs index f23eb617e9d..112383e7e4c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -124,7 +124,7 @@ pub fn format_expr( if is_unsafe_block(block) { rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) } else if let rw @ Some(_) = - rewrite_empty_block(context, block, Some(&expr.attrs), "", shape) + rewrite_empty_block(context, block, Some(&expr.attrs), opt_label, "", shape) { // Rewrite block without trying to put it in a single line. rw @@ -136,6 +136,7 @@ pub fn format_expr( &prefix, block, Some(&expr.attrs), + opt_label, shape, true, ) @@ -316,9 +317,14 @@ pub fn format_expr( // satisfy our width restrictions. ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::Catch(ref block) => { - if let rw @ Some(_) = - rewrite_single_line_block(context, "do catch ", block, Some(&expr.attrs), shape) - { + if let rw @ Some(_) = rewrite_single_line_block( + context, + "do catch ", + block, + Some(&expr.attrs), + None, + shape, + ) { rw } else { // 9 = `do catch ` @@ -543,16 +549,18 @@ fn rewrite_empty_block( context: &RewriteContext, block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, prefix: &str, shape: Shape, ) -> Option { + let label_str = rewrite_label(label); if attrs.map_or(false, |a| !inner_attributes(a).is_empty()) { return None; } if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 { - return Some(format!("{}{{}}", prefix)); + return Some(format!("{}{}{{}}", prefix, label_str)); } // If a block contains only a single-line comment, then leave it on one line. @@ -565,7 +573,7 @@ fn rewrite_empty_block( && !comment_str.starts_with("//") && comment_str.len() + 4 <= shape.width { - return Some(format!("{}{{ {} }}", prefix, comment_str)); + return Some(format!("{}{}{{ {} }}", prefix, label_str, comment_str)); } } @@ -605,12 +613,14 @@ fn rewrite_single_line_block( prefix: &str, block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, shape: Shape, ) -> Option { if is_simple_block(block, attrs, context.codemap) { let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; - let result = format!("{}{{ {} }}", prefix, expr_str); + let label_str = rewrite_label(label); + let result = format!("{}{}{{ {} }}", prefix, label_str, expr_str); if result.len() <= shape.width && !result.contains('\n') { return Some(result); } @@ -623,10 +633,11 @@ pub fn rewrite_block_with_visitor( prefix: &str, block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, shape: Shape, has_braces: bool, ) -> Option { - if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, prefix, shape) { + if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, label, prefix, shape) { return rw; } @@ -643,8 +654,9 @@ pub fn rewrite_block_with_visitor( } let inner_attrs = attrs.map(inner_attributes); + let label_str = rewrite_label(label); visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); - Some(format!("{}{}", prefix, visitor.buffer)) + Some(format!("{}{}{}", prefix, label_str, visitor.buffer)) } impl Rewrite for ast::Block { @@ -660,20 +672,20 @@ fn rewrite_block( context: &RewriteContext, shape: Shape, ) -> Option { - let unsafe_string = block_prefix(context, block, shape)?; - let label_string = rewrite_label(label); - let prefix = format!("{}{}", unsafe_string, label_string); + let prefix = block_prefix(context, block, shape)?; // shape.width is used only for the single line case: either the empty block `{}`, // or an unsafe expression `unsafe { e }`. - if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, &prefix, shape) { + if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, label, &prefix, shape) { return rw; } - let result = rewrite_block_with_visitor(context, &prefix, block, attrs, shape, true); + let result = rewrite_block_with_visitor(context, &prefix, block, attrs, label, shape, true); if let Some(ref result_str) = result { if result_str.lines().count() <= 3 { - if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, block, attrs, shape) { + if let rw @ Some(_) = + rewrite_single_line_block(context, &prefix, block, attrs, label, shape) + { return rw; } } @@ -1125,7 +1137,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let block_str = { let old_val = context.is_if_else_block.replace(self.else_block.is_some()); let result = - rewrite_block_with_visitor(context, "", self.block, None, block_shape, true); + rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true); context.is_if_else_block.replace(old_val); result? }; diff --git a/tests/target/label_break.rs b/tests/target/label_break.rs index a288b3624ad..728d78137c9 100644 --- a/tests/target/label_break.rs +++ b/tests/target/label_break.rs @@ -1,6 +1,6 @@ // format with label break value. fn main() { - 'emty_block: {} + 'empty_block: {} 'block: { do_thing(); -- cgit 1.4.1-3-g733a5 From 94e68b1eb6c0407f46e6ebffda6cd908b5fa47f5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Jun 2018 12:32:10 +0900 Subject: Set the flag in RewriteContext when rewriting macro call failed --- src/macros.rs | 17 +++++++++++++---- src/rewrite.rs | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index ae95acaf301..674a652322d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -129,6 +129,12 @@ fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> Stri } } +// Use this on failing to format the macro call. +fn return_original_snippet_with_failure_marked(context: &RewriteContext, span: Span) -> Option { + context.macro_rewrite_failure.replace(true); + Some(context.snippet(span).to_owned()) +} + pub fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, @@ -138,6 +144,9 @@ pub fn rewrite_macro( ) -> Option { context.inside_macro.replace(true); let result = rewrite_macro_inner(mac, extra_ident, context, shape, position); + if result.is_none() { + context.macro_rewrite_failure.replace(true); + } context.inside_macro.replace(false); result } @@ -196,7 +205,7 @@ pub fn rewrite_macro_inner( loop { match parse_macro_arg(&mut parser) { Some(arg) => arg_vec.push(arg), - None => return Some(context.snippet(mac.span).to_owned()), + None => return return_original_snippet_with_failure_marked(context, mac.span), } match parser.token { @@ -216,13 +225,13 @@ pub fn rewrite_macro_inner( break; } } - None => return Some(context.snippet(mac.span).to_owned()), + None => return return_original_snippet_with_failure_marked(context, mac.span), } } } - return Some(context.snippet(mac.span).to_owned()); + return return_original_snippet_with_failure_marked(context, mac.span); } - _ => return Some(context.snippet(mac.span).to_owned()), + _ => return return_original_snippet_with_failure_marked(context, mac.span), } parser.bump(); diff --git a/src/rewrite.rs b/src/rewrite.rs index 00c03a3c879..90b613df6c4 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -39,6 +39,8 @@ pub struct RewriteContext<'a> { // When rewriting chain, veto going multi line except the last element pub force_one_line_chain: RefCell, pub snippet_provider: &'a SnippetProvider<'a>, + // Used for `format_snippet` + pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, } -- cgit 1.4.1-3-g733a5 From d1477ca1de6ff7b0d5ad0fe190ed9ae7fe65f1f5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Jun 2018 12:32:58 +0900 Subject: Add a field in Summary for notiyfing about formatting failure of macro --- src/config/summary.rs | 11 +++++++++++ src/lib.rs | 13 ++++++++++--- src/visitor.rs | 19 ++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/summary.rs b/src/config/summary.rs index 53d2c0a2f20..1ef6d18a540 100644 --- a/src/config/summary.rs +++ b/src/config/summary.rs @@ -23,6 +23,9 @@ pub struct Summary { // Code is valid, but it is impossible to format it properly. has_formatting_errors: bool, + // Code contains macro call that was unable to format. + pub(crate) has_macro_format_failure: bool, + // Failed a check, such as the license check or other opt-in checking. has_check_errors: bool, @@ -80,6 +83,10 @@ impl Summary { self.has_check_errors } + pub(crate) fn has_macro_formatting_failure(&self) -> bool { + self.has_macro_format_failure + } + pub fn add_operational_error(&mut self) { self.has_operational_errors = true; } @@ -100,6 +107,10 @@ impl Summary { self.has_diff = true; } + pub(crate) fn add_macro_foramt_failure(&mut self) { + self.has_macro_format_failure = true; + } + pub fn has_no_errors(&self) -> bool { !(self.has_operational_errors || self.has_parsing_errors diff --git a/src/lib.rs b/src/lib.rs index 02307a8dc6d..a8f09e4843d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -422,13 +422,14 @@ fn format_ast( config: &Config, report: FormatReport, mut after_file: F, -) -> Result<(FileMap, bool), io::Error> +) -> Result<(FileMap, bool, bool), io::Error> where F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result, { let mut result = FileMap::new(); // diff mode: check if any files are differing let mut has_diff = false; + let mut has_macro_rewrite_failure = false; let skip_children = config.skip_children(); for (path, module) in modules::list_files(krate, parse_session.codemap())? { @@ -472,10 +473,12 @@ where } }; + has_macro_rewrite_failure |= visitor.macro_rewrite_failure; + result.push((path.clone(), visitor.buffer)); } - Ok((result, has_diff)) + Ok((result, has_diff, has_macro_rewrite_failure)) } /// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. @@ -902,7 +905,7 @@ fn format_input_inner( } match format_result { - Ok((file_map, has_diff)) => { + Ok((file_map, has_diff, has_macro_rewrite_failure)) => { if report.has_warnings() { summary.add_formatting_error(); } @@ -911,6 +914,10 @@ fn format_input_inner( summary.add_diff(); } + if has_macro_rewrite_failure { + summary.add_macro_foramt_failure(); + } + Ok((summary, file_map, report)) } Err(e) => Err((From::from(e), summary)), diff --git a/src/visitor.rs b/src/visitor.rs index 4a0ce4399a4..830f3079aa8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -70,6 +70,7 @@ pub struct FmtVisitor<'a> { pub snippet_provider: &'a SnippetProvider<'a>, pub line_number: usize, pub skipped_range: Vec<(usize, usize)>, + pub macro_rewrite_failure: bool, pub(crate) report: FormatReport, } @@ -519,7 +520,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // 1 = ; let shape = self.shape().sub_width(1).unwrap(); - let rewrite = rewrite_macro(mac, ident, &self.get_context(), shape, pos); + let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); self.push_rewrite(mac.span, rewrite); } @@ -578,6 +579,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider, line_number: 0, skipped_range: vec![], + macro_rewrite_failure: false, report, } } @@ -736,6 +738,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } + pub fn with_context(&mut self, f: F) -> Option + where + F: Fn(&RewriteContext) -> Option, + { + let mut result; + let macro_rewrite_failure = { + let context = self.get_context(); + result = f(&context); + unsafe { *context.macro_rewrite_failure.as_ptr() } + }; + self.macro_rewrite_failure |= macro_rewrite_failure; + result + } + pub fn get_context(&self) -> RewriteContext { RewriteContext { parse_session: self.parse_session, @@ -746,6 +762,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { is_if_else_block: RefCell::new(false), force_one_line_chain: RefCell::new(false), snippet_provider: self.snippet_provider, + macro_rewrite_failure: RefCell::new(false), report: self.report.clone(), } } -- cgit 1.4.1-3-g733a5 From c95fa8cbe22d782cd7bc007dfe06aba9ceddff78 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Jun 2018 12:33:33 +0900 Subject: Return None when the formatting of macro failed in format_snippet --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index a8f09e4843d..8d4cbb51b5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -689,6 +689,7 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { config.set().hide_parse_errors(true); match format_input(input, &config, Some(&mut out)) { // `format_input()` returns an empty string on parsing error. + Ok((summary, _)) if summary.has_macro_formatting_failure() => None, Ok(..) if out.is_empty() && !snippet.is_empty() => None, Ok(..) => String::from_utf8(out).ok(), Err(..) => None, -- cgit 1.4.1-3-g733a5 From 19054347cad5b0edc006957efd92188671eb0735 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 7 Jun 2018 15:20:01 +0900 Subject: Fix test failures --- src/macros.rs | 11 +++++++++-- src/visitor.rs | 2 +- tests/target/issue-2523.rs | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 674a652322d..9053aaebd90 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -130,7 +130,10 @@ fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> Stri } // Use this on failing to format the macro call. -fn return_original_snippet_with_failure_marked(context: &RewriteContext, span: Span) -> Option { +fn return_original_snippet_with_failure_marked( + context: &RewriteContext, + span: Span, +) -> Option { context.macro_rewrite_failure.replace(true); Some(context.snippet(span).to_owned()) } @@ -225,7 +228,11 @@ pub fn rewrite_macro_inner( break; } } - None => return return_original_snippet_with_failure_marked(context, mac.span), + None => { + return return_original_snippet_with_failure_marked( + context, mac.span, + ) + } } } } diff --git a/src/visitor.rs b/src/visitor.rs index 830f3079aa8..7d676770421 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -742,7 +742,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { where F: Fn(&RewriteContext) -> Option, { - let mut result; + let result; let macro_rewrite_failure = { let context = self.get_context(); result = f(&context); diff --git a/tests/target/issue-2523.rs b/tests/target/issue-2523.rs index 6805f7ec2ca..d908831c21c 100644 --- a/tests/target/issue-2523.rs +++ b/tests/target/issue-2523.rs @@ -2,7 +2,7 @@ // Do not unindent macro calls in comment with unformattable syntax. //! ```rust -//! let x = 3; +//! let x = 3 ; //! some_macro!(pub fn fn foo() ( //! println!("Don't unindent me!"); //! )); -- cgit 1.4.1-3-g733a5 From 8c32a9d909ee7a517b9fb24b85f871a43eb5cbba Mon Sep 17 00:00:00 2001 From: Tibo Delor Date: Sun, 10 Jun 2018 00:25:06 +1000 Subject: Parse Error return an Error instead of a successful empty response --- src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 8d4cbb51b5a..40ecd71fdf3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,6 +132,9 @@ pub enum ErrorKind { /// An io error during reading or writing. #[fail(display = "io error: {}", _0)] IoError(io::Error), + /// Parse error occured when parsing the Input. + #[fail(display = "parse error")] + ParseError, /// The user mandated a version and the current version of Rustfmt does not /// satisfy that requirement. #[fail(display = "Version mismatch")] @@ -172,9 +175,10 @@ impl FormattingError { } fn msg_prefix(&self) -> &str { match self.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace | ErrorKind::IoError(_) => { - "internal error:" - } + ErrorKind::LineOverflow(..) + | ErrorKind::TrailingWhitespace + | ErrorKind::IoError(_) + | ErrorKind::ParseError => "internal error:", ErrorKind::LicenseCheck | ErrorKind::BadAttr | ErrorKind::VersionMismatch => "error:", ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", } @@ -844,7 +848,7 @@ fn format_input_inner( ParseError::Recovered => {} } summary.add_parsing_error(); - return Ok((summary, FileMap::new(), FormatReport::new())); + return Err((ErrorKind::ParseError, summary)); } }; -- cgit 1.4.1-3-g733a5 From 6b00b8b302ba2e0a0946739ebe279d17f43f589b Mon Sep 17 00:00:00 2001 From: Tibo Delor Date: Sun, 10 Jun 2018 00:25:47 +1000 Subject: Move newline logic inside the formatting process. Why?: - Conceptually it sounds right - Absolutely all write modes where doing it anyway - It was done several times in some in case - It greatly simplify the code --- src/filemap.rs | 137 +++++++++++++++----------------------------------------- src/lib.rs | 32 ++++++++++++- src/test/mod.rs | 12 ++--- 3 files changed, 70 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 96d9abc2a35..507e85f2086 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -10,13 +10,12 @@ // TODO: add tests -use std::fs::{self, File}; -use std::io::{self, BufWriter, Read, Write}; -use std::path::Path; +use std::fs; +use std::io::{self, Write}; use checkstyle::output_checkstyle_file; -use config::{Config, EmitMode, FileName, NewlineStyle, Verbosity}; -use rustfmt_diff::{make_diff, output_modified, print_diff, Mismatch}; +use config::{Config, EmitMode, FileName, Verbosity}; +use rustfmt_diff::{make_diff, output_modified, print_diff}; #[cfg(test)] use FileRecord; @@ -48,42 +47,8 @@ where Ok(()) } -// Prints all newlines either as `\n` or as `\r\n`. -pub fn write_system_newlines(writer: T, text: &str, config: &Config) -> Result<(), io::Error> -where - T: Write, -{ - // Buffer output, since we're writing a since char at a time. - let mut writer = BufWriter::new(writer); - - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; - - match style { - NewlineStyle::Unix => write!(writer, "{}", text), - NewlineStyle::Windows => { - for c in text.chars() { - match c { - '\n' => write!(writer, "\r\n")?, - '\r' => continue, - c => write!(writer, "{}", c)?, - } - } - Ok(()) - } - NewlineStyle::Native => unreachable!(), - } -} - pub fn write_file( - text: &str, + formatted_text: &str, filename: &FileName, out: &mut T, config: &Config, @@ -91,29 +56,6 @@ pub fn write_file( where T: Write, { - fn source_and_formatted_text( - text: &str, - filename: &Path, - config: &Config, - ) -> Result<(String, String), io::Error> { - let mut f = File::open(filename)?; - let mut ori_text = String::new(); - f.read_to_string(&mut ori_text)?; - let mut v = Vec::new(); - write_system_newlines(&mut v, text, config)?; - let fmt_text = String::from_utf8(v).unwrap(); - Ok((ori_text, fmt_text)) - } - - fn create_diff( - filename: &Path, - text: &str, - config: &Config, - ) -> Result, io::Error> { - let (ori, fmt) = source_and_formatted_text(text, filename, config)?; - Ok(make_diff(&ori, &fmt, 3)) - } - let filename_to_path = || match *filename { FileName::Real(ref path) => path, _ => panic!("cannot format `{}` and emit to files", filename), @@ -122,65 +64,58 @@ where match config.emit_mode() { EmitMode::Files if config.make_backup() => { let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - if fmt != ori { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.with_extension("tmp"); - let bk_name = filename.with_extension("bk"); - { - // Write text to temp file - let tmp_file = File::create(&tmp_name)?; - write_system_newlines(tmp_file, text, config)?; - } - - fs::rename(filename, bk_name)?; - fs::rename(tmp_name, filename)?; - } + let ori = fs::read_to_string(filename)?; + if ori != formatted_text { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.with_extension("tmp"); + let bk_name = filename.with_extension("bk"); + + fs::write(&tmp_name, formatted_text)?; + fs::rename(filename, bk_name)?; + fs::rename(tmp_name, filename)?; } } EmitMode::Files => { // Write text directly over original file if there is a diff. let filename = filename_to_path(); - let (source, formatted) = source_and_formatted_text(text, filename, config)?; - if source != formatted { - let file = File::create(filename)?; - write_system_newlines(file, text, config)?; + let ori = fs::read_to_string(filename)?; + if ori != formatted_text { + fs::write(filename, formatted_text)?; } } EmitMode::Stdout | EmitMode::Coverage => { if config.verbose() != Verbosity::Quiet { println!("{}:\n", filename); } - write_system_newlines(out, text, config)?; + write!(out, "{}", formatted_text)?; } EmitMode::ModifiedLines => { let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - let mismatch = make_diff(&ori, &fmt, 0); - let has_diff = !mismatch.is_empty(); - output_modified(out, mismatch); - return Ok(has_diff); - } + let ori = fs::read_to_string(filename)?; + let mismatch = make_diff(&ori, formatted_text, 0); + let has_diff = !mismatch.is_empty(); + output_modified(out, mismatch); + return Ok(has_diff); } EmitMode::Checkstyle => { let filename = filename_to_path(); - let diff = create_diff(filename, text, config)?; + let ori = fs::read_to_string(filename)?; + let diff = make_diff(&ori, formatted_text, 3); output_checkstyle_file(out, filename, diff)?; } EmitMode::Diff => { let filename = filename_to_path(); - if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) { - let mismatch = make_diff(&ori, &fmt, 3); - let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config, - ); - return Ok(has_diff); - } + let ori = fs::read_to_string(filename)?; + let mismatch = make_diff(&ori, formatted_text, 3); + let has_diff = !mismatch.is_empty(); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), + config, + ); + return Ok(has_diff); } } diff --git a/src/lib.rs b/src/lib.rs index 40ecd71fdf3..0ea3c604770 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,7 +60,8 @@ use visitor::{FmtVisitor, SnippetProvider}; pub use checkstyle::{footer as checkstyle_footer, header as checkstyle_header}; pub use config::summary::Summary; pub use config::{ - load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, Range, Verbosity, + load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, NewlineStyle, Range, + Verbosity, }; #[macro_use] @@ -877,6 +878,7 @@ fn format_input_inner( filemap::append_newline(file); format_lines(file, file_name, skipped_range, config, report); + replace_with_system_newlines(file, config); if let Some(ref mut out) = out { return filemap::write_file(file, file_name, out, config); @@ -929,6 +931,34 @@ fn format_input_inner( } } +pub fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { + let style = if config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + config.newline_style() + }; + + match style { + NewlineStyle::Unix => return, + NewlineStyle::Windows => { + let mut transformed = String::with_capacity(text.capacity()); + for c in text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } + } + *text = transformed; + } + NewlineStyle::Native => unreachable!(), + } +} + /// A single span of changed lines, with 0 or more removed lines /// and a vector of 0 or more inserted lines. #[derive(Debug, PartialEq, Eq)] diff --git a/src/test/mod.rs b/src/test/mod.rs index 3ac8caae291..fdbe1e6856e 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -22,7 +22,6 @@ use std::str::Chars; use config::summary::Summary; use config::{Color, Config, ReportTactic}; -use filemap::write_system_newlines; use rustfmt_diff::*; use *; @@ -401,14 +400,9 @@ fn idempotent_check( } let mut write_result = HashMap::new(); - for &(ref filename, ref text) in &file_map { - let mut v = Vec::new(); - // Won't panic, as we're not doing any IO. - write_system_newlines(&mut v, text, &config).unwrap(); - // Won't panic, we are writing correct utf8. - let one_result = String::from_utf8(v).unwrap(); - if let FileName::Real(ref filename) = *filename { - write_result.insert(filename.to_owned(), one_result); + for (filename, text) in file_map { + if let FileName::Real(ref filename) = filename { + write_result.insert(filename.to_owned(), text); } } -- cgit 1.4.1-3-g733a5 From 42efae59449b4dda7b310ea70e15d57d65550217 Mon Sep 17 00:00:00 2001 From: Tibo Delor Date: Sun, 10 Jun 2018 14:07:33 +1000 Subject: Clean Up code where last whitspace tracking isn't used --- src/lib.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 8d4cbb51b5a..35448a087a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -517,7 +517,7 @@ fn format_lines( report: &FormatReport, ) { let mut trims = vec![]; - let mut last_wspace: Option = None; + let mut last_was_space = false; let mut line_len = 0; let mut cur_line = 1; let mut newline_count = 0; @@ -542,7 +542,7 @@ fn format_lines( } // Iterate over the chars in the file map. - for (kind, (b, c)) in CharClasses::new(text.chars().enumerate()) { + for (kind, c) in CharClasses::new(text.chars()) { if c == '\r' { continue; } @@ -563,7 +563,7 @@ fn format_lines( if c == '\n' { if format_line { // Check for (and record) trailing whitespace. - if let Some(..) = last_wspace { + if last_was_space { if should_report_error(config, kind, is_string, &ErrorKind::TrailingWhitespace) { trims.push((cur_line, kind, line_buffer.clone())); @@ -591,19 +591,13 @@ fn format_lines( cur_line += 1; format_line = config.file_lines().contains_line(name, cur_line); newline_count += 1; - last_wspace = None; + last_was_space = false; line_buffer.clear(); is_string = false; } else { newline_count = 0; line_len += if c == '\t' { config.tab_spaces() } else { 1 }; - if c.is_whitespace() { - if last_wspace.is_none() { - last_wspace = Some(b); - } - } else { - last_wspace = None; - } + last_was_space = c.is_whitespace(); line_buffer.push(c); if kind.is_string() { is_string = true; -- cgit 1.4.1-3-g733a5 From 2e90c4314c97b84b8a134fc628cb8d9b1f28d3ad Mon Sep 17 00:00:00 2001 From: Tibo Delor Date: Sun, 10 Jun 2018 14:19:09 +1000 Subject: Stop delaying Trailing whitespace error reporting --- src/lib.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 35448a087a3..c3bf8efb64e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -516,7 +516,6 @@ fn format_lines( config: &Config, report: &FormatReport, ) { - let mut trims = vec![]; let mut last_was_space = false; let mut line_len = 0; let mut cur_line = 1; @@ -565,8 +564,15 @@ fn format_lines( // Check for (and record) trailing whitespace. if last_was_space { if should_report_error(config, kind, is_string, &ErrorKind::TrailingWhitespace) + && !is_skipped_line(cur_line, skipped_range) { - trims.push((cur_line, kind, line_buffer.clone())); + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::TrailingWhitespace, + is_comment: kind.is_comment(), + is_string: kind.is_string(), + line_buffer: line_buffer.clone(), + }); } line_len -= 1; } @@ -611,18 +617,6 @@ fn format_lines( text.truncate(line); } - for &(l, kind, ref b) in &trims { - if !is_skipped_line(l, skipped_range) { - errors.push(FormattingError { - line: l, - kind: ErrorKind::TrailingWhitespace, - is_comment: kind.is_comment(), - is_string: kind.is_string(), - line_buffer: b.clone(), - }); - } - } - report.append(name.clone(), errors); } -- cgit 1.4.1-3-g733a5 From 261238ea51bd564460027d5fddbd93fcd189a5cd Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 19 Jun 2018 13:26:36 +1200 Subject: Change `use_small_heuristics` to an enum and stabilise Since it is now an enum, we can be future compatible since we can add variants for different heuristics. Closes #1974 --- CHANGELOG.md | 3 +++ Configurations.md | 10 +++++----- src/config/config_type.rs | 2 +- src/config/mod.rs | 6 +++--- src/config/options.rs | 7 +++++++ tests/source/chains.rs | 2 +- tests/target/chains.rs | 2 +- 7 files changed, 21 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b9d82ef7be..d868d83a5ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased] +- `use_small_heuristics` changed to be an enum and stabilised. Configuration + options are now ready for 1.0. + ## [0.4.1] 2018-03-16 ### Added diff --git a/Configurations.md b/Configurations.md index 6c4e7dc7760..79a20c4531a 100644 --- a/Configurations.md +++ b/Configurations.md @@ -275,11 +275,11 @@ fn lorem() -> T Whether to use different formatting for items and expressions if they satisfy a heuristic notion of 'small'. -- **Default value**: `true` -- **Possible values**: `true`, `false` -- **Stable**: No +- **Default value**: `Default` +- **Possible values**: `Default`, `Off` +- **Stable**: Yess -#### `true` (default): +#### `Default` (default): ```rust enum Lorem { @@ -309,7 +309,7 @@ fn main() { } ``` -#### `false`: +#### `Off`: ```rust enum Lorem { diff --git a/src/config/config_type.rs b/src/config/config_type.rs index f12d1864728..57a02fb531b 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -399,7 +399,7 @@ macro_rules! create_config { } fn set_heuristics(&mut self) { - if self.use_small_heuristics.2 { + if self.use_small_heuristics.2 == Heuristics::Default { let max_width = self.max_width.2; self.set().width_heuristics(WidthHeuristics::scaled(max_width)); } else { diff --git a/src/config/mod.rs b/src/config/mod.rs index 31da2820167..71bdefeea79 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -41,8 +41,8 @@ create_config! { hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; tab_spaces: usize, 4, true, "Number of spaces per tab"; newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; - use_small_heuristics: bool, true, false, "Whether to use different formatting for items and \ - expressions if they satisfy a heuristic notion of 'small'."; + use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ + formatting for items and expressions if they satisfy a heuristic notion of 'small'."; indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; // Comments and strings @@ -236,7 +236,7 @@ mod test { create_config! { // Options that are used by the generated functions max_width: usize, 100, true, "Maximum width of each line"; - use_small_heuristics: bool, true, false, + use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different formatting for items and \ expressions if they satisfy a heuristic notion of 'small'."; license_template_path: String, String::default(), false, diff --git a/src/config/options.rs b/src/config/options.rs index 8f16e57d468..5f781507d90 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -151,6 +151,13 @@ configuration_option_enum! { TypeDensity: Wide, } +configuration_option_enum! { Heuristics: + // Turn off any heuristics + Off, + // Use Rustfmt's defaults + Default, +} + impl Density { pub fn to_list_tactic(self) -> ListTactic { match self { diff --git a/tests/source/chains.rs b/tests/source/chains.rs index 0ed52ae61be..f9581101bb5 100644 --- a/tests/source/chains.rs +++ b/tests/source/chains.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-use_small_heuristics: false +// rustfmt-use_small_heuristics: Off // Test chain formatting. fn main() { diff --git a/tests/target/chains.rs b/tests/target/chains.rs index 172a7815c39..8023b1243cb 100644 --- a/tests/target/chains.rs +++ b/tests/target/chains.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-use_small_heuristics: false +// rustfmt-use_small_heuristics: Off // Test chain formatting. fn main() { -- cgit 1.4.1-3-g733a5 From 488e6fda12116d3b407e6137cf083d1bbf603254 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 19 Jun 2018 14:36:50 +1200 Subject: Remove some unnecessary `pub`s --- src/reorder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index 027b64e8317..343bbb497bd 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -194,7 +194,7 @@ enum ReorderableItemKind { } impl ReorderableItemKind { - pub fn from(item: &ast::Item) -> Self { + fn from(item: &ast::Item) -> Self { match item.node { _ if contains_macro_use_attr(item) => ReorderableItemKind::Other, ast::ItemKind::ExternCrate(..) => ReorderableItemKind::ExternCrate, @@ -204,11 +204,11 @@ impl ReorderableItemKind { } } - pub fn is_same_item_kind(&self, item: &ast::Item) -> bool { + fn is_same_item_kind(&self, item: &ast::Item) -> bool { ReorderableItemKind::from(item) == *self } - pub fn is_reorderable(&self, config: &Config) -> bool { + fn is_reorderable(&self, config: &Config) -> bool { match *self { ReorderableItemKind::ExternCrate => config.reorder_imports(), ReorderableItemKind::Mod => config.reorder_modules(), @@ -217,7 +217,7 @@ impl ReorderableItemKind { } } - pub fn in_group(&self) -> bool { + fn in_group(&self) -> bool { match *self { ReorderableItemKind::ExternCrate | ReorderableItemKind::Mod -- cgit 1.4.1-3-g733a5 From 036244cdcec6110016ff4287b06d7ac8698a9a15 Mon Sep 17 00:00:00 2001 From: Shohei Wada Date: Wed, 13 Jun 2018 21:54:06 +0900 Subject: Fix #2728. --- src/lib.rs | 12 ++++++++++-- tests/source/issue-2728.rs | 8 ++++++++ tests/target/issue-2728.rs | 8 ++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-2728.rs create mode 100644 tests/target/issue-2728.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 7c33a01953b..114e72c4847 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -718,10 +718,18 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { let mut result = String::with_capacity(snippet.len()); let mut is_first = true; + // While formatting the code, ignore the config's newline style setting and always use "\n" + // instead of "\r\n" for the newline characters. This is okay because the output here is + // not directly outputted by rustfmt command, but used by the comment formatter's input. + // We have output-file-wide "\n" ==> "\r\n" conversion proccess after here if it's necessary. + let mut config_with_unix_newline = config.clone(); + config_with_unix_newline + .set() + .newline_style(NewlineStyle::Unix); + let formatted = format_snippet(&snippet, &config_with_unix_newline)?; + // Trim "fn main() {" on the first line and "}" on the last line, // then unindent the whole code block. - let formatted = format_snippet(&snippet, config)?; - // 2 = "}\n" let block_len = formatted.rfind('}').unwrap_or(formatted.len()); let mut is_indented = true; for (kind, ref line) in LineClasses::new(&formatted[FN_MAIN_PREFIX.len()..block_len]) { diff --git a/tests/source/issue-2728.rs b/tests/source/issue-2728.rs new file mode 100644 index 00000000000..6cb41b75b6d --- /dev/null +++ b/tests/source/issue-2728.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: true +// rustfmt-newline_style: Windows + +//! ```rust +//! extern crate uom; +//! ``` + +fn main() {} diff --git a/tests/target/issue-2728.rs b/tests/target/issue-2728.rs new file mode 100644 index 00000000000..6cb41b75b6d --- /dev/null +++ b/tests/target/issue-2728.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: true +// rustfmt-newline_style: Windows + +//! ```rust +//! extern crate uom; +//! ``` + +fn main() {} -- cgit 1.4.1-3-g733a5 From 2077855e000210be5c89f4d7e17e495122686b28 Mon Sep 17 00:00:00 2001 From: Josh Chase Date: Tue, 19 Jun 2018 11:28:00 -0400 Subject: Remove NestedImport tactic --- src/config/lists.rs | 2 -- src/imports.rs | 16 ++++++---------- src/lists.rs | 5 ++--- 3 files changed, 8 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/config/lists.rs b/src/config/lists.rs index a9846a1cc74..04406e8d566 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -19,8 +19,6 @@ pub enum DefinitiveListTactic { Vertical, Horizontal, Mixed, - /// Tactic for nested import. - NestedImport, /// Special case tactic for `format!()`, `write!()` style macros. SpecialMacro(usize), } diff --git a/src/imports.rs b/src/imports.rs index a1cf6a83f07..4740921c525 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -706,16 +706,12 @@ fn rewrite_nested_use_tree( shape.width.saturating_sub(2) }; - let tactic = if has_nested_list { - DefinitiveListTactic::NestedImport - } else { - definitive_tactic( - &list_items, - context.config.imports_layout(), - Separator::Comma, - remaining_width, - ) - }; + let tactic = definitive_tactic( + &list_items, + context.config.imports_layout(), + Separator::Comma, + remaining_width, + ); let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; diff --git a/src/lists.rs b/src/lists.rs index 6e867918864..5562602133b 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -282,14 +282,13 @@ where result.push('\n'); result.push_str(indent_str); } - DefinitiveListTactic::Mixed | DefinitiveListTactic::NestedImport => { + DefinitiveListTactic::Mixed => { let total_width = total_item_width(item) + item_sep_len; // 1 is space between separator and item. if (line_len > 0 && line_len + 1 + total_width > formatting.shape.width) || prev_item_had_post_comment - || (tactic == DefinitiveListTactic::NestedImport - && (prev_item_is_nested_import || (!first && inner_item.contains("::")))) + || (prev_item_is_nested_import || (!first && inner_item.contains("::"))) { result.push('\n'); result.push_str(indent_str); -- cgit 1.4.1-3-g733a5 From ee5ff2d9e8f2fcf7ef8ceefc5de78e5439ed7a21 Mon Sep 17 00:00:00 2001 From: Josh Chase Date: Tue, 19 Jun 2018 11:28:58 -0400 Subject: Add flag to the ListFormatting struct for nested imports --- src/attr.rs | 1 + src/closures.rs | 1 + src/expr.rs | 2 ++ src/imports.rs | 1 + src/items.rs | 4 ++++ src/lists.rs | 6 +++++- src/macros.rs | 1 + src/matches.rs | 1 + src/overflow.rs | 1 + src/reorder.rs | 1 + src/types.rs | 1 + src/vertical.rs | 1 + 12 files changed, 20 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 28e3e24ea09..efbd4872aae 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -247,6 +247,7 @@ impl Rewrite for ast::MetaItem { shape: item_shape, ends_with_newline: false, preserve_newline: false, + nested: false, config: context.config, }; let item_str = write_list(&item_vec, &fmt)?; diff --git a/src/closures.rs b/src/closures.rs index 3d0a52de0dc..257b8729f45 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -260,6 +260,7 @@ fn rewrite_closure_fn_decl( shape: arg_shape, ends_with_newline: false, preserve_newline: true, + nested: false, config: context.config, }; let list_str = write_list(&item_vec, &fmt)?; diff --git a/src/expr.rs b/src/expr.rs index 112383e7e4c..0c2716a2dba 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1338,6 +1338,7 @@ pub fn rewrite_multiple_patterns( shape, ends_with_newline: false, preserve_newline: false, + nested: false, config: context.config, }; write_list(&items, &fmt) @@ -1902,6 +1903,7 @@ where shape, ends_with_newline: false, preserve_newline: false, + nested: false, config: context.config, }; let list_str = write_list(&item_vec, &fmt)?; diff --git a/src/imports.rs b/src/imports.rs index 4740921c525..7e45bb55f0d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -727,6 +727,7 @@ fn rewrite_nested_use_tree( shape: nested_shape, ends_with_newline, preserve_newline: true, + nested: has_nested_list, config: context.config, }; diff --git a/src/items.rs b/src/items.rs index 38311abcba0..843d5839de9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -533,6 +533,7 @@ impl<'a> FmtVisitor<'a> { shape, ends_with_newline: true, preserve_newline: true, + nested: false, config: self.config, }; @@ -2307,6 +2308,7 @@ fn rewrite_args( shape: Shape::legacy(budget, indent), ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, + nested: false, config: context.config, }; @@ -2494,6 +2496,7 @@ fn rewrite_where_clause_rfc_style( shape: clause_shape, ends_with_newline: true, preserve_newline: true, + nested: false, config: context.config, }; let preds_str = write_list(&items.collect::>(), &fmt)?; @@ -2607,6 +2610,7 @@ fn rewrite_where_clause( shape: Shape::legacy(budget, offset), ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, + nested: false, config: context.config, }; let preds_str = write_list(&item_vec, &fmt)?; diff --git a/src/lists.rs b/src/lists.rs index 5562602133b..97dd093b4f9 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -34,6 +34,8 @@ pub struct ListFormatting<'a> { pub ends_with_newline: bool, // Remove newlines between list elements for expressions. pub preserve_newline: bool, + // Nested import lists get some special handling for the "Mixed" list type + pub nested: bool, pub config: &'a Config, } @@ -288,7 +290,8 @@ where // 1 is space between separator and item. if (line_len > 0 && line_len + 1 + total_width > formatting.shape.width) || prev_item_had_post_comment - || (prev_item_is_nested_import || (!first && inner_item.contains("::"))) + || (formatting.nested + && (prev_item_is_nested_import || (!first && inner_item.contains("::")))) { result.push('\n'); result.push_str(indent_str); @@ -824,6 +827,7 @@ pub fn struct_lit_formatting<'a>( shape, ends_with_newline, preserve_newline: true, + nested: false, config: context.config, } } diff --git a/src/macros.rs b/src/macros.rs index 9053aaebd90..801e04baad0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -399,6 +399,7 @@ pub fn rewrite_macro_def( shape: arm_shape, ends_with_newline: true, preserve_newline: true, + nested: false, config: context.config, }; diff --git a/src/matches.rs b/src/matches.rs index 9551dc36002..c179efc3963 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -224,6 +224,7 @@ fn rewrite_match_arms( shape: arm_shape, ends_with_newline: true, preserve_newline: true, + nested: false, config: context.config, }; diff --git a/src/overflow.rs b/src/overflow.rs index 62675b4002c..f91ef38e2ee 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -388,6 +388,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { _ => false, }, preserve_newline: false, + nested: false, config: self.context.config, }; diff --git a/src/reorder.rs b/src/reorder.rs index 027b64e8317..ed6df1227ef 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -77,6 +77,7 @@ fn wrap_reorderable_items( shape, ends_with_newline: true, preserve_newline: false, + nested: false, config: context.config, }; diff --git a/src/types.rs b/src/types.rs index 46d48e72763..44fdbee6efd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -366,6 +366,7 @@ where shape: list_shape, ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), preserve_newline: true, + nested: false, config: context.config, }; diff --git a/src/vertical.rs b/src/vertical.rs index 1595b22c5c4..a8a8ee6cec3 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -252,6 +252,7 @@ fn rewrite_aligned_items_inner( shape: item_shape, ends_with_newline: true, preserve_newline: true, + nested: false, config: context.config, }; write_list(&items, &fmt) -- cgit 1.4.1-3-g733a5 From 87edd75ecf26c9084969f431bb5e363693a8a4ca Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 22 Jun 2018 14:41:17 +1200 Subject: TODO -> FIXME Or just delete Closes #25 --- src/filemap.rs | 2 -- src/format-diff/main.rs | 2 +- src/items.rs | 4 ++-- src/lists.rs | 1 - src/macros.rs | 1 - src/missed_spans.rs | 2 -- src/reorder.rs | 2 +- src/types.rs | 2 +- 8 files changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index 507e85f2086..f64e428c221 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// TODO: add tests - use std::fs; use std::io::{self, Write}; diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index fe528a6c0ea..37ad4f35a1d 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -175,7 +175,7 @@ where None => continue, }; - // TODO(emilio): We could avoid this most of the time if needed, but + // FIXME(emilio): We could avoid this most of the time if needed, but // it's not clear it's worth it. if !file_filter.is_match(file) { continue; diff --git a/src/items.rs b/src/items.rs index 843d5839de9..507ea09a8fe 100644 --- a/src/items.rs +++ b/src/items.rs @@ -125,8 +125,8 @@ impl Rewrite for ast::Local { } } -// TODO convert to using rewrite style rather than visitor -// TODO format modules in this style +// FIXME convert to using rewrite style rather than visitor +// FIXME format modules in this style #[allow(dead_code)] struct Item<'a> { keyword: &'static str, diff --git a/src/lists.rs b/src/lists.rs index 97dd093b4f9..3b49a27ccef 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -212,7 +212,6 @@ where } // Format a list of commented items into a string. -// TODO: add unit tests pub fn write_list(items: I, formatting: &ListFormatting) -> Option where I: IntoIterator + Clone, diff --git a/src/macros.rs b/src/macros.rs index 801e04baad0..512c3ac1c56 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -192,7 +192,6 @@ pub fn rewrite_macro_inner( }; } // Format well-known macros which cannot be parsed as a valid AST. - // TODO: Maybe add more macros? if macro_name == "lazy_static!" && !has_comment { if let success @ Some(..) = format_lazy_static(context, shape, &ts) { return success; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7e558d308b7..70d4c66d7fb 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -43,8 +43,6 @@ impl<'a> FmtVisitor<'a> { self.buffer.is_empty() } - // TODO these format_missing methods are ugly. Refactor and add unit tests - // for the central whitespace stripping loop. pub fn format_missing(&mut self, end: BytePos) { // HACK(topecongiro) // We use `format_missing()` to extract a missing comment between a macro diff --git a/src/reorder.rs b/src/reorder.rs index ecad2c25652..3d2b098781d 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -14,7 +14,7 @@ //! order. Trait items are reordered in pre-determined order (associated types //! and constants comes before methods). -// TODO(#2455): Reorder trait items. +// FIXME(#2455): Reorder trait items. use config::{lists::*, Config}; use syntax::{ast, attr, codemap::Span}; diff --git a/src/types.rs b/src/types.rs index 44fdbee6efd..6e550594680 100644 --- a/src/types.rs +++ b/src/types.rs @@ -418,7 +418,7 @@ fn type_bound_colon(context: &RewriteContext) -> &'static str { impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - // TODO: dead spans? + // FIXME: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ref bound_generic_params, -- cgit 1.4.1-3-g733a5 From 1d4b988414e48f16c1aa44a79e6f4b11d929bb76 Mon Sep 17 00:00:00 2001 From: Mike Baker Date: Sat, 14 Apr 2018 10:21:54 +0100 Subject: Strip leading `|` in match arm patterns This addresses issue #2621 This commit turns out to be a partial revert of ea3c01e3374143912f048b22fda106ee8d5a1cd8 The rationale is that a `|` character preceding a match pattern is not semantically relevant and therefore should be considered a style/formatting choice. A discussion concluded that the best way to emit consistent formatting here was to strip the leading `|` This removes the match_with_beginning_vert test because it was asserting the old behaviour which has been changed, it adds a new test (issue_2621) which should be a more comprehensive check of the behavior of `|` in match arms. Discussion at https://github.com/rust-lang-nursery/fmt-rfcs/issues/119 --- src/matches.rs | 40 +++++++++++++++------------------------- tests/source/match.rs | 28 +++++++++++++++++----------- tests/target/match.rs | 25 +++++++++++++++---------- 3 files changed, 47 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index c179efc3963..d46b19be723 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -68,7 +68,7 @@ impl<'a> Spanned for ArmWrapper<'a> { impl<'a> Rewrite for ArmWrapper<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last, self.beginning_vert) + rewrite_match_arm(context, self.arm, shape, self.is_last) } } @@ -236,7 +236,6 @@ fn rewrite_match_arm( arm: &ast::Arm, shape: Shape, is_last: bool, - beginning_vert: Option, ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { @@ -256,22 +255,18 @@ fn rewrite_match_arm( } else { (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; - let pats_str = rewrite_match_pattern( - context, - &ptr_vec_to_ref_vec(&arm.pats), - &arm.guard, - beginning_vert.is_some(), - shape, - ).and_then(|pats_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &pats_str, - missing_span, - shape, - false, - ) - })?; + let pats_str = + rewrite_match_pattern(context, &ptr_vec_to_ref_vec(&arm.pats), &arm.guard, shape) + .and_then(|pats_str| { + combine_strs_with_missing_comments( + context, + &attrs_str, + &pats_str, + missing_span, + shape, + false, + ) + })?; rewrite_match_body( context, &arm.body, @@ -286,22 +281,17 @@ fn rewrite_match_pattern( context: &RewriteContext, pats: &[&ast::Pat], guard: &Option>, - has_beginning_vert: bool, shape: Shape, ) -> Option { // Patterns // 5 = ` => {` - // 2 = `| ` - let pat_shape = shape - .sub_width(5)? - .offset_left(if has_beginning_vert { 2 } else { 0 })?; + let pat_shape = shape.sub_width(5)?; let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?; - let beginning_vert = if has_beginning_vert { "| " } else { "" }; // Guard let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; - Some(format!("{}{}{}", beginning_vert, pats_str, guard_str)) + Some(format!("{}{}", pats_str, guard_str)) } // (extend, body) diff --git a/tests/source/match.rs b/tests/source/match.rs index d1664ca9f37..244d0b45f25 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -452,17 +452,6 @@ fn issue_2152() { } } -// #2462 -// Preserve a `|` at the beginning of a match arm. -fn match_with_beginning_vert() { - let x = Foo::A; - match x { - | Foo::A - | Foo::B => println!("AB"), - | Foo::C => println!("C"), - } -} - // #2376 // Preserve block around expressions with condition. fn issue_2376() { @@ -485,3 +474,20 @@ fn issue_2376() { } } } + +// #2621 +// Strip leading `|` in match arm patterns +fn issue_2621() { + let x = Foo::A; + match x { + Foo::A => println!("No vert single condition"), + Foo::B | Foo::C => println!("Center vert two conditions"), + | Foo::D => println!("Preceding vert single condition"), + | Foo::E + | Foo::F => println!("Preceding vert over two lines"), + Foo::G | + Foo::H => println!("Trailing vert over two lines"), + // Comment on its own line + | Foo::I => println!("With comment"), // Comment after line + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 7ed49c61f1d..be1ecb49535 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -481,16 +481,6 @@ fn issue_2152() { } } -// #2462 -// Preserve a `|` at the beginning of a match arm. -fn match_with_beginning_vert() { - let x = Foo::A; - match x { - | Foo::A | Foo::B => println!("AB"), - | Foo::C => println!("C"), - } -} - // #2376 // Preserve block around expressions with condition. fn issue_2376() { @@ -513,3 +503,18 @@ fn issue_2376() { } } } + +// #2621 +// Strip leading `|` in match arm patterns +fn issue_2621() { + let x = Foo::A; + match x { + Foo::A => println!("No vert single condition"), + Foo::B | Foo::C => println!("Center vert two conditions"), + Foo::D => println!("Preceding vert single condition"), + Foo::E | Foo::F => println!("Preceding vert over two lines"), + Foo::G | Foo::H => println!("Trailing vert over two lines"), + // Comment on its own line + Foo::I => println!("With comment"), // Comment after line + } +} -- cgit 1.4.1-3-g733a5 From e5e1e0cea8c3a2b10dbad4cce7d79d7c24f8364b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 25 Jun 2018 15:24:00 +0900 Subject: Fix compile errors from breaking changes in libsyntax cc https://github.com/rust-lang/rust/pull/48149. --- src/chains.rs | 9 ++++--- src/expr.rs | 29 +++++++++++++++----- src/imports.rs | 2 +- src/items.rs | 41 +++++++++++----------------- src/spanned.rs | 60 ++++++++++++++++++++--------------------- src/types.rs | 84 +++++++++++++++++++++++++++++++--------------------------- src/visitor.rs | 8 +++--- 7 files changed, 120 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c0dafc4f0f2..52999635cf1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -70,6 +70,7 @@ use expr::rewrite_call; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use spanned::Spanned; use utils::{ first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, wrap_str, @@ -436,9 +437,9 @@ fn rewrite_chain_subexpr( match expr.node { ast::ExprKind::MethodCall(ref segment, ref expressions) => { - let types = match segment.parameters { + let types = match segment.args { Some(ref params) => match **params { - ast::PathParameters::AngleBracketed(ref data) => &data.types[..], + ast::GenericArgs::AngleBracketed(ref data) => &data.args[..], _ => &[], }, _ => &[], @@ -484,7 +485,7 @@ fn is_try(expr: &ast::Expr) -> bool { fn rewrite_method_call( method_name: ast::Ident, - types: &[ptr::P], + types: &[ast::GenericArg], args: &[ptr::P], span: Span, context: &RewriteContext, @@ -500,7 +501,7 @@ fn rewrite_method_call( let type_str = format!("::<{}>", type_list.join(", ")); - (types.last().unwrap().span.hi(), type_str) + (types.last().unwrap().span().hi(), type_str) }; let callee_str = format!(".{}{}", method_name, type_str); diff --git a/src/expr.rs b/src/expr.rs index 0c2716a2dba..b8a323f73a2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2014,8 +2014,8 @@ fn rewrite_assignment( pub enum RhsTactics { /// Use heuristics. Default, - /// Put the rhs on the next line if it uses multiple line. - ForceNextLine, + /// Put the rhs on the next line if it uses multiple line, without extra indentation. + ForceNextLineWithoutIndent, } // The left hand side must contain everything up to, and including, the @@ -2072,11 +2072,12 @@ fn choose_rhs( _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(shape.rhs_overhead(context.config))?; + let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics)?; let new_rhs = expr.rewrite(context, new_shape); - let new_indent_str = &new_shape.indent.to_string_with_newline(context.config); + let new_indent_str = &shape + .indent + .block_indent(context.config) + .to_string_with_newline(context.config); match (orig_rhs, new_rhs) { (Some(ref orig_rhs), Some(ref new_rhs)) @@ -2098,8 +2099,22 @@ fn choose_rhs( } } +fn shape_from_rhs_tactic( + context: &RewriteContext, + shape: Shape, + rhs_tactic: RhsTactics, +) -> Option { + match rhs_tactic { + RhsTactics::ForceNextLineWithoutIndent => Some(shape.with_max_width(context.config)), + RhsTactics::Default => { + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(shape.rhs_overhead(context.config)) + } + } +} + pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { - rhs_tactics == RhsTactics::ForceNextLine + rhs_tactics == RhsTactics::ForceNextLineWithoutIndent || !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 } diff --git a/src/imports.rs b/src/imports.rs index 7e45bb55f0d..b8639fdd67e 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -346,7 +346,7 @@ impl UseTree { .collect(), )); } - UseTreeKind::Simple(ref rename) => { + UseTreeKind::Simple(ref rename, ..) => { let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); let alias = rename.and_then(|ident| { if ident == path_to_imported_ident(&a.prefix) { diff --git a/src/items.rs b/src/items.rs index 507ea09a8fe..05ac3a3fe36 100644 --- a/src/items.rs +++ b/src/items.rs @@ -36,7 +36,6 @@ use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; -use types::TraitTyParamBounds; use utils::*; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -971,7 +970,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) is_auto, unsafety, ref generics, - ref type_param_bounds, + ref generic_bounds, ref trait_items, ) = item.node { @@ -997,23 +996,22 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. - if !type_param_bounds.is_empty() { + if !generic_bounds.is_empty() { let ident_hi = context .snippet_provider .span_after(item.span, &format!("{}", item.ident)); - let bound_hi = type_param_bounds.last().unwrap().span().hi(); + let bound_hi = generic_bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); if contains_comment(snippet) { return None; } - } - if !type_param_bounds.is_empty() { + result = rewrite_assign_rhs_with( context, result + ":", - &TraitTyParamBounds::new(type_param_bounds), + generic_bounds, shape, - RhsTactics::ForceNextLine, + RhsTactics::ForceNextLineWithoutIndent, )?; } @@ -1026,10 +1024,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) }; let where_budget = context.budget(last_line_width(&result)); - let pos_before_where = if type_param_bounds.is_empty() { + let pos_before_where = if generic_bounds.is_empty() { generics.where_clause.span.lo() } else { - type_param_bounds[type_param_bounds.len() - 1].span().hi() + generic_bounds[generic_bounds.len() - 1].span().hi() }; let option = WhereClauseOption::snuggled(&generics_str); let where_clause_str = rewrite_where_clause( @@ -1134,7 +1132,7 @@ pub fn format_trait_alias( context: &RewriteContext, ident: ast::Ident, generics: &ast::Generics, - ty_param_bounds: &ast::TyParamBounds, + generic_bounds: &ast::GenericBounds, shape: Shape, ) -> Option { let alias = ident.name.as_str(); @@ -1143,7 +1141,7 @@ pub fn format_trait_alias( let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?; let lhs = format!("trait {} =", generics_str); // 1 = ";" - rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";") + rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";") } fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { @@ -1671,13 +1669,13 @@ fn rewrite_static( pub fn rewrite_associated_type( ident: ast::Ident, ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, + generic_bounds_opt: Option<&ast::GenericBounds>, context: &RewriteContext, indent: Indent, ) -> Option { let prefix = format!("type {}", ident); - let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt { + let type_bounds_str = if let Some(bounds) = generic_bounds_opt { if bounds.is_empty() { String::new() } else { @@ -1703,11 +1701,11 @@ pub fn rewrite_associated_impl_type( ident: ast::Ident, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, - ty_param_bounds_opt: Option<&ast::TyParamBounds>, + generic_bounds_opt: Option<&ast::GenericBounds>, context: &RewriteContext, indent: Indent, ) -> Option { - let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?; + let result = rewrite_associated_type(ident, ty_opt, generic_bounds_opt, context, indent)?; match defaultness { ast::Defaultness::Default => Some(format!("default {}", result)), @@ -2698,7 +2696,7 @@ fn format_generics( } // If the generics are not parameterized then generics.span.hi() == 0, // so we use span.lo(), which is the position after `struct Foo`. - let span_end_before_where = if generics.is_parameterized() { + let span_end_before_where = if !generics.params.is_empty() { generics.span.hi() } else { span.lo() @@ -2804,15 +2802,6 @@ impl Rewrite for ast::ForeignItem { } } -impl Rewrite for ast::GenericParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape), - ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape), - } - } -} - /// Rewrite an inline mod. pub fn rewrite_mod(item: &ast::Item) -> String { let mut result = String::with_capacity(32); diff --git a/src/spanned.rs b/src/spanned.rs index 237624ab8fe..c2886fcdd8f 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -14,6 +14,8 @@ use syntax::codemap::Span; use macros::MacroArg; use utils::{mk_sp, outer_attributes}; +use std::cmp::max; + /// Spanned returns a span including attributes, if available. pub trait Spanned { fn span(&self) -> Span; @@ -110,10 +112,25 @@ impl Spanned for ast::Arg { impl Spanned for ast::GenericParam { fn span(&self) -> Span { - match *self { - ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.span(), - ast::GenericParam::Type(ref ty) => ty.span(), - } + let lo = if self.attrs.is_empty() { + self.ident.span.lo() + } else { + self.attrs[0].span.lo() + }; + let hi = if self.bounds.is_empty() { + self.ident.span.hi() + } else { + self.bounds.last().unwrap().span().hi() + }; + let ty_hi = if let ast::GenericParamKind::Type { + default: Some(ref ty), + } = self.kind + { + ty.span().hi() + } else { + hi + }; + mk_sp(lo, max(hi, ty_hi)) } } @@ -142,45 +159,24 @@ impl Spanned for ast::FunctionRetTy { } } -impl Spanned for ast::TyParam { +impl Spanned for ast::GenericArg { fn span(&self) -> Span { - // Note that ty.span is the span for ty.ident, not the whole item. - let lo = if self.attrs.is_empty() { - self.ident.span.lo() - } else { - self.attrs[0].span.lo() - }; - if let Some(ref def) = self.default { - return mk_sp(lo, def.span.hi()); - } - if self.bounds.is_empty() { - return mk_sp(lo, self.ident.span.hi()); + match *self { + ast::GenericArg::Lifetime(ref lt) => lt.ident.span, + ast::GenericArg::Type(ref ty) => ty.span(), } - let hi = self.bounds[self.bounds.len() - 1].span().hi(); - mk_sp(lo, hi) } } -impl Spanned for ast::TyParamBound { +impl Spanned for ast::GenericBound { fn span(&self) -> Span { match *self { - ast::TyParamBound::TraitTyParamBound(ref ptr, _) => ptr.span, - ast::TyParamBound::RegionTyParamBound(ref l) => l.ident.span, + ast::GenericBound::Trait(ref ptr, _) => ptr.span, + ast::GenericBound::Outlives(ref l) => l.ident.span, } } } -impl Spanned for ast::LifetimeDef { - fn span(&self) -> Span { - let hi = if self.bounds.is_empty() { - self.lifetime.ident.span.hi() - } else { - self.bounds[self.bounds.len() - 1].ident.span.hi() - }; - mk_sp(self.lifetime.ident.span.lo(), hi) - } -} - impl Spanned for MacroArg { fn span(&self) -> Span { match *self { diff --git a/src/types.rs b/src/types.rs index 6e550594680..20c6cebeefd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -148,6 +148,15 @@ enum SegmentParam<'a> { Binding(&'a ast::TypeBinding), } +impl<'a> SegmentParam<'a> { + fn from_generic_arg(arg: &ast::GenericArg) -> SegmentParam { + match arg { + ast::GenericArg::Lifetime(ref lt) => SegmentParam::LifeTime(lt), + ast::GenericArg::Type(ref ty) => SegmentParam::Type(ty), + } + } +} + impl<'a> Spanned for SegmentParam<'a> { fn span(&self) -> Span { match *self { @@ -220,18 +229,15 @@ fn rewrite_segment( shape.shrink_left(ident_len)? }; - if let Some(ref params) = segment.parameters { - match **params { - ast::PathParameters::AngleBracketed(ref data) - if !data.lifetimes.is_empty() - || !data.types.is_empty() - || !data.bindings.is_empty() => + if let Some(ref args) = segment.args { + match **args { + ast::GenericArgs::AngleBracketed(ref data) + if !data.args.is_empty() || !data.bindings.is_empty() => { let param_list = data - .lifetimes + .args .iter() - .map(SegmentParam::LifeTime) - .chain(data.types.iter().map(|x| SegmentParam::Type(&*x))) + .map(SegmentParam::from_generic_arg) .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); @@ -257,7 +263,7 @@ fn rewrite_segment( result.push_str(&generics_str) } - ast::PathParameters::Parenthesized(ref data) => { + ast::GenericArgs::Parenthesized(ref data) => { let output = match data.output { Some(ref ty) => FunctionRetTy::Ty(ty.clone()), None => FunctionRetTy::Default(codemap::DUMMY_SP), @@ -457,15 +463,18 @@ impl Rewrite for ast::WherePredicate { } } -impl Rewrite for ast::LifetimeDef { +impl Rewrite for ast::GenericArg { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - rewrite_bounded_lifetime(&self.lifetime, &self.bounds, context, shape) + match *self { + ast::GenericArg::Lifetime(ref lt) => lt.rewrite(context, shape), + ast::GenericArg::Type(ref ty) => ty.rewrite(context, shape), + } } } fn rewrite_bounded_lifetime( lt: &ast::Lifetime, - bounds: &[ast::Lifetime], + bounds: &[ast::GenericBound], context: &RewriteContext, shape: Shape, ) -> Option { @@ -486,45 +495,36 @@ fn rewrite_bounded_lifetime( } } -impl Rewrite for ast::TyParamBound { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - match *self { - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => { - tref.rewrite(context, shape) - } - ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => Some( - format!("?{}", tref.rewrite(context, shape.offset_left(1)?)?), - ), - ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape), - } - } -} - impl Rewrite for ast::Lifetime { fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { Some(self.ident.to_string()) } } -/// A simple wrapper over type param bounds in trait. -#[derive(new)] -pub struct TraitTyParamBounds<'a> { - inner: &'a ast::TyParamBounds, -} - -impl<'a> Rewrite for TraitTyParamBounds<'a> { +impl Rewrite for ast::GenericBound { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - join_bounds(context, shape, self.inner, false) + match *self { + ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => { + match trait_bound_modifier { + ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape), + ast::TraitBoundModifier::Maybe => { + let rw = poly_trait_ref.rewrite(context, shape.offset_left(1)?)?; + Some(format!("?{}", rw)) + } + } + } + ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), + } } } -impl Rewrite for ast::TyParamBounds { +impl Rewrite for ast::GenericBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { join_bounds(context, shape, self, true) } } -impl Rewrite for ast::TyParam { +impl Rewrite for ast::GenericParam { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut result = String::with_capacity(128); // FIXME: If there are more than one attributes, this will force multiline. @@ -537,7 +537,10 @@ impl Rewrite for ast::TyParam { result.push_str(type_bound_colon(context)); result.push_str(&self.bounds.rewrite(context, shape)?) } - if let Some(ref def) = self.default { + if let ast::GenericParamKind::Type { + default: Some(ref def), + } = self.kind + { let eq_str = match context.config.type_punctuation_density() { TypeDensity::Compressed => "=", TypeDensity::Wide => " = ", @@ -786,7 +789,10 @@ fn rewrite_lifetime_param( ) -> Option { let result = generic_params .iter() - .filter(|p| p.is_lifetime_param()) + .filter(|p| match p.kind { + ast::GenericParamKind::Lifetime => true, + _ => false, + }) .map(|lt| lt.rewrite(context, shape)) .collect::>>()? .join(", "); diff --git a/src/visitor.rs b/src/visitor.rs index 7d676770421..c58122025de 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -354,13 +354,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = format_trait(&self.get_context(), item, self.block_indent); self.push_rewrite(item.span, rw); } - ast::ItemKind::TraitAlias(ref generics, ref ty_param_bounds) => { + ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { let shape = Shape::indented(self.block_indent, self.config); let rw = format_trait_alias( &self.get_context(), item.ident, generics, - ty_param_bounds, + generic_bounds, shape, ); self.push_rewrite(item.span, rw); @@ -461,11 +461,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(&inner_attrs), ); } - ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => { + ast::TraitItemKind::Type(ref generic_bounds, ref type_default) => { let rewrite = rewrite_associated_type( ti.ident, type_default.as_ref(), - Some(type_param_bounds), + Some(generic_bounds), &self.get_context(), self.block_indent, ); -- cgit 1.4.1-3-g733a5 From 3027c2137119b8c93252db9cdda35071c74c35db Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 Jun 2018 23:36:45 +0900 Subject: Handle raw identifiers --- src/imports.rs | 24 +++++++------- src/items.rs | 97 +++++++++++++++++++++++++++++++++++++++------------------ src/macros.rs | 18 ++++++----- src/patterns.rs | 6 ++-- src/reorder.rs | 2 +- src/types.rs | 16 +++++----- src/utils.rs | 8 +++-- src/vertical.rs | 4 +-- src/visitor.rs | 9 ++++-- 9 files changed, 117 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index b8639fdd67e..ddb7262430d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -21,7 +21,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListIte use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::mk_sp; +use utils::{mk_sp, rewrite_ident}; use visitor::FmtVisitor; use std::borrow::Cow; @@ -141,9 +141,12 @@ impl UseSegment { } } - fn from_path_segment(path_seg: &ast::PathSegment) -> Option { - let name = path_seg.ident.name.as_str(); - if name == "{{root}}" { + fn from_path_segment( + context: &RewriteContext, + path_seg: &ast::PathSegment, + ) -> Option { + let name = rewrite_ident(context, path_seg.ident); + if name.is_empty() || name == "{{root}}" { return None; } Some(if name == "self" { @@ -231,10 +234,9 @@ impl fmt::Display for UseTree { impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { - let vis = self - .visibility - .as_ref() - .map_or(Cow::from(""), |vis| ::utils::format_visibility(&vis)); + let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { + ::utils::format_visibility(context, &vis) + }); let use_str = self .rewrite(context, shape.offset_left(vis.len())?) .map(|s| { @@ -314,7 +316,7 @@ impl UseTree { attrs, }; for p in &a.prefix.segments { - if let Some(use_segment) = UseSegment::from_path_segment(p) { + if let Some(use_segment) = UseSegment::from_path_segment(context, p) { result.path.push(use_segment); } } @@ -347,12 +349,12 @@ impl UseTree { )); } UseTreeKind::Simple(ref rename, ..) => { - let mut name = (*path_to_imported_ident(&a.prefix).name.as_str()).to_owned(); + let mut name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned(); let alias = rename.and_then(|ident| { if ident == path_to_imported_ident(&a.prefix) { None } else { - Some(ident.to_string()) + Some(rewrite_ident(context, ident).to_owned()) } }); diff --git a/src/items.rs b/src/items.rs index 05ac3a3fe36..bef8fd79599 100644 --- a/src/items.rs +++ b/src/items.rs @@ -233,7 +233,7 @@ impl<'a> FnSig<'a> { fn to_str(&self, context: &RewriteContext) -> String { let mut result = String::with_capacity(128); // Vis defaultness constness unsafety abi. - result.push_str(&*format_visibility(&self.visibility)); + result.push_str(&*format_visibility(context, &self.visibility)); result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); result.push_str(format_unsafety(self.unsafety)); @@ -437,7 +437,7 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span, ) { - let enum_header = format_header("enum ", ident, vis); + let enum_header = format_header(&self.get_context(), "enum ", ident, vis); self.push_str(&enum_header); let enum_snippet = self.snippet(span); @@ -571,10 +571,10 @@ impl<'a> FmtVisitor<'a> { )?, ast::VariantData::Unit(..) => { if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", field.node.ident.name); + let lhs = format!("{} =", rewrite_ident(&context, field.node.ident)); rewrite_assign_rhs(&context, lhs, &*expr.value, shape)? } else { - field.node.ident.name.to_string() + rewrite_ident(&context, field.node.ident).to_owned() } } }; @@ -797,7 +797,7 @@ fn format_impl_ref_and_type( { let mut result = String::with_capacity(128); - result.push_str(&format_visibility(&item.vis)); + result.push_str(&format_visibility(context, &item.vis)); result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); @@ -916,8 +916,8 @@ pub struct StructParts<'a> { } impl<'a> StructParts<'a> { - fn format_header(&self) -> String { - format_header(self.prefix, self.ident, self.vis) + fn format_header(&self, context: &RewriteContext) -> String { + format_header(context, self.prefix, self.ident, self.vis) } fn from_variant(variant: &'a ast::Variant) -> Self { @@ -977,7 +977,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let mut result = String::with_capacity(128); let header = format!( "{}{}{}trait ", - format_visibility(&item.vis), + format_visibility(context, &item.vis), format_unsafety(unsafety), format_auto(is_auto), ); @@ -988,7 +988,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = rewrite_generics( context, - &item.ident.to_string(), + rewrite_ident(context, item.ident), generics, shape, mk_sp(item.span.lo(), body_lo), @@ -999,7 +999,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if !generic_bounds.is_empty() { let ident_hi = context .snippet_provider - .span_after(item.span, &format!("{}", item.ident)); + .span_after(item.span, &item.ident.as_str()); let bound_hi = generic_bounds.last().unwrap().span().hi(); let snippet = context.snippet(mk_sp(ident_hi, bound_hi)); if contains_comment(snippet) { @@ -1135,7 +1135,7 @@ pub fn format_trait_alias( generic_bounds: &ast::GenericBounds, shape: Shape, ) -> Option { - let alias = ident.name.as_str(); + let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?; @@ -1145,7 +1145,7 @@ pub fn format_trait_alias( } fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { - let header_str = format_header(p.prefix, p.ident, p.vis); + let header_str = format_header(context, p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { let hi = if generics.where_clause.predicates.is_empty() { generics.span.hi() @@ -1177,7 +1177,7 @@ pub fn format_struct_struct( let mut result = String::with_capacity(1024); let span = struct_parts.span; - let header_str = struct_parts.format_header(); + let header_str = struct_parts.format_header(context); result.push_str(&header_str); let header_hi = span.lo() + BytePos(header_str.len() as u32); @@ -1312,7 +1312,7 @@ fn format_tuple_struct( let mut result = String::with_capacity(1024); let span = struct_parts.span; - let header_str = struct_parts.format_header(); + let header_str = struct_parts.format_header(context); result.push_str(&header_str); let body_lo = if fields.is_empty() { @@ -1413,7 +1413,7 @@ pub fn rewrite_type_alias( ) -> Option { let mut result = String::with_capacity(128); - result.push_str(&format_visibility(vis)); + result.push_str(&format_visibility(context, vis)); result.push_str("type "); // 2 = `= ` @@ -1424,7 +1424,13 @@ pub fn rewrite_type_alias( context.snippet_provider.span_after(span, "type"), ty.span.lo(), ); - let generics_str = rewrite_generics(context, &ident.to_string(), generics, g_shape, g_span)?; + let generics_str = rewrite_generics( + context, + rewrite_ident(context, ident), + generics, + g_shape, + g_span, + )?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1467,10 +1473,15 @@ pub fn rewrite_struct_field_prefix( context: &RewriteContext, field: &ast::StructField, ) -> Option { - let vis = format_visibility(&field.vis); + let vis = format_visibility(context, &field.vis); let type_annotation_spacing = type_annotation_spacing(context.config); Some(match field.ident { - Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0), + Some(name) => format!( + "{}{}{}:", + vis, + rewrite_ident(context, name), + type_annotation_spacing.0 + ), None => format!("{}", vis), }) } @@ -1623,7 +1634,7 @@ fn rewrite_static( ); let mut prefix = format!( "{}{}{} {}{}{}", - format_visibility(static_parts.vis), + format_visibility(context, static_parts.vis), static_parts.defaultness.map_or("", format_defaultness), static_parts.prefix, format_mutability(static_parts.mutability), @@ -1673,7 +1684,7 @@ pub fn rewrite_associated_type( context: &RewriteContext, indent: Indent, ) -> Option { - let prefix = format!("type {}", ident); + let prefix = format!("type {}", rewrite_ident(context, ident)); let type_bounds_str = if let Some(bounds) = generic_bounds_opt { if bounds.is_empty() { @@ -1881,8 +1892,13 @@ fn rewrite_fn_base( }; let fd = fn_sig.decl; let g_span = mk_sp(span.lo(), fd.output.span().lo()); - let generics_str = - rewrite_generics(context, &ident.to_string(), fn_sig.generics, shape, g_span)?; + let generics_str = rewrite_generics( + context, + rewrite_ident(context, ident), + fn_sig.generics, + shape, + g_span, + )?; result.push_str(&generics_str); let snuggle_angle_bracket = generics_str @@ -2665,8 +2681,18 @@ fn rewrite_comments_before_after_where( Some((before_comment, after_comment)) } -fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String { - format!("{}{}{}", format_visibility(vis), item_name, ident) +fn format_header( + context: &RewriteContext, + item_name: &str, + ident: ast::Ident, + vis: &ast::Visibility, +) -> String { + format!( + "{}{}{}", + format_visibility(context, vis), + item_name, + rewrite_ident(context, ident) + ) } #[derive(PartialEq, Eq, Clone, Copy)] @@ -2771,15 +2797,24 @@ impl Rewrite for ast::ForeignItem { ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. - let vis = format_visibility(&self.vis); + let vis = format_visibility(context, &self.vis); let mut_str = if is_mutable { "mut " } else { "" }; - let prefix = format!("{}static {}{}:", vis, mut_str, self.ident); + let prefix = format!( + "{}static {}{}:", + vis, + mut_str, + rewrite_ident(context, self.ident) + ); // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } ast::ForeignItemKind::Ty => { - let vis = format_visibility(&self.vis); - Some(format!("{}type {};", vis, self.ident)) + let vis = format_visibility(context, &self.vis); + Some(format!( + "{}type {};", + vis, + rewrite_ident(context, self.ident) + )) } ast::ForeignItemKind::Macro(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) @@ -2803,11 +2838,11 @@ impl Rewrite for ast::ForeignItem { } /// Rewrite an inline mod. -pub fn rewrite_mod(item: &ast::Item) -> String { +pub fn rewrite_mod(context: &RewriteContext, item: &ast::Item) -> String { let mut result = String::with_capacity(32); - result.push_str(&*format_visibility(&item.vis)); + result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); - result.push_str(&item.ident.to_string()); + result.push_str(rewrite_ident(context, item.ident)); result.push(';'); result } diff --git a/src/macros.rs b/src/macros.rs index 512c3ac1c56..e3539d3b699 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -43,7 +43,7 @@ use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; -use utils::{format_visibility, mk_sp, wrap_str}; +use utils::{format_visibility, mk_sp, rewrite_ident, wrap_str}; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -116,10 +116,14 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { } /// Rewrite macro name without using pretty-printer if possible. -fn rewrite_macro_name(path: &ast::Path, extra_ident: Option) -> String { +fn rewrite_macro_name( + context: &RewriteContext, + path: &ast::Path, + extra_ident: Option, +) -> String { let name = if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. - format!("{}!", path.segments[0].ident) + format!("{}!", rewrite_ident(context, path.segments[0].ident)) } else { format!("{}!", path) }; @@ -170,7 +174,7 @@ pub fn rewrite_macro_inner( let original_style = macro_style(mac, context); - let macro_name = rewrite_macro_name(&mac.node.path, extra_ident); + let macro_name = rewrite_macro_name(context, &mac.node.path, extra_ident); let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { DelimToken::Bracket @@ -361,11 +365,11 @@ pub fn rewrite_macro_def( let mut result = if def.legacy { String::from("macro_rules!") } else { - format!("{}macro", format_visibility(vis)) + format!("{}macro", format_visibility(context, vis)) }; result += " "; - result += &ident.name.as_str(); + result += rewrite_ident(context, ident); let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; @@ -1339,7 +1343,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) while parser.token != Token::Eof { // Parse a `lazy_static!` item. - let vis = ::utils::format_visibility(&parse_or!(parse_visibility, false)); + let vis = ::utils::format_visibility(context, &parse_or!(parse_visibility, false)); parser.eat_keyword(symbol::keywords::Static); parser.eat_keyword(symbol::keywords::Ref); let id = parse_or!(parse_ident); diff --git a/src/patterns.rs b/src/patterns.rs index fcab484287c..943434b68ec 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -28,7 +28,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; use types::{rewrite_path, PathContext}; -use utils::{format_mutability, mk_sp}; +use utils::{format_mutability, mk_sp, rewrite_ident}; /// Returns true if the given pattern is short. A short pattern is defined by the following grammer: /// @@ -74,7 +74,7 @@ impl Rewrite for Pat { BindingMode::ByValue(mutability) => ("", mutability), }; let mut_infix = format_mutability(mutability); - let id_str = ident.name.to_string(); + let id_str = rewrite_ident(context, ident); let sub_pat = match *sub_pat { Some(ref p) => { // 3 - ` @ `. @@ -246,7 +246,7 @@ impl Rewrite for FieldPat { pat } else { let pat_str = pat?; - let id_str = self.ident.to_string(); + let id_str = rewrite_ident(context, self.ident); let one_line_width = id_str.len() + 2 + pat_str.len(); if one_line_width <= shape.width { Some(format!("{}: {}", id_str, pat_str)) diff --git a/src/reorder.rs b/src/reorder.rs index 3d2b098781d..9908c402a43 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -100,7 +100,7 @@ fn rewrite_reorderable_item( let item_str = match item.node { ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, - ast::ItemKind::Mod(..) => rewrite_mod(item), + ast::ItemKind::Mod(..) => rewrite_mod(context, item), _ => return None, }; diff --git a/src/types.rs b/src/types.rs index 20c6cebeefd..3608d582d98 100644 --- a/src/types.rs +++ b/src/types.rs @@ -29,7 +29,7 @@ use shape::Shape; use spanned::Spanned; use utils::{ colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_width, - mk_sp, + mk_sp, rewrite_ident, }; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -187,8 +187,10 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(binding) => { let mut result = match context.config.type_punctuation_density() { - TypeDensity::Wide => format!("{} = ", binding.ident), - TypeDensity::Compressed => format!("{}=", binding.ident), + TypeDensity::Wide => format!("{} = ", rewrite_ident(context, binding.ident)), + TypeDensity::Compressed => { + format!("{}=", rewrite_ident(context, binding.ident)) + } }; let budget = shape.width.checked_sub(result.len())?; let rewrite = binding @@ -220,7 +222,7 @@ fn rewrite_segment( shape: Shape, ) -> Option { let mut result = String::with_capacity(128); - result.push_str(&segment.ident.name.as_str()); + result.push_str(rewrite_ident(context, segment.ident)); let ident_len = result.len(); let shape = if context.use_block_indent() { @@ -496,8 +498,8 @@ fn rewrite_bounded_lifetime( } impl Rewrite for ast::Lifetime { - fn rewrite(&self, _: &RewriteContext, _: Shape) -> Option { - Some(self.ident.to_string()) + fn rewrite(&self, context: &RewriteContext, _: Shape) -> Option { + Some(rewrite_ident(context, self.ident).to_owned()) } } @@ -532,7 +534,7 @@ impl Rewrite for ast::GenericParam { Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), _ => (), } - result.push_str(&self.ident.to_string()); + result.push_str(rewrite_ident(context, self.ident)); if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); result.push_str(&self.bounds.rewrite(context, shape)?) diff --git a/src/utils.rs b/src/utils.rs index 127a7ddb59e..a8f8592d2f2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -24,6 +24,10 @@ use shape::Shape; pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; +pub fn rewrite_ident<'a>(context: &'a RewriteContext, ident: ast::Ident) -> &'a str { + context.snippet(ident.span) +} + // Computes the length of a string's last line, minus offset. pub fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { @@ -34,7 +38,7 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize { } // Uses Cow to avoid allocating in the common cases. -pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { +pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'static, str> { match vis.node { VisibilityKind::Public => Cow::from("pub "), VisibilityKind::Inherited => Cow::from(""), @@ -42,7 +46,7 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> { VisibilityKind::Crate(CrateSugar::JustCrate) => Cow::from("crate "), VisibilityKind::Restricted { ref path, .. } => { let Path { ref segments, .. } = **path; - let mut segments_iter = segments.iter().map(|seg| seg.ident.name.to_string()); + let mut segments_iter = segments.iter().map(|seg| rewrite_ident(context, seg.ident)); if path.is_global() { segments_iter .next() diff --git a/src/vertical.rs b/src/vertical.rs index a8a8ee6cec3..58422d782ac 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -24,7 +24,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separat use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use spanned::Spanned; -use utils::{contains_skip, is_attributes_extendable, mk_sp}; +use utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; pub trait AlignedItem { fn skip(&self) -> bool; @@ -88,7 +88,7 @@ impl AlignedItem for ast::Field { fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; - let name = &self.ident.name.to_string(); + let name = rewrite_ident(context, self.ident); let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) } else { diff --git a/src/visitor.rs b/src/visitor.rs index c58122025de..76fd3395ba9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -28,7 +28,7 @@ use shape::{Indent, Shape}; use spanned::Spanned; use utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, - DEPR_SKIP_ANNOTATION, + rewrite_ident, DEPR_SKIP_ANNOTATION, }; use {ErrorKind, FormatReport, FormattingError}; @@ -682,9 +682,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { attrs: &[ast::Attribute], is_internal: bool, ) { - self.push_str(&*utils::format_visibility(vis)); + let vis_str = utils::format_visibility(&self.get_context(), vis); + self.push_str(&*vis_str); self.push_str("mod "); - self.push_str(&ident.to_string()); + // Calling `to_owned()` to work around borrow checker. + let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); + self.push_str(&ident_str); if is_internal { match self.config.brace_style() { -- cgit 1.4.1-3-g733a5 From be4d37da4bf37835a2432abe9b7be664c09b8676 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 25 Jun 2018 12:16:17 +1200 Subject: Indent a match guard if the pattern is multiline Closes #2377 --- src/matches.rs | 19 ++++++++++++++----- tests/source/match.rs | 16 ++++++++++++++++ tests/target/match.rs | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index d46b19be723..87bce7fab04 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -289,7 +289,13 @@ fn rewrite_match_pattern( let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?; // Guard - let guard_str = rewrite_guard(context, guard, shape, trimmed_last_line_width(&pats_str))?; + let guard_str = rewrite_guard( + context, + guard, + shape, + trimmed_last_line_width(&pats_str), + pats_str.contains("\n"), + )?; Some(format!("{}{}", pats_str, guard_str)) } @@ -450,6 +456,7 @@ fn rewrite_guard( // The amount of space used up on this line for the pattern in // the arm (excludes offset). pattern_width: usize, + multiline_pattern: bool, ) -> Option { if let Some(ref guard) = *guard { // First try to fit the guard string on the same line as the pattern. @@ -457,10 +464,12 @@ fn rewrite_guard( let cond_shape = shape .offset_left(pattern_width + 4) .and_then(|s| s.sub_width(5)); - if let Some(cond_shape) = cond_shape { - if let Some(cond_str) = guard.rewrite(context, cond_shape) { - if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { - return Some(format!(" if {}", cond_str)); + if !multiline_pattern { + if let Some(cond_shape) = cond_shape { + if let Some(cond_str) = guard.rewrite(context, cond_shape) { + if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() { + return Some(format!(" if {}", cond_str)); + } } } } diff --git a/tests/source/match.rs b/tests/source/match.rs index 244d0b45f25..8ff7afb7a44 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -491,3 +491,19 @@ fn issue_2621() { | Foo::I => println!("With comment"), // Comment after line } } + +fn issue_2377() { + match tok { + Tok::Not + | Tok::BNot + | Tok::Plus + | Tok::Minus + | Tok::PlusPlus + | Tok::MinusMinus + | Tok::Void + | Tok::Delete if prec <= 16 => { + // code here... + } + Tok::TypeOf if prec <= 16 => {} + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index be1ecb49535..cda0ed2abe5 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -518,3 +518,21 @@ fn issue_2621() { Foo::I => println!("With comment"), // Comment after line } } + +fn issue_2377() { + match tok { + Tok::Not + | Tok::BNot + | Tok::Plus + | Tok::Minus + | Tok::PlusPlus + | Tok::MinusMinus + | Tok::Void + | Tok::Delete + if prec <= 16 => + { + // code here... + } + Tok::TypeOf if prec <= 16 => {} + } +} -- cgit 1.4.1-3-g733a5 From 42f03458dd8f55d86d7f462ff3acbaff1dfddc7b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 26 Jun 2018 14:58:51 +1200 Subject: Refactor and fixup attribute formatting Preserves trailing commas (except in derives where we follow function args). Correctly uses `#` vs `#!` for derives. Uses block indent for derives, fixes #2805. --- src/attr.rs | 416 +++++++++++++++++++++++++++++++------------------ src/lists.rs | 4 +- src/shape.rs | 1 + tests/source/attrib.rs | 8 +- tests/target/attrib.rs | 26 +++- 5 files changed, 296 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index efbd4872aae..6aa62f40db2 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,12 +10,9 @@ //! Format attributes and meta items. +use comment::{contains_comment, rewrite_doc_comment}; use config::lists::*; use config::IndentStyle; -use syntax::ast; -use syntax::codemap::Span; - -use comment::{combine_strs_with_missing_comments, contains_comment, rewrite_doc_comment}; use expr::rewrite_literal; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; @@ -23,6 +20,10 @@ use shape::Shape; use types::{rewrite_path, PathContext}; use utils::{count_newlines, mk_sp}; +use std::borrow::Cow; +use syntax::ast; +use syntax::codemap::{BytePos, Span, DUMMY_SP}; + /// Returns attributes on the given statement. pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { match stmt.node { @@ -47,42 +48,62 @@ fn is_derive(attr: &ast::Attribute) -> bool { } /// Returns the arguments of `#[derive(...)]`. -fn get_derive_args<'a>(context: &'a RewriteContext, attr: &ast::Attribute) -> Option> { +fn get_derive_spans<'a>(attr: &ast::Attribute) -> Option> { attr.meta_item_list().map(|meta_item_list| { meta_item_list .iter() - .map(|nested_meta_item| context.snippet(nested_meta_item.span)) + .map(|nested_meta_item| nested_meta_item.span) .collect() }) } -// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. -fn format_derive(context: &RewriteContext, derive_args: &[&str], shape: Shape) -> Option { +// The shape of the arguments to a function-like attribute. +fn argument_shape( + left: usize, + right: usize, + shape: Shape, + context: &RewriteContext, +) -> Option { + match context.config.indent_style() { + IndentStyle::Block => Some( + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), + ), + IndentStyle::Visual => shape + .visual_indent(0) + .shrink_left(left) + .and_then(|s| s.sub_width(right)), + } +} + +fn format_derive( + derive_args: &[Span], + prefix: &str, + shape: Shape, + context: &RewriteContext, +) -> Option { let mut result = String::with_capacity(128); - result.push_str("#[derive("); - // 11 = `#[derive()]` - let initial_budget = shape.width.checked_sub(11)?; - let mut budget = initial_budget; - let num = derive_args.len(); - for (i, a) in derive_args.iter().enumerate() { - // 2 = `, ` or `)]` - let width = a.len() + 2; - if width > budget { - if i > 0 { - // Remove trailing whitespace. - result.pop(); - } - result.push('\n'); - // 9 = `#[derive(` - result.push_str(&(shape.indent + 9).to_string(context.config)); - budget = initial_budget; - } else { - budget = budget.saturating_sub(width); - } - result.push_str(a); - if i != num - 1 { - result.push_str(", ") - } + result.push_str(prefix); + result.push_str("[derive("); + + let argument_shape = argument_shape(10 + prefix.len(), 2, shape, context)?; + let item_str = format_arg_list( + derive_args.iter(), + |_| DUMMY_SP.lo(), + |_| DUMMY_SP.hi(), + |sp| Some(context.snippet(**sp).to_owned()), + DUMMY_SP, + context, + argument_shape, + // 10 = "[derive()]", 3 = "()" and "]" + shape.offset_left(10 + prefix.len())?.sub_width(3)?, + )?; + + result.push_str(&item_str); + if item_str.starts_with('\n') { + result.push(','); + result.push_str(&shape.indent.to_string_with_newline(context.config)); } result.push_str(")]"); Some(result) @@ -120,15 +141,14 @@ where &attrs[..len] } -/// Rewrite the same kind of attributes at the same time. This includes doc -/// comments and derives. -fn rewrite_first_group_attrs( +/// Rewrite the any doc comments which come before any other attributes. +fn rewrite_initial_doc_comments( context: &RewriteContext, attrs: &[ast::Attribute], shape: Shape, -) -> Option<(usize, String)> { +) -> Option<(usize, Option)> { if attrs.is_empty() { - return Some((0, String::new())); + return Some((0, None)); } // Rewrite doc comments let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); @@ -140,22 +160,15 @@ fn rewrite_first_group_attrs( .join("\n"); return Some(( sugared_docs.len(), - rewrite_doc_comment(&snippet, shape.comment(context.config), context.config)?, + Some(rewrite_doc_comment( + &snippet, + shape.comment(context.config), + context.config, + )?), )); } - // Rewrite `#[derive(..)]`s. - if context.config.merge_derives() { - let derives = take_while_with_pred(context, attrs, is_derive); - if !derives.is_empty() { - let mut derive_args = vec![]; - for derive in derives { - derive_args.append(&mut get_derive_args(context, derive)?); - } - return Some((derives.len(), format_derive(context, &derive_args, shape)?)); - } - } - // Rewrite the first attribute. - Some((1, attrs[0].rewrite(context, shape)?)) + + Some((0, None)) } impl Rewrite for ast::NestedMetaItem { @@ -185,19 +198,6 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) } -fn allow_mixed_tactic_for_nested_metaitem_list(list: &[ast::NestedMetaItem]) -> bool { - list.iter().all(|nested_metaitem| { - if let ast::NestedMetaItemKind::MetaItem(ref inner_metaitem) = nested_metaitem.node { - match inner_metaitem.node { - ast::MetaItemKind::List(..) | ast::MetaItemKind::NameValue(..) => false, - _ => true, - } - } else { - true - } - }) -} - impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { Some(match self.node { @@ -206,62 +206,36 @@ impl Rewrite for ast::MetaItem { } ast::MetaItemKind::List(ref list) => { let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; - let item_shape = match context.config.indent_style() { - IndentStyle::Block => shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), - // 1 = `(`, 2 = `]` and `)` - IndentStyle::Visual => shape - .visual_indent(0) - .shrink_left(path.len() + 1) - .and_then(|s| s.sub_width(2))?, - }; - let items = itemize_list( - context.snippet_provider, + + let snippet = context.snippet(self.span); + // 2 = )] (this might go wrong if there is whitespace between the brackets, but + // it's close enough). + let snippet = snippet[..snippet.len() - 2].trim(); + let trailing_comma = if snippet.ends_with(',') { "," } else { "" }; + + let argument_shape = + argument_shape(path.len() + 1, 2 + trailing_comma.len(), shape, context)?; + let item_str = format_arg_list( list.iter(), - ")", - ",", |nested_meta_item| nested_meta_item.span.lo(), |nested_meta_item| nested_meta_item.span.hi(), - |nested_meta_item| nested_meta_item.rewrite(context, item_shape), - self.span.lo(), - self.span.hi(), - false, - ); - let item_vec = items.collect::>(); - let tactic = if allow_mixed_tactic_for_nested_metaitem_list(list) { - DefinitiveListTactic::Mixed + |nested_meta_item| nested_meta_item.rewrite(context, argument_shape), + self.span, + context, + argument_shape, + // 3 = "()" and "]" + shape + .offset_left(path.len())? + .sub_width(3 + trailing_comma.len())?, + )?; + + let indent = if item_str.starts_with('\n') { + shape.indent.to_string_with_newline(context.config) } else { - ::lists::definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - ::lists::Separator::Comma, - item_shape.width, - ) + Cow::Borrowed("") }; - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: item_shape, - ends_with_newline: false, - preserve_newline: false, - nested: false, - config: context.config, - }; - let item_str = write_list(&item_vec, &fmt)?; - // 3 = "()" and "]" - let one_line_budget = shape.offset_left(path.len())?.sub_width(3)?.width; - if context.config.indent_style() == IndentStyle::Visual - || (!item_str.contains('\n') && item_str.len() <= one_line_budget) - { - format!("{}({})", path, item_str) - } else { - let indent = shape.indent.to_string_with_newline(context.config); - let nested_indent = item_shape.indent.to_string_with_newline(context.config); - format!("{}({}{}{})", path, nested_indent, item_str, indent) - } + + format!("{}({}{}{})", path, item_str, trailing_comma, indent) } ast::MetaItemKind::NameValue(ref literal) => { let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; @@ -281,16 +255,73 @@ impl Rewrite for ast::MetaItem { } } +fn format_arg_list( + list: I, + get_lo: F1, + get_hi: F2, + get_item_string: F3, + span: Span, + context: &RewriteContext, + shape: Shape, + one_line_shape: Shape, +) -> Option +where + I: Iterator, + F1: Fn(&T) -> BytePos, + F2: Fn(&T) -> BytePos, + F3: Fn(&T) -> Option, +{ + let items = itemize_list( + context.snippet_provider, + list, + ")", + ",", + get_lo, + get_hi, + get_item_string, + span.lo(), + span.hi(), + false, + ); + let item_vec = items.collect::>(); + let tactic = ::lists::definitive_tactic( + &item_vec, + ListTactic::HorizontalVertical, + ::lists::Separator::Comma, + shape.width, + ); + let fmt = ListFormatting { + tactic, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: false, + preserve_newline: false, + nested: false, + config: context.config, + }; + let item_str = write_list(&item_vec, &fmt)?; + + let one_line_budget = one_line_shape.width; + if context.config.indent_style() == IndentStyle::Visual + || (!item_str.contains('\n') && item_str.len() <= one_line_budget) + { + Some(item_str) + } else { + let nested_indent = shape.indent.to_string_with_newline(context.config); + Some(format!("{}{}", nested_indent, item_str)) + } +} + impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let prefix = match self.style { - ast::AttrStyle::Inner => "#!", - ast::AttrStyle::Outer => "#", - }; let snippet = context.snippet(self.span); if self.is_sugared_doc { rewrite_doc_comment(snippet, shape.comment(context.config), context.config) } else { + let prefix = attr_prefix(self); + if contains_comment(snippet) { return Some(snippet.to_owned()); } @@ -310,47 +341,126 @@ impl<'a> Rewrite for [ast::Attribute] { if self.is_empty() { return Some(String::new()); } - let (first_group_len, first_group_str) = rewrite_first_group_attrs(context, self, shape)?; - if self.len() == 1 || first_group_len == self.len() { - Some(first_group_str) - } else { - let rest_str = self[first_group_len..].rewrite(context, shape)?; - let missing_span = mk_sp( - self[first_group_len - 1].span.hi(), - self[first_group_len].span.lo(), - ); - // Preserve an empty line before/after doc comments. - if self[0].is_sugared_doc || self[first_group_len].is_sugared_doc { - let snippet = context.snippet(missing_span); - let (mla, mlb) = has_newlines_before_after_comment(snippet); + + // The current remaining attributes. + let mut attrs = self; + let mut result = String::new(); + + // This is not just a simple map because we need to handle doc comments + // (where we take as many doc comment attributes as possible) and possibly + // merging derives into a single attribute. + loop { + if attrs.is_empty() { + return Some(result); + } + + // Handle doc comments. + let (doc_comment_len, doc_comment_str) = + rewrite_initial_doc_comments(context, attrs, shape)?; + if doc_comment_len > 0 { + let doc_comment_str = doc_comment_str.expect("doc comments, but no result"); + result.push_str(&doc_comment_str); + + let missing_span = attrs + .get(doc_comment_len) + .map(|next| mk_sp(attrs[doc_comment_len - 1].span.hi(), next.span.lo())); + if let Some(missing_span) = missing_span { + let snippet = context.snippet(missing_span); + let (mla, mlb) = has_newlines_before_after_comment(snippet); + let comment = ::comment::recover_missing_comment_in_span( + missing_span, + shape.with_max_width(context.config), + context, + 0, + )?; + let comment = if comment.is_empty() { + format!("\n{}", mlb) + } else { + format!("{}{}\n{}", mla, comment, mlb) + }; + result.push_str(&comment); + result.push_str(&shape.indent.to_string(context.config)); + } + + attrs = &attrs[doc_comment_len..]; + + continue; + } + + // Handle derives if we will merge them. + if context.config.merge_derives() && is_derive(&attrs[0]) { + let derives = take_while_with_pred(context, attrs, is_derive); + let mut derive_spans = vec![]; + for derive in derives { + derive_spans.append(&mut get_derive_spans(derive)?); + } + let derive_str = + format_derive(&derive_spans, attr_prefix(&attrs[0]), shape, context)?; + result.push_str(&derive_str); + + let missing_span = attrs + .get(derives.len()) + .map(|next| mk_sp(attrs[derives.len() - 1].span.hi(), next.span.lo())); + if let Some(missing_span) = missing_span { + let comment = ::comment::recover_missing_comment_in_span( + missing_span, + shape.with_max_width(context.config), + context, + 0, + )?; + result.push_str(&comment); + if let Some(next) = attrs.get(derives.len()) { + if next.is_sugared_doc { + let snippet = context.snippet(missing_span); + let (_, mlb) = has_newlines_before_after_comment(snippet); + result.push_str(&mlb); + } + } + result.push('\n'); + result.push_str(&shape.indent.to_string(context.config)); + } + + attrs = &attrs[derives.len()..]; + + continue; + } + + // If we get here, then we have a regular attribute, just handle one + // at a time. + + let formatted_attr = attrs[0].rewrite(context, shape)?; + result.push_str(&formatted_attr); + + let missing_span = attrs + .get(1) + .map(|next| mk_sp(attrs[0].span.hi(), next.span.lo())); + if let Some(missing_span) = missing_span { let comment = ::comment::recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, 0, )?; - let comment = if comment.is_empty() { - format!("\n{}", mlb) - } else { - format!("{}{}\n{}", mla, comment, mlb) - }; - Some(format!( - "{}{}{}{}", - first_group_str, - comment, - shape.indent.to_string(context.config), - rest_str - )) - } else { - combine_strs_with_missing_comments( - context, - &first_group_str, - &rest_str, - missing_span, - shape, - false, - ) + result.push_str(&comment); + if let Some(next) = attrs.get(1) { + if next.is_sugared_doc { + let snippet = context.snippet(missing_span); + let (_, mlb) = has_newlines_before_after_comment(snippet); + result.push_str(&mlb); + } + } + result.push('\n'); + result.push_str(&shape.indent.to_string(context.config)); } + + attrs = &attrs[1..]; } } } + +fn attr_prefix(attr: &ast::Attribute) -> &'static str { + match attr.style { + ast::AttrStyle::Inner => "#!", + ast::AttrStyle::Outer => "#", + } +} diff --git a/src/lists.rs b/src/lists.rs index 3b49a27ccef..d0ac21d4bba 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -533,7 +533,7 @@ where let pre_snippet = self .snippet_provider .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) - .unwrap(); + .unwrap_or(""); let trimmed_pre_snippet = pre_snippet.trim(); let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); let has_block_comment = trimmed_pre_snippet.starts_with("/*"); @@ -572,7 +572,7 @@ where let post_snippet = self .snippet_provider .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) - .unwrap(); + .unwrap_or(""); let comment_end = match self.inner.peek() { Some(..) => { diff --git a/src/shape.rs b/src/shape.rs index 6cf0e8ea890..ab33826c028 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -27,6 +27,7 @@ pub struct Indent { const INDENT_BUFFER_LEN: usize = 80; const INDENT_BUFFER: &str = "\n "; + impl Indent { pub fn new(block_indent: usize, alignment: usize) -> Indent { Indent { diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 409e5f5a4a9..2408b8b748f 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -151,7 +151,13 @@ fn attributes_on_statements() { foo!(); } -// Large derive +// Large derives +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Mul)] + + +/// Foo bar baz + + #[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] pub struct HP(pub u8); diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index b0b8ea89f82..e93bd405e5a 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -155,9 +155,29 @@ fn attributes_on_statements() { foo!(); } -// Large derive -#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, - Deserialize)] +// Large derives +#[derive( + Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Mul, +)] + +/// Foo bar baz + +#[derive( + Add, + Sub, + Mul, + Div, + Clone, + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, + Debug, + Hash, + Serialize, + Deserialize, +)] pub struct HP(pub u8); // Long `#[doc = "..."]` -- cgit 1.4.1-3-g733a5 From 3abebf95cea12e396ed536cb9e29ef8dd1a6c6c1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 26 Jun 2018 15:15:29 +1200 Subject: Apply short function call heuristic to attributes Closes #2620 --- src/attr.rs | 17 +++++++++++------ tests/source/attrib.rs | 19 +++++++++++++++++++ tests/target/attrib.rs | 29 ++++++++++++++++++++++++++++- tests/target/enum.rs | 7 ++++++- tests/target/struct-field-attributes.rs | 10 ++++++++-- 5 files changed, 72 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 6aa62f40db2..3c545bdda70 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -98,6 +98,7 @@ fn format_derive( argument_shape, // 10 = "[derive()]", 3 = "()" and "]" shape.offset_left(10 + prefix.len())?.sub_width(3)?, + None, )?; result.push_str(&item_str); @@ -227,6 +228,7 @@ impl Rewrite for ast::MetaItem { shape .offset_left(path.len())? .sub_width(3 + trailing_comma.len())?, + Some(context.config.width_heuristics().fn_call_width), )?; let indent = if item_str.starts_with('\n') { @@ -264,6 +266,7 @@ fn format_arg_list( context: &RewriteContext, shape: Shape, one_line_shape: Shape, + one_line_limit: Option, ) -> Option where I: Iterator, @@ -284,12 +287,14 @@ where false, ); let item_vec = items.collect::>(); - let tactic = ::lists::definitive_tactic( - &item_vec, - ListTactic::HorizontalVertical, - ::lists::Separator::Comma, - shape.width, - ); + let tactic = if let Some(limit) = one_line_limit { + ListTactic::LimitedHorizontalVertical(limit) + } else { + ListTactic::HorizontalVertical + }; + + let tactic = + ::lists::definitive_tactic(&item_vec, tactic, ::lists::Separator::Comma, shape.width); let fmt = ListFormatting { tactic, separator: ",", diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 2408b8b748f..708147f0e6f 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -174,3 +174,22 @@ pub fn foo() {} #[clippy::bar(a, b, c)] pub fn foo() {} +mod issue_2620 { + #[derive(Debug, StructOpt)] +#[structopt(about = "Display information about the character on FF Logs")] +pub struct Params { + #[structopt(help = "The server the character is on")] + server: String, + #[structopt(help = "The character's first name")] + first_name: String, + #[structopt(help = "The character's last name")] + last_name: String, + #[structopt( + short = "j", + long = "job", + help = "The job to look at", + parse(try_from_str) + )] + job: Option +} +} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index e93bd405e5a..1e069458ea1 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -76,7 +76,14 @@ struct Foo { // #1668 /// Default path (*nix) -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))] +#[cfg( + all( + unix, + not(target_os = "macos"), + not(target_os = "ios"), + not(target_os = "android") + ) +)] fn foo() { #[cfg(target_os = "freertos")] match port_id { @@ -197,3 +204,23 @@ pub fn foo() {} #[clippy::bar=foo] #[clippy::bar(a, b, c)] pub fn foo() {} + +mod issue_2620 { + #[derive(Debug, StructOpt)] + #[structopt(about = "Display information about the character on FF Logs")] + pub struct Params { + #[structopt(help = "The server the character is on")] + server: String, + #[structopt(help = "The character's first name")] + first_name: String, + #[structopt(help = "The character's last name")] + last_name: String, + #[structopt( + short = "j", + long = "job", + help = "The job to look at", + parse(try_from_str) + )] + job: Option, + } +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index b19b6997826..33eb211a4b5 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -255,7 +255,12 @@ pub enum QlError { #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), // (kind, input, expected) - #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] + #[fail( + display = "Could not find {}: Found: {}, expected: {:?}", + 0, + 1, + 2 + )] ResolveError(&'static str, String, Option), } diff --git a/tests/target/struct-field-attributes.rs b/tests/target/struct-field-attributes.rs index 5d6e92a91d9..0f461b98bc7 100644 --- a/tests/target/struct-field-attributes.rs +++ b/tests/target/struct-field-attributes.rs @@ -39,13 +39,19 @@ fn new_foo() -> Foo { // #2044 pub enum State { Closure( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::serialization::closure"))] + #[cfg_attr( + feature = "serde_derive", + serde(state_with = "::serialization::closure") + )] GcPtr, ), } struct Fields( - #[cfg_attr(feature = "serde_derive", serde(state_with = "::base::serialization::shared"))] + #[cfg_attr( + feature = "serde_derive", + serde(state_with = "::base::serialization::shared") + )] Arc>, ); -- cgit 1.4.1-3-g733a5 From cc2afeca9eda9d85c088479335c3c664d449a7f4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 28 Jun 2018 16:26:10 +0900 Subject: Fix compile errors from breaking changes --- src/closures.rs | 3 ++- src/expr.rs | 4 +++- src/items.rs | 14 +++++++------- src/visitor.rs | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 257b8729f45..5f1102a36fc 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -31,6 +31,7 @@ use utils::{last_line_width, left_most_sub_expr, stmt_expr}; // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. +// FIXME(topecongiro) Format async closures (#2813). pub fn rewrite_closure( capture: ast::CaptureBy, movability: ast::Movability, @@ -288,7 +289,7 @@ pub fn rewrite_last_closure( expr: &ast::Expr, shape: Shape, ) -> Option { - if let ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) = expr.node { + if let ast::ExprKind::Closure(capture, _, movability, ref fn_decl, ref body, _) = expr.node { let body = match body.node { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) diff --git a/src/expr.rs b/src/expr.rs index b8a323f73a2..ca31b0b82ef 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -183,7 +183,7 @@ pub fn format_expr( } else { Some("yield".to_string()) }, - ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { + ast::ExprKind::Closure(capture, _, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( capture, movability, fn_decl, body, expr.span, context, shape, ) @@ -344,6 +344,8 @@ pub fn format_expr( } // FIXME(#2743) ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), + // FIXME(topecongiro) Format async block. + ast::ExprKind::Async(..) => None, }; expr_rw diff --git a/src/items.rs b/src/items.rs index bef8fd79599..fe638a17069 100644 --- a/src/items.rs +++ b/src/items.rs @@ -192,10 +192,10 @@ impl<'a> FnSig<'a> { generics: &'a ast::Generics, ) -> FnSig<'a> { FnSig { - unsafety: method_sig.unsafety, - constness: method_sig.constness.node, + unsafety: method_sig.header.unsafety, + constness: method_sig.header.constness.node, defaultness: ast::Defaultness::Final, - abi: method_sig.abi, + abi: method_sig.header.abi, decl: &*method_sig.decl, generics, visibility: DEFAULT_VISIBILITY, @@ -209,13 +209,13 @@ impl<'a> FnSig<'a> { defaultness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { - visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig { + visit::FnKind::ItemFn(_, fn_header, visibility, _) => FnSig { decl, generics, - abi, - constness: constness.node, + abi: fn_header.abi, + constness: fn_header.constness.node, defaultness, - unsafety, + unsafety: fn_header.unsafety, visibility: visibility.clone(), }, visit::FnKind::Method(_, method_sig, vis, _) => { diff --git a/src/visitor.rs b/src/visitor.rs index 76fd3395ba9..2b0f08dd0c7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -252,6 +252,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. + // FIXME(topecongiro) Format async fn (#2812). fn visit_fn( &mut self, fk: visit::FnKind, @@ -264,7 +265,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let indent = self.block_indent; let block; let rewrite = match fk { - visit::FnKind::ItemFn(ident, _, _, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { + visit::FnKind::ItemFn(ident, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { block = b; self.rewrite_fn( indent, @@ -392,10 +393,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { + ast::ItemKind::Fn(ref decl, fn_header, ref generics, ref body) => { let inner_attrs = inner_attributes(&item.attrs); self.visit_fn( - visit::FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), + visit::FnKind::ItemFn(item.ident, fn_header, &item.vis, body), generics, decl, item.span, -- cgit 1.4.1-3-g733a5 From bc16d8864adc9303463679d7dddca5f3bffb5bbe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 30 Jun 2018 15:53:28 +0900 Subject: Fix compile error from breaking changes in libsyntax --- src/patterns.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 943434b68ec..85b9b84b6b2 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -99,7 +99,7 @@ impl Rewrite for Pat { } } PatKind::Range(ref lhs, ref rhs, ref end_kind) => { - let infix = match *end_kind { + let infix = match end_kind.node { RangeEnd::Included(RangeSyntax::DotDotDot) => "...", RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", RangeEnd::Excluded => "..", -- cgit 1.4.1-3-g733a5 From 57a6cae49f7f97d470511c48fe83c93fa99c14df Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 30 Jun 2018 19:21:15 +0900 Subject: Fix span bug when searching for the closing paren --- src/items.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index fe638a17069..84a24e7149e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1330,13 +1330,10 @@ fn format_tuple_struct( } else { // This is a dirty hack to work around a missing `)` from the span of the last field. let last_arg_span = fields[fields.len() - 1].span; - if context.snippet(last_arg_span).ends_with(')') { - last_arg_span.hi() - } else { - context - .snippet_provider - .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") - } + context + .snippet_provider + .opt_span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") + .unwrap_or(last_arg_span.hi()) }; let where_clause_str = match struct_parts.generics { -- cgit 1.4.1-3-g733a5 From f7a25a1177c86541071932a9e578819c7ae33d5a Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 30 Jun 2018 17:03:18 +0200 Subject: warn on use of default value for an option --- Contributing.md | 2 +- src/config/config_type.rs | 11 +++++++++++ src/config/file_lines.rs | 2 +- src/config/options.rs | 4 ++-- src/test/mod.rs | 3 +++ 5 files changed, 18 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/Contributing.md b/Contributing.md index 527041ab737..9478bc89f3b 100644 --- a/Contributing.md +++ b/Contributing.md @@ -205,7 +205,7 @@ and `ListFormatting` the key structure for configuration. You'll need to make a Rustfmt strives to be highly configurable. Often the first part of a patch is creating a configuration option for the feature you are implementing. All -handling of configuration options is done in [src/config.rs](src/config.rs). Look for the +handling of configuration options is done in [src/config/mod.rs](src/config/mod.rs). Look for the `create_config!` macro at the end of the file for all the options. The rest of the file defines a bunch of enums used for options, and the machinery to produce the config struct and parse a config file, etc. Checking an option is done by diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 57a02fb531b..ddb063feeab 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -281,6 +281,7 @@ macro_rules! create_config { match key { $( stringify!($i) => { + self.$i.1 = true; self.$i.2 = val.parse::<$ty>() .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", stringify!($i), @@ -421,6 +422,16 @@ macro_rules! create_config { fn set_ignore(&mut self, dir: &Path) { self.ignore.2.add_prefix(dir); } + + /// Returns true if the config key was explicitely set and is the default value. + pub fn is_default(&self, key: &str) -> bool { + $( + if let stringify!($i) = key { + return self.$i.1 && self.$i.2 == $def; + } + )+ + false + } } // Template for the default configuration diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index d776dbb6a79..436c7a83b81 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -126,7 +126,7 @@ impl Range { /// It is represented as a multimap keyed on file names, with values a collection of /// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all /// lines in all files. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct FileLines(Option>>); /// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, diff --git a/src/config/options.rs b/src/config/options.rs index 5f781507d90..b3599c230f4 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -223,7 +223,7 @@ configuration_option_enum! { Verbosity: Quiet, } -#[derive(Deserialize, Serialize, Clone, Debug)] +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct WidthHeuristics { // Maximum width of the args of a function call before falling back // to vertical formatting. @@ -293,7 +293,7 @@ impl Default for EmitMode { } /// A set of directories, files and modules that rustfmt should ignore. -#[derive(Default, Deserialize, Serialize, Clone, Debug)] +#[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct IgnoreList(HashSet); impl IgnoreList { diff --git a/src/test/mod.rs b/src/test/mod.rs index fdbe1e6856e..233055a067e 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -363,6 +363,9 @@ fn read_config(filename: &Path) -> Config { for (key, val) in &sig_comments { if key != "target" && key != "config" { config.override_value(key, val); + if config.is_default(key) { + warn!("Default value {} used explicitly for {}", val, key); + } } } -- cgit 1.4.1-3-g733a5 From 5a3640da699ac243d601683802899d897b364e60 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 1 Jul 2018 09:59:53 +0900 Subject: Return the trimmed original snippet when formatting macro def failed --- src/macros.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index e3539d3b699..8468dbf1591 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -411,7 +411,10 @@ pub fn rewrite_macro_def( result += &arm_shape.indent.to_string_with_newline(context.config); } - result += write_list(&branch_items, &fmt)?.as_str(); + match write_list(&branch_items, &fmt) { + Some(ref s) => result += s, + None => return snippet, + } if multi_branch_style { result += &indent.to_string_with_newline(context.config); -- cgit 1.4.1-3-g733a5 From e7c6c295620d64db44a1a76235095364af57c96a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 1 Jul 2018 10:46:32 +0900 Subject: Avoid panicking on deeply nested expressions --- src/overflow.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index f91ef38e2ee..8fccf3da735 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -511,21 +511,18 @@ fn shape_from_indent_style( overhead: usize, offset: usize, ) -> Shape { - if context.use_block_indent() { - // 1 = "," - shape + let (shape, overhead) = if context.use_block_indent() { + let shape = shape .block() .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) - .sub_width(1) - .unwrap() + .with_max_width(context.config); + (shape, 1) // 1 = "," } else { - let shape = shape.visual_indent(offset); - if let Some(shape) = shape.sub_width(overhead) { - shape - } else { - Shape { width: 0, ..shape } - } + (shape.visual_indent(offset), overhead) + }; + Shape { + width: shape.width.saturating_sub(overhead), + ..shape } } -- cgit 1.4.1-3-g733a5 From 54af8b578e2d039a64abec9fae817c66973b44bd Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 1 Jul 2018 10:49:05 +0900 Subject: Factor out block_can_be_flattened --- src/matches.rs | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 87bce7fab04..b01dc69a528 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -300,28 +300,38 @@ fn rewrite_match_pattern( Some(format!("{}{}", pats_str, guard_str)) } +fn block_can_be_flattened<'a>( + context: &RewriteContext, + expr: &'a ast::Expr, +) -> Option<&'a ast::Block> { + match expr.node { + ast::ExprKind::Block(ref block, _) + if !is_unsafe_block(block) + && is_simple_block(block, Some(&expr.attrs), context.codemap) => + { + Some(&*block) + } + _ => None, + } +} + // (extend, body) // @extend: true if the arm body can be put next to `=>` // @body: flattened body, if the body is block with a single expression fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { - match body.node { - ast::ExprKind::Block(ref block, _) - if !is_unsafe_block(block) - && is_simple_block(block, Some(&body.attrs), context.codemap) => - { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - ( - !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr), - &*expr, - ) - } else { - (false, &*body) - } + if let Some(ref block) = block_can_be_flattened(context, body) { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { + let can_extend_expr = + !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); + (can_extend_expr, &*expr) + } else { + (false, &*body) } - _ => ( + } else { + ( !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), &*body, - ), + ) } } -- cgit 1.4.1-3-g733a5 From ebb162626419fa01c6b885ca74be6d29d22d5b0d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 1 Jul 2018 10:51:36 +0900 Subject: Flatten multiple empty blocks at once --- src/matches.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index b01dc69a528..201e10d5ccf 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -321,9 +321,13 @@ fn block_can_be_flattened<'a>( fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { if let Some(ref block) = block_can_be_flattened(context, body) { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - let can_extend_expr = - !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); - (can_extend_expr, &*expr) + if let ast::ExprKind::Block(..) = expr.node { + flatten_arm_body(context, expr) + } else { + let can_extend_expr = + !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); + (can_extend_expr, &*expr) + } } else { (false, &*body) } -- cgit 1.4.1-3-g733a5 From 5e5992517d3591e2708d4ca6b155dfcbdf3344b9 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 2 Jul 2018 09:34:55 +1200 Subject: Update rustc-ap-syntax --- Cargo.lock | 68 ++++++++++++++++++++++++++++++------------------------------ Cargo.toml | 4 ++-- src/types.rs | 2 +- 3 files changed, 37 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 4d7bfb139aa..6ff790bf82d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -425,15 +425,15 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -442,7 +442,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -450,8 +450,8 @@ dependencies = [ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -460,57 +460,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "181.0.0" +version = "182.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -565,8 +565,8 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.68 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -851,14 +851,14 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13c93d55961981ba9226a213b385216f83ab43bd6ac53ab16b2eeb47e337cf4e" "checksum regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05b06a75f5217880fc5e905952a42750bf44787e56a6c6d6852ed0992f5e1d54" -"checksum rustc-ap-arena 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c53ec4752168e9baf464e6474f934093d6e2b49823c00a083eccb4bfc0c80031" -"checksum rustc-ap-rustc_cratesio_shim 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02a6fac389bf133f43e17254a4126f5366186f02a11c55b08a2a08832ca6170e" -"checksum rustc-ap-rustc_data_structures 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d791dbc2bd409fa402e7b4794f2832d1d68bd52c55b7416ad012a59448c7cc8f" -"checksum rustc-ap-rustc_errors 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a8991eba194a3b87ea1d662cdbbe1df9d647a4e72b8e803771d8277c1358b03" -"checksum rustc-ap-rustc_target 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e73f48d6067a07e1fb8ad2038ac2bf01e9a2a3d4ddfcd9001140fddbdf46e37d" -"checksum rustc-ap-serialize 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efe00d380caaaa7b4cef96b74db152355785a30ccb2147a63c538867b73332ab" -"checksum rustc-ap-syntax 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a73328d8547bbb4b54439861c67d637c15f58d4ee6c8759cef8a221a607744e" -"checksum rustc-ap-syntax_pos 181.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02edc84fe5ea1cfc9fe36cbd2fd1330ef6518880168e2c896066ddafe4df9786" +"checksum rustc-ap-arena 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7bd7aabbf60986181924ddad8c5bee830cf83213ed8553f715145d050e42d0c" +"checksum rustc-ap-rustc_cratesio_shim 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1bc122961e39834268cb45baf75995eaca376b78146efce962b27de71b3e8b7" +"checksum rustc-ap-rustc_data_structures 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6c2ed8ee3a204499534a1ea22a8eb6c87c0c39dd139197d4a0f913b8e12a4c2" +"checksum rustc-ap-rustc_errors 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d35753d6c9159f49c74f800b0d00707db09863a7554679e1b701c7eeeb5a611c" +"checksum rustc-ap-rustc_target 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1b3da32f4862d4722e6f699e92ffa8b556166752fbdbbd64cc7d9ddd8db0e8" +"checksum rustc-ap-serialize 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "182579d9dc2e46e232de4cdd1a56ec352a55440a86e7389a6109dae73f2a392b" +"checksum rustc-ap-syntax 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c890882969e05d73cb97695a64e32b526830c7f197a708feb376e8684d16abb2" +"checksum rustc-ap-syntax_pos 182.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c779602d2e364440d28f8cb3c1fa13dcf11a546b96c5eab2bc7554869e2aca4" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" diff --git a/Cargo.toml b/Cargo.toml index 728b7ed03e3..a240d2c1e73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,8 +47,8 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.5.1" -rustc-ap-rustc_target = "181.0.0" -rustc-ap-syntax = "181.0.0" +rustc-ap-rustc_target = "182.0.0" +rustc-ap-syntax = "182.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/types.rs b/src/types.rs index 3608d582d98..42dfd3596c8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -681,7 +681,7 @@ impl Rewrite for ast::Ty { rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(ref it) => it + ast::TyKind::ImplTrait(_, ref it) => it .rewrite(context, shape) .map(|it_str| format!("impl {}", it_str)), ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), -- cgit 1.4.1-3-g733a5 From 9d8f3812cc2e5c0f1e9a4417dd41c66a4b4871c4 Mon Sep 17 00:00:00 2001 From: Florian Walch Date: Mon, 2 Jul 2018 23:16:17 +0200 Subject: Change default newline style to "Native" Fixes #2626. --- Configurations.md | 2 +- src/config/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 21a8d300db3..dc462cfccef 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1250,7 +1250,7 @@ fn main() { Unix or Windows line endings -- **Default value**: `"Unix"` +- **Default value**: `"Native"` - **Possible values**: `"Native"`, `"Unix"`, `"Windows"` - **Stable**: Yes diff --git a/src/config/mod.rs b/src/config/mod.rs index 71bdefeea79..98845661ef7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -40,7 +40,7 @@ create_config! { max_width: usize, 100, true, "Maximum width of each line"; hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; tab_spaces: usize, 4, true, "Number of spaces per tab"; - newline_style: NewlineStyle, NewlineStyle::Unix, true, "Unix or Windows line endings"; + newline_style: NewlineStyle, NewlineStyle::Native, true, "Unix or Windows line endings"; use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ formatting for items and expressions if they satisfy a heuristic notion of 'small'."; indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; -- cgit 1.4.1-3-g733a5 From 363363d06644738a4310122db8f855a4099822f7 Mon Sep 17 00:00:00 2001 From: Florian Walch Date: Mon, 2 Jul 2018 23:43:54 +0200 Subject: test: Assert CRLF line endings on Windows --- src/lib.rs | 5 +++++ src/test/mod.rs | 3 +++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 114e72c4847..01db0af61fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1038,9 +1038,14 @@ mod unit_tests { #[test] fn test_format_snippet() { let snippet = "fn main() { println!(\"hello, world\"); }"; + #[cfg(not(windows))] let expected = "fn main() {\n \ println!(\"hello, world\");\n\ }\n"; + #[cfg(windows)] + let expected = "fn main() {\r\n \ + println!(\"hello, world\");\r\n\ + }\r\n"; assert!(test_format_inner(format_snippet, snippet, expected)); } diff --git a/src/test/mod.rs b/src/test/mod.rs index 233055a067e..313ece43a40 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -247,7 +247,10 @@ fn stdin_formatting_smoke_test() { let (error_summary, _) = format_input(input, &config, Some(&mut buf)).unwrap(); assert!(error_summary.has_no_errors()); //eprintln!("{:?}", ); + #[cfg(not(windows))] assert_eq!(buf, "fn main() {}\n".as_bytes()); + #[cfg(windows)] + assert_eq!(buf, "fn main() {}\r\n".as_bytes()); } // FIXME(#1990) restore this test -- cgit 1.4.1-3-g733a5 From 800e488de84d6c13867654511262639690492b90 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 5 Jul 2018 22:50:23 -0700 Subject: Fix help for --help=file-lines Due to the way getopts works, it requires the equals sign. --- src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index fad9eeae6bb..b11e7ef18dd 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -137,7 +137,7 @@ fn make_opts() -> Options { opts.optopt( "", "file-lines", - "Format specified line ranges. Run with `--help file-lines` for \ + "Format specified line ranges. Run with `--help=file-lines` for \ more detail (unstable).", "JSON", ); -- cgit 1.4.1-3-g733a5 From 60ce411b5310c8af09de2d552e67b0593f3f1d4b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 9 Jul 2018 23:20:53 +0900 Subject: Format async closure --- src/closures.rs | 20 ++++++++++++-------- src/config/mod.rs | 3 ++- src/config/options.rs | 15 +++++++++++++++ src/expr.rs | 4 ++-- src/lib.rs | 2 ++ 5 files changed, 33 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 5f1102a36fc..5e2f01053f1 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -31,9 +31,9 @@ use utils::{last_line_width, left_most_sub_expr, stmt_expr}; // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. -// FIXME(topecongiro) Format async closures (#2813). pub fn rewrite_closure( capture: ast::CaptureBy, + asyncness: ast::IsAsync, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -43,8 +43,9 @@ pub fn rewrite_closure( ) -> Option { debug!("rewrite_closure {:?}", body); - let (prefix, extra_offset) = - rewrite_closure_fn_decl(capture, movability, fn_decl, body, span, context, shape)?; + let (prefix, extra_offset) = rewrite_closure_fn_decl( + capture, asyncness, movability, fn_decl, body, span, context, shape, + )?; // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; @@ -198,6 +199,7 @@ fn rewrite_closure_block( // Return type is (prefix, extra_offset) fn rewrite_closure_fn_decl( capture: ast::CaptureBy, + asyncness: ast::IsAsync, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -205,12 +207,12 @@ fn rewrite_closure_fn_decl( context: &RewriteContext, shape: Shape, ) -> Option<(String, usize)> { + let is_async = if asyncness.is_async() { "async " } else { "" }; let mover = if capture == ast::CaptureBy::Value { "move " } else { "" }; - let immovable = if movability == ast::Movability::Static { "static " } else { @@ -219,7 +221,7 @@ fn rewrite_closure_fn_decl( // 4 = "|| {".len(), which is overconservative when the closure consists of // a single expression. let nested_shape = shape - .shrink_left(mover.len() + immovable.len())? + .shrink_left(is_async.len() + mover.len() + immovable.len())? .sub_width(4)?; // 1 = | @@ -265,7 +267,7 @@ fn rewrite_closure_fn_decl( config: context.config, }; let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}{}|{}|", immovable, mover, list_str); + let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str); if !ret_str.is_empty() { if prefix.contains('\n') { @@ -289,7 +291,9 @@ pub fn rewrite_last_closure( expr: &ast::Expr, shape: Shape, ) -> Option { - if let ast::ExprKind::Closure(capture, _, movability, ref fn_decl, ref body, _) = expr.node { + if let ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) = + expr.node + { let body = match body.node { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) @@ -300,7 +304,7 @@ pub fn rewrite_last_closure( _ => body, }; let (prefix, extra_offset) = rewrite_closure_fn_decl( - capture, movability, fn_decl, body, expr.span, context, shape, + capture, asyncness, movability, fn_decl, body, expr.span, context, shape, )?; // If the closure goes multi line before its body, do not overflow the closure. if prefix.contains('\n') { diff --git a/src/config/mod.rs b/src/config/mod.rs index 71bdefeea79..fcda529ea89 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -104,6 +104,7 @@ create_config! { "Maximum number of blank lines which can be put between items."; blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items."; + edition: Edition, Edition::Edition2015, false, "The edition of the parser. (RFC 2052)"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; @@ -111,7 +112,7 @@ create_config! { use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible"; force_explicit_abi: bool, true, true, "Always print the abi for extern items"; condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ - in tuple patterns"; + in tuple patterns"; // Control options (changes the operation of rustfmt, rather than the formatting) color: Color, Color::Auto, false, diff --git a/src/config/options.rs b/src/config/options.rs index b3599c230f4..5fa0a048313 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -340,3 +340,18 @@ pub trait CliOptions { fn apply_to(self, config: &mut Config); fn config_path(&self) -> Option<&Path>; } + +/// The edition of the compiler (RFC 2052) +configuration_option_enum!{ Edition: + Edition2015, + Edition2018, +} + +impl Edition { + pub(crate) fn to_libsyntax_pos_edition(&self) -> syntax_pos::edition::Edition { + match self { + Edition::Edition2015 => syntax_pos::edition::Edition::Edition2015, + Edition::Edition2018 => syntax_pos::edition::Edition::Edition2018, + } + } +} diff --git a/src/expr.rs b/src/expr.rs index ca31b0b82ef..6928b77f360 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -183,9 +183,9 @@ pub fn format_expr( } else { Some("yield".to_string()) }, - ast::ExprKind::Closure(capture, _, movability, ref fn_decl, ref body, _) => { + ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( - capture, movability, fn_decl, body, expr.span, context, shape, + capture, asyncness, movability, fn_decl, body, expr.span, context, shape, ) } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => { diff --git a/src/lib.rs b/src/lib.rs index 114e72c4847..817ed426e52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ extern crate serde; extern crate serde_derive; extern crate serde_json; extern crate syntax; +extern crate syntax_pos; extern crate toml; extern crate unicode_segmentation; @@ -793,6 +794,7 @@ fn format_input_inner( config: &Config, mut out: Option<&mut T>, ) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> { + syntax_pos::hygiene::set_default_edition(config.edition().to_libsyntax_pos_edition()); let mut summary = Summary::default(); if config.disable_all_formatting() { // When the input is from stdin, echo back the input. -- cgit 1.4.1-3-g733a5 From b6ea973d19ff1063ff97a95666e988bae226ebb2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Jun 2018 11:50:03 +1200 Subject: Factor out PairParts::infix --- src/expr.rs | 19 +++++++++++++++---- src/patterns.rs | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6928b77f360..d9fa4717357 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -92,7 +92,7 @@ pub fn format_expr( rewrite_pair( &**lhs, &**rhs, - PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), + PairParts::infix(&format!(" {} ", context.snippet(op.span))), context, shape, context.config.binop_separator(), @@ -211,7 +211,7 @@ pub fn format_expr( ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - PairParts::new("", " as ", ""), + PairParts::infix(" as "), context, shape, SeparatorPlace::Front, @@ -219,7 +219,7 @@ pub fn format_expr( ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - PairParts::new("", ": ", ""), + PairParts::infix(": "), context, shape, SeparatorPlace::Back, @@ -288,7 +288,7 @@ pub fn format_expr( rewrite_pair( &*lhs, &*rhs, - PairParts::new("", &sp_delim, ""), + PairParts::infix(&sp_delim), context, shape, context.config.binop_separator(), @@ -435,6 +435,7 @@ fn rewrite_simple_binaries( None } +/// Sigils that decorate a binop pair. #[derive(new, Clone, Copy)] pub struct PairParts<'a> { prefix: &'a str, @@ -442,6 +443,16 @@ pub struct PairParts<'a> { suffix: &'a str, } +impl<'a> PairParts<'a> { + pub fn infix(infix: &'a str) -> PairParts<'a> { + PairParts { + prefix: "", + infix, + suffix: "", + } + } +} + pub fn rewrite_pair( lhs: &LHS, rhs: &RHS, diff --git a/src/patterns.rs b/src/patterns.rs index 85b9b84b6b2..5e3cbfc31f3 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -112,7 +112,7 @@ impl Rewrite for Pat { rewrite_pair( &**lhs, &**rhs, - PairParts::new("", &infix, ""), + PairParts::infix(&infix), context, shape, SeparatorPlace::Front, -- cgit 1.4.1-3-g733a5 From b68fd9e6bfd40802afc2a8379824fdcf541c9c1d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 28 Jun 2018 12:02:05 +1200 Subject: Move pair handling to its own module --- src/expr.rs | 104 +------------------------------------------------ src/lib.rs | 1 + src/pairs.rs | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/patterns.rs | 5 +-- src/types.rs | 5 +-- 5 files changed, 125 insertions(+), 109 deletions(-) create mode 100644 src/pairs.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d9fa4717357..8f167650507 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,6 +31,7 @@ use lists::{ use macros::{rewrite_macro, MacroArg, MacroPosition}; use matches::rewrite_match; use overflow; +use pairs::{rewrite_pair, PairParts}; use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; @@ -435,109 +436,6 @@ fn rewrite_simple_binaries( None } -/// Sigils that decorate a binop pair. -#[derive(new, Clone, Copy)] -pub struct PairParts<'a> { - prefix: &'a str, - infix: &'a str, - suffix: &'a str, -} - -impl<'a> PairParts<'a> { - pub fn infix(infix: &'a str) -> PairParts<'a> { - PairParts { - prefix: "", - infix, - suffix: "", - } - } -} - -pub fn rewrite_pair( - lhs: &LHS, - rhs: &RHS, - pp: PairParts, - context: &RewriteContext, - shape: Shape, - separator_place: SeparatorPlace, -) -> Option -where - LHS: Rewrite, - RHS: Rewrite, -{ - let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), - SeparatorPlace::Front => shape.used_width(), - }; - let lhs_shape = Shape { - width: context.budget(lhs_overhead), - ..shape - }; - let lhs_result = lhs - .rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; - - // Try to put both lhs and rhs on the same line. - let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + pp.infix.len()) - .and_then(|s| s.sub_width(pp.suffix.len())) - .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); - if let Some(ref rhs_result) = rhs_orig_result { - // If the length of the lhs is equal to or shorter than the tab width or - // the rhs looks like block expression, we put the rhs on the same - // line with the lhs even if the rhs is multi-lined. - let allow_same_line = lhs_result.len() <= context.config.tab_spaces() - || rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); - if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) - + pp.infix.len() - + first_line_width(rhs_result) - + pp.suffix.len(); - if one_line_width <= shape.width { - return Some(format!( - "{}{}{}{}", - lhs_result, pp.infix, rhs_result, pp.suffix - )); - } - } - } - - // We have to use multiple lines. - // Re-evaluate the rhs because we have more space now: - let mut rhs_shape = match context.config.indent_style() { - IndentStyle::Visual => shape - .sub_width(pp.suffix.len() + pp.prefix.len())? - .visual_indent(pp.prefix.len()), - IndentStyle::Block => { - // Try to calculate the initial constraint on the right hand side. - let rhs_overhead = shape.rhs_overhead(context.config); - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(rhs_overhead)? - } - }; - let infix = match separator_place { - SeparatorPlace::Back => pp.infix.trim_right(), - SeparatorPlace::Front => pp.infix.trim_left(), - }; - if separator_place == SeparatorPlace::Front { - rhs_shape = rhs_shape.offset_left(infix.len())?; - } - let rhs_result = rhs.rewrite(context, rhs_shape)?; - let indent_str = rhs_shape.indent.to_string_with_newline(context.config); - let infix_with_sep = match separator_place { - SeparatorPlace::Back => format!("{}{}", infix, indent_str), - SeparatorPlace::Front => format!("{}{}", indent_str, infix), - }; - Some(format!( - "{}{}{}{}", - lhs_result, infix_with_sep, rhs_result, pp.suffix - )) -} - pub fn rewrite_array( name: &str, exprs: &[&T], diff --git a/src/lib.rs b/src/lib.rs index 817ed426e52..2c9a792d92d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ mod matches; mod missed_spans; pub(crate) mod modules; mod overflow; +mod pairs; mod patterns; mod reorder; mod rewrite; diff --git a/src/pairs.rs b/src/pairs.rs new file mode 100644 index 00000000000..55c78b641a0 --- /dev/null +++ b/src/pairs.rs @@ -0,0 +1,119 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::lists::*; + +use config::IndentStyle; +use rewrite::{Rewrite, RewriteContext}; +use shape::Shape; +use utils::{first_line_width, last_line_width}; + +/// Sigils that decorate a binop pair. +#[derive(new, Clone, Copy)] +pub struct PairParts<'a> { + prefix: &'a str, + infix: &'a str, + suffix: &'a str, +} + +impl<'a> PairParts<'a> { + pub fn infix(infix: &'a str) -> PairParts<'a> { + PairParts { + prefix: "", + infix, + suffix: "", + } + } +} + +pub fn rewrite_pair( + lhs: &LHS, + rhs: &RHS, + pp: PairParts, + context: &RewriteContext, + shape: Shape, + separator_place: SeparatorPlace, +) -> Option +where + LHS: Rewrite, + RHS: Rewrite, +{ + let lhs_overhead = match separator_place { + SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), + SeparatorPlace::Front => shape.used_width(), + }; + let lhs_shape = Shape { + width: context.budget(lhs_overhead), + ..shape + }; + let lhs_result = lhs + .rewrite(context, lhs_shape) + .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; + + // Try to put both lhs and rhs on the same line. + let rhs_orig_result = shape + .offset_left(last_line_width(&lhs_result) + pp.infix.len()) + .and_then(|s| s.sub_width(pp.suffix.len())) + .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); + if let Some(ref rhs_result) = rhs_orig_result { + // If the length of the lhs is equal to or shorter than the tab width or + // the rhs looks like block expression, we put the rhs on the same + // line with the lhs even if the rhs is multi-lined. + let allow_same_line = lhs_result.len() <= context.config.tab_spaces() + || rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); + if !rhs_result.contains('\n') || allow_same_line { + let one_line_width = last_line_width(&lhs_result) + + pp.infix.len() + + first_line_width(rhs_result) + + pp.suffix.len(); + if one_line_width <= shape.width { + return Some(format!( + "{}{}{}{}", + lhs_result, pp.infix, rhs_result, pp.suffix + )); + } + } + } + + // We have to use multiple lines. + // Re-evaluate the rhs because we have more space now: + let mut rhs_shape = match context.config.indent_style() { + IndentStyle::Visual => shape + .sub_width(pp.suffix.len() + pp.prefix.len())? + .visual_indent(pp.prefix.len()), + IndentStyle::Block => { + // Try to calculate the initial constraint on the right hand side. + let rhs_overhead = shape.rhs_overhead(context.config); + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(rhs_overhead)? + } + }; + let infix = match separator_place { + SeparatorPlace::Back => pp.infix.trim_right(), + SeparatorPlace::Front => pp.infix.trim_left(), + }; + if separator_place == SeparatorPlace::Front { + rhs_shape = rhs_shape.offset_left(infix.len())?; + } + let rhs_result = rhs.rewrite(context, rhs_shape)?; + let indent_str = rhs_shape.indent.to_string_with_newline(context.config); + let infix_with_sep = match separator_place { + SeparatorPlace::Back => format!("{}{}", infix, indent_str), + SeparatorPlace::Front => format!("{}{}", indent_str, infix), + }; + Some(format!( + "{}{}{}{}", + lhs_result, infix_with_sep, rhs_result, pp.suffix + )) +} diff --git a/src/patterns.rs b/src/patterns.rs index 5e3cbfc31f3..dbe0c8a6f66 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -15,15 +15,14 @@ use syntax::ptr; use codemap::SpanUtils; use comment::FindUncommented; -use expr::{ - can_be_overflowed_expr, rewrite_pair, rewrite_unary_prefix, wrap_struct_field, PairParts, -}; +use expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use lists::{ itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; use macros::{rewrite_macro, MacroPosition}; use overflow; +use pairs::{rewrite_pair, PairParts}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; diff --git a/src/types.rs b/src/types.rs index 42dfd3596c8..0c978ea28a6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,12 +18,11 @@ use syntax::symbol::keywords; use codemap::SpanUtils; use config::{IndentStyle, TypeDensity}; -use expr::{ - rewrite_assign_rhs, rewrite_pair, rewrite_tuple, rewrite_unary_prefix, PairParts, ToExpr, -}; +use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; +use pairs::{rewrite_pair, PairParts}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -- cgit 1.4.1-3-g733a5 From a4cdb68925e4cb3a2df74df61da333136afae582 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 30 Jun 2018 19:53:06 +1200 Subject: Improve formatting of series of binop expressions This commit changes the handling of binops (and potentially other pairs), where the expressions are logically a list, e.g., `a + b + c`. It makes the single line vs multi-line approaches explicit and introduces a lowering step. This improves formatting in a number of places, mostly improving consistency of formatting with very short sub-expressions, but also some weird indentation. Closes #2802 --- src/expr.rs | 80 +-------------------- src/pairs.rs | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 221 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8f167650507..7f39e93b267 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -31,7 +31,7 @@ use lists::{ use macros::{rewrite_macro, MacroArg, MacroPosition}; use matches::rewrite_match; use overflow; -use pairs::{rewrite_pair, PairParts}; +use pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; @@ -89,7 +89,7 @@ pub fn format_expr( ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span), ast::ExprKind::Binary(op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator - rewrite_simple_binaries(context, expr, shape, op).or_else(|| { + rewrite_all_pairs(expr, shape, context).or_else(|| { rewrite_pair( &**lhs, &**rhs, @@ -362,80 +362,6 @@ pub fn format_expr( }) } -/// Collect operands that appears in the given binary operator in the opposite order. -/// e.g. `collect_binary_items(e, ||)` for `a && b || c || d` returns `[d, c, a && b]`. -fn collect_binary_items<'a>(mut expr: &'a ast::Expr, binop: ast::BinOp) -> Vec<&'a ast::Expr> { - let mut result = vec![]; - let mut prev_lhs = None; - loop { - match expr.node { - ast::ExprKind::Binary(inner_binop, ref lhs, ref rhs) - if inner_binop.node == binop.node => - { - result.push(&**rhs); - expr = lhs; - prev_lhs = Some(lhs); - } - _ => { - if let Some(lhs) = prev_lhs { - result.push(lhs); - } - break; - } - } - } - result -} - -/// Rewrites a binary expression whose operands fits within a single line. -fn rewrite_simple_binaries( - context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, - op: ast::BinOp, -) -> Option { - let op_str = context.snippet(op.span); - - // 2 = spaces around a binary operator. - let sep_overhead = op_str.len() + 2; - let nested_overhead = sep_overhead - 1; - - let nested_shape = (match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), - }).with_max_width(context.config); - let nested_shape = match context.config.binop_separator() { - SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?, - SeparatorPlace::Front => nested_shape.offset_left(nested_overhead)?, - }; - - let opt_rewrites: Option> = collect_binary_items(expr, op) - .iter() - .rev() - .map(|e| e.rewrite(context, nested_shape)) - .collect(); - if let Some(rewrites) = opt_rewrites { - if rewrites.iter().all(|e| ::utils::is_single_line(e)) { - let total_width = rewrites.iter().map(|s| s.len()).sum::() - + sep_overhead * (rewrites.len() - 1); - - let sep_str = if total_width <= shape.width { - format!(" {} ", op_str) - } else { - let indent_str = nested_shape.indent.to_string_with_newline(context.config); - match context.config.binop_separator() { - SeparatorPlace::Back => format!(" {}{}", op_str.trim_right(), indent_str), - SeparatorPlace::Front => format!("{}{} ", indent_str, op_str.trim_left()), - } - }; - - return wrap_str(rewrites.join(&sep_str), context.config.max_width(), shape); - } - } - - None -} - pub fn rewrite_array( name: &str, exprs: &[&T], @@ -2004,7 +1930,7 @@ fn choose_rhs( } (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), (None, None) => None, - (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), + (Some(orig_rhs), _) => Some(format!(" {}", orig_rhs)), } } } diff --git a/src/pairs.rs b/src/pairs.rs index 55c78b641a0..3cd044d606e 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -8,23 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::lists::*; +use syntax::ast; +use config::lists::*; use config::IndentStyle; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use utils::{first_line_width, last_line_width}; +use utils::{first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str}; /// Sigils that decorate a binop pair. #[derive(new, Clone, Copy)] -pub struct PairParts<'a> { +pub(crate) struct PairParts<'a> { prefix: &'a str, infix: &'a str, suffix: &'a str, } impl<'a> PairParts<'a> { - pub fn infix(infix: &'a str) -> PairParts<'a> { + pub(crate) fn infix(infix: &'a str) -> PairParts<'a> { PairParts { prefix: "", infix, @@ -33,7 +34,148 @@ impl<'a> PairParts<'a> { } } -pub fn rewrite_pair( +// Flattens a tree of pairs into a list and tries to rewrite them all at once. +// FIXME would be nice to reuse the lists API for this, but because each separator +// can be different, we can't. +pub(crate) fn rewrite_all_pairs( + expr: &ast::Expr, + shape: Shape, + context: &RewriteContext, +) -> Option { + // First we try formatting on one line. + if let Some(list) = expr.flatten(context, false) { + if let Some(r) = rewrite_pairs_one_line(&list, shape, context) { + return Some(r); + } + } + + // We can't format on line, so try many. When we flatten here we make sure + // to only flatten pairs with the same operator, that way we don't + // necessarily need one line per sub-expression, but we don't do anything + // too funny wrt precedence. + expr.flatten(context, true) + .and_then(|list| rewrite_pairs_multiline(list, shape, context)) +} + +// This may return a multi-line result since we allow the last expression to go +// multiline in a 'single line' formatting. +fn rewrite_pairs_one_line( + list: &PairList, + shape: Shape, + context: &RewriteContext, +) -> Option { + assert!(list.list.len() >= 2, "Not a pair?"); + + let mut result = String::new(); + let base_shape = shape.block(); + + for (e, s) in list.list[..list.list.len()] + .iter() + .zip(list.separators.iter()) + { + let cur_shape = base_shape.offset_left(last_line_width(&result))?; + let rewrite = e.rewrite(context, cur_shape)?; + + if !is_single_line(&rewrite) || result.len() > shape.width { + return None; + } + + result.push_str(&rewrite); + result.push(' '); + result.push_str(s); + result.push(' '); + } + + let last = list.list.last().unwrap(); + let cur_shape = base_shape.offset_left(last_line_width(&result))?; + let rewrite = last.rewrite(context, cur_shape)?; + result.push_str(&rewrite); + + if first_line_width(&result) > shape.width { + return None; + } + + // Check the last expression in the list. We let this expression go over + // multiple lines, but we check that if this is necessary, then we can't + // do better using multi-line formatting. + if !is_single_line(&result) { + let multiline_shape = shape.offset_left(list.separators.last().unwrap().len() + 1)?; + let multiline_list: PairList = PairList { + list: vec![last], + separators: vec![], + separator_place: list.separator_place, + }; + // Format as if we were multi-line. + if let Some(rewrite) = rewrite_pairs_multiline(multiline_list, multiline_shape, context) { + // Also, don't let expressions surrounded by parens go multi-line, + // this looks really bad. + if rewrite.starts_with('(') || is_single_line(&rewrite) { + return None; + } + } + } + + wrap_str(result, context.config.max_width(), shape) +} + +fn rewrite_pairs_multiline( + list: PairList, + shape: Shape, + context: &RewriteContext, +) -> Option { + let rhs_offset = shape.rhs_overhead(&context.config); + let nested_shape = (match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), + }).with_max_width(&context.config) + .sub_width(rhs_offset)?; + + let indent_str = nested_shape.indent.to_string_with_newline(context.config); + let mut result = String::new(); + + let rewrite = list.list[0].rewrite(context, shape)?; + result.push_str(&rewrite); + + for (e, s) in list.list[1..].iter().zip(list.separators.iter()) { + if trimmed_last_line_width(&result) <= context.config.tab_spaces() { + // We must snuggle the next line onto the previous line to avoid an orphan. + if let Some(line_shape) = + shape.offset_left(s.len() + 2 + trimmed_last_line_width(&result)) + { + if let Some(rewrite) = e.rewrite(context, line_shape) { + result.push(' '); + result.push_str(s); + result.push(' '); + result.push_str(&rewrite); + continue; + } + } + } + + let nested_overhead = s.len() + 1; + let line_shape = match context.config.binop_separator() { + SeparatorPlace::Back => { + result.push(' '); + result.push_str(s); + result.push_str(&indent_str); + nested_shape.sub_width(nested_overhead)? + } + SeparatorPlace::Front => { + result.push_str(&indent_str); + result.push_str(s); + result.push(' '); + nested_shape.offset_left(nested_overhead)? + } + }; + + let rewrite = e.rewrite(context, line_shape)?; + result.push_str(&rewrite); + } + Some(result) +} + +// Rewrites a single pair. +pub(crate) fn rewrite_pair( lhs: &LHS, rhs: &RHS, pp: PairParts, @@ -45,6 +187,7 @@ where LHS: Rewrite, RHS: Rewrite, { + let tab_spaces = context.config.tab_spaces(); let lhs_overhead = match separator_place { SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), SeparatorPlace::Front => shape.used_width(), @@ -66,12 +209,11 @@ where // If the length of the lhs is equal to or shorter than the tab width or // the rhs looks like block expression, we put the rhs on the same // line with the lhs even if the rhs is multi-lined. - let allow_same_line = lhs_result.len() <= context.config.tab_spaces() - || rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); + let allow_same_line = lhs_result.len() <= tab_spaces || rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { let one_line_width = last_line_width(&lhs_result) + pp.infix.len() @@ -117,3 +259,68 @@ where lhs_result, infix_with_sep, rhs_result, pp.suffix )) } + +// A pair which forms a tree and can be flattened (e.g., binops). +trait FlattenPair: Rewrite + Sized { + // If `_same_op` is `true`, then we only combine binops with the same + // operator into the list. E.g,, if the source is `a * b + c`, if `_same_op` + // is true, we make `[(a * b), c]` if `_same_op` is false, we make + // `[a, b, c]` + fn flatten(&self, _context: &RewriteContext, _same_op: bool) -> Option> { + None + } +} + +struct PairList<'a, 'b, T: Rewrite + 'b> { + list: Vec<&'b T>, + separators: Vec<&'a str>, + separator_place: SeparatorPlace, +} + +impl FlattenPair for ast::Expr { + fn flatten(&self, context: &RewriteContext, same_op: bool) -> Option> { + let top_op = match self.node { + ast::ExprKind::Binary(op, _, _) => op.node, + _ => return None, + }; + + // Turn a tree of binop expressions into a list using a depth-first, + // in-order traversal. + let mut stack = vec![]; + let mut list = vec![]; + let mut separators = vec![]; + let mut node = self; + loop { + match node.node { + ast::ExprKind::Binary(op, ref lhs, _) if !same_op || op.node == top_op => { + stack.push(node); + node = lhs; + } + _ => { + list.push(node); + if let Some(pop) = stack.pop() { + match pop.node { + ast::ExprKind::Binary(op, _, ref rhs) => { + separators.push(op.node.to_string()); + node = rhs; + } + _ => unreachable!(), + } + } else { + break; + } + } + } + } + + assert_eq!(list.len() - 1, separators.len()); + Some(PairList { + list, + separators, + separator_place: context.config.binop_separator(), + }) + } +} + +impl FlattenPair for ast::Ty {} +impl FlattenPair for ast::Pat {} -- cgit 1.4.1-3-g733a5 From 486f8fd8e7b02b08832cd2bedf62afa351bdf672 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 6 Jul 2018 11:58:22 +1200 Subject: Fixup formatting of tests and source --- src/attr.rs | 3 ++- src/bin/main.rs | 3 ++- src/closures.rs | 3 ++- src/expr.rs | 12 ++++++------ src/items.rs | 9 ++++++--- src/lists.rs | 9 ++++----- src/macros.rs | 33 ++++++++++++++++----------------- src/overflow.rs | 6 ++---- src/reorder.rs | 13 +++++++------ src/string.rs | 3 ++- src/test/mod.rs | 3 ++- src/utils.rs | 9 ++++----- src/vertical.rs | 7 +++++-- tests/target/expr.rs | 9 +++++---- 14 files changed, 65 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 3c545bdda70..555c0eb96e7 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -194,7 +194,8 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { .rev() .take_while(|c| c.is_whitespace()) .filter(|&c| c == '\n') - .count() > 1 + .count() + > 1 }; (if mlb { "\n" } else { "" }, if mla { "\n" } else { "" }) } diff --git a/src/bin/main.rs b/src/bin/main.rs index b11e7ef18dd..cd5e58437e6 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -38,7 +38,8 @@ fn main() { let exit_code = match execute(&opts) { Ok((exit_mode, summary)) => { - if summary.has_operational_errors() || summary.has_parsing_errors() + if summary.has_operational_errors() + || summary.has_parsing_errors() || ((summary.has_diff || summary.has_check_errors()) && exit_mode == ExitCodeMode::Check) { diff --git a/src/closures.rs b/src/closures.rs index 5e2f01053f1..42b883589db 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -363,7 +363,8 @@ where }) .unwrap_or(false) }) - .count() > 1 + .count() + > 1 } fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { diff --git a/src/expr.rs b/src/expr.rs index 7f39e93b267..c4675cbcdf7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -863,16 +863,16 @@ impl<'a> ControlFlow<'a> { && context .config .width_heuristics() - .single_line_if_else_max_width > 0 + .single_line_if_else_max_width + > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if let Some(cond_str) = trial { - if cond_str.len() - <= context - .config - .width_heuristics() - .single_line_if_else_max_width + if cond_str.len() <= context + .config + .width_heuristics() + .single_line_if_else_max_width { return Some((cond_str, 0)); } diff --git a/src/items.rs b/src/items.rs index 84a24e7149e..00db19f3b6c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1382,7 +1382,8 @@ fn format_tuple_struct( )?; } - if !where_clause_str.is_empty() && !where_clause_str.contains('\n') + if !where_clause_str.is_empty() + && !where_clause_str.contains('\n') && (result.contains('\n') || offset.block_indent + result.len() + where_clause_str.len() + 1 > context.config.max_width()) @@ -2527,7 +2528,8 @@ fn rewrite_where_clause_rfc_style( && comment_before.is_empty() && comment_after.is_empty() && !preds_str.contains('\n') - && 6 + preds_str.len() <= shape.width || where_single_line + && 6 + preds_str.len() <= shape.width + || where_single_line { Cow::from(" ") } else { @@ -2737,7 +2739,8 @@ fn format_generics( false, )?; result.push_str(&where_clause_str); - brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine + brace_pos == BracePos::ForceSameLine + || brace_style == BraceStyle::PreferSameLine || (generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1) } else { diff --git a/src/lists.rs b/src/lists.rs index d0ac21d4bba..29c7e40fb17 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -97,11 +97,10 @@ impl ListItem { } pub fn is_different_group(&self) -> bool { - self.inner_as_ref().contains('\n') || self.pre_comment.is_some() - || self - .post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) + self.inner_as_ref().contains('\n') || self.pre_comment.is_some() || self + .post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) } pub fn is_multiline(&self) -> bool { diff --git a/src/macros.rs b/src/macros.rs index 8468dbf1591..76f50b30a54 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1107,23 +1107,22 @@ fn indent_macro_snippet( .min()?; Some( - first_line + "\n" - + &trimmed_lines - .iter() - .map( - |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { - _ if !trimmed => line.to_owned(), - Some(original_indent_width) => { - let new_indent_width = indent.width() - + original_indent_width.saturating_sub(min_prefix_space_width); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) - } - None => String::new(), - }, - ) - .collect::>() - .join("\n"), + first_line + "\n" + &trimmed_lines + .iter() + .map( + |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { + _ if !trimmed => line.to_owned(), + Some(original_indent_width) => { + let new_indent_width = indent.width() + original_indent_width + .saturating_sub(min_prefix_space_width); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line.trim()) + } + None => String::new(), + }, + ) + .collect::>() + .join("\n"), ) } diff --git a/src/overflow.rs b/src/overflow.rs index 8fccf3da735..54e594d814f 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -320,15 +320,13 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { ListTactic::HorizontalVertical, Separator::Comma, self.nested_shape.width, - ) - == DefinitiveListTactic::Horizontal + ) == DefinitiveListTactic::Horizontal && definitive_tactic( &list_items[num_args_before + 1..], ListTactic::HorizontalVertical, Separator::Comma, self.nested_shape.width, - ) - == DefinitiveListTactic::Horizontal; + ) == DefinitiveListTactic::Horizontal; if one_line { tactic = DefinitiveListTactic::SpecialMacro(num_args_before); diff --git a/src/reorder.rs b/src/reorder.rs index 9908c402a43..5947b4ae87f 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -242,12 +242,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let item_length = items .iter() .take_while(|ppi| { - item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) + item_kind.is_same_item_kind(&***ppi) + && (!in_group || { + let current = self.codemap.lookup_line_range(ppi.span()); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) }) .count(); let items = &items[..item_length]; diff --git a/src/string.rs b/src/string.rs index a5453c0a8ed..39eaf57d72e 100644 --- a/src/string.rs +++ b/src/string.rs @@ -72,7 +72,8 @@ pub fn rewrite_string<'a>( // succeed. let mut max_chars = shape .width - .checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + .checked_sub(fmt.opener.len() + ender_length + 1)? + + 1; // Snip a line at a time from `orig` until it is used up. Push the snippet // onto result. diff --git a/src/test/mod.rs b/src/test/mod.rs index 233055a067e..633f9f8bd3f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -703,7 +703,8 @@ impl ConfigCodeBlock { .unwrap() .split('\n') .nth(0) - .unwrap_or("") == "#![rustfmt::skip]"; + .unwrap_or("") + == "#![rustfmt::skip]"; if self.config_name.is_none() && !fmt_skip { write_message(&format!( diff --git a/src/utils.rs b/src/utils.rs index a8f8592d2f2..48b71d9a84f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -295,11 +295,10 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { // Return true if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { ($self:ident, $span:expr) => { - !$self.config.file_lines().is_all() - && !$self - .config - .file_lines() - .intersects(&$self.codemap.lookup_line_range($span)) + !$self.config.file_lines().is_all() && !$self + .config + .file_lines() + .intersects(&$self.codemap.lookup_line_range($span)) }; } diff --git a/src/vertical.rs b/src/vertical.rs index 58422d782ac..1b7fdb9be1d 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -173,11 +173,14 @@ pub fn rewrite_with_alignment( let rest_span = mk_sp(init_last_pos, span.hi()); let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; Some( - result + spaces + "\n" + result + + spaces + + "\n" + &shape .indent .block_indent(context.config) - .to_string(context.config) + &rest_str, + .to_string(context.config) + + &rest_str, ) } } diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 9a529ffeaee..dc529fbd374 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -14,15 +14,15 @@ fn foo() -> bool { self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb - / (bbbbbb - function_call(x, *very_long_pointer, y)) + 1000; + / (bbbbbb - function_call(x, *very_long_pointer, y)) + + 1000; some_ridiculously_loooooooooooooooooooooong_function( 10000 * 30000000000 + 40000 / 1002200000000 - 50000 * sqrt(-1), trivial_value, ); (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + a - + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa); { @@ -358,7 +358,8 @@ fn issue1749() { { { if self.shape[(r as f32 + self.x_offset) as usize] - [(c as f32 + self.y_offset) as usize] != 0 + [(c as f32 + self.y_offset) as usize] + != 0 { // hello } -- cgit 1.4.1-3-g733a5 From 229a55248b49137d32af96bdd88c58913409106e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 12 Jul 2018 22:21:07 +1200 Subject: address reviewer comments --- src/lists.rs | 3 ++- src/pairs.rs | 15 ++++++++++----- tests/target/expr.rs | 6 ++++-- 3 files changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 29c7e40fb17..c415032ad67 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -419,7 +419,8 @@ where if first_line_width(&formatted_comment) + last_line_width(&result) + comment_alignment - + 1 > formatting.config.max_width() + + 1 + > formatting.config.max_width() { item_max_width = None; formatted_comment = rewrite_post_comment(&mut item_max_width)?; diff --git a/src/pairs.rs b/src/pairs.rs index 3cd044d606e..2c4358f7278 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -69,10 +69,7 @@ fn rewrite_pairs_one_line( let mut result = String::new(); let base_shape = shape.block(); - for (e, s) in list.list[..list.list.len()] - .iter() - .zip(list.separators.iter()) - { + for (e, s) in list.list.iter().zip(list.separators.iter()) { let cur_shape = base_shape.offset_left(last_line_width(&result))?; let rewrite = e.rewrite(context, cur_shape)?; @@ -137,7 +134,15 @@ fn rewrite_pairs_multiline( result.push_str(&rewrite); for (e, s) in list.list[1..].iter().zip(list.separators.iter()) { - if trimmed_last_line_width(&result) <= context.config.tab_spaces() { + // The following test checks if we should keep two subexprs on the same + // line. We do this if not doing so would create an orphan and there is + // enough space to do so. + let offset = if result.contains('\n') { + 0 + } else { + shape.used_width() + }; + if last_line_width(&result) + offset <= nested_shape.used_width() { // We must snuggle the next line onto the previous line to avoid an orphan. if let Some(line_shape) = shape.offset_left(s.len() + 2 + trimmed_last_line_width(&result)) diff --git a/tests/target/expr.rs b/tests/target/expr.rs index e8caa73387e..5684b6efd31 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -22,7 +22,8 @@ fn foo() -> bool { trivial_value, ); (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - + a + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + a + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaa); { @@ -514,5 +515,6 @@ fn issue_2802() { * a_very_specific_length(specific_length_arg) * very_specific_length(Foo { a: some_much_much_longer_value, - }) * some_value + }) + * some_value } -- cgit 1.4.1-3-g733a5 From 472a2ed0f6f75cc33f42a72beaf1827c13b713d1 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 7 Jul 2018 12:24:09 +0200 Subject: fix rewrite_string when a line feed is present in a sequence of whitespaces, resulting in strange formatting --- src/string.rs | 296 ++++++++++++++++++++++++++++++++----------- src/utils.rs | 2 +- tests/source/issue-1210/a.rs | 12 ++ tests/source/issue-1210/b.rs | 12 ++ tests/source/issue-1210/c.rs | 5 + tests/source/issue-1210/d.rs | 4 + tests/source/issue-1210/e.rs | 8 ++ tests/target/issue-1210/a.rs | 16 +++ tests/target/issue-1210/b.rs | 16 +++ tests/target/issue-1210/c.rs | 7 + tests/target/issue-1210/d.rs | 4 + tests/target/issue-1210/e.rs | 11 ++ 12 files changed, 320 insertions(+), 73 deletions(-) create mode 100644 tests/source/issue-1210/a.rs create mode 100644 tests/source/issue-1210/b.rs create mode 100644 tests/source/issue-1210/c.rs create mode 100644 tests/source/issue-1210/d.rs create mode 100644 tests/source/issue-1210/e.rs create mode 100644 tests/target/issue-1210/a.rs create mode 100644 tests/target/issue-1210/b.rs create mode 100644 tests/target/issue-1210/c.rs create mode 100644 tests/target/issue-1210/d.rs create mode 100644 tests/target/issue-1210/e.rs (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 39eaf57d72e..387bee3cec9 100644 --- a/src/string.rs +++ b/src/string.rs @@ -41,21 +41,43 @@ impl<'a> StringFormat<'a> { config, } } + + /// Returns the maximum number of graphemes that is possible on a line while taking the + /// indentation into account. + /// + /// If we cannot put at least a single character per line, the rewrite won't succeed. + fn max_chars_with_indent(&self) -> Option { + Some( + self.shape + .width + .checked_sub(self.opener.len() + self.line_end.len() + 1)? + + 1; + ) + } + + /// Like max_chars_with_indent but the indentation is not substracted. + /// This allows to fit more graphemes from the string on a line when + /// SnippetState::Overflow. + fn max_chars_without_indent(&self) -> Option { + Some(self.config.max_width().checked_sub(self.line_end.len())?) + } } -// FIXME: simplify this! pub fn rewrite_string<'a>( orig: &str, fmt: &StringFormat<'a>, max_width: Option, ) -> Option { + let max_chars_with_indent = fmt.max_chars_with_indent()?; + let max_chars_without_indent = fmt.max_chars_without_indent()?; + let indent = fmt.shape.indent.to_string_with_newline(fmt.config); + // Strip line breaks. - let re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); - let stripped_str = re.replace_all(orig, "$1"); + // With this regex applied, all remaining whitespaces are significant + let strip_line_breaks_re = Regex::new(r"([^\\](\\\\)*)\\[\n\r][[:space:]]*").unwrap(); + let stripped_str = strip_line_breaks_re.replace_all(orig, "$1"); let graphemes = UnicodeSegmentation::graphemes(&*stripped_str, false).collect::>(); - let shape = fmt.shape; - let indent = shape.indent.to_string_with_newline(fmt.config); // `cur_start` is the position in `orig` of the start of the current line. let mut cur_start = 0; @@ -67,85 +89,129 @@ pub fn rewrite_string<'a>( ); result.push_str(fmt.opener); - let ender_length = fmt.line_end.len(); - // If we cannot put at least a single character per line, the rewrite won't - // succeed. - let mut max_chars = shape - .width - .checked_sub(fmt.opener.len() + ender_length + 1)? - + 1; - - // Snip a line at a time from `orig` until it is used up. Push the snippet + // Snip a line at a time from `stripped_str` until it is used up. Push the snippet // onto result. - 'outer: loop { - // `cur_end` will be where we break the line, as an offset into `orig`. - // Initialised to the maximum it could be (which may be beyond `orig`). - let mut cur_end = cur_start + max_chars; - - // We can fit the rest of the string on this line, so we're done. - if cur_end >= graphemes.len() { - let line = &graphemes[cur_start..].join(""); - result.push_str(line); - break 'outer; + let mut cur_max_chars = max_chars_with_indent; + loop { + // All the input starting at cur_start fits on the current line + if graphemes.len() - cur_start <= cur_max_chars { + result.push_str(&graphemes[cur_start..].join("")); + break; } - // Push cur_end left until we reach whitespace (or the line is too small). - while !is_whitespace(graphemes[cur_end - 1]) { - cur_end -= 1; - if cur_end < cur_start + MIN_STRING { - // We couldn't find whitespace before the string got too small. - // So start again at the max length and look for punctuation. - cur_end = cur_start + max_chars; - while !is_punctuation(graphemes[cur_end - 1]) { - cur_end -= 1; - - // If we can't break at whitespace or punctuation, grow the string instead. - if cur_end < cur_start + MIN_STRING { - cur_end = cur_start + max_chars; - while !(is_punctuation(graphemes[cur_end - 1]) - || is_whitespace(graphemes[cur_end - 1])) - { - cur_end += 1; - if cur_end == graphemes.len() { - let line = &graphemes[cur_start..].join(""); - result.push_str(line); - break 'outer; - } - } - break; - } - } + // The input starting at cur_start needs to be broken + match break_string(cur_max_chars, fmt.trim_end, &graphemes[cur_start..]) { + SnippetState::LineEnd(line, len) => { + result.push_str(&line); + result.push_str(fmt.line_end); + result.push_str(&indent); + result.push_str(fmt.line_start); + cur_max_chars = max_chars_with_indent; + cur_start += len; + } + SnippetState::Overflow(line, len) => { + result.push_str(&line); + cur_max_chars = max_chars_without_indent; + cur_start += len; + } + SnippetState::EndOfInput(line) => { + result.push_str(&line); break; } } - // Make sure there is no whitespace to the right of the break. - while cur_end < stripped_str.len() && is_whitespace(graphemes[cur_end]) { - cur_end += 1; - } + } - // Make the current line and add it on to result. - let raw_line = graphemes[cur_start..cur_end].join(""); - let line = if fmt.trim_end { - raw_line.trim() - } else { - raw_line.as_str() - }; + result.push_str(fmt.closer); + wrap_str(result, fmt.config.max_width(), fmt.shape) +} - result.push_str(line); - result.push_str(fmt.line_end); - result.push_str(&indent); - result.push_str(fmt.line_start); +/// Result of breaking a string so it fits in a line and the state it ended in. +/// The state informs about what to do with the snippet and how to continue the breaking process. +#[derive(Debug, PartialEq)] +enum SnippetState { + /// The input could not be broken and so rewriting the string is finished. + EndOfInput(String), + /// The input could be broken and the returned snippet should be ended with a + /// `[StringFormat::line_end]`. The next snippet needs to be indented. + LineEnd(String, usize), + /// The input could be broken but the returned snippet should not be ended with a + /// `[StringFormat::line_end]` because the whitespace is significant. Therefore, the next + /// snippet should not be indented. + Overflow(String, usize), +} - // The next line starts where the current line ends. - cur_start = cur_end; +/// Break the input string at a boundary character around the offset `max_chars`. A boundary +/// character is either a punctuation or a whitespace. +fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetState { + let break_at = |index /* grapheme at index is included */| { + // Take in any whitespaces to the left/right of `input[index]` and + // check if there is a line feed, in which case whitespaces needs to be kept. + let mut index_minus_ws = index; + for (i, grapheme) in input[0..=index].iter().enumerate().rev() { + if !trim_end && is_line_feed(grapheme) { + return SnippetState::Overflow(input[0..=i].join("").to_string(), i + 1); + } else if !is_whitespace(grapheme) { + index_minus_ws = i; + break; + } + } + let mut index_plus_ws = index; + for (i, grapheme) in input[index + 1..].iter().enumerate() { + if !trim_end && is_line_feed(grapheme) { + return SnippetState::Overflow( + input[0..=index + 1 + i].join("").to_string(), + index + 2 + i, + ); + } else if !is_whitespace(grapheme) { + index_plus_ws = index + i; + break; + } + } - if let Some(new_max_chars) = max_width { - max_chars = new_max_chars.checked_sub(fmt.opener.len() + ender_length + 1)? + 1; + if trim_end { + SnippetState::LineEnd( + input[0..=index_minus_ws].join("").to_string(), + index_plus_ws + 1, + ) + } else { + SnippetState::LineEnd( + input[0..=index_plus_ws].join("").to_string(), + index_plus_ws + 1, + ) } + }; + + // Find the position in input for breaking the string + match input[0..max_chars] + .iter() + .rposition(|grapheme| is_whitespace(grapheme)) + { + // Found a whitespace and what is on its left side is big enough. + Some(index) if index >= MIN_STRING => break_at(index), + // No whitespace found, try looking for a punctuation instead + _ => match input[0..max_chars] + .iter() + .rposition(|grapheme| is_punctuation(grapheme)) + { + // Found a punctuation and what is on its left side is big enough. + Some(index) if index >= MIN_STRING => break_at(index), + // Either no boundary character was found to the left of `input[max_chars]`, or the line + // got too small. We try searching for a boundary character to the right. + _ => match input[max_chars..] + .iter() + .position(|grapheme| is_whitespace(grapheme) || is_punctuation(grapheme)) + { + // A boundary was found after the line limit + Some(index) => break_at(max_chars + index), + // No boundary to the right, the input cannot be broken + None => SnippetState::EndOfInput(input.join("").to_string()), + }, + }, } +} - result.push_str(fmt.closer); - wrap_str(result, fmt.config.max_width(), fmt.shape) +fn is_line_feed(grapheme: &str) -> bool { + grapheme.as_bytes()[0] == b'\n' } fn is_whitespace(grapheme: &str) -> bool { @@ -161,8 +227,9 @@ fn is_punctuation(grapheme: &str) -> bool { #[cfg(test)] mod test { - use super::{rewrite_string, StringFormat}; + use super::{break_string, rewrite_string, SnippetState, StringFormat}; use shape::{Indent, Shape}; + use unicode_segmentation::UnicodeSegmentation; #[test] fn issue343() { @@ -170,4 +237,89 @@ mod test { let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); rewrite_string("eq_", &fmt, None); } + + #[test] + fn should_break_on_whitespace() { + let string = "Placerat felis. Mauris porta ante sagittis purus."; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(20, false, &graphemes[..]), + SnippetState::LineEnd("Placerat felis. ".to_string(), 16) + ); + assert_eq!( + break_string(20, true, &graphemes[..]), + SnippetState::LineEnd("Placerat felis.".to_string(), 16) + ); + } + + #[test] + fn should_break_on_punctuation() { + let string = "Placerat_felis._Mauris_porta_ante_sagittis_purus."; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(20, false, &graphemes[..]), + SnippetState::LineEnd("Placerat_felis.".to_string(), 15) + ); + } + + #[test] + fn should_break_forward() { + let string = "Venenatis_tellus_vel_tellus. Aliquam aliquam dolor at justo."; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(20, false, &graphemes[..]), + SnippetState::LineEnd("Venenatis_tellus_vel_tellus. ".to_string(), 29) + ); + assert_eq!( + break_string(20, true, &graphemes[..]), + SnippetState::LineEnd("Venenatis_tellus_vel_tellus.".to_string(), 29) + ); + } + + #[test] + fn nothing_to_break() { + let string = "Venenatis_tellus_vel_tellus"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(20, false, &graphemes[..]), + SnippetState::EndOfInput("Venenatis_tellus_vel_tellus".to_string()) + ); + } + + #[test] + fn significant_whitespaces() { + let string = "Neque in sem. \n Pellentesque tellus augue."; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(15, false, &graphemes[..]), + SnippetState::Overflow("Neque in sem. \n".to_string(), 20) + ); + assert_eq!( + break_string(25, false, &graphemes[..]), + SnippetState::Overflow("Neque in sem. \n".to_string(), 20) + ); + // if `StringFormat::line_end` is true, then the line feed does not matter anymore + assert_eq!( + break_string(15, true, &graphemes[..]), + SnippetState::LineEnd("Neque in sem.".to_string(), 26) + ); + assert_eq!( + break_string(25, true, &graphemes[..]), + SnippetState::LineEnd("Neque in sem.".to_string(), 26) + ); + } + + #[test] + fn big_whitespace() { + let string = "Neque in sem. Pellentesque tellus augue."; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(20, false, &graphemes[..]), + SnippetState::LineEnd("Neque in sem. ".to_string(), 25) + ); + assert_eq!( + break_string(20, true, &graphemes[..]), + SnippetState::LineEnd("Neque in sem.".to_string(), 25) + ); + } } diff --git a/src/utils.rs b/src/utils.rs index 48b71d9a84f..99275b52dc1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -320,7 +320,7 @@ macro_rules! skip_out_of_file_lines_range_visitor { } // Wraps String in an Option. Returns Some when the string adheres to the -// Rewrite constraints defined for the Rewrite trait and else otherwise. +// Rewrite constraints defined for the Rewrite trait and None otherwise. pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { if is_valid_str(&s, max_width, shape) { Some(s) diff --git a/tests/source/issue-1210/a.rs b/tests/source/issue-1210/a.rs new file mode 100644 index 00000000000..6bb9964b4e3 --- /dev/null +++ b/tests/source/issue-1210/a.rs @@ -0,0 +1,12 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +impl Foo { + fn cxx(&self, target: &str) -> &Path { + match self.cxx.get(target) { + Some(p) => p.path(), + None => panic!("\n\ntarget `{}` is not configured as a host, + only as a target\n\n", target), + } + } +} diff --git a/tests/source/issue-1210/b.rs b/tests/source/issue-1210/b.rs new file mode 100644 index 00000000000..8c71ef98b7f --- /dev/null +++ b/tests/source/issue-1210/b.rs @@ -0,0 +1,12 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +impl Foo { + fn cxx(&self, target: &str) -> &Path { + match self.cxx.get(target) { + Some(p) => p.path(), + None => panic!("\ntarget `{}`: is not, configured as a host, + only as a target\n\n", target), + } + } +} diff --git a/tests/source/issue-1210/c.rs b/tests/source/issue-1210/c.rs new file mode 100644 index 00000000000..c080cef950b --- /dev/null +++ b/tests/source/issue-1210/c.rs @@ -0,0 +1,5 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +const foo: String = "trailing_spaces!! + keep them! Amet neque. Praesent rhoncus eros non velit."; diff --git a/tests/source/issue-1210/d.rs b/tests/source/issue-1210/d.rs new file mode 100644 index 00000000000..783736bc3b2 --- /dev/null +++ b/tests/source/issue-1210/d.rs @@ -0,0 +1,4 @@ +// rustfmt-wrap_comments: true + +// trailing_spaces_in_comment!! +// remove those from above diff --git a/tests/source/issue-1210/e.rs b/tests/source/issue-1210/e.rs new file mode 100644 index 00000000000..9abada1d6d8 --- /dev/null +++ b/tests/source/issue-1210/e.rs @@ -0,0 +1,8 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +// explicit line breaks should be kept in order to preserve the layout + +const foo: String = "Suspendisse vel augue at felis tincidunt sollicitudin. Fusce arcu. + Duis et odio et leo + sollicitudin consequat. Aliquam lobortis. Phasellus condimentum."; diff --git a/tests/target/issue-1210/a.rs b/tests/target/issue-1210/a.rs new file mode 100644 index 00000000000..94c1b44e5e5 --- /dev/null +++ b/tests/target/issue-1210/a.rs @@ -0,0 +1,16 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +impl Foo { + fn cxx(&self, target: &str) -> &Path { + match self.cxx.get(target) { + Some(p) => p.path(), + None => panic!( + "\n\ntarget `{}` is not \ + configured as a host, + only as a target\n\n", + target + ), + } + } +} diff --git a/tests/target/issue-1210/b.rs b/tests/target/issue-1210/b.rs new file mode 100644 index 00000000000..a7b1e3bcdc8 --- /dev/null +++ b/tests/target/issue-1210/b.rs @@ -0,0 +1,16 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +impl Foo { + fn cxx(&self, target: &str) -> &Path { + match self.cxx.get(target) { + Some(p) => p.path(), + None => panic!( + "\ntarget `{}`: is not, \ + configured as a host, + only as a target\n\n", + target + ), + } + } +} diff --git a/tests/target/issue-1210/c.rs b/tests/target/issue-1210/c.rs new file mode 100644 index 00000000000..183d79f9258 --- /dev/null +++ b/tests/target/issue-1210/c.rs @@ -0,0 +1,7 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +const foo: String = + "trailing_spaces!! + keep them! Amet neque. Praesent \ + rhoncus eros non velit."; diff --git a/tests/target/issue-1210/d.rs b/tests/target/issue-1210/d.rs new file mode 100644 index 00000000000..9279e6fc999 --- /dev/null +++ b/tests/target/issue-1210/d.rs @@ -0,0 +1,4 @@ +// rustfmt-wrap_comments: true + +// trailing_spaces_in_comment!! +// remove those from above diff --git a/tests/target/issue-1210/e.rs b/tests/target/issue-1210/e.rs new file mode 100644 index 00000000000..55f80c6c3cc --- /dev/null +++ b/tests/target/issue-1210/e.rs @@ -0,0 +1,11 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 50 + +// explicit line breaks should be kept in order to preserve the layout + +const foo: String = + "Suspendisse vel augue at felis tincidunt \ + sollicitudin. Fusce arcu. + Duis et odio et leo + sollicitudin consequat. Aliquam \ + lobortis. Phasellus condimentum."; -- cgit 1.4.1-3-g733a5 From 86018133a02064e838404c94a860e57547a5a9ef Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 14 Jul 2018 19:17:07 +0200 Subject: removed unused max_width argument of rewrite_string function --- src/comment.rs | 4 ++-- src/expr.rs | 1 - src/string.rs | 10 +++------- 3 files changed, 5 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index f684a6291ff..53e496bf457 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -438,7 +438,7 @@ fn rewrite_comment_inner( } if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { - match rewrite_string(line, &fmt, Some(max_chars)) { + match rewrite_string(line, &fmt) { Some(ref s) => { is_prev_line_multi_line = s.contains('\n'); result.push_str(s); @@ -449,7 +449,7 @@ fn rewrite_comment_inner( result.pop(); result.push_str(&comment_line_separator); fmt.shape = Shape::legacy(max_chars, fmt_indent); - match rewrite_string(line, &fmt, Some(max_chars)) { + match rewrite_string(line, &fmt) { Some(ref s) => { is_prev_line_multi_line = s.contains('\n'); result.push_str(s); diff --git a/src/expr.rs b/src/expr.rs index c4675cbcdf7..6e1af266e9b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1229,7 +1229,6 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt rewrite_string( str_lit, &StringFormat::new(shape.visual_indent(0), context.config), - None, ) } diff --git a/src/string.rs b/src/string.rs index 387bee3cec9..fd7ac89013a 100644 --- a/src/string.rs +++ b/src/string.rs @@ -51,7 +51,7 @@ impl<'a> StringFormat<'a> { self.shape .width .checked_sub(self.opener.len() + self.line_end.len() + 1)? - + 1; + + 1, ) } @@ -63,11 +63,7 @@ impl<'a> StringFormat<'a> { } } -pub fn rewrite_string<'a>( - orig: &str, - fmt: &StringFormat<'a>, - max_width: Option, -) -> Option { +pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { let max_chars_with_indent = fmt.max_chars_with_indent()?; let max_chars_without_indent = fmt.max_chars_without_indent()?; let indent = fmt.shape.indent.to_string_with_newline(fmt.config); @@ -235,7 +231,7 @@ mod test { fn issue343() { let config = Default::default(); let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); - rewrite_string("eq_", &fmt, None); + rewrite_string("eq_", &fmt); } #[test] -- cgit 1.4.1-3-g733a5 From b28a0cd6e68e342aa026e25dcc651cb9bc5007f8 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 17 Jul 2018 15:38:50 +1200 Subject: Fix an anomaly with comments and array literals Closes #2842 --- src/lists.rs | 10 +++++----- tests/source/array_comment.rs | 19 +++++++++++++++++++ tests/target/array_comment.rs | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 tests/source/array_comment.rs create mode 100644 tests/target/array_comment.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index c415032ad67..0e3baa7c1e1 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -297,17 +297,15 @@ where if formatting.ends_with_newline { trailing_separator = true; } + } else if line_len > 0 { + result.push(' '); + line_len += 1; } if last && formatting.ends_with_newline { separate = formatting.trailing_separator != SeparatorTactic::Never; } - if line_len > 0 { - result.push(' '); - line_len += 1; - } - line_len += total_width; } _ => {} @@ -341,6 +339,8 @@ where } else { result.push('\n'); result.push_str(indent_str); + // This is the width of the item (without comments). + line_len = item.item.as_ref().map_or(0, |str| str.len()); } } else { result.push(' '); diff --git a/tests/source/array_comment.rs b/tests/source/array_comment.rs new file mode 100644 index 00000000000..87372b2793f --- /dev/null +++ b/tests/source/array_comment.rs @@ -0,0 +1,19 @@ +// Issue 2842 +// The comment should not make the last line shorter + +static XXX: [i8; 64] = [ + 1, // Comment + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; + +static XXX: [i8; 64] = [ + 1, + // Comment + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; + +static XXX: [i8; 64] = [ + 1, + // Comment + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; diff --git a/tests/target/array_comment.rs b/tests/target/array_comment.rs new file mode 100644 index 00000000000..93e1f5f4034 --- /dev/null +++ b/tests/target/array_comment.rs @@ -0,0 +1,18 @@ +// Issue 2842 +// The comment should not make the last line shorter + +static XXX: [i8; 64] = [ + 1, // Comment + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; + +static XXX: [i8; 64] = [ + 1, // Comment + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; + +static XXX: [i8; 64] = [ + 1, // Comment + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, +]; -- cgit 1.4.1-3-g733a5 From c2ae39e77a869836eae0403ac92245154a25379e Mon Sep 17 00:00:00 2001 From: Michael Bebenita Date: Tue, 17 Jul 2018 13:17:04 -0400 Subject: Add max_width option for all heuristics. This is useful when working with very small max_widths like 79 chars. --- Configurations.md | 20 ++++++++++++++++++- src/config/config_type.rs | 3 +++ src/config/options.rs | 13 ++++++++++++ tests/source/configs/use_small_heuristics/max.rs | 25 ++++++++++++++++++++++++ tests/target/configs/use_small_heuristics/max.rs | 15 ++++++++++++++ 5 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/source/configs/use_small_heuristics/max.rs create mode 100644 tests/target/configs/use_small_heuristics/max.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 58740d0fb90..2a9df314417 100644 --- a/Configurations.md +++ b/Configurations.md @@ -276,7 +276,7 @@ fn lorem() -> T Whether to use different formatting for items and expressions if they satisfy a heuristic notion of 'small'. - **Default value**: `Default` -- **Possible values**: `Default`, `Off` +- **Possible values**: `Default`, `Off`, `Max` - **Stable**: Yes #### `Default` (default): @@ -337,6 +337,24 @@ fn main() { } ``` +#### `Max`: + +```rust +enum Lorem { + Ipsum, + Dolor(bool), + Sit { amet: Consectetur, adipiscing: Elit }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { ipsum: dolor, sit: amet }; + + let lorem = if ipsum { dolor } else { sit }; +} +``` + ## `binop_separator` Where to put a binary operator when a binary expression goes multiline. diff --git a/src/config/config_type.rs b/src/config/config_type.rs index ddb063feeab..82cf0e19a8f 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -403,6 +403,9 @@ macro_rules! create_config { if self.use_small_heuristics.2 == Heuristics::Default { let max_width = self.max_width.2; self.set().width_heuristics(WidthHeuristics::scaled(max_width)); + } else if self.use_small_heuristics.2 == Heuristics::Max { + let max_width = self.max_width.2; + self.set().width_heuristics(WidthHeuristics::set(max_width)); } else { self.set().width_heuristics(WidthHeuristics::null()); } diff --git a/src/config/options.rs b/src/config/options.rs index 5fa0a048313..a581cdef43d 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -154,6 +154,8 @@ configuration_option_enum! { TypeDensity: configuration_option_enum! { Heuristics: // Turn off any heuristics Off, + // Turn on max heuristics + Max, // Use Rustfmt's defaults Default, } @@ -257,6 +259,17 @@ impl WidthHeuristics { } } + pub fn set(max_width: usize) -> WidthHeuristics { + WidthHeuristics { + fn_call_width: max_width, + struct_lit_width: max_width, + struct_variant_width: max_width, + array_width: max_width, + chain_width: max_width, + single_line_if_else_max_width: max_width, + } + } + // scale the default WidthHeuristics according to max_width pub fn scaled(max_width: usize) -> WidthHeuristics { const DEFAULT_MAX_WIDTH: usize = 100; diff --git a/tests/source/configs/use_small_heuristics/max.rs b/tests/source/configs/use_small_heuristics/max.rs new file mode 100644 index 00000000000..8d30932e2c2 --- /dev/null +++ b/tests/source/configs/use_small_heuristics/max.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Max + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} diff --git a/tests/target/configs/use_small_heuristics/max.rs b/tests/target/configs/use_small_heuristics/max.rs new file mode 100644 index 00000000000..785dfbea014 --- /dev/null +++ b/tests/target/configs/use_small_heuristics/max.rs @@ -0,0 +1,15 @@ +// rustfmt-use_small_heuristics: Max + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { amet: Consectetur, adipiscing: Elit }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { ipsum: dolor, sit: amet }; + + let lorem = if ipsum { dolor } else { sit }; +} -- cgit 1.4.1-3-g733a5 From b27d544478e5e70c18b74f84310c6ad43d7b7a86 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 Jul 2018 09:16:51 +1200 Subject: `replace_with_system_newlines` doesn't need to be public --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index e2a80525312..b856c66dd71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -930,7 +930,7 @@ fn format_input_inner( } } -pub fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { +fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { let style = if config.newline_style() == NewlineStyle::Native { if cfg!(windows) { NewlineStyle::Windows -- cgit 1.4.1-3-g733a5 From 79c5ee8b42fe93f7432108fc0a656fc728f10c1d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 Jul 2018 12:03:59 +1200 Subject: Add config options for formatting macro matchers and bodies Closes #2753 --- Configurations.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/config/mod.rs | 27 +++++++++++---------- src/macros.rs | 26 ++++++++++++++++++--- 3 files changed, 108 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 2a9df314417..a0e3e63c74e 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1006,6 +1006,76 @@ fn main() { See also [`max_width`](#max_width). +## `format_macro_matchers` + +Format the metavariable matching patterns in macros. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): + +```rust +macro_rules! foo { + ($a: ident : $b: ty) => { + $a(42): $b; + }; + ($a: ident $b: ident $c: ident) => { + $a = $b + $c; + }; +} +``` + +#### `true`: + +```rust +macro_rules! foo { + ($a:ident : $b:ty) => { + $a(42): $b; + }; + ($a:ident $b:ident $c:ident) => { + $a = $b + $c; + }; +} +``` + +See also [`format_macro_bodies`](#format_macro_bodies). + + +## `format_macro_bodies` + +Format the bodies of macros. + +- **Default value**: `true` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `true` (default): + +```rust +macro_rules! foo { + ($a:ident : $b:ty) => { + $a(42): $b; + }; + ($a:ident $b:ident $c:ident) => { + $a = $b + $c; + }; +} +``` + +#### `false`: + +```rust +macro_rules! foo { + ($a:ident : $b:ty) => { $a(42): $b; }; + ($a:ident $b:ident $c:ident) => { $a=$b+$c; }; +} +``` + +See also [`format_macro_matchers`](#format_macro_matchers). + + ## `hard_tabs` Use tab characters for indentation, spaces for alignment diff --git a/src/config/mod.rs b/src/config/mod.rs index baf1982639c..af344a8720a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -42,10 +42,10 @@ create_config! { tab_spaces: usize, 4, true, "Number of spaces per tab"; newline_style: NewlineStyle, NewlineStyle::Native, true, "Unix or Windows line endings"; use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ - formatting for items and expressions if they satisfy a heuristic notion of 'small'."; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items."; + formatting for items and expressions if they satisfy a heuristic notion of 'small'"; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; - // Comments and strings + // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; @@ -53,6 +53,9 @@ create_config! { license_template_path: String, String::default(), false, "Beginning of file must match license template"; format_strings: bool, false, false, "Format string literals where necessary"; + format_macro_matchers: bool, true, false, + "Format the metavariable matching patterns in macros"; + format_macro_bodies: bool, true, false, "Format the bodies of macros"; // Single line expressions and items empty_item_single_line: bool, true, false, @@ -79,13 +82,13 @@ create_config! { space_after_colon: bool, true, false, "Leave a space after the colon"; spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators"; binop_separator: SeparatorPlace, SeparatorPlace::Front, false, - "Where to put a binary operator when a binary expression goes multiline."; + "Where to put a binary operator when a binary expression goes multiline"; // Misc. - remove_nested_parens: bool, true, true, "Remove nested parens."; - combine_control_expr: bool, true, false, "Combine control expressions with function calls."; + remove_nested_parens: bool, true, true, "Remove nested parens"; + combine_control_expr: bool, true, false, "Combine control expressions with function calls"; struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ - threshold."; + threshold"; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; force_multiline_blocks: bool, false, false, @@ -101,10 +104,10 @@ create_config! { match_block_trailing_comma: bool, false, false, "Put a trailing comma after a block based match arm (non-block arms are not affected)"; blank_lines_upper_bound: usize, 1, false, - "Maximum number of blank lines which can be put between items."; + "Maximum number of blank lines which can be put between items"; blank_lines_lower_bound: usize, 0, false, - "Minimum number of blank lines which must be put between items."; - edition: Edition, Edition::Edition2015, false, "The edition of the parser. (RFC 2052)"; + "Minimum number of blank lines which must be put between items"; + edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; @@ -118,7 +121,7 @@ create_config! { color: Color, Color::Auto, false, "What Color option to use when none is supplied: Always, Never, Auto"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, - "Require a specific version of rustfmt."; + "Require a specific version of rustfmt"; unstable_features: bool, false, false, "Enables unstable features. Only available on nightly channel"; disable_all_formatting: bool, false, false, "Don't reformat anything"; @@ -133,7 +136,7 @@ create_config! { report_fixme: ReportTactic, ReportTactic::Never, false, "Report all, none or unnumbered occurrences of FIXME in source file comments"; ignore: IgnoreList, IgnoreList::default(), false, - "Skip formatting the specified files and directories."; + "Skip formatting the specified files and directories"; // Not user-facing verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user"; diff --git a/src/macros.rs b/src/macros.rs index 76f50b30a54..4f3891fbf49 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -938,10 +938,22 @@ fn format_macro_args( toks: ThinTokenStream, shape: Shape, ) -> Option { + if !context.config.format_macro_matchers() { + let token_stream: TokenStream = toks.into(); + let span = span_for_token_stream(token_stream); + return Some(match span { + Some(span) => context.snippet(span).to_owned(), + None => String::new(), + }); + } let parsed_args = MacroArgParser::new().parse(toks)?; wrap_macro_args(context, &parsed_args, shape) } +fn span_for_token_stream(token_stream: TokenStream) -> Option { + token_stream.trees().next().map(|tt| tt.span()) +} + // We should insert a space if the next token is a: #[derive(Copy, Clone, PartialEq)] enum SpaceState { @@ -1172,13 +1184,14 @@ impl MacroParser { TokenTree::Token(_, Token::FatArrow) => {} _ => return None, } - let (mut hi, body) = match self.toks.next()? { + let (mut hi, body, whole_body) = match self.toks.next()? { TokenTree::Token(..) => return None, TokenTree::Delimited(sp, _) => { let data = sp.data(); ( data.hi, Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), + sp, ) } }; @@ -1191,6 +1204,7 @@ impl MacroParser { args_paren_kind, args, body, + whole_body, }) } } @@ -1207,6 +1221,7 @@ struct MacroBranch { args_paren_kind: DelimToken, args: ThinTokenStream, body: Span, + whole_body: Span, } impl MacroBranch { @@ -1229,6 +1244,12 @@ impl MacroBranch { result += " =>"; } + if !context.config.format_macro_bodies() { + result += " "; + result += context.snippet(self.whole_body); + return Some(result); + } + // The macro body is the most interesting part. It might end up as various // AST nodes, but also has special variables (e.g, `$foo`) which can't be // parsed as regular Rust code (and note that these can be escaped using @@ -1237,14 +1258,13 @@ impl MacroBranch { let old_body = context.snippet(self.body).trim(); let (body_str, substs) = replace_names(old_body)?; + let has_block_body = old_body.starts_with('{'); let mut config = context.config.clone(); config.set().hide_parse_errors(true); result += " {"; - let has_block_body = old_body.starts_with('{'); - let body_indent = if has_block_body { shape.indent } else { -- cgit 1.4.1-3-g733a5 From 90c5792565d937b871d0767dd4fbfc317afab707 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 18 Jul 2018 12:09:50 +1200 Subject: Set rustfmt-format_macro_matchers to false by default cc #2543 --- Configurations.md | 8 ++++---- src/config/mod.rs | 2 +- tests/source/macro_rules.rs | 1 + tests/source/macros.rs | 1 + tests/target/macro_rules.rs | 2 ++ tests/target/macros.rs | 1 + 6 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index a0e3e63c74e..403154ea6d8 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1055,10 +1055,10 @@ Format the bodies of macros. ```rust macro_rules! foo { - ($a:ident : $b:ty) => { + ($a: ident : $b: ty) => { $a(42): $b; }; - ($a:ident $b:ident $c:ident) => { + ($a: ident $b: ident $c: ident) => { $a = $b + $c; }; } @@ -1068,8 +1068,8 @@ macro_rules! foo { ```rust macro_rules! foo { - ($a:ident : $b:ty) => { $a(42): $b; }; - ($a:ident $b:ident $c:ident) => { $a=$b+$c; }; + ($a: ident : $b: ty) => { $a(42): $b; }; + ($a: ident $b: ident $c: ident) => { $a=$b+$c; }; } ``` diff --git a/src/config/mod.rs b/src/config/mod.rs index af344a8720a..ba6596c3da7 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -53,7 +53,7 @@ create_config! { license_template_path: String, String::default(), false, "Beginning of file must match license template"; format_strings: bool, false, false, "Format string literals where necessary"; - format_macro_matchers: bool, true, false, + format_macro_matchers: bool, false, false, "Format the metavariable matching patterns in macros"; format_macro_bodies: bool, true, false, "Format the bodies of macros"; diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index b6ff049430d..e8f9aa505ac 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -1,3 +1,4 @@ +// rustfmt-format_macro_matchers: true macro_rules! m { () => (); diff --git a/tests/source/macros.rs b/tests/source/macros.rs index b44162be7d1..10a207009b7 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_macro_matchers: true itemmacro!(this, is.now() .formatted(yay)); itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 41bc1420476..4f31519faaf 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -1,3 +1,5 @@ +// rustfmt-format_macro_matchers: true + macro_rules! m { () => {}; ($x:ident) => {}; diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 41324e04af1..00b91ca81a2 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_macro_matchers: true itemmacro!(this, is.now().formatted(yay)); itemmacro!( -- cgit 1.4.1-3-g733a5 From 6899471497614d73f8bc13ac074d7624b4554091 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Jul 2018 14:27:56 +1200 Subject: Check for comments after the `=>` in a match arm Closes #2188 --- rustfmt.toml | 2 +- src/matches.rs | 70 +++++++++++++++++++++++++---------- tests/target/comment-not-disappear.rs | 4 +- 3 files changed, 54 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/rustfmt.toml b/rustfmt.toml index c1f797409c3..6abb5a9ef6d 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,3 @@ error_on_line_overflow = true error_on_unformatted = true -edition = "Edition2018" \ No newline at end of file +edition = "Edition2018" diff --git a/src/matches.rs b/src/matches.rs index 201e10d5ccf..791f34cefe8 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -17,7 +17,7 @@ use syntax::codemap::{BytePos, Span}; use syntax::{ast, ptr}; use codemap::SpanUtils; -use comment::combine_strs_with_missing_comments; +use comment::{combine_strs_with_missing_comments, rewrite_comment}; use config::{Config, ControlBraceStyle, IndentStyle}; use expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, @@ -267,12 +267,15 @@ fn rewrite_match_arm( false, ) })?; + + let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span.lo()); rewrite_match_body( context, &arm.body, &pats_str, shape, arm.guard.is_some(), + arrow_span, is_last, ) } @@ -345,6 +348,7 @@ fn rewrite_match_body( pats_str: &str, shape: Shape, has_guard: bool, + arrow_span: Span, is_last: bool, ) -> Option { let (extend, body) = flatten_arm_body(context, body); @@ -369,24 +373,43 @@ fn rewrite_match_body( Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma)) }; - let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; let next_line_indent = if !is_block || is_empty_block { shape.indent.block_indent(context.config) } else { shape.indent }; + + let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; + + // Look for comments between `=>` and the start of the body. + let arrow_comment = { + let arrow_snippet = context.snippet(arrow_span).trim(); + let arrow_index = arrow_snippet.find("=>").unwrap(); + // 2 = `=>` + let comment_str = arrow_snippet[arrow_index + 2..].trim(); + if comment_str.is_empty() { + String::new() + } else { + rewrite_comment(comment_str, false, shape, &context.config)? + } + }; + let combine_next_line_body = |body_str: &str| { + let nested_indent_str = next_line_indent.to_string_with_newline(context.config); + if is_block { - return Some(format!( - "{} =>{}{}", - pats_str, - next_line_indent.to_string_with_newline(context.config), - body_str - )); + let mut result = pats_str.to_owned(); + result.push_str(" =>"); + if !arrow_comment.is_empty() { + result.push_str(&nested_indent_str); + result.push_str(&arrow_comment); + } + result.push_str(&nested_indent_str); + result.push_str(&body_str); + return Some(result); } let indent_str = shape.indent.to_string_with_newline(context.config); - let nested_indent_str = next_line_indent.to_string_with_newline(context.config); let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { let comma = if context.config.match_block_trailing_comma() { "," @@ -401,14 +424,22 @@ fn rewrite_match_body( let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), _ if body_prefix.is_empty() => "".to_owned(), - _ if forbid_same_line => format!("{}{}", alt_block_sep, body_prefix), + _ if forbid_same_line || !arrow_comment.is_empty() => { + format!("{}{}", alt_block_sep, body_prefix) + } _ => format!(" {}", body_prefix), } + &nested_indent_str; - Some(format!( - "{} =>{}{}{}", - pats_str, block_sep, body_str, body_suffix - )) + let mut result = pats_str.to_owned(); + result.push_str(" =>"); + if !arrow_comment.is_empty() { + result.push_str(&indent_str); + result.push_str(&arrow_comment); + } + result.push_str(&block_sep); + result.push_str(&body_str); + result.push_str(&body_suffix); + Some(result) }; // Let's try and get the arm body on the same line as the condition. @@ -416,7 +447,9 @@ fn rewrite_match_body( let orig_body_shape = shape .offset_left(extra_offset(pats_str, shape) + 4) .and_then(|shape| shape.sub_width(comma.len())); - let orig_body = if let Some(body_shape) = orig_body_shape { + let orig_body = if forbid_same_line || !arrow_comment.is_empty() { + None + } else if let Some(body_shape) = orig_body_shape { let rewrite = nop_block_collapse( format_expr(body, ExprType::Statement, context, body_shape), body_shape.width, @@ -424,9 +457,7 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if !forbid_same_line - && (is_block - || (!body_str.contains('\n') && body_str.len() <= body_shape.width)) => + if is_block || (!body_str.contains('\n') && body_str.len() <= body_shape.width) => { return combine_orig_body(body_str); } @@ -445,8 +476,7 @@ fn rewrite_match_body( ); match (orig_body, next_line_body) { (Some(ref orig_str), Some(ref next_line_str)) - if forbid_same_line - || prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => + if prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { combine_next_line_body(next_line_str) } diff --git a/tests/target/comment-not-disappear.rs b/tests/target/comment-not-disappear.rs index 646b37e46e2..b1fa0ff6fe1 100644 --- a/tests/target/comment-not-disappear.rs +++ b/tests/target/comment-not-disappear.rs @@ -11,8 +11,10 @@ fn a() { fn b() { match x { X => - // A comment + // A comment + { y + } } } -- cgit 1.4.1-3-g733a5 From b085113cbe77b558624bbd2acb098956f5d6f266 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 20 Jul 2018 14:42:48 +1200 Subject: Trigger an internal error if we skip formatting due to a lost comment --- src/comment.rs | 13 ++++++++++++- src/lib.rs | 28 ++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 53e496bf457..3d55f6560e3 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -20,6 +20,7 @@ use rewrite::RewriteContext; use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; use utils::{count_newlines, first_line_width, last_line_width}; +use {ErrorKind, FormattingError}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { @@ -1124,7 +1125,17 @@ pub fn recover_comment_removed( ) -> Option { let snippet = context.snippet(span); if snippet != new && changed_comment_content(snippet, &new) { - // We missed some comments. Keep the original text. + // We missed some comments. Warn and keep the original text. + if context.config.error_on_unformatted() { + context.report.append( + context.codemap.span_to_filename(span).into(), + vec![FormattingError::from_span( + &span, + &context.codemap, + ErrorKind::LostComment, + )], + ); + } Some(snippet.to_owned()) } else { Some(new) diff --git a/src/lib.rs b/src/lib.rs index b856c66dd71..820134c2085 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -140,8 +140,20 @@ pub enum ErrorKind { ParseError, /// The user mandated a version and the current version of Rustfmt does not /// satisfy that requirement. - #[fail(display = "Version mismatch")] + #[fail(display = "version mismatch")] VersionMismatch, + /// If we had formatted the given node, then we would have lost a comment. + #[fail(display = "not formatted because a comment would be lost")] + LostComment, +} + +impl ErrorKind { + fn is_comment(&self) -> bool { + match self { + ErrorKind::LostComment => true, + _ => false, + } + } } impl From for ErrorKind { @@ -162,8 +174,8 @@ impl FormattingError { fn from_span(span: &Span, codemap: &CodeMap, kind: ErrorKind) -> FormattingError { FormattingError { line: codemap.lookup_char_pos(span.lo()).line, + is_comment: kind.is_comment(), kind, - is_comment: false, is_string: false, line_buffer: codemap .span_to_lines(*span) @@ -181,7 +193,8 @@ impl FormattingError { ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace | ErrorKind::IoError(_) - | ErrorKind::ParseError => "internal error:", + | ErrorKind::ParseError + | ErrorKind::LostComment => "internal error:", ErrorKind::LicenseCheck | ErrorKind::BadAttr | ErrorKind::VersionMismatch => "error:", ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", } @@ -200,7 +213,10 @@ impl FormattingError { fn format_len(&self) -> (usize, usize) { match self.kind { ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace | ErrorKind::DeprecatedAttr | ErrorKind::BadAttr => { + ErrorKind::TrailingWhitespace + | ErrorKind::DeprecatedAttr + | ErrorKind::BadAttr + | ErrorKind::LostComment => { let trailing_ws_start = self .line_buffer .rfind(|c: char| !c.is_whitespace()) @@ -501,7 +517,7 @@ fn should_report_error( is_string: bool, error_kind: &ErrorKind, ) -> bool { - let allow_error_report = if char_kind.is_comment() || is_string { + let allow_error_report = if char_kind.is_comment() || is_string || error_kind.is_comment() { config.error_on_unformatted() } else { true @@ -509,7 +525,7 @@ fn should_report_error( match error_kind { ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, - ErrorKind::TrailingWhitespace => allow_error_report, + ErrorKind::TrailingWhitespace | ErrorKind::LostComment => allow_error_report, _ => true, } } -- cgit 1.4.1-3-g733a5 From d40ed146a5eec39b277514b1d5d48d927934768a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 20 Jul 2018 16:18:45 +0900 Subject: Fix breaking changes cc https://github.com/rust-lang/rust/pull/51829. --- src/closures.rs | 18 +++++++++++++++++- src/imports.rs | 7 ++----- src/utils.rs | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 42b883589db..783ca1c029b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -118,6 +118,22 @@ fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bo || prefix.contains('\n') } +fn veto_block(e: &ast::Expr) -> bool { + match e.node { + ast::ExprKind::Call(..) + | ast::ExprKind::Binary(..) + | ast::ExprKind::Cast(..) + | ast::ExprKind::Type(..) + | ast::ExprKind::Assign(..) + | ast::ExprKind::AssignOp(..) + | ast::ExprKind::Field(..) + | ast::ExprKind::Index(..) + | ast::ExprKind::Range(..) + | ast::ExprKind::Try(..) => true, + _ => false, + } +} + // Rewrite closure with a single expression wrapping its body with block. fn rewrite_closure_with_block( body: &ast::Expr, @@ -126,7 +142,7 @@ fn rewrite_closure_with_block( shape: Shape, ) -> Option { let left_most = left_most_sub_expr(body); - let veto_block = left_most != body && !classify::expr_requires_semi_to_be_stmt(left_most); + let veto_block = veto_block(body) && !classify::expr_requires_semi_to_be_stmt(left_most); if veto_block { return None; } diff --git a/src/imports.rs b/src/imports.rs index ddb7262430d..79d0641504e 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -21,7 +21,7 @@ use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListIte use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{mk_sp, rewrite_ident}; +use utils::{is_same_visibility, mk_sp, rewrite_ident}; use visitor::FmtVisitor; use std::borrow::Cow; @@ -485,10 +485,7 @@ impl UseTree { }), ) | (None, None) => true, - ( - Some(codemap::Spanned { node: lnode, .. }), - Some(codemap::Spanned { node: rnode, .. }), - ) => lnode == rnode, + (Some(ref a), Some(ref b)) => is_same_visibility(a, b), _ => false, } } diff --git a/src/utils.rs b/src/utils.rs index 99275b52dc1..f1b0582b120 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -37,6 +37,26 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize { } } +pub fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { + match (&a.node, &b.node) { + ( + VisibilityKind::Restricted { path: p, .. }, + VisibilityKind::Restricted { path: q, .. }, + ) => format!("{}", p) == format!("{}", q), + (VisibilityKind::Public, VisibilityKind::Public) + | (VisibilityKind::Inherited, VisibilityKind::Inherited) + | ( + VisibilityKind::Crate(CrateSugar::PubCrate), + VisibilityKind::Crate(CrateSugar::PubCrate), + ) + | ( + VisibilityKind::Crate(CrateSugar::JustCrate), + VisibilityKind::Crate(CrateSugar::JustCrate), + ) => true, + _ => false, + } +} + // Uses Cow to avoid allocating in the common cases. pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'static, str> { match vis.node { -- cgit 1.4.1-3-g733a5 From 4153e66e422fde262bac3d36b82e79af69d01f2d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Jul 2018 12:45:41 +1200 Subject: Move non-public API from lib.rs to its own module --- src/filemap.rs | 2 +- src/formatting.rs | 593 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 639 +++--------------------------------------------------- src/test/mod.rs | 10 +- 4 files changed, 631 insertions(+), 613 deletions(-) create mode 100644 src/formatting.rs (limited to 'src') diff --git a/src/filemap.rs b/src/filemap.rs index f64e428c221..20140321032 100644 --- a/src/filemap.rs +++ b/src/filemap.rs @@ -16,7 +16,7 @@ use config::{Config, EmitMode, FileName, Verbosity}; use rustfmt_diff::{make_diff, output_modified, print_diff}; #[cfg(test)] -use FileRecord; +use formatting::FileRecord; // Append a newline to the end of each file. pub fn append_newline(s: &mut String) { diff --git a/src/formatting.rs b/src/formatting.rs new file mode 100644 index 00000000000..95e2b08e3fe --- /dev/null +++ b/src/formatting.rs @@ -0,0 +1,593 @@ +// High level formatting functions. + +use std::collections::HashMap; +use std::io::{self, Write}; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::rc::Rc; +use std::time::Duration; + +use syntax::ast; +use syntax::codemap::{CodeMap, FilePathMapping, Span}; +use syntax::errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::errors::{DiagnosticBuilder, Handler}; +use syntax::parse::{self, ParseSess}; + +use comment::{CharClasses, FullCodeCharKind}; +use issues::BadIssueSeeker; +use visitor::{FmtVisitor, SnippetProvider}; +use {filemap, modules, ErrorKind, FormatReport, Input}; + +use config::summary::Summary; +use config::{Config, FileName, NewlineStyle, Verbosity}; + +// A map of the files of a crate, with their new content +pub(crate) type FileMap = Vec; + +pub(crate) type FileRecord = (FileName, String); + +pub(crate) struct FormattingError { + pub(crate) line: usize, + pub(crate) kind: ErrorKind, + is_comment: bool, + is_string: bool, + pub(crate) line_buffer: String, +} + +impl FormattingError { + pub(crate) fn from_span(span: &Span, codemap: &CodeMap, kind: ErrorKind) -> FormattingError { + FormattingError { + line: codemap.lookup_char_pos(span.lo()).line, + is_comment: kind.is_comment(), + kind, + is_string: false, + line_buffer: codemap + .span_to_lines(*span) + .ok() + .and_then(|fl| { + fl.file + .get_line(fl.lines[0].line_index) + .map(|l| l.into_owned()) + }) + .unwrap_or_else(|| String::new()), + } + } + + pub(crate) fn msg_prefix(&self) -> &str { + match self.kind { + ErrorKind::LineOverflow(..) + | ErrorKind::TrailingWhitespace + | ErrorKind::IoError(_) + | ErrorKind::ParseError + | ErrorKind::LostComment => "internal error:", + ErrorKind::LicenseCheck | ErrorKind::BadAttr | ErrorKind::VersionMismatch => "error:", + ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", + } + } + + pub(crate) fn msg_suffix(&self) -> &str { + if self.is_comment || self.is_string { + "set `error_on_unformatted = false` to suppress \ + the warning against comments or string literals\n" + } else { + "" + } + } + + // (space, target) + pub(crate) fn format_len(&self) -> (usize, usize) { + match self.kind { + ErrorKind::LineOverflow(found, max) => (max, found - max), + ErrorKind::TrailingWhitespace + | ErrorKind::DeprecatedAttr + | ErrorKind::BadAttr + | ErrorKind::LostComment => { + let trailing_ws_start = self + .line_buffer + .rfind(|c: char| !c.is_whitespace()) + .map(|pos| pos + 1) + .unwrap_or(0); + ( + trailing_ws_start, + self.line_buffer.len() - trailing_ws_start, + ) + } + _ => unreachable!(), + } + } +} + +pub(crate) type FormatErrorMap = HashMap>; + +#[derive(Default, Debug)] +pub(crate) struct ReportedErrors { + pub(crate) has_operational_errors: bool, + pub(crate) has_check_errors: bool, +} + +fn should_emit_verbose(path: &FileName, config: &Config, f: F) +where + F: Fn(), +{ + if config.verbose() == Verbosity::Verbose && path != &FileName::Stdin { + f(); + } +} + +// Formatting which depends on the AST. +fn format_ast( + krate: &ast::Crate, + parse_session: &mut ParseSess, + main_file: &FileName, + config: &Config, + report: FormatReport, + mut after_file: F, +) -> Result<(FileMap, bool, bool), io::Error> +where + F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result, +{ + let mut result = FileMap::new(); + // diff mode: check if any files are differing + let mut has_diff = false; + let mut has_macro_rewrite_failure = false; + + let skip_children = config.skip_children(); + for (path, module) in modules::list_files(krate, parse_session.codemap())? { + if (skip_children && path != *main_file) || config.ignore().skip_file(&path) { + continue; + } + should_emit_verbose(&path, config, || println!("Formatting {}", path)); + let filemap = parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = + FmtVisitor::from_codemap(parse_session, config, &snippet_provider, report.clone()); + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == *main_file { + visitor.skip_empty_lines(filemap.end_pos); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); + } else { + visitor.format_separate_mod(module, &*filemap); + } + } else { + visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); + visitor.format_separate_mod(module, &*filemap); + }; + + debug_assert_eq!( + visitor.line_number, + ::utils::count_newlines(&visitor.buffer) + ); + + has_diff |= match after_file(&path, &mut visitor.buffer, &visitor.skipped_range, &report) { + Ok(result) => result, + Err(e) => { + // Create a new error with path_str to help users see which files failed + let err_msg = format!("{}: {}", path, e); + return Err(io::Error::new(e.kind(), err_msg)); + } + }; + + has_macro_rewrite_failure |= visitor.macro_rewrite_failure; + + result.push((path.clone(), visitor.buffer)); + } + + Ok((result, has_diff, has_macro_rewrite_failure)) +} + +/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. +fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { + skipped_range + .iter() + .any(|&(lo, hi)| lo <= line_number && line_number <= hi) +} + +fn should_report_error( + config: &Config, + char_kind: FullCodeCharKind, + is_string: bool, + error_kind: &ErrorKind, +) -> bool { + let allow_error_report = if char_kind.is_comment() || is_string || error_kind.is_comment() { + config.error_on_unformatted() + } else { + true + }; + + match error_kind { + ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, + ErrorKind::TrailingWhitespace | ErrorKind::LostComment => allow_error_report, + _ => true, + } +} + +// Formatting done on a char by char or line by line basis. +// FIXME(#20) other stuff for parity with make tidy +fn format_lines( + text: &mut String, + name: &FileName, + skipped_range: &[(usize, usize)], + config: &Config, + report: &FormatReport, +) { + let mut last_was_space = false; + let mut line_len = 0; + let mut cur_line = 1; + let mut newline_count = 0; + let mut errors = vec![]; + let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); + let mut line_buffer = String::with_capacity(config.max_width() * 2); + let mut is_string = false; // true if the current line contains a string literal. + let mut format_line = config.file_lines().contains_line(name, cur_line); + let allow_issue_seek = !issue_seeker.is_disabled(); + + // Check license. + if let Some(ref license_template) = config.license_template { + if !license_template.is_match(text) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::LicenseCheck, + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); + } + } + + // Iterate over the chars in the file map. + for (kind, c) in CharClasses::new(text.chars()) { + if c == '\r' { + continue; + } + + if allow_issue_seek && format_line { + // Add warnings for bad todos/ fixmes + if let Some(issue) = issue_seeker.inspect(c) { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::BadIssue(issue), + is_comment: false, + is_string: false, + line_buffer: String::new(), + }); + } + } + + if c == '\n' { + if format_line { + // Check for (and record) trailing whitespace. + if last_was_space { + if should_report_error(config, kind, is_string, &ErrorKind::TrailingWhitespace) + && !is_skipped_line(cur_line, skipped_range) + { + errors.push(FormattingError { + line: cur_line, + kind: ErrorKind::TrailingWhitespace, + is_comment: kind.is_comment(), + is_string: kind.is_string(), + line_buffer: line_buffer.clone(), + }); + } + line_len -= 1; + } + + // Check for any line width errors we couldn't correct. + let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); + if line_len > config.max_width() + && !is_skipped_line(cur_line, skipped_range) + && should_report_error(config, kind, is_string, &error_kind) + { + errors.push(FormattingError { + line: cur_line, + kind: error_kind, + is_comment: kind.is_comment(), + is_string, + line_buffer: line_buffer.clone(), + }); + } + } + + line_len = 0; + cur_line += 1; + format_line = config.file_lines().contains_line(name, cur_line); + newline_count += 1; + last_was_space = false; + line_buffer.clear(); + is_string = false; + } else { + newline_count = 0; + line_len += if c == '\t' { config.tab_spaces() } else { 1 }; + last_was_space = c.is_whitespace(); + line_buffer.push(c); + if kind.is_string() { + is_string = true; + } + } + } + + if newline_count > 1 { + debug!("track truncate: {} {}", text.len(), newline_count); + let line = text.len() - newline_count + 1; + text.truncate(line); + } + + report.append(name.clone(), errors); +} + +fn parse_input<'sess>( + input: Input, + parse_session: &'sess ParseSess, + config: &Config, +) -> Result> { + let mut parser = match input { + Input::File(file) => parse::new_parser_from_file(parse_session, &file), + Input::Text(text) => parse::new_parser_from_source_str( + parse_session, + syntax::codemap::FileName::Custom("stdin".to_owned()), + text, + ), + }; + + parser.cfg_mods = false; + if config.skip_children() { + parser.recurse_into_file_modules = false; + } + + let mut parser = AssertUnwindSafe(parser); + let result = catch_unwind(move || parser.0.parse_crate_mod()); + + match result { + Ok(Ok(c)) => { + if parse_session.span_diagnostic.has_errors() { + // Bail out if the parser recovered from an error. + Err(ParseError::Recovered) + } else { + Ok(c) + } + } + Ok(Err(e)) => Err(ParseError::Error(e)), + Err(_) => Err(ParseError::Panic), + } +} + +/// All the ways that parsing can fail. +enum ParseError<'sess> { + /// There was an error, but the parser recovered. + Recovered, + /// There was an error (supplied) and parsing failed. + Error(DiagnosticBuilder<'sess>), + /// The parser panicked. + Panic, +} + +pub(crate) fn format_input_inner( + input: Input, + config: &Config, + mut out: Option<&mut T>, +) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> { + syntax_pos::hygiene::set_default_edition(config.edition().to_libsyntax_pos_edition()); + let mut summary = Summary::default(); + if config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err((From::from(e), summary)); + } + } + return Ok((summary, FileMap::new(), FormatReport::new())); + } + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + + let tty_handler = if config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; + let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + + let main_file = match input { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Stdin, + }; + + let krate = match parse_input(input, &parse_session, config) { + Ok(krate) => krate, + Err(err) => { + match err { + ParseError::Error(mut diagnostic) => diagnostic.emit(), + ParseError::Panic => { + // Note that if you see this message and want more information, + // then go to `parse_input` and run the parse function without + // `catch_unwind` so rustfmt panics and you can get a backtrace. + should_emit_verbose(&main_file, config, || { + println!("The Rust parser panicked") + }); + } + ParseError::Recovered => {} + } + summary.add_parsing_error(); + return Err((ErrorKind::ParseError, summary)); + } + }; + + summary.mark_parse_time(); + + // Suppress error output after parsing. + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + + let report = FormatReport::new(); + + let format_result = format_ast( + &krate, + &mut parse_session, + &main_file, + config, + report.clone(), + |file_name, file, skipped_range, report| { + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(file); + + format_lines(file, file_name, skipped_range, config, report); + replace_with_system_newlines(file, config); + + if let Some(ref mut out) = out { + return filemap::write_file(file, file_name, out, config); + } + Ok(false) + }, + ); + + summary.mark_format_time(); + + should_emit_verbose(&main_file, config, || { + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } + + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + duration_to_f32(summary.get_parse_time().unwrap()), + duration_to_f32(summary.get_format_time().unwrap()), + ) + }); + + { + let report_errs = &report.internal.borrow().1; + if report_errs.has_check_errors { + summary.add_check_error(); + } + if report_errs.has_operational_errors { + summary.add_operational_error(); + } + } + + match format_result { + Ok((file_map, has_diff, has_macro_rewrite_failure)) => { + if report.has_warnings() { + summary.add_formatting_error(); + } + + if has_diff { + summary.add_diff(); + } + + if has_macro_rewrite_failure { + summary.add_macro_foramt_failure(); + } + + Ok((summary, file_map, report)) + } + Err(e) => Err((From::from(e), summary)), + } +} + +fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { + let style = if config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + config.newline_style() + }; + + match style { + NewlineStyle::Unix => return, + NewlineStyle::Windows => { + let mut transformed = String::with_capacity(text.capacity()); + for c in text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } + } + *text = transformed; + } + NewlineStyle::Native => unreachable!(), + } +} + +/// A single span of changed lines, with 0 or more removed lines +/// and a vector of 0 or more inserted lines. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ModifiedChunk { + /// The first to be removed from the original text + pub line_number_orig: u32, + /// The number of lines which have been replaced + pub lines_removed: u32, + /// The new lines + pub lines: Vec, +} + +/// Set of changed sections of a file. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ModifiedLines { + /// The set of changed chunks. + pub chunks: Vec, +} + +/// Format a file and return a `ModifiedLines` data structure describing +/// the changed ranges of lines. +#[cfg(test)] +pub(crate) fn get_modified_lines( + input: Input, + config: &Config, +) -> Result { + use std::io::BufRead; + + let mut data = Vec::new(); + + let mut config = config.clone(); + config.set().emit_mode(::config::EmitMode::ModifiedLines); + ::format_input(input, &config, Some(&mut data))?; + + let mut lines = data.lines(); + let mut chunks = Vec::new(); + while let Some(Ok(header)) = lines.next() { + // Parse the header line + let values: Vec<_> = header + .split(' ') + .map(|s| s.parse::().unwrap()) + .collect(); + assert_eq!(values.len(), 3); + let line_number_orig = values[0]; + let lines_removed = values[1]; + let num_added = values[2]; + let mut added_lines = Vec::new(); + for _ in 0..num_added { + added_lines.push(lines.next().unwrap().unwrap()); + } + chunks.push(ModifiedChunk { + line_number_orig, + lines_removed, + lines: added_lines, + }); + } + Ok(ModifiedLines { chunks }) +} diff --git a/src/lib.rs b/src/lib.rs index 820134c2085..2c1ef49f354 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,22 +41,15 @@ use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::io::{self, Write}; -use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::PathBuf; use std::rc::Rc; -use std::time::Duration; - use syntax::ast; -use syntax::codemap::{CodeMap, FilePathMapping, Span}; -use syntax::errors::emitter::{ColorConfig, EmitterWriter}; -use syntax::errors::{DiagnosticBuilder, Handler}; -use syntax::parse::{self, ParseSess}; -use comment::{CharClasses, FullCodeCharKind, LineClasses}; +use comment::LineClasses; use failure::Fail; -use issues::{BadIssueSeeker, Issue}; +use formatting::{format_input_inner, FormatErrorMap, FormattingError, ReportedErrors}; +use issues::Issue; use shape::Indent; -use visitor::{FmtVisitor, SnippetProvider}; pub use checkstyle::{footer as checkstyle_footer, header as checkstyle_header}; pub use config::summary::Summary; @@ -77,6 +70,7 @@ mod comment; pub(crate) mod config; mod expr; pub(crate) mod filemap; +pub(crate) mod formatting; mod imports; mod issues; mod items; @@ -100,11 +94,6 @@ mod types; mod vertical; pub(crate) mod visitor; -// A map of the files of a crate, with their new content -pub(crate) type FileMap = Vec; - -pub(crate) type FileRecord = (FileName, String); - /// The various errors that can occur during formatting. Note that not all of /// these can currently be propagated to clients. #[derive(Fail, Debug)] @@ -162,76 +151,6 @@ impl From for ErrorKind { } } -struct FormattingError { - line: usize, - kind: ErrorKind, - is_comment: bool, - is_string: bool, - line_buffer: String, -} - -impl FormattingError { - fn from_span(span: &Span, codemap: &CodeMap, kind: ErrorKind) -> FormattingError { - FormattingError { - line: codemap.lookup_char_pos(span.lo()).line, - is_comment: kind.is_comment(), - kind, - is_string: false, - line_buffer: codemap - .span_to_lines(*span) - .ok() - .and_then(|fl| { - fl.file - .get_line(fl.lines[0].line_index) - .map(|l| l.into_owned()) - }) - .unwrap_or_else(|| String::new()), - } - } - fn msg_prefix(&self) -> &str { - match self.kind { - ErrorKind::LineOverflow(..) - | ErrorKind::TrailingWhitespace - | ErrorKind::IoError(_) - | ErrorKind::ParseError - | ErrorKind::LostComment => "internal error:", - ErrorKind::LicenseCheck | ErrorKind::BadAttr | ErrorKind::VersionMismatch => "error:", - ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", - } - } - - fn msg_suffix(&self) -> &str { - if self.is_comment || self.is_string { - "set `error_on_unformatted = false` to suppress \ - the warning against comments or string literals\n" - } else { - "" - } - } - - // (space, target) - fn format_len(&self) -> (usize, usize) { - match self.kind { - ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace - | ErrorKind::DeprecatedAttr - | ErrorKind::BadAttr - | ErrorKind::LostComment => { - let trailing_ws_start = self - .line_buffer - .rfind(|c: char| !c.is_whitespace()) - .map(|pos| pos + 1) - .unwrap_or(0); - ( - trailing_ws_start, - self.line_buffer.len() - trailing_ws_start, - ) - } - _ => unreachable!(), - } - } -} - /// Reports on any issues that occurred during a run of Rustfmt. /// /// Can be reported to the user via its `Display` implementation of `print_fancy`. @@ -241,14 +160,6 @@ pub struct FormatReport { internal: Rc>, } -type FormatErrorMap = HashMap>; - -#[derive(Default, Debug)] -struct ReportedErrors { - has_operational_errors: bool, - has_check_errors: bool, -} - impl FormatReport { fn new() -> FormatReport { FormatReport { @@ -336,7 +247,7 @@ impl FormatReport { t.attr(term::Attr::Bold)?; write!(t, "{}| ", prefix_spaces)?; t.fg(term::color::RED)?; - writeln!(t, "{}", target_str(space_len, target_len))?; + writeln!(t, "{}", FormatReport::target_str(space_len, target_len))?; t.reset()?; } @@ -367,12 +278,12 @@ impl FormatReport { Ok(()) } -} -fn target_str(space_len: usize, target_len: usize) -> String { - let empty_line = " ".repeat(space_len); - let overflowed = "^".repeat(target_len); - empty_line + &overflowed + fn target_str(space_len: usize, target_len: usize) -> String { + let empty_line = " ".repeat(space_len); + let overflowed = "^".repeat(target_len); + empty_line + &overflowed + } } impl fmt::Display for FormatReport { @@ -393,7 +304,7 @@ impl fmt::Display for FormatReport { error.line, error.line_buffer, prefix_spaces, - target_str(space_len, target_len) + FormatReport::target_str(space_len, target_len) ) }; @@ -428,267 +339,6 @@ impl fmt::Display for FormatReport { } } -fn should_emit_verbose(path: &FileName, config: &Config, f: F) -where - F: Fn(), -{ - if config.verbose() == Verbosity::Verbose && path != &FileName::Stdin { - f(); - } -} - -// Formatting which depends on the AST. -fn format_ast( - krate: &ast::Crate, - parse_session: &mut ParseSess, - main_file: &FileName, - config: &Config, - report: FormatReport, - mut after_file: F, -) -> Result<(FileMap, bool, bool), io::Error> -where - F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result, -{ - let mut result = FileMap::new(); - // diff mode: check if any files are differing - let mut has_diff = false; - let mut has_macro_rewrite_failure = false; - - let skip_children = config.skip_children(); - for (path, module) in modules::list_files(krate, parse_session.codemap())? { - if (skip_children && path != *main_file) || config.ignore().skip_file(&path) { - continue; - } - should_emit_verbose(&path, config, || println!("Formatting {}", path)); - let filemap = parse_session - .codemap() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = - FmtVisitor::from_codemap(parse_session, config, &snippet_provider, report.clone()); - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == *main_file { - visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, &*filemap); - } - } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); - visitor.format_separate_mod(module, &*filemap); - }; - - debug_assert_eq!( - visitor.line_number, - ::utils::count_newlines(&visitor.buffer) - ); - - has_diff |= match after_file(&path, &mut visitor.buffer, &visitor.skipped_range, &report) { - Ok(result) => result, - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg)); - } - }; - - has_macro_rewrite_failure |= visitor.macro_rewrite_failure; - - result.push((path.clone(), visitor.buffer)); - } - - Ok((result, has_diff, has_macro_rewrite_failure)) -} - -/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. -fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { - skipped_range - .iter() - .any(|&(lo, hi)| lo <= line_number && line_number <= hi) -} - -fn should_report_error( - config: &Config, - char_kind: FullCodeCharKind, - is_string: bool, - error_kind: &ErrorKind, -) -> bool { - let allow_error_report = if char_kind.is_comment() || is_string || error_kind.is_comment() { - config.error_on_unformatted() - } else { - true - }; - - match error_kind { - ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, - ErrorKind::TrailingWhitespace | ErrorKind::LostComment => allow_error_report, - _ => true, - } -} - -// Formatting done on a char by char or line by line basis. -// FIXME(#20) other stuff for parity with make tidy -fn format_lines( - text: &mut String, - name: &FileName, - skipped_range: &[(usize, usize)], - config: &Config, - report: &FormatReport, -) { - let mut last_was_space = false; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); - let mut line_buffer = String::with_capacity(config.max_width() * 2); - let mut is_string = false; // true if the current line contains a string literal. - let mut format_line = config.file_lines().contains_line(name, cur_line); - let allow_issue_seek = !issue_seeker.is_disabled(); - - // Check license. - if let Some(ref license_template) = config.license_template { - if !license_template.is_match(text) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LicenseCheck, - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } - } - - // Iterate over the chars in the file map. - for (kind, c) in CharClasses::new(text.chars()) { - if c == '\r' { - continue; - } - - if allow_issue_seek && format_line { - // Add warnings for bad todos/ fixmes - if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } - } - - if c == '\n' { - if format_line { - // Check for (and record) trailing whitespace. - if last_was_space { - if should_report_error(config, kind, is_string, &ErrorKind::TrailingWhitespace) - && !is_skipped_line(cur_line, skipped_range) - { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::TrailingWhitespace, - is_comment: kind.is_comment(), - is_string: kind.is_string(), - line_buffer: line_buffer.clone(), - }); - } - line_len -= 1; - } - - // Check for any line width errors we couldn't correct. - let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); - if line_len > config.max_width() - && !is_skipped_line(cur_line, skipped_range) - && should_report_error(config, kind, is_string, &error_kind) - { - errors.push(FormattingError { - line: cur_line, - kind: error_kind, - is_comment: kind.is_comment(), - is_string, - line_buffer: line_buffer.clone(), - }); - } - } - - line_len = 0; - cur_line += 1; - format_line = config.file_lines().contains_line(name, cur_line); - newline_count += 1; - last_was_space = false; - line_buffer.clear(); - is_string = false; - } else { - newline_count = 0; - line_len += if c == '\t' { config.tab_spaces() } else { 1 }; - last_was_space = c.is_whitespace(); - line_buffer.push(c); - if kind.is_string() { - is_string = true; - } - } - } - - if newline_count > 1 { - debug!("track truncate: {} {}", text.len(), newline_count); - let line = text.len() - newline_count + 1; - text.truncate(line); - } - - report.append(name.clone(), errors); -} - -fn parse_input<'sess>( - input: Input, - parse_session: &'sess ParseSess, - config: &Config, -) -> Result> { - let mut parser = match input { - Input::File(file) => parse::new_parser_from_file(parse_session, &file), - Input::Text(text) => parse::new_parser_from_source_str( - parse_session, - syntax::codemap::FileName::Custom("stdin".to_owned()), - text, - ), - }; - - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - - let mut parser = AssertUnwindSafe(parser); - let result = catch_unwind(move || parser.0.parse_crate_mod()); - - match result { - Ok(Ok(c)) => { - if parse_session.span_diagnostic.has_errors() { - // Bail out if the parser recovered from an error. - Err(ParseError::Recovered) - } else { - Ok(c) - } - } - Ok(Err(e)) => Err(ParseError::Error(e)), - Err(_) => Err(ParseError::Panic), - } -} - -/// All the ways that parsing can fail. -enum ParseError<'sess> { - /// There was an error, but the parser recovered. - Recovered, - /// There was an error (supplied) and parsing failed. - Error(DiagnosticBuilder<'sess>), - /// The parser panicked. - Panic, -} - /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. fn format_snippet(snippet: &str, config: &Config) -> Option { @@ -707,30 +357,30 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { } } -const FN_MAIN_PREFIX: &str = "fn main() {\n"; - -fn enclose_in_main_block(s: &str, config: &Config) -> String { - let indent = Indent::from_width(config, config.tab_spaces()); - let mut result = String::with_capacity(s.len() * 2); - result.push_str(FN_MAIN_PREFIX); - let mut need_indent = true; - for (kind, line) in LineClasses::new(s) { - if need_indent { - result.push_str(&indent.to_string(config)); - } - result.push_str(&line); - result.push('\n'); - need_indent = !kind.is_string() || line.ends_with('\\'); - } - result.push('}'); - result -} - /// Format the given code block. Mainly targeted for code block in comment. /// The code block may be incomplete (i.e. parser may be unable to parse it). /// To avoid panic in parser, we wrap the code block with a dummy function. /// The returned code block does *not* end with newline. fn format_code_block(code_snippet: &str, config: &Config) -> Option { + const FN_MAIN_PREFIX: &str = "fn main() {\n"; + + fn enclose_in_main_block(s: &str, config: &Config) -> String { + let indent = Indent::from_width(config, config.tab_spaces()); + let mut result = String::with_capacity(s.len() * 2); + result.push_str(FN_MAIN_PREFIX); + let mut need_indent = true; + for (kind, line) in LineClasses::new(s) { + if need_indent { + result.push_str(&indent.to_string(config)); + } + result.push_str(&line); + result.push('\n'); + need_indent = !kind.is_string() || line.ends_with('\\'); + } + result.push('}'); + result + } + // Wrap the given code block with `fn main()` if it does not have one. let snippet = enclose_in_main_block(code_snippet, config); let mut result = String::with_capacity(snippet.len()); @@ -806,236 +456,9 @@ pub fn format_input( syntax::with_globals(|| format_input_inner(input, config, out)).map(|tup| (tup.0, tup.2)) } -fn format_input_inner( - input: Input, - config: &Config, - mut out: Option<&mut T>, -) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> { - syntax_pos::hygiene::set_default_edition(config.edition().to_libsyntax_pos_edition()); - let mut summary = Summary::default(); - if config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err((From::from(e), summary)); - } - } - return Ok((summary, FileMap::new(), FormatReport::new())); - } - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - - let tty_handler = if config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - Handler::with_emitter(true, false, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) - }; - let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Stdin, - }; - - let krate = match parse_input(input, &parse_session, config) { - Ok(krate) => krate, - Err(err) => { - match err { - ParseError::Error(mut diagnostic) => diagnostic.emit(), - ParseError::Panic => { - // Note that if you see this message and want more information, - // then go to `parse_input` and run the parse function without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(&main_file, config, || { - println!("The Rust parser panicked") - }); - } - ParseError::Recovered => {} - } - summary.add_parsing_error(); - return Err((ErrorKind::ParseError, summary)); - } - }; - - summary.mark_parse_time(); - - // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - - let report = FormatReport::new(); - - let format_result = format_ast( - &krate, - &mut parse_session, - &main_file, - config, - report.clone(), - |file_name, file, skipped_range, report| { - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(file); - - format_lines(file, file_name, skipped_range, config, report); - replace_with_system_newlines(file, config); - - if let Some(ref mut out) = out { - return filemap::write_file(file, file_name, out, config); - } - Ok(false) - }, - ); - - summary.mark_format_time(); - - should_emit_verbose(&main_file, config, || { - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 - } - - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(summary.get_parse_time().unwrap()), - duration_to_f32(summary.get_format_time().unwrap()), - ) - }); - - { - let report_errs = &report.internal.borrow().1; - if report_errs.has_check_errors { - summary.add_check_error(); - } - if report_errs.has_operational_errors { - summary.add_operational_error(); - } - } - - match format_result { - Ok((file_map, has_diff, has_macro_rewrite_failure)) => { - if report.has_warnings() { - summary.add_formatting_error(); - } - - if has_diff { - summary.add_diff(); - } - - if has_macro_rewrite_failure { - summary.add_macro_foramt_failure(); - } - - Ok((summary, file_map, report)) - } - Err(e) => Err((From::from(e), summary)), - } -} - -fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; - - match style { - NewlineStyle::Unix => return, - NewlineStyle::Windows => { - let mut transformed = String::with_capacity(text.capacity()); - for c in text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } - } - *text = transformed; - } - NewlineStyle::Native => unreachable!(), - } -} - -/// A single span of changed lines, with 0 or more removed lines -/// and a vector of 0 or more inserted lines. -#[derive(Debug, PartialEq, Eq)] -struct ModifiedChunk { - /// The first to be removed from the original text - pub line_number_orig: u32, - /// The number of lines which have been replaced - pub lines_removed: u32, - /// The new lines - pub lines: Vec, -} - -/// Set of changed sections of a file. -#[derive(Debug, PartialEq, Eq)] -struct ModifiedLines { - /// The set of changed chunks. - pub chunks: Vec, -} - -/// Format a file and return a `ModifiedLines` data structure describing -/// the changed ranges of lines. -#[cfg(test)] -fn get_modified_lines( - input: Input, - config: &Config, -) -> Result { - use std::io::BufRead; - - let mut data = Vec::new(); - - let mut config = config.clone(); - config.set().emit_mode(config::EmitMode::ModifiedLines); - format_input(input, &config, Some(&mut data))?; - - let mut lines = data.lines(); - let mut chunks = Vec::new(); - while let Some(Ok(header)) = lines.next() { - // Parse the header line - let values: Vec<_> = header - .split(' ') - .map(|s| s.parse::().unwrap()) - .collect(); - assert_eq!(values.len(), 3); - let line_number_orig = values[0]; - let lines_removed = values[1]; - let num_added = values[2]; - let mut added_lines = Vec::new(); - for _ in 0..num_added { - added_lines.push(lines.next().unwrap().unwrap()); - } - chunks.push(ModifiedChunk { - line_number_orig, - lines_removed, - lines: added_lines, - }); - } - Ok(ModifiedLines { chunks }) -} - #[cfg(test)] mod unit_tests { - use super::{format_code_block, format_snippet, Config}; + use super::*; #[test] fn test_no_panic_on_format_snippet_and_format_code_block() { diff --git a/src/test/mod.rs b/src/test/mod.rs index 47b801011bf..b2eead3183d 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -15,15 +15,17 @@ use syntax; use std::collections::{HashMap, HashSet}; use std::env; use std::fs; -use std::io::{self, BufRead, BufReader, Read}; +use std::io::{self, BufRead, BufReader, Read, Write}; use std::iter::{Enumerate, Peekable}; use std::path::{Path, PathBuf}; use std::str::Chars; use config::summary::Summary; -use config::{Color, Config, ReportTactic}; -use rustfmt_diff::*; -use *; +use config::{Color, Config, EmitMode, FileName, ReportTactic}; +use filemap; +use formatting::{format_input_inner, get_modified_lines, FileMap, ModifiedChunk, ModifiedLines}; +use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; +use {format_input, FormatReport, Input}; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; -- cgit 1.4.1-3-g733a5 From 71d3d04270474ae0afdeeb410fdcc168a54714b7 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Jul 2018 14:52:02 +1200 Subject: factor out a `Session` object --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/bin/main.rs | 163 ++++++++++++---------------- src/formatting.rs | 278 +++++++++++++++++++++--------------------------- src/git-rustfmt/main.rs | 12 +-- src/imports.rs | 6 +- src/items.rs | 2 +- src/lib.rs | 83 +++++++++++---- src/test/mod.rs | 111 +++++++++++++------ 9 files changed, 336 insertions(+), 323 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index f6e11cdb0a9..70dec3dcd2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -533,7 +533,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.8.3" +version = "0.9.0" dependencies = [ "assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 99c83f993d4..5023e8bec0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "0.8.3" +version = "0.9.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang-nursery/rustfmt" diff --git a/src/bin/main.rs b/src/bin/main.rs index cd5e58437e6..5b6398f028e 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -28,8 +28,8 @@ use failure::err_msg; use getopts::{Matches, Options}; use rustfmt::{ - checkstyle_footer, checkstyle_header, format_input, load_config, CliOptions, Color, Config, - EmitMode, ErrorKind, FileLines, FileName, Input, Summary, Verbosity, + load_config, CliOptions, Color, Config, EmitMode, ErrorKind, FileLines, FileName, Input, + Session, Verbosity, }; fn main() { @@ -37,17 +37,7 @@ fn main() { let opts = make_opts(); let exit_code = match execute(&opts) { - Ok((exit_mode, summary)) => { - if summary.has_operational_errors() - || summary.has_parsing_errors() - || ((summary.has_diff || summary.has_check_errors()) - && exit_mode == ExitCodeMode::Check) - { - 1 - } else { - 0 - } - } + Ok(code) => code, Err(e) => { eprintln!("{}", e.to_string()); 1 @@ -174,26 +164,27 @@ fn is_nightly() -> bool { .unwrap_or(false) } -fn execute(opts: &Options) -> Result<(ExitCodeMode, Summary), failure::Error> { +// Returned i32 is an exit code +fn execute(opts: &Options) -> Result { let matches = opts.parse(env::args().skip(1))?; let options = GetOptsOptions::from_matches(&matches)?; match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { print_usage_to_stdout(opts, ""); - Ok((ExitCodeMode::Normal, Summary::default())) + return Ok(1); } Operation::Help(HelpOp::Config) => { Config::print_docs(&mut stdout(), options.unstable_features); - Ok((ExitCodeMode::Normal, Summary::default())) + return Ok(1); } Operation::Help(HelpOp::FileLines) => { print_help_file_lines(); - Ok((ExitCodeMode::Normal, Summary::default())) + return Ok(1); } Operation::Version => { print_version(); - Ok((ExitCodeMode::Normal, Summary::default())) + return Ok(1); } Operation::ConfigOutputDefault { path } => { let toml = Config::default().all_options().to_toml().map_err(err_msg)?; @@ -203,35 +194,9 @@ fn execute(opts: &Options) -> Result<(ExitCodeMode, Summary), failure::Error> { } else { io::stdout().write_all(toml.as_bytes())?; } - Ok((ExitCodeMode::Normal, Summary::default())) - } - Operation::Stdin { input } => { - // try to read config from local directory - let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; - - // emit mode is always Stdout for Stdin. - config.set().emit_mode(EmitMode::Stdout); - config.set().verbose(Verbosity::Quiet); - - // parse file_lines - config.set().file_lines(options.file_lines); - for f in config.file_lines().files() { - match *f { - FileName::Stdin => {} - _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), - } - } - - let mut error_summary = Summary::default(); - emit_pre_matter(&config); - match format_and_emit_report(Input::Text(input), &config) { - Ok(summary) => error_summary.add(summary), - Err(_) => error_summary.add_operational_error(), - } - emit_post_matter(&config); - - Ok((ExitCodeMode::Normal, error_summary)) + return Ok(1); } + Operation::Stdin { input } => format_string(input, options), Operation::Format { files, minimal_config_path, @@ -239,11 +204,41 @@ fn execute(opts: &Options) -> Result<(ExitCodeMode, Summary), failure::Error> { } } +fn format_string(input: String, options: GetOptsOptions) -> Result { + // try to read config from local directory + let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; + + // emit mode is always Stdout for Stdin. + config.set().emit_mode(EmitMode::Stdout); + config.set().verbose(Verbosity::Quiet); + + // parse file_lines + config.set().file_lines(options.file_lines); + for f in config.file_lines().files() { + match *f { + FileName::Stdin => {} + _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), + } + } + + let out = &mut stdout(); + let mut session = Session::new(config, Some(out)); + format_and_emit_report(&mut session, Input::Text(input)); + + let exit_code = + if session.summary.has_operational_errors() || session.summary.has_parsing_errors() { + 1 + } else { + 0 + }; + Ok(exit_code) +} + fn format( files: Vec, minimal_config_path: Option, options: GetOptsOptions, -) -> Result<(ExitCodeMode, Summary), failure::Error> { +) -> Result { options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(options.clone()))?; @@ -253,19 +248,19 @@ fn format( } } - emit_pre_matter(&config); - let mut error_summary = Summary::default(); + let out = &mut stdout(); + let mut session = Session::new(config, Some(out)); for file in files { if !file.exists() { eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); - error_summary.add_operational_error(); + session.summary.add_operational_error(); } else if file.is_dir() { eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); - error_summary.add_operational_error(); + session.summary.add_operational_error(); } else { // Check the file directory if the config-path could not be read or not provided - let local_config = if config_path.is_none() { + if config_path.is_none() { let (local_config, config_path) = load_config(Some(file.parent().unwrap()), Some(options.clone()))?; if local_config.verbose() == Verbosity::Verbose { @@ -277,47 +272,42 @@ fn format( ); } } - local_config + + session.override_config(local_config, |sess| { + format_and_emit_report(sess, Input::File(file)) + }); } else { - config.clone() - }; - - match format_and_emit_report(Input::File(file), &local_config) { - Ok(summary) => error_summary.add(summary), - Err(_) => { - error_summary.add_operational_error(); - break; - } + format_and_emit_report(&mut session, Input::File(file)); } } } - emit_post_matter(&config); // If we were given a path via dump-minimal-config, output any options // that were used during formatting as TOML. if let Some(path) = minimal_config_path { let mut file = File::create(path)?; - let toml = config.used_options().to_toml().map_err(err_msg)?; + let toml = session.config.used_options().to_toml().map_err(err_msg)?; file.write_all(toml.as_bytes())?; } - let exit_mode = if options.check { - ExitCodeMode::Check + let exit_code = if session.summary.has_operational_errors() + || session.summary.has_parsing_errors() + || ((session.summary.has_diff || session.summary.has_check_errors()) && options.check) + { + 1 } else { - ExitCodeMode::Normal + 0 }; - Ok((exit_mode, error_summary)) + Ok(exit_code) } -fn format_and_emit_report(input: Input, config: &Config) -> Result { - let out = &mut stdout(); - - match format_input(input, config, Some(out)) { - Ok((summary, report)) => { +fn format_and_emit_report(session: &mut Session, input: Input) { + match session.format(input) { + Ok(report) => { if report.has_warnings() { match term::stderr() { Some(ref t) - if config.color().use_colored_tty() + if session.config.color().use_colored_tty() && t.supports_color() && t.supports_attr(term::Attr::Bold) => { @@ -329,29 +319,14 @@ fn format_and_emit_report(input: Input, config: &Config) -> Result eprintln!("{}", report), } } - - Ok(summary) } - Err((msg, mut summary)) => { + Err(msg) => { eprintln!("Error writing files: {}", msg); - summary.add_operational_error(); - Ok(summary) + session.summary.add_operational_error(); } } } -fn emit_pre_matter(config: &Config) { - if config.emit_mode() == EmitMode::Checkstyle { - println!("{}", checkstyle_header()); - } -} - -fn emit_post_matter(config: &Config) { - if config.emit_mode() == EmitMode::Checkstyle { - println!("{}", checkstyle_footer()); - } -} - fn print_usage_to_stdout(opts: &Options, reason: &str) { let sep = if reason.is_empty() { String::new() @@ -456,12 +431,6 @@ fn determine_operation(matches: &Matches) -> Result { }) } -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -enum ExitCodeMode { - Normal, - Check, -} - const STABLE_EMIT_MODES: [EmitMode; 3] = [EmitMode::Files, EmitMode::Stdout, EmitMode::Diff]; /// Parsed command line options. diff --git a/src/formatting.rs b/src/formatting.rs index 95e2b08e3fe..53e673c5e7a 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -15,9 +15,8 @@ use syntax::parse::{self, ParseSess}; use comment::{CharClasses, FullCodeCharKind}; use issues::BadIssueSeeker; use visitor::{FmtVisitor, SnippetProvider}; -use {filemap, modules, ErrorKind, FormatReport, Input}; +use {filemap, modules, ErrorKind, FormatReport, Input, Session}; -use config::summary::Summary; use config::{Config, FileName, NewlineStyle, Verbosity}; // A map of the files of a crate, with their new content @@ -365,143 +364,146 @@ enum ParseError<'sess> { Panic, } -pub(crate) fn format_input_inner( - input: Input, - config: &Config, - mut out: Option<&mut T>, -) -> Result<(Summary, FileMap, FormatReport), (ErrorKind, Summary)> { - syntax_pos::hygiene::set_default_edition(config.edition().to_libsyntax_pos_edition()); - let mut summary = Summary::default(); - if config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err((From::from(e), summary)); +impl<'b, T: Write + 'b> Session<'b, T> { + pub(crate) fn format_input_inner( + &mut self, + input: Input, + ) -> Result<(FileMap, FormatReport), ErrorKind> { + syntax_pos::hygiene::set_default_edition(self.config.edition().to_libsyntax_pos_edition()); + + if self.config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err(From::from(e)); + } } + return Ok((FileMap::new(), FormatReport::new())); } - return Ok((summary, FileMap::new(), FormatReport::new())); - } - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + + let tty_handler = if self.config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; + let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + + let main_file = match input { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Stdin, + }; + + let krate = match parse_input(input, &parse_session, &self.config) { + Ok(krate) => krate, + Err(err) => { + match err { + ParseError::Error(mut diagnostic) => diagnostic.emit(), + ParseError::Panic => { + // Note that if you see this message and want more information, + // then go to `parse_input` and run the parse function without + // `catch_unwind` so rustfmt panics and you can get a backtrace. + should_emit_verbose(&main_file, &self.config, || { + println!("The Rust parser panicked") + }); + } + ParseError::Recovered => {} + } + self.summary.add_parsing_error(); + return Err(ErrorKind::ParseError); + } + }; - let tty_handler = if config.hide_parse_errors() { + self.summary.mark_parse_time(); + + // Suppress error output after parsing. let silent_emitter = Box::new(EmitterWriter::new( Box::new(Vec::new()), Some(codemap.clone()), false, false, )); - Handler::with_emitter(true, false, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) - }; - let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); - - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Stdin, - }; - - let krate = match parse_input(input, &parse_session, config) { - Ok(krate) => krate, - Err(err) => { - match err { - ParseError::Error(mut diagnostic) => diagnostic.emit(), - ParseError::Panic => { - // Note that if you see this message and want more information, - // then go to `parse_input` and run the parse function without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(&main_file, config, || { - println!("The Rust parser panicked") - }); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + + let report = FormatReport::new(); + + let config = &self.config; + let out = &mut self.out; + let format_result = format_ast( + &krate, + &mut parse_session, + &main_file, + config, + report.clone(), + |file_name, file, skipped_range, report| { + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(file); + + format_lines(file, file_name, skipped_range, config, report); + replace_with_system_newlines(file, config); + + if let Some(ref mut out) = out { + return filemap::write_file(file, file_name, out, config); } - ParseError::Recovered => {} - } - summary.add_parsing_error(); - return Err((ErrorKind::ParseError, summary)); - } - }; + Ok(false) + }, + ); + + self.summary.mark_format_time(); - summary.mark_parse_time(); - - // Suppress error output after parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - - let report = FormatReport::new(); - - let format_result = format_ast( - &krate, - &mut parse_session, - &main_file, - config, - report.clone(), - |file_name, file, skipped_range, report| { - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(file); - - format_lines(file, file_name, skipped_range, config, report); - replace_with_system_newlines(file, config); - - if let Some(ref mut out) = out { - return filemap::write_file(file, file_name, out, config); + should_emit_verbose(&main_file, &self.config, || { + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 } - Ok(false) - }, - ); - summary.mark_format_time(); + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + duration_to_f32(self.summary.get_parse_time().unwrap()), + duration_to_f32(self.summary.get_format_time().unwrap()), + ) + }); - should_emit_verbose(&main_file, config, || { - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + { + let report_errs = &report.internal.borrow().1; + if report_errs.has_check_errors { + self.summary.add_check_error(); + } + if report_errs.has_operational_errors { + self.summary.add_operational_error(); + } } - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(summary.get_parse_time().unwrap()), - duration_to_f32(summary.get_format_time().unwrap()), - ) - }); - - { - let report_errs = &report.internal.borrow().1; - if report_errs.has_check_errors { - summary.add_check_error(); - } - if report_errs.has_operational_errors { - summary.add_operational_error(); - } - } + match format_result { + Ok((file_map, has_diff, has_macro_rewrite_failure)) => { + if report.has_warnings() { + self.summary.add_formatting_error(); + } - match format_result { - Ok((file_map, has_diff, has_macro_rewrite_failure)) => { - if report.has_warnings() { - summary.add_formatting_error(); - } + if has_diff { + self.summary.add_diff(); + } - if has_diff { - summary.add_diff(); - } + if has_macro_rewrite_failure { + self.summary.add_macro_foramt_failure(); + } - if has_macro_rewrite_failure { - summary.add_macro_foramt_failure(); + Ok((file_map, report)) } - - Ok((summary, file_map, report)) + Err(e) => Err(From::from(e)), } - Err(e) => Err((From::from(e), summary)), } } @@ -551,43 +553,3 @@ pub(crate) struct ModifiedLines { /// The set of changed chunks. pub chunks: Vec, } - -/// Format a file and return a `ModifiedLines` data structure describing -/// the changed ranges of lines. -#[cfg(test)] -pub(crate) fn get_modified_lines( - input: Input, - config: &Config, -) -> Result { - use std::io::BufRead; - - let mut data = Vec::new(); - - let mut config = config.clone(); - config.set().emit_mode(::config::EmitMode::ModifiedLines); - ::format_input(input, &config, Some(&mut data))?; - - let mut lines = data.lines(); - let mut chunks = Vec::new(); - while let Some(Ok(header)) = lines.next() { - // Parse the header line - let values: Vec<_> = header - .split(' ') - .map(|s| s.parse::().unwrap()) - .collect(); - assert_eq!(values.len(), 3); - let line_number_orig = values[0]; - let lines_removed = values[1]; - let num_added = values[2]; - let mut added_lines = Vec::new(); - for _ in 0..num_added { - added_lines.push(lines.next().unwrap().unwrap()); - } - chunks.push(ModifiedChunk { - line_number_orig, - lines_removed, - lines: added_lines, - }); - } - Ok(ModifiedLines { chunks }) -} diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 545756576c9..d6ab3661482 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -22,7 +22,7 @@ use std::str::FromStr; use getopts::{Matches, Options}; -use rustfmt::{format_input, load_config, CliOptions, Input}; +use rustfmt::{load_config, CliOptions, Input, Session}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -73,16 +73,14 @@ fn fmt_files(files: &[&str]) -> i32 { load_config::(Some(Path::new(".")), None).expect("couldn't load config"); let mut exit_code = 0; + let mut out = stdout(); + let mut session = Session::new(config, Some(&mut out)); for file in files { - let (summary, report) = format_input( - Input::File(PathBuf::from(file)), - &config, - Some(&mut stdout()), - ).unwrap(); + let report = session.format(Input::File(PathBuf::from(file))).unwrap(); if report.has_warnings() { eprintln!("{}", report); } - if !summary.has_no_errors() { + if !session.summary.has_no_errors() { exit_code = 1; } } diff --git a/src/imports.rs b/src/imports.rs index 79d0641504e..f087ea5e52a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -349,7 +349,7 @@ impl UseTree { )); } UseTreeKind::Simple(ref rename, ..) => { - let mut name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned(); + let name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned(); let alias = rename.and_then(|ident| { if ident == path_to_imported_ident(&a.prefix) { None @@ -511,7 +511,7 @@ impl UseTree { let prefix = &self.path[..self.path.len() - 1]; let mut result = vec![]; for nested_use_tree in list { - for mut flattend in &mut nested_use_tree.clone().flatten() { + for flattend in &mut nested_use_tree.clone().flatten() { let mut new_path = prefix.to_vec(); new_path.append(&mut flattend.path); result.push(UseTree { @@ -532,7 +532,7 @@ impl UseTree { fn merge(&mut self, other: UseTree) { let mut new_path = vec![]; - for (mut a, b) in self + for (a, b) in self .path .clone() .iter_mut() diff --git a/src/items.rs b/src/items.rs index 00db19f3b6c..721f02b0187 100644 --- a/src/items.rs +++ b/src/items.rs @@ -663,7 +663,7 @@ pub fn format_impl( option.compress_where(); } - let mut where_clause_str = rewrite_where_clause( + let where_clause_str = rewrite_where_clause( context, &generics.where_clause, context.config.brace_style(), diff --git a/src/lib.rs b/src/lib.rs index 2c1ef49f354..6183117a58c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![feature(type_ascription)] #![feature(unicode_internals)] #![feature(extern_prelude)] +#![feature(nll)] #[macro_use] extern crate derive_new; @@ -41,17 +42,17 @@ use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::io::{self, Write}; +use std::mem; use std::path::PathBuf; use std::rc::Rc; use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{format_input_inner, FormatErrorMap, FormattingError, ReportedErrors}; +use formatting::{FormatErrorMap, FormattingError, ReportedErrors}; use issues::Issue; use shape::Indent; -pub use checkstyle::{footer as checkstyle_footer, header as checkstyle_header}; pub use config::summary::Summary; pub use config::{ load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, NewlineStyle, Range, @@ -348,13 +349,16 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { config.set().emit_mode(config::EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); config.set().hide_parse_errors(true); - match format_input(input, &config, Some(&mut out)) { - // `format_input()` returns an empty string on parsing error. - Ok((summary, _)) if summary.has_macro_formatting_failure() => None, - Ok(..) if out.is_empty() && !snippet.is_empty() => None, - Ok(..) => String::from_utf8(out).ok(), - Err(..) => None, + { + let mut session = Session::new(config, Some(&mut out)); + let result = session.format(input); + let formatting_error = session.summary.has_macro_formatting_failure() + || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty(); + if formatting_error || result.is_err() { + return None; + } } + String::from_utf8(out).ok() } /// Format the given code block. Mainly targeted for code block in comment. @@ -436,24 +440,59 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { Some(result) } -#[derive(Debug)] -pub enum Input { - File(PathBuf), - Text(String), +/// A session is a run of rustfmt across a single or multiple inputs. +pub struct Session<'b, T: Write + 'b> { + pub config: Config, + pub out: Option<&'b mut T>, + pub summary: Summary, +} + +impl<'b, T: Write + 'b> Session<'b, T> { + pub fn new(config: Config, out: Option<&'b mut T>) -> Session<'b, T> { + if config.emit_mode() == EmitMode::Checkstyle { + println!("{}", checkstyle::header()); + } + + Session { + config, + out, + summary: Summary::default(), + } + } + + /// The main entry point for Rustfmt. Formats the given input according to the + /// given config. `out` is only necessary if required by the configuration. + pub fn format(&mut self, input: Input) -> Result { + if !self.config.version_meets_requirement() { + return Err(ErrorKind::VersionMismatch); + } + + syntax::with_globals(|| self.format_input_inner(input)).map(|tup| tup.1) + } + + pub fn override_config(&mut self, mut config: Config, f: F) -> U + where + F: FnOnce(&mut Session<'b, T>) -> U, + { + mem::swap(&mut config, &mut self.config); + let result = f(self); + mem::swap(&mut config, &mut self.config); + result + } } -/// The main entry point for Rustfmt. Formats the given input according to the -/// given config. `out` is only necessary if required by the configuration. -pub fn format_input( - input: Input, - config: &Config, - out: Option<&mut T>, -) -> Result<(Summary, FormatReport), (ErrorKind, Summary)> { - if !config.version_meets_requirement() { - return Err((ErrorKind::VersionMismatch, Summary::default())); +impl<'b, T: Write + 'b> Drop for Session<'b, T> { + fn drop(&mut self) { + if self.config.emit_mode() == EmitMode::Checkstyle { + println!("{}", checkstyle::footer()); + } } +} - syntax::with_globals(|| format_input_inner(input, config, out)).map(|tup| (tup.0, tup.2)) +#[derive(Debug)] +pub enum Input { + File(PathBuf), + Text(String), } #[cfg(test)] diff --git a/src/test/mod.rs b/src/test/mod.rs index b2eead3183d..f02cfbc858c 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -23,9 +23,9 @@ use std::str::Chars; use config::summary::Summary; use config::{Color, Config, EmitMode, FileName, ReportTactic}; use filemap; -use formatting::{format_input_inner, get_modified_lines, FileMap, ModifiedChunk, ModifiedLines}; +use formatting::{FileMap, ModifiedChunk}; use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; -use {format_input, FormatReport, Input}; +use {FormatReport, Input, Session}; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; @@ -142,25 +142,56 @@ fn checkstyle_test() { #[test] fn modified_test() { + use std::io::BufRead; + // Test "modified" output let filename = "tests/writemode/source/modified.rs"; - let result = get_modified_lines(Input::File(filename.into()), &Config::default()).unwrap(); - assert_eq!( - result, - ModifiedLines { - chunks: vec![ - ModifiedChunk { - line_number_orig: 4, - lines_removed: 4, - lines: vec!["fn blah() {}".into()], - }, - ModifiedChunk { - line_number_orig: 9, - lines_removed: 6, - lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], - }, - ], + let mut data = Vec::new(); + let mut config = Config::default(); + config.set().emit_mode(::config::EmitMode::ModifiedLines); + + { + let mut session = Session::new(config, Some(&mut data)); + session.format(Input::File(filename.into())).unwrap(); + } + + let mut lines = data.lines(); + let mut chunks = Vec::new(); + while let Some(Ok(header)) = lines.next() { + // Parse the header line + let values: Vec<_> = header + .split(' ') + .map(|s| s.parse::().unwrap()) + .collect(); + assert_eq!(values.len(), 3); + let line_number_orig = values[0]; + let lines_removed = values[1]; + let num_added = values[2]; + let mut added_lines = Vec::new(); + for _ in 0..num_added { + added_lines.push(lines.next().unwrap().unwrap()); } + chunks.push(ModifiedChunk { + line_number_orig, + lines_removed, + lines: added_lines, + }); + } + + assert_eq!( + chunks, + vec![ + ModifiedChunk { + line_number_orig: 4, + lines_removed: 4, + lines: vec!["fn blah() {}".into()], + }, + ModifiedChunk { + line_number_orig: 9, + lines_removed: 6, + lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], + }, + ], ); } @@ -168,7 +199,7 @@ fn modified_test() { // to a known output file generated by one of the write modes. fn assert_output(source: &Path, expected_filename: &Path) { let config = read_config(source); - let (_error_summary, file_map, _report) = format_file(source, &config); + let (_, file_map, _) = format_file(source, config.clone()); // Populate output by writing to a vec. let mut out = vec![]; @@ -246,8 +277,11 @@ fn stdin_formatting_smoke_test() { let mut config = Config::default(); config.set().emit_mode(EmitMode::Stdout); let mut buf: Vec = vec![]; - let (error_summary, _) = format_input(input, &config, Some(&mut buf)).unwrap(); - assert!(error_summary.has_no_errors()); + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + assert!(session.summary.has_no_errors()); + } //eprintln!("{:?}", ); #[cfg(not(windows))] assert_eq!(buf, "fn main() {}\n".as_bytes()); @@ -284,8 +318,9 @@ fn format_lines_errors_are_reported() { let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let mut config = Config::default(); config.set().error_on_line_overflow(true); - let (error_summary, _) = format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); + let mut session = Session::::new(config, None); + session.format(input).unwrap(); + assert!(session.summary.has_formatting_errors()); } #[test] @@ -295,8 +330,9 @@ fn format_lines_errors_are_reported_with_tabs() { let mut config = Config::default(); config.set().error_on_line_overflow(true); config.set().hard_tabs(true); - let (error_summary, _) = format_input::(input, &config, None).unwrap(); - assert!(error_summary.has_formatting_errors()); + let mut session = Session::::new(config, None); + session.format(input).unwrap(); + assert!(session.summary.has_formatting_errors()); } // For each file, run rustfmt and collect the output. @@ -380,11 +416,15 @@ fn read_config(filename: &Path) -> Config { config } -fn format_file>(filepath: P, config: &Config) -> (Summary, FileMap, FormatReport) { +fn format_file>(filepath: P, config: Config) -> (bool, FileMap, FormatReport) { let filepath = filepath.into(); let input = Input::File(filepath); - //format_input::(input, config, None).unwrap() - syntax::with_globals(|| format_input_inner::(input, config, None)).unwrap() + let mut session = Session::::new(config, None); + syntax::with_globals(|| { + let result = session.format_input_inner(input).unwrap(); + let parsing_errors = session.summary.has_parsing_errors(); + (parsing_errors, result.0, result.1) + }) } enum IdempotentCheckError { @@ -402,8 +442,8 @@ fn idempotent_check( } else { read_config(filename) }; - let (error_summary, file_map, format_report) = format_file(filename, &config); - if error_summary.has_parsing_errors() { + let (parsing_errors, file_map, format_report) = format_file(filename, config); + if parsing_errors { return Err(IdempotentCheckError::Parse); } @@ -779,10 +819,15 @@ impl ConfigCodeBlock { config.set().emit_mode(EmitMode::Stdout); let mut buf: Vec = vec![]; - let (error_summary, _) = format_input(input, &config, Some(&mut buf)).unwrap(); + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + if self.has_parsing_errors(session.summary) { + return false; + } + } - !self.has_parsing_errors(error_summary) - && !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) + !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) } // Extract a code block from the iterator. Behavior: -- cgit 1.4.1-3-g733a5 From 09a8c6d22b46afd8c6ea9d97860f8917f43d00e1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 23 Jul 2018 20:01:45 +1200 Subject: Refactoring: move code around in formatting To try and make cleaner abstractions and to start to separate formatting from other tasks. --- src/formatting.rs | 314 ++++++++++++++++++++++++++---------------------------- src/lib.rs | 9 ++ 2 files changed, 163 insertions(+), 160 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 53e673c5e7a..d0184d6ea0e 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -103,82 +103,15 @@ pub(crate) struct ReportedErrors { pub(crate) has_check_errors: bool, } -fn should_emit_verbose(path: &FileName, config: &Config, f: F) +fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) where F: Fn(), { - if config.verbose() == Verbosity::Verbose && path != &FileName::Stdin { + if config.verbose() == Verbosity::Verbose && !is_stdin { f(); } } -// Formatting which depends on the AST. -fn format_ast( - krate: &ast::Crate, - parse_session: &mut ParseSess, - main_file: &FileName, - config: &Config, - report: FormatReport, - mut after_file: F, -) -> Result<(FileMap, bool, bool), io::Error> -where - F: FnMut(&FileName, &mut String, &[(usize, usize)], &FormatReport) -> Result, -{ - let mut result = FileMap::new(); - // diff mode: check if any files are differing - let mut has_diff = false; - let mut has_macro_rewrite_failure = false; - - let skip_children = config.skip_children(); - for (path, module) in modules::list_files(krate, parse_session.codemap())? { - if (skip_children && path != *main_file) || config.ignore().skip_file(&path) { - continue; - } - should_emit_verbose(&path, config, || println!("Formatting {}", path)); - let filemap = parse_session - .codemap() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = - FmtVisitor::from_codemap(parse_session, config, &snippet_provider, report.clone()); - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == *main_file { - visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, &*filemap); - } - } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); - visitor.format_separate_mod(module, &*filemap); - }; - - debug_assert_eq!( - visitor.line_number, - ::utils::count_newlines(&visitor.buffer) - ); - - has_diff |= match after_file(&path, &mut visitor.buffer, &visitor.skipped_range, &report) { - Ok(result) => result, - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg)); - } - }; - - has_macro_rewrite_failure |= visitor.macro_rewrite_failure; - - result.push((path.clone(), visitor.buffer)); - } - - Ok((result, has_diff, has_macro_rewrite_failure)) -} - /// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { skipped_range @@ -380,32 +313,63 @@ impl<'b, T: Write + 'b> Session<'b, T> { } return Ok((FileMap::new(), FormatReport::new())); } - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - let tty_handler = if self.config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - Handler::with_emitter(true, false, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) - }; - let mut parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone()); + let input_is_stdin = input.is_text(); + let mut filemap = FileMap::new(); + // TODO split Session? out vs config - but what about summary? + // - look at error handling + let format_result = self.format_ast(input, |this, path, mut result| { + if let Some(ref mut out) = this.out { + // TODO pull out the has_diff return value + match filemap::write_file(&mut result, &path, out, &this.config) { + Ok(b) if b => this.summary.add_diff(), + Err(e) => { + // Create a new error with path_str to help users see which files failed + let err_msg = format!("{}: {}", path, e); + return Err(io::Error::new(e.kind(), err_msg).into()); + } + _ => {} + } + } + + filemap.push((path, result)); + Ok(()) + }); + + should_emit_verbose(input_is_stdin, &self.config, || { + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } + + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + duration_to_f32(self.summary.get_parse_time().unwrap()), + duration_to_f32(self.summary.get_format_time().unwrap()), + ) + }); + + format_result.map(|r| (filemap, r)) + } + // TODO name, only uses config and summary + // TODO move timing from summary to Session + // Formatting which depends on the AST. + fn format_ast( + &mut self, + input: Input, + mut formatted_file: F, + ) -> Result + where + F: FnMut(&mut Session, FileName, String) -> Result<(), ErrorKind>, + { let main_file = match input { Input::File(ref file) => FileName::Real(file.clone()), Input::Text(..) => FileName::Stdin, }; + // Parse the crate. + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + let mut parse_session = self.make_parse_sess(codemap.clone()); let krate = match parse_input(input, &parse_session, &self.config) { Ok(krate) => krate, Err(err) => { @@ -415,7 +379,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { // Note that if you see this message and want more information, // then go to `parse_input` and run the parse function without // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(&main_file, &self.config, || { + should_emit_verbose(main_file != FileName::Stdin, &self.config, || { println!("The Rust parser panicked") }); } @@ -425,10 +389,9 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::ParseError); } }; - self.summary.mark_parse_time(); - // Suppress error output after parsing. + // Suppress error output if we have to do any further parsing. let silent_emitter = Box::new(EmitterWriter::new( Box::new(Vec::new()), Some(codemap.clone()), @@ -439,43 +402,69 @@ impl<'b, T: Write + 'b> Session<'b, T> { let report = FormatReport::new(); - let config = &self.config; - let out = &mut self.out; - let format_result = format_ast( - &krate, - &mut parse_session, - &main_file, - config, - report.clone(), - |file_name, file, skipped_range, report| { - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(file); - - format_lines(file, file_name, skipped_range, config, report); - replace_with_system_newlines(file, config); - - if let Some(ref mut out) = out { - return filemap::write_file(file, file_name, out, config); + let skip_children = self.config.skip_children(); + for (path, module) in modules::list_files(&krate, parse_session.codemap())? { + if (skip_children && path != main_file) || self.config.ignore().skip_file(&path) { + continue; + } + should_emit_verbose(main_file != FileName::Stdin, &self.config, || { + println!("Formatting {}", path) + }); + let filemap = parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = FmtVisitor::from_codemap( + &parse_session, + &self.config, + &snippet_provider, + report.clone(), + ); + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == main_file { + visitor.skip_empty_lines(filemap.end_pos); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); + } else { + visitor.format_separate_mod(module, &*filemap); } - Ok(false) - }, - ); - - self.summary.mark_format_time(); + } else { + visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); + visitor.format_separate_mod(module, &*filemap); + }; - should_emit_verbose(&main_file, &self.config, || { - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + debug_assert_eq!( + visitor.line_number, + ::utils::count_newlines(&visitor.buffer) + ); + + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(&mut visitor.buffer); + + format_lines( + &mut visitor.buffer, + &path, + &visitor.skipped_range, + &self.config, + &report, + ); + self.replace_with_system_newlines(&mut visitor.buffer); + + if visitor.macro_rewrite_failure { + self.summary.add_macro_foramt_failure(); } - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(self.summary.get_parse_time().unwrap()), - duration_to_f32(self.summary.get_format_time().unwrap()), - ) - }); + formatted_file(self, path, visitor.buffer)?; + } + self.summary.mark_format_time(); + if report.has_warnings() { + self.summary.add_formatting_error(); + } { let report_errs = &report.internal.borrow().1; if report_errs.has_check_errors { @@ -486,52 +475,57 @@ impl<'b, T: Write + 'b> Session<'b, T> { } } - match format_result { - Ok((file_map, has_diff, has_macro_rewrite_failure)) => { - if report.has_warnings() { - self.summary.add_formatting_error(); - } - - if has_diff { - self.summary.add_diff(); - } + Ok(report) + } - if has_macro_rewrite_failure { - self.summary.add_macro_foramt_failure(); - } + fn make_parse_sess(&self, codemap: Rc) -> ParseSess { + let tty_handler = if self.config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; - Ok((file_map, report)) - } - Err(e) => Err(From::from(e)), - } + ParseSess::with_span_handler(tty_handler, codemap) } -} -fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows + fn replace_with_system_newlines(&self, text: &mut String) -> () { + let style = if self.config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; + self.config.newline_style() + }; - match style { - NewlineStyle::Unix => return, - NewlineStyle::Windows => { - let mut transformed = String::with_capacity(text.capacity()); - for c in text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), + match style { + NewlineStyle::Unix => return, + NewlineStyle::Windows => { + let mut transformed = String::with_capacity(text.capacity()); + for c in text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } } + *text = transformed; } - *text = transformed; + NewlineStyle::Native => unreachable!(), } - NewlineStyle::Native => unreachable!(), } } diff --git a/src/lib.rs b/src/lib.rs index 6183117a58c..c35fb25f777 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -495,6 +495,15 @@ pub enum Input { Text(String), } +impl Input { + fn is_text(&self) -> bool { + match *self { + Input::File(_) => false, + Input::Text(_) => true, + } + } +} + #[cfg(test)] mod unit_tests { use super::*; -- cgit 1.4.1-3-g733a5 From 069c4fc50871acfcf41f8726107daa26a29b488c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 08:42:33 +1200 Subject: Refactoring: summary Move the timer from Summary to Session. Move Summary from config to formatting. --- src/config/mod.rs | 1 - src/config/summary.rs | 160 -------------------------------------------------- src/formatting.rs | 145 ++++++++++++++++++++++++++++++++++++++++++--- src/lib.rs | 7 ++- src/test/mod.rs | 3 +- 5 files changed, 143 insertions(+), 173 deletions(-) delete mode 100644 src/config/summary.rs (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index ba6596c3da7..42686483419 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -29,7 +29,6 @@ pub mod options; pub mod file_lines; pub mod license; pub mod lists; -pub mod summary; /// This macro defines configuration options used in rustfmt. Each option /// is defined as follows: diff --git a/src/config/summary.rs b/src/config/summary.rs deleted file mode 100644 index 1ef6d18a540..00000000000 --- a/src/config/summary.rs +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::default::Default; -use std::time::{Duration, Instant}; - -/// A summary of a Rustfmt run. -#[derive(Debug, Default, Clone, Copy)] -pub struct Summary { - // Encountered e.g. an IO error. - has_operational_errors: bool, - - // Failed to reformat code because of parsing errors. - has_parsing_errors: bool, - - // Code is valid, but it is impossible to format it properly. - has_formatting_errors: bool, - - // Code contains macro call that was unable to format. - pub(crate) has_macro_format_failure: bool, - - // Failed a check, such as the license check or other opt-in checking. - has_check_errors: bool, - - /// Formatted code differs from existing code (--check only). - pub has_diff: bool, - - // Keeps track of time spent in parsing and formatting steps. - timer: Timer, -} - -impl Summary { - pub(crate) fn mark_parse_time(&mut self) { - self.timer = self.timer.done_parsing(); - } - - pub(crate) fn mark_format_time(&mut self) { - self.timer = self.timer.done_formatting(); - } - - /// Returns the time it took to parse the source files in nanoseconds. - pub(crate) fn get_parse_time(&self) -> Option { - match self.timer { - Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { - // This should never underflow since `Instant::now()` guarantees monotonicity. - Some(parse_time.duration_since(init)) - } - Timer::Initialized(..) => None, - } - } - - /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is - /// not included. - pub(crate) fn get_format_time(&self) -> Option { - match self.timer { - Timer::DoneFormatting(_init, parse_time, format_time) => { - Some(format_time.duration_since(parse_time)) - } - Timer::DoneParsing(..) | Timer::Initialized(..) => None, - } - } - - pub fn has_operational_errors(&self) -> bool { - self.has_operational_errors - } - - pub fn has_parsing_errors(&self) -> bool { - self.has_parsing_errors - } - - pub fn has_formatting_errors(&self) -> bool { - self.has_formatting_errors - } - - pub fn has_check_errors(&self) -> bool { - self.has_check_errors - } - - pub(crate) fn has_macro_formatting_failure(&self) -> bool { - self.has_macro_format_failure - } - - pub fn add_operational_error(&mut self) { - self.has_operational_errors = true; - } - - pub(crate) fn add_parsing_error(&mut self) { - self.has_parsing_errors = true; - } - - pub(crate) fn add_formatting_error(&mut self) { - self.has_formatting_errors = true; - } - - pub(crate) fn add_check_error(&mut self) { - self.has_check_errors = true; - } - - pub(crate) fn add_diff(&mut self) { - self.has_diff = true; - } - - pub(crate) fn add_macro_foramt_failure(&mut self) { - self.has_macro_format_failure = true; - } - - pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors - || self.has_parsing_errors - || self.has_formatting_errors - || self.has_diff) - } - - /// Combine two summaries together. - pub fn add(&mut self, other: Summary) { - self.has_operational_errors |= other.has_operational_errors; - self.has_formatting_errors |= other.has_formatting_errors; - self.has_parsing_errors |= other.has_parsing_errors; - self.has_check_errors |= other.has_check_errors; - self.has_diff |= other.has_diff; - } -} - -#[derive(Clone, Copy, Debug)] -enum Timer { - Initialized(Instant), - DoneParsing(Instant, Instant), - DoneFormatting(Instant, Instant, Instant), -} - -impl Default for Timer { - fn default() -> Self { - Timer::Initialized(Instant::now()) - } -} - -impl Timer { - fn done_parsing(self) -> Self { - match self { - Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), - _ => panic!("Timer can only transition to DoneParsing from Initialized state"), - } - } - - fn done_formatting(self) -> Self { - match self { - Timer::DoneParsing(init_time, parse_time) => { - Timer::DoneFormatting(init_time, parse_time, Instant::now()) - } - _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), - } - } -} diff --git a/src/formatting.rs b/src/formatting.rs index d0184d6ea0e..43651fb4559 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::io::{self, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::rc::Rc; -use std::time::Duration; +use std::time::{Duration, Instant}; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping, Span}; @@ -13,12 +13,11 @@ use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use comment::{CharClasses, FullCodeCharKind}; +use config::{Config, FileName, NewlineStyle, Verbosity}; use issues::BadIssueSeeker; use visitor::{FmtVisitor, SnippetProvider}; use {filemap, modules, ErrorKind, FormatReport, Input, Session}; -use config::{Config, FileName, NewlineStyle, Verbosity}; - // A map of the files of a crate, with their new content pub(crate) type FileMap = Vec; @@ -343,8 +342,8 @@ impl<'b, T: Write + 'b> Session<'b, T> { println!( "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(self.summary.get_parse_time().unwrap()), - duration_to_f32(self.summary.get_format_time().unwrap()), + duration_to_f32(self.get_parse_time().unwrap()), + duration_to_f32(self.get_format_time().unwrap()), ) }); @@ -352,7 +351,6 @@ impl<'b, T: Write + 'b> Session<'b, T> { } // TODO name, only uses config and summary - // TODO move timing from summary to Session // Formatting which depends on the AST. fn format_ast( &mut self, @@ -389,7 +387,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::ParseError); } }; - self.summary.mark_parse_time(); + self.timer = self.timer.done_parsing(); // Suppress error output if we have to do any further parsing. let silent_emitter = Box::new(EmitterWriter::new( @@ -460,7 +458,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { formatted_file(self, path, visitor.buffer)?; } - self.summary.mark_format_time(); + self.timer = self.timer.done_formatting(); if report.has_warnings() { self.summary.add_formatting_error(); @@ -527,6 +525,28 @@ impl<'b, T: Write + 'b> Session<'b, T> { NewlineStyle::Native => unreachable!(), } } + + /// Returns the time it took to parse the source files in nanoseconds. + fn get_parse_time(&self) -> Option { + match self.timer { + Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { + // This should never underflow since `Instant::now()` guarantees monotonicity. + Some(parse_time.duration_since(init)) + } + Timer::Initialized(..) => None, + } + } + + /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is + /// not included. + fn get_format_time(&self) -> Option { + match self.timer { + Timer::DoneFormatting(_init, parse_time, format_time) => { + Some(format_time.duration_since(parse_time)) + } + Timer::DoneParsing(..) | Timer::Initialized(..) => None, + } + } } /// A single span of changed lines, with 0 or more removed lines @@ -547,3 +567,112 @@ pub(crate) struct ModifiedLines { /// The set of changed chunks. pub chunks: Vec, } + +#[derive(Clone, Copy, Debug)] +pub(crate) enum Timer { + Initialized(Instant), + DoneParsing(Instant, Instant), + DoneFormatting(Instant, Instant, Instant), +} + +impl Timer { + fn done_parsing(self) -> Self { + match self { + Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), + _ => panic!("Timer can only transition to DoneParsing from Initialized state"), + } + } + + fn done_formatting(self) -> Self { + match self { + Timer::DoneParsing(init_time, parse_time) => { + Timer::DoneFormatting(init_time, parse_time, Instant::now()) + } + _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), + } + } +} + +/// A summary of a Rustfmt run. +#[derive(Debug, Default, Clone, Copy)] +pub struct Summary { + // Encountered e.g. an IO error. + has_operational_errors: bool, + + // Failed to reformat code because of parsing errors. + has_parsing_errors: bool, + + // Code is valid, but it is impossible to format it properly. + has_formatting_errors: bool, + + // Code contains macro call that was unable to format. + pub(crate) has_macro_format_failure: bool, + + // Failed a check, such as the license check or other opt-in checking. + has_check_errors: bool, + + /// Formatted code differs from existing code (--check only). + pub has_diff: bool, +} + +impl Summary { + pub fn has_operational_errors(&self) -> bool { + self.has_operational_errors + } + + pub fn has_parsing_errors(&self) -> bool { + self.has_parsing_errors + } + + pub fn has_formatting_errors(&self) -> bool { + self.has_formatting_errors + } + + pub fn has_check_errors(&self) -> bool { + self.has_check_errors + } + + pub(crate) fn has_macro_formatting_failure(&self) -> bool { + self.has_macro_format_failure + } + + pub fn add_operational_error(&mut self) { + self.has_operational_errors = true; + } + + pub(crate) fn add_parsing_error(&mut self) { + self.has_parsing_errors = true; + } + + pub(crate) fn add_formatting_error(&mut self) { + self.has_formatting_errors = true; + } + + pub(crate) fn add_check_error(&mut self) { + self.has_check_errors = true; + } + + pub(crate) fn add_diff(&mut self) { + self.has_diff = true; + } + + pub(crate) fn add_macro_foramt_failure(&mut self) { + self.has_macro_format_failure = true; + } + + pub fn has_no_errors(&self) -> bool { + !(self.has_operational_errors + || self.has_parsing_errors + || self.has_formatting_errors + || self.has_diff) + } + + /// Combine two summaries together. + pub fn add(&mut self, other: Summary) { + self.has_operational_errors |= other.has_operational_errors; + self.has_formatting_errors |= other.has_formatting_errors; + self.has_parsing_errors |= other.has_parsing_errors; + self.has_check_errors |= other.has_check_errors; + self.has_diff |= other.has_diff; + } +} diff --git a/src/lib.rs b/src/lib.rs index c35fb25f777..2cbe5c46e30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,15 +45,15 @@ use std::io::{self, Write}; use std::mem; use std::path::PathBuf; use std::rc::Rc; +use std::time::Instant; use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{FormatErrorMap, FormattingError, ReportedErrors}; +use formatting::{FormatErrorMap, FormattingError, ReportedErrors, Summary, Timer}; use issues::Issue; use shape::Indent; -pub use config::summary::Summary; pub use config::{ load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, NewlineStyle, Range, Verbosity, @@ -445,6 +445,8 @@ pub struct Session<'b, T: Write + 'b> { pub config: Config, pub out: Option<&'b mut T>, pub summary: Summary, + // Keeps track of time spent in parsing and formatting steps. + timer: Timer, } impl<'b, T: Write + 'b> Session<'b, T> { @@ -457,6 +459,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { config, out, summary: Summary::default(), + timer: Timer::Initialized(Instant::now()), } } diff --git a/src/test/mod.rs b/src/test/mod.rs index f02cfbc858c..d670bc1d5db 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -20,10 +20,9 @@ use std::iter::{Enumerate, Peekable}; use std::path::{Path, PathBuf}; use std::str::Chars; -use config::summary::Summary; use config::{Color, Config, EmitMode, FileName, ReportTactic}; use filemap; -use formatting::{FileMap, ModifiedChunk}; +use formatting::{FileMap, ModifiedChunk, Summary}; use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; use {FormatReport, Input, Session}; -- cgit 1.4.1-3-g733a5 From 920a50ded91cf108ca29ce85dab7eda3b5a76309 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 09:03:31 +1200 Subject: Refactoring: return a summary from `format_project` Rather than modifying `self.summary`. Also move some Timer methods. --- src/formatting.rs | 82 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 43651fb4559..6c545632aeb 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -315,11 +315,9 @@ impl<'b, T: Write + 'b> Session<'b, T> { let input_is_stdin = input.is_text(); let mut filemap = FileMap::new(); - // TODO split Session? out vs config - but what about summary? - // - look at error handling - let format_result = self.format_ast(input, |this, path, mut result| { + // TODO split Session? out vs config? + let format_result = self.format_project(input, |this, path, mut result| { if let Some(ref mut out) = this.out { - // TODO pull out the has_diff return value match filemap::write_file(&mut result, &path, out, &this.config) { Ok(b) if b => this.summary.add_diff(), Err(e) => { @@ -342,24 +340,27 @@ impl<'b, T: Write + 'b> Session<'b, T> { println!( "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(self.get_parse_time().unwrap()), - duration_to_f32(self.get_format_time().unwrap()), + duration_to_f32(self.timer.get_parse_time().unwrap()), + duration_to_f32(self.timer.get_format_time().unwrap()), ) }); - format_result.map(|r| (filemap, r)) + format_result.map(|(result, summary)| { + self.summary.add(summary); + (filemap, result) + }) } - // TODO name, only uses config and summary - // Formatting which depends on the AST. - fn format_ast( + // TODO only uses config and timer + fn format_project( &mut self, input: Input, mut formatted_file: F, - ) -> Result + ) -> Result<(FormatReport, Summary), ErrorKind> where F: FnMut(&mut Session, FileName, String) -> Result<(), ErrorKind>, { + let mut summary = Summary::default(); let main_file = match input { Input::File(ref file) => FileName::Real(file.clone()), Input::Text(..) => FileName::Stdin, @@ -383,7 +384,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { } ParseError::Recovered => {} } - self.summary.add_parsing_error(); + summary.add_parsing_error(); return Err(ErrorKind::ParseError); } }; @@ -453,7 +454,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { self.replace_with_system_newlines(&mut visitor.buffer); if visitor.macro_rewrite_failure { - self.summary.add_macro_foramt_failure(); + summary.add_macro_format_failure(); } formatted_file(self, path, visitor.buffer)?; @@ -461,19 +462,19 @@ impl<'b, T: Write + 'b> Session<'b, T> { self.timer = self.timer.done_formatting(); if report.has_warnings() { - self.summary.add_formatting_error(); + summary.add_formatting_error(); } { let report_errs = &report.internal.borrow().1; if report_errs.has_check_errors { - self.summary.add_check_error(); + summary.add_check_error(); } if report_errs.has_operational_errors { - self.summary.add_operational_error(); + summary.add_operational_error(); } } - Ok(report) + Ok((report, summary)) } fn make_parse_sess(&self, codemap: Rc) -> ParseSess { @@ -525,28 +526,6 @@ impl<'b, T: Write + 'b> Session<'b, T> { NewlineStyle::Native => unreachable!(), } } - - /// Returns the time it took to parse the source files in nanoseconds. - fn get_parse_time(&self) -> Option { - match self.timer { - Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { - // This should never underflow since `Instant::now()` guarantees monotonicity. - Some(parse_time.duration_since(init)) - } - Timer::Initialized(..) => None, - } - } - - /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is - /// not included. - fn get_format_time(&self) -> Option { - match self.timer { - Timer::DoneFormatting(_init, parse_time, format_time) => { - Some(format_time.duration_since(parse_time)) - } - Timer::DoneParsing(..) | Timer::Initialized(..) => None, - } - } } /// A single span of changed lines, with 0 or more removed lines @@ -591,6 +570,28 @@ impl Timer { _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), } } + + /// Returns the time it took to parse the source files in nanoseconds. + fn get_parse_time(&self) -> Option { + match *self { + Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { + // This should never underflow since `Instant::now()` guarantees monotonicity. + Some(parse_time.duration_since(init)) + } + Timer::Initialized(..) => None, + } + } + + /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is + /// not included. + fn get_format_time(&self) -> Option { + match *self { + Timer::DoneFormatting(_init, parse_time, format_time) => { + Some(format_time.duration_since(parse_time)) + } + Timer::DoneParsing(..) | Timer::Initialized(..) => None, + } + } } /// A summary of a Rustfmt run. @@ -656,7 +657,7 @@ impl Summary { self.has_diff = true; } - pub(crate) fn add_macro_foramt_failure(&mut self) { + pub(crate) fn add_macro_format_failure(&mut self) { self.has_macro_format_failure = true; } @@ -671,6 +672,7 @@ impl Summary { pub fn add(&mut self, other: Summary) { self.has_operational_errors |= other.has_operational_errors; self.has_formatting_errors |= other.has_formatting_errors; + self.has_macro_format_failure |= other.has_macro_format_failure; self.has_parsing_errors |= other.has_parsing_errors; self.has_check_errors |= other.has_check_errors; self.has_diff |= other.has_diff; -- cgit 1.4.1-3-g733a5 From b9c6754d8c0d92f9d205fcc48d23d2f5a2b9fc72 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 10:08:41 +1200 Subject: Refactoring: move `format_project` and `Timer` out of Session --- src/formatting.rs | 353 +++++++++++++++++++++++++++--------------------------- src/lib.rs | 6 +- 2 files changed, 176 insertions(+), 183 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 6c545632aeb..1c196ca3b75 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -313,13 +313,12 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Ok((FileMap::new(), FormatReport::new())); } - let input_is_stdin = input.is_text(); let mut filemap = FileMap::new(); - // TODO split Session? out vs config? - let format_result = self.format_project(input, |this, path, mut result| { - if let Some(ref mut out) = this.out { - match filemap::write_file(&mut result, &path, out, &this.config) { - Ok(b) if b => this.summary.add_diff(), + let config = &self.config.clone(); + let format_result = format_project(input, config, |path, mut result| { + if let Some(ref mut out) = self.out { + match filemap::write_file(&mut result, &path, out, &self.config) { + Ok(b) if b => self.summary.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed let err_msg = format!("{}: {}", path, e); @@ -333,198 +332,192 @@ impl<'b, T: Write + 'b> Session<'b, T> { Ok(()) }); - should_emit_verbose(input_is_stdin, &self.config, || { - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 - } - - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - duration_to_f32(self.timer.get_parse_time().unwrap()), - duration_to_f32(self.timer.get_format_time().unwrap()), - ) - }); - format_result.map(|(result, summary)| { self.summary.add(summary); (filemap, result) }) } +} - // TODO only uses config and timer - fn format_project( - &mut self, - input: Input, - mut formatted_file: F, - ) -> Result<(FormatReport, Summary), ErrorKind> - where - F: FnMut(&mut Session, FileName, String) -> Result<(), ErrorKind>, - { - let mut summary = Summary::default(); - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Stdin, - }; - - // Parse the crate. - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - let mut parse_session = self.make_parse_sess(codemap.clone()); - let krate = match parse_input(input, &parse_session, &self.config) { - Ok(krate) => krate, - Err(err) => { - match err { - ParseError::Error(mut diagnostic) => diagnostic.emit(), - ParseError::Panic => { - // Note that if you see this message and want more information, - // then go to `parse_input` and run the parse function without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(main_file != FileName::Stdin, &self.config, || { - println!("The Rust parser panicked") - }); - } - ParseError::Recovered => {} - } - summary.add_parsing_error(); - return Err(ErrorKind::ParseError); - } - }; - self.timer = self.timer.done_parsing(); - - // Suppress error output if we have to do any further parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); +fn format_project( + input: Input, + config: &Config, + mut formatted_file: F, +) -> Result<(FormatReport, Summary), ErrorKind> +where + F: FnMut(FileName, String) -> Result<(), ErrorKind>, +{ + let mut summary = Summary::default(); + let mut timer = Timer::Initialized(Instant::now()); - let report = FormatReport::new(); + let input_is_stdin = input.is_text(); + let main_file = match input { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Stdin, + }; - let skip_children = self.config.skip_children(); - for (path, module) in modules::list_files(&krate, parse_session.codemap())? { - if (skip_children && path != main_file) || self.config.ignore().skip_file(&path) { - continue; - } - should_emit_verbose(main_file != FileName::Stdin, &self.config, || { - println!("Formatting {}", path) - }); - let filemap = parse_session - .codemap() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = FmtVisitor::from_codemap( - &parse_session, - &self.config, - &snippet_provider, - report.clone(), - ); - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == main_file { - visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, &*filemap); + // Parse the crate. + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + let mut parse_session = make_parse_sess(codemap.clone(), config); + let krate = match parse_input(input, &parse_session, config) { + Ok(krate) => krate, + Err(err) => { + match err { + ParseError::Error(mut diagnostic) => diagnostic.emit(), + ParseError::Panic => { + // Note that if you see this message and want more information, + // then go to `parse_input` and run the parse function without + // `catch_unwind` so rustfmt panics and you can get a backtrace. + should_emit_verbose(main_file != FileName::Stdin, config, || { + println!("The Rust parser panicked") + }); } + ParseError::Recovered => {} + } + summary.add_parsing_error(); + return Err(ErrorKind::ParseError); + } + }; + timer = timer.done_parsing(); + + // Suppress error output if we have to do any further parsing. + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + + let report = FormatReport::new(); + + let skip_children = config.skip_children(); + for (path, module) in modules::list_files(&krate, parse_session.codemap())? { + if (skip_children && path != main_file) || config.ignore().skip_file(&path) { + continue; + } + should_emit_verbose(main_file != FileName::Stdin, config, || { + println!("Formatting {}", path) + }); + let filemap = parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = + FmtVisitor::from_codemap(&parse_session, config, &snippet_provider, report.clone()); + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == main_file { + visitor.skip_empty_lines(filemap.end_pos); + if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); visitor.format_separate_mod(module, &*filemap); - }; - - debug_assert_eq!( - visitor.line_number, - ::utils::count_newlines(&visitor.buffer) - ); - - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(&mut visitor.buffer); - - format_lines( - &mut visitor.buffer, - &path, - &visitor.skipped_range, - &self.config, - &report, - ); - self.replace_with_system_newlines(&mut visitor.buffer); - - if visitor.macro_rewrite_failure { - summary.add_macro_format_failure(); } + } else { + visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); + visitor.format_separate_mod(module, &*filemap); + }; - formatted_file(self, path, visitor.buffer)?; + debug_assert_eq!( + visitor.line_number, + ::utils::count_newlines(&visitor.buffer) + ); + + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(&mut visitor.buffer); + + format_lines( + &mut visitor.buffer, + &path, + &visitor.skipped_range, + config, + &report, + ); + replace_with_system_newlines(&mut visitor.buffer, config); + + if visitor.macro_rewrite_failure { + summary.add_macro_format_failure(); } - self.timer = self.timer.done_formatting(); - if report.has_warnings() { - summary.add_formatting_error(); + formatted_file(path, visitor.buffer)?; + } + timer = timer.done_formatting(); + + should_emit_verbose(input_is_stdin, config, || { + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + timer.get_parse_time(), + timer.get_format_time(), + ) + }); + + if report.has_warnings() { + summary.add_formatting_error(); + } + { + let report_errs = &report.internal.borrow().1; + if report_errs.has_check_errors { + summary.add_check_error(); } - { - let report_errs = &report.internal.borrow().1; - if report_errs.has_check_errors { - summary.add_check_error(); - } - if report_errs.has_operational_errors { - summary.add_operational_error(); - } + if report_errs.has_operational_errors { + summary.add_operational_error(); } - - Ok((report, summary)) } - fn make_parse_sess(&self, codemap: Rc) -> ParseSess { - let tty_handler = if self.config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - Handler::with_emitter(true, false, silent_emitter) + Ok((report, summary)) +} + +fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { + let tty_handler = if config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + ColorConfig::Never }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; - ParseSess::with_span_handler(tty_handler, codemap) - } + ParseSess::with_span_handler(tty_handler, codemap) +} - fn replace_with_system_newlines(&self, text: &mut String) -> () { - let style = if self.config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } +fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { + let style = if config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows } else { - self.config.newline_style() - }; + NewlineStyle::Unix + } + } else { + config.newline_style() + }; - match style { - NewlineStyle::Unix => return, - NewlineStyle::Windows => { - let mut transformed = String::with_capacity(text.capacity()); - for c in text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } + match style { + NewlineStyle::Unix => return, + NewlineStyle::Windows => { + let mut transformed = String::with_capacity(text.capacity()); + for c in text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), } - *text = transformed; } - NewlineStyle::Native => unreachable!(), + *text = transformed; } + NewlineStyle::Native => unreachable!(), } } @@ -548,7 +541,7 @@ pub(crate) struct ModifiedLines { } #[derive(Clone, Copy, Debug)] -pub(crate) enum Timer { +enum Timer { Initialized(Instant), DoneParsing(Instant, Instant), DoneFormatting(Instant, Instant, Instant), @@ -571,27 +564,31 @@ impl Timer { } } - /// Returns the time it took to parse the source files in nanoseconds. - fn get_parse_time(&self) -> Option { + /// Returns the time it took to parse the source files in seconds. + fn get_parse_time(&self) -> f32 { match *self { Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { // This should never underflow since `Instant::now()` guarantees monotonicity. - Some(parse_time.duration_since(init)) + Self::duration_to_f32(parse_time.duration_since(init)) } - Timer::Initialized(..) => None, + Timer::Initialized(..) => unreachable!(), } } /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is /// not included. - fn get_format_time(&self) -> Option { + fn get_format_time(&self) -> f32 { match *self { Timer::DoneFormatting(_init, parse_time, format_time) => { - Some(format_time.duration_since(parse_time)) + Self::duration_to_f32(format_time.duration_since(parse_time)) } - Timer::DoneParsing(..) | Timer::Initialized(..) => None, + Timer::DoneParsing(..) | Timer::Initialized(..) => unreachable!(), } } + + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } } /// A summary of a Rustfmt run. diff --git a/src/lib.rs b/src/lib.rs index 2cbe5c46e30..4d90f5a223e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,12 +45,11 @@ use std::io::{self, Write}; use std::mem; use std::path::PathBuf; use std::rc::Rc; -use std::time::Instant; use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{FormatErrorMap, FormattingError, ReportedErrors, Summary, Timer}; +use formatting::{FormatErrorMap, FormattingError, ReportedErrors, Summary}; use issues::Issue; use shape::Indent; @@ -445,8 +444,6 @@ pub struct Session<'b, T: Write + 'b> { pub config: Config, pub out: Option<&'b mut T>, pub summary: Summary, - // Keeps track of time spent in parsing and formatting steps. - timer: Timer, } impl<'b, T: Write + 'b> Session<'b, T> { @@ -459,7 +456,6 @@ impl<'b, T: Write + 'b> Session<'b, T> { config, out, summary: Summary::default(), - timer: Timer::Initialized(Instant::now()), } } -- cgit 1.4.1-3-g733a5 From 2af1ed109c95747cd674ace5758b175ff1f5e50f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 10:33:24 +1200 Subject: Refactoring: factor out `format_file` and `FormatHandler` This effectively separates out formatting from other handling. --- src/formatting.rs | 211 +++++++++++++++++++++++++++++++++--------------------- src/lib.rs | 10 ++- src/test/mod.rs | 13 ++-- 3 files changed, 140 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 1c196ca3b75..71ebe9d4102 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -20,7 +20,6 @@ use {filemap, modules, ErrorKind, FormatReport, Input, Session}; // A map of the files of a crate, with their new content pub(crate) type FileMap = Vec; - pub(crate) type FileRecord = (FileName, String); pub(crate) struct FormattingError { @@ -297,56 +296,72 @@ enum ParseError<'sess> { } impl<'b, T: Write + 'b> Session<'b, T> { - pub(crate) fn format_input_inner( - &mut self, - input: Input, - ) -> Result<(FileMap, FormatReport), ErrorKind> { - syntax_pos::hygiene::set_default_edition(self.config.edition().to_libsyntax_pos_edition()); - - if self.config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err(From::from(e)); - } - } - return Ok((FileMap::new(), FormatReport::new())); + pub(crate) fn format_input_inner(&mut self, input: Input) -> Result { + if !self.config.version_meets_requirement() { + return Err(ErrorKind::VersionMismatch); } - let mut filemap = FileMap::new(); - let config = &self.config.clone(); - let format_result = format_project(input, config, |path, mut result| { - if let Some(ref mut out) = self.out { - match filemap::write_file(&mut result, &path, out, &self.config) { - Ok(b) if b => self.summary.add_diff(), - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg).into()); + syntax::with_globals(|| { + syntax_pos::hygiene::set_default_edition( + self.config.edition().to_libsyntax_pos_edition(), + ); + + if self.config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err(From::from(e)); } - _ => {} } + return Ok(FormatReport::new()); } - filemap.push((path, result)); - Ok(()) - }); + let config = &self.config.clone(); + let format_result = format_project(input, config, self); - format_result.map(|(result, summary)| { - self.summary.add(summary); - (filemap, result) + format_result.map(|(report, summary)| { + self.summary.add(summary); + report + }) }) } } -fn format_project( +// Handle the results of formatting. +trait FormatHandler { + fn handle_formatted_file(&mut self, path: FileName, result: String) -> Result<(), ErrorKind>; +} + +impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { + // Called for each formatted file. + fn handle_formatted_file( + &mut self, + path: FileName, + mut result: String, + ) -> Result<(), ErrorKind> { + if let Some(ref mut out) = self.out { + match filemap::write_file(&mut result, &path, out, &self.config) { + Ok(b) if b => self.summary.add_diff(), + Err(e) => { + // Create a new error with path_str to help users see which files failed + let err_msg = format!("{}: {}", path, e); + return Err(io::Error::new(e.kind(), err_msg).into()); + } + _ => {} + } + } + + self.filemap.push((path, result)); + Ok(()) + } +} + +// Format an entire crate (or subset of the module tree). +fn format_project( input: Input, config: &Config, - mut formatted_file: F, -) -> Result<(FormatReport, Summary), ErrorKind> -where - F: FnMut(FileName, String) -> Result<(), ErrorKind>, -{ + handler: &mut T, +) -> Result<(FormatReport, Summary), ErrorKind> { let mut summary = Summary::default(); let mut timer = Timer::Initialized(Instant::now()); @@ -368,7 +383,7 @@ where // Note that if you see this message and want more information, // then go to `parse_input` and run the parse function without // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(main_file != FileName::Stdin, config, || { + should_emit_verbose(!input_is_stdin, config, || { println!("The Rust parser panicked") }); } @@ -389,28 +404,86 @@ where )); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - let report = FormatReport::new(); - - let skip_children = config.skip_children(); - for (path, module) in modules::list_files(&krate, parse_session.codemap())? { - if (skip_children && path != main_file) || config.ignore().skip_file(&path) { + let mut context = FormatContext::new( + &krate, + FormatReport::new(), + summary, + parse_session, + config, + handler, + ); + + let files = modules::list_files(&krate, context.parse_session.codemap())?; + for (path, module) in files { + if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { continue; } - should_emit_verbose(main_file != FileName::Stdin, config, || { - println!("Formatting {}", path) - }); - let filemap = parse_session + should_emit_verbose(!input_is_stdin, config, || println!("Formatting {}", path)); + let is_root = path == main_file; + context.format_file(path, module, is_root)?; + } + timer = timer.done_formatting(); + + should_emit_verbose(!input_is_stdin, config, || { + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + timer.get_parse_time(), + timer.get_format_time(), + ) + }); + + if context.report.has_warnings() { + context.summary.add_formatting_error(); + } + { + let report_errs = &context.report.internal.borrow().1; + if report_errs.has_check_errors { + context.summary.add_check_error(); + } + if report_errs.has_operational_errors { + context.summary.add_operational_error(); + } + } + + Ok((context.report, context.summary)) +} + +// Used for formatting files. +#[derive(new)] +struct FormatContext<'a, T: FormatHandler + 'a> { + krate: &'a ast::Crate, + report: FormatReport, + summary: Summary, + parse_session: ParseSess, + config: &'a Config, + handler: &'a mut T, +} + +impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { + // Formats a single file/module. + fn format_file( + &mut self, + path: FileName, + module: &ast::Mod, + is_root: bool, + ) -> Result<(), ErrorKind> { + let filemap = self + .parse_session .codemap() .lookup_char_pos(module.inner.lo()) .file; let big_snippet = filemap.src.as_ref().unwrap(); let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = - FmtVisitor::from_codemap(&parse_session, config, &snippet_provider, report.clone()); + let mut visitor = FmtVisitor::from_codemap( + &self.parse_session, + &self.config, + &snippet_provider, + self.report.clone(), + ); // Format inner attributes if available. - if !krate.attrs.is_empty() && path == main_file { + if !self.krate.attrs.is_empty() && is_root { visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner) { + if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); } else { visitor.format_separate_mod(module, &*filemap); @@ -434,41 +507,17 @@ where &mut visitor.buffer, &path, &visitor.skipped_range, - config, - &report, + &self.config, + &self.report, ); - replace_with_system_newlines(&mut visitor.buffer, config); + replace_with_system_newlines(&mut visitor.buffer, &self.config); if visitor.macro_rewrite_failure { - summary.add_macro_format_failure(); + self.summary.add_macro_format_failure(); } - formatted_file(path, visitor.buffer)?; + self.handler.handle_formatted_file(path, visitor.buffer) } - timer = timer.done_formatting(); - - should_emit_verbose(input_is_stdin, config, || { - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - timer.get_parse_time(), - timer.get_format_time(), - ) - }); - - if report.has_warnings() { - summary.add_formatting_error(); - } - { - let report_errs = &report.internal.borrow().1; - if report_errs.has_check_errors { - summary.add_check_error(); - } - if report_errs.has_operational_errors { - summary.add_operational_error(); - } - } - - Ok((report, summary)) } fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { diff --git a/src/lib.rs b/src/lib.rs index 4d90f5a223e..e21bd6c79be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{FormatErrorMap, FormattingError, ReportedErrors, Summary}; +use formatting::{FileMap, FormatErrorMap, FormattingError, ReportedErrors, Summary}; use issues::Issue; use shape::Indent; @@ -444,6 +444,7 @@ pub struct Session<'b, T: Write + 'b> { pub config: Config, pub out: Option<&'b mut T>, pub summary: Summary, + filemap: FileMap, } impl<'b, T: Write + 'b> Session<'b, T> { @@ -456,17 +457,14 @@ impl<'b, T: Write + 'b> Session<'b, T> { config, out, summary: Summary::default(), + filemap: FileMap::new(), } } /// The main entry point for Rustfmt. Formats the given input according to the /// given config. `out` is only necessary if required by the configuration. pub fn format(&mut self, input: Input) -> Result { - if !self.config.version_meets_requirement() { - return Err(ErrorKind::VersionMismatch); - } - - syntax::with_globals(|| self.format_input_inner(input)).map(|tup| tup.1) + self.format_input_inner(input) } pub fn override_config(&mut self, mut config: Config, f: F) -> U diff --git a/src/test/mod.rs b/src/test/mod.rs index d670bc1d5db..63b5f244b90 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -10,13 +10,12 @@ extern crate assert_cli; -use syntax; - use std::collections::{HashMap, HashSet}; use std::env; use std::fs; use std::io::{self, BufRead, BufReader, Read, Write}; use std::iter::{Enumerate, Peekable}; +use std::mem; use std::path::{Path, PathBuf}; use std::str::Chars; @@ -419,11 +418,11 @@ fn format_file>(filepath: P, config: Config) -> (bool, FileMap, let filepath = filepath.into(); let input = Input::File(filepath); let mut session = Session::::new(config, None); - syntax::with_globals(|| { - let result = session.format_input_inner(input).unwrap(); - let parsing_errors = session.summary.has_parsing_errors(); - (parsing_errors, result.0, result.1) - }) + let result = session.format(input).unwrap(); + let parsing_errors = session.summary.has_parsing_errors(); + let mut filemap = FileMap::new(); + mem::swap(&mut session.filemap, &mut filemap); + (parsing_errors, filemap, result) } enum IdempotentCheckError { -- cgit 1.4.1-3-g733a5 From 9fbce1f627afe175c37fe9b8d81fb27269ea9158 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 14:10:09 +1200 Subject: Reorganise formatting.rs --- src/formatting.rs | 870 +++++++++++++++++++++++++++--------------------------- 1 file changed, 435 insertions(+), 435 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 71ebe9d4102..656a18b876f 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -22,6 +22,231 @@ use {filemap, modules, ErrorKind, FormatReport, Input, Session}; pub(crate) type FileMap = Vec; pub(crate) type FileRecord = (FileName, String); +impl<'b, T: Write + 'b> Session<'b, T> { + pub(crate) fn format_input_inner(&mut self, input: Input) -> Result { + if !self.config.version_meets_requirement() { + return Err(ErrorKind::VersionMismatch); + } + + syntax::with_globals(|| { + syntax_pos::hygiene::set_default_edition( + self.config.edition().to_libsyntax_pos_edition(), + ); + + if self.config.disable_all_formatting() { + // When the input is from stdin, echo back the input. + if let Input::Text(ref buf) = input { + if let Err(e) = io::stdout().write_all(buf.as_bytes()) { + return Err(From::from(e)); + } + } + return Ok(FormatReport::new()); + } + + let config = &self.config.clone(); + let format_result = format_project(input, config, self); + + format_result.map(|(report, summary)| { + self.summary.add(summary); + report + }) + }) + } +} + +// Format an entire crate (or subset of the module tree). +fn format_project( + input: Input, + config: &Config, + handler: &mut T, +) -> Result<(FormatReport, Summary), ErrorKind> { + let mut summary = Summary::default(); + let mut timer = Timer::Initialized(Instant::now()); + + let input_is_stdin = input.is_text(); + let main_file = match input { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Stdin, + }; + + // Parse the crate. + let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); + let mut parse_session = make_parse_sess(codemap.clone(), config); + let krate = match parse_input(input, &parse_session, config) { + Ok(krate) => krate, + Err(err) => { + match err { + ParseError::Error(mut diagnostic) => diagnostic.emit(), + ParseError::Panic => { + // Note that if you see this message and want more information, + // then go to `parse_input` and run the parse function without + // `catch_unwind` so rustfmt panics and you can get a backtrace. + should_emit_verbose(!input_is_stdin, config, || { + println!("The Rust parser panicked") + }); + } + ParseError::Recovered => {} + } + summary.add_parsing_error(); + return Err(ErrorKind::ParseError); + } + }; + timer = timer.done_parsing(); + + // Suppress error output if we have to do any further parsing. + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + + let mut context = FormatContext::new( + &krate, + FormatReport::new(), + summary, + parse_session, + config, + handler, + ); + + let files = modules::list_files(&krate, context.parse_session.codemap())?; + for (path, module) in files { + if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { + continue; + } + should_emit_verbose(!input_is_stdin, config, || println!("Formatting {}", path)); + let is_root = path == main_file; + context.format_file(path, module, is_root)?; + } + timer = timer.done_formatting(); + + should_emit_verbose(!input_is_stdin, config, || { + println!( + "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", + timer.get_parse_time(), + timer.get_format_time(), + ) + }); + + if context.report.has_warnings() { + context.summary.add_formatting_error(); + } + { + let report_errs = &context.report.internal.borrow().1; + if report_errs.has_check_errors { + context.summary.add_check_error(); + } + if report_errs.has_operational_errors { + context.summary.add_operational_error(); + } + } + + Ok((context.report, context.summary)) +} + +// Used for formatting files. +#[derive(new)] +struct FormatContext<'a, T: FormatHandler + 'a> { + krate: &'a ast::Crate, + report: FormatReport, + summary: Summary, + parse_session: ParseSess, + config: &'a Config, + handler: &'a mut T, +} + +impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { + // Formats a single file/module. + fn format_file( + &mut self, + path: FileName, + module: &ast::Mod, + is_root: bool, + ) -> Result<(), ErrorKind> { + let filemap = self + .parse_session + .codemap() + .lookup_char_pos(module.inner.lo()) + .file; + let big_snippet = filemap.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); + let mut visitor = FmtVisitor::from_codemap( + &self.parse_session, + &self.config, + &snippet_provider, + self.report.clone(), + ); + // Format inner attributes if available. + if !self.krate.attrs.is_empty() && is_root { + visitor.skip_empty_lines(filemap.end_pos); + if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { + visitor.push_rewrite(module.inner, None); + } else { + visitor.format_separate_mod(module, &*filemap); + } + } else { + visitor.last_pos = filemap.start_pos; + visitor.skip_empty_lines(filemap.end_pos); + visitor.format_separate_mod(module, &*filemap); + }; + + debug_assert_eq!( + visitor.line_number, + ::utils::count_newlines(&visitor.buffer) + ); + + // For some reason, the codemap does not include terminating + // newlines so we must add one on for each file. This is sad. + filemap::append_newline(&mut visitor.buffer); + + format_lines( + &mut visitor.buffer, + &path, + &visitor.skipped_range, + &self.config, + &self.report, + ); + replace_with_system_newlines(&mut visitor.buffer, &self.config); + + if visitor.macro_rewrite_failure { + self.summary.add_macro_format_failure(); + } + + self.handler.handle_formatted_file(path, visitor.buffer) + } +} + +// Handle the results of formatting. +trait FormatHandler { + fn handle_formatted_file(&mut self, path: FileName, result: String) -> Result<(), ErrorKind>; +} + +impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { + // Called for each formatted file. + fn handle_formatted_file( + &mut self, + path: FileName, + mut result: String, + ) -> Result<(), ErrorKind> { + if let Some(ref mut out) = self.out { + match filemap::write_file(&mut result, &path, out, &self.config) { + Ok(b) if b => self.summary.add_diff(), + Err(e) => { + // Create a new error with path_str to help users see which files failed + let err_msg = format!("{}: {}", path, e); + return Err(io::Error::new(e.kind(), err_msg).into()); + } + _ => {} + } + } + + self.filemap.push((path, result)); + Ok(()) + } +} + pub(crate) struct FormattingError { pub(crate) line: usize, pub(crate) kind: ErrorKind, @@ -101,26 +326,181 @@ pub(crate) struct ReportedErrors { pub(crate) has_check_errors: bool, } -fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) -where - F: Fn(), -{ - if config.verbose() == Verbosity::Verbose && !is_stdin { - f(); - } +/// A single span of changed lines, with 0 or more removed lines +/// and a vector of 0 or more inserted lines. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ModifiedChunk { + /// The first to be removed from the original text + pub line_number_orig: u32, + /// The number of lines which have been replaced + pub lines_removed: u32, + /// The new lines + pub lines: Vec, } -/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. -fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { - skipped_range - .iter() - .any(|&(lo, hi)| lo <= line_number && line_number <= hi) +/// Set of changed sections of a file. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ModifiedLines { + /// The set of changed chunks. + pub chunks: Vec, } -fn should_report_error( - config: &Config, - char_kind: FullCodeCharKind, - is_string: bool, +/// A summary of a Rustfmt run. +#[derive(Debug, Default, Clone, Copy)] +pub struct Summary { + // Encountered e.g. an IO error. + has_operational_errors: bool, + + // Failed to reformat code because of parsing errors. + has_parsing_errors: bool, + + // Code is valid, but it is impossible to format it properly. + has_formatting_errors: bool, + + // Code contains macro call that was unable to format. + pub(crate) has_macro_format_failure: bool, + + // Failed a check, such as the license check or other opt-in checking. + has_check_errors: bool, + + /// Formatted code differs from existing code (--check only). + pub has_diff: bool, +} + +impl Summary { + pub fn has_operational_errors(&self) -> bool { + self.has_operational_errors + } + + pub fn has_parsing_errors(&self) -> bool { + self.has_parsing_errors + } + + pub fn has_formatting_errors(&self) -> bool { + self.has_formatting_errors + } + + pub fn has_check_errors(&self) -> bool { + self.has_check_errors + } + + pub(crate) fn has_macro_formatting_failure(&self) -> bool { + self.has_macro_format_failure + } + + pub fn add_operational_error(&mut self) { + self.has_operational_errors = true; + } + + pub(crate) fn add_parsing_error(&mut self) { + self.has_parsing_errors = true; + } + + pub(crate) fn add_formatting_error(&mut self) { + self.has_formatting_errors = true; + } + + pub(crate) fn add_check_error(&mut self) { + self.has_check_errors = true; + } + + pub(crate) fn add_diff(&mut self) { + self.has_diff = true; + } + + pub(crate) fn add_macro_format_failure(&mut self) { + self.has_macro_format_failure = true; + } + + pub fn has_no_errors(&self) -> bool { + !(self.has_operational_errors + || self.has_parsing_errors + || self.has_formatting_errors + || self.has_diff) + } + + /// Combine two summaries together. + pub fn add(&mut self, other: Summary) { + self.has_operational_errors |= other.has_operational_errors; + self.has_formatting_errors |= other.has_formatting_errors; + self.has_macro_format_failure |= other.has_macro_format_failure; + self.has_parsing_errors |= other.has_parsing_errors; + self.has_check_errors |= other.has_check_errors; + self.has_diff |= other.has_diff; + } +} + +#[derive(Clone, Copy, Debug)] +enum Timer { + Initialized(Instant), + DoneParsing(Instant, Instant), + DoneFormatting(Instant, Instant, Instant), +} + +impl Timer { + fn done_parsing(self) -> Self { + match self { + Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), + _ => panic!("Timer can only transition to DoneParsing from Initialized state"), + } + } + + fn done_formatting(self) -> Self { + match self { + Timer::DoneParsing(init_time, parse_time) => { + Timer::DoneFormatting(init_time, parse_time, Instant::now()) + } + _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), + } + } + + /// Returns the time it took to parse the source files in seconds. + fn get_parse_time(&self) -> f32 { + match *self { + Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { + // This should never underflow since `Instant::now()` guarantees monotonicity. + Self::duration_to_f32(parse_time.duration_since(init)) + } + Timer::Initialized(..) => unreachable!(), + } + } + + /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is + /// not included. + fn get_format_time(&self) -> f32 { + match *self { + Timer::DoneFormatting(_init, parse_time, format_time) => { + Self::duration_to_f32(format_time.duration_since(parse_time)) + } + Timer::DoneParsing(..) | Timer::Initialized(..) => unreachable!(), + } + } + + fn duration_to_f32(d: Duration) -> f32 { + d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 + } +} + +fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) +where + F: Fn(), +{ + if config.verbose() == Verbosity::Verbose && !is_stdin { + f(); + } +} + +/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. +fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { + skipped_range + .iter() + .any(|&(lo, hi)| lo <= line_number && line_number <= hi) +} + +fn should_report_error( + config: &Config, + char_kind: FullCodeCharKind, + is_string: bool, error_kind: &ErrorKind, ) -> bool { let allow_error_report = if char_kind.is_comment() || is_string || error_kind.is_comment() { @@ -295,432 +675,52 @@ enum ParseError<'sess> { Panic, } -impl<'b, T: Write + 'b> Session<'b, T> { - pub(crate) fn format_input_inner(&mut self, input: Input) -> Result { - if !self.config.version_meets_requirement() { - return Err(ErrorKind::VersionMismatch); - } - - syntax::with_globals(|| { - syntax_pos::hygiene::set_default_edition( - self.config.edition().to_libsyntax_pos_edition(), - ); - - if self.config.disable_all_formatting() { - // When the input is from stdin, echo back the input. - if let Input::Text(ref buf) = input { - if let Err(e) = io::stdout().write_all(buf.as_bytes()) { - return Err(From::from(e)); - } - } - return Ok(FormatReport::new()); - } - - let config = &self.config.clone(); - let format_result = format_project(input, config, self); +fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { + let tty_handler = if config.hide_parse_errors() { + let silent_emitter = Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap.clone()), + false, + false, + )); + Handler::with_emitter(true, false, silent_emitter) + } else { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + }; - format_result.map(|(report, summary)| { - self.summary.add(summary); - report - }) - }) - } + ParseSess::with_span_handler(tty_handler, codemap) } -// Handle the results of formatting. -trait FormatHandler { - fn handle_formatted_file(&mut self, path: FileName, result: String) -> Result<(), ErrorKind>; -} +fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { + let style = if config.newline_style() == NewlineStyle::Native { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + config.newline_style() + }; -impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { - // Called for each formatted file. - fn handle_formatted_file( - &mut self, - path: FileName, - mut result: String, - ) -> Result<(), ErrorKind> { - if let Some(ref mut out) = self.out { - match filemap::write_file(&mut result, &path, out, &self.config) { - Ok(b) if b => self.summary.add_diff(), - Err(e) => { - // Create a new error with path_str to help users see which files failed - let err_msg = format!("{}: {}", path, e); - return Err(io::Error::new(e.kind(), err_msg).into()); + match style { + NewlineStyle::Unix => return, + NewlineStyle::Windows => { + let mut transformed = String::with_capacity(text.capacity()); + for c in text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), } - _ => {} } - } - - self.filemap.push((path, result)); - Ok(()) - } -} - -// Format an entire crate (or subset of the module tree). -fn format_project( - input: Input, - config: &Config, - handler: &mut T, -) -> Result<(FormatReport, Summary), ErrorKind> { - let mut summary = Summary::default(); - let mut timer = Timer::Initialized(Instant::now()); - - let input_is_stdin = input.is_text(); - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Stdin, - }; - - // Parse the crate. - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - let mut parse_session = make_parse_sess(codemap.clone(), config); - let krate = match parse_input(input, &parse_session, config) { - Ok(krate) => krate, - Err(err) => { - match err { - ParseError::Error(mut diagnostic) => diagnostic.emit(), - ParseError::Panic => { - // Note that if you see this message and want more information, - // then go to `parse_input` and run the parse function without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(!input_is_stdin, config, || { - println!("The Rust parser panicked") - }); - } - ParseError::Recovered => {} - } - summary.add_parsing_error(); - return Err(ErrorKind::ParseError); - } - }; - timer = timer.done_parsing(); - - // Suppress error output if we have to do any further parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - - let mut context = FormatContext::new( - &krate, - FormatReport::new(), - summary, - parse_session, - config, - handler, - ); - - let files = modules::list_files(&krate, context.parse_session.codemap())?; - for (path, module) in files { - if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { - continue; - } - should_emit_verbose(!input_is_stdin, config, || println!("Formatting {}", path)); - let is_root = path == main_file; - context.format_file(path, module, is_root)?; - } - timer = timer.done_formatting(); - - should_emit_verbose(!input_is_stdin, config, || { - println!( - "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", - timer.get_parse_time(), - timer.get_format_time(), - ) - }); - - if context.report.has_warnings() { - context.summary.add_formatting_error(); - } - { - let report_errs = &context.report.internal.borrow().1; - if report_errs.has_check_errors { - context.summary.add_check_error(); - } - if report_errs.has_operational_errors { - context.summary.add_operational_error(); - } - } - - Ok((context.report, context.summary)) -} - -// Used for formatting files. -#[derive(new)] -struct FormatContext<'a, T: FormatHandler + 'a> { - krate: &'a ast::Crate, - report: FormatReport, - summary: Summary, - parse_session: ParseSess, - config: &'a Config, - handler: &'a mut T, -} - -impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { - // Formats a single file/module. - fn format_file( - &mut self, - path: FileName, - module: &ast::Mod, - is_root: bool, - ) -> Result<(), ErrorKind> { - let filemap = self - .parse_session - .codemap() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = FmtVisitor::from_codemap( - &self.parse_session, - &self.config, - &snippet_provider, - self.report.clone(), - ); - // Format inner attributes if available. - if !self.krate.attrs.is_empty() && is_root { - visitor.skip_empty_lines(filemap.end_pos); - if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, &*filemap); - } - } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); - visitor.format_separate_mod(module, &*filemap); - }; - - debug_assert_eq!( - visitor.line_number, - ::utils::count_newlines(&visitor.buffer) - ); - - // For some reason, the codemap does not include terminating - // newlines so we must add one on for each file. This is sad. - filemap::append_newline(&mut visitor.buffer); - - format_lines( - &mut visitor.buffer, - &path, - &visitor.skipped_range, - &self.config, - &self.report, - ); - replace_with_system_newlines(&mut visitor.buffer, &self.config); - - if visitor.macro_rewrite_failure { - self.summary.add_macro_format_failure(); - } - - self.handler.handle_formatted_file(path, visitor.buffer) - } -} - -fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { - let tty_handler = if config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); - Handler::with_emitter(true, false, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) - }; - - ParseSess::with_span_handler(tty_handler, codemap) -} - -fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; - - match style { - NewlineStyle::Unix => return, - NewlineStyle::Windows => { - let mut transformed = String::with_capacity(text.capacity()); - for c in text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } - } - *text = transformed; + *text = transformed; } NewlineStyle::Native => unreachable!(), } } - -/// A single span of changed lines, with 0 or more removed lines -/// and a vector of 0 or more inserted lines. -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ModifiedChunk { - /// The first to be removed from the original text - pub line_number_orig: u32, - /// The number of lines which have been replaced - pub lines_removed: u32, - /// The new lines - pub lines: Vec, -} - -/// Set of changed sections of a file. -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ModifiedLines { - /// The set of changed chunks. - pub chunks: Vec, -} - -#[derive(Clone, Copy, Debug)] -enum Timer { - Initialized(Instant), - DoneParsing(Instant, Instant), - DoneFormatting(Instant, Instant, Instant), -} - -impl Timer { - fn done_parsing(self) -> Self { - match self { - Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), - _ => panic!("Timer can only transition to DoneParsing from Initialized state"), - } - } - - fn done_formatting(self) -> Self { - match self { - Timer::DoneParsing(init_time, parse_time) => { - Timer::DoneFormatting(init_time, parse_time, Instant::now()) - } - _ => panic!("Timer can only transition to DoneFormatting from DoneParsing state"), - } - } - - /// Returns the time it took to parse the source files in seconds. - fn get_parse_time(&self) -> f32 { - match *self { - Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { - // This should never underflow since `Instant::now()` guarantees monotonicity. - Self::duration_to_f32(parse_time.duration_since(init)) - } - Timer::Initialized(..) => unreachable!(), - } - } - - /// Returns the time it took to go from the parsed AST to the formatted output. Parsing time is - /// not included. - fn get_format_time(&self) -> f32 { - match *self { - Timer::DoneFormatting(_init, parse_time, format_time) => { - Self::duration_to_f32(format_time.duration_since(parse_time)) - } - Timer::DoneParsing(..) | Timer::Initialized(..) => unreachable!(), - } - } - - fn duration_to_f32(d: Duration) -> f32 { - d.as_secs() as f32 + d.subsec_nanos() as f32 / 1_000_000_000f32 - } -} - -/// A summary of a Rustfmt run. -#[derive(Debug, Default, Clone, Copy)] -pub struct Summary { - // Encountered e.g. an IO error. - has_operational_errors: bool, - - // Failed to reformat code because of parsing errors. - has_parsing_errors: bool, - - // Code is valid, but it is impossible to format it properly. - has_formatting_errors: bool, - - // Code contains macro call that was unable to format. - pub(crate) has_macro_format_failure: bool, - - // Failed a check, such as the license check or other opt-in checking. - has_check_errors: bool, - - /// Formatted code differs from existing code (--check only). - pub has_diff: bool, -} - -impl Summary { - pub fn has_operational_errors(&self) -> bool { - self.has_operational_errors - } - - pub fn has_parsing_errors(&self) -> bool { - self.has_parsing_errors - } - - pub fn has_formatting_errors(&self) -> bool { - self.has_formatting_errors - } - - pub fn has_check_errors(&self) -> bool { - self.has_check_errors - } - - pub(crate) fn has_macro_formatting_failure(&self) -> bool { - self.has_macro_format_failure - } - - pub fn add_operational_error(&mut self) { - self.has_operational_errors = true; - } - - pub(crate) fn add_parsing_error(&mut self) { - self.has_parsing_errors = true; - } - - pub(crate) fn add_formatting_error(&mut self) { - self.has_formatting_errors = true; - } - - pub(crate) fn add_check_error(&mut self) { - self.has_check_errors = true; - } - - pub(crate) fn add_diff(&mut self) { - self.has_diff = true; - } - - pub(crate) fn add_macro_format_failure(&mut self) { - self.has_macro_format_failure = true; - } - - pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors - || self.has_parsing_errors - || self.has_formatting_errors - || self.has_diff) - } - - /// Combine two summaries together. - pub fn add(&mut self, other: Summary) { - self.has_operational_errors |= other.has_operational_errors; - self.has_formatting_errors |= other.has_formatting_errors; - self.has_macro_format_failure |= other.has_macro_format_failure; - self.has_parsing_errors |= other.has_parsing_errors; - self.has_check_errors |= other.has_check_errors; - self.has_diff |= other.has_diff; - } -} -- cgit 1.4.1-3-g733a5 From d3288841ea86b7ebcff57c840b9a4855f9033ece Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 14:25:17 +1200 Subject: Refactoring: factor `format_lines` and `format_project` into smaller chunks --- src/formatting.rs | 392 +++++++++++++++++++++++++++++------------------------- src/lib.rs | 7 + 2 files changed, 217 insertions(+), 182 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 656a18b876f..ee2539a2fa5 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -9,7 +9,7 @@ use std::time::{Duration, Instant}; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping, Span}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; -use syntax::errors::{DiagnosticBuilder, Handler}; +use syntax::errors::Handler; use syntax::parse::{self, ParseSess}; use comment::{CharClasses, FullCodeCharKind}; @@ -63,43 +63,17 @@ fn format_project( let mut summary = Summary::default(); let mut timer = Timer::Initialized(Instant::now()); - let input_is_stdin = input.is_text(); - let main_file = match input { - Input::File(ref file) => FileName::Real(file.clone()), - Input::Text(..) => FileName::Stdin, - }; + let main_file = input.file_name(); + let input_is_stdin = main_file == FileName::Stdin; // Parse the crate. let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); let mut parse_session = make_parse_sess(codemap.clone(), config); - let krate = match parse_input(input, &parse_session, config) { - Ok(krate) => krate, - Err(err) => { - match err { - ParseError::Error(mut diagnostic) => diagnostic.emit(), - ParseError::Panic => { - // Note that if you see this message and want more information, - // then go to `parse_input` and run the parse function without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(!input_is_stdin, config, || { - println!("The Rust parser panicked") - }); - } - ParseError::Recovered => {} - } - summary.add_parsing_error(); - return Err(ErrorKind::ParseError); - } - }; + let krate = parse_crate(input, &parse_session, config, &mut summary)?; timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); + let silent_emitter = silent_emitter(codemap); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); let mut context = FormatContext::new( @@ -130,19 +104,7 @@ fn format_project( ) }); - if context.report.has_warnings() { - context.summary.add_formatting_error(); - } - { - let report_errs = &context.report.internal.borrow().1; - if report_errs.has_check_errors { - context.summary.add_check_error(); - } - if report_errs.has_operational_errors { - context.summary.add_operational_error(); - } - } - + context.summarise_errors(); Ok((context.report, context.summary)) } @@ -158,6 +120,20 @@ struct FormatContext<'a, T: FormatHandler + 'a> { } impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { + // Moves errors from the report to the summary. + fn summarise_errors(&mut self) { + if self.report.has_warnings() { + self.summary.add_formatting_error(); + } + let report_errs = &self.report.internal.borrow().1; + if report_errs.has_check_errors { + self.summary.add_check_error(); + } + if report_errs.has_operational_errors { + self.summary.add_operational_error(); + } + } + // Formats a single file/module. fn format_file( &mut self, @@ -178,6 +154,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &snippet_provider, self.report.clone(), ); + // Format inner attributes if available. if !self.krate.attrs.is_empty() && is_root { visitor.skip_empty_lines(filemap.end_pos); @@ -481,41 +458,6 @@ impl Timer { } } -fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) -where - F: Fn(), -{ - if config.verbose() == Verbosity::Verbose && !is_stdin { - f(); - } -} - -/// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. -fn is_skipped_line(line_number: usize, skipped_range: &[(usize, usize)]) -> bool { - skipped_range - .iter() - .any(|&(lo, hi)| lo <= line_number && line_number <= hi) -} - -fn should_report_error( - config: &Config, - char_kind: FullCodeCharKind, - is_string: bool, - error_kind: &ErrorKind, -) -> bool { - let allow_error_report = if char_kind.is_comment() || is_string || error_kind.is_comment() { - config.error_on_unformatted() - } else { - true - }; - - match error_kind { - ErrorKind::LineOverflow(..) => config.error_on_line_overflow() && allow_error_report, - ErrorKind::TrailingWhitespace | ErrorKind::LostComment => allow_error_report, - _ => true, - } -} - // Formatting done on a char by char or line by line basis. // FIXME(#20) other stuff for parity with make tidy fn format_lines( @@ -525,115 +467,191 @@ fn format_lines( config: &Config, report: &FormatReport, ) { - let mut last_was_space = false; - let mut line_len = 0; - let mut cur_line = 1; - let mut newline_count = 0; - let mut errors = vec![]; - let mut issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); - let mut line_buffer = String::with_capacity(config.max_width() * 2); - let mut is_string = false; // true if the current line contains a string literal. - let mut format_line = config.file_lines().contains_line(name, cur_line); - let allow_issue_seek = !issue_seeker.is_disabled(); - - // Check license. - if let Some(ref license_template) = config.license_template { - if !license_template.is_match(text) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::LicenseCheck, - is_comment: false, - is_string: false, - line_buffer: String::new(), - }); - } + let mut formatter = FormatLines::new(name, skipped_range, config); + formatter.check_license(text); + formatter.iterate(text); + + if formatter.newline_count > 1 { + debug!("track truncate: {} {}", text.len(), formatter.newline_count); + let line = text.len() - formatter.newline_count + 1; + text.truncate(line); } - // Iterate over the chars in the file map. - for (kind, c) in CharClasses::new(text.chars()) { - if c == '\r' { - continue; + report.append(name.clone(), formatter.errors); +} + +struct FormatLines<'a> { + name: &'a FileName, + skipped_range: &'a [(usize, usize)], + last_was_space: bool, + line_len: usize, + cur_line: usize, + newline_count: usize, + errors: Vec, + issue_seeker: BadIssueSeeker, + line_buffer: String, + // true if the current line contains a string literal. + is_string: bool, + format_line: bool, + allow_issue_seek: bool, + config: &'a Config, +} + +impl<'a> FormatLines<'a> { + fn new( + name: &'a FileName, + skipped_range: &'a [(usize, usize)], + config: &'a Config, + ) -> FormatLines<'a> { + let issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme()); + FormatLines { + name, + skipped_range, + last_was_space: false, + line_len: 0, + cur_line: 1, + newline_count: 0, + errors: vec![], + allow_issue_seek: !issue_seeker.is_disabled(), + issue_seeker, + line_buffer: String::with_capacity(config.max_width() * 2), + is_string: false, + format_line: config.file_lines().contains_line(name, 1), + config, } + } - if allow_issue_seek && format_line { - // Add warnings for bad todos/ fixmes - if let Some(issue) = issue_seeker.inspect(c) { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::BadIssue(issue), + fn check_license(&mut self, text: &mut String) { + if let Some(ref license_template) = self.config.license_template { + if !license_template.is_match(text) { + self.errors.push(FormattingError { + line: self.cur_line, + kind: ErrorKind::LicenseCheck, is_comment: false, is_string: false, line_buffer: String::new(), }); } } + } - if c == '\n' { - if format_line { - // Check for (and record) trailing whitespace. - if last_was_space { - if should_report_error(config, kind, is_string, &ErrorKind::TrailingWhitespace) - && !is_skipped_line(cur_line, skipped_range) - { - errors.push(FormattingError { - line: cur_line, - kind: ErrorKind::TrailingWhitespace, - is_comment: kind.is_comment(), - is_string: kind.is_string(), - line_buffer: line_buffer.clone(), - }); - } - line_len -= 1; + // Iterate over the chars in the file map. + fn iterate(&mut self, text: &mut String) { + for (kind, c) in CharClasses::new(text.chars()) { + if c == '\r' { + continue; + } + + if self.allow_issue_seek && self.format_line { + // Add warnings for bad todos/ fixmes + if let Some(issue) = self.issue_seeker.inspect(c) { + self.push_err(ErrorKind::BadIssue(issue), false, false); } + } - // Check for any line width errors we couldn't correct. - let error_kind = ErrorKind::LineOverflow(line_len, config.max_width()); - if line_len > config.max_width() - && !is_skipped_line(cur_line, skipped_range) - && should_report_error(config, kind, is_string, &error_kind) + if c == '\n' { + self.new_line(kind); + } else { + self.char(c, kind); + } + } + } + + fn new_line(&mut self, kind: FullCodeCharKind) { + if self.format_line { + // Check for (and record) trailing whitespace. + if self.last_was_space { + if self.should_report_error(kind, &ErrorKind::TrailingWhitespace) + && !self.is_skipped_line() { - errors.push(FormattingError { - line: cur_line, - kind: error_kind, - is_comment: kind.is_comment(), - is_string, - line_buffer: line_buffer.clone(), - }); + self.push_err( + ErrorKind::TrailingWhitespace, + kind.is_comment(), + kind.is_string(), + ); } + self.line_len -= 1; } - line_len = 0; - cur_line += 1; - format_line = config.file_lines().contains_line(name, cur_line); - newline_count += 1; - last_was_space = false; - line_buffer.clear(); - is_string = false; - } else { - newline_count = 0; - line_len += if c == '\t' { config.tab_spaces() } else { 1 }; - last_was_space = c.is_whitespace(); - line_buffer.push(c); - if kind.is_string() { - is_string = true; + // Check for any line width errors we couldn't correct. + let error_kind = ErrorKind::LineOverflow(self.line_len, self.config.max_width()); + if self.line_len > self.config.max_width() + && !self.is_skipped_line() + && self.should_report_error(kind, &error_kind) + { + self.push_err(error_kind, kind.is_comment(), self.is_string); } } + + self.line_len = 0; + self.cur_line += 1; + self.format_line = self + .config + .file_lines() + .contains_line(self.name, self.cur_line); + self.newline_count += 1; + self.last_was_space = false; + self.line_buffer.clear(); + self.is_string = false; + } + + fn char(&mut self, c: char, kind: FullCodeCharKind) { + self.newline_count = 0; + self.line_len += if c == '\t' { + self.config.tab_spaces() + } else { + 1 + }; + self.last_was_space = c.is_whitespace(); + self.line_buffer.push(c); + if kind.is_string() { + self.is_string = true; + } } - if newline_count > 1 { - debug!("track truncate: {} {}", text.len(), newline_count); - let line = text.len() - newline_count + 1; - text.truncate(line); + fn push_err(&mut self, kind: ErrorKind, is_comment: bool, is_string: bool) { + self.errors.push(FormattingError { + line: self.cur_line, + kind, + is_comment, + is_string, + line_buffer: self.line_buffer.clone(), + }); } - report.append(name.clone(), errors); + fn should_report_error(&self, char_kind: FullCodeCharKind, error_kind: &ErrorKind) -> bool { + let allow_error_report = + if char_kind.is_comment() || self.is_string || error_kind.is_comment() { + self.config.error_on_unformatted() + } else { + true + }; + + match error_kind { + ErrorKind::LineOverflow(..) => { + self.config.error_on_line_overflow() && allow_error_report + } + ErrorKind::TrailingWhitespace | ErrorKind::LostComment => allow_error_report, + _ => true, + } + } + + /// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. + fn is_skipped_line(&self) -> bool { + self.skipped_range + .iter() + .any(|&(lo, hi)| lo <= self.cur_line && self.cur_line <= hi) + } } -fn parse_input<'sess>( +fn parse_crate( input: Input, - parse_session: &'sess ParseSess, + parse_session: &ParseSess, config: &Config, -) -> Result> { + summary: &mut Summary, +) -> Result { + let input_is_stdin = input.is_text(); + let mut parser = match input { Input::File(file) => parse::new_parser_from_file(parse_session, &file), Input::Text(text) => parse::new_parser_from_source_str( @@ -653,36 +671,37 @@ fn parse_input<'sess>( match result { Ok(Ok(c)) => { - if parse_session.span_diagnostic.has_errors() { - // Bail out if the parser recovered from an error. - Err(ParseError::Recovered) - } else { - Ok(c) + if !parse_session.span_diagnostic.has_errors() { + return Ok(c); } } - Ok(Err(e)) => Err(ParseError::Error(e)), - Err(_) => Err(ParseError::Panic), + Ok(Err(mut e)) => e.emit(), + Err(_) => { + // Note that if you see this message and want more information, + // then run the `parse_crate_mod` function above without + // `catch_unwind` so rustfmt panics and you can get a backtrace. + should_emit_verbose(!input_is_stdin, config, || { + println!("The Rust parser panicked") + }); + } } + + summary.add_parsing_error(); + Err(ErrorKind::ParseError) } -/// All the ways that parsing can fail. -enum ParseError<'sess> { - /// There was an error, but the parser recovered. - Recovered, - /// There was an error (supplied) and parsing failed. - Error(DiagnosticBuilder<'sess>), - /// The parser panicked. - Panic, +fn silent_emitter(codemap: Rc) -> Box { + Box::new(EmitterWriter::new( + Box::new(Vec::new()), + Some(codemap), + false, + false, + )) } fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { let tty_handler = if config.hide_parse_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - false, - false, - )); + let silent_emitter = silent_emitter(codemap.clone()); Handler::with_emitter(true, false, silent_emitter) } else { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); @@ -724,3 +743,12 @@ fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { NewlineStyle::Native => unreachable!(), } } + +fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) +where + F: Fn(), +{ + if config.verbose() == Verbosity::Verbose && !is_stdin { + f(); + } +} diff --git a/src/lib.rs b/src/lib.rs index e21bd6c79be..a1cd3ba84a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -499,6 +499,13 @@ impl Input { Input::Text(_) => true, } } + + fn file_name(&self) -> FileName { + match *self { + Input::File(ref file) => FileName::Real(file.clone()), + Input::Text(..) => FileName::Stdin, + } + } } #[cfg(test)] -- cgit 1.4.1-3-g733a5 From 728b0182c5ba5e6b98981c523868a23cbaf88719 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Jul 2018 09:13:33 +1200 Subject: Changes to chains with block indent * More often combine a chain item to the previous line (if it is a block) * Don't indent if the parent is a block This is not perfect and doesn't pass tests, but I need to refactor to make more progress --- src/chains.rs | 91 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 52999635cf1..44edaa9c34d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -78,7 +78,6 @@ use utils::{ use std::borrow::Cow; use std::cmp::min; -use std::iter; use syntax::codemap::Span; use syntax::{ast, ptr}; @@ -99,8 +98,8 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent, "\n") { match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape, + IndentStyle::Visual => shape.visual_indent(0), } } else { shape @@ -110,18 +109,30 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); + let parent_is_block = is_block_expr(context, &parent, &parent_rewrite); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - context.config.indent_style() == IndentStyle::Visual || is_small_parent, - ) - } else if is_block_expr(context, &parent, &parent_rewrite) { + match context.config.indent_style() { + IndentStyle::Block => { + // TODO this is naive since if the first child is on the same line + // as the parent, then we should look at that, instead of the parent. + // Can we make the parent the first two things then? + let shape = if parent_is_block { + shape + } else { + chain_indent(context, shape.add_offset(parent_rewrite.len())) + }; + (shape, is_small_parent) + } + // TODO is this right? + IndentStyle::Visual => (chain_indent(context, shape.add_offset(parent_rewrite.len())), true), + } + } else if parent_is_block { match context.config.indent_style() { // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape.block_indent(context.config.tab_spaces()), true), + IndentStyle::Block => (parent_shape, true), // The parent is a block, so align the rest of the chain with the closing // brace. IndentStyle::Visual => (parent_shape, false), @@ -136,11 +147,21 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let other_child_shape = nested_shape.with_max_width(context.config); let first_child_shape = if extend { - let overhead = last_line_width(&parent_rewrite); - let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; match context.config.indent_style() { - IndentStyle::Visual => parent_shape.offset_left(overhead)?, - IndentStyle::Block => parent_shape.offset_left(offset)?, + IndentStyle::Block => { + let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; + if parent_is_block { + parent_shape.offset_left(offset)? + } else { + parent_shape + .block_indent(context.config.tab_spaces()) + .offset_left(offset)? + } + } + IndentStyle::Visual => { + let overhead = last_line_width(&parent_rewrite); + parent_shape.offset_left(overhead)? + } } } else { other_child_shape @@ -150,16 +171,25 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - first_child_shape, other_child_shape ); - let child_shape_iter = Some(first_child_shape) - .into_iter() - .chain(iter::repeat(other_child_shape)); let subexpr_num = subexpr_list.len(); let last_subexpr = &subexpr_list[suffix_try_num]; let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; - let iter = subexpr_list.iter().skip(1).rev().zip(child_shape_iter); - let mut rewrites = iter - .map(|(e, shape)| rewrite_chain_subexpr(e, total_span, context, shape)) - .collect::>>()?; + + let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); + let mut is_block_like = Vec::with_capacity(subexpr_list.len()); + is_block_like.push(true); + for (i, expr) in subexpr_list.iter().skip(1).rev().enumerate() { + // TODO should only use first_child_shape if expr is block like + let shape = if *is_block_like.last().unwrap() && !(extend && i == 0) { + // TODO change the name of the shapes + first_child_shape + } else { + other_child_shape + }; + let rewrite = rewrite_chain_subexpr(expr, total_span, context, shape)?; + is_block_like.push(is_block_expr(context, expr, &rewrite)); + rewrites.push(rewrite); + } // Total of all items excluding the last. let extend_last_subexpr = if is_small_parent { @@ -180,7 +210,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = if rewrites.is_empty() { + let last_shape = if is_block_like[rewrites.len()] { first_child_shape } else { other_child_shape @@ -228,7 +258,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - parent_shape.offset_left(almost_total).map(|shape| { if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { // We allow overflowing here only if both of the following conditions match: - // 1. The entire chain fits in a single line expect the last child. + // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. let line_count = rw.lines().count(); let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; @@ -255,6 +285,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - (rewrite_last(), false) }; rewrites.push(last_subexpr_str?); + // We should never look at this, since we only look at the block-ness of the + // previous item in the chain. + is_block_like.push(false); let connector = if fits_single_line && !parent_rewrite_contains_newline { // Yay, we can put everything on one line. @@ -293,14 +326,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - first_connector, rewrites[0], second_connector, - join_rewrites(&rewrites[1..], &connector) + join_rewrites(&rewrites[1..], &is_block_like[2..], &connector), ) } else { format!( "{}{}{}", parent_rewrite, first_connector, - join_rewrites(&rewrites, &connector) + join_rewrites(&rewrites, &is_block_like[1..], &connector), ) }; let result = format!("{}{}", result, "?".repeat(suffix_try_num)); @@ -332,12 +365,12 @@ fn rewrite_try( Some(format!("{}{}", sub_expr, "?".repeat(try_count))) } -fn join_rewrites(rewrites: &[String], connector: &str) -> String { +fn join_rewrites(rewrites: &[String], is_block_like: &[bool], connector: &str) -> String { let mut rewrite_iter = rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); - for rewrite in rewrite_iter { - if rewrite != "?" { + for (rewrite, prev_is_block_like) in rewrite_iter.zip(is_block_like.iter()) { + if rewrite != "?" && !prev_is_block_like { result.push_str(connector); } result.push_str(&rewrite); @@ -365,7 +398,11 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool ast::ExprKind::Paren(ref expr) | ast::ExprKind::Binary(_, _, ref expr) | ast::ExprKind::Index(_, ref expr) - | ast::ExprKind::Unary(_, ref expr) => is_block_expr(context, expr, repr), + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Closure(_, _, _, _, ref expr, _) => is_block_expr(context, expr, repr), + ast::ExprKind::MethodCall(_, ref exprs) => { + is_block_expr(context, exprs.last().unwrap(), repr) + } _ => false, } } -- cgit 1.4.1-3-g733a5 From a8d5f2557216d2102a8cbb73e3b10f8d88de44a6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Jul 2018 13:02:14 +1200 Subject: chains: split handling of chains in block and visual cases Just refactoring, lots of code dup here, but it should get better... --- src/chains.rs | 278 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 220 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 44edaa9c34d..e0d31e45caa 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -84,6 +84,13 @@ use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { debug!("rewrite_chain {:?}", shape); + match context.config.indent_style() { + IndentStyle::Block => rewrite_chain_block(expr, context, shape), + IndentStyle::Visual => rewrite_chain_visual(expr, context, shape), + } +} + +fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { let total_span = expr.span; let (parent, subexpr_list) = make_subexpr_list(expr, context); @@ -96,14 +103,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = if is_block_expr(context, &parent, "\n") { - match context.config.indent_style() { - IndentStyle::Block => shape, - IndentStyle::Visual => shape.visual_indent(0), - } - } else { - shape - }; + let parent_shape = shape; let parent_rewrite = parent .rewrite(context, parent_shape) .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; @@ -114,29 +114,14 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - match context.config.indent_style() { - IndentStyle::Block => { - // TODO this is naive since if the first child is on the same line - // as the parent, then we should look at that, instead of the parent. - // Can we make the parent the first two things then? - let shape = if parent_is_block { - shape - } else { - chain_indent(context, shape.add_offset(parent_rewrite.len())) - }; - (shape, is_small_parent) - } - // TODO is this right? - IndentStyle::Visual => (chain_indent(context, shape.add_offset(parent_rewrite.len())), true), - } + let shape = if parent_is_block { + shape + } else { + chain_indent(context, shape.add_offset(parent_rewrite.len())) + }; + (shape, is_small_parent) } else if parent_is_block { - match context.config.indent_style() { - // Try to put the first child on the same line with parent's last line - IndentStyle::Block => (parent_shape, true), - // The parent is a block, so align the rest of the chain with the closing - // brace. - IndentStyle::Visual => (parent_shape, false), - } + (parent_shape, true) } else { ( chain_indent(context, shape.add_offset(parent_rewrite.len())), @@ -147,21 +132,13 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let other_child_shape = nested_shape.with_max_width(context.config); let first_child_shape = if extend { - match context.config.indent_style() { - IndentStyle::Block => { - let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; - if parent_is_block { - parent_shape.offset_left(offset)? - } else { - parent_shape - .block_indent(context.config.tab_spaces()) - .offset_left(offset)? - } - } - IndentStyle::Visual => { - let overhead = last_line_width(&parent_rewrite); - parent_shape.offset_left(overhead)? - } + let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; + if parent_is_block { + parent_shape.offset_left(offset)? + } else { + parent_shape + .block_indent(context.config.tab_spaces()) + .offset_left(offset)? } } else { other_child_shape @@ -179,9 +156,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let mut is_block_like = Vec::with_capacity(subexpr_list.len()); is_block_like.push(true); for (i, expr) in subexpr_list.iter().skip(1).rev().enumerate() { - // TODO should only use first_child_shape if expr is block like let shape = if *is_block_like.last().unwrap() && !(extend && i == 0) { - // TODO change the name of the shapes first_child_shape } else { other_child_shape @@ -303,7 +278,6 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let first_connector = if is_small_parent || fits_single_line || last_line_extendable(&parent_rewrite) - || context.config.indent_style() == IndentStyle::Visual { "" } else { @@ -314,7 +288,6 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - let second_connector = if fits_single_line || rewrites[1] == "?" || last_line_extendable(&rewrites[0]) - || context.config.indent_style() == IndentStyle::Visual { "" } else { @@ -337,11 +310,203 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - ) }; let result = format!("{}{}", result, "?".repeat(suffix_try_num)); - if context.config.indent_style() == IndentStyle::Visual { - wrap_str(result, context.config.max_width(), shape) + Some(result) +} + +fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { + let total_span = expr.span; + let (parent, subexpr_list) = make_subexpr_list(expr, context); + + // Bail out if the chain is just try sugar, i.e., an expression followed by + // any number of `?`s. + if chain_only_try(&subexpr_list) { + return rewrite_try(&parent, subexpr_list.len(), context, shape); + } + let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); + let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); + + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. + let parent_shape = if is_block_expr(context, &parent, "\n") { + shape.visual_indent(0) + } else { + shape + }; + let parent_rewrite = parent + .rewrite(context, parent_shape) + .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; + let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); + let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); + let parent_is_block = is_block_expr(context, &parent, &parent_rewrite); + + // Decide how to layout the rest of the chain. `extend` is true if we can + // put the first non-parent item on the same line as the parent. + let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { + (shape.visual_indent(0), true) + } else if parent_is_block { + (parent_shape, false) + } else { + ( + shape.visual_indent(0), + false, + ) + }; + + let other_child_shape = nested_shape.with_max_width(context.config); + + let first_child_shape = if extend { + let overhead = last_line_width(&parent_rewrite); + parent_shape.offset_left(overhead)? } else { - Some(result) + other_child_shape + }; + debug!( + "child_shapes {:?} {:?}", + first_child_shape, other_child_shape + ); + + let subexpr_num = subexpr_list.len(); + let last_subexpr = &subexpr_list[suffix_try_num]; + let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; + + let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); + let mut is_block_like = Vec::with_capacity(subexpr_list.len()); + is_block_like.push(true); + for (i, expr) in subexpr_list.iter().skip(1).rev().enumerate() { + let shape = if *is_block_like.last().unwrap() && !(extend && i == 0) { + first_child_shape + } else { + other_child_shape + }; + let rewrite = rewrite_chain_subexpr(expr, total_span, context, shape)?; + is_block_like.push(is_block_expr(context, expr, &rewrite)); + rewrites.push(rewrite); } + + // Total of all items excluding the last. + let extend_last_subexpr = if is_small_parent { + rewrites.len() == 1 && last_line_extendable(&rewrites[0]) + } else { + rewrites.is_empty() && last_line_extendable(&parent_rewrite) + }; + let almost_total = if extend_last_subexpr { + last_line_width(&parent_rewrite) + } else { + rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() + } + suffix_try_num; + let one_line_budget = if rewrites.is_empty() { + shape.width + } else { + min(shape.width, context.config.width_heuristics().chain_width) + }; + let all_in_one_line = !parent_rewrite_contains_newline + && rewrites.iter().all(|s| !s.contains('\n')) + && almost_total < one_line_budget; + let last_shape = if is_block_like[rewrites.len()] { + first_child_shape + } else { + other_child_shape + }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; + + // Rewrite the last child. The last child of a chain requires special treatment. We need to + // know whether 'overflowing' the last child make a better formatting: + // + // A chain with overflowing the last child: + // ``` + // parent.child1.child2.last_child( + // a, + // b, + // c, + // ) + // ``` + // + // A chain without overflowing the last child (in vertical layout): + // ``` + // parent + // .child1 + // .child2 + // .last_child(a, b, c) + // ``` + // + // In particular, overflowing is effective when the last child is a method with a multi-lined + // block-like argument (e.g. closure): + // ``` + // parent.child1.child2.last_child(|a, b, c| { + // let x = foo(a, b, c); + // let y = bar(a, b, c); + // + // // ... + // + // result + // }) + // ``` + + // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of + // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); + let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { + // First we try to 'overflow' the last child and see if it looks better than using + // vertical layout. + parent_shape.offset_left(almost_total).map(|shape| { + if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + // We allow overflowing here only if both of the following conditions match: + // 1. The entire chain fits in a single line except the last child. + // 2. `last_child_str.lines().count() >= 5`. + let line_count = rw.lines().count(); + let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + if fits_single_line && line_count >= 5 { + (Some(rw), true) + } else { + // We could not know whether overflowing is better than using vertical layout, + // just by looking at the overflowed rewrite. Now we rewrite the last child + // on its own line, and compare two rewrites to choose which is better. + match rewrite_last() { + Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), + Some(ref new_rw) if new_rw.lines().count() >= line_count => { + (Some(rw), fits_single_line) + } + new_rw @ Some(..) => (new_rw, false), + _ => (Some(rw), fits_single_line), + } + } + } else { + (rewrite_last(), false) + } + })? + } else { + (rewrite_last(), false) + }; + rewrites.push(last_subexpr_str?); + // We should never look at this, since we only look at the block-ness of the + // previous item in the chain. + is_block_like.push(false); + + let connector = if fits_single_line && !parent_rewrite_contains_newline { + // Yay, we can put everything on one line. + Cow::from("") + } else { + // Use new lines. + if *context.force_one_line_chain.borrow() { + return None; + } + nested_shape.indent.to_string_with_newline(context.config) + }; + + let result = if is_small_parent && rewrites.len() > 1 { + format!( + "{}{}{}", + parent_rewrite, + rewrites[0], + join_rewrites(&rewrites[1..], &is_block_like[2..], &connector), + ) + } else { + format!( + "{}{}", + parent_rewrite, + join_rewrites(&rewrites, &is_block_like[1..], &connector), + ) + }; + let result = format!("{}{}", result, "?".repeat(suffix_try_num)); + wrap_str(result, context.config.max_width(), shape) } // True if the chain is only `?`s. @@ -421,12 +586,9 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, } fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), - } + IndentStyle::Block => shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), } // Returns the expression's subexpression, if it exists. When the subexpr -- cgit 1.4.1-3-g733a5 From d244234607417e850e264afc9fbf7a4842ebad19 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Jul 2018 13:10:57 +1200 Subject: factor out treatment of 1-length chains And create `Chain` and `ChainItem` structs --- src/chains.rs | 106 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index e0d31e45caa..3a851899f08 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -84,29 +84,56 @@ use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { debug!("rewrite_chain {:?}", shape); + let chain = Chain::from_ast(expr, context); + if chain.children.is_empty() { + return rewrite_try(&chain.parent.expr, chain.parent.tries, context, shape); + } match context.config.indent_style() { - IndentStyle::Block => rewrite_chain_block(expr, context, shape), - IndentStyle::Visual => rewrite_chain_visual(expr, context, shape), + IndentStyle::Block => rewrite_chain_block(chain, context, shape), + IndentStyle::Visual => rewrite_chain_visual(chain, context, shape), } } -fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - let total_span = expr.span; - let (parent, subexpr_list) = make_subexpr_list(expr, context); +// An expression plus trailing `?`s to be formatted together. +struct ChainItem { + expr: ast::Expr, + tries: usize, +} + +struct Chain { + parent: ChainItem, + // TODO do we need to clone the exprs? + children: Vec, + span: Span, +} - // Bail out if the chain is just try sugar, i.e., an expression followed by - // any number of `?`s. - if chain_only_try(&subexpr_list) { - return rewrite_try(&parent, subexpr_list.len(), context, shape); +impl Chain { + fn from_ast(expr: &ast::Expr, context: &RewriteContext) -> Chain { + let (parent, mut subexpr_list) = make_subexpr_list(expr, context); + let tries = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); + let new_len = subexpr_list.len() - tries; + subexpr_list.truncate(new_len); + Chain { + parent: ChainItem { + expr: parent, + tries, + }, + children: subexpr_list, + span: expr.span, + } } +} + +fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + let (parent, subexpr_list) = (&chain.parent.expr, &chain.children); + let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); - let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = shape; let parent_rewrite = parent .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; + .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); let parent_is_block = is_block_expr(context, &parent, &parent_rewrite); @@ -132,7 +159,7 @@ fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) let other_child_shape = nested_shape.with_max_width(context.config); let first_child_shape = if extend { - let offset = trimmed_last_line_width(&parent_rewrite) + prefix_try_num; + let offset = trimmed_last_line_width(&parent_rewrite) + chain.parent.tries; if parent_is_block { parent_shape.offset_left(offset)? } else { @@ -148,9 +175,8 @@ fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) first_child_shape, other_child_shape ); - let subexpr_num = subexpr_list.len(); let last_subexpr = &subexpr_list[suffix_try_num]; - let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; + let subexpr_list = &subexpr_list[suffix_try_num..]; let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); let mut is_block_like = Vec::with_capacity(subexpr_list.len()); @@ -161,7 +187,7 @@ fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) } else { other_child_shape }; - let rewrite = rewrite_chain_subexpr(expr, total_span, context, shape)?; + let rewrite = rewrite_chain_subexpr(expr, chain.span, context, shape)?; is_block_like.push(is_block_expr(context, expr, &rewrite)); rewrites.push(rewrite); } @@ -226,12 +252,12 @@ fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, chain.span, context, last_shape); let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. parent_shape.offset_left(almost_total).map(|shape| { - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + if let Some(rw) = rewrite_chain_subexpr(last_subexpr, chain.span, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -313,17 +339,10 @@ fn rewrite_chain_block(expr: &ast::Expr, context: &RewriteContext, shape: Shape) Some(result) } -fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - let total_span = expr.span; - let (parent, subexpr_list) = make_subexpr_list(expr, context); +fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + let (parent, subexpr_list) = (&chain.parent.expr, &chain.children); - // Bail out if the chain is just try sugar, i.e., an expression followed by - // any number of `?`s. - if chain_only_try(&subexpr_list) { - return rewrite_try(&parent, subexpr_list.len(), context, shape); - } let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); - let prefix_try_num = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent, "\n") { @@ -333,7 +352,7 @@ fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape }; let parent_rewrite = parent .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &"?".repeat(prefix_try_num))?; + .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); let parent_is_block = is_block_expr(context, &parent, &parent_rewrite); @@ -364,9 +383,8 @@ fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape first_child_shape, other_child_shape ); - let subexpr_num = subexpr_list.len(); let last_subexpr = &subexpr_list[suffix_try_num]; - let subexpr_list = &subexpr_list[suffix_try_num..subexpr_num - prefix_try_num]; + let subexpr_list = &subexpr_list[suffix_try_num..]; let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); let mut is_block_like = Vec::with_capacity(subexpr_list.len()); @@ -377,7 +395,7 @@ fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape } else { other_child_shape }; - let rewrite = rewrite_chain_subexpr(expr, total_span, context, shape)?; + let rewrite = rewrite_chain_subexpr(expr, chain.span, context, shape)?; is_block_like.push(is_block_expr(context, expr, &rewrite)); rewrites.push(rewrite); } @@ -442,12 +460,12 @@ fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, total_span, context, last_shape); + let rewrite_last = || rewrite_chain_subexpr(last_subexpr, chain.span, context, last_shape); let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. parent_shape.offset_left(almost_total).map(|shape| { - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, total_span, context, shape) { + if let Some(rw) = rewrite_chain_subexpr(last_subexpr, chain.span, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -509,17 +527,6 @@ fn rewrite_chain_visual(expr: &ast::Expr, context: &RewriteContext, shape: Shape wrap_str(result, context.config.max_width(), shape) } -// True if the chain is only `?`s. -fn chain_only_try(exprs: &[ast::Expr]) -> bool { - exprs.iter().all(|e| { - if let ast::ExprKind::Try(_) = e.node { - true - } else { - false - } - }) -} - fn rewrite_try( expr: &ast::Expr, try_count: usize, @@ -566,12 +573,19 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Closure(_, _, _, _, ref expr, _) => is_block_expr(context, expr, repr), ast::ExprKind::MethodCall(_, ref exprs) => { + // TODO maybe should be like Call is_block_expr(context, exprs.last().unwrap(), repr) } _ => false, } } +fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) +} + // Returns the root of the chain and a Vec of the prefixes of the rest of the chain. // E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { @@ -585,12 +599,6 @@ fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, (parent, subexpr_list) } -fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - IndentStyle::Block => shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), -} - // Returns the expression's subexpression, if it exists. When the subexpr // is a try! macro, we'll convert it to shorthand when the option is set. fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { -- cgit 1.4.1-3-g733a5 From 9c8222474696d3d833cf850a1d50f1c485b63f09 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Jul 2018 14:18:58 +1200 Subject: chains: simplify visual formatting a bit --- src/chains.rs | 58 +++++++++++++++++++++++++++------------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3a851899f08..220cc4b8750 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -340,9 +340,9 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> } fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - let (parent, subexpr_list) = (&chain.parent.expr, &chain.children); + let parent = &chain.parent.expr; - let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); + let suffix_try_num = chain.children.iter().take_while(|e| is_try(e)).count(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent, "\n") { @@ -355,22 +355,13 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); - let parent_is_block = is_block_expr(context, &parent, &parent_rewrite); + + let nested_shape = shape.visual_indent(0); + let other_child_shape = nested_shape.with_max_width(context.config); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - (shape.visual_indent(0), true) - } else if parent_is_block { - (parent_shape, false) - } else { - ( - shape.visual_indent(0), - false, - ) - }; - - let other_child_shape = nested_shape.with_max_width(context.config); + let extend = !parent_rewrite_contains_newline && is_continuable(&parent); let first_child_shape = if extend { let overhead = last_line_width(&parent_rewrite); @@ -383,20 +374,17 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> first_child_shape, other_child_shape ); - let last_subexpr = &subexpr_list[suffix_try_num]; - let subexpr_list = &subexpr_list[suffix_try_num..]; + let last_subexpr = &chain.children[suffix_try_num]; + let subexpr_list = &chain.children[suffix_try_num..]; let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); - let mut is_block_like = Vec::with_capacity(subexpr_list.len()); - is_block_like.push(true); for (i, expr) in subexpr_list.iter().skip(1).rev().enumerate() { - let shape = if *is_block_like.last().unwrap() && !(extend && i == 0) { + let shape = if i == 0 { first_child_shape } else { other_child_shape }; let rewrite = rewrite_chain_subexpr(expr, chain.span, context, shape)?; - is_block_like.push(is_block_expr(context, expr, &rewrite)); rewrites.push(rewrite); } @@ -419,11 +407,8 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> let all_in_one_line = !parent_rewrite_contains_newline && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = if is_block_like[rewrites.len()] { - first_child_shape - } else { - other_child_shape - }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; + let last_shape = + other_child_shape.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: @@ -494,9 +479,6 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> (rewrite_last(), false) }; rewrites.push(last_subexpr_str?); - // We should never look at this, since we only look at the block-ness of the - // previous item in the chain. - is_block_like.push(false); let connector = if fits_single_line && !parent_rewrite_contains_newline { // Yay, we can put everything on one line. @@ -514,13 +496,13 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> "{}{}{}", parent_rewrite, rewrites[0], - join_rewrites(&rewrites[1..], &is_block_like[2..], &connector), + join_rewrites_vis(&rewrites[1..], &connector), ) } else { format!( "{}{}", parent_rewrite, - join_rewrites(&rewrites, &is_block_like[1..], &connector), + join_rewrites_vis(&rewrites, &connector), ) }; let result = format!("{}{}", result, "?".repeat(suffix_try_num)); @@ -551,6 +533,20 @@ fn join_rewrites(rewrites: &[String], is_block_like: &[bool], connector: &str) - result } +fn join_rewrites_vis(rewrites: &[String], connector: &str) -> String { + let mut rewrite_iter = rewrites.iter(); + let mut result = rewrite_iter.next().unwrap().clone(); + + for rewrite in rewrite_iter { + if rewrite != "?" { + result.push_str(connector); + } + result.push_str(&rewrite); + } + + result +} + // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { -- cgit 1.4.1-3-g733a5 From 38e8b086e8b1b318be3164e89d16e5e19d16cc59 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Jul 2018 20:45:30 +1200 Subject: chains: refactoring pre-process the expression tree to get a list of chain items. --- src/chains.rs | 203 ++++++++++++++++++++++++---------------------------------- 1 file changed, 84 insertions(+), 119 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 220cc4b8750..99fd3d0779b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -85,9 +85,13 @@ use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { debug!("rewrite_chain {:?}", shape); let chain = Chain::from_ast(expr, context); + // If this is just an expression with some `?`s, then format it trivially and + // return early. if chain.children.is_empty() { - return rewrite_try(&chain.parent.expr, chain.parent.tries, context, shape); + let rewrite = chain.parent.expr.rewrite(context, shape.sub_width(chain.parent.tries)?)?; + return Some(format!("{}{}", rewrite, "?".repeat(chain.parent.tries))); } + match context.config.indent_style() { IndentStyle::Block => rewrite_chain_block(chain, context, shape), IndentStyle::Visual => rewrite_chain_visual(chain, context, shape), @@ -103,70 +107,69 @@ struct ChainItem { struct Chain { parent: ChainItem, // TODO do we need to clone the exprs? - children: Vec, - span: Span, + children: Vec, } impl Chain { fn from_ast(expr: &ast::Expr, context: &RewriteContext) -> Chain { - let (parent, mut subexpr_list) = make_subexpr_list(expr, context); - let tries = subexpr_list.iter().rev().take_while(|e| is_try(e)).count(); - let new_len = subexpr_list.len() - tries; - subexpr_list.truncate(new_len); + let mut subexpr_list = make_subexpr_list(expr, context); + + // Un-parse the expression tree into ChainItems + let mut children = vec![]; + let mut sub_tries = 0; + loop { + if subexpr_list.is_empty() { + break; + } + + let subexpr = subexpr_list.pop().unwrap(); + match subexpr.node { + ast::ExprKind::Try(_) => sub_tries += 1, + _ => { + children.push(ChainItem { + expr: subexpr.clone(), + tries: sub_tries, + }); + sub_tries = 0; + } + } + } + Chain { - parent: ChainItem { - expr: parent, - tries, - }, - children: subexpr_list, - span: expr.span, + parent: children.pop().unwrap(), + children: children.into_iter().rev().collect(), } } } -fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - let (parent, subexpr_list) = (&chain.parent.expr, &chain.children); - - let suffix_try_num = subexpr_list.iter().take_while(|e| is_try(e)).count(); +fn rewrite_chain_block(mut chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + let last = chain.children.pop().unwrap(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = shape; - let parent_rewrite = parent - .rewrite(context, parent_shape) + let parent_rewrite = chain.parent.expr + .rewrite(context, shape) .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); - let parent_is_block = is_block_expr(context, &parent, &parent_rewrite); + let parent_is_block = is_block_expr(context, &chain.parent.expr, &parent_rewrite); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let (nested_shape, extend) = if !parent_rewrite_contains_newline && is_continuable(&parent) { - let shape = if parent_is_block { - shape - } else { - chain_indent(context, shape.add_offset(parent_rewrite.len())) - }; - (shape, is_small_parent) - } else if parent_is_block { - (parent_shape, true) + let other_child_shape = if parent_is_block { + shape } else { - ( - chain_indent(context, shape.add_offset(parent_rewrite.len())), - false, - ) - }; + shape.block_indent(context.config.tab_spaces()) + }.with_max_width(context.config); - let other_child_shape = nested_shape.with_max_width(context.config); + let extend = if !parent_rewrite_contains_newline && is_continuable(&chain.parent.expr) { + is_small_parent + } else { + parent_is_block + }; let first_child_shape = if extend { let offset = trimmed_last_line_width(&parent_rewrite) + chain.parent.tries; - if parent_is_block { - parent_shape.offset_left(offset)? - } else { - parent_shape - .block_indent(context.config.tab_spaces()) - .offset_left(offset)? - } + other_child_shape.offset_left(offset)? } else { other_child_shape }; @@ -175,21 +178,18 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> first_child_shape, other_child_shape ); - let last_subexpr = &subexpr_list[suffix_try_num]; - let subexpr_list = &subexpr_list[suffix_try_num..]; - - let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); - let mut is_block_like = Vec::with_capacity(subexpr_list.len()); + let mut rewrites: Vec = Vec::with_capacity(chain.children.len()); + let mut is_block_like = Vec::with_capacity(chain.children.len()); is_block_like.push(true); - for (i, expr) in subexpr_list.iter().skip(1).rev().enumerate() { + for (i, item) in chain.children.iter().enumerate() { let shape = if *is_block_like.last().unwrap() && !(extend && i == 0) { first_child_shape } else { other_child_shape }; - let rewrite = rewrite_chain_subexpr(expr, chain.span, context, shape)?; - is_block_like.push(is_block_expr(context, expr, &rewrite)); - rewrites.push(rewrite); + let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); + rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); } // Total of all items excluding the last. @@ -202,7 +202,7 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> last_line_width(&parent_rewrite) } else { rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() - } + suffix_try_num; + } + last.tries; let one_line_budget = if rewrites.is_empty() { shape.width } else { @@ -215,7 +215,7 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> first_child_shape } else { other_child_shape - }.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; + }.sub_width(shape.rhs_overhead(context.config) + last.tries)?; // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: @@ -252,12 +252,11 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, chain.span, context, last_shape); let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. - parent_shape.offset_left(almost_total).map(|shape| { - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, chain.span, context, shape) { + shape.offset_left(almost_total).map(|shape| { + if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -269,7 +268,7 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> // We could not know whether overflowing is better than using vertical layout, // just by looking at the overflowed rewrite. Now we rewrite the last child // on its own line, and compare two rewrites to choose which is better. - match rewrite_last() { + match rewrite_chain_subexpr(&last.expr, context, last_shape) { Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), Some(ref new_rw) if new_rw.lines().count() >= line_count => { (Some(rw), fits_single_line) @@ -279,11 +278,11 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> } } } else { - (rewrite_last(), false) + (rewrite_chain_subexpr(&last.expr, context, last_shape), false) } })? } else { - (rewrite_last(), false) + (rewrite_chain_subexpr(&last.expr, context, last_shape), false) }; rewrites.push(last_subexpr_str?); // We should never look at this, since we only look at the block-ness of the @@ -298,7 +297,7 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> if *context.force_one_line_chain.borrow() { return None; } - nested_shape.indent.to_string_with_newline(context.config) + other_child_shape.indent.to_string_with_newline(context.config) }; let first_connector = if is_small_parent @@ -335,33 +334,30 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> join_rewrites(&rewrites, &is_block_like[1..], &connector), ) }; - let result = format!("{}{}", result, "?".repeat(suffix_try_num)); + let result = format!("{}{}", result, "?".repeat(last.tries)); Some(result) } -fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - let parent = &chain.parent.expr; - - let suffix_try_num = chain.children.iter().take_while(|e| is_try(e)).count(); +fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + let last = chain.children.pop().unwrap(); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = if is_block_expr(context, &parent, "\n") { + let parent_shape = if is_block_expr(context, &chain.parent.expr, "\n") { shape.visual_indent(0) } else { shape }; - let parent_rewrite = parent + let parent_rewrite = chain.parent.expr .rewrite(context, parent_shape) .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); - let nested_shape = shape.visual_indent(0); - let other_child_shape = nested_shape.with_max_width(context.config); + let other_child_shape = shape.visual_indent(0).with_max_width(context.config); // Decide how to layout the rest of the chain. `extend` is true if we can // put the first non-parent item on the same line as the parent. - let extend = !parent_rewrite_contains_newline && is_continuable(&parent); + let extend = !parent_rewrite_contains_newline && is_continuable(&chain.parent.expr); let first_child_shape = if extend { let overhead = last_line_width(&parent_rewrite); @@ -374,18 +370,15 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> first_child_shape, other_child_shape ); - let last_subexpr = &chain.children[suffix_try_num]; - let subexpr_list = &chain.children[suffix_try_num..]; - - let mut rewrites: Vec = Vec::with_capacity(subexpr_list.len()); - for (i, expr) in subexpr_list.iter().skip(1).rev().enumerate() { + let mut rewrites: Vec = Vec::with_capacity(chain.children.len()); + for (i, item) in chain.children.iter().enumerate() { let shape = if i == 0 { first_child_shape } else { other_child_shape }; - let rewrite = rewrite_chain_subexpr(expr, chain.span, context, shape)?; - rewrites.push(rewrite); + let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); } // Total of all items excluding the last. @@ -398,7 +391,7 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> last_line_width(&parent_rewrite) } else { rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() - } + suffix_try_num; + } + last.tries; let one_line_budget = if rewrites.is_empty() { shape.width } else { @@ -408,7 +401,7 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> && rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; let last_shape = - other_child_shape.sub_width(shape.rhs_overhead(context.config) + suffix_try_num)?; + other_child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: @@ -443,14 +436,11 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> // }) // ``` - // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of - // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let rewrite_last = || rewrite_chain_subexpr(last_subexpr, chain.span, context, last_shape); let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. parent_shape.offset_left(almost_total).map(|shape| { - if let Some(rw) = rewrite_chain_subexpr(last_subexpr, chain.span, context, shape) { + if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -462,7 +452,7 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> // We could not know whether overflowing is better than using vertical layout, // just by looking at the overflowed rewrite. Now we rewrite the last child // on its own line, and compare two rewrites to choose which is better. - match rewrite_last() { + match rewrite_chain_subexpr(&last.expr, context, last_shape) { Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), Some(ref new_rw) if new_rw.lines().count() >= line_count => { (Some(rw), fits_single_line) @@ -472,11 +462,11 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> } } } else { - (rewrite_last(), false) + (rewrite_chain_subexpr(&last.expr, context, last_shape), false) } })? } else { - (rewrite_last(), false) + (rewrite_chain_subexpr(&last.expr, context, last_shape), false) }; rewrites.push(last_subexpr_str?); @@ -488,7 +478,7 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> if *context.force_one_line_chain.borrow() { return None; } - nested_shape.indent.to_string_with_newline(context.config) + other_child_shape.indent.to_string_with_newline(context.config) }; let result = if is_small_parent && rewrites.len() > 1 { @@ -505,20 +495,10 @@ fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> join_rewrites_vis(&rewrites, &connector), ) }; - let result = format!("{}{}", result, "?".repeat(suffix_try_num)); + let result = format!("{}{}", result, "?".repeat(last.tries)); wrap_str(result, context.config.max_width(), shape) } -fn rewrite_try( - expr: &ast::Expr, - try_count: usize, - context: &RewriteContext, - shape: Shape, -) -> Option { - let sub_expr = expr.rewrite(context, shape.sub_width(try_count)?)?; - Some(format!("{}{}", sub_expr, "?".repeat(try_count))) -} - fn join_rewrites(rewrites: &[String], is_block_like: &[bool], connector: &str) -> String { let mut rewrite_iter = rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); @@ -576,23 +556,16 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool } } -fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape { - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config) -} - -// Returns the root of the chain and a Vec of the prefixes of the rest of the chain. -// E.g., for input `a.b.c` we return (`a`, [`a.b.c`, `a.b`]) -fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> (ast::Expr, Vec) { +// Returns a Vec of the prefixes of the chain. +// E.g., for input `a.b.c` we return [`a.b.c`, `a.b`, 'a'] +fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> Vec { let mut subexpr_list = vec![expr.clone()]; while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { subexpr_list.push(subexpr.clone()); } - let parent = subexpr_list.pop().unwrap(); - (parent, subexpr_list) + subexpr_list } // Returns the expression's subexpression, if it exists. When the subexpr @@ -626,7 +599,6 @@ fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { // `.c`. fn rewrite_chain_subexpr( expr: &ast::Expr, - span: Span, context: &RewriteContext, shape: Shape, ) -> Option { @@ -647,7 +619,7 @@ fn rewrite_chain_subexpr( }, _ => &[], }; - rewrite_method_call(segment.ident, types, expressions, span, context, shape) + rewrite_method_call(segment.ident, types, expressions, expr.span, context, shape) } ast::ExprKind::Field(ref nested, ref field) => { let space = if is_tup_field_access(expr) && is_tup_field_access(nested) { @@ -679,13 +651,6 @@ fn is_continuable(expr: &ast::Expr) -> bool { } } -fn is_try(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Try(..) => true, - _ => false, - } -} - fn rewrite_method_call( method_name: ast::Ident, types: &[ast::GenericArg], -- cgit 1.4.1-3-g733a5 From 914e750c9ead9a80e6514c08388cce11380cb949 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 Jul 2018 21:09:25 +1200 Subject: chains: further simplification --- src/chains.rs | 78 ++++++++++++++++++++++++----------------------------------- 1 file changed, 32 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 99fd3d0779b..a407fdda112 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -161,11 +161,7 @@ fn rewrite_chain_block(mut chain: Chain, context: &RewriteContext, shape: Shape) shape.block_indent(context.config.tab_spaces()) }.with_max_width(context.config); - let extend = if !parent_rewrite_contains_newline && is_continuable(&chain.parent.expr) { - is_small_parent - } else { - parent_is_block - }; + let extend = parent_is_block || (is_small_parent && !parent_rewrite_contains_newline && is_continuable(&chain.parent.expr)); let first_child_shape = if extend { let offset = trimmed_last_line_width(&parent_rewrite) + chain.parent.tries; @@ -351,7 +347,6 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape .rewrite(context, parent_shape) .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); - let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); let other_child_shape = shape.visual_indent(0).with_max_width(context.config); @@ -382,16 +377,7 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape } // Total of all items excluding the last. - let extend_last_subexpr = if is_small_parent { - rewrites.len() == 1 && last_line_extendable(&rewrites[0]) - } else { - rewrites.is_empty() && last_line_extendable(&parent_rewrite) - }; - let almost_total = if extend_last_subexpr { - last_line_width(&parent_rewrite) - } else { - rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() - } + last.tries; + let almost_total = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() + last.tries; let one_line_budget = if rewrites.is_empty() { shape.width } else { @@ -436,38 +422,48 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape // }) // ``` - let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { + let mut last_subexpr_str = None; + let mut fits_single_line = false; + + if all_in_one_line { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. - parent_shape.offset_left(almost_total).map(|shape| { + if let Some(shape) = parent_shape.offset_left(almost_total) { if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. let line_count = rw.lines().count(); - let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if fits_single_line && line_count >= 5 { - (Some(rw), true) + let could_fit_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + if could_fit_single_line && line_count >= 5 { + last_subexpr_str = Some(rw); + fits_single_line = true; } else { // We could not know whether overflowing is better than using vertical layout, // just by looking at the overflowed rewrite. Now we rewrite the last child // on its own line, and compare two rewrites to choose which is better. match rewrite_chain_subexpr(&last.expr, context, last_shape) { - Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), + Some(ref new_rw) if !could_fit_single_line => { + last_subexpr_str = Some(new_rw.clone()); + } Some(ref new_rw) if new_rw.lines().count() >= line_count => { - (Some(rw), fits_single_line) + last_subexpr_str = Some(rw); + fits_single_line = could_fit_single_line; + } + new_rw @ Some(..) => { + last_subexpr_str = new_rw; + } + _ => { + last_subexpr_str = Some(rw); + fits_single_line = could_fit_single_line; } - new_rw @ Some(..) => (new_rw, false), - _ => (Some(rw), fits_single_line), } } - } else { - (rewrite_chain_subexpr(&last.expr, context, last_shape), false) } - })? - } else { - (rewrite_chain_subexpr(&last.expr, context, last_shape), false) - }; + } + } + + last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); rewrites.push(last_subexpr_str?); let connector = if fits_single_line && !parent_rewrite_contains_newline { @@ -481,21 +477,11 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape other_child_shape.indent.to_string_with_newline(context.config) }; - let result = if is_small_parent && rewrites.len() > 1 { - format!( - "{}{}{}", - parent_rewrite, - rewrites[0], - join_rewrites_vis(&rewrites[1..], &connector), - ) - } else { - format!( - "{}{}", - parent_rewrite, - join_rewrites_vis(&rewrites, &connector), - ) - }; - let result = format!("{}{}", result, "?".repeat(last.tries)); + let result = format!("{}{}{}", + parent_rewrite, + join_rewrites_vis(&rewrites, &connector), + "?".repeat(last.tries), + ); wrap_str(result, context.config.max_width(), shape) } -- cgit 1.4.1-3-g733a5 From 92701552bcdcd29dd93f72bd5055f96caf2d25c6 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 10 Jul 2018 12:24:45 +1200 Subject: chains: refactor block formatting --- src/chains.rs | 207 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 93 insertions(+), 114 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index a407fdda112..ff3633a8cff 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -71,10 +71,7 @@ use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{ - first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, - wrap_str, -}; +use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, wrap_str}; use std::borrow::Cow; use std::cmp::min; @@ -99,11 +96,13 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - } // An expression plus trailing `?`s to be formatted together. +#[derive(Debug)] struct ChainItem { expr: ast::Expr, tries: usize, } +#[derive(Debug)] struct Chain { parent: ChainItem, // TODO do we need to clone the exprs? @@ -136,82 +135,89 @@ impl Chain { } Chain { - parent: children.pop().unwrap(), - children: children.into_iter().rev().collect(), + parent: children.remove(0), + children, } } } -fn rewrite_chain_block(mut chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - let last = chain.children.pop().unwrap(); - +fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + debug!("rewrite_chain_block {:?} {:?}", chain, shape); // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_rewrite = chain.parent.expr + // Root is the parent plus any other chain items placed on the first line to + // avoid an orphan. E.g., + // ``` + // foo.bar + // .baz() + // ``` + // If `bar` were not part of the root, then baz would be orphaned and 'float'. + let mut root_rewrite = chain.parent.expr .rewrite(context, shape) .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; - let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); - let is_small_parent = shape.offset + parent_rewrite.len() <= context.config.tab_spaces(); - let parent_is_block = is_block_expr(context, &chain.parent.expr, &parent_rewrite); - // Decide how to layout the rest of the chain. `extend` is true if we can - // put the first non-parent item on the same line as the parent. - let other_child_shape = if parent_is_block { + let mut children: &[_] = &chain.children; + let mut root_ends_with_block = is_block_expr(context, &chain.parent.expr, &root_rewrite); + let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); + + while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { + let item = &children[0]; + let shape = shape.offset_left(root_rewrite.len())?; + match rewrite_chain_subexpr(&item.expr, context, shape) { + Some(rewrite) => { + root_rewrite.push_str(&rewrite); + root_rewrite.push_str(&"?".repeat(item.tries)); + } + None => break, + } + + root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); + + children = &children[1..]; + if children.is_empty() { + return Some(root_rewrite); + } + } + + // Separate out the last item in the chain for special treatment below. + let last = &children[children.len() - 1]; + children = &children[..children.len() - 1]; + + // Decide how to layout the rest of the chain. + let child_shape = if root_ends_with_block { shape } else { shape.block_indent(context.config.tab_spaces()) }.with_max_width(context.config); - let extend = parent_is_block || (is_small_parent && !parent_rewrite_contains_newline && is_continuable(&chain.parent.expr)); - - let first_child_shape = if extend { - let offset = trimmed_last_line_width(&parent_rewrite) + chain.parent.tries; - other_child_shape.offset_left(offset)? - } else { - other_child_shape - }; - debug!( - "child_shapes {:?} {:?}", - first_child_shape, other_child_shape - ); - - let mut rewrites: Vec = Vec::with_capacity(chain.children.len()); - let mut is_block_like = Vec::with_capacity(chain.children.len()); - is_block_like.push(true); - for (i, item) in chain.children.iter().enumerate() { - let shape = if *is_block_like.last().unwrap() && !(extend && i == 0) { - first_child_shape - } else { - other_child_shape - }; - let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + let mut rewrites: Vec = Vec::with_capacity(children.len()); + rewrites.push(root_rewrite); + let mut is_block_like = Vec::with_capacity(children.len()); + is_block_like.push(root_ends_with_block); + for item in children { + let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); } // Total of all items excluding the last. - let extend_last_subexpr = if is_small_parent { - rewrites.len() == 1 && last_line_extendable(&rewrites[0]) - } else { - rewrites.is_empty() && last_line_extendable(&parent_rewrite) - }; + let extend_last_subexpr = last_line_extendable(&rewrites[rewrites.len() - 1]); let almost_total = if extend_last_subexpr { - last_line_width(&parent_rewrite) + last_line_width(&rewrites[rewrites.len() - 1]) } else { - rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() + rewrites.iter().fold(0, |a, b| a + b.len()) } + last.tries; - let one_line_budget = if rewrites.is_empty() { + let one_line_budget = if rewrites.len() == 1 { shape.width } else { min(shape.width, context.config.width_heuristics().chain_width) }; - let all_in_one_line = !parent_rewrite_contains_newline - && rewrites.iter().all(|s| !s.contains('\n')) + let all_in_one_line = rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = if is_block_like[rewrites.len()] { - first_child_shape + let last_shape = if all_in_one_line { + shape.sub_width(last.tries)? } else { - other_child_shape - }.sub_width(shape.rhs_overhead(context.config) + last.tries)?; + child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)? + }; // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: @@ -246,46 +252,54 @@ fn rewrite_chain_block(mut chain: Chain, context: &RewriteContext, shape: Shape) // }) // ``` - // `rewrite_last` rewrites the last child on its own line. We use a closure here instead of - // directly calling `rewrite_chain_subexpr()` to avoid exponential blowup. - let (last_subexpr_str, fits_single_line) = if all_in_one_line || extend_last_subexpr { + let mut last_subexpr_str = None; + let mut fits_single_line = false; + if all_in_one_line || extend_last_subexpr { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. - shape.offset_left(almost_total).map(|shape| { + if let Some(shape) = last_shape.offset_left(almost_total) { if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. let line_count = rw.lines().count(); - let fits_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + let could_fit_single_line = almost_total + first_line_width(&rw) <= one_line_budget; if fits_single_line && line_count >= 5 { - (Some(rw), true) + last_subexpr_str = Some(rw); + fits_single_line = true; } else { // We could not know whether overflowing is better than using vertical layout, // just by looking at the overflowed rewrite. Now we rewrite the last child // on its own line, and compare two rewrites to choose which is better. match rewrite_chain_subexpr(&last.expr, context, last_shape) { - Some(ref new_rw) if !fits_single_line => (Some(new_rw.clone()), false), + Some(ref new_rw) if !could_fit_single_line => { + last_subexpr_str = Some(new_rw.clone()); + } Some(ref new_rw) if new_rw.lines().count() >= line_count => { - (Some(rw), fits_single_line) + last_subexpr_str = Some(rw); + fits_single_line = could_fit_single_line; + } + new_rw @ Some(..) => { + last_subexpr_str = new_rw; + } + _ => { + last_subexpr_str = Some(rw); + fits_single_line = could_fit_single_line; } - new_rw @ Some(..) => (new_rw, false), - _ => (Some(rw), fits_single_line), } } - } else { - (rewrite_chain_subexpr(&last.expr, context, last_shape), false) } - })? - } else { - (rewrite_chain_subexpr(&last.expr, context, last_shape), false) - }; - rewrites.push(last_subexpr_str?); + } + } + + last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); + rewrites.push(format!("{}{}", last_subexpr_str?, "?".repeat(last.tries))); + // We should never look at this, since we only look at the block-ness of the // previous item in the chain. is_block_like.push(false); - let connector = if fits_single_line && !parent_rewrite_contains_newline { + let connector = if fits_single_line && all_in_one_line { // Yay, we can put everything on one line. Cow::from("") } else { @@ -293,44 +307,10 @@ fn rewrite_chain_block(mut chain: Chain, context: &RewriteContext, shape: Shape) if *context.force_one_line_chain.borrow() { return None; } - other_child_shape.indent.to_string_with_newline(context.config) + child_shape.indent.to_string_with_newline(context.config) }; - let first_connector = if is_small_parent - || fits_single_line - || last_line_extendable(&parent_rewrite) - { - "" - } else { - &connector - }; - - let result = if is_small_parent && rewrites.len() > 1 { - let second_connector = if fits_single_line - || rewrites[1] == "?" - || last_line_extendable(&rewrites[0]) - { - "" - } else { - &connector - }; - format!( - "{}{}{}{}{}", - parent_rewrite, - first_connector, - rewrites[0], - second_connector, - join_rewrites(&rewrites[1..], &is_block_like[2..], &connector), - ) - } else { - format!( - "{}{}{}", - parent_rewrite, - first_connector, - join_rewrites(&rewrites, &is_block_like[1..], &connector), - ) - }; - let result = format!("{}{}", result, "?".repeat(last.tries)); + let result = join_rewrites(&rewrites, &is_block_like, &connector); Some(result) } @@ -424,7 +404,6 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape let mut last_subexpr_str = None; let mut fits_single_line = false; - if all_in_one_line { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. @@ -517,7 +496,9 @@ fn join_rewrites_vis(rewrites: &[String], connector: &str) -> String { // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { match expr.node { - ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) => { + ast::ExprKind::Mac(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) => { context.use_block_indent() && repr.contains('\n') } ast::ExprKind::Struct(..) @@ -533,11 +514,9 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool | ast::ExprKind::Binary(_, _, ref expr) | ast::ExprKind::Index(_, ref expr) | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Closure(_, _, _, _, ref expr, _) => is_block_expr(context, expr, repr), - ast::ExprKind::MethodCall(_, ref exprs) => { - // TODO maybe should be like Call - is_block_expr(context, exprs.last().unwrap(), repr) - } + | ast::ExprKind::Closure(_, _, _, _, ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), _ => false, } } -- cgit 1.4.1-3-g733a5 From 86314bf09f22341703dfc539d4e0c55478face0b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 10 Jul 2018 15:14:44 +1200 Subject: chains: more refactoring of visual formatting --- src/chains.rs | 70 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index ff3633a8cff..9f06b240c7c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -189,9 +189,9 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> shape.block_indent(context.config.tab_spaces()) }.with_max_width(context.config); - let mut rewrites: Vec = Vec::with_capacity(children.len()); + let mut rewrites: Vec = Vec::with_capacity(children.len() + 2); rewrites.push(root_rewrite); - let mut is_block_like = Vec::with_capacity(children.len()); + let mut is_block_like = Vec::with_capacity(children.len() + 2); is_block_like.push(root_ends_with_block); for item in children { let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; @@ -314,60 +314,53 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Some(result) } -fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - let last = chain.children.pop().unwrap(); - +fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &chain.parent.expr, "\n") { shape.visual_indent(0) } else { shape }; - let parent_rewrite = chain.parent.expr + let mut children: &[_] = &chain.children; + let mut root_rewrite = chain.parent.expr .rewrite(context, parent_shape) .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; - let parent_rewrite_contains_newline = parent_rewrite.contains('\n'); - let other_child_shape = shape.visual_indent(0).with_max_width(context.config); + if !root_rewrite.contains('\n') && is_continuable(&chain.parent.expr) { + let item = &children[0]; + let overhead = last_line_width(&root_rewrite); + let shape = parent_shape.offset_left(overhead)?; + let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + root_rewrite.push_str(&rewrite); + root_rewrite.push_str(&"?".repeat(item.tries)); + children = &children[1..]; + if children.is_empty() { + return Some(root_rewrite); + } + } - // Decide how to layout the rest of the chain. `extend` is true if we can - // put the first non-parent item on the same line as the parent. - let extend = !parent_rewrite_contains_newline && is_continuable(&chain.parent.expr); + let last = &children[children.len() - 1]; + children = &children[..children.len() - 1]; - let first_child_shape = if extend { - let overhead = last_line_width(&parent_rewrite); - parent_shape.offset_left(overhead)? - } else { - other_child_shape - }; - debug!( - "child_shapes {:?} {:?}", - first_child_shape, other_child_shape - ); + let child_shape = shape.visual_indent(0).with_max_width(context.config); - let mut rewrites: Vec = Vec::with_capacity(chain.children.len()); - for (i, item) in chain.children.iter().enumerate() { - let shape = if i == 0 { - first_child_shape - } else { - other_child_shape - }; - let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + let mut rewrites: Vec = Vec::with_capacity(children.len() + 2); + rewrites.push(root_rewrite); + for item in chain.children.iter() { + let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); } // Total of all items excluding the last. - let almost_total = rewrites.iter().fold(0, |a, b| a + b.len()) + parent_rewrite.len() + last.tries; - let one_line_budget = if rewrites.is_empty() { + let almost_total = rewrites.iter().fold(0, |a, b| a + b.len()) + last.tries; + let one_line_budget = if rewrites.len() == 1 { shape.width } else { min(shape.width, context.config.width_heuristics().chain_width) }; - let all_in_one_line = !parent_rewrite_contains_newline - && rewrites.iter().all(|s| !s.contains('\n')) + let all_in_one_line = rewrites.iter().all(|s| !s.contains('\n')) && almost_total < one_line_budget; - let last_shape = - other_child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; + let last_shape = child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: @@ -445,7 +438,7 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); rewrites.push(last_subexpr_str?); - let connector = if fits_single_line && !parent_rewrite_contains_newline { + let connector = if fits_single_line && all_in_one_line { // Yay, we can put everything on one line. Cow::from("") } else { @@ -453,11 +446,10 @@ fn rewrite_chain_visual(mut chain: Chain, context: &RewriteContext, shape: Shape if *context.force_one_line_chain.borrow() { return None; } - other_child_shape.indent.to_string_with_newline(context.config) + child_shape.indent.to_string_with_newline(context.config) }; - let result = format!("{}{}{}", - parent_rewrite, + let result = format!("{}{}", join_rewrites_vis(&rewrites, &connector), "?".repeat(last.tries), ); -- cgit 1.4.1-3-g733a5 From a56ff9d02f67a2736a6735014564fe5e496ad148 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 12:01:39 +1200 Subject: chains: factor into objects --- src/chains.rs | 632 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 331 insertions(+), 301 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9f06b240c7c..692d1c946fc 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -111,7 +111,7 @@ struct Chain { impl Chain { fn from_ast(expr: &ast::Expr, context: &RewriteContext) -> Chain { - let mut subexpr_list = make_subexpr_list(expr, context); + let mut subexpr_list = Self::make_subexpr_list(expr, context); // Un-parse the expression tree into ChainItems let mut children = vec![]; @@ -139,10 +139,67 @@ impl Chain { children, } } + + // Returns a Vec of the prefixes of the chain. + // E.g., for input `a.b.c` we return [`a.b.c`, `a.b`, 'a'] + fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> Vec { + let mut subexpr_list = vec![expr.clone()]; + + while let Some(subexpr) = Self::pop_expr_chain(subexpr_list.last().unwrap(), context) { + subexpr_list.push(subexpr.clone()); + } + + subexpr_list + } + + // Returns the expression's subexpression, if it exists. When the subexpr + // is a try! macro, we'll convert it to shorthand when the option is set. + fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { + match expr.node { + ast::ExprKind::MethodCall(_, ref expressions) => { + Some(Self::convert_try(&expressions[0], context)) + } + ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) => { + Some(Self::convert_try(subexpr, context)) + } + _ => None, + } + } + + fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { + match expr.node { + ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { + if let Some(subexpr) = convert_try_mac(mac, context) { + subexpr + } else { + expr.clone() + } + } + _ => expr.clone(), + } + } } -fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - debug!("rewrite_chain_block {:?} {:?}", chain, shape); +// TODO comments +struct ChainFormatterBlock<'a> { + children: &'a[ChainItem], + rewrites: Vec, + root_ends_with_block: bool, + is_block_like: Vec, + fits_single_line: bool, +} + +impl <'a> ChainFormatterBlock<'a> { + fn new(chain: &'a Chain) -> ChainFormatterBlock<'a> { + ChainFormatterBlock { + children: &chain.children, + root_ends_with_block: false, + rewrites: Vec::with_capacity(chain.children.len() + 1), + is_block_like: Vec::with_capacity(chain.children.len() + 1), + fits_single_line: false, + } + } + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. // Root is the parent plus any other chain items placed on the first line to // avoid an orphan. E.g., @@ -151,73 +208,53 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> // .baz() // ``` // If `bar` were not part of the root, then baz would be orphaned and 'float'. - let mut root_rewrite = chain.parent.expr - .rewrite(context, shape) - .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; - - let mut children: &[_] = &chain.children; - let mut root_ends_with_block = is_block_expr(context, &chain.parent.expr, &root_rewrite); - let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); - - while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { - let item = &children[0]; - let shape = shape.offset_left(root_rewrite.len())?; - match rewrite_chain_subexpr(&item.expr, context, shape) { - Some(rewrite) => { - root_rewrite.push_str(&rewrite); - root_rewrite.push_str(&"?".repeat(item.tries)); + fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { + let mut root_rewrite: String = parent.expr + .rewrite(context, shape) + .map(|parent_rw| parent_rw + &"?".repeat(parent.tries))?; + + self.root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); + let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); + + while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { + let item = &self.children[0]; + let shape = shape.offset_left(root_rewrite.len())?; + match rewrite_chain_subexpr(&item.expr, context, shape) { + Some(rewrite) => { + root_rewrite.push_str(&rewrite); + root_rewrite.push_str(&"?".repeat(item.tries)); + } + None => break, } - None => break, - } - root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); + self.root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); - children = &children[1..]; - if children.is_empty() { - return Some(root_rewrite); + self.children = &self.children[1..]; + if self.children.is_empty() { + break; + } } + self.rewrites.push(root_rewrite); + Some(()) } - // Separate out the last item in the chain for special treatment below. - let last = &children[children.len() - 1]; - children = &children[..children.len() - 1]; - - // Decide how to layout the rest of the chain. - let child_shape = if root_ends_with_block { - shape - } else { - shape.block_indent(context.config.tab_spaces()) - }.with_max_width(context.config); - - let mut rewrites: Vec = Vec::with_capacity(children.len() + 2); - rewrites.push(root_rewrite); - let mut is_block_like = Vec::with_capacity(children.len() + 2); - is_block_like.push(root_ends_with_block); - for item in children { - let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; - is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); - rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape { + if self.root_ends_with_block { + shape + } else { + shape.block_indent(context.config.tab_spaces()) + }.with_max_width(context.config) } - // Total of all items excluding the last. - let extend_last_subexpr = last_line_extendable(&rewrites[rewrites.len() - 1]); - let almost_total = if extend_last_subexpr { - last_line_width(&rewrites[rewrites.len() - 1]) - } else { - rewrites.iter().fold(0, |a, b| a + b.len()) - } + last.tries; - let one_line_budget = if rewrites.len() == 1 { - shape.width - } else { - min(shape.width, context.config.width_heuristics().chain_width) - }; - let all_in_one_line = rewrites.iter().all(|s| !s.contains('\n')) - && almost_total < one_line_budget; - let last_shape = if all_in_one_line { - shape.sub_width(last.tries)? - } else { - child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)? - }; + fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { + self.is_block_like.push(self.root_ends_with_block); + for item in &self.children[..self.children.len()] { + let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; + self.is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); + self.rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); + } + Some(()) + } // Rewrite the last child. The last child of a chain requires special treatment. We need to // know whether 'overflowing' the last child make a better formatting: @@ -251,237 +288,277 @@ fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> // result // }) // ``` + fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { + let last = &self.children[self.children.len() - 1]; + let extendable = last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); + // Total of all items excluding the last. + let almost_total = if extendable { + last_line_width(&self.rewrites[self.rewrites.len() - 1]) + } else { + self.rewrites.iter().fold(0, |a, b| a + b.len()) + } + last.tries; + let one_line_budget = if self.rewrites.len() == 1 { + shape.width + } else { + min(shape.width, context.config.width_heuristics().chain_width) + }.saturating_sub(almost_total); - let mut last_subexpr_str = None; - let mut fits_single_line = false; - if all_in_one_line || extend_last_subexpr { - // First we try to 'overflow' the last child and see if it looks better than using - // vertical layout. - if let Some(shape) = last_shape.offset_left(almost_total) { - if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { - // We allow overflowing here only if both of the following conditions match: - // 1. The entire chain fits in a single line except the last child. - // 2. `last_child_str.lines().count() >= 5`. - let line_count = rw.lines().count(); - let could_fit_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if fits_single_line && line_count >= 5 { - last_subexpr_str = Some(rw); - fits_single_line = true; - } else { - // We could not know whether overflowing is better than using vertical layout, - // just by looking at the overflowed rewrite. Now we rewrite the last child - // on its own line, and compare two rewrites to choose which is better. - match rewrite_chain_subexpr(&last.expr, context, last_shape) { - Some(ref new_rw) if !could_fit_single_line => { - last_subexpr_str = Some(new_rw.clone()); - } - Some(ref new_rw) if new_rw.lines().count() >= line_count => { - last_subexpr_str = Some(rw); - fits_single_line = could_fit_single_line; - } - new_rw @ Some(..) => { - last_subexpr_str = new_rw; - } - _ => { - last_subexpr_str = Some(rw); - fits_single_line = could_fit_single_line; + let all_in_one_line = self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; + let last_shape = if all_in_one_line { + shape.sub_width(last.tries)? + } else { + child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)? + }; + + let mut last_subexpr_str = None; + if all_in_one_line || extendable { + // First we try to 'overflow' the last child and see if it looks better than using + // vertical layout. + if let Some(shape) = last_shape.offset_left(almost_total) { + if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { + // We allow overflowing here only if both of the following conditions match: + // 1. The entire chain fits in a single line except the last child. + // 2. `last_child_str.lines().count() >= 5`. + let line_count = rw.lines().count(); + let could_fit_single_line = first_line_width(&rw) <= one_line_budget; + if could_fit_single_line && line_count >= 5 { + last_subexpr_str = Some(rw); + self.fits_single_line = all_in_one_line; + } else { + // We could not know whether overflowing is better than using vertical layout, + // just by looking at the overflowed rewrite. Now we rewrite the last child + // on its own line, and compare two rewrites to choose which is better. + match rewrite_chain_subexpr(&last.expr, context, last_shape) { + Some(ref new_rw) if !could_fit_single_line => { + last_subexpr_str = Some(new_rw.clone()); + } + Some(ref new_rw) if new_rw.lines().count() >= line_count => { + last_subexpr_str = Some(rw); + self.fits_single_line = could_fit_single_line && all_in_one_line; + } + new_rw @ Some(..) => { + last_subexpr_str = new_rw; + } + _ => { + last_subexpr_str = Some(rw); + self.fits_single_line = could_fit_single_line && all_in_one_line; + } } } } } } + + last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); + self.rewrites.push(format!("{}{}", last_subexpr_str?, "?".repeat(last.tries))); + Some(()) } - last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); - rewrites.push(format!("{}{}", last_subexpr_str?, "?".repeat(last.tries))); - // We should never look at this, since we only look at the block-ness of the - // previous item in the chain. - is_block_like.push(false); + fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + let connector = if self.fits_single_line { + // Yay, we can put everything on one line. + Cow::from("") + } else { + // Use new lines. + if *context.force_one_line_chain.borrow() { + return None; + } + child_shape.indent.to_string_with_newline(context.config) + }; - let connector = if fits_single_line && all_in_one_line { - // Yay, we can put everything on one line. - Cow::from("") - } else { - // Use new lines. - if *context.force_one_line_chain.borrow() { - return None; + let mut rewrite_iter = self.rewrites.iter(); + let mut result = rewrite_iter.next().unwrap().clone(); + + for (rewrite, prev_is_block_like) in rewrite_iter.zip(self.is_block_like.iter()) { + if rewrite != "?" && !prev_is_block_like { + result.push_str(&connector); + } + result.push_str(&rewrite); } - child_shape.indent.to_string_with_newline(context.config) - }; - let result = join_rewrites(&rewrites, &is_block_like, &connector); + Some(result) + } +} + +fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + debug!("rewrite_chain_block {:?} {:?}", chain, shape); + + let mut formatter = ChainFormatterBlock::new(&chain); + + formatter.format_root(&chain.parent, context, shape)?; + if formatter.children.is_empty() { + assert_eq!(formatter.rewrites.len(), 1); + return Some(formatter.rewrites.pop().unwrap()); + } + + // Decide how to layout the rest of the chain. + let child_shape = formatter.child_shape(context, shape); + formatter.format_children(context, child_shape)?; + + formatter.format_last_child(context, shape, child_shape)?; + + let result = formatter.join_rewrites(context, child_shape)?; Some(result) } -fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = if is_block_expr(context, &chain.parent.expr, "\n") { - shape.visual_indent(0) - } else { - shape - }; - let mut children: &[_] = &chain.children; - let mut root_rewrite = chain.parent.expr - .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &"?".repeat(chain.parent.tries))?; - - if !root_rewrite.contains('\n') && is_continuable(&chain.parent.expr) { - let item = &children[0]; - let overhead = last_line_width(&root_rewrite); - let shape = parent_shape.offset_left(overhead)?; - let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; - root_rewrite.push_str(&rewrite); - root_rewrite.push_str(&"?".repeat(item.tries)); - children = &children[1..]; - if children.is_empty() { - return Some(root_rewrite); +struct ChainFormatterVisual<'a> { + children: &'a[ChainItem], + rewrites: Vec, + fits_single_line: bool, +} + +impl<'a> ChainFormatterVisual<'a> { + fn new(chain: &'a Chain) -> ChainFormatterVisual<'a> { + ChainFormatterVisual { + children: &chain.children, + rewrites: Vec::with_capacity(chain.children.len() + 1), + fits_single_line: false, } } - let last = &children[children.len() - 1]; - children = &children[..children.len() - 1]; + fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. + let parent_shape = if is_block_expr(context, &parent.expr, "\n") { + shape.visual_indent(0) + } else { + shape + }; + let mut root_rewrite = parent.expr + .rewrite(context, parent_shape) + .map(|parent_rw| parent_rw + &"?".repeat(parent.tries))?; + + if !root_rewrite.contains('\n') && Self::is_continuable(&parent.expr) { + let item = &self.children[0]; + let overhead = last_line_width(&root_rewrite); + let shape = parent_shape.offset_left(overhead)?; + let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + root_rewrite.push_str(&rewrite); + root_rewrite.push_str(&"?".repeat(item.tries)); + + self.children = &self.children[1..]; + } - let child_shape = shape.visual_indent(0).with_max_width(context.config); + self.rewrites.push(root_rewrite); + Some(()) + } - let mut rewrites: Vec = Vec::with_capacity(children.len() + 2); - rewrites.push(root_rewrite); - for item in chain.children.iter() { - let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; - rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); + // Determines if we can continue formatting a given expression on the same line. + fn is_continuable(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Path(..) => true, + _ => false, + } } - // Total of all items excluding the last. - let almost_total = rewrites.iter().fold(0, |a, b| a + b.len()) + last.tries; - let one_line_budget = if rewrites.len() == 1 { - shape.width - } else { - min(shape.width, context.config.width_heuristics().chain_width) - }; - let all_in_one_line = rewrites.iter().all(|s| !s.contains('\n')) - && almost_total < one_line_budget; - let last_shape = child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; + fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { + for item in &self.children[..self.children.len() - 1] { + let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; + self.rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); + } + Some(()) + } - // Rewrite the last child. The last child of a chain requires special treatment. We need to - // know whether 'overflowing' the last child make a better formatting: - // - // A chain with overflowing the last child: - // ``` - // parent.child1.child2.last_child( - // a, - // b, - // c, - // ) - // ``` - // - // A chain without overflowing the last child (in vertical layout): - // ``` - // parent - // .child1 - // .child2 - // .last_child(a, b, c) - // ``` - // - // In particular, overflowing is effective when the last child is a method with a multi-lined - // block-like argument (e.g. closure): - // ``` - // parent.child1.child2.last_child(|a, b, c| { - // let x = foo(a, b, c); - // let y = bar(a, b, c); - // - // // ... - // - // result - // }) - // ``` + fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { + let last = &self.children[self.children.len() - 1]; - let mut last_subexpr_str = None; - let mut fits_single_line = false; - if all_in_one_line { - // First we try to 'overflow' the last child and see if it looks better than using - // vertical layout. - if let Some(shape) = parent_shape.offset_left(almost_total) { - if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { - // We allow overflowing here only if both of the following conditions match: - // 1. The entire chain fits in a single line except the last child. - // 2. `last_child_str.lines().count() >= 5`. - let line_count = rw.lines().count(); - let could_fit_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if could_fit_single_line && line_count >= 5 { - last_subexpr_str = Some(rw); - fits_single_line = true; - } else { - // We could not know whether overflowing is better than using vertical layout, - // just by looking at the overflowed rewrite. Now we rewrite the last child - // on its own line, and compare two rewrites to choose which is better. - match rewrite_chain_subexpr(&last.expr, context, last_shape) { - Some(ref new_rw) if !could_fit_single_line => { - last_subexpr_str = Some(new_rw.clone()); - } - Some(ref new_rw) if new_rw.lines().count() >= line_count => { - last_subexpr_str = Some(rw); - fits_single_line = could_fit_single_line; - } - new_rw @ Some(..) => { - last_subexpr_str = new_rw; - } - _ => { - last_subexpr_str = Some(rw); - fits_single_line = could_fit_single_line; + // Total of all items excluding the last. + let almost_total = self.rewrites.iter().fold(0, |a, b| a + b.len()) + last.tries; + let one_line_budget = if self.rewrites.len() == 1 { + shape.width + } else { + min(shape.width, context.config.width_heuristics().chain_width) + }; + let all_in_one_line = self.rewrites.iter().all(|s| !s.contains('\n')) + && almost_total < one_line_budget; + let last_shape = child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; + + + let mut last_subexpr_str = None; + if all_in_one_line { + // First we try to 'overflow' the last child and see if it looks better than using + // vertical layout. + if let Some(shape) = shape.offset_left(almost_total) { + if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { + // We allow overflowing here only if both of the following conditions match: + // 1. The entire chain fits in a single line except the last child. + // 2. `last_child_str.lines().count() >= 5`. + let line_count = rw.lines().count(); + let could_fit_single_line = almost_total + first_line_width(&rw) <= one_line_budget; + if could_fit_single_line && line_count >= 5 { + last_subexpr_str = Some(rw); + self.fits_single_line = all_in_one_line; + } else { + // We could not know whether overflowing is better than using vertical layout, + // just by looking at the overflowed rewrite. Now we rewrite the last child + // on its own line, and compare two rewrites to choose which is better. + match rewrite_chain_subexpr(&last.expr, context, last_shape) { + Some(ref new_rw) if !could_fit_single_line => { + last_subexpr_str = Some(new_rw.clone()); + } + Some(ref new_rw) if new_rw.lines().count() >= line_count => { + last_subexpr_str = Some(rw); + self.fits_single_line = could_fit_single_line && all_in_one_line; + } + new_rw @ Some(..) => { + last_subexpr_str = new_rw; + } + _ => { + last_subexpr_str = Some(rw); + self.fits_single_line = could_fit_single_line && all_in_one_line; + } } } } } - } - } + } - last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); - rewrites.push(last_subexpr_str?); - - let connector = if fits_single_line && all_in_one_line { - // Yay, we can put everything on one line. - Cow::from("") - } else { - // Use new lines. - if *context.force_one_line_chain.borrow() { - return None; - } - child_shape.indent.to_string_with_newline(context.config) - }; + let last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); + self.rewrites.push(format!("{}{}", last_subexpr_str?, "?".repeat(last.tries))); + Some(()) + } - let result = format!("{}{}", - join_rewrites_vis(&rewrites, &connector), - "?".repeat(last.tries), - ); - wrap_str(result, context.config.max_width(), shape) -} + fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + let connector = if self.fits_single_line { + // Yay, we can put everything on one line. + Cow::from("") + } else { + // Use new lines. + if *context.force_one_line_chain.borrow() { + return None; + } + child_shape.indent.to_string_with_newline(context.config) + }; -fn join_rewrites(rewrites: &[String], is_block_like: &[bool], connector: &str) -> String { - let mut rewrite_iter = rewrites.iter(); - let mut result = rewrite_iter.next().unwrap().clone(); + let mut rewrite_iter = self.rewrites.iter(); + let mut result = rewrite_iter.next().unwrap().clone(); - for (rewrite, prev_is_block_like) in rewrite_iter.zip(is_block_like.iter()) { - if rewrite != "?" && !prev_is_block_like { - result.push_str(connector); + for rewrite in rewrite_iter { + result.push_str(&connector); + result.push_str(&rewrite); } - result.push_str(&rewrite); - } - result + Some(result) + } } -fn join_rewrites_vis(rewrites: &[String], connector: &str) -> String { - let mut rewrite_iter = rewrites.iter(); - let mut result = rewrite_iter.next().unwrap().clone(); +fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { + let mut formatter = ChainFormatterVisual::new(&chain); + + formatter.format_root(&chain.parent, context, shape)?; - for rewrite in rewrite_iter { - if rewrite != "?" { - result.push_str(connector); - } - result.push_str(&rewrite); + if formatter.children.is_empty() { + assert_eq!(formatter.rewrites.len(), 1); + return Some(formatter.rewrites.pop().unwrap()); } - result + let child_shape = shape.visual_indent(0).with_max_width(context.config); + + formatter.format_children(context, child_shape)?; + formatter.format_last_child(context, shape, child_shape)?; + + let result = formatter.join_rewrites(context, child_shape)?; + wrap_str(result, context.config.max_width(), shape) } // States whether an expression's last line exclusively consists of closing @@ -513,45 +590,6 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool } } -// Returns a Vec of the prefixes of the chain. -// E.g., for input `a.b.c` we return [`a.b.c`, `a.b`, 'a'] -fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> Vec { - let mut subexpr_list = vec![expr.clone()]; - - while let Some(subexpr) = pop_expr_chain(subexpr_list.last().unwrap(), context) { - subexpr_list.push(subexpr.clone()); - } - - subexpr_list -} - -// Returns the expression's subexpression, if it exists. When the subexpr -// is a try! macro, we'll convert it to shorthand when the option is set. -fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { - match expr.node { - ast::ExprKind::MethodCall(_, ref expressions) => { - Some(convert_try(&expressions[0], context)) - } - ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) => { - Some(convert_try(subexpr, context)) - } - _ => None, - } -} - -fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { - match expr.node { - ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { - if let Some(subexpr) = convert_try_mac(mac, context) { - subexpr - } else { - expr.clone() - } - } - _ => expr.clone(), - } -} - // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite // `.c`. fn rewrite_chain_subexpr( @@ -600,14 +638,6 @@ fn is_tup_field_access(expr: &ast::Expr) -> bool { } } -// Determines if we can continue formatting a given expression on the same line. -fn is_continuable(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Path(..) => true, - _ => false, - } -} - fn rewrite_method_call( method_name: ast::Ident, types: &[ast::GenericArg], -- cgit 1.4.1-3-g733a5 From f55cadb65aacded4593312e56709fff3388e5f13 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 13:39:35 +1200 Subject: chains: refactor formatting of chain items --- src/chains.rs | 205 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 102 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 692d1c946fc..5e2c3e051f6 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -85,8 +85,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // If this is just an expression with some `?`s, then format it trivially and // return early. if chain.children.is_empty() { - let rewrite = chain.parent.expr.rewrite(context, shape.sub_width(chain.parent.tries)?)?; - return Some(format!("{}{}", rewrite, "?".repeat(chain.parent.tries))); + return chain.parent.rewrite(context, shape); } match context.config.indent_style() { @@ -102,6 +101,89 @@ struct ChainItem { tries: usize, } +impl Rewrite for ChainItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let rewrite = self.expr.rewrite(context, shape.sub_width(self.tries)?)?; + Some(format!("{}{}", rewrite, "?".repeat(self.tries))) + } +} + +impl ChainItem { + // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite + // `.c` and any trailing `?`s. + fn rewrite_postfix( + &self, + context: &RewriteContext, + shape: Shape, + ) -> Option { + let shape = shape.sub_width(self.tries)?; + let mut rewrite = match self.expr.node { + ast::ExprKind::MethodCall(ref segment, ref expressions) => { + let types = match segment.args { + Some(ref params) => match **params { + ast::GenericArgs::AngleBracketed(ref data) => &data.args[..], + _ => &[], + }, + _ => &[], + }; + Self::rewrite_method_call(segment.ident, types, expressions, self.expr.span, context, shape)? + } + ast::ExprKind::Field(ref nested, ref field) => { + let space = if Self::is_tup_field_access(&self.expr) && Self::is_tup_field_access(nested) { + " " + } else { + "" + }; + let result = format!("{}.{}", space, field.name); + if result.len() <= shape.width { + result + } else { + return None; + } + } + _ => unreachable!(), + }; + rewrite.push_str(&"?".repeat(self.tries)); + Some(rewrite) + } + + fn is_tup_field_access(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Field(_, ref field) => { + field.name.to_string().chars().all(|c| c.is_digit(10)) + } + _ => false, + } + } + + fn rewrite_method_call( + method_name: ast::Ident, + types: &[ast::GenericArg], + args: &[ptr::P], + span: Span, + context: &RewriteContext, + shape: Shape, + ) -> Option { + let (lo, type_str) = if types.is_empty() { + (args[0].span.hi(), String::new()) + } else { + let type_list = types + .iter() + .map(|ty| ty.rewrite(context, shape)) + .collect::>>()?; + + let type_str = format!("::<{}>", type_list.join(", ")); + + (types.last().unwrap().span().hi(), type_str) + }; + + let callee_str = format!(".{}{}", method_name, type_str); + let span = mk_sp(lo, span.hi()); + + rewrite_call(context, &callee_str, &args[1..], span, shape) + } +} + #[derive(Debug)] struct Chain { parent: ChainItem, @@ -209,9 +291,7 @@ impl <'a> ChainFormatterBlock<'a> { // ``` // If `bar` were not part of the root, then baz would be orphaned and 'float'. fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { - let mut root_rewrite: String = parent.expr - .rewrite(context, shape) - .map(|parent_rw| parent_rw + &"?".repeat(parent.tries))?; + let mut root_rewrite: String = parent.rewrite(context, shape)?; self.root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); @@ -219,11 +299,8 @@ impl <'a> ChainFormatterBlock<'a> { while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { let item = &self.children[0]; let shape = shape.offset_left(root_rewrite.len())?; - match rewrite_chain_subexpr(&item.expr, context, shape) { - Some(rewrite) => { - root_rewrite.push_str(&rewrite); - root_rewrite.push_str(&"?".repeat(item.tries)); - } + match &item.rewrite_postfix(context, shape) { + Some(rewrite) => root_rewrite.push_str(rewrite), None => break, } @@ -248,10 +325,10 @@ impl <'a> ChainFormatterBlock<'a> { fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { self.is_block_like.push(self.root_ends_with_block); - for item in &self.children[..self.children.len()] { - let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; + for item in &self.children[..self.children.len() - 1] { + let rewrite = item.rewrite_postfix(context, child_shape)?; self.is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); - self.rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); + self.rewrites.push(rewrite); } Some(()) } @@ -315,7 +392,7 @@ impl <'a> ChainFormatterBlock<'a> { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. if let Some(shape) = last_shape.offset_left(almost_total) { - if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { + if let Some(rw) = last.rewrite_postfix(context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -328,7 +405,7 @@ impl <'a> ChainFormatterBlock<'a> { // We could not know whether overflowing is better than using vertical layout, // just by looking at the overflowed rewrite. Now we rewrite the last child // on its own line, and compare two rewrites to choose which is better. - match rewrite_chain_subexpr(&last.expr, context, last_shape) { + match last.rewrite_postfix(context, last_shape) { Some(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); } @@ -349,8 +426,8 @@ impl <'a> ChainFormatterBlock<'a> { } } - last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); - self.rewrites.push(format!("{}{}", last_subexpr_str?, "?".repeat(last.tries))); + last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite_postfix(context, last_shape)); + self.rewrites.push(last_subexpr_str?); Some(()) } @@ -424,17 +501,14 @@ impl<'a> ChainFormatterVisual<'a> { } else { shape }; - let mut root_rewrite = parent.expr - .rewrite(context, parent_shape) - .map(|parent_rw| parent_rw + &"?".repeat(parent.tries))?; + let mut root_rewrite = parent.rewrite(context, parent_shape)?; if !root_rewrite.contains('\n') && Self::is_continuable(&parent.expr) { let item = &self.children[0]; let overhead = last_line_width(&root_rewrite); let shape = parent_shape.offset_left(overhead)?; - let rewrite = rewrite_chain_subexpr(&item.expr, context, shape)?; + let rewrite = item.rewrite_postfix(context, shape)?; root_rewrite.push_str(&rewrite); - root_rewrite.push_str(&"?".repeat(item.tries)); self.children = &self.children[1..]; } @@ -453,8 +527,8 @@ impl<'a> ChainFormatterVisual<'a> { fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { for item in &self.children[..self.children.len() - 1] { - let rewrite = rewrite_chain_subexpr(&item.expr, context, child_shape)?; - self.rewrites.push(format!("{}{}", rewrite, "?".repeat(item.tries))); + let rewrite = item.rewrite_postfix(context, child_shape)?; + self.rewrites.push(rewrite); } Some(()) } @@ -479,7 +553,7 @@ impl<'a> ChainFormatterVisual<'a> { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. if let Some(shape) = shape.offset_left(almost_total) { - if let Some(rw) = rewrite_chain_subexpr(&last.expr, context, shape) { + if let Some(rw) = last.rewrite_postfix(context, shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -492,7 +566,7 @@ impl<'a> ChainFormatterVisual<'a> { // We could not know whether overflowing is better than using vertical layout, // just by looking at the overflowed rewrite. Now we rewrite the last child // on its own line, and compare two rewrites to choose which is better. - match rewrite_chain_subexpr(&last.expr, context, last_shape) { + match last.rewrite_postfix(context, last_shape) { Some(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); } @@ -513,8 +587,8 @@ impl<'a> ChainFormatterVisual<'a> { } } - let last_subexpr_str = last_subexpr_str.or_else(|| rewrite_chain_subexpr(&last.expr, context, last_shape)); - self.rewrites.push(format!("{}{}", last_subexpr_str?, "?".repeat(last.tries))); + let last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite_postfix(context, last_shape)); + self.rewrites.push(last_subexpr_str?); Some(()) } @@ -589,78 +663,3 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool _ => false, } } - -// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite -// `.c`. -fn rewrite_chain_subexpr( - expr: &ast::Expr, - context: &RewriteContext, - shape: Shape, -) -> Option { - let rewrite_element = |expr_str: String| { - if expr_str.len() <= shape.width { - Some(expr_str) - } else { - None - } - }; - - match expr.node { - ast::ExprKind::MethodCall(ref segment, ref expressions) => { - let types = match segment.args { - Some(ref params) => match **params { - ast::GenericArgs::AngleBracketed(ref data) => &data.args[..], - _ => &[], - }, - _ => &[], - }; - rewrite_method_call(segment.ident, types, expressions, expr.span, context, shape) - } - ast::ExprKind::Field(ref nested, ref field) => { - let space = if is_tup_field_access(expr) && is_tup_field_access(nested) { - " " - } else { - "" - }; - rewrite_element(format!("{}.{}", space, field.name)) - } - ast::ExprKind::Try(_) => rewrite_element(String::from("?")), - _ => unreachable!(), - } -} - -fn is_tup_field_access(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Field(_, ref field) => { - field.name.to_string().chars().all(|c| c.is_digit(10)) - } - _ => false, - } -} - -fn rewrite_method_call( - method_name: ast::Ident, - types: &[ast::GenericArg], - args: &[ptr::P], - span: Span, - context: &RewriteContext, - shape: Shape, -) -> Option { - let (lo, type_str) = if types.is_empty() { - (args[0].span.hi(), String::new()) - } else { - let type_list = types - .iter() - .map(|ty| ty.rewrite(context, shape)) - .collect::>>()?; - - let type_str = format!("::<{}>", type_list.join(", ")); - - (types.last().unwrap().span().hi(), type_str) - }; - - let callee_str = format!(".{}{}", method_name, type_str); - let span = mk_sp(lo, span.hi()); - - rewrite_call(context, &callee_str, &args[1..], span, shape) -} -- cgit 1.4.1-3-g733a5 From 467b095d48ebf5f5e057e1a2b4c1c25aa0375ea1 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 14:50:42 +1200 Subject: chains: share code between block and visual formatters --- src/chains.rs | 338 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 154 insertions(+), 184 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 5e2c3e051f6..13436106ccb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -75,6 +75,7 @@ use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, wrap use std::borrow::Cow; use std::cmp::min; +use std::iter; use syntax::codemap::Span; use syntax::{ast, ptr}; @@ -88,10 +89,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - return chain.parent.rewrite(context, shape); } - match context.config.indent_style() { - IndentStyle::Block => rewrite_chain_block(chain, context, shape), - IndentStyle::Visual => rewrite_chain_visual(chain, context, shape), - } + chain.rewrite(context, shape) } // An expression plus trailing `?`s to be formatted together. @@ -262,26 +260,36 @@ impl Chain { } } -// TODO comments -struct ChainFormatterBlock<'a> { - children: &'a[ChainItem], - rewrites: Vec, - root_ends_with_block: bool, - is_block_like: Vec, - fits_single_line: bool, -} +impl Rewrite for Chain { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + debug!("rewrite chain {:?} {:?}", self, shape); -impl <'a> ChainFormatterBlock<'a> { - fn new(chain: &'a Chain) -> ChainFormatterBlock<'a> { - ChainFormatterBlock { - children: &chain.children, - root_ends_with_block: false, - rewrites: Vec::with_capacity(chain.children.len() + 1), - is_block_like: Vec::with_capacity(chain.children.len() + 1), - fits_single_line: false, + let mut formatter = match context.config.indent_style() { + IndentStyle::Block => Box::new(ChainFormatterBlock::new(self)) as Box, + IndentStyle::Visual => Box::new(ChainFormatterVisual::new(self)) as Box, + }; + + formatter.format_root(&self.parent, context, shape)?; + if let result @ Some(_) = formatter.pure_root() { + return result; } + + // Decide how to layout the rest of the chain. + let child_shape = formatter.child_shape(context, shape); + + formatter.format_children(context, child_shape)?; + formatter.format_last_child(context, shape, child_shape)?; + + let result = formatter.join_rewrites(context, child_shape)?; + wrap_str(result, context.config.max_width(), shape) } +} +// There are a few types for formatting chains. This is because there is a lot +// in common between formatting with block vs visual indent, but they are +// different enough that branching on the indent all over the place gets ugly. +// Anything that can format a chain is a ChainFormatter. +trait ChainFormatter { // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. // Root is the parent plus any other chain items placed on the first line to // avoid an orphan. E.g., @@ -290,47 +298,43 @@ impl <'a> ChainFormatterBlock<'a> { // .baz() // ``` // If `bar` were not part of the root, then baz would be orphaned and 'float'. - fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { - let mut root_rewrite: String = parent.rewrite(context, shape)?; - - self.root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); - let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); - - while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { - let item = &self.children[0]; - let shape = shape.offset_left(root_rewrite.len())?; - match &item.rewrite_postfix(context, shape) { - Some(rewrite) => root_rewrite.push_str(rewrite), - None => break, - } + fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()>; + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape; + fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()>; + fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()>; + fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option; + // Returns `Some` if the chain is only a root, None otherwise. + fn pure_root(&mut self) -> Option; +} - self.root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); +// Data and behaviour that is shared by both chain formatters. The concrete +// formatters can delegate much behaviour to `ChainFormatterShared`. +struct ChainFormatterShared<'a> { + // The current working set of child items. + children: &'a[ChainItem], + // The current rewrites of items (includes trailing `?`s, but not any way to + // connect the rewrites together). + rewrites: Vec, + // Whether the chain can fit on one line. + fits_single_line: bool, +} - self.children = &self.children[1..]; - if self.children.is_empty() { - break; - } +impl <'a> ChainFormatterShared<'a> { + fn new(chain: &'a Chain) -> ChainFormatterShared<'a> { + ChainFormatterShared { + children: &chain.children, + rewrites: Vec::with_capacity(chain.children.len() + 1), + fits_single_line: false, } - self.rewrites.push(root_rewrite); - Some(()) } - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape { - if self.root_ends_with_block { - shape + fn pure_root(&mut self) -> Option { + if self.children.is_empty() { + assert_eq!(self.rewrites.len(), 1); + Some(self.rewrites.pop().unwrap()) } else { - shape.block_indent(context.config.tab_spaces()) - }.with_max_width(context.config) - } - - fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { - self.is_block_like.push(self.root_ends_with_block); - for item in &self.children[..self.children.len() - 1] { - let rewrite = item.rewrite_postfix(context, child_shape)?; - self.is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); - self.rewrites.push(rewrite); + None } - Some(()) } // Rewrite the last child. The last child of a chain requires special treatment. We need to @@ -365,9 +369,10 @@ impl <'a> ChainFormatterBlock<'a> { // result // }) // ``` - fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { + fn format_last_child(&mut self, may_extend: bool, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { let last = &self.children[self.children.len() - 1]; - let extendable = last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); + let extendable = may_extend && last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); + // Total of all items excluding the last. let almost_total = if extendable { last_line_width(&self.rewrites[self.rewrites.len() - 1]) @@ -431,8 +436,7 @@ impl <'a> ChainFormatterBlock<'a> { Some(()) } - - fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape, block_like_iter: impl Iterator) -> Option { let connector = if self.fits_single_line { // Yay, we can put everything on one line. Cow::from("") @@ -447,8 +451,8 @@ impl <'a> ChainFormatterBlock<'a> { let mut rewrite_iter = self.rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); - for (rewrite, prev_is_block_like) in rewrite_iter.zip(self.is_block_like.iter()) { - if rewrite != "?" && !prev_is_block_like { + for (rewrite, prev_is_block_like) in rewrite_iter.zip(block_like_iter) { + if !prev_is_block_like { result.push_str(&connector); } result.push_str(&rewrite); @@ -458,43 +462,102 @@ impl <'a> ChainFormatterBlock<'a> { } } -fn rewrite_chain_block(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - debug!("rewrite_chain_block {:?} {:?}", chain, shape); +// Formats a chain using block indent. +struct ChainFormatterBlock<'a> { + shared: ChainFormatterShared<'a>, + // For each rewrite, whether the corresponding item is block-like. + is_block_like: Vec, +} + +impl <'a> ChainFormatterBlock<'a> { + fn new(chain: &'a Chain) -> ChainFormatterBlock<'a> { + ChainFormatterBlock { + shared: ChainFormatterShared::new(chain), + is_block_like: Vec::with_capacity(chain.children.len() + 1), + } + } +} - let mut formatter = ChainFormatterBlock::new(&chain); +impl <'a> ChainFormatter for ChainFormatterBlock<'a> { + fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { + let mut root_rewrite: String = parent.rewrite(context, shape)?; - formatter.format_root(&chain.parent, context, shape)?; - if formatter.children.is_empty() { - assert_eq!(formatter.rewrites.len(), 1); - return Some(formatter.rewrites.pop().unwrap()); + let mut root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); + let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); + + while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { + let item = &self.shared.children[0]; + let shape = shape.offset_left(root_rewrite.len())?; + match &item.rewrite_postfix(context, shape) { + Some(rewrite) => root_rewrite.push_str(rewrite), + None => break, + } + + root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); + + self.shared.children = &self.shared.children[1..]; + if self.shared.children.is_empty() { + break; + } + } + self.is_block_like.push(root_ends_with_block); + self.shared.rewrites.push(root_rewrite); + Some(()) + } + + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape { + if self.is_block_like[0] { + shape + } else { + shape.block_indent(context.config.tab_spaces()) + }.with_max_width(context.config) + } + + fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { + for item in &self.shared.children[..self.shared.children.len() - 1] { + let rewrite = item.rewrite_postfix(context, child_shape)?; + self.is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); + self.shared.rewrites.push(rewrite); + } + Some(()) } - // Decide how to layout the rest of the chain. - let child_shape = formatter.child_shape(context, shape); - formatter.format_children(context, child_shape)?; + fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { + self.shared.format_last_child(true, context, shape, child_shape) + } - formatter.format_last_child(context, shape, child_shape)?; + fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + self.shared.join_rewrites(context, child_shape, self.is_block_like.iter().cloned()) + } - let result = formatter.join_rewrites(context, child_shape)?; - Some(result) + fn pure_root(&mut self) -> Option { + self.shared.pure_root() + } } +// Format a chain using visual indent. struct ChainFormatterVisual<'a> { - children: &'a[ChainItem], - rewrites: Vec, - fits_single_line: bool, + shared: ChainFormatterShared<'a>, } impl<'a> ChainFormatterVisual<'a> { fn new(chain: &'a Chain) -> ChainFormatterVisual<'a> { ChainFormatterVisual { - children: &chain.children, - rewrites: Vec::with_capacity(chain.children.len() + 1), - fits_single_line: false, + shared: ChainFormatterShared::new(chain), } } +} +impl <'a> ChainFormatter for ChainFormatterVisual<'a> { fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { + // Determines if we can continue formatting a given expression on the same line. + fn is_continuable(expr: &ast::Expr) -> bool { + match expr.node { + ast::ExprKind::Path(..) => true, + _ => false, + } + } + // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. let parent_shape = if is_block_expr(context, &parent.expr, "\n") { shape.visual_indent(0) @@ -503,136 +566,43 @@ impl<'a> ChainFormatterVisual<'a> { }; let mut root_rewrite = parent.rewrite(context, parent_shape)?; - if !root_rewrite.contains('\n') && Self::is_continuable(&parent.expr) { - let item = &self.children[0]; + if !root_rewrite.contains('\n') && is_continuable(&parent.expr) { + let item = &self.shared.children[0]; let overhead = last_line_width(&root_rewrite); let shape = parent_shape.offset_left(overhead)?; let rewrite = item.rewrite_postfix(context, shape)?; root_rewrite.push_str(&rewrite); - self.children = &self.children[1..]; + self.shared.children = &self.shared.children[1..]; } - self.rewrites.push(root_rewrite); + self.shared.rewrites.push(root_rewrite); Some(()) } - // Determines if we can continue formatting a given expression on the same line. - fn is_continuable(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Path(..) => true, - _ => false, - } + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape { + shape.visual_indent(0).with_max_width(context.config) } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { - for item in &self.children[..self.children.len() - 1] { + for item in &self.shared.children[..self.shared.children.len() - 1] { let rewrite = item.rewrite_postfix(context, child_shape)?; - self.rewrites.push(rewrite); + self.shared.rewrites.push(rewrite); } Some(()) } fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { - let last = &self.children[self.children.len() - 1]; - - // Total of all items excluding the last. - let almost_total = self.rewrites.iter().fold(0, |a, b| a + b.len()) + last.tries; - let one_line_budget = if self.rewrites.len() == 1 { - shape.width - } else { - min(shape.width, context.config.width_heuristics().chain_width) - }; - let all_in_one_line = self.rewrites.iter().all(|s| !s.contains('\n')) - && almost_total < one_line_budget; - let last_shape = child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; - - - let mut last_subexpr_str = None; - if all_in_one_line { - // First we try to 'overflow' the last child and see if it looks better than using - // vertical layout. - if let Some(shape) = shape.offset_left(almost_total) { - if let Some(rw) = last.rewrite_postfix(context, shape) { - // We allow overflowing here only if both of the following conditions match: - // 1. The entire chain fits in a single line except the last child. - // 2. `last_child_str.lines().count() >= 5`. - let line_count = rw.lines().count(); - let could_fit_single_line = almost_total + first_line_width(&rw) <= one_line_budget; - if could_fit_single_line && line_count >= 5 { - last_subexpr_str = Some(rw); - self.fits_single_line = all_in_one_line; - } else { - // We could not know whether overflowing is better than using vertical layout, - // just by looking at the overflowed rewrite. Now we rewrite the last child - // on its own line, and compare two rewrites to choose which is better. - match last.rewrite_postfix(context, last_shape) { - Some(ref new_rw) if !could_fit_single_line => { - last_subexpr_str = Some(new_rw.clone()); - } - Some(ref new_rw) if new_rw.lines().count() >= line_count => { - last_subexpr_str = Some(rw); - self.fits_single_line = could_fit_single_line && all_in_one_line; - } - new_rw @ Some(..) => { - last_subexpr_str = new_rw; - } - _ => { - last_subexpr_str = Some(rw); - self.fits_single_line = could_fit_single_line && all_in_one_line; - } - } - } - } - } - } - - let last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite_postfix(context, last_shape)); - self.rewrites.push(last_subexpr_str?); - Some(()) + self.shared.format_last_child(false, context, shape, child_shape) } fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { - let connector = if self.fits_single_line { - // Yay, we can put everything on one line. - Cow::from("") - } else { - // Use new lines. - if *context.force_one_line_chain.borrow() { - return None; - } - child_shape.indent.to_string_with_newline(context.config) - }; - - let mut rewrite_iter = self.rewrites.iter(); - let mut result = rewrite_iter.next().unwrap().clone(); - - for rewrite in rewrite_iter { - result.push_str(&connector); - result.push_str(&rewrite); - } - - Some(result) + self.shared.join_rewrites(context, child_shape, iter::repeat(false)) } -} -fn rewrite_chain_visual(chain: Chain, context: &RewriteContext, shape: Shape) -> Option { - let mut formatter = ChainFormatterVisual::new(&chain); - - formatter.format_root(&chain.parent, context, shape)?; - - if formatter.children.is_empty() { - assert_eq!(formatter.rewrites.len(), 1); - return Some(formatter.rewrites.pop().unwrap()); + fn pure_root(&mut self) -> Option { + self.shared.pure_root() } - - let child_shape = shape.visual_indent(0).with_max_width(context.config); - - formatter.format_children(context, child_shape)?; - formatter.format_last_child(context, shape, child_shape)?; - - let result = formatter.join_rewrites(context, child_shape)?; - wrap_str(result, context.config.max_width(), shape) } // States whether an expression's last line exclusively consists of closing -- cgit 1.4.1-3-g733a5 From 5bc27593f44a7c2108ca1a69eba2d34b3db90935 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 14:56:26 +1200 Subject: chains: minor fixups * remove unnecessary clone * comment formatting * fix bug with `?` collection * respect the heuristic if the root is more than just the parent --- src/chains.rs | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 13436106ccb..81be8d54128 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -81,8 +81,9 @@ use syntax::codemap::Span; use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { - debug!("rewrite_chain {:?}", shape); let chain = Chain::from_ast(expr, context); + debug!("rewrite_chain {:?} {:?}", chain, shape); + // If this is just an expression with some `?`s, then format it trivially and // return early. if chain.children.is_empty() { @@ -95,6 +96,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // An expression plus trailing `?`s to be formatted together. #[derive(Debug)] struct ChainItem { + // FIXME: we can't use a reference here because to convert `try!` to `?` we + // synthesise the AST node. However, I think we could use `Cow` and that + // would remove a lot of cloning. expr: ast::Expr, tries: usize, } @@ -185,28 +189,22 @@ impl ChainItem { #[derive(Debug)] struct Chain { parent: ChainItem, - // TODO do we need to clone the exprs? children: Vec, } impl Chain { fn from_ast(expr: &ast::Expr, context: &RewriteContext) -> Chain { - let mut subexpr_list = Self::make_subexpr_list(expr, context); + let subexpr_list = Self::make_subexpr_list(expr, context); // Un-parse the expression tree into ChainItems let mut children = vec![]; let mut sub_tries = 0; - loop { - if subexpr_list.is_empty() { - break; - } - - let subexpr = subexpr_list.pop().unwrap(); + for subexpr in subexpr_list { match subexpr.node { ast::ExprKind::Try(_) => sub_tries += 1, _ => { children.push(ChainItem { - expr: subexpr.clone(), + expr: subexpr, tries: sub_tries, }); sub_tries = 0; @@ -215,7 +213,7 @@ impl Chain { } Chain { - parent: children.remove(0), + parent: children.pop().unwrap(), children, } } @@ -317,6 +315,9 @@ struct ChainFormatterShared<'a> { rewrites: Vec, // Whether the chain can fit on one line. fits_single_line: bool, + // The number of children in the chain. This is not equal to `self.children.len()` + // because `self.children` will change size as we process the chain. + child_count: usize, } impl <'a> ChainFormatterShared<'a> { @@ -325,6 +326,7 @@ impl <'a> ChainFormatterShared<'a> { children: &chain.children, rewrites: Vec::with_capacity(chain.children.len() + 1), fits_single_line: false, + child_count: chain.children.len(), } } @@ -370,7 +372,7 @@ impl <'a> ChainFormatterShared<'a> { // }) // ``` fn format_last_child(&mut self, may_extend: bool, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { - let last = &self.children[self.children.len() - 1]; + let last = &self.children[0]; let extendable = may_extend && last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); // Total of all items excluding the last. @@ -379,7 +381,7 @@ impl <'a> ChainFormatterShared<'a> { } else { self.rewrites.iter().fold(0, |a, b| a + b.len()) } + last.tries; - let one_line_budget = if self.rewrites.len() == 1 { + let one_line_budget = if self.child_count == 1 { shape.width } else { min(shape.width, context.config.width_heuristics().chain_width) @@ -407,9 +409,10 @@ impl <'a> ChainFormatterShared<'a> { last_subexpr_str = Some(rw); self.fits_single_line = all_in_one_line; } else { - // We could not know whether overflowing is better than using vertical layout, - // just by looking at the overflowed rewrite. Now we rewrite the last child - // on its own line, and compare two rewrites to choose which is better. + // We could not know whether overflowing is better than using vertical + // layout, just by looking at the overflowed rewrite. Now we rewrite the + // last child on its own line, and compare two rewrites to choose which is + // better. match last.rewrite_postfix(context, last_shape) { Some(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); @@ -486,7 +489,7 @@ impl <'a> ChainFormatter for ChainFormatterBlock<'a> { let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { - let item = &self.shared.children[0]; + let item = &self.shared.children[self.shared.children.len() - 1]; let shape = shape.offset_left(root_rewrite.len())?; match &item.rewrite_postfix(context, shape) { Some(rewrite) => root_rewrite.push_str(rewrite), @@ -495,7 +498,7 @@ impl <'a> ChainFormatter for ChainFormatterBlock<'a> { root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); - self.shared.children = &self.shared.children[1..]; + self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; if self.shared.children.is_empty() { break; } @@ -514,7 +517,7 @@ impl <'a> ChainFormatter for ChainFormatterBlock<'a> { } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { - for item in &self.shared.children[..self.shared.children.len() - 1] { + for item in self.shared.children[1..].iter().rev() { let rewrite = item.rewrite_postfix(context, child_shape)?; self.is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); self.shared.rewrites.push(rewrite); @@ -567,13 +570,13 @@ impl <'a> ChainFormatter for ChainFormatterVisual<'a> { let mut root_rewrite = parent.rewrite(context, parent_shape)?; if !root_rewrite.contains('\n') && is_continuable(&parent.expr) { - let item = &self.shared.children[0]; + let item = &self.shared.children[self.shared.children.len() - 1]; let overhead = last_line_width(&root_rewrite); let shape = parent_shape.offset_left(overhead)?; let rewrite = item.rewrite_postfix(context, shape)?; root_rewrite.push_str(&rewrite); - self.shared.children = &self.shared.children[1..]; + self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; } self.shared.rewrites.push(root_rewrite); @@ -585,7 +588,7 @@ impl <'a> ChainFormatter for ChainFormatterVisual<'a> { } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { - for item in &self.shared.children[..self.shared.children.len() - 1] { + for item in self.shared.children[1..].iter().rev() { let rewrite = item.rewrite_postfix(context, child_shape)?; self.shared.rewrites.push(rewrite); } -- cgit 1.4.1-3-g733a5 From f0fe9c3c4acb4eafba5a552a2823e6997e75a3f4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 21:01:40 +1200 Subject: chains: prefer to use the next line for an expression, if using the same line would introduce an open block or similar This problem came to light due to the chains changes, but effects other code too. It only happens rarely, e.g., before this fix: ``` match foo { MacroArgKind::Delimited(ref delim_tok, ref args) => rewrite_delimited_inner( delim_tok, args, ).map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs)), }; ``` after: ``` match foo { MacroArgKind::Delimited(ref delim_tok, ref args) => { rewrite_delimited_inner(delim_tok, args) .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs)) } } ``` --- src/chains.rs | 5 +++-- src/expr.rs | 9 ++++++--- src/utils.rs | 7 +++++++ 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 81be8d54128..d7126b2f5e7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -398,8 +398,8 @@ impl <'a> ChainFormatterShared<'a> { if all_in_one_line || extendable { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. - if let Some(shape) = last_shape.offset_left(almost_total) { - if let Some(rw) = last.rewrite_postfix(context, shape) { + if let Some(one_line_shape) = last_shape.offset_left(almost_total) { + if let Some(rw) = last.rewrite_postfix(context, one_line_shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -413,6 +413,7 @@ impl <'a> ChainFormatterShared<'a> { // layout, just by looking at the overflowed rewrite. Now we rewrite the // last child on its own line, and compare two rewrites to choose which is // better. + let last_shape = child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; match last.rewrite_postfix(context, last_shape) { Some(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); diff --git a/src/expr.rs b/src/expr.rs index 6e1af266e9b..8aa5d9bd286 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -39,9 +39,9 @@ use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{ - colon_spaces, contains_skip, count_newlines, first_line_width, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, - semicolon_for_stmt, wrap_str, + colon_spaces, contains_skip, count_newlines, first_line_ends_with, first_line_width, + inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, + ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str, }; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -1953,6 +1953,9 @@ pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTac rhs_tactics == RhsTactics::ForceNextLineWithoutIndent || !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 + || first_line_ends_with(orig_rhs, '(') && !first_line_ends_with(next_line_rhs, '(') + || first_line_ends_with(orig_rhs, '{') && !first_line_ends_with(next_line_rhs, '{') + || first_line_ends_with(orig_rhs, '[') && !first_line_ends_with(next_line_rhs, '[') } fn rewrite_expr_addrof( diff --git a/src/utils.rs b/src/utils.rs index f1b0582b120..b8474792cd3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -382,6 +382,7 @@ pub fn colon_spaces(before: bool, after: bool) -> &'static str { } } +#[inline] pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { match e.node { ast::ExprKind::Call(ref e, _) @@ -398,6 +399,12 @@ pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { } } +#[inline] pub fn starts_with_newline(s: &str) -> bool { s.starts_with('\n') || s.starts_with("\r\n") } + +#[inline] +pub fn first_line_ends_with(s: &str, c: char) -> bool { + s.lines().next().map_or(false, |l| l.ends_with(c)) +} -- cgit 1.4.1-3-g733a5 From 481e85cc5847b02458288cc068816625a21dcfad Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 21:35:10 +1200 Subject: formatting --- src/bin/main.rs | 3 +- src/cargo-fmt/main.rs | 3 +- src/chains.rs | 123 ++++++++++++++++++++++++++++++++++-------------- src/closures.rs | 10 ++-- src/comment.rs | 12 ++--- src/config/options.rs | 3 +- src/expr.rs | 3 +- src/git-rustfmt/main.rs | 3 +- src/imports.rs | 3 +- src/items.rs | 22 ++++----- src/macros.rs | 38 +++++++-------- src/reorder.rs | 19 ++++---- src/rustfmt_diff.rs | 16 ++++--- src/test/mod.rs | 9 ++-- src/types.rs | 6 +-- src/vertical.rs | 6 +-- 16 files changed, 154 insertions(+), 125 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 5b6398f028e..7767ea84764 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -422,8 +422,7 @@ fn determine_operation(matches: &Matches) -> Result { // we will do comparison later, so here tries to canonicalize first // to get the expected behavior. p.canonicalize().unwrap_or(p) - }) - .collect(); + }).collect(); Ok(Operation::Format { files, diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 3246908e20c..2d8234ef41e 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -163,8 +163,7 @@ fn format_crate( if verbosity == Verbosity::Verbose { println!("[{}] {:?}", t.kind, t.path) } - }) - .map(|t| t.path) + }).map(|t| t.path) .collect(); run_rustfmt(&files, &rustfmt_args, verbosity) diff --git a/src/chains.rs b/src/chains.rs index d7126b2f5e7..439c0d188a2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -113,11 +113,7 @@ impl Rewrite for ChainItem { impl ChainItem { // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite // `.c` and any trailing `?`s. - fn rewrite_postfix( - &self, - context: &RewriteContext, - shape: Shape, - ) -> Option { + fn rewrite_postfix(&self, context: &RewriteContext, shape: Shape) -> Option { let shape = shape.sub_width(self.tries)?; let mut rewrite = match self.expr.node { ast::ExprKind::MethodCall(ref segment, ref expressions) => { @@ -128,14 +124,22 @@ impl ChainItem { }, _ => &[], }; - Self::rewrite_method_call(segment.ident, types, expressions, self.expr.span, context, shape)? + Self::rewrite_method_call( + segment.ident, + types, + expressions, + self.expr.span, + context, + shape, + )? } ast::ExprKind::Field(ref nested, ref field) => { - let space = if Self::is_tup_field_access(&self.expr) && Self::is_tup_field_access(nested) { - " " - } else { - "" - }; + let space = + if Self::is_tup_field_access(&self.expr) && Self::is_tup_field_access(nested) { + " " + } else { + "" + }; let result = format!("{}.{}", space, field.name); if result.len() <= shape.width { result @@ -296,10 +300,20 @@ trait ChainFormatter { // .baz() // ``` // If `bar` were not part of the root, then baz would be orphaned and 'float'. - fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()>; + fn format_root( + &mut self, + parent: &ChainItem, + context: &RewriteContext, + shape: Shape, + ) -> Option<()>; fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape; fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()>; - fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()>; + fn format_last_child( + &mut self, + context: &RewriteContext, + shape: Shape, + child_shape: Shape, + ) -> Option<()>; fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option; // Returns `Some` if the chain is only a root, None otherwise. fn pure_root(&mut self) -> Option; @@ -309,7 +323,7 @@ trait ChainFormatter { // formatters can delegate much behaviour to `ChainFormatterShared`. struct ChainFormatterShared<'a> { // The current working set of child items. - children: &'a[ChainItem], + children: &'a [ChainItem], // The current rewrites of items (includes trailing `?`s, but not any way to // connect the rewrites together). rewrites: Vec, @@ -320,7 +334,7 @@ struct ChainFormatterShared<'a> { child_count: usize, } -impl <'a> ChainFormatterShared<'a> { +impl<'a> ChainFormatterShared<'a> { fn new(chain: &'a Chain) -> ChainFormatterShared<'a> { ChainFormatterShared { children: &chain.children, @@ -371,9 +385,16 @@ impl <'a> ChainFormatterShared<'a> { // result // }) // ``` - fn format_last_child(&mut self, may_extend: bool, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { + fn format_last_child( + &mut self, + may_extend: bool, + context: &RewriteContext, + shape: Shape, + child_shape: Shape, + ) -> Option<()> { let last = &self.children[0]; - let extendable = may_extend && last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); + let extendable = + may_extend && last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); // Total of all items excluding the last. let almost_total = if extendable { @@ -387,7 +408,8 @@ impl <'a> ChainFormatterShared<'a> { min(shape.width, context.config.width_heuristics().chain_width) }.saturating_sub(almost_total); - let all_in_one_line = self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; + let all_in_one_line = + self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; let last_shape = if all_in_one_line { shape.sub_width(last.tries)? } else { @@ -413,7 +435,8 @@ impl <'a> ChainFormatterShared<'a> { // layout, just by looking at the overflowed rewrite. Now we rewrite the // last child on its own line, and compare two rewrites to choose which is // better. - let last_shape = child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?; + let last_shape = child_shape + .sub_width(shape.rhs_overhead(context.config) + last.tries)?; match last.rewrite_postfix(context, last_shape) { Some(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); @@ -440,7 +463,12 @@ impl <'a> ChainFormatterShared<'a> { Some(()) } - fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape, block_like_iter: impl Iterator) -> Option { + fn join_rewrites( + &self, + context: &RewriteContext, + child_shape: Shape, + block_like_iter: impl Iterator, + ) -> Option { let connector = if self.fits_single_line { // Yay, we can put everything on one line. Cow::from("") @@ -473,7 +501,7 @@ struct ChainFormatterBlock<'a> { is_block_like: Vec, } -impl <'a> ChainFormatterBlock<'a> { +impl<'a> ChainFormatterBlock<'a> { fn new(chain: &'a Chain) -> ChainFormatterBlock<'a> { ChainFormatterBlock { shared: ChainFormatterShared::new(chain), @@ -482,8 +510,13 @@ impl <'a> ChainFormatterBlock<'a> { } } -impl <'a> ChainFormatter for ChainFormatterBlock<'a> { - fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { +impl<'a> ChainFormatter for ChainFormatterBlock<'a> { + fn format_root( + &mut self, + parent: &ChainItem, + context: &RewriteContext, + shape: Shape, + ) -> Option<()> { let mut root_rewrite: String = parent.rewrite(context, shape)?; let mut root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); @@ -520,18 +553,26 @@ impl <'a> ChainFormatter for ChainFormatterBlock<'a> { fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { for item in self.shared.children[1..].iter().rev() { let rewrite = item.rewrite_postfix(context, child_shape)?; - self.is_block_like.push(is_block_expr(context, &item.expr, &rewrite)); + self.is_block_like + .push(is_block_expr(context, &item.expr, &rewrite)); self.shared.rewrites.push(rewrite); } Some(()) } - fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { - self.shared.format_last_child(true, context, shape, child_shape) + fn format_last_child( + &mut self, + context: &RewriteContext, + shape: Shape, + child_shape: Shape, + ) -> Option<()> { + self.shared + .format_last_child(true, context, shape, child_shape) } fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { - self.shared.join_rewrites(context, child_shape, self.is_block_like.iter().cloned()) + self.shared + .join_rewrites(context, child_shape, self.is_block_like.iter().cloned()) } fn pure_root(&mut self) -> Option { @@ -552,8 +593,13 @@ impl<'a> ChainFormatterVisual<'a> { } } -impl <'a> ChainFormatter for ChainFormatterVisual<'a> { - fn format_root(&mut self, parent: &ChainItem, context: &RewriteContext, shape: Shape) -> Option<()> { +impl<'a> ChainFormatter for ChainFormatterVisual<'a> { + fn format_root( + &mut self, + parent: &ChainItem, + context: &RewriteContext, + shape: Shape, + ) -> Option<()> { // Determines if we can continue formatting a given expression on the same line. fn is_continuable(expr: &ast::Expr) -> bool { match expr.node { @@ -596,12 +642,19 @@ impl <'a> ChainFormatter for ChainFormatterVisual<'a> { Some(()) } - fn format_last_child(&mut self, context: &RewriteContext, shape: Shape, child_shape: Shape) -> Option<()> { - self.shared.format_last_child(false, context, shape, child_shape) + fn format_last_child( + &mut self, + context: &RewriteContext, + shape: Shape, + child_shape: Shape, + ) -> Option<()> { + self.shared + .format_last_child(false, context, shape, child_shape) } fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { - self.shared.join_rewrites(context, child_shape, iter::repeat(false)) + self.shared + .join_rewrites(context, child_shape, iter::repeat(false)) } fn pure_root(&mut self) -> Option { @@ -613,9 +666,7 @@ impl <'a> ChainFormatter for ChainFormatterVisual<'a> { // parens, braces, and brackets in its idiomatic formatting. fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { match expr.node { - ast::ExprKind::Mac(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::MethodCall(..) => { + ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) => { context.use_block_indent() && repr.contains('\n') } ast::ExprKind::Struct(..) @@ -631,7 +682,7 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool | ast::ExprKind::Binary(_, _, ref expr) | ast::ExprKind::Index(_, ref expr) | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Closure(_, _, _, _, ref expr, _) + | ast::ExprKind::Closure(_, _, _, _, ref expr, _) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), _ => false, diff --git a/src/closures.rs b/src/closures.rs index 783ca1c029b..128e1dc8e0b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -198,8 +198,7 @@ fn rewrite_closure_expr( } else { Some(rw) } - }) - .map(|rw| format!("{} {}", prefix, rw)) + }).map(|rw| format!("{} {}", prefix, rw)) } // Rewrite closure whose body is block. @@ -376,11 +375,8 @@ where .map(|e| match e.node { ast::ExprKind::Closure(..) => true, _ => false, - }) - .unwrap_or(false) - }) - .count() - > 1 + }).unwrap_or(false) + }).count() > 1 } fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { diff --git a/src/comment.rs b/src/comment.rs index 3d55f6560e3..ed83a3925b0 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -348,8 +348,7 @@ fn rewrite_comment_inner( } line - }) - .map(|s| left_trim_comment_line(s, &style)) + }).map(|s| left_trim_comment_line(s, &style)) .map(|(line, has_leading_whitespace)| { if orig.starts_with("/*") && line_breaks == 0 { ( @@ -517,8 +516,7 @@ fn trim_custom_comment_prefix(s: &str) -> String { } else { line } - }) - .collect::>() + }).collect::>() .join("\n") } @@ -606,8 +604,7 @@ fn light_rewrite_comment( }; // Preserve markdown's double-space line break syntax in doc comment. trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) - }) - .collect(); + }).collect(); Some(lines.join(&format!("\n{}", offset.to_string(config)))) } @@ -1341,8 +1338,7 @@ mod test { .filter_map(|(s, c)| match s { FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), _ => None, - }) - .collect() + }).collect() } #[test] diff --git a/src/config/options.rs b/src/config/options.rs index a581cdef43d..c48f9a4d727 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -322,8 +322,7 @@ impl IgnoreList { path.push(s); path } - }) - .collect(); + }).collect(); } fn skip_file_inner(&self, file: &Path) -> bool { diff --git a/src/expr.rs b/src/expr.rs index 8aa5d9bd286..6814b91e053 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1212,8 +1212,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt new_indent.to_string(context.config), line.trim_left() ) - }) - .collect::>() + }).collect::>() .join("\n") .trim_left(), ); diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index d6ab3661482..d47827ab55e 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -46,8 +46,7 @@ fn prune_files(files: Vec<&str>) -> Vec<&str> { return true; } pruned_prefixes.iter().all(|pp| !f.starts_with(pp)) - }) - .collect() + }).collect() } fn git_diff(commits: &str) -> String { diff --git a/src/imports.rs b/src/imports.rs index f087ea5e52a..93f2ac8867a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -344,8 +344,7 @@ impl UseTree { .zip(items.into_iter()) .map(|(t, list_item)| { Self::from_ast(context, &t.0, Some(list_item), None, None, None) - }) - .collect(), + }).collect(), )); } UseTreeKind::Simple(ref rename, ..) => { diff --git a/src/items.rs b/src/items.rs index 721f02b0187..23338435d9a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1669,7 +1669,7 @@ fn rewrite_static( &**expr, Shape::legacy(remaining_width, offset.block_only()), ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) - .map(|s| if s.ends_with(';') { s } else { s + ";" }) + .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{}{};", prefix, ty_str)) } @@ -2783,17 +2783,15 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.node { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => { - rewrite_fn_base( - context, - shape.indent, - self.ident, - &FnSig::new(fn_decl, generics, self.vis.clone()), - span, - false, - false, - ).map(|(s, _)| format!("{};", s)) - } + ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => rewrite_fn_base( + context, + shape.indent, + self.ident, + &FnSig::new(fn_decl, generics, self.vis.clone()), + span, + false, + false, + ).map(|(s, _)| format!("{};", s)), ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. diff --git a/src/macros.rs b/src/macros.rs index 4f3891fbf49..91c29958ba1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1115,26 +1115,25 @@ fn indent_macro_snippet( }; trimmed_lines.push((trimmed, line, prefix_space_width)); prefix_space_width - }) - .min()?; + }).min()?; Some( - first_line + "\n" + &trimmed_lines - .iter() - .map( - |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { - _ if !trimmed => line.to_owned(), - Some(original_indent_width) => { - let new_indent_width = indent.width() + original_indent_width - .saturating_sub(min_prefix_space_width); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) - } - None => String::new(), - }, - ) - .collect::>() - .join("\n"), + first_line + "\n" + + &trimmed_lines + .iter() + .map( + |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { + _ if !trimmed => line.to_owned(), + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width.saturating_sub(min_prefix_space_width); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line.trim()) + } + None => String::new(), + }, + ).collect::>() + .join("\n"), ) } @@ -1296,8 +1295,7 @@ impl MacroBranch { } (s + l + "\n", !kind.is_string() || l.ends_with('\\')) }, - ) - .0; + ).0; // Undo our replacement of macro variables. // FIXME: this could be *much* more efficient. diff --git a/src/reorder.rs b/src/reorder.rs index 5947b4ae87f..df32ab47b2f 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -151,8 +151,7 @@ fn rewrite_reorderable_items( .map(|use_tree| ListItem { item: use_tree.rewrite_top_level(context, nested_shape), ..use_tree.list_item.unwrap_or_else(ListItem::empty) - }) - .collect(); + }).collect(); wrap_reorderable_items(context, &item_vec, nested_shape) } @@ -242,15 +241,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let item_length = items .iter() .take_while(|ppi| { - item_kind.is_same_item_kind(&***ppi) - && (!in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) - }) - .count(); + item_kind.is_same_item_kind(&***ppi) && (!in_group || { + let current = self.codemap.lookup_line_range(ppi.span()); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) + }).count(); let items = &items[..item_length]; let at_least_one_in_file_lines = items diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index de52b28c08b..2a331eec19a 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -193,13 +193,15 @@ where W: Write, { for mismatch in diff { - let (num_removed, num_added) = mismatch.lines.iter().fold((0, 0), |(rem, add), line| { - match *line { - DiffLine::Context(_) => panic!("No Context expected"), - DiffLine::Expected(_) => (rem, add + 1), - DiffLine::Resulting(_) => (rem + 1, add), - } - }); + let (num_removed, num_added) = + mismatch + .lines + .iter() + .fold((0, 0), |(rem, add), line| match *line { + DiffLine::Context(_) => panic!("No Context expected"), + DiffLine::Expected(_) => (rem, add + 1), + DiffLine::Resulting(_) => (rem + 1, add), + }); // Write a header with enough information to separate the modified lines. writeln!( out, diff --git a/src/test/mod.rs b/src/test/mod.rs index 63b5f244b90..ba4607be37c 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -514,8 +514,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap { .to_owned(), ) }) - }) - .collect() + }).collect() } // Compare output to input. @@ -884,8 +883,8 @@ fn configuration_snippet_tests() { fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), ).lines() - .map(|l| l.unwrap()) - .enumerate(); + .map(|l| l.unwrap()) + .enumerate(); let mut code_blocks: Vec = Vec::new(); let mut hash_set = Config::hash_set(); @@ -961,5 +960,5 @@ fn verify_check_works() { "--check", temp_file.path.to_str().unwrap(), ]).succeeds() - .unwrap(); + .unwrap(); } diff --git a/src/types.rs b/src/types.rs index 0c978ea28a6..d6e4001eacf 100644 --- a/src/types.rs +++ b/src/types.rs @@ -548,7 +548,8 @@ impl Rewrite for ast::GenericParam { }; result.push_str(eq_str); let budget = shape.width.checked_sub(result.len())?; - let rewrite = def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; + let rewrite = + def.rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; result.push_str(&rewrite); } @@ -793,8 +794,7 @@ fn rewrite_lifetime_param( .filter(|p| match p.kind { ast::GenericParamKind::Lifetime => true, _ => false, - }) - .map(|lt| lt.rewrite(context, shape)) + }).map(|lt| lt.rewrite(context, shape)) .collect::>>()? .join(", "); if result.is_empty() { diff --git a/src/vertical.rs b/src/vertical.rs index 1b7fdb9be1d..ead5719f61f 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -200,14 +200,12 @@ fn struct_field_prefix_max_min_width( Some(field_str.len()) } }) - }) - .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { + }).fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { (Some((max_len, min_len)), Some(len)) => { Some((cmp::max(max_len, len), cmp::min(min_len, len))) } _ => None, - }) - .unwrap_or((0, 0)) + }).unwrap_or((0, 0)) } fn rewrite_aligned_items_inner( -- cgit 1.4.1-3-g733a5 From 8618a558342e98b57f5b2e4697c615b1d0f9b735 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jul 2018 22:06:30 +1200 Subject: chains: treat some string lits as blocks --- src/chains.rs | 81 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 439c0d188a2..67390bc6b7c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -71,7 +71,10 @@ use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; -use utils::{first_line_width, last_line_extendable, last_line_width, mk_sp, wrap_str}; +use utils::{ + first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, + wrap_str, +}; use std::borrow::Cow; use std::cmp::min; @@ -395,10 +398,11 @@ impl<'a> ChainFormatterShared<'a> { let last = &self.children[0]; let extendable = may_extend && last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); + let prev_last_line_width = last_line_width(&self.rewrites[self.rewrites.len() - 1]); // Total of all items excluding the last. let almost_total = if extendable { - last_line_width(&self.rewrites[self.rewrites.len() - 1]) + prev_last_line_width } else { self.rewrites.iter().fold(0, |a, b| a + b.len()) } + last.tries; @@ -410,7 +414,7 @@ impl<'a> ChainFormatterShared<'a> { let all_in_one_line = self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; - let last_shape = if all_in_one_line { + let last_shape = if all_in_one_line || extendable { shape.sub_width(last.tries)? } else { child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)? @@ -508,6 +512,37 @@ impl<'a> ChainFormatterBlock<'a> { is_block_like: Vec::with_capacity(chain.children.len() + 1), } } + + // States whether an expression's last line exclusively consists of closing + // parens, braces, and brackets in its idiomatic formatting. + fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { + match expr.node { + ast::ExprKind::Mac(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) + | ast::ExprKind::Binary(_, _, ref expr) + | ast::ExprKind::Index(_, ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Closure(_, _, _, _, ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Yield(Some(ref expr)) => Self::is_block_expr(context, expr, repr), + // This can only be a string lit + ast::ExprKind::Lit(_) => { + repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces() + } + _ => false, + } + } } impl<'a> ChainFormatter for ChainFormatterBlock<'a> { @@ -519,7 +554,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { ) -> Option<()> { let mut root_rewrite: String = parent.rewrite(context, shape)?; - let mut root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); + let mut root_ends_with_block = Self::is_block_expr(context, &parent.expr, &root_rewrite); let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { @@ -530,7 +565,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { None => break, } - root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); + root_ends_with_block = Self::is_block_expr(context, &item.expr, &root_rewrite); self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; if self.shared.children.is_empty() { @@ -554,7 +589,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { for item in self.shared.children[1..].iter().rev() { let rewrite = item.rewrite_postfix(context, child_shape)?; self.is_block_like - .push(is_block_expr(context, &item.expr, &rewrite)); + .push(Self::is_block_expr(context, &item.expr, &rewrite)); self.shared.rewrites.push(rewrite); } Some(()) @@ -608,12 +643,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } } - // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. - let parent_shape = if is_block_expr(context, &parent.expr, "\n") { - shape.visual_indent(0) - } else { - shape - }; + let parent_shape = shape.visual_indent(0); let mut root_rewrite = parent.rewrite(context, parent_shape)?; if !root_rewrite.contains('\n') && is_continuable(&parent.expr) { @@ -661,30 +691,3 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { self.shared.pure_root() } } - -// States whether an expression's last line exclusively consists of closing -// parens, braces, and brackets in its idiomatic formatting. -fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { - match expr.node { - ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) => { - context.use_block_indent() && repr.contains('\n') - } - ast::ExprKind::Struct(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Match(..) => repr.contains('\n'), - ast::ExprKind::Paren(ref expr) - | ast::ExprKind::Binary(_, _, ref expr) - | ast::ExprKind::Index(_, ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Closure(_, _, _, _, ref expr, _) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), - _ => false, - } -} -- cgit 1.4.1-3-g733a5 From f9510a55eb952f078764f3caa8a8415bfbf9d352 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 12 Jul 2018 10:44:06 +1200 Subject: chains: fix visual indent chain layout --- src/chains.rs | 140 +++++++++++++++++++++++++++++++++------------------------- src/shape.rs | 6 +++ 2 files changed, 85 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 67390bc6b7c..45b45b16732 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -275,12 +275,12 @@ impl Rewrite for Chain { }; formatter.format_root(&self.parent, context, shape)?; - if let result @ Some(_) = formatter.pure_root() { - return result; + if let Some(result) = formatter.pure_root() { + return wrap_str(result, context.config.max_width(), shape); } // Decide how to layout the rest of the chain. - let child_shape = formatter.child_shape(context, shape); + let child_shape = formatter.child_shape(context, shape)?; formatter.format_children(context, child_shape)?; formatter.format_last_child(context, shape, child_shape)?; @@ -309,7 +309,7 @@ trait ChainFormatter { context: &RewriteContext, shape: Shape, ) -> Option<()>; - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape; + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option; fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()>; fn format_last_child( &mut self, @@ -414,8 +414,10 @@ impl<'a> ChainFormatterShared<'a> { let all_in_one_line = self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; - let last_shape = if all_in_one_line || extendable { + let last_shape = if all_in_one_line { shape.sub_width(last.tries)? + } else if extendable { + child_shape.sub_width(last.tries)? } else { child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)? }; @@ -481,7 +483,7 @@ impl<'a> ChainFormatterShared<'a> { if *context.force_one_line_chain.borrow() { return None; } - child_shape.indent.to_string_with_newline(context.config) + child_shape.to_string_with_newline(context.config) }; let mut rewrite_iter = self.rewrites.iter(); @@ -512,37 +514,6 @@ impl<'a> ChainFormatterBlock<'a> { is_block_like: Vec::with_capacity(chain.children.len() + 1), } } - - // States whether an expression's last line exclusively consists of closing - // parens, braces, and brackets in its idiomatic formatting. - fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { - match expr.node { - ast::ExprKind::Mac(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Match(..) => repr.contains('\n'), - ast::ExprKind::Paren(ref expr) - | ast::ExprKind::Binary(_, _, ref expr) - | ast::ExprKind::Index(_, ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Closure(_, _, _, _, ref expr, _) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Yield(Some(ref expr)) => Self::is_block_expr(context, expr, repr), - // This can only be a string lit - ast::ExprKind::Lit(_) => { - repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces() - } - _ => false, - } - } } impl<'a> ChainFormatter for ChainFormatterBlock<'a> { @@ -554,7 +525,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { ) -> Option<()> { let mut root_rewrite: String = parent.rewrite(context, shape)?; - let mut root_ends_with_block = Self::is_block_expr(context, &parent.expr, &root_rewrite); + let mut root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { @@ -565,7 +536,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { None => break, } - root_ends_with_block = Self::is_block_expr(context, &item.expr, &root_rewrite); + root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; if self.shared.children.is_empty() { @@ -577,19 +548,21 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { Some(()) } - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape { - if self.is_block_like[0] { - shape - } else { - shape.block_indent(context.config.tab_spaces()) - }.with_max_width(context.config) + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option { + Some( + if self.is_block_like[0] { + shape.block_indent(0) + } else { + shape.block_indent(context.config.tab_spaces()) + }.with_max_width(context.config), + ) } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { for item in self.shared.children[1..].iter().rev() { let rewrite = item.rewrite_postfix(context, child_shape)?; self.is_block_like - .push(Self::is_block_expr(context, &item.expr, &rewrite)); + .push(is_block_expr(context, &item.expr, &rewrite)); self.shared.rewrites.push(rewrite); } Some(()) @@ -618,12 +591,15 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { // Format a chain using visual indent. struct ChainFormatterVisual<'a> { shared: ChainFormatterShared<'a>, + // The extra offset from the chain's shape to the position of the `.` + offset: usize, } impl<'a> ChainFormatterVisual<'a> { fn new(chain: &'a Chain) -> ChainFormatterVisual<'a> { ChainFormatterVisual { shared: ChainFormatterShared::new(chain), + offset: 0, } } } @@ -635,23 +611,31 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { context: &RewriteContext, shape: Shape, ) -> Option<()> { - // Determines if we can continue formatting a given expression on the same line. - fn is_continuable(expr: &ast::Expr) -> bool { - match expr.node { - ast::ExprKind::Path(..) => true, - _ => false, - } - } - let parent_shape = shape.visual_indent(0); let mut root_rewrite = parent.rewrite(context, parent_shape)?; + let multiline = root_rewrite.contains('\n'); + self.offset = if multiline { + last_line_width(&root_rewrite).saturating_sub(shape.used_width()) + } else { + trimmed_last_line_width(&root_rewrite) + }; - if !root_rewrite.contains('\n') && is_continuable(&parent.expr) { + if !multiline || is_block_expr(context, &parent.expr, &root_rewrite) { let item = &self.shared.children[self.shared.children.len() - 1]; - let overhead = last_line_width(&root_rewrite); - let shape = parent_shape.offset_left(overhead)?; - let rewrite = item.rewrite_postfix(context, shape)?; - root_rewrite.push_str(&rewrite); + let child_shape = parent_shape + .visual_indent(self.offset) + .sub_width(self.offset)?; + let rewrite = item.rewrite_postfix(context, child_shape)?; + match wrap_str(rewrite, context.config.max_width(), shape) { + Some(rewrite) => root_rewrite.push_str(&rewrite), + None => { + // We couldn't fit in at the visual indent, try the last + // indent. + let rewrite = item.rewrite_postfix(context, parent_shape)?; + root_rewrite.push_str(&rewrite); + self.offset = 0; + } + } self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; } @@ -660,8 +644,11 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { Some(()) } - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Shape { - shape.visual_indent(0).with_max_width(context.config) + fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option { + shape + .with_max_width(context.config) + .offset_left(self.offset) + .map(|s| s.visual_indent(0)) } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { @@ -691,3 +678,34 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { self.shared.pure_root() } } + +// States whether an expression's last line exclusively consists of closing +// parens, braces, and brackets in its idiomatic formatting. +fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { + match expr.node { + ast::ExprKind::Mac(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) + | ast::ExprKind::Binary(_, _, ref expr) + | ast::ExprKind::Index(_, ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Closure(_, _, _, _, ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), + // This can only be a string lit + ast::ExprKind::Lit(_) => { + repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces() + } + _ => false, + } +} diff --git a/src/shape.rs b/src/shape.rs index ab33826c028..12a911a1931 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -274,6 +274,12 @@ impl Shape { ); Shape { width, ..*self } } + + pub fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { + let mut offset_indent = self.indent; + offset_indent.alignment = self.offset; + offset_indent.to_string_inner(config, 0) + } } #[cfg(test)] -- cgit 1.4.1-3-g733a5 From df4fb8a05b95f770304dae63c0bd90bb7408a232 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 15:48:23 +1200 Subject: Reformatting after rebase --- src/chains.rs | 2 +- src/closures.rs | 3 ++- src/formatting.rs | 3 +-- src/macros.rs | 31 +++++++++++++++---------------- src/pairs.rs | 2 +- src/reorder.rs | 13 +++++++------ 6 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 45b45b16732..7acb9b9126f 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -302,7 +302,7 @@ trait ChainFormatter { // foo.bar // .baz() // ``` - // If `bar` were not part of the root, then baz would be orphaned and 'float'. + // If `bar` were not part of the root, then foo would be orphaned and 'float'. fn format_root( &mut self, parent: &ChainItem, diff --git a/src/closures.rs b/src/closures.rs index 128e1dc8e0b..c03c8e6b606 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -376,7 +376,8 @@ where ast::ExprKind::Closure(..) => true, _ => false, }).unwrap_or(false) - }).count() > 1 + }).count() + > 1 } fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { diff --git a/src/formatting.rs b/src/formatting.rs index ee2539a2fa5..42ab4e89c3b 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -246,8 +246,7 @@ impl FormattingError { fl.file .get_line(fl.lines[0].line_index) .map(|l| l.into_owned()) - }) - .unwrap_or_else(|| String::new()), + }).unwrap_or_else(|| String::new()), } } diff --git a/src/macros.rs b/src/macros.rs index 91c29958ba1..b55375b949c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1118,22 +1118,21 @@ fn indent_macro_snippet( }).min()?; Some( - first_line + "\n" - + &trimmed_lines - .iter() - .map( - |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { - _ if !trimmed => line.to_owned(), - Some(original_indent_width) => { - let new_indent_width = indent.width() - + original_indent_width.saturating_sub(min_prefix_space_width); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) - } - None => String::new(), - }, - ).collect::>() - .join("\n"), + first_line + "\n" + &trimmed_lines + .iter() + .map( + |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { + _ if !trimmed => line.to_owned(), + Some(original_indent_width) => { + let new_indent_width = indent.width() + original_indent_width + .saturating_sub(min_prefix_space_width); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line.trim()) + } + None => String::new(), + }, + ).collect::>() + .join("\n"), ) } diff --git a/src/pairs.rs b/src/pairs.rs index 2c4358f7278..17b86975022 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -125,7 +125,7 @@ fn rewrite_pairs_multiline( IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), }).with_max_width(&context.config) - .sub_width(rhs_offset)?; + .sub_width(rhs_offset)?; let indent_str = nested_shape.indent.to_string_with_newline(context.config); let mut result = String::new(); diff --git a/src/reorder.rs b/src/reorder.rs index df32ab47b2f..48ddd116337 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -241,12 +241,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let item_length = items .iter() .take_while(|ppi| { - item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); - let in_same_group = current.lo < last.hi + 2; - last = current; - in_same_group - }) + item_kind.is_same_item_kind(&***ppi) + && (!in_group || { + let current = self.codemap.lookup_line_range(ppi.span()); + let in_same_group = current.lo < last.hi + 2; + last = current; + in_same_group + }) }).count(); let items = &items[..item_length]; -- cgit 1.4.1-3-g733a5 From 43f178bd58b02f4be0bd38a2169b5d446bd39da5 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 24 Jul 2018 21:41:49 +1200 Subject: Remove `Summary` --- src/bin/main.rs | 23 ++++--- src/formatting.rs | 172 ++++++++++++++---------------------------------- src/git-rustfmt/main.rs | 2 +- src/lib.rs | 58 ++++++++++++++-- src/test/mod.rs | 16 ++--- 5 files changed, 124 insertions(+), 147 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 7767ea84764..049749f8f52 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -225,12 +225,11 @@ fn format_string(input: String, options: GetOptsOptions) -> Result(session: &mut Session, input: Input) { } Err(msg) => { eprintln!("Error writing files: {}", msg); - session.summary.add_operational_error(); + session.add_operational_error(); } } } diff --git a/src/formatting.rs b/src/formatting.rs index 42ab4e89c3b..ceada0d4040 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -46,8 +46,12 @@ impl<'b, T: Write + 'b> Session<'b, T> { let config = &self.config.clone(); let format_result = format_project(input, config, self); - format_result.map(|(report, summary)| { - self.summary.add(summary); + format_result.map(|report| { + { + let new_errors = &report.internal.borrow().1; + + self.errors.add(new_errors); + } report }) }) @@ -59,8 +63,7 @@ fn format_project( input: Input, config: &Config, handler: &mut T, -) -> Result<(FormatReport, Summary), ErrorKind> { - let mut summary = Summary::default(); +) -> Result { let mut timer = Timer::Initialized(Instant::now()); let main_file = input.file_name(); @@ -69,21 +72,15 @@ fn format_project( // Parse the crate. let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); let mut parse_session = make_parse_sess(codemap.clone(), config); - let krate = parse_crate(input, &parse_session, config, &mut summary)?; + let mut report = FormatReport::new(); + let krate = parse_crate(input, &parse_session, config, &mut report)?; timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. let silent_emitter = silent_emitter(codemap); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - let mut context = FormatContext::new( - &krate, - FormatReport::new(), - summary, - parse_session, - config, - handler, - ); + let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::list_files(&krate, context.parse_session.codemap())?; for (path, module) in files { @@ -104,8 +101,7 @@ fn format_project( ) }); - context.summarise_errors(); - Ok((context.report, context.summary)) + Ok(context.report) } // Used for formatting files. @@ -113,27 +109,12 @@ fn format_project( struct FormatContext<'a, T: FormatHandler + 'a> { krate: &'a ast::Crate, report: FormatReport, - summary: Summary, parse_session: ParseSess, config: &'a Config, handler: &'a mut T, } impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { - // Moves errors from the report to the summary. - fn summarise_errors(&mut self) { - if self.report.has_warnings() { - self.summary.add_formatting_error(); - } - let report_errs = &self.report.internal.borrow().1; - if report_errs.has_check_errors { - self.summary.add_check_error(); - } - if report_errs.has_operational_errors { - self.summary.add_operational_error(); - } - } - // Formats a single file/module. fn format_file( &mut self, @@ -188,16 +169,22 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { replace_with_system_newlines(&mut visitor.buffer, &self.config); if visitor.macro_rewrite_failure { - self.summary.add_macro_format_failure(); + self.report.add_macro_format_failure(); } - self.handler.handle_formatted_file(path, visitor.buffer) + self.handler + .handle_formatted_file(path, visitor.buffer, &mut self.report) } } // Handle the results of formatting. trait FormatHandler { - fn handle_formatted_file(&mut self, path: FileName, result: String) -> Result<(), ErrorKind>; + fn handle_formatted_file( + &mut self, + path: FileName, + result: String, + report: &mut FormatReport, + ) -> Result<(), ErrorKind>; } impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { @@ -206,10 +193,11 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { &mut self, path: FileName, mut result: String, + report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { match filemap::write_file(&mut result, &path, out, &self.config) { - Ok(b) if b => self.summary.add_diff(), + Ok(b) if b => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed let err_msg = format!("{}: {}", path, e); @@ -298,114 +286,56 @@ pub(crate) type FormatErrorMap = HashMap>; #[derive(Default, Debug)] pub(crate) struct ReportedErrors { - pub(crate) has_operational_errors: bool, - pub(crate) has_check_errors: bool, -} - -/// A single span of changed lines, with 0 or more removed lines -/// and a vector of 0 or more inserted lines. -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ModifiedChunk { - /// The first to be removed from the original text - pub line_number_orig: u32, - /// The number of lines which have been replaced - pub lines_removed: u32, - /// The new lines - pub lines: Vec, -} - -/// Set of changed sections of a file. -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ModifiedLines { - /// The set of changed chunks. - pub chunks: Vec, -} - -/// A summary of a Rustfmt run. -#[derive(Debug, Default, Clone, Copy)] -pub struct Summary { // Encountered e.g. an IO error. - has_operational_errors: bool, + pub(crate) has_operational_errors: bool, // Failed to reformat code because of parsing errors. - has_parsing_errors: bool, + pub(crate) has_parsing_errors: bool, // Code is valid, but it is impossible to format it properly. - has_formatting_errors: bool, + pub(crate) has_formatting_errors: bool, // Code contains macro call that was unable to format. pub(crate) has_macro_format_failure: bool, // Failed a check, such as the license check or other opt-in checking. - has_check_errors: bool, + pub(crate) has_check_errors: bool, /// Formatted code differs from existing code (--check only). - pub has_diff: bool, + pub(crate) has_diff: bool, } -impl Summary { - pub fn has_operational_errors(&self) -> bool { - self.has_operational_errors - } - - pub fn has_parsing_errors(&self) -> bool { - self.has_parsing_errors - } - - pub fn has_formatting_errors(&self) -> bool { - self.has_formatting_errors - } - - pub fn has_check_errors(&self) -> bool { - self.has_check_errors - } - - pub(crate) fn has_macro_formatting_failure(&self) -> bool { - self.has_macro_format_failure - } - - pub fn add_operational_error(&mut self) { - self.has_operational_errors = true; - } - - pub(crate) fn add_parsing_error(&mut self) { - self.has_parsing_errors = true; - } - - pub(crate) fn add_formatting_error(&mut self) { - self.has_formatting_errors = true; - } - - pub(crate) fn add_check_error(&mut self) { - self.has_check_errors = true; - } - - pub(crate) fn add_diff(&mut self) { - self.has_diff = true; - } - - pub(crate) fn add_macro_format_failure(&mut self) { - self.has_macro_format_failure = true; - } - - pub fn has_no_errors(&self) -> bool { - !(self.has_operational_errors - || self.has_parsing_errors - || self.has_formatting_errors - || self.has_diff) - } - +impl ReportedErrors { /// Combine two summaries together. - pub fn add(&mut self, other: Summary) { + pub fn add(&mut self, other: &ReportedErrors) { self.has_operational_errors |= other.has_operational_errors; + self.has_parsing_errors |= other.has_parsing_errors; self.has_formatting_errors |= other.has_formatting_errors; self.has_macro_format_failure |= other.has_macro_format_failure; - self.has_parsing_errors |= other.has_parsing_errors; self.has_check_errors |= other.has_check_errors; self.has_diff |= other.has_diff; } } +/// A single span of changed lines, with 0 or more removed lines +/// and a vector of 0 or more inserted lines. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ModifiedChunk { + /// The first to be removed from the original text + pub line_number_orig: u32, + /// The number of lines which have been replaced + pub lines_removed: u32, + /// The new lines + pub lines: Vec, +} + +/// Set of changed sections of a file. +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct ModifiedLines { + /// The set of changed chunks. + pub chunks: Vec, +} + #[derive(Clone, Copy, Debug)] enum Timer { Initialized(Instant), @@ -647,7 +577,7 @@ fn parse_crate( input: Input, parse_session: &ParseSess, config: &Config, - summary: &mut Summary, + report: &mut FormatReport, ) -> Result { let input_is_stdin = input.is_text(); @@ -685,7 +615,7 @@ fn parse_crate( } } - summary.add_parsing_error(); + report.add_parsing_error(); Err(ErrorKind::ParseError) } diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index d47827ab55e..0042ff353a7 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -79,7 +79,7 @@ fn fmt_files(files: &[&str]) -> i32 { if report.has_warnings() { eprintln!("{}", report); } - if !session.summary.has_no_errors() { + if !session.has_no_errors() { exit_code = 1; } } diff --git a/src/lib.rs b/src/lib.rs index a1cd3ba84a1..0ee913690b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{FileMap, FormatErrorMap, FormattingError, ReportedErrors, Summary}; +use formatting::{FileMap, FormatErrorMap, FormattingError, ReportedErrors}; use issues::Issue; use shape::Indent; @@ -179,6 +179,9 @@ impl FormatReport { fn track_errors(&self, new_errors: &[FormattingError]) { let errs = &mut self.internal.borrow_mut().1; + if !new_errors.is_empty() { + errs.has_formatting_errors = true; + } if errs.has_operational_errors && errs.has_check_errors { return; } @@ -199,6 +202,18 @@ impl FormatReport { } } + fn add_diff(&mut self) { + self.internal.borrow_mut().1.has_diff = true; + } + + fn add_macro_format_failure(&mut self) { + self.internal.borrow_mut().1.has_macro_format_failure = true; + } + + fn add_parsing_error(&mut self) { + self.internal.borrow_mut().1.has_parsing_errors = true; + } + fn warning_count(&self) -> usize { self.internal .borrow() @@ -210,7 +225,7 @@ impl FormatReport { /// Whether any warnings or errors are present in the report. pub fn has_warnings(&self) -> bool { - self.warning_count() > 0 + self.internal.borrow().1.has_formatting_errors } /// Print the report to a terminal using colours and potentially other @@ -351,7 +366,7 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { { let mut session = Session::new(config, Some(&mut out)); let result = session.format(input); - let formatting_error = session.summary.has_macro_formatting_failure() + let formatting_error = session.errors.has_macro_format_failure || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty(); if formatting_error || result.is_err() { return None; @@ -443,7 +458,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { pub struct Session<'b, T: Write + 'b> { pub config: Config, pub out: Option<&'b mut T>, - pub summary: Summary, + pub(crate) errors: ReportedErrors, filemap: FileMap, } @@ -456,7 +471,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { Session { config, out, - summary: Summary::default(), + errors: ReportedErrors::default(), filemap: FileMap::new(), } } @@ -476,6 +491,39 @@ impl<'b, T: Write + 'b> Session<'b, T> { mem::swap(&mut config, &mut self.config); result } + + pub fn add_operational_error(&mut self) { + self.errors.has_operational_errors = true; + } + + pub fn has_operational_errors(&self) -> bool { + self.errors.has_operational_errors + } + + pub fn has_parsing_errors(&self) -> bool { + self.errors.has_parsing_errors + } + + pub fn has_formatting_errors(&self) -> bool { + self.errors.has_formatting_errors + } + + pub fn has_check_errors(&self) -> bool { + self.errors.has_check_errors + } + + pub fn has_diff(&self) -> bool { + self.errors.has_diff + } + + pub fn has_no_errors(&self) -> bool { + !(self.has_operational_errors() + || self.has_parsing_errors() + || self.has_formatting_errors() + || self.has_check_errors() + || self.has_diff()) + || self.errors.has_macro_format_failure + } } impl<'b, T: Write + 'b> Drop for Session<'b, T> { diff --git a/src/test/mod.rs b/src/test/mod.rs index ba4607be37c..beba2628112 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -21,7 +21,7 @@ use std::str::Chars; use config::{Color, Config, EmitMode, FileName, ReportTactic}; use filemap; -use formatting::{FileMap, ModifiedChunk, Summary}; +use formatting::{FileMap, ModifiedChunk}; use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; use {FormatReport, Input, Session}; @@ -278,7 +278,7 @@ fn stdin_formatting_smoke_test() { { let mut session = Session::new(config, Some(&mut buf)); session.format(input).unwrap(); - assert!(session.summary.has_no_errors()); + assert!(session.has_no_errors()); } //eprintln!("{:?}", ); #[cfg(not(windows))] @@ -318,7 +318,7 @@ fn format_lines_errors_are_reported() { config.set().error_on_line_overflow(true); let mut session = Session::::new(config, None); session.format(input).unwrap(); - assert!(session.summary.has_formatting_errors()); + assert!(session.has_formatting_errors()); } #[test] @@ -330,7 +330,7 @@ fn format_lines_errors_are_reported_with_tabs() { config.set().hard_tabs(true); let mut session = Session::::new(config, None); session.format(input).unwrap(); - assert!(session.summary.has_formatting_errors()); + assert!(session.has_formatting_errors()); } // For each file, run rustfmt and collect the output. @@ -419,7 +419,7 @@ fn format_file>(filepath: P, config: Config) -> (bool, FileMap, let input = Input::File(filepath); let mut session = Session::::new(config, None); let result = session.format(input).unwrap(); - let parsing_errors = session.summary.has_parsing_errors(); + let parsing_errors = session.has_parsing_errors(); let mut filemap = FileMap::new(); mem::swap(&mut session.filemap, &mut filemap); (parsing_errors, filemap, result) @@ -767,8 +767,8 @@ impl ConfigCodeBlock { true } - fn has_parsing_errors(&self, error_summary: Summary) -> bool { - if error_summary.has_parsing_errors() { + fn has_parsing_errors(&self, session: &Session) -> bool { + if session.has_parsing_errors() { write_message(&format!( "\u{261d}\u{1f3fd} Cannot format {}:{}", CONFIGURATIONS_FILE_NAME, @@ -819,7 +819,7 @@ impl ConfigCodeBlock { { let mut session = Session::new(config, Some(&mut buf)); session.format(input).unwrap(); - if self.has_parsing_errors(session.summary) { + if self.has_parsing_errors(&session) { return false; } } -- cgit 1.4.1-3-g733a5 From fc307ff582002f36a4400fa4cb0c2e0458e936e3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Jul 2018 00:30:01 +0900 Subject: Format exitential type --- src/items.rs | 115 +++++++++++++++++++++++++++++++++++++++++---------------- src/visitor.rs | 26 +++++++++++-- 2 files changed, 107 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 23338435d9a..62bcfd0538d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1400,36 +1400,27 @@ fn format_tuple_struct( Some(result) } -pub fn rewrite_type_alias( +fn rewrite_type_prefix( context: &RewriteContext, indent: Indent, + prefix: &str, ident: ast::Ident, - ty: &ast::Ty, generics: &ast::Generics, - vis: &ast::Visibility, - span: Span, ) -> Option { let mut result = String::with_capacity(128); - - result.push_str(&format_visibility(context, vis)); - result.push_str("type "); + result.push_str(prefix); + let ident_str = rewrite_ident(context, ident); // 2 = `= ` - let g_shape = Shape::indented(indent, context.config) - .offset_left(result.len())? - .sub_width(2)?; - let g_span = mk_sp( - context.snippet_provider.span_after(span, "type"), - ty.span.lo(), - ); - let generics_str = rewrite_generics( - context, - rewrite_ident(context, ident), - generics, - g_shape, - g_span, - )?; - result.push_str(&generics_str); + if generics.params.is_empty() { + result.push_str(ident_str) + } else { + let g_shape = Shape::indented(indent, context.config) + .offset_left(result.len())? + .sub_width(2)?; + let generics_str = rewrite_generics(context, ident_str, generics, g_shape, generics.span)?; + result.push_str(&generics_str); + } let where_budget = context.budget(last_line_width(&result)); let option = WhereClauseOption::snuggled(&result); @@ -1440,24 +1431,76 @@ pub fn rewrite_type_alias( Shape::legacy(where_budget, indent), Density::Vertical, "=", - Some(span.hi()), + None, generics.span.hi(), option, false, )?; result.push_str(&where_clause_str); - if where_clause_str.is_empty() { - result.push_str(" ="); + + Some(result) +} + +fn rewrite_type_item( + context: &RewriteContext, + indent: Indent, + prefix: &str, + suffix: &str, + ident: ast::Ident, + rhs: &R, + generics: &ast::Generics, + vis: &ast::Visibility, +) -> Option { + let mut result = String::with_capacity(128); + result.push_str(&rewrite_type_prefix( + context, + indent, + &format!("{}{} ", format_visibility(context, vis), prefix), + ident, + generics, + )?); + + if generics.where_clause.predicates.is_empty() { + result.push_str(suffix); } else { - result.push_str(&format!( - "{}=", - indent.to_string_with_newline(context.config) - )); + result.push_str(&indent.to_string_with_newline(context.config)); + result.push_str(suffix.trim_left()); } // 1 = ";" - let ty_shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";") + let rhs_shape = Shape::indented(indent, context.config).sub_width(1)?; + rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";") +} + +pub fn rewrite_type_alias( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + ty: &ast::Ty, + generics: &ast::Generics, + vis: &ast::Visibility, +) -> Option { + rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis) +} + +pub fn rewrite_existential_type( + context: &RewriteContext, + indent: Indent, + ident: ast::Ident, + generic_bounds: &ast::GenericBounds, + generics: &ast::Generics, + vis: &ast::Visibility, +) -> Option { + rewrite_type_item( + context, + indent, + "existential type", + ":", + ident, + generic_bounds, + generics, + vis, + ) } fn type_annotation_spacing(config: &Config) -> (&str, &str) { @@ -1706,6 +1749,16 @@ pub fn rewrite_associated_type( } } +pub fn rewrite_existential_impl_type( + context: &RewriteContext, + ident: ast::Ident, + generic_bounds: &ast::GenericBounds, + indent: Indent, +) -> Option { + rewrite_associated_type(ident, None, Some(generic_bounds), context, indent) + .map(|s| format!("existential {}", s)) +} + pub fn rewrite_associated_impl_type( ident: ast::Ident, defaultness: ast::Defaultness, diff --git a/src/visitor.rs b/src/visitor.rs index 2b0f08dd0c7..4fabb3301fc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -19,8 +19,9 @@ use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; use config::{BraceStyle, Config}; use items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, - rewrite_type_alias, FnSig, StaticParts, StructParts, + rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, + rewrite_existential_type, rewrite_extern_crate, rewrite_type_alias, FnSig, StaticParts, + StructParts, }; use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; @@ -412,7 +413,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ty, generics, &item.vis, - item.span, + ); + self.push_rewrite(item.span, rewrite); + } + ast::ItemKind::Existential(ref generic_bounds, ref generics) => { + let rewrite = rewrite_existential_type( + &self.get_context(), + self.block_indent, + item.ident, + generic_bounds, + generics, + &item.vis, ); self.push_rewrite(item.span, rewrite); } @@ -510,6 +521,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(ii.span, rewrite); } + ast::ImplItemKind::Existential(ref generic_bounds) => { + let rewrite = rewrite_existential_impl_type( + &self.get_context(), + ii.ident, + generic_bounds, + self.block_indent, + ); + self.push_rewrite(ii.span, rewrite); + } ast::ImplItemKind::Macro(ref mac) => { self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); } -- cgit 1.4.1-3-g733a5 From 6d7a764b3df8ef28baf08107c43ba74ee68d438d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Jul 2018 00:34:46 +0900 Subject: Remove span from rewrite_generics's parameter We can just use the span from ast::Generics. --- src/items.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 62bcfd0538d..6b81dbaf796 100644 --- a/src/items.rs +++ b/src/items.rs @@ -801,17 +801,12 @@ fn format_impl_ref_and_type( result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); - let lo = context.snippet_provider.span_after(item.span, "impl"); - let hi = match *trait_ref { - Some(ref tr) => tr.path.span.lo(), - None => self_ty.span.lo(), - }; let shape = generics_shape_from_config( context.config, Shape::indented(offset + last_line_width(&result), context.config), 0, )?; - let generics_str = rewrite_generics(context, "impl", generics, shape, mk_sp(lo, hi))?; + let generics_str = rewrite_generics(context, "impl", generics, shape)?; result.push_str(&generics_str); let polarity_str = if polarity == ast::ImplPolarity::Negative { @@ -986,13 +981,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let body_lo = context.snippet_provider.span_after(item.span, "{"); let shape = Shape::indented(offset, context.config).offset_left(result.len())?; - let generics_str = rewrite_generics( - context, - rewrite_ident(context, item.ident), - generics, - shape, - mk_sp(item.span.lo(), body_lo), - )?; + let generics_str = + rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?; result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. @@ -1138,7 +1128,7 @@ pub fn format_trait_alias( let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; - let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?; + let generics_str = rewrite_generics(context, &alias, generics, g_shape)?; let lhs = format!("trait {} =", generics_str); // 1 = ";" rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";") @@ -1340,8 +1330,7 @@ fn format_tuple_struct( Some(generics) => { let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); - let g_span = mk_sp(span.lo(), body_lo); - let generics_str = rewrite_generics(context, "", generics, shape, g_span)?; + let generics_str = rewrite_generics(context, "", generics, shape)?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1418,7 +1407,7 @@ fn rewrite_type_prefix( let g_shape = Shape::indented(indent, context.config) .offset_left(result.len())? .sub_width(2)?; - let generics_str = rewrite_generics(context, ident_str, generics, g_shape, generics.span)?; + let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?; result.push_str(&generics_str); } @@ -1942,13 +1931,11 @@ fn rewrite_fn_base( offset: used_width, }; let fd = fn_sig.decl; - let g_span = mk_sp(span.lo(), fd.output.span().lo()); let generics_str = rewrite_generics( context, rewrite_ident(context, ident), fn_sig.generics, shape, - g_span, )?; result.push_str(&generics_str); @@ -2466,7 +2453,6 @@ fn rewrite_generics( ident: &str, generics: &ast::Generics, shape: Shape, - span: Span, ) -> Option { // FIXME: convert bounds to where clauses where they get too big or if // there is a where clause at all. @@ -2476,7 +2462,7 @@ fn rewrite_generics( } let params = &generics.params.iter().map(|e| &*e).collect::>(); - overflow::rewrite_with_angle_brackets(context, ident, params, shape, span) + overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span) } pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { @@ -2764,7 +2750,7 @@ fn format_generics( used_width: usize, ) -> Option { let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = rewrite_generics(context, "", generics, shape, span)?; + let mut result = rewrite_generics(context, "", generics, shape)?; let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { let budget = context.budget(last_line_used_width(&result, offset.width())); -- cgit 1.4.1-3-g733a5 From 975b3753ba9ef60889daa654b0f96db85be30e2a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Jul 2018 07:15:33 +0900 Subject: Keep the inside macro context in nested macro call --- src/macros.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b55375b949c..c97ef18d65e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -142,6 +142,24 @@ fn return_original_snippet_with_failure_marked( Some(context.snippet(span).to_owned()) } +struct InsideMacroGuard<'a> { + context: &'a RewriteContext<'a>, + is_nested: bool, +} + +impl<'a> InsideMacroGuard<'a> { + fn inside_macro_context(context: &'a RewriteContext) -> InsideMacroGuard<'a> { + let is_nested = context.inside_macro.replace(true); + InsideMacroGuard { context, is_nested } + } +} + +impl<'a> Drop for InsideMacroGuard<'a> { + fn drop(&mut self) { + self.context.inside_macro.replace(self.is_nested); + } +} + pub fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, @@ -149,12 +167,11 @@ pub fn rewrite_macro( shape: Shape, position: MacroPosition, ) -> Option { - context.inside_macro.replace(true); + let guard = InsideMacroGuard::inside_macro_context(context); let result = rewrite_macro_inner(mac, extra_ident, context, shape, position); if result.is_none() { context.macro_rewrite_failure.replace(true); } - context.inside_macro.replace(false); result } -- cgit 1.4.1-3-g733a5 From 6cecdd681f13c0800ba1383072725761cc17e57d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Jul 2018 08:34:43 +0900 Subject: Put lifetimes after trait when they gets orphaned --- src/items.rs | 3 +-- src/types.rs | 53 ++++++++++++++++++++++++++++++++++++++++++----------- src/visitor.rs | 1 - 3 files changed, 43 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6b81dbaf796..7da84bfe68f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1752,11 +1752,10 @@ pub fn rewrite_associated_impl_type( ident: ast::Ident, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, - generic_bounds_opt: Option<&ast::GenericBounds>, context: &RewriteContext, indent: Indent, ) -> Option { - let result = rewrite_associated_type(ident, ty_opt, generic_bounds_opt, context, indent)?; + let result = rewrite_associated_type(ident, ty_opt, None, context, indent)?; match defaultness { ast::Defaultness::Default => Some(format!("default {}", result)), diff --git a/src/types.rs b/src/types.rs index d6e4001eacf..a67ba876591 100644 --- a/src/types.rs +++ b/src/types.rs @@ -27,8 +27,8 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use spanned::Spanned; use utils::{ - colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_width, - mk_sp, rewrite_ident, + colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, + last_line_extendable, last_line_width, mk_sp, rewrite_ident, }; #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -733,15 +733,28 @@ fn rewrite_bare_fn( Some(result) } -fn join_bounds( +fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool { + let is_trait = |b: &ast::GenericBound| match b { + ast::GenericBound::Outlives(..) => false, + ast::GenericBound::Trait(..) => true, + }; + let is_lifetime = |b: &ast::GenericBound| !is_trait(b); + let last_trait_index = generic_bounds.iter().rposition(is_trait); + let first_lifetime_index = generic_bounds.iter().position(is_lifetime); + match (last_trait_index, first_lifetime_index) { + (Some(last_trait_index), Some(first_lifetime_index)) => { + last_trait_index < first_lifetime_index + } + _ => true, + } +} + +fn join_bounds( context: &RewriteContext, shape: Shape, - items: &[T], + items: &[ast::GenericBound], need_indent: bool, -) -> Option -where - T: Rewrite, -{ +) -> Option { // Try to join types in a single line let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", @@ -752,7 +765,7 @@ where .map(|item| item.rewrite(context, shape)) .collect::>>()?; let result = type_strs.join(joiner); - if items.len() == 1 || (!result.contains('\n') && result.len() <= shape.width) { + if items.len() <= 1 || (!result.contains('\n') && result.len() <= shape.width) { return Some(result); } @@ -769,8 +782,26 @@ where (type_strs, shape.indent) }; - let joiner = format!("{}+ ", offset.to_string_with_newline(context.config)); - Some(type_strs.join(&joiner)) + let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b { + ast::GenericBound::Outlives(..) => true, + ast::GenericBound::Trait(..) => last_line_extendable(s), + }; + let mut result = String::with_capacity(128); + result.push_str(&type_strs[0]); + let mut can_be_put_on_the_same_line = is_bound_extendable(&result, &items[0]); + let generic_bounds_in_order = is_generic_bounds_in_order(items); + for (bound, bound_str) in items[1..].iter().zip(type_strs[1..].iter()) { + if generic_bounds_in_order && can_be_put_on_the_same_line { + result.push_str(joiner); + } else { + result.push_str(&offset.to_string_with_newline(context.config)); + result.push_str("+ "); + } + result.push_str(bound_str); + can_be_put_on_the_same_line = is_bound_extendable(bound_str, bound); + } + + Some(result) } pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { diff --git a/src/visitor.rs b/src/visitor.rs index 4fabb3301fc..fdbc9907f22 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -515,7 +515,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ii.ident, ii.defaultness, Some(ty), - None, &self.get_context(), self.block_indent, ); -- cgit 1.4.1-3-g733a5 From 339fa20973c8dabe35a8c2ce65b2e1ee47e7d478 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Jul 2018 07:16:43 +0900 Subject: Veto converting delimiters inside nested macro --- src/macros.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index c97ef18d65e..f00bb339cb0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -168,7 +168,7 @@ pub fn rewrite_macro( position: MacroPosition, ) -> Option { let guard = InsideMacroGuard::inside_macro_context(context); - let result = rewrite_macro_inner(mac, extra_ident, context, shape, position); + let result = rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested); if result.is_none() { context.macro_rewrite_failure.replace(true); } @@ -181,6 +181,7 @@ pub fn rewrite_macro_inner( context: &RewriteContext, shape: Shape, position: MacroPosition, + is_nested_macro: bool, ) -> Option { if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { @@ -193,7 +194,7 @@ pub fn rewrite_macro_inner( let macro_name = rewrite_macro_name(context, &mac.node.path, extra_ident); - let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { + let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) && !is_nested_macro { DelimToken::Bracket } else { original_style @@ -326,7 +327,7 @@ pub fn rewrite_macro_inner( } else { Some(SeparatorTactic::Never) }; - if FORCED_BRACKET_MACROS.contains(macro_name) { + if FORCED_BRACKET_MACROS.contains(macro_name) && !is_nested_macro { context.inside_macro.replace(false); if context.use_block_indent() { force_trailing_comma = Some(SeparatorTactic::Vertical); -- cgit 1.4.1-3-g733a5 From e6255ca3ded6aca5f740b3b6cf1488c0ed4c5d1c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 25 Jul 2018 18:27:25 +0900 Subject: Preserve parens in trait bounds --- src/types.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index d6e4001eacf..985465644ac 100644 --- a/src/types.rs +++ b/src/types.rs @@ -521,7 +521,24 @@ impl Rewrite for ast::GenericBound { impl Rewrite for ast::GenericBounds { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - join_bounds(context, shape, self, true) + if self.is_empty() { + return Some(String::new()); + } + + let span = mk_sp(self.get(0)?.span().lo(), self.last()?.span().hi()); + let has_paren = context.snippet(span).starts_with("("); + let bounds_shape = if has_paren { + shape.offset_left(1)?.sub_width(1)? + } else { + shape + }; + join_bounds(context, bounds_shape, self, true).map(|s| { + if has_paren { + format!("({})", s) + } else { + s + } + }) } } -- cgit 1.4.1-3-g733a5 From 7b37776ade019d8aa6cf86c5bcb2d9f39c0121a5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 26 Jul 2018 21:35:56 +0900 Subject: Modify the rule for reordering impl items 1. If two items have the same kind, then reorder them based on its ident. 2. Handle existential type. --- src/items.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7da84bfe68f..8c32d393df4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -591,23 +591,31 @@ impl<'a> FmtVisitor<'a> { buffer.push((self.buffer.clone(), item.clone())); self.buffer.clear(); } - // type -> const -> macro -> method + // type -> existential -> const -> macro -> method use ast::ImplItemKind::*; fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { match (a, b) { - (Type(..), Type(..)) | (Const(..), Const(..)) => false, + (Type(..), Type(..)) + | (Const(..), Const(..)) + | (Existential(..), Existential(..)) => false, _ => true, } } buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { + (Type(..), Type(..)) + | (Const(..), Const(..)) + | (Macro(..), Macro(..)) + | (Existential(..), Existential(..)) => a.ident.as_str().cmp(&b.ident.as_str()), + (Method(..), Method(..)) => a.span.lo().cmp(&b.span.lo()), (Type(..), _) => Ordering::Less, (_, Type(..)) => Ordering::Greater, + (Existential(..), _) => Ordering::Less, + (_, Existential(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, (_, Const(..)) => Ordering::Greater, (Macro(..), _) => Ordering::Less, (_, Macro(..)) => Ordering::Greater, - _ => a.span.lo().cmp(&b.span.lo()), }); let mut prev_kind = None; for (buf, item) in buffer { -- cgit 1.4.1-3-g733a5 From f121b1a3a96d34909d148a31e7082c78da51111b Mon Sep 17 00:00:00 2001 From: Andrew Audibert Date: Sat, 28 Jul 2018 19:38:14 -0700 Subject: Support raw identifiers in struct expressions --- src/expr.rs | 2 +- tests/target/raw_identifiers.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6814b91e053..8118e3bccfd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1651,7 +1651,7 @@ pub fn rewrite_field( if !attrs_str.is_empty() { attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); }; - let name = &field.ident.name.to_string(); + let name = context.snippet(field.ident.span); if field.is_shorthand { Some(attrs_str + &name) } else { diff --git a/tests/target/raw_identifiers.rs b/tests/target/raw_identifiers.rs index 4abb22b88b7..dd76117fa8e 100644 --- a/tests/target/raw_identifiers.rs +++ b/tests/target/raw_identifiers.rs @@ -10,7 +10,7 @@ fn main() { #[r#attr] r#foo::r#bar(); - let r#local = 3; + let r#local = r#Struct { r#field: () }; let r#async = r#foo(r#local); r#macro!(); -- cgit 1.4.1-3-g733a5 From 6ff2a5e0f3416a140f4e2df6fad0a135da7addc1 Mon Sep 17 00:00:00 2001 From: Aaron Loucks Date: Sat, 28 Jul 2018 16:18:58 -0400 Subject: Auto-detect newline style by default --- Configurations.md | 4 +- src/config/mod.rs | 2 +- src/config/options.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/formatting.rs | 34 ++------------- 4 files changed, 120 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 403154ea6d8..4c621e7b5d2 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1338,8 +1338,8 @@ fn main() { Unix or Windows line endings -- **Default value**: `"Native"` -- **Possible values**: `"Native"`, `"Unix"`, `"Windows"` +- **Default value**: `"Auto"` +- **Possible values**: `"Auto"`, `"Native"`, `"Unix"`, `"Windows"` - **Stable**: Yes ## `normalize_comments` diff --git a/src/config/mod.rs b/src/config/mod.rs index 42686483419..f240c7b13c6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -39,7 +39,7 @@ create_config! { max_width: usize, 100, true, "Maximum width of each line"; hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; tab_spaces: usize, 4, true, "Number of spaces per tab"; - newline_style: NewlineStyle, NewlineStyle::Native, true, "Unix or Windows line endings"; + newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings"; use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ formatting for items and expressions if they satisfy a heuristic notion of 'small'"; indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; diff --git a/src/config/options.rs b/src/config/options.rs index c48f9a4d727..f17e95e57e6 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -105,11 +105,68 @@ macro_rules! configuration_option_enum{ } configuration_option_enum! { NewlineStyle: + Auto, // Auto-detect based on the raw source input Windows, // \r\n Unix, // \n Native, // \r\n in Windows, \n on other platforms } +impl NewlineStyle { + fn auto_detect(raw_input_text: &str) -> NewlineStyle { + if let Some(pos) = raw_input_text.find('\n') { + let pos = pos.saturating_sub(1); + if let Some('\r') = raw_input_text.chars().nth(pos) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + NewlineStyle::Native + } + } + + fn native() -> NewlineStyle { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } + + /// Apply this newline style to the formatted text. When the style is set + /// to `Auto`, the `raw_input_text` is used to detect the existing line + /// endings. + /// + /// If the style is set to `Auto` and `raw_input_text` contains no + /// newlines, the `Native` style will be used. + pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { + use NewlineStyle::*; + let mut style = self; + if style == Auto { + style = Self::auto_detect(raw_input_text); + } + if style == Native { + style = Self::native(); + } + match style { + Windows => { + let mut transformed = String::with_capacity(formatted_text.capacity()); + for c in formatted_text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } + } + *formatted_text = transformed; + } + Unix => return, + Native => unreachable!("NewlineStyle::Native"), + Auto => unreachable!("NewlineStyle::Auto"), + } + } +} + configuration_option_enum! { BraceStyle: AlwaysNextLine, PreferSameLine, @@ -367,3 +424,59 @@ impl Edition { } } } + +#[test] +fn test_newline_style_auto_detect() { + let lf = "One\nTwo\nThree"; + let crlf = "One\r\nTwo\r\nThree"; + let none = "One Two Three"; + + assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf)); + assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf)); + assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none)); +} + +#[test] +fn test_newline_style_auto_apply() { + let auto = NewlineStyle::Auto; + + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One\nTwo\nThree"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); + + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One\r\nTwo\r\nThree"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); + + #[cfg(not(windows))] + { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!( + "One\nTwo\nThree", &out, + "auto-native-unix should detect 'lf'" + ); + } + + #[cfg(windows)] + { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!( + "One\r\nTwo\r\nThree", &out, + "auto-native-windows should detect 'crlf'" + ); + } +} diff --git a/src/formatting.rs b/src/formatting.rs index ceada0d4040..d29c9398174 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -13,7 +13,7 @@ use syntax::errors::Handler; use syntax::parse::{self, ParseSess}; use comment::{CharClasses, FullCodeCharKind}; -use config::{Config, FileName, NewlineStyle, Verbosity}; +use config::{Config, FileName, Verbosity}; use issues::BadIssueSeeker; use visitor::{FmtVisitor, SnippetProvider}; use {filemap, modules, ErrorKind, FormatReport, Input, Session}; @@ -166,7 +166,9 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &self.config, &self.report, ); - replace_with_system_newlines(&mut visitor.buffer, &self.config); + self.config + .newline_style() + .apply(&mut visitor.buffer, &big_snippet); if visitor.macro_rewrite_failure { self.report.add_macro_format_failure(); @@ -645,34 +647,6 @@ fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { ParseSess::with_span_handler(tty_handler, codemap) } -fn replace_with_system_newlines(text: &mut String, config: &Config) -> () { - let style = if config.newline_style() == NewlineStyle::Native { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - config.newline_style() - }; - - match style { - NewlineStyle::Unix => return, - NewlineStyle::Windows => { - let mut transformed = String::with_capacity(text.capacity()); - for c in text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } - } - *text = transformed; - } - NewlineStyle::Native => unreachable!(), - } -} - fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) where F: Fn(), -- cgit 1.4.1-3-g733a5 From 0b25f602fd60dc0961d8e507919328889ceeb32e Mon Sep 17 00:00:00 2001 From: Ben Brittain Date: Sun, 29 Jul 2018 07:37:24 -0700 Subject: Format Async block and async fn --- src/expr.rs | 23 +++++++++++++++++++++-- src/items.rs | 5 +++++ src/utils.rs | 8 ++++++++ src/visitor.rs | 1 - 4 files changed, 34 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 6814b91e053..05020a419a9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -345,8 +345,27 @@ pub fn format_expr( } // FIXME(#2743) ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), - // FIXME(topecongiro) Format async block. - ast::ExprKind::Async(..) => None, + ast::ExprKind::Async(_capture_by, _node_id, ref block) => { + if let rw @ Some(_) = + rewrite_single_line_block(context, "async ", block, Some(&expr.attrs), None, shape) + { + rw + } else { + // 6 = `async ` + let budget = shape.width.saturating_sub(6); + Some(format!( + "{}{}", + "async ", + rewrite_block( + block, + Some(&expr.attrs), + None, + context, + Shape::legacy(budget, shape.indent) + )? + )) + } + } }; expr_rw diff --git a/src/items.rs b/src/items.rs index 8c32d393df4..3076082d037 100644 --- a/src/items.rs +++ b/src/items.rs @@ -164,6 +164,7 @@ pub struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, abi: abi::Abi, + asyncness: ast::IsAsync, constness: ast::Constness, defaultness: ast::Defaultness, unsafety: ast::Unsafety, @@ -180,6 +181,7 @@ impl<'a> FnSig<'a> { decl, generics, abi: abi::Abi::Rust, + asyncness: ast::IsAsync::NotAsync, constness: ast::Constness::NotConst, defaultness: ast::Defaultness::Final, unsafety: ast::Unsafety::Normal, @@ -193,6 +195,7 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, + asyncness: method_sig.header.asyncness, constness: method_sig.header.constness.node, defaultness: ast::Defaultness::Final, abi: method_sig.header.abi, @@ -214,6 +217,7 @@ impl<'a> FnSig<'a> { generics, abi: fn_header.abi, constness: fn_header.constness.node, + asyncness: fn_header.asyncness, defaultness, unsafety: fn_header.unsafety, visibility: visibility.clone(), @@ -235,6 +239,7 @@ impl<'a> FnSig<'a> { // Vis defaultness constness unsafety abi. result.push_str(&*format_visibility(context, &self.visibility)); result.push_str(format_defaultness(self.defaultness)); + result.push_str(format_asyncness(self.asyncness)); result.push_str(format_constness(self.constness)); result.push_str(format_unsafety(self.unsafety)); result.push_str(&format_abi( diff --git a/src/utils.rs b/src/utils.rs index b8474792cd3..3dbffd6d175 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -81,6 +81,14 @@ pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'sta } } +#[inline] +pub fn format_asyncness(asyncness: ast::IsAsync) -> &'static str { + match asyncness { + ast::IsAsync::Async { .. } => "async ", + ast::IsAsync::NotAsync => "", + } +} + #[inline] pub fn format_constness(constness: ast::Constness) -> &'static str { match constness { diff --git a/src/visitor.rs b/src/visitor.rs index fdbc9907f22..903fe039b1b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -253,7 +253,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. - // FIXME(topecongiro) Format async fn (#2812). fn visit_fn( &mut self, fk: visit::FnKind, -- cgit 1.4.1-3-g733a5 From fedde3790c32c4956b06ae45699f0f76b4502865 Mon Sep 17 00:00:00 2001 From: Ben Brittain Date: Sun, 29 Jul 2018 08:45:31 -0700 Subject: Add tests for async & async move --- src/expr.rs | 21 ++++++++++++++++----- src/items.rs | 2 +- tests/source/async_block.rs | 7 +++++++ tests/source/async_fn.rs | 15 +++++++++++++++ tests/target/async_block.rs | 5 +++++ tests/target/async_fn.rs | 13 +++++++++++++ 6 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 tests/source/async_block.rs create mode 100644 tests/source/async_fn.rs create mode 100644 tests/target/async_block.rs create mode 100644 tests/target/async_fn.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 05020a419a9..65284182cb2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -345,17 +345,28 @@ pub fn format_expr( } // FIXME(#2743) ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), - ast::ExprKind::Async(_capture_by, _node_id, ref block) => { - if let rw @ Some(_) = - rewrite_single_line_block(context, "async ", block, Some(&expr.attrs), None, shape) - { + ast::ExprKind::Async(capture_by, _node_id, ref block) => { + let mover = if capture_by == ast::CaptureBy::Value { + "move " + } else { + "" + }; + if let rw @ Some(_) = rewrite_single_line_block( + context, + format!("{}{}", "async ", mover).as_str(), + block, + Some(&expr.attrs), + None, + shape, + ) { rw } else { // 6 = `async ` let budget = shape.width.saturating_sub(6); Some(format!( - "{}{}", + "{}{}{}", "async ", + mover, rewrite_block( block, Some(&expr.attrs), diff --git a/src/items.rs b/src/items.rs index 3076082d037..47e35fb101d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -239,9 +239,9 @@ impl<'a> FnSig<'a> { // Vis defaultness constness unsafety abi. result.push_str(&*format_visibility(context, &self.visibility)); result.push_str(format_defaultness(self.defaultness)); - result.push_str(format_asyncness(self.asyncness)); result.push_str(format_constness(self.constness)); result.push_str(format_unsafety(self.unsafety)); + result.push_str(format_asyncness(self.asyncness)); result.push_str(&format_abi( self.abi, context.config.force_explicit_abi(), diff --git a/tests/source/async_block.rs b/tests/source/async_block.rs new file mode 100644 index 00000000000..69e9892fbf7 --- /dev/null +++ b/tests/source/async_block.rs @@ -0,0 +1,7 @@ +// rustfmt-edition: Edition2018 + +fn main() { + let x = async { + Ok(()) + }; +} diff --git a/tests/source/async_fn.rs b/tests/source/async_fn.rs new file mode 100644 index 00000000000..651cca7c340 --- /dev/null +++ b/tests/source/async_fn.rs @@ -0,0 +1,15 @@ +// rustfmt-edition: Edition2018 + +async fn bar() -> Result<(), ()> { + Ok(()) +} + +pub async fn baz() -> Result<(), ()> { + Ok(()) +} + +unsafe async fn foo() { + async move { + Ok(()) + } +} diff --git a/tests/target/async_block.rs b/tests/target/async_block.rs new file mode 100644 index 00000000000..1bc24d1de15 --- /dev/null +++ b/tests/target/async_block.rs @@ -0,0 +1,5 @@ +// rustfmt-edition: Edition2018 + +fn main() { + let x = async { Ok(()) }; +} diff --git a/tests/target/async_fn.rs b/tests/target/async_fn.rs new file mode 100644 index 00000000000..a6e7cbc44b2 --- /dev/null +++ b/tests/target/async_fn.rs @@ -0,0 +1,13 @@ +// rustfmt-edition: Edition2018 + +async fn bar() -> Result<(), ()> { + Ok(()) +} + +pub async fn baz() -> Result<(), ()> { + Ok(()) +} + +unsafe async fn foo() { + async move { Ok(()) } +} -- cgit 1.4.1-3-g733a5 From 46b241004dbc4d6f77e81868304af4e79df9fe6f Mon Sep 17 00:00:00 2001 From: Benjamin Brittain Date: Sun, 29 Jul 2018 17:20:11 -0700 Subject: fix nits --- src/items.rs | 10 +++++----- src/utils.rs | 4 ++-- tests/source/async_block.rs | 12 ++++++++++++ tests/source/async_fn.rs | 6 ++++++ tests/target/async_block.rs | 10 ++++++++++ tests/target/async_fn.rs | 7 +++++++ 6 files changed, 42 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 47e35fb101d..b352294d3f3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -164,7 +164,7 @@ pub struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, abi: abi::Abi, - asyncness: ast::IsAsync, + is_async: ast::IsAsync, constness: ast::Constness, defaultness: ast::Defaultness, unsafety: ast::Unsafety, @@ -181,7 +181,7 @@ impl<'a> FnSig<'a> { decl, generics, abi: abi::Abi::Rust, - asyncness: ast::IsAsync::NotAsync, + is_async: ast::IsAsync::NotAsync, constness: ast::Constness::NotConst, defaultness: ast::Defaultness::Final, unsafety: ast::Unsafety::Normal, @@ -195,7 +195,7 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, - asyncness: method_sig.header.asyncness, + is_async: method_sig.header.asyncness, constness: method_sig.header.constness.node, defaultness: ast::Defaultness::Final, abi: method_sig.header.abi, @@ -217,7 +217,7 @@ impl<'a> FnSig<'a> { generics, abi: fn_header.abi, constness: fn_header.constness.node, - asyncness: fn_header.asyncness, + is_async: fn_header.asyncness, defaultness, unsafety: fn_header.unsafety, visibility: visibility.clone(), @@ -241,7 +241,7 @@ impl<'a> FnSig<'a> { result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); result.push_str(format_unsafety(self.unsafety)); - result.push_str(format_asyncness(self.asyncness)); + result.push_str(format_async(self.is_async)); result.push_str(&format_abi( self.abi, context.config.force_explicit_abi(), diff --git a/src/utils.rs b/src/utils.rs index 3dbffd6d175..5f92255e79c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -82,8 +82,8 @@ pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'sta } #[inline] -pub fn format_asyncness(asyncness: ast::IsAsync) -> &'static str { - match asyncness { +pub fn format_async(is_async: ast::IsAsync) -> &'static str { + match is_async { ast::IsAsync::Async { .. } => "async ", ast::IsAsync::NotAsync => "", } diff --git a/tests/source/async_block.rs b/tests/source/async_block.rs index 69e9892fbf7..5e05e58c6c1 100644 --- a/tests/source/async_block.rs +++ b/tests/source/async_block.rs @@ -5,3 +5,15 @@ fn main() { Ok(()) }; } + +fn baz() { + // test + let x = async { + // async blocks are great + Ok(()) + }; + + let y = async { + Ok(()) + }; // comment +} diff --git a/tests/source/async_fn.rs b/tests/source/async_fn.rs index 651cca7c340..cae9d5badaf 100644 --- a/tests/source/async_fn.rs +++ b/tests/source/async_fn.rs @@ -13,3 +13,9 @@ unsafe async fn foo() { Ok(()) } } + +unsafe async fn rust() { + async move { // comment + Ok(()) + } +} diff --git a/tests/target/async_block.rs b/tests/target/async_block.rs index 1bc24d1de15..611c719e95f 100644 --- a/tests/target/async_block.rs +++ b/tests/target/async_block.rs @@ -3,3 +3,13 @@ fn main() { let x = async { Ok(()) }; } + +fn baz() { + // test + let x = async { + // async blocks are great + Ok(()) + }; + + let y = async { Ok(()) }; // comment +} diff --git a/tests/target/async_fn.rs b/tests/target/async_fn.rs index a6e7cbc44b2..e23f04d28c0 100644 --- a/tests/target/async_fn.rs +++ b/tests/target/async_fn.rs @@ -11,3 +11,10 @@ pub async fn baz() -> Result<(), ()> { unsafe async fn foo() { async move { Ok(()) } } + +unsafe async fn rust() { + async move { + // comment + Ok(()) + } +} -- cgit 1.4.1-3-g733a5 From d43874113e6b9fc604dbacfd202d2a913a11fef4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 31 Jul 2018 10:02:32 +1200 Subject: Warn the user if using an unstable option without `--unstable-options` Fixes #2796 --- src/bin/main.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 049749f8f52..05752055e06 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -473,6 +473,25 @@ impl GetOptsOptions { if let Some(ref file_lines) = matches.opt_str("file-lines") { options.file_lines = file_lines.parse().map_err(err_msg)?; } + } else { + let mut unstable_options = vec![]; + if matches.opt_present("skip-children") { + unstable_options.push("`--skip-children`"); + } + if matches.opt_present("error-on-unformatted") { + unstable_options.push("`--error-on-unformatted`"); + } + if matches.opt_present("file-lines") { + unstable_options.push("`--file-lines`"); + } + if !unstable_options.is_empty() { + let s = if unstable_options.len() == 1 { "" } else { "s" }; + return Err(format_err!( + "Unstable option{} ({}) used without `--unstable-features`", + s, + unstable_options.join(", "), + )); + } } options.config_path = matches.opt_str("config-path").map(PathBuf::from); -- cgit 1.4.1-3-g733a5 From ca6b360c8a2c40bec3cf04bb4c9198ad30779309 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 31 Jul 2018 13:41:49 +1200 Subject: Emit 0 exit code for --version and similar operations Fixes #2878 --- src/bin/main.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 05752055e06..7faa8557352 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -172,19 +172,19 @@ fn execute(opts: &Options) -> Result { match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { print_usage_to_stdout(opts, ""); - return Ok(1); + return Ok(0); } Operation::Help(HelpOp::Config) => { Config::print_docs(&mut stdout(), options.unstable_features); - return Ok(1); + return Ok(0); } Operation::Help(HelpOp::FileLines) => { print_help_file_lines(); - return Ok(1); + return Ok(0); } Operation::Version => { print_version(); - return Ok(1); + return Ok(0); } Operation::ConfigOutputDefault { path } => { let toml = Config::default().all_options().to_toml().map_err(err_msg)?; @@ -194,7 +194,7 @@ fn execute(opts: &Options) -> Result { } else { io::stdout().write_all(toml.as_bytes())?; } - return Ok(1); + return Ok(0); } Operation::Stdin { input } => format_string(input, options), Operation::Format { -- cgit 1.4.1-3-g733a5 From dab572e0b0c3ee7373d51a76af5bdf0c7e81ce68 Mon Sep 17 00:00:00 2001 From: Aaron Loucks Date: Mon, 30 Jul 2018 23:19:46 -0400 Subject: Increase capacity for newline conversion buffer --- src/config/options.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index f17e95e57e6..d2a74f54677 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -150,7 +150,7 @@ impl NewlineStyle { } match style { Windows => { - let mut transformed = String::with_capacity(formatted_text.capacity()); + let mut transformed = String::with_capacity(2 * formatted_text.capacity()); for c in formatted_text.chars() { match c { '\n' => transformed.push_str("\r\n"), -- cgit 1.4.1-3-g733a5 From c25deef110dc258ef6696daca9db228bd37c2d4b Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 31 Jul 2018 11:50:09 +0100 Subject: Fix check for unstable features These features are registered only on Nightly and so matches.opt_present panics when it's called without the is_nightly guard. --- src/bin/main.rs | 59 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 7faa8557352..96237d533a2 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -459,38 +459,39 @@ impl GetOptsOptions { let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") .map(|c| c == "nightly") .unwrap_or(false); + if rust_nightly { options.unstable_features = matches.opt_present("unstable-features"); - } - if options.unstable_features { - if matches.opt_present("skip-children") { - options.skip_children = Some(true); - } - if matches.opt_present("error-on-unformatted") { - options.error_on_unformatted = Some(true); - } - if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse().map_err(err_msg)?; - } - } else { - let mut unstable_options = vec![]; - if matches.opt_present("skip-children") { - unstable_options.push("`--skip-children`"); - } - if matches.opt_present("error-on-unformatted") { - unstable_options.push("`--error-on-unformatted`"); - } - if matches.opt_present("file-lines") { - unstable_options.push("`--file-lines`"); - } - if !unstable_options.is_empty() { - let s = if unstable_options.len() == 1 { "" } else { "s" }; - return Err(format_err!( - "Unstable option{} ({}) used without `--unstable-features`", - s, - unstable_options.join(", "), - )); + if options.unstable_features { + if matches.opt_present("skip-children") { + options.skip_children = Some(true); + } + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = Some(true); + } + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse().map_err(err_msg)?; + } + } else { + let mut unstable_options = vec![]; + if matches.opt_present("skip-children") { + unstable_options.push("`--skip-children`"); + } + if matches.opt_present("error-on-unformatted") { + unstable_options.push("`--error-on-unformatted`"); + } + if matches.opt_present("file-lines") { + unstable_options.push("`--file-lines`"); + } + if !unstable_options.is_empty() { + let s = if unstable_options.len() == 1 { "" } else { "s" }; + return Err(format_err!( + "Unstable option{} ({}) used without `--unstable-features`", + s, + unstable_options.join(", "), + )); + } } } -- cgit 1.4.1-3-g733a5 From 593a5c40a4c8c255ca15969d9ba15760cbc86391 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 31 Jul 2018 11:53:22 +0100 Subject: Use is_nightly helper instead of duplicate code --- src/bin/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 96237d533a2..e5f5b625eba 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -456,9 +456,7 @@ impl GetOptsOptions { return Err(format_err!("Can't use both `--verbose` and `--quiet`")); } - let rust_nightly = option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") - .unwrap_or(false); + let rust_nightly = is_nightly(); if rust_nightly { options.unstable_features = matches.opt_present("unstable-features"); -- cgit 1.4.1-3-g733a5 From 1928ae78a26caf25da807f1bc13e92191d1a37f7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 3 Aug 2018 20:06:36 +0900 Subject: Regard digits as an upper case character --- src/imports.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 93f2ac8867a..cfb4ecc648b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -597,7 +597,8 @@ impl Ord for UseSegment { use self::UseSegment::*; fn is_upper_snake_case(s: &str) -> bool { - s.chars().all(|c| c.is_uppercase() || c == '_') + s.chars() + .all(|c| c.is_uppercase() || c == '_' || c.is_numeric()) } match (self, other) { -- cgit 1.4.1-3-g733a5 From 024c03e81bb576c0063857263b2595ca0980ecf4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 3 Aug 2018 22:13:20 +0900 Subject: Use builder pattern for ListFormatting --- src/attr.rs | 14 +++--------- src/closures.rs | 14 +++--------- src/expr.rs | 30 +++++++------------------ src/imports.rs | 24 +++++++++----------- src/items.rs | 69 ++++++++++++++++++--------------------------------------- src/lists.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/macros.rs | 15 ++++--------- src/matches.rs | 16 ++++--------- src/overflow.rs | 45 +++++++++++++++++-------------------- src/patterns.rs | 4 ++-- src/reorder.rs | 15 ++----------- src/types.rs | 24 ++++++++------------ src/vertical.rs | 15 ++++--------- 13 files changed, 148 insertions(+), 204 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 555c0eb96e7..c83e9808d0d 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -296,17 +296,9 @@ where let tactic = ::lists::definitive_tactic(&item_vec, tactic, ::lists::Separator::Comma, shape.width); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: false, - preserve_newline: false, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(shape, context.config) + .tactic(tactic) + .ends_with_newline(false); let item_str = write_list(&item_vec, &fmt)?; let one_line_budget = one_line_shape.width; diff --git a/src/closures.rs b/src/closures.rs index c03c8e6b606..1a4a6e44fdf 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -270,17 +270,9 @@ fn rewrite_closure_fn_decl( _ => arg_shape, }; - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arg_shape, - ends_with_newline: false, - preserve_newline: true, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(arg_shape, context.config) + .tactic(tactic) + .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str); diff --git a/src/expr.rs b/src/expr.rs index 72cf618dca5..0f4474d7c0f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1197,17 +1197,11 @@ pub fn rewrite_multiple_patterns( shape.width, ) }; - let fmt = ListFormatting { - tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - separator_place: context.config.binop_separator(), - shape, - ends_with_newline: false, - preserve_newline: false, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(shape, context.config) + .tactic(tactic) + .separator(" |") + .separator_place(context.config.binop_separator()) + .ends_with_newline(false); write_list(&items, &fmt) } @@ -1760,17 +1754,9 @@ where Separator::Comma, nested_shape.width, ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: false, - preserve_newline: false, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(shape, context.config) + .tactic(tactic) + .ends_with_newline(false); let list_str = write_list(&item_vec, &fmt)?; Some(format!("({})", list_str)) diff --git a/src/imports.rs b/src/imports.rs index 93f2ac8867a..564f755fa08 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -713,21 +713,17 @@ fn rewrite_nested_use_tree( let ends_with_newline = context.config.imports_indent() == IndentStyle::Block && tactic != DefinitiveListTactic::Horizontal; - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if ends_with_newline { - context.config.trailing_comma() - } else { - SeparatorTactic::Never - }, - separator_place: SeparatorPlace::Back, - shape: nested_shape, - ends_with_newline, - preserve_newline: true, - nested: has_nested_list, - config: context.config, + let trailing_separator = if ends_with_newline { + context.config.trailing_comma() + } else { + SeparatorTactic::Never }; + let fmt = ListFormatting::new(nested_shape, context.config) + .tactic(tactic) + .trailing_separator(trailing_separator) + .ends_with_newline(ends_with_newline) + .preserve_newline(true) + .nested(has_nested_list); let list_str = write_list(&list_items, &fmt)?; diff --git a/src/items.rs b/src/items.rs index b352294d3f3..0152fb8794c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -529,17 +529,9 @@ impl<'a> FmtVisitor<'a> { } let shape = self.shape().sub_width(2)?; - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: ",", - trailing_separator: self.config.trailing_comma(), - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: true, - preserve_newline: true, - nested: false, - config: self.config, - }; + let fmt = ListFormatting::new(shape, self.config) + .trailing_separator(self.config.trailing_comma()) + .preserve_newline(true); let list = write_list(&items, &fmt)?; result.push_str(&list); @@ -2360,22 +2352,16 @@ fn rewrite_args( debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if variadic { - SeparatorTactic::Never - } else { - trailing_comma - }, - separator_place: SeparatorPlace::Back, - shape: Shape::legacy(budget, indent), - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - nested: false, - config: context.config, + let trailing_separator = if variadic { + SeparatorTactic::Never + } else { + trailing_comma }; - + let fmt = ListFormatting::new(Shape::legacy(budget, indent), context.config) + .tactic(tactic) + .trailing_separator(trailing_separator) + .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) + .preserve_newline(true); write_list(&arg_items, &fmt) } @@ -2551,17 +2537,10 @@ fn rewrite_where_clause_rfc_style( DefinitiveListTactic::Vertical }; - let fmt = ListFormatting { - tactic: shape_tactic, - separator: ",", - trailing_separator: comma_tactic, - separator_place: SeparatorPlace::Back, - shape: clause_shape, - ends_with_newline: true, - preserve_newline: true, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(clause_shape, context.config) + .tactic(shape_tactic) + .trailing_separator(comma_tactic) + .preserve_newline(true); let preds_str = write_list(&items.collect::>(), &fmt)?; let comment_separator = |comment: &str, shape: Shape| { @@ -2666,17 +2645,11 @@ fn rewrite_where_clause( comma_tactic = SeparatorTactic::Never; } - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: comma_tactic, - separator_place: SeparatorPlace::Back, - shape: Shape::legacy(budget, offset), - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(Shape::legacy(budget, offset), context.config) + .tactic(tactic) + .trailing_separator(comma_tactic) + .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) + .preserve_newline(true); let preds_str = write_list(&item_vec, &fmt)?; let end_length = if terminator == "{" { diff --git a/src/lists.rs b/src/lists.rs index 0e3baa7c1e1..1ffa2093965 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -24,22 +24,71 @@ use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_wit use visitor::SnippetProvider; pub struct ListFormatting<'a> { - pub tactic: DefinitiveListTactic, - pub separator: &'a str, - pub trailing_separator: SeparatorTactic, - pub separator_place: SeparatorPlace, - pub shape: Shape, + pub(self) tactic: DefinitiveListTactic, + pub(self) separator: &'a str, + pub(self) trailing_separator: SeparatorTactic, + pub(self) separator_place: SeparatorPlace, + pub(self) shape: Shape, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. - pub ends_with_newline: bool, + pub(self) ends_with_newline: bool, // Remove newlines between list elements for expressions. - pub preserve_newline: bool, + pub(self) preserve_newline: bool, // Nested import lists get some special handling for the "Mixed" list type - pub nested: bool, - pub config: &'a Config, + pub(self) nested: bool, + pub(self) config: &'a Config, } impl<'a> ListFormatting<'a> { + pub fn new(shape: Shape, config: &'a Config) -> Self { + ListFormatting { + tactic: DefinitiveListTactic::Vertical, + separator: ",", + trailing_separator: SeparatorTactic::Never, + separator_place: SeparatorPlace::Back, + shape, + ends_with_newline: true, + preserve_newline: false, + nested: false, + config: config, + } + } + + pub fn tactic(mut self, tactic: DefinitiveListTactic) -> Self { + self.tactic = tactic; + self + } + + pub fn separator(mut self, separator: &'a str) -> Self { + self.separator = separator; + self + } + + pub fn trailing_separator(mut self, trailing_separator: SeparatorTactic) -> Self { + self.trailing_separator = trailing_separator; + self + } + + pub fn separator_place(mut self, separator_place: SeparatorPlace) -> Self { + self.separator_place = separator_place; + self + } + + pub fn ends_with_newline(mut self, ends_with_newline: bool) -> Self { + self.ends_with_newline = ends_with_newline; + self + } + + pub fn preserve_newline(mut self, preserve_newline: bool) -> Self { + self.preserve_newline = preserve_newline; + self + } + + pub fn nested(mut self, nested: bool) -> Self { + self.nested = nested; + self + } + pub fn needs_trailing_separator(&self) -> bool { match self.trailing_separator { // We always put separator in front. diff --git a/src/macros.rs b/src/macros.rs index f00bb339cb0..b32de753fda 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -412,17 +412,10 @@ pub fn rewrite_macro_def( false, ).collect::>(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: if def.legacy { ";" } else { "" }, - trailing_separator: SeparatorTactic::Always, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(arm_shape, context.config) + .separator(if def.legacy { ";" } else { "" }) + .trailing_separator(SeparatorTactic::Always) + .preserve_newline(true); if multi_branch_style { result += " {"; diff --git a/src/matches.rs b/src/matches.rs index 791f34cefe8..29e9f19ad7d 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -215,18 +215,10 @@ fn rewrite_match_arms( false, ); let arms_vec: Vec<_> = items.collect(); - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape: arm_shape, - ends_with_newline: true, - preserve_newline: true, - nested: false, - config: context.config, - }; + // We will add/remove commas inside `arm.rewrite()`, and hence no separator here. + let fmt = ListFormatting::new(arm_shape, context.config) + .separator("") + .preserve_newline(true); write_list(&arms_vec, &fmt) } diff --git a/src/overflow.rs b/src/overflow.rs index 54e594d814f..e18fe140c8d 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -363,32 +363,27 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { // indentation. If its first line fits on one line with the other arguments, // we format the function arguments horizontally. let tactic = self.try_overflow_last_item(&mut list_items); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if let Some(tactic) = self.force_separator_tactic { - tactic - } else if !self.context.use_block_indent() { - SeparatorTactic::Never - } else if tactic == DefinitiveListTactic::Mixed { - // We are using mixed layout because everything did not fit within a single line. - SeparatorTactic::Always - } else { - self.context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape: self.nested_shape, - ends_with_newline: match tactic { - DefinitiveListTactic::Vertical | DefinitiveListTactic::Mixed => { - self.context.use_block_indent() - } - _ => false, - }, - preserve_newline: false, - nested: false, - config: self.context.config, + let trailing_separator = if let Some(tactic) = self.force_separator_tactic { + tactic + } else if !self.context.use_block_indent() { + SeparatorTactic::Never + } else if tactic == DefinitiveListTactic::Mixed { + // We are using mixed layout because everything did not fit within a single line. + SeparatorTactic::Always + } else { + self.context.config.trailing_comma() }; + let ends_with_newline = match tactic { + DefinitiveListTactic::Vertical | DefinitiveListTactic::Mixed => { + self.context.use_block_indent() + } + _ => false, + }; + + let fmt = ListFormatting::new(self.nested_shape, self.context.config) + .tactic(tactic) + .trailing_separator(trailing_separator) + .ends_with_newline(ends_with_newline); write_list(&list_items, &fmt) .map(|items_str| (tactic == DefinitiveListTactic::Horizontal, items_str)) diff --git a/src/patterns.rs b/src/patterns.rs index dbe0c8a6f66..7ab43def8c7 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -214,7 +214,7 @@ fn rewrite_struct_pat( if ellipsis { if fields_str.contains('\n') || fields_str.len() > one_line_width { // Add a missing trailing comma. - if fmt.trailing_separator == SeparatorTactic::Never { + if context.config.trailing_comma() == SeparatorTactic::Never { fields_str.push_str(","); } fields_str.push_str("\n"); @@ -223,7 +223,7 @@ fn rewrite_struct_pat( } else { if !fields_str.is_empty() { // there are preceding struct fields being matched on - if fmt.tactic == DefinitiveListTactic::Vertical { + if tactic == DefinitiveListTactic::Vertical { // if the tactic is Vertical, write_list already added a trailing , fields_str.push_str(" "); } else { diff --git a/src/reorder.rs b/src/reorder.rs index 48ddd116337..bc429a10ab6 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -16,7 +16,7 @@ // FIXME(#2455): Reorder trait items. -use config::{lists::*, Config}; +use config::Config; use syntax::{ast, attr, codemap::Span}; use attr::filter_inline_attrs; @@ -69,18 +69,7 @@ fn wrap_reorderable_items( list_items: &[ListItem], shape: Shape, ) -> Option { - let fmt = ListFormatting { - tactic: DefinitiveListTactic::Vertical, - separator: "", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: true, - preserve_newline: false, - nested: false, - config: context.config, - }; - + let fmt = ListFormatting::new(shape, context.config).separator(""); write_list(list_items, &fmt) } diff --git a/src/types.rs b/src/types.rs index 5d57b99d32d..360c7304988 100644 --- a/src/types.rs +++ b/src/types.rs @@ -360,23 +360,17 @@ where Separator::Comma, budget, ); - - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: if !context.use_block_indent() || variadic { - SeparatorTactic::Never - } else { - context.config.trailing_comma() - }, - separator_place: SeparatorPlace::Back, - shape: list_shape, - ends_with_newline: tactic.ends_with_newline(context.config.indent_style()), - preserve_newline: true, - nested: false, - config: context.config, + let trailing_separator = if !context.use_block_indent() || variadic { + SeparatorTactic::Never + } else { + context.config.trailing_comma() }; + let fmt = ListFormatting::new(list_shape, context.config) + .tactic(tactic) + .trailing_separator(trailing_separator) + .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) + .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; let ty_shape = match context.config.indent_style() { diff --git a/src/vertical.rs b/src/vertical.rs index ead5719f61f..c6721bc5010 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -245,17 +245,10 @@ fn rewrite_aligned_items_inner( one_line_width, ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: context.config.trailing_comma(), - separator_place: SeparatorPlace::Back, - shape: item_shape, - ends_with_newline: true, - preserve_newline: true, - nested: false, - config: context.config, - }; + let fmt = ListFormatting::new(item_shape, context.config) + .tactic(tactic) + .trailing_separator(context.config.trailing_comma()) + .preserve_newline(true); write_list(&items, &fmt) } -- cgit 1.4.1-3-g733a5 From e5c79bb26bcb56bfa5eb846cb8707b90955cd747 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 3 Aug 2018 22:14:45 +0900 Subject: Fix imports --- src/attr.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index c83e9808d0d..2ec47d30572 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -14,7 +14,7 @@ use comment::{contains_comment, rewrite_doc_comment}; use config::lists::*; use config::IndentStyle; use expr::rewrite_literal; -use lists::{itemize_list, write_list, ListFormatting}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use types::{rewrite_path, PathContext}; @@ -294,8 +294,7 @@ where ListTactic::HorizontalVertical }; - let tactic = - ::lists::definitive_tactic(&item_vec, tactic, ::lists::Separator::Comma, shape.width); + let tactic = definitive_tactic(&item_vec, tactic, Separator::Comma, shape.width); let fmt = ListFormatting::new(shape, context.config) .tactic(tactic) .ends_with_newline(false); -- cgit 1.4.1-3-g733a5 From 1a6df18d6f358dbe01b2dd4def94ff597f791590 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 4 Aug 2018 08:47:48 +0900 Subject: Remove pub(self) --- src/lists.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 1ffa2093965..f7a6f9944cd 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -24,19 +24,19 @@ use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_wit use visitor::SnippetProvider; pub struct ListFormatting<'a> { - pub(self) tactic: DefinitiveListTactic, - pub(self) separator: &'a str, - pub(self) trailing_separator: SeparatorTactic, - pub(self) separator_place: SeparatorPlace, - pub(self) shape: Shape, + tactic: DefinitiveListTactic, + separator: &'a str, + trailing_separator: SeparatorTactic, + separator_place: SeparatorPlace, + shape: Shape, // Non-expressions, e.g. items, will have a new line at the end of the list. // Important for comment styles. - pub(self) ends_with_newline: bool, + ends_with_newline: bool, // Remove newlines between list elements for expressions. - pub(self) preserve_newline: bool, + preserve_newline: bool, // Nested import lists get some special handling for the "Mixed" list type - pub(self) nested: bool, - pub(self) config: &'a Config, + nested: bool, + config: &'a Config, } impl<'a> ListFormatting<'a> { -- cgit 1.4.1-3-g733a5 From d96e3ca604a1299b7688e4008e28b76fb525f2be Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 4 Aug 2018 09:59:38 +0900 Subject: Explicitly handle semicolon after the item in statement position --- src/visitor.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 903fe039b1b..c80cd78a992 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -90,6 +90,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { match stmt.node { ast::StmtKind::Item(ref item) => { self.visit_item(item); + // Handle potential `;` after the item. + self.format_missing(stmt.span.hi()); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { if contains_skip(get_attrs_from_stmt(stmt)) { -- cgit 1.4.1-3-g733a5 From 2eca09e438c0d1471c9c602d63075d0405df8b10 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 4 Aug 2018 19:27:34 +0900 Subject: Fix parsing '#'-hiding of rustdoc --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index ed83a3925b0..5958349c6ad 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -500,7 +500,7 @@ fn rewrite_comment_inner( const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; fn hide_sharp_behind_comment<'a>(s: &'a str) -> Cow<'a, str> { - if s.trim_left().starts_with('#') { + if s.trim_left().starts_with("# ") { Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s)) } else { Cow::from(s) -- cgit 1.4.1-3-g733a5 From 2eeb3663116df5dbf2ed7291277d79c5ff201b89 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 10:50:34 +0900 Subject: Ignore comment in wrap_str --- src/comment.rs | 32 ++++++++++++++++++++++++++++++++ src/utils.rs | 3 ++- 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index ed83a3925b0..2e7402ed178 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1139,6 +1139,21 @@ pub fn recover_comment_removed( } } +pub fn filter_normal_code(code: &str) -> String { + let mut buffer = String::with_capacity(code.len()); + LineClasses::new(code).for_each(|(kind, line)| match kind { + FullCodeCharKind::Normal | FullCodeCharKind::InString => { + buffer.push_str(&line); + buffer.push('\n'); + } + _ => (), + }); + if !code.ends_with("\n") && buffer.ends_with("\n") { + buffer.pop(); + } + buffer +} + /// Return true if the two strings of code have the same payload of comments. /// The payload of comments is everything in the string except: /// - actual code (not comments) @@ -1392,4 +1407,21 @@ mod test { let s = format!(" r#\"\n test\n \"#"); assert_eq!(remove_trailing_white_spaces(&s), s); } + + #[test] + fn test_filter_normal_code() { + let s = r#" +fn main() { + println!("hello, world"); +} +"#; + assert_eq!(s, filter_normal_code(s)); + let s_with_comment = r#" +fn main() { + // hello, world + println!("hello, world"); +} +"#; + assert_eq!(s, filter_normal_code(s_with_comment)); + } } diff --git a/src/utils.rs b/src/utils.rs index 5f92255e79c..9eac3fd4f0d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,6 +18,7 @@ use syntax::ast::{ use syntax::codemap::{BytePos, Span, NO_EXPANSION}; use syntax::ptr; +use comment::filter_normal_code; use rewrite::RewriteContext; use shape::Shape; @@ -350,7 +351,7 @@ macro_rules! skip_out_of_file_lines_range_visitor { // Wraps String in an Option. Returns Some when the string adheres to the // Rewrite constraints defined for the Rewrite trait and None otherwise. pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { - if is_valid_str(&s, max_width, shape) { + if is_valid_str(&filter_normal_code(&s), max_width, shape) { Some(s) } else { None -- cgit 1.4.1-3-g733a5 From c5b36f53ae8ec42daf0c364958cc01c4f0c04063 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 4 Aug 2018 23:58:34 +0900 Subject: Normalize chain elements Instead of passing around a list of subexpressions ([`a`, `a.b`, `a.b.c`]), we now use a list of chain element ([`a`, `.b`, `.c`]). This should make it easier to extract comments between chain elements. --- src/chains.rs | 144 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 80 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 7acb9b9126f..ce0940362ff 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -99,61 +99,33 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - // An expression plus trailing `?`s to be formatted together. #[derive(Debug)] struct ChainItem { - // FIXME: we can't use a reference here because to convert `try!` to `?` we - // synthesise the AST node. However, I think we could use `Cow` and that - // would remove a lot of cloning. - expr: ast::Expr, + kind: ChainItemKind, tries: usize, } -impl Rewrite for ChainItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let rewrite = self.expr.rewrite(context, shape.sub_width(self.tries)?)?; - Some(format!("{}{}", rewrite, "?".repeat(self.tries))) - } +// FIXME: we can't use a reference here because to convert `try!` to `?` we +// synthesise the AST node. However, I think we could use `Cow` and that +// would remove a lot of cloning. +#[derive(Debug)] +enum ChainItemKind { + Parent(ast::Expr), + MethodCall( + ast::PathSegment, + Vec, + Vec>, + Span, + ), + StructField(ast::Ident), + TupleField(ast::Ident, bool), } -impl ChainItem { - // Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite - // `.c` and any trailing `?`s. - fn rewrite_postfix(&self, context: &RewriteContext, shape: Shape) -> Option { - let shape = shape.sub_width(self.tries)?; - let mut rewrite = match self.expr.node { - ast::ExprKind::MethodCall(ref segment, ref expressions) => { - let types = match segment.args { - Some(ref params) => match **params { - ast::GenericArgs::AngleBracketed(ref data) => &data.args[..], - _ => &[], - }, - _ => &[], - }; - Self::rewrite_method_call( - segment.ident, - types, - expressions, - self.expr.span, - context, - shape, - )? - } - ast::ExprKind::Field(ref nested, ref field) => { - let space = - if Self::is_tup_field_access(&self.expr) && Self::is_tup_field_access(nested) { - " " - } else { - "" - }; - let result = format!("{}.{}", space, field.name); - if result.len() <= shape.width { - result - } else { - return None; - } - } - _ => unreachable!(), - }; - rewrite.push_str(&"?".repeat(self.tries)); - Some(rewrite) +impl ChainItemKind { + fn is_block_like(&self, context: &RewriteContext, reps: &str) -> bool { + match self { + ChainItemKind::Parent(ref expr) => is_block_expr(context, expr, reps), + ChainItemKind::MethodCall(..) => reps.contains('\n'), + ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) => false, + } } fn is_tup_field_access(expr: &ast::Expr) -> bool { @@ -165,6 +137,50 @@ impl ChainItem { } } + fn from_ast(expr: &ast::Expr) -> ChainItemKind { + match expr.node { + ast::ExprKind::MethodCall(ref segment, ref expressions) => { + let types = if let Some(ref generic_args) = segment.args { + if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { + data.args.clone() + } else { + vec![] + } + } else { + vec![] + }; + ChainItemKind::MethodCall(segment.clone(), types, expressions.clone(), expr.span) + } + ast::ExprKind::Field(ref nested, field) => { + if Self::is_tup_field_access(expr) { + ChainItemKind::TupleField(field, Self::is_tup_field_access(nested)) + } else { + ChainItemKind::StructField(field) + } + } + _ => ChainItemKind::Parent(expr.clone()), + } + } +} + +impl Rewrite for ChainItem { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + let shape = shape.sub_width(self.tries)?; + let rewrite = match self.kind { + ChainItemKind::Parent(ref expr) => expr.rewrite(context, shape)?, + ChainItemKind::MethodCall(ref segment, ref types, ref exprs, span) => { + Self::rewrite_method_call(segment.ident, types, exprs, span, context, shape)? + } + ChainItemKind::StructField(ident) => format!(".{}", ident.name), + ChainItemKind::TupleField(ident, nested) => { + format!("{}.{}", if nested { " " } else { "" }, ident.name) + } + }; + Some(format!("{}{}", rewrite, "?".repeat(self.tries))) + } +} + +impl ChainItem { fn rewrite_method_call( method_name: ast::Ident, types: &[ast::GenericArg], @@ -206,12 +222,12 @@ impl Chain { // Un-parse the expression tree into ChainItems let mut children = vec![]; let mut sub_tries = 0; - for subexpr in subexpr_list { + for subexpr in &subexpr_list { match subexpr.node { ast::ExprKind::Try(_) => sub_tries += 1, _ => { children.push(ChainItem { - expr: subexpr, + kind: ChainItemKind::from_ast(subexpr), tries: sub_tries, }); sub_tries = 0; @@ -427,7 +443,7 @@ impl<'a> ChainFormatterShared<'a> { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. if let Some(one_line_shape) = last_shape.offset_left(almost_total) { - if let Some(rw) = last.rewrite_postfix(context, one_line_shape) { + if let Some(rw) = last.rewrite(context, one_line_shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. // 2. `last_child_str.lines().count() >= 5`. @@ -443,7 +459,7 @@ impl<'a> ChainFormatterShared<'a> { // better. let last_shape = child_shape .sub_width(shape.rhs_overhead(context.config) + last.tries)?; - match last.rewrite_postfix(context, last_shape) { + match last.rewrite(context, last_shape) { Some(ref new_rw) if !could_fit_single_line => { last_subexpr_str = Some(new_rw.clone()); } @@ -464,7 +480,7 @@ impl<'a> ChainFormatterShared<'a> { } } - last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite_postfix(context, last_shape)); + last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite(context, last_shape)); self.rewrites.push(last_subexpr_str?); Some(()) } @@ -525,18 +541,18 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { ) -> Option<()> { let mut root_rewrite: String = parent.rewrite(context, shape)?; - let mut root_ends_with_block = is_block_expr(context, &parent.expr, &root_rewrite); + let mut root_ends_with_block = parent.kind.is_block_like(context, &root_rewrite); let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { let item = &self.shared.children[self.shared.children.len() - 1]; let shape = shape.offset_left(root_rewrite.len())?; - match &item.rewrite_postfix(context, shape) { + match &item.rewrite(context, shape) { Some(rewrite) => root_rewrite.push_str(rewrite), None => break, } - root_ends_with_block = is_block_expr(context, &item.expr, &root_rewrite); + root_ends_with_block = item.kind.is_block_like(context, &root_rewrite); self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; if self.shared.children.is_empty() { @@ -560,9 +576,9 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { for item in self.shared.children[1..].iter().rev() { - let rewrite = item.rewrite_postfix(context, child_shape)?; + let rewrite = item.rewrite(context, child_shape)?; self.is_block_like - .push(is_block_expr(context, &item.expr, &rewrite)); + .push(item.kind.is_block_like(context, &rewrite)); self.shared.rewrites.push(rewrite); } Some(()) @@ -620,18 +636,18 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { trimmed_last_line_width(&root_rewrite) }; - if !multiline || is_block_expr(context, &parent.expr, &root_rewrite) { + if !multiline || parent.kind.is_block_like(context, &root_rewrite) { let item = &self.shared.children[self.shared.children.len() - 1]; let child_shape = parent_shape .visual_indent(self.offset) .sub_width(self.offset)?; - let rewrite = item.rewrite_postfix(context, child_shape)?; + let rewrite = item.rewrite(context, child_shape)?; match wrap_str(rewrite, context.config.max_width(), shape) { Some(rewrite) => root_rewrite.push_str(&rewrite), None => { // We couldn't fit in at the visual indent, try the last // indent. - let rewrite = item.rewrite_postfix(context, parent_shape)?; + let rewrite = item.rewrite(context, parent_shape)?; root_rewrite.push_str(&rewrite); self.offset = 0; } @@ -653,7 +669,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { for item in self.shared.children[1..].iter().rev() { - let rewrite = item.rewrite_postfix(context, child_shape)?; + let rewrite = item.rewrite(context, child_shape)?; self.shared.rewrites.push(rewrite); } Some(()) -- cgit 1.4.1-3-g733a5 From c20bf454c96c79bdd8ceb3a3fdb9d099fcdbfe74 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 13:02:24 +0900 Subject: Add Span field to ChainItem --- src/chains.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index ce0940362ff..a1308ee5fc2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -101,6 +101,7 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - struct ChainItem { kind: ChainItemKind, tries: usize, + span: Span, } // FIXME: we can't use a reference here because to convert `try!` to `?` we @@ -113,7 +114,6 @@ enum ChainItemKind { ast::PathSegment, Vec, Vec>, - Span, ), StructField(ast::Ident), TupleField(ast::Ident, bool), @@ -137,7 +137,7 @@ impl ChainItemKind { } } - fn from_ast(expr: &ast::Expr) -> ChainItemKind { + fn from_ast(expr: &ast::Expr) -> (ChainItemKind, Span) { match expr.node { ast::ExprKind::MethodCall(ref segment, ref expressions) => { let types = if let Some(ref generic_args) = segment.args { @@ -149,16 +149,18 @@ impl ChainItemKind { } else { vec![] }; - ChainItemKind::MethodCall(segment.clone(), types, expressions.clone(), expr.span) + let kind = ChainItemKind::MethodCall(segment.clone(), types, expressions.clone()); + (kind, expr.span) } ast::ExprKind::Field(ref nested, field) => { - if Self::is_tup_field_access(expr) { + let kind = if Self::is_tup_field_access(expr) { ChainItemKind::TupleField(field, Self::is_tup_field_access(nested)) } else { ChainItemKind::StructField(field) - } + }; + (kind, expr.span) } - _ => ChainItemKind::Parent(expr.clone()), + _ => (ChainItemKind::Parent(expr.clone()), expr.span), } } } @@ -168,8 +170,8 @@ impl Rewrite for ChainItem { let shape = shape.sub_width(self.tries)?; let rewrite = match self.kind { ChainItemKind::Parent(ref expr) => expr.rewrite(context, shape)?, - ChainItemKind::MethodCall(ref segment, ref types, ref exprs, span) => { - Self::rewrite_method_call(segment.ident, types, exprs, span, context, shape)? + ChainItemKind::MethodCall(ref segment, ref types, ref exprs) => { + Self::rewrite_method_call(segment.ident, types, exprs, self.span, context, shape)? } ChainItemKind::StructField(ident) => format!(".{}", ident.name), ChainItemKind::TupleField(ident, nested) => { @@ -181,6 +183,11 @@ impl Rewrite for ChainItem { } impl ChainItem { + fn new(expr: &ast::Expr, tries: usize) -> ChainItem { + let (kind, span) = ChainItemKind::from_ast(expr); + ChainItem { kind, tries, span } + } + fn rewrite_method_call( method_name: ast::Ident, types: &[ast::GenericArg], @@ -226,10 +233,7 @@ impl Chain { match subexpr.node { ast::ExprKind::Try(_) => sub_tries += 1, _ => { - children.push(ChainItem { - kind: ChainItemKind::from_ast(subexpr), - tries: sub_tries, - }); + children.push(ChainItem::new(subexpr, sub_tries)); sub_tries = 0; } } -- cgit 1.4.1-3-g733a5 From c480309aade9ad5704bca6763f3daf267b81d580 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 13:35:33 +0900 Subject: Get correct span --- src/chains.rs | 36 +++++++++++++++++++----------------- src/codemap.rs | 6 +++++- 2 files changed, 24 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index a1308ee5fc2..eafa537c309 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -65,6 +65,7 @@ //! .qux //! ``` +use codemap::SpanUtils; use config::IndentStyle; use expr::rewrite_call; use macros::convert_try_mac; @@ -137,8 +138,8 @@ impl ChainItemKind { } } - fn from_ast(expr: &ast::Expr) -> (ChainItemKind, Span) { - match expr.node { + fn from_ast(context: &RewriteContext, expr: &ast::Expr) -> (ChainItemKind, Span) { + let (kind, span) = match expr.node { ast::ExprKind::MethodCall(ref segment, ref expressions) => { let types = if let Some(ref generic_args) = segment.args { if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { @@ -149,8 +150,9 @@ impl ChainItemKind { } else { vec![] }; + let span = mk_sp(expressions[0].span.hi(), expr.span.hi()); let kind = ChainItemKind::MethodCall(segment.clone(), types, expressions.clone()); - (kind, expr.span) + (kind, span) } ast::ExprKind::Field(ref nested, field) => { let kind = if Self::is_tup_field_access(expr) { @@ -158,10 +160,15 @@ impl ChainItemKind { } else { ChainItemKind::StructField(field) }; - (kind, expr.span) + let span = mk_sp(nested.span.hi(), field.span.hi()); + (kind, span) } - _ => (ChainItemKind::Parent(expr.clone()), expr.span), - } + _ => return (ChainItemKind::Parent(expr.clone()), expr.span), + }; + + // Remove comments from the span. + let lo = context.snippet_provider.span_before(span, "."); + (kind, mk_sp(lo, span.hi())) } } @@ -183,8 +190,8 @@ impl Rewrite for ChainItem { } impl ChainItem { - fn new(expr: &ast::Expr, tries: usize) -> ChainItem { - let (kind, span) = ChainItemKind::from_ast(expr); + fn new(context: &RewriteContext, expr: &ast::Expr, tries: usize) -> ChainItem { + let (kind, span) = ChainItemKind::from_ast(context, expr); ChainItem { kind, tries, span } } @@ -196,22 +203,17 @@ impl ChainItem { context: &RewriteContext, shape: Shape, ) -> Option { - let (lo, type_str) = if types.is_empty() { - (args[0].span.hi(), String::new()) + let type_str = if types.is_empty() { + String::new() } else { let type_list = types .iter() .map(|ty| ty.rewrite(context, shape)) .collect::>>()?; - let type_str = format!("::<{}>", type_list.join(", ")); - - (types.last().unwrap().span().hi(), type_str) + format!("::<{}>", type_list.join(", ")) }; - let callee_str = format!(".{}{}", method_name, type_str); - let span = mk_sp(lo, span.hi()); - rewrite_call(context, &callee_str, &args[1..], span, shape) } } @@ -233,7 +235,7 @@ impl Chain { match subexpr.node { ast::ExprKind::Try(_) => sub_tries += 1, _ => { - children.push(ChainItem::new(subexpr, sub_tries)); + children.push(ChainItem::new(context, subexpr, sub_tries)); sub_tries = 0; } } diff --git a/src/codemap.rs b/src/codemap.rs index c5f24004fcf..2e73fdcec13 100644 --- a/src/codemap.rs +++ b/src/codemap.rs @@ -51,7 +51,11 @@ impl<'a> SpanUtils for SnippetProvider<'a> { } fn span_before(&self, original: Span, needle: &str) -> BytePos { - self.opt_span_before(original, needle).expect("bad span") + self.opt_span_before(original, needle).expect(&format!( + "bad span: {}: {}", + needle, + self.span_to_snippet(original).unwrap() + )) } fn opt_span_after(&self, original: Span, needle: &str) -> Option { -- cgit 1.4.1-3-g733a5 From fc3ea494ac73aee782a903849c09bb011fe18e37 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 13:54:28 +0900 Subject: Make children list in-order instead of working on reveresed list. --- src/chains.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index eafa537c309..f6b1384b6b4 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -71,7 +71,6 @@ use expr::rewrite_call; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; -use spanned::Spanned; use utils::{ first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, wrap_str, @@ -243,7 +242,7 @@ impl Chain { Chain { parent: children.pop().unwrap(), - children, + children: children.into_iter().rev().collect(), } } @@ -417,10 +416,9 @@ impl<'a> ChainFormatterShared<'a> { shape: Shape, child_shape: Shape, ) -> Option<()> { - let last = &self.children[0]; - let extendable = - may_extend && last_line_extendable(&self.rewrites[self.rewrites.len() - 1]); - let prev_last_line_width = last_line_width(&self.rewrites[self.rewrites.len() - 1]); + let last = self.children.last()?; + let extendable = may_extend && last_line_extendable(&self.rewrites[0]); + let prev_last_line_width = last_line_width(&self.rewrites[0]); // Total of all items excluding the last. let almost_total = if extendable { @@ -551,7 +549,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { let tab_width = context.config.tab_spaces().saturating_sub(shape.offset); while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { - let item = &self.shared.children[self.shared.children.len() - 1]; + let item = &self.shared.children[0]; let shape = shape.offset_left(root_rewrite.len())?; match &item.rewrite(context, shape) { Some(rewrite) => root_rewrite.push_str(rewrite), @@ -560,7 +558,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { root_ends_with_block = item.kind.is_block_like(context, &root_rewrite); - self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; + self.shared.children = &self.shared.children[1..]; if self.shared.children.is_empty() { break; } @@ -581,7 +579,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { - for item in self.shared.children[1..].iter().rev() { + for item in &self.shared.children[..self.shared.children.len() - 1] { let rewrite = item.rewrite(context, child_shape)?; self.is_block_like .push(item.kind.is_block_like(context, &rewrite)); @@ -643,7 +641,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { }; if !multiline || parent.kind.is_block_like(context, &root_rewrite) { - let item = &self.shared.children[self.shared.children.len() - 1]; + let item = &self.shared.children[0]; let child_shape = parent_shape .visual_indent(self.offset) .sub_width(self.offset)?; @@ -659,7 +657,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } } - self.shared.children = &self.shared.children[..self.shared.children.len() - 1]; + self.shared.children = &self.shared.children[1..]; } self.shared.rewrites.push(root_rewrite); @@ -674,7 +672,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { - for item in self.shared.children[1..].iter().rev() { + for item in &self.shared.children[..self.shared.children.len() - 1] { let rewrite = item.rewrite(context, child_shape)?; self.shared.rewrites.push(rewrite); } -- cgit 1.4.1-3-g733a5 From 844e878d123acfd0c88fa9283c3fe3b21cd84ec2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 14:27:47 +0900 Subject: Add Comment to ChainItemKind --- src/chains.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f6b1384b6b4..8b7ca2fa93a 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -66,6 +66,7 @@ //! ``` use codemap::SpanUtils; +use comment::rewrite_comment; use config::IndentStyle; use expr::rewrite_call; use macros::convert_try_mac; @@ -117,6 +118,7 @@ enum ChainItemKind { ), StructField(ast::Ident), TupleField(ast::Ident, bool), + Comment, } impl ChainItemKind { @@ -124,7 +126,9 @@ impl ChainItemKind { match self { ChainItemKind::Parent(ref expr) => is_block_expr(context, expr, reps), ChainItemKind::MethodCall(..) => reps.contains('\n'), - ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) => false, + ChainItemKind::StructField(..) + | ChainItemKind::TupleField(..) + | ChainItemKind::Comment => false, } } @@ -183,6 +187,9 @@ impl Rewrite for ChainItem { ChainItemKind::TupleField(ident, nested) => { format!("{}.{}", if nested { " " } else { "" }, ident.name) } + ChainItemKind::Comment => { + rewrite_comment(context.snippet(self.span).trim(), false, shape, context.config)? + } }; Some(format!("{}{}", rewrite, "?".repeat(self.tries))) } -- cgit 1.4.1-3-g733a5 From e6bde923f534fcc630c92a2756449e7483d84662 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 14:28:10 +0900 Subject: Format comment between chain elements --- src/chains.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 8b7ca2fa93a..daff789296e 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -201,6 +201,14 @@ impl ChainItem { ChainItem { kind, tries, span } } + fn comment(span: Span) -> ChainItem { + ChainItem { + kind: ChainItemKind::Comment, + tries: 0, + span, + } + } + fn rewrite_method_call( method_name: ast::Ident, types: &[ast::GenericArg], @@ -235,22 +243,32 @@ impl Chain { let subexpr_list = Self::make_subexpr_list(expr, context); // Un-parse the expression tree into ChainItems - let mut children = vec![]; + let mut rev_children = vec![]; let mut sub_tries = 0; for subexpr in &subexpr_list { match subexpr.node { ast::ExprKind::Try(_) => sub_tries += 1, _ => { - children.push(ChainItem::new(context, subexpr, sub_tries)); + rev_children.push(ChainItem::new(context, subexpr, sub_tries)); sub_tries = 0; } } } - Chain { - parent: children.pop().unwrap(), - children: children.into_iter().rev().collect(), + let parent = rev_children.pop().unwrap(); + let mut children = vec![]; + let mut prev_hi = parent.span.hi(); + for chain_item in rev_children.into_iter().rev() { + let comment_span = mk_sp(prev_hi, chain_item.span.lo()); + let comment_snippet = context.snippet(comment_span); + if !comment_snippet.trim().is_empty() { + children.push(ChainItem::comment(comment_span)); + } + prev_hi = chain_item.span.hi(); + children.push(chain_item); } + + Chain { parent, children } } // Returns a Vec of the prefixes of the chain. -- cgit 1.4.1-3-g733a5 From caefd218c9f6c43493c28c5cc4ea8828c494830e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 14:28:20 +0900 Subject: Do not combine short parent and comment --- src/chains.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index daff789296e..a6bffd8f2fb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -575,6 +575,9 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { let item = &self.shared.children[0]; + if let ChainItemKind::Comment = item.kind { + break; + } let shape = shape.offset_left(root_rewrite.len())?; match &item.rewrite(context, shape) { Some(rewrite) => root_rewrite.push_str(rewrite), @@ -667,6 +670,10 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { if !multiline || parent.kind.is_block_like(context, &root_rewrite) { let item = &self.shared.children[0]; + if let ChainItemKind::Comment = item.kind { + self.shared.rewrites.push(root_rewrite); + return Some(()); + } let child_shape = parent_shape .visual_indent(self.offset) .sub_width(self.offset)?; -- cgit 1.4.1-3-g733a5 From 91c058a51675a6c3dafdc7817e6e9624fdc996df Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 14:34:34 +0900 Subject: Veto putting a chain with comment in a single line --- src/chains.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index a6bffd8f2fb..25c3a8bbdd7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -209,6 +209,13 @@ impl ChainItem { } } + fn is_comment(&self) -> bool { + match self.kind { + ChainItemKind::Comment => true, + _ => false, + } + } + fn rewrite_method_call( method_name: ast::Ident, types: &[ast::GenericArg], @@ -458,7 +465,9 @@ impl<'a> ChainFormatterShared<'a> { }.saturating_sub(almost_total); let all_in_one_line = - self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; + !self.children.iter().any(ChainItem::is_comment) + && self.rewrites.iter().all(|s| !s.contains('\n')) + && one_line_budget > 0; let last_shape = if all_in_one_line { shape.sub_width(last.tries)? } else if extendable { -- cgit 1.4.1-3-g733a5 From 75967f0da270083308991f0bb712a0d6d37c98e6 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 14:37:13 +0900 Subject: Add a space before comment that comes after a block-like chain item --- src/chains.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 25c3a8bbdd7..3a2462e8aec 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -546,6 +546,9 @@ impl<'a> ChainFormatterShared<'a> { for (rewrite, prev_is_block_like) in rewrite_iter.zip(block_like_iter) { if !prev_is_block_like { result.push_str(&connector); + } else if rewrite.starts_with('/') { + // This is comment, add a space before it. + result.push(' '); } result.push_str(&rewrite); } -- cgit 1.4.1-3-g733a5 From 9e113b5bab1b713d1e5e26f7db6af0b664dd8bf0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 15:03:36 +0900 Subject: Do not handle comment when converting try As we get faulty span. --- src/chains.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3a2462e8aec..391d8a59972 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -262,13 +262,20 @@ impl Chain { } } + fn is_tries(s: &str) -> bool { + s.chars().all(|c| c == '?') + } + let parent = rev_children.pop().unwrap(); let mut children = vec![]; let mut prev_hi = parent.span.hi(); for chain_item in rev_children.into_iter().rev() { let comment_span = mk_sp(prev_hi, chain_item.span.lo()); let comment_snippet = context.snippet(comment_span); - if !comment_snippet.trim().is_empty() { + if !(context.config.use_try_shorthand() + || comment_snippet.trim().is_empty() + || is_tries(comment_snippet.trim())) + { children.push(ChainItem::comment(comment_span)); } prev_hi = chain_item.span.hi(); -- cgit 1.4.1-3-g733a5 From 49945a14f7a566dd12993910171e9bdd9b6c32fb Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 15:04:48 +0900 Subject: Format --- src/chains.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 391d8a59972..9d0e8c7c6d2 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -187,9 +187,12 @@ impl Rewrite for ChainItem { ChainItemKind::TupleField(ident, nested) => { format!("{}.{}", if nested { " " } else { "" }, ident.name) } - ChainItemKind::Comment => { - rewrite_comment(context.snippet(self.span).trim(), false, shape, context.config)? - } + ChainItemKind::Comment => rewrite_comment( + context.snippet(self.span).trim(), + false, + shape, + context.config, + )?, }; Some(format!("{}{}", rewrite, "?".repeat(self.tries))) } @@ -471,8 +474,7 @@ impl<'a> ChainFormatterShared<'a> { min(shape.width, context.config.width_heuristics().chain_width) }.saturating_sub(almost_total); - let all_in_one_line = - !self.children.iter().any(ChainItem::is_comment) + let all_in_one_line = !self.children.iter().any(ChainItem::is_comment) && self.rewrites.iter().all(|s| !s.contains('\n')) && one_line_budget > 0; let last_shape = if all_in_one_line { -- cgit 1.4.1-3-g733a5 From 3ec6de1de8ed9d4576d667893b3dd066704837a8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 15:06:05 +0900 Subject: Add FIXME comment --- src/chains.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9d0e8c7c6d2..1937bfa1960 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -275,6 +275,7 @@ impl Chain { for chain_item in rev_children.into_iter().rev() { let comment_span = mk_sp(prev_hi, chain_item.span.lo()); let comment_snippet = context.snippet(comment_span); + // FIXME: Figure out the way to get a correct span when converting `try!` to `?`. if !(context.config.use_try_shorthand() || comment_snippet.trim().is_empty() || is_tries(comment_snippet.trim())) -- cgit 1.4.1-3-g733a5 From 24fccdc45c170a6d64025bbebd44ae30bea52d32 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 15:50:49 +0900 Subject: Factor out functions that extract comments around items --- src/lists.rs | 260 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 142 insertions(+), 118 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 0e3baa7c1e1..9a21b720dc0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -515,6 +515,139 @@ where leave_last: bool, } +pub fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommentStyle) { + let trimmed_pre_snippet = pre_snippet.trim(); + let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); + let has_block_comment = trimmed_pre_snippet.starts_with("/*"); + if has_single_line_comment { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else if has_block_comment { + let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); + if pre_snippet + .chars() + .rev() + .take(comment_end + 1) + .any(|c| c == '\n') + { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) + } else { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::SameLine, + ) + } + } else { + (None, ListItemCommentStyle::None) + } +} + +pub fn extract_post_comment( + post_snippet: &str, + comment_end: usize, + separator: &str, +) -> Option { + let white_space: &[_] = &[' ', '\t']; + + // Cleanup post-comment: strip separators and whitespace. + let post_snippet = post_snippet[..comment_end].trim(); + let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { + post_snippet[1..].trim_matches(white_space) + } else if post_snippet.starts_with(separator) { + post_snippet[separator.len()..].trim_matches(white_space) + } else if post_snippet.ends_with(',') { + post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) + } else { + post_snippet + }; + + if !post_snippet_trimmed.is_empty() { + Some(post_snippet_trimmed.to_owned()) + } else { + None + } +} + +pub fn get_comment_end( + post_snippet: &str, + separator: &str, + terminator: &str, + is_last: bool, +) -> usize { + if is_last { + return post_snippet + .find_uncommented(terminator) + .unwrap_or_else(|| post_snippet.len()); + } + + let mut block_open_index = post_snippet.find("/*"); + // check if it really is a block comment (and not `//*` or a nested comment) + if let Some(i) = block_open_index { + match post_snippet.find('/') { + Some(j) if j < i => block_open_index = None, + _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, + _ => (), + } + } + let newline_index = post_snippet.find('\n'); + if let Some(separator_index) = post_snippet.find_uncommented(separator) { + match (block_open_index, newline_index) { + // Separator before comment, with the next item on same line. + // Comment belongs to next item. + (Some(i), None) if i > separator_index => separator_index + 1, + // Block-style post-comment before the separator. + (Some(i), None) => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Block-style post-comment. Either before or after the separator. + (Some(i), Some(j)) if i < j => cmp::max( + find_comment_end(&post_snippet[i..]).unwrap() + i, + separator_index + 1, + ), + // Potential *single* line comment. + (_, Some(j)) if j > separator_index => j + 1, + _ => post_snippet.len(), + } + } else if let Some(newline_index) = newline_index { + // Match arms may not have trailing comma. In any case, for match arms, + // we will assume that the post comment belongs to the next arm if they + // do not end with trailing comma. + newline_index + 1 + } else { + 0 + } +} + +// Account for extra whitespace between items. This is fiddly +// because of the way we divide pre- and post- comments. +fn has_extra_newline(post_snippet: &str, comment_end: usize) -> bool { + if post_snippet.is_empty() || comment_end == 0 { + return false; + } + + // Everything from the separator to the next item. + let test_snippet = &post_snippet[comment_end - 1..]; + let first_newline = test_snippet + .find('\n') + .unwrap_or_else(|| test_snippet.len()); + // From the end of the first line of comments. + let test_snippet = &test_snippet[first_newline..]; + let first = test_snippet + .find(|c: char| !c.is_whitespace()) + .unwrap_or_else(|| test_snippet.len()); + // From the end of the first line of comments to the next non-whitespace char. + let test_snippet = &test_snippet[..first]; + + // There were multiple line breaks which got trimmed to nothing. + count_newlines(test_snippet) > 1 +} + impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3> where I: Iterator, @@ -525,44 +658,13 @@ where type Item = ListItem; fn next(&mut self) -> Option { - let white_space: &[_] = &[' ', '\t']; - self.inner.next().map(|item| { - let mut new_lines = false; // Pre-comment let pre_snippet = self .snippet_provider .span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item))) .unwrap_or(""); - let trimmed_pre_snippet = pre_snippet.trim(); - let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); - let has_block_comment = trimmed_pre_snippet.starts_with("/*"); - let (pre_comment, pre_comment_style) = if has_single_line_comment { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else if has_block_comment { - let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); - if pre_snippet - .chars() - .rev() - .take(comment_end + 1) - .any(|c| c == '\n') - { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::SameLine, - ) - } - } else { - (None, ListItemCommentStyle::None) - }; + let (pre_comment, pre_comment_style) = extract_pre_comment(pre_snippet); // Post-comment let next_start = match self.inner.peek() { @@ -573,94 +675,16 @@ where .snippet_provider .span_to_snippet(mk_sp((self.get_hi)(&item), next_start)) .unwrap_or(""); + let comment_end = get_comment_end( + post_snippet, + self.separator, + self.terminator, + self.inner.peek().is_none(), + ); + let new_lines = has_extra_newline(post_snippet, comment_end); + let post_comment = extract_post_comment(post_snippet, comment_end, self.separator); - let comment_end = match self.inner.peek() { - Some(..) => { - let mut block_open_index = post_snippet.find("/*"); - // check if it really is a block comment (and not `//*` or a nested comment) - if let Some(i) = block_open_index { - match post_snippet.find('/') { - Some(j) if j < i => block_open_index = None, - _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, - _ => (), - } - } - let newline_index = post_snippet.find('\n'); - if let Some(separator_index) = post_snippet.find_uncommented(self.separator) { - match (block_open_index, newline_index) { - // Separator before comment, with the next item on same line. - // Comment belongs to next item. - (Some(i), None) if i > separator_index => separator_index + 1, - // Block-style post-comment before the separator. - (Some(i), None) => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Block-style post-comment. Either before or after the separator. - (Some(i), Some(j)) if i < j => cmp::max( - find_comment_end(&post_snippet[i..]).unwrap() + i, - separator_index + 1, - ), - // Potential *single* line comment. - (_, Some(j)) if j > separator_index => j + 1, - _ => post_snippet.len(), - } - } else if let Some(newline_index) = newline_index { - // Match arms may not have trailing comma. In any case, for match arms, - // we will assume that the post comment belongs to the next arm if they - // do not end with trailing comma. - newline_index + 1 - } else { - 0 - } - } - None => post_snippet - .find_uncommented(self.terminator) - .unwrap_or_else(|| post_snippet.len()), - }; - - if !post_snippet.is_empty() && comment_end > 0 { - // Account for extra whitespace between items. This is fiddly - // because of the way we divide pre- and post- comments. - - // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end - 1..]; - let first_newline = test_snippet - .find('\n') - .unwrap_or_else(|| test_snippet.len()); - // From the end of the first line of comments. - let test_snippet = &test_snippet[first_newline..]; - let first = test_snippet - .find(|c: char| !c.is_whitespace()) - .unwrap_or_else(|| test_snippet.len()); - // From the end of the first line of comments to the next non-whitespace char. - let test_snippet = &test_snippet[..first]; - - if count_newlines(test_snippet) > 1 { - // There were multiple line breaks which got trimmed to nothing. - new_lines = true; - } - } - - // Cleanup post-comment: strip separators and whitespace. self.prev_span_end = (self.get_hi)(&item) + BytePos(comment_end as u32); - let post_snippet = post_snippet[..comment_end].trim(); - - let post_snippet_trimmed = if post_snippet.starts_with(|c| c == ',' || c == ':') { - post_snippet[1..].trim_matches(white_space) - } else if post_snippet.starts_with(self.separator) { - post_snippet[self.separator.len()..].trim_matches(white_space) - } else if post_snippet.ends_with(',') { - post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) - } else { - post_snippet - }; - - let post_comment = if !post_snippet_trimmed.is_empty() { - Some(post_snippet_trimmed.to_owned()) - } else { - None - }; ListItem { pre_comment, -- cgit 1.4.1-3-g733a5 From e6d814c423db142575563e2c5126ca9cd0794b14 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 19:34:22 +0900 Subject: Put comment between chain elements on its original position --- src/chains.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 1937bfa1960..99d943c494a 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -69,6 +69,7 @@ use codemap::SpanUtils; use comment::rewrite_comment; use config::IndentStyle; use expr::rewrite_call; +use lists::{extract_post_comment, extract_pre_comment, get_comment_end}; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; @@ -81,7 +82,7 @@ use std::borrow::Cow; use std::cmp::min; use std::iter; -use syntax::codemap::Span; +use syntax::codemap::{BytePos, Span}; use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { @@ -97,6 +98,12 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) - chain.rewrite(context, shape) } +#[derive(Debug)] +enum CommentPosition { + Back, + Top, +} + // An expression plus trailing `?`s to be formatted together. #[derive(Debug)] struct ChainItem { @@ -118,7 +125,7 @@ enum ChainItemKind { ), StructField(ast::Ident), TupleField(ast::Ident, bool), - Comment, + Comment(String, CommentPosition), } impl ChainItemKind { @@ -128,7 +135,7 @@ impl ChainItemKind { ChainItemKind::MethodCall(..) => reps.contains('\n'), ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) - | ChainItemKind::Comment => false, + | ChainItemKind::Comment(..) => false, } } @@ -187,12 +194,9 @@ impl Rewrite for ChainItem { ChainItemKind::TupleField(ident, nested) => { format!("{}.{}", if nested { " " } else { "" }, ident.name) } - ChainItemKind::Comment => rewrite_comment( - context.snippet(self.span).trim(), - false, - shape, - context.config, - )?, + ChainItemKind::Comment(ref comment, _) => { + rewrite_comment(comment, false, shape, context.config)? + } }; Some(format!("{}{}", rewrite, "?".repeat(self.tries))) } @@ -204,9 +208,9 @@ impl ChainItem { ChainItem { kind, tries, span } } - fn comment(span: Span) -> ChainItem { + fn comment(span: Span, comment: String, pos: CommentPosition) -> ChainItem { ChainItem { - kind: ChainItemKind::Comment, + kind: ChainItemKind::Comment(comment, pos), tries: 0, span, } @@ -214,7 +218,7 @@ impl ChainItem { fn is_comment(&self) -> bool { match self.kind { - ChainItemKind::Comment => true, + ChainItemKind::Comment(..) => true, _ => false, } } @@ -269,21 +273,98 @@ impl Chain { s.chars().all(|c| c == '?') } + fn handle_post_comment( + post_comment_span: Span, + post_comment_snippet: &str, + prev_span_end: &mut BytePos, + children: &mut Vec, + ) { + let white_spaces: &[_] = &[' ', '\t']; + if post_comment_snippet + .trim_matches(white_spaces) + .starts_with('\n') + { + // No post comment. + return; + } + // HACK: Treat `?`s as separators. + let trimmed_snippet = post_comment_snippet.trim_matches('?'); + let comment_end = get_comment_end(trimmed_snippet, "?", "", false); + let maybe_post_comment = extract_post_comment(trimmed_snippet, comment_end, "?") + .and_then(|comment| { + if comment.is_empty() { + None + } else { + Some((comment, comment_end)) + } + }); + + if let Some((post_comment, comment_end)) = maybe_post_comment { + children.push(ChainItem::comment( + post_comment_span, + post_comment, + CommentPosition::Back, + )); + *prev_span_end = *prev_span_end + BytePos(comment_end as u32); + } + } + let parent = rev_children.pop().unwrap(); let mut children = vec![]; - let mut prev_hi = parent.span.hi(); - for chain_item in rev_children.into_iter().rev() { - let comment_span = mk_sp(prev_hi, chain_item.span.lo()); + let mut prev_span_end = parent.span.hi(); + let mut iter = rev_children.into_iter().rev().peekable(); + if let Some(first_chain_item) = iter.peek() { + let comment_span = mk_sp(prev_span_end, first_chain_item.span.lo()); let comment_snippet = context.snippet(comment_span); + if !is_tries(comment_snippet.trim()) { + handle_post_comment( + comment_span, + comment_snippet, + &mut prev_span_end, + &mut children, + ); + } + } + while let Some(chain_item) = iter.next() { + let comment_snippet = context.snippet(chain_item.span); // FIXME: Figure out the way to get a correct span when converting `try!` to `?`. - if !(context.config.use_try_shorthand() - || comment_snippet.trim().is_empty() - || is_tries(comment_snippet.trim())) - { - children.push(ChainItem::comment(comment_span)); + let handle_comment = + !(context.config.use_try_shorthand() || is_tries(comment_snippet.trim())); + + // Pre-comment + if handle_comment { + let pre_comment_span = mk_sp(prev_span_end, chain_item.span.lo()); + let pre_comment_snippet = context.snippet(pre_comment_span); + let (pre_comment, _) = extract_pre_comment(pre_comment_snippet); + match pre_comment { + Some(ref comment) if !comment.is_empty() => { + children.push(ChainItem::comment( + pre_comment_span, + comment.to_owned(), + CommentPosition::Top, + )); + } + _ => (), + } } - prev_hi = chain_item.span.hi(); + + prev_span_end = chain_item.span.hi(); children.push(chain_item); + + // Post-comment + if !handle_comment || iter.peek().is_none() { + continue; + } + + let next_lo = iter.peek().unwrap().span.lo(); + let post_comment_span = mk_sp(prev_span_end, next_lo); + let post_comment_snippet = context.snippet(post_comment_span); + handle_post_comment( + post_comment_span, + post_comment_snippet, + &mut prev_span_end, + &mut children, + ); } Chain { parent, children } @@ -552,13 +633,18 @@ impl<'a> ChainFormatterShared<'a> { let mut rewrite_iter = self.rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); + let children_iter = self.children.iter(); + let iter = rewrite_iter.zip(block_like_iter).zip(children_iter); - for (rewrite, prev_is_block_like) in rewrite_iter.zip(block_like_iter) { - if !prev_is_block_like { - result.push_str(&connector); - } else if rewrite.starts_with('/') { - // This is comment, add a space before it. - result.push(' '); + for ((rewrite, prev_is_block_like), chain_item) in iter { + match chain_item.kind { + ChainItemKind::Comment(_, CommentPosition::Back) => result.push(' '), + ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector), + _ => { + if !prev_is_block_like { + result.push_str(&connector); + } + } } result.push_str(&rewrite); } @@ -597,7 +683,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { while root_rewrite.len() <= tab_width && !root_rewrite.contains('\n') { let item = &self.shared.children[0]; - if let ChainItemKind::Comment = item.kind { + if let ChainItemKind::Comment(..) = item.kind { break; } let shape = shape.offset_left(root_rewrite.len())?; @@ -692,7 +778,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { if !multiline || parent.kind.is_block_like(context, &root_rewrite) { let item = &self.shared.children[0]; - if let ChainItemKind::Comment = item.kind { + if let ChainItemKind::Comment(..) = item.kind { self.shared.rewrites.push(root_rewrite); return Some(()); } -- cgit 1.4.1-3-g733a5 From 4bbfe0829d0ca4579c20c51100bb43c70f7c8e2d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 5 Aug 2018 21:03:45 +0900 Subject: Fix chain with many try operators --- src/chains.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 99d943c494a..429b9ceb961 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -335,6 +335,7 @@ impl Chain { if handle_comment { let pre_comment_span = mk_sp(prev_span_end, chain_item.span.lo()); let pre_comment_snippet = context.snippet(pre_comment_span); + let pre_comment_snippet = pre_comment_snippet.trim().trim_matches('?'); let (pre_comment, _) = extract_pre_comment(pre_comment_snippet); match pre_comment { Some(ref comment) if !comment.is_empty() => { -- cgit 1.4.1-3-g733a5 From b1c241ea722b97f2fa8940a19f0ae7dc18fac41a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 6 Aug 2018 08:10:19 +0900 Subject: Combine list-like attributes --- src/attr.rs | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 555c0eb96e7..9433cfcadb9 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -61,15 +61,22 @@ fn get_derive_spans<'a>(attr: &ast::Attribute) -> Option> { fn argument_shape( left: usize, right: usize, + combine: bool, shape: Shape, context: &RewriteContext, ) -> Option { match context.config.indent_style() { - IndentStyle::Block => Some( - shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config), - ), + IndentStyle::Block => { + if combine { + shape.offset_left(left) + } else { + Some( + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config), + ) + } + } IndentStyle::Visual => shape .visual_indent(0) .shrink_left(left) @@ -87,7 +94,7 @@ fn format_derive( result.push_str(prefix); result.push_str("[derive("); - let argument_shape = argument_shape(10 + prefix.len(), 2, shape, context)?; + let argument_shape = argument_shape(10 + prefix.len(), 2, false, shape, context)?; let item_str = format_arg_list( derive_args.iter(), |_| DUMMY_SP.lo(), @@ -99,6 +106,7 @@ fn format_derive( // 10 = "[derive()]", 3 = "()" and "]" shape.offset_left(10 + prefix.len())?.sub_width(3)?, None, + false, )?; result.push_str(&item_str); @@ -214,9 +222,29 @@ impl Rewrite for ast::MetaItem { // it's close enough). let snippet = snippet[..snippet.len() - 2].trim(); let trailing_comma = if snippet.ends_with(',') { "," } else { "" }; + let combine = list.len() == 1 && match list[0].node { + ast::NestedMetaItemKind::Literal(..) => false, + ast::NestedMetaItemKind::MetaItem(ref inner_meta_item) => { + match inner_meta_item.node { + ast::MetaItemKind::List(..) => rewrite_path( + context, + PathContext::Type, + None, + &inner_meta_item.ident, + shape, + ).map_or(false, |s| s.len() + path.len() + 2 <= shape.width), + _ => false, + } + } + }; - let argument_shape = - argument_shape(path.len() + 1, 2 + trailing_comma.len(), shape, context)?; + let argument_shape = argument_shape( + path.len() + 1, + 2 + trailing_comma.len(), + combine, + shape, + context, + )?; let item_str = format_arg_list( list.iter(), |nested_meta_item| nested_meta_item.span.lo(), @@ -230,6 +258,7 @@ impl Rewrite for ast::MetaItem { .offset_left(path.len())? .sub_width(3 + trailing_comma.len())?, Some(context.config.width_heuristics().fn_call_width), + combine, )?; let indent = if item_str.starts_with('\n') { @@ -268,6 +297,7 @@ fn format_arg_list( shape: Shape, one_line_shape: Shape, one_line_limit: Option, + combine: bool, ) -> Option where I: Iterator, @@ -311,6 +341,7 @@ where let one_line_budget = one_line_shape.width; if context.config.indent_style() == IndentStyle::Visual + || combine || (!item_str.contains('\n') && item_str.len() <= one_line_budget) { Some(item_str) -- cgit 1.4.1-3-g733a5 From 4ad1c6600115593a7c2f2273f138872728d3211a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 6 Aug 2018 22:28:05 +0900 Subject: Use custom path value if one exists when searching modules --- src/modules.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index d94b2dd1333..3316c5a970b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -15,6 +15,7 @@ use std::path::{Path, PathBuf}; use syntax::ast; use syntax::codemap; use syntax::parse::{parser, DirectoryOwnership}; +use syntax_pos::symbol::Symbol; use config::FileName; use utils::contains_skip; @@ -38,6 +39,18 @@ pub fn list_files<'a>( Ok(result) } +fn path_value(attr: &ast::Attribute) -> Option { + if attr.name() == "path" { + attr.value_str() + } else { + None + } +} + +fn find_path_value(attrs: &[ast::Attribute]) -> Option { + attrs.iter().flat_map(path_value).next() +} + /// Recursively list all external modules included in a module. fn list_submodules<'a>( module: &'a ast::Mod, @@ -53,7 +66,11 @@ fn list_submodules<'a>( let is_internal = codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); let (dir_path, relative) = if is_internal { - (search_dir.join(&item.ident.to_string()), None) + if let Some(path) = find_path_value(&item.attrs) { + (search_dir.join(&path.as_str()), None) + } else { + (search_dir.join(&item.ident.to_string()), None) + } } else { let (mod_path, relative) = module_file(item.ident, &item.attrs, search_dir, relative, codemap)?; -- cgit 1.4.1-3-g733a5 From a201d856d10913b887f259c5302d4f5dfcebf6a9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 6 Aug 2018 22:34:58 +0900 Subject: Add comment --- src/modules.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 3316c5a970b..7619c0afa57 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -47,6 +47,9 @@ fn path_value(attr: &ast::Attribute) -> Option { } } +// N.B. Even when there are multiple `#[path = ...]` attributes, we just need to +// examine the first one, since rustc ignores the second and the subsequent ones +// as unused attributes. fn find_path_value(attrs: &[ast::Attribute]) -> Option { attrs.iter().flat_map(path_value).next() } -- cgit 1.4.1-3-g733a5 From 934cf2807d488334fd6dbbc7c4fa1b050a7a236c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 12 Aug 2018 23:56:09 +0900 Subject: Remove a wildcard parttern from slice patterns --- src/patterns.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 7ab43def8c7..465d64627e8 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -144,7 +144,8 @@ impl Rewrite for Pat { let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); let slice_pat = slice_pat .as_ref() - .map(|p| Some(format!("{}..", p.rewrite(context, shape)?))); + .and_then(|p| p.rewrite(context, shape)) + .map(|rw| Some(format!("{}..", if rw == "_" { "" } else { &rw }))); let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); // Munge them together. -- cgit 1.4.1-3-g733a5 From 4604f46ce8fa5b80b2e47f845c8ed669e8e714ba Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 14 Aug 2018 13:33:58 +0200 Subject: Expose FileLines JSON representation --- src/config/file_lines.rs | 82 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 436c7a83b81..962a4bb9a41 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -15,6 +15,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::{cmp, fmt, iter, str}; +use serde::ser::{self, Serialize, Serializer}; use serde::de::{Deserialize, Deserializer}; use serde_json as json; @@ -53,6 +54,35 @@ impl fmt::Display for FileName { } } +impl<'de> Deserialize<'de> for FileName { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + if s == "stdin" { + Ok(FileName::Stdin) + } else { + Ok(FileName::Real(s.into())) + } + } +} + +impl Serialize for FileName { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let s = match self { + FileName::Stdin => Ok("stdin"), + FileName::Real(path) => path.to_str().ok_or_else(|| + ser::Error::custom("path can't be serialized as UTF-8 string")) + }; + + s.and_then(|s| serializer.serialize_str(s)) + } +} + impl LineRange { pub fn file_name(&self) -> FileName { self.file.name.clone().into() @@ -175,6 +205,20 @@ impl FileLines { Files(self.0.as_ref().map(|m| m.keys())) } + /// Returns JSON representation as accepted by the `--file-lines JSON` arg. + pub fn to_json_spans(&self) -> Vec { + match &self.0 { + None => vec![], + Some(file_ranges) => file_ranges + .iter() + .flat_map(|(file, ranges)| ranges.iter().map(move |r| (file, r))) + .map(|(file, range)| JsonSpan { + file: file.to_owned(), + range: (range.lo, range.hi), + }).collect(), + } + } + /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in /// the designated file (if any) and returns true if `f` ever does. fn file_range_matches(&self, file_name: &FileName, f: F) -> bool @@ -249,22 +293,12 @@ impl str::FromStr for FileLines { } // For JSON decoding. -#[derive(Clone, Debug, Deserialize)] -struct JsonSpan { - #[serde(deserialize_with = "deserialize_filename")] +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct JsonSpan { file: FileName, range: (usize, usize), } -fn deserialize_filename<'de, D: Deserializer<'de>>(d: D) -> Result { - let s = String::deserialize(d)?; - if s == "stdin" { - Ok(FileName::Stdin) - } else { - Ok(FileName::Real(s.into())) - } -} - impl JsonSpan { fn into_tuple(self) -> Result<(FileName, Range), String> { let (lo, hi) = self.range; @@ -350,4 +384,28 @@ mod test { Range::new(3, 7).merge(Range::new(4, 5)) ); } + + use std::{collections::HashMap, path::PathBuf}; + use super::{FileName, FileLines}; + use super::json::{self, json, json_internal}; + + #[test] + fn file_lines_to_json() { + let ranges: HashMap> = [ + (FileName::Real(PathBuf::from("src/main.rs")), vec![ + Range::new(1, 3), + Range::new(5, 7) + ]), + (FileName::Real(PathBuf::from("src/lib.rs")), vec![ + Range::new(1, 7) + ])].iter().cloned().collect(); + + let file_lines = FileLines::from_ranges(ranges); + let json = json::to_value(&file_lines.to_json_spans()).unwrap(); + assert_eq!(json, json! {[ + {"file": "src/main.rs", "range": [1, 3]}, + {"file": "src/main.rs", "range": [5, 7]}, + {"file": "src/lib.rs", "range": [1, 7]}, + ]}); + } } -- cgit 1.4.1-3-g733a5 From 38361c05bc48f0634501a8ad5bfb973388a777a2 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 14 Aug 2018 23:22:09 +0200 Subject: Make file_lines_to_json test deterministic --- src/config/file_lines.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 962a4bb9a41..bc0974e11f4 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -293,7 +293,7 @@ impl str::FromStr for FileLines { } // For JSON decoding. -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)] pub struct JsonSpan { file: FileName, range: (usize, usize), @@ -401,11 +401,13 @@ mod test { ])].iter().cloned().collect(); let file_lines = FileLines::from_ranges(ranges); - let json = json::to_value(&file_lines.to_json_spans()).unwrap(); + let mut spans = file_lines.to_json_spans(); + spans.sort(); + let json = json::to_value(&spans).unwrap(); assert_eq!(json, json! {[ + {"file": "src/lib.rs", "range": [1, 7]}, {"file": "src/main.rs", "range": [1, 3]}, {"file": "src/main.rs", "range": [5, 7]}, - {"file": "src/lib.rs", "range": [1, 7]}, ]}); } } -- cgit 1.4.1-3-g733a5 From 9d52940dbeb2a099675f2d66c2a8cc173ea00059 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 14 Aug 2018 23:23:00 +0200 Subject: Run `cargo fmt` --- src/config/file_lines.rs | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index bc0974e11f4..58f65b3c1b6 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -15,8 +15,8 @@ use std::path::PathBuf; use std::rc::Rc; use std::{cmp, fmt, iter, str}; -use serde::ser::{self, Serialize, Serializer}; use serde::de::{Deserialize, Deserializer}; +use serde::ser::{self, Serialize, Serializer}; use serde_json as json; use syntax::codemap::{self, FileMap}; @@ -75,8 +75,9 @@ impl Serialize for FileName { { let s = match self { FileName::Stdin => Ok("stdin"), - FileName::Real(path) => path.to_str().ok_or_else(|| - ser::Error::custom("path can't be serialized as UTF-8 string")) + FileName::Real(path) => path + .to_str() + .ok_or_else(|| ser::Error::custom("path can't be serialized as UTF-8 string")), }; s.and_then(|s| serializer.serialize_str(s)) @@ -385,29 +386,37 @@ mod test { ); } - use std::{collections::HashMap, path::PathBuf}; - use super::{FileName, FileLines}; use super::json::{self, json, json_internal}; + use super::{FileLines, FileName}; + use std::{collections::HashMap, path::PathBuf}; #[test] fn file_lines_to_json() { let ranges: HashMap> = [ - (FileName::Real(PathBuf::from("src/main.rs")), vec![ - Range::new(1, 3), - Range::new(5, 7) - ]), - (FileName::Real(PathBuf::from("src/lib.rs")), vec![ - Range::new(1, 7) - ])].iter().cloned().collect(); + ( + FileName::Real(PathBuf::from("src/main.rs")), + vec![Range::new(1, 3), Range::new(5, 7)], + ), + ( + FileName::Real(PathBuf::from("src/lib.rs")), + vec![Range::new(1, 7)], + ), + ] + .iter() + .cloned() + .collect(); let file_lines = FileLines::from_ranges(ranges); let mut spans = file_lines.to_json_spans(); spans.sort(); let json = json::to_value(&spans).unwrap(); - assert_eq!(json, json! {[ - {"file": "src/lib.rs", "range": [1, 7]}, - {"file": "src/main.rs", "range": [1, 3]}, - {"file": "src/main.rs", "range": [5, 7]}, - ]}); + assert_eq!( + json, + json! {[ + {"file": "src/lib.rs", "range": [1, 7]}, + {"file": "src/main.rs", "range": [1, 3]}, + {"file": "src/main.rs", "range": [5, 7]}, + ]} + ); } } -- cgit 1.4.1-3-g733a5 From 9a5a86164f25f937683d5b830ae1c8dd0b51df0d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 16 Aug 2018 07:46:59 +0900 Subject: Reduce the max width by the width of indent --- src/macros.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b32de753fda..439fd446e5c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1277,12 +1277,10 @@ impl MacroBranch { let body_indent = if has_block_body { shape.indent } else { - // We'll hack the indent below, take this into account when formatting, - let body_indent = shape.indent.block_indent(&config); - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); - body_indent + shape.indent.block_indent(&config) }; + let new_width = config.max_width() - body_indent.width(); + config.set().max_width(new_width); // First try to format as items, then as statements. let new_body = match ::format_snippet(&body_str, &config) { -- cgit 1.4.1-3-g733a5 From b318e5a68417db710beaa582775c4b6a2af5c0b1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 16 Aug 2018 07:47:37 +0900 Subject: Increase the max width by tab width when using format_code_block since the macro body will be surrounded by fn main block. --- src/macros.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 439fd446e5c..e95cd3de607 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1285,10 +1285,14 @@ impl MacroBranch { // First try to format as items, then as statements. let new_body = match ::format_snippet(&body_str, &config) { Some(new_body) => new_body, - None => match ::format_code_block(&body_str, &config) { - Some(new_body) => new_body, - None => return None, - }, + None => { + let new_width = new_width + config.tab_spaces(); + config.set().max_width(new_width); + match ::format_code_block(&body_str, &config) { + Some(new_body) => new_body, + None => return None, + } + } }; let new_body = wrap_str(new_body, config.max_width(), shape)?; -- cgit 1.4.1-3-g733a5 From f23e6aaaf958ee434d677fdc8883543de83f4e0f Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 16 Aug 2018 19:55:15 +0200 Subject: fix the identification of a block comment. Block comments like below were not properly supported: /* something here but it doesn't start with a star */ because of the line that didn't start with a star. --- src/comment.rs | 76 ++++++++++++++++++++++++++++++----------------- tests/source/issue-539.rs | 5 ++++ tests/source/issue-683.rs | 5 ++++ tests/target/issue-539.rs | 3 ++ tests/target/issue-683.rs | 3 ++ 5 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 tests/source/issue-539.rs create mode 100644 tests/source/issue-683.rs create mode 100644 tests/target/issue-539.rs create mode 100644 tests/target/issue-683.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d979bf5c4b7..e9d91818d0d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -96,21 +96,6 @@ impl<'a> CommentStyle<'a> { pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { (self.opener(), self.closer(), self.line_start()) } - - pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool) -> bool { - match *self { - CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { - line.trim_left().starts_with(self.line_start().trim_left()) - || comment_style(line, normalize_comments) == *self - } - CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { - line.trim_left().starts_with(self.closer().trim_left()) - || line.trim_left().starts_with(self.line_start().trim_left()) - || comment_style(line, normalize_comments) == *self - } - CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()), - } - } } fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { @@ -273,19 +258,56 @@ fn identify_comment( is_doc_comment: bool, ) -> Option { let style = comment_style(orig, false); - let first_group = orig - .lines() - .take_while(|l| style.line_with_same_comment_style(l, false)) - .collect::>() - .join("\n"); - let rest = orig - .lines() - .skip(first_group.lines().count()) - .collect::>() - .join("\n"); + let mut first_group_ending = 0; + + fn compute_len(orig: &str, line: &str) -> usize { + if orig.len() > line.len() { + if orig.as_bytes()[line.len()] == b'\r' { + line.len() + 2 + } else { + line.len() + 1 + } + } else { + line.len() + } + } + + match style { + CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { + let line_start = style.line_start().trim_left(); + for line in orig.lines() { + if line.trim_left().starts_with(line_start) || comment_style(line, false) == style { + first_group_ending += compute_len(&orig[first_group_ending..], line); + } else { + break; + } + } + } + CommentStyle::Custom(opener) => { + let trimmed_opener = opener.trim_right(); + for line in orig.lines() { + if line.trim_left().starts_with(trimmed_opener) { + first_group_ending += compute_len(&orig[first_group_ending..], line); + } else { + break; + } + } + } + // for a block comment, search for the closing symbol + CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { + let closer = style.closer().trim_left(); + for line in orig.lines() { + first_group_ending += compute_len(&orig[first_group_ending..], line); + if line.trim_left().ends_with(closer) { + break; + } + } + } + } + let (first_group, rest) = orig.split_at(first_group_ending); let first_group_str = rewrite_comment_inner( - &first_group, + first_group, block_style, style, shape, @@ -295,7 +317,7 @@ fn identify_comment( if rest.is_empty() { Some(first_group_str) } else { - identify_comment(&rest, block_style, shape, config, is_doc_comment).map(|rest_str| { + identify_comment(rest, block_style, shape, config, is_doc_comment).map(|rest_str| { format!( "{}\n{}{}", first_group_str, diff --git a/tests/source/issue-539.rs b/tests/source/issue-539.rs new file mode 100644 index 00000000000..d70682e3bee --- /dev/null +++ b/tests/source/issue-539.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +/* + FIXME (#3300): Should allow items to be anonymous. Right now + we just use dummy names for anon items. + */ diff --git a/tests/source/issue-683.rs b/tests/source/issue-683.rs new file mode 100644 index 00000000000..fd99015ea51 --- /dev/null +++ b/tests/source/issue-683.rs @@ -0,0 +1,5 @@ +// rustfmt-normalize_comments: true +/* + * FIXME (#3300): Should allow items to be anonymous. Right now + * we just use dummy names for anon items. + */ diff --git a/tests/target/issue-539.rs b/tests/target/issue-539.rs new file mode 100644 index 00000000000..adeb33555fb --- /dev/null +++ b/tests/target/issue-539.rs @@ -0,0 +1,3 @@ +// rustfmt-normalize_comments: true +// FIXME (#3300): Should allow items to be anonymous. Right now +// we just use dummy names for anon items. diff --git a/tests/target/issue-683.rs b/tests/target/issue-683.rs new file mode 100644 index 00000000000..adeb33555fb --- /dev/null +++ b/tests/target/issue-683.rs @@ -0,0 +1,3 @@ +// rustfmt-normalize_comments: true +// FIXME (#3300): Should allow items to be anonymous. Right now +// we just use dummy names for anon items. -- cgit 1.4.1-3-g733a5 From dd14d304ef27c2aa209e1138ac371d7f27b7a012 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 16 Aug 2018 19:59:32 +0200 Subject: discard trailing blank comments --- src/comment.rs | 8 ++++++-- tests/target/doc-comment-with-example.rs | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e9d91818d0d..4f2f813166b 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -449,8 +449,12 @@ fn rewrite_comment_inner( } } else if is_prev_line_multi_line && !line.is_empty() { result.push(' ') - } else if is_last && !closer.is_empty() && line.is_empty() { - result.push_str(&indent_str); + } else if is_last && line.is_empty() { + // trailing blank lines are unwanted + if !closer.is_empty() { + result.push_str(&indent_str); + } + break; } else { result.push_str(&comment_line_separator); if !has_leading_whitespace && result.ends_with(' ') { diff --git a/tests/target/doc-comment-with-example.rs b/tests/target/doc-comment-with-example.rs index 720e337ad4e..bdf2adf0c64 100644 --- a/tests/target/doc-comment-with-example.rs +++ b/tests/target/doc-comment-with-example.rs @@ -8,5 +8,4 @@ /// # #![cfg_attr(not(dox), no_std)] /// fn foo() {} /// ``` -/// fn foo() {} -- cgit 1.4.1-3-g733a5 From 2db2327aafe2de16cb2757c4efe779b644099a28 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 16 Aug 2018 20:00:49 +0200 Subject: fix verbose output --- src/formatting.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index d29c9398174..a695d3363a6 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -87,13 +87,13 @@ fn format_project( if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { continue; } - should_emit_verbose(!input_is_stdin, config, || println!("Formatting {}", path)); + should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); let is_root = path == main_file; context.format_file(path, module, is_root)?; } timer = timer.done_formatting(); - should_emit_verbose(!input_is_stdin, config, || { + should_emit_verbose(input_is_stdin, config, || { println!( "Spent {0:.3} secs in the parsing phase, and {1:.3} secs in the formatting phase", timer.get_parse_time(), @@ -611,7 +611,7 @@ fn parse_crate( // Note that if you see this message and want more information, // then run the `parse_crate_mod` function above without // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(!input_is_stdin, config, || { + should_emit_verbose(input_is_stdin, config, || { println!("The Rust parser panicked") }); } -- cgit 1.4.1-3-g733a5 From 05a0c8140db4a1e35ac6961aaa403c5a07ae7528 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 19 Aug 2018 00:26:34 +0900 Subject: Update import path to ThinVec --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index e95cd3de607..df7b3cdb918 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,7 +29,7 @@ use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::print::pprust; use syntax::symbol; use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; -use syntax::util::ThinVec; +use syntax::ThinVec; use syntax::{ast, ptr}; use codemap::SpanUtils; -- cgit 1.4.1-3-g733a5 From a15df80e967f2bb35b95a1e717a3fbe6f272f765 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Thu, 23 Aug 2018 04:24:15 -0400 Subject: Consider "dev" as nightly for feature (un)gating Closes #2940 --- src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index e5f5b625eba..760333955a0 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -160,7 +160,7 @@ fn make_opts() -> Options { fn is_nightly() -> bool { option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") + .map(|c| c == "nightly" || c == "dev") .unwrap_or(false) } -- cgit 1.4.1-3-g733a5 From 8cc4200b7de6794ba97ae253538e85f63a8080cf Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Thu, 23 Aug 2018 04:28:44 -0400 Subject: Consider "dev" as nightly for feature (un)gating --- src/config/config_type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 82cf0e19a8f..aea19b34375 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -73,7 +73,7 @@ impl ConfigType for IgnoreList { macro_rules! is_nightly_channel { () => { option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly") + .map(|c| c == "nightly" || c == "dev") .unwrap_or(true) }; } -- cgit 1.4.1-3-g733a5 From 04d804c3655eaaa262d1147446290e8fe4aabc67 Mon Sep 17 00:00:00 2001 From: cad97 Date: Thu, 23 Aug 2018 17:10:46 -0400 Subject: Rename CodeMap/FileMap to SourceMap/SourceFile #2946 --- Cargo.lock | 70 ++++++++++----------- Cargo.toml | 6 +- src/attr.rs | 2 +- src/chains.rs | 4 +- src/closures.rs | 10 +-- src/codemap.rs | 92 --------------------------- src/comment.rs | 6 +- src/config/file_lines.rs | 12 ++-- src/expr.rs | 28 ++++----- src/filemap.rs | 122 ------------------------------------ src/formatting.rs | 62 +++++++++--------- src/imports.rs | 10 +-- src/items.rs | 14 ++--- src/lib.rs | 10 +-- src/lists.rs | 2 +- src/macros.rs | 4 +- src/matches.rs | 8 +-- src/missed_spans.rs | 16 ++--- src/modules.rs | 22 +++---- src/overflow.rs | 4 +- src/patterns.rs | 8 +-- src/reorder.rs | 8 +-- src/rewrite.rs | 4 +- src/source_file.rs | 122 ++++++++++++++++++++++++++++++++++++ src/source_map.rs | 92 +++++++++++++++++++++++++++ src/spanned.rs | 2 +- src/test/mod.rs | 20 +++--- src/types.rs | 6 +- src/utils.rs | 4 +- src/vertical.rs | 4 +- src/visitor.rs | 34 +++++----- tests/source/expr-block.rs | 4 +- tests/source/expr.rs | 2 +- tests/target/expr-block.rs | 4 +- tests/target/expr.rs | 2 +- tests/target/nested-visual-block.rs | 4 +- 36 files changed, 412 insertions(+), 412 deletions(-) delete mode 100644 src/codemap.rs delete mode 100644 src/filemap.rs create mode 100644 src/source_file.rs create mode 100644 src/source_map.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 1b699b8b2b0..ac3fd7ab242 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -401,15 +401,15 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -418,7 +418,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -426,8 +426,8 @@ dependencies = [ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -436,57 +436,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "230.0.0" +version = "235.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,9 +541,9 @@ dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -820,14 +820,14 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum rustc-ap-arena 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0cfa6cc1afa6a0f100f07052ae80fadb2af6034bad7e1eedc8b9c399f8f47ff8" -"checksum rustc-ap-rustc_cratesio_shim 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e771302cd244d9579c7ba3344415e88c56ad21eddd79356825fe022d7b2d81ab" -"checksum rustc-ap-rustc_data_structures 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a17d0e44cd437b65748e525111f6b170f9af50a625b45b55b6ef78217d3209c0" -"checksum rustc-ap-rustc_errors 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1553077b149a2272978e94281a8f4a457fe00fc21bb45947c406f50edb8bea72" -"checksum rustc-ap-rustc_target 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "919bf28c3d2e2f695fa6a8c3779a41275d45e02bcfec6156813bcdcc686e5a04" -"checksum rustc-ap-serialize 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96e676167b9a4b49e33ca92a5747205082e667d9064d8bb48447b75f8695e658" -"checksum rustc-ap-syntax 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad8cf79b47d76743be20371ec61bee5a7c11ffbd0590939378afb9ab573501d" -"checksum rustc-ap-syntax_pos 230.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd44296b68ba3b690f276dba8b5b3fe52aad24b35faa6c993d3ee31dc6b53bb" +"checksum rustc-ap-arena 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f322d66bfa4314b6bbc6e7a0dbce4f33f7a5ed08c5a1bb0588fa8a0d904a99f" +"checksum rustc-ap-rustc_cratesio_shim 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "082c176b1346fd356c086ffb9695d188bb6a2cffc1db987e1604f36d495797d5" +"checksum rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df2ce9493ece082cfb8301a718f2945646fc622386d4c68d8fe503b35f36194f" +"checksum rustc-ap-rustc_errors 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43a08156fd6b8df7d7e4bae3edd0dc4c67b842518acbfc516cde2ce0638cd82" +"checksum rustc-ap-rustc_target 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36f7dc5977708040caf9a87f3ad877159c2573a75245280239083315f2f958a7" +"checksum rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca9beb1012c0120f95767975bc41f4b599c105da8d7561185ed22dfe2bc52cd6" +"checksum rustc-ap-syntax 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32fee8563391d36dcef52b180540cf72543a0a4505ee361ac30ed48ce9884a1b" +"checksum rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b71f85a97f5c3ed6df05040f0e29227f9c302da4325c27c33a1701ecf9d6a0" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" diff --git a/Cargo.toml b/Cargo.toml index b3a341992ef..5583b056085 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,9 +47,9 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.6" -rustc-ap-rustc_target = "230.0.0" -rustc-ap-syntax = "230.0.0" -rustc-ap-syntax_pos = "230.0.0" +rustc-ap-rustc_target = "235.0.0" +rustc-ap-syntax = "235.0.0" +rustc-ap-syntax_pos = "235.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/attr.rs b/src/attr.rs index b13c873a598..deaf2be46b8 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -22,7 +22,7 @@ use utils::{count_newlines, mk_sp}; use std::borrow::Cow; use syntax::ast; -use syntax::codemap::{BytePos, Span, DUMMY_SP}; +use syntax::source_map::{BytePos, Span, DUMMY_SP}; /// Returns attributes on the given statement. pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { diff --git a/src/chains.rs b/src/chains.rs index 429b9ceb961..8686d2c66b9 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -65,7 +65,7 @@ //! .qux //! ``` -use codemap::SpanUtils; +use source_map::SpanUtils; use comment::rewrite_comment; use config::IndentStyle; use expr::rewrite_call; @@ -82,7 +82,7 @@ use std::borrow::Cow; use std::cmp::min; use std::iter; -use syntax::codemap::{BytePos, Span}; +use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { diff --git a/src/closures.rs b/src/closures.rs index 1a4a6e44fdf..e786339ed7c 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -9,11 +9,11 @@ // except according to those terms. use config::lists::*; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::parse::classify; use syntax::{ast, ptr}; -use codemap::SpanUtils; +use source_map::SpanUtils; use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; @@ -51,7 +51,7 @@ pub fn rewrite_closure( if let ast::ExprKind::Block(ref block, _) = body.node { // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) { + if block.stmts.is_empty() && !block_contains_comment(block, context.source_map) { return body .rewrite(context, shape) .map(|s| format!("{} {}", prefix, s)); @@ -114,7 +114,7 @@ fn get_inner_expr<'a>( fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { is_unsafe_block(block) || block.stmts.len() > 1 - || block_contains_comment(block, context.codemap) + || block_contains_comment(block, context.source_map) || prefix.contains('\n') } @@ -304,7 +304,7 @@ pub fn rewrite_last_closure( let body = match body.node { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) - && is_simple_block(block, Some(&body.attrs), context.codemap) => + && is_simple_block(block, Some(&body.attrs), context.source_map) => { stmt_expr(&block.stmts[0]).unwrap_or(body) } diff --git a/src/codemap.rs b/src/codemap.rs deleted file mode 100644 index 2e73fdcec13..00000000000 --- a/src/codemap.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This module contains utilities that work with the `CodeMap` from `libsyntax` / `syntex_syntax`. -//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. - -use config::file_lines::LineRange; -use syntax::codemap::{BytePos, CodeMap, Span}; -use visitor::SnippetProvider; - -use comment::FindUncommented; - -pub trait SpanUtils { - fn span_after(&self, original: Span, needle: &str) -> BytePos; - fn span_after_last(&self, original: Span, needle: &str) -> BytePos; - fn span_before(&self, original: Span, needle: &str) -> BytePos; - fn opt_span_after(&self, original: Span, needle: &str) -> Option; - fn opt_span_before(&self, original: Span, needle: &str) -> Option; -} - -pub trait LineRangeUtils { - /// Returns the `LineRange` that corresponds to `span` in `self`. - /// - /// # Panics - /// - /// Panics if `span` crosses a file boundary, which shouldn't happen. - fn lookup_line_range(&self, span: Span) -> LineRange; -} - -impl<'a> SpanUtils for SnippetProvider<'a> { - fn span_after(&self, original: Span, needle: &str) -> BytePos { - self.opt_span_after(original, needle).expect("bad span") - } - - fn span_after_last(&self, original: Span, needle: &str) -> BytePos { - let snippet = self.span_to_snippet(original).unwrap(); - let mut offset = 0; - - while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { - offset += additional_offset + needle.len(); - } - - original.lo() + BytePos(offset as u32) - } - - fn span_before(&self, original: Span, needle: &str) -> BytePos { - self.opt_span_before(original, needle).expect(&format!( - "bad span: {}: {}", - needle, - self.span_to_snippet(original).unwrap() - )) - } - - fn opt_span_after(&self, original: Span, needle: &str) -> Option { - self.opt_span_before(original, needle) - .map(|bytepos| bytepos + BytePos(needle.len() as u32)) - } - - fn opt_span_before(&self, original: Span, needle: &str) -> Option { - let snippet = self.span_to_snippet(original)?; - let offset = snippet.find_uncommented(needle)?; - - Some(original.lo() + BytePos(offset as u32)) - } -} - -impl LineRangeUtils for CodeMap { - fn lookup_line_range(&self, span: Span) -> LineRange { - let lo = self.lookup_line(span.lo()).unwrap(); - let hi = self.lookup_line(span.hi()).unwrap(); - - debug_assert_eq!( - lo.fm.name, hi.fm.name, - "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, hi - ); - - // Line numbers start at 1 - LineRange { - file: lo.fm.clone(), - lo: lo.line + 1, - hi: hi.line + 1, - } - } -} diff --git a/src/comment.rs b/src/comment.rs index 4f2f813166b..78d087ce7a4 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -13,7 +13,7 @@ use std::{self, borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; -use syntax::codemap::Span; +use syntax::source_map::Span; use config::Config; use rewrite::RewriteContext; @@ -1151,10 +1151,10 @@ pub fn recover_comment_removed( // We missed some comments. Warn and keep the original text. if context.config.error_on_unformatted() { context.report.append( - context.codemap.span_to_filename(span).into(), + context.source_map.span_to_filename(span).into(), vec![FormattingError::from_span( &span, - &context.codemap, + &context.source_map, ErrorKind::LostComment, )], ); diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 58f65b3c1b6..ba317af8360 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -19,11 +19,11 @@ use serde::de::{Deserialize, Deserializer}; use serde::ser::{self, Serialize, Serializer}; use serde_json as json; -use syntax::codemap::{self, FileMap}; +use syntax::source_map::{self, SourceFile}; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { - pub file: Rc, + pub file: Rc, pub lo: usize, pub hi: usize, } @@ -35,11 +35,11 @@ pub enum FileName { Stdin, } -impl From for FileName { - fn from(name: codemap::FileName) -> FileName { +impl From for FileName { + fn from(name: source_map::FileName) -> FileName { match name { - codemap::FileName::Real(p) => FileName::Real(p), - codemap::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, + source_map::FileName::Real(p) => FileName::Real(p), + source_map::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, _ => unreachable!(), } } diff --git a/src/expr.rs b/src/expr.rs index 0f4474d7c0f..909ea46f75d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,13 +12,13 @@ use std::borrow::Cow; use std::cmp::min; use config::lists::*; -use syntax::codemap::{BytePos, CodeMap, Span}; +use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::parse::token::DelimToken; use syntax::{ast, ptr}; use chains::rewrite_chain; use closures; -use codemap::{LineRangeUtils, SpanUtils}; +use source_map::{LineRangeUtils, SpanUtils}; use comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, @@ -425,7 +425,7 @@ fn rewrite_empty_block( return None; } - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 + if block.stmts.is_empty() && !block_contains_comment(block, context.source_map) && shape.width >= 2 { return Some(format!("{}{}{{}}", prefix, label_str)); } @@ -483,7 +483,7 @@ fn rewrite_single_line_block( label: Option, shape: Shape, ) -> Option { - if is_simple_block(block, attrs, context.codemap) { + if is_simple_block(block, attrs, context.source_map) { let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; let label_str = rewrite_label(label); @@ -769,8 +769,8 @@ impl<'a> ControlFlow<'a> { let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node, _) = else_block.node { - if !is_simple_block(self.block, None, context.codemap) - || !is_simple_block(else_node, None, context.codemap) + if !is_simple_block(self.block, None, context.source_map) + || !is_simple_block(else_node, None, context.source_map) || pat_expr_str.contains('\n') { return None; @@ -1113,8 +1113,8 @@ fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option } } -pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { - let snippet = codemap.span_to_snippet(block.span).unwrap(); +pub fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> bool { + let snippet = source_map.span_to_snippet(block.span).unwrap(); contains_comment(&snippet) } @@ -1125,11 +1125,11 @@ pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { pub fn is_simple_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, - codemap: &CodeMap, + source_map: &SourceMap, ) -> bool { (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, codemap) + && !block_contains_comment(block, source_map) && attrs.map_or(true, |a| a.is_empty())) } @@ -1138,10 +1138,10 @@ pub fn is_simple_block( pub fn is_simple_block_stmt( block: &ast::Block, attrs: Option<&[ast::Attribute]>, - codemap: &CodeMap, + source_map: &SourceMap, ) -> bool { block.stmts.len() <= 1 - && !block_contains_comment(block, codemap) + && !block_contains_comment(block, source_map) && attrs.map_or(true, |a| a.is_empty()) } @@ -1150,10 +1150,10 @@ pub fn is_simple_block_stmt( pub fn is_empty_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, - codemap: &CodeMap, + source_map: &SourceMap, ) -> bool { block.stmts.is_empty() - && !block_contains_comment(block, codemap) + && !block_contains_comment(block, source_map) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } diff --git a/src/filemap.rs b/src/filemap.rs deleted file mode 100644 index 20140321032..00000000000 --- a/src/filemap.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::fs; -use std::io::{self, Write}; - -use checkstyle::output_checkstyle_file; -use config::{Config, EmitMode, FileName, Verbosity}; -use rustfmt_diff::{make_diff, output_modified, print_diff}; - -#[cfg(test)] -use formatting::FileRecord; - -// Append a newline to the end of each file. -pub fn append_newline(s: &mut String) { - s.push_str("\n"); -} - -#[cfg(test)] -pub(crate) fn write_all_files( - file_map: &[FileRecord], - out: &mut T, - config: &Config, -) -> Result<(), io::Error> -where - T: Write, -{ - if config.emit_mode() == EmitMode::Checkstyle { - write!(out, "{}", ::checkstyle::header())?; - } - for &(ref filename, ref text) in file_map { - write_file(text, filename, out, config)?; - } - if config.emit_mode() == EmitMode::Checkstyle { - write!(out, "{}", ::checkstyle::footer())?; - } - - Ok(()) -} - -pub fn write_file( - formatted_text: &str, - filename: &FileName, - out: &mut T, - config: &Config, -) -> Result -where - T: Write, -{ - let filename_to_path = || match *filename { - FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` and emit to files", filename), - }; - - match config.emit_mode() { - EmitMode::Files if config.make_backup() => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - if ori != formatted_text { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.with_extension("tmp"); - let bk_name = filename.with_extension("bk"); - - fs::write(&tmp_name, formatted_text)?; - fs::rename(filename, bk_name)?; - fs::rename(tmp_name, filename)?; - } - } - EmitMode::Files => { - // Write text directly over original file if there is a diff. - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - if ori != formatted_text { - fs::write(filename, formatted_text)?; - } - } - EmitMode::Stdout | EmitMode::Coverage => { - if config.verbose() != Verbosity::Quiet { - println!("{}:\n", filename); - } - write!(out, "{}", formatted_text)?; - } - EmitMode::ModifiedLines => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - let mismatch = make_diff(&ori, formatted_text, 0); - let has_diff = !mismatch.is_empty(); - output_modified(out, mismatch); - return Ok(has_diff); - } - EmitMode::Checkstyle => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - let diff = make_diff(&ori, formatted_text, 3); - output_checkstyle_file(out, filename, diff)?; - } - EmitMode::Diff => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - let mismatch = make_diff(&ori, formatted_text, 3); - let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), - config, - ); - return Ok(has_diff); - } - } - - // when we are not in diff mode, don't indicate differing files - Ok(false) -} diff --git a/src/formatting.rs b/src/formatting.rs index a695d3363a6..2c44f21417d 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -7,7 +7,7 @@ use std::rc::Rc; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::codemap::{CodeMap, FilePathMapping, Span}; +use syntax::source_map::{SourceMap, FilePathMapping, Span}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::Handler; use syntax::parse::{self, ParseSess}; @@ -16,10 +16,10 @@ use comment::{CharClasses, FullCodeCharKind}; use config::{Config, FileName, Verbosity}; use issues::BadIssueSeeker; use visitor::{FmtVisitor, SnippetProvider}; -use {filemap, modules, ErrorKind, FormatReport, Input, Session}; +use {source_file, modules, ErrorKind, FormatReport, Input, Session}; // A map of the files of a crate, with their new content -pub(crate) type FileMap = Vec; +pub(crate) type SourceFile = Vec; pub(crate) type FileRecord = (FileName, String); impl<'b, T: Write + 'b> Session<'b, T> { @@ -70,19 +70,19 @@ fn format_project( let input_is_stdin = main_file == FileName::Stdin; // Parse the crate. - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - let mut parse_session = make_parse_sess(codemap.clone(), config); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let mut parse_session = make_parse_sess(source_map.clone(), config); let mut report = FormatReport::new(); let krate = parse_crate(input, &parse_session, config, &mut report)?; timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. - let silent_emitter = silent_emitter(codemap); + let silent_emitter = silent_emitter(source_map); parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); - let files = modules::list_files(&krate, context.parse_session.codemap())?; + let files = modules::list_files(&krate, context.parse_session.source_map())?; for (path, module) in files { if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { continue; @@ -122,14 +122,14 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { module: &ast::Mod, is_root: bool, ) -> Result<(), ErrorKind> { - let filemap = self + let source_file = self .parse_session - .codemap() + .source_map() .lookup_char_pos(module.inner.lo()) .file; - let big_snippet = filemap.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet); - let mut visitor = FmtVisitor::from_codemap( + let big_snippet = source_file.src.as_ref().unwrap(); + let snippet_provider = SnippetProvider::new(source_file.start_pos, big_snippet); + let mut visitor = FmtVisitor::from_source_map( &self.parse_session, &self.config, &snippet_provider, @@ -138,16 +138,16 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { // Format inner attributes if available. if !self.krate.attrs.is_empty() && is_root { - visitor.skip_empty_lines(filemap.end_pos); + visitor.skip_empty_lines(source_file.end_pos); if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); } else { - visitor.format_separate_mod(module, &*filemap); + visitor.format_separate_mod(module, &*source_file); } } else { - visitor.last_pos = filemap.start_pos; - visitor.skip_empty_lines(filemap.end_pos); - visitor.format_separate_mod(module, &*filemap); + visitor.last_pos = source_file.start_pos; + visitor.skip_empty_lines(source_file.end_pos); + visitor.format_separate_mod(module, &*source_file); }; debug_assert_eq!( @@ -155,9 +155,9 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { ::utils::count_newlines(&visitor.buffer) ); - // For some reason, the codemap does not include terminating + // For some reason, the source_map does not include terminating // newlines so we must add one on for each file. This is sad. - filemap::append_newline(&mut visitor.buffer); + source_file::append_newline(&mut visitor.buffer); format_lines( &mut visitor.buffer, @@ -198,7 +198,7 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { - match filemap::write_file(&mut result, &path, out, &self.config) { + match source_file::write_file(&mut result, &path, out, &self.config) { Ok(b) if b => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed @@ -209,7 +209,7 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { } } - self.filemap.push((path, result)); + self.source_file.push((path, result)); Ok(()) } } @@ -223,13 +223,13 @@ pub(crate) struct FormattingError { } impl FormattingError { - pub(crate) fn from_span(span: &Span, codemap: &CodeMap, kind: ErrorKind) -> FormattingError { + pub(crate) fn from_span(span: &Span, source_map: &SourceMap, kind: ErrorKind) -> FormattingError { FormattingError { - line: codemap.lookup_char_pos(span.lo()).line, + line: source_map.lookup_char_pos(span.lo()).line, is_comment: kind.is_comment(), kind, is_string: false, - line_buffer: codemap + line_buffer: source_map .span_to_lines(*span) .ok() .and_then(|fl| { @@ -587,7 +587,7 @@ fn parse_crate( Input::File(file) => parse::new_parser_from_file(parse_session, &file), Input::Text(text) => parse::new_parser_from_source_str( parse_session, - syntax::codemap::FileName::Custom("stdin".to_owned()), + syntax::source_map::FileName::Custom("stdin".to_owned()), text, ), }; @@ -621,18 +621,18 @@ fn parse_crate( Err(ErrorKind::ParseError) } -fn silent_emitter(codemap: Rc) -> Box { +fn silent_emitter(source_map: Rc) -> Box { Box::new(EmitterWriter::new( Box::new(Vec::new()), - Some(codemap), + Some(source_map), false, false, )) } -fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { +fn make_parse_sess(source_map: Rc, config: &Config) -> ParseSess { let tty_handler = if config.hide_parse_errors() { - let silent_emitter = silent_emitter(codemap.clone()); + let silent_emitter = silent_emitter(source_map.clone()); Handler::with_emitter(true, false, silent_emitter) } else { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); @@ -641,10 +641,10 @@ fn make_parse_sess(codemap: Rc, config: &Config) -> ParseSess { } else { ColorConfig::Never }; - Handler::with_tty_emitter(color_cfg, true, false, Some(codemap.clone())) + Handler::with_tty_emitter(color_cfg, true, false, Some(source_map.clone())) }; - ParseSess::with_span_handler(tty_handler, codemap) + ParseSess::with_span_handler(tty_handler, source_map) } fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) diff --git a/src/imports.rs b/src/imports.rs index 2007d05bc54..d964a21edc3 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -12,9 +12,9 @@ use std::cmp::Ordering; use config::lists::*; use syntax::ast::{self, UseTreeKind}; -use syntax::codemap::{self, BytePos, Span, DUMMY_SP}; +use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; -use codemap::SpanUtils; +use source_map::SpanUtils; use comment::combine_strs_with_missing_comments; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; @@ -470,7 +470,7 @@ impl UseTree { fn same_visibility(&self, other: &UseTree) -> bool { match (&self.visibility, &other.visibility) { ( - Some(codemap::Spanned { + Some(source_map::Spanned { node: ast::VisibilityKind::Inherited, .. }), @@ -478,7 +478,7 @@ impl UseTree { ) | ( None, - Some(codemap::Spanned { + Some(source_map::Spanned { node: ast::VisibilityKind::Inherited, .. }), @@ -785,7 +785,7 @@ impl Rewrite for UseTree { #[cfg(test)] mod test { use super::*; - use syntax::codemap::DUMMY_SP; + use syntax::source_map::DUMMY_SP; // Parse the path part of an import. This parser is not robust and is only // suitable for use in a test harness. diff --git a/src/items.rs b/src/items.rs index 0152fb8794c..51f11d8f58a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -16,11 +16,11 @@ use std::cmp::{min, Ordering}; use config::lists::*; use regex::Regex; use rustc_target::spec::abi; -use syntax::codemap::{self, BytePos, Span}; +use syntax::source_map::{self, BytePos, Span}; use syntax::visit; use syntax::{ast, ptr, symbol}; -use codemap::{LineRangeUtils, SpanUtils}; +use source_map::{LineRangeUtils, SpanUtils}; use comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented, @@ -40,9 +40,9 @@ use utils::*; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; -const DEFAULT_VISIBILITY: ast::Visibility = codemap::Spanned { +const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned { node: ast::VisibilityKind::Inherited, - span: codemap::DUMMY_SP, + span: source_map::DUMMY_SP, }; fn type_annotation_separator(config: &Config) -> &str { @@ -380,16 +380,16 @@ impl<'a> FmtVisitor<'a> { return None; } - let codemap = self.get_context().codemap; + let source_map = self.get_context().source_map; if self.config.empty_item_single_line() - && is_empty_block(block, None, codemap) + && is_empty_block(block, None, source_map) && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() { return Some(format!("{}{{}}", fn_str)); } - if self.config.fn_single_line() && is_simple_block_stmt(block, None, codemap) { + if self.config.fn_single_line() && is_simple_block_stmt(block, None, source_map) { let rewrite = { if let Some(stmt) = block.stmts.first() { match stmt_expr(stmt) { diff --git a/src/lib.rs b/src/lib.rs index 0ee913690b0..0131aa875d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{FileMap, FormatErrorMap, FormattingError, ReportedErrors}; +use formatting::{SourceFile, FormatErrorMap, FormattingError, ReportedErrors}; use issues::Issue; use shape::Indent; @@ -65,11 +65,11 @@ mod attr; mod chains; pub(crate) mod checkstyle; mod closures; -pub(crate) mod codemap; +pub(crate) mod source_map; mod comment; pub(crate) mod config; mod expr; -pub(crate) mod filemap; +pub(crate) mod source_file; pub(crate) mod formatting; mod imports; mod issues; @@ -459,7 +459,7 @@ pub struct Session<'b, T: Write + 'b> { pub config: Config, pub out: Option<&'b mut T>, pub(crate) errors: ReportedErrors, - filemap: FileMap, + source_file: SourceFile, } impl<'b, T: Write + 'b> Session<'b, T> { @@ -472,7 +472,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { config, out, errors: ReportedErrors::default(), - filemap: FileMap::new(), + source_file: SourceFile::new(), } } diff --git a/src/lists.rs b/src/lists.rs index 49548cc26a3..9b65fdbd1da 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -14,7 +14,7 @@ use std::cmp; use std::iter::Peekable; use config::lists::*; -use syntax::codemap::BytePos; +use syntax::source_map::BytePos; use comment::{find_comment_end, rewrite_comment, FindUncommented}; use config::{Config, IndentStyle}; diff --git a/src/macros.rs b/src/macros.rs index df7b3cdb918..9bbee1097e1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,7 +22,7 @@ use std::collections::HashMap; use config::lists::*; -use syntax::codemap::{BytePos, Span}; +use syntax::source_map::{BytePos, Span}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; use syntax::parse::token::{BinOpToken, DelimToken, Token}; @@ -32,7 +32,7 @@ use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, ptr}; -use codemap::SpanUtils; +use source_map::SpanUtils; use comment::{ contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, diff --git a/src/matches.rs b/src/matches.rs index 29e9f19ad7d..0ee63fb0c5a 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -13,10 +13,10 @@ use std::iter::repeat; use config::lists::*; -use syntax::codemap::{BytePos, Span}; +use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; -use codemap::SpanUtils; +use source_map::SpanUtils; use comment::{combine_strs_with_missing_comments, rewrite_comment}; use config::{Config, ControlBraceStyle, IndentStyle}; use expr::{ @@ -302,7 +302,7 @@ fn block_can_be_flattened<'a>( match expr.node { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) - && is_simple_block(block, Some(&expr.attrs), context.codemap) => + && is_simple_block(block, Some(&expr.attrs), context.source_map) => { Some(&*block) } @@ -347,7 +347,7 @@ fn rewrite_match_body( let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.node { ( true, - is_empty_block(block, Some(&body.attrs), context.codemap), + is_empty_block(block, Some(&body.attrs), context.source_map), ) } else { (false, false) diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 70d4c66d7fb..f61098ed879 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -10,9 +10,9 @@ use std::borrow::Cow; -use syntax::codemap::{BytePos, Pos, Span}; +use syntax::source_map::{BytePos, Pos, Span}; -use codemap::LineRangeUtils; +use source_map::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::{EmitMode, FileName}; use shape::{Indent, Shape}; @@ -97,8 +97,8 @@ impl<'a> FmtVisitor<'a> { assert!( start < end, "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end) + self.source_map.lookup_char_pos(start), + self.source_map.lookup_char_pos(end) ); self.last_pos = end; @@ -159,9 +159,9 @@ impl<'a> FmtVisitor<'a> { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment // follows code on the same line, we won't touch it. - let big_span_lo = self.codemap.lookup_char_pos(span.lo()).file.start_pos; - let local_begin = self.codemap.lookup_byte_offset(big_span_lo); - let local_end = self.codemap.lookup_byte_offset(span.hi()); + let big_span_lo = self.source_map.lookup_char_pos(span.lo()).file.start_pos; + let local_begin = self.source_map.lookup_byte_offset(big_span_lo); + let local_end = self.source_map.lookup_byte_offset(span.hi()); let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; @@ -187,7 +187,7 @@ impl<'a> FmtVisitor<'a> { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. - let char_pos = self.codemap.lookup_char_pos(span.lo()); + let char_pos = self.source_map.lookup_char_pos(span.lo()); let file_name = &char_pos.file.name.clone().into(); let mut status = SnippetStatus::new(char_pos.line); diff --git a/src/modules.rs b/src/modules.rs index 7619c0afa57..2f5743fbedf 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -13,7 +13,7 @@ use std::io; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::codemap; +use syntax::source_map; use syntax::parse::{parser, DirectoryOwnership}; use syntax_pos::symbol::Symbol; @@ -24,16 +24,16 @@ use utils::contains_skip; /// If a file is used twice in a crate, it appears only once. pub fn list_files<'a>( krate: &'a ast::Crate, - codemap: &codemap::CodeMap, + source_map: &source_map::SourceMap, ) -> Result, io::Error> { let mut result = BTreeMap::new(); // Enforce file order determinism - let root_filename = codemap.span_to_filename(krate.span); + let root_filename = source_map.span_to_filename(krate.span); { let parent = match root_filename { - codemap::FileName::Real(ref path) => path.parent().unwrap(), + source_map::FileName::Real(ref path) => path.parent().unwrap(), _ => Path::new(""), }; - list_submodules(&krate.module, parent, None, codemap, &mut result)?; + list_submodules(&krate.module, parent, None, source_map, &mut result)?; } result.insert(root_filename.into(), &krate.module); Ok(result) @@ -59,7 +59,7 @@ fn list_submodules<'a>( module: &'a ast::Mod, search_dir: &Path, relative: Option, - codemap: &codemap::CodeMap, + source_map: &source_map::SourceMap, result: &mut BTreeMap, ) -> Result<(), io::Error> { debug!("list_submodules: search_dir: {:?}", search_dir); @@ -67,7 +67,7 @@ fn list_submodules<'a>( if let ast::ItemKind::Mod(ref sub_mod) = item.node { if !contains_skip(&item.attrs) { let is_internal = - codemap.span_to_filename(item.span) == codemap.span_to_filename(sub_mod.inner); + source_map.span_to_filename(item.span) == source_map.span_to_filename(sub_mod.inner); let (dir_path, relative) = if is_internal { if let Some(path) = find_path_value(&item.attrs) { (search_dir.join(&path.as_str()), None) @@ -76,12 +76,12 @@ fn list_submodules<'a>( } } else { let (mod_path, relative) = - module_file(item.ident, &item.attrs, search_dir, relative, codemap)?; + module_file(item.ident, &item.attrs, search_dir, relative, source_map)?; let dir_path = mod_path.parent().unwrap().to_owned(); result.insert(FileName::Real(mod_path), sub_mod); (dir_path, relative) }; - list_submodules(sub_mod, &dir_path, relative, codemap, result)?; + list_submodules(sub_mod, &dir_path, relative, source_map, result)?; } } } @@ -94,13 +94,13 @@ fn module_file( attrs: &[ast::Attribute], dir_path: &Path, relative: Option, - codemap: &codemap::CodeMap, + source_map: &source_map::SourceMap, ) -> Result<(PathBuf, Option), io::Error> { if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { return Ok((path, None)); } - match parser::Parser::default_submod_path(id, relative, dir_path, codemap).result { + match parser::Parser::default_submod_path(id, relative, dir_path, source_map).result { Ok(parser::ModulePathSuccess { path, directory_ownership, diff --git a/src/overflow.rs b/src/overflow.rs index e18fe140c8d..6e63649ca80 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -13,11 +13,11 @@ use config::lists::*; use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; use syntax::parse::token::DelimToken; use closures; -use codemap::SpanUtils; +use source_map::SpanUtils; use expr::{is_every_expr_simple, is_method_call, is_nested_call, maybe_get_args_offset, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; diff --git a/src/patterns.rs b/src/patterns.rs index 465d64627e8..b58431cbb65 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -10,10 +10,10 @@ use config::lists::*; use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; -use syntax::codemap::{self, BytePos, Span}; +use syntax::source_map::{self, BytePos, Span}; use syntax::ptr; -use codemap::SpanUtils; +use source_map::SpanUtils; use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use lists::{ @@ -171,7 +171,7 @@ impl Rewrite for Pat { fn rewrite_struct_pat( path: &ast::Path, - fields: &[codemap::Spanned], + fields: &[source_map::Spanned], ellipsis: bool, span: Span, context: &RewriteContext, @@ -332,7 +332,7 @@ fn rewrite_tuple_pat( lo, // 2 == "..".len() lo + BytePos(2), - codemap::NO_EXPANSION, + source_map::NO_EXPANSION, )); pat_vec.insert(pos, dotdot); } diff --git a/src/reorder.rs b/src/reorder.rs index bc429a10ab6..21a3797a6e4 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -17,10 +17,10 @@ // FIXME(#2455): Reorder trait items. use config::Config; -use syntax::{ast, attr, codemap::Span}; +use syntax::{ast, attr, source_map::Span}; use attr::filter_inline_attrs; -use codemap::LineRangeUtils; +use source_map::LineRangeUtils; use comment::combine_strs_with_missing_comments; use imports::{merge_use_trees, UseTree}; use items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; @@ -226,13 +226,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item_kind: ReorderableItemKind, in_group: bool, ) -> usize { - let mut last = self.codemap.lookup_line_range(items[0].span()); + let mut last = self.source_map.lookup_line_range(items[0].span()); let item_length = items .iter() .take_while(|ppi| { item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.codemap.lookup_line_range(ppi.span()); + let current = self.source_map.lookup_line_range(ppi.span()); let in_same_group = current.lo < last.hi + 2; last = current; in_same_group diff --git a/src/rewrite.rs b/src/rewrite.rs index 90b613df6c4..232f4311155 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -10,7 +10,7 @@ // A generic trait to abstract the rewriting of an element (of the AST). -use syntax::codemap::{CodeMap, Span}; +use syntax::source_map::{SourceMap, Span}; use syntax::parse::ParseSess; use config::{Config, IndentStyle}; @@ -28,7 +28,7 @@ pub trait Rewrite { #[derive(Clone)] pub struct RewriteContext<'a> { pub parse_session: &'a ParseSess, - pub codemap: &'a CodeMap, + pub source_map: &'a SourceMap, pub config: &'a Config, pub inside_macro: RefCell, // Force block indent style even if we are using visual indent style. diff --git a/src/source_file.rs b/src/source_file.rs new file mode 100644 index 00000000000..306f2626639 --- /dev/null +++ b/src/source_file.rs @@ -0,0 +1,122 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::fs; +use std::io::{self, Write}; + +use checkstyle::output_checkstyle_file; +use config::{Config, EmitMode, FileName, Verbosity}; +use rustfmt_diff::{make_diff, output_modified, print_diff}; + +#[cfg(test)] +use formatting::FileRecord; + +// Append a newline to the end of each file. +pub fn append_newline(s: &mut String) { + s.push_str("\n"); +} + +#[cfg(test)] +pub(crate) fn write_all_files( + source_file: &[FileRecord], + out: &mut T, + config: &Config, +) -> Result<(), io::Error> +where + T: Write, +{ + if config.emit_mode() == EmitMode::Checkstyle { + write!(out, "{}", ::checkstyle::header())?; + } + for &(ref filename, ref text) in source_file { + write_file(text, filename, out, config)?; + } + if config.emit_mode() == EmitMode::Checkstyle { + write!(out, "{}", ::checkstyle::footer())?; + } + + Ok(()) +} + +pub fn write_file( + formatted_text: &str, + filename: &FileName, + out: &mut T, + config: &Config, +) -> Result +where + T: Write, +{ + let filename_to_path = || match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` and emit to files", filename), + }; + + match config.emit_mode() { + EmitMode::Files if config.make_backup() => { + let filename = filename_to_path(); + let ori = fs::read_to_string(filename)?; + if ori != formatted_text { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.with_extension("tmp"); + let bk_name = filename.with_extension("bk"); + + fs::write(&tmp_name, formatted_text)?; + fs::rename(filename, bk_name)?; + fs::rename(tmp_name, filename)?; + } + } + EmitMode::Files => { + // Write text directly over original file if there is a diff. + let filename = filename_to_path(); + let ori = fs::read_to_string(filename)?; + if ori != formatted_text { + fs::write(filename, formatted_text)?; + } + } + EmitMode::Stdout | EmitMode::Coverage => { + if config.verbose() != Verbosity::Quiet { + println!("{}:\n", filename); + } + write!(out, "{}", formatted_text)?; + } + EmitMode::ModifiedLines => { + let filename = filename_to_path(); + let ori = fs::read_to_string(filename)?; + let mismatch = make_diff(&ori, formatted_text, 0); + let has_diff = !mismatch.is_empty(); + output_modified(out, mismatch); + return Ok(has_diff); + } + EmitMode::Checkstyle => { + let filename = filename_to_path(); + let ori = fs::read_to_string(filename)?; + let diff = make_diff(&ori, formatted_text, 3); + output_checkstyle_file(out, filename, diff)?; + } + EmitMode::Diff => { + let filename = filename_to_path(); + let ori = fs::read_to_string(filename)?; + let mismatch = make_diff(&ori, formatted_text, 3); + let has_diff = !mismatch.is_empty(); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), + config, + ); + return Ok(has_diff); + } + } + + // when we are not in diff mode, don't indicate differing files + Ok(false) +} diff --git a/src/source_map.rs b/src/source_map.rs new file mode 100644 index 00000000000..678e4fe4cc6 --- /dev/null +++ b/src/source_map.rs @@ -0,0 +1,92 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains utilities that work with the `SourceMap` from `libsyntax` / `syntex_syntax`. +//! This includes extension traits and methods for looking up spans and line ranges for AST nodes. + +use config::file_lines::LineRange; +use syntax::source_map::{BytePos, SourceMap, Span}; +use visitor::SnippetProvider; + +use comment::FindUncommented; + +pub trait SpanUtils { + fn span_after(&self, original: Span, needle: &str) -> BytePos; + fn span_after_last(&self, original: Span, needle: &str) -> BytePos; + fn span_before(&self, original: Span, needle: &str) -> BytePos; + fn opt_span_after(&self, original: Span, needle: &str) -> Option; + fn opt_span_before(&self, original: Span, needle: &str) -> Option; +} + +pub trait LineRangeUtils { + /// Returns the `LineRange` that corresponds to `span` in `self`. + /// + /// # Panics + /// + /// Panics if `span` crosses a file boundary, which shouldn't happen. + fn lookup_line_range(&self, span: Span) -> LineRange; +} + +impl<'a> SpanUtils for SnippetProvider<'a> { + fn span_after(&self, original: Span, needle: &str) -> BytePos { + self.opt_span_after(original, needle).expect("bad span") + } + + fn span_after_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo() + BytePos(offset as u32) + } + + fn span_before(&self, original: Span, needle: &str) -> BytePos { + self.opt_span_before(original, needle).expect(&format!( + "bad span: {}: {}", + needle, + self.span_to_snippet(original).unwrap() + )) + } + + fn opt_span_after(&self, original: Span, needle: &str) -> Option { + self.opt_span_before(original, needle) + .map(|bytepos| bytepos + BytePos(needle.len() as u32)) + } + + fn opt_span_before(&self, original: Span, needle: &str) -> Option { + let snippet = self.span_to_snippet(original)?; + let offset = snippet.find_uncommented(needle)?; + + Some(original.lo() + BytePos(offset as u32)) + } +} + +impl LineRangeUtils for SourceMap { + fn lookup_line_range(&self, span: Span) -> LineRange { + let lo = self.lookup_line(span.lo()).unwrap(); + let hi = self.lookup_line(span.hi()).unwrap(); + + debug_assert_eq!( + lo.fm.name, hi.fm.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, hi + ); + + // Line numbers start at 1 + LineRange { + file: lo.fm.clone(), + lo: lo.line + 1, + hi: hi.line + 1, + } + } +} diff --git a/src/spanned.rs b/src/spanned.rs index c2886fcdd8f..a7ba0f1a72d 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -9,7 +9,7 @@ // except according to those terms. use syntax::ast; -use syntax::codemap::Span; +use syntax::source_map::Span; use macros::MacroArg; use utils::{mk_sp, outer_attributes}; diff --git a/src/test/mod.rs b/src/test/mod.rs index beba2628112..35a720e4c56 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -20,8 +20,8 @@ use std::path::{Path, PathBuf}; use std::str::Chars; use config::{Color, Config, EmitMode, FileName, ReportTactic}; -use filemap; -use formatting::{FileMap, ModifiedChunk}; +use source_file; +use formatting::{SourceFile, ModifiedChunk}; use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; use {FormatReport, Input, Session}; @@ -197,11 +197,11 @@ fn modified_test() { // to a known output file generated by one of the write modes. fn assert_output(source: &Path, expected_filename: &Path) { let config = read_config(source); - let (_, file_map, _) = format_file(source, config.clone()); + let (_, source_file, _) = format_file(source, config.clone()); // Populate output by writing to a vec. let mut out = vec![]; - let _ = filemap::write_all_files(&file_map, &mut out, &config); + let _ = source_file::write_all_files(&source_file, &mut out, &config); let output = String::from_utf8(out).unwrap(); let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); @@ -414,15 +414,15 @@ fn read_config(filename: &Path) -> Config { config } -fn format_file>(filepath: P, config: Config) -> (bool, FileMap, FormatReport) { +fn format_file>(filepath: P, config: Config) -> (bool, SourceFile, FormatReport) { let filepath = filepath.into(); let input = Input::File(filepath); let mut session = Session::::new(config, None); let result = session.format(input).unwrap(); let parsing_errors = session.has_parsing_errors(); - let mut filemap = FileMap::new(); - mem::swap(&mut session.filemap, &mut filemap); - (parsing_errors, filemap, result) + let mut source_file = SourceFile::new(); + mem::swap(&mut session.source_file, &mut source_file); + (parsing_errors, source_file, result) } enum IdempotentCheckError { @@ -440,13 +440,13 @@ fn idempotent_check( } else { read_config(filename) }; - let (parsing_errors, file_map, format_report) = format_file(filename, config); + let (parsing_errors, source_file, format_report) = format_file(filename, config); if parsing_errors { return Err(IdempotentCheckError::Parse); } let mut write_result = HashMap::new(); - for (filename, text) in file_map { + for (filename, text) in source_file { if let FileName::Real(ref filename) = filename { write_result.insert(filename.to_owned(), text); } diff --git a/src/types.rs b/src/types.rs index 360c7304988..601868bf1f3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -13,10 +13,10 @@ use std::ops::Deref; use config::lists::*; use syntax::ast::{self, FunctionRetTy, Mutability}; -use syntax::codemap::{self, BytePos, Span}; +use syntax::source_map::{self, BytePos, Span}; use syntax::symbol::keywords; -use codemap::SpanUtils; +use source_map::SpanUtils; use config::{IndentStyle, TypeDensity}; use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; @@ -267,7 +267,7 @@ fn rewrite_segment( ast::GenericArgs::Parenthesized(ref data) => { let output = match data.output { Some(ref ty) => FunctionRetTy::Ty(ty.clone()), - None => FunctionRetTy::Default(codemap::DUMMY_SP), + None => FunctionRetTy::Default(source_map::DUMMY_SP), }; result.push_str(&format_function_type( data.inputs.iter().map(|x| &**x), diff --git a/src/utils.rs b/src/utils.rs index 9eac3fd4f0d..1bfccf237b4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,7 +15,7 @@ use syntax::ast::{ self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, Visibility, VisibilityKind, }; -use syntax::codemap::{BytePos, Span, NO_EXPANSION}; +use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use syntax::ptr; use comment::filter_normal_code; @@ -327,7 +327,7 @@ macro_rules! out_of_file_lines_range { !$self.config.file_lines().is_all() && !$self .config .file_lines() - .intersects(&$self.codemap.lookup_line_range($span)) + .intersects(&$self.source_map.lookup_line_range($span)) }; } diff --git a/src/vertical.rs b/src/vertical.rs index c6721bc5010..98f90530e8b 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -14,9 +14,9 @@ use std::cmp; use config::lists::*; use syntax::ast; -use syntax::codemap::{BytePos, Span}; +use syntax::source_map::{BytePos, Span}; -use codemap::SpanUtils; +use source_map::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; diff --git a/src/visitor.rs b/src/visitor.rs index c80cd78a992..bc500281a88 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -9,12 +9,12 @@ // except according to those terms. use syntax::attr::HasAttrs; -use syntax::codemap::{self, BytePos, CodeMap, Pos, Span}; +use syntax::source_map::{self, BytePos, SourceMap, Pos, Span}; use syntax::parse::ParseSess; use syntax::{ast, visit}; use attr::*; -use codemap::{LineRangeUtils, SpanUtils}; +use source_map::{LineRangeUtils, SpanUtils}; use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; use config::{BraceStyle, Config}; use items::{ @@ -61,7 +61,7 @@ impl<'a> SnippetProvider<'a> { pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, - pub codemap: &'a CodeMap, + pub source_map: &'a SourceMap, pub buffer: String, pub last_pos: BytePos, // FIXME: use an RAII util or closure for indenting @@ -83,8 +83,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &ast::Stmt) { debug!( "visit_stmt: {:?} {:?}", - self.codemap.lookup_char_pos(stmt.span.lo()), - self.codemap.lookup_char_pos(stmt.span.hi()) + self.source_map.lookup_char_pos(stmt.span.lo()), + self.source_map.lookup_char_pos(stmt.span.hi()) ); match stmt.node { @@ -121,8 +121,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) { debug!( "visit_block: {:?} {:?}", - self.codemap.lookup_char_pos(b.span.lo()), - self.codemap.lookup_char_pos(b.span.hi()) + self.source_map.lookup_char_pos(b.span.lo()), + self.source_map.lookup_char_pos(b.span.hi()) ); // Check if this block has braces. @@ -575,7 +575,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { - FmtVisitor::from_codemap( + FmtVisitor::from_source_map( ctx.parse_session, ctx.config, ctx.snippet_provider, @@ -583,7 +583,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) } - pub(crate) fn from_codemap( + pub(crate) fn from_source_map( parse_session: &'a ParseSess, config: &'a Config, snippet_provider: &'a SnippetProvider, @@ -591,7 +591,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) -> FmtVisitor<'a> { FmtVisitor { parse_session, - codemap: parse_session.codemap(), + source_map: parse_session.source_map(), buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), last_pos: BytePos(0), block_indent: Indent::empty(), @@ -617,12 +617,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { if attr.name() == DEPR_SKIP_ANNOTATION { - let file_name = self.codemap.span_to_filename(attr.span).into(); + let file_name = self.source_map.span_to_filename(attr.span).into(); self.report.append( file_name, vec![FormattingError::from_span( &attr.span, - &self.codemap, + &self.source_map, ErrorKind::DeprecatedAttr, )], ); @@ -630,12 +630,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if attr.path.segments.len() == 1 || attr.path.segments[1].ident.to_string() != "skip" { - let file_name = self.codemap.span_to_filename(attr.span).into(); + let file_name = self.source_map.span_to_filename(attr.span).into(); self.report.append( file_name, vec![FormattingError::from_span( &attr.span, - &self.codemap, + &self.source_map, ErrorKind::BadAttr, )], ); @@ -741,10 +741,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub fn format_separate_mod(&mut self, m: &ast::Mod, filemap: &codemap::FileMap) { + pub fn format_separate_mod(&mut self, m: &ast::Mod, source_file: &source_map::SourceFile) { self.block_indent = Indent::empty(); self.walk_mod_items(m); - self.format_missing_with_indent(filemap.end_pos); + self.format_missing_with_indent(source_file.end_pos); } pub fn skip_empty_lines(&mut self, end_pos: BytePos) { @@ -779,7 +779,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn get_context(&self) -> RewriteContext { RewriteContext { parse_session: self.parse_session, - codemap: self.codemap, + source_map: self.source_map, config: self.config, inside_macro: RefCell::new(false), use_block: RefCell::new(false), diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index f08fd317a51..48cc1fd72ae 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -77,7 +77,7 @@ fn arrays() { } fn function_calls() { - let items = itemize_list(context.codemap, + let items = itemize_list(context.source_map, args.iter(), ")", |item| item.span.lo(), @@ -92,7 +92,7 @@ fn function_calls() { span.lo(), span.hi()); - itemize_list(context.codemap, + itemize_list(context.source_map, args.iter(), ")", |item| item.span.lo(), diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 56f90808ab7..7098d65f100 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -9,7 +9,7 @@ fn foo() -> bool { let very_long_variable_name = ( a + first + simple + test ); let very_long_variable_name = (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); - let is_internalxxxx = self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + let is_internalxxxx = self.source_map.span_to_filename(s) == self.source_map.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 501ee3eaea0..d3a45566efa 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -73,7 +73,7 @@ fn arrays() { fn function_calls() { let items = itemize_list( - context.codemap, + context.source_map, args.iter(), ")", |item| item.span.lo(), @@ -92,7 +92,7 @@ fn function_calls() { ); itemize_list( - context.codemap, + context.source_map, args.iter(), ")", |item| item.span.lo(), diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 370e31bdabe..2e2312a11d5 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -11,7 +11,7 @@ fn foo() -> bool { (a + first + simple + test + AAAAAAAAAAAAA + BBBBBBBBBBBBBBBBB + b + c); let is_internalxxxx = - self.codemap.span_to_filename(s) == self.codemap.span_to_filename(m.inner); + self.source_map.span_to_filename(s) == self.source_map.span_to_filename(m.inner); let some_val = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa * bbbb / (bbbbbb - function_call(x, *very_long_pointer, y)) diff --git a/tests/target/nested-visual-block.rs b/tests/target/nested-visual-block.rs index 95b9bc2dea2..ed6c181fc7b 100644 --- a/tests/target/nested-visual-block.rs +++ b/tests/target/nested-visual-block.rs @@ -1,7 +1,7 @@ fn main() { // #1078 let items = itemize_list( - context.codemap, + context.source_map, field_iter, "}", |item| match *item { @@ -33,7 +33,7 @@ fn main() { } } }, - context.codemap.span_after(span, "{"), + context.source_map.span_after(span, "{"), span.hi(), ); -- cgit 1.4.1-3-g733a5 From fc1909d311cebd2920b968b8fe161267c12c5fe1 Mon Sep 17 00:00:00 2001 From: cad97 Date: Thu, 23 Aug 2018 17:14:19 -0400 Subject: Reformat --- src/chains.rs | 2 +- src/closures.rs | 4 ++-- src/expr.rs | 8 +++++--- src/formatting.rs | 10 +++++++--- src/imports.rs | 2 +- src/items.rs | 2 +- src/lib.rs | 6 +++--- src/macros.rs | 4 ++-- src/matches.rs | 2 +- src/missed_spans.rs | 2 +- src/modules.rs | 6 +++--- src/overflow.rs | 4 ++-- src/patterns.rs | 4 ++-- src/reorder.rs | 2 +- src/rewrite.rs | 2 +- src/source_map.rs | 2 +- src/test/mod.rs | 4 ++-- src/types.rs | 2 +- src/utils.rs | 2 +- src/vertical.rs | 2 +- src/visitor.rs | 4 ++-- 21 files changed, 41 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 8686d2c66b9..3f5ff75a722 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -65,7 +65,6 @@ //! .qux //! ``` -use source_map::SpanUtils; use comment::rewrite_comment; use config::IndentStyle; use expr::rewrite_call; @@ -73,6 +72,7 @@ use lists::{extract_post_comment, extract_pre_comment, get_comment_end}; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use utils::{ first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, wrap_str, diff --git a/src/closures.rs b/src/closures.rs index e786339ed7c..f6a3d8436f2 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -9,16 +9,16 @@ // except according to those terms. use config::lists::*; -use syntax::source_map::Span; use syntax::parse::classify; +use syntax::source_map::Span; use syntax::{ast, ptr}; -use source_map::SpanUtils; use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use utils::{last_line_width, left_most_sub_expr, stmt_expr}; // This module is pretty messy because of the rules around closures and blocks: diff --git a/src/expr.rs b/src/expr.rs index 909ea46f75d..e6161c0c42b 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,13 +12,12 @@ use std::borrow::Cow; use std::cmp::min; use config::lists::*; -use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::parse::token::DelimToken; +use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::{ast, ptr}; use chains::rewrite_chain; use closures; -use source_map::{LineRangeUtils, SpanUtils}; use comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, @@ -35,6 +34,7 @@ use pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; @@ -425,7 +425,9 @@ fn rewrite_empty_block( return None; } - if block.stmts.is_empty() && !block_contains_comment(block, context.source_map) && shape.width >= 2 + if block.stmts.is_empty() + && !block_contains_comment(block, context.source_map) + && shape.width >= 2 { return Some(format!("{}{}{{}}", prefix, label_str)); } diff --git a/src/formatting.rs b/src/formatting.rs index 2c44f21417d..3012837ba64 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -7,16 +7,16 @@ use std::rc::Rc; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::source_map::{SourceMap, FilePathMapping, Span}; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::Handler; use syntax::parse::{self, ParseSess}; +use syntax::source_map::{FilePathMapping, SourceMap, Span}; use comment::{CharClasses, FullCodeCharKind}; use config::{Config, FileName, Verbosity}; use issues::BadIssueSeeker; use visitor::{FmtVisitor, SnippetProvider}; -use {source_file, modules, ErrorKind, FormatReport, Input, Session}; +use {modules, source_file, ErrorKind, FormatReport, Input, Session}; // A map of the files of a crate, with their new content pub(crate) type SourceFile = Vec; @@ -223,7 +223,11 @@ pub(crate) struct FormattingError { } impl FormattingError { - pub(crate) fn from_span(span: &Span, source_map: &SourceMap, kind: ErrorKind) -> FormattingError { + pub(crate) fn from_span( + span: &Span, + source_map: &SourceMap, + kind: ErrorKind, + ) -> FormattingError { FormattingError { line: source_map.lookup_char_pos(span.lo()).line, is_comment: kind.is_comment(), diff --git a/src/imports.rs b/src/imports.rs index d964a21edc3..a2d14c129d9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -14,12 +14,12 @@ use config::lists::*; use syntax::ast::{self, UseTreeKind}; use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; -use source_map::SpanUtils; use comment::combine_strs_with_missing_comments; use config::IndentStyle; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use spanned::Spanned; use utils::{is_same_visibility, mk_sp, rewrite_ident}; use visitor::FmtVisitor; diff --git a/src/items.rs b/src/items.rs index 51f11d8f58a..ff635137e42 100644 --- a/src/items.rs +++ b/src/items.rs @@ -20,7 +20,6 @@ use syntax::source_map::{self, BytePos, Span}; use syntax::visit; use syntax::{ast, ptr, symbol}; -use source_map::{LineRangeUtils, SpanUtils}; use comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented, @@ -35,6 +34,7 @@ use macros::{rewrite_macro, MacroPosition}; use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use utils::*; use vertical::rewrite_with_alignment; diff --git a/src/lib.rs b/src/lib.rs index 0131aa875d7..89dcf6f5ff3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,7 @@ use syntax::ast; use comment::LineClasses; use failure::Fail; -use formatting::{SourceFile, FormatErrorMap, FormattingError, ReportedErrors}; +use formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use issues::Issue; use shape::Indent; @@ -65,11 +65,9 @@ mod attr; mod chains; pub(crate) mod checkstyle; mod closures; -pub(crate) mod source_map; mod comment; pub(crate) mod config; mod expr; -pub(crate) mod source_file; pub(crate) mod formatting; mod imports; mod issues; @@ -86,6 +84,8 @@ mod reorder; mod rewrite; pub(crate) mod rustfmt_diff; mod shape; +pub(crate) mod source_file; +pub(crate) mod source_map; mod spanned; mod string; #[cfg(test)] diff --git a/src/macros.rs b/src/macros.rs index 9bbee1097e1..e8e0f1b572e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,17 +22,16 @@ use std::collections::HashMap; use config::lists::*; -use syntax::source_map::{BytePos, Span}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::print::pprust; +use syntax::source_map::{BytePos, Span}; use syntax::symbol; use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, ptr}; -use source_map::SpanUtils; use comment::{ contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, @@ -42,6 +41,7 @@ use lists::{itemize_list, write_list, ListFormatting}; use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use source_map::SpanUtils; use spanned::Spanned; use utils::{format_visibility, mk_sp, rewrite_ident, wrap_str}; diff --git a/src/matches.rs b/src/matches.rs index 0ee63fb0c5a..231112edb1e 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -16,7 +16,6 @@ use config::lists::*; use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; -use source_map::SpanUtils; use comment::{combine_strs_with_missing_comments, rewrite_comment}; use config::{Config, ControlBraceStyle, IndentStyle}; use expr::{ @@ -26,6 +25,7 @@ use expr::{ use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use spanned::Spanned; use utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index f61098ed879..ef047b3144c 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -12,10 +12,10 @@ use std::borrow::Cow; use syntax::source_map::{BytePos, Pos, Span}; -use source_map::LineRangeUtils; use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use config::{EmitMode, FileName}; use shape::{Indent, Shape}; +use source_map::LineRangeUtils; use utils::{count_newlines, last_line_width, mk_sp}; use visitor::FmtVisitor; diff --git a/src/modules.rs b/src/modules.rs index 2f5743fbedf..aa36f4103e4 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -13,8 +13,8 @@ use std::io; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::source_map; use syntax::parse::{parser, DirectoryOwnership}; +use syntax::source_map; use syntax_pos::symbol::Symbol; use config::FileName; @@ -66,8 +66,8 @@ fn list_submodules<'a>( for item in &module.items { if let ast::ItemKind::Mod(ref sub_mod) = item.node { if !contains_skip(&item.attrs) { - let is_internal = - source_map.span_to_filename(item.span) == source_map.span_to_filename(sub_mod.inner); + let is_internal = source_map.span_to_filename(item.span) + == source_map.span_to_filename(sub_mod.inner); let (dir_path, relative) = if is_internal { if let Some(path) = find_path_value(&item.attrs) { (search_dir.join(&path.as_str()), None) diff --git a/src/overflow.rs b/src/overflow.rs index 6e63649ca80..1a223cf3ca6 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -13,15 +13,15 @@ use config::lists::*; use syntax::ast; -use syntax::source_map::Span; use syntax::parse::token::DelimToken; +use syntax::source_map::Span; use closures; -use source_map::SpanUtils; use expr::{is_every_expr_simple, is_method_call, is_nested_call, maybe_get_args_offset, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use spanned::Spanned; use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; diff --git a/src/patterns.rs b/src/patterns.rs index b58431cbb65..13ae0d180e8 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -10,10 +10,9 @@ use config::lists::*; use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; -use syntax::source_map::{self, BytePos, Span}; use syntax::ptr; +use syntax::source_map::{self, BytePos, Span}; -use source_map::SpanUtils; use comment::FindUncommented; use expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use lists::{ @@ -25,6 +24,7 @@ use overflow; use pairs::{rewrite_pair, PairParts}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use spanned::Spanned; use types::{rewrite_path, PathContext}; use utils::{format_mutability, mk_sp, rewrite_ident}; diff --git a/src/reorder.rs b/src/reorder.rs index 21a3797a6e4..b6876738cfd 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -20,13 +20,13 @@ use config::Config; use syntax::{ast, attr, source_map::Span}; use attr::filter_inline_attrs; -use source_map::LineRangeUtils; use comment::combine_strs_with_missing_comments; use imports::{merge_use_trees, UseTree}; use items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use lists::{itemize_list, write_list, ListFormatting, ListItem}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::LineRangeUtils; use spanned::Spanned; use utils::mk_sp; use visitor::FmtVisitor; diff --git a/src/rewrite.rs b/src/rewrite.rs index 232f4311155..f463732c0e4 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -10,8 +10,8 @@ // A generic trait to abstract the rewriting of an element (of the AST). -use syntax::source_map::{SourceMap, Span}; use syntax::parse::ParseSess; +use syntax::source_map::{SourceMap, Span}; use config::{Config, IndentStyle}; use shape::Shape; diff --git a/src/source_map.rs b/src/source_map.rs index 678e4fe4cc6..dee5e4f7601 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This module contains utilities that work with the `SourceMap` from `libsyntax` / `syntex_syntax`. +//! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. use config::file_lines::LineRange; diff --git a/src/test/mod.rs b/src/test/mod.rs index 35a720e4c56..8b2358f1ada 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -20,9 +20,9 @@ use std::path::{Path, PathBuf}; use std::str::Chars; use config::{Color, Config, EmitMode, FileName, ReportTactic}; -use source_file; -use formatting::{SourceFile, ModifiedChunk}; +use formatting::{ModifiedChunk, SourceFile}; use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; +use source_file; use {FormatReport, Input, Session}; const DIFF_CONTEXT_SIZE: usize = 3; diff --git a/src/types.rs b/src/types.rs index 601868bf1f3..dd7f60a60b4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -16,7 +16,6 @@ use syntax::ast::{self, FunctionRetTy, Mutability}; use syntax::source_map::{self, BytePos, Span}; use syntax::symbol::keywords; -use source_map::SpanUtils; use config::{IndentStyle, TypeDensity}; use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ToExpr}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; @@ -25,6 +24,7 @@ use overflow; use pairs::{rewrite_pair, PairParts}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; +use source_map::SpanUtils; use spanned::Spanned; use utils::{ colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, diff --git a/src/utils.rs b/src/utils.rs index 1bfccf237b4..63b238a7817 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,8 +15,8 @@ use syntax::ast::{ self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, Visibility, VisibilityKind, }; -use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use syntax::ptr; +use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use comment::filter_normal_code; use rewrite::RewriteContext; diff --git a/src/vertical.rs b/src/vertical.rs index 98f90530e8b..e76f44ca39b 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -16,13 +16,13 @@ use config::lists::*; use syntax::ast; use syntax::source_map::{BytePos, Span}; -use source_map::SpanUtils; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use source_map::SpanUtils; use spanned::Spanned; use utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; diff --git a/src/visitor.rs b/src/visitor.rs index bc500281a88..7f557747778 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -9,12 +9,11 @@ // except according to those terms. use syntax::attr::HasAttrs; -use syntax::source_map::{self, BytePos, SourceMap, Pos, Span}; use syntax::parse::ParseSess; +use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; use syntax::{ast, visit}; use attr::*; -use source_map::{LineRangeUtils, SpanUtils}; use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; use config::{BraceStyle, Config}; use items::{ @@ -26,6 +25,7 @@ use items::{ use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, -- cgit 1.4.1-3-g733a5 From 4e748a269ec1e07a25c2b8dd74dee8bdc5db54d8 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 21 Aug 2018 18:38:21 -0400 Subject: Fixed ellipsis bug where rustfmt was creating code that could not be parsed --- src/patterns.rs | 4 +++- tests/source/issue-2936.rs | 19 +++++++++++++++++++ tests/target/issue-2936.rs | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-2936.rs create mode 100644 tests/target/issue-2936.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 465d64627e8..f70c696f52a 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -369,7 +369,9 @@ fn rewrite_tuple_pat( shape, span, context.config.max_width(), - if add_comma { + if dotdot_pos.is_some() { + Some(SeparatorTactic::Never) + } else if add_comma { Some(SeparatorTactic::Always) } else { None diff --git a/tests/source/issue-2936.rs b/tests/source/issue-2936.rs new file mode 100644 index 00000000000..55b5c56e698 --- /dev/null +++ b/tests/source/issue-2936.rs @@ -0,0 +1,19 @@ +struct AStruct { + A: u32, + B: u32, + C: u32, +} + +impl Something for AStruct { + fn a_func() { + match a_val { + ContextualParseError::InvalidMediaRule(ref err) => { + let err: &CStr = match err.kind { + ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureName(..)) => { + cstr!("PEMQExpectedFeatureName") + }, + }; + } + }; + } +} diff --git a/tests/target/issue-2936.rs b/tests/target/issue-2936.rs new file mode 100644 index 00000000000..876050a20f4 --- /dev/null +++ b/tests/target/issue-2936.rs @@ -0,0 +1,19 @@ +struct AStruct { + A: u32, + B: u32, + C: u32, +} + +impl Something for AStruct { + fn a_func() { + match a_val { + ContextualParseError::InvalidMediaRule(ref err) => { + let err: &CStr = match err.kind { + ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureName( + .. + )) => cstr!("PEMQExpectedFeatureName"), + }; + } + }; + } +} -- cgit 1.4.1-3-g733a5 From 10512a59d00cd5b1f134d78a7ff4e2ce5abb9b12 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 24 Aug 2018 01:39:05 -0400 Subject: Impl only use (#2951) --- src/config/file_lines.rs | 2 +- src/imports.rs | 28 +++++++++++++--------------- tests/source/imports-impl-only-use.rs | 4 ++++ tests/target/imports-impl-only-use.rs | 4 ++++ 4 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 tests/source/imports-impl-only-use.rs create mode 100644 tests/target/imports-impl-only-use.rs (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index ba317af8360..e113118c643 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -386,7 +386,7 @@ mod test { ); } - use super::json::{self, json, json_internal}; + use super::json::{self, json}; use super::{FileLines, FileName}; use std::{collections::HashMap, path::PathBuf}; diff --git a/src/imports.rs b/src/imports.rs index a2d14c129d9..b3408bf7bf2 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -149,12 +149,10 @@ impl UseSegment { if name.is_empty() || name == "{{root}}" { return None; } - Some(if name == "self" { - UseSegment::Slf(None) - } else if name == "super" { - UseSegment::Super(None) - } else { - UseSegment::Ident((*name).to_owned(), None) + Some(match name { + "self" => UseSegment::Slf(None), + "super" => UseSegment::Super(None), + _ => UseSegment::Ident((*name).to_owned(), None), }) } } @@ -350,19 +348,19 @@ impl UseTree { UseTreeKind::Simple(ref rename, ..) => { let name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned(); let alias = rename.and_then(|ident| { - if ident == path_to_imported_ident(&a.prefix) { + if ident.name == "_" { + // for impl-only-use + Some("_".to_owned()) + } else if ident == path_to_imported_ident(&a.prefix) { None } else { Some(rewrite_ident(context, ident).to_owned()) } }); - - let segment = if &name == "self" { - UseSegment::Slf(alias) - } else if &name == "super" { - UseSegment::Super(alias) - } else { - UseSegment::Ident(name, alias) + let segment = match name.as_ref() { + "self" => UseSegment::Slf(alias), + "super" => UseSegment::Super(alias), + _ => UseSegment::Ident(name, alias), }; // `name` is already in result. @@ -746,7 +744,7 @@ fn rewrite_nested_use_tree( impl Rewrite for UseSegment { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - Some(match *self { + Some(match self { UseSegment::Ident(ref ident, Some(ref rename)) => format!("{} as {}", ident, rename), UseSegment::Ident(ref ident, None) => ident.clone(), UseSegment::Slf(Some(ref rename)) => format!("self as {}", rename), diff --git a/tests/source/imports-impl-only-use.rs b/tests/source/imports-impl-only-use.rs new file mode 100644 index 00000000000..d290d8d9185 --- /dev/null +++ b/tests/source/imports-impl-only-use.rs @@ -0,0 +1,4 @@ +#![feature(underscore_imports)] + +use attr; +use std::iter::Iterator as _; diff --git a/tests/target/imports-impl-only-use.rs b/tests/target/imports-impl-only-use.rs new file mode 100644 index 00000000000..d290d8d9185 --- /dev/null +++ b/tests/target/imports-impl-only-use.rs @@ -0,0 +1,4 @@ +#![feature(underscore_imports)] + +use attr; +use std::iter::Iterator as _; -- cgit 1.4.1-3-g733a5 From ca19c9a35a22d04d9911c95e6e8619082cc45f1b Mon Sep 17 00:00:00 2001 From: Zach Lute Date: Sat, 25 Aug 2018 21:02:24 -0700 Subject: Fix build with rust nightly by updating try block syntax. (#2965) --- Cargo.lock | 81 +++++++++++++++++++++++++++------------------------ Cargo.toml | 6 ++-- src/closures.rs | 2 +- src/expr.rs | 17 ++++------- tests/source/catch.rs | 17 ++++++----- tests/target/catch.rs | 17 ++++++----- 6 files changed, 71 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ac3fd7ab242..187b58f803b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,7 +331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -401,15 +401,15 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -418,7 +418,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -426,67 +426,72 @@ dependencies = [ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-ap-syntax" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "235.0.0" +version = "237.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -541,9 +546,9 @@ dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -608,7 +613,7 @@ dependencies = [ [[package]] name = "smallvec" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -820,14 +825,14 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum rustc-ap-arena 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f322d66bfa4314b6bbc6e7a0dbce4f33f7a5ed08c5a1bb0588fa8a0d904a99f" -"checksum rustc-ap-rustc_cratesio_shim 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "082c176b1346fd356c086ffb9695d188bb6a2cffc1db987e1604f36d495797d5" -"checksum rustc-ap-rustc_data_structures 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df2ce9493ece082cfb8301a718f2945646fc622386d4c68d8fe503b35f36194f" -"checksum rustc-ap-rustc_errors 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a43a08156fd6b8df7d7e4bae3edd0dc4c67b842518acbfc516cde2ce0638cd82" -"checksum rustc-ap-rustc_target 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36f7dc5977708040caf9a87f3ad877159c2573a75245280239083315f2f958a7" -"checksum rustc-ap-serialize 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca9beb1012c0120f95767975bc41f4b599c105da8d7561185ed22dfe2bc52cd6" -"checksum rustc-ap-syntax 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32fee8563391d36dcef52b180540cf72543a0a4505ee361ac30ed48ce9884a1b" -"checksum rustc-ap-syntax_pos 235.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b71f85a97f5c3ed6df05040f0e29227f9c302da4325c27c33a1701ecf9d6a0" +"checksum rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d24c8b3c1437fad023cb9472381216a1d41d82dbb2d2e6c7858bd6f50317719" +"checksum rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c5b02c76cd1ee4e9c97c8228701796d6b7431e8f100dea2d8af1d6c2c2bad56" +"checksum rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076388154497fb9a007e3badd78e415402a5594111cd6bc7ce1420dd1b1818b" +"checksum rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c11e4789cbc276ceaa87d326c234b1a2d1e0fe6017b88a8a25903200060acb" +"checksum rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25f711bb152b9d7cdd69410cfe6d99aeb1409c959e0fdf3c8ca4d220e568aa52" +"checksum rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57638db658d4942d3f30a12566836f9a67a636ed8002c8cae1c9231214e39929" +"checksum rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6dbcf07abf7a9957dce8d34353d55dfb4cd882153181f24349f4690facb58f0" +"checksum rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0915cb5e166cabe588a129dec2d47357077e96fb1f9b57318fbe217eac4ce508" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" @@ -840,7 +845,7 @@ dependencies = [ "checksum serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfad05c8854584e5f72fb859385ecdfa03af69c3fd0572f0da2d4c95f060bdb" "checksum serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "b719c6d5e9f73fbc37892246d5852333f040caa617b8873c6aced84bcb28e7bb" "checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" -"checksum smallvec 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "211a489e65e94b103926d2054ae515a1cdb5d515ea0ef414fee23b7e043ce748" +"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b7bfcbb0c068d0f642a0ffbd5c604965a360a61f99e8add013cef23a838614f3" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" diff --git a/Cargo.toml b/Cargo.toml index 5583b056085..623654329d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,9 +47,9 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.6" -rustc-ap-rustc_target = "235.0.0" -rustc-ap-syntax = "235.0.0" -rustc-ap-syntax_pos = "235.0.0" +rustc-ap-rustc_target = "237.0.0" +rustc-ap-syntax = "237.0.0" +rustc-ap-syntax_pos = "237.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/closures.rs b/src/closures.rs index f6a3d8436f2..3451fcfe6f4 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -173,7 +173,7 @@ fn rewrite_closure_expr( match expr.node { ast::ExprKind::Match(..) | ast::ExprKind::Block(..) - | ast::ExprKind::Catch(..) + | ast::ExprKind::TryBlock(..) | ast::ExprKind::Loop(..) | ast::ExprKind::Struct(..) => true, diff --git a/src/expr.rs b/src/expr.rs index e6161c0c42b..fdea683df0a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -317,22 +317,17 @@ pub fn format_expr( // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), - ast::ExprKind::Catch(ref block) => { - if let rw @ Some(_) = rewrite_single_line_block( - context, - "do catch ", - block, - Some(&expr.attrs), - None, - shape, - ) { + ast::ExprKind::TryBlock(ref block) => { + if let rw @ Some(_) = + rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) + { rw } else { - // 9 = `do catch ` + // 9 = `try ` let budget = shape.width.saturating_sub(9); Some(format!( "{}{}", - "do catch ", + "try ", rewrite_block( block, Some(&expr.attrs), diff --git a/tests/source/catch.rs b/tests/source/catch.rs index 64cc9e7a207..6674e7eebe4 100644 --- a/tests/source/catch.rs +++ b/tests/source/catch.rs @@ -1,27 +1,28 @@ -#![feature(catch_expr)] +// rustfmt-edition: Edition2018 +#![feature(try_blocks)] fn main() { - let x = do catch { + let x = try { foo()? }; - let x = do catch /* Invisible comment */ { foo()? }; + let x = try /* Invisible comment */ { foo()? }; - let x = do catch { + let x = try { unsafe { foo()? } }; - let y = match (do catch { + let y = match (try { foo()? }) { _ => (), }; - do catch { + try { foo()?; }; - do catch { - // Regular do catch block + try { + // Regular try block }; } diff --git a/tests/target/catch.rs b/tests/target/catch.rs index 640f9bade49..6987a19bcad 100644 --- a/tests/target/catch.rs +++ b/tests/target/catch.rs @@ -1,21 +1,22 @@ -#![feature(catch_expr)] +// rustfmt-edition: Edition2018 +#![feature(try_blocks)] fn main() { - let x = do catch { foo()? }; + let x = try { foo()? }; - let x = do catch /* Invisible comment */ { foo()? }; + let x = try /* Invisible comment */ { foo()? }; - let x = do catch { unsafe { foo()? } }; + let x = try { unsafe { foo()? } }; - let y = match (do catch { foo()? }) { + let y = match (try { foo()? }) { _ => (), }; - do catch { + try { foo()?; }; - do catch { - // Regular do catch block + try { + // Regular try block }; } -- cgit 1.4.1-3-g733a5 From 6aae9d870fcd9f30d265d3f287627ac5fbad8f4f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 26 Aug 2018 13:20:07 +0900 Subject: Remove an unnecessary attribute --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 89dcf6f5ff3..7ebb967a494 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_attributes)] #![feature(decl_macro)] #![allow(unused_attributes)] #![feature(type_ascription)] -- cgit 1.4.1-3-g733a5 From 78a0cde5bfb337af1812b06a73819cbb5ad61f06 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 26 Aug 2018 13:20:25 +0900 Subject: Format in-place expression like assignment --- src/expr.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index fdea683df0a..74639c6ef63 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -338,8 +338,10 @@ pub fn format_expr( )) } } - // FIXME(#2743) - ast::ExprKind::ObsoleteInPlace(..) => unimplemented!(), + ast::ExprKind::ObsoleteInPlace(ref lhs, ref rhs) => lhs + .rewrite(context, shape) + .map(|s| s + " <-") + .and_then(|lhs| rewrite_assign_rhs(context, lhs, &**rhs, shape)), ast::ExprKind::Async(capture_by, _node_id, ref block) => { let mover = if capture_by == ast::CaptureBy::Value { "move " -- cgit 1.4.1-3-g733a5 From 0d60f6715df7bf7bff875b6492f06702564c25f2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 27 Aug 2018 16:37:58 +0900 Subject: Use span_ends_with_comma to find a trailing comma in an attribute --- src/attr.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index deaf2be46b8..f4b84e51a30 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -217,11 +217,8 @@ impl Rewrite for ast::MetaItem { ast::MetaItemKind::List(ref list) => { let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; - let snippet = context.snippet(self.span); - // 2 = )] (this might go wrong if there is whitespace between the brackets, but - // it's close enough). - let snippet = snippet[..snippet.len() - 2].trim(); - let trailing_comma = if snippet.ends_with(',') { "," } else { "" }; + let has_comma = ::expr::span_ends_with_comma(context, self.span); + let trailing_comma = if has_comma { "," } else { "" }; let combine = list.len() == 1 && match list[0].node { ast::NestedMetaItemKind::Literal(..) => false, ast::NestedMetaItemKind::MetaItem(ref inner_meta_item) => { -- cgit 1.4.1-3-g733a5 From 5d642e8b234e96b360ef94734f724af12b36abb6 Mon Sep 17 00:00:00 2001 From: crw5996 Date: Mon, 27 Aug 2018 12:31:26 -0400 Subject: Fixed #2955. Added value to determine whether or not rustfmt has condensed a tuple-struct Refactored to not use a mutable variable --- bin/main.rs | 589 ++++++++++++++++++++++++++ cargo-fmt/main.rs | 381 +++++++++++++++++ config/config_type.rs | 452 ++++++++++++++++++++ config/file_lines.rs | 422 ++++++++++++++++++ config/license.rs | 266 ++++++++++++ config/lists.rs | 105 +++++ config/mod.rs | 360 ++++++++++++++++ config/options.rs | 482 +++++++++++++++++++++ format-diff/main.rs | 251 +++++++++++ format-diff/test/bindgen.diff | 67 +++ git-rustfmt/main.rs | 206 +++++++++ src/patterns.rs | 33 +- test/mod.rs | 964 ++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 4561 insertions(+), 17 deletions(-) create mode 100644 bin/main.rs create mode 100644 cargo-fmt/main.rs create mode 100644 config/config_type.rs create mode 100644 config/file_lines.rs create mode 100644 config/license.rs create mode 100644 config/lists.rs create mode 100644 config/mod.rs create mode 100644 config/options.rs create mode 100644 format-diff/main.rs create mode 100644 format-diff/test/bindgen.diff create mode 100644 git-rustfmt/main.rs create mode 100644 test/mod.rs (limited to 'src') diff --git a/bin/main.rs b/bin/main.rs new file mode 100644 index 00000000000..760333955a0 --- /dev/null +++ b/bin/main.rs @@ -0,0 +1,589 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(not(test))] +#![feature(extern_prelude)] + +extern crate env_logger; +#[macro_use] +extern crate failure; +extern crate getopts; +extern crate rustfmt_nightly as rustfmt; + +use std::env; +use std::fs::File; +use std::io::{self, stdout, Read, Write}; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use failure::err_msg; + +use getopts::{Matches, Options}; + +use rustfmt::{ + load_config, CliOptions, Color, Config, EmitMode, ErrorKind, FileLines, FileName, Input, + Session, Verbosity, +}; + +fn main() { + env_logger::init(); + let opts = make_opts(); + + let exit_code = match execute(&opts) { + Ok(code) => code, + Err(e) => { + eprintln!("{}", e.to_string()); + 1 + } + }; + // Make sure standard output is flushed before we exit. + std::io::stdout().flush().unwrap(); + + // Exit with given exit code. + // + // NOTE: This immediately terminates the process without doing any cleanup, + // so make sure to finish all necessary cleanup before this is called. + std::process::exit(exit_code); +} + +/// Rustfmt operations. +enum Operation { + /// Format files and their child modules. + Format { + files: Vec, + minimal_config_path: Option, + }, + /// Print the help message. + Help(HelpOp), + // Print version information + Version, + /// Output default config to a file, or stdout if None + ConfigOutputDefault { + path: Option, + }, + /// No file specified, read from stdin + Stdin { + input: String, + }, +} + +/// Arguments to `--help` +enum HelpOp { + None, + Config, + FileLines, +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + + opts.optflag( + "", + "check", + "Run in 'check' mode. Exits with 0 if input if formatted correctly. Exits \ + with 1 and prints a diff if formatting is required.", + ); + let is_nightly = is_nightly(); + let emit_opts = if is_nightly { + "[files|stdout|coverage|checkstyle]" + } else { + "[files|stdout]" + }; + opts.optopt("", "emit", "What data to emit and how", emit_opts); + opts.optflag("", "backup", "Backup any modified files."); + opts.optopt( + "", + "config-path", + "Recursively searches the given path for the rustfmt.toml config file. If not \ + found reverts to the input file path", + "[Path for the configuration file]", + ); + opts.optopt( + "", + "color", + "Use colored output (if supported)", + "[always|never|auto]", + ); + opts.optopt( + "", + "print-config", + "Dumps a default or minimal config to PATH. A minimal config is the \ + subset of the current config file used for formatting the current program.", + "[minimal|default] PATH", + ); + + if is_nightly { + opts.optflag( + "", + "unstable-features", + "Enables unstable features. Only available on nightly channel.", + ); + opts.optopt( + "", + "file-lines", + "Format specified line ranges. Run with `--help=file-lines` for \ + more detail (unstable).", + "JSON", + ); + opts.optflag( + "", + "error-on-unformatted", + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces (unstable).", + ); + opts.optflag( + "", + "skip-children", + "Don't reformat child modules (unstable).", + ); + } + + opts.optflag("v", "verbose", "Print verbose output"); + opts.optflag("q", "quiet", "Print less output"); + opts.optflag("V", "version", "Show version information"); + opts.optflagopt( + "h", + "help", + "Show this message or help about a specific topic: `config` or `file-lines`", + "=TOPIC", + ); + + opts +} + +fn is_nightly() -> bool { + option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly" || c == "dev") + .unwrap_or(false) +} + +// Returned i32 is an exit code +fn execute(opts: &Options) -> Result { + let matches = opts.parse(env::args().skip(1))?; + let options = GetOptsOptions::from_matches(&matches)?; + + match determine_operation(&matches)? { + Operation::Help(HelpOp::None) => { + print_usage_to_stdout(opts, ""); + return Ok(0); + } + Operation::Help(HelpOp::Config) => { + Config::print_docs(&mut stdout(), options.unstable_features); + return Ok(0); + } + Operation::Help(HelpOp::FileLines) => { + print_help_file_lines(); + return Ok(0); + } + Operation::Version => { + print_version(); + return Ok(0); + } + Operation::ConfigOutputDefault { path } => { + let toml = Config::default().all_options().to_toml().map_err(err_msg)?; + if let Some(path) = path { + let mut file = File::create(path)?; + file.write_all(toml.as_bytes())?; + } else { + io::stdout().write_all(toml.as_bytes())?; + } + return Ok(0); + } + Operation::Stdin { input } => format_string(input, options), + Operation::Format { + files, + minimal_config_path, + } => format(files, minimal_config_path, options), + } +} + +fn format_string(input: String, options: GetOptsOptions) -> Result { + // try to read config from local directory + let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; + + // emit mode is always Stdout for Stdin. + config.set().emit_mode(EmitMode::Stdout); + config.set().verbose(Verbosity::Quiet); + + // parse file_lines + config.set().file_lines(options.file_lines); + for f in config.file_lines().files() { + match *f { + FileName::Stdin => {} + _ => eprintln!("Warning: Extra file listed in file_lines option '{}'", f), + } + } + + let out = &mut stdout(); + let mut session = Session::new(config, Some(out)); + format_and_emit_report(&mut session, Input::Text(input)); + + let exit_code = if session.has_operational_errors() || session.has_parsing_errors() { + 1 + } else { + 0 + }; + Ok(exit_code) +} + +fn format( + files: Vec, + minimal_config_path: Option, + options: GetOptsOptions, +) -> Result { + options.verify_file_lines(&files); + let (config, config_path) = load_config(None, Some(options.clone()))?; + + if config.verbose() == Verbosity::Verbose { + if let Some(path) = config_path.as_ref() { + println!("Using rustfmt config file {}", path.display()); + } + } + + let out = &mut stdout(); + let mut session = Session::new(config, Some(out)); + + for file in files { + if !file.exists() { + eprintln!("Error: file `{}` does not exist", file.to_str().unwrap()); + session.add_operational_error(); + } else if file.is_dir() { + eprintln!("Error: `{}` is a directory", file.to_str().unwrap()); + session.add_operational_error(); + } else { + // Check the file directory if the config-path could not be read or not provided + if config_path.is_none() { + let (local_config, config_path) = + load_config(Some(file.parent().unwrap()), Some(options.clone()))?; + if local_config.verbose() == Verbosity::Verbose { + if let Some(path) = config_path { + println!( + "Using rustfmt config file {} for {}", + path.display(), + file.display() + ); + } + } + + session.override_config(local_config, |sess| { + format_and_emit_report(sess, Input::File(file)) + }); + } else { + format_and_emit_report(&mut session, Input::File(file)); + } + } + } + + // If we were given a path via dump-minimal-config, output any options + // that were used during formatting as TOML. + if let Some(path) = minimal_config_path { + let mut file = File::create(path)?; + let toml = session.config.used_options().to_toml().map_err(err_msg)?; + file.write_all(toml.as_bytes())?; + } + + let exit_code = if session.has_operational_errors() + || session.has_parsing_errors() + || ((session.has_diff() || session.has_check_errors()) && options.check) + { + 1 + } else { + 0 + }; + Ok(exit_code) +} + +fn format_and_emit_report(session: &mut Session, input: Input) { + match session.format(input) { + Ok(report) => { + if report.has_warnings() { + match term::stderr() { + Some(ref t) + if session.config.color().use_colored_tty() + && t.supports_color() + && t.supports_attr(term::Attr::Bold) => + { + match report.fancy_print(term::stderr().unwrap()) { + Ok(..) => (), + Err(..) => panic!("Unable to write to stderr: {}", report), + } + } + _ => eprintln!("{}", report), + } + } + } + Err(msg) => { + eprintln!("Error writing files: {}", msg); + session.add_operational_error(); + } + } +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + let sep = if reason.is_empty() { + String::new() + } else { + format!("{}\n\n", reason) + }; + let msg = format!( + "{}Format Rust code\n\nusage: {} [options] ...", + sep, + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&msg)); +} + +fn print_help_file_lines() { + println!( + "If you want to restrict reformatting to specific sets of lines, you can +use the `--file-lines` option. Its argument is a JSON array of objects +with `file` and `range` properties, where `file` is a file name, and +`range` is an array representing a range of lines like `[7,13]`. Ranges +are 1-based and inclusive of both end points. Specifying an empty array +will result in no files being formatted. For example, + +``` +rustfmt --file-lines '[ + {{\"file\":\"src/lib.rs\",\"range\":[7,13]}}, + {{\"file\":\"src/lib.rs\",\"range\":[21,29]}}, + {{\"file\":\"src/foo.rs\",\"range\":[10,11]}}, + {{\"file\":\"src/foo.rs\",\"range\":[15,15]}}]' +``` + +would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`, +and `15` of `src/foo.rs`. No other files would be formatted, even if they +are included as out of line modules from `src/lib.rs`." + ); +} + +fn print_version() { + let version_info = format!( + "{}-{}", + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"), + include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")) + ); + + println!("rustfmt {}", version_info); +} + +fn determine_operation(matches: &Matches) -> Result { + if matches.opt_present("h") { + let topic = matches.opt_str("h"); + if topic == None { + return Ok(Operation::Help(HelpOp::None)); + } else if topic == Some("config".to_owned()) { + return Ok(Operation::Help(HelpOp::Config)); + } else if topic == Some("file-lines".to_owned()) { + return Ok(Operation::Help(HelpOp::FileLines)); + } else { + println!("Unknown help topic: `{}`\n", topic.unwrap()); + return Ok(Operation::Help(HelpOp::None)); + } + } + + let mut minimal_config_path = None; + if let Some(ref kind) = matches.opt_str("print-config") { + let path = matches.free.get(0).cloned(); + if kind == "default" { + return Ok(Operation::ConfigOutputDefault { path }); + } else if kind == "minimal" { + minimal_config_path = path; + if minimal_config_path.is_none() { + println!("WARNING: PATH required for `--print-config minimal`"); + } + } + } + + if matches.opt_present("version") { + return Ok(Operation::Version); + } + + // if no file argument is supplied, read from stdin + if matches.free.is_empty() { + let mut buffer = String::new(); + io::stdin().read_to_string(&mut buffer)?; + + return Ok(Operation::Stdin { input: buffer }); + } + + let files: Vec<_> = matches + .free + .iter() + .map(|s| { + let p = PathBuf::from(s); + // we will do comparison later, so here tries to canonicalize first + // to get the expected behavior. + p.canonicalize().unwrap_or(p) + }).collect(); + + Ok(Operation::Format { + files, + minimal_config_path, + }) +} + +const STABLE_EMIT_MODES: [EmitMode; 3] = [EmitMode::Files, EmitMode::Stdout, EmitMode::Diff]; + +/// Parsed command line options. +#[derive(Clone, Debug, Default)] +struct GetOptsOptions { + skip_children: Option, + quiet: bool, + verbose: bool, + config_path: Option, + emit_mode: EmitMode, + backup: bool, + check: bool, + color: Option, + file_lines: FileLines, // Default is all lines in all files. + unstable_features: bool, + error_on_unformatted: Option, +} + +impl GetOptsOptions { + pub fn from_matches(matches: &Matches) -> Result { + let mut options = GetOptsOptions::default(); + options.verbose = matches.opt_present("verbose"); + options.quiet = matches.opt_present("quiet"); + if options.verbose && options.quiet { + return Err(format_err!("Can't use both `--verbose` and `--quiet`")); + } + + let rust_nightly = is_nightly(); + + if rust_nightly { + options.unstable_features = matches.opt_present("unstable-features"); + + if options.unstable_features { + if matches.opt_present("skip-children") { + options.skip_children = Some(true); + } + if matches.opt_present("error-on-unformatted") { + options.error_on_unformatted = Some(true); + } + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = file_lines.parse().map_err(err_msg)?; + } + } else { + let mut unstable_options = vec![]; + if matches.opt_present("skip-children") { + unstable_options.push("`--skip-children`"); + } + if matches.opt_present("error-on-unformatted") { + unstable_options.push("`--error-on-unformatted`"); + } + if matches.opt_present("file-lines") { + unstable_options.push("`--file-lines`"); + } + if !unstable_options.is_empty() { + let s = if unstable_options.len() == 1 { "" } else { "s" }; + return Err(format_err!( + "Unstable option{} ({}) used without `--unstable-features`", + s, + unstable_options.join(", "), + )); + } + } + } + + options.config_path = matches.opt_str("config-path").map(PathBuf::from); + + options.check = matches.opt_present("check"); + if let Some(ref emit_str) = matches.opt_str("emit") { + if options.check { + return Err(format_err!("Invalid to use `--emit` and `--check`")); + } + if let Ok(emit_mode) = emit_mode_from_emit_str(emit_str) { + options.emit_mode = emit_mode; + } else { + return Err(format_err!("Invalid value for `--emit`")); + } + } + + if matches.opt_present("backup") { + options.backup = true; + } + + if !rust_nightly { + if !STABLE_EMIT_MODES.contains(&options.emit_mode) { + return Err(format_err!( + "Invalid value for `--emit` - using an unstable \ + value without `--unstable-features`", + )); + } + } + + if let Some(ref color) = matches.opt_str("color") { + match Color::from_str(color) { + Ok(color) => options.color = Some(color), + _ => return Err(format_err!("Invalid color: {}", color)), + } + } + + Ok(options) + } + + fn verify_file_lines(&self, files: &[PathBuf]) { + for f in self.file_lines.files() { + match *f { + FileName::Real(ref f) if files.contains(f) => {} + FileName::Real(_) => { + eprintln!("Warning: Extra file listed in file_lines option '{}'", f) + } + FileName::Stdin => eprintln!("Warning: Not a file '{}'", f), + } + } + } +} + +impl CliOptions for GetOptsOptions { + fn apply_to(self, config: &mut Config) { + if self.verbose { + config.set().verbose(Verbosity::Verbose); + } else if self.quiet { + config.set().verbose(Verbosity::Quiet); + } else { + config.set().verbose(Verbosity::Normal); + } + config.set().file_lines(self.file_lines); + config.set().unstable_features(self.unstable_features); + if let Some(skip_children) = self.skip_children { + config.set().skip_children(skip_children); + } + if let Some(error_on_unformatted) = self.error_on_unformatted { + config.set().error_on_unformatted(error_on_unformatted); + } + if self.check { + config.set().emit_mode(EmitMode::Diff); + } else { + config.set().emit_mode(self.emit_mode); + } + if self.backup { + config.set().make_backup(true); + } + if let Some(color) = self.color { + config.set().color(color); + } + } + + fn config_path(&self) -> Option<&Path> { + self.config_path.as_ref().map(|p| &**p) + } +} + +fn emit_mode_from_emit_str(emit_str: &str) -> Result { + match emit_str { + "files" => Ok(EmitMode::Files), + "stdout" => Ok(EmitMode::Stdout), + "coverage" => Ok(EmitMode::Coverage), + "checkstyle" => Ok(EmitMode::Checkstyle), + _ => Err(format_err!("Invalid value for `--emit`")), + } +} diff --git a/cargo-fmt/main.rs b/cargo-fmt/main.rs new file mode 100644 index 00000000000..2d8234ef41e --- /dev/null +++ b/cargo-fmt/main.rs @@ -0,0 +1,381 @@ +// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) + +#![cfg(not(test))] +#![deny(warnings)] + +extern crate cargo_metadata; +extern crate getopts; +extern crate serde_json as json; + +use std::collections::HashSet; +use std::env; +use std::fs; +use std::hash::{Hash, Hasher}; +use std::io::{self, Write}; +use std::iter::FromIterator; +use std::path::{Path, PathBuf}; +use std::process::{Command, ExitStatus}; +use std::str; + +use getopts::{Matches, Options}; + +fn main() { + let exit_status = execute(); + std::io::stdout().flush().unwrap(); + std::process::exit(exit_status); +} + +const SUCCESS: i32 = 0; +const FAILURE: i32 = 1; + +fn execute() -> i32 { + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("q", "quiet", "no output printed to stdout"); + opts.optflag("v", "verbose", "use verbose output"); + opts.optmulti( + "p", + "package", + "specify package to format (only usable in workspaces)", + "", + ); + opts.optflag("", "version", "print rustfmt version and exit"); + opts.optflag("", "all", "format all packages (only usable in workspaces)"); + + // If there is any invalid argument passed to `cargo fmt`, return without formatting. + let mut is_package_arg = false; + for arg in env::args().skip(2).take_while(|a| a != "--") { + if arg.starts_with('-') { + is_package_arg = arg.starts_with("--package"); + } else if !is_package_arg { + print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); + return FAILURE; + } else { + is_package_arg = false; + } + } + + let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { + Ok(m) => m, + Err(e) => { + print_usage_to_stderr(&opts, &e.to_string()); + return FAILURE; + } + }; + + let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { + (false, false) => Verbosity::Normal, + (false, true) => Verbosity::Quiet, + (true, false) => Verbosity::Verbose, + (true, true) => { + print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); + return FAILURE; + } + }; + + if matches.opt_present("h") { + print_usage_to_stdout(&opts, ""); + return SUCCESS; + } + + if matches.opt_present("version") { + return handle_command_status(get_version(verbosity), &opts); + } + + let strategy = CargoFmtStrategy::from_matches(&matches); + handle_command_status(format_crate(verbosity, &strategy), &opts) +} + +macro_rules! print_usage { + ($print:ident, $opts:ident, $reason:expr) => {{ + let msg = format!("{}\nusage: cargo fmt [options]", $reason); + $print!( + "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ + Arguments after `--` are passed to rustfmt.", + $opts.usage(&msg) + ); + }}; +} + +fn print_usage_to_stdout(opts: &Options, reason: &str) { + print_usage!(println, opts, reason); +} + +fn print_usage_to_stderr(opts: &Options, reason: &str) { + print_usage!(eprintln, opts, reason); +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Verbosity { + Verbose, + Normal, + Quiet, +} + +fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { + match status { + Err(e) => { + print_usage_to_stderr(opts, &e.to_string()); + FAILURE + } + Ok(status) => { + if status.success() { + SUCCESS + } else { + status.code().unwrap_or(FAILURE) + } + } + } +} + +fn get_version(verbosity: Verbosity) -> Result { + run_rustfmt(&[], &[String::from("--version")], verbosity) +} + +fn format_crate( + verbosity: Verbosity, + strategy: &CargoFmtStrategy, +) -> Result { + let rustfmt_args = get_fmt_args(); + let targets = if rustfmt_args + .iter() + .any(|s| ["--print-config", "-h", "--help", "-V", "--verison"].contains(&s.as_str())) + { + HashSet::new() + } else { + get_targets(strategy)? + }; + + // Currently only bin and lib files get formatted + let files: Vec<_> = targets + .into_iter() + .inspect(|t| { + if verbosity == Verbosity::Verbose { + println!("[{}] {:?}", t.kind, t.path) + } + }).map(|t| t.path) + .collect(); + + run_rustfmt(&files, &rustfmt_args, verbosity) +} + +fn get_fmt_args() -> Vec { + // All arguments after -- are passed to rustfmt + env::args().skip_while(|a| a != "--").skip(1).collect() +} + +/// Target uses a `path` field for equality and hashing. +#[derive(Debug)] +pub struct Target { + /// A path to the main source file of the target. + path: PathBuf, + /// A kind of target (e.g. lib, bin, example, ...). + kind: String, +} + +impl Target { + pub fn from_target(target: &cargo_metadata::Target) -> Self { + let path = PathBuf::from(&target.src_path); + let canonicalized = fs::canonicalize(&path).unwrap_or(path); + + Target { + path: canonicalized, + kind: target.kind[0].clone(), + } + } +} + +impl PartialEq for Target { + fn eq(&self, other: &Target) -> bool { + self.path == other.path + } +} + +impl Eq for Target {} + +impl Hash for Target { + fn hash(&self, state: &mut H) { + self.path.hash(state); + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum CargoFmtStrategy { + /// Format every packages and dependencies. + All, + /// Format packages that are specified by the command line argument. + Some(Vec), + /// Format the root packages only. + Root, +} + +impl CargoFmtStrategy { + pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { + match (matches.opt_present("all"), matches.opt_present("p")) { + (false, false) => CargoFmtStrategy::Root, + (true, _) => CargoFmtStrategy::All, + (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), + } + } +} + +/// Based on the specified `CargoFmtStrategy`, returns a set of main source files. +fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { + let mut targets = HashSet::new(); + + match *strategy { + CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, + CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, + CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, + } + + if targets.is_empty() { + Err(io::Error::new( + io::ErrorKind::Other, + "Failed to find targets".to_owned(), + )) + } else { + Ok(targets) + } +} + +fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + let current_dir = env::current_dir()?.canonicalize()?; + let current_dir_manifest = current_dir.join("Cargo.toml"); + let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; + let in_workspace_root = workspace_root_path == current_dir; + + for package in metadata.packages { + if in_workspace_root || PathBuf::from(&package.manifest_path) == current_dir_manifest { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } + } + } + + Ok(()) +} + +fn get_targets_recursive( + manifest_path: Option<&Path>, + mut targets: &mut HashSet, + visited: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(manifest_path)?; + + for package in metadata.packages { + add_targets(&package.targets, &mut targets); + + // Look for local dependencies. + for dependency in package.dependencies { + if dependency.source.is_some() || visited.contains(&dependency.name) { + continue; + } + + let mut manifest_path = PathBuf::from(&package.manifest_path); + + manifest_path.pop(); + manifest_path.push(&dependency.name); + manifest_path.push("Cargo.toml"); + + if manifest_path.exists() { + visited.insert(dependency.name); + get_targets_recursive(Some(&manifest_path), &mut targets, visited)?; + } + } + } + + Ok(()) +} + +fn get_targets_with_hitlist( + hitlist: &[String], + targets: &mut HashSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(None)?; + + let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); + + for package in metadata.packages { + if workspace_hitlist.remove(&package.name) { + for target in package.targets { + targets.insert(Target::from_target(&target)); + } + } + } + + if workspace_hitlist.is_empty() { + Ok(()) + } else { + let package = workspace_hitlist.iter().next().unwrap(); + Err(io::Error::new( + io::ErrorKind::InvalidInput, + format!("package `{}` is not a member of the workspace", package), + )) + } +} + +fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { + for target in target_paths { + targets.insert(Target::from_target(target)); + } +} + +fn run_rustfmt( + files: &[PathBuf], + fmt_args: &[String], + verbosity: Verbosity, +) -> Result { + let stdout = if verbosity == Verbosity::Quiet { + std::process::Stdio::null() + } else { + std::process::Stdio::inherit() + }; + + if verbosity == Verbosity::Verbose { + print!("rustfmt"); + for a in fmt_args { + print!(" {}", a); + } + for f in files { + print!(" {}", f.display()); + } + println!(); + } + + let mut command = Command::new("rustfmt") + .stdout(stdout) + .args(files) + .args(fmt_args) + .spawn() + .map_err(|e| match e.kind() { + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), + _ => e, + })?; + + command.wait() +} + +fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { + match cargo_metadata::metadata(manifest_path) { + Ok(metadata) => Ok(metadata), + Err(..) => Err(io::Error::new( + io::ErrorKind::Other, + "`cargo manifest` failed.", + )), + } +} diff --git a/config/config_type.rs b/config/config_type.rs new file mode 100644 index 00000000000..aea19b34375 --- /dev/null +++ b/config/config_type.rs @@ -0,0 +1,452 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::file_lines::FileLines; +use config::options::{IgnoreList, WidthHeuristics}; + +/// Trait for types that can be used in `Config`. +pub trait ConfigType: Sized { + /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a + /// pipe-separated list of variants; for other types it returns "". + fn doc_hint() -> String; +} + +impl ConfigType for bool { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for usize { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for isize { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for String { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for FileLines { + fn doc_hint() -> String { + String::from("") + } +} + +impl ConfigType for WidthHeuristics { + fn doc_hint() -> String { + String::new() + } +} + +impl ConfigType for IgnoreList { + fn doc_hint() -> String { + String::from("[,..]") + } +} + +/// Check if we're in a nightly build. +/// +/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap +/// to "stable", "beta", or "nightly" depending on what toolchain is being built. +/// If we are being built as part of the stable or beta toolchains, we want +/// to disable unstable configuration options. +/// +/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), +/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the +/// nightly compiler when installed from crates.io, default to nightly mode. +macro_rules! is_nightly_channel { + () => { + option_env!("CFG_RELEASE_CHANNEL") + .map(|c| c == "nightly" || c == "dev") + .unwrap_or(true) + }; +} + +macro_rules! create_config { + ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( + #[cfg(test)] + use std::collections::HashSet; + use std::io::Write; + + #[derive(Clone)] + pub struct Config { + // if a license_template_path has been specified, successfully read, parsed and compiled + // into a regex, it will be stored here + pub license_template: Option, + // For each config item, we store a bool indicating whether it has + // been accessed and the value, and a bool whether the option was + // manually initialised, or taken from the default, + $($i: (Cell, bool, $ty, bool)),+ + } + + // Just like the Config struct but with each property wrapped + // as Option. This is used to parse a rustfmt.toml that doesn't + // specify all properties of `Config`. + // We first parse into `PartialConfig`, then create a default `Config` + // and overwrite the properties with corresponding values from `PartialConfig`. + #[derive(Deserialize, Serialize, Clone)] + pub struct PartialConfig { + $(pub $i: Option<$ty>),+ + } + + impl PartialConfig { + pub fn to_toml(&self) -> Result { + // Non-user-facing options can't be specified in TOML + let mut cloned = self.clone(); + cloned.file_lines = None; + cloned.verbose = None; + cloned.width_heuristics = None; + + ::toml::to_string(&cloned) + .map_err(|e| format!("Could not output config: {}", e.to_string())) + } + } + + // Macro hygiene won't allow us to make `set_$i()` methods on Config + // for each item, so this struct is used to give the API to set values: + // `config.set().option(false)`. It's pretty ugly. Consider replacing + // with `config.set_option(false)` if we ever get a stable/usable + // `concat_idents!()`. + pub struct ConfigSetter<'a>(&'a mut Config); + + impl<'a> ConfigSetter<'a> { + $( + pub fn $i(&mut self, value: $ty) { + (self.0).$i.2 = value; + match stringify!($i) { + "max_width" | "use_small_heuristics" => self.0.set_heuristics(), + "license_template_path" => self.0.set_license_template(), + &_ => (), + } + } + )+ + } + + // Query each option, returns true if the user set the option, false if + // a default was used. + pub struct ConfigWasSet<'a>(&'a Config); + + impl<'a> ConfigWasSet<'a> { + $( + pub fn $i(&self) -> bool { + (self.0).$i.1 + } + )+ + } + + impl Config { + pub(crate) fn version_meets_requirement(&self) -> bool { + if self.was_set().required_version() { + let version = env!("CARGO_PKG_VERSION"); + let required_version = self.required_version(); + if version != required_version { + println!( + "Error: rustfmt version ({}) doesn't match the required version ({})", + version, + required_version, + ); + return false; + } + } + + true + } + + $( + pub fn $i(&self) -> $ty { + self.$i.0.set(true); + self.$i.2.clone() + } + )+ + + pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { + ConfigSetter(self) + } + + pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { + ConfigWasSet(self) + } + + fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config { + $( + if let Some(val) = parsed.$i { + if self.$i.3 { + self.$i.1 = true; + self.$i.2 = val; + } else { + if is_nightly_channel!() { + self.$i.1 = true; + self.$i.2 = val; + } else { + eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \ + available in nightly channel.", stringify!($i), val); + } + } + } + )+ + self.set_heuristics(); + self.set_license_template(); + self.set_ignore(dir); + self + } + + /// Returns a hash set initialized with every user-facing config option name. + #[cfg(test)] + pub(crate) fn hash_set() -> HashSet { + let mut hash_set = HashSet::new(); + $( + hash_set.insert(stringify!($i).to_owned()); + )+ + hash_set + } + + pub(crate) fn is_valid_name(name: &str) -> bool { + match name { + $( + stringify!($i) => true, + )+ + _ => false, + } + } + + pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + let parsed: ::toml::Value = + toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; + let mut err: String = String::new(); + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for key in table.keys() { + if !Config::is_valid_name(key) { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } + } + } + match parsed.try_into() { + Ok(parsed_config) => { + if !err.is_empty() { + eprint!("{}", err); + } + Ok(Config::default().fill_from_parsed_config(parsed_config, dir: &Path)) + } + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); + err.push_str("Please check your config file."); + Err(err) + } + } + } + + pub fn used_options(&self) -> PartialConfig { + PartialConfig { + $( + $i: if self.$i.0.get() { + Some(self.$i.2.clone()) + } else { + None + }, + )+ + } + } + + pub fn all_options(&self) -> PartialConfig { + PartialConfig { + $( + $i: Some(self.$i.2.clone()), + )+ + } + } + + pub fn override_value(&mut self, key: &str, val: &str) + { + match key { + $( + stringify!($i) => { + self.$i.1 = true; + self.$i.2 = val.parse::<$ty>() + .expect(&format!("Failed to parse override for {} (\"{}\") as a {}", + stringify!($i), + val, + stringify!($ty))); + } + )+ + _ => panic!("Unknown config key in override: {}", key) + } + + match key { + "max_width" | "use_small_heuristics" => self.set_heuristics(), + "license_template_path" => self.set_license_template(), + &_ => (), + } + } + + /// Construct a `Config` from the toml file specified at `file_path`. + /// + /// This method only looks at the provided path, for a method that + /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. + /// + /// Return a `Config` if the config could be read and parsed from + /// the file, Error otherwise. + pub(super) fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + Config::from_toml(&toml, file_path.parent().unwrap()) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + /// Resolve the config for input in `dir`. + /// + /// Searches for `rustfmt.toml` beginning with `dir`, and + /// recursively checking parents of `dir` if no config file is found. + /// If no config file exists in `dir` or in any parent, a + /// default `Config` will be returned (and the returned path will be empty). + /// + /// Returns the `Config` to use, and the path of the project file if there was + /// one. + pub(super) fn from_resolved_toml_path( + dir: &Path, + ) -> Result<(Config, Option), Error> { + /// Try to find a project file in the given directory and its parents. + /// Returns the path of a the nearest project file if one exists, + /// or `None` if no project file was found. + fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => () + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + return Ok(None); + } + } + } + + match resolve_project_file(dir)? { + None => Ok((Config::default(), None)), + Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + } + } + + pub fn is_hidden_option(name: &str) -> bool { + const HIDE_OPTIONS: [&str; 4] = + ["verbose", "verbose_diff", "file_lines", "width_heuristics"]; + HIDE_OPTIONS.contains(&name) + } + + pub fn print_docs(out: &mut Write, include_unstable: bool) { + use std::cmp; + let max = 0; + $( let max = cmp::max(max, stringify!($i).len()+1); )+ + let mut space_str = String::with_capacity(max); + for _ in 0..max { + space_str.push(' '); + } + writeln!(out, "Configuration Options:").unwrap(); + $( + if $stb || include_unstable { + let name_raw = stringify!($i); + + if !Config::is_hidden_option(name_raw) { + let mut name_out = String::with_capacity(max); + for _ in name_raw.len()..max-1 { + name_out.push(' ') + } + name_out.push_str(name_raw); + name_out.push(' '); + writeln!(out, + "{}{} Default: {:?}{}", + name_out, + <$ty>::doc_hint(), + $def, + if !$stb { " (unstable)" } else { "" }).unwrap(); + $( + writeln!(out, "{}{}", space_str, $dstring).unwrap(); + )+ + writeln!(out).unwrap(); + } + } + )+ + } + + fn set_heuristics(&mut self) { + if self.use_small_heuristics.2 == Heuristics::Default { + let max_width = self.max_width.2; + self.set().width_heuristics(WidthHeuristics::scaled(max_width)); + } else if self.use_small_heuristics.2 == Heuristics::Max { + let max_width = self.max_width.2; + self.set().width_heuristics(WidthHeuristics::set(max_width)); + } else { + self.set().width_heuristics(WidthHeuristics::null()); + } + } + + fn set_license_template(&mut self) { + if self.was_set().license_template_path() { + let lt_path = self.license_template_path(); + match license::load_and_compile_template(<_path) { + Ok(re) => self.license_template = Some(re), + Err(msg) => eprintln!("Warning for license template file {:?}: {}", + lt_path, msg), + } + } + } + + fn set_ignore(&mut self, dir: &Path) { + self.ignore.2.add_prefix(dir); + } + + /// Returns true if the config key was explicitely set and is the default value. + pub fn is_default(&self, key: &str) -> bool { + $( + if let stringify!($i) = key { + return self.$i.1 && self.$i.2 == $def; + } + )+ + false + } + } + + // Template for the default configuration + impl Default for Config { + fn default() -> Config { + Config { + license_template: None, + $( + $i: (Cell::new(false), false, $def, $stb), + )+ + } + } + } + ) +} diff --git a/config/file_lines.rs b/config/file_lines.rs new file mode 100644 index 00000000000..e113118c643 --- /dev/null +++ b/config/file_lines.rs @@ -0,0 +1,422 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module contains types and functions to support formatting specific line ranges. + +use std::collections::HashMap; +use std::path::PathBuf; +use std::rc::Rc; +use std::{cmp, fmt, iter, str}; + +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{self, Serialize, Serializer}; +use serde_json as json; + +use syntax::source_map::{self, SourceFile}; + +/// A range of lines in a file, inclusive of both ends. +pub struct LineRange { + pub file: Rc, + pub lo: usize, + pub hi: usize, +} + +/// Defines the name of an input - either a file or stdin. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] +pub enum FileName { + Real(PathBuf), + Stdin, +} + +impl From for FileName { + fn from(name: source_map::FileName) -> FileName { + match name { + source_map::FileName::Real(p) => FileName::Real(p), + source_map::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, + _ => unreachable!(), + } + } +} + +impl fmt::Display for FileName { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + FileName::Real(p) => write!(f, "{}", p.to_str().unwrap()), + FileName::Stdin => write!(f, "stdin"), + } + } +} + +impl<'de> Deserialize<'de> for FileName { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + if s == "stdin" { + Ok(FileName::Stdin) + } else { + Ok(FileName::Real(s.into())) + } + } +} + +impl Serialize for FileName { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let s = match self { + FileName::Stdin => Ok("stdin"), + FileName::Real(path) => path + .to_str() + .ok_or_else(|| ser::Error::custom("path can't be serialized as UTF-8 string")), + }; + + s.and_then(|s| serializer.serialize_str(s)) + } +} + +impl LineRange { + pub fn file_name(&self) -> FileName { + self.file.name.clone().into() + } +} + +/// A range that is inclusive of both ends. +#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Deserialize)] +pub struct Range { + lo: usize, + hi: usize, +} + +impl<'a> From<&'a LineRange> for Range { + fn from(range: &'a LineRange) -> Range { + Range::new(range.lo, range.hi) + } +} + +impl Range { + pub fn new(lo: usize, hi: usize) -> Range { + Range { lo, hi } + } + + fn is_empty(self) -> bool { + self.lo > self.hi + } + + #[allow(dead_code)] + fn contains(self, other: Range) -> bool { + if other.is_empty() { + true + } else { + !self.is_empty() && self.lo <= other.lo && self.hi >= other.hi + } + } + + fn intersects(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + (self.lo <= other.hi && other.hi <= self.hi) + || (other.lo <= self.hi && self.hi <= other.hi) + } + } + + fn adjacent_to(self, other: Range) -> bool { + if self.is_empty() || other.is_empty() { + false + } else { + self.hi + 1 == other.lo || other.hi + 1 == self.lo + } + } + + /// Returns a new `Range` with lines from `self` and `other` if they were adjacent or + /// intersect; returns `None` otherwise. + fn merge(self, other: Range) -> Option { + if self.adjacent_to(other) || self.intersects(other) { + Some(Range::new( + cmp::min(self.lo, other.lo), + cmp::max(self.hi, other.hi), + )) + } else { + None + } + } +} + +/// A set of lines in files. +/// +/// It is represented as a multimap keyed on file names, with values a collection of +/// non-overlapping ranges sorted by their start point. An inner `None` is interpreted to mean all +/// lines in all files. +#[derive(Clone, Debug, Default, PartialEq)] +pub struct FileLines(Option>>); + +/// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, +/// and ordered by their start point. +fn normalize_ranges(ranges: &mut HashMap>) { + for ranges in ranges.values_mut() { + ranges.sort(); + let mut result = vec![]; + { + let mut iter = ranges.into_iter().peekable(); + while let Some(next) = iter.next() { + let mut next = *next; + while let Some(&&mut peek) = iter.peek() { + if let Some(merged) = next.merge(peek) { + iter.next().unwrap(); + next = merged; + } else { + break; + } + } + result.push(next) + } + } + *ranges = result; + } +} + +impl FileLines { + /// Creates a `FileLines` that contains all lines in all files. + pub(crate) fn all() -> FileLines { + FileLines(None) + } + + /// Returns true if this `FileLines` contains all lines in all files. + pub(crate) fn is_all(&self) -> bool { + self.0.is_none() + } + + pub fn from_ranges(mut ranges: HashMap>) -> FileLines { + normalize_ranges(&mut ranges); + FileLines(Some(ranges)) + } + + /// Returns an iterator over the files contained in `self`. + pub fn files(&self) -> Files { + Files(self.0.as_ref().map(|m| m.keys())) + } + + /// Returns JSON representation as accepted by the `--file-lines JSON` arg. + pub fn to_json_spans(&self) -> Vec { + match &self.0 { + None => vec![], + Some(file_ranges) => file_ranges + .iter() + .flat_map(|(file, ranges)| ranges.iter().map(move |r| (file, r))) + .map(|(file, range)| JsonSpan { + file: file.to_owned(), + range: (range.lo, range.hi), + }).collect(), + } + } + + /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in + /// the designated file (if any) and returns true if `f` ever does. + fn file_range_matches(&self, file_name: &FileName, f: F) -> bool + where + F: FnMut(&Range) -> bool, + { + let map = match self.0 { + // `None` means "all lines in all files". + None => return true, + Some(ref map) => map, + }; + + match canonicalize_path_string(file_name).and_then(|file| map.get(&file)) { + Some(ranges) => ranges.iter().any(f), + None => false, + } + } + + /// Returns true if `range` is fully contained in `self`. + #[allow(dead_code)] + pub(crate) fn contains(&self, range: &LineRange) -> bool { + self.file_range_matches(&range.file_name(), |r| r.contains(Range::from(range))) + } + + /// Returns true if any lines in `range` are in `self`. + pub(crate) fn intersects(&self, range: &LineRange) -> bool { + self.file_range_matches(&range.file_name(), |r| r.intersects(Range::from(range))) + } + + /// Returns true if `line` from `file_name` is in `self`. + pub(crate) fn contains_line(&self, file_name: &FileName, line: usize) -> bool { + self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) + } + + /// Returns true if all the lines between `lo` and `hi` from `file_name` are in `self`. + pub(crate) fn contains_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { + self.file_range_matches(file_name, |r| r.contains(Range::new(lo, hi))) + } +} + +/// `FileLines` files iterator. +pub struct Files<'a>(Option<::std::collections::hash_map::Keys<'a, FileName, Vec>>); + +impl<'a> iter::Iterator for Files<'a> { + type Item = &'a FileName; + + fn next(&mut self) -> Option<&'a FileName> { + self.0.as_mut().and_then(Iterator::next) + } +} + +fn canonicalize_path_string(file: &FileName) -> Option { + match *file { + FileName::Real(ref path) => path.canonicalize().ok().map(FileName::Real), + _ => Some(file.clone()), + } +} + +// This impl is needed for `Config::override_value` to work for use in tests. +impl str::FromStr for FileLines { + type Err = String; + + fn from_str(s: &str) -> Result { + let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; + let mut m = HashMap::new(); + for js in v { + let (s, r) = JsonSpan::into_tuple(js)?; + m.entry(s).or_insert_with(|| vec![]).push(r); + } + Ok(FileLines::from_ranges(m)) + } +} + +// For JSON decoding. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)] +pub struct JsonSpan { + file: FileName, + range: (usize, usize), +} + +impl JsonSpan { + fn into_tuple(self) -> Result<(FileName, Range), String> { + let (lo, hi) = self.range; + let canonical = canonicalize_path_string(&self.file) + .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; + Ok((canonical, Range::new(lo, hi))) + } +} + +// This impl is needed for inclusion in the `Config` struct. We don't have a toml representation +// for `FileLines`, so it will just panic instead. +impl<'de> ::serde::de::Deserialize<'de> for FileLines { + fn deserialize(_: D) -> Result + where + D: ::serde::de::Deserializer<'de>, + { + panic!( + "FileLines cannot be deserialized from a project rustfmt.toml file: please \ + specify it via the `--file-lines` option instead" + ); + } +} + +// We also want to avoid attempting to serialize a FileLines to toml. The +// `Config` struct should ensure this impl is never reached. +impl ::serde::ser::Serialize for FileLines { + fn serialize(&self, _: S) -> Result + where + S: ::serde::ser::Serializer, + { + unreachable!("FileLines cannot be serialized. This is a rustfmt bug."); + } +} + +#[cfg(test)] +mod test { + use super::Range; + + #[test] + fn test_range_intersects() { + assert!(Range::new(1, 2).intersects(Range::new(1, 1))); + assert!(Range::new(1, 2).intersects(Range::new(2, 2))); + assert!(!Range::new(1, 2).intersects(Range::new(0, 0))); + assert!(!Range::new(1, 2).intersects(Range::new(3, 10))); + assert!(!Range::new(1, 3).intersects(Range::new(5, 5))); + } + + #[test] + fn test_range_adjacent_to() { + assert!(!Range::new(1, 2).adjacent_to(Range::new(1, 1))); + assert!(!Range::new(1, 2).adjacent_to(Range::new(2, 2))); + assert!(Range::new(1, 2).adjacent_to(Range::new(0, 0))); + assert!(Range::new(1, 2).adjacent_to(Range::new(3, 10))); + assert!(!Range::new(1, 3).adjacent_to(Range::new(5, 5))); + } + + #[test] + fn test_range_contains() { + assert!(Range::new(1, 2).contains(Range::new(1, 1))); + assert!(Range::new(1, 2).contains(Range::new(2, 2))); + assert!(!Range::new(1, 2).contains(Range::new(0, 0))); + assert!(!Range::new(1, 2).contains(Range::new(3, 10))); + } + + #[test] + fn test_range_merge() { + assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5))); + assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1))); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(4, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(5, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 5).merge(Range::new(6, 7)) + ); + assert_eq!( + Some(Range::new(3, 7)), + Range::new(3, 7).merge(Range::new(4, 5)) + ); + } + + use super::json::{self, json}; + use super::{FileLines, FileName}; + use std::{collections::HashMap, path::PathBuf}; + + #[test] + fn file_lines_to_json() { + let ranges: HashMap> = [ + ( + FileName::Real(PathBuf::from("src/main.rs")), + vec![Range::new(1, 3), Range::new(5, 7)], + ), + ( + FileName::Real(PathBuf::from("src/lib.rs")), + vec![Range::new(1, 7)], + ), + ] + .iter() + .cloned() + .collect(); + + let file_lines = FileLines::from_ranges(ranges); + let mut spans = file_lines.to_json_spans(); + spans.sort(); + let json = json::to_value(&spans).unwrap(); + assert_eq!( + json, + json! {[ + {"file": "src/lib.rs", "range": [1, 7]}, + {"file": "src/main.rs", "range": [1, 3]}, + {"file": "src/main.rs", "range": [5, 7]}, + ]} + ); + } +} diff --git a/config/license.rs b/config/license.rs new file mode 100644 index 00000000000..630399319c1 --- /dev/null +++ b/config/license.rs @@ -0,0 +1,266 @@ +use std::fmt; +use std::fs::File; +use std::io; +use std::io::Read; + +use regex; +use regex::Regex; + +#[derive(Debug)] +pub enum LicenseError { + IO(io::Error), + Regex(regex::Error), + Parse(String), +} + +impl fmt::Display for LicenseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + LicenseError::IO(ref err) => err.fmt(f), + LicenseError::Regex(ref err) => err.fmt(f), + LicenseError::Parse(ref err) => write!(f, "parsing failed, {}", err), + } + } +} + +impl From for LicenseError { + fn from(err: io::Error) -> LicenseError { + LicenseError::IO(err) + } +} + +impl From for LicenseError { + fn from(err: regex::Error) -> LicenseError { + LicenseError::Regex(err) + } +} + +// the template is parsed using a state machine +enum ParsingState { + Lit, + LitEsc, + // the u32 keeps track of brace nesting + Re(u32), + ReEsc(u32), + Abort(String), +} + +use self::ParsingState::*; + +pub struct TemplateParser { + parsed: String, + buffer: String, + state: ParsingState, + linum: u32, + open_brace_line: u32, +} + +impl TemplateParser { + fn new() -> Self { + Self { + parsed: "^".to_owned(), + buffer: String::new(), + state: Lit, + linum: 1, + // keeps track of last line on which a regex placeholder was started + open_brace_line: 0, + } + } + + /// Convert a license template into a string which can be turned into a regex. + /// + /// The license template could use regex syntax directly, but that would require a lot of manual + /// escaping, which is inconvenient. It is therefore literal by default, with optional regex + /// subparts delimited by `{` and `}`. Additionally: + /// + /// - to insert literal `{`, `}` or `\`, escape it with `\` + /// - an empty regex placeholder (`{}`) is shorthand for `{.*?}` + /// + /// This function parses this input format and builds a properly escaped *string* representation + /// of the equivalent regular expression. It **does not** however guarantee that the returned + /// string is a syntactically valid regular expression. + /// + /// # Examples + /// + /// ```ignore + /// assert_eq!( + /// TemplateParser::parse( + /// r" + /// // Copyright {\d+} The \} Rust \\ Project \{ Developers. See the {([A-Z]+)} + /// // file at the top-level directory of this distribution and at + /// // {}. + /// // + /// // Licensed under the Apache License, Version 2.0 or the MIT license + /// // , at your + /// // option. This file may not be copied, modified, or distributed + /// // except according to those terms. + /// " + /// ).unwrap(), + /// r"^ + /// // Copyright \d+ The \} Rust \\ Project \{ Developers\. See the ([A-Z]+) + /// // file at the top\-level directory of this distribution and at + /// // .*?\. + /// // + /// // Licensed under the Apache License, Version 2\.0 or the MIT license + /// // , at your + /// // option\. This file may not be copied, modified, or distributed + /// // except according to those terms\. + /// " + /// ); + /// ``` + pub fn parse(template: &str) -> Result { + let mut parser = Self::new(); + for chr in template.chars() { + if chr == '\n' { + parser.linum += 1; + } + parser.state = match parser.state { + Lit => parser.trans_from_lit(chr), + LitEsc => parser.trans_from_litesc(chr), + Re(brace_nesting) => parser.trans_from_re(chr, brace_nesting), + ReEsc(brace_nesting) => parser.trans_from_reesc(chr, brace_nesting), + Abort(msg) => return Err(LicenseError::Parse(msg)), + }; + } + // check if we've ended parsing in a valid state + match parser.state { + Abort(msg) => return Err(LicenseError::Parse(msg)), + Re(_) | ReEsc(_) => { + return Err(LicenseError::Parse(format!( + "escape or balance opening brace on l. {}", + parser.open_brace_line + ))); + } + LitEsc => { + return Err(LicenseError::Parse(format!( + "incomplete escape sequence on l. {}", + parser.linum + ))) + } + _ => (), + } + parser.parsed.push_str(®ex::escape(&parser.buffer)); + + Ok(parser.parsed) + } + + fn trans_from_lit(&mut self, chr: char) -> ParsingState { + match chr { + '{' => { + self.parsed.push_str(®ex::escape(&self.buffer)); + self.buffer.clear(); + self.open_brace_line = self.linum; + Re(1) + } + '}' => Abort(format!( + "escape or balance closing brace on l. {}", + self.linum + )), + '\\' => LitEsc, + _ => { + self.buffer.push(chr); + Lit + } + } + } + + fn trans_from_litesc(&mut self, chr: char) -> ParsingState { + self.buffer.push(chr); + Lit + } + + fn trans_from_re(&mut self, chr: char, brace_nesting: u32) -> ParsingState { + match chr { + '{' => { + self.buffer.push(chr); + Re(brace_nesting + 1) + } + '}' => { + match brace_nesting { + 1 => { + // default regex for empty placeholder {} + if self.buffer.is_empty() { + self.parsed.push_str(".*?"); + } else { + self.parsed.push_str(&self.buffer); + } + self.buffer.clear(); + Lit + } + _ => { + self.buffer.push(chr); + Re(brace_nesting - 1) + } + } + } + '\\' => { + self.buffer.push(chr); + ReEsc(brace_nesting) + } + _ => { + self.buffer.push(chr); + Re(brace_nesting) + } + } + } + + fn trans_from_reesc(&mut self, chr: char, brace_nesting: u32) -> ParsingState { + self.buffer.push(chr); + Re(brace_nesting) + } +} + +pub fn load_and_compile_template(path: &str) -> Result { + let mut lt_file = File::open(&path)?; + let mut lt_str = String::new(); + lt_file.read_to_string(&mut lt_str)?; + let lt_parsed = TemplateParser::parse(<_str)?; + Ok(Regex::new(<_parsed)?) +} + +#[cfg(test)] +mod test { + use super::TemplateParser; + + #[test] + fn test_parse_license_template() { + assert_eq!( + TemplateParser::parse("literal (.*)").unwrap(), + r"^literal \(\.\*\)" + ); + assert_eq!( + TemplateParser::parse(r"escaping \}").unwrap(), + r"^escaping \}" + ); + assert!(TemplateParser::parse("unbalanced } without escape").is_err()); + assert_eq!( + TemplateParser::parse(r"{\d+} place{-?}holder{s?}").unwrap(), + r"^\d+ place-?holders?" + ); + assert_eq!(TemplateParser::parse("default {}").unwrap(), "^default .*?"); + assert_eq!( + TemplateParser::parse(r"unbalanced nested braces {\{{3}}").unwrap(), + r"^unbalanced nested braces \{{3}" + ); + assert_eq!( + &TemplateParser::parse("parsing error }") + .unwrap_err() + .to_string(), + "parsing failed, escape or balance closing brace on l. 1" + ); + assert_eq!( + &TemplateParser::parse("parsing error {\nsecond line") + .unwrap_err() + .to_string(), + "parsing failed, escape or balance opening brace on l. 1" + ); + assert_eq!( + &TemplateParser::parse(r"parsing error \") + .unwrap_err() + .to_string(), + "parsing failed, incomplete escape sequence on l. 1" + ); + } +} diff --git a/config/lists.rs b/config/lists.rs new file mode 100644 index 00000000000..04406e8d566 --- /dev/null +++ b/config/lists.rs @@ -0,0 +1,105 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Configuration options related to rewriting a list. + +use config::config_type::ConfigType; +use config::IndentStyle; + +/// The definitive formatting tactic for lists. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum DefinitiveListTactic { + Vertical, + Horizontal, + Mixed, + /// Special case tactic for `format!()`, `write!()` style macros. + SpecialMacro(usize), +} + +impl DefinitiveListTactic { + pub fn ends_with_newline(&self, indent_style: IndentStyle) -> bool { + match indent_style { + IndentStyle::Block => *self != DefinitiveListTactic::Horizontal, + IndentStyle::Visual => false, + } + } +} + +/// Formatting tactic for lists. This will be cast down to a +/// `DefinitiveListTactic` depending on the number and length of the items and +/// their comments. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum ListTactic { + // One item per row. + Vertical, + // All items on one row. + Horizontal, + // Try Horizontal layout, if that fails then vertical. + HorizontalVertical, + // HorizontalVertical with a soft limit of n characters. + LimitedHorizontalVertical(usize), + // Pack as many items as possible per row over (possibly) many rows. + Mixed, +} + +impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorTactic { + Always, + Never, + Vertical, +} + +impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); + +impl SeparatorTactic { + pub fn from_bool(b: bool) -> SeparatorTactic { + if b { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + } + } +} + +/// Where to put separator. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum SeparatorPlace { + Front, + Back, +} + +impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); + +impl SeparatorPlace { + pub fn is_front(&self) -> bool { + *self == SeparatorPlace::Front + } + + pub fn is_back(&self) -> bool { + *self == SeparatorPlace::Back + } + + pub fn from_tactic( + default: SeparatorPlace, + tactic: DefinitiveListTactic, + sep: &str, + ) -> SeparatorPlace { + match tactic { + DefinitiveListTactic::Vertical => default, + _ => if sep == "," { + SeparatorPlace::Back + } else { + default + }, + } + } +} diff --git a/config/mod.rs b/config/mod.rs new file mode 100644 index 00000000000..f240c7b13c6 --- /dev/null +++ b/config/mod.rs @@ -0,0 +1,360 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use regex::Regex; +use std::cell::Cell; +use std::default::Default; +use std::fs::File; +use std::io::{Error, ErrorKind, Read}; +use std::path::{Path, PathBuf}; +use std::{env, fs}; + +use config::config_type::ConfigType; +pub use config::file_lines::{FileLines, FileName, Range}; +pub use config::lists::*; +pub use config::options::*; + +#[macro_use] +pub mod config_type; +#[macro_use] +pub mod options; + +pub mod file_lines; +pub mod license; +pub mod lists; + +/// This macro defines configuration options used in rustfmt. Each option +/// is defined as follows: +/// +/// `name: value type, default value, is stable, description;` +create_config! { + // Fundamental stuff + max_width: usize, 100, true, "Maximum width of each line"; + hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; + tab_spaces: usize, 4, true, "Number of spaces per tab"; + newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings"; + use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ + formatting for items and expressions if they satisfy a heuristic notion of 'small'"; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; + + // Comments. macros, and strings + wrap_comments: bool, false, false, "Break comments to fit on the line"; + comment_width: usize, 80, false, + "Maximum length of comments. No effect unless wrap_comments = true"; + normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; + license_template_path: String, String::default(), false, + "Beginning of file must match license template"; + format_strings: bool, false, false, "Format string literals where necessary"; + format_macro_matchers: bool, false, false, + "Format the metavariable matching patterns in macros"; + format_macro_bodies: bool, true, false, "Format the bodies of macros"; + + // Single line expressions and items + empty_item_single_line: bool, true, false, + "Put empty-body functions and impls on a single line"; + struct_lit_single_line: bool, true, false, + "Put small struct literals on a single line"; + fn_single_line: bool, false, false, "Put single-expression functions on a single line"; + where_single_line: bool, false, false, "Force where clauses to be on a single line"; + + // Imports + imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports"; + imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; + merge_imports: bool, false, false, "Merge imports"; + + // Ordering + reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically"; + reorder_modules: bool, true, true, "Reorder module statements alphabetically in group"; + reorder_impl_items: bool, false, false, "Reorder impl items"; + + // Spaces around punctuation + type_punctuation_density: TypeDensity, TypeDensity::Wide, false, + "Determines if '+' or '=' are wrapped in spaces in the punctuation of types"; + space_before_colon: bool, false, false, "Leave a space before the colon"; + space_after_colon: bool, true, false, "Leave a space after the colon"; + spaces_around_ranges: bool, false, false, "Put spaces around the .. and ..= range operators"; + binop_separator: SeparatorPlace, SeparatorPlace::Front, false, + "Where to put a binary operator when a binary expression goes multiline"; + + // Misc. + remove_nested_parens: bool, true, true, "Remove nested parens"; + combine_control_expr: bool, true, false, "Combine control expressions with function calls"; + struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ + threshold"; + match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ + the same line with the pattern of arms"; + force_multiline_blocks: bool, false, false, + "Force multiline closure bodies and match arms to be wrapped in a block"; + fn_args_density: Density, Density::Tall, false, "Argument density in functions"; + brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; + control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, + "Brace style for control flow constructs"; + trailing_semicolon: bool, true, false, + "Add trailing semicolon after break, continue and return"; + trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false, + "How to handle trailing commas for lists"; + match_block_trailing_comma: bool, false, false, + "Put a trailing comma after a block based match arm (non-block arms are not affected)"; + blank_lines_upper_bound: usize, 1, false, + "Maximum number of blank lines which can be put between items"; + blank_lines_lower_bound: usize, 0, false, + "Minimum number of blank lines which must be put between items"; + edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)"; + + // Options that can change the source code beyond whitespace/blocks (somewhat linty things) + merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; + use_try_shorthand: bool, false, true, "Replace uses of the try! macro by the ? shorthand"; + use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible"; + force_explicit_abi: bool, true, true, "Always print the abi for extern items"; + condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \ + in tuple patterns"; + + // Control options (changes the operation of rustfmt, rather than the formatting) + color: Color, Color::Auto, false, + "What Color option to use when none is supplied: Always, Never, Auto"; + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, + "Require a specific version of rustfmt"; + unstable_features: bool, false, false, + "Enables unstable features. Only available on nightly channel"; + disable_all_formatting: bool, false, false, "Don't reformat anything"; + skip_children: bool, false, false, "Don't reformat out of line modules"; + hide_parse_errors: bool, false, false, "Hide errors from the parser"; + error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width"; + error_on_unformatted: bool, false, false, + "Error if unable to get comments or string literals within max_width, \ + or they are left with trailing whitespaces"; + report_todo: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of TODO in source file comments"; + report_fixme: ReportTactic, ReportTactic::Never, false, + "Report all, none or unnumbered occurrences of FIXME in source file comments"; + ignore: IgnoreList, IgnoreList::default(), false, + "Skip formatting the specified files and directories"; + + // Not user-facing + verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; + emit_mode: EmitMode, EmitMode::Files, false, + "What emit Mode to use when none is supplied"; + make_backup: bool, false, false, "Backup changed files"; +} + +/// Load a config by checking the client-supplied options and if appropriate, the +/// file system (including searching the file system for overrides). +pub fn load_config( + file_path: Option<&Path>, + options: Option, +) -> Result<(Config, Option), Error> { + let over_ride = match options { + Some(ref opts) => config_path(opts)?, + None => None, + }; + + let result = if let Some(over_ride) = over_ride { + Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned()))) + } else if let Some(file_path) = file_path { + Config::from_resolved_toml_path(file_path) + } else { + Ok((Config::default(), None)) + }; + + result.map(|(mut c, p)| { + if let Some(options) = options { + options.apply_to(&mut c); + } + (c, p) + }) +} + +// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +// +// Return the path if a config file exists, empty if no file exists, and Error for IO errors +fn get_toml_path(dir: &Path) -> Result, Error> { + const CONFIG_FILE_NAMES: [&str; 2] = [".rustfmt.toml", "rustfmt.toml"]; + for config_file_name in &CONFIG_FILE_NAMES { + let config_file = dir.join(config_file_name); + match fs::metadata(&config_file) { + // Only return if it's a file to handle the unlikely situation of a directory named + // `rustfmt.toml`. + Ok(ref md) if md.is_file() => return Ok(Some(config_file)), + // Return the error if it's something other than `NotFound`; otherwise we didn't + // find the project file yet, and continue searching. + Err(e) => { + if e.kind() != ErrorKind::NotFound { + return Err(e); + } + } + _ => {} + } + } + Ok(None) +} + +fn config_path(options: &CliOptions) -> Result, Error> { + let config_path_not_found = |path: &str| -> Result, Error> { + Err(Error::new( + ErrorKind::NotFound, + format!( + "Error: unable to find a config file for the given path: `{}`", + path + ), + )) + }; + + // Read the config_path and convert to parent dir if a file is provided. + // If a config file cannot be found from the given path, return error. + match options.config_path() { + Some(path) if !path.exists() => config_path_not_found(path.to_str().unwrap()), + Some(path) if path.is_dir() => { + let config_file_path = get_toml_path(path)?; + if config_file_path.is_some() { + Ok(config_file_path) + } else { + config_path_not_found(path.to_str().unwrap()) + } + } + path => Ok(path.map(|p| p.to_owned())), + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::str; + + #[allow(dead_code)] + mod mock { + use super::super::*; + + create_config! { + // Options that are used by the generated functions + max_width: usize, 100, true, "Maximum width of each line"; + use_small_heuristics: Heuristics, Heuristics::Default, true, + "Whether to use different formatting for items and \ + expressions if they satisfy a heuristic notion of 'small'."; + license_template_path: String, String::default(), false, + "Beginning of file must match license template"; + required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, + "Require a specific version of rustfmt."; + ignore: IgnoreList, IgnoreList::default(), false, + "Skip formatting the specified files and directories."; + verbose: Verbosity, Verbosity::Normal, false, + "How much to information to emit to the user"; + file_lines: FileLines, FileLines::all(), false, + "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ + via the --file-lines option"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; + + // Options that are used by the tests + stable_option: bool, false, true, "A stable option"; + unstable_option: bool, false, false, "An unstable option"; + } + } + + #[test] + fn test_config_set() { + let mut config = Config::default(); + config.set().verbose(Verbosity::Quiet); + assert_eq!(config.verbose(), Verbosity::Quiet); + config.set().verbose(Verbosity::Normal); + assert_eq!(config.verbose(), Verbosity::Normal); + } + + #[test] + fn test_config_used_to_toml() { + let config = Config::default(); + + let merge_derives = config.merge_derives(); + let skip_children = config.skip_children(); + + let used_options = config.used_options(); + let toml = used_options.to_toml().unwrap(); + assert_eq!( + toml, + format!( + "merge_derives = {}\nskip_children = {}\n", + merge_derives, skip_children, + ) + ); + } + + #[test] + fn test_was_set() { + use std::path::Path; + let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); + + assert_eq!(config.was_set().hard_tabs(), true); + assert_eq!(config.was_set().verbose(), false); + } + + #[test] + fn test_print_docs_exclude_unstable() { + use self::mock::Config; + + let mut output = Vec::new(); + Config::print_docs(&mut output, false); + + let s = str::from_utf8(&output).unwrap(); + + assert_eq!(s.contains("stable_option"), true); + assert_eq!(s.contains("unstable_option"), false); + assert_eq!(s.contains("(unstable)"), false); + } + + #[test] + fn test_print_docs_include_unstable() { + use self::mock::Config; + + let mut output = Vec::new(); + Config::print_docs(&mut output, true); + + let s = str::from_utf8(&output).unwrap(); + assert_eq!(s.contains("stable_option"), true); + assert_eq!(s.contains("unstable_option"), true); + assert_eq!(s.contains("(unstable)"), true); + } + + // FIXME(#2183) these tests cannot be run in parallel because they use env vars + // #[test] + // fn test_as_not_nightly_channel() { + // let mut config = Config::default(); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // } + + // #[test] + // fn test_as_nightly_channel() { + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // let mut config = Config::default(); + // config.set().unstable_features(true); + // assert_eq!(config.was_set().unstable_features(), false); + // config.set().unstable_features(true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } + + // #[test] + // fn test_unstable_from_toml() { + // let mut config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), false); + // let v = ::std::env::var("CFG_RELEASE_CHANNEL").unwrap_or(String::from("")); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", "nightly"); + // config = Config::from_toml("unstable_features = true").unwrap(); + // assert_eq!(config.was_set().unstable_features(), true); + // assert_eq!(config.unstable_features(), true); + // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); + // } +} diff --git a/config/options.rs b/config/options.rs new file mode 100644 index 00000000000..d2a74f54677 --- /dev/null +++ b/config/options.rs @@ -0,0 +1,482 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use config::config_type::ConfigType; +use config::lists::*; +use config::{Config, FileName}; + +use isatty::stdout_isatty; + +use std::collections::HashSet; +use std::path::{Path, PathBuf}; + +/// Macro for deriving implementations of Serialize/Deserialize for enums +#[macro_export] +macro_rules! impl_enum_serialize_and_deserialize { + ( $e:ident, $( $x:ident ),* ) => { + impl ::serde::ser::Serialize for $e { + fn serialize(&self, serializer: S) -> Result + where S: ::serde::ser::Serializer + { + use serde::ser::Error; + + // We don't know whether the user of the macro has given us all options. + #[allow(unreachable_patterns)] + match *self { + $( + $e::$x => serializer.serialize_str(stringify!($x)), + )* + _ => { + Err(S::Error::custom(format!("Cannot serialize {:?}", self))) + } + } + } + } + + impl<'de> ::serde::de::Deserialize<'de> for $e { + fn deserialize(d: D) -> Result + where D: ::serde::Deserializer<'de> { + use serde::de::{Error, Visitor}; + use std::marker::PhantomData; + use std::fmt; + struct StringOnly(PhantomData); + impl<'de, T> Visitor<'de> for StringOnly + where T: ::serde::Deserializer<'de> { + type Value = String; + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("string") + } + fn visit_str(self, value: &str) -> Result { + Ok(String::from(value)) + } + } + let s = d.deserialize_string(StringOnly::(PhantomData))?; + $( + if stringify!($x).eq_ignore_ascii_case(&s) { + return Ok($e::$x); + } + )* + static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; + Err(D::Error::unknown_variant(&s, ALLOWED)) + } + } + + impl ::std::str::FromStr for $e { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + $( + if stringify!($x).eq_ignore_ascii_case(s) { + return Ok($e::$x); + } + )* + Err("Bad variant") + } + } + + impl ConfigType for $e { + fn doc_hint() -> String { + let mut variants = Vec::new(); + $( + variants.push(stringify!($x)); + )* + format!("[{}]", variants.join("|")) + } + } + }; +} + +macro_rules! configuration_option_enum{ + ($e:ident: $( $x:ident ),+ $(,)*) => { + #[derive(Copy, Clone, Eq, PartialEq, Debug)] + pub enum $e { + $( $x ),+ + } + + impl_enum_serialize_and_deserialize!($e, $( $x ),+); + } +} + +configuration_option_enum! { NewlineStyle: + Auto, // Auto-detect based on the raw source input + Windows, // \r\n + Unix, // \n + Native, // \r\n in Windows, \n on other platforms +} + +impl NewlineStyle { + fn auto_detect(raw_input_text: &str) -> NewlineStyle { + if let Some(pos) = raw_input_text.find('\n') { + let pos = pos.saturating_sub(1); + if let Some('\r') = raw_input_text.chars().nth(pos) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + NewlineStyle::Native + } + } + + fn native() -> NewlineStyle { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } + + /// Apply this newline style to the formatted text. When the style is set + /// to `Auto`, the `raw_input_text` is used to detect the existing line + /// endings. + /// + /// If the style is set to `Auto` and `raw_input_text` contains no + /// newlines, the `Native` style will be used. + pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { + use NewlineStyle::*; + let mut style = self; + if style == Auto { + style = Self::auto_detect(raw_input_text); + } + if style == Native { + style = Self::native(); + } + match style { + Windows => { + let mut transformed = String::with_capacity(2 * formatted_text.capacity()); + for c in formatted_text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } + } + *formatted_text = transformed; + } + Unix => return, + Native => unreachable!("NewlineStyle::Native"), + Auto => unreachable!("NewlineStyle::Auto"), + } + } +} + +configuration_option_enum! { BraceStyle: + AlwaysNextLine, + PreferSameLine, + // Prefer same line except where there is a where clause, in which case force + // the brace to the next line. + SameLineWhere, +} + +configuration_option_enum! { ControlBraceStyle: + // K&R style, Rust community default + AlwaysSameLine, + // Stroustrup style + ClosingNextLine, + // Allman style + AlwaysNextLine, +} + +configuration_option_enum! { IndentStyle: + // First line on the same line as the opening brace, all lines aligned with + // the first line. + Visual, + // First line is on a new line and all lines align with block indent. + Block, +} + +configuration_option_enum! { Density: + // Fit as much on one line as possible. + Compressed, + // Use more lines. + Tall, + // Place every item on a separate line. + Vertical, +} + +configuration_option_enum! { TypeDensity: + // No spaces around "=" and "+" + Compressed, + // Spaces around " = " and " + " + Wide, +} + +configuration_option_enum! { Heuristics: + // Turn off any heuristics + Off, + // Turn on max heuristics + Max, + // Use Rustfmt's defaults + Default, +} + +impl Density { + pub fn to_list_tactic(self) -> ListTactic { + match self { + Density::Compressed => ListTactic::Mixed, + Density::Tall => ListTactic::HorizontalVertical, + Density::Vertical => ListTactic::Vertical, + } + } +} + +configuration_option_enum! { ReportTactic: + Always, + Unnumbered, + Never, +} + +// What Rustfmt should emit. Mostly corresponds to the `--emit` command line +// option. +configuration_option_enum! { EmitMode: + // Emits to files. + Files, + // Writes the output to stdout. + Stdout, + // Displays how much of the input file was processed + Coverage, + // Unfancy stdout + Checkstyle, + // Output the changed lines (for internal value only) + ModifiedLines, + // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. + // This option is designed to be run in CI where a non-zero exit signifies non-standard code + // formatting. Used for `--check`. + Diff, +} + +// Client-preference for coloured output. +configuration_option_enum! { Color: + // Always use color, whether it is a piped or terminal output + Always, + // Never use color + Never, + // Automatically use color, if supported by terminal + Auto, +} + +impl Color { + /// Whether we should use a coloured terminal. + pub fn use_colored_tty(&self) -> bool { + match self { + Color::Always => true, + Color::Never => false, + Color::Auto => stdout_isatty(), + } + } +} + +// How chatty should Rustfmt be? +configuration_option_enum! { Verbosity: + // Emit more. + Verbose, + Normal, + // Emit as little as possible. + Quiet, +} + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +pub struct WidthHeuristics { + // Maximum width of the args of a function call before falling back + // to vertical formatting. + pub fn_call_width: usize, + // Maximum width in the body of a struct lit before falling back to + // vertical formatting. + pub struct_lit_width: usize, + // Maximum width in the body of a struct variant before falling back + // to vertical formatting. + pub struct_variant_width: usize, + // Maximum width of an array literal before falling back to vertical + // formatting. + pub array_width: usize, + // Maximum length of a chain to fit on a single line. + pub chain_width: usize, + // Maximum line length for single line if-else expressions. A value + // of zero means always break if-else expressions. + pub single_line_if_else_max_width: usize, +} + +impl WidthHeuristics { + // Using this WidthHeuristics means we ignore heuristics. + pub fn null() -> WidthHeuristics { + WidthHeuristics { + fn_call_width: usize::max_value(), + struct_lit_width: 0, + struct_variant_width: 0, + array_width: usize::max_value(), + chain_width: usize::max_value(), + single_line_if_else_max_width: 0, + } + } + + pub fn set(max_width: usize) -> WidthHeuristics { + WidthHeuristics { + fn_call_width: max_width, + struct_lit_width: max_width, + struct_variant_width: max_width, + array_width: max_width, + chain_width: max_width, + single_line_if_else_max_width: max_width, + } + } + + // scale the default WidthHeuristics according to max_width + pub fn scaled(max_width: usize) -> WidthHeuristics { + const DEFAULT_MAX_WIDTH: usize = 100; + let max_width_ratio = if max_width > DEFAULT_MAX_WIDTH { + let ratio = max_width as f32 / DEFAULT_MAX_WIDTH as f32; + // round to the closest 0.1 + (ratio * 10.0).round() / 10.0 + } else { + 1.0 + }; + WidthHeuristics { + fn_call_width: (60.0 * max_width_ratio).round() as usize, + struct_lit_width: (18.0 * max_width_ratio).round() as usize, + struct_variant_width: (35.0 * max_width_ratio).round() as usize, + array_width: (60.0 * max_width_ratio).round() as usize, + chain_width: (60.0 * max_width_ratio).round() as usize, + single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize, + } + } +} + +impl ::std::str::FromStr for WidthHeuristics { + type Err = &'static str; + + fn from_str(_: &str) -> Result { + Err("WidthHeuristics is not parsable") + } +} + +impl Default for EmitMode { + fn default() -> EmitMode { + EmitMode::Files + } +} + +/// A set of directories, files and modules that rustfmt should ignore. +#[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)] +pub struct IgnoreList(HashSet); + +impl IgnoreList { + pub fn add_prefix(&mut self, dir: &Path) { + self.0 = self + .0 + .iter() + .map(|s| { + if s.has_root() { + s.clone() + } else { + let mut path = PathBuf::from(dir); + path.push(s); + path + } + }).collect(); + } + + fn skip_file_inner(&self, file: &Path) -> bool { + self.0.iter().any(|path| file.starts_with(path)) + } + + pub fn skip_file(&self, file: &FileName) -> bool { + if let FileName::Real(ref path) = file { + self.skip_file_inner(path) + } else { + false + } + } +} + +impl ::std::str::FromStr for IgnoreList { + type Err = &'static str; + + fn from_str(_: &str) -> Result { + Err("IgnoreList is not parsable") + } +} + +/// Maps client-supplied options to Rustfmt's internals, mostly overriding +/// values in a config with values from the command line. +pub trait CliOptions { + fn apply_to(self, config: &mut Config); + fn config_path(&self) -> Option<&Path>; +} + +/// The edition of the compiler (RFC 2052) +configuration_option_enum!{ Edition: + Edition2015, + Edition2018, +} + +impl Edition { + pub(crate) fn to_libsyntax_pos_edition(&self) -> syntax_pos::edition::Edition { + match self { + Edition::Edition2015 => syntax_pos::edition::Edition::Edition2015, + Edition::Edition2018 => syntax_pos::edition::Edition::Edition2018, + } + } +} + +#[test] +fn test_newline_style_auto_detect() { + let lf = "One\nTwo\nThree"; + let crlf = "One\r\nTwo\r\nThree"; + let none = "One Two Three"; + + assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf)); + assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf)); + assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none)); +} + +#[test] +fn test_newline_style_auto_apply() { + let auto = NewlineStyle::Auto; + + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One\nTwo\nThree"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); + + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One\r\nTwo\r\nThree"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); + + #[cfg(not(windows))] + { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!( + "One\nTwo\nThree", &out, + "auto-native-unix should detect 'lf'" + ); + } + + #[cfg(windows)] + { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!( + "One\r\nTwo\r\nThree", &out, + "auto-native-windows should detect 'crlf'" + ); + } +} diff --git a/format-diff/main.rs b/format-diff/main.rs new file mode 100644 index 00000000000..37ad4f35a1d --- /dev/null +++ b/format-diff/main.rs @@ -0,0 +1,251 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Inspired by Clang's clang-format-diff: +// +// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py + +#![deny(warnings)] + +extern crate env_logger; +#[macro_use] +extern crate failure; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate regex; +#[macro_use] +extern crate serde_derive; +extern crate serde_json as json; + +use std::collections::HashSet; +use std::io::{self, BufRead}; +use std::{env, process}; + +use regex::Regex; + +/// The default pattern of files to format. +/// +/// We only want to format rust files by default. +const DEFAULT_PATTERN: &str = r".*\.rs"; + +#[derive(Fail, Debug)] +enum FormatDiffError { + #[fail(display = "{}", _0)] + IncorrectOptions(#[cause] getopts::Fail), + #[fail(display = "{}", _0)] + IncorrectFilter(#[cause] regex::Error), + #[fail(display = "{}", _0)] + IoError(#[cause] io::Error), +} + +impl From for FormatDiffError { + fn from(fail: getopts::Fail) -> Self { + FormatDiffError::IncorrectOptions(fail) + } +} + +impl From for FormatDiffError { + fn from(err: regex::Error) -> Self { + FormatDiffError::IncorrectFilter(err) + } +} + +impl From for FormatDiffError { + fn from(fail: io::Error) -> Self { + FormatDiffError::IoError(fail) + } +} + +fn main() { + env_logger::init(); + + let mut opts = getopts::Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optopt( + "p", + "skip-prefix", + "skip the smallest prefix containing NUMBER slashes", + "NUMBER", + ); + opts.optopt( + "f", + "filter", + "custom pattern selecting file paths to reformat", + "PATTERN", + ); + + if let Err(e) = run(&opts) { + println!("{}", opts.usage(&format!("{}", e))); + process::exit(1); + } +} + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +struct Range { + file: String, + range: [u32; 2], +} + +fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { + let matches = opts.parse(env::args().skip(1))?; + + if matches.opt_present("h") { + println!("{}", opts.usage("usage: ")); + return Ok(()); + } + + let filter = matches + .opt_str("f") + .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); + + let skip_prefix = matches + .opt_str("p") + .and_then(|p| p.parse::().ok()) + .unwrap_or(0); + + let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; + + run_rustfmt(&files, &ranges) +} + +fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDiffError> { + if files.is_empty() || ranges.is_empty() { + debug!("No files to format found"); + return Ok(()); + } + + let ranges_as_json = json::to_string(ranges).unwrap(); + + debug!("Files: {:?}", files); + debug!("Ranges: {:?}", ranges); + + let exit_status = process::Command::new("rustfmt") + .args(files) + .arg("--file-lines") + .arg(ranges_as_json) + .status()?; + + if !exit_status.success() { + return Err(FormatDiffError::IoError(io::Error::new( + io::ErrorKind::Other, + format!("rustfmt failed with {}", exit_status), + ))); + } + Ok(()) +} + +/// Scans a diff from `from`, and returns the set of files found, and the ranges +/// in those files. +fn scan_diff( + from: R, + skip_prefix: u32, + file_filter: &str, +) -> Result<(HashSet, Vec), FormatDiffError> +where + R: io::Read, +{ + let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix); + let diff_pattern = Regex::new(&diff_pattern).unwrap(); + + let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap(); + + let file_filter = Regex::new(&format!("^{}$", file_filter))?; + + let mut current_file = None; + + let mut files = HashSet::new(); + let mut ranges = vec![]; + for line in io::BufReader::new(from).lines() { + let line = line.unwrap(); + + if let Some(captures) = diff_pattern.captures(&line) { + current_file = Some(captures.get(1).unwrap().as_str().to_owned()); + } + + let file = match current_file { + Some(ref f) => &**f, + None => continue, + }; + + // FIXME(emilio): We could avoid this most of the time if needed, but + // it's not clear it's worth it. + if !file_filter.is_match(file) { + continue; + } + + let lines_captures = match lines_pattern.captures(&line) { + Some(captures) => captures, + None => continue, + }; + + let start_line = lines_captures + .get(1) + .unwrap() + .as_str() + .parse::() + .unwrap(); + let line_count = match lines_captures.get(3) { + Some(line_count) => line_count.as_str().parse::().unwrap(), + None => 1, + }; + + if line_count == 0 { + continue; + } + + let end_line = start_line + line_count - 1; + files.insert(file.to_owned()); + ranges.push(Range { + file: file.to_owned(), + range: [start_line, end_line], + }); + } + + Ok((files, ranges)) +} + +#[test] +fn scan_simple_git_diff() { + const DIFF: &'static str = include_str!("test/bindgen.diff"); + let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); + + assert!( + files.contains("src/ir/traversal.rs"), + "Should've matched the filter" + ); + + assert!( + !files.contains("tests/headers/anon_enum.hpp"), + "Shouldn't have matched the filter" + ); + + assert_eq!( + &ranges, + &[ + Range { + file: "src/ir/item.rs".to_owned(), + range: [148, 158], + }, + Range { + file: "src/ir/item.rs".to_owned(), + range: [160, 170], + }, + Range { + file: "src/ir/traversal.rs".to_owned(), + range: [9, 16], + }, + Range { + file: "src/ir/traversal.rs".to_owned(), + range: [35, 43], + }, + ] + ); +} diff --git a/format-diff/test/bindgen.diff b/format-diff/test/bindgen.diff new file mode 100644 index 00000000000..d2fd379f471 --- /dev/null +++ b/format-diff/test/bindgen.diff @@ -0,0 +1,67 @@ +diff --git a/src/ir/item.rs b/src/ir/item.rs +index 7f3afefb..90d15e96 100644 +--- a/src/ir/item.rs ++++ b/src/ir/item.rs +@@ -148,7 +148,11 @@ impl<'a, 'b> Iterator for ItemAncestorsIter<'a, 'b> + impl AsTemplateParam for ItemId { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + ctx.resolve_item(*self).as_template_param(ctx, &()) + } + } +@@ -156,7 +160,11 @@ impl AsTemplateParam for ItemId { + impl AsTemplateParam for Item { + type Extra = (); + +- fn as_template_param(&self, ctx: &BindgenContext, _: &()) -> Option { ++ fn as_template_param( ++ &self, ++ ctx: &BindgenContext, ++ _: &(), ++ ) -> Option { + self.kind.as_template_param(ctx, self) + } + } +diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs +index 762a3e2d..b9c9dd4e 100644 +--- a/src/ir/traversal.rs ++++ b/src/ir/traversal.rs +@@ -9,6 +9,8 @@ use std::collections::{BTreeMap, VecDeque}; + /// + /// from --> to + /// ++/// Random content to generate a diff. ++/// + /// The `from` is left implicit: it is the concrete `Trace` implementer which + /// yielded this outgoing edge. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +@@ -33,7 +35,9 @@ impl Into for Edge { + } + } + +-/// The kind of edge reference. This is useful when we wish to only consider ++/// The kind of edge reference. ++/// ++/// This is useful when we wish to only consider + /// certain kinds of edges for a particular traversal or analysis. + #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum EdgeKind { +diff --git a/tests/headers/anon_enum.hpp b/tests/headers/anon_enum.hpp +index 1961fe6c..34759df3 100644 +--- a/tests/headers/anon_enum.hpp ++++ b/tests/headers/anon_enum.hpp +@@ -1,7 +1,7 @@ + struct Test { + int foo; + float bar; +- enum { T_NONE }; ++ enum { T_NONE, T_SOME }; + }; + + typedef enum { diff --git a/git-rustfmt/main.rs b/git-rustfmt/main.rs new file mode 100644 index 00000000000..0042ff353a7 --- /dev/null +++ b/git-rustfmt/main.rs @@ -0,0 +1,206 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate env_logger; +extern crate getopts; +#[macro_use] +extern crate log; +extern crate rustfmt_nightly as rustfmt; + +use std::env; +use std::io::stdout; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::str::FromStr; + +use getopts::{Matches, Options}; + +use rustfmt::{load_config, CliOptions, Input, Session}; + +fn prune_files(files: Vec<&str>) -> Vec<&str> { + let prefixes: Vec<_> = files + .iter() + .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs")) + .map(|f| &f[..f.len() - 6]) + .collect(); + + let mut pruned_prefixes = vec![]; + for p1 in prefixes { + if p1.starts_with("src/bin/") || pruned_prefixes.iter().all(|p2| !p1.starts_with(p2)) { + pruned_prefixes.push(p1); + } + } + debug!("prefixes: {:?}", pruned_prefixes); + + files + .into_iter() + .filter(|f| { + if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") { + return true; + } + pruned_prefixes.iter().all(|pp| !f.starts_with(pp)) + }).collect() +} + +fn git_diff(commits: &str) -> String { + let mut cmd = Command::new("git"); + cmd.arg("diff"); + if commits != "0" { + cmd.arg(format!("HEAD~{}", commits)); + } + let output = cmd.output().expect("Couldn't execute `git diff`"); + String::from_utf8_lossy(&output.stdout).into_owned() +} + +fn get_files(input: &str) -> Vec<&str> { + input + .lines() + .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs")) + .map(|line| &line[6..]) + .collect() +} + +fn fmt_files(files: &[&str]) -> i32 { + let (config, _) = + load_config::(Some(Path::new(".")), None).expect("couldn't load config"); + + let mut exit_code = 0; + let mut out = stdout(); + let mut session = Session::new(config, Some(&mut out)); + for file in files { + let report = session.format(Input::File(PathBuf::from(file))).unwrap(); + if report.has_warnings() { + eprintln!("{}", report); + } + if !session.has_no_errors() { + exit_code = 1; + } + } + exit_code +} + +struct NullOptions; + +impl CliOptions for NullOptions { + fn apply_to(self, _: &mut rustfmt::Config) { + unreachable!(); + } + fn config_path(&self) -> Option<&Path> { + unreachable!(); + } +} + +fn uncommitted_files() -> Vec { + let mut cmd = Command::new("git"); + cmd.arg("ls-files"); + cmd.arg("--others"); + cmd.arg("--modified"); + cmd.arg("--exclude-standard"); + let output = cmd.output().expect("Couldn't execute Git"); + let stdout = String::from_utf8_lossy(&output.stdout); + stdout + .lines() + .filter(|s| s.ends_with(".rs")) + .map(|s| s.to_owned()) + .collect() +} + +fn check_uncommitted() { + let uncommitted = uncommitted_files(); + debug!("uncommitted files: {:?}", uncommitted); + if !uncommitted.is_empty() { + println!("Found untracked changes:"); + for f in &uncommitted { + println!(" {}", f); + } + println!("Commit your work, or run with `-u`."); + println!("Exiting."); + std::process::exit(1); + } +} + +fn make_opts() -> Options { + let mut opts = Options::new(); + opts.optflag("h", "help", "show this message"); + opts.optflag("c", "check", "check only, don't format (unimplemented)"); + opts.optflag("u", "uncommitted", "format uncommitted files"); + opts +} + +struct Config { + commits: String, + uncommitted: bool, + check: bool, +} + +impl Config { + fn from_args(matches: &Matches, opts: &Options) -> Config { + // `--help` display help message and quit + if matches.opt_present("h") { + let message = format!( + "\nusage: {} [options]\n\n\ + commits: number of commits to format, default: 1", + env::args_os().next().unwrap().to_string_lossy() + ); + println!("{}", opts.usage(&message)); + std::process::exit(0); + } + + let mut config = Config { + commits: "1".to_owned(), + uncommitted: false, + check: false, + }; + + if matches.opt_present("c") { + config.check = true; + unimplemented!(); + } + + if matches.opt_present("u") { + config.uncommitted = true; + } + + if matches.free.len() > 1 { + panic!("unknown arguments, use `-h` for usage"); + } + if matches.free.len() == 1 { + let commits = matches.free[0].trim(); + if u32::from_str(commits).is_err() { + panic!("Couldn't parse number of commits"); + } + config.commits = commits.to_owned(); + } + + config + } +} + +fn main() { + env_logger::init(); + + let opts = make_opts(); + let matches = opts + .parse(env::args().skip(1)) + .expect("Couldn't parse command line"); + let config = Config::from_args(&matches, &opts); + + if !config.uncommitted { + check_uncommitted(); + } + + let stdout = git_diff(&config.commits); + let files = get_files(&stdout); + debug!("files: {:?}", files); + let files = prune_files(files); + debug!("pruned files: {:?}", files); + let exit_code = fmt_files(&files); + std::process::exit(exit_code); +} diff --git a/src/patterns.rs b/src/patterns.rs index 90725972bd5..d5c4802904b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -336,29 +336,28 @@ fn rewrite_tuple_pat( )); pat_vec.insert(pos, dotdot); } - if pat_vec.is_empty() { return Some(format!("{}()", path_str.unwrap_or_default())); } - let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); - let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 - { - let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; - let sp = pat_vec[new_item_count - 1].span(); - let snippet = context.snippet(sp); - let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); - ( - &pat_vec[..new_item_count], - mk_sp(span.lo(), lo + BytePos(1)), - ) - } else { - (&pat_vec[..], span) - }; + let (pat_vec, span, condensed) = + if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 { + let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; + let sp = pat_vec[new_item_count - 1].span(); + let snippet = context.snippet(sp); + let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + ( + &pat_vec[..new_item_count], + mk_sp(span.lo(), lo + BytePos(1)), + true, + ) + } else { + (&pat_vec[..], span, false) + }; // add comma if `(x,)` - let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none(); + let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none() && !condensed; let path_str = path_str.unwrap_or_default(); let pat_ref_vec = pat_vec.iter().collect::>(); diff --git a/test/mod.rs b/test/mod.rs new file mode 100644 index 00000000000..8b2358f1ada --- /dev/null +++ b/test/mod.rs @@ -0,0 +1,964 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate assert_cli; + +use std::collections::{HashMap, HashSet}; +use std::env; +use std::fs; +use std::io::{self, BufRead, BufReader, Read, Write}; +use std::iter::{Enumerate, Peekable}; +use std::mem; +use std::path::{Path, PathBuf}; +use std::str::Chars; + +use config::{Color, Config, EmitMode, FileName, ReportTactic}; +use formatting::{ModifiedChunk, SourceFile}; +use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; +use source_file; +use {FormatReport, Input, Session}; + +const DIFF_CONTEXT_SIZE: usize = 3; +const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; + +// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the +// given path. The `recursive` argument controls if files from subdirectories +// are also returned. +fn get_test_files(path: &Path, recursive: bool) -> Vec { + let mut files = vec![]; + if path.is_dir() { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read directory {}", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get DirEntry"); + let path = entry.path(); + if path.is_dir() && recursive { + files.append(&mut get_test_files(&path, recursive)); + } else if path.extension().map_or(false, |f| f == "rs") { + files.push(path); + } + } + } + files +} + +fn verify_config_used(path: &Path, config_name: &str) { + for entry in fs::read_dir(path).expect(&format!( + "Couldn't read {} directory", + path.to_str().unwrap() + )) { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.extension().map_or(false, |f| f == "rs") { + // check if "// rustfmt-:" appears in the file. + let filebuf = BufReader::new( + fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), + ); + assert!( + filebuf + .lines() + .map(|l| l.unwrap()) + .take_while(|l| l.starts_with("//")) + .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), + format!( + "config option file {} does not contain expected config name", + path.display() + ) + ); + } + } +} + +#[test] +fn verify_config_test_names() { + for path in &[ + Path::new("tests/source/configs"), + Path::new("tests/target/configs"), + ] { + for entry in fs::read_dir(path).expect("Couldn't read configs directory") { + let entry = entry.expect("Couldn't get directory entry"); + let path = entry.path(); + if path.is_dir() { + let config_name = path.file_name().unwrap().to_str().unwrap(); + + // Make sure that config name is used in the files in the directory. + verify_config_used(&path, config_name); + } + } + } +} + +// This writes to the terminal using the same approach (via term::stdout or +// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing +// using only one or the other will cause the output order to differ when +// `print_diff` selects the approach not used. +fn write_message(msg: &str) { + let mut writer = OutputWriter::new(Color::Auto); + writer.writeln(&format!("{}", msg), None); +} + +// Integration tests. The files in the tests/source are formatted and compared +// to their equivalent in tests/target. The target file and config can be +// overridden by annotations in the source file. The input and output must match +// exactly. +#[test] +fn system_tests() { + // Get all files in the tests/source directory. + let files = get_test_files(Path::new("tests/source"), true); + let (_reports, count, fails) = check_files(files, None); + + // Display results. + println!("Ran {} system tests.", count); + assert_eq!(fails, 0, "{} system tests failed", fails); +} + +// Do the same for tests/coverage-source directory +// the only difference is the coverage mode +#[test] +fn coverage_tests() { + let files = get_test_files(Path::new("tests/coverage/source"), true); + let (_reports, count, fails) = check_files(files, None); + + println!("Ran {} tests in coverage mode.", count); + assert_eq!(fails, 0, "{} tests failed", fails); +} + +#[test] +fn checkstyle_test() { + let filename = "tests/writemode/source/fn-single-line.rs"; + let expected_filename = "tests/writemode/target/checkstyle.xml"; + assert_output(Path::new(filename), Path::new(expected_filename)); +} + +#[test] +fn modified_test() { + use std::io::BufRead; + + // Test "modified" output + let filename = "tests/writemode/source/modified.rs"; + let mut data = Vec::new(); + let mut config = Config::default(); + config.set().emit_mode(::config::EmitMode::ModifiedLines); + + { + let mut session = Session::new(config, Some(&mut data)); + session.format(Input::File(filename.into())).unwrap(); + } + + let mut lines = data.lines(); + let mut chunks = Vec::new(); + while let Some(Ok(header)) = lines.next() { + // Parse the header line + let values: Vec<_> = header + .split(' ') + .map(|s| s.parse::().unwrap()) + .collect(); + assert_eq!(values.len(), 3); + let line_number_orig = values[0]; + let lines_removed = values[1]; + let num_added = values[2]; + let mut added_lines = Vec::new(); + for _ in 0..num_added { + added_lines.push(lines.next().unwrap().unwrap()); + } + chunks.push(ModifiedChunk { + line_number_orig, + lines_removed, + lines: added_lines, + }); + } + + assert_eq!( + chunks, + vec![ + ModifiedChunk { + line_number_orig: 4, + lines_removed: 4, + lines: vec!["fn blah() {}".into()], + }, + ModifiedChunk { + line_number_orig: 9, + lines_removed: 6, + lines: vec!["#[cfg(a, b)]".into(), "fn main() {}".into()], + }, + ], + ); +} + +// Helper function for comparing the results of rustfmt +// to a known output file generated by one of the write modes. +fn assert_output(source: &Path, expected_filename: &Path) { + let config = read_config(source); + let (_, source_file, _) = format_file(source, config.clone()); + + // Populate output by writing to a vec. + let mut out = vec![]; + let _ = source_file::write_all_files(&source_file, &mut out, &config); + let output = String::from_utf8(out).unwrap(); + + let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); + let mut expected_text = String::new(); + expected_file + .read_to_string(&mut expected_text) + .expect("Failed reading target"); + + let compare = make_diff(&expected_text, &output, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + let mut failures = HashMap::new(); + failures.insert(source.to_owned(), compare); + print_mismatches_default_message(failures); + assert!(false, "Text does not match expected output"); + } +} + +// Idempotence tests. Files in tests/target are checked to be unaltered by +// rustfmt. +#[test] +fn idempotence_tests() { + match option_env!("CFG_RELEASE_CHANNEL") { + None | Some("nightly") => {} + _ => return, // these tests require nightly + } + // Get all files in the tests/target directory. + let files = get_test_files(Path::new("tests/target"), true); + let (_reports, count, fails) = check_files(files, None); + + // Display results. + println!("Ran {} idempotent tests.", count); + assert_eq!(fails, 0, "{} idempotent tests failed", fails); +} + +// Run rustfmt on itself. This operation must be idempotent. We also check that +// no warnings are emitted. +#[test] +fn self_tests() { + let mut files = get_test_files(Path::new("tests"), false); + let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; + for dir in bin_directories { + let mut path = PathBuf::from("src"); + path.push(dir); + path.push("main.rs"); + files.push(path); + } + files.push(PathBuf::from("src/lib.rs")); + + let (reports, count, fails) = check_files(files, Some(PathBuf::from("rustfmt.toml"))); + let mut warnings = 0; + + // Display results. + println!("Ran {} self tests.", count); + assert_eq!(fails, 0, "{} self tests failed", fails); + + for format_report in reports { + println!("{}", format_report); + warnings += format_report.warning_count(); + } + + assert_eq!( + warnings, 0, + "Rustfmt's code generated {} warnings", + warnings + ); +} + +#[test] +fn stdin_formatting_smoke_test() { + let input = Input::Text("fn main () {}".to_owned()); + let mut config = Config::default(); + config.set().emit_mode(EmitMode::Stdout); + let mut buf: Vec = vec![]; + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + assert!(session.has_no_errors()); + } + //eprintln!("{:?}", ); + #[cfg(not(windows))] + assert_eq!(buf, "fn main() {}\n".as_bytes()); + #[cfg(windows)] + assert_eq!(buf, "fn main() {}\r\n".as_bytes()); +} + +// FIXME(#1990) restore this test +// #[test] +// fn stdin_disable_all_formatting_test() { +// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); +// let mut child = Command::new("./target/debug/rustfmt") +// .stdin(Stdio::piped()) +// .stdout(Stdio::piped()) +// .arg("--config-path=./tests/config/disable_all_formatting.toml") +// .spawn() +// .expect("failed to execute child"); + +// { +// let stdin = child.stdin.as_mut().expect("failed to get stdin"); +// stdin +// .write_all(input.as_bytes()) +// .expect("failed to write stdin"); +// } +// let output = child.wait_with_output().expect("failed to wait on child"); +// assert!(output.status.success()); +// assert!(output.stderr.is_empty()); +// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); +// } + +#[test] +fn format_lines_errors_are_reported() { + let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); + let input = Input::Text(format!("fn {}() {{}}", long_identifier)); + let mut config = Config::default(); + config.set().error_on_line_overflow(true); + let mut session = Session::::new(config, None); + session.format(input).unwrap(); + assert!(session.has_formatting_errors()); +} + +#[test] +fn format_lines_errors_are_reported_with_tabs() { + let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); + let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); + let mut config = Config::default(); + config.set().error_on_line_overflow(true); + config.set().hard_tabs(true); + let mut session = Session::::new(config, None); + session.format(input).unwrap(); + assert!(session.has_formatting_errors()); +} + +// For each file, run rustfmt and collect the output. +// Returns the number of files checked and the number of failures. +fn check_files(files: Vec, opt_config: Option) -> (Vec, u32, u32) { + let mut count = 0; + let mut fails = 0; + let mut reports = vec![]; + + for file_name in files { + debug!("Testing '{}'...", file_name.display()); + + match idempotent_check(&file_name, &opt_config) { + Ok(ref report) if report.has_warnings() => { + print!("{}", report); + fails += 1; + } + Ok(report) => reports.push(report), + Err(err) => { + if let IdempotentCheckError::Mismatch(msg) = err { + print_mismatches_default_message(msg); + } + fails += 1; + } + } + + count += 1; + } + + (reports, count, fails) +} + +fn print_mismatches_default_message(result: HashMap>) { + for (file_name, diff) in result { + let mismatch_msg_formatter = + |line_num| format!("\nMismatch at {}:{}:", file_name.display(), line_num); + print_diff(diff, &mismatch_msg_formatter, &Default::default()); + } + + if let Some(mut t) = term::stdout() { + t.reset().unwrap_or(()); + } +} + +fn print_mismatches String>( + result: HashMap>, + mismatch_msg_formatter: T, +) { + for (_file_name, diff) in result { + print_diff(diff, &mismatch_msg_formatter, &Default::default()); + } + + if let Some(mut t) = term::stdout() { + t.reset().unwrap_or(()); + } +} + +fn read_config(filename: &Path) -> Config { + let sig_comments = read_significant_comments(filename); + // Look for a config file... If there is a 'config' property in the significant comments, use + // that. Otherwise, if there are no significant comments at all, look for a config file with + // the same name as the test file. + let mut config = if !sig_comments.is_empty() { + get_config(sig_comments.get("config").map(Path::new)) + } else { + get_config(filename.with_extension("toml").file_name().map(Path::new)) + }; + + for (key, val) in &sig_comments { + if key != "target" && key != "config" { + config.override_value(key, val); + if config.is_default(key) { + warn!("Default value {} used explicitly for {}", val, key); + } + } + } + + // Don't generate warnings for to-do items. + config.set().report_todo(ReportTactic::Never); + + config +} + +fn format_file>(filepath: P, config: Config) -> (bool, SourceFile, FormatReport) { + let filepath = filepath.into(); + let input = Input::File(filepath); + let mut session = Session::::new(config, None); + let result = session.format(input).unwrap(); + let parsing_errors = session.has_parsing_errors(); + let mut source_file = SourceFile::new(); + mem::swap(&mut session.source_file, &mut source_file); + (parsing_errors, source_file, result) +} + +enum IdempotentCheckError { + Mismatch(HashMap>), + Parse, +} + +fn idempotent_check( + filename: &PathBuf, + opt_config: &Option, +) -> Result { + let sig_comments = read_significant_comments(filename); + let config = if let Some(ref config_file_path) = opt_config { + Config::from_toml_path(config_file_path).expect("rustfmt.toml not found") + } else { + read_config(filename) + }; + let (parsing_errors, source_file, format_report) = format_file(filename, config); + if parsing_errors { + return Err(IdempotentCheckError::Parse); + } + + let mut write_result = HashMap::new(); + for (filename, text) in source_file { + if let FileName::Real(ref filename) = filename { + write_result.insert(filename.to_owned(), text); + } + } + + let target = sig_comments.get("target").map(|x| &(*x)[..]); + + handle_result(write_result, target).map(|_| format_report) +} + +// Reads test config file using the supplied (optional) file name. If there's no file name or the +// file doesn't exist, just return the default config. Otherwise, the file must be read +// successfully. +fn get_config(config_file: Option<&Path>) -> Config { + let config_file_name = match config_file { + None => return Default::default(), + Some(file_name) => { + let mut full_path = PathBuf::from("tests/config/"); + full_path.push(file_name); + if !full_path.exists() { + return Default::default(); + }; + full_path + } + }; + + let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); + let mut def_config = String::new(); + def_config_file + .read_to_string(&mut def_config) + .expect("Couldn't read config"); + + Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml") +} + +// Reads significant comments of the form: // rustfmt-key: value +// into a hash map. +fn read_significant_comments(file_name: &Path) -> HashMap { + let file = + fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); + let reader = BufReader::new(file); + let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; + let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); + + // Matches lines containing significant comments or whitespace. + let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") + .expect("Failed creating pattern 2"); + + reader + .lines() + .map(|line| line.expect("Failed getting line")) + .take_while(|line| line_regex.is_match(line)) + .filter_map(|line| { + regex.captures_iter(&line).next().map(|capture| { + ( + capture + .get(1) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + capture + .get(2) + .expect("Couldn't unwrap capture") + .as_str() + .to_owned(), + ) + }) + }).collect() +} + +// Compare output to input. +// TODO: needs a better name, more explanation. +fn handle_result( + result: HashMap, + target: Option<&str>, +) -> Result<(), IdempotentCheckError> { + let mut failures = HashMap::new(); + + for (file_name, fmt_text) in result { + // If file is in tests/source, compare to file with same name in tests/target. + let target = get_target(&file_name, target); + let open_error = format!("Couldn't open target {:?}", &target); + let mut f = fs::File::open(&target).expect(&open_error); + + let mut text = String::new(); + let read_error = format!("Failed reading target {:?}", &target); + f.read_to_string(&mut text).expect(&read_error); + + // Ignore LF and CRLF difference for Windows. + if !string_eq_ignore_newline_repr(&fmt_text, &text) { + let diff = make_diff(&text, &fmt_text, DIFF_CONTEXT_SIZE); + assert!( + !diff.is_empty(), + "Empty diff? Maybe due to a missing a newline at the end of a file?" + ); + failures.insert(file_name, diff); + } + } + + if failures.is_empty() { + Ok(()) + } else { + Err(IdempotentCheckError::Mismatch(failures)) + } +} + +// Map source file paths to their target paths. +fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { + if let Some(n) = file_name + .components() + .position(|c| c.as_os_str() == "source") + { + let mut target_file_name = PathBuf::new(); + for (i, c) in file_name.components().enumerate() { + if i == n { + target_file_name.push("target"); + } else { + target_file_name.push(c.as_os_str()); + } + } + if let Some(replace_name) = target { + target_file_name.with_file_name(replace_name) + } else { + target_file_name + } + } else { + // This is either and idempotence check or a self check + file_name.to_owned() + } +} + +#[test] +fn rustfmt_diff_make_diff_tests() { + let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); + assert_eq!( + diff, + vec![Mismatch { + line_number: 1, + line_number_orig: 1, + lines: vec![ + DiffLine::Context("a".into()), + DiffLine::Resulting("b".into()), + DiffLine::Expected("e".into()), + DiffLine::Context("c".into()), + DiffLine::Context("d".into()), + ], + }] + ); +} + +#[test] +fn rustfmt_diff_no_diff_test() { + let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); + assert_eq!(diff, vec![]); +} + +// Compare strings without distinguishing between CRLF and LF +fn string_eq_ignore_newline_repr(left: &str, right: &str) -> bool { + let left = CharsIgnoreNewlineRepr(left.chars().peekable()); + let right = CharsIgnoreNewlineRepr(right.chars().peekable()); + left.eq(right) +} + +struct CharsIgnoreNewlineRepr<'a>(Peekable>); + +impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { + type Item = char; + + fn next(&mut self) -> Option { + self.0.next().map(|c| { + if c == '\r' { + if *self.0.peek().unwrap_or(&'\0') == '\n' { + self.0.next(); + '\n' + } else { + '\r' + } + } else { + c + } + }) + } +} + +#[test] +fn string_eq_ignore_newline_repr_test() { + assert!(string_eq_ignore_newline_repr("", "")); + assert!(!string_eq_ignore_newline_repr("", "abc")); + assert!(!string_eq_ignore_newline_repr("abc", "")); + assert!(string_eq_ignore_newline_repr("a\nb\nc\rd", "a\nb\r\nc\rd")); + assert!(string_eq_ignore_newline_repr("a\r\n\r\n\r\nb", "a\n\n\nb")); + assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); +} + +// This enum is used to represent one of three text features in Configurations.md: a block of code +// with its starting line number, the name of a rustfmt configuration option, or the value of a +// rustfmt configuration option. +enum ConfigurationSection { + CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) + ConfigName(String), + ConfigValue(String), +} + +impl ConfigurationSection { + fn get_section>( + file: &mut Enumerate, + ) -> Option { + lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = + regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = + regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) + .expect("Failed creating configuration value pattern"); + } + + loop { + match file.next() { + Some((i, line)) => { + if line.starts_with("```rust") { + // Get the lines of the code block. + let lines: Vec = file + .map(|(_i, l)| l) + .take_while(|l| !l.starts_with("```")) + .collect(); + let block = format!("{}\n", lines.join("\n")); + + // +1 to translate to one-based indexing + // +1 to get to first line of code (line after "```") + let start_line = (i + 2) as u32; + + return Some(ConfigurationSection::CodeBlock((block, start_line))); + } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); + } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); + } + } + None => return None, // reached the end of the file + } + } + } +} + +// This struct stores the information about code blocks in the configurations +// file, formats the code blocks, and prints formatting errors. +struct ConfigCodeBlock { + config_name: Option, + config_value: Option, + code_block: Option, + code_block_start: Option, +} + +impl ConfigCodeBlock { + fn new() -> ConfigCodeBlock { + ConfigCodeBlock { + config_name: None, + config_value: None, + code_block: None, + code_block_start: None, + } + } + + fn set_config_name(&mut self, name: Option) { + self.config_name = name; + self.config_value = None; + } + + fn set_config_value(&mut self, value: Option) { + self.config_value = value; + } + + fn set_code_block(&mut self, code_block: String, code_block_start: u32) { + self.code_block = Some(code_block); + self.code_block_start = Some(code_block_start); + } + + fn get_block_config(&self) -> Config { + let mut config = Config::default(); + if self.config_value.is_some() && self.config_value.is_some() { + config.override_value( + self.config_name.as_ref().unwrap(), + self.config_value.as_ref().unwrap(), + ); + } + config + } + + fn code_block_valid(&self) -> bool { + // We never expect to not have a code block. + assert!(self.code_block.is_some() && self.code_block_start.is_some()); + + // See if code block begins with #![rustfmt::skip]. + let fmt_skip = self + .code_block + .as_ref() + .unwrap() + .split('\n') + .nth(0) + .unwrap_or("") + == "#![rustfmt::skip]"; + + if self.config_name.is_none() && !fmt_skip { + write_message(&format!( + "No configuration name for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + if self.config_value.is_none() && !fmt_skip { + write_message(&format!( + "No configuration value for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + true + } + + fn has_parsing_errors(&self, session: &Session) -> bool { + if session.has_parsing_errors() { + write_message(&format!( + "\u{261d}\u{1f3fd} Cannot format {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return true; + } + + false + } + + fn print_diff(&self, compare: Vec) { + let mut mismatches = HashMap::new(); + mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); + print_mismatches(mismatches, |line_num| { + format!( + "\nMismatch at {}:{}:", + CONFIGURATIONS_FILE_NAME, + line_num + self.code_block_start.unwrap() - 1 + ) + }); + } + + fn formatted_has_diff(&self, text: &str) -> bool { + let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + self.print_diff(compare); + return true; + } + + false + } + + // Return a bool indicating if formatting this code block is an idempotent + // operation. This function also triggers printing any formatting failure + // messages. + fn formatted_is_idempotent(&self) -> bool { + // Verify that we have all of the expected information. + if !self.code_block_valid() { + return false; + } + + let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); + let mut config = self.get_block_config(); + config.set().emit_mode(EmitMode::Stdout); + let mut buf: Vec = vec![]; + + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + if self.has_parsing_errors(&session) { + return false; + } + } + + !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) + } + + // Extract a code block from the iterator. Behavior: + // - Rust code blocks are identifed by lines beginning with "```rust". + // - One explicit configuration setting is supported per code block. + // - Rust code blocks with no configuration setting are illegal and cause an + // assertion failure, unless the snippet begins with #![rustfmt::skip]. + // - Configuration names in Configurations.md must be in the form of + // "## `NAME`". + // - Configuration values in Configurations.md must be in the form of + // "#### `VALUE`". + fn extract>( + file: &mut Enumerate, + prev: Option<&ConfigCodeBlock>, + hash_set: &mut HashSet, + ) -> Option { + let mut code_block = ConfigCodeBlock::new(); + code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); + + loop { + match ConfigurationSection::get_section(file) { + Some(ConfigurationSection::CodeBlock((block, start_line))) => { + code_block.set_code_block(block, start_line); + break; + } + Some(ConfigurationSection::ConfigName(name)) => { + assert!( + Config::is_valid_name(&name), + "an unknown configuration option was found: {}", + name + ); + assert!( + hash_set.remove(&name), + "multiple configuration guides found for option {}", + name + ); + code_block.set_config_name(Some(name)); + } + Some(ConfigurationSection::ConfigValue(value)) => { + code_block.set_config_value(Some(value)); + } + None => return None, // end of file was reached + } + } + + Some(code_block) + } +} + +#[test] +fn configuration_snippet_tests() { + // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one + // entry for each Rust code block found. + fn get_code_blocks() -> Vec { + let mut file_iter = BufReader::new( + fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) + .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + ).lines() + .map(|l| l.unwrap()) + .enumerate(); + let mut code_blocks: Vec = Vec::new(); + let mut hash_set = Config::hash_set(); + + while let Some(cb) = + ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) + { + code_blocks.push(cb); + } + + for name in hash_set { + if !Config::is_hidden_option(&name) { + panic!("{} does not have a configuration guide", name); + } + } + + code_blocks + } + + let blocks = get_code_blocks(); + let failures = blocks + .iter() + .map(|b| b.formatted_is_idempotent()) + .fold(0, |acc, r| acc + (!r as u32)); + + // Display results. + println!("Ran {} configurations tests.", blocks.len()); + assert_eq!(failures, 0, "{} configurations tests failed", failures); +} + +struct TempFile { + path: PathBuf, +} + +fn make_temp_file(file_name: &'static str) -> TempFile { + use std::env::var; + use std::fs::File; + + // Used in the Rust build system. + let target_dir = var("RUSTFMT_TEST_DIR").unwrap_or_else(|_| ".".to_owned()); + let path = Path::new(&target_dir).join(file_name); + + let mut file = File::create(&path).expect("Couldn't create temp file"); + let content = "fn main() {}\n"; + file.write_all(content.as_bytes()) + .expect("Couldn't write temp file"); + TempFile { path } +} + +impl Drop for TempFile { + fn drop(&mut self) { + use std::fs::remove_file; + remove_file(&self.path).expect("Couldn't delete temp file"); + } +} + +fn rustfmt() -> PathBuf { + let mut me = env::current_exe().expect("failed to get current executable"); + me.pop(); // chop of the test name + me.pop(); // chop off `deps` + me.push("rustfmt"); + assert!( + me.is_file() || me.with_extension("exe").is_file(), + "no rustfmt bin, try running `cargo build` before testing" + ); + return me; +} + +#[test] +fn verify_check_works() { + let temp_file = make_temp_file("temp_check.rs"); + assert_cli::Assert::command(&[ + rustfmt().to_str().unwrap(), + "--check", + temp_file.path.to_str().unwrap(), + ]).succeeds() + .unwrap(); +} -- cgit 1.4.1-3-g733a5 From 20075306f7f18050744b851b82a72e2bd12fc9d1 Mon Sep 17 00:00:00 2001 From: crw5996 Date: Mon, 27 Aug 2018 14:31:43 -0400 Subject: Fixed Issues brought up in PR --- src/imports.rs | 20 +++++++++++++++++--- tests/source/issue-2927-2.rs | 7 +++++++ tests/source/issue-2927.rs | 7 +++++++ tests/target/issue-2927-2.rs | 7 +++++++ tests/target/issue-2927.rs | 7 +++++++ 5 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/source/issue-2927-2.rs create mode 100644 tests/source/issue-2927.rs create mode 100644 tests/target/issue-2927-2.rs create mode 100644 tests/target/issue-2927.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index b3408bf7bf2..4aee67759c1 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -15,7 +15,7 @@ use syntax::ast::{self, UseTreeKind}; use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; use comment::combine_strs_with_missing_comments; -use config::IndentStyle; +use config::{Edition, IndentStyle}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; @@ -144,6 +144,7 @@ impl UseSegment { fn from_path_segment( context: &RewriteContext, path_seg: &ast::PathSegment, + modsep: bool, ) -> Option { let name = rewrite_ident(context, path_seg.ident); if name.is_empty() || name == "{{root}}" { @@ -152,7 +153,10 @@ impl UseSegment { Some(match name { "self" => UseSegment::Slf(None), "super" => UseSegment::Super(None), - _ => UseSegment::Ident((*name).to_owned(), None), + _ => { + let mod_sep = if modsep { "::" } else { "" }; + UseSegment::Ident(format!("{}{}", mod_sep, name), None) + } }) } } @@ -313,8 +317,18 @@ impl UseTree { visibility, attrs, }; + + let leading_modsep = if context.config.edition() == Edition::Edition2018 { + if a.prefix.to_string().len() > 2 && a.prefix.to_string().starts_with("::") { + true + } else { + false + } + } else { + false + }; for p in &a.prefix.segments { - if let Some(use_segment) = UseSegment::from_path_segment(context, p) { + if let Some(use_segment) = UseSegment::from_path_segment(context, p, leading_modsep) { result.path.push(use_segment); } } diff --git a/tests/source/issue-2927-2.rs b/tests/source/issue-2927-2.rs new file mode 100644 index 00000000000..0a8969c4837 --- /dev/null +++ b/tests/source/issue-2927-2.rs @@ -0,0 +1,7 @@ +// rustfmt-edition: Edition2015 +#![feature(rust_2018_preview, uniform_paths)] +use futures::prelude::*; +use http_03::cli::Cli; +use hyper::{service::service_fn_ok, Body, Response, Server}; +use ::log::{error, info, log}; +use structopt::StructOpt; diff --git a/tests/source/issue-2927.rs b/tests/source/issue-2927.rs new file mode 100644 index 00000000000..69871b48496 --- /dev/null +++ b/tests/source/issue-2927.rs @@ -0,0 +1,7 @@ +// rustfmt-edition: Edition2018 +#![feature(rust_2018_preview, uniform_paths)] +use futures::prelude::*; +use http_03::cli::Cli; +use hyper::{service::service_fn_ok, Body, Response, Server}; +use ::log::{error, info, log}; +use structopt::StructOpt; diff --git a/tests/target/issue-2927-2.rs b/tests/target/issue-2927-2.rs new file mode 100644 index 00000000000..c9fdcdea239 --- /dev/null +++ b/tests/target/issue-2927-2.rs @@ -0,0 +1,7 @@ +// rustfmt-edition: Edition2015 +#![feature(rust_2018_preview, uniform_paths)] +use futures::prelude::*; +use http_03::cli::Cli; +use hyper::{service::service_fn_ok, Body, Response, Server}; +use log::{error, info, log}; +use structopt::StructOpt; diff --git a/tests/target/issue-2927.rs b/tests/target/issue-2927.rs new file mode 100644 index 00000000000..1aa34f01741 --- /dev/null +++ b/tests/target/issue-2927.rs @@ -0,0 +1,7 @@ +// rustfmt-edition: Edition2018 +#![feature(rust_2018_preview, uniform_paths)] +use ::log::{error, info, log}; +use futures::prelude::*; +use http_03::cli::Cli; +use hyper::{service::service_fn_ok, Body, Response, Server}; +use structopt::StructOpt; -- cgit 1.4.1-3-g733a5 From 18cd0c4986b2f262c6dedf193b3b36c2d0b7028d Mon Sep 17 00:00:00 2001 From: crw5996 Date: Mon, 27 Aug 2018 23:08:37 -0400 Subject: Fixed overly complicated code as requested in the code review --- src/imports.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 4aee67759c1..db00c45b9d9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -318,15 +318,10 @@ impl UseTree { attrs, }; - let leading_modsep = if context.config.edition() == Edition::Edition2018 { - if a.prefix.to_string().len() > 2 && a.prefix.to_string().starts_with("::") { - true - } else { - false - } - } else { - false - }; + let leading_modsep = context.config.edition() == Edition::Edition2018 + && a.prefix.to_string().len() > 2 + && a.prefix.to_string().starts_with("::"); + for p in &a.prefix.segments { if let Some(use_segment) = UseSegment::from_path_segment(context, p, leading_modsep) { result.path.push(use_segment); -- cgit 1.4.1-3-g733a5 From df72570b58824e9a2bc9ec48c36e0c708412797b Mon Sep 17 00:00:00 2001 From: Maximilian Roos Date: Tue, 28 Aug 2018 00:33:51 -0400 Subject: set of clippy changes --- src/comment.rs | 18 ++++++++---------- src/config/config_type.rs | 4 ++-- src/config/lists.rs | 8 ++++---- src/lists.rs | 4 ++-- src/matches.rs | 2 +- src/overflow.rs | 2 +- src/types.rs | 2 +- 7 files changed, 19 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 78d087ce7a4..e3c6201d3c4 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -525,7 +525,7 @@ fn rewrite_comment_inner( const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; -fn hide_sharp_behind_comment<'a>(s: &'a str) -> Cow<'a, str> { +fn hide_sharp_behind_comment(s: &str) -> Cow { if s.trim_left().starts_with("# ") { Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s)) } else { @@ -823,8 +823,8 @@ pub enum FullCodeCharKind { } impl FullCodeCharKind { - pub fn is_comment(&self) -> bool { - match *self { + pub fn is_comment(self) -> bool { + match self { FullCodeCharKind::StartComment | FullCodeCharKind::InComment | FullCodeCharKind::EndComment => true, @@ -832,11 +832,11 @@ impl FullCodeCharKind { } } - pub fn is_string(&self) -> bool { - *self == FullCodeCharKind::InString + pub fn is_string(self) -> bool { + self == FullCodeCharKind::InString } - fn to_codecharkind(&self) -> CodeCharKind { + fn to_codecharkind(self) -> CodeCharKind { if self.is_comment() { CodeCharKind::Comment } else { @@ -987,9 +987,7 @@ impl<'a> Iterator for LineClasses<'a> { type Item = (FullCodeCharKind, String); fn next(&mut self) -> Option { - if self.base.peek().is_none() { - return None; - } + self.base.peek()?; let mut line = String::new(); @@ -1174,7 +1172,7 @@ pub fn filter_normal_code(code: &str) -> String { } _ => (), }); - if !code.ends_with("\n") && buffer.ends_with("\n") { + if !code.ends_with('\n') && buffer.ends_with('\n') { buffer.pop(); } buffer diff --git a/src/config/config_type.rs b/src/config/config_type.rs index aea19b34375..bf9cd859732 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -175,11 +175,11 @@ macro_rules! create_config { } )+ - pub fn set<'a>(&'a mut self) -> ConfigSetter<'a> { + pub fn set(&mut self) -> ConfigSetter { ConfigSetter(self) } - pub fn was_set<'a>(&'a self) -> ConfigWasSet<'a> { + pub fn was_set(&self) -> ConfigWasSet { ConfigWasSet(self) } diff --git a/src/config/lists.rs b/src/config/lists.rs index 04406e8d566..61496e21642 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -80,12 +80,12 @@ pub enum SeparatorPlace { impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); impl SeparatorPlace { - pub fn is_front(&self) -> bool { - *self == SeparatorPlace::Front + pub fn is_front(self) -> bool { + self == SeparatorPlace::Front } - pub fn is_back(&self) -> bool { - *self == SeparatorPlace::Back + pub fn is_back(self) -> bool { + self == SeparatorPlace::Back } pub fn from_tactic( diff --git a/src/lists.rs b/src/lists.rs index 9b65fdbd1da..8867c6f2283 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -209,8 +209,8 @@ pub enum Separator { } impl Separator { - pub fn len(&self) -> usize { - match *self { + pub fn len(self) -> usize { + match self { // 2 = `, ` Separator::Comma => 2, // 3 = ` | ` diff --git a/src/matches.rs b/src/matches.rs index 231112edb1e..931aaff1765 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -289,7 +289,7 @@ fn rewrite_match_pattern( guard, shape, trimmed_last_line_width(&pats_str), - pats_str.contains("\n"), + pats_str.contains('\n'), )?; Some(format!("{}{}", pats_str, guard_str)) diff --git a/src/overflow.rs b/src/overflow.rs index 1a223cf3ca6..9a9c9831f40 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -223,7 +223,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { // 1 = "(" let combine_arg_with_callee = self.items.len() == 1 && self.items[0].to_expr().is_some() - && self.ident.len() + 1 <= self.context.config.tab_spaces(); + && self.ident.len() < self.context.config.tab_spaces(); let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, self.items); // Replace the last item with its first line to see if it fits with diff --git a/src/types.rs b/src/types.rs index dd7f60a60b4..3ab639a1ac3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -520,7 +520,7 @@ impl Rewrite for ast::GenericBounds { } let span = mk_sp(self.get(0)?.span().lo(), self.last()?.span().hi()); - let has_paren = context.snippet(span).starts_with("("); + let has_paren = context.snippet(span).starts_with('('); let bounds_shape = if has_paren { shape.offset_left(1)?.sub_width(1)? } else { -- cgit 1.4.1-3-g733a5 From 7d60e3a1ad6551afd013b19f59c308ad2dbaa266 Mon Sep 17 00:00:00 2001 From: Maximilian Roos Date: Tue, 28 Aug 2018 21:57:08 -0400 Subject: more clippy --- src/overflow.rs | 2 +- src/visitor.rs | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index 9a9c9831f40..674eb14b677 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -291,7 +291,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => { list_items[self.items.len() - 1].item = placeholder; } - _ if self.items.len() >= 1 => { + _ if !self.items.is_empty() => { list_items[self.items.len() - 1].item = self .items .last() diff --git a/src/visitor.rs b/src/visitor.rs index 7f557747778..4373fc048ea 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -626,20 +626,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ErrorKind::DeprecatedAttr, )], ); - } else if attr.path.segments[0].ident.to_string() == "rustfmt" { - if attr.path.segments.len() == 1 - || attr.path.segments[1].ident.to_string() != "skip" - { - let file_name = self.source_map.span_to_filename(attr.span).into(); - self.report.append( - file_name, - vec![FormattingError::from_span( - &attr.span, - &self.source_map, - ErrorKind::BadAttr, - )], - ); - } + } else if attr.path.segments[0].ident.to_string() == "rustfmt" + && (attr.path.segments.len() == 1 + || attr.path.segments[1].ident.to_string() != "skip") + { + let file_name = self.source_map.span_to_filename(attr.span).into(); + self.report.append( + file_name, + vec![FormattingError::from_span( + &attr.span, + &self.source_map, + ErrorKind::BadAttr, + )], + ); } } if contains_skip(attrs) { -- cgit 1.4.1-3-g733a5 From ad903e08fdaac65a7567c952a1191a14413ec00d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 30 Aug 2018 23:39:39 +0900 Subject: Keep formatting fn even if there is an unformattable argument --- src/items.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index ff635137e42..7f8980dd150 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2232,8 +2232,10 @@ fn rewrite_args( ) -> Option { let mut arg_item_strs = args .iter() - .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))) - .collect::>>()?; + .map(|arg| { + arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) + .unwrap_or_else(|| context.snippet(arg.span()).to_owned()) + }).collect::>(); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked -- cgit 1.4.1-3-g733a5 From 309be479b2e9a4a3474f8ebb7ae0a4b2b9286812 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 31 Aug 2018 10:37:46 +0900 Subject: Handle raw string literals in CharClasses --- src/comment.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e3c6201d3c4..d6fcc288379 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -785,6 +785,9 @@ enum CharClassesStatus { Normal, LitString, LitStringEscape, + LitRawString(u32), + RawStringPrefix(u32), + RawStringSuffix(u32), LitChar, LitCharEscape, // The u32 is the nesting deepness of the comment @@ -858,6 +861,20 @@ where } } +fn is_raw_string_suffix(iter: &mut MultiPeek, count: u32) -> bool +where + T: Iterator, + T::Item: RichChar, +{ + for _ in 0..count { + match iter.peek() { + Some(c) if c.get_char() == '#' => continue, + _ => return false, + } + } + true +} + impl Iterator for CharClasses where T: Iterator, @@ -870,6 +887,40 @@ where let chr = item.get_char(); let mut char_kind = FullCodeCharKind::Normal; self.status = match self.status { + CharClassesStatus::LitRawString(sharps) => { + char_kind = FullCodeCharKind::InString; + match chr { + '"' => { + if is_raw_string_suffix(&mut self.base, sharps) { + CharClassesStatus::RawStringSuffix(sharps) + } else { + CharClassesStatus::LitRawString(sharps) + } + } + _ => CharClassesStatus::LitRawString(sharps), + } + } + CharClassesStatus::RawStringPrefix(sharps) => { + char_kind = FullCodeCharKind::InString; + match chr { + '#' => CharClassesStatus::RawStringPrefix(sharps + 1), + '"' => CharClassesStatus::LitRawString(sharps), + _ => CharClassesStatus::Normal, // Unreachable. + } + } + CharClassesStatus::RawStringSuffix(sharps) => { + match chr { + '#' => { + if sharps == 1 { + CharClassesStatus::Normal + } else { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::RawStringSuffix(sharps - 1) + } + } + _ => CharClassesStatus::Normal, // Unreachable + } + } CharClassesStatus::LitString => match chr { '"' => CharClassesStatus::Normal, '\\' => { @@ -892,6 +943,17 @@ where }, CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, CharClassesStatus::Normal => match chr { + 'r' => match self.base.peek().map(|c| c.get_char()) { + Some('#') => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::RawStringPrefix(0) + } + Some('"') => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::LitString + } + _ => CharClassesStatus::Normal, + }, '"' => { char_kind = FullCodeCharKind::InString; CharClassesStatus::LitString -- cgit 1.4.1-3-g733a5 From 67480422b98fce60e2f34b924cb8e85e1fb0a37f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 31 Aug 2018 10:49:39 +0900 Subject: Handle raw string literal without any sharps --- src/comment.rs | 11 +++++------ tests/source/macro_rules.rs | 9 +++++++++ tests/target/macro_rules.rs | 11 +++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d6fcc288379..356cef30a8f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -891,7 +891,10 @@ where char_kind = FullCodeCharKind::InString; match chr { '"' => { - if is_raw_string_suffix(&mut self.base, sharps) { + if sharps == 0 { + char_kind = FullCodeCharKind::Normal; + CharClassesStatus::Normal + } else if is_raw_string_suffix(&mut self.base, sharps) { CharClassesStatus::RawStringSuffix(sharps) } else { CharClassesStatus::LitRawString(sharps) @@ -944,14 +947,10 @@ where CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, CharClassesStatus::Normal => match chr { 'r' => match self.base.peek().map(|c| c.get_char()) { - Some('#') => { + Some('#') | Some('"') => { char_kind = FullCodeCharKind::InString; CharClassesStatus::RawStringPrefix(0) } - Some('"') => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString - } _ => CharClassesStatus::Normal, }, '"' => { diff --git a/tests/source/macro_rules.rs b/tests/source/macro_rules.rs index 41b1496f065..5aaca0c83fa 100644 --- a/tests/source/macro_rules.rs +++ b/tests/source/macro_rules.rs @@ -290,3 +290,12 @@ macro_rules! template { "##, $name) } } + +macro_rules! template { + () => { + format_args!(r" +// + +") + } +} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index d3d4d0eba96..97444aef404 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -347,3 +347,14 @@ macro_rules! template { ) }; } + +macro_rules! template { + () => { + format_args!( + r" +// + +" + ) + }; +} -- cgit 1.4.1-3-g733a5 From eec74360dce0be790b537ab41239bd9b876741d2 Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Fri, 31 Aug 2018 00:04:23 -0700 Subject: Accept 2015 and 2018 instead of Edition2015 and Edition2018 for edition option --- .travis.yml | 2 +- Configurations.md | 6 +++--- README.md | 2 +- rustfmt.toml | 2 +- src/config/options.rs | 45 ++++++++++++++++++++++++++++--------------- tests/source/async_block.rs | 2 +- tests/source/async_fn.rs | 2 +- tests/source/catch.rs | 2 +- tests/source/issue-2927-2.rs | 2 +- tests/source/issue-2927.rs | 2 +- tests/target/async_block.rs | 2 +- tests/target/async_closure.rs | 2 +- tests/target/async_fn.rs | 2 +- tests/target/catch.rs | 2 +- tests/target/issue-2927-2.rs | 2 +- tests/target/issue-2927.rs | 2 +- 16 files changed, 47 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/.travis.yml b/.travis.yml index 2d4dcf1c601..f5242b79d5c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ matrix: - env: INTEGRATION=stdsimd - env: INTEGRATION=tempdir allow_failures: - # Needs `edition = "Edition2018"` in rustfmt.toml + # Needs `edition = "2018"` in rustfmt.toml - env: INTEGRATION=chalk # Fails tests, don't know why - env: INTEGRATION=crater diff --git a/Configurations.md b/Configurations.md index ab91f11be04..ae8ea2b3c6d 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2176,8 +2176,8 @@ ignore = [ Specifies which edition is used by the parser. -- **Default value**: `Edition2015` -- **Possible values**: `Edition2015`, `Edition2018` +- **Default value**: `2015` +- **Possible values**: `2015`, `2018` - **Stable**: No ### Example @@ -2185,7 +2185,7 @@ Specifies which edition is used by the parser. If you want to format code that requires edition 2018, add the following to your config file: ```toml -edition = "Edition2018" +edition = "2018" ``` ## `emit_mode` diff --git a/README.md b/README.md index 37fdad5b975..8d8bfcc1e01 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ cargo +nightly fmt To format code that requires edition 2018, create a `rustfmt.toml` [configuration](#configuring-rustfmt) file containing: ```toml -edition = "Edition2018" +edition = "2018" ``` ## Limitations diff --git a/rustfmt.toml b/rustfmt.toml index 6abb5a9ef6d..94f74163652 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,3 @@ error_on_line_overflow = true error_on_unformatted = true -edition = "Edition2018" +edition = "2018" diff --git a/src/config/options.rs b/src/config/options.rs index d2a74f54677..ac80116e0d0 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -20,7 +20,15 @@ use std::path::{Path, PathBuf}; /// Macro for deriving implementations of Serialize/Deserialize for enums #[macro_export] macro_rules! impl_enum_serialize_and_deserialize { - ( $e:ident, $( $x:ident ),* ) => { + (@stringify $variant:ident) => ( + stringify!($variant) + ); + + (@stringify $_variant:ident: $value:expr) => ( + stringify!($value) + ); + + ( $e:ident, $( $variant:ident $(: $value:expr)* ),* ) => { impl ::serde::ser::Serialize for $e { fn serialize(&self, serializer: S) -> Result where S: ::serde::ser::Serializer @@ -31,7 +39,9 @@ macro_rules! impl_enum_serialize_and_deserialize { #[allow(unreachable_patterns)] match *self { $( - $e::$x => serializer.serialize_str(stringify!($x)), + $e::$variant => serializer.serialize_str( + impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + ), )* _ => { Err(S::Error::custom(format!("Cannot serialize {:?}", self))) @@ -59,11 +69,13 @@ macro_rules! impl_enum_serialize_and_deserialize { } let s = d.deserialize_string(StringOnly::(PhantomData))?; $( - if stringify!($x).eq_ignore_ascii_case(&s) { - return Ok($e::$x); + if impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + .eq_ignore_ascii_case(&s) { + return Ok($e::$variant); } )* - static ALLOWED: &'static[&str] = &[$(stringify!($x),)*]; + static ALLOWED: &'static[&str] = &[ + $(impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*),)*]; Err(D::Error::unknown_variant(&s, ALLOWED)) } } @@ -73,8 +85,9 @@ macro_rules! impl_enum_serialize_and_deserialize { fn from_str(s: &str) -> Result { $( - if stringify!($x).eq_ignore_ascii_case(s) { - return Ok($e::$x); + if impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + .eq_ignore_ascii_case(s) { + return Ok($e::$variant); } )* Err("Bad variant") @@ -85,7 +98,9 @@ macro_rules! impl_enum_serialize_and_deserialize { fn doc_hint() -> String { let mut variants = Vec::new(); $( - variants.push(stringify!($x)); + variants.push( + impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + ); )* format!("[{}]", variants.join("|")) } @@ -93,15 +108,15 @@ macro_rules! impl_enum_serialize_and_deserialize { }; } -macro_rules! configuration_option_enum{ - ($e:ident: $( $x:ident ),+ $(,)*) => { +macro_rules! configuration_option_enum { + ($e:ident: $( $name:ident $(: $value:expr)* ),+ $(,)*) => ( #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum $e { - $( $x ),+ + $( $name ),+ } - impl_enum_serialize_and_deserialize!($e, $( $x ),+); - } + impl_enum_serialize_and_deserialize!($e, $( $name $(: $value)* ),+); + ); } configuration_option_enum! { NewlineStyle: @@ -412,8 +427,8 @@ pub trait CliOptions { /// The edition of the compiler (RFC 2052) configuration_option_enum!{ Edition: - Edition2015, - Edition2018, + Edition2015: 2015, + Edition2018: 2018, } impl Edition { diff --git a/tests/source/async_block.rs b/tests/source/async_block.rs index 5e05e58c6c1..a7018316812 100644 --- a/tests/source/async_block.rs +++ b/tests/source/async_block.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 fn main() { let x = async { diff --git a/tests/source/async_fn.rs b/tests/source/async_fn.rs index cae9d5badaf..f77dc73acd9 100644 --- a/tests/source/async_fn.rs +++ b/tests/source/async_fn.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 async fn bar() -> Result<(), ()> { Ok(()) diff --git a/tests/source/catch.rs b/tests/source/catch.rs index 6674e7eebe4..541db1dc90c 100644 --- a/tests/source/catch.rs +++ b/tests/source/catch.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 #![feature(try_blocks)] fn main() { diff --git a/tests/source/issue-2927-2.rs b/tests/source/issue-2927-2.rs index 0a8969c4837..d87761fdc9c 100644 --- a/tests/source/issue-2927-2.rs +++ b/tests/source/issue-2927-2.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2015 +// rustfmt-edition: 2015 #![feature(rust_2018_preview, uniform_paths)] use futures::prelude::*; use http_03::cli::Cli; diff --git a/tests/source/issue-2927.rs b/tests/source/issue-2927.rs index 69871b48496..a7df32084f3 100644 --- a/tests/source/issue-2927.rs +++ b/tests/source/issue-2927.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 #![feature(rust_2018_preview, uniform_paths)] use futures::prelude::*; use http_03::cli::Cli; diff --git a/tests/target/async_block.rs b/tests/target/async_block.rs index 611c719e95f..5c1649373ad 100644 --- a/tests/target/async_block.rs +++ b/tests/target/async_block.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 fn main() { let x = async { Ok(()) }; diff --git a/tests/target/async_closure.rs b/tests/target/async_closure.rs index 1728460eb66..db6405482c5 100644 --- a/tests/target/async_closure.rs +++ b/tests/target/async_closure.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 fn main() { let async_closure = async { diff --git a/tests/target/async_fn.rs b/tests/target/async_fn.rs index e23f04d28c0..bba220ee250 100644 --- a/tests/target/async_fn.rs +++ b/tests/target/async_fn.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 async fn bar() -> Result<(), ()> { Ok(()) diff --git a/tests/target/catch.rs b/tests/target/catch.rs index 6987a19bcad..ffe694f8e72 100644 --- a/tests/target/catch.rs +++ b/tests/target/catch.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 #![feature(try_blocks)] fn main() { diff --git a/tests/target/issue-2927-2.rs b/tests/target/issue-2927-2.rs index c9fdcdea239..e895783ba8b 100644 --- a/tests/target/issue-2927-2.rs +++ b/tests/target/issue-2927-2.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2015 +// rustfmt-edition: 2015 #![feature(rust_2018_preview, uniform_paths)] use futures::prelude::*; use http_03::cli::Cli; diff --git a/tests/target/issue-2927.rs b/tests/target/issue-2927.rs index 1aa34f01741..3267be28d7b 100644 --- a/tests/target/issue-2927.rs +++ b/tests/target/issue-2927.rs @@ -1,4 +1,4 @@ -// rustfmt-edition: Edition2018 +// rustfmt-edition: 2018 #![feature(rust_2018_preview, uniform_paths)] use ::log::{error, info, log}; use futures::prelude::*; -- cgit 1.4.1-3-g733a5 From 2880d59ec0441476323cf2048b911e53b0cf0c37 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 31 Aug 2018 18:11:52 +0900 Subject: Add trim_tries --- src/chains.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3f5ff75a722..650acbd6937 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -65,7 +65,7 @@ //! .qux //! ``` -use comment::rewrite_comment; +use comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use config::IndentStyle; use expr::rewrite_call; use lists::{extract_post_comment, extract_pre_comment, get_comment_end}; @@ -870,3 +870,28 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool _ => false, } } + +/// Remove try operators (`?`s) that appear in the given string. If removing +/// them leaves an empty line, remove that line as well unless it is the first +/// line (we need the first newline for detecting pre/post comment). +fn trim_tries(s: &str) -> String { + let mut result = String::with_capacity(s.len()); + let mut line_buffer = String::with_capacity(s.len()); + for (kind, rich_char) in CharClasses::new(s.chars()) { + match rich_char.get_char() { + '\n' => { + if result.is_empty() || !line_buffer.trim().is_empty() { + result.push_str(&line_buffer); + result.push('\n') + } + line_buffer.clear(); + } + '?' if kind == FullCodeCharKind::Normal => continue, + c => line_buffer.push(c), + } + } + if !line_buffer.trim().is_empty() { + result.push_str(&line_buffer); + } + result +} -- cgit 1.4.1-3-g733a5 From 612f1af7347a618d96d0700e161bdac5131f6c05 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 31 Aug 2018 18:11:59 +0900 Subject: Use trim_tries to extract pre-comments over simple trim_matches --- src/chains.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 650acbd6937..d93995c9484 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -334,9 +334,8 @@ impl Chain { // Pre-comment if handle_comment { let pre_comment_span = mk_sp(prev_span_end, chain_item.span.lo()); - let pre_comment_snippet = context.snippet(pre_comment_span); - let pre_comment_snippet = pre_comment_snippet.trim().trim_matches('?'); - let (pre_comment, _) = extract_pre_comment(pre_comment_snippet); + let pre_comment_snippet = trim_tries(context.snippet(pre_comment_span)); + let (pre_comment, _) = extract_pre_comment(&pre_comment_snippet); match pre_comment { Some(ref comment) if !comment.is_empty() => { children.push(ChainItem::comment( -- cgit 1.4.1-3-g733a5 From 9df1dbe1aca8989d018ad85f66a1e84862c1032e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 31 Aug 2018 18:16:50 +0900 Subject: Use trim_tries to extract post comment over simple trim_matches --- src/chains.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index d93995c9484..f73f57a19a6 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -288,9 +288,9 @@ impl Chain { return; } // HACK: Treat `?`s as separators. - let trimmed_snippet = post_comment_snippet.trim_matches('?'); - let comment_end = get_comment_end(trimmed_snippet, "?", "", false); - let maybe_post_comment = extract_post_comment(trimmed_snippet, comment_end, "?") + let trimmed_snippet = trim_tries(post_comment_snippet); + let comment_end = get_comment_end(&trimmed_snippet, "?", "", false); + let maybe_post_comment = extract_post_comment(&trimmed_snippet, comment_end, "?") .and_then(|comment| { if comment.is_empty() { None -- cgit 1.4.1-3-g733a5 From 20aac086d6b460373c5b896c3e1680dac14d8081 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 31 Aug 2018 18:19:13 +0900 Subject: Simplify post-comment extraction --- src/chains.rs | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index f73f57a19a6..a0174c622d5 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -68,7 +68,7 @@ use comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use config::IndentStyle; use expr::rewrite_call; -use lists::{extract_post_comment, extract_pre_comment, get_comment_end}; +use lists::extract_pre_comment; use macros::convert_try_mac; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; @@ -273,6 +273,20 @@ impl Chain { s.chars().all(|c| c == '?') } + fn is_post_comment(s: &str) -> bool { + let comment_start_index = s.chars().position(|c| c == '/'); + if comment_start_index.is_none() { + return false; + } + + let newline_index = s.chars().position(|c| c == '\n'); + if newline_index.is_none() { + return true; + } + + comment_start_index.unwrap() < newline_index.unwrap() + } + fn handle_post_comment( post_comment_span: Span, post_comment_snippet: &str, @@ -287,25 +301,14 @@ impl Chain { // No post comment. return; } - // HACK: Treat `?`s as separators. let trimmed_snippet = trim_tries(post_comment_snippet); - let comment_end = get_comment_end(&trimmed_snippet, "?", "", false); - let maybe_post_comment = extract_post_comment(&trimmed_snippet, comment_end, "?") - .and_then(|comment| { - if comment.is_empty() { - None - } else { - Some((comment, comment_end)) - } - }); - - if let Some((post_comment, comment_end)) = maybe_post_comment { + if is_post_comment(&trimmed_snippet) { children.push(ChainItem::comment( post_comment_span, - post_comment, + trimmed_snippet.trim().to_owned(), CommentPosition::Back, )); - *prev_span_end = *prev_span_end + BytePos(comment_end as u32); + *prev_span_end = post_comment_span.hi(); } } -- cgit 1.4.1-3-g733a5 From 6a029974de78f3cc918c52047cbd4c0ec5cbcfe0 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Fri, 31 Aug 2018 15:50:41 +0300 Subject: Fix shape in rewrite_tuple_in_visual_indent_style --- src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 74639c6ef63..11d53eb7074 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1753,7 +1753,7 @@ where Separator::Comma, nested_shape.width, ); - let fmt = ListFormatting::new(shape, context.config) + let fmt = ListFormatting::new(nested_shape, context.config) .tactic(tactic) .ends_with_newline(false); let list_str = write_list(&item_vec, &fmt)?; -- cgit 1.4.1-3-g733a5 From 05b6aaa130f5ffefd7d3629a8655779cd7916e66 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Fri, 31 Aug 2018 16:52:45 +0300 Subject: Add debug logging to fn-related functions --- src/types.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 3ab639a1ac3..d64bd6ebe3a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -298,6 +298,8 @@ where ::Item: Deref, ::Target: Rewrite + Spanned + 'a, { + debug!("format_function_type {:#?}", shape); + // Code for handling variadics is somewhat duplicated for items, but they // are different enough to need some serious refactoring to share code. enum ArgumentKind @@ -706,6 +708,8 @@ fn rewrite_bare_fn( context: &RewriteContext, shape: Shape, ) -> Option { + debug!("rewrite_bare_fn {:#?}", shape); + let mut result = String::with_capacity(128); if let Some(ref lifetime_str) = rewrite_lifetime_param(context, shape, &bare_fn.generic_params) -- cgit 1.4.1-3-g733a5 From 54f8bcb5a2c5aca77e4c941365e04582ba97f9a8 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Fri, 31 Aug 2018 16:53:18 +0300 Subject: Use correct fn args indent for Visual --- src/types.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index d64bd6ebe3a..3a30f40a591 100644 --- a/src/types.rs +++ b/src/types.rs @@ -732,7 +732,11 @@ fn rewrite_bare_fn( result.push_str("fn"); - let func_ty_shape = shape.offset_left(result.len())?; + let func_ty_shape = if context.use_block_indent() { + shape.offset_left(result.len())? + } else { + shape.visual_indent(result.len()).sub_width(result.len())? + }; let rewrite = format_function_type( bare_fn.decl.inputs.iter(), -- cgit 1.4.1-3-g733a5 From 08e282877a46698565c1af04609700971300d17d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 1 Sep 2018 16:18:27 +0900 Subject: Handle raw identifiers in chain --- src/chains.rs | 16 +++++++++------- tests/target/raw_identifiers.rs | 2 ++ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3f5ff75a722..124a33e5001 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -74,8 +74,8 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use source_map::SpanUtils; use utils::{ - first_line_width, last_line_extendable, last_line_width, mk_sp, trimmed_last_line_width, - wrap_str, + first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, + trimmed_last_line_width, wrap_str, }; use std::borrow::Cow; @@ -190,10 +190,12 @@ impl Rewrite for ChainItem { ChainItemKind::MethodCall(ref segment, ref types, ref exprs) => { Self::rewrite_method_call(segment.ident, types, exprs, self.span, context, shape)? } - ChainItemKind::StructField(ident) => format!(".{}", ident.name), - ChainItemKind::TupleField(ident, nested) => { - format!("{}.{}", if nested { " " } else { "" }, ident.name) - } + ChainItemKind::StructField(ident) => format!(".{}", rewrite_ident(context, ident)), + ChainItemKind::TupleField(ident, nested) => format!( + "{}.{}", + if nested { " " } else { "" }, + rewrite_ident(context, ident) + ), ChainItemKind::Comment(ref comment, _) => { rewrite_comment(comment, false, shape, context.config)? } @@ -241,7 +243,7 @@ impl ChainItem { format!("::<{}>", type_list.join(", ")) }; - let callee_str = format!(".{}{}", method_name, type_str); + let callee_str = format!(".{}{}", rewrite_ident(context, method_name), type_str); rewrite_call(context, &callee_str, &args[1..], span, shape) } } diff --git a/tests/target/raw_identifiers.rs b/tests/target/raw_identifiers.rs index dd76117fa8e..275d9515a92 100644 --- a/tests/target/raw_identifiers.rs +++ b/tests/target/raw_identifiers.rs @@ -11,6 +11,8 @@ fn main() { r#foo::r#bar(); let r#local = r#Struct { r#field: () }; + r#local.r#field = 1; + r#foo.r#barr(); let r#async = r#foo(r#local); r#macro!(); -- cgit 1.4.1-3-g733a5 From 968affc3e0bd713d2e4c46f273eca8b988c469ae Mon Sep 17 00:00:00 2001 From: Maximilian Roos Date: Sat, 1 Sep 2018 16:26:47 -0400 Subject: final clippy changes --- src/attr.rs | 2 +- src/bin/main.rs | 14 +++++++------- src/comment.rs | 6 +++--- src/config/options.rs | 4 ++-- src/expr.rs | 14 +++++++------- src/format-diff/main.rs | 2 +- src/formatting.rs | 10 +++++----- src/imports.rs | 4 ++-- src/lists.rs | 2 +- src/macros.rs | 18 +++++++++--------- src/missed_spans.rs | 2 +- src/reorder.rs | 12 ++++++------ src/shape.rs | 2 +- src/test/mod.rs | 4 ++-- src/vertical.rs | 2 +- src/visitor.rs | 29 +++++++++++++++-------------- 16 files changed, 64 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index f4b84e51a30..fc29c69b498 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -48,7 +48,7 @@ fn is_derive(attr: &ast::Attribute) -> bool { } /// Returns the arguments of `#[derive(...)]`. -fn get_derive_spans<'a>(attr: &ast::Attribute) -> Option> { +fn get_derive_spans(attr: &ast::Attribute) -> Option> { attr.meta_item_list().map(|meta_item_list| { meta_item_list .iter() diff --git a/src/bin/main.rs b/src/bin/main.rs index 760333955a0..a3d2819e1db 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -172,19 +172,19 @@ fn execute(opts: &Options) -> Result { match determine_operation(&matches)? { Operation::Help(HelpOp::None) => { print_usage_to_stdout(opts, ""); - return Ok(0); + Ok(0) } Operation::Help(HelpOp::Config) => { Config::print_docs(&mut stdout(), options.unstable_features); - return Ok(0); + Ok(0) } Operation::Help(HelpOp::FileLines) => { print_help_file_lines(); - return Ok(0); + Ok(0) } Operation::Version => { print_version(); - return Ok(0); + Ok(0) } Operation::ConfigOutputDefault { path } => { let toml = Config::default().all_options().to_toml().map_err(err_msg)?; @@ -194,13 +194,13 @@ fn execute(opts: &Options) -> Result { } else { io::stdout().write_all(toml.as_bytes())?; } - return Ok(0); + Ok(0) } Operation::Stdin { input } => format_string(input, options), Operation::Format { files, minimal_config_path, - } => format(files, minimal_config_path, options), + } => format(files, minimal_config_path, &options), } } @@ -236,7 +236,7 @@ fn format_string(input: String, options: GetOptsOptions) -> Result, minimal_config_path: Option, - options: GetOptsOptions, + options: &GetOptsOptions, ) -> Result { options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(options.clone()))?; diff --git a/src/comment.rs b/src/comment.rs index e3c6201d3c4..de0fca11f71 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -47,7 +47,7 @@ fn custom_opener(s: &str) -> &str { s.lines().next().map_or("", |first_line| { first_line .find(' ') - .map_or(first_line, |space_index| &first_line[0..space_index + 1]) + .map_or(first_line, |space_index| &first_line[0..=space_index]) }) } @@ -1151,7 +1151,7 @@ pub fn recover_comment_removed( context.report.append( context.source_map.span_to_filename(span).into(), vec![FormattingError::from_span( - &span, + span, &context.source_map, ErrorKind::LostComment, )], @@ -1428,7 +1428,7 @@ mod test { #[test] fn test_remove_trailing_white_spaces() { - let s = format!(" r#\"\n test\n \"#"); + let s = " r#\"\n test\n \"#"; assert_eq!(remove_trailing_white_spaces(&s), s); } diff --git a/src/config/options.rs b/src/config/options.rs index d2a74f54677..95ccef96fc5 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -264,7 +264,7 @@ configuration_option_enum! { Color: impl Color { /// Whether we should use a coloured terminal. - pub fn use_colored_tty(&self) -> bool { + pub fn use_colored_tty(self) -> bool { match self { Color::Always => true, Color::Never => false, @@ -417,7 +417,7 @@ configuration_option_enum!{ Edition: } impl Edition { - pub(crate) fn to_libsyntax_pos_edition(&self) -> syntax_pos::edition::Edition { + pub(crate) fn to_libsyntax_pos_edition(self) -> syntax_pos::edition::Edition { match self { Edition::Edition2015 => syntax_pos::edition::Edition::Edition2015, Edition::Edition2018 => syntax_pos::edition::Edition::Edition2018, diff --git a/src/expr.rs b/src/expr.rs index 74639c6ef63..a5435f53f8d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -100,7 +100,7 @@ pub fn format_expr( ) }) } - ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), + ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( context, path, @@ -1519,7 +1519,7 @@ fn rewrite_index( } } -fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { +fn struct_lit_can_be_aligned(fields: &[ast::Field], base: Option<&ast::Expr>) -> bool { if base.is_some() { return false; } @@ -1555,7 +1555,7 @@ fn rewrite_struct_lit<'a>( let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, &base) + let fields_str = if struct_lit_can_be_aligned(fields, base) && context.config.struct_field_align_threshold() > 0 { rewrite_with_alignment( @@ -1676,7 +1676,7 @@ pub fn rewrite_field( }; let name = context.snippet(field.ident.span); if field.is_shorthand { - Some(attrs_str + &name) + Some(attrs_str + name) } else { let mut separator = String::from(struct_lit_field_separator(context.config)); for _ in 0..prefix_max_width.saturating_sub(name.len()) { @@ -1688,7 +1688,7 @@ pub fn rewrite_field( match expr { Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { - Some(attrs_str + &name) + Some(attrs_str + name) } Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { @@ -1827,12 +1827,12 @@ pub fn rewrite_unary_suffix( fn rewrite_unary_op( context: &RewriteContext, - op: &ast::UnOp, + op: ast::UnOp, expr: &ast::Expr, shape: Shape, ) -> Option { // For some reason, an UnOp is not spanned like BinOp! - let operator_str = match *op { + let operator_str = match op { ast::UnOp::Deref => "*", ast::UnOp::Not => "!", ast::UnOp::Neg => "-", diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 37ad4f35a1d..d509a4429b4 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -214,7 +214,7 @@ where #[test] fn scan_simple_git_diff() { - const DIFF: &'static str = include_str!("test/bindgen.diff"); + const DIFF: &str = include_str!("test/bindgen.diff"); let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?"); assert!( diff --git a/src/formatting.rs b/src/formatting.rs index 3012837ba64..9386302c479 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -194,11 +194,11 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { fn handle_formatted_file( &mut self, path: FileName, - mut result: String, + result: String, report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { - match source_file::write_file(&mut result, &path, out, &self.config) { + match source_file::write_file(&result, &path, out, &self.config) { Ok(b) if b => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed @@ -224,7 +224,7 @@ pub(crate) struct FormattingError { impl FormattingError { pub(crate) fn from_span( - span: &Span, + span: Span, source_map: &SourceMap, kind: ErrorKind, ) -> FormattingError { @@ -234,13 +234,13 @@ impl FormattingError { kind, is_string: false, line_buffer: source_map - .span_to_lines(*span) + .span_to_lines(span) .ok() .and_then(|fl| { fl.file .get_line(fl.lines[0].line_index) .map(|l| l.into_owned()) - }).unwrap_or_else(|| String::new()), + }).unwrap_or_else(String::new), } } diff --git a/src/imports.rs b/src/imports.rs index db00c45b9d9..3ca063a58e7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -179,7 +179,7 @@ pub fn merge_use_trees(use_trees: Vec) -> Vec { fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree) { for tree in trees.iter_mut() { if tree.share_prefix(&use_tree) { - tree.merge(use_tree); + tree.merge(&use_tree); return; } } @@ -536,7 +536,7 @@ impl UseTree { } } - fn merge(&mut self, other: UseTree) { + fn merge(&mut self, other: &UseTree) { let mut new_path = vec![]; for (a, b) in self .path diff --git a/src/lists.rs b/src/lists.rs index 8867c6f2283..f1b01ea8055 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -475,7 +475,7 @@ where formatted_comment = rewrite_post_comment(&mut item_max_width)?; comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); } - for _ in 0..(comment_alignment + 1) { + for _ in 0..=comment_alignment { result.push(' '); } // An additional space for the missing trailing separator. diff --git a/src/macros.rs b/src/macros.rs index e8e0f1b572e..6aae1b23f0c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -524,12 +524,12 @@ enum MacroArgKind { fn delim_token_to_str( context: &RewriteContext, - delim_token: &DelimToken, + delim_token: DelimToken, shape: Shape, use_multiple_lines: bool, inner_is_empty: bool, ) -> (String, String) { - let (lhs, rhs) = match *delim_token { + let (lhs, rhs) = match delim_token { DelimToken::Paren => ("(", ")"), DelimToken::Bracket => ("[", "]"), DelimToken::Brace => { @@ -612,7 +612,7 @@ impl MacroArgKind { MacroArgKind::MetaVariable(ty, ref name) => { Some(format!("${}:{}", name, ty.name.as_str())) } - MacroArgKind::Repeat(ref delim_tok, ref args, ref another, ref tok) => { + MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => { let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?; let another = another .as_ref() @@ -622,7 +622,7 @@ impl MacroArgKind { Some(format!("${}{}{}{}{}", lhs, inner, rhs, another, repeat_tok)) } - MacroArgKind::Delimited(ref delim_tok, ref args) => { + MacroArgKind::Delimited(delim_tok, ref args) => { rewrite_delimited_inner(delim_tok, args) .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs)) } @@ -755,8 +755,8 @@ impl MacroArgParser { let mut hi = span.hi(); // Parse '*', '+' or '?. - for ref tok in iter { - self.set_last_tok(tok); + for tok in iter { + self.set_last_tok(&tok); if first { first = false; lo = tok.span().lo(); @@ -977,7 +977,7 @@ enum SpaceState { fn force_space_before(tok: &Token) -> bool { debug!("tok: force_space_before {:?}", tok); - match *tok { + match tok { Token::Eq | Token::Lt | Token::Le @@ -1002,7 +1002,7 @@ fn force_space_before(tok: &Token) -> bool { } fn ident_like(tok: &Token) -> bool { - match *tok { + match tok { Token::Ident(..) | Token::Literal(..) | Token::Lifetime(_) => true, _ => false, } @@ -1011,7 +1011,7 @@ fn ident_like(tok: &Token) -> bool { fn next_space(tok: &Token) -> SpaceState { debug!("next_space: {:?}", tok); - match *tok { + match tok { Token::Not | Token::BinOp(BinOpToken::And) | Token::Tilde diff --git a/src/missed_spans.rs b/src/missed_spans.rs index ef047b3144c..f2f2295a872 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -315,7 +315,7 @@ impl<'a> FmtVisitor<'a> { self.push_str("\n"); status.last_wspace = None; } else { - self.push_str(&snippet[status.line_start..i + 1]); + self.push_str(&snippet[status.line_start..=i]); } status.cur_line += 1; diff --git a/src/reorder.rs b/src/reorder.rs index b6876738cfd..47aae3bfc2a 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -193,12 +193,12 @@ impl ReorderableItemKind { } } - fn is_same_item_kind(&self, item: &ast::Item) -> bool { - ReorderableItemKind::from(item) == *self + fn is_same_item_kind(self, item: &ast::Item) -> bool { + ReorderableItemKind::from(item) == self } - fn is_reorderable(&self, config: &Config) -> bool { - match *self { + fn is_reorderable(self, config: &Config) -> bool { + match self { ReorderableItemKind::ExternCrate => config.reorder_imports(), ReorderableItemKind::Mod => config.reorder_modules(), ReorderableItemKind::Use => config.reorder_imports(), @@ -206,8 +206,8 @@ impl ReorderableItemKind { } } - fn in_group(&self) -> bool { - match *self { + fn in_group(self) -> bool { + match self { ReorderableItemKind::ExternCrate | ReorderableItemKind::Mod | ReorderableItemKind::Use => true, diff --git a/src/shape.rs b/src/shape.rs index 12a911a1931..5868f0b85fd 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -91,7 +91,7 @@ impl Indent { }; let num_chars = num_tabs + num_spaces; if num_tabs == 0 && num_chars + offset <= INDENT_BUFFER_LEN { - Cow::from(&INDENT_BUFFER[offset..num_chars + 1]) + Cow::from(&INDENT_BUFFER[offset..=num_chars]) } else { let mut indent = String::with_capacity(num_chars + if offset == 0 { 1 } else { 0 }); if offset == 0 { diff --git a/src/test/mod.rs b/src/test/mod.rs index 8b2358f1ada..17f8ffec9a1 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -102,7 +102,7 @@ fn verify_config_test_names() { // `print_diff` selects the approach not used. fn write_message(msg: &str) { let mut writer = OutputWriter::new(Color::Auto); - writer.writeln(&format!("{}", msg), None); + writer.writeln(msg, None); } // Integration tests. The files in the tests/source are formatted and compared @@ -949,7 +949,7 @@ fn rustfmt() -> PathBuf { me.is_file() || me.with_extension("exe").is_file(), "no rustfmt bin, try running `cargo build` before testing" ); - return me; + me } #[test] diff --git a/src/vertical.rs b/src/vertical.rs index e76f44ca39b..3f533920106 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -126,7 +126,7 @@ pub fn rewrite_with_alignment( } else { ("", fields.len() - 1) }; - let init = &fields[0..group_index + 1]; + let init = &fields[0..=group_index]; let rest = &fields[group_index + 1..]; let init_last_pos = if rest.is_empty() { span.hi() diff --git a/src/visitor.rs b/src/visitor.rs index 4373fc048ea..e6ef7f23da0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -621,24 +621,25 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.report.append( file_name, vec![FormattingError::from_span( - &attr.span, + attr.span, &self.source_map, ErrorKind::DeprecatedAttr, )], ); - } else if attr.path.segments[0].ident.to_string() == "rustfmt" - && (attr.path.segments.len() == 1 - || attr.path.segments[1].ident.to_string() != "skip") - { - let file_name = self.source_map.span_to_filename(attr.span).into(); - self.report.append( - file_name, - vec![FormattingError::from_span( - &attr.span, - &self.source_map, - ErrorKind::BadAttr, - )], - ); + } else if attr.path.segments[0].ident.to_string() == "rustfmt" { + if attr.path.segments.len() == 1 + || attr.path.segments[1].ident.to_string() != "skip" + { + let file_name = self.source_map.span_to_filename(attr.span).into(); + self.report.append( + file_name, + vec![FormattingError::from_span( + attr.span, + &self.source_map, + ErrorKind::BadAttr, + )], + ); + } } } if contains_skip(attrs) { -- cgit 1.4.1-3-g733a5 From 1704e249560ed99c8ecc2a28397a3edab21ca5ac Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 31 Aug 2018 14:21:02 +0900 Subject: Cargo update --- Cargo.lock | 222 ++++++++++++++++++++++++++++++--------------------------- Cargo.toml | 6 +- src/matches.rs | 12 +++- 3 files changed, 129 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 9c3e4f59669..3199f7b0de3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,9 +1,9 @@ [[package]] name = "aho-corasick" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -54,18 +54,18 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.4" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -75,14 +75,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -134,9 +134,9 @@ name = "derive-new" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -164,14 +164,14 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -201,9 +201,9 @@ name = "failure_derive" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -212,7 +212,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -283,7 +283,7 @@ dependencies = [ [[package]] name = "memchr" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -337,7 +337,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -350,10 +350,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -381,14 +381,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -401,24 +401,24 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -426,8 +426,8 @@ dependencies = [ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -437,31 +437,31 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -469,29 +469,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "237.0.0" +version = "246.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -506,7 +506,7 @@ name = "rustc-hash" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -538,19 +538,19 @@ dependencies = [ "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -559,7 +559,7 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -578,7 +578,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -588,17 +588,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.71" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.71" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -607,8 +607,8 @@ version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,11 +626,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.14.8" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -639,9 +639,9 @@ name = "synstructure" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -650,7 +650,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -664,10 +664,10 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -693,7 +693,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -726,7 +726,7 @@ dependencies = [ [[package]] name = "utf8-ranges" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -753,6 +753,14 @@ name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -768,23 +776,24 @@ dependencies = [ [[package]] name = "wincolor" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" +"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a29ab7c0ed62970beb0534d637a8688842506d0ff9157de83286dacd065c8149" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum byteorder 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8389c509ec62b9fe8eca58c502a0acaf017737355615243496cde4994f8fa4f9" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" -"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275" +"checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum colored 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc0a60679001b62fb628c4da80e574b9645ab4646056d7c9018885efffe45533" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" @@ -795,7 +804,7 @@ dependencies = [ "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621" -"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" +"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" @@ -810,48 +819,48 @@ dependencies = [ "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" -"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" +"checksum proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "37460f858ac0db19bceb2585494de611c9d8618062e6da2994a211b600cc4fc9" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ed7d650913520df631972f21e104a4fa2f9c82a14afc65d17b388a2e29731e7c" +"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" +"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum rustc-ap-arena 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d24c8b3c1437fad023cb9472381216a1d41d82dbb2d2e6c7858bd6f50317719" -"checksum rustc-ap-rustc_cratesio_shim 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c5b02c76cd1ee4e9c97c8228701796d6b7431e8f100dea2d8af1d6c2c2bad56" -"checksum rustc-ap-rustc_data_structures 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076388154497fb9a007e3badd78e415402a5594111cd6bc7ce1420dd1b1818b" -"checksum rustc-ap-rustc_errors 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c11e4789cbc276ceaa87d326c234b1a2d1e0fe6017b88a8a25903200060acb" -"checksum rustc-ap-rustc_target 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25f711bb152b9d7cdd69410cfe6d99aeb1409c959e0fdf3c8ca4d220e568aa52" -"checksum rustc-ap-serialize 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57638db658d4942d3f30a12566836f9a67a636ed8002c8cae1c9231214e39929" -"checksum rustc-ap-syntax 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6dbcf07abf7a9957dce8d34353d55dfb4cd882153181f24349f4690facb58f0" -"checksum rustc-ap-syntax_pos 237.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0915cb5e166cabe588a129dec2d47357077e96fb1f9b57318fbe217eac4ce508" +"checksum rustc-ap-arena 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf0d22cdac821e87879daee5f3be1b2f61cd8e8143523ea5983f8a23c1658a22" +"checksum rustc-ap-rustc_cratesio_shim 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f9c4ed8b9175db82421dc1d663faefcf328194365de4a7d6fad87596f21b5b" +"checksum rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "727d8195e549a01d54b9782f5f1ca35989989be9479457ce84f376649cb6af10" +"checksum rustc-ap-rustc_errors 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8462144b3f8600ce583cbcd7840d0244e2ea92d2d858c54c8b8f8fd6addde5e" +"checksum rustc-ap-rustc_target 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79c419f1060e8f279dc10f949a6536a06a807352302988b0ede5277ffe38f00e" +"checksum rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f8eb12053983063787e16416292ec8fcd4002e7357f53a7b574c35c8ce3604a" +"checksum rustc-ap-syntax 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f93c483e0f6dd28ebf5351e8880487907cac2853fe45c7dbbd426b592449e025" +"checksum rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08155e4f9c79c8604c198a8efca5ddbc75a180a9c66b568b505e8c5e8c480d56" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" -"checksum ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b" +"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfad05c8854584e5f72fb859385ecdfa03af69c3fd0572f0da2d4c95f060bdb" -"checksum serde_derive 1.0.71 (registry+https://github.com/rust-lang/crates.io-index)" = "b719c6d5e9f73fbc37892246d5852333f040caa617b8873c6aced84bcb28e7bb" +"checksum serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)" = "d00c69ae39089576cddfd235556e3b21bf41c2d80018063cb5ab8a1183c917fd" +"checksum serde_derive 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8384360683b7114fc6eeeb41dde6ee37eeba2cf3660deef3a7a0d7548e55e9" "checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum syn 0.14.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b7bfcbb0c068d0f642a0ffbd5c604965a360a61f99e8add013cef23a838614f3" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" -"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836" +"checksum termcolor 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3bac0e465b59f194e7037ed404b0326e56ff234d767edc4c5cc9cd49e7a2c7" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" @@ -860,11 +869,12 @@ dependencies = [ "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" -"checksum wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9dc3aa9dcda98b5a16150c54619c1ead22e3d3a5d458778ae914be760aa981a" +"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/Cargo.toml b/Cargo.toml index 6730d200b80..3af9c7f0bcf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,9 +47,9 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.6" -rustc-ap-rustc_target = "237.0.0" -rustc-ap-syntax = "237.0.0" -rustc-ap-syntax_pos = "237.0.0" +rustc-ap-rustc_target = "246.0.0" +rustc-ap-syntax = "246.0.0" +rustc-ap-syntax_pos = "246.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/matches.rs b/src/matches.rs index 931aaff1765..9fac170b96c 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -275,7 +275,7 @@ fn rewrite_match_arm( fn rewrite_match_pattern( context: &RewriteContext, pats: &[&ast::Pat], - guard: &Option>, + guard: &Option, shape: Shape, ) -> Option { // Patterns @@ -484,10 +484,18 @@ fn rewrite_match_body( } } +impl Rewrite for ast::Guard { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self { + ast::Guard::If(ref expr) => expr.rewrite(context, shape), + } + } +} + // The `if ...` guard on a match arm. fn rewrite_guard( context: &RewriteContext, - guard: &Option>, + guard: &Option, shape: Shape, // The amount of space used up on this line for the pattern in // the arm (excludes offset). -- cgit 1.4.1-3-g733a5 From e058a3f7e7299fda0e2667765069aba60e400a0f Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 6 Sep 2018 02:07:09 +0200 Subject: fix cargo test --release. test::verify_check_works was failing in relase mode on my machine. The problem was it would check for target/debug/rustfmt in release mode instead of target/release/rustfmt and fail an assert. This commit fixes it so that cargo check looks for target/debug/rustfmt and cargo check --release looks for target/release/rustfmt --- src/test/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 17f8ffec9a1..f7848dfd737 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -944,10 +944,21 @@ fn rustfmt() -> PathBuf { let mut me = env::current_exe().expect("failed to get current executable"); me.pop(); // chop of the test name me.pop(); // chop off `deps` + + // if we run `cargo test --release` we might only have a release build + if cfg!(release) { + // ../release/ + me.pop(); + me.push("release"); + } me.push("rustfmt"); assert!( me.is_file() || me.with_extension("exe").is_file(), - "no rustfmt bin, try running `cargo build` before testing" + if cfg!(release) { + "no rustfmt bin, try running `cargo build --release` before testing" + } else { + "no rustfmt bin, try running `cargo build` before testing" + } ); me } -- cgit 1.4.1-3-g733a5 From 992b179d33360b9e623e287442e754c6a2f8805e Mon Sep 17 00:00:00 2001 From: Robert Bartlensky Date: Thu, 6 Sep 2018 17:16:48 +0100 Subject: Change `print_diff` to output the correct line number. --- src/rustfmt_diff.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 2a331eec19a..4e0ac31e312 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -161,7 +161,7 @@ where let mut writer = OutputWriter::new(color); for mismatch in diff { - let title = get_section_title(mismatch.line_number); + let title = get_section_title(mismatch.line_number_orig); writer.writeln(&title, None); for line in mismatch.lines { -- cgit 1.4.1-3-g733a5 From 90ec5a226f64881aad0a59dce7f6ef1248ecbd80 Mon Sep 17 00:00:00 2001 From: David Hotham Date: Fri, 7 Sep 2018 09:01:44 +0100 Subject: Fix typo in usage text --- src/bin/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index a3d2819e1db..7069733cae1 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -87,7 +87,7 @@ fn make_opts() -> Options { opts.optflag( "", "check", - "Run in 'check' mode. Exits with 0 if input if formatted correctly. Exits \ + "Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits \ with 1 and prints a diff if formatting is required.", ); let is_nightly = is_nightly(); -- cgit 1.4.1-3-g733a5 From 6f318e3ceff807a1f2e63a0b73aa5c1a4a27519a Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 7 Sep 2018 14:48:52 +0200 Subject: propagate errors about failing to rewrite a macro --- src/expr.rs | 3 +++ src/items.rs | 8 ++++++++ src/macros.rs | 13 +++++++++++- src/visitor.rs | 10 ++++++--- tests/source/issue-2977/impl.rs | 44 ++++++++++++++++++++++++++++++++++++++++ tests/source/issue-2977/trait.rs | 44 ++++++++++++++++++++++++++++++++++++++++ tests/target/issue-2977/block.rs | 11 ++++++++++ tests/target/issue-2977/impl.rs | 44 ++++++++++++++++++++++++++++++++++++++++ tests/target/issue-2977/item.rs | 11 ++++++++++ tests/target/issue-2977/trait.rs | 44 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 tests/source/issue-2977/impl.rs create mode 100644 tests/source/issue-2977/trait.rs create mode 100644 tests/target/issue-2977/block.rs create mode 100644 tests/target/issue-2977/impl.rs create mode 100644 tests/target/issue-2977/item.rs create mode 100644 tests/target/issue-2977/trait.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 329081f5d70..722898b8150 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -522,6 +522,9 @@ pub fn rewrite_block_with_visitor( let inner_attrs = attrs.map(inner_attributes); let label_str = rewrite_label(label); visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } Some(format!("{}{}{}", prefix, label_str, visitor.buffer)) } diff --git a/src/items.rs b/src/items.rs index 7f8980dd150..9dfc4c584cd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -747,6 +747,10 @@ pub fn format_impl( visitor.format_missing(item.span.hi() - BytePos(1)); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); @@ -1106,6 +1110,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) visitor.format_missing(item.span.hi() - BytePos(1)); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); diff --git a/src/macros.rs b/src/macros.rs index 6aae1b23f0c..6e52b63363d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -69,6 +69,9 @@ impl Rewrite for ast::Item { visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } Some(visitor.buffer) } } @@ -406,7 +409,15 @@ pub fn rewrite_macro_def( ";", |branch| branch.span.lo(), |branch| branch.span.hi(), - |branch| branch.rewrite(context, arm_shape, multi_branch_style), + |branch| match branch.rewrite(context, arm_shape, multi_branch_style) { + Some(v) => Some(v), + // if the rewrite returned None because a macro could not be rewritten, then return the + // original body + None if *context.macro_rewrite_failure.borrow() == true => { + Some(context.snippet(branch.body).trim().to_string()) + } + None => None, + }, context.snippet_provider.span_after(span, "{"), span.hi(), false, diff --git a/src/visitor.rs b/src/visitor.rs index e6ef7f23da0..c622de6ef48 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -97,7 +97,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if contains_skip(get_attrs_from_stmt(stmt)) { self.push_skipped_with_span(stmt.span()); } else { - let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + let shape = self.shape().clone(); + let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); self.push_rewrite(stmt.span(), rewrite) } } @@ -350,11 +351,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let where_span_end = snippet .find_uncommented("{") .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); - let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); + let block_indent = self.block_indent.clone(); + let rw = + self.with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end)); self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { - let rw = format_trait(&self.get_context(), item, self.block_indent); + let block_indent = self.block_indent.clone(); + let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); self.push_rewrite(item.span, rw); } ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { diff --git a/tests/source/issue-2977/impl.rs b/tests/source/issue-2977/impl.rs new file mode 100644 index 00000000000..8d7bb9414eb --- /dev/null +++ b/tests/source/issue-2977/impl.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + impl AtomicBits for $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} diff --git a/tests/source/issue-2977/trait.rs b/tests/source/issue-2977/trait.rs new file mode 100644 index 00000000000..ae20668cd75 --- /dev/null +++ b/tests/source/issue-2977/trait.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + trait $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} diff --git a/tests/target/issue-2977/block.rs b/tests/target/issue-2977/block.rs new file mode 100644 index 00000000000..d376e370c72 --- /dev/null +++ b/tests/target/issue-2977/block.rs @@ -0,0 +1,11 @@ +macro_rules! atomic_bits { + ($ldrex:expr) => { + execute(|| { + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + }) + }; +} diff --git a/tests/target/issue-2977/impl.rs b/tests/target/issue-2977/impl.rs new file mode 100644 index 00000000000..8d7bb9414eb --- /dev/null +++ b/tests/target/issue-2977/impl.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + impl AtomicBits for $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} diff --git a/tests/target/issue-2977/item.rs b/tests/target/issue-2977/item.rs new file mode 100644 index 00000000000..857065ca93f --- /dev/null +++ b/tests/target/issue-2977/item.rs @@ -0,0 +1,11 @@ +macro_rules! atomic_bits { + ($ldrex:expr) => { + some_macro!(pub fn foo() { + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + }) + }; +} diff --git a/tests/target/issue-2977/trait.rs b/tests/target/issue-2977/trait.rs new file mode 100644 index 00000000000..ae20668cd75 --- /dev/null +++ b/tests/target/issue-2977/trait.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + trait $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} -- cgit 1.4.1-3-g733a5 From 4b7130dfa191e94043fa84673c9cb57e7ff46f63 Mon Sep 17 00:00:00 2001 From: lqd Date: Fri, 7 Sep 2018 19:51:21 +0200 Subject: normalize_doc_attributes option: convert doc attributes to comments Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. --- Configurations.md | 26 ++++++++++++++++++++++++++ src/attr.rs | 29 ++++++++++++++++++++++++++--- src/config/mod.rs | 1 + tests/source/doc-attrib.rs | 11 +++++++++++ tests/target/doc-attrib.rs | 17 +++++++++++++++++ 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 tests/source/doc-attrib.rs create mode 100644 tests/target/doc-attrib.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ae8ea2b3c6d..7f44fa5d3e8 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2188,6 +2188,32 @@ If you want to format code that requires edition 2018, add the following to your edition = "2018" ``` +## `normalize_doc_attributes` + +Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): + +```rust +#![doc = "Example documentation"] + +#[doc = "Example item documentation"] +pub enum Foo {} +``` + +#### `true`: + +```rust +//! Example documentation + +/// Example item documentation +pub enum Foo {} +``` + ## `emit_mode` Internal option diff --git a/src/attr.rs b/src/attr.rs index fc29c69b498..c7ee633ec4e 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,7 +10,7 @@ //! Format attributes and meta items. -use comment::{contains_comment, rewrite_doc_comment}; +use comment::{contains_comment, rewrite_doc_comment, CommentStyle}; use config::lists::*; use config::IndentStyle; use expr::rewrite_literal; @@ -350,11 +350,34 @@ impl Rewrite for ast::Attribute { if contains_comment(snippet) { return Some(snippet.to_owned()); } + + let meta = self.meta(); + + // This attribute is possibly a doc attribute needing normalization to a doc comment + if context.config.normalize_doc_attributes() { + if let Some(ref meta) = meta { + if meta.check_name("doc") { + if let Some(ref literal) = meta.value_str() { + let comment_style = match self.style { + ast::AttrStyle::Inner => CommentStyle::Doc, + ast::AttrStyle::Outer => CommentStyle::TripleSlash, + }; + + let doc_comment = format!("{}{}", comment_style.opener(), literal); + return rewrite_doc_comment( + &doc_comment, + shape.comment(context.config), + context.config, + ); + } + } + } + } + // 1 = `[` let shape = shape.offset_left(prefix.len() + 1)?; Some( - self.meta() - .and_then(|meta| meta.rewrite(context, shape)) + meta.and_then(|meta| meta.rewrite(context, shape)) .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), ) } diff --git a/src/config/mod.rs b/src/config/mod.rs index f240c7b13c6..fca4ca98ddd 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -107,6 +107,7 @@ create_config! { blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items"; edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)"; + normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/tests/source/doc-attrib.rs b/tests/source/doc-attrib.rs new file mode 100644 index 00000000000..f8f2b9566dc --- /dev/null +++ b/tests/source/doc-attrib.rs @@ -0,0 +1,11 @@ +// rustfmt-wrap_comments: true +// rustfmt-normalize_doc_attributes: true + +#![doc = "Example doc attribute comment"] + +// Long `#[doc = "..."]` +struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } + + +#[doc = "The `nodes` and `edges` method each return instantiations of `Cow<[T]>` to leave implementers the freedom to create entirely new vectors or to pass back slices into internally owned vectors."] +struct B { b: i32 } \ No newline at end of file diff --git a/tests/target/doc-attrib.rs b/tests/target/doc-attrib.rs new file mode 100644 index 00000000000..5f77de07de3 --- /dev/null +++ b/tests/target/doc-attrib.rs @@ -0,0 +1,17 @@ +// rustfmt-wrap_comments: true +// rustfmt-normalize_doc_attributes: true + +//! Example doc attribute comment + +// Long `#[doc = "..."]` +struct A { + /// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + b: i32, +} + +/// The `nodes` and `edges` method each return instantiations of `Cow<[T]>` to +/// leave implementers the freedom to create entirely new vectors or to pass +/// back slices into internally owned vectors. +struct B { + b: i32, +} -- cgit 1.4.1-3-g733a5 From 46e2a2e7c76dbc6ada09ee815a440701d6aeaba9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 9 Sep 2018 11:12:13 -0700 Subject: Support platforms without a timer I've dabbled recently in seeing how hard it would be to compile rustfmt to wasm and then run it in a web browser, and it turns out that it's [not too hard][wasm]! In addition to patching a few dependencies which already have a number of patches out rustfmt also needed some modifications to get it to work, namely avoiding the usage of `Instant::now()` on the "happy path" which doesn't work on wasm (it just panics). This commit is an attempt to add a support for this by avoiding using `Instant::now()` on the wasm target, but panicking if the actual time elapsed is requested (which doesn't happen unless verbosely logging I believe). [wasm]: https://alexcrichton.github.io/rustfmt-wasm/ --- src/formatting.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 9386302c479..a07cdcc8a14 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -64,7 +64,7 @@ fn format_project( config: &Config, handler: &mut T, ) -> Result { - let mut timer = Timer::Initialized(Instant::now()); + let mut timer = Timer::start(); let main_file = input.file_name(); let input_is_stdin = main_file == FileName::Stdin; @@ -344,14 +344,23 @@ pub(crate) struct ModifiedLines { #[derive(Clone, Copy, Debug)] enum Timer { + Disabled, Initialized(Instant), DoneParsing(Instant, Instant), DoneFormatting(Instant, Instant, Instant), } impl Timer { + fn start() -> Timer { + if cfg!(target_arch = "wasm32") { + Timer::Disabled + } else { + Timer::Initialized(Instant::now()) + } + } fn done_parsing(self) -> Self { match self { + Timer::Disabled => Timer::Disabled, Timer::Initialized(init_time) => Timer::DoneParsing(init_time, Instant::now()), _ => panic!("Timer can only transition to DoneParsing from Initialized state"), } @@ -359,6 +368,7 @@ impl Timer { fn done_formatting(self) -> Self { match self { + Timer::Disabled => Timer::Disabled, Timer::DoneParsing(init_time, parse_time) => { Timer::DoneFormatting(init_time, parse_time, Instant::now()) } @@ -369,6 +379,7 @@ impl Timer { /// Returns the time it took to parse the source files in seconds. fn get_parse_time(&self) -> f32 { match *self { + Timer::Disabled => panic!("this platform cannot time execution"), Timer::DoneParsing(init, parse_time) | Timer::DoneFormatting(init, parse_time, _) => { // This should never underflow since `Instant::now()` guarantees monotonicity. Self::duration_to_f32(parse_time.duration_since(init)) @@ -381,6 +392,7 @@ impl Timer { /// not included. fn get_format_time(&self) -> f32 { match *self { + Timer::Disabled => panic!("this platform cannot time execution"), Timer::DoneFormatting(_init, parse_time, format_time) => { Self::duration_to_f32(format_time.duration_since(parse_time)) } -- cgit 1.4.1-3-g733a5 From d8357484ac07db3e9f4fe03bf09bea3b0f925f1e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 11 Sep 2018 13:31:37 +0900 Subject: Refactor the corner case of handling long function --- src/items.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7f8980dd150..44d8889d832 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2040,18 +2040,16 @@ fn rewrite_fn_base( let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); // Put the closing brace on the next line if it overflows the max width. // 1 = `)` - if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() { - result.push('\n'); - } + let closing_paren_overflow_max_width = + fd.inputs.is_empty() && used_width + 1 > context.config.max_width(); // If the last line of args contains comment, we cannot put the closing paren // on the same line. - if arg_str + args_last_line_contains_comment = arg_str .lines() .last() - .map_or(false, |last_line| last_line.contains("//")) - { - args_last_line_contains_comment = true; - result.push_str(&arg_indent.to_string_with_newline(context.config)); + .map_or(false, |last_line| last_line.contains("//")); + if closing_paren_overflow_max_width || args_last_line_contains_comment { + result.push_str(&indent.to_string_with_newline(context.config)); } result.push(')'); } -- cgit 1.4.1-3-g733a5 From e06f16a0a50a2b100b0a691cdec791f2a362f3fd Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 11 Sep 2018 13:52:46 +0900 Subject: Cargo update --- Cargo.lock | 268 +++++++++++++++++++++++++++++++++++----------------------- Cargo.toml | 6 +- src/macros.rs | 17 ++-- 3 files changed, 174 insertions(+), 117 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 3199f7b0de3..4be9518491a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ dependencies = [ "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -54,7 +54,7 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -75,14 +75,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -90,6 +90,14 @@ name = "cfg-if" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "colored" version = "1.6.1" @@ -134,7 +142,7 @@ name = "derive-new" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -159,7 +167,7 @@ name = "ena" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -169,8 +177,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -201,7 +209,7 @@ name = "failure_derive" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -239,9 +247,10 @@ dependencies = [ [[package]] name = "isatty" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -257,7 +266,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -273,9 +282,18 @@ name = "libc" version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lock_api" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -317,11 +335,11 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.5.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -335,9 +353,21 @@ dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" -version = "0.4.16" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -353,7 +383,7 @@ name = "quote" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -366,6 +396,23 @@ dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "redox_syscall" version = "0.1.40" @@ -381,7 +428,7 @@ dependencies = [ [[package]] name = "regex" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -401,33 +448,34 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -437,31 +485,32 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -469,29 +518,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "246.0.0" +version = "253.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -530,6 +579,14 @@ dependencies = [ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustfmt-nightly" version = "0.99.4" @@ -541,17 +598,17 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -578,7 +635,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -588,27 +645,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -629,7 +686,17 @@ name = "syn" version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -639,7 +706,7 @@ name = "synstructure" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -654,14 +721,6 @@ dependencies = [ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "termcolor" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "termcolor" version = "1.0.3" @@ -693,7 +752,7 @@ name = "toml" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -766,14 +825,6 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "wincolor" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "wincolor" version = "1.0.1" @@ -793,8 +844,9 @@ dependencies = [ "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" -"checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131" +"checksum cc 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "70f2a88c2e69ceee91c209d8ef25b81fc1a65f42c7f14dfd59d1fed189e514d1" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum colored 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc0a60679001b62fb628c4da80e574b9645ab4646056d7c9018885efffe45533" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" @@ -813,53 +865,58 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6c324313540cd4d7ba008d43dc6606a32a5579f13cc17b2804c13096f0a5c522" +"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" -"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" -"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" +"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54" +"checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" "checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" +"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" -"checksum proc-macro2 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "37460f858ac0db19bceb2585494de611c9d8618062e6da2994a211b600cc4fc9" +"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum proc-macro2 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ffe022fb8c8bd254524b0b3305906c1921fa37a84a644e29079a9e62200c3901" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" +"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" +"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" +"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum rustc-ap-arena 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf0d22cdac821e87879daee5f3be1b2f61cd8e8143523ea5983f8a23c1658a22" -"checksum rustc-ap-rustc_cratesio_shim 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f9c4ed8b9175db82421dc1d663faefcf328194365de4a7d6fad87596f21b5b" -"checksum rustc-ap-rustc_data_structures 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "727d8195e549a01d54b9782f5f1ca35989989be9479457ce84f376649cb6af10" -"checksum rustc-ap-rustc_errors 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8462144b3f8600ce583cbcd7840d0244e2ea92d2d858c54c8b8f8fd6addde5e" -"checksum rustc-ap-rustc_target 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79c419f1060e8f279dc10f949a6536a06a807352302988b0ede5277ffe38f00e" -"checksum rustc-ap-serialize 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f8eb12053983063787e16416292ec8fcd4002e7357f53a7b574c35c8ce3604a" -"checksum rustc-ap-syntax 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f93c483e0f6dd28ebf5351e8880487907cac2853fe45c7dbbd426b592449e025" -"checksum rustc-ap-syntax_pos 246.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08155e4f9c79c8604c198a8efca5ddbc75a180a9c66b568b505e8c5e8c480d56" +"checksum rustc-ap-arena 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f71b0c1c25faf669df975d3c66f18e25b35a7ad269c773f4138ad345144db7b" +"checksum rustc-ap-rustc_cratesio_shim 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96d785b5c27a976e894d9b38df4fa206a2ee063a2239a7f096ad7ccf73800f92" +"checksum rustc-ap-rustc_data_structures 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20e56d1c142acbaeb277a08f900c72f757271a3fa8875804c4279b1a930c6332" +"checksum rustc-ap-rustc_errors 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd4be4ed5166faad26c186261724d0445b2a4d94d2ec8b58271c659de92fc735" +"checksum rustc-ap-rustc_target 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e499b324ca1fd9bff89df32b6a6e132bb439a94123b563ef8fe20d1f9f91cd17" +"checksum rustc-ap-serialize 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "592c21d5bc657442b51645e7b9d7ed742730626037b3efdbe7e8ecd4b0c3fcd0" +"checksum rustc-ap-syntax 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2de66ed92e083bb3f7f127b38744c142e9526062333df3b9663f348809fedbf4" +"checksum rustc-ap-syntax_pos 253.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c62e0b11580828baefa992329b143fae536e14d150f57393d5e086fc22bd907" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)" = "d00c69ae39089576cddfd235556e3b21bf41c2d80018063cb5ab8a1183c917fd" -"checksum serde_derive 1.0.76 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8384360683b7114fc6eeeb41dde6ee37eeba2cf3660deef3a7a0d7548e55e9" -"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" +"checksum serde 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)" = "92ec94e2754699adddbbc4f555791bd3acc2a2f5574cba16c93a4a9cf4a04415" +"checksum serde_derive 1.0.78 (registry+https://github.com/rust-lang/crates.io-index)" = "0fb622d85245add5327d4f08b2d24fd51fa5d35fe1bba19ee79a1f211e9ac0ff" +"checksum serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "59790990c5115d16027f00913e2e66de23a51f70422e549d2ad68c8c5f268f1c" "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum syn 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c1514eb7bb4216fc722b3cd08783d326d7de0d62f6d5e48a774f610bc97cb6" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" -"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" "checksum termcolor 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3bac0e465b59f194e7037ed404b0326e56ff234d767edc4c5cc9cd49e7a2c7" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -876,5 +933,4 @@ dependencies = [ "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/Cargo.toml b/Cargo.toml index 3af9c7f0bcf..5e8e90b3750 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,9 +47,9 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.6" -rustc-ap-rustc_target = "246.0.0" -rustc-ap-syntax = "246.0.0" -rustc-ap-syntax_pos = "246.0.0" +rustc-ap-rustc_target = "253.0.0" +rustc-ap-syntax = "253.0.0" +rustc-ap-syntax_pos = "253.0.0" failure = "0.1.1" [dev-dependencies] diff --git a/src/macros.rs b/src/macros.rs index 6aae1b23f0c..8eff489412b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -855,7 +855,7 @@ impl MacroArgParser { self.add_meta_variable(&mut iter)?; } TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t), - TokenTree::Delimited(sp, delimited) => { + TokenTree::Delimited(delimited_span, delimited) => { if !self.buf.is_empty() { if next_space(&self.last_tok) == SpaceState::Always { self.add_separator(); @@ -866,14 +866,15 @@ impl MacroArgParser { // Parse the stuff inside delimiters. let mut parser = MacroArgParser::new(); - parser.lo = sp.lo(); + parser.lo = delimited_span.open.lo(); let delimited_arg = parser.parse(delimited.tts.clone())?; + let span = delimited_span.entire(); if self.is_meta_var { - self.add_repeat(delimited_arg, delimited.delim, &mut iter, *sp)?; + self.add_repeat(delimited_arg, delimited.delim, &mut iter, span)?; self.is_meta_var = false; } else { - self.add_delimited(delimited_arg, delimited.delim, *sp); + self.add_delimited(delimited_arg, delimited.delim, span); } } } @@ -1186,7 +1187,7 @@ impl MacroParser { let tok = self.toks.next()?; let (lo, args_paren_kind) = match tok { TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, ref d) => (sp.lo(), d.delim), + TokenTree::Delimited(delimited_span, ref d) => (delimited_span.open.lo(), d.delim), }; let args = tok.joint().into(); match self.toks.next()? { @@ -1195,12 +1196,12 @@ impl MacroParser { } let (mut hi, body, whole_body) = match self.toks.next()? { TokenTree::Token(..) => return None, - TokenTree::Delimited(sp, _) => { - let data = sp.data(); + TokenTree::Delimited(delimited_span, _) => { + let data = delimited_span.entire().data(); ( data.hi, Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt), - sp, + delimited_span.entire(), ) } }; -- cgit 1.4.1-3-g733a5 From 838df8dfb60e8a17b3b3b43a642da0d8ca9828e2 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 11 Sep 2018 08:41:16 +0300 Subject: Use correct heuristic for match block flattening --- Configurations.md | 4 ++-- src/config/lists.rs | 12 +++++++----- src/expr.rs | 12 +++++++----- src/matches.rs | 14 ++++++-------- 4 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index ae8ea2b3c6d..6fcd0609b65 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1303,7 +1303,7 @@ fn main() { }); match lorem { - None => if ipsum { + None => |ipsum| { println!("Hello World"); }, Some(dolor) => foo(), @@ -1324,7 +1324,7 @@ fn main() { match lorem { None => { - if ipsum { + |ipsum| { println!("Hello World"); } } diff --git a/src/config/lists.rs b/src/config/lists.rs index 61496e21642..9dc3a7e6b0f 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -95,11 +95,13 @@ impl SeparatorPlace { ) -> SeparatorPlace { match tactic { DefinitiveListTactic::Vertical => default, - _ => if sep == "," { - SeparatorPlace::Back - } else { - default - }, + _ => { + if sep == "," { + SeparatorPlace::Back + } else { + default + } + } } } } diff --git a/src/expr.rs b/src/expr.rs index 329081f5d70..fef4a024cf5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -179,11 +179,13 @@ pub fn format_expr( Some(format!("break{}", id_str)) } } - ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape) - } else { - Some("yield".to_string()) - }, + ast::ExprKind::Yield(ref opt_expr) => { + if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, "yield ", &**expr, shape) + } else { + Some("yield".to_string()) + } + } ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( capture, asyncness, movability, fn_decl, body, expr.span, context, shape, diff --git a/src/matches.rs b/src/matches.rs index 9fac170b96c..2295535b121 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -20,7 +20,7 @@ use comment::{combine_strs_with_missing_comments, rewrite_comment}; use config::{Config, ControlBraceStyle, IndentStyle}; use expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, - rewrite_multiple_patterns, ExprType, RhsTactics, ToExpr, + rewrite_multiple_patterns, ExprType, RhsTactics, }; use lists::{itemize_list, write_list, ListFormatting}; use rewrite::{Rewrite, RewriteContext}; @@ -314,23 +314,21 @@ fn block_can_be_flattened<'a>( // @extend: true if the arm body can be put next to `=>` // @body: flattened body, if the body is block with a single expression fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { + let can_extend = + |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); + if let Some(ref block) = block_can_be_flattened(context, body) { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { if let ast::ExprKind::Block(..) = expr.node { flatten_arm_body(context, expr) } else { - let can_extend_expr = - !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); - (can_extend_expr, &*expr) + (can_extend(expr), &*expr) } } else { (false, &*body) } } else { - ( - !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1), - &*body, - ) + (can_extend(body), &*body) } } -- cgit 1.4.1-3-g733a5 From 4b4fb557d7fbe4ecf08d23d6421bed604ba9d8f7 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 11 Sep 2018 11:08:28 +0300 Subject: Fix last chain item shape for Visual indent_style --- src/chains.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3acb8e2eac3..c57a9b49629 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -614,6 +614,12 @@ impl<'a> ChainFormatterShared<'a> { } } + let last_shape = if context.use_block_indent() { + last_shape + } else { + child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)? + }; + last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite(context, last_shape)); self.rewrites.push(last_subexpr_str?); Some(()) -- cgit 1.4.1-3-g733a5 From 60c414c85791d391b33f0a1643d06f172d8706ec Mon Sep 17 00:00:00 2001 From: Pascal Seitz Date: Tue, 11 Sep 2018 10:46:39 +0200 Subject: fixes #2914 by handling BadIssue case --- src/formatting.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index a07cdcc8a14..95dfdefd0e2 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -271,6 +271,7 @@ impl FormattingError { ErrorKind::LineOverflow(found, max) => (max, found - max), ErrorKind::TrailingWhitespace | ErrorKind::DeprecatedAttr + | ErrorKind::BadIssue(_) | ErrorKind::BadAttr | ErrorKind::LostComment => { let trailing_ws_start = self -- cgit 1.4.1-3-g733a5 From 11435c5954b10542745fafc6783401b7e3d9fdaa Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 11 Sep 2018 12:34:33 +0300 Subject: Don't insert a new line when fn has no return type --- src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 3a30f40a591..07794030ba8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -400,7 +400,7 @@ where shape.block().indent.to_string_with_newline(context.config), ) }; - if last_line_width(&args) + first_line_width(&output) <= shape.width { + if output.is_empty() || last_line_width(&args) + first_line_width(&output) <= shape.width { Some(format!("{}{}", args, output)) } else { Some(format!( -- cgit 1.4.1-3-g733a5 From 1befc93ba02e2fff85c985573652147de3b7aab2 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 12 Sep 2018 13:09:07 +0200 Subject: implement Drop from FmtVisitor in order to simplify failures passing --- src/expr.rs | 3 --- src/formatting.rs | 2 +- src/items.rs | 8 -------- src/macros.rs | 5 +---- src/visitor.rs | 22 ++++++++++++++++++++-- 5 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 722898b8150..329081f5d70 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -522,9 +522,6 @@ pub fn rewrite_block_with_visitor( let inner_attrs = attrs.map(inner_attributes); let label_str = rewrite_label(label); visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); - if visitor.macro_rewrite_failure { - context.macro_rewrite_failure.replace(true); - } Some(format!("{}{}{}", prefix, label_str, visitor.buffer)) } diff --git a/src/formatting.rs b/src/formatting.rs index 9386302c479..5ad6cfb653f 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -175,7 +175,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { } self.handler - .handle_formatted_file(path, visitor.buffer, &mut self.report) + .handle_formatted_file(path, visitor.buffer.to_owned(), &mut self.report) } } diff --git a/src/items.rs b/src/items.rs index 9dfc4c584cd..7f8980dd150 100644 --- a/src/items.rs +++ b/src/items.rs @@ -747,10 +747,6 @@ pub fn format_impl( visitor.format_missing(item.span.hi() - BytePos(1)); - if visitor.macro_rewrite_failure { - context.macro_rewrite_failure.replace(true); - } - let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); @@ -1110,10 +1106,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) visitor.format_missing(item.span.hi() - BytePos(1)); - if visitor.macro_rewrite_failure { - context.macro_rewrite_failure.replace(true); - } - let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); diff --git a/src/macros.rs b/src/macros.rs index 6e52b63363d..3f107f81ab2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -69,10 +69,7 @@ impl Rewrite for ast::Item { visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); - if visitor.macro_rewrite_failure { - context.macro_rewrite_failure.replace(true); - } - Some(visitor.buffer) + Some(visitor.buffer.to_owned()) } } diff --git a/src/visitor.rs b/src/visitor.rs index c622de6ef48..f27a399beed 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -60,6 +60,7 @@ impl<'a> SnippetProvider<'a> { } pub struct FmtVisitor<'a> { + parent_context: Option<&'a RewriteContext<'a>>, pub parse_session: &'a ParseSess, pub source_map: &'a SourceMap, pub buffer: String, @@ -75,7 +76,21 @@ pub struct FmtVisitor<'a> { pub(crate) report: FormatReport, } +impl<'a> Drop for FmtVisitor<'a> { + fn drop(&mut self) { + if let Some(ctx) = self.parent_context { + if self.macro_rewrite_failure { + ctx.macro_rewrite_failure.replace(true); + } + } + } +} + impl<'b, 'a: 'b> FmtVisitor<'a> { + fn set_parent_context(&mut self, context: &'a RewriteContext) { + self.parent_context = Some(context); + } + pub fn shape(&self) -> Shape { Shape::indented(self.block_indent, self.config) } @@ -579,12 +594,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { - FmtVisitor::from_source_map( + let mut visitor = FmtVisitor::from_source_map( ctx.parse_session, ctx.config, ctx.snippet_provider, ctx.report.clone(), - ) + ); + visitor.set_parent_context(ctx); + visitor } pub(crate) fn from_source_map( @@ -594,6 +611,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { report: FormatReport, ) -> FmtVisitor<'a> { FmtVisitor { + parent_context: None, parse_session, source_map: parse_session.source_map(), buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), -- cgit 1.4.1-3-g733a5 From 5947ea607c66e383b51db87913880e55509d7d65 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Wed, 12 Sep 2018 21:43:31 +0200 Subject: cargo fmt: fix typo in format_crate(): (verison -> version) --- src/cargo-fmt/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 2d8234ef41e..8a6f038b485 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -149,7 +149,7 @@ fn format_crate( let rustfmt_args = get_fmt_args(); let targets = if rustfmt_args .iter() - .any(|s| ["--print-config", "-h", "--help", "-V", "--verison"].contains(&s.as_str())) + .any(|s| ["--print-config", "-h", "--help", "-V", "--version"].contains(&s.as_str())) { HashSet::new() } else { -- cgit 1.4.1-3-g733a5 From 9f6cf7b72c0b34f66349ad03a801827f6b203e0e Mon Sep 17 00:00:00 2001 From: Rémy Rakic Date: Thu, 13 Sep 2018 00:37:31 +0200 Subject: move config attribute --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index fca4ca98ddd..52401a18d92 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -49,6 +49,7 @@ create_config! { comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; + normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments"; license_template_path: String, String::default(), false, "Beginning of file must match license template"; format_strings: bool, false, false, "Format string literals where necessary"; @@ -107,7 +108,6 @@ create_config! { blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items"; edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)"; - normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; -- cgit 1.4.1-3-g733a5 From 6c96ab7c9a6d2d1824af121022e6e70c639a3b3b Mon Sep 17 00:00:00 2001 From: Rémy Rakic Date: Thu, 13 Sep 2018 01:13:07 +0200 Subject: address review comment in Attribute rewrite fn --- src/attr.rs | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index c7ee633ec4e..f8f6cd1c376 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -351,35 +351,33 @@ impl Rewrite for ast::Attribute { return Some(snippet.to_owned()); } - let meta = self.meta(); - - // This attribute is possibly a doc attribute needing normalization to a doc comment - if context.config.normalize_doc_attributes() { - if let Some(ref meta) = meta { - if meta.check_name("doc") { - if let Some(ref literal) = meta.value_str() { - let comment_style = match self.style { - ast::AttrStyle::Inner => CommentStyle::Doc, - ast::AttrStyle::Outer => CommentStyle::TripleSlash, - }; - - let doc_comment = format!("{}{}", comment_style.opener(), literal); - return rewrite_doc_comment( - &doc_comment, - shape.comment(context.config), - context.config, - ); - } + if let Some(ref meta) = self.meta() { + // This attribute is possibly a doc attribute needing normalization to a doc comment + if context.config.normalize_doc_attributes() && meta.check_name("doc") { + if let Some(ref literal) = meta.value_str() { + let comment_style = match self.style { + ast::AttrStyle::Inner => CommentStyle::Doc, + ast::AttrStyle::Outer => CommentStyle::TripleSlash, + }; + + let doc_comment = format!("{}{}", comment_style.opener(), literal); + return rewrite_doc_comment( + &doc_comment, + shape.comment(context.config), + context.config, + ); } } - } - // 1 = `[` - let shape = shape.offset_left(prefix.len() + 1)?; - Some( - meta.and_then(|meta| meta.rewrite(context, shape)) - .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), - ) + // 1 = `[` + let shape = shape.offset_left(prefix.len() + 1)?; + Some( + meta.rewrite(context, shape) + .map_or_else(|| snippet.to_owned(), |rw| format!("{}[{}]", prefix, rw)), + ) + } else { + Some(snippet.to_owned()) + } } } } -- cgit 1.4.1-3-g733a5 From c3edf6d3a1f72088a4343948f6aafe1fc74a3208 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 17 Sep 2018 23:17:36 +0200 Subject: Fix indent computation of a macro with braces. The leading whitespace of a multine string was taken into account when computing the `min_prefix_space_width`, even if that line couldn't be trimmed. The consequence is it was always shifting the macro's content to the right. --- src/comment.rs | 43 ++++++++---- src/macros.rs | 10 ++- tests/source/issue-2973.rs | 158 +++++++++++++++++++++++++++++++++++++++++++++ tests/target/issue-2973.rs | 158 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 354 insertions(+), 15 deletions(-) create mode 100644 tests/source/issue-2973.rs create mode 100644 tests/target/issue-2973.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index a48012d411e..17ec29c3cbc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -821,6 +821,10 @@ pub enum FullCodeCharKind { InComment, /// Last character of a comment, '\n' for a line comment, '/' for a block comment. EndComment, + /// Start of a mutlitine string + StartString, + /// End of a mutlitine string + EndString, /// Inside a string. InString, } @@ -836,7 +840,7 @@ impl FullCodeCharKind { } pub fn is_string(self) -> bool { - self == FullCodeCharKind::InString + self == FullCodeCharKind::InString || self == FullCodeCharKind::StartString } fn to_codecharkind(self) -> CodeCharKind { @@ -924,17 +928,14 @@ where _ => CharClassesStatus::Normal, // Unreachable } } - CharClassesStatus::LitString => match chr { - '"' => CharClassesStatus::Normal, - '\\' => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitStringEscape - } - _ => { - char_kind = FullCodeCharKind::InString; - CharClassesStatus::LitString + CharClassesStatus::LitString => { + char_kind = FullCodeCharKind::InString; + match chr { + '"' => CharClassesStatus::Normal, + '\\' => CharClassesStatus::LitStringEscape, + _ => CharClassesStatus::LitString, } - }, + } CharClassesStatus::LitStringEscape => { char_kind = FullCodeCharKind::InString; CharClassesStatus::LitString @@ -1052,9 +1053,22 @@ impl<'a> Iterator for LineClasses<'a> { let mut line = String::new(); + let start_class = match self.base.peek() { + Some((kind, _)) => *kind, + None => FullCodeCharKind::Normal, + }; + while let Some((kind, c)) = self.base.next() { - self.kind = kind; if c == '\n' { + self.kind = match (start_class, kind) { + (FullCodeCharKind::Normal, FullCodeCharKind::InString) => { + FullCodeCharKind::StartString + } + (FullCodeCharKind::InString, FullCodeCharKind::Normal) => { + FullCodeCharKind::EndString + } + _ => kind, + }; break; } else { line.push(c); @@ -1227,7 +1241,10 @@ pub fn recover_comment_removed( pub fn filter_normal_code(code: &str) -> String { let mut buffer = String::with_capacity(code.len()); LineClasses::new(code).for_each(|(kind, line)| match kind { - FullCodeCharKind::Normal | FullCodeCharKind::InString => { + FullCodeCharKind::Normal + | FullCodeCharKind::StartString + | FullCodeCharKind::InString + | FullCodeCharKind::EndString => { buffer.push_str(&line); buffer.push('\n'); } diff --git a/src/macros.rs b/src/macros.rs index 8eff489412b..e68a725e15f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1118,6 +1118,7 @@ fn indent_macro_snippet( } else { Some(get_prefix_space_width(context, &line)) }; + let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) { veto_trim = kind.is_string() && !line.ends_with('\\'); trimmed = false; @@ -1126,7 +1127,12 @@ fn indent_macro_snippet( line.trim().to_owned() }; trimmed_lines.push((trimmed, line, prefix_space_width)); - prefix_space_width + + // when computing the minimum, do not consider lines within a string + match kind { + FullCodeCharKind::InString | FullCodeCharKind::EndString => None, + _ => prefix_space_width, + } }).min()?; Some( @@ -1139,7 +1145,7 @@ fn indent_macro_snippet( let new_indent_width = indent.width() + original_indent_width .saturating_sub(min_prefix_space_width); let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line.trim()) + format!("{}{}", new_indent.to_string(context.config), line) } None => String::new(), }, diff --git a/tests/source/issue-2973.rs b/tests/source/issue-2973.rs new file mode 100644 index 00000000000..5256dd7c960 --- /dev/null +++ b/tests/source/issue-2973.rs @@ -0,0 +1,158 @@ +#[cfg(test)] +mod test { + summary_test! { + tokenize_recipe_interpolation_eol, + "foo: # some comment + {{hello}} +", + "foo: \ + {{hello}} \ +{{ahah}}", + "N:#$>^{N}$<.", + } + + summary_test! { + tokenize_strings, + r#"a = "'a'" + '"b"' + "'c'" + '"d"'#echo hello"#, + r#"N="+'+"+'#."#, + } + + summary_test! { + tokenize_recipe_interpolation_eol, + "foo: # some comment + {{hello}} +", + "N:#$>^{N}$<.", + } + + summary_test! { + tokenize_recipe_interpolation_eof, + "foo: # more comments + {{hello}} +# another comment +", + "N:#$>^{N}$<#$.", + } + + summary_test! { + tokenize_recipe_complex_interpolation_expression, + "foo: #lol\n {{a + b + \"z\" + blarg}}", + "N:#$>^{N+N+\"+N}<.", + } + + summary_test! { + tokenize_recipe_multiple_interpolations, + "foo:,#ok\n {{a}}0{{b}}1{{c}}", + "N:,#$>^{N}_{N}_{N}<.", + } + + summary_test! { + tokenize_junk, + "bob + +hello blah blah blah : a b c #whatever + ", + "N$$NNNN:NNN#$.", + } + + summary_test! { + tokenize_empty_lines, + " +# this does something +hello: + asdf + bsdf + + csdf + + dsdf # whatever + +# yolo + ", + "$#$N:$>^_$^_$$^_$$^_$$<#$.", + } + + summary_test! { + tokenize_comment_before_variable, + " +# +A='1' +echo: + echo {{A}} + ", + "$#$N='$N:$>^_{N}$<.", + } + + summary_test! { + tokenize_interpolation_backticks, + "hello:\n echo {{`echo hello` + `echo goodbye`}}", + "N:$>^_{`+`}<.", + } + + summary_test! { + tokenize_assignment_backticks, + "a = `echo hello` + `echo goodbye`", + "N=`+`.", + } + + summary_test! { + tokenize_multiple, + " +hello: + a + b + + c + + d + +# hello +bob: + frank + ", + + "$N:$>^_$^_$$^_$$^_$$<#$N:$>^_$<.", + } + + summary_test! { + tokenize_comment, + "a:=#", + "N:=#." + } + + summary_test! { + tokenize_comment_with_bang, + "a:=#foo!", + "N:=#." + } + + summary_test! { + tokenize_order, + r" +b: a + @mv a b + +a: + @touch F + @touch a + +d: c + @rm c + +c: b + @mv b c", + "$N:N$>^_$$^_$^_$$^_$$^_<.", + } + + summary_test! { + tokenize_parens, + r"((())) )abc(+", + "((())))N(+.", + } + + summary_test! { + crlf_newline, + "#\r\n#asdf\r\n", + "#$#$.", + } +} diff --git a/tests/target/issue-2973.rs b/tests/target/issue-2973.rs new file mode 100644 index 00000000000..86574bd8668 --- /dev/null +++ b/tests/target/issue-2973.rs @@ -0,0 +1,158 @@ +#[cfg(test)] +mod test { + summary_test! { + tokenize_recipe_interpolation_eol, + "foo: # some comment + {{hello}} +", + "foo: \ + {{hello}} \ + {{ahah}}", + "N:#$>^{N}$<.", + } + + summary_test! { + tokenize_strings, + r#"a = "'a'" + '"b"' + "'c'" + '"d"'#echo hello"#, + r#"N="+'+"+'#."#, + } + + summary_test! { + tokenize_recipe_interpolation_eol, + "foo: # some comment + {{hello}} +", + "N:#$>^{N}$<.", + } + + summary_test! { + tokenize_recipe_interpolation_eof, + "foo: # more comments + {{hello}} +# another comment +", + "N:#$>^{N}$<#$.", + } + + summary_test! { + tokenize_recipe_complex_interpolation_expression, + "foo: #lol\n {{a + b + \"z\" + blarg}}", + "N:#$>^{N+N+\"+N}<.", + } + + summary_test! { + tokenize_recipe_multiple_interpolations, + "foo:,#ok\n {{a}}0{{b}}1{{c}}", + "N:,#$>^{N}_{N}_{N}<.", + } + + summary_test! { + tokenize_junk, + "bob + +hello blah blah blah : a b c #whatever + ", + "N$$NNNN:NNN#$.", + } + + summary_test! { + tokenize_empty_lines, + " +# this does something +hello: + asdf + bsdf + + csdf + + dsdf # whatever + +# yolo + ", + "$#$N:$>^_$^_$$^_$$^_$$<#$.", + } + + summary_test! { + tokenize_comment_before_variable, + " +# +A='1' +echo: + echo {{A}} + ", + "$#$N='$N:$>^_{N}$<.", + } + + summary_test! { + tokenize_interpolation_backticks, + "hello:\n echo {{`echo hello` + `echo goodbye`}}", + "N:$>^_{`+`}<.", + } + + summary_test! { + tokenize_assignment_backticks, + "a = `echo hello` + `echo goodbye`", + "N=`+`.", + } + + summary_test! { + tokenize_multiple, + " +hello: + a + b + + c + + d + +# hello +bob: + frank + ", + + "$N:$>^_$^_$$^_$$^_$$<#$N:$>^_$<.", + } + + summary_test! { + tokenize_comment, + "a:=#", + "N:=#." + } + + summary_test! { + tokenize_comment_with_bang, + "a:=#foo!", + "N:=#." + } + + summary_test! { + tokenize_order, + r" +b: a + @mv a b + +a: + @touch F + @touch a + +d: c + @rm c + +c: b + @mv b c", + "$N:N$>^_$$^_$^_$$^_$$^_<.", + } + + summary_test! { + tokenize_parens, + r"((())) )abc(+", + "((())))N(+.", + } + + summary_test! { + crlf_newline, + "#\r\n#asdf\r\n", + "#$#$.", + } +} -- cgit 1.4.1-3-g733a5 From d165533813b9b001afd78578c2a648efd393d6fb Mon Sep 17 00:00:00 2001 From: Nathan Sutton Date: Tue, 18 Sep 2018 06:20:07 -0500 Subject: Improve error message when failing cargo metadata (#3024) --- src/cargo-fmt/main.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 8a6f038b485..1ce5ef2fce8 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -373,9 +373,6 @@ fn run_rustfmt( fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { match cargo_metadata::metadata(manifest_path) { Ok(metadata) => Ok(metadata), - Err(..) => Err(io::Error::new( - io::ErrorKind::Other, - "`cargo manifest` failed.", - )), + Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())), } } -- cgit 1.4.1-3-g733a5 From 7eca33f8a53ddf0184d98b1808d953af072c1713 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 19 Sep 2018 22:33:10 +0900 Subject: Format generics on associated types --- src/items.rs | 13 ++++++++++--- src/visitor.rs | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 44d8889d832..d1522d46481 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1715,11 +1715,16 @@ fn rewrite_static( pub fn rewrite_associated_type( ident: ast::Ident, ty_opt: Option<&ptr::P>, + generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, context: &RewriteContext, indent: Indent, ) -> Option { - let prefix = format!("type {}", rewrite_ident(context, ident)); + let ident_str = rewrite_ident(context, ident); + // 5 = "type " + let generics_shape = Shape::indented(indent, context.config).offset_left(5)?; + let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?; + let prefix = format!("type {}", generics_str); let type_bounds_str = if let Some(bounds) = generic_bounds_opt { if bounds.is_empty() { @@ -1746,10 +1751,11 @@ pub fn rewrite_associated_type( pub fn rewrite_existential_impl_type( context: &RewriteContext, ident: ast::Ident, + generics: &ast::Generics, generic_bounds: &ast::GenericBounds, indent: Indent, ) -> Option { - rewrite_associated_type(ident, None, Some(generic_bounds), context, indent) + rewrite_associated_type(ident, None, generics, Some(generic_bounds), context, indent) .map(|s| format!("existential {}", s)) } @@ -1757,10 +1763,11 @@ pub fn rewrite_associated_impl_type( ident: ast::Ident, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, + generics: &ast::Generics, context: &RewriteContext, indent: Indent, ) -> Option { - let result = rewrite_associated_type(ident, ty_opt, None, context, indent)?; + let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?; match defaultness { ast::Defaultness::Default => Some(format!("default {}", result)), diff --git a/src/visitor.rs b/src/visitor.rs index f27a399beed..4591ff720a5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -497,6 +497,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite = rewrite_associated_type( ti.ident, type_default.as_ref(), + &ti.generics, Some(generic_bounds), &self.get_context(), self.block_indent, @@ -535,6 +536,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ii.ident, ii.defaultness, Some(ty), + &ii.generics, &self.get_context(), self.block_indent, ); @@ -544,6 +546,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite = rewrite_existential_impl_type( &self.get_context(), ii.ident, + &ii.generics, generic_bounds, self.block_indent, ); -- cgit 1.4.1-3-g733a5 From 76650174c70ca443936d2187a2edecff6dbd5d25 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 19 Sep 2018 23:20:43 +0900 Subject: Combine chain items only when the item will get orphaned --- src/chains.rs | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index c57a9b49629..56bd8574fc9 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -80,7 +80,6 @@ use utils::{ use std::borrow::Cow; use std::cmp::min; -use std::iter; use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; @@ -132,8 +131,8 @@ impl ChainItemKind { fn is_block_like(&self, context: &RewriteContext, reps: &str) -> bool { match self { ChainItemKind::Parent(ref expr) => is_block_expr(context, expr, reps), - ChainItemKind::MethodCall(..) => reps.contains('\n'), - ChainItemKind::StructField(..) + ChainItemKind::MethodCall(..) + | ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) | ChainItemKind::Comment(..) => false, } @@ -625,12 +624,7 @@ impl<'a> ChainFormatterShared<'a> { Some(()) } - fn join_rewrites( - &self, - context: &RewriteContext, - child_shape: Shape, - block_like_iter: impl Iterator, - ) -> Option { + fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { let connector = if self.fits_single_line { // Yay, we can put everything on one line. Cow::from("") @@ -645,17 +639,13 @@ impl<'a> ChainFormatterShared<'a> { let mut rewrite_iter = self.rewrites.iter(); let mut result = rewrite_iter.next().unwrap().clone(); let children_iter = self.children.iter(); - let iter = rewrite_iter.zip(block_like_iter).zip(children_iter); + let iter = rewrite_iter.zip(children_iter); - for ((rewrite, prev_is_block_like), chain_item) in iter { + for (rewrite, chain_item) in iter { match chain_item.kind { ChainItemKind::Comment(_, CommentPosition::Back) => result.push(' '), ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector), - _ => { - if !prev_is_block_like { - result.push_str(&connector); - } - } + _ => result.push_str(&connector), } result.push_str(&rewrite); } @@ -667,15 +657,14 @@ impl<'a> ChainFormatterShared<'a> { // Formats a chain using block indent. struct ChainFormatterBlock<'a> { shared: ChainFormatterShared<'a>, - // For each rewrite, whether the corresponding item is block-like. - is_block_like: Vec, + root_ends_with_block: bool, } impl<'a> ChainFormatterBlock<'a> { fn new(chain: &'a Chain) -> ChainFormatterBlock<'a> { ChainFormatterBlock { shared: ChainFormatterShared::new(chain), - is_block_like: Vec::with_capacity(chain.children.len() + 1), + root_ends_with_block: false, } } } @@ -703,21 +692,21 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { None => break, } - root_ends_with_block = item.kind.is_block_like(context, &root_rewrite); + root_ends_with_block = last_line_extendable(&root_rewrite); self.shared.children = &self.shared.children[1..]; if self.shared.children.is_empty() { break; } } - self.is_block_like.push(root_ends_with_block); self.shared.rewrites.push(root_rewrite); + self.root_ends_with_block = root_ends_with_block; Some(()) } fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option { Some( - if self.is_block_like[0] { + if self.root_ends_with_block { shape.block_indent(0) } else { shape.block_indent(context.config.tab_spaces()) @@ -728,8 +717,6 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { for item in &self.shared.children[..self.shared.children.len() - 1] { let rewrite = item.rewrite(context, child_shape)?; - self.is_block_like - .push(item.kind.is_block_like(context, &rewrite)); self.shared.rewrites.push(rewrite); } Some(()) @@ -746,8 +733,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { } fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { - self.shared - .join_rewrites(context, child_shape, self.is_block_like.iter().cloned()) + self.shared.join_rewrites(context, child_shape) } fn pure_root(&mut self) -> Option { @@ -841,8 +827,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { - self.shared - .join_rewrites(context, child_shape, iter::repeat(false)) + self.shared.join_rewrites(context, child_shape) } fn pure_root(&mut self) -> Option { -- cgit 1.4.1-3-g733a5 From d4f7e219dcd74989f695fe261534cc8fef5b1477 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 19 Sep 2018 23:21:07 +0900 Subject: Fix shape for index --- src/expr.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index fef4a024cf5..a5d1cdd5583 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1486,7 +1486,12 @@ fn rewrite_index( .offset_left(offset) .and_then(|shape| shape.sub_width(1 + rhs_overhead)) } else { - shape.visual_indent(offset).sub_width(offset + 1) + match context.config.indent_style() { + IndentStyle::Block => shape + .offset_left(offset) + .and_then(|shape| shape.sub_width(1)), + IndentStyle::Visual => shape.visual_indent(offset).sub_width(offset + 1), + } }; let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); -- cgit 1.4.1-3-g733a5 From e2b9c66cc9d3228339d07cb5410f6cabdac97de8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 19 Sep 2018 23:22:26 +0900 Subject: Cargo fmt --- src/attr.rs | 3 ++- src/bin/main.rs | 3 ++- src/cargo-fmt/main.rs | 3 ++- src/chains.rs | 6 ++++-- src/closures.rs | 9 ++++++--- src/comment.rs | 12 ++++++++---- src/config/file_lines.rs | 3 ++- src/config/options.rs | 3 ++- src/expr.rs | 9 ++++++--- src/formatting.rs | 3 ++- src/git-rustfmt/main.rs | 3 ++- src/imports.rs | 12 ++++++++---- src/items.rs | 15 ++++++++++----- src/macros.rs | 15 ++++++++++----- src/overflow.rs | 15 ++++++++++----- src/pairs.rs | 3 ++- src/patterns.rs | 3 ++- src/reorder.rs | 6 ++++-- src/rustfmt_diff.rs | 3 ++- src/test/mod.rs | 9 ++++++--- src/types.rs | 3 ++- src/vertical.rs | 9 ++++++--- src/visitor.rs | 3 ++- 23 files changed, 102 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index f8f6cd1c376..aa1517167d8 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -229,7 +229,8 @@ impl Rewrite for ast::MetaItem { None, &inner_meta_item.ident, shape, - ).map_or(false, |s| s.len() + path.len() + 2 <= shape.width), + ) + .map_or(false, |s| s.len() + path.len() + 2 <= shape.width), _ => false, } } diff --git a/src/bin/main.rs b/src/bin/main.rs index 7069733cae1..8676e6290e0 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -421,7 +421,8 @@ fn determine_operation(matches: &Matches) -> Result { // we will do comparison later, so here tries to canonicalize first // to get the expected behavior. p.canonicalize().unwrap_or(p) - }).collect(); + }) + .collect(); Ok(Operation::Format { files, diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 1ce5ef2fce8..eee102b6bf8 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -163,7 +163,8 @@ fn format_crate( if verbosity == Verbosity::Verbose { println!("[{}] {:?}", t.kind, t.path) } - }).map(|t| t.path) + }) + .map(|t| t.path) .collect(); run_rustfmt(&files, &rustfmt_args, verbosity) diff --git a/src/chains.rs b/src/chains.rs index 56bd8574fc9..36c89eef20d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -558,7 +558,8 @@ impl<'a> ChainFormatterShared<'a> { shape.width } else { min(shape.width, context.config.width_heuristics().chain_width) - }.saturating_sub(almost_total); + } + .saturating_sub(almost_total); let all_in_one_line = !self.children.iter().any(ChainItem::is_comment) && self.rewrites.iter().all(|s| !s.contains('\n')) @@ -710,7 +711,8 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { shape.block_indent(0) } else { shape.block_indent(context.config.tab_spaces()) - }.with_max_width(context.config), + } + .with_max_width(context.config), ) } diff --git a/src/closures.rs b/src/closures.rs index 3451fcfe6f4..9546451d7ca 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -198,7 +198,8 @@ fn rewrite_closure_expr( } else { Some(rw) } - }).map(|rw| format!("{} {}", prefix, rw)) + }) + .map(|rw| format!("{} {}", prefix, rw)) } // Rewrite closure whose body is block. @@ -367,8 +368,10 @@ where .map(|e| match e.node { ast::ExprKind::Closure(..) => true, _ => false, - }).unwrap_or(false) - }).count() + }) + .unwrap_or(false) + }) + .count() > 1 } diff --git a/src/comment.rs b/src/comment.rs index 17ec29c3cbc..e79b9011cbf 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -370,7 +370,8 @@ fn rewrite_comment_inner( } line - }).map(|s| left_trim_comment_line(s, &style)) + }) + .map(|s| left_trim_comment_line(s, &style)) .map(|(line, has_leading_whitespace)| { if orig.starts_with("/*") && line_breaks == 0 { ( @@ -542,7 +543,8 @@ fn trim_custom_comment_prefix(s: &str) -> String { } else { line } - }).collect::>() + }) + .collect::>() .join("\n") } @@ -630,7 +632,8 @@ fn light_rewrite_comment( }; // Preserve markdown's double-space line break syntax in doc comment. trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) - }).collect(); + }) + .collect(); Some(lines.join(&format!("\n{}", offset.to_string(config)))) } @@ -1455,7 +1458,8 @@ mod test { .filter_map(|(s, c)| match s { FullCodeCharKind::Normal | FullCodeCharKind::InString => Some(c), _ => None, - }).collect() + }) + .collect() } #[test] diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index e113118c643..84ab0a8fc07 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -216,7 +216,8 @@ impl FileLines { .map(|(file, range)| JsonSpan { file: file.to_owned(), range: (range.lo, range.hi), - }).collect(), + }) + .collect(), } } diff --git a/src/config/options.rs b/src/config/options.rs index e1aec1ddea9..7dca87e1777 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -394,7 +394,8 @@ impl IgnoreList { path.push(s); path } - }).collect(); + }) + .collect(); } fn skip_file_inner(&self, file: &Path) -> bool { diff --git a/src/expr.rs b/src/expr.rs index a5d1cdd5583..674f719b5c7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1029,7 +1029,8 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) + ) + .rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if( @@ -1040,7 +1041,8 @@ impl<'a> Rewrite for ControlFlow<'a> { false, true, mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) + ) + .rewrite(context, shape) } _ => { last_in_chain = true; @@ -1237,7 +1239,8 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt new_indent.to_string(context.config), line.trim_left() ) - }).collect::>() + }) + .collect::>() .join("\n") .trim_left(), ); diff --git a/src/formatting.rs b/src/formatting.rs index 90fb5899098..d940c35f1c7 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -240,7 +240,8 @@ impl FormattingError { fl.file .get_line(fl.lines[0].line_index) .map(|l| l.into_owned()) - }).unwrap_or_else(String::new), + }) + .unwrap_or_else(String::new), } } diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 0042ff353a7..4ad004d3a8b 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -46,7 +46,8 @@ fn prune_files(files: Vec<&str>) -> Vec<&str> { return true; } pruned_prefixes.iter().all(|pp| !f.starts_with(pp)) - }).collect() + }) + .collect() } fn git_diff(commits: &str) -> String { diff --git a/src/imports.rs b/src/imports.rs index 3ca063a58e7..962d82868d7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -44,7 +44,8 @@ impl<'a> FmtVisitor<'a> { Some(item.vis.clone()), Some(item.span.lo()), Some(item.attrs.clone()), - ).rewrite_top_level(&self.get_context(), shape); + ) + .rewrite_top_level(&self.get_context(), shape); match rw { Some(ref s) if s.is_empty() => { // Format up to last newline @@ -291,7 +292,8 @@ impl UseTree { } else { Some(item.attrs.clone()) }, - ).normalize(), + ) + .normalize(), ), _ => None, } @@ -345,13 +347,15 @@ impl UseTree { context.snippet_provider.span_after(a.span, "{"), a.span.hi(), false, - ).collect(); + ) + .collect(); result.path.push(UseSegment::List( list.iter() .zip(items.into_iter()) .map(|(t, list_item)| { Self::from_ast(context, &t.0, Some(list_item), None, None, None) - }).collect(), + }) + .collect(), )); } UseTreeKind::Simple(ref rename, ..) => { diff --git a/src/items.rs b/src/items.rs index 44d8889d832..18b43972051 100644 --- a/src/items.rs +++ b/src/items.rs @@ -460,7 +460,8 @@ impl<'a> FmtVisitor<'a> { self.block_indent, mk_sp(span.lo(), body_start), last_line_width(&enum_header), - ).unwrap(); + ) + .unwrap(); self.push_str(&generics_str); self.last_pos = body_start; @@ -517,7 +518,8 @@ impl<'a> FmtVisitor<'a> { body_lo, body_hi, false, - ).collect() + ) + .collect() }; let mut items: Vec<_> = itemize_list_with(self.config.width_heuristics().struct_variant_width); @@ -1705,7 +1707,8 @@ fn rewrite_static( lhs, &**expr, Shape::legacy(remaining_width, offset.block_only()), - ).and_then(|res| recover_comment_removed(res, static_parts.span, context)) + ) + .and_then(|res| recover_comment_removed(res, static_parts.span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{}{};", prefix, ty_str)) @@ -2233,7 +2236,8 @@ fn rewrite_args( .map(|arg| { arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) .unwrap_or_else(|| context.snippet(arg.span()).to_owned()) - }).collect::>(); + }) + .collect::>(); // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked @@ -2815,7 +2819,8 @@ impl Rewrite for ast::ForeignItem { span, false, false, - ).map(|(s, _)| format!("{};", s)), + ) + .map(|(s, _)| format!("{};", s)), ast::ForeignItemKind::Static(ref ty, is_mutable) => { // FIXME(#21): we're dropping potential comments in between the // function keywords here. diff --git a/src/macros.rs b/src/macros.rs index 736333cf44d..282519286fa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -287,7 +287,8 @@ pub fn rewrite_macro_inner( } else { Some(SeparatorTactic::Never) }, - ).map(|rw| match position { + ) + .map(|rw| match position { MacroPosition::Item => format!("{};", rw), _ => rw, }) @@ -418,7 +419,8 @@ pub fn rewrite_macro_def( context.snippet_provider.span_after(span, "{"), span.hi(), false, - ).collect::>(); + ) + .collect::>(); let fmt = ListFormatting::new(arm_shape, context.config) .separator(if def.legacy { ";" } else { "" }) @@ -1141,7 +1143,8 @@ fn indent_macro_snippet( FullCodeCharKind::InString | FullCodeCharKind::EndString => None, _ => prefix_space_width, } - }).min()?; + }) + .min()?; Some( first_line + "\n" + &trimmed_lines @@ -1157,7 +1160,8 @@ fn indent_macro_snippet( } None => String::new(), }, - ).collect::>() + ) + .collect::>() .join("\n"), ) } @@ -1322,7 +1326,8 @@ impl MacroBranch { } (s + l + "\n", !kind.is_string() || l.ends_with('\\')) }, - ).0; + ) + .0; // Undo our replacement of macro variables. // FIXME: this could be *much* more efficient. diff --git a/src/overflow.rs b/src/overflow.rs index 674eb14b677..acf6d7b4d38 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -52,7 +52,8 @@ where item_max_width, force_separator_tactic, None, - ).rewrite(shape) + ) + .rewrite(shape) } pub fn rewrite_with_angle_brackets( @@ -76,7 +77,8 @@ where context.config.max_width(), None, None, - ).rewrite(shape) + ) + .rewrite(shape) } pub fn rewrite_with_square_brackets( @@ -107,7 +109,8 @@ where context.config.width_heuristics().array_width, force_separator_tactic, Some(("[", "]")), - ).rewrite(shape) + ) + .rewrite(shape) } struct Context<'a, T: 'a> { @@ -242,7 +245,8 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { list_items, self.one_line_shape, self.item_max_width, - ).and_then(|arg_shape| { + ) + .and_then(|arg_shape| { self.rewrite_last_item_with_overflow( &mut list_items[self.items.len() - 1], arg_shape, @@ -495,7 +499,8 @@ where Shape { width: min(args_max_width, shape.width), ..shape - }.offset_left(offset) + } + .offset_left(offset) } fn shape_from_indent_style( diff --git a/src/pairs.rs b/src/pairs.rs index 17b86975022..f078022b9e0 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -124,7 +124,8 @@ fn rewrite_pairs_multiline( let nested_shape = (match context.config.indent_style() { IndentStyle::Visual => shape.visual_indent(0), IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), - }).with_max_width(&context.config) + }) + .with_max_width(&context.config) .sub_width(rhs_offset)?; let indent_str = nested_shape.indent.to_string_with_newline(context.config); diff --git a/src/patterns.rs b/src/patterns.rs index d5c4802904b..13fea046aaf 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -397,7 +397,8 @@ fn count_wildcard_suffix_len( context.snippet_provider.span_after(span, "("), span.hi() - BytePos(1), false, - ).collect(); + ) + .collect(); for item in items.iter().rev().take_while(|i| match i.item { Some(ref internal_string) if internal_string == "_" => true, diff --git a/src/reorder.rs b/src/reorder.rs index 47aae3bfc2a..f990e686565 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -140,7 +140,8 @@ fn rewrite_reorderable_items( .map(|use_tree| ListItem { item: use_tree.rewrite_top_level(context, nested_shape), ..use_tree.list_item.unwrap_or_else(ListItem::empty) - }).collect(); + }) + .collect(); wrap_reorderable_items(context, &item_vec, nested_shape) } @@ -237,7 +238,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { last = current; in_same_group }) - }).count(); + }) + .count(); let items = &items[..item_length]; let at_least_one_in_file_lines = items diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 4e0ac31e312..dbe1c05406a 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -207,7 +207,8 @@ where out, "{} {} {}", mismatch.line_number_orig, num_removed, num_added - ).unwrap(); + ) + .unwrap(); for line in mismatch.lines { match line { diff --git a/src/test/mod.rs b/src/test/mod.rs index f7848dfd737..a9015cedf6a 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -514,7 +514,8 @@ fn read_significant_comments(file_name: &Path) -> HashMap { .to_owned(), ) }) - }).collect() + }) + .collect() } // Compare output to input. @@ -882,7 +883,8 @@ fn configuration_snippet_tests() { let mut file_iter = BufReader::new( fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), - ).lines() + ) + .lines() .map(|l| l.unwrap()) .enumerate(); let mut code_blocks: Vec = Vec::new(); @@ -970,6 +972,7 @@ fn verify_check_works() { rustfmt().to_str().unwrap(), "--check", temp_file.path.to_str().unwrap(), - ]).succeeds() + ]) + .succeeds() .unwrap(); } diff --git a/src/types.rs b/src/types.rs index 07794030ba8..5f71dd6bdc4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -844,7 +844,8 @@ fn rewrite_lifetime_param( .filter(|p| match p.kind { ast::GenericParamKind::Lifetime => true, _ => false, - }).map(|lt| lt.rewrite(context, shape)) + }) + .map(|lt| lt.rewrite(context, shape)) .collect::>>()? .join(", "); if result.is_empty() { diff --git a/src/vertical.rs b/src/vertical.rs index 3f533920106..d18fa4b9b75 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -200,12 +200,14 @@ fn struct_field_prefix_max_min_width( Some(field_str.len()) } }) - }).fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { + }) + .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { (Some((max_len, min_len)), Some(len)) => { Some((cmp::max(max_len, len), cmp::min(min_len, len))) } _ => None, - }).unwrap_or((0, 0)) + }) + .unwrap_or((0, 0)) } fn rewrite_aligned_items_inner( @@ -236,7 +238,8 @@ fn rewrite_aligned_items_inner( span.lo(), span.hi(), false, - ).collect::>(); + ) + .collect::>(); let tactic = definitive_tactic( &items, diff --git a/src/visitor.rs b/src/visitor.rs index f27a399beed..ba87efb5052 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -158,7 +158,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item.attrs.first() } else { first_stmt.attrs().first() - }.and_then(|attr| { + } + .and_then(|attr| { // Some stmts can have embedded attributes. // e.g. `match { #![attr] ... }` let attr_lo = attr.span.lo(); -- cgit 1.4.1-3-g733a5 From f70d139f9c2ceac9bb31e917c073a9643a0e6f8b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 21 Sep 2018 00:58:47 +0900 Subject: Do not trim a block from expression if its condition will go multi-line --- src/matches.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 2295535b121..a143c20f4bf 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -19,7 +19,7 @@ use syntax::{ast, ptr}; use comment::{combine_strs_with_missing_comments, rewrite_comment}; use config::{Config, ControlBraceStyle, IndentStyle}; use expr::{ - format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, + format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, rewrite_multiple_patterns, ExprType, RhsTactics, }; use lists::{itemize_list, write_list, ListFormatting}; @@ -231,7 +231,7 @@ fn rewrite_match_arm( ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { - let (_, body) = flatten_arm_body(context, &arm.body); + let (_, body) = flatten_arm_body(context, &arm.body, None); // `arm.span()` does not include trailing comma, add it manually. return Some(format!( "{}{}", @@ -313,16 +313,27 @@ fn block_can_be_flattened<'a>( // (extend, body) // @extend: true if the arm body can be put next to `=>` // @body: flattened body, if the body is block with a single expression -fn flatten_arm_body<'a>(context: &'a RewriteContext, body: &'a ast::Expr) -> (bool, &'a ast::Expr) { +fn flatten_arm_body<'a>( + context: &'a RewriteContext, + body: &'a ast::Expr, + opt_shape: Option, +) -> (bool, &'a ast::Expr) { let can_extend = |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); if let Some(ref block) = block_can_be_flattened(context, body) { if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { if let ast::ExprKind::Block(..) = expr.node { - flatten_arm_body(context, expr) + flatten_arm_body(context, expr, None) } else { - (can_extend(expr), &*expr) + let cond_becomes_muti_line = opt_shape + .and_then(|shape| rewrite_cond(context, expr, shape)) + .map_or(false, |cond| cond.contains('\n')); + if cond_becomes_muti_line { + (false, &*body) + } else { + (can_extend(expr), &*expr) + } } } else { (false, &*body) @@ -341,7 +352,11 @@ fn rewrite_match_body( arrow_span: Span, is_last: bool, ) -> Option { - let (extend, body) = flatten_arm_body(context, body); + let (extend, body) = flatten_arm_body( + context, + body, + shape.offset_left(extra_offset(pats_str, shape) + 4), + ); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.node { ( true, -- cgit 1.4.1-3-g733a5 From 98a0ef2436d70bdbb7283f3816e7cc08825a369c Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Fri, 21 Sep 2018 18:46:35 +0100 Subject: Fix bug in import where two consecutive module separators were possible. Fixes #3043. --- src/imports.rs | 6 +++++- tests/target/issue-3043.rs | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-3043.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 962d82868d7..f4751eb117b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -324,11 +324,15 @@ impl UseTree { && a.prefix.to_string().len() > 2 && a.prefix.to_string().starts_with("::"); + let mut modsep = leading_modsep; + for p in &a.prefix.segments { - if let Some(use_segment) = UseSegment::from_path_segment(context, p, leading_modsep) { + if let Some(use_segment) = UseSegment::from_path_segment(context, p, modsep) { result.path.push(use_segment); + modsep = false; } } + match a.kind { UseTreeKind::Glob => { result.path.push(UseSegment::Glob); diff --git a/tests/target/issue-3043.rs b/tests/target/issue-3043.rs new file mode 100644 index 00000000000..b54e244a401 --- /dev/null +++ b/tests/target/issue-3043.rs @@ -0,0 +1,5 @@ +// rustfmt-edition: 2018 + +use ::std::vec::Vec; + +fn main() {} -- cgit 1.4.1-3-g733a5 From 5fdb6db1363782ee2fa7aee82a3cf564c1b3ecaf Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 22 Sep 2018 00:09:11 +0200 Subject: Prevent right-shifting of block comments with bare lines. Lines that didn't start with a comment sigil were returned unchanged in comment::rewrite_comment. Then these unchanged lines were indented in MacroBranch::rewrite. --- src/comment.rs | 265 ++++++++++++++++++++++++--------- tests/source/issue-2917/packed_simd.rs | 63 ++++++++ tests/target/issue-2896.rs | 34 ++--- tests/target/issue-2917/minimal.rs | 8 + tests/target/issue-2917/packed_simd.rs | 63 ++++++++ 5 files changed, 345 insertions(+), 88 deletions(-) create mode 100644 tests/source/issue-2917/packed_simd.rs create mode 100644 tests/target/issue-2917/minimal.rs create mode 100644 tests/target/issue-2917/packed_simd.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e79b9011cbf..60fa7e891f7 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -52,6 +52,27 @@ fn custom_opener(s: &str) -> &str { } impl<'a> CommentStyle<'a> { + /// Returns true if the commenting style covers a line only. + pub fn is_line_comment(&self) -> bool { + match *self { + CommentStyle::DoubleSlash + | CommentStyle::TripleSlash + | CommentStyle::Doc + | CommentStyle::Custom(_) => true, + _ => false, + } + } + + /// Returns true if the commenting style can span over multiple lines. + pub fn is_block_comment(&self) -> bool { + match *self { + CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation => { + true + } + _ => false, + } + } + pub fn is_doc_comment(&self) -> bool { match *self { CommentStyle::TripleSlash | CommentStyle::Doc => true, @@ -213,7 +234,7 @@ pub fn combine_strs_with_missing_comments( } pub fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { - _rewrite_comment(orig, false, shape, config, true) + identify_comment(orig, false, shape, config, true) } pub fn rewrite_comment( @@ -222,32 +243,7 @@ pub fn rewrite_comment( shape: Shape, config: &Config, ) -> Option { - _rewrite_comment(orig, block_style, shape, config, false) -} - -fn _rewrite_comment( - orig: &str, - block_style: bool, - shape: Shape, - config: &Config, - is_doc_comment: bool, -) -> Option { - // If there are lines without a starting sigil, we won't format them correctly - // so in that case we won't even re-align (if !config.normalize_comments()) and - // we should stop now. - let num_bare_lines = orig - .lines() - .map(|line| line.trim()) - .filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))) - .count(); - if num_bare_lines > 0 && !config.normalize_comments() { - return Some(orig.to_owned()); - } - if !config.normalize_comments() && !config.wrap_comments() { - return light_rewrite_comment(orig, shape.indent, config, is_doc_comment); - } - - identify_comment(orig, block_style, shape, config, is_doc_comment) + identify_comment(orig, block_style, shape, config, false) } fn identify_comment( @@ -258,8 +254,8 @@ fn identify_comment( is_doc_comment: bool, ) -> Option { let style = comment_style(orig, false); - let mut first_group_ending = 0; + // Computes the len of line taking into account a newline if the line is part of a paragraph. fn compute_len(orig: &str, line: &str) -> usize { if orig.len() > line.len() { if orig.as_bytes()[line.len()] == b'\r' { @@ -272,62 +268,145 @@ fn identify_comment( } } - match style { + // Get the first group of line comments having the same commenting style. + // + // Returns a tuple with: + // - a boolean indicating if there is a blank line + // - a number indicating the size of the first group of comments + fn consume_same_line_comments( + style: CommentStyle, + orig: &str, + line_start: &str, + ) -> (bool, usize) { + let mut first_group_ending = 0; + let mut hbl = false; + + for line in orig.lines() { + let trimmed_line = line.trim_left(); + if trimmed_line.is_empty() { + hbl = true; + break; + } else if trimmed_line.starts_with(line_start) + || comment_style(trimmed_line, false) == style + { + first_group_ending += compute_len(&orig[first_group_ending..], line); + } else { + break; + } + } + (hbl, first_group_ending) + } + + let (has_bare_lines, first_group_ending) = match style { CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { let line_start = style.line_start().trim_left(); - for line in orig.lines() { - if line.trim_left().starts_with(line_start) || comment_style(line, false) == style { - first_group_ending += compute_len(&orig[first_group_ending..], line); - } else { - break; - } - } + consume_same_line_comments(style, orig, line_start) } CommentStyle::Custom(opener) => { let trimmed_opener = opener.trim_right(); - for line in orig.lines() { - if line.trim_left().starts_with(trimmed_opener) { - first_group_ending += compute_len(&orig[first_group_ending..], line); - } else { - break; - } - } + consume_same_line_comments(style, orig, trimmed_opener) } // for a block comment, search for the closing symbol CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { let closer = style.closer().trim_left(); + let mut closing_symbol_offset = 0; + let mut hbl = false; for line in orig.lines() { - first_group_ending += compute_len(&orig[first_group_ending..], line); - if line.trim_left().ends_with(closer) { + closing_symbol_offset += compute_len(&orig[closing_symbol_offset..], line); + let trimmed_line = line.trim_left(); + if !trimmed_line.starts_with('*') + && !trimmed_line.starts_with("//") + && !trimmed_line.starts_with("/*") + { + hbl = true; + } + if trimmed_line.ends_with(closer) { break; } } + (hbl, closing_symbol_offset) } - } + }; let (first_group, rest) = orig.split_at(first_group_ending); - let first_group_str = rewrite_comment_inner( - first_group, - block_style, - style, - shape, - config, - is_doc_comment || style.is_doc_comment(), - )?; + let rewritten_first_group = + if !config.normalize_comments() && has_bare_lines && style.is_block_comment() { + light_rewrite_block_comment_with_bare_lines(first_group, shape, config)? + } else if !config.normalize_comments() && !config.wrap_comments() { + light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)? + } else { + rewrite_comment_inner( + first_group, + block_style, + style, + shape, + config, + is_doc_comment || style.is_doc_comment(), + )? + }; if rest.is_empty() { - Some(first_group_str) + Some(rewritten_first_group) } else { - identify_comment(rest, block_style, shape, config, is_doc_comment).map(|rest_str| { - format!( - "{}\n{}{}", - first_group_str, - shape.indent.to_string(config), - rest_str - ) - }) + identify_comment(rest.trim_left(), block_style, shape, config, is_doc_comment).map( + |rest_str| { + format!( + "{}\n{}{}{}", + rewritten_first_group, + // insert back the blank line + if has_bare_lines && style.is_line_comment() { + "\n" + } else { + "" + }, + shape.indent.to_string(config), + rest_str + ) + }, + ) } } +/// Trims a minimum of leading whitespaces so that the content layout is kept and aligns to indent. +fn light_rewrite_block_comment_with_bare_lines( + orig: &str, + shape: Shape, + config: &Config, +) -> Option { + let prefix_whitespace_min = orig + .lines() + // skip the line with the starting sigil since the leading whitespace is removed + // otherwise, the minimum would always be zero + .skip(1) + .filter(|line| !line.is_empty()) + .map(|line| { + let mut width = 0; + for c in line.chars() { + match c { + ' ' => width += 1, + '\t' => width += config.tab_spaces(), + _ => break, + } + } + width + }) + .min()?; + + let indent_str = shape.indent.to_string(config); + let mut lines = orig.lines(); + let first_line = lines.next()?; + let rest = lines + .map(|line| { + if line.is_empty() { + line + } else { + &line[prefix_whitespace_min..] + } + }) + .collect::>() + .join(&format!("\n{}", indent_str)); + Some(format!("{}\n{}{}", first_line, indent_str, rest)) +} + fn rewrite_comment_inner( orig: &str, block_style: bool, @@ -1413,26 +1492,29 @@ mod test { #[test] #[rustfmt::skip] fn format_comments() { - let mut config: ::config::Config = Default::default(); - config.set().wrap_comments(true); - config.set().normalize_comments(true); + let mut wrap_normalize_config: ::config::Config = Default::default(); + wrap_normalize_config.set().wrap_comments(true); + wrap_normalize_config.set().normalize_comments(true); + + let mut wrap_config: ::config::Config = Default::default(); + wrap_config.set().wrap_comments(true); let comment = rewrite_comment(" //test", true, Shape::legacy(100, Indent::new(0, 100)), - &config).unwrap(); + &wrap_normalize_config).unwrap(); assert_eq!("/* test */", comment); let comment = rewrite_comment("// comment on a", false, Shape::legacy(10, Indent::empty()), - &config).unwrap(); + &wrap_normalize_config).unwrap(); assert_eq!("// comment\n// on a", comment); let comment = rewrite_comment("// A multi line comment\n // between args.", false, Shape::legacy(60, Indent::new(0, 12)), - &config).unwrap(); + &wrap_normalize_config).unwrap(); assert_eq!("// A multi line comment\n // between args.", comment); let input = "// comment"; @@ -1441,14 +1523,55 @@ mod test { let comment = rewrite_comment(input, true, Shape::legacy(9, Indent::new(0, 69)), - &config).unwrap(); + &wrap_normalize_config).unwrap(); assert_eq!(expected, comment); let comment = rewrite_comment("/* trimmed */", true, Shape::legacy(100, Indent::new(0, 100)), - &config).unwrap(); + &wrap_normalize_config).unwrap(); assert_eq!("/* trimmed */", comment); + + // check that different comment style are properly recognised + let comment = rewrite_comment(r#"/// test1 + /// test2 + /* + * test3 + */"#, + false, + Shape::legacy(100, Indent::new(0, 0)), + &wrap_normalize_config).unwrap(); + assert_eq!("/// test1\n/// test2\n// test3", comment); + + // check that the blank line marks the end of a commented paragraph + let comment = rewrite_comment(r#"// test1 + + // test2"#, + false, + Shape::legacy(100, Indent::new(0, 0)), + &wrap_normalize_config).unwrap(); + assert_eq!("// test1\n\n// test2", comment); + + // check that the blank line marks the end of a custom-commented paragraph + let comment = rewrite_comment(r#"//@ test1 + + //@ test2"#, + false, + Shape::legacy(100, Indent::new(0, 0)), + &wrap_normalize_config).unwrap(); + assert_eq!("//@ test1\n\n//@ test2", comment); + + // check that bare lines are just indented but left unchanged otherwise + let comment = rewrite_comment(r#"// test1 + /* + a bare line! + + another bare line! + */"#, + false, + Shape::legacy(100, Indent::new(0, 0)), + &wrap_config).unwrap(); + assert_eq!("// test1\n/*\n a bare line!\n\n another bare line!\n*/", comment); } // This is probably intended to be a non-test fn, but it is not used. I'm diff --git a/tests/source/issue-2917/packed_simd.rs b/tests/source/issue-2917/packed_simd.rs new file mode 100644 index 00000000000..afa9e67c8ab --- /dev/null +++ b/tests/source/issue-2917/packed_simd.rs @@ -0,0 +1,63 @@ +// rustfmt-wrap_comments: true +//! Implements `From` and `Into` for vector types. + +macro_rules! impl_from_vector { + ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt | $source:ident) => { + impl From<$source> for $id { + #[inline] + fn from(source: $source) -> Self { + fn static_assert_same_number_of_lanes() + where + T: crate::sealed::Simd, + U: crate::sealed::Simd, + { + } + use llvm::simd_cast; + static_assert_same_number_of_lanes::<$id, $source>(); + Simd(unsafe { simd_cast(source.0) }) + } + } + + // FIXME: `Into::into` is not inline, but due to + // the blanket impl in `std`, which is not + // marked `default`, we cannot override it here with + // specialization. + /* + impl Into<$id> for $source { + #[inline] + fn into(self) -> $id { + unsafe { simd_cast(self) } + } + } + */ + + test_if!{ + $test_tt: + interpolate_idents! { + mod [$id _from_ $source] { + use super::*; + #[test] + fn from() { + assert_eq!($id::lanes(), $source::lanes()); + let source: $source = Default::default(); + let vec: $id = Default::default(); + + let e = $id::from(source); + assert_eq!(e, vec); + + let e: $id = source.into(); + assert_eq!(e, vec); + } + } + } + } + }; +} + +macro_rules! impl_from_vectors { + ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt | $($source:ident),*) => { + $( + impl_from_vector!([$elem_ty; $elem_count]: $id | $test_tt | $source); + )* + } +} diff --git a/tests/target/issue-2896.rs b/tests/target/issue-2896.rs index e2c3247f144..6fb6b12ed31 100644 --- a/tests/target/issue-2896.rs +++ b/tests/target/issue-2896.rs @@ -91,23 +91,23 @@ fn main() { let probe = cooccurrences_with_row_sums.probe(); /* - // produce the (item, item) collection - let cooccurrences = occurrences - .join_map(&occurrences, |_user, &item_a, &item_b| (item_a, item_b)); - // count the occurrences of each item. - let counts = cooccurrences - .map(|(item_a,_)| item_a) - .count(); - // produce ((item1, item2), count1, count2, count12) tuples - let cooccurrences_with_counts = cooccurrences - .join_map(&counts, |&item_a, &item_b, &count_item_a| (item_b, (item_a, count_item_a))) - .join_map(&counts, |&item_b, &(item_a, count_item_a), &count_item_b| { - ((item_a, item_b), count_item_a, count_item_b) - }); - let probe = cooccurrences_with_counts - .inspect(|x| println!("change: {:?}", x)) - .probe(); -*/ + // produce the (item, item) collection + let cooccurrences = occurrences + .join_map(&occurrences, |_user, &item_a, &item_b| (item_a, item_b)); + // count the occurrences of each item. + let counts = cooccurrences + .map(|(item_a,_)| item_a) + .count(); + // produce ((item1, item2), count1, count2, count12) tuples + let cooccurrences_with_counts = cooccurrences + .join_map(&counts, |&item_a, &item_b, &count_item_a| (item_b, (item_a, count_item_a))) + .join_map(&counts, |&item_b, &(item_a, count_item_a), &count_item_b| { + ((item_a, item_b), count_item_a, count_item_b) + }); + let probe = cooccurrences_with_counts + .inspect(|x| println!("change: {:?}", x)) + .probe(); + */ (input, probe) }); diff --git a/tests/target/issue-2917/minimal.rs b/tests/target/issue-2917/minimal.rs new file mode 100644 index 00000000000..e81e1e6a5a8 --- /dev/null +++ b/tests/target/issue-2917/minimal.rs @@ -0,0 +1,8 @@ +macro_rules! foo { + () => { + // comment + /* + + */ + }; +} diff --git a/tests/target/issue-2917/packed_simd.rs b/tests/target/issue-2917/packed_simd.rs new file mode 100644 index 00000000000..59a7090505e --- /dev/null +++ b/tests/target/issue-2917/packed_simd.rs @@ -0,0 +1,63 @@ +// rustfmt-wrap_comments: true +//! Implements `From` and `Into` for vector types. + +macro_rules! impl_from_vector { + ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt | $source:ident) => { + impl From<$source> for $id { + #[inline] + fn from(source: $source) -> Self { + fn static_assert_same_number_of_lanes() + where + T: crate::sealed::Simd, + U: crate::sealed::Simd, + { + } + use llvm::simd_cast; + static_assert_same_number_of_lanes::<$id, $source>(); + Simd(unsafe { simd_cast(source.0) }) + } + } + + // FIXME: `Into::into` is not inline, but due to + // the blanket impl in `std`, which is not + // marked `default`, we cannot override it here with + // specialization. + /* + impl Into<$id> for $source { + #[inline] + fn into(self) -> $id { + unsafe { simd_cast(self) } + } + } + */ + + test_if!{ + $test_tt: + interpolate_idents! { + mod [$id _from_ $source] { + use super::*; + #[test] + fn from() { + assert_eq!($id::lanes(), $source::lanes()); + let source: $source = Default::default(); + let vec: $id = Default::default(); + + let e = $id::from(source); + assert_eq!(e, vec); + + let e: $id = source.into(); + assert_eq!(e, vec); + } + } + } + } + }; +} + +macro_rules! impl_from_vectors { + ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt | $($source:ident),*) => { + $( + impl_from_vector!([$elem_ty; $elem_count]: $id | $test_tt | $source); + )* + } +} -- cgit 1.4.1-3-g733a5 From 66c15e46ba1c3cb0f48b65bd2e3ab2d2bb09fc99 Mon Sep 17 00:00:00 2001 From: Emilio Cobos Álvarez Date: Sat, 22 Sep 2018 12:03:33 +0200 Subject: lists: Detect block comment by starting from the end. The issue with the current code is that comments are collapsed, so comments like the one from the test end up in a string like: ``` "// this is a single line comment\n/* block = */" ``` I chose to fix it by detecting whether we're in a block comment starting from the end instead, and tested a single-line comment ended in `*/` just for sanity, ensuring line breaks are not removed in that case, which would break the formatting. The right fix eventually is probably to lex the comments properly, but this does the work for now, I guess :) Fixes #3025 --- src/lists.rs | 14 +++++++------- tests/source/expr-block.rs | 15 +++++++++++++++ tests/target/expr-block.rs | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index f1b01ea8055..57f778896d3 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -566,14 +566,9 @@ where pub fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommentStyle) { let trimmed_pre_snippet = pre_snippet.trim(); + let has_block_comment = trimmed_pre_snippet.ends_with("*/"); let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); - let has_block_comment = trimmed_pre_snippet.starts_with("/*"); - if has_single_line_comment { - ( - Some(trimmed_pre_snippet.to_owned()), - ListItemCommentStyle::DifferentLine, - ) - } else if has_block_comment { + if has_block_comment { let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); if pre_snippet .chars() @@ -591,6 +586,11 @@ pub fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommen ListItemCommentStyle::SameLine, ) } + } else if has_single_line_comment { + ( + Some(trimmed_pre_snippet.to_owned()), + ListItemCommentStyle::DifferentLine, + ) } else { (None, ListItemCommentStyle::None) } diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 48cc1fd72ae..a3e6100b7f2 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -280,6 +280,21 @@ fn issue_1862() { ) } +fn issue_3025() { + foo( + // This describes the argument below. + /* bar = */ None , + // This describes the argument below. + something_something, + // This describes the argument below. */ + None , + // This describes the argument below. + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ None , + // This describes the argument below. + /* com */ this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment , + ) +} + fn issue_1878() { let channel: &str = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?; } diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 3d452cbde39..c5770065087 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -281,6 +281,23 @@ fn issue_1862() { ) } +fn issue_3025() { + foo( + // This describes the argument below. + /* bar = */ None, + // This describes the argument below. + something_something, + // This describes the argument below. */ + None, + // This describes the argument below. + /* This comment waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay too long to be kept on the same line */ + None, + // This describes the argument below. + /* com */ + this_last_arg_is_tooooooooooooooooooooooooooooooooo_long_to_be_kept_with_the_pre_comment, + ) +} + fn issue_1878() { let channel: &str = seq .next_element()? -- cgit 1.4.1-3-g733a5 From 88f3b32e43a17d2d5cecf325dd63dc8a4cad128d Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 25 Sep 2018 18:23:17 +1200 Subject: Remove unnecessary feature flag --- src/bin/main.rs | 3 --- src/lib.rs | 1 - 2 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 8676e6290e0..c03835ea74a 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg(not(test))] -#![feature(extern_prelude)] - extern crate env_logger; #[macro_use] extern crate failure; diff --git a/src/lib.rs b/src/lib.rs index 7ebb967a494..14872cfc610 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,6 @@ #![allow(unused_attributes)] #![feature(type_ascription)] #![feature(unicode_internals)] -#![feature(extern_prelude)] #![feature(nll)] #[macro_use] -- cgit 1.4.1-3-g733a5 From 2727d41ddb676787729cd5632ecedcc4a2d299bb Mon Sep 17 00:00:00 2001 From: André Luis Leal Cardoso Junior Date: Tue, 25 Sep 2018 08:53:42 -0300 Subject: Makes brace behavior consistent with empty bodies for traits and impls Adds a newline before the last brace on impls without a body if the first brace is also on a newline --- src/items.rs | 5 ++--- tests/target/big-impl-block.rs | 3 ++- tests/target/impls.rs | 12 ++++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 46abe086717..a7ba48776d6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -755,11 +755,10 @@ pub fn format_impl( result.push_str(&inner_indent_str); result.push_str(visitor.buffer.to_string().trim()); result.push_str(&outer_indent_str); - } - - if result.ends_with('{') && !context.config.empty_item_single_line() { + } else if need_newline || !context.config.empty_item_single_line() { result.push_str(&sep); } + result.push('}'); Some(result) diff --git a/tests/target/big-impl-block.rs b/tests/target/big-impl-block.rs index fbf1757c635..e3728caba3f 100644 --- a/tests/target/big-impl-block.rs +++ b/tests/target/big-impl-block.rs @@ -78,4 +78,5 @@ where S: event::Stream, F: for<'t> FnMut(transform::Api<'t, Stream>>) -> transform::Api<'t, X>, X: event::Stream, -{} +{ +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 390f1a12cd3..0777a7ed249 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -134,11 +134,13 @@ mod m { impl Handle, HandleType> -{} +{ +} impl PartialEq for Handle, HandleType> -{} +{ +} mod x { impl Foo @@ -147,7 +149,8 @@ mod x { B: 'static, C: 'static, D: 'static, - {} + { + } } impl @@ -229,4 +232,5 @@ impl<'seq1, 'seq2, 'body, 'scope, Channel> > where Channel: DmaChannel, -{} +{ +} -- cgit 1.4.1-3-g733a5 From cc22869fb45f5ad73dce67f8484dd2a6a61bd41e Mon Sep 17 00:00:00 2001 From: moxian Date: Fri, 29 Jun 2018 06:47:51 +0000 Subject: Add option to vertically align enum discriminants. --- Configurations.md | 46 ++++++++++++++++++++++ src/config/mod.rs | 2 + src/items.rs | 33 ++++++++++++++-- .../configs/enum_discrim_align_threshold/20.rs | 28 +++++++++++++ .../configs/enum_discrim_align_threshold/20.rs | 28 +++++++++++++ 5 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 tests/source/configs/enum_discrim_align_threshold/20.rs create mode 100644 tests/target/configs/enum_discrim_align_threshold/20.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 8861d7b2a13..6ac376efa68 100644 --- a/Configurations.md +++ b/Configurations.md @@ -885,6 +885,52 @@ impl Lorem { See also [`brace_style`](#brace_style), [`control_brace_style`](#control_brace_style). +## `enum_discrim_align_threshold` + +The maximum diff of width between enum variants to have discriminants aligned with each other. +Variants without discriminants would be ignored for the purpose of alignment. + +- **Default value** : 0 +- **Possible values**: any positive integer +- **Stable**: No + +#### `0` (default): + +```rust +enum Foo { + A = 0, + Bb = 1, + RandomLongVariantWithoutDiscriminant, + Ccc = 71, +} + +enum Bar { + A = 0, + Bb = 1, + ThisOneisWithDiscriminantAndPreventsAlignment = 10, + Ccc = 71, +} +``` + +#### `20`: + +```rust +enum Foo { + A = 0, + Bb = 1, + RandomLongVariantWithoutDiscriminant, + Ccc = 2, +} + +enum Bar { + A = 0, + Bb = 1, + ThisOneisWithDiscriminantAndPreventsAlignment = 10, + Ccc = 71, +} +``` + + ## `fn_single_line` Put single-expression functions on a single line diff --git a/src/config/mod.rs b/src/config/mod.rs index 52401a18d92..a553bf2ee3c 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -89,6 +89,8 @@ create_config! { combine_control_expr: bool, true, false, "Combine control expressions with function calls"; struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ threshold"; + enum_discrim_align_threshold: usize, 0, false, + "Align enum variants discrims, if their diffs fit within threshold"; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; force_multiline_blocks: bool, false, false, diff --git a/src/items.rs b/src/items.rs index 46abe086717..a341267681e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -500,6 +500,24 @@ impl<'a> FmtVisitor<'a> { let original_offset = self.block_indent; self.block_indent = self.block_indent.block_indent(self.config); + // If enum variants have discriminants, try to vertically align those, + // provided it does not result in too much padding + let pad_discrim_ident_to; + let diff_threshold = self.config.enum_discrim_align_threshold(); + let discr_ident_lens: Vec<_> = enum_def + .variants + .iter() + .filter(|var| var.node.disr_expr.is_some()) + .map(|var| rewrite_ident(&self.get_context(), var.node.ident).len()) + .collect(); + let shortest_w_discr = *discr_ident_lens.iter().min().unwrap_or(&0); + let longest_w_discr = *discr_ident_lens.iter().max().unwrap_or(&0); + if longest_w_discr > shortest_w_discr + diff_threshold { + pad_discrim_ident_to = 0; + } else { + pad_discrim_ident_to = longest_w_discr; + } + let itemize_list_with = |one_line_width: usize| { itemize_list( self.snippet_provider, @@ -514,7 +532,7 @@ impl<'a> FmtVisitor<'a> { } }, |f| f.span.hi(), - |f| self.format_variant(f, one_line_width), + |f| self.format_variant(f, one_line_width, pad_discrim_ident_to), body_lo, body_hi, false, @@ -543,7 +561,12 @@ impl<'a> FmtVisitor<'a> { } // Variant of an enum. - fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option { + fn format_variant( + &self, + field: &ast::Variant, + one_line_width: usize, + pad_discrim_ident_to: usize, + ) -> Option { if contains_skip(&field.node.attrs) { let lo = field.node.attrs[0].span.lo(); let span = mk_sp(lo, field.span.hi()); @@ -570,7 +593,11 @@ impl<'a> FmtVisitor<'a> { )?, ast::VariantData::Unit(..) => { if let Some(ref expr) = field.node.disr_expr { - let lhs = format!("{} =", rewrite_ident(&context, field.node.ident)); + let lhs = format!( + "{:1$} =", + rewrite_ident(&context, field.node.ident), + pad_discrim_ident_to + ); rewrite_assign_rhs(&context, lhs, &*expr.value, shape)? } else { rewrite_ident(&context, field.node.ident).to_owned() diff --git a/tests/source/configs/enum_discrim_align_threshold/20.rs b/tests/source/configs/enum_discrim_align_threshold/20.rs new file mode 100644 index 00000000000..d619d17922a --- /dev/null +++ b/tests/source/configs/enum_discrim_align_threshold/20.rs @@ -0,0 +1,28 @@ +// rustfmt-enum_discrim_align_threshold: 20 + +enum Standard { + A = 1, + Bcdef = 2, +} + +enum Mixed { + ThisIsAFairlyLongEnumVariantWithoutDiscrim, + A = 1, + ThisIsAFairlyLongEnumVariantWithoutDiscrim2, + Bcdef = 2, +} + +enum TooLong { + ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaaaaaaaa = 10, + A = 1, + Bcdef = 2, +} + +// Live specimen from #1686 +enum LongWithSmallDiff { + SceneColorimetryEstimates = 0x73636F65, + SceneAppearanceEstimates = 0x73617065, + FocalPlaneColorimetryEstimates = 0x66706365, + ReflectionHardcopyOriginalColorimetry = 0x72686F63, + ReflectionPrintOutputColorimetry = 0x72706F63, +} \ No newline at end of file diff --git a/tests/target/configs/enum_discrim_align_threshold/20.rs b/tests/target/configs/enum_discrim_align_threshold/20.rs new file mode 100644 index 00000000000..06d621a34cc --- /dev/null +++ b/tests/target/configs/enum_discrim_align_threshold/20.rs @@ -0,0 +1,28 @@ +// rustfmt-enum_discrim_align_threshold: 20 + +enum Standard { + A = 1, + Bcdef = 2, +} + +enum Mixed { + ThisIsAFairlyLongEnumVariantWithoutDiscrim, + A = 1, + ThisIsAFairlyLongEnumVariantWithoutDiscrim2, + Bcdef = 2, +} + +enum TooLong { + ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaaaaaaaa = 10, + A = 1, + Bcdef = 2, +} + +// Live specimen from #1686 +enum LongWithSmallDiff { + SceneColorimetryEstimates = 0x73636F65, + SceneAppearanceEstimates = 0x73617065, + FocalPlaneColorimetryEstimates = 0x66706365, + ReflectionHardcopyOriginalColorimetry = 0x72686F63, + ReflectionPrintOutputColorimetry = 0x72706F63, +} -- cgit 1.4.1-3-g733a5 From 65ae0b9a094d83616585438b86e38b36047d8b45 Mon Sep 17 00:00:00 2001 From: moxian Date: Wed, 26 Sep 2018 18:29:26 +0000 Subject: Change enum align semantics to care about absolute length, rather than difference. If we're only aligning enum discriminants that are "not too far apart (length-wise)", then this works really well for enums with consistently-long or consistently-short idents, but not for the mixed ones. However, consistently-long idents is somewhate of an uncommon case and overlong idents may be allowed to be formatted suboptimally if that makes mixed-length idents work better (and it does in this case). --- Configurations.md | 25 ++++++++-------- src/items.rs | 21 +++++++------ .../configs/enum_discrim_align_threshold/20.rs | 28 ------------------ .../configs/enum_discrim_align_threshold/40.rs | 34 ++++++++++++++++++++++ .../configs/enum_discrim_align_threshold/20.rs | 28 ------------------ .../configs/enum_discrim_align_threshold/40.rs | 34 ++++++++++++++++++++++ 6 files changed, 91 insertions(+), 79 deletions(-) delete mode 100644 tests/source/configs/enum_discrim_align_threshold/20.rs create mode 100644 tests/source/configs/enum_discrim_align_threshold/40.rs delete mode 100644 tests/target/configs/enum_discrim_align_threshold/20.rs create mode 100644 tests/target/configs/enum_discrim_align_threshold/40.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 6ac376efa68..824868bca09 100644 --- a/Configurations.md +++ b/Configurations.md @@ -887,9 +887,12 @@ See also [`brace_style`](#brace_style), [`control_brace_style`](#control_brace_s ## `enum_discrim_align_threshold` -The maximum diff of width between enum variants to have discriminants aligned with each other. +The maximum length of enum variant having discriminant, that gets vertically aligned with others. Variants without discriminants would be ignored for the purpose of alignment. +Note that this is not how much whitespace is inserted, but instead the longest variant name that +doesn't get ignored when aligning. + - **Default value** : 0 - **Possible values**: any positive integer - **Stable**: No @@ -897,18 +900,17 @@ Variants without discriminants would be ignored for the purpose of alignment. #### `0` (default): ```rust -enum Foo { +enum Bar { A = 0, Bb = 1, - RandomLongVariantWithoutDiscriminant, + RandomLongVariantGoesHere = 10, Ccc = 71, } enum Bar { - A = 0, - Bb = 1, - ThisOneisWithDiscriminantAndPreventsAlignment = 10, - Ccc = 71, + VeryLongVariantNameHereA = 0, + VeryLongVariantNameHereBb = 1, + VeryLongVariantNameHereCcc = 2, } ``` @@ -918,15 +920,14 @@ enum Bar { enum Foo { A = 0, Bb = 1, - RandomLongVariantWithoutDiscriminant, + RandomLongVariantGoesHere = 10, Ccc = 2, } enum Bar { - A = 0, - Bb = 1, - ThisOneisWithDiscriminantAndPreventsAlignment = 10, - Ccc = 71, + VeryLongVariantNameHereA = 0, + VeryLongVariantNameHereBb = 1, + VeryLongVariantNameHereCcc = 2, } ``` diff --git a/src/items.rs b/src/items.rs index a341267681e..04e95935844 100644 --- a/src/items.rs +++ b/src/items.rs @@ -501,22 +501,21 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); // If enum variants have discriminants, try to vertically align those, - // provided it does not result in too much padding - let pad_discrim_ident_to; - let diff_threshold = self.config.enum_discrim_align_threshold(); - let discr_ident_lens: Vec<_> = enum_def + // provided the discrims are not shifted too much to the right + let align_threshold: usize = self.config.enum_discrim_align_threshold(); + let discr_ident_lens: Vec = enum_def .variants .iter() .filter(|var| var.node.disr_expr.is_some()) .map(|var| rewrite_ident(&self.get_context(), var.node.ident).len()) .collect(); - let shortest_w_discr = *discr_ident_lens.iter().min().unwrap_or(&0); - let longest_w_discr = *discr_ident_lens.iter().max().unwrap_or(&0); - if longest_w_discr > shortest_w_discr + diff_threshold { - pad_discrim_ident_to = 0; - } else { - pad_discrim_ident_to = longest_w_discr; - } + // cut the list at the point of longest discrim shorter than the threshold + // All of the discrims under the threshold will get padded, and all above - left as is. + let pad_discrim_ident_to = *discr_ident_lens + .iter() + .filter(|&l| *l <= align_threshold) + .max() + .unwrap_or(&0); let itemize_list_with = |one_line_width: usize| { itemize_list( diff --git a/tests/source/configs/enum_discrim_align_threshold/20.rs b/tests/source/configs/enum_discrim_align_threshold/20.rs deleted file mode 100644 index d619d17922a..00000000000 --- a/tests/source/configs/enum_discrim_align_threshold/20.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-enum_discrim_align_threshold: 20 - -enum Standard { - A = 1, - Bcdef = 2, -} - -enum Mixed { - ThisIsAFairlyLongEnumVariantWithoutDiscrim, - A = 1, - ThisIsAFairlyLongEnumVariantWithoutDiscrim2, - Bcdef = 2, -} - -enum TooLong { - ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaaaaaaaa = 10, - A = 1, - Bcdef = 2, -} - -// Live specimen from #1686 -enum LongWithSmallDiff { - SceneColorimetryEstimates = 0x73636F65, - SceneAppearanceEstimates = 0x73617065, - FocalPlaneColorimetryEstimates = 0x66706365, - ReflectionHardcopyOriginalColorimetry = 0x72686F63, - ReflectionPrintOutputColorimetry = 0x72706F63, -} \ No newline at end of file diff --git a/tests/source/configs/enum_discrim_align_threshold/40.rs b/tests/source/configs/enum_discrim_align_threshold/40.rs new file mode 100644 index 00000000000..796e47c384b --- /dev/null +++ b/tests/source/configs/enum_discrim_align_threshold/40.rs @@ -0,0 +1,34 @@ +// rustfmt-enum_discrim_align_threshold: 40 + +enum Standard { + A = 1, + Bcdef = 2, +} + +enum NoDiscrims { + ThisIsAFairlyLongEnumVariantWithoutDiscrimLongerThan40, + A = 1, + ThisIsAnotherFairlyLongEnumVariantWithoutDiscrimLongerThan40, + Bcdef = 2, +} + +enum TooLong { + ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaaChar40 = 10, + A = 1, + Bcdef = 2, +} + +enum Borderline { + ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaa = 10, + A = 1, + Bcdef = 2, +} + +// Live specimen from #1686 +enum LongWithSmallDiff { + SceneColorimetryEstimates = 0x73636F65, + SceneAppearanceEstimates = 0x73617065, + FocalPlaneColorimetryEstimates = 0x66706365, + ReflectionHardcopyOriginalColorimetry = 0x72686F63, + ReflectionPrintOutputColorimetry = 0x72706F63, +} \ No newline at end of file diff --git a/tests/target/configs/enum_discrim_align_threshold/20.rs b/tests/target/configs/enum_discrim_align_threshold/20.rs deleted file mode 100644 index 06d621a34cc..00000000000 --- a/tests/target/configs/enum_discrim_align_threshold/20.rs +++ /dev/null @@ -1,28 +0,0 @@ -// rustfmt-enum_discrim_align_threshold: 20 - -enum Standard { - A = 1, - Bcdef = 2, -} - -enum Mixed { - ThisIsAFairlyLongEnumVariantWithoutDiscrim, - A = 1, - ThisIsAFairlyLongEnumVariantWithoutDiscrim2, - Bcdef = 2, -} - -enum TooLong { - ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaaaaaaaa = 10, - A = 1, - Bcdef = 2, -} - -// Live specimen from #1686 -enum LongWithSmallDiff { - SceneColorimetryEstimates = 0x73636F65, - SceneAppearanceEstimates = 0x73617065, - FocalPlaneColorimetryEstimates = 0x66706365, - ReflectionHardcopyOriginalColorimetry = 0x72686F63, - ReflectionPrintOutputColorimetry = 0x72706F63, -} diff --git a/tests/target/configs/enum_discrim_align_threshold/40.rs b/tests/target/configs/enum_discrim_align_threshold/40.rs new file mode 100644 index 00000000000..3ed66039c9d --- /dev/null +++ b/tests/target/configs/enum_discrim_align_threshold/40.rs @@ -0,0 +1,34 @@ +// rustfmt-enum_discrim_align_threshold: 40 + +enum Standard { + A = 1, + Bcdef = 2, +} + +enum NoDiscrims { + ThisIsAFairlyLongEnumVariantWithoutDiscrimLongerThan40, + A = 1, + ThisIsAnotherFairlyLongEnumVariantWithoutDiscrimLongerThan40, + Bcdef = 2, +} + +enum TooLong { + ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaaChar40 = 10, + A = 1, + Bcdef = 2, +} + +enum Borderline { + ThisOneHasDiscrimAaaaaaaaaaaaaaaaaaaaaa = 10, + A = 1, + Bcdef = 2, +} + +// Live specimen from #1686 +enum LongWithSmallDiff { + SceneColorimetryEstimates = 0x73636F65, + SceneAppearanceEstimates = 0x73617065, + FocalPlaneColorimetryEstimates = 0x66706365, + ReflectionHardcopyOriginalColorimetry = 0x72686F63, + ReflectionPrintOutputColorimetry = 0x72706F63, +} -- cgit 1.4.1-3-g733a5 From 2bcc3a93025894345674c8d714b1bf3c5fec7f6c Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 28 Sep 2018 04:06:29 +0200 Subject: do not format a code block in documentation if it is annotated with ignore or text (#3058) --- src/comment.rs | 63 +++++++++++++++++++++++------ tests/source/issue-3055/original.rs | 42 +++++++++++++++++++ tests/target/issue-3055/backtick.rs | 10 +++++ tests/target/issue-3055/empty-code-block.rs | 18 +++++++++ tests/target/issue-3055/original.rs | 41 +++++++++++++++++++ 5 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 tests/source/issue-3055/original.rs create mode 100644 tests/target/issue-3055/backtick.rs create mode 100644 tests/target/issue-3055/empty-code-block.rs create mode 100644 tests/target/issue-3055/original.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 60fa7e891f7..b561e411f9e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -407,6 +407,31 @@ fn light_rewrite_block_comment_with_bare_lines( Some(format!("{}\n{}{}", first_line, indent_str, rest)) } +/// Attributes for code blocks in rustdoc. +/// See https://doc.rust-lang.org/rustdoc/print.html#attributes +enum CodeBlockAttribute { + Rust, + Ignore, + Text, + ShouldPanic, + NoRun, + CompileFail, +} + +impl CodeBlockAttribute { + fn new(attribute: &str) -> CodeBlockAttribute { + match attribute { + "rust" | "" => CodeBlockAttribute::Rust, + "ignore" => CodeBlockAttribute::Ignore, + "text" => CodeBlockAttribute::Text, + "should_panic" => CodeBlockAttribute::ShouldPanic, + "no_run" => CodeBlockAttribute::NoRun, + "compile_fail" => CodeBlockAttribute::CompileFail, + _ => CodeBlockAttribute::Text, + } + } +} + fn rewrite_comment_inner( orig: &str, block_style: bool, @@ -466,7 +491,7 @@ fn rewrite_comment_inner( result.push_str(opener); let mut code_block_buffer = String::with_capacity(128); let mut is_prev_line_multi_line = false; - let mut inside_code_block = false; + let mut code_block_attr = None; let comment_line_separator = format!("{}{}", indent_str, line_start); let join_code_block_with_comment_line_separator = |s: &str| { let mut result = String::with_capacity(s.len() + 128); @@ -485,28 +510,36 @@ fn rewrite_comment_inner( for (i, (line, has_leading_whitespace)) in lines.enumerate() { let is_last = i == count_newlines(orig); - if inside_code_block { + if let Some(ref attr) = code_block_attr { if line.starts_with("```") { - inside_code_block = false; - result.push_str(&comment_line_separator); - let code_block = { - let mut config = config.clone(); - config.set().wrap_comments(false); - match ::format_code_block(&code_block_buffer, &config) { - Some(ref s) => trim_custom_comment_prefix(s), - None => trim_custom_comment_prefix(&code_block_buffer), + let code_block = match attr { + CodeBlockAttribute::Ignore | CodeBlockAttribute::Text => { + trim_custom_comment_prefix(&code_block_buffer) + } + _ if code_block_buffer.is_empty() => String::new(), + _ => { + let mut config = config.clone(); + config.set().wrap_comments(false); + match ::format_code_block(&code_block_buffer, &config) { + Some(ref s) => trim_custom_comment_prefix(s), + None => trim_custom_comment_prefix(&code_block_buffer), + } } }; - result.push_str(&join_code_block_with_comment_line_separator(&code_block)); + if !code_block.is_empty() { + result.push_str(&comment_line_separator); + result.push_str(&join_code_block_with_comment_line_separator(&code_block)); + } code_block_buffer.clear(); result.push_str(&comment_line_separator); result.push_str(line); + code_block_attr = None; } else { code_block_buffer.push_str(&hide_sharp_behind_comment(line)); code_block_buffer.push('\n'); if is_last { - // There is an code block that is not properly enclosed by backticks. + // There is a code block that is not properly enclosed by backticks. // We will leave them untouched. result.push_str(&comment_line_separator); result.push_str(&join_code_block_with_comment_line_separator( @@ -517,7 +550,11 @@ fn rewrite_comment_inner( continue; } else { - inside_code_block = line.starts_with("```"); + code_block_attr = if line.starts_with("```") { + Some(CodeBlockAttribute::new(&line[3..])) + } else { + None + }; if result == opener { let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; diff --git a/tests/source/issue-3055/original.rs b/tests/source/issue-3055/original.rs new file mode 100644 index 00000000000..1f7d33ac5ae --- /dev/null +++ b/tests/source/issue-3055/original.rs @@ -0,0 +1,42 @@ +// rustfmt-wrap_comments: true + +/// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc commodo ultricies dui. +/// +/// Should not format with text attribute +/// ```text +/// .--------------. +/// | v +/// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot +/// ^ ^ ' ' ' +/// ' ' ' ' ' +/// ' `--------' ' ' +/// `---------------' ' ' +/// `--------------------------' ' +/// `-------------------------------------' +/// ``` +/// +/// Should not format with ignore attribute +/// ```ignore +/// .--------------. +/// | v +/// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot +/// ^ ^ ' ' ' +/// ' ' ' ' ' +/// ' `--------' ' ' +/// `---------------' ' ' +/// `--------------------------' ' +/// `-------------------------------------' +/// ``` +/// +/// Should format with rust attribute +/// ```rust +/// let x = +/// 42; +/// ``` +/// +/// Should format with no attribute as it defaults to rust +/// ``` +/// let x = +/// 42; +/// ``` +fn func() {} diff --git a/tests/target/issue-3055/backtick.rs b/tests/target/issue-3055/backtick.rs new file mode 100644 index 00000000000..f5bae8d3db4 --- /dev/null +++ b/tests/target/issue-3055/backtick.rs @@ -0,0 +1,10 @@ +// rustfmt-wrap_comments: true + +/// Simple block +/// +/// ```text +/// ` +/// ``` +fn main() { + println!("Hello, world!"); +} diff --git a/tests/target/issue-3055/empty-code-block.rs b/tests/target/issue-3055/empty-code-block.rs new file mode 100644 index 00000000000..566f7ef9b6e --- /dev/null +++ b/tests/target/issue-3055/empty-code-block.rs @@ -0,0 +1,18 @@ +// rustfmt-wrap_comments: true + +/// Simple block +/// +/// ``` +/// ``` +/// +/// ```no_run +/// ``` +/// +/// ```should_panic +/// ``` +/// +/// ```compile_fail +/// ``` +fn main() { + println!("Hello, world!"); +} diff --git a/tests/target/issue-3055/original.rs b/tests/target/issue-3055/original.rs new file mode 100644 index 00000000000..1455ac1a916 --- /dev/null +++ b/tests/target/issue-3055/original.rs @@ -0,0 +1,41 @@ +// rustfmt-wrap_comments: true + +/// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc +/// commodo ultricies dui. +/// +/// Should not format with text attribute +/// ```text +/// .--------------. +/// | v +/// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot +/// ^ ^ ' ' ' +/// ' ' ' ' ' +/// ' `--------' ' ' +/// `---------------' ' ' +/// `--------------------------' ' +/// `-------------------------------------' +/// ``` +/// +/// Should not format with ignore attribute +/// ```ignore +/// .--------------. +/// | v +/// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot +/// ^ ^ ' ' ' +/// ' ' ' ' ' +/// ' `--------' ' ' +/// `---------------' ' ' +/// `--------------------------' ' +/// `-------------------------------------' +/// ``` +/// +/// Should format with rust attribute +/// ```rust +/// let x = 42; +/// ``` +/// +/// Should format with no attribute as it defaults to rust +/// ``` +/// let x = 42; +/// ``` +fn func() {} -- cgit 1.4.1-3-g733a5 From c7377c3555c37d23b0c31a727b3d7b95427767d3 Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Thu, 27 Sep 2018 22:31:17 -0700 Subject: Fix help message for edition config option --- src/config/options.rs | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index 7dca87e1777..34b6ea0dde6 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -17,17 +17,21 @@ use isatty::stdout_isatty; use std::collections::HashSet; use std::path::{Path, PathBuf}; -/// Macro for deriving implementations of Serialize/Deserialize for enums +/// Macro that will stringify the enum variants or a provided textual repr #[macro_export] -macro_rules! impl_enum_serialize_and_deserialize { - (@stringify $variant:ident) => ( +macro_rules! configuration_option_enum_stringify { + ($variant:ident) => { stringify!($variant) - ); + }; - (@stringify $_variant:ident: $value:expr) => ( + ($_variant:ident: $value:expr) => { stringify!($value) - ); + }; +} +/// Macro for deriving implementations of Serialize/Deserialize for enums +#[macro_export] +macro_rules! impl_enum_serialize_and_deserialize { ( $e:ident, $( $variant:ident $(: $value:expr)* ),* ) => { impl ::serde::ser::Serialize for $e { fn serialize(&self, serializer: S) -> Result @@ -40,7 +44,7 @@ macro_rules! impl_enum_serialize_and_deserialize { match *self { $( $e::$variant => serializer.serialize_str( - impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + configuration_option_enum_stringify!($variant $(: $value)*) ), )* _ => { @@ -69,13 +73,13 @@ macro_rules! impl_enum_serialize_and_deserialize { } let s = d.deserialize_string(StringOnly::(PhantomData))?; $( - if impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + if configuration_option_enum_stringify!($variant $(: $value)*) .eq_ignore_ascii_case(&s) { return Ok($e::$variant); } )* static ALLOWED: &'static[&str] = &[ - $(impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*),)*]; + $(configuration_option_enum_stringify!($variant $(: $value)*),)*]; Err(D::Error::unknown_variant(&s, ALLOWED)) } } @@ -85,7 +89,7 @@ macro_rules! impl_enum_serialize_and_deserialize { fn from_str(s: &str) -> Result { $( - if impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + if configuration_option_enum_stringify!($variant $(: $value)*) .eq_ignore_ascii_case(s) { return Ok($e::$variant); } @@ -99,7 +103,7 @@ macro_rules! impl_enum_serialize_and_deserialize { let mut variants = Vec::new(); $( variants.push( - impl_enum_serialize_and_deserialize!(@stringify $variant $(: $value)*) + configuration_option_enum_stringify!($variant $(: $value)*) ); )* format!("[{}]", variants.join("|")) @@ -110,11 +114,21 @@ macro_rules! impl_enum_serialize_and_deserialize { macro_rules! configuration_option_enum { ($e:ident: $( $name:ident $(: $value:expr)* ),+ $(,)*) => ( - #[derive(Copy, Clone, Eq, PartialEq, Debug)] + #[derive(Copy, Clone, Eq, PartialEq)] pub enum $e { $( $name ),+ } + impl ::std::fmt::Debug for $e { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.write_str(match self { + $( + $e::$name => configuration_option_enum_stringify!($name $(: $value)*), + )+ + }) + } + } + impl_enum_serialize_and_deserialize!($e, $( $name $(: $value)* ),+); ); } -- cgit 1.4.1-3-g733a5 From 301ddd39db4cbb6196edd6c8854730bdb6241615 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Thu, 27 Sep 2018 16:45:22 -0300 Subject: comment: Add documentation to `is_doc_comment` public method Signed-off-by: Otavio Salvador --- src/comment.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index b561e411f9e..d4af68e7d25 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -73,6 +73,7 @@ impl<'a> CommentStyle<'a> { } } + /// Returns true if the commenting style is for documentation. pub fn is_doc_comment(&self) -> bool { match *self { CommentStyle::TripleSlash | CommentStyle::Doc => true, -- cgit 1.4.1-3-g733a5 From 755d27a4241d9b2a6fa90118d9d40ae729fe5c68 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 29 Sep 2018 14:33:00 +0900 Subject: Take impl Iterator for overflow routines --- src/expr.rs | 44 +++++++++++++++++++++++++++++--------------- src/items.rs | 5 ++--- src/macros.rs | 6 ++---- src/overflow.rs | 40 ++++++++++++++++++++-------------------- src/patterns.rs | 3 +-- src/rewrite.rs | 7 +++++++ src/spanned.rs | 9 +++++++-- src/types.rs | 11 ++++------- 8 files changed, 72 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 674f719b5c7..f104a40bf87 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -73,7 +73,7 @@ pub fn format_expr( let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( "", - &ptr_vec_to_ref_vec(expr_vec), + expr_vec.iter(), expr.span, context, shape, @@ -110,7 +110,7 @@ pub fn format_expr( shape, ), ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape) + rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) @@ -391,15 +391,18 @@ pub fn format_expr( }) } -pub fn rewrite_array( - name: &str, - exprs: &[&T], +pub fn rewrite_array<'a, T: 'a>( + name: &'a str, + exprs: impl Iterator, span: Span, - context: &RewriteContext, + context: &'a RewriteContext, shape: Shape, force_separator_tactic: Option, delim_token: Option, -) -> Option { +) -> Option +where + T: Rewrite + Spanned + ToExpr, +{ overflow::rewrite_with_square_brackets( context, name, @@ -1329,7 +1332,7 @@ pub fn rewrite_call( overflow::rewrite_with_parens( context, callee, - &ptr_vec_to_ref_vec(args), + args.iter(), shape, span, context.config.width_heuristics().fn_call_width, @@ -1722,17 +1725,17 @@ pub fn rewrite_field( fn rewrite_tuple_in_visual_indent_style<'a, T>( context: &RewriteContext, - items: &[&T], + mut items: impl Iterator, span: Span, shape: Shape, + is_singleton_tuple: bool, ) -> Option where T: Rewrite + Spanned + ToExpr + 'a, { - let mut items = items.iter(); // In case of length 1, need a trailing comma debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); - if items.len() == 1 { + if is_singleton_tuple { // 3 = "(" + ",)" let nested_shape = shape.sub_width(3)?.visual_indent(1); return items @@ -1772,10 +1775,11 @@ where } pub fn rewrite_tuple<'a, T>( - context: &RewriteContext, - items: &[&T], + context: &'a RewriteContext, + items: impl Iterator, span: Span, shape: Shape, + is_singleton_tuple: bool, ) -> Option where T: Rewrite + Spanned + ToExpr + 'a, @@ -1789,7 +1793,7 @@ where } else { Some(SeparatorTactic::Never) } - } else if items.len() == 1 { + } else if is_singleton_tuple { Some(SeparatorTactic::Always) } else { None @@ -1804,7 +1808,7 @@ where force_tactic, ) } else { - rewrite_tuple_in_visual_indent_style(context, items, span, shape) + rewrite_tuple_in_visual_indent_style(context, items, span, shape, is_singleton_tuple) } } @@ -2068,6 +2072,16 @@ impl ToExpr for ast::GenericParam { } } +impl ToExpr for ptr::P { + fn to_expr(&self) -> Option<&ast::Expr> { + (**self).to_expr() + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + (**self).can_be_overflowed(context, len) + } +} + pub fn is_method_call(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::MethodCall(..) => true, diff --git a/src/items.rs b/src/items.rs index 17a9e529692..3f8fb852497 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1391,11 +1391,10 @@ fn format_tuple_struct( format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")"); } else { let shape = Shape::indented(offset, context.config).sub_width(1)?; - let fields = &fields.iter().collect::>(); result = overflow::rewrite_with_parens( context, &result, - fields, + fields.iter(), shape, span, context.config.width_heuristics().fn_call_width, @@ -2495,7 +2494,7 @@ fn rewrite_generics( return Some(ident.to_owned()); } - let params = &generics.params.iter().map(|e| &*e).collect::>(); + let params = generics.params.iter(); overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span) } diff --git a/src/macros.rs b/src/macros.rs index 282519286fa..886e929c43f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -278,7 +278,7 @@ pub fn rewrite_macro_inner( overflow::rewrite_with_parens( context, ¯o_name, - &arg_vec.iter().map(|e| &*e).collect::>(), + arg_vec.iter(), shape, mac.span, context.config.width_heuristics().fn_call_width, @@ -334,11 +334,9 @@ pub fn rewrite_macro_inner( force_trailing_comma = Some(SeparatorTactic::Vertical); }; } - // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. - let arg_vec = &arg_vec.iter().map(|e| &*e).collect::>(); let rewrite = rewrite_array( macro_name, - arg_vec, + arg_vec.iter(), mac.span, context, shape, diff --git a/src/overflow.rs b/src/overflow.rs index acf6d7b4d38..5c50e3b3a37 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -29,10 +29,10 @@ use std::cmp::min; const SHORT_ITEM_THRESHOLD: usize = 10; -pub fn rewrite_with_parens( - context: &RewriteContext, - ident: &str, - items: &[&T], +pub fn rewrite_with_parens<'a, 'b, T: 'a>( + context: &'a RewriteContext, + ident: &'a str, + items: impl Iterator, shape: Shape, span: Span, item_max_width: usize, @@ -56,10 +56,10 @@ where .rewrite(shape) } -pub fn rewrite_with_angle_brackets( - context: &RewriteContext, - ident: &str, - items: &[&T], +pub fn rewrite_with_angle_brackets<'a, T: 'a>( + context: &'a RewriteContext, + ident: &'a str, + items: impl Iterator, shape: Shape, span: Span, ) -> Option @@ -81,10 +81,10 @@ where .rewrite(shape) } -pub fn rewrite_with_square_brackets( - context: &RewriteContext, - name: &str, - items: &[&T], +pub fn rewrite_with_square_brackets<'a, T: 'a>( + context: &'a RewriteContext, + name: &'a str, + items: impl Iterator, shape: Shape, span: Span, force_separator_tactic: Option, @@ -115,7 +115,7 @@ where struct Context<'a, T: 'a> { context: &'a RewriteContext<'a>, - items: &'a [&'a T], + items: Vec<&'a T>, ident: &'a str, prefix: &'static str, suffix: &'static str, @@ -131,7 +131,7 @@ struct Context<'a, T: 'a> { impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { pub fn new( context: &'a RewriteContext, - items: &'a [&'a T], + items: impl Iterator, ident: &'a str, shape: Shape, span: Span, @@ -153,7 +153,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1); Context { context, - items, + items: items.collect(), ident, one_line_shape, nested_shape, @@ -192,7 +192,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { ast::ExprKind::Closure(..) => { // If the argument consists of multiple closures, we do not overflow // the last closure. - if closures::args_have_many_closure(self.items) { + if closures::args_have_many_closure(&self.items) { None } else { closures::rewrite_last_closure(self.context, expr, shape) @@ -227,7 +227,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let combine_arg_with_callee = self.items.len() == 1 && self.items[0].to_expr().is_some() && self.ident.len() < self.context.config.tab_spaces(); - let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, self.items); + let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, &self.items); // Replace the last item with its first line to see if it fits with // first arguments. @@ -241,7 +241,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { } } let result = last_item_shape( - self.items, + &self.items, list_items, self.one_line_shape, self.item_max_width, @@ -316,7 +316,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { if tactic == DefinitiveListTactic::Vertical { if let Some((all_simple, num_args_before)) = - maybe_get_args_offset(self.ident, self.items) + maybe_get_args_offset(self.ident, &self.items) { let one_line = all_simple && definitive_tactic( @@ -335,7 +335,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { if one_line { tactic = DefinitiveListTactic::SpecialMacro(num_args_before); }; - } else if is_every_expr_simple(self.items) && no_long_items(list_items) { + } else if is_every_expr_simple(&self.items) && no_long_items(list_items) { tactic = DefinitiveListTactic::Mixed; } } diff --git a/src/patterns.rs b/src/patterns.rs index 13fea046aaf..8277a768e0e 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -359,12 +359,11 @@ fn rewrite_tuple_pat( // add comma if `(x,)` let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none() && !condensed; let path_str = path_str.unwrap_or_default(); - let pat_ref_vec = pat_vec.iter().collect::>(); overflow::rewrite_with_parens( &context, &path_str, - &pat_ref_vec, + pat_vec.iter(), shape, span, context.config.max_width(), diff --git a/src/rewrite.rs b/src/rewrite.rs index f463732c0e4..d151c922e81 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -11,6 +11,7 @@ // A generic trait to abstract the rewriting of an element (of the AST). use syntax::parse::ParseSess; +use syntax::ptr; use syntax::source_map::{SourceMap, Span}; use config::{Config, IndentStyle}; @@ -25,6 +26,12 @@ pub trait Rewrite { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; } +impl Rewrite for ptr::P { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + (**self).rewrite(context, shape) + } +} + #[derive(Clone)] pub struct RewriteContext<'a> { pub parse_session: &'a ParseSess, diff --git a/src/spanned.rs b/src/spanned.rs index a7ba0f1a72d..504d18fb7fd 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast; -use syntax::source_map::Span; +use syntax::{ast, ptr, source_map::Span}; use macros::MacroArg; use utils::{mk_sp, outer_attributes}; @@ -21,6 +20,12 @@ pub trait Spanned { fn span(&self) -> Span; } +impl Spanned for ptr::P { + fn span(&self) -> Span { + (**self).span() + } +} + macro_rules! span_with_attrs_lo_hi { ($this:ident, $lo:expr, $hi:expr) => {{ let attrs = outer_attributes(&$this.attrs); diff --git a/src/types.rs b/src/types.rs index 5f71dd6bdc4..8ab89848407 100644 --- a/src/types.rs +++ b/src/types.rs @@ -252,7 +252,7 @@ fn rewrite_segment( let generics_str = overflow::rewrite_with_angle_brackets( context, "", - ¶m_list.iter().map(|e| &*e).collect::>(), + param_list.iter(), shape, mk_sp(*span_lo, span_hi), )?; @@ -664,12 +664,9 @@ impl Rewrite for ast::Ty { ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) .map(|ty_str| format!("[{}]", ty_str)) } - ast::TyKind::Tup(ref items) => rewrite_tuple( - context, - &::utils::ptr_vec_to_ref_vec(items), - self.span, - shape, - ), + ast::TyKind::Tup(ref items) => { + rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1) + } ast::TyKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape) } -- cgit 1.4.1-3-g733a5 From c302409f56d0d08948d5e23d336818553b26a322 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 00:26:36 +0900 Subject: Get rid of ToExpr trait --- src/closures.rs | 8 +-- src/expr.rs | 116 ++++-------------------------------- src/overflow.rs | 182 +++++++++++++++++++++++++++++++++++++++++++++----------- src/types.rs | 17 +----- 4 files changed, 164 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 9546451d7ca..153f3413f10 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -13,9 +13,10 @@ use syntax::parse::classify; use syntax::source_map::Span; use syntax::{ast, ptr}; -use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond, ToExpr}; +use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use overflow::OverflowableItem; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use source_map::SpanUtils; @@ -358,10 +359,7 @@ pub fn rewrite_last_closure( } /// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. -pub fn args_have_many_closure(args: &[&T]) -> bool -where - T: ToExpr, -{ +pub fn args_have_many_closure(args: &[OverflowableItem]) -> bool { args.iter() .filter(|arg| { arg.to_expr() diff --git a/src/expr.rs b/src/expr.rs index f104a40bf87..102fab346d7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -27,17 +27,17 @@ use lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, }; -use macros::{rewrite_macro, MacroArg, MacroPosition}; +use macros::{rewrite_macro, MacroPosition}; use matches::rewrite_match; -use overflow; +use overflow::{self, IntoOverflowableItem, OverflowableItem}; use pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; -use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; +use patterns::is_short_pattern; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use string::{rewrite_string, StringFormat}; -use types::{can_be_overflowed_type, rewrite_path, PathContext}; +use types::{rewrite_path, PathContext}; use utils::{ colon_spaces, contains_skip, count_newlines, first_line_ends_with, first_line_width, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, @@ -391,7 +391,7 @@ pub fn format_expr( }) } -pub fn rewrite_array<'a, T: 'a>( +pub fn rewrite_array<'a, T: 'a + IntoOverflowableItem<'a>>( name: &'a str, exprs: impl Iterator, span: Span, @@ -399,10 +399,7 @@ pub fn rewrite_array<'a, T: 'a>( shape: Shape, force_separator_tactic: Option, delim_token: Option, -) -> Option -where - T: Rewrite + Spanned + ToExpr, -{ +) -> Option { overflow::rewrite_with_square_brackets( context, name, @@ -1263,7 +1260,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt } /// In case special-case style is required, returns an offset from which we start horizontal layout. -pub fn maybe_get_args_offset(callee_str: &str, args: &[&T]) -> Option<(bool, usize)> { +pub fn maybe_get_args_offset(callee_str: &str, args: &[OverflowableItem]) -> Option<(bool, usize)> { if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST .iter() .find(|&&(s, _)| s == callee_str) @@ -1358,7 +1355,7 @@ fn is_simple_expr(expr: &ast::Expr) -> bool { } } -pub fn is_every_expr_simple(lists: &[&T]) -> bool { +pub fn is_every_expr_simple(lists: &[OverflowableItem]) -> bool { lists .iter() .all(|arg| arg.to_expr().map_or(false, is_simple_expr)) @@ -1723,16 +1720,13 @@ pub fn rewrite_field( } } -fn rewrite_tuple_in_visual_indent_style<'a, T>( +fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>( context: &RewriteContext, mut items: impl Iterator, span: Span, shape: Shape, is_singleton_tuple: bool, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ +) -> Option { // In case of length 1, need a trailing comma debug!("rewrite_tuple_in_visual_indent_style {:?}", shape); if is_singleton_tuple { @@ -1774,16 +1768,13 @@ where Some(format!("({})", list_str)) } -pub fn rewrite_tuple<'a, T>( +pub fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext, items: impl Iterator, span: Span, shape: Shape, is_singleton_tuple: bool, -) -> Option -where - T: Rewrite + Spanned + ToExpr + 'a, -{ +) -> Option { debug!("rewrite_tuple {:?}", shape); if context.use_block_indent() { // We use the same rule as function calls for rewriting tuples. @@ -1999,89 +1990,6 @@ fn rewrite_expr_addrof( rewrite_unary_prefix(context, operator_str, expr, shape) } -pub trait ToExpr { - fn to_expr(&self) -> Option<&ast::Expr>; - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool; -} - -impl ToExpr for ast::Expr { - fn to_expr(&self) -> Option<&ast::Expr> { - Some(self) - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_expr(context, self, len) - } -} - -impl ToExpr for ast::Ty { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_type(context, self, len) - } -} - -impl<'a> ToExpr for TuplePatField<'a> { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - can_be_overflowed_pat(context, self, len) - } -} - -impl<'a> ToExpr for ast::StructField { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { - false - } -} - -impl<'a> ToExpr for MacroArg { - fn to_expr(&self) -> Option<&ast::Expr> { - match *self { - MacroArg::Expr(ref expr) => Some(expr), - _ => None, - } - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - match *self { - MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), - MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), - MacroArg::Pat(..) => false, - MacroArg::Item(..) => len == 1, - } - } -} - -impl ToExpr for ast::GenericParam { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, _: &RewriteContext, _: usize) -> bool { - false - } -} - -impl ToExpr for ptr::P { - fn to_expr(&self) -> Option<&ast::Expr> { - (**self).to_expr() - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - (**self).can_be_overflowed(context, len) - } -} - pub fn is_method_call(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::MethodCall(..) => true, diff --git a/src/overflow.rs b/src/overflow.rs index 5c50e3b3a37..37d070cfd40 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -9,27 +9,154 @@ // except according to those terms. //! Rewrite a list some items with overflow. -// FIXME: Replace `ToExpr` with some enum. use config::lists::*; -use syntax::ast; use syntax::parse::token::DelimToken; use syntax::source_map::Span; +use syntax::{ast, ptr}; use closures; -use expr::{is_every_expr_simple, is_method_call, is_nested_call, maybe_get_args_offset, ToExpr}; +use expr::{ + can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, + maybe_get_args_offset, +}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; +use macros::MacroArg; +use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use source_map::SpanUtils; use spanned::Spanned; +use types::{can_be_overflowed_type, SegmentParam}; use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; use std::cmp::min; +pub enum OverflowableItem<'a> { + Expr(&'a ast::Expr), + GenericParam(&'a ast::GenericParam), + MacroArg(&'a MacroArg), + SegmentParam(&'a SegmentParam<'a>), + StructField(&'a ast::StructField), + TuplePatField(&'a TuplePatField<'a>), + Ty(&'a ast::Ty), +} + +impl<'a> Rewrite for OverflowableItem<'a> { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + self.map(|item| item.rewrite(context, shape)) + } +} + +impl<'a> Spanned for OverflowableItem<'a> { + fn span(&self) -> Span { + self.map(|item| item.span()) + } +} + +impl<'a> OverflowableItem<'a> { + pub fn map(&self, f: F) -> T + where + F: Fn(&IntoOverflowableItem<'a>) -> T, + { + match self { + OverflowableItem::Expr(expr) => f(*expr), + OverflowableItem::GenericParam(gp) => f(*gp), + OverflowableItem::MacroArg(macro_arg) => f(*macro_arg), + OverflowableItem::SegmentParam(sp) => f(*sp), + OverflowableItem::StructField(sf) => f(*sf), + OverflowableItem::TuplePatField(pat) => f(*pat), + OverflowableItem::Ty(ty) => f(*ty), + } + } + + pub fn to_expr(&self) -> Option<&'a ast::Expr> { + match self { + OverflowableItem::Expr(expr) => Some(expr), + OverflowableItem::MacroArg(macro_arg) => match macro_arg { + MacroArg::Expr(ref expr) => Some(expr), + _ => None, + }, + _ => None, + } + } + + pub fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + match self { + OverflowableItem::Expr(expr) => can_be_overflowed_expr(context, expr, len), + OverflowableItem::MacroArg(macro_arg) => match macro_arg { + MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), + MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), + MacroArg::Pat(..) => false, + MacroArg::Item(..) => len == 1, + }, + OverflowableItem::SegmentParam(seg) => match seg { + SegmentParam::Type(ty) => can_be_overflowed_type(context, ty, len), + _ => false, + }, + OverflowableItem::TuplePatField(pat) => can_be_overflowed_pat(context, pat, len), + OverflowableItem::Ty(ty) => can_be_overflowed_type(context, ty, len), + _ => false, + } + } +} + +pub trait IntoOverflowableItem<'a>: Rewrite + Spanned { + fn into_overflowable_item(&'a self) -> OverflowableItem<'a>; +} + +impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for ptr::P { + fn into_overflowable_item(&'a self) -> OverflowableItem<'a> { + (**self).into_overflowable_item() + } +} + +macro impl_into_overflowable_item_for_ast_node { + ($($ast_node:ident),*) => { + $( + impl<'a> IntoOverflowableItem<'a> for ast::$ast_node { + fn into_overflowable_item(&'a self) -> OverflowableItem<'a> { + OverflowableItem::$ast_node(self) + } + } + )* + } +} + +macro impl_into_overflowable_item_for_rustfmt_types { + ([$($ty:ident),*], [$($ty_with_lifetime:ident),*]) => { + $( + impl<'a> IntoOverflowableItem<'a> for $ty { + fn into_overflowable_item(&'a self) -> OverflowableItem<'a> { + OverflowableItem::$ty(self) + } + } + )* + $( + impl<'a> IntoOverflowableItem<'a> for $ty_with_lifetime<'a> { + fn into_overflowable_item(&'a self) -> OverflowableItem<'a> { + OverflowableItem::$ty_with_lifetime(self) + } + } + )* + } +} + +impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, StructField, Ty); +impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); + +pub fn into_overflowable_list<'a, T>( + iter: impl Iterator, +) -> impl Iterator> +where + T: 'a + IntoOverflowableItem<'a>, +{ + iter.map(|x| IntoOverflowableItem::into_overflowable_item(x)) +} + const SHORT_ITEM_THRESHOLD: usize = 10; -pub fn rewrite_with_parens<'a, 'b, T: 'a>( +pub fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext, ident: &'a str, items: impl Iterator, @@ -37,10 +164,7 @@ pub fn rewrite_with_parens<'a, 'b, T: 'a>( span: Span, item_max_width: usize, force_separator_tactic: Option, -) -> Option -where - T: Rewrite + ToExpr + Spanned, -{ +) -> Option { Context::new( context, items, @@ -56,16 +180,13 @@ where .rewrite(shape) } -pub fn rewrite_with_angle_brackets<'a, T: 'a>( +pub fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext, ident: &'a str, items: impl Iterator, shape: Shape, span: Span, -) -> Option -where - T: Rewrite + ToExpr + Spanned, -{ +) -> Option { Context::new( context, items, @@ -81,7 +202,7 @@ where .rewrite(shape) } -pub fn rewrite_with_square_brackets<'a, T: 'a>( +pub fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext, name: &'a str, items: impl Iterator, @@ -89,10 +210,7 @@ pub fn rewrite_with_square_brackets<'a, T: 'a>( span: Span, force_separator_tactic: Option, delim_token: Option, -) -> Option -where - T: Rewrite + ToExpr + Spanned, -{ +) -> Option { let (lhs, rhs) = match delim_token { Some(DelimToken::Paren) => ("(", ")"), Some(DelimToken::Brace) => ("{", "}"), @@ -113,9 +231,9 @@ where .rewrite(shape) } -struct Context<'a, T: 'a> { +struct Context<'a> { context: &'a RewriteContext<'a>, - items: Vec<&'a T>, + items: Vec>, ident: &'a str, prefix: &'static str, suffix: &'static str, @@ -128,8 +246,8 @@ struct Context<'a, T: 'a> { custom_delims: Option<(&'a str, &'a str)>, } -impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { - pub fn new( +impl<'a> Context<'a> { + pub fn new>( context: &'a RewriteContext, items: impl Iterator, ident: &'a str, @@ -140,7 +258,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { item_max_width: usize, force_separator_tactic: Option, custom_delims: Option<(&'a str, &'a str)>, - ) -> Context<'a, T> { + ) -> Context<'a> { let used_width = extra_offset(ident, shape); // 1 = `()` let one_line_width = shape.width.saturating_sub(used_width + 2); @@ -153,7 +271,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1); Context { context, - items: items.collect(), + items: into_overflowable_list(items).collect(), ident, one_line_shape, nested_shape, @@ -167,7 +285,7 @@ impl<'a, T: 'a + Rewrite + ToExpr + Spanned> Context<'a, T> { } } - fn last_item(&self) -> Option<&&T> { + fn last_item(&self) -> Option<&OverflowableItem> { self.items.last() } @@ -465,25 +583,19 @@ fn need_block_indent(s: &str, shape: Shape) -> bool { }) } -fn can_be_overflowed<'a, T>(context: &RewriteContext, items: &[&T]) -> bool -where - T: Rewrite + Spanned + ToExpr + 'a, -{ +fn can_be_overflowed<'a>(context: &RewriteContext, items: &[OverflowableItem]) -> bool { items .last() .map_or(false, |x| x.can_be_overflowed(context, items.len())) } /// Returns a shape for the last argument which is going to be overflowed. -fn last_item_shape( - lists: &[&T], +fn last_item_shape( + lists: &[OverflowableItem], items: &[ListItem], shape: Shape, args_max_width: usize, -) -> Option -where - T: Rewrite + Spanned + ToExpr, -{ +) -> Option { let is_nested_call = lists .iter() .next() diff --git a/src/types.rs b/src/types.rs index 8ab89848407..e7282c13317 100644 --- a/src/types.rs +++ b/src/types.rs @@ -17,7 +17,7 @@ use syntax::source_map::{self, BytePos, Span}; use syntax::symbol::keywords; use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ToExpr}; +use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix}; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use macros::{rewrite_macro, MacroPosition}; use overflow; @@ -141,7 +141,7 @@ where } #[derive(Debug)] -enum SegmentParam<'a> { +pub enum SegmentParam<'a> { LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), Binding(&'a ast::TypeBinding), @@ -166,19 +166,6 @@ impl<'a> Spanned for SegmentParam<'a> { } } -impl<'a> ToExpr for SegmentParam<'a> { - fn to_expr(&self) -> Option<&ast::Expr> { - None - } - - fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { - match *self { - SegmentParam::Type(ty) => ty.can_be_overflowed(context, len), - _ => false, - } - } -} - impl<'a> Rewrite for SegmentParam<'a> { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { -- cgit 1.4.1-3-g733a5 From 63387824b31667b9830e8e84cdd4884162534aea Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 07:10:31 +0900 Subject: Avoid using to_expr as much as possible --- src/closures.rs | 11 +++------ src/expr.rs | 6 ++--- src/overflow.rs | 75 ++++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 54 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 153f3413f10..bde08931d18 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -361,13 +361,10 @@ pub fn rewrite_last_closure( /// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. pub fn args_have_many_closure(args: &[OverflowableItem]) -> bool { args.iter() - .filter(|arg| { - arg.to_expr() - .map(|e| match e.node { - ast::ExprKind::Closure(..) => true, - _ => false, - }) - .unwrap_or(false) + .filter_map(|arg| arg.to_expr()) + .filter(|expr| match expr.node { + ast::ExprKind::Closure(..) => true, + _ => false, }) .count() > 1 diff --git a/src/expr.rs b/src/expr.rs index 102fab346d7..06c9d355906 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1337,7 +1337,7 @@ pub fn rewrite_call( ) } -fn is_simple_expr(expr: &ast::Expr) -> bool { +pub fn is_simple_expr(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, @@ -1356,9 +1356,7 @@ fn is_simple_expr(expr: &ast::Expr) -> bool { } pub fn is_every_expr_simple(lists: &[OverflowableItem]) -> bool { - lists - .iter() - .all(|arg| arg.to_expr().map_or(false, is_simple_expr)) + lists.iter().all(OverflowableItem::is_simple) } pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { diff --git a/src/overflow.rs b/src/overflow.rs index 37d070cfd40..22b07fbc178 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -17,7 +17,7 @@ use syntax::{ast, ptr}; use closures; use expr::{ - can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, + can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, maybe_get_args_offset, }; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; @@ -70,6 +70,30 @@ impl<'a> OverflowableItem<'a> { } } + pub fn is_simple(&self) -> bool { + match self { + OverflowableItem::Expr(expr) => is_simple_expr(expr), + OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), + _ => false, + } + } + + pub fn is_expr(&self) -> bool { + match self { + OverflowableItem::Expr(..) => true, + OverflowableItem::MacroArg(MacroArg::Expr(..)) => true, + _ => false, + } + } + + pub fn is_nested_call(&self) -> bool { + match self { + OverflowableItem::Expr(expr) => is_nested_call(expr), + OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_nested_call(expr), + _ => false, + } + } + pub fn to_expr(&self) -> Option<&'a ast::Expr> { match self { OverflowableItem::Expr(expr) => Some(expr), @@ -303,23 +327,24 @@ impl<'a> Context<'a> { shape: Shape, ) -> Option { let last_item = self.last_item()?; - let rewrite = if let Some(expr) = last_item.to_expr() { - match expr.node { - // When overflowing the closure which consists of a single control flow expression, - // force to use block if its condition uses multi line. - ast::ExprKind::Closure(..) => { - // If the argument consists of multiple closures, we do not overflow - // the last closure. - if closures::args_have_many_closure(&self.items) { - None - } else { - closures::rewrite_last_closure(self.context, expr, shape) + let rewrite = match last_item { + OverflowableItem::Expr(ref expr) => { + match expr.node { + // When overflowing the closure which consists of a single control flow + // expression, force to use block if its condition uses multi line. + ast::ExprKind::Closure(..) => { + // If the argument consists of multiple closures, we do not overflow + // the last closure. + if closures::args_have_many_closure(&self.items) { + None + } else { + closures::rewrite_last_closure(self.context, expr, shape) + } } + _ => expr.rewrite(self.context, shape), } - _ => expr.rewrite(self.context, shape), } - } else { - last_item.rewrite(self.context, shape) + item @ _ => item.rewrite(self.context, shape), }; if let Some(rewrite) = rewrite { @@ -343,7 +368,7 @@ impl<'a> Context<'a> { fn try_overflow_last_item(&self, list_items: &mut Vec) -> DefinitiveListTactic { // 1 = "(" let combine_arg_with_callee = self.items.len() == 1 - && self.items[0].to_expr().is_some() + && self.items[0].is_expr() && self.ident.len() < self.context.config.tab_spaces(); let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, &self.items); @@ -351,12 +376,13 @@ impl<'a> Context<'a> { // first arguments. let placeholder = if overflow_last { let old_value = *self.context.force_one_line_chain.borrow(); - if !combine_arg_with_callee { - if let Some(ref expr) = self.last_item().and_then(|item| item.to_expr()) { - if is_method_call(expr) { - self.context.force_one_line_chain.replace(true); - } + match self.last_item() { + Some(OverflowableItem::Expr(expr)) + if !combine_arg_with_callee && is_method_call(expr) => + { + self.context.force_one_line_chain.replace(true); } + _ => (), } let result = last_item_shape( &self.items, @@ -596,12 +622,7 @@ fn last_item_shape( shape: Shape, args_max_width: usize, ) -> Option { - let is_nested_call = lists - .iter() - .next() - .and_then(|item| item.to_expr()) - .map_or(false, is_nested_call); - if items.len() == 1 && !is_nested_call { + if items.len() == 1 && !lists.iter().next()?.is_nested_call() { return Some(shape); } let offset = items.iter().rev().skip(1).fold(0, |acc, i| { -- cgit 1.4.1-3-g733a5 From 052ba6c5df9d67dd56ec069f588ab6efba0fadd0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 08:02:55 +0900 Subject: Move maybe_get_args_offset to overflow.rs --- src/expr.rs | 48 ------------------------------------------------ src/overflow.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 06c9d355906..09ab3da6920 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1259,54 +1259,6 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } -/// In case special-case style is required, returns an offset from which we start horizontal layout. -pub fn maybe_get_args_offset(callee_str: &str, args: &[OverflowableItem]) -> Option<(bool, usize)> { - if let Some(&(_, num_args_before)) = SPECIAL_MACRO_WHITELIST - .iter() - .find(|&&(s, _)| s == callee_str) - { - let all_simple = args.len() > num_args_before && is_every_expr_simple(args); - - Some((all_simple, num_args_before)) - } else { - None - } -} - -/// A list of `format!`-like macros, that take a long format string and a list of arguments to -/// format. -/// -/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of -/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, -/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). -const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ - // format! like macros - // From the Rust Standard Library. - ("eprint!", 0), - ("eprintln!", 0), - ("format!", 0), - ("format_args!", 0), - ("print!", 0), - ("println!", 0), - ("panic!", 0), - ("unreachable!", 0), - // From the `log` crate. - ("debug!", 0), - ("error!", 0), - ("info!", 0), - ("warn!", 0), - // write! like macros - ("assert!", 1), - ("debug_assert!", 1), - ("write!", 1), - ("writeln!", 1), - // assert_eq! like macros - ("assert_eq!", 2), - ("assert_ne!", 2), - ("debug_assert_eq!", 2), - ("debug_assert_ne!", 2), -]; - fn choose_separator_tactic(context: &RewriteContext, span: Span) -> Option { if context.inside_macro() { if span_ends_with_comma(context, span) { diff --git a/src/overflow.rs b/src/overflow.rs index 22b07fbc178..47979fa119c 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -18,7 +18,6 @@ use syntax::{ast, ptr}; use closures; use expr::{ can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, - maybe_get_args_offset, }; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use macros::MacroArg; @@ -32,6 +31,42 @@ use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_ use std::cmp::min; +const SHORT_ITEM_THRESHOLD: usize = 10; + +/// A list of `format!`-like macros, that take a long format string and a list of arguments to +/// format. +/// +/// Organized as a list of `(&str, usize)` tuples, giving the name of the macro and the number of +/// arguments before the format string (none for `format!("format", ...)`, one for `assert!(result, +/// "format", ...)`, two for `assert_eq!(left, right, "format", ...)`). +const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ + // format! like macros + // From the Rust Standard Library. + ("eprint!", 0), + ("eprintln!", 0), + ("format!", 0), + ("format_args!", 0), + ("print!", 0), + ("println!", 0), + ("panic!", 0), + ("unreachable!", 0), + // From the `log` crate. + ("debug!", 0), + ("error!", 0), + ("info!", 0), + ("warn!", 0), + // write! like macros + ("assert!", 1), + ("debug_assert!", 1), + ("write!", 1), + ("writeln!", 1), + // assert_eq! like macros + ("assert_eq!", 2), + ("assert_ne!", 2), + ("debug_assert_eq!", 2), + ("debug_assert_ne!", 2), +]; + pub enum OverflowableItem<'a> { Expr(&'a ast::Expr), GenericParam(&'a ast::GenericParam), @@ -178,8 +213,6 @@ where iter.map(|x| IntoOverflowableItem::into_overflowable_item(x)) } -const SHORT_ITEM_THRESHOLD: usize = 10; - pub fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext, ident: &'a str, @@ -661,3 +694,21 @@ fn no_long_items(list: &[ListItem]) -> bool { list.iter() .all(|item| item.inner_as_ref().len() <= SHORT_ITEM_THRESHOLD) } + +/// In case special-case style is required, returns an offset from which we start horizontal layout. +pub fn maybe_get_args_offset(callee_str: &str, args: &[OverflowableItem]) -> Option<(bool, usize)> { + if let Some(&(_, num_args_before)) = args + .get(0)? + .whitelist() + .iter() + .find(|&&(s, _)| s == callee_str) + { + let all_simple = args.len() > num_args_before + && is_every_expr_simple(&args[0..num_args_before]) + && is_every_expr_simple(&args[num_args_before + 1..]); + + Some((all_simple, num_args_before)) + } else { + None + } +} -- cgit 1.4.1-3-g733a5 From d7e1f0006a9fdb520d05e76d1b67cf326e70124c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 08:03:26 +0900 Subject: Put arguments of the fail attribute on the same line as println! --- src/attr.rs | 61 ++++++++++++--------------------------------------------- src/overflow.rs | 33 +++++++++++++++++++++++++++++-- src/patterns.rs | 1 + src/spanned.rs | 11 ++++++++++- 4 files changed, 55 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index aa1517167d8..19c6bdc2484 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -15,12 +15,12 @@ use config::lists::*; use config::IndentStyle; use expr::rewrite_literal; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use overflow; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use types::{rewrite_path, PathContext}; use utils::{count_newlines, mk_sp}; -use std::borrow::Cow; use syntax::ast; use syntax::source_map::{BytePos, Span, DUMMY_SP}; @@ -216,56 +216,21 @@ impl Rewrite for ast::MetaItem { } ast::MetaItemKind::List(ref list) => { let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; - - let has_comma = ::expr::span_ends_with_comma(context, self.span); - let trailing_comma = if has_comma { "," } else { "" }; - let combine = list.len() == 1 && match list[0].node { - ast::NestedMetaItemKind::Literal(..) => false, - ast::NestedMetaItemKind::MetaItem(ref inner_meta_item) => { - match inner_meta_item.node { - ast::MetaItemKind::List(..) => rewrite_path( - context, - PathContext::Type, - None, - &inner_meta_item.ident, - shape, - ) - .map_or(false, |s| s.len() + path.len() + 2 <= shape.width), - _ => false, - } - } - }; - - let argument_shape = argument_shape( - path.len() + 1, - 2 + trailing_comma.len(), - combine, - shape, + let has_trailing_comma = ::expr::span_ends_with_comma(context, self.span); + overflow::rewrite_with_parens( context, - )?; - let item_str = format_arg_list( + &path, list.iter(), - |nested_meta_item| nested_meta_item.span.lo(), - |nested_meta_item| nested_meta_item.span.hi(), - |nested_meta_item| nested_meta_item.rewrite(context, argument_shape), + // 1 = "]" + shape.sub_width(1)?, self.span, - context, - argument_shape, - // 3 = "()" and "]" - shape - .offset_left(path.len())? - .sub_width(3 + trailing_comma.len())?, - Some(context.config.width_heuristics().fn_call_width), - combine, - )?; - - let indent = if item_str.starts_with('\n') { - shape.indent.to_string_with_newline(context.config) - } else { - Cow::Borrowed("") - }; - - format!("{}({}{}{})", path, item_str, trailing_comma, indent) + context.config.width_heuristics().fn_call_width, + Some(if has_trailing_comma { + SeparatorTactic::Always + } else { + SeparatorTactic::Never + }), + )? } ast::MetaItemKind::NameValue(ref literal) => { let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; diff --git a/src/overflow.rs b/src/overflow.rs index 47979fa119c..a7fc9728666 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -67,10 +67,17 @@ const SPECIAL_MACRO_WHITELIST: &[(&str, usize)] = &[ ("debug_assert_ne!", 2), ]; +const SPECIAL_ATTR_WHITELIST: &[(&str, usize)] = &[ + // From the `failure` crate. + ("fail", 0), +]; + +#[derive(Debug)] pub enum OverflowableItem<'a> { Expr(&'a ast::Expr), GenericParam(&'a ast::GenericParam), MacroArg(&'a MacroArg), + NestedMetaItem(&'a ast::NestedMetaItem), SegmentParam(&'a SegmentParam<'a>), StructField(&'a ast::StructField), TuplePatField(&'a TuplePatField<'a>), @@ -98,6 +105,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::Expr(expr) => f(*expr), OverflowableItem::GenericParam(gp) => f(*gp), OverflowableItem::MacroArg(macro_arg) => f(*macro_arg), + OverflowableItem::NestedMetaItem(nmi) => f(*nmi), OverflowableItem::SegmentParam(sp) => f(*sp), OverflowableItem::StructField(sf) => f(*sf), OverflowableItem::TuplePatField(pat) => f(*pat), @@ -109,6 +117,13 @@ impl<'a> OverflowableItem<'a> { match self { OverflowableItem::Expr(expr) => is_simple_expr(expr), OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), + OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item.node { + ast::NestedMetaItemKind::Literal(..) => true, + ast::NestedMetaItemKind::MetaItem(ref meta_item) => match meta_item.node { + ast::MetaItemKind::Word => true, + _ => false, + }, + }, _ => false, } } @@ -149,6 +164,12 @@ impl<'a> OverflowableItem<'a> { MacroArg::Pat(..) => false, MacroArg::Item(..) => len == 1, }, + OverflowableItem::NestedMetaItem(nested_meta_item) if len == 1 => { + match nested_meta_item.node { + ast::NestedMetaItemKind::Literal(..) => false, + ast::NestedMetaItemKind::MetaItem(..) => true, + } + } OverflowableItem::SegmentParam(seg) => match seg { SegmentParam::Type(ty) => can_be_overflowed_type(context, ty, len), _ => false, @@ -158,6 +179,14 @@ impl<'a> OverflowableItem<'a> { _ => false, } } + + fn whitelist(&self) -> &'static [(&'static str, usize)] { + match self { + OverflowableItem::MacroArg(..) => SPECIAL_MACRO_WHITELIST, + OverflowableItem::NestedMetaItem(..) => SPECIAL_ATTR_WHITELIST, + _ => &[], + } + } } pub trait IntoOverflowableItem<'a>: Rewrite + Spanned { @@ -201,7 +230,7 @@ macro impl_into_overflowable_item_for_rustfmt_types { } } -impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, StructField, Ty); +impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, StructField, Ty); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); pub fn into_overflowable_list<'a, T>( @@ -655,7 +684,7 @@ fn last_item_shape( shape: Shape, args_max_width: usize, ) -> Option { - if items.len() == 1 && !lists.iter().next()?.is_nested_call() { + if items.len() == 1 && !lists.get(0)?.is_nested_call() { return Some(shape); } let offset = items.iter().rev().skip(1).fold(0, |acc, i| { diff --git a/src/patterns.rs b/src/patterns.rs index 8277a768e0e..bd4af3f7bba 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -264,6 +264,7 @@ impl Rewrite for FieldPat { } } +#[derive(Debug)] pub enum TuplePatField<'a> { Pat(&'a ptr::P), Dotdot(Span), diff --git a/src/spanned.rs b/src/spanned.rs index 504d18fb7fd..2488f3b428d 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::{ast, ptr, source_map::Span}; +use syntax::{ + ast, ptr, + source_map::{self, Span}, +}; use macros::MacroArg; use utils::{mk_sp, outer_attributes}; @@ -26,6 +29,12 @@ impl Spanned for ptr::P { } } +impl Spanned for source_map::Spanned { + fn span(&self) -> Span { + self.span + } +} + macro_rules! span_with_attrs_lo_hi { ($this:ident, $lo:expr, $hi:expr) => {{ let attrs = outer_attributes(&$this.attrs); -- cgit 1.4.1-3-g733a5 From 6e901c8f37235913a6361a97c84689f8768bf8b7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 08:04:34 +0900 Subject: Format and update test --- src/lib.rs | 3 +-- tests/target/enum.rs | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 14872cfc610..e77eacb5c34 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,8 +100,7 @@ pub enum ErrorKind { #[fail( display = "line formatted, but exceeded maximum width \ (maximum: {} (see `max_width` option), found: {})", - _0, - _1 + _0, _1 )] LineOverflow(usize, usize), /// Line ends in whitespace. diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 5da186cc201..57809b143f5 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -256,9 +256,7 @@ pub enum QlError { // (kind, input, expected) #[fail( display = "Could not find {}: Found: {}, expected: {:?}", - 0, - 1, - 2 + 0, 1, 2 )] ResolveError(&'static str, String, Option), } -- cgit 1.4.1-3-g733a5 From 4a15875f0709d0d8eaec5e138189a0783cc79dfe Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 23:27:03 +0900 Subject: Add a test for #3003 and run cargo fmt. --- src/config/file_lines.rs | 6 +++--- tests/source/expr.rs | 12 ++++++++++++ tests/target/expr.rs | 12 ++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 84ab0a8fc07..c5fd6eaa623 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -403,9 +403,9 @@ mod test { vec![Range::new(1, 7)], ), ] - .iter() - .cloned() - .collect(); + .iter() + .cloned() + .collect(); let file_lines = FileLines::from_ranges(ranges); let mut spans = file_lines.to_json_spans(); diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 7098d65f100..71c79223221 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -450,3 +450,15 @@ fn issue_2802() { a: some_much_much_longer_value, }) * some_value } + +fn issue_3003() { + let mut path: PathBuf = [ + env!("CARGO_MANIFEST_DIR"), + "tests", + "support", + "dejavu-fonts-ttf-2.37", + "ttf", + ] + .iter() + .collect(); +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 2e2312a11d5..2730b1c570c 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -529,3 +529,15 @@ fn issue_2802() { }) * some_value } + +fn issue_3003() { + let mut path: PathBuf = [ + env!("CARGO_MANIFEST_DIR"), + "tests", + "support", + "dejavu-fonts-ttf-2.37", + "ttf", + ] + .iter() + .collect(); +} -- cgit 1.4.1-3-g733a5 From 30048222f2ce28e8d5fe4907aa63512523e4a3e1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 30 Sep 2018 23:27:27 +0900 Subject: Consider a multi-lined array as a block-like expression --- src/chains.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 36c89eef20d..c2ca322eca1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -844,6 +844,7 @@ fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) -- cgit 1.4.1-3-g733a5 From 70c8e366a6be95f44c326ccd98564a06a8f45021 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 1 Oct 2018 00:07:18 +0900 Subject: Format a paren expr with double slash comment --- src/expr.rs | 56 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 674f719b5c7..3fbb0af10fb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -39,9 +39,9 @@ use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{ - colon_spaces, contains_skip, count_newlines, first_line_ends_with, first_line_width, - inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, - ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str, + colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, + last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, + semicolon_for_stmt, wrap_str, }; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -1438,13 +1438,15 @@ fn rewrite_paren( debug!("rewrite_paren, shape: {:?}", shape); // Extract comments within parens. + let mut pre_span; + let mut post_span; let mut pre_comment; let mut post_comment; let remove_nested_parens = context.config.remove_nested_parens(); loop { // 1 = "(" or ")" - let pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span.lo()); - let post_span = mk_sp(subexpr.span.hi(), span.hi() - BytePos(1)); + pre_span = mk_sp(span.lo() + BytePos(1), subexpr.span.lo()); + post_span = mk_sp(subexpr.span.hi(), span.hi() - BytePos(1)); pre_comment = rewrite_missing_comment(pre_span, shape, context)?; post_comment = rewrite_missing_comment(post_span, shape, context)?; @@ -1460,20 +1462,48 @@ fn rewrite_paren( break; } - // 1 `(` - let sub_shape = shape.offset_left(1).and_then(|s| s.sub_width(1))?; - + // 1 = `(` and `)` + let sub_shape = shape.offset_left(1)?.sub_width(1)?; let subexpr_str = subexpr.rewrite(context, sub_shape)?; - debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str); - - // 2 = `()` - if subexpr_str.contains('\n') || first_line_width(&subexpr_str) + 2 <= shape.width { + let fits_single_line = !pre_comment.contains("//") && !post_comment.contains("//"); + if fits_single_line { Some(format!("({}{}{})", pre_comment, &subexpr_str, post_comment)) } else { - None + rewrite_paren_in_multi_line(context, subexpr, shape, pre_span, post_span) } } +fn rewrite_paren_in_multi_line( + context: &RewriteContext, + subexpr: &ast::Expr, + shape: Shape, + pre_span: Span, + post_span: Span, +) -> Option { + let nested_indent = shape.indent.block_indent(context.config); + let nested_shape = Shape::indented(nested_indent, context.config); + let pre_comment = rewrite_missing_comment(pre_span, nested_shape, context)?; + let post_comment = rewrite_missing_comment(post_span, nested_shape, context)?; + let subexpr_str = subexpr.rewrite(context, nested_shape)?; + + let mut result = String::with_capacity(subexpr_str.len() * 2); + result.push('('); + if !pre_comment.is_empty() { + result.push_str(&nested_indent.to_string_with_newline(context.config)); + result.push_str(&pre_comment); + } + result.push_str(&nested_indent.to_string_with_newline(context.config)); + result.push_str(&subexpr_str); + if !post_comment.is_empty() { + result.push_str(&nested_indent.to_string_with_newline(context.config)); + result.push_str(&post_comment); + } + result.push_str(&shape.indent.to_string_with_newline(context.config)); + result.push(')'); + + Some(result) +} + fn rewrite_index( expr: &ast::Expr, index: &ast::Expr, -- cgit 1.4.1-3-g733a5 From 4b26723e555114592b4f4af7011cf5401ae46beb Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 2 Oct 2018 00:41:56 +0200 Subject: format_strings: take into account newline occurring within a rewritten line --- src/string.rs | 51 +++++++++++++++++++++++++++++-- tests/target/format_strings/issue-202.rs | 25 +++++++++++++++ tests/target/format_strings/issue-2833.rs | 15 +++++++++ tests/target/format_strings/issue-687.rs | 10 ++++++ tests/target/format_strings/issue564.rs | 7 +++++ 5 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 tests/target/format_strings/issue-202.rs create mode 100644 tests/target/format_strings/issue-2833.rs create mode 100644 tests/target/format_strings/issue-687.rs create mode 100644 tests/target/format_strings/issue564.rs (limited to 'src') diff --git a/src/string.rs b/src/string.rs index fd7ac89013a..6f84a8e2c02 100644 --- a/src/string.rs +++ b/src/string.rs @@ -19,12 +19,19 @@ use utils::wrap_str; const MIN_STRING: usize = 10; +/// Describes the layout of a piece of text. pub struct StringFormat<'a> { + /// The opening sequence of characters for the piece of text pub opener: &'a str, + /// The closing sequence of characters for the piece of text pub closer: &'a str, + /// The opening sequence of characters for a line pub line_start: &'a str, + /// The closing sequence of characters for a line pub line_end: &'a str, + /// The allocated box to fit the text into pub shape: Shape, + /// Trim trailing whitespaces pub trim_end: bool, pub config: &'a Config, } @@ -129,6 +136,9 @@ enum SnippetState { EndOfInput(String), /// The input could be broken and the returned snippet should be ended with a /// `[StringFormat::line_end]`. The next snippet needs to be indented. + /// The returned string is the line to print out and the number is the length that got read in + /// the text being rewritten. That length may be greater than the returned string if trailing + /// whitespaces got trimmed. LineEnd(String, usize), /// The input could be broken but the returned snippet should not be ended with a /// `[StringFormat::line_end]` because the whitespace is significant. Therefore, the next @@ -144,13 +154,23 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat // check if there is a line feed, in which case whitespaces needs to be kept. let mut index_minus_ws = index; for (i, grapheme) in input[0..=index].iter().enumerate().rev() { - if !trim_end && is_line_feed(grapheme) { - return SnippetState::Overflow(input[0..=i].join("").to_string(), i + 1); - } else if !is_whitespace(grapheme) { + if !is_whitespace(grapheme) { index_minus_ws = i; break; } } + // Take into account newlines occuring in input[0..=index], i.e., the possible next new + // line. If there is one, then text after it could be rewritten in a way that the available + // space is fully used. + for (i, grapheme) in input[0..=index].iter().enumerate() { + if is_line_feed(grapheme) { + if i < index_minus_ws || !trim_end { + return SnippetState::Overflow(input[0..=i].join("").to_string(), i + 1); + } + break; + } + } + let mut index_plus_ws = index; for (i, grapheme) in input[index + 1..].iter().enumerate() { if !trim_end && is_line_feed(grapheme) { @@ -224,6 +244,7 @@ fn is_punctuation(grapheme: &str) -> bool { #[cfg(test)] mod test { use super::{break_string, rewrite_string, SnippetState, StringFormat}; + use config::Config; use shape::{Indent, Shape}; use unicode_segmentation::UnicodeSegmentation; @@ -318,4 +339,28 @@ mod test { SnippetState::LineEnd("Neque in sem.".to_string(), 25) ); } + + #[test] + fn newline_in_candidate_line() { + let string = "Nulla\nconsequat erat at massa. Vivamus id mi."; + + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!( + break_string(25, false, &graphemes[..]), + SnippetState::Overflow("Nulla\n".to_string(), 6) + ); + assert_eq!( + break_string(25, true, &graphemes[..]), + SnippetState::Overflow("Nulla\n".to_string(), 6) + ); + + let mut config: Config = Default::default(); + config.set().max_width(27); + let fmt = StringFormat::new(Shape::legacy(25, Indent::empty()), &config); + let rewritten_string = rewrite_string(string, &fmt); + assert_eq!( + rewritten_string, + Some("\"Nulla\nconsequat erat at massa. \\\n Vivamus id mi.\"".to_string()) + ); + } } diff --git a/tests/target/format_strings/issue-202.rs b/tests/target/format_strings/issue-202.rs new file mode 100644 index 00000000000..2a2c24140dd --- /dev/null +++ b/tests/target/format_strings/issue-202.rs @@ -0,0 +1,25 @@ +// rustfmt-format_strings: true + +#[test] +fn compile_empty_program() { + let result = get_result(); + let expected = "; ModuleID = \'foo\' + +; Function Attrs: nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 + +declare i32 @write(i32, i8*, i32) + +declare i32 @putchar(i32) + +declare i32 @getchar() + +define i32 @main() { +entry: + ret i32 0 +} + +attributes #0 = { nounwind } +"; + assert_eq!(result, CString::new(expected).unwrap()); +} diff --git a/tests/target/format_strings/issue-2833.rs b/tests/target/format_strings/issue-2833.rs new file mode 100644 index 00000000000..70483532528 --- /dev/null +++ b/tests/target/format_strings/issue-2833.rs @@ -0,0 +1,15 @@ +// rustfmt-format_strings: true +// rustfmt-max_width: 80 + +fn test1() { + let expected = "\ +but Doctor Watson has to have it taken out for him and dusted, +"; +} + +fn test2() { + let expected = "\ +[Omitted long matching line] +but Doctor Watson has to have it taken out for him and dusted, +"; +} diff --git a/tests/target/format_strings/issue-687.rs b/tests/target/format_strings/issue-687.rs new file mode 100644 index 00000000000..21d292f9eb9 --- /dev/null +++ b/tests/target/format_strings/issue-687.rs @@ -0,0 +1,10 @@ +// rustfmt-format_strings: true + +fn foo() -> &'static str { + let sql = "ATTACH DATABASE ':memory:' AS my_attached; + BEGIN; + CREATE TABLE my_attached.foo(x INTEGER); + INSERT INTO my_attached.foo VALUES(42); + END;"; + sql +} diff --git a/tests/target/format_strings/issue564.rs b/tests/target/format_strings/issue564.rs new file mode 100644 index 00000000000..d9ef077c256 --- /dev/null +++ b/tests/target/format_strings/issue564.rs @@ -0,0 +1,7 @@ +// rustfmt-format_strings: true + +const USAGE: &'static str = " +Usage: codegen project + codegen regenerate + codegen verify +"; -- cgit 1.4.1-3-g733a5 From cbaed838d5e8c2fa40a019434b0ed9cec970ca61 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sat, 29 Sep 2018 12:16:03 +0300 Subject: No trailing comma in struct literals (Visual) --- Configurations.md | 2 +- src/expr.rs | 2 +- tests/target/chains-visual.rs | 16 ++++++++-------- tests/target/configs/indent_style/visual_struct_lit.rs | 2 +- tests/target/struct_lits_visual.rs | 10 +++++----- tests/target/struct_lits_visual_multiline.rs | 12 ++++++------ 6 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 824868bca09..66b5d840f3c 100644 --- a/Configurations.md +++ b/Configurations.md @@ -236,7 +236,7 @@ fn main() { ```rust fn main() { let lorem = Lorem { ipsum: dolor, - sit: amet, }; + sit: amet }; } ``` diff --git a/src/expr.rs b/src/expr.rs index 674f719b5c7..bdc5e82e6a9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1630,7 +1630,7 @@ fn rewrite_struct_lit<'a>( nested_shape, tactic, context, - force_no_trailing_comma || base.is_some(), + force_no_trailing_comma || base.is_some() || !context.use_block_indent(), ); write_list(&item_vec, &fmt)? diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index ab49096e55a..979816f3abb 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -55,11 +55,11 @@ fn main() { fn floaters() { let z = Foo { field1: val1, - field2: val2, }; + field2: val2 }; let x = Foo { field1: val1, - field2: val2, }.method_call() - .method_call(); + field2: val2 }.method_call() + .method_call(); let y = if cond { val1 } else { val2 }.method_call(); @@ -89,11 +89,11 @@ fn floaters() { .quux(); Foo { y: i_am_multi_line, - z: ok, }.baz(|| { - force(); - multiline(); - }) - .quux(); + z: ok }.baz(|| { + force(); + multiline(); + }) + .quux(); a + match x { true => "yay!", diff --git a/tests/target/configs/indent_style/visual_struct_lit.rs b/tests/target/configs/indent_style/visual_struct_lit.rs index b4effba0e8a..ec49021d330 100644 --- a/tests/target/configs/indent_style/visual_struct_lit.rs +++ b/tests/target/configs/indent_style/visual_struct_lit.rs @@ -3,5 +3,5 @@ fn main() { let lorem = Lorem { ipsum: dolor, - sit: amet, }; + sit: amet }; } diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 00e17589db1..a9627fb90f5 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -20,17 +20,17 @@ fn main() { Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment a: foo(), /* Comment */ // Comment - b: bar(), /* Comment */ }; + b: bar() /* Comment */ }; Foo { a: Bar, b: f() }; Quux { x: if cond { bar(); }, - y: baz(), }; + y: baz() }; Baz { x: yxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - z: zzzzz, /* test */ }; + z: zzzzz /* test */ }; A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante @@ -38,12 +38,12 @@ fn main() { first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; + second: Item }; Diagram { // o This graph demonstrates how // / \ significant whitespace is // o o preserved. // /|\ \ // o o o o - graph: G, } + graph: G } } diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs index d9312b7af4d..3f43ef0c981 100644 --- a/tests/target/struct_lits_visual_multiline.rs +++ b/tests/target/struct_lits_visual_multiline.rs @@ -17,20 +17,20 @@ fn main() { ..something }; Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; + b: bar() }; Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment a: foo(), /* Comment */ // Comment - b: bar(), /* Comment */ }; + b: bar() /* Comment */ }; Foo { a: Bar, - b: foo(), }; + b: foo() }; Quux { x: if cond { bar(); }, - y: baz(), }; + y: baz() }; A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante @@ -38,12 +38,12 @@ fn main() { first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; + second: Item }; Diagram { // o This graph demonstrates how // / \ significant whitespace is // o o preserved. // /|\ \ // o o o o - graph: G, } + graph: G } } -- cgit 1.4.1-3-g733a5 From dee68434e6046094bd3740618388d18077bf2a43 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sat, 6 Oct 2018 16:32:38 +0300 Subject: Overflow Visual functions even with one argument --- src/chains.rs | 10 +++++++++- src/expr.rs | 3 +-- tests/target/chains-visual.rs | 40 ++++++++++++++++++++-------------------- tests/target/issue-2985.rs | 40 ++++++++++++++++++++-------------------- 4 files changed, 50 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 36c89eef20d..4a4c123f4da 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -576,7 +576,15 @@ impl<'a> ChainFormatterShared<'a> { if all_in_one_line || extendable { // First we try to 'overflow' the last child and see if it looks better than using // vertical layout. - if let Some(one_line_shape) = last_shape.offset_left(almost_total) { + let one_line_shape = if context.use_block_indent() { + last_shape.offset_left(almost_total) + } else { + last_shape + .visual_indent(almost_total) + .sub_width(almost_total) + }; + + if let Some(one_line_shape) = one_line_shape { if let Some(rw) = last.rewrite(context, one_line_shape) { // We allow overflowing here only if both of the following conditions match: // 1. The entire chain fits in a single line except the last child. diff --git a/src/expr.rs b/src/expr.rs index bdc5e82e6a9..09257e59110 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1376,8 +1376,7 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { - context.use_block_indent() - || context.config.indent_style() == IndentStyle::Visual && args_len > 1 + context.use_block_indent() || context.config.indent_style() == IndentStyle::Visual } ast::ExprKind::Array(..) | ast::ExprKind::Call(..) diff --git a/tests/target/chains-visual.rs b/tests/target/chains-visual.rs index 979816f3abb..76ef99a4b59 100644 --- a/tests/target/chains-visual.rs +++ b/tests/target/chains-visual.rs @@ -37,8 +37,8 @@ fn main() { fffffffffffffffffffffffffffffffffff(a, { SCRIPT_TASK_ROOT.with(|root| { - *root.borrow_mut() = Some(&script_task); - }); + *root.borrow_mut() = Some(&script_task); + }); }); let suuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum = @@ -47,9 +47,9 @@ fn main() { .fold(0, |acc, x| acc + x); aaaaaaaaaaaaaaaa.map(|x| { - x += 1; - x - }) + x += 1; + x + }) .filter(some_mod::some_filter) } @@ -83,16 +83,16 @@ fn floaters() { .baz(); Foo { x: val }.baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); Foo { y: i_am_multi_line, z: ok }.baz(|| { - force(); - multiline(); - }) + force(); + multiline(); + }) .quux(); a + match x { @@ -137,9 +137,9 @@ fn issue1434() { for _ in 0..100 { let prototype_id = PrototypeIdData::from_reader::<_, B>(&mut self.file_cursor).chain_err(|| { - format!("could not read prototype ID at offset {:#010x}", - current_offset) - })?; + format!("could not read prototype ID at offset {:#010x}", + current_offset) + })?; } } @@ -147,12 +147,12 @@ fn issue2264() { { something.function() .map(|| { - if let a_very_very_very_very_very_very_very_very_long_variable = - compute_this_variable() - { - println!("Hello"); - } - }) + if let a_very_very_very_very_very_very_very_very_long_variable = + compute_this_variable() + { + println!("Hello"); + } + }) .collect(); } } diff --git a/tests/target/issue-2985.rs b/tests/target/issue-2985.rs index c82714aba52..37b216ea9b1 100644 --- a/tests/target/issue-2985.rs +++ b/tests/target/issue-2985.rs @@ -4,30 +4,30 @@ fn foo() { { let extra_encoder_settings = extra_encoder_settings.iter() .filter_map(|&(name, value)| { - value.split() - .next() - .something() - .something2() - .something3() - .something4() - }); + value.split() + .next() + .something() + .something2() + .something3() + .something4() + }); let extra_encoder_settings = extra_encoder_settings.iter() .filter_map(|&(name, value)| { - value.split() - .next() - .something() - .something2() - .something3() - .something4() - }) + value.split() + .next() + .something() + .something2() + .something3() + .something4() + }) .something(); if let Some(subpod) = pod.subpods.iter().find(|s| { - !s.plaintext - .as_ref() - .map(String::as_ref) - .unwrap_or("") - .is_empty() - }) { + !s.plaintext + .as_ref() + .map(String::as_ref) + .unwrap_or("") + .is_empty() + }) { do_something(); } } -- cgit 1.4.1-3-g733a5 From 003fc730e6007b569dedada8cdde7ce362f2f85c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 7 Oct 2018 00:52:06 +0900 Subject: Fix empty types being inserted to closure cc https://github.com/rust-lang/rust/pull/54229. --- src/items.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 17a9e529692..6a988d6127a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1816,12 +1816,9 @@ impl Rewrite for ast::FunctionRetTy { } } -fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool { +fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool { match ty.node { - ast::TyKind::Infer => { - let original = context.snippet(ty.span); - original != "_" - } + ast::TyKind::Infer => ty.span.hi() == pat_span.hi(), _ => false, } } @@ -1833,7 +1830,7 @@ impl Rewrite for ast::Arg { .pat .rewrite(context, Shape::legacy(shape.width, shape.indent))?; - if !is_empty_infer(context, &*self.ty) { + if !is_empty_infer(&*self.ty, self.pat.span) { if context.config.space_before_colon() { result.push_str(" "); } -- cgit 1.4.1-3-g733a5 From baa20dfcf1c1210c3b2fe2612f5111669e81d206 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 8 Oct 2018 13:40:10 +0900 Subject: Format a macro call with a single item-like argument --- src/macros.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 886e929c43f..7348e7a0315 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -44,6 +44,7 @@ use shape::{Indent, Shape}; use source_map::SpanUtils; use spanned::Spanned; use utils::{format_visibility, mk_sp, rewrite_ident, wrap_str}; +use visitor::FmtVisitor; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -271,6 +272,24 @@ pub fn rewrite_macro_inner( } } + if !arg_vec.is_empty() && arg_vec.iter().all(|arg| { + if let MacroArg::Item(..) = arg { + true + } else { + false + } + }) { + return rewrite_macro_with_items( + context, + &arg_vec, + ¯o_name, + shape, + style, + position, + mac.span, + ); + } + match style { DelimToken::Paren => { // Format macro invocation as function call, preserve the trailing @@ -1428,3 +1447,45 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) Some(result) } + +fn rewrite_macro_with_items( + context: &RewriteContext, + items: &[MacroArg], + macro_name: &str, + shape: Shape, + style: DelimToken, + position: MacroPosition, + span: Span, +) -> Option { + let (opener, closer) = match style { + DelimToken::Paren => ("(", ")"), + DelimToken::Bracket => ("[", "]"), + DelimToken::Brace => (" {", "}"), + _ => return None, + }; + let trailing_semicolon = match style { + DelimToken::Paren | DelimToken::Bracket if position == MacroPosition::Item => ";", + _ => "", + }; + + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = shape.indent.block_indent(context.config); + visitor.last_pos = context.snippet_provider.span_after(span, opener.trim()); + for item in items { + let item = match item { + MacroArg::Item(item) => item, + _ => return None, + }; + visitor.visit_item(&item); + } + + let mut result = String::with_capacity(256); + result.push_str(¯o_name); + result.push_str(opener); + result.push_str(&visitor.block_indent.to_string_with_newline(context.config)); + result.push_str(visitor.buffer.trim()); + result.push_str(&shape.indent.to_string_with_newline(context.config)); + result.push_str(closer); + result.push_str(trailing_semicolon); + return Some(result); +} -- cgit 1.4.1-3-g733a5 From 70177a08a47eb6e3a84cee4d92c0eb4ccbd125c4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 8 Oct 2018 13:49:24 +0900 Subject: Format a macro call with multile item-like arguments --- src/macros.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 7348e7a0315..dab27d8a073 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -64,6 +64,15 @@ pub enum MacroArg { Item(ptr::P), } +impl MacroArg { + fn is_item(&self) -> bool { + match self { + MacroArg::Item(..) => true, + _ => false, + } + } +} + impl Rewrite for ast::Item { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let mut visitor = ::visitor::FmtVisitor::from_context(context); @@ -260,6 +269,7 @@ pub fn rewrite_macro_inner( } return return_original_snippet_with_failure_marked(context, mac.span); } + _ if arg_vec.last().map_or(false, MacroArg::is_item) => continue, _ => return return_original_snippet_with_failure_marked(context, mac.span), } @@ -272,13 +282,7 @@ pub fn rewrite_macro_inner( } } - if !arg_vec.is_empty() && arg_vec.iter().all(|arg| { - if let MacroArg::Item(..) = arg { - true - } else { - false - } - }) { + if !arg_vec.is_empty() && arg_vec.iter().all(MacroArg::is_item) { return rewrite_macro_with_items( context, &arg_vec, -- cgit 1.4.1-3-g733a5 From f46082fbd8e5c347d018dd1889181fef2015c4bd Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 4 Oct 2018 09:16:08 +0200 Subject: rewrite_string: trim trailing whitespace in case the last_line fits in the given shape --- src/string.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 6f84a8e2c02..b5ba022a93c 100644 --- a/src/string.rs +++ b/src/string.rs @@ -98,7 +98,12 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option loop { // All the input starting at cur_start fits on the current line if graphemes.len() - cur_start <= cur_max_chars { - result.push_str(&graphemes[cur_start..].join("")); + let last_line = graphemes[cur_start..].join(""); + if fmt.trim_end { + result.push_str(&last_line.trim_right()); + } else { + result.push_str(&last_line); + } break; } @@ -363,4 +368,19 @@ mod test { Some("\"Nulla\nconsequat erat at massa. \\\n Vivamus id mi.\"".to_string()) ); } + + #[test] + fn last_line_fit_with_trailing_whitespaces() { + let string = "Vivamus id mi. "; + let config: Config = Default::default(); + let mut fmt = StringFormat::new(Shape::legacy(25, Indent::empty()), &config); + + fmt.trim_end = true; + let rewritten_string = rewrite_string(string, &fmt); + assert_eq!(rewritten_string, Some("\"Vivamus id mi.\"".to_string())); + + fmt.trim_end = false; // default value of trim_end + let rewritten_string = rewrite_string(string, &fmt); + assert_eq!(rewritten_string, Some("\"Vivamus id mi. \"".to_string())); + } } -- cgit 1.4.1-3-g733a5 From 2fc1de6b4a9369dc545e12a504d26a4b2ea06f57 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 4 Oct 2018 11:40:47 +0200 Subject: rewrite_string: do not overflow the next line when the line_start is not a whitespace --- src/string.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index b5ba022a93c..7589dca1bf9 100644 --- a/src/string.rs +++ b/src/string.rs @@ -64,7 +64,7 @@ impl<'a> StringFormat<'a> { /// Like max_chars_with_indent but the indentation is not substracted. /// This allows to fit more graphemes from the string on a line when - /// SnippetState::Overflow. + /// SnippetState::EndWithLineFeed. fn max_chars_without_indent(&self) -> Option { Some(self.config.max_width().checked_sub(self.line_end.len())?) } @@ -73,7 +73,8 @@ impl<'a> StringFormat<'a> { pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { let max_chars_with_indent = fmt.max_chars_with_indent()?; let max_chars_without_indent = fmt.max_chars_without_indent()?; - let indent = fmt.shape.indent.to_string_with_newline(fmt.config); + let indent_with_newline = fmt.shape.indent.to_string_with_newline(fmt.config); + let indent_without_newline = fmt.shape.indent.to_string(fmt.config); // Strip line breaks. // With this regex applied, all remaining whitespaces are significant @@ -95,6 +96,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // Snip a line at a time from `stripped_str` until it is used up. Push the snippet // onto result. let mut cur_max_chars = max_chars_with_indent; + let is_overflow_allowed = is_whitespace(fmt.line_start); loop { // All the input starting at cur_start fits on the current line if graphemes.len() - cur_start <= cur_max_chars { @@ -112,14 +114,21 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option SnippetState::LineEnd(line, len) => { result.push_str(&line); result.push_str(fmt.line_end); - result.push_str(&indent); + result.push_str(&indent_with_newline); result.push_str(fmt.line_start); cur_max_chars = max_chars_with_indent; cur_start += len; } - SnippetState::Overflow(line, len) => { + SnippetState::EndWithLineFeed(line, len) => { result.push_str(&line); - cur_max_chars = max_chars_without_indent; + if is_overflow_allowed { + // the next line can benefit from the full width + cur_max_chars = max_chars_without_indent; + } else { + result.push_str(&indent_without_newline); + result.push_str(fmt.line_start); + cur_max_chars = max_chars_with_indent; + } cur_start += len; } SnippetState::EndOfInput(line) => { @@ -141,14 +150,19 @@ enum SnippetState { EndOfInput(String), /// The input could be broken and the returned snippet should be ended with a /// `[StringFormat::line_end]`. The next snippet needs to be indented. + /// /// The returned string is the line to print out and the number is the length that got read in /// the text being rewritten. That length may be greater than the returned string if trailing /// whitespaces got trimmed. LineEnd(String, usize), - /// The input could be broken but the returned snippet should not be ended with a - /// `[StringFormat::line_end]` because the whitespace is significant. Therefore, the next - /// snippet should not be indented. - Overflow(String, usize), + /// The input could be broken but a newline is present that cannot be trimmed. The next snippet + /// to be rewritten *could* use more width than what is specified by the given shape. For + /// example with a multiline string, the next snippet does not need to be indented, allowing + /// more characters to be fit within a line. + /// + /// The returned string is the line to print out and the number is the length that got read in + /// the text being rewritten. + EndWithLineFeed(String, usize), } /// Break the input string at a boundary character around the offset `max_chars`. A boundary @@ -170,7 +184,7 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat for (i, grapheme) in input[0..=index].iter().enumerate() { if is_line_feed(grapheme) { if i < index_minus_ws || !trim_end { - return SnippetState::Overflow(input[0..=i].join("").to_string(), i + 1); + return SnippetState::EndWithLineFeed(input[0..=i].join("").to_string(), i + 1); } break; } @@ -179,7 +193,7 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat let mut index_plus_ws = index; for (i, grapheme) in input[index + 1..].iter().enumerate() { if !trim_end && is_line_feed(grapheme) { - return SnippetState::Overflow( + return SnippetState::EndWithLineFeed( input[0..=index + 1 + i].join("").to_string(), index + 2 + i, ); @@ -314,11 +328,11 @@ mod test { let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( break_string(15, false, &graphemes[..]), - SnippetState::Overflow("Neque in sem. \n".to_string(), 20) + SnippetState::EndWithLineFeed("Neque in sem. \n".to_string(), 20) ); assert_eq!( break_string(25, false, &graphemes[..]), - SnippetState::Overflow("Neque in sem. \n".to_string(), 20) + SnippetState::EndWithLineFeed("Neque in sem. \n".to_string(), 20) ); // if `StringFormat::line_end` is true, then the line feed does not matter anymore assert_eq!( @@ -352,11 +366,11 @@ mod test { let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( break_string(25, false, &graphemes[..]), - SnippetState::Overflow("Nulla\n".to_string(), 6) + SnippetState::EndWithLineFeed("Nulla\n".to_string(), 6) ); assert_eq!( break_string(25, true, &graphemes[..]), - SnippetState::Overflow("Nulla\n".to_string(), 6) + SnippetState::EndWithLineFeed("Nulla\n".to_string(), 6) ); let mut config: Config = Default::default(); @@ -383,4 +397,50 @@ mod test { let rewritten_string = rewrite_string(string, &fmt); assert_eq!(rewritten_string, Some("\"Vivamus id mi. \"".to_string())); } + + #[test] + fn overflow_in_non_string_content() { + let comment = "Aenean metus.\nVestibulum ac lacus. Vivamus porttitor"; + let config: Config = Default::default(); + let fmt = StringFormat { + opener: "", + closer: "", + line_start: "// ", + line_end: "", + shape: Shape::legacy(30, Indent::from_width(&config, 8)), + trim_end: true, + config: &config, + }; + + assert_eq!( + rewrite_string(comment, &fmt), + Some( + "Aenean metus.\n // Vestibulum ac lacus. Vivamus\n // porttitor" + .to_string() + ) + ); + } + + #[test] + fn overflow_in_non_string_content_with_line_end() { + let comment = "Aenean metus.\nVestibulum ac lacus. Vivamus porttitor"; + let config: Config = Default::default(); + let fmt = StringFormat { + opener: "", + closer: "", + line_start: "// ", + line_end: "@", + shape: Shape::legacy(30, Indent::from_width(&config, 8)), + trim_end: true, + config: &config, + }; + + assert_eq!( + rewrite_string(comment, &fmt), + Some( + "Aenean metus.\n // Vestibulum ac lacus. Vivamus@\n // porttitor" + .to_string() + ) + ); + } } -- cgit 1.4.1-3-g733a5 From 3205e17cc379684baa7ec098add6929096d28644 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 4 Oct 2018 13:56:57 +0200 Subject: rewrite_string: handle newlines in the last line that fits in the shape for cases where line_start is not a whitespace --- src/string.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 7589dca1bf9..39a0596b9a9 100644 --- a/src/string.rs +++ b/src/string.rs @@ -96,15 +96,35 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // Snip a line at a time from `stripped_str` until it is used up. Push the snippet // onto result. let mut cur_max_chars = max_chars_with_indent; - let is_overflow_allowed = is_whitespace(fmt.line_start); + let is_bareline_ok = fmt.line_start.is_empty() || is_whitespace(fmt.line_start); loop { // All the input starting at cur_start fits on the current line if graphemes.len() - cur_start <= cur_max_chars { - let last_line = graphemes[cur_start..].join(""); - if fmt.trim_end { - result.push_str(&last_line.trim_right()); + // trim trailing whitespaces + let graphemes_minus_ws = if !fmt.trim_end { + &graphemes[cur_start..] } else { - result.push_str(&last_line); + match graphemes[cur_start..] + .iter() + .rposition(|grapheme| !is_whitespace(grapheme)) + { + Some(index) => &graphemes[cur_start..=cur_start + index], + None => &graphemes[cur_start..], + } + }; + if is_bareline_ok { + // new lines don't need to start with line_start + result.push_str(&graphemes_minus_ws.join("")); + } else { + // new lines need to be indented and prefixed with line_start + for grapheme in graphemes_minus_ws { + if is_line_feed(grapheme) { + result.push_str(&indent_with_newline); + result.push_str(fmt.line_start); + } else { + result.push_str(grapheme); + } + } } break; } @@ -121,7 +141,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option } SnippetState::EndWithLineFeed(line, len) => { result.push_str(&line); - if is_overflow_allowed { + if is_bareline_ok { // the next line can benefit from the full width cur_max_chars = max_chars_without_indent; } else { @@ -171,13 +191,10 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat let break_at = |index /* grapheme at index is included */| { // Take in any whitespaces to the left/right of `input[index]` and // check if there is a line feed, in which case whitespaces needs to be kept. - let mut index_minus_ws = index; - for (i, grapheme) in input[0..=index].iter().enumerate().rev() { - if !is_whitespace(grapheme) { - index_minus_ws = i; - break; - } - } + let index_minus_ws = input[0..=index] + .iter() + .rposition(|grapheme| !is_whitespace(grapheme)) + .unwrap_or(index); // Take into account newlines occuring in input[0..=index], i.e., the possible next new // line. If there is one, then text after it could be rewritten in a way that the available // space is fully used. @@ -398,6 +415,27 @@ mod test { assert_eq!(rewritten_string, Some("\"Vivamus id mi. \"".to_string())); } + #[test] + fn last_line_fit_with_newline() { + let string = "Vivamus id mi.\nVivamus id mi."; + let config: Config = Default::default(); + let fmt = StringFormat { + opener: "", + closer: "", + line_start: "// ", + line_end: "", + shape: Shape::legacy(100, Indent::from_width(&config, 4)), + trim_end: true, + config: &config, + }; + + let rewritten_string = rewrite_string(string, &fmt); + assert_eq!( + rewritten_string, + Some("Vivamus id mi.\n // Vivamus id mi.".to_string()) + ); + } + #[test] fn overflow_in_non_string_content() { let comment = "Aenean metus.\nVestibulum ac lacus. Vivamus porttitor"; -- cgit 1.4.1-3-g733a5 From 1c6a2e3de8789a70007fe9bf85d4c945e1e15a93 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 5 Oct 2018 17:09:17 +0200 Subject: rewrite_string: take care of blank lines appearing within the last line --- src/string.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 39a0596b9a9..dcedeed1114 100644 --- a/src/string.rs +++ b/src/string.rs @@ -119,6 +119,10 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option // new lines need to be indented and prefixed with line_start for grapheme in graphemes_minus_ws { if is_line_feed(grapheme) { + // take care of blank lines + if fmt.trim_end && result.ends_with(' ') { + result = result.trim_right().to_string(); + } result.push_str(&indent_with_newline); result.push_str(fmt.line_start); } else { @@ -140,6 +144,9 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option cur_start += len; } SnippetState::EndWithLineFeed(line, len) => { + if line == "\n" && fmt.trim_end { + result = result.trim_right().to_string(); + } result.push_str(&line); if is_bareline_ok { // the next line can benefit from the full width @@ -189,8 +196,8 @@ enum SnippetState { /// character is either a punctuation or a whitespace. fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetState { let break_at = |index /* grapheme at index is included */| { - // Take in any whitespaces to the left/right of `input[index]` and - // check if there is a line feed, in which case whitespaces needs to be kept. + // Take in any whitespaces to the left/right of `input[index]` while + // preserving line feeds let index_minus_ws = input[0..=index] .iter() .rposition(|grapheme| !is_whitespace(grapheme)) @@ -481,4 +488,40 @@ mod test { ) ); } + + #[test] + fn blank_line_with_non_empty_line_start() { + let config: Config = Default::default(); + let mut fmt = StringFormat { + opener: "", + closer: "", + line_start: "// ", + line_end: "", + shape: Shape::legacy(30, Indent::from_width(&config, 4)), + trim_end: true, + config: &config, + }; + + let comment = "Aenean metus. Vestibulum\n\nac lacus. Vivamus porttitor"; + assert_eq!( + rewrite_string(comment, &fmt), + Some( + "Aenean metus. Vestibulum\n //\n // ac lacus. Vivamus porttitor".to_string() + ) + ); + + fmt.shape = Shape::legacy(15, Indent::from_width(&config, 4)); + let comment = "Aenean\n\nmetus. Vestibulum ac lacus. Vivamus porttitor"; + assert_eq!( + rewrite_string(comment, &fmt), + Some( + r#"Aenean + // + // metus. Vestibulum + // ac lacus. Vivamus + // porttitor"# + .to_string() + ) + ); + } } -- cgit 1.4.1-3-g733a5 From bb7442802abe354a0ed844ec237cd20969789224 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sun, 7 Oct 2018 22:53:48 +0200 Subject: rewrite_string: retain blank lines that are trailing --- src/string.rs | 95 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index dcedeed1114..daca59e8702 100644 --- a/src/string.rs +++ b/src/string.rs @@ -100,36 +100,20 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option loop { // All the input starting at cur_start fits on the current line if graphemes.len() - cur_start <= cur_max_chars { - // trim trailing whitespaces - let graphemes_minus_ws = if !fmt.trim_end { - &graphemes[cur_start..] - } else { - match graphemes[cur_start..] - .iter() - .rposition(|grapheme| !is_whitespace(grapheme)) - { - Some(index) => &graphemes[cur_start..=cur_start + index], - None => &graphemes[cur_start..], - } - }; - if is_bareline_ok { - // new lines don't need to start with line_start - result.push_str(&graphemes_minus_ws.join("")); - } else { - // new lines need to be indented and prefixed with line_start - for grapheme in graphemes_minus_ws { - if is_line_feed(grapheme) { - // take care of blank lines - if fmt.trim_end && result.ends_with(' ') { - result = result.trim_right().to_string(); - } - result.push_str(&indent_with_newline); + for (i, grapheme) in graphemes[cur_start..].iter().enumerate() { + if is_line_feed(grapheme) { + // take care of blank lines + result = trim_right_but_line_feed(fmt.trim_end, result); + result.push_str("\n"); + if !is_bareline_ok && cur_start + i + 1 < graphemes.len() { + result.push_str(&indent_without_newline); result.push_str(fmt.line_start); - } else { - result.push_str(grapheme); } + } else { + result.push_str(grapheme); } } + result = trim_right_but_line_feed(fmt.trim_end, result); break; } @@ -169,6 +153,18 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option wrap_str(result, fmt.config.max_width(), fmt.shape) } +/// Trims whitespaces to the right except for the line feed character. +fn trim_right_but_line_feed(trim_end: bool, result: String) -> String { + let whitespace_except_line_feed = |c: char| c.is_whitespace() && c != '\n'; + if trim_end && result.ends_with(whitespace_except_line_feed) { + result + .trim_right_matches(whitespace_except_line_feed) + .to_string() + } else { + result + } +} + /// Result of breaking a string so it fits in a line and the state it ended in. /// The state informs about what to do with the snippet and how to continue the breaking process. #[derive(Debug, PartialEq)] @@ -198,17 +194,22 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat let break_at = |index /* grapheme at index is included */| { // Take in any whitespaces to the left/right of `input[index]` while // preserving line feeds + let not_whitespace_except_line_feed = |g| is_line_feed(g) || !is_whitespace(g); let index_minus_ws = input[0..=index] .iter() - .rposition(|grapheme| !is_whitespace(grapheme)) + .rposition(|grapheme| not_whitespace_except_line_feed(grapheme)) .unwrap_or(index); // Take into account newlines occuring in input[0..=index], i.e., the possible next new // line. If there is one, then text after it could be rewritten in a way that the available // space is fully used. for (i, grapheme) in input[0..=index].iter().enumerate() { if is_line_feed(grapheme) { - if i < index_minus_ws || !trim_end { - return SnippetState::EndWithLineFeed(input[0..=i].join("").to_string(), i + 1); + if i <= index_minus_ws { + let mut line = input[0..i].join(""); + if trim_end { + line = line.trim_right().to_string(); + } + return SnippetState::EndWithLineFeed(format!("{}\n", line), i + 1); } break; } @@ -221,7 +222,7 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat input[0..=index + 1 + i].join("").to_string(), index + 2 + i, ); - } else if !is_whitespace(grapheme) { + } else if not_whitespace_except_line_feed(grapheme) { index_plus_ws = index + i; break; } @@ -524,4 +525,38 @@ mod test { ) ); } + + #[test] + fn retain_blank_lines() { + let config: Config = Default::default(); + let fmt = StringFormat { + opener: "", + closer: "", + line_start: "// ", + line_end: "", + shape: Shape::legacy(20, Indent::from_width(&config, 4)), + trim_end: true, + config: &config, + }; + + let comment = "Aenean\n\nmetus. Vestibulum ac lacus.\n\n"; + assert_eq!( + rewrite_string(comment, &fmt), + Some( + "Aenean\n //\n // metus. Vestibulum ac\n // lacus.\n //\n".to_string() + ) + ); + + let comment = "Aenean\n\nmetus. Vestibulum ac lacus.\n"; + assert_eq!( + rewrite_string(comment, &fmt), + Some("Aenean\n //\n // metus. Vestibulum ac\n // lacus.\n".to_string()) + ); + + let comment = "Aenean\n \nmetus. Vestibulum ac lacus."; + assert_eq!( + rewrite_string(comment, &fmt), + Some("Aenean\n //\n // metus. Vestibulum ac\n // lacus.".to_string()) + ); + } } -- cgit 1.4.1-3-g733a5 From 8b3788d875a921e367c7df014eb2456cdde30eac Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sun, 7 Oct 2018 22:57:07 +0200 Subject: rewrite_string: allow to break on a boundary character that is on edge --- src/string.rs | 89 +++++++++++++++++++++++++++-------- tests/target/comment5.rs | 4 +- tests/target/enum.rs | 4 +- tests/target/struct_lits.rs | 4 +- tests/target/struct_lits_multiline.rs | 4 +- 5 files changed, 78 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index daca59e8702..6a888cf8318 100644 --- a/src/string.rs +++ b/src/string.rs @@ -118,7 +118,12 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option } // The input starting at cur_start needs to be broken - match break_string(cur_max_chars, fmt.trim_end, &graphemes[cur_start..]) { + match break_string( + cur_max_chars, + fmt.trim_end, + fmt.line_end, + &graphemes[cur_start..], + ) { SnippetState::LineEnd(line, len) => { result.push_str(&line); result.push_str(fmt.line_end); @@ -190,7 +195,7 @@ enum SnippetState { /// Break the input string at a boundary character around the offset `max_chars`. A boundary /// character is either a punctuation or a whitespace. -fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetState { +fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str]) -> SnippetState { let break_at = |index /* grapheme at index is included */| { // Take in any whitespaces to the left/right of `input[index]` while // preserving line feeds @@ -242,6 +247,17 @@ fn break_string(max_chars: usize, trim_end: bool, input: &[&str]) -> SnippetStat }; // Find the position in input for breaking the string + if line_end.is_empty() + && trim_end + && !is_whitespace(input[max_chars - 1]) + && is_whitespace(input[max_chars]) + { + // At a breaking point already + // The line won't invalidate the rewriting because: + // - no extra space needed for the line_end character + // - extra whitespaces to the right can be trimmed + return break_at(max_chars - 1); + } match input[0..max_chars] .iter() .rposition(|grapheme| is_whitespace(grapheme)) @@ -304,11 +320,11 @@ mod test { let string = "Placerat felis. Mauris porta ante sagittis purus."; let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(20, false, &graphemes[..]), + break_string(20, false, "", &graphemes[..]), SnippetState::LineEnd("Placerat felis. ".to_string(), 16) ); assert_eq!( - break_string(20, true, &graphemes[..]), + break_string(20, true, "", &graphemes[..]), SnippetState::LineEnd("Placerat felis.".to_string(), 16) ); } @@ -318,7 +334,7 @@ mod test { let string = "Placerat_felis._Mauris_porta_ante_sagittis_purus."; let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(20, false, &graphemes[..]), + break_string(20, false, "", &graphemes[..]), SnippetState::LineEnd("Placerat_felis.".to_string(), 15) ); } @@ -328,11 +344,11 @@ mod test { let string = "Venenatis_tellus_vel_tellus. Aliquam aliquam dolor at justo."; let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(20, false, &graphemes[..]), + break_string(20, false, "", &graphemes[..]), SnippetState::LineEnd("Venenatis_tellus_vel_tellus. ".to_string(), 29) ); assert_eq!( - break_string(20, true, &graphemes[..]), + break_string(20, true, "", &graphemes[..]), SnippetState::LineEnd("Venenatis_tellus_vel_tellus.".to_string(), 29) ); } @@ -342,7 +358,7 @@ mod test { let string = "Venenatis_tellus_vel_tellus"; let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(20, false, &graphemes[..]), + break_string(20, false, "", &graphemes[..]), SnippetState::EndOfInput("Venenatis_tellus_vel_tellus".to_string()) ); } @@ -352,21 +368,21 @@ mod test { let string = "Neque in sem. \n Pellentesque tellus augue."; let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(15, false, &graphemes[..]), + break_string(15, false, "", &graphemes[..]), SnippetState::EndWithLineFeed("Neque in sem. \n".to_string(), 20) ); assert_eq!( - break_string(25, false, &graphemes[..]), + break_string(25, false, "", &graphemes[..]), SnippetState::EndWithLineFeed("Neque in sem. \n".to_string(), 20) ); - // if `StringFormat::line_end` is true, then the line feed does not matter anymore + assert_eq!( - break_string(15, true, &graphemes[..]), - SnippetState::LineEnd("Neque in sem.".to_string(), 26) + break_string(15, true, "", &graphemes[..]), + SnippetState::LineEnd("Neque in sem.".to_string(), 19) ); assert_eq!( - break_string(25, true, &graphemes[..]), - SnippetState::LineEnd("Neque in sem.".to_string(), 26) + break_string(25, true, "", &graphemes[..]), + SnippetState::EndWithLineFeed("Neque in sem.\n".to_string(), 20) ); } @@ -375,11 +391,11 @@ mod test { let string = "Neque in sem. Pellentesque tellus augue."; let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(20, false, &graphemes[..]), + break_string(20, false, "", &graphemes[..]), SnippetState::LineEnd("Neque in sem. ".to_string(), 25) ); assert_eq!( - break_string(20, true, &graphemes[..]), + break_string(20, true, "", &graphemes[..]), SnippetState::LineEnd("Neque in sem.".to_string(), 25) ); } @@ -390,11 +406,11 @@ mod test { let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); assert_eq!( - break_string(25, false, &graphemes[..]), + break_string(25, false, "", &graphemes[..]), SnippetState::EndWithLineFeed("Nulla\n".to_string(), 6) ); assert_eq!( - break_string(25, true, &graphemes[..]), + break_string(25, true, "", &graphemes[..]), SnippetState::EndWithLineFeed("Nulla\n".to_string(), 6) ); @@ -559,4 +575,39 @@ mod test { Some("Aenean\n //\n // metus. Vestibulum ac\n // lacus.".to_string()) ); } + + #[test] + fn boundary_on_edge() { + let config: Config = Default::default(); + let mut fmt = StringFormat { + opener: "", + closer: "", + line_start: "// ", + line_end: "", + shape: Shape::legacy(13, Indent::from_width(&config, 4)), + trim_end: true, + config: &config, + }; + + let comment = "Aenean metus. Vestibulum ac lacus."; + assert_eq!( + rewrite_string(comment, &fmt), + Some("Aenean metus.\n // Vestibulum ac\n // lacus.".to_string()) + ); + + fmt.trim_end = false; + let comment = "Vestibulum ac lacus."; + assert_eq!( + rewrite_string(comment, &fmt), + Some("Vestibulum \n // ac lacus.".to_string()) + ); + + fmt.trim_end = true; + fmt.line_end = "\\"; + let comment = "Vestibulum ac lacus."; + assert_eq!( + rewrite_string(comment, &fmt), + Some("Vestibulum\\\n // ac lacus.".to_string()) + ); + } } diff --git a/tests/target/comment5.rs b/tests/target/comment5.rs index c52f9b38977..82d171e6f6a 100644 --- a/tests/target/comment5.rs +++ b/tests/target/comment5.rs @@ -2,8 +2,8 @@ // rustfmt-wrap_comments: true //@ special comment -//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam -//@ lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam +//@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec adiam lectus. +//@ Sed sit amet ipsum mauris. Maecenas congue ligula ac quam //@ //@ foo fn test() {} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 57809b143f5..6bc355bc807 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -145,8 +145,8 @@ pub enum Bencoding<'i> { Int(i64), List(Vec>), /// A bencoded dict value. The first element the slice of bytes in the - /// source that the dict is composed of. The second is the dict, - /// decoded into an ordered map. + /// source that the dict is composed of. The second is the dict, decoded + /// into an ordered map. // TODO make Dict "structlike" AKA name the two values. Dict(&'i [u8], BTreeMap<&'i [u8], Bencoding<'i>>), } diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index fc504e5d39b..d3bc364c350 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -40,8 +40,8 @@ fn main() { A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. + // Donec et mollis dolor. first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. diff --git a/tests/target/struct_lits_multiline.rs b/tests/target/struct_lits_multiline.rs index c831dc7a8ba..b29aafd0548 100644 --- a/tests/target/struct_lits_multiline.rs +++ b/tests/target/struct_lits_multiline.rs @@ -50,8 +50,8 @@ fn main() { A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit - // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante - // hendrerit. Donec et mollis dolor. + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. + // Donec et mollis dolor. first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. -- cgit 1.4.1-3-g733a5 From 0279b7d02c40b060d5d5881f993bb57ae3ab1da3 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Mon, 8 Oct 2018 14:39:16 -0300 Subject: Replace `isatty` crate with `atty` The `isatty` crate has been deprecated and a replacement has been released for it called `atty`. It offers a nicer API and the code change to adapt is trivial. Signed-off-by: Otavio Salvador --- Cargo.lock | 14 +------------- Cargo.toml | 2 +- src/config/options.rs | 4 ++-- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 2a6380d1bdf..558b12dfa28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -245,17 +245,6 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "isatty" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itertools" version = "0.7.8" @@ -603,13 +592,13 @@ name = "rustfmt-nightly" version = "0.99.5" dependencies = [ "assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -876,7 +865,6 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" diff --git a/Cargo.toml b/Cargo.toml index 44646bdd4d9..0359917d67a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ cargo-fmt = [] rustfmt-format-diff = [] [dependencies] -isatty = "0.1" +atty = "0.2" itertools = "0.7" toml = "0.4" serde = "1.0" diff --git a/src/config/options.rs b/src/config/options.rs index 34b6ea0dde6..a4ba21b53cf 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -12,7 +12,7 @@ use config::config_type::ConfigType; use config::lists::*; use config::{Config, FileName}; -use isatty::stdout_isatty; +use atty; use std::collections::HashSet; use std::path::{Path, PathBuf}; @@ -297,7 +297,7 @@ impl Color { match self { Color::Always => true, Color::Never => false, - Color::Auto => stdout_isatty(), + Color::Auto => atty::is(atty::Stream::Stdout), } } } diff --git a/src/lib.rs b/src/lib.rs index e77eacb5c34..b8f9d4cfb6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,9 +16,9 @@ #[macro_use] extern crate derive_new; +extern crate atty; extern crate diff; extern crate failure; -extern crate isatty; extern crate itertools; #[cfg(test)] #[macro_use] -- cgit 1.4.1-3-g733a5 From c0b7222e2d33843102060d222fbe60a55ec438b5 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 8 Oct 2018 11:44:23 +0200 Subject: handle itemized items inside comments --- src/comment.rs | 175 ++++++++++++++++++++++++-------- tests/source/itemized-blocks/no_wrap.rs | 46 +++++++++ tests/source/itemized-blocks/wrap.rs | 54 ++++++++++ tests/target/itemized-blocks/no_wrap.rs | 46 +++++++++ tests/target/itemized-blocks/wrap.rs | 91 +++++++++++++++++ 5 files changed, 371 insertions(+), 41 deletions(-) create mode 100644 tests/source/itemized-blocks/no_wrap.rs create mode 100644 tests/source/itemized-blocks/wrap.rs create mode 100644 tests/target/itemized-blocks/no_wrap.rs create mode 100644 tests/target/itemized-blocks/wrap.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d4af68e7d25..41301527653 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -433,6 +433,58 @@ impl CodeBlockAttribute { } } +/// Block that is formatted as an item. +/// +/// An item starts with either a star `*` or a dash `-`. Different level of indentation are +/// handled. +struct ItemizedBlock { + /// the number of whitespaces up to the item sigil + indent: usize, + /// the string that marks the start of an item + opener: String, + /// sequence of whitespaces to prefix new lines that are part of the item + line_start: String, +} + +impl ItemizedBlock { + /// Returns true if the line is formatted as an item + fn is_itemized_line(line: &str) -> bool { + let trimmed = line.trim_left(); + trimmed.starts_with("* ") || trimmed.starts_with("- ") + } + + /// Creates a new ItemizedBlock described with the given line. + /// The `is_itemized_line` needs to be called first. + fn new(line: &str) -> ItemizedBlock { + let space_to_sigil = line.chars().take_while(|c| c.is_whitespace()).count(); + let indent = space_to_sigil + 2; + ItemizedBlock { + indent, + opener: line[..indent].to_string(), + line_start: " ".repeat(indent), + } + } + + /// Returns a `StringFormat` used for formatting the content of an item + fn create_string_format<'a>(&'a self, fmt: &'a StringFormat) -> StringFormat<'a> { + StringFormat { + opener: "", + closer: "", + line_start: "", + line_end: "", + shape: Shape::legacy(fmt.shape.width.saturating_sub(self.indent), Indent::empty()), + trim_end: true, + config: fmt.config, + } + } + + /// Returns true if the line is part of the current itemized block + fn in_block(&self, line: &str) -> bool { + !ItemizedBlock::is_itemized_line(line) + && self.indent <= line.chars().take_while(|c| c.is_whitespace()).count() + } +} + fn rewrite_comment_inner( orig: &str, block_style: bool, @@ -493,15 +545,17 @@ fn rewrite_comment_inner( let mut code_block_buffer = String::with_capacity(128); let mut is_prev_line_multi_line = false; let mut code_block_attr = None; + let mut item_block_buffer = String::with_capacity(128); + let mut item_block: Option = None; let comment_line_separator = format!("{}{}", indent_str, line_start); - let join_code_block_with_comment_line_separator = |s: &str| { + let join_block = |s: &str, sep: &str| { let mut result = String::with_capacity(s.len() + 128); let mut iter = s.lines().peekable(); while let Some(line) = iter.next() { result.push_str(line); result.push_str(match iter.peek() { - Some(next_line) if next_line.is_empty() => comment_line_separator.trim_right(), - Some(..) => &comment_line_separator, + Some(next_line) if next_line.is_empty() => sep.trim_right(), + Some(..) => &sep, None => "", }); } @@ -511,7 +565,26 @@ fn rewrite_comment_inner( for (i, (line, has_leading_whitespace)) in lines.enumerate() { let is_last = i == count_newlines(orig); - if let Some(ref attr) = code_block_attr { + if let Some(ref ib) = item_block { + if ib.in_block(&line) { + item_block_buffer.push_str(&line); + item_block_buffer.push('\n'); + continue; + } + is_prev_line_multi_line = false; + fmt.shape = Shape::legacy(max_chars, fmt_indent); + let item_fmt = ib.create_string_format(&fmt); + result.push_str(&comment_line_separator); + result.push_str(&ib.opener); + match rewrite_string(&item_block_buffer.replace("\n", " "), &item_fmt) { + Some(s) => result.push_str(&join_block( + &s, + &format!("{}{}", &comment_line_separator, ib.line_start), + )), + None => result.push_str(&join_block(&item_block_buffer, &comment_line_separator)), + }; + item_block_buffer.clear(); + } else if let Some(ref attr) = code_block_attr { if line.starts_with("```") { let code_block = match attr { CodeBlockAttribute::Ignore | CodeBlockAttribute::Text => { @@ -529,7 +602,7 @@ fn rewrite_comment_inner( }; if !code_block.is_empty() { result.push_str(&comment_line_separator); - result.push_str(&join_code_block_with_comment_line_separator(&code_block)); + result.push_str(&join_block(&code_block, &comment_line_separator)); } code_block_buffer.clear(); result.push_str(&comment_line_separator); @@ -538,46 +611,42 @@ fn rewrite_comment_inner( } else { code_block_buffer.push_str(&hide_sharp_behind_comment(line)); code_block_buffer.push('\n'); - - if is_last { - // There is a code block that is not properly enclosed by backticks. - // We will leave them untouched. - result.push_str(&comment_line_separator); - result.push_str(&join_code_block_with_comment_line_separator( - &trim_custom_comment_prefix(&code_block_buffer), - )); - } } + continue; + } + code_block_attr = None; + item_block = None; + if line.starts_with("```") { + code_block_attr = Some(CodeBlockAttribute::new(&line[3..])) + } else if config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { + let ib = ItemizedBlock::new(&line); + item_block_buffer.push_str(&line[ib.indent..]); + item_block_buffer.push('\n'); + item_block = Some(ib); continue; - } else { - code_block_attr = if line.starts_with("```") { - Some(CodeBlockAttribute::new(&line[3..])) - } else { - None - }; + } - if result == opener { - let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; - if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { - result.pop(); - } - if line.is_empty() { - continue; - } - } else if is_prev_line_multi_line && !line.is_empty() { - result.push(' ') - } else if is_last && line.is_empty() { - // trailing blank lines are unwanted - if !closer.is_empty() { - result.push_str(&indent_str); - } - break; - } else { - result.push_str(&comment_line_separator); - if !has_leading_whitespace && result.ends_with(' ') { - result.pop(); - } + if result == opener { + let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; + if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { + result.pop(); + } + if line.is_empty() { + continue; + } + } else if is_prev_line_multi_line && !line.is_empty() { + result.push(' ') + } else if is_last && line.is_empty() { + // trailing blank lines are unwanted + if !closer.is_empty() { + result.push_str(&indent_str); + } + break; + } else { + result.push_str(&comment_line_separator); + if !has_leading_whitespace && result.ends_with(' ') { + result.pop(); } } @@ -631,6 +700,30 @@ fn rewrite_comment_inner( is_prev_line_multi_line = false; } } + if !code_block_buffer.is_empty() { + // There is a code block that is not properly enclosed by backticks. + // We will leave them untouched. + result.push_str(&comment_line_separator); + result.push_str(&join_block( + &trim_custom_comment_prefix(&code_block_buffer), + &comment_line_separator, + )); + } + if !item_block_buffer.is_empty() { + // the last few lines are part of an itemized block + let ib = item_block.unwrap(); + fmt.shape = Shape::legacy(max_chars, fmt_indent); + let item_fmt = ib.create_string_format(&fmt); + result.push_str(&comment_line_separator); + result.push_str(&ib.opener); + match rewrite_string(&item_block_buffer.replace("\n", " "), &item_fmt) { + Some(s) => result.push_str(&join_block( + &s, + &format!("{}{}", &comment_line_separator, ib.line_start), + )), + None => result.push_str(&join_block(&item_block_buffer, &comment_line_separator)), + }; + } result.push_str(closer); if result.ends_with(opener) && opener.ends_with(' ') { diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs new file mode 100644 index 00000000000..dff9ee8a222 --- /dev/null +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -0,0 +1,46 @@ +// rustfmt-normalize_comments: true + +//! This is a list: +//! * Outer +//! * Outer +//! * Inner +//! * Inner with lots of text so that it could be reformatted something something something lots of text so that it could be reformatted something something something +//! +//! This example shows how to configure fern to output really nicely colored logs +//! - when the log level is error, the whole line is red +//! - when the log level is warn, the whole line is yellow +//! - when the log level is info, the level name is green and the rest of the line is white +//! - when the log level is debug, the whole line is white +//! - when the log level is trace, the whole line is gray ("bright black") + +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor +fn func1() {} + +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +/// ``` +/// let x = 42; +/// ``` +fn func2() {} + +/// Look: +/// +/// ``` +/// let x = 42; +/// ``` +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +fn func3() {} diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs new file mode 100644 index 00000000000..5daba855e6b --- /dev/null +++ b/tests/source/itemized-blocks/wrap.rs @@ -0,0 +1,54 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 + +//! This is a list: +//! * Outer +//! * Outer +//! * Inner +//! * Inner with lots of text so that it could be reformatted something something something lots of text so that it could be reformatted something something something +//! +//! This example shows how to configure fern to output really nicely colored logs +//! - when the log level is error, the whole line is red +//! - when the log level is warn, the whole line is yellow +//! - when the log level is info, the level name is green and the rest of the line is white +//! - when the log level is debug, the whole line is white +//! - when the log level is trace, the whole line is gray ("bright black") + +// This example shows how to configure fern to output really nicely colored logs +// - when the log level is error, the whole line is red +// - when the log level is warn, the whole line is yellow +// - when the log level is info, the level name is green and the rest of the line is white +// - when the log level is debug, the whole line is white +// - when the log level is trace, the whole line is gray ("bright black") + +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor +fn func1() {} + +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +/// ``` +/// let x = 42; +/// ``` +fn func2() {} + +/// Look: +/// +/// ``` +/// let x = 42; +/// ``` +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +fn func3() {} diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs new file mode 100644 index 00000000000..c7151cf81ff --- /dev/null +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -0,0 +1,46 @@ +// rustfmt-normalize_comments: true + +//! This is a list: +//! * Outer +//! * Outer +//! * Inner +//! * Inner with lots of text so that it could be reformatted something something something lots of text so that it could be reformatted something something something +//! +//! This example shows how to configure fern to output really nicely colored logs +//! - when the log level is error, the whole line is red +//! - when the log level is warn, the whole line is yellow +//! - when the log level is info, the level name is green and the rest of the line is white +//! - when the log level is debug, the whole line is white +//! - when the log level is trace, the whole line is gray ("bright black") + +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor +fn func1() {} + +/// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote +/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +/// ``` +/// let x = 42; +/// ``` +fn func2() {} + +/// Look: +/// +/// ``` +/// let x = 42; +/// ``` +/// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means +/// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater +/// * `tag` is a tag that identifies the message type +/// * `msg` is the (serialized) message +fn func3() {} diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs new file mode 100644 index 00000000000..08d8ca35261 --- /dev/null +++ b/tests/target/itemized-blocks/wrap.rs @@ -0,0 +1,91 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 + +//! This is a list: +//! * Outer +//! * Outer +//! * Inner +//! * Inner with lots of text so that it could +//! be reformatted something something +//! something lots of text so that it could be +//! reformatted something something something +//! +//! This example shows how to configure fern to +//! output really nicely colored logs +//! - when the log level is error, the whole line +//! is red +//! - when the log level is warn, the whole line +//! is yellow +//! - when the log level is info, the level name +//! is green and the rest of the line is white +//! - when the log level is debug, the whole line +//! is white +//! - when the log level is trace, the whole line +//! is gray ("bright black") + +// This example shows how to configure fern to +// output really nicely colored logs +// - when the log level is error, the whole line +// is red +// - when the log level is warn, the whole line +// is yellow +// - when the log level is info, the level +// name is green and the rest of the line is +// white +// - when the log level is debug, the whole line +// is white +// - when the log level is trace, the whole line +// is gray ("bright black") + +/// All the parameters ***except for +/// `from_theater`*** should be inserted as sent +/// by the remote theater, ie. as passed to +/// [`Theater::send`] on the remote +/// actor: +/// * `from` is the sending (remote) [`ActorId`], +/// as reported by the remote theater by +/// theater-specific means +/// * `to` is the receiving (local) [`ActorId`], +/// as requested by the remote theater +/// * `tag` is a tag that identifies the message +/// type +/// * `msg` is the (serialized) message +/// All the parameters ***except for +/// `from_theater`*** should be inserted as sent +/// by the remote theater, ie. as passed to +/// [`Theater::send`] on the remote +/// actor +fn func1() {} + +/// All the parameters ***except for +/// `from_theater`*** should be inserted as sent +/// by the remote theater, ie. as passed to +/// [`Theater::send`] on the remote +/// actor: +/// * `from` is the sending (remote) [`ActorId`], +/// as reported by the remote theater by +/// theater-specific means +/// * `to` is the receiving (local) [`ActorId`], +/// as requested by the remote theater +/// * `tag` is a tag that identifies the message +/// type +/// * `msg` is the (serialized) message +/// ``` +/// let x = 42; +/// ``` +fn func2() {} + +/// Look: +/// +/// ``` +/// let x = 42; +/// ``` +/// * `from` is the sending (remote) [`ActorId`], +/// as reported by the remote theater by +/// theater-specific means +/// * `to` is the receiving (local) [`ActorId`], +/// as requested by the remote theater +/// * `tag` is a tag that identifies the message +/// type +/// * `msg` is the (serialized) message +fn func3() {} -- cgit 1.4.1-3-g733a5 From 2ae1b4804ca528d21005738f56018b7c6a6141e9 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 9 Oct 2018 09:06:16 -0300 Subject: Enable `stdin_disable_all_formatting_test` test Fixes: #1990. Signed-off-by: Otavio Salvador --- src/test/mod.rs | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index a9015cedf6a..1967c74da45 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -17,6 +17,7 @@ use std::io::{self, BufRead, BufReader, Read, Write}; use std::iter::{Enumerate, Peekable}; use std::mem; use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; use std::str::Chars; use config::{Color, Config, EmitMode, FileName, ReportTactic}; @@ -287,28 +288,32 @@ fn stdin_formatting_smoke_test() { assert_eq!(buf, "fn main() {}\r\n".as_bytes()); } -// FIXME(#1990) restore this test -// #[test] -// fn stdin_disable_all_formatting_test() { -// let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); -// let mut child = Command::new("./target/debug/rustfmt") -// .stdin(Stdio::piped()) -// .stdout(Stdio::piped()) -// .arg("--config-path=./tests/config/disable_all_formatting.toml") -// .spawn() -// .expect("failed to execute child"); - -// { -// let stdin = child.stdin.as_mut().expect("failed to get stdin"); -// stdin -// .write_all(input.as_bytes()) -// .expect("failed to write stdin"); -// } -// let output = child.wait_with_output().expect("failed to wait on child"); -// assert!(output.status.success()); -// assert!(output.stderr.is_empty()); -// assert_eq!(input, String::from_utf8(output.stdout).unwrap()); -// } +#[test] +fn stdin_disable_all_formatting_test() { + match option_env!("CFG_RELEASE_CHANNEL") { + None | Some("nightly") => {} + _ => return, // these tests require nightly + } + let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); + let mut child = Command::new("./target/debug/rustfmt") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .arg("--config-path=./tests/config/disable_all_formatting.toml") + .spawn() + .expect("failed to execute child"); + + { + let stdin = child.stdin.as_mut().expect("failed to get stdin"); + stdin + .write_all(input.as_bytes()) + .expect("failed to write stdin"); + } + + let output = child.wait_with_output().expect("failed to wait on child"); + assert!(output.status.success()); + assert!(output.stderr.is_empty()); + assert_eq!(input, String::from_utf8(output.stdout).unwrap()); +} #[test] fn format_lines_errors_are_reported() { -- cgit 1.4.1-3-g733a5 From 375c87820f97c03fec4ec1a23803b00df1b1d5dc Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 9 Oct 2018 21:47:32 +0200 Subject: rewrite_string: detect when a url is being split and place the new line after it --- src/string.rs | 77 +++++++++++++++++++++++++++- tests/source/itemized-blocks/rewrite_fail.rs | 11 ++++ tests/source/itemized-blocks/urls.rs | 22 ++++++++ tests/target/itemized-blocks/rewrite_fail.rs | 14 +++++ tests/target/itemized-blocks/urls.rs | 25 +++++++++ 5 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 tests/source/itemized-blocks/rewrite_fail.rs create mode 100644 tests/source/itemized-blocks/urls.rs create mode 100644 tests/target/itemized-blocks/rewrite_fail.rs create mode 100644 tests/target/itemized-blocks/urls.rs (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 6a888cf8318..2fe13db2139 100644 --- a/src/string.rs +++ b/src/string.rs @@ -158,6 +158,31 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option wrap_str(result, fmt.config.max_width(), fmt.shape) } +/// Returns the index to the end of the url if the given string includes an +/// URL or alike. Otherwise, returns None; +fn detect_url(s: &[&str], index: usize) -> Option { + let start = match s[..=index].iter().rposition(|g| is_whitespace(g)) { + Some(pos) => pos + 1, + None => 0, + }; + if s.len() < start + 8 { + return None; + } + let prefix = s[start..start + 8].join(""); + if prefix.starts_with("https://") + || prefix.starts_with("http://") + || prefix.starts_with("ftp://") + || prefix.starts_with("file://") + { + match s[index..].iter().position(|g| is_whitespace(g)) { + Some(pos) => Some(index + pos - 1), + None => Some(s.len() - 1), + } + } else { + None + } +} + /// Trims whitespaces to the right except for the line feed character. fn trim_right_but_line_feed(trim_end: bool, result: String) -> String { let whitespace_except_line_feed = |c: char| c.is_whitespace() && c != '\n'; @@ -193,13 +218,16 @@ enum SnippetState { EndWithLineFeed(String, usize), } +fn not_whitespace_except_line_feed(g: &str) -> bool { + is_line_feed(g) || !is_whitespace(g) +} + /// Break the input string at a boundary character around the offset `max_chars`. A boundary /// character is either a punctuation or a whitespace. fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str]) -> SnippetState { let break_at = |index /* grapheme at index is included */| { // Take in any whitespaces to the left/right of `input[index]` while // preserving line feeds - let not_whitespace_except_line_feed = |g| is_line_feed(g) || !is_whitespace(g); let index_minus_ws = input[0..=index] .iter() .rposition(|grapheme| not_whitespace_except_line_feed(grapheme)) @@ -258,6 +286,24 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] // - extra whitespaces to the right can be trimmed return break_at(max_chars - 1); } + if let Some(url_index_end) = detect_url(input, max_chars) { + let index_plus_ws = url_index_end + input[url_index_end..] + .iter() + .skip(1) + .position(|grapheme| not_whitespace_except_line_feed(grapheme)) + .unwrap_or(0); + return if trim_end { + SnippetState::LineEnd( + input[..=url_index_end].join("").to_string(), + index_plus_ws + 1, + ) + } else { + return SnippetState::LineEnd( + input[..=index_plus_ws].join("").to_string(), + index_plus_ws + 1, + ); + }; + } match input[0..max_chars] .iter() .rposition(|grapheme| is_whitespace(grapheme)) @@ -303,7 +349,7 @@ fn is_punctuation(grapheme: &str) -> bool { #[cfg(test)] mod test { - use super::{break_string, rewrite_string, SnippetState, StringFormat}; + use super::{break_string, detect_url, rewrite_string, SnippetState, StringFormat}; use config::Config; use shape::{Indent, Shape}; use unicode_segmentation::UnicodeSegmentation; @@ -610,4 +656,31 @@ mod test { Some("Vestibulum\\\n // ac lacus.".to_string()) ); } + + #[test] + fn detect_urls() { + let string = "aaa http://example.org something"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!(detect_url(&graphemes, 8), Some(21)); + + let string = "https://example.org something"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!(detect_url(&graphemes, 0), Some(18)); + + let string = "aaa ftp://example.org something"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!(detect_url(&graphemes, 8), Some(20)); + + let string = "aaa file://example.org something"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!(detect_url(&graphemes, 8), Some(21)); + + let string = "aaa http not an url"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!(detect_url(&graphemes, 6), None); + + let string = "aaa file://example.org"; + let graphemes = UnicodeSegmentation::graphemes(&*string, false).collect::>(); + assert_eq!(detect_url(&graphemes, 8), Some(21)); + } } diff --git a/tests/source/itemized-blocks/rewrite_fail.rs b/tests/source/itemized-blocks/rewrite_fail.rs new file mode 100644 index 00000000000..f99c2cc5ff9 --- /dev/null +++ b/tests/source/itemized-blocks/rewrite_fail.rs @@ -0,0 +1,11 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 + +// This example shows how to configure fern to output really nicely colored logs +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - when the log level is info, the level name is green and the rest of the line is white +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn func1() {} diff --git a/tests/source/itemized-blocks/urls.rs b/tests/source/itemized-blocks/urls.rs new file mode 100644 index 00000000000..2eaaafbbc4a --- /dev/null +++ b/tests/source/itemized-blocks/urls.rs @@ -0,0 +1,22 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 79 + +//! CMSIS: Cortex Microcontroller Software Interface Standard +//! +//! The version 5 of the standard can be found at: +//! +//! http://arm-software.github.io/CMSIS_5/Core/html/index.html +//! +//! The API reference of the standard can be found at: +//! +//! - example -- http://example.org -- something something something something something something +//! - something something something something something something more -- http://example.org +//! - http://example.org/something/something/something/something/something/something and the rest +//! - Core function access -- http://arm-software.github.io/CMSIS_5/Core/html/group__Core__Register__gr.html +//! - Intrinsic functions for CPU instructions -- http://arm-software.github.io/CMSIS_5/Core/html/group__intrinsic__CPU__gr.html +//! - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum sem lacus, commodo vitae. +//! +//! The reference C implementation used as the base of this Rust port can be +//! found at +//! +//! https://github.com/ARM-software/CMSIS_5/blob/5.3.0/CMSIS/Core/Include/cmsis_gcc.h diff --git a/tests/target/itemized-blocks/rewrite_fail.rs b/tests/target/itemized-blocks/rewrite_fail.rs new file mode 100644 index 00000000000..a118ef6faa1 --- /dev/null +++ b/tests/target/itemized-blocks/rewrite_fail.rs @@ -0,0 +1,14 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 50 + +// This example shows how to configure fern to +// output really nicely colored logs +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - when the log level is info, the level +// name is green and the rest of the line is +// white +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +// - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +fn func1() {} diff --git a/tests/target/itemized-blocks/urls.rs b/tests/target/itemized-blocks/urls.rs new file mode 100644 index 00000000000..bc46ea47e16 --- /dev/null +++ b/tests/target/itemized-blocks/urls.rs @@ -0,0 +1,25 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 79 + +//! CMSIS: Cortex Microcontroller Software Interface Standard +//! +//! The version 5 of the standard can be found at: +//! +//! http://arm-software.github.io/CMSIS_5/Core/html/index.html +//! +//! The API reference of the standard can be found at: +//! +//! - example -- http://example.org -- something something something something +//! something something +//! - something something something something something something more -- http://example.org +//! - http://example.org/something/something/something/something/something/something +//! and the rest +//! - Core function access -- http://arm-software.github.io/CMSIS_5/Core/html/group__Core__Register__gr.html +//! - Intrinsic functions for CPU instructions -- http://arm-software.github.io/CMSIS_5/Core/html/group__intrinsic__CPU__gr.html +//! - Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum sem +//! lacus, commodo vitae. +//! +//! The reference C implementation used as the base of this Rust port can be +//! found at +//! +//! https://github.com/ARM-software/CMSIS_5/blob/5.3.0/CMSIS/Core/Include/cmsis_gcc.h -- cgit 1.4.1-3-g733a5 From 7003276b7369ef9fec08309ef2b1f710df4b2836 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 11 Oct 2018 09:05:33 +0200 Subject: fixed display message for the LineOverflow error --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index b8f9d4cfb6e..267096d9943 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -100,7 +100,7 @@ pub enum ErrorKind { #[fail( display = "line formatted, but exceeded maximum width \ (maximum: {} (see `max_width` option), found: {})", - _0, _1 + _1, _0 )] LineOverflow(usize, usize), /// Line ends in whitespace. -- cgit 1.4.1-3-g733a5 From 6391b7ab352d0ae79a6ed547efac39b7f8c6f644 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Thu, 11 Oct 2018 10:21:15 -0300 Subject: rewrite: adjust comment as it refers to `is_if_else_block` Signed-off-by: Otavio Salvador --- src/rewrite.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rewrite.rs b/src/rewrite.rs index d151c922e81..17bb027bd56 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -40,7 +40,7 @@ pub struct RewriteContext<'a> { pub inside_macro: RefCell, // Force block indent style even if we are using visual indent style. pub use_block: RefCell, - // When `format_if_else_cond_comment` is true, unindent the comment on top + // When `is_if_else_block` is true, unindent the comment on top // of the `else` or `else if`. pub is_if_else_block: RefCell, // When rewriting chain, veto going multi line except the last element -- cgit 1.4.1-3-g733a5 From b2de57484835ee42567db3a1bf59f13ecc7fab33 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 11 Oct 2018 23:10:57 +0900 Subject: Add format_doc_comments --- Configurations.md | 50 ++++++++++++++++++++++++++++++++ src/comment.rs | 9 ++++-- src/config/mod.rs | 1 + tests/source/doc-comment-with-example.rs | 2 +- tests/target/doc-comment-with-example.rs | 2 +- 5 files changed, 59 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 66b5d840f3c..f23506d5fe8 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1979,6 +1979,56 @@ fn main() { } ``` +## `format_doc_comments` + +Format doc comments. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default): + +```rust +/// Adds one to the number given. +/// +/// # Examples +/// +/// ```rust +/// let five=5; +/// +/// assert_eq!( +/// 6, +/// add_one(5) +/// ); +/// # fn add_one(x: i32) -> i32 { +/// # x + 1 +/// # } +/// ``` +fn add_one(x: i32) -> i32 { + x + 1 +} +``` + +#### `true` + +```rust +/// Adds one to the number given. +/// +/// # Examples +/// +/// ```rust +/// let five = 5; +/// +/// assert_eq!(6, add_one(5)); +/// # fn add_one(x: i32) -> i32 { +/// # x + 1 +/// # } +/// ``` +fn add_one(x: i32) -> i32 { + x + 1 +} +``` ## `wrap_comments` diff --git a/src/comment.rs b/src/comment.rs index 41301527653..213879e50a1 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -333,7 +333,10 @@ fn identify_comment( let rewritten_first_group = if !config.normalize_comments() && has_bare_lines && style.is_block_comment() { light_rewrite_block_comment_with_bare_lines(first_group, shape, config)? - } else if !config.normalize_comments() && !config.wrap_comments() { + } else if !config.normalize_comments() + && !config.wrap_comments() + && !config.format_doc_comments() + { light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)? } else { rewrite_comment_inner( @@ -593,7 +596,7 @@ fn rewrite_comment_inner( _ if code_block_buffer.is_empty() => String::new(), _ => { let mut config = config.clone(); - config.set().wrap_comments(false); + config.set().format_doc_comments(false); match ::format_code_block(&code_block_buffer, &config) { Some(ref s) => trim_custom_comment_prefix(s), None => trim_custom_comment_prefix(&code_block_buffer), @@ -1622,7 +1625,7 @@ mod test { #[test] #[rustfmt::skip] - fn format_comments() { + fn format_doc_comments() { let mut wrap_normalize_config: ::config::Config = Default::default(); wrap_normalize_config.set().wrap_comments(true); wrap_normalize_config.set().normalize_comments(true); diff --git a/src/config/mod.rs b/src/config/mod.rs index a553bf2ee3c..98754eb0b60 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -46,6 +46,7 @@ create_config! { // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; + format_doc_comments: bool, false, false, "Format doc comments."; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; diff --git a/tests/source/doc-comment-with-example.rs b/tests/source/doc-comment-with-example.rs index 683ad789baf..58d98acfa25 100644 --- a/tests/source/doc-comment-with-example.rs +++ b/tests/source/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-wrap_comments: true +// rustfmt-format_doc_comments: true /// Foo /// diff --git a/tests/target/doc-comment-with-example.rs b/tests/target/doc-comment-with-example.rs index bdf2adf0c64..bec931d13c7 100644 --- a/tests/target/doc-comment-with-example.rs +++ b/tests/target/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-wrap_comments: true +// rustfmt-format_doc_comments: true /// Foo /// -- cgit 1.4.1-3-g733a5 From 8b709c0019244d8554c0799084815146a5ce800a Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 12 Oct 2018 15:17:27 +1300 Subject: Add `attr_fn_like_width` to the width heuristics It is a bit larger than than `fn_call_width` which we used previously, so fewer attributes get reformatted. Closes #2929 --- src/attr.rs | 2 +- src/config/options.rs | 6 ++++++ tests/source/enum.rs | 2 +- tests/target/enum.rs | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 19c6bdc2484..033f3767ecd 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -224,7 +224,7 @@ impl Rewrite for ast::MetaItem { // 1 = "]" shape.sub_width(1)?, self.span, - context.config.width_heuristics().fn_call_width, + context.config.width_heuristics().attr_fn_like_width, Some(if has_trailing_comma { SeparatorTactic::Always } else { diff --git a/src/config/options.rs b/src/config/options.rs index a4ba21b53cf..27a4db70fea 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -316,6 +316,9 @@ pub struct WidthHeuristics { // Maximum width of the args of a function call before falling back // to vertical formatting. pub fn_call_width: usize, + // Maximum width of the args of a function-like attributes before falling + // back to vertical formatting. + pub attr_fn_like_width: usize, // Maximum width in the body of a struct lit before falling back to // vertical formatting. pub struct_lit_width: usize, @@ -337,6 +340,7 @@ impl WidthHeuristics { pub fn null() -> WidthHeuristics { WidthHeuristics { fn_call_width: usize::max_value(), + attr_fn_like_width: usize::max_value(), struct_lit_width: 0, struct_variant_width: 0, array_width: usize::max_value(), @@ -348,6 +352,7 @@ impl WidthHeuristics { pub fn set(max_width: usize) -> WidthHeuristics { WidthHeuristics { fn_call_width: max_width, + attr_fn_like_width: max_width, struct_lit_width: max_width, struct_variant_width: max_width, array_width: max_width, @@ -368,6 +373,7 @@ impl WidthHeuristics { }; WidthHeuristics { fn_call_width: (60.0 * max_width_ratio).round() as usize, + attr_fn_like_width: (70.0 * max_width_ratio).round() as usize, struct_lit_width: (18.0 * max_width_ratio).round() as usize, struct_variant_width: (35.0 * max_width_ratio).round() as usize, array_width: (60.0 * max_width_ratio).round() as usize, diff --git a/tests/source/enum.rs b/tests/source/enum.rs index 5db64b3ee3e..c348b5752e2 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -189,7 +189,7 @@ pub enum QlError { // (from, to) #[fail(display = "Translation error: from {} to {}", 0, 1)] TranslationError(String, String), // (kind, input, expected) - #[fail(display = "Could not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), + #[fail(display = "aaaaaaaaaaaaCould not find {}: Found: {}, expected: {:?}", 0, 1, 2)] ResolveError(&'static str, String, Option), } // #2594 diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 6bc355bc807..dda58c4b5b0 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -255,7 +255,7 @@ pub enum QlError { TranslationError(String, String), // (kind, input, expected) #[fail( - display = "Could not find {}: Found: {}, expected: {:?}", + display = "aaaaaaaaaaaaCould not find {}: Found: {}, expected: {:?}", 0, 1, 2 )] ResolveError(&'static str, String, Option), -- cgit 1.4.1-3-g733a5 From 0ac68c9477739532166c1f9a62d317fdf4450ae6 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 13 Oct 2018 00:41:17 +0900 Subject: Do not add parens around lifetimes Parens should be added only around trait objects. --- src/types.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index e7282c13317..d5010314b57 100644 --- a/src/types.rs +++ b/src/types.rs @@ -473,7 +473,7 @@ fn rewrite_bounded_lifetime( "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, true)? + join_bounds(context, shape.sub_width(overhead)?, bounds, true, false)? ); Some(result) } @@ -515,13 +515,7 @@ impl Rewrite for ast::GenericBounds { } else { shape }; - join_bounds(context, bounds_shape, self, true).map(|s| { - if has_paren { - format!("({})", s) - } else { - s - } - }) + join_bounds(context, bounds_shape, self, true, has_paren) } } @@ -757,7 +751,10 @@ fn join_bounds( shape: Shape, items: &[ast::GenericBound], need_indent: bool, + has_paren: bool, ) -> Option { + debug_assert!(!items.is_empty()); + // Try to join types in a single line let joiner = match context.config.type_punctuation_density() { TypeDensity::Compressed => "+", @@ -765,9 +762,36 @@ fn join_bounds( }; let type_strs = items .iter() - .map(|item| item.rewrite(context, shape)) + .map(|item| { + item.rewrite( + context, + if has_paren { + shape.sub_width(1)?.offset_left(1)? + } else { + shape + }, + ) + }) .collect::>>()?; - let result = type_strs.join(joiner); + let mut result = String::with_capacity(128); + let mut closing_paren = has_paren; + if has_paren { + result.push('('); + } + result.push_str(&type_strs[0]); + if has_paren && type_strs.len() == 1 { + result.push(')'); + } + for (i, type_str) in type_strs[1..].iter().enumerate() { + if closing_paren { + if let ast::GenericBound::Outlives(..) = items[i + 1] { + result.push(')'); + closing_paren = false; + } + } + result.push_str(joiner); + result.push_str(type_str); + } if items.len() <= 1 || (!result.contains('\n') && result.len() <= shape.width) { return Some(result); } @@ -790,10 +814,20 @@ fn join_bounds( ast::GenericBound::Trait(..) => last_line_extendable(s), }; let mut result = String::with_capacity(128); + let mut closing_paren = has_paren; + if has_paren { + result.push('('); + } result.push_str(&type_strs[0]); let mut can_be_put_on_the_same_line = is_bound_extendable(&result, &items[0]); let generic_bounds_in_order = is_generic_bounds_in_order(items); for (bound, bound_str) in items[1..].iter().zip(type_strs[1..].iter()) { + if closing_paren { + if let ast::GenericBound::Outlives(..) = bound { + closing_paren = false; + result.push(')'); + } + } if generic_bounds_in_order && can_be_put_on_the_same_line { result.push_str(joiner); } else { -- cgit 1.4.1-3-g733a5 From 78d9091afff88464a32d14508cd4671e8d419e7d Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 12 Oct 2018 20:41:56 +0200 Subject: do not vertically align list items in case the tactic is Horizontal --- src/vertical.rs | 18 ++++++++++++++++-- tests/target/issue-2633.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-2633.rs (limited to 'src') diff --git a/src/vertical.rs b/src/vertical.rs index d18fa4b9b75..dbb3e732d62 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -19,7 +19,7 @@ use syntax::source_map::{BytePos, Span}; use comment::{combine_strs_with_missing_comments, contains_comment}; use expr::rewrite_field; use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use source_map::SpanUtils; @@ -227,7 +227,7 @@ fn rewrite_aligned_items_inner( field_prefix_max_width = 0; } - let items = itemize_list( + let mut items = itemize_list( context.snippet_provider, fields.iter(), "}", @@ -248,6 +248,20 @@ fn rewrite_aligned_items_inner( one_line_width, ); + if tactic == DefinitiveListTactic::Horizontal { + // since the items fits on a line, there is no need to align them + let do_rewrite = + |field: &T| -> Option { field.rewrite_aligned_item(context, item_shape, 0) }; + fields + .iter() + .zip(items.iter_mut()) + .for_each(|(field, list_item): (&T, &mut ListItem)| { + if list_item.item.is_some() { + list_item.item = do_rewrite(field); + } + }); + } + let fmt = ListFormatting::new(item_shape, context.config) .tactic(tactic) .trailing_separator(context.config.trailing_comma()) diff --git a/tests/target/issue-2633.rs b/tests/target/issue-2633.rs new file mode 100644 index 00000000000..a381945fd8b --- /dev/null +++ b/tests/target/issue-2633.rs @@ -0,0 +1,13 @@ +// rustfmt-struct_field_align_threshold: 5 + +#[derive(Fail, Debug, Clone)] +pub enum BuildError { + LineTooLong { length: usize, limit: usize }, + DisallowedByte { b: u8, pos: usize }, + ContainsNewLine { pos: usize }, +} + +enum Foo { + A { a: usize, bbbbb: () }, + B { a: (), bbbbb: () }, +} -- cgit 1.4.1-3-g733a5 From b144adf3be09bc31f4d306be9e5992b000fc7b1f Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 12 Oct 2018 20:07:25 -0300 Subject: closures: replace `.unwrap_or` with `.map_or` Signed-off-by: Otavio Salvador --- src/closures.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index bde08931d18..fa656cc351e 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -345,9 +345,9 @@ pub fn rewrite_last_closure( // When overflowing the closure which consists of a single control flow expression, // force to use block if its condition uses multi line. - let is_multi_lined_cond = rewrite_cond(context, body, body_shape) - .map(|cond| cond.contains('\n') || cond.len() > body_shape.width) - .unwrap_or(false); + let is_multi_lined_cond = rewrite_cond(context, body, body_shape).map_or(false, |cond| { + cond.contains('\n') || cond.len() > body_shape.width + }); if is_multi_lined_cond { return rewrite_closure_with_block(body, &prefix, context, body_shape); } -- cgit 1.4.1-3-g733a5 From 8feeddf1f88cb3753b51c894cffea4f11b0036d3 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Mon, 8 Oct 2018 20:49:33 -0300 Subject: Only combine `match` if its condition expression fits in a single line This improves the formatting and reading of code avoiding the condition expression to be rewrite, if it goes multi line. Fixes: #3029. Signed-off-by: Otavio Salvador --- src/overflow.rs | 11 +++++++++++ tests/source/issue-3029.rs | 21 +++++++++++++++++++++ tests/target/issue-3029.rs | 21 +++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/source/issue-3029.rs create mode 100644 tests/target/issue-3029.rs (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index a7fc9728666..40cfc4be30f 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -18,6 +18,7 @@ use syntax::{ast, ptr}; use closures; use expr::{ can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, + rewrite_cond, }; use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; use macros::MacroArg; @@ -403,6 +404,16 @@ impl<'a> Context<'a> { closures::rewrite_last_closure(self.context, expr, shape) } } + ast::ExprKind::Match(..) => { + let multi_line = rewrite_cond(self.context, expr, shape) + .map_or(false, |cond| cond.contains('\n')); + + if multi_line { + None + } else { + expr.rewrite(self.context, shape) + } + } _ => expr.rewrite(self.context, shape), } } diff --git a/tests/source/issue-3029.rs b/tests/source/issue-3029.rs new file mode 100644 index 00000000000..49ce07fae3a --- /dev/null +++ b/tests/source/issue-3029.rs @@ -0,0 +1,21 @@ +fn foo() { + EvaluateJSReply::NumberValue( + match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + Ok(ConversionResult::Success(v)) => v, + _ => unreachable!(), + }, + ) +} + +fn bar() { + { + { + EvaluateJSReply::NumberValue( + match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + Ok(ConversionResult::Success(v)) => v, + _ => unreachable!(), + }, + ) + } + } +} diff --git a/tests/target/issue-3029.rs b/tests/target/issue-3029.rs new file mode 100644 index 00000000000..49ce07fae3a --- /dev/null +++ b/tests/target/issue-3029.rs @@ -0,0 +1,21 @@ +fn foo() { + EvaluateJSReply::NumberValue( + match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + Ok(ConversionResult::Success(v)) => v, + _ => unreachable!(), + }, + ) +} + +fn bar() { + { + { + EvaluateJSReply::NumberValue( + match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + Ok(ConversionResult::Success(v)) => v, + _ => unreachable!(), + }, + ) + } + } +} -- cgit 1.4.1-3-g733a5 From 2e9a97a84dd99787def5add43850dc6c8b0f3341 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 12 Oct 2018 20:21:22 -0300 Subject: expr: replace `.unwrap_or` with `.map_or` Signed-off-by: Otavio Salvador --- src/expr.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d3f51fc5f3c..7a6a1473060 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -273,11 +273,9 @@ pub fn format_expr( format!( "{}{}{}", - lhs.map(|lhs| space_if(needs_space_before_range(context, lhs))) - .unwrap_or(""), + lhs.map_or("", |lhs| space_if(needs_space_before_range(context, lhs))), delim, - rhs.map(|rhs| space_if(needs_space_after_range(rhs))) - .unwrap_or(""), + rhs.map_or("", |rhs| space_if(needs_space_after_range(rhs))), ) }; -- cgit 1.4.1-3-g733a5 From 5d4ed07f1c61b6442ffb28419336626deed1509d Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 12 Oct 2018 20:21:48 -0300 Subject: config: replace `.unwrap_or` with `.map_or` Signed-off-by: Otavio Salvador --- src/config/config_type.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index bf9cd859732..edd6ae5634f 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -72,9 +72,7 @@ impl ConfigType for IgnoreList { /// nightly compiler when installed from crates.io, default to nightly mode. macro_rules! is_nightly_channel { () => { - option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly" || c == "dev") - .unwrap_or(true) + option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") }; } -- cgit 1.4.1-3-g733a5 From 6d7fef078ea01f6cbe3ac9fee0044e32c138f309 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 12 Oct 2018 20:22:10 -0300 Subject: bin: replace `.unwrap_or` with `.map_or` Signed-off-by: Otavio Salvador --- src/bin/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index c03835ea74a..91260a199c4 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -156,9 +156,7 @@ fn make_opts() -> Options { } fn is_nightly() -> bool { - option_env!("CFG_RELEASE_CHANNEL") - .map(|c| c == "nightly" || c == "dev") - .unwrap_or(false) + option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "nightly" || c == "dev") } // Returned i32 is an exit code -- cgit 1.4.1-3-g733a5 From 8f7a0470b073803317e85e306308a4b9457dc5cd Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 13 Oct 2018 09:57:43 +0200 Subject: handle lines prefixed with a # inside code blocks --- src/comment.rs | 11 +++++++++-- tests/source/wrapped_hidden_code_block.rs | 10 ++++++++++ tests/target/wrapped_hidden_code_block.rs | 13 +++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/source/wrapped_hidden_code_block.rs create mode 100644 tests/target/wrapped_hidden_code_block.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 213879e50a1..c946cc6e1c0 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -752,9 +752,16 @@ fn trim_custom_comment_prefix(s: &str) -> String { .map(|line| { let left_trimmed = line.trim_left(); if left_trimmed.starts_with(RUSTFMT_CUSTOM_COMMENT_PREFIX) { - left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX) + let orig = left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX); + // due to comment wrapping, a line that was originaly behind `#` is split over + // multiple lines, which needs then to be prefixed with a `#` + if !orig.trim_left().starts_with("# ") { + format!("# {}", orig) + } else { + orig.to_string() + } } else { - line + line.to_string() } }) .collect::>() diff --git a/tests/source/wrapped_hidden_code_block.rs b/tests/source/wrapped_hidden_code_block.rs new file mode 100644 index 00000000000..d8de8443812 --- /dev/null +++ b/tests/source/wrapped_hidden_code_block.rs @@ -0,0 +1,10 @@ +// rustfmt-max_width: 79 +// rustfmt-wrap_comments: true + +/// ```rust +/// # #![cfg_attr(not(dox), feature(cfg_target_feature, target_feature, stdsimd)not(dox), feature(cfg_target_feature, target_feature, stdsimd))] +/// +/// // Est lectus hendrerit lorem, eget dignissim orci nisl sit amet massa. Etiam volutpat lobortis eros. +/// let x = 42; +/// ``` +fn func() {} diff --git a/tests/target/wrapped_hidden_code_block.rs b/tests/target/wrapped_hidden_code_block.rs new file mode 100644 index 00000000000..572f448c4e7 --- /dev/null +++ b/tests/target/wrapped_hidden_code_block.rs @@ -0,0 +1,13 @@ +// rustfmt-max_width: 79 +// rustfmt-wrap_comments: true + +/// ```rust +/// # #![cfg_attr(not(dox), feature(cfg_target_feature, target_feature, +/// # stdsimd)not(dox), feature(cfg_target_feature, target_feature, +/// # stdsimd))] +/// +/// // Est lectus hendrerit lorem, eget dignissim orci nisl sit amet massa. +/// // Etiam volutpat lobortis eros. +/// let x = 42; +/// ``` +fn func() {} -- cgit 1.4.1-3-g733a5 From ef59b34cd7011302008230d928e5379d0e855edc Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 13 Oct 2018 09:05:54 -0300 Subject: Avoid control flow expressions conditions to go multi line Extends the multi line condition to over other control flow expressions, it now covers: `if`, `if let`, `for`, `loop`, `while`, `while let` and `match`. Refs: #3029 Signed-off-by: Otavio Salvador --- src/overflow.rs | 10 +++++- tests/source/issue-3029.rs | 89 +++++++++++++++++++++++++++++++++++++++++----- tests/target/issue-3029.rs | 89 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 171 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index 40cfc4be30f..fc1803b2ab6 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -404,7 +404,15 @@ impl<'a> Context<'a> { closures::rewrite_last_closure(self.context, expr, shape) } } - ast::ExprKind::Match(..) => { + // When overflowing the expressions which consists of a control flow + // expression, avoid condition to use multi line. + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Match(..) => { let multi_line = rewrite_cond(self.context, expr, shape) .map_or(false, |cond| cond.contains('\n')); diff --git a/tests/source/issue-3029.rs b/tests/source/issue-3029.rs index 49ce07fae3a..a7ac5c32b06 100644 --- a/tests/source/issue-3029.rs +++ b/tests/source/issue-3029.rs @@ -1,13 +1,86 @@ -fn foo() { - EvaluateJSReply::NumberValue( - match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { - Ok(ConversionResult::Success(v)) => v, - _ => unreachable!(), - }, - ) +fn keep_if() { + { + { + { + EvaluateJSReply::NumberValue( + if FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_if_let() { + { + { + { + EvaluateJSReply::NumberValue( + if let Some(e) = FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_for() { + { + { + { + EvaluateJSReply::NumberValue( + for conv in FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_loop() { + { + { + { + EvaluateJSReply::NumberValue(loop { + FromJSValConvertible::from_jsval(cx, rval.handle(), ()); + }) + } + } + } +} + +fn keep_while() { + { + { + { + EvaluateJSReply::NumberValue( + while FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_while_let() { + { + { + { + EvaluateJSReply::NumberValue( + while let Some(e) = FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } } -fn bar() { +fn keep_match() { { { EvaluateJSReply::NumberValue( diff --git a/tests/target/issue-3029.rs b/tests/target/issue-3029.rs index 49ce07fae3a..a7ac5c32b06 100644 --- a/tests/target/issue-3029.rs +++ b/tests/target/issue-3029.rs @@ -1,13 +1,86 @@ -fn foo() { - EvaluateJSReply::NumberValue( - match FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { - Ok(ConversionResult::Success(v)) => v, - _ => unreachable!(), - }, - ) +fn keep_if() { + { + { + { + EvaluateJSReply::NumberValue( + if FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_if_let() { + { + { + { + EvaluateJSReply::NumberValue( + if let Some(e) = FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_for() { + { + { + { + EvaluateJSReply::NumberValue( + for conv in FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_loop() { + { + { + { + EvaluateJSReply::NumberValue(loop { + FromJSValConvertible::from_jsval(cx, rval.handle(), ()); + }) + } + } + } +} + +fn keep_while() { + { + { + { + EvaluateJSReply::NumberValue( + while FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } +} + +fn keep_while_let() { + { + { + { + EvaluateJSReply::NumberValue( + while let Some(e) = FromJSValConvertible::from_jsval(cx, rval.handle(), ()) { + unimplemented!(); + }, + ) + } + } + } } -fn bar() { +fn keep_match() { { { EvaluateJSReply::NumberValue( -- cgit 1.4.1-3-g733a5 From fdfb489c48a1996076cede1bc1a417134fef57f2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 14 Oct 2018 21:43:59 +0900 Subject: Add a correct indent before trait's closing brace with empty body --- src/items.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f74458fdaa6..1673bffbce9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1121,6 +1121,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let snippet = context.snippet(item.span); let open_pos = snippet.find_uncommented("{")? + 1; + let outer_indent_str = offset.block_only().to_string_with_newline(context.config); if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); @@ -1134,13 +1135,12 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) visitor.format_missing(item.span.hi() - BytePos(1)); let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); - let outer_indent_str = offset.block_only().to_string_with_newline(context.config); result.push_str(&inner_indent_str); result.push_str(visitor.buffer.to_string().trim()); result.push_str(&outer_indent_str); } else if result.contains('\n') { - result.push('\n'); + result.push_str(&outer_indent_str); } result.push('}'); -- cgit 1.4.1-3-g733a5 From 5f5d04283ce68b514a13ae5c41ba3961549ab46f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 14 Oct 2018 21:44:56 +0900 Subject: Use correct width When rewriting trait bounds on the next line, we do not want to add an extra indentation. However, the max width should be smaller. --- src/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7a6a1473060..8a5b3de7a14 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1937,7 +1937,9 @@ fn shape_from_rhs_tactic( rhs_tactic: RhsTactics, ) -> Option { match rhs_tactic { - RhsTactics::ForceNextLineWithoutIndent => Some(shape.with_max_width(context.config)), + RhsTactics::ForceNextLineWithoutIndent => shape + .with_max_width(context.config) + .sub_width(shape.indent.width()), RhsTactics::Default => { Shape::indented(shape.indent.block_indent(context.config), context.config) .sub_width(shape.rhs_overhead(context.config)) -- cgit 1.4.1-3-g733a5 From e203057db055adc5a5367d35bcd5bd103a3a21e8 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 13 Oct 2018 17:39:19 -0300 Subject: utils: rewrite `count_newlines` using `bytecount::count` This uses a optimized byte count and also makes use of SIMD instructions to optimize the processing of the byte arrays. Signed-off-by: Otavio Salvador --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/lib.rs | 1 + src/utils.rs | 6 ++++-- 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 1df841605cf..be908dac466 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,6 +63,11 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytecount" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.6" @@ -593,6 +598,7 @@ version = "0.99.5" dependencies = [ "assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -842,6 +848,7 @@ dependencies = [ "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" "checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" diff --git a/Cargo.toml b/Cargo.toml index b6b69509046..e42b25a2191 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,7 @@ rustc-ap-rustc_target = "272.0.0" rustc-ap-syntax = "272.0.0" rustc-ap-syntax_pos = "272.0.0" failure = "0.1.1" +bytecount = { version = "0.3", features = ["simd-accel"] } [dev-dependencies] assert_cli = "0.6" diff --git a/src/lib.rs b/src/lib.rs index 267096d9943..772ed8cb141 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ #[macro_use] extern crate derive_new; extern crate atty; +extern crate bytecount; extern crate diff; extern crate failure; extern crate itertools; diff --git a/src/utils.rs b/src/utils.rs index 63b238a7817..7ef9254a482 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,6 +10,8 @@ use std::borrow::Cow; +use bytecount; + use rustc_target::spec::abi; use syntax::ast::{ self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, Path, @@ -305,8 +307,8 @@ pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { #[inline] pub fn count_newlines(input: &str) -> usize { - // Using `as_bytes` to omit UTF-8 decoding - input.as_bytes().iter().filter(|&&c| c == b'\n').count() + // Using bytes to omit UTF-8 decoding + bytecount::count(input.as_bytes(), b'\n') } // For format_missing and last_pos, need to use the source callsite (if applicable). -- cgit 1.4.1-3-g733a5 From b81b9028215dbb89cd8e16d783ccd146e1d4c162 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 15 Oct 2018 11:48:12 +1300 Subject: Simplify situations in which the last sub-expr in a bin-op can go multiline without making the whole expr multiline Fixes #3034 --- src/pairs.rs | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/pairs.rs b/src/pairs.rs index f078022b9e0..c4451a8e466 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -43,7 +43,7 @@ pub(crate) fn rewrite_all_pairs( context: &RewriteContext, ) -> Option { // First we try formatting on one line. - if let Some(list) = expr.flatten(context, false) { + if let Some(list) = expr.flatten(false) { if let Some(r) = rewrite_pairs_one_line(&list, shape, context) { return Some(r); } @@ -53,7 +53,7 @@ pub(crate) fn rewrite_all_pairs( // to only flatten pairs with the same operator, that way we don't // necessarily need one line per sub-expression, but we don't do anything // too funny wrt precedence. - expr.flatten(context, true) + expr.flatten(true) .and_then(|list| rewrite_pairs_multiline(list, shape, context)) } @@ -83,33 +83,22 @@ fn rewrite_pairs_one_line( result.push(' '); } + let prefix_len = result.len(); let last = list.list.last().unwrap(); let cur_shape = base_shape.offset_left(last_line_width(&result))?; - let rewrite = last.rewrite(context, cur_shape)?; - result.push_str(&rewrite); + let last_rewrite = last.rewrite(context, cur_shape)?; + result.push_str(&last_rewrite); if first_line_width(&result) > shape.width { return None; } - // Check the last expression in the list. We let this expression go over - // multiple lines, but we check that if this is necessary, then we can't - // do better using multi-line formatting. - if !is_single_line(&result) { - let multiline_shape = shape.offset_left(list.separators.last().unwrap().len() + 1)?; - let multiline_list: PairList = PairList { - list: vec![last], - separators: vec![], - separator_place: list.separator_place, - }; - // Format as if we were multi-line. - if let Some(rewrite) = rewrite_pairs_multiline(multiline_list, multiline_shape, context) { - // Also, don't let expressions surrounded by parens go multi-line, - // this looks really bad. - if rewrite.starts_with('(') || is_single_line(&rewrite) { - return None; - } - } + // Check the last expression in the list. We sometimes let this expression + // go over multiple lines, but we check for some ugly conditions. + if !(is_single_line(&result) || last_rewrite.starts_with('{')) + && (last_rewrite.starts_with('(') || prefix_len > context.config.tab_spaces()) + { + return None; } wrap_str(result, context.config.max_width(), shape) @@ -272,7 +261,7 @@ trait FlattenPair: Rewrite + Sized { // operator into the list. E.g,, if the source is `a * b + c`, if `_same_op` // is true, we make `[(a * b), c]` if `_same_op` is false, we make // `[a, b, c]` - fn flatten(&self, _context: &RewriteContext, _same_op: bool) -> Option> { + fn flatten(&self, _same_op: bool) -> Option> { None } } @@ -280,11 +269,10 @@ trait FlattenPair: Rewrite + Sized { struct PairList<'a, 'b, T: Rewrite + 'b> { list: Vec<&'b T>, separators: Vec<&'a str>, - separator_place: SeparatorPlace, } impl FlattenPair for ast::Expr { - fn flatten(&self, context: &RewriteContext, same_op: bool) -> Option> { + fn flatten(&self, same_op: bool) -> Option> { let top_op = match self.node { ast::ExprKind::Binary(op, _, _) => op.node, _ => return None, @@ -323,7 +311,6 @@ impl FlattenPair for ast::Expr { Some(PairList { list, separators, - separator_place: context.config.binop_separator(), }) } } -- cgit 1.4.1-3-g733a5 From cbd568083d87a90dfe5ab0e90f404454946c9f20 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 15 Oct 2018 11:52:27 +1300 Subject: Fixup formatting --- src/expr.rs | 9 +++++---- src/lists.rs | 10 ++++++---- src/macros.rs | 34 ++++++++++++++++++---------------- src/pairs.rs | 16 +++++++--------- src/string.rs | 11 ++++++----- src/utils.rs | 9 +++++---- 6 files changed, 47 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8a5b3de7a14..47777e4c5c4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -898,10 +898,11 @@ impl<'a> ControlFlow<'a> { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if let Some(cond_str) = trial { - if cond_str.len() <= context - .config - .width_heuristics() - .single_line_if_else_max_width + if cond_str.len() + <= context + .config + .width_heuristics() + .single_line_if_else_max_width { return Some((cond_str, 0)); } diff --git a/src/lists.rs b/src/lists.rs index 57f778896d3..6005ae6fd25 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -146,10 +146,12 @@ impl ListItem { } pub fn is_different_group(&self) -> bool { - self.inner_as_ref().contains('\n') || self.pre_comment.is_some() || self - .post_comment - .as_ref() - .map_or(false, |s| s.contains('\n')) + self.inner_as_ref().contains('\n') + || self.pre_comment.is_some() + || self + .post_comment + .as_ref() + .map_or(false, |s| s.contains('\n')) } pub fn is_multiline(&self) -> bool { diff --git a/src/macros.rs b/src/macros.rs index dab27d8a073..49f4a03ee1d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1168,22 +1168,24 @@ fn indent_macro_snippet( .min()?; Some( - first_line + "\n" + &trimmed_lines - .iter() - .map( - |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { - _ if !trimmed => line.to_owned(), - Some(original_indent_width) => { - let new_indent_width = indent.width() + original_indent_width - .saturating_sub(min_prefix_space_width); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line) - } - None => String::new(), - }, - ) - .collect::>() - .join("\n"), + first_line + + "\n" + + &trimmed_lines + .iter() + .map( + |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { + _ if !trimmed => line.to_owned(), + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width.saturating_sub(min_prefix_space_width); + let new_indent = Indent::from_width(context.config, new_indent_width); + format!("{}{}", new_indent.to_string(context.config), line) + } + None => String::new(), + }, + ) + .collect::>() + .join("\n"), ) } diff --git a/src/pairs.rs b/src/pairs.rs index c4451a8e466..79ae3081f1f 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -204,11 +204,12 @@ where // If the length of the lhs is equal to or shorter than the tab width or // the rhs looks like block expression, we put the rhs on the same // line with the lhs even if the rhs is multi-lined. - let allow_same_line = lhs_result.len() <= tab_spaces || rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); + let allow_same_line = lhs_result.len() <= tab_spaces + || rhs_result + .lines() + .next() + .map(|first_line| first_line.ends_with('{')) + .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { let one_line_width = last_line_width(&lhs_result) + pp.infix.len() @@ -308,10 +309,7 @@ impl FlattenPair for ast::Expr { } assert_eq!(list.len() - 1, separators.len()); - Some(PairList { - list, - separators, - }) + Some(PairList { list, separators }) } } diff --git a/src/string.rs b/src/string.rs index 2fe13db2139..b3f6daadfac 100644 --- a/src/string.rs +++ b/src/string.rs @@ -287,11 +287,12 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] return break_at(max_chars - 1); } if let Some(url_index_end) = detect_url(input, max_chars) { - let index_plus_ws = url_index_end + input[url_index_end..] - .iter() - .skip(1) - .position(|grapheme| not_whitespace_except_line_feed(grapheme)) - .unwrap_or(0); + let index_plus_ws = url_index_end + + input[url_index_end..] + .iter() + .skip(1) + .position(|grapheme| not_whitespace_except_line_feed(grapheme)) + .unwrap_or(0); return if trim_end { SnippetState::LineEnd( input[..=url_index_end].join("").to_string(), diff --git a/src/utils.rs b/src/utils.rs index 63b238a7817..421ab38e3f8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -324,10 +324,11 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { // Return true if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { ($self:ident, $span:expr) => { - !$self.config.file_lines().is_all() && !$self - .config - .file_lines() - .intersects(&$self.source_map.lookup_line_range($span)) + !$self.config.file_lines().is_all() + && !$self + .config + .file_lines() + .intersects(&$self.source_map.lookup_line_range($span)) }; } -- cgit 1.4.1-3-g733a5 From e29fd7bebe0ba302ec8d326a02c86b7fe71c30b4 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 15 Oct 2018 14:06:52 +1300 Subject: Only put `{` on a newline in a match arm where necessary Fixes #3005 --- src/chains.rs | 36 ++---------------------------------- src/matches.rs | 58 ++++++++++++++++++++++++---------------------------------- src/utils.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index b7619c0a18a..eb9771a2356 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -74,7 +74,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use source_map::SpanUtils; use utils::{ - first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, + self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, trimmed_last_line_width, wrap_str, }; @@ -130,7 +130,7 @@ enum ChainItemKind { impl ChainItemKind { fn is_block_like(&self, context: &RewriteContext, reps: &str) -> bool { match self { - ChainItemKind::Parent(ref expr) => is_block_expr(context, expr, reps), + ChainItemKind::Parent(ref expr) => utils::is_block_expr(context, expr, reps), ChainItemKind::MethodCall(..) | ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) @@ -845,38 +845,6 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } } -// States whether an expression's last line exclusively consists of closing -// parens, braces, and brackets in its idiomatic formatting. -fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { - match expr.node { - ast::ExprKind::Mac(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Array(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::Block(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) - | ast::ExprKind::Match(..) => repr.contains('\n'), - ast::ExprKind::Paren(ref expr) - | ast::ExprKind::Binary(_, _, ref expr) - | ast::ExprKind::Index(_, ref expr) - | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Closure(_, _, _, _, ref expr, _) - | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), - // This can only be a string lit - ast::ExprKind::Lit(_) => { - repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces() - } - _ => false, - } -} - /// Remove try operators (`?`s) that appear in the given string. If removing /// them leaves an empty line, remove that line as well unless it is the first /// line (we need the first newline for detecting pre/post comment). diff --git a/src/matches.rs b/src/matches.rs index a143c20f4bf..24f55483972 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -247,52 +247,42 @@ fn rewrite_match_arm( } else { (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; - let pats_str = - rewrite_match_pattern(context, &ptr_vec_to_ref_vec(&arm.pats), &arm.guard, shape) - .and_then(|pats_str| { - combine_strs_with_missing_comments( - context, - &attrs_str, - &pats_str, - missing_span, - shape, - false, - ) - })?; - let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span.lo()); - rewrite_match_body( - context, - &arm.body, - &pats_str, - shape, - arm.guard.is_some(), - arrow_span, - is_last, - ) -} - -fn rewrite_match_pattern( - context: &RewriteContext, - pats: &[&ast::Pat], - guard: &Option, - shape: Shape, -) -> Option { // Patterns // 5 = ` => {` let pat_shape = shape.sub_width(5)?; - let pats_str = rewrite_multiple_patterns(context, pats, pat_shape)?; + let pats_str = rewrite_multiple_patterns(context, &ptr_vec_to_ref_vec(&arm.pats), pat_shape)?; // Guard + let block_like_pat = trimmed_last_line_width(&pats_str) <= context.config.tab_spaces(); + let new_line_guard = pats_str.contains('\n') && !block_like_pat; let guard_str = rewrite_guard( context, - guard, + &arm.guard, shape, trimmed_last_line_width(&pats_str), - pats_str.contains('\n'), + new_line_guard, )?; - Some(format!("{}{}", pats_str, guard_str)) + let lhs_str = combine_strs_with_missing_comments( + context, + &attrs_str, + &format!("{}{}", pats_str, guard_str), + missing_span, + shape, + false, + )?; + + let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span.lo()); + rewrite_match_body( + context, + &arm.body, + &lhs_str, + shape, + guard_str.contains('\n'), + arrow_span, + is_last, + ) } fn block_can_be_flattened<'a>( diff --git a/src/utils.rs b/src/utils.rs index 63b238a7817..7d9272fe7e3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -417,3 +417,35 @@ pub fn starts_with_newline(s: &str) -> bool { pub fn first_line_ends_with(s: &str, c: char) -> bool { s.lines().next().map_or(false, |l| l.ends_with(c)) } + +// States whether an expression's last line exclusively consists of closing +// parens, braces, and brackets in its idiomatic formatting. +pub fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { + match expr.node { + ast::ExprKind::Mac(..) + | ast::ExprKind::Call(..) + | ast::ExprKind::MethodCall(..) + | ast::ExprKind::Array(..) + | ast::ExprKind::Struct(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::Match(..) => repr.contains('\n'), + ast::ExprKind::Paren(ref expr) + | ast::ExprKind::Binary(_, _, ref expr) + | ast::ExprKind::Index(_, ref expr) + | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Closure(_, _, _, _, ref expr, _) + | ast::ExprKind::Try(ref expr) + | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), + // This can only be a string lit + ast::ExprKind::Lit(_) => { + repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces() + } + _ => false, + } +} -- cgit 1.4.1-3-g733a5 From 075aa909cd2bcdc603f45e0b65119c6a7e3b2030 Mon Sep 17 00:00:00 2001 From: Daniele D'Orazio Date: Mon, 15 Oct 2018 04:18:37 +0200 Subject: try to fix comment bad wrapping (#3099) --- src/comment.rs | 16 +++++++++++---- src/expr.rs | 1 + src/string.rs | 38 ++++++++++++++++++++---------------- tests/source/issue-3059.rs | 7 +++++++ tests/target/issue-3059.rs | 8 ++++++++ tests/target/itemized-blocks/wrap.rs | 9 +++------ 6 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 tests/source/issue-3059.rs create mode 100644 tests/target/issue-3059.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index c946cc6e1c0..0f2409be1c6 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -579,7 +579,11 @@ fn rewrite_comment_inner( let item_fmt = ib.create_string_format(&fmt); result.push_str(&comment_line_separator); result.push_str(&ib.opener); - match rewrite_string(&item_block_buffer.replace("\n", " "), &item_fmt) { + match rewrite_string( + &item_block_buffer.replace("\n", " "), + &item_fmt, + max_chars.saturating_sub(ib.indent), + ) { Some(s) => result.push_str(&join_block( &s, &format!("{}{}", &comment_line_separator, ib.line_start), @@ -654,7 +658,7 @@ fn rewrite_comment_inner( } if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { - match rewrite_string(line, &fmt) { + match rewrite_string(line, &fmt, max_chars) { Some(ref s) => { is_prev_line_multi_line = s.contains('\n'); result.push_str(s); @@ -665,7 +669,7 @@ fn rewrite_comment_inner( result.pop(); result.push_str(&comment_line_separator); fmt.shape = Shape::legacy(max_chars, fmt_indent); - match rewrite_string(line, &fmt) { + match rewrite_string(line, &fmt, max_chars) { Some(ref s) => { is_prev_line_multi_line = s.contains('\n'); result.push_str(s); @@ -719,7 +723,11 @@ fn rewrite_comment_inner( let item_fmt = ib.create_string_format(&fmt); result.push_str(&comment_line_separator); result.push_str(&ib.opener); - match rewrite_string(&item_block_buffer.replace("\n", " "), &item_fmt) { + match rewrite_string( + &item_block_buffer.replace("\n", " "), + &item_fmt, + max_chars.saturating_sub(ib.indent), + ) { Some(s) => result.push_str(&join_block( &s, &format!("{}{}", &comment_line_separator, ib.line_start), diff --git a/src/expr.rs b/src/expr.rs index 8a5b3de7a14..752fb792899 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1254,6 +1254,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt rewrite_string( str_lit, &StringFormat::new(shape.visual_indent(0), context.config), + shape.width.saturating_sub(2), ) } diff --git a/src/string.rs b/src/string.rs index 2fe13db2139..ca063123e39 100644 --- a/src/string.rs +++ b/src/string.rs @@ -70,7 +70,11 @@ impl<'a> StringFormat<'a> { } } -pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option { +pub fn rewrite_string<'a>( + orig: &str, + fmt: &StringFormat<'a>, + newline_max_chars: usize, +) -> Option { let max_chars_with_indent = fmt.max_chars_with_indent()?; let max_chars_without_indent = fmt.max_chars_without_indent()?; let indent_with_newline = fmt.shape.indent.to_string_with_newline(fmt.config); @@ -129,7 +133,7 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option result.push_str(fmt.line_end); result.push_str(&indent_with_newline); result.push_str(fmt.line_start); - cur_max_chars = max_chars_with_indent; + cur_max_chars = newline_max_chars; cur_start += len; } SnippetState::EndWithLineFeed(line, len) => { @@ -358,7 +362,7 @@ mod test { fn issue343() { let config = Default::default(); let fmt = StringFormat::new(Shape::legacy(2, Indent::empty()), &config); - rewrite_string("eq_", &fmt); + rewrite_string("eq_", &fmt, 2); } #[test] @@ -463,7 +467,7 @@ mod test { let mut config: Config = Default::default(); config.set().max_width(27); let fmt = StringFormat::new(Shape::legacy(25, Indent::empty()), &config); - let rewritten_string = rewrite_string(string, &fmt); + let rewritten_string = rewrite_string(string, &fmt, 27); assert_eq!( rewritten_string, Some("\"Nulla\nconsequat erat at massa. \\\n Vivamus id mi.\"".to_string()) @@ -477,11 +481,11 @@ mod test { let mut fmt = StringFormat::new(Shape::legacy(25, Indent::empty()), &config); fmt.trim_end = true; - let rewritten_string = rewrite_string(string, &fmt); + let rewritten_string = rewrite_string(string, &fmt, 25); assert_eq!(rewritten_string, Some("\"Vivamus id mi.\"".to_string())); fmt.trim_end = false; // default value of trim_end - let rewritten_string = rewrite_string(string, &fmt); + let rewritten_string = rewrite_string(string, &fmt, 25); assert_eq!(rewritten_string, Some("\"Vivamus id mi. \"".to_string())); } @@ -499,7 +503,7 @@ mod test { config: &config, }; - let rewritten_string = rewrite_string(string, &fmt); + let rewritten_string = rewrite_string(string, &fmt, 100); assert_eq!( rewritten_string, Some("Vivamus id mi.\n // Vivamus id mi.".to_string()) @@ -521,7 +525,7 @@ mod test { }; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 30), Some( "Aenean metus.\n // Vestibulum ac lacus. Vivamus\n // porttitor" .to_string() @@ -544,7 +548,7 @@ mod test { }; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 30), Some( "Aenean metus.\n // Vestibulum ac lacus. Vivamus@\n // porttitor" .to_string() @@ -567,7 +571,7 @@ mod test { let comment = "Aenean metus. Vestibulum\n\nac lacus. Vivamus porttitor"; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 30), Some( "Aenean metus. Vestibulum\n //\n // ac lacus. Vivamus porttitor".to_string() ) @@ -576,7 +580,7 @@ mod test { fmt.shape = Shape::legacy(15, Indent::from_width(&config, 4)); let comment = "Aenean\n\nmetus. Vestibulum ac lacus. Vivamus porttitor"; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 15), Some( r#"Aenean // @@ -603,7 +607,7 @@ mod test { let comment = "Aenean\n\nmetus. Vestibulum ac lacus.\n\n"; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 20), Some( "Aenean\n //\n // metus. Vestibulum ac\n // lacus.\n //\n".to_string() ) @@ -611,13 +615,13 @@ mod test { let comment = "Aenean\n\nmetus. Vestibulum ac lacus.\n"; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 20), Some("Aenean\n //\n // metus. Vestibulum ac\n // lacus.\n".to_string()) ); let comment = "Aenean\n \nmetus. Vestibulum ac lacus."; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 20), Some("Aenean\n //\n // metus. Vestibulum ac\n // lacus.".to_string()) ); } @@ -637,14 +641,14 @@ mod test { let comment = "Aenean metus. Vestibulum ac lacus."; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 13), Some("Aenean metus.\n // Vestibulum ac\n // lacus.".to_string()) ); fmt.trim_end = false; let comment = "Vestibulum ac lacus."; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 13), Some("Vestibulum \n // ac lacus.".to_string()) ); @@ -652,7 +656,7 @@ mod test { fmt.line_end = "\\"; let comment = "Vestibulum ac lacus."; assert_eq!( - rewrite_string(comment, &fmt), + rewrite_string(comment, &fmt, 13), Some("Vestibulum\\\n // ac lacus.".to_string()) ); } diff --git a/tests/source/issue-3059.rs b/tests/source/issue-3059.rs new file mode 100644 index 00000000000..49a75cd67ab --- /dev/null +++ b/tests/source/issue-3059.rs @@ -0,0 +1,7 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 80 + +/// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc commodo ultricies dui. +/// Cras gravida rutrum massa. Donec accumsan mattis turpis. Quisque sem. Quisque elementum sapien +/// iaculis augue. In dui sem, congue sit amet, feugiat quis, lobortis at, eros. +fn func4() {} diff --git a/tests/target/issue-3059.rs b/tests/target/issue-3059.rs new file mode 100644 index 00000000000..f750c128759 --- /dev/null +++ b/tests/target/issue-3059.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 80 + +/// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc +/// commodo ultricies dui. Cras gravida rutrum massa. Donec accumsan mattis +/// turpis. Quisque sem. Quisque elementum sapien iaculis augue. In dui sem, +/// congue sit amet, feugiat quis, lobortis at, eros. +fn func4() {} diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index 08d8ca35261..c4d687dd3db 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -40,8 +40,7 @@ /// All the parameters ***except for /// `from_theater`*** should be inserted as sent /// by the remote theater, ie. as passed to -/// [`Theater::send`] on the remote -/// actor: +/// [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], /// as reported by the remote theater by /// theater-specific means @@ -53,15 +52,13 @@ /// All the parameters ***except for /// `from_theater`*** should be inserted as sent /// by the remote theater, ie. as passed to -/// [`Theater::send`] on the remote -/// actor +/// [`Theater::send`] on the remote actor fn func1() {} /// All the parameters ***except for /// `from_theater`*** should be inserted as sent /// by the remote theater, ie. as passed to -/// [`Theater::send`] on the remote -/// actor: +/// [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], /// as reported by the remote theater by /// theater-specific means -- cgit 1.4.1-3-g733a5 From 094e687e42a19b747203fa1967d192c5384ef459 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 9 Oct 2018 21:28:40 +0900 Subject: Remove an unsafe code --- src/visitor.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 30752826a85..7b952c20f52 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -792,13 +792,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { where F: Fn(&RewriteContext) -> Option, { - let result; - let macro_rewrite_failure = { - let context = self.get_context(); - result = f(&context); - unsafe { *context.macro_rewrite_failure.as_ptr() } - }; - self.macro_rewrite_failure |= macro_rewrite_failure; + let context = self.get_context(); + let result = f(&context); + self.macro_rewrite_failure |= *context.macro_rewrite_failure.borrow(); result } -- cgit 1.4.1-3-g733a5 From d55729987ff798b49838e5b5707cfca807b5b6b7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 9 Oct 2018 21:47:00 +0900 Subject: Use UnOp::to_string --- src/expr.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 752fb792899..48a493c8a74 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1815,12 +1815,7 @@ fn rewrite_unary_op( shape: Shape, ) -> Option { // For some reason, an UnOp is not spanned like BinOp! - let operator_str = match op { - ast::UnOp::Deref => "*", - ast::UnOp::Not => "!", - ast::UnOp::Neg => "-", - }; - rewrite_unary_prefix(context, operator_str, expr, shape) + rewrite_unary_prefix(context, ast::UnOp::to_string(op), expr, shape) } fn rewrite_assignment( -- cgit 1.4.1-3-g733a5 From 751bcf5fa08ee5c5ba156e43c7f8327f7968b02f Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 15 Oct 2018 20:36:39 +0900 Subject: Clippy --- src/format-diff/main.rs | 2 +- src/items.rs | 19 +++++++------------ src/lists.rs | 2 +- src/macros.rs | 4 ++-- src/overflow.rs | 2 +- src/source_map.rs | 12 +++++++----- src/utils.rs | 2 +- src/visitor.rs | 33 ++++++++++++++++----------------- 8 files changed, 36 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index d509a4429b4..aacfa12d437 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -83,7 +83,7 @@ fn main() { ); if let Err(e) = run(&opts) { - println!("{}", opts.usage(&format!("{}", e))); + println!("{}", opts.usage(&e.to_string())); process::exit(1); } } diff --git a/src/items.rs b/src/items.rs index 1673bffbce9..b35e8ea4587 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1543,7 +1543,7 @@ pub fn rewrite_struct_field_prefix( rewrite_ident(context, name), type_annotation_spacing.0 ), - None => format!("{}", vis), + None => vis.to_string(), }) } @@ -2004,18 +2004,13 @@ fn rewrite_fn_base( one_line_budget, multi_line_budget, arg_indent ); + result.push('('); // Check if vertical layout was forced. - if one_line_budget == 0 { - if snuggle_angle_bracket { - result.push('('); - } else { - result.push_str("("); - if context.config.indent_style() == IndentStyle::Visual { - result.push_str(&arg_indent.to_string_with_newline(context.config)); - } - } - } else { - result.push('('); + if one_line_budget == 0 + && !snuggle_angle_bracket + && context.config.indent_style() == IndentStyle::Visual + { + result.push_str(&arg_indent.to_string_with_newline(context.config)); } // Skip `pub(crate)`. diff --git a/src/lists.rs b/src/lists.rs index 57f778896d3..92990fe9a17 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -50,7 +50,7 @@ impl<'a> ListFormatting<'a> { ends_with_newline: true, preserve_newline: false, nested: false, - config: config, + config, } } diff --git a/src/macros.rs b/src/macros.rs index dab27d8a073..1e668cf1d87 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1073,7 +1073,7 @@ fn next_space(tok: &Token) -> SpaceState { /// when the macro is not an instance of try! (or parsing the inner expression /// failed). pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { - if &format!("{}", mac.node.path) == "try" { + if &mac.node.path.to_string() == "try" { let ts: TokenStream = mac.node.tts.clone().into(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); @@ -1491,5 +1491,5 @@ fn rewrite_macro_with_items( result.push_str(&shape.indent.to_string_with_newline(context.config)); result.push_str(closer); result.push_str(trailing_semicolon); - return Some(result); + Some(result) } diff --git a/src/overflow.rs b/src/overflow.rs index fc1803b2ab6..053ce1b9212 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -425,7 +425,7 @@ impl<'a> Context<'a> { _ => expr.rewrite(self.context, shape), } } - item @ _ => item.rewrite(self.context, shape), + item => item.rewrite(self.context, shape), }; if let Some(rewrite) = rewrite { diff --git a/src/source_map.rs b/src/source_map.rs index dee5e4f7601..ed081adcd86 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -51,11 +51,13 @@ impl<'a> SpanUtils for SnippetProvider<'a> { } fn span_before(&self, original: Span, needle: &str) -> BytePos { - self.opt_span_before(original, needle).expect(&format!( - "bad span: {}: {}", - needle, - self.span_to_snippet(original).unwrap() - )) + self.opt_span_before(original, needle).unwrap_or_else(|| { + panic!( + "bad span: {}: {}", + needle, + self.span_to_snippet(original).unwrap() + ) + }) } fn opt_span_after(&self, original: Span, needle: &str) -> Option { diff --git a/src/utils.rs b/src/utils.rs index 7ef9254a482..2ff3b7e525a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -45,7 +45,7 @@ pub fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { ( VisibilityKind::Restricted { path: p, .. }, VisibilityKind::Restricted { path: q, .. }, - ) => format!("{}", p) == format!("{}", q), + ) => p.to_string() == q.to_string(), (VisibilityKind::Public, VisibilityKind::Public) | (VisibilityKind::Inherited, VisibilityKind::Inherited) | ( diff --git a/src/visitor.rs b/src/visitor.rs index 7b952c20f52..63e2c6bdcac 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -112,7 +112,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if contains_skip(get_attrs_from_stmt(stmt)) { self.push_skipped_with_span(stmt.span()); } else { - let shape = self.shape().clone(); + let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); self.push_rewrite(stmt.span(), rewrite) } @@ -367,13 +367,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let where_span_end = snippet .find_uncommented("{") .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); - let block_indent = self.block_indent.clone(); + let block_indent = self.block_indent; let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end)); self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { - let block_indent = self.block_indent.clone(); + let block_indent = self.block_indent; let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); self.push_rewrite(item.span, rw); } @@ -652,20 +652,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ErrorKind::DeprecatedAttr, )], ); - } else if attr.path.segments[0].ident.to_string() == "rustfmt" { - if attr.path.segments.len() == 1 - || attr.path.segments[1].ident.to_string() != "skip" - { - let file_name = self.source_map.span_to_filename(attr.span).into(); - self.report.append( - file_name, - vec![FormattingError::from_span( - attr.span, - &self.source_map, - ErrorKind::BadAttr, - )], - ); - } + } else if attr.path.segments[0].ident.to_string() == "rustfmt" + && (attr.path.segments.len() == 1 + || attr.path.segments[1].ident.to_string() != "skip") + { + let file_name = self.source_map.span_to_filename(attr.span).into(); + self.report.append( + file_name, + vec![FormattingError::from_span( + attr.span, + &self.source_map, + ErrorKind::BadAttr, + )], + ); } } if contains_skip(attrs) { -- cgit 1.4.1-3-g733a5 From 6380f885278e33ff058e01555538ced58c44dacf Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 10 Oct 2018 10:50:25 +0900 Subject: Cleanup --- src/missed_spans.rs | 18 ++---------------- src/string.rs | 4 ++-- 2 files changed, 4 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index f2f2295a872..b7d73bbf0ba 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -120,7 +120,7 @@ impl<'a> FmtVisitor<'a> { } fn push_vertical_spaces(&mut self, mut newline_count: usize) { - let offset = self.count_trailing_newlines(); + let offset = self.buffer.chars().rev().take_while(|c| *c == '\n').count(); let newline_upper_bound = self.config.blank_lines_upper_bound() + 1; let newline_lower_bound = self.config.blank_lines_lower_bound() + 1; @@ -142,16 +142,6 @@ impl<'a> FmtVisitor<'a> { self.push_str(&blank_lines); } - fn count_trailing_newlines(&self) -> usize { - let mut buf = &*self.buffer; - let mut result = 0; - while buf.ends_with('\n') { - buf = &buf[..buf.len() - 1]; - result += 1; - } - result - } - fn write_snippet(&mut self, span: Span, process_last_snippet: F) where F: Fn(&mut FmtVisitor, &str, &str), @@ -271,11 +261,7 @@ impl<'a> FmtVisitor<'a> { if let Some('/') = subslice.chars().nth(1) { // check that there are no contained block comments - if !subslice - .split('\n') - .map(|s| s.trim_left()) - .any(|s| s.len() >= 2 && &s[0..2] == "/*") - { + if !subslice.lines().any(|s| s.trim_left().starts_with("/*")) { // Add a newline after line comments self.push_str("\n"); } diff --git a/src/string.rs b/src/string.rs index ca063123e39..b70f9f0f12b 100644 --- a/src/string.rs +++ b/src/string.rs @@ -242,9 +242,9 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] for (i, grapheme) in input[0..=index].iter().enumerate() { if is_line_feed(grapheme) { if i <= index_minus_ws { - let mut line = input[0..i].join(""); + let mut line = &input[0..i].join("")[..]; if trim_end { - line = line.trim_right().to_string(); + line = line.trim_right(); } return SnippetState::EndWithLineFeed(format!("{}\n", line), i + 1); } -- cgit 1.4.1-3-g733a5 From 6fb188bd43840f4a99c6a4b4cdbdb21ccf3304e7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 15 Oct 2018 21:10:34 +0900 Subject: Use concat() instead of join("") --- src/string.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/string.rs b/src/string.rs index b70f9f0f12b..d45f15a1c9b 100644 --- a/src/string.rs +++ b/src/string.rs @@ -172,7 +172,7 @@ fn detect_url(s: &[&str], index: usize) -> Option { if s.len() < start + 8 { return None; } - let prefix = s[start..start + 8].join(""); + let prefix = s[start..start + 8].concat(); if prefix.starts_with("https://") || prefix.starts_with("http://") || prefix.starts_with("ftp://") @@ -242,7 +242,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] for (i, grapheme) in input[0..=index].iter().enumerate() { if is_line_feed(grapheme) { if i <= index_minus_ws { - let mut line = &input[0..i].join("")[..]; + let mut line = &input[0..i].concat()[..]; if trim_end { line = line.trim_right(); } @@ -256,7 +256,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] for (i, grapheme) in input[index + 1..].iter().enumerate() { if !trim_end && is_line_feed(grapheme) { return SnippetState::EndWithLineFeed( - input[0..=index + 1 + i].join("").to_string(), + input[0..=index + 1 + i].concat(), index + 2 + i, ); } else if not_whitespace_except_line_feed(grapheme) { @@ -266,15 +266,9 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] } if trim_end { - SnippetState::LineEnd( - input[0..=index_minus_ws].join("").to_string(), - index_plus_ws + 1, - ) + SnippetState::LineEnd(input[0..=index_minus_ws].concat(), index_plus_ws + 1) } else { - SnippetState::LineEnd( - input[0..=index_plus_ws].join("").to_string(), - index_plus_ws + 1, - ) + SnippetState::LineEnd(input[0..=index_plus_ws].concat(), index_plus_ws + 1) } }; @@ -297,15 +291,9 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] .position(|grapheme| not_whitespace_except_line_feed(grapheme)) .unwrap_or(0); return if trim_end { - SnippetState::LineEnd( - input[..=url_index_end].join("").to_string(), - index_plus_ws + 1, - ) + SnippetState::LineEnd(input[..=url_index_end].concat(), index_plus_ws + 1) } else { - return SnippetState::LineEnd( - input[..=index_plus_ws].join("").to_string(), - index_plus_ws + 1, - ); + return SnippetState::LineEnd(input[..=index_plus_ws].concat(), index_plus_ws + 1); }; } match input[0..max_chars] @@ -330,7 +318,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] // A boundary was found after the line limit Some(index) => break_at(max_chars + index), // No boundary to the right, the input cannot be broken - None => SnippetState::EndOfInput(input.join("").to_string()), + None => SnippetState::EndOfInput(input.concat()), }, }, } -- cgit 1.4.1-3-g733a5 From 6c964fd0303041066381204328d4368b5c29d3f7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 15 Oct 2018 21:20:03 +0900 Subject: Reduce allocations --- src/comment.rs | 6 +++--- src/config/config_type.rs | 2 +- src/items.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0f2409be1c6..561989a1a11 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -764,12 +764,12 @@ fn trim_custom_comment_prefix(s: &str) -> String { // due to comment wrapping, a line that was originaly behind `#` is split over // multiple lines, which needs then to be prefixed with a `#` if !orig.trim_left().starts_with("# ") { - format!("# {}", orig) + Cow::from(format!("# {}", orig)) } else { - orig.to_string() + Cow::from(orig) } } else { - line.to_string() + Cow::from(line) } }) .collect::>() diff --git a/src/config/config_type.rs b/src/config/config_type.rs index edd6ae5634f..291a59e1055 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -112,7 +112,7 @@ macro_rules! create_config { cloned.width_heuristics = None; ::toml::to_string(&cloned) - .map_err(|e| format!("Could not output config: {}", e.to_string())) + .map_err(|e| format!("Could not output config: {}", e)) } } diff --git a/src/items.rs b/src/items.rs index b35e8ea4587..19caafbfb82 100644 --- a/src/items.rs +++ b/src/items.rs @@ -779,7 +779,7 @@ pub fn format_impl( let outer_indent_str = offset.block_only().to_string_with_newline(context.config); result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.to_string().trim()); + result.push_str(visitor.buffer.trim()); result.push_str(&outer_indent_str); } else if need_newline || !context.config.empty_item_single_line() { result.push_str(&sep); @@ -1137,7 +1137,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); result.push_str(&inner_indent_str); - result.push_str(visitor.buffer.to_string().trim()); + result.push_str(visitor.buffer.trim()); result.push_str(&outer_indent_str); } else if result.contains('\n') { result.push_str(&outer_indent_str); -- cgit 1.4.1-3-g733a5 From 30c06da78124dad8341689a15d6ccfe1450c5ab9 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 15 Oct 2018 23:24:35 +0200 Subject: force a newline after the `if` condition if there is a different indentation level --- src/expr.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- tests/source/issue-3038.rs | 20 ++++++++++++++++++++ tests/target/issue-2985.rs | 3 ++- tests/target/issue-3038.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3038.rs create mode 100644 tests/target/issue-3038.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 15ffb842ee4..fbbc592e547 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -801,6 +801,20 @@ impl<'a> ControlFlow<'a> { } } +/// Returns true if the last line of pat_str has leading whitespace and it is wider than the +/// shape's indent. +fn last_line_offsetted(start_column: usize, pat_str: &str) -> bool { + let mut leading_whitespaces = 0; + for c in pat_str.chars().rev() { + match c { + '\n' => break, + _ if c.is_whitespace() => leading_whitespaces += 1, + _ => leading_whitespaces = 0, + } + } + leading_whitespaces > start_column +} + impl<'a> ControlFlow<'a> { fn rewrite_pat_expr( &self, @@ -885,7 +899,8 @@ impl<'a> ControlFlow<'a> { .saturating_sub(constr_shape.used_width() + offset + brace_overhead); let force_newline_brace = (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) - && !last_line_extendable(&pat_expr_string); + && (!last_line_extendable(&pat_expr_string) + || last_line_offsetted(shape.used_width(), &pat_expr_string)); // Try to format if-else on single line. if self.allow_single_line @@ -1977,3 +1992,29 @@ pub fn is_method_call(expr: &ast::Expr) -> bool { _ => false, } } + +#[cfg(test)] +mod test { + use super::last_line_offsetted; + + #[test] + fn test_last_line_offsetted() { + let lines = "one\n two"; + assert_eq!(last_line_offsetted(2, lines), true); + assert_eq!(last_line_offsetted(4, lines), false); + assert_eq!(last_line_offsetted(6, lines), false); + + let lines = "one two"; + assert_eq!(last_line_offsetted(2, lines), false); + assert_eq!(last_line_offsetted(0, lines), false); + + let lines = "\ntwo"; + assert_eq!(last_line_offsetted(2, lines), false); + assert_eq!(last_line_offsetted(0, lines), false); + + let lines = "one\n two three"; + assert_eq!(last_line_offsetted(2, lines), true); + let lines = "one\n two three"; + assert_eq!(last_line_offsetted(2, lines), false); + } +} diff --git a/tests/source/issue-3038.rs b/tests/source/issue-3038.rs new file mode 100644 index 00000000000..0fbb05ddc0e --- /dev/null +++ b/tests/source/issue-3038.rs @@ -0,0 +1,20 @@ +impl HTMLTableElement { + fn func() { + if number_of_row_elements == 0 { + if let Some(last_tbody) = node.rev_children() + .filter_map(DomRoot::downcast::) + .find(|n| n.is::() && n.local_name() == &local_name!("tbody")) { + last_tbody.upcast::().AppendChild(new_row.upcast::()) + .expect("InsertRow failed to append first row."); + } + } + + if number_of_row_elements == 0 { + if let Some(last_tbody) = node + .find(|n| n.is::() && n.local_name() == &local_name!("tbody")) { + last_tbody.upcast::().AppendChild(new_row.upcast::()) + .expect("InsertRow failed to append first row."); + } + } + } +} diff --git a/tests/target/issue-2985.rs b/tests/target/issue-2985.rs index 37b216ea9b1..faad859236d 100644 --- a/tests/target/issue-2985.rs +++ b/tests/target/issue-2985.rs @@ -27,7 +27,8 @@ fn foo() { .map(String::as_ref) .unwrap_or("") .is_empty() - }) { + }) + { do_something(); } } diff --git a/tests/target/issue-3038.rs b/tests/target/issue-3038.rs new file mode 100644 index 00000000000..3c398b825d7 --- /dev/null +++ b/tests/target/issue-3038.rs @@ -0,0 +1,29 @@ +impl HTMLTableElement { + fn func() { + if number_of_row_elements == 0 { + if let Some(last_tbody) = node + .rev_children() + .filter_map(DomRoot::downcast::) + .find(|n| { + n.is::() && n.local_name() == &local_name!("tbody") + }) + { + last_tbody + .upcast::() + .AppendChild(new_row.upcast::()) + .expect("InsertRow failed to append first row."); + } + } + + if number_of_row_elements == 0 { + if let Some(last_tbody) = node.find(|n| { + n.is::() && n.local_name() == &local_name!("tbody") + }) { + last_tbody + .upcast::() + .AppendChild(new_row.upcast::()) + .expect("InsertRow failed to append first row."); + } + } + } +} -- cgit 1.4.1-3-g733a5 From 8c4e92a14ecd63b71c28cc6461883dc914d47979 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 17 Oct 2018 14:21:04 +0900 Subject: Catch parser panic in format_snippet (#3103) --- src/lib.rs | 34 +++++++++++++++--------- tests/source/invalid-rust-code-in-doc-comment.rs | 20 ++++++++++++++ tests/target/invalid-rust-code-in-doc-comment.rs | 18 +++++++++++++ 3 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 tests/source/invalid-rust-code-in-doc-comment.rs create mode 100644 tests/target/invalid-rust-code-in-doc-comment.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 772ed8cb141..9540b9fd20e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ use std::collections::HashMap; use std::fmt; use std::io::{self, Write}; use std::mem; +use std::panic; use std::path::PathBuf; use std::rc::Rc; use syntax::ast; @@ -355,21 +356,28 @@ impl fmt::Display for FormatReport { /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. fn format_snippet(snippet: &str, config: &Config) -> Option { - let mut out: Vec = Vec::with_capacity(snippet.len() * 2); - let input = Input::Text(snippet.into()); let mut config = config.clone(); - config.set().emit_mode(config::EmitMode::Stdout); - config.set().verbose(Verbosity::Quiet); - config.set().hide_parse_errors(true); - { - let mut session = Session::new(config, Some(&mut out)); - let result = session.format(input); - let formatting_error = session.errors.has_macro_format_failure - || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty(); - if formatting_error || result.is_err() { - return None; + let out = panic::catch_unwind(|| { + let mut out: Vec = Vec::with_capacity(snippet.len() * 2); + config.set().emit_mode(config::EmitMode::Stdout); + config.set().verbose(Verbosity::Quiet); + config.set().hide_parse_errors(true); + let formatting_error = { + let input = Input::Text(snippet.into()); + let mut session = Session::new(config, Some(&mut out)); + let result = session.format(input); + session.errors.has_macro_format_failure + || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() + || result.is_err() + }; + if formatting_error { + None + } else { + Some(out) } - } + }) + .ok()??; // The first try operator handles the error from catch_unwind, + // whereas the second one handles None from the closure. String::from_utf8(out).ok() } diff --git a/tests/source/invalid-rust-code-in-doc-comment.rs b/tests/source/invalid-rust-code-in-doc-comment.rs new file mode 100644 index 00000000000..6d33dcfce55 --- /dev/null +++ b/tests/source/invalid-rust-code-in-doc-comment.rs @@ -0,0 +1,20 @@ +// rustfmt-format_doc_comments: true + +/// ```rust +/// if (true) { … } +/// ``` +fn a() { +} + +/// ```rust +/// if foo() { +/// … +/// } +/// ``` +fn a() { +} + +/// ```rust +/// k1 == k2 ⇒ hash(k1) == hash(k2) +/// ``` +pub struct a ; diff --git a/tests/target/invalid-rust-code-in-doc-comment.rs b/tests/target/invalid-rust-code-in-doc-comment.rs new file mode 100644 index 00000000000..2593410a418 --- /dev/null +++ b/tests/target/invalid-rust-code-in-doc-comment.rs @@ -0,0 +1,18 @@ +// rustfmt-format_doc_comments: true + +/// ```rust +/// if (true) { … } +/// ``` +fn a() {} + +/// ```rust +/// if foo() { +/// … +/// } +/// ``` +fn a() {} + +/// ```rust +/// k1 == k2 ⇒ hash(k1) == hash(k2) +/// ``` +pub struct a; -- cgit 1.4.1-3-g733a5 From 613dfcc521e07088dbd72a8dcf484f002139f453 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 18 Oct 2018 09:55:21 +1300 Subject: Remove various feature flags --- src/config/config_type.rs | 2 +- src/imports.rs | 22 +++++++++++++--------- src/lib.rs | 4 ---- src/macros.rs | 27 +++++++++++++++------------ src/overflow.rs | 4 ++-- 5 files changed, 31 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 291a59e1055..419cd06436f 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -243,7 +243,7 @@ macro_rules! create_config { if !err.is_empty() { eprint!("{}", err); } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir: &Path)) + Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); diff --git a/src/imports.rs b/src/imports.rs index f4751eb117b..e7817c175b4 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -925,19 +925,23 @@ mod test { parser.parse_in_list() } - macro parse_use_trees($($s:expr),* $(,)*) { - vec![ - $(parse_use_tree($s),)* - ] + macro_rules! parse_use_trees { + ($($s:expr),* $(,)*) => { + vec![ + $(parse_use_tree($s),)* + ] + } } #[test] fn test_use_tree_merge() { - macro test_merge([$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) { - assert_eq!( - merge_use_trees(parse_use_trees!($($input,)*)), - parse_use_trees!($($output,)*), - ); + macro_rules! test_merge { + ([$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => { + assert_eq!( + merge_use_trees(parse_use_trees!($($input,)*)), + parse_use_trees!($($output,)*), + ); + } } test_merge!(["a::b::{c, d}", "a::b::{e, f}"], ["a::b::{c, d, e, f}"]); diff --git a/src/lib.rs b/src/lib.rs index 9540b9fd20e..a8958abab39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,10 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro)] -#![allow(unused_attributes)] -#![feature(type_ascription)] -#![feature(unicode_internals)] #![feature(nll)] #[macro_use] diff --git a/src/macros.rs b/src/macros.rs index baf1ed45253..a7a6a7fc6b7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -867,7 +867,8 @@ impl MacroArgParser { /// Returns a collection of parsed macro def's arguments. pub fn parse(mut self, tokens: ThinTokenStream) -> Option> { - let mut iter = (tokens.into(): TokenStream).trees(); + let stream: TokenStream = tokens.into(); + let mut iter = stream.trees(); while let Some(ref tok) = iter.next() { match tok { @@ -1398,21 +1399,23 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) result.push_str("lazy_static! {"); result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); - macro parse_or($method:ident $(,)* $($arg:expr),* $(,)*) { - match parser.$method($($arg,)*) { - Ok(val) => { - if parser.sess.span_diagnostic.has_errors() { + macro_rules! parse_or { + ($method:ident $(,)* $($arg:expr),* $(,)*) => { + match parser.$method($($arg,)*) { + Ok(val) => { + if parser.sess.span_diagnostic.has_errors() { + parser.sess.span_diagnostic.reset_err_count(); + return None; + } else { + val + } + } + Err(mut err) => { + err.cancel(); parser.sess.span_diagnostic.reset_err_count(); return None; - } else { - val } } - Err(mut err) => { - err.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - return None; - } } } diff --git a/src/overflow.rs b/src/overflow.rs index 053ce1b9212..5336b86eb4b 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -200,7 +200,7 @@ impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for ptr::P { $( impl<'a> IntoOverflowableItem<'a> for ast::$ast_node { @@ -212,7 +212,7 @@ macro impl_into_overflowable_item_for_ast_node { } } -macro impl_into_overflowable_item_for_rustfmt_types { +macro_rules! impl_into_overflowable_item_for_rustfmt_types { ([$($ty:ident),*], [$($ty_with_lifetime:ident),*]) => { $( impl<'a> IntoOverflowableItem<'a> for $ty { -- cgit 1.4.1-3-g733a5 From 4bb84f6002d8b57f7baf3d31feb636a1d3711ffc Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 18 Oct 2018 11:45:55 +1300 Subject: Remove NLL feature And do some refactoring in comments.rs Closes #3107 --- src/chains.rs | 8 +- src/comment.rs | 452 +++++++++++++++++++++++++++++------------------------- src/formatting.rs | 3 +- src/lib.rs | 2 - src/macros.rs | 7 +- src/test/mod.rs | 2 +- src/utils.rs | 37 ++++- src/visitor.rs | 12 +- 8 files changed, 298 insertions(+), 225 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index eb9771a2356..be383006196 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -447,7 +447,7 @@ trait ChainFormatter { // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. // Root is the parent plus any other chain items placed on the first line to // avoid an orphan. E.g., - // ``` + // ```ignore // foo.bar // .baz() // ``` @@ -509,7 +509,7 @@ impl<'a> ChainFormatterShared<'a> { // know whether 'overflowing' the last child make a better formatting: // // A chain with overflowing the last child: - // ``` + // ```ignore // parent.child1.child2.last_child( // a, // b, @@ -518,7 +518,7 @@ impl<'a> ChainFormatterShared<'a> { // ``` // // A chain without overflowing the last child (in vertical layout): - // ``` + // ```ignore // parent // .child1 // .child2 @@ -527,7 +527,7 @@ impl<'a> ChainFormatterShared<'a> { // // In particular, overflowing is effective when the last child is a method with a multi-lined // block-like argument (e.g. closure): - // ``` + // ```ignore // parent.child1.child2.last_child(|a, b, c| { // let x = foo(a, b, c); // let y = bar(a, b, c); diff --git a/src/comment.rs b/src/comment.rs index 561989a1a11..9dd7d689655 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -488,70 +488,75 @@ impl ItemizedBlock { } } -fn rewrite_comment_inner( - orig: &str, - block_style: bool, - style: CommentStyle, - shape: Shape, - config: &Config, - is_doc_comment: bool, -) -> Option { - let (opener, closer, line_start) = if block_style { - CommentStyle::SingleBullet.to_str_tuplet() - } else { - comment_style(orig, config.normalize_comments()).to_str_tuplet() - }; +struct CommentRewrite<'a> { + result: String, + code_block_buffer: String, + is_prev_line_multi_line: bool, + code_block_attr: Option, + item_block_buffer: String, + item_block: Option, + comment_line_separator: String, + indent_str: String, + max_chars: usize, + fmt_indent: Indent, + fmt: StringFormat<'a>, - let max_chars = shape - .width - .checked_sub(closer.len() + opener.len()) - .unwrap_or(1); - let indent_str = shape.indent.to_string_with_newline(config); - let fmt_indent = shape.indent + (opener.len() - line_start.len()); - let mut fmt = StringFormat { - opener: "", - closer: "", - line_start, - line_end: "", - shape: Shape::legacy(max_chars, fmt_indent), - trim_end: true, - config, - }; + opener: String, + closer: String, + line_start: String, +} - let line_breaks = count_newlines(orig.trim_right()); - let lines = orig - .lines() - .enumerate() - .map(|(i, mut line)| { - line = trim_right_unless_two_whitespaces(line.trim_left(), is_doc_comment); - // Drop old closer. - if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = line[..(line.len() - 2)].trim_right(); - } +impl<'a> CommentRewrite<'a> { + fn new( + orig: &'a str, + block_style: bool, + shape: Shape, + config: &'a Config, + ) -> CommentRewrite<'a> { + let (opener, closer, line_start) = if block_style { + CommentStyle::SingleBullet.to_str_tuplet() + } else { + comment_style(orig, config.normalize_comments()).to_str_tuplet() + }; - line - }) - .map(|s| left_trim_comment_line(s, &style)) - .map(|(line, has_leading_whitespace)| { - if orig.starts_with("/*") && line_breaks == 0 { - ( - line.trim_left(), - has_leading_whitespace || config.normalize_comments(), - ) - } else { - (line, has_leading_whitespace || config.normalize_comments()) - } - }); + let max_chars = shape + .width + .checked_sub(closer.len() + opener.len()) + .unwrap_or(1); + let indent_str = shape.indent.to_string_with_newline(config).to_string(); + let fmt_indent = shape.indent + (opener.len() - line_start.len()); + + let mut cr = CommentRewrite { + result: String::with_capacity(orig.len() * 2), + code_block_buffer: String::with_capacity(128), + is_prev_line_multi_line: false, + code_block_attr: None, + item_block_buffer: String::with_capacity(128), + item_block: None, + comment_line_separator: format!("{}{}", indent_str, line_start), + max_chars, + indent_str, + fmt_indent, + + fmt: StringFormat { + opener: "", + closer: "", + line_start, + line_end: "", + shape: Shape::legacy(max_chars, fmt_indent), + trim_end: true, + config, + }, - let mut result = String::with_capacity(orig.len() * 2); - result.push_str(opener); - let mut code_block_buffer = String::with_capacity(128); - let mut is_prev_line_multi_line = false; - let mut code_block_attr = None; - let mut item_block_buffer = String::with_capacity(128); - let mut item_block: Option = None; - let comment_line_separator = format!("{}{}", indent_str, line_start); - let join_block = |s: &str, sep: &str| { + opener: opener.to_owned(), + closer: closer.to_owned(), + line_start: line_start.to_owned(), + }; + cr.result.push_str(opener); + cr + } + + fn join_block(s: &str, sep: &str) -> String { let mut result = String::with_capacity(s.len() + 128); let mut iter = s.lines().peekable(); while let Some(line) = iter.next() { @@ -563,186 +568,252 @@ fn rewrite_comment_inner( }); } result - }; + } - for (i, (line, has_leading_whitespace)) in lines.enumerate() { + fn finish(mut self) -> String { + if !self.code_block_buffer.is_empty() { + // There is a code block that is not properly enclosed by backticks. + // We will leave them untouched. + self.result.push_str(&self.comment_line_separator); + self.result.push_str(&Self::join_block( + &trim_custom_comment_prefix(&self.code_block_buffer), + &self.comment_line_separator, + )); + } + + if !self.item_block_buffer.is_empty() { + // the last few lines are part of an itemized block + self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + let mut ib = None; + ::std::mem::swap(&mut ib, &mut self.item_block); + let ib = ib.unwrap(); + let item_fmt = ib.create_string_format(&self.fmt); + self.result.push_str(&self.comment_line_separator); + self.result.push_str(&ib.opener); + match rewrite_string( + &self.item_block_buffer.replace("\n", " "), + &item_fmt, + self.max_chars.saturating_sub(ib.indent), + ) { + Some(s) => self.result.push_str(&Self::join_block( + &s, + &format!("{}{}", &self.comment_line_separator, ib.line_start), + )), + None => self.result.push_str(&Self::join_block( + &self.item_block_buffer, + &self.comment_line_separator, + )), + }; + } + + self.result.push_str(&self.closer); + if self.result.ends_with(&self.opener) && self.opener.ends_with(' ') { + // Trailing space. + self.result.pop(); + } + + self.result + } + + fn handle_line( + &mut self, + orig: &'a str, + i: usize, + line: &'a str, + has_leading_whitespace: bool, + ) -> bool { let is_last = i == count_newlines(orig); - if let Some(ref ib) = item_block { + if let Some(ref ib) = self.item_block { if ib.in_block(&line) { - item_block_buffer.push_str(&line); - item_block_buffer.push('\n'); - continue; + self.item_block_buffer.push_str(&line); + self.item_block_buffer.push('\n'); + return false; } - is_prev_line_multi_line = false; - fmt.shape = Shape::legacy(max_chars, fmt_indent); - let item_fmt = ib.create_string_format(&fmt); - result.push_str(&comment_line_separator); - result.push_str(&ib.opener); + self.is_prev_line_multi_line = false; + self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + let item_fmt = ib.create_string_format(&self.fmt); + self.result.push_str(&self.comment_line_separator); + self.result.push_str(&ib.opener); match rewrite_string( - &item_block_buffer.replace("\n", " "), + &self.item_block_buffer.replace("\n", " "), &item_fmt, - max_chars.saturating_sub(ib.indent), + self.max_chars.saturating_sub(ib.indent), ) { - Some(s) => result.push_str(&join_block( + Some(s) => self.result.push_str(&Self::join_block( &s, - &format!("{}{}", &comment_line_separator, ib.line_start), + &format!("{}{}", &self.comment_line_separator, ib.line_start), + )), + None => self.result.push_str(&Self::join_block( + &self.item_block_buffer, + &self.comment_line_separator, )), - None => result.push_str(&join_block(&item_block_buffer, &comment_line_separator)), }; - item_block_buffer.clear(); - } else if let Some(ref attr) = code_block_attr { + self.item_block_buffer.clear(); + } else if self.code_block_attr.is_some() { if line.starts_with("```") { - let code_block = match attr { + let code_block = match self.code_block_attr.as_ref().unwrap() { CodeBlockAttribute::Ignore | CodeBlockAttribute::Text => { - trim_custom_comment_prefix(&code_block_buffer) + trim_custom_comment_prefix(&self.code_block_buffer) } - _ if code_block_buffer.is_empty() => String::new(), + _ if self.code_block_buffer.is_empty() => String::new(), _ => { - let mut config = config.clone(); + let mut config = self.fmt.config.clone(); config.set().format_doc_comments(false); - match ::format_code_block(&code_block_buffer, &config) { + match ::format_code_block(&self.code_block_buffer, &config) { Some(ref s) => trim_custom_comment_prefix(s), - None => trim_custom_comment_prefix(&code_block_buffer), + None => trim_custom_comment_prefix(&self.code_block_buffer), } } }; if !code_block.is_empty() { - result.push_str(&comment_line_separator); - result.push_str(&join_block(&code_block, &comment_line_separator)); + self.result.push_str(&self.comment_line_separator); + self.result + .push_str(&Self::join_block(&code_block, &self.comment_line_separator)); } - code_block_buffer.clear(); - result.push_str(&comment_line_separator); - result.push_str(line); - code_block_attr = None; + self.code_block_buffer.clear(); + self.result.push_str(&self.comment_line_separator); + self.result.push_str(line); + self.code_block_attr = None; } else { - code_block_buffer.push_str(&hide_sharp_behind_comment(line)); - code_block_buffer.push('\n'); + self.code_block_buffer + .push_str(&hide_sharp_behind_comment(line)); + self.code_block_buffer.push('\n'); } - continue; + return false; } - code_block_attr = None; - item_block = None; + self.code_block_attr = None; + self.item_block = None; if line.starts_with("```") { - code_block_attr = Some(CodeBlockAttribute::new(&line[3..])) - } else if config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { + self.code_block_attr = Some(CodeBlockAttribute::new(&line[3..])) + } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { let ib = ItemizedBlock::new(&line); - item_block_buffer.push_str(&line[ib.indent..]); - item_block_buffer.push('\n'); - item_block = Some(ib); - continue; + self.item_block_buffer.push_str(&line[ib.indent..]); + self.item_block_buffer.push('\n'); + self.item_block = Some(ib); + return false; } - if result == opener { - let force_leading_whitespace = opener == "/* " && count_newlines(orig) == 0; - if !has_leading_whitespace && !force_leading_whitespace && result.ends_with(' ') { - result.pop(); + if self.result == self.opener { + let force_leading_whitespace = &self.opener == "/* " && count_newlines(orig) == 0; + if !has_leading_whitespace && !force_leading_whitespace && self.result.ends_with(' ') { + self.result.pop(); } if line.is_empty() { - continue; + return false; } - } else if is_prev_line_multi_line && !line.is_empty() { - result.push(' ') + } else if self.is_prev_line_multi_line && !line.is_empty() { + self.result.push(' ') } else if is_last && line.is_empty() { // trailing blank lines are unwanted - if !closer.is_empty() { - result.push_str(&indent_str); + if !self.closer.is_empty() { + self.result.push_str(&self.indent_str); } - break; + return true; } else { - result.push_str(&comment_line_separator); - if !has_leading_whitespace && result.ends_with(' ') { - result.pop(); + self.result.push_str(&self.comment_line_separator); + if !has_leading_whitespace && self.result.ends_with(' ') { + self.result.pop(); } } - if config.wrap_comments() && line.len() > fmt.shape.width && !has_url(line) { - match rewrite_string(line, &fmt, max_chars) { + if self.fmt.config.wrap_comments() && line.len() > self.fmt.shape.width && !has_url(line) { + match rewrite_string(line, &self.fmt, self.max_chars) { Some(ref s) => { - is_prev_line_multi_line = s.contains('\n'); - result.push_str(s); + self.is_prev_line_multi_line = s.contains('\n'); + self.result.push_str(s); } - None if is_prev_line_multi_line => { + None if self.is_prev_line_multi_line => { // We failed to put the current `line` next to the previous `line`. // Remove the trailing space, then start rewrite on the next line. - result.pop(); - result.push_str(&comment_line_separator); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - match rewrite_string(line, &fmt, max_chars) { + self.result.pop(); + self.result.push_str(&self.comment_line_separator); + self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + match rewrite_string(line, &self.fmt, self.max_chars) { Some(ref s) => { - is_prev_line_multi_line = s.contains('\n'); - result.push_str(s); + self.is_prev_line_multi_line = s.contains('\n'); + self.result.push_str(s); } None => { - is_prev_line_multi_line = false; - result.push_str(line); + self.is_prev_line_multi_line = false; + self.result.push_str(line); } } } None => { - is_prev_line_multi_line = false; - result.push_str(line); + self.is_prev_line_multi_line = false; + self.result.push_str(line); } } - fmt.shape = if is_prev_line_multi_line { + self.fmt.shape = if self.is_prev_line_multi_line { // 1 = " " - let offset = 1 + last_line_width(&result) - line_start.len(); + let offset = 1 + last_line_width(&self.result) - self.line_start.len(); Shape { - width: max_chars.saturating_sub(offset), - indent: fmt_indent, - offset: fmt.shape.offset + offset, + width: self.max_chars.saturating_sub(offset), + indent: self.fmt_indent, + offset: self.fmt.shape.offset + offset, } } else { - Shape::legacy(max_chars, fmt_indent) + Shape::legacy(self.max_chars, self.fmt_indent) }; } else { - if line.is_empty() && result.ends_with(' ') && !is_last { + if line.is_empty() && self.result.ends_with(' ') && !is_last { // Remove space if this is an empty comment or a doc comment. - result.pop(); + self.result.pop(); } - result.push_str(line); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - is_prev_line_multi_line = false; + self.result.push_str(line); + self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + self.is_prev_line_multi_line = false; } + + false } - if !code_block_buffer.is_empty() { - // There is a code block that is not properly enclosed by backticks. - // We will leave them untouched. - result.push_str(&comment_line_separator); - result.push_str(&join_block( - &trim_custom_comment_prefix(&code_block_buffer), - &comment_line_separator, - )); - } - if !item_block_buffer.is_empty() { - // the last few lines are part of an itemized block - let ib = item_block.unwrap(); - fmt.shape = Shape::legacy(max_chars, fmt_indent); - let item_fmt = ib.create_string_format(&fmt); - result.push_str(&comment_line_separator); - result.push_str(&ib.opener); - match rewrite_string( - &item_block_buffer.replace("\n", " "), - &item_fmt, - max_chars.saturating_sub(ib.indent), - ) { - Some(s) => result.push_str(&join_block( - &s, - &format!("{}{}", &comment_line_separator, ib.line_start), - )), - None => result.push_str(&join_block(&item_block_buffer, &comment_line_separator)), - }; - } +} - result.push_str(closer); - if result.ends_with(opener) && opener.ends_with(' ') { - // Trailing space. - result.pop(); +fn rewrite_comment_inner( + orig: &str, + block_style: bool, + style: CommentStyle, + shape: Shape, + config: &Config, + is_doc_comment: bool, +) -> Option { + let mut rewriter = CommentRewrite::new(orig, block_style, shape, config); + + let line_breaks = count_newlines(orig.trim_right()); + let lines = orig + .lines() + .enumerate() + .map(|(i, mut line)| { + line = trim_right_unless_two_whitespaces(line.trim_left(), is_doc_comment); + // Drop old closer. + if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { + line = line[..(line.len() - 2)].trim_right(); + } + + line + }) + .map(|s| left_trim_comment_line(s, &style)) + .map(|(line, has_leading_whitespace)| { + if orig.starts_with("/*") && line_breaks == 0 { + ( + line.trim_left(), + has_leading_whitespace || config.normalize_comments(), + ) + } else { + (line, has_leading_whitespace || config.normalize_comments()) + } + }); + + for (i, (line, has_leading_whitespace)) in lines.enumerate() { + if rewriter.handle_line(orig, i, line, has_leading_whitespace) { + break; + } } - Some(result) + Some(rewriter.finish()) } const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; @@ -957,35 +1028,6 @@ pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) } -/// Remove trailing spaces from the specified snippet. We do not remove spaces -/// inside strings or comments. -pub fn remove_trailing_white_spaces(text: &str) -> String { - let mut buffer = String::with_capacity(text.len()); - let mut space_buffer = String::with_capacity(128); - for (char_kind, c) in CharClasses::new(text.chars()) { - match c { - '\n' => { - if char_kind == FullCodeCharKind::InString { - buffer.push_str(&space_buffer); - } - space_buffer.clear(); - buffer.push('\n'); - } - _ if c.is_whitespace() => { - space_buffer.push(c); - } - _ => { - if !space_buffer.is_empty() { - buffer.push_str(&space_buffer); - space_buffer.clear(); - } - buffer.push(c); - } - } - } - buffer -} - pub struct CharClasses where T: Iterator, @@ -1780,12 +1822,6 @@ mod test { check("\"/* abc", "abc", Some(4)); } - #[test] - fn test_remove_trailing_white_spaces() { - let s = " r#\"\n test\n \"#"; - assert_eq!(remove_trailing_white_spaces(&s), s); - } - #[test] fn test_filter_normal_code() { let s = r#" diff --git a/src/formatting.rs b/src/formatting.rs index d940c35f1c7..d2748b35736 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -528,7 +528,8 @@ impl<'a> FormatLines<'a> { && !self.is_skipped_line() && self.should_report_error(kind, &error_kind) { - self.push_err(error_kind, kind.is_comment(), self.is_string); + let is_string = self.is_string; + self.push_err(error_kind, kind.is_comment(), is_string); } } diff --git a/src/lib.rs b/src/lib.rs index a8958abab39..ff006325be0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(nll)] - #[macro_use] extern crate derive_new; extern crate atty; diff --git a/src/macros.rs b/src/macros.rs index a7a6a7fc6b7..10a037e35a3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -32,10 +32,7 @@ use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, ptr}; -use comment::{ - contains_comment, remove_trailing_white_spaces, CharClasses, FindUncommented, FullCodeCharKind, - LineClasses, -}; +use comment::{contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses}; use expr::rewrite_array; use lists::{itemize_list, write_list, ListFormatting}; use overflow; @@ -43,7 +40,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use source_map::SpanUtils; use spanned::Spanned; -use utils::{format_visibility, mk_sp, rewrite_ident, wrap_str}; +use utils::{format_visibility, mk_sp, remove_trailing_white_spaces, rewrite_ident, wrap_str}; use visitor::FmtVisitor; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; diff --git a/src/test/mod.rs b/src/test/mod.rs index 1967c74da45..aa3e729bb43 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -281,7 +281,7 @@ fn stdin_formatting_smoke_test() { session.format(input).unwrap(); assert!(session.has_no_errors()); } - //eprintln!("{:?}", ); + #[cfg(not(windows))] assert_eq!(buf, "fn main() {}\n".as_bytes()); #[cfg(windows)] diff --git a/src/utils.rs b/src/utils.rs index 3d6f1ad230d..d90bcc5931d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,7 +20,7 @@ use syntax::ast::{ use syntax::ptr; use syntax::source_map::{BytePos, Span, NO_EXPANSION}; -use comment::filter_normal_code; +use comment::{filter_normal_code, CharClasses, FullCodeCharKind}; use rewrite::RewriteContext; use shape::Shape; @@ -452,3 +452,38 @@ pub fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> _ => false, } } + +/// Remove trailing spaces from the specified snippet. We do not remove spaces +/// inside strings or comments. +pub fn remove_trailing_white_spaces(text: &str) -> String { + let mut buffer = String::with_capacity(text.len()); + let mut space_buffer = String::with_capacity(128); + for (char_kind, c) in CharClasses::new(text.chars()) { + match c { + '\n' => { + if char_kind == FullCodeCharKind::InString { + buffer.push_str(&space_buffer); + } + space_buffer.clear(); + buffer.push('\n'); + } + _ if c.is_whitespace() => { + space_buffer.push(c); + } + _ => { + if !space_buffer.is_empty() { + buffer.push_str(&space_buffer); + space_buffer.clear(); + } + buffer.push(c); + } + } + } + buffer +} + +#[test] +fn test_remove_trailing_white_spaces() { + let s = " r#\"\n test\n \"#"; + assert_eq!(remove_trailing_white_spaces(&s), s); +} diff --git a/src/visitor.rs b/src/visitor.rs index 63e2c6bdcac..a6f926736cc 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -791,9 +791,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { where F: Fn(&RewriteContext) -> Option, { - let context = self.get_context(); - let result = f(&context); - self.macro_rewrite_failure |= *context.macro_rewrite_failure.borrow(); + // FIXME borrow checker fighting - can be simplified a lot with NLL. + let (result, mrf) = { + let context = self.get_context(); + let result = f(&context); + let mrf = &context.macro_rewrite_failure.borrow(); + (result, *std::ops::Deref::deref(mrf)) + }; + + self.macro_rewrite_failure |= mrf; result } -- cgit 1.4.1-3-g733a5 From 8c996331ccce771ea0b005a97262451c7beeddd2 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 19 Oct 2018 01:11:28 +0200 Subject: fix a couple of clippy lint warnings simplify a comparison with "true" fn can_be_overflowed: remove unused lifetime fn rewrite_pairs_one_line: pass "list" by reference (it is not consumed in the function) fn span_for_token_stream: pass "token_stream" by reference since it is not consumed use tool lints for clippy suppressions --- src/lists.rs | 2 +- src/macros.rs | 6 +++--- src/overflow.rs | 2 +- src/pairs.rs | 4 ++-- src/visitor.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 87eee34daca..cd6f363e269 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -752,7 +752,7 @@ where } } -#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] +#[allow(clippy::too_many_arguments)] // Creates an iterator over a list's items with associated comments. pub fn itemize_list<'a, T, I, F1, F2, F3>( snippet_provider: &'a SnippetProvider, diff --git a/src/macros.rs b/src/macros.rs index 10a037e35a3..13b761029e2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -429,7 +429,7 @@ pub fn rewrite_macro_def( Some(v) => Some(v), // if the rewrite returned None because a macro could not be rewritten, then return the // original body - None if *context.macro_rewrite_failure.borrow() == true => { + None if *context.macro_rewrite_failure.borrow() => { Some(context.snippet(branch.body).trim().to_string()) } None => None, @@ -981,7 +981,7 @@ fn format_macro_args( ) -> Option { if !context.config.format_macro_matchers() { let token_stream: TokenStream = toks.into(); - let span = span_for_token_stream(token_stream); + let span = span_for_token_stream(&token_stream); return Some(match span { Some(span) => context.snippet(span).to_owned(), None => String::new(), @@ -991,7 +991,7 @@ fn format_macro_args( wrap_macro_args(context, &parsed_args, shape) } -fn span_for_token_stream(token_stream: TokenStream) -> Option { +fn span_for_token_stream(token_stream: &TokenStream) -> Option { token_stream.trees().next().map(|tt| tt.span()) } diff --git a/src/overflow.rs b/src/overflow.rs index 5336b86eb4b..31cd1b05466 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -690,7 +690,7 @@ fn need_block_indent(s: &str, shape: Shape) -> bool { }) } -fn can_be_overflowed<'a>(context: &RewriteContext, items: &[OverflowableItem]) -> bool { +fn can_be_overflowed(context: &RewriteContext, items: &[OverflowableItem]) -> bool { items .last() .map_or(false, |x| x.can_be_overflowed(context, items.len())) diff --git a/src/pairs.rs b/src/pairs.rs index 79ae3081f1f..360a9964f70 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -54,7 +54,7 @@ pub(crate) fn rewrite_all_pairs( // necessarily need one line per sub-expression, but we don't do anything // too funny wrt precedence. expr.flatten(true) - .and_then(|list| rewrite_pairs_multiline(list, shape, context)) + .and_then(|list| rewrite_pairs_multiline(&list, shape, context)) } // This may return a multi-line result since we allow the last expression to go @@ -105,7 +105,7 @@ fn rewrite_pairs_one_line( } fn rewrite_pairs_multiline( - list: PairList, + list: &PairList, shape: Shape, context: &RewriteContext, ) -> Option { diff --git a/src/visitor.rs b/src/visitor.rs index a6f926736cc..9ad6d3ccaa8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -573,7 +573,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.buffer.push_str(s); } - #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] + #[allow(clippy::needless_pass_by_value)] fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { if let Some(ref s) = rewrite { self.push_str(s); -- cgit 1.4.1-3-g733a5 From b25f974c0d6277de3f8f8473533f3f263ec9fbb7 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 19 Oct 2018 00:44:14 +0200 Subject: fix a few typos found via codespell. --- CHANGELOG.md | 2 +- src/comment.rs | 2 +- src/config/config_type.rs | 2 +- src/items.rs | 2 +- src/lib.rs | 4 ++-- src/missed_spans.rs | 2 +- src/patterns.rs | 2 +- src/string.rs | 4 ++-- tests/source/match.rs | 2 +- tests/source/pattern-condense-wildcards.rs | 2 +- tests/source/remove_blank_lines.rs | 2 +- tests/source/reorder-impl-items.rs | 2 +- tests/target/impl.rs | 2 +- tests/target/match.rs | 2 +- tests/target/pattern-condense-wildcards.rs | 2 +- tests/target/remove_blank_lines.rs | 2 +- tests/target/reorder-impl-items.rs | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index d868d83a5ce..87b54af8299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,7 +97,7 @@ ### Changed -- Warn when unkown configuration option is used. +- Warn when unknown configuration option is used. ### Fixed diff --git a/src/comment.rs b/src/comment.rs index 9dd7d689655..358c18e1b95 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -832,7 +832,7 @@ fn trim_custom_comment_prefix(s: &str) -> String { let left_trimmed = line.trim_left(); if left_trimmed.starts_with(RUSTFMT_CUSTOM_COMMENT_PREFIX) { let orig = left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX); - // due to comment wrapping, a line that was originaly behind `#` is split over + // due to comment wrapping, a line that was originally behind `#` is split over // multiple lines, which needs then to be prefixed with a `#` if !orig.trim_left().starts_with("# ") { Cow::from(format!("# {}", orig)) diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 419cd06436f..b7c1da36017 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -424,7 +424,7 @@ macro_rules! create_config { self.ignore.2.add_prefix(dir); } - /// Returns true if the config key was explicitely set and is the default value. + /// Returns true if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { $( if let stringify!($i) = key { diff --git a/src/items.rs b/src/items.rs index 19caafbfb82..ee4cd866ac2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1592,7 +1592,7 @@ pub fn rewrite_struct_field( for _ in 0..lhs_offset { spacing.push(' '); } - // In this extreme case we will be missing a space betweeen an attribute and a field. + // In this extreme case we will be missing a space between an attribute and a field. if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() { spacing.push(' '); } diff --git a/src/lib.rs b/src/lib.rs index ff006325be0..6f366f0b64a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,7 +117,7 @@ pub enum ErrorKind { /// An io error during reading or writing. #[fail(display = "io error: {}", _0)] IoError(io::Error), - /// Parse error occured when parsing the Input. + /// Parse error occurred when parsing the input. #[fail(display = "parse error")] ParseError, /// The user mandated a version and the current version of Rustfmt does not @@ -407,7 +407,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { // While formatting the code, ignore the config's newline style setting and always use "\n" // instead of "\r\n" for the newline characters. This is okay because the output here is // not directly outputted by rustfmt command, but used by the comment formatter's input. - // We have output-file-wide "\n" ==> "\r\n" conversion proccess after here if it's necessary. + // We have output-file-wide "\n" ==> "\r\n" conversion process after here if it's necessary. let mut config_with_unix_newline = config.clone(); config_with_unix_newline .set() diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b7d73bbf0ba..2b48673dcd4 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -20,7 +20,7 @@ use utils::{count_newlines, last_line_width, mk_sp}; use visitor::FmtVisitor; struct SnippetStatus { - /// An offset to the current line from the beginnig of the original snippet. + /// An offset to the current line from the beginning of the original snippet. line_start: usize, /// A length of trailing whitespaces on the current line. last_wspace: Option, diff --git a/src/patterns.rs b/src/patterns.rs index bd4af3f7bba..675572f4908 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -29,7 +29,7 @@ use spanned::Spanned; use types::{rewrite_path, PathContext}; use utils::{format_mutability, mk_sp, rewrite_ident}; -/// Returns true if the given pattern is short. A short pattern is defined by the following grammer: +/// Returns true if the given pattern is short. A short pattern is defined by the following grammar: /// /// [small, ntp]: /// - single token diff --git a/src/string.rs b/src/string.rs index bbf51ffcba3..561d96813b0 100644 --- a/src/string.rs +++ b/src/string.rs @@ -62,7 +62,7 @@ impl<'a> StringFormat<'a> { ) } - /// Like max_chars_with_indent but the indentation is not substracted. + /// Like max_chars_with_indent but the indentation is not subtracted. /// This allows to fit more graphemes from the string on a line when /// SnippetState::EndWithLineFeed. fn max_chars_without_indent(&self) -> Option { @@ -236,7 +236,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] .iter() .rposition(|grapheme| not_whitespace_except_line_feed(grapheme)) .unwrap_or(index); - // Take into account newlines occuring in input[0..=index], i.e., the possible next new + // Take into account newlines occurring in input[0..=index], i.e., the possible next new // line. If there is one, then text after it could be rewritten in a way that the available // space is fully used. for (i, grapheme) in input[0..=index].iter().enumerate() { diff --git a/tests/source/match.rs b/tests/source/match.rs index c5a5455cfc7..116f5f718b9 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -150,7 +150,7 @@ fn issue339() { { } - p => { // Dont collapse me + p => { // Don't collapse me } q => { } r => { diff --git a/tests/source/pattern-condense-wildcards.rs b/tests/source/pattern-condense-wildcards.rs index 244e935639a..69c3fa3cbad 100644 --- a/tests/source/pattern-condense-wildcards.rs +++ b/tests/source/pattern-condense-wildcards.rs @@ -7,6 +7,6 @@ fn main() { Tup (_) => "nah", Quad (_,_, x,_) => " also no rewrite", Quad (x, _, _, _) => "condense me pls", - Weird (x, _, _, /* dont condense before */ _, _, _) => "pls work", + Weird (x, _, _, /* don't condense before */ _, _, _) => "pls work", } } diff --git a/tests/source/remove_blank_lines.rs b/tests/source/remove_blank_lines.rs index 7466e21eed8..43733ce7636 100644 --- a/tests/source/remove_blank_lines.rs +++ b/tests/source/remove_blank_lines.rs @@ -35,7 +35,7 @@ fn bar() { // comment after statement - // comment before statment + // comment before statement let y = 2; let z = 3; diff --git a/tests/source/reorder-impl-items.rs b/tests/source/reorder-impl-items.rs index ab008b89d22..16efff55b06 100644 --- a/tests/source/reorder-impl-items.rs +++ b/tests/source/reorder-impl-items.rs @@ -1,6 +1,6 @@ // rustfmt-reorder_impl_items: true -// The ordering of the folllowing impl items should be idempotent. +// The ordering of the following impl items should be idempotent. impl<'a> Command<'a> { pub fn send_to(&self, w: &mut io::Write) -> io::Result<()> { match self { diff --git a/tests/target/impl.rs b/tests/target/impl.rs index 5895c74bcc9..f37fbcf1fcb 100644 --- a/tests/target/impl.rs +++ b/tests/target/impl.rs @@ -8,7 +8,7 @@ impl>> Handle Test where - V: Clone, // This comment is NOT removed by formating! + V: Clone, // This comment is NOT removed by formatting! { pub fn new(value: V) -> Self { Test { diff --git a/tests/target/match.rs b/tests/target/match.rs index c8a4022d2ac..b5352336b1e 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -149,7 +149,7 @@ fn issue339() { n => {} o => {} p => { - // Dont collapse me + // Don't collapse me } q => {} r => {} diff --git a/tests/target/pattern-condense-wildcards.rs b/tests/target/pattern-condense-wildcards.rs index 39f99d9e123..a85a16004ad 100644 --- a/tests/target/pattern-condense-wildcards.rs +++ b/tests/target/pattern-condense-wildcards.rs @@ -7,6 +7,6 @@ fn main() { Tup(_) => "nah", Quad(_, _, x, _) => " also no rewrite", Quad(x, ..) => "condense me pls", - Weird(x, _, _, /* dont condense before */ ..) => "pls work", + Weird(x, _, _, /* don't condense before */ ..) => "pls work", } } diff --git a/tests/target/remove_blank_lines.rs b/tests/target/remove_blank_lines.rs index 89b18e40b83..de74c81ef57 100644 --- a/tests/target/remove_blank_lines.rs +++ b/tests/target/remove_blank_lines.rs @@ -20,7 +20,7 @@ fn bar() { let x = 1; // comment after statement - // comment before statment + // comment before statement let y = 2; let z = 3; diff --git a/tests/target/reorder-impl-items.rs b/tests/target/reorder-impl-items.rs index ab008b89d22..16efff55b06 100644 --- a/tests/target/reorder-impl-items.rs +++ b/tests/target/reorder-impl-items.rs @@ -1,6 +1,6 @@ // rustfmt-reorder_impl_items: true -// The ordering of the folllowing impl items should be idempotent. +// The ordering of the following impl items should be idempotent. impl<'a> Command<'a> { pub fn send_to(&self, w: &mut io::Write) -> io::Result<()> { match self { -- cgit 1.4.1-3-g733a5 From 086c1834479b3c437b36a975d1ef54dcd9b58b2a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 22 Oct 2018 22:20:25 +0900 Subject: Use correct width when formatting type on local statement --- src/items.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 19caafbfb82..949307fefd0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -94,10 +94,16 @@ impl Rewrite for ast::Local { if let Some(ref ty) = self.ty { let separator = type_annotation_separator(context.config); - let indent = shape.indent + last_line_width(&result) + separator.len(); - // 1 = ; - let budget = shape.width.checked_sub(indent.width() + 1)?; - let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?; + let ty_shape = if pat_str.contains('\n') { + shape.with_max_width(context.config) + } else { + shape + } + .offset_left(last_line_width(&result) + separator.len())? + // 2 = ` =` + .sub_width(2)?; + + let rewrite = ty.rewrite(context, ty_shape)?; infix.push_str(separator); infix.push_str(&rewrite); -- cgit 1.4.1-3-g733a5 From e9fa99d8b86d904f2eabed14115606523ab9777d Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 23 Oct 2018 02:33:25 -0300 Subject: rustfmt: avoid duplicating the error handling for `--emit` There is no need to produce the error message again as it is already produced by the helper method that does the emit mode validation. Signed-off-by: Otavio Salvador --- src/bin/main.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 91260a199c4..7bbb237ccb1 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -496,11 +496,8 @@ impl GetOptsOptions { if options.check { return Err(format_err!("Invalid to use `--emit` and `--check`")); } - if let Ok(emit_mode) = emit_mode_from_emit_str(emit_str) { - options.emit_mode = emit_mode; - } else { - return Err(format_err!("Invalid value for `--emit`")); - } + + options.emit_mode = emit_mode_from_emit_str(emit_str)?; } if matches.opt_present("backup") { -- cgit 1.4.1-3-g733a5 From 584d871494aa715b9b6e270bcb308d347fc1edbe Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 23 Oct 2018 02:33:33 -0300 Subject: config: use 2015 as default Edition Signed-off-by: Otavio Salvador --- src/config/options.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index 27a4db70fea..38ed1e526eb 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -452,6 +452,12 @@ configuration_option_enum!{ Edition: Edition2018: 2018, } +impl Default for Edition { + fn default() -> Edition { + Edition::Edition2015 + } +} + impl Edition { pub(crate) fn to_libsyntax_pos_edition(self) -> syntax_pos::edition::Edition { match self { -- cgit 1.4.1-3-g733a5 From 2eab9714e457cd5d7715a880cb4535e453e861e7 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 23 Oct 2018 02:33:36 -0300 Subject: lib: export config::Edition so it can be used externally Signed-off-by: Otavio Salvador --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 6f366f0b64a..667e44b7324 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,8 +48,8 @@ use issues::Issue; use shape::Indent; pub use config::{ - load_config, CliOptions, Color, Config, EmitMode, FileLines, FileName, NewlineStyle, Range, - Verbosity, + load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, + Range, Verbosity, }; #[macro_use] -- cgit 1.4.1-3-g733a5 From e41fcb137cc28c2d0ec6d81eec802ab8cb0a9f61 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 23 Oct 2018 02:33:38 -0300 Subject: rustfmt: add support to specify the Rust edition as argument The new `--edition` command line argument allow the setting of the desired Rust edition to be used. Refs: #3104. Signed-off-by: Otavio Salvador --- src/bin/main.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 7bbb237ccb1..204efa19541 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -25,8 +25,8 @@ use failure::err_msg; use getopts::{Matches, Options}; use rustfmt::{ - load_config, CliOptions, Color, Config, EmitMode, ErrorKind, FileLines, FileName, Input, - Session, Verbosity, + load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines, FileName, + Input, Session, Verbosity, }; fn main() { @@ -102,6 +102,7 @@ fn make_opts() -> Options { found reverts to the input file path", "[Path for the configuration file]", ); + opts.optopt("", "edition", "Rust edition to use", "[2015|2018]"); opts.optopt( "", "color", @@ -437,6 +438,7 @@ struct GetOptsOptions { emit_mode: EmitMode, backup: bool, check: bool, + edition: Edition, color: Option, file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, @@ -500,6 +502,10 @@ impl GetOptsOptions { options.emit_mode = emit_mode_from_emit_str(emit_str)?; } + if let Some(ref edition_str) = matches.opt_str("edition") { + options.edition = edition_from_edition_str(edition_str)?; + } + if matches.opt_present("backup") { options.backup = true; } @@ -553,6 +559,7 @@ impl CliOptions for GetOptsOptions { if let Some(error_on_unformatted) = self.error_on_unformatted { config.set().error_on_unformatted(error_on_unformatted); } + config.set().edition(self.edition); if self.check { config.set().emit_mode(EmitMode::Diff); } else { @@ -571,6 +578,14 @@ impl CliOptions for GetOptsOptions { } } +fn edition_from_edition_str(edition_str: &str) -> Result { + match edition_str { + "2015" => Ok(Edition::Edition2015), + "2018" => Ok(Edition::Edition2018), + _ => Err(format_err!("Invalid value for `--edition`")), + } +} + fn emit_mode_from_emit_str(emit_str: &str) -> Result { match emit_str { "files" => Ok(EmitMode::Files), -- cgit 1.4.1-3-g733a5 From 799005f6ae66edb4f9745243ee78c677495821d3 Mon Sep 17 00:00:00 2001 From: JoshBrudnak Date: Mon, 22 Oct 2018 18:49:10 -0400 Subject: Treat crates non-alphabetically Fixes: #3118 --- src/imports.rs | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index e7817c175b4..deef4d096c9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -97,6 +97,7 @@ pub enum UseSegment { Ident(String, Option), Slf(Option), Super(Option), + Crate(Option), Glob, List(Vec), } @@ -138,6 +139,7 @@ impl UseSegment { UseSegment::Ident(ref s, _) => UseSegment::Ident(s.clone(), None), UseSegment::Slf(_) => UseSegment::Slf(None), UseSegment::Super(_) => UseSegment::Super(None), + UseSegment::Crate(_) => UseSegment::Crate(None), _ => self.clone(), } } @@ -154,6 +156,7 @@ impl UseSegment { Some(match name { "self" => UseSegment::Slf(None), "super" => UseSegment::Super(None), + "crate" => UseSegment::Crate(None), _ => { let mod_sep = if modsep { "::" } else { "" }; UseSegment::Ident(format!("{}{}", mod_sep, name), None) @@ -207,6 +210,7 @@ impl fmt::Display for UseSegment { UseSegment::Ident(ref s, _) => write!(f, "{}", s), UseSegment::Slf(..) => write!(f, "self"), UseSegment::Super(..) => write!(f, "super"), + UseSegment::Crate(..) => write!(f, "crate"), UseSegment::List(ref list) => { write!(f, "{{")?; for (i, item) in list.iter().enumerate() { @@ -377,6 +381,7 @@ impl UseTree { let segment = match name.as_ref() { "self" => UseSegment::Slf(alias), "super" => UseSegment::Super(alias), + "crate" => UseSegment::Crate(alias), _ => UseSegment::Ident(name, alias), }; @@ -617,7 +622,9 @@ impl Ord for UseSegment { } match (self, other) { - (&Slf(ref a), &Slf(ref b)) | (&Super(ref a), &Super(ref b)) => a.cmp(b), + (&Slf(ref a), &Slf(ref b)) + | (&Super(ref a), &Super(ref b)) + | (&Crate(ref a), &Crate(ref b)) => a.cmp(b), (&Glob, &Glob) => Ordering::Equal, (&Ident(ref ia, ref aa), &Ident(ref ib, ref ab)) => { // snake_case < CamelCase < UPPER_SNAKE_CASE @@ -659,6 +666,8 @@ impl Ord for UseSegment { (_, &Slf(_)) => Ordering::Greater, (&Super(_), _) => Ordering::Less, (_, &Super(_)) => Ordering::Greater, + (&Crate(_), _) => Ordering::Less, + (_, &Crate(_)) => Ordering::Greater, (&Ident(..), _) => Ordering::Less, (_, &Ident(..)) => Ordering::Greater, (&Glob, _) => Ordering::Less, @@ -768,6 +777,8 @@ impl Rewrite for UseSegment { UseSegment::Slf(None) => "self".to_owned(), UseSegment::Super(Some(ref rename)) => format!("super as {}", rename), UseSegment::Super(None) => "super".to_owned(), + UseSegment::Crate(Some(ref rename)) => format!("crate as {}", rename), + UseSegment::Crate(None) => "crate".to_owned(), UseSegment::Glob => "*".to_owned(), UseSegment::List(ref use_tree_list) => rewrite_nested_use_tree( context, @@ -830,18 +841,28 @@ mod test { if !buf.is_empty() { let mut alias = None; swap(alias_buf, &mut alias); - if buf == "self" { - result.push(UseSegment::Slf(alias)); - *buf = String::new(); - *alias_buf = None; - } else if buf == "super" { - result.push(UseSegment::Super(alias)); - *buf = String::new(); - *alias_buf = None; - } else { - let mut name = String::new(); - swap(buf, &mut name); - result.push(UseSegment::Ident(name, alias)); + + match buf.as_ref() { + "self" => { + result.push(UseSegment::Slf(alias)); + *buf = String::new(); + *alias_buf = None; + } + "super" => { + result.push(UseSegment::Super(alias)); + *buf = String::new(); + *alias_buf = None; + } + "crate" => { + result.push(UseSegment::Crate(alias)); + *buf = String::new(); + *alias_buf = None; + } + _ => { + let mut name = String::new(); + swap(buf, &mut name); + result.push(UseSegment::Ident(name, alias)); + } } } } -- cgit 1.4.1-3-g733a5 From 9c75a15f4c81a6e412844f85d6d24541a88b49e7 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 18 Oct 2018 22:58:45 +0200 Subject: Fix handling of code that is annotated with rustfmt::skip. A rustfmt::skip'ed block is indented although original lines are returned. In order to resolve this, the leading whitespaces are trimmed on each line while retaining the layout; this leaves the skipped code to be indented as necessary by the caller. --- src/comment.rs | 51 +++++----------------------------------------- src/utils.rs | 41 ++++++++++++++++++++++++++++++++++++- src/visitor.rs | 15 ++++++++++---- tests/source/issue-3105.rs | 30 +++++++++++++++++++++++++++ tests/target/issue-3105.rs | 30 +++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 51 deletions(-) create mode 100644 tests/source/issue-3105.rs create mode 100644 tests/target/issue-3105.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 358c18e1b95..7e06d9a8d60 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -19,7 +19,7 @@ use config::Config; use rewrite::RewriteContext; use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; -use utils::{count_newlines, first_line_width, last_line_width}; +use utils::{count_newlines, first_line_width, last_line_width, trim_left_preserve_layout}; use {ErrorKind, FormattingError}; fn is_custom_comment(comment: &str) -> bool { @@ -332,12 +332,12 @@ fn identify_comment( let (first_group, rest) = orig.split_at(first_group_ending); let rewritten_first_group = if !config.normalize_comments() && has_bare_lines && style.is_block_comment() { - light_rewrite_block_comment_with_bare_lines(first_group, shape, config)? + trim_left_preserve_layout(first_group, &shape.indent, config) } else if !config.normalize_comments() && !config.wrap_comments() && !config.format_doc_comments() { - light_rewrite_comment(first_group, shape.indent, config, is_doc_comment)? + light_rewrite_comment(first_group, shape.indent, config, is_doc_comment) } else { rewrite_comment_inner( first_group, @@ -370,47 +370,6 @@ fn identify_comment( } } -/// Trims a minimum of leading whitespaces so that the content layout is kept and aligns to indent. -fn light_rewrite_block_comment_with_bare_lines( - orig: &str, - shape: Shape, - config: &Config, -) -> Option { - let prefix_whitespace_min = orig - .lines() - // skip the line with the starting sigil since the leading whitespace is removed - // otherwise, the minimum would always be zero - .skip(1) - .filter(|line| !line.is_empty()) - .map(|line| { - let mut width = 0; - for c in line.chars() { - match c { - ' ' => width += 1, - '\t' => width += config.tab_spaces(), - _ => break, - } - } - width - }) - .min()?; - - let indent_str = shape.indent.to_string(config); - let mut lines = orig.lines(); - let first_line = lines.next()?; - let rest = lines - .map(|line| { - if line.is_empty() { - line - } else { - &line[prefix_whitespace_min..] - } - }) - .collect::>() - .join(&format!("\n{}", indent_str)); - Some(format!("{}\n{}{}", first_line, indent_str, rest)) -} - /// Attributes for code blocks in rustdoc. /// See https://doc.rust-lang.org/rustdoc/print.html#attributes enum CodeBlockAttribute { @@ -912,7 +871,7 @@ fn light_rewrite_comment( offset: Indent, config: &Config, is_doc_comment: bool, -) -> Option { +) -> String { let lines: Vec<&str> = orig .lines() .map(|l| { @@ -933,7 +892,7 @@ fn light_rewrite_comment( trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) }) .collect(); - Some(lines.join(&format!("\n{}", offset.to_string(config)))) + lines.join(&format!("\n{}", offset.to_string(config))) } /// Trims comment characters and possibly a single space from the left of a string. diff --git a/src/utils.rs b/src/utils.rs index d90bcc5931d..a2d15b820eb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -21,8 +21,9 @@ use syntax::ptr; use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use comment::{filter_normal_code, CharClasses, FullCodeCharKind}; +use config::Config; use rewrite::RewriteContext; -use shape::Shape; +use shape::{Indent, Shape}; pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; @@ -482,6 +483,44 @@ pub fn remove_trailing_white_spaces(text: &str) -> String { buffer } +/// Trims a minimum of leading whitespaces so that the content layout is kept and aligns to indent. +pub fn trim_left_preserve_layout(orig: &str, indent: &Indent, config: &Config) -> String { + let prefix_whitespace_min = orig + .lines() + // skip the line with the starting sigil since the leading whitespace is removed + // otherwise, the minimum would always be zero + .skip(1) + .filter(|line| !line.is_empty()) + .map(|line| { + let mut width = 0; + for c in line.chars() { + match c { + ' ' => width += 1, + '\t' => width += config.tab_spaces(), + _ => break, + } + } + width + }) + .min() + .unwrap_or(0); + + let indent_str = indent.to_string(config); + let mut lines = orig.lines(); + let first_line = lines.next().unwrap(); + let rest = lines + .map(|line| { + if line.is_empty() { + String::from("\n") + } else { + format!("\n{}{}", indent_str, &line[prefix_whitespace_min..]) + } + }) + .collect::>() + .concat(); + format!("{}{}", first_line, rest) +} + #[test] fn test_remove_trailing_white_spaces() { let s = " r#\"\n test\n \"#"; diff --git a/src/visitor.rs b/src/visitor.rs index 9ad6d3ccaa8..036c4990a58 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -29,7 +29,7 @@ use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, - rewrite_ident, DEPR_SKIP_ANNOTATION, + rewrite_ident, trim_left_preserve_layout, DEPR_SKIP_ANNOTATION, }; use {ErrorKind, FormatReport, FormattingError}; @@ -574,9 +574,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } #[allow(clippy::needless_pass_by_value)] - fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { + fn push_rewrite_inner(&mut self, span: Span, rewrite: Option, is_skipped: bool) { if let Some(ref s) = rewrite { self.push_str(s); + } else if is_skipped { + // in case the code block (e.g., inside a macro or a doc) is skipped a minimum of + // leading whitespaces is trimmed so that the code layout is kept but allows it to + // be indented as necessary + let snippet = + trim_left_preserve_layout(self.snippet(span), &self.block_indent, self.config); + self.push_str(&snippet); } else { let snippet = self.snippet(span); self.push_str(snippet); @@ -586,13 +593,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo()); - self.push_rewrite_inner(span, rewrite); + self.push_rewrite_inner(span, rewrite, false); } pub fn push_skipped_with_span(&mut self, span: Span) { self.format_missing_with_indent(source!(self, span).lo()); let lo = self.line_number + 1; - self.push_rewrite_inner(span, None); + self.push_rewrite_inner(span, None, true); let hi = self.line_number + 1; self.skipped_range.push((lo, hi)); } diff --git a/tests/source/issue-3105.rs b/tests/source/issue-3105.rs new file mode 100644 index 00000000000..f6331cd6a02 --- /dev/null +++ b/tests/source/issue-3105.rs @@ -0,0 +1,30 @@ +// rustfmt-wrap_comments: true + +/// ``` +/// pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { +/// let imm8 = (imm8 & 0xFF) as u8; +/// let a = a.as_i16x16(); +/// macro_rules! shuffle_done { +/// ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { +/// #[cfg_attr(rustfmt, rustfmt_skip)] +/// simd_shuffle16(a, a, [ +/// 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, +/// 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 +/// ]); +/// }; +/// } +/// } +/// ``` +pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { + let imm8 = (imm8 & 0xFF) as u8; + let a = a.as_i16x16(); + macro_rules! shuffle_done { + ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { + #[cfg_attr(rustfmt, rustfmt_skip)] + simd_shuffle16(a, a, [ + 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, + 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 + ]); + }; + } +} diff --git a/tests/target/issue-3105.rs b/tests/target/issue-3105.rs new file mode 100644 index 00000000000..2b9f5ce91df --- /dev/null +++ b/tests/target/issue-3105.rs @@ -0,0 +1,30 @@ +// rustfmt-wrap_comments: true + +/// ``` +/// pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { +/// let imm8 = (imm8 & 0xFF) as u8; +/// let a = a.as_i16x16(); +/// macro_rules! shuffle_done { +/// ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { +/// #[cfg_attr(rustfmt, rustfmt_skip)] +/// simd_shuffle16(a, a, [ +/// 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, +/// 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 +/// ]); +/// }; +/// } +/// } +/// ``` +pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { + let imm8 = (imm8 & 0xFF) as u8; + let a = a.as_i16x16(); + macro_rules! shuffle_done { + ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { + #[cfg_attr(rustfmt, rustfmt_skip)] + simd_shuffle16(a, a, [ + 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, + 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 + ]); + }; + } +} -- cgit 1.4.1-3-g733a5 From 2f5d864c086df35a57b65400b2e0f3f90e52d1ea Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 24 Oct 2018 01:24:56 +0200 Subject: keep track of lines which formatting was disabled in order to prevent indentation which would cause code right-shifting --- src/comment.rs | 2 +- src/formatting.rs | 2 ++ src/lib.rs | 83 ++++++++++++++++++++++++++++++++++++---------- src/macros.rs | 16 ++++++--- src/visitor.rs | 47 ++++++++++++++------------ tests/source/issue-3105.rs | 30 ----------------- tests/target/issue-3105.rs | 28 +++++++++++++--- 7 files changed, 129 insertions(+), 79 deletions(-) delete mode 100644 tests/source/issue-3105.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 7e06d9a8d60..e76bb331856 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -620,7 +620,7 @@ impl<'a> CommentRewrite<'a> { let mut config = self.fmt.config.clone(); config.set().format_doc_comments(false); match ::format_code_block(&self.code_block_buffer, &config) { - Some(ref s) => trim_custom_comment_prefix(s), + Some(ref s) => trim_custom_comment_prefix(&s.snippet), None => trim_custom_comment_prefix(&self.code_block_buffer), } } diff --git a/src/formatting.rs b/src/formatting.rs index d2748b35736..039276ba6e8 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -173,6 +173,8 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { if visitor.macro_rewrite_failure { self.report.add_macro_format_failure(); } + self.report + .add_non_formatted_ranges(visitor.skipped_range.clone()); self.handler .handle_formatted_file(path, visitor.buffer.to_owned(), &mut self.report) diff --git a/src/lib.rs b/src/lib.rs index 6f366f0b64a..2dcbf823d55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,6 +144,34 @@ impl From for ErrorKind { } } +/// Result of formatting a snippet of code along with ranges of lines that didn't get formatted, +/// i.e., that got returned as they were originally. +#[derive(Debug)] +struct FormattedSnippet { + snippet: String, + non_formatted_ranges: Vec<(usize, usize)>, +} + +impl FormattedSnippet { + /// In case the snippet needed to be wrapped in a function, this shifts down the ranges of + /// non-formatted code. + fn unwrap_code_block(&mut self) { + self.non_formatted_ranges + .iter_mut() + .for_each(|(low, high)| { + *low -= 1; + *high -= 1; + }); + } + + /// Returns true if the line n did not get formatted. + fn is_line_non_formatted(&self, n: usize) -> bool { + self.non_formatted_ranges + .iter() + .any(|(low, high)| *low <= n && n <= *high) + } +} + /// Reports on any issues that occurred during a run of Rustfmt. /// /// Can be reported to the user via its `Display` implementation of `print_fancy`. @@ -151,15 +179,21 @@ impl From for ErrorKind { pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. internal: Rc>, + non_formatted_ranges: Vec<(usize, usize)>, } impl FormatReport { fn new() -> FormatReport { FormatReport { internal: Rc::new(RefCell::new((HashMap::new(), ReportedErrors::default()))), + non_formatted_ranges: Vec::new(), } } + fn add_non_formatted_ranges(&mut self, mut ranges: Vec<(usize, usize)>) { + self.non_formatted_ranges.append(&mut ranges); + } + fn append(&self, f: FileName, mut v: Vec) { self.track_errors(&v); self.internal @@ -349,37 +383,44 @@ impl fmt::Display for FormatReport { /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. -fn format_snippet(snippet: &str, config: &Config) -> Option { +fn format_snippet(snippet: &str, config: &Config) -> Option { let mut config = config.clone(); - let out = panic::catch_unwind(|| { + panic::catch_unwind(|| { let mut out: Vec = Vec::with_capacity(snippet.len() * 2); config.set().emit_mode(config::EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); config.set().hide_parse_errors(true); - let formatting_error = { + + let (formatting_error, result) = { let input = Input::Text(snippet.into()); let mut session = Session::new(config, Some(&mut out)); let result = session.format(input); - session.errors.has_macro_format_failure - || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() - || result.is_err() + ( + session.errors.has_macro_format_failure + || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() + || result.is_err(), + result, + ) }; if formatting_error { None } else { - Some(out) + String::from_utf8(out).ok().map(|snippet| FormattedSnippet { + snippet, + non_formatted_ranges: result.unwrap().non_formatted_ranges, + }) } }) - .ok()??; // The first try operator handles the error from catch_unwind, - // whereas the second one handles None from the closure. - String::from_utf8(out).ok() + // Discard panics encountered while formatting the snippet + // The ? operator is needed to remove the extra Option + .ok()? } /// Format the given code block. Mainly targeted for code block in comment. /// The code block may be incomplete (i.e. parser may be unable to parse it). /// To avoid panic in parser, we wrap the code block with a dummy function. /// The returned code block does *not* end with newline. -fn format_code_block(code_snippet: &str, config: &Config) -> Option { +fn format_code_block(code_snippet: &str, config: &Config) -> Option { const FN_MAIN_PREFIX: &str = "fn main() {\n"; fn enclose_in_main_block(s: &str, config: &Config) -> String { @@ -412,13 +453,18 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { config_with_unix_newline .set() .newline_style(NewlineStyle::Unix); - let formatted = format_snippet(&snippet, &config_with_unix_newline)?; + let mut formatted = format_snippet(&snippet, &config_with_unix_newline)?; + // Remove wrapping main block + formatted.unwrap_code_block(); // Trim "fn main() {" on the first line and "}" on the last line, // then unindent the whole code block. - let block_len = formatted.rfind('}').unwrap_or(formatted.len()); + let block_len = formatted + .snippet + .rfind('}') + .unwrap_or(formatted.snippet.len()); let mut is_indented = true; - for (kind, ref line) in LineClasses::new(&formatted[FN_MAIN_PREFIX.len()..block_len]) { + for (kind, ref line) in LineClasses::new(&formatted.snippet[FN_MAIN_PREFIX.len()..block_len]) { if !is_first { result.push('\n'); } else { @@ -451,7 +497,10 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { result.push_str(trimmed_line); is_indented = !kind.is_string() || line.ends_with('\\'); } - Some(result) + Some(FormattedSnippet { + snippet: result, + non_formatted_ranges: formatted.non_formatted_ranges, + }) } /// A session is a run of rustfmt across a single or multiple inputs. @@ -571,10 +620,10 @@ mod unit_tests { fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool where - F: Fn(&str, &Config) -> Option, + F: Fn(&str, &Config) -> Option, { let output = formatter(input, &Config::default()); - output.is_some() && output.unwrap() == expected + output.is_some() && output.unwrap().snippet == expected } #[test] diff --git a/src/macros.rs b/src/macros.rs index 13b761029e2..d378bb8ffb1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1323,7 +1323,7 @@ impl MacroBranch { config.set().max_width(new_width); // First try to format as items, then as statements. - let new_body = match ::format_snippet(&body_str, &config) { + let new_body_snippet = match ::format_snippet(&body_str, &config) { Some(new_body) => new_body, None => { let new_width = new_width + config.tab_spaces(); @@ -1334,15 +1334,23 @@ impl MacroBranch { } } }; - let new_body = wrap_str(new_body, config.max_width(), shape)?; + let new_body = wrap_str( + new_body_snippet.snippet.to_string(), + config.max_width(), + shape, + )?; // Indent the body since it is in a block. let indent_str = body_indent.to_string(&config); let mut new_body = LineClasses::new(new_body.trim_right()) + .enumerate() .fold( (String::new(), true), - |(mut s, need_indent), (kind, ref l)| { - if !l.is_empty() && need_indent { + |(mut s, need_indent), (i, (kind, ref l))| { + if !l.is_empty() + && need_indent + && !new_body_snippet.is_line_non_formatted(i + 1) + { s += &indent_str; } (s + l + "\n", !kind.is_string() || l.ends_with('\\')) diff --git a/src/visitor.rs b/src/visitor.rs index 036c4990a58..b286465b276 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -29,7 +29,7 @@ use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, - rewrite_ident, trim_left_preserve_layout, DEPR_SKIP_ANNOTATION, + rewrite_ident, DEPR_SKIP_ANNOTATION, }; use {ErrorKind, FormatReport, FormattingError}; @@ -71,6 +71,8 @@ pub struct FmtVisitor<'a> { pub is_if_else_block: bool, pub snippet_provider: &'a SnippetProvider<'a>, pub line_number: usize, + /// List of 1-based line ranges which were annotated with skip + /// Both bounds are inclusifs. pub skipped_range: Vec<(usize, usize)>, pub macro_rewrite_failure: bool, pub(crate) report: FormatReport, @@ -109,8 +111,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.format_missing(stmt.span.hi()); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - if contains_skip(get_attrs_from_stmt(stmt)) { - self.push_skipped_with_span(stmt.span()); + let attrs = get_attrs_from_stmt(stmt); + if contains_skip(attrs) { + self.push_skipped_with_span(attrs, stmt.span()); } else { let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); @@ -120,7 +123,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, ref attrs) = **mac; if self.visit_attrs(attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(stmt.span()); + self.push_skipped_with_span(attrs, stmt.span()); } else { self.visit_mac(mac, None, MacroPosition::Statement); } @@ -328,14 +331,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // For use items, skip rewriting attributes. Just check for a skip attribute. ast::ItemKind::Use(..) => { if contains_skip(attrs) { - self.push_skipped_with_span(item.span()); + self.push_skipped_with_span(attrs.as_slice(), item.span()); return; } } // Module is inline, in this case we treat it like any other item. _ if !is_mod_decl(item) => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); + self.push_skipped_with_span(item.attrs.as_slice(), item.span()); return; } } @@ -354,7 +357,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } _ => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.span()); + self.push_skipped_with_span(item.attrs.as_slice(), item.span()); return; } } @@ -471,7 +474,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, ti.span); if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ti.span()); + self.push_skipped_with_span(ti.attrs.as_slice(), ti.span()); return; } @@ -515,7 +518,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, ii.span); if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ii.span()); + self.push_skipped_with_span(ii.attrs.as_slice(), ii.span()); return; } @@ -574,16 +577,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } #[allow(clippy::needless_pass_by_value)] - fn push_rewrite_inner(&mut self, span: Span, rewrite: Option, is_skipped: bool) { + fn push_rewrite_inner(&mut self, span: Span, rewrite: Option) { if let Some(ref s) = rewrite { self.push_str(s); - } else if is_skipped { - // in case the code block (e.g., inside a macro or a doc) is skipped a minimum of - // leading whitespaces is trimmed so that the code layout is kept but allows it to - // be indented as necessary - let snippet = - trim_left_preserve_layout(self.snippet(span), &self.block_indent, self.config); - self.push_str(&snippet); } else { let snippet = self.snippet(span); self.push_str(snippet); @@ -593,13 +589,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo()); - self.push_rewrite_inner(span, rewrite, false); + self.push_rewrite_inner(span, rewrite); } - pub fn push_skipped_with_span(&mut self, span: Span) { - self.format_missing_with_indent(source!(self, span).lo()); - let lo = self.line_number + 1; - self.push_rewrite_inner(span, None, true); + pub fn push_skipped_with_span(&mut self, attrs: &[ast::Attribute], item_span: Span) { + self.format_missing_with_indent(source!(self, item_span).lo()); + // do not take into account the lines with attributes as part of the skipped range + let attrs_end = attrs + .iter() + .map(|attr| self.source_map.lookup_char_pos(attr.span().hi()).line) + .max() + .unwrap_or(1); + // Add 1 to get the line past the last attribute + let lo = attrs_end + 1; + self.push_rewrite_inner(item_span, None); let hi = self.line_number + 1; self.skipped_range.push((lo, hi)); } diff --git a/tests/source/issue-3105.rs b/tests/source/issue-3105.rs deleted file mode 100644 index f6331cd6a02..00000000000 --- a/tests/source/issue-3105.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-wrap_comments: true - -/// ``` -/// pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { -/// let imm8 = (imm8 & 0xFF) as u8; -/// let a = a.as_i16x16(); -/// macro_rules! shuffle_done { -/// ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { -/// #[cfg_attr(rustfmt, rustfmt_skip)] -/// simd_shuffle16(a, a, [ -/// 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, -/// 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 -/// ]); -/// }; -/// } -/// } -/// ``` -pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { - let imm8 = (imm8 & 0xFF) as u8; - let a = a.as_i16x16(); - macro_rules! shuffle_done { - ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { - #[cfg_attr(rustfmt, rustfmt_skip)] - simd_shuffle16(a, a, [ - 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, - 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 - ]); - }; - } -} diff --git a/tests/target/issue-3105.rs b/tests/target/issue-3105.rs index 2b9f5ce91df..4f1123805b8 100644 --- a/tests/target/issue-3105.rs +++ b/tests/target/issue-3105.rs @@ -1,5 +1,8 @@ // rustfmt-wrap_comments: true +/// Although the indentation of the skipped method is off, it shouldn't be +/// changed. +/// /// ``` /// pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { /// let imm8 = (imm8 & 0xFF) as u8; @@ -7,10 +10,10 @@ /// macro_rules! shuffle_done { /// ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { /// #[cfg_attr(rustfmt, rustfmt_skip)] -/// simd_shuffle16(a, a, [ -/// 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, -/// 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 -/// ]); +/// simd_shuffle16(a, a, [ +/// 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, +/// 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 +/// ]); /// }; /// } /// } @@ -21,7 +24,22 @@ pub unsafe fn _mm256_shufflehi_epi16(a: __m256i, imm8: i32) -> __m256i { macro_rules! shuffle_done { ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { #[cfg_attr(rustfmt, rustfmt_skip)] - simd_shuffle16(a, a, [ + simd_shuffle16(a, a, [ + 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, + 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 + ]); + }; + } +} + +/// The skipped method shouldn't right-shift +pub unsafe fn _mm256_shufflehi_epi32(a: __m256i, imm8: i32) -> __m256i { + let imm8 = (imm8 & 0xFF) as u8; + let a = a.as_i16x16(); + macro_rules! shuffle_done { + ($x01:expr, $x23:expr, $x45:expr, $x67:expr) => { + #[cfg_attr(rustfmt, rustfmt_skip)] + simd_shuffle32(a, a, [ 0, 1, 2, 3, 4+$x01, 4+$x23, 4+$x45, 4+$x67, 8, 9, 10, 11, 12+$x01, 12+$x23, 12+$x45, 12+$x67 ]); -- cgit 1.4.1-3-g733a5 From de0b661bfa7646b1c871b3b10de2672cd911e6d0 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Tue, 23 Oct 2018 02:33:46 -0300 Subject: cargo-fmt: Take into account the edition for each target When formatting the crate, with `cargo fmt`, it parses each target with the specific Rust edition. Fixes: #3104. Signed-off-by: Otavio Salvador --- src/cargo-fmt/main.rs | 108 +++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index eee102b6bf8..45d00251828 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -17,14 +17,14 @@ extern crate cargo_metadata; extern crate getopts; extern crate serde_json as json; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::env; use std::fs; use std::hash::{Hash, Hasher}; use std::io::{self, Write}; use std::iter::FromIterator; use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus}; +use std::process::Command; use std::str; use getopts::{Matches, Options}; @@ -122,30 +122,21 @@ pub enum Verbosity { Quiet, } -fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { +fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { match status { Err(e) => { print_usage_to_stderr(opts, &e.to_string()); FAILURE } - Ok(status) => { - if status.success() { - SUCCESS - } else { - status.code().unwrap_or(FAILURE) - } - } + Ok(status) => status, } } -fn get_version(verbosity: Verbosity) -> Result { - run_rustfmt(&[], &[String::from("--version")], verbosity) +fn get_version(verbosity: Verbosity) -> Result { + run_rustfmt(&HashSet::new(), &[String::from("--version")], verbosity) } -fn format_crate( - verbosity: Verbosity, - strategy: &CargoFmtStrategy, -) -> Result { +fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result { let rustfmt_args = get_fmt_args(); let targets = if rustfmt_args .iter() @@ -157,17 +148,7 @@ fn format_crate( }; // Currently only bin and lib files get formatted - let files: Vec<_> = targets - .into_iter() - .inspect(|t| { - if verbosity == Verbosity::Verbose { - println!("[{}] {:?}", t.kind, t.path) - } - }) - .map(|t| t.path) - .collect(); - - run_rustfmt(&files, &rustfmt_args, verbosity) + run_rustfmt(&targets, &rustfmt_args, verbosity) } fn get_fmt_args() -> Vec { @@ -182,6 +163,8 @@ pub struct Target { path: PathBuf, /// A kind of target (e.g. lib, bin, example, ...). kind: String, + /// Rust edition for this target. + edition: String, } impl Target { @@ -192,6 +175,7 @@ impl Target { Target { path: canonicalized, kind: target.kind[0].clone(), + edition: target.edition.clone(), } } } @@ -334,41 +318,55 @@ fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet, fmt_args: &[String], verbosity: Verbosity, -) -> Result { - let stdout = if verbosity == Verbosity::Quiet { - std::process::Stdio::null() - } else { - std::process::Stdio::inherit() - }; +) -> Result { + let by_edition: HashMap<_, _> = targets + .iter() + .inspect(|t| { + if verbosity == Verbosity::Verbose { + println!("[{} ({})] {:?}", t.kind, t.edition, t.path) + } + }) + .map(|t| (&t.edition, vec![&t.path])) + .collect(); - if verbosity == Verbosity::Verbose { - print!("rustfmt"); - for a in fmt_args { - print!(" {}", a); + for (edition, files) in by_edition { + let stdout = if verbosity == Verbosity::Quiet { + std::process::Stdio::null() + } else { + std::process::Stdio::inherit() + }; + + if verbosity == Verbosity::Verbose { + print!("rustfmt"); + fmt_args.iter().for_each(|f| print!(" {}", f)); + files.iter().for_each(|f| print!(" {}", f.display())); + println!(); } - for f in files { - print!(" {}", f.display()); + + let mut command = Command::new("rustfmt") + .stdout(stdout) + .args(files) + .args(&["--edition", edition]) + .args(fmt_args) + .spawn() + .map_err(|e| match e.kind() { + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), + _ => e, + })?; + + let status = command.wait()?; + if !status.success() { + return Ok(status.code().unwrap_or(FAILURE)); } - println!(); } - let mut command = Command::new("rustfmt") - .stdout(stdout) - .args(files) - .args(fmt_args) - .spawn() - .map_err(|e| match e.kind() { - io::ErrorKind::NotFound => io::Error::new( - io::ErrorKind::Other, - "Could not run rustfmt, please make sure it is in your PATH.", - ), - _ => e, - })?; - - command.wait() + Ok(SUCCESS) } fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { -- cgit 1.4.1-3-g733a5 From 9c3ae2d9519fca1f66cc1ba135d05a6ae046faa8 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 24 Oct 2018 22:31:42 -0300 Subject: Stabilize `edition` configuration option Refs: #3104. Signed-off-by: Otavio Salvador --- Configurations.md | 2 +- src/config/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index f23506d5fe8..3eb8cbd780f 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2275,7 +2275,7 @@ Specifies which edition is used by the parser. - **Default value**: `2015` - **Possible values**: `2015`, `2018` -- **Stable**: No +- **Stable**: Yes ### Example diff --git a/src/config/mod.rs b/src/config/mod.rs index 98754eb0b60..c3b998d0211 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -110,7 +110,7 @@ create_config! { "Maximum number of blank lines which can be put between items"; blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items"; - edition: Edition, Edition::Edition2015, false, "The edition of the parser (RFC 2052)"; + edition: Edition, Edition::Edition2015, true, "The edition of the parser (RFC 2052)"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; -- cgit 1.4.1-3-g733a5 From 7093bbe2ff9d5df41d10493bc96422b2f56417a7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 26 Oct 2018 16:36:11 +0900 Subject: Simplify handling parens on generic bound trait --- src/types.rs | 67 +++++++++++------------------------------------------------- 1 file changed, 12 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index d5010314b57..20828429cb1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -473,7 +473,7 @@ fn rewrite_bounded_lifetime( "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, true, false)? + join_bounds(context, shape.sub_width(overhead)?, bounds, true)? ); Some(result) } @@ -489,13 +489,15 @@ impl Rewrite for ast::GenericBound { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { match *self { ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => { - match trait_bound_modifier { + let snippet = context.snippet(self.span()); + let has_paren = snippet.starts_with("(") && snippet.ends_with(")"); + let rewrite = match trait_bound_modifier { ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape), - ast::TraitBoundModifier::Maybe => { - let rw = poly_trait_ref.rewrite(context, shape.offset_left(1)?)?; - Some(format!("?{}", rw)) - } - } + ast::TraitBoundModifier::Maybe => poly_trait_ref + .rewrite(context, shape.offset_left(1)?) + .map(|s| format!("?{}", s)), + }; + rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), } @@ -508,14 +510,7 @@ impl Rewrite for ast::GenericBounds { return Some(String::new()); } - let span = mk_sp(self.get(0)?.span().lo(), self.last()?.span().hi()); - let has_paren = context.snippet(span).starts_with('('); - let bounds_shape = if has_paren { - shape.offset_left(1)?.sub_width(1)? - } else { - shape - }; - join_bounds(context, bounds_shape, self, true, has_paren) + join_bounds(context, shape, self, true) } } @@ -751,7 +746,6 @@ fn join_bounds( shape: Shape, items: &[ast::GenericBound], need_indent: bool, - has_paren: bool, ) -> Option { debug_assert!(!items.is_empty()); @@ -762,36 +756,9 @@ fn join_bounds( }; let type_strs = items .iter() - .map(|item| { - item.rewrite( - context, - if has_paren { - shape.sub_width(1)?.offset_left(1)? - } else { - shape - }, - ) - }) + .map(|item| item.rewrite(context, shape)) .collect::>>()?; - let mut result = String::with_capacity(128); - let mut closing_paren = has_paren; - if has_paren { - result.push('('); - } - result.push_str(&type_strs[0]); - if has_paren && type_strs.len() == 1 { - result.push(')'); - } - for (i, type_str) in type_strs[1..].iter().enumerate() { - if closing_paren { - if let ast::GenericBound::Outlives(..) = items[i + 1] { - result.push(')'); - closing_paren = false; - } - } - result.push_str(joiner); - result.push_str(type_str); - } + let result = type_strs.join(joiner); if items.len() <= 1 || (!result.contains('\n') && result.len() <= shape.width) { return Some(result); } @@ -814,20 +781,10 @@ fn join_bounds( ast::GenericBound::Trait(..) => last_line_extendable(s), }; let mut result = String::with_capacity(128); - let mut closing_paren = has_paren; - if has_paren { - result.push('('); - } result.push_str(&type_strs[0]); let mut can_be_put_on_the_same_line = is_bound_extendable(&result, &items[0]); let generic_bounds_in_order = is_generic_bounds_in_order(items); for (bound, bound_str) in items[1..].iter().zip(type_strs[1..].iter()) { - if closing_paren { - if let ast::GenericBound::Outlives(..) = bound { - closing_paren = false; - result.push(')'); - } - } if generic_bounds_in_order && can_be_put_on_the_same_line { result.push_str(joiner); } else { -- cgit 1.4.1-3-g733a5 From 68638508d4e84ccf3e50a77d92b89334136ba29a Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 26 Oct 2018 14:45:25 +0200 Subject: fix clippy::redundant_clones warnings. --- src/imports.rs | 4 ++-- src/matches.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index deef4d096c9..14233661227 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -248,7 +248,7 @@ impl UseTree { .rewrite(context, shape.offset_left(vis.len())?) .map(|s| { if s.is_empty() { - s.to_owned() + s } else { format!("{}use {};", vis, s) } @@ -592,7 +592,7 @@ fn merge_rest(a: &[UseSegment], b: &[UseSegment], len: usize) -> Option, budget: usize) -> Option= 2 && (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() == block_str.len() - 2) { - "{}".to_owned() + String::from("{}") } else { - block_str.to_owned() + block_str } }) } -- cgit 1.4.1-3-g733a5 From 5ca90edc5bdba1d0e8c280581ee05c7517683622 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 27 Oct 2018 11:22:40 +0900 Subject: Do not remove path disambiugator inside macro --- src/types.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 20828429cb1..f1d89ab9aed 100644 --- a/src/types.rs +++ b/src/types.rs @@ -229,7 +229,9 @@ fn rewrite_segment( .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let separator = if path_context == PathContext::Expr { + let force_separator = + context.inside_macro() && context.snippet(data.span).starts_with("::"); + let separator = if path_context == PathContext::Expr || force_separator { "::" } else { "" -- cgit 1.4.1-3-g733a5 From 3efca8a59604de5cfdb7f4723f49af119f421ec8 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 27 Oct 2018 11:49:48 -0300 Subject: cargo-fmt: Add --edition when printing the command By mistake, it was forgotten to print out the edition in use when printing the rustcmd command. Fix it. Signed-off-by: Otavio Salvador --- src/cargo-fmt/main.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 45d00251828..84b52aed943 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -341,6 +341,7 @@ fn run_rustfmt( if verbosity == Verbosity::Verbose { print!("rustfmt"); + print!(" --edition {}", edition); fmt_args.iter().for_each(|f| print!(" {}", f)); files.iter().for_each(|f| print!(" {}", f.display())); println!(); -- cgit 1.4.1-3-g733a5 From 12275f2e6a44d4f466aa38a65d120c0469814ff2 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Sat, 27 Oct 2018 11:55:41 -0300 Subject: cargo-fmt: Fix splitting of targets across editions When I reworked the code, it ended not generating the complete list of need targets. Fix it. Fixes: #3143. Signed-off-by: Otavio Salvador --- src/cargo-fmt/main.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 84b52aed943..e903c27555a 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -322,15 +322,18 @@ fn run_rustfmt( fmt_args: &[String], verbosity: Verbosity, ) -> Result { - let by_edition: HashMap<_, _> = targets + let by_edition = targets .iter() .inspect(|t| { if verbosity == Verbosity::Verbose { println!("[{} ({})] {:?}", t.kind, t.edition, t.path) } }) - .map(|t| (&t.edition, vec![&t.path])) - .collect(); + .map(|t| (&t.edition, &t.path)) + .fold(HashMap::new(), |mut h, t| { + h.entry(t.0).or_insert_with(Vec::new).push(t.1); + h + }); for (edition, files) in by_edition { let stdout = if verbosity == Verbosity::Quiet { -- cgit 1.4.1-3-g733a5 From 00a20bceff40e98034a7346e5cc6319cbd2d21b7 Mon Sep 17 00:00:00 2001 From: Ivan Komarov Date: Sat, 27 Oct 2018 04:01:37 +0300 Subject: Fix formatting failures on Windows When newline_style is set to Windows, an empty line inside of a macro results in `\r` being passed to the `fold()` in `MacroBranch::rewrite()`. `\r` is technically not an empty string, so we try to indent it, leaving trailing whitespaces behind, even though that was not intended (as far as I can see). This commit replaces the `!l.is_empty()` check with calling `is_empty_line()`, since trying to indent any whitespace-only string will probably result in problematic trailing whitespaces. Fixes: #2810 --- src/macros.rs | 2 +- tests/target/issue-2810.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-2810.rs (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index d378bb8ffb1..43f3071b70a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1347,7 +1347,7 @@ impl MacroBranch { .fold( (String::new(), true), |(mut s, need_indent), (i, (kind, ref l))| { - if !l.is_empty() + if !is_empty_line(l) && need_indent && !new_body_snippet.is_line_non_formatted(i + 1) { diff --git a/tests/target/issue-2810.rs b/tests/target/issue-2810.rs new file mode 100644 index 00000000000..34140c7a1fc --- /dev/null +++ b/tests/target/issue-2810.rs @@ -0,0 +1,14 @@ +// rustfmt-newline_style: Windows + +#[macro_export] +macro_rules! hmmm___ffi_error { + ($result:ident) => { + pub struct $result { + success: bool, + } + + impl $result { + pub fn foo(self) {} + } + }; +} -- cgit 1.4.1-3-g733a5 From 6fa804debaec69cb49f020a84a1c62c3a8aa0969 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Oct 2018 22:53:29 +0900 Subject: Use edition in rustfmt.toml when no command line argument is passed --- src/bin/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 204efa19541..b3c61b3df42 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -438,7 +438,7 @@ struct GetOptsOptions { emit_mode: EmitMode, backup: bool, check: bool, - edition: Edition, + edition: Option, color: Option, file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, @@ -503,7 +503,7 @@ impl GetOptsOptions { } if let Some(ref edition_str) = matches.opt_str("edition") { - options.edition = edition_from_edition_str(edition_str)?; + options.edition = Some(edition_from_edition_str(edition_str)?); } if matches.opt_present("backup") { @@ -559,7 +559,9 @@ impl CliOptions for GetOptsOptions { if let Some(error_on_unformatted) = self.error_on_unformatted { config.set().error_on_unformatted(error_on_unformatted); } - config.set().edition(self.edition); + if let Some(edition) = self.edition { + config.set().edition(edition); + } if self.check { config.set().emit_mode(EmitMode::Diff); } else { -- cgit 1.4.1-3-g733a5 From 4a82252f034ccb4ad886de2466cb093203ecc994 Mon Sep 17 00:00:00 2001 From: Emilio Cobos Álvarez Date: Tue, 30 Oct 2018 03:11:14 +0100 Subject: missed-spans: Fix bogus check. I don't really know what it's trying to do, but forgetting about everything you've seen before when you see whitespace followed by a semicolon doesn't look right to me, and absolutely no tests were hitting that. This check was introduced in 5ecdd072d6745cd70ec7c37eea8dbf1f3ee42f2e, however it was wrong even at that point, and now rustfmt still passes that test, regardless of macro name. Fixes #3154. --- src/missed_spans.rs | 3 --- tests/source/long-use-statement-issue-3154.rs | 3 +++ tests/target/long-use-statement-issue-3154.rs | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 tests/source/long-use-statement-issue-3154.rs create mode 100644 tests/target/long-use-statement-issue-3154.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2b48673dcd4..28cd9874d9c 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -308,9 +308,6 @@ impl<'a> FmtVisitor<'a> { status.line_start = i + 1; } else if c.is_whitespace() && status.last_wspace.is_none() { status.last_wspace = Some(i); - } else if c == ';' && status.last_wspace.is_some() { - status.line_start = i; - status.last_wspace = None; } else { status.last_wspace = None; } diff --git a/tests/source/long-use-statement-issue-3154.rs b/tests/source/long-use-statement-issue-3154.rs new file mode 100644 index 00000000000..339382b5bbf --- /dev/null +++ b/tests/source/long-use-statement-issue-3154.rs @@ -0,0 +1,3 @@ +// rustfmt-reorder_imports: false + +pub use self :: super :: super :: super :: root::mozilla::detail::StringClassFlags as nsTStringRepr_ClassFlags ; diff --git a/tests/target/long-use-statement-issue-3154.rs b/tests/target/long-use-statement-issue-3154.rs new file mode 100644 index 00000000000..339382b5bbf --- /dev/null +++ b/tests/target/long-use-statement-issue-3154.rs @@ -0,0 +1,3 @@ +// rustfmt-reorder_imports: false + +pub use self :: super :: super :: super :: root::mozilla::detail::StringClassFlags as nsTStringRepr_ClassFlags ; -- cgit 1.4.1-3-g733a5 From 2d718a3fc23fbe9a27c71709c54128b5305609c7 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 30 Oct 2018 01:09:09 +0100 Subject: The method trim_left_preserve_layout didn't handle tabs properly. This is fixed by taking the method macros::indent_macro_snippet which essentially does the same: it indents a paragraph while preserving the layout. --- src/comment.rs | 2 +- src/macros.rs | 109 ++------------------------------ src/utils.rs | 153 ++++++++++++++++++++++++++++++++++----------- tests/source/issue-3132.rs | 13 ++++ tests/target/issue-3132.rs | 13 ++++ 5 files changed, 147 insertions(+), 143 deletions(-) create mode 100644 tests/source/issue-3132.rs create mode 100644 tests/target/issue-3132.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e76bb331856..eaed5e1d41e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -332,7 +332,7 @@ fn identify_comment( let (first_group, rest) = orig.split_at(first_group_ending); let rewritten_first_group = if !config.normalize_comments() && has_bare_lines && style.is_block_comment() { - trim_left_preserve_layout(first_group, &shape.indent, config) + trim_left_preserve_layout(first_group, &shape.indent, config)? } else if !config.normalize_comments() && !config.wrap_comments() && !config.format_doc_comments() diff --git a/src/macros.rs b/src/macros.rs index 43f3071b70a..20592beaf17 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -40,7 +40,10 @@ use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; use source_map::SpanUtils; use spanned::Spanned; -use utils::{format_visibility, mk_sp, remove_trailing_white_spaces, rewrite_ident, wrap_str}; +use utils::{ + format_visibility, is_empty_line, mk_sp, remove_trailing_white_spaces, rewrite_ident, + trim_left_preserve_layout, wrap_str, +}; use visitor::FmtVisitor; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -373,7 +376,7 @@ pub fn rewrite_macro_inner( } DelimToken::Brace => { // Skip macro invocations with braces, for now. - indent_macro_snippet(context, context.snippet(mac.span), shape.indent) + trim_left_preserve_layout(context.snippet(mac.span), &shape.indent, &context.config) } _ => unreachable!(), } @@ -1101,108 +1104,6 @@ fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> DelimToken { } } -/// Indent each line according to the specified `indent`. -/// e.g. -/// -/// ```rust,ignore -/// foo!{ -/// x, -/// y, -/// foo( -/// a, -/// b, -/// c, -/// ), -/// } -/// ``` -/// -/// will become -/// -/// ```rust,ignore -/// foo!{ -/// x, -/// y, -/// foo( -/// a, -/// b, -/// c, -/// ), -/// } -/// ``` -fn indent_macro_snippet( - context: &RewriteContext, - macro_str: &str, - indent: Indent, -) -> Option { - let mut lines = LineClasses::new(macro_str); - let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?; - let mut trimmed_lines = Vec::with_capacity(16); - - let mut veto_trim = false; - let min_prefix_space_width = lines - .filter_map(|(kind, line)| { - let mut trimmed = true; - let prefix_space_width = if is_empty_line(&line) { - None - } else { - Some(get_prefix_space_width(context, &line)) - }; - - let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) { - veto_trim = kind.is_string() && !line.ends_with('\\'); - trimmed = false; - line - } else { - line.trim().to_owned() - }; - trimmed_lines.push((trimmed, line, prefix_space_width)); - - // when computing the minimum, do not consider lines within a string - match kind { - FullCodeCharKind::InString | FullCodeCharKind::EndString => None, - _ => prefix_space_width, - } - }) - .min()?; - - Some( - first_line - + "\n" - + &trimmed_lines - .iter() - .map( - |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { - _ if !trimmed => line.to_owned(), - Some(original_indent_width) => { - let new_indent_width = indent.width() - + original_indent_width.saturating_sub(min_prefix_space_width); - let new_indent = Indent::from_width(context.config, new_indent_width); - format!("{}{}", new_indent.to_string(context.config), line) - } - None => String::new(), - }, - ) - .collect::>() - .join("\n"), - ) -} - -fn get_prefix_space_width(context: &RewriteContext, s: &str) -> usize { - let mut width = 0; - for c in s.chars() { - match c { - ' ' => width += 1, - '\t' => width += context.config.tab_spaces(), - _ => return width, - } - } - width -} - -fn is_empty_line(s: &str) -> bool { - s.is_empty() || s.chars().all(char::is_whitespace) -} - // A very simple parser that just parses a macros 2.0 definition into its branches. // Currently we do not attempt to parse any further than that. #[derive(new)] diff --git a/src/utils.rs b/src/utils.rs index a2d15b820eb..86c01af39fb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,7 +20,7 @@ use syntax::ast::{ use syntax::ptr; use syntax::source_map::{BytePos, Span, NO_EXPANSION}; -use comment::{filter_normal_code, CharClasses, FullCodeCharKind}; +use comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; use config::Config; use rewrite::RewriteContext; use shape::{Indent, Shape}; @@ -483,46 +483,123 @@ pub fn remove_trailing_white_spaces(text: &str) -> String { buffer } -/// Trims a minimum of leading whitespaces so that the content layout is kept and aligns to indent. -pub fn trim_left_preserve_layout(orig: &str, indent: &Indent, config: &Config) -> String { - let prefix_whitespace_min = orig - .lines() - // skip the line with the starting sigil since the leading whitespace is removed - // otherwise, the minimum would always be zero - .skip(1) - .filter(|line| !line.is_empty()) - .map(|line| { - let mut width = 0; - for c in line.chars() { - match c { - ' ' => width += 1, - '\t' => width += config.tab_spaces(), - _ => break, - } - } - width - }) - .min() - .unwrap_or(0); - - let indent_str = indent.to_string(config); - let mut lines = orig.lines(); - let first_line = lines.next().unwrap(); - let rest = lines - .map(|line| { - if line.is_empty() { - String::from("\n") +/// Indent each line according to the specified `indent`. +/// e.g. +/// +/// ```rust,ignore +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +/// ), +/// } +/// ``` +/// +/// will become +/// +/// ```rust,ignore +/// foo!{ +/// x, +/// y, +/// foo( +/// a, +/// b, +/// c, +/// ), +/// } +/// ``` +pub fn trim_left_preserve_layout(orig: &str, indent: &Indent, config: &Config) -> Option { + let mut lines = LineClasses::new(orig); + let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?; + let mut trimmed_lines = Vec::with_capacity(16); + + let mut veto_trim = false; + let min_prefix_space_width = lines + .filter_map(|(kind, line)| { + let mut trimmed = true; + let prefix_space_width = if is_empty_line(&line) { + None } else { - format!("\n{}{}", indent_str, &line[prefix_whitespace_min..]) + Some(get_prefix_space_width(config, &line)) + }; + + let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) { + veto_trim = kind.is_string() && !line.ends_with('\\'); + trimmed = false; + line + } else { + line.trim().to_owned() + }; + trimmed_lines.push((trimmed, line, prefix_space_width)); + + // When computing the minimum, do not consider lines within a string. + // The reason is there is a veto against trimming and indenting such lines + match kind { + FullCodeCharKind::InString | FullCodeCharKind::EndString => None, + _ => prefix_space_width, } }) - .collect::>() - .concat(); - format!("{}{}", first_line, rest) + .min()?; + + Some( + first_line + + "\n" + + &trimmed_lines + .iter() + .map( + |&(trimmed, ref line, prefix_space_width)| match prefix_space_width { + _ if !trimmed => line.to_owned(), + Some(original_indent_width) => { + let new_indent_width = indent.width() + + original_indent_width.saturating_sub(min_prefix_space_width); + let new_indent = Indent::from_width(config, new_indent_width); + format!("{}{}", new_indent.to_string(config), line) + } + None => String::new(), + }, + ) + .collect::>() + .join("\n"), + ) +} + +pub fn is_empty_line(s: &str) -> bool { + s.is_empty() || s.chars().all(char::is_whitespace) +} + +fn get_prefix_space_width(config: &Config, s: &str) -> usize { + let mut width = 0; + for c in s.chars() { + match c { + ' ' => width += 1, + '\t' => width += config.tab_spaces(), + _ => return width, + } + } + width } -#[test] -fn test_remove_trailing_white_spaces() { - let s = " r#\"\n test\n \"#"; - assert_eq!(remove_trailing_white_spaces(&s), s); +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_remove_trailing_white_spaces() { + let s = " r#\"\n test\n \"#"; + assert_eq!(remove_trailing_white_spaces(&s), s); + } + + #[test] + fn test_trim_left_preserve_layout() { + let s = "aaa\n\tbbb\n ccc"; + let config = Config::default(); + let indent = Indent::new(4, 0); + assert_eq!( + trim_left_preserve_layout(&s, &indent, &config), + Some("aaa\n bbb\n ccc".to_string()) + ); + } } diff --git a/tests/source/issue-3132.rs b/tests/source/issue-3132.rs new file mode 100644 index 00000000000..a43b83223e2 --- /dev/null +++ b/tests/source/issue-3132.rs @@ -0,0 +1,13 @@ +fn test() { + /* + a + */ + let x = 42; + /* + aaa + "line 1 + line 2 + line 3" + */ + let x = 42; +} diff --git a/tests/target/issue-3132.rs b/tests/target/issue-3132.rs new file mode 100644 index 00000000000..42388e09f74 --- /dev/null +++ b/tests/target/issue-3132.rs @@ -0,0 +1,13 @@ +fn test() { + /* + a + */ + let x = 42; + /* + aaa + "line 1 + line 2 + line 3" + */ + let x = 42; +} -- cgit 1.4.1-3-g733a5 From 7132fe03a0dff64f871230d95f5006eb81354f60 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sun, 4 Nov 2018 10:51:38 +0100 Subject: fix alignment of a struct's fields with the visual style - rewrite_with_alignment was called from the expr module with the wrong shape that missed the extra offset needed for the visual style - rewrite_with_alignment was indenting the given shape although that should have been the caller's responsability --- src/expr.rs | 2 +- src/items.rs | 2 +- src/vertical.rs | 20 ++++++++------------ tests/source/alignment_2633/block_style.rs | 8 ++++++++ tests/source/alignment_2633/visual_style.rs | 9 +++++++++ tests/target/alignment_2633/block_style.rs | 10 ++++++++++ tests/target/alignment_2633/horizontal_tactic.rs | 13 +++++++++++++ tests/target/alignment_2633/visual_style.rs | 9 +++++++++ tests/target/issue-2633.rs | 13 ------------- 9 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 tests/source/alignment_2633/block_style.rs create mode 100644 tests/source/alignment_2633/visual_style.rs create mode 100644 tests/target/alignment_2633/block_style.rs create mode 100644 tests/target/alignment_2633/horizontal_tactic.rs create mode 100644 tests/target/alignment_2633/visual_style.rs delete mode 100644 tests/target/issue-2633.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index fbbc592e547..08b9ad3079c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1565,7 +1565,7 @@ fn rewrite_struct_lit<'a>( rewrite_with_alignment( fields, context, - shape, + v_shape, mk_sp(body_lo, span.hi()), one_line_width, )? diff --git a/src/items.rs b/src/items.rs index 66fdaf50e5a..7c6219a4e04 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1265,7 +1265,7 @@ pub fn format_struct_struct( let items_str = rewrite_with_alignment( fields, context, - Shape::indented(offset, context.config).sub_width(1)?, + Shape::indented(offset.block_indent(context.config), context.config).sub_width(1)?, mk_sp(body_lo, span.hi()), one_line_budget, )?; diff --git a/src/vertical.rs b/src/vertical.rs index dbb3e732d62..0364db763f9 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -172,16 +172,13 @@ pub fn rewrite_with_alignment( } else { let rest_span = mk_sp(init_last_pos, span.hi()); let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; - Some( - result - + spaces - + "\n" - + &shape - .indent - .block_indent(context.config) - .to_string(context.config) - + &rest_str, - ) + Some(format!( + "{}{}\n{}{}", + result, + spaces, + &shape.indent.to_string(context.config), + &rest_str + )) } } @@ -217,9 +214,8 @@ fn rewrite_aligned_items_inner( offset: Indent, one_line_width: usize, ) -> Option { - let item_indent = offset.block_indent(context.config); // 1 = "," - let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; + let item_shape = Shape::indented(offset, context.config).sub_width(1)?; let (mut field_prefix_max_width, field_prefix_min_width) = struct_field_prefix_max_min_width(context, fields, item_shape); let max_diff = field_prefix_max_width.saturating_sub(field_prefix_min_width); diff --git a/tests/source/alignment_2633/block_style.rs b/tests/source/alignment_2633/block_style.rs new file mode 100644 index 00000000000..77fb2919edb --- /dev/null +++ b/tests/source/alignment_2633/block_style.rs @@ -0,0 +1,8 @@ +// rustfmt-struct_field_align_threshold: 50 + +fn func() { + Ok(ServerInformation { name: unwrap_message_string(items.get(0)), + vendor: unwrap_message_string(items.get(1)), + version: unwrap_message_string(items.get(2)), + spec_version: unwrap_message_string(items.get(3)), }); +} diff --git a/tests/source/alignment_2633/visual_style.rs b/tests/source/alignment_2633/visual_style.rs new file mode 100644 index 00000000000..f34cc621e64 --- /dev/null +++ b/tests/source/alignment_2633/visual_style.rs @@ -0,0 +1,9 @@ +// rustfmt-struct_field_align_threshold: 50 +// rustfmt-indent_style: Visual + +fn func() { + Ok(ServerInformation { name: unwrap_message_string(items.get(0)), + vendor: unwrap_message_string(items.get(1)), + version: unwrap_message_string(items.get(2)), + spec_version: unwrap_message_string(items.get(3)), }); +} diff --git a/tests/target/alignment_2633/block_style.rs b/tests/target/alignment_2633/block_style.rs new file mode 100644 index 00000000000..f13e8a8760e --- /dev/null +++ b/tests/target/alignment_2633/block_style.rs @@ -0,0 +1,10 @@ +// rustfmt-struct_field_align_threshold: 50 + +fn func() { + Ok(ServerInformation { + name: unwrap_message_string(items.get(0)), + vendor: unwrap_message_string(items.get(1)), + version: unwrap_message_string(items.get(2)), + spec_version: unwrap_message_string(items.get(3)), + }); +} diff --git a/tests/target/alignment_2633/horizontal_tactic.rs b/tests/target/alignment_2633/horizontal_tactic.rs new file mode 100644 index 00000000000..a381945fd8b --- /dev/null +++ b/tests/target/alignment_2633/horizontal_tactic.rs @@ -0,0 +1,13 @@ +// rustfmt-struct_field_align_threshold: 5 + +#[derive(Fail, Debug, Clone)] +pub enum BuildError { + LineTooLong { length: usize, limit: usize }, + DisallowedByte { b: u8, pos: usize }, + ContainsNewLine { pos: usize }, +} + +enum Foo { + A { a: usize, bbbbb: () }, + B { a: (), bbbbb: () }, +} diff --git a/tests/target/alignment_2633/visual_style.rs b/tests/target/alignment_2633/visual_style.rs new file mode 100644 index 00000000000..7d21b599af4 --- /dev/null +++ b/tests/target/alignment_2633/visual_style.rs @@ -0,0 +1,9 @@ +// rustfmt-struct_field_align_threshold: 50 +// rustfmt-indent_style: Visual + +fn func() { + Ok(ServerInformation { name: unwrap_message_string(items.get(0)), + vendor: unwrap_message_string(items.get(1)), + version: unwrap_message_string(items.get(2)), + spec_version: unwrap_message_string(items.get(3)), }); +} diff --git a/tests/target/issue-2633.rs b/tests/target/issue-2633.rs deleted file mode 100644 index a381945fd8b..00000000000 --- a/tests/target/issue-2633.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-struct_field_align_threshold: 5 - -#[derive(Fail, Debug, Clone)] -pub enum BuildError { - LineTooLong { length: usize, limit: usize }, - DisallowedByte { b: u8, pos: usize }, - ContainsNewLine { pos: usize }, -} - -enum Foo { - A { a: usize, bbbbb: () }, - B { a: (), bbbbb: () }, -} -- cgit 1.4.1-3-g733a5 From 83d1d9aa14bed7a1399e8d67aba7efd47227433a Mon Sep 17 00:00:00 2001 From: Rémy Rakic Date: Mon, 5 Nov 2018 18:24:36 +0100 Subject: normalize_doc_attributes: remove leading whitespace from the doc comment opener Remove possible whitespace from the `CommentStyle::opener()` so that the literal itself has control over the comment's leading spaces. This is most useful for tools, such as bindgen, to allow for example: machine-readable comments with precise syntax rules, or idempotently round-tripping between the proc-macro API and rustfmt. --- src/attr.rs | 6 +++++- tests/source/doc-attrib.rs | 46 +++++++++++++++++++++++++++++++++++++--------- tests/target/doc-attrib.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 033f3767ecd..d7d1876b02d 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -326,7 +326,11 @@ impl Rewrite for ast::Attribute { ast::AttrStyle::Outer => CommentStyle::TripleSlash, }; - let doc_comment = format!("{}{}", comment_style.opener(), literal); + // Remove possible whitespace from the `CommentStyle::opener()` so that + // the literal itself has control over the comment's leading spaces. + let opener = comment_style.opener().trim_end(); + + let doc_comment = format!("{}{}", opener, literal); return rewrite_doc_comment( &doc_comment, shape.comment(context.config), diff --git a/tests/source/doc-attrib.rs b/tests/source/doc-attrib.rs index 363e1441da3..1fea6e361c2 100644 --- a/tests/source/doc-attrib.rs +++ b/tests/source/doc-attrib.rs @@ -2,7 +2,8 @@ // rustfmt-normalize_doc_attributes: true // Only doc = "" attributes should be normalized -#![doc = "Example doc attribute comment"] +#![doc = " Example doc attribute comment"] +#![doc = " Example doc attribute comment with 10 leading spaces"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -10,20 +11,20 @@ // Long `#[doc = "..."]` -struct A { #[doc = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } +struct A { #[doc = " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] b: i32 } -#[doc = "The `nodes` and `edges` method each return instantiations of `Cow<[T]>` to leave implementers the freedom to create entirely new vectors or to pass back slices into internally owned vectors."] +#[doc = " The `nodes` and `edges` method each return instantiations of `Cow<[T]>` to leave implementers the freedom to create entirely new vectors or to pass back slices into internally owned vectors."] struct B { b: i32 } -#[doc = "Level 1 comment"] +#[doc = " Level 1 comment"] mod tests { - #[doc = "Level 2 comment"] + #[doc = " Level 2 comment"] impl A { - #[doc = "Level 3 comment"] + #[doc = " Level 3 comment"] fn f() { - #[doc = "Level 4 comment"] + #[doc = " Level 4 comment"] fn g() { } } @@ -31,12 +32,12 @@ mod tests { } struct C { - #[doc = "item doc attrib comment"] + #[doc = " item doc attrib comment"] // regular item comment b: i32, // regular item comment - #[doc = "item doc attrib comment"] + #[doc = " item doc attrib comment"] c: i32, } @@ -89,3 +90,30 @@ pub struct Params { all(target_arch = "wasm32", feature = "wasm-bindgen"), ))))] type Os = NoSource; + +// use cases from bindgen needing precise control over leading spaces +#[doc = "
"] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ContradictAccessors { + #[doc = "no leading spaces here"] + pub mBothAccessors: ::std::os::raw::c_int, + #[doc = "
"] + pub mNoAccessors: ::std::os::raw::c_int, + #[doc = "
"] + pub mUnsafeAccessors: ::std::os::raw::c_int, + #[doc = "
"] + pub mImmutableAccessor: ::std::os::raw::c_int, +} + +#[doc = " \\brief MPI structure"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct mbedtls_mpi { + #[doc = "< integer sign"] + pub s: ::std::os::raw::c_int, + #[doc = "< total # of limbs"] + pub n: ::std::os::raw::c_ulong, + #[doc = "< pointer to limbs"] + pub p: *mut mbedtls_mpi_uint, +} diff --git a/tests/target/doc-attrib.rs b/tests/target/doc-attrib.rs index 044e004decc..e85235afd0c 100644 --- a/tests/target/doc-attrib.rs +++ b/tests/target/doc-attrib.rs @@ -3,6 +3,7 @@ // Only doc = "" attributes should be normalized //! Example doc attribute comment +//! Example doc attribute comment with 10 leading spaces #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", @@ -103,3 +104,30 @@ mod issue_2620 { ) )))] type Os = NoSource; + +// use cases from bindgen needing precise control over leading spaces +///
+#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct ContradictAccessors { + ///no leading spaces here + pub mBothAccessors: ::std::os::raw::c_int, + ///
+ pub mNoAccessors: ::std::os::raw::c_int, + ///
+ pub mUnsafeAccessors: ::std::os::raw::c_int, + ///
+ pub mImmutableAccessor: ::std::os::raw::c_int, +} + +/// \brief MPI structure +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct mbedtls_mpi { + ///< integer sign + pub s: ::std::os::raw::c_int, + ///< total # of limbs + pub n: ::std::os::raw::c_ulong, + ///< pointer to limbs + pub p: *mut mbedtls_mpi_uint, +} -- cgit 1.4.1-3-g733a5 From 5a2ebdddccb7d7a0fd344dcb07619c908601cdbc Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 5 Nov 2018 20:22:06 +0100 Subject: trim the start of a line when wrapping an item in preparation for formatting --- src/comment.rs | 4 ++-- tests/source/issue-3153.rs | 9 +++++++++ tests/target/issue-3153.rs | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3153.rs create mode 100644 tests/target/issue-3153.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index eaed5e1d41e..db5102a3755 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -398,7 +398,7 @@ impl CodeBlockAttribute { /// Block that is formatted as an item. /// /// An item starts with either a star `*` or a dash `-`. Different level of indentation are -/// handled. +/// handled by shrinking the shape accordingly. struct ItemizedBlock { /// the number of whitespaces up to the item sigil indent: usize, @@ -585,7 +585,7 @@ impl<'a> CommentRewrite<'a> { if let Some(ref ib) = self.item_block { if ib.in_block(&line) { - self.item_block_buffer.push_str(&line); + self.item_block_buffer.push_str(line.trim_start()); self.item_block_buffer.push('\n'); return false; } diff --git a/tests/source/issue-3153.rs b/tests/source/issue-3153.rs new file mode 100644 index 00000000000..2836ce97cf8 --- /dev/null +++ b/tests/source/issue-3153.rs @@ -0,0 +1,9 @@ +// rustfmt-wrap_comments: true + +/// This may panic if: +/// - there are fewer than `max_header_bytes` bytes preceding the body +/// - there are fewer than `max_footer_bytes` bytes following the body +/// - the sum of the body bytes and post-body bytes is less than the sum +/// of `min_body_and_padding_bytes` and `max_footer_bytes` (in other +/// words, the minimum body and padding byte requirement is not met) +fn foo() {} diff --git a/tests/target/issue-3153.rs b/tests/target/issue-3153.rs new file mode 100644 index 00000000000..39e569c0d54 --- /dev/null +++ b/tests/target/issue-3153.rs @@ -0,0 +1,9 @@ +// rustfmt-wrap_comments: true + +/// This may panic if: +/// - there are fewer than `max_header_bytes` bytes preceding the body +/// - there are fewer than `max_footer_bytes` bytes following the body +/// - the sum of the body bytes and post-body bytes is less than the sum of +/// `min_body_and_padding_bytes` and `max_footer_bytes` (in other words, the +/// minimum body and padding byte requirement is not met) +fn foo() {} -- cgit 1.4.1-3-g733a5 From 25b828d35fc4072a860cd504dfa051747b4487a4 Mon Sep 17 00:00:00 2001 From: Kevin Stenerson Date: Mon, 5 Nov 2018 21:12:40 -0700 Subject: Add config option to more aggressively allow overflow --- src/config/mod.rs | 6 +- src/expr.rs | 31 +++++++-- src/overflow.rs | 2 + tests/source/expr-overflow-delimited.rs | 111 ++++++++++++++++++++++++++++++++ tests/target/expr-overflow-delimited.rs | 80 +++++++++++++++++++++++ 5 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 tests/source/expr-overflow-delimited.rs create mode 100644 tests/target/expr-overflow-delimited.rs (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index c3b998d0211..84d94fada77 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -88,8 +88,10 @@ create_config! { // Misc. remove_nested_parens: bool, true, true, "Remove nested parens"; combine_control_expr: bool, true, false, "Combine control expressions with function calls"; - struct_field_align_threshold: usize, 0, false, "Align struct fields if their diffs fits within \ - threshold"; + overflow_delimited_expr: bool, false, false, + "Allow trailing bracket/brace delimited expressions to overflow"; + struct_field_align_threshold: usize, 0, false, + "Align struct fields if their diffs fits within threshold"; enum_discrim_align_threshold: usize, 0, false, "Align enum variants discrims, if their diffs fit within threshold"; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ diff --git a/src/expr.rs b/src/expr.rs index 08b9ad3079c..502c42ff213 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1343,12 +1343,31 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { context.use_block_indent() || context.config.indent_style() == IndentStyle::Visual } - ast::ExprKind::Array(..) - | ast::ExprKind::Call(..) - | ast::ExprKind::Mac(..) - | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Struct(..) - | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1, + + // Handle `[]` and `{}`-like expressions + ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) => { + if context.config.overflow_delimited_expr() { + context.use_block_indent() || context.config.indent_style() == IndentStyle::Visual + } else { + context.use_block_indent() && args_len == 1 + } + } + ast::ExprKind::Mac(ref macro_) => { + match (macro_.node.delim, context.config.overflow_delimited_expr()) { + (ast::MacDelimiter::Bracket, true) | (ast::MacDelimiter::Brace, true) => { + context.use_block_indent() + || context.config.indent_style() == IndentStyle::Visual + } + _ => context.use_block_indent() && args_len == 1, + } + } + + // Handle parenthetical expressions + ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) | ast::ExprKind::Tup(..) => { + context.use_block_indent() && args_len == 1 + } + + // Handle unary-like expressions ast::ExprKind::AddrOf(_, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) diff --git a/src/overflow.rs b/src/overflow.rs index 31cd1b05466..4a583fc1de8 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -404,6 +404,7 @@ impl<'a> Context<'a> { closures::rewrite_last_closure(self.context, expr, shape) } } + // When overflowing the expressions which consists of a control flow // expression, avoid condition to use multi line. ast::ExprKind::If(..) @@ -422,6 +423,7 @@ impl<'a> Context<'a> { expr.rewrite(self.context, shape) } } + _ => expr.rewrite(self.context, shape), } } diff --git a/tests/source/expr-overflow-delimited.rs b/tests/source/expr-overflow-delimited.rs new file mode 100644 index 00000000000..5a3d1671f2c --- /dev/null +++ b/tests/source/expr-overflow-delimited.rs @@ -0,0 +1,111 @@ +// rustfmt-overflow_delimited_expr: true + +fn combine_blocklike() { + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/target/expr-overflow-delimited.rs b/tests/target/expr-overflow-delimited.rs new file mode 100644 index 00000000000..440b149997e --- /dev/null +++ b/tests/target/expr-overflow-delimited.rs @@ -0,0 +1,80 @@ +// rustfmt-overflow_delimited_expr: true + +fn combine_blocklike() { + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing(Bar { + x: value, + y: value2, + }); + + do_thing(x, Bar { + x: value, + y: value2, + }); + + do_thing(&[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(x, &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(x, vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); +} + +fn combine_struct_sample() { + let identity = verify(&ctx, VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + })?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount("/", routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ]) + .launch(); +} -- cgit 1.4.1-3-g733a5 From cd8bb50aea35f73fa4be62857dfed88f772cd07e Mon Sep 17 00:00:00 2001 From: Kevin Stenerson <2653498+kestred@users.noreply.github.com> Date: Wed, 7 Nov 2018 01:49:53 -0700 Subject: Trim the indentation on macros which heuristically appear to use block-style indentation (#3178) --- src/comment.rs | 2 +- src/macros.rs | 41 +++++++++++++++++++++++++++++++++-------- src/test/mod.rs | 2 +- src/utils.rs | 4 ++-- tests/source/macros.rs | 13 +++++++++++++ tests/target/macros.rs | 12 ++++++++++++ 6 files changed, 62 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index db5102a3755..4ba95bda053 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -332,7 +332,7 @@ fn identify_comment( let (first_group, rest) = orig.split_at(first_group_ending); let rewritten_first_group = if !config.normalize_comments() && has_bare_lines && style.is_block_comment() { - trim_left_preserve_layout(first_group, &shape.indent, config)? + trim_left_preserve_layout(first_group, shape.indent, config)? } else if !config.normalize_comments() && !config.wrap_comments() && !config.format_doc_comments() diff --git a/src/macros.rs b/src/macros.rs index 20592beaf17..e956ad4dbc8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -144,11 +144,32 @@ fn rewrite_macro_name( } // Use this on failing to format the macro call. -fn return_original_snippet_with_failure_marked( +fn return_macro_parse_failure_fallback( context: &RewriteContext, + indent: Indent, span: Span, ) -> Option { + // Mark this as a failure however we format it context.macro_rewrite_failure.replace(true); + + // Heuristically determine whether the last line of the macro uses "Block" style + // rather than using "Visual" style, or another indentation style. + let is_like_block_indent_style = context + .snippet(span) + .lines() + .last() + .map(|closing_line| { + closing_line.trim().chars().all(|ch| match ch { + '}' | ')' | ']' => true, + _ => false, + }) + }) + .unwrap_or(false); + if is_like_block_indent_style { + return trim_left_preserve_layout(context.snippet(span), indent, &context.config); + } + + // Return the snippet unmodified if the macro is not block-like Some(context.snippet(span).to_owned()) } @@ -239,7 +260,9 @@ pub fn rewrite_macro_inner( loop { match parse_macro_arg(&mut parser) { Some(arg) => arg_vec.push(arg), - None => return return_original_snippet_with_failure_marked(context, mac.span), + None => { + return return_macro_parse_failure_fallback(context, shape.indent, mac.span); + } } match parser.token { @@ -260,17 +283,19 @@ pub fn rewrite_macro_inner( } } None => { - return return_original_snippet_with_failure_marked( - context, mac.span, - ) + return return_macro_parse_failure_fallback( + context, + shape.indent, + mac.span, + ); } } } } - return return_original_snippet_with_failure_marked(context, mac.span); + return return_macro_parse_failure_fallback(context, shape.indent, mac.span); } _ if arg_vec.last().map_or(false, MacroArg::is_item) => continue, - _ => return return_original_snippet_with_failure_marked(context, mac.span), + _ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span), } parser.bump(); @@ -376,7 +401,7 @@ pub fn rewrite_macro_inner( } DelimToken::Brace => { // Skip macro invocations with braces, for now. - trim_left_preserve_layout(context.snippet(mac.span), &shape.indent, &context.config) + trim_left_preserve_layout(context.snippet(mac.span), shape.indent, &context.config) } _ => unreachable!(), } diff --git a/src/test/mod.rs b/src/test/mod.rs index aa3e729bb43..5999d6f71bf 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -749,7 +749,7 @@ impl ConfigCodeBlock { .code_block .as_ref() .unwrap() - .split('\n') + .lines() .nth(0) .unwrap_or("") == "#![rustfmt::skip]"; diff --git a/src/utils.rs b/src/utils.rs index 86c01af39fb..c5f9a5eda5e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -511,7 +511,7 @@ pub fn remove_trailing_white_spaces(text: &str) -> String { /// ), /// } /// ``` -pub fn trim_left_preserve_layout(orig: &str, indent: &Indent, config: &Config) -> Option { +pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Option { let mut lines = LineClasses::new(orig); let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?; let mut trimmed_lines = Vec::with_capacity(16); @@ -598,7 +598,7 @@ mod test { let config = Config::default(); let indent = Indent::new(4, 0); assert_eq!( - trim_left_preserve_layout(&s, &indent, &config), + trim_left_preserve_layout(&s, indent, &config), Some("aaa\n bbb\n ccc".to_string()) ); } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index dc08a120047..c828ffb881a 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -184,6 +184,19 @@ fn issue1577() { }); } +// #3174 +fn issue_3174() { + let data = + if let Some(debug) = error.debug_info() { + json!({ + "errorKind": format!("{:?}", error.err_kind()), + "debugMessage": debug.message, + }) + } else { + json!({"errorKind": format!("{:?}", error.err_kind())}) + }; +} + gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 1bb5ecf9cb1..e16159ced10 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -225,6 +225,18 @@ fn issue1577() { }); } +// #3174 +fn issue_3174() { + let data = if let Some(debug) = error.debug_info() { + json!({ + "errorKind": format!("{:?}", error.err_kind()), + "debugMessage": debug.message, + }) + } else { + json!({ "errorKind": format!("{:?}", error.err_kind()) }) + }; +} + gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", -- cgit 1.4.1-3-g733a5 From 9467033a8e7f369b5a3d8cc68a51283fd19f4955 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 7 Nov 2018 15:00:33 +0100 Subject: fix the logic for retaining a comment before the arrow in a match --- src/matches.rs | 4 +++- tests/source/issue-3131.rs | 8 ++++++++ tests/target/issue-3131.rs | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-3131.rs create mode 100644 tests/target/issue-3131.rs (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 442f38b28ea..fc7d4cca020 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -379,7 +379,9 @@ fn rewrite_match_body( // Look for comments between `=>` and the start of the body. let arrow_comment = { let arrow_snippet = context.snippet(arrow_span).trim(); - let arrow_index = arrow_snippet.find("=>").unwrap(); + // search for the arrow starting from the end of the snippet since there may be a match + // expression within the guard + let arrow_index = arrow_snippet.rfind("=>").unwrap(); // 2 = `=>` let comment_str = arrow_snippet[arrow_index + 2..].trim(); if comment_str.is_empty() { diff --git a/tests/source/issue-3131.rs b/tests/source/issue-3131.rs new file mode 100644 index 00000000000..c4cb2d8c03c --- /dev/null +++ b/tests/source/issue-3131.rs @@ -0,0 +1,8 @@ +fn main() { + match 3 { + t if match t { + _ => true, + } => {}, + _ => {} + } +} diff --git a/tests/target/issue-3131.rs b/tests/target/issue-3131.rs new file mode 100644 index 00000000000..c7304dd5585 --- /dev/null +++ b/tests/target/issue-3131.rs @@ -0,0 +1,8 @@ +fn main() { + match 3 { + t if match t { + _ => true, + } => {} + _ => {} + } +} -- cgit 1.4.1-3-g733a5 From a5043a81be1b6288e96b8320cf69f397e4be7159 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 7 Nov 2018 16:48:39 +0100 Subject: do not wrap comments in doctest to avoid failing doctest runs --- src/comment.rs | 13 +++---------- tests/source/wrapped_hidden_code_block.rs | 10 ---------- tests/target/issue-3182.rs | 10 ++++++++++ tests/target/wrapped_hidden_code_block.rs | 13 ------------- 4 files changed, 13 insertions(+), 33 deletions(-) delete mode 100644 tests/source/wrapped_hidden_code_block.rs create mode 100644 tests/target/issue-3182.rs delete mode 100644 tests/target/wrapped_hidden_code_block.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4ba95bda053..8b2a4eefa9a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -618,7 +618,7 @@ impl<'a> CommentRewrite<'a> { _ if self.code_block_buffer.is_empty() => String::new(), _ => { let mut config = self.fmt.config.clone(); - config.set().format_doc_comments(false); + config.set().wrap_comments(false); match ::format_code_block(&self.code_block_buffer, &config) { Some(ref s) => trim_custom_comment_prefix(&s.snippet), None => trim_custom_comment_prefix(&self.code_block_buffer), @@ -790,16 +790,9 @@ fn trim_custom_comment_prefix(s: &str) -> String { .map(|line| { let left_trimmed = line.trim_left(); if left_trimmed.starts_with(RUSTFMT_CUSTOM_COMMENT_PREFIX) { - let orig = left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX); - // due to comment wrapping, a line that was originally behind `#` is split over - // multiple lines, which needs then to be prefixed with a `#` - if !orig.trim_left().starts_with("# ") { - Cow::from(format!("# {}", orig)) - } else { - Cow::from(orig) - } + left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX) } else { - Cow::from(line) + line } }) .collect::>() diff --git a/tests/source/wrapped_hidden_code_block.rs b/tests/source/wrapped_hidden_code_block.rs deleted file mode 100644 index d8de8443812..00000000000 --- a/tests/source/wrapped_hidden_code_block.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-max_width: 79 -// rustfmt-wrap_comments: true - -/// ```rust -/// # #![cfg_attr(not(dox), feature(cfg_target_feature, target_feature, stdsimd)not(dox), feature(cfg_target_feature, target_feature, stdsimd))] -/// -/// // Est lectus hendrerit lorem, eget dignissim orci nisl sit amet massa. Etiam volutpat lobortis eros. -/// let x = 42; -/// ``` -fn func() {} diff --git a/tests/target/issue-3182.rs b/tests/target/issue-3182.rs new file mode 100644 index 00000000000..d8de8443812 --- /dev/null +++ b/tests/target/issue-3182.rs @@ -0,0 +1,10 @@ +// rustfmt-max_width: 79 +// rustfmt-wrap_comments: true + +/// ```rust +/// # #![cfg_attr(not(dox), feature(cfg_target_feature, target_feature, stdsimd)not(dox), feature(cfg_target_feature, target_feature, stdsimd))] +/// +/// // Est lectus hendrerit lorem, eget dignissim orci nisl sit amet massa. Etiam volutpat lobortis eros. +/// let x = 42; +/// ``` +fn func() {} diff --git a/tests/target/wrapped_hidden_code_block.rs b/tests/target/wrapped_hidden_code_block.rs deleted file mode 100644 index 572f448c4e7..00000000000 --- a/tests/target/wrapped_hidden_code_block.rs +++ /dev/null @@ -1,13 +0,0 @@ -// rustfmt-max_width: 79 -// rustfmt-wrap_comments: true - -/// ```rust -/// # #![cfg_attr(not(dox), feature(cfg_target_feature, target_feature, -/// # stdsimd)not(dox), feature(cfg_target_feature, target_feature, -/// # stdsimd))] -/// -/// // Est lectus hendrerit lorem, eget dignissim orci nisl sit amet massa. -/// // Etiam volutpat lobortis eros. -/// let x = 42; -/// ``` -fn func() {} -- cgit 1.4.1-3-g733a5 From 3986e690d103e701ef0532c5a3c6715f6e278b77 Mon Sep 17 00:00:00 2001 From: Alan Du Date: Thu, 8 Nov 2018 00:28:08 -0500 Subject: Do not count /*/ as both start and end comment (#3185) --- src/comment.rs | 10 +++++++++- tests/target/issue-3184.rs | 5 +++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-3184.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4ba95bda053..f36690d3f92 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -312,15 +312,23 @@ fn identify_comment( let closer = style.closer().trim_left(); let mut closing_symbol_offset = 0; let mut hbl = false; + let mut first = true; for line in orig.lines() { closing_symbol_offset += compute_len(&orig[closing_symbol_offset..], line); - let trimmed_line = line.trim_left(); + let mut trimmed_line = line.trim_left(); if !trimmed_line.starts_with('*') && !trimmed_line.starts_with("//") && !trimmed_line.starts_with("/*") { hbl = true; } + + // Remove opener from consideration when searching for closer + if first { + let opener = style.opener().trim_right(); + trimmed_line = &trimmed_line[opener.len()..]; + first = false; + } if trimmed_line.ends_with(closer) { break; } diff --git a/tests/target/issue-3184.rs b/tests/target/issue-3184.rs new file mode 100644 index 00000000000..f8d9b169f1d --- /dev/null +++ b/tests/target/issue-3184.rs @@ -0,0 +1,5 @@ +/*/ +struct Error{ + message: String, +} +*/ -- cgit 1.4.1-3-g733a5 From 9534dfc062f636ecd9bdb5d617a8d6a192e6ff27 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 8 Nov 2018 23:16:13 +0900 Subject: Cargo update (#3186) Update `rustc-ap-*` crates to 290.0.0. --- Cargo.lock | 269 +++++++++++++++++++++++++--------------------------- Cargo.toml | 6 +- src/macros.rs | 32 +++++-- src/missed_spans.rs | 2 +- src/source_map.rs | 4 +- 5 files changed, 161 insertions(+), 152 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 4dd60f485a2..80b18771c46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,9 +1,9 @@ [[package]] name = "aho-corasick" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -22,8 +22,8 @@ dependencies = [ "colored 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -43,7 +43,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,7 +73,7 @@ dependencies = [ [[package]] name = "byteorder" -version = "1.2.6" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -83,8 +83,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -95,7 +95,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -111,7 +111,7 @@ name = "colored" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -129,9 +129,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -142,17 +142,17 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "derive-new" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -175,7 +175,7 @@ name = "ena" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -185,8 +185,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -205,22 +205,22 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -268,11 +268,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" @@ -290,18 +287,18 @@ dependencies = [ [[package]] name = "log" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -379,7 +376,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", @@ -435,54 +432,60 @@ dependencies = [ [[package]] name = "regex" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-arena" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-graphviz" +version = "290.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -492,33 +495,33 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -526,29 +529,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "274.0.0" +version = "290.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -563,7 +566,7 @@ name = "rustc-hash" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -581,7 +584,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -608,21 +611,21 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -650,7 +653,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -660,17 +663,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -680,7 +683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -703,32 +706,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.14.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.8" +version = "0.15.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -737,7 +730,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -764,7 +757,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -772,12 +765,12 @@ name = "toml" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ucd-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -805,7 +798,7 @@ dependencies = [ [[package]] name = "utf8-ranges" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -855,7 +848,7 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "68f56c7353e5a9547cbd76ed90f7bb5ffc3ba09d4ea9bd1d8c06c8b1142eeb5a" +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a29ab7c0ed62970beb0534d637a8688842506d0ff9157de83286dacd065c8149" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" @@ -863,16 +856,16 @@ dependencies = [ "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" -"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" +"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum cargo_metadata 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1aaa1a9856ae2d188340526d0986feb6899c9ad11c5dfd73453c784fed6e373d" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum colored 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc0a60679001b62fb628c4da80e574b9645ab4646056d7c9018885efffe45533" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "899ec79626c14e00ccc9729b4d750bbe67fe76a8f436824c16e0233bbd9d7daa" +"checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" @@ -880,19 +873,19 @@ dependencies = [ "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9" -"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426" +"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" +"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" -"checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" -"checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" @@ -902,23 +895,24 @@ dependencies = [ "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" +"checksum quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5829244f52738cfee93b3a165c1911388675be000c888d2fae620dee8fa5b" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" -"checksum rustc-ap-arena 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "866fda692855b38f9d6562f0e952c75c6ebe4032d7dd63c608a88e7c4d3f8087" -"checksum rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6c2343e11a97b4eb3bee29cd5f9314ea409a87baee5d3fec8d1516d1633412e" -"checksum rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b88f905f7ab99bf14220a3a87eff60ec143af8136fd0ca8573641c78be532ec8" -"checksum rustc-ap-rustc_errors 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86fda6cf42e0355b7ecf40f14888340c20b7b864c9d37f6ffca85fe87200652" -"checksum rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fa8622299beac8c40270e8536a7b0509ca80f227a2b56550019a325fa5a60c0" -"checksum rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d16cc3d014af9a524c0bed6ca806c3170e39d5987180f0f8ce8fb7df5113576c" -"checksum rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a29f280f04f4f45e1bdd773ab5e667b36e757bfbbd01193c330815b9e76d05a" -"checksum rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ea27b65311571c7614deb393691eb18c5e41fd4fd9d8490304e128e1358646" +"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" +"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" +"checksum rustc-ap-arena 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecd5dec94d9c198773f141c25c29198238defd318f842c2b88398e9e2f880fb" +"checksum rustc-ap-graphviz 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b17bcb91de88472c65f8dbbecad7c301824ffa98604286d91fefa60b8df81ed0" +"checksum rustc-ap-rustc_cratesio_shim 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2e2f7482c9731aae1ae8957b905a9ad0788229d65dea969877ed990a8963b54" +"checksum rustc-ap-rustc_data_structures 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb644e0a7bfd9644cfb80642d3f6cf0a1a0a5c189a8c79f81a02114b2fcac882" +"checksum rustc-ap-rustc_errors 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85f805e0773fc036cf1774d39f588d123e8e35312f63915b45a71d2574fd9f35" +"checksum rustc-ap-rustc_target 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6367c531821e2478bb3ed94b8a6eb7a832401dba3621a891c9f71af15b51b6a7" +"checksum rustc-ap-serialize 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15d1807a8d7872e598bd15a22ef195b11281a9b763ba12bdcd4be9599ec64aaf" +"checksum rustc-ap-syntax 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "872a36bcc400adff6acdd7467c8effd9c36e7d22a67b761d5d8b2ca164047458" +"checksum rustc-ap-syntax_pos 290.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f88d38440a16fa26176a2829baa92a8b446ce56a7f30c5a9d88491b1ba25a4fe" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" @@ -930,26 +924,25 @@ dependencies = [ "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "84257ccd054dc351472528c8587b4de2dbf0dc0fe2e634030c1a90bfdacebaa9" -"checksum serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)" = "31569d901045afbff7a9479f793177fe9259819aff10ab4f89ef69bbc5f567fe" +"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" +"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" "checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" "checksum simd 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0048b17eb9577ac545c61d85c3559b41dfb4cbea41c9bd9ca6a4f73ff05fda84" "checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" -"checksum syn 0.15.8 (registry+https://github.com/rust-lang/crates.io-index)" = "356d1c5043597c40489e9af2d2498c7fefc33e99b7d75b43be336c8a59b3e45e" -"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" +"checksum syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)" = "90c39a061e2f412a9f869540471ab679e85e50c6b05604daf28bc3060f75c430" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2ecc31b0351ea18b3fe11274b8db6e4d82bce861bbb22e6dbed40417902c65" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f8bfa9ff0cadcd210129ad9d2c5f145c13e9ced3d3e5d948a6213487d52444" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" diff --git a/Cargo.toml b/Cargo.toml index da3ac3a80f5..9150a190e79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,9 +47,9 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.6" -rustc-ap-rustc_target = "274.0.0" -rustc-ap-syntax = "274.0.0" -rustc-ap-syntax_pos = "274.0.0" +rustc-ap-rustc_target = "290.0.0" +rustc-ap-syntax = "290.0.0" +rustc-ap-syntax_pos = "290.0.0" failure = "0.1.1" bytecount = { version = "0.3", features = ["simd-accel"] } diff --git a/src/macros.rs b/src/macros.rs index e956ad4dbc8..a2c1f243879 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,7 @@ use syntax::source_map::{BytePos, Span}; use syntax::symbol; use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::ThinVec; -use syntax::{ast, ptr}; +use syntax::{ast, parse, ptr}; use comment::{contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses}; use expr::rewrite_array; @@ -94,11 +94,11 @@ impl Rewrite for MacroArg { } } -fn parse_macro_arg(parser: &mut Parser) -> Option { +fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { macro_rules! parse_macro_arg { - ($macro_arg:ident, $parser:ident, $f:expr) => { + ($macro_arg:ident, $parser:expr, $f:expr) => { let mut cloned_parser = (*parser).clone(); - match cloned_parser.$parser() { + match $parser(&mut cloned_parser) { Ok(x) => { if parser.sess.span_diagnostic.has_errors() { parser.sess.span_diagnostic.reset_err_count(); @@ -116,11 +116,27 @@ fn parse_macro_arg(parser: &mut Parser) -> Option { }; } - parse_macro_arg!(Expr, parse_expr, |x: ptr::P| Some(x)); - parse_macro_arg!(Ty, parse_ty, |x: ptr::P| Some(x)); - parse_macro_arg!(Pat, parse_pat, |x: ptr::P| Some(x)); + parse_macro_arg!( + Expr, + |parser: &mut parse::parser::Parser<'b>| parser.parse_expr(), + |x: ptr::P| Some(x) + ); + parse_macro_arg!( + Ty, + |parser: &mut parse::parser::Parser<'b>| parser.parse_ty(), + |x: ptr::P| Some(x) + ); + parse_macro_arg!( + Pat, + |parser: &mut parse::parser::Parser<'b>| parser.parse_pat(None), + |x: ptr::P| Some(x) + ); // `parse_item` returns `Option>`. - parse_macro_arg!(Item, parse_item, |x: Option>| x); + parse_macro_arg!( + Item, + |parser: &mut parse::parser::Parser<'b>| parser.parse_item(), + |x: Option>| x + ); None } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 28cd9874d9c..a61134a4833 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -154,7 +154,7 @@ impl<'a> FmtVisitor<'a> { let local_end = self.source_map.lookup_byte_offset(span.hi()); let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.fm.src.as_ref().unwrap()[start_index..end_index]; + let big_snippet = &local_begin.sf.src.as_ref().unwrap()[start_index..end_index]; let big_diff = (span.lo() - big_span_lo).to_usize(); let snippet = self.snippet(span); diff --git a/src/source_map.rs b/src/source_map.rs index ed081adcd86..1d6ff29c19c 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -79,14 +79,14 @@ impl LineRangeUtils for SourceMap { let hi = self.lookup_line(span.hi()).unwrap(); debug_assert_eq!( - lo.fm.name, hi.fm.name, + lo.sf.name, hi.sf.name, "span crossed file boundary: lo: {:?}, hi: {:?}", lo, hi ); // Line numbers start at 1 LineRange { - file: lo.fm.clone(), + file: lo.sf.clone(), lo: lo.line + 1, hi: hi.line + 1, } -- cgit 1.4.1-3-g733a5 From f570438e75006e5a7a4f6a74e7e8f96eae6cf048 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 8 Nov 2018 22:44:59 +0100 Subject: do not add a newline after a missed span if it is the end of a block comment --- src/missed_spans.rs | 5 ++--- tests/target/issue-3124.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 tests/target/issue-3124.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index a61134a4833..237a31e86b8 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -260,9 +260,8 @@ impl<'a> FmtVisitor<'a> { status.line_start = offset + subslice.len(); if let Some('/') = subslice.chars().nth(1) { - // check that there are no contained block comments - if !subslice.lines().any(|s| s.trim_left().starts_with("/*")) { - // Add a newline after line comments + // Only add a newline if the last line is a line comment + if !subslice.trim_end().ends_with("*/") { self.push_str("\n"); } } else if status.line_start <= snippet.len() { diff --git a/tests/target/issue-3124.rs b/tests/target/issue-3124.rs new file mode 100644 index 00000000000..1083050d8f4 --- /dev/null +++ b/tests/target/issue-3124.rs @@ -0,0 +1,14 @@ +pub fn fail1() { + // Some comment. + /**/// +} + +pub fn fail2() { + // Some comment. + /**/ +} + +pub fn fail3() { + // Some comment. + // +} -- cgit 1.4.1-3-g733a5 From 97843377ee507bf15fd0c195c2604ea39c342db0 Mon Sep 17 00:00:00 2001 From: Kevin Stenerson Date: Thu, 8 Nov 2018 19:26:12 -0700 Subject: Replace always true conditionals with `true` --- src/expr.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 502c42ff213..aea5fa5f96f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1340,24 +1340,18 @@ pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_l | ast::ExprKind::WhileLet(..) => { context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } - ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => { - context.use_block_indent() || context.config.indent_style() == IndentStyle::Visual - } + + // Handle always block-like expressions + ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true, // Handle `[]` and `{}`-like expressions ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) => { - if context.config.overflow_delimited_expr() { - context.use_block_indent() || context.config.indent_style() == IndentStyle::Visual - } else { - context.use_block_indent() && args_len == 1 - } + context.config.overflow_delimited_expr() + || (context.use_block_indent() && args_len == 1) } ast::ExprKind::Mac(ref macro_) => { match (macro_.node.delim, context.config.overflow_delimited_expr()) { - (ast::MacDelimiter::Bracket, true) | (ast::MacDelimiter::Brace, true) => { - context.use_block_indent() - || context.config.indent_style() == IndentStyle::Visual - } + (ast::MacDelimiter::Bracket, true) | (ast::MacDelimiter::Brace, true) => true, _ => context.use_block_indent() && args_len == 1, } } -- cgit 1.4.1-3-g733a5 From d121d7205f7a41859013de8ae6cea97ea623f1b6 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 9 Nov 2018 20:50:07 +0100 Subject: fix logic for adding or not a newline after a missed span --- src/missed_spans.rs | 17 +++++++++-------- src/visitor.rs | 2 +- tests/target/issue-3032.rs | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 tests/target/issue-3032.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 237a31e86b8..3c67108b1f1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -259,15 +259,16 @@ impl<'a> FmtVisitor<'a> { status.last_wspace = None; status.line_start = offset + subslice.len(); - if let Some('/') = subslice.chars().nth(1) { - // Only add a newline if the last line is a line comment - if !subslice.trim_end().ends_with("*/") { - self.push_str("\n"); - } - } else if status.line_start <= snippet.len() { - // For other comments add a newline if there isn't one at the end already + // Add a newline: + // - if there isn't one already + // - otherwise, only if the last line is a line comment + if status.line_start <= snippet.len() { match snippet[status.line_start..].chars().next() { - Some('\n') | Some('\r') => (), + Some('\n') | Some('\r') => { + if !subslice.trim_end().ends_with("*/") { + self.push_str("\n"); + } + } _ => self.push_str("\n"), } } diff --git a/src/visitor.rs b/src/visitor.rs index b286465b276..612c8a3b8eb 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -236,7 +236,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - let unindent_comment = (self.is_if_else_block && !b.stmts.is_empty()) && { + let unindent_comment = self.is_if_else_block && !b.stmts.is_empty() && { let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); snippet.contains("//") || snippet.contains("/*") diff --git a/tests/target/issue-3032.rs b/tests/target/issue-3032.rs new file mode 100644 index 00000000000..a0ebf4b7c73 --- /dev/null +++ b/tests/target/issue-3032.rs @@ -0,0 +1,36 @@ +pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option { + let raw_id = id.into(); + unsafe { + if RUST_JSID_IS_INT(raw_id) { + return Some(RUST_JSID_TO_INT(raw_id) as u32); + } + None + } + // if id is length atom, -1, otherwise + /*return if JSID_IS_ATOM(id) { + let atom = JSID_TO_ATOM(id); + //let s = *GetAtomChars(id); + if s > 'a' && s < 'z' { + return -1; + } + + let i = 0; + let str = AtomToLinearString(JSID_TO_ATOM(id)); + return if StringIsArray(str, &mut i) != 0 { i } else { -1 } + } else { + IdToInt32(cx, id); + }*/ +} + +impl Foo { + fn bar() -> usize { + 42 + /* a block comment */ + } + + fn baz() -> usize { + 42 + // this is a line + /* a block comment */ + } +} -- cgit 1.4.1-3-g733a5 From a4e97fa17bbf898a0d2675b5292d814cdef0b544 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 13 Nov 2018 21:10:30 +0100 Subject: compute the span after a struct-like item based on the ident description --- src/items.rs | 9 +++++--- tests/source/issue-3194.rs | 13 ++++++++++++ tests/target/issue-3194.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/source/issue-3194.rs create mode 100644 tests/target/issue-3194.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7c6219a4e04..a4800e9ee01 100644 --- a/src/items.rs +++ b/src/items.rs @@ -464,7 +464,8 @@ impl<'a> FmtVisitor<'a> { BracePos::Auto }, self.block_indent, - mk_sp(span.lo(), body_start), + // make a span that starts right after `enum Foo` + mk_sp(ident.span.hi(), body_start), last_line_width(&enum_header), ) .unwrap(); @@ -1186,7 +1187,8 @@ fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) context.config.brace_style(), BracePos::None, offset, - mk_sp(generics.span.lo(), hi), + // make a span that starts right after `struct Foo` + mk_sp(p.ident.span.hi(), hi), last_line_width(&header_str), )? } else { @@ -1208,7 +1210,7 @@ pub fn format_struct_struct( let header_str = struct_parts.format_header(context); result.push_str(&header_str); - let header_hi = span.lo() + BytePos(header_str.len() as u32); + let header_hi = struct_parts.ident.span.hi(); let body_lo = context.snippet_provider.span_after(span, "{"); let generics_str = match struct_parts.generics { @@ -1222,6 +1224,7 @@ pub fn format_struct_struct( BracePos::Auto }, offset, + // make a span that starts right after `struct Foo` mk_sp(header_hi, body_lo), last_line_width(&result), )?, diff --git a/tests/source/issue-3194.rs b/tests/source/issue-3194.rs new file mode 100644 index 00000000000..b80ce346b6c --- /dev/null +++ b/tests/source/issue-3194.rs @@ -0,0 +1,13 @@ +mod m { struct S where A: B; } + +mod n { struct Foo where A: B { foo: usize } } + +mod o { enum Bar where A: B { Bar } } + +mod with_comments { + mod m { struct S /* before where */ where A: B; /* after where */ } + + mod n { struct Foo /* before where */ where A: B /* after where */ { foo: usize } } + + mod o { enum Bar /* before where */ where A: B /* after where */ { Bar } } +} diff --git a/tests/target/issue-3194.rs b/tests/target/issue-3194.rs new file mode 100644 index 00000000000..a9614913ed1 --- /dev/null +++ b/tests/target/issue-3194.rs @@ -0,0 +1,52 @@ +mod m { + struct S + where + A: B; +} + +mod n { + struct Foo + where + A: B, + { + foo: usize, + } +} + +mod o { + enum Bar + where + A: B, + { + Bar, + } +} + +mod with_comments { + mod m { + struct S + /* before where */ + where + A: B; /* after where */ + } + + mod n { + struct Foo + /* before where */ + where + A: B, /* after where */ + { + foo: usize, + } + } + + mod o { + enum Bar + /* before where */ + where + A: B, /* after where */ + { + Bar, + } + } +} -- cgit 1.4.1-3-g733a5 From dd7add784b166d9d5e6e28588e8e1b494701ba04 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 15 Nov 2018 16:45:16 +1300 Subject: Don't align comments on `extern crate`s Closes #3128 --- src/comment.rs | 8 ++++++++ src/lists.rs | 49 +++++++++++++++++++++++++++++++++---------------- src/reorder.rs | 4 +++- 3 files changed, 44 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index bc46ab6edc2..d126e89f3bc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -163,6 +163,14 @@ pub fn combine_strs_with_missing_comments( shape: Shape, allow_extend: bool, ) -> Option { + trace!( + "combine_strs_with_missing_comments `{}` `{}` {:?} {:?}", + prev_str, + next_str, + span, + shape + ); + let mut result = String::with_capacity(prev_str.len() + next_str.len() + shape.indent.width() + 128); result.push_str(prev_str); diff --git a/src/lists.rs b/src/lists.rs index cd6f363e269..61fe6c24960 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -36,6 +36,8 @@ pub struct ListFormatting<'a> { preserve_newline: bool, // Nested import lists get some special handling for the "Mixed" list type nested: bool, + // Whether comments should be visually aligned. + align_comments: bool, config: &'a Config, } @@ -50,6 +52,7 @@ impl<'a> ListFormatting<'a> { ends_with_newline: true, preserve_newline: false, nested: false, + align_comments: true, config, } } @@ -89,6 +92,11 @@ impl<'a> ListFormatting<'a> { self } + pub fn align_comments(mut self, align_comments: bool) -> Self { + self.align_comments = align_comments; + self + } + pub fn needs_trailing_separator(&self) -> bool { match self.trailing_separator { // We always put separator in front. @@ -465,23 +473,31 @@ where let mut formatted_comment = rewrite_post_comment(&mut item_max_width)?; if !starts_with_newline(comment) { - let mut comment_alignment = - post_comment_alignment(item_max_width, inner_item.len()); - if first_line_width(&formatted_comment) - + last_line_width(&result) - + comment_alignment - + 1 - > formatting.config.max_width() - { - item_max_width = None; - formatted_comment = rewrite_post_comment(&mut item_max_width)?; - comment_alignment = post_comment_alignment(item_max_width, inner_item.len()); - } - for _ in 0..=comment_alignment { - result.push(' '); + if formatting.align_comments { + let mut comment_alignment = + post_comment_alignment(item_max_width, inner_item.len()); + if first_line_width(&formatted_comment) + + last_line_width(&result) + + comment_alignment + + 1 + > formatting.config.max_width() + { + item_max_width = None; + formatted_comment = rewrite_post_comment(&mut item_max_width)?; + comment_alignment = + post_comment_alignment(item_max_width, inner_item.len()); + } + for _ in 0..=comment_alignment { + result.push(' '); + } } - // An additional space for the missing trailing separator. - if last && item_max_width.is_some() && !separate && !formatting.separator.is_empty() + // An additional space for the missing trailing separator (or + // if we skipped alignment above). + if !formatting.align_comments + || (last + && item_max_width.is_some() + && !separate + && !formatting.separator.is_empty()) { result.push(' '); } @@ -902,6 +918,7 @@ pub fn struct_lit_formatting<'a>( ends_with_newline, preserve_newline: true, nested: false, + align_comments: true, config: context.config, } } diff --git a/src/reorder.rs b/src/reorder.rs index f990e686565..a865247e805 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -69,7 +69,9 @@ fn wrap_reorderable_items( list_items: &[ListItem], shape: Shape, ) -> Option { - let fmt = ListFormatting::new(shape, context.config).separator(""); + let fmt = ListFormatting::new(shape, context.config) + .separator("") + .align_comments(false); write_list(list_items, &fmt) } -- cgit 1.4.1-3-g733a5 From 3aa153398aa95c19847fc902f84509b2cb9f9de1 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Fri, 16 Nov 2018 22:25:33 +0100 Subject: fix a few clippy warnings types.rs: fix single_char_pattern (use character patters instead of string for .ends_with() and .starts_with() patterns.rs expr.rs file_lines.rs: fix into_iter_on_ref_ptr (use iter() or iter_mut() instead of into_iter() tests/mod.rs: check_files(): take Option by reference --- src/config/file_lines.rs | 2 +- src/expr.rs | 2 +- src/patterns.rs | 2 +- src/test/mod.rs | 10 +++++----- src/types.rs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index c5fd6eaa623..07df0e32d9c 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -167,7 +167,7 @@ fn normalize_ranges(ranges: &mut HashMap>) { ranges.sort(); let mut result = vec![]; { - let mut iter = ranges.into_iter().peekable(); + let mut iter = ranges.iter_mut().peekable(); while let Some(next) = iter.next() { let mut next = *next; while let Some(&&mut peek) = iter.peek() { diff --git a/src/expr.rs b/src/expr.rs index aea5fa5f96f..973c72d871f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1584,7 +1584,7 @@ fn rewrite_struct_lit<'a>( )? } else { let field_iter = fields - .into_iter() + .iter() .map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); diff --git a/src/patterns.rs b/src/patterns.rs index 675572f4908..7dd315fcb9b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -313,7 +313,7 @@ fn rewrite_tuple_pat( context: &RewriteContext, shape: Shape, ) -> Option { - let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect(); + let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect(); if let Some(pos) = dotdot_pos { let prev = if pos == 0 { diff --git a/src/test/mod.rs b/src/test/mod.rs index 5999d6f71bf..599f83cd49c 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -114,7 +114,7 @@ fn write_message(msg: &str) { fn system_tests() { // Get all files in the tests/source directory. let files = get_test_files(Path::new("tests/source"), true); - let (_reports, count, fails) = check_files(files, None); + let (_reports, count, fails) = check_files(files, &None); // Display results. println!("Ran {} system tests.", count); @@ -126,7 +126,7 @@ fn system_tests() { #[test] fn coverage_tests() { let files = get_test_files(Path::new("tests/coverage/source"), true); - let (_reports, count, fails) = check_files(files, None); + let (_reports, count, fails) = check_files(files, &None); println!("Ran {} tests in coverage mode.", count); assert_eq!(fails, 0, "{} tests failed", fails); @@ -230,7 +230,7 @@ fn idempotence_tests() { } // Get all files in the tests/target directory. let files = get_test_files(Path::new("tests/target"), true); - let (_reports, count, fails) = check_files(files, None); + let (_reports, count, fails) = check_files(files, &None); // Display results. println!("Ran {} idempotent tests.", count); @@ -251,7 +251,7 @@ fn self_tests() { } files.push(PathBuf::from("src/lib.rs")); - let (reports, count, fails) = check_files(files, Some(PathBuf::from("rustfmt.toml"))); + let (reports, count, fails) = check_files(files, &Some(PathBuf::from("rustfmt.toml"))); let mut warnings = 0; // Display results. @@ -340,7 +340,7 @@ fn format_lines_errors_are_reported_with_tabs() { // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. -fn check_files(files: Vec, opt_config: Option) -> (Vec, u32, u32) { +fn check_files(files: Vec, opt_config: &Option) -> (Vec, u32, u32) { let mut count = 0; let mut fails = 0; let mut reports = vec![]; diff --git a/src/types.rs b/src/types.rs index f1d89ab9aed..f407e44036f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -492,7 +492,7 @@ impl Rewrite for ast::GenericBound { match *self { ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => { let snippet = context.snippet(self.span()); - let has_paren = snippet.starts_with("(") && snippet.ends_with(")"); + let has_paren = snippet.starts_with('(') && snippet.ends_with(')'); let rewrite = match trait_bound_modifier { ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape), ast::TraitBoundModifier::Maybe => poly_trait_ref -- cgit 1.4.1-3-g733a5 From 1a3bc79c686e246cb5088ed16bdc648d1564ffb2 Mon Sep 17 00:00:00 2001 From: Kevin Stenerson Date: Mon, 5 Nov 2018 22:48:49 -0700 Subject: Preserve possibly one whitespace for brace macros --- src/macros.rs | 14 +++++++++++++- tests/source/macros.rs | 3 +++ tests/target/macros.rs | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index a2c1f243879..ca0de8fbb23 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -256,7 +256,19 @@ pub fn rewrite_macro_inner( } DelimToken::Paren => Some(format!("{}()", macro_name)), DelimToken::Bracket => Some(format!("{}[]", macro_name)), - DelimToken::Brace => Some(format!("{}{{}}", macro_name)), + DelimToken::Brace => { + // Preserve at most one space before the braces. + let char_after_bang = context + .snippet(mac.span) + .split('!') + .nth(1) + .and_then(|x| x.chars().next()); + if let Some(' ') = char_after_bang { + Some(format!("{} {{}}", macro_name)) + } else { + Some(format!("{}{{}}", macro_name)) + } + } _ => unreachable!(), }; } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index c828ffb881a..383fc723b5b 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -106,6 +106,9 @@ fn main() { impl X { empty_invoc!{} + + // Don't format empty either! + empty_invoc! {} } fn issue_1279() { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index e16159ced10..70ed0b042fe 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -132,6 +132,9 @@ fn main() { impl X { empty_invoc!{} + + // Don't format empty either! + empty_invoc! {} } fn issue_1279() { -- cgit 1.4.1-3-g733a5 From bc5124e01609d86d23c9c7b3d83d7133a9f12449 Mon Sep 17 00:00:00 2001 From: Kevin Stenerson Date: Sat, 17 Nov 2018 11:53:11 -0700 Subject: Always enforce exactly one space between `macro!` and braces (`{}`) --- src/macros.rs | 25 ++++++++++--------------- tests/source/macros.rs | 4 +--- tests/target/issue-2917/packed_simd.rs | 2 +- tests/target/lazy_static.rs | 2 +- tests/target/macros.rs | 14 ++++++-------- tests/target/match.rs | 14 +++++++------- 6 files changed, 26 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index ca0de8fbb23..53afccb53ec 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -256,19 +256,7 @@ pub fn rewrite_macro_inner( } DelimToken::Paren => Some(format!("{}()", macro_name)), DelimToken::Bracket => Some(format!("{}[]", macro_name)), - DelimToken::Brace => { - // Preserve at most one space before the braces. - let char_after_bang = context - .snippet(mac.span) - .split('!') - .nth(1) - .and_then(|x| x.chars().next()); - if let Some(' ') = char_after_bang { - Some(format!("{} {{}}", macro_name)) - } else { - Some(format!("{}{{}}", macro_name)) - } - } + DelimToken::Brace => Some(format!("{} {{}}", macro_name)), _ => unreachable!(), }; } @@ -428,8 +416,15 @@ pub fn rewrite_macro_inner( } } DelimToken::Brace => { - // Skip macro invocations with braces, for now. - trim_left_preserve_layout(context.snippet(mac.span), shape.indent, &context.config) + // For macro invocations with braces, always put a space between + // the `macro_name!` and `{ /* macro_body */ }` but skip modifying + // anything in between the braces (for now). + let snippet = context.snippet(mac.span); + let macro_raw = snippet.split_at(snippet.find('!')? + 1).1.trim_start(); + match trim_left_preserve_layout(macro_raw, &shape.indent, &context.config) { + Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), + None => Some(format!("{} {}", macro_name, macro_raw)), + } } _ => unreachable!(), } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 383fc723b5b..07934255bac 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -4,7 +4,7 @@ itemmacro!(this, is.now() .formatted(yay)); itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb() .is.formatted()); -itemmacro!{this, is.bracket().formatted()} +itemmacro!{this, is.brace().formatted()} peg_file! modname ("mygrammarfile.rustpeg"); @@ -106,8 +106,6 @@ fn main() { impl X { empty_invoc!{} - - // Don't format empty either! empty_invoc! {} } diff --git a/tests/target/issue-2917/packed_simd.rs b/tests/target/issue-2917/packed_simd.rs index 59a7090505e..274614f83e2 100644 --- a/tests/target/issue-2917/packed_simd.rs +++ b/tests/target/issue-2917/packed_simd.rs @@ -31,7 +31,7 @@ macro_rules! impl_from_vector { } */ - test_if!{ + test_if! { $test_tt: interpolate_idents! { mod [$id _from_ $source] { diff --git a/tests/target/lazy_static.rs b/tests/target/lazy_static.rs index 0aed6d38ccf..3625e0a5f5c 100644 --- a/tests/target/lazy_static.rs +++ b/tests/target/lazy_static.rs @@ -10,7 +10,7 @@ lazy_static! { // We need to be able to format `lazy_static!` without known syntax. lazy_static!(xxx, yyyy, zzzzz); -lazy_static!{} +lazy_static! {} // #2354 lazy_static! { diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 70ed0b042fe..061d1746422 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -9,7 +9,7 @@ itemmacro!( .formatted() ); -itemmacro!{this, is.bracket().formatted()} +itemmacro! {this, is.brace().formatted()} peg_file! modname("mygrammarfile.rustpeg"); @@ -94,7 +94,7 @@ fn main() { foo(makro!(1, 3)); - hamkaas!{ () }; + hamkaas! { () }; macrowithbraces! {dont, format, me} @@ -104,11 +104,11 @@ fn main() { some_macro![]; - some_macro!{ + some_macro! { // comment }; - some_macro!{ + some_macro! { // comment }; @@ -131,9 +131,7 @@ fn main() { } impl X { - empty_invoc!{} - - // Don't format empty either! + empty_invoc! {} empty_invoc! {} } @@ -952,7 +950,7 @@ macro_rules! m { }; } fn foo() { - f!{r#" + f! {r#" test "#}; } diff --git a/tests/target/match.rs b/tests/target/match.rs index b5352336b1e..31c09550aaf 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -204,19 +204,19 @@ fn issue355() { vec![3; 4] } // Funky bracketing styles - t => println!{"a", b}, + t => println! {"a", b}, u => vec![1, 2], v => vec![3; 4], w => println!["a", b], x => vec![1, 2], y => vec![3; 4], // Brackets with comments - tc => println!{"a", b}, // comment - uc => vec![1, 2], // comment - vc => vec![3; 4], // comment - wc => println!["a", b], // comment - xc => vec![1, 2], // comment - yc => vec![3; 4], // comment + tc => println! {"a", b}, // comment + uc => vec![1, 2], // comment + vc => vec![3; 4], // comment + wc => println!["a", b], // comment + xc => vec![1, 2], // comment + yc => vec![3; 4], // comment yd => looooooooooooooooooooooooooooooooooooooooooooooooooooooooong_func( aaaaaaaaaa, bbbbbbbbbb, cccccccccc, dddddddddd, ), -- cgit 1.4.1-3-g733a5 From 1dd54e67a11c133b16d7ed6185e1b71961668803 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 18 Nov 2018 21:31:40 +0900 Subject: Prefer to break arguments over putting output type on the next line (#3190) --- src/types.rs | 75 ++++++++++++++++++++++++---------------------- tests/source/type.rs | 6 ++++ tests/target/fn-simple.rs | 5 ++-- tests/target/issue-2164.rs | 25 +++++++++------- tests/target/type.rs | 12 ++++++++ 5 files changed, 74 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index f407e44036f..7b23cd51915 100644 --- a/src/types.rs +++ b/src/types.rs @@ -289,6 +289,19 @@ where { debug!("format_function_type {:#?}", shape); + let ty_shape = match context.config.indent_style() { + // 4 = " -> " + IndentStyle::Block => shape.offset_left(4)?, + IndentStyle::Visual => shape.block_left(4)?, + }; + let output = match *output { + FunctionRetTy::Ty(ref ty) => { + let type_str = ty.rewrite(context, ty_shape)?; + format!(" -> {}", type_str) + } + FunctionRetTy::Default(..) => String::new(), + }; + // Code for handling variadics is somewhat duplicated for items, but they // are different enough to need some serious refactoring to share code. enum ArgumentKind @@ -307,19 +320,18 @@ where None }; - // 2 for () - let budget = shape.width.checked_sub(2)?; - // 1 for ( - let offset = match context.config.indent_style() { - IndentStyle::Block => { - shape - .block() - .block_indent(context.config.tab_spaces()) - .indent - } - IndentStyle::Visual => shape.indent + 1, + let list_shape = if context.use_block_indent() { + Shape::indented( + shape.block().indent.block_indent(context.config), + context.config, + ) + } else { + // 2 for () + let budget = shape.width.checked_sub(2)?; + // 1 for ( + let offset = shape.indent + 1; + Shape::legacy(budget, offset) }; - let list_shape = Shape::legacy(budget, offset); let list_lo = context.snippet_provider.span_after(span, "("); let items = itemize_list( context.snippet_provider, @@ -345,12 +357,18 @@ where let item_vec: Vec<_> = items.collect(); - let tactic = definitive_tactic( - &*item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - budget, - ); + // If the return type is multi-lined, then force to use multiple lines for + // arguments as well. + let tactic = if output.contains('\n') { + DefinitiveListTactic::Vertical + } else { + definitive_tactic( + &*item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + shape.width.saturating_sub(2 + output.len()), + ) + }; let trailing_separator = if !context.use_block_indent() || variadic { SeparatorTactic::Never } else { @@ -364,27 +382,12 @@ where .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; - let ty_shape = match context.config.indent_style() { - // 4 = " -> " - IndentStyle::Block => shape.offset_left(4)?, - IndentStyle::Visual => shape.block_left(4)?, - }; - let output = match *output { - FunctionRetTy::Ty(ref ty) => { - let type_str = ty.rewrite(context, ty_shape)?; - format!(" -> {}", type_str) - } - FunctionRetTy::Default(..) => String::new(), - }; - - let args = if (!list_str.contains('\n') || list_str.is_empty()) && !output.contains('\n') - || !context.use_block_indent() - { + let args = if tactic == DefinitiveListTactic::Horizontal || !context.use_block_indent() { format!("({})", list_str) } else { format!( "({}{}{})", - offset.to_string_with_newline(context.config), + list_shape.indent.to_string_with_newline(context.config), list_str, shape.block().indent.to_string_with_newline(context.config), ) @@ -395,7 +398,7 @@ where Some(format!( "{}\n{}{}", args, - offset.to_string(context.config), + list_shape.indent.to_string(context.config), output.trim_left() )) } diff --git a/tests/source/type.rs b/tests/source/type.rs index 208a30e634e..55eb05442d6 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -129,3 +129,9 @@ fn issue3139() { json!( { "test": None :: } ) ); } + +// #3180 +fn foo(a: SomeLongComplexType, b: SomeOtherLongComplexType) -> Box> { +} + +type MyFn = fn(a: SomeLongComplexType, b: SomeOtherLongComplexType,) -> Box>; diff --git a/tests/target/fn-simple.rs b/tests/target/fn-simple.rs index f35c5d8a0ed..692739fa6a9 100644 --- a/tests/target/fn-simple.rs +++ b/tests/target/fn-simple.rs @@ -9,8 +9,9 @@ fn simple( x: Typ, key: &[u8], upd: Box< - Fn(Option<&memcache::Item>) - -> (memcache::Status, Result>), + Fn( + Option<&memcache::Item>, + ) -> (memcache::Status, Result>), >, ) -> MapResult { } diff --git a/tests/target/issue-2164.rs b/tests/target/issue-2164.rs index ab1d7dfd37a..dbf92107ce2 100644 --- a/tests/target/issue-2164.rs +++ b/tests/target/issue-2164.rs @@ -56,8 +56,10 @@ pub struct emacs_env_25 { ) -> emacs_value, >, pub intern: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, symbol_name: *const ::libc::c_char) - -> emacs_value, + unsafe extern "C" fn( + env: *mut emacs_env, + symbol_name: *const ::libc::c_char, + ) -> emacs_value, >, pub type_of: ::std::option::Option< unsafe extern "C" fn(env: *mut emacs_env, value: emacs_value) -> emacs_value, @@ -87,15 +89,16 @@ pub struct emacs_env_25 { ) -> bool, >, pub make_string: ::std::option::Option< - unsafe extern "C" fn(env: *mut emacs_env, contents: *const ::libc::c_char, length: isize) - -> emacs_value, + unsafe extern "C" fn( + env: *mut emacs_env, + contents: *const ::libc::c_char, + length: isize, + ) -> emacs_value, >, pub make_user_ptr: ::std::option::Option< unsafe extern "C" fn( env: *mut emacs_env, - fin: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void), - >, + fin: ::std::option::Option, ptr: *mut ::libc::c_void, ) -> emacs_value, >, @@ -107,7 +110,9 @@ pub struct emacs_env_25 { >, pub get_user_finalizer: ::std::option::Option< unsafe extern "C" fn( - arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value + arg1: *mut ::libc::c_void, + env: *mut emacs_env, + uptr: emacs_value, ) -> ::std::option::Option< unsafe extern "C" fn(arg1: *mut ::libc::c_void, env: *mut emacs_env, uptr: emacs_value), >, @@ -116,9 +121,7 @@ pub struct emacs_env_25 { unsafe extern "C" fn( env: *mut emacs_env, uptr: emacs_value, - fin: ::std::option::Option< - unsafe extern "C" fn(arg1: *mut ::libc::c_void), - >, + fin: ::std::option::Option, ), >, pub vec_get: ::std::option::Option< diff --git a/tests/target/type.rs b/tests/target/type.rs index b8f41218f41..2afcc652c44 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -128,3 +128,15 @@ fn issue3139() { json!({ "test": None:: }) ); } + +// #3180 +fn foo( + a: SomeLongComplexType, + b: SomeOtherLongComplexType, +) -> Box> { +} + +type MyFn = fn( + a: SomeLongComplexType, + b: SomeOtherLongComplexType, +) -> Box>; -- cgit 1.4.1-3-g733a5 From b9f4624ca6c721fad166ba58577d430101433c9b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 19 Nov 2018 14:09:29 +1300 Subject: fixup minor bugs --- src/config/options.rs | 2 +- src/macros.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index 38ed1e526eb..3de24ee99bc 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -447,7 +447,7 @@ pub trait CliOptions { } /// The edition of the compiler (RFC 2052) -configuration_option_enum!{ Edition: +configuration_option_enum! { Edition: Edition2015: 2015, Edition2018: 2018, } diff --git a/src/macros.rs b/src/macros.rs index 53afccb53ec..8d3b45da0d2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -421,7 +421,7 @@ pub fn rewrite_macro_inner( // anything in between the braces (for now). let snippet = context.snippet(mac.span); let macro_raw = snippet.split_at(snippet.find('!')? + 1).1.trim_start(); - match trim_left_preserve_layout(macro_raw, &shape.indent, &context.config) { + match trim_left_preserve_layout(macro_raw, shape.indent, &context.config) { Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), None => Some(format!("{} {}", macro_name, macro_raw)), } -- cgit 1.4.1-3-g733a5 From a2da636ab340b02d79b95ff02a653199b01e0af2 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 26 Nov 2018 20:39:12 +0100 Subject: allow to run a rustfmt command from cargo-fmt even when there is no target --- src/cargo-fmt/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index e903c27555a..b2496565885 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -322,7 +322,8 @@ fn run_rustfmt( fmt_args: &[String], verbosity: Verbosity, ) -> Result { - let by_edition = targets + let default_edition = String::from("2015"); + let mut by_edition = targets .iter() .inspect(|t| { if verbosity == Verbosity::Verbose { @@ -334,6 +335,9 @@ fn run_rustfmt( h.entry(t.0).or_insert_with(Vec::new).push(t.1); h }); + if by_edition.is_empty() { + by_edition.insert(&default_edition, Vec::new()); + } for (edition, files) in by_edition { let stdout = if verbosity == Verbosity::Quiet { -- cgit 1.4.1-3-g733a5 From 378994b85834497a18ff9bad86dc0a33297c1f05 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 27 Nov 2018 14:04:48 +1300 Subject: Add a version option --- Cargo.toml | 2 +- Configurations.md | 16 ++++++++++++++ Contributing.md | 25 +++++++++++----------- README.md | 2 +- src/config/mod.rs | 1 + src/config/options.rs | 7 ++++++ tests/target/configs/combine_control_expr/false.rs | 2 +- tests/target/configs/combine_control_expr/true.rs | 2 +- 8 files changed, 41 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 2a6b07d3c21..b15fb999fcd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ name = "rustfmt-nightly" version = "1.0.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" -repository = "https://github.com/rust-lang-nursery/rustfmt" +repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" license = "Apache-2.0/MIT" build = "build.rs" diff --git a/Configurations.md b/Configurations.md index 4d41fe52e3d..9b59b19acc5 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2367,6 +2367,22 @@ If you want to format code that requires edition 2018, add the following to your edition = "2018" ``` +## `version` + +Which version of the formatting rules to use. `Version::One` is backwards-compatible +with Rustfmt 1.0. Other versions are only backwards compatible within a major +version number. + +- **Default value**: `One` +- **Possible values**: `One`, `Two` +- **Stable**: No + +### Example + +```toml +version = "Two" +``` + ## `normalize_doc_attributes` Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. diff --git a/Contributing.md b/Contributing.md index bbd736ec98f..23b3de3e8fa 100644 --- a/Contributing.md +++ b/Contributing.md @@ -2,8 +2,8 @@ There are many ways to contribute to Rustfmt. This document lays out what they are and has information for how to get started. If you have any questions about -contributing or need help with anything, please ping nrc on irc, #rust-dev-tools -on irc.mozilla.org is probably the best channel. Feel free to also ask questions +contributing or need help with anything, please ask in the WG-Rustfmt channel +on [Discord](https://discordapp.com/invite/rust-lang). Feel free to also ask questions on issues, or file new issues specifically to get help. All contributors are expected to follow our [Code of @@ -14,14 +14,6 @@ Conduct](CODE_OF_CONDUCT.md). It would be really useful to have people use rustfmt on their projects and file issues where it does something you don't expect. -A really useful thing to do that on a crate from the Rust repo. If it does -something unexpected, file an issue; if not, make a PR to the Rust repo with the -reformatted code. We hope to get the whole repo consistently rustfmt'ed and to -replace `make tidy` with rustfmt as a medium-term goal. Issues with stack traces -for bugs and/or minimal test cases are especially useful. - -See this [blog post](http://ncameron.org/blog/rustfmt-ing-rust/) for more details. - ## Create test cases @@ -66,11 +58,14 @@ example, the `issue-1111.rs` test file is configured by the file ## Debugging -Some `rewrite_*` methods use the `debug!` macro for printing useful information. These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`. These traces can be helpful in understanding which part of the code was used and get a better grasp on the execution flow. +Some `rewrite_*` methods use the `debug!` macro for printing useful information. +These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`. +These traces can be helpful in understanding which part of the code was used +and get a better grasp on the execution flow. ## Hack! -Here are some [good starting issues](https://github.com/rust-lang-nursery/rustfmt/issues?q=is%3Aopen+is%3Aissue+label%3Agood-first-issue). +Here are some [good starting issues](https://github.com/rust-lang/rustfmt/issues?q=is%3Aopen+is%3Aissue+label%3Agood-first-issue). If you've found areas which need polish and don't have issues, please submit a PR, don't feel there needs to be an issue. @@ -86,6 +81,12 @@ Talking of tests, if you add a new feature or fix a bug, please also add a test. It's really easy, see above for details. Please run `cargo test` before submitting a PR to ensure your patch passes all tests, it's pretty quick. +Rustfmt is post-1.0 and within major version releases we strive for backwards +compatibility (at least when using the default options). That means any code +which changes Rustfmt's output must be guarded by either an option or a version +check. The latter is implemented as an option called `option`. See the section on +[configuration](#Configuration) below. + Please try to avoid leaving `TODO`s in the code. There are a few around, but I wish there weren't. You can leave `FIXME`s, preferably with an issue number. diff --git a/README.md b/README.md index 0af1a94080d..17d5a5bd3e6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# rustfmt [![Build Status](https://travis-ci.org/rust-lang-nursery/rustfmt.svg)](https://travis-ci.org/rust-lang-nursery/rustfmt) [![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rustfmt?svg=true)](https://ci.appveyor.com/project/nrc/rustfmt) [![crates.io](https://img.shields.io/crates/v/rustfmt-nightly.svg)](https://crates.io/crates/rustfmt-nightly) [![Travis Configuration Status](https://img.shields.io/travis/davidalber/rustfmt-travis.svg?label=travis%20example)](https://travis-ci.org/davidalber/rustfmt-travis) +# rustfmt [![Build Status](https://travis-ci.org/rust-lang/rustfmt.svg)](https://travis-ci.org/rust-lang/rustfmt) [![Build Status](https://ci.appveyor.com/api/projects/status/github/rust-lang/rustfmt?svg=true)](https://ci.appveyor.com/project/nrc/rustfmt) [![crates.io](https://img.shields.io/crates/v/rustfmt-nightly.svg)](https://crates.io/crates/rustfmt-nightly) [![Travis Configuration Status](https://img.shields.io/travis/davidalber/rustfmt-travis.svg?label=travis%20example)](https://travis-ci.org/davidalber/rustfmt-travis) A tool for formatting Rust code according to style guidelines. diff --git a/src/config/mod.rs b/src/config/mod.rs index 84d94fada77..1aec0d5bfcd 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -113,6 +113,7 @@ create_config! { blank_lines_lower_bound: usize, 0, false, "Minimum number of blank lines which must be put between items"; edition: Edition, Edition::Edition2015, true, "The edition of the parser (RFC 2052)"; + version: Version, Version::One, false, "Version of formatting rules"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/src/config/options.rs b/src/config/options.rs index 3de24ee99bc..ed3e87a27fd 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -291,6 +291,13 @@ configuration_option_enum! { Color: Auto, } +configuration_option_enum! { Version: + // 1.x.y + One, + // 2.x.y + Two, +} + impl Color { /// Whether we should use a coloured terminal. pub fn use_colored_tty(self) -> bool { diff --git a/tests/target/configs/combine_control_expr/false.rs b/tests/target/configs/combine_control_expr/false.rs index 81eff08660d..b44d8e1b775 100644 --- a/tests/target/configs/combine_control_expr/false.rs +++ b/tests/target/configs/combine_control_expr/false.rs @@ -1,6 +1,6 @@ // rustfmt-indent_style: Block // rustfmt-combine_control_expr: false -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. +// Combining openings and closings. See https://github.com/rust-lang/fmt-rfcs/issues/61. fn main() { // Call diff --git a/tests/target/configs/combine_control_expr/true.rs b/tests/target/configs/combine_control_expr/true.rs index c5372c2ff37..ea7c61ef396 100644 --- a/tests/target/configs/combine_control_expr/true.rs +++ b/tests/target/configs/combine_control_expr/true.rs @@ -1,6 +1,6 @@ // rustfmt-indent_style: Block // rustfmt-combine_control_expr: true -// Combining openings and closings. See https://github.com/rust-lang-nursery/fmt-rfcs/issues/61. +// Combining openings and closings. See https://github.com/rust-lang/fmt-rfcs/issues/61. fn main() { // Call -- cgit 1.4.1-3-g733a5 From 7fb5c0b0c960b12737be8bf904cd926b1898ea0c Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 27 Nov 2018 23:03:09 +0000 Subject: Cosmetic improvements --- src/reorder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index a865247e805..89bafccd6ed 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -37,15 +37,15 @@ use std::cmp::{Ord, Ordering}; fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { match (&a.node, &b.node) { (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { - a.ident.name.as_str().cmp(&b.ident.name.as_str()) + a.ident.as_str().cmp(&b.ident.as_str()) } (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` // ^^^ Comparing this. let a_orig_name = - a_name.map_or_else(|| a.ident.name.as_str(), |symbol| symbol.as_str()); + a_name.map_or_else(|| a.ident.as_str(), |symbol| symbol.as_str()); let b_orig_name = - b_name.map_or_else(|| b.ident.name.as_str(), |symbol| symbol.as_str()); + b_name.map_or_else(|| b.ident.as_str(), |symbol| symbol.as_str()); let result = a_orig_name.cmp(&b_orig_name); if result != Ordering::Equal { return result; @@ -57,7 +57,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (Some(..), None) => Ordering::Greater, (None, Some(..)) => Ordering::Less, (None, None) => Ordering::Equal, - (Some(..), Some(..)) => a.ident.name.as_str().cmp(&b.ident.name.as_str()), + (Some(..), Some(..)) => a.ident.as_str().cmp(&b.ident.as_str()), } } _ => unreachable!(), -- cgit 1.4.1-3-g733a5 From 40174e9481872d99ac446ac61e27cf800bfd4842 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 28 Nov 2018 22:49:09 +0100 Subject: fix the visitor's starting position when visiting a labelled block Close #3217 --- src/expr.rs | 15 ++++++++------- src/reorder.rs | 6 ++---- tests/source/issue-3217.rs | 8 ++++++++ tests/target/issue-3217.rs | 24 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 tests/source/issue-3217.rs create mode 100644 tests/target/issue-3217.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 973c72d871f..5d0383ddcb2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -417,15 +417,16 @@ fn rewrite_empty_block( prefix: &str, shape: Shape, ) -> Option { + if !block.stmts.is_empty() { + return None; + } + let label_str = rewrite_label(label); if attrs.map_or(false, |a| !inner_attributes(a).is_empty()) { return None; } - if block.stmts.is_empty() - && !block_contains_comment(block, context.source_map) - && shape.width >= 2 - { + if !block_contains_comment(block, context.source_map) && shape.width >= 2 { return Some(format!("{}{}{{}}", prefix, label_str)); } @@ -510,13 +511,13 @@ pub fn rewrite_block_with_visitor( let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.is_if_else_block = context.is_if_else_block(); - match block.rules { - ast::BlockCheckMode::Unsafe(..) => { + match (block.rules, label) { + (ast::BlockCheckMode::Unsafe(..), _) | (ast::BlockCheckMode::Default, Some(_)) => { let snippet = context.snippet(block.span); let open_pos = snippet.find_uncommented("{")?; visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) } - ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(), + (ast::BlockCheckMode::Default, None) => visitor.last_pos = block.span.lo(), } let inner_attrs = attrs.map(inner_attributes); diff --git a/src/reorder.rs b/src/reorder.rs index 89bafccd6ed..eddc0446035 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -42,10 +42,8 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` // ^^^ Comparing this. - let a_orig_name = - a_name.map_or_else(|| a.ident.as_str(), |symbol| symbol.as_str()); - let b_orig_name = - b_name.map_or_else(|| b.ident.as_str(), |symbol| symbol.as_str()); + let a_orig_name = a_name.map_or_else(|| a.ident.as_str(), |symbol| symbol.as_str()); + let b_orig_name = b_name.map_or_else(|| b.ident.as_str(), |symbol| symbol.as_str()); let result = a_orig_name.cmp(&b_orig_name); if result != Ordering::Equal { return result; diff --git a/tests/source/issue-3217.rs b/tests/source/issue-3217.rs new file mode 100644 index 00000000000..176c702002a --- /dev/null +++ b/tests/source/issue-3217.rs @@ -0,0 +1,8 @@ +#![feature(label_break_value)] + +fn main() { + let mut res = 0; + 's_39: { if res == 0i32 { println!("Hello, world!"); } } + 's_40: loop { println!("res = {}", res); res += 1; if res == 3i32 { break 's_40; } } + let toto = || { if true { 42 } else { 24 } }; +} diff --git a/tests/target/issue-3217.rs b/tests/target/issue-3217.rs new file mode 100644 index 00000000000..5121320a097 --- /dev/null +++ b/tests/target/issue-3217.rs @@ -0,0 +1,24 @@ +#![feature(label_break_value)] + +fn main() { + let mut res = 0; + 's_39: { + if res == 0i32 { + println!("Hello, world!"); + } + } + 's_40: loop { + println!("res = {}", res); + res += 1; + if res == 3i32 { + break 's_40; + } + } + let toto = || { + if true { + 42 + } else { + 24 + } + }; +} -- cgit 1.4.1-3-g733a5 From d03d9a45efd6995533e2cd79e458cbfeb8408e6e Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 29 Nov 2018 20:39:07 +0100 Subject: end expressions like return/continue/break with a semicolon Close #3213 --- src/config/license.rs | 2 +- src/matches.rs | 9 +++++++-- tests/source/issue-3213.rs | 7 +++++++ tests/source/match.rs | 2 +- tests/target/issue-3213.rs | 11 +++++++++++ tests/target/match.rs | 2 +- 6 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 tests/source/issue-3213.rs create mode 100644 tests/target/issue-3213.rs (limited to 'src') diff --git a/src/config/license.rs b/src/config/license.rs index 630399319c1..b7324829393 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -137,7 +137,7 @@ impl TemplateParser { return Err(LicenseError::Parse(format!( "incomplete escape sequence on l. {}", parser.linum - ))) + ))); } _ => (), } diff --git a/src/matches.rs b/src/matches.rs index fc7d4cca020..56d2cc5c598 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -29,7 +29,7 @@ use source_map::SpanUtils; use spanned::Spanned; use utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - ptr_vec_to_ref_vec, trimmed_last_line_width, + ptr_vec_to_ref_vec, semicolon_for_expr, trimmed_last_line_width, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. @@ -413,7 +413,12 @@ fn rewrite_match_body( } else { "" }; - ("{", format!("{}}}{}", indent_str, comma)) + let semicolon = if semicolon_for_expr(context, body) { + ";" + } else { + "" + }; + ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) } else { ("", String::from(",")) }; diff --git a/tests/source/issue-3213.rs b/tests/source/issue-3213.rs new file mode 100644 index 00000000000..a00ec4d3661 --- /dev/null +++ b/tests/source/issue-3213.rs @@ -0,0 +1,7 @@ +fn foo() { + match 0 { + 0 => return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + 1 => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + _ => "", + }; +} diff --git a/tests/source/match.rs b/tests/source/match.rs index 116f5f718b9..b226d60b7c6 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -545,7 +545,7 @@ fn issue_3005() { { return NoCalcLength::parse_dimension(context, value, unit) .map(LengthOrPercentage::Length) - .map_err(|()| location.new_unexpected_token_error(token.clone())) + .map_err(|()| location.new_unexpected_token_error(token.clone())); }, } } diff --git a/tests/target/issue-3213.rs b/tests/target/issue-3213.rs new file mode 100644 index 00000000000..bd2ee48138a --- /dev/null +++ b/tests/target/issue-3213.rs @@ -0,0 +1,11 @@ +fn foo() { + match 0 { + 0 => { + return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + } + 1 => { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + _ => "", + }; +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 31c09550aaf..f45574ee46c 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -572,7 +572,7 @@ fn issue_3005() { } if num_context.is_ok(context.parsing_mode, value) => { return NoCalcLength::parse_dimension(context, value, unit) .map(LengthOrPercentage::Length) - .map_err(|()| location.new_unexpected_token_error(token.clone())) + .map_err(|()| location.new_unexpected_token_error(token.clone())); } } } -- cgit 1.4.1-3-g733a5 From ab7f4e19eb4264b19fb769682bdd5a37ee68c7c4 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 1 Dec 2018 23:28:08 +0100 Subject: rewrite_comment: fix block fallback when failing to rewrite an itemized block Close #3224 --- src/comment.rs | 55 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index d126e89f3bc..2a4db512091 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -416,6 +416,8 @@ impl CodeBlockAttribute { /// An item starts with either a star `*` or a dash `-`. Different level of indentation are /// handled by shrinking the shape accordingly. struct ItemizedBlock { + /// the lines that are identified as part of an itemized block + lines: Vec, /// the number of whitespaces up to the item sigil indent: usize, /// the string that marks the start of an item @@ -437,6 +439,7 @@ impl ItemizedBlock { let space_to_sigil = line.chars().take_while(|c| c.is_whitespace()).count(); let indent = space_to_sigil + 2; ItemizedBlock { + lines: vec![line[indent..].to_string()], indent, opener: line[..indent].to_string(), line_start: " ".repeat(indent), @@ -456,10 +459,32 @@ impl ItemizedBlock { } } - /// Returns true if the line is part of the current itemized block - fn in_block(&self, line: &str) -> bool { - !ItemizedBlock::is_itemized_line(line) + /// Returns true if the line is part of the current itemized block. + /// If it is, then it is added to the internal lines vec. + fn add_line(&mut self, line: &str) -> bool { + if !ItemizedBlock::is_itemized_line(line) && self.indent <= line.chars().take_while(|c| c.is_whitespace()).count() + { + self.lines.push(line.to_string()); + return true; + } + false + } + + /// Returns the block as a string, with each line trimmed at the start. + fn trimmed_block_as_string(&self) -> String { + self.lines + .iter() + .map(|line| format!("{} ", line.trim_start())) + .collect::() + } + + /// Returns the block as a string under its original form + fn original_block_as_string(&self) -> String { + self.lines + .iter() + .map(|line| format!("{}\n", line)) + .collect::() } } @@ -468,7 +493,6 @@ struct CommentRewrite<'a> { code_block_buffer: String, is_prev_line_multi_line: bool, code_block_attr: Option, - item_block_buffer: String, item_block: Option, comment_line_separator: String, indent_str: String, @@ -506,7 +530,6 @@ impl<'a> CommentRewrite<'a> { code_block_buffer: String::with_capacity(128), is_prev_line_multi_line: false, code_block_attr: None, - item_block_buffer: String::with_capacity(128), item_block: None, comment_line_separator: format!("{}{}", indent_str, line_start), max_chars, @@ -556,17 +579,14 @@ impl<'a> CommentRewrite<'a> { )); } - if !self.item_block_buffer.is_empty() { + if let Some(ref ib) = self.item_block { // the last few lines are part of an itemized block self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); - let mut ib = None; - ::std::mem::swap(&mut ib, &mut self.item_block); - let ib = ib.unwrap(); let item_fmt = ib.create_string_format(&self.fmt); self.result.push_str(&self.comment_line_separator); self.result.push_str(&ib.opener); match rewrite_string( - &self.item_block_buffer.replace("\n", " "), + &ib.trimmed_block_as_string(), &item_fmt, self.max_chars.saturating_sub(ib.indent), ) { @@ -575,7 +595,7 @@ impl<'a> CommentRewrite<'a> { &format!("{}{}", &self.comment_line_separator, ib.line_start), )), None => self.result.push_str(&Self::join_block( - &self.item_block_buffer, + &ib.original_block_as_string(), &self.comment_line_separator, )), }; @@ -599,10 +619,8 @@ impl<'a> CommentRewrite<'a> { ) -> bool { let is_last = i == count_newlines(orig); - if let Some(ref ib) = self.item_block { - if ib.in_block(&line) { - self.item_block_buffer.push_str(line.trim_start()); - self.item_block_buffer.push('\n'); + if let Some(ref mut ib) = self.item_block { + if ib.add_line(&line) { return false; } self.is_prev_line_multi_line = false; @@ -611,7 +629,7 @@ impl<'a> CommentRewrite<'a> { self.result.push_str(&self.comment_line_separator); self.result.push_str(&ib.opener); match rewrite_string( - &self.item_block_buffer.replace("\n", " "), + &ib.trimmed_block_as_string(), &item_fmt, self.max_chars.saturating_sub(ib.indent), ) { @@ -620,11 +638,10 @@ impl<'a> CommentRewrite<'a> { &format!("{}{}", &self.comment_line_separator, ib.line_start), )), None => self.result.push_str(&Self::join_block( - &self.item_block_buffer, + &ib.original_block_as_string(), &self.comment_line_separator, )), }; - self.item_block_buffer.clear(); } else if self.code_block_attr.is_some() { if line.starts_with("```") { let code_block = match self.code_block_attr.as_ref().unwrap() { @@ -664,8 +681,6 @@ impl<'a> CommentRewrite<'a> { self.code_block_attr = Some(CodeBlockAttribute::new(&line[3..])) } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) { let ib = ItemizedBlock::new(&line); - self.item_block_buffer.push_str(&line[ib.indent..]); - self.item_block_buffer.push('\n'); self.item_block = Some(ib); return false; } -- cgit 1.4.1-3-g733a5 From fd27eabbb7350a3b413f33728ae315be2e184825 Mon Sep 17 00:00:00 2001 From: kngwyu Date: Sat, 8 Dec 2018 14:39:52 +0900 Subject: Update rustc-ap-syntax to 306.0 --- Cargo.lock | 99 +++++++++++++++++++++++++-------------------------------- Cargo.toml | 6 ++-- src/closures.rs | 6 ++-- src/macros.rs | 5 ++- src/types.rs | 2 +- src/utils.rs | 15 +++++++-- 6 files changed, 65 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 61a61013fa0..661f5178f18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,7 +172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ena" -version = "0.9.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,17 +346,6 @@ dependencies = [ "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot_core" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" version = "0.3.1" @@ -460,20 +449,20 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -483,17 +472,16 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -503,34 +491,34 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -538,29 +526,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "297.0.0" +version = "306.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -629,9 +617,9 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -873,7 +861,7 @@ dependencies = [ "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" -"checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621" +"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" @@ -896,7 +884,6 @@ dependencies = [ "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -909,15 +896,15 @@ dependencies = [ "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" "checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" -"checksum rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b69fd4a0e8a3ecd99b497965d05f6f04dd2e4601a6146a841dbe4c8e77c2b30c" -"checksum rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8136418dbc491bab74aa0565eaa2086754a7a81a5e74a1d84d6168d18e889e7" -"checksum rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a972feda82332d1d05b1ba5a097e915cd9c9c8f1af2bd7b08af09fb88c753d5f" -"checksum rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "582584c6c48b0ece4b8aef3f9bb59d94d17c5665612bc87a71f509e45a3113b5" -"checksum rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd852096944d0ac6af1aefa9639a2ae6dede217606ce97f88ff0dcc8c86d6ff6" -"checksum rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98301a272ecfeec29d2d4e97b07238707c2b89d86fc3a4a5f31a00728f14e288" -"checksum rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f13510e617e2e322e3297038fd6a7346f2297124af9e10e33a627c5d544e9d" -"checksum rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0792f5a9ccfc5ec13bb5b0472fa49e145481029c39f6bf5b1a36decc99c3328f" -"checksum rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0df9f97f41650d23b14f92f7267f8c61089655efb4533d82bf8991f99245198d" +"checksum rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfb540c1347a3993060896b18e0d64084203fa37aaffdc5e5c31264f275d476" +"checksum rustc-ap-graphviz 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "790ac657d5bf69be9ef56f6810e8a0238b07e8460a88526e11d41f8214eb6c4e" +"checksum rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b721cf32b543f3ee90240d7b757ca4a45930fe9981458a50678b4ccd75c472e2" +"checksum rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4fa11df199d45ce948b07792ca593f59c1d19d2cb05d35c6b0a02271e772a416" +"checksum rustc-ap-rustc_errors 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7ead3163ef995bbba520b88739e1d60f9ccf74fdacdda985067644c8134e827" +"checksum rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "688fef9cc27837755019b72b4f13e7a3d3e5012473475f377b75dbb1f07beb5f" +"checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737" +"checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a" +"checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" diff --git a/Cargo.toml b/Cargo.toml index 3c93e26c714..34c330ac219 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.5" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.6" -rustc-ap-rustc_target = "297.0.0" -rustc-ap-syntax = "297.0.0" -rustc-ap-syntax_pos = "297.0.0" +rustc-ap-rustc_target = "306.0.0" +rustc-ap-syntax = "306.0.0" +rustc-ap-syntax_pos = "306.0.0" failure = "0.1.1" bytecount = "0.4" diff --git a/src/closures.rs b/src/closures.rs index fa656cc351e..e29a412a515 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -20,7 +20,7 @@ use overflow::OverflowableItem; use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use source_map::SpanUtils; -use utils::{last_line_width, left_most_sub_expr, stmt_expr}; +use utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; // This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. @@ -150,11 +150,11 @@ fn rewrite_closure_with_block( let block = ast::Block { stmts: vec![ast::Stmt { - id: ast::NodeId::new(0), + id: ast::NodeId::root(), node: ast::StmtKind::Expr(ptr::P(body.clone())), span: body.span, }], - id: ast::NodeId::new(0), + id: ast::NodeId::root(), rules: ast::BlockCheckMode::Default, span: body.span, recovered: false, diff --git a/src/macros.rs b/src/macros.rs index 8d3b45da0d2..2a4774149ca 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -42,7 +42,7 @@ use source_map::SpanUtils; use spanned::Spanned; use utils::{ format_visibility, is_empty_line, mk_sp, remove_trailing_white_spaces, rewrite_ident, - trim_left_preserve_layout, wrap_str, + trim_left_preserve_layout, wrap_str, NodeIdExt, }; use visitor::FmtVisitor; @@ -1102,7 +1102,6 @@ fn next_space(tok: &Token) -> SpaceState { | Token::DotDot | Token::DotDotDot | Token::DotDotEq - | Token::DotEq | Token::Question => SpaceState::Punctuation, Token::ModSep @@ -1127,7 +1126,7 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option usize { width } +pub(crate) trait NodeIdExt { + fn root() -> Self; +} + +impl NodeIdExt for NodeId { + fn root() -> NodeId { + NodeId::placeholder_from_mark(Mark::root()) + } +} + #[cfg(test)] mod test { use super::*; -- cgit 1.4.1-3-g733a5 From 10b9afa9061899f5e2db4be864655ee9d3a110d4 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 8 Dec 2018 22:32:35 +0100 Subject: Add test asserting we catch Rust parser panics --- src/test/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 599f83cd49c..77abc3c8558 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -288,6 +288,18 @@ fn stdin_formatting_smoke_test() { assert_eq!(buf, "fn main() {}\r\n".as_bytes()); } +#[test] +fn stdin_parser_panic_caught() { + // https://github.com/rust-lang/rustfmt/issues/3239 + for text in ["{", "}"].iter().cloned().map(String::from) { + let mut buf = vec![]; + let mut session = Session::new(Default::default(), Some(&mut buf)); + let _ = session.format(Input::Text(text)); + + assert!(session.has_parsing_errors()); + } +} + #[test] fn stdin_disable_all_formatting_test() { match option_env!("CFG_RELEASE_CHANNEL") { -- cgit 1.4.1-3-g733a5 From a2042a64700840310be96041e039877383db14f2 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 8 Dec 2018 23:22:23 +0100 Subject: Use non-panicking maybe_parser_from_source_str --- src/formatting.rs | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 039276ba6e8..326059c7357 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -8,7 +8,7 @@ use std::time::{Duration, Instant}; use syntax::ast; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; -use syntax::errors::Handler; +use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use syntax::source_map::{FilePathMapping, SourceMap, Span}; @@ -604,22 +604,33 @@ fn parse_crate( ) -> Result { let input_is_stdin = input.is_text(); - let mut parser = match input { - Input::File(file) => parse::new_parser_from_file(parse_session, &file), - Input::Text(text) => parse::new_parser_from_source_str( + let parser = match input { + Input::File(file) => Ok(parse::new_parser_from_file(parse_session, &file)), + Input::Text(text) => parse::maybe_new_parser_from_source_str( parse_session, syntax::source_map::FileName::Custom("stdin".to_owned()), text, - ), + ) + .map_err(|diags| { + diags + .into_iter() + .map(|d| DiagnosticBuilder::new_diagnostic(&parse_session.span_diagnostic, d)) + .collect::>() + }), }; - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } + let result = match parser { + Ok(mut parser) => { + parser.cfg_mods = false; + if config.skip_children() { + parser.recurse_into_file_modules = false; + } - let mut parser = AssertUnwindSafe(parser); - let result = catch_unwind(move || parser.0.parse_crate_mod()); + let mut parser = AssertUnwindSafe(parser); + catch_unwind(move || parser.0.parse_crate_mod().map_err(|d| vec![d])) + } + Err(db) => Ok(Err(db)), + }; match result { Ok(Ok(c)) => { @@ -627,7 +638,7 @@ fn parse_crate( return Ok(c); } } - Ok(Err(mut e)) => e.emit(), + Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(|d| d.emit()), Err(_) => { // Note that if you see this message and want more information, // then run the `parse_crate_mod` function above without -- cgit 1.4.1-3-g733a5 From c7ee2a2857b0b8f1346bb02aabf19ce46184530f Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 13 Dec 2018 13:34:01 +0100 Subject: Don't ignore parse error when constructing report --- src/formatting.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 326059c7357..f909086f0e0 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -73,7 +73,12 @@ fn format_project( let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let mut parse_session = make_parse_sess(source_map.clone(), config); let mut report = FormatReport::new(); - let krate = parse_crate(input, &parse_session, config, &mut report)?; + let krate = match parse_crate(input, &parse_session, config, &mut report) { + Ok(krate) => krate, + // Surface parse error via Session (errors are merged there from report) + Err(ErrorKind::ParseError) => return Ok(report), + Err(e) => return Err(e), + }; timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. -- cgit 1.4.1-3-g733a5 From b73a602d6e7e5567fe591c1c2dc5b99f09388272 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 14 Dec 2018 09:48:20 +0100 Subject: version-gate the trailing semicolon change of return statements inside a match arm --- src/matches.rs | 13 +++++++------ tests/source/issue-3213.rs | 7 ------- tests/source/issue-3213/version_one.rs | 9 +++++++++ tests/source/issue-3213/version_two.rs | 9 +++++++++ tests/target/issue-3213.rs | 11 ----------- tests/target/issue-3213/version_one.rs | 13 +++++++++++++ tests/target/issue-3213/version_two.rs | 13 +++++++++++++ 7 files changed, 51 insertions(+), 24 deletions(-) delete mode 100644 tests/source/issue-3213.rs create mode 100644 tests/source/issue-3213/version_one.rs create mode 100644 tests/source/issue-3213/version_two.rs delete mode 100644 tests/target/issue-3213.rs create mode 100644 tests/target/issue-3213/version_one.rs create mode 100644 tests/target/issue-3213/version_two.rs (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 56d2cc5c598..14733eece86 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -17,7 +17,7 @@ use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; use comment::{combine_strs_with_missing_comments, rewrite_comment}; -use config::{Config, ControlBraceStyle, IndentStyle}; +use config::{Config, ControlBraceStyle, IndentStyle, Version}; use expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, rewrite_multiple_patterns, ExprType, RhsTactics, @@ -413,11 +413,12 @@ fn rewrite_match_body( } else { "" }; - let semicolon = if semicolon_for_expr(context, body) { - ";" - } else { - "" - }; + let semicolon = + if context.config.version() == Version::Two && semicolon_for_expr(context, body) { + ";" + } else { + "" + }; ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) } else { ("", String::from(",")) diff --git a/tests/source/issue-3213.rs b/tests/source/issue-3213.rs deleted file mode 100644 index a00ec4d3661..00000000000 --- a/tests/source/issue-3213.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn foo() { - match 0 { - 0 => return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - 1 => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, - _ => "", - }; -} diff --git a/tests/source/issue-3213/version_one.rs b/tests/source/issue-3213/version_one.rs new file mode 100644 index 00000000000..f9f4cab55e3 --- /dev/null +++ b/tests/source/issue-3213/version_one.rs @@ -0,0 +1,9 @@ +// rustfmt-version: One + +fn foo() { + match 0 { + 0 => return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + 1 => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + _ => "", + }; +} diff --git a/tests/source/issue-3213/version_two.rs b/tests/source/issue-3213/version_two.rs new file mode 100644 index 00000000000..0f068c19d74 --- /dev/null +++ b/tests/source/issue-3213/version_two.rs @@ -0,0 +1,9 @@ +// rustfmt-version: Two + +fn foo() { + match 0 { + 0 => return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + 1 => AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, + _ => "", + }; +} diff --git a/tests/target/issue-3213.rs b/tests/target/issue-3213.rs deleted file mode 100644 index bd2ee48138a..00000000000 --- a/tests/target/issue-3213.rs +++ /dev/null @@ -1,11 +0,0 @@ -fn foo() { - match 0 { - 0 => { - return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - } - 1 => { - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - } - _ => "", - }; -} diff --git a/tests/target/issue-3213/version_one.rs b/tests/target/issue-3213/version_one.rs new file mode 100644 index 00000000000..307903b128b --- /dev/null +++ b/tests/target/issue-3213/version_one.rs @@ -0,0 +1,13 @@ +// rustfmt-version: One + +fn foo() { + match 0 { + 0 => { + return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + 1 => { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + _ => "", + }; +} diff --git a/tests/target/issue-3213/version_two.rs b/tests/target/issue-3213/version_two.rs new file mode 100644 index 00000000000..de93d04ba95 --- /dev/null +++ b/tests/target/issue-3213/version_two.rs @@ -0,0 +1,13 @@ +// rustfmt-version: Two + +fn foo() { + match 0 { + 0 => { + return AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; + } + 1 => { + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + } + _ => "", + }; +} -- cgit 1.4.1-3-g733a5 From 836562baf4342668f22be0ca5f1b02cfc2adc988 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Thu, 13 Dec 2018 22:46:09 +0100 Subject: remove deprecated dependency assert_cli --- Cargo.lock | 36 ------------------------------------ Cargo.toml | 1 - src/test/mod.rs | 15 ++++++--------- 3 files changed, 6 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 369e0e02b6f..6991e6e7b8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,19 +14,6 @@ dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "assert_cli" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "colored 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "atty" version = "0.2.11" @@ -106,14 +93,6 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "colored" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.2.0" @@ -160,11 +139,6 @@ name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "difference" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "either" version = "1.5.0" @@ -190,11 +164,6 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "environment" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "error-chain" version = "0.12.0" @@ -604,7 +573,6 @@ dependencies = [ name = "rustfmt-nightly" version = "1.0.1" dependencies = [ - "assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -842,7 +810,6 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" -"checksum assert_cli 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a29ab7c0ed62970beb0534d637a8688842506d0ff9157de83286dacd065c8149" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" @@ -853,17 +820,14 @@ dependencies = [ "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum colored 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc0a60679001b62fb628c4da80e574b9645ab4646056d7c9018885efffe45533" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" diff --git a/Cargo.toml b/Cargo.toml index c598a417a72..7281ce5efdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,5 +60,4 @@ bytecount = "0.4" rustc-workspace-hack = "1.0.0" [dev-dependencies] -assert_cli = "0.6" lazy_static = "1.0.0" diff --git a/src/test/mod.rs b/src/test/mod.rs index 599f83cd49c..e2c2380bc2a 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate assert_cli; - use std::collections::{HashMap, HashSet}; use std::env; use std::fs; @@ -973,11 +971,10 @@ fn rustfmt() -> PathBuf { #[test] fn verify_check_works() { let temp_file = make_temp_file("temp_check.rs"); - assert_cli::Assert::command(&[ - rustfmt().to_str().unwrap(), - "--check", - temp_file.path.to_str().unwrap(), - ]) - .succeeds() - .unwrap(); + + Command::new(rustfmt().to_str().unwrap()) + .arg("--check") + .arg(temp_file.path.to_str().unwrap()) + .status() + .expect("run with check option failed"); } -- cgit 1.4.1-3-g733a5 From 653f3ae63690c9a1a37b72a49bfbe1d0384c5919 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Thu, 13 Dec 2018 22:49:22 +0100 Subject: use the rustfmt function to find the bin makes it possible to execute the test after a release build --- src/test/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index e2c2380bc2a..d54245c78c9 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -293,7 +293,7 @@ fn stdin_disable_all_formatting_test() { _ => return, // these tests require nightly } let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); - let mut child = Command::new("./target/debug/rustfmt") + let mut child = Command::new(rustfmt().to_str().unwrap()) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .arg("--config-path=./tests/config/disable_all_formatting.toml") -- cgit 1.4.1-3-g733a5 From d0785954c846dbfdc9116084a731ccd44b0205ce Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 18 Dec 2018 03:21:31 +0100 Subject: Fix trim_right/trim_left deprecation warnings (#3252) --- build.rs | 2 +- src/comment.rs | 73 ++++++++++++++++++++++++++++------------------------- src/expr.rs | 4 +-- src/imports.rs | 2 +- src/items.rs | 8 +++--- src/lists.rs | 6 ++--- src/macros.rs | 2 +- src/missed_spans.rs | 4 +-- src/pairs.rs | 6 ++--- src/string.rs | 12 ++++----- src/types.rs | 4 +-- src/utils.rs | 2 +- src/vertical.rs | 6 ++--- 13 files changed, 68 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index 3f1c412a7af..adccd083807 100644 --- a/build.rs +++ b/build.rs @@ -36,7 +36,7 @@ fn main() { fn commit_info() -> String { match (channel(), commit_hash(), commit_date()) { (channel, Some(hash), Some(date)) => { - format!("{} ({} {})", channel, hash.trim_right(), date) + format!("{} ({} {})", channel, hash.trim_end(), date) } _ => String::new(), } diff --git a/src/comment.rs b/src/comment.rs index d126e89f3bc..6f229414e0d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -291,7 +291,7 @@ fn identify_comment( let mut hbl = false; for line in orig.lines() { - let trimmed_line = line.trim_left(); + let trimmed_line = line.trim_start(); if trimmed_line.is_empty() { hbl = true; break; @@ -308,22 +308,22 @@ fn identify_comment( let (has_bare_lines, first_group_ending) = match style { CommentStyle::DoubleSlash | CommentStyle::TripleSlash | CommentStyle::Doc => { - let line_start = style.line_start().trim_left(); + let line_start = style.line_start().trim_start(); consume_same_line_comments(style, orig, line_start) } CommentStyle::Custom(opener) => { - let trimmed_opener = opener.trim_right(); + let trimmed_opener = opener.trim_end(); consume_same_line_comments(style, orig, trimmed_opener) } // for a block comment, search for the closing symbol CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { - let closer = style.closer().trim_left(); + let closer = style.closer().trim_start(); let mut closing_symbol_offset = 0; let mut hbl = false; let mut first = true; for line in orig.lines() { closing_symbol_offset += compute_len(&orig[closing_symbol_offset..], line); - let mut trimmed_line = line.trim_left(); + let mut trimmed_line = line.trim_start(); if !trimmed_line.starts_with('*') && !trimmed_line.starts_with("//") && !trimmed_line.starts_with("/*") @@ -333,7 +333,7 @@ fn identify_comment( // Remove opener from consideration when searching for closer if first { - let opener = style.opener().trim_right(); + let opener = style.opener().trim_end(); trimmed_line = &trimmed_line[opener.len()..]; first = false; } @@ -367,22 +367,27 @@ fn identify_comment( if rest.is_empty() { Some(rewritten_first_group) } else { - identify_comment(rest.trim_left(), block_style, shape, config, is_doc_comment).map( - |rest_str| { - format!( - "{}\n{}{}{}", - rewritten_first_group, - // insert back the blank line - if has_bare_lines && style.is_line_comment() { - "\n" - } else { - "" - }, - shape.indent.to_string(config), - rest_str - ) - }, + identify_comment( + rest.trim_start(), + block_style, + shape, + config, + is_doc_comment, ) + .map(|rest_str| { + format!( + "{}\n{}{}{}", + rewritten_first_group, + // insert back the blank line + if has_bare_lines && style.is_line_comment() { + "\n" + } else { + "" + }, + shape.indent.to_string(config), + rest_str + ) + }) } } @@ -427,7 +432,7 @@ struct ItemizedBlock { impl ItemizedBlock { /// Returns true if the line is formatted as an item fn is_itemized_line(line: &str) -> bool { - let trimmed = line.trim_left(); + let trimmed = line.trim_start(); trimmed.starts_with("* ") || trimmed.starts_with("- ") } @@ -537,7 +542,7 @@ impl<'a> CommentRewrite<'a> { while let Some(line) = iter.next() { result.push_str(line); result.push_str(match iter.peek() { - Some(next_line) if next_line.is_empty() => sep.trim_right(), + Some(next_line) if next_line.is_empty() => sep.trim_end(), Some(..) => &sep, None => "", }); @@ -757,15 +762,15 @@ fn rewrite_comment_inner( ) -> Option { let mut rewriter = CommentRewrite::new(orig, block_style, shape, config); - let line_breaks = count_newlines(orig.trim_right()); + let line_breaks = count_newlines(orig.trim_end()); let lines = orig .lines() .enumerate() .map(|(i, mut line)| { - line = trim_right_unless_two_whitespaces(line.trim_left(), is_doc_comment); + line = trim_end_unless_two_whitespaces(line.trim_start(), is_doc_comment); // Drop old closer. if i == line_breaks && line.ends_with("*/") && !line.starts_with("//") { - line = line[..(line.len() - 2)].trim_right(); + line = line[..(line.len() - 2)].trim_end(); } line @@ -774,7 +779,7 @@ fn rewrite_comment_inner( .map(|(line, has_leading_whitespace)| { if orig.starts_with("/*") && line_breaks == 0 { ( - line.trim_left(), + line.trim_start(), has_leading_whitespace || config.normalize_comments(), ) } else { @@ -794,7 +799,7 @@ fn rewrite_comment_inner( const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; fn hide_sharp_behind_comment(s: &str) -> Cow { - if s.trim_left().starts_with("# ") { + if s.trim_start().starts_with("# ") { Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s)) } else { Cow::from(s) @@ -804,9 +809,9 @@ fn hide_sharp_behind_comment(s: &str) -> Cow { fn trim_custom_comment_prefix(s: &str) -> String { s.lines() .map(|line| { - let left_trimmed = line.trim_left(); + let left_trimmed = line.trim_start(); if left_trimmed.starts_with(RUSTFMT_CUSTOM_COMMENT_PREFIX) { - left_trimmed.trim_left_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX) + left_trimmed.trim_start_matches(RUSTFMT_CUSTOM_COMMENT_PREFIX) } else { line } @@ -866,11 +871,11 @@ pub fn recover_missing_comment_in_span( } /// Trim trailing whitespaces unless they consist of two or more whitespaces. -fn trim_right_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str { +fn trim_end_unless_two_whitespaces(s: &str, is_doc_comment: bool) -> &str { if is_doc_comment && s.ends_with(" ") { s } else { - s.trim_right() + s.trim_end() } } @@ -898,7 +903,7 @@ fn light_rewrite_comment( "" }; // Preserve markdown's double-space line break syntax in doc comment. - trim_right_unless_two_whitespaces(left_trimmed, is_doc_comment) + trim_end_unless_two_whitespaces(left_trimmed, is_doc_comment) }) .collect(); lines.join(&format!("\n{}", offset.to_string(config))) @@ -918,7 +923,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, if line.starts_with(opener) { (&line[opener.len()..], true) } else { - (&line[opener.trim_right().len()..], false) + (&line[opener.trim_end().len()..], false) } } else if line.starts_with("/* ") || line.starts_with("// ") diff --git a/src/expr.rs b/src/expr.rs index 5d0383ddcb2..9509f0f4980 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1252,12 +1252,12 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt format!( "{}{}", new_indent.to_string(context.config), - line.trim_left() + line.trim_start() ) }) .collect::>() .join("\n") - .trim_left(), + .trim_start(), ); return wrap_str(indented_string_lit, context.config.max_width(), shape); } else { diff --git a/src/imports.rs b/src/imports.rs index 14233661227..f8721456aa7 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -50,7 +50,7 @@ impl<'a> FmtVisitor<'a> { Some(ref s) if s.is_empty() => { // Format up to last newline let prev_span = mk_sp(self.last_pos, source!(self, span).lo()); - let trimmed_snippet = self.snippet(prev_span).trim_right(); + let trimmed_snippet = self.snippet(prev_span).trim_end(); let span_end = self.last_pos + BytePos(trimmed_snippet.len() as u32); self.format_missing(span_end); // We have an excessive newline from the removed import. diff --git a/src/items.rs b/src/items.rs index a4800e9ee01..8298ffee7fa 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1249,7 +1249,7 @@ pub fn format_struct_struct( { result.push('\n'); result.push_str(&offset.to_string(context.config)); - result.push_str(generics_str.trim_left()); + result.push_str(generics_str.trim_start()); } else { result.push_str(&generics_str); } @@ -1493,7 +1493,7 @@ fn rewrite_type_item( result.push_str(suffix); } else { result.push_str(&indent.to_string_with_newline(context.config)); - result.push_str(suffix.trim_left()); + result.push_str(suffix.trim_start()); } // 1 = ";" @@ -1619,7 +1619,7 @@ pub fn rewrite_struct_field( let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?; // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. let field_str = if is_prefix_empty { - field_str.trim_left() + field_str.trim_start() } else { &field_str }; @@ -1986,7 +1986,7 @@ fn rewrite_fn_base( let snuggle_angle_bracket = generics_str .lines() .last() - .map_or(false, |l| l.trim_left().len() == 1); + .map_or(false, |l| l.trim_start().len() == 1); // Note that the width and indent don't really matter, we'll re-layout the // return type later anyway. diff --git a/src/lists.rs b/src/lists.rs index 61fe6c24960..eebebfcf306 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -177,11 +177,11 @@ impl ListItem { pub fn has_single_line_comment(&self) -> bool { self.pre_comment .as_ref() - .map_or(false, |comment| comment.trim_left().starts_with("//")) + .map_or(false, |comment| comment.trim_start().starts_with("//")) || self .post_comment .as_ref() - .map_or(false, |comment| comment.trim_left().starts_with("//")) + .map_or(false, |comment| comment.trim_start().starts_with("//")) } pub fn has_comment(&self) -> bool { @@ -463,7 +463,7 @@ where || comment.trim().len() > width; rewrite_comment( - comment.trim_left(), + comment.trim_start(), block_style, comment_shape, formatting.config, diff --git a/src/macros.rs b/src/macros.rs index 2a4774149ca..9ce5c913ca5 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1290,7 +1290,7 @@ impl MacroBranch { // Indent the body since it is in a block. let indent_str = body_indent.to_string(&config); - let mut new_body = LineClasses::new(new_body.trim_right()) + let mut new_body = LineClasses::new(new_body.trim_end()) .enumerate() .fold( (String::new(), true), diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 3c67108b1f1..d414527a61b 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -63,7 +63,7 @@ impl<'a> FmtVisitor<'a> { pub fn format_missing_with_indent(&mut self, end: BytePos) { let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { - this.push_str(last_snippet.trim_right()); + this.push_str(last_snippet.trim_end()); if last_snippet == snippet && !this.output_at_start() { // No new lines in the snippet. this.push_str("\n"); @@ -75,7 +75,7 @@ impl<'a> FmtVisitor<'a> { pub fn format_missing_no_indent(&mut self, end: BytePos) { self.format_missing_inner(end, |this, last_snippet, _| { - this.push_str(last_snippet.trim_right()); + this.push_str(last_snippet.trim_end()); }) } diff --git a/src/pairs.rs b/src/pairs.rs index 360a9964f70..609c425ef4b 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -184,7 +184,7 @@ where { let tab_spaces = context.config.tab_spaces(); let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), + SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_end().len(), SeparatorPlace::Front => shape.used_width(), }; let lhs_shape = Shape { @@ -238,8 +238,8 @@ where } }; let infix = match separator_place { - SeparatorPlace::Back => pp.infix.trim_right(), - SeparatorPlace::Front => pp.infix.trim_left(), + SeparatorPlace::Back => pp.infix.trim_end(), + SeparatorPlace::Front => pp.infix.trim_start(), }; if separator_place == SeparatorPlace::Front { rhs_shape = rhs_shape.offset_left(infix.len())?; diff --git a/src/string.rs b/src/string.rs index 561d96813b0..668324b4d8f 100644 --- a/src/string.rs +++ b/src/string.rs @@ -107,7 +107,7 @@ pub fn rewrite_string<'a>( for (i, grapheme) in graphemes[cur_start..].iter().enumerate() { if is_line_feed(grapheme) { // take care of blank lines - result = trim_right_but_line_feed(fmt.trim_end, result); + result = trim_end_but_line_feed(fmt.trim_end, result); result.push_str("\n"); if !is_bareline_ok && cur_start + i + 1 < graphemes.len() { result.push_str(&indent_without_newline); @@ -117,7 +117,7 @@ pub fn rewrite_string<'a>( result.push_str(grapheme); } } - result = trim_right_but_line_feed(fmt.trim_end, result); + result = trim_end_but_line_feed(fmt.trim_end, result); break; } @@ -138,7 +138,7 @@ pub fn rewrite_string<'a>( } SnippetState::EndWithLineFeed(line, len) => { if line == "\n" && fmt.trim_end { - result = result.trim_right().to_string(); + result = result.trim_end().to_string(); } result.push_str(&line); if is_bareline_ok { @@ -188,11 +188,11 @@ fn detect_url(s: &[&str], index: usize) -> Option { } /// Trims whitespaces to the right except for the line feed character. -fn trim_right_but_line_feed(trim_end: bool, result: String) -> String { +fn trim_end_but_line_feed(trim_end: bool, result: String) -> String { let whitespace_except_line_feed = |c: char| c.is_whitespace() && c != '\n'; if trim_end && result.ends_with(whitespace_except_line_feed) { result - .trim_right_matches(whitespace_except_line_feed) + .trim_end_matches(whitespace_except_line_feed) .to_string() } else { result @@ -244,7 +244,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] if i <= index_minus_ws { let mut line = &input[0..i].concat()[..]; if trim_end { - line = line.trim_right(); + line = line.trim_end(); } return SnippetState::EndWithLineFeed(format!("{}\n", line), i + 1); } diff --git a/src/types.rs b/src/types.rs index 1c2c386932a..d27d1f13f98 100644 --- a/src/types.rs +++ b/src/types.rs @@ -399,7 +399,7 @@ where "{}\n{}{}", args, list_shape.indent.to_string(context.config), - output.trim_left() + output.trim_start() )) } } @@ -422,7 +422,7 @@ impl Rewrite for ast::WherePredicate { .. }) => { let type_str = bounded_ty.rewrite(context, shape)?; - let colon = type_bound_colon(context).trim_right(); + let colon = type_bound_colon(context).trim_end(); let lhs = if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, bound_generic_params) { diff --git a/src/utils.rs b/src/utils.rs index 7f1bc284180..a6a46df6ddc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -514,7 +514,7 @@ pub fn remove_trailing_white_spaces(text: &str) -> String { /// ``` pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Option { let mut lines = LineClasses::new(orig); - let first_line = lines.next().map(|(_, s)| s.trim_right().to_owned())?; + let first_line = lines.next().map(|(_, s)| s.trim_end().to_owned())?; let mut trimmed_lines = Vec::with_capacity(16); let mut veto_trim = false; diff --git a/src/vertical.rs b/src/vertical.rs index 0364db763f9..61272e7db02 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -141,14 +141,14 @@ pub fn rewrite_with_alignment( ); let snippet = context.snippet(missing_span); - if snippet.trim_left().starts_with("//") { + if snippet.trim_start().starts_with("//") { let offset = snippet.lines().next().map_or(0, |l| l.len()); // 2 = "," + "\n" init_hi + BytePos(offset as u32 + 2) - } else if snippet.trim_left().starts_with("/*") { + } else if snippet.trim_start().starts_with("/*") { let comment_lines = snippet .lines() - .position(|line| line.trim_right().ends_with("*/")) + .position(|line| line.trim_end().ends_with("*/")) .unwrap_or(0); let offset = snippet -- cgit 1.4.1-3-g733a5 From e3052624933f779e93b287578a61b501f59143a1 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 19 Dec 2018 09:25:04 +0100 Subject: clarify the version-gate used for the #3229 change --- src/matches.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 14733eece86..5d3b2dd548b 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -413,12 +413,15 @@ fn rewrite_match_body( } else { "" }; - let semicolon = - if context.config.version() == Version::Two && semicolon_for_expr(context, body) { + let semicolon = if context.config.version() == Version::One { + "" + } else { + if semicolon_for_expr(context, body) { ";" } else { "" - }; + } + }; ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) } else { ("", String::from(",")) -- cgit 1.4.1-3-g733a5 From 49568d7f76226aac5f7a641848a2251618079230 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 20 Dec 2018 01:14:14 +0900 Subject: Do not modify original source code inside macro call --- src/closures.rs | 3 ++- src/types.rs | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index e29a412a515..008b884bcb2 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -59,7 +59,7 @@ pub fn rewrite_closure( } let result = match fn_decl.output { - ast::FunctionRetTy::Default(_) => { + ast::FunctionRetTy::Default(_) if !context.inside_macro() => { try_rewrite_without_block(body, &prefix, context, shape, body_shape) } _ => None, @@ -306,6 +306,7 @@ pub fn rewrite_last_closure( let body = match body.node { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) + && !context.inside_macro() && is_simple_block(block, Some(&body.attrs), context.source_map) => { stmt_expr(&block.stmts[0]).unwrap_or(body) diff --git a/src/types.rs b/src/types.rs index d27d1f13f98..8cfba778a48 100644 --- a/src/types.rs +++ b/src/types.rs @@ -583,7 +583,13 @@ impl Rewrite for ast::Ty { let is_dyn = tobj_syntax == ast::TraitObjectSyntax::Dyn; // 4 is length of 'dyn ' let shape = if is_dyn { shape.offset_left(4)? } else { shape }; - let res = bounds.rewrite(context, shape)?; + let mut res = bounds.rewrite(context, shape)?; + // We may have falsely removed a trailing `+` inside macro call. + if context.inside_macro() && bounds.len() == 1 { + if context.snippet(self.span).ends_with('+') && !res.ends_with('+') { + res.push('+'); + } + } if is_dyn { Some(format!("dyn {}", res)) } else { -- cgit 1.4.1-3-g733a5 From f3f511af1b0937cd64f739976cdcf485d0e3e2e0 Mon Sep 17 00:00:00 2001 From: Shohei Wada Date: Mon, 24 Dec 2018 06:12:28 +0900 Subject: Fix #2973 in Windows CRLF env. --- src/comment.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 6f229414e0d..89f9258fd7a 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1304,7 +1304,13 @@ impl<'a> Iterator for LineClasses<'a> { None => FullCodeCharKind::Normal, }; - while let Some((kind, c)) = self.base.next() { + while let Some((kind, mut c)) = self.base.next() { + // If \r\n newline appears, consume one more character. + // Then do the same process with the single \n case. + if c == '\r' && self.base.peek().map_or(false, |(_, c2)| *c2 == '\n') { + self.base.next(); + c = '\n'; + } if c == '\n' { self.kind = match (start_class, kind) { (FullCodeCharKind::Normal, FullCodeCharKind::InString) => { -- cgit 1.4.1-3-g733a5 From e37f468b218f11096173538774c77c483006efdd Mon Sep 17 00:00:00 2001 From: Shohei Wada Date: Mon, 24 Dec 2018 07:25:15 +0900 Subject: Change \r detection much simpler. --- src/comment.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 89f9258fd7a..635ee9a85f2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1304,13 +1304,7 @@ impl<'a> Iterator for LineClasses<'a> { None => FullCodeCharKind::Normal, }; - while let Some((kind, mut c)) = self.base.next() { - // If \r\n newline appears, consume one more character. - // Then do the same process with the single \n case. - if c == '\r' && self.base.peek().map_or(false, |(_, c2)| *c2 == '\n') { - self.base.next(); - c = '\n'; - } + while let Some((kind, c)) = self.base.next() { if c == '\n' { self.kind = match (start_class, kind) { (FullCodeCharKind::Normal, FullCodeCharKind::InString) => { @@ -1327,6 +1321,11 @@ impl<'a> Iterator for LineClasses<'a> { } } + // Workaround for CRLF newline. + if line.ends_with('\r') { + line.pop(); + } + Some((self.kind, line)) } } -- cgit 1.4.1-3-g733a5 From d504a66076339a32e5b35de26020771b74564345 Mon Sep 17 00:00:00 2001 From: Shohei Wada Date: Mon, 24 Dec 2018 17:48:42 +0900 Subject: Remove a trivial redundant code. self.base.peek().is_none() case is already catched by the line above. --- src/comment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 6f229414e0d..7d7f56f54a5 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1301,7 +1301,7 @@ impl<'a> Iterator for LineClasses<'a> { let start_class = match self.base.peek() { Some((kind, _)) => *kind, - None => FullCodeCharKind::Normal, + None => unreachable!(), }; while let Some((kind, c)) = self.base.next() { -- cgit 1.4.1-3-g733a5 From 09c9cd41256c8232274534189a0dffde2656f447 Mon Sep 17 00:00:00 2001 From: wada314 Date: Tue, 25 Dec 2018 18:03:48 +0900 Subject: Fix issue #3263 (#3264) --- src/string.rs | 13 +++++++------ tests/target/format_strings/issue-3263.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 tests/target/format_strings/issue-3263.rs (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 668324b4d8f..c2e136d9938 100644 --- a/src/string.rs +++ b/src/string.rs @@ -105,7 +105,7 @@ pub fn rewrite_string<'a>( // All the input starting at cur_start fits on the current line if graphemes.len() - cur_start <= cur_max_chars { for (i, grapheme) in graphemes[cur_start..].iter().enumerate() { - if is_line_feed(grapheme) { + if is_new_line(grapheme) { // take care of blank lines result = trim_end_but_line_feed(fmt.trim_end, result); result.push_str("\n"); @@ -223,7 +223,7 @@ enum SnippetState { } fn not_whitespace_except_line_feed(g: &str) -> bool { - is_line_feed(g) || !is_whitespace(g) + is_new_line(g) || !is_whitespace(g) } /// Break the input string at a boundary character around the offset `max_chars`. A boundary @@ -240,7 +240,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] // line. If there is one, then text after it could be rewritten in a way that the available // space is fully used. for (i, grapheme) in input[0..=index].iter().enumerate() { - if is_line_feed(grapheme) { + if is_new_line(grapheme) { if i <= index_minus_ws { let mut line = &input[0..i].concat()[..]; if trim_end { @@ -254,7 +254,7 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] let mut index_plus_ws = index; for (i, grapheme) in input[index + 1..].iter().enumerate() { - if !trim_end && is_line_feed(grapheme) { + if !trim_end && is_new_line(grapheme) { return SnippetState::EndWithLineFeed( input[0..=index + 1 + i].concat(), index + 2 + i, @@ -325,8 +325,9 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] } } -fn is_line_feed(grapheme: &str) -> bool { - grapheme.as_bytes()[0] == b'\n' +fn is_new_line(grapheme: &str) -> bool { + let bytes = grapheme.as_bytes(); + bytes.starts_with(b"\n") || bytes.starts_with(b"\r\n") } fn is_whitespace(grapheme: &str) -> bool { diff --git a/tests/target/format_strings/issue-3263.rs b/tests/target/format_strings/issue-3263.rs new file mode 100644 index 00000000000..72f7e9cc627 --- /dev/null +++ b/tests/target/format_strings/issue-3263.rs @@ -0,0 +1,26 @@ +// rustfmt-format_strings: true +// rustfmt-newline_style: Windows + +#[test] +fn compile_empty_program() { + let result = get_result(); + let expected = "; ModuleID = \'foo\' + +; Function Attrs: nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0 + +declare i32 @write(i32, i8*, i32) + +declare i32 @putchar(i32) + +declare i32 @getchar() + +define i32 @main() { +entry: + ret i32 0 +} + +attributes #0 = { nounwind } +"; + assert_eq!(result, CString::new(expected).unwrap()); +} -- cgit 1.4.1-3-g733a5 From 996d5e8d6ce2e756f50bfa51b9622c50f725415c Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 25 Dec 2018 18:20:29 +0900 Subject: Fix shape when formatting return or break expr on statement position (#3259) --- .travis.yml | 4 ++-- src/expr.rs | 7 ++++++- tests/source/expr.rs | 17 +++++++++++++++++ tests/target/expr.rs | 21 +++++++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/.travis.yml b/.travis.yml index e38ed696d17..f7ed9a61929 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,8 +37,8 @@ matrix: allow_failures: # Doesn't build - seems to be because of an option - env: INTEGRATION=packed_simd - # Test failure - - env: INTEGRATION=rust-clippy + # Doesn't build - a temporal build failure due to breaking changes in the nightly compilre + - env: INTEGRATION=rust-semverver script: - | diff --git a/src/expr.rs b/src/expr.rs index 9509f0f4980..0d8e9c87580 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -41,7 +41,7 @@ use types::{rewrite_path, PathContext}; use utils::{ colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, - semicolon_for_stmt, wrap_str, + semicolon_for_expr, semicolon_for_stmt, wrap_str, }; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -69,6 +69,11 @@ pub fn format_expr( if contains_skip(&*expr.attrs) { return Some(context.snippet(expr.span()).to_owned()); } + let shape = if expr_type == ExprType::Statement && semicolon_for_expr(context, expr) { + shape.sub_width(1)? + } else { + shape + }; let expr_rw = match expr.node { ast::ExprKind::Array(ref expr_vec) => rewrite_array( diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 71c79223221..514f755c698 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -462,3 +462,20 @@ fn issue_3003() { .iter() .collect(); } + +fn issue3226() { + { + { + { + return Err(ErrorKind::ManagementInterfaceError("Server exited unexpectedly").into()) + } + } + } + { + { + { + break Err(ErrorKind::ManagementInterfaceError("Server exited unexpectedlyy").into()) + } + } + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 2730b1c570c..e46cb898232 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -541,3 +541,24 @@ fn issue_3003() { .iter() .collect(); } + +fn issue3226() { + { + { + { + return Err( + ErrorKind::ManagementInterfaceError("Server exited unexpectedly").into(), + ); + } + } + } + { + { + { + break Err( + ErrorKind::ManagementInterfaceError("Server exited unexpectedlyy").into(), + ); + } + } + } +} -- cgit 1.4.1-3-g733a5 From 3b18238009f161c0cd765526076ad4b0b8dc8812 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 25 Dec 2018 23:15:52 +0100 Subject: simplify function to create a string from the itemized block --- src/comment.rs | 5 +---- tests/target/issue-3224.rs | 11 +++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 tests/target/issue-3224.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 2a4db512091..36bdaca19f0 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -481,10 +481,7 @@ impl ItemizedBlock { /// Returns the block as a string under its original form fn original_block_as_string(&self) -> String { - self.lines - .iter() - .map(|line| format!("{}\n", line)) - .collect::() + self.lines.join("\n") } } diff --git a/tests/target/issue-3224.rs b/tests/target/issue-3224.rs new file mode 100644 index 00000000000..6476d2117c6 --- /dev/null +++ b/tests/target/issue-3224.rs @@ -0,0 +1,11 @@ +// rustfmt-wrap_comments: true + +//! Test: +//! * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +//! * [`examples/simple`] – Demonstrates use of the [`init`] API with plain +//! structs. +//! * [`examples/simple_flatbuffer`] – Demonstrates use of the [`init`] API with +//! FlatBuffers. +//! * [`examples/gravity`] – Demonstrates use of the [`RLBot::set_game_state`] +//! API +fn foo() {} -- cgit 1.4.1-3-g733a5 From a8d2591f0c722d66a9a2bffbee6de4a7fee2df45 Mon Sep 17 00:00:00 2001 From: David Hewson Date: Tue, 1 Jan 2019 17:49:55 +0000 Subject: allow specifying package with -p currently `cargo fmt -p blah` is rejected but `cargo fmt --package blah` is allowed. both should be allowed --- src/cargo-fmt/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index b2496565885..ec67a0cd984 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -56,7 +56,7 @@ fn execute() -> i32 { let mut is_package_arg = false; for arg in env::args().skip(2).take_while(|a| a != "--") { if arg.starts_with('-') { - is_package_arg = arg.starts_with("--package"); + is_package_arg = arg.starts_with("--package") | arg.starts_with("-p"); } else if !is_package_arg { print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); return FAILURE; -- cgit 1.4.1-3-g733a5 From baa62c609e421c4518070958df9ef721c20857e1 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 10 Jan 2019 14:25:07 +0100 Subject: recognize strings inside comments in order to avoid indenting them Close #3270 --- src/comment.rs | 84 +++++++++++++++++++++++++++++++++-------- src/utils.rs | 15 +++++--- tests/source/issue-3132.rs | 13 ------- tests/source/issue-3270.rs | 10 +++++ tests/target/issue-3132.rs | 10 ++--- tests/target/issue-3270-wrap.rs | 10 +++++ tests/target/issue-3270.rs | 10 +++++ 7 files changed, 114 insertions(+), 38 deletions(-) delete mode 100644 tests/source/issue-3132.rs create mode 100644 tests/source/issue-3270.rs create mode 100644 tests/target/issue-3270-wrap.rs create mode 100644 tests/target/issue-3270.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 492b03c045a..ef63bf464bc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1029,21 +1029,28 @@ impl RichChar for (usize, char) { #[derive(PartialEq, Eq, Debug, Clone, Copy)] enum CharClassesStatus { Normal, + /// Character is within a string LitString, LitStringEscape, + /// Character is within a raw string LitRawString(u32), RawStringPrefix(u32), RawStringSuffix(u32), LitChar, LitCharEscape, - // The u32 is the nesting deepness of the comment + /// Character inside a block comment, with the integer indicating the nesting deepness of the + /// comment BlockComment(u32), - // Status when the '/' has been consumed, but not yet the '*', deepness is - // the new deepness (after the comment opening). + /// Character inside a block-commented string, with the integer indicating the nesting deepness + /// of the comment + StringInBlockComment(u32), + /// Status when the '/' has been consumed, but not yet the '*', deepness is + /// the new deepness (after the comment opening). BlockCommentOpening(u32), - // Status when the '*' has been consumed, but not yet the '/', deepness is - // the new deepness (after the comment closing). + /// Status when the '*' has been consumed, but not yet the '/', deepness is + /// the new deepness (after the comment closing). BlockCommentClosing(u32), + /// Character is within a line comment LineComment, } @@ -1067,6 +1074,12 @@ pub enum FullCodeCharKind { InComment, /// Last character of a comment, '\n' for a line comment, '/' for a block comment. EndComment, + /// Start of a mutlitine string inside a comment + StartStringCommented, + /// End of a mutlitine string inside a comment + EndStringCommented, + /// Inside a commented string + InStringCommented, /// Start of a mutlitine string StartString, /// End of a mutlitine string @@ -1080,7 +1093,21 @@ impl FullCodeCharKind { match self { FullCodeCharKind::StartComment | FullCodeCharKind::InComment - | FullCodeCharKind::EndComment => true, + | FullCodeCharKind::EndComment + | FullCodeCharKind::StartStringCommented + | FullCodeCharKind::InStringCommented + | FullCodeCharKind::EndStringCommented => true, + _ => false, + } + } + + /// Returns true if the character is inside a comment + pub fn inside_comment(self) -> bool { + match self { + FullCodeCharKind::InComment + | FullCodeCharKind::StartStringCommented + | FullCodeCharKind::InStringCommented + | FullCodeCharKind::EndStringCommented => true, _ => false, } } @@ -1089,6 +1116,12 @@ impl FullCodeCharKind { self == FullCodeCharKind::InString || self == FullCodeCharKind::StartString } + /// Returns true if the character is within a commented string + pub fn is_commented_string(self) -> bool { + self == FullCodeCharKind::InStringCommented + || self == FullCodeCharKind::StartStringCommented + } + fn to_codecharkind(self) -> CodeCharKind { if self.is_comment() { CodeCharKind::Comment @@ -1232,18 +1265,27 @@ where }, _ => CharClassesStatus::Normal, }, + CharClassesStatus::StringInBlockComment(deepness) => { + char_kind = FullCodeCharKind::InStringCommented; + if chr == '"' { + CharClassesStatus::BlockComment(deepness) + } else { + CharClassesStatus::StringInBlockComment(deepness) + } + } CharClassesStatus::BlockComment(deepness) => { assert_ne!(deepness, 0); - self.status = match self.base.peek() { + char_kind = FullCodeCharKind::InComment; + match self.base.peek() { Some(next) if next.get_char() == '/' && chr == '*' => { CharClassesStatus::BlockCommentClosing(deepness - 1) } Some(next) if next.get_char() == '*' && chr == '/' => { CharClassesStatus::BlockCommentOpening(deepness + 1) } - _ => CharClassesStatus::BlockComment(deepness), - }; - return Some((FullCodeCharKind::InComment, item)); + _ if chr == '"' => CharClassesStatus::StringInBlockComment(deepness), + _ => self.status, + } } CharClassesStatus::BlockCommentOpening(deepness) => { assert_eq!(chr, '*'); @@ -1299,26 +1341,33 @@ impl<'a> Iterator for LineClasses<'a> { let mut line = String::new(); - let start_class = match self.base.peek() { + let start_kind = match self.base.peek() { Some((kind, _)) => *kind, None => unreachable!(), }; while let Some((kind, c)) = self.base.next() { + // needed to set the kind of the ending character on the last line + self.kind = kind; if c == '\n' { - self.kind = match (start_class, kind) { + self.kind = match (start_kind, kind) { (FullCodeCharKind::Normal, FullCodeCharKind::InString) => { FullCodeCharKind::StartString } (FullCodeCharKind::InString, FullCodeCharKind::Normal) => { FullCodeCharKind::EndString } + (FullCodeCharKind::InComment, FullCodeCharKind::InStringCommented) => { + FullCodeCharKind::StartStringCommented + } + (FullCodeCharKind::InStringCommented, FullCodeCharKind::InComment) => { + FullCodeCharKind::EndStringCommented + } _ => kind, }; break; - } else { - line.push(c); } + line.push(c); } // Workaround for CRLF newline. @@ -1364,7 +1413,12 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { } FullCodeCharKind::StartComment => { // Consume the whole comment - while let Some((FullCodeCharKind::InComment, (_, _))) = self.iter.next() {} + loop { + match self.iter.next() { + Some((kind, ..)) if kind.inside_comment() => continue, + _ => break, + } + } } _ => panic!(), } diff --git a/src/utils.rs b/src/utils.rs index a6a46df6ddc..dd480f9788f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -527,8 +527,10 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Some(get_prefix_space_width(config, &line)) }; - let line = if veto_trim || (kind.is_string() && !line.ends_with('\\')) { - veto_trim = kind.is_string() && !line.ends_with('\\'); + let new_veto_trim_value = + (kind.is_string() || kind.is_commented_string()) && !line.ends_with('\\'); + let line = if veto_trim || new_veto_trim_value { + veto_trim = new_veto_trim_value; trimmed = false; line } else { @@ -536,10 +538,13 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> }; trimmed_lines.push((trimmed, line, prefix_space_width)); - // When computing the minimum, do not consider lines within a string. - // The reason is there is a veto against trimming and indenting such lines + // Because there is a veto against trimming and indenting lines within a string, + // such lines should not be taken into account when computing the minimum. match kind { - FullCodeCharKind::InString | FullCodeCharKind::EndString => None, + FullCodeCharKind::InString + | FullCodeCharKind::EndString + | FullCodeCharKind::InStringCommented + | FullCodeCharKind::EndStringCommented => None, _ => prefix_space_width, } }) diff --git a/tests/source/issue-3132.rs b/tests/source/issue-3132.rs deleted file mode 100644 index a43b83223e2..00000000000 --- a/tests/source/issue-3132.rs +++ /dev/null @@ -1,13 +0,0 @@ -fn test() { - /* - a - */ - let x = 42; - /* - aaa - "line 1 - line 2 - line 3" - */ - let x = 42; -} diff --git a/tests/source/issue-3270.rs b/tests/source/issue-3270.rs new file mode 100644 index 00000000000..9b1a66a63b7 --- /dev/null +++ b/tests/source/issue-3270.rs @@ -0,0 +1,10 @@ +pub fn main() { + /* let s = String::from( + " +hello +world +", + ); */ + + assert_eq!(s, "\nhello\nworld\n"); +} diff --git a/tests/target/issue-3132.rs b/tests/target/issue-3132.rs index 42388e09f74..c3d24fc10f6 100644 --- a/tests/target/issue-3132.rs +++ b/tests/target/issue-3132.rs @@ -4,10 +4,10 @@ fn test() { */ let x = 42; /* - aaa - "line 1 - line 2 - line 3" - */ + aaa + "line 1 + line 2 + line 3" + */ let x = 42; } diff --git a/tests/target/issue-3270-wrap.rs b/tests/target/issue-3270-wrap.rs new file mode 100644 index 00000000000..e27f71aa32f --- /dev/null +++ b/tests/target/issue-3270-wrap.rs @@ -0,0 +1,10 @@ +// rustfmt-wrap_comments: true + +fn func() { + let x = 42; + /* + let something = "one line line line line line line line line line line line line + two lines + three lines"; + */ +} diff --git a/tests/target/issue-3270.rs b/tests/target/issue-3270.rs new file mode 100644 index 00000000000..4f624f1193b --- /dev/null +++ b/tests/target/issue-3270.rs @@ -0,0 +1,10 @@ +pub fn main() { + /* let s = String::from( + " +hello +world +", + ); */ + + assert_eq!(s, "\nhello\nworld\n"); +} -- cgit 1.4.1-3-g733a5 From a01990c4d0f6415a1e4824cf109125effacaaa81 Mon Sep 17 00:00:00 2001 From: wada314 Date: Tue, 15 Jan 2019 08:41:09 +0900 Subject: Use Unicode-standard char width to wrap comments or strings. (#3275) --- Cargo.lock | 8 +++++ Cargo.toml | 2 ++ src/comment.rs | 40 +++++++++++++--------- src/lib.rs | 2 ++ src/overflow.rs | 3 +- src/string.rs | 70 ++++++++++++++++++++++++-------------- src/utils.rs | 34 ++++++++++-------- tests/source/comment6.rs | 10 ++++++ tests/source/string_punctuation.rs | 2 ++ tests/target/comment6.rs | 14 ++++++++ tests/target/string_punctuation.rs | 10 ++++++ 11 files changed, 136 insertions(+), 59 deletions(-) create mode 100644 tests/source/comment6.rs create mode 100644 tests/target/comment6.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 6991e6e7b8f..ef4b6fd92a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -595,6 +595,8 @@ dependencies = [ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -748,6 +750,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "1.0.0" @@ -896,6 +903,7 @@ dependencies = [ "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" diff --git a/Cargo.toml b/Cargo.toml index 7281ce5efdc..9e0bce1dc08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,8 @@ rustc-ap-syntax = "306.0.0" rustc-ap-syntax_pos = "306.0.0" failure = "0.1.1" bytecount = "0.4" +unicode-width = "0.1.5" +unicode_categories = "0.1.1" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/comment.rs b/src/comment.rs index 54c3ee1d9d7..3841424904f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -19,7 +19,9 @@ use config::Config; use rewrite::RewriteContext; use shape::{Indent, Shape}; use string::{rewrite_string, StringFormat}; -use utils::{count_newlines, first_line_width, last_line_width, trim_left_preserve_layout}; +use utils::{ + count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, unicode_str_width, +}; use {ErrorKind, FormattingError}; fn is_custom_comment(comment: &str) -> bool { @@ -264,7 +266,8 @@ fn identify_comment( ) -> Option { let style = comment_style(orig, false); - // Computes the len of line taking into account a newline if the line is part of a paragraph. + // Computes the byte length of line taking into account a newline if the line is part of a + // paragraph. fn compute_len(orig: &str, line: &str) -> usize { if orig.len() > line.len() { if orig.as_bytes()[line.len()] == b'\r' { @@ -498,7 +501,7 @@ struct CommentRewrite<'a> { item_block: Option, comment_line_separator: String, indent_str: String, - max_chars: usize, + max_width: usize, fmt_indent: Indent, fmt: StringFormat<'a>, @@ -520,7 +523,7 @@ impl<'a> CommentRewrite<'a> { comment_style(orig, config.normalize_comments()).to_str_tuplet() }; - let max_chars = shape + let max_width = shape .width .checked_sub(closer.len() + opener.len()) .unwrap_or(1); @@ -534,7 +537,7 @@ impl<'a> CommentRewrite<'a> { code_block_attr: None, item_block: None, comment_line_separator: format!("{}{}", indent_str, line_start), - max_chars, + max_width, indent_str, fmt_indent, @@ -543,7 +546,7 @@ impl<'a> CommentRewrite<'a> { closer: "", line_start, line_end: "", - shape: Shape::legacy(max_chars, fmt_indent), + shape: Shape::legacy(max_width, fmt_indent), trim_end: true, config, }, @@ -583,14 +586,14 @@ impl<'a> CommentRewrite<'a> { if let Some(ref ib) = self.item_block { // the last few lines are part of an itemized block - self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent); let item_fmt = ib.create_string_format(&self.fmt); self.result.push_str(&self.comment_line_separator); self.result.push_str(&ib.opener); match rewrite_string( &ib.trimmed_block_as_string(), &item_fmt, - self.max_chars.saturating_sub(ib.indent), + self.max_width.saturating_sub(ib.indent), ) { Some(s) => self.result.push_str(&Self::join_block( &s, @@ -626,14 +629,14 @@ impl<'a> CommentRewrite<'a> { return false; } self.is_prev_line_multi_line = false; - self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent); let item_fmt = ib.create_string_format(&self.fmt); self.result.push_str(&self.comment_line_separator); self.result.push_str(&ib.opener); match rewrite_string( &ib.trimmed_block_as_string(), &item_fmt, - self.max_chars.saturating_sub(ib.indent), + self.max_width.saturating_sub(ib.indent), ) { Some(s) => self.result.push_str(&Self::join_block( &s, @@ -710,8 +713,11 @@ impl<'a> CommentRewrite<'a> { } } - if self.fmt.config.wrap_comments() && line.len() > self.fmt.shape.width && !has_url(line) { - match rewrite_string(line, &self.fmt, self.max_chars) { + if self.fmt.config.wrap_comments() + && unicode_str_width(line) > self.fmt.shape.width + && !has_url(line) + { + match rewrite_string(line, &self.fmt, self.max_width) { Some(ref s) => { self.is_prev_line_multi_line = s.contains('\n'); self.result.push_str(s); @@ -721,8 +727,8 @@ impl<'a> CommentRewrite<'a> { // Remove the trailing space, then start rewrite on the next line. self.result.pop(); self.result.push_str(&self.comment_line_separator); - self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); - match rewrite_string(line, &self.fmt, self.max_chars) { + self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent); + match rewrite_string(line, &self.fmt, self.max_width) { Some(ref s) => { self.is_prev_line_multi_line = s.contains('\n'); self.result.push_str(s); @@ -743,12 +749,12 @@ impl<'a> CommentRewrite<'a> { // 1 = " " let offset = 1 + last_line_width(&self.result) - self.line_start.len(); Shape { - width: self.max_chars.saturating_sub(offset), + width: self.max_width.saturating_sub(offset), indent: self.fmt_indent, offset: self.fmt.shape.offset + offset, } } else { - Shape::legacy(self.max_chars, self.fmt_indent) + Shape::legacy(self.max_width, self.fmt_indent) }; } else { if line.is_empty() && self.result.ends_with(' ') && !is_last { @@ -756,7 +762,7 @@ impl<'a> CommentRewrite<'a> { self.result.pop(); } self.result.push_str(line); - self.fmt.shape = Shape::legacy(self.max_chars, self.fmt_indent); + self.fmt.shape = Shape::legacy(self.max_width, self.fmt_indent); self.is_prev_line_multi_line = false; } diff --git a/src/lib.rs b/src/lib.rs index 751f9acfd66..ce28fce3182 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,9 @@ extern crate serde_json; extern crate syntax; extern crate syntax_pos; extern crate toml; +extern crate unicode_categories; extern crate unicode_segmentation; +extern crate unicode_width; use std::cell::RefCell; use std::collections::HashMap; diff --git a/src/overflow.rs b/src/overflow.rs index 4a583fc1de8..8c4bac2a8a5 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -431,7 +431,8 @@ impl<'a> Context<'a> { }; if let Some(rewrite) = rewrite { - let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned()); + // splitn(2, *).next().unwrap() is always safe. + let rewrite_first_line = Some(rewrite.splitn(2, '\n').next().unwrap().to_owned()); last_list_item.item = rewrite_first_line; Some(rewrite) } else { diff --git a/src/string.rs b/src/string.rs index c2e136d9938..dc48a6b13fd 100644 --- a/src/string.rs +++ b/src/string.rs @@ -11,11 +11,12 @@ // Format string literals. use regex::Regex; +use unicode_categories::UnicodeCategories; use unicode_segmentation::UnicodeSegmentation; use config::Config; use shape::Shape; -use utils::wrap_str; +use utils::{unicode_str_width, wrap_str}; const MIN_STRING: usize = 10; @@ -53,7 +54,7 @@ impl<'a> StringFormat<'a> { /// indentation into account. /// /// If we cannot put at least a single character per line, the rewrite won't succeed. - fn max_chars_with_indent(&self) -> Option { + fn max_width_with_indent(&self) -> Option { Some( self.shape .width @@ -62,10 +63,10 @@ impl<'a> StringFormat<'a> { ) } - /// Like max_chars_with_indent but the indentation is not subtracted. + /// Like max_width_with_indent but the indentation is not subtracted. /// This allows to fit more graphemes from the string on a line when /// SnippetState::EndWithLineFeed. - fn max_chars_without_indent(&self) -> Option { + fn max_width_without_indent(&self) -> Option { Some(self.config.max_width().checked_sub(self.line_end.len())?) } } @@ -75,8 +76,8 @@ pub fn rewrite_string<'a>( fmt: &StringFormat<'a>, newline_max_chars: usize, ) -> Option { - let max_chars_with_indent = fmt.max_chars_with_indent()?; - let max_chars_without_indent = fmt.max_chars_without_indent()?; + let max_width_with_indent = fmt.max_width_with_indent()?; + let max_width_without_indent = fmt.max_width_without_indent()?; let indent_with_newline = fmt.shape.indent.to_string_with_newline(fmt.config); let indent_without_newline = fmt.shape.indent.to_string(fmt.config); @@ -99,11 +100,11 @@ pub fn rewrite_string<'a>( // Snip a line at a time from `stripped_str` until it is used up. Push the snippet // onto result. - let mut cur_max_chars = max_chars_with_indent; + let mut cur_max_width = max_width_with_indent; let is_bareline_ok = fmt.line_start.is_empty() || is_whitespace(fmt.line_start); loop { // All the input starting at cur_start fits on the current line - if graphemes.len() - cur_start <= cur_max_chars { + if graphemes_width(&graphemes[cur_start..]) <= cur_max_width { for (i, grapheme) in graphemes[cur_start..].iter().enumerate() { if is_new_line(grapheme) { // take care of blank lines @@ -123,7 +124,7 @@ pub fn rewrite_string<'a>( // The input starting at cur_start needs to be broken match break_string( - cur_max_chars, + cur_max_width, fmt.trim_end, fmt.line_end, &graphemes[cur_start..], @@ -133,7 +134,7 @@ pub fn rewrite_string<'a>( result.push_str(fmt.line_end); result.push_str(&indent_with_newline); result.push_str(fmt.line_start); - cur_max_chars = newline_max_chars; + cur_max_width = newline_max_chars; cur_start += len; } SnippetState::EndWithLineFeed(line, len) => { @@ -143,11 +144,11 @@ pub fn rewrite_string<'a>( result.push_str(&line); if is_bareline_ok { // the next line can benefit from the full width - cur_max_chars = max_chars_without_indent; + cur_max_width = max_width_without_indent; } else { result.push_str(&indent_without_newline); result.push_str(fmt.line_start); - cur_max_chars = max_chars_with_indent; + cur_max_width = max_width_with_indent; } cur_start += len; } @@ -226,9 +227,10 @@ fn not_whitespace_except_line_feed(g: &str) -> bool { is_new_line(g) || !is_whitespace(g) } -/// Break the input string at a boundary character around the offset `max_chars`. A boundary +/// Break the input string at a boundary character around the offset `max_width`. A boundary /// character is either a punctuation or a whitespace. -fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str]) -> SnippetState { +/// FIXME(issue#3281): We must follow UAX#14 algorithm instead of this. +fn break_string(max_width: usize, trim_end: bool, line_end: &str, input: &[&str]) -> SnippetState { let break_at = |index /* grapheme at index is included */| { // Take in any whitespaces to the left/right of `input[index]` while // preserving line feeds @@ -272,19 +274,33 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] } }; + // find a first index where the unicode width of input[0..x] become > max_width + let max_width_index_in_input = { + let mut cur_width = 0; + let mut cur_index = 0; + for (i, grapheme) in input.iter().enumerate() { + cur_width += unicode_str_width(grapheme); + cur_index = i; + if cur_width > max_width { + break; + } + } + cur_index + }; + // Find the position in input for breaking the string if line_end.is_empty() && trim_end - && !is_whitespace(input[max_chars - 1]) - && is_whitespace(input[max_chars]) + && !is_whitespace(input[max_width_index_in_input - 1]) + && is_whitespace(input[max_width_index_in_input]) { // At a breaking point already // The line won't invalidate the rewriting because: // - no extra space needed for the line_end character // - extra whitespaces to the right can be trimmed - return break_at(max_chars - 1); + return break_at(max_width_index_in_input - 1); } - if let Some(url_index_end) = detect_url(input, max_chars) { + if let Some(url_index_end) = detect_url(input, max_width_index_in_input) { let index_plus_ws = url_index_end + input[url_index_end..] .iter() @@ -297,14 +313,15 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] return SnippetState::LineEnd(input[..=index_plus_ws].concat(), index_plus_ws + 1); }; } - match input[0..max_chars] + + match input[0..max_width_index_in_input] .iter() .rposition(|grapheme| is_whitespace(grapheme)) { // Found a whitespace and what is on its left side is big enough. Some(index) if index >= MIN_STRING => break_at(index), // No whitespace found, try looking for a punctuation instead - _ => match input[0..max_chars] + _ => match input[0..max_width_index_in_input] .iter() .rposition(|grapheme| is_punctuation(grapheme)) { @@ -312,12 +329,12 @@ fn break_string(max_chars: usize, trim_end: bool, line_end: &str, input: &[&str] Some(index) if index >= MIN_STRING => break_at(index), // Either no boundary character was found to the left of `input[max_chars]`, or the line // got too small. We try searching for a boundary character to the right. - _ => match input[max_chars..] + _ => match input[max_width_index_in_input..] .iter() .position(|grapheme| is_whitespace(grapheme) || is_punctuation(grapheme)) { // A boundary was found after the line limit - Some(index) => break_at(max_chars + index), + Some(index) => break_at(max_width_index_in_input + index), // No boundary to the right, the input cannot be broken None => SnippetState::EndOfInput(input.concat()), }, @@ -335,10 +352,11 @@ fn is_whitespace(grapheme: &str) -> bool { } fn is_punctuation(grapheme: &str) -> bool { - match grapheme.as_bytes()[0] { - b':' | b',' | b';' | b'.' => true, - _ => false, - } + grapheme.chars().all(|c| c.is_punctuation_other()) +} + +fn graphemes_width(graphemes: &[&str]) -> usize { + graphemes.iter().map(|s| unicode_str_width(s)).sum() } #[cfg(test)] diff --git a/src/utils.rs b/src/utils.rs index a6a46df6ddc..9efe57e7277 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -26,6 +26,8 @@ use config::Config; use rewrite::RewriteContext; use shape::{Indent, Shape}; +use unicode_width::UnicodeWidthStr; + pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; @@ -193,19 +195,13 @@ pub fn is_attributes_extendable(attrs_str: &str) -> bool { // The width of the first line in s. #[inline] pub fn first_line_width(s: &str) -> usize { - match s.find('\n') { - Some(n) => n, - None => s.len(), - } + unicode_str_width(s.splitn(2, '\n').next().unwrap_or("")) } // The width of the last line in s. #[inline] pub fn last_line_width(s: &str) -> usize { - match s.rfind('\n') { - Some(n) => s.len() - n - 1, - None => s.len(), - } + unicode_str_width(s.rsplitn(2, '\n').next().unwrap_or("")) } // The total used width of the last line. @@ -214,16 +210,16 @@ pub fn last_line_used_width(s: &str, offset: usize) -> usize { if s.contains('\n') { last_line_width(s) } else { - offset + s.len() + offset + unicode_str_width(s) } } #[inline] pub fn trimmed_last_line_width(s: &str) -> usize { - match s.rfind('\n') { - Some(n) => s[(n + 1)..].trim().len(), - None => s.trim().len(), - } + unicode_str_width(match s.rfind('\n') { + Some(n) => s[(n + 1)..].trim(), + None => s.trim(), + }) } #[inline] @@ -370,11 +366,15 @@ fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { return false; } // If the snippet does not include newline, we are done. - if first_line_width(snippet) == snippet.len() { + if is_single_line(snippet) { return true; } // The other lines must fit within the maximum width. - if snippet.lines().skip(1).any(|line| line.len() > max_width) { + if snippet + .lines() + .skip(1) + .any(|line| unicode_str_width(line) > max_width) + { return false; } // A special check for the last line, since the caller may @@ -593,6 +593,10 @@ impl NodeIdExt for NodeId { } } +pub(crate) fn unicode_str_width(s: &str) -> usize { + s.width() +} + #[cfg(test)] mod test { use super::*; diff --git a/tests/source/comment6.rs b/tests/source/comment6.rs new file mode 100644 index 00000000000..e5d72113ce6 --- /dev/null +++ b/tests/source/comment6.rs @@ -0,0 +1,10 @@ +// rustfmt-wrap_comments: true + +// Pendant la nuit du 9 mars 1860, les nuages, se confondant avec la mer, limitaient à quelques brasses la portée de la vue. +// Sur cette mer démontée, dont les lames déferlaient en projetant des lueurs livides, un léger bâtiment fuyait presque à sec de toile. + +pub mod foo {} + +// ゆく河の流れは絶えずして、しかももとの水にあらず。淀みに浮かぶうたかたは、かつ消えかつ結びて、久しくとどまりたるためしなし。世の中にある人とすみかと、またかくのごとし。 + +pub mod bar {} diff --git a/tests/source/string_punctuation.rs b/tests/source/string_punctuation.rs index efbadebb083..552c461ed34 100644 --- a/tests/source/string_punctuation.rs +++ b/tests/source/string_punctuation.rs @@ -4,4 +4,6 @@ fn main() { println!("ThisIsAReallyLongStringWithNoSpaces.It_should_prefer_to_break_onpunctuation:Likethisssssssssssss"); format!("{}__{}__{}ItShouldOnlyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyNoticeSemicolonsPeriodsColonsAndCommasAndResortToMid-CharBreaksAfterPunctuation{}{}",x,y,z,a,b); println!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaalhijalfhiigjapdighjapdigjapdighdapighapdighpaidhg;adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea"); + println!("sentuhaesnuthaesnutheasunteahusnaethuseantuihaesntdiastnidaetnuhaideuhsenathe。WeShouldSupportNonAsciiPunctuations§ensuhatheasunteahsuneathusneathuasnuhaesnuhaesnuaethusnaetuheasnuth"); + println!("ThisIsASampleOfCJKString.祇園精舍の鐘の声、諸行無常の響きあり。娑羅双樹の花の色、盛者必衰の理をあらはす。奢れる人も久しからず、ただ春の夜の夢のごとし。猛き者もつひにはほろびぬ、ひとへに風の前の塵に同じ。"); } diff --git a/tests/target/comment6.rs b/tests/target/comment6.rs new file mode 100644 index 00000000000..565fee632f5 --- /dev/null +++ b/tests/target/comment6.rs @@ -0,0 +1,14 @@ +// rustfmt-wrap_comments: true + +// Pendant la nuit du 9 mars 1860, les nuages, se confondant avec la mer, +// limitaient à quelques brasses la portée de la vue. Sur cette mer démontée, +// dont les lames déferlaient en projetant des lueurs livides, un léger bâtiment +// fuyait presque à sec de toile. + +pub mod foo {} + +// ゆく河の流れは絶えずして、しかももとの水にあらず。淀みに浮かぶうたかたは、 +// かつ消えかつ結びて、久しくとどまりたるためしなし。世の中にある人とすみかと、 +// またかくのごとし。 + +pub mod bar {} diff --git a/tests/target/string_punctuation.rs b/tests/target/string_punctuation.rs index 5e574a400cc..0b8ec1b7f39 100644 --- a/tests/target/string_punctuation.rs +++ b/tests/target/string_punctuation.rs @@ -11,4 +11,14 @@ fn main() { adopgihadoguaadbadgad,qeoihapethae8t0aet8haetadbjtaeg;\ ooeouthaoeutgadlgajduabgoiuadogabudogubaodugbadgadgadga;adoughaoeugbaouea" ); + println!( + "sentuhaesnuthaesnutheasunteahusnaethuseantuihaesntdiastnidaetnuhaideuhsenathe。\ + WeShouldSupportNonAsciiPunctuations§\ + ensuhatheasunteahsuneathusneathuasnuhaesnuhaesnuaethusnaetuheasnuth" + ); + println!( + "ThisIsASampleOfCJKString.祇園精舍の鐘の声、諸行無常の響きあり。娑羅双樹の花の色、\ + 盛者必衰の理をあらはす。奢れる人も久しからず、ただ春の夜の夢のごとし。\ + 猛き者もつひにはほろびぬ、ひとへに風の前の塵に同じ。" + ); } -- cgit 1.4.1-3-g733a5 From 083a20fb1aee4daef685735652ae21e9b370350d Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 16 Jan 2019 23:06:28 +0100 Subject: version-gate the formatting of commented strings --- src/utils.rs | 17 ++++++++++------- tests/source/issue-3270.rs | 10 ---------- tests/source/issue-3270/one.rs | 12 ++++++++++++ tests/source/issue-3270/two.rs | 12 ++++++++++++ tests/target/issue-3132.rs | 2 ++ tests/target/issue-3270-wrap.rs | 10 ---------- tests/target/issue-3270.rs | 10 ---------- tests/target/issue-3270/one.rs | 12 ++++++++++++ tests/target/issue-3270/two.rs | 12 ++++++++++++ tests/target/issue-3270/wrap.rs | 13 +++++++++++++ 10 files changed, 73 insertions(+), 37 deletions(-) delete mode 100644 tests/source/issue-3270.rs create mode 100644 tests/source/issue-3270/one.rs create mode 100644 tests/source/issue-3270/two.rs delete mode 100644 tests/target/issue-3270-wrap.rs delete mode 100644 tests/target/issue-3270.rs create mode 100644 tests/target/issue-3270/one.rs create mode 100644 tests/target/issue-3270/two.rs create mode 100644 tests/target/issue-3270/wrap.rs (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index dd480f9788f..2f357d7e359 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -22,7 +22,7 @@ use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use syntax_pos::Mark; use comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; -use config::Config; +use config::{Config, Version}; use rewrite::RewriteContext; use shape::{Indent, Shape}; @@ -527,8 +527,9 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Some(get_prefix_space_width(config, &line)) }; - let new_veto_trim_value = - (kind.is_string() || kind.is_commented_string()) && !line.ends_with('\\'); + let new_veto_trim_value = (kind.is_string() + || (config.version() == Version::Two && kind.is_commented_string())) + && !line.ends_with('\\'); let line = if veto_trim || new_veto_trim_value { veto_trim = new_veto_trim_value; trimmed = false; @@ -541,10 +542,12 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> // Because there is a veto against trimming and indenting lines within a string, // such lines should not be taken into account when computing the minimum. match kind { - FullCodeCharKind::InString - | FullCodeCharKind::EndString - | FullCodeCharKind::InStringCommented - | FullCodeCharKind::EndStringCommented => None, + FullCodeCharKind::InStringCommented | FullCodeCharKind::EndStringCommented + if config.version() == Version::Two => + { + None + } + FullCodeCharKind::InString | FullCodeCharKind::EndString => None, _ => prefix_space_width, } }) diff --git a/tests/source/issue-3270.rs b/tests/source/issue-3270.rs deleted file mode 100644 index 9b1a66a63b7..00000000000 --- a/tests/source/issue-3270.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub fn main() { - /* let s = String::from( - " -hello -world -", - ); */ - - assert_eq!(s, "\nhello\nworld\n"); -} diff --git a/tests/source/issue-3270/one.rs b/tests/source/issue-3270/one.rs new file mode 100644 index 00000000000..3c2e27e2293 --- /dev/null +++ b/tests/source/issue-3270/one.rs @@ -0,0 +1,12 @@ +// rustfmt-version: One + +pub fn main() { + /* let s = String::from( + " +hello +world +", + ); */ + + assert_eq!(s, "\nhello\nworld\n"); +} diff --git a/tests/source/issue-3270/two.rs b/tests/source/issue-3270/two.rs new file mode 100644 index 00000000000..0eb756471e7 --- /dev/null +++ b/tests/source/issue-3270/two.rs @@ -0,0 +1,12 @@ +// rustfmt-version: Two + +pub fn main() { + /* let s = String::from( + " +hello +world +", + ); */ + + assert_eq!(s, "\nhello\nworld\n"); +} diff --git a/tests/target/issue-3132.rs b/tests/target/issue-3132.rs index c3d24fc10f6..4dffe0ab836 100644 --- a/tests/target/issue-3132.rs +++ b/tests/target/issue-3132.rs @@ -1,3 +1,5 @@ +// rustfmt-version: Two + fn test() { /* a diff --git a/tests/target/issue-3270-wrap.rs b/tests/target/issue-3270-wrap.rs deleted file mode 100644 index e27f71aa32f..00000000000 --- a/tests/target/issue-3270-wrap.rs +++ /dev/null @@ -1,10 +0,0 @@ -// rustfmt-wrap_comments: true - -fn func() { - let x = 42; - /* - let something = "one line line line line line line line line line line line line - two lines - three lines"; - */ -} diff --git a/tests/target/issue-3270.rs b/tests/target/issue-3270.rs deleted file mode 100644 index 4f624f1193b..00000000000 --- a/tests/target/issue-3270.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub fn main() { - /* let s = String::from( - " -hello -world -", - ); */ - - assert_eq!(s, "\nhello\nworld\n"); -} diff --git a/tests/target/issue-3270/one.rs b/tests/target/issue-3270/one.rs new file mode 100644 index 00000000000..78de9473243 --- /dev/null +++ b/tests/target/issue-3270/one.rs @@ -0,0 +1,12 @@ +// rustfmt-version: One + +pub fn main() { + /* let s = String::from( + " + hello + world + ", + ); */ + + assert_eq!(s, "\nhello\nworld\n"); +} diff --git a/tests/target/issue-3270/two.rs b/tests/target/issue-3270/two.rs new file mode 100644 index 00000000000..e48b5921329 --- /dev/null +++ b/tests/target/issue-3270/two.rs @@ -0,0 +1,12 @@ +// rustfmt-version: Two + +pub fn main() { + /* let s = String::from( + " +hello +world +", + ); */ + + assert_eq!(s, "\nhello\nworld\n"); +} diff --git a/tests/target/issue-3270/wrap.rs b/tests/target/issue-3270/wrap.rs new file mode 100644 index 00000000000..7435c5f0866 --- /dev/null +++ b/tests/target/issue-3270/wrap.rs @@ -0,0 +1,13 @@ +// rustfmt-wrap_comments: true +// rustfmt-version: Two + +// check that a line below max_width does not get over the limit when wrapping +// it in a block comment +fn func() { + let x = 42; + /* + let something = "one line line line line line line line line line line line line line + two lines + three lines"; + */ +} -- cgit 1.4.1-3-g733a5 From a2bfc026e55427296b5044b3b4c427d3e9353956 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 23 Jan 2019 00:01:53 +0100 Subject: keep leading double-colon to respect the 2018 edition of rust's paths --- src/imports.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index f8721456aa7..061d37e86da 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -324,9 +324,8 @@ impl UseTree { attrs, }; - let leading_modsep = context.config.edition() == Edition::Edition2018 - && a.prefix.to_string().len() > 2 - && a.prefix.to_string().starts_with("::"); + let leading_modsep = + context.config.edition() == Edition::Edition2018 && a.prefix.is_global(); let mut modsep = leading_modsep; @@ -367,7 +366,15 @@ impl UseTree { )); } UseTreeKind::Simple(ref rename, ..) => { - let name = rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned(); + // If the path has leading double colons and is composed of only 2 segments, then we + // bypass the call to path_to_imported_ident which would get only the ident and + // lose the path root, e.g., `that` in `::that`. + // The span of `a.prefix` contains the leading colons. + let name = if a.prefix.segments.len() == 2 && leading_modsep { + context.snippet(a.prefix.span).to_owned() + } else { + rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned() + }; let alias = rename.and_then(|ident| { if ident.name == "_" { // for impl-only-use -- cgit 1.4.1-3-g733a5 From 7b996542cc2677523570d0c64daf9c7f1601155f Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Fri, 25 Jan 2019 23:40:12 +0900 Subject: change new line point in the case of no args --- src/items.rs | 10 ++++++++-- tests/source/issue-3278.rs | 3 +++ tests/target/issue-3278.rs | 6 ++++++ tests/target/long-fn-1.rs | 8 ++++---- 4 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 tests/source/issue-3278.rs create mode 100644 tests/target/issue-3278.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 8298ffee7fa..6216c79975e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2064,6 +2064,8 @@ fn rewrite_fn_base( } && !fd.inputs.is_empty(); let mut args_last_line_contains_comment = false; + let mut no_args_and_over_max_width = false; + if put_args_in_block { arg_indent = indent.block_indent(context.config); result.push_str(&arg_indent.to_string_with_newline(context.config)); @@ -2083,10 +2085,12 @@ fn rewrite_fn_base( .lines() .last() .map_or(false, |last_line| last_line.contains("//")); + result.push(')'); + if closing_paren_overflow_max_width || args_last_line_contains_comment { result.push_str(&indent.to_string_with_newline(context.config)); + no_args_and_over_max_width = true; } - result.push(')'); } // Return type. @@ -2126,7 +2130,9 @@ fn rewrite_fn_base( result.push_str(&indent.to_string_with_newline(context.config)); indent } else { - result.push(' '); + if arg_str.len() != 0 || !no_args_and_over_max_width { + result.push(' '); + } Indent::new(indent.block_indent, last_line_width(&result)) }; diff --git a/tests/source/issue-3278.rs b/tests/source/issue-3278.rs new file mode 100644 index 00000000000..f86caafc541 --- /dev/null +++ b/tests/source/issue-3278.rs @@ -0,0 +1,3 @@ +pub fn parse_conditional<'a, I: 'a>() -> impl Parser + 'a +where I: Stream +{} \ No newline at end of file diff --git a/tests/target/issue-3278.rs b/tests/target/issue-3278.rs new file mode 100644 index 00000000000..07219295a7a --- /dev/null +++ b/tests/target/issue-3278.rs @@ -0,0 +1,6 @@ +pub fn parse_conditional<'a, I: 'a>() +-> impl Parser + 'a +where + I: Stream, +{ +} diff --git a/tests/target/long-fn-1.rs b/tests/target/long-fn-1.rs index 5fd605dd315..320617f2772 100644 --- a/tests/target/long-fn-1.rs +++ b/tests/target/long-fn-1.rs @@ -15,14 +15,14 @@ impl Foo { // #1843 #[allow(non_snake_case)] -pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash( -) -> bool { +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash() +-> bool { false } // #3009 impl Something { - fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine( - ) -> Result<(), String> { + fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine() + -> Result<(), String> { } } -- cgit 1.4.1-3-g733a5 From d44ee754385e6385e9afc069f398b3756e616e23 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 26 Jan 2019 00:17:36 +0100 Subject: update dependencies update itertools from 0.7 to 0.8 update env_logger from 0.5 to 0.6 update cargo_metadata from 0.6 to 0.7 update bytecount from 0.4 to 0.5 --- Cargo.lock | 36 ++++++++++++++++++------------------ Cargo.toml | 10 +++++----- src/cargo-fmt/main.rs | 7 ++++++- 3 files changed, 29 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ef4b6fd92a7..64692829bca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytecount" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -154,7 +154,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.13" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -174,16 +174,16 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -224,7 +224,7 @@ dependencies = [ [[package]] name = "itertools" -version = "0.7.11" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -574,14 +574,14 @@ name = "rustfmt-nightly" version = "1.0.1" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -821,9 +821,9 @@ dependencies = [ "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" +"checksum bytecount 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c219c0335c21a8bd79587ce5aee9f64aff1d0bd7a2cca7a58a815f9780cd3b0d" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" -"checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2" +"checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -834,15 +834,15 @@ dependencies = [ "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" -"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" -"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" diff --git a/Cargo.toml b/Cargo.toml index 9e0bce1dc08..039accd0643 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ generic-simd = ["bytecount/generic-simd"] [dependencies] atty = "0.2" -itertools = "0.7" +itertools = "0.8" toml = "0.4" serde = "1.0" serde_derive = "1.0" @@ -44,15 +44,15 @@ regex = "1.0" term = "0.5" diff = "0.1" log = "0.4" -env_logger = "0.5" +env_logger = "0.6" getopts = "0.2" derive-new = "0.5" -cargo_metadata = "0.6" +cargo_metadata = "0.7" rustc-ap-rustc_target = "306.0.0" rustc-ap-syntax = "306.0.0" rustc-ap-syntax_pos = "306.0.0" -failure = "0.1.1" -bytecount = "0.4" +failure = "0.1.3" +bytecount = "0.5" unicode-width = "0.1.5" unicode_categories = "0.1.1" diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index ec67a0cd984..83a93240ff2 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -378,7 +378,12 @@ fn run_rustfmt( } fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { - match cargo_metadata::metadata(manifest_path) { + let mut cmd = cargo_metadata::MetadataCommand::new(); + cmd.no_deps(); + if let Some(manifest_path) = manifest_path { + cmd.manifest_path(manifest_path); + } + match cmd.exec() { Ok(metadata) => Ok(metadata), Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())), } -- cgit 1.4.1-3-g733a5 From f92f3e3bda3550752b2483bb6b6e4c91f24a34f1 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 27 Jan 2019 14:33:03 +0900 Subject: add the version gate to the code and test --- src/items.rs | 24 ++++++++++++++++++------ tests/source/issue-3278.rs | 3 --- tests/source/issue-3278/version_one.rs | 8 ++++++++ tests/source/issue-3278/version_two.rs | 8 ++++++++ tests/source/long-fn-1.rs | 20 -------------------- tests/source/long-fn-1/version_one.rs | 21 +++++++++++++++++++++ tests/source/long-fn-1/version_two.rs | 21 +++++++++++++++++++++ tests/target/issue-3278.rs | 6 ------ tests/target/issue-3278/version_one.rs | 8 ++++++++ tests/target/issue-3278/version_two.rs | 8 ++++++++ tests/target/long-fn-1.rs | 28 ---------------------------- tests/target/long-fn-1/version_one.rs | 29 +++++++++++++++++++++++++++++ tests/target/long-fn-1/version_two.rs | 29 +++++++++++++++++++++++++++++ 13 files changed, 150 insertions(+), 63 deletions(-) delete mode 100644 tests/source/issue-3278.rs create mode 100644 tests/source/issue-3278/version_one.rs create mode 100644 tests/source/issue-3278/version_two.rs delete mode 100644 tests/source/long-fn-1.rs create mode 100644 tests/source/long-fn-1/version_one.rs create mode 100644 tests/source/long-fn-1/version_two.rs delete mode 100644 tests/target/issue-3278.rs create mode 100644 tests/target/issue-3278/version_one.rs create mode 100644 tests/target/issue-3278/version_two.rs delete mode 100644 tests/target/long-fn-1.rs create mode 100644 tests/target/long-fn-1/version_one.rs create mode 100644 tests/target/long-fn-1/version_two.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6216c79975e..a2bf023a33e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -24,7 +24,7 @@ use comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented, }; -use config::{BraceStyle, Config, Density, IndentStyle}; +use config::{BraceStyle, Config, Density, IndentStyle, Version}; use expr::{ format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, ExprType, RhsTactics, @@ -2085,11 +2085,18 @@ fn rewrite_fn_base( .lines() .last() .map_or(false, |last_line| last_line.contains("//")); - result.push(')'); - if closing_paren_overflow_max_width || args_last_line_contains_comment { - result.push_str(&indent.to_string_with_newline(context.config)); - no_args_and_over_max_width = true; + if context.config.version() == Version::Two { + result.push(')'); + if closing_paren_overflow_max_width || args_last_line_contains_comment { + result.push_str(&indent.to_string_with_newline(context.config)); + no_args_and_over_max_width = true; + } + } else { + if closing_paren_overflow_max_width || args_last_line_contains_comment { + result.push_str(&indent.to_string_with_newline(context.config)); + } + result.push(')'); } } @@ -2130,9 +2137,14 @@ fn rewrite_fn_base( result.push_str(&indent.to_string_with_newline(context.config)); indent } else { - if arg_str.len() != 0 || !no_args_and_over_max_width { + if context.config.version() == Version::Two { + if arg_str.len() != 0 || !no_args_and_over_max_width { + result.push(' '); + } + } else { result.push(' '); } + Indent::new(indent.block_indent, last_line_width(&result)) }; diff --git a/tests/source/issue-3278.rs b/tests/source/issue-3278.rs deleted file mode 100644 index f86caafc541..00000000000 --- a/tests/source/issue-3278.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub fn parse_conditional<'a, I: 'a>() -> impl Parser + 'a -where I: Stream -{} \ No newline at end of file diff --git a/tests/source/issue-3278/version_one.rs b/tests/source/issue-3278/version_one.rs new file mode 100644 index 00000000000..580679fbae3 --- /dev/null +++ b/tests/source/issue-3278/version_one.rs @@ -0,0 +1,8 @@ +// rustfmt-version: One + +pub fn parse_conditional<'a, I: 'a>( +) -> impl Parser + 'a +where + I: Stream, +{ +} diff --git a/tests/source/issue-3278/version_two.rs b/tests/source/issue-3278/version_two.rs new file mode 100644 index 00000000000..c17b1742d39 --- /dev/null +++ b/tests/source/issue-3278/version_two.rs @@ -0,0 +1,8 @@ +// rustfmt-version: Two + +pub fn parse_conditional<'a, I: 'a>() +-> impl Parser + 'a +where + I: Stream, +{ +} diff --git a/tests/source/long-fn-1.rs b/tests/source/long-fn-1.rs deleted file mode 100644 index 1f53d78802d..00000000000 --- a/tests/source/long-fn-1.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Tests that a function which is almost short enough, but not quite, gets -// formatted correctly. - -impl Foo { - fn some_input(&mut self, input: Input, input_path: Option, ) -> (Input, Option) {} - - fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) {} -} - -// #1843 -#[allow(non_snake_case)] -pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash() -> bool { - false -} - -// #3009 -impl Something { - fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine( -) -> Result< (), String > {} -} diff --git a/tests/source/long-fn-1/version_one.rs b/tests/source/long-fn-1/version_one.rs new file mode 100644 index 00000000000..d6832c2af09 --- /dev/null +++ b/tests/source/long-fn-1/version_one.rs @@ -0,0 +1,21 @@ +// rustfmt-version: One +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input(&mut self, input: Input, input_path: Option, ) -> (Input, Option) {} + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) {} +} + +// #1843 +#[allow(non_snake_case)] +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash() -> bool { + false +} + +// #3009 +impl Something { + fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine( +) -> Result< (), String > {} +} diff --git a/tests/source/long-fn-1/version_two.rs b/tests/source/long-fn-1/version_two.rs new file mode 100644 index 00000000000..f402a26e8b6 --- /dev/null +++ b/tests/source/long-fn-1/version_two.rs @@ -0,0 +1,21 @@ +// rustfmt-version: Two +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input(&mut self, input: Input, input_path: Option, ) -> (Input, Option) {} + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) {} +} + +// #1843 +#[allow(non_snake_case)] +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash() -> bool { + false +} + +// #3009 +impl Something { + fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine( +) -> Result< (), String > {} +} diff --git a/tests/target/issue-3278.rs b/tests/target/issue-3278.rs deleted file mode 100644 index 07219295a7a..00000000000 --- a/tests/target/issue-3278.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub fn parse_conditional<'a, I: 'a>() --> impl Parser + 'a -where - I: Stream, -{ -} diff --git a/tests/target/issue-3278/version_one.rs b/tests/target/issue-3278/version_one.rs new file mode 100644 index 00000000000..580679fbae3 --- /dev/null +++ b/tests/target/issue-3278/version_one.rs @@ -0,0 +1,8 @@ +// rustfmt-version: One + +pub fn parse_conditional<'a, I: 'a>( +) -> impl Parser + 'a +where + I: Stream, +{ +} diff --git a/tests/target/issue-3278/version_two.rs b/tests/target/issue-3278/version_two.rs new file mode 100644 index 00000000000..c17b1742d39 --- /dev/null +++ b/tests/target/issue-3278/version_two.rs @@ -0,0 +1,8 @@ +// rustfmt-version: Two + +pub fn parse_conditional<'a, I: 'a>() +-> impl Parser + 'a +where + I: Stream, +{ +} diff --git a/tests/target/long-fn-1.rs b/tests/target/long-fn-1.rs deleted file mode 100644 index 320617f2772..00000000000 --- a/tests/target/long-fn-1.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Tests that a function which is almost short enough, but not quite, gets -// formatted correctly. - -impl Foo { - fn some_input( - &mut self, - input: Input, - input_path: Option, - ) -> (Input, Option) { - } - - fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { - } -} - -// #1843 -#[allow(non_snake_case)] -pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash() --> bool { - false -} - -// #3009 -impl Something { - fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine() - -> Result<(), String> { - } -} diff --git a/tests/target/long-fn-1/version_one.rs b/tests/target/long-fn-1/version_one.rs new file mode 100644 index 00000000000..05f69953c26 --- /dev/null +++ b/tests/target/long-fn-1/version_one.rs @@ -0,0 +1,29 @@ +// rustfmt-version: One +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input( + &mut self, + input: Input, + input_path: Option, + ) -> (Input, Option) { + } + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { + } +} + +// #1843 +#[allow(non_snake_case)] +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash( +) -> bool { + false +} + +// #3009 +impl Something { + fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine( + ) -> Result<(), String> { + } +} diff --git a/tests/target/long-fn-1/version_two.rs b/tests/target/long-fn-1/version_two.rs new file mode 100644 index 00000000000..32794bccde2 --- /dev/null +++ b/tests/target/long-fn-1/version_two.rs @@ -0,0 +1,29 @@ +// rustfmt-version: Two +// Tests that a function which is almost short enough, but not quite, gets +// formatted correctly. + +impl Foo { + fn some_input( + &mut self, + input: Input, + input_path: Option, + ) -> (Input, Option) { + } + + fn some_inpu(&mut self, input: Input, input_path: Option) -> (Input, Option) { + } +} + +// #1843 +#[allow(non_snake_case)] +pub extern "C" fn Java_com_exonum_binding_storage_indices_ValueSetIndexProxy_nativeContainsByHash() +-> bool { + false +} + +// #3009 +impl Something { + fn my_function_name_is_way_to_long_but_used_as_a_case_study_or_an_example_its_fine() + -> Result<(), String> { + } +} -- cgit 1.4.1-3-g733a5 From 35d5ef78282ff3011d0a73d40c11ac6bd62dd009 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 27 Jan 2019 16:26:09 +0900 Subject: Apply rustfmt::skip on imports (#3289) --- src/reorder.rs | 8 +++++--- tests/source/imports.rs | 4 ++++ tests/target/imports.rs | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/reorder.rs b/src/reorder.rs index eddc0446035..30b9bbee657 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -10,7 +10,7 @@ //! Reorder items. //! -//! `mod`, `extern crate` and `use` declarations are reorderd in alphabetical +//! `mod`, `extern crate` and `use` declarations are reordered in alphabetical //! order. Trait items are reordered in pre-determined order (associated types //! and constants comes before methods). @@ -28,7 +28,7 @@ use rewrite::{Rewrite, RewriteContext}; use shape::Shape; use source_map::LineRangeUtils; use spanned::Spanned; -use utils::mk_sp; +use utils::{contains_skip, mk_sp}; use visitor::FmtVisitor; use std::cmp::{Ord, Ordering}; @@ -186,7 +186,9 @@ enum ReorderableItemKind { impl ReorderableItemKind { fn from(item: &ast::Item) -> Self { match item.node { - _ if contains_macro_use_attr(item) => ReorderableItemKind::Other, + _ if contains_macro_use_attr(item) | contains_skip(&item.attrs) => { + ReorderableItemKind::Other + } ast::ItemKind::ExternCrate(..) => ReorderableItemKind::ExternCrate, ast::ItemKind::Mod(..) if is_mod_decl(item) => ReorderableItemKind::Mod, ast::ItemKind::Use(..) => ReorderableItemKind::Use, diff --git a/tests/source/imports.rs b/tests/source/imports.rs index 95a789bd1bf..d0bdeda595d 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -101,3 +101,7 @@ use imports_with_attr; // #2888 use std::f64::consts::{SQRT_2, E, PI}; + +// #3273 +#[rustfmt::skip] +use std::fmt::{self, {Display, Formatter}}; diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 36bbc20547c..852c1f5bfe7 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -123,3 +123,7 @@ use imports_with_attr; // #2888 use std::f64::consts::{E, PI, SQRT_2}; + +// #3273 +#[rustfmt::skip] +use std::fmt::{self, {Display, Formatter}}; -- cgit 1.4.1-3-g733a5 From 2125ad272e036c13547e6c6ff8cdfd0188c91fd7 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sun, 27 Jan 2019 12:46:14 +0100 Subject: fix glob and nested global imports --- src/imports.rs | 9 +++++++++ tests/source/issue-3241.rs | 11 +++++++++++ tests/target/issue-3241.rs | 11 +++++++++++ 3 files changed, 31 insertions(+) create mode 100644 tests/source/issue-3241.rs create mode 100644 tests/target/issue-3241.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 061d37e86da..dea8fdf313f 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -338,6 +338,10 @@ impl UseTree { match a.kind { UseTreeKind::Glob => { + // in case of a global path and the glob starts at the root, e.g., "::*" + if a.prefix.segments.len() == 1 && leading_modsep { + result.path.push(UseSegment::Ident("".to_owned(), None)); + } result.path.push(UseSegment::Glob); } UseTreeKind::Nested(ref list) => { @@ -356,6 +360,11 @@ impl UseTree { false, ) .collect(); + // in case of a global path and the nested list starts at the root, + // e.g., "::{foo, bar}" + if a.prefix.segments.len() == 1 && leading_modsep { + result.path.push(UseSegment::Ident("".to_owned(), None)); + } result.path.push(UseSegment::List( list.iter() .zip(items.into_iter()) diff --git a/tests/source/issue-3241.rs b/tests/source/issue-3241.rs new file mode 100644 index 00000000000..090284a21fd --- /dev/null +++ b/tests/source/issue-3241.rs @@ -0,0 +1,11 @@ +// rustfmt-edition: 2018 + +use ::ignore; +use ::ignore::some::more; +use ::{foo, bar}; +use ::*; +use ::baz::{foo, bar}; + +fn main() { + println!("Hello, world!"); +} diff --git a/tests/target/issue-3241.rs b/tests/target/issue-3241.rs new file mode 100644 index 00000000000..60b452abdde --- /dev/null +++ b/tests/target/issue-3241.rs @@ -0,0 +1,11 @@ +// rustfmt-edition: 2018 + +use ::baz::{bar, foo}; +use ::ignore; +use ::ignore::some::more; +use ::*; +use ::{bar, foo}; + +fn main() { + println!("Hello, world!"); +} -- cgit 1.4.1-3-g733a5 From 24daa174ca9a7bfcaec6189af2830b9449801b63 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 7 Jan 2019 20:38:56 +0100 Subject: Look for a global rustfmt.toml. If no rustfmt.toml is found in the usual way, the directory 'rustfmt' in the user's config directory is checked. - $XDG_CONFIG_HOME/rustfmt/ (or $HOME/.config/rustfmt/), or - $HOME/Library/Preferences/rustfmt/ on Mac, or - %AppData%\rustfmt\ on Windows. --- Cargo.lock | 56 +++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/config/config_type.rs | 12 +++++++++- src/lib.rs | 1 + 4 files changed, 69 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 64692829bca..01cb370a89a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,15 @@ dependencies = [ "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "argon2rs" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayvec" version = "0.4.8" @@ -50,6 +59,15 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bytecount" version = "0.5.0" @@ -93,6 +111,11 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "crossbeam-deque" version = "0.2.0" @@ -139,6 +162,16 @@ name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dirs" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.0" @@ -396,6 +429,17 @@ dependencies = [ "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_users" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "1.0.6" @@ -578,6 +622,7 @@ dependencies = [ "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -609,6 +654,11 @@ name = "scoped-tls" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "scopeguard" version = "0.3.3" @@ -816,22 +866,26 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum bytecount 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c219c0335c21a8bd79587ce5aee9f64aff1d0bd7a2cca7a58a815f9780cd3b0d" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" +"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" @@ -865,6 +919,7 @@ dependencies = [ "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" "checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" "checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" "checksum rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfb540c1347a3993060896b18e0d64084203fa37aaffdc5e5c31264f275d476" @@ -884,6 +939,7 @@ dependencies = [ "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" diff --git a/Cargo.toml b/Cargo.toml index 039accd0643..b1e83e93b09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" unicode_categories = "0.1.1" +dirs = "1.0.4" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/config/config_type.rs b/src/config/config_type.rs index b7c1da36017..665afded9da 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -345,9 +345,19 @@ macro_rules! create_config { // If the current directory has no parent, we're done searching. if !current.pop() { - return Ok(None); + break; } } + + // If none was found, check in the global configuration directory. + if let Some(mut config_dir) = dirs::config_dir() { + config_dir.push("rustfmt"); + if let Some(path) = get_toml_path(&config_dir)? { + return Ok(Some(path)); + } + } + + return Ok(None); } match resolve_project_file(dir)? { diff --git a/src/lib.rs b/src/lib.rs index ce28fce3182..a6e531e476b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ extern crate derive_new; extern crate atty; extern crate bytecount; extern crate diff; +extern crate dirs; extern crate failure; extern crate itertools; #[cfg(test)] -- cgit 1.4.1-3-g733a5 From 635a4cdcdcf726aab4b6f7dcb620ffdb33c5e367 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 14 Jan 2019 11:20:46 +0100 Subject: Also look in home directory for global config. --- Configurations.md | 2 +- src/config/config_type.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 4f0be788948..3399f7ff782 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1,6 +1,6 @@ # Configuring Rustfmt -Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, your [global config directory](https://docs.rs/dirs/1.0.4/dirs/fn.config_dir.html) is checked for a folder called `rustfmt`, which may contain a `rustfmt.toml` (e.g. `~/.config/rustfmt/rustfmt.toml`). +Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/1.0.4/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well. A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this: diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 665afded9da..9e58eac52a2 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -349,7 +349,14 @@ macro_rules! create_config { } } - // If none was found, check in the global configuration directory. + // If nothing was found, check in the home directory. + if let Some(home_dir) = dirs::home_dir() { + if let Some(path) = get_toml_path(&home_dir)? { + return Ok(Some(path)); + } + } + + // If none was found ther either, check in the user's configuration directory. if let Some(mut config_dir) = dirs::config_dir() { config_dir.push("rustfmt"); if let Some(path) = get_toml_path(&config_dir)? { -- cgit 1.4.1-3-g733a5 From 5df0a18849b11baf33f9a5ee0cc58e6f3be7e518 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 27 Jan 2019 20:50:16 +0900 Subject: Avoid putting a long macro call in a single line --- src/overflow.rs | 17 +++++++++++------ tests/source/macros.rs | 8 -------- tests/source/single-line-macro/v1.rs | 10 ++++++++++ tests/source/single-line-macro/v2.rs | 10 ++++++++++ tests/target/macros.rs | 8 -------- tests/target/single-line-macro/v1.rs | 10 ++++++++++ tests/target/single-line-macro/v2.rs | 14 ++++++++++++++ 7 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 tests/source/single-line-macro/v1.rs create mode 100644 tests/source/single-line-macro/v2.rs create mode 100644 tests/target/single-line-macro/v1.rs create mode 100644 tests/target/single-line-macro/v2.rs (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index 8c4bac2a8a5..8cc42cadfd4 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -11,6 +11,7 @@ //! Rewrite a list some items with overflow. use config::lists::*; +use config::Version; use syntax::parse::token::DelimToken; use syntax::source_map::Span; use syntax::{ast, ptr}; @@ -632,8 +633,6 @@ impl<'a> Context<'a> { _ => (self.prefix, self.suffix), }; - // 2 = `()` - let fits_one_line = items_str.len() + 2 <= shape.width; let extend_width = if items_str.is_empty() { 2 } else { @@ -652,10 +651,16 @@ impl<'a> Context<'a> { ); result.push_str(self.ident); result.push_str(prefix); - if !self.context.use_block_indent() - || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line) - || (is_extendable && extend_width <= shape.width) - { + let force_single_line = if self.context.config.version() == Version::Two { + !self.context.use_block_indent() || (is_extendable && extend_width <= shape.width) + } else { + // 2 = `()` + let fits_one_line = items_str.len() + 2 <= shape.width; + !self.context.use_block_indent() + || (self.context.inside_macro() && !items_str.contains('\n') && fits_one_line) + || (is_extendable && extend_width <= shape.width) + }; + if force_single_line { result.push_str(items_str); } else { if !items_str.is_empty() { diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 29d8f066126..5386d68898d 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -400,14 +400,6 @@ fn foo() { foo!(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,); } -// #2652 -// Preserve trailing comma inside macro, even if it looks an array. -macro_rules! bar { - ($m:ident) => { - $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]); - }; -} - // #2830 // Preserve trailing comma-less/ness inside nested macro. named!( diff --git a/tests/source/single-line-macro/v1.rs b/tests/source/single-line-macro/v1.rs new file mode 100644 index 00000000000..a3aa631ed4a --- /dev/null +++ b/tests/source/single-line-macro/v1.rs @@ -0,0 +1,10 @@ +// rustfmt-version: One + +// #2652 +// Preserve trailing comma inside macro, even if it looks an array. +macro_rules! bar { + ($m:ident) => { + $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,]); + $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]); + }; +} diff --git a/tests/source/single-line-macro/v2.rs b/tests/source/single-line-macro/v2.rs new file mode 100644 index 00000000000..51a665f7560 --- /dev/null +++ b/tests/source/single-line-macro/v2.rs @@ -0,0 +1,10 @@ +// rustfmt-version: Two + +// #2652 +// Preserve trailing comma inside macro, even if it looks an array. +macro_rules! bar { + ($m:ident) => { + $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,]); + $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]); + }; +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index bc15a86cf34..ca5f91b715e 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -980,14 +980,6 @@ fn foo() { ); } -// #2652 -// Preserve trailing comma inside macro, even if it looks an array. -macro_rules! bar { - ($m:ident) => { - $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]); - }; -} - // #2830 // Preserve trailing comma-less/ness inside nested macro. named!( diff --git a/tests/target/single-line-macro/v1.rs b/tests/target/single-line-macro/v1.rs new file mode 100644 index 00000000000..a3aa631ed4a --- /dev/null +++ b/tests/target/single-line-macro/v1.rs @@ -0,0 +1,10 @@ +// rustfmt-version: One + +// #2652 +// Preserve trailing comma inside macro, even if it looks an array. +macro_rules! bar { + ($m:ident) => { + $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,]); + $m!([a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]); + }; +} diff --git a/tests/target/single-line-macro/v2.rs b/tests/target/single-line-macro/v2.rs new file mode 100644 index 00000000000..9c6bcf33ad5 --- /dev/null +++ b/tests/target/single-line-macro/v2.rs @@ -0,0 +1,14 @@ +// rustfmt-version: Two + +// #2652 +// Preserve trailing comma inside macro, even if it looks an array. +macro_rules! bar { + ($m:ident) => { + $m!([ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, + ]); + $m!([ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z + ]); + }; +} -- cgit 1.4.1-3-g733a5 From 181ca427dccf3ed4b3e483177718f67fb8ddec5c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 27 Jan 2019 21:01:12 +0900 Subject: Use the same rule with macro and function calls with a single chain --- src/overflow.rs | 7 +++++++ tests/source/issue-3272/v1.rs | 15 +++++++++++++++ tests/source/issue-3272/v2.rs | 15 +++++++++++++++ tests/target/issue-3272/v1.rs | 15 +++++++++++++++ tests/target/issue-3272/v2.rs | 17 +++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 tests/source/issue-3272/v1.rs create mode 100644 tests/source/issue-3272/v2.rs create mode 100644 tests/target/issue-3272/v1.rs create mode 100644 tests/target/issue-3272/v2.rs (limited to 'src') diff --git a/src/overflow.rs b/src/overflow.rs index 8cc42cadfd4..344fb28620b 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -467,6 +467,13 @@ impl<'a> Context<'a> { { self.context.force_one_line_chain.replace(true); } + Some(OverflowableItem::MacroArg(MacroArg::Expr(expr))) + if !combine_arg_with_callee + && is_method_call(expr) + && self.context.config.version() == Version::Two => + { + self.context.force_one_line_chain.replace(true); + } _ => (), } let result = last_item_shape( diff --git a/tests/source/issue-3272/v1.rs b/tests/source/issue-3272/v1.rs new file mode 100644 index 00000000000..f4c1b7c992b --- /dev/null +++ b/tests/source/issue-3272/v1.rs @@ -0,0 +1,15 @@ +// rustfmt-version: One + +fn main() { + assert!(HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some()); + + assert( + HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some(), + ); +} diff --git a/tests/source/issue-3272/v2.rs b/tests/source/issue-3272/v2.rs new file mode 100644 index 00000000000..0148368edc8 --- /dev/null +++ b/tests/source/issue-3272/v2.rs @@ -0,0 +1,15 @@ +// rustfmt-version: Two + +fn main() { + assert!(HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some()); + + assert( + HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some(), + ); +} diff --git a/tests/target/issue-3272/v1.rs b/tests/target/issue-3272/v1.rs new file mode 100644 index 00000000000..aab201027d5 --- /dev/null +++ b/tests/target/issue-3272/v1.rs @@ -0,0 +1,15 @@ +// rustfmt-version: One + +fn main() { + assert!(HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some()); + + assert( + HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some(), + ); +} diff --git a/tests/target/issue-3272/v2.rs b/tests/target/issue-3272/v2.rs new file mode 100644 index 00000000000..a42a2fccd5b --- /dev/null +++ b/tests/target/issue-3272/v2.rs @@ -0,0 +1,17 @@ +// rustfmt-version: Two + +fn main() { + assert!( + HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some() + ); + + assert( + HAYSTACK + .par_iter() + .find_any(|&&x| x[0] % 1000 == 999) + .is_some(), + ); +} -- cgit 1.4.1-3-g733a5 From 154ccf6a02e3842e064ebc17b47a6abaf00e0691 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 31 Jan 2019 23:44:58 +0900 Subject: Do not force trailing comma when using mixed layout --- Cargo.lock | 2 ++ src/overflow.rs | 3 --- tests/source/trailing-comma-never.rs | 4 ++++ tests/target/trailing-comma-never.rs | 4 ++++ 4 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 01cb370a89a..bc52c406226 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "aho-corasick" version = "0.6.9" diff --git a/src/overflow.rs b/src/overflow.rs index 344fb28620b..98702e82fda 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -607,9 +607,6 @@ impl<'a> Context<'a> { tactic } else if !self.context.use_block_indent() { SeparatorTactic::Never - } else if tactic == DefinitiveListTactic::Mixed { - // We are using mixed layout because everything did not fit within a single line. - SeparatorTactic::Always } else { self.context.config.trailing_comma() }; diff --git a/tests/source/trailing-comma-never.rs b/tests/source/trailing-comma-never.rs index 5985b514724..c74267cd179 100644 --- a/tests/source/trailing-comma-never.rs +++ b/tests/source/trailing-comma-never.rs @@ -39,3 +39,7 @@ enum StructY { i: i32, } } + +static XXX: [i8; 64] = [ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, 1, +]; diff --git a/tests/target/trailing-comma-never.rs b/tests/target/trailing-comma-never.rs index 3df0c7950eb..ea199f5ff29 100644 --- a/tests/target/trailing-comma-never.rs +++ b/tests/target/trailing-comma-never.rs @@ -29,3 +29,7 @@ enum StructY { A { s: u16 }, B { u: u32, i: i32 } } + +static XXX: [i8; 64] = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +]; -- cgit 1.4.1-3-g733a5 From 0142e961ad03e99663cf811c27012daef51c9270 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 1 Feb 2019 00:16:33 +0900 Subject: Prioritize single_line_fn and empty_item_single_line over brace_style When either one of these two options are set to `true`, each should take precedence over the brace_style option. This commit does not introduce any formatting change to the default configuration, so no version gate is required. --- src/items.rs | 81 +++++++++++----------- tests/source/issue-2835.rs | 7 ++ .../configs/brace_style/item_always_next_line.rs | 4 +- tests/target/fn-custom-7.rs | 8 +-- tests/target/issue-2835.rs | 4 ++ 5 files changed, 53 insertions(+), 51 deletions(-) create mode 100644 tests/source/issue-2835.rs create mode 100644 tests/target/issue-2835.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a2bf023a33e..d681564bd57 100644 --- a/src/items.rs +++ b/src/items.rs @@ -333,19 +333,21 @@ impl<'a> FmtVisitor<'a> { newline_brace = false; } - // Prepare for the function body by possibly adding a newline and - // indent. - // FIXME we'll miss anything between the end of the signature and the - // start of the body, but we need more spans from the compiler to solve - // this. - if newline_brace { - result.push_str(&indent.to_string_with_newline(self.config)); + if let rw @ Some(..) = self.single_line_fn(&result, block, inner_attrs) { + rw } else { - result.push(' '); + // Prepare for the function body by possibly adding a newline and + // indent. + // FIXME we'll miss anything between the end of the signature and the + // start of the body, but we need more spans from the compiler to solve + // this. + if newline_brace { + result.push_str(&indent.to_string_with_newline(self.config)); + } else { + result.push(' '); + } + Some(result) } - - self.single_line_fn(&result, block, inner_attrs) - .or_else(|| Some(result)) } pub fn rewrite_required_fn( @@ -390,42 +392,37 @@ impl<'a> FmtVisitor<'a> { if self.config.empty_item_single_line() && is_empty_block(block, None, source_map) - && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() + && self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width() + && !last_line_contains_single_line_comment(fn_str) { - return Some(format!("{}{{}}", fn_str)); - } - - if self.config.fn_single_line() && is_simple_block_stmt(block, None, source_map) { - let rewrite = { - if let Some(stmt) = block.stmts.first() { - match stmt_expr(stmt) { - Some(e) => { - let suffix = if semicolon_for_expr(&self.get_context(), e) { - ";" - } else { - "" - }; - - format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) - .map(|s| s + suffix) - .or_else(|| Some(self.snippet(e.span).to_owned())) - } - None => stmt.rewrite(&self.get_context(), self.shape()), - } + return Some(format!("{} {{}}", fn_str)); + } + + if !self.config.fn_single_line() || !is_simple_block_stmt(block, None, source_map) { + return None; + } + + let stmt = block.stmts.first()?; + let res = match stmt_expr(stmt) { + Some(e) => { + let suffix = if semicolon_for_expr(&self.get_context(), e) { + ";" } else { - None - } - }; + "" + }; - if let Some(res) = rewrite { - let width = self.block_indent.width() + fn_str.len() + res.len() + 4; - if !res.contains('\n') && width <= self.config.max_width() { - return Some(format!("{}{{ {} }}", fn_str, res)); - } + format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) + .map(|s| s + suffix)? } - } + None => stmt.rewrite(&self.get_context(), self.shape())?, + }; - None + let width = self.block_indent.width() + fn_str.len() + res.len() + 5; + if !res.contains('\n') && width <= self.config.max_width() { + Some(format!("{} {{ {} }}", fn_str, res)) + } else { + None + } } pub fn visit_static(&mut self, static_parts: &StaticParts) { diff --git a/tests/source/issue-2835.rs b/tests/source/issue-2835.rs new file mode 100644 index 00000000000..2219b0b38e4 --- /dev/null +++ b/tests/source/issue-2835.rs @@ -0,0 +1,7 @@ +// rustfmt-brace_style: AlwaysNextLine +// rustfmt-fn_single_line: true + +fn lorem() -> i32 +{ + 42 +} diff --git a/tests/target/configs/brace_style/item_always_next_line.rs b/tests/target/configs/brace_style/item_always_next_line.rs index 38ed449d178..c13018630be 100644 --- a/tests/target/configs/brace_style/item_always_next_line.rs +++ b/tests/target/configs/brace_style/item_always_next_line.rs @@ -21,7 +21,5 @@ where mod tests { #[test] - fn it_works() - { - } + fn it_works() {} } diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index 4d88eb8fbe1..f98150c4291 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -30,11 +30,7 @@ fn foo( trait Test { - fn foo(a: u8) - { - } + fn foo(a: u8) {} - fn bar(a: u8) -> String - { - } + fn bar(a: u8) -> String {} } diff --git a/tests/target/issue-2835.rs b/tests/target/issue-2835.rs new file mode 100644 index 00000000000..21e8ce41145 --- /dev/null +++ b/tests/target/issue-2835.rs @@ -0,0 +1,4 @@ +// rustfmt-brace_style: AlwaysNextLine +// rustfmt-fn_single_line: true + +fn lorem() -> i32 { 42 } -- cgit 1.4.1-3-g733a5 From c2534f53247b31647b8b457a2bb90757b695b9ad Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Fri, 1 Feb 2019 19:58:38 +0900 Subject: fix "internal error: left behind trailing whitespace" with long lines --- Configurations.md | 3 +- src/expr.rs | 8 +++-- .../indent_style/block_trailing_comma_call.rs | 8 ----- .../indent_style/block_trailing_comma_call/one.rs | 9 +++++ .../indent_style/block_trailing_comma_call/two.rs | 9 +++++ tests/source/issue-2179.rs | 35 ------------------- tests/source/issue-2179/one.rs | 36 +++++++++++++++++++ tests/source/issue-2179/two.rs | 36 +++++++++++++++++++ tests/source/issue-3295/two.rs | 13 +++++++ .../indent_style/block_trailing_comma_call.rs | 11 ------ .../indent_style/block_trailing_comma_call/one.rs | 12 +++++++ .../indent_style/block_trailing_comma_call/two.rs | 14 ++++++++ tests/target/issue-2179.rs | 36 ------------------- tests/target/issue-2179/one.rs | 37 ++++++++++++++++++++ tests/target/issue-2179/two.rs | 40 ++++++++++++++++++++++ tests/target/issue-3295/two.rs | 14 ++++++++ 16 files changed, 227 insertions(+), 94 deletions(-) delete mode 100644 tests/source/configs/indent_style/block_trailing_comma_call.rs create mode 100644 tests/source/configs/indent_style/block_trailing_comma_call/one.rs create mode 100644 tests/source/configs/indent_style/block_trailing_comma_call/two.rs delete mode 100644 tests/source/issue-2179.rs create mode 100644 tests/source/issue-2179/one.rs create mode 100644 tests/source/issue-2179/two.rs create mode 100644 tests/source/issue-3295/two.rs delete mode 100644 tests/target/configs/indent_style/block_trailing_comma_call.rs create mode 100644 tests/target/configs/indent_style/block_trailing_comma_call/one.rs create mode 100644 tests/target/configs/indent_style/block_trailing_comma_call/two.rs delete mode 100644 tests/target/issue-2179.rs create mode 100644 tests/target/issue-2179/one.rs create mode 100644 tests/target/issue-2179/two.rs create mode 100644 tests/target/issue-3295/two.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index abe40f2ea6f..02d17f5cddd 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1037,8 +1037,7 @@ Format string literals where necessary ```rust fn main() { - let lorem = - "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit amet consectetur adipiscing"; + let lorem = "ipsum dolor sit amet consectetur adipiscing elit lorem ipsum dolor sit amet consectetur adipiscing"; } ``` diff --git a/src/expr.rs b/src/expr.rs index 0d8e9c87580..1468b3bdd8e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -22,7 +22,7 @@ use comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, }; -use config::{Config, ControlBraceStyle, IndentStyle}; +use config::{Config, ControlBraceStyle, IndentStyle, Version}; use lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, @@ -1264,7 +1264,11 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt .join("\n") .trim_start(), ); - return wrap_str(indented_string_lit, context.config.max_width(), shape); + return if context.config.version() == Version::Two { + Some(indented_string_lit) + } else { + wrap_str(indented_string_lit, context.config.max_width(), shape) + }; } else { return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); } diff --git a/tests/source/configs/indent_style/block_trailing_comma_call.rs b/tests/source/configs/indent_style/block_trailing_comma_call.rs deleted file mode 100644 index c907ec50d45..00000000000 --- a/tests/source/configs/indent_style/block_trailing_comma_call.rs +++ /dev/null @@ -1,8 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Block - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); -} diff --git a/tests/source/configs/indent_style/block_trailing_comma_call/one.rs b/tests/source/configs/indent_style/block_trailing_comma_call/one.rs new file mode 100644 index 00000000000..6d48ea742fc --- /dev/null +++ b/tests/source/configs/indent_style/block_trailing_comma_call/one.rs @@ -0,0 +1,9 @@ +// rustfmt-version: One +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); +} diff --git a/tests/source/configs/indent_style/block_trailing_comma_call/two.rs b/tests/source/configs/indent_style/block_trailing_comma_call/two.rs new file mode 100644 index 00000000000..7a62d722c6e --- /dev/null +++ b/tests/source/configs/indent_style/block_trailing_comma_call/two.rs @@ -0,0 +1,9 @@ +// rustfmt-version: Two +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo(a, oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt()); +} diff --git a/tests/source/issue-2179.rs b/tests/source/issue-2179.rs deleted file mode 100644 index ade953971ec..00000000000 --- a/tests/source/issue-2179.rs +++ /dev/null @@ -1,35 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -fn issue_2179() { - let (opts, rustflags, clear_env_rust_log) = - { - // We mustn't lock configuration for the whole build process - let rls_config = rls_config.lock().unwrap(); - - let opts = CargoOptions::new(&rls_config); - trace!("Cargo compilation options:\n{:?}", opts); - let rustflags = prepare_cargo_rustflags(&rls_config); - - // Warn about invalid specified bin target or package depending on current mode - // TODO: Return client notifications along with diagnostics to inform the user - if !rls_config.workspace_mode { - let cur_pkg_targets = ws.current().unwrap().targets(); - - if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { - let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); - if let None = bins.find(|x| x.name() == build_bin) { - warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); - } - } - } else { - for package in &opts.package { - if let None = ws.members().find(|x| x.name() == package) { - warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); - } - } - } - - (opts, rustflags, rls_config.clear_env_rust_log) - }; - -} diff --git a/tests/source/issue-2179/one.rs b/tests/source/issue-2179/one.rs new file mode 100644 index 00000000000..d23947931ff --- /dev/null +++ b/tests/source/issue-2179/one.rs @@ -0,0 +1,36 @@ +// rustfmt-version: One +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = + { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; + +} diff --git a/tests/source/issue-2179/two.rs b/tests/source/issue-2179/two.rs new file mode 100644 index 00000000000..f4cc9cc488b --- /dev/null +++ b/tests/source/issue-2179/two.rs @@ -0,0 +1,36 @@ +// rustfmt-version: Two +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = + { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!("cargo - couldn't find binary `{}` specified in `build_bin` configuration", build_bin); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; + +} diff --git a/tests/source/issue-3295/two.rs b/tests/source/issue-3295/two.rs new file mode 100644 index 00000000000..0eaf022249b --- /dev/null +++ b/tests/source/issue-3295/two.rs @@ -0,0 +1,13 @@ +// rustfmt-version: Two +pub enum TestEnum { + a, + b, +} + +fn the_test(input: TestEnum) { + match input { + TestEnum::a => String::from("aaa"), + TestEnum::b => String::from("this is a very very very very very very very very very very very very very very very ong string"), + + }; +} diff --git a/tests/target/configs/indent_style/block_trailing_comma_call.rs b/tests/target/configs/indent_style/block_trailing_comma_call.rs deleted file mode 100644 index a7e8590ed97..00000000000 --- a/tests/target/configs/indent_style/block_trailing_comma_call.rs +++ /dev/null @@ -1,11 +0,0 @@ -// rustfmt-error_on_line_overflow: false -// rustfmt-indent_style: Block - -// rustfmt should not add trailing comma when rewriting macro. See #1528. -fn a() { - panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); - foo( - a, - oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), - ); -} diff --git a/tests/target/configs/indent_style/block_trailing_comma_call/one.rs b/tests/target/configs/indent_style/block_trailing_comma_call/one.rs new file mode 100644 index 00000000000..6b9489bef55 --- /dev/null +++ b/tests/target/configs/indent_style/block_trailing_comma_call/one.rs @@ -0,0 +1,12 @@ +// rustfmt-version: One +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!("this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:"); + foo( + a, + oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), + ); +} diff --git a/tests/target/configs/indent_style/block_trailing_comma_call/two.rs b/tests/target/configs/indent_style/block_trailing_comma_call/two.rs new file mode 100644 index 00000000000..4f4292e5f48 --- /dev/null +++ b/tests/target/configs/indent_style/block_trailing_comma_call/two.rs @@ -0,0 +1,14 @@ +// rustfmt-version: Two +// rustfmt-error_on_line_overflow: false +// rustfmt-indent_style: Block + +// rustfmt should not add trailing comma when rewriting macro. See #1528. +fn a() { + panic!( + "this is a long string that goes past the maximum line length causing rustfmt to insert a comma here:" + ); + foo( + a, + oooptoptoptoptptooptoptoptoptptooptoptoptoptptoptoptoptoptpt(), + ); +} diff --git a/tests/target/issue-2179.rs b/tests/target/issue-2179.rs deleted file mode 100644 index db8f9c557b4..00000000000 --- a/tests/target/issue-2179.rs +++ /dev/null @@ -1,36 +0,0 @@ -// rustfmt-error_on_line_overflow: false - -fn issue_2179() { - let (opts, rustflags, clear_env_rust_log) = { - // We mustn't lock configuration for the whole build process - let rls_config = rls_config.lock().unwrap(); - - let opts = CargoOptions::new(&rls_config); - trace!("Cargo compilation options:\n{:?}", opts); - let rustflags = prepare_cargo_rustflags(&rls_config); - - // Warn about invalid specified bin target or package depending on current mode - // TODO: Return client notifications along with diagnostics to inform the user - if !rls_config.workspace_mode { - let cur_pkg_targets = ws.current().unwrap().targets(); - - if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { - let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); - if let None = bins.find(|x| x.name() == build_bin) { - warn!( - "cargo - couldn't find binary `{}` specified in `build_bin` configuration", - build_bin - ); - } - } - } else { - for package in &opts.package { - if let None = ws.members().find(|x| x.name() == package) { - warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); - } - } - } - - (opts, rustflags, rls_config.clear_env_rust_log) - }; -} diff --git a/tests/target/issue-2179/one.rs b/tests/target/issue-2179/one.rs new file mode 100644 index 00000000000..3f98acc8dcd --- /dev/null +++ b/tests/target/issue-2179/one.rs @@ -0,0 +1,37 @@ +// rustfmt-version: One +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!( + "cargo - couldn't find binary `{}` specified in `build_bin` configuration", + build_bin + ); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!("cargo - couldn't find member package `{}` specified in `analyze_package` configuration", package); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; +} diff --git a/tests/target/issue-2179/two.rs b/tests/target/issue-2179/two.rs new file mode 100644 index 00000000000..96531509ea2 --- /dev/null +++ b/tests/target/issue-2179/two.rs @@ -0,0 +1,40 @@ +// rustfmt-version: Two +// rustfmt-error_on_line_overflow: false + +fn issue_2179() { + let (opts, rustflags, clear_env_rust_log) = { + // We mustn't lock configuration for the whole build process + let rls_config = rls_config.lock().unwrap(); + + let opts = CargoOptions::new(&rls_config); + trace!("Cargo compilation options:\n{:?}", opts); + let rustflags = prepare_cargo_rustflags(&rls_config); + + // Warn about invalid specified bin target or package depending on current mode + // TODO: Return client notifications along with diagnostics to inform the user + if !rls_config.workspace_mode { + let cur_pkg_targets = ws.current().unwrap().targets(); + + if let &Some(ref build_bin) = rls_config.build_bin.as_ref() { + let mut bins = cur_pkg_targets.iter().filter(|x| x.is_bin()); + if let None = bins.find(|x| x.name() == build_bin) { + warn!( + "cargo - couldn't find binary `{}` specified in `build_bin` configuration", + build_bin + ); + } + } + } else { + for package in &opts.package { + if let None = ws.members().find(|x| x.name() == package) { + warn!( + "cargo - couldn't find member package `{}` specified in `analyze_package` configuration", + package + ); + } + } + } + + (opts, rustflags, rls_config.clear_env_rust_log) + }; +} diff --git a/tests/target/issue-3295/two.rs b/tests/target/issue-3295/two.rs new file mode 100644 index 00000000000..3e669a0bb75 --- /dev/null +++ b/tests/target/issue-3295/two.rs @@ -0,0 +1,14 @@ +// rustfmt-version: Two +pub enum TestEnum { + a, + b, +} + +fn the_test(input: TestEnum) { + match input { + TestEnum::a => String::from("aaa"), + TestEnum::b => String::from( + "this is a very very very very very very very very very very very very very very very ong string", + ), + }; +} -- cgit 1.4.1-3-g733a5 From ece629b1cc4403e1e4f7118534dee8e147a162cf Mon Sep 17 00:00:00 2001 From: Evgenii Date: Mon, 4 Feb 2019 13:30:43 +0300 Subject: transition to Rust 2018 --- build.rs | 4 +--- src/attr.rs | 30 +++++++++++++++--------------- src/bin/main.rs | 2 +- src/chains.rs | 26 +++++++++++++------------- src/checkstyle.rs | 2 +- src/closures.rs | 21 +++++++++++---------- src/comment.rs | 20 ++++++++++---------- src/config/config_type.rs | 4 ++-- src/config/lists.rs | 4 ++-- src/config/mod.rs | 11 ++++++----- src/config/options.rs | 12 ++++++------ src/expr.rs | 40 ++++++++++++++++++++-------------------- src/formatting.rs | 12 ++++++------ src/git-rustfmt/main.rs | 2 +- src/imports.rs | 29 +++++++++++++++-------------- src/issues.rs | 2 +- src/items.rs | 32 +++++++++++++++++--------------- src/lib.rs | 13 +++++++------ src/lists.rs | 14 +++++++------- src/macros.rs | 34 ++++++++++++++++++---------------- src/matches.rs | 20 ++++++++++---------- src/missed_spans.rs | 12 ++++++------ src/modules.rs | 4 ++-- src/overflow.rs | 34 ++++++++++++++++++---------------- src/pairs.rs | 12 +++++++----- src/patterns.rs | 26 +++++++++++++------------- src/reorder.rs | 28 ++++++++++++++-------------- src/rewrite.rs | 12 ++++++------ src/rustfmt_diff.rs | 6 ++++-- src/shape.rs | 2 +- src/source_file.rs | 12 ++++++------ src/source_map.rs | 6 +++--- src/spanned.rs | 10 +++++----- src/string.rs | 10 +++++----- src/test/mod.rs | 14 ++++++++------ src/types.rs | 26 +++++++++++++------------- src/utils.rs | 11 +++++------ src/vertical.rs | 22 ++++++++++++---------- src/visitor.rs | 26 +++++++++++++------------- 39 files changed, 311 insertions(+), 296 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index adccd083807..57422945ade 100644 --- a/build.rs +++ b/build.rs @@ -35,9 +35,7 @@ fn main() { // (git not installed or if this is not a git repository) just return an empty string. fn commit_info() -> String { match (channel(), commit_hash(), commit_date()) { - (channel, Some(hash), Some(date)) => { - format!("{} ({} {})", channel, hash.trim_end(), date) - } + (channel, Some(hash), Some(date)) => format!("{} ({} {})", channel, hash.trim_end(), date), _ => String::new(), } } diff --git a/src/attr.rs b/src/attr.rs index d7d1876b02d..465c17fe2a0 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,20 +10,20 @@ //! Format attributes and meta items. -use comment::{contains_comment, rewrite_doc_comment, CommentStyle}; -use config::lists::*; -use config::IndentStyle; -use expr::rewrite_literal; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use overflow; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use types::{rewrite_path, PathContext}; -use utils::{count_newlines, mk_sp}; - use syntax::ast; use syntax::source_map::{BytePos, Span, DUMMY_SP}; +use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; +use crate::config::lists::*; +use crate::config::IndentStyle; +use crate::expr::rewrite_literal; +use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::overflow; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::types::{rewrite_path, PathContext}; +use crate::utils::{count_newlines, mk_sp}; + /// Returns attributes on the given statement. pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { match stmt.node { @@ -216,7 +216,7 @@ impl Rewrite for ast::MetaItem { } ast::MetaItemKind::List(ref list) => { let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; - let has_trailing_comma = ::expr::span_ends_with_comma(context, self.span); + let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span); overflow::rewrite_with_parens( context, &path, @@ -383,7 +383,7 @@ impl<'a> Rewrite for [ast::Attribute] { if let Some(missing_span) = missing_span { let snippet = context.snippet(missing_span); let (mla, mlb) = has_newlines_before_after_comment(snippet); - let comment = ::comment::recover_missing_comment_in_span( + let comment = crate::comment::recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, @@ -418,7 +418,7 @@ impl<'a> Rewrite for [ast::Attribute] { .get(derives.len()) .map(|next| mk_sp(attrs[derives.len() - 1].span.hi(), next.span.lo())); if let Some(missing_span) = missing_span { - let comment = ::comment::recover_missing_comment_in_span( + let comment = crate::comment::recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, @@ -451,7 +451,7 @@ impl<'a> Rewrite for [ast::Attribute] { .get(1) .map(|next| mk_sp(attrs[0].span.hi(), next.span.lo())); if let Some(missing_span) = missing_span { - let comment = ::comment::recover_missing_comment_in_span( + let comment = crate::comment::recover_missing_comment_in_span( missing_span, shape.with_max_width(context.config), context, diff --git a/src/bin/main.rs b/src/bin/main.rs index b3c61b3df42..53e95e8b5b6 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -24,7 +24,7 @@ use failure::err_msg; use getopts::{Matches, Options}; -use rustfmt::{ +use crate::rustfmt::{ load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines, FileName, Input, Session, Verbosity, }; diff --git a/src/chains.rs b/src/chains.rs index be383006196..9ea37a3684f 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -65,25 +65,25 @@ //! .qux //! ``` -use comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; -use config::IndentStyle; -use expr::rewrite_call; -use lists::extract_pre_comment; -use macros::convert_try_mac; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use utils::{ - self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, - trimmed_last_line_width, wrap_str, -}; - use std::borrow::Cow; use std::cmp::min; use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; +use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; +use crate::config::IndentStyle; +use crate::expr::rewrite_call; +use crate::lists::extract_pre_comment; +use crate::macros::convert_try_mac; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::utils::{ + self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident, + trimmed_last_line_width, wrap_str, +}; + pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { let chain = Chain::from_ast(expr, context); debug!("rewrite_chain {:?} {:?}", chain, shape); diff --git a/src/checkstyle.rs b/src/checkstyle.rs index e252e71f829..efc35a0b083 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -11,7 +11,7 @@ use std::io::{self, Write}; use std::path::Path; -use rustfmt_diff::{DiffLine, Mismatch}; +use crate::rustfmt_diff::{DiffLine, Mismatch}; /// The checkstyle header - should be emitted before the output of Rustfmt. /// diff --git a/src/closures.rs b/src/closures.rs index 008b884bcb2..4ec66f06386 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -8,19 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::lists::*; use syntax::parse::classify; use syntax::source_map::Span; use syntax::{ast, ptr}; -use expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; -use items::{span_hi_for_arg, span_lo_for_arg}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use overflow::OverflowableItem; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; +use crate::config::lists::*; +use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; +use crate::items::{span_hi_for_arg, span_lo_for_arg}; +use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::overflow::OverflowableItem; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; // This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. @@ -159,7 +159,8 @@ fn rewrite_closure_with_block( span: body.span, recovered: false, }; - let block = ::expr::rewrite_block_with_visitor(context, "", &block, None, None, shape, false)?; + let block = + crate::expr::rewrite_block_with_visitor(context, "", &block, None, None, shape, false)?; Some(format!("{} {}", prefix, block)) } diff --git a/src/comment.rs b/src/comment.rs index 4ceb2595e70..7b3a21fa4af 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -15,14 +15,14 @@ use std::{self, borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; use syntax::source_map::Span; -use config::Config; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; -use string::{rewrite_string, StringFormat}; -use utils::{ +use crate::config::Config; +use crate::rewrite::RewriteContext; +use crate::shape::{Indent, Shape}; +use crate::string::{rewrite_string, StringFormat}; +use crate::utils::{ count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, unicode_str_width, }; -use {ErrorKind, FormattingError}; +use crate::{ErrorKind, FormattingError}; fn is_custom_comment(comment: &str) -> bool { if !comment.starts_with("//") { @@ -657,7 +657,7 @@ impl<'a> CommentRewrite<'a> { _ => { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - match ::format_code_block(&self.code_block_buffer, &config) { + match crate::format_code_block(&self.code_block_buffer, &config) { Some(ref s) => trim_custom_comment_prefix(&s.snippet), None => trim_custom_comment_prefix(&self.code_block_buffer), } @@ -1672,7 +1672,7 @@ fn remove_comment_header(comment: &str) -> &str { #[cfg(test)] mod test { use super::*; - use shape::{Indent, Shape}; + use crate::shape::{Indent, Shape}; #[test] fn char_classes() { @@ -1733,11 +1733,11 @@ mod test { #[test] #[rustfmt::skip] fn format_doc_comments() { - let mut wrap_normalize_config: ::config::Config = Default::default(); + let mut wrap_normalize_config: crate::config::Config = Default::default(); wrap_normalize_config.set().wrap_comments(true); wrap_normalize_config.set().normalize_comments(true); - let mut wrap_config: ::config::Config = Default::default(); + let mut wrap_config: crate::config::Config = Default::default(); wrap_config.set().wrap_comments(true); let comment = rewrite_comment(" //test", diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 9e58eac52a2..09c41f8bb1d 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::file_lines::FileLines; -use config::options::{IgnoreList, WidthHeuristics}; +use crate::config::file_lines::FileLines; +use crate::config::options::{IgnoreList, WidthHeuristics}; /// Trait for types that can be used in `Config`. pub trait ConfigType: Sized { diff --git a/src/config/lists.rs b/src/config/lists.rs index 9dc3a7e6b0f..74f8e186180 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -10,8 +10,8 @@ //! Configuration options related to rewriting a list. -use config::config_type::ConfigType; -use config::IndentStyle; +use crate::config::config_type::ConfigType; +use crate::config::IndentStyle; /// The definitive formatting tactic for lists. #[derive(Eq, PartialEq, Debug, Copy, Clone)] diff --git a/src/config/mod.rs b/src/config/mod.rs index 1aec0d5bfcd..3685db306c8 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use regex::Regex; use std::cell::Cell; use std::default::Default; use std::fs::File; @@ -16,10 +15,12 @@ use std::io::{Error, ErrorKind, Read}; use std::path::{Path, PathBuf}; use std::{env, fs}; -use config::config_type::ConfigType; -pub use config::file_lines::{FileLines, FileName, Range}; -pub use config::lists::*; -pub use config::options::*; +use regex::Regex; + +use crate::config::config_type::ConfigType; +pub use crate::config::file_lines::{FileLines, FileName, Range}; +pub use crate::config::lists::*; +pub use crate::config::options::*; #[macro_use] pub mod config_type; diff --git a/src/config/options.rs b/src/config/options.rs index ed3e87a27fd..7734cfbd506 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::config_type::ConfigType; -use config::lists::*; -use config::{Config, FileName}; +use std::collections::HashSet; +use std::path::{Path, PathBuf}; use atty; -use std::collections::HashSet; -use std::path::{Path, PathBuf}; +use crate::config::config_type::ConfigType; +use crate::config::lists::*; +use crate::config::{Config, FileName}; /// Macro that will stringify the enum variants or a provided textual repr #[macro_export] @@ -169,7 +169,7 @@ impl NewlineStyle { /// If the style is set to `Auto` and `raw_input_text` contains no /// newlines, the `Native` style will be used. pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { - use NewlineStyle::*; + use crate::NewlineStyle::*; let mut style = self; if style == Auto { style = Self::auto_detect(raw_input_text); diff --git a/src/expr.rs b/src/expr.rs index 1468b3bdd8e..0e22134680f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -11,40 +11,40 @@ use std::borrow::Cow; use std::cmp::min; -use config::lists::*; use syntax::parse::token::DelimToken; use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::{ast, ptr}; -use chains::rewrite_chain; -use closures; -use comment::{ +use crate::chains::rewrite_chain; +use crate::closures; +use crate::comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, }; -use config::{Config, ControlBraceStyle, IndentStyle, Version}; -use lists::{ +use crate::config::lists::*; +use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; +use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, }; -use macros::{rewrite_macro, MacroPosition}; -use matches::rewrite_match; -use overflow::{self, IntoOverflowableItem, OverflowableItem}; -use pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; -use patterns::is_short_pattern; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use source_map::{LineRangeUtils, SpanUtils}; -use spanned::Spanned; -use string::{rewrite_string, StringFormat}; -use types::{rewrite_path, PathContext}; -use utils::{ +use crate::macros::{rewrite_macro, MacroPosition}; +use crate::matches::rewrite_match; +use crate::overflow::{self, IntoOverflowableItem, OverflowableItem}; +use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; +use crate::patterns::is_short_pattern; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::{Indent, Shape}; +use crate::source_map::{LineRangeUtils, SpanUtils}; +use crate::spanned::Spanned; +use crate::string::{rewrite_string, StringFormat}; +use crate::types::{rewrite_path, PathContext}; +use crate::utils::{ colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, semicolon_for_expr, semicolon_for_stmt, wrap_str, }; -use vertical::rewrite_with_alignment; -use visitor::FmtVisitor; +use crate::vertical::rewrite_with_alignment; +use crate::visitor::FmtVisitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { diff --git a/src/formatting.rs b/src/formatting.rs index f909086f0e0..9ffa0308297 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -12,11 +12,11 @@ use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use syntax::source_map::{FilePathMapping, SourceMap, Span}; -use comment::{CharClasses, FullCodeCharKind}; -use config::{Config, FileName, Verbosity}; -use issues::BadIssueSeeker; -use visitor::{FmtVisitor, SnippetProvider}; -use {modules, source_file, ErrorKind, FormatReport, Input, Session}; +use crate::comment::{CharClasses, FullCodeCharKind}; +use crate::config::{Config, FileName, Verbosity}; +use crate::issues::BadIssueSeeker; +use crate::visitor::{FmtVisitor, SnippetProvider}; +use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; // A map of the files of a crate, with their new content pub(crate) type SourceFile = Vec; @@ -157,7 +157,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { debug_assert_eq!( visitor.line_number, - ::utils::count_newlines(&visitor.buffer) + crate::utils::count_newlines(&visitor.buffer) ); // For some reason, the source_map does not include terminating diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 4ad004d3a8b..f7a181c4b6c 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -22,7 +22,7 @@ use std::str::FromStr; use getopts::{Matches, Options}; -use rustfmt::{load_config, CliOptions, Input, Session}; +use crate::rustfmt::{load_config, CliOptions, Input, Session}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files diff --git a/src/imports.rs b/src/imports.rs index dea8fdf313f..ad102a64c6b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,24 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow::Cow; use std::cmp::Ordering; +use std::fmt; -use config::lists::*; use syntax::ast::{self, UseTreeKind}; use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; -use comment::combine_strs_with_missing_comments; -use config::{Edition, IndentStyle}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{is_same_visibility, mk_sp, rewrite_ident}; -use visitor::FmtVisitor; - -use std::borrow::Cow; -use std::fmt; +use crate::comment::combine_strs_with_missing_comments; +use crate::config::lists::*; +use crate::config::{Edition, IndentStyle}; +use crate::lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::utils::{is_same_visibility, mk_sp, rewrite_ident}; +use crate::visitor::FmtVisitor; /// Returns a name imported by a `use` declaration. e.g. returns `Ordering` /// for `std::cmp::Ordering` and `self` for `std::cmp::self`. @@ -242,7 +243,7 @@ impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { - ::utils::format_visibility(context, &vis) + crate::utils::format_visibility(context, &vis) }); let use_str = self .rewrite(context, shape.offset_left(vis.len())?) diff --git a/src/issues.rs b/src/issues.rs index ad7babca118..3104f720436 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -14,7 +14,7 @@ use std::fmt; -use config::ReportTactic; +use crate::config::ReportTactic; const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o']; const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e']; diff --git a/src/items.rs b/src/items.rs index d681564bd57..3bef81c7d9a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -13,32 +13,34 @@ use std::borrow::Cow; use std::cmp::{min, Ordering}; -use config::lists::*; use regex::Regex; use rustc_target::spec::abi; use syntax::source_map::{self, BytePos, Span}; use syntax::visit; use syntax::{ast, ptr, symbol}; -use comment::{ +use crate::comment::{ combine_strs_with_missing_comments, contains_comment, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented, }; -use config::{BraceStyle, Config, Density, IndentStyle, Version}; -use expr::{ +use crate::config::lists::*; +use crate::config::{BraceStyle, Config, Density, IndentStyle, Version}; +use crate::expr::{ format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, ExprType, RhsTactics, }; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use macros::{rewrite_macro, MacroPosition}; -use overflow; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use source_map::{LineRangeUtils, SpanUtils}; -use spanned::Spanned; -use utils::*; -use vertical::rewrite_with_alignment; -use visitor::FmtVisitor; +use crate::lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +}; +use crate::macros::{rewrite_macro, MacroPosition}; +use crate::overflow; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::{Indent, Shape}; +use crate::source_map::{LineRangeUtils, SpanUtils}; +use crate::spanned::Spanned; +use crate::utils::*; +use crate::vertical::rewrite_with_alignment; +use crate::visitor::FmtVisitor; const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned { node: ast::VisibilityKind::Inherited, @@ -621,7 +623,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.clear(); } // type -> existential -> const -> macro -> method - use ast::ImplItemKind::*; + use crate::ast::ImplItemKind::*; fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { match (a, b) { (Type(..), Type(..)) diff --git a/src/lib.rs b/src/lib.rs index a6e531e476b..6fc3dc85945 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,15 +42,16 @@ use std::mem; use std::panic; use std::path::PathBuf; use std::rc::Rc; -use syntax::ast; -use comment::LineClasses; use failure::Fail; -use formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; -use issues::Issue; -use shape::Indent; +use syntax::ast; + +use crate::comment::LineClasses; +use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; +use crate::issues::Issue; +use crate::shape::Indent; -pub use config::{ +pub use crate::config::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, Range, Verbosity, }; diff --git a/src/lists.rs b/src/lists.rs index eebebfcf306..3575b207dba 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -13,15 +13,15 @@ use std::cmp; use std::iter::Peekable; -use config::lists::*; use syntax::source_map::BytePos; -use comment::{find_comment_end, rewrite_comment, FindUncommented}; -use config::{Config, IndentStyle}; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; -use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; -use visitor::SnippetProvider; +use crate::comment::{find_comment_end, rewrite_comment, FindUncommented}; +use crate::config::lists::*; +use crate::config::{Config, IndentStyle}; +use crate::rewrite::RewriteContext; +use crate::shape::{Indent, Shape}; +use crate::utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; +use crate::visitor::SnippetProvider; pub struct ListFormatting<'a> { tactic: DefinitiveListTactic, diff --git a/src/macros.rs b/src/macros.rs index 9ce5c913ca5..51cf9db53e8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -21,7 +21,6 @@ use std::collections::HashMap; -use config::lists::*; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; use syntax::parse::token::{BinOpToken, DelimToken, Token}; @@ -32,19 +31,22 @@ use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, parse, ptr}; -use comment::{contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses}; -use expr::rewrite_array; -use lists::{itemize_list, write_list, ListFormatting}; -use overflow; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{ +use crate::comment::{ + contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, +}; +use crate::config::lists::*; +use crate::expr::rewrite_array; +use crate::lists::{itemize_list, write_list, ListFormatting}; +use crate::overflow; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::{Indent, Shape}; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::utils::{ format_visibility, is_empty_line, mk_sp, remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt, }; -use visitor::FmtVisitor; +use crate::visitor::FmtVisitor; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; @@ -75,7 +77,7 @@ impl MacroArg { impl Rewrite for ast::Item { fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { - let mut visitor = ::visitor::FmtVisitor::from_context(context); + let mut visitor = crate::visitor::FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); @@ -1271,12 +1273,12 @@ impl MacroBranch { config.set().max_width(new_width); // First try to format as items, then as statements. - let new_body_snippet = match ::format_snippet(&body_str, &config) { + let new_body_snippet = match crate::format_snippet(&body_str, &config) { Some(new_body) => new_body, None => { let new_width = new_width + config.tab_spaces(); config.set().max_width(new_width); - match ::format_code_block(&body_str, &config) { + match crate::format_code_block(&body_str, &config) { Some(new_body) => new_body, None => return None, } @@ -1374,7 +1376,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) while parser.token != Token::Eof { // Parse a `lazy_static!` item. - let vis = ::utils::format_visibility(context, &parse_or!(parse_visibility, false)); + let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false)); parser.eat_keyword(symbol::keywords::Static); parser.eat_keyword(symbol::keywords::Ref); let id = parse_or!(parse_ident); @@ -1392,7 +1394,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) id, ty.rewrite(context, nested_shape)? )); - result.push_str(&::expr::rewrite_assign_rhs( + result.push_str(&crate::expr::rewrite_assign_rhs( context, stmt, &*expr, diff --git a/src/matches.rs b/src/matches.rs index 5d3b2dd548b..febab4da178 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -12,22 +12,22 @@ use std::iter::repeat; -use config::lists::*; use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; -use comment::{combine_strs_with_missing_comments, rewrite_comment}; -use config::{Config, ControlBraceStyle, IndentStyle, Version}; -use expr::{ +use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; +use crate::config::lists::*; +use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; +use crate::expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, rewrite_multiple_patterns, ExprType, RhsTactics, }; -use lists::{itemize_list, write_list, ListFormatting}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{ +use crate::lists::{itemize_list, write_list, ListFormatting}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, ptr_vec_to_ref_vec, semicolon_for_expr, trimmed_last_line_width, }; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index d414527a61b..2b409ab7b87 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -12,12 +12,12 @@ use std::borrow::Cow; use syntax::source_map::{BytePos, Pos, Span}; -use comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; -use config::{EmitMode, FileName}; -use shape::{Indent, Shape}; -use source_map::LineRangeUtils; -use utils::{count_newlines, last_line_width, mk_sp}; -use visitor::FmtVisitor; +use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::config::{EmitMode, FileName}; +use crate::shape::{Indent, Shape}; +use crate::source_map::LineRangeUtils; +use crate::utils::{count_newlines, last_line_width, mk_sp}; +use crate::visitor::FmtVisitor; struct SnippetStatus { /// An offset to the current line from the beginning of the original snippet. diff --git a/src/modules.rs b/src/modules.rs index aa36f4103e4..1a89be66e8f 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -17,8 +17,8 @@ use syntax::parse::{parser, DirectoryOwnership}; use syntax::source_map; use syntax_pos::symbol::Symbol; -use config::FileName; -use utils::contains_skip; +use crate::config::FileName; +use crate::utils::contains_skip; /// List all the files containing modules of a crate. /// If a file is used twice in a crate, it appears only once. diff --git a/src/overflow.rs b/src/overflow.rs index 98702e82fda..04456aea106 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -10,28 +10,30 @@ //! Rewrite a list some items with overflow. -use config::lists::*; -use config::Version; +use std::cmp::min; + use syntax::parse::token::DelimToken; use syntax::source_map::Span; use syntax::{ast, ptr}; -use closures; -use expr::{ +use crate::closures; +use crate::config::lists::*; +use crate::config::Version; +use crate::expr::{ can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, rewrite_cond, }; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use macros::MacroArg; -use patterns::{can_be_overflowed_pat, TuplePatField}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use spanned::Spanned; -use types::{can_be_overflowed_type, SegmentParam}; -use utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; - -use std::cmp::min; +use crate::lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +}; +use crate::macros::MacroArg; +use crate::patterns::{can_be_overflowed_pat, TuplePatField}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::types::{can_be_overflowed_type, SegmentParam}; +use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; const SHORT_ITEM_THRESHOLD: usize = 10; @@ -544,7 +546,7 @@ impl<'a> Context<'a> { && self.one_line_width != 0 && !list_items[0].has_comment() && !list_items[0].inner_as_ref().contains('\n') - && ::lists::total_item_width(&list_items[0]) <= self.one_line_width + && crate::lists::total_item_width(&list_items[0]) <= self.one_line_width { tactic = DefinitiveListTactic::Horizontal; } else { diff --git a/src/pairs.rs b/src/pairs.rs index 609c425ef4b..05a0911c388 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -10,11 +10,13 @@ use syntax::ast; -use config::lists::*; -use config::IndentStyle; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use utils::{first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str}; +use crate::config::lists::*; +use crate::config::IndentStyle; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::utils::{ + first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str, +}; /// Sigils that decorate a binop pair. #[derive(new, Clone, Copy)] diff --git a/src/patterns.rs b/src/patterns.rs index 7dd315fcb9b..acfb6ee1933 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -8,26 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::lists::*; use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; use syntax::ptr; use syntax::source_map::{self, BytePos, Span}; -use comment::FindUncommented; -use expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; -use lists::{ +use crate::comment::FindUncommented; +use crate::config::lists::*; +use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; +use crate::lists::{ itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; -use macros::{rewrite_macro, MacroPosition}; -use overflow; -use pairs::{rewrite_pair, PairParts}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use spanned::Spanned; -use types::{rewrite_path, PathContext}; -use utils::{format_mutability, mk_sp, rewrite_ident}; +use crate::macros::{rewrite_macro, MacroPosition}; +use crate::overflow; +use crate::pairs::{rewrite_pair, PairParts}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::types::{rewrite_path, PathContext}; +use crate::utils::{format_mutability, mk_sp, rewrite_ident}; /// Returns true if the given pattern is short. A short pattern is defined by the following grammar: /// diff --git a/src/reorder.rs b/src/reorder.rs index 30b9bbee657..5891cde7594 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -16,22 +16,22 @@ // FIXME(#2455): Reorder trait items. -use config::Config; -use syntax::{ast, attr, source_map::Span}; +use std::cmp::{Ord, Ordering}; -use attr::filter_inline_attrs; -use comment::combine_strs_with_missing_comments; -use imports::{merge_use_trees, UseTree}; -use items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; -use lists::{itemize_list, write_list, ListFormatting, ListItem}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::LineRangeUtils; -use spanned::Spanned; -use utils::{contains_skip, mk_sp}; -use visitor::FmtVisitor; +use syntax::{ast, attr, source_map::Span}; -use std::cmp::{Ord, Ordering}; +use crate::attr::filter_inline_attrs; +use crate::comment::combine_strs_with_missing_comments; +use crate::config::Config; +use crate::imports::{merge_use_trees, UseTree}; +use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; +use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::LineRangeUtils; +use crate::spanned::Spanned; +use crate::utils::{contains_skip, mk_sp}; +use crate::visitor::FmtVisitor; /// Choose the ordering between the given two items. fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { diff --git a/src/rewrite.rs b/src/rewrite.rs index 17bb027bd56..9d3733a279c 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -10,16 +10,16 @@ // A generic trait to abstract the rewriting of an element (of the AST). +use std::cell::RefCell; + use syntax::parse::ParseSess; use syntax::ptr; use syntax::source_map::{SourceMap, Span}; -use config::{Config, IndentStyle}; -use shape::Shape; -use visitor::SnippetProvider; -use FormatReport; - -use std::cell::RefCell; +use crate::config::{Config, IndentStyle}; +use crate::shape::Shape; +use crate::visitor::SnippetProvider; +use crate::FormatReport; pub trait Rewrite { /// Rewrite self into shape. diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index dbe1c05406a..8a74aa47c0c 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use config::{Color, Config, Verbosity}; -use diff; use std::collections::VecDeque; use std::io; use std::io::Write; +use diff; + +use crate::config::{Color, Config, Verbosity}; + #[derive(Debug, PartialEq)] pub enum DiffLine { Context(String), diff --git a/src/shape.rs b/src/shape.rs index 5868f0b85fd..1b1217346fa 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -12,7 +12,7 @@ use std::borrow::Cow; use std::cmp::min; use std::ops::{Add, Sub}; -use Config; +use crate::Config; #[derive(Copy, Clone, Debug)] pub struct Indent { diff --git a/src/source_file.rs b/src/source_file.rs index 306f2626639..b26cd0521fa 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -11,12 +11,12 @@ use std::fs; use std::io::{self, Write}; -use checkstyle::output_checkstyle_file; -use config::{Config, EmitMode, FileName, Verbosity}; -use rustfmt_diff::{make_diff, output_modified, print_diff}; +use crate::checkstyle::output_checkstyle_file; +use crate::config::{Config, EmitMode, FileName, Verbosity}; +use crate::rustfmt_diff::{make_diff, output_modified, print_diff}; #[cfg(test)] -use formatting::FileRecord; +use crate::formatting::FileRecord; // Append a newline to the end of each file. pub fn append_newline(s: &mut String) { @@ -33,13 +33,13 @@ where T: Write, { if config.emit_mode() == EmitMode::Checkstyle { - write!(out, "{}", ::checkstyle::header())?; + write!(out, "{}", crate::checkstyle::header())?; } for &(ref filename, ref text) in source_file { write_file(text, filename, out, config)?; } if config.emit_mode() == EmitMode::Checkstyle { - write!(out, "{}", ::checkstyle::footer())?; + write!(out, "{}", crate::checkstyle::footer())?; } Ok(()) diff --git a/src/source_map.rs b/src/source_map.rs index 1d6ff29c19c..8caff51ee40 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -11,11 +11,11 @@ //! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. -use config::file_lines::LineRange; use syntax::source_map::{BytePos, SourceMap, Span}; -use visitor::SnippetProvider; -use comment::FindUncommented; +use crate::comment::FindUncommented; +use crate::config::file_lines::LineRange; +use crate::visitor::SnippetProvider; pub trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; diff --git a/src/spanned.rs b/src/spanned.rs index 2488f3b428d..ab021ed7ec1 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -8,15 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp::max; + use syntax::{ ast, ptr, source_map::{self, Span}, }; -use macros::MacroArg; -use utils::{mk_sp, outer_attributes}; - -use std::cmp::max; +use crate::macros::MacroArg; +use crate::utils::{mk_sp, outer_attributes}; /// Spanned returns a span including attributes, if available. pub trait Spanned { @@ -116,7 +116,7 @@ impl Spanned for ast::Arm { impl Spanned for ast::Arg { fn span(&self) -> Span { - if ::items::is_named_arg(self) { + if crate::items::is_named_arg(self) { mk_sp(self.pat.span.lo(), self.ty.span.hi()) } else { self.ty.span diff --git a/src/string.rs b/src/string.rs index dc48a6b13fd..cb174841738 100644 --- a/src/string.rs +++ b/src/string.rs @@ -14,9 +14,9 @@ use regex::Regex; use unicode_categories::UnicodeCategories; use unicode_segmentation::UnicodeSegmentation; -use config::Config; -use shape::Shape; -use utils::{unicode_str_width, wrap_str}; +use crate::config::Config; +use crate::shape::Shape; +use crate::utils::{unicode_str_width, wrap_str}; const MIN_STRING: usize = 10; @@ -362,8 +362,8 @@ fn graphemes_width(graphemes: &[&str]) -> usize { #[cfg(test)] mod test { use super::{break_string, detect_url, rewrite_string, SnippetState, StringFormat}; - use config::Config; - use shape::{Indent, Shape}; + use crate::config::Config; + use crate::shape::{Indent, Shape}; use unicode_segmentation::UnicodeSegmentation; #[test] diff --git a/src/test/mod.rs b/src/test/mod.rs index f7517b18134..7e0be85f5ab 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -18,11 +18,11 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str::Chars; -use config::{Color, Config, EmitMode, FileName, ReportTactic}; -use formatting::{ModifiedChunk, SourceFile}; -use rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; -use source_file; -use {FormatReport, Input, Session}; +use crate::config::{Color, Config, EmitMode, FileName, ReportTactic}; +use crate::formatting::{ModifiedChunk, SourceFile}; +use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; +use crate::source_file; +use crate::{FormatReport, Input, Session}; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; @@ -145,7 +145,9 @@ fn modified_test() { let filename = "tests/writemode/source/modified.rs"; let mut data = Vec::new(); let mut config = Config::default(); - config.set().emit_mode(::config::EmitMode::ModifiedLines); + config + .set() + .emit_mode(crate::config::EmitMode::ModifiedLines); { let mut session = Session::new(config, Some(&mut data)); diff --git a/src/types.rs b/src/types.rs index 8cfba778a48..6c683a20796 100644 --- a/src/types.rs +++ b/src/types.rs @@ -11,22 +11,22 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; -use config::lists::*; use syntax::ast::{self, FunctionRetTy, Mutability}; use syntax::source_map::{self, BytePos, Span}; use syntax::symbol::keywords; -use config::{IndentStyle, TypeDensity}; -use expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use macros::{rewrite_macro, MacroPosition}; -use overflow; -use pairs::{rewrite_pair, PairParts}; -use rewrite::{Rewrite, RewriteContext}; -use shape::Shape; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{ +use crate::config::lists::*; +use crate::config::{IndentStyle, TypeDensity}; +use crate::expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix}; +use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::macros::{rewrite_macro, MacroPosition}; +use crate::overflow; +use crate::pairs::{rewrite_pair, PairParts}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::utils::{ colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, last_line_extendable, last_line_width, mk_sp, rewrite_ident, }; @@ -706,7 +706,7 @@ fn rewrite_bare_fn( result.push_str("> "); } - result.push_str(::utils::format_unsafety(bare_fn.unsafety)); + result.push_str(crate::utils::format_unsafety(bare_fn.unsafety)); result.push_str(&format_abi( bare_fn.abi, diff --git a/src/utils.rs b/src/utils.rs index 3c260cae22e..06f1ca2d8d8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,14 +20,13 @@ use syntax::ast::{ use syntax::ptr; use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use syntax_pos::Mark; - -use comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; -use config::{Config, Version}; -use rewrite::RewriteContext; -use shape::{Indent, Shape}; - use unicode_width::UnicodeWidthStr; +use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; +use crate::config::{Config, Version}; +use crate::rewrite::RewriteContext; +use crate::shape::{Indent, Shape}; + pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; diff --git a/src/vertical.rs b/src/vertical.rs index 61272e7db02..cf018b7291d 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -12,19 +12,21 @@ use std::cmp; -use config::lists::*; use syntax::ast; use syntax::source_map::{BytePos, Span}; -use comment::{combine_strs_with_missing_comments, contains_comment}; -use expr::rewrite_field; -use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; +use crate::comment::{combine_strs_with_missing_comments, contains_comment}; +use crate::config::lists::*; +use crate::expr::rewrite_field; +use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix}; +use crate::lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::{Indent, Shape}; +use crate::source_map::SpanUtils; +use crate::spanned::Spanned; +use crate::utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; pub trait AlignedItem { fn skip(&self) -> bool; diff --git a/src/visitor.rs b/src/visitor.rs index 612c8a3b8eb..029905f7e80 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -8,32 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cell::RefCell; + use syntax::attr::HasAttrs; use syntax::parse::ParseSess; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; use syntax::{ast, visit}; -use attr::*; -use comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; -use config::{BraceStyle, Config}; -use items::{ +use crate::attr::*; +use crate::comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; +use crate::config::{BraceStyle, Config}; +use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, rewrite_existential_type, rewrite_extern_crate, rewrite_type_alias, FnSig, StaticParts, StructParts, }; -use macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use source_map::{LineRangeUtils, SpanUtils}; -use spanned::Spanned; -use utils::{ +use crate::macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::{Indent, Shape}; +use crate::source_map::{LineRangeUtils, SpanUtils}; +use crate::spanned::Spanned; +use crate::utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, DEPR_SKIP_ANNOTATION, }; -use {ErrorKind, FormatReport, FormattingError}; - -use std::cell::RefCell; +use crate::{ErrorKind, FormatReport, FormattingError}; /// Creates a string slice corresponding to the specified span. pub struct SnippetProvider<'a> { -- cgit 1.4.1-3-g733a5 From 5fcb7507cac3e2f2818add67151b7aea2e12a6c0 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Tue, 5 Feb 2019 13:12:45 +0900 Subject: fix Removed indentation after nested comments error --- src/comment.rs | 6 +++++- tests/source/issue-3314.rs | 5 +++++ tests/target/issue-3314.rs | 5 +++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-3314.rs create mode 100644 tests/target/issue-3314.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 4ceb2595e70..0d41a97a3a2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -321,6 +321,7 @@ fn identify_comment( // for a block comment, search for the closing symbol CommentStyle::DoubleBullet | CommentStyle::SingleBullet | CommentStyle::Exclamation => { let closer = style.closer().trim_start(); + let mut count = orig.matches(closer).count(); let mut closing_symbol_offset = 0; let mut hbl = false; let mut first = true; @@ -341,7 +342,10 @@ fn identify_comment( first = false; } if trimmed_line.ends_with(closer) { - break; + count -= 1; + if count == 0 { + break; + } } } (hbl, closing_symbol_offset) diff --git a/tests/source/issue-3314.rs b/tests/source/issue-3314.rs new file mode 100644 index 00000000000..1cd32afb02f --- /dev/null +++ b/tests/source/issue-3314.rs @@ -0,0 +1,5 @@ +/*code +/*code*/ +if true { + println!("1"); +}*/ diff --git a/tests/target/issue-3314.rs b/tests/target/issue-3314.rs new file mode 100644 index 00000000000..1cd32afb02f --- /dev/null +++ b/tests/target/issue-3314.rs @@ -0,0 +1,5 @@ +/*code +/*code*/ +if true { + println!("1"); +}*/ -- cgit 1.4.1-3-g733a5 From da2d8a4c5797b3d1e2139a1ec0638e1b0546fd0c Mon Sep 17 00:00:00 2001 From: Evgenii Date: Wed, 6 Feb 2019 09:34:50 +0300 Subject: calculate statement first line properly --- src/attr.rs | 12 ++++++++++++ src/visitor.rs | 28 ++++++++++++++++++---------- tests/source/issue-3304.rs | 12 ++++++++++++ tests/target/issue-3304.rs | 12 ++++++++++++ 4 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 tests/source/issue-3304.rs create mode 100644 tests/target/issue-3304.rs (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 465c17fe2a0..52b55a9a175 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -34,6 +34,18 @@ pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { } } +pub fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { + match stmt.node { + ast::StmtKind::Local(ref local) => local.span, + ast::StmtKind::Item(ref item) => item.span, + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, + ast::StmtKind::Mac(ref mac) => { + let (ref mac, _, _) = **mac; + mac.span + } + } +} + /// Returns attributes that are within `outer_span`. pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { attrs diff --git a/src/visitor.rs b/src/visitor.rs index 029905f7e80..41309f5272e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -113,7 +113,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let attrs = get_attrs_from_stmt(stmt); if contains_skip(attrs) { - self.push_skipped_with_span(attrs, stmt.span()); + self.push_skipped_with_span(attrs, stmt.span(), get_span_without_attrs(stmt)); } else { let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); @@ -123,7 +123,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, ref attrs) = **mac; if self.visit_attrs(attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(attrs, stmt.span()); + self.push_skipped_with_span(attrs, stmt.span(), get_span_without_attrs(stmt)); } else { self.visit_mac(mac, None, MacroPosition::Statement); } @@ -331,14 +331,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // For use items, skip rewriting attributes. Just check for a skip attribute. ast::ItemKind::Use(..) => { if contains_skip(attrs) { - self.push_skipped_with_span(attrs.as_slice(), item.span()); + self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span()); return; } } // Module is inline, in this case we treat it like any other item. _ if !is_mod_decl(item) => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.attrs.as_slice(), item.span()); + self.push_skipped_with_span(item.attrs.as_slice(), item.span(), item.span()); return; } } @@ -357,7 +357,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } _ => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(item.attrs.as_slice(), item.span()); + self.push_skipped_with_span(item.attrs.as_slice(), item.span(), item.span()); return; } } @@ -474,7 +474,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, ti.span); if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ti.attrs.as_slice(), ti.span()); + self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span()); return; } @@ -518,7 +518,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, ii.span); if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ii.attrs.as_slice(), ii.span()); + self.push_skipped_with_span(ii.attrs.as_slice(), ii.span(), ii.span()); return; } @@ -592,7 +592,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite_inner(span, rewrite); } - pub fn push_skipped_with_span(&mut self, attrs: &[ast::Attribute], item_span: Span) { + pub fn push_skipped_with_span( + &mut self, + attrs: &[ast::Attribute], + item_span: Span, + main_span: Span, + ) { self.format_missing_with_indent(source!(self, item_span).lo()); // do not take into account the lines with attributes as part of the skipped range let attrs_end = attrs @@ -600,8 +605,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { .map(|attr| self.source_map.lookup_char_pos(attr.span().hi()).line) .max() .unwrap_or(1); - // Add 1 to get the line past the last attribute - let lo = attrs_end + 1; + let first_line = self.source_map.lookup_char_pos(main_span.lo()).line; + // Statement can start after some newlines and/or spaces + // or it can be on the same line as the last attribute. + // So here we need to take a minimum between two. + let lo = std::cmp::min(attrs_end + 1, first_line); self.push_rewrite_inner(item_span, None); let hi = self.line_number + 1; self.skipped_range.push((lo, hi)); diff --git a/tests/source/issue-3304.rs b/tests/source/issue-3304.rs new file mode 100644 index 00000000000..680a80ef333 --- /dev/null +++ b/tests/source/issue-3304.rs @@ -0,0 +1,12 @@ +// rustfmt-error_on_line_overflow: true + +macro_rules! test_macro { + ($($id:ident),*) => {}; +} + +fn main() { + #[rustfmt::skip] test_macro! { one, two, three, four, five, six, seven, eight, night, ten, eleven, twelve, thirteen, fourteen, fiveteen }; + #[rustfmt::skip] + + test_macro! { one, two, three, four, five, six, seven, eight, night, ten, eleven, twelve, thirteen, fourteen, fiveteen }; +} diff --git a/tests/target/issue-3304.rs b/tests/target/issue-3304.rs new file mode 100644 index 00000000000..680a80ef333 --- /dev/null +++ b/tests/target/issue-3304.rs @@ -0,0 +1,12 @@ +// rustfmt-error_on_line_overflow: true + +macro_rules! test_macro { + ($($id:ident),*) => {}; +} + +fn main() { + #[rustfmt::skip] test_macro! { one, two, three, four, five, six, seven, eight, night, ten, eleven, twelve, thirteen, fourteen, fiveteen }; + #[rustfmt::skip] + + test_macro! { one, two, three, four, five, six, seven, eight, night, ten, eleven, twelve, thirteen, fourteen, fiveteen }; +} -- cgit 1.4.1-3-g733a5 From f4f9502ea7b7e87e760f7f2a288829d28f213812 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 30 Jan 2019 00:55:52 +0900 Subject: Cargo update - Update `rustc-ap-*` crates to 366.0.0 - Update the other crates to the latest stable --- Cargo.lock | 379 ++++++++++++++++++++++++++++---------------------------- Cargo.toml | 6 +- src/closures.rs | 1 - src/expr.rs | 1 + src/macros.rs | 30 ++--- src/visitor.rs | 28 +---- 6 files changed, 210 insertions(+), 235 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index bc52c406226..43e1ca13bbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -19,7 +19,7 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -30,30 +30,36 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -66,7 +72,7 @@ name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -75,12 +81,12 @@ name = "bytecount" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -90,14 +96,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.25" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -132,7 +138,7 @@ name = "crossbeam-epoch" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -154,9 +160,9 @@ name = "derive-new" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -169,7 +175,7 @@ name = "dirs" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -193,9 +199,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -204,7 +210,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -212,7 +218,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -221,24 +227,15 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" +name = "fuchsia-cprng" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -251,7 +248,7 @@ dependencies = [ [[package]] name = "humantime" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -277,7 +274,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -299,12 +296,11 @@ dependencies = [ [[package]] name = "memchr" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -319,10 +315,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -335,7 +331,7 @@ dependencies = [ [[package]] name = "packed_simd" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -355,16 +351,16 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -377,50 +373,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" -version = "0.1.43" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -428,7 +434,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -438,25 +444,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -464,20 +470,20 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -487,90 +493,90 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "306.0.0" +version = "366.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -578,28 +584,28 @@ name = "rustc-hash" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-rayon" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-rayon-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -631,16 +637,16 @@ dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -672,7 +678,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -682,32 +688,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.80" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.80" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -720,11 +726,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.22" +version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -733,9 +739,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -744,7 +750,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -761,8 +767,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -776,10 +782,10 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -820,11 +826,6 @@ name = "utf8-ranges" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "void" version = "1.0.2" @@ -846,7 +847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -863,22 +864,23 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayvec 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f405cc4c21cd8b784f6c8fc2adf9bc00f59558f0049b5ec21517f875963040cc" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum bytecount 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c219c0335c21a8bd79587ce5aee9f64aff1d0bd7a2cca7a58a815f9780cd3b0d" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" @@ -894,49 +896,49 @@ dependencies = [ "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum packed_simd 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25d36de864f7218ec5633572a800109bbe5a1cc8d9d95a967f3daf93ea7e6ddc" +"checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" -"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" -"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" -"checksum rustc-ap-arena 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfb540c1347a3993060896b18e0d64084203fa37aaffdc5e5c31264f275d476" -"checksum rustc-ap-graphviz 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "790ac657d5bf69be9ef56f6810e8a0238b07e8460a88526e11d41f8214eb6c4e" -"checksum rustc-ap-rustc_cratesio_shim 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b721cf32b543f3ee90240d7b757ca4a45930fe9981458a50678b4ccd75c472e2" -"checksum rustc-ap-rustc_data_structures 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4fa11df199d45ce948b07792ca593f59c1d19d2cb05d35c6b0a02271e772a416" -"checksum rustc-ap-rustc_errors 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7ead3163ef995bbba520b88739e1d60f9ccf74fdacdda985067644c8134e827" -"checksum rustc-ap-rustc_target 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "688fef9cc27837755019b72b4f13e7a3d3e5012473475f377b75dbb1f07beb5f" -"checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737" -"checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a" -"checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum rustc-ap-arena 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c1c284b1bd0fee735ff2dcc0e3463ffcb608e87ab38e34a4e1a4046b6cb0b1" +"checksum rustc-ap-graphviz 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6b811e0827f59c51d4ebae105aed916adec1b856b7977d6bb89b9dde5facf5e" +"checksum rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4153554ceefebe588b663c0c753405bb43027e535fbc00176074512a096a285" +"checksum rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7bfee70c65cd8cc5ccfa7229886c67a2a22883a026c76a92bc94b7e0a5b618" +"checksum rustc-ap-rustc_errors 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "227a98739f3986bd01336922a7160f54b4b7a8c0c48cfc4691f51999cdf8089b" +"checksum rustc-ap-rustc_target 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1dd662b713db36ca8098c8b78d881157412a263c02b919782f32cc3ba7b35b6" +"checksum rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c93c7172e63fea0b5d0bb512e2505d144cd7a072576b8d78aa4d2196f958dff9" +"checksum rustc-ap-syntax 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89bd6296deeb4996445c1f59907c1a916bb6debcd09ffd1a75e0efc4ef5085e9" +"checksum rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d00d2473c057c20bdb3845794e500ae123c3862b39e2a6cdaadeb272b16770" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" -"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" +"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544" +"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108" "checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" @@ -945,18 +947,18 @@ dependencies = [ "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" -"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" -"checksum smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "622df2d454c29a4d89b30dc3b27b42d7d90d6b9e587dbf8f67652eb7514da484" +"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" +"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "19782e145d5abefb03758958f06ea35f7b1d8421b534140e0238fd3d0bfd66e3" +"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" @@ -964,10 +966,9 @@ dependencies = [ "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" diff --git a/Cargo.toml b/Cargo.toml index b1e83e93b09..b62a25431ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.7" -rustc-ap-rustc_target = "306.0.0" -rustc-ap-syntax = "306.0.0" -rustc-ap-syntax_pos = "306.0.0" +rustc-ap-rustc_target = "366.0.0" +rustc-ap-syntax = "366.0.0" +rustc-ap-syntax_pos = "366.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/closures.rs b/src/closures.rs index 4ec66f06386..a0489718740 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -157,7 +157,6 @@ fn rewrite_closure_with_block( id: ast::NodeId::root(), rules: ast::BlockCheckMode::Default, span: body.span, - recovered: false, }; let block = crate::expr::rewrite_block_with_visitor(context, "", &block, None, None, shape, false)?; diff --git a/src/expr.rs b/src/expr.rs index 0e22134680f..744bc00d0de 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -379,6 +379,7 @@ pub fn format_expr( )) } } + ast::ExprKind::Err => None, }; expr_rw diff --git a/src/macros.rs b/src/macros.rs index 51cf9db53e8..a1b571ba0ad 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -27,7 +27,7 @@ use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::print::pprust; use syntax::source_map::{BytePos, Span}; use syntax::symbol; -use syntax::tokenstream::{Cursor, ThinTokenStream, TokenStream, TokenTree}; +use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, parse, ptr}; @@ -751,7 +751,7 @@ struct MacroArgParser { fn last_tok(tt: &TokenTree) -> Token { match *tt { TokenTree::Token(_, ref t) => t.clone(), - TokenTree::Delimited(_, ref d) => d.close_token(), + TokenTree::Delimited(_, delim, _) => Token::CloseDelim(delim), } } @@ -916,11 +916,11 @@ impl MacroArgParser { } /// Returns a collection of parsed macro def's arguments. - pub fn parse(mut self, tokens: ThinTokenStream) -> Option> { + pub fn parse(mut self, tokens: TokenStream) -> Option> { let stream: TokenStream = tokens.into(); let mut iter = stream.trees(); - while let Some(ref tok) = iter.next() { + while let Some(tok) = iter.next() { match tok { TokenTree::Token(sp, Token::Dollar) => { // We always want to add a separator before meta variables. @@ -937,7 +937,7 @@ impl MacroArgParser { self.add_meta_variable(&mut iter)?; } TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t), - TokenTree::Delimited(delimited_span, delimited) => { + TokenTree::Delimited(delimited_span, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok) == SpaceState::Always { self.add_separator(); @@ -949,19 +949,19 @@ impl MacroArgParser { // Parse the stuff inside delimiters. let mut parser = MacroArgParser::new(); parser.lo = delimited_span.open.lo(); - let delimited_arg = parser.parse(delimited.tts.clone())?; + let delimited_arg = parser.parse(tts.clone())?; let span = delimited_span.entire(); if self.is_meta_var { - self.add_repeat(delimited_arg, delimited.delim, &mut iter, span)?; + self.add_repeat(delimited_arg, delimited, &mut iter, span)?; self.is_meta_var = false; } else { - self.add_delimited(delimited_arg, delimited.delim, span); + self.add_delimited(delimited_arg, delimited, span); } } } - self.set_last_tok(tok); + self.set_last_tok(&tok); } // We are left with some stuff in the buffer. Since there is nothing @@ -1027,11 +1027,7 @@ fn wrap_macro_args_inner( // // We always try and format on one line. // FIXME: Use multi-line when every thing does not fit on one line. -fn format_macro_args( - context: &RewriteContext, - toks: ThinTokenStream, - shape: Shape, -) -> Option { +fn format_macro_args(context: &RewriteContext, toks: TokenStream, shape: Shape) -> Option { if !context.config.format_macro_matchers() { let token_stream: TokenStream = toks.into(); let span = span_for_token_stream(&token_stream); @@ -1176,7 +1172,7 @@ impl MacroParser { let tok = self.toks.next()?; let (lo, args_paren_kind) = match tok { TokenTree::Token(..) => return None, - TokenTree::Delimited(delimited_span, ref d) => (delimited_span.open.lo(), d.delim), + TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d), }; let args = tok.joint().into(); match self.toks.next()? { @@ -1185,7 +1181,7 @@ impl MacroParser { } let (mut hi, body, whole_body) = match self.toks.next()? { TokenTree::Token(..) => return None, - TokenTree::Delimited(delimited_span, _) => { + TokenTree::Delimited(delimited_span, ..) => { let data = delimited_span.entire().data(); ( data.hi, @@ -1218,7 +1214,7 @@ struct Macro { struct MacroBranch { span: Span, args_paren_kind: DelimToken, - args: ThinTokenStream, + args: TokenStream, body: Span, whole_body: Span, } diff --git a/src/visitor.rs b/src/visitor.rs index 029905f7e80..a677ce6c985 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -10,7 +10,6 @@ use std::cell::RefCell; -use syntax::attr::HasAttrs; use syntax::parse::ParseSess; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; use syntax::{ast, visit}; @@ -152,32 +151,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_str("{"); if let Some(first_stmt) = b.stmts.first() { - let attr_lo = inner_attrs + let hi = inner_attrs .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) - .or_else(|| { - // Attributes for an item in a statement position - // do not belong to the statement. (rust-lang/rust#34459) - if let ast::StmtKind::Item(ref item) = first_stmt.node { - item.attrs.first() - } else { - first_stmt.attrs().first() - } - .and_then(|attr| { - // Some stmts can have embedded attributes. - // e.g. `match { #![attr] ... }` - let attr_lo = attr.span.lo(); - if attr_lo < first_stmt.span.lo() { - Some(attr_lo) - } else { - None - } - }) - }); + .unwrap_or(first_stmt.span().lo()); - let snippet = self.snippet(mk_sp( - self.last_pos, - attr_lo.unwrap_or_else(|| first_stmt.span.lo()), - )); + let snippet = self.snippet(mk_sp(self.last_pos, hi)); let len = CommentCodeSlices::new(snippet) .nth(0) .and_then(|(kind, _, s)| { -- cgit 1.4.1-3-g733a5 From 6541f200c9d396ebfab8edaa1506e94da3d9b2c9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 6 Feb 2019 23:04:44 +0900 Subject: Fix how we get span of the PathSegment separator --- src/types.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 6c683a20796..2bbf1ba9f22 100644 --- a/src/types.rs +++ b/src/types.rs @@ -229,8 +229,14 @@ fn rewrite_segment( .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); - let force_separator = - context.inside_macro() && context.snippet(data.span).starts_with("::"); + // HACK: squeeze out the span between the identifier and the parameters. + // The hack is requried so that we don't remove the separator inside macro calls. + // This does not work in the presence of comment, hoping that people are + // sane about where to put their comment. + let separator_snippet = context + .snippet(mk_sp(segment.ident.span.hi(), data.span.lo())) + .trim(); + let force_separator = context.inside_macro() && separator_snippet.starts_with("::"); let separator = if path_context == PathContext::Expr || force_separator { "::" } else { -- cgit 1.4.1-3-g733a5 From 813aa79567cba6b0e2ed8d1126e11e83c8d450fd Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Thu, 7 Feb 2019 00:05:05 +0100 Subject: fix formatting of strings within a macro --- src/lib.rs | 7 ++++--- src/macros.rs | 6 +++--- src/utils.rs | 13 +++++++++++-- tests/source/issue-3302.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ tests/target/issue-3302.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 tests/source/issue-3302.rs create mode 100644 tests/target/issue-3302.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 6fc3dc85945..35f0cba26a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,10 +50,11 @@ use crate::comment::LineClasses; use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use crate::issues::Issue; use crate::shape::Indent; +use crate::utils::indent_next_line; pub use crate::config::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, Verbosity, + Range, Verbosity, Version, }; #[macro_use] @@ -438,7 +439,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option Option Some(get_prefix_space_width(config, &line)) }; - let new_veto_trim_value = (kind.is_string() - || (config.version() == Version::Two && kind.is_commented_string())) + // just InString{Commented} in order to allow the start of a string to be indented + let new_veto_trim_value = (kind == FullCodeCharKind::InString + || (config.version() == Version::Two + && kind == FullCodeCharKind::InStringCommented)) && !line.ends_with('\\'); let line = if veto_trim || new_veto_trim_value { veto_trim = new_veto_trim_value; @@ -574,6 +576,13 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> ) } +/// Based on the given line, determine if the next line can be indented or not. +/// This allows to preserve the indentation of multi-line literals. +pub fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Config) -> bool { + !(kind.is_string() || (config.version() == Version::Two && kind.is_commented_string())) + || line.ends_with('\\') +} + pub fn is_empty_line(s: &str) -> bool { s.is_empty() || s.chars().all(char::is_whitespace) } diff --git a/tests/source/issue-3302.rs b/tests/source/issue-3302.rs new file mode 100644 index 00000000000..c037584fd71 --- /dev/null +++ b/tests/source/issue-3302.rs @@ -0,0 +1,43 @@ +// rustfmt-version: Two + +macro_rules! moo1 { + () => { + bar! { +" +" + } + }; +} + +macro_rules! moo2 { + () => { + bar! { + " +" + } + }; +} + +macro_rules! moo3 { + () => { + 42 + /* + bar! { + " + toto +tata" + } + */ + }; +} + +macro_rules! moo4 { + () => { + bar! { +" + foo + bar +baz" + } + }; +} diff --git a/tests/target/issue-3302.rs b/tests/target/issue-3302.rs new file mode 100644 index 00000000000..146cb983819 --- /dev/null +++ b/tests/target/issue-3302.rs @@ -0,0 +1,43 @@ +// rustfmt-version: Two + +macro_rules! moo1 { + () => { + bar! { + " +" + } + }; +} + +macro_rules! moo2 { + () => { + bar! { + " +" + } + }; +} + +macro_rules! moo3 { + () => { + 42 + /* + bar! { + " + toto +tata" + } + */ + }; +} + +macro_rules! moo4 { + () => { + bar! { + " + foo + bar +baz" + } + }; +} -- cgit 1.4.1-3-g733a5 From 2502939b608b2cb33e9d916d1f3d3b9afeac7e0c Mon Sep 17 00:00:00 2001 From: Evgenii Date: Thu, 7 Feb 2019 10:55:52 +0300 Subject: fix review comments --- src/visitor.rs | 2 +- tests/source/issue-3304.rs | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 tests/source/issue-3304.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 41309f5272e..83caaf495fb 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -608,7 +608,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let first_line = self.source_map.lookup_char_pos(main_span.lo()).line; // Statement can start after some newlines and/or spaces // or it can be on the same line as the last attribute. - // So here we need to take a minimum between two. + // So here we need to take a minimum between the two. let lo = std::cmp::min(attrs_end + 1, first_line); self.push_rewrite_inner(item_span, None); let hi = self.line_number + 1; diff --git a/tests/source/issue-3304.rs b/tests/source/issue-3304.rs deleted file mode 100644 index 680a80ef333..00000000000 --- a/tests/source/issue-3304.rs +++ /dev/null @@ -1,12 +0,0 @@ -// rustfmt-error_on_line_overflow: true - -macro_rules! test_macro { - ($($id:ident),*) => {}; -} - -fn main() { - #[rustfmt::skip] test_macro! { one, two, three, four, five, six, seven, eight, night, ten, eleven, twelve, thirteen, fourteen, fiveteen }; - #[rustfmt::skip] - - test_macro! { one, two, three, four, five, six, seven, eight, night, ten, eleven, twelve, thirteen, fourteen, fiveteen }; -} -- cgit 1.4.1-3-g733a5 From c0f93a6ea35c41859c21da7d90fb142fa34a2df4 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Sat, 9 Feb 2019 15:53:12 +0900 Subject: cargo +nightly fix --edition-idioms --- src/bin/main.rs | 8 ++++---- src/cargo-fmt/main.rs | 6 +++--- src/format-diff/main.rs | 8 ++++---- src/git-rustfmt/main.rs | 6 +++--- src/lib.rs | 16 ---------------- 5 files changed, 14 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 53e95e8b5b6..b357eed34cf 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate env_logger; +use env_logger; #[macro_use] extern crate failure; -extern crate getopts; -extern crate rustfmt_nightly as rustfmt; + +use rustfmt_nightly as rustfmt; use std::env; use std::fs::File; @@ -296,7 +296,7 @@ fn format( Ok(exit_code) } -fn format_and_emit_report(session: &mut Session, input: Input) { +fn format_and_emit_report(session: &mut Session<'_, T>, input: Input) { match session.format(input) { Ok(report) => { if report.has_warnings() { diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 83a93240ff2..05861743963 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -13,9 +13,9 @@ #![cfg(not(test))] #![deny(warnings)] -extern crate cargo_metadata; -extern crate getopts; -extern crate serde_json as json; +use cargo_metadata; +use getopts; + use std::collections::{HashMap, HashSet}; use std::env; diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index aacfa12d437..5ffff79811c 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -14,16 +14,16 @@ #![deny(warnings)] -extern crate env_logger; +use env_logger; #[macro_use] extern crate failure; -extern crate getopts; +use getopts; #[macro_use] extern crate log; -extern crate regex; +use regex; #[macro_use] extern crate serde_derive; -extern crate serde_json as json; +use serde_json as json; use std::collections::HashSet; use std::io::{self, BufRead}; diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index f7a181c4b6c..aae81ba3270 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate env_logger; -extern crate getopts; +use env_logger; + #[macro_use] extern crate log; -extern crate rustfmt_nightly as rustfmt; +use rustfmt_nightly as rustfmt; use std::env; use std::io::stdout; diff --git a/src/lib.rs b/src/lib.rs index 6fc3dc85945..799aad90b7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,29 +10,13 @@ #[macro_use] extern crate derive_new; -extern crate atty; -extern crate bytecount; -extern crate diff; -extern crate dirs; -extern crate failure; -extern crate itertools; #[cfg(test)] #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; -extern crate regex; -extern crate rustc_target; -extern crate serde; #[macro_use] extern crate serde_derive; -extern crate serde_json; -extern crate syntax; -extern crate syntax_pos; -extern crate toml; -extern crate unicode_categories; -extern crate unicode_segmentation; -extern crate unicode_width; use std::cell::RefCell; use std::collections::HashMap; -- cgit 1.4.1-3-g733a5 From e70e6eb273d449e78349dde9a0980414df102c06 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Sat, 9 Feb 2019 15:55:17 +0900 Subject: deny rust_2018_idioms --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 799aad90b7b..fdc8d851d40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(rust_2018_idioms)] + #[macro_use] extern crate derive_new; #[cfg(test)] -- cgit 1.4.1-3-g733a5 From 4bb90f5cc8e0347534436612f45a3c22c7e265bb Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Sat, 9 Feb 2019 16:14:30 +0900 Subject: Fix rust_2018_idioms warnings --- src/attr.rs | 18 ++++---- src/chains.rs | 60 +++++++++++++------------- src/closures.rs | 22 +++++----- src/comment.rs | 20 ++++----- src/config/config_type.rs | 6 +-- src/config/file_lines.rs | 4 +- src/config/license.rs | 2 +- src/config/mod.rs | 2 +- src/config/options.rs | 4 +- src/expr.rs | 92 ++++++++++++++++++++-------------------- src/formatting.rs | 2 +- src/imports.rs | 22 +++++----- src/issues.rs | 2 +- src/items.rs | 104 +++++++++++++++++++++++----------------------- src/lib.rs | 6 +-- src/lists.rs | 10 ++--- src/macros.rs | 38 ++++++++--------- src/matches.rs | 20 ++++----- src/missed_spans.rs | 6 +-- src/overflow.rs | 24 +++++------ src/pairs.rs | 20 ++++----- src/patterns.rs | 16 +++---- src/reorder.rs | 6 +-- src/rewrite.rs | 4 +- src/rustfmt_diff.rs | 2 +- src/test/mod.rs | 2 +- src/types.rs | 42 +++++++++---------- src/utils.rs | 10 ++--- src/vertical.rs | 20 ++++----- src/visitor.rs | 12 +++--- 30 files changed, 299 insertions(+), 299 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 52b55a9a175..89b0367c484 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -75,7 +75,7 @@ fn argument_shape( right: usize, combine: bool, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { match context.config.indent_style() { IndentStyle::Block => { @@ -100,7 +100,7 @@ fn format_derive( derive_args: &[Span], prefix: &str, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { let mut result = String::with_capacity(128); result.push_str(prefix); @@ -133,7 +133,7 @@ fn format_derive( /// Returns the first group of attributes that fills the given predicate. /// We consider two doc comments are in different group if they are separated by normal comments. fn take_while_with_pred<'a, P>( - context: &RewriteContext, + context: &RewriteContext<'_>, attrs: &'a [ast::Attribute], pred: P, ) -> &'a [ast::Attribute] @@ -164,7 +164,7 @@ where /// Rewrite the any doc comments which come before any other attributes. fn rewrite_initial_doc_comments( - context: &RewriteContext, + context: &RewriteContext<'_>, attrs: &[ast::Attribute], shape: Shape, ) -> Option<(usize, Option)> { @@ -193,7 +193,7 @@ fn rewrite_initial_doc_comments( } impl Rewrite for ast::NestedMetaItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.node { ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), @@ -221,7 +221,7 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { } impl Rewrite for ast::MetaItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { Some(match self.node { ast::MetaItemKind::Word => { rewrite_path(context, PathContext::Type, None, &self.ident, shape)? @@ -268,7 +268,7 @@ fn format_arg_list( get_hi: F2, get_item_string: F3, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, one_line_shape: Shape, one_line_limit: Option, @@ -318,7 +318,7 @@ where } impl Rewrite for ast::Attribute { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let snippet = context.snippet(self.span); if self.is_sugared_doc { rewrite_doc_comment(snippet, shape.comment(context.config), context.config) @@ -365,7 +365,7 @@ impl Rewrite for ast::Attribute { } impl<'a> Rewrite for [ast::Attribute] { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if self.is_empty() { return Some(String::new()); } diff --git a/src/chains.rs b/src/chains.rs index 9ea37a3684f..37bbde1f4ee 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -84,7 +84,7 @@ use crate::utils::{ trimmed_last_line_width, wrap_str, }; -pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -> Option { +pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext<'_>, shape: Shape) -> Option { let chain = Chain::from_ast(expr, context); debug!("rewrite_chain {:?} {:?}", chain, shape); @@ -128,7 +128,7 @@ enum ChainItemKind { } impl ChainItemKind { - fn is_block_like(&self, context: &RewriteContext, reps: &str) -> bool { + fn is_block_like(&self, context: &RewriteContext<'_>, reps: &str) -> bool { match self { ChainItemKind::Parent(ref expr) => utils::is_block_expr(context, expr, reps), ChainItemKind::MethodCall(..) @@ -147,7 +147,7 @@ impl ChainItemKind { } } - fn from_ast(context: &RewriteContext, expr: &ast::Expr) -> (ChainItemKind, Span) { + fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) { let (kind, span) = match expr.node { ast::ExprKind::MethodCall(ref segment, ref expressions) => { let types = if let Some(ref generic_args) = segment.args { @@ -182,7 +182,7 @@ impl ChainItemKind { } impl Rewrite for ChainItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let shape = shape.sub_width(self.tries)?; let rewrite = match self.kind { ChainItemKind::Parent(ref expr) => expr.rewrite(context, shape)?, @@ -204,7 +204,7 @@ impl Rewrite for ChainItem { } impl ChainItem { - fn new(context: &RewriteContext, expr: &ast::Expr, tries: usize) -> ChainItem { + fn new(context: &RewriteContext<'_>, expr: &ast::Expr, tries: usize) -> ChainItem { let (kind, span) = ChainItemKind::from_ast(context, expr); ChainItem { kind, tries, span } } @@ -229,7 +229,7 @@ impl ChainItem { types: &[ast::GenericArg], args: &[ptr::P], span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let type_str = if types.is_empty() { @@ -254,7 +254,7 @@ struct Chain { } impl Chain { - fn from_ast(expr: &ast::Expr, context: &RewriteContext) -> Chain { + fn from_ast(expr: &ast::Expr, context: &RewriteContext<'_>) -> Chain { let subexpr_list = Self::make_subexpr_list(expr, context); // Un-parse the expression tree into ChainItems @@ -376,7 +376,7 @@ impl Chain { // Returns a Vec of the prefixes of the chain. // E.g., for input `a.b.c` we return [`a.b.c`, `a.b`, 'a'] - fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext) -> Vec { + fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext<'_>) -> Vec { let mut subexpr_list = vec![expr.clone()]; while let Some(subexpr) = Self::pop_expr_chain(subexpr_list.last().unwrap(), context) { @@ -388,7 +388,7 @@ impl Chain { // Returns the expression's subexpression, if it exists. When the subexpr // is a try! macro, we'll convert it to shorthand when the option is set. - fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext) -> Option { + fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option { match expr.node { ast::ExprKind::MethodCall(_, ref expressions) => { Some(Self::convert_try(&expressions[0], context)) @@ -400,7 +400,7 @@ impl Chain { } } - fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr { + fn convert_try(expr: &ast::Expr, context: &RewriteContext<'_>) -> ast::Expr { match expr.node { ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { if let Some(subexpr) = convert_try_mac(mac, context) { @@ -415,12 +415,12 @@ impl Chain { } impl Rewrite for Chain { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { debug!("rewrite chain {:?} {:?}", self, shape); let mut formatter = match context.config.indent_style() { - IndentStyle::Block => Box::new(ChainFormatterBlock::new(self)) as Box, - IndentStyle::Visual => Box::new(ChainFormatterVisual::new(self)) as Box, + IndentStyle::Block => Box::new(ChainFormatterBlock::new(self)) as Box, + IndentStyle::Visual => Box::new(ChainFormatterVisual::new(self)) as Box, }; formatter.format_root(&self.parent, context, shape)?; @@ -455,18 +455,18 @@ trait ChainFormatter { fn format_root( &mut self, parent: &ChainItem, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option<()>; - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option; - fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()>; + fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; + fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()>; fn format_last_child( &mut self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, child_shape: Shape, ) -> Option<()>; - fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option; + fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option; // Returns `Some` if the chain is only a root, None otherwise. fn pure_root(&mut self) -> Option; } @@ -540,7 +540,7 @@ impl<'a> ChainFormatterShared<'a> { fn format_last_child( &mut self, may_extend: bool, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, child_shape: Shape, ) -> Option<()> { @@ -633,7 +633,7 @@ impl<'a> ChainFormatterShared<'a> { Some(()) } - fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option { let connector = if self.fits_single_line { // Yay, we can put everything on one line. Cow::from("") @@ -682,7 +682,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { fn format_root( &mut self, parent: &ChainItem, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option<()> { let mut root_rewrite: String = parent.rewrite(context, shape)?; @@ -713,7 +713,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { Some(()) } - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option { + fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { Some( if self.root_ends_with_block { shape.block_indent(0) @@ -724,7 +724,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { ) } - fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { + fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> { for item in &self.shared.children[..self.shared.children.len() - 1] { let rewrite = item.rewrite(context, child_shape)?; self.shared.rewrites.push(rewrite); @@ -734,7 +734,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { fn format_last_child( &mut self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, child_shape: Shape, ) -> Option<()> { @@ -742,7 +742,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> { .format_last_child(true, context, shape, child_shape) } - fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option { self.shared.join_rewrites(context, child_shape) } @@ -771,7 +771,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { fn format_root( &mut self, parent: &ChainItem, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option<()> { let parent_shape = shape.visual_indent(0); @@ -811,14 +811,14 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { Some(()) } - fn child_shape(&self, context: &RewriteContext, shape: Shape) -> Option { + fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { shape .with_max_width(context.config) .offset_left(self.offset) .map(|s| s.visual_indent(0)) } - fn format_children(&mut self, context: &RewriteContext, child_shape: Shape) -> Option<()> { + fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> { for item in &self.shared.children[..self.shared.children.len() - 1] { let rewrite = item.rewrite(context, child_shape)?; self.shared.rewrites.push(rewrite); @@ -828,7 +828,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { fn format_last_child( &mut self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, child_shape: Shape, ) -> Option<()> { @@ -836,7 +836,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { .format_last_child(false, context, shape, child_shape) } - fn join_rewrites(&self, context: &RewriteContext, child_shape: Shape) -> Option { + fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option { self.shared.join_rewrites(context, child_shape) } diff --git a/src/closures.rs b/src/closures.rs index a0489718740..4924c8628f5 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -39,7 +39,7 @@ pub fn rewrite_closure( fn_decl: &ast::FnDecl, body: &ast::Expr, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { debug!("rewrite_closure {:?}", body); @@ -81,7 +81,7 @@ pub fn rewrite_closure( fn try_rewrite_without_block( expr: &ast::Expr, prefix: &str, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, body_shape: Shape, ) -> Option { @@ -97,7 +97,7 @@ fn try_rewrite_without_block( fn get_inner_expr<'a>( expr: &'a ast::Expr, prefix: &str, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> &'a ast::Expr { if let ast::ExprKind::Block(ref block, _) = expr.node { if !needs_block(block, prefix, context) { @@ -112,7 +112,7 @@ fn get_inner_expr<'a>( } // Figure out if a block is necessary. -fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext) -> bool { +fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) -> bool { is_unsafe_block(block) || block.stmts.len() > 1 || block_contains_comment(block, context.source_map) @@ -139,7 +139,7 @@ fn veto_block(e: &ast::Expr) -> bool { fn rewrite_closure_with_block( body: &ast::Expr, prefix: &str, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let left_most = left_most_sub_expr(body); @@ -167,7 +167,7 @@ fn rewrite_closure_with_block( fn rewrite_closure_expr( expr: &ast::Expr, prefix: &str, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { fn allow_multi_line(expr: &ast::Expr) -> bool { @@ -207,7 +207,7 @@ fn rewrite_closure_expr( fn rewrite_closure_block( block: &ast::Block, prefix: &str, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { Some(format!("{} {}", prefix, block.rewrite(context, shape)?)) @@ -221,7 +221,7 @@ fn rewrite_closure_fn_decl( fn_decl: &ast::FnDecl, body: &ast::Expr, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option<(String, usize)> { let is_async = if asyncness.is_async() { "async " } else { "" }; @@ -296,7 +296,7 @@ fn rewrite_closure_fn_decl( // Rewriting closure which is placed at the end of the function call's arg. // Returns `None` if the reformatted closure 'looks bad'. pub fn rewrite_last_closure( - context: &RewriteContext, + context: &RewriteContext<'_>, expr: &ast::Expr, shape: Shape, ) -> Option { @@ -360,7 +360,7 @@ pub fn rewrite_last_closure( } /// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. -pub fn args_have_many_closure(args: &[OverflowableItem]) -> bool { +pub fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool { args.iter() .filter_map(|arg| arg.to_expr()) .filter(|expr| match expr.node { @@ -371,7 +371,7 @@ pub fn args_have_many_closure(args: &[OverflowableItem]) -> bool { > 1 } -fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { +fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { // If we are inside macro, we do not want to add or remove block from closure body. if context.inside_macro() { false diff --git a/src/comment.rs b/src/comment.rs index 5845fc69227..d9d367fa353 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -122,7 +122,7 @@ impl<'a> CommentStyle<'a> { } } -fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { +fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> { if !normalize_comments { if orig.starts_with("/**") && !orig.starts_with("/**/") { CommentStyle::DoubleBullet @@ -158,7 +158,7 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle { /// strings, then they will be put on a single line as long as doing so does not /// exceed max width. pub fn combine_strs_with_missing_comments( - context: &RewriteContext, + context: &RewriteContext<'_>, prev_str: &str, next_str: &str, span: Span, @@ -286,7 +286,7 @@ fn identify_comment( // - a boolean indicating if there is a blank line // - a number indicating the size of the first group of comments fn consume_same_line_comments( - style: CommentStyle, + style: CommentStyle<'_>, orig: &str, line_start: &str, ) -> (bool, usize) { @@ -459,7 +459,7 @@ impl ItemizedBlock { } /// Returns a `StringFormat` used for formatting the content of an item - fn create_string_format<'a>(&'a self, fmt: &'a StringFormat) -> StringFormat<'a> { + fn create_string_format<'a>(&'a self, fmt: &'a StringFormat<'_>) -> StringFormat<'a> { StringFormat { opener: "", closer: "", @@ -777,7 +777,7 @@ impl<'a> CommentRewrite<'a> { fn rewrite_comment_inner( orig: &str, block_style: bool, - style: CommentStyle, + style: CommentStyle<'_>, shape: Shape, config: &Config, is_doc_comment: bool, @@ -820,7 +820,7 @@ fn rewrite_comment_inner( const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; -fn hide_sharp_behind_comment(s: &str) -> Cow { +fn hide_sharp_behind_comment(s: &str) -> Cow<'_, str> { if s.trim_start().starts_with("# ") { Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s)) } else { @@ -853,7 +853,7 @@ fn has_url(s: &str) -> bool { pub fn rewrite_missing_comment( span: Span, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { let missing_snippet = context.snippet(span); let trimmed_snippet = missing_snippet.trim(); @@ -870,7 +870,7 @@ pub fn rewrite_missing_comment( pub fn recover_missing_comment_in_span( span: Span, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, used_width: usize, ) -> Option { let missing_comment = rewrite_missing_comment(span, shape, context)?; @@ -934,7 +934,7 @@ fn light_rewrite_comment( /// Trims comment characters and possibly a single space from the left of a string. /// Does not trim all whitespace. If a single space is trimmed from the left of the string, /// this function returns true. -fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> (&'a str, bool) { +fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a str, bool) { if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") @@ -1544,7 +1544,7 @@ impl<'a> Iterator for CommentCodeSlices<'a> { pub fn recover_comment_removed( new: String, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { let snippet = context.snippet(span); if snippet != new && changed_comment_content(snippet, &new) { diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 09c41f8bb1d..08d086c668e 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -173,11 +173,11 @@ macro_rules! create_config { } )+ - pub fn set(&mut self) -> ConfigSetter { + pub fn set(&mut self) -> ConfigSetter<'_> { ConfigSetter(self) } - pub fn was_set(&self) -> ConfigWasSet { + pub fn was_set(&self) -> ConfigWasSet<'_> { ConfigWasSet(self) } @@ -379,7 +379,7 @@ macro_rules! create_config { HIDE_OPTIONS.contains(&name) } - pub fn print_docs(out: &mut Write, include_unstable: bool) { + pub fn print_docs(out: &mut dyn Write, include_unstable: bool) { use std::cmp; let max = 0; $( let max = cmp::max(max, stringify!($i).len()+1); )+ diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 07df0e32d9c..a7371a3da90 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -46,7 +46,7 @@ impl From for FileName { } impl fmt::Display for FileName { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { FileName::Real(p) => write!(f, "{}", p.to_str().unwrap()), FileName::Stdin => write!(f, "stdin"), @@ -202,7 +202,7 @@ impl FileLines { } /// Returns an iterator over the files contained in `self`. - pub fn files(&self) -> Files { + pub fn files(&self) -> Files<'_> { Files(self.0.as_ref().map(|m| m.keys())) } diff --git a/src/config/license.rs b/src/config/license.rs index b7324829393..38e37508450 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -14,7 +14,7 @@ pub enum LicenseError { } impl fmt::Display for LicenseError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { LicenseError::IO(ref err) => err.fmt(f), LicenseError::Regex(ref err) => err.fmt(f), diff --git a/src/config/mod.rs b/src/config/mod.rs index 3685db306c8..e51279018e2 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -208,7 +208,7 @@ fn get_toml_path(dir: &Path) -> Result, Error> { Ok(None) } -fn config_path(options: &CliOptions) -> Result, Error> { +fn config_path(options: &dyn CliOptions) -> Result, Error> { let config_path_not_found = |path: &str| -> Result, Error> { Err(Error::new( ErrorKind::NotFound, diff --git a/src/config/options.rs b/src/config/options.rs index 7734cfbd506..f167c34aedf 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -64,7 +64,7 @@ macro_rules! impl_enum_serialize_and_deserialize { impl<'de, T> Visitor<'de> for StringOnly where T: ::serde::Deserializer<'de> { type Value = String; - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("string") } fn visit_str(self, value: &str) -> Result { @@ -120,7 +120,7 @@ macro_rules! configuration_option_enum { } impl ::std::fmt::Debug for $e { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { f.write_str(match self { $( $e::$name => configuration_option_enum_stringify!($name $(: $value)*), diff --git a/src/expr.rs b/src/expr.rs index 744bc00d0de..14a5ebd28ee 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -47,7 +47,7 @@ use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; impl Rewrite for ast::Expr { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { format_expr(self, ExprType::SubExpression, context, shape) } } @@ -61,7 +61,7 @@ pub enum ExprType { pub fn format_expr( expr: &ast::Expr, expr_type: ExprType, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { skip_out_of_file_lines_range!(context, expr.span); @@ -249,7 +249,7 @@ pub fn format_expr( ast::RangeLimits::Closed => "..=", }; - fn needs_space_before_range(context: &RewriteContext, lhs: &ast::Expr) -> bool { + fn needs_space_before_range(context: &RewriteContext<'_>, lhs: &ast::Expr) -> bool { match lhs.node { ast::ExprKind::Lit(ref lit) => match lit.node { ast::LitKind::FloatUnsuffixed(..) => { @@ -399,7 +399,7 @@ pub fn rewrite_array<'a, T: 'a + IntoOverflowableItem<'a>>( name: &'a str, exprs: impl Iterator, span: Span, - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, shape: Shape, force_separator_tactic: Option, delim_token: Option, @@ -416,7 +416,7 @@ pub fn rewrite_array<'a, T: 'a + IntoOverflowableItem<'a>>( } fn rewrite_empty_block( - context: &RewriteContext, + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, label: Option, @@ -453,7 +453,7 @@ fn rewrite_empty_block( None } -fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> Option { +fn block_prefix(context: &RewriteContext<'_>, block: &ast::Block, shape: Shape) -> Option { Some(match block.rules { ast::BlockCheckMode::Unsafe(..) => { let snippet = context.snippet(block.span); @@ -482,7 +482,7 @@ fn block_prefix(context: &RewriteContext, block: &ast::Block, shape: Shape) -> O } fn rewrite_single_line_block( - context: &RewriteContext, + context: &RewriteContext<'_>, prefix: &str, block: &ast::Block, attrs: Option<&[ast::Attribute]>, @@ -502,7 +502,7 @@ fn rewrite_single_line_block( } pub fn rewrite_block_with_visitor( - context: &RewriteContext, + context: &RewriteContext<'_>, prefix: &str, block: &ast::Block, attrs: Option<&[ast::Attribute]>, @@ -533,7 +533,7 @@ pub fn rewrite_block_with_visitor( } impl Rewrite for ast::Block { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { rewrite_block(self, None, None, context, shape) } } @@ -542,7 +542,7 @@ fn rewrite_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, label: Option, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let prefix = block_prefix(context, block, shape)?; @@ -568,7 +568,7 @@ fn rewrite_block( } impl Rewrite for ast::Stmt { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { skip_out_of_file_lines_range!(context, self.span()); let result = match self.node { @@ -590,7 +590,7 @@ impl Rewrite for ast::Stmt { } // Rewrite condition if the given expression has one. -pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option { +pub fn rewrite_cond(context: &RewriteContext<'_>, expr: &ast::Expr, shape: Shape) -> Option { match expr.node { ast::ExprKind::Match(ref cond, _) => { // `match `cond` {` @@ -627,7 +627,7 @@ struct ControlFlow<'a> { span: Span, } -fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { +fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option> { match expr.node { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( cond, @@ -767,7 +767,7 @@ impl<'a> ControlFlow<'a> { fn rewrite_single_line( &self, pat_expr_str: &str, - context: &RewriteContext, + context: &RewriteContext<'_>, width: usize, ) -> Option { assert!(self.allow_single_line); @@ -825,7 +825,7 @@ fn last_line_offsetted(start_column: usize, pat_str: &str) -> bool { impl<'a> ControlFlow<'a> { fn rewrite_pat_expr( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, expr: &ast::Expr, shape: Shape, offset: usize, @@ -865,7 +865,7 @@ impl<'a> ControlFlow<'a> { fn rewrite_cond( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, alt_block_sep: &str, ) -> Option<(String, usize)> { @@ -1001,7 +1001,7 @@ impl<'a> ControlFlow<'a> { } impl<'a> Rewrite for ControlFlow<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { debug!("ControlFlow::rewrite {:?} {:?}", self, shape); let alt_block_sep = &shape.indent.to_string_with_newline(context.config); @@ -1126,7 +1126,7 @@ fn rewrite_label(opt_label: Option) -> Cow<'static, str> { } } -fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option { +fn extract_comment(span: Span, context: &RewriteContext<'_>, shape: Shape) -> Option { match rewrite_missing_comment(span, shape, context) { Some(ref comment) if !comment.is_empty() => Some(format!( "{indent}{}{indent}", @@ -1197,7 +1197,7 @@ pub fn is_unsafe_block(block: &ast::Block) -> bool { } pub fn rewrite_multiple_patterns( - context: &RewriteContext, + context: &RewriteContext<'_>, pats: &[&ast::Pat], shape: Shape, ) -> Option { @@ -1229,7 +1229,7 @@ pub fn rewrite_multiple_patterns( write_list(&items, &fmt) } -pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option { +pub fn rewrite_literal(context: &RewriteContext<'_>, l: &ast::Lit, shape: Shape) -> Option { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), _ => wrap_str( @@ -1240,7 +1240,7 @@ pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> } } -fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option { +fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> Option { let string_lit = context.snippet(span); if !context.config.format_strings() { @@ -1285,7 +1285,7 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt ) } -fn choose_separator_tactic(context: &RewriteContext, span: Span) -> Option { +fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option { if context.inside_macro() { if span_ends_with_comma(context, span) { Some(SeparatorTactic::Always) @@ -1298,7 +1298,7 @@ fn choose_separator_tactic(context: &RewriteContext, span: Span) -> Option, callee: &str, args: &[ptr::P], span: Span, @@ -1333,11 +1333,11 @@ pub fn is_simple_expr(expr: &ast::Expr) -> bool { } } -pub fn is_every_expr_simple(lists: &[OverflowableItem]) -> bool { +pub fn is_every_expr_simple(lists: &[OverflowableItem<'_>]) -> bool { lists.iter().all(OverflowableItem::is_simple) } -pub fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool { +pub fn can_be_overflowed_expr(context: &RewriteContext<'_>, expr: &ast::Expr, args_len: usize) -> bool { match expr.node { ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) @@ -1397,7 +1397,7 @@ pub fn is_nested_call(expr: &ast::Expr) -> bool { /// Return true if a function call or a method call represented by the given span ends with a /// trailing comma. This function is used when rewriting macro, as adding or removing a trailing /// comma from macro can potentially break the code. -pub fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { +pub fn span_ends_with_comma(context: &RewriteContext<'_>, span: Span) -> bool { let mut result: bool = Default::default(); let mut prev_char: char = Default::default(); let closing_delimiters = &[')', '}', ']']; @@ -1418,7 +1418,7 @@ pub fn span_ends_with_comma(context: &RewriteContext, span: Span) -> bool { } fn rewrite_paren( - context: &RewriteContext, + context: &RewriteContext<'_>, mut subexpr: &ast::Expr, shape: Shape, mut span: Span, @@ -1462,7 +1462,7 @@ fn rewrite_paren( } fn rewrite_paren_in_multi_line( - context: &RewriteContext, + context: &RewriteContext<'_>, subexpr: &ast::Expr, shape: Shape, pre_span: Span, @@ -1495,7 +1495,7 @@ fn rewrite_paren_in_multi_line( fn rewrite_index( expr: &ast::Expr, index: &ast::Expr, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let expr_str = expr.rewrite(context, shape)?; @@ -1556,7 +1556,7 @@ fn struct_lit_can_be_aligned(fields: &[ast::Field], base: Option<&ast::Expr>) -> } fn rewrite_struct_lit<'a>( - context: &RewriteContext, + context: &RewriteContext<'_>, path: &ast::Path, fields: &'a [ast::Field], base: Option<&'a ast::Expr>, @@ -1599,7 +1599,7 @@ fn rewrite_struct_lit<'a>( .map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); - let span_lo = |item: &StructLitField| match *item { + let span_lo = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => field.span().lo(), StructLitField::Base(expr) => { let last_field_hi = fields.last().map_or(span.lo(), |field| field.span.hi()); @@ -1608,11 +1608,11 @@ fn rewrite_struct_lit<'a>( last_field_hi + BytePos(pos as u32) } }; - let span_hi = |item: &StructLitField| match *item { + let span_hi = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => field.span().hi(), StructLitField::Base(expr) => expr.span.hi(), }; - let rewrite = |item: &StructLitField| match *item { + let rewrite = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => { // The 1 taken from the v_budget is for the comma. rewrite_field(context, field, v_shape.sub_width(1)?, 0) @@ -1662,7 +1662,7 @@ fn rewrite_struct_lit<'a>( } pub fn wrap_struct_field( - context: &RewriteContext, + context: &RewriteContext<'_>, fields_str: &str, shape: Shape, nested_shape: Shape, @@ -1690,7 +1690,7 @@ pub fn struct_lit_field_separator(config: &Config) -> &str { } pub fn rewrite_field( - context: &RewriteContext, + context: &RewriteContext<'_>, field: &ast::Field, shape: Shape, prefix_max_width: usize, @@ -1739,7 +1739,7 @@ pub fn rewrite_field( } fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>( - context: &RewriteContext, + context: &RewriteContext<'_>, mut items: impl Iterator, span: Span, shape: Shape, @@ -1787,7 +1787,7 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>( } pub fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, items: impl Iterator, span: Span, shape: Shape, @@ -1822,7 +1822,7 @@ pub fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( } pub fn rewrite_unary_prefix( - context: &RewriteContext, + context: &RewriteContext<'_>, prefix: &str, rewrite: &R, shape: Shape, @@ -1835,7 +1835,7 @@ pub fn rewrite_unary_prefix( // FIXME: this is probably not correct for multi-line Rewrites. we should // subtract suffix.len() from the last line budget, not the first! pub fn rewrite_unary_suffix( - context: &RewriteContext, + context: &RewriteContext<'_>, suffix: &str, rewrite: &R, shape: Shape, @@ -1849,7 +1849,7 @@ pub fn rewrite_unary_suffix( } fn rewrite_unary_op( - context: &RewriteContext, + context: &RewriteContext<'_>, op: ast::UnOp, expr: &ast::Expr, shape: Shape, @@ -1859,7 +1859,7 @@ fn rewrite_unary_op( } fn rewrite_assignment( - context: &RewriteContext, + context: &RewriteContext<'_>, lhs: &ast::Expr, rhs: &ast::Expr, op: Option<&ast::BinOp>, @@ -1889,7 +1889,7 @@ pub enum RhsTactics { // The left hand side must contain everything up to, and including, the // assignment operator. pub fn rewrite_assign_rhs, R: Rewrite>( - context: &RewriteContext, + context: &RewriteContext<'_>, lhs: S, ex: &R, shape: Shape, @@ -1898,7 +1898,7 @@ pub fn rewrite_assign_rhs, R: Rewrite>( } pub fn rewrite_assign_rhs_with, R: Rewrite>( - context: &RewriteContext, + context: &RewriteContext<'_>, lhs: S, ex: &R, shape: Shape, @@ -1927,7 +1927,7 @@ pub fn rewrite_assign_rhs_with, R: Rewrite>( } fn choose_rhs( - context: &RewriteContext, + context: &RewriteContext<'_>, expr: &R, shape: Shape, orig_rhs: Option, @@ -1968,7 +1968,7 @@ fn choose_rhs( } fn shape_from_rhs_tactic( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, rhs_tactic: RhsTactics, ) -> Option { @@ -1993,7 +1993,7 @@ pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTac } fn rewrite_expr_addrof( - context: &RewriteContext, + context: &RewriteContext<'_>, mutability: ast::Mutability, expr: &ast::Expr, shape: Shape, diff --git a/src/formatting.rs b/src/formatting.rs index 9ffa0308297..91930bad00a 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -111,7 +111,7 @@ fn format_project( // Used for formatting files. #[derive(new)] -struct FormatContext<'a, T: FormatHandler + 'a> { +struct FormatContext<'a, T: FormatHandler> { krate: &'a ast::Crate, report: FormatReport, parse_session: ParseSess, diff --git a/src/imports.rs b/src/imports.rs index ad102a64c6b..6ca29cfeaed 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -146,7 +146,7 @@ impl UseSegment { } fn from_path_segment( - context: &RewriteContext, + context: &RewriteContext<'_>, path_seg: &ast::PathSegment, modsep: bool, ) -> Option { @@ -193,19 +193,19 @@ fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree) { } impl fmt::Debug for UseTree { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } impl fmt::Debug for UseSegment { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } impl fmt::Display for UseSegment { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { UseSegment::Glob => write!(f, "*"), UseSegment::Ident(ref s, _) => write!(f, "{}", s), @@ -227,7 +227,7 @@ impl fmt::Display for UseSegment { } } impl fmt::Display for UseTree { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for (i, segment) in self.path.iter().enumerate() { let is_last = i == self.path.len() - 1; write!(f, "{}", segment)?; @@ -241,7 +241,7 @@ impl fmt::Display for UseTree { impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. - pub fn rewrite_top_level(&self, context: &RewriteContext, shape: Shape) -> Option { + pub fn rewrite_top_level(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { crate::utils::format_visibility(context, &vis) }); @@ -281,7 +281,7 @@ impl UseTree { } pub fn from_ast_with_normalization( - context: &RewriteContext, + context: &RewriteContext<'_>, item: &ast::Item, ) -> Option { match item.node { @@ -305,7 +305,7 @@ impl UseTree { } fn from_ast( - context: &RewriteContext, + context: &RewriteContext<'_>, a: &ast::UseTree, list_item: Option, visibility: Option, @@ -710,7 +710,7 @@ impl Ord for UseTree { } fn rewrite_nested_use_tree( - context: &RewriteContext, + context: &RewriteContext<'_>, use_tree_list: &[UseTree], shape: Shape, ) -> Option { @@ -786,7 +786,7 @@ fn rewrite_nested_use_tree( } impl Rewrite for UseSegment { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { Some(match self { UseSegment::Ident(ref ident, Some(ref rename)) => format!("{} as {}", ident, rename), UseSegment::Ident(ref ident, None) => ident.clone(), @@ -809,7 +809,7 @@ impl Rewrite for UseSegment { impl Rewrite for UseTree { // This does NOT format attributes and visibility or add a trailing `;`. - fn rewrite(&self, context: &RewriteContext, mut shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option { let mut result = String::with_capacity(256); let mut iter = self.path.iter().peekable(); while let Some(ref segment) = iter.next() { diff --git a/src/issues.rs b/src/issues.rs index 3104f720436..3716110465e 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -48,7 +48,7 @@ pub struct Issue { } impl fmt::Display for Issue { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { let msg = match self.issue_type { IssueType::Todo => "TODO", IssueType::Fixme => "FIXME", diff --git a/src/items.rs b/src/items.rs index 3bef81c7d9a..b272a42ba18 100644 --- a/src/items.rs +++ b/src/items.rs @@ -54,7 +54,7 @@ fn type_annotation_separator(config: &Config) -> &str { // Statements of the form // let pat: ty = init; impl Rewrite for ast::Local { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { debug!( "Local::rewrite {:?} {} {:?}", self, shape.width, shape.indent @@ -214,7 +214,7 @@ impl<'a> FnSig<'a> { } pub fn from_fn_kind( - fn_kind: &'a visit::FnKind, + fn_kind: &'a visit::FnKind<'_>, generics: &'a ast::Generics, decl: &'a ast::FnDecl, defaultness: ast::Defaultness, @@ -242,7 +242,7 @@ impl<'a> FnSig<'a> { } } - fn to_str(&self, context: &RewriteContext) -> String { + fn to_str(&self, context: &RewriteContext<'_>) -> String { let mut result = String::with_capacity(128); // Vis defaultness constness unsafety abi. result.push_str(&*format_visibility(context, &self.visibility)); @@ -260,7 +260,7 @@ impl<'a> FnSig<'a> { } impl<'a> FmtVisitor<'a> { - fn format_item(&mut self, item: &Item) { + fn format_item(&mut self, item: &Item<'_>) { self.buffer.push_str(&item.abi); let snippet = self.snippet(item.span); @@ -292,7 +292,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.hi(); } - fn format_body_element(&mut self, element: &BodyElement) { + fn format_body_element(&mut self, element: &BodyElement<'_>) { match *element { BodyElement::ForeignItem(item) => self.format_foreign_item(item), } @@ -313,7 +313,7 @@ impl<'a> FmtVisitor<'a> { &mut self, indent: Indent, ident: ast::Ident, - fn_sig: &FnSig, + fn_sig: &FnSig<'_>, span: Span, block: &ast::Block, inner_attrs: Option<&[ast::Attribute]>, @@ -427,12 +427,12 @@ impl<'a> FmtVisitor<'a> { } } - pub fn visit_static(&mut self, static_parts: &StaticParts) { + pub fn visit_static(&mut self, static_parts: &StaticParts<'_>) { let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); self.push_rewrite(static_parts.span, rewrite); } - pub fn visit_struct(&mut self, struct_parts: &StructParts) { + pub fn visit_struct(&mut self, struct_parts: &StructParts<'_>) { let is_tuple = struct_parts.def.is_tuple(); let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) .map(|s| if is_tuple { s + ";" } else { s }); @@ -672,7 +672,7 @@ impl<'a> FmtVisitor<'a> { } pub fn format_impl( - context: &RewriteContext, + context: &RewriteContext<'_>, item: &ast::Item, offset: Indent, where_span_end: Option, @@ -800,7 +800,7 @@ pub fn format_impl( } fn is_impl_single_line( - context: &RewriteContext, + context: &RewriteContext<'_>, items: &[ast::ImplItem], result: &str, where_clause_str: &str, @@ -819,7 +819,7 @@ fn is_impl_single_line( } fn format_impl_ref_and_type( - context: &RewriteContext, + context: &RewriteContext<'_>, item: &ast::Item, offset: Indent, ) -> Option { @@ -913,7 +913,7 @@ fn format_impl_ref_and_type( } fn rewrite_trait_ref( - context: &RewriteContext, + context: &RewriteContext<'_>, trait_ref: &ast::TraitRef, offset: Indent, polarity_str: &str, @@ -949,7 +949,7 @@ pub struct StructParts<'a> { } impl<'a> StructParts<'a> { - fn format_header(&self, context: &RewriteContext) -> String { + fn format_header(&self, context: &RewriteContext<'_>) -> String { format_header(context, self.prefix, self.ident, self.vis) } @@ -982,8 +982,8 @@ impl<'a> StructParts<'a> { } fn format_struct( - context: &RewriteContext, - struct_parts: &StructParts, + context: &RewriteContext<'_>, + struct_parts: &StructParts<'_>, offset: Indent, one_line_width: Option, ) -> Option { @@ -998,7 +998,7 @@ fn format_struct( } } -pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { +pub fn format_trait(context: &RewriteContext<'_>, item: &ast::Item, offset: Indent) -> Option { if let ast::ItemKind::Trait( is_auto, unsafety, @@ -1157,7 +1157,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } pub fn format_trait_alias( - context: &RewriteContext, + context: &RewriteContext<'_>, ident: ast::Ident, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, @@ -1172,7 +1172,7 @@ pub fn format_trait_alias( rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";") } -fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option { +fn format_unit_struct(context: &RewriteContext<'_>, p: &StructParts<'_>, offset: Indent) -> Option { let header_str = format_header(context, p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { let hi = if generics.where_clause.predicates.is_empty() { @@ -1197,8 +1197,8 @@ fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) } pub fn format_struct_struct( - context: &RewriteContext, - struct_parts: &StructParts, + context: &RewriteContext<'_>, + struct_parts: &StructParts<'_>, fields: &[ast::StructField], offset: Indent, one_line_width: Option, @@ -1301,7 +1301,7 @@ fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> By // Format tuple or struct without any fields. We need to make sure that the comments // inside the delimiters are preserved. fn format_empty_struct_or_tuple( - context: &RewriteContext, + context: &RewriteContext<'_>, span: Span, offset: Indent, result: &mut String, @@ -1334,8 +1334,8 @@ fn format_empty_struct_or_tuple( } fn format_tuple_struct( - context: &RewriteContext, - struct_parts: &StructParts, + context: &RewriteContext<'_>, + struct_parts: &StructParts<'_>, fields: &[ast::StructField], offset: Indent, ) -> Option { @@ -1429,7 +1429,7 @@ fn format_tuple_struct( } fn rewrite_type_prefix( - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, prefix: &str, ident: ast::Ident, @@ -1470,7 +1470,7 @@ fn rewrite_type_prefix( } fn rewrite_type_item( - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, prefix: &str, suffix: &str, @@ -1501,7 +1501,7 @@ fn rewrite_type_item( } pub fn rewrite_type_alias( - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, ident: ast::Ident, ty: &ast::Ty, @@ -1512,7 +1512,7 @@ pub fn rewrite_type_alias( } pub fn rewrite_existential_type( - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, ident: ast::Ident, generic_bounds: &ast::GenericBounds, @@ -1539,7 +1539,7 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { } pub fn rewrite_struct_field_prefix( - context: &RewriteContext, + context: &RewriteContext<'_>, field: &ast::StructField, ) -> Option { let vis = format_visibility(context, &field.vis); @@ -1556,13 +1556,13 @@ pub fn rewrite_struct_field_prefix( } impl Rewrite for ast::StructField { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { rewrite_struct_field(context, self, shape, 0) } } pub fn rewrite_struct_field( - context: &RewriteContext, + context: &RewriteContext<'_>, field: &ast::StructField, shape: Shape, lhs_max_width: usize, @@ -1693,8 +1693,8 @@ impl<'a> StaticParts<'a> { } fn rewrite_static( - context: &RewriteContext, - static_parts: &StaticParts, + context: &RewriteContext<'_>, + static_parts: &StaticParts<'_>, offset: Indent, ) -> Option { let colon = colon_spaces( @@ -1752,7 +1752,7 @@ pub fn rewrite_associated_type( ty_opt: Option<&ptr::P>, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, ) -> Option { let ident_str = rewrite_ident(context, ident); @@ -1784,7 +1784,7 @@ pub fn rewrite_associated_type( } pub fn rewrite_existential_impl_type( - context: &RewriteContext, + context: &RewriteContext<'_>, ident: ast::Ident, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, @@ -1799,7 +1799,7 @@ pub fn rewrite_associated_impl_type( defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, generics: &ast::Generics, - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, ) -> Option { let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?; @@ -1811,7 +1811,7 @@ pub fn rewrite_associated_impl_type( } impl Rewrite for ast::FunctionRetTy { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { ast::FunctionRetTy::Default(_) => Some(String::new()), ast::FunctionRetTy::Ty(ref ty) => { @@ -1831,7 +1831,7 @@ fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool { } impl Rewrite for ast::Arg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if is_named_arg(self) { let mut result = self .pat @@ -1863,7 +1863,7 @@ impl Rewrite for ast::Arg { fn rewrite_explicit_self( explicit_self: &ast::ExplicitSelf, args: &[ast::Arg], - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { match explicit_self.node { ast::SelfKind::Region(lt, m) => { @@ -1922,7 +1922,7 @@ pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { } } -pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos { +pub fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> BytePos { match arg.ty.node { ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), @@ -1940,10 +1940,10 @@ pub fn is_named_arg(arg: &ast::Arg) -> bool { // Return type is (result, force_new_line_for_brace) fn rewrite_fn_base( - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, ident: ast::Ident, - fn_sig: &FnSig, + fn_sig: &FnSig<'_>, span: Span, newline_brace: bool, has_body: bool, @@ -2269,7 +2269,7 @@ impl WhereClauseOption { } fn rewrite_args( - context: &RewriteContext, + context: &RewriteContext<'_>, args: &[ast::Arg], explicit_self: Option<&ast::ExplicitSelf>, one_line_budget: usize, @@ -2427,7 +2427,7 @@ fn arg_has_pattern(arg: &ast::Arg) -> bool { } fn compute_budgets_for_args( - context: &RewriteContext, + context: &RewriteContext<'_>, result: &str, indent: Indent, ret_str_len: usize, @@ -2500,7 +2500,7 @@ fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { } fn rewrite_generics( - context: &RewriteContext, + context: &RewriteContext<'_>, ident: &str, generics: &ast::Generics, shape: Shape, @@ -2531,7 +2531,7 @@ pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) } fn rewrite_where_clause_rfc_style( - context: &RewriteContext, + context: &RewriteContext<'_>, where_clause: &ast::WhereClause, shape: Shape, terminator: &str, @@ -2631,7 +2631,7 @@ fn rewrite_where_clause_rfc_style( } fn rewrite_where_clause( - context: &RewriteContext, + context: &RewriteContext<'_>, where_clause: &ast::WhereClause, brace_style: BraceStyle, shape: Shape, @@ -2743,7 +2743,7 @@ fn missing_span_before_after_where( } fn rewrite_comments_before_after_where( - context: &RewriteContext, + context: &RewriteContext<'_>, span_before_where: Span, span_after_where: Span, shape: Shape, @@ -2758,7 +2758,7 @@ fn rewrite_comments_before_after_where( } fn format_header( - context: &RewriteContext, + context: &RewriteContext<'_>, item_name: &str, ident: ast::Ident, vis: &ast::Visibility, @@ -2779,7 +2779,7 @@ enum BracePos { } fn format_generics( - context: &RewriteContext, + context: &RewriteContext<'_>, generics: &ast::Generics, brace_style: BraceStyle, brace_pos: BracePos, @@ -2853,7 +2853,7 @@ fn format_generics( } impl Rewrite for ast::ForeignItem { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; // Drop semicolon or it will be interpreted as comment. // FIXME: this may be a faulty span from libsyntax. @@ -2914,7 +2914,7 @@ impl Rewrite for ast::ForeignItem { } /// Rewrite an inline mod. -pub fn rewrite_mod(context: &RewriteContext, item: &ast::Item) -> String { +pub fn rewrite_mod(context: &RewriteContext<'_>, item: &ast::Item) -> String { let mut result = String::with_capacity(32); result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); @@ -2924,7 +2924,7 @@ pub fn rewrite_mod(context: &RewriteContext, item: &ast::Item) -> String { } /// Rewrite `extern crate foo;` WITHOUT attributes. -pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option { +pub fn rewrite_extern_crate(context: &RewriteContext<'_>, item: &ast::Item) -> Option { assert!(is_extern_crate(item)); let new_str = context.snippet(item.span); Some(if contains_comment(new_str) { diff --git a/src/lib.rs b/src/lib.rs index fdc8d851d40..49652436493 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -249,7 +249,7 @@ impl FormatReport { /// fancy output. pub fn fancy_print( &self, - mut t: Box>, + mut t: Box>, ) -> Result<(), term::Error> { for (file, errors) in &self.internal.borrow().0 { for error in errors { @@ -320,7 +320,7 @@ impl FormatReport { impl fmt::Display for FormatReport { // Prints all the formatting errors. - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { for (file, errors) in &self.internal.borrow().0 { for error in errors { let prefix_space_len = error.line.to_string().len(); @@ -494,7 +494,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option { +pub struct Session<'b, T: Write> { pub config: Config, pub out: Option<&'b mut T>, pub(crate) errors: ReportedErrors, diff --git a/src/lists.rs b/src/lists.rs index 3575b207dba..0fb1eec68d0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -270,7 +270,7 @@ where } // Format a list of commented items into a string. -pub fn write_list(items: I, formatting: &ListFormatting) -> Option +pub fn write_list(items: I, formatting: &ListFormatting<'_>) -> Option where I: IntoIterator + Clone, T: AsRef, @@ -771,7 +771,7 @@ where #[allow(clippy::too_many_arguments)] // Creates an iterator over a list's items with associated comments. pub fn itemize_list<'a, T, I, F1, F2, F3>( - snippet_provider: &'a SnippetProvider, + snippet_provider: &'a SnippetProvider<'_>, inner: I, terminator: &'a str, separator: &'a str, @@ -838,7 +838,7 @@ fn comment_len(comment: Option<&str>) -> usize { // Compute horizontal and vertical shapes for a struct-lit-like thing. pub fn struct_lit_shape( shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, prefix_width: usize, suffix_width: usize, ) -> Option<(Option, Shape)> { @@ -867,7 +867,7 @@ pub fn struct_lit_shape( // Compute the tactic for the internals of a struct-lit-like thing. pub fn struct_lit_tactic( h_shape: Option, - context: &RewriteContext, + context: &RewriteContext<'_>, items: &[ListItem], ) -> DefinitiveListTactic { if let Some(h_shape) = h_shape { @@ -900,7 +900,7 @@ pub fn shape_for_tactic( pub fn struct_lit_formatting<'a>( shape: Shape, tactic: DefinitiveListTactic, - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, force_no_trailing_comma: bool, ) -> ListFormatting<'a> { let ends_with_newline = context.config.indent_style() != IndentStyle::Visual diff --git a/src/macros.rs b/src/macros.rs index a1b571ba0ad..8243b6a9734 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -76,7 +76,7 @@ impl MacroArg { } impl Rewrite for ast::Item { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let mut visitor = crate::visitor::FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); @@ -86,7 +86,7 @@ impl Rewrite for ast::Item { } impl Rewrite for MacroArg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { MacroArg::Expr(ref expr) => expr.rewrite(context, shape), MacroArg::Ty(ref ty) => ty.rewrite(context, shape), @@ -145,7 +145,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { /// Rewrite macro name without using pretty-printer if possible. fn rewrite_macro_name( - context: &RewriteContext, + context: &RewriteContext<'_>, path: &ast::Path, extra_ident: Option, ) -> String { @@ -163,7 +163,7 @@ fn rewrite_macro_name( // Use this on failing to format the macro call. fn return_macro_parse_failure_fallback( - context: &RewriteContext, + context: &RewriteContext<'_>, indent: Indent, span: Span, ) -> Option { @@ -197,7 +197,7 @@ struct InsideMacroGuard<'a> { } impl<'a> InsideMacroGuard<'a> { - fn inside_macro_context(context: &'a RewriteContext) -> InsideMacroGuard<'a> { + fn inside_macro_context(context: &'a RewriteContext<'_>) -> InsideMacroGuard<'a> { let is_nested = context.inside_macro.replace(true); InsideMacroGuard { context, is_nested } } @@ -212,7 +212,7 @@ impl<'a> Drop for InsideMacroGuard<'a> { pub fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, ) -> Option { @@ -227,7 +227,7 @@ pub fn rewrite_macro( pub fn rewrite_macro_inner( mac: &ast::Mac, extra_ident: Option, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, is_nested_macro: bool, @@ -433,7 +433,7 @@ pub fn rewrite_macro_inner( } pub fn rewrite_macro_def( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, indent: Indent, def: &ast::MacroDef, @@ -604,7 +604,7 @@ enum MacroArgKind { } fn delim_token_to_str( - context: &RewriteContext, + context: &RewriteContext<'_>, delim_token: DelimToken, shape: Shape, use_multiple_lines: bool, @@ -670,7 +670,7 @@ impl MacroArgKind { fn rewrite( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, use_multiple_lines: bool, ) -> Option { @@ -722,7 +722,7 @@ struct ParsedMacroArg { impl ParsedMacroArg { pub fn rewrite( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, use_multiple_lines: bool, ) -> Option { @@ -975,7 +975,7 @@ impl MacroArgParser { } fn wrap_macro_args( - context: &RewriteContext, + context: &RewriteContext<'_>, args: &[ParsedMacroArg], shape: Shape, ) -> Option { @@ -984,7 +984,7 @@ fn wrap_macro_args( } fn wrap_macro_args_inner( - context: &RewriteContext, + context: &RewriteContext<'_>, args: &[ParsedMacroArg], shape: Shape, use_multiple_lines: bool, @@ -1027,7 +1027,7 @@ fn wrap_macro_args_inner( // // We always try and format on one line. // FIXME: Use multi-line when every thing does not fit on one line. -fn format_macro_args(context: &RewriteContext, toks: TokenStream, shape: Shape) -> Option { +fn format_macro_args(context: &RewriteContext<'_>, toks: TokenStream, shape: Shape) -> Option { if !context.config.format_macro_matchers() { let token_stream: TokenStream = toks.into(); let span = span_for_token_stream(&token_stream); @@ -1118,7 +1118,7 @@ fn next_space(tok: &Token) -> SpaceState { /// Tries to convert a macro use into a short hand try expression. Returns None /// when the macro is not an instance of try! (or parsing the inner expression /// failed). -pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option { +pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { if &mac.node.path.to_string() == "try" { let ts: TokenStream = mac.node.tts.clone().into(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); @@ -1134,7 +1134,7 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option DelimToken { +fn macro_style(mac: &ast::Mac, context: &RewriteContext<'_>) -> DelimToken { let snippet = context.snippet(mac.span); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); @@ -1222,7 +1222,7 @@ struct MacroBranch { impl MacroBranch { fn rewrite( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, multi_branch_style: bool, ) -> Option { @@ -1340,7 +1340,7 @@ impl MacroBranch { /// [pub] static ref NAME_N: TYPE_N = EXPR_N; /// } /// ``` -fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) -> Option { +fn format_lazy_static(context: &RewriteContext<'_>, shape: Shape, ts: &TokenStream) -> Option { let mut result = String::with_capacity(1024); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); let nested_shape = shape @@ -1409,7 +1409,7 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) } fn rewrite_macro_with_items( - context: &RewriteContext, + context: &RewriteContext<'_>, items: &[MacroArg], macro_name: &str, shape: Shape, diff --git a/src/matches.rs b/src/matches.rs index febab4da178..15ff7dbb8fe 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -67,13 +67,13 @@ impl<'a> Spanned for ArmWrapper<'a> { } impl<'a> Rewrite for ArmWrapper<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { rewrite_match_arm(context, self.arm, shape, self.is_last) } } pub fn rewrite_match( - context: &RewriteContext, + context: &RewriteContext<'_>, cond: &ast::Expr, arms: &[ast::Arm], shape: Shape, @@ -168,7 +168,7 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { /// Collect a byte position of the beginning `|` for each arm, if available. fn collect_beginning_verts( - context: &RewriteContext, + context: &RewriteContext<'_>, arms: &[ast::Arm], span: Span, ) -> Vec> { @@ -184,7 +184,7 @@ fn collect_beginning_verts( } fn rewrite_match_arms( - context: &RewriteContext, + context: &RewriteContext<'_>, arms: &[ast::Arm], shape: Shape, span: Span, @@ -224,7 +224,7 @@ fn rewrite_match_arms( } fn rewrite_match_arm( - context: &RewriteContext, + context: &RewriteContext<'_>, arm: &ast::Arm, shape: Shape, is_last: bool, @@ -286,7 +286,7 @@ fn rewrite_match_arm( } fn block_can_be_flattened<'a>( - context: &RewriteContext, + context: &RewriteContext<'_>, expr: &'a ast::Expr, ) -> Option<&'a ast::Block> { match expr.node { @@ -304,7 +304,7 @@ fn block_can_be_flattened<'a>( // @extend: true if the arm body can be put next to `=>` // @body: flattened body, if the body is block with a single expression fn flatten_arm_body<'a>( - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, body: &'a ast::Expr, opt_shape: Option, ) -> (bool, &'a ast::Expr) { @@ -334,7 +334,7 @@ fn flatten_arm_body<'a>( } fn rewrite_match_body( - context: &RewriteContext, + context: &RewriteContext<'_>, body: &ptr::P, pats_str: &str, shape: Shape, @@ -499,7 +499,7 @@ fn rewrite_match_body( } impl Rewrite for ast::Guard { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self { ast::Guard::If(ref expr) => expr.rewrite(context, shape), } @@ -508,7 +508,7 @@ impl Rewrite for ast::Guard { // The `if ...` guard on a match arm. fn rewrite_guard( - context: &RewriteContext, + context: &RewriteContext<'_>, guard: &Option, shape: Shape, // The amount of space used up on this line for the pattern in diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2b409ab7b87..740378fbc2a 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -79,7 +79,7 @@ impl<'a> FmtVisitor<'a> { }) } - fn format_missing_inner( + fn format_missing_inner, &str, &str)>( &mut self, end: BytePos, process_last_snippet: F, @@ -144,7 +144,7 @@ impl<'a> FmtVisitor<'a> { fn write_snippet(&mut self, span: Span, process_last_snippet: F) where - F: Fn(&mut FmtVisitor, &str, &str), + F: Fn(&mut FmtVisitor<'_>, &str, &str), { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment @@ -172,7 +172,7 @@ impl<'a> FmtVisitor<'a> { span: Span, process_last_snippet: F, ) where - F: Fn(&mut FmtVisitor, &str, &str), + F: Fn(&mut FmtVisitor<'_>, &str, &str), { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not diff --git a/src/overflow.rs b/src/overflow.rs index 04456aea106..8f50f08ed2a 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -89,7 +89,7 @@ pub enum OverflowableItem<'a> { } impl<'a> Rewrite for OverflowableItem<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { self.map(|item| item.rewrite(context, shape)) } } @@ -103,7 +103,7 @@ impl<'a> Spanned for OverflowableItem<'a> { impl<'a> OverflowableItem<'a> { pub fn map(&self, f: F) -> T where - F: Fn(&IntoOverflowableItem<'a>) -> T, + F: Fn(&dyn IntoOverflowableItem<'a>) -> T, { match self { OverflowableItem::Expr(expr) => f(*expr), @@ -159,7 +159,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + pub fn can_be_overflowed(&self, context: &RewriteContext<'_>, len: usize) -> bool { match self { OverflowableItem::Expr(expr) => can_be_overflowed_expr(context, expr, len), OverflowableItem::MacroArg(macro_arg) => match macro_arg { @@ -247,7 +247,7 @@ where } pub fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, ident: &'a str, items: impl Iterator, shape: Shape, @@ -271,7 +271,7 @@ pub fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( } pub fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, ident: &'a str, items: impl Iterator, shape: Shape, @@ -293,7 +293,7 @@ pub fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( } pub fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, name: &'a str, items: impl Iterator, shape: Shape, @@ -338,7 +338,7 @@ struct Context<'a> { impl<'a> Context<'a> { pub fn new>( - context: &'a RewriteContext, + context: &'a RewriteContext<'_>, items: impl Iterator, ident: &'a str, shape: Shape, @@ -375,7 +375,7 @@ impl<'a> Context<'a> { } } - fn last_item(&self) -> Option<&OverflowableItem> { + fn last_item(&self) -> Option<&OverflowableItem<'_>> { self.items.last() } @@ -704,7 +704,7 @@ fn need_block_indent(s: &str, shape: Shape) -> bool { }) } -fn can_be_overflowed(context: &RewriteContext, items: &[OverflowableItem]) -> bool { +fn can_be_overflowed(context: &RewriteContext<'_>, items: &[OverflowableItem<'_>]) -> bool { items .last() .map_or(false, |x| x.can_be_overflowed(context, items.len())) @@ -712,7 +712,7 @@ fn can_be_overflowed(context: &RewriteContext, items: &[OverflowableItem]) -> bo /// Returns a shape for the last argument which is going to be overflowed. fn last_item_shape( - lists: &[OverflowableItem], + lists: &[OverflowableItem<'_>], items: &[ListItem], shape: Shape, args_max_width: usize, @@ -732,7 +732,7 @@ fn last_item_shape( } fn shape_from_indent_style( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, overhead: usize, offset: usize, @@ -758,7 +758,7 @@ fn no_long_items(list: &[ListItem]) -> bool { } /// In case special-case style is required, returns an offset from which we start horizontal layout. -pub fn maybe_get_args_offset(callee_str: &str, args: &[OverflowableItem]) -> Option<(bool, usize)> { +pub fn maybe_get_args_offset(callee_str: &str, args: &[OverflowableItem<'_>]) -> Option<(bool, usize)> { if let Some(&(_, num_args_before)) = args .get(0)? .whitelist() diff --git a/src/pairs.rs b/src/pairs.rs index 05a0911c388..8429d33114f 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -42,7 +42,7 @@ impl<'a> PairParts<'a> { pub(crate) fn rewrite_all_pairs( expr: &ast::Expr, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { // First we try formatting on one line. if let Some(list) = expr.flatten(false) { @@ -62,9 +62,9 @@ pub(crate) fn rewrite_all_pairs( // This may return a multi-line result since we allow the last expression to go // multiline in a 'single line' formatting. fn rewrite_pairs_one_line( - list: &PairList, + list: &PairList<'_, '_, T>, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { assert!(list.list.len() >= 2, "Not a pair?"); @@ -107,9 +107,9 @@ fn rewrite_pairs_one_line( } fn rewrite_pairs_multiline( - list: &PairList, + list: &PairList<'_, '_, T>, shape: Shape, - context: &RewriteContext, + context: &RewriteContext<'_>, ) -> Option { let rhs_offset = shape.rhs_overhead(&context.config); let nested_shape = (match context.config.indent_style() { @@ -175,8 +175,8 @@ fn rewrite_pairs_multiline( pub(crate) fn rewrite_pair( lhs: &LHS, rhs: &RHS, - pp: PairParts, - context: &RewriteContext, + pp: PairParts<'_>, + context: &RewriteContext<'_>, shape: Shape, separator_place: SeparatorPlace, ) -> Option @@ -264,18 +264,18 @@ trait FlattenPair: Rewrite + Sized { // operator into the list. E.g,, if the source is `a * b + c`, if `_same_op` // is true, we make `[(a * b), c]` if `_same_op` is false, we make // `[a, b, c]` - fn flatten(&self, _same_op: bool) -> Option> { + fn flatten(&self, _same_op: bool) -> Option> { None } } -struct PairList<'a, 'b, T: Rewrite + 'b> { +struct PairList<'a, 'b, T: Rewrite> { list: Vec<&'b T>, separators: Vec<&'a str>, } impl FlattenPair for ast::Expr { - fn flatten(&self, same_op: bool) -> Option> { + fn flatten(&self, same_op: bool) -> Option> { let top_op = match self.node { ast::ExprKind::Binary(op, _, _) => op.node, _ => return None, diff --git a/src/patterns.rs b/src/patterns.rs index acfb6ee1933..6114362e76f 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -64,7 +64,7 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { } impl Rewrite for Pat { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.node { PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(binding_mode, ident, ref sub_pat) => { @@ -174,7 +174,7 @@ fn rewrite_struct_pat( fields: &[source_map::Spanned], ellipsis: bool, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { // 2 = ` {` @@ -240,7 +240,7 @@ fn rewrite_struct_pat( } impl Rewrite for FieldPat { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let pat = self.pat.rewrite(context, shape); if self.is_shorthand { pat @@ -271,7 +271,7 @@ pub enum TuplePatField<'a> { } impl<'a> Rewrite for TuplePatField<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { TuplePatField::Pat(p) => p.rewrite(context, shape), TuplePatField::Dotdot(_) => Some("..".to_string()), @@ -288,7 +288,7 @@ impl<'a> Spanned for TuplePatField<'a> { } } -pub fn can_be_overflowed_pat(context: &RewriteContext, pat: &TuplePatField, len: usize) -> bool { +pub fn can_be_overflowed_pat(context: &RewriteContext<'_>, pat: &TuplePatField<'_>, len: usize) -> bool { match *pat { TuplePatField::Pat(pat) => match pat.node { ast::PatKind::Path(..) @@ -310,7 +310,7 @@ fn rewrite_tuple_pat( dotdot_pos: Option, path_str: Option, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect(); @@ -379,8 +379,8 @@ fn rewrite_tuple_pat( } fn count_wildcard_suffix_len( - context: &RewriteContext, - patterns: &[TuplePatField], + context: &RewriteContext<'_>, + patterns: &[TuplePatField<'_>], span: Span, shape: Shape, ) -> usize { diff --git a/src/reorder.rs b/src/reorder.rs index 5891cde7594..e078cc3279b 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -63,7 +63,7 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { } fn wrap_reorderable_items( - context: &RewriteContext, + context: &RewriteContext<'_>, list_items: &[ListItem], shape: Shape, ) -> Option { @@ -74,7 +74,7 @@ fn wrap_reorderable_items( } fn rewrite_reorderable_item( - context: &RewriteContext, + context: &RewriteContext<'_>, item: &ast::Item, shape: Shape, ) -> Option { @@ -99,7 +99,7 @@ fn rewrite_reorderable_item( /// Rewrite a list of items with reordering. Every item in `items` must have /// the same `ast::ItemKind`. fn rewrite_reorderable_items( - context: &RewriteContext, + context: &RewriteContext<'_>, reorderable_items: &[&ast::Item], shape: Shape, span: Span, diff --git a/src/rewrite.rs b/src/rewrite.rs index 9d3733a279c..5c5ed438f5e 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -23,11 +23,11 @@ use crate::FormatReport; pub trait Rewrite { /// Rewrite self into shape. - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option; + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; } impl Rewrite for ptr::P { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { (**self).rewrite(context, shape) } } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 8a74aa47c0c..81778c33ecf 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -46,7 +46,7 @@ impl Mismatch { // This struct handles writing output to stdout and abstracts away the logic // of printing in color, if it's possible in the executing environment. pub struct OutputWriter { - terminal: Option>>, + terminal: Option>>, } impl OutputWriter { diff --git a/src/test/mod.rs b/src/test/mod.rs index 7e0be85f5ab..ac2a1a3ba22 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -785,7 +785,7 @@ impl ConfigCodeBlock { true } - fn has_parsing_errors(&self, session: &Session) -> bool { + fn has_parsing_errors(&self, session: &Session<'_, T>) -> bool { if session.has_parsing_errors() { write_message(&format!( "\u{261d}\u{1f3fd} Cannot format {}:{}", diff --git a/src/types.rs b/src/types.rs index 2bbf1ba9f22..340f15ead48 100644 --- a/src/types.rs +++ b/src/types.rs @@ -40,7 +40,7 @@ pub enum PathContext { // Does not wrap on simple segments. pub fn rewrite_path( - context: &RewriteContext, + context: &RewriteContext<'_>, path_context: PathContext, qself: Option<&ast::QSelf>, path: &ast::Path, @@ -103,7 +103,7 @@ fn rewrite_path_segments<'a, I>( iter: I, mut span_lo: BytePos, span_hi: BytePos, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option where @@ -148,7 +148,7 @@ pub enum SegmentParam<'a> { } impl<'a> SegmentParam<'a> { - fn from_generic_arg(arg: &ast::GenericArg) -> SegmentParam { + fn from_generic_arg(arg: &ast::GenericArg) -> SegmentParam<'_> { match arg { ast::GenericArg::Lifetime(ref lt) => SegmentParam::LifeTime(lt), ast::GenericArg::Type(ref ty) => SegmentParam::Type(ty), @@ -167,7 +167,7 @@ impl<'a> Spanned for SegmentParam<'a> { } impl<'a> Rewrite for SegmentParam<'a> { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), @@ -204,7 +204,7 @@ fn rewrite_segment( segment: &ast::PathSegment, span_lo: &mut BytePos, span_hi: BytePos, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let mut result = String::with_capacity(128); @@ -285,7 +285,7 @@ fn format_function_type<'a, I>( output: &FunctionRetTy, variadic: bool, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option where @@ -410,7 +410,7 @@ where } } -fn type_bound_colon(context: &RewriteContext) -> &'static str { +fn type_bound_colon(context: &RewriteContext<'_>) -> &'static str { colon_spaces( context.config.space_before_colon(), context.config.space_after_colon(), @@ -418,7 +418,7 @@ fn type_bound_colon(context: &RewriteContext) -> &'static str { } impl Rewrite for ast::WherePredicate { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { // FIXME: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { @@ -459,7 +459,7 @@ impl Rewrite for ast::WherePredicate { } impl Rewrite for ast::GenericArg { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { ast::GenericArg::Lifetime(ref lt) => lt.rewrite(context, shape), ast::GenericArg::Type(ref ty) => ty.rewrite(context, shape), @@ -470,7 +470,7 @@ impl Rewrite for ast::GenericArg { fn rewrite_bounded_lifetime( lt: &ast::Lifetime, bounds: &[ast::GenericBound], - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { let result = lt.rewrite(context, shape)?; @@ -491,13 +491,13 @@ fn rewrite_bounded_lifetime( } impl Rewrite for ast::Lifetime { - fn rewrite(&self, context: &RewriteContext, _: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option { Some(rewrite_ident(context, self.ident).to_owned()) } } impl Rewrite for ast::GenericBound { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => { let snippet = context.snippet(self.span()); @@ -516,7 +516,7 @@ impl Rewrite for ast::GenericBound { } impl Rewrite for ast::GenericBounds { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if self.is_empty() { return Some(String::new()); } @@ -526,7 +526,7 @@ impl Rewrite for ast::GenericBounds { } impl Rewrite for ast::GenericParam { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let mut result = String::with_capacity(128); // FIXME: If there are more than one attributes, this will force multiline. match self.attrs.rewrite(context, shape) { @@ -558,7 +558,7 @@ impl Rewrite for ast::GenericParam { } impl Rewrite for ast::PolyTraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if let Some(lifetime_str) = rewrite_lifetime_param(context, shape, &self.bound_generic_params) { @@ -576,13 +576,13 @@ impl Rewrite for ast::PolyTraitRef { } impl Rewrite for ast::TraitRef { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { rewrite_path(context, PathContext::Type, None, &self.path, shape) } } impl Rewrite for ast::Ty { - fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.node { ast::TyKind::TraitObject(ref bounds, tobj_syntax) => { // we have to consider 'dyn' keyword is used or not!!! @@ -695,7 +695,7 @@ impl Rewrite for ast::Ty { fn rewrite_bare_fn( bare_fn: &ast::BareFnTy, span: Span, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, ) -> Option { debug!("rewrite_bare_fn {:#?}", shape); @@ -759,7 +759,7 @@ fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool { } fn join_bounds( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, items: &[ast::GenericBound], need_indent: bool, @@ -815,7 +815,7 @@ fn join_bounds( Some(result) } -pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize) -> bool { +pub fn can_be_overflowed_type(context: &RewriteContext<'_>, ty: &ast::Ty, len: usize) -> bool { match ty.node { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { @@ -827,7 +827,7 @@ pub fn can_be_overflowed_type(context: &RewriteContext, ty: &ast::Ty, len: usize /// Returns `None` if there is no `LifetimeDef` in the given generic parameters. fn rewrite_lifetime_param( - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, generic_params: &[ast::GenericParam], ) -> Option { diff --git a/src/utils.rs b/src/utils.rs index 06f1ca2d8d8..9c70ef7d975 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -30,7 +30,7 @@ use crate::shape::{Indent, Shape}; pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; -pub fn rewrite_ident<'a>(context: &'a RewriteContext, ident: ast::Ident) -> &'a str { +pub fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: ast::Ident) -> &'a str { context.snippet(ident.span) } @@ -64,7 +64,7 @@ pub fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { } // Uses Cow to avoid allocating in the common cases. -pub fn format_visibility(context: &RewriteContext, vis: &Visibility) -> Cow<'static, str> { +pub fn format_visibility(context: &RewriteContext<'_>, vis: &Visibility) -> Cow<'static, str> { match vis.node { VisibilityKind::Public => Cow::from("pub "), VisibilityKind::Inherited => Cow::from(""), @@ -267,7 +267,7 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool { } #[inline] -pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { +pub fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { context.config.trailing_semicolon() @@ -277,7 +277,7 @@ pub fn semicolon_for_expr(context: &RewriteContext, expr: &ast::Expr) -> bool { } #[inline] -pub fn semicolon_for_stmt(context: &RewriteContext, stmt: &ast::Stmt) -> bool { +pub fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> bool { match stmt.node { ast::StmtKind::Semi(ref expr) => match expr.node { ast::ExprKind::While(..) @@ -424,7 +424,7 @@ pub fn first_line_ends_with(s: &str, c: char) -> bool { // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. -pub fn is_block_expr(context: &RewriteContext, expr: &ast::Expr, repr: &str) -> bool { +pub fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool { match expr.node { ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) diff --git a/src/vertical.rs b/src/vertical.rs index cf018b7291d..fe476c0bd40 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -31,10 +31,10 @@ use crate::utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident pub trait AlignedItem { fn skip(&self) -> bool; fn get_span(&self) -> Span; - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option; + fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; fn rewrite_aligned_item( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, ) -> Option; @@ -49,7 +49,7 @@ impl AlignedItem for ast::StructField { self.span() } - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) @@ -71,7 +71,7 @@ impl AlignedItem for ast::StructField { fn rewrite_aligned_item( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, ) -> Option { @@ -88,7 +88,7 @@ impl AlignedItem for ast::Field { self.span() } - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; let name = rewrite_ident(context, self.ident); let missing_span = if self.attrs.is_empty() { @@ -108,7 +108,7 @@ impl AlignedItem for ast::Field { fn rewrite_aligned_item( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, ) -> Option { @@ -118,7 +118,7 @@ impl AlignedItem for ast::Field { pub fn rewrite_with_alignment( fields: &[T], - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, span: Span, one_line_width: usize, @@ -185,7 +185,7 @@ pub fn rewrite_with_alignment( } fn struct_field_prefix_max_min_width( - context: &RewriteContext, + context: &RewriteContext<'_>, fields: &[T], shape: Shape, ) -> (usize, usize) { @@ -210,7 +210,7 @@ fn struct_field_prefix_max_min_width( } fn rewrite_aligned_items_inner( - context: &RewriteContext, + context: &RewriteContext<'_>, fields: &[T], span: Span, offset: Indent, @@ -268,7 +268,7 @@ fn rewrite_aligned_items_inner( } fn group_aligned_items( - context: &RewriteContext, + context: &RewriteContext<'_>, fields: &[T], ) -> (&'static str, usize) { let mut index = 0; diff --git a/src/visitor.rs b/src/visitor.rs index 6d46adedba5..ed4ab867586 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -88,7 +88,7 @@ impl<'a> Drop for FmtVisitor<'a> { } impl<'b, 'a: 'b> FmtVisitor<'a> { - fn set_parent_context(&mut self, context: &'a RewriteContext) { + fn set_parent_context(&mut self, context: &'a RewriteContext<'_>) { self.parent_context = Some(context); } @@ -255,7 +255,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // on traits do not get handled here. fn visit_fn( &mut self, - fk: visit::FnKind, + fk: visit::FnKind<'_>, generics: &ast::Generics, fd: &ast::FnDecl, s: Span, @@ -593,7 +593,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.skipped_range.push((lo, hi)); } - pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> { + pub fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { let mut visitor = FmtVisitor::from_source_map( ctx.parse_session, ctx.config, @@ -607,7 +607,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn from_source_map( parse_session: &'a ParseSess, config: &'a Config, - snippet_provider: &'a SnippetProvider, + snippet_provider: &'a SnippetProvider<'_>, report: FormatReport, ) -> FmtVisitor<'a> { FmtVisitor { @@ -785,7 +785,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub fn with_context(&mut self, f: F) -> Option where - F: Fn(&RewriteContext) -> Option, + F: Fn(&RewriteContext<'_>) -> Option, { // FIXME borrow checker fighting - can be simplified a lot with NLL. let (result, mrf) = { @@ -799,7 +799,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { result } - pub fn get_context(&self) -> RewriteContext { + pub fn get_context(&self) -> RewriteContext<'_> { RewriteContext { parse_session: self.parse_session, source_map: self.source_map, -- cgit 1.4.1-3-g733a5 From 8183b949c49cfdd5889859162e82fab4c8e64065 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Sat, 9 Feb 2019 16:20:38 +0900 Subject: cargo fmt --- src/cargo-fmt/main.rs | 1 - src/chains.rs | 14 +++++++++++--- src/expr.rs | 12 ++++++++++-- src/items.rs | 12 ++++++++++-- src/macros.rs | 12 ++++++++++-- src/overflow.rs | 5 ++++- src/patterns.rs | 6 +++++- 7 files changed, 50 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 05861743963..3873671781c 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -16,7 +16,6 @@ use cargo_metadata; use getopts; - use std::collections::{HashMap, HashSet}; use std::env; use std::fs; diff --git a/src/chains.rs b/src/chains.rs index 37bbde1f4ee..66862116323 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -84,7 +84,11 @@ use crate::utils::{ trimmed_last_line_width, wrap_str, }; -pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext<'_>, shape: Shape) -> Option { +pub fn rewrite_chain( + expr: &ast::Expr, + context: &RewriteContext<'_>, + shape: Shape, +) -> Option { let chain = Chain::from_ast(expr, context); debug!("rewrite_chain {:?} {:?}", chain, shape); @@ -419,8 +423,12 @@ impl Rewrite for Chain { debug!("rewrite chain {:?} {:?}", self, shape); let mut formatter = match context.config.indent_style() { - IndentStyle::Block => Box::new(ChainFormatterBlock::new(self)) as Box, - IndentStyle::Visual => Box::new(ChainFormatterVisual::new(self)) as Box, + IndentStyle::Block => { + Box::new(ChainFormatterBlock::new(self)) as Box + } + IndentStyle::Visual => { + Box::new(ChainFormatterVisual::new(self)) as Box + } }; formatter.format_root(&self.parent, context, shape)?; diff --git a/src/expr.rs b/src/expr.rs index 14a5ebd28ee..5b59a5114b5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -590,7 +590,11 @@ impl Rewrite for ast::Stmt { } // Rewrite condition if the given expression has one. -pub fn rewrite_cond(context: &RewriteContext<'_>, expr: &ast::Expr, shape: Shape) -> Option { +pub fn rewrite_cond( + context: &RewriteContext<'_>, + expr: &ast::Expr, + shape: Shape, +) -> Option { match expr.node { ast::ExprKind::Match(ref cond, _) => { // `match `cond` {` @@ -1337,7 +1341,11 @@ pub fn is_every_expr_simple(lists: &[OverflowableItem<'_>]) -> bool { lists.iter().all(OverflowableItem::is_simple) } -pub fn can_be_overflowed_expr(context: &RewriteContext<'_>, expr: &ast::Expr, args_len: usize) -> bool { +pub fn can_be_overflowed_expr( + context: &RewriteContext<'_>, + expr: &ast::Expr, + args_len: usize, +) -> bool { match expr.node { ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) diff --git a/src/items.rs b/src/items.rs index b272a42ba18..a18cba69d65 100644 --- a/src/items.rs +++ b/src/items.rs @@ -998,7 +998,11 @@ fn format_struct( } } -pub fn format_trait(context: &RewriteContext<'_>, item: &ast::Item, offset: Indent) -> Option { +pub fn format_trait( + context: &RewriteContext<'_>, + item: &ast::Item, + offset: Indent, +) -> Option { if let ast::ItemKind::Trait( is_auto, unsafety, @@ -1172,7 +1176,11 @@ pub fn format_trait_alias( rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";") } -fn format_unit_struct(context: &RewriteContext<'_>, p: &StructParts<'_>, offset: Indent) -> Option { +fn format_unit_struct( + context: &RewriteContext<'_>, + p: &StructParts<'_>, + offset: Indent, +) -> Option { let header_str = format_header(context, p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { let hi = if generics.where_clause.predicates.is_empty() { diff --git a/src/macros.rs b/src/macros.rs index 8243b6a9734..47985a4d6c0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1027,7 +1027,11 @@ fn wrap_macro_args_inner( // // We always try and format on one line. // FIXME: Use multi-line when every thing does not fit on one line. -fn format_macro_args(context: &RewriteContext<'_>, toks: TokenStream, shape: Shape) -> Option { +fn format_macro_args( + context: &RewriteContext<'_>, + toks: TokenStream, + shape: Shape, +) -> Option { if !context.config.format_macro_matchers() { let token_stream: TokenStream = toks.into(); let span = span_for_token_stream(&token_stream); @@ -1340,7 +1344,11 @@ impl MacroBranch { /// [pub] static ref NAME_N: TYPE_N = EXPR_N; /// } /// ``` -fn format_lazy_static(context: &RewriteContext<'_>, shape: Shape, ts: &TokenStream) -> Option { +fn format_lazy_static( + context: &RewriteContext<'_>, + shape: Shape, + ts: &TokenStream, +) -> Option { let mut result = String::with_capacity(1024); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); let nested_shape = shape diff --git a/src/overflow.rs b/src/overflow.rs index 8f50f08ed2a..3bd57711be9 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -758,7 +758,10 @@ fn no_long_items(list: &[ListItem]) -> bool { } /// In case special-case style is required, returns an offset from which we start horizontal layout. -pub fn maybe_get_args_offset(callee_str: &str, args: &[OverflowableItem<'_>]) -> Option<(bool, usize)> { +pub fn maybe_get_args_offset( + callee_str: &str, + args: &[OverflowableItem<'_>], +) -> Option<(bool, usize)> { if let Some(&(_, num_args_before)) = args .get(0)? .whitelist() diff --git a/src/patterns.rs b/src/patterns.rs index 6114362e76f..956ce56bdf1 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -288,7 +288,11 @@ impl<'a> Spanned for TuplePatField<'a> { } } -pub fn can_be_overflowed_pat(context: &RewriteContext<'_>, pat: &TuplePatField<'_>, len: usize) -> bool { +pub fn can_be_overflowed_pat( + context: &RewriteContext<'_>, + pat: &TuplePatField<'_>, + len: usize, +) -> bool { match *pat { TuplePatField::Pat(pat) => match pat.node { ast::PatKind::Path(..) -- cgit 1.4.1-3-g733a5 From b86dd161df35086d55dd627fa97337635cd2b046 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 9 Feb 2019 14:23:54 +0100 Subject: remove unneeded Version import --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 35f0cba26a8..c993d8390fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,7 +54,7 @@ use crate::utils::indent_next_line; pub use crate::config::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, Verbosity, Version, + Range, Verbosity, }; #[macro_use] -- cgit 1.4.1-3-g733a5 From 9a7ea6aacb12dd7b0aadc0cb9140f77d1ea1251f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 8 Feb 2019 12:28:35 +0900 Subject: Handle a macro argument with a single keyword Closes #3331. --- src/macros.rs | 101 ++++++++++++++++++++++++++++++++++++++++++++----- src/overflow.rs | 1 + src/spanned.rs | 1 + tests/source/macros.rs | 8 ++++ tests/target/macros.rs | 8 ++++ 5 files changed, 110 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index a925331f9fe..6b4c353cfd2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -26,7 +26,7 @@ use syntax::parse::parser::Parser; use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::print::pprust; use syntax::source_map::{BytePos, Span}; -use syntax::symbol; +use syntax::symbol::keywords; use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, parse, ptr}; @@ -64,6 +64,7 @@ pub enum MacroArg { Ty(ptr::P), Pat(ptr::P), Item(ptr::P), + Keyword(ast::Ident, Span), } impl MacroArg { @@ -92,6 +93,7 @@ impl Rewrite for MacroArg { MacroArg::Ty(ref ty) => ty.rewrite(context, shape), MacroArg::Pat(ref pat) => pat.rewrite(context, shape), MacroArg::Item(ref item) => item.rewrite(context, shape), + MacroArg::Keyword(ident, _) => Some(ident.to_string()), } } } @@ -156,7 +158,7 @@ fn rewrite_macro_name( format!("{}!", path) }; match extra_ident { - Some(ident) if ident != symbol::keywords::Invalid.ident() => format!("{} {}", name, ident), + Some(ident) if ident != keywords::Invalid.ident() => format!("{} {}", name, ident), _ => name, } } @@ -224,6 +226,23 @@ pub fn rewrite_macro( result } +fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { + for &keyword in RUST_KEYWORDS.iter() { + if parser.token.is_keyword(keyword) + && parser.look_ahead(1, |t| { + *t == Token::Eof + || *t == Token::Comma + || *t == Token::CloseDelim(DelimToken::NoDelim) + }) + { + let macro_arg = MacroArg::Keyword(keyword.ident(), parser.span); + parser.bump(); + return Some(macro_arg); + } + } + None +} + pub fn rewrite_macro_inner( mac: &ast::Mac, extra_ident: Option, @@ -276,11 +295,12 @@ pub fn rewrite_macro_inner( if DelimToken::Brace != style { loop { - match parse_macro_arg(&mut parser) { - Some(arg) => arg_vec.push(arg), - None => { - return return_macro_parse_failure_fallback(context, shape.indent, mac.span); - } + if let Some(arg) = parse_macro_arg(&mut parser) { + arg_vec.push(arg); + } else if let Some(arg) = check_keyword(&mut parser) { + arg_vec.push(arg); + } else { + return return_macro_parse_failure_fallback(context, shape.indent, mac.span); } match parser.token { @@ -1373,8 +1393,8 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) while parser.token != Token::Eof { // Parse a `lazy_static!` item. let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false)); - parser.eat_keyword(symbol::keywords::Static); - parser.eat_keyword(symbol::keywords::Ref); + parser.eat_keyword(keywords::Static); + parser.eat_keyword(keywords::Ref); let id = parse_or!(parse_ident); parser.eat(&Token::Colon); let ty = parse_or!(parse_ty); @@ -1449,3 +1469,66 @@ fn rewrite_macro_with_items( result.push_str(trailing_semicolon); Some(result) } + +const RUST_KEYWORDS: [keywords::Keyword; 60] = [ + keywords::PathRoot, + keywords::DollarCrate, + keywords::Underscore, + keywords::As, + keywords::Box, + keywords::Break, + keywords::Const, + keywords::Continue, + keywords::Crate, + keywords::Else, + keywords::Enum, + keywords::Extern, + keywords::False, + keywords::Fn, + keywords::For, + keywords::If, + keywords::Impl, + keywords::In, + keywords::Let, + keywords::Loop, + keywords::Match, + keywords::Mod, + keywords::Move, + keywords::Mut, + keywords::Pub, + keywords::Ref, + keywords::Return, + keywords::SelfLower, + keywords::SelfUpper, + keywords::Static, + keywords::Struct, + keywords::Super, + keywords::Trait, + keywords::True, + keywords::Type, + keywords::Unsafe, + keywords::Use, + keywords::Where, + keywords::While, + keywords::Abstract, + keywords::Become, + keywords::Do, + keywords::Final, + keywords::Macro, + keywords::Override, + keywords::Priv, + keywords::Typeof, + keywords::Unsized, + keywords::Virtual, + keywords::Yield, + keywords::Dyn, + keywords::Async, + keywords::Try, + keywords::UnderscoreLifetime, + keywords::StaticLifetime, + keywords::Auto, + keywords::Catch, + keywords::Default, + keywords::Existential, + keywords::Union, +]; diff --git a/src/overflow.rs b/src/overflow.rs index 04456aea106..6a2895d4ff9 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -167,6 +167,7 @@ impl<'a> OverflowableItem<'a> { MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), MacroArg::Pat(..) => false, MacroArg::Item(..) => len == 1, + MacroArg::Keyword(..) => false, }, OverflowableItem::NestedMetaItem(nested_meta_item) if len == 1 => { match nested_meta_item.node { diff --git a/src/spanned.rs b/src/spanned.rs index ab021ed7ec1..9c45d6ae705 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -198,6 +198,7 @@ impl Spanned for MacroArg { MacroArg::Ty(ref ty) => ty.span(), MacroArg::Pat(ref pat) => pat.span(), MacroArg::Item(ref item) => item.span(), + MacroArg::Keyword(_, span) => span, } } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 5386d68898d..d41a72e52f1 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -463,3 +463,11 @@ fn issue3004() { foo!(|_| { ( ) }); stringify!(( foo+ )); } + +// #3331 +pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { + Abi { + extern_token: Token ! [ extern ](tokens_helper(_visitor, &_i.extern_token.span)), + name: (_i.name).map(|it| _visitor.fold_lit_str(it)), + } +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index ca5f91b715e..d0fe892d91b 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1040,3 +1040,11 @@ fn issue3004() { foo!(|_| { () }); stringify!((foo+)); } + +// #3331 +pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { + Abi { + extern_token: Token![extern](tokens_helper(_visitor, &_i.extern_token.span)), + name: (_i.name).map(|it| _visitor.fold_lit_str(it)), + } +} -- cgit 1.4.1-3-g733a5 From 96a3df3b5ca025ee0010cb5b699a48f79bd962b9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 12 Feb 2019 10:16:12 +0900 Subject: Format visibility on trait alias --- src/items.rs | 4 +++- src/visitor.rs | 1 + tests/source/trait.rs | 7 +++++++ tests/target/trait.rs | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a18cba69d65..818cf5d6c91 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1163,6 +1163,7 @@ pub fn format_trait( pub fn format_trait_alias( context: &RewriteContext<'_>, ident: ast::Ident, + vis: &ast::Visibility, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, shape: Shape, @@ -1171,7 +1172,8 @@ pub fn format_trait_alias( // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; let generics_str = rewrite_generics(context, &alias, generics, g_shape)?; - let lhs = format!("trait {} =", generics_str); + let vis_str = format_visibility(context, vis); + let lhs = format!("{}trait {} =", vis_str, generics_str); // 1 = ";" rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";") } diff --git a/src/visitor.rs b/src/visitor.rs index ed4ab867586..8ca53401126 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -363,6 +363,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rw = format_trait_alias( &self.get_context(), item.ident, + &item.vis, generics, generic_bounds, shape, diff --git a/tests/source/trait.rs b/tests/source/trait.rs index d5ee4f04417..10802110951 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -84,7 +84,14 @@ trait FooBar = trait FooBar = Foo + Bar; +pub trait FooBar = + Foo + + Bar; +pub trait FooBar = + Foo + + Bar; trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +pub trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDDD; trait AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = FooBar; diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 18747c47fef..89a82847923 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -113,7 +113,11 @@ trait MyTrait< // Trait aliases trait FooBar = Foo + Bar; trait FooBar = Foo + Bar; +pub trait FooBar = Foo + Bar; +pub trait FooBar = Foo + Bar; trait AAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; +pub trait AAAAAAAAAAAAAAAAAA = + BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; trait AAAAAAAAAAAAAAAAAAA = BBBBBBBBBBBBBBBBBBB + CCCCCCCCCCCCCCCCCCCCCCCCCCCCC + DDDDDDDDDDDDDDDDDD; trait AAAAAAAAAAAAAAAAAA = -- cgit 1.4.1-3-g733a5 From 7d9a2ef96d8106fe399a0e97fc4087a76361c4e2 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Fri, 8 Feb 2019 21:39:11 +0900 Subject: version/2: Align loop and while formatting The loop and while formatting was diverting as `loop` was not being moved to a new, indented block, as `while` was. This commit fixes this inconsistency but pins it to version 2 to avoid changing existing code. --- src/closures.rs | 8 +++++--- tests/source/issue-3227/one.rs | 13 +++++++++++++ tests/source/issue-3227/two.rs | 13 +++++++++++++ tests/target/issue-3227/one.rs | 13 +++++++++++++ tests/target/issue-3227/two.rs | 15 +++++++++++++++ 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 tests/source/issue-3227/one.rs create mode 100644 tests/source/issue-3227/two.rs create mode 100644 tests/target/issue-3227/one.rs create mode 100644 tests/target/issue-3227/two.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index a0489718740..e74d0f7a44d 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -13,6 +13,7 @@ use syntax::source_map::Span; use syntax::{ast, ptr}; use crate::config::lists::*; +use crate::config::Version; use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; use crate::items::{span_hi_for_arg, span_lo_for_arg}; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; @@ -376,22 +377,23 @@ fn is_block_closure_forced(context: &RewriteContext, expr: &ast::Expr) -> bool { if context.inside_macro() { false } else { - is_block_closure_forced_inner(expr) + is_block_closure_forced_inner(expr, context.config.version()) } } -fn is_block_closure_forced_inner(expr: &ast::Expr) -> bool { +fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { match expr.node { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) | ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::Loop(..) if version == Version::Two => true, ast::ExprKind::AddrOf(_, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) - | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr), + | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr, version), _ => false, } } diff --git a/tests/source/issue-3227/one.rs b/tests/source/issue-3227/one.rs new file mode 100644 index 00000000000..fcc8331000d --- /dev/null +++ b/tests/source/issue-3227/one.rs @@ -0,0 +1,13 @@ +// rustfmt-version: One + +fn main() { + thread::spawn(|| { + while true { + println!("iteration"); + } + }); + + thread::spawn(|| loop { + println!("iteration"); + }); +} diff --git a/tests/source/issue-3227/two.rs b/tests/source/issue-3227/two.rs new file mode 100644 index 00000000000..c1572c00d57 --- /dev/null +++ b/tests/source/issue-3227/two.rs @@ -0,0 +1,13 @@ +// rustfmt-version: Two + +fn main() { + thread::spawn(|| { + while true { + println!("iteration"); + } + }); + + thread::spawn(|| loop { + println!("iteration"); + }); +} diff --git a/tests/target/issue-3227/one.rs b/tests/target/issue-3227/one.rs new file mode 100644 index 00000000000..fcc8331000d --- /dev/null +++ b/tests/target/issue-3227/one.rs @@ -0,0 +1,13 @@ +// rustfmt-version: One + +fn main() { + thread::spawn(|| { + while true { + println!("iteration"); + } + }); + + thread::spawn(|| loop { + println!("iteration"); + }); +} diff --git a/tests/target/issue-3227/two.rs b/tests/target/issue-3227/two.rs new file mode 100644 index 00000000000..374ab54305d --- /dev/null +++ b/tests/target/issue-3227/two.rs @@ -0,0 +1,15 @@ +// rustfmt-version: Two + +fn main() { + thread::spawn(|| { + while true { + println!("iteration"); + } + }); + + thread::spawn(|| { + loop { + println!("iteration"); + } + }); +} -- cgit 1.4.1-3-g733a5 From 9df1ed6ab49d7e7f94edb3c0585d7d899fec0d1a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 14 Feb 2019 11:08:05 +0900 Subject: Cargo update Update `rustc-ap-*` crates to 373.0.0. --- Cargo.lock | 104 +++++++++++++++++++++++++++------------------------------ Cargo.toml | 6 ++-- src/spanned.rs | 1 + src/types.rs | 2 ++ 4 files changed, 56 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 43e1ca13bbd..452f2a7d37a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -296,12 +296,8 @@ dependencies = [ [[package]] name = "memchr" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memoffset" @@ -315,7 +311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", @@ -454,7 +450,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -470,20 +466,20 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -493,16 +489,16 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -512,34 +508,34 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -547,29 +543,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "366.0.0" +version = "373.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -605,7 +601,7 @@ dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,7 +622,7 @@ name = "rustfmt-nightly" version = "1.0.1" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bytecount 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -638,9 +634,9 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", @@ -877,7 +873,7 @@ dependencies = [ "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum bytecount 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c219c0335c21a8bd79587ce5aee9f64aff1d0bd7a2cca7a58a815f9780cd3b0d" +"checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" "checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" @@ -905,10 +901,10 @@ dependencies = [ "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" @@ -926,15 +922,15 @@ dependencies = [ "checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" -"checksum rustc-ap-arena 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c1c284b1bd0fee735ff2dcc0e3463ffcb608e87ab38e34a4e1a4046b6cb0b1" -"checksum rustc-ap-graphviz 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6b811e0827f59c51d4ebae105aed916adec1b856b7977d6bb89b9dde5facf5e" -"checksum rustc-ap-rustc_cratesio_shim 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4153554ceefebe588b663c0c753405bb43027e535fbc00176074512a096a285" -"checksum rustc-ap-rustc_data_structures 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7bfee70c65cd8cc5ccfa7229886c67a2a22883a026c76a92bc94b7e0a5b618" -"checksum rustc-ap-rustc_errors 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "227a98739f3986bd01336922a7160f54b4b7a8c0c48cfc4691f51999cdf8089b" -"checksum rustc-ap-rustc_target 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1dd662b713db36ca8098c8b78d881157412a263c02b919782f32cc3ba7b35b6" -"checksum rustc-ap-serialize 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c93c7172e63fea0b5d0bb512e2505d144cd7a072576b8d78aa4d2196f958dff9" -"checksum rustc-ap-syntax 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89bd6296deeb4996445c1f59907c1a916bb6debcd09ffd1a75e0efc4ef5085e9" -"checksum rustc-ap-syntax_pos 366.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d00d2473c057c20bdb3845794e500ae123c3862b39e2a6cdaadeb272b16770" +"checksum rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8be999235b541fc8eb54901b66e899a06076709ac5f53d6b2c5c59d29ad54780" +"checksum rustc-ap-graphviz 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "532b5df15ca1a19a42815e37e521a20a7632b86b36868d1447932f8476f8f789" +"checksum rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c388afe1ef810013c878bdf9073ab1ae28dc49e9325863b351afb10acf4cc46e" +"checksum rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63a8f08b9fb6d607afb842ee7206273d09d69c9201bfc1c479a726093251a24e" +"checksum rustc-ap-rustc_errors 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dc0df7bf31588ea67e6386f6ad19f6b9a37ba7d5726ecad1cacce22e231bd98" +"checksum rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb4623a6f6c65b928cbe8d9c52b38cf57ba1722677645dc53fb1bdadfd0e127" +"checksum rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c290b148c9e4e08bbcb8a313393e257c1103cedf6a038aefc9f957c8a77c755" +"checksum rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "526fdc5bdbaaeae3b2a9ba42e5f5f7f29cda6ce8971b607a2955b1cb4ca339b5" +"checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544" diff --git a/Cargo.toml b/Cargo.toml index b62a25431ed..a05771b1e5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.7" -rustc-ap-rustc_target = "366.0.0" -rustc-ap-syntax = "366.0.0" -rustc-ap-syntax_pos = "366.0.0" +rustc-ap-rustc_target = "373.0.0" +rustc-ap-syntax = "373.0.0" +rustc-ap-syntax_pos = "373.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/spanned.rs b/src/spanned.rs index ab021ed7ec1..2fd9b124e0d 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -178,6 +178,7 @@ impl Spanned for ast::GenericArg { match *self { ast::GenericArg::Lifetime(ref lt) => lt.ident.span, ast::GenericArg::Type(ref ty) => ty.span(), + ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) } } } diff --git a/src/types.rs b/src/types.rs index 2bbf1ba9f22..7155a006de5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -152,6 +152,7 @@ impl<'a> SegmentParam<'a> { match arg { ast::GenericArg::Lifetime(ref lt) => SegmentParam::LifeTime(lt), ast::GenericArg::Type(ref ty) => SegmentParam::Type(ty), + ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) } } } @@ -463,6 +464,7 @@ impl Rewrite for ast::GenericArg { match *self { ast::GenericArg::Lifetime(ref lt) => lt.rewrite(context, shape), ast::GenericArg::Type(ref ty) => ty.rewrite(context, shape), + ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) } } } -- cgit 1.4.1-3-g733a5 From 7a3b7c9275f057aa1d71ea7516ef33a44bdffb7f Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 19 Feb 2019 02:56:42 +0000 Subject: Various cosmetic improvements (#3403) --- build.rs | 10 --- src/attr.rs | 10 --- src/bin/main.rs | 12 +-- src/cargo-fmt/main.rs | 18 +--- src/chains.rs | 18 +--- src/checkstyle.rs | 10 --- src/closures.rs | 12 +-- src/comment.rs | 67 ++++++-------- src/config/config_type.rs | 24 ++--- src/config/file_lines.rs | 24 ++--- src/config/license.rs | 2 +- src/config/lists.rs | 10 --- src/config/mod.rs | 16 +--- src/config/options.rs | 12 +-- src/expr.rs | 16 +--- src/format-diff/main.rs | 10 --- src/formatting.rs | 8 +- src/git-rustfmt/main.rs | 15 +--- src/imports.rs | 18 +--- src/issues.rs | 10 --- src/items.rs | 44 ++++----- src/lib.rs | 18 +--- src/lists.rs | 14 +-- src/macros.rs | 28 ++---- src/matches.rs | 14 +-- src/missed_spans.rs | 15 +--- src/modules.rs | 14 +-- src/overflow.rs | 12 +-- src/pairs.rs | 10 --- src/patterns.rs | 15 +--- src/reorder.rs | 12 +-- src/rewrite.rs | 12 +-- src/rustfmt_diff.rs | 14 +-- src/shape.rs | 10 --- src/source_file.rs | 10 --- src/source_map.rs | 10 --- src/spanned.rs | 10 --- src/string.rs | 14 +-- src/test/mod.rs | 100 ++++++++++----------- src/types.rs | 10 --- src/utils.rs | 14 +-- src/vertical.rs | 10 --- src/visitor.rs | 10 --- .../configs/struct_field_align_threshold/20.rs | 2 +- tests/source/fn-simple.rs | 2 +- tests/source/itemized-blocks/no_wrap.rs | 6 +- tests/source/itemized-blocks/wrap.rs | 6 +- tests/source/multiple.rs | 2 +- tests/source/soft-wrapping.rs | 2 +- tests/source/structs.rs | 2 +- tests/source/type-ascription.rs | 3 +- tests/source/unions.rs | 2 +- tests/target/comments-fn.rs | 2 +- tests/target/configs/combine_control_expr/false.rs | 3 +- tests/target/configs/combine_control_expr/true.rs | 3 +- .../configs/struct_field_align_threshold/20.rs | 2 +- tests/target/issue-3032.rs | 2 +- tests/target/itemized-blocks/no_wrap.rs | 6 +- tests/target/itemized-blocks/wrap.rs | 6 +- tests/target/multiple.rs | 2 +- tests/target/soft-wrapping.rs | 2 +- tests/target/structs.rs | 2 +- tests/target/unions.rs | 2 +- 63 files changed, 198 insertions(+), 603 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index 57422945ade..e7b1e1b854c 100644 --- a/build.rs +++ b/build.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::env; use std::fs::File; use std::io::Write; diff --git a/src/attr.rs b/src/attr.rs index 89b0367c484..3379bf2369b 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Format attributes and meta items. use syntax::ast; diff --git a/src/bin/main.rs b/src/bin/main.rs index b357eed34cf..dc1e64a27bb 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use env_logger; #[macro_use] extern crate failure; @@ -45,7 +35,7 @@ fn main() { // Exit with given exit code. // - // NOTE: This immediately terminates the process without doing any cleanup, + // NOTE: this immediately terminates the process without doing any cleanup, // so make sure to finish all necessary cleanup before this is called. std::process::exit(exit_code); } diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 3873671781c..e887b940fce 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -1,14 +1,4 @@ -// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/) +// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/). #![cfg(not(test))] #![deny(warnings)] @@ -146,12 +136,12 @@ fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result Vec { - // All arguments after -- are passed to rustfmt + // All arguments after -- are passed to rustfmt. env::args().skip_while(|a| a != "--").skip(1).collect() } @@ -160,7 +150,7 @@ fn get_fmt_args() -> Vec { pub struct Target { /// A path to the main source file of the target. path: PathBuf, - /// A kind of target (e.g. lib, bin, example, ...). + /// A kind of target (e.g., lib, bin, example, ...). kind: String, /// Rust edition for this target. edition: String, diff --git a/src/chains.rs b/src/chains.rs index 66862116323..3d928623aac 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -1,15 +1,5 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Formatting of chained expressions, i.e. expressions which are chained by -//! dots: struct and enum field access, method calls, and try shorthand (?). +//! Formatting of chained expressions, i.e., expressions that are chained by +//! dots: struct and enum field access, method calls, and try shorthand (`?`). //! //! Instead of walking these subexpressions one-by-one, as is our usual strategy //! for expression formatting, we collect maximal sequences of these expressions @@ -534,7 +524,7 @@ impl<'a> ChainFormatterShared<'a> { // ``` // // In particular, overflowing is effective when the last child is a method with a multi-lined - // block-like argument (e.g. closure): + // block-like argument (e.g., closure): // ```ignore // parent.child1.child2.last_child(|a, b, c| { // let x = foo(a, b, c); @@ -853,7 +843,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { } } -/// Remove try operators (`?`s) that appear in the given string. If removing +/// Removes try operators (`?`s) that appear in the given string. If removing /// them leaves an empty line, remove that line as well unless it is the first /// line (we need the first newline for detecting pre/post comment). fn trim_tries(s: &str) -> String { diff --git a/src/checkstyle.rs b/src/checkstyle.rs index efc35a0b083..169a3741be4 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::io::{self, Write}; use std::path::Path; diff --git a/src/closures.rs b/src/closures.rs index a93d718161a..381d083c82f 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use syntax::parse::classify; use syntax::source_map::Span; use syntax::{ast, ptr}; @@ -360,7 +350,7 @@ pub fn rewrite_last_closure( None } -/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`. +/// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`. pub fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool { args.iter() .filter_map(|arg| arg.to_expr()) diff --git a/src/comment.rs b/src/comment.rs index d9d367fa353..83ec810381e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Formatting and tools for comments. use std::{self, borrow::Cow, iter}; @@ -54,7 +44,7 @@ fn custom_opener(s: &str) -> &str { } impl<'a> CommentStyle<'a> { - /// Returns true if the commenting style covers a line only. + /// Returns `true` if the commenting style covers a line only. pub fn is_line_comment(&self) -> bool { match *self { CommentStyle::DoubleSlash @@ -65,7 +55,7 @@ impl<'a> CommentStyle<'a> { } } - /// Returns true if the commenting style can span over multiple lines. + /// Returns `true` if the commenting style can span over multiple lines. pub fn is_block_comment(&self) -> bool { match *self { CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation => { @@ -75,7 +65,7 @@ impl<'a> CommentStyle<'a> { } } - /// Returns true if the commenting style is for documentation. + /// Returns `true` if the commenting style is for documentation. pub fn is_doc_comment(&self) -> bool { match *self { CommentStyle::TripleSlash | CommentStyle::Doc => true, @@ -439,7 +429,7 @@ struct ItemizedBlock { } impl ItemizedBlock { - /// Returns true if the line is formatted as an item + /// Returns `true` if the line is formatted as an item fn is_itemized_line(line: &str) -> bool { let trimmed = line.trim_start(); trimmed.starts_with("* ") || trimmed.starts_with("- ") @@ -458,7 +448,7 @@ impl ItemizedBlock { } } - /// Returns a `StringFormat` used for formatting the content of an item + /// Returns a `StringFormat` used for formatting the content of an item. fn create_string_format<'a>(&'a self, fmt: &'a StringFormat<'_>) -> StringFormat<'a> { StringFormat { opener: "", @@ -471,8 +461,8 @@ impl ItemizedBlock { } } - /// Returns true if the line is part of the current itemized block. - /// If it is, then it is added to the internal lines vec. + /// Returns `true` if the line is part of the current itemized block. + /// If it is, then it is added to the internal lines list. fn add_line(&mut self, line: &str) -> bool { if !ItemizedBlock::is_itemized_line(line) && self.indent <= line.chars().take_while(|c| c.is_whitespace()).count() @@ -491,7 +481,7 @@ impl ItemizedBlock { .collect::() } - /// Returns the block as a string under its original form + /// Returns the block as a string under its original form. fn original_block_as_string(&self) -> String { self.lines.join("\n") } @@ -842,7 +832,7 @@ fn trim_custom_comment_prefix(s: &str) -> String { .join("\n") } -/// Returns true if the given string MAY include URLs or alike. +/// Returns `true` if the given string MAY include URLs or alike. fn has_url(s: &str) -> bool { // This function may return false positive, but should get its job done in most cases. s.contains("https://") || s.contains("http://") || s.contains("ftp://") || s.contains("file://") @@ -1000,8 +990,8 @@ impl FindUncommented for str { // Returns the first byte position after the first comment. The given string // is expected to be prefixed by a comment, including delimiters. -// Good: "/* /* inner */ outer */ code();" -// Bad: "code(); // hello\n world!" +// Good: `/* /* inner */ outer */ code();` +// Bad: `code(); // hello\n world!` pub fn find_comment_end(s: &str) -> Option { let mut iter = CharClasses::new(s.char_indices()); for (kind, (i, _c)) in &mut iter { @@ -1010,7 +1000,7 @@ pub fn find_comment_end(s: &str) -> Option { } } - // Handle case where the comment ends at the end of s. + // Handle case where the comment ends at the end of `s`. if iter.status == CharClassesStatus::Normal { Some(s.len()) } else { @@ -1018,7 +1008,7 @@ pub fn find_comment_end(s: &str) -> Option { } } -/// Returns true if text contains any comment. +/// Returns `true` if text contains any comment. pub fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) } @@ -1540,7 +1530,7 @@ impl<'a> Iterator for CommentCodeSlices<'a> { } /// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text -/// (if it fits in the width/offset, else return None), else return `new` +/// (if it fits in the width/offset, else return `None`), else return `new` pub fn recover_comment_removed( new: String, span: Span, @@ -1583,14 +1573,14 @@ pub fn filter_normal_code(code: &str) -> String { buffer } -/// Return true if the two strings of code have the same payload of comments. +/// Returns `true` if the two strings of code have the same payload of comments. /// The payload of comments is everything in the string except: -/// - actual code (not comments) -/// - comment start/end marks -/// - whitespace -/// - '*' at the beginning of lines in block comments +/// - actual code (not comments), +/// - comment start/end marks, +/// - whitespace, +/// - '*' at the beginning of lines in block comments. fn changed_comment_content(orig: &str, new: &str) -> bool { - // Cannot write this as a fn since we cannot return types containing closures + // Cannot write this as a fn since we cannot return types containing closures. let code_comment_content = |code| { let slices = UngroupedCommentCodeSlices::new(code); slices @@ -1625,7 +1615,8 @@ impl<'a> CommentReducer<'a> { let comment = remove_comment_header(comment); CommentReducer { is_block, - at_start_line: false, // There are no supplementary '*' on the first line + // There are no supplementary '*' on the first line. + at_start_line: false, iter: comment.chars(), } } @@ -1641,7 +1632,7 @@ impl<'a> Iterator for CommentReducer<'a> { while c.is_whitespace() { c = self.iter.next()?; } - // Ignore leading '*' + // Ignore leading '*'. if c == '*' { c = self.iter.next()?; } @@ -1777,7 +1768,7 @@ mod test { &wrap_normalize_config).unwrap(); assert_eq!("/* trimmed */", comment); - // check that different comment style are properly recognised + // Check that different comment style are properly recognised. let comment = rewrite_comment(r#"/// test1 /// test2 /* @@ -1788,7 +1779,7 @@ mod test { &wrap_normalize_config).unwrap(); assert_eq!("/// test1\n/// test2\n// test3", comment); - // check that the blank line marks the end of a commented paragraph + // Check that the blank line marks the end of a commented paragraph. let comment = rewrite_comment(r#"// test1 // test2"#, @@ -1797,7 +1788,7 @@ mod test { &wrap_normalize_config).unwrap(); assert_eq!("// test1\n\n// test2", comment); - // check that the blank line marks the end of a custom-commented paragraph + // Check that the blank line marks the end of a custom-commented paragraph. let comment = rewrite_comment(r#"//@ test1 //@ test2"#, @@ -1806,7 +1797,7 @@ mod test { &wrap_normalize_config).unwrap(); assert_eq!("//@ test1\n\n//@ test2", comment); - // check that bare lines are just indented but left unchanged otherwise + // Check that bare lines are just indented but otherwise left unchanged. let comment = rewrite_comment(r#"// test1 /* a bare line! @@ -1819,8 +1810,8 @@ mod test { assert_eq!("// test1\n/*\n a bare line!\n\n another bare line!\n*/", comment); } - // This is probably intended to be a non-test fn, but it is not used. I'm - // keeping it around unless it helps us test stuff. + // This is probably intended to be a non-test fn, but it is not used. + // We should keep this around unless it helps us test stuff to remove it. fn uncommented(text: &str) -> String { CharClasses::new(text.chars()) .filter_map(|(s, c)| match s { diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 08d086c668e..4d09eea7c47 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use crate::config::file_lines::FileLines; use crate::config::options::{IgnoreList, WidthHeuristics}; @@ -60,14 +50,14 @@ impl ConfigType for IgnoreList { } } -/// Check if we're in a nightly build. +/// Checks if we're in a nightly build. /// /// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap /// to "stable", "beta", or "nightly" depending on what toolchain is being built. /// If we are being built as part of the stable or beta toolchains, we want /// to disable unstable configuration options. /// -/// If we're being built by cargo (e.g. `cargo +nightly install rustfmt-nightly`), +/// If we're being built by cargo (e.g., `cargo +nightly install rustfmt-nightly`), /// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the /// nightly compiler when installed from crates.io, default to nightly mode. macro_rules! is_nightly_channel { @@ -297,13 +287,13 @@ macro_rules! create_config { } } - /// Construct a `Config` from the toml file specified at `file_path`. + /// Constructs a `Config` from the toml file specified at `file_path`. /// /// This method only looks at the provided path, for a method that /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. /// - /// Return a `Config` if the config could be read and parsed from - /// the file, Error otherwise. + /// Returns a `Config` if the config could be read and parsed from + /// the file, otherwise errors. pub(super) fn from_toml_path(file_path: &Path) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); @@ -312,7 +302,7 @@ macro_rules! create_config { .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } - /// Resolve the config for input in `dir`. + /// Resolves the config for input in `dir`. /// /// Searches for `rustfmt.toml` beginning with `dir`, and /// recursively checking parents of `dir` if no config file is found. @@ -441,7 +431,7 @@ macro_rules! create_config { self.ignore.2.add_prefix(dir); } - /// Returns true if the config key was explicitly set and is the default value. + /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { $( if let stringify!($i) = key { diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index a7371a3da90..c085a0b5deb 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -1,13 +1,3 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This module contains types and functions to support formatting specific line ranges. use std::collections::HashMap; @@ -191,7 +181,7 @@ impl FileLines { FileLines(None) } - /// Returns true if this `FileLines` contains all lines in all files. + /// Returns `true` if this `FileLines` contains all lines in all files. pub(crate) fn is_all(&self) -> bool { self.0.is_none() } @@ -221,8 +211,8 @@ impl FileLines { } } - /// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in - /// the designated file (if any) and returns true if `f` ever does. + /// Returns `true` if `self` includes all lines in all files. Otherwise runs `f` on all ranges + /// in the designated file (if any) and returns true if `f` ever does. fn file_range_matches(&self, file_name: &FileName, f: F) -> bool where F: FnMut(&Range) -> bool, @@ -239,23 +229,23 @@ impl FileLines { } } - /// Returns true if `range` is fully contained in `self`. + /// Returns `true` if `range` is fully contained in `self`. #[allow(dead_code)] pub(crate) fn contains(&self, range: &LineRange) -> bool { self.file_range_matches(&range.file_name(), |r| r.contains(Range::from(range))) } - /// Returns true if any lines in `range` are in `self`. + /// Returns `true` if any lines in `range` are in `self`. pub(crate) fn intersects(&self, range: &LineRange) -> bool { self.file_range_matches(&range.file_name(), |r| r.intersects(Range::from(range))) } - /// Returns true if `line` from `file_name` is in `self`. + /// Returns `true` if `line` from `file_name` is in `self`. pub(crate) fn contains_line(&self, file_name: &FileName, line: usize) -> bool { self.file_range_matches(file_name, |r| r.lo <= line && r.hi >= line) } - /// Returns true if all the lines between `lo` and `hi` from `file_name` are in `self`. + /// Returns `true` if all the lines between `lo` and `hi` from `file_name` are in `self`. pub(crate) fn contains_range(&self, file_name: &FileName, lo: usize, hi: usize) -> bool { self.file_range_matches(file_name, |r| r.contains(Range::new(lo, hi))) } diff --git a/src/config/license.rs b/src/config/license.rs index 38e37508450..7adaecf9d5c 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -67,7 +67,7 @@ impl TemplateParser { } } - /// Convert a license template into a string which can be turned into a regex. + /// Converts a license template into a string which can be turned into a regex. /// /// The license template could use regex syntax directly, but that would require a lot of manual /// escaping, which is inconvenient. It is therefore literal by default, with optional regex diff --git a/src/config/lists.rs b/src/config/lists.rs index 74f8e186180..79fd3db5b6e 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Configuration options related to rewriting a list. use crate::config::config_type::ConfigType; diff --git a/src/config/mod.rs b/src/config/mod.rs index e51279018e2..6c09e4b0b1a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::cell::Cell; use std::default::Default; use std::fs::File; @@ -65,7 +55,7 @@ create_config! { struct_lit_single_line: bool, true, false, "Put small struct literals on a single line"; fn_single_line: bool, false, false, "Put single-expression functions on a single line"; - where_single_line: bool, false, false, "Force where clauses to be on a single line"; + where_single_line: bool, false, false, "Force where-clauses to be on a single line"; // Imports imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports"; @@ -157,7 +147,7 @@ create_config! { make_backup: bool, false, false, "Backup changed files"; } -/// Load a config by checking the client-supplied options and if appropriate, the +/// Loads a config by checking the client-supplied options and if appropriate, the /// file system (including searching the file system for overrides). pub fn load_config( file_path: Option<&Path>, @@ -333,7 +323,7 @@ mod test { assert_eq!(s.contains("(unstable)"), true); } - // FIXME(#2183) these tests cannot be run in parallel because they use env vars + // FIXME(#2183): these tests cannot be run in parallel because they use env vars. // #[test] // fn test_as_not_nightly_channel() { // let mut config = Config::default(); diff --git a/src/config/options.rs b/src/config/options.rs index f167c34aedf..be32c142916 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::HashSet; use std::path::{Path, PathBuf}; @@ -199,7 +189,7 @@ impl NewlineStyle { configuration_option_enum! { BraceStyle: AlwaysNextLine, PreferSameLine, - // Prefer same line except where there is a where clause, in which case force + // Prefer same line except where there is a where-clause, in which case force // the brace to the next line. SameLineWhere, } diff --git a/src/expr.rs b/src/expr.rs index 5b59a5114b5..d4461293d60 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Cow; use std::cmp::min; @@ -626,7 +616,7 @@ struct ControlFlow<'a> { matcher: &'a str, connector: &'a str, allow_single_line: bool, - // True if this is an `if` expression in an `else if` :-( hacky + // HACK: `true` if this is an `if` expression in an `else if`. nested_if: bool, span: Span, } @@ -812,7 +802,7 @@ impl<'a> ControlFlow<'a> { } } -/// Returns true if the last line of pat_str has leading whitespace and it is wider than the +/// Returns `true` if the last line of pat_str has leading whitespace and it is wider than the /// shape's indent. fn last_line_offsetted(start_column: usize, pat_str: &str) -> bool { let mut leading_whitespaces = 0; @@ -1402,7 +1392,7 @@ pub fn is_nested_call(expr: &ast::Expr) -> bool { } } -/// Return true if a function call or a method call represented by the given span ends with a +/// Returns `true` if a function call or a method call represented by the given span ends with a /// trailing comma. This function is used when rewriting macro, as adding or removing a trailing /// comma from macro can potentially break the code. pub fn span_ends_with_comma(context: &RewriteContext<'_>, span: Span) -> bool { diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 5ffff79811c..a10a04386aa 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Inspired by Clang's clang-format-diff: // // https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py diff --git a/src/formatting.rs b/src/formatting.rs index 91930bad00a..38440802ef2 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -301,7 +301,7 @@ pub(crate) type FormatErrorMap = HashMap>; #[derive(Default, Debug)] pub(crate) struct ReportedErrors { - // Encountered e.g. an IO error. + // Encountered e.g., an IO error. pub(crate) has_operational_errors: bool, // Failed to reformat code because of parsing errors. @@ -415,7 +415,7 @@ impl Timer { } // Formatting done on a char by char or line by line basis. -// FIXME(#20) other stuff for parity with make tidy +// FIXME(#20): other stuff for parity with make tidy. fn format_lines( text: &mut String, name: &FileName, @@ -446,7 +446,7 @@ struct FormatLines<'a> { errors: Vec, issue_seeker: BadIssueSeeker, line_buffer: String, - // true if the current line contains a string literal. + // `true` if the current line contains a string literal. is_string: bool, format_line: bool, allow_issue_seek: bool, @@ -593,7 +593,7 @@ impl<'a> FormatLines<'a> { } } - /// Returns true if the line with the given line number was skipped by `#[rustfmt::skip]`. + /// Returns `true` if the line with the given line number was skipped by `#[rustfmt::skip]`. fn is_skipped_line(&self) -> bool { self.skipped_range .iter() diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index aae81ba3270..67b641a384d 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -1,18 +1,5 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use env_logger; - #[macro_use] extern crate log; -use rustfmt_nightly as rustfmt; use std::env; use std::io::stdout; @@ -20,7 +7,9 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; +use env_logger; use getopts::{Matches, Options}; +use rustfmt_nightly as rustfmt; use crate::rustfmt::{load_config, CliOptions, Input, Session}; diff --git a/src/imports.rs b/src/imports.rs index 6ca29cfeaed..43835c30e4b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; @@ -28,8 +18,8 @@ use crate::spanned::Spanned; use crate::utils::{is_same_visibility, mk_sp, rewrite_ident}; use crate::visitor::FmtVisitor; -/// Returns a name imported by a `use` declaration. e.g. returns `Ordering` -/// for `std::cmp::Ordering` and `self` for `std::cmp::self`. +/// Returns a name imported by a `use` declaration. +/// E.g., returns `Ordering` for `std::cmp::Ordering` and `self` for `std::cmp::self`. pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { path.segments.last().unwrap().ident } @@ -87,7 +77,7 @@ impl<'a> FmtVisitor<'a> { // when ordering unless the imports are identical except for the alias (rare in // practice). -// FIXME(#2531) - we should unify the comparison code here with the formatting +// FIXME(#2531): we should unify the comparison code here with the formatting // code elsewhere since we are essentially string-ifying twice. Furthermore, by // parsing to our own format on comparison, we repeat a lot of work when // sorting. @@ -267,7 +257,7 @@ impl UseTree { // FIXME: Use correct span? // The given span is essentially incorrect, since we are reconstructing - // use statements. This should not be a problem, though, since we have + // use-statements. This should not be a problem, though, since we have // already tried to extract comment and observed that there are no comment // around the given use item, and the span will not be used afterward. fn from_path(path: Vec, span: Span) -> UseTree { diff --git a/src/issues.rs b/src/issues.rs index 3716110465e..c89469bff79 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Objects for seeking through a char stream for occurrences of TODO and FIXME. // Depending on the loaded configuration, may also check that these have an // associated issue number. diff --git a/src/items.rs b/src/items.rs index 818cf5d6c91..c2568735ad8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Formatting top-level items - functions, structs, enums, traits, impls. use std::borrow::Cow; @@ -715,7 +705,7 @@ pub fn format_impl( false, )?; - // If there is no where clause, we may have missing comments between the trait name and + // If there is no where-clause, we may have missing comments between the trait name and // the opening brace. if generics.where_clause.predicates.is_empty() { if let Some(hi) = where_span_end { @@ -737,7 +727,7 @@ pub fn format_impl( result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { // if the where_clause contains extra comments AND - // there is only one where clause predicate + // there is only one where-clause predicate // recover the suppressed comma in single line where_clause formatting if generics.where_clause.predicates.len() == 1 { result.push_str(","); @@ -868,7 +858,7 @@ fn format_impl_ref_and_type( // ` for` let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { - // If there is no where clause adapt budget for type formatting to take space and curly + // If there is no where-clause adapt budget for type formatting to take space and curly // brace into account. match context.config.brace_style() { BraceStyle::AlwaysNextLine => 0, @@ -1047,7 +1037,7 @@ pub fn format_trait( )?; } - // Rewrite where clause. + // Rewrite where-clause. if !generics.where_clause.predicates.is_empty() { let where_density = if context.config.indent_style() == IndentStyle::Block { Density::Compressed @@ -1074,8 +1064,8 @@ pub fn format_trait( option, false, )?; - // If the where clause cannot fit on the same line, - // put the where clause on a new line + // If the where-clause cannot fit on the same line, + // put the where-clause on a new line if !where_clause_str.contains('\n') && last_line_width(&result) + where_clause_str.len() + offset.width() > context.config.comment_width() @@ -1426,8 +1416,8 @@ fn format_tuple_struct( || offset.block_indent + result.len() + where_clause_str.len() + 1 > context.config.max_width()) { - // We need to put the where clause on a new line, but we didn't - // know that earlier, so the where clause will not be indented properly. + // We need to put the where-clause on a new line, but we didn't + // know that earlier, so the where-clause will not be indented properly. result.push('\n'); result.push_str( &(offset.block_only() + (context.config.tab_spaces() - 1)).to_string(context.config), @@ -2122,7 +2112,7 @@ fn rewrite_fn_base( // the closing parenthesis of the argument and the arrow '->' is considered. let mut sig_length = result.len() + indent.width() + ret_str_len + 1; - // If there is no where clause, take into account the space after the return type + // If there is no where-clause, take into account the space after the return type // and the brace. if where_clause.predicates.is_empty() { sig_length += 2; @@ -2139,7 +2129,7 @@ fn rewrite_fn_base( } else { // FIXME: we might want to check that using the arg indent // doesn't blow our budget, and if it does, then fallback to - // the where clause indent. + // the where-clause indent. arg_indent }; @@ -2215,7 +2205,7 @@ fn rewrite_fn_base( option, is_args_multi_lined, )?; - // If there are neither where clause nor return type, we may be missing comments between + // If there are neither where-clause nor return type, we may be missing comments between // args and `{`. if where_clause_str.is_empty() { if let ast::FunctionRetTy::Default(ret_span) = fd.output { @@ -2245,7 +2235,7 @@ fn rewrite_fn_base( struct WhereClauseOption { suppress_comma: bool, // Force no trailing comma snuggle: bool, // Do not insert newline before `where` - compress_where: bool, // Try single line where clause instead of vertical layout + compress_where: bool, // Try single line where-clause instead of vertical layout } impl WhereClauseOption { @@ -2515,8 +2505,8 @@ fn rewrite_generics( generics: &ast::Generics, shape: Shape, ) -> Option { - // FIXME: convert bounds to where clauses where they get too big or if - // there is a where clause at all. + // FIXME: convert bounds to where-clauses where they get too big or if + // there is a where-clause at all. if generics.params.is_empty() { return Some(ident.to_owned()); @@ -2593,7 +2583,7 @@ fn rewrite_where_clause_rfc_style( }; // shape should be vertical only and only if we have `where_single_line` option enabled - // and the number of items of the where clause is equal to 1 + // and the number of items of the where-clause is equal to 1 let shape_tactic = if where_single_line { DefinitiveListTactic::Horizontal } else { @@ -2703,7 +2693,7 @@ fn rewrite_where_clause( let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget); let mut comma_tactic = context.config.trailing_comma(); - // Kind of a hack because we don't usually have trailing commas in where clauses. + // Kind of a hack because we don't usually have trailing commas in where-clauses. if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma { comma_tactic = SeparatorTactic::Never; } @@ -2945,7 +2935,7 @@ pub fn rewrite_extern_crate(context: &RewriteContext<'_>, item: &ast::Item) -> O }) } -/// Returns true for `mod foo;`, false for `mod foo { .. }`. +/// Returns `true` for `mod foo;`, false for `mod foo { .. }`. pub fn is_mod_decl(item: &ast::Item) -> bool { match item.node { ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), diff --git a/src/lib.rs b/src/lib.rs index 49ddbdb0a6c..520a6e66fcd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,3 @@ -// Copyright 2015-2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![deny(rust_2018_idioms)] #[macro_use] @@ -155,7 +145,7 @@ impl FormattedSnippet { }); } - /// Returns true if the line n did not get formatted. + /// Returns `true` if the line n did not get formatted. fn is_line_non_formatted(&self, n: usize) -> bool { self.non_formatted_ranges .iter() @@ -408,9 +398,9 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { } /// Format the given code block. Mainly targeted for code block in comment. -/// The code block may be incomplete (i.e. parser may be unable to parse it). +/// The code block may be incomplete (i.e., parser may be unable to parse it). /// To avoid panic in parser, we wrap the code block with a dummy function. -/// The returned code block does *not* end with newline. +/// The returned code block does **not** end with newline. fn format_code_block(code_snippet: &str, config: &Config) -> Option { const FN_MAIN_PREFIX: &str = "fn main() {\n"; @@ -437,7 +427,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option "\r\n" conversion process after here if it's necessary. let mut config_with_unix_newline = config.clone(); diff --git a/src/lists.rs b/src/lists.rs index 0fb1eec68d0..cbf5d35c49c 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Format list-like expressions and items. use std::cmp; @@ -29,7 +19,7 @@ pub struct ListFormatting<'a> { trailing_separator: SeparatorTactic, separator_place: SeparatorPlace, shape: Shape, - // Non-expressions, e.g. items, will have a new line at the end of the list. + // Non-expressions, e.g., items, will have a new line at the end of the list. // Important for comment styles. ends_with_newline: bool, // Remove newlines between list elements for expressions. @@ -198,7 +188,7 @@ impl ListItem { } } - // true if the item causes something to be written. + // Returns `true` if the item causes something to be written. fn is_substantial(&self) -> bool { fn empty(s: &Option) -> bool { match *s { diff --git a/src/macros.rs b/src/macros.rs index d79ae82980d..6bc181fc6f9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Format list-like macro invocations. These are invocations whose token trees // can be interpreted as expressions and separated by commas. // Note that these token trees do not actually have to be interpreted as @@ -601,9 +591,9 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { #[derive(Debug, Clone)] enum MacroArgKind { - /// e.g. `$x: expr`. + /// e.g., `$x: expr`. MetaVariable(ast::Ident, String), - /// e.g. `$($foo: expr),*` + /// e.g., `$($foo: expr),*` Repeat( /// `()`, `[]` or `{}`. DelimToken, @@ -614,12 +604,12 @@ enum MacroArgKind { /// The repeat token. This could be one of `*`, `+` or `?`. Token, ), - /// e.g. `[derive(Debug)]` + /// e.g., `[derive(Debug)]` Delimited(DelimToken, Vec), - /// A possible separator. e.g. `,` or `;`. + /// A possible separator. e.g., `,` or `;`. Separator(String, String), /// Other random stuff that does not fit to other kinds. - /// e.g. `== foo` in `($x: expr == foo)`. + /// e.g., `== foo` in `($x: expr == foo)`. Other(String, String), } @@ -752,13 +742,13 @@ impl ParsedMacroArg { /// Parses macro arguments on macro def. struct MacroArgParser { - /// Holds either a name of the next metavariable, a separator or a junk. + /// Either a name of the next metavariable, a separator, or junk. buf: String, /// The start position on the current buffer. lo: BytePos, /// The first token of the current buffer. start_tok: Token, - /// Set to true if we are parsing a metavariable or a repeat. + /// `true` if we are parsing a metavariable or a repeat. is_meta_var: bool, /// The position of the last token. hi: BytePos, @@ -1139,8 +1129,8 @@ fn next_space(tok: &Token) -> SpaceState { } } -/// Tries to convert a macro use into a short hand try expression. Returns None -/// when the macro is not an instance of try! (or parsing the inner expression +/// Tries to convert a macro use into a short hand try expression. Returns `None` +/// when the macro is not an instance of `try!` (or parsing the inner expression /// failed). pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { if &mac.node.path.to_string() == "try" { diff --git a/src/matches.rs b/src/matches.rs index 15ff7dbb8fe..c3102f12123 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Format match expression. use std::iter::repeat; @@ -35,8 +25,8 @@ use crate::utils::{ /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. struct ArmWrapper<'a> { pub arm: &'a ast::Arm, - /// True if the arm is the last one in match expression. Used to decide on whether we should add - /// trailing comma to the match arm when `config.trailing_comma() == Never`. + /// `true` if the arm is the last one in match expression. Used to decide on whether we should + /// add trailing comma to the match arm when `config.trailing_comma() == Never`. pub is_last: bool, /// Holds a byte position of `|` at the beginning of the arm pattern, if available. pub beginning_vert: Option, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 740378fbc2a..008efd2bef1 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Cow; use syntax::source_map::{BytePos, Pos, Span}; @@ -44,9 +34,8 @@ impl<'a> FmtVisitor<'a> { } pub fn format_missing(&mut self, end: BytePos) { - // HACK(topecongiro) - // We use `format_missing()` to extract a missing comment between a macro - // (or alike) and a trailing semicolon. Here we just try to avoid calling + // HACK(topecongiro): we use `format_missing()` to extract a missing comment between + // a macro (or similar) and a trailing semicolon. Here we just try to avoid calling // `format_missing_inner` in the common case where there is no such comment. // This is a hack, ideally we should fix a possible bug in `format_missing_inner` // or refactor `visit_mac` and `rewrite_macro`, but this should suffice to fix the diff --git a/src/modules.rs b/src/modules.rs index 1a89be66e8f..7bb50356ed8 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::BTreeMap; use std::io; use std::path::{Path, PathBuf}; @@ -47,7 +37,7 @@ fn path_value(attr: &ast::Attribute) -> Option { } } -// N.B. Even when there are multiple `#[path = ...]` attributes, we just need to +// N.B., even when there are multiple `#[path = ...]` attributes, we just need to // examine the first one, since rustc ignores the second and the subsequent ones // as unused attributes. fn find_path_value(attrs: &[ast::Attribute]) -> Option { @@ -88,7 +78,7 @@ fn list_submodules<'a>( Ok(()) } -/// Find the file corresponding to an external mod +/// Finds the file corresponding to an external mod fn module_file( id: ast::Ident, attrs: &[ast::Attribute], diff --git a/src/overflow.rs b/src/overflow.rs index 27923ddfc7c..ac425b591aa 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Rewrite a list some items with overflow. use std::cmp::min; @@ -513,7 +503,7 @@ impl<'a> Context<'a> { // When we are rewriting a nested function call, we restrict the // budget for the inner function to avoid them being deeply nested. // However, when the inner function has a prefix or a suffix - // (e.g. `foo() as u32`), this budget reduction may produce poorly + // (e.g., `foo() as u32`), this budget reduction may produce poorly // formatted code, where a prefix or a suffix being left on its own // line. Here we explicitlly check those cases. if count_newlines(overflowed) == 1 { diff --git a/src/pairs.rs b/src/pairs.rs index 8429d33114f..421167ad6d7 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use syntax::ast; use crate::config::lists::*; diff --git a/src/patterns.rs b/src/patterns.rs index 956ce56bdf1..2140b8d870f 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; use syntax::ptr; use syntax::source_map::{self, BytePos, Span}; @@ -29,7 +19,8 @@ use crate::spanned::Spanned; use crate::types::{rewrite_path, PathContext}; use crate::utils::{format_mutability, mk_sp, rewrite_ident}; -/// Returns true if the given pattern is short. A short pattern is defined by the following grammar: +/// Returns `true` if the given pattern is "short". +/// A short pattern is defined by the following grammar: /// /// [small, ntp]: /// - single token @@ -152,7 +143,7 @@ impl Rewrite for Pat { let pats: Option> = prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); - // Check that all the rewrites succeeded, and if not return None. + // Check that all the rewrites succeeded, and if not return `None`. let pats = pats?; // Unwrap all the sub-strings and join them with commas. diff --git a/src/reorder.rs b/src/reorder.rs index e078cc3279b..40f6f07c8dc 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -1,13 +1,3 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Reorder items. //! //! `mod`, `extern crate` and `use` declarations are reordered in alphabetical @@ -263,7 +253,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item_length } - /// Visit and format the given items. Items are reordered If they are + /// Visits and format the given items. Items are reordered If they are /// consecutive and reorderable. pub fn visit_items_with_reordering(&mut self, mut items: &[&ast::Item]) { while !items.is_empty() { diff --git a/src/rewrite.rs b/src/rewrite.rs index 5c5ed438f5e..df147e0c427 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // A generic trait to abstract the rewriting of an element (of the AST). use std::cell::RefCell; @@ -56,7 +46,7 @@ impl<'a> RewriteContext<'a> { self.snippet_provider.span_to_snippet(span).unwrap() } - /// Return true if we should use block indent style for rewriting function call. + /// Returns `true` if we should use block indent style for rewriting function call. pub fn use_block_indent(&self) -> bool { self.config.indent_style() == IndentStyle::Block || *self.use_block.borrow() } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 81778c33ecf..c6262dcab15 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::VecDeque; use std::io; use std::io::Write; @@ -184,11 +174,11 @@ where } } -/// Convert a Mismatch into a serialised form which just includes +/// Converts a `Mismatch` into a serialized form, which just includes /// enough information to modify the original file. /// Each section starts with a line with three integers, space separated: /// lineno num_removed num_added -/// followed by (num_added) lines of added text. The line numbers are +/// followed by (`num_added`) lines of added text. The line numbers are /// relative to the original file. pub fn output_modified(mut out: W, diff: Vec) where diff --git a/src/shape.rs b/src/shape.rs index 1b1217346fa..d793d99a318 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Cow; use std::cmp::min; use std::ops::{Add, Sub}; diff --git a/src/source_file.rs b/src/source_file.rs index b26cd0521fa..07c1e37fbed 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::fs; use std::io::{self, Write}; diff --git a/src/source_map.rs b/src/source_map.rs index 8caff51ee40..d0c4adbe61d 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -1,13 +1,3 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. diff --git a/src/spanned.rs b/src/spanned.rs index 22079a45bea..068a3b8b4f4 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::cmp::max; use syntax::{ diff --git a/src/string.rs b/src/string.rs index cb174841738..8b910c0b4ce 100644 --- a/src/string.rs +++ b/src/string.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Format string literals. use regex::Regex; @@ -163,8 +153,8 @@ pub fn rewrite_string<'a>( wrap_str(result, fmt.config.max_width(), fmt.shape) } -/// Returns the index to the end of the url if the given string includes an -/// URL or alike. Otherwise, returns None; +/// Returns the index to the end of the URL if the given string includes an +/// URL or alike. Otherwise, returns `None`; fn detect_url(s: &[&str], index: usize) -> Option { let start = match s[..=index].iter().rposition(|g| is_whitespace(g)) { Some(pos) => pos + 1, diff --git a/src/test/mod.rs b/src/test/mod.rs index ac2a1a3ba22..2d1a62ceda5 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::collections::{HashMap, HashSet}; use std::env; use std::fs; @@ -27,17 +17,17 @@ use crate::{FormatReport, Input, Session}; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; -// Returns a `Vec` containing `PathBuf`s of files with a rs extension in the +// Returns a `Vec` containing `PathBuf`s of files with an `rs` extension in the // given path. The `recursive` argument controls if files from subdirectories // are also returned. fn get_test_files(path: &Path, recursive: bool) -> Vec { let mut files = vec![]; if path.is_dir() { for entry in fs::read_dir(path).expect(&format!( - "Couldn't read directory {}", + "couldn't read directory {}", path.to_str().unwrap() )) { - let entry = entry.expect("Couldn't get DirEntry"); + let entry = entry.expect("couldn't get `DirEntry`"); let path = entry.path(); if path.is_dir() && recursive { files.append(&mut get_test_files(&path, recursive)); @@ -51,15 +41,15 @@ fn get_test_files(path: &Path, recursive: bool) -> Vec { fn verify_config_used(path: &Path, config_name: &str) { for entry in fs::read_dir(path).expect(&format!( - "Couldn't read {} directory", + "couldn't read {} directory", path.to_str().unwrap() )) { - let entry = entry.expect("Couldn't get directory entry"); + let entry = entry.expect("couldn't get directory entry"); let path = entry.path(); if path.extension().map_or(false, |f| f == "rs") { // check if "// rustfmt-:" appears in the file. let filebuf = BufReader::new( - fs::File::open(&path).expect(&format!("Couldn't read file {}", path.display())), + fs::File::open(&path).expect(&format!("couldn't read file {}", path.display())), ); assert!( filebuf @@ -82,8 +72,8 @@ fn verify_config_test_names() { Path::new("tests/source/configs"), Path::new("tests/target/configs"), ] { - for entry in fs::read_dir(path).expect("Couldn't read configs directory") { - let entry = entry.expect("Couldn't get directory entry"); + for entry in fs::read_dir(path).expect("couldn't read configs directory") { + let entry = entry.expect("couldn't get directory entry"); let path = entry.path(); if path.is_dir() { let config_name = path.file_name().unwrap().to_str().unwrap(); @@ -95,8 +85,8 @@ fn verify_config_test_names() { } } -// This writes to the terminal using the same approach (via term::stdout or -// println!) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing +// This writes to the terminal using the same approach (via `term::stdout` or +// `println!`) that is used by `rustfmt::rustfmt_diff::print_diff`. Writing // using only one or the other will cause the output order to differ when // `print_diff` selects the approach not used. fn write_message(msg: &str) { @@ -104,8 +94,8 @@ fn write_message(msg: &str) { writer.writeln(msg, None); } -// Integration tests. The files in the tests/source are formatted and compared -// to their equivalent in tests/target. The target file and config can be +// Integration tests. The files in `tests/source` are formatted and compared +// to their equivalent in `tests/target`. The target file and config can be // overridden by annotations in the source file. The input and output must match // exactly. #[test] @@ -119,8 +109,8 @@ fn system_tests() { assert_eq!(fails, 0, "{} system tests failed", fails); } -// Do the same for tests/coverage-source directory -// the only difference is the coverage mode +// Do the same for tests/coverage-source directory. +// The only difference is the coverage mode. #[test] fn coverage_tests() { let files = get_test_files(Path::new("tests/coverage/source"), true); @@ -205,7 +195,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { let _ = source_file::write_all_files(&source_file, &mut out, &config); let output = String::from_utf8(out).unwrap(); - let mut expected_file = fs::File::open(&expected_filename).expect("Couldn't open target"); + let mut expected_file = fs::File::open(&expected_filename).expect("couldn't open target"); let mut expected_text = String::new(); expected_file .read_to_string(&mut expected_text) @@ -290,7 +280,7 @@ fn stdin_formatting_smoke_test() { #[test] fn stdin_parser_panic_caught() { - // https://github.com/rust-lang/rustfmt/issues/3239 + // See issue #3239. for text in ["{", "}"].iter().cloned().map(String::from) { let mut buf = vec![]; let mut session = Session::new(Default::default(), Some(&mut buf)); @@ -304,7 +294,8 @@ fn stdin_parser_panic_caught() { fn stdin_disable_all_formatting_test() { match option_env!("CFG_RELEASE_CHANNEL") { None | Some("nightly") => {} - _ => return, // these tests require nightly + // These tests require nightly. + _ => return, } let input = String::from("fn main() { println!(\"This should not be formatted.\"); }"); let mut child = Command::new(rustfmt().to_str().unwrap()) @@ -407,7 +398,7 @@ fn print_mismatches String>( fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); - // Look for a config file... If there is a 'config' property in the significant comments, use + // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. let mut config = if !sig_comments.is_empty() { @@ -453,7 +444,7 @@ fn idempotent_check( ) -> Result { let sig_comments = read_significant_comments(filename); let config = if let Some(ref config_file_path) = opt_config { - Config::from_toml_path(config_file_path).expect("rustfmt.toml not found") + Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found") } else { read_config(filename) }; @@ -490,43 +481,42 @@ fn get_config(config_file: Option<&Path>) -> Config { } }; - let mut def_config_file = fs::File::open(config_file_name).expect("Couldn't open config"); + let mut def_config_file = fs::File::open(config_file_name).expect("couldn't open config"); let mut def_config = String::new(); def_config_file .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config, Path::new("tests/config/")).expect("Invalid toml") + Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML") } -// Reads significant comments of the form: // rustfmt-key: value -// into a hash map. +// Reads significant comments of the form: `// rustfmt-key: value` into a hash map. fn read_significant_comments(file_name: &Path) -> HashMap { let file = - fs::File::open(file_name).expect(&format!("Couldn't read file {}", file_name.display())); + fs::File::open(file_name).expect(&format!("couldn't read file {}", file_name.display())); let reader = BufReader::new(file); let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; - let regex = regex::Regex::new(pattern).expect("Failed creating pattern 1"); + let regex = regex::Regex::new(pattern).expect("failed creating pattern 1"); // Matches lines containing significant comments or whitespace. let line_regex = regex::Regex::new(r"(^\s*$)|(^\s*//\s*rustfmt-[^:]+:\s*\S+)") - .expect("Failed creating pattern 2"); + .expect("failed creating pattern 2"); reader .lines() - .map(|line| line.expect("Failed getting line")) + .map(|line| line.expect("failed getting line")) .take_while(|line| line_regex.is_match(line)) .filter_map(|line| { regex.captures_iter(&line).next().map(|capture| { ( capture .get(1) - .expect("Couldn't unwrap capture") + .expect("couldn't unwrap capture") .as_str() .to_owned(), capture .get(2) - .expect("Couldn't unwrap capture") + .expect("couldn't unwrap capture") .as_str() .to_owned(), ) @@ -535,7 +525,7 @@ fn read_significant_comments(file_name: &Path) -> HashMap { .collect() } -// Compare output to input. +// Compares output to input. // TODO: needs a better name, more explanation. fn handle_result( result: HashMap, @@ -546,11 +536,11 @@ fn handle_result( for (file_name, fmt_text) in result { // If file is in tests/source, compare to file with same name in tests/target. let target = get_target(&file_name, target); - let open_error = format!("Couldn't open target {:?}", &target); + let open_error = format!("couldn't open target {:?}", &target); let mut f = fs::File::open(&target).expect(&open_error); let mut text = String::new(); - let read_error = format!("Failed reading target {:?}", &target); + let read_error = format!("failed reading target {:?}", &target); f.read_to_string(&mut text).expect(&read_error); // Ignore LF and CRLF difference for Windows. @@ -571,7 +561,7 @@ fn handle_result( } } -// Map source file paths to their target paths. +// Maps source file paths to their target paths. fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { if let Some(n) = file_name .components() @@ -591,7 +581,7 @@ fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { target_file_name } } else { - // This is either and idempotence check or a self check + // This is either and idempotence check or a self check. file_name.to_owned() } } @@ -674,10 +664,10 @@ impl ConfigurationSection { ) -> Option { lazy_static! { static ref CONFIG_NAME_REGEX: regex::Regex = - regex::Regex::new(r"^## `([^`]+)`").expect("Failed creating configuration pattern"); + regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern"); static ref CONFIG_VALUE_REGEX: regex::Regex = regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) - .expect("Failed creating configuration value pattern"); + .expect("failed creating configuration value pattern"); } loop { @@ -899,7 +889,7 @@ fn configuration_snippet_tests() { fn get_code_blocks() -> Vec { let mut file_iter = BufReader::new( fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) - .expect(&format!("Couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + .expect(&format!("couldn't read file {}", CONFIGURATIONS_FILE_NAME)), ) .lines() .map(|l| l.unwrap()) @@ -945,28 +935,30 @@ fn make_temp_file(file_name: &'static str) -> TempFile { let target_dir = var("RUSTFMT_TEST_DIR").unwrap_or_else(|_| ".".to_owned()); let path = Path::new(&target_dir).join(file_name); - let mut file = File::create(&path).expect("Couldn't create temp file"); + let mut file = File::create(&path).expect("couldn't create temp file"); let content = "fn main() {}\n"; file.write_all(content.as_bytes()) - .expect("Couldn't write temp file"); + .expect("couldn't write temp file"); TempFile { path } } impl Drop for TempFile { fn drop(&mut self) { use std::fs::remove_file; - remove_file(&self.path).expect("Couldn't delete temp file"); + remove_file(&self.path).expect("couldn't delete temp file"); } } fn rustfmt() -> PathBuf { let mut me = env::current_exe().expect("failed to get current executable"); - me.pop(); // chop of the test name - me.pop(); // chop off `deps` + // Chop of the test name. + me.pop(); + // Chop off `deps`. + me.pop(); - // if we run `cargo test --release` we might only have a release build + // If we run `cargo test --release`, we might only have a release build. if cfg!(release) { - // ../release/ + // `../release/` me.pop(); me.push("release"); } diff --git a/src/types.rs b/src/types.rs index 10b46959136..e2ddc49bf86 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::iter::ExactSizeIterator; use std::ops::Deref; diff --git a/src/utils.rs b/src/utils.rs index b7f08a556e8..e42b5c8c7d1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::borrow::Cow; use bytecount; @@ -320,7 +310,7 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi, NO_EXPANSION) } -// Return true if the given span does not intersect with file lines. +// Returns `true` if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { ($self:ident, $span:expr) => { !$self.config.file_lines().is_all() @@ -454,7 +444,7 @@ pub fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) } } -/// Remove trailing spaces from the specified snippet. We do not remove spaces +/// Removes trailing spaces from the specified snippet. We do not remove spaces /// inside strings or comments. pub fn remove_trailing_white_spaces(text: &str) -> String { let mut buffer = String::with_capacity(text.len()); diff --git a/src/vertical.rs b/src/vertical.rs index fe476c0bd40..9dca1d600f3 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -1,13 +1,3 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // Format with vertical alignment. use std::cmp; diff --git a/src/visitor.rs b/src/visitor.rs index 8ca53401126..0d350e66c1a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,13 +1,3 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - use std::cell::RefCell; use syntax::parse::ParseSess; diff --git a/tests/source/configs/struct_field_align_threshold/20.rs b/tests/source/configs/struct_field_align_threshold/20.rs index 229817e1405..81253c46037 100644 --- a/tests/source/configs/struct_field_align_threshold/20.rs +++ b/tests/source/configs/struct_field_align_threshold/20.rs @@ -97,7 +97,7 @@ struct Qux<'a, struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); -// With a where clause and generics. +// With a where-clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever { diff --git a/tests/source/fn-simple.rs b/tests/source/fn-simple.rs index 855332d137d..528b9a0292a 100644 --- a/tests/source/fn-simple.rs +++ b/tests/source/fn-simple.rs @@ -19,7 +19,7 @@ fn generic(arg: T) -> &SomeType A, // Second argument B, C, D, /* pre comment */ E /* last comment */) -> &SomeType { - arg(a, b, c, d, e) + arg(a, b, c, d, e) } fn foo() -> ! {} diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs index dff9ee8a222..6354d39eb96 100644 --- a/tests/source/itemized-blocks/no_wrap.rs +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -14,17 +14,17 @@ //! - when the log level is trace, the whole line is gray ("bright black") /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// theater, i.e., as passed to [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means /// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater /// * `tag` is a tag that identifies the message type /// * `msg` is the (serialized) message /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor +/// theater, i.e., as passed to [`Theater::send`] on the remote actor fn func1() {} /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// theater, i.e., as passed to [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means /// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater /// * `tag` is a tag that identifies the message type diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs index 5daba855e6b..61448dce852 100644 --- a/tests/source/itemized-blocks/wrap.rs +++ b/tests/source/itemized-blocks/wrap.rs @@ -22,17 +22,17 @@ // - when the log level is trace, the whole line is gray ("bright black") /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// theater, i.e., as passed to [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means /// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater /// * `tag` is a tag that identifies the message type /// * `msg` is the (serialized) message /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor +/// theater, i.e., as passed to [`Theater::send`] on the remote actor fn func1() {} /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// theater, i.e., as passed to [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means /// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater /// * `tag` is a tag that identifies the message type diff --git a/tests/source/multiple.rs b/tests/source/multiple.rs index c26df03edda..f89f4f68da9 100644 --- a/tests/source/multiple.rs +++ b/tests/source/multiple.rs @@ -88,7 +88,7 @@ pub struct Foo { struct Bar; -// With a where clause and generics. +// With a where-clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever { diff --git a/tests/source/soft-wrapping.rs b/tests/source/soft-wrapping.rs index ace8359409c..b0682d4db3a 100644 --- a/tests/source/soft-wrapping.rs +++ b/tests/source/soft-wrapping.rs @@ -8,7 +8,7 @@ // ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off // the result are the upper 96 bits of `a`. -/// Compare the lowest `f32` of both inputs for greater than or equal. The +/// Compares the lowest `f32` of both inputs for greater than or equal. The /// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is /// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits off /// the result are the upper 96 bits of `a`. diff --git a/tests/source/structs.rs b/tests/source/structs.rs index d4ee741d4d3..711264a11d3 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -70,7 +70,7 @@ struct Qux<'a, struct Tuple(/*Comment 1*/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, /* Comment 2 */ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,); -// With a where clause and generics. +// With a where-clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever { diff --git a/tests/source/type-ascription.rs b/tests/source/type-ascription.rs index 3b761f4fc78..4874094ccc4 100644 --- a/tests/source/type-ascription.rs +++ b/tests/source/type-ascription.rs @@ -1,3 +1,4 @@ + fn main() { let xxxxxxxxxxx = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : SomeTrait; @@ -5,5 +6,5 @@ fn main() { let z = funk(yyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzz, wwwwww): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; - x : u32 - 1u32 / 10f32 : u32 + x : u32 - 1u32 / 10f32 : u32 } diff --git a/tests/source/unions.rs b/tests/source/unions.rs index 730ba980abb..53630788fe5 100644 --- a/tests/source/unions.rs +++ b/tests/source/unions.rs @@ -37,7 +37,7 @@ pub union Writebatch { marker: PhantomData, } -// With a where clause and generics. +// With a where-clause and generics. pub union Foo<'a, Y: Baz> where X: Whatever { diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 39af3fd064e..5a17f03089c 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -12,7 +12,7 @@ fn foo( e: eeeeeeeeeeeee, /* comment before paren */ ) -> bar where - F: Foo, // COmment after where clause + F: Foo, // COmment after where-clause G: Goo, // final comment { diff --git a/tests/target/configs/combine_control_expr/false.rs b/tests/target/configs/combine_control_expr/false.rs index b44d8e1b775..5ada9b1dd14 100644 --- a/tests/target/configs/combine_control_expr/false.rs +++ b/tests/target/configs/combine_control_expr/false.rs @@ -1,6 +1,7 @@ // rustfmt-indent_style: Block // rustfmt-combine_control_expr: false -// Combining openings and closings. See https://github.com/rust-lang/fmt-rfcs/issues/61. + +// Combining openings and closings. See rust-lang/fmt-rfcs#61. fn main() { // Call diff --git a/tests/target/configs/combine_control_expr/true.rs b/tests/target/configs/combine_control_expr/true.rs index ea7c61ef396..52acd26492a 100644 --- a/tests/target/configs/combine_control_expr/true.rs +++ b/tests/target/configs/combine_control_expr/true.rs @@ -1,6 +1,7 @@ // rustfmt-indent_style: Block // rustfmt-combine_control_expr: true -// Combining openings and closings. See https://github.com/rust-lang/fmt-rfcs/issues/61. + +// Combining openings and closings. See rust-lang/fmt-rfcs#61. fn main() { // Call diff --git a/tests/target/configs/struct_field_align_threshold/20.rs b/tests/target/configs/struct_field_align_threshold/20.rs index f952775f5f2..848abd3d3cf 100644 --- a/tests/target/configs/struct_field_align_threshold/20.rs +++ b/tests/target/configs/struct_field_align_threshold/20.rs @@ -102,7 +102,7 @@ struct Tuple( BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, ); -// With a where clause and generics. +// With a where-clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever, diff --git a/tests/target/issue-3032.rs b/tests/target/issue-3032.rs index a0ebf4b7c73..3533a81fbc4 100644 --- a/tests/target/issue-3032.rs +++ b/tests/target/issue-3032.rs @@ -6,7 +6,7 @@ pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option } None } - // if id is length atom, -1, otherwise + // If `id` is length atom, `-1`, otherwise: /*return if JSID_IS_ATOM(id) { let atom = JSID_TO_ATOM(id); //let s = *GetAtomChars(id); diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs index c7151cf81ff..945c3fbbca0 100644 --- a/tests/target/itemized-blocks/no_wrap.rs +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -14,17 +14,17 @@ //! - when the log level is trace, the whole line is gray ("bright black") /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// theater, i.e., as passed to [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means /// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater /// * `tag` is a tag that identifies the message type /// * `msg` is the (serialized) message /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor +/// theater, i.e., as passed to [`Theater::send`] on the remote actor fn func1() {} /// All the parameters ***except for `from_theater`*** should be inserted as sent by the remote -/// theater, ie. as passed to [`Theater::send`] on the remote actor: +/// theater, i.e., as passed to [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], as reported by the remote theater by theater-specific means /// * `to` is the receiving (local) [`ActorId`], as requested by the remote theater /// * `tag` is a tag that identifies the message type diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index c4d687dd3db..0a21c474ca6 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -39,7 +39,7 @@ /// All the parameters ***except for /// `from_theater`*** should be inserted as sent -/// by the remote theater, ie. as passed to +/// by the remote theater, i.e., as passed to /// [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], /// as reported by the remote theater by @@ -51,13 +51,13 @@ /// * `msg` is the (serialized) message /// All the parameters ***except for /// `from_theater`*** should be inserted as sent -/// by the remote theater, ie. as passed to +/// by the remote theater, i.e., as passed to /// [`Theater::send`] on the remote actor fn func1() {} /// All the parameters ***except for /// `from_theater`*** should be inserted as sent -/// by the remote theater, ie. as passed to +/// by the remote theater, i.e., as passed to /// [`Theater::send`] on the remote actor: /// * `from` is the sending (remote) [`ActorId`], /// as reported by the remote theater by diff --git a/tests/target/multiple.rs b/tests/target/multiple.rs index 832567fdf7e..ee6ef220c4b 100644 --- a/tests/target/multiple.rs +++ b/tests/target/multiple.rs @@ -114,7 +114,7 @@ pub struct Foo { struct Bar; -// With a where clause and generics. +// With a where-clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever, diff --git a/tests/target/soft-wrapping.rs b/tests/target/soft-wrapping.rs index 58f3557fbe2..5b4c6d9e85a 100644 --- a/tests/target/soft-wrapping.rs +++ b/tests/target/soft-wrapping.rs @@ -8,7 +8,7 @@ // ggreater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits // off the result are the upper 96 bits of `a`. -/// Compare the lowest `f32` of both inputs for greater than or equal. The +/// Compares the lowest `f32` of both inputs for greater than or equal. The /// lowest 32 bits of the result will be `0xffffffff` if `a.extract(0)` is /// greater than or equal `b.extract(0)`, or `0` otherwise. The upper 96 bits /// off the result are the upper 96 bits of `a`. diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 829a4de5315..0495ab3c81c 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -75,7 +75,7 @@ struct Tuple( BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB, ); -// With a where clause and generics. +// With a where-clause and generics. pub struct Foo<'a, Y: Baz> where X: Whatever, diff --git a/tests/target/unions.rs b/tests/target/unions.rs index 386ceb3836c..8ed16b269c2 100644 --- a/tests/target/unions.rs +++ b/tests/target/unions.rs @@ -37,7 +37,7 @@ pub union Writebatch { marker: PhantomData, } -// With a where clause and generics. +// With a where-clause and generics. pub union Foo<'a, Y: Baz> where X: Whatever, -- cgit 1.4.1-3-g733a5 From 0e408bf83ce26e086724e3ef8a55919588e420f1 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Tue, 19 Feb 2019 21:13:26 +0900 Subject: add config inline_attribute_width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the line width is width within config width, attribute is inline. I don't want to change default rustfmt behavior, so config default value is 0. - fix description - fix test comment - remove unnecessary clone - remove unnecessary test file - fix test for β version - attributes => attribute --- src/config/mod.rs | 3 +++ src/imports.rs | 20 +++++++++++++++++-- tests/source/issue-3343.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++ tests/target/issue-3343.rs | 45 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3343.rs create mode 100644 tests/target/issue-3343.rs (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index 6c09e4b0b1a..4f78a105cdb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -105,6 +105,9 @@ create_config! { "Minimum number of blank lines which must be put between items"; edition: Edition, Edition::Edition2015, true, "The edition of the parser (RFC 2052)"; version: Version, Version::One, false, "Version of formatting rules"; + inline_attribute_width: usize, 0, false, + "Write an item and its attribute on the same line \ + if their combined width is below a threshold"; // Options that can change the source code beyond whitespace/blocks (somewhat linty things) merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one"; diff --git a/src/imports.rs b/src/imports.rs index 43835c30e4b..0fa6dec2265 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -7,7 +7,7 @@ use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; -use crate::config::{Edition, IndentStyle}; +use crate::config::{Edition, IndentStyle, Version}; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, }; @@ -249,7 +249,23 @@ impl UseTree { let lo = attrs.last().as_ref()?.span().hi(); let hi = self.span.lo(); let span = mk_sp(lo, hi); - combine_strs_with_missing_comments(context, &attr_str, &use_str, span, shape, false) + + let allow_extend = if context.config.version() == Version::Two { + let line_len = attr_str.len() + 1 + use_str.len(); + !attrs.first().unwrap().is_sugared_doc + && context.config.inline_attribute_width() >= line_len + } else { + false + }; + + combine_strs_with_missing_comments( + context, + &attr_str, + &use_str, + span, + shape, + allow_extend, + ) } else { Some(use_str) } diff --git a/tests/source/issue-3343.rs b/tests/source/issue-3343.rs new file mode 100644 index 00000000000..760d84dc3c3 --- /dev/null +++ b/tests/source/issue-3343.rs @@ -0,0 +1,48 @@ +// rustfmt-inline_attribute_width: 50 + +#[cfg(feature = "alloc")] +use core::slice; + +#[cfg(feature = "alloc")] +use total_len_is::_50__; + +#[cfg(feature = "alloc")] +use total_len_is::_51___; + +#[cfg(feature = "alloc")] +extern crate len_is_50_; + +#[cfg(feature = "alloc")] +extern crate len_is_51__; + +/// this is a comment to test is_sugared_doc property +use core::convert; + +#[fooooo] +#[barrrrr] +use total_len_is_::_51______; + +#[cfg(not(all( + feature = "std", + any( + target_os = "linux", + target_os = "android", + target_os = "netbsd", + target_os = "dragonfly", + target_os = "haiku", + target_os = "emscripten", + target_os = "solaris", + target_os = "cloudabi", + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "openbsd", + target_os = "bitrig", + target_os = "redox", + target_os = "fuchsia", + windows, + all(target_arch = "wasm32", feature = "stdweb"), + all(target_arch = "wasm32", feature = "wasm-bindgen"), + ) +)))] +use core::slice; diff --git a/tests/target/issue-3343.rs b/tests/target/issue-3343.rs new file mode 100644 index 00000000000..4a1496ef364 --- /dev/null +++ b/tests/target/issue-3343.rs @@ -0,0 +1,45 @@ +// rustfmt-inline_attribute_width: 50 + +#[cfg(feature = "alloc")] use core::slice; + +#[cfg(feature = "alloc")] use total_len_is::_50__; + +#[cfg(feature = "alloc")] +use total_len_is::_51___; + +#[cfg(feature = "alloc")] extern crate len_is_50_; + +#[cfg(feature = "alloc")] +extern crate len_is_51__; + +/// this is a comment to test is_sugared_doc property +use core::convert; + +#[fooooo] +#[barrrrr] +use total_len_is_::_51______; + +#[cfg(not(all( + feature = "std", + any( + target_os = "linux", + target_os = "android", + target_os = "netbsd", + target_os = "dragonfly", + target_os = "haiku", + target_os = "emscripten", + target_os = "solaris", + target_os = "cloudabi", + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "openbsd", + target_os = "bitrig", + target_os = "redox", + target_os = "fuchsia", + windows, + all(target_arch = "wasm32", feature = "stdweb"), + all(target_arch = "wasm32", feature = "wasm-bindgen"), + ) +)))] +use core::slice; -- cgit 1.4.1-3-g733a5 From be7b3ba2e2c8d71fd01dfd7daa0200133d62cfea Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Fri, 22 Feb 2019 23:02:22 +0900 Subject: apply inline_attribute_width for extern crate --- src/imports.rs | 4 ++-- src/reorder.rs | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 0fa6dec2265..a87d100ca9b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -7,7 +7,7 @@ use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; -use crate::config::{Edition, IndentStyle, Version}; +use crate::config::{Edition, IndentStyle}; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, }; @@ -250,7 +250,7 @@ impl UseTree { let hi = self.span.lo(); let span = mk_sp(lo, hi); - let allow_extend = if context.config.version() == Version::Two { + let allow_extend = if attrs.len() == 1 { let line_len = attr_str.len() + 1 + use_str.len(); !attrs.first().unwrap().is_sugared_doc && context.config.inline_attribute_width() >= line_len diff --git a/src/reorder.rs b/src/reorder.rs index 40f6f07c8dc..e206d9249e7 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -83,7 +83,22 @@ fn rewrite_reorderable_item( _ => return None, }; - combine_strs_with_missing_comments(context, &attrs_str, &item_str, missed_span, shape, false) + let allow_extend = if attrs.len() == 1 { + let line_len = attrs_str.len() + 1 + item_str.len(); + !attrs.first().unwrap().is_sugared_doc + && context.config.inline_attribute_width() >= line_len + } else { + false + }; + + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missed_span, + shape, + allow_extend, + ) } /// Rewrite a list of items with reordering. Every item in `items` must have -- cgit 1.4.1-3-g733a5 From ae7330eea4100566f9f3826221cb3d694cfde5cc Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 24 Feb 2019 15:18:46 +0900 Subject: leave pre comment for self --- src/items.rs | 16 ++++++++++++++-- tests/source/issue-3198.rs | 40 ++++++++++++++++++++++++++++++++++++++++ tests/target/issue-3198.rs | 19 +++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3198.rs create mode 100644 tests/target/issue-3198.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index c2568735ad8..d0b29b03ff3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -20,7 +20,8 @@ use crate::expr::{ ExprType, RhsTactics, }; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + definitive_tactic, extract_pre_comment, itemize_list, write_list, ListFormatting, ListItem, + Separator, }; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; @@ -2291,9 +2292,15 @@ fn rewrite_args( // Account for sugary self. // FIXME: the comment for the self argument is dropped. This is blocked // on rust issue #27522. + let mut comment_str = ""; let min_args = explicit_self .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) .map_or(1, |self_str| { + let comment_span = mk_sp(span.lo(), args[0].pat.span.lo()); + comment_str = context + .snippet_provider + .span_to_snippet(comment_span) + .unwrap(); arg_item_strs[0] = self_str; 2 }); @@ -2368,7 +2375,12 @@ fn rewrite_args( && (arg_items.is_empty() || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); - for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) { + for (index, (item, arg)) in arg_items.iter_mut().zip(arg_item_strs).enumerate() { + if index == 0 && explicit_self.is_some() { + let (pre_comment, pre_comment_style) = extract_pre_comment(comment_str); + item.pre_comment = pre_comment; + item.pre_comment_style = pre_comment_style; + } item.item = Some(arg); } diff --git a/tests/source/issue-3198.rs b/tests/source/issue-3198.rs new file mode 100644 index 00000000000..517533ae562 --- /dev/null +++ b/tests/source/issue-3198.rs @@ -0,0 +1,40 @@ +impl TestTrait { + fn foo_one(/* Important comment1 */ + self) { + } + + fn foo( + /* Important comment1 */ + self, + /* Important comment2 */ + a: i32, + ) { + } + + fn bar( + /* Important comment1 */ + &mut self, + /* Important comment2 */ + a: i32, + ) { + } + + fn baz( + /* Important comment1 */ + self: X< 'a , 'b >, + /* Important comment2 */ + a: i32, + ) { + } + + fn baz_tree( + /* Important comment1 */ + + self: X< 'a , 'b >, + /* Important comment2 */ + a: i32, + /* Important comment3 */ + b: i32, + ) { + } +} diff --git a/tests/target/issue-3198.rs b/tests/target/issue-3198.rs new file mode 100644 index 00000000000..de307fed6b1 --- /dev/null +++ b/tests/target/issue-3198.rs @@ -0,0 +1,19 @@ +impl TestTrait { + fn foo_one(/* Important comment1 */ self) {} + + fn foo(/* Important comment1 */ self, /* Important comment2 */ a: i32) {} + + fn bar(/* Important comment1 */ &mut self, /* Important comment2 */ a: i32) {} + + fn baz(/* Important comment1 */ self: X<'a, 'b>, /* Important comment2 */ a: i32) {} + + fn baz_tree( + /* Important comment1 */ + self: X<'a, 'b>, + /* Important comment2 */ + a: i32, + /* Important comment3 */ + b: i32, + ) { + } +} -- cgit 1.4.1-3-g733a5 From dec390207685351dd67dcc0185a861771363d4d1 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 24 Feb 2019 23:04:47 +0900 Subject: leave post comment for self --- src/items.rs | 71 ++++++++++++++++++++++++++-------------------- src/lists.rs | 2 +- tests/source/issue-3198.rs | 71 ++++++++++++++++++++++++++++++++++++++++++---- tests/target/issue-3198.rs | 58 +++++++++++++++++++++++++++++++++---- 4 files changed, 160 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d0b29b03ff3..5f751035f3e 100644 --- a/src/items.rs +++ b/src/items.rs @@ -20,8 +20,8 @@ use crate::expr::{ ExprType, RhsTactics, }; use crate::lists::{ - definitive_tactic, extract_pre_comment, itemize_list, write_list, ListFormatting, ListItem, - Separator, + definitive_tactic, extract_post_comment, extract_pre_comment, get_comment_end, + has_extra_newline, itemize_list, write_list, ListFormatting, ListItem, Separator, }; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; @@ -2281,6 +2281,10 @@ fn rewrite_args( variadic: bool, generics_str_contains_newline: bool, ) -> Option { + let terminator = ")"; + let separator = ","; + let next_span_start = span.hi(); + let mut arg_item_strs = args .iter() .map(|arg| { @@ -2290,17 +2294,20 @@ fn rewrite_args( .collect::>(); // Account for sugary self. - // FIXME: the comment for the self argument is dropped. This is blocked - // on rust issue #27522. - let mut comment_str = ""; + let mut pre_comment_str = ""; + let mut post_comment_str = ""; let min_args = explicit_self .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) .map_or(1, |self_str| { - let comment_span = mk_sp(span.lo(), args[0].pat.span.lo()); - comment_str = context - .snippet_provider - .span_to_snippet(comment_span) - .unwrap(); + pre_comment_str = context.snippet(mk_sp(span.lo(), args[0].pat.span.lo())); + + let next_start = if args.len() > 1 { + args[1].pat.span().lo() + } else { + span.hi() + }; + post_comment_str = context.snippet(mk_sp(args[0].ty.span.hi(), next_start)); + arg_item_strs[0] = self_str; 2 }); @@ -2317,14 +2324,18 @@ fn rewrite_args( // it is explicit. if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { - let second_arg_start = if arg_has_pattern(&args[1]) { - args[1].pat.span.lo() + let remove_comma_byte_pos = context + .snippet_provider + .span_after(mk_sp(args[0].ty.span.hi(), args[1].pat.span.lo()), ","); + let first_post_and_second_pre_span = + mk_sp(remove_comma_byte_pos, args[1].pat.span.lo()); + if count_newlines(context.snippet(first_post_and_second_pre_span)) > 0 { + context + .snippet_provider + .span_after(first_post_and_second_pre_span, "\n") } else { - args[1].ty.span.lo() - }; - let reduced_span = mk_sp(span.lo(), second_arg_start); - - context.snippet_provider.span_after_last(reduced_span, ",") + remove_comma_byte_pos + } } else { span.lo() }; @@ -2349,8 +2360,8 @@ fn rewrite_args( .iter() .map(ArgumentKind::Regular) .chain(variadic_arg), - ")", - ",", + terminator, + separator, |arg| match *arg { ArgumentKind::Regular(arg) => span_lo_for_arg(arg), ArgumentKind::Variadic(start) => start, @@ -2364,22 +2375,30 @@ fn rewrite_args( ArgumentKind::Variadic(..) => Some("...".to_owned()), }, comment_span_start, - span.hi(), + next_span_start, false, ); arg_items.extend(more_items); } + let arg_items_len = arg_items.len(); let fits_in_one_line = !generics_str_contains_newline && (arg_items.is_empty() - || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget); + || arg_items_len == 1 && arg_item_strs[0].len() <= one_line_budget); for (index, (item, arg)) in arg_items.iter_mut().zip(arg_item_strs).enumerate() { + // add pre comment and post comment for first arg(self) if index == 0 && explicit_self.is_some() { - let (pre_comment, pre_comment_style) = extract_pre_comment(comment_str); + let (pre_comment, pre_comment_style) = extract_pre_comment(pre_comment_str); item.pre_comment = pre_comment; item.pre_comment_style = pre_comment_style; + + let comment_end = + get_comment_end(post_comment_str, separator, terminator, arg_items_len == 1); + + item.new_lines = has_extra_newline(post_comment_str, comment_end); + item.post_comment = extract_post_comment(post_comment_str, comment_end, separator); } item.item = Some(arg); } @@ -2430,14 +2449,6 @@ fn rewrite_args( write_list(&arg_items, &fmt) } -fn arg_has_pattern(arg: &ast::Arg) -> bool { - if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident != symbol::keywords::Invalid.ident() - } else { - true - } -} - fn compute_budgets_for_args( context: &RewriteContext<'_>, result: &str, diff --git a/src/lists.rs b/src/lists.rs index cbf5d35c49c..cb404123af0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -683,7 +683,7 @@ pub fn get_comment_end( // Account for extra whitespace between items. This is fiddly // because of the way we divide pre- and post- comments. -fn has_extra_newline(post_snippet: &str, comment_end: usize) -> bool { +pub fn has_extra_newline(post_snippet: &str, comment_end: usize) -> bool { if post_snippet.is_empty() || comment_end == 0 { return false; } diff --git a/tests/source/issue-3198.rs b/tests/source/issue-3198.rs index 517533ae562..48cb24a0025 100644 --- a/tests/source/issue-3198.rs +++ b/tests/source/issue-3198.rs @@ -1,9 +1,13 @@ impl TestTrait { - fn foo_one(/* Important comment1 */ + fn foo_one_pre(/* Important comment1 */ self) { } - fn foo( + fn foo_one_post(self + /* Important comment1 */) { + } + + fn foo_pre( /* Important comment1 */ self, /* Important comment2 */ @@ -11,7 +15,15 @@ impl TestTrait { ) { } - fn bar( + fn foo_post( + self + /* Important comment1 */, + a: i32 + /* Important comment2 */, + ) { + } + + fn bar_pre( /* Important comment1 */ &mut self, /* Important comment2 */ @@ -19,7 +31,15 @@ impl TestTrait { ) { } - fn baz( + fn bar_post( + &mut self + /* Important comment1 */, + a: i32 + /* Important comment2 */, + ) { + } + + fn baz_pre( /* Important comment1 */ self: X< 'a , 'b >, /* Important comment2 */ @@ -27,9 +47,16 @@ impl TestTrait { ) { } - fn baz_tree( - /* Important comment1 */ + fn baz_post( + self: X< 'a , 'b > + /* Important comment1 */, + a: i32 + /* Important comment2 */, + ) { + } + fn baz_tree_pre( + /* Important comment1 */ self: X< 'a , 'b >, /* Important comment2 */ a: i32, @@ -37,4 +64,36 @@ impl TestTrait { b: i32, ) { } + + fn baz_tree_post( + self: X< 'a , 'b > + /* Important comment1 */, + a: i32 + /* Important comment2 */, + b: i32 + /* Important comment3 */,){ + } + + fn multi_line( + self: X<'a, 'b>, /* Important comment1-1 */ + /* Important comment1-2 */ + a: i32, /* Important comment2 */ + b: i32, /* Important comment3 */ + ) { + } + + fn two_line_comment( + self: X<'a, 'b>, /* Important comment1-1 + Important comment1-2 */ + a: i32, /* Important comment2 */ + b: i32, /* Important comment3 */ + ) { + } + + fn no_first_line_comment( + self: X<'a, 'b>, + /* Important comment2 */a: i32, + /* Important comment3 */b: i32, + ) { + } } diff --git a/tests/target/issue-3198.rs b/tests/target/issue-3198.rs index de307fed6b1..9291f181d03 100644 --- a/tests/target/issue-3198.rs +++ b/tests/target/issue-3198.rs @@ -1,13 +1,31 @@ impl TestTrait { - fn foo_one(/* Important comment1 */ self) {} + fn foo_one_pre(/* Important comment1 */ self) {} - fn foo(/* Important comment1 */ self, /* Important comment2 */ a: i32) {} + fn foo_one_post(self /* Important comment1 */) {} - fn bar(/* Important comment1 */ &mut self, /* Important comment2 */ a: i32) {} + fn foo_pre(/* Important comment1 */ self, /* Important comment2 */ a: i32) {} - fn baz(/* Important comment1 */ self: X<'a, 'b>, /* Important comment2 */ a: i32) {} + fn foo_post(self /* Important comment1 */, a: i32 /* Important comment2 */) {} - fn baz_tree( + fn bar_pre(/* Important comment1 */ &mut self, /* Important comment2 */ a: i32) {} + + fn bar_post(&mut self /* Important comment1 */, a: i32 /* Important comment2 */) {} + + fn baz_pre( + /* Important comment1 */ + self: X<'a, 'b>, + /* Important comment2 */ + a: i32, + ) { + } + + fn baz_post( + self: X<'a, 'b>, /* Important comment1 */ + a: i32, /* Important comment2 */ + ) { + } + + fn baz_tree_pre( /* Important comment1 */ self: X<'a, 'b>, /* Important comment2 */ @@ -16,4 +34,34 @@ impl TestTrait { b: i32, ) { } + + fn baz_tree_post( + self: X<'a, 'b>, /* Important comment1 */ + a: i32, /* Important comment2 */ + b: i32, /* Important comment3 */ + ) { + } + + fn multi_line( + self: X<'a, 'b>, /* Important comment1-1 */ + /* Important comment1-2 */ + a: i32, /* Important comment2 */ + b: i32, /* Important comment3 */ + ) { + } + + fn two_line_comment( + self: X<'a, 'b>, /* Important comment1-1 + Important comment1-2 */ + a: i32, /* Important comment2 */ + b: i32, /* Important comment3 */ + ) { + } + + fn no_first_line_comment( + self: X<'a, 'b>, + /* Important comment2 */ a: i32, + /* Important comment3 */ b: i32, + ) { + } } -- cgit 1.4.1-3-g733a5 From 8e3ef3e3a9f400699e2c801275a34c948226281e Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Tue, 5 Mar 2019 00:18:33 +0900 Subject: fix not to remove comment in the case of no arg --- src/items.rs | 15 +++++++++++---- tests/source/no_arg_with_commnet.rs | 2 ++ tests/target/no_arg_with_commnet.rs | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 tests/source/no_arg_with_commnet.rs create mode 100644 tests/target/no_arg_with_commnet.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 5f751035f3e..51b7239927a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2285,6 +2285,17 @@ fn rewrite_args( let separator = ","; let next_span_start = span.hi(); + if args.len() == 0 { + let comment = context + .snippet(mk_sp( + span.lo(), + // to remove ')' + span.hi() - BytePos(1), + )) + .trim(); + return Some(comment.to_owned()); + } + let mut arg_item_strs = args .iter() .map(|arg| { @@ -2318,10 +2329,6 @@ fn rewrite_args( arg_items.push(ListItem::from_str("")); } - // FIXME(#21): if there are no args, there might still be a comment, but - // without spans for the comment or parens, there is no chance of - // getting it right. You also don't get to put a comment on self, unless - // it is explicit. if args.len() >= min_args || variadic { let comment_span_start = if min_args == 2 { let remove_comma_byte_pos = context diff --git a/tests/source/no_arg_with_commnet.rs b/tests/source/no_arg_with_commnet.rs new file mode 100644 index 00000000000..ea4ee0f1eee --- /dev/null +++ b/tests/source/no_arg_with_commnet.rs @@ -0,0 +1,2 @@ +fn foo( /* cooment */ +) {} diff --git a/tests/target/no_arg_with_commnet.rs b/tests/target/no_arg_with_commnet.rs new file mode 100644 index 00000000000..69f61b60f29 --- /dev/null +++ b/tests/target/no_arg_with_commnet.rs @@ -0,0 +1 @@ +fn foo(/* cooment */) {} -- cgit 1.4.1-3-g733a5 From 0437bf7a7d968af885dc05931e4e7d1eaddaadbf Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 1 Mar 2019 17:59:38 +0100 Subject: Allow for stdin input in EmitMode::ModifiedLines --- src/formatting.rs | 16 +++++++++----- src/lib.rs | 2 ++ src/source_file.rs | 63 ++++++++++++++++++++++++++++++++++++------------------ src/test/mod.rs | 26 +++++++++++++++++++++- 4 files changed, 80 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 38440802ef2..f6daab0f487 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -181,8 +181,12 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { self.report .add_non_formatted_ranges(visitor.skipped_range.clone()); - self.handler - .handle_formatted_file(path, visitor.buffer.to_owned(), &mut self.report) + self.handler.handle_formatted_file( + self.parse_session.source_map(), + path, + visitor.buffer.to_owned(), + &mut self.report, + ) } } @@ -190,6 +194,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { trait FormatHandler { fn handle_formatted_file( &mut self, + source_map: &SourceMap, path: FileName, result: String, report: &mut FormatReport, @@ -200,13 +205,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { // Called for each formatted file. fn handle_formatted_file( &mut self, + source_map: &SourceMap, path: FileName, result: String, report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { - match source_file::write_file(&result, &path, out, &self.config) { - Ok(b) if b => report.add_diff(), + match source_file::write_file(Some(source_map), &path, &result, out, &self.config) { + Ok(has_diff) if has_diff => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed let err_msg = format!("{}: {}", path, e); @@ -299,7 +305,7 @@ impl FormattingError { pub(crate) type FormatErrorMap = HashMap>; -#[derive(Default, Debug)] +#[derive(Default, Debug, PartialEq)] pub(crate) struct ReportedErrors { // Encountered e.g., an IO error. pub(crate) has_operational_errors: bool, diff --git a/src/lib.rs b/src/lib.rs index 520a6e66fcd..2a64d58ba52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,8 @@ pub use crate::config::{ Range, Verbosity, }; +pub use crate::rustfmt_diff::make_diff; + #[macro_use] mod utils; diff --git a/src/source_file.rs b/src/source_file.rs index 07c1e37fbed..5cbb01dd123 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -1,5 +1,8 @@ use std::fs; use std::io::{self, Write}; +use std::path::Path; + +use syntax::source_map::SourceMap; use crate::checkstyle::output_checkstyle_file; use crate::config::{Config, EmitMode, FileName, Verbosity}; @@ -26,7 +29,7 @@ where write!(out, "{}", crate::checkstyle::header())?; } for &(ref filename, ref text) in source_file { - write_file(text, filename, out, config)?; + write_file(None, filename, text, out, config)?; } if config.emit_mode() == EmitMode::Checkstyle { write!(out, "{}", crate::checkstyle::footer())?; @@ -36,24 +39,46 @@ where } pub fn write_file( - formatted_text: &str, + source_map: Option<&SourceMap>, filename: &FileName, + formatted_text: &str, out: &mut T, config: &Config, ) -> Result where T: Write, { - let filename_to_path = || match *filename { - FileName::Real(ref path) => path, - _ => panic!("cannot format `{}` and emit to files", filename), + fn ensure_real_path(filename: &FileName) -> &Path { + match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` and emit to files", filename), + } + } + + impl From<&FileName> for syntax_pos::FileName { + fn from(filename: &FileName) -> syntax_pos::FileName { + match filename { + FileName::Real(path) => syntax_pos::FileName::Real(path.to_owned()), + FileName::Stdin => syntax_pos::FileName::Custom("stdin".to_owned()), + } + } + } + + // If parse session is around (cfg(not(test))) then try getting source from + // there instead of hitting the file system. This also supports getting + // original text for `FileName::Stdin`. + let original_text = source_map + .and_then(|x| x.get_source_file(&filename.into())) + .and_then(|x| x.src.as_ref().map(|x| x.to_string())); + let original_text = match original_text { + Some(ori) => ori, + None => fs::read_to_string(ensure_real_path(filename))?, }; match config.emit_mode() { EmitMode::Files if config.make_backup() => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - if ori != formatted_text { + let filename = ensure_real_path(filename); + if original_text != formatted_text { // Do a little dance to make writing safer - write to a temp file // rename the original to a .bk, then rename the temp file to the // original. @@ -67,9 +92,9 @@ where } EmitMode::Files => { // Write text directly over original file if there is a diff. - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - if ori != formatted_text { + let filename = ensure_real_path(filename); + + if original_text != formatted_text { fs::write(filename, formatted_text)?; } } @@ -80,27 +105,23 @@ where write!(out, "{}", formatted_text)?; } EmitMode::ModifiedLines => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - let mismatch = make_diff(&ori, formatted_text, 0); + let mismatch = make_diff(&original_text, formatted_text, 0); let has_diff = !mismatch.is_empty(); output_modified(out, mismatch); return Ok(has_diff); } EmitMode::Checkstyle => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - let diff = make_diff(&ori, formatted_text, 3); + let filename = ensure_real_path(filename); + + let diff = make_diff(&original_text, formatted_text, 3); output_checkstyle_file(out, filename, diff)?; } EmitMode::Diff => { - let filename = filename_to_path(); - let ori = fs::read_to_string(filename)?; - let mismatch = make_diff(&ori, formatted_text, 3); + let mismatch = make_diff(&original_text, formatted_text, 3); let has_diff = !mismatch.is_empty(); print_diff( mismatch, - |line_num| format!("Diff in {} at line {}:", filename.display(), line_num), + |line_num| format!("Diff in {} at line {}:", filename, line_num), config, ); return Ok(has_diff); diff --git a/src/test/mod.rs b/src/test/mod.rs index 2d1a62ceda5..5d9c103ed03 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -9,7 +9,7 @@ use std::process::{Command, Stdio}; use std::str::Chars; use crate::config::{Color, Config, EmitMode, FileName, ReportTactic}; -use crate::formatting::{ModifiedChunk, SourceFile}; +use crate::formatting::{ModifiedChunk, ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; use crate::source_file; use crate::{FormatReport, Input, Session}; @@ -290,6 +290,30 @@ fn stdin_parser_panic_caught() { } } +/// Ensures that `EmitMode::ModifiedLines` works with input from `stdin`. Useful +/// when embedding Rustfmt (e.g. inside RLS). +#[test] +fn stdin_works_with_modified_lines() { + let input = "\nfn\n some( )\n{\n}\nfn main () {}\n"; + let output = "1 6 2\nfn some() {}\nfn main() {}\n"; + + let input = Input::Text(input.to_owned()); + let mut config = Config::default(); + config.set().emit_mode(EmitMode::ModifiedLines); + let mut buf: Vec = vec![]; + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + let errors = ReportedErrors { + has_diff: true, + ..Default::default() + }; + assert_eq!(session.errors, errors); + } + let newline = if cfg!(windows) { "\r\n" } else { "\n" }; + assert_eq!(buf, output.replace('\n', newline).as_bytes()); +} + #[test] fn stdin_disable_all_formatting_test() { match option_env!("CFG_RELEASE_CHANNEL") { -- cgit 1.4.1-3-g733a5 From b3c28dba830fb7c88133a0a402f02a5dff9d0738 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 1 Mar 2019 19:20:57 +0100 Subject: Expose ModifiedLines and implement parsing data from the string output This moves `Modified{Chunks,Lines}` from `src/formatting.rs` to `src/rustfmt_diff.rs` and reexports it in `src/lib.rs`. With this, a conversion from `Vec` to `ModifiedLines` was implemented and now this implements complementary `Display` and `FromStr`, which simplified the previously used `output_modified` function and which allows to parse the raw data emitted with `EmitMode::ModifiedLines`. --- src/formatting.rs | 19 ------ src/lib.rs | 2 +- src/rustfmt_diff.rs | 184 +++++++++++++++++++++++++++++++++++++++++----------- src/source_file.rs | 4 +- src/test/mod.rs | 4 +- 5 files changed, 150 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index f6daab0f487..9ec887ebbdf 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -338,25 +338,6 @@ impl ReportedErrors { } } -/// A single span of changed lines, with 0 or more removed lines -/// and a vector of 0 or more inserted lines. -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ModifiedChunk { - /// The first to be removed from the original text - pub line_number_orig: u32, - /// The number of lines which have been replaced - pub lines_removed: u32, - /// The new lines - pub lines: Vec, -} - -/// Set of changed sections of a file. -#[derive(Debug, PartialEq, Eq)] -pub(crate) struct ModifiedLines { - /// The set of changed chunks. - pub chunks: Vec, -} - #[derive(Clone, Copy, Debug)] enum Timer { Disabled, diff --git a/src/lib.rs b/src/lib.rs index 2a64d58ba52..53e74210ede 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ pub use crate::config::{ Range, Verbosity, }; -pub use crate::rustfmt_diff::make_diff; +pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines}; #[macro_use] mod utils; diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c6262dcab15..c796db09c87 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::fmt; use std::io; use std::io::Write; @@ -33,6 +34,118 @@ impl Mismatch { } } +/// A single span of changed lines, with 0 or more removed lines +/// and a vector of 0 or more inserted lines. +#[derive(Debug, PartialEq, Eq)] +pub struct ModifiedChunk { + /// The first to be removed from the original text + pub line_number_orig: u32, + /// The number of lines which have been replaced + pub lines_removed: u32, + /// The new lines + pub lines: Vec, +} + +/// Set of changed sections of a file. +#[derive(Debug, PartialEq, Eq)] +pub struct ModifiedLines { + /// The set of changed chunks. + pub chunks: Vec, +} + +impl From> for ModifiedLines { + fn from(mismatches: Vec) -> ModifiedLines { + let chunks = mismatches.into_iter().map(|mismatch| { + let lines = || mismatch.lines.iter(); + let num_removed = lines() + .filter(|line| match line { + DiffLine::Resulting(_) => true, + _ => false, + }) + .count(); + + let new_lines = mismatch.lines.into_iter().filter_map(|line| match line { + DiffLine::Context(_) | DiffLine::Resulting(_) => None, + DiffLine::Expected(str) => Some(str), + }); + + ModifiedChunk { + line_number_orig: mismatch.line_number_orig, + lines_removed: num_removed as u32, + lines: new_lines.collect(), + } + }); + + ModifiedLines { + chunks: chunks.collect(), + } + } +} + +// Converts a `Mismatch` into a serialized form, which just includes +// enough information to modify the original file. +// Each section starts with a line with three integers, space separated: +// lineno num_removed num_added +// followed by (`num_added`) lines of added text. The line numbers are +// relative to the original file. +impl fmt::Display for ModifiedLines { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for chunk in &self.chunks { + writeln!( + f, + "{} {} {}", + chunk.line_number_orig, + chunk.lines_removed, + chunk.lines.iter().count() + )?; + + for line in &chunk.lines { + writeln!(f, "{}", line)?; + } + } + + Ok(()) + } +} + +// Allows to convert `Display`ed `ModifiedLines` back to the structural data. +impl std::str::FromStr for ModifiedLines { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut chunks = vec![]; + + let mut lines = s.lines(); + while let Some(header) = lines.next() { + let mut header = header.split_whitespace(); + let (orig, rem, new_lines) = match (header.next(), header.next(), header.next()) { + (Some(orig), Some(removed), Some(added)) => (orig, removed, added), + _ => return Err(()), + }; + eprintln!("{} {} {}", orig, rem, new_lines); + let (orig, rem, new_lines): (u32, u32, usize) = + match (orig.parse(), rem.parse(), new_lines.parse()) { + (Ok(a), Ok(b), Ok(c)) => (a, b, c), + _ => return Err(()), + }; + eprintln!("{} {} {}", orig, rem, new_lines); + let lines = lines.by_ref().take(new_lines); + let lines: Vec<_> = lines.map(ToOwned::to_owned).collect(); + if lines.len() != new_lines { + return Err(()); + } + + chunks.push(ModifiedChunk { + line_number_orig: orig, + lines_removed: rem, + lines, + }); + } + + Ok(ModifiedLines { chunks }) + } +} + // This struct handles writing output to stdout and abstracts away the logic // of printing in color, if it's possible in the executing environment. pub struct OutputWriter { @@ -174,49 +287,11 @@ where } } -/// Converts a `Mismatch` into a serialized form, which just includes -/// enough information to modify the original file. -/// Each section starts with a line with three integers, space separated: -/// lineno num_removed num_added -/// followed by (`num_added`) lines of added text. The line numbers are -/// relative to the original file. -pub fn output_modified(mut out: W, diff: Vec) -where - W: Write, -{ - for mismatch in diff { - let (num_removed, num_added) = - mismatch - .lines - .iter() - .fold((0, 0), |(rem, add), line| match *line { - DiffLine::Context(_) => panic!("No Context expected"), - DiffLine::Expected(_) => (rem, add + 1), - DiffLine::Resulting(_) => (rem + 1, add), - }); - // Write a header with enough information to separate the modified lines. - writeln!( - out, - "{} {} {}", - mismatch.line_number_orig, num_removed, num_added - ) - .unwrap(); - - for line in mismatch.lines { - match line { - DiffLine::Context(_) | DiffLine::Resulting(_) => (), - DiffLine::Expected(ref str) => { - writeln!(out, "{}", str).unwrap(); - } - } - } - } -} - #[cfg(test)] mod test { use super::DiffLine::*; use super::{make_diff, Mismatch}; + use super::{ModifiedChunk, ModifiedLines}; #[test] fn diff_simple() { @@ -298,4 +373,35 @@ mod test { }] ); } + + #[test] + fn modified_lines_from_str() { + use std::str::FromStr; + + let src = "1 6 2\nfn some() {}\nfn main() {}\n25 3 1\n struct Test {}"; + let lines = ModifiedLines::from_str(src).unwrap(); + assert_eq!( + lines, + ModifiedLines { + chunks: vec![ + ModifiedChunk { + line_number_orig: 1, + lines_removed: 6, + lines: vec!["fn some() {}".to_owned(), "fn main() {}".to_owned(),] + }, + ModifiedChunk { + line_number_orig: 25, + lines_removed: 3, + lines: vec![" struct Test {}".to_owned()] + } + ] + } + ); + + let src = "1 5 3"; + assert_eq!(ModifiedLines::from_str(src), Err(())); + + let src = "1 5 3\na\nb"; + assert_eq!(ModifiedLines::from_str(src), Err(())); + } } diff --git a/src/source_file.rs b/src/source_file.rs index 5cbb01dd123..a779c4dfbe2 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -6,7 +6,7 @@ use syntax::source_map::SourceMap; use crate::checkstyle::output_checkstyle_file; use crate::config::{Config, EmitMode, FileName, Verbosity}; -use crate::rustfmt_diff::{make_diff, output_modified, print_diff}; +use crate::rustfmt_diff::{make_diff, print_diff, ModifiedLines}; #[cfg(test)] use crate::formatting::FileRecord; @@ -107,7 +107,7 @@ where EmitMode::ModifiedLines => { let mismatch = make_diff(&original_text, formatted_text, 0); let has_diff = !mismatch.is_empty(); - output_modified(out, mismatch); + write!(out, "{}", ModifiedLines::from(mismatch))?; return Ok(has_diff); } EmitMode::Checkstyle => { diff --git a/src/test/mod.rs b/src/test/mod.rs index 5d9c103ed03..24772d70c16 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -9,8 +9,8 @@ use std::process::{Command, Stdio}; use std::str::Chars; use crate::config::{Color, Config, EmitMode, FileName, ReportTactic}; -use crate::formatting::{ModifiedChunk, ReportedErrors, SourceFile}; -use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, OutputWriter}; +use crate::formatting::{ReportedErrors, SourceFile}; +use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; use crate::{FormatReport, Input, Session}; -- cgit 1.4.1-3-g733a5 From 8aa0f44d15fe133f10830e4b58cd20f207bbf769 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 2 Mar 2019 23:21:47 +0100 Subject: Remove eprintln --- src/rustfmt_diff.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c796db09c87..8081221af49 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -122,13 +122,11 @@ impl std::str::FromStr for ModifiedLines { (Some(orig), Some(removed), Some(added)) => (orig, removed, added), _ => return Err(()), }; - eprintln!("{} {} {}", orig, rem, new_lines); let (orig, rem, new_lines): (u32, u32, usize) = match (orig.parse(), rem.parse(), new_lines.parse()) { (Ok(a), Ok(b), Ok(c)) => (a, b, c), _ => return Err(()), }; - eprintln!("{} {} {}", orig, rem, new_lines); let lines = lines.by_ref().take(new_lines); let lines: Vec<_> = lines.map(ToOwned::to_owned).collect(); if lines.len() != new_lines { -- cgit 1.4.1-3-g733a5 From 6b993c8b8b72faa3b768ffef52a42c19ac134227 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Mon, 4 Mar 2019 18:28:25 +0100 Subject: Fix stdin_works... test on Windows --- src/test/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 24772d70c16..1992190bb62 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -8,7 +8,7 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str::Chars; -use crate::config::{Color, Config, EmitMode, FileName, ReportTactic}; +use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; use crate::formatting::{ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; @@ -299,6 +299,7 @@ fn stdin_works_with_modified_lines() { let input = Input::Text(input.to_owned()); let mut config = Config::default(); + config.set().newline_style(NewlineStyle::Unix); config.set().emit_mode(EmitMode::ModifiedLines); let mut buf: Vec = vec![]; { @@ -310,8 +311,7 @@ fn stdin_works_with_modified_lines() { }; assert_eq!(session.errors, errors); } - let newline = if cfg!(windows) { "\r\n" } else { "\n" }; - assert_eq!(buf, output.replace('\n', newline).as_bytes()); + assert_eq!(buf, output.as_bytes()); } #[test] -- cgit 1.4.1-3-g733a5 From fbfda614be1f666a57e44ae2f981b0ff0ef64c5b Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Mon, 4 Mar 2019 18:32:58 +0100 Subject: Remove redundant closure --- src/rustfmt_diff.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index 8081221af49..c83eb1080a6 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -56,8 +56,8 @@ pub struct ModifiedLines { impl From> for ModifiedLines { fn from(mismatches: Vec) -> ModifiedLines { let chunks = mismatches.into_iter().map(|mismatch| { - let lines = || mismatch.lines.iter(); - let num_removed = lines() + let lines = mismatch.lines.iter(); + let num_removed = lines .filter(|line| match line { DiffLine::Resulting(_) => true, _ => false, -- cgit 1.4.1-3-g733a5 From 40ff078abf0206364243fd01dce76a22dff26dca Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 10 Mar 2019 22:58:34 +0900 Subject: fix 'Ident of macro+ident gets duplicated' error --- src/macros.rs | 3 ++- tests/target/issue-3439.rs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-3439.rs (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 6bc181fc6f9..60fdb9160a7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -432,7 +432,8 @@ pub fn rewrite_macro_inner( // the `macro_name!` and `{ /* macro_body */ }` but skip modifying // anything in between the braces (for now). let snippet = context.snippet(mac.span); - let macro_raw = snippet.split_at(snippet.find('!')? + 1).1.trim_start(); + // to remove unnecessary space after macro name + let macro_raw = snippet.trim_start_matches(¯o_name).trim_start(); match trim_left_preserve_layout(macro_raw, shape.indent, &context.config) { Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), None => Some(format!("{} {}", macro_name, macro_raw)), diff --git a/tests/target/issue-3439.rs b/tests/target/issue-3439.rs new file mode 100644 index 00000000000..835fae243ce --- /dev/null +++ b/tests/target/issue-3439.rs @@ -0,0 +1,6 @@ +use repro::my_macro; + +#[my_macro] +xyz! abc { + let a = 1; +} -- cgit 1.4.1-3-g733a5 From 5f3dfe6c5195baa6f05e7e4dddc113037055a599 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 11 Mar 2019 23:18:43 +0900 Subject: Format the if expression at the end of the block in a single line (#3338) --- src/expr.rs | 16 ++++++++++----- src/visitor.rs | 25 ++++++++++++++++++----- tests/source/one_line_if_v1.rs | 42 ++++++++++++++++++++++++++++++++++++++ tests/source/one_line_if_v2.rs | 42 ++++++++++++++++++++++++++++++++++++++ tests/target/one_line_if_v1.rs | 46 ++++++++++++++++++++++++++++++++++++++++++ tests/target/one_line_if_v2.rs | 38 ++++++++++++++++++++++++++++++++++ 6 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 tests/source/one_line_if_v1.rs create mode 100644 tests/source/one_line_if_v2.rs create mode 100644 tests/target/one_line_if_v1.rs create mode 100644 tests/target/one_line_if_v2.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index d4461293d60..068b8f7fed6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -664,11 +664,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option &'static str { - if pats.is_empty() { - "" - } else { - "let" - } + if pats.is_empty() { "" } else { "let" } } impl<'a> ControlFlow<'a> { @@ -1182,6 +1178,16 @@ pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { } } +pub(crate) fn stmt_is_if(stmt: &ast::Stmt) -> bool { + match stmt.node { + ast::StmtKind::Expr(ref e) => match e.node { + ast::ExprKind::If(..) => true, + _ => false, + }, + _ => false, + } +} + pub fn is_unsafe_block(block: &ast::Block) -> bool { if let ast::BlockCheckMode::Unsafe(..) = block.rules { true diff --git a/src/visitor.rs b/src/visitor.rs index 0d350e66c1a..e1a440f3441 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -6,7 +6,8 @@ use syntax::{ast, visit}; use crate::attr::*; use crate::comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; -use crate::config::{BraceStyle, Config}; +use crate::config::{BraceStyle, Config, Version}; +use crate::expr::{format_expr, ExprType}; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, @@ -20,7 +21,7 @@ use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::utils::{ self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, - rewrite_ident, DEPR_SKIP_ANNOTATION, + rewrite_ident, stmt_expr, DEPR_SKIP_ANNOTATION, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -177,7 +178,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.walk_block_stmts(b); if !b.stmts.is_empty() { - if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) { + if let Some(expr) = stmt_expr(&b.stmts[b.stmts.len() - 1]) { if utils::semicolon_for_expr(&self.get_context(), expr) { self.push_str(";"); } @@ -694,8 +695,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { .collect(); if items.is_empty() { - self.visit_stmt(&stmts[0]); - self.walk_stmts(&stmts[1..]); + // The `if` expression at the end of the block should be formatted in a single + // line if possible. + if self.config.version() == Version::Two + && stmts.len() == 1 + && crate::expr::stmt_is_if(&stmts[0]) + && !contains_skip(get_attrs_from_stmt(&stmts[0])) + { + let shape = self.shape(); + let rewrite = self.with_context(|ctx| { + format_expr(stmt_expr(&stmts[0])?, ExprType::SubExpression, ctx, shape) + }); + self.push_rewrite(stmts[0].span(), rewrite); + } else { + self.visit_stmt(&stmts[0]); + self.walk_stmts(&stmts[1..]); + } } else { self.visit_items_with_reordering(&items); self.walk_stmts(&stmts[items.len()..]); diff --git a/tests/source/one_line_if_v1.rs b/tests/source/one_line_if_v1.rs new file mode 100644 index 00000000000..d3dcbe6787a --- /dev/null +++ b/tests/source/one_line_if_v1.rs @@ -0,0 +1,42 @@ +// rustfmt-version: One + +fn plain_if(x: bool) -> u8 { + if x { + 0 + } else { + 1 + } +} + +fn paren_if(x: bool) -> u8 { + (if x { 0 } else { 1 }) +} + +fn let_if(x: bool) -> u8 { + let x = if x { + foo() + } else { + bar() + }; + x +} + +fn return_if(x: bool) -> u8 { + return if x { + 0 + } else { + 1 + }; +} + +fn multi_if() { + use std::io; + if x { foo() } else { bar() } + if x { foo() } else { bar() } +} + +fn middle_if() { + use std::io; + if x { foo() } else { bar() } + let x = 1; +} diff --git a/tests/source/one_line_if_v2.rs b/tests/source/one_line_if_v2.rs new file mode 100644 index 00000000000..40c834959f9 --- /dev/null +++ b/tests/source/one_line_if_v2.rs @@ -0,0 +1,42 @@ +// rustfmt-version: Two + +fn plain_if(x: bool) -> u8 { + if x { + 0 + } else { + 1 + } +} + +fn paren_if(x: bool) -> u8 { + (if x { 0 } else { 1 }) +} + +fn let_if(x: bool) -> u8 { + let x = if x { + foo() + } else { + bar() + }; + x +} + +fn return_if(x: bool) -> u8 { + return if x { + 0 + } else { + 1 + }; +} + +fn multi_if() { + use std::io; + if x { foo() } else { bar() } + if x { foo() } else { bar() } +} + +fn middle_if() { + use std::io; + if x { foo() } else { bar() } + let x = 1; +} diff --git a/tests/target/one_line_if_v1.rs b/tests/target/one_line_if_v1.rs new file mode 100644 index 00000000000..b3c6c4cbeb2 --- /dev/null +++ b/tests/target/one_line_if_v1.rs @@ -0,0 +1,46 @@ +// rustfmt-version: One + +fn plain_if(x: bool) -> u8 { + if x { + 0 + } else { + 1 + } +} + +fn paren_if(x: bool) -> u8 { + (if x { 0 } else { 1 }) +} + +fn let_if(x: bool) -> u8 { + let x = if x { foo() } else { bar() }; + x +} + +fn return_if(x: bool) -> u8 { + return if x { 0 } else { 1 }; +} + +fn multi_if() { + use std::io; + if x { + foo() + } else { + bar() + } + if x { + foo() + } else { + bar() + } +} + +fn middle_if() { + use std::io; + if x { + foo() + } else { + bar() + } + let x = 1; +} diff --git a/tests/target/one_line_if_v2.rs b/tests/target/one_line_if_v2.rs new file mode 100644 index 00000000000..81ca4c8b8b4 --- /dev/null +++ b/tests/target/one_line_if_v2.rs @@ -0,0 +1,38 @@ +// rustfmt-version: Two + +fn plain_if(x: bool) -> u8 { + if x { 0 } else { 1 } +} + +fn paren_if(x: bool) -> u8 { + (if x { 0 } else { 1 }) +} + +fn let_if(x: bool) -> u8 { + let x = if x { foo() } else { bar() }; + x +} + +fn return_if(x: bool) -> u8 { + return if x { 0 } else { 1 }; +} + +fn multi_if() { + use std::io; + if x { + foo() + } else { + bar() + } + if x { foo() } else { bar() } +} + +fn middle_if() { + use std::io; + if x { + foo() + } else { + bar() + } + let x = 1; +} -- cgit 1.4.1-3-g733a5 From f0c861bfa95a497bcb48f81276136f38627fcbd1 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Mon, 11 Mar 2019 22:24:49 +0900 Subject: implement for const generics --- src/lists.rs | 8 ++++++-- src/spanned.rs | 2 +- src/types.rs | 26 ++++++++++++++++++++++---- tests/source/const_generics.rs | 32 ++++++++++++++++++++++++++++++++ tests/target/const_generics.rs | 24 ++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 tests/source/const_generics.rs create mode 100644 tests/target/const_generics.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index cb404123af0..14b799622c9 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -622,8 +622,12 @@ pub fn extract_post_comment( } else { post_snippet }; - - if !post_snippet_trimmed.is_empty() { + // FIXME(#3441): post_snippet includes 'const' now + // it should not include here + let removed_newline_snippet = post_snippet_trimmed.trim(); + if !post_snippet_trimmed.is_empty() + && (removed_newline_snippet.starts_with("//") || removed_newline_snippet.starts_with("/*")) + { Some(post_snippet_trimmed.to_owned()) } else { None diff --git a/src/spanned.rs b/src/spanned.rs index 068a3b8b4f4..118b84526e7 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -168,7 +168,7 @@ impl Spanned for ast::GenericArg { match *self { ast::GenericArg::Lifetime(ref lt) => lt.ident.span, ast::GenericArg::Type(ref ty) => ty.span(), - ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) + ast::GenericArg::Const(ref _const) => _const.value.span(), } } } diff --git a/src/types.rs b/src/types.rs index e2ddc49bf86..f8193e1c9f2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -7,7 +7,7 @@ use syntax::symbol::keywords; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity}; -use crate::expr::{rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix}; +use crate::expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; @@ -132,6 +132,7 @@ where #[derive(Debug)] pub enum SegmentParam<'a> { + Const(&'a ast::AnonConst), LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), Binding(&'a ast::TypeBinding), @@ -142,7 +143,7 @@ impl<'a> SegmentParam<'a> { match arg { ast::GenericArg::Lifetime(ref lt) => SegmentParam::LifeTime(lt), ast::GenericArg::Type(ref ty) => SegmentParam::Type(ty), - ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) + ast::GenericArg::Const(const_) => SegmentParam::Const(const_), } } } @@ -150,6 +151,7 @@ impl<'a> SegmentParam<'a> { impl<'a> Spanned for SegmentParam<'a> { fn span(&self) -> Span { match *self { + SegmentParam::Const(const_) => const_.value.span, SegmentParam::LifeTime(lt) => lt.ident.span, SegmentParam::Type(ty) => ty.span, SegmentParam::Binding(binding) => binding.span, @@ -160,6 +162,7 @@ impl<'a> Spanned for SegmentParam<'a> { impl<'a> Rewrite for SegmentParam<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { + SegmentParam::Const(const_) => const_.rewrite(context, shape), SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(binding) => { @@ -454,7 +457,7 @@ impl Rewrite for ast::GenericArg { match *self { ast::GenericArg::Lifetime(ref lt) => lt.rewrite(context, shape), ast::GenericArg::Type(ref ty) => ty.rewrite(context, shape), - ast::GenericArg::Const(..) => unreachable!(), // FIXME(#3336) + ast::GenericArg::Const(ref const_) => const_.rewrite(context, shape), } } } @@ -482,6 +485,12 @@ fn rewrite_bounded_lifetime( } } +impl Rewrite for ast::AnonConst { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + format_expr(&self.value, ExprType::SubExpression, context, shape) + } +} + impl Rewrite for ast::Lifetime { fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option { Some(rewrite_ident(context, self.ident).to_owned()) @@ -525,7 +534,16 @@ impl Rewrite for ast::GenericParam { Some(ref rw) if !rw.is_empty() => result.push_str(&format!("{} ", rw)), _ => (), } - result.push_str(rewrite_ident(context, self.ident)); + + if let syntax::ast::GenericParamKind::Const { ref ty } = &self.kind { + result.push_str("const "); + result.push_str(rewrite_ident(context, self.ident)); + result.push_str(": "); + result.push_str(&ty.rewrite(context, shape)?); + } else { + result.push_str(rewrite_ident(context, self.ident)); + } + if !self.bounds.is_empty() { result.push_str(type_bound_colon(context)); result.push_str(&self.bounds.rewrite(context, shape)?) diff --git a/tests/source/const_generics.rs b/tests/source/const_generics.rs new file mode 100644 index 00000000000..420810b92ea --- /dev/null +++ b/tests/source/const_generics.rs @@ -0,0 +1,32 @@ +struct Message { + field2: Vec< + "MessageEntity" + >, + field3: Vec< + 1 + >, + field4: Vec< + 2 , 3 + >, + +} + +struct RectangularArray { + array: [[T; WIDTH]; HEIGHT], +} + +fn main() { + const X: usize = 7; + let x: RectangularArray; + let y: RectangularArray; +} + +fn foo() { + const Y: usize = X * 2; + static Z: (usize, usize) = (X, X); + + struct Foo([i32; X]); +} + +type Foo = [i32; N + 1]; diff --git a/tests/target/const_generics.rs b/tests/target/const_generics.rs new file mode 100644 index 00000000000..f60b7eb0880 --- /dev/null +++ b/tests/target/const_generics.rs @@ -0,0 +1,24 @@ +struct Message { + field2: Vec<"MessageEntity">, + field3: Vec<1>, + field4: Vec<2, 3>, +} + +struct RectangularArray { + array: [[T; WIDTH]; HEIGHT], +} + +fn main() { + const X: usize = 7; + let x: RectangularArray; + let y: RectangularArray; +} + +fn foo() { + const Y: usize = X * 2; + static Z: (usize, usize) = (X, X); + + struct Foo([i32; X]); +} + +type Foo = [i32; N + 1]; -- cgit 1.4.1-3-g733a5 From ce5cccc32c3897488d2c503fe9d2a9a429a9b0eb Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 14 Mar 2019 22:50:53 +0900 Subject: Update rustc-ap-* crates to 407.0.0 (#3447) --- Cargo.lock | 390 +++++++++++++++++++++++----------------- Cargo.toml | 6 +- src/config/mod.rs | 8 +- src/config/options.rs | 5 +- src/formatting.rs | 6 +- src/items.rs | 214 ++++------------------ src/source_map.rs | 10 +- src/types.rs | 38 +--- src/visitor.rs | 2 +- tests/source/attrib.rs | 3 +- tests/source/doc-attrib.rs | 1 - tests/target/attrib.rs | 1 - tests/target/doc-attrib.rs | 1 - tests/target/macro_rules.rs | 2 +- tests/target/trailing_commas.rs | 2 +- 15 files changed, 293 insertions(+), 396 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 4eed10e320d..88276e45991 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -30,7 +30,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -42,13 +42,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -58,8 +58,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -91,24 +91,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.29" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -139,9 +139,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -152,7 +152,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -162,7 +162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -172,17 +172,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "dirs" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "either" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -195,13 +195,13 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -210,7 +210,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -218,7 +218,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -229,7 +229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -259,7 +259,7 @@ name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -267,14 +267,24 @@ name = "itoa" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "jobserver" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -291,7 +301,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -314,7 +324,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -330,27 +340,27 @@ name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -377,26 +387,29 @@ dependencies = [ [[package]] name = "rand" -version = "0.4.6" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand" -version = "0.5.6" +name = "rand_chacha" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -412,6 +425,62 @@ name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -435,21 +504,21 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -466,20 +535,20 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -489,84 +558,86 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "373.0.0" +version = "407.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -589,7 +660,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -599,8 +670,8 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -623,24 +694,24 @@ version = "1.0.3" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -655,7 +726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "scoped-tls" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -674,7 +745,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -684,36 +755,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "stable_deref_trait" @@ -722,7 +790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.26" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -737,7 +805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -763,7 +831,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -773,7 +841,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -781,7 +849,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -809,24 +877,11 @@ name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "utf8-ranges" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.3.6" @@ -864,20 +919,20 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "585784cac9b05c93a53b17a0b24a5cdd1dfdda5256f030e089b549d2390cc720" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cargo_metadata 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bc796c7161c220089dfc7159e13324979181532850a237576b8fb907dd087c0d" +"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" @@ -885,10 +940,10 @@ dependencies = [ "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a" -"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" +"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +"checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" -"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" @@ -897,8 +952,9 @@ dependencies = [ "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" +"checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" @@ -907,30 +963,36 @@ dependencies = [ "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26" -"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" -"checksum rustc-ap-arena 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8be999235b541fc8eb54901b66e899a06076709ac5f53d6b2c5c59d29ad54780" -"checksum rustc-ap-graphviz 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "532b5df15ca1a19a42815e37e521a20a7632b86b36868d1447932f8476f8f789" -"checksum rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c388afe1ef810013c878bdf9073ab1ae28dc49e9325863b351afb10acf4cc46e" -"checksum rustc-ap-rustc_data_structures 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63a8f08b9fb6d607afb842ee7206273d09d69c9201bfc1c479a726093251a24e" -"checksum rustc-ap-rustc_errors 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dc0df7bf31588ea67e6386f6ad19f6b9a37ba7d5726ecad1cacce22e231bd98" -"checksum rustc-ap-rustc_target 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb4623a6f6c65b928cbe8d9c52b38cf57ba1722677645dc53fb1bdadfd0e127" -"checksum rustc-ap-serialize 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c290b148c9e4e08bbcb8a313393e257c1103cedf6a038aefc9f957c8a77c755" -"checksum rustc-ap-syntax 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "526fdc5bdbaaeae3b2a9ba42e5f5f7f29cda6ce8971b607a2955b1cb4ca339b5" -"checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952" +"checksum rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aab2fb5e5becf1c9183f6c63b8714817a3e780a20b4fe6b3920751c98a18225" +"checksum rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0235ff613d4f96176ea56748010b5d8e978605cc47856ba9bb5372f4f38e9c03" +"checksum rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e04a90b0dd8597da83633961698c61a2948f50c9d4b9a71e8afafc0ba0f158" +"checksum rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c03988d65fc5130787df32e8ea91738f78a8ed62b7a5bdd77f10e5cceb531d8e" +"checksum rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b33b9dc34f9fa50bf7e6fd14f2f3c1adc69833acf43c10f3e9795bd4d613712" +"checksum rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6de75caef2c7acba11994614266d60238653657677934817ab368d169333cba" +"checksum rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf09c60aaee892b0fd107544cfe607d8d463e7f33da34aa823566b8fd2b17f53" +"checksum rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69f38cc120ff317678bbda8c4f58c1bbc1de64b615383ab01480482dde5e95a1" +"checksum rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20a0a201141c5c416b1924b079eeefc7b013e34ece0740ce4997f358b3684a7f" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544" @@ -938,17 +1000,17 @@ dependencies = [ "checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" +"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" -"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" -"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" @@ -960,9 +1022,7 @@ dependencies = [ "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" diff --git a/Cargo.toml b/Cargo.toml index 2274ae86bd2..f1d819f0d08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,9 +49,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.7" -rustc-ap-rustc_target = "373.0.0" -rustc-ap-syntax = "373.0.0" -rustc-ap-syntax_pos = "373.0.0" +rustc-ap-rustc_target = "407.0.0" +rustc-ap-syntax = "407.0.0" +rustc-ap-syntax_pos = "407.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/config/mod.rs b/src/config/mod.rs index 4f78a105cdb..785d61749a4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -21,10 +21,10 @@ pub mod file_lines; pub mod license; pub mod lists; -/// This macro defines configuration options used in rustfmt. Each option -/// is defined as follows: -/// -/// `name: value type, default value, is stable, description;` +// This macro defines configuration options used in rustfmt. Each option +// is defined as follows: +// +// `name: value type, default value, is stable, description;` create_config! { // Fundamental stuff max_width: usize, 100, true, "Maximum width of each line"; diff --git a/src/config/options.rs b/src/config/options.rs index be32c142916..02c3c87368e 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -237,10 +237,11 @@ configuration_option_enum! { Heuristics: } impl Density { - pub fn to_list_tactic(self) -> ListTactic { + pub fn to_list_tactic(self, len: usize) -> ListTactic { match self { Density::Compressed => ListTactic::Mixed, Density::Tall => ListTactic::HorizontalVertical, + Density::Vertical if len == 1 => ListTactic::Horizontal, Density::Vertical => ListTactic::Vertical, } } @@ -443,7 +444,7 @@ pub trait CliOptions { fn config_path(&self) -> Option<&Path>; } -/// The edition of the compiler (RFC 2052) +// The edition of the compiler (RFC 2052) configuration_option_enum! { Edition: Edition2015: 2015, Edition2018: 2018, diff --git a/src/formatting.rs b/src/formatting.rs index 9ec887ebbdf..eee02f275cf 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -83,7 +83,7 @@ fn format_project( // Suppress error output if we have to do any further parsing. let silent_emitter = silent_emitter(source_map); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); + parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); @@ -657,7 +657,7 @@ fn silent_emitter(source_map: Rc) -> Box { fn make_parse_sess(source_map: Rc, config: &Config) -> ParseSess { let tty_handler = if config.hide_parse_errors() { let silent_emitter = silent_emitter(source_map.clone()); - Handler::with_emitter(true, false, silent_emitter) + Handler::with_emitter(true, None, silent_emitter) } else { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); let color_cfg = if supports_color { @@ -665,7 +665,7 @@ fn make_parse_sess(source_map: Rc, config: &Config) -> ParseSess { } else { ColorConfig::Never }; - Handler::with_tty_emitter(color_cfg, true, false, Some(source_map.clone())) + Handler::with_tty_emitter(color_cfg, true, None, Some(source_map.clone())) }; ParseSess::with_span_handler(tty_handler, source_map) diff --git a/src/items.rs b/src/items.rs index 51b7239927a..8cd6010f72f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -19,10 +19,7 @@ use crate::expr::{ format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, ExprType, RhsTactics, }; -use crate::lists::{ - definitive_tactic, extract_post_comment, extract_pre_comment, get_comment_end, - has_extra_newline, itemize_list, write_list, ListFormatting, ListItem, Separator, -}; +use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext}; @@ -194,7 +191,7 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, - is_async: method_sig.header.asyncness, + is_async: method_sig.header.asyncness.node, constness: method_sig.header.constness.node, defaultness: ast::Defaultness::Final, abi: method_sig.header.abi, @@ -216,7 +213,7 @@ impl<'a> FnSig<'a> { generics, abi: fn_header.abi, constness: fn_header.constness.node, - is_async: fn_header.asyncness, + is_async: fn_header.asyncness.node, defaultness, unsafety: fn_header.unsafety, visibility: visibility.clone(), @@ -1833,7 +1830,9 @@ fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool { impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - if is_named_arg(self) { + if let Some(ref explicit_self) = self.to_self() { + rewrite_explicit_self(context, explicit_self) + } else if is_named_arg(self) { let mut result = self .pat .rewrite(context, Shape::legacy(shape.width, shape.indent))?; @@ -1862,9 +1861,8 @@ impl Rewrite for ast::Arg { } fn rewrite_explicit_self( - explicit_self: &ast::ExplicitSelf, - args: &[ast::Arg], context: &RewriteContext<'_>, + explicit_self: &ast::ExplicitSelf, ) -> Option { match explicit_self.node { ast::SelfKind::Region(lt, m) => { @@ -1880,10 +1878,7 @@ fn rewrite_explicit_self( None => Some(format!("&{}self", mut_str)), } } - ast::SelfKind::Explicit(ref ty, _) => { - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - - let mutability = explicit_self_mutability(&args[0]); + ast::SelfKind::Explicit(ref ty, mutability) => { let type_str = ty.rewrite( context, Shape::legacy(context.config.max_width(), Indent::empty()), @@ -1895,23 +1890,7 @@ fn rewrite_explicit_self( type_str )) } - ast::SelfKind::Value(_) => { - assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty."); - - let mutability = explicit_self_mutability(&args[0]); - - Some(format!("{}self", format_mutability(mutability))) - } - } -} - -// Hacky solution caused by absence of `Mutability` in `SelfValue` and -// `SelfExplicit` variants of `ast::ExplicitSelf_`. -fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability { - if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node { - mutability - } else { - unreachable!() + ast::SelfKind::Value(mutability) => Some(format!("{}self", format_mutability(mutability))), } } @@ -2048,14 +2027,12 @@ fn rewrite_fn_base( let arg_str = rewrite_args( context, &fd.inputs, - fd.get_self().as_ref(), one_line_budget, multi_line_budget, indent, arg_indent, args_span, - fd.variadic, - generics_str.contains('\n'), + fd.c_variadic, )?; let put_args_in_block = match context.config.indent_style() { @@ -2272,19 +2249,13 @@ impl WhereClauseOption { fn rewrite_args( context: &RewriteContext<'_>, args: &[ast::Arg], - explicit_self: Option<&ast::ExplicitSelf>, one_line_budget: usize, multi_line_budget: usize, indent: Indent, arg_indent: Indent, span: Span, variadic: bool, - generics_str_contains_newline: bool, ) -> Option { - let terminator = ")"; - let separator = ","; - let next_span_start = span.hi(); - if args.len() == 0 { let comment = context .snippet(mk_sp( @@ -2295,144 +2266,29 @@ fn rewrite_args( .trim(); return Some(comment.to_owned()); } - - let mut arg_item_strs = args - .iter() - .map(|arg| { + let arg_items: Vec<_> = itemize_list( + context.snippet_provider, + args.iter(), + ")", + ",", + |arg| span_lo_for_arg(arg), + |arg| arg.ty.span.hi(), + |arg| { arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) - .unwrap_or_else(|| context.snippet(arg.span()).to_owned()) - }) - .collect::>(); - - // Account for sugary self. - let mut pre_comment_str = ""; - let mut post_comment_str = ""; - let min_args = explicit_self - .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context)) - .map_or(1, |self_str| { - pre_comment_str = context.snippet(mk_sp(span.lo(), args[0].pat.span.lo())); - - let next_start = if args.len() > 1 { - args[1].pat.span().lo() - } else { - span.hi() - }; - post_comment_str = context.snippet(mk_sp(args[0].ty.span.hi(), next_start)); - - arg_item_strs[0] = self_str; - 2 - }); - - // Comments between args. - let mut arg_items = Vec::new(); - if min_args == 2 { - arg_items.push(ListItem::from_str("")); - } - - if args.len() >= min_args || variadic { - let comment_span_start = if min_args == 2 { - let remove_comma_byte_pos = context - .snippet_provider - .span_after(mk_sp(args[0].ty.span.hi(), args[1].pat.span.lo()), ","); - let first_post_and_second_pre_span = - mk_sp(remove_comma_byte_pos, args[1].pat.span.lo()); - if count_newlines(context.snippet(first_post_and_second_pre_span)) > 0 { - context - .snippet_provider - .span_after(first_post_and_second_pre_span, "\n") - } else { - remove_comma_byte_pos - } - } else { - span.lo() - }; - - enum ArgumentKind<'a> { - Regular(&'a ast::Arg), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi()); - let variadic_start = - context.snippet_provider.span_after(variadic_span, "...") - BytePos(3); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - - let more_items = itemize_list( - context.snippet_provider, - args[min_args - 1..] - .iter() - .map(ArgumentKind::Regular) - .chain(variadic_arg), - terminator, - separator, - |arg| match *arg { - ArgumentKind::Regular(arg) => span_lo_for_arg(arg), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(arg) => arg.ty.span.hi(), - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(..) => None, - ArgumentKind::Variadic(..) => Some("...".to_owned()), - }, - comment_span_start, - next_span_start, - false, - ); - - arg_items.extend(more_items); - } - - let arg_items_len = arg_items.len(); - let fits_in_one_line = !generics_str_contains_newline - && (arg_items.is_empty() - || arg_items_len == 1 && arg_item_strs[0].len() <= one_line_budget); - - for (index, (item, arg)) in arg_items.iter_mut().zip(arg_item_strs).enumerate() { - // add pre comment and post comment for first arg(self) - if index == 0 && explicit_self.is_some() { - let (pre_comment, pre_comment_style) = extract_pre_comment(pre_comment_str); - item.pre_comment = pre_comment; - item.pre_comment_style = pre_comment_style; - - let comment_end = - get_comment_end(post_comment_str, separator, terminator, arg_items_len == 1); - - item.new_lines = has_extra_newline(post_comment_str, comment_end); - item.post_comment = extract_post_comment(post_comment_str, comment_end, separator); - } - item.item = Some(arg); - } - - let last_line_ends_with_comment = arg_items - .iter() - .last() - .and_then(|item| item.post_comment.as_ref()) - .map_or(false, |s| s.trim().starts_with("//")); - - let (indent, trailing_comma) = match context.config.indent_style() { - IndentStyle::Block if fits_in_one_line => { - (indent.block_indent(context.config), SeparatorTactic::Never) - } - IndentStyle::Block => ( - indent.block_indent(context.config), - context.config.trailing_comma(), - ), - IndentStyle::Visual if last_line_ends_with_comment => { - (arg_indent, context.config.trailing_comma()) - } - IndentStyle::Visual => (arg_indent, SeparatorTactic::Never), - }; + .or_else(|| Some(context.snippet(arg.span()).to_owned())) + }, + span.lo(), + span.hi(), + false, + ) + .collect(); let tactic = definitive_tactic( &arg_items, - context.config.fn_args_density().to_list_tactic(), + context + .config + .fn_args_density() + .to_list_tactic(arg_items.len()), Separator::Comma, one_line_budget, ); @@ -2440,13 +2296,17 @@ fn rewrite_args( DefinitiveListTactic::Horizontal => one_line_budget, _ => multi_line_budget, }; - - debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic); - + let indent = match context.config.indent_style() { + IndentStyle::Block => indent.block_indent(context.config), + IndentStyle::Visual => arg_indent, + }; let trailing_separator = if variadic { SeparatorTactic::Never } else { - trailing_comma + match context.config.indent_style() { + IndentStyle::Block => context.config.trailing_comma(), + IndentStyle::Visual => SeparatorTactic::Never, + } }; let fmt = ListFormatting::new(Shape::legacy(budget, indent), context.config) .tactic(tactic) diff --git a/src/source_map.rs b/src/source_map.rs index d0c4adbe61d..c98b7596383 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -26,7 +26,13 @@ pub trait LineRangeUtils { impl<'a> SpanUtils for SnippetProvider<'a> { fn span_after(&self, original: Span, needle: &str) -> BytePos { - self.opt_span_after(original, needle).expect("bad span") + self.opt_span_after(original, needle).unwrap_or_else(|| { + panic!( + "bad span: `{}`: `{}`", + needle, + self.span_to_snippet(original).unwrap() + ) + }) } fn span_after_last(&self, original: Span, needle: &str) -> BytePos { @@ -43,7 +49,7 @@ impl<'a> SpanUtils for SnippetProvider<'a> { fn span_before(&self, original: Span, needle: &str) -> BytePos { self.opt_span_before(original, needle).unwrap_or_else(|| { panic!( - "bad span: {}: {}", + "bad span: `{}`: `{}`", needle, self.span_to_snippet(original).unwrap() ) diff --git a/src/types.rs b/src/types.rs index f8193e1c9f2..e6a16b38ce8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -302,24 +302,6 @@ where FunctionRetTy::Default(..) => String::new(), }; - // Code for handling variadics is somewhat duplicated for items, but they - // are different enough to need some serious refactoring to share code. - enum ArgumentKind - where - T: Deref, - ::Target: Rewrite + Spanned, - { - Regular(T), - Variadic(BytePos), - } - - let variadic_arg = if variadic { - let variadic_start = context.snippet_provider.span_before(span, "..."); - Some(ArgumentKind::Variadic(variadic_start)) - } else { - None - }; - let list_shape = if context.use_block_indent() { Shape::indented( shape.block().indent.block_indent(context.config), @@ -335,21 +317,12 @@ where let list_lo = context.snippet_provider.span_after(span, "("); let items = itemize_list( context.snippet_provider, - inputs.map(ArgumentKind::Regular).chain(variadic_arg), + inputs, ")", ",", - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().lo(), - ArgumentKind::Variadic(start) => start, - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.span().hi(), - ArgumentKind::Variadic(start) => start + BytePos(3), - }, - |arg| match *arg { - ArgumentKind::Regular(ref ty) => ty.rewrite(context, list_shape), - ArgumentKind::Variadic(_) => Some("...".to_owned()), - }, + |arg| arg.span().lo(), + |arg| arg.span().hi(), + |arg| arg.rewrite(context, list_shape), list_lo, span.hi(), false, @@ -697,6 +670,7 @@ impl Rewrite for ast::Ty { ast::TyKind::ImplTrait(_, ref it) => it .rewrite(context, shape) .map(|it_str| format!("impl {}", it_str)), + ast::TyKind::CVarArgs => Some("...".to_owned()), ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), } } @@ -741,7 +715,7 @@ fn rewrite_bare_fn( let rewrite = format_function_type( bare_fn.decl.inputs.iter(), &bare_fn.decl.output, - bare_fn.decl.variadic, + bare_fn.decl.c_variadic, span, context, func_ty_shape, diff --git a/src/visitor.rs b/src/visitor.rs index e1a440f3441..3bd5af3112d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -388,7 +388,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::Fn(ref decl, fn_header, ref generics, ref body) => { + ast::ItemKind::Fn(ref decl, ref fn_header, ref generics, ref body) => { let inner_attrs = inner_attributes(&item.attrs); self.visit_fn( visit::FnKind::ItemFn(item.ident, fn_header, &item.vis, body), diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index fc9afa27310..f92c9cd31e2 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -168,7 +168,6 @@ pub fn foo() {} // path attrs #[clippy::bar] -#[clippy::bar=foo] #[clippy::bar(a, b, c)] pub fn foo() {} @@ -217,4 +216,4 @@ fn stmt_expr_attributes() { let foo ; #[must_use] foo = false ; -} \ No newline at end of file +} diff --git a/tests/source/doc-attrib.rs b/tests/source/doc-attrib.rs index 1fea6e361c2..cecc837d7f9 100644 --- a/tests/source/doc-attrib.rs +++ b/tests/source/doc-attrib.rs @@ -47,7 +47,6 @@ pub fn foo() {} // path attrs #[clippy::bar] -#[clippy::bar=foo] #[clippy::bar(a, b, c)] pub fn foo() {} diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index f359bf22411..b5a6c3491de 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -197,7 +197,6 @@ pub fn foo() {} // path attrs #[clippy::bar] -#[clippy::bar=foo] #[clippy::bar(a, b, c)] pub fn foo() {} diff --git a/tests/target/doc-attrib.rs b/tests/target/doc-attrib.rs index e85235afd0c..474c19282fd 100644 --- a/tests/target/doc-attrib.rs +++ b/tests/target/doc-attrib.rs @@ -55,7 +55,6 @@ pub fn foo() {} // path attrs #[clippy::bar] -#[clippy::bar=foo] #[clippy::bar(a, b, c)] pub fn foo() {} diff --git a/tests/target/macro_rules.rs b/tests/target/macro_rules.rs index 97444aef404..68052b25f48 100644 --- a/tests/target/macro_rules.rs +++ b/tests/target/macro_rules.rs @@ -172,7 +172,7 @@ macro_rules! m [ ]; // #2470 -macro foo($type_name:ident, $docs:expr) { +macro foo($type_name: ident, $docs: expr) { #[allow(non_camel_case_types)] #[doc=$docs] #[derive(Debug, Clone, Copy)] diff --git a/tests/target/trailing_commas.rs b/tests/target/trailing_commas.rs index ce9e16a4006..06f0a13b10c 100644 --- a/tests/target/trailing_commas.rs +++ b/tests/target/trailing_commas.rs @@ -23,7 +23,7 @@ impl Trait for T where T: P, { - fn f(x: T) -> T + fn f(x: T,) -> T where T: Q + R, { -- cgit 1.4.1-3-g733a5 From 2d5bc69475e727165d220d021bb589de00623d16 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 16 Mar 2019 12:23:02 +0100 Subject: remove trailing whitespaces in missing spans --- src/missed_spans.rs | 7 ++++++- tests/source/issue-3423.rs | 5 +++++ tests/target/issue-3423.rs | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-3423.rs create mode 100644 tests/target/issue-3423.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 008efd2bef1..27b94a6c8ae 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -252,7 +252,12 @@ impl<'a> FmtVisitor<'a> { // - if there isn't one already // - otherwise, only if the last line is a line comment if status.line_start <= snippet.len() { - match snippet[status.line_start..].chars().next() { + match snippet[status.line_start..] + .chars() + // skip trailing whitespaces + .skip_while(|c| *c == ' ' || *c == '\t') + .next() + { Some('\n') | Some('\r') => { if !subslice.trim_end().ends_with("*/") { self.push_str("\n"); diff --git a/tests/source/issue-3423.rs b/tests/source/issue-3423.rs new file mode 100644 index 00000000000..fbe8e5c372e --- /dev/null +++ b/tests/source/issue-3423.rs @@ -0,0 +1,5 @@ +/* a nice comment with a trailing whitespace */ +fn foo() {} + +/* a nice comment with a trailing tab */ +fn bar() {} diff --git a/tests/target/issue-3423.rs b/tests/target/issue-3423.rs new file mode 100644 index 00000000000..cd60251771d --- /dev/null +++ b/tests/target/issue-3423.rs @@ -0,0 +1,5 @@ +/* a nice comment with a trailing whitespace */ +fn foo() {} + +/* a nice comment with a trailing tab */ +fn bar() {} -- cgit 1.4.1-3-g733a5 From bde77714e696602f52ca6d9378eabd9a642a1a27 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 17 Mar 2019 12:21:57 +0900 Subject: Disable self_tests on beta channel --- src/test/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 1992190bb62..20845b08f83 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -231,6 +231,10 @@ fn idempotence_tests() { // no warnings are emitted. #[test] fn self_tests() { + match option_env!("CFG_RELEASE_CHANNEL") { + None | Some("nightly") => {} + _ => return, // these tests require nightly + } let mut files = get_test_files(Path::new("tests"), false); let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; for dir in bin_directories { -- cgit 1.4.1-3-g733a5 From 92f57211c1ed9a27fcd86bf05ee9c930b1b4449a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 17 Mar 2019 12:25:59 +0900 Subject: Support path-clarity submodule --- src/formatting.rs | 31 ++++++-- src/lib.rs | 20 ++++- src/modules.rs | 229 +++++++++++++++++++++++++++++++++++------------------- 3 files changed, 192 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index eee02f275cf..56adfa9b1a3 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -10,7 +10,7 @@ use syntax::ast; use syntax::errors::emitter::{ColorConfig, EmitterWriter}; use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; -use syntax::source_map::{FilePathMapping, SourceMap, Span}; +use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; @@ -73,7 +73,14 @@ fn format_project( let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let mut parse_session = make_parse_sess(source_map.clone(), config); let mut report = FormatReport::new(); - let krate = match parse_crate(input, &parse_session, config, &mut report) { + let directory_ownership = input.to_directory_ownership(); + let krate = match parse_crate( + input, + &parse_session, + config, + &mut report, + directory_ownership, + ) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) Err(ErrorKind::ParseError) => return Ok(report), @@ -87,8 +94,14 @@ fn format_project( let mut context = FormatContext::new(&krate, report, parse_session, config, handler); - let files = modules::list_files(&krate, context.parse_session.source_map())?; - for (path, module) in files { + let files = modules::ModResolver::new( + context.parse_session.source_map(), + directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(false)), + input_is_stdin, + ) + .visit_crate(&krate) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + for (path, (module, _)) in files { if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { continue; } @@ -593,11 +606,19 @@ fn parse_crate( parse_session: &ParseSess, config: &Config, report: &mut FormatReport, + directory_ownership: Option, ) -> Result { let input_is_stdin = input.is_text(); let parser = match input { - Input::File(file) => Ok(parse::new_parser_from_file(parse_session, &file)), + Input::File(ref file) => { + // Use `new_sub_parser_from_file` when we the input is a submodule. + Ok(if let Some(dir_own) = directory_ownership { + parse::new_sub_parser_from_file(parse_session, file, dir_own, None, DUMMY_SP) + } else { + parse::new_parser_from_file(parse_session, file) + }) + } Input::Text(text) => parse::maybe_new_parser_from_source_str( parse_session, syntax::source_map::FileName::Custom("stdin".to_owned()), diff --git a/src/lib.rs b/src/lib.rs index 53e74210ede..b1090e95ff3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ use std::path::PathBuf; use std::rc::Rc; use failure::Fail; -use syntax::ast; +use syntax::{ast, parse::DirectoryOwnership}; use crate::comment::LineClasses; use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; @@ -586,6 +586,24 @@ impl Input { Input::Text(..) => FileName::Stdin, } } + + fn to_directory_ownership(&self) -> Option { + match self { + Input::File(ref file) => { + // If there exists a directory with the same name as an input, + // then the input should be parsed as a sub module. + let file_stem = file.file_stem()?; + if file.parent()?.to_path_buf().join(file_stem).is_dir() { + Some(DirectoryOwnership::Owned { + relative: file_stem.to_str().map(ast::Ident::from_str), + }) + } else { + None + } + } + _ => None, + } + } } #[cfg(test)] diff --git a/src/modules.rs b/src/modules.rs index 7bb50356ed8..01a0784c6f4 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -1,5 +1,4 @@ use std::collections::BTreeMap; -use std::io; use std::path::{Path, PathBuf}; use syntax::ast; @@ -8,25 +7,157 @@ use syntax::source_map; use syntax_pos::symbol::Symbol; use crate::config::FileName; +use crate::items::is_mod_decl; use crate::utils::contains_skip; -/// List all the files containing modules of a crate. -/// If a file is used twice in a crate, it appears only once. -pub fn list_files<'a>( - krate: &'a ast::Crate, - source_map: &source_map::SourceMap, -) -> Result, io::Error> { - let mut result = BTreeMap::new(); // Enforce file order determinism - let root_filename = source_map.span_to_filename(krate.span); - { - let parent = match root_filename { - source_map::FileName::Real(ref path) => path.parent().unwrap(), - _ => Path::new(""), +type FileModMap<'a> = BTreeMap; + +/// Maps each module to the corresponding file. +pub struct ModResolver<'a, 'b> { + source_map: &'b source_map::SourceMap, + directory: Directory, + file_map: FileModMap<'a>, + is_input_stdin: bool, +} + +#[derive(Clone)] +struct Directory { + path: PathBuf, + ownership: DirectoryOwnership, +} + +impl<'a, 'b> ModResolver<'a, 'b> { + /// Creates a new `ModResolver`. + pub fn new( + source_map: &'b source_map::SourceMap, + directory_ownership: DirectoryOwnership, + is_input_stdin: bool, + ) -> Self { + ModResolver { + directory: Directory { + path: PathBuf::new(), + ownership: directory_ownership, + }, + file_map: BTreeMap::new(), + source_map, + is_input_stdin, + } + } + + /// Creates a map that maps a file name to the module in AST. + pub fn visit_crate(mut self, krate: &'a ast::Crate) -> Result, String> { + let root_filename = self.source_map.span_to_filename(krate.span); + self.directory.path = match root_filename { + source_map::FileName::Real(ref path) => path + .parent() + .expect("Parent directory should exists") + .to_path_buf(), + _ => PathBuf::new(), + }; + + // Skip visiting sub modules when the input is from stdin. + if !self.is_input_stdin { + self.visit_mod(&krate.module)?; + } + + self.file_map + .insert(root_filename.into(), (&krate.module, "")); + Ok(self.file_map) + } + + fn visit_mod(&mut self, module: &'a ast::Mod) -> Result<(), String> { + for item in &module.items { + if let ast::ItemKind::Mod(ref sub_mod) = item.node { + if contains_skip(&item.attrs) { + continue; + } + + let old_direcotry = self.directory.clone(); + if is_mod_decl(item) { + // mod foo; + // Look for an extern file. + let (mod_path, directory_ownership) = + self.find_external_module(item.ident, &item.attrs)?; + self.file_map.insert( + FileName::Real(mod_path.clone()), + (sub_mod, item.ident.name.as_str().get()), + ); + self.directory = Directory { + path: mod_path.parent().unwrap().to_path_buf(), + ownership: directory_ownership, + } + } else { + // An internal module (`mod foo { /* ... */ }`); + if let Some(path) = find_path_value(&item.attrs) { + // All `#[path]` files are treated as though they are a `mod.rs` file. + self.directory = Directory { + path: Path::new(&path.as_str()).to_path_buf(), + ownership: DirectoryOwnership::Owned { relative: None }, + }; + } else { + self.push_inline_mod_directory(item.ident, &item.attrs); + } + } + self.visit_mod(sub_mod)?; + self.directory = old_direcotry; + } + } + Ok(()) + } + + fn find_external_module( + &self, + mod_name: ast::Ident, + attrs: &[ast::Attribute], + ) -> Result<(PathBuf, DirectoryOwnership), String> { + if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &self.directory.path) { + return Ok((path, DirectoryOwnership::Owned { relative: None })); + } + + let relative = match self.directory.ownership { + DirectoryOwnership::Owned { relative } => relative, + DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod(_) => None, }; - list_submodules(&krate.module, parent, None, source_map, &mut result)?; + match parser::Parser::default_submod_path( + mod_name, + relative, + &self.directory.path, + self.source_map, + ) + .result + { + Ok(parser::ModulePathSuccess { + path, + directory_ownership, + .. + }) => Ok((path, directory_ownership)), + Err(_) => Err(format!( + "Failed to find module {} in {:?} {:?}", + mod_name, self.directory.path, relative, + )), + } + } + + fn push_inline_mod_directory(&mut self, id: ast::Ident, attrs: &[ast::Attribute]) { + if let Some(path) = find_path_value(attrs) { + self.directory.path.push(&path.as_str()); + self.directory.ownership = DirectoryOwnership::Owned { relative: None }; + } else { + // We have to push on the current module name in the case of relative + // paths in order to ensure that any additional module paths from inline + // `mod x { ... }` come after the relative extension. + // + // For example, a `mod z { ... }` inside `x/y.rs` should set the current + // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. + if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership { + if let Some(ident) = relative.take() { + // remove the relative offset + self.directory.path.push(ident.as_str()); + } + } + self.directory.path.push(&id.as_str()); + } } - result.insert(root_filename.into(), &krate.module); - Ok(result) } fn path_value(attr: &ast::Attribute) -> Option { @@ -43,69 +174,3 @@ fn path_value(attr: &ast::Attribute) -> Option { fn find_path_value(attrs: &[ast::Attribute]) -> Option { attrs.iter().flat_map(path_value).next() } - -/// Recursively list all external modules included in a module. -fn list_submodules<'a>( - module: &'a ast::Mod, - search_dir: &Path, - relative: Option, - source_map: &source_map::SourceMap, - result: &mut BTreeMap, -) -> Result<(), io::Error> { - debug!("list_submodules: search_dir: {:?}", search_dir); - for item in &module.items { - if let ast::ItemKind::Mod(ref sub_mod) = item.node { - if !contains_skip(&item.attrs) { - let is_internal = source_map.span_to_filename(item.span) - == source_map.span_to_filename(sub_mod.inner); - let (dir_path, relative) = if is_internal { - if let Some(path) = find_path_value(&item.attrs) { - (search_dir.join(&path.as_str()), None) - } else { - (search_dir.join(&item.ident.to_string()), None) - } - } else { - let (mod_path, relative) = - module_file(item.ident, &item.attrs, search_dir, relative, source_map)?; - let dir_path = mod_path.parent().unwrap().to_owned(); - result.insert(FileName::Real(mod_path), sub_mod); - (dir_path, relative) - }; - list_submodules(sub_mod, &dir_path, relative, source_map, result)?; - } - } - } - Ok(()) -} - -/// Finds the file corresponding to an external mod -fn module_file( - id: ast::Ident, - attrs: &[ast::Attribute], - dir_path: &Path, - relative: Option, - source_map: &source_map::SourceMap, -) -> Result<(PathBuf, Option), io::Error> { - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) { - return Ok((path, None)); - } - - match parser::Parser::default_submod_path(id, relative, dir_path, source_map).result { - Ok(parser::ModulePathSuccess { - path, - directory_ownership, - .. - }) => { - let relative = if let DirectoryOwnership::Owned { relative } = directory_ownership { - relative - } else { - None - }; - Ok((path, relative)) - } - Err(_) => Err(io::Error::new( - io::ErrorKind::Other, - format!("Couldn't find module {}", id), - )), - } -} -- cgit 1.4.1-3-g733a5 From d0e96ed3310a289354cf7358a19fce02254cba40 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 17 Mar 2019 12:26:45 +0900 Subject: Do not look for external modules when the input is from stdin --- src/formatting.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 56adfa9b1a3..a23c312bd2a 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -624,6 +624,10 @@ fn parse_crate( syntax::source_map::FileName::Custom("stdin".to_owned()), text, ) + .map(|mut parser| { + parser.recurse_into_file_modules = false; + parser + }) .map_err(|diags| { diags .into_iter() -- cgit 1.4.1-3-g733a5 From 7fc4e418bfcc77b2ff6fc63cd542442d203b5eab Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 17 Mar 2019 12:27:24 +0900 Subject: Tweak test settings --- src/test/mod.rs | 15 ++++++++++++++- tests/source/configs/skip_children/foo/mod.rs | 3 +++ tests/target/configs/skip_children/foo/mod.rs | 3 +++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/source/configs/skip_children/foo/mod.rs create mode 100644 tests/target/configs/skip_children/foo/mod.rs (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 20845b08f83..98f81cbe245 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -17,6 +17,19 @@ use crate::{FormatReport, Input, Session}; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; +// A list of files on which we want to skip testing. +const SKIP_FILE_WHITE_LIST: &[&str] = &[ + // We want to make sure that the `skip_children` is correctly working, + // so we do not want to test this file directly. + "configs/skip_children/foo/mod.rs", +]; + +fn is_file_skip(path: &Path) -> bool { + SKIP_FILE_WHITE_LIST + .iter() + .any(|file_path| path.ends_with(file_path)) +} + // Returns a `Vec` containing `PathBuf`s of files with an `rs` extension in the // given path. The `recursive` argument controls if files from subdirectories // are also returned. @@ -31,7 +44,7 @@ fn get_test_files(path: &Path, recursive: bool) -> Vec { let path = entry.path(); if path.is_dir() && recursive { files.append(&mut get_test_files(&path, recursive)); - } else if path.extension().map_or(false, |f| f == "rs") { + } else if path.extension().map_or(false, |f| f == "rs") && !is_file_skip(&path) { files.push(path); } } diff --git a/tests/source/configs/skip_children/foo/mod.rs b/tests/source/configs/skip_children/foo/mod.rs new file mode 100644 index 00000000000..d7ff6cdb829 --- /dev/null +++ b/tests/source/configs/skip_children/foo/mod.rs @@ -0,0 +1,3 @@ +fn skip_formatting_this() { + println ! ( "Skip this" ) ; +} diff --git a/tests/target/configs/skip_children/foo/mod.rs b/tests/target/configs/skip_children/foo/mod.rs new file mode 100644 index 00000000000..d7ff6cdb829 --- /dev/null +++ b/tests/target/configs/skip_children/foo/mod.rs @@ -0,0 +1,3 @@ +fn skip_formatting_this() { + println ! ( "Skip this" ) ; +} -- cgit 1.4.1-3-g733a5 From be0ada27f4d0686b77e8119b223129d104985187 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sun, 17 Mar 2019 12:30:06 +0900 Subject: Add comment which refers to an issue on nightly-only test Co-Authored-By: topecongiro --- src/test/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 98f81cbe245..61d7c88884a 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -246,7 +246,7 @@ fn idempotence_tests() { fn self_tests() { match option_env!("CFG_RELEASE_CHANNEL") { None | Some("nightly") => {} - _ => return, // these tests require nightly + _ => return, // Issue-3443: these tests require nightly } let mut files = get_test_files(Path::new("tests"), false); let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; -- cgit 1.4.1-3-g733a5 From c9479de9a71ace57620ac49080ec708c4a428b5b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 19 Mar 2019 10:50:44 +0900 Subject: Avoid panic on macro inside deeply nested block Closes #3457. --- src/shape.rs | 4 ++++ src/visitor.rs | 2 +- tests/source/expr.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/target/expr.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/shape.rs b/src/shape.rs index d793d99a318..5524a21f4b7 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -228,6 +228,10 @@ impl Shape { } } + pub fn saturating_sub_width(&self, width: usize) -> Shape { + self.sub_width(width).unwrap_or(Shape { width: 0, ..*self }) + } + pub fn sub_width(&self, width: usize) -> Option { Some(Shape { width: self.width.checked_sub(width)?, diff --git a/src/visitor.rs b/src/visitor.rs index 3bd5af3112d..56a27889c20 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -536,7 +536,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_out_of_file_lines_range_visitor!(self, mac.span); // 1 = ; - let shape = self.shape().sub_width(1).unwrap(); + let shape = self.shape().saturating_sub_width(1); let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); self.push_rewrite(mac.span, rewrite); } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 514f755c698..1bb2d9014e2 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -479,3 +479,56 @@ fn issue3226() { } } } + +// #3457 +fn issue3457() { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + println!("Test"); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index e46cb898232..88de6f7fb88 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -562,3 +562,56 @@ fn issue3226() { } } } + +// #3457 +fn issue3457() { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + { + println!("Test"); + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From cdd08da27bfb76d24dc44848e4b086df7d25d4f6 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 19 Mar 2019 10:19:45 +0100 Subject: fix line numbering in missed spans and handle file_lines in edge cases - a leading/trailing newline character in missed spans was throwing off the start/end of ranges used to compare against file_lines - fix handling of file_lines when closing a block Close #3442 --- src/missed_spans.rs | 45 ++++++++++++++++++++++++++------ src/source_map.rs | 8 ++++-- src/visitor.rs | 64 +++++++++++++++++++++++++++------------------- tests/target/issue-3442.rs | 10 ++++++++ 4 files changed, 91 insertions(+), 36 deletions(-) create mode 100644 tests/target/issue-3442.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 27b94a6c8ae..70ca898f2af 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use syntax::source_map::{BytePos, Pos, Span}; use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::config::file_lines::FileLines; use crate::config::{EmitMode, FileName}; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; @@ -156,7 +157,7 @@ impl<'a> FmtVisitor<'a> { fn write_snippet_inner( &mut self, big_snippet: &str, - big_diff: usize, + mut big_diff: usize, old_snippet: &str, span: Span, process_last_snippet: F, @@ -175,16 +176,36 @@ impl<'a> FmtVisitor<'a> { _ => Cow::from(old_snippet), }; - for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { - debug!("{:?}: {:?}", kind, subslice); + // if the snippet starts with a new line, then information about the lines needs to be + // adjusted since it is off by 1. + let snippet = if snippet.starts_with('\n') { + // this takes into account the blank_lines_* options + self.push_vertical_spaces(1); + // include the newline character into the big_diff + big_diff += 1; + status.cur_line += 1; + &snippet[1..] + } else { + snippet + }; - let newline_count = count_newlines(subslice); - let within_file_lines_range = self.config.file_lines().contains_range( + let slice_within_file_lines_range = |file_lines: FileLines, cur_line, s| -> (usize, bool) { + let newline_count = count_newlines(s); + let within_file_lines_range = file_lines.contains_range( file_name, - status.cur_line, - status.cur_line + newline_count, + cur_line, + // if a newline character is at the end of the slice, then the number of newlines + // needs to be decreased by 1 so that the range checked against the file_lines is + // the visual range one would expect. + cur_line + newline_count - if s.ends_with('\n') { 1 } else { 0 }, ); + (newline_count, within_file_lines_range) + }; + for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { + debug!("{:?}: {:?}", kind, subslice); + let (newline_count, within_file_lines_range) = + slice_within_file_lines_range(self.config.file_lines(), status.cur_line, subslice); if CodeCharKind::Comment == kind && within_file_lines_range { // 1: comment. self.process_comment( @@ -205,7 +226,15 @@ impl<'a> FmtVisitor<'a> { } } - process_last_snippet(self, &snippet[status.line_start..], snippet); + let last_snippet = &snippet[status.line_start..]; + let (_, within_file_lines_range) = + slice_within_file_lines_range(self.config.file_lines(), status.cur_line, last_snippet); + if within_file_lines_range { + process_last_snippet(self, last_snippet, snippet); + } else { + // just append what's left + self.push_str(last_snippet); + } } fn process_comment( diff --git a/src/source_map.rs b/src/source_map.rs index c98b7596383..096a7ce5713 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -71,6 +71,7 @@ impl<'a> SpanUtils for SnippetProvider<'a> { impl LineRangeUtils for SourceMap { fn lookup_line_range(&self, span: Span) -> LineRange { + let snippet = self.span_to_snippet(span).unwrap_or(String::new()); let lo = self.lookup_line(span.lo()).unwrap(); let hi = self.lookup_line(span.hi()).unwrap(); @@ -80,11 +81,14 @@ impl LineRangeUtils for SourceMap { lo, hi ); + // in case the span starts with a newline, the line range is off by 1 without the + // adjustment below + let offset = 1 + if snippet.starts_with('\n') { 1 } else { 0 }; // Line numbers start at 1 LineRange { file: lo.sf.clone(), - lo: lo.line + 1, - hi: hi.line + 1, + lo: lo.line + offset, + hi: hi.line + offset, } } } diff --git a/src/visitor.rs b/src/visitor.rs index 3bd5af3112d..2c603fbebf7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -6,6 +6,7 @@ use syntax::{ast, visit}; use crate::attr::*; use crate::comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; +use crate::config::file_lines::FileName; use crate::config::{BraceStyle, Config, Version}; use crate::expr::{format_expr, ExprType}; use crate::items::{ @@ -170,7 +171,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if skip_rewrite { self.push_rewrite(b.span, None); - self.close_block(false); + self.close_block(false, b.span); self.last_pos = source!(self, b.span).hi(); return; } @@ -187,21 +188,25 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let mut remove_len = BytePos(0); if let Some(stmt) = b.stmts.last() { - let snippet = self.snippet(mk_sp( + let span_after_last_stmt = mk_sp( stmt.span.hi(), source!(self, b.span).hi() - brace_compensation, - )); - let len = CommentCodeSlices::new(snippet) - .last() - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal && s.trim().is_empty() { - Some(s.len()) - } else { - None - } - }); - if let Some(len) = len { - remove_len = BytePos::from_usize(len); + ); + // if the span is outside of a file_lines range, then do not try to remove anything + if !out_of_file_lines_range!(self, span_after_last_stmt) { + let snippet = self.snippet(span_after_last_stmt); + let len = CommentCodeSlices::new(snippet) + .last() + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal && s.trim().is_empty() { + Some(s.len()) + } else { + None + } + }); + if let Some(len) = len { + remove_len = BytePos::from_usize(len); + } } } @@ -220,7 +225,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if unindent_comment { self.block_indent = self.block_indent.block_indent(self.config); } - self.close_block(unindent_comment); + self.close_block(unindent_comment, b.span); self.last_pos = source!(self, b.span).hi(); } @@ -228,16 +233,23 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // item in the block and the closing brace to the block's level. // The closing brace itself, however, should be indented at a shallower // level. - fn close_block(&mut self, unindent_comment: bool) { - let total_len = self.buffer.len(); - let chars_too_many = if unindent_comment { - 0 - } else if self.config.hard_tabs() { - 1 - } else { - self.config.tab_spaces() - }; - self.buffer.truncate(total_len - chars_too_many); + fn close_block(&mut self, unindent_comment: bool, span: Span) { + let file_name: FileName = self.source_map.span_to_filename(span).into(); + let skip_this_line = !self + .config + .file_lines() + .contains_line(&file_name, self.line_number); + if !skip_this_line { + let total_len = self.buffer.len(); + let chars_too_many = if unindent_comment { + 0 + } else if self.config.hard_tabs() { + 1 + } else { + self.config.tab_spaces() + }; + self.buffer.truncate(total_len - chars_too_many); + } self.push_str("}"); self.block_indent = self.block_indent.block_unindent(self.config); } @@ -759,7 +771,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_attrs(attrs, ast::AttrStyle::Inner); self.walk_mod_items(m); self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); - self.close_block(false); + self.close_block(false, m.inner); } self.last_pos = source!(self, m.inner).hi(); } else { diff --git a/tests/target/issue-3442.rs b/tests/target/issue-3442.rs new file mode 100644 index 00000000000..3664c50ee7a --- /dev/null +++ b/tests/target/issue-3442.rs @@ -0,0 +1,10 @@ +// rustfmt-file_lines: [{"file":"tests/target/issue-3442.rs","range":[5,5]},{"file":"tests/target/issue-3442.rs","range":[8,8]}] + +extern crate alpha; // comment 1 +extern crate beta; // comment 2 +#[allow(aaa)] // comment 3 +#[macro_use] +extern crate gamma; +#[allow(bbb)] // comment 4 +#[macro_use] +extern crate lazy_static; -- cgit 1.4.1-3-g733a5 From 1f8553d66ff8aa25e54bc5a5be8550cdfe1ee476 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sat, 16 Mar 2019 23:13:10 +0900 Subject: add new attribute rustfmt::skip::macros add test for function not having attribute --- src/expr.rs | 22 +++++++++++++++------- src/rewrite.rs | 1 + src/visitor.rs | 47 ++++++++++++++++++++++++++++++++++++++++------ tests/source/issue-3434.rs | 22 ++++++++++++++++++++++ tests/target/issue-3434.rs | 24 +++++++++++++++++++++++ 5 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 tests/source/issue-3434.rs create mode 100644 tests/target/issue-3434.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 068b8f7fed6..1f8d08704ba 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -190,13 +190,20 @@ pub fn format_expr( rewrite_chain(expr, context, shape) } ast::ExprKind::Mac(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - }) + let should_skip = context + .skip_macro_names + .contains(&context.snippet(mac.node.path.span).to_owned()); + if should_skip { + None + } else { + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + }) + } } ast::ExprKind::Ret(None) => Some("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { @@ -1920,6 +1927,7 @@ pub fn rewrite_assign_rhs_with, R: Rewrite>( offset: shape.offset + last_line_width + 1, ..shape }); + // dbg!( let rhs = choose_rhs( context, ex, diff --git a/src/rewrite.rs b/src/rewrite.rs index df147e0c427..01ba5410896 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -39,6 +39,7 @@ pub struct RewriteContext<'a> { // Used for `format_snippet` pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, + pub skip_macro_names: Vec, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index 56a27889c20..ada69d860d8 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,7 +1,8 @@ use std::cell::RefCell; -use syntax::parse::ParseSess; +use syntax::parse::{token, ParseSess}; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; +use syntax::tokenstream::TokenTree; use syntax::{ast, visit}; use crate::attr::*; @@ -66,6 +67,7 @@ pub struct FmtVisitor<'a> { pub skipped_range: Vec<(usize, usize)>, pub macro_rewrite_failure: bool, pub(crate) report: FormatReport, + pub skip_macro_names: Vec, } impl<'a> Drop for FmtVisitor<'a> { @@ -331,6 +333,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } } + self.get_skip_macros(&attrs); match item.node { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), @@ -437,7 +440,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } - } + }; + self.skip_macro_names.clear(); } pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { @@ -616,6 +620,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skipped_range: vec![], macro_rewrite_failure: false, report, + skip_macro_names: vec![], } } @@ -640,10 +645,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ErrorKind::DeprecatedAttr, )], ); - } else if attr.path.segments[0].ident.to_string() == "rustfmt" - && (attr.path.segments.len() == 1 - || attr.path.segments[1].ident.to_string() != "skip") - { + } else if self.is_rustfmt_macro_error(&attr.path.segments) { let file_name = self.source_map.span_to_filename(attr.span).into(); self.report.append( file_name, @@ -671,6 +673,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { false } + fn is_rustfmt_macro_error(&self, segments: &Vec) -> bool { + if segments[0].ident.to_string() != "rustfmt" { + return false; + } + + match segments.len() { + 2 => segments[1].ident.to_string() != "skip", + 3 => { + segments[1].ident.to_string() != "skip" || segments[2].ident.to_string() != "macros" + } + _ => false, + } + } + fn walk_mod_items(&mut self, m: &ast::Mod) { self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); } @@ -817,6 +833,25 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider: self.snippet_provider, macro_rewrite_failure: RefCell::new(false), report: self.report.clone(), + skip_macro_names: self.skip_macro_names.clone(), + } + } + + pub fn get_skip_macros(&mut self, attrs: &[ast::Attribute]) { + for attr in attrs { + for token in attr.tokens.trees() { + if let TokenTree::Delimited(_, _, stream) = token { + for inner_token in stream.trees() { + if let TokenTree::Token(span, token) = inner_token { + if let token::Token::Ident(_, _) = token { + // FIXME ident.span.lo() and ident.span.hi() are 0 + let macro_name = self.get_context().snippet(span).to_owned(); + self.skip_macro_names.push(macro_name); + } + } + } + } + } } } } diff --git a/tests/source/issue-3434.rs b/tests/source/issue-3434.rs new file mode 100644 index 00000000000..5d753ef0c4d --- /dev/null +++ b/tests/source/issue-3434.rs @@ -0,0 +1,22 @@ +#[rustfmt::skip::macros(html, skip_macro)] +fn main() { + let macro_result1 = html! {
+Hello
+ }.to_string(); + + let macro_result2 = not_skip_macro! {
+Hello
+ }.to_string(); + + skip_macro! { +this is a skip_macro here +}; + + foo(); +} + +fn foo() { + let macro_result1 = html! {
+Hello
+ }.to_string(); +} diff --git a/tests/target/issue-3434.rs b/tests/target/issue-3434.rs new file mode 100644 index 00000000000..44171bb83fb --- /dev/null +++ b/tests/target/issue-3434.rs @@ -0,0 +1,24 @@ +#[rustfmt::skip::macros(html, skip_macro)] +fn main() { + let macro_result1 = html! {
+Hello
+ }.to_string(); + + let macro_result2 = not_skip_macro! {
+ Hello
+ } + .to_string(); + + skip_macro! { +this is a skip_macro here +}; + + foo(); +} + +fn foo() { + let macro_result1 = html! {
+ Hello
+ } + .to_string(); +} -- cgit 1.4.1-3-g733a5 From f493a59783f3062eff30613e05436dd59087d060 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sat, 16 Mar 2019 23:33:26 +0900 Subject: use RefCell and Rc --- src/expr.rs | 1 + src/rewrite.rs | 3 ++- src/visitor.rs | 9 +++++---- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1f8d08704ba..247ec298b00 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -192,6 +192,7 @@ pub fn format_expr( ast::ExprKind::Mac(ref mac) => { let should_skip = context .skip_macro_names + .borrow() .contains(&context.snippet(mac.node.path.span).to_owned()); if should_skip { None diff --git a/src/rewrite.rs b/src/rewrite.rs index 01ba5410896..406dc64dccf 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -1,6 +1,7 @@ // A generic trait to abstract the rewriting of an element (of the AST). use std::cell::RefCell; +use std::rc::Rc; use syntax::parse::ParseSess; use syntax::ptr; @@ -39,7 +40,7 @@ pub struct RewriteContext<'a> { // Used for `format_snippet` pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, - pub skip_macro_names: Vec, + pub skip_macro_names: Rc>>, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index ada69d860d8..4b1bd5bc55e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::rc::Rc; use syntax::parse::{token, ParseSess}; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; @@ -67,7 +68,7 @@ pub struct FmtVisitor<'a> { pub skipped_range: Vec<(usize, usize)>, pub macro_rewrite_failure: bool, pub(crate) report: FormatReport, - pub skip_macro_names: Vec, + pub skip_macro_names: Rc>>, } impl<'a> Drop for FmtVisitor<'a> { @@ -441,7 +442,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(item.span, rewrite); } }; - self.skip_macro_names.clear(); + self.skip_macro_names.borrow_mut().clear(); } pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { @@ -620,7 +621,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skipped_range: vec![], macro_rewrite_failure: false, report, - skip_macro_names: vec![], + skip_macro_names: Rc::new(RefCell::new(vec![])), } } @@ -846,7 +847,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if let token::Token::Ident(_, _) = token { // FIXME ident.span.lo() and ident.span.hi() are 0 let macro_name = self.get_context().snippet(span).to_owned(); - self.skip_macro_names.push(macro_name); + self.skip_macro_names.borrow_mut().push(macro_name); } } } -- cgit 1.4.1-3-g733a5 From 1fa06ecf1ef7684b4ed3674028aa304e62ddfd90 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Wed, 20 Mar 2019 18:18:02 +0100 Subject: Fix formatting of async blocks --- src/expr.rs | 2 +- tests/source/async_block.rs | 16 ++++++++++++++++ tests/target/async_block.rs | 10 ++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 068b8f7fed6..90cbba334f1 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1357,7 +1357,7 @@ pub fn can_be_overflowed_expr( } // Handle always block-like expressions - ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true, + ast::ExprKind::Async(..) | ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => true, // Handle `[]` and `{}`-like expressions ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) => { diff --git a/tests/source/async_block.rs b/tests/source/async_block.rs index a7018316812..3de51a084d2 100644 --- a/tests/source/async_block.rs +++ b/tests/source/async_block.rs @@ -16,4 +16,20 @@ fn baz() { let y = async { Ok(()) }; // comment + + spawn( + a, + async move { + action(); + Ok(()) + }, + ); + + spawn( + a, + async move || { + action(); + Ok(()) + }, + ); } diff --git a/tests/target/async_block.rs b/tests/target/async_block.rs index 5c1649373ad..258dd937a6f 100644 --- a/tests/target/async_block.rs +++ b/tests/target/async_block.rs @@ -12,4 +12,14 @@ fn baz() { }; let y = async { Ok(()) }; // comment + + spawn(a, async move { + action(); + Ok(()) + }); + + spawn(a, async move || { + action(); + Ok(()) + }); } -- cgit 1.4.1-3-g733a5 From 017e491a1770c79ae923300fd7b57008589e3b68 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Thu, 21 Mar 2019 15:58:39 +0900 Subject: Avoid duplication on the presence of spaces between macro name and ! --- src/macros.rs | 8 +++----- tests/source/macros.rs | 4 ++++ tests/target/macros.rs | 4 ++++ 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 60fdb9160a7..95504a23aba 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -431,12 +431,10 @@ pub fn rewrite_macro_inner( // For macro invocations with braces, always put a space between // the `macro_name!` and `{ /* macro_body */ }` but skip modifying // anything in between the braces (for now). - let snippet = context.snippet(mac.span); - // to remove unnecessary space after macro name - let macro_raw = snippet.trim_start_matches(¯o_name).trim_start(); - match trim_left_preserve_layout(macro_raw, shape.indent, &context.config) { + let snippet = context.snippet(mac.span).trim_start_matches(|c| c != '{'); + match trim_left_preserve_layout(snippet, shape.indent, &context.config) { Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), - None => Some(format!("{} {}", macro_name, macro_raw)), + None => Some(format!("{} {}", macro_name, snippet)), } } _ => unreachable!(), diff --git a/tests/source/macros.rs b/tests/source/macros.rs index d41a72e52f1..66012e4d69d 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -471,3 +471,7 @@ pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { name: (_i.name).map(|it| _visitor.fold_lit_str(it)), } } + +// #3463 +x ! {()} +x ! y {()} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index d0fe892d91b..8f86b79f922 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1048,3 +1048,7 @@ pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { name: (_i.name).map(|it| _visitor.fold_lit_str(it)), } } + +// #3463 +x! {()} +x! y {()} -- cgit 1.4.1-3-g733a5 From bbbc1e86ebe3a003d41bd7b912ee3042086ff918 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Mon, 18 Mar 2019 21:41:31 +0900 Subject: refrect topecongiro reviews - &Vec => &[ast::PathSegment] - remove unnecessary implements - transfer skip logic to inside rewrite_macro - fix test - use util methods in libsyntax - use meta_item_list directly - avoid no_entry.rs for test using module system - add logic to skip rustfmt::skip::macros only - remove base_skip_macro_names - remove Rc - use clone to append skip_macro_names --- src/expr.rs | 23 +-- src/formatting.rs | 10 +- src/macros.rs | 19 +- src/rewrite.rs | 3 +- src/test/mod.rs | 1 + src/utils.rs | 20 +++ src/visitor.rs | 279 +++++++++++++++--------------- tests/source/issue-3434.rs | 22 --- tests/source/issue-3434/lib.rs | 36 ++++ tests/source/issue-3434/no_entry.rs | 18 ++ tests/source/issue-3434/not_skip_macro.rs | 8 + tests/target/issue-3434.rs | 24 --- tests/target/issue-3434/lib.rs | 36 ++++ tests/target/issue-3434/no_entry.rs | 19 ++ tests/target/issue-3434/not_skip_macro.rs | 8 + 15 files changed, 311 insertions(+), 215 deletions(-) delete mode 100644 tests/source/issue-3434.rs create mode 100644 tests/source/issue-3434/lib.rs create mode 100644 tests/source/issue-3434/no_entry.rs create mode 100644 tests/source/issue-3434/not_skip_macro.rs delete mode 100644 tests/target/issue-3434.rs create mode 100644 tests/target/issue-3434/lib.rs create mode 100644 tests/target/issue-3434/no_entry.rs create mode 100644 tests/target/issue-3434/not_skip_macro.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 247ec298b00..068b8f7fed6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -190,21 +190,13 @@ pub fn format_expr( rewrite_chain(expr, context, shape) } ast::ExprKind::Mac(ref mac) => { - let should_skip = context - .skip_macro_names - .borrow() - .contains(&context.snippet(mac.node.path.span).to_owned()); - if should_skip { - None - } else { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - }) - } + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + }) } ast::ExprKind::Ret(None) => Some("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { @@ -1928,7 +1920,6 @@ pub fn rewrite_assign_rhs_with, R: Rewrite>( offset: shape.offset + last_line_width + 1, ..shape }); - // dbg!( let rhs = choose_rhs( context, ex, diff --git a/src/formatting.rs b/src/formatting.rs index a23c312bd2a..545d2fe279f 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -15,6 +15,7 @@ use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::issues::BadIssueSeeker; +use crate::utils::{count_newlines, get_skip_macro_names}; use crate::visitor::{FmtVisitor, SnippetProvider}; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; @@ -153,6 +154,10 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &snippet_provider, self.report.clone(), ); + visitor + .skip_macro_names + .borrow_mut() + .append(&mut get_skip_macro_names(&self.krate.attrs)); // Format inner attributes if available. if !self.krate.attrs.is_empty() && is_root { @@ -168,10 +173,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { visitor.format_separate_mod(module, &*source_file); }; - debug_assert_eq!( - visitor.line_number, - crate::utils::count_newlines(&visitor.buffer) - ); + debug_assert_eq!(visitor.line_number, count_newlines(&visitor.buffer)); // For some reason, the source_map does not include terminating // newlines so we must add one on for each file. This is sad. diff --git a/src/macros.rs b/src/macros.rs index 60fdb9160a7..40a3b7edcd6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -208,12 +208,21 @@ pub fn rewrite_macro( shape: Shape, position: MacroPosition, ) -> Option { - let guard = InsideMacroGuard::inside_macro_context(context); - let result = rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested); - if result.is_none() { - context.macro_rewrite_failure.replace(true); + let should_skip = context + .skip_macro_names + .borrow() + .contains(&context.snippet(mac.node.path.span).to_owned()); + if should_skip { + None + } else { + let guard = InsideMacroGuard::inside_macro_context(context); + let result = + rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested); + if result.is_none() { + context.macro_rewrite_failure.replace(true); + } + result } - result } fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { diff --git a/src/rewrite.rs b/src/rewrite.rs index 406dc64dccf..c736c2535a6 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -1,7 +1,6 @@ // A generic trait to abstract the rewriting of an element (of the AST). use std::cell::RefCell; -use std::rc::Rc; use syntax::parse::ParseSess; use syntax::ptr; @@ -40,7 +39,7 @@ pub struct RewriteContext<'a> { // Used for `format_snippet` pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, - pub skip_macro_names: Rc>>, + pub skip_macro_names: RefCell>, } impl<'a> RewriteContext<'a> { diff --git a/src/test/mod.rs b/src/test/mod.rs index 61d7c88884a..0628094fdef 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -22,6 +22,7 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ // We want to make sure that the `skip_children` is correctly working, // so we do not want to test this file directly. "configs/skip_children/foo/mod.rs", + "issue-3434/no_entry.rs", ]; fn is_file_skip(path: &Path) -> bool { diff --git a/src/utils.rs b/src/utils.rs index e42b5c8c7d1..743a8627612 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -603,6 +603,26 @@ pub(crate) fn unicode_str_width(s: &str) -> usize { s.width() } +pub fn get_skip_macro_names(attrs: &[ast::Attribute]) -> Vec { + let mut skip_macro_names = vec![]; + for attr in attrs { + // syntax::ast::Path is implemented partialEq + // but it is designed for segments.len() == 1 + if format!("{}", attr.path) != "rustfmt::skip::macros" { + continue; + } + + if let Some(list) = attr.meta_item_list() { + for spanned in list { + if let Some(name) = spanned.name() { + skip_macro_names.push(name.to_string()); + } + } + } + } + skip_macro_names +} + #[cfg(test)] mod test { use super::*; diff --git a/src/visitor.rs b/src/visitor.rs index 4b1bd5bc55e..441f7b4e75f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,9 +1,7 @@ use std::cell::RefCell; -use std::rc::Rc; -use syntax::parse::{token, ParseSess}; +use syntax::parse::ParseSess; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; -use syntax::tokenstream::TokenTree; use syntax::{ast, visit}; use crate::attr::*; @@ -22,8 +20,8 @@ use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::utils::{ - self, contains_skip, count_newlines, inner_attributes, mk_sp, ptr_vec_to_ref_vec, - rewrite_ident, stmt_expr, DEPR_SKIP_ANNOTATION, + self, contains_skip, count_newlines, get_skip_macro_names, inner_attributes, mk_sp, + ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, DEPR_SKIP_ANNOTATION, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -68,7 +66,7 @@ pub struct FmtVisitor<'a> { pub skipped_range: Vec<(usize, usize)>, pub macro_rewrite_failure: bool, pub(crate) report: FormatReport, - pub skip_macro_names: Rc>>, + pub skip_macro_names: RefCell>, } impl<'a> Drop for FmtVisitor<'a> { @@ -299,25 +297,32 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // the AST lumps them all together. let filtered_attrs; let mut attrs = &item.attrs; - match item.node { + let temp_skip_macro_names = self.skip_macro_names.clone(); + self.skip_macro_names + .borrow_mut() + .append(&mut get_skip_macro_names(&attrs)); + + let should_visit_node_again = match item.node { // For use items, skip rewriting attributes. Just check for a skip attribute. ast::ItemKind::Use(..) => { if contains_skip(attrs) { self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span()); - return; + false + } else { + true } } // Module is inline, in this case we treat it like any other item. _ if !is_mod_decl(item) => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_skipped_with_span(item.attrs.as_slice(), item.span(), item.span()); - return; + false + } else { + true } } // Module is not inline, but should be skipped. - ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => { - return; - } + ast::ItemKind::Mod(..) if contains_skip(&item.attrs) => false, // Module is not inline and should not be skipped. We want // to process only the attributes in the current file. ast::ItemKind::Mod(..) => { @@ -326,123 +331,127 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // the above case. assert!(!self.visit_attrs(&filtered_attrs, ast::AttrStyle::Outer)); attrs = &filtered_attrs; + true } _ => { if self.visit_attrs(&item.attrs, ast::AttrStyle::Outer) { self.push_skipped_with_span(item.attrs.as_slice(), item.span(), item.span()); - return; + false + } else { + true } } - } - self.get_skip_macros(&attrs); - - match item.node { - ast::ItemKind::Use(ref tree) => self.format_import(item, tree), - ast::ItemKind::Impl(..) => { - let snippet = self.snippet(item.span); - let where_span_end = snippet - .find_uncommented("{") - .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); - let block_indent = self.block_indent; - let rw = - self.with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end)); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::Trait(..) => { - let block_indent = self.block_indent; - let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { - let shape = Shape::indented(self.block_indent, self.config); - let rw = format_trait_alias( - &self.get_context(), - item.ident, - &item.vis, - generics, - generic_bounds, - shape, - ); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::ExternCrate(_) => { - let rw = rewrite_extern_crate(&self.get_context(), item); - self.push_rewrite(item.span, rw); - } - ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { - self.visit_struct(&StructParts::from_item(item)); - } - ast::ItemKind::Enum(ref def, ref generics) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - self.visit_enum(item.ident, &item.vis, def, generics, item.span); - self.last_pos = source!(self, item.span).hi(); - } - ast::ItemKind::Mod(ref module) => { - let is_inline = !is_mod_decl(item); - self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); - } - ast::ItemKind::Mac(ref mac) => { - self.visit_mac(mac, Some(item.ident), MacroPosition::Item); - } - ast::ItemKind::ForeignMod(ref foreign_mod) => { - self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_foreign_mod(foreign_mod, item.span); - } - ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { - self.visit_static(&StaticParts::from_item(item)); - } - ast::ItemKind::Fn(ref decl, ref fn_header, ref generics, ref body) => { - let inner_attrs = inner_attributes(&item.attrs); - self.visit_fn( - visit::FnKind::ItemFn(item.ident, fn_header, &item.vis, body), - generics, - decl, - item.span, - ast::Defaultness::Final, - Some(&inner_attrs), - ) - } - ast::ItemKind::Ty(ref ty, ref generics) => { - let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, - item.ident, - ty, - generics, - &item.vis, - ); - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::Existential(ref generic_bounds, ref generics) => { - let rewrite = rewrite_existential_type( - &self.get_context(), - self.block_indent, - item.ident, - generic_bounds, - generics, - &item.vis, - ); - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::GlobalAsm(..) => { - let snippet = Some(self.snippet(item.span).to_owned()); - self.push_rewrite(item.span, snippet); - } - ast::ItemKind::MacroDef(ref def) => { - let rewrite = rewrite_macro_def( - &self.get_context(), - self.shape(), - self.block_indent, - def, - item.ident, - &item.vis, - item.span, - ); - self.push_rewrite(item.span, rewrite); - } }; - self.skip_macro_names.borrow_mut().clear(); + + if should_visit_node_again { + match item.node { + ast::ItemKind::Use(ref tree) => self.format_import(item, tree), + ast::ItemKind::Impl(..) => { + let snippet = self.snippet(item.span); + let where_span_end = snippet + .find_uncommented("{") + .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); + let block_indent = self.block_indent; + let rw = self + .with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end)); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::Trait(..) => { + let block_indent = self.block_indent; + let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { + let shape = Shape::indented(self.block_indent, self.config); + let rw = format_trait_alias( + &self.get_context(), + item.ident, + &item.vis, + generics, + generic_bounds, + shape, + ); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::ExternCrate(_) => { + let rw = rewrite_extern_crate(&self.get_context(), item); + self.push_rewrite(item.span, rw); + } + ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { + self.visit_struct(&StructParts::from_item(item)); + } + ast::ItemKind::Enum(ref def, ref generics) => { + self.format_missing_with_indent(source!(self, item.span).lo()); + self.visit_enum(item.ident, &item.vis, def, generics, item.span); + self.last_pos = source!(self, item.span).hi(); + } + ast::ItemKind::Mod(ref module) => { + let is_inline = !is_mod_decl(item); + self.format_missing_with_indent(source!(self, item.span).lo()); + self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); + } + ast::ItemKind::Mac(ref mac) => { + self.visit_mac(mac, Some(item.ident), MacroPosition::Item); + } + ast::ItemKind::ForeignMod(ref foreign_mod) => { + self.format_missing_with_indent(source!(self, item.span).lo()); + self.format_foreign_mod(foreign_mod, item.span); + } + ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { + self.visit_static(&StaticParts::from_item(item)); + } + ast::ItemKind::Fn(ref decl, ref fn_header, ref generics, ref body) => { + let inner_attrs = inner_attributes(&item.attrs); + self.visit_fn( + visit::FnKind::ItemFn(item.ident, fn_header, &item.vis, body), + generics, + decl, + item.span, + ast::Defaultness::Final, + Some(&inner_attrs), + ) + } + ast::ItemKind::Ty(ref ty, ref generics) => { + let rewrite = rewrite_type_alias( + &self.get_context(), + self.block_indent, + item.ident, + ty, + generics, + &item.vis, + ); + self.push_rewrite(item.span, rewrite); + } + ast::ItemKind::Existential(ref generic_bounds, ref generics) => { + let rewrite = rewrite_existential_type( + &self.get_context(), + self.block_indent, + item.ident, + generic_bounds, + generics, + &item.vis, + ); + self.push_rewrite(item.span, rewrite); + } + ast::ItemKind::GlobalAsm(..) => { + let snippet = Some(self.snippet(item.span).to_owned()); + self.push_rewrite(item.span, snippet); + } + ast::ItemKind::MacroDef(ref def) => { + let rewrite = rewrite_macro_def( + &self.get_context(), + self.shape(), + self.block_indent, + def, + item.ident, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + }; + } + self.skip_macro_names = temp_skip_macro_names; } pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { @@ -597,6 +606,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ctx.snippet_provider, ctx.report.clone(), ); + visitor + .skip_macro_names + .borrow_mut() + .append(&mut ctx.skip_macro_names.borrow().clone()); visitor.set_parent_context(ctx); visitor } @@ -621,7 +634,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skipped_range: vec![], macro_rewrite_failure: false, report, - skip_macro_names: Rc::new(RefCell::new(vec![])), + skip_macro_names: RefCell::new(vec![]), } } @@ -674,7 +687,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { false } - fn is_rustfmt_macro_error(&self, segments: &Vec) -> bool { + fn is_rustfmt_macro_error(&self, segments: &[ast::PathSegment]) -> bool { if segments[0].ident.to_string() != "rustfmt" { return false; } @@ -837,22 +850,4 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skip_macro_names: self.skip_macro_names.clone(), } } - - pub fn get_skip_macros(&mut self, attrs: &[ast::Attribute]) { - for attr in attrs { - for token in attr.tokens.trees() { - if let TokenTree::Delimited(_, _, stream) = token { - for inner_token in stream.trees() { - if let TokenTree::Token(span, token) = inner_token { - if let token::Token::Ident(_, _) = token { - // FIXME ident.span.lo() and ident.span.hi() are 0 - let macro_name = self.get_context().snippet(span).to_owned(); - self.skip_macro_names.borrow_mut().push(macro_name); - } - } - } - } - } - } - } } diff --git a/tests/source/issue-3434.rs b/tests/source/issue-3434.rs deleted file mode 100644 index 5d753ef0c4d..00000000000 --- a/tests/source/issue-3434.rs +++ /dev/null @@ -1,22 +0,0 @@ -#[rustfmt::skip::macros(html, skip_macro)] -fn main() { - let macro_result1 = html! {
-Hello
- }.to_string(); - - let macro_result2 = not_skip_macro! {
-Hello
- }.to_string(); - - skip_macro! { -this is a skip_macro here -}; - - foo(); -} - -fn foo() { - let macro_result1 = html! {
-Hello
- }.to_string(); -} diff --git a/tests/source/issue-3434/lib.rs b/tests/source/issue-3434/lib.rs new file mode 100644 index 00000000000..d3f4056bd8a --- /dev/null +++ b/tests/source/issue-3434/lib.rs @@ -0,0 +1,36 @@ +#![rustfmt::skip::macros(skip_macro_mod)] + +mod no_entry; + +#[rustfmt::skip::macros(html, skip_macro)] +fn main() { + let macro_result1 = html! {
+this should be skipped
+ } + .to_string(); + + let macro_result2 = not_skip_macro! {
+this should be mangled
+ } + .to_string(); + + skip_macro! { +this should be skipped +}; + + foo(); +} + +fn foo() { + let macro_result1 = html! {
+this should be mangled
+ } + .to_string(); +} + +fn bar() { + let macro_result1 = skip_macro_mod! {
+this should be skipped
+ } + .to_string(); +} diff --git a/tests/source/issue-3434/no_entry.rs b/tests/source/issue-3434/no_entry.rs new file mode 100644 index 00000000000..0838829fed3 --- /dev/null +++ b/tests/source/issue-3434/no_entry.rs @@ -0,0 +1,18 @@ +#[rustfmt::skip::macros(another_macro)] +fn foo() { + another_macro!( +This should be skipped. + ); +} + +fn bar() { + skip_macro_mod!( +This should be skipped. + ); +} + +fn baz() { + let macro_result1 = no_skip_macro! {
+this should be mangled
+ }.to_string(); +} diff --git a/tests/source/issue-3434/not_skip_macro.rs b/tests/source/issue-3434/not_skip_macro.rs new file mode 100644 index 00000000000..1d7d73c523d --- /dev/null +++ b/tests/source/issue-3434/not_skip_macro.rs @@ -0,0 +1,8 @@ +#[this::is::not::skip::macros(ouch)] + +fn main() { + let macro_result1 = ouch! {
+this should be mangled
+ } + .to_string(); +} diff --git a/tests/target/issue-3434.rs b/tests/target/issue-3434.rs deleted file mode 100644 index 44171bb83fb..00000000000 --- a/tests/target/issue-3434.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[rustfmt::skip::macros(html, skip_macro)] -fn main() { - let macro_result1 = html! {
-Hello
- }.to_string(); - - let macro_result2 = not_skip_macro! {
- Hello
- } - .to_string(); - - skip_macro! { -this is a skip_macro here -}; - - foo(); -} - -fn foo() { - let macro_result1 = html! {
- Hello
- } - .to_string(); -} diff --git a/tests/target/issue-3434/lib.rs b/tests/target/issue-3434/lib.rs new file mode 100644 index 00000000000..95bc75642f0 --- /dev/null +++ b/tests/target/issue-3434/lib.rs @@ -0,0 +1,36 @@ +#![rustfmt::skip::macros(skip_macro_mod)] + +mod no_entry; + +#[rustfmt::skip::macros(html, skip_macro)] +fn main() { + let macro_result1 = html! {
+this should be skipped
+ } + .to_string(); + + let macro_result2 = not_skip_macro! {
+ this should be mangled
+ } + .to_string(); + + skip_macro! { +this should be skipped +}; + + foo(); +} + +fn foo() { + let macro_result1 = html! {
+ this should be mangled
+ } + .to_string(); +} + +fn bar() { + let macro_result1 = skip_macro_mod! {
+this should be skipped
+ } + .to_string(); +} diff --git a/tests/target/issue-3434/no_entry.rs b/tests/target/issue-3434/no_entry.rs new file mode 100644 index 00000000000..a2ecf2c2f99 --- /dev/null +++ b/tests/target/issue-3434/no_entry.rs @@ -0,0 +1,19 @@ +#[rustfmt::skip::macros(another_macro)] +fn foo() { + another_macro!( +This should be skipped. + ); +} + +fn bar() { + skip_macro_mod!( +This should be skipped. + ); +} + +fn baz() { + let macro_result1 = no_skip_macro! {
+ this should be mangled
+ } + .to_string(); +} diff --git a/tests/target/issue-3434/not_skip_macro.rs b/tests/target/issue-3434/not_skip_macro.rs new file mode 100644 index 00000000000..c90d09744b2 --- /dev/null +++ b/tests/target/issue-3434/not_skip_macro.rs @@ -0,0 +1,8 @@ +#[this::is::not::skip::macros(ouch)] + +fn main() { + let macro_result1 = ouch! {
+ this should be mangled
+ } + .to_string(); +} -- cgit 1.4.1-3-g733a5 From 1d9104bbae5a86251a41cd455780f347af393783 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Thu, 21 Mar 2019 01:33:40 +0900 Subject: reflect scampi review - fix README.md - fix BadAttr doc - is_rustfmt_macro_error => is_unknown_rustfmt_attr --- README.md | 2 +- src/lib.rs | 2 +- src/visitor.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index 94878d0bba0..2738363160a 100644 --- a/README.md +++ b/README.md @@ -205,7 +205,7 @@ needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`. | coverage | displays how much of the input file was processed | Yes | | checkstyle | emits in a checkstyle format | Yes | -* For things you do not want rustfmt to mangle for some macro, +* To prevent rustfmt from formatting a macro, use `#[rustfmt::skip::macros(target_macro_name)]` Example: diff --git a/src/lib.rs b/src/lib.rs index b1090e95ff3..7e465ffdcfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ pub enum ErrorKind { /// Used deprecated skip attribute. #[fail(display = "`rustfmt_skip` is deprecated; use `rustfmt::skip`")] DeprecatedAttr, - /// Used a rustfmt:: attribute other than skip. + /// Used a rustfmt:: attribute other than skip or skip::macros. #[fail(display = "invalid attribute")] BadAttr, /// An io error during reading or writing. diff --git a/src/visitor.rs b/src/visitor.rs index 441f7b4e75f..8688c5b7827 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -659,7 +659,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ErrorKind::DeprecatedAttr, )], ); - } else if self.is_rustfmt_macro_error(&attr.path.segments) { + } else if self.is_unknown_rustfmt_attr(&attr.path.segments) { let file_name = self.source_map.span_to_filename(attr.span).into(); self.report.append( file_name, @@ -687,7 +687,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { false } - fn is_rustfmt_macro_error(&self, segments: &[ast::PathSegment]) -> bool { + fn is_unknown_rustfmt_attr(&self, segments: &[ast::PathSegment]) -> bool { if segments[0].ident.to_string() != "rustfmt" { return false; } -- cgit 1.4.1-3-g733a5 From 037cf2c43649b7040befd38122c2f86db5968580 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 24 Mar 2019 17:01:09 +0900 Subject: Discard every parsing error in silent_emitter `EmitterWriter` from rustc is wasting soooo much time constructing an error message that will never be emitted, instead we just implement our own `Emitter` that just discards every error message. --- src/formatting.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index a23c312bd2a..2705bda72d1 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -7,7 +7,7 @@ use std::rc::Rc; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::errors::emitter::{ColorConfig, EmitterWriter}; +use syntax::errors::emitter::{ColorConfig, Emitter}; use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; @@ -89,7 +89,7 @@ fn format_project( timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. - let silent_emitter = silent_emitter(source_map); + let silent_emitter = silent_emitter(); parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); @@ -670,18 +670,20 @@ fn parse_crate( Err(ErrorKind::ParseError) } -fn silent_emitter(source_map: Rc) -> Box { - Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(source_map), - false, - false, - )) +/// Emitter which discards every error. +struct SilentEmitter; + +impl Emitter for SilentEmitter { + fn emit(&mut self, _db: &DiagnosticBuilder<'_>) {} +} + +fn silent_emitter() -> Box { + Box::new(SilentEmitter {}) } fn make_parse_sess(source_map: Rc, config: &Config) -> ParseSess { let tty_handler = if config.hide_parse_errors() { - let silent_emitter = silent_emitter(source_map.clone()); + let silent_emitter = silent_emitter(); Handler::with_emitter(true, None, silent_emitter) } else { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); -- cgit 1.4.1-3-g733a5 From abfb381189846923157f5edd5948f2c0f00002eb Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 24 Mar 2019 18:55:11 +0900 Subject: Avoid rewriting pairs mutiple times --- src/pairs.rs | 93 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/pairs.rs b/src/pairs.rs index 421167ad6d7..49a77c102f6 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -34,19 +34,11 @@ pub(crate) fn rewrite_all_pairs( shape: Shape, context: &RewriteContext<'_>, ) -> Option { - // First we try formatting on one line. - if let Some(list) = expr.flatten(false) { - if let Some(r) = rewrite_pairs_one_line(&list, shape, context) { - return Some(r); - } - } - - // We can't format on line, so try many. When we flatten here we make sure - // to only flatten pairs with the same operator, that way we don't - // necessarily need one line per sub-expression, but we don't do anything - // too funny wrt precedence. - expr.flatten(true) - .and_then(|list| rewrite_pairs_multiline(&list, shape, context)) + expr.flatten(context, shape).and_then(|list| { + // First we try formatting on one line. + rewrite_pairs_one_line(&list, shape, context) + .or_else(|| rewrite_pairs_multiline(&list, shape, context)) + }) } // This may return a multi-line result since we allow the last expression to go @@ -61,22 +53,23 @@ fn rewrite_pairs_one_line( let mut result = String::new(); let base_shape = shape.block(); - for (e, s) in list.list.iter().zip(list.separators.iter()) { - let cur_shape = base_shape.offset_left(last_line_width(&result))?; - let rewrite = e.rewrite(context, cur_shape)?; + for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) { + if let Some(rewrite) = rewrite { + if !is_single_line(&rewrite) || result.len() > shape.width { + return None; + } - if !is_single_line(&rewrite) || result.len() > shape.width { + result.push_str(&rewrite); + result.push(' '); + result.push_str(s); + result.push(' '); + } else { return None; } - - result.push_str(&rewrite); - result.push(' '); - result.push_str(s); - result.push(' '); } let prefix_len = result.len(); - let last = list.list.last().unwrap(); + let last = list.list.last()?.0; let cur_shape = base_shape.offset_left(last_line_width(&result))?; let last_rewrite = last.rewrite(context, cur_shape)?; result.push_str(&last_rewrite); @@ -112,10 +105,9 @@ fn rewrite_pairs_multiline( let indent_str = nested_shape.indent.to_string_with_newline(context.config); let mut result = String::new(); - let rewrite = list.list[0].rewrite(context, shape)?; - result.push_str(&rewrite); + result.push_str(&list.list[0].1.as_ref()?); - for (e, s) in list.list[1..].iter().zip(list.separators.iter()) { + for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) { // The following test checks if we should keep two subexprs on the same // line. We do this if not doing so would create an orphan and there is // enough space to do so. @@ -139,24 +131,20 @@ fn rewrite_pairs_multiline( } } - let nested_overhead = s.len() + 1; - let line_shape = match context.config.binop_separator() { + match context.config.binop_separator() { SeparatorPlace::Back => { result.push(' '); result.push_str(s); result.push_str(&indent_str); - nested_shape.sub_width(nested_overhead)? } SeparatorPlace::Front => { result.push_str(&indent_str); result.push_str(s); result.push(' '); - nested_shape.offset_left(nested_overhead)? } - }; + } - let rewrite = e.rewrite(context, line_shape)?; - result.push_str(&rewrite); + result.push_str(&default_rw.as_ref()?); } Some(result) } @@ -250,27 +238,46 @@ where // A pair which forms a tree and can be flattened (e.g., binops). trait FlattenPair: Rewrite + Sized { - // If `_same_op` is `true`, then we only combine binops with the same - // operator into the list. E.g,, if the source is `a * b + c`, if `_same_op` - // is true, we make `[(a * b), c]` if `_same_op` is false, we make - // `[a, b, c]` - fn flatten(&self, _same_op: bool) -> Option> { + fn flatten(&self, _: &RewriteContext<'_>, _: Shape) -> Option> { None } } struct PairList<'a, 'b, T: Rewrite> { - list: Vec<&'b T>, + list: Vec<(&'b T, Option)>, separators: Vec<&'a str>, } impl FlattenPair for ast::Expr { - fn flatten(&self, same_op: bool) -> Option> { + fn flatten( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Option> { let top_op = match self.node { ast::ExprKind::Binary(op, _, _) => op.node, _ => return None, }; + let default_rewrite = |node: &ast::Expr, sep: usize, is_first: bool| { + if is_first { + return node.rewrite(context, shape); + } + let nested_overhead = sep + 1; + let rhs_offset = shape.rhs_overhead(&context.config); + let nested_shape = (match context.config.indent_style() { + IndentStyle::Visual => shape.visual_indent(0), + IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), + }) + .with_max_width(&context.config) + .sub_width(rhs_offset)?; + let default_shape = match context.config.binop_separator() { + SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?, + SeparatorPlace::Front => nested_shape.offset_left(nested_overhead)?, + }; + node.rewrite(context, default_shape) + }; + // Turn a tree of binop expressions into a list using a depth-first, // in-order traversal. let mut stack = vec![]; @@ -279,12 +286,14 @@ impl FlattenPair for ast::Expr { let mut node = self; loop { match node.node { - ast::ExprKind::Binary(op, ref lhs, _) if !same_op || op.node == top_op => { + ast::ExprKind::Binary(op, ref lhs, _) if op.node == top_op => { stack.push(node); node = lhs; } _ => { - list.push(node); + let op_len = separators.last().map_or(0, |s: &&str| s.len()); + let rw = default_rewrite(node, op_len, list.is_empty()); + list.push((node, rw)); if let Some(pop) = stack.pop() { match pop.node { ast::ExprKind::Binary(op, _, ref rhs) => { -- cgit 1.4.1-3-g733a5 From 0d67db47443591db1e678f3d54bd845fbc1e4d6f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 24 Mar 2019 23:36:07 +0900 Subject: Move some code out of create_config --- src/config/config_type.rs | 137 ---------------------------------------------- src/config/mod.rs | 136 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 137 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 4d09eea7c47..14c2dcbb8db 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -93,19 +93,6 @@ macro_rules! create_config { $(pub $i: Option<$ty>),+ } - impl PartialConfig { - pub fn to_toml(&self) -> Result { - // Non-user-facing options can't be specified in TOML - let mut cloned = self.clone(); - cloned.file_lines = None; - cloned.verbose = None; - cloned.width_heuristics = None; - - ::toml::to_string(&cloned) - .map_err(|e| format!("Could not output config: {}", e)) - } - } - // Macro hygiene won't allow us to make `set_$i()` methods on Config // for each item, so this struct is used to give the API to set values: // `config.set().option(false)`. It's pretty ugly. Consider replacing @@ -139,23 +126,6 @@ macro_rules! create_config { } impl Config { - pub(crate) fn version_meets_requirement(&self) -> bool { - if self.was_set().required_version() { - let version = env!("CARGO_PKG_VERSION"); - let required_version = self.required_version(); - if version != required_version { - println!( - "Error: rustfmt version ({}) doesn't match the required version ({})", - version, - required_version, - ); - return false; - } - } - - true - } - $( pub fn $i(&self) -> $ty { self.$i.0.set(true); @@ -213,37 +183,6 @@ macro_rules! create_config { } } - pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { - let parsed: ::toml::Value = - toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?; - let mut err: String = String::new(); - { - let table = parsed - .as_table() - .ok_or(String::from("Parsed config was not table"))?; - for key in table.keys() { - if !Config::is_valid_name(key) { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) - } - } - } - match parsed.try_into() { - Ok(parsed_config) => { - if !err.is_empty() { - eprint!("{}", err); - } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) - } - Err(e) => { - err.push_str("Error: Decoding config file failed:\n"); - err.push_str(format!("{}\n", e).as_str()); - err.push_str("Please check your config file."); - Err(err) - } - } - } - pub fn used_options(&self) -> PartialConfig { PartialConfig { $( @@ -287,82 +226,6 @@ macro_rules! create_config { } } - /// Constructs a `Config` from the toml file specified at `file_path`. - /// - /// This method only looks at the provided path, for a method that - /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. - /// - /// Returns a `Config` if the config could be read and parsed from - /// the file, otherwise errors. - pub(super) fn from_toml_path(file_path: &Path) -> Result { - let mut file = File::open(&file_path)?; - let mut toml = String::new(); - file.read_to_string(&mut toml)?; - Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) - } - - /// Resolves the config for input in `dir`. - /// - /// Searches for `rustfmt.toml` beginning with `dir`, and - /// recursively checking parents of `dir` if no config file is found. - /// If no config file exists in `dir` or in any parent, a - /// default `Config` will be returned (and the returned path will be empty). - /// - /// Returns the `Config` to use, and the path of the project file if there was - /// one. - pub(super) fn from_resolved_toml_path( - dir: &Path, - ) -> Result<(Config, Option), Error> { - /// Try to find a project file in the given directory and its parents. - /// Returns the path of a the nearest project file if one exists, - /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { - let mut current = if dir.is_relative() { - env::current_dir()?.join(dir) - } else { - dir.to_path_buf() - }; - - current = fs::canonicalize(current)?; - - loop { - match get_toml_path(¤t) { - Ok(Some(path)) => return Ok(Some(path)), - Err(e) => return Err(e), - _ => () - } - - // If the current directory has no parent, we're done searching. - if !current.pop() { - break; - } - } - - // If nothing was found, check in the home directory. - if let Some(home_dir) = dirs::home_dir() { - if let Some(path) = get_toml_path(&home_dir)? { - return Ok(Some(path)); - } - } - - // If none was found ther either, check in the user's configuration directory. - if let Some(mut config_dir) = dirs::config_dir() { - config_dir.push("rustfmt"); - if let Some(path) = get_toml_path(&config_dir)? { - return Ok(Some(path)); - } - } - - return Ok(None); - } - - match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), - } - } - pub fn is_hidden_option(name: &str) -> bool { const HIDE_OPTIONS: [&str; 4] = ["verbose", "verbose_diff", "file_lines", "width_heuristics"]; diff --git a/src/config/mod.rs b/src/config/mod.rs index 785d61749a4..0790a3be2a6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -150,6 +150,142 @@ create_config! { make_backup: bool, false, false, "Backup changed files"; } +impl PartialConfig { + pub fn to_toml(&self) -> Result { + // Non-user-facing options can't be specified in TOML + let mut cloned = self.clone(); + cloned.file_lines = None; + cloned.verbose = None; + cloned.width_heuristics = None; + + ::toml::to_string(&cloned).map_err(|e| format!("Could not output config: {}", e)) + } +} + +impl Config { + pub(crate) fn version_meets_requirement(&self) -> bool { + if self.was_set().required_version() { + let version = env!("CARGO_PKG_VERSION"); + let required_version = self.required_version(); + if version != required_version { + println!( + "Error: rustfmt version ({}) doesn't match the required version ({})", + version, required_version, + ); + return false; + } + } + + true + } + + /// Constructs a `Config` from the toml file specified at `file_path`. + /// + /// This method only looks at the provided path, for a method that + /// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`. + /// + /// Returns a `Config` if the config could be read and parsed from + /// the file, otherwise errors. + pub(super) fn from_toml_path(file_path: &Path) -> Result { + let mut file = File::open(&file_path)?; + let mut toml = String::new(); + file.read_to_string(&mut toml)?; + Config::from_toml(&toml, file_path.parent().unwrap()) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + } + + /// Resolves the config for input in `dir`. + /// + /// Searches for `rustfmt.toml` beginning with `dir`, and + /// recursively checking parents of `dir` if no config file is found. + /// If no config file exists in `dir` or in any parent, a + /// default `Config` will be returned (and the returned path will be empty). + /// + /// Returns the `Config` to use, and the path of the project file if there was + /// one. + pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + /// Try to find a project file in the given directory and its parents. + /// Returns the path of a the nearest project file if one exists, + /// or `None` if no project file was found. + fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => (), + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + break; + } + } + + // If nothing was found, check in the home directory. + if let Some(home_dir) = dirs::home_dir() { + if let Some(path) = get_toml_path(&home_dir)? { + return Ok(Some(path)); + } + } + + // If none was found ther either, check in the user's configuration directory. + if let Some(mut config_dir) = dirs::config_dir() { + config_dir.push("rustfmt"); + if let Some(path) = get_toml_path(&config_dir)? { + return Ok(Some(path)); + } + } + + return Ok(None); + } + + match resolve_project_file(dir)? { + None => Ok((Config::default(), None)), + Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + } + } + + pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + let parsed: ::toml::Value = toml + .parse() + .map_err(|e| format!("Could not parse TOML: {}", e))?; + let mut err: String = String::new(); + { + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for key in table.keys() { + if !Config::is_valid_name(key) { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) + } + } + } + match parsed.try_into() { + Ok(parsed_config) => { + if !err.is_empty() { + eprint!("{}", err); + } + Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) + } + Err(e) => { + err.push_str("Error: Decoding config file failed:\n"); + err.push_str(format!("{}\n", e).as_str()); + err.push_str("Please check your config file."); + Err(err) + } + } + } +} + /// Loads a config by checking the client-supplied options and if appropriate, the /// file system (including searching the file system for overrides). pub fn load_config( -- cgit 1.4.1-3-g733a5 From 5f1f5aac0564e80700785abea20e8255837e6d48 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 25 Mar 2019 07:54:31 +0900 Subject: Make sure that we run rustfmt against every edition --- src/cargo-fmt/main.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index e887b940fce..25ce43d47e2 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -311,8 +311,7 @@ fn run_rustfmt( fmt_args: &[String], verbosity: Verbosity, ) -> Result { - let default_edition = String::from("2015"); - let mut by_edition = targets + let by_edition = targets .iter() .inspect(|t| { if verbosity == Verbosity::Verbose { @@ -324,10 +323,8 @@ fn run_rustfmt( h.entry(t.0).or_insert_with(Vec::new).push(t.1); h }); - if by_edition.is_empty() { - by_edition.insert(&default_edition, Vec::new()); - } + let mut status = vec![]; for (edition, files) in by_edition { let stdout = if verbosity == Verbosity::Quiet { std::process::Stdio::null() @@ -357,13 +354,14 @@ fn run_rustfmt( _ => e, })?; - let status = command.wait()?; - if !status.success() { - return Ok(status.code().unwrap_or(FAILURE)); - } + status.push(command.wait()?); } - Ok(SUCCESS) + Ok(status + .iter() + .filter_map(|s| if s.success() { None } else { s.code() }) + .next() + .unwrap_or(SUCCESS)) } fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { -- cgit 1.4.1-3-g733a5 From b4d4b5795ef9229f24f838592c4c915a7f4086bc Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 25 Mar 2019 07:54:52 +0900 Subject: Use BTreeMap to guarantee consistent ordering --- src/cargo-fmt/main.rs | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 25ce43d47e2..a686e91b694 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -6,7 +6,8 @@ use cargo_metadata; use getopts; -use std::collections::{HashMap, HashSet}; +use std::cmp::Ordering; +use std::collections::{BTreeMap, BTreeSet}; use std::env; use std::fs; use std::hash::{Hash, Hasher}; @@ -122,7 +123,7 @@ fn handle_command_status(status: Result, opts: &getopts::Options } fn get_version(verbosity: Verbosity) -> Result { - run_rustfmt(&HashSet::new(), &[String::from("--version")], verbosity) + run_rustfmt(&BTreeSet::new(), &[String::from("--version")], verbosity) } fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result { @@ -131,7 +132,7 @@ fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result Option { + Some(self.path.cmp(&other.path)) + } +} + +impl Ord for Target { + fn cmp(&self, other: &Target) -> Ordering { + self.path.cmp(&other.path) + } +} + impl Eq for Target {} impl Hash for Target { @@ -204,12 +217,12 @@ impl CargoFmtStrategy { } /// Based on the specified `CargoFmtStrategy`, returns a set of main source files. -fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { - let mut targets = HashSet::new(); +fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { + let mut targets = BTreeSet::new(); match *strategy { CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, - CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?, + CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut BTreeSet::new())?, CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, } @@ -223,7 +236,7 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error } } -fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> { +fn get_targets_root_only(targets: &mut BTreeSet) -> Result<(), io::Error> { let metadata = get_cargo_metadata(None)?; let current_dir = env::current_dir()?.canonicalize()?; let current_dir_manifest = current_dir.join("Cargo.toml"); @@ -243,8 +256,8 @@ fn get_targets_root_only(targets: &mut HashSet) -> Result<(), io::Error> fn get_targets_recursive( manifest_path: Option<&Path>, - mut targets: &mut HashSet, - visited: &mut HashSet, + mut targets: &mut BTreeSet, + visited: &mut BTreeSet, ) -> Result<(), io::Error> { let metadata = get_cargo_metadata(manifest_path)?; @@ -275,11 +288,11 @@ fn get_targets_recursive( fn get_targets_with_hitlist( hitlist: &[String], - targets: &mut HashSet, + targets: &mut BTreeSet, ) -> Result<(), io::Error> { let metadata = get_cargo_metadata(None)?; - let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist); + let mut workspace_hitlist: BTreeSet<&String> = BTreeSet::from_iter(hitlist); for package in metadata.packages { if workspace_hitlist.remove(&package.name) { @@ -300,14 +313,14 @@ fn get_targets_with_hitlist( } } -fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet) { +fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut BTreeSet) { for target in target_paths { targets.insert(Target::from_target(target)); } } fn run_rustfmt( - targets: &HashSet, + targets: &BTreeSet, fmt_args: &[String], verbosity: Verbosity, ) -> Result { @@ -318,9 +331,8 @@ fn run_rustfmt( println!("[{} ({})] {:?}", t.kind, t.edition, t.path) } }) - .map(|t| (&t.edition, &t.path)) - .fold(HashMap::new(), |mut h, t| { - h.entry(t.0).or_insert_with(Vec::new).push(t.1); + .fold(BTreeMap::new(), |mut h, t| { + h.entry(&t.edition).or_insert_with(Vec::new).push(&t.path); h }); -- cgit 1.4.1-3-g733a5 From 17ca7408f392781250086ced3e4b6d6d3d517850 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 25 Mar 2019 11:20:14 +0900 Subject: Do not add a space after empty impl --- src/types.rs | 10 +++++++--- tests/source/type.rs | 4 ++++ tests/target/type.rs | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index e6a16b38ce8..81cfc20961d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -667,9 +667,13 @@ impl Rewrite for ast::Ty { rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(_, ref it) => it - .rewrite(context, shape) - .map(|it_str| format!("impl {}", it_str)), + ast::TyKind::ImplTrait(_, ref it) => { + // Empty trait is not a parser error. + it.rewrite(context, shape).map(|it_str| { + let space = if it_str.is_empty() { "" } else { " " }; + format!("impl{}{}", space, it_str) + }) + } ast::TyKind::CVarArgs => Some("...".to_owned()), ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), } diff --git a/tests/source/type.rs b/tests/source/type.rs index 55eb05442d6..27387c5bdca 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -83,6 +83,10 @@ impl Future + 'a, 'c { } +// #3051 +token![impl]; +token![ impl ]; + // #3060 macro_rules! foo { ($foo_api: ty) => { diff --git a/tests/target/type.rs b/tests/target/type.rs index 2afcc652c44..575bd3573bc 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -82,6 +82,10 @@ pub fn do_something<'a, T: Trait1 + Trait2 + 'a>( > + 'a + 'b + 'c { } +// #3051 +token![impl]; +token![impl]; + // #3060 macro_rules! foo { ($foo_api: ty) => { -- cgit 1.4.1-3-g733a5 From b473e652570b294237cae795fb2b673366f1a86d Mon Sep 17 00:00:00 2001 From: Devin Alvaro Date: Tue, 26 Mar 2019 06:47:18 +0700 Subject: Add `--print-config current` --- src/bin/main.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index dc1e64a27bb..551b422e06c 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -55,6 +55,10 @@ enum Operation { ConfigOutputDefault { path: Option, }, + /// Output current config (as if formatting to a file) to stdout + ConfigOutputCurrent { + path: Option, + }, /// No file specified, read from stdin Stdin { input: String, @@ -103,8 +107,9 @@ fn make_opts() -> Options { "", "print-config", "Dumps a default or minimal config to PATH. A minimal config is the \ - subset of the current config file used for formatting the current program.", - "[minimal|default] PATH", + subset of the current config file used for formatting the current program. \ + `current` writes to stdout current config as if formatting the file at PATH.", + "[default|minimal|current] PATH", ); if is_nightly { @@ -182,6 +187,21 @@ fn execute(opts: &Options) -> Result { } Ok(0) } + Operation::ConfigOutputCurrent { path } => { + let path = match path { + Some(path) => path, + None => return Err(format_err!("PATH required for `--print-config current`")), + }; + + let file = PathBuf::from(path); + let file = file.canonicalize().unwrap_or(file); + + let (config, _) = load_config(Some(file.parent().unwrap()), Some(options.clone()))?; + let toml = config.all_options().to_toml().map_err(err_msg)?; + io::stdout().write_all(toml.as_bytes())?; + + Ok(0) + } Operation::Stdin { input } => format_string(input, options), Operation::Format { files, @@ -379,6 +399,8 @@ fn determine_operation(matches: &Matches) -> Result { let path = matches.free.get(0).cloned(); if kind == "default" { return Ok(Operation::ConfigOutputDefault { path }); + } else if kind == "current" { + return Ok(Operation::ConfigOutputCurrent { path }); } else if kind == "minimal" { minimal_config_path = path; if minimal_config_path.is_none() { -- cgit 1.4.1-3-g733a5 From 968d30f5d8c5c2616b7f8e926a89a57f619164b9 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 26 Mar 2019 23:35:07 +0900 Subject: Run tests in a thread with larger stack size --- src/test/mod.rs | 67 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 0628094fdef..fc25d27b531 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -7,6 +7,7 @@ use std::mem; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str::Chars; +use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; use crate::formatting::{ReportedErrors, SourceFile}; @@ -25,6 +26,32 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ "issue-3434/no_entry.rs", ]; +struct TestSetting { + /// The size of the stack of the thread that run tests. + stack_size: usize, +} + +impl Default for TestSetting { + fn default() -> Self { + TestSetting { + stack_size: 8388608, // 8MB + } + } +} + +fn run_test_with(test_setting: &TestSetting, f: F) +where + F: FnOnce(), + F: Send + 'static, +{ + thread::Builder::new() + .stack_size(test_setting.stack_size) + .spawn(f) + .expect("Failed to create a test thread") + .join() + .expect("Failed to join a test thread") +} + fn is_file_skip(path: &Path) -> bool { SKIP_FILE_WHITE_LIST .iter() @@ -114,13 +141,15 @@ fn write_message(msg: &str) { // exactly. #[test] fn system_tests() { - // Get all files in the tests/source directory. - let files = get_test_files(Path::new("tests/source"), true); - let (_reports, count, fails) = check_files(files, &None); - - // Display results. - println!("Ran {} system tests.", count); - assert_eq!(fails, 0, "{} system tests failed", fails); + run_test_with(&TestSetting::default(), || { + // Get all files in the tests/source directory. + let files = get_test_files(Path::new("tests/source"), true); + let (_reports, count, fails) = check_files(files, &None); + + // Display results. + println!("Ran {} system tests.", count); + assert_eq!(fails, 0, "{} system tests failed", fails); + }); } // Do the same for tests/coverage-source directory. @@ -228,17 +257,19 @@ fn assert_output(source: &Path, expected_filename: &Path) { // rustfmt. #[test] fn idempotence_tests() { - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - _ => return, // these tests require nightly - } - // Get all files in the tests/target directory. - let files = get_test_files(Path::new("tests/target"), true); - let (_reports, count, fails) = check_files(files, &None); - - // Display results. - println!("Ran {} idempotent tests.", count); - assert_eq!(fails, 0, "{} idempotent tests failed", fails); + run_test_with(&TestSetting::default(), || { + match option_env!("CFG_RELEASE_CHANNEL") { + None | Some("nightly") => {} + _ => return, // these tests require nightly + } + // Get all files in the tests/target directory. + let files = get_test_files(Path::new("tests/target"), true); + let (_reports, count, fails) = check_files(files, &None); + + // Display results. + println!("Ran {} idempotent tests.", count); + assert_eq!(fails, 0, "{} idempotent tests failed", fails); + }); } // Run rustfmt on itself. This operation must be idempotent. We also check that -- cgit 1.4.1-3-g733a5 From e3a4a036574da637367a7f99e6de0edc1b93c764 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 16:52:29 +0900 Subject: Use str::repeat --- src/config/config_type.rs | 5 +---- src/macros.rs | 13 ++++--------- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 14c2dcbb8db..7c4298dcf1c 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -236,10 +236,7 @@ macro_rules! create_config { use std::cmp; let max = 0; $( let max = cmp::max(max, stringify!($i).len()+1); )+ - let mut space_str = String::with_capacity(max); - for _ in 0..max { - space_str.push(' '); - } + let space_str = " ".repeat(max); writeln!(out, "Configuration Options:").unwrap(); $( if $stb || include_unstable { diff --git a/src/macros.rs b/src/macros.rs index 18df24b45c8..088b3e4490f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -540,17 +540,12 @@ fn register_metavariable( name: &str, dollar_count: usize, ) { - let mut new_name = String::new(); - let mut old_name = String::new(); + let mut new_name = "$".repeat(dollar_count - 1); + let mut old_name = "$".repeat(dollar_count); - old_name.push('$'); - for _ in 0..(dollar_count - 1) { - new_name.push('$'); - old_name.push('$'); - } new_name.push('z'); - new_name.push_str(&name); - old_name.push_str(&name); + new_name.push_str(name); + old_name.push_str(name); result.push_str(&new_name); map.insert(old_name, new_name); -- cgit 1.4.1-3-g733a5 From a2d9b6d1b11ba318d309a9c5512b3b7974091ccb Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 16:59:50 +0900 Subject: Remove redundant scopes --- src/config/file_lines.rs | 22 ++++++++++------------ src/config/mod.rs | 18 ++++++++---------- src/formatting.rs | 6 +----- 3 files changed, 19 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index c085a0b5deb..67d2355c938 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -156,20 +156,18 @@ fn normalize_ranges(ranges: &mut HashMap>) { for ranges in ranges.values_mut() { ranges.sort(); let mut result = vec![]; - { - let mut iter = ranges.iter_mut().peekable(); - while let Some(next) = iter.next() { - let mut next = *next; - while let Some(&&mut peek) = iter.peek() { - if let Some(merged) = next.merge(peek) { - iter.next().unwrap(); - next = merged; - } else { - break; - } + let mut iter = ranges.iter_mut().peekable(); + while let Some(next) = iter.next() { + let mut next = *next; + while let Some(&&mut peek) = iter.peek() { + if let Some(merged) = next.merge(peek) { + iter.next().unwrap(); + next = merged; + } else { + break; } - result.push(next) } + result.push(next) } *ranges = result; } diff --git a/src/config/mod.rs b/src/config/mod.rs index 0790a3be2a6..4a4647a5663 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -257,16 +257,14 @@ impl Config { let parsed: ::toml::Value = toml .parse() .map_err(|e| format!("Could not parse TOML: {}", e))?; - let mut err: String = String::new(); - { - let table = parsed - .as_table() - .ok_or(String::from("Parsed config was not table"))?; - for key in table.keys() { - if !Config::is_valid_name(key) { - let msg = &format!("Warning: Unknown configuration option `{}`\n", key); - err.push_str(msg) - } + let mut err = String::new(); + let table = parsed + .as_table() + .ok_or(String::from("Parsed config was not table"))?; + for key in table.keys() { + if !Config::is_valid_name(key) { + let msg = &format!("Warning: Unknown configuration option `{}`\n", key); + err.push_str(msg) } } match parsed.try_into() { diff --git a/src/formatting.rs b/src/formatting.rs index b14a7b798c7..ccf60b242be 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -48,11 +48,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { let format_result = format_project(input, config, self); format_result.map(|report| { - { - let new_errors = &report.internal.borrow().1; - - self.errors.add(new_errors); - } + self.errors.add(&report.internal.borrow().1); report }) }) -- cgit 1.4.1-3-g733a5 From 6e288fdae02c3794b4626bc66c79c5b221d2f117 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 17:27:56 +0900 Subject: Remove a write of empty string --- src/imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index a87d100ca9b..aa2459f7f86 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -225,7 +225,7 @@ impl fmt::Display for UseTree { write!(f, "::")?; } } - write!(f, "") + Ok(()) } } -- cgit 1.4.1-3-g733a5 From 8e4c20da80eb31b57abcb695d76cc8720c95e395 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 17:30:39 +0900 Subject: Write seperator beforehand --- src/imports.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index aa2459f7f86..b0ead7a87b9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -205,11 +205,10 @@ impl fmt::Display for UseSegment { UseSegment::List(ref list) => { write!(f, "{{")?; for (i, item) in list.iter().enumerate() { - let is_last = i == list.len() - 1; - write!(f, "{}", item)?; - if !is_last { + if i != 0 { write!(f, ", ")?; } + write!(f, "{}", item)?; } write!(f, "}}") } @@ -219,11 +218,10 @@ impl fmt::Display for UseSegment { impl fmt::Display for UseTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for (i, segment) in self.path.iter().enumerate() { - let is_last = i == self.path.len() - 1; - write!(f, "{}", segment)?; - if !is_last { + if i != 0 { write!(f, "::")?; } + write!(f, "{}", segment)?; } Ok(()) } -- cgit 1.4.1-3-g733a5 From ff0683d66690cef6348226bf1e84c693ad6f6006 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 17:54:29 +0900 Subject: Simplify iterators --- src/chains.rs | 2 +- src/expr.rs | 4 ++-- src/lists.rs | 9 ++------- src/overflow.rs | 13 +++++++++---- src/vertical.rs | 14 ++++++++------ 5 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 3d928623aac..832cae898ef 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -550,7 +550,7 @@ impl<'a> ChainFormatterShared<'a> { let almost_total = if extendable { prev_last_line_width } else { - self.rewrites.iter().fold(0, |a, b| a + b.len()) + self.rewrites.iter().map(|a| a.len()).sum() } + last.tries; let one_line_budget = if self.child_count == 1 { shape.width diff --git a/src/expr.rs b/src/expr.rs index 90cbba334f1..11a7767d37c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::cmp::min; +use itertools::Itertools; use syntax::parse::token::DelimToken; use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::{ast, ptr}; @@ -1246,8 +1247,7 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> if !context.config.format_strings() { if string_lit .lines() - .rev() - .skip(1) + .dropping_back(1) .all(|line| line.ends_with('\\')) { let new_indent = shape.visual_indent(1).indent; diff --git a/src/lists.rs b/src/lists.rs index 14b799622c9..63cabc3c354 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -577,13 +577,8 @@ pub fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommen let has_block_comment = trimmed_pre_snippet.ends_with("*/"); let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); if has_block_comment { - let comment_end = pre_snippet.chars().rev().position(|c| c == '/').unwrap(); - if pre_snippet - .chars() - .rev() - .take(comment_end + 1) - .any(|c| c == '\n') - { + let comment_end = pre_snippet.rfind(|c| c == '/').unwrap(); + if pre_snippet[comment_end..].contains('\n') { ( Some(trimmed_pre_snippet.to_owned()), ListItemCommentStyle::DifferentLine, diff --git a/src/overflow.rs b/src/overflow.rs index ac425b591aa..17e04b2e7a4 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -2,6 +2,7 @@ use std::cmp::min; +use itertools::Itertools; use syntax::parse::token::DelimToken; use syntax::source_map::Span; use syntax::{ast, ptr}; @@ -711,10 +712,14 @@ fn last_item_shape( if items.len() == 1 && !lists.get(0)?.is_nested_call() { return Some(shape); } - let offset = items.iter().rev().skip(1).fold(0, |acc, i| { - // 2 = ", " - acc + 2 + i.inner_as_ref().len() - }); + let offset = items + .iter() + .dropping_back(1) + .map(|i| { + // 2 = ", " + 2 + i.inner_as_ref().len() + }) + .sum(); Shape { width: min(args_max_width, shape.width), ..shape diff --git a/src/vertical.rs b/src/vertical.rs index 9dca1d600f3..a7977a64e6c 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -2,6 +2,7 @@ use std::cmp; +use itertools::Itertools; use syntax::ast; use syntax::source_map::{BytePos, Span}; @@ -190,11 +191,8 @@ fn struct_field_prefix_max_min_width( } }) }) - .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) { - (Some((max_len, min_len)), Some(len)) => { - Some((cmp::max(max_len, len), cmp::min(min_len, len))) - } - _ => None, + .fold_options((0, ::std::usize::MAX), |(max_len, min_len), len| { + (cmp::max(max_len, len), cmp::min(min_len, len)) }) .unwrap_or((0, 0)) } @@ -274,7 +272,11 @@ fn group_aligned_items( .skip(1) .collect::>() .join("\n"); - let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) { + let spacings = if snippet + .lines() + .dropping_back(1) + .any(|l| l.trim().is_empty()) + { "\n" } else { "" -- cgit 1.4.1-3-g733a5 From 9fda93777965f0023d055c947e8f2dc301dbc62f Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 19:17:50 +0900 Subject: Remove redundant & --- src/comment.rs | 4 ++-- src/expr.rs | 2 +- src/items.rs | 8 ++++---- src/test/mod.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 83ec810381e..87c6b65865b 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -591,7 +591,7 @@ impl<'a> CommentRewrite<'a> { ) { Some(s) => self.result.push_str(&Self::join_block( &s, - &format!("{}{}", &self.comment_line_separator, ib.line_start), + &format!("{}{}", self.comment_line_separator, ib.line_start), )), None => self.result.push_str(&Self::join_block( &ib.original_block_as_string(), @@ -634,7 +634,7 @@ impl<'a> CommentRewrite<'a> { ) { Some(s) => self.result.push_str(&Self::join_block( &s, - &format!("{}{}", &self.comment_line_separator, ib.line_start), + &format!("{}{}", self.comment_line_separator, ib.line_start), )), None => self.result.push_str(&Self::join_block( &ib.original_block_as_string(), diff --git a/src/expr.rs b/src/expr.rs index 11a7767d37c..8d241dff1f9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1459,7 +1459,7 @@ fn rewrite_paren( let subexpr_str = subexpr.rewrite(context, sub_shape)?; let fits_single_line = !pre_comment.contains("//") && !post_comment.contains("//"); if fits_single_line { - Some(format!("({}{}{})", pre_comment, &subexpr_str, post_comment)) + Some(format!("({}{}{})", pre_comment, subexpr_str, post_comment)) } else { rewrite_paren_in_multi_line(context, subexpr, shape, pre_span, post_span) } diff --git a/src/items.rs b/src/items.rs index 8cd6010f72f..1647ecfcc3b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -730,7 +730,7 @@ pub fn format_impl( if generics.where_clause.predicates.len() == 1 { result.push_str(","); } - result.push_str(&format!("{}{{{}}}", &sep, &sep)); + result.push_str(&format!("{}{{{}}}", sep, sep)); } else { result.push_str(" {}"); } @@ -912,7 +912,7 @@ fn rewrite_trait_ref( let shape = Shape::indented(offset + used_space, context.config); if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) { if !trait_ref_str.contains('\n') { - return Some(format!(" {}{}", polarity_str, &trait_ref_str)); + return Some(format!(" {}{}", polarity_str, trait_ref_str)); } } // We could not make enough space for trait_ref, so put it on new line. @@ -921,9 +921,9 @@ fn rewrite_trait_ref( let trait_ref_str = trait_ref.rewrite(context, shape)?; Some(format!( "{}{}{}", - &offset.to_string_with_newline(context.config), + offset.to_string_with_newline(context.config), polarity_str, - &trait_ref_str + trait_ref_str )) } diff --git a/src/test/mod.rs b/src/test/mod.rs index fc25d27b531..dc297a52dfb 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -609,11 +609,11 @@ fn handle_result( for (file_name, fmt_text) in result { // If file is in tests/source, compare to file with same name in tests/target. let target = get_target(&file_name, target); - let open_error = format!("couldn't open target {:?}", &target); + let open_error = format!("couldn't open target {:?}", target); let mut f = fs::File::open(&target).expect(&open_error); let mut text = String::new(); - let read_error = format!("failed reading target {:?}", &target); + let read_error = format!("failed reading target {:?}", target); f.read_to_string(&mut text).expect(&read_error); // Ignore LF and CRLF difference for Windows. -- cgit 1.4.1-3-g733a5 From c0ff894a22511eead2f521b5321f040cca8b1d5b Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 29 Mar 2019 20:12:45 +0900 Subject: Fix indexing panic on unicode whitespaces --- src/lists.rs | 9 +++++++-- tests/source/issue-2995.rs | 7 +++++++ tests/target/issue-2995.rs | 7 +++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-2995.rs create mode 100644 tests/target/issue-2995.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 14b799622c9..c75206b5ce6 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -651,7 +651,7 @@ pub fn get_comment_end( if let Some(i) = block_open_index { match post_snippet.find('/') { Some(j) if j < i => block_open_index = None, - _ if i > 0 && &post_snippet[i - 1..i] == "/" => block_open_index = None, + _ if post_snippet[..i].chars().last() == Some('/') => block_open_index = None, _ => (), } } @@ -692,8 +692,13 @@ pub fn has_extra_newline(post_snippet: &str, comment_end: usize) -> bool { return false; } + let len_last = post_snippet[..comment_end] + .chars() + .last() + .unwrap() + .len_utf8(); // Everything from the separator to the next item. - let test_snippet = &post_snippet[comment_end - 1..]; + let test_snippet = &post_snippet[comment_end - len_last..]; let first_newline = test_snippet .find('\n') .unwrap_or_else(|| test_snippet.len()); diff --git a/tests/source/issue-2995.rs b/tests/source/issue-2995.rs new file mode 100644 index 00000000000..accf7c3a1ad --- /dev/null +++ b/tests/source/issue-2995.rs @@ -0,0 +1,7 @@ +fn issue_2995() { + // '\u{2028}' is inserted in the code below. + + [0, 
1]; + [0, 
/* */ 1]; + 
[
0
,
1
]
; +} diff --git a/tests/target/issue-2995.rs b/tests/target/issue-2995.rs new file mode 100644 index 00000000000..890da8def92 --- /dev/null +++ b/tests/target/issue-2995.rs @@ -0,0 +1,7 @@ +fn issue_2995() { + // '\u{2028}' is inserted in the code below. + + [0, 1]; + [0, /* */ 1]; + [0, 1]; +} -- cgit 1.4.1-3-g733a5 From 919bee89909d93972b6c8da333b58ed03d9b3591 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sat, 30 Mar 2019 18:37:37 +0100 Subject: Enable overflow_delimited_expr for structs This fixes https://github.com/rust-lang/rustfmt/issues/3482. --- src/expr.rs | 1 + tests/source/match_overflow_expr.rs | 53 +++++++++++++++++++++++++++++++++++++ tests/target/match_overflow_expr.rs | 50 ++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 tests/source/match_overflow_expr.rs create mode 100644 tests/target/match_overflow_expr.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8d241dff1f9..f383eaca36f 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1346,6 +1346,7 @@ pub fn can_be_overflowed_expr( ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) + || context.config.overflow_delimited_expr() } ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) diff --git a/tests/source/match_overflow_expr.rs b/tests/source/match_overflow_expr.rs new file mode 100644 index 00000000000..91275a89429 --- /dev/null +++ b/tests/source/match_overflow_expr.rs @@ -0,0 +1,53 @@ +// rustfmt-overflow_delimited_expr: true + +fn main() { + println!( + "Foobar: {}", + match "input" { + "a" => "", + "b" => "", + "c" => "", + "d" => "", + "e" => "", + "f" => "", + "g" => "", + "h" => "", + "i" => "", + "j" => "", + "k" => "", + "l" => "", + "m" => "", + "n" => "", + "o" => "", + "p" => "", + "q" => "", + "r" => "Rust", + } + ); +} + +fn main() { + println!( + "Very Long Input String Which Makes It Impossible To Fit On The Same Line: {}", + match "input" { + "a" => "", + "b" => "", + "c" => "", + "d" => "", + "e" => "", + "f" => "", + "g" => "", + "h" => "", + "i" => "", + "j" => "", + "k" => "", + "l" => "", + "m" => "", + "n" => "", + "o" => "", + "p" => "", + "q" => "", + "r" => "Rust", + } + ); +} diff --git a/tests/target/match_overflow_expr.rs b/tests/target/match_overflow_expr.rs new file mode 100644 index 00000000000..b817879d1f4 --- /dev/null +++ b/tests/target/match_overflow_expr.rs @@ -0,0 +1,50 @@ +// rustfmt-overflow_delimited_expr: true + +fn main() { + println!("Foobar: {}", match "input" { + "a" => "", + "b" => "", + "c" => "", + "d" => "", + "e" => "", + "f" => "", + "g" => "", + "h" => "", + "i" => "", + "j" => "", + "k" => "", + "l" => "", + "m" => "", + "n" => "", + "o" => "", + "p" => "", + "q" => "", + "r" => "Rust", + }); +} + +fn main() { + println!( + "Very Long Input String Which Makes It Impossible To Fit On The Same Line: {}", + match "input" { + "a" => "", + "b" => "", + "c" => "", + "d" => "", + "e" => "", + "f" => "", + "g" => "", + "h" => "", + "i" => "", + "j" => "", + "k" => "", + "l" => "", + "m" => "", + "n" => "", + "o" => "", + "p" => "", + "q" => "", + "r" => "Rust", + } + ); +} -- cgit 1.4.1-3-g733a5 From 8e068510a4a7e0bf7ae1c4e641f8a790842f6f17 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 3 Apr 2019 11:16:54 +0200 Subject: keep comment appearing between parameter's name and its type (#3491) --- src/expr.rs | 2 +- src/items.rs | 55 ++++++++++++++++++++++++++++++++++++---------- src/types.rs | 5 +---- src/utils.rs | 4 +++- tests/target/issue-2976.rs | 3 +++ 5 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 tests/target/issue-2976.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index f383eaca36f..1dbcf73618a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1691,7 +1691,7 @@ pub fn wrap_struct_field( } pub fn struct_lit_field_separator(config: &Config) -> &str { - colon_spaces(config.space_before_colon(), config.space_after_colon()) + colon_spaces(config) } pub fn rewrite_field( diff --git a/src/items.rs b/src/items.rs index 1647ecfcc3b..c907d34b47c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -36,7 +36,7 @@ const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned { }; fn type_annotation_separator(config: &Config) -> &str { - colon_spaces(config.space_before_colon(), config.space_after_colon()) + colon_spaces(config) } // Statements of the form @@ -1695,10 +1695,7 @@ fn rewrite_static( static_parts: &StaticParts<'_>, offset: Indent, ) -> Option { - let colon = colon_spaces( - context.config.space_before_colon(), - context.config.space_after_colon(), - ); + let colon = colon_spaces(context.config); let mut prefix = format!( "{}{}{} {}{}{}", format_visibility(context, static_parts.vis), @@ -1828,6 +1825,42 @@ fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool { } } +/// Recover any missing comments between the argument and the type. +/// +/// # Returns +/// +/// A 2-len tuple with the comment before the colon in first position, and the comment after the +/// colon in second position. +fn get_missing_arg_comments( + context: &RewriteContext<'_>, + pat_span: Span, + ty_span: Span, + shape: Shape, +) -> (String, String) { + let missing_comment_span = mk_sp(pat_span.hi(), ty_span.lo()); + + let span_before_colon = { + let missing_comment_span_hi = context + .snippet_provider + .span_before(missing_comment_span, ":"); + mk_sp(pat_span.hi(), missing_comment_span_hi) + }; + let span_after_colon = { + let missing_comment_span_lo = context + .snippet_provider + .span_after(missing_comment_span, ":"); + mk_sp(missing_comment_span_lo, ty_span.lo()) + }; + + let comment_before_colon = rewrite_missing_comment(span_before_colon, shape, context) + .filter(|comment| !comment.is_empty()) + .map_or(String::new(), |comment| format!(" {}", comment)); + let comment_after_colon = rewrite_missing_comment(span_after_colon, shape, context) + .filter(|comment| !comment.is_empty()) + .map_or(String::new(), |comment| format!("{} ", comment)); + (comment_before_colon, comment_after_colon) +} + impl Rewrite for ast::Arg { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if let Some(ref explicit_self) = self.to_self() { @@ -1838,13 +1871,11 @@ impl Rewrite for ast::Arg { .rewrite(context, Shape::legacy(shape.width, shape.indent))?; if !is_empty_infer(&*self.ty, self.pat.span) { - if context.config.space_before_colon() { - result.push_str(" "); - } - result.push_str(":"); - if context.config.space_after_colon() { - result.push_str(" "); - } + let (before_comment, after_comment) = + get_missing_arg_comments(context, self.pat.span, self.ty.span, shape); + result.push_str(&before_comment); + result.push_str(colon_spaces(context.config)); + result.push_str(&after_comment); let overhead = last_line_width(&result); let max_width = shape.width.checked_sub(overhead)?; let ty_str = self diff --git a/src/types.rs b/src/types.rs index 81cfc20961d..8ed73b99913 100644 --- a/src/types.rs +++ b/src/types.rs @@ -378,10 +378,7 @@ where } fn type_bound_colon(context: &RewriteContext<'_>) -> &'static str { - colon_spaces( - context.config.space_before_colon(), - context.config.space_after_colon(), - ) + colon_spaces(context.config) } impl Rewrite for ast::WherePredicate { diff --git a/src/utils.rs b/src/utils.rs index 743a8627612..a1ab5fd5aad 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -376,7 +376,9 @@ fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { } #[inline] -pub fn colon_spaces(before: bool, after: bool) -> &'static str { +pub fn colon_spaces(config: &Config) -> &'static str { + let before = config.space_before_colon(); + let after = config.space_after_colon(); match (before, after) { (true, true) => " : ", (true, false) => " :", diff --git a/tests/target/issue-2976.rs b/tests/target/issue-2976.rs new file mode 100644 index 00000000000..51c94a84ba2 --- /dev/null +++ b/tests/target/issue-2976.rs @@ -0,0 +1,3 @@ +fn a(_ /*comment*/: u8 /* toto */) {} +fn b(/*comment*/ _: u8 /* tata */) {} +fn c(_: /*comment*/ u8) {} -- cgit 1.4.1-3-g733a5 From bf383c4610adbe2da38190185bcb7544410f2fce Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 5 Apr 2019 17:11:11 +0200 Subject: keep missed comments appearing after the struct/enum ident --- src/comment.rs | 5 ++++ src/items.rs | 69 +++++++++++++++++++++++++++++--------------- src/missed_spans.rs | 4 +-- tests/target/issue-1096.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 25 deletions(-) create mode 100644 tests/target/issue-1096.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 87c6b65865b..a811d4a26ed 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -142,6 +142,11 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> { } } +/// Returns true if the last line of the passed string finishes with a block-comment. +pub fn is_last_comment_block(s: &str) -> bool { + s.trim_end().ends_with("*/") +} + /// Combine `prev_str` and `next_str` into a single `String`. `span` may contain /// comments between two strings. If there are such comments, then that will be /// recovered. If `allow_extend` is true and there is no comment between the two diff --git a/src/items.rs b/src/items.rs index c907d34b47c..57bded72604 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,8 +10,9 @@ use syntax::visit; use syntax::{ast, ptr, symbol}; use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, recover_comment_removed, - recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented, + combine_strs_with_missing_comments, contains_comment, is_last_comment_block, + recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, + FindUncommented, }; use crate::config::lists::*; use crate::config::{BraceStyle, Config, Density, IndentStyle, Version}; @@ -1173,11 +1174,7 @@ fn format_unit_struct( ) -> Option { let header_str = format_header(context, p.prefix, p.ident, p.vis); let generics_str = if let Some(generics) = p.generics { - let hi = if generics.where_clause.predicates.is_empty() { - generics.span.hi() - } else { - generics.where_clause.span.hi() - }; + let hi = context.snippet_provider.span_before(p.span, ";"); format_generics( context, generics, @@ -2711,19 +2708,19 @@ fn format_generics( let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); let mut result = rewrite_generics(context, "", generics, shape)?; - let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') { + // If the generics are not parameterized then generics.span.hi() == 0, + // so we use span.lo(), which is the position after `struct Foo`. + let span_end_before_where = if !generics.params.is_empty() { + generics.span.hi() + } else { + span.lo() + }; + let (same_line_brace, missed_comments) = if !generics.where_clause.predicates.is_empty() { let budget = context.budget(last_line_used_width(&result, offset.width())); let mut option = WhereClauseOption::snuggled(&result); if brace_pos == BracePos::None { option.suppress_comma = true; } - // If the generics are not parameterized then generics.span.hi() == 0, - // so we use span.lo(), which is the position after `struct Foo`. - let span_end_before_where = if !generics.params.is_empty() { - generics.span.hi() - } else { - span.lo() - }; let where_clause_str = rewrite_where_clause( context, &generics.where_clause, @@ -2737,15 +2734,41 @@ fn format_generics( false, )?; result.push_str(&where_clause_str); - brace_pos == BracePos::ForceSameLine - || brace_style == BraceStyle::PreferSameLine - || (generics.where_clause.predicates.is_empty() - && trimmed_last_line_width(&result) == 1) + ( + brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine, + // missed comments are taken care of in #rewrite_where_clause + None, + ) } else { - brace_pos == BracePos::ForceSameLine - || trimmed_last_line_width(&result) == 1 - || brace_style != BraceStyle::AlwaysNextLine + ( + brace_pos == BracePos::ForceSameLine + || (result.contains('\n') && brace_style == BraceStyle::PreferSameLine + || brace_style != BraceStyle::AlwaysNextLine) + || trimmed_last_line_width(&result) == 1, + rewrite_missing_comment( + mk_sp( + span_end_before_where, + if brace_pos == BracePos::None { + span.hi() + } else { + context.snippet_provider.span_before(span, "{") + }, + ), + shape, + context, + ), + ) }; + // add missing comments + let missed_line_comments = missed_comments + .filter(|missed_comments| !missed_comments.is_empty()) + .map_or(false, |missed_comments| { + let is_block = is_last_comment_block(&missed_comments); + let sep = if is_block { " " } else { "\n" }; + result.push_str(sep); + result.push_str(&missed_comments); + !is_block + }); if brace_pos == BracePos::None { return Some(result); } @@ -2761,7 +2784,7 @@ fn format_generics( // 2 = ` {` 2 }; - let forbid_same_line_brace = overhead > remaining_budget; + let forbid_same_line_brace = missed_line_comments || overhead > remaining_budget; if !forbid_same_line_brace && same_line_brace { result.push(' '); } else { diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 70ca898f2af..0f459571d42 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use syntax::source_map::{BytePos, Pos, Span}; -use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileLines; use crate::config::{EmitMode, FileName}; use crate::shape::{Indent, Shape}; @@ -288,7 +288,7 @@ impl<'a> FmtVisitor<'a> { .next() { Some('\n') | Some('\r') => { - if !subslice.trim_end().ends_with("*/") { + if !is_last_comment_block(subslice) { self.push_str("\n"); } } diff --git a/tests/target/issue-1096.rs b/tests/target/issue-1096.rs new file mode 100644 index 00000000000..de78e736483 --- /dev/null +++ b/tests/target/issue-1096.rs @@ -0,0 +1,71 @@ +struct StructA /* comment 1 */ { + t: T, +} + +struct StructB /* comment 2 */; + +struct StructC /* comment 3 */; + +struct StructD /* comment 4 */ { + t: usize, +} + +struct StructE +/* comment 5 */ +where + T: Clone, +{ + t: usize, +} + +struct StructF +/* comment 6 */ +where + T: Clone, +{ + t: usize, +} + +struct StructG +/* comment 7 */ +// why a line comment?? +{ + t: T, +} + +struct StructH +/* comment 8 */ +// why a line comment?? +where + T: Clone, +{ + t: T, +} + +enum EnumA /* comment 8 */ { + Field(T), +} + +enum EnumB /* comment 9 */ { + Field, +} + +// Issue 2781 +struct StructX1 +// where +// T: Clone +{ + inner: String, +} + +struct StructX2< + T, + U: Iterator, + V: Iterator, + W: Iterator, +> +// where +// T: Clone +{ + inner: String, +} -- cgit 1.4.1-3-g733a5 From 8ffe4146cc813c32bee479c4640e22fdbfcaf657 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 7 Apr 2019 12:31:57 +0900 Subject: fix not to delete semicolon --- src/macros.rs | 3 +++ tests/target/issue-3499.rs | 1 + 2 files changed, 4 insertions(+) create mode 100644 tests/target/issue-3499.rs (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 088b3e4490f..42dd8c344ee 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -274,6 +274,9 @@ pub fn rewrite_macro_inner( DelimToken::Paren if position == MacroPosition::Item => { Some(format!("{}();", macro_name)) } + DelimToken::Bracket if position == MacroPosition::Item => { + Some(format!("{}[];", macro_name)) + } DelimToken::Paren => Some(format!("{}()", macro_name)), DelimToken::Bracket => Some(format!("{}[]", macro_name)), DelimToken::Brace => Some(format!("{} {{}}", macro_name)), diff --git a/tests/target/issue-3499.rs b/tests/target/issue-3499.rs new file mode 100644 index 00000000000..88fd7f7e165 --- /dev/null +++ b/tests/target/issue-3499.rs @@ -0,0 +1 @@ +test![]; -- cgit 1.4.1-3-g733a5 From 4352681d624bcbfb9d5aa9d2f5057091622402a6 Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Thu, 11 Apr 2019 13:48:13 +0200 Subject: fix clippy warnings clippy::needless_return clippy::redundant_closure clippy::or_fun_call clippy::len_zero clippy::expect_fun_call clippy::assertions_on_constants clippy::identity_conversion clippy::chars_last_cmp --- src/chains.rs | 2 +- src/closures.rs | 2 +- src/comment.rs | 2 +- src/config/file_lines.rs | 2 +- src/config/mod.rs | 6 +++--- src/formatting.rs | 4 ++-- src/git-rustfmt/main.rs | 2 +- src/imports.rs | 5 +---- src/items.rs | 6 +++--- src/lib.rs | 2 +- src/lists.rs | 6 +++--- src/macros.rs | 12 +++++------- src/reorder.rs | 6 ++++-- src/source_file.rs | 2 +- src/source_map.rs | 2 +- src/string.rs | 6 ++++-- src/test/mod.rs | 19 ++++++++++--------- src/vertical.rs | 2 +- src/visitor.rs | 2 +- 19 files changed, 45 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 832cae898ef..5ea3953a2c7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -550,7 +550,7 @@ impl<'a> ChainFormatterShared<'a> { let almost_total = if extendable { prev_last_line_width } else { - self.rewrites.iter().map(|a| a.len()).sum() + self.rewrites.iter().map(String::len).sum() } + last.tries; let one_line_budget = if self.child_count == 1 { shape.width diff --git a/src/closures.rs b/src/closures.rs index 381d083c82f..d88b7334034 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -353,7 +353,7 @@ pub fn rewrite_last_closure( /// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`. pub fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool { args.iter() - .filter_map(|arg| arg.to_expr()) + .filter_map(OverflowableItem::to_expr) .filter(|expr| match expr.node { ast::ExprKind::Closure(..) => true, _ => false, diff --git a/src/comment.rs b/src/comment.rs index a811d4a26ed..797f75fc580 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1243,7 +1243,7 @@ where }, CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, CharClassesStatus::Normal => match chr { - 'r' => match self.base.peek().map(|c| c.get_char()) { + 'r' => match self.base.peek().map(RichChar::get_char) { Some('#') | Some('"') => { char_kind = FullCodeCharKind::InString; CharClassesStatus::RawStringPrefix(0) diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 67d2355c938..356861282b1 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -191,7 +191,7 @@ impl FileLines { /// Returns an iterator over the files contained in `self`. pub fn files(&self) -> Files<'_> { - Files(self.0.as_ref().map(|m| m.keys())) + Files(self.0.as_ref().map(HashMap::keys)) } /// Returns JSON representation as accepted by the `--file-lines JSON` arg. diff --git a/src/config/mod.rs b/src/config/mod.rs index 4a4647a5663..6be3dd2b31c 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -244,7 +244,7 @@ impl Config { } } - return Ok(None); + Ok(None) } match resolve_project_file(dir)? { @@ -260,7 +260,7 @@ impl Config { let mut err = String::new(); let table = parsed .as_table() - .ok_or(String::from("Parsed config was not table"))?; + .ok_or_else(|| String::from("Parsed config was not table"))?; for key in table.keys() { if !Config::is_valid_name(key) { let msg = &format!("Warning: Unknown configuration option `{}`\n", key); @@ -358,7 +358,7 @@ fn config_path(options: &dyn CliOptions) -> Result, Error> { config_path_not_found(path.to_str().unwrap()) } } - path => Ok(path.map(|p| p.to_owned())), + path => Ok(path.map(ToOwned::to_owned)), } } diff --git a/src/formatting.rs b/src/formatting.rs index ccf60b242be..ad80e7e1aef 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -263,7 +263,7 @@ impl FormattingError { .and_then(|fl| { fl.file .get_line(fl.lines[0].line_index) - .map(|l| l.into_owned()) + .map(std::borrow::Cow::into_owned) }) .unwrap_or_else(String::new), } @@ -653,7 +653,7 @@ fn parse_crate( return Ok(c); } } - Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(|d| d.emit()), + Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(DiagnosticBuilder::emit), Err(_) => { // Note that if you see this message and want more information, // then run the `parse_crate_mod` function above without diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 67b641a384d..f71ae097808 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -98,7 +98,7 @@ fn uncommitted_files() -> Vec { stdout .lines() .filter(|s| s.ends_with(".rs")) - .map(|s| s.to_owned()) + .map(std::borrow::ToOwned::to_owned) .collect() } diff --git a/src/imports.rs b/src/imports.rs index b0ead7a87b9..f6b41deaef9 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -492,10 +492,7 @@ impl UseTree { // Recursively normalize elements of a list use (including sorting the list). if let UseSegment::List(list) = last { - let mut list = list - .into_iter() - .map(|ut| ut.normalize()) - .collect::>(); + let mut list = list.into_iter().map(UseTree::normalize).collect::>(); list.sort(); last = UseSegment::List(list); } diff --git a/src/items.rs b/src/items.rs index 57bded72604..c7f95557ea3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1358,7 +1358,7 @@ fn format_tuple_struct( context .snippet_provider .opt_span_after(mk_sp(last_arg_span.hi(), span.hi()), ")") - .unwrap_or(last_arg_span.hi()) + .unwrap_or_else(|| last_arg_span.hi()) }; let where_clause_str = match struct_parts.generics { @@ -2143,7 +2143,7 @@ fn rewrite_fn_base( indent } else { if context.config.version() == Version::Two { - if arg_str.len() != 0 || !no_args_and_over_max_width { + if !arg_str.is_empty() || !no_args_and_over_max_width { result.push(' '); } } else { @@ -2284,7 +2284,7 @@ fn rewrite_args( span: Span, variadic: bool, ) -> Option { - if args.len() == 0 { + if args.is_empty() { let comment = context .snippet(mk_sp( span.lo(), diff --git a/src/lib.rs b/src/lib.rs index 7e465ffdcfe..464d318638d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -445,7 +445,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option block_open_index = None, - _ if post_snippet[..i].chars().last() == Some('/') => block_open_index = None, + _ if post_snippet[..i].ends_with('/') => block_open_index = None, _ => (), } } @@ -811,7 +811,7 @@ where pub fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) - + item.item.as_ref().map_or(0, |str| str.len()) + + item.item.as_ref().map_or(0, String::len) } fn comment_len(comment: Option<&str>) -> usize { diff --git a/src/macros.rs b/src/macros.rs index 42dd8c344ee..f8141e0e0d6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -933,8 +933,7 @@ impl MacroArgParser { /// Returns a collection of parsed macro def's arguments. pub fn parse(mut self, tokens: TokenStream) -> Option> { - let stream: TokenStream = tokens.into(); - let mut iter = stream.trees(); + let mut iter = tokens.trees(); while let Some(tok) = iter.next() { match tok { @@ -1045,18 +1044,17 @@ fn wrap_macro_args_inner( // FIXME: Use multi-line when every thing does not fit on one line. fn format_macro_args( context: &RewriteContext<'_>, - toks: TokenStream, + token_stream: TokenStream, shape: Shape, ) -> Option { if !context.config.format_macro_matchers() { - let token_stream: TokenStream = toks.into(); let span = span_for_token_stream(&token_stream); return Some(match span { Some(span) => context.snippet(span).to_owned(), None => String::new(), }); } - let parsed_args = MacroArgParser::new().parse(toks)?; + let parsed_args = MacroArgParser::new().parse(token_stream)?; wrap_macro_args(context, &parsed_args, shape) } @@ -1140,7 +1138,7 @@ fn next_space(tok: &Token) -> SpaceState { /// failed). pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { if &mac.node.path.to_string() == "try" { - let ts: TokenStream = mac.node.tts.clone().into(); + let ts: TokenStream = mac.node.tts.clone(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); Some(ast::Expr { @@ -1194,7 +1192,7 @@ impl MacroParser { TokenTree::Token(..) => return None, TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d), }; - let args = tok.joint().into(); + let args = tok.joint(); match self.toks.next()? { TokenTree::Token(_, Token::FatArrow) => {} _ => return None, diff --git a/src/reorder.rs b/src/reorder.rs index e206d9249e7..49a4638f33f 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -32,8 +32,10 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` // ^^^ Comparing this. - let a_orig_name = a_name.map_or_else(|| a.ident.as_str(), |symbol| symbol.as_str()); - let b_orig_name = b_name.map_or_else(|| b.ident.as_str(), |symbol| symbol.as_str()); + let a_orig_name = + a_name.map_or_else(|| a.ident.as_str(), syntax_pos::symbol::Symbol::as_str); + let b_orig_name = + b_name.map_or_else(|| b.ident.as_str(), syntax_pos::symbol::Symbol::as_str); let result = a_orig_name.cmp(&b_orig_name); if result != Ordering::Equal { return result; diff --git a/src/source_file.rs b/src/source_file.rs index a779c4dfbe2..36483146f05 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -69,7 +69,7 @@ where // original text for `FileName::Stdin`. let original_text = source_map .and_then(|x| x.get_source_file(&filename.into())) - .and_then(|x| x.src.as_ref().map(|x| x.to_string())); + .and_then(|x| x.src.as_ref().map(ToString::to_string)); let original_text = match original_text { Some(ori) => ori, None => fs::read_to_string(ensure_real_path(filename))?, diff --git a/src/source_map.rs b/src/source_map.rs index 096a7ce5713..9cc9cb857b1 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -71,7 +71,7 @@ impl<'a> SpanUtils for SnippetProvider<'a> { impl LineRangeUtils for SourceMap { fn lookup_line_range(&self, span: Span) -> LineRange { - let snippet = self.span_to_snippet(span).unwrap_or(String::new()); + let snippet = self.span_to_snippet(span).unwrap_or_default(); let lo = self.lookup_line(span.lo()).unwrap(); let hi = self.lookup_line(span.hi()).unwrap(); diff --git a/src/string.rs b/src/string.rs index 8b910c0b4ce..14220ba5d79 100644 --- a/src/string.rs +++ b/src/string.rs @@ -338,11 +338,13 @@ fn is_new_line(grapheme: &str) -> bool { } fn is_whitespace(grapheme: &str) -> bool { - grapheme.chars().all(|c| c.is_whitespace()) + grapheme.chars().all(char::is_whitespace) } fn is_punctuation(grapheme: &str) -> bool { - grapheme.chars().all(|c| c.is_punctuation_other()) + grapheme + .chars() + .all(UnicodeCategories::is_punctuation_other) } fn graphemes_width(graphemes: &[&str]) -> usize { diff --git a/src/test/mod.rs b/src/test/mod.rs index dc297a52dfb..0ee25ff5c19 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -34,7 +34,7 @@ struct TestSetting { impl Default for TestSetting { fn default() -> Self { TestSetting { - stack_size: 8388608, // 8MB + stack_size: 8_388_608, // 8MB } } } @@ -90,12 +90,13 @@ fn verify_config_used(path: &Path, config_name: &str) { if path.extension().map_or(false, |f| f == "rs") { // check if "// rustfmt-:" appears in the file. let filebuf = BufReader::new( - fs::File::open(&path).expect(&format!("couldn't read file {}", path.display())), + fs::File::open(&path) + .unwrap_or_else(|_| panic!("couldn't read file {}", path.display())), ); assert!( filebuf .lines() - .map(|l| l.unwrap()) + .map(Result::unwrap) .take_while(|l| l.starts_with("//")) .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), format!( @@ -249,7 +250,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { let mut failures = HashMap::new(); failures.insert(source.to_owned(), compare); print_mismatches_default_message(failures); - assert!(false, "Text does not match expected output"); + panic!("Text does not match expected output"); } } @@ -565,8 +566,8 @@ fn get_config(config_file: Option<&Path>) -> Config { // Reads significant comments of the form: `// rustfmt-key: value` into a hash map. fn read_significant_comments(file_name: &Path) -> HashMap { - let file = - fs::File::open(file_name).expect(&format!("couldn't read file {}", file_name.display())); + let file = fs::File::open(file_name) + .unwrap_or_else(|_| panic!("couldn't read file {}", file_name.display())); let reader = BufReader::new(file); let pattern = r"^\s*//\s*rustfmt-([^:]+):\s*(\S+)"; let regex = regex::Regex::new(pattern).expect("failed creating pattern 1"); @@ -962,10 +963,10 @@ fn configuration_snippet_tests() { fn get_code_blocks() -> Vec { let mut file_iter = BufReader::new( fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) - .expect(&format!("couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + .unwrap_or_else(|_| panic!("couldn't read file {}", CONFIGURATIONS_FILE_NAME)), ) .lines() - .map(|l| l.unwrap()) + .map(Result::unwrap) .enumerate(); let mut code_blocks: Vec = Vec::new(); let mut hash_set = Config::hash_set(); @@ -988,7 +989,7 @@ fn configuration_snippet_tests() { let blocks = get_code_blocks(); let failures = blocks .iter() - .map(|b| b.formatted_is_idempotent()) + .map(ConfigCodeBlock::formatted_is_idempotent) .fold(0, |acc, r| acc + (!r as u32)); // Display results. diff --git a/src/vertical.rs b/src/vertical.rs index a7977a64e6c..0b69c3603d4 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -135,7 +135,7 @@ pub fn rewrite_with_alignment( let snippet = context.snippet(missing_span); if snippet.trim_start().starts_with("//") { - let offset = snippet.lines().next().map_or(0, |l| l.len()); + let offset = snippet.lines().next().map_or(0, str::len); // 2 = "," + "\n" init_hi + BytePos(offset as u32 + 2) } else if snippet.trim_start().starts_with("/*") { diff --git a/src/visitor.rs b/src/visitor.rs index c29409c2fdf..b1d3b12ea14 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -146,7 +146,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if let Some(first_stmt) = b.stmts.first() { let hi = inner_attrs .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) - .unwrap_or(first_stmt.span().lo()); + .unwrap_or_else(|| first_stmt.span().lo()); let snippet = self.snippet(mk_sp(self.last_pos, hi)); let len = CommentCodeSlices::new(snippet) -- cgit 1.4.1-3-g733a5 From 8a04ec6ec7d3db1ad101ea0b43fc570f38cea6c4 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 14 Apr 2019 00:23:10 +0900 Subject: fix not to emit version --- src/cargo-fmt/main.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index a686e91b694..59b76a54279 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -79,7 +79,7 @@ fn execute() -> i32 { } if matches.opt_present("version") { - return handle_command_status(get_version(verbosity), &opts); + return handle_command_status(get_version(), &opts); } let strategy = CargoFmtStrategy::from_matches(&matches); @@ -122,8 +122,19 @@ fn handle_command_status(status: Result, opts: &getopts::Options } } -fn get_version(verbosity: Verbosity) -> Result { - run_rustfmt(&BTreeSet::new(), &[String::from("--version")], verbosity) +fn get_version() -> Result { + let mut status = vec![]; + let mut command = Command::new("rustfmt") + .stdout(std::process::Stdio::inherit()) + .args(&[String::from("--version")]) + .spawn()?; + status.push(command.wait()?); + + Ok(status + .iter() + .filter_map(|s| if s.success() { None } else { s.code() }) + .next() + .unwrap_or(SUCCESS)) } fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result { -- cgit 1.4.1-3-g733a5 From 3759a6695d12abcb7901c82a7b93d184deb55248 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 14 Apr 2019 17:34:53 +0900 Subject: add the error mapping --- src/cargo-fmt/main.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 59b76a54279..55f098348b9 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -127,7 +127,14 @@ fn get_version() -> Result { let mut command = Command::new("rustfmt") .stdout(std::process::Stdio::inherit()) .args(&[String::from("--version")]) - .spawn()?; + .spawn() + .map_err(|e| match e.kind() { + io::ErrorKind::NotFound => io::Error::new( + io::ErrorKind::Other, + "Could not run rustfmt, please make sure it is in your PATH.", + ), + _ => e, + })?; status.push(command.wait()?); Ok(status -- cgit 1.4.1-3-g733a5 From 34bf13718a6af228260312139f646c7d79e6aa71 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Sun, 14 Apr 2019 19:30:44 +0900 Subject: Allow specifying glob pattern to ignore config option (#3488) --- Cargo.lock | 78 +++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/config/config_type.rs | 6 +--- src/config/mod.rs | 10 +++--- src/config/options.rs | 25 +++++++-------- src/formatting.rs | 13 ++++++-- src/ignore_path.rs | 55 +++++++++++++++++++++++++++++++++ src/lib.rs | 5 +++ src/test/mod.rs | 2 +- 9 files changed, 167 insertions(+), 28 deletions(-) create mode 100644 src/ignore_path.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index da7026bb138..be6c0364ac8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,6 +124,15 @@ name = "constant_time_eq" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-channel" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.2.0" @@ -155,6 +164,15 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-utils" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive-new" version = "0.5.6" @@ -233,6 +251,11 @@ dependencies = [ "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -246,6 +269,18 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "globset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "humantime" version = "1.2.0" @@ -254,6 +289,23 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ignore" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools" version = "0.8.0" @@ -701,6 +753,7 @@ dependencies = [ "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -724,6 +777,14 @@ name = "ryu" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "same-file" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scoped-tls" version = "1.0.0" @@ -882,6 +943,16 @@ name = "utf8-ranges" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "2.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.3.6" @@ -935,9 +1006,11 @@ dependencies = [ "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" @@ -947,9 +1020,12 @@ dependencies = [ "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" +"checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum ignore 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ad03ca67dc12474ecd91fdb94d758cbd20cb4e7a78ebe831df26a9b7511e1162" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "dd80e58f77e0cdea53ba96acc5e04479e5ffc5d869626a6beafe50fed867eace" @@ -1000,6 +1076,7 @@ dependencies = [ "checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -1023,6 +1100,7 @@ dependencies = [ "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" diff --git a/Cargo.toml b/Cargo.toml index 2e6cc9e8a06..d84ca1d7292 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ bytecount = "0.5" unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "1.0.4" +ignore = "0.4.6" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 7c4298dcf1c..40da2986808 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -141,7 +141,7 @@ macro_rules! create_config { ConfigWasSet(self) } - fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config { + fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { $( if let Some(val) = parsed.$i { if self.$i.3 { @@ -160,7 +160,6 @@ macro_rules! create_config { )+ self.set_heuristics(); self.set_license_template(); - self.set_ignore(dir); self } @@ -287,9 +286,6 @@ macro_rules! create_config { } } - fn set_ignore(&mut self, dir: &Path) { - self.ignore.2.add_prefix(dir); - } /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { diff --git a/src/config/mod.rs b/src/config/mod.rs index 6be3dd2b31c..839e9bb6e21 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -190,8 +190,7 @@ impl Config { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; - Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolves the config for input in `dir`. @@ -253,7 +252,7 @@ impl Config { } } - pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + pub(crate) fn from_toml(toml: &str) -> Result { let parsed: ::toml::Value = toml .parse() .map_err(|e| format!("Could not parse TOML: {}", e))?; @@ -272,7 +271,7 @@ impl Config { if !err.is_empty() { eprint!("{}", err); } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) + Ok(Config::default().fill_from_parsed_config(parsed_config)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -426,8 +425,7 @@ mod test { #[test] fn test_was_set() { - use std::path::Path; - let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); + let config = Config::from_toml("hard_tabs = true").unwrap(); assert_eq!(config.was_set().hard_tabs(), true); assert_eq!(config.was_set().verbose(), false); diff --git a/src/config/options.rs b/src/config/options.rs index 02c3c87368e..bd8c5056854 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,11 +1,11 @@ -use std::collections::HashSet; +use std::collections::{hash_set, HashSet}; use std::path::{Path, PathBuf}; use atty; use crate::config::config_type::ConfigType; use crate::config::lists::*; -use crate::config::{Config, FileName}; +use crate::config::Config; /// Macro that will stringify the enum variants or a provided textual repr #[macro_export] @@ -399,6 +399,15 @@ impl Default for EmitMode { #[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct IgnoreList(HashSet); +impl<'a> IntoIterator for &'a IgnoreList { + type Item = &'a PathBuf; + type IntoIter = hash_set::Iter<'a, PathBuf>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + impl IgnoreList { pub fn add_prefix(&mut self, dir: &Path) { self.0 = self @@ -415,18 +424,6 @@ impl IgnoreList { }) .collect(); } - - fn skip_file_inner(&self, file: &Path) -> bool { - self.0.iter().any(|path| file.starts_with(path)) - } - - pub fn skip_file(&self, file: &FileName) -> bool { - if let FileName::Real(ref path) = file { - self.skip_file_inner(path) - } else { - false - } - } } impl ::std::str::FromStr for IgnoreList { diff --git a/src/formatting.rs b/src/formatting.rs index ad80e7e1aef..391a3c0e384 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -14,6 +14,7 @@ use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; +use crate::ignore_path::IgnorePathSet; use crate::issues::BadIssueSeeker; use crate::utils::{count_newlines, get_skip_macro_names}; use crate::visitor::{FmtVisitor, SnippetProvider}; @@ -90,6 +91,10 @@ fn format_project( parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); + let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { + Ok(set) => set, + Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), + }; let files = modules::ModResolver::new( context.parse_session.source_map(), @@ -99,7 +104,8 @@ fn format_project( .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; for (path, (module, _)) in files { - if (config.skip_children() && path != main_file) || config.ignore().skip_file(&path) { + let should_ignore = !input_is_stdin && ignore_path_set.is_match(&path); + if (config.skip_children() && path != main_file) || should_ignore { continue; } should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); @@ -276,7 +282,10 @@ impl FormattingError { | ErrorKind::IoError(_) | ErrorKind::ParseError | ErrorKind::LostComment => "internal error:", - ErrorKind::LicenseCheck | ErrorKind::BadAttr | ErrorKind::VersionMismatch => "error:", + ErrorKind::LicenseCheck + | ErrorKind::BadAttr + | ErrorKind::InvalidGlobPattern(..) + | ErrorKind::VersionMismatch => "error:", ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", } } diff --git a/src/ignore_path.rs b/src/ignore_path.rs new file mode 100644 index 00000000000..1e17337e625 --- /dev/null +++ b/src/ignore_path.rs @@ -0,0 +1,55 @@ +use ignore::{self, gitignore}; +use std::path::PathBuf; + +use crate::config::{FileName, IgnoreList}; + +pub struct IgnorePathSet { + ignore_set: gitignore::Gitignore, +} + +impl IgnorePathSet { + pub fn from_ignore_list(ignore_list: &IgnoreList) -> Result { + let mut ignore_builder = gitignore::GitignoreBuilder::new(PathBuf::from("")); + + for ignore_path in ignore_list { + ignore_builder.add_line(None, ignore_path.to_str().unwrap())?; + } + + Ok(IgnorePathSet { + ignore_set: ignore_builder.build()?, + }) + } + + pub fn is_match(&self, file_name: &FileName) -> bool { + match file_name { + FileName::Stdin => false, + FileName::Real(p) => self + .ignore_set + .matched_path_or_any_parents(p, false) + .is_ignore(), + } + } +} + +#[cfg(test)] +mod test { + use crate::config::{Config, FileName}; + use crate::ignore_path::IgnorePathSet; + use std::path::PathBuf; + + #[test] + fn test_ignore_path_set() { + let config = Config::from_toml( + "ignore = [ + \"foo.rs\", + \"bar_dir/*\", + ]", + ) + .unwrap(); + let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); + + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs")))); + assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs")))); + } +} diff --git a/src/lib.rs b/src/lib.rs index 464d318638d..b804f5637d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ use std::path::PathBuf; use std::rc::Rc; use failure::Fail; +use ignore; use syntax::{ast, parse::DirectoryOwnership}; use crate::comment::LineClasses; @@ -46,6 +47,7 @@ mod comment; pub(crate) mod config; mod expr; pub(crate) mod formatting; +mod ignore_path; mod imports; mod issues; mod items; @@ -110,6 +112,9 @@ pub enum ErrorKind { /// If we had formatted the given node, then we would have lost a comment. #[fail(display = "not formatted because a comment would be lost")] LostComment, + /// Invalid glob pattern in `ignore` configuration option. + #[fail(display = "Invalid glob pattern found in ignore list: {}", _0)] + InvalidGlobPattern(ignore::Error), } impl ErrorKind { diff --git a/src/test/mod.rs b/src/test/mod.rs index 0ee25ff5c19..199c2400476 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -561,7 +561,7 @@ fn get_config(config_file: Option<&Path>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML") + Config::from_toml(&def_config).expect("invalid TOML") } // Reads significant comments of the form: `// rustfmt-key: value` into a hash map. -- cgit 1.4.1-3-g733a5 From 3d80678e248ec880b5ee363f123b298189c7724b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 14 Apr 2019 20:13:07 +0900 Subject: Do not include body's attributes in `arrow_span` --- src/matches.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index c3102f12123..84fe1bdafe8 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -263,7 +263,7 @@ fn rewrite_match_arm( false, )?; - let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span.lo()); + let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span().lo()); rewrite_match_body( context, &arm.body, -- cgit 1.4.1-3-g733a5 From b57e0e22795a881b670defa205908964fb0a8040 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 14 Apr 2019 20:13:54 +0900 Subject: Disallow putting a body with attributes on the same line --- src/matches.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 84fe1bdafe8..c09949cf2e8 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -364,7 +364,8 @@ fn rewrite_match_body( shape.indent }; - let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block; + let forbid_same_line = + (has_guard && pats_str.contains('\n') && !is_empty_block) || !body.attrs.is_empty(); // Look for comments between `=>` and the start of the body. let arrow_comment = { -- cgit 1.4.1-3-g733a5 From 15ab3635084a4f6a7f56d20a2678e4c86019ac0e Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Sun, 14 Apr 2019 20:37:29 +0900 Subject: not to use Vec --- src/cargo-fmt/main.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 55f098348b9..14d9c7f2423 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -123,7 +123,6 @@ fn handle_command_status(status: Result, opts: &getopts::Options } fn get_version() -> Result { - let mut status = vec![]; let mut command = Command::new("rustfmt") .stdout(std::process::Stdio::inherit()) .args(&[String::from("--version")]) @@ -135,13 +134,12 @@ fn get_version() -> Result { ), _ => e, })?; - status.push(command.wait()?); - - Ok(status - .iter() - .filter_map(|s| if s.success() { None } else { s.code() }) - .next() - .unwrap_or(SUCCESS)) + let result = command.wait()?; + if result.success() { + Ok(SUCCESS) + } else { + Ok(result.code().unwrap_or(SUCCESS)) + } } fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result { -- cgit 1.4.1-3-g733a5 From d3e578b1312b2258f0a8ee24c15416affcaf1ce1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 14 Apr 2019 20:45:04 +0900 Subject: Avoid overflowing item if it has attributes --- src/expr.rs | 1 + src/overflow.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 90cbba334f1..ff95ee41d02 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1343,6 +1343,7 @@ pub fn can_be_overflowed_expr( args_len: usize, ) -> bool { match expr.node { + _ if !expr.attrs.is_empty() => false, ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) || (context.config.indent_style() == IndentStyle::Visual && args_len > 1) diff --git a/src/overflow.rs b/src/overflow.rs index ac425b591aa..bd23d955aae 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -91,6 +91,17 @@ impl<'a> Spanned for OverflowableItem<'a> { } impl<'a> OverflowableItem<'a> { + fn has_attrs(&self) -> bool { + match self { + OverflowableItem::Expr(ast::Expr { attrs, .. }) + | OverflowableItem::GenericParam(ast::GenericParam { attrs, .. }) => !attrs.is_empty(), + OverflowableItem::StructField(ast::StructField { attrs, .. }) => !attrs.is_empty(), + OverflowableItem::MacroArg(MacroArg::Expr(expr)) => !expr.attrs.is_empty(), + OverflowableItem::MacroArg(MacroArg::Item(item)) => !item.attrs.is_empty(), + _ => false, + } + } + pub fn map(&self, f: F) -> T where F: Fn(&dyn IntoOverflowableItem<'a>) -> T, @@ -447,6 +458,7 @@ impl<'a> Context<'a> { // 1 = "(" let combine_arg_with_callee = self.items.len() == 1 && self.items[0].is_expr() + && !self.items[0].has_attrs() && self.ident.len() < self.context.config.tab_spaces(); let overflow_last = combine_arg_with_callee || can_be_overflowed(self.context, &self.items); -- cgit 1.4.1-3-g733a5 From 1c7202b2eebb6a514fa1b175e38a66ac518ff409 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 15 Apr 2019 12:50:01 +0200 Subject: fix test_ignore_path_set test when run on beta ``` ---- ignore_path::test::test_ignore_path_set stdout ---- Warning: can't set `ignore = IgnoreList({"foo.rs", "bar_dir/*"})`, unstable features are only available in nightly channel. thread 'ignore_path::test::test_ignore_path_set' panicked at 'assertion failed: ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))', src/ignore_path.rs:51:9 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. failures: ignore_path::test::test_ignore_path_set ``` --- src/ignore_path.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/ignore_path.rs b/src/ignore_path.rs index 1e17337e625..6299aedf4a7 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -39,17 +39,17 @@ mod test { #[test] fn test_ignore_path_set() { - let config = Config::from_toml( - "ignore = [ - \"foo.rs\", - \"bar_dir/*\", - ]", - ) - .unwrap(); - let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); - - assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); - assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs")))); - assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs")))); + match option_env!("CFG_RELEASE_CHANNEL") { + // this test requires nightly + None | Some("nightly") => { + let config = Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#).unwrap(); + let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); + + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); + assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("bar_dir/baz.rs")))); + assert!(!ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/bar.rs")))); + } + _ => (), + }; } } -- cgit 1.4.1-3-g733a5 From 3dc625c661924d47fcb040b27f56ab7a9a206c60 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 17 Apr 2019 14:33:36 +0200 Subject: Use annotate-snippets for emitting errors (#3507) --- Cargo.lock | 19 +++++ Cargo.toml | 1 + src/bin/main.rs | 34 ++++---- src/format_report_formatter.rs | 173 +++++++++++++++++++++++++++++++++++++++++ src/formatting.rs | 10 +-- src/git-rustfmt/main.rs | 4 +- src/lib.rs | 124 ++++------------------------- src/test/mod.rs | 9 ++- 8 files changed, 238 insertions(+), 136 deletions(-) create mode 100644 src/format_report_formatter.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index be6c0364ac8..90961fa86f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,22 @@ dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "annotate-snippets" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "argon2rs" version = "0.2.5" @@ -744,6 +760,7 @@ dependencies = [ name = "rustfmt-nightly" version = "1.2.0" dependencies = [ + "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -991,6 +1008,8 @@ dependencies = [ [metadata] "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8bcdcd5b291ce85a78f2b9d082a8de9676c12b1840d386d67bc5eea6f9d2b4e" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" diff --git a/Cargo.toml b/Cargo.toml index d84ca1d7292..55a44e2890d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,7 @@ unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "1.0.4" ignore = "0.4.6" +annotate-snippets = { version = "0.5.0", features = ["ansi_term"] } # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/bin/main.rs b/src/bin/main.rs index 551b422e06c..5b69a440b65 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -16,7 +16,7 @@ use getopts::{Matches, Options}; use crate::rustfmt::{ load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines, FileName, - Input, Session, Verbosity, + FormatReportFormatterBuilder, Input, Session, Verbosity, }; fn main() { @@ -310,19 +310,12 @@ fn format_and_emit_report(session: &mut Session<'_, T>, input: Input) match session.format(input) { Ok(report) => { if report.has_warnings() { - match term::stderr() { - Some(ref t) - if session.config.color().use_colored_tty() - && t.supports_color() - && t.supports_attr(term::Attr::Bold) => - { - match report.fancy_print(term::stderr().unwrap()) { - Ok(..) => (), - Err(..) => panic!("Unable to write to stderr: {}", report), - } - } - _ => eprintln!("{}", report), - } + eprintln!( + "{}", + FormatReportFormatterBuilder::new(&report) + .enable_colors(should_print_with_colors(session)) + .build() + ); } } Err(msg) => { @@ -332,6 +325,19 @@ fn format_and_emit_report(session: &mut Session<'_, T>, input: Input) } } +fn should_print_with_colors(session: &mut Session<'_, T>) -> bool { + match term::stderr() { + Some(ref t) + if session.config.color().use_colored_tty() + && t.supports_color() + && t.supports_attr(term::Attr::Bold) => + { + true + } + _ => false, + } +} + fn print_usage_to_stdout(opts: &Options, reason: &str) { let sep = if reason.is_empty() { String::new() diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs new file mode 100644 index 00000000000..550380cdd2b --- /dev/null +++ b/src/format_report_formatter.rs @@ -0,0 +1,173 @@ +use crate::config::FileName; +use crate::formatting::FormattingError; +use crate::{ErrorKind, FormatReport}; +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; +use std::fmt::{self, Display}; + +/// A builder for [`FormatReportFormatter`]. +pub struct FormatReportFormatterBuilder<'a> { + report: &'a FormatReport, + enable_colors: bool, +} + +impl<'a> FormatReportFormatterBuilder<'a> { + /// Creates a new [`FormatReportFormatterBuilder`]. + pub fn new(report: &'a FormatReport) -> Self { + Self { + report, + enable_colors: false, + } + } + + /// Enables colors and formatting in the output. + pub fn enable_colors(self, enable_colors: bool) -> Self { + Self { + enable_colors, + ..self + } + } + + /// Creates a new [`FormatReportFormatter`] from the settings in this builder. + pub fn build(self) -> FormatReportFormatter<'a> { + FormatReportFormatter { + report: self.report, + enable_colors: self.enable_colors, + } + } +} + +/// Formats the warnings/errors in a [`FormatReport`]. +/// +/// Can be created using a [`FormatReportFormatterBuilder`]. +pub struct FormatReportFormatter<'a> { + report: &'a FormatReport, + enable_colors: bool, +} + +impl<'a> Display for FormatReportFormatter<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let formatter = DisplayListFormatter::new(self.enable_colors); + let errors_by_file = &self.report.internal.borrow().0; + + for (file, errors) in errors_by_file { + for error in errors { + let snippet = formatting_error_to_snippet(file, error); + writeln!(f, "{}\n", formatter.format(&DisplayList::from(snippet)))?; + } + } + + if !errors_by_file.is_empty() { + let snippet = formatting_failure_snippet(self.report.warning_count()); + writeln!(f, "{}", formatter.format(&DisplayList::from(snippet)))?; + } + + Ok(()) + } +} + +fn formatting_failure_snippet(warning_count: usize) -> Snippet { + Snippet { + title: Some(Annotation { + id: None, + label: Some(format!( + "rustfmt has failed to format. See previous {} errors.", + warning_count + )), + annotation_type: AnnotationType::Warning, + }), + footer: Vec::new(), + slices: Vec::new(), + } +} + +fn formatting_error_to_snippet(file: &FileName, error: &FormattingError) -> Snippet { + let slices = vec![snippet_code_slice(file, error)]; + let title = Some(snippet_title(error)); + let footer = snippet_footer(error).into_iter().collect(); + + Snippet { + title, + footer, + slices, + } +} + +fn snippet_title(error: &FormattingError) -> Annotation { + let annotation_type = error_kind_to_snippet_annotation_type(&error.kind); + + Annotation { + id: title_annotation_id(error), + label: Some(error.kind.to_string()), + annotation_type, + } +} + +fn snippet_footer(error: &FormattingError) -> Option { + let message_suffix = error.msg_suffix(); + + if !message_suffix.is_empty() { + Some(Annotation { + id: None, + label: Some(message_suffix.to_string()), + annotation_type: AnnotationType::Note, + }) + } else { + None + } +} + +fn snippet_code_slice(file: &FileName, error: &FormattingError) -> Slice { + let annotations = slice_annotation(error).into_iter().collect(); + let origin = Some(format!("{}:{}", file, error.line)); + let source = error.line_buffer.clone(); + + Slice { + source, + line_start: error.line, + origin, + fold: false, + annotations, + } +} + +fn slice_annotation(error: &FormattingError) -> Option { + let (range_start, range_length) = error.format_len(); + let range_end = range_start + range_length; + + if range_length > 0 { + Some(SourceAnnotation { + annotation_type: AnnotationType::Error, + range: (range_start, range_end), + label: String::new(), + }) + } else { + None + } +} + +fn title_annotation_id(error: &FormattingError) -> Option { + const INTERNAL_ERROR_ID: &str = "internal"; + + if error.is_internal() { + Some(INTERNAL_ERROR_ID.to_string()) + } else { + None + } +} + +fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationType { + match error_kind { + ErrorKind::LineOverflow(..) + | ErrorKind::TrailingWhitespace + | ErrorKind::IoError(_) + | ErrorKind::ParseError + | ErrorKind::LostComment + | ErrorKind::LicenseCheck + | ErrorKind::BadAttr + | ErrorKind::InvalidGlobPattern(_) + | ErrorKind::VersionMismatch => AnnotationType::Error, + ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => AnnotationType::Warning, + } +} diff --git a/src/formatting.rs b/src/formatting.rs index 391a3c0e384..47ff9021c97 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -275,18 +275,14 @@ impl FormattingError { } } - pub(crate) fn msg_prefix(&self) -> &str { + pub(crate) fn is_internal(&self) -> bool { match self.kind { ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace | ErrorKind::IoError(_) | ErrorKind::ParseError - | ErrorKind::LostComment => "internal error:", - ErrorKind::LicenseCheck - | ErrorKind::BadAttr - | ErrorKind::InvalidGlobPattern(..) - | ErrorKind::VersionMismatch => "error:", - ErrorKind::BadIssue(_) | ErrorKind::DeprecatedAttr => "warning:", + | ErrorKind::LostComment => true, + _ => false, } } diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index f71ae097808..c90eae3e649 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -11,7 +11,7 @@ use env_logger; use getopts::{Matches, Options}; use rustfmt_nightly as rustfmt; -use crate::rustfmt::{load_config, CliOptions, Input, Session}; +use crate::rustfmt::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -67,7 +67,7 @@ fn fmt_files(files: &[&str]) -> i32 { for file in files { let report = session.format(Input::File(PathBuf::from(file))).unwrap(); if report.has_warnings() { - eprintln!("{}", report); + eprintln!("{}", FormatReportFormatterBuilder::new(&report).build()); } if !session.has_no_errors() { exit_code = 1; diff --git a/src/lib.rs b/src/lib.rs index b804f5637d7..3de9616a2ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,8 @@ pub use crate::config::{ Range, Verbosity, }; +pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; + pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines}; #[macro_use] @@ -46,6 +48,7 @@ mod closures; mod comment; pub(crate) mod config; mod expr; +mod format_report_formatter; pub(crate) mod formatting; mod ignore_path; mod imports; @@ -162,7 +165,7 @@ impl FormattedSnippet { /// Reports on any issues that occurred during a run of Rustfmt. /// -/// Can be reported to the user via its `Display` implementation of `print_fancy`. +/// Can be reported to the user using the `Display` impl on [`FormatReportFormatter`]. #[derive(Clone)] pub struct FormatReport { // Maps stringified file paths to their associated formatting errors. @@ -245,126 +248,27 @@ impl FormatReport { /// Print the report to a terminal using colours and potentially other /// fancy output. + #[deprecated(note = "Use FormatReportFormatter with colors enabled instead")] pub fn fancy_print( &self, mut t: Box>, ) -> Result<(), term::Error> { - for (file, errors) in &self.internal.borrow().0 { - for error in errors { - let prefix_space_len = error.line.to_string().len(); - let prefix_spaces = " ".repeat(1 + prefix_space_len); - - // First line: the overview of error - t.fg(term::color::RED)?; - t.attr(term::Attr::Bold)?; - write!(t, "{} ", error.msg_prefix())?; - t.reset()?; - t.attr(term::Attr::Bold)?; - writeln!(t, "{}", error.kind)?; - - // Second line: file info - write!(t, "{}--> ", &prefix_spaces[1..])?; - t.reset()?; - writeln!(t, "{}:{}", file, error.line)?; - - // Third to fifth lines: show the line which triggered error, if available. - if !error.line_buffer.is_empty() { - let (space_len, target_len) = error.format_len(); - t.attr(term::Attr::Bold)?; - write!(t, "{}|\n{} | ", prefix_spaces, error.line)?; - t.reset()?; - writeln!(t, "{}", error.line_buffer)?; - t.attr(term::Attr::Bold)?; - write!(t, "{}| ", prefix_spaces)?; - t.fg(term::color::RED)?; - writeln!(t, "{}", FormatReport::target_str(space_len, target_len))?; - t.reset()?; - } - - // The last line: show note if available. - let msg_suffix = error.msg_suffix(); - if !msg_suffix.is_empty() { - t.attr(term::Attr::Bold)?; - write!(t, "{}= note: ", prefix_spaces)?; - t.reset()?; - writeln!(t, "{}", error.msg_suffix())?; - } else { - writeln!(t)?; - } - t.reset()?; - } - } - - if !self.internal.borrow().0.is_empty() { - t.attr(term::Attr::Bold)?; - write!(t, "warning: ")?; - t.reset()?; - write!( - t, - "rustfmt may have failed to format. See previous {} errors.\n\n", - self.warning_count(), - )?; - } - + writeln!( + t, + "{}", + FormatReportFormatterBuilder::new(&self) + .enable_colors(true) + .build() + )?; Ok(()) } - - fn target_str(space_len: usize, target_len: usize) -> String { - let empty_line = " ".repeat(space_len); - let overflowed = "^".repeat(target_len); - empty_line + &overflowed - } } +#[deprecated(note = "Use FormatReportFormatter instead")] impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - for (file, errors) in &self.internal.borrow().0 { - for error in errors { - let prefix_space_len = error.line.to_string().len(); - let prefix_spaces = " ".repeat(1 + prefix_space_len); - - let error_line_buffer = if error.line_buffer.is_empty() { - String::from(" ") - } else { - let (space_len, target_len) = error.format_len(); - format!( - "{}|\n{} | {}\n{}| {}", - prefix_spaces, - error.line, - error.line_buffer, - prefix_spaces, - FormatReport::target_str(space_len, target_len) - ) - }; - - let error_info = format!("{} {}", error.msg_prefix(), error.kind); - let file_info = format!("{}--> {}:{}", &prefix_spaces[1..], file, error.line); - let msg_suffix = error.msg_suffix(); - let note = if msg_suffix.is_empty() { - String::new() - } else { - format!("{}note= ", prefix_spaces) - }; - - writeln!( - fmt, - "{}\n{}\n{}\n{}{}", - error_info, - file_info, - error_line_buffer, - note, - error.msg_suffix() - )?; - } - } - if !self.internal.borrow().0.is_empty() { - writeln!( - fmt, - "warning: rustfmt may have failed to format. See previous {} errors.", - self.warning_count(), - )?; - } + write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?; Ok(()) } } diff --git a/src/test/mod.rs b/src/test/mod.rs index 199c2400476..c084742a217 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -13,7 +13,7 @@ use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTacti use crate::formatting::{ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; -use crate::{FormatReport, Input, Session}; +use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session}; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; @@ -299,7 +299,10 @@ fn self_tests() { assert_eq!(fails, 0, "{} self tests failed", fails); for format_report in reports { - println!("{}", format_report); + println!( + "{}", + FormatReportFormatterBuilder::new(&format_report).build() + ); warnings += format_report.warning_count(); } @@ -427,7 +430,7 @@ fn check_files(files: Vec, opt_config: &Option) -> (Vec { - print!("{}", report); + print!("{}", FormatReportFormatterBuilder::new(&report).build()); fails += 1; } Ok(report) => reports.push(report), -- cgit 1.4.1-3-g733a5 From c60d6ddc02e8187ee83c1e99376b3eb37d81f981 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Apr 2019 13:04:44 +0200 Subject: "first" element check does nothing --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index f8141e0e0d6..05a70ae9d4e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -847,7 +847,7 @@ impl MacroArgParser { span: Span, ) -> Option<()> { let mut buffer = String::new(); - let mut first = false; + let mut first = true; let mut lo = span.lo(); let mut hi = span.hi(); -- cgit 1.4.1-3-g733a5 From f8d3aa590808a4953770012a2af8dbc4a6e1c120 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 Apr 2019 08:12:02 +0900 Subject: Add a path to the parent dir of rustfmt.toml as a prefix Paths users specify in `ignore` configuraiton option is relative to the directory which contains the rustfmt.toml file. When processing the ignore paths internally, rustfmt should add a path to the directory as a prefix since RealPath passed from libsyntax is a full path. --- src/config/config_type.rs | 6 +++++- src/config/mod.rs | 9 +++++---- src/ignore_path.rs | 10 +++++++--- src/test/mod.rs | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 40da2986808..7c4298dcf1c 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -141,7 +141,7 @@ macro_rules! create_config { ConfigWasSet(self) } - fn fill_from_parsed_config(mut self, parsed: PartialConfig) -> Config { + fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config { $( if let Some(val) = parsed.$i { if self.$i.3 { @@ -160,6 +160,7 @@ macro_rules! create_config { )+ self.set_heuristics(); self.set_license_template(); + self.set_ignore(dir); self } @@ -286,6 +287,9 @@ macro_rules! create_config { } } + fn set_ignore(&mut self, dir: &Path) { + self.ignore.2.add_prefix(dir); + } /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { diff --git a/src/config/mod.rs b/src/config/mod.rs index 839e9bb6e21..c0221e93e02 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -190,7 +190,8 @@ impl Config { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; - Config::from_toml(&toml).map_err(|err| Error::new(ErrorKind::InvalidData, err)) + Config::from_toml(&toml, file_path.parent().unwrap()) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolves the config for input in `dir`. @@ -252,7 +253,7 @@ impl Config { } } - pub(crate) fn from_toml(toml: &str) -> Result { + pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { let parsed: ::toml::Value = toml .parse() .map_err(|e| format!("Could not parse TOML: {}", e))?; @@ -271,7 +272,7 @@ impl Config { if !err.is_empty() { eprint!("{}", err); } - Ok(Config::default().fill_from_parsed_config(parsed_config)) + Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -425,7 +426,7 @@ mod test { #[test] fn test_was_set() { - let config = Config::from_toml("hard_tabs = true").unwrap(); + let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap(); assert_eq!(config.was_set().hard_tabs(), true); assert_eq!(config.was_set().verbose(), false); diff --git a/src/ignore_path.rs b/src/ignore_path.rs index 6299aedf4a7..b0ebef62170 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -1,6 +1,7 @@ -use ignore::{self, gitignore}; use std::path::PathBuf; +use ignore::{self, gitignore}; + use crate::config::{FileName, IgnoreList}; pub struct IgnorePathSet { @@ -33,16 +34,19 @@ impl IgnorePathSet { #[cfg(test)] mod test { + use std::path::{Path, PathBuf}; + use crate::config::{Config, FileName}; use crate::ignore_path::IgnorePathSet; - use std::path::PathBuf; #[test] fn test_ignore_path_set() { match option_env!("CFG_RELEASE_CHANNEL") { // this test requires nightly None | Some("nightly") => { - let config = Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#).unwrap(); + let config = + Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")) + .unwrap(); let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap(); assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs")))); diff --git a/src/test/mod.rs b/src/test/mod.rs index c084742a217..6766ba2af54 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -564,7 +564,7 @@ fn get_config(config_file: Option<&Path>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config).expect("invalid TOML") + Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML") } // Reads significant comments of the form: `// rustfmt-key: value` into a hash map. -- cgit 1.4.1-3-g733a5 From af3e940940706a1001e5eeaffd760633a84d350e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 23 Apr 2019 08:50:59 +0900 Subject: Attempt to format attributes if only they exist --- src/imports.rs | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index f6b41deaef9..08647dee490 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -242,30 +242,31 @@ impl UseTree { format!("{}use {};", vis, s) } })?; - if let Some(ref attrs) = self.attrs { - let attr_str = attrs.rewrite(context, shape)?; - let lo = attrs.last().as_ref()?.span().hi(); - let hi = self.span.lo(); - let span = mk_sp(lo, hi); - - let allow_extend = if attrs.len() == 1 { - let line_len = attr_str.len() + 1 + use_str.len(); - !attrs.first().unwrap().is_sugared_doc - && context.config.inline_attribute_width() >= line_len - } else { - false - }; + match self.attrs { + Some(ref attrs) if !attrs.is_empty() => { + let attr_str = attrs.rewrite(context, shape)?; + let lo = attrs.last().as_ref()?.span().hi(); + let hi = self.span.lo(); + let span = mk_sp(lo, hi); + + let allow_extend = if attrs.len() == 1 { + let line_len = attr_str.len() + 1 + use_str.len(); + !attrs.first().unwrap().is_sugared_doc + && context.config.inline_attribute_width() >= line_len + } else { + false + }; - combine_strs_with_missing_comments( - context, - &attr_str, - &use_str, - span, - shape, - allow_extend, - ) - } else { - Some(use_str) + combine_strs_with_missing_comments( + context, + &attr_str, + &use_str, + span, + shape, + allow_extend, + ) + } + _ => Some(use_str), } } -- cgit 1.4.1-3-g733a5 From 05547d90b51a089e789ba29be5b2e11099235709 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Wed, 24 Apr 2019 08:21:04 +0900 Subject: leave the comment in parentheses of argumentless Fn (#3518) --- src/source_map.rs | 12 ++++++ src/types.rs | 101 ++++++++++++++++++++++++++++----------------- tests/source/issue-3508.rs | 29 +++++++++++++ tests/target/issue-3508.rs | 22 ++++++++++ 4 files changed, 127 insertions(+), 37 deletions(-) create mode 100644 tests/source/issue-3508.rs create mode 100644 tests/target/issue-3508.rs (limited to 'src') diff --git a/src/source_map.rs b/src/source_map.rs index 9cc9cb857b1..db4796eb08e 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -11,6 +11,7 @@ pub trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; fn span_after_last(&self, original: Span, needle: &str) -> BytePos; fn span_before(&self, original: Span, needle: &str) -> BytePos; + fn span_before_last(&self, original: Span, needle: &str) -> BytePos; fn opt_span_after(&self, original: Span, needle: &str) -> Option; fn opt_span_before(&self, original: Span, needle: &str) -> Option; } @@ -56,6 +57,17 @@ impl<'a> SpanUtils for SnippetProvider<'a> { }) } + fn span_before_last(&self, original: Span, needle: &str) -> BytePos { + let snippet = self.span_to_snippet(original).unwrap(); + let mut offset = 0; + + while let Some(additional_offset) = snippet[offset..].find_uncommented(needle) { + offset += additional_offset + needle.len(); + } + + original.lo() + BytePos(offset as u32 - 1) + } + fn opt_span_after(&self, original: Span, needle: &str) -> Option { self.opt_span_before(original, needle) .map(|bytepos| bytepos + BytePos(needle.len() as u32)) diff --git a/src/types.rs b/src/types.rs index 8ed73b99913..f939aeae35d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,7 +8,9 @@ use syntax::symbol::keywords; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity}; use crate::expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +}; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; use crate::pairs::{rewrite_pair, PairParts}; @@ -314,47 +316,56 @@ where let offset = shape.indent + 1; Shape::legacy(budget, offset) }; + let list_lo = context.snippet_provider.span_after(span, "("); - let items = itemize_list( - context.snippet_provider, - inputs, - ")", - ",", - |arg| arg.span().lo(), - |arg| arg.span().hi(), - |arg| arg.rewrite(context, list_shape), - list_lo, - span.hi(), - false, - ); + let (list_str, tactic) = if inputs.len() == 0 { + let tactic = get_tactics(&[], &output, shape); + let list_hi = context.snippet_provider.span_before_last(span, ")"); + let comment = context + .snippet_provider + .span_to_snippet(mk_sp(list_lo, list_hi))? + .trim(); + let comment = if comment.starts_with("//") { + format!( + "{}{}{}", + &list_shape.indent.to_string_with_newline(context.config), + comment, + &shape.block().indent.to_string_with_newline(context.config) + ) + } else { + comment.to_string() + }; + (comment, tactic) + } else { + let items = itemize_list( + context.snippet_provider, + inputs, + ")", + ",", + |arg| arg.span().lo(), + |arg| arg.span().hi(), + |arg| arg.rewrite(context, list_shape), + list_lo, + span.hi(), + false, + ); - let item_vec: Vec<_> = items.collect(); + let item_vec: Vec<_> = items.collect(); + let tactic = get_tactics(&item_vec, &output, shape); + let trailing_separator = if !context.use_block_indent() || variadic { + SeparatorTactic::Never + } else { + context.config.trailing_comma() + }; - // If the return type is multi-lined, then force to use multiple lines for - // arguments as well. - let tactic = if output.contains('\n') { - DefinitiveListTactic::Vertical - } else { - definitive_tactic( - &*item_vec, - ListTactic::HorizontalVertical, - Separator::Comma, - shape.width.saturating_sub(2 + output.len()), - ) - }; - let trailing_separator = if !context.use_block_indent() || variadic { - SeparatorTactic::Never - } else { - context.config.trailing_comma() + let fmt = ListFormatting::new(list_shape, context.config) + .tactic(tactic) + .trailing_separator(trailing_separator) + .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) + .preserve_newline(true); + (write_list(&item_vec, &fmt)?, tactic) }; - let fmt = ListFormatting::new(list_shape, context.config) - .tactic(tactic) - .trailing_separator(trailing_separator) - .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) - .preserve_newline(true); - let list_str = write_list(&item_vec, &fmt)?; - let args = if tactic == DefinitiveListTactic::Horizontal || !context.use_block_indent() { format!("({})", list_str) } else { @@ -381,6 +392,22 @@ fn type_bound_colon(context: &RewriteContext<'_>) -> &'static str { colon_spaces(context.config) } +// If the return type is multi-lined, then force to use multiple lines for +// arguments as well. +fn get_tactics(item_vec: &[ListItem], output: &str, shape: Shape) -> DefinitiveListTactic { + if output.contains('\n') { + DefinitiveListTactic::Vertical + } else { + definitive_tactic( + item_vec, + ListTactic::HorizontalVertical, + Separator::Comma, + // 2 is for the case of ',\n' + shape.width.saturating_sub(2 + output.len()), + ) + } +} + impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { // FIXME: dead spans? diff --git a/tests/source/issue-3508.rs b/tests/source/issue-3508.rs new file mode 100644 index 00000000000..821e947c707 --- /dev/null +++ b/tests/source/issue-3508.rs @@ -0,0 +1,29 @@ +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted +), +{ +} + +fn foo_block(foo2: F) +where + F: Fn( + /* this comment is deleted */ + ), +{ +} + +fn bar( + bar2: impl Fn( + // this comment is deleted + ), +) { +} + +fn bar_block( + bar2: impl Fn( + /* this comment is deleted */ + ), +) { +} diff --git a/tests/target/issue-3508.rs b/tests/target/issue-3508.rs new file mode 100644 index 00000000000..5f4e156582d --- /dev/null +++ b/tests/target/issue-3508.rs @@ -0,0 +1,22 @@ +fn foo(foo2: F) +where + F: Fn( + // this comment is deleted + ), +{ +} + +fn foo_block(foo2: F) +where + F: Fn(/* this comment is deleted */), +{ +} + +fn bar( + bar2: impl Fn( + // this comment is deleted + ), +) { +} + +fn bar_block(bar2: impl Fn(/* this comment is deleted */)) {} -- cgit 1.4.1-3-g733a5 From a20ffc6d52e741341d98eca4a4502faae66d1dc4 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 24 Apr 2019 20:22:35 +0900 Subject: Add a path to rustfmt.toml to GitIgnore as root path --- src/config/options.rs | 64 ++++++++++++++++++++++++++++++++++++++------------- src/ignore_path.rs | 4 +--- 2 files changed, 49 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index bd8c5056854..bded90b8693 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,7 +1,9 @@ use std::collections::{hash_set, HashSet}; +use std::fmt; use std::path::{Path, PathBuf}; use atty; +use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; use crate::config::config_type::ConfigType; use crate::config::lists::*; @@ -396,33 +398,63 @@ impl Default for EmitMode { } /// A set of directories, files and modules that rustfmt should ignore. -#[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)] -pub struct IgnoreList(HashSet); +#[derive(Default, Serialize, Clone, Debug, PartialEq)] +pub struct IgnoreList { + /// A set of path specified in rustfmt.toml. + #[serde(flatten)] + path_set: HashSet, + /// A path to rustfmt.toml. + #[serde(skip_serializing)] + rustfmt_toml_path: PathBuf, +} + +impl<'de> Deserialize<'de> for IgnoreList { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct HashSetVisitor; + impl<'v> Visitor<'v> for HashSetVisitor { + type Value = HashSet; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a sequence of path") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'v>, + { + let mut path_set = HashSet::new(); + while let Some(elem) = seq.next_element()? { + path_set.insert(elem); + } + Ok(path_set) + } + } + Ok(IgnoreList { + path_set: deserializer.deserialize_seq(HashSetVisitor)?, + rustfmt_toml_path: PathBuf::new(), + }) + } +} impl<'a> IntoIterator for &'a IgnoreList { type Item = &'a PathBuf; type IntoIter = hash_set::Iter<'a, PathBuf>; fn into_iter(self) -> Self::IntoIter { - self.0.iter() + self.path_set.iter() } } impl IgnoreList { pub fn add_prefix(&mut self, dir: &Path) { - self.0 = self - .0 - .iter() - .map(|s| { - if s.has_root() { - s.clone() - } else { - let mut path = PathBuf::from(dir); - path.push(s); - path - } - }) - .collect(); + self.rustfmt_toml_path = dir.to_path_buf(); + } + + pub fn rustfmt_toml_path(&self) -> &Path { + &self.rustfmt_toml_path } } diff --git a/src/ignore_path.rs b/src/ignore_path.rs index b0ebef62170..844ea427f49 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -1,5 +1,3 @@ -use std::path::PathBuf; - use ignore::{self, gitignore}; use crate::config::{FileName, IgnoreList}; @@ -10,7 +8,7 @@ pub struct IgnorePathSet { impl IgnorePathSet { pub fn from_ignore_list(ignore_list: &IgnoreList) -> Result { - let mut ignore_builder = gitignore::GitignoreBuilder::new(PathBuf::from("")); + let mut ignore_builder = gitignore::GitignoreBuilder::new(ignore_list.rustfmt_toml_path()); for ignore_path in ignore_list { ignore_builder.add_line(None, ignore_path.to_str().unwrap())?; -- cgit 1.4.1-3-g733a5 From f520f7e0f8e2046f431315b7fdd5ca14531ffa8e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 24 Apr 2019 20:23:02 +0900 Subject: Suppress spurious parse error messages on skipped files --- src/formatting.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 47ff9021c97..9776359bef3 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -67,6 +67,14 @@ fn format_project( let main_file = input.file_name(); let input_is_stdin = main_file == FileName::Stdin; + let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { + Ok(set) => set, + Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), + }; + if config.skip_children() && ignore_path_set.is_match(&main_file) { + return Ok(FormatReport::new()); + } + // Parse the crate. let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let mut parse_session = make_parse_sess(source_map.clone(), config); @@ -91,11 +99,6 @@ fn format_project( parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); - let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(set) => set, - Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), - }; - let files = modules::ModResolver::new( context.parse_session.source_map(), directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(false)), -- cgit 1.4.1-3-g733a5 From ba5b2e9c9be3c0cd90bed4d675fb09dc6aa1789a Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 19:40:21 +0200 Subject: Extract applying of newline style into own mod --- src/config/options.rs | 112 -------------------------------------- src/formatting.rs | 2 + src/formatting/newline_style.rs | 118 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 112 deletions(-) create mode 100644 src/formatting/newline_style.rs (limited to 'src') diff --git a/src/config/options.rs b/src/config/options.rs index bded90b8693..dc5d0a47a33 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -132,62 +132,6 @@ configuration_option_enum! { NewlineStyle: Native, // \r\n in Windows, \n on other platforms } -impl NewlineStyle { - fn auto_detect(raw_input_text: &str) -> NewlineStyle { - if let Some(pos) = raw_input_text.find('\n') { - let pos = pos.saturating_sub(1); - if let Some('\r') = raw_input_text.chars().nth(pos) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } else { - NewlineStyle::Native - } - } - - fn native() -> NewlineStyle { - if cfg!(windows) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix - } - } - - /// Apply this newline style to the formatted text. When the style is set - /// to `Auto`, the `raw_input_text` is used to detect the existing line - /// endings. - /// - /// If the style is set to `Auto` and `raw_input_text` contains no - /// newlines, the `Native` style will be used. - pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { - use crate::NewlineStyle::*; - let mut style = self; - if style == Auto { - style = Self::auto_detect(raw_input_text); - } - if style == Native { - style = Self::native(); - } - match style { - Windows => { - let mut transformed = String::with_capacity(2 * formatted_text.capacity()); - for c in formatted_text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } - } - *formatted_text = transformed; - } - Unix => return, - Native => unreachable!("NewlineStyle::Native"), - Auto => unreachable!("NewlineStyle::Auto"), - } - } -} - configuration_option_enum! { BraceStyle: AlwaysNextLine, PreferSameLine, @@ -493,59 +437,3 @@ impl Edition { } } } - -#[test] -fn test_newline_style_auto_detect() { - let lf = "One\nTwo\nThree"; - let crlf = "One\r\nTwo\r\nThree"; - let none = "One Two Three"; - - assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf)); - assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf)); - assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none)); -} - -#[test] -fn test_newline_style_auto_apply() { - let auto = NewlineStyle::Auto; - - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One\nTwo\nThree"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); - - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One\r\nTwo\r\nThree"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); - - #[cfg(not(windows))] - { - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One Two Three"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!( - "One\nTwo\nThree", &out, - "auto-native-unix should detect 'lf'" - ); - } - - #[cfg(windows)] - { - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One Two Three"; - - let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); - assert_eq!( - "One\r\nTwo\r\nThree", &out, - "auto-native-windows should detect 'crlf'" - ); - } -} diff --git a/src/formatting.rs b/src/formatting.rs index 9776359bef3..e4875d7df4c 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -20,6 +20,8 @@ use crate::utils::{count_newlines, get_skip_macro_names}; use crate::visitor::{FmtVisitor, SnippetProvider}; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; +mod newline_style; + // A map of the files of a crate, with their new content pub(crate) type SourceFile = Vec; pub(crate) type FileRecord = (FileName, String); diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs new file mode 100644 index 00000000000..3cf66f83ed6 --- /dev/null +++ b/src/formatting/newline_style.rs @@ -0,0 +1,118 @@ +use crate::NewlineStyle; + +impl NewlineStyle { + fn auto_detect(raw_input_text: &str) -> NewlineStyle { + if let Some(pos) = raw_input_text.find('\n') { + let pos = pos.saturating_sub(1); + if let Some('\r') = raw_input_text.chars().nth(pos) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } else { + NewlineStyle::Native + } + } + + fn native() -> NewlineStyle { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix + } + } + + /// Apply this newline style to the formatted text. When the style is set + /// to `Auto`, the `raw_input_text` is used to detect the existing line + /// endings. + /// + /// If the style is set to `Auto` and `raw_input_text` contains no + /// newlines, the `Native` style will be used. + pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { + use crate::NewlineStyle::*; + let mut style = self; + if style == Auto { + style = Self::auto_detect(raw_input_text); + } + if style == Native { + style = Self::native(); + } + match style { + Windows => { + let mut transformed = String::with_capacity(2 * formatted_text.capacity()); + for c in formatted_text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } + } + *formatted_text = transformed; + } + Unix => return, + Native => unreachable!("NewlineStyle::Native"), + Auto => unreachable!("NewlineStyle::Auto"), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_newline_style_auto_detect() { + let lf = "One\nTwo\nThree"; + let crlf = "One\r\nTwo\r\nThree"; + let none = "One Two Three"; + + assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf)); + assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf)); + assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none)); + } + + #[test] + fn test_newline_style_auto_apply() { + let auto = NewlineStyle::Auto; + + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One\nTwo\nThree"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); + + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One\r\nTwo\r\nThree"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); + + #[cfg(not(windows))] + { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!( + "One\nTwo\nThree", &out, + "auto-native-unix should detect 'lf'" + ); + } + + #[cfg(windows)] + { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; + + let mut out = String::from(formatted_text); + auto.apply(&mut out, raw_input_text); + assert_eq!( + "One\r\nTwo\r\nThree", &out, + "auto-native-windows should detect 'crlf'" + ); + } + } +} -- cgit 1.4.1-3-g733a5 From 8849273efb890e767d7bfa610f6e5040583a6545 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 19:45:11 +0200 Subject: Convert to free standing functions --- src/formatting.rs | 10 ++-- src/formatting/newline_style.rs | 102 ++++++++++++++++++++-------------------- 2 files changed, 59 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index e4875d7df4c..3ae73ea1c99 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -12,6 +12,7 @@ use syntax::errors::{DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; +use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::ignore_path::IgnorePathSet; @@ -193,9 +194,12 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &self.config, &self.report, ); - self.config - .newline_style() - .apply(&mut visitor.buffer, &big_snippet); + + apply_newline_style( + self.config.newline_style(), + &mut visitor.buffer, + &big_snippet, + ); if visitor.macro_rewrite_failure { self.report.add_macro_format_failure(); diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 3cf66f83ed6..91d8466bb9d 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -1,58 +1,60 @@ use crate::NewlineStyle; -impl NewlineStyle { - fn auto_detect(raw_input_text: &str) -> NewlineStyle { - if let Some(pos) = raw_input_text.find('\n') { - let pos = pos.saturating_sub(1); - if let Some('\r') = raw_input_text.chars().nth(pos) { - NewlineStyle::Windows - } else { - NewlineStyle::Unix +/// Apply this newline style to the formatted text. When the style is set +/// to `Auto`, the `raw_input_text` is used to detect the existing line +/// endings. +/// +/// If the style is set to `Auto` and `raw_input_text` contains no +/// newlines, the `Native` style will be used. +pub(crate) fn apply_newline_style( + newline_style: NewlineStyle, + formatted_text: &mut String, + raw_input_text: &str, +) { + use crate::NewlineStyle::*; + let mut style = newline_style; + if style == Auto { + style = auto_detect_newline_style(raw_input_text); + } + if style == Native { + style = native(); + } + match style { + Windows => { + let mut transformed = String::with_capacity(2 * formatted_text.capacity()); + for c in formatted_text.chars() { + match c { + '\n' => transformed.push_str("\r\n"), + '\r' => continue, + c => transformed.push(c), + } } - } else { - NewlineStyle::Native + *formatted_text = transformed; } + Unix => return, + Native => unreachable!("NewlineStyle::Native"), + Auto => unreachable!("NewlineStyle::Auto"), } +} - fn native() -> NewlineStyle { - if cfg!(windows) { +fn auto_detect_newline_style(raw_input_text: &str) -> NewlineStyle { + if let Some(pos) = raw_input_text.find('\n') { + let pos = pos.saturating_sub(1); + if let Some('\r') = raw_input_text.chars().nth(pos) { NewlineStyle::Windows } else { NewlineStyle::Unix } + } else { + NewlineStyle::Native } +} - /// Apply this newline style to the formatted text. When the style is set - /// to `Auto`, the `raw_input_text` is used to detect the existing line - /// endings. - /// - /// If the style is set to `Auto` and `raw_input_text` contains no - /// newlines, the `Native` style will be used. - pub(crate) fn apply(self, formatted_text: &mut String, raw_input_text: &str) { - use crate::NewlineStyle::*; - let mut style = self; - if style == Auto { - style = Self::auto_detect(raw_input_text); - } - if style == Native { - style = Self::native(); - } - match style { - Windows => { - let mut transformed = String::with_capacity(2 * formatted_text.capacity()); - for c in formatted_text.chars() { - match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, - c => transformed.push(c), - } - } - *formatted_text = transformed; - } - Unix => return, - Native => unreachable!("NewlineStyle::Native"), - Auto => unreachable!("NewlineStyle::Auto"), - } +fn native() -> NewlineStyle { + if cfg!(windows) { + NewlineStyle::Windows + } else { + NewlineStyle::Unix } } @@ -66,9 +68,9 @@ mod tests { let crlf = "One\r\nTwo\r\nThree"; let none = "One Two Three"; - assert_eq!(NewlineStyle::Unix, NewlineStyle::auto_detect(lf)); - assert_eq!(NewlineStyle::Windows, NewlineStyle::auto_detect(crlf)); - assert_eq!(NewlineStyle::Native, NewlineStyle::auto_detect(none)); + assert_eq!(NewlineStyle::Unix, auto_detect_newline_style(lf)); + assert_eq!(NewlineStyle::Windows, auto_detect_newline_style(crlf)); + assert_eq!(NewlineStyle::Native, auto_detect_newline_style(none)); } #[test] @@ -79,14 +81,14 @@ mod tests { let raw_input_text = "One\nTwo\nThree"; let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); + apply_newline_style(auto, &mut out, raw_input_text); assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); let formatted_text = "One\nTwo\nThree"; let raw_input_text = "One\r\nTwo\r\nThree"; let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); + apply_newline_style(auto, &mut out, raw_input_text); assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); #[cfg(not(windows))] @@ -95,7 +97,7 @@ mod tests { let raw_input_text = "One Two Three"; let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); + apply_newline_style(auto, &mut out, raw_input_text); assert_eq!( "One\nTwo\nThree", &out, "auto-native-unix should detect 'lf'" @@ -108,7 +110,7 @@ mod tests { let raw_input_text = "One Two Three"; let mut out = String::from(formatted_text); - auto.apply(&mut out, raw_input_text); + apply_newline_style(auto, &mut out, raw_input_text); assert_eq!( "One\r\nTwo\r\nThree", &out, "auto-native-windows should detect 'crlf'" -- cgit 1.4.1-3-g733a5 From add473667a480b67862cde7a90901dae5173beae Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 19:47:05 +0200 Subject: Introduce effective newline style --- src/formatting/newline_style.rs | 65 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 91d8466bb9d..354d6d31ee6 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -11,16 +11,8 @@ pub(crate) fn apply_newline_style( formatted_text: &mut String, raw_input_text: &str, ) { - use crate::NewlineStyle::*; - let mut style = newline_style; - if style == Auto { - style = auto_detect_newline_style(raw_input_text); - } - if style == Native { - style = native(); - } - match style { - Windows => { + match effective_newline_style(newline_style, raw_input_text) { + EffectiveNewlineStyle::Windows => { let mut transformed = String::with_capacity(2 * formatted_text.capacity()); for c in formatted_text.chars() { match c { @@ -31,30 +23,46 @@ pub(crate) fn apply_newline_style( } *formatted_text = transformed; } - Unix => return, - Native => unreachable!("NewlineStyle::Native"), - Auto => unreachable!("NewlineStyle::Auto"), + EffectiveNewlineStyle::Unix => {} + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum EffectiveNewlineStyle { + Windows, + Unix, +} + +fn effective_newline_style( + newline_style: NewlineStyle, + raw_input_text: &str, +) -> EffectiveNewlineStyle { + match newline_style { + NewlineStyle::Auto => auto_detect_newline_style(raw_input_text), + NewlineStyle::Native => native_newline_style(), + NewlineStyle::Windows => EffectiveNewlineStyle::Windows, + NewlineStyle::Unix => EffectiveNewlineStyle::Unix, } } -fn auto_detect_newline_style(raw_input_text: &str) -> NewlineStyle { +fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle { if let Some(pos) = raw_input_text.find('\n') { let pos = pos.saturating_sub(1); if let Some('\r') = raw_input_text.chars().nth(pos) { - NewlineStyle::Windows + EffectiveNewlineStyle::Windows } else { - NewlineStyle::Unix + EffectiveNewlineStyle::Unix } } else { - NewlineStyle::Native + native_newline_style() } } -fn native() -> NewlineStyle { +fn native_newline_style() -> EffectiveNewlineStyle { if cfg!(windows) { - NewlineStyle::Windows + EffectiveNewlineStyle::Windows } else { - NewlineStyle::Unix + EffectiveNewlineStyle::Unix } } @@ -68,9 +76,20 @@ mod tests { let crlf = "One\r\nTwo\r\nThree"; let none = "One Two Three"; - assert_eq!(NewlineStyle::Unix, auto_detect_newline_style(lf)); - assert_eq!(NewlineStyle::Windows, auto_detect_newline_style(crlf)); - assert_eq!(NewlineStyle::Native, auto_detect_newline_style(none)); + assert_eq!(EffectiveNewlineStyle::Unix, auto_detect_newline_style(lf)); + assert_eq!( + EffectiveNewlineStyle::Windows, + auto_detect_newline_style(crlf) + ); + + if cfg!(windows) { + assert_eq!( + EffectiveNewlineStyle::Windows, + auto_detect_newline_style(none) + ); + } else { + assert_eq!(EffectiveNewlineStyle::Unix, auto_detect_newline_style(none)); + } } #[test] -- cgit 1.4.1-3-g733a5 From 58d7b2cc66235198b1a08b001da699da42926494 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 19:34:10 +0200 Subject: Extract literals into constants --- src/formatting/newline_style.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 354d6d31ee6..5a90c1f2aaa 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -11,13 +11,15 @@ pub(crate) fn apply_newline_style( formatted_text: &mut String, raw_input_text: &str, ) { + const WINDOWS_NEWLINE: &str = "\r\n"; + match effective_newline_style(newline_style, raw_input_text) { EffectiveNewlineStyle::Windows => { let mut transformed = String::with_capacity(2 * formatted_text.capacity()); for c in formatted_text.chars() { match c { - '\n' => transformed.push_str("\r\n"), - '\r' => continue, + LINE_FEED => transformed.push_str(WINDOWS_NEWLINE), + CARRIAGE_RETURN => continue, c => transformed.push(c), } } @@ -27,6 +29,9 @@ pub(crate) fn apply_newline_style( } } +const LINE_FEED: char = '\n'; +const CARRIAGE_RETURN: char = '\r'; + #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum EffectiveNewlineStyle { Windows, @@ -46,9 +51,9 @@ fn effective_newline_style( } fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle { - if let Some(pos) = raw_input_text.find('\n') { + if let Some(pos) = raw_input_text.find(LINE_FEED) { let pos = pos.saturating_sub(1); - if let Some('\r') = raw_input_text.chars().nth(pos) { + if let Some(CARRIAGE_RETURN) = raw_input_text.chars().nth(pos) { EffectiveNewlineStyle::Windows } else { EffectiveNewlineStyle::Unix -- cgit 1.4.1-3-g733a5 From 764cdf60fafe3f8866c75935c381fbf8bcc7f485 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 19:54:37 +0200 Subject: Extract conversion to windows newlines into fn --- src/formatting/newline_style.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 5a90c1f2aaa..e86fbeb75fa 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -11,27 +11,14 @@ pub(crate) fn apply_newline_style( formatted_text: &mut String, raw_input_text: &str, ) { - const WINDOWS_NEWLINE: &str = "\r\n"; - match effective_newline_style(newline_style, raw_input_text) { EffectiveNewlineStyle::Windows => { - let mut transformed = String::with_capacity(2 * formatted_text.capacity()); - for c in formatted_text.chars() { - match c { - LINE_FEED => transformed.push_str(WINDOWS_NEWLINE), - CARRIAGE_RETURN => continue, - c => transformed.push(c), - } - } - *formatted_text = transformed; + *formatted_text = convert_to_windows_newlines(formatted_text); } EffectiveNewlineStyle::Unix => {} } } -const LINE_FEED: char = '\n'; -const CARRIAGE_RETURN: char = '\r'; - #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum EffectiveNewlineStyle { Windows, @@ -50,6 +37,9 @@ fn effective_newline_style( } } +const LINE_FEED: char = '\n'; +const CARRIAGE_RETURN: char = '\r'; + fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle { if let Some(pos) = raw_input_text.find(LINE_FEED) { let pos = pos.saturating_sub(1); @@ -71,6 +61,19 @@ fn native_newline_style() -> EffectiveNewlineStyle { } } +fn convert_to_windows_newlines(formatted_text: &String) -> String { + let mut transformed = String::with_capacity(2 * formatted_text.capacity()); + for c in formatted_text.chars() { + const WINDOWS_NEWLINE: &str = "\r\n"; + match c { + LINE_FEED => transformed.push_str(WINDOWS_NEWLINE), + CARRIAGE_RETURN => continue, + c => transformed.push(c), + } + } + transformed +} + #[cfg(test)] mod tests { use super::*; -- cgit 1.4.1-3-g733a5 From 20c8d8aabc74b2b045f96afcade2383796019ff4 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 20:01:06 +0200 Subject: Split auto_detect tests into seperate fns --- src/formatting/newline_style.rs | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index e86fbeb75fa..dc80715044f 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -79,25 +79,32 @@ mod tests { use super::*; #[test] - fn test_newline_style_auto_detect() { - let lf = "One\nTwo\nThree"; - let crlf = "One\r\nTwo\r\nThree"; - let none = "One Two Three"; + fn auto_detects_unix_newlines() { + assert_eq!( + EffectiveNewlineStyle::Unix, + auto_detect_newline_style("One\nTwo\nThree") + ); + } - assert_eq!(EffectiveNewlineStyle::Unix, auto_detect_newline_style(lf)); + #[test] + fn auto_detects_windows_newlines() { assert_eq!( EffectiveNewlineStyle::Windows, - auto_detect_newline_style(crlf) + auto_detect_newline_style("One\r\nTwo\r\nThree") ); + } - if cfg!(windows) { - assert_eq!( - EffectiveNewlineStyle::Windows, - auto_detect_newline_style(none) - ); + #[test] + fn falls_back_to_native_newlines_if_no_newlines_are_found() { + let expected_newline_style = if cfg!(windows) { + EffectiveNewlineStyle::Windows } else { - assert_eq!(EffectiveNewlineStyle::Unix, auto_detect_newline_style(none)); - } + EffectiveNewlineStyle::Unix + }; + assert_eq!( + expected_newline_style, + auto_detect_newline_style("One Two Three") + ); } #[test] -- cgit 1.4.1-3-g733a5 From 0f1d5760ba5ea2d2831002bbed50306a3d6ee535 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 20:14:29 +0200 Subject: Fix auto detection of windows newlines for inputs with multibyte chars --- src/formatting/newline_style.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index dc80715044f..f95413db025 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -41,7 +41,7 @@ const LINE_FEED: char = '\n'; const CARRIAGE_RETURN: char = '\r'; fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle { - if let Some(pos) = raw_input_text.find(LINE_FEED) { + if let Some(pos) = raw_input_text.chars().position(|ch| ch == LINE_FEED) { let pos = pos.saturating_sub(1); if let Some(CARRIAGE_RETURN) = raw_input_text.chars().nth(pos) { EffectiveNewlineStyle::Windows @@ -94,6 +94,14 @@ mod tests { ); } + #[test] + fn auto_detects_windows_newlines_with_multibyte_char_on_first_line() { + assert_eq!( + EffectiveNewlineStyle::Windows, + auto_detect_newline_style("A 🎢 of a first line\r\nTwo\r\nThree") + ); + } + #[test] fn falls_back_to_native_newlines_if_no_newlines_are_found() { let expected_newline_style = if cfg!(windows) { -- cgit 1.4.1-3-g733a5 From 2e77f2bca7a7f740fbccca97a9112b690a3aa555 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 20:28:14 +0200 Subject: Split apply with auto detection tests into separate fns --- src/formatting/newline_style.rs | 42 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index f95413db025..f5eb2e43d88 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -116,47 +116,43 @@ mod tests { } #[test] - fn test_newline_style_auto_apply() { - let auto = NewlineStyle::Auto; - + fn auto_detects_and_applies_unix_newlines() { let formatted_text = "One\nTwo\nThree"; let raw_input_text = "One\nTwo\nThree"; let mut out = String::from(formatted_text); - apply_newline_style(auto, &mut out, raw_input_text); + apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text); assert_eq!("One\nTwo\nThree", &out, "auto should detect 'lf'"); + } + #[test] + fn auto_detects_and_applies_windows_newlines() { let formatted_text = "One\nTwo\nThree"; let raw_input_text = "One\r\nTwo\r\nThree"; let mut out = String::from(formatted_text); - apply_newline_style(auto, &mut out, raw_input_text); + apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text); assert_eq!("One\r\nTwo\r\nThree", &out, "auto should detect 'crlf'"); + } - #[cfg(not(windows))] - { - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One Two Three"; - - let mut out = String::from(formatted_text); - apply_newline_style(auto, &mut out, raw_input_text); - assert_eq!( - "One\nTwo\nThree", &out, - "auto-native-unix should detect 'lf'" - ); - } + #[test] + fn auto_detects_and_applies_native_newlines() { + let formatted_text = "One\nTwo\nThree"; + let raw_input_text = "One Two Three"; - #[cfg(windows)] - { - let formatted_text = "One\nTwo\nThree"; - let raw_input_text = "One Two Three"; + let mut out = String::from(formatted_text); + apply_newline_style(NewlineStyle::Auto, &mut out, raw_input_text); - let mut out = String::from(formatted_text); - apply_newline_style(auto, &mut out, raw_input_text); + if cfg!(windows) { assert_eq!( "One\r\nTwo\r\nThree", &out, "auto-native-windows should detect 'crlf'" ); + } else { + assert_eq!( + "One\nTwo\nThree", &out, + "auto-native-unix should detect 'lf'" + ); } } } -- cgit 1.4.1-3-g733a5 From 19bd1a44cebb3cbab7c1a9bf8486ea3458a03aef Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 20:52:43 +0200 Subject: Preserve standalone carriage returns on windows also --- src/formatting/newline_style.rs | 23 +++++++++++++++++++++- tests/source/preserves_carriage_return_for_unix.rs | 2 ++ .../preserves_carriage_return_for_windows.rs | 2 ++ tests/target/preserves_carriage_return_for_unix.rs | 2 ++ .../preserves_carriage_return_for_windows.rs | 2 ++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/source/preserves_carriage_return_for_unix.rs create mode 100644 tests/source/preserves_carriage_return_for_windows.rs create mode 100644 tests/target/preserves_carriage_return_for_unix.rs create mode 100644 tests/target/preserves_carriage_return_for_windows.rs (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index f5eb2e43d88..1813ccad35a 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -67,7 +67,6 @@ fn convert_to_windows_newlines(formatted_text: &String) -> String { const WINDOWS_NEWLINE: &str = "\r\n"; match c { LINE_FEED => transformed.push_str(WINDOWS_NEWLINE), - CARRIAGE_RETURN => continue, c => transformed.push(c), } } @@ -155,4 +154,26 @@ mod tests { ); } } + + #[test] + fn preserves_standalone_carriage_returns_when_applying_windows_newlines() { + let formatted_text = "One\nTwo\nThree\rDrei"; + let raw_input_text = "One\nTwo\nThree\rDrei"; + + let mut out = String::from(formatted_text); + apply_newline_style(NewlineStyle::Windows, &mut out, raw_input_text); + + assert_eq!("One\r\nTwo\r\nThree\rDrei", &out); + } + + #[test] + fn preserves_standalone_carriage_returns_when_applying_unix_newlines() { + let formatted_text = "One\nTwo\nThree\rDrei"; + let raw_input_text = "One\nTwo\nThree\rDrei"; + + let mut out = String::from(formatted_text); + apply_newline_style(NewlineStyle::Unix, &mut out, raw_input_text); + + assert_eq!("One\nTwo\nThree\rDrei", &out); + } } diff --git a/tests/source/preserves_carriage_return_for_unix.rs b/tests/source/preserves_carriage_return_for_unix.rs new file mode 100644 index 00000000000..e5e0b286598 --- /dev/null +++ b/tests/source/preserves_carriage_return_for_unix.rs @@ -0,0 +1,2 @@ +// rustfmt-newline_style: Unix +// Foo Bar diff --git a/tests/source/preserves_carriage_return_for_windows.rs b/tests/source/preserves_carriage_return_for_windows.rs new file mode 100644 index 00000000000..1085360ee59 --- /dev/null +++ b/tests/source/preserves_carriage_return_for_windows.rs @@ -0,0 +1,2 @@ +// rustfmt-newline_style: Windows +// Foo Bar diff --git a/tests/target/preserves_carriage_return_for_unix.rs b/tests/target/preserves_carriage_return_for_unix.rs new file mode 100644 index 00000000000..e5e0b286598 --- /dev/null +++ b/tests/target/preserves_carriage_return_for_unix.rs @@ -0,0 +1,2 @@ +// rustfmt-newline_style: Unix +// Foo Bar diff --git a/tests/target/preserves_carriage_return_for_windows.rs b/tests/target/preserves_carriage_return_for_windows.rs new file mode 100644 index 00000000000..1085360ee59 --- /dev/null +++ b/tests/target/preserves_carriage_return_for_windows.rs @@ -0,0 +1,2 @@ +// rustfmt-newline_style: Windows +// Foo Bar -- cgit 1.4.1-3-g733a5 From 7556c420ab48867c04afc973a1bc5062def8ea5f Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 24 Apr 2019 21:58:50 +0200 Subject: Use more descriptive names --- src/formatting/newline_style.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 1813ccad35a..7d64441bd04 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -41,15 +41,17 @@ const LINE_FEED: char = '\n'; const CARRIAGE_RETURN: char = '\r'; fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle { - if let Some(pos) = raw_input_text.chars().position(|ch| ch == LINE_FEED) { - let pos = pos.saturating_sub(1); - if let Some(CARRIAGE_RETURN) = raw_input_text.chars().nth(pos) { - EffectiveNewlineStyle::Windows - } else { - EffectiveNewlineStyle::Unix + let first_line_feed_pos = raw_input_text.chars().position(|ch| ch == LINE_FEED); + match first_line_feed_pos { + Some(first_line_feed_pos) => { + let char_before_line_feed_pos = first_line_feed_pos.saturating_sub(1); + let char_before_line_feed = raw_input_text.chars().nth(char_before_line_feed_pos); + match char_before_line_feed { + Some(CARRIAGE_RETURN) => EffectiveNewlineStyle::Windows, + _ => EffectiveNewlineStyle::Unix, + } } - } else { - native_newline_style() + None => native_newline_style(), } } -- cgit 1.4.1-3-g733a5 From 20bdb2fb9dd11f1313edfbe0a0c94904beaca19f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 31 Mar 2019 18:44:35 +0900 Subject: Use config_type proc macro --- Cargo.lock | 4 +- src/config/lists.rs | 15 ++--- src/config/options.rs | 171 +++++++++++--------------------------------------- 3 files changed, 43 insertions(+), 147 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 0ed465c66fe..dd148264be3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,8 +148,8 @@ name = "config_proc_macro" version = "0.1.0" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/src/config/lists.rs b/src/config/lists.rs index 79fd3db5b6e..86faab57d16 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -1,6 +1,7 @@ //! Configuration options related to rewriting a list. -use crate::config::config_type::ConfigType; +use config_proc_macro::config_type; + use crate::config::IndentStyle; /// The definitive formatting tactic for lists. @@ -25,7 +26,7 @@ impl DefinitiveListTactic { /// Formatting tactic for lists. This will be cast down to a /// `DefinitiveListTactic` depending on the number and length of the items and /// their comments. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[config_type] pub enum ListTactic { // One item per row. Vertical, @@ -39,17 +40,13 @@ pub enum ListTactic { Mixed, } -impl_enum_serialize_and_deserialize!(ListTactic, Vertical, Horizontal, HorizontalVertical, Mixed); - -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[config_type] pub enum SeparatorTactic { Always, Never, Vertical, } -impl_enum_serialize_and_deserialize!(SeparatorTactic, Always, Never, Vertical); - impl SeparatorTactic { pub fn from_bool(b: bool) -> SeparatorTactic { if b { @@ -61,14 +58,12 @@ impl SeparatorTactic { } /// Where to put separator. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[config_type] pub enum SeparatorPlace { Front, Back, } -impl_enum_serialize_and_deserialize!(SeparatorPlace, Front, Back); - impl SeparatorPlace { pub fn is_front(self) -> bool { self == SeparatorPlace::Front diff --git a/src/config/options.rs b/src/config/options.rs index bded90b8693..e8a26a4aeea 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -3,133 +3,18 @@ use std::fmt; use std::path::{Path, PathBuf}; use atty; +use config_proc_macro::config_type; use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; -use crate::config::config_type::ConfigType; use crate::config::lists::*; use crate::config::Config; -/// Macro that will stringify the enum variants or a provided textual repr -#[macro_export] -macro_rules! configuration_option_enum_stringify { - ($variant:ident) => { - stringify!($variant) - }; - - ($_variant:ident: $value:expr) => { - stringify!($value) - }; -} - -/// Macro for deriving implementations of Serialize/Deserialize for enums -#[macro_export] -macro_rules! impl_enum_serialize_and_deserialize { - ( $e:ident, $( $variant:ident $(: $value:expr)* ),* ) => { - impl ::serde::ser::Serialize for $e { - fn serialize(&self, serializer: S) -> Result - where S: ::serde::ser::Serializer - { - use serde::ser::Error; - - // We don't know whether the user of the macro has given us all options. - #[allow(unreachable_patterns)] - match *self { - $( - $e::$variant => serializer.serialize_str( - configuration_option_enum_stringify!($variant $(: $value)*) - ), - )* - _ => { - Err(S::Error::custom(format!("Cannot serialize {:?}", self))) - } - } - } - } - - impl<'de> ::serde::de::Deserialize<'de> for $e { - fn deserialize(d: D) -> Result - where D: ::serde::Deserializer<'de> { - use serde::de::{Error, Visitor}; - use std::marker::PhantomData; - use std::fmt; - struct StringOnly(PhantomData); - impl<'de, T> Visitor<'de> for StringOnly - where T: ::serde::Deserializer<'de> { - type Value = String; - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("string") - } - fn visit_str(self, value: &str) -> Result { - Ok(String::from(value)) - } - } - let s = d.deserialize_string(StringOnly::(PhantomData))?; - $( - if configuration_option_enum_stringify!($variant $(: $value)*) - .eq_ignore_ascii_case(&s) { - return Ok($e::$variant); - } - )* - static ALLOWED: &'static[&str] = &[ - $(configuration_option_enum_stringify!($variant $(: $value)*),)*]; - Err(D::Error::unknown_variant(&s, ALLOWED)) - } - } - - impl ::std::str::FromStr for $e { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - $( - if configuration_option_enum_stringify!($variant $(: $value)*) - .eq_ignore_ascii_case(s) { - return Ok($e::$variant); - } - )* - Err("Bad variant") - } - } - - impl ConfigType for $e { - fn doc_hint() -> String { - let mut variants = Vec::new(); - $( - variants.push( - configuration_option_enum_stringify!($variant $(: $value)*) - ); - )* - format!("[{}]", variants.join("|")) - } - } - }; -} - -macro_rules! configuration_option_enum { - ($e:ident: $( $name:ident $(: $value:expr)* ),+ $(,)*) => ( - #[derive(Copy, Clone, Eq, PartialEq)] - pub enum $e { - $( $name ),+ - } - - impl ::std::fmt::Debug for $e { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - f.write_str(match self { - $( - $e::$name => configuration_option_enum_stringify!($name $(: $value)*), - )+ - }) - } - } - - impl_enum_serialize_and_deserialize!($e, $( $name $(: $value)* ),+); - ); -} - -configuration_option_enum! { NewlineStyle: - Auto, // Auto-detect based on the raw source input +#[config_type] +pub enum NewlineStyle { + Auto, // Auto-detect based on the raw source input Windows, // \r\n - Unix, // \n - Native, // \r\n in Windows, \n on other platforms + Unix, // \n + Native, // \r\n in Windows, \n on other platforms } impl NewlineStyle { @@ -188,7 +73,8 @@ impl NewlineStyle { } } -configuration_option_enum! { BraceStyle: +#[config_type] +pub enum BraceStyle { AlwaysNextLine, PreferSameLine, // Prefer same line except where there is a where-clause, in which case force @@ -196,7 +82,8 @@ configuration_option_enum! { BraceStyle: SameLineWhere, } -configuration_option_enum! { ControlBraceStyle: +#[config_type] +pub enum ControlBraceStyle { // K&R style, Rust community default AlwaysSameLine, // Stroustrup style @@ -205,7 +92,8 @@ configuration_option_enum! { ControlBraceStyle: AlwaysNextLine, } -configuration_option_enum! { IndentStyle: +#[config_type] +pub enum IndentStyle { // First line on the same line as the opening brace, all lines aligned with // the first line. Visual, @@ -213,7 +101,8 @@ configuration_option_enum! { IndentStyle: Block, } -configuration_option_enum! { Density: +#[config_type] +pub enum Density { // Fit as much on one line as possible. Compressed, // Use more lines. @@ -222,14 +111,16 @@ configuration_option_enum! { Density: Vertical, } -configuration_option_enum! { TypeDensity: +#[config_type] +pub enum TypeDensity { // No spaces around "=" and "+" Compressed, // Spaces around " = " and " + " Wide, } -configuration_option_enum! { Heuristics: +#[config_type] +pub enum Heuristics { // Turn off any heuristics Off, // Turn on max heuristics @@ -249,7 +140,8 @@ impl Density { } } -configuration_option_enum! { ReportTactic: +#[config_type] +pub enum ReportTactic { Always, Unnumbered, Never, @@ -257,7 +149,8 @@ configuration_option_enum! { ReportTactic: // What Rustfmt should emit. Mostly corresponds to the `--emit` command line // option. -configuration_option_enum! { EmitMode: +#[config_type] +pub enum EmitMode { // Emits to files. Files, // Writes the output to stdout. @@ -275,7 +168,8 @@ configuration_option_enum! { EmitMode: } // Client-preference for coloured output. -configuration_option_enum! { Color: +#[config_type] +pub enum Color { // Always use color, whether it is a piped or terminal output Always, // Never use color @@ -284,7 +178,8 @@ configuration_option_enum! { Color: Auto, } -configuration_option_enum! { Version: +#[config_type] +pub enum Version { // 1.x.y One, // 2.x.y @@ -303,7 +198,8 @@ impl Color { } // How chatty should Rustfmt be? -configuration_option_enum! { Verbosity: +#[config_type] +pub enum Verbosity { // Emit more. Verbose, Normal, @@ -474,9 +370,14 @@ pub trait CliOptions { } // The edition of the compiler (RFC 2052) -configuration_option_enum! { Edition: - Edition2015: 2015, - Edition2018: 2018, +#[config_type] +pub enum Edition { + #[value = "2015"] + #[doc_hint = "2015"] + Edition2015, + #[value = "2018"] + #[doc_hint = "2018"] + Edition2018, } impl Default for Edition { -- cgit 1.4.1-3-g733a5 From 3dec18a681c7ff4eef2d4eb5e62c0278b6110e22 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 31 Mar 2019 19:13:15 +0900 Subject: Add doc comment --- config_proc_macro/src/attrs.rs | 16 ++++++ config_proc_macro/src/config_type.rs | 2 + config_proc_macro/src/item_enum.rs | 1 + src/config/lists.rs | 10 ++-- src/config/options.rs | 97 +++++++++++++++++++++--------------- 5 files changed, 81 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index cd0a701479b..0df68772ae6 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -1,23 +1,39 @@ +//! This module provides utilities for handling attributes on variants +//! of `config_type` enum. Currently there are two types of attributes +//! that could appear on the variants of `config_type` enum: `doc_hint` +//! and `value`. Both comes in the form of name-value pair whose value +//! is string literal. + +/// Returns the value of the first `doc_hint` attribute in the given slice or +/// `None` if `doc_hint` attribute is not available. pub fn find_doc_hint(attrs: &[syn::Attribute]) -> Option { attrs.iter().filter_map(doc_hint).next() } +/// Returns `true` if the given attribute is a `doc_hint` attribute. pub fn is_doc_hint(attr: &syn::Attribute) -> bool { is_attr_name_value(attr, "doc_hint") } +/// Returns a string literal value if the given attribute is `doc_hint` +/// attribute or `None` otherwise. pub fn doc_hint(attr: &syn::Attribute) -> Option { get_name_value_str_lit(attr, "doc_hint") } +/// Returns the value of the first `value` attribute in the given slice or +/// `None` if `value` attribute is not available. pub fn find_config_value(attrs: &[syn::Attribute]) -> Option { attrs.iter().filter_map(config_value).next() } +/// Returns a string literal value if the given attribute is `value` +/// attribute or `None` otherwise. pub fn config_value(attr: &syn::Attribute) -> Option { get_name_value_str_lit(attr, "value") } +/// Returns `true` if the given attribute is a `value` attribute. pub fn is_config_value(attr: &syn::Attribute) -> bool { is_attr_name_value(attr, "value") } diff --git a/config_proc_macro/src/config_type.rs b/config_proc_macro/src/config_type.rs index daff3f5c61c..93a78b8463e 100644 --- a/config_proc_macro/src/config_type.rs +++ b/config_proc_macro/src/config_type.rs @@ -3,6 +3,8 @@ use proc_macro2::TokenStream; use crate::item_enum::define_config_type_on_enum; use crate::item_struct::define_config_type_on_struct; +/// Defines `config_type` on enum or struct. +// FIXME: Implement this on struct. pub fn define_config_type(input: &syn::Item) -> TokenStream { match input { syn::Item::Struct(st) => define_config_type_on_struct(st), diff --git a/config_proc_macro/src/item_enum.rs b/config_proc_macro/src/item_enum.rs index acb00a99cb4..eb7254ada7a 100644 --- a/config_proc_macro/src/item_enum.rs +++ b/config_proc_macro/src/item_enum.rs @@ -6,6 +6,7 @@ use crate::utils::*; type Variants = syn::punctuated::Punctuated; +/// Defines and implements `config_type` enum. pub fn define_config_type_on_enum(em: &syn::ItemEnum) -> syn::Result { let syn::ItemEnum { vis, diff --git a/src/config/lists.rs b/src/config/lists.rs index 86faab57d16..0270bd0eb0b 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -28,15 +28,15 @@ impl DefinitiveListTactic { /// their comments. #[config_type] pub enum ListTactic { - // One item per row. + /// One item per row. Vertical, - // All items on one row. + /// All items on one row. Horizontal, - // Try Horizontal layout, if that fails then vertical. + /// Try Horizontal layout, if that fails then vertical. HorizontalVertical, - // HorizontalVertical with a soft limit of n characters. + /// HorizontalVertical with a soft limit of n characters. LimitedHorizontalVertical(usize), - // Pack as many items as possible per row over (possibly) many rows. + /// Pack as many items as possible per row over (possibly) many rows. Mixed, } diff --git a/src/config/options.rs b/src/config/options.rs index e8a26a4aeea..9b0060bfdb6 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -11,10 +11,14 @@ use crate::config::Config; #[config_type] pub enum NewlineStyle { - Auto, // Auto-detect based on the raw source input - Windows, // \r\n - Unix, // \n - Native, // \r\n in Windows, \n on other platforms + /// Auto-detect based on the raw source input. + Auto, + /// Force CRLF (`\r\n`). + Windows, + /// Force CR (`\n). + Unix, + /// `\r\n` in Windows, `\n`` on other platforms. + Native, } impl NewlineStyle { @@ -74,58 +78,66 @@ impl NewlineStyle { } #[config_type] +/// Where to put the opening brace of items (`fn`, `impl`, etc.). pub enum BraceStyle { + /// Put the opening brace on the next line. AlwaysNextLine, + /// Put the opening brace on the same line, if possible. PreferSameLine, - // Prefer same line except where there is a where-clause, in which case force - // the brace to the next line. + /// Prefer the same line except where there is a where-clause, in which + /// case force the brace to be put on the next line. SameLineWhere, } #[config_type] +/// Where to put the opening brace of conditional expressions (`if`, `match`, etc.). pub enum ControlBraceStyle { - // K&R style, Rust community default + /// K&R style, Rust community default AlwaysSameLine, - // Stroustrup style + /// Stroustrup style ClosingNextLine, - // Allman style + /// Allman style AlwaysNextLine, } #[config_type] +/// How to indent. pub enum IndentStyle { - // First line on the same line as the opening brace, all lines aligned with - // the first line. + /// First line on the same line as the opening brace, all lines aligned with + /// the first line. Visual, - // First line is on a new line and all lines align with block indent. + /// First line is on a new line and all lines align with **block** indent. Block, } #[config_type] +/// How to place a list-like items. pub enum Density { - // Fit as much on one line as possible. + /// Fit as much on one line as possible. Compressed, - // Use more lines. + /// Use more lines. Tall, - // Place every item on a separate line. + /// Place every item on a separate line. Vertical, } #[config_type] +/// Spacing around type combinators. pub enum TypeDensity { - // No spaces around "=" and "+" + /// No spaces around "=" and "+" Compressed, - // Spaces around " = " and " + " + /// Spaces around " = " and " + " Wide, } #[config_type] +/// To what extent does rustfmt pursue its heuristics? pub enum Heuristics { - // Turn off any heuristics + /// Turn off any heuristics Off, - // Turn on max heuristics + /// Turn on max heuristics Max, - // Use Rustfmt's defaults + /// Use Rustfmt's defaults Default, } @@ -147,42 +159,44 @@ pub enum ReportTactic { Never, } -// What Rustfmt should emit. Mostly corresponds to the `--emit` command line -// option. +/// What Rustfmt should emit. Mostly corresponds to the `--emit` command line +/// option. #[config_type] pub enum EmitMode { - // Emits to files. + /// Emits to files. Files, - // Writes the output to stdout. + /// Writes the output to stdout. Stdout, - // Displays how much of the input file was processed + /// Displays how much of the input file was processed Coverage, - // Unfancy stdout + /// Unfancy stdout Checkstyle, - // Output the changed lines (for internal value only) + /// Output the changed lines (for internal value only) ModifiedLines, - // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1. - // This option is designed to be run in CI where a non-zero exit signifies non-standard code - // formatting. Used for `--check`. + /// Checks if a diff can be generated. If so, rustfmt outputs a diff and + /// quits with exit code 1. + /// This option is designed to be run in CI where a non-zero exit signifies + /// non-standard code formatting. Used for `--check`. Diff, } -// Client-preference for coloured output. +/// Client-preference for coloured output. #[config_type] pub enum Color { - // Always use color, whether it is a piped or terminal output + /// Always use color, whether it is a piped or terminal output Always, - // Never use color + /// Never use color Never, - // Automatically use color, if supported by terminal + /// Automatically use color, if supported by terminal Auto, } #[config_type] +/// rustfmt format style version. pub enum Version { - // 1.x.y + /// 1.x.y. When specified, rustfmt will format in the same style as 1.0.0. One, - // 2.x.y + /// 2.x.y. When specified, rustfmt will formatin the the latest style. Two, } @@ -197,13 +211,14 @@ impl Color { } } -// How chatty should Rustfmt be? +/// How chatty should Rustfmt be? #[config_type] pub enum Verbosity { - // Emit more. + /// Emit more. Verbose, + /// Default. Normal, - // Emit as little as possible. + /// Emit as little as possible. Quiet, } @@ -369,14 +384,16 @@ pub trait CliOptions { fn config_path(&self) -> Option<&Path>; } -// The edition of the compiler (RFC 2052) +/// The edition of the syntax and semntics of code (RFC 2052). #[config_type] pub enum Edition { #[value = "2015"] #[doc_hint = "2015"] + /// Edition 2015. Edition2015, #[value = "2018"] #[doc_hint = "2018"] + /// Edition 2018. Edition2018, } -- cgit 1.4.1-3-g733a5 From 2c58b205d5f30d313e1ed36885355a97adc6c5b6 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Mon, 29 Apr 2019 21:38:38 +0900 Subject: fix Comma in comment causes no formatting --- src/lists.rs | 2 +- tests/source/issue-3532.rs | 7 +++++++ tests/target/issue-3532.rs | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-3532.rs create mode 100644 tests/target/issue-3532.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index ffb92d3a83c..97592f893a5 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -612,7 +612,7 @@ pub fn extract_post_comment( post_snippet[1..].trim_matches(white_space) } else if post_snippet.starts_with(separator) { post_snippet[separator.len()..].trim_matches(white_space) - } else if post_snippet.ends_with(',') { + } else if post_snippet.ends_with(',') && !post_snippet.trim().starts_with("//") { post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) } else { post_snippet diff --git a/tests/source/issue-3532.rs b/tests/source/issue-3532.rs new file mode 100644 index 00000000000..ec0c01610cd --- /dev/null +++ b/tests/source/issue-3532.rs @@ -0,0 +1,7 @@ +fn foo(a: T) { + match a { +1 => {} + 0 => {} + // _ => panic!("doesn't format!"), + } +} diff --git a/tests/target/issue-3532.rs b/tests/target/issue-3532.rs new file mode 100644 index 00000000000..f41902620cd --- /dev/null +++ b/tests/target/issue-3532.rs @@ -0,0 +1,6 @@ +fn foo(a: T) { + match a { + 1 => {} + 0 => {} // _ => panic!("doesn't format!"), + } +} -- cgit 1.4.1-3-g733a5 From 3300bb22a5a42ee5d6c768b2f192c4ac33abad67 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Thu, 2 May 2019 21:11:13 +0800 Subject: Isolate format_doc_comment with normalize_comments and wrap_comments. --- src/comment.rs | 13 ++++++++++--- tests/source/issue-2520.rs | 1 + tests/source/issue-2523.rs | 1 + tests/source/issue-3055/original.rs | 1 + tests/source/itemized-blocks/no_wrap.rs | 1 + tests/source/itemized-blocks/wrap.rs | 1 + tests/target/issue-2520.rs | 1 + tests/target/issue-2523.rs | 1 + tests/target/issue-3055/original.rs | 1 + tests/target/itemized-blocks/no_wrap.rs | 1 + tests/target/itemized-blocks/wrap.rs | 1 + .../wrap_comments_should_not_imply_format_doc_comments.rs | 1 - 12 files changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 797f75fc580..b8dcae23521 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -656,9 +656,16 @@ impl<'a> CommentRewrite<'a> { _ => { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - match crate::format_code_block(&self.code_block_buffer, &config) { - Some(ref s) => trim_custom_comment_prefix(&s.snippet), - None => trim_custom_comment_prefix(&self.code_block_buffer), + if config.format_doc_comments() { + if let Some(s) = + crate::format_code_block(&self.code_block_buffer, &config) + { + trim_custom_comment_prefix(&s.snippet) + } else { + trim_custom_comment_prefix(&self.code_block_buffer) + } + } else { + trim_custom_comment_prefix(&self.code_block_buffer) } } }; diff --git a/tests/source/issue-2520.rs b/tests/source/issue-2520.rs index d8ecf1f7d69..9ea522c4fe4 100644 --- a/tests/source/issue-2520.rs +++ b/tests/source/issue-2520.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_doc_comments: true //! ```rust //! println!( "hello, world" ); diff --git a/tests/source/issue-2523.rs b/tests/source/issue-2523.rs index 693d06e131a..71aed6ac535 100644 --- a/tests/source/issue-2523.rs +++ b/tests/source/issue-2523.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/source/issue-3055/original.rs b/tests/source/issue-3055/original.rs index 1f7d33ac5ae..eaf00afa3d3 100644 --- a/tests/source/issue-3055/original.rs +++ b/tests/source/issue-3055/original.rs @@ -1,4 +1,5 @@ // rustfmt-wrap_comments: true +// rustfmt-format_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc commodo ultricies dui. /// diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs index 6354d39eb96..a0c546ad18e 100644 --- a/tests/source/itemized-blocks/no_wrap.rs +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs index 61448dce852..14fc8daa2e9 100644 --- a/tests/source/itemized-blocks/wrap.rs +++ b/tests/source/itemized-blocks/wrap.rs @@ -1,4 +1,5 @@ // rustfmt-wrap_comments: true +// rustfmt-format_doc_comments: true // rustfmt-max_width: 50 //! This is a list: diff --git a/tests/target/issue-2520.rs b/tests/target/issue-2520.rs index 012921f441c..7d22b2b665a 100644 --- a/tests/target/issue-2520.rs +++ b/tests/target/issue-2520.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_doc_comments: true //! ```rust //! println!("hello, world"); diff --git a/tests/target/issue-2523.rs b/tests/target/issue-2523.rs index c62e058cde6..c0118e53780 100644 --- a/tests/target/issue-2523.rs +++ b/tests/target/issue-2523.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/target/issue-3055/original.rs b/tests/target/issue-3055/original.rs index 1455ac1a916..1fb35d50682 100644 --- a/tests/target/issue-3055/original.rs +++ b/tests/target/issue-3055/original.rs @@ -1,4 +1,5 @@ // rustfmt-wrap_comments: true +// rustfmt-format_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc /// commodo ultricies dui. diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs index 945c3fbbca0..a1f9c39a115 100644 --- a/tests/target/itemized-blocks/no_wrap.rs +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -1,4 +1,5 @@ // rustfmt-normalize_comments: true +// rustfmt-format_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index 0a21c474ca6..967a38b91ae 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -1,4 +1,5 @@ // rustfmt-wrap_comments: true +// rustfmt-format_doc_comments: true // rustfmt-max_width: 50 //! This is a list: diff --git a/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs b/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs index a316179f820..d61d4d7c216 100644 --- a/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs +++ b/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs @@ -8,7 +8,6 @@ /// # #![cfg_attr(not(dox), no_std)] /// fn foo() { } /// ``` -/// fn foo() {} /// A long commment for wrapping -- cgit 1.4.1-3-g733a5 From 7a93a26aad24ebbdab28906316ccbc6371becd5d Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Mon, 6 May 2019 00:01:13 +0900 Subject: correct to get wrong BytePos --- src/types.rs | 2 +- tests/target/issue-3539.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-3539.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index f939aeae35d..55367805ca3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -320,7 +320,7 @@ where let list_lo = context.snippet_provider.span_after(span, "("); let (list_str, tactic) = if inputs.len() == 0 { let tactic = get_tactics(&[], &output, shape); - let list_hi = context.snippet_provider.span_before_last(span, ")"); + let list_hi = context.snippet_provider.span_before(span, ")"); let comment = context .snippet_provider .span_to_snippet(mk_sp(list_lo, list_hi))? diff --git a/tests/target/issue-3539.rs b/tests/target/issue-3539.rs new file mode 100644 index 00000000000..aa2fa72ece3 --- /dev/null +++ b/tests/target/issue-3539.rs @@ -0,0 +1,8 @@ +use std::io::Error; + +fn main() { + let _read_num: fn() -> Result<(i32), Error> = || -> Result<(i32), Error> { + let a = 1; + Ok(a) + }; +} -- cgit 1.4.1-3-g733a5 From bfe5e9c108bff11eff00643b1d19b6665e43283e Mon Sep 17 00:00:00 2001 From: David Alber Date: Sun, 5 May 2019 11:55:11 -0700 Subject: Fix condition typo --- src/test/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 6766ba2af54..23f6a69b8d1 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -810,7 +810,7 @@ impl ConfigCodeBlock { fn get_block_config(&self) -> Config { let mut config = Config::default(); - if self.config_value.is_some() && self.config_value.is_some() { + if self.config_name.is_some() && self.config_value.is_some() { config.override_value( self.config_name.as_ref().unwrap(), self.config_value.as_ref().unwrap(), -- cgit 1.4.1-3-g733a5 From 6a6924c12b2ad9a99686df9b3d65fd2dd8647665 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Mon, 6 May 2019 19:45:34 +0800 Subject: Change config option from format_doc_comments to format_code_in_doc_comments. --- Configurations.md | 4 ++-- src/comment.rs | 4 ++-- src/config/mod.rs | 2 +- tests/source/doc-comment-with-example.rs | 2 +- tests/source/invalid-rust-code-in-doc-comment.rs | 2 +- tests/source/issue-2520.rs | 2 +- tests/source/issue-2523.rs | 2 +- tests/source/issue-3055/original.rs | 2 +- tests/source/itemized-blocks/no_wrap.rs | 2 +- tests/source/itemized-blocks/wrap.rs | 2 +- tests/target/doc-comment-with-example.rs | 2 +- tests/target/invalid-rust-code-in-doc-comment.rs | 2 +- tests/target/issue-2520.rs | 2 +- tests/target/issue-2523.rs | 2 +- tests/target/issue-3055/original.rs | 2 +- tests/target/itemized-blocks/no_wrap.rs | 2 +- tests/target/itemized-blocks/wrap.rs | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 7557b3637f1..dc91a3d255a 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1978,9 +1978,9 @@ fn main() { } ``` -## `format_doc_comments` +## `format_code_in_doc_comments` -Format doc comments. +Format code snippet included in doc comments. - **Default value**: `false` - **Possible values**: `true`, `false` diff --git a/src/comment.rs b/src/comment.rs index b8dcae23521..0a3062583c5 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -353,7 +353,7 @@ fn identify_comment( trim_left_preserve_layout(first_group, shape.indent, config)? } else if !config.normalize_comments() && !config.wrap_comments() - && !config.format_doc_comments() + && !config.format_code_in_doc_comments() { light_rewrite_comment(first_group, shape.indent, config, is_doc_comment) } else { @@ -656,7 +656,7 @@ impl<'a> CommentRewrite<'a> { _ => { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - if config.format_doc_comments() { + if config.format_code_in_doc_comments() { if let Some(s) = crate::format_code_block(&self.code_block_buffer, &config) { diff --git a/src/config/mod.rs b/src/config/mod.rs index c0221e93e02..f04074e4f32 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -37,7 +37,7 @@ create_config! { // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; - format_doc_comments: bool, false, false, "Format doc comments."; + format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments."; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; diff --git a/tests/source/doc-comment-with-example.rs b/tests/source/doc-comment-with-example.rs index 58d98acfa25..e74ceefd195 100644 --- a/tests/source/doc-comment-with-example.rs +++ b/tests/source/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Foo /// diff --git a/tests/source/invalid-rust-code-in-doc-comment.rs b/tests/source/invalid-rust-code-in-doc-comment.rs index 6d33dcfce55..835b0261b76 100644 --- a/tests/source/invalid-rust-code-in-doc-comment.rs +++ b/tests/source/invalid-rust-code-in-doc-comment.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// ```rust /// if (true) { … } diff --git a/tests/source/issue-2520.rs b/tests/source/issue-2520.rs index 9ea522c4fe4..5a23f10430d 100644 --- a/tests/source/issue-2520.rs +++ b/tests/source/issue-2520.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! ```rust //! println!( "hello, world" ); diff --git a/tests/source/issue-2523.rs b/tests/source/issue-2523.rs index 71aed6ac535..491d5c38fc2 100644 --- a/tests/source/issue-2523.rs +++ b/tests/source/issue-2523.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/source/issue-3055/original.rs b/tests/source/issue-3055/original.rs index eaf00afa3d3..ad505547ac0 100644 --- a/tests/source/issue-3055/original.rs +++ b/tests/source/issue-3055/original.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc commodo ultricies dui. /// diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs index a0c546ad18e..a7b6a10a010 100644 --- a/tests/source/itemized-blocks/no_wrap.rs +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs index 14fc8daa2e9..955cc698b79 100644 --- a/tests/source/itemized-blocks/wrap.rs +++ b/tests/source/itemized-blocks/wrap.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 //! This is a list: diff --git a/tests/target/doc-comment-with-example.rs b/tests/target/doc-comment-with-example.rs index bec931d13c7..c5a4e779ea2 100644 --- a/tests/target/doc-comment-with-example.rs +++ b/tests/target/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Foo /// diff --git a/tests/target/invalid-rust-code-in-doc-comment.rs b/tests/target/invalid-rust-code-in-doc-comment.rs index 2593410a418..f8479d4e345 100644 --- a/tests/target/invalid-rust-code-in-doc-comment.rs +++ b/tests/target/invalid-rust-code-in-doc-comment.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// ```rust /// if (true) { … } diff --git a/tests/target/issue-2520.rs b/tests/target/issue-2520.rs index 7d22b2b665a..7c134d3972b 100644 --- a/tests/target/issue-2520.rs +++ b/tests/target/issue-2520.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! ```rust //! println!("hello, world"); diff --git a/tests/target/issue-2523.rs b/tests/target/issue-2523.rs index c0118e53780..612f93249ac 100644 --- a/tests/target/issue-2523.rs +++ b/tests/target/issue-2523.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/target/issue-3055/original.rs b/tests/target/issue-3055/original.rs index 1fb35d50682..de27ccfb344 100644 --- a/tests/target/issue-3055/original.rs +++ b/tests/target/issue-3055/original.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc /// commodo ultricies dui. diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs index a1f9c39a115..de885638272 100644 --- a/tests/target/itemized-blocks/no_wrap.rs +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index 967a38b91ae..a4907303c9e 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 //! This is a list: -- cgit 1.4.1-3-g733a5 From 97d7216cd4ebce511d5707ec5dd8b7b8fe771cba Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Wed, 8 May 2019 16:51:32 +0800 Subject: Revert "Change config option from format_doc_comments to format_code_in_doc_comments." This reverts commit 6a6924c12b2ad9a99686df9b3d65fd2dd8647665. --- Configurations.md | 4 ++-- src/comment.rs | 4 ++-- src/config/mod.rs | 2 +- tests/source/doc-comment-with-example.rs | 2 +- tests/source/invalid-rust-code-in-doc-comment.rs | 2 +- tests/source/issue-2520.rs | 2 +- tests/source/issue-2523.rs | 2 +- tests/source/issue-3055/original.rs | 2 +- tests/source/itemized-blocks/no_wrap.rs | 2 +- tests/source/itemized-blocks/wrap.rs | 2 +- tests/target/doc-comment-with-example.rs | 2 +- tests/target/invalid-rust-code-in-doc-comment.rs | 2 +- tests/target/issue-2520.rs | 2 +- tests/target/issue-2523.rs | 2 +- tests/target/issue-3055/original.rs | 2 +- tests/target/itemized-blocks/no_wrap.rs | 2 +- tests/target/itemized-blocks/wrap.rs | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index dc91a3d255a..7557b3637f1 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1978,9 +1978,9 @@ fn main() { } ``` -## `format_code_in_doc_comments` +## `format_doc_comments` -Format code snippet included in doc comments. +Format doc comments. - **Default value**: `false` - **Possible values**: `true`, `false` diff --git a/src/comment.rs b/src/comment.rs index 0a3062583c5..b8dcae23521 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -353,7 +353,7 @@ fn identify_comment( trim_left_preserve_layout(first_group, shape.indent, config)? } else if !config.normalize_comments() && !config.wrap_comments() - && !config.format_code_in_doc_comments() + && !config.format_doc_comments() { light_rewrite_comment(first_group, shape.indent, config, is_doc_comment) } else { @@ -656,7 +656,7 @@ impl<'a> CommentRewrite<'a> { _ => { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - if config.format_code_in_doc_comments() { + if config.format_doc_comments() { if let Some(s) = crate::format_code_block(&self.code_block_buffer, &config) { diff --git a/src/config/mod.rs b/src/config/mod.rs index f04074e4f32..c0221e93e02 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -37,7 +37,7 @@ create_config! { // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; - format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments."; + format_doc_comments: bool, false, false, "Format doc comments."; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; diff --git a/tests/source/doc-comment-with-example.rs b/tests/source/doc-comment-with-example.rs index e74ceefd195..58d98acfa25 100644 --- a/tests/source/doc-comment-with-example.rs +++ b/tests/source/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true /// Foo /// diff --git a/tests/source/invalid-rust-code-in-doc-comment.rs b/tests/source/invalid-rust-code-in-doc-comment.rs index 835b0261b76..6d33dcfce55 100644 --- a/tests/source/invalid-rust-code-in-doc-comment.rs +++ b/tests/source/invalid-rust-code-in-doc-comment.rs @@ -1,4 +1,4 @@ -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true /// ```rust /// if (true) { … } diff --git a/tests/source/issue-2520.rs b/tests/source/issue-2520.rs index 5a23f10430d..9ea522c4fe4 100644 --- a/tests/source/issue-2520.rs +++ b/tests/source/issue-2520.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true //! ```rust //! println!( "hello, world" ); diff --git a/tests/source/issue-2523.rs b/tests/source/issue-2523.rs index 491d5c38fc2..71aed6ac535 100644 --- a/tests/source/issue-2523.rs +++ b/tests/source/issue-2523.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/source/issue-3055/original.rs b/tests/source/issue-3055/original.rs index ad505547ac0..eaf00afa3d3 100644 --- a/tests/source/issue-3055/original.rs +++ b/tests/source/issue-3055/original.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc commodo ultricies dui. /// diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs index a7b6a10a010..a0c546ad18e 100644 --- a/tests/source/itemized-blocks/no_wrap.rs +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs index 955cc698b79..14fc8daa2e9 100644 --- a/tests/source/itemized-blocks/wrap.rs +++ b/tests/source/itemized-blocks/wrap.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true // rustfmt-max_width: 50 //! This is a list: diff --git a/tests/target/doc-comment-with-example.rs b/tests/target/doc-comment-with-example.rs index c5a4e779ea2..bec931d13c7 100644 --- a/tests/target/doc-comment-with-example.rs +++ b/tests/target/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true /// Foo /// diff --git a/tests/target/invalid-rust-code-in-doc-comment.rs b/tests/target/invalid-rust-code-in-doc-comment.rs index f8479d4e345..2593410a418 100644 --- a/tests/target/invalid-rust-code-in-doc-comment.rs +++ b/tests/target/invalid-rust-code-in-doc-comment.rs @@ -1,4 +1,4 @@ -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true /// ```rust /// if (true) { … } diff --git a/tests/target/issue-2520.rs b/tests/target/issue-2520.rs index 7c134d3972b..7d22b2b665a 100644 --- a/tests/target/issue-2520.rs +++ b/tests/target/issue-2520.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true //! ```rust //! println!("hello, world"); diff --git a/tests/target/issue-2523.rs b/tests/target/issue-2523.rs index 612f93249ac..c0118e53780 100644 --- a/tests/target/issue-2523.rs +++ b/tests/target/issue-2523.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/target/issue-3055/original.rs b/tests/target/issue-3055/original.rs index de27ccfb344..1fb35d50682 100644 --- a/tests/target/issue-3055/original.rs +++ b/tests/target/issue-3055/original.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc /// commodo ultricies dui. diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs index de885638272..a1f9c39a115 100644 --- a/tests/target/itemized-blocks/no_wrap.rs +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index a4907303c9e..967a38b91ae 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_code_in_doc_comments: true +// rustfmt-format_doc_comments: true // rustfmt-max_width: 50 //! This is a list: -- cgit 1.4.1-3-g733a5 From f54fc2f2fc7512292e00a7826ca5d144c359fbe4 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Thu, 9 May 2019 17:22:16 +0200 Subject: Implement conversion to unix newlines --- src/formatting/newline_style.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 7d64441bd04..02aab9b024b 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -11,11 +11,9 @@ pub(crate) fn apply_newline_style( formatted_text: &mut String, raw_input_text: &str, ) { - match effective_newline_style(newline_style, raw_input_text) { - EffectiveNewlineStyle::Windows => { - *formatted_text = convert_to_windows_newlines(formatted_text); - } - EffectiveNewlineStyle::Unix => {} + *formatted_text = match effective_newline_style(newline_style, raw_input_text) { + EffectiveNewlineStyle::Windows => convert_to_windows_newlines(formatted_text), + EffectiveNewlineStyle::Unix => convert_to_unix_newlines(formatted_text), } } @@ -39,6 +37,8 @@ fn effective_newline_style( const LINE_FEED: char = '\n'; const CARRIAGE_RETURN: char = '\r'; +const WINDOWS_NEWLINE: &str = "\r\n"; +const UNIX_NEWLINE: &str = "\n"; fn auto_detect_newline_style(raw_input_text: &str) -> EffectiveNewlineStyle { let first_line_feed_pos = raw_input_text.chars().position(|ch| ch == LINE_FEED); @@ -66,7 +66,6 @@ fn native_newline_style() -> EffectiveNewlineStyle { fn convert_to_windows_newlines(formatted_text: &String) -> String { let mut transformed = String::with_capacity(2 * formatted_text.capacity()); for c in formatted_text.chars() { - const WINDOWS_NEWLINE: &str = "\r\n"; match c { LINE_FEED => transformed.push_str(WINDOWS_NEWLINE), c => transformed.push(c), @@ -75,6 +74,10 @@ fn convert_to_windows_newlines(formatted_text: &String) -> String { transformed } +fn convert_to_unix_newlines(formatted_text: &String) -> String { + formatted_text.replace(WINDOWS_NEWLINE, UNIX_NEWLINE) +} + #[cfg(test)] mod tests { use super::*; @@ -157,6 +160,17 @@ mod tests { } } + #[test] + fn applies_unix_newlines() { + let formatted_text = "One\r\nTwo\nThree"; + let raw_input_text = formatted_text; + + let mut out = String::from(formatted_text); + apply_newline_style(NewlineStyle::Unix, &mut out, raw_input_text); + + assert_eq!("One\nTwo\nThree", &out); + } + #[test] fn preserves_standalone_carriage_returns_when_applying_windows_newlines() { let formatted_text = "One\nTwo\nThree\rDrei"; -- cgit 1.4.1-3-g733a5 From 1f09d94cbbf4b7f3607fcfa3fd0e91d836e3af8e Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Thu, 9 May 2019 17:44:52 +0200 Subject: Make sure windows newlines don't gain an extra carriage return --- src/formatting/newline_style.rs | 74 +++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index 02aab9b024b..d46aabe9761 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -65,10 +65,13 @@ fn native_newline_style() -> EffectiveNewlineStyle { fn convert_to_windows_newlines(formatted_text: &String) -> String { let mut transformed = String::with_capacity(2 * formatted_text.capacity()); - for c in formatted_text.chars() { - match c { + let mut chars = formatted_text.chars().peekable(); + while let Some(current_char) = chars.next() { + let next_char = chars.peek(); + match current_char { LINE_FEED => transformed.push_str(WINDOWS_NEWLINE), - c => transformed.push(c), + CARRIAGE_RETURN if next_char == Some(&LINE_FEED) => {} + current_char => transformed.push(current_char), } } transformed @@ -162,34 +165,63 @@ mod tests { #[test] fn applies_unix_newlines() { - let formatted_text = "One\r\nTwo\nThree"; - let raw_input_text = formatted_text; + test_newlines_are_applied_correctly( + "One\r\nTwo\nThree", + "One\nTwo\nThree", + NewlineStyle::Unix, + ); + } - let mut out = String::from(formatted_text); - apply_newline_style(NewlineStyle::Unix, &mut out, raw_input_text); + #[test] + fn applying_windows_newlines_changes_nothing_for_windows_newlines() { + let formatted_text = "One\r\nTwo\r\nThree"; - assert_eq!("One\nTwo\nThree", &out); + test_newlines_are_applied_correctly(formatted_text, formatted_text, NewlineStyle::Windows); } #[test] - fn preserves_standalone_carriage_returns_when_applying_windows_newlines() { - let formatted_text = "One\nTwo\nThree\rDrei"; - let raw_input_text = "One\nTwo\nThree\rDrei"; - - let mut out = String::from(formatted_text); - apply_newline_style(NewlineStyle::Windows, &mut out, raw_input_text); + fn keeps_carriage_returns_when_applying_windows_newlines_to_str_with_unix_newlines() { + test_newlines_are_applied_correctly( + "One\nTwo\nThree\rDrei", + "One\r\nTwo\r\nThree\rDrei", + NewlineStyle::Windows, + ); + } - assert_eq!("One\r\nTwo\r\nThree\rDrei", &out); + #[test] + fn keeps_carriage_returns_when_applying_unix_newlines_to_str_with_unix_newlines() { + test_newlines_are_applied_correctly( + "One\nTwo\nThree\rDrei", + "One\nTwo\nThree\rDrei", + NewlineStyle::Unix, + ); } #[test] - fn preserves_standalone_carriage_returns_when_applying_unix_newlines() { - let formatted_text = "One\nTwo\nThree\rDrei"; - let raw_input_text = "One\nTwo\nThree\rDrei"; + fn keeps_carriage_returns_when_applying_windows_newlines_to_str_with_windows_newlines() { + test_newlines_are_applied_correctly( + "One\r\nTwo\r\nThree\rDrei", + "One\r\nTwo\r\nThree\rDrei", + NewlineStyle::Windows, + ); + } - let mut out = String::from(formatted_text); - apply_newline_style(NewlineStyle::Unix, &mut out, raw_input_text); + #[test] + fn keeps_carriage_returns_when_applying_unix_newlines_to_str_with_windows_newlines() { + test_newlines_are_applied_correctly( + "One\r\nTwo\r\nThree\rDrei", + "One\nTwo\nThree\rDrei", + NewlineStyle::Unix, + ); + } - assert_eq!("One\nTwo\nThree\rDrei", &out); + fn test_newlines_are_applied_correctly( + input: &str, + expected: &str, + newline_style: NewlineStyle, + ) { + let mut out = String::from(input); + apply_newline_style(newline_style, &mut out, input); + assert_eq!(expected, &out); } } -- cgit 1.4.1-3-g733a5 From 821a370417104c622fe8d952a7fce3384a1dde44 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Thu, 9 May 2019 17:51:02 +0200 Subject: Add tests to cover more edge cases --- src/formatting/newline_style.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/formatting/newline_style.rs b/src/formatting/newline_style.rs index d46aabe9761..ac620094900 100644 --- a/src/formatting/newline_style.rs +++ b/src/formatting/newline_style.rs @@ -172,10 +172,33 @@ mod tests { ); } + #[test] + fn applying_unix_newlines_changes_nothing_for_unix_newlines() { + let formatted_text = "One\nTwo\nThree"; + test_newlines_are_applied_correctly(formatted_text, formatted_text, NewlineStyle::Unix); + } + + #[test] + fn applies_unix_newlines_to_string_with_unix_and_windows_newlines() { + test_newlines_are_applied_correctly( + "One\r\nTwo\r\nThree\nFour", + "One\nTwo\nThree\nFour", + NewlineStyle::Unix, + ); + } + + #[test] + fn applies_windows_newlines_to_string_with_unix_and_windows_newlines() { + test_newlines_are_applied_correctly( + "One\nTwo\nThree\r\nFour", + "One\r\nTwo\r\nThree\r\nFour", + NewlineStyle::Windows, + ); + } + #[test] fn applying_windows_newlines_changes_nothing_for_windows_newlines() { let formatted_text = "One\r\nTwo\r\nThree"; - test_newlines_are_applied_correctly(formatted_text, formatted_text, NewlineStyle::Windows); } -- cgit 1.4.1-3-g733a5 From ee6f686cc9aeadc60090dc72a4cbeab6c3156c5a Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 9 May 2019 13:22:44 -0400 Subject: use `derive` feature over `serde_derive` crate --- Cargo.lock | 4 +++- Cargo.toml | 3 +-- src/config/config_type.rs | 2 ++ src/config/file_lines.rs | 3 +-- src/config/options.rs | 3 ++- src/format-diff/main.rs | 3 +-- src/lib.rs | 2 -- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index dd148264be3..b1e1a4b0226 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -798,7 +798,6 @@ dependencies = [ "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -853,6 +852,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "serde" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" diff --git a/Cargo.toml b/Cargo.toml index ba888db72ab..4e332ec43b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,8 +37,7 @@ generic-simd = ["bytecount/generic-simd"] atty = "0.2" itertools = "0.8" toml = "0.5" -serde = "1.0" -serde_derive = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" unicode-segmentation = "1.0.0" regex = "1.0" diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 7c4298dcf1c..82a19c5898f 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -72,6 +72,8 @@ macro_rules! create_config { use std::collections::HashSet; use std::io::Write; + use serde::{Deserialize, Serialize}; + #[derive(Clone)] pub struct Config { // if a license_template_path has been specified, successfully read, parsed and compiled diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 356861282b1..f52f6dab339 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -5,8 +5,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::{cmp, fmt, iter, str}; -use serde::de::{Deserialize, Deserializer}; -use serde::ser::{self, Serialize, Serializer}; +use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; use syntax::source_map::{self, SourceFile}; diff --git a/src/config/options.rs b/src/config/options.rs index 9b0060bfdb6..c927cffba29 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -4,7 +4,8 @@ use std::path::{Path, PathBuf}; use atty; use config_proc_macro::config_type; -use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; +use serde::de::{SeqAccess, Visitor}; +use serde::{Deserialize, Deserializer, Serialize}; use crate::config::lists::*; use crate::config::Config; diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index a10a04386aa..bf1bd4add97 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -11,8 +11,7 @@ use getopts; #[macro_use] extern crate log; use regex; -#[macro_use] -extern crate serde_derive; +use serde::{Deserialize, Serialize}; use serde_json as json; use std::collections::HashSet; diff --git a/src/lib.rs b/src/lib.rs index 3de9616a2ce..788fa133546 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,8 +7,6 @@ extern crate derive_new; extern crate lazy_static; #[macro_use] extern crate log; -#[macro_use] -extern crate serde_derive; use std::cell::RefCell; use std::collections::HashMap; -- cgit 1.4.1-3-g733a5 From 618d092bf722c15496235b45d1208178b8351c99 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Thu, 9 May 2019 20:37:51 +0200 Subject: Enable unreachable_pub lint --- src/attr.rs | 6 ++-- src/chains.rs | 2 +- src/checkstyle.rs | 6 ++-- src/closures.rs | 6 ++-- src/comment.rs | 64 +++++++++++++++++----------------- src/config/config_type.rs | 17 ++++++++- src/config/license.rs | 8 ++--- src/config/mod.rs | 13 ++++--- src/expr.rs | 68 ++++++++++++++++++++---------------- src/formatting.rs | 2 +- src/ignore_path.rs | 6 ++-- src/imports.rs | 26 ++++++++------ src/issues.rs | 8 ++--- src/items.rs | 89 +++++++++++++++++++++++++---------------------- src/lib.rs | 1 + src/lists.rs | 80 +++++++++++++++++++++--------------------- src/macros.rs | 18 +++++----- src/matches.rs | 14 +++----- src/missed_spans.rs | 6 ++-- src/modules.rs | 6 ++-- src/overflow.rs | 28 +++++++-------- src/patterns.rs | 6 ++-- src/reorder.rs | 2 +- src/rewrite.rs | 32 ++++++++--------- src/rustfmt_diff.rs | 10 +++--- src/shape.rs | 64 +++++++++++++++++----------------- src/source_file.rs | 4 +-- src/source_map.rs | 4 +-- src/spanned.rs | 2 +- src/string.rs | 20 +++++------ src/types.rs | 8 ++--- src/utils.rs | 86 ++++++++++++++++++++++----------------------- src/vertical.rs | 4 +-- src/visitor.rs | 68 +++++++++++++++++++----------------- 34 files changed, 411 insertions(+), 373 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 3379bf2369b..a1f5de37c55 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -15,7 +15,7 @@ use crate::types::{rewrite_path, PathContext}; use crate::utils::{count_newlines, mk_sp}; /// Returns attributes on the given statement. -pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { +pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { match stmt.node { ast::StmtKind::Local(ref local) => &local.attrs, ast::StmtKind::Item(ref item) => &item.attrs, @@ -24,7 +24,7 @@ pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { } } -pub fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { +pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { match stmt.node { ast::StmtKind::Local(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, @@ -37,7 +37,7 @@ pub fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { } /// Returns attributes that are within `outer_span`. -pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { +pub(crate) fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { attrs .iter() .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) diff --git a/src/chains.rs b/src/chains.rs index 5ea3953a2c7..c4941141a64 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -74,7 +74,7 @@ use crate::utils::{ trimmed_last_line_width, wrap_str, }; -pub fn rewrite_chain( +pub(crate) fn rewrite_chain( expr: &ast::Expr, context: &RewriteContext<'_>, shape: Shape, diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 169a3741be4..79c59bb1e8c 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -7,7 +7,7 @@ use crate::rustfmt_diff::{DiffLine, Mismatch}; /// /// Note that emitting checkstyle output is not stable and may removed in a /// future version of Rustfmt. -pub fn header() -> String { +pub(crate) fn header() -> String { let mut xml_heading = String::new(); xml_heading.push_str(""); xml_heading.push_str("\n"); @@ -19,11 +19,11 @@ pub fn header() -> String { /// /// Note that emitting checkstyle output is not stable and may removed in a /// future version of Rustfmt. -pub fn footer() -> String { +pub(crate) fn footer() -> String { "\n".to_owned() } -pub fn output_checkstyle_file( +pub(crate) fn output_checkstyle_file( mut writer: T, filename: &Path, diff: Vec, diff --git a/src/closures.rs b/src/closures.rs index d88b7334034..8a7f47af44b 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -23,7 +23,7 @@ use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; // statement without needing a semi-colon), then adding or removing braces // can change whether it is treated as an expression or statement. -pub fn rewrite_closure( +pub(crate) fn rewrite_closure( capture: ast::CaptureBy, asyncness: ast::IsAsync, movability: ast::Movability, @@ -286,7 +286,7 @@ fn rewrite_closure_fn_decl( // Rewriting closure which is placed at the end of the function call's arg. // Returns `None` if the reformatted closure 'looks bad'. -pub fn rewrite_last_closure( +pub(crate) fn rewrite_last_closure( context: &RewriteContext<'_>, expr: &ast::Expr, shape: Shape, @@ -351,7 +351,7 @@ pub fn rewrite_last_closure( } /// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`. -pub fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool { +pub(crate) fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool { args.iter() .filter_map(OverflowableItem::to_expr) .filter(|expr| match expr.node { diff --git a/src/comment.rs b/src/comment.rs index 797f75fc580..7f7dce1166d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -25,7 +25,7 @@ fn is_custom_comment(comment: &str) -> bool { } #[derive(Copy, Clone, PartialEq, Eq)] -pub enum CommentStyle<'a> { +pub(crate) enum CommentStyle<'a> { DoubleSlash, TripleSlash, Doc, @@ -45,7 +45,7 @@ fn custom_opener(s: &str) -> &str { impl<'a> CommentStyle<'a> { /// Returns `true` if the commenting style covers a line only. - pub fn is_line_comment(&self) -> bool { + pub(crate) fn is_line_comment(&self) -> bool { match *self { CommentStyle::DoubleSlash | CommentStyle::TripleSlash @@ -56,7 +56,7 @@ impl<'a> CommentStyle<'a> { } /// Returns `true` if the commenting style can span over multiple lines. - pub fn is_block_comment(&self) -> bool { + pub(crate) fn is_block_comment(&self) -> bool { match *self { CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation => { true @@ -66,14 +66,14 @@ impl<'a> CommentStyle<'a> { } /// Returns `true` if the commenting style is for documentation. - pub fn is_doc_comment(&self) -> bool { + pub(crate) fn is_doc_comment(&self) -> bool { match *self { CommentStyle::TripleSlash | CommentStyle::Doc => true, _ => false, } } - pub fn opener(&self) -> &'a str { + pub(crate) fn opener(&self) -> &'a str { match *self { CommentStyle::DoubleSlash => "// ", CommentStyle::TripleSlash => "/// ", @@ -85,7 +85,7 @@ impl<'a> CommentStyle<'a> { } } - pub fn closer(&self) -> &'a str { + pub(crate) fn closer(&self) -> &'a str { match *self { CommentStyle::DoubleSlash | CommentStyle::TripleSlash @@ -96,7 +96,7 @@ impl<'a> CommentStyle<'a> { } } - pub fn line_start(&self) -> &'a str { + pub(crate) fn line_start(&self) -> &'a str { match *self { CommentStyle::DoubleSlash => "// ", CommentStyle::TripleSlash => "/// ", @@ -107,7 +107,7 @@ impl<'a> CommentStyle<'a> { } } - pub fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { + pub(crate) fn to_str_tuplet(&self) -> (&'a str, &'a str, &'a str) { (self.opener(), self.closer(), self.line_start()) } } @@ -143,7 +143,7 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> { } /// Returns true if the last line of the passed string finishes with a block-comment. -pub fn is_last_comment_block(s: &str) -> bool { +pub(crate) fn is_last_comment_block(s: &str) -> bool { s.trim_end().ends_with("*/") } @@ -152,7 +152,7 @@ pub fn is_last_comment_block(s: &str) -> bool { /// recovered. If `allow_extend` is true and there is no comment between the two /// strings, then they will be put on a single line as long as doing so does not /// exceed max width. -pub fn combine_strs_with_missing_comments( +pub(crate) fn combine_strs_with_missing_comments( context: &RewriteContext<'_>, prev_str: &str, next_str: &str, @@ -239,11 +239,11 @@ pub fn combine_strs_with_missing_comments( Some(result) } -pub fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { +pub(crate) fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option { identify_comment(orig, false, shape, config, true) } -pub fn rewrite_comment( +pub(crate) fn rewrite_comment( orig: &str, block_style: bool, shape: Shape, @@ -845,7 +845,7 @@ fn has_url(s: &str) -> bool { /// Given the span, rewrite the missing comment inside it if available. /// Note that the given span must only include comments (or leading/trailing whitespaces). -pub fn rewrite_missing_comment( +pub(crate) fn rewrite_missing_comment( span: Span, shape: Shape, context: &RewriteContext<'_>, @@ -862,7 +862,7 @@ pub fn rewrite_missing_comment( /// Recover the missing comments in the specified span, if available. /// The layout of the comments will be preserved as long as it does not break the code /// and its total width does not exceed the max width. -pub fn recover_missing_comment_in_span( +pub(crate) fn recover_missing_comment_in_span( span: Span, shape: Shape, context: &RewriteContext<'_>, @@ -964,7 +964,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s } } -pub trait FindUncommented { +pub(crate) trait FindUncommented { fn find_uncommented(&self, pat: &str) -> Option; } @@ -997,7 +997,7 @@ impl FindUncommented for str { // is expected to be prefixed by a comment, including delimiters. // Good: `/* /* inner */ outer */ code();` // Bad: `code(); // hello\n world!` -pub fn find_comment_end(s: &str) -> Option { +pub(crate) fn find_comment_end(s: &str) -> Option { let mut iter = CharClasses::new(s.char_indices()); for (kind, (i, _c)) in &mut iter { if kind == FullCodeCharKind::Normal || kind == FullCodeCharKind::InString { @@ -1014,11 +1014,11 @@ pub fn find_comment_end(s: &str) -> Option { } /// Returns `true` if text contains any comment. -pub fn contains_comment(text: &str) -> bool { +pub(crate) fn contains_comment(text: &str) -> bool { CharClasses::new(text.chars()).any(|(kind, _)| kind.is_comment()) } -pub struct CharClasses +pub(crate) struct CharClasses where T: Iterator, T::Item: RichChar, @@ -1027,7 +1027,7 @@ where status: CharClassesStatus, } -pub trait RichChar { +pub(crate) trait RichChar { fn get_char(&self) -> char; } @@ -1073,7 +1073,7 @@ enum CharClassesStatus { /// Distinguish between functional part of code and comments #[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum CodeCharKind { +pub(crate) enum CodeCharKind { Normal, Comment, } @@ -1082,7 +1082,7 @@ pub enum CodeCharKind { /// describing opening and closing of comments for ease when chunking /// code from tagged characters #[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum FullCodeCharKind { +pub(crate) enum FullCodeCharKind { Normal, /// The first character of a comment, there is only one for a comment (always '/') StartComment, @@ -1106,7 +1106,7 @@ pub enum FullCodeCharKind { } impl FullCodeCharKind { - pub fn is_comment(self) -> bool { + pub(crate) fn is_comment(self) -> bool { match self { FullCodeCharKind::StartComment | FullCodeCharKind::InComment @@ -1119,7 +1119,7 @@ impl FullCodeCharKind { } /// Returns true if the character is inside a comment - pub fn inside_comment(self) -> bool { + pub(crate) fn inside_comment(self) -> bool { match self { FullCodeCharKind::InComment | FullCodeCharKind::StartStringCommented @@ -1129,12 +1129,12 @@ impl FullCodeCharKind { } } - pub fn is_string(self) -> bool { + pub(crate) fn is_string(self) -> bool { self == FullCodeCharKind::InString || self == FullCodeCharKind::StartString } /// Returns true if the character is within a commented string - pub fn is_commented_string(self) -> bool { + pub(crate) fn is_commented_string(self) -> bool { self == FullCodeCharKind::InStringCommented || self == FullCodeCharKind::StartStringCommented } @@ -1153,7 +1153,7 @@ where T: Iterator, T::Item: RichChar, { - pub fn new(base: T) -> CharClasses { + pub(crate) fn new(base: T) -> CharClasses { CharClasses { base: multipeek(base), status: CharClassesStatus::Normal, @@ -1336,13 +1336,13 @@ where /// An iterator over the lines of a string, paired with the char kind at the /// end of the line. -pub struct LineClasses<'a> { +pub(crate) struct LineClasses<'a> { base: iter::Peekable>>, kind: FullCodeCharKind, } impl<'a> LineClasses<'a> { - pub fn new(s: &'a str) -> Self { + pub(crate) fn new(s: &'a str) -> Self { LineClasses { base: CharClasses::new(s.chars()).peekable(), kind: FullCodeCharKind::Normal, @@ -1458,14 +1458,14 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> { /// Iterator over an alternating sequence of functional and commented parts of /// a string. The first item is always a, possibly zero length, subslice of /// functional text. Line style comments contain their ending newlines. -pub struct CommentCodeSlices<'a> { +pub(crate) struct CommentCodeSlices<'a> { slice: &'a str, last_slice_kind: CodeCharKind, last_slice_end: usize, } impl<'a> CommentCodeSlices<'a> { - pub fn new(slice: &'a str) -> CommentCodeSlices<'a> { + pub(crate) fn new(slice: &'a str) -> CommentCodeSlices<'a> { CommentCodeSlices { slice, last_slice_kind: CodeCharKind::Comment, @@ -1536,7 +1536,7 @@ impl<'a> Iterator for CommentCodeSlices<'a> { /// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text /// (if it fits in the width/offset, else return `None`), else return `new` -pub fn recover_comment_removed( +pub(crate) fn recover_comment_removed( new: String, span: Span, context: &RewriteContext<'_>, @@ -1560,7 +1560,7 @@ pub fn recover_comment_removed( } } -pub fn filter_normal_code(code: &str) -> String { +pub(crate) fn filter_normal_code(code: &str) -> String { let mut buffer = String::with_capacity(code.len()); LineClasses::new(code).for_each(|(kind, line)| match kind { FullCodeCharKind::Normal diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 7c4298dcf1c..94d362f5faf 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -2,7 +2,7 @@ use crate::config::file_lines::FileLines; use crate::config::options::{IgnoreList, WidthHeuristics}; /// Trait for types that can be used in `Config`. -pub trait ConfigType: Sized { +pub(crate) trait ConfigType: Sized { /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a /// pipe-separated list of variants; for other types it returns "". fn doc_hint() -> String; @@ -73,6 +73,7 @@ macro_rules! create_config { use std::io::Write; #[derive(Clone)] + #[allow(unreachable_pub)] pub struct Config { // if a license_template_path has been specified, successfully read, parsed and compiled // into a regex, it will be stored here @@ -89,6 +90,7 @@ macro_rules! create_config { // We first parse into `PartialConfig`, then create a default `Config` // and overwrite the properties with corresponding values from `PartialConfig`. #[derive(Deserialize, Serialize, Clone)] + #[allow(unreachable_pub)] pub struct PartialConfig { $(pub $i: Option<$ty>),+ } @@ -98,10 +100,12 @@ macro_rules! create_config { // `config.set().option(false)`. It's pretty ugly. Consider replacing // with `config.set_option(false)` if we ever get a stable/usable // `concat_idents!()`. + #[allow(unreachable_pub)] pub struct ConfigSetter<'a>(&'a mut Config); impl<'a> ConfigSetter<'a> { $( + #[allow(unreachable_pub)] pub fn $i(&mut self, value: $ty) { (self.0).$i.2 = value; match stringify!($i) { @@ -115,10 +119,12 @@ macro_rules! create_config { // Query each option, returns true if the user set the option, false if // a default was used. + #[allow(unreachable_pub)] pub struct ConfigWasSet<'a>(&'a Config); impl<'a> ConfigWasSet<'a> { $( + #[allow(unreachable_pub)] pub fn $i(&self) -> bool { (self.0).$i.1 } @@ -127,16 +133,19 @@ macro_rules! create_config { impl Config { $( + #[allow(unreachable_pub)] pub fn $i(&self) -> $ty { self.$i.0.set(true); self.$i.2.clone() } )+ + #[allow(unreachable_pub)] pub fn set(&mut self) -> ConfigSetter<'_> { ConfigSetter(self) } + #[allow(unreachable_pub)] pub fn was_set(&self) -> ConfigWasSet<'_> { ConfigWasSet(self) } @@ -183,6 +192,7 @@ macro_rules! create_config { } } + #[allow(unreachable_pub)] pub fn used_options(&self) -> PartialConfig { PartialConfig { $( @@ -195,6 +205,7 @@ macro_rules! create_config { } } + #[allow(unreachable_pub)] pub fn all_options(&self) -> PartialConfig { PartialConfig { $( @@ -203,6 +214,7 @@ macro_rules! create_config { } } + #[allow(unreachable_pub)] pub fn override_value(&mut self, key: &str, val: &str) { match key { @@ -226,12 +238,14 @@ macro_rules! create_config { } } + #[allow(unreachable_pub)] pub fn is_hidden_option(name: &str) -> bool { const HIDE_OPTIONS: [&str; 4] = ["verbose", "verbose_diff", "file_lines", "width_heuristics"]; HIDE_OPTIONS.contains(&name) } + #[allow(unreachable_pub)] pub fn print_docs(out: &mut dyn Write, include_unstable: bool) { use std::cmp; let max = 0; @@ -291,6 +305,7 @@ macro_rules! create_config { self.ignore.2.add_prefix(dir); } + #[allow(unreachable_pub)] /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { $( diff --git a/src/config/license.rs b/src/config/license.rs index 7adaecf9d5c..2eb23bbcec7 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -7,7 +7,7 @@ use regex; use regex::Regex; #[derive(Debug)] -pub enum LicenseError { +pub(crate) enum LicenseError { IO(io::Error), Regex(regex::Error), Parse(String), @@ -47,7 +47,7 @@ enum ParsingState { use self::ParsingState::*; -pub struct TemplateParser { +pub(crate) struct TemplateParser { parsed: String, buffer: String, state: ParsingState, @@ -110,7 +110,7 @@ impl TemplateParser { /// " /// ); /// ``` - pub fn parse(template: &str) -> Result { + pub(crate) fn parse(template: &str) -> Result { let mut parser = Self::new(); for chr in template.chars() { if chr == '\n' { @@ -212,7 +212,7 @@ impl TemplateParser { } } -pub fn load_and_compile_template(path: &str) -> Result { +pub(crate) fn load_and_compile_template(path: &str) -> Result { let mut lt_file = File::open(&path)?; let mut lt_str = String::new(); lt_file.read_to_string(&mut lt_str)?; diff --git a/src/config/mod.rs b/src/config/mod.rs index c0221e93e02..82a7f5fc39a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -8,18 +8,21 @@ use std::{env, fs}; use regex::Regex; use crate::config::config_type::ConfigType; +#[allow(unreachable_pub)] pub use crate::config::file_lines::{FileLines, FileName, Range}; +#[allow(unreachable_pub)] pub use crate::config::lists::*; +#[allow(unreachable_pub)] pub use crate::config::options::*; #[macro_use] -pub mod config_type; +pub(crate) mod config_type; #[macro_use] -pub mod options; +pub(crate) mod options; -pub mod file_lines; -pub mod license; -pub mod lists; +pub(crate) mod file_lines; +pub(crate) mod license; +pub(crate) mod lists; // This macro defines configuration options used in rustfmt. Each option // is defined as follows: diff --git a/src/expr.rs b/src/expr.rs index da1b035ad1c..c4c41fb6957 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -44,12 +44,12 @@ impl Rewrite for ast::Expr { } #[derive(Copy, Clone, PartialEq)] -pub enum ExprType { +pub(crate) enum ExprType { Statement, SubExpression, } -pub fn format_expr( +pub(crate) fn format_expr( expr: &ast::Expr, expr_type: ExprType, context: &RewriteContext<'_>, @@ -386,7 +386,7 @@ pub fn format_expr( }) } -pub fn rewrite_array<'a, T: 'a + IntoOverflowableItem<'a>>( +pub(crate) fn rewrite_array<'a, T: 'a + IntoOverflowableItem<'a>>( name: &'a str, exprs: impl Iterator, span: Span, @@ -492,7 +492,7 @@ fn rewrite_single_line_block( None } -pub fn rewrite_block_with_visitor( +pub(crate) fn rewrite_block_with_visitor( context: &RewriteContext<'_>, prefix: &str, block: &ast::Block, @@ -581,7 +581,7 @@ impl Rewrite for ast::Stmt { } // Rewrite condition if the given expression has one. -pub fn rewrite_cond( +pub(crate) fn rewrite_cond( context: &RewriteContext<'_>, expr: &ast::Expr, shape: Shape, @@ -1128,7 +1128,7 @@ fn extract_comment(span: Span, context: &RewriteContext<'_>, shape: Shape) -> Op } } -pub fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> bool { +pub(crate) fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> bool { let snippet = source_map.span_to_snippet(block.span).unwrap(); contains_comment(&snippet) } @@ -1137,7 +1137,7 @@ pub fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> boo // attributes. // FIXME: incorrectly returns false when comment is contained completely within // the expression. -pub fn is_simple_block( +pub(crate) fn is_simple_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, source_map: &SourceMap, @@ -1150,7 +1150,7 @@ pub fn is_simple_block( /// Checks whether a block contains at most one statement or expression, and no /// comments or attributes. -pub fn is_simple_block_stmt( +pub(crate) fn is_simple_block_stmt( block: &ast::Block, attrs: Option<&[ast::Attribute]>, source_map: &SourceMap, @@ -1162,7 +1162,7 @@ pub fn is_simple_block_stmt( /// Checks whether a block contains no statements, expressions, comments, or /// inner attributes. -pub fn is_empty_block( +pub(crate) fn is_empty_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, source_map: &SourceMap, @@ -1172,7 +1172,7 @@ pub fn is_empty_block( && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } -pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool { +pub(crate) fn stmt_is_expr(stmt: &ast::Stmt) -> bool { match stmt.node { ast::StmtKind::Expr(..) => true, _ => false, @@ -1189,7 +1189,7 @@ pub(crate) fn stmt_is_if(stmt: &ast::Stmt) -> bool { } } -pub fn is_unsafe_block(block: &ast::Block) -> bool { +pub(crate) fn is_unsafe_block(block: &ast::Block) -> bool { if let ast::BlockCheckMode::Unsafe(..) = block.rules { true } else { @@ -1197,7 +1197,7 @@ pub fn is_unsafe_block(block: &ast::Block) -> bool { } } -pub fn rewrite_multiple_patterns( +pub(crate) fn rewrite_multiple_patterns( context: &RewriteContext<'_>, pats: &[&ast::Pat], shape: Shape, @@ -1230,7 +1230,11 @@ pub fn rewrite_multiple_patterns( write_list(&items, &fmt) } -pub fn rewrite_literal(context: &RewriteContext<'_>, l: &ast::Lit, shape: Shape) -> Option { +pub(crate) fn rewrite_literal( + context: &RewriteContext<'_>, + l: &ast::Lit, + shape: Shape, +) -> Option { match l.node { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), _ => wrap_str( @@ -1297,7 +1301,7 @@ fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option, callee: &str, args: &[ptr::P], @@ -1315,7 +1319,7 @@ pub fn rewrite_call( ) } -pub fn is_simple_expr(expr: &ast::Expr) -> bool { +pub(crate) fn is_simple_expr(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, @@ -1333,11 +1337,11 @@ pub fn is_simple_expr(expr: &ast::Expr) -> bool { } } -pub fn is_every_expr_simple(lists: &[OverflowableItem<'_>]) -> bool { +pub(crate) fn is_every_expr_simple(lists: &[OverflowableItem<'_>]) -> bool { lists.iter().all(OverflowableItem::is_simple) } -pub fn can_be_overflowed_expr( +pub(crate) fn can_be_overflowed_expr( context: &RewriteContext<'_>, expr: &ast::Expr, args_len: usize, @@ -1388,7 +1392,7 @@ pub fn can_be_overflowed_expr( } } -pub fn is_nested_call(expr: &ast::Expr) -> bool { +pub(crate) fn is_nested_call(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, ast::ExprKind::AddrOf(_, ref expr) @@ -1403,7 +1407,7 @@ pub fn is_nested_call(expr: &ast::Expr) -> bool { /// Returns `true` if a function call or a method call represented by the given span ends with a /// trailing comma. This function is used when rewriting macro, as adding or removing a trailing /// comma from macro can potentially break the code. -pub fn span_ends_with_comma(context: &RewriteContext<'_>, span: Span) -> bool { +pub(crate) fn span_ends_with_comma(context: &RewriteContext<'_>, span: Span) -> bool { let mut result: bool = Default::default(); let mut prev_char: char = Default::default(); let closing_delimiters = &[')', '}', ']']; @@ -1667,7 +1671,7 @@ fn rewrite_struct_lit<'a>( // of space, we should fall back to BlockIndent. } -pub fn wrap_struct_field( +pub(crate) fn wrap_struct_field( context: &RewriteContext<'_>, fields_str: &str, shape: Shape, @@ -1691,11 +1695,11 @@ pub fn wrap_struct_field( } } -pub fn struct_lit_field_separator(config: &Config) -> &str { +pub(crate) fn struct_lit_field_separator(config: &Config) -> &str { colon_spaces(config) } -pub fn rewrite_field( +pub(crate) fn rewrite_field( context: &RewriteContext<'_>, field: &ast::Field, shape: Shape, @@ -1792,7 +1796,7 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>( Some(format!("({})", list_str)) } -pub fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( +pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext<'_>, items: impl Iterator, span: Span, @@ -1827,7 +1831,7 @@ pub fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( } } -pub fn rewrite_unary_prefix( +pub(crate) fn rewrite_unary_prefix( context: &RewriteContext<'_>, prefix: &str, rewrite: &R, @@ -1840,7 +1844,7 @@ pub fn rewrite_unary_prefix( // FIXME: this is probably not correct for multi-line Rewrites. we should // subtract suffix.len() from the last line budget, not the first! -pub fn rewrite_unary_suffix( +pub(crate) fn rewrite_unary_suffix( context: &RewriteContext<'_>, suffix: &str, rewrite: &R, @@ -1885,7 +1889,7 @@ fn rewrite_assignment( /// Controls where to put the rhs. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum RhsTactics { +pub(crate) enum RhsTactics { /// Use heuristics. Default, /// Put the rhs on the next line if it uses multiple line, without extra indentation. @@ -1894,7 +1898,7 @@ pub enum RhsTactics { // The left hand side must contain everything up to, and including, the // assignment operator. -pub fn rewrite_assign_rhs, R: Rewrite>( +pub(crate) fn rewrite_assign_rhs, R: Rewrite>( context: &RewriteContext<'_>, lhs: S, ex: &R, @@ -1903,7 +1907,7 @@ pub fn rewrite_assign_rhs, R: Rewrite>( rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default) } -pub fn rewrite_assign_rhs_with, R: Rewrite>( +pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( context: &RewriteContext<'_>, lhs: S, ex: &R, @@ -1989,7 +1993,11 @@ fn shape_from_rhs_tactic( } } -pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { +pub(crate) fn prefer_next_line( + orig_rhs: &str, + next_line_rhs: &str, + rhs_tactics: RhsTactics, +) -> bool { rhs_tactics == RhsTactics::ForceNextLineWithoutIndent || !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 @@ -2011,7 +2019,7 @@ fn rewrite_expr_addrof( rewrite_unary_prefix(context, operator_str, expr, shape) } -pub fn is_method_call(expr: &ast::Expr) -> bool { +pub(crate) fn is_method_call(expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::MethodCall(..) => true, ast::ExprKind::AddrOf(_, ref expr) diff --git a/src/formatting.rs b/src/formatting.rs index 9776359bef3..e9fd5c2204b 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -347,7 +347,7 @@ pub(crate) struct ReportedErrors { impl ReportedErrors { /// Combine two summaries together. - pub fn add(&mut self, other: &ReportedErrors) { + pub(crate) fn add(&mut self, other: &ReportedErrors) { self.has_operational_errors |= other.has_operational_errors; self.has_parsing_errors |= other.has_parsing_errors; self.has_formatting_errors |= other.has_formatting_errors; diff --git a/src/ignore_path.rs b/src/ignore_path.rs index 844ea427f49..d8974e12b8f 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -2,12 +2,12 @@ use ignore::{self, gitignore}; use crate::config::{FileName, IgnoreList}; -pub struct IgnorePathSet { +pub(crate) struct IgnorePathSet { ignore_set: gitignore::Gitignore, } impl IgnorePathSet { - pub fn from_ignore_list(ignore_list: &IgnoreList) -> Result { + pub(crate) fn from_ignore_list(ignore_list: &IgnoreList) -> Result { let mut ignore_builder = gitignore::GitignoreBuilder::new(ignore_list.rustfmt_toml_path()); for ignore_path in ignore_list { @@ -19,7 +19,7 @@ impl IgnorePathSet { }) } - pub fn is_match(&self, file_name: &FileName) -> bool { + pub(crate) fn is_match(&self, file_name: &FileName) -> bool { match file_name { FileName::Stdin => false, FileName::Real(p) => self diff --git a/src/imports.rs b/src/imports.rs index 08647dee490..1d9eba7b1ef 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -20,12 +20,12 @@ use crate::visitor::FmtVisitor; /// Returns a name imported by a `use` declaration. /// E.g., returns `Ordering` for `std::cmp::Ordering` and `self` for `std::cmp::self`. -pub fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { +pub(crate) fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { path.segments.last().unwrap().ident } impl<'a> FmtVisitor<'a> { - pub fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { + pub(crate) fn format_import(&mut self, item: &ast::Item, tree: &ast::UseTree) { let span = item.span(); let shape = self.shape(); let rw = UseTree::from_ast( @@ -84,7 +84,7 @@ impl<'a> FmtVisitor<'a> { // FIXME we do a lot of allocation to make our own representation. #[derive(Clone, Eq, PartialEq)] -pub enum UseSegment { +pub(crate) enum UseSegment { Ident(String, Option), Slf(Option), Super(Option), @@ -94,11 +94,11 @@ pub enum UseSegment { } #[derive(Clone)] -pub struct UseTree { - pub path: Vec, - pub span: Span, +pub(crate) struct UseTree { + pub(crate) path: Vec, + pub(crate) span: Span, // Comment information within nested use tree. - pub list_item: Option, + pub(crate) list_item: Option, // Additional fields for top level use items. // Should we have another struct for top-level use items rather than reusing this? visibility: Option, @@ -156,7 +156,7 @@ impl UseSegment { } } -pub fn merge_use_trees(use_trees: Vec) -> Vec { +pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { let mut result = Vec::with_capacity(use_trees.len()); for use_tree in use_trees { if use_tree.has_comment() || use_tree.attrs.is_some() { @@ -229,7 +229,11 @@ impl fmt::Display for UseTree { impl UseTree { // Rewrite use tree with `use ` and a trailing `;`. - pub fn rewrite_top_level(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + pub(crate) fn rewrite_top_level( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Option { let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| { crate::utils::format_visibility(context, &vis) }); @@ -285,7 +289,7 @@ impl UseTree { } } - pub fn from_ast_with_normalization( + pub(crate) fn from_ast_with_normalization( context: &RewriteContext<'_>, item: &ast::Item, ) -> Option { @@ -416,7 +420,7 @@ impl UseTree { } // Do the adjustments that rustfmt does elsewhere to use paths. - pub fn normalize(mut self) -> UseTree { + pub(crate) fn normalize(mut self) -> UseTree { let mut last = self.path.pop().expect("Empty use tree?"); // Hack around borrow checker. let mut normalize_sole_list = false; diff --git a/src/issues.rs b/src/issues.rs index c89469bff79..d369b75541e 100644 --- a/src/issues.rs +++ b/src/issues.rs @@ -65,14 +65,14 @@ enum IssueClassification { None, } -pub struct BadIssueSeeker { +pub(crate) struct BadIssueSeeker { state: Seeking, report_todo: ReportTactic, report_fixme: ReportTactic, } impl BadIssueSeeker { - pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { + pub(crate) fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker { BadIssueSeeker { state: Seeking::Issue { todo_idx: 0, @@ -83,13 +83,13 @@ impl BadIssueSeeker { } } - pub fn is_disabled(&self) -> bool { + pub(crate) fn is_disabled(&self) -> bool { !is_enabled(self.report_todo) && !is_enabled(self.report_fixme) } // Check whether or not the current char is conclusive evidence for an // unnumbered TO-DO or FIX-ME. - pub fn inspect(&mut self, c: char) -> Option { + pub(crate) fn inspect(&mut self, c: char) -> Option { match self.state { Seeking::Issue { todo_idx, diff --git a/src/items.rs b/src/items.rs index c7f95557ea3..17e67b3f79f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -157,7 +157,7 @@ enum BodyElement<'a> { } /// Represents a fn's signature. -pub struct FnSig<'a> { +pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, abi: abi::Abi, @@ -169,7 +169,7 @@ pub struct FnSig<'a> { } impl<'a> FnSig<'a> { - pub fn new( + pub(crate) fn new( decl: &'a ast::FnDecl, generics: &'a ast::Generics, vis: ast::Visibility, @@ -186,7 +186,7 @@ impl<'a> FnSig<'a> { } } - pub fn from_method_sig( + pub(crate) fn from_method_sig( method_sig: &'a ast::MethodSig, generics: &'a ast::Generics, ) -> FnSig<'a> { @@ -202,7 +202,7 @@ impl<'a> FnSig<'a> { } } - pub fn from_fn_kind( + pub(crate) fn from_fn_kind( fn_kind: &'a visit::FnKind<'_>, generics: &'a ast::Generics, decl: &'a ast::FnDecl, @@ -287,7 +287,7 @@ impl<'a> FmtVisitor<'a> { } } - pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { + pub(crate) fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) { let item = Item::from_foreign_mod(fm, span, self.config); self.format_item(&item); } @@ -298,7 +298,7 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.hi(); } - pub fn rewrite_fn( + pub(crate) fn rewrite_fn( &mut self, indent: Indent, ident: ast::Ident, @@ -341,7 +341,7 @@ impl<'a> FmtVisitor<'a> { } } - pub fn rewrite_required_fn( + pub(crate) fn rewrite_required_fn( &mut self, indent: Indent, ident: ast::Ident, @@ -416,19 +416,19 @@ impl<'a> FmtVisitor<'a> { } } - pub fn visit_static(&mut self, static_parts: &StaticParts<'_>) { + pub(crate) fn visit_static(&mut self, static_parts: &StaticParts<'_>) { let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent); self.push_rewrite(static_parts.span, rewrite); } - pub fn visit_struct(&mut self, struct_parts: &StructParts<'_>) { + pub(crate) fn visit_struct(&mut self, struct_parts: &StructParts<'_>) { let is_tuple = struct_parts.def.is_tuple(); let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) .map(|s| if is_tuple { s + ";" } else { s }); self.push_rewrite(struct_parts.span, rewrite); } - pub fn visit_enum( + pub(crate) fn visit_enum( &mut self, ident: ast::Ident, vis: &ast::Visibility, @@ -660,7 +660,7 @@ impl<'a> FmtVisitor<'a> { } } -pub fn format_impl( +pub(crate) fn format_impl( context: &RewriteContext<'_>, item: &ast::Item, offset: Indent, @@ -928,7 +928,7 @@ fn rewrite_trait_ref( )) } -pub struct StructParts<'a> { +pub(crate) struct StructParts<'a> { prefix: &'a str, ident: ast::Ident, vis: &'a ast::Visibility, @@ -953,7 +953,7 @@ impl<'a> StructParts<'a> { } } - pub fn from_item(item: &'a ast::Item) -> Self { + pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (prefix, def, generics) = match item.node { ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), @@ -987,7 +987,7 @@ fn format_struct( } } -pub fn format_trait( +pub(crate) fn format_trait( context: &RewriteContext<'_>, item: &ast::Item, offset: Indent, @@ -1149,7 +1149,7 @@ pub fn format_trait( } } -pub fn format_trait_alias( +pub(crate) fn format_trait_alias( context: &RewriteContext<'_>, ident: ast::Ident, vis: &ast::Visibility, @@ -1191,7 +1191,7 @@ fn format_unit_struct( Some(format!("{}{};", header_str, generics_str)) } -pub fn format_struct_struct( +pub(crate) fn format_struct_struct( context: &RewriteContext<'_>, struct_parts: &StructParts<'_>, fields: &[ast::StructField], @@ -1495,7 +1495,7 @@ fn rewrite_type_item( rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";") } -pub fn rewrite_type_alias( +pub(crate) fn rewrite_type_alias( context: &RewriteContext<'_>, indent: Indent, ident: ast::Ident, @@ -1506,7 +1506,7 @@ pub fn rewrite_type_alias( rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis) } -pub fn rewrite_existential_type( +pub(crate) fn rewrite_existential_type( context: &RewriteContext<'_>, indent: Indent, ident: ast::Ident, @@ -1533,7 +1533,7 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { ) } -pub fn rewrite_struct_field_prefix( +pub(crate) fn rewrite_struct_field_prefix( context: &RewriteContext<'_>, field: &ast::StructField, ) -> Option { @@ -1556,7 +1556,7 @@ impl Rewrite for ast::StructField { } } -pub fn rewrite_struct_field( +pub(crate) fn rewrite_struct_field( context: &RewriteContext<'_>, field: &ast::StructField, shape: Shape, @@ -1620,7 +1620,7 @@ pub fn rewrite_struct_field( combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false) } -pub struct StaticParts<'a> { +pub(crate) struct StaticParts<'a> { prefix: &'a str, vis: &'a ast::Visibility, ident: ast::Ident, @@ -1632,7 +1632,7 @@ pub struct StaticParts<'a> { } impl<'a> StaticParts<'a> { - pub fn from_item(item: &'a ast::Item) -> Self { + pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (prefix, ty, mutability, expr) = match item.node { ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), ast::ItemKind::Const(ref ty, ref expr) => { @@ -1652,7 +1652,7 @@ impl<'a> StaticParts<'a> { } } - pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self { + pub(crate) fn from_trait_item(ti: &'a ast::TraitItem) -> Self { let (ty, expr_opt) = match ti.node { ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), _ => unreachable!(), @@ -1669,7 +1669,7 @@ impl<'a> StaticParts<'a> { } } - pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self { + pub(crate) fn from_impl_item(ii: &'a ast::ImplItem) -> Self { let (ty, expr) = match ii.node { ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), _ => unreachable!(), @@ -1739,7 +1739,7 @@ fn rewrite_static( } } -pub fn rewrite_associated_type( +pub(crate) fn rewrite_associated_type( ident: ast::Ident, ty_opt: Option<&ptr::P>, generics: &ast::Generics, @@ -1775,7 +1775,7 @@ pub fn rewrite_associated_type( } } -pub fn rewrite_existential_impl_type( +pub(crate) fn rewrite_existential_impl_type( context: &RewriteContext<'_>, ident: ast::Ident, generics: &ast::Generics, @@ -1786,7 +1786,7 @@ pub fn rewrite_existential_impl_type( .map(|s| format!("existential {}", s)) } -pub fn rewrite_associated_impl_type( +pub(crate) fn rewrite_associated_impl_type( ident: ast::Ident, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, @@ -1922,7 +1922,7 @@ fn rewrite_explicit_self( } } -pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { +pub(crate) fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { if is_named_arg(arg) { arg.pat.span.lo() } else { @@ -1930,7 +1930,7 @@ pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { } } -pub fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> BytePos { +pub(crate) fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> BytePos { match arg.ty.node { ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), @@ -1938,7 +1938,7 @@ pub fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> BytePos } } -pub fn is_named_arg(arg: &ast::Arg) -> bool { +pub(crate) fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { ident != symbol::keywords::Invalid.ident() } else { @@ -2245,7 +2245,7 @@ struct WhereClauseOption { } impl WhereClauseOption { - pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { + fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { WhereClauseOption { suppress_comma, snuggle, @@ -2253,7 +2253,7 @@ impl WhereClauseOption { } } - pub fn snuggled(current: &str) -> WhereClauseOption { + fn snuggled(current: &str) -> WhereClauseOption { WhereClauseOption { suppress_comma: false, snuggle: last_line_width(current) == 1, @@ -2261,15 +2261,15 @@ impl WhereClauseOption { } } - pub fn suppress_comma(&mut self) { + fn suppress_comma(&mut self) { self.suppress_comma = true } - pub fn compress_where(&mut self) { + fn compress_where(&mut self) { self.compress_where = true } - pub fn snuggle(&mut self) { + fn snuggle(&mut self) { self.snuggle = true } } @@ -2434,7 +2434,11 @@ fn rewrite_generics( overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span) } -pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { +pub(crate) fn generics_shape_from_config( + config: &Config, + shape: Shape, + offset: usize, +) -> Option { match config.indent_style() { IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), IndentStyle::Block => { @@ -2858,7 +2862,7 @@ impl Rewrite for ast::ForeignItem { } /// Rewrite an inline mod. -pub fn rewrite_mod(context: &RewriteContext<'_>, item: &ast::Item) -> String { +pub(crate) fn rewrite_mod(context: &RewriteContext<'_>, item: &ast::Item) -> String { let mut result = String::with_capacity(32); result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); @@ -2868,7 +2872,10 @@ pub fn rewrite_mod(context: &RewriteContext<'_>, item: &ast::Item) -> String { } /// Rewrite `extern crate foo;` WITHOUT attributes. -pub fn rewrite_extern_crate(context: &RewriteContext<'_>, item: &ast::Item) -> Option { +pub(crate) fn rewrite_extern_crate( + context: &RewriteContext<'_>, + item: &ast::Item, +) -> Option { assert!(is_extern_crate(item)); let new_str = context.snippet(item.span); Some(if contains_comment(new_str) { @@ -2880,21 +2887,21 @@ pub fn rewrite_extern_crate(context: &RewriteContext<'_>, item: &ast::Item) -> O } /// Returns `true` for `mod foo;`, false for `mod foo { .. }`. -pub fn is_mod_decl(item: &ast::Item) -> bool { +pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { match item.node { ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), _ => false, } } -pub fn is_use_item(item: &ast::Item) -> bool { +pub(crate) fn is_use_item(item: &ast::Item) -> bool { match item.node { ast::ItemKind::Use(_) => true, _ => false, } } -pub fn is_extern_crate(item: &ast::Item) -> bool { +pub(crate) fn is_extern_crate(item: &ast::Item) -> bool { match item.node { ast::ItemKind::ExternCrate(..) => true, _ => false, diff --git a/src/lib.rs b/src/lib.rs index 3de9616a2ce..56b67b2eb7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![deny(rust_2018_idioms)] +#![warn(unreachable_pub)] #[macro_use] extern crate derive_new; diff --git a/src/lists.rs b/src/lists.rs index 97592f893a5..f57a78f9874 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -13,7 +13,7 @@ use crate::shape::{Indent, Shape}; use crate::utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; use crate::visitor::SnippetProvider; -pub struct ListFormatting<'a> { +pub(crate) struct ListFormatting<'a> { tactic: DefinitiveListTactic, separator: &'a str, trailing_separator: SeparatorTactic, @@ -32,7 +32,7 @@ pub struct ListFormatting<'a> { } impl<'a> ListFormatting<'a> { - pub fn new(shape: Shape, config: &'a Config) -> Self { + pub(crate) fn new(shape: Shape, config: &'a Config) -> Self { ListFormatting { tactic: DefinitiveListTactic::Vertical, separator: ",", @@ -47,47 +47,47 @@ impl<'a> ListFormatting<'a> { } } - pub fn tactic(mut self, tactic: DefinitiveListTactic) -> Self { + pub(crate) fn tactic(mut self, tactic: DefinitiveListTactic) -> Self { self.tactic = tactic; self } - pub fn separator(mut self, separator: &'a str) -> Self { + pub(crate) fn separator(mut self, separator: &'a str) -> Self { self.separator = separator; self } - pub fn trailing_separator(mut self, trailing_separator: SeparatorTactic) -> Self { + pub(crate) fn trailing_separator(mut self, trailing_separator: SeparatorTactic) -> Self { self.trailing_separator = trailing_separator; self } - pub fn separator_place(mut self, separator_place: SeparatorPlace) -> Self { + pub(crate) fn separator_place(mut self, separator_place: SeparatorPlace) -> Self { self.separator_place = separator_place; self } - pub fn ends_with_newline(mut self, ends_with_newline: bool) -> Self { + pub(crate) fn ends_with_newline(mut self, ends_with_newline: bool) -> Self { self.ends_with_newline = ends_with_newline; self } - pub fn preserve_newline(mut self, preserve_newline: bool) -> Self { + pub(crate) fn preserve_newline(mut self, preserve_newline: bool) -> Self { self.preserve_newline = preserve_newline; self } - pub fn nested(mut self, nested: bool) -> Self { + pub(crate) fn nested(mut self, nested: bool) -> Self { self.nested = nested; self } - pub fn align_comments(mut self, align_comments: bool) -> Self { + pub(crate) fn align_comments(mut self, align_comments: bool) -> Self { self.align_comments = align_comments; self } - pub fn needs_trailing_separator(&self) -> bool { + pub(crate) fn needs_trailing_separator(&self) -> bool { match self.trailing_separator { // We always put separator in front. SeparatorTactic::Always => true, @@ -106,7 +106,7 @@ impl AsRef for ListItem { } #[derive(PartialEq, Eq, Debug, Copy, Clone)] -pub enum ListItemCommentStyle { +pub(crate) enum ListItemCommentStyle { // Try to keep the comment on the same line with the item. SameLine, // Put the comment on the previous or the next line of the item. @@ -116,20 +116,20 @@ pub enum ListItemCommentStyle { } #[derive(Debug, Clone)] -pub struct ListItem { +pub(crate) struct ListItem { // None for comments mean that they are not present. - pub pre_comment: Option, - pub pre_comment_style: ListItemCommentStyle, + pub(crate) pre_comment: Option, + pub(crate) pre_comment_style: ListItemCommentStyle, // Item should include attributes and doc comments. None indicates a failed // rewrite. - pub item: Option, - pub post_comment: Option, + pub(crate) item: Option, + pub(crate) post_comment: Option, // Whether there is extra whitespace before this item. - pub new_lines: bool, + pub(crate) new_lines: bool, } impl ListItem { - pub fn empty() -> ListItem { + pub(crate) fn empty() -> ListItem { ListItem { pre_comment: None, pre_comment_style: ListItemCommentStyle::None, @@ -139,11 +139,11 @@ impl ListItem { } } - pub fn inner_as_ref(&self) -> &str { + pub(crate) fn inner_as_ref(&self) -> &str { self.item.as_ref().map_or("", |s| s) } - pub fn is_different_group(&self) -> bool { + pub(crate) fn is_different_group(&self) -> bool { self.inner_as_ref().contains('\n') || self.pre_comment.is_some() || self @@ -152,7 +152,7 @@ impl ListItem { .map_or(false, |s| s.contains('\n')) } - pub fn is_multiline(&self) -> bool { + pub(crate) fn is_multiline(&self) -> bool { self.inner_as_ref().contains('\n') || self .pre_comment @@ -164,7 +164,7 @@ impl ListItem { .map_or(false, |s| s.contains('\n')) } - pub fn has_single_line_comment(&self) -> bool { + pub(crate) fn has_single_line_comment(&self) -> bool { self.pre_comment .as_ref() .map_or(false, |comment| comment.trim_start().starts_with("//")) @@ -174,11 +174,11 @@ impl ListItem { .map_or(false, |comment| comment.trim_start().starts_with("//")) } - pub fn has_comment(&self) -> bool { + pub(crate) fn has_comment(&self) -> bool { self.pre_comment.is_some() || self.post_comment.is_some() } - pub fn from_str>(s: S) -> ListItem { + pub(crate) fn from_str>(s: S) -> ListItem { ListItem { pre_comment: None, pre_comment_style: ListItemCommentStyle::None, @@ -203,13 +203,13 @@ impl ListItem { /// The type of separator for lists. #[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum Separator { +pub(crate) enum Separator { Comma, VerticalBar, } impl Separator { - pub fn len(self) -> usize { + pub(crate) fn len(self) -> usize { match self { // 2 = `, ` Separator::Comma => 2, @@ -219,7 +219,7 @@ impl Separator { } } -pub fn definitive_tactic( +pub(crate) fn definitive_tactic( items: I, tactic: ListTactic, sep: Separator, @@ -260,7 +260,7 @@ where } // Format a list of commented items into a string. -pub fn write_list(items: I, formatting: &ListFormatting<'_>) -> Option +pub(crate) fn write_list(items: I, formatting: &ListFormatting<'_>) -> Option where I: IntoIterator + Clone, T: AsRef, @@ -556,7 +556,7 @@ fn post_comment_alignment(item_max_width: Option, inner_item_len: usize) item_max_width.unwrap_or(0).saturating_sub(inner_item_len) } -pub struct ListItems<'a, I, F1, F2, F3> +pub(crate) struct ListItems<'a, I, F1, F2, F3> where I: Iterator, { @@ -572,7 +572,7 @@ where leave_last: bool, } -pub fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommentStyle) { +pub(crate) fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommentStyle) { let trimmed_pre_snippet = pre_snippet.trim(); let has_block_comment = trimmed_pre_snippet.ends_with("*/"); let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); @@ -599,7 +599,7 @@ pub fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommen } } -pub fn extract_post_comment( +pub(crate) fn extract_post_comment( post_snippet: &str, comment_end: usize, separator: &str, @@ -629,7 +629,7 @@ pub fn extract_post_comment( } } -pub fn get_comment_end( +pub(crate) fn get_comment_end( post_snippet: &str, separator: &str, terminator: &str, @@ -682,7 +682,7 @@ pub fn get_comment_end( // Account for extra whitespace between items. This is fiddly // because of the way we divide pre- and post- comments. -pub fn has_extra_newline(post_snippet: &str, comment_end: usize) -> bool { +pub(crate) fn has_extra_newline(post_snippet: &str, comment_end: usize) -> bool { if post_snippet.is_empty() || comment_end == 0 { return false; } @@ -764,7 +764,7 @@ where #[allow(clippy::too_many_arguments)] // Creates an iterator over a list's items with associated comments. -pub fn itemize_list<'a, T, I, F1, F2, F3>( +pub(crate) fn itemize_list<'a, T, I, F1, F2, F3>( snippet_provider: &'a SnippetProvider<'_>, inner: I, terminator: &'a str, @@ -808,7 +808,7 @@ where .fold((0, 0), |acc, l| (acc.0 + 1, acc.1 + l)) } -pub fn total_item_width(item: &ListItem) -> usize { +pub(crate) fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) + item.item.as_ref().map_or(0, String::len) @@ -830,7 +830,7 @@ fn comment_len(comment: Option<&str>) -> usize { } // Compute horizontal and vertical shapes for a struct-lit-like thing. -pub fn struct_lit_shape( +pub(crate) fn struct_lit_shape( shape: Shape, context: &RewriteContext<'_>, prefix_width: usize, @@ -859,7 +859,7 @@ pub fn struct_lit_shape( } // Compute the tactic for the internals of a struct-lit-like thing. -pub fn struct_lit_tactic( +pub(crate) fn struct_lit_tactic( h_shape: Option, context: &RewriteContext<'_>, items: &[ListItem], @@ -878,7 +878,7 @@ pub fn struct_lit_tactic( // Given a tactic and possible shapes for horizontal and vertical layout, // come up with the actual shape to use. -pub fn shape_for_tactic( +pub(crate) fn shape_for_tactic( tactic: DefinitiveListTactic, h_shape: Option, v_shape: Shape, @@ -891,7 +891,7 @@ pub fn shape_for_tactic( // Create a ListFormatting object for formatting the internals of a // struct-lit-like thing, that is a series of fields. -pub fn struct_lit_formatting<'a>( +pub(crate) fn struct_lit_formatting<'a>( shape: Shape, tactic: DefinitiveListTactic, context: &'a RewriteContext<'_>, diff --git a/src/macros.rs b/src/macros.rs index 05a70ae9d4e..478b55b4920 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -41,7 +41,7 @@ use crate::visitor::FmtVisitor; const FORCED_BRACKET_MACROS: &[&str] = &["vec!"]; #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum MacroPosition { +pub(crate) enum MacroPosition { Item, Statement, Expression, @@ -49,7 +49,7 @@ pub enum MacroPosition { } #[derive(Debug)] -pub enum MacroArg { +pub(crate) enum MacroArg { Expr(ptr::P), Ty(ptr::P), Pat(ptr::P), @@ -201,7 +201,7 @@ impl<'a> Drop for InsideMacroGuard<'a> { } } -pub fn rewrite_macro( +pub(crate) fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, context: &RewriteContext<'_>, @@ -242,7 +242,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { None } -pub fn rewrite_macro_inner( +fn rewrite_macro_inner( mac: &ast::Mac, extra_ident: Option, context: &RewriteContext<'_>, @@ -453,7 +453,7 @@ pub fn rewrite_macro_inner( } } -pub fn rewrite_macro_def( +pub(crate) fn rewrite_macro_def( context: &RewriteContext<'_>, shape: Shape, indent: Indent, @@ -736,7 +736,7 @@ struct ParsedMacroArg { } impl ParsedMacroArg { - pub fn rewrite( + fn rewrite( &self, context: &RewriteContext<'_>, shape: Shape, @@ -772,7 +772,7 @@ fn last_tok(tt: &TokenTree) -> Token { } impl MacroArgParser { - pub fn new() -> MacroArgParser { + fn new() -> MacroArgParser { MacroArgParser { lo: BytePos(0), hi: BytePos(0), @@ -932,7 +932,7 @@ impl MacroArgParser { } /// Returns a collection of parsed macro def's arguments. - pub fn parse(mut self, tokens: TokenStream) -> Option> { + fn parse(mut self, tokens: TokenStream) -> Option> { let mut iter = tokens.trees(); while let Some(tok) = iter.next() { @@ -1136,7 +1136,7 @@ fn next_space(tok: &Token) -> SpaceState { /// Tries to convert a macro use into a short hand try expression. Returns `None` /// when the macro is not an instance of `try!` (or parsing the inner expression /// failed). -pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { +pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { if &mac.node.path.to_string() == "try" { let ts: TokenStream = mac.node.tts.clone(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); diff --git a/src/matches.rs b/src/matches.rs index c09949cf2e8..2e2c5477616 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -24,20 +24,16 @@ use crate::utils::{ /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. struct ArmWrapper<'a> { - pub arm: &'a ast::Arm, + arm: &'a ast::Arm, /// `true` if the arm is the last one in match expression. Used to decide on whether we should /// add trailing comma to the match arm when `config.trailing_comma() == Never`. - pub is_last: bool, + is_last: bool, /// Holds a byte position of `|` at the beginning of the arm pattern, if available. - pub beginning_vert: Option, + beginning_vert: Option, } impl<'a> ArmWrapper<'a> { - pub fn new( - arm: &'a ast::Arm, - is_last: bool, - beginning_vert: Option, - ) -> ArmWrapper<'a> { + fn new(arm: &'a ast::Arm, is_last: bool, beginning_vert: Option) -> ArmWrapper<'a> { ArmWrapper { arm, is_last, @@ -62,7 +58,7 @@ impl<'a> Rewrite for ArmWrapper<'a> { } } -pub fn rewrite_match( +pub(crate) fn rewrite_match( context: &RewriteContext<'_>, cond: &ast::Expr, arms: &[ast::Arm], diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 0f459571d42..84246e3ed51 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -34,7 +34,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.is_empty() } - pub fn format_missing(&mut self, end: BytePos) { + pub(crate) fn format_missing(&mut self, end: BytePos) { // HACK(topecongiro): we use `format_missing()` to extract a missing comment between // a macro (or similar) and a trailing semicolon. Here we just try to avoid calling // `format_missing_inner` in the common case where there is no such comment. @@ -50,7 +50,7 @@ impl<'a> FmtVisitor<'a> { self.format_missing_inner(end, |this, last_snippet, _| this.push_str(last_snippet)) } - pub fn format_missing_with_indent(&mut self, end: BytePos) { + pub(crate) fn format_missing_with_indent(&mut self, end: BytePos) { let config = self.config; self.format_missing_inner(end, |this, last_snippet, snippet| { this.push_str(last_snippet.trim_end()); @@ -63,7 +63,7 @@ impl<'a> FmtVisitor<'a> { }) } - pub fn format_missing_no_indent(&mut self, end: BytePos) { + pub(crate) fn format_missing_no_indent(&mut self, end: BytePos) { self.format_missing_inner(end, |this, last_snippet, _| { this.push_str(last_snippet.trim_end()); }) diff --git a/src/modules.rs b/src/modules.rs index 01a0784c6f4..3d009b2098b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -13,7 +13,7 @@ use crate::utils::contains_skip; type FileModMap<'a> = BTreeMap; /// Maps each module to the corresponding file. -pub struct ModResolver<'a, 'b> { +pub(crate) struct ModResolver<'a, 'b> { source_map: &'b source_map::SourceMap, directory: Directory, file_map: FileModMap<'a>, @@ -28,7 +28,7 @@ struct Directory { impl<'a, 'b> ModResolver<'a, 'b> { /// Creates a new `ModResolver`. - pub fn new( + pub(crate) fn new( source_map: &'b source_map::SourceMap, directory_ownership: DirectoryOwnership, is_input_stdin: bool, @@ -45,7 +45,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { } /// Creates a map that maps a file name to the module in AST. - pub fn visit_crate(mut self, krate: &'a ast::Crate) -> Result, String> { + pub(crate) fn visit_crate(mut self, krate: &'a ast::Crate) -> Result, String> { let root_filename = self.source_map.span_to_filename(krate.span); self.directory.path = match root_filename { source_map::FileName::Real(ref path) => path diff --git a/src/overflow.rs b/src/overflow.rs index 8bc32fcbbc8..3fe2a2fd25b 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -68,7 +68,7 @@ const SPECIAL_ATTR_WHITELIST: &[(&str, usize)] = &[ ]; #[derive(Debug)] -pub enum OverflowableItem<'a> { +pub(crate) enum OverflowableItem<'a> { Expr(&'a ast::Expr), GenericParam(&'a ast::GenericParam), MacroArg(&'a MacroArg), @@ -103,7 +103,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn map(&self, f: F) -> T + pub(crate) fn map(&self, f: F) -> T where F: Fn(&dyn IntoOverflowableItem<'a>) -> T, { @@ -119,7 +119,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn is_simple(&self) -> bool { + pub(crate) fn is_simple(&self) -> bool { match self { OverflowableItem::Expr(expr) => is_simple_expr(expr), OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), @@ -134,7 +134,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn is_expr(&self) -> bool { + pub(crate) fn is_expr(&self) -> bool { match self { OverflowableItem::Expr(..) => true, OverflowableItem::MacroArg(MacroArg::Expr(..)) => true, @@ -142,7 +142,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn is_nested_call(&self) -> bool { + pub(crate) fn is_nested_call(&self) -> bool { match self { OverflowableItem::Expr(expr) => is_nested_call(expr), OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_nested_call(expr), @@ -150,7 +150,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn to_expr(&self) -> Option<&'a ast::Expr> { + pub(crate) fn to_expr(&self) -> Option<&'a ast::Expr> { match self { OverflowableItem::Expr(expr) => Some(expr), OverflowableItem::MacroArg(macro_arg) => match macro_arg { @@ -161,7 +161,7 @@ impl<'a> OverflowableItem<'a> { } } - pub fn can_be_overflowed(&self, context: &RewriteContext<'_>, len: usize) -> bool { + pub(crate) fn can_be_overflowed(&self, context: &RewriteContext<'_>, len: usize) -> bool { match self { OverflowableItem::Expr(expr) => can_be_overflowed_expr(context, expr, len), OverflowableItem::MacroArg(macro_arg) => match macro_arg { @@ -196,7 +196,7 @@ impl<'a> OverflowableItem<'a> { } } -pub trait IntoOverflowableItem<'a>: Rewrite + Spanned { +pub(crate) trait IntoOverflowableItem<'a>: Rewrite + Spanned { fn into_overflowable_item(&'a self) -> OverflowableItem<'a>; } @@ -240,7 +240,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, StructField, Ty); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); -pub fn into_overflowable_list<'a, T>( +pub(crate) fn into_overflowable_list<'a, T>( iter: impl Iterator, ) -> impl Iterator> where @@ -249,7 +249,7 @@ where iter.map(|x| IntoOverflowableItem::into_overflowable_item(x)) } -pub fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( +pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext<'_>, ident: &'a str, items: impl Iterator, @@ -273,7 +273,7 @@ pub fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>( .rewrite(shape) } -pub fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( +pub(crate) fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext<'_>, ident: &'a str, items: impl Iterator, @@ -295,7 +295,7 @@ pub fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( .rewrite(shape) } -pub fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( +pub(crate) fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>( context: &'a RewriteContext<'_>, name: &'a str, items: impl Iterator, @@ -340,7 +340,7 @@ struct Context<'a> { } impl<'a> Context<'a> { - pub fn new>( + fn new>( context: &'a RewriteContext<'_>, items: impl Iterator, ident: &'a str, @@ -766,7 +766,7 @@ fn no_long_items(list: &[ListItem]) -> bool { } /// In case special-case style is required, returns an offset from which we start horizontal layout. -pub fn maybe_get_args_offset( +pub(crate) fn maybe_get_args_offset( callee_str: &str, args: &[OverflowableItem<'_>], ) -> Option<(bool, usize)> { diff --git a/src/patterns.rs b/src/patterns.rs index 2140b8d870f..73ff2c0f7ab 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -30,7 +30,7 @@ use crate::utils::{format_mutability, mk_sp, rewrite_ident}; /// - `[small, ntp]` /// - unary tuple constructor `([small, ntp])` /// - `&[small]` -pub fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { +pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { // We also require that the pattern is reasonably 'small' with its literal width. pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat) } @@ -256,7 +256,7 @@ impl Rewrite for FieldPat { } #[derive(Debug)] -pub enum TuplePatField<'a> { +pub(crate) enum TuplePatField<'a> { Pat(&'a ptr::P), Dotdot(Span), } @@ -279,7 +279,7 @@ impl<'a> Spanned for TuplePatField<'a> { } } -pub fn can_be_overflowed_pat( +pub(crate) fn can_be_overflowed_pat( context: &RewriteContext<'_>, pat: &TuplePatField<'_>, len: usize, diff --git a/src/reorder.rs b/src/reorder.rs index 49a4638f33f..2423fffcbea 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -272,7 +272,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { /// Visits and format the given items. Items are reordered If they are /// consecutive and reorderable. - pub fn visit_items_with_reordering(&mut self, mut items: &[&ast::Item]) { + pub(crate) fn visit_items_with_reordering(&mut self, mut items: &[&ast::Item]) { while !items.is_empty() { // If the next item is a `use`, `extern crate` or `mod`, then extract it and any // subsequent items that have the same item kind to be reordered within diff --git a/src/rewrite.rs b/src/rewrite.rs index c736c2535a6..9a955dbd91b 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -11,7 +11,7 @@ use crate::shape::Shape; use crate::visitor::SnippetProvider; use crate::FormatReport; -pub trait Rewrite { +pub(crate) trait Rewrite { /// Rewrite self into shape. fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; } @@ -23,44 +23,44 @@ impl Rewrite for ptr::P { } #[derive(Clone)] -pub struct RewriteContext<'a> { - pub parse_session: &'a ParseSess, - pub source_map: &'a SourceMap, - pub config: &'a Config, - pub inside_macro: RefCell, +pub(crate) struct RewriteContext<'a> { + pub(crate) parse_session: &'a ParseSess, + pub(crate) source_map: &'a SourceMap, + pub(crate) config: &'a Config, + pub(crate) inside_macro: RefCell, // Force block indent style even if we are using visual indent style. - pub use_block: RefCell, + pub(crate) use_block: RefCell, // When `is_if_else_block` is true, unindent the comment on top // of the `else` or `else if`. - pub is_if_else_block: RefCell, + pub(crate) is_if_else_block: RefCell, // When rewriting chain, veto going multi line except the last element - pub force_one_line_chain: RefCell, - pub snippet_provider: &'a SnippetProvider<'a>, + pub(crate) force_one_line_chain: RefCell, + pub(crate) snippet_provider: &'a SnippetProvider<'a>, // Used for `format_snippet` pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, - pub skip_macro_names: RefCell>, + pub(crate) skip_macro_names: RefCell>, } impl<'a> RewriteContext<'a> { - pub fn snippet(&self, span: Span) -> &str { + pub(crate) fn snippet(&self, span: Span) -> &str { self.snippet_provider.span_to_snippet(span).unwrap() } /// Returns `true` if we should use block indent style for rewriting function call. - pub fn use_block_indent(&self) -> bool { + pub(crate) fn use_block_indent(&self) -> bool { self.config.indent_style() == IndentStyle::Block || *self.use_block.borrow() } - pub fn budget(&self, used_width: usize) -> usize { + pub(crate) fn budget(&self, used_width: usize) -> usize { self.config.max_width().saturating_sub(used_width) } - pub fn inside_macro(&self) -> bool { + pub(crate) fn inside_macro(&self) -> bool { *self.inside_macro.borrow() } - pub fn is_if_else_block(&self) -> bool { + pub(crate) fn is_if_else_block(&self) -> bool { *self.is_if_else_block.borrow() } } diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c83eb1080a6..fd332b12403 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -146,14 +146,14 @@ impl std::str::FromStr for ModifiedLines { // This struct handles writing output to stdout and abstracts away the logic // of printing in color, if it's possible in the executing environment. -pub struct OutputWriter { +pub(crate) struct OutputWriter { terminal: Option>>, } impl OutputWriter { // Create a new OutputWriter instance based on the caller's preference // for colorized output and the capabilities of the terminal. - pub fn new(color: Color) -> Self { + pub(crate) fn new(color: Color) -> Self { if let Some(t) = term::stdout() { if color.use_colored_tty() && t.supports_color() { return OutputWriter { terminal: Some(t) }; @@ -165,7 +165,7 @@ impl OutputWriter { // Write output in the optionally specified color. The output is written // in the specified color if this OutputWriter instance contains a // Terminal in its `terminal` field. - pub fn writeln(&mut self, msg: &str, color: Option) { + pub(crate) fn writeln(&mut self, msg: &str, color: Option) { match &mut self.terminal { Some(ref mut t) => { if let Some(color) = color { @@ -182,7 +182,7 @@ impl OutputWriter { } // Produces a diff between the expected output and actual output of rustfmt. -pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { +pub(crate) fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec { let mut line_number = 1; let mut line_number_orig = 1; let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size); @@ -250,7 +250,7 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec(diff: Vec, get_section_title: F, config: &Config) +pub(crate) fn print_diff(diff: Vec, get_section_title: F, config: &Config) where F: Fn(u32) -> String, { diff --git a/src/shape.rs b/src/shape.rs index 5524a21f4b7..d8971e05ef9 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -5,12 +5,12 @@ use std::ops::{Add, Sub}; use crate::Config; #[derive(Copy, Clone, Debug)] -pub struct Indent { +pub(crate) struct Indent { // Width of the block indent, in characters. Must be a multiple of // Config::tab_spaces. - pub block_indent: usize, + pub(crate) block_indent: usize, // Alignment in characters. - pub alignment: usize, + pub(crate) alignment: usize, } // INDENT_BUFFER.len() = 81 @@ -19,14 +19,14 @@ const INDENT_BUFFER: &str = "\n "; impl Indent { - pub fn new(block_indent: usize, alignment: usize) -> Indent { + pub(crate) fn new(block_indent: usize, alignment: usize) -> Indent { Indent { block_indent, alignment, } } - pub fn from_width(config: &Config, width: usize) -> Indent { + pub(crate) fn from_width(config: &Config, width: usize) -> Indent { if config.hard_tabs() { let tab_num = width / config.tab_spaces(); let alignment = width % config.tab_spaces(); @@ -36,23 +36,23 @@ impl Indent { } } - pub fn empty() -> Indent { + pub(crate) fn empty() -> Indent { Indent::new(0, 0) } - pub fn block_only(&self) -> Indent { + pub(crate) fn block_only(&self) -> Indent { Indent { block_indent: self.block_indent, alignment: 0, } } - pub fn block_indent(mut self, config: &Config) -> Indent { + pub(crate) fn block_indent(mut self, config: &Config) -> Indent { self.block_indent += config.tab_spaces(); self } - pub fn block_unindent(mut self, config: &Config) -> Indent { + pub(crate) fn block_unindent(mut self, config: &Config) -> Indent { if self.block_indent < config.tab_spaces() { Indent::new(self.block_indent, 0) } else { @@ -61,15 +61,15 @@ impl Indent { } } - pub fn width(&self) -> usize { + pub(crate) fn width(&self) -> usize { self.block_indent + self.alignment } - pub fn to_string(&self, config: &Config) -> Cow<'static, str> { + pub(crate) fn to_string(&self, config: &Config) -> Cow<'static, str> { self.to_string_inner(config, 1) } - pub fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { + pub(crate) fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { self.to_string_inner(config, 0) } @@ -137,13 +137,13 @@ impl Sub for Indent { } #[derive(Copy, Clone, Debug)] -pub struct Shape { - pub width: usize, +pub(crate) struct Shape { + pub(crate) width: usize, // The current indentation of code. - pub indent: Indent, + pub(crate) indent: Indent, // Indentation + any already emitted text on the first line of the current // statement. - pub offset: usize, + pub(crate) offset: usize, } impl Shape { @@ -162,7 +162,7 @@ impl Shape { // |<------------>| max width // |<---->| indent // |<--->| width - pub fn legacy(width: usize, indent: Indent) -> Shape { + pub(crate) fn legacy(width: usize, indent: Indent) -> Shape { Shape { width, indent, @@ -170,7 +170,7 @@ impl Shape { } } - pub fn indented(indent: Indent, config: &Config) -> Shape { + pub(crate) fn indented(indent: Indent, config: &Config) -> Shape { Shape { width: config.max_width().saturating_sub(indent.width()), indent, @@ -178,14 +178,14 @@ impl Shape { } } - pub fn with_max_width(&self, config: &Config) -> Shape { + pub(crate) fn with_max_width(&self, config: &Config) -> Shape { Shape { width: config.max_width().saturating_sub(self.indent.width()), ..*self } } - pub fn visual_indent(&self, extra_width: usize) -> Shape { + pub(crate) fn visual_indent(&self, extra_width: usize) -> Shape { let alignment = self.offset + extra_width; Shape { width: self.width, @@ -194,7 +194,7 @@ impl Shape { } } - pub fn block_indent(&self, extra_width: usize) -> Shape { + pub(crate) fn block_indent(&self, extra_width: usize) -> Shape { if self.indent.alignment == 0 { Shape { width: self.width, @@ -210,36 +210,36 @@ impl Shape { } } - pub fn block_left(&self, width: usize) -> Option { + pub(crate) fn block_left(&self, width: usize) -> Option { self.block_indent(width).sub_width(width) } - pub fn add_offset(&self, extra_width: usize) -> Shape { + pub(crate) fn add_offset(&self, extra_width: usize) -> Shape { Shape { offset: self.offset + extra_width, ..*self } } - pub fn block(&self) -> Shape { + pub(crate) fn block(&self) -> Shape { Shape { indent: self.indent.block_only(), ..*self } } - pub fn saturating_sub_width(&self, width: usize) -> Shape { + pub(crate) fn saturating_sub_width(&self, width: usize) -> Shape { self.sub_width(width).unwrap_or(Shape { width: 0, ..*self }) } - pub fn sub_width(&self, width: usize) -> Option { + pub(crate) fn sub_width(&self, width: usize) -> Option { Some(Shape { width: self.width.checked_sub(width)?, ..*self }) } - pub fn shrink_left(&self, width: usize) -> Option { + pub(crate) fn shrink_left(&self, width: usize) -> Option { Some(Shape { width: self.width.checked_sub(width)?, indent: self.indent + width, @@ -247,21 +247,21 @@ impl Shape { }) } - pub fn offset_left(&self, width: usize) -> Option { + pub(crate) fn offset_left(&self, width: usize) -> Option { self.add_offset(width).sub_width(width) } - pub fn used_width(&self) -> usize { + pub(crate) fn used_width(&self) -> usize { self.indent.block_indent + self.offset } - pub fn rhs_overhead(&self, config: &Config) -> usize { + pub(crate) fn rhs_overhead(&self, config: &Config) -> usize { config .max_width() .saturating_sub(self.used_width() + self.width) } - pub fn comment(&self, config: &Config) -> Shape { + pub(crate) fn comment(&self, config: &Config) -> Shape { let width = min( self.width, config.comment_width().saturating_sub(self.indent.width()), @@ -269,7 +269,7 @@ impl Shape { Shape { width, ..*self } } - pub fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { + pub(crate) fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> { let mut offset_indent = self.indent; offset_indent.alignment = self.offset; offset_indent.to_string_inner(config, 0) diff --git a/src/source_file.rs b/src/source_file.rs index 36483146f05..a7e0074cd2f 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -12,7 +12,7 @@ use crate::rustfmt_diff::{make_diff, print_diff, ModifiedLines}; use crate::formatting::FileRecord; // Append a newline to the end of each file. -pub fn append_newline(s: &mut String) { +pub(crate) fn append_newline(s: &mut String) { s.push_str("\n"); } @@ -38,7 +38,7 @@ where Ok(()) } -pub fn write_file( +pub(crate) fn write_file( source_map: Option<&SourceMap>, filename: &FileName, formatted_text: &str, diff --git a/src/source_map.rs b/src/source_map.rs index db4796eb08e..757d5f57db3 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -7,7 +7,7 @@ use crate::comment::FindUncommented; use crate::config::file_lines::LineRange; use crate::visitor::SnippetProvider; -pub trait SpanUtils { +pub(crate) trait SpanUtils { fn span_after(&self, original: Span, needle: &str) -> BytePos; fn span_after_last(&self, original: Span, needle: &str) -> BytePos; fn span_before(&self, original: Span, needle: &str) -> BytePos; @@ -16,7 +16,7 @@ pub trait SpanUtils { fn opt_span_before(&self, original: Span, needle: &str) -> Option; } -pub trait LineRangeUtils { +pub(crate) trait LineRangeUtils { /// Returns the `LineRange` that corresponds to `span` in `self`. /// /// # Panics diff --git a/src/spanned.rs b/src/spanned.rs index 118b84526e7..6e687a262c6 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -9,7 +9,7 @@ use crate::macros::MacroArg; use crate::utils::{mk_sp, outer_attributes}; /// Spanned returns a span including attributes, if available. -pub trait Spanned { +pub(crate) trait Spanned { fn span(&self) -> Span; } diff --git a/src/string.rs b/src/string.rs index 14220ba5d79..4898c9e425c 100644 --- a/src/string.rs +++ b/src/string.rs @@ -11,24 +11,24 @@ use crate::utils::{unicode_str_width, wrap_str}; const MIN_STRING: usize = 10; /// Describes the layout of a piece of text. -pub struct StringFormat<'a> { +pub(crate) struct StringFormat<'a> { /// The opening sequence of characters for the piece of text - pub opener: &'a str, + pub(crate) opener: &'a str, /// The closing sequence of characters for the piece of text - pub closer: &'a str, + pub(crate) closer: &'a str, /// The opening sequence of characters for a line - pub line_start: &'a str, + pub(crate) line_start: &'a str, /// The closing sequence of characters for a line - pub line_end: &'a str, + pub(crate) line_end: &'a str, /// The allocated box to fit the text into - pub shape: Shape, + pub(crate) shape: Shape, /// Trim trailing whitespaces - pub trim_end: bool, - pub config: &'a Config, + pub(crate) trim_end: bool, + pub(crate) config: &'a Config, } impl<'a> StringFormat<'a> { - pub fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { + pub(crate) fn new(shape: Shape, config: &'a Config) -> StringFormat<'a> { StringFormat { opener: "\"", closer: "\"", @@ -61,7 +61,7 @@ impl<'a> StringFormat<'a> { } } -pub fn rewrite_string<'a>( +pub(crate) fn rewrite_string<'a>( orig: &str, fmt: &StringFormat<'a>, newline_max_chars: usize, diff --git a/src/types.rs b/src/types.rs index 55367805ca3..3b548b0fb8d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -24,14 +24,14 @@ use crate::utils::{ }; #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum PathContext { +pub(crate) enum PathContext { Expr, Type, Import, } // Does not wrap on simple segments. -pub fn rewrite_path( +pub(crate) fn rewrite_path( context: &RewriteContext<'_>, path_context: PathContext, qself: Option<&ast::QSelf>, @@ -133,7 +133,7 @@ where } #[derive(Debug)] -pub enum SegmentParam<'a> { +pub(crate) enum SegmentParam<'a> { Const(&'a ast::AnonConst), LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), @@ -827,7 +827,7 @@ fn join_bounds( Some(result) } -pub fn can_be_overflowed_type(context: &RewriteContext<'_>, ty: &ast::Ty, len: usize) -> bool { +pub(crate) fn can_be_overflowed_type(context: &RewriteContext<'_>, ty: &ast::Ty, len: usize) -> bool { match ty.node { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { diff --git a/src/utils.rs b/src/utils.rs index a1ab5fd5aad..4576ca8c5bf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -17,15 +17,15 @@ use crate::config::{Config, Version}; use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; -pub const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; -pub const SKIP_ANNOTATION: &str = "rustfmt::skip"; +pub(crate) const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; +pub(crate) const SKIP_ANNOTATION: &str = "rustfmt::skip"; -pub fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: ast::Ident) -> &'a str { +pub(crate) fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: ast::Ident) -> &'a str { context.snippet(ident.span) } // Computes the length of a string's last line, minus offset. -pub fn extra_offset(text: &str, shape: Shape) -> usize { +pub(crate) fn extra_offset(text: &str, shape: Shape) -> usize { match text.rfind('\n') { // 1 for newline character Some(idx) => text.len().saturating_sub(idx + 1 + shape.used_width()), @@ -33,7 +33,7 @@ pub fn extra_offset(text: &str, shape: Shape) -> usize { } } -pub fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { +pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { match (&a.node, &b.node) { ( VisibilityKind::Restricted { path: p, .. }, @@ -54,7 +54,7 @@ pub fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { } // Uses Cow to avoid allocating in the common cases. -pub fn format_visibility(context: &RewriteContext<'_>, vis: &Visibility) -> Cow<'static, str> { +pub(crate) fn format_visibility(context: &RewriteContext<'_>, vis: &Visibility) -> Cow<'static, str> { match vis.node { VisibilityKind::Public => Cow::from("pub "), VisibilityKind::Inherited => Cow::from(""), @@ -78,7 +78,7 @@ pub fn format_visibility(context: &RewriteContext<'_>, vis: &Visibility) -> Cow< } #[inline] -pub fn format_async(is_async: ast::IsAsync) -> &'static str { +pub(crate) fn format_async(is_async: ast::IsAsync) -> &'static str { match is_async { ast::IsAsync::Async { .. } => "async ", ast::IsAsync::NotAsync => "", @@ -86,7 +86,7 @@ pub fn format_async(is_async: ast::IsAsync) -> &'static str { } #[inline] -pub fn format_constness(constness: ast::Constness) -> &'static str { +pub(crate) fn format_constness(constness: ast::Constness) -> &'static str { match constness { ast::Constness::Const => "const ", ast::Constness::NotConst => "", @@ -94,7 +94,7 @@ pub fn format_constness(constness: ast::Constness) -> &'static str { } #[inline] -pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { +pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { match defaultness { ast::Defaultness::Default => "default ", ast::Defaultness::Final => "", @@ -102,7 +102,7 @@ pub fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { } #[inline] -pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { +pub(crate) fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { match unsafety { ast::Unsafety::Unsafe => "unsafe ", ast::Unsafety::Normal => "", @@ -110,7 +110,7 @@ pub fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { } #[inline] -pub fn format_auto(is_auto: ast::IsAuto) -> &'static str { +pub(crate) fn format_auto(is_auto: ast::IsAuto) -> &'static str { match is_auto { ast::IsAuto::Yes => "auto ", ast::IsAuto::No => "", @@ -118,7 +118,7 @@ pub fn format_auto(is_auto: ast::IsAuto) -> &'static str { } #[inline] -pub fn format_mutability(mutability: ast::Mutability) -> &'static str { +pub(crate) fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { ast::Mutability::Mutable => "mut ", ast::Mutability::Immutable => "", @@ -126,7 +126,7 @@ pub fn format_mutability(mutability: ast::Mutability) -> &'static str { } #[inline] -pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { +pub(crate) fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { if abi == abi::Abi::Rust && !is_mod { Cow::from("") } else if abi == abi::Abi::C && !explicit_abi { @@ -138,12 +138,12 @@ pub fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'stati #[inline] // Transform `Vec>` into `Vec<&T>` -pub fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { +pub(crate) fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { vec.iter().map(|x| &**x).collect::>() } #[inline] -pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { +pub(crate) fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { attrs .iter() .filter(|a| a.style == style) @@ -152,50 +152,50 @@ pub fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec } #[inline] -pub fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { +pub(crate) fn inner_attributes(attrs: &[ast::Attribute]) -> Vec { filter_attributes(attrs, ast::AttrStyle::Inner) } #[inline] -pub fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { +pub(crate) fn outer_attributes(attrs: &[ast::Attribute]) -> Vec { filter_attributes(attrs, ast::AttrStyle::Outer) } #[inline] -pub fn is_single_line(s: &str) -> bool { +pub(crate) fn is_single_line(s: &str) -> bool { s.chars().find(|&c| c == '\n').is_none() } #[inline] -pub fn first_line_contains_single_line_comment(s: &str) -> bool { +pub(crate) fn first_line_contains_single_line_comment(s: &str) -> bool { s.lines().next().map_or(false, |l| l.contains("//")) } #[inline] -pub fn last_line_contains_single_line_comment(s: &str) -> bool { +pub(crate) fn last_line_contains_single_line_comment(s: &str) -> bool { s.lines().last().map_or(false, |l| l.contains("//")) } #[inline] -pub fn is_attributes_extendable(attrs_str: &str) -> bool { +pub(crate) fn is_attributes_extendable(attrs_str: &str) -> bool { !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) } // The width of the first line in s. #[inline] -pub fn first_line_width(s: &str) -> usize { +pub(crate) fn first_line_width(s: &str) -> usize { unicode_str_width(s.splitn(2, '\n').next().unwrap_or("")) } // The width of the last line in s. #[inline] -pub fn last_line_width(s: &str) -> usize { +pub(crate) fn last_line_width(s: &str) -> usize { unicode_str_width(s.rsplitn(2, '\n').next().unwrap_or("")) } // The total used width of the last line. #[inline] -pub fn last_line_used_width(s: &str, offset: usize) -> usize { +pub(crate) fn last_line_used_width(s: &str, offset: usize) -> usize { if s.contains('\n') { last_line_width(s) } else { @@ -204,7 +204,7 @@ pub fn last_line_used_width(s: &str, offset: usize) -> usize { } #[inline] -pub fn trimmed_last_line_width(s: &str) -> usize { +pub(crate) fn trimmed_last_line_width(s: &str) -> usize { unicode_str_width(match s.rfind('\n') { Some(n) => s[(n + 1)..].trim(), None => s.trim(), @@ -212,7 +212,7 @@ pub fn trimmed_last_line_width(s: &str) -> usize { } #[inline] -pub fn last_line_extendable(s: &str) -> bool { +pub(crate) fn last_line_extendable(s: &str) -> bool { if s.ends_with("\"#") { return true; } @@ -250,14 +250,14 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { } #[inline] -pub fn contains_skip(attrs: &[Attribute]) -> bool { +pub(crate) fn contains_skip(attrs: &[Attribute]) -> bool { attrs .iter() .any(|a| a.meta().map_or(false, |a| is_skip(&a))) } #[inline] -pub fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { +pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { match expr.node { ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { context.config.trailing_semicolon() @@ -267,7 +267,7 @@ pub fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> boo } #[inline] -pub fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> bool { +pub(crate) fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> bool { match stmt.node { ast::StmtKind::Semi(ref expr) => match expr.node { ast::ExprKind::While(..) @@ -285,7 +285,7 @@ pub fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> boo } #[inline] -pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { +pub(crate) fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { match stmt.node { ast::StmtKind::Expr(ref expr) => Some(expr), _ => None, @@ -293,7 +293,7 @@ pub fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { } #[inline] -pub fn count_newlines(input: &str) -> usize { +pub(crate) fn count_newlines(input: &str) -> usize { // Using bytes to omit UTF-8 decoding bytecount::count(input.as_bytes(), b'\n') } @@ -306,7 +306,7 @@ macro_rules! source { }; } -pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span { +pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi, NO_EXPANSION) } @@ -340,7 +340,7 @@ macro_rules! skip_out_of_file_lines_range_visitor { // Wraps String in an Option. Returns Some when the string adheres to the // Rewrite constraints defined for the Rewrite trait and None otherwise. -pub fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { +pub(crate) fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { if is_valid_str(&filter_normal_code(&s), max_width, shape) { Some(s) } else { @@ -376,7 +376,7 @@ fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool { } #[inline] -pub fn colon_spaces(config: &Config) -> &'static str { +pub(crate) fn colon_spaces(config: &Config) -> &'static str { let before = config.space_before_colon(); let after = config.space_after_colon(); match (before, after) { @@ -388,7 +388,7 @@ pub fn colon_spaces(config: &Config) -> &'static str { } #[inline] -pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { +pub(crate) fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { match e.node { ast::ExprKind::Call(ref e, _) | ast::ExprKind::Binary(_, ref e, _) @@ -405,18 +405,18 @@ pub fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { } #[inline] -pub fn starts_with_newline(s: &str) -> bool { +pub(crate) fn starts_with_newline(s: &str) -> bool { s.starts_with('\n') || s.starts_with("\r\n") } #[inline] -pub fn first_line_ends_with(s: &str, c: char) -> bool { +pub(crate) fn first_line_ends_with(s: &str, c: char) -> bool { s.lines().next().map_or(false, |l| l.ends_with(c)) } // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. -pub fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool { +pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool { match expr.node { ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) @@ -448,7 +448,7 @@ pub fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) /// Removes trailing spaces from the specified snippet. We do not remove spaces /// inside strings or comments. -pub fn remove_trailing_white_spaces(text: &str) -> String { +pub(crate) fn remove_trailing_white_spaces(text: &str) -> String { let mut buffer = String::with_capacity(text.len()); let mut space_buffer = String::with_capacity(128); for (char_kind, c) in CharClasses::new(text.chars()) { @@ -503,7 +503,7 @@ pub fn remove_trailing_white_spaces(text: &str) -> String { /// ), /// } /// ``` -pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Option { +pub(crate) fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Option { let mut lines = LineClasses::new(orig); let first_line = lines.next().map(|(_, s)| s.trim_end().to_owned())?; let mut trimmed_lines = Vec::with_capacity(16); @@ -570,12 +570,12 @@ pub fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> /// Based on the given line, determine if the next line can be indented or not. /// This allows to preserve the indentation of multi-line literals. -pub fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Config) -> bool { +pub(crate) fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Config) -> bool { !(kind.is_string() || (config.version() == Version::Two && kind.is_commented_string())) || line.ends_with('\\') } -pub fn is_empty_line(s: &str) -> bool { +pub(crate) fn is_empty_line(s: &str) -> bool { s.is_empty() || s.chars().all(char::is_whitespace) } @@ -605,7 +605,7 @@ pub(crate) fn unicode_str_width(s: &str) -> usize { s.width() } -pub fn get_skip_macro_names(attrs: &[ast::Attribute]) -> Vec { +pub(crate) fn get_skip_macro_names(attrs: &[ast::Attribute]) -> Vec { let mut skip_macro_names = vec![]; for attr in attrs { // syntax::ast::Path is implemented partialEq diff --git a/src/vertical.rs b/src/vertical.rs index 0b69c3603d4..62cc7d8b33d 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -19,7 +19,7 @@ use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; -pub trait AlignedItem { +pub(crate) trait AlignedItem { fn skip(&self) -> bool; fn get_span(&self) -> Span; fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; @@ -107,7 +107,7 @@ impl AlignedItem for ast::Field { } } -pub fn rewrite_with_alignment( +pub(crate) fn rewrite_with_alignment( fields: &[T], context: &RewriteContext<'_>, shape: Shape, diff --git a/src/visitor.rs b/src/visitor.rs index b1d3b12ea14..f317e015423 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -27,7 +27,7 @@ use crate::utils::{ use crate::{ErrorKind, FormatReport, FormattingError}; /// Creates a string slice corresponding to the specified span. -pub struct SnippetProvider<'a> { +pub(crate) struct SnippetProvider<'a> { /// A pointer to the content of the file we are formatting. big_snippet: &'a str, /// A position of the start of `big_snippet`, used as an offset. @@ -35,13 +35,13 @@ pub struct SnippetProvider<'a> { } impl<'a> SnippetProvider<'a> { - pub fn span_to_snippet(&self, span: Span) -> Option<&str> { + pub(crate) fn span_to_snippet(&self, span: Span) -> Option<&str> { let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; Some(&self.big_snippet[start_index..end_index]) } - pub fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { + pub(crate) fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { let start_pos = start_pos.to_usize(); SnippetProvider { big_snippet, @@ -50,24 +50,24 @@ impl<'a> SnippetProvider<'a> { } } -pub struct FmtVisitor<'a> { +pub(crate) struct FmtVisitor<'a> { parent_context: Option<&'a RewriteContext<'a>>, - pub parse_session: &'a ParseSess, - pub source_map: &'a SourceMap, - pub buffer: String, - pub last_pos: BytePos, + pub(crate) parse_session: &'a ParseSess, + pub(crate) source_map: &'a SourceMap, + pub(crate) buffer: String, + pub(crate) last_pos: BytePos, // FIXME: use an RAII util or closure for indenting - pub block_indent: Indent, - pub config: &'a Config, - pub is_if_else_block: bool, - pub snippet_provider: &'a SnippetProvider<'a>, - pub line_number: usize, + pub(crate) block_indent: Indent, + pub(crate) config: &'a Config, + pub(crate) is_if_else_block: bool, + pub(crate) snippet_provider: &'a SnippetProvider<'a>, + pub(crate) line_number: usize, /// List of 1-based line ranges which were annotated with skip /// Both bounds are inclusifs. - pub skipped_range: Vec<(usize, usize)>, - pub macro_rewrite_failure: bool, + pub(crate) skipped_range: Vec<(usize, usize)>, + pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, - pub skip_macro_names: RefCell>, + pub(crate) skip_macro_names: RefCell>, } impl<'a> Drop for FmtVisitor<'a> { @@ -85,7 +85,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.parent_context = Some(context); } - pub fn shape(&self) -> Shape { + pub(crate) fn shape(&self) -> Shape { Shape::indented(self.block_indent, self.config) } @@ -124,7 +124,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub fn visit_block( + pub(crate) fn visit_block( &mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>, @@ -300,7 +300,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_block(block, inner_attrs, true) } - pub fn visit_item(&mut self, item: &ast::Item) { + pub(crate) fn visit_item(&mut self, item: &ast::Item) { skip_out_of_file_lines_range_visitor!(self, item.span); // This is where we bail out if there is a skip attribute. This is only @@ -466,7 +466,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.skip_macro_names = temp_skip_macro_names; } - pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + pub(crate) fn visit_trait_item(&mut self, ti: &ast::TraitItem) { skip_out_of_file_lines_range_visitor!(self, ti.span); if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { @@ -510,7 +510,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + pub(crate) fn visit_impl_item(&mut self, ii: &ast::ImplItem) { skip_out_of_file_lines_range_visitor!(self, ii.span); if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { @@ -567,7 +567,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(mac.span, rewrite); } - pub fn push_str(&mut self, s: &str) { + pub(crate) fn push_str(&mut self, s: &str) { self.line_number += count_newlines(s); self.buffer.push_str(s); } @@ -583,12 +583,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = source!(self, span).hi(); } - pub fn push_rewrite(&mut self, span: Span, rewrite: Option) { + pub(crate) fn push_rewrite(&mut self, span: Span, rewrite: Option) { self.format_missing_with_indent(source!(self, span).lo()); self.push_rewrite_inner(span, rewrite); } - pub fn push_skipped_with_span( + pub(crate) fn push_skipped_with_span( &mut self, attrs: &[ast::Attribute], item_span: Span, @@ -611,7 +611,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.skipped_range.push((lo, hi)); } - pub fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { + pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { let mut visitor = FmtVisitor::from_source_map( ctx.parse_session, ctx.config, @@ -650,16 +650,16 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { + pub(crate) fn opt_snippet(&'b self, span: Span) -> Option<&'a str> { self.snippet_provider.span_to_snippet(span) } - pub fn snippet(&'b self, span: Span) -> &'a str { + pub(crate) fn snippet(&'b self, span: Span) -> &'a str { self.opt_snippet(span).unwrap() } // Returns true if we should skip the following item. - pub fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { + pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { if attr.name() == DEPR_SKIP_ANNOTATION { let file_name = self.source_map.span_to_filename(attr.span).into(); @@ -810,13 +810,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub fn format_separate_mod(&mut self, m: &ast::Mod, source_file: &source_map::SourceFile) { + pub(crate) fn format_separate_mod( + &mut self, + m: &ast::Mod, + source_file: &source_map::SourceFile, + ) { self.block_indent = Indent::empty(); self.walk_mod_items(m); self.format_missing_with_indent(source_file.end_pos); } - pub fn skip_empty_lines(&mut self, end_pos: BytePos) { + pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) { while let Some(pos) = self .snippet_provider .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") @@ -831,7 +835,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub fn with_context(&mut self, f: F) -> Option + pub(crate) fn with_context(&mut self, f: F) -> Option where F: Fn(&RewriteContext<'_>) -> Option, { @@ -847,7 +851,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { result } - pub fn get_context(&self) -> RewriteContext<'_> { + pub(crate) fn get_context(&self) -> RewriteContext<'_> { RewriteContext { parse_session: self.parse_session, source_map: self.source_map, -- cgit 1.4.1-3-g733a5 From d1c1f8e61e5773fdbcb4d548820a543549c4a7b9 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Thu, 9 May 2019 21:13:32 +0200 Subject: Run rustfmt --- src/attr.rs | 5 ++++- src/types.rs | 6 +++++- src/utils.rs | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index a1f5de37c55..498d6e4d851 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -37,7 +37,10 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { } /// Returns attributes that are within `outer_span`. -pub(crate) fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec { +pub(crate) fn filter_inline_attrs( + attrs: &[ast::Attribute], + outer_span: Span, +) -> Vec { attrs .iter() .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi()) diff --git a/src/types.rs b/src/types.rs index 3b548b0fb8d..eb90a67d0dc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -827,7 +827,11 @@ fn join_bounds( Some(result) } -pub(crate) fn can_be_overflowed_type(context: &RewriteContext<'_>, ty: &ast::Ty, len: usize) -> bool { +pub(crate) fn can_be_overflowed_type( + context: &RewriteContext<'_>, + ty: &ast::Ty, + len: usize, +) -> bool { match ty.node { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { diff --git a/src/utils.rs b/src/utils.rs index 4576ca8c5bf..9a0a29dc5c3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -54,7 +54,10 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { } // Uses Cow to avoid allocating in the common cases. -pub(crate) fn format_visibility(context: &RewriteContext<'_>, vis: &Visibility) -> Cow<'static, str> { +pub(crate) fn format_visibility( + context: &RewriteContext<'_>, + vis: &Visibility, +) -> Cow<'static, str> { match vis.node { VisibilityKind::Public => Cow::from("pub "), VisibilityKind::Inherited => Cow::from(""), @@ -143,7 +146,10 @@ pub(crate) fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { } #[inline] -pub(crate) fn filter_attributes(attrs: &[ast::Attribute], style: ast::AttrStyle) -> Vec { +pub(crate) fn filter_attributes( + attrs: &[ast::Attribute], + style: ast::AttrStyle, +) -> Vec { attrs .iter() .filter(|a| a.style == style) @@ -503,7 +509,11 @@ pub(crate) fn remove_trailing_white_spaces(text: &str) -> String { /// ), /// } /// ``` -pub(crate) fn trim_left_preserve_layout(orig: &str, indent: Indent, config: &Config) -> Option { +pub(crate) fn trim_left_preserve_layout( + orig: &str, + indent: Indent, + config: &Config, +) -> Option { let mut lines = LineClasses::new(orig); let first_line = lines.next().map(|(_, s)| s.trim_end().to_owned())?; let mut trimmed_lines = Vec::with_capacity(16); -- cgit 1.4.1-3-g733a5 From a956a2053257131f794bcad6a88edf5370b93e23 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 10 May 2019 21:22:52 +0800 Subject: Revert "Revert "Change config option from format_doc_comments to format_code_in_doc_comments."" This reverts commit 97d7216cd4ebce511d5707ec5dd8b7b8fe771cba. --- Configurations.md | 4 ++-- src/comment.rs | 4 ++-- src/config/mod.rs | 2 +- tests/source/doc-comment-with-example.rs | 2 +- tests/source/invalid-rust-code-in-doc-comment.rs | 2 +- tests/source/issue-2520.rs | 2 +- tests/source/issue-2523.rs | 2 +- tests/source/issue-3055/original.rs | 2 +- tests/source/itemized-blocks/no_wrap.rs | 2 +- tests/source/itemized-blocks/wrap.rs | 2 +- tests/target/doc-comment-with-example.rs | 2 +- tests/target/invalid-rust-code-in-doc-comment.rs | 2 +- tests/target/issue-2520.rs | 2 +- tests/target/issue-2523.rs | 2 +- tests/target/issue-3055/original.rs | 2 +- tests/target/itemized-blocks/no_wrap.rs | 2 +- tests/target/itemized-blocks/wrap.rs | 2 +- 17 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index f51c464b6f9..dc91a3d255a 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1978,9 +1978,9 @@ fn main() { } ``` -## `format_doc_comments` +## `format_code_in_doc_comments` -Format code snippet in doc comments. +Format code snippet included in doc comments. - **Default value**: `false` - **Possible values**: `true`, `false` diff --git a/src/comment.rs b/src/comment.rs index b8dcae23521..0a3062583c5 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -353,7 +353,7 @@ fn identify_comment( trim_left_preserve_layout(first_group, shape.indent, config)? } else if !config.normalize_comments() && !config.wrap_comments() - && !config.format_doc_comments() + && !config.format_code_in_doc_comments() { light_rewrite_comment(first_group, shape.indent, config, is_doc_comment) } else { @@ -656,7 +656,7 @@ impl<'a> CommentRewrite<'a> { _ => { let mut config = self.fmt.config.clone(); config.set().wrap_comments(false); - if config.format_doc_comments() { + if config.format_code_in_doc_comments() { if let Some(s) = crate::format_code_block(&self.code_block_buffer, &config) { diff --git a/src/config/mod.rs b/src/config/mod.rs index c0221e93e02..f04074e4f32 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -37,7 +37,7 @@ create_config! { // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; - format_doc_comments: bool, false, false, "Format doc comments."; + format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments."; comment_width: usize, 80, false, "Maximum length of comments. No effect unless wrap_comments = true"; normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible"; diff --git a/tests/source/doc-comment-with-example.rs b/tests/source/doc-comment-with-example.rs index 58d98acfa25..e74ceefd195 100644 --- a/tests/source/doc-comment-with-example.rs +++ b/tests/source/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Foo /// diff --git a/tests/source/invalid-rust-code-in-doc-comment.rs b/tests/source/invalid-rust-code-in-doc-comment.rs index 6d33dcfce55..835b0261b76 100644 --- a/tests/source/invalid-rust-code-in-doc-comment.rs +++ b/tests/source/invalid-rust-code-in-doc-comment.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// ```rust /// if (true) { … } diff --git a/tests/source/issue-2520.rs b/tests/source/issue-2520.rs index 9ea522c4fe4..5a23f10430d 100644 --- a/tests/source/issue-2520.rs +++ b/tests/source/issue-2520.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! ```rust //! println!( "hello, world" ); diff --git a/tests/source/issue-2523.rs b/tests/source/issue-2523.rs index 71aed6ac535..491d5c38fc2 100644 --- a/tests/source/issue-2523.rs +++ b/tests/source/issue-2523.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/source/issue-3055/original.rs b/tests/source/issue-3055/original.rs index eaf00afa3d3..ad505547ac0 100644 --- a/tests/source/issue-3055/original.rs +++ b/tests/source/issue-3055/original.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc commodo ultricies dui. /// diff --git a/tests/source/itemized-blocks/no_wrap.rs b/tests/source/itemized-blocks/no_wrap.rs index a0c546ad18e..a7b6a10a010 100644 --- a/tests/source/itemized-blocks/no_wrap.rs +++ b/tests/source/itemized-blocks/no_wrap.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/source/itemized-blocks/wrap.rs b/tests/source/itemized-blocks/wrap.rs index 14fc8daa2e9..955cc698b79 100644 --- a/tests/source/itemized-blocks/wrap.rs +++ b/tests/source/itemized-blocks/wrap.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 //! This is a list: diff --git a/tests/target/doc-comment-with-example.rs b/tests/target/doc-comment-with-example.rs index bec931d13c7..c5a4e779ea2 100644 --- a/tests/target/doc-comment-with-example.rs +++ b/tests/target/doc-comment-with-example.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Foo /// diff --git a/tests/target/invalid-rust-code-in-doc-comment.rs b/tests/target/invalid-rust-code-in-doc-comment.rs index 2593410a418..f8479d4e345 100644 --- a/tests/target/invalid-rust-code-in-doc-comment.rs +++ b/tests/target/invalid-rust-code-in-doc-comment.rs @@ -1,4 +1,4 @@ -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// ```rust /// if (true) { … } diff --git a/tests/target/issue-2520.rs b/tests/target/issue-2520.rs index 7d22b2b665a..7c134d3972b 100644 --- a/tests/target/issue-2520.rs +++ b/tests/target/issue-2520.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! ```rust //! println!("hello, world"); diff --git a/tests/target/issue-2523.rs b/tests/target/issue-2523.rs index c0118e53780..612f93249ac 100644 --- a/tests/target/issue-2523.rs +++ b/tests/target/issue-2523.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // Do not unindent macro calls in comment with unformattable syntax. //! ```rust diff --git a/tests/target/issue-3055/original.rs b/tests/target/issue-3055/original.rs index 1fb35d50682..de27ccfb344 100644 --- a/tests/target/issue-3055/original.rs +++ b/tests/target/issue-3055/original.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true /// Vestibulum elit nibh, rhoncus non, euismod sit amet, pretium eu, enim. Nunc /// commodo ultricies dui. diff --git a/tests/target/itemized-blocks/no_wrap.rs b/tests/target/itemized-blocks/no_wrap.rs index a1f9c39a115..de885638272 100644 --- a/tests/target/itemized-blocks/no_wrap.rs +++ b/tests/target/itemized-blocks/no_wrap.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true //! This is a list: //! * Outer diff --git a/tests/target/itemized-blocks/wrap.rs b/tests/target/itemized-blocks/wrap.rs index 967a38b91ae..a4907303c9e 100644 --- a/tests/target/itemized-blocks/wrap.rs +++ b/tests/target/itemized-blocks/wrap.rs @@ -1,5 +1,5 @@ // rustfmt-wrap_comments: true -// rustfmt-format_doc_comments: true +// rustfmt-format_code_in_doc_comments: true // rustfmt-max_width: 50 //! This is a list: -- cgit 1.4.1-3-g733a5 From 47a0f78b3b7087550b82564f3bfe0b3701683c66 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Sat, 11 May 2019 15:05:08 +0200 Subject: Fix normalisation of multi-line doc attributes --- src/attr.rs | 11 +++--- src/attr/doc_comment.rs | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 src/attr/doc_comment.rs (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 498d6e4d851..378c56b83a3 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -3,6 +3,7 @@ use syntax::ast; use syntax::source_map::{BytePos, Span, DUMMY_SP}; +use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; use crate::config::lists::*; use crate::config::IndentStyle; @@ -14,6 +15,8 @@ use crate::shape::Shape; use crate::types::{rewrite_path, PathContext}; use crate::utils::{count_newlines, mk_sp}; +mod doc_comment; + /// Returns attributes on the given statement. pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { match stmt.node { @@ -331,11 +334,9 @@ impl Rewrite for ast::Attribute { ast::AttrStyle::Outer => CommentStyle::TripleSlash, }; - // Remove possible whitespace from the `CommentStyle::opener()` so that - // the literal itself has control over the comment's leading spaces. - let opener = comment_style.opener().trim_end(); - - let doc_comment = format!("{}{}", opener, literal); + let doc_comment_formatter = + DocCommentFormatter::new(literal, comment_style); + let doc_comment = format!("{}", doc_comment_formatter); return rewrite_doc_comment( &doc_comment, shape.comment(context.config), diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs new file mode 100644 index 00000000000..e687492fb89 --- /dev/null +++ b/src/attr/doc_comment.rs @@ -0,0 +1,92 @@ +use crate::comment::CommentStyle; +use std::fmt::{self, Display}; +use syntax_pos::symbol::Symbol; + +pub(super) struct DocCommentFormatter<'a> { + literal: &'a Symbol, + style: CommentStyle<'a>, +} + +impl<'a> DocCommentFormatter<'a> { + pub(super) fn new(literal: &'a Symbol, style: CommentStyle<'a>) -> Self { + Self { literal, style } + } +} + +impl Display for DocCommentFormatter<'_> { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + let opener = self.style.opener().trim_end(); + + let literal_as_str = self.literal.as_str().get(); + let line_count = literal_as_str.lines().count(); + let last_line_index = line_count - 1; + let lines = literal_as_str.lines().enumerate(); + + for (index, line) in lines { + if index == last_line_index { + write!(formatter, "{}{}", opener, line)?; + } else { + writeln!(formatter, "{}{}", opener, line)?; + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use syntax_pos::{Globals, GLOBALS}; + + #[test] + fn literal_controls_leading_spaces() { + test_doc_comment_is_formatted_correctly( + " Lorem ipsum", + "/// Lorem ipsum", + CommentStyle::TripleSlash, + ); + } + + #[test] + fn single_line_doc_comment_is_formatted_correctly() { + test_doc_comment_is_formatted_correctly( + "Lorem ipsum", + "///Lorem ipsum", + CommentStyle::TripleSlash, + ); + } + + #[test] + fn multi_line_doc_comment_is_formatted_correctly() { + test_doc_comment_is_formatted_correctly( + "Lorem ipsum\nDolor sit amet", + "///Lorem ipsum\n///Dolor sit amet", + CommentStyle::TripleSlash, + ); + } + + #[test] + fn whitespace_within_lines_is_preserved() { + test_doc_comment_is_formatted_correctly( + " Lorem ipsum \n Dolor sit amet ", + "/// Lorem ipsum \n/// Dolor sit amet ", + CommentStyle::TripleSlash, + ); + } + + fn test_doc_comment_is_formatted_correctly( + literal: &str, + expected_comment: &str, + style: CommentStyle<'_>, + ) { + GLOBALS.set(&Globals::new(), || { + let literal = Symbol::gensym(literal); + + assert_eq!( + expected_comment, + format!("{}", DocCommentFormatter::new(&literal, style)) + ); + }); + } +} -- cgit 1.4.1-3-g733a5 From 4ac0d35ebb8aeae27c8861850b59a747ac44f194 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Sun, 12 May 2019 23:03:48 +0200 Subject: Only run test on nightly --- src/test/mod.rs | 27 ++++++++++++++++++----- tests/source/normalize_multiline_doc_attribute.rs | 2 ++ tests/target/normalize_multiline_doc_attribute.rs | 2 ++ 3 files changed, 25 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 23f6a69b8d1..20c4bce5d81 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -259,9 +259,9 @@ fn assert_output(source: &Path, expected_filename: &Path) { #[test] fn idempotence_tests() { run_test_with(&TestSetting::default(), || { - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - _ => return, // these tests require nightly + // these tests require nightly + if !is_nightly() { + return; } // Get all files in the tests/target directory. let files = get_test_files(Path::new("tests/target"), true); @@ -277,9 +277,9 @@ fn idempotence_tests() { // no warnings are emitted. #[test] fn self_tests() { - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - _ => return, // Issue-3443: these tests require nightly + // Issue-3443: these tests require nightly + if !is_nightly() { + return; } let mut files = get_test_files(Path::new("tests"), false); let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; @@ -313,6 +313,11 @@ fn self_tests() { ); } +fn is_nightly() -> bool { + let release_channel = option_env!("CFG_RELEASE_CHANNEL"); + release_channel.is_none() || release_channel == Some("nightly") +} + #[test] fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); @@ -426,6 +431,16 @@ fn check_files(files: Vec, opt_config: &Option) -> (Vec Date: Mon, 13 May 2019 09:40:16 +0200 Subject: Ignore unstable key when overriding config --- src/test/mod.rs | 2 +- tests/config/normalize_multiline_doc_attribute.toml | 1 - tests/source/normalize_multiline_doc_attribute.rs | 1 + tests/target/normalize_multiline_doc_attribute.rs | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 tests/config/normalize_multiline_doc_attribute.toml (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 20c4bce5d81..101a8c07fd9 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -500,7 +500,7 @@ fn read_config(filename: &Path) -> Config { }; for (key, val) in &sig_comments { - if key != "target" && key != "config" { + if key != "target" && key != "config" && key != "unstable" { config.override_value(key, val); if config.is_default(key) { warn!("Default value {} used explicitly for {}", val, key); diff --git a/tests/config/normalize_multiline_doc_attribute.toml b/tests/config/normalize_multiline_doc_attribute.toml deleted file mode 100644 index e8bb3d9a050..00000000000 --- a/tests/config/normalize_multiline_doc_attribute.toml +++ /dev/null @@ -1 +0,0 @@ -normalize_doc_attributes = true diff --git a/tests/source/normalize_multiline_doc_attribute.rs b/tests/source/normalize_multiline_doc_attribute.rs index fd4bf796c95..91d93091244 100644 --- a/tests/source/normalize_multiline_doc_attribute.rs +++ b/tests/source/normalize_multiline_doc_attribute.rs @@ -1,4 +1,5 @@ // rustfmt-unstable: true +// rustfmt-normalize_doc_attributes: true #[doc = "This comment is split diff --git a/tests/target/normalize_multiline_doc_attribute.rs b/tests/target/normalize_multiline_doc_attribute.rs index 8227317512a..3b30525cace 100644 --- a/tests/target/normalize_multiline_doc_attribute.rs +++ b/tests/target/normalize_multiline_doc_attribute.rs @@ -1,4 +1,5 @@ // rustfmt-unstable: true +// rustfmt-normalize_doc_attributes: true ///This comment ///is split -- cgit 1.4.1-3-g733a5 From b875fe94859bbe37465219c0456583dbc0bed206 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Tue, 14 May 2019 20:23:55 +0200 Subject: Name field more verbosely This makes the comment above it obsolete --- src/formatting.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index eff7b552fab..47d885ef2e3 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -458,8 +458,7 @@ struct FormatLines<'a> { errors: Vec, issue_seeker: BadIssueSeeker, line_buffer: String, - // `true` if the current line contains a string literal. - is_string: bool, + current_line_contains_string_literal: bool, format_line: bool, allow_issue_seek: bool, config: &'a Config, @@ -483,7 +482,7 @@ impl<'a> FormatLines<'a> { allow_issue_seek: !issue_seeker.is_disabled(), issue_seeker, line_buffer: String::with_capacity(config.max_width() * 2), - is_string: false, + current_line_contains_string_literal: false, format_line: config.file_lines().contains_line(name, 1), config, } @@ -547,7 +546,7 @@ impl<'a> FormatLines<'a> { && !self.is_skipped_line() && self.should_report_error(kind, &error_kind) { - let is_string = self.is_string; + let is_string = self.current_line_contains_string_literal; self.push_err(error_kind, kind.is_comment(), is_string); } } @@ -561,7 +560,7 @@ impl<'a> FormatLines<'a> { self.newline_count += 1; self.last_was_space = false; self.line_buffer.clear(); - self.is_string = false; + self.current_line_contains_string_literal = false; } fn char(&mut self, c: char, kind: FullCodeCharKind) { @@ -574,7 +573,7 @@ impl<'a> FormatLines<'a> { self.last_was_space = c.is_whitespace(); self.line_buffer.push(c); if kind.is_string() { - self.is_string = true; + self.current_line_contains_string_literal = true; } } @@ -589,12 +588,14 @@ impl<'a> FormatLines<'a> { } fn should_report_error(&self, char_kind: FullCodeCharKind, error_kind: &ErrorKind) -> bool { - let allow_error_report = - if char_kind.is_comment() || self.is_string || error_kind.is_comment() { - self.config.error_on_unformatted() - } else { - true - }; + let allow_error_report = if char_kind.is_comment() + || self.current_line_contains_string_literal + || error_kind.is_comment() + { + self.config.error_on_unformatted() + } else { + true + }; match error_kind { ErrorKind::LineOverflow(..) => { -- cgit 1.4.1-3-g733a5 From 6a406a822d0bd05f0b045be6dc6db5dab79e6a06 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Tue, 14 May 2019 20:38:28 +0200 Subject: Return iterator instead of collecting early --- src/attr.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 498d6e4d851..e40b16314fd 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -53,12 +53,11 @@ fn is_derive(attr: &ast::Attribute) -> bool { } /// Returns the arguments of `#[derive(...)]`. -fn get_derive_spans(attr: &ast::Attribute) -> Option> { +fn get_derive_spans<'a>(attr: &'a ast::Attribute) -> Option + 'a> { attr.meta_item_list().map(|meta_item_list| { meta_item_list - .iter() + .into_iter() .map(|nested_meta_item| nested_meta_item.span) - .collect() }) } @@ -411,10 +410,11 @@ impl<'a> Rewrite for [ast::Attribute] { // Handle derives if we will merge them. if context.config.merge_derives() && is_derive(&attrs[0]) { let derives = take_while_with_pred(context, attrs, is_derive); - let mut derive_spans = vec![]; - for derive in derives { - derive_spans.append(&mut get_derive_spans(derive)?); - } + let derive_spans: Vec<_> = derives + .iter() + .filter_map(get_derive_spans) + .flatten() + .collect(); let derive_str = format_derive(&derive_spans, attr_prefix(&attrs[0]), shape, context)?; result.push_str(&derive_str); -- cgit 1.4.1-3-g733a5 From c724528bf9d7c04788254496fbc290fdcb7332a3 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 15 May 2019 17:37:55 +0200 Subject: Avoid unnecessary allocation --- src/checkstyle.rs | 66 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 79c59bb1e8c..557ab37703f 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -1,3 +1,4 @@ +use std::fmt::{self, Display}; use std::io::{self, Write}; use std::path::Path; @@ -35,13 +36,12 @@ where for mismatch in diff { for line in mismatch.lines { // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. - if let DiffLine::Expected(ref str) = line { - let message = xml_escape_str(str); + if let DiffLine::Expected(message) = line { write!( writer, "", - mismatch.line_number, message + mismatch.line_number, XmlEscaped(&message) )?; } } @@ -50,19 +50,53 @@ where Ok(()) } -// Convert special characters into XML entities. -// This is needed for checkstyle output. -fn xml_escape_str(string: &str) -> String { - let mut out = String::new(); - for c in string.chars() { - match c { - '<' => out.push_str("<"), - '>' => out.push_str(">"), - '"' => out.push_str("""), - '\'' => out.push_str("'"), - '&' => out.push_str("&"), - _ => out.push(c), +/// Convert special characters into XML entities. +/// This is needed for checkstyle output. +struct XmlEscaped<'a>(&'a str); + +impl<'a> Display for XmlEscaped<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + for char in self.0.chars() { + match char { + '<' => write!(formatter, "<"), + '>' => write!(formatter, ">"), + '"' => write!(formatter, """), + '\'' => write!(formatter, "'"), + '&' => write!(formatter, "&"), + _ => write!(formatter, "{}", char), + }?; } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn special_characters_are_escaped() { + assert_eq!( + "<>"'&", + format!("{}", XmlEscaped(r#"<>"'&"#)), + ); + } + + #[test] + fn special_characters_are_escaped_in_string_with_other_characters() { + assert_eq!( + "The quick brown "🦊" jumps <over> the lazy 🐶", + format!( + "{}", + XmlEscaped(r#"The quick brown "🦊" jumps the lazy 🐶"#) + ), + ); + } + + #[test] + fn other_characters_are_not_escaped() { + let string = "The quick brown 🦊 jumps over the lazy 🐶"; + assert_eq!(string, format!("{}", XmlEscaped(string)),); } - out } -- cgit 1.4.1-3-g733a5 From c84785d93c8a4ccfd1b13ab07b5a2e3c7b006351 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 15 May 2019 18:17:48 +0200 Subject: Use raw strings --- src/checkstyle.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index 557ab37703f..d0fbed57cf2 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -10,9 +10,9 @@ use crate::rustfmt_diff::{DiffLine, Mismatch}; /// future version of Rustfmt. pub(crate) fn header() -> String { let mut xml_heading = String::new(); - xml_heading.push_str(""); + xml_heading.push_str(r#""#); xml_heading.push_str("\n"); - xml_heading.push_str(""); + xml_heading.push_str(r#""#); xml_heading } @@ -32,16 +32,16 @@ pub(crate) fn output_checkstyle_file( where T: Write, { - write!(writer, "", filename.display())?; + write!(writer, r#""#, filename.display())?; for mismatch in diff { for line in mismatch.lines { // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. if let DiffLine::Expected(message) = line { write!( writer, - "", - mismatch.line_number, XmlEscaped(&message) + r#""#, + mismatch.line_number, + XmlEscaped(&message) )?; } } -- cgit 1.4.1-3-g733a5 From 424193041ff64e1f97975e540adcf488e278836e Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 15 May 2019 18:29:04 +0200 Subject: Remove unnecessary comma --- src/checkstyle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs index d0fbed57cf2..5c2b46583b4 100644 --- a/src/checkstyle.rs +++ b/src/checkstyle.rs @@ -97,6 +97,6 @@ mod tests { #[test] fn other_characters_are_not_escaped() { let string = "The quick brown 🦊 jumps over the lazy 🐶"; - assert_eq!(string, format!("{}", XmlEscaped(string)),); + assert_eq!(string, format!("{}", XmlEscaped(string))); } } -- cgit 1.4.1-3-g733a5 From bdf105245bc5d548c21f3626ed576a808eac57ba Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Thu, 16 May 2019 13:22:25 +0900 Subject: fix `Const generics are handled incorrectly` --- src/comment.rs | 6 ++++++ tests/target/issue-3554.rs | 4 ++++ 2 files changed, 10 insertions(+) create mode 100644 tests/target/issue-3554.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 232d3745e59..be94e2db2c9 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -880,6 +880,12 @@ pub(crate) fn recover_missing_comment_in_span( Some(String::new()) } else { let missing_snippet = context.snippet(span); + let trimmed_missing_snippet = missing_snippet.trim(); + if !trimmed_missing_snippet.starts_with("//") && !trimmed_missing_snippet.starts_with("/*") + { + return None; + }; + let pos = missing_snippet.find('/').unwrap_or(0); // 1 = ` ` let total_width = missing_comment.len() + used_width + 1; diff --git a/tests/target/issue-3554.rs b/tests/target/issue-3554.rs new file mode 100644 index 00000000000..4ece90403e1 --- /dev/null +++ b/tests/target/issue-3554.rs @@ -0,0 +1,4 @@ +#![feature(const_generics)] + +pub struct S; +impl S<{ 0 }> {} -- cgit 1.4.1-3-g733a5 From 53142b486d847e2bf846fd82b02ad602bab85d41 Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Thu, 16 May 2019 21:27:34 +0900 Subject: use the span between the self_ty and left brace --- src/comment.rs | 6 ------ src/items.rs | 3 ++- src/visitor.rs | 9 ++------- 3 files changed, 4 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index be94e2db2c9..232d3745e59 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -880,12 +880,6 @@ pub(crate) fn recover_missing_comment_in_span( Some(String::new()) } else { let missing_snippet = context.snippet(span); - let trimmed_missing_snippet = missing_snippet.trim(); - if !trimmed_missing_snippet.starts_with("//") && !trimmed_missing_snippet.starts_with("/*") - { - return None; - }; - let pos = missing_snippet.find('/').unwrap_or(0); // 1 = ` ` let total_width = missing_comment.len() + used_width + 1; diff --git a/src/items.rs b/src/items.rs index 17e67b3f79f..202eb2cf117 100644 --- a/src/items.rs +++ b/src/items.rs @@ -664,7 +664,6 @@ pub(crate) fn format_impl( context: &RewriteContext<'_>, item: &ast::Item, offset: Indent, - where_span_end: Option, ) -> Option { if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { let mut result = String::with_capacity(128); @@ -691,6 +690,8 @@ pub(crate) fn format_impl( option.compress_where(); } + let misssing_span = mk_sp(self_ty.span.hi(), item.span.hi()); + let where_span_end = context.snippet_provider.opt_span_before(misssing_span, "{"); let where_clause_str = rewrite_where_clause( context, &generics.where_clause, diff --git a/src/visitor.rs b/src/visitor.rs index f317e015423..5fdd0625dff 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -5,7 +5,7 @@ use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; use syntax::{ast, visit}; use crate::attr::*; -use crate::comment::{CodeCharKind, CommentCodeSlices, FindUncommented}; +use crate::comment::{CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileName; use crate::config::{BraceStyle, Config, Version}; use crate::expr::{format_expr, ExprType}; @@ -359,13 +359,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { match item.node { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), ast::ItemKind::Impl(..) => { - let snippet = self.snippet(item.span); - let where_span_end = snippet - .find_uncommented("{") - .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); let block_indent = self.block_indent; - let rw = self - .with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end)); + let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent)); self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { -- cgit 1.4.1-3-g733a5 From fd22c27c47a71cff2f92e61b11b3344ed9e50d25 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Fri, 17 May 2019 15:58:01 +0200 Subject: Allow tests to be run on nightly only --- src/test/mod.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 23f6a69b8d1..101a8c07fd9 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -259,9 +259,9 @@ fn assert_output(source: &Path, expected_filename: &Path) { #[test] fn idempotence_tests() { run_test_with(&TestSetting::default(), || { - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - _ => return, // these tests require nightly + // these tests require nightly + if !is_nightly() { + return; } // Get all files in the tests/target directory. let files = get_test_files(Path::new("tests/target"), true); @@ -277,9 +277,9 @@ fn idempotence_tests() { // no warnings are emitted. #[test] fn self_tests() { - match option_env!("CFG_RELEASE_CHANNEL") { - None | Some("nightly") => {} - _ => return, // Issue-3443: these tests require nightly + // Issue-3443: these tests require nightly + if !is_nightly() { + return; } let mut files = get_test_files(Path::new("tests"), false); let bin_directories = vec!["cargo-fmt", "git-rustfmt", "bin", "format-diff"]; @@ -313,6 +313,11 @@ fn self_tests() { ); } +fn is_nightly() -> bool { + let release_channel = option_env!("CFG_RELEASE_CHANNEL"); + release_channel.is_none() || release_channel == Some("nightly") +} + #[test] fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); @@ -426,6 +431,16 @@ fn check_files(files: Vec, opt_config: &Option) -> (Vec Config { }; for (key, val) in &sig_comments { - if key != "target" && key != "config" { + if key != "target" && key != "config" && key != "unstable" { config.override_value(key, val); if config.is_default(key) { warn!("Default value {} used explicitly for {}", val, key); -- cgit 1.4.1-3-g733a5 From 4745cec7f3a016d48c86c67bb6b41b3d434cd28e Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Fri, 17 May 2019 16:07:49 +0200 Subject: Re-use nightly channel macro --- src/config/config_type.rs | 1 + src/test/mod.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index d14969418ad..26cd672f83a 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -60,6 +60,7 @@ impl ConfigType for IgnoreList { /// If we're being built by cargo (e.g., `cargo +nightly install rustfmt-nightly`), /// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the /// nightly compiler when installed from crates.io, default to nightly mode. +#[macro_export] macro_rules! is_nightly_channel { () => { option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") diff --git a/src/test/mod.rs b/src/test/mod.rs index 101a8c07fd9..d3e18130977 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -14,6 +14,7 @@ use crate::formatting::{ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::is_nightly_channel; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; @@ -260,7 +261,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { fn idempotence_tests() { run_test_with(&TestSetting::default(), || { // these tests require nightly - if !is_nightly() { + if !is_nightly_channel!() { return; } // Get all files in the tests/target directory. @@ -278,7 +279,7 @@ fn idempotence_tests() { #[test] fn self_tests() { // Issue-3443: these tests require nightly - if !is_nightly() { + if !is_nightly_channel!() { return; } let mut files = get_test_files(Path::new("tests"), false); @@ -313,11 +314,6 @@ fn self_tests() { ); } -fn is_nightly() -> bool { - let release_channel = option_env!("CFG_RELEASE_CHANNEL"); - release_channel.is_none() || release_channel == Some("nightly") -} - #[test] fn stdin_formatting_smoke_test() { let input = Input::Text("fn main () {}".to_owned()); @@ -432,7 +428,7 @@ fn check_files(files: Vec, opt_config: &Option) -> (Vec Date: Fri, 17 May 2019 16:13:46 +0200 Subject: Move macro to separate module --- src/config/config_type.rs | 19 +------------------ src/lib.rs | 3 +++ src/release_channel.rs | 16 ++++++++++++++++ src/test/mod.rs | 2 +- 4 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 src/release_channel.rs (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 26cd672f83a..326d81b2113 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -50,23 +50,6 @@ impl ConfigType for IgnoreList { } } -/// Checks if we're in a nightly build. -/// -/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap -/// to "stable", "beta", or "nightly" depending on what toolchain is being built. -/// If we are being built as part of the stable or beta toolchains, we want -/// to disable unstable configuration options. -/// -/// If we're being built by cargo (e.g., `cargo +nightly install rustfmt-nightly`), -/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the -/// nightly compiler when installed from crates.io, default to nightly mode. -#[macro_export] -macro_rules! is_nightly_channel { - () => { - option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") - }; -} - macro_rules! create_config { ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => ( #[cfg(test)] @@ -160,7 +143,7 @@ macro_rules! create_config { self.$i.1 = true; self.$i.2 = val; } else { - if is_nightly_channel!() { + if crate::is_nightly_channel!() { self.$i.1 = true; self.$i.2 = val; } else { diff --git a/src/lib.rs b/src/lib.rs index efd88357088..88605079b7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,9 @@ pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines}; #[macro_use] mod utils; +#[macro_use] +mod release_channel; + mod attr; mod chains; pub(crate) mod checkstyle; diff --git a/src/release_channel.rs b/src/release_channel.rs new file mode 100644 index 00000000000..948247b3c97 --- /dev/null +++ b/src/release_channel.rs @@ -0,0 +1,16 @@ +/// Checks if we're in a nightly build. +/// +/// The environment variable `CFG_RELEASE_CHANNEL` is set during the rustc bootstrap +/// to "stable", "beta", or "nightly" depending on what toolchain is being built. +/// If we are being built as part of the stable or beta toolchains, we want +/// to disable unstable configuration options. +/// +/// If we're being built by cargo (e.g., `cargo +nightly install rustfmt-nightly`), +/// `CFG_RELEASE_CHANNEL` is not set. As we only support being built against the +/// nightly compiler when installed from crates.io, default to nightly mode. +#[macro_export] +macro_rules! is_nightly_channel { + () => { + option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") + }; +} diff --git a/src/test/mod.rs b/src/test/mod.rs index d3e18130977..68fd90a01cf 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -11,10 +11,10 @@ use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; use crate::formatting::{ReportedErrors, SourceFile}; +use crate::is_nightly_channel; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session}; -use crate::is_nightly_channel; const DIFF_CONTEXT_SIZE: usize = 3; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; -- cgit 1.4.1-3-g733a5 From 8d4cb6e783c076829568bb82dcd5a0c888a09cb7 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Sat, 18 May 2019 11:42:49 +0200 Subject: Use peek() instead of checking indexes --- src/attr/doc_comment.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs index e687492fb89..1affc7bc910 100644 --- a/src/attr/doc_comment.rs +++ b/src/attr/doc_comment.rs @@ -16,14 +16,12 @@ impl<'a> DocCommentFormatter<'a> { impl Display for DocCommentFormatter<'_> { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let opener = self.style.opener().trim_end(); - let literal_as_str = self.literal.as_str().get(); - let line_count = literal_as_str.lines().count(); - let last_line_index = line_count - 1; - let lines = literal_as_str.lines().enumerate(); - for (index, line) in lines { - if index == last_line_index { + let mut lines = literal_as_str.lines().peekable(); + while let Some(line) = lines.next() { + let is_last_line = lines.peek().is_none(); + if is_last_line { write!(formatter, "{}{}", opener, line)?; } else { writeln!(formatter, "{}{}", opener, line)?; -- cgit 1.4.1-3-g733a5 From 11a68d313ad351907acd68da3e4a683f7c30d94f Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Sat, 18 May 2019 11:47:54 +0200 Subject: Pass string instead of Symbol to DocCommentFormatter --- src/attr.rs | 2 +- src/attr/doc_comment.rs | 28 +++++++--------------------- 2 files changed, 8 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 961b6031c93..1fb4ef407eb 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -334,7 +334,7 @@ impl Rewrite for ast::Attribute { }; let doc_comment_formatter = - DocCommentFormatter::new(literal, comment_style); + DocCommentFormatter::new(literal.as_str().get(), comment_style); let doc_comment = format!("{}", doc_comment_formatter); return rewrite_doc_comment( &doc_comment, diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs index 1affc7bc910..c2ae16d1c91 100644 --- a/src/attr/doc_comment.rs +++ b/src/attr/doc_comment.rs @@ -1,24 +1,16 @@ use crate::comment::CommentStyle; use std::fmt::{self, Display}; -use syntax_pos::symbol::Symbol; +#[derive(new)] pub(super) struct DocCommentFormatter<'a> { - literal: &'a Symbol, + literal: &'a str, style: CommentStyle<'a>, } -impl<'a> DocCommentFormatter<'a> { - pub(super) fn new(literal: &'a Symbol, style: CommentStyle<'a>) -> Self { - Self { literal, style } - } -} - impl Display for DocCommentFormatter<'_> { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let opener = self.style.opener().trim_end(); - let literal_as_str = self.literal.as_str().get(); - - let mut lines = literal_as_str.lines().peekable(); + let mut lines = self.literal.lines().peekable(); while let Some(line) = lines.next() { let is_last_line = lines.peek().is_none(); if is_last_line { @@ -27,7 +19,6 @@ impl Display for DocCommentFormatter<'_> { writeln!(formatter, "{}{}", opener, line)?; } } - Ok(()) } } @@ -35,7 +26,6 @@ impl Display for DocCommentFormatter<'_> { #[cfg(test)] mod tests { use super::*; - use syntax_pos::{Globals, GLOBALS}; #[test] fn literal_controls_leading_spaces() { @@ -78,13 +68,9 @@ mod tests { expected_comment: &str, style: CommentStyle<'_>, ) { - GLOBALS.set(&Globals::new(), || { - let literal = Symbol::gensym(literal); - - assert_eq!( - expected_comment, - format!("{}", DocCommentFormatter::new(&literal, style)) - ); - }); + assert_eq!( + expected_comment, + format!("{}", DocCommentFormatter::new(&literal, style)) + ); } } -- cgit 1.4.1-3-g733a5 From 1ba35fc9b52587f5ff01e188e7ae3d12e078765b Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Sat, 18 May 2019 11:50:09 +0200 Subject: Document DocCommentFormatter --- src/attr/doc_comment.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs index c2ae16d1c91..00185425d6a 100644 --- a/src/attr/doc_comment.rs +++ b/src/attr/doc_comment.rs @@ -1,6 +1,7 @@ use crate::comment::CommentStyle; use std::fmt::{self, Display}; +/// Formats a string as a doc comment using the given [`CommentStyle`]. #[derive(new)] pub(super) struct DocCommentFormatter<'a> { literal: &'a str, -- cgit 1.4.1-3-g733a5 From 0ef2144c82fbba72411c8cce105a60866e2fa53d Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Tue, 21 May 2019 11:43:28 +0900 Subject: not to avoid self (#3570) --- src/imports.rs | 11 +++++++---- tests/target/imports.rs | 6 +++--- tests/target/issue-3568.rs | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 tests/target/issue-3568.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 1d9eba7b1ef..eeda0b5cb7b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -478,7 +478,7 @@ impl UseTree { // Normalise foo::{bar} -> foo::bar if let UseSegment::List(ref list) = last { - if list.len() == 1 { + if list.len() == 1 && list[0].to_string() != "self" { normalize_sole_list = true; } } @@ -1034,7 +1034,10 @@ mod test { parse_use_tree("a::self as foo").normalize(), parse_use_tree("a as foo") ); - assert_eq!(parse_use_tree("a::{self}").normalize(), parse_use_tree("a")); + assert_eq!( + parse_use_tree("a::{self}").normalize(), + parse_use_tree("a::{self}") + ); assert_eq!(parse_use_tree("a::{b}").normalize(), parse_use_tree("a::b")); assert_eq!( parse_use_tree("a::{b, c::self}").normalize(), @@ -1069,8 +1072,8 @@ mod test { ); assert!( - parse_use_tree("foo::{self as bar}").normalize() - < parse_use_tree("foo::{qux as bar}").normalize() + parse_use_tree("foo::{qux as bar}").normalize() + < parse_use_tree("foo::{self as bar}").normalize() ); assert!( parse_use_tree("foo::{qux as bar}").normalize() diff --git a/tests/target/imports.rs b/tests/target/imports.rs index 852c1f5bfe7..c497a375b59 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -22,13 +22,13 @@ use list::{ use test::{/* A */ self /* B */, Other /* C */}; -use syntax; pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; +use syntax::{self}; use Foo::{Bar, Baz}; use {Bar /* comment */, /* Pre-comment! */ Foo}; use std::io; -use std::io; +use std::io::{self}; mod Foo { pub use syntax::ast::{ @@ -53,8 +53,8 @@ use foo; use foo::bar::baz; // With aliases. -use foo as bar; use foo::qux as bar; +use foo::{self as bar}; use foo::{self as bar, baz}; use foo::{baz, qux as bar}; diff --git a/tests/target/issue-3568.rs b/tests/target/issue-3568.rs new file mode 100644 index 00000000000..a146f3df24d --- /dev/null +++ b/tests/target/issue-3568.rs @@ -0,0 +1 @@ +use a::b::{self}; -- cgit 1.4.1-3-g733a5 From bee1a32f26301d91284f8dd91ec153b830b3498d Mon Sep 17 00:00:00 2001 From: rchaser53 Date: Wed, 22 May 2019 00:06:15 +0900 Subject: add the handling for vec! with paren inside macro --- src/macros.rs | 107 ++++++++++++++++++++++++++++----------------- tests/target/issue-3567.rs | 3 ++ 2 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 tests/target/issue-3567.rs (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 478b55b4920..a42b839f9c5 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -361,51 +361,35 @@ fn rewrite_macro_inner( match style { DelimToken::Paren => { - // Format macro invocation as function call, preserve the trailing - // comma because not all macros support them. - overflow::rewrite_with_parens( - context, - ¯o_name, - arg_vec.iter(), - shape, - mac.span, - context.config.width_heuristics().fn_call_width, - if trailing_comma { - Some(SeparatorTactic::Always) - } else { - Some(SeparatorTactic::Never) - }, - ) - .map(|rw| match position { - MacroPosition::Item => format!("{};", rw), - _ => rw, - }) + // Handle special case: `vec!(expr; expr)` + if vec_with_semi { + handle_vec_semi(context, shape, arg_vec, macro_name, style) + } else { + // Format macro invocation as function call, preserve the trailing + // comma because not all macros support them. + overflow::rewrite_with_parens( + context, + ¯o_name, + arg_vec.iter(), + shape, + mac.span, + context.config.width_heuristics().fn_call_width, + if trailing_comma { + Some(SeparatorTactic::Always) + } else { + Some(SeparatorTactic::Never) + }, + ) + .map(|rw| match position { + MacroPosition::Item => format!("{};", rw), + _ => rw, + }) + } } DelimToken::Bracket => { // Handle special case: `vec![expr; expr]` if vec_with_semi { - let mac_shape = shape.offset_left(macro_name.len())?; - // 8 = `vec![]` + `; ` - let total_overhead = 8; - let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = arg_vec[0].rewrite(context, nested_shape)?; - let rhs = arg_vec[1].rewrite(context, nested_shape)?; - if !lhs.contains('\n') - && !rhs.contains('\n') - && lhs.len() + rhs.len() + total_overhead <= shape.width - { - Some(format!("{}[{}; {}]", macro_name, lhs, rhs)) - } else { - Some(format!( - "{}[{}{};{}{}{}]", - macro_name, - nested_shape.indent.to_string_with_newline(context.config), - lhs, - nested_shape.indent.to_string_with_newline(context.config), - rhs, - shape.indent.to_string_with_newline(context.config), - )) - } + handle_vec_semi(context, shape, arg_vec, macro_name, style) } else { // If we are rewriting `vec!` macro or other special macros, // then we can rewrite this as an usual array literal. @@ -453,6 +437,47 @@ fn rewrite_macro_inner( } } +fn handle_vec_semi( + context: &RewriteContext<'_>, + shape: Shape, + arg_vec: Vec, + macro_name: String, + delim_token: DelimToken, +) -> Option { + let (left, right) = match delim_token { + DelimToken::Paren => ("(", ")"), + DelimToken::Bracket => ("[", "]"), + _ => unreachable!(), + }; + + let mac_shape = shape.offset_left(macro_name.len())?; + // 8 = `vec![]` + `; ` or `vec!()` + `; ` + let total_overhead = 8; + let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); + let lhs = arg_vec[0].rewrite(context, nested_shape)?; + let rhs = arg_vec[1].rewrite(context, nested_shape)?; + if !lhs.contains('\n') + && !rhs.contains('\n') + && lhs.len() + rhs.len() + total_overhead <= shape.width + { + // macro_name(lhs; rhs) or macro_name[lhs; rhs] + Some(format!("{}{}{}; {}{}", macro_name, left, lhs, rhs, right)) + } else { + // macro_name(\nlhs;\nrhs\n) or macro_name[\nlhs;\nrhs\n] + Some(format!( + "{}{}{}{};{}{}{}{}", + macro_name, + left, + nested_shape.indent.to_string_with_newline(context.config), + lhs, + nested_shape.indent.to_string_with_newline(context.config), + rhs, + shape.indent.to_string_with_newline(context.config), + right + )) + } +} + pub(crate) fn rewrite_macro_def( context: &RewriteContext<'_>, shape: Shape, diff --git a/tests/target/issue-3567.rs b/tests/target/issue-3567.rs new file mode 100644 index 00000000000..3cf08628db0 --- /dev/null +++ b/tests/target/issue-3567.rs @@ -0,0 +1,3 @@ +fn check() { + vec![vec!(0; 10); 10]; +} -- cgit 1.4.1-3-g733a5 From bdb72237a274a2edbe38b9e1ebae18c00ae3ae96 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 22 May 2019 00:10:46 +0900 Subject: Insert an empty line when normalizing `#[doc = ""]` --- src/attr/doc_comment.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/attr/doc_comment.rs b/src/attr/doc_comment.rs index 00185425d6a..c3dcb84c948 100644 --- a/src/attr/doc_comment.rs +++ b/src/attr/doc_comment.rs @@ -12,6 +12,12 @@ impl Display for DocCommentFormatter<'_> { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let opener = self.style.opener().trim_end(); let mut lines = self.literal.lines().peekable(); + + // Handle `#[doc = ""]`. + if lines.peek().is_none() { + return write!(formatter, "{}", opener); + } + while let Some(line) = lines.next() { let is_last_line = lines.peek().is_none(); if is_last_line { -- cgit 1.4.1-3-g733a5 From ed073a9b7cc7b9e68094d673e3830324c15392cb Mon Sep 17 00:00:00 2001 From: Ivan Veselov Date: Mon, 20 May 2019 10:23:03 +0100 Subject: Use structopt for command line arguments parsing in cargo-fmt --- Cargo.lock | 68 +++++++++++++ Cargo.toml | 1 + src/cargo-fmt/main.rs | 264 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 257 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b1e1a4b0226..b5eec3599de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,6 +135,20 @@ name = "cfg-if" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -314,6 +328,14 @@ dependencies = [ "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "humantime" version = "1.2.0" @@ -799,6 +821,7 @@ dependencies = [ "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -886,6 +909,31 @@ name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "0.15.32" @@ -935,6 +983,14 @@ dependencies = [ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread_local" version = "0.3.6" @@ -981,6 +1037,11 @@ name = "utf8-ranges" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.7" @@ -1045,6 +1106,7 @@ dependencies = [ "checksum cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "178d62b240c34223f265a4c1e275e37d62da163d421fc8d7f7e3ee340f803c57" "checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" @@ -1065,6 +1127,7 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" "checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" @@ -1128,11 +1191,15 @@ dependencies = [ "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" +"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" "checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c5890a989fa47ecdc7bcb4c63a77a82c18f306714104b1decfd722db17b39e" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -1141,6 +1208,7 @@ dependencies = [ "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/Cargo.toml b/Cargo.toml index 4e332ec43b9..1321f0e84ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,7 @@ unicode_categories = "0.1.1" dirs = "1.0.4" ignore = "0.4.6" annotate-snippets = { version = "0.5.0", features = ["ansi_term"] } +structopt = "0.2.15" config_proc_macro = { path = "config_proc_macro" } diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 14d9c7f2423..82c8743587e 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -1,10 +1,8 @@ // Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/). -#![cfg(not(test))] #![deny(warnings)] use cargo_metadata; -use getopts; use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; @@ -17,7 +15,41 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; -use getopts::{Matches, Options}; +use structopt::StructOpt; + +#[derive(StructOpt, Debug)] +#[structopt( + bin_name = "cargo fmt", + author = "", + about = "This utility formats all bin and lib files of \ + the current crate using rustfmt." +)] +pub struct Opts { + /// No output printed to stdout + #[structopt(short = "q", long = "quiet")] + quiet: bool, + + /// Use verbose output + #[structopt(short = "v", long = "verbose")] + verbose: bool, + + /// Print rustfmt version and exit + #[structopt(long = "version")] + version: bool, + + /// Specify package to format (only usable in workspaces) + #[structopt(short = "p", long = "package", value_name = "package")] + packages: Vec, + + /// Options passed to rustfmt + // 'raw = true' to make `--` explicit. + #[structopt(name = "rustfmt_options", raw(raw = "true"))] + rustfmt_options: Vec, + + /// Format all packages (only usable in workspaces) + #[structopt(long = "all")] + format_all: bool, +} fn main() { let exit_status = execute(); @@ -29,80 +61,32 @@ const SUCCESS: i32 = 0; const FAILURE: i32 = 1; fn execute() -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optflag("q", "quiet", "no output printed to stdout"); - opts.optflag("v", "verbose", "use verbose output"); - opts.optmulti( - "p", - "package", - "specify package to format (only usable in workspaces)", - "", - ); - opts.optflag("", "version", "print rustfmt version and exit"); - opts.optflag("", "all", "format all packages (only usable in workspaces)"); - - // If there is any invalid argument passed to `cargo fmt`, return without formatting. - let mut is_package_arg = false; - for arg in env::args().skip(2).take_while(|a| a != "--") { - if arg.starts_with('-') { - is_package_arg = arg.starts_with("--package") | arg.starts_with("-p"); - } else if !is_package_arg { - print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg)); - return FAILURE; - } else { - is_package_arg = false; - } - } + let opts = Opts::from_args(); - let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) { - Ok(m) => m, - Err(e) => { - print_usage_to_stderr(&opts, &e.to_string()); - return FAILURE; - } - }; - - let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) { + let verbosity = match (opts.verbose, opts.quiet) { (false, false) => Verbosity::Normal, (false, true) => Verbosity::Quiet, (true, false) => Verbosity::Verbose, (true, true) => { - print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible"); + print_usage_to_stderr("quiet mode and verbose mode are not compatible"); return FAILURE; } }; - if matches.opt_present("h") { - print_usage_to_stdout(&opts, ""); - return SUCCESS; + if opts.version { + return handle_command_status(get_version()); } - if matches.opt_present("version") { - return handle_command_status(get_version(), &opts); - } + let strategy = CargoFmtStrategy::from_opts(&opts); - let strategy = CargoFmtStrategy::from_matches(&matches); - handle_command_status(format_crate(verbosity, &strategy), &opts) + handle_command_status(format_crate(verbosity, &strategy, opts.rustfmt_options)) } -macro_rules! print_usage { - ($print:ident, $opts:ident, $reason:expr) => {{ - let msg = format!("{}\nusage: cargo fmt [options]", $reason); - $print!( - "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \ - Arguments after `--` are passed to rustfmt.", - $opts.usage(&msg) - ); - }}; -} - -fn print_usage_to_stdout(opts: &Options, reason: &str) { - print_usage!(println, opts, reason); -} - -fn print_usage_to_stderr(opts: &Options, reason: &str) { - print_usage!(eprintln, opts, reason); +fn print_usage_to_stderr(reason: &str) { + eprintln!("{}", reason); + let app = Opts::clap(); + app.write_help(&mut io::stderr()) + .expect("failed to write to stderr"); } #[derive(Debug, Clone, Copy, PartialEq)] @@ -112,10 +96,10 @@ pub enum Verbosity { Quiet, } -fn handle_command_status(status: Result, opts: &getopts::Options) -> i32 { +fn handle_command_status(status: Result) -> i32 { match status { Err(e) => { - print_usage_to_stderr(opts, &e.to_string()); + print_usage_to_stderr(&e.to_string()); FAILURE } Ok(status) => status, @@ -142,8 +126,11 @@ fn get_version() -> Result { } } -fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result { - let rustfmt_args = get_fmt_args(); +fn format_crate( + verbosity: Verbosity, + strategy: &CargoFmtStrategy, + rustfmt_args: Vec, +) -> Result { let targets = if rustfmt_args .iter() .any(|s| ["--print-config", "-h", "--help", "-V", "--version"].contains(&s.as_str())) @@ -157,11 +144,6 @@ fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result Vec { - // All arguments after -- are passed to rustfmt. - env::args().skip_while(|a| a != "--").skip(1).collect() -} - /// Target uses a `path` field for equality and hashing. #[derive(Debug)] pub struct Target { @@ -223,11 +205,11 @@ pub enum CargoFmtStrategy { } impl CargoFmtStrategy { - pub fn from_matches(matches: &Matches) -> CargoFmtStrategy { - match (matches.opt_present("all"), matches.opt_present("p")) { - (false, false) => CargoFmtStrategy::Root, + pub fn from_opts(opts: &Opts) -> CargoFmtStrategy { + match (opts.format_all, opts.packages.is_empty()) { + (false, true) => CargoFmtStrategy::Root, (true, _) => CargoFmtStrategy::All, - (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")), + (false, false) => CargoFmtStrategy::Some(opts.packages.clone()), } } } @@ -403,3 +385,133 @@ fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result Err(io::Error::new(io::ErrorKind::Other, error.to_string())), } } + +#[cfg(test)] +mod cargo_fmt_tests { + use super::*; + + #[test] + fn default_options() { + let empty: Vec = vec![]; + let o = Opts::from_iter(&empty); + assert_eq!(false, o.quiet); + assert_eq!(false, o.verbose); + assert_eq!(false, o.version); + assert_eq!(empty, o.packages); + assert_eq!(empty, o.rustfmt_options); + assert_eq!(false, o.format_all); + } + + #[test] + fn good_options() { + let o = Opts::from_iter(&[ + "test", + "-q", + "-p", + "p1", + "-p", + "p2", + "--", + "--edition", + "2018", + ]); + assert_eq!(true, o.quiet); + assert_eq!(false, o.verbose); + assert_eq!(false, o.version); + assert_eq!(vec!["p1", "p2"], o.packages); + assert_eq!(vec!["--edition", "2018"], o.rustfmt_options); + assert_eq!(false, o.format_all); + } + + #[test] + fn unexpected_option() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "unexpected"]) + .is_err() + ); + } + + #[test] + fn unexpected_flag() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--flag"]) + .is_err() + ); + } + + #[test] + fn mandatory_separator() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--check"]) + .is_err() + ); + assert!( + !Opts::clap() + .get_matches_from_safe(&["test", "--", "--check"]) + .is_err() + ); + } + + #[test] + fn multiple_packages_one_by_one() { + let o = Opts::from_iter(&[ + "test", + "-p", + "package1", + "--package", + "package2", + "-p", + "package3", + ]); + assert_eq!(3, o.packages.len()); + } + + #[test] + fn multiple_packages_grouped() { + let o = Opts::from_iter(&[ + "test", + "--package", + "package1", + "package2", + "-p", + "package3", + "package4", + ]); + assert_eq!(4, o.packages.len()); + } + + #[test] + fn empty_packages_1() { + assert!(Opts::clap().get_matches_from_safe(&["test", "-p"]).is_err()); + } + + #[test] + fn empty_packages_2() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--", "--check"]) + .is_err() + ); + } + + #[test] + fn empty_packages_3() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--verbose"]) + .is_err() + ); + } + + #[test] + fn empty_packages_4() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "--check"]) + .is_err() + ); + } +} -- cgit 1.4.1-3-g733a5 From 32fbe75a4cd23cfd64465d3e3419df2e79eb6828 Mon Sep 17 00:00:00 2001 From: Ivan Veselov Date: Mon, 20 May 2019 13:17:32 +0100 Subject: Drop extra `fmt` command line argument provided by cargo --- src/cargo-fmt/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 82c8743587e..a265347e033 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -61,7 +61,9 @@ const SUCCESS: i32 = 0; const FAILURE: i32 = 1; fn execute() -> i32 { - let opts = Opts::from_args(); + // Drop extra `fmt` argument provided by `cargo`. + let args = env::args().filter(|x| x != "fmt"); + let opts = Opts::from_iter(args); let verbosity = match (opts.verbose, opts.quiet) { (false, false) => Verbosity::Normal, -- cgit 1.4.1-3-g733a5 From a7afdeb9b841b7007a7ed9d3b45834ef7953772c Mon Sep 17 00:00:00 2001 From: Ivan Veselov Date: Tue, 21 May 2019 16:33:51 +0100 Subject: Drop only the first occurrence of `fmt` while preparing CLI arguments --- src/cargo-fmt/main.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index a265347e033..3c4d1c08b08 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -62,7 +62,16 @@ const FAILURE: i32 = 1; fn execute() -> i32 { // Drop extra `fmt` argument provided by `cargo`. - let args = env::args().filter(|x| x != "fmt"); + let mut found_fmt = false; + let args = env::args().filter(|x| { + if found_fmt { + true + } else { + found_fmt = x == "fmt"; + x != "fmt" + } + }); + let opts = Opts::from_iter(args); let verbosity = match (opts.verbose, opts.quiet) { -- cgit 1.4.1-3-g733a5 From b5449ba7850406821d1b05ca4f55c5eb3b7e8ae8 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 22 May 2019 10:51:19 +0900 Subject: Allow overflowing rhs of unit variant (#3566) --- src/expr.rs | 9 ++++++++- src/items.rs | 8 +++++++- src/shape.rs | 11 +++++++++++ tests/source/enum.rs | 7 +++++++ tests/target/enum.rs | 9 +++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index c4c41fb6957..afd9465c73c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1894,6 +1894,9 @@ pub(crate) enum RhsTactics { Default, /// Put the rhs on the next line if it uses multiple line, without extra indentation. ForceNextLineWithoutIndent, + /// Allow overflowing max width if neither `Default` nor `ForceNextLineWithoutIndent` + /// did not work. + AllowOverflow, } // The left hand side must contain everything up to, and including, the @@ -1970,6 +1973,10 @@ fn choose_rhs( Some(format!("{}{}", new_indent_str, new_rhs)) } (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), + (None, None) if rhs_tactics == RhsTactics::AllowOverflow => { + let shape = shape.infinite_width(); + expr.rewrite(context, shape).map(|s| format!(" {}", s)) + } (None, None) => None, (Some(orig_rhs), _) => Some(format!(" {}", orig_rhs)), } @@ -1986,7 +1993,7 @@ fn shape_from_rhs_tactic( RhsTactics::ForceNextLineWithoutIndent => shape .with_max_width(context.config) .sub_width(shape.indent.width()), - RhsTactics::Default => { + RhsTactics::Default | RhsTactics::AllowOverflow => { Shape::indented(shape.indent.block_indent(context.config), context.config) .sub_width(shape.rhs_overhead(context.config)) } diff --git a/src/items.rs b/src/items.rs index 202eb2cf117..d642718412f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -592,7 +592,13 @@ impl<'a> FmtVisitor<'a> { rewrite_ident(&context, field.node.ident), pad_discrim_ident_to ); - rewrite_assign_rhs(&context, lhs, &*expr.value, shape)? + rewrite_assign_rhs_with( + &context, + lhs, + &*expr.value, + shape, + RhsTactics::AllowOverflow, + )? } else { rewrite_ident(&context, field.node.ident).to_owned() } diff --git a/src/shape.rs b/src/shape.rs index d8971e05ef9..4376fd12b52 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -136,6 +136,9 @@ impl Sub for Indent { } } +// 8096 is close enough to infinite for rustfmt. +const INFINITE_SHAPE_WIDTH: usize = 8096; + #[derive(Copy, Clone, Debug)] pub(crate) struct Shape { pub(crate) width: usize, @@ -274,6 +277,14 @@ impl Shape { offset_indent.alignment = self.offset; offset_indent.to_string_inner(config, 0) } + + /// Creates a `Shape` with a virtually infinite width. + pub(crate) fn infinite_width(&self) -> Shape { + Shape { + width: INFINITE_SHAPE_WIDTH, + ..*self + } + } } #[cfg(test)] diff --git a/tests/source/enum.rs b/tests/source/enum.rs index c348b5752e2..fd563206ae5 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -195,3 +195,10 @@ pub enum QlError { // #2594 enum Foo {} enum Bar { } + +// #3562 +enum PublishedFileVisibility { + Public = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPublic, + FriendsOnly = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityFriendsOnly, + Private = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPrivate, +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index dda58c4b5b0..6af05cbed90 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -264,3 +264,12 @@ pub enum QlError { // #2594 enum Foo {} enum Bar {} + +// #3562 +enum PublishedFileVisibility { + Public = + sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPublic, + FriendsOnly = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityFriendsOnly, + Private = + sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPrivate, +} -- cgit 1.4.1-3-g733a5 From a7d4ec92cb4cb77e602ef78a7e2ce3461922a7f1 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 22 May 2019 16:41:57 +0900 Subject: Implement Serialize on IgnoreList (#3565) * Implement Serialize on IgnoreList * Add a test for #3536 --- src/config/mod.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/config/options.rs | 20 +++++++++++--- 2 files changed, 89 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index d2189904965..eaa6d012d5b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -462,6 +462,79 @@ mod test { assert_eq!(s.contains("(unstable)"), true); } + #[test] + fn test_dump_default_config() { + const DEFAULT_CONFIG: &str = r#"max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Auto" +use_small_heuristics = "Default" +indent_style = "Block" +wrap_comments = false +format_code_in_doc_comments = false +comment_width = 80 +normalize_comments = false +normalize_doc_attributes = false +license_template_path = "" +format_strings = false +format_macro_matchers = false +format_macro_bodies = true +empty_item_single_line = true +struct_lit_single_line = true +fn_single_line = false +where_single_line = false +imports_indent = "Block" +imports_layout = "Mixed" +merge_imports = false +reorder_imports = true +reorder_modules = true +reorder_impl_items = false +type_punctuation_density = "Wide" +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false +binop_separator = "Front" +remove_nested_parens = true +combine_control_expr = true +overflow_delimited_expr = false +struct_field_align_threshold = 0 +enum_discrim_align_threshold = 0 +match_arm_blocks = true +force_multiline_blocks = false +fn_args_density = "Tall" +brace_style = "SameLineWhere" +control_brace_style = "AlwaysSameLine" +trailing_semicolon = true +trailing_comma = "Vertical" +match_block_trailing_comma = false +blank_lines_upper_bound = 1 +blank_lines_lower_bound = 0 +edition = "2015" +version = "One" +inline_attribute_width = 0 +merge_derives = true +use_try_shorthand = false +use_field_init_shorthand = false +force_explicit_abi = true +condense_wildcard_suffixes = false +color = "Auto" +required_version = "1.2.2" +unstable_features = false +disable_all_formatting = false +skip_children = false +hide_parse_errors = false +error_on_line_overflow = false +error_on_unformatted = false +report_todo = "Never" +report_fixme = "Never" +ignore = [] +emit_mode = "Files" +make_backup = false +"#; + let toml = Config::default().all_options().to_toml().unwrap(); + assert_eq!(&toml, DEFAULT_CONFIG); + } + // FIXME(#2183): these tests cannot be run in parallel because they use env vars. // #[test] // fn test_as_not_nightly_channel() { diff --git a/src/config/options.rs b/src/config/options.rs index 4de8ef928dd..72acaacd348 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -5,7 +5,8 @@ use std::path::{Path, PathBuf}; use atty; use config_proc_macro::config_type; use serde::de::{SeqAccess, Visitor}; -use serde::{Deserialize, Deserializer, Serialize}; +use serde::ser::SerializeSeq; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::config::lists::*; use crate::config::Config; @@ -254,16 +255,27 @@ impl Default for EmitMode { } /// A set of directories, files and modules that rustfmt should ignore. -#[derive(Default, Serialize, Clone, Debug, PartialEq)] +#[derive(Default, Clone, Debug, PartialEq)] pub struct IgnoreList { /// A set of path specified in rustfmt.toml. - #[serde(flatten)] path_set: HashSet, /// A path to rustfmt.toml. - #[serde(skip_serializing)] rustfmt_toml_path: PathBuf, } +impl Serialize for IgnoreList { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.path_set.len()))?; + for e in &self.path_set { + seq.serialize_element(e)?; + } + seq.end() + } +} + impl<'de> Deserialize<'de> for IgnoreList { fn deserialize(deserializer: D) -> Result where -- cgit 1.4.1-3-g733a5 From 84432627815ced7befde505d64c615abaa938db8 Mon Sep 17 00:00:00 2001 From: Ivan Veselov Date: Wed, 22 May 2019 20:51:36 +0100 Subject: Use structopt for rustfmt-format-diff arguments parsing --- src/format-diff/main.rs | 134 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index bf1bd4add97..80815b5f1d9 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -7,7 +7,6 @@ use env_logger; #[macro_use] extern crate failure; -use getopts; #[macro_use] extern crate log; use regex; @@ -16,10 +15,13 @@ use serde_json as json; use std::collections::HashSet; use std::io::{self, BufRead}; -use std::{env, process}; +use std::process; use regex::Regex; +use structopt::clap::AppSettings; +use structopt::StructOpt; + /// The default pattern of files to format. /// /// We only want to format rust files by default. @@ -53,26 +55,40 @@ impl From for FormatDiffError { } } -fn main() { - env_logger::init(); +#[derive(StructOpt, Debug)] +#[structopt( + name = "rustfmt-format-diff", + author = "", + about = "", + raw(setting = "AppSettings::DisableVersion"), + raw(setting = "AppSettings::NextLineHelp") +)] +pub struct Opts { + /// Skip the smallest prefix containing NUMBER slashes + #[structopt( + short = "p", + long = "skip-prefix", + value_name = "NUMBER", + default_value = "0" + )] + skip_prefix: u32, - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this message"); - opts.optopt( - "p", - "skip-prefix", - "skip the smallest prefix containing NUMBER slashes", - "NUMBER", - ); - opts.optopt( - "f", - "filter", - "custom pattern selecting file paths to reformat", - "PATTERN", - ); + /// Custom pattern selecting file paths to reformat + #[structopt( + short = "f", + long = "filter", + value_name = "PATTERN", + raw(default_value = "DEFAULT_PATTERN") + )] + filter: String, +} - if let Err(e) = run(&opts) { - println!("{}", opts.usage(&e.to_string())); +fn main() { + env_logger::init(); + let opts = Opts::from_args(); + if let Err(e) = run(opts) { + println!("{}", e); + Opts::clap().print_help().expect("cannot write to stdout"); process::exit(1); } } @@ -83,25 +99,8 @@ struct Range { range: [u32; 2], } -fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> { - let matches = opts.parse(env::args().skip(1))?; - - if matches.opt_present("h") { - println!("{}", opts.usage("usage: ")); - return Ok(()); - } - - let filter = matches - .opt_str("f") - .unwrap_or_else(|| DEFAULT_PATTERN.to_owned()); - - let skip_prefix = matches - .opt_str("p") - .and_then(|p| p.parse::().ok()) - .unwrap_or(0); - - let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?; - +fn run(opts: Opts) -> Result<(), FormatDiffError> { + let (files, ranges) = scan_diff(io::stdin(), opts.skip_prefix, &opts.filter)?; run_rustfmt(&files, &ranges) } @@ -238,3 +237,60 @@ fn scan_simple_git_diff() { ] ); } + +#[cfg(test)] +mod cmd_line_tests { + use super::*; + + #[test] + fn default_options() { + let empty: Vec = vec![]; + let o = Opts::from_iter(&empty); + assert_eq!(DEFAULT_PATTERN, o.filter); + assert_eq!(0, o.skip_prefix); + } + + #[test] + fn good_options() { + let o = Opts::from_iter(&["test", "-p", "10", "-f", r".*\.hs"]); + assert_eq!(r".*\.hs", o.filter); + assert_eq!(10, o.skip_prefix); + } + + #[test] + fn unexpected_option() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "unexpected"]) + .is_err() + ); + } + + #[test] + fn unexpected_flag() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "--flag"]) + .is_err() + ); + } + + #[test] + fn overridden_option() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "10", "-p", "20"]) + .is_err() + ); + } + + #[test] + fn negative_filter() { + assert!( + Opts::clap() + .get_matches_from_safe(&["test", "-p", "-1"]) + .is_err() + ); + } + +} -- cgit 1.4.1-3-g733a5 From 95c2ad37e141a62f184f49dc7a6f12840b67b826 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 26 May 2019 21:15:38 +0900 Subject: Refactor rewrite_where_clause --- src/items.rs | 205 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 136 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d642718412f..d39a0bb528b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -693,7 +693,7 @@ pub(crate) fn format_impl( { option.suppress_comma(); option.snuggle(); - option.compress_where(); + option.allow_single_line(); } let misssing_span = mk_sp(self_ty.span.hi(), item.span.hi()); @@ -708,7 +708,6 @@ pub(crate) fn format_impl( where_span_end, self_ty.span.hi(), option, - false, )?; // If there is no where-clause, we may have missing comments between the trait name and @@ -1068,7 +1067,6 @@ pub(crate) fn format_trait( None, pos_before_where, option, - false, )?; // If the where-clause cannot fit on the same line, // put the where-clause on a new line @@ -1376,7 +1374,7 @@ fn format_tuple_struct( result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::new(true, false); + let option = WhereClauseOption::new(true, WhereClauseSpace::Newline); rewrite_where_clause( context, &generics.where_clause, @@ -1387,7 +1385,6 @@ fn format_tuple_struct( None, body_hi, option, - false, )? } None => "".to_owned(), @@ -1464,7 +1461,6 @@ fn rewrite_type_prefix( None, generics.span.hi(), option, - false, )?; result.push_str(&where_clause_str); @@ -2205,7 +2201,15 @@ fn rewrite_fn_base( let is_args_multi_lined = arg_str.contains('\n'); - let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty()); + let space = if put_args_in_block && ret_str.is_empty() { + WhereClauseSpace::Space + } else { + WhereClauseSpace::Newline + }; + let mut option = WhereClauseOption::new(!has_body, space); + if is_args_multi_lined { + option.veto_single_line(); + } let where_clause_str = rewrite_where_clause( context, where_clause, @@ -2216,7 +2220,6 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, - is_args_multi_lined, )?; // If there are neither where-clause nor return type, we may be missing comments between // args and `{`. @@ -2244,27 +2247,45 @@ fn rewrite_fn_base( Some((result, force_new_line_for_brace)) } +/// Kind of spaces to put before `where`. +#[derive(Copy, Clone)] +enum WhereClauseSpace { + /// A single space. + Space, + /// A new line. + Newline, + /// Nothing. + None, +} + #[derive(Copy, Clone)] struct WhereClauseOption { suppress_comma: bool, // Force no trailing comma - snuggle: bool, // Do not insert newline before `where` - compress_where: bool, // Try single line where-clause instead of vertical layout + snuggle: WhereClauseSpace, + allow_single_line: bool, // Try single line where-clause instead of vertical layout + veto_single_line: bool, // Disallow a single-line where-clause. } impl WhereClauseOption { - fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption { + fn new(suppress_comma: bool, snuggle: WhereClauseSpace) -> WhereClauseOption { WhereClauseOption { suppress_comma, snuggle, - compress_where: false, + allow_single_line: false, + veto_single_line: false, } } fn snuggled(current: &str) -> WhereClauseOption { WhereClauseOption { suppress_comma: false, - snuggle: last_line_width(current) == 1, - compress_where: false, + snuggle: if last_line_width(current) == 1 { + WhereClauseSpace::Space + } else { + WhereClauseSpace::Newline + }, + allow_single_line: false, + veto_single_line: false, } } @@ -2272,12 +2293,16 @@ impl WhereClauseOption { self.suppress_comma = true } - fn compress_where(&mut self) { - self.compress_where = true + fn allow_single_line(&mut self) { + self.allow_single_line = true } fn snuggle(&mut self) { - self.snuggle = true + self.snuggle = WhereClauseSpace::Space + } + + fn veto_single_line(&mut self) { + self.veto_single_line = true; } } @@ -2467,25 +2492,104 @@ fn rewrite_where_clause_rfc_style( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, - is_args_multi_line: bool, ) -> Option { + let (where_keyword, allow_single_line) = rewrite_where_keyword( + context, + where_clause, + shape, + span_end_before_where, + where_clause_option, + )?; + + // 1 = `,` + let clause_shape = shape + .block() + .with_max_width(context.config) + .block_left(context.config.tab_spaces())? + .sub_width(1)?; + let force_single_line = context.config.where_single_line() + && where_clause.predicates.len() == 1 + && !where_clause_option.veto_single_line; + + let preds_str = rewrite_bounds_on_where_clause( + context, + where_clause, + clause_shape, + terminator, + span_end, + where_clause_option, + force_single_line, + )?; + + // 6 = `where ` + let clause_sep = + if allow_single_line && !preds_str.contains('\n') && 6 + preds_str.len() <= shape.width + || force_single_line + { + Cow::from(" ") + } else { + clause_shape.indent.to_string_with_newline(context.config) + }; + + Some(format!("{}{}{}", where_keyword, clause_sep, preds_str)) +} + +/// Rewrite `where` and comment around it. +fn rewrite_where_keyword( + context: &RewriteContext<'_>, + where_clause: &ast::WhereClause, + shape: Shape, + span_end_before_where: BytePos, + where_clause_option: WhereClauseOption, +) -> Option<(String, bool)> { let block_shape = shape.block().with_max_width(context.config); + // 1 = `,` + let clause_shape = block_shape + .block_left(context.config.tab_spaces())? + .sub_width(1)?; + + let comment_separator = |comment: &str, shape: Shape| { + if comment.is_empty() { + Cow::from("") + } else { + shape.indent.to_string_with_newline(context.config) + } + }; let (span_before, span_after) = missing_span_before_after_where(span_end_before_where, where_clause); let (comment_before, comment_after) = rewrite_comments_before_after_where(context, span_before, span_after, shape)?; - let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() { - Cow::from(" ") - } else { - block_shape.indent.to_string_with_newline(context.config) + let starting_newline = match where_clause_option.snuggle { + WhereClauseSpace::Space if comment_before.is_empty() => Cow::from(" "), + WhereClauseSpace::None => Cow::from(""), + _ => block_shape.indent.to_string_with_newline(context.config), }; - let clause_shape = block_shape.block_left(context.config.tab_spaces())?; - // 1 = `,` - let clause_shape = clause_shape.sub_width(1)?; - // each clause on one line, trailing comma (except if suppress_comma) + let newline_before_where = comment_separator(&comment_before, shape); + let newline_after_where = comment_separator(&comment_after, clause_shape); + let result = format!( + "{}{}{}where{}{}", + starting_newline, comment_before, newline_before_where, newline_after_where, comment_after + ); + let allow_single_line = where_clause_option.allow_single_line + && comment_before.is_empty() + && comment_after.is_empty(); + + Some((result, allow_single_line)) +} + +/// Rewrite bounds on a where clause. +fn rewrite_bounds_on_where_clause( + context: &RewriteContext<'_>, + where_clause: &ast::WhereClause, + shape: Shape, + terminator: &str, + span_end: Option, + where_clause_option: WhereClauseOption, + force_single_line: bool, +) -> Option { let span_start = where_clause.predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. @@ -2499,64 +2603,30 @@ fn rewrite_where_clause_rfc_style( ",", |pred| pred.span().lo(), |pred| pred.span().hi(), - |pred| pred.rewrite(context, clause_shape), + |pred| pred.rewrite(context, shape), span_start, span_end, false, ); - let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line; - let comma_tactic = if where_clause_option.suppress_comma || where_single_line { + let comma_tactic = if where_clause_option.suppress_comma || force_single_line { SeparatorTactic::Never } else { context.config.trailing_comma() }; - // shape should be vertical only and only if we have `where_single_line` option enabled + // shape should be vertical only and only if we have `force_single_line` option enabled // and the number of items of the where-clause is equal to 1 - let shape_tactic = if where_single_line { + let shape_tactic = if force_single_line { DefinitiveListTactic::Horizontal } else { DefinitiveListTactic::Vertical }; - let fmt = ListFormatting::new(clause_shape, context.config) + let fmt = ListFormatting::new(shape, context.config) .tactic(shape_tactic) .trailing_separator(comma_tactic) .preserve_newline(true); - let preds_str = write_list(&items.collect::>(), &fmt)?; - - let comment_separator = |comment: &str, shape: Shape| { - if comment.is_empty() { - Cow::from("") - } else { - shape.indent.to_string_with_newline(context.config) - } - }; - let newline_before_where = comment_separator(&comment_before, shape); - let newline_after_where = comment_separator(&comment_after, clause_shape); - - // 6 = `where ` - let clause_sep = if where_clause_option.compress_where - && comment_before.is_empty() - && comment_after.is_empty() - && !preds_str.contains('\n') - && 6 + preds_str.len() <= shape.width - || where_single_line - { - Cow::from(" ") - } else { - clause_shape.indent.to_string_with_newline(context.config) - }; - Some(format!( - "{}{}{}where{}{}{}{}", - starting_newline, - comment_before, - newline_before_where, - newline_after_where, - comment_after, - clause_sep, - preds_str - )) + write_list(&items.collect::>(), &fmt) } fn rewrite_where_clause( @@ -2569,7 +2639,6 @@ fn rewrite_where_clause( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, - is_args_multi_line: bool, ) -> Option { if where_clause.predicates.is_empty() { return Some(String::new()); @@ -2584,7 +2653,6 @@ fn rewrite_where_clause( span_end, span_end_before_where, where_clause_option, - is_args_multi_line, ); } @@ -2742,7 +2810,6 @@ fn format_generics( Some(span.hi()), span_end_before_where, option, - false, )?; result.push_str(&where_clause_str); ( -- cgit 1.4.1-3-g733a5 From c1373b267ba8be93eee9626ea1ac876fa36dac67 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 26 May 2019 21:15:55 +0900 Subject: Format trait aliases with where clauses --- src/items.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d39a0bb528b..7640fa32d22 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1154,6 +1154,45 @@ pub(crate) fn format_trait( } } +pub(crate) struct TraitAliasBounds<'a> { + generic_bounds: &'a ast::GenericBounds, + generics: &'a ast::Generics, +} + +impl<'a> Rewrite for TraitAliasBounds<'a> { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + let generic_bounds_str = self.generic_bounds.rewrite(context, shape)?; + + let mut option = WhereClauseOption::new(true, WhereClauseSpace::None); + option.allow_single_line(); + + let where_str = rewrite_where_clause( + context, + &self.generics.where_clause, + context.config.brace_style(), + shape, + Density::Compressed, + ";", + None, + self.generics.where_clause.span.lo(), + option, + )?; + + let fits_single_line = !generic_bounds_str.contains('\n') + && !where_str.contains('\n') + && generic_bounds_str.len() + where_str.len() + 1 <= shape.width; + let space = if generic_bounds_str.is_empty() || where_str.is_empty() { + Cow::from("") + } else if fits_single_line { + Cow::from(" ") + } else { + shape.indent.to_string_with_newline(&context.config) + }; + + Some(format!("{}{}{}", generic_bounds_str, space, where_str)) + } +} + pub(crate) fn format_trait_alias( context: &RewriteContext<'_>, ident: ast::Ident, @@ -1169,7 +1208,11 @@ pub(crate) fn format_trait_alias( let vis_str = format_visibility(context, vis); let lhs = format!("{}trait {} =", vis_str, generics_str); // 1 = ";" - rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";") + let trait_alias_bounds = TraitAliasBounds { + generics, + generic_bounds, + }; + rewrite_assign_rhs(context, lhs, &trait_alias_bounds, shape.sub_width(1)?).map(|s| s + ";") } fn format_unit_struct( -- cgit 1.4.1-3-g733a5 From f7cd789ebc135cb165f00e64a7e5edaf821c0c62 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 28 May 2019 00:03:50 +0900 Subject: Catch panics from the parser while rewriting macro calls --- src/macros.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index a42b839f9c5..d25106c4961 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -10,6 +10,7 @@ // and those with brackets will be formatted as array literals. use std::collections::HashMap; +use std::panic::{catch_unwind, AssertUnwindSafe}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; @@ -208,21 +209,24 @@ pub(crate) fn rewrite_macro( shape: Shape, position: MacroPosition, ) -> Option { - let should_skip = context - .skip_macro_names - .borrow() - .contains(&context.snippet(mac.node.path.span).to_owned()); - if should_skip { - None - } else { - let guard = InsideMacroGuard::inside_macro_context(context); - let result = - rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested); - if result.is_none() { - context.macro_rewrite_failure.replace(true); + catch_unwind(AssertUnwindSafe(|| { + let should_skip = context + .skip_macro_names + .borrow() + .contains(&context.snippet(mac.node.path.span).to_owned()); + if should_skip { + None + } else { + let guard = InsideMacroGuard::inside_macro_context(context); + let result = + rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested); + if result.is_none() { + context.macro_rewrite_failure.replace(true); + } + result } - result - } + })) + .ok()? } fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { -- cgit 1.4.1-3-g733a5 From 36dd49ae5f4fd0e0d54111533f1577fccfef979a Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 28 May 2019 00:14:36 +0900 Subject: Set macro_rewrite_failure to true on catching panic --- src/macros.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index d25106c4961..077e6a32d62 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -209,24 +209,25 @@ pub(crate) fn rewrite_macro( shape: Shape, position: MacroPosition, ) -> Option { - catch_unwind(AssertUnwindSafe(|| { - let should_skip = context - .skip_macro_names - .borrow() - .contains(&context.snippet(mac.node.path.span).to_owned()); - if should_skip { - None - } else { - let guard = InsideMacroGuard::inside_macro_context(context); - let result = - rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested); - if result.is_none() { + let should_skip = context + .skip_macro_names + .borrow() + .contains(&context.snippet(mac.node.path.span).to_owned()); + if should_skip { + None + } else { + let guard = InsideMacroGuard::inside_macro_context(context); + let result = catch_unwind(AssertUnwindSafe(|| { + rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested) + })); + match result { + Err(..) | Ok(None) => { context.macro_rewrite_failure.replace(true); + None } - result + Ok(rw) => rw, } - })) - .ok()? + } } fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { -- cgit 1.4.1-3-g733a5 From fbd9f335f9fa53f50da89d63571117b5bfe8e65d Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Thu, 30 May 2019 07:31:48 +0900 Subject: fix Erasing inner attributes in struct (#3593) --- src/expr.rs | 39 ++++++++++++++++++++++++++++----------- src/patterns.rs | 3 ++- tests/target/issue-3592.rs | 13 +++++++++++++ 3 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 tests/target/issue-3592.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index afd9465c73c..23628d929e8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -102,6 +102,7 @@ pub(crate) fn format_expr( path, fields, base.as_ref().map(|e| &**e), + &expr.attrs, expr.span, shape, ), @@ -1570,6 +1571,7 @@ fn rewrite_struct_lit<'a>( path: &ast::Path, fields: &'a [ast::Field], base: Option<&'a ast::Expr>, + attrs: &[ast::Attribute], span: Span, shape: Shape, ) -> Option { @@ -1664,7 +1666,8 @@ fn rewrite_struct_lit<'a>( write_list(&item_vec, &fmt)? }; - let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + let fields_str = + wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?; Some(format!("{} {{{}}}", path_str, fields_str)) // FIXME if context.config.indent_style() == Visual, but we run out @@ -1673,25 +1676,39 @@ fn rewrite_struct_lit<'a>( pub(crate) fn wrap_struct_field( context: &RewriteContext<'_>, + attrs: &[ast::Attribute], fields_str: &str, shape: Shape, nested_shape: Shape, one_line_width: usize, -) -> String { - if context.config.indent_style() == IndentStyle::Block +) -> Option { + let should_vertical = context.config.indent_style() == IndentStyle::Block && (fields_str.contains('\n') || !context.config.struct_lit_single_line() - || fields_str.len() > one_line_width) - { - format!( - "{}{}{}", + || fields_str.len() > one_line_width); + + let inner_attrs = &inner_attributes(attrs); + if inner_attrs.is_empty() { + if should_vertical { + Some(format!( + "{}{}{}", + nested_shape.indent.to_string_with_newline(context.config), + fields_str, + shape.indent.to_string_with_newline(context.config) + )) + } else { + // One liner or visual indent. + Some(format!(" {} ", fields_str)) + } + } else { + Some(format!( + "{}{}{}{}{}", + nested_shape.indent.to_string_with_newline(context.config), + inner_attrs.rewrite(context, shape)?, nested_shape.indent.to_string_with_newline(context.config), fields_str, shape.indent.to_string_with_newline(context.config) - ) - } else { - // One liner or visual indent. - format!(" {} ", fields_str) + )) } } diff --git a/src/patterns.rs b/src/patterns.rs index 73ff2c0f7ab..c26451f6d69 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -226,7 +226,8 @@ fn rewrite_struct_pat( } } - let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width); + // ast::Pat doesn't have attrs so use &[] + let fields_str = wrap_struct_field(context, &[], &fields_str, shape, v_shape, one_line_width)?; Some(format!("{} {{{}}}", path_str, fields_str)) } diff --git a/tests/target/issue-3592.rs b/tests/target/issue-3592.rs new file mode 100644 index 00000000000..3142268e081 --- /dev/null +++ b/tests/target/issue-3592.rs @@ -0,0 +1,13 @@ +fn r() -> (Biz, ()) { + ( + Biz { + #![cfg(unix)] + field: 9 + }, + Biz { + #![cfg(not(unix))] + field: 200 + }, + (), + ) +} -- cgit 1.4.1-3-g733a5 From e6b60a40d50c8905d8ef8696943c686947f905d7 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 3 Jun 2019 15:26:48 +0200 Subject: stabilise fn_args_density (#3581) --- CHANGELOG.md | 3 ++ Configurations.md | 6 ++-- Processes.md | 1 + src/config/mod.rs | 5 +-- src/config/options.rs | 3 +- src/items.rs | 28 +++++++-------- src/lists.rs | 5 +-- tests/config/small_tabs.toml | 2 +- tests/source/configs/fn_args_density/compressed.rs | 16 --------- tests/source/configs/fn_args_density/tall.rs | 16 --------- tests/source/configs/fn_args_density/vertical.rs | 16 --------- tests/source/configs/fn_args_layout/compressed.rs | 16 +++++++++ tests/source/configs/fn_args_layout/tall.rs | 16 +++++++++ tests/source/configs/fn_args_layout/vertical.rs | 16 +++++++++ tests/source/fn-custom-7.rs | 2 +- tests/source/fn-custom.rs | 2 +- tests/source/fn_args_density-vertical.rs | 33 ----------------- tests/source/fn_args_layout-vertical.rs | 33 +++++++++++++++++ tests/target/configs/fn_args_density/compressed.rs | 22 ------------ tests/target/configs/fn_args_density/tall.rs | 32 ----------------- tests/target/configs/fn_args_density/vertical.rs | 42 ---------------------- tests/target/configs/fn_args_layout/compressed.rs | 22 ++++++++++++ tests/target/configs/fn_args_layout/tall.rs | 32 +++++++++++++++++ tests/target/configs/fn_args_layout/vertical.rs | 42 ++++++++++++++++++++++ tests/target/fn-custom-7.rs | 2 +- tests/target/fn-custom.rs | 2 +- tests/target/fn_args_density-vertical.rs | 39 -------------------- tests/target/fn_args_layout-vertical.rs | 39 ++++++++++++++++++++ 28 files changed, 246 insertions(+), 247 deletions(-) delete mode 100644 tests/source/configs/fn_args_density/compressed.rs delete mode 100644 tests/source/configs/fn_args_density/tall.rs delete mode 100644 tests/source/configs/fn_args_density/vertical.rs create mode 100644 tests/source/configs/fn_args_layout/compressed.rs create mode 100644 tests/source/configs/fn_args_layout/tall.rs create mode 100644 tests/source/configs/fn_args_layout/vertical.rs delete mode 100644 tests/source/fn_args_density-vertical.rs create mode 100644 tests/source/fn_args_layout-vertical.rs delete mode 100644 tests/target/configs/fn_args_density/compressed.rs delete mode 100644 tests/target/configs/fn_args_density/tall.rs delete mode 100644 tests/target/configs/fn_args_density/vertical.rs create mode 100644 tests/target/configs/fn_args_layout/compressed.rs create mode 100644 tests/target/configs/fn_args_layout/tall.rs create mode 100644 tests/target/configs/fn_args_layout/vertical.rs delete mode 100644 tests/target/fn_args_density-vertical.rs create mode 100644 tests/target/fn_args_layout-vertical.rs (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index 836b2fd81a1..be4e6c42074 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ ## [Unreleased] +### Changed + - Change option `format_doc_comment` to `format_code_in_doc_comment`. - `use_small_heuristics` changed to be an enum and stabilised. Configuration options are now ready for 1.0. +- Stabilise `fn_args_density` configuration option and rename it to `fn_args_layout` #3581 ## [1.2.2] 2019-04-24 diff --git a/Configurations.md b/Configurations.md index 3737b1c9a4e..304bc690034 100644 --- a/Configurations.md +++ b/Configurations.md @@ -629,13 +629,13 @@ trailing whitespaces. - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: #3392) -## `fn_args_density` +## `fn_args_layout` -Argument density in functions +Control the layout of arguments in a function - **Default value**: `"Tall"` - **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"` -- **Stable**: No (tracking issue: #3375) +- **Stable**: Yes #### `"Tall"` (default): diff --git a/Processes.md b/Processes.md index 3f1c07c52b3..9d86d52b122 100644 --- a/Processes.md +++ b/Processes.md @@ -17,6 +17,7 @@ Open a pull request that closes the tracking issue. The tracking issue is listed - Update the `Config` enum marking the option as stable. - Update the the `Configuration.md` file marking the option as stable. +- Update `CHANGELOG.md` marking the option as stable. ## After the stabilisation diff --git a/src/config/mod.rs b/src/config/mod.rs index eaa6d012d5b..1b9e97fc5bf 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -92,7 +92,8 @@ create_config! { the same line with the pattern of arms"; force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; - fn_args_density: Density, Density::Tall, false, "Argument density in functions"; + fn_args_layout: Density, Density::Tall, true, + "Control the layout of arguments in a function"; brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items"; control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false, "Brace style for control flow constructs"; @@ -501,7 +502,7 @@ struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true force_multiline_blocks = false -fn_args_density = "Tall" +fn_args_layout = "Tall" brace_style = "SameLineWhere" control_brace_style = "AlwaysSameLine" trailing_semicolon = true diff --git a/src/config/options.rs b/src/config/options.rs index 72acaacd348..663c5d4dee2 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -58,10 +58,11 @@ pub enum IndentStyle { #[config_type] /// How to place a list-like items. +/// FIXME: Issue-3581: this should be renamed to ItemsLayout when publishing 2.0 pub enum Density { /// Fit as much on one line as possible. Compressed, - /// Use more lines. + /// Items are placed horizontally if sufficient space, vertically otherwise. Tall, /// Place every item on a separate line. Vertical, diff --git a/src/items.rs b/src/items.rs index 7640fa32d22..ea0475ccc57 100644 --- a/src/items.rs +++ b/src/items.rs @@ -15,7 +15,7 @@ use crate::comment::{ FindUncommented, }; use crate::config::lists::*; -use crate::config::{BraceStyle, Config, Density, IndentStyle, Version}; +use crate::config::{BraceStyle, Config, IndentStyle, Version}; use crate::expr::{ format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, ExprType, RhsTactics, @@ -703,7 +703,7 @@ pub(crate) fn format_impl( &generics.where_clause, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), - Density::Vertical, + false, "{", where_span_end, self_ty.span.hi(), @@ -1044,11 +1044,7 @@ pub(crate) fn format_trait( // Rewrite where-clause. if !generics.where_clause.predicates.is_empty() { - let where_density = if context.config.indent_style() == IndentStyle::Block { - Density::Compressed - } else { - Density::Tall - }; + let where_on_new_line = context.config.indent_style() != IndentStyle::Block; let where_budget = context.budget(last_line_width(&result)); let pos_before_where = if generic_bounds.is_empty() { @@ -1062,7 +1058,7 @@ pub(crate) fn format_trait( &generics.where_clause, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), - where_density, + where_on_new_line, "{", None, pos_before_where, @@ -1171,7 +1167,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { &self.generics.where_clause, context.config.brace_style(), shape, - Density::Compressed, + false, ";", None, self.generics.where_clause.span.lo(), @@ -1423,7 +1419,7 @@ fn format_tuple_struct( &generics.where_clause, context.config.brace_style(), Shape::legacy(where_budget, offset.block_only()), - Density::Compressed, + false, ";", None, body_hi, @@ -1499,7 +1495,7 @@ fn rewrite_type_prefix( &generics.where_clause, context.config.brace_style(), Shape::legacy(where_budget, indent), - Density::Vertical, + false, "=", None, generics.span.hi(), @@ -2258,7 +2254,7 @@ fn rewrite_fn_base( where_clause, context.config.brace_style(), Shape::indented(indent, context.config), - Density::Tall, + true, "{", Some(span.hi()), pos_before_where, @@ -2390,7 +2386,7 @@ fn rewrite_args( &arg_items, context .config - .fn_args_density() + .fn_args_layout() .to_list_tactic(arg_items.len()), Separator::Comma, one_line_budget, @@ -2677,7 +2673,7 @@ fn rewrite_where_clause( where_clause: &ast::WhereClause, brace_style: BraceStyle, shape: Shape, - density: Density, + on_new_line: bool, terminator: &str, span_end: Option, span_end_before_where: BytePos, @@ -2757,7 +2753,7 @@ fn rewrite_where_clause( } else { terminator.len() }; - if density == Density::Tall + if on_new_line || preds_str.contains('\n') || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { @@ -2848,7 +2844,7 @@ fn format_generics( &generics.where_clause, brace_style, Shape::legacy(budget, offset.block_only()), - Density::Tall, + true, "{", Some(span.hi()), span_end_before_where, diff --git a/src/lists.rs b/src/lists.rs index f57a78f9874..428a0eab9b0 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -246,10 +246,7 @@ where let total_sep_len = sep.len() * sep_count.saturating_sub(1); let real_total = total_width + total_sep_len; - if real_total <= limit - && !pre_line_comments - && !items.into_iter().any(|item| item.as_ref().is_multiline()) - { + if real_total <= limit && !items.into_iter().any(|item| item.as_ref().is_multiline()) { DefinitiveListTactic::Horizontal } else { match tactic { diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index d03ac281acb..35c8fd86467 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -3,7 +3,7 @@ comment_width = 80 tab_spaces = 2 newline_style = "Unix" brace_style = "SameLineWhere" -fn_args_density = "Tall" +fn_args_layout = "Tall" trailing_comma = "Vertical" indent_style = "Block" report_todo = "Always" diff --git a/tests/source/configs/fn_args_density/compressed.rs b/tests/source/configs/fn_args_density/compressed.rs deleted file mode 100644 index 86c0b42e53c..00000000000 --- a/tests/source/configs/fn_args_density/compressed.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/source/configs/fn_args_density/tall.rs b/tests/source/configs/fn_args_density/tall.rs deleted file mode 100644 index fc400e1c113..00000000000 --- a/tests/source/configs/fn_args_density/tall.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Tall -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/source/configs/fn_args_density/vertical.rs b/tests/source/configs/fn_args_density/vertical.rs deleted file mode 100644 index 20b1427d83d..00000000000 --- a/tests/source/configs/fn_args_density/vertical.rs +++ /dev/null @@ -1,16 +0,0 @@ -// rustfmt-fn_args_density: Vertical -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { - // body - } -} diff --git a/tests/source/configs/fn_args_layout/compressed.rs b/tests/source/configs/fn_args_layout/compressed.rs new file mode 100644 index 00000000000..66a371c259f --- /dev/null +++ b/tests/source/configs/fn_args_layout/compressed.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_layout: Compressed +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/tests/source/configs/fn_args_layout/tall.rs b/tests/source/configs/fn_args_layout/tall.rs new file mode 100644 index 00000000000..f11e86fd313 --- /dev/null +++ b/tests/source/configs/fn_args_layout/tall.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_layout: Tall +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/tests/source/configs/fn_args_layout/vertical.rs b/tests/source/configs/fn_args_layout/vertical.rs new file mode 100644 index 00000000000..a23cc025225 --- /dev/null +++ b/tests/source/configs/fn_args_layout/vertical.rs @@ -0,0 +1,16 @@ +// rustfmt-fn_args_layout: Vertical +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } +} diff --git a/tests/source/fn-custom-7.rs b/tests/source/fn-custom-7.rs index d76125234fa..d5330196bf7 100644 --- a/tests/source/fn-custom-7.rs +++ b/tests/source/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_density: Vertical +// rustfmt-fn_args_layout: Vertical // rustfmt-brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/source/fn-custom.rs b/tests/source/fn-custom.rs index b8d734bfbaf..77ced4c5e0e 100644 --- a/tests/source/fn-custom.rs +++ b/tests/source/fn-custom.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_density: Compressed +// rustfmt-fn_args_layout: Compressed // Test some of the ways function signatures can be customised. // Test compressed layout of args. diff --git a/tests/source/fn_args_density-vertical.rs b/tests/source/fn_args_density-vertical.rs deleted file mode 100644 index b61c337dfb9..00000000000 --- a/tests/source/fn_args_density-vertical.rs +++ /dev/null @@ -1,33 +0,0 @@ -// rustfmt-fn_args_density: Vertical - -// Empty list should stay on one line. -fn do_bar( - -) -> u8 { - bar() -} - -// A single argument should stay on the same line. -fn do_bar( - a: u8) -> u8 { - bar() -} - -// Multiple arguments should each get their own line. -fn do_bar(a: u8, mut b: u8, c: &u8, d: &mut u8, closure: &Fn(i32) -> i32) -> i32 { - // This feature should not affect closures. - let bar = |x: i32, y: i32| -> i32 { x + y }; - bar(a, b) -} - -// If the first argument doesn't fit on the same line with the function name, -// the whole list should probably be pushed to the next line with hanging -// indent. That's not what happens though, so check current behaviour instead. -// In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, c: u8, d: u8) { - this(); - that(); - the_other_thing(); -} diff --git a/tests/source/fn_args_layout-vertical.rs b/tests/source/fn_args_layout-vertical.rs new file mode 100644 index 00000000000..759bc83d015 --- /dev/null +++ b/tests/source/fn_args_layout-vertical.rs @@ -0,0 +1,33 @@ +// rustfmt-fn_args_layout: Vertical + +// Empty list should stay on one line. +fn do_bar( + +) -> u8 { + bar() +} + +// A single argument should stay on the same line. +fn do_bar( + a: u8) -> u8 { + bar() +} + +// Multiple arguments should each get their own line. +fn do_bar(a: u8, mut b: u8, c: &u8, d: &mut u8, closure: &Fn(i32) -> i32) -> i32 { + // This feature should not affect closures. + let bar = |x: i32, y: i32| -> i32 { x + y }; + bar(a, b) +} + +// If the first argument doesn't fit on the same line with the function name, +// the whole list should probably be pushed to the next line with hanging +// indent. That's not what happens though, so check current behaviour instead. +// In any case, it should maintain single argument per line. +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, c: u8, d: u8) { + this(); + that(); + the_other_thing(); +} diff --git a/tests/target/configs/fn_args_density/compressed.rs b/tests/target/configs/fn_args_density/compressed.rs deleted file mode 100644 index 99283722bee..00000000000 --- a/tests/target/configs/fn_args_density/compressed.rs +++ /dev/null @@ -1,22 +0,0 @@ -// rustfmt-fn_args_density: Compressed -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, - adipiscing: Adipiscing, elit: Elit, - ) { - // body - } -} diff --git a/tests/target/configs/fn_args_density/tall.rs b/tests/target/configs/fn_args_density/tall.rs deleted file mode 100644 index 6ee43b41a19..00000000000 --- a/tests/target/configs/fn_args_density/tall.rs +++ /dev/null @@ -1,32 +0,0 @@ -// rustfmt-fn_args_density: Tall -// Function arguments density - -trait Lorem { - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); - - fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} diff --git a/tests/target/configs/fn_args_density/vertical.rs b/tests/target/configs/fn_args_density/vertical.rs deleted file mode 100644 index d48b3492452..00000000000 --- a/tests/target/configs/fn_args_density/vertical.rs +++ /dev/null @@ -1,42 +0,0 @@ -// rustfmt-fn_args_density: Vertical -// Function arguments density - -trait Lorem { - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - ) { - // body - } - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ); - - fn lorem( - ipsum: Ipsum, - dolor: Dolor, - sit: Sit, - amet: Amet, - consectetur: onsectetur, - adipiscing: Adipiscing, - elit: Elit, - ) { - // body - } -} diff --git a/tests/target/configs/fn_args_layout/compressed.rs b/tests/target/configs/fn_args_layout/compressed.rs new file mode 100644 index 00000000000..f189446e25d --- /dev/null +++ b/tests/target/configs/fn_args_layout/compressed.rs @@ -0,0 +1,22 @@ +// rustfmt-fn_args_layout: Compressed +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, + adipiscing: Adipiscing, elit: Elit, + ) { + // body + } +} diff --git a/tests/target/configs/fn_args_layout/tall.rs b/tests/target/configs/fn_args_layout/tall.rs new file mode 100644 index 00000000000..20f308973ac --- /dev/null +++ b/tests/target/configs/fn_args_layout/tall.rs @@ -0,0 +1,32 @@ +// rustfmt-fn_args_layout: Tall +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} diff --git a/tests/target/configs/fn_args_layout/vertical.rs b/tests/target/configs/fn_args_layout/vertical.rs new file mode 100644 index 00000000000..6c695a75df9 --- /dev/null +++ b/tests/target/configs/fn_args_layout/vertical.rs @@ -0,0 +1,42 @@ +// rustfmt-fn_args_layout: Vertical +// Function arguments density + +trait Lorem { + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } +} diff --git a/tests/target/fn-custom-7.rs b/tests/target/fn-custom-7.rs index f98150c4291..2c20ac5a752 100644 --- a/tests/target/fn-custom-7.rs +++ b/tests/target/fn-custom-7.rs @@ -1,5 +1,5 @@ // rustfmt-normalize_comments: true -// rustfmt-fn_args_density: Vertical +// rustfmt-fn_args_layout: Vertical // rustfmt-brace_style: AlwaysNextLine // Case with only one variable. diff --git a/tests/target/fn-custom.rs b/tests/target/fn-custom.rs index bf87553dedc..2eb2a973d24 100644 --- a/tests/target/fn-custom.rs +++ b/tests/target/fn-custom.rs @@ -1,4 +1,4 @@ -// rustfmt-fn_args_density: Compressed +// rustfmt-fn_args_layout: Compressed // Test some of the ways function signatures can be customised. // Test compressed layout of args. diff --git a/tests/target/fn_args_density-vertical.rs b/tests/target/fn_args_density-vertical.rs deleted file mode 100644 index 477a48cc35f..00000000000 --- a/tests/target/fn_args_density-vertical.rs +++ /dev/null @@ -1,39 +0,0 @@ -// rustfmt-fn_args_density: Vertical - -// Empty list should stay on one line. -fn do_bar() -> u8 { - bar() -} - -// A single argument should stay on the same line. -fn do_bar(a: u8) -> u8 { - bar() -} - -// Multiple arguments should each get their own line. -fn do_bar( - a: u8, - mut b: u8, - c: &u8, - d: &mut u8, - closure: &Fn(i32) -> i32, -) -> i32 { - // This feature should not affect closures. - let bar = |x: i32, y: i32| -> i32 { x + y }; - bar(a, b) -} - -// If the first argument doesn't fit on the same line with the function name, -// the whole list should probably be pushed to the next line with hanging -// indent. That's not what happens though, so check current behaviour instead. -// In any case, it should maintain single argument per line. -fn do_this_that_and_the_other_thing( - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, - b: u8, - c: u8, - d: u8, -) { - this(); - that(); - the_other_thing(); -} diff --git a/tests/target/fn_args_layout-vertical.rs b/tests/target/fn_args_layout-vertical.rs new file mode 100644 index 00000000000..da0ac981d87 --- /dev/null +++ b/tests/target/fn_args_layout-vertical.rs @@ -0,0 +1,39 @@ +// rustfmt-fn_args_layout: Vertical + +// Empty list should stay on one line. +fn do_bar() -> u8 { + bar() +} + +// A single argument should stay on the same line. +fn do_bar(a: u8) -> u8 { + bar() +} + +// Multiple arguments should each get their own line. +fn do_bar( + a: u8, + mut b: u8, + c: &u8, + d: &mut u8, + closure: &Fn(i32) -> i32, +) -> i32 { + // This feature should not affect closures. + let bar = |x: i32, y: i32| -> i32 { x + y }; + bar(a, b) +} + +// If the first argument doesn't fit on the same line with the function name, +// the whole list should probably be pushed to the next line with hanging +// indent. That's not what happens though, so check current behaviour instead. +// In any case, it should maintain single argument per line. +fn do_this_that_and_the_other_thing( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: u8, + b: u8, + c: u8, + d: u8, +) { + this(); + that(); + the_other_thing(); +} -- cgit 1.4.1-3-g733a5 From 2244f326e65a21b7025691478a3218d588d74f7e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 3 Jun 2019 23:57:02 +0900 Subject: Cargo update (#3559) Update `rustc-ap-*` crates to 486.0.0. --- Cargo.lock | 335 ++++++++++++++++++++++++++--------------------- Cargo.toml | 6 +- src/attr.rs | 22 ++-- src/chains.rs | 13 +- src/closures.rs | 36 ++++- src/expr.rs | 21 ++- src/formatting.rs | 8 +- src/imports.rs | 5 +- src/items.rs | 23 ++-- src/macros.rs | 135 +++++++++---------- src/matches.rs | 2 +- src/modules.rs | 9 +- src/overflow.rs | 12 +- src/reorder.rs | 7 +- src/spanned.rs | 6 + src/types.rs | 4 +- src/utils.rs | 34 +++-- src/visitor.rs | 8 +- tests/source/async_fn.rs | 4 +- tests/target/async_fn.rs | 4 +- 20 files changed, 396 insertions(+), 298 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b5eec3599de..a14828ed62f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,27 +46,26 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.15" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -74,8 +73,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -94,7 +93,7 @@ dependencies = [ [[package]] name = "bstr" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -118,21 +117,21 @@ name = "cargo_metadata" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -161,9 +160,9 @@ dependencies = [ name = "config_proc_macro" version = "0.1.0" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -195,7 +194,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -208,7 +207,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -216,7 +215,7 @@ name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -225,9 +224,9 @@ name = "derive-new" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -240,7 +239,7 @@ name = "dirs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -252,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ena" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -272,10 +271,11 @@ dependencies = [ [[package]] name = "error-chain" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -283,7 +283,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -292,10 +292,10 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -310,7 +310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -322,7 +322,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -333,7 +333,7 @@ name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -361,6 +361,11 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "itertools" version = "0.8.0" @@ -371,7 +376,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -379,7 +384,7 @@ name = "jobserver" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -391,7 +396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.51" +version = "0.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -408,7 +413,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -431,9 +436,14 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "owning_ref" version = "0.4.0" @@ -447,7 +457,7 @@ name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -464,7 +474,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -473,7 +483,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.27" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -489,7 +499,7 @@ name = "quote" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -497,13 +507,13 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -515,7 +525,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -550,10 +560,10 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -565,7 +575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -576,7 +586,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -642,20 +652,21 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -665,85 +676,103 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_macros" +version = "486.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_target" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "407.0.0" +version = "486.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -763,22 +792,22 @@ dependencies = [ [[package]] name = "rustc-rayon" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-rayon-core" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -809,29 +838,29 @@ dependencies = [ "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ryu" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -863,7 +892,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -873,20 +902,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -894,9 +923,9 @@ name = "serde_json" version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -929,29 +958,29 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.32" +version = "0.15.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -975,10 +1004,11 @@ dependencies = [ [[package]] name = "termion" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1001,10 +1031,10 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1014,7 +1044,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1042,6 +1072,11 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.7" @@ -1095,17 +1130,17 @@ dependencies = [ "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" +"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" +"checksum backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1a13fc43f04daf08ab4f71e3d27e1fc27fc437d3e95ac0063a796d92fb40f39b" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c8203ca06c502958719dae5f653a79e0cc6ba808ed02beffbf27d09610f2143" +"checksum bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "59604ece62a407dc9164732e5adea02467898954c3a5811fd2dc140af14ef15b" "checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "178d62b240c34223f265a4c1e275e37d62da163d421fc8d7f7e3ee340f803c57" -"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" @@ -1118,34 +1153,36 @@ dependencies = [ "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" +"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" +"checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" "checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b3d51e24009d966c8285d524dbaf6d60926636b2a89caee9ce0bd612494ddc16" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" +"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" @@ -1154,7 +1191,7 @@ dependencies = [ "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" @@ -1164,51 +1201,53 @@ dependencies = [ "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum rustc-ap-arena 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5aab2fb5e5becf1c9183f6c63b8714817a3e780a20b4fe6b3920751c98a18225" -"checksum rustc-ap-graphviz 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0235ff613d4f96176ea56748010b5d8e978605cc47856ba9bb5372f4f38e9c03" -"checksum rustc-ap-rustc_cratesio_shim 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e04a90b0dd8597da83633961698c61a2948f50c9d4b9a71e8afafc0ba0f158" -"checksum rustc-ap-rustc_data_structures 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c03988d65fc5130787df32e8ea91738f78a8ed62b7a5bdd77f10e5cceb531d8e" -"checksum rustc-ap-rustc_errors 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b33b9dc34f9fa50bf7e6fd14f2f3c1adc69833acf43c10f3e9795bd4d613712" -"checksum rustc-ap-rustc_target 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6de75caef2c7acba11994614266d60238653657677934817ab368d169333cba" -"checksum rustc-ap-serialize 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf09c60aaee892b0fd107544cfe607d8d463e7f33da34aa823566b8fd2b17f53" -"checksum rustc-ap-syntax 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69f38cc120ff317678bbda8c4f58c1bbc1de64b615383ab01480482dde5e95a1" -"checksum rustc-ap-syntax_pos 407.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20a0a201141c5c416b1924b079eeefc7b013e34ece0740ce4997f358b3684a7f" +"checksum rustc-ap-arena 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af30808ea1dad5e3967d1997d97f32829ff9a999686768aac694ca20a8ca5507" +"checksum rustc-ap-graphviz 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8c4bc0c92187923ced8e6d1cbdde129b0fce020af817d8a889fddc36d81429" +"checksum rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "724100fb95b88e6f2a870cd957d60fc4f62d7a26f1e5b889ebcb090965118d33" +"checksum rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d178c2ffcacf8e95d3af281b23d382ef8efce581bdd487a8fac38624a52344f" +"checksum rustc-ap-rustc_errors 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229720cd73ce22a76e763f6554653863f91667c624bc92f89422beeb72002ebb" +"checksum rustc-ap-rustc_macros 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd85f5873ed31ab1d511e132743e08f14c88d912dfcf1d7949b7d5666ba030e7" +"checksum rustc-ap-rustc_target 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "190dbb1a01e51b2280387cc18985382e785da2264473ff9a86ad6917c8343a6e" +"checksum rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de6ea7e67ea3b8ddee324339bf4369c9af5c72a664b98f33083f8480c1df3b4" +"checksum rustc-ap-syntax 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4620f48399b89ab3eee54e81c0206e60645ce7b658269f09a7a9752f66c78fa1" +"checksum rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bf89da0ea5cde2c8ab974aaf7941ac4e1c9ba9cd2e00e3814974bd4a2bfe68" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" -"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544" -"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108" +"checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" +"checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" "checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" -"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" +"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" +"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" "checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" -"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum toml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87c5890a989fa47ecdc7bcb4c63a77a82c18f306714104b1decfd722db17b39e" +"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" +"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/Cargo.toml b/Cargo.toml index 1321f0e84ef..92418a49ec5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.7" -rustc-ap-rustc_target = "407.0.0" -rustc-ap-syntax = "407.0.0" -rustc-ap-syntax_pos = "407.0.0" +rustc-ap-rustc_target = "486.0.0" +rustc-ap-syntax = "486.0.0" +rustc-ap-syntax_pos = "486.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/attr.rs b/src/attr.rs index 1fb4ef407eb..78d88958ac7 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -2,6 +2,7 @@ use syntax::ast; use syntax::source_map::{BytePos, Span, DUMMY_SP}; +use syntax::symbol::sym; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; @@ -52,7 +53,7 @@ pub(crate) fn filter_inline_attrs( } fn is_derive(attr: &ast::Attribute) -> bool { - attr.check_name("derive") + attr.check_name(sym::derive) } /// Returns the arguments of `#[derive(...)]`. @@ -60,7 +61,7 @@ fn get_derive_spans<'a>(attr: &'a ast::Attribute) -> Option, shape: Shape) -> Option { - match self.node { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), - ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape), + match self { + ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape), + ast::NestedMetaItem::Literal(ref l) => rewrite_literal(context, l, shape), } } } @@ -219,10 +220,10 @@ impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { Some(match self.node { ast::MetaItemKind::Word => { - rewrite_path(context, PathContext::Type, None, &self.ident, shape)? + rewrite_path(context, PathContext::Type, None, &self.path, shape)? } ast::MetaItemKind::List(ref list) => { - let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; + let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?; let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span); overflow::rewrite_with_parens( context, @@ -240,7 +241,7 @@ impl Rewrite for ast::MetaItem { )? } ast::MetaItemKind::NameValue(ref literal) => { - let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?; + let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?; // 3 = ` = ` let lit_shape = shape.shrink_left(path.len() + 3)?; // `rewrite_literal` returns `None` when `literal` exceeds max @@ -326,15 +327,16 @@ impl Rewrite for ast::Attribute { if let Some(ref meta) = self.meta() { // This attribute is possibly a doc attribute needing normalization to a doc comment - if context.config.normalize_doc_attributes() && meta.check_name("doc") { + if context.config.normalize_doc_attributes() && meta.check_name(sym::doc) { if let Some(ref literal) = meta.value_str() { let comment_style = match self.style { ast::AttrStyle::Inner => CommentStyle::Doc, ast::AttrStyle::Outer => CommentStyle::TripleSlash, }; + let literal_str = literal.as_str(); let doc_comment_formatter = - DocCommentFormatter::new(literal.as_str().get(), comment_style); + DocCommentFormatter::new(literal_str.get(), comment_style); let doc_comment = format!("{}", doc_comment_formatter); return rewrite_doc_comment( &doc_comment, diff --git a/src/chains.rs b/src/chains.rs index c4941141a64..9a5823817a1 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -118,6 +118,7 @@ enum ChainItemKind { ), StructField(ast::Ident), TupleField(ast::Ident, bool), + Await, Comment(String, CommentPosition), } @@ -128,6 +129,7 @@ impl ChainItemKind { ChainItemKind::MethodCall(..) | ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) + | ChainItemKind::Await | ChainItemKind::Comment(..) => false, } } @@ -166,6 +168,10 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), field.span.hi()); (kind, span) } + ast::ExprKind::Await(_, ref nested) => { + let span = mk_sp(nested.span.hi(), expr.span.hi()); + (ChainItemKind::Await, span) + } _ => return (ChainItemKind::Parent(expr.clone()), expr.span), }; @@ -189,6 +195,7 @@ impl Rewrite for ChainItem { if nested { " " } else { "" }, rewrite_ident(context, ident) ), + ChainItemKind::Await => ".await".to_owned(), ChainItemKind::Comment(ref comment, _) => { rewrite_comment(comment, false, shape, context.config)? } @@ -387,9 +394,9 @@ impl Chain { ast::ExprKind::MethodCall(_, ref expressions) => { Some(Self::convert_try(&expressions[0], context)) } - ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) => { - Some(Self::convert_try(subexpr, context)) - } + ast::ExprKind::Field(ref subexpr, _) + | ast::ExprKind::Try(ref subexpr) + | ast::ExprKind::Await(_, ref subexpr) => Some(Self::convert_try(subexpr, context)), _ => None, } } diff --git a/src/closures.rs b/src/closures.rs index 8a7f47af44b..72d010f12b3 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,4 +1,3 @@ -use syntax::parse::classify; use syntax::source_map::Span; use syntax::{ast, ptr}; @@ -25,7 +24,7 @@ use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; pub(crate) fn rewrite_closure( capture: ast::CaptureBy, - asyncness: ast::IsAsync, + is_async: &ast::IsAsync, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -36,7 +35,7 @@ pub(crate) fn rewrite_closure( debug!("rewrite_closure {:?}", body); let (prefix, extra_offset) = rewrite_closure_fn_decl( - capture, asyncness, movability, fn_decl, body, span, context, shape, + capture, is_async, movability, fn_decl, body, span, context, shape, )?; // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; @@ -134,7 +133,7 @@ fn rewrite_closure_with_block( shape: Shape, ) -> Option { let left_most = left_most_sub_expr(body); - let veto_block = veto_block(body) && !classify::expr_requires_semi_to_be_stmt(left_most); + let veto_block = veto_block(body) && !expr_requires_semi_to_be_stmt(left_most); if veto_block { return None; } @@ -207,7 +206,7 @@ fn rewrite_closure_block( // Return type is (prefix, extra_offset) fn rewrite_closure_fn_decl( capture: ast::CaptureBy, - asyncness: ast::IsAsync, + asyncness: &ast::IsAsync, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -291,7 +290,7 @@ pub(crate) fn rewrite_last_closure( expr: &ast::Expr, shape: Shape, ) -> Option { - if let ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) = + if let ast::ExprKind::Closure(capture, ref is_async, movability, ref fn_decl, ref body, _) = expr.node { let body = match body.node { @@ -305,7 +304,7 @@ pub(crate) fn rewrite_last_closure( _ => body, }; let (prefix, extra_offset) = rewrite_closure_fn_decl( - capture, asyncness, movability, fn_decl, body, expr.span, context, shape, + capture, is_async, movability, fn_decl, body, expr.span, context, shape, )?; // If the closure goes multi line before its body, do not overflow the closure. if prefix.contains('\n') { @@ -387,3 +386,26 @@ fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { _ => false, } } + +/// Does this expression require a semicolon to be treated +/// as a statement? The negation of this: 'can this expression +/// be used as a statement without a semicolon' -- is used +/// as an early-bail-out in the parser so that, for instance, +/// if true {...} else {...} +/// |x| 5 +/// isn't parsed as (if true {...} else {...} | x) | 5 +// From https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/classify.rs. +fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { + match e.node { + ast::ExprKind::If(..) + | ast::ExprKind::IfLet(..) + | ast::ExprKind::Match(..) + | ast::ExprKind::Block(..) + | ast::ExprKind::While(..) + | ast::ExprKind::WhileLet(..) + | ast::ExprKind::Loop(..) + | ast::ExprKind::ForLoop(..) + | ast::ExprKind::TryBlock(..) => false, + _ => true, + } +} diff --git a/src/expr.rs b/src/expr.rs index 23628d929e8..78473803fa9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::cmp::min; +use std::iter; use itertools::Itertools; use syntax::parse::token::DelimToken; @@ -183,9 +184,9 @@ pub(crate) fn format_expr( Some("yield".to_string()) } } - ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) => { + ast::ExprKind::Closure(capture, ref is_async, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( - capture, asyncness, movability, fn_decl, body, expr.span, context, shape, + capture, is_async, movability, fn_decl, body, expr.span, context, shape, ) } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => { @@ -335,10 +336,6 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::ObsoleteInPlace(ref lhs, ref rhs) => lhs - .rewrite(context, shape) - .map(|s| s + " <-") - .and_then(|lhs| rewrite_assign_rhs(context, lhs, &**rhs, shape)), ast::ExprKind::Async(capture_by, _node_id, ref block) => { let mover = if capture_by == ast::CaptureBy::Value { "move " @@ -371,6 +368,18 @@ pub(crate) fn format_expr( )) } } + ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, _) => rewrite_chain(expr, context, shape), + ast::ExprKind::Await(ast::AwaitOrigin::MacroLike, ref nested) => { + overflow::rewrite_with_parens( + context, + "await!", + iter::once(nested), + shape, + expr.span, + context.config.max_width(), + None, + ) + } ast::ExprKind::Err => None, }; diff --git a/src/formatting.rs b/src/formatting.rs index 47d885ef2e3..acfd3723b1a 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -33,11 +33,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::VersionMismatch); } - syntax::with_globals(|| { - syntax_pos::hygiene::set_default_edition( - self.config.edition().to_libsyntax_pos_edition(), - ); - + syntax::with_globals(self.config.edition().to_libsyntax_pos_edition(), || { if self.config.disable_all_formatting() { // When the input is from stdin, echo back the input. if let Input::Text(ref buf) = input { @@ -687,7 +683,7 @@ fn parse_crate( struct SilentEmitter; impl Emitter for SilentEmitter { - fn emit(&mut self, _db: &DiagnosticBuilder<'_>) {} + fn emit_diagnostic(&mut self, _db: &DiagnosticBuilder<'_>) {} } fn silent_emitter() -> Box { diff --git a/src/imports.rs b/src/imports.rs index eeda0b5cb7b..dd506000a69 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -4,6 +4,7 @@ use std::fmt; use syntax::ast::{self, UseTreeKind}; use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; +use syntax::symbol::sym; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; @@ -249,7 +250,7 @@ impl UseTree { match self.attrs { Some(ref attrs) if !attrs.is_empty() => { let attr_str = attrs.rewrite(context, shape)?; - let lo = attrs.last().as_ref()?.span().hi(); + let lo = attrs.last().as_ref()?.span.hi(); let hi = self.span.lo(); let span = mk_sp(lo, hi); @@ -395,7 +396,7 @@ impl UseTree { rewrite_ident(context, path_to_imported_ident(&a.prefix)).to_owned() }; let alias = rename.and_then(|ident| { - if ident.name == "_" { + if ident.name == sym::underscore_imports { // for impl-only-use Some("_".to_owned()) } else if ident == path_to_imported_ident(&a.prefix) { diff --git a/src/items.rs b/src/items.rs index ea0475ccc57..cffb580a814 100644 --- a/src/items.rs +++ b/src/items.rs @@ -161,7 +161,7 @@ pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, abi: abi::Abi, - is_async: ast::IsAsync, + is_async: Cow<'a, ast::IsAsync>, constness: ast::Constness, defaultness: ast::Defaultness, unsafety: ast::Unsafety, @@ -178,7 +178,7 @@ impl<'a> FnSig<'a> { decl, generics, abi: abi::Abi::Rust, - is_async: ast::IsAsync::NotAsync, + is_async: Cow::Owned(ast::IsAsync::NotAsync), constness: ast::Constness::NotConst, defaultness: ast::Defaultness::Final, unsafety: ast::Unsafety::Normal, @@ -192,7 +192,7 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, - is_async: method_sig.header.asyncness.node, + is_async: Cow::Borrowed(&method_sig.header.asyncness.node), constness: method_sig.header.constness.node, defaultness: ast::Defaultness::Final, abi: method_sig.header.abi, @@ -214,7 +214,7 @@ impl<'a> FnSig<'a> { generics, abi: fn_header.abi, constness: fn_header.constness.node, - is_async: fn_header.asyncness.node, + is_async: Cow::Borrowed(&fn_header.asyncness.node), defaultness, unsafety: fn_header.unsafety, visibility: visibility.clone(), @@ -237,8 +237,8 @@ impl<'a> FnSig<'a> { result.push_str(&*format_visibility(context, &self.visibility)); result.push_str(format_defaultness(self.defaultness)); result.push_str(format_constness(self.constness)); + result.push_str(format_async(&self.is_async)); result.push_str(format_unsafety(self.unsafety)); - result.push_str(format_async(self.is_async)); result.push_str(&format_abi( self.abi, context.config.force_explicit_abi(), @@ -422,7 +422,10 @@ impl<'a> FmtVisitor<'a> { } pub(crate) fn visit_struct(&mut self, struct_parts: &StructParts<'_>) { - let is_tuple = struct_parts.def.is_tuple(); + let is_tuple = match struct_parts.def { + ast::VariantData::Tuple(..) => true, + _ => false, + }; let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None) .map(|s| if is_tuple { s + ";" } else { s }); self.push_rewrite(struct_parts.span, rewrite); @@ -1982,7 +1985,7 @@ pub(crate) fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> B pub(crate) fn is_named_arg(arg: &ast::Arg) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { - ident != symbol::keywords::Invalid.ident() + ident.name != symbol::kw::Invalid } else { true } @@ -2931,11 +2934,11 @@ impl Rewrite for ast::ForeignItem { false, ) .map(|(s, _)| format!("{};", s)), - ast::ForeignItemKind::Static(ref ty, is_mutable) => { + ast::ForeignItemKind::Static(ref ty, mutability) => { // FIXME(#21): we're dropping potential comments in between the - // function keywords here. + // function kw here. let vis = format_visibility(context, &self.vis); - let mut_str = if is_mutable { "mut " } else { "" }; + let mut_str = format_mutability(mutability); let prefix = format!( "{}static {}{}:", vis, diff --git a/src/macros.rs b/src/macros.rs index 077e6a32d62..7122a60f2cf 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -17,10 +17,11 @@ use syntax::parse::parser::Parser; use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::print::pprust; use syntax::source_map::{BytePos, Span}; -use syntax::symbol::keywords; +use syntax::symbol::kw; use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, parse, ptr}; +use syntax_pos::Symbol; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, @@ -149,7 +150,7 @@ fn rewrite_macro_name( format!("{}!", path) }; match extra_ident { - Some(ident) if ident != keywords::Invalid.ident() => format!("{} {}", name, ident), + Some(ident) if ident.name != kw::Invalid => format!("{} {}", name, ident), _ => name, } } @@ -231,7 +232,7 @@ pub(crate) fn rewrite_macro( } fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { - for &keyword in RUST_KEYWORDS.iter() { + for &keyword in RUST_KW.iter() { if parser.token.is_keyword(keyword) && parser.look_ahead(1, |t| { *t == Token::Eof @@ -239,7 +240,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { || *t == Token::CloseDelim(DelimToken::NoDelim) }) { - let macro_arg = MacroArg::Keyword(keyword.ident(), parser.span); + let macro_arg = MacroArg::Keyword(ast::Ident::with_empty_ctxt(keyword), parser.span); parser.bump(); return Some(macro_arg); } @@ -1425,8 +1426,8 @@ fn format_lazy_static( while parser.token != Token::Eof { // Parse a `lazy_static!` item. let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false)); - parser.eat_keyword(keywords::Static); - parser.eat_keyword(keywords::Ref); + parser.eat_keyword(kw::Static); + parser.eat_keyword(kw::Ref); let id = parse_or!(parse_ident); parser.eat(&Token::Colon); let ty = parse_or!(parse_ty); @@ -1502,65 +1503,65 @@ fn rewrite_macro_with_items( Some(result) } -const RUST_KEYWORDS: [keywords::Keyword; 60] = [ - keywords::PathRoot, - keywords::DollarCrate, - keywords::Underscore, - keywords::As, - keywords::Box, - keywords::Break, - keywords::Const, - keywords::Continue, - keywords::Crate, - keywords::Else, - keywords::Enum, - keywords::Extern, - keywords::False, - keywords::Fn, - keywords::For, - keywords::If, - keywords::Impl, - keywords::In, - keywords::Let, - keywords::Loop, - keywords::Match, - keywords::Mod, - keywords::Move, - keywords::Mut, - keywords::Pub, - keywords::Ref, - keywords::Return, - keywords::SelfLower, - keywords::SelfUpper, - keywords::Static, - keywords::Struct, - keywords::Super, - keywords::Trait, - keywords::True, - keywords::Type, - keywords::Unsafe, - keywords::Use, - keywords::Where, - keywords::While, - keywords::Abstract, - keywords::Become, - keywords::Do, - keywords::Final, - keywords::Macro, - keywords::Override, - keywords::Priv, - keywords::Typeof, - keywords::Unsized, - keywords::Virtual, - keywords::Yield, - keywords::Dyn, - keywords::Async, - keywords::Try, - keywords::UnderscoreLifetime, - keywords::StaticLifetime, - keywords::Auto, - keywords::Catch, - keywords::Default, - keywords::Existential, - keywords::Union, +const RUST_KW: [Symbol; 60] = [ + kw::PathRoot, + kw::DollarCrate, + kw::Underscore, + kw::As, + kw::Box, + kw::Break, + kw::Const, + kw::Continue, + kw::Crate, + kw::Else, + kw::Enum, + kw::Extern, + kw::False, + kw::Fn, + kw::For, + kw::If, + kw::Impl, + kw::In, + kw::Let, + kw::Loop, + kw::Match, + kw::Mod, + kw::Move, + kw::Mut, + kw::Pub, + kw::Ref, + kw::Return, + kw::SelfLower, + kw::SelfUpper, + kw::Static, + kw::Struct, + kw::Super, + kw::Trait, + kw::True, + kw::Type, + kw::Unsafe, + kw::Use, + kw::Where, + kw::While, + kw::Abstract, + kw::Become, + kw::Do, + kw::Final, + kw::Macro, + kw::Override, + kw::Priv, + kw::Typeof, + kw::Unsized, + kw::Virtual, + kw::Yield, + kw::Dyn, + kw::Async, + kw::Try, + kw::UnderscoreLifetime, + kw::StaticLifetime, + kw::Auto, + kw::Catch, + kw::Default, + kw::Existential, + kw::Union, ]; diff --git a/src/matches.rs b/src/matches.rs index 2e2c5477616..7c20ea06df0 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -111,7 +111,7 @@ pub(crate) fn rewrite_match( .snippet_provider .span_after(mk_sp(cond.span.hi(), hi), "{") } else { - inner_attrs[inner_attrs.len() - 1].span().hi() + inner_attrs[inner_attrs.len() - 1].span.hi() }; if arms.is_empty() { diff --git a/src/modules.rs b/src/modules.rs index 3d009b2098b..4140cb4f545 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -4,13 +4,14 @@ use std::path::{Path, PathBuf}; use syntax::ast; use syntax::parse::{parser, DirectoryOwnership}; use syntax::source_map; +use syntax::symbol::sym; use syntax_pos::symbol::Symbol; use crate::config::FileName; use crate::items::is_mod_decl; use crate::utils::contains_skip; -type FileModMap<'a> = BTreeMap; +type FileModMap<'a> = BTreeMap; /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'a, 'b> { @@ -61,7 +62,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { } self.file_map - .insert(root_filename.into(), (&krate.module, "")); + .insert(root_filename.into(), (&krate.module, String::new())); Ok(self.file_map) } @@ -80,7 +81,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { self.find_external_module(item.ident, &item.attrs)?; self.file_map.insert( FileName::Real(mod_path.clone()), - (sub_mod, item.ident.name.as_str().get()), + (sub_mod, item.ident.as_str().get().to_owned()), ); self.directory = Directory { path: mod_path.parent().unwrap().to_path_buf(), @@ -161,7 +162,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { } fn path_value(attr: &ast::Attribute) -> Option { - if attr.name() == "path" { + if attr.check_name(sym::path) { attr.value_str() } else { None diff --git a/src/overflow.rs b/src/overflow.rs index 3fe2a2fd25b..1731c3cf08e 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -123,9 +123,9 @@ impl<'a> OverflowableItem<'a> { match self { OverflowableItem::Expr(expr) => is_simple_expr(expr), OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), - OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item.node { - ast::NestedMetaItemKind::Literal(..) => true, - ast::NestedMetaItemKind::MetaItem(ref meta_item) => match meta_item.node { + OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item { + ast::NestedMetaItem::Literal(..) => true, + ast::NestedMetaItem::MetaItem(ref meta_item) => match meta_item.node { ast::MetaItemKind::Word => true, _ => false, }, @@ -172,9 +172,9 @@ impl<'a> OverflowableItem<'a> { MacroArg::Keyword(..) => false, }, OverflowableItem::NestedMetaItem(nested_meta_item) if len == 1 => { - match nested_meta_item.node { - ast::NestedMetaItemKind::Literal(..) => false, - ast::NestedMetaItemKind::MetaItem(..) => true, + match nested_meta_item { + ast::NestedMetaItem::Literal(..) => false, + ast::NestedMetaItem::MetaItem(..) => true, } } OverflowableItem::SegmentParam(seg) => match seg { diff --git a/src/reorder.rs b/src/reorder.rs index 2423fffcbea..ee80000b1fa 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -8,7 +8,7 @@ use std::cmp::{Ord, Ordering}; -use syntax::{ast, attr, source_map::Span}; +use syntax::{ast, attr, source_map::Span, symbol::sym}; use crate::attr::filter_inline_attrs; use crate::comment::combine_strs_with_missing_comments; @@ -176,7 +176,10 @@ fn rewrite_reorderable_items( } fn contains_macro_use_attr(item: &ast::Item) -> bool { - attr::contains_name(&filter_inline_attrs(&item.attrs, item.span()), "macro_use") + attr::contains_name( + &filter_inline_attrs(&item.attrs, item.span()), + sym::macro_use, + ) } /// A simplified version of `ast::ItemKind`. diff --git a/src/spanned.rs b/src/spanned.rs index 6e687a262c6..00dd24a0f06 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -193,3 +193,9 @@ impl Spanned for MacroArg { } } } + +impl Spanned for ast::NestedMetaItem { + fn span(&self) -> Span { + self.span() + } +} diff --git a/src/types.rs b/src/types.rs index eb90a67d0dc..70b8413836d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -3,7 +3,7 @@ use std::ops::Deref; use syntax::ast::{self, FunctionRetTy, Mutability}; use syntax::source_map::{self, BytePos, Span}; -use syntax::symbol::keywords; +use syntax::symbol::kw; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity}; @@ -106,7 +106,7 @@ where for segment in iter { // Indicates a global path, shouldn't be rendered. - if segment.ident.name == keywords::PathRoot.name() { + if segment.ident.name == kw::PathRoot { continue; } if first { diff --git a/src/utils.rs b/src/utils.rs index 9a0a29dc5c3..afa64e6c045 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,11 +4,12 @@ use bytecount; use rustc_target::spec::abi; use syntax::ast::{ - self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind, - NodeId, Path, Visibility, VisibilityKind, + self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NodeId, Path, Visibility, + VisibilityKind, }; use syntax::ptr; use syntax::source_map::{BytePos, Span, NO_EXPANSION}; +use syntax::symbol::{sym, Symbol}; use syntax_pos::Mark; use unicode_width::UnicodeWidthStr; @@ -17,8 +18,15 @@ use crate::config::{Config, Version}; use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; -pub(crate) const DEPR_SKIP_ANNOTATION: &str = "rustfmt_skip"; -pub(crate) const SKIP_ANNOTATION: &str = "rustfmt::skip"; +#[inline] +pub(crate) fn depr_skip_annotation() -> Symbol { + Symbol::intern("rustfmt_skip") +} + +#[inline] +pub(crate) fn skip_annotation() -> Symbol { + Symbol::intern("rustfmt::skip") +} pub(crate) fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: ast::Ident) -> &'a str { context.snippet(ident.span) @@ -81,7 +89,7 @@ pub(crate) fn format_visibility( } #[inline] -pub(crate) fn format_async(is_async: ast::IsAsync) -> &'static str { +pub(crate) fn format_async(is_async: &ast::IsAsync) -> &'static str { match is_async { ast::IsAsync::Async { .. } => "async ", ast::IsAsync::NotAsync => "", @@ -237,11 +245,11 @@ pub(crate) fn last_line_extendable(s: &str) -> bool { fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.node { MetaItemKind::Word => { - let path_str = meta_item.ident.to_string(); - path_str == SKIP_ANNOTATION || path_str == DEPR_SKIP_ANNOTATION + let path_str = meta_item.path.to_string(); + path_str == skip_annotation().as_str() || path_str == depr_skip_annotation().as_str() } MetaItemKind::List(ref l) => { - meta_item.name() == "cfg_attr" && l.len() == 2 && is_skip_nested(&l[1]) + meta_item.check_name(sym::cfg_attr) && l.len() == 2 && is_skip_nested(&l[1]) } _ => false, } @@ -249,9 +257,9 @@ fn is_skip(meta_item: &MetaItem) -> bool { #[inline] fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { - match meta_item.node { - NestedMetaItemKind::MetaItem(ref mi) => is_skip(mi), - NestedMetaItemKind::Literal(_) => false, + match meta_item { + NestedMetaItem::MetaItem(ref mi) => is_skip(mi), + NestedMetaItem::Literal(_) => false, } } @@ -625,8 +633,8 @@ pub(crate) fn get_skip_macro_names(attrs: &[ast::Attribute]) -> Vec { } if let Some(list) = attr.meta_item_list() { - for spanned in list { - if let Some(name) = spanned.name() { + for nested_meta_item in list { + if let Some(name) = nested_meta_item.ident() { skip_macro_names.push(name.to_string()); } } diff --git a/src/visitor.rs b/src/visitor.rs index 5fdd0625dff..db571abbeb0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,8 +21,8 @@ use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::utils::{ - self, contains_skip, count_newlines, get_skip_macro_names, inner_attributes, mk_sp, - ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, DEPR_SKIP_ANNOTATION, + self, contains_skip, count_newlines, depr_skip_annotation, get_skip_macro_names, + inner_attributes, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -593,7 +593,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // do not take into account the lines with attributes as part of the skipped range let attrs_end = attrs .iter() - .map(|attr| self.source_map.lookup_char_pos(attr.span().hi()).line) + .map(|attr| self.source_map.lookup_char_pos(attr.span.hi()).line) .max() .unwrap_or(1); let first_line = self.source_map.lookup_char_pos(main_span.lo()).line; @@ -656,7 +656,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Returns true if we should skip the following item. pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { - if attr.name() == DEPR_SKIP_ANNOTATION { + if attr.check_name(depr_skip_annotation()) { let file_name = self.source_map.span_to_filename(attr.span).into(); self.report.append( file_name, diff --git a/tests/source/async_fn.rs b/tests/source/async_fn.rs index f77dc73acd9..f6c5f5e1c9a 100644 --- a/tests/source/async_fn.rs +++ b/tests/source/async_fn.rs @@ -8,13 +8,13 @@ pub async fn baz() -> Result<(), ()> { Ok(()) } -unsafe async fn foo() { +async unsafe fn foo() { async move { Ok(()) } } -unsafe async fn rust() { +async unsafe fn rust() { async move { // comment Ok(()) } diff --git a/tests/target/async_fn.rs b/tests/target/async_fn.rs index bba220ee250..7992e63c080 100644 --- a/tests/target/async_fn.rs +++ b/tests/target/async_fn.rs @@ -8,11 +8,11 @@ pub async fn baz() -> Result<(), ()> { Ok(()) } -unsafe async fn foo() { +async unsafe fn foo() { async move { Ok(()) } } -unsafe async fn rust() { +async unsafe fn rust() { async move { // comment Ok(()) -- cgit 1.4.1-3-g733a5 From e0459eb3fecd8b1fe769157e3e9585a08fb10461 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Tue, 4 Jun 2019 17:14:12 +0200 Subject: inline the attribute with its item even with the macro_use attribute or when reorder_imports is disabled (#3598) --- src/items.rs | 53 ++++++++++++++++++++-- src/reorder.rs | 39 +++------------- src/visitor.rs | 13 ++++-- tests/source/issue-3585/extern_crate.rs | 12 +++++ .../source/issue-3585/reorder_imports_disabled.rs | 12 +++++ tests/source/issue-3585/reorder_imports_enabled.rs | 12 +++++ tests/source/issue-3585/use.rs | 7 +++ tests/target/issue-3585/extern_crate.rs | 10 ++++ .../target/issue-3585/reorder_imports_disabled.rs | 8 ++++ tests/target/issue-3585/reorder_imports_enabled.rs | 8 ++++ tests/target/issue-3585/use.rs | 5 ++ 11 files changed, 137 insertions(+), 42 deletions(-) create mode 100644 tests/source/issue-3585/extern_crate.rs create mode 100644 tests/source/issue-3585/reorder_imports_disabled.rs create mode 100644 tests/source/issue-3585/reorder_imports_enabled.rs create mode 100644 tests/source/issue-3585/use.rs create mode 100644 tests/target/issue-3585/extern_crate.rs create mode 100644 tests/target/issue-3585/reorder_imports_disabled.rs create mode 100644 tests/target/issue-3585/reorder_imports_enabled.rs create mode 100644 tests/target/issue-3585/use.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cffb580a814..4ae3f383e74 100644 --- a/src/items.rs +++ b/src/items.rs @@ -9,6 +9,7 @@ use syntax::source_map::{self, BytePos, Span}; use syntax::visit; use syntax::{ast, ptr, symbol}; +use crate::attr::filter_inline_attrs; use crate::comment::{ combine_strs_with_missing_comments, contains_comment, is_last_comment_block, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, @@ -2977,29 +2978,71 @@ impl Rewrite for ast::ForeignItem { } } +/// Rewrite the attributes of an item. +fn rewrite_attrs( + context: &RewriteContext<'_>, + item: &ast::Item, + item_str: &str, + shape: Shape, +) -> Option { + let attrs = filter_inline_attrs(&item.attrs, item.span()); + let attrs_str = attrs.rewrite(context, shape)?; + + let missed_span = if attrs.is_empty() { + mk_sp(item.span.lo(), item.span.lo()) + } else { + mk_sp(attrs[attrs.len() - 1].span.hi(), item.span.lo()) + }; + + let allow_extend = if attrs.len() == 1 { + let line_len = attrs_str.len() + 1 + item_str.len(); + !attrs.first().unwrap().is_sugared_doc + && context.config.inline_attribute_width() >= line_len + } else { + false + }; + + combine_strs_with_missing_comments( + context, + &attrs_str, + &item_str, + missed_span, + shape, + allow_extend, + ) +} + /// Rewrite an inline mod. -pub(crate) fn rewrite_mod(context: &RewriteContext<'_>, item: &ast::Item) -> String { +/// The given shape is used to format the mod's attributes. +pub(crate) fn rewrite_mod( + context: &RewriteContext<'_>, + item: &ast::Item, + attrs_shape: Shape, +) -> Option { let mut result = String::with_capacity(32); result.push_str(&*format_visibility(context, &item.vis)); result.push_str("mod "); result.push_str(rewrite_ident(context, item.ident)); result.push(';'); - result + rewrite_attrs(context, item, &result, attrs_shape) } -/// Rewrite `extern crate foo;` WITHOUT attributes. +/// Rewrite `extern crate foo;`. +/// The given shape is used to format the extern crate's attributes. pub(crate) fn rewrite_extern_crate( context: &RewriteContext<'_>, item: &ast::Item, + attrs_shape: Shape, ) -> Option { assert!(is_extern_crate(item)); let new_str = context.snippet(item.span); - Some(if contains_comment(new_str) { + let item_str = if contains_comment(new_str) { new_str.to_owned() } else { let no_whitespace = &new_str.split_whitespace().collect::>().join(" "); String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";")) - }) + }; + rewrite_attrs(context, item, &item_str, attrs_shape) } /// Returns `true` for `mod foo;`, false for `mod foo { .. }`. diff --git a/src/reorder.rs b/src/reorder.rs index ee80000b1fa..a246772f648 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -11,12 +11,11 @@ use std::cmp::{Ord, Ordering}; use syntax::{ast, attr, source_map::Span, symbol::sym}; use crate::attr::filter_inline_attrs; -use crate::comment::combine_strs_with_missing_comments; use crate::config::Config; use crate::imports::{merge_use_trees, UseTree}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; -use crate::rewrite::{Rewrite, RewriteContext}; +use crate::rewrite::RewriteContext; use crate::shape::Shape; use crate::source_map::LineRangeUtils; use crate::spanned::Spanned; @@ -70,37 +69,11 @@ fn rewrite_reorderable_item( item: &ast::Item, shape: Shape, ) -> Option { - let attrs = filter_inline_attrs(&item.attrs, item.span()); - let attrs_str = attrs.rewrite(context, shape)?; - - let missed_span = if attrs.is_empty() { - mk_sp(item.span.lo(), item.span.lo()) - } else { - mk_sp(attrs.last().unwrap().span.hi(), item.span.lo()) - }; - - let item_str = match item.node { - ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item)?, - ast::ItemKind::Mod(..) => rewrite_mod(context, item), - _ => return None, - }; - - let allow_extend = if attrs.len() == 1 { - let line_len = attrs_str.len() + 1 + item_str.len(); - !attrs.first().unwrap().is_sugared_doc - && context.config.inline_attribute_width() >= line_len - } else { - false - }; - - combine_strs_with_missing_comments( - context, - &attrs_str, - &item_str, - missed_span, - shape, - allow_extend, - ) + match item.node { + ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape), + ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape), + _ => None, + } } /// Rewrite a list of items with reordering. Every item in `items` must have diff --git a/src/visitor.rs b/src/visitor.rs index db571abbeb0..0560cd2ff09 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -315,8 +315,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { .append(&mut get_skip_macro_names(&attrs)); let should_visit_node_again = match item.node { - // For use items, skip rewriting attributes. Just check for a skip attribute. - ast::ItemKind::Use(..) => { + // For use/extern crate items, skip rewriting attributes but check for a skip attribute. + ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => { if contains_skip(attrs) { self.push_skipped_with_span(attrs.as_slice(), item.span(), item.span()); false @@ -381,8 +381,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(item.span, rw); } ast::ItemKind::ExternCrate(_) => { - let rw = rewrite_extern_crate(&self.get_context(), item); - self.push_rewrite(item.span, rw); + let rw = rewrite_extern_crate(&self.get_context(), item, self.shape()); + let span = if attrs.is_empty() { + item.span + } else { + mk_sp(attrs[0].span.lo(), item.span.hi()) + }; + self.push_rewrite(span, rw); } ast::ItemKind::Struct(..) | ast::ItemKind::Union(..) => { self.visit_struct(&StructParts::from_item(item)); diff --git a/tests/source/issue-3585/extern_crate.rs b/tests/source/issue-3585/extern_crate.rs new file mode 100644 index 00000000000..6716983ba0f --- /dev/null +++ b/tests/source/issue-3585/extern_crate.rs @@ -0,0 +1,12 @@ +// rustfmt-inline_attribute_width: 100 + +#[macro_use] +extern crate static_assertions; + +#[cfg(unix)] +extern crate static_assertions; + +// a comment before the attribute +#[macro_use] +// some comment after +extern crate static_assertions; diff --git a/tests/source/issue-3585/reorder_imports_disabled.rs b/tests/source/issue-3585/reorder_imports_disabled.rs new file mode 100644 index 00000000000..45b1bb9fdd9 --- /dev/null +++ b/tests/source/issue-3585/reorder_imports_disabled.rs @@ -0,0 +1,12 @@ +// rustfmt-inline_attribute_width: 100 +// rustfmt-reorder_imports: false + +#[cfg(unix)] +extern crate crateb; +#[cfg(unix)] +extern crate cratea; + +#[cfg(unix)] +use crateb; +#[cfg(unix)] +use cratea; diff --git a/tests/source/issue-3585/reorder_imports_enabled.rs b/tests/source/issue-3585/reorder_imports_enabled.rs new file mode 100644 index 00000000000..9f433e5ca21 --- /dev/null +++ b/tests/source/issue-3585/reorder_imports_enabled.rs @@ -0,0 +1,12 @@ +// rustfmt-inline_attribute_width: 100 +// rustfmt-reorder_imports: true + +#[cfg(unix)] +extern crate crateb; +#[cfg(unix)] +extern crate cratea; + +#[cfg(unix)] +use crateb; +#[cfg(unix)] +use cratea; diff --git a/tests/source/issue-3585/use.rs b/tests/source/issue-3585/use.rs new file mode 100644 index 00000000000..e71ba9008ce --- /dev/null +++ b/tests/source/issue-3585/use.rs @@ -0,0 +1,7 @@ +// rustfmt-inline_attribute_width: 100 + +#[macro_use] +use static_assertions; + +#[cfg(unix)] +use static_assertions; diff --git a/tests/target/issue-3585/extern_crate.rs b/tests/target/issue-3585/extern_crate.rs new file mode 100644 index 00000000000..dc7c9e0246b --- /dev/null +++ b/tests/target/issue-3585/extern_crate.rs @@ -0,0 +1,10 @@ +// rustfmt-inline_attribute_width: 100 + +#[macro_use] extern crate static_assertions; + +#[cfg(unix)] extern crate static_assertions; + +// a comment before the attribute +#[macro_use] +// some comment after +extern crate static_assertions; diff --git a/tests/target/issue-3585/reorder_imports_disabled.rs b/tests/target/issue-3585/reorder_imports_disabled.rs new file mode 100644 index 00000000000..f9637729b7e --- /dev/null +++ b/tests/target/issue-3585/reorder_imports_disabled.rs @@ -0,0 +1,8 @@ +// rustfmt-inline_attribute_width: 100 +// rustfmt-reorder_imports: false + +#[cfg(unix)] extern crate crateb; +#[cfg(unix)] extern crate cratea; + +#[cfg(unix)] use crateb; +#[cfg(unix)] use cratea; diff --git a/tests/target/issue-3585/reorder_imports_enabled.rs b/tests/target/issue-3585/reorder_imports_enabled.rs new file mode 100644 index 00000000000..d040d0ed341 --- /dev/null +++ b/tests/target/issue-3585/reorder_imports_enabled.rs @@ -0,0 +1,8 @@ +// rustfmt-inline_attribute_width: 100 +// rustfmt-reorder_imports: true + +#[cfg(unix)] extern crate cratea; +#[cfg(unix)] extern crate crateb; + +#[cfg(unix)] use cratea; +#[cfg(unix)] use crateb; diff --git a/tests/target/issue-3585/use.rs b/tests/target/issue-3585/use.rs new file mode 100644 index 00000000000..c76a9eaacc8 --- /dev/null +++ b/tests/target/issue-3585/use.rs @@ -0,0 +1,5 @@ +// rustfmt-inline_attribute_width: 100 + +#[macro_use] use static_assertions; + +#[cfg(unix)] use static_assertions; -- cgit 1.4.1-3-g733a5 From 5607178d0a6d1136faf2bad63cc3cc2448752f1b Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Thu, 6 Jun 2019 13:06:40 +0900 Subject: fix the bug add unwanted code to impl (#3601) (#3602) --- src/items.rs | 10 +++++----- tests/target/issue-3601.rs | 11 +++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 tests/target/issue-3601.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 4ae3f383e74..14d386047f0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -700,8 +700,8 @@ pub(crate) fn format_impl( option.allow_single_line(); } - let misssing_span = mk_sp(self_ty.span.hi(), item.span.hi()); - let where_span_end = context.snippet_provider.opt_span_before(misssing_span, "{"); + let missing_span = mk_sp(self_ty.span.hi(), item.span.hi()); + let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{"); let where_clause_str = rewrite_where_clause( context, &generics.where_clause, @@ -765,15 +765,15 @@ pub(crate) fn format_impl( } result.push('{'); - - let snippet = context.snippet(item.span); + // this is an impl body snippet(impl SampleImple { /* here */ }) + let snippet = context.snippet(mk_sp(item.span.hi(), self_ty.span.hi())); let open_pos = snippet.find_uncommented("{")? + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); let item_indent = offset.block_only().block_indent(context.config); visitor.block_indent = item_indent; - visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); + visitor.last_pos = self_ty.span.hi() + BytePos(open_pos as u32); visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); visitor.visit_impl_items(items); diff --git a/tests/target/issue-3601.rs b/tests/target/issue-3601.rs new file mode 100644 index 00000000000..c86ca24e707 --- /dev/null +++ b/tests/target/issue-3601.rs @@ -0,0 +1,11 @@ +#![feature(const_generics)] + +trait A { + fn foo(&self); +} + +pub struct B([usize; N]); + +impl A for B<{ N }> { + fn foo(&self) {} +} -- cgit 1.4.1-3-g733a5 From dae63e98ce0c5d4f40c4c350e58e813057e88213 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Jun 2019 14:55:41 +0900 Subject: Ignore sub-modules when skip-children is used --- src/formatting.rs | 2 +- src/modules.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 47d885ef2e3..06bffd4dad8 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -105,7 +105,7 @@ fn format_project( let files = modules::ModResolver::new( context.parse_session.source_map(), directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(false)), - input_is_stdin, + !(input_is_stdin || config.skip_children()), ) .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; diff --git a/src/modules.rs b/src/modules.rs index 3d009b2098b..f8496b9566a 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -17,7 +17,7 @@ pub(crate) struct ModResolver<'a, 'b> { source_map: &'b source_map::SourceMap, directory: Directory, file_map: FileModMap<'a>, - is_input_stdin: bool, + recursive: bool, } #[derive(Clone)] @@ -31,7 +31,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { pub(crate) fn new( source_map: &'b source_map::SourceMap, directory_ownership: DirectoryOwnership, - is_input_stdin: bool, + recursive: bool, ) -> Self { ModResolver { directory: Directory { @@ -40,7 +40,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { }, file_map: BTreeMap::new(), source_map, - is_input_stdin, + recursive, } } @@ -56,7 +56,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { }; // Skip visiting sub modules when the input is from stdin. - if !self.is_input_stdin { + if self.recursive { self.visit_mod(&krate.module)?; } -- cgit 1.4.1-3-g733a5 From e71bffb0080e53a11078e6279f0bb1e470c452e0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 8 Jun 2019 18:47:18 +0900 Subject: Format modules defined inside cfg_if macro calls (#3600) --- src/formatting.rs | 6 +- src/modules.rs | 188 +++++++++--- src/modules/visitor.rs | 105 +++++++ src/test/mod.rs | 14 +- tests/source/cfg_if/detect/arch/aarch64.rs | 106 +++++++ tests/source/cfg_if/detect/arch/arm.rs | 39 +++ tests/source/cfg_if/detect/arch/mips.rs | 29 ++ tests/source/cfg_if/detect/arch/mips64.rs | 29 ++ tests/source/cfg_if/detect/arch/powerpc.rs | 42 +++ tests/source/cfg_if/detect/arch/powerpc64.rs | 42 +++ tests/source/cfg_if/detect/arch/x86.rs | 348 +++++++++++++++++++++ tests/source/cfg_if/detect/bit.rs | 9 + tests/source/cfg_if/detect/cache.rs | 164 ++++++++++ tests/source/cfg_if/detect/error_macros.rs | 150 +++++++++ tests/source/cfg_if/detect/mod.rs | 85 +++++ tests/source/cfg_if/detect/os/aarch64.rs | 79 +++++ tests/source/cfg_if/detect/os/freebsd/aarch64.rs | 28 ++ tests/source/cfg_if/detect/os/freebsd/arm.rs | 27 ++ tests/source/cfg_if/detect/os/freebsd/auxvec.rs | 86 ++++++ tests/source/cfg_if/detect/os/freebsd/mod.rs | 22 ++ tests/source/cfg_if/detect/os/freebsd/powerpc.rs | 27 ++ tests/source/cfg_if/detect/os/linux/aarch64.rs | 157 ++++++++++ tests/source/cfg_if/detect/os/linux/arm.rs | 49 +++ tests/source/cfg_if/detect/os/linux/auxvec.rs | 307 +++++++++++++++++++ tests/source/cfg_if/detect/os/linux/cpuinfo.rs | 301 ++++++++++++++++++ tests/source/cfg_if/detect/os/linux/mips.rs | 31 ++ tests/source/cfg_if/detect/os/linux/mod.rs | 28 ++ tests/source/cfg_if/detect/os/linux/powerpc.rs | 41 +++ tests/source/cfg_if/detect/os/other.rs | 9 + tests/source/cfg_if/detect/os/x86.rs | 375 +++++++++++++++++++++++ tests/source/cfg_if/lib.rs | 49 +++ tests/source/cfg_if/mod.rs | 5 + tests/target/cfg_if/detect/arch/aarch64.rs | 98 ++++++ tests/target/cfg_if/detect/arch/arm.rs | 47 +++ tests/target/cfg_if/detect/arch/mips.rs | 30 ++ tests/target/cfg_if/detect/arch/mips64.rs | 30 ++ tests/target/cfg_if/detect/arch/powerpc.rs | 42 +++ tests/target/cfg_if/detect/arch/powerpc64.rs | 42 +++ tests/target/cfg_if/detect/arch/x86.rs | 333 ++++++++++++++++++++ tests/target/cfg_if/detect/bit.rs | 9 + tests/target/cfg_if/detect/cache.rs | 164 ++++++++++ tests/target/cfg_if/detect/error_macros.rs | 150 +++++++++ tests/target/cfg_if/detect/mod.rs | 85 +++++ tests/target/cfg_if/detect/os/aarch64.rs | 88 ++++++ tests/target/cfg_if/detect/os/freebsd/aarch64.rs | 28 ++ tests/target/cfg_if/detect/os/freebsd/arm.rs | 27 ++ tests/target/cfg_if/detect/os/freebsd/auxvec.rs | 94 ++++++ tests/target/cfg_if/detect/os/freebsd/mod.rs | 22 ++ tests/target/cfg_if/detect/os/freebsd/powerpc.rs | 27 ++ tests/target/cfg_if/detect/os/linux/aarch64.rs | 160 ++++++++++ tests/target/cfg_if/detect/os/linux/arm.rs | 52 ++++ tests/target/cfg_if/detect/os/linux/auxvec.rs | 304 ++++++++++++++++++ tests/target/cfg_if/detect/os/linux/cpuinfo.rs | 300 ++++++++++++++++++ tests/target/cfg_if/detect/os/linux/mips.rs | 31 ++ tests/target/cfg_if/detect/os/linux/mod.rs | 28 ++ tests/target/cfg_if/detect/os/linux/powerpc.rs | 41 +++ tests/target/cfg_if/detect/os/other.rs | 9 + tests/target/cfg_if/detect/os/x86.rs | 367 ++++++++++++++++++++++ tests/target/cfg_if/lib.rs | 49 +++ tests/target/cfg_if/mod.rs | 5 + 60 files changed, 5589 insertions(+), 50 deletions(-) create mode 100644 src/modules/visitor.rs create mode 100644 tests/source/cfg_if/detect/arch/aarch64.rs create mode 100644 tests/source/cfg_if/detect/arch/arm.rs create mode 100644 tests/source/cfg_if/detect/arch/mips.rs create mode 100644 tests/source/cfg_if/detect/arch/mips64.rs create mode 100644 tests/source/cfg_if/detect/arch/powerpc.rs create mode 100644 tests/source/cfg_if/detect/arch/powerpc64.rs create mode 100644 tests/source/cfg_if/detect/arch/x86.rs create mode 100644 tests/source/cfg_if/detect/bit.rs create mode 100644 tests/source/cfg_if/detect/cache.rs create mode 100644 tests/source/cfg_if/detect/error_macros.rs create mode 100644 tests/source/cfg_if/detect/mod.rs create mode 100644 tests/source/cfg_if/detect/os/aarch64.rs create mode 100644 tests/source/cfg_if/detect/os/freebsd/aarch64.rs create mode 100644 tests/source/cfg_if/detect/os/freebsd/arm.rs create mode 100644 tests/source/cfg_if/detect/os/freebsd/auxvec.rs create mode 100644 tests/source/cfg_if/detect/os/freebsd/mod.rs create mode 100644 tests/source/cfg_if/detect/os/freebsd/powerpc.rs create mode 100644 tests/source/cfg_if/detect/os/linux/aarch64.rs create mode 100644 tests/source/cfg_if/detect/os/linux/arm.rs create mode 100644 tests/source/cfg_if/detect/os/linux/auxvec.rs create mode 100644 tests/source/cfg_if/detect/os/linux/cpuinfo.rs create mode 100644 tests/source/cfg_if/detect/os/linux/mips.rs create mode 100644 tests/source/cfg_if/detect/os/linux/mod.rs create mode 100644 tests/source/cfg_if/detect/os/linux/powerpc.rs create mode 100644 tests/source/cfg_if/detect/os/other.rs create mode 100644 tests/source/cfg_if/detect/os/x86.rs create mode 100644 tests/source/cfg_if/lib.rs create mode 100644 tests/source/cfg_if/mod.rs create mode 100644 tests/target/cfg_if/detect/arch/aarch64.rs create mode 100644 tests/target/cfg_if/detect/arch/arm.rs create mode 100644 tests/target/cfg_if/detect/arch/mips.rs create mode 100644 tests/target/cfg_if/detect/arch/mips64.rs create mode 100644 tests/target/cfg_if/detect/arch/powerpc.rs create mode 100644 tests/target/cfg_if/detect/arch/powerpc64.rs create mode 100644 tests/target/cfg_if/detect/arch/x86.rs create mode 100644 tests/target/cfg_if/detect/bit.rs create mode 100644 tests/target/cfg_if/detect/cache.rs create mode 100644 tests/target/cfg_if/detect/error_macros.rs create mode 100644 tests/target/cfg_if/detect/mod.rs create mode 100644 tests/target/cfg_if/detect/os/aarch64.rs create mode 100644 tests/target/cfg_if/detect/os/freebsd/aarch64.rs create mode 100644 tests/target/cfg_if/detect/os/freebsd/arm.rs create mode 100644 tests/target/cfg_if/detect/os/freebsd/auxvec.rs create mode 100644 tests/target/cfg_if/detect/os/freebsd/mod.rs create mode 100644 tests/target/cfg_if/detect/os/freebsd/powerpc.rs create mode 100644 tests/target/cfg_if/detect/os/linux/aarch64.rs create mode 100644 tests/target/cfg_if/detect/os/linux/arm.rs create mode 100644 tests/target/cfg_if/detect/os/linux/auxvec.rs create mode 100644 tests/target/cfg_if/detect/os/linux/cpuinfo.rs create mode 100644 tests/target/cfg_if/detect/os/linux/mips.rs create mode 100644 tests/target/cfg_if/detect/os/linux/mod.rs create mode 100644 tests/target/cfg_if/detect/os/linux/powerpc.rs create mode 100644 tests/target/cfg_if/detect/os/other.rs create mode 100644 tests/target/cfg_if/detect/os/x86.rs create mode 100644 tests/target/cfg_if/lib.rs create mode 100644 tests/target/cfg_if/mod.rs (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 4787b15e94a..0e98bca9896 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -99,8 +99,8 @@ fn format_project( let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( - context.parse_session.source_map(), - directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(false)), + &context.parse_session, + directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(true)), !(input_is_stdin || config.skip_children()), ) .visit_crate(&krate) @@ -112,7 +112,7 @@ fn format_project( } should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); let is_root = path == main_file; - context.format_file(path, module, is_root)?; + context.format_file(path, &module, is_root)?; } timer = timer.done_formatting(); diff --git a/src/modules.rs b/src/modules.rs index 9da76de19ff..e54bdb87570 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -1,23 +1,27 @@ +use std::borrow::Cow; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::parse::{parser, DirectoryOwnership}; +use syntax::parse::{parser, DirectoryOwnership, ParseSess}; use syntax::source_map; use syntax::symbol::sym; +use syntax::visit::Visitor; use syntax_pos::symbol::Symbol; use crate::config::FileName; use crate::items::is_mod_decl; use crate::utils::contains_skip; -type FileModMap<'a> = BTreeMap; +mod visitor; + +type FileModMap<'ast> = BTreeMap, String)>; /// Maps each module to the corresponding file. -pub(crate) struct ModResolver<'a, 'b> { - source_map: &'b source_map::SourceMap, +pub(crate) struct ModResolver<'ast, 'sess> { + parse_sess: &'sess ParseSess, directory: Directory, - file_map: FileModMap<'a>, + file_map: FileModMap<'ast>, recursive: bool, } @@ -27,10 +31,28 @@ struct Directory { ownership: DirectoryOwnership, } -impl<'a, 'b> ModResolver<'a, 'b> { +impl<'a> Directory { + fn to_syntax_directory(&'a self) -> syntax::parse::Directory<'a> { + syntax::parse::Directory { + path: Cow::Borrowed(&self.path), + ownership: self.ownership.clone(), + } + } +} + +enum SubModKind { + /// `mod foo;` + External(PathBuf, DirectoryOwnership), + /// `#[path = "..."] mod foo {}` + InternalWithPath(PathBuf), + /// `mod foo {}` + Internal, +} + +impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Creates a new `ModResolver`. pub(crate) fn new( - source_map: &'b source_map::SourceMap, + parse_sess: &'sess ParseSess, directory_ownership: DirectoryOwnership, recursive: bool, ) -> Self { @@ -40,14 +62,17 @@ impl<'a, 'b> ModResolver<'a, 'b> { ownership: directory_ownership, }, file_map: BTreeMap::new(), - source_map, + parse_sess, recursive, } } /// Creates a map that maps a file name to the module in AST. - pub(crate) fn visit_crate(mut self, krate: &'a ast::Crate) -> Result, String> { - let root_filename = self.source_map.span_to_filename(krate.span); + pub(crate) fn visit_crate( + mut self, + krate: &'ast ast::Crate, + ) -> Result, String> { + let root_filename = self.parse_sess.source_map().span_to_filename(krate.span); self.directory.path = match root_filename { source_map::FileName::Real(ref path) => path .parent() @@ -58,54 +83,125 @@ impl<'a, 'b> ModResolver<'a, 'b> { // Skip visiting sub modules when the input is from stdin. if self.recursive { - self.visit_mod(&krate.module)?; + self.visit_mod_from_ast(&krate.module)?; } - self.file_map - .insert(root_filename.into(), (&krate.module, String::new())); + self.file_map.insert( + root_filename.into(), + (Cow::Borrowed(&krate.module), String::new()), + ); Ok(self.file_map) } - fn visit_mod(&mut self, module: &'a ast::Mod) -> Result<(), String> { + /// Visit macro calls and look for module declarations. Currently only supports `cfg_if` macro. + fn visit_mac(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { + let mut visitor = + visitor::CfgIfVisitor::new(self.parse_sess, self.directory.to_syntax_directory()); + visitor.visit_item(&item); + for module_item in visitor.mods() { + if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.node { + self.visit_mod_from_mac_inner(&item, Cow::Owned(sub_mod.clone()))?; + } + } + Ok(()) + } + + /// Visit modules defined inside macro calls. + fn visit_mod_from_macro(&mut self, module: Cow<'ast, ast::Mod>) -> Result<(), String> { for item in &module.items { + if let ast::ItemKind::Mac(..) = item.node { + self.visit_mac(Cow::Owned(item.clone().into_inner()))?; + } + if let ast::ItemKind::Mod(ref sub_mod) = item.node { - if contains_skip(&item.attrs) { - continue; - } + self.visit_mod_from_mac_inner(item, Cow::Owned(sub_mod.clone()))?; + } + } + Ok(()) + } - let old_direcotry = self.directory.clone(); - if is_mod_decl(item) { - // mod foo; - // Look for an extern file. - let (mod_path, directory_ownership) = - self.find_external_module(item.ident, &item.attrs)?; - self.file_map.insert( - FileName::Real(mod_path.clone()), - (sub_mod, item.ident.as_str().get().to_owned()), - ); - self.directory = Directory { - path: mod_path.parent().unwrap().to_path_buf(), - ownership: directory_ownership, - } - } else { - // An internal module (`mod foo { /* ... */ }`); - if let Some(path) = find_path_value(&item.attrs) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - self.directory = Directory { - path: Path::new(&path.as_str()).to_path_buf(), - ownership: DirectoryOwnership::Owned { relative: None }, - }; - } else { - self.push_inline_mod_directory(item.ident, &item.attrs); - } - } - self.visit_mod(sub_mod)?; - self.directory = old_direcotry; + fn visit_mod_from_mac_inner( + &mut self, + item: &'c ast::Item, + sub_mod: Cow<'ast, ast::Mod>, + ) -> Result<(), String> { + let old_directory = self.directory.clone(); + self.visit_sub_mod(item, &sub_mod)?; + self.visit_mod_from_macro(sub_mod)?; + self.directory = old_directory; + Ok(()) + } + + /// Visit modules from AST. + fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), String> { + for item in &module.items { + if let ast::ItemKind::Mac(..) = item.node { + self.visit_mac(Cow::Borrowed(item))?; + } + + if let ast::ItemKind::Mod(ref sub_mod) = item.node { + let old_directory = self.directory.clone(); + self.visit_sub_mod(item, &Cow::Borrowed(sub_mod))?; + self.visit_mod_from_ast(sub_mod)?; + self.directory = old_directory; + } + } + Ok(()) + } + + fn visit_sub_mod( + &mut self, + item: &'c ast::Item, + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Result<(), String> { + match self.peek_sub_mod(item)? { + Some(SubModKind::External(mod_path, directory_ownership)) => { + self.file_map.insert( + FileName::Real(mod_path.clone()), + (sub_mod.clone(), item.ident.name.as_str().get().to_owned()), + ); + self.directory = Directory { + path: mod_path.parent().unwrap().to_path_buf(), + ownership: directory_ownership, + }; + } + Some(SubModKind::InternalWithPath(mod_path)) => { + // All `#[path]` files are treated as though they are a `mod.rs` file. + self.directory = Directory { + path: mod_path, + ownership: DirectoryOwnership::Owned { relative: None }, + }; } + Some(SubModKind::Internal) => self.push_inline_mod_directory(item.ident, &item.attrs), + None => (), // rustfmt::skip } Ok(()) } + /// Inspect the given sub-module which we are about to visit and returns its kind. + fn peek_sub_mod(&self, item: &'c ast::Item) -> Result, String> { + if contains_skip(&item.attrs) { + return Ok(None); + } + + if is_mod_decl(item) { + // mod foo; + // Look for an extern file. + let (mod_path, directory_ownership) = + self.find_external_module(item.ident, &item.attrs)?; + Ok(Some(SubModKind::External(mod_path, directory_ownership))) + } else { + // An internal module (`mod foo { /* ... */ }`); + if let Some(path) = find_path_value(&item.attrs) { + let path = Path::new(&path.as_str()).to_path_buf(); + Ok(Some(SubModKind::InternalWithPath(path))) + } else { + Ok(Some(SubModKind::Internal)) + } + } + } + + /// Find a file path in the filesystem which corresponds to the given module. fn find_external_module( &self, mod_name: ast::Ident, @@ -123,7 +219,7 @@ impl<'a, 'b> ModResolver<'a, 'b> { mod_name, relative, &self.directory.path, - self.source_map, + self.parse_sess.source_map(), ) .result { diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs new file mode 100644 index 00000000000..1086a1a026c --- /dev/null +++ b/src/modules/visitor.rs @@ -0,0 +1,105 @@ +use syntax::ast; +use syntax::parse::token::{DelimToken, Token}; +use syntax::parse::{stream_to_parser_with_base_dir, Directory, ParseSess}; +use syntax::symbol::kw; +use syntax::visit::Visitor; +use syntax_pos::Symbol; + +pub(crate) struct ModItem { + pub(crate) item: ast::Item, +} + +/// Traverse `cfg_if!` macro and fetch modules. +pub(crate) struct CfgIfVisitor<'a> { + parse_sess: &'a ParseSess, + mods: Vec, + base_dir: Directory<'a>, +} + +impl<'a> CfgIfVisitor<'a> { + pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: Directory<'a>) -> CfgIfVisitor<'a> { + CfgIfVisitor { + mods: vec![], + parse_sess, + base_dir, + } + } + + pub(crate) fn mods(self) -> Vec { + self.mods + } +} + +impl<'a, 'ast: 'a> Visitor<'ast> for CfgIfVisitor<'a> { + fn visit_mac(&mut self, mac: &'ast ast::Mac) { + match self.visit_mac_inner(mac) { + Ok(()) => (), + Err(e) => debug!("{}", e), + } + } +} + +impl<'a, 'ast: 'a> CfgIfVisitor<'a> { + fn visit_mac_inner(&mut self, mac: &'ast ast::Mac) -> Result<(), &'static str> { + if mac.node.path != Symbol::intern("cfg_if") { + return Err("Expected cfg_if"); + } + + let mut parser = stream_to_parser_with_base_dir( + self.parse_sess, + mac.node.tts.clone(), + self.base_dir.clone(), + ); + parser.cfg_mods = false; + let mut process_if_cfg = true; + + while parser.token != Token::Eof { + if process_if_cfg { + if !parser.eat_keyword(kw::If) { + return Err("Expected `if`"); + } + parser + .parse_attribute(false) + .map_err(|_| "Failed to parse attributes")?; + } + + if !parser.eat(&Token::OpenDelim(DelimToken::Brace)) { + return Err("Expected an opening brace"); + } + + while parser.token != Token::CloseDelim(DelimToken::Brace) && parser.token != Token::Eof + { + let item = match parser.parse_item() { + Ok(Some(item_ptr)) => item_ptr.into_inner(), + Ok(None) => continue, + Err(mut err) => { + err.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + return Err( + "Expected item inside cfg_if block, but failed to parse it as an item", + ); + } + }; + if let ast::ItemKind::Mod(..) = item.node { + self.mods.push(ModItem { item }); + } + } + + if !parser.eat(&Token::CloseDelim(DelimToken::Brace)) { + return Err("Expected a closing brace"); + } + + if parser.eat(&Token::Eof) { + break; + } + + if !parser.eat_keyword(kw::Else) { + return Err("Expected `else`"); + } + + process_if_cfg = parser.token.is_keyword(kw::If); + } + + Ok(()) + } +} diff --git a/src/test/mod.rs b/src/test/mod.rs index 68fd90a01cf..c68b33b844f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -25,6 +25,9 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ // so we do not want to test this file directly. "configs/skip_children/foo/mod.rs", "issue-3434/no_entry.rs", + // These files and directory are a part of modules defined inside `cfg_if!`. + "cfg_if/mod.rs", + "cfg_if/detect", ]; struct TestSetting { @@ -53,10 +56,19 @@ where .expect("Failed to join a test thread") } +fn is_subpath

(path: &Path, subpath: &P) -> bool +where + P: AsRef, +{ + (0..path.components().count()) + .map(|i| path.components().take(i)) + .any(|c| c.zip(subpath.as_ref().components()).all(|(a, b)| a == b)) +} + fn is_file_skip(path: &Path) -> bool { SKIP_FILE_WHITE_LIST .iter() - .any(|file_path| path.ends_with(file_path)) + .any(|file_path| is_subpath(path, file_path)) } // Returns a `Vec` containing `PathBuf`s of files with an `rs` extension in the diff --git a/tests/source/cfg_if/detect/arch/aarch64.rs b/tests/source/cfg_if/detect/arch/aarch64.rs new file mode 100644 index 00000000000..ebae2bd2854 --- /dev/null +++ b/tests/source/cfg_if/detect/arch/aarch64.rs @@ -0,0 +1,106 @@ +//! Aarch64 run-time features. + +/// Checks if `aarch64` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_aarch64_feature_detected { + ("neon") => { + // FIXME: this should be removed once we rename Aarch64 neon to asimd + cfg!(target_feature = "neon") || + $crate::detect::check_for($crate::detect::Feature::asimd) + }; + ("asimd") => { + cfg!(target_feature = "neon") || + $crate::detect::check_for($crate::detect::Feature::asimd) + }; + ("pmull") => { + cfg!(target_feature = "pmull") || + $crate::detect::check_for($crate::detect::Feature::pmull) + }; + ("fp") => { + cfg!(target_feature = "fp") || + $crate::detect::check_for($crate::detect::Feature::fp) + }; + ("fp16") => { + cfg!(target_feature = "fp16") || + $crate::detect::check_for($crate::detect::Feature::fp16) + }; + ("sve") => { + cfg!(target_feature = "sve") || + $crate::detect::check_for($crate::detect::Feature::sve) + }; + ("crc") => { + cfg!(target_feature = "crc") || + $crate::detect::check_for($crate::detect::Feature::crc) + }; + ("crypto") => { + cfg!(target_feature = "crypto") || + $crate::detect::check_for($crate::detect::Feature::crypto) + }; + ("lse") => { + cfg!(target_feature = "lse") || + $crate::detect::check_for($crate::detect::Feature::lse) + }; + ("rdm") => { + cfg!(target_feature = "rdm") || + $crate::detect::check_for($crate::detect::Feature::rdm) + }; + ("rcpc") => { + cfg!(target_feature = "rcpc") || + $crate::detect::check_for($crate::detect::Feature::rcpc) + }; + ("dotprod") => { + cfg!(target_feature = "dotprod") || + $crate::detect::check_for($crate::detect::Feature::dotprod) + }; + ("ras") => { + compile_error!("\"ras\" feature cannot be detected at run-time") + }; + ("v8.1a") => { + compile_error!("\"v8.1a\" feature cannot be detected at run-time") + }; + ("v8.2a") => { + compile_error!("\"v8.2a\" feature cannot be detected at run-time") + }; + ("v8.3a") => { + compile_error!("\"v8.3a\" feature cannot be detected at run-time") + }; + ($t:tt,) => { + is_aarch64_feature_detected!($t); + }; + ($t:tt) => { compile_error!(concat!("unknown aarch64 target feature: ", $t)) }; +} + +/// ARM Aarch64 CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// ARM Advanced SIMD (ASIMD) + asimd, + /// Polynomial Multiply + pmull, + /// Floating point support + fp, + /// Half-float support. + fp16, + /// Scalable Vector Extension (SVE) + sve, + /// CRC32 (Cyclic Redundancy Check) + crc, + /// Crypto: AES + PMULL + SHA1 + SHA2 + crypto, + /// Atomics (Large System Extension) + lse, + /// Rounding Double Multiply (ASIMDRDM) + rdm, + /// Release consistent Processor consistent (RcPc) + rcpc, + /// Vector Dot-Product (ASIMDDP) + dotprod, +} diff --git a/tests/source/cfg_if/detect/arch/arm.rs b/tests/source/cfg_if/detect/arch/arm.rs new file mode 100644 index 00000000000..b2626bf2923 --- /dev/null +++ b/tests/source/cfg_if/detect/arch/arm.rs @@ -0,0 +1,39 @@ +//! Run-time feature detection on ARM Aarch32. + +/// Checks if `arm` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_arm_feature_detected { + ("neon") => { + cfg!(target_feature = "neon") || + $crate::detect::check_for($crate::detect::Feature::neon) + }; + ("pmull") => { + cfg!(target_feature = "pmull") || + $crate::detect::check_for($crate::detect::Feature::pmull) + }; + ("v7") => { compile_error!("\"v7\" feature cannot be detected at run-time") }; + ("vfp2") => { compile_error!("\"vfp2\" feature cannot be detected at run-time") }; + ("vfp3") => { compile_error!("\"vfp3\" feature cannot be detected at run-time") }; + ("vfp4") => { compile_error!("\"vfp4\" feature cannot be detected at run-time") }; + ($t:tt,) => { + is_arm_feature_detected!($t); + }; + ($t:tt) => { compile_error!(concat!("unknown arm target feature: ", $t)) }; +} + +/// ARM CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// ARM Advanced SIMD (NEON) - Aarch32 + neon, + /// Polynomial Multiply + pmull, +} diff --git a/tests/source/cfg_if/detect/arch/mips.rs b/tests/source/cfg_if/detect/arch/mips.rs new file mode 100644 index 00000000000..f4381b811cd --- /dev/null +++ b/tests/source/cfg_if/detect/arch/mips.rs @@ -0,0 +1,29 @@ +//! Run-time feature detection on MIPS. + +/// Checks if `mips` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_mips_feature_detected { + ("msa") => { + cfg!(target_feature = "msa") || + $crate::detect::check_for($crate::detect::Feature::msa) + }; + ($t:tt,) => { + is_mips_feature_detected!($t); + }; + ($t:tt) => { compile_error!(concat!("unknown mips target feature: ", $t)) }; +} + +/// MIPS CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// MIPS SIMD Architecture (MSA) + msa, +} diff --git a/tests/source/cfg_if/detect/arch/mips64.rs b/tests/source/cfg_if/detect/arch/mips64.rs new file mode 100644 index 00000000000..2663bc68ba9 --- /dev/null +++ b/tests/source/cfg_if/detect/arch/mips64.rs @@ -0,0 +1,29 @@ +//! Run-time feature detection on MIPS64. + +/// Checks if `mips64` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_mips64_feature_detected { + ("msa") => { + cfg!(target_feature = "msa") || + $crate::detect::check_for($crate::detect::Feature::msa) + }; + ($t:tt,) => { + is_mips64_feature_detected!($t); + }; + ($t:tt) => { compile_error!(concat!("unknown mips64 target feature: ", $t)) }; +} + +/// MIPS64 CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// MIPS SIMD Architecture (MSA) + msa, +} diff --git a/tests/source/cfg_if/detect/arch/powerpc.rs b/tests/source/cfg_if/detect/arch/powerpc.rs new file mode 100644 index 00000000000..a342dc1aacc --- /dev/null +++ b/tests/source/cfg_if/detect/arch/powerpc.rs @@ -0,0 +1,42 @@ +//! Run-time feature detection on PowerPC. + +/// Checks if `powerpc` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_powerpc_feature_detected { + ("altivec") => { + cfg!(target_feature = "altivec") || + $crate::detect::check_for($crate::detect::Feature::altivec) + }; + ("vsx") => { + cfg!(target_feature = "vsx") || + $crate::detect::check_for($crate::detect::Feature::vsx) + }; + ("power8") => { + cfg!(target_feature = "power8") || + $crate::detect::check_for($crate::detect::Feature::power8) + }; + ($t:tt,) => { + is_powerpc_feature_detected!($t); + }; + ($t:tt) => { compile_error!(concat!("unknown powerpc target feature: ", $t)) }; +} + + +/// PowerPC CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// Altivec + altivec, + /// VSX + vsx, + /// Power8 + power8, +} diff --git a/tests/source/cfg_if/detect/arch/powerpc64.rs b/tests/source/cfg_if/detect/arch/powerpc64.rs new file mode 100644 index 00000000000..2e82c569252 --- /dev/null +++ b/tests/source/cfg_if/detect/arch/powerpc64.rs @@ -0,0 +1,42 @@ +//! Run-time feature detection on PowerPC64. + +/// Checks if `powerpc64` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_powerpc64_feature_detected { + ("altivec") => { + cfg!(target_feature = "altivec") || + $crate::detect::check_for($crate::detect::Feature::altivec) + }; + ("vsx") => { + cfg!(target_feature = "vsx") || + $crate::detect::check_for($crate::detect::Feature::vsx) + }; + ("power8") => { + cfg!(target_feature = "power8") || + $crate::detect::check_for($crate::detect::Feature::power8) + }; + ($t:tt,) => { + is_powerpc64_feature_detected!($t); + }; + ($t:tt) => { compile_error!(concat!("unknown powerpc64 target feature: ", $t)) }; +} + + +/// PowerPC64 CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// Altivec + altivec, + /// VSX + vsx, + /// Power8 + power8, +} diff --git a/tests/source/cfg_if/detect/arch/x86.rs b/tests/source/cfg_if/detect/arch/x86.rs new file mode 100644 index 00000000000..50d5cfa87c4 --- /dev/null +++ b/tests/source/cfg_if/detect/arch/x86.rs @@ -0,0 +1,348 @@ +//! This module implements minimal run-time feature detection for x86. +//! +//! The features are detected using the `detect_features` function below. +//! This function uses the CPUID instruction to read the feature flags from the +//! CPU and encodes them in an `usize` where each bit position represents +//! whether a feature is available (bit is set) or unavaiable (bit is cleared). +//! +//! The enum `Feature` is used to map bit positions to feature names, and the +//! the `__crate::detect::check_for!` macro is used to map string literals (e.g., +//! "avx") to these bit positions (e.g., `Feature::avx`). +//! +//! The run-time feature detection is performed by the +//! `__crate::detect::check_for(Feature) -> bool` function. On its first call, +//! this functions queries the CPU for the available features and stores them +//! in a global `AtomicUsize` variable. The query is performed by just checking +//! whether the feature bit in this global variable is set or cleared. + +/// A macro to test at *runtime* whether a CPU feature is available on +/// x86/x86-64 platforms. +/// +/// This macro is provided in the standard library and will detect at runtime +/// whether the specified CPU feature is detected. This does **not** resolve at +/// compile time unless the specified feature is already enabled for the entire +/// crate. Runtime detection currently relies mostly on the `cpuid` instruction. +/// +/// This macro only takes one argument which is a string literal of the feature +/// being tested for. The feature names supported are the lowercase versions of +/// the ones defined by Intel in [their documentation][docs]. +/// +/// ## Supported arguments +/// +/// This macro supports the same names that `#[target_feature]` supports. Unlike +/// `#[target_feature]`, however, this macro does not support names separated +/// with a comma. Instead testing for multiple features must be done through +/// separate macro invocations for now. +/// +/// Supported arguments are: +/// +/// * `"aes"` +/// * `"pclmulqdq"` +/// * `"rdrand"` +/// * `"rdseed"` +/// * `"tsc"` +/// * `"mmx"` +/// * `"sse"` +/// * `"sse2"` +/// * `"sse3"` +/// * `"ssse3"` +/// * `"sse4.1"` +/// * `"sse4.2"` +/// * `"sse4a"` +/// * `"sha"` +/// * `"avx"` +/// * `"avx2"` +/// * `"avx512f"` +/// * `"avx512cd"` +/// * `"avx512er"` +/// * `"avx512pf"` +/// * `"avx512bw"` +/// * `"avx512dq"` +/// * `"avx512vl"` +/// * `"avx512ifma"` +/// * `"avx512vbmi"` +/// * `"avx512vpopcntdq"` +/// * `"f16c"` +/// * `"fma"` +/// * `"bmi1"` +/// * `"bmi2"` +/// * `"abm"` +/// * `"lzcnt"` +/// * `"tbm"` +/// * `"popcnt"` +/// * `"fxsr"` +/// * `"xsave"` +/// * `"xsaveopt"` +/// * `"xsaves"` +/// * `"xsavec"` +/// * `"adx"` +/// * `"rtm"` +/// +/// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide +#[macro_export] +#[stable(feature = "simd_x86", since = "1.27.0")] +#[allow_internal_unstable(stdsimd_internal,stdsimd)] +macro_rules! is_x86_feature_detected { + ("aes") => { + cfg!(target_feature = "aes") || $crate::detect::check_for( + $crate::detect::Feature::aes) }; + ("pclmulqdq") => { + cfg!(target_feature = "pclmulqdq") || $crate::detect::check_for( + $crate::detect::Feature::pclmulqdq) }; + ("rdrand") => { + cfg!(target_feature = "rdrand") || $crate::detect::check_for( + $crate::detect::Feature::rdrand) }; + ("rdseed") => { + cfg!(target_feature = "rdseed") || $crate::detect::check_for( + $crate::detect::Feature::rdseed) }; + ("tsc") => { + cfg!(target_feature = "tsc") || $crate::detect::check_for( + $crate::detect::Feature::tsc) }; + ("mmx") => { + cfg!(target_feature = "mmx") || $crate::detect::check_for( + $crate::detect::Feature::mmx) }; + ("sse") => { + cfg!(target_feature = "sse") || $crate::detect::check_for( + $crate::detect::Feature::sse) }; + ("sse2") => { + cfg!(target_feature = "sse2") || $crate::detect::check_for( + $crate::detect::Feature::sse2) + }; + ("sse3") => { + cfg!(target_feature = "sse3") || $crate::detect::check_for( + $crate::detect::Feature::sse3) + }; + ("ssse3") => { + cfg!(target_feature = "ssse3") || $crate::detect::check_for( + $crate::detect::Feature::ssse3) + }; + ("sse4.1") => { + cfg!(target_feature = "sse4.1") || $crate::detect::check_for( + $crate::detect::Feature::sse4_1) + }; + ("sse4.2") => { + cfg!(target_feature = "sse4.2") || $crate::detect::check_for( + $crate::detect::Feature::sse4_2) + }; + ("sse4a") => { + cfg!(target_feature = "sse4a") || $crate::detect::check_for( + $crate::detect::Feature::sse4a) + }; + ("sha") => { + cfg!(target_feature = "sha") || $crate::detect::check_for( + $crate::detect::Feature::sha) + }; + ("avx") => { + cfg!(target_feature = "avx") || $crate::detect::check_for( + $crate::detect::Feature::avx) + }; + ("avx2") => { + cfg!(target_feature = "avx2") || $crate::detect::check_for( + $crate::detect::Feature::avx2) + }; + ("avx512f") => { + cfg!(target_feature = "avx512f") || $crate::detect::check_for( + $crate::detect::Feature::avx512f) + }; + ("avx512cd") => { + cfg!(target_feature = "avx512cd") || $crate::detect::check_for( + $crate::detect::Feature::avx512cd) + }; + ("avx512er") => { + cfg!(target_feature = "avx512er") || $crate::detect::check_for( + $crate::detect::Feature::avx512er) + }; + ("avx512pf") => { + cfg!(target_feature = "avx512pf") || $crate::detect::check_for( + $crate::detect::Feature::avx512pf) + }; + ("avx512bw") => { + cfg!(target_feature = "avx512bw") || $crate::detect::check_for( + $crate::detect::Feature::avx512bw) + }; + ("avx512dq") => { + cfg!(target_feature = "avx512dq") || $crate::detect::check_for( + $crate::detect::Feature::avx512dq) + }; + ("avx512vl") => { + cfg!(target_Feature = "avx512vl") || $crate::detect::check_for( + $crate::detect::Feature::avx512vl) + }; + ("avx512ifma") => { + cfg!(target_feature = "avx512ifma") || $crate::detect::check_for( + $crate::detect::Feature::avx512_ifma) + }; + ("avx512vbmi") => { + cfg!(target_feature = "avx512vbmi") || $crate::detect::check_for( + $crate::detect::Feature::avx512_vbmi) + }; + ("avx512vpopcntdq") => { + cfg!(target_feature = "avx512vpopcntdq") || $crate::detect::check_for( + $crate::detect::Feature::avx512_vpopcntdq) + }; + ("f16c") => { + cfg!(target_feature = "f16c") || $crate::detect::check_for( + $crate::detect::Feature::f16c) + }; + ("fma") => { + cfg!(target_feature = "fma") || $crate::detect::check_for( + $crate::detect::Feature::fma) + }; + ("bmi1") => { + cfg!(target_feature = "bmi1") || $crate::detect::check_for( + $crate::detect::Feature::bmi) + }; + ("bmi2") => { + cfg!(target_feature = "bmi2") || $crate::detect::check_for( + $crate::detect::Feature::bmi2) + }; + ("abm") => { + cfg!(target_feature = "abm") || $crate::detect::check_for( + $crate::detect::Feature::abm) + }; + ("lzcnt") => { + cfg!(target_feature = "lzcnt") || $crate::detect::check_for( + $crate::detect::Feature::abm) + }; + ("tbm") => { + cfg!(target_feature = "tbm") || $crate::detect::check_for( + $crate::detect::Feature::tbm) + }; + ("popcnt") => { + cfg!(target_feature = "popcnt") || $crate::detect::check_for( + $crate::detect::Feature::popcnt) + }; + ("fxsr") => { + cfg!(target_feature = "fxsr") || $crate::detect::check_for( + $crate::detect::Feature::fxsr) + }; + ("xsave") => { + cfg!(target_feature = "xsave") || $crate::detect::check_for( + $crate::detect::Feature::xsave) + }; + ("xsaveopt") => { + cfg!(target_feature = "xsaveopt") || $crate::detect::check_for( + $crate::detect::Feature::xsaveopt) + }; + ("xsaves") => { + cfg!(target_feature = "xsaves") || $crate::detect::check_for( + $crate::detect::Feature::xsaves) + }; + ("xsavec") => { + cfg!(target_feature = "xsavec") || $crate::detect::check_for( + $crate::detect::Feature::xsavec) + }; + ("cmpxchg16b") => { + cfg!(target_feature = "cmpxchg16b") || $crate::detect::check_for( + $crate::detect::Feature::cmpxchg16b) + }; + ("adx") => { + cfg!(target_feature = "adx") || $crate::detect::check_for( + $crate::detect::Feature::adx) + }; + ("rtm") => { + cfg!(target_feature = "rtm") || $crate::detect::check_for( + $crate::detect::Feature::rtm) + }; + ($t:tt,) => { + is_x86_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown target feature: ", $t)) + }; +} + +/// X86 CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// This is an unstable implementation detail subject to change. +#[allow(non_camel_case_types)] +#[repr(u8)] +#[doc(hidden)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// AES (Advanced Encryption Standard New Instructions AES-NI) + aes, + /// CLMUL (Carry-less Multiplication) + pclmulqdq, + /// RDRAND + rdrand, + /// RDSEED + rdseed, + /// TSC (Time Stamp Counter) + tsc, + /// MMX + mmx, + /// SSE (Streaming SIMD Extensions) + sse, + /// SSE2 (Streaming SIMD Extensions 2) + sse2, + /// SSE3 (Streaming SIMD Extensions 3) + sse3, + /// SSSE3 (Supplemental Streaming SIMD Extensions 3) + ssse3, + /// SSE4.1 (Streaming SIMD Extensions 4.1) + sse4_1, + /// SSE4.2 (Streaming SIMD Extensions 4.2) + sse4_2, + /// SSE4a (Streaming SIMD Extensions 4a) + sse4a, + /// SHA + sha, + /// AVX (Advanced Vector Extensions) + avx, + /// AVX2 (Advanced Vector Extensions 2) + avx2, + /// AVX-512 F (Foundation) + avx512f, + /// AVX-512 CD (Conflict Detection Instructions) + avx512cd, + /// AVX-512 ER (Exponential and Reciprocal Instructions) + avx512er, + /// AVX-512 PF (Prefetch Instructions) + avx512pf, + /// AVX-512 BW (Byte and Word Instructions) + avx512bw, + /// AVX-512 DQ (Doubleword and Quadword) + avx512dq, + /// AVX-512 VL (Vector Length Extensions) + avx512vl, + /// AVX-512 IFMA (Integer Fused Multiply Add) + avx512_ifma, + /// AVX-512 VBMI (Vector Byte Manipulation Instructions) + avx512_vbmi, + /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and + /// Quadword) + avx512_vpopcntdq, + /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats) + f16c, + /// FMA (Fused Multiply Add) + fma, + /// BMI1 (Bit Manipulation Instructions 1) + bmi, + /// BMI1 (Bit Manipulation Instructions 2) + bmi2, + /// ABM (Advanced Bit Manipulation) on AMD / LZCNT (Leading Zero + /// Count) on Intel + abm, + /// TBM (Trailing Bit Manipulation) + tbm, + /// POPCNT (Population Count) + popcnt, + /// FXSR (Floating-point context fast save and restor) + fxsr, + /// XSAVE (Save Processor Extended States) + xsave, + /// XSAVEOPT (Save Processor Extended States Optimized) + xsaveopt, + /// XSAVES (Save Processor Extended States Supervisor) + xsaves, + /// XSAVEC (Save Processor Extended States Compacted) + xsavec, + /// CMPXCH16B, a 16-byte compare-and-swap instruction + cmpxchg16b, + /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + adx, + /// RTM, Intel (Restricted Transactional Memory) + rtm, +} diff --git a/tests/source/cfg_if/detect/bit.rs b/tests/source/cfg_if/detect/bit.rs new file mode 100644 index 00000000000..578f0b16b74 --- /dev/null +++ b/tests/source/cfg_if/detect/bit.rs @@ -0,0 +1,9 @@ +//! Bit manipulation utilities. + +/// Tests the `bit` of `x`. +#[allow(dead_code)] +#[inline] +pub(crate) fn test(x: usize, bit: u32) -> bool { + debug_assert!(bit < 32, "bit index out-of-bounds"); + x & (1 << bit) != 0 +} diff --git a/tests/source/cfg_if/detect/cache.rs b/tests/source/cfg_if/detect/cache.rs new file mode 100644 index 00000000000..92bc4b58d16 --- /dev/null +++ b/tests/source/cfg_if/detect/cache.rs @@ -0,0 +1,164 @@ +//! Caches run-time feature detection so that it only needs to be computed +//! once. + +#![allow(dead_code)] // not used on all platforms + +use crate::sync::atomic::Ordering; + +#[cfg(target_pointer_width = "64")] +use crate::sync::atomic::AtomicU64; + +#[cfg(target_pointer_width = "32")] +use crate::sync::atomic::AtomicU32; + +/// Sets the `bit` of `x`. +#[inline] +const fn set_bit(x: u64, bit: u32) -> u64 { + x | 1 << bit +} + +/// Tests the `bit` of `x`. +#[inline] +const fn test_bit(x: u64, bit: u32) -> bool { + x & (1 << bit) != 0 +} + +/// Maximum number of features that can be cached. +const CACHE_CAPACITY: u32 = 63; + +/// This type is used to initialize the cache +#[derive(Copy, Clone)] +pub(crate) struct Initializer(u64); + +#[allow(clippy::use_self)] +impl Default for Initializer { + fn default() -> Self { + Initializer(0) + } +} + +impl Initializer { + /// Tests the `bit` of the cache. + #[allow(dead_code)] + #[inline] + pub(crate) fn test(self, bit: u32) -> bool { + // FIXME: this way of making sure that the cache is large enough is + // brittle. + debug_assert!( + bit < CACHE_CAPACITY, + "too many features, time to increase the cache size!" + ); + test_bit(self.0, bit) + } + + /// Sets the `bit` of the cache. + #[inline] + pub(crate) fn set(&mut self, bit: u32) { + // FIXME: this way of making sure that the cache is large enough is + // brittle. + debug_assert!( + bit < CACHE_CAPACITY, + "too many features, time to increase the cache size!" + ); + let v = self.0; + self.0 = set_bit(v, bit); + } +} + +/// This global variable is a cache of the features supported by the CPU. +static CACHE: Cache = Cache::uninitialized(); + +/// Feature cache with capacity for `CACHE_CAPACITY` features. +/// +/// Note: the last feature bit is used to represent an +/// uninitialized cache. +#[cfg(target_pointer_width = "64")] +struct Cache(AtomicU64); + +#[cfg(target_pointer_width = "64")] +#[allow(clippy::use_self)] +impl Cache { + /// Creates an uninitialized cache. + #[allow(clippy::declare_interior_mutable_const)] + const fn uninitialized() -> Self { + Cache(AtomicU64::new(u64::max_value())) + } + /// Is the cache uninitialized? + #[inline] + pub(crate) fn is_uninitialized(&self) -> bool { + self.0.load(Ordering::Relaxed) == u64::max_value() + } + + /// Is the `bit` in the cache set? + #[inline] + pub(crate) fn test(&self, bit: u32) -> bool { + test_bit(CACHE.0.load(Ordering::Relaxed), bit) + } + + /// Initializes the cache. + #[inline] + pub(crate) fn initialize(&self, value: Initializer) { + self.0.store(value.0, Ordering::Relaxed); + } +} + +/// Feature cache with capacity for `CACHE_CAPACITY` features. +/// +/// Note: the last feature bit is used to represent an +/// uninitialized cache. +#[cfg(target_pointer_width = "32")] +struct Cache(AtomicU32, AtomicU32); + +#[cfg(target_pointer_width = "32")] +impl Cache { + /// Creates an uninitialized cache. + const fn uninitialized() -> Self { + Cache( + AtomicU32::new(u32::max_value()), + AtomicU32::new(u32::max_value()), + ) + } + /// Is the cache uninitialized? + #[inline] + pub(crate) fn is_uninitialized(&self) -> bool { + self.1.load(Ordering::Relaxed) == u32::max_value() + } + + /// Is the `bit` in the cache set? + #[inline] + pub(crate) fn test(&self, bit: u32) -> bool { + if bit < 32 { + test_bit(CACHE.0.load(Ordering::Relaxed) as u64, bit) + } else { + test_bit(CACHE.1.load(Ordering::Relaxed) as u64, bit - 32) + } + } + + /// Initializes the cache. + #[inline] + pub(crate) fn initialize(&self, value: Initializer) { + let lo: u32 = value.0 as u32; + let hi: u32 = (value.0 >> 32) as u32; + self.0.store(lo, Ordering::Relaxed); + self.1.store(hi, Ordering::Relaxed); + } +} + +/// Tests the `bit` of the storage. If the storage has not been initialized, +/// initializes it with the result of `f()`. +/// +/// On its first invocation, it detects the CPU features and caches them in the +/// `CACHE` global variable as an `AtomicU64`. +/// +/// It uses the `Feature` variant to index into this variable as a bitset. If +/// the bit is set, the feature is enabled, and otherwise it is disabled. +#[inline] +pub(crate) fn test(bit: u32, f: F) -> bool +where + F: FnOnce() -> Initializer, +{ + if CACHE.is_uninitialized() { + CACHE.initialize(f()); + } + CACHE.test(bit) +} diff --git a/tests/source/cfg_if/detect/error_macros.rs b/tests/source/cfg_if/detect/error_macros.rs new file mode 100644 index 00000000000..6769757ed93 --- /dev/null +++ b/tests/source/cfg_if/detect/error_macros.rs @@ -0,0 +1,150 @@ +//! The `is_{target_arch}_feature_detected!` macro are only available on their +//! architecture. These macros provide a better error messages when the user +//! attempts to call them in a different architecture. + +/// Prevents compilation if `is_x86_feature_detected` is used somewhere +/// else than `x86` and `x86_64` targets. +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_x86_feature_detected { + ($t: tt) => { + compile_error!( + r#" + is_x86_feature_detected can only be used on x86 and x86_64 targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + if is_x86_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_arm_feature_detected` is used somewhere else +/// than `ARM` targets. +#[cfg(not(target_arch = "arm"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_arm_feature_detected { + ($t:tt) => { + compile_error!( + r#" + is_arm_feature_detected can only be used on ARM targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "arm")] { + if is_arm_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_aarch64_feature_detected` is used somewhere else +/// than `aarch64` targets. +#[cfg(not(target_arch = "aarch64"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_aarch64_feature_detected { + ($t: tt) => { + compile_error!( + r#" + is_aarch64_feature_detected can only be used on AArch64 targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "aarch64")] { + if is_aarch64_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_powerpc_feature_detected` is used somewhere else +/// than `PowerPC` targets. +#[cfg(not(target_arch = "powerpc"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_powerpc_feature_detected { + ($t:tt) => { + compile_error!( + r#" +is_powerpc_feature_detected can only be used on PowerPC targets. +You can prevent it from being used in other architectures by +guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "powerpc")] { + if is_powerpc_feature_detected(...) { ... } + } +"# + ) + }; +} + +/// Prevents compilation if `is_powerpc64_feature_detected` is used somewhere +/// else than `PowerPC64` targets. +#[cfg(not(target_arch = "powerpc64"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_powerpc64_feature_detected { + ($t:tt) => { + compile_error!( + r#" +is_powerpc64_feature_detected can only be used on PowerPC64 targets. +You can prevent it from being used in other architectures by +guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "powerpc64")] { + if is_powerpc64_feature_detected(...) { ... } + } +"# + ) + }; +} + +/// Prevents compilation if `is_mips_feature_detected` is used somewhere else +/// than `MIPS` targets. +#[cfg(not(target_arch = "mips"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_mips_feature_detected { + ($t:tt) => { + compile_error!( + r#" + is_mips_feature_detected can only be used on MIPS targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "mips")] { + if is_mips_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_mips64_feature_detected` is used somewhere else +/// than `MIPS64` targets. +#[cfg(not(target_arch = "mips64"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_mips64_feature_detected { + ($t:tt) => { + compile_error!( + r#" + is_mips64_feature_detected can only be used on MIPS64 targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "mips64")] { + if is_mips64_feature_detected(...) { ... } + } + "# + ) + }; +} diff --git a/tests/source/cfg_if/detect/mod.rs b/tests/source/cfg_if/detect/mod.rs new file mode 100644 index 00000000000..f446e88eedc --- /dev/null +++ b/tests/source/cfg_if/detect/mod.rs @@ -0,0 +1,85 @@ +//! This module implements run-time feature detection. +//! +//! The `is_{arch}_feature_detected!("feature-name")` macros take the name of a +//! feature as a string-literal, and return a boolean indicating whether the +//! feature is enabled at run-time or not. +//! +//! These macros do two things: +//! * map the string-literal into an integer stored as a `Feature` enum, +//! * call a `os::check_for(x: Feature)` function that returns `true` if the +//! feature is enabled. +//! +//! The `Feature` enums are also implemented in the `arch/{target_arch}.rs` +//! modules. +//! +//! The `check_for` functions are, in general, Operating System dependent. Most +//! architectures do not allow user-space programs to query the feature bits +//! due to security concerns (x86 is the big exception). These functions are +//! implemented in the `os/{target_os}.rs` modules. + +#[macro_use] +mod error_macros; + +cfg_if! { + if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + #[path = "arch/x86.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "arm")] { + #[path = "arch/arm.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "aarch64")] { + #[path = "arch/aarch64.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "powerpc")] { + #[path = "arch/powerpc.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "powerpc64")] { + #[path = "arch/powerpc64.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "mips")] { + #[path = "arch/mips.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "mips64")] { + #[path = "arch/mips64.rs"] + #[macro_use] + mod arch; + } else { + // Unimplemented architecture: + mod arch { + pub enum Feature { + Null + } + } + } +} +pub use self::arch::Feature; + +mod bit; +mod cache; + +cfg_if! { + if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + // On x86/x86_64 no OS specific functionality is required. + #[path = "os/x86.rs"] + mod os; + } else if #[cfg(all(target_os = "linux", feature = "use_std"))] { + #[path = "os/linux/mod.rs"] + mod os; + } else if #[cfg(target_os = "freebsd")] { + #[cfg(target_arch = "aarch64")] + #[path = "os/aarch64.rs"] + mod aarch64; + #[path = "os/freebsd/mod.rs"] + mod os; + } else { + #[path = "os/other.rs"] + mod os; + } +} +pub use self::os::check_for; diff --git a/tests/source/cfg_if/detect/os/aarch64.rs b/tests/source/cfg_if/detect/os/aarch64.rs new file mode 100644 index 00000000000..dfb8c87707f --- /dev/null +++ b/tests/source/cfg_if/detect/os/aarch64.rs @@ -0,0 +1,79 @@ +//! Run-time feature detection for Aarch64 on any OS that emulates the mrs instruction. +//! +//! On FreeBSD >= 12.0, Linux >= 4.11 and other operating systems, it is possible to use +//! privileged system registers from userspace to check CPU feature support. +//! +//! AArch64 system registers ID_AA64ISAR0_EL1, ID_AA64PFR0_EL1, ID_AA64ISAR1_EL1 +//! have bits dedicated to features like AdvSIMD, CRC32, AES, atomics (LSE), etc. +//! Each part of the register indicates the level of support for a certain feature, e.g. +//! when ID_AA64ISAR0_EL1\[7:4\] is >= 1, AES is supported; when it's >= 2, PMULL is supported. +//! +//! For proper support of [SoCs where different cores have different capabilities](https://medium.com/@jadr2ddude/a-big-little-problem-a-tale-of-big-little-gone-wrong-e7778ce744bb), +//! the OS has to always report only the features supported by all cores, like [FreeBSD does](https://reviews.freebsd.org/D17137#393947). +//! +//! References: +//! +//! - [Zircon implementation](https://fuchsia.googlesource.com/zircon/+/master/kernel/arch/arm64/feature.cpp) +//! - [Linux documentation](https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt) + +use crate::detect::{Feature, cache}; + +/// Try to read the features from the system registers. +/// +/// This will cause SIGILL if the current OS is not trapping the mrs instruction. +pub(crate) fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + + { + let mut enable_feature = |f, enable| { + if enable { + value.set(f as u32); + } + }; + + // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0 + let aa64isar0: u64; + unsafe { asm!("mrs $0, ID_AA64ISAR0_EL1" : "=r"(aa64isar0)); } + + let aes = bits_shift(aa64isar0, 7, 4) >= 1; + let pmull = bits_shift(aa64isar0, 7, 4) >= 2; + let sha1 = bits_shift(aa64isar0, 11, 8) >= 1; + let sha2 = bits_shift(aa64isar0, 15, 12) >= 1; + enable_feature(Feature::pmull, pmull); + // Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp + enable_feature(Feature::crypto, aes && pmull && sha1 && sha2); + enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1); + enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1); + + // ID_AA64PFR0_EL1 - Processor Feature Register 0 + let aa64pfr0: u64; + unsafe { asm!("mrs $0, ID_AA64PFR0_EL1" : "=r"(aa64pfr0)); } + + let fp = bits_shift(aa64pfr0, 19, 16) < 0xF; + let fphp = bits_shift(aa64pfr0, 19, 16) >= 1; + let asimd = bits_shift(aa64pfr0, 23, 20) < 0xF; + let asimdhp = bits_shift(aa64pfr0, 23, 20) >= 1; + enable_feature(Feature::fp, fp); + enable_feature(Feature::fp16, fphp); + // SIMD support requires float support - if half-floats are + // supported, it also requires half-float support: + enable_feature(Feature::asimd, fp && asimd && (!fphp | asimdhp)); + // SIMD extensions require SIMD support: + enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1); + enable_feature(Feature::dotprod, asimd && bits_shift(aa64isar0, 47, 44) >= 1); + enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1); + + // ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1 + let aa64isar1: u64; + unsafe { asm!("mrs $0, ID_AA64ISAR1_EL1" : "=r"(aa64isar1)); } + + enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1); + } + + value +} + +#[inline] +fn bits_shift(x: u64, high: usize, low: usize) -> u64 { + (x >> low) & ((1 << (high - low + 1)) - 1) +} diff --git a/tests/source/cfg_if/detect/os/freebsd/aarch64.rs b/tests/source/cfg_if/detect/os/freebsd/aarch64.rs new file mode 100644 index 00000000000..910d2f33b39 --- /dev/null +++ b/tests/source/cfg_if/detect/os/freebsd/aarch64.rs @@ -0,0 +1,28 @@ +//! Run-time feature detection for Aarch64 on FreeBSD. + +use crate::detect::{Feature, cache}; +use super::super::aarch64::detect_features; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +#[cfg(test)] +mod tests { + #[test] + fn dump() { + println!("asimd: {:?}", is_aarch64_feature_detected!("asimd")); + println!("pmull: {:?}", is_aarch64_feature_detected!("pmull")); + println!("fp: {:?}", is_aarch64_feature_detected!("fp")); + println!("fp16: {:?}", is_aarch64_feature_detected!("fp16")); + println!("sve: {:?}", is_aarch64_feature_detected!("sve")); + println!("crc: {:?}", is_aarch64_feature_detected!("crc")); + println!("crypto: {:?}", is_aarch64_feature_detected!("crypto")); + println!("lse: {:?}", is_aarch64_feature_detected!("lse")); + println!("rdm: {:?}", is_aarch64_feature_detected!("rdm")); + println!("rcpc: {:?}", is_aarch64_feature_detected!("rcpc")); + println!("dotprod: {:?}", is_aarch64_feature_detected!("dotprod")); + } +} diff --git a/tests/source/cfg_if/detect/os/freebsd/arm.rs b/tests/source/cfg_if/detect/os/freebsd/arm.rs new file mode 100644 index 00000000000..e13847dcbd8 --- /dev/null +++ b/tests/source/cfg_if/detect/os/freebsd/arm.rs @@ -0,0 +1,27 @@ +//! Run-time feature detection for ARM on FreeBSD + +use crate::detect::{Feature, cache}; +use super::{auxvec}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::neon, auxv.hwcap & 0x00001000 != 0); + enable_feature(&mut value, Feature::pmull, auxv.hwcap2 & 0x00000002 != 0); + return value; + } + value +} diff --git a/tests/source/cfg_if/detect/os/freebsd/auxvec.rs b/tests/source/cfg_if/detect/os/freebsd/auxvec.rs new file mode 100644 index 00000000000..a2bac767601 --- /dev/null +++ b/tests/source/cfg_if/detect/os/freebsd/auxvec.rs @@ -0,0 +1,86 @@ +//! Parses ELF auxiliary vectors. +#![cfg_attr(any(target_arch = "arm", target_arch = "powerpc64"), allow(dead_code))] + +/// Key to access the CPU Hardware capabilities bitfield. +pub(crate) const AT_HWCAP: usize = 25; +/// Key to access the CPU Hardware capabilities 2 bitfield. +pub(crate) const AT_HWCAP2: usize = 26; + +/// Cache HWCAP bitfields of the ELF Auxiliary Vector. +/// +/// If an entry cannot be read all the bits in the bitfield are set to zero. +/// This should be interpreted as all the features being disabled. +#[derive(Debug, Copy, Clone)] +pub(crate) struct AuxVec { + pub hwcap: usize, + pub hwcap2: usize, +} + +/// ELF Auxiliary Vector +/// +/// The auxiliary vector is a memory region in a running ELF program's stack +/// composed of (key: usize, value: usize) pairs. +/// +/// The keys used in the aux vector are platform dependent. For FreeBSD, they are +/// defined in [sys/elf_common.h][elf_common_h]. The hardware capabilities of a given +/// CPU can be queried with the `AT_HWCAP` and `AT_HWCAP2` keys. +/// +/// Note that run-time feature detection is not invoked for features that can +/// be detected at compile-time. +/// +/// [elf_common.h]: https://svnweb.freebsd.org/base/release/12.0.0/sys/sys/elf_common.h?revision=341707 +pub(crate) fn auxv() -> Result { + if let Ok(hwcap) = archauxv(AT_HWCAP) { + if let Ok(hwcap2) = archauxv(AT_HWCAP2) { + if hwcap != 0 && hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + } + Err(()) +} + +/// Tries to read the `key` from the auxiliary vector. +fn archauxv(key: usize) -> Result { + use crate::mem; + + #[derive (Copy, Clone)] + #[repr(C)] + pub struct Elf_Auxinfo { + pub a_type: usize, + pub a_un: unnamed, + } + #[derive (Copy, Clone)] + #[repr(C)] + pub union unnamed { + pub a_val: libc::c_long, + pub a_ptr: *mut libc::c_void, + pub a_fcn: Option ()>, + } + + let mut auxv: [Elf_Auxinfo; 27] = + [Elf_Auxinfo{a_type: 0, a_un: unnamed{a_val: 0,},}; 27]; + + let mut len: libc::c_uint = mem::size_of_val(&auxv) as libc::c_uint; + + unsafe { + let mut mib = [libc::CTL_KERN, libc::KERN_PROC, libc::KERN_PROC_AUXV, libc::getpid()]; + + let ret = libc::sysctl(mib.as_mut_ptr(), + mib.len() as u32, + &mut auxv as *mut _ as *mut _, + &mut len as *mut _ as *mut _, + 0 as *mut libc::c_void, + 0, + ); + + if ret != -1 { + for i in 0..auxv.len() { + if auxv[i].a_type == key { + return Ok(auxv[i].a_un.a_val as usize); + } + } + } + } + return Ok(0); +} diff --git a/tests/source/cfg_if/detect/os/freebsd/mod.rs b/tests/source/cfg_if/detect/os/freebsd/mod.rs new file mode 100644 index 00000000000..1a5338a3555 --- /dev/null +++ b/tests/source/cfg_if/detect/os/freebsd/mod.rs @@ -0,0 +1,22 @@ +//! Run-time feature detection on FreeBSD + +mod auxvec; + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::check_for; + } else if #[cfg(target_arch = "arm")] { + mod arm; + pub use self::arm::check_for; + } else if #[cfg(target_arch = "powerpc64")] { + mod powerpc; + pub use self::powerpc::check_for; + } else { + use crate::arch::detect::Feature; + /// Performs run-time feature detection. + pub fn check_for(_x: Feature) -> bool { + false + } + } +} diff --git a/tests/source/cfg_if/detect/os/freebsd/powerpc.rs b/tests/source/cfg_if/detect/os/freebsd/powerpc.rs new file mode 100644 index 00000000000..c7f761d4d60 --- /dev/null +++ b/tests/source/cfg_if/detect/os/freebsd/powerpc.rs @@ -0,0 +1,27 @@ +//! Run-time feature detection for PowerPC on FreeBSD. + +use crate::detect::{Feature, cache}; +use super::{auxvec}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0); + enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0); + enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0); + return value; + } + value +} diff --git a/tests/source/cfg_if/detect/os/linux/aarch64.rs b/tests/source/cfg_if/detect/os/linux/aarch64.rs new file mode 100644 index 00000000000..f7dc0f0222e --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/aarch64.rs @@ -0,0 +1,157 @@ +//! Run-time feature detection for Aarch64 on Linux. + +use crate::detect::{Feature, cache, bit}; +use super::{auxvec, cpuinfo}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from /proc/cpuinfo. +fn detect_features() -> cache::Initializer { + if let Ok(auxv) = auxvec::auxv() { + let hwcap: AtHwcap = auxv.into(); + return hwcap.cache(); + } + if let Ok(c) = cpuinfo::CpuInfo::new() { + let hwcap: AtHwcap = c.into(); + return hwcap.cache(); + } + cache::Initializer::default() +} + +/// These values are part of the platform-specific [asm/hwcap.h][hwcap] . +/// +/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h +struct AtHwcap { + fp: bool, // 0 + asimd: bool, // 1 + // evtstrm: bool, // 2 + aes: bool, // 3 + pmull: bool, // 4 + sha1: bool, // 5 + sha2: bool, // 6 + crc32: bool, // 7 + atomics: bool, // 8 + fphp: bool, // 9 + asimdhp: bool, // 10 + // cpuid: bool, // 11 + asimdrdm: bool, // 12 + // jscvt: bool, // 13 + // fcma: bool, // 14 + lrcpc: bool, // 15 + // dcpop: bool, // 16 + // sha3: bool, // 17 + // sm3: bool, // 18 + // sm4: bool, // 19 + asimddp: bool, // 20 + // sha512: bool, // 21 + sve: bool, // 22 +} + +impl From for AtHwcap { + /// Reads AtHwcap from the auxiliary vector. + fn from(auxv: auxvec::AuxVec) -> Self { + AtHwcap { + fp: bit::test(auxv.hwcap, 0), + asimd: bit::test(auxv.hwcap, 1), + // evtstrm: bit::test(auxv.hwcap, 2), + aes: bit::test(auxv.hwcap, 3), + pmull: bit::test(auxv.hwcap, 4), + sha1: bit::test(auxv.hwcap, 5), + sha2: bit::test(auxv.hwcap, 6), + crc32: bit::test(auxv.hwcap, 7), + atomics: bit::test(auxv.hwcap, 8), + fphp: bit::test(auxv.hwcap, 9), + asimdhp: bit::test(auxv.hwcap, 10), + // cpuid: bit::test(auxv.hwcap, 11), + asimdrdm: bit::test(auxv.hwcap, 12), + // jscvt: bit::test(auxv.hwcap, 13), + // fcma: bit::test(auxv.hwcap, 14), + lrcpc: bit::test(auxv.hwcap, 15), + // dcpop: bit::test(auxv.hwcap, 16), + // sha3: bit::test(auxv.hwcap, 17), + // sm3: bit::test(auxv.hwcap, 18), + // sm4: bit::test(auxv.hwcap, 19), + asimddp: bit::test(auxv.hwcap, 20), + // sha512: bit::test(auxv.hwcap, 21), + sve: bit::test(auxv.hwcap, 22), + } + } +} + +impl From for AtHwcap { + /// Reads AtHwcap from /proc/cpuinfo . + fn from(c: cpuinfo::CpuInfo) -> Self { + let f = &c.field("Features"); + AtHwcap { + // 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will + // map some of the 64-bit names to some 32-bit feature names. This does not + // cover that yet. + fp: f.has("fp"), + asimd: f.has("asimd"), + // evtstrm: f.has("evtstrm"), + aes: f.has("aes"), + pmull: f.has("pmull"), + sha1: f.has("sha1"), + sha2: f.has("sha2"), + crc32: f.has("crc32"), + atomics: f.has("atomics"), + fphp: f.has("fphp"), + asimdhp: f.has("asimdhp"), + // cpuid: f.has("cpuid"), + asimdrdm: f.has("asimdrdm"), + // jscvt: f.has("jscvt"), + // fcma: f.has("fcma"), + lrcpc: f.has("lrcpc"), + // dcpop: f.has("dcpop"), + // sha3: f.has("sha3"), + // sm3: f.has("sm3"), + // sm4: f.has("sm4"), + asimddp: f.has("asimddp"), + // sha512: f.has("sha512"), + sve: f.has("sve"), + } + } +} + +impl AtHwcap { + /// Initializes the cache from the feature -bits. + /// + /// The features are enabled approximately like in LLVM host feature detection: + /// https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Host.cpp#L1273 + fn cache(self) -> cache::Initializer { + let mut value = cache::Initializer::default(); + { + let mut enable_feature = |f, enable| { + if enable { + value.set(f as u32); + } + }; + + enable_feature(Feature::fp, self.fp); + // Half-float support requires float support + enable_feature(Feature::fp16, self.fp && self.fphp); + enable_feature(Feature::pmull, self.pmull); + enable_feature(Feature::crc, self.crc32); + enable_feature(Feature::lse, self.atomics); + enable_feature(Feature::rcpc, self.lrcpc); + + // SIMD support requires float support - if half-floats are + // supported, it also requires half-float support: + let asimd = self.fp && self.asimd && (!self.fphp | self.asimdhp); + enable_feature(Feature::asimd, asimd); + // SIMD extensions require SIMD support: + enable_feature(Feature::rdm, self.asimdrdm && asimd); + enable_feature(Feature::dotprod, self.asimddp && asimd); + enable_feature(Feature::sve, self.sve && asimd); + + // Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp + enable_feature(Feature::crypto, self.aes && self.pmull && self.sha1 && self.sha2); + } + value + } +} diff --git a/tests/source/cfg_if/detect/os/linux/arm.rs b/tests/source/cfg_if/detect/os/linux/arm.rs new file mode 100644 index 00000000000..0d58a847cd6 --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/arm.rs @@ -0,0 +1,49 @@ +//! Run-time feature detection for ARM on Linux. + +use crate::detect::{Feature, cache, bit}; +use super::{auxvec, cpuinfo}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from /proc/cpuinfo. +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + // The values are part of the platform-specific [asm/hwcap.h][hwcap] + // + // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::neon, bit::test(auxv.hwcap, 12)); + enable_feature(&mut value, Feature::pmull, bit::test(auxv.hwcap2, 1)); + return value; + } + + if let Ok(c) = cpuinfo::CpuInfo::new() { + enable_feature(&mut value, Feature::neon, c.field("Features").has("neon") && + !has_broken_neon(&c)); + enable_feature(&mut value, Feature::pmull, c.field("Features").has("pmull")); + return value; + } + value +} + +/// Is the CPU known to have a broken NEON unit? +/// +/// See https://crbug.com/341598. +fn has_broken_neon(cpuinfo: &cpuinfo::CpuInfo) -> bool { + cpuinfo.field("CPU implementer") == "0x51" + && cpuinfo.field("CPU architecture") == "7" + && cpuinfo.field("CPU variant") == "0x1" + && cpuinfo.field("CPU part") == "0x04d" + && cpuinfo.field("CPU revision") == "0" +} diff --git a/tests/source/cfg_if/detect/os/linux/auxvec.rs b/tests/source/cfg_if/detect/os/linux/auxvec.rs new file mode 100644 index 00000000000..07b6432eafd --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/auxvec.rs @@ -0,0 +1,307 @@ +//! Parses ELF auxiliary vectors. +#![cfg_attr(not(target_arch = "aarch64"), allow(dead_code))] + +#[cfg(feature = "std_detect_file_io")] +use crate::{fs::File, io::Read}; + +/// Key to access the CPU Hardware capabilities bitfield. +pub(crate) const AT_HWCAP: usize = 16; +/// Key to access the CPU Hardware capabilities 2 bitfield. +#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] +pub(crate) const AT_HWCAP2: usize = 26; + +/// Cache HWCAP bitfields of the ELF Auxiliary Vector. +/// +/// If an entry cannot be read all the bits in the bitfield are set to zero. +/// This should be interpreted as all the features being disabled. +#[derive(Debug, Copy, Clone)] +pub(crate) struct AuxVec { + pub hwcap: usize, + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + pub hwcap2: usize, +} + +/// ELF Auxiliary Vector +/// +/// The auxiliary vector is a memory region in a running ELF program's stack +/// composed of (key: usize, value: usize) pairs. +/// +/// The keys used in the aux vector are platform dependent. For Linux, they are +/// defined in [linux/auxvec.h][auxvec_h]. The hardware capabilities of a given +/// CPU can be queried with the `AT_HWCAP` and `AT_HWCAP2` keys. +/// +/// There is no perfect way of reading the auxiliary vector. +/// +/// - If the `std_detect_dlsym_getauxval` cargo feature is enabled, this will use +/// `getauxval` if its linked to the binary, and otherwise proceed to a fallback implementation. +/// When `std_detect_dlsym_getauxval` is disabled, this will assume that `getauxval` is +/// linked to the binary - if that is not the case the behavior is undefined. +/// - Otherwise, if the `std_detect_file_io` cargo feature is enabled, it will +/// try to read `/proc/self/auxv`. +/// - If that fails, this function returns an error. +/// +/// Note that run-time feature detection is not invoked for features that can +/// be detected at compile-time. Also note that if this function returns an +/// error, cpuinfo still can (and will) be used to try to perform run-time +/// feature detecton on some platforms. +/// +/// For more information about when `getauxval` is available check the great +/// [`auxv` crate documentation][auxv_docs]. +/// +/// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h +/// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/ +pub(crate) fn auxv() -> Result { + #[cfg(feature = "std_detect_dlsym_getauxval")] { + // Try to call a dynamically-linked getauxval function. + if let Ok(hwcap) = getauxval(AT_HWCAP) { + // Targets with only AT_HWCAP: + #[cfg(any(target_arch = "aarch64", target_arch = "mips", + target_arch = "mips64"))] + { + if hwcap != 0 { + return Ok(AuxVec { hwcap }); + } + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + if let Ok(hwcap2) = getauxval(AT_HWCAP2) { + if hwcap != 0 && hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + } + drop(hwcap); + } + #[cfg(feature = "std_detect_file_io")] { + // If calling getauxval fails, try to read the auxiliary vector from + // its file: + auxv_from_file("/proc/self/auxv") + } + #[cfg(not(feature = "std_detect_file_io"))] { + Err(()) + } + } + + #[cfg(not(feature = "std_detect_dlsym_getauxval"))] { + let hwcap = unsafe { ffi_getauxval(AT_HWCAP) }; + + // Targets with only AT_HWCAP: + #[cfg(any(target_arch = "aarch64", target_arch = "mips", + target_arch = "mips64"))] + { + if hwcap != 0 { + return Ok(AuxVec { hwcap }); + } + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + let hwcap2 = unsafe { ffi_getauxval(AT_HWCAP2) }; + if hwcap != 0 && hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + } +} + +/// Tries to read the `key` from the auxiliary vector by calling the +/// dynamically-linked `getauxval` function. If the function is not linked, +/// this function return `Err`. +#[cfg(feature = "std_detect_dlsym_getauxval")] +fn getauxval(key: usize) -> Result { + use libc; + pub type F = unsafe extern "C" fn(usize) -> usize; + unsafe { + let ptr = libc::dlsym( + libc::RTLD_DEFAULT, + "getauxval\0".as_ptr() as *const _, + ); + if ptr.is_null() { + return Err(()); + } + + let ffi_getauxval: F = mem::transmute(ptr); + Ok(ffi_getauxval(key)) + } +} + +/// Tries to read the auxiliary vector from the `file`. If this fails, this +/// function returns `Err`. +#[cfg(feature = "std_detect_file_io")] +fn auxv_from_file(file: &str) -> Result { + let mut file = File::open(file).map_err(|_| ())?; + + // See . + // + // The auxiliary vector contains at most 32 (key,value) fields: from + // `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of + // 2*32 `usize` elements is enough to read the whole vector. + let mut buf = [0_usize; 64]; + { + let raw: &mut [u8; 64 * mem::size_of::()] = + unsafe { mem::transmute(&mut buf) }; + file.read(raw).map_err(|_| ())?; + } + auxv_from_buf(&buf) +} + +/// Tries to interpret the `buffer` as an auxiliary vector. If that fails, this +/// function returns `Err`. +#[cfg(feature = "std_detect_file_io")] +fn auxv_from_buf(buf: &[usize; 64]) -> Result { + // Targets with only AT_HWCAP: + #[cfg(any(target_arch = "aarch64", target_arch = "mips", + target_arch = "mips64"))] + { + for el in buf.chunks(2) { + match el[0] { + AT_HWCAP => return Ok(AuxVec { hwcap: el[1] }), + _ => (), + } + } + } + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + let mut hwcap = None; + let mut hwcap2 = None; + for el in buf.chunks(2) { + match el[0] { + AT_HWCAP => hwcap = Some(el[1]), + AT_HWCAP2 => hwcap2 = Some(el[1]), + _ => (), + } + } + + if let (Some(hwcap), Some(hwcap2)) = (hwcap, hwcap2) { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + drop(buf); + Err(()) +} + +#[cfg(test)] +mod tests { + extern crate auxv as auxv_crate; + use super::*; + + // Reads the Auxiliary Vector key from /proc/self/auxv + // using the auxv crate. + #[cfg(feature = "std_detect_file_io")] + fn auxv_crate_getprocfs(key: usize) -> Option { + use self::auxv_crate::AuxvType; + use self::auxv_crate::procfs::search_procfs_auxv; + let k = key as AuxvType; + match search_procfs_auxv(&[k]) { + Ok(v) => Some(v[&k] as usize), + Err(_) => None, + } + } + + // Reads the Auxiliary Vector key from getauxval() + // using the auxv crate. + #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] + fn auxv_crate_getauxval(key: usize) -> Option { + use self::auxv_crate::AuxvType; + use self::auxv_crate::getauxval::Getauxval; + let q = auxv_crate::getauxval::NativeGetauxval {}; + match q.getauxval(key as AuxvType) { + Ok(v) => Some(v as usize), + Err(_) => None, + } + } + + // FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv + // does not always contain the AT_HWCAP key under qemu. + #[cfg(not(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc")))] + #[test] + fn auxv_crate() { + let v = auxv(); + if let Some(hwcap) = auxv_crate_getauxval(AT_HWCAP) { + let rt_hwcap = v.expect("failed to find hwcap key").hwcap; + assert_eq!(rt_hwcap, hwcap); + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + if let Some(hwcap2) = auxv_crate_getauxval(AT_HWCAP2) { + let rt_hwcap2 = v.expect("failed to find hwcap2 key").hwcap2; + assert_eq!(rt_hwcap2, hwcap2); + } + } + } + + #[test] + fn auxv_dump() { + if let Ok(auxvec) = auxv() { + println!("{:?}", auxvec); + } else { + println!("both getauxval() and reading /proc/self/auxv failed!"); + } + } + + #[cfg(feature = "std_detect_file_io")] + cfg_if! { + if #[cfg(target_arch = "arm")] { + #[test] + fn linux_rpi3() { + let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-rpi3.auxv"); + println!("file: {}", file); + let v = auxv_from_file(file).unwrap(); + assert_eq!(v.hwcap, 4174038); + assert_eq!(v.hwcap2, 16); + } + + #[test] + #[should_panic] + fn linux_macos_vb() { + let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/macos-virtualbox-linux-x86-4850HQ.auxv"); + println!("file: {}", file); + let v = auxv_from_file(file).unwrap(); + // this file is incomplete (contains hwcap but not hwcap2), we + // want to fall back to /proc/cpuinfo in this case, so + // reading should fail. assert_eq!(v.hwcap, 126614527); + // assert_eq!(v.hwcap2, 0); + } + } else if #[cfg(target_arch = "aarch64")] { + #[test] + fn linux_x64() { + let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-x64-i7-6850k.auxv"); + println!("file: {}", file); + let v = auxv_from_file(file).unwrap(); + assert_eq!(v.hwcap, 3219913727); + } + } + } + + #[test] + #[cfg(feature = "std_detect_file_io")] + fn auxv_dump_procfs() { + if let Ok(auxvec) = auxv_from_file("/proc/self/auxv") { + println!("{:?}", auxvec); + } else { + println!("reading /proc/self/auxv failed!"); + } + } + + #[test] + fn auxv_crate_procfs() { + let v = auxv(); + if let Some(hwcap) = auxv_crate_getprocfs(AT_HWCAP) { + assert_eq!(v.unwrap().hwcap, hwcap); + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + if let Some(hwcap2) = auxv_crate_getprocfs(AT_HWCAP2) { + assert_eq!(v.unwrap().hwcap2, hwcap2); + } + } + } +} diff --git a/tests/source/cfg_if/detect/os/linux/cpuinfo.rs b/tests/source/cfg_if/detect/os/linux/cpuinfo.rs new file mode 100644 index 00000000000..b3168578537 --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/cpuinfo.rs @@ -0,0 +1,301 @@ +//! Parses /proc/cpuinfo +#![cfg_attr(not(target_arch = "arm"), allow(dead_code))] + +extern crate std; +use self::std::{prelude::v1::*, fs::File, io, io::Read}; + +/// cpuinfo +pub(crate) struct CpuInfo { + raw: String, +} + +impl CpuInfo { + /// Reads /proc/cpuinfo into CpuInfo. + pub(crate) fn new() -> Result { + let mut file = File::open("/proc/cpuinfo")?; + let mut cpui = Self { raw: String::new() }; + file.read_to_string(&mut cpui.raw)?; + Ok(cpui) + } + /// Returns the value of the cpuinfo `field`. + pub(crate) fn field(&self, field: &str) -> CpuInfoField { + for l in self.raw.lines() { + if l.trim().starts_with(field) { + return CpuInfoField::new(l.split(": ").nth(1)); + } + } + CpuInfoField(None) + } + + /// Returns the `raw` contents of `/proc/cpuinfo` + #[cfg(test)] + fn raw(&self) -> &String { + &self.raw + } + + #[cfg(test)] + fn from_str(other: &str) -> Result { + Ok(Self { + raw: String::from(other), + }) + } +} + +/// Field of cpuinfo +#[derive(Debug)] +pub(crate) struct CpuInfoField<'a>(Option<&'a str>); + +impl<'a> PartialEq<&'a str> for CpuInfoField<'a> { + fn eq(&self, other: &&'a str) -> bool { + match self.0 { + None => other.is_empty(), + Some(f) => f == other.trim(), + } + } +} + +impl<'a> CpuInfoField<'a> { + pub(crate) fn new<'b>(v: Option<&'b str>) -> CpuInfoField<'b> { + match v { + None => CpuInfoField::<'b>(None), + Some(f) => CpuInfoField::<'b>(Some(f.trim())), + } + } + /// Does the field exist? + #[cfg(test)] + pub(crate) fn exists(&self) -> bool { + self.0.is_some() + } + /// Does the field contain `other`? + pub(crate) fn has(&self, other: &str) -> bool { + match self.0 { + None => other.is_empty(), + Some(f) => { + let other = other.trim(); + for v in f.split(' ') { + if v == other { + return true; + } + } + false + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn raw_dump() { + let cpuinfo = CpuInfo::new().unwrap(); + if cpuinfo.field("vendor_id") == "GenuineIntel" { + assert!(cpuinfo.field("flags").exists()); + assert!(!cpuinfo.field("vendor33_id").exists()); + assert!(cpuinfo.field("flags").has("sse")); + assert!(!cpuinfo.field("flags").has("avx314")); + } + println!("{}", cpuinfo.raw()); + } + + const CORE_DUO_T6500: &str = r"processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU T6500 @ 2.10GHz +stepping : 10 +microcode : 0xa0b +cpu MHz : 1600.000 +cache size : 2048 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fdiv_bug : no +hlt_bug : no +f00f_bug : no +coma_bug : no +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm +bogomips : 4190.43 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +"; + + #[test] + fn core_duo_t6500() { + let cpuinfo = CpuInfo::from_str(CORE_DUO_T6500).unwrap(); + assert_eq!(cpuinfo.field("vendor_id"), "GenuineIntel"); + assert_eq!(cpuinfo.field("cpu family"), "6"); + assert_eq!(cpuinfo.field("model"), "23"); + assert_eq!( + cpuinfo.field("model name"), + "Intel(R) Core(TM)2 Duo CPU T6500 @ 2.10GHz" + ); + assert_eq!( + cpuinfo.field("flags"), + "fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm" + ); + assert!(cpuinfo.field("flags").has("fpu")); + assert!(cpuinfo.field("flags").has("dtherm")); + assert!(cpuinfo.field("flags").has("sse2")); + assert!(!cpuinfo.field("flags").has("avx")); + } + + const ARM_CORTEX_A53: &str = + r"Processor : AArch64 Processor rev 3 (aarch64) + processor : 0 + processor : 1 + processor : 2 + processor : 3 + processor : 4 + processor : 5 + processor : 6 + processor : 7 + Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 + CPU implementer : 0x41 + CPU architecture: AArch64 + CPU variant : 0x0 + CPU part : 0xd03 + CPU revision : 3 + + Hardware : HiKey Development Board + "; + + #[test] + fn arm_cortex_a53() { + let cpuinfo = CpuInfo::from_str(ARM_CORTEX_A53).unwrap(); + assert_eq!( + cpuinfo.field("Processor"), + "AArch64 Processor rev 3 (aarch64)" + ); + assert_eq!( + cpuinfo.field("Features"), + "fp asimd evtstrm aes pmull sha1 sha2 crc32" + ); + assert!(cpuinfo.field("Features").has("pmull")); + assert!(!cpuinfo.field("Features").has("neon")); + assert!(cpuinfo.field("Features").has("asimd")); + } + + const ARM_CORTEX_A57: &str = r"Processor : Cortex A57 Processor rev 1 (aarch64) +processor : 0 +processor : 1 +processor : 2 +processor : 3 +Features : fp asimd aes pmull sha1 sha2 crc32 wp half thumb fastmult vfp edsp neon vfpv3 tlsi vfpv4 idiva idivt +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x1 +CPU part : 0xd07 +CPU revision : 1"; + + #[test] + fn arm_cortex_a57() { + let cpuinfo = CpuInfo::from_str(ARM_CORTEX_A57).unwrap(); + assert_eq!( + cpuinfo.field("Processor"), + "Cortex A57 Processor rev 1 (aarch64)" + ); + assert_eq!( + cpuinfo.field("Features"), + "fp asimd aes pmull sha1 sha2 crc32 wp half thumb fastmult vfp edsp neon vfpv3 tlsi vfpv4 idiva idivt" + ); + assert!(cpuinfo.field("Features").has("pmull")); + assert!(cpuinfo.field("Features").has("neon")); + assert!(cpuinfo.field("Features").has("asimd")); + } + + const POWER8E_POWERKVM: &str = r"processor : 0 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +processor : 1 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +processor : 2 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +processor : 3 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +timebase : 512000000 +platform : pSeries +model : IBM pSeries (emulated by qemu) +machine : CHRP IBM pSeries (emulated by qemu)"; + + #[test] + fn power8_powerkvm() { + let cpuinfo = CpuInfo::from_str(POWER8E_POWERKVM).unwrap(); + assert_eq!(cpuinfo.field("cpu"), "POWER8E (raw), altivec supported"); + + assert!(cpuinfo.field("cpu").has("altivec")); + } + + const POWER5P: &str = r"processor : 0 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 1 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 2 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 3 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 4 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 5 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 6 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 7 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +timebase : 237331000 +platform : pSeries +machine : CHRP IBM,9133-55A"; + + #[test] + fn power5p() { + let cpuinfo = CpuInfo::from_str(POWER5P).unwrap(); + assert_eq!(cpuinfo.field("cpu"), "POWER5+ (gs)"); + + assert!(!cpuinfo.field("cpu").has("altivec")); + } +} diff --git a/tests/source/cfg_if/detect/os/linux/mips.rs b/tests/source/cfg_if/detect/os/linux/mips.rs new file mode 100644 index 00000000000..c0a5fb2e5d8 --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/mips.rs @@ -0,0 +1,31 @@ +//! Run-time feature detection for MIPS on Linux. + +use crate::detect::{Feature, cache, bit}; +use super::auxvec; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from `/proc/cpuinfo`. +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + // The values are part of the platform-specific [asm/hwcap.h][hwcap] + // + // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::msa, bit::test(auxv.hwcap, 1)); + return value; + } + // TODO: fall back via `cpuinfo`. + value +} diff --git a/tests/source/cfg_if/detect/os/linux/mod.rs b/tests/source/cfg_if/detect/os/linux/mod.rs new file mode 100644 index 00000000000..e02d5e6dcda --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/mod.rs @@ -0,0 +1,28 @@ +//! Run-time feature detection on Linux + +mod auxvec; + +#[cfg(feature = "std_detect_file_io")] +mod cpuinfo; + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::check_for; + } else if #[cfg(target_arch = "arm")] { + mod arm; + pub use self::arm::check_for; + } else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { + mod mips; + pub use self::mips::check_for; + } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { + mod powerpc; + pub use self::powerpc::check_for; + } else { + use crate::detect::Feature; + /// Performs run-time feature detection. + pub fn check_for(_x: Feature) -> bool { + false + } + } +} diff --git a/tests/source/cfg_if/detect/os/linux/powerpc.rs b/tests/source/cfg_if/detect/os/linux/powerpc.rs new file mode 100644 index 00000000000..1c08a58443d --- /dev/null +++ b/tests/source/cfg_if/detect/os/linux/powerpc.rs @@ -0,0 +1,41 @@ +//! Run-time feature detection for PowerPC on Linux. + +use crate::detect::{Feature, cache}; +use super::{auxvec, cpuinfo}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from /proc/cpuinfo. +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + // The values are part of the platform-specific [asm/cputable.h][cputable] + // + // [cputable]: https://github.com/torvalds/linux/blob/master/arch/powerpc/include/uapi/asm/cputable.h + if let Ok(auxv) = auxvec::auxv() { + // note: the PowerPC values are the mask to do the test (instead of the + // index of the bit to test like in ARM and Aarch64) + enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0); + enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0); + enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0); + return value; + } + + // PowerPC's /proc/cpuinfo lacks a proper Feature field, + // but `altivec` support is indicated in the `cpu` field. + if let Ok(c) = cpuinfo::CpuInfo::new() { + enable_feature(&mut value, Feature::altivec, c.field("cpu").has("altivec")); + return value; + } + value +} diff --git a/tests/source/cfg_if/detect/os/other.rs b/tests/source/cfg_if/detect/os/other.rs new file mode 100644 index 00000000000..23e399ea790 --- /dev/null +++ b/tests/source/cfg_if/detect/os/other.rs @@ -0,0 +1,9 @@ +//! Other operating systems + +use crate::detect::Feature; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(_x: Feature) -> bool { + false +} diff --git a/tests/source/cfg_if/detect/os/x86.rs b/tests/source/cfg_if/detect/os/x86.rs new file mode 100644 index 00000000000..9257b8a4be6 --- /dev/null +++ b/tests/source/cfg_if/detect/os/x86.rs @@ -0,0 +1,375 @@ +//! x86 run-time feature detection is OS independent. + +#[cfg(target_arch = "x86")] +use crate::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use crate::arch::x86_64::*; + +use crate::mem; + +use crate::detect::{Feature, cache, bit}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Run-time feature detection on x86 works by using the CPUID instruction. +/// +/// The [CPUID Wikipedia page][wiki_cpuid] contains +/// all the information about which flags to set to query which values, and in +/// which registers these are reported. +/// +/// The definitive references are: +/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2: +/// Instruction Set Reference, A-Z][intel64_ref]. +/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and +/// System Instructions][amd64_ref]. +/// +/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID +/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf +/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf +#[allow(clippy::similar_names)] +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + + // If the x86 CPU does not support the CPUID instruction then it is too + // old to support any of the currently-detectable features. + if !has_cpuid() { + return value; + } + + // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU + // has `cpuid` support. + + // 0. EAX = 0: Basic Information: + // - EAX returns the "Highest Function Parameter", that is, the maximum + // leaf value for subsequent calls of `cpuinfo` in range [0, + // 0x8000_0000]. - The vendor ID is stored in 12 u8 ascii chars, + // returned in EBX, EDX, and ECX (in that order): + let (max_basic_leaf, vendor_id) = unsafe { + let CpuidResult { + eax: max_basic_leaf, + ebx, + ecx, + edx, + } = __cpuid(0); + let vendor_id: [[u8; 4]; 3] = [ + mem::transmute(ebx), + mem::transmute(edx), + mem::transmute(ecx), + ]; + let vendor_id: [u8; 12] = mem::transmute(vendor_id); + (max_basic_leaf, vendor_id) + }; + + if max_basic_leaf < 1 { + // Earlier Intel 486, CPUID not implemented + return value; + } + + // EAX = 1, ECX = 0: Queries "Processor Info and Feature Bits"; + // Contains information about most x86 features. + let CpuidResult { + ecx: proc_info_ecx, + edx: proc_info_edx, + .. + } = unsafe { __cpuid(0x0000_0001_u32) }; + + // EAX = 7, ECX = 0: Queries "Extended Features"; + // Contains information about bmi,bmi2, and avx2 support. + let (extended_features_ebx, extended_features_ecx) = if max_basic_leaf >= 7 + { + let CpuidResult { ebx, ecx, .. } = unsafe { __cpuid(0x0000_0007_u32) }; + (ebx, ecx) + } else { + (0, 0) // CPUID does not support "Extended Features" + }; + + // EAX = 0x8000_0000, ECX = 0: Get Highest Extended Function Supported + // - EAX returns the max leaf value for extended information, that is, + // `cpuid` calls in range [0x8000_0000; u32::MAX]: + let CpuidResult { + eax: extended_max_basic_leaf, + .. + } = unsafe { __cpuid(0x8000_0000_u32) }; + + // EAX = 0x8000_0001, ECX=0: Queries "Extended Processor Info and Feature + // Bits" + let extended_proc_info_ecx = if extended_max_basic_leaf >= 1 { + let CpuidResult { ecx, .. } = unsafe { __cpuid(0x8000_0001_u32) }; + ecx + } else { + 0 + }; + + { + // borrows value till the end of this scope: + let mut enable = |r, rb, f| { + if bit::test(r as usize, rb) { + value.set(f as u32); + } + }; + + enable(proc_info_ecx, 0, Feature::sse3); + enable(proc_info_ecx, 1, Feature::pclmulqdq); + enable(proc_info_ecx, 9, Feature::ssse3); + enable(proc_info_ecx, 13, Feature::cmpxchg16b); + enable(proc_info_ecx, 19, Feature::sse4_1); + enable(proc_info_ecx, 20, Feature::sse4_2); + enable(proc_info_ecx, 23, Feature::popcnt); + enable(proc_info_ecx, 25, Feature::aes); + enable(proc_info_ecx, 29, Feature::f16c); + enable(proc_info_ecx, 30, Feature::rdrand); + enable(extended_features_ebx, 18, Feature::rdseed); + enable(extended_features_ebx, 19, Feature::adx); + enable(extended_features_ebx, 11, Feature::rtm); + enable(proc_info_edx, 4, Feature::tsc); + enable(proc_info_edx, 23, Feature::mmx); + enable(proc_info_edx, 24, Feature::fxsr); + enable(proc_info_edx, 25, Feature::sse); + enable(proc_info_edx, 26, Feature::sse2); + enable(extended_features_ebx, 29, Feature::sha); + + enable(extended_features_ebx, 3, Feature::bmi); + enable(extended_features_ebx, 8, Feature::bmi2); + + // `XSAVE` and `AVX` support: + let cpu_xsave = bit::test(proc_info_ecx as usize, 26); + if cpu_xsave { + // 0. Here the CPU supports `XSAVE`. + + // 1. Detect `OSXSAVE`, that is, whether the OS is AVX enabled and + // supports saving the state of the AVX/AVX2 vector registers on + // context-switches, see: + // + // - [intel: is avx enabled?][is_avx_enabled], + // - [mozilla: sse.cpp][mozilla_sse_cpp]. + // + // [is_avx_enabled]: https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled + // [mozilla_sse_cpp]: https://hg.mozilla.org/mozilla-central/file/64bab5cbb9b6/mozglue/build/SSE.cpp#l190 + let cpu_osxsave = bit::test(proc_info_ecx as usize, 27); + + if cpu_osxsave { + // 2. The OS must have signaled the CPU that it supports saving and + // restoring the: + // + // * SSE -> `XCR0.SSE[1]` + // * AVX -> `XCR0.AVX[2]` + // * AVX-512 -> `XCR0.AVX-512[7:5]`. + // + // by setting the corresponding bits of `XCR0` to `1`. + // + // This is safe because the CPU supports `xsave` + // and the OS has set `osxsave`. + let xcr0 = unsafe { _xgetbv(0) }; + // Test `XCR0.SSE[1]` and `XCR0.AVX[2]` with the mask `0b110 == 6`: + let os_avx_support = xcr0 & 6 == 6; + // Test `XCR0.AVX-512[7:5]` with the mask `0b1110_0000 == 224`: + let os_avx512_support = xcr0 & 224 == 224; + + // Only if the OS and the CPU support saving/restoring the AVX + // registers we enable `xsave` support: + if os_avx_support { + // See "13.3 ENABLING THE XSAVE FEATURE SET AND XSAVE-ENABLED + // FEATURES" in the "Intel® 64 and IA-32 Architectures Software + // Developer’s Manual, Volume 1: Basic Architecture": + // + // "Software enables the XSAVE feature set by setting + // CR4.OSXSAVE[bit 18] to 1 (e.g., with the MOV to CR4 + // instruction). If this bit is 0, execution of any of XGETBV, + // XRSTOR, XRSTORS, XSAVE, XSAVEC, XSAVEOPT, XSAVES, and XSETBV + // causes an invalid-opcode exception (#UD)" + // + enable(proc_info_ecx, 26, Feature::xsave); + + // For `xsaveopt`, `xsavec`, and `xsaves` we need to query: + // Processor Extended State Enumeration Sub-leaf (EAX = 0DH, + // ECX = 1): + if max_basic_leaf >= 0xd { + let CpuidResult { + eax: proc_extended_state1_eax, + .. + } = unsafe { __cpuid_count(0xd_u32, 1) }; + enable(proc_extended_state1_eax, 0, Feature::xsaveopt); + enable(proc_extended_state1_eax, 1, Feature::xsavec); + enable(proc_extended_state1_eax, 3, Feature::xsaves); + } + + // FMA (uses 256-bit wide registers): + enable(proc_info_ecx, 12, Feature::fma); + + // And AVX/AVX2: + enable(proc_info_ecx, 28, Feature::avx); + enable(extended_features_ebx, 5, Feature::avx2); + + // For AVX-512 the OS also needs to support saving/restoring + // the extended state, only then we enable AVX-512 support: + if os_avx512_support { + enable(extended_features_ebx, 16, Feature::avx512f); + enable(extended_features_ebx, 17, Feature::avx512dq); + enable(extended_features_ebx, 21, Feature::avx512_ifma); + enable(extended_features_ebx, 26, Feature::avx512pf); + enable(extended_features_ebx, 27, Feature::avx512er); + enable(extended_features_ebx, 28, Feature::avx512cd); + enable(extended_features_ebx, 30, Feature::avx512bw); + enable(extended_features_ebx, 31, Feature::avx512vl); + enable(extended_features_ecx, 1, Feature::avx512_vbmi); + enable( + extended_features_ecx, + 14, + Feature::avx512_vpopcntdq, + ); + } + } + } + } + + // This detects ABM on AMD CPUs and LZCNT on Intel CPUs. + // On intel CPUs with popcnt, lzcnt implements the + // "missing part" of ABM, so we map both to the same + // internal feature. + // + // The `is_x86_feature_detected!("lzcnt")` macro then + // internally maps to Feature::abm. + enable(extended_proc_info_ecx, 5, Feature::abm); + // As Hygon Dhyana originates from AMD technology and shares most of the architecture with + // AMD's family 17h, but with different CPU Vendor ID("HygonGenuine")/Family series + // number(Family 18h). + // + // For CPUID feature bits, Hygon Dhyana(family 18h) share the same definition with AMD + // family 17h. + // + // Related AMD CPUID specification is https://www.amd.com/system/files/TechDocs/25481.pdf. + // Related Hygon kernel patch can be found on + // http://lkml.kernel.org/r/5ce86123a7b9dad925ac583d88d2f921040e859b.1538583282.git.puwen@hygon.cn + if vendor_id == *b"AuthenticAMD" || vendor_id == *b"HygonGenuine" { + // These features are available on AMD arch CPUs: + enable(extended_proc_info_ecx, 6, Feature::sse4a); + enable(extended_proc_info_ecx, 21, Feature::tbm); + } + } + + value +} + +#[cfg(test)] +mod tests { + extern crate cupid; + + #[test] + fn dump() { + println!("aes: {:?}", is_x86_feature_detected!("aes")); + println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("rdrand: {:?}", is_x86_feature_detected!("rdrand")); + println!("rdseed: {:?}", is_x86_feature_detected!("rdseed")); + println!("tsc: {:?}", is_x86_feature_detected!("tsc")); + println!("sse: {:?}", is_x86_feature_detected!("sse")); + println!("sse2: {:?}", is_x86_feature_detected!("sse2")); + println!("sse3: {:?}", is_x86_feature_detected!("sse3")); + println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); + println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1")); + println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2")); + println!("sse4a: {:?}", is_x86_feature_detected!("sse4a")); + println!("sha: {:?}", is_x86_feature_detected!("sha")); + println!("avx: {:?}", is_x86_feature_detected!("avx")); + println!("avx2: {:?}", is_x86_feature_detected!("avx2")); + println!("avx512f {:?}", is_x86_feature_detected!("avx512f")); + println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd")); + println!("avx512er {:?}", is_x86_feature_detected!("avx512er")); + println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf")); + println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw")); + println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); + println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); + println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); + println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); + println!( + "avx512_vpopcntdq {:?}", + is_x86_feature_detected!("avx512vpopcntdq") + ); + println!("fma: {:?}", is_x86_feature_detected!("fma")); + println!("abm: {:?}", is_x86_feature_detected!("abm")); + println!("bmi: {:?}", is_x86_feature_detected!("bmi1")); + println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); + println!("tbm: {:?}", is_x86_feature_detected!("tbm")); + println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); + println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); + println!("xsave: {:?}", is_x86_feature_detected!("xsave")); + println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt")); + println!("xsaves: {:?}", is_x86_feature_detected!("xsaves")); + println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); + println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b")); + println!("adx: {:?}", is_x86_feature_detected!("adx")); + println!("rtm: {:?}", is_x86_feature_detected!("rtm")); + } + + #[test] + fn compare_with_cupid() { + let information = cupid::master().unwrap(); + assert_eq!(is_x86_feature_detected!("aes"), information.aesni()); + assert_eq!(is_x86_feature_detected!("pclmulqdq"), information.pclmulqdq()); + assert_eq!(is_x86_feature_detected!("rdrand"), information.rdrand()); + assert_eq!(is_x86_feature_detected!("rdseed"), information.rdseed()); + assert_eq!(is_x86_feature_detected!("tsc"), information.tsc()); + assert_eq!(is_x86_feature_detected!("sse"), information.sse()); + assert_eq!(is_x86_feature_detected!("sse2"), information.sse2()); + assert_eq!(is_x86_feature_detected!("sse3"), information.sse3()); + assert_eq!(is_x86_feature_detected!("ssse3"), information.ssse3()); + assert_eq!(is_x86_feature_detected!("sse4.1"), information.sse4_1()); + assert_eq!(is_x86_feature_detected!("sse4.2"), information.sse4_2()); + assert_eq!(is_x86_feature_detected!("sse4a"), information.sse4a()); + assert_eq!(is_x86_feature_detected!("sha"), information.sha()); + assert_eq!(is_x86_feature_detected!("avx"), information.avx()); + assert_eq!(is_x86_feature_detected!("avx2"), information.avx2()); + assert_eq!(is_x86_feature_detected!("avx512f"), information.avx512f()); + assert_eq!(is_x86_feature_detected!("avx512cd"), information.avx512cd()); + assert_eq!(is_x86_feature_detected!("avx512er"), information.avx512er()); + assert_eq!(is_x86_feature_detected!("avx512pf"), information.avx512pf()); + assert_eq!(is_x86_feature_detected!("avx512bw"), information.avx512bw()); + assert_eq!(is_x86_feature_detected!("avx512dq"), information.avx512dq()); + assert_eq!(is_x86_feature_detected!("avx512vl"), information.avx512vl()); + assert_eq!( + is_x86_feature_detected!("avx512ifma"), + information.avx512_ifma() + ); + assert_eq!( + is_x86_feature_detected!("avx512vbmi"), + information.avx512_vbmi() + ); + assert_eq!( + is_x86_feature_detected!("avx512vpopcntdq"), + information.avx512_vpopcntdq() + ); + assert_eq!(is_x86_feature_detected!("fma"), information.fma()); + assert_eq!(is_x86_feature_detected!("bmi1"), information.bmi1()); + assert_eq!(is_x86_feature_detected!("bmi2"), information.bmi2()); + assert_eq!(is_x86_feature_detected!("popcnt"), information.popcnt()); + assert_eq!(is_x86_feature_detected!("abm"), information.lzcnt()); + assert_eq!(is_x86_feature_detected!("tbm"), information.tbm()); + assert_eq!(is_x86_feature_detected!("lzcnt"), information.lzcnt()); + assert_eq!(is_x86_feature_detected!("xsave"), information.xsave()); + assert_eq!(is_x86_feature_detected!("xsaveopt"), information.xsaveopt()); + assert_eq!( + is_x86_feature_detected!("xsavec"), + information.xsavec_and_xrstor() + ); + assert_eq!( + is_x86_feature_detected!("xsaves"), + information.xsaves_xrstors_and_ia32_xss() + ); + assert_eq!( + is_x86_feature_detected!("cmpxchg16b"), + information.cmpxchg16b(), + ); + assert_eq!( + is_x86_feature_detected!("adx"), + information.adx(), + ); + assert_eq!( + is_x86_feature_detected!("rtm"), + information.rtm(), + ); + } +} diff --git a/tests/source/cfg_if/lib.rs b/tests/source/cfg_if/lib.rs new file mode 100644 index 00000000000..8b3bb304f1c --- /dev/null +++ b/tests/source/cfg_if/lib.rs @@ -0,0 +1,49 @@ +//! Run-time feature detection for the Rust standard library. +//! +//! To detect whether a feature is enabled in the system running the binary +//! use one of the appropriate macro for the target: +//! +//! * `x86` and `x86_64`: [`is_x86_feature_detected`] +//! * `arm`: [`is_arm_feature_detected`] +//! * `aarch64`: [`is_aarch64_feature_detected`] +//! * `mips`: [`is_mips_feature_detected`] +//! * `mips64`: [`is_mips64_feature_detected`] +//! * `powerpc`: [`is_powerpc_feature_detected`] +//! * `powerpc64`: [`is_powerpc64_feature_detected`] + +#![unstable(feature = "stdsimd", issue = "27731")] +#![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] +#![allow(clippy::shadow_reuse)] +#![deny(clippy::missing_inline_in_public_items)] +#![cfg_attr(target_os = "linux", feature(linkage))] +#![cfg_attr(all(target_os = "freebsd", target_arch = "aarch64"), feature(asm))] +#![cfg_attr(stdsimd_strict, deny(warnings))] +#![cfg_attr(test, allow(unused_imports))] +#![no_std] + +#[macro_use] +extern crate cfg_if; + +cfg_if! { + if #[cfg(feature = "std_detect_file_io")] { + #[cfg_attr(test, macro_use(println))] + extern crate std; + + #[allow(unused_imports)] + use std::{arch, fs, io, mem, sync}; + } else { + #[cfg(test)] + #[macro_use(println)] + extern crate std; + + #[allow(unused_imports)] + use core::{arch, mem, sync}; + } +} + +#[cfg(feature = "std_detect_dlsym_getauxval")] +extern crate libc; + +#[doc(hidden)] +#[unstable(feature = "stdsimd", issue = "27731")] +pub mod detect; diff --git a/tests/source/cfg_if/mod.rs b/tests/source/cfg_if/mod.rs new file mode 100644 index 00000000000..b630e7ff383 --- /dev/null +++ b/tests/source/cfg_if/mod.rs @@ -0,0 +1,5 @@ +//! `std_detect` + +#[doc(hidden)] // unstable implementation detail +#[unstable(feature = "stdsimd", issue = "27731")] +pub mod detect; diff --git a/tests/target/cfg_if/detect/arch/aarch64.rs b/tests/target/cfg_if/detect/arch/aarch64.rs new file mode 100644 index 00000000000..91c51ed89e6 --- /dev/null +++ b/tests/target/cfg_if/detect/arch/aarch64.rs @@ -0,0 +1,98 @@ +//! Aarch64 run-time features. + +/// Checks if `aarch64` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_aarch64_feature_detected { + ("neon") => { + // FIXME: this should be removed once we rename Aarch64 neon to asimd + cfg!(target_feature = "neon") || $crate::detect::check_for($crate::detect::Feature::asimd) + }; + ("asimd") => { + cfg!(target_feature = "neon") || $crate::detect::check_for($crate::detect::Feature::asimd) + }; + ("pmull") => { + cfg!(target_feature = "pmull") || $crate::detect::check_for($crate::detect::Feature::pmull) + }; + ("fp") => { + cfg!(target_feature = "fp") || $crate::detect::check_for($crate::detect::Feature::fp) + }; + ("fp16") => { + cfg!(target_feature = "fp16") || $crate::detect::check_for($crate::detect::Feature::fp16) + }; + ("sve") => { + cfg!(target_feature = "sve") || $crate::detect::check_for($crate::detect::Feature::sve) + }; + ("crc") => { + cfg!(target_feature = "crc") || $crate::detect::check_for($crate::detect::Feature::crc) + }; + ("crypto") => { + cfg!(target_feature = "crypto") + || $crate::detect::check_for($crate::detect::Feature::crypto) + }; + ("lse") => { + cfg!(target_feature = "lse") || $crate::detect::check_for($crate::detect::Feature::lse) + }; + ("rdm") => { + cfg!(target_feature = "rdm") || $crate::detect::check_for($crate::detect::Feature::rdm) + }; + ("rcpc") => { + cfg!(target_feature = "rcpc") || $crate::detect::check_for($crate::detect::Feature::rcpc) + }; + ("dotprod") => { + cfg!(target_feature = "dotprod") + || $crate::detect::check_for($crate::detect::Feature::dotprod) + }; + ("ras") => { + compile_error!("\"ras\" feature cannot be detected at run-time") + }; + ("v8.1a") => { + compile_error!("\"v8.1a\" feature cannot be detected at run-time") + }; + ("v8.2a") => { + compile_error!("\"v8.2a\" feature cannot be detected at run-time") + }; + ("v8.3a") => { + compile_error!("\"v8.3a\" feature cannot be detected at run-time") + }; + ($t:tt,) => { + is_aarch64_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown aarch64 target feature: ", $t)) + }; +} + +/// ARM Aarch64 CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// ARM Advanced SIMD (ASIMD) + asimd, + /// Polynomial Multiply + pmull, + /// Floating point support + fp, + /// Half-float support. + fp16, + /// Scalable Vector Extension (SVE) + sve, + /// CRC32 (Cyclic Redundancy Check) + crc, + /// Crypto: AES + PMULL + SHA1 + SHA2 + crypto, + /// Atomics (Large System Extension) + lse, + /// Rounding Double Multiply (ASIMDRDM) + rdm, + /// Release consistent Processor consistent (RcPc) + rcpc, + /// Vector Dot-Product (ASIMDDP) + dotprod, +} diff --git a/tests/target/cfg_if/detect/arch/arm.rs b/tests/target/cfg_if/detect/arch/arm.rs new file mode 100644 index 00000000000..90c61fed8ac --- /dev/null +++ b/tests/target/cfg_if/detect/arch/arm.rs @@ -0,0 +1,47 @@ +//! Run-time feature detection on ARM Aarch32. + +/// Checks if `arm` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_arm_feature_detected { + ("neon") => { + cfg!(target_feature = "neon") || $crate::detect::check_for($crate::detect::Feature::neon) + }; + ("pmull") => { + cfg!(target_feature = "pmull") || $crate::detect::check_for($crate::detect::Feature::pmull) + }; + ("v7") => { + compile_error!("\"v7\" feature cannot be detected at run-time") + }; + ("vfp2") => { + compile_error!("\"vfp2\" feature cannot be detected at run-time") + }; + ("vfp3") => { + compile_error!("\"vfp3\" feature cannot be detected at run-time") + }; + ("vfp4") => { + compile_error!("\"vfp4\" feature cannot be detected at run-time") + }; + ($t:tt,) => { + is_arm_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown arm target feature: ", $t)) + }; +} + +/// ARM CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// ARM Advanced SIMD (NEON) - Aarch32 + neon, + /// Polynomial Multiply + pmull, +} diff --git a/tests/target/cfg_if/detect/arch/mips.rs b/tests/target/cfg_if/detect/arch/mips.rs new file mode 100644 index 00000000000..2397a090602 --- /dev/null +++ b/tests/target/cfg_if/detect/arch/mips.rs @@ -0,0 +1,30 @@ +//! Run-time feature detection on MIPS. + +/// Checks if `mips` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_mips_feature_detected { + ("msa") => { + cfg!(target_feature = "msa") || $crate::detect::check_for($crate::detect::Feature::msa) + }; + ($t:tt,) => { + is_mips_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown mips target feature: ", $t)) + }; +} + +/// MIPS CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// MIPS SIMD Architecture (MSA) + msa, +} diff --git a/tests/target/cfg_if/detect/arch/mips64.rs b/tests/target/cfg_if/detect/arch/mips64.rs new file mode 100644 index 00000000000..d378defc5df --- /dev/null +++ b/tests/target/cfg_if/detect/arch/mips64.rs @@ -0,0 +1,30 @@ +//! Run-time feature detection on MIPS64. + +/// Checks if `mips64` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_mips64_feature_detected { + ("msa") => { + cfg!(target_feature = "msa") || $crate::detect::check_for($crate::detect::Feature::msa) + }; + ($t:tt,) => { + is_mips64_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown mips64 target feature: ", $t)) + }; +} + +/// MIPS64 CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// MIPS SIMD Architecture (MSA) + msa, +} diff --git a/tests/target/cfg_if/detect/arch/powerpc.rs b/tests/target/cfg_if/detect/arch/powerpc.rs new file mode 100644 index 00000000000..e7a9daac688 --- /dev/null +++ b/tests/target/cfg_if/detect/arch/powerpc.rs @@ -0,0 +1,42 @@ +//! Run-time feature detection on PowerPC. + +/// Checks if `powerpc` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_powerpc_feature_detected { + ("altivec") => { + cfg!(target_feature = "altivec") + || $crate::detect::check_for($crate::detect::Feature::altivec) + }; + ("vsx") => { + cfg!(target_feature = "vsx") || $crate::detect::check_for($crate::detect::Feature::vsx) + }; + ("power8") => { + cfg!(target_feature = "power8") + || $crate::detect::check_for($crate::detect::Feature::power8) + }; + ($t:tt,) => { + is_powerpc_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown powerpc target feature: ", $t)) + }; +} + +/// PowerPC CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// Altivec + altivec, + /// VSX + vsx, + /// Power8 + power8, +} diff --git a/tests/target/cfg_if/detect/arch/powerpc64.rs b/tests/target/cfg_if/detect/arch/powerpc64.rs new file mode 100644 index 00000000000..c102202695e --- /dev/null +++ b/tests/target/cfg_if/detect/arch/powerpc64.rs @@ -0,0 +1,42 @@ +//! Run-time feature detection on PowerPC64. + +/// Checks if `powerpc64` feature is enabled. +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_powerpc64_feature_detected { + ("altivec") => { + cfg!(target_feature = "altivec") + || $crate::detect::check_for($crate::detect::Feature::altivec) + }; + ("vsx") => { + cfg!(target_feature = "vsx") || $crate::detect::check_for($crate::detect::Feature::vsx) + }; + ("power8") => { + cfg!(target_feature = "power8") + || $crate::detect::check_for($crate::detect::Feature::power8) + }; + ($t:tt,) => { + is_powerpc64_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown powerpc64 target feature: ", $t)) + }; +} + +/// PowerPC64 CPU Feature enum. Each variant denotes a position in a bitset +/// for a particular feature. +/// +/// PLEASE: do not use this, it is an implementation detail subject to change. +#[doc(hidden)] +#[allow(non_camel_case_types)] +#[repr(u8)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// Altivec + altivec, + /// VSX + vsx, + /// Power8 + power8, +} diff --git a/tests/target/cfg_if/detect/arch/x86.rs b/tests/target/cfg_if/detect/arch/x86.rs new file mode 100644 index 00000000000..9219a4a577f --- /dev/null +++ b/tests/target/cfg_if/detect/arch/x86.rs @@ -0,0 +1,333 @@ +//! This module implements minimal run-time feature detection for x86. +//! +//! The features are detected using the `detect_features` function below. +//! This function uses the CPUID instruction to read the feature flags from the +//! CPU and encodes them in an `usize` where each bit position represents +//! whether a feature is available (bit is set) or unavaiable (bit is cleared). +//! +//! The enum `Feature` is used to map bit positions to feature names, and the +//! the `__crate::detect::check_for!` macro is used to map string literals (e.g., +//! "avx") to these bit positions (e.g., `Feature::avx`). +//! +//! The run-time feature detection is performed by the +//! `__crate::detect::check_for(Feature) -> bool` function. On its first call, +//! this functions queries the CPU for the available features and stores them +//! in a global `AtomicUsize` variable. The query is performed by just checking +//! whether the feature bit in this global variable is set or cleared. + +/// A macro to test at *runtime* whether a CPU feature is available on +/// x86/x86-64 platforms. +/// +/// This macro is provided in the standard library and will detect at runtime +/// whether the specified CPU feature is detected. This does **not** resolve at +/// compile time unless the specified feature is already enabled for the entire +/// crate. Runtime detection currently relies mostly on the `cpuid` instruction. +/// +/// This macro only takes one argument which is a string literal of the feature +/// being tested for. The feature names supported are the lowercase versions of +/// the ones defined by Intel in [their documentation][docs]. +/// +/// ## Supported arguments +/// +/// This macro supports the same names that `#[target_feature]` supports. Unlike +/// `#[target_feature]`, however, this macro does not support names separated +/// with a comma. Instead testing for multiple features must be done through +/// separate macro invocations for now. +/// +/// Supported arguments are: +/// +/// * `"aes"` +/// * `"pclmulqdq"` +/// * `"rdrand"` +/// * `"rdseed"` +/// * `"tsc"` +/// * `"mmx"` +/// * `"sse"` +/// * `"sse2"` +/// * `"sse3"` +/// * `"ssse3"` +/// * `"sse4.1"` +/// * `"sse4.2"` +/// * `"sse4a"` +/// * `"sha"` +/// * `"avx"` +/// * `"avx2"` +/// * `"avx512f"` +/// * `"avx512cd"` +/// * `"avx512er"` +/// * `"avx512pf"` +/// * `"avx512bw"` +/// * `"avx512dq"` +/// * `"avx512vl"` +/// * `"avx512ifma"` +/// * `"avx512vbmi"` +/// * `"avx512vpopcntdq"` +/// * `"f16c"` +/// * `"fma"` +/// * `"bmi1"` +/// * `"bmi2"` +/// * `"abm"` +/// * `"lzcnt"` +/// * `"tbm"` +/// * `"popcnt"` +/// * `"fxsr"` +/// * `"xsave"` +/// * `"xsaveopt"` +/// * `"xsaves"` +/// * `"xsavec"` +/// * `"adx"` +/// * `"rtm"` +/// +/// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide +#[macro_export] +#[stable(feature = "simd_x86", since = "1.27.0")] +#[allow_internal_unstable(stdsimd_internal, stdsimd)] +macro_rules! is_x86_feature_detected { + ("aes") => { + cfg!(target_feature = "aes") || $crate::detect::check_for($crate::detect::Feature::aes) + }; + ("pclmulqdq") => { + cfg!(target_feature = "pclmulqdq") + || $crate::detect::check_for($crate::detect::Feature::pclmulqdq) + }; + ("rdrand") => { + cfg!(target_feature = "rdrand") + || $crate::detect::check_for($crate::detect::Feature::rdrand) + }; + ("rdseed") => { + cfg!(target_feature = "rdseed") + || $crate::detect::check_for($crate::detect::Feature::rdseed) + }; + ("tsc") => { + cfg!(target_feature = "tsc") || $crate::detect::check_for($crate::detect::Feature::tsc) + }; + ("mmx") => { + cfg!(target_feature = "mmx") || $crate::detect::check_for($crate::detect::Feature::mmx) + }; + ("sse") => { + cfg!(target_feature = "sse") || $crate::detect::check_for($crate::detect::Feature::sse) + }; + ("sse2") => { + cfg!(target_feature = "sse2") || $crate::detect::check_for($crate::detect::Feature::sse2) + }; + ("sse3") => { + cfg!(target_feature = "sse3") || $crate::detect::check_for($crate::detect::Feature::sse3) + }; + ("ssse3") => { + cfg!(target_feature = "ssse3") || $crate::detect::check_for($crate::detect::Feature::ssse3) + }; + ("sse4.1") => { + cfg!(target_feature = "sse4.1") + || $crate::detect::check_for($crate::detect::Feature::sse4_1) + }; + ("sse4.2") => { + cfg!(target_feature = "sse4.2") + || $crate::detect::check_for($crate::detect::Feature::sse4_2) + }; + ("sse4a") => { + cfg!(target_feature = "sse4a") || $crate::detect::check_for($crate::detect::Feature::sse4a) + }; + ("sha") => { + cfg!(target_feature = "sha") || $crate::detect::check_for($crate::detect::Feature::sha) + }; + ("avx") => { + cfg!(target_feature = "avx") || $crate::detect::check_for($crate::detect::Feature::avx) + }; + ("avx2") => { + cfg!(target_feature = "avx2") || $crate::detect::check_for($crate::detect::Feature::avx2) + }; + ("avx512f") => { + cfg!(target_feature = "avx512f") + || $crate::detect::check_for($crate::detect::Feature::avx512f) + }; + ("avx512cd") => { + cfg!(target_feature = "avx512cd") + || $crate::detect::check_for($crate::detect::Feature::avx512cd) + }; + ("avx512er") => { + cfg!(target_feature = "avx512er") + || $crate::detect::check_for($crate::detect::Feature::avx512er) + }; + ("avx512pf") => { + cfg!(target_feature = "avx512pf") + || $crate::detect::check_for($crate::detect::Feature::avx512pf) + }; + ("avx512bw") => { + cfg!(target_feature = "avx512bw") + || $crate::detect::check_for($crate::detect::Feature::avx512bw) + }; + ("avx512dq") => { + cfg!(target_feature = "avx512dq") + || $crate::detect::check_for($crate::detect::Feature::avx512dq) + }; + ("avx512vl") => { + cfg!(target_Feature = "avx512vl") + || $crate::detect::check_for($crate::detect::Feature::avx512vl) + }; + ("avx512ifma") => { + cfg!(target_feature = "avx512ifma") + || $crate::detect::check_for($crate::detect::Feature::avx512_ifma) + }; + ("avx512vbmi") => { + cfg!(target_feature = "avx512vbmi") + || $crate::detect::check_for($crate::detect::Feature::avx512_vbmi) + }; + ("avx512vpopcntdq") => { + cfg!(target_feature = "avx512vpopcntdq") + || $crate::detect::check_for($crate::detect::Feature::avx512_vpopcntdq) + }; + ("f16c") => { + cfg!(target_feature = "f16c") || $crate::detect::check_for($crate::detect::Feature::f16c) + }; + ("fma") => { + cfg!(target_feature = "fma") || $crate::detect::check_for($crate::detect::Feature::fma) + }; + ("bmi1") => { + cfg!(target_feature = "bmi1") || $crate::detect::check_for($crate::detect::Feature::bmi) + }; + ("bmi2") => { + cfg!(target_feature = "bmi2") || $crate::detect::check_for($crate::detect::Feature::bmi2) + }; + ("abm") => { + cfg!(target_feature = "abm") || $crate::detect::check_for($crate::detect::Feature::abm) + }; + ("lzcnt") => { + cfg!(target_feature = "lzcnt") || $crate::detect::check_for($crate::detect::Feature::abm) + }; + ("tbm") => { + cfg!(target_feature = "tbm") || $crate::detect::check_for($crate::detect::Feature::tbm) + }; + ("popcnt") => { + cfg!(target_feature = "popcnt") + || $crate::detect::check_for($crate::detect::Feature::popcnt) + }; + ("fxsr") => { + cfg!(target_feature = "fxsr") || $crate::detect::check_for($crate::detect::Feature::fxsr) + }; + ("xsave") => { + cfg!(target_feature = "xsave") || $crate::detect::check_for($crate::detect::Feature::xsave) + }; + ("xsaveopt") => { + cfg!(target_feature = "xsaveopt") + || $crate::detect::check_for($crate::detect::Feature::xsaveopt) + }; + ("xsaves") => { + cfg!(target_feature = "xsaves") + || $crate::detect::check_for($crate::detect::Feature::xsaves) + }; + ("xsavec") => { + cfg!(target_feature = "xsavec") + || $crate::detect::check_for($crate::detect::Feature::xsavec) + }; + ("cmpxchg16b") => { + cfg!(target_feature = "cmpxchg16b") + || $crate::detect::check_for($crate::detect::Feature::cmpxchg16b) + }; + ("adx") => { + cfg!(target_feature = "adx") || $crate::detect::check_for($crate::detect::Feature::adx) + }; + ("rtm") => { + cfg!(target_feature = "rtm") || $crate::detect::check_for($crate::detect::Feature::rtm) + }; + ($t:tt,) => { + is_x86_feature_detected!($t); + }; + ($t:tt) => { + compile_error!(concat!("unknown target feature: ", $t)) + }; +} + +/// X86 CPU Feature enum. Each variant denotes a position in a bitset for a +/// particular feature. +/// +/// This is an unstable implementation detail subject to change. +#[allow(non_camel_case_types)] +#[repr(u8)] +#[doc(hidden)] +#[unstable(feature = "stdsimd_internal", issue = "0")] +pub enum Feature { + /// AES (Advanced Encryption Standard New Instructions AES-NI) + aes, + /// CLMUL (Carry-less Multiplication) + pclmulqdq, + /// RDRAND + rdrand, + /// RDSEED + rdseed, + /// TSC (Time Stamp Counter) + tsc, + /// MMX + mmx, + /// SSE (Streaming SIMD Extensions) + sse, + /// SSE2 (Streaming SIMD Extensions 2) + sse2, + /// SSE3 (Streaming SIMD Extensions 3) + sse3, + /// SSSE3 (Supplemental Streaming SIMD Extensions 3) + ssse3, + /// SSE4.1 (Streaming SIMD Extensions 4.1) + sse4_1, + /// SSE4.2 (Streaming SIMD Extensions 4.2) + sse4_2, + /// SSE4a (Streaming SIMD Extensions 4a) + sse4a, + /// SHA + sha, + /// AVX (Advanced Vector Extensions) + avx, + /// AVX2 (Advanced Vector Extensions 2) + avx2, + /// AVX-512 F (Foundation) + avx512f, + /// AVX-512 CD (Conflict Detection Instructions) + avx512cd, + /// AVX-512 ER (Exponential and Reciprocal Instructions) + avx512er, + /// AVX-512 PF (Prefetch Instructions) + avx512pf, + /// AVX-512 BW (Byte and Word Instructions) + avx512bw, + /// AVX-512 DQ (Doubleword and Quadword) + avx512dq, + /// AVX-512 VL (Vector Length Extensions) + avx512vl, + /// AVX-512 IFMA (Integer Fused Multiply Add) + avx512_ifma, + /// AVX-512 VBMI (Vector Byte Manipulation Instructions) + avx512_vbmi, + /// AVX-512 VPOPCNTDQ (Vector Population Count Doubleword and + /// Quadword) + avx512_vpopcntdq, + /// F16C (Conversions between IEEE-754 `binary16` and `binary32` formats) + f16c, + /// FMA (Fused Multiply Add) + fma, + /// BMI1 (Bit Manipulation Instructions 1) + bmi, + /// BMI1 (Bit Manipulation Instructions 2) + bmi2, + /// ABM (Advanced Bit Manipulation) on AMD / LZCNT (Leading Zero + /// Count) on Intel + abm, + /// TBM (Trailing Bit Manipulation) + tbm, + /// POPCNT (Population Count) + popcnt, + /// FXSR (Floating-point context fast save and restor) + fxsr, + /// XSAVE (Save Processor Extended States) + xsave, + /// XSAVEOPT (Save Processor Extended States Optimized) + xsaveopt, + /// XSAVES (Save Processor Extended States Supervisor) + xsaves, + /// XSAVEC (Save Processor Extended States Compacted) + xsavec, + /// CMPXCH16B, a 16-byte compare-and-swap instruction + cmpxchg16b, + /// ADX, Intel ADX (Multi-Precision Add-Carry Instruction Extensions) + adx, + /// RTM, Intel (Restricted Transactional Memory) + rtm, +} diff --git a/tests/target/cfg_if/detect/bit.rs b/tests/target/cfg_if/detect/bit.rs new file mode 100644 index 00000000000..578f0b16b74 --- /dev/null +++ b/tests/target/cfg_if/detect/bit.rs @@ -0,0 +1,9 @@ +//! Bit manipulation utilities. + +/// Tests the `bit` of `x`. +#[allow(dead_code)] +#[inline] +pub(crate) fn test(x: usize, bit: u32) -> bool { + debug_assert!(bit < 32, "bit index out-of-bounds"); + x & (1 << bit) != 0 +} diff --git a/tests/target/cfg_if/detect/cache.rs b/tests/target/cfg_if/detect/cache.rs new file mode 100644 index 00000000000..92bc4b58d16 --- /dev/null +++ b/tests/target/cfg_if/detect/cache.rs @@ -0,0 +1,164 @@ +//! Caches run-time feature detection so that it only needs to be computed +//! once. + +#![allow(dead_code)] // not used on all platforms + +use crate::sync::atomic::Ordering; + +#[cfg(target_pointer_width = "64")] +use crate::sync::atomic::AtomicU64; + +#[cfg(target_pointer_width = "32")] +use crate::sync::atomic::AtomicU32; + +/// Sets the `bit` of `x`. +#[inline] +const fn set_bit(x: u64, bit: u32) -> u64 { + x | 1 << bit +} + +/// Tests the `bit` of `x`. +#[inline] +const fn test_bit(x: u64, bit: u32) -> bool { + x & (1 << bit) != 0 +} + +/// Maximum number of features that can be cached. +const CACHE_CAPACITY: u32 = 63; + +/// This type is used to initialize the cache +#[derive(Copy, Clone)] +pub(crate) struct Initializer(u64); + +#[allow(clippy::use_self)] +impl Default for Initializer { + fn default() -> Self { + Initializer(0) + } +} + +impl Initializer { + /// Tests the `bit` of the cache. + #[allow(dead_code)] + #[inline] + pub(crate) fn test(self, bit: u32) -> bool { + // FIXME: this way of making sure that the cache is large enough is + // brittle. + debug_assert!( + bit < CACHE_CAPACITY, + "too many features, time to increase the cache size!" + ); + test_bit(self.0, bit) + } + + /// Sets the `bit` of the cache. + #[inline] + pub(crate) fn set(&mut self, bit: u32) { + // FIXME: this way of making sure that the cache is large enough is + // brittle. + debug_assert!( + bit < CACHE_CAPACITY, + "too many features, time to increase the cache size!" + ); + let v = self.0; + self.0 = set_bit(v, bit); + } +} + +/// This global variable is a cache of the features supported by the CPU. +static CACHE: Cache = Cache::uninitialized(); + +/// Feature cache with capacity for `CACHE_CAPACITY` features. +/// +/// Note: the last feature bit is used to represent an +/// uninitialized cache. +#[cfg(target_pointer_width = "64")] +struct Cache(AtomicU64); + +#[cfg(target_pointer_width = "64")] +#[allow(clippy::use_self)] +impl Cache { + /// Creates an uninitialized cache. + #[allow(clippy::declare_interior_mutable_const)] + const fn uninitialized() -> Self { + Cache(AtomicU64::new(u64::max_value())) + } + /// Is the cache uninitialized? + #[inline] + pub(crate) fn is_uninitialized(&self) -> bool { + self.0.load(Ordering::Relaxed) == u64::max_value() + } + + /// Is the `bit` in the cache set? + #[inline] + pub(crate) fn test(&self, bit: u32) -> bool { + test_bit(CACHE.0.load(Ordering::Relaxed), bit) + } + + /// Initializes the cache. + #[inline] + pub(crate) fn initialize(&self, value: Initializer) { + self.0.store(value.0, Ordering::Relaxed); + } +} + +/// Feature cache with capacity for `CACHE_CAPACITY` features. +/// +/// Note: the last feature bit is used to represent an +/// uninitialized cache. +#[cfg(target_pointer_width = "32")] +struct Cache(AtomicU32, AtomicU32); + +#[cfg(target_pointer_width = "32")] +impl Cache { + /// Creates an uninitialized cache. + const fn uninitialized() -> Self { + Cache( + AtomicU32::new(u32::max_value()), + AtomicU32::new(u32::max_value()), + ) + } + /// Is the cache uninitialized? + #[inline] + pub(crate) fn is_uninitialized(&self) -> bool { + self.1.load(Ordering::Relaxed) == u32::max_value() + } + + /// Is the `bit` in the cache set? + #[inline] + pub(crate) fn test(&self, bit: u32) -> bool { + if bit < 32 { + test_bit(CACHE.0.load(Ordering::Relaxed) as u64, bit) + } else { + test_bit(CACHE.1.load(Ordering::Relaxed) as u64, bit - 32) + } + } + + /// Initializes the cache. + #[inline] + pub(crate) fn initialize(&self, value: Initializer) { + let lo: u32 = value.0 as u32; + let hi: u32 = (value.0 >> 32) as u32; + self.0.store(lo, Ordering::Relaxed); + self.1.store(hi, Ordering::Relaxed); + } +} + +/// Tests the `bit` of the storage. If the storage has not been initialized, +/// initializes it with the result of `f()`. +/// +/// On its first invocation, it detects the CPU features and caches them in the +/// `CACHE` global variable as an `AtomicU64`. +/// +/// It uses the `Feature` variant to index into this variable as a bitset. If +/// the bit is set, the feature is enabled, and otherwise it is disabled. +#[inline] +pub(crate) fn test(bit: u32, f: F) -> bool +where + F: FnOnce() -> Initializer, +{ + if CACHE.is_uninitialized() { + CACHE.initialize(f()); + } + CACHE.test(bit) +} diff --git a/tests/target/cfg_if/detect/error_macros.rs b/tests/target/cfg_if/detect/error_macros.rs new file mode 100644 index 00000000000..6769757ed93 --- /dev/null +++ b/tests/target/cfg_if/detect/error_macros.rs @@ -0,0 +1,150 @@ +//! The `is_{target_arch}_feature_detected!` macro are only available on their +//! architecture. These macros provide a better error messages when the user +//! attempts to call them in a different architecture. + +/// Prevents compilation if `is_x86_feature_detected` is used somewhere +/// else than `x86` and `x86_64` targets. +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_x86_feature_detected { + ($t: tt) => { + compile_error!( + r#" + is_x86_feature_detected can only be used on x86 and x86_64 targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + if is_x86_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_arm_feature_detected` is used somewhere else +/// than `ARM` targets. +#[cfg(not(target_arch = "arm"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_arm_feature_detected { + ($t:tt) => { + compile_error!( + r#" + is_arm_feature_detected can only be used on ARM targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "arm")] { + if is_arm_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_aarch64_feature_detected` is used somewhere else +/// than `aarch64` targets. +#[cfg(not(target_arch = "aarch64"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_aarch64_feature_detected { + ($t: tt) => { + compile_error!( + r#" + is_aarch64_feature_detected can only be used on AArch64 targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "aarch64")] { + if is_aarch64_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_powerpc_feature_detected` is used somewhere else +/// than `PowerPC` targets. +#[cfg(not(target_arch = "powerpc"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_powerpc_feature_detected { + ($t:tt) => { + compile_error!( + r#" +is_powerpc_feature_detected can only be used on PowerPC targets. +You can prevent it from being used in other architectures by +guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "powerpc")] { + if is_powerpc_feature_detected(...) { ... } + } +"# + ) + }; +} + +/// Prevents compilation if `is_powerpc64_feature_detected` is used somewhere +/// else than `PowerPC64` targets. +#[cfg(not(target_arch = "powerpc64"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_powerpc64_feature_detected { + ($t:tt) => { + compile_error!( + r#" +is_powerpc64_feature_detected can only be used on PowerPC64 targets. +You can prevent it from being used in other architectures by +guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "powerpc64")] { + if is_powerpc64_feature_detected(...) { ... } + } +"# + ) + }; +} + +/// Prevents compilation if `is_mips_feature_detected` is used somewhere else +/// than `MIPS` targets. +#[cfg(not(target_arch = "mips"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_mips_feature_detected { + ($t:tt) => { + compile_error!( + r#" + is_mips_feature_detected can only be used on MIPS targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "mips")] { + if is_mips_feature_detected(...) { ... } + } + "# + ) + }; +} + +/// Prevents compilation if `is_mips64_feature_detected` is used somewhere else +/// than `MIPS64` targets. +#[cfg(not(target_arch = "mips64"))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_mips64_feature_detected { + ($t:tt) => { + compile_error!( + r#" + is_mips64_feature_detected can only be used on MIPS64 targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(target_arch = "mips64")] { + if is_mips64_feature_detected(...) { ... } + } + "# + ) + }; +} diff --git a/tests/target/cfg_if/detect/mod.rs b/tests/target/cfg_if/detect/mod.rs new file mode 100644 index 00000000000..f446e88eedc --- /dev/null +++ b/tests/target/cfg_if/detect/mod.rs @@ -0,0 +1,85 @@ +//! This module implements run-time feature detection. +//! +//! The `is_{arch}_feature_detected!("feature-name")` macros take the name of a +//! feature as a string-literal, and return a boolean indicating whether the +//! feature is enabled at run-time or not. +//! +//! These macros do two things: +//! * map the string-literal into an integer stored as a `Feature` enum, +//! * call a `os::check_for(x: Feature)` function that returns `true` if the +//! feature is enabled. +//! +//! The `Feature` enums are also implemented in the `arch/{target_arch}.rs` +//! modules. +//! +//! The `check_for` functions are, in general, Operating System dependent. Most +//! architectures do not allow user-space programs to query the feature bits +//! due to security concerns (x86 is the big exception). These functions are +//! implemented in the `os/{target_os}.rs` modules. + +#[macro_use] +mod error_macros; + +cfg_if! { + if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + #[path = "arch/x86.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "arm")] { + #[path = "arch/arm.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "aarch64")] { + #[path = "arch/aarch64.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "powerpc")] { + #[path = "arch/powerpc.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "powerpc64")] { + #[path = "arch/powerpc64.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "mips")] { + #[path = "arch/mips.rs"] + #[macro_use] + mod arch; + } else if #[cfg(target_arch = "mips64")] { + #[path = "arch/mips64.rs"] + #[macro_use] + mod arch; + } else { + // Unimplemented architecture: + mod arch { + pub enum Feature { + Null + } + } + } +} +pub use self::arch::Feature; + +mod bit; +mod cache; + +cfg_if! { + if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { + // On x86/x86_64 no OS specific functionality is required. + #[path = "os/x86.rs"] + mod os; + } else if #[cfg(all(target_os = "linux", feature = "use_std"))] { + #[path = "os/linux/mod.rs"] + mod os; + } else if #[cfg(target_os = "freebsd")] { + #[cfg(target_arch = "aarch64")] + #[path = "os/aarch64.rs"] + mod aarch64; + #[path = "os/freebsd/mod.rs"] + mod os; + } else { + #[path = "os/other.rs"] + mod os; + } +} +pub use self::os::check_for; diff --git a/tests/target/cfg_if/detect/os/aarch64.rs b/tests/target/cfg_if/detect/os/aarch64.rs new file mode 100644 index 00000000000..9adc938a264 --- /dev/null +++ b/tests/target/cfg_if/detect/os/aarch64.rs @@ -0,0 +1,88 @@ +//! Run-time feature detection for Aarch64 on any OS that emulates the mrs instruction. +//! +//! On FreeBSD >= 12.0, Linux >= 4.11 and other operating systems, it is possible to use +//! privileged system registers from userspace to check CPU feature support. +//! +//! AArch64 system registers ID_AA64ISAR0_EL1, ID_AA64PFR0_EL1, ID_AA64ISAR1_EL1 +//! have bits dedicated to features like AdvSIMD, CRC32, AES, atomics (LSE), etc. +//! Each part of the register indicates the level of support for a certain feature, e.g. +//! when ID_AA64ISAR0_EL1\[7:4\] is >= 1, AES is supported; when it's >= 2, PMULL is supported. +//! +//! For proper support of [SoCs where different cores have different capabilities](https://medium.com/@jadr2ddude/a-big-little-problem-a-tale-of-big-little-gone-wrong-e7778ce744bb), +//! the OS has to always report only the features supported by all cores, like [FreeBSD does](https://reviews.freebsd.org/D17137#393947). +//! +//! References: +//! +//! - [Zircon implementation](https://fuchsia.googlesource.com/zircon/+/master/kernel/arch/arm64/feature.cpp) +//! - [Linux documentation](https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt) + +use crate::detect::{cache, Feature}; + +/// Try to read the features from the system registers. +/// +/// This will cause SIGILL if the current OS is not trapping the mrs instruction. +pub(crate) fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + + { + let mut enable_feature = |f, enable| { + if enable { + value.set(f as u32); + } + }; + + // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0 + let aa64isar0: u64; + unsafe { + asm!("mrs $0, ID_AA64ISAR0_EL1" : "=r"(aa64isar0)); + } + + let aes = bits_shift(aa64isar0, 7, 4) >= 1; + let pmull = bits_shift(aa64isar0, 7, 4) >= 2; + let sha1 = bits_shift(aa64isar0, 11, 8) >= 1; + let sha2 = bits_shift(aa64isar0, 15, 12) >= 1; + enable_feature(Feature::pmull, pmull); + // Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp + enable_feature(Feature::crypto, aes && pmull && sha1 && sha2); + enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1); + enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1); + + // ID_AA64PFR0_EL1 - Processor Feature Register 0 + let aa64pfr0: u64; + unsafe { + asm!("mrs $0, ID_AA64PFR0_EL1" : "=r"(aa64pfr0)); + } + + let fp = bits_shift(aa64pfr0, 19, 16) < 0xF; + let fphp = bits_shift(aa64pfr0, 19, 16) >= 1; + let asimd = bits_shift(aa64pfr0, 23, 20) < 0xF; + let asimdhp = bits_shift(aa64pfr0, 23, 20) >= 1; + enable_feature(Feature::fp, fp); + enable_feature(Feature::fp16, fphp); + // SIMD support requires float support - if half-floats are + // supported, it also requires half-float support: + enable_feature(Feature::asimd, fp && asimd && (!fphp | asimdhp)); + // SIMD extensions require SIMD support: + enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1); + enable_feature( + Feature::dotprod, + asimd && bits_shift(aa64isar0, 47, 44) >= 1, + ); + enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1); + + // ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1 + let aa64isar1: u64; + unsafe { + asm!("mrs $0, ID_AA64ISAR1_EL1" : "=r"(aa64isar1)); + } + + enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1); + } + + value +} + +#[inline] +fn bits_shift(x: u64, high: usize, low: usize) -> u64 { + (x >> low) & ((1 << (high - low + 1)) - 1) +} diff --git a/tests/target/cfg_if/detect/os/freebsd/aarch64.rs b/tests/target/cfg_if/detect/os/freebsd/aarch64.rs new file mode 100644 index 00000000000..97fe40f80a4 --- /dev/null +++ b/tests/target/cfg_if/detect/os/freebsd/aarch64.rs @@ -0,0 +1,28 @@ +//! Run-time feature detection for Aarch64 on FreeBSD. + +use super::super::aarch64::detect_features; +use crate::detect::{cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +#[cfg(test)] +mod tests { + #[test] + fn dump() { + println!("asimd: {:?}", is_aarch64_feature_detected!("asimd")); + println!("pmull: {:?}", is_aarch64_feature_detected!("pmull")); + println!("fp: {:?}", is_aarch64_feature_detected!("fp")); + println!("fp16: {:?}", is_aarch64_feature_detected!("fp16")); + println!("sve: {:?}", is_aarch64_feature_detected!("sve")); + println!("crc: {:?}", is_aarch64_feature_detected!("crc")); + println!("crypto: {:?}", is_aarch64_feature_detected!("crypto")); + println!("lse: {:?}", is_aarch64_feature_detected!("lse")); + println!("rdm: {:?}", is_aarch64_feature_detected!("rdm")); + println!("rcpc: {:?}", is_aarch64_feature_detected!("rcpc")); + println!("dotprod: {:?}", is_aarch64_feature_detected!("dotprod")); + } +} diff --git a/tests/target/cfg_if/detect/os/freebsd/arm.rs b/tests/target/cfg_if/detect/os/freebsd/arm.rs new file mode 100644 index 00000000000..7aa040075e0 --- /dev/null +++ b/tests/target/cfg_if/detect/os/freebsd/arm.rs @@ -0,0 +1,27 @@ +//! Run-time feature detection for ARM on FreeBSD + +use super::auxvec; +use crate::detect::{cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::neon, auxv.hwcap & 0x00001000 != 0); + enable_feature(&mut value, Feature::pmull, auxv.hwcap2 & 0x00000002 != 0); + return value; + } + value +} diff --git a/tests/target/cfg_if/detect/os/freebsd/auxvec.rs b/tests/target/cfg_if/detect/os/freebsd/auxvec.rs new file mode 100644 index 00000000000..c595ec459b5 --- /dev/null +++ b/tests/target/cfg_if/detect/os/freebsd/auxvec.rs @@ -0,0 +1,94 @@ +//! Parses ELF auxiliary vectors. +#![cfg_attr(any(target_arch = "arm", target_arch = "powerpc64"), allow(dead_code))] + +/// Key to access the CPU Hardware capabilities bitfield. +pub(crate) const AT_HWCAP: usize = 25; +/// Key to access the CPU Hardware capabilities 2 bitfield. +pub(crate) const AT_HWCAP2: usize = 26; + +/// Cache HWCAP bitfields of the ELF Auxiliary Vector. +/// +/// If an entry cannot be read all the bits in the bitfield are set to zero. +/// This should be interpreted as all the features being disabled. +#[derive(Debug, Copy, Clone)] +pub(crate) struct AuxVec { + pub hwcap: usize, + pub hwcap2: usize, +} + +/// ELF Auxiliary Vector +/// +/// The auxiliary vector is a memory region in a running ELF program's stack +/// composed of (key: usize, value: usize) pairs. +/// +/// The keys used in the aux vector are platform dependent. For FreeBSD, they are +/// defined in [sys/elf_common.h][elf_common_h]. The hardware capabilities of a given +/// CPU can be queried with the `AT_HWCAP` and `AT_HWCAP2` keys. +/// +/// Note that run-time feature detection is not invoked for features that can +/// be detected at compile-time. +/// +/// [elf_common.h]: https://svnweb.freebsd.org/base/release/12.0.0/sys/sys/elf_common.h?revision=341707 +pub(crate) fn auxv() -> Result { + if let Ok(hwcap) = archauxv(AT_HWCAP) { + if let Ok(hwcap2) = archauxv(AT_HWCAP2) { + if hwcap != 0 && hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + } + Err(()) +} + +/// Tries to read the `key` from the auxiliary vector. +fn archauxv(key: usize) -> Result { + use crate::mem; + + #[derive(Copy, Clone)] + #[repr(C)] + pub struct Elf_Auxinfo { + pub a_type: usize, + pub a_un: unnamed, + } + #[derive(Copy, Clone)] + #[repr(C)] + pub union unnamed { + pub a_val: libc::c_long, + pub a_ptr: *mut libc::c_void, + pub a_fcn: Option ()>, + } + + let mut auxv: [Elf_Auxinfo; 27] = [Elf_Auxinfo { + a_type: 0, + a_un: unnamed { a_val: 0 }, + }; 27]; + + let mut len: libc::c_uint = mem::size_of_val(&auxv) as libc::c_uint; + + unsafe { + let mut mib = [ + libc::CTL_KERN, + libc::KERN_PROC, + libc::KERN_PROC_AUXV, + libc::getpid(), + ]; + + let ret = libc::sysctl( + mib.as_mut_ptr(), + mib.len() as u32, + &mut auxv as *mut _ as *mut _, + &mut len as *mut _ as *mut _, + 0 as *mut libc::c_void, + 0, + ); + + if ret != -1 { + for i in 0..auxv.len() { + if auxv[i].a_type == key { + return Ok(auxv[i].a_un.a_val as usize); + } + } + } + } + return Ok(0); +} diff --git a/tests/target/cfg_if/detect/os/freebsd/mod.rs b/tests/target/cfg_if/detect/os/freebsd/mod.rs new file mode 100644 index 00000000000..1a5338a3555 --- /dev/null +++ b/tests/target/cfg_if/detect/os/freebsd/mod.rs @@ -0,0 +1,22 @@ +//! Run-time feature detection on FreeBSD + +mod auxvec; + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::check_for; + } else if #[cfg(target_arch = "arm")] { + mod arm; + pub use self::arm::check_for; + } else if #[cfg(target_arch = "powerpc64")] { + mod powerpc; + pub use self::powerpc::check_for; + } else { + use crate::arch::detect::Feature; + /// Performs run-time feature detection. + pub fn check_for(_x: Feature) -> bool { + false + } + } +} diff --git a/tests/target/cfg_if/detect/os/freebsd/powerpc.rs b/tests/target/cfg_if/detect/os/freebsd/powerpc.rs new file mode 100644 index 00000000000..203e5cd7f25 --- /dev/null +++ b/tests/target/cfg_if/detect/os/freebsd/powerpc.rs @@ -0,0 +1,27 @@ +//! Run-time feature detection for PowerPC on FreeBSD. + +use super::auxvec; +use crate::detect::{cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0); + enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0); + enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0); + return value; + } + value +} diff --git a/tests/target/cfg_if/detect/os/linux/aarch64.rs b/tests/target/cfg_if/detect/os/linux/aarch64.rs new file mode 100644 index 00000000000..8d874f2280f --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/aarch64.rs @@ -0,0 +1,160 @@ +//! Run-time feature detection for Aarch64 on Linux. + +use super::{auxvec, cpuinfo}; +use crate::detect::{bit, cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from /proc/cpuinfo. +fn detect_features() -> cache::Initializer { + if let Ok(auxv) = auxvec::auxv() { + let hwcap: AtHwcap = auxv.into(); + return hwcap.cache(); + } + if let Ok(c) = cpuinfo::CpuInfo::new() { + let hwcap: AtHwcap = c.into(); + return hwcap.cache(); + } + cache::Initializer::default() +} + +/// These values are part of the platform-specific [asm/hwcap.h][hwcap] . +/// +/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h +struct AtHwcap { + fp: bool, // 0 + asimd: bool, // 1 + // evtstrm: bool, // 2 + aes: bool, // 3 + pmull: bool, // 4 + sha1: bool, // 5 + sha2: bool, // 6 + crc32: bool, // 7 + atomics: bool, // 8 + fphp: bool, // 9 + asimdhp: bool, // 10 + // cpuid: bool, // 11 + asimdrdm: bool, // 12 + // jscvt: bool, // 13 + // fcma: bool, // 14 + lrcpc: bool, // 15 + // dcpop: bool, // 16 + // sha3: bool, // 17 + // sm3: bool, // 18 + // sm4: bool, // 19 + asimddp: bool, // 20 + // sha512: bool, // 21 + sve: bool, // 22 +} + +impl From for AtHwcap { + /// Reads AtHwcap from the auxiliary vector. + fn from(auxv: auxvec::AuxVec) -> Self { + AtHwcap { + fp: bit::test(auxv.hwcap, 0), + asimd: bit::test(auxv.hwcap, 1), + // evtstrm: bit::test(auxv.hwcap, 2), + aes: bit::test(auxv.hwcap, 3), + pmull: bit::test(auxv.hwcap, 4), + sha1: bit::test(auxv.hwcap, 5), + sha2: bit::test(auxv.hwcap, 6), + crc32: bit::test(auxv.hwcap, 7), + atomics: bit::test(auxv.hwcap, 8), + fphp: bit::test(auxv.hwcap, 9), + asimdhp: bit::test(auxv.hwcap, 10), + // cpuid: bit::test(auxv.hwcap, 11), + asimdrdm: bit::test(auxv.hwcap, 12), + // jscvt: bit::test(auxv.hwcap, 13), + // fcma: bit::test(auxv.hwcap, 14), + lrcpc: bit::test(auxv.hwcap, 15), + // dcpop: bit::test(auxv.hwcap, 16), + // sha3: bit::test(auxv.hwcap, 17), + // sm3: bit::test(auxv.hwcap, 18), + // sm4: bit::test(auxv.hwcap, 19), + asimddp: bit::test(auxv.hwcap, 20), + // sha512: bit::test(auxv.hwcap, 21), + sve: bit::test(auxv.hwcap, 22), + } + } +} + +impl From for AtHwcap { + /// Reads AtHwcap from /proc/cpuinfo . + fn from(c: cpuinfo::CpuInfo) -> Self { + let f = &c.field("Features"); + AtHwcap { + // 64-bit names. FIXME: In 32-bit compatibility mode /proc/cpuinfo will + // map some of the 64-bit names to some 32-bit feature names. This does not + // cover that yet. + fp: f.has("fp"), + asimd: f.has("asimd"), + // evtstrm: f.has("evtstrm"), + aes: f.has("aes"), + pmull: f.has("pmull"), + sha1: f.has("sha1"), + sha2: f.has("sha2"), + crc32: f.has("crc32"), + atomics: f.has("atomics"), + fphp: f.has("fphp"), + asimdhp: f.has("asimdhp"), + // cpuid: f.has("cpuid"), + asimdrdm: f.has("asimdrdm"), + // jscvt: f.has("jscvt"), + // fcma: f.has("fcma"), + lrcpc: f.has("lrcpc"), + // dcpop: f.has("dcpop"), + // sha3: f.has("sha3"), + // sm3: f.has("sm3"), + // sm4: f.has("sm4"), + asimddp: f.has("asimddp"), + // sha512: f.has("sha512"), + sve: f.has("sve"), + } + } +} + +impl AtHwcap { + /// Initializes the cache from the feature -bits. + /// + /// The features are enabled approximately like in LLVM host feature detection: + /// https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Host.cpp#L1273 + fn cache(self) -> cache::Initializer { + let mut value = cache::Initializer::default(); + { + let mut enable_feature = |f, enable| { + if enable { + value.set(f as u32); + } + }; + + enable_feature(Feature::fp, self.fp); + // Half-float support requires float support + enable_feature(Feature::fp16, self.fp && self.fphp); + enable_feature(Feature::pmull, self.pmull); + enable_feature(Feature::crc, self.crc32); + enable_feature(Feature::lse, self.atomics); + enable_feature(Feature::rcpc, self.lrcpc); + + // SIMD support requires float support - if half-floats are + // supported, it also requires half-float support: + let asimd = self.fp && self.asimd && (!self.fphp | self.asimdhp); + enable_feature(Feature::asimd, asimd); + // SIMD extensions require SIMD support: + enable_feature(Feature::rdm, self.asimdrdm && asimd); + enable_feature(Feature::dotprod, self.asimddp && asimd); + enable_feature(Feature::sve, self.sve && asimd); + + // Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp + enable_feature( + Feature::crypto, + self.aes && self.pmull && self.sha1 && self.sha2, + ); + } + value + } +} diff --git a/tests/target/cfg_if/detect/os/linux/arm.rs b/tests/target/cfg_if/detect/os/linux/arm.rs new file mode 100644 index 00000000000..9c89500cc10 --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/arm.rs @@ -0,0 +1,52 @@ +//! Run-time feature detection for ARM on Linux. + +use super::{auxvec, cpuinfo}; +use crate::detect::{bit, cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from /proc/cpuinfo. +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + // The values are part of the platform-specific [asm/hwcap.h][hwcap] + // + // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::neon, bit::test(auxv.hwcap, 12)); + enable_feature(&mut value, Feature::pmull, bit::test(auxv.hwcap2, 1)); + return value; + } + + if let Ok(c) = cpuinfo::CpuInfo::new() { + enable_feature( + &mut value, + Feature::neon, + c.field("Features").has("neon") && !has_broken_neon(&c), + ); + enable_feature(&mut value, Feature::pmull, c.field("Features").has("pmull")); + return value; + } + value +} + +/// Is the CPU known to have a broken NEON unit? +/// +/// See https://crbug.com/341598. +fn has_broken_neon(cpuinfo: &cpuinfo::CpuInfo) -> bool { + cpuinfo.field("CPU implementer") == "0x51" + && cpuinfo.field("CPU architecture") == "7" + && cpuinfo.field("CPU variant") == "0x1" + && cpuinfo.field("CPU part") == "0x04d" + && cpuinfo.field("CPU revision") == "0" +} diff --git a/tests/target/cfg_if/detect/os/linux/auxvec.rs b/tests/target/cfg_if/detect/os/linux/auxvec.rs new file mode 100644 index 00000000000..6ebae67fbf8 --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/auxvec.rs @@ -0,0 +1,304 @@ +//! Parses ELF auxiliary vectors. +#![cfg_attr(not(target_arch = "aarch64"), allow(dead_code))] + +#[cfg(feature = "std_detect_file_io")] +use crate::{fs::File, io::Read}; + +/// Key to access the CPU Hardware capabilities bitfield. +pub(crate) const AT_HWCAP: usize = 16; +/// Key to access the CPU Hardware capabilities 2 bitfield. +#[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] +pub(crate) const AT_HWCAP2: usize = 26; + +/// Cache HWCAP bitfields of the ELF Auxiliary Vector. +/// +/// If an entry cannot be read all the bits in the bitfield are set to zero. +/// This should be interpreted as all the features being disabled. +#[derive(Debug, Copy, Clone)] +pub(crate) struct AuxVec { + pub hwcap: usize, + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + pub hwcap2: usize, +} + +/// ELF Auxiliary Vector +/// +/// The auxiliary vector is a memory region in a running ELF program's stack +/// composed of (key: usize, value: usize) pairs. +/// +/// The keys used in the aux vector are platform dependent. For Linux, they are +/// defined in [linux/auxvec.h][auxvec_h]. The hardware capabilities of a given +/// CPU can be queried with the `AT_HWCAP` and `AT_HWCAP2` keys. +/// +/// There is no perfect way of reading the auxiliary vector. +/// +/// - If the `std_detect_dlsym_getauxval` cargo feature is enabled, this will use +/// `getauxval` if its linked to the binary, and otherwise proceed to a fallback implementation. +/// When `std_detect_dlsym_getauxval` is disabled, this will assume that `getauxval` is +/// linked to the binary - if that is not the case the behavior is undefined. +/// - Otherwise, if the `std_detect_file_io` cargo feature is enabled, it will +/// try to read `/proc/self/auxv`. +/// - If that fails, this function returns an error. +/// +/// Note that run-time feature detection is not invoked for features that can +/// be detected at compile-time. Also note that if this function returns an +/// error, cpuinfo still can (and will) be used to try to perform run-time +/// feature detecton on some platforms. +/// +/// For more information about when `getauxval` is available check the great +/// [`auxv` crate documentation][auxv_docs]. +/// +/// [auxvec_h]: https://github.com/torvalds/linux/blob/master/include/uapi/linux/auxvec.h +/// [auxv_docs]: https://docs.rs/auxv/0.3.3/auxv/ +pub(crate) fn auxv() -> Result { + #[cfg(feature = "std_detect_dlsym_getauxval")] + { + // Try to call a dynamically-linked getauxval function. + if let Ok(hwcap) = getauxval(AT_HWCAP) { + // Targets with only AT_HWCAP: + #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] + { + if hwcap != 0 { + return Ok(AuxVec { hwcap }); + } + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + if let Ok(hwcap2) = getauxval(AT_HWCAP2) { + if hwcap != 0 && hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + } + drop(hwcap); + } + #[cfg(feature = "std_detect_file_io")] + { + // If calling getauxval fails, try to read the auxiliary vector from + // its file: + auxv_from_file("/proc/self/auxv") + } + #[cfg(not(feature = "std_detect_file_io"))] + { + Err(()) + } + } + + #[cfg(not(feature = "std_detect_dlsym_getauxval"))] + { + let hwcap = unsafe { ffi_getauxval(AT_HWCAP) }; + + // Targets with only AT_HWCAP: + #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] + { + if hwcap != 0 { + return Ok(AuxVec { hwcap }); + } + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + let hwcap2 = unsafe { ffi_getauxval(AT_HWCAP2) }; + if hwcap != 0 && hwcap2 != 0 { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + } +} + +/// Tries to read the `key` from the auxiliary vector by calling the +/// dynamically-linked `getauxval` function. If the function is not linked, +/// this function return `Err`. +#[cfg(feature = "std_detect_dlsym_getauxval")] +fn getauxval(key: usize) -> Result { + use libc; + pub type F = unsafe extern "C" fn(usize) -> usize; + unsafe { + let ptr = libc::dlsym(libc::RTLD_DEFAULT, "getauxval\0".as_ptr() as *const _); + if ptr.is_null() { + return Err(()); + } + + let ffi_getauxval: F = mem::transmute(ptr); + Ok(ffi_getauxval(key)) + } +} + +/// Tries to read the auxiliary vector from the `file`. If this fails, this +/// function returns `Err`. +#[cfg(feature = "std_detect_file_io")] +fn auxv_from_file(file: &str) -> Result { + let mut file = File::open(file).map_err(|_| ())?; + + // See . + // + // The auxiliary vector contains at most 32 (key,value) fields: from + // `AT_EXECFN = 31` to `AT_NULL = 0`. That is, a buffer of + // 2*32 `usize` elements is enough to read the whole vector. + let mut buf = [0_usize; 64]; + { + let raw: &mut [u8; 64 * mem::size_of::()] = unsafe { mem::transmute(&mut buf) }; + file.read(raw).map_err(|_| ())?; + } + auxv_from_buf(&buf) +} + +/// Tries to interpret the `buffer` as an auxiliary vector. If that fails, this +/// function returns `Err`. +#[cfg(feature = "std_detect_file_io")] +fn auxv_from_buf(buf: &[usize; 64]) -> Result { + // Targets with only AT_HWCAP: + #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] + { + for el in buf.chunks(2) { + match el[0] { + AT_HWCAP => return Ok(AuxVec { hwcap: el[1] }), + _ => (), + } + } + } + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + let mut hwcap = None; + let mut hwcap2 = None; + for el in buf.chunks(2) { + match el[0] { + AT_HWCAP => hwcap = Some(el[1]), + AT_HWCAP2 => hwcap2 = Some(el[1]), + _ => (), + } + } + + if let (Some(hwcap), Some(hwcap2)) = (hwcap, hwcap2) { + return Ok(AuxVec { hwcap, hwcap2 }); + } + } + drop(buf); + Err(()) +} + +#[cfg(test)] +mod tests { + extern crate auxv as auxv_crate; + use super::*; + + // Reads the Auxiliary Vector key from /proc/self/auxv + // using the auxv crate. + #[cfg(feature = "std_detect_file_io")] + fn auxv_crate_getprocfs(key: usize) -> Option { + use self::auxv_crate::procfs::search_procfs_auxv; + use self::auxv_crate::AuxvType; + let k = key as AuxvType; + match search_procfs_auxv(&[k]) { + Ok(v) => Some(v[&k] as usize), + Err(_) => None, + } + } + + // Reads the Auxiliary Vector key from getauxval() + // using the auxv crate. + #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] + fn auxv_crate_getauxval(key: usize) -> Option { + use self::auxv_crate::getauxval::Getauxval; + use self::auxv_crate::AuxvType; + let q = auxv_crate::getauxval::NativeGetauxval {}; + match q.getauxval(key as AuxvType) { + Ok(v) => Some(v as usize), + Err(_) => None, + } + } + + // FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv + // does not always contain the AT_HWCAP key under qemu. + #[cfg(not(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc")))] + #[test] + fn auxv_crate() { + let v = auxv(); + if let Some(hwcap) = auxv_crate_getauxval(AT_HWCAP) { + let rt_hwcap = v.expect("failed to find hwcap key").hwcap; + assert_eq!(rt_hwcap, hwcap); + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + if let Some(hwcap2) = auxv_crate_getauxval(AT_HWCAP2) { + let rt_hwcap2 = v.expect("failed to find hwcap2 key").hwcap2; + assert_eq!(rt_hwcap2, hwcap2); + } + } + } + + #[test] + fn auxv_dump() { + if let Ok(auxvec) = auxv() { + println!("{:?}", auxvec); + } else { + println!("both getauxval() and reading /proc/self/auxv failed!"); + } + } + + #[cfg(feature = "std_detect_file_io")] + cfg_if! { + if #[cfg(target_arch = "arm")] { + #[test] + fn linux_rpi3() { + let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-rpi3.auxv"); + println!("file: {}", file); + let v = auxv_from_file(file).unwrap(); + assert_eq!(v.hwcap, 4174038); + assert_eq!(v.hwcap2, 16); + } + + #[test] + #[should_panic] + fn linux_macos_vb() { + let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/macos-virtualbox-linux-x86-4850HQ.auxv"); + println!("file: {}", file); + let v = auxv_from_file(file).unwrap(); + // this file is incomplete (contains hwcap but not hwcap2), we + // want to fall back to /proc/cpuinfo in this case, so + // reading should fail. assert_eq!(v.hwcap, 126614527); + // assert_eq!(v.hwcap2, 0); + } + } else if #[cfg(target_arch = "aarch64")] { + #[test] + fn linux_x64() { + let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-x64-i7-6850k.auxv"); + println!("file: {}", file); + let v = auxv_from_file(file).unwrap(); + assert_eq!(v.hwcap, 3219913727); + } + } + } + + #[test] + #[cfg(feature = "std_detect_file_io")] + fn auxv_dump_procfs() { + if let Ok(auxvec) = auxv_from_file("/proc/self/auxv") { + println!("{:?}", auxvec); + } else { + println!("reading /proc/self/auxv failed!"); + } + } + + #[test] + fn auxv_crate_procfs() { + let v = auxv(); + if let Some(hwcap) = auxv_crate_getprocfs(AT_HWCAP) { + assert_eq!(v.unwrap().hwcap, hwcap); + } + + // Targets with AT_HWCAP and AT_HWCAP2: + #[cfg(any(target_arch = "arm", target_arch = "powerpc64"))] + { + if let Some(hwcap2) = auxv_crate_getprocfs(AT_HWCAP2) { + assert_eq!(v.unwrap().hwcap2, hwcap2); + } + } + } +} diff --git a/tests/target/cfg_if/detect/os/linux/cpuinfo.rs b/tests/target/cfg_if/detect/os/linux/cpuinfo.rs new file mode 100644 index 00000000000..f76c48a4b16 --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/cpuinfo.rs @@ -0,0 +1,300 @@ +//! Parses /proc/cpuinfo +#![cfg_attr(not(target_arch = "arm"), allow(dead_code))] + +extern crate std; +use self::std::{fs::File, io, io::Read, prelude::v1::*}; + +/// cpuinfo +pub(crate) struct CpuInfo { + raw: String, +} + +impl CpuInfo { + /// Reads /proc/cpuinfo into CpuInfo. + pub(crate) fn new() -> Result { + let mut file = File::open("/proc/cpuinfo")?; + let mut cpui = Self { raw: String::new() }; + file.read_to_string(&mut cpui.raw)?; + Ok(cpui) + } + /// Returns the value of the cpuinfo `field`. + pub(crate) fn field(&self, field: &str) -> CpuInfoField { + for l in self.raw.lines() { + if l.trim().starts_with(field) { + return CpuInfoField::new(l.split(": ").nth(1)); + } + } + CpuInfoField(None) + } + + /// Returns the `raw` contents of `/proc/cpuinfo` + #[cfg(test)] + fn raw(&self) -> &String { + &self.raw + } + + #[cfg(test)] + fn from_str(other: &str) -> Result { + Ok(Self { + raw: String::from(other), + }) + } +} + +/// Field of cpuinfo +#[derive(Debug)] +pub(crate) struct CpuInfoField<'a>(Option<&'a str>); + +impl<'a> PartialEq<&'a str> for CpuInfoField<'a> { + fn eq(&self, other: &&'a str) -> bool { + match self.0 { + None => other.is_empty(), + Some(f) => f == other.trim(), + } + } +} + +impl<'a> CpuInfoField<'a> { + pub(crate) fn new<'b>(v: Option<&'b str>) -> CpuInfoField<'b> { + match v { + None => CpuInfoField::<'b>(None), + Some(f) => CpuInfoField::<'b>(Some(f.trim())), + } + } + /// Does the field exist? + #[cfg(test)] + pub(crate) fn exists(&self) -> bool { + self.0.is_some() + } + /// Does the field contain `other`? + pub(crate) fn has(&self, other: &str) -> bool { + match self.0 { + None => other.is_empty(), + Some(f) => { + let other = other.trim(); + for v in f.split(' ') { + if v == other { + return true; + } + } + false + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn raw_dump() { + let cpuinfo = CpuInfo::new().unwrap(); + if cpuinfo.field("vendor_id") == "GenuineIntel" { + assert!(cpuinfo.field("flags").exists()); + assert!(!cpuinfo.field("vendor33_id").exists()); + assert!(cpuinfo.field("flags").has("sse")); + assert!(!cpuinfo.field("flags").has("avx314")); + } + println!("{}", cpuinfo.raw()); + } + + const CORE_DUO_T6500: &str = r"processor : 0 +vendor_id : GenuineIntel +cpu family : 6 +model : 23 +model name : Intel(R) Core(TM)2 Duo CPU T6500 @ 2.10GHz +stepping : 10 +microcode : 0xa0b +cpu MHz : 1600.000 +cache size : 2048 KB +physical id : 0 +siblings : 2 +core id : 0 +cpu cores : 2 +apicid : 0 +initial apicid : 0 +fdiv_bug : no +hlt_bug : no +f00f_bug : no +coma_bug : no +fpu : yes +fpu_exception : yes +cpuid level : 13 +wp : yes +flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm +bogomips : 4190.43 +clflush size : 64 +cache_alignment : 64 +address sizes : 36 bits physical, 48 bits virtual +power management: +"; + + #[test] + fn core_duo_t6500() { + let cpuinfo = CpuInfo::from_str(CORE_DUO_T6500).unwrap(); + assert_eq!(cpuinfo.field("vendor_id"), "GenuineIntel"); + assert_eq!(cpuinfo.field("cpu family"), "6"); + assert_eq!(cpuinfo.field("model"), "23"); + assert_eq!( + cpuinfo.field("model name"), + "Intel(R) Core(TM)2 Duo CPU T6500 @ 2.10GHz" + ); + assert_eq!( + cpuinfo.field("flags"), + "fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm" + ); + assert!(cpuinfo.field("flags").has("fpu")); + assert!(cpuinfo.field("flags").has("dtherm")); + assert!(cpuinfo.field("flags").has("sse2")); + assert!(!cpuinfo.field("flags").has("avx")); + } + + const ARM_CORTEX_A53: &str = r"Processor : AArch64 Processor rev 3 (aarch64) + processor : 0 + processor : 1 + processor : 2 + processor : 3 + processor : 4 + processor : 5 + processor : 6 + processor : 7 + Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 + CPU implementer : 0x41 + CPU architecture: AArch64 + CPU variant : 0x0 + CPU part : 0xd03 + CPU revision : 3 + + Hardware : HiKey Development Board + "; + + #[test] + fn arm_cortex_a53() { + let cpuinfo = CpuInfo::from_str(ARM_CORTEX_A53).unwrap(); + assert_eq!( + cpuinfo.field("Processor"), + "AArch64 Processor rev 3 (aarch64)" + ); + assert_eq!( + cpuinfo.field("Features"), + "fp asimd evtstrm aes pmull sha1 sha2 crc32" + ); + assert!(cpuinfo.field("Features").has("pmull")); + assert!(!cpuinfo.field("Features").has("neon")); + assert!(cpuinfo.field("Features").has("asimd")); + } + + const ARM_CORTEX_A57: &str = r"Processor : Cortex A57 Processor rev 1 (aarch64) +processor : 0 +processor : 1 +processor : 2 +processor : 3 +Features : fp asimd aes pmull sha1 sha2 crc32 wp half thumb fastmult vfp edsp neon vfpv3 tlsi vfpv4 idiva idivt +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x1 +CPU part : 0xd07 +CPU revision : 1"; + + #[test] + fn arm_cortex_a57() { + let cpuinfo = CpuInfo::from_str(ARM_CORTEX_A57).unwrap(); + assert_eq!( + cpuinfo.field("Processor"), + "Cortex A57 Processor rev 1 (aarch64)" + ); + assert_eq!( + cpuinfo.field("Features"), + "fp asimd aes pmull sha1 sha2 crc32 wp half thumb fastmult vfp edsp neon vfpv3 tlsi vfpv4 idiva idivt" + ); + assert!(cpuinfo.field("Features").has("pmull")); + assert!(cpuinfo.field("Features").has("neon")); + assert!(cpuinfo.field("Features").has("asimd")); + } + + const POWER8E_POWERKVM: &str = r"processor : 0 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +processor : 1 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +processor : 2 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +processor : 3 +cpu : POWER8E (raw), altivec supported +clock : 3425.000000MHz +revision : 2.1 (pvr 004b 0201) + +timebase : 512000000 +platform : pSeries +model : IBM pSeries (emulated by qemu) +machine : CHRP IBM pSeries (emulated by qemu)"; + + #[test] + fn power8_powerkvm() { + let cpuinfo = CpuInfo::from_str(POWER8E_POWERKVM).unwrap(); + assert_eq!(cpuinfo.field("cpu"), "POWER8E (raw), altivec supported"); + + assert!(cpuinfo.field("cpu").has("altivec")); + } + + const POWER5P: &str = r"processor : 0 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 1 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 2 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 3 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 4 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 5 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 6 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +processor : 7 +cpu : POWER5+ (gs) +clock : 1900.098000MHz +revision : 2.1 (pvr 003b 0201) + +timebase : 237331000 +platform : pSeries +machine : CHRP IBM,9133-55A"; + + #[test] + fn power5p() { + let cpuinfo = CpuInfo::from_str(POWER5P).unwrap(); + assert_eq!(cpuinfo.field("cpu"), "POWER5+ (gs)"); + + assert!(!cpuinfo.field("cpu").has("altivec")); + } +} diff --git a/tests/target/cfg_if/detect/os/linux/mips.rs b/tests/target/cfg_if/detect/os/linux/mips.rs new file mode 100644 index 00000000000..46a47fb7b78 --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/mips.rs @@ -0,0 +1,31 @@ +//! Run-time feature detection for MIPS on Linux. + +use super::auxvec; +use crate::detect::{bit, cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from `/proc/cpuinfo`. +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + // The values are part of the platform-specific [asm/hwcap.h][hwcap] + // + // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::msa, bit::test(auxv.hwcap, 1)); + return value; + } + // TODO: fall back via `cpuinfo`. + value +} diff --git a/tests/target/cfg_if/detect/os/linux/mod.rs b/tests/target/cfg_if/detect/os/linux/mod.rs new file mode 100644 index 00000000000..e02d5e6dcda --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/mod.rs @@ -0,0 +1,28 @@ +//! Run-time feature detection on Linux + +mod auxvec; + +#[cfg(feature = "std_detect_file_io")] +mod cpuinfo; + +cfg_if! { + if #[cfg(target_arch = "aarch64")] { + mod aarch64; + pub use self::aarch64::check_for; + } else if #[cfg(target_arch = "arm")] { + mod arm; + pub use self::arm::check_for; + } else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { + mod mips; + pub use self::mips::check_for; + } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { + mod powerpc; + pub use self::powerpc::check_for; + } else { + use crate::detect::Feature; + /// Performs run-time feature detection. + pub fn check_for(_x: Feature) -> bool { + false + } + } +} diff --git a/tests/target/cfg_if/detect/os/linux/powerpc.rs b/tests/target/cfg_if/detect/os/linux/powerpc.rs new file mode 100644 index 00000000000..dc19bc8eda5 --- /dev/null +++ b/tests/target/cfg_if/detect/os/linux/powerpc.rs @@ -0,0 +1,41 @@ +//! Run-time feature detection for PowerPC on Linux. + +use super::{auxvec, cpuinfo}; +use crate::detect::{cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Try to read the features from the auxiliary vector, and if that fails, try +/// to read them from /proc/cpuinfo. +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, f, enable| { + if enable { + value.set(f as u32); + } + }; + + // The values are part of the platform-specific [asm/cputable.h][cputable] + // + // [cputable]: https://github.com/torvalds/linux/blob/master/arch/powerpc/include/uapi/asm/cputable.h + if let Ok(auxv) = auxvec::auxv() { + // note: the PowerPC values are the mask to do the test (instead of the + // index of the bit to test like in ARM and Aarch64) + enable_feature(&mut value, Feature::altivec, auxv.hwcap & 0x10000000 != 0); + enable_feature(&mut value, Feature::vsx, auxv.hwcap & 0x00000080 != 0); + enable_feature(&mut value, Feature::power8, auxv.hwcap2 & 0x80000000 != 0); + return value; + } + + // PowerPC's /proc/cpuinfo lacks a proper Feature field, + // but `altivec` support is indicated in the `cpu` field. + if let Ok(c) = cpuinfo::CpuInfo::new() { + enable_feature(&mut value, Feature::altivec, c.field("cpu").has("altivec")); + return value; + } + value +} diff --git a/tests/target/cfg_if/detect/os/other.rs b/tests/target/cfg_if/detect/os/other.rs new file mode 100644 index 00000000000..23e399ea790 --- /dev/null +++ b/tests/target/cfg_if/detect/os/other.rs @@ -0,0 +1,9 @@ +//! Other operating systems + +use crate::detect::Feature; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(_x: Feature) -> bool { + false +} diff --git a/tests/target/cfg_if/detect/os/x86.rs b/tests/target/cfg_if/detect/os/x86.rs new file mode 100644 index 00000000000..2e228aa3745 --- /dev/null +++ b/tests/target/cfg_if/detect/os/x86.rs @@ -0,0 +1,367 @@ +//! x86 run-time feature detection is OS independent. + +#[cfg(target_arch = "x86")] +use crate::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use crate::arch::x86_64::*; + +use crate::mem; + +use crate::detect::{bit, cache, Feature}; + +/// Performs run-time feature detection. +#[inline] +pub fn check_for(x: Feature) -> bool { + cache::test(x as u32, detect_features) +} + +/// Run-time feature detection on x86 works by using the CPUID instruction. +/// +/// The [CPUID Wikipedia page][wiki_cpuid] contains +/// all the information about which flags to set to query which values, and in +/// which registers these are reported. +/// +/// The definitive references are: +/// - [Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2: +/// Instruction Set Reference, A-Z][intel64_ref]. +/// - [AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and +/// System Instructions][amd64_ref]. +/// +/// [wiki_cpuid]: https://en.wikipedia.org/wiki/CPUID +/// [intel64_ref]: http://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf +/// [amd64_ref]: http://support.amd.com/TechDocs/24594.pdf +#[allow(clippy::similar_names)] +fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + + // If the x86 CPU does not support the CPUID instruction then it is too + // old to support any of the currently-detectable features. + if !has_cpuid() { + return value; + } + + // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU + // has `cpuid` support. + + // 0. EAX = 0: Basic Information: + // - EAX returns the "Highest Function Parameter", that is, the maximum + // leaf value for subsequent calls of `cpuinfo` in range [0, + // 0x8000_0000]. - The vendor ID is stored in 12 u8 ascii chars, + // returned in EBX, EDX, and ECX (in that order): + let (max_basic_leaf, vendor_id) = unsafe { + let CpuidResult { + eax: max_basic_leaf, + ebx, + ecx, + edx, + } = __cpuid(0); + let vendor_id: [[u8; 4]; 3] = [ + mem::transmute(ebx), + mem::transmute(edx), + mem::transmute(ecx), + ]; + let vendor_id: [u8; 12] = mem::transmute(vendor_id); + (max_basic_leaf, vendor_id) + }; + + if max_basic_leaf < 1 { + // Earlier Intel 486, CPUID not implemented + return value; + } + + // EAX = 1, ECX = 0: Queries "Processor Info and Feature Bits"; + // Contains information about most x86 features. + let CpuidResult { + ecx: proc_info_ecx, + edx: proc_info_edx, + .. + } = unsafe { __cpuid(0x0000_0001_u32) }; + + // EAX = 7, ECX = 0: Queries "Extended Features"; + // Contains information about bmi,bmi2, and avx2 support. + let (extended_features_ebx, extended_features_ecx) = if max_basic_leaf >= 7 { + let CpuidResult { ebx, ecx, .. } = unsafe { __cpuid(0x0000_0007_u32) }; + (ebx, ecx) + } else { + (0, 0) // CPUID does not support "Extended Features" + }; + + // EAX = 0x8000_0000, ECX = 0: Get Highest Extended Function Supported + // - EAX returns the max leaf value for extended information, that is, + // `cpuid` calls in range [0x8000_0000; u32::MAX]: + let CpuidResult { + eax: extended_max_basic_leaf, + .. + } = unsafe { __cpuid(0x8000_0000_u32) }; + + // EAX = 0x8000_0001, ECX=0: Queries "Extended Processor Info and Feature + // Bits" + let extended_proc_info_ecx = if extended_max_basic_leaf >= 1 { + let CpuidResult { ecx, .. } = unsafe { __cpuid(0x8000_0001_u32) }; + ecx + } else { + 0 + }; + + { + // borrows value till the end of this scope: + let mut enable = |r, rb, f| { + if bit::test(r as usize, rb) { + value.set(f as u32); + } + }; + + enable(proc_info_ecx, 0, Feature::sse3); + enable(proc_info_ecx, 1, Feature::pclmulqdq); + enable(proc_info_ecx, 9, Feature::ssse3); + enable(proc_info_ecx, 13, Feature::cmpxchg16b); + enable(proc_info_ecx, 19, Feature::sse4_1); + enable(proc_info_ecx, 20, Feature::sse4_2); + enable(proc_info_ecx, 23, Feature::popcnt); + enable(proc_info_ecx, 25, Feature::aes); + enable(proc_info_ecx, 29, Feature::f16c); + enable(proc_info_ecx, 30, Feature::rdrand); + enable(extended_features_ebx, 18, Feature::rdseed); + enable(extended_features_ebx, 19, Feature::adx); + enable(extended_features_ebx, 11, Feature::rtm); + enable(proc_info_edx, 4, Feature::tsc); + enable(proc_info_edx, 23, Feature::mmx); + enable(proc_info_edx, 24, Feature::fxsr); + enable(proc_info_edx, 25, Feature::sse); + enable(proc_info_edx, 26, Feature::sse2); + enable(extended_features_ebx, 29, Feature::sha); + + enable(extended_features_ebx, 3, Feature::bmi); + enable(extended_features_ebx, 8, Feature::bmi2); + + // `XSAVE` and `AVX` support: + let cpu_xsave = bit::test(proc_info_ecx as usize, 26); + if cpu_xsave { + // 0. Here the CPU supports `XSAVE`. + + // 1. Detect `OSXSAVE`, that is, whether the OS is AVX enabled and + // supports saving the state of the AVX/AVX2 vector registers on + // context-switches, see: + // + // - [intel: is avx enabled?][is_avx_enabled], + // - [mozilla: sse.cpp][mozilla_sse_cpp]. + // + // [is_avx_enabled]: https://software.intel.com/en-us/blogs/2011/04/14/is-avx-enabled + // [mozilla_sse_cpp]: https://hg.mozilla.org/mozilla-central/file/64bab5cbb9b6/mozglue/build/SSE.cpp#l190 + let cpu_osxsave = bit::test(proc_info_ecx as usize, 27); + + if cpu_osxsave { + // 2. The OS must have signaled the CPU that it supports saving and + // restoring the: + // + // * SSE -> `XCR0.SSE[1]` + // * AVX -> `XCR0.AVX[2]` + // * AVX-512 -> `XCR0.AVX-512[7:5]`. + // + // by setting the corresponding bits of `XCR0` to `1`. + // + // This is safe because the CPU supports `xsave` + // and the OS has set `osxsave`. + let xcr0 = unsafe { _xgetbv(0) }; + // Test `XCR0.SSE[1]` and `XCR0.AVX[2]` with the mask `0b110 == 6`: + let os_avx_support = xcr0 & 6 == 6; + // Test `XCR0.AVX-512[7:5]` with the mask `0b1110_0000 == 224`: + let os_avx512_support = xcr0 & 224 == 224; + + // Only if the OS and the CPU support saving/restoring the AVX + // registers we enable `xsave` support: + if os_avx_support { + // See "13.3 ENABLING THE XSAVE FEATURE SET AND XSAVE-ENABLED + // FEATURES" in the "Intel® 64 and IA-32 Architectures Software + // Developer’s Manual, Volume 1: Basic Architecture": + // + // "Software enables the XSAVE feature set by setting + // CR4.OSXSAVE[bit 18] to 1 (e.g., with the MOV to CR4 + // instruction). If this bit is 0, execution of any of XGETBV, + // XRSTOR, XRSTORS, XSAVE, XSAVEC, XSAVEOPT, XSAVES, and XSETBV + // causes an invalid-opcode exception (#UD)" + // + enable(proc_info_ecx, 26, Feature::xsave); + + // For `xsaveopt`, `xsavec`, and `xsaves` we need to query: + // Processor Extended State Enumeration Sub-leaf (EAX = 0DH, + // ECX = 1): + if max_basic_leaf >= 0xd { + let CpuidResult { + eax: proc_extended_state1_eax, + .. + } = unsafe { __cpuid_count(0xd_u32, 1) }; + enable(proc_extended_state1_eax, 0, Feature::xsaveopt); + enable(proc_extended_state1_eax, 1, Feature::xsavec); + enable(proc_extended_state1_eax, 3, Feature::xsaves); + } + + // FMA (uses 256-bit wide registers): + enable(proc_info_ecx, 12, Feature::fma); + + // And AVX/AVX2: + enable(proc_info_ecx, 28, Feature::avx); + enable(extended_features_ebx, 5, Feature::avx2); + + // For AVX-512 the OS also needs to support saving/restoring + // the extended state, only then we enable AVX-512 support: + if os_avx512_support { + enable(extended_features_ebx, 16, Feature::avx512f); + enable(extended_features_ebx, 17, Feature::avx512dq); + enable(extended_features_ebx, 21, Feature::avx512_ifma); + enable(extended_features_ebx, 26, Feature::avx512pf); + enable(extended_features_ebx, 27, Feature::avx512er); + enable(extended_features_ebx, 28, Feature::avx512cd); + enable(extended_features_ebx, 30, Feature::avx512bw); + enable(extended_features_ebx, 31, Feature::avx512vl); + enable(extended_features_ecx, 1, Feature::avx512_vbmi); + enable(extended_features_ecx, 14, Feature::avx512_vpopcntdq); + } + } + } + } + + // This detects ABM on AMD CPUs and LZCNT on Intel CPUs. + // On intel CPUs with popcnt, lzcnt implements the + // "missing part" of ABM, so we map both to the same + // internal feature. + // + // The `is_x86_feature_detected!("lzcnt")` macro then + // internally maps to Feature::abm. + enable(extended_proc_info_ecx, 5, Feature::abm); + // As Hygon Dhyana originates from AMD technology and shares most of the architecture with + // AMD's family 17h, but with different CPU Vendor ID("HygonGenuine")/Family series + // number(Family 18h). + // + // For CPUID feature bits, Hygon Dhyana(family 18h) share the same definition with AMD + // family 17h. + // + // Related AMD CPUID specification is https://www.amd.com/system/files/TechDocs/25481.pdf. + // Related Hygon kernel patch can be found on + // http://lkml.kernel.org/r/5ce86123a7b9dad925ac583d88d2f921040e859b.1538583282.git.puwen@hygon.cn + if vendor_id == *b"AuthenticAMD" || vendor_id == *b"HygonGenuine" { + // These features are available on AMD arch CPUs: + enable(extended_proc_info_ecx, 6, Feature::sse4a); + enable(extended_proc_info_ecx, 21, Feature::tbm); + } + } + + value +} + +#[cfg(test)] +mod tests { + extern crate cupid; + + #[test] + fn dump() { + println!("aes: {:?}", is_x86_feature_detected!("aes")); + println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq")); + println!("rdrand: {:?}", is_x86_feature_detected!("rdrand")); + println!("rdseed: {:?}", is_x86_feature_detected!("rdseed")); + println!("tsc: {:?}", is_x86_feature_detected!("tsc")); + println!("sse: {:?}", is_x86_feature_detected!("sse")); + println!("sse2: {:?}", is_x86_feature_detected!("sse2")); + println!("sse3: {:?}", is_x86_feature_detected!("sse3")); + println!("ssse3: {:?}", is_x86_feature_detected!("ssse3")); + println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1")); + println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2")); + println!("sse4a: {:?}", is_x86_feature_detected!("sse4a")); + println!("sha: {:?}", is_x86_feature_detected!("sha")); + println!("avx: {:?}", is_x86_feature_detected!("avx")); + println!("avx2: {:?}", is_x86_feature_detected!("avx2")); + println!("avx512f {:?}", is_x86_feature_detected!("avx512f")); + println!("avx512cd {:?}", is_x86_feature_detected!("avx512cd")); + println!("avx512er {:?}", is_x86_feature_detected!("avx512er")); + println!("avx512pf {:?}", is_x86_feature_detected!("avx512pf")); + println!("avx512bw {:?}", is_x86_feature_detected!("avx512bw")); + println!("avx512dq {:?}", is_x86_feature_detected!("avx512dq")); + println!("avx512vl {:?}", is_x86_feature_detected!("avx512vl")); + println!("avx512_ifma {:?}", is_x86_feature_detected!("avx512ifma")); + println!("avx512_vbmi {:?}", is_x86_feature_detected!("avx512vbmi")); + println!( + "avx512_vpopcntdq {:?}", + is_x86_feature_detected!("avx512vpopcntdq") + ); + println!("fma: {:?}", is_x86_feature_detected!("fma")); + println!("abm: {:?}", is_x86_feature_detected!("abm")); + println!("bmi: {:?}", is_x86_feature_detected!("bmi1")); + println!("bmi2: {:?}", is_x86_feature_detected!("bmi2")); + println!("tbm: {:?}", is_x86_feature_detected!("tbm")); + println!("popcnt: {:?}", is_x86_feature_detected!("popcnt")); + println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt")); + println!("fxsr: {:?}", is_x86_feature_detected!("fxsr")); + println!("xsave: {:?}", is_x86_feature_detected!("xsave")); + println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt")); + println!("xsaves: {:?}", is_x86_feature_detected!("xsaves")); + println!("xsavec: {:?}", is_x86_feature_detected!("xsavec")); + println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b")); + println!("adx: {:?}", is_x86_feature_detected!("adx")); + println!("rtm: {:?}", is_x86_feature_detected!("rtm")); + } + + #[test] + fn compare_with_cupid() { + let information = cupid::master().unwrap(); + assert_eq!(is_x86_feature_detected!("aes"), information.aesni()); + assert_eq!( + is_x86_feature_detected!("pclmulqdq"), + information.pclmulqdq() + ); + assert_eq!(is_x86_feature_detected!("rdrand"), information.rdrand()); + assert_eq!(is_x86_feature_detected!("rdseed"), information.rdseed()); + assert_eq!(is_x86_feature_detected!("tsc"), information.tsc()); + assert_eq!(is_x86_feature_detected!("sse"), information.sse()); + assert_eq!(is_x86_feature_detected!("sse2"), information.sse2()); + assert_eq!(is_x86_feature_detected!("sse3"), information.sse3()); + assert_eq!(is_x86_feature_detected!("ssse3"), information.ssse3()); + assert_eq!(is_x86_feature_detected!("sse4.1"), information.sse4_1()); + assert_eq!(is_x86_feature_detected!("sse4.2"), information.sse4_2()); + assert_eq!(is_x86_feature_detected!("sse4a"), information.sse4a()); + assert_eq!(is_x86_feature_detected!("sha"), information.sha()); + assert_eq!(is_x86_feature_detected!("avx"), information.avx()); + assert_eq!(is_x86_feature_detected!("avx2"), information.avx2()); + assert_eq!(is_x86_feature_detected!("avx512f"), information.avx512f()); + assert_eq!(is_x86_feature_detected!("avx512cd"), information.avx512cd()); + assert_eq!(is_x86_feature_detected!("avx512er"), information.avx512er()); + assert_eq!(is_x86_feature_detected!("avx512pf"), information.avx512pf()); + assert_eq!(is_x86_feature_detected!("avx512bw"), information.avx512bw()); + assert_eq!(is_x86_feature_detected!("avx512dq"), information.avx512dq()); + assert_eq!(is_x86_feature_detected!("avx512vl"), information.avx512vl()); + assert_eq!( + is_x86_feature_detected!("avx512ifma"), + information.avx512_ifma() + ); + assert_eq!( + is_x86_feature_detected!("avx512vbmi"), + information.avx512_vbmi() + ); + assert_eq!( + is_x86_feature_detected!("avx512vpopcntdq"), + information.avx512_vpopcntdq() + ); + assert_eq!(is_x86_feature_detected!("fma"), information.fma()); + assert_eq!(is_x86_feature_detected!("bmi1"), information.bmi1()); + assert_eq!(is_x86_feature_detected!("bmi2"), information.bmi2()); + assert_eq!(is_x86_feature_detected!("popcnt"), information.popcnt()); + assert_eq!(is_x86_feature_detected!("abm"), information.lzcnt()); + assert_eq!(is_x86_feature_detected!("tbm"), information.tbm()); + assert_eq!(is_x86_feature_detected!("lzcnt"), information.lzcnt()); + assert_eq!(is_x86_feature_detected!("xsave"), information.xsave()); + assert_eq!(is_x86_feature_detected!("xsaveopt"), information.xsaveopt()); + assert_eq!( + is_x86_feature_detected!("xsavec"), + information.xsavec_and_xrstor() + ); + assert_eq!( + is_x86_feature_detected!("xsaves"), + information.xsaves_xrstors_and_ia32_xss() + ); + assert_eq!( + is_x86_feature_detected!("cmpxchg16b"), + information.cmpxchg16b(), + ); + assert_eq!(is_x86_feature_detected!("adx"), information.adx(),); + assert_eq!(is_x86_feature_detected!("rtm"), information.rtm(),); + } +} diff --git a/tests/target/cfg_if/lib.rs b/tests/target/cfg_if/lib.rs new file mode 100644 index 00000000000..8b3bb304f1c --- /dev/null +++ b/tests/target/cfg_if/lib.rs @@ -0,0 +1,49 @@ +//! Run-time feature detection for the Rust standard library. +//! +//! To detect whether a feature is enabled in the system running the binary +//! use one of the appropriate macro for the target: +//! +//! * `x86` and `x86_64`: [`is_x86_feature_detected`] +//! * `arm`: [`is_arm_feature_detected`] +//! * `aarch64`: [`is_aarch64_feature_detected`] +//! * `mips`: [`is_mips_feature_detected`] +//! * `mips64`: [`is_mips64_feature_detected`] +//! * `powerpc`: [`is_powerpc_feature_detected`] +//! * `powerpc64`: [`is_powerpc64_feature_detected`] + +#![unstable(feature = "stdsimd", issue = "27731")] +#![feature(const_fn, staged_api, stdsimd, doc_cfg, allow_internal_unstable)] +#![allow(clippy::shadow_reuse)] +#![deny(clippy::missing_inline_in_public_items)] +#![cfg_attr(target_os = "linux", feature(linkage))] +#![cfg_attr(all(target_os = "freebsd", target_arch = "aarch64"), feature(asm))] +#![cfg_attr(stdsimd_strict, deny(warnings))] +#![cfg_attr(test, allow(unused_imports))] +#![no_std] + +#[macro_use] +extern crate cfg_if; + +cfg_if! { + if #[cfg(feature = "std_detect_file_io")] { + #[cfg_attr(test, macro_use(println))] + extern crate std; + + #[allow(unused_imports)] + use std::{arch, fs, io, mem, sync}; + } else { + #[cfg(test)] + #[macro_use(println)] + extern crate std; + + #[allow(unused_imports)] + use core::{arch, mem, sync}; + } +} + +#[cfg(feature = "std_detect_dlsym_getauxval")] +extern crate libc; + +#[doc(hidden)] +#[unstable(feature = "stdsimd", issue = "27731")] +pub mod detect; diff --git a/tests/target/cfg_if/mod.rs b/tests/target/cfg_if/mod.rs new file mode 100644 index 00000000000..b630e7ff383 --- /dev/null +++ b/tests/target/cfg_if/mod.rs @@ -0,0 +1,5 @@ +//! `std_detect` + +#[doc(hidden)] // unstable implementation detail +#[unstable(feature = "stdsimd", issue = "27731")] +pub mod detect; -- cgit 1.4.1-3-g733a5 From 47a11cd5166a605897beb678095d17abc66c136f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 9 Jun 2019 09:20:39 +0900 Subject: Format modules defined in cfg_attr (#3604) --- src/attr.rs | 33 +++ src/formatting.rs | 2 +- src/modules.rs | 340 ++++++++++++++++++++++----- src/modules/visitor.rs | 39 +++ src/test/mod.rs | 5 + tests/source/cfg_mod/bar.rs | 3 + tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs | 6 + tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs | 6 + tests/source/cfg_mod/foo.rs | 4 + tests/source/cfg_mod/mod.rs | 10 + tests/source/cfg_mod/other.rs | 1 + tests/source/cfg_mod/wasm32.rs | 4 + tests/target/cfg_mod/bar.rs | 3 + tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs | 3 + tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs | 3 + tests/target/cfg_mod/foo.rs | 3 + tests/target/cfg_mod/mod.rs | 10 + tests/target/cfg_mod/other.rs | 3 + tests/target/cfg_mod/wasm32.rs | 3 + 19 files changed, 415 insertions(+), 66 deletions(-) create mode 100644 tests/source/cfg_mod/bar.rs create mode 100644 tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs create mode 100644 tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs create mode 100644 tests/source/cfg_mod/foo.rs create mode 100644 tests/source/cfg_mod/mod.rs create mode 100644 tests/source/cfg_mod/other.rs create mode 100644 tests/source/cfg_mod/wasm32.rs create mode 100644 tests/target/cfg_mod/bar.rs create mode 100644 tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs create mode 100644 tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs create mode 100644 tests/target/cfg_mod/foo.rs create mode 100644 tests/target/cfg_mod/mod.rs create mode 100644 tests/target/cfg_mod/other.rs create mode 100644 tests/target/cfg_mod/wasm32.rs (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 78d88958ac7..8497917ab06 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -488,3 +488,36 @@ fn attr_prefix(attr: &ast::Attribute) -> &'static str { ast::AttrStyle::Outer => "#", } } + +pub(crate) trait MetaVisitor<'ast> { + fn visit_meta_item(&mut self, meta_item: &'ast ast::MetaItem) { + match meta_item.node { + ast::MetaItemKind::Word => self.visit_meta_word(meta_item), + ast::MetaItemKind::List(ref list) => self.visit_meta_list(meta_item, list), + ast::MetaItemKind::NameValue(ref lit) => self.visit_meta_name_value(meta_item, lit), + } + } + + fn visit_meta_list( + &mut self, + _meta_item: &'ast ast::MetaItem, + list: &'ast [ast::NestedMetaItem], + ) { + for nm in list { + self.visit_nested_meta_item(nm); + } + } + + fn visit_meta_word(&mut self, _meta_item: &'ast ast::MetaItem) {} + + fn visit_meta_name_value(&mut self, _meta_item: &'ast ast::MetaItem, _lit: &'ast ast::Lit) {} + + fn visit_nested_meta_item(&mut self, nm: &'ast ast::NestedMetaItem) { + match nm { + ast::NestedMetaItem::MetaItem(ref meta_item) => self.visit_meta_item(meta_item), + ast::NestedMetaItem::Literal(ref lit) => self.visit_literal(lit), + } + } + + fn visit_literal(&mut self, _lit: &'ast ast::Lit) {} +} diff --git a/src/formatting.rs b/src/formatting.rs index 0e98bca9896..d431dd2679c 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -105,7 +105,7 @@ fn format_project( ) .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - for (path, (module, _)) in files { + for (path, module) in files { let should_ignore = !input_is_stdin && ignore_path_set.is_match(&path); if (config.skip_children() && path != main_file) || should_ignore { continue; diff --git a/src/modules.rs b/src/modules.rs index e54bdb87570..18b91add17b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -3,19 +3,23 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::parse::{parser, DirectoryOwnership, ParseSess}; -use syntax::source_map; +use syntax::attr; +use syntax::parse::{ + new_sub_parser_from_file, parser, token, DirectoryOwnership, PResult, ParseSess, +}; +use syntax::source_map::{self, Span}; use syntax::symbol::sym; use syntax::visit::Visitor; -use syntax_pos::symbol::Symbol; +use syntax_pos::{self, symbol::Symbol, DUMMY_SP}; +use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; use crate::utils::contains_skip; mod visitor; -type FileModMap<'ast> = BTreeMap, String)>; +type FileModMap<'ast> = BTreeMap>; /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { @@ -40,13 +44,16 @@ impl<'a> Directory { } } -enum SubModKind { +#[derive(Clone)] +enum SubModKind<'a, 'ast> { /// `mod foo;` External(PathBuf, DirectoryOwnership), + /// `mod foo;` with multiple sources. + MultiExternal(Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)>), /// `#[path = "..."] mod foo {}` InternalWithPath(PathBuf), /// `mod foo {}` - Internal, + Internal(&'a ast::Item), } impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { @@ -86,64 +93,48 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.visit_mod_from_ast(&krate.module)?; } - self.file_map.insert( - root_filename.into(), - (Cow::Borrowed(&krate.module), String::new()), - ); + self.file_map + .insert(root_filename.into(), Cow::Borrowed(&krate.module)); Ok(self.file_map) } - /// Visit macro calls and look for module declarations. Currently only supports `cfg_if` macro. - fn visit_mac(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { + /// Visit `cfg_if` macro and look for module declarations. + fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess, self.directory.to_syntax_directory()); visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.node { - self.visit_mod_from_mac_inner(&item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; } } Ok(()) } /// Visit modules defined inside macro calls. - fn visit_mod_from_macro(&mut self, module: Cow<'ast, ast::Mod>) -> Result<(), String> { - for item in &module.items { - if let ast::ItemKind::Mac(..) = item.node { - self.visit_mac(Cow::Owned(item.clone().into_inner()))?; + fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), String> { + for item in module.items { + if is_cfg_if(&item) { + self.visit_cfg_if(Cow::Owned(item.into_inner()))?; + continue; } if let ast::ItemKind::Mod(ref sub_mod) = item.node { - self.visit_mod_from_mac_inner(item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; } } Ok(()) } - fn visit_mod_from_mac_inner( - &mut self, - item: &'c ast::Item, - sub_mod: Cow<'ast, ast::Mod>, - ) -> Result<(), String> { - let old_directory = self.directory.clone(); - self.visit_sub_mod(item, &sub_mod)?; - self.visit_mod_from_macro(sub_mod)?; - self.directory = old_directory; - Ok(()) - } - /// Visit modules from AST. fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), String> { for item in &module.items { - if let ast::ItemKind::Mac(..) = item.node { - self.visit_mac(Cow::Borrowed(item))?; + if is_cfg_if(item) { + self.visit_cfg_if(Cow::Borrowed(item))?; } if let ast::ItemKind::Mod(ref sub_mod) = item.node { - let old_directory = self.directory.clone(); - self.visit_sub_mod(item, &Cow::Borrowed(sub_mod))?; - self.visit_mod_from_ast(sub_mod)?; - self.directory = old_directory; + self.visit_sub_mod(item, Cow::Borrowed(sub_mod))?; } } Ok(()) @@ -152,34 +143,24 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn visit_sub_mod( &mut self, item: &'c ast::Item, - sub_mod: &Cow<'ast, ast::Mod>, + sub_mod: Cow<'ast, ast::Mod>, ) -> Result<(), String> { - match self.peek_sub_mod(item)? { - Some(SubModKind::External(mod_path, directory_ownership)) => { - self.file_map.insert( - FileName::Real(mod_path.clone()), - (sub_mod.clone(), item.ident.name.as_str().get().to_owned()), - ); - self.directory = Directory { - path: mod_path.parent().unwrap().to_path_buf(), - ownership: directory_ownership, - }; - } - Some(SubModKind::InternalWithPath(mod_path)) => { - // All `#[path]` files are treated as though they are a `mod.rs` file. - self.directory = Directory { - path: mod_path, - ownership: DirectoryOwnership::Owned { relative: None }, - }; - } - Some(SubModKind::Internal) => self.push_inline_mod_directory(item.ident, &item.attrs), - None => (), // rustfmt::skip + let old_directory = self.directory.clone(); + let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?; + if let Some(sub_mod_kind) = sub_mod_kind { + self.insert_sub_mod(sub_mod_kind.clone(), sub_mod.clone())?; + self.visit_sub_mod_inner(sub_mod, sub_mod_kind)?; } + self.directory = old_directory; Ok(()) } /// Inspect the given sub-module which we are about to visit and returns its kind. - fn peek_sub_mod(&self, item: &'c ast::Item) -> Result, String> { + fn peek_sub_mod( + &self, + item: &'c ast::Item, + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Result>, String> { if contains_skip(&item.attrs) { return Ok(None); } @@ -187,30 +168,109 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if is_mod_decl(item) { // mod foo; // Look for an extern file. - let (mod_path, directory_ownership) = - self.find_external_module(item.ident, &item.attrs)?; - Ok(Some(SubModKind::External(mod_path, directory_ownership))) + self.find_external_module(item.ident, &item.attrs, sub_mod) + .map(Some) } else { // An internal module (`mod foo { /* ... */ }`); if let Some(path) = find_path_value(&item.attrs) { let path = Path::new(&path.as_str()).to_path_buf(); Ok(Some(SubModKind::InternalWithPath(path))) } else { - Ok(Some(SubModKind::Internal)) + Ok(Some(SubModKind::Internal(item))) } } } + fn insert_sub_mod( + &mut self, + sub_mod_kind: SubModKind<'c, 'ast>, + sub_mod: Cow<'ast, ast::Mod>, + ) -> Result<(), String> { + match sub_mod_kind { + SubModKind::External(mod_path, _) => { + self.file_map.insert(FileName::Real(mod_path), sub_mod); + } + SubModKind::MultiExternal(mods) => { + for (mod_path, _, sub_mod) in mods { + self.file_map.insert(FileName::Real(mod_path), sub_mod); + } + } + _ => (), + } + Ok(()) + } + + fn visit_sub_mod_inner( + &mut self, + sub_mod: Cow<'ast, ast::Mod>, + sub_mod_kind: SubModKind<'c, 'ast>, + ) -> Result<(), String> { + match sub_mod_kind { + SubModKind::External(mod_path, directory_ownership) => { + let directory = Directory { + path: mod_path.parent().unwrap().to_path_buf(), + ownership: directory_ownership, + }; + self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) + } + SubModKind::InternalWithPath(mod_path) => { + // All `#[path]` files are treated as though they are a `mod.rs` file. + let directory = Directory { + path: mod_path, + ownership: DirectoryOwnership::Owned { relative: None }, + }; + self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) + } + SubModKind::Internal(ref item) => { + self.push_inline_mod_directory(item.ident, &item.attrs); + self.visit_sub_mod_after_directory_update(sub_mod, None) + } + SubModKind::MultiExternal(mods) => { + for (mod_path, directory_ownership, sub_mod) in mods { + let directory = Directory { + path: mod_path.parent().unwrap().to_path_buf(), + ownership: directory_ownership, + }; + self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))?; + } + Ok(()) + } + } + } + + fn visit_sub_mod_after_directory_update( + &mut self, + sub_mod: Cow<'ast, ast::Mod>, + directory: Option, + ) -> Result<(), String> { + if let Some(directory) = directory { + self.directory = directory; + } + match sub_mod { + Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod), + Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod), + } + } + /// Find a file path in the filesystem which corresponds to the given module. fn find_external_module( &self, mod_name: ast::Ident, attrs: &[ast::Attribute], - ) -> Result<(PathBuf, DirectoryOwnership), String> { + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Result, String> { if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &self.directory.path) { - return Ok((path, DirectoryOwnership::Owned { relative: None })); + return Ok(SubModKind::External( + path, + DirectoryOwnership::Owned { relative: None }, + )); } + // Look for nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. + let mut mods_outside_ast = self + .find_mods_ouside_of_ast(attrs, sub_mod) + .unwrap_or(vec![]); + let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod(_) => None, @@ -227,7 +287,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { path, directory_ownership, .. - }) => Ok((path, directory_ownership)), + }) => Ok(if mods_outside_ast.is_empty() { + SubModKind::External(path, directory_ownership) + } else { + mods_outside_ast.push((path, directory_ownership, sub_mod.clone())); + SubModKind::MultiExternal(mods_outside_ast) + }), + Err(_) if !mods_outside_ast.is_empty() => { + Ok(SubModKind::MultiExternal(mods_outside_ast)) + } Err(_) => Err(format!( "Failed to find module {} in {:?} {:?}", mod_name, self.directory.path, relative, @@ -255,6 +323,89 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.directory.path.push(&id.as_str()); } } + + fn find_mods_ouside_of_ast( + &self, + attrs: &[ast::Attribute], + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Option)>> { + use std::panic::{catch_unwind, AssertUnwindSafe}; + Some( + catch_unwind(AssertUnwindSafe(|| { + self.find_mods_ouside_of_ast_inner(attrs, sub_mod) + })) + .ok()?, + ) + } + + fn find_mods_ouside_of_ast_inner( + &self, + attrs: &[ast::Attribute], + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)> { + // Filter nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. + let mut path_visitor = visitor::PathVisitor::default(); + for attr in attrs.iter() { + if let Some(meta) = attr.meta() { + path_visitor.visit_meta_item(&meta) + } + } + let mut result = vec![]; + for path in path_visitor.paths() { + let mut actual_path = self.directory.path.clone(); + actual_path.push(&path); + if !actual_path.exists() { + continue; + } + let file_name = syntax_pos::FileName::Real(actual_path.clone()); + if self + .parse_sess + .source_map() + .get_source_file(&file_name) + .is_some() + { + // If the specfied file is already parsed, then we just use that. + result.push(( + actual_path, + DirectoryOwnership::Owned { relative: None }, + sub_mod.clone(), + )); + continue; + } + let mut parser = new_sub_parser_from_file( + self.parse_sess, + &actual_path, + self.directory.ownership, + None, + DUMMY_SP, + ); + parser.cfg_mods = false; + let lo = parser.span; + // FIXME(topecongiro) Format inner attributes (#3606). + let _mod_attrs = match parse_inner_attributes(&mut parser) { + Ok(attrs) => attrs, + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + continue; + } + }; + let m = match parse_mod_items(&mut parser, lo) { + Ok(m) => m, + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + continue; + } + }; + result.push(( + actual_path, + DirectoryOwnership::Owned { relative: None }, + Cow::Owned(m), + )) + } + result + } } fn path_value(attr: &ast::Attribute) -> Option { @@ -271,3 +422,62 @@ fn path_value(attr: &ast::Attribute) -> Option { fn find_path_value(attrs: &[ast::Attribute]) -> Option { attrs.iter().flat_map(path_value).next() } + +// FIXME(topecongiro) Use the method from libsyntax[1] once it become public. +// +// [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs +fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Vec> { + let mut attrs: Vec = vec![]; + loop { + match parser.token { + token::Pound => { + // Don't even try to parse if it's not an inner attribute. + if !parser.look_ahead(1, |t| t == &token::Not) { + break; + } + + let attr = parser.parse_attribute(true)?; + assert_eq!(attr.style, ast::AttrStyle::Inner); + attrs.push(attr); + } + token::DocComment(s) => { + // we need to get the position of this token before we bump. + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, parser.span); + if attr.style == ast::AttrStyle::Inner { + attrs.push(attr); + parser.bump(); + } else { + break; + } + } + _ => break, + } + } + Ok(attrs) +} + +fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResult<'a, ast::Mod> { + let mut items = vec![]; + while let Some(item) = parser.parse_item()? { + items.push(item); + } + + let hi = if parser.span.is_dummy() { + inner_lo + } else { + parser.prev_span + }; + + Ok(ast::Mod { + inner: inner_lo.to(hi), + items, + inline: false, + }) +} + +fn is_cfg_if(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Mac(..) if item.ident.name == Symbol::intern("cfg_if") => true, + _ => false, + } +} diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 1086a1a026c..4b4b2acd913 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -5,6 +5,8 @@ use syntax::symbol::kw; use syntax::visit::Visitor; use syntax_pos::Symbol; +use crate::attr::MetaVisitor; + pub(crate) struct ModItem { pub(crate) item: ast::Item, } @@ -103,3 +105,40 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { Ok(()) } } + +/// Extracts `path = "foo.rs"` from attributes. +#[derive(Default)] +pub(crate) struct PathVisitor { + /// A list of path defined in attributes. + paths: Vec, +} + +impl PathVisitor { + pub(crate) fn paths(self) -> Vec { + self.paths + } +} + +impl<'ast> MetaVisitor<'ast> for PathVisitor { + fn visit_meta_name_value(&mut self, meta_item: &'ast ast::MetaItem, lit: &'ast ast::Lit) { + if meta_item.check_name(Symbol::intern("path")) && lit.node.is_str() { + self.paths.push(lit_to_str(lit)); + } + } +} + +#[cfg(not(windows))] +fn lit_to_str(lit: &ast::Lit) -> String { + match lit.node { + ast::LitKind::Str(symbol, ..) => symbol.to_string(), + _ => unreachable!(), + } +} + +#[cfg(windows)] +fn lit_to_str(lit: &ast::Lit) -> String { + match lit.node { + ast::LitKind::Str(symbol, ..) => symbol.as_str().replace("/", "\\"), + _ => unreachable!(), + } +} diff --git a/src/test/mod.rs b/src/test/mod.rs index c68b33b844f..96f6f2ce9ba 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -28,6 +28,11 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ // These files and directory are a part of modules defined inside `cfg_if!`. "cfg_if/mod.rs", "cfg_if/detect", + // These files and directory are a part of modules defined inside `cfg_attr(..)`. + "cfg_mod/dir", + "cfg_mod/bar.rs", + "cfg_mod/foo.rs", + "cfg_mod/wasm32.rs", ]; struct TestSetting { diff --git a/tests/source/cfg_mod/bar.rs b/tests/source/cfg_mod/bar.rs new file mode 100644 index 00000000000..5b6b5f43837 --- /dev/null +++ b/tests/source/cfg_mod/bar.rs @@ -0,0 +1,3 @@ +fn bar( ) -> &str { +"bar" +} diff --git a/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs b/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs new file mode 100644 index 00000000000..0f8c0a3a7ac --- /dev/null +++ b/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs @@ -0,0 +1,6 @@ +fn + wasm32 + () -> &str +{ + "wasm32" +} diff --git a/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs b/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs new file mode 100644 index 00000000000..0f8c0a3a7ac --- /dev/null +++ b/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs @@ -0,0 +1,6 @@ +fn + wasm32 + () -> &str +{ + "wasm32" +} diff --git a/tests/source/cfg_mod/foo.rs b/tests/source/cfg_mod/foo.rs new file mode 100644 index 00000000000..de4ce55ef6f --- /dev/null +++ b/tests/source/cfg_mod/foo.rs @@ -0,0 +1,4 @@ +fn foo( ) + -> &str { + "foo" +} diff --git a/tests/source/cfg_mod/mod.rs b/tests/source/cfg_mod/mod.rs new file mode 100644 index 00000000000..45ba86f11b3 --- /dev/null +++ b/tests/source/cfg_mod/mod.rs @@ -0,0 +1,10 @@ +#[cfg_attr(feature = "foo", path = "foo.rs")] +#[cfg_attr(not(feture = "foo"), path = "bar.rs")] +mod sub_mod; + +#[cfg_attr(target_arch = "wasm32", path = "dir/dir1/dir2/wasm32.rs")] +#[cfg_attr(not(target_arch = "wasm32"), path = "dir/dir1/dir3/wasm32.rs")] +mod wasm32; + +#[some_attr(path = "somewhere.rs")] +mod other; diff --git a/tests/source/cfg_mod/other.rs b/tests/source/cfg_mod/other.rs new file mode 100644 index 00000000000..0b5c04d2192 --- /dev/null +++ b/tests/source/cfg_mod/other.rs @@ -0,0 +1 @@ +fn other() -> &str { "other"} diff --git a/tests/source/cfg_mod/wasm32.rs b/tests/source/cfg_mod/wasm32.rs new file mode 100644 index 00000000000..3741e53fd4e --- /dev/null +++ b/tests/source/cfg_mod/wasm32.rs @@ -0,0 +1,4 @@ +fn + wasm32() -> &str { + "wasm32" + } diff --git a/tests/target/cfg_mod/bar.rs b/tests/target/cfg_mod/bar.rs new file mode 100644 index 00000000000..20dc5b4a080 --- /dev/null +++ b/tests/target/cfg_mod/bar.rs @@ -0,0 +1,3 @@ +fn bar() -> &str { + "bar" +} diff --git a/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs b/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs new file mode 100644 index 00000000000..ac437e4225a --- /dev/null +++ b/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs @@ -0,0 +1,3 @@ +fn wasm32() -> &str { + "wasm32" +} diff --git a/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs b/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs new file mode 100644 index 00000000000..ac437e4225a --- /dev/null +++ b/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs @@ -0,0 +1,3 @@ +fn wasm32() -> &str { + "wasm32" +} diff --git a/tests/target/cfg_mod/foo.rs b/tests/target/cfg_mod/foo.rs new file mode 100644 index 00000000000..053c8e6f3ed --- /dev/null +++ b/tests/target/cfg_mod/foo.rs @@ -0,0 +1,3 @@ +fn foo() -> &str { + "foo" +} diff --git a/tests/target/cfg_mod/mod.rs b/tests/target/cfg_mod/mod.rs new file mode 100644 index 00000000000..45ba86f11b3 --- /dev/null +++ b/tests/target/cfg_mod/mod.rs @@ -0,0 +1,10 @@ +#[cfg_attr(feature = "foo", path = "foo.rs")] +#[cfg_attr(not(feture = "foo"), path = "bar.rs")] +mod sub_mod; + +#[cfg_attr(target_arch = "wasm32", path = "dir/dir1/dir2/wasm32.rs")] +#[cfg_attr(not(target_arch = "wasm32"), path = "dir/dir1/dir3/wasm32.rs")] +mod wasm32; + +#[some_attr(path = "somewhere.rs")] +mod other; diff --git a/tests/target/cfg_mod/other.rs b/tests/target/cfg_mod/other.rs new file mode 100644 index 00000000000..5929b8dcf53 --- /dev/null +++ b/tests/target/cfg_mod/other.rs @@ -0,0 +1,3 @@ +fn other() -> &str { + "other" +} diff --git a/tests/target/cfg_mod/wasm32.rs b/tests/target/cfg_mod/wasm32.rs new file mode 100644 index 00000000000..ac437e4225a --- /dev/null +++ b/tests/target/cfg_mod/wasm32.rs @@ -0,0 +1,3 @@ +fn wasm32() -> &str { + "wasm32" +} -- cgit 1.4.1-3-g733a5 From 0e3cf08ff10b099e0336b8c7a7282d7197ac3f77 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 9 Jun 2019 21:28:57 +0900 Subject: Release 1.3.0 (#3611) --- Cargo.lock | 209 ++++++++++++++++++++++++------------------------ Cargo.toml | 8 +- src/config/mod.rs | 2 +- src/macros.rs | 212 +++++++++++++++++++++++++++++-------------------- src/modules.rs | 16 ++-- src/modules/visitor.rs | 13 +-- src/types.rs | 27 +++++-- 7 files changed, 268 insertions(+), 219 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index a14828ed62f..3b07550bd21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,7 +46,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -58,14 +58,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.26" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -74,12 +74,12 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -119,8 +119,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -141,7 +141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -153,7 +153,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -162,7 +162,7 @@ version = "0.1.0" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -226,7 +226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -239,7 +239,7 @@ name = "dirs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -266,7 +266,7 @@ dependencies = [ "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -274,7 +274,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -283,7 +283,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -294,7 +294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -384,7 +384,7 @@ name = "jobserver" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -396,7 +396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.55" +version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -436,7 +436,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -474,7 +474,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -508,7 +508,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -563,7 +563,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -575,7 +575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -652,31 +652,31 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -686,9 +686,9 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -698,47 +698,48 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_macros" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -747,39 +748,39 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "486.0.0" +version = "491.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -807,7 +808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -826,7 +827,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.2.2" +version = "1.3.0" dependencies = [ "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -844,13 +845,13 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -892,7 +893,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -902,20 +903,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -925,7 +926,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -945,27 +946,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.34" +version = "0.15.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -980,7 +981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -996,7 +997,7 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1007,7 +1008,7 @@ name = "termion" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1034,7 +1035,7 @@ name = "toml" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1131,9 +1132,9 @@ dependencies = [ "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1a13fc43f04daf08ab4f71e3d27e1fc27fc437d3e95ac0063a796d92fb40f39b" +"checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "59604ece62a407dc9164732e5adea02467898954c3a5811fd2dc140af14ef15b" "checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" @@ -1170,7 +1171,7 @@ dependencies = [ "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b3d51e24009d966c8285d524dbaf6d60926636b2a89caee9ce0bd612494ddc16" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" +"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" @@ -1201,17 +1202,17 @@ dependencies = [ "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum rustc-ap-arena 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af30808ea1dad5e3967d1997d97f32829ff9a999686768aac694ca20a8ca5507" -"checksum rustc-ap-graphviz 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8c4bc0c92187923ced8e6d1cbdde129b0fce020af817d8a889fddc36d81429" -"checksum rustc-ap-rustc_cratesio_shim 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "724100fb95b88e6f2a870cd957d60fc4f62d7a26f1e5b889ebcb090965118d33" -"checksum rustc-ap-rustc_data_structures 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d178c2ffcacf8e95d3af281b23d382ef8efce581bdd487a8fac38624a52344f" -"checksum rustc-ap-rustc_errors 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229720cd73ce22a76e763f6554653863f91667c624bc92f89422beeb72002ebb" -"checksum rustc-ap-rustc_macros 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd85f5873ed31ab1d511e132743e08f14c88d912dfcf1d7949b7d5666ba030e7" -"checksum rustc-ap-rustc_target 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "190dbb1a01e51b2280387cc18985382e785da2264473ff9a86ad6917c8343a6e" -"checksum rustc-ap-serialize 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de6ea7e67ea3b8ddee324339bf4369c9af5c72a664b98f33083f8480c1df3b4" -"checksum rustc-ap-syntax 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4620f48399b89ab3eee54e81c0206e60645ce7b658269f09a7a9752f66c78fa1" -"checksum rustc-ap-syntax_pos 486.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bf89da0ea5cde2c8ab974aaf7941ac4e1c9ba9cd2e00e3814974bd4a2bfe68" -"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" +"checksum rustc-ap-arena 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc0ad4318f3425229ed7b117275368b83269bec75f9609d4965dcb9752483c86" +"checksum rustc-ap-graphviz 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b80b7ea7902919f397c4bb12d102abe896fced7893d09d84bcac233e555bb388" +"checksum rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "752463d2b80039d23e42e667a9f6fe08213bd865f6ea301fb35f8068d94955ac" +"checksum rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3d6a14181e11c132d0ef97a6c27e1bb1d4da09682d02222393875c10d1c364" +"checksum rustc-ap-rustc_errors 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55caea8426565de362e8df0df737e43b9f22d632e0e52710cbfe316acc6ce2f0" +"checksum rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "071420d762d2c779d1d4972356f37f5d049dcdd6c49e78f1b037e04c5a0f1a19" +"checksum rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5464696d0748e3019b9e5daca5fcadc53889dc2bca1dc26bf42001fd1c4194f" +"checksum rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9464445c11c15cf32ef27815b3ec89315b0ed73c6c771cbcf8543be59a3c1502" +"checksum rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff53245ae370d8e8073dc9cc13f8921e6110d0ccd208b64c388c5653fa6b9c83" +"checksum rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41896f0eb2eb2f4ddba406939aa6b07386160fa38bee8cde3f7f0d85663e3d47" +"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" "checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" @@ -1224,18 +1225,18 @@ dependencies = [ "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" -"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" +"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" +"checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3d0760c312538987d363c36c42339b55f5ee176ea8808bbe4543d484a291c8d1" -"checksum structopt-derive 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "528aeb7351d042e6ffbc2a6fb76a86f9b622fdf7c25932798e7a82cb03bc94c6" -"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" +"checksum structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c767a8971f53d7324583085deee2e230903be09e52fb27df9af94c5cb2b43c31" +"checksum structopt-derive 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c57a30c87454ced2186f62f940e981746e8cbbe026d52090c8c4352b636f8235" +"checksum syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)" = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" -"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" diff --git a/Cargo.toml b/Cargo.toml index 92418a49ec5..251399510ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.2.2" +version = "1.3.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.7" -rustc-ap-rustc_target = "486.0.0" -rustc-ap-syntax = "486.0.0" -rustc-ap-syntax_pos = "486.0.0" +rustc-ap-rustc_target = "491.0.0" +rustc-ap-syntax = "491.0.0" +rustc-ap-syntax_pos = "491.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/config/mod.rs b/src/config/mod.rs index 1b9e97fc5bf..27044ee18d6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.2.2" +required_version = "1.3.0" unstable_features = false disable_all_formatting = false skip_children = false diff --git a/src/macros.rs b/src/macros.rs index 7122a60f2cf..ac00e4452a7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -14,14 +14,14 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use syntax::parse::new_parser_from_tts; use syntax::parse::parser::Parser; -use syntax::parse::token::{BinOpToken, DelimToken, Token}; +use syntax::parse::token::{BinOpToken, DelimToken, Token, TokenKind}; use syntax::print::pprust; use syntax::source_map::{BytePos, Span}; use syntax::symbol::kw; use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, parse, ptr}; -use syntax_pos::Symbol; +use syntax_pos::{Symbol, DUMMY_SP}; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, @@ -235,13 +235,14 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { for &keyword in RUST_KW.iter() { if parser.token.is_keyword(keyword) && parser.look_ahead(1, |t| { - *t == Token::Eof - || *t == Token::Comma - || *t == Token::CloseDelim(DelimToken::NoDelim) + t.kind == TokenKind::Eof + || t.kind == TokenKind::Comma + || t.kind == TokenKind::CloseDelim(DelimToken::NoDelim) }) { - let macro_arg = MacroArg::Keyword(ast::Ident::with_empty_ctxt(keyword), parser.span); parser.bump(); + let macro_arg = + MacroArg::Keyword(ast::Ident::with_empty_ctxt(keyword), parser.prev_span); return Some(macro_arg); } } @@ -311,19 +312,19 @@ fn rewrite_macro_inner( return return_macro_parse_failure_fallback(context, shape.indent, mac.span); } - match parser.token { - Token::Eof => break, - Token::Comma => (), - Token::Semi => { + match parser.token.kind { + TokenKind::Eof => break, + TokenKind::Comma => (), + TokenKind::Semi => { // Try to parse `vec![expr; expr]` if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { parser.bump(); - if parser.token != Token::Eof { + if parser.token.kind != TokenKind::Eof { match parse_macro_arg(&mut parser) { Some(arg) => { arg_vec.push(arg); parser.bump(); - if parser.token == Token::Eof && arg_vec.len() == 2 { + if parser.token.kind == TokenKind::Eof && arg_vec.len() == 2 { vec_with_semi = true; break; } @@ -346,7 +347,7 @@ fn rewrite_macro_inner( parser.bump(); - if parser.token == Token::Eof { + if parser.token.kind == TokenKind::Eof { trailing_comma = true; break; } @@ -629,7 +630,7 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { #[derive(Debug, Clone)] enum MacroArgKind { /// e.g., `$x: expr`. - MetaVariable(ast::Ident, String), + MetaVariable(ast::Name, String), /// e.g., `$($foo: expr),*` Repeat( /// `()`, `[]` or `{}`. @@ -737,9 +738,7 @@ impl MacroArgKind { }; match *self { - MacroArgKind::MetaVariable(ty, ref name) => { - Some(format!("${}:{}", name, ty.name.as_str())) - } + MacroArgKind::MetaVariable(ty, ref name) => Some(format!("${}:{}", name, ty)), MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => { let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?; let another = another @@ -797,8 +796,11 @@ struct MacroArgParser { fn last_tok(tt: &TokenTree) -> Token { match *tt { - TokenTree::Token(_, ref t) => t.clone(), - TokenTree::Delimited(_, delim, _) => Token::CloseDelim(delim), + TokenTree::Token(ref t) => t.clone(), + TokenTree::Delimited(delim_span, delim, _) => Token { + kind: TokenKind::CloseDelim(delim), + span: delim_span.close, + }, } } @@ -809,8 +811,14 @@ impl MacroArgParser { hi: BytePos(0), buf: String::new(), is_meta_var: false, - last_tok: Token::Eof, - start_tok: Token::Eof, + last_tok: Token { + kind: TokenKind::Eof, + span: DUMMY_SP, + }, + start_tok: Token { + kind: TokenKind::Eof, + span: DUMMY_SP, + }, result: vec![], } } @@ -848,10 +856,13 @@ impl MacroArgParser { fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> { match iter.next() { - Some(TokenTree::Token(sp, Token::Ident(ref ident, _))) => { + Some(TokenTree::Token(Token { + kind: TokenKind::Ident(name, _), + span, + })) => { self.result.push(ParsedMacroArg { - kind: MacroArgKind::MetaVariable(*ident, self.buf.clone()), - span: mk_sp(self.lo, sp.hi()), + kind: MacroArgKind::MetaVariable(name, self.buf.clone()), + span: mk_sp(self.lo, span.hi()), }); self.buf.clear(); @@ -891,14 +902,23 @@ impl MacroArgParser { } match tok { - TokenTree::Token(_, Token::BinOp(BinOpToken::Plus)) - | TokenTree::Token(_, Token::Question) - | TokenTree::Token(_, Token::BinOp(BinOpToken::Star)) => { + TokenTree::Token(Token { + kind: TokenKind::BinOp(BinOpToken::Plus), + .. + }) + | TokenTree::Token(Token { + kind: TokenKind::Question, + .. + }) + | TokenTree::Token(Token { + kind: TokenKind::BinOp(BinOpToken::Star), + .. + }) => { break; } - TokenTree::Token(sp, ref t) => { - buffer.push_str(&pprust::token_to_string(t)); - hi = sp.hi(); + TokenTree::Token(ref t) => { + buffer.push_str(&pprust::token_to_string(&t.kind)); + hi = t.span.hi(); } _ => return None, } @@ -921,9 +941,9 @@ impl MacroArgParser { Some(()) } - fn update_buffer(&mut self, lo: BytePos, t: &Token) { + fn update_buffer(&mut self, t: &Token) { if self.buf.is_empty() { - self.lo = lo; + self.lo = t.span.lo(); self.start_tok = t.clone(); } else { let needs_space = match next_space(&self.last_tok) { @@ -950,7 +970,7 @@ impl MacroArgParser { if ident_like(&self.start_tok) { return true; } - if self.start_tok == Token::Colon { + if self.start_tok.kind == TokenKind::Colon { return true; } } @@ -968,7 +988,10 @@ impl MacroArgParser { while let Some(tok) = iter.next() { match tok { - TokenTree::Token(sp, Token::Dollar) => { + TokenTree::Token(Token { + kind: TokenKind::Dollar, + span, + }) => { // We always want to add a separator before meta variables. if !self.buf.is_empty() { self.add_separator(); @@ -976,13 +999,19 @@ impl MacroArgParser { // Start keeping the name of this metavariable in the buffer. self.is_meta_var = true; - self.lo = sp.lo(); - self.start_tok = Token::Dollar; + self.lo = span.lo(); + self.start_tok = Token { + kind: TokenKind::Dollar, + span, + }; } - TokenTree::Token(_, Token::Colon) if self.is_meta_var => { + TokenTree::Token(Token { + kind: TokenKind::Colon, + .. + }) if self.is_meta_var => { self.add_meta_variable(&mut iter)?; } - TokenTree::Token(sp, ref t) => self.update_buffer(sp.lo(), t), + TokenTree::Token(ref t) => self.update_buffer(t), TokenTree::Delimited(delimited_span, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok) == SpaceState::Always { @@ -1102,63 +1131,63 @@ enum SpaceState { Always, } -fn force_space_before(tok: &Token) -> bool { +fn force_space_before(tok: &TokenKind) -> bool { debug!("tok: force_space_before {:?}", tok); match tok { - Token::Eq - | Token::Lt - | Token::Le - | Token::EqEq - | Token::Ne - | Token::Ge - | Token::Gt - | Token::AndAnd - | Token::OrOr - | Token::Not - | Token::Tilde - | Token::BinOpEq(_) - | Token::At - | Token::RArrow - | Token::LArrow - | Token::FatArrow - | Token::BinOp(_) - | Token::Pound - | Token::Dollar => true, + TokenKind::Eq + | TokenKind::Lt + | TokenKind::Le + | TokenKind::EqEq + | TokenKind::Ne + | TokenKind::Ge + | TokenKind::Gt + | TokenKind::AndAnd + | TokenKind::OrOr + | TokenKind::Not + | TokenKind::Tilde + | TokenKind::BinOpEq(_) + | TokenKind::At + | TokenKind::RArrow + | TokenKind::LArrow + | TokenKind::FatArrow + | TokenKind::BinOp(_) + | TokenKind::Pound + | TokenKind::Dollar => true, _ => false, } } fn ident_like(tok: &Token) -> bool { - match tok { - Token::Ident(..) | Token::Literal(..) | Token::Lifetime(_) => true, + match tok.kind { + TokenKind::Ident(..) | TokenKind::Literal(..) | TokenKind::Lifetime(_) => true, _ => false, } } -fn next_space(tok: &Token) -> SpaceState { +fn next_space(tok: &TokenKind) -> SpaceState { debug!("next_space: {:?}", tok); match tok { - Token::Not - | Token::BinOp(BinOpToken::And) - | Token::Tilde - | Token::At - | Token::Comma - | Token::Dot - | Token::DotDot - | Token::DotDotDot - | Token::DotDotEq - | Token::Question => SpaceState::Punctuation, - - Token::ModSep - | Token::Pound - | Token::Dollar - | Token::OpenDelim(_) - | Token::CloseDelim(_) - | Token::Whitespace => SpaceState::Never, - - Token::Literal(..) | Token::Ident(..) | Token::Lifetime(_) => SpaceState::Ident, + TokenKind::Not + | TokenKind::BinOp(BinOpToken::And) + | TokenKind::Tilde + | TokenKind::At + | TokenKind::Comma + | TokenKind::Dot + | TokenKind::DotDot + | TokenKind::DotDotDot + | TokenKind::DotDotEq + | TokenKind::Question => SpaceState::Punctuation, + + TokenKind::ModSep + | TokenKind::Pound + | TokenKind::Dollar + | TokenKind::OpenDelim(_) + | TokenKind::CloseDelim(_) + | TokenKind::Whitespace => SpaceState::Never, + + TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(_) => SpaceState::Ident, _ => SpaceState::Always, } @@ -1225,7 +1254,10 @@ impl MacroParser { }; let args = tok.joint(); match self.toks.next()? { - TokenTree::Token(_, Token::FatArrow) => {} + TokenTree::Token(Token { + kind: TokenKind::FatArrow, + .. + }) => {} _ => return None, } let (mut hi, body, whole_body) = match self.toks.next()? { @@ -1239,9 +1271,13 @@ impl MacroParser { ) } }; - if let Some(TokenTree::Token(sp, Token::Semi)) = self.toks.look_ahead(0) { + if let Some(TokenTree::Token(Token { + kind: TokenKind::Semi, + span, + })) = self.toks.look_ahead(0) + { self.toks.next(); - hi = sp.hi(); + hi = span.hi(); } Some(MacroBranch { span: mk_sp(lo, hi), @@ -1423,17 +1459,17 @@ fn format_lazy_static( } } - while parser.token != Token::Eof { + while parser.token.kind != TokenKind::Eof { // Parse a `lazy_static!` item. let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false)); parser.eat_keyword(kw::Static); parser.eat_keyword(kw::Ref); let id = parse_or!(parse_ident); - parser.eat(&Token::Colon); + parser.eat(&TokenKind::Colon); let ty = parse_or!(parse_ty); - parser.eat(&Token::Eq); + parser.eat(&TokenKind::Eq); let expr = parse_or!(parse_expr); - parser.eat(&Token::Semi); + parser.eat(&TokenKind::Semi); // Rewrite as a static item. let mut stmt = String::with_capacity(128); @@ -1450,7 +1486,7 @@ fn format_lazy_static( nested_shape.sub_width(1)?, )?); result.push(';'); - if parser.token != Token::Eof { + if parser.token.kind != TokenKind::Eof { result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); } } diff --git a/src/modules.rs b/src/modules.rs index 18b91add17b..5f7e4310a07 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use syntax::ast; use syntax::attr; use syntax::parse::{ - new_sub_parser_from_file, parser, token, DirectoryOwnership, PResult, ParseSess, + new_sub_parser_from_file, parser, token::TokenKind, DirectoryOwnership, PResult, ParseSess, }; use syntax::source_map::{self, Span}; use syntax::symbol::sym; @@ -380,7 +380,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { DUMMY_SP, ); parser.cfg_mods = false; - let lo = parser.span; + let lo = parser.token.span; // FIXME(topecongiro) Format inner attributes (#3606). let _mod_attrs = match parse_inner_attributes(&mut parser) { Ok(attrs) => attrs, @@ -429,10 +429,10 @@ fn find_path_value(attrs: &[ast::Attribute]) -> Option { fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Vec> { let mut attrs: Vec = vec![]; loop { - match parser.token { - token::Pound => { + match parser.token.kind { + TokenKind::Pound => { // Don't even try to parse if it's not an inner attribute. - if !parser.look_ahead(1, |t| t == &token::Not) { + if !parser.look_ahead(1, |t| t == &TokenKind::Not) { break; } @@ -440,9 +440,9 @@ fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Ve assert_eq!(attr.style, ast::AttrStyle::Inner); attrs.push(attr); } - token::DocComment(s) => { + TokenKind::DocComment(s) => { // we need to get the position of this token before we bump. - let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, parser.span); + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, parser.token.span); if attr.style == ast::AttrStyle::Inner { attrs.push(attr); parser.bump(); @@ -462,7 +462,7 @@ fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResu items.push(item); } - let hi = if parser.span.is_dummy() { + let hi = if parser.token.span.is_dummy() { inner_lo } else { parser.prev_span diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 4b4b2acd913..3eb2e05b2d7 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -1,5 +1,5 @@ use syntax::ast; -use syntax::parse::token::{DelimToken, Token}; +use syntax::parse::token::{DelimToken, TokenKind}; use syntax::parse::{stream_to_parser_with_base_dir, Directory, ParseSess}; use syntax::symbol::kw; use syntax::visit::Visitor; @@ -55,7 +55,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { parser.cfg_mods = false; let mut process_if_cfg = true; - while parser.token != Token::Eof { + while parser.token.kind != TokenKind::Eof { if process_if_cfg { if !parser.eat_keyword(kw::If) { return Err("Expected `if`"); @@ -65,11 +65,12 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { .map_err(|_| "Failed to parse attributes")?; } - if !parser.eat(&Token::OpenDelim(DelimToken::Brace)) { + if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) { return Err("Expected an opening brace"); } - while parser.token != Token::CloseDelim(DelimToken::Brace) && parser.token != Token::Eof + while parser.token != TokenKind::CloseDelim(DelimToken::Brace) + && parser.token.kind != TokenKind::Eof { let item = match parser.parse_item() { Ok(Some(item_ptr)) => item_ptr.into_inner(), @@ -87,11 +88,11 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } } - if !parser.eat(&Token::CloseDelim(DelimToken::Brace)) { + if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) { return Err("Expected a closing brace"); } - if parser.eat(&Token::Eof) { + if parser.eat(&TokenKind::Eof) { break; } diff --git a/src/types.rs b/src/types.rs index 70b8413836d..c15a580f1a8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -137,7 +137,7 @@ pub(crate) enum SegmentParam<'a> { Const(&'a ast::AnonConst), LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), - Binding(&'a ast::TypeBinding), + Binding(&'a ast::AssocTyConstraint), } impl<'a> SegmentParam<'a> { @@ -167,16 +167,18 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::Const(const_) => const_.rewrite(context, shape), SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), - SegmentParam::Binding(binding) => { + SegmentParam::Binding(assoc_ty_constraint) => { let mut result = match context.config.type_punctuation_density() { - TypeDensity::Wide => format!("{} = ", rewrite_ident(context, binding.ident)), + TypeDensity::Wide => { + format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident)) + } TypeDensity::Compressed => { - format!("{}=", rewrite_ident(context, binding.ident)) + format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident)) } }; let budget = shape.width.checked_sub(result.len())?; - let rewrite = binding - .ty + let rewrite = assoc_ty_constraint + .kind .rewrite(context, Shape::legacy(budget, shape.indent + result.len()))?; result.push_str(&rewrite); Some(result) @@ -185,6 +187,15 @@ impl<'a> Rewrite for SegmentParam<'a> { } } +impl Rewrite for ast::AssocTyConstraintKind { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + match self { + ast::AssocTyConstraintKind::Equality { ty } => ty.rewrite(context, shape), + ast::AssocTyConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), + } + } +} + // Formats a path segment. There are some hacks involved to correctly determine // the segment's associated span since it's not part of the AST. // @@ -216,13 +227,13 @@ fn rewrite_segment( if let Some(ref args) = segment.args { match **args { ast::GenericArgs::AngleBracketed(ref data) - if !data.args.is_empty() || !data.bindings.is_empty() => + if !data.args.is_empty() || !data.constraints.is_empty() => { let param_list = data .args .iter() .map(SegmentParam::from_generic_arg) - .chain(data.bindings.iter().map(|x| SegmentParam::Binding(&*x))) + .chain(data.constraints.iter().map(|x| SegmentParam::Binding(&*x))) .collect::>(); // HACK: squeeze out the span between the identifier and the parameters. -- cgit 1.4.1-3-g733a5 From d33450247b17d92a951d9663822c5a3635a37dde Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 9 Jun 2019 22:29:36 +0900 Subject: Rename config_proc_macro to rustfmt-config_proc_macro --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 2 +- config_proc_macro/Cargo.lock | 20 ++++++++++---------- config_proc_macro/Cargo.toml | 6 +++++- src/config/lists.rs | 2 +- src/config/options.rs | 2 +- 6 files changed, 28 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 3b07550bd21..5bd8d006b4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,15 +156,6 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "config_proc_macro" -version = "0.1.0" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "constant_time_eq" version = "0.1.3" @@ -825,6 +816,15 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustfmt-config_proc_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustfmt-nightly" version = "1.3.0" @@ -833,7 +833,6 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "config_proc_macro 0.1.0", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -849,6 +848,7 @@ dependencies = [ "rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-config_proc_macro 0.1.0", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 251399510ba..dd282f70a0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ ignore = "0.4.6" annotate-snippets = { version = "0.5.0", features = ["ansi_term"] } structopt = "0.2.15" -config_proc_macro = { path = "config_proc_macro" } +rustfmt-config_proc_macro = { version = "0.1", path = "config_proc_macro" } # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/config_proc_macro/Cargo.lock b/config_proc_macro/Cargo.lock index 6ee8e34b13f..f1efb8e7dfd 100644 --- a/config_proc_macro/Cargo.lock +++ b/config_proc_macro/Cargo.lock @@ -1,15 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "config_proc_macro" -version = "0.1.0" -dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro2" version = "0.4.27" @@ -26,6 +16,16 @@ dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustfmt-config_proc_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde" version = "1.0.89" diff --git a/config_proc_macro/Cargo.toml b/config_proc_macro/Cargo.toml index 45f80bf0956..033cc0aaf1f 100644 --- a/config_proc_macro/Cargo.toml +++ b/config_proc_macro/Cargo.toml @@ -1,8 +1,12 @@ [package] -name = "config_proc_macro" +name = "rustfmt-config_proc_macro" version = "0.1.0" authors = ["topecongiro "] edition = "2018" +description = "A collection of procedural macros for rustfmt" +license = "Apache-2.0/MIT" +categories = ["development-tools::procedural-macro-helpers"] +repository = "https://github.com/rust-lang/rustfmt" [lib] proc-macro = true diff --git a/src/config/lists.rs b/src/config/lists.rs index 0270bd0eb0b..11cb17068fb 100644 --- a/src/config/lists.rs +++ b/src/config/lists.rs @@ -1,6 +1,6 @@ //! Configuration options related to rewriting a list. -use config_proc_macro::config_type; +use rustfmt_config_proc_macro::config_type; use crate::config::IndentStyle; diff --git a/src/config/options.rs b/src/config/options.rs index 663c5d4dee2..6b714f6937d 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -3,7 +3,7 @@ use std::fmt; use std::path::{Path, PathBuf}; use atty; -use config_proc_macro::config_type; +use rustfmt_config_proc_macro::config_type; use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -- cgit 1.4.1-3-g733a5 From 04add0cd38197c25404ea2f7d3be104c92b8cad8 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 12 Jun 2019 13:20:42 +0200 Subject: implement Display for enums with attribute config_type (#3621) --- config_proc_macro/src/item_enum.rs | 25 +++++++++++++++++++++++++ src/config/config_type.rs | 8 ++++++-- src/config/file_lines.rs | 22 ++++++++++++++++++++++ src/config/options.rs | 22 ++++++++++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/config_proc_macro/src/item_enum.rs b/config_proc_macro/src/item_enum.rs index eb7254ada7a..d59c87d77bf 100644 --- a/config_proc_macro/src/item_enum.rs +++ b/config_proc_macro/src/item_enum.rs @@ -23,6 +23,7 @@ pub fn define_config_type_on_enum(em: &syn::ItemEnum) -> syn::Result syn::Result TokenStream { } } +fn impl_display(ident: &syn::Ident, variants: &Variants) -> TokenStream { + let vs = variants + .iter() + .filter(|v| is_unit(v)) + .map(|v| (config_value_of_variant(v), &v.ident)); + let match_patterns = fold_quote(vs, |(s, v)| { + quote! { + #ident::#v => write!(f, "{}", #s), + } + }); + quote! { + use std::fmt; + impl fmt::Display for #ident { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + #match_patterns + _ => unimplemented!(), + } + } + } + } +} + fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream { let vs = variants .iter() diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 326d81b2113..7b91f54877d 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -249,11 +249,15 @@ macro_rules! create_config { } name_out.push_str(name_raw); name_out.push(' '); + let mut default_str = format!("{}", $def); + if default_str.is_empty() { + default_str = String::from("\"\""); + } writeln!(out, - "{}{} Default: {:?}{}", + "{}{} Default: {}{}", name_out, <$ty>::doc_hint(), - $def, + default_str, if !$stb { " (unstable)" } else { "" }).unwrap(); $( writeln!(out, "{}{}", space_str, $dstring).unwrap(); diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index f52f6dab339..f0dc6c66597 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -1,5 +1,6 @@ //! This module contains types and functions to support formatting specific line ranges. +use itertools::Itertools; use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; @@ -92,6 +93,12 @@ impl<'a> From<&'a LineRange> for Range { } } +impl fmt::Display for Range { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}..{}", self.lo, self.hi) + } +} + impl Range { pub fn new(lo: usize, hi: usize) -> Range { Range { lo, hi } @@ -149,6 +156,21 @@ impl Range { #[derive(Clone, Debug, Default, PartialEq)] pub struct FileLines(Option>>); +impl fmt::Display for FileLines { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match &self.0 { + None => write!(f, "None")?, + Some(map) => { + for (file_name, ranges) in map.iter() { + write!(f, "{}: ", file_name)?; + write!(f, "{}\n", ranges.iter().format(", "))?; + } + } + }; + Ok(()) + } +} + /// Normalizes the ranges so that the invariants for `FileLines` hold: ranges are non-overlapping, /// and ordered by their start point. fn normalize_ranges(ranges: &mut HashMap>) { diff --git a/src/config/options.rs b/src/config/options.rs index 6b714f6937d..cf1a328e9cd 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -3,6 +3,7 @@ use std::fmt; use std::path::{Path, PathBuf}; use atty; +use itertools::Itertools; use rustfmt_config_proc_macro::config_type; use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; @@ -193,6 +194,12 @@ pub struct WidthHeuristics { pub single_line_if_else_max_width: usize, } +impl fmt::Display for WidthHeuristics { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + impl WidthHeuristics { // Using this WidthHeuristics means we ignore heuristics. pub fn null() -> WidthHeuristics { @@ -264,6 +271,21 @@ pub struct IgnoreList { rustfmt_toml_path: PathBuf, } +impl fmt::Display for IgnoreList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "[{}]", + self.path_set + .iter() + .format_with(", ", |path, f| f(&format_args!( + "{}", + path.to_string_lossy() + ))) + ) + } +} + impl Serialize for IgnoreList { fn serialize(&self, serializer: S) -> Result where -- cgit 1.4.1-3-g733a5 From 1cea171cef198cf371a2f6d9182bc44a1a549e56 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 12 Jun 2019 13:28:29 +0200 Subject: Improve handling of unicode characters (#3618) --- src/chains.rs | 5 ++++- src/expr.rs | 6 ++++-- tests/source/unicode.rs | 25 +++++++++++++++++++++++++ tests/target/unicode.rs | 22 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 tests/source/unicode.rs create mode 100644 tests/target/unicode.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 9a5823817a1..6cac55c6e86 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -557,7 +557,10 @@ impl<'a> ChainFormatterShared<'a> { let almost_total = if extendable { prev_last_line_width } else { - self.rewrites.iter().map(String::len).sum() + self.rewrites + .iter() + .map(|rw| utils::unicode_str_width(&rw)) + .sum() } + last.tries; let one_line_budget = if self.child_count == 1 { shape.width diff --git a/src/expr.rs b/src/expr.rs index 78473803fa9..b1ba99ba6e5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -33,7 +33,7 @@ use crate::types::{rewrite_path, PathContext}; use crate::utils::{ colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, - semicolon_for_expr, semicolon_for_stmt, wrap_str, + semicolon_for_expr, semicolon_for_stmt, unicode_str_width, wrap_str, }; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; @@ -1973,7 +1973,9 @@ fn choose_rhs( rhs_tactics: RhsTactics, ) -> Option { match orig_rhs { - Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => { + Some(ref new_str) + if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => + { Some(format!(" {}", new_str)) } _ => { diff --git a/tests/source/unicode.rs b/tests/source/unicode.rs new file mode 100644 index 00000000000..8b46a437190 --- /dev/null +++ b/tests/source/unicode.rs @@ -0,0 +1,25 @@ +// rustfmt-wrap_comments: true + +fn foo() { + let s = "this line goes to 100: ͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶ"; + let s = 42; + + // a comment of length 80, with the starting sigil: ҘҘҘҘҘҘҘҘҘҘ ҘҘҘҘҘҘҘҘҘҘҘҘҘҘ + let s = 42; +} + +pub fn bar(config: &Config) { + let csv = RefCell::new(create_csv(config, "foo")); + { + let mut csv = csv.borrow_mut(); + for (i1, i2, i3) in iproduct!(0..2, 0..3, 0..3) { + csv.write_field(format!("γ[{}.{}.{}]", i1, i2, i3)) + .unwrap(); + csv.write_field(format!("d[{}.{}.{}]", i1, i2, i3)) + .unwrap(); + csv.write_field(format!("i[{}.{}.{}]", i1, i2, i3)) + .unwrap(); + } + csv.write_record(None::<&[u8]>).unwrap(); + } +} diff --git a/tests/target/unicode.rs b/tests/target/unicode.rs new file mode 100644 index 00000000000..00fb59d13db --- /dev/null +++ b/tests/target/unicode.rs @@ -0,0 +1,22 @@ +// rustfmt-wrap_comments: true + +fn foo() { + let s = "this line goes to 100: ͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶ"; + let s = 42; + + // a comment of length 80, with the starting sigil: ҘҘҘҘҘҘҘҘҘҘ ҘҘҘҘҘҘҘҘҘҘҘҘҘҘ + let s = 42; +} + +pub fn bar(config: &Config) { + let csv = RefCell::new(create_csv(config, "foo")); + { + let mut csv = csv.borrow_mut(); + for (i1, i2, i3) in iproduct!(0..2, 0..3, 0..3) { + csv.write_field(format!("γ[{}.{}.{}]", i1, i2, i3)).unwrap(); + csv.write_field(format!("d[{}.{}.{}]", i1, i2, i3)).unwrap(); + csv.write_field(format!("i[{}.{}.{}]", i1, i2, i3)).unwrap(); + } + csv.write_record(None::<&[u8]>).unwrap(); + } +} -- cgit 1.4.1-3-g733a5 From dbac28b4b4f2adb135104593365943b3eab24685 Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Wed, 12 Jun 2019 23:59:20 +0200 Subject: Use trait to abstract emit modes (#3616) --- src/checkstyle.rs | 102 --------------------------------------- src/emitter.rs | 50 +++++++++++++++++++ src/emitter/checkstyle.rs | 64 ++++++++++++++++++++++++ src/emitter/checkstyle/xml.rs | 52 ++++++++++++++++++++ src/emitter/diff.rs | 35 ++++++++++++++ src/emitter/files.rs | 24 +++++++++ src/emitter/files_with_backup.rs | 31 ++++++++++++ src/emitter/modified_lines.rs | 24 +++++++++ src/emitter/stdout.rs | 32 ++++++++++++ src/formatting.rs | 4 +- src/lib.rs | 32 +++++++++--- src/source_file.rs | 85 ++++++++------------------------ src/test/mod.rs | 7 +-- 13 files changed, 363 insertions(+), 179 deletions(-) delete mode 100644 src/checkstyle.rs create mode 100644 src/emitter.rs create mode 100644 src/emitter/checkstyle.rs create mode 100644 src/emitter/checkstyle/xml.rs create mode 100644 src/emitter/diff.rs create mode 100644 src/emitter/files.rs create mode 100644 src/emitter/files_with_backup.rs create mode 100644 src/emitter/modified_lines.rs create mode 100644 src/emitter/stdout.rs (limited to 'src') diff --git a/src/checkstyle.rs b/src/checkstyle.rs deleted file mode 100644 index 5c2b46583b4..00000000000 --- a/src/checkstyle.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::fmt::{self, Display}; -use std::io::{self, Write}; -use std::path::Path; - -use crate::rustfmt_diff::{DiffLine, Mismatch}; - -/// The checkstyle header - should be emitted before the output of Rustfmt. -/// -/// Note that emitting checkstyle output is not stable and may removed in a -/// future version of Rustfmt. -pub(crate) fn header() -> String { - let mut xml_heading = String::new(); - xml_heading.push_str(r#""#); - xml_heading.push_str("\n"); - xml_heading.push_str(r#""#); - xml_heading -} - -/// The checkstyle footer - should be emitted after the output of Rustfmt. -/// -/// Note that emitting checkstyle output is not stable and may removed in a -/// future version of Rustfmt. -pub(crate) fn footer() -> String { - "\n".to_owned() -} - -pub(crate) fn output_checkstyle_file( - mut writer: T, - filename: &Path, - diff: Vec, -) -> Result<(), io::Error> -where - T: Write, -{ - write!(writer, r#""#, filename.display())?; - for mismatch in diff { - for line in mismatch.lines { - // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. - if let DiffLine::Expected(message) = line { - write!( - writer, - r#""#, - mismatch.line_number, - XmlEscaped(&message) - )?; - } - } - } - write!(writer, "")?; - Ok(()) -} - -/// Convert special characters into XML entities. -/// This is needed for checkstyle output. -struct XmlEscaped<'a>(&'a str); - -impl<'a> Display for XmlEscaped<'a> { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - for char in self.0.chars() { - match char { - '<' => write!(formatter, "<"), - '>' => write!(formatter, ">"), - '"' => write!(formatter, """), - '\'' => write!(formatter, "'"), - '&' => write!(formatter, "&"), - _ => write!(formatter, "{}", char), - }?; - } - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn special_characters_are_escaped() { - assert_eq!( - "<>"'&", - format!("{}", XmlEscaped(r#"<>"'&"#)), - ); - } - - #[test] - fn special_characters_are_escaped_in_string_with_other_characters() { - assert_eq!( - "The quick brown "🦊" jumps <over> the lazy 🐶", - format!( - "{}", - XmlEscaped(r#"The quick brown "🦊" jumps the lazy 🐶"#) - ), - ); - } - - #[test] - fn other_characters_are_not_escaped() { - let string = "The quick brown 🦊 jumps over the lazy 🐶"; - assert_eq!(string, format!("{}", XmlEscaped(string))); - } -} diff --git a/src/emitter.rs b/src/emitter.rs new file mode 100644 index 00000000000..03ca1e35b72 --- /dev/null +++ b/src/emitter.rs @@ -0,0 +1,50 @@ +pub(crate) use self::checkstyle::*; +pub(crate) use self::diff::*; +pub(crate) use self::files::*; +pub(crate) use self::files_with_backup::*; +pub(crate) use self::modified_lines::*; +pub(crate) use self::stdout::*; +use crate::FileName; +use std::io::{self, Write}; +use std::path::Path; + +mod checkstyle; +mod diff; +mod files; +mod files_with_backup; +mod modified_lines; +mod stdout; + +pub(crate) struct FormattedFile<'a> { + pub(crate) filename: &'a FileName, + pub(crate) original_text: &'a str, + pub(crate) formatted_text: &'a str, +} + +#[derive(Debug, Default, Clone)] +pub(crate) struct EmitterResult { + pub(crate) has_diff: bool, +} + +pub(crate) trait Emitter { + fn emit_formatted_file( + &self, + output: &mut dyn Write, + formatted_file: FormattedFile<'_>, + ) -> Result; + + fn emit_header(&self, _output: &mut dyn Write) -> Result<(), io::Error> { + Ok(()) + } + + fn emit_footer(&self, _output: &mut dyn Write) -> Result<(), io::Error> { + Ok(()) + } +} + +fn ensure_real_path(filename: &FileName) -> &Path { + match *filename { + FileName::Real(ref path) => path, + _ => panic!("cannot format `{}` and emit to files", filename), + } +} diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs new file mode 100644 index 00000000000..eb1499985fd --- /dev/null +++ b/src/emitter/checkstyle.rs @@ -0,0 +1,64 @@ +use self::xml::XmlEscaped; +use super::*; +use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch}; +use std::io::{self, Write}; +use std::path::Path; + +mod xml; + +#[derive(Debug, Default)] +pub(crate) struct CheckstyleEmitter; + +impl Emitter for CheckstyleEmitter { + fn emit_header(&self, output: &mut dyn Write) -> Result<(), io::Error> { + writeln!(output, r#""#)?; + write!(output, r#""#)?; + Ok(()) + } + + fn emit_footer(&self, output: &mut dyn Write) -> Result<(), io::Error> { + writeln!(output, "") + } + + fn emit_formatted_file( + &self, + output: &mut dyn Write, + FormattedFile { + filename, + original_text, + formatted_text, + }: FormattedFile<'_>, + ) -> Result { + const CONTEXT_SIZE: usize = 3; + let filename = ensure_real_path(filename); + let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE); + output_checkstyle_file(output, filename, diff)?; + Ok(EmitterResult::default()) + } +} + +pub(crate) fn output_checkstyle_file( + mut writer: T, + filename: &Path, + diff: Vec, +) -> Result<(), io::Error> +where + T: Write, +{ + write!(writer, r#""#, filename.display())?; + for mismatch in diff { + for line in mismatch.lines { + // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. + if let DiffLine::Expected(message) = line { + write!( + writer, + r#""#, + mismatch.line_number, + XmlEscaped(&message) + )?; + } + } + } + write!(writer, "")?; + Ok(()) +} diff --git a/src/emitter/checkstyle/xml.rs b/src/emitter/checkstyle/xml.rs new file mode 100644 index 00000000000..f251aabe878 --- /dev/null +++ b/src/emitter/checkstyle/xml.rs @@ -0,0 +1,52 @@ +use std::fmt::{self, Display}; + +/// Convert special characters into XML entities. +/// This is needed for checkstyle output. +pub(super) struct XmlEscaped<'a>(pub(super) &'a str); + +impl<'a> Display for XmlEscaped<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + for char in self.0.chars() { + match char { + '<' => write!(formatter, "<"), + '>' => write!(formatter, ">"), + '"' => write!(formatter, """), + '\'' => write!(formatter, "'"), + '&' => write!(formatter, "&"), + _ => write!(formatter, "{}", char), + }?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn special_characters_are_escaped() { + assert_eq!( + "<>"'&", + format!("{}", XmlEscaped(r#"<>"'&"#)), + ); + } + + #[test] + fn special_characters_are_escaped_in_string_with_other_characters() { + assert_eq!( + "The quick brown "🦊" jumps <over> the lazy 🐶", + format!( + "{}", + XmlEscaped(r#"The quick brown "🦊" jumps the lazy 🐶"#) + ), + ); + } + + #[test] + fn other_characters_are_not_escaped() { + let string = "The quick brown 🦊 jumps over the lazy 🐶"; + assert_eq!(string, format!("{}", XmlEscaped(string))); + } +} diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs new file mode 100644 index 00000000000..5e387395b5b --- /dev/null +++ b/src/emitter/diff.rs @@ -0,0 +1,35 @@ +use super::*; +use crate::config::Config; +use crate::rustfmt_diff::{make_diff, print_diff}; + +pub(crate) struct DiffEmitter { + config: Config, +} + +impl DiffEmitter { + pub(crate) fn new(config: Config) -> Self { + Self { config } + } +} + +impl Emitter for DiffEmitter { + fn emit_formatted_file( + &self, + _output: &mut dyn Write, + FormattedFile { + filename, + original_text, + formatted_text, + }: FormattedFile<'_>, + ) -> Result { + const CONTEXT_SIZE: usize = 3; + let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE); + let has_diff = !mismatch.is_empty(); + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename, line_num), + &self.config, + ); + return Ok(EmitterResult { has_diff }); + } +} diff --git a/src/emitter/files.rs b/src/emitter/files.rs new file mode 100644 index 00000000000..5b1dbce11c9 --- /dev/null +++ b/src/emitter/files.rs @@ -0,0 +1,24 @@ +use super::*; +use std::fs; + +#[derive(Debug, Default)] +pub(crate) struct FilesEmitter; + +impl Emitter for FilesEmitter { + fn emit_formatted_file( + &self, + _output: &mut dyn Write, + FormattedFile { + filename, + original_text, + formatted_text, + }: FormattedFile<'_>, + ) -> Result { + // Write text directly over original file if there is a diff. + let filename = ensure_real_path(filename); + if original_text != formatted_text { + fs::write(filename, formatted_text)?; + } + Ok(EmitterResult::default()) + } +} diff --git a/src/emitter/files_with_backup.rs b/src/emitter/files_with_backup.rs new file mode 100644 index 00000000000..af3e0e2d91d --- /dev/null +++ b/src/emitter/files_with_backup.rs @@ -0,0 +1,31 @@ +use super::*; +use std::fs; + +#[derive(Debug, Default)] +pub(crate) struct FilesWithBackupEmitter; + +impl Emitter for FilesWithBackupEmitter { + fn emit_formatted_file( + &self, + _output: &mut dyn Write, + FormattedFile { + filename, + original_text, + formatted_text, + }: FormattedFile<'_>, + ) -> Result { + let filename = ensure_real_path(filename); + if original_text != formatted_text { + // Do a little dance to make writing safer - write to a temp file + // rename the original to a .bk, then rename the temp file to the + // original. + let tmp_name = filename.with_extension("tmp"); + let bk_name = filename.with_extension("bk"); + + fs::write(&tmp_name, formatted_text)?; + fs::rename(filename, bk_name)?; + fs::rename(tmp_name, filename)?; + } + Ok(EmitterResult::default()) + } +} diff --git a/src/emitter/modified_lines.rs b/src/emitter/modified_lines.rs new file mode 100644 index 00000000000..83736c47bd6 --- /dev/null +++ b/src/emitter/modified_lines.rs @@ -0,0 +1,24 @@ +use super::*; +use crate::rustfmt_diff::{make_diff, ModifiedLines}; +use std::io::Write; + +#[derive(Debug, Default)] +pub(crate) struct ModifiedLinesEmitter; + +impl Emitter for ModifiedLinesEmitter { + fn emit_formatted_file( + &self, + output: &mut dyn Write, + FormattedFile { + original_text, + formatted_text, + .. + }: FormattedFile<'_>, + ) -> Result { + const CONTEXT_SIZE: usize = 0; + let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE); + let has_diff = !mismatch.is_empty(); + write!(output, "{}", ModifiedLines::from(mismatch))?; + Ok(EmitterResult { has_diff }) + } +} diff --git a/src/emitter/stdout.rs b/src/emitter/stdout.rs new file mode 100644 index 00000000000..968de68c741 --- /dev/null +++ b/src/emitter/stdout.rs @@ -0,0 +1,32 @@ +use super::*; +use crate::config::Verbosity; +use std::io::Write; + +#[derive(Debug)] +pub(crate) struct StdoutEmitter { + verbosity: Verbosity, +} + +impl StdoutEmitter { + pub(crate) fn new(verbosity: Verbosity) -> Self { + Self { verbosity } + } +} + +impl Emitter for StdoutEmitter { + fn emit_formatted_file( + &self, + output: &mut dyn Write, + FormattedFile { + filename, + formatted_text, + .. + }: FormattedFile<'_>, + ) -> Result { + if self.verbosity != Verbosity::Quiet { + writeln!(output, "{}:\n", filename)?; + } + write!(output, "{}", formatted_text)?; + Ok(EmitterResult::default()) + } +} diff --git a/src/formatting.rs b/src/formatting.rs index d431dd2679c..522de400840 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -233,8 +233,8 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { - match source_file::write_file(Some(source_map), &path, &result, out, &self.config) { - Ok(has_diff) if has_diff => report.add_diff(), + match source_file::write_file(Some(source_map), &path, &result, out, &*self.emitter) { + Ok(ref result) if result.has_diff => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed let err_msg = format!("{}: {}", path, e); diff --git a/src/lib.rs b/src/lib.rs index 88605079b7e..14e2a6fe6e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ use ignore; use syntax::{ast, parse::DirectoryOwnership}; use crate::comment::LineClasses; +use crate::emitter::Emitter; use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use crate::issues::Issue; use crate::shape::Indent; @@ -45,10 +46,10 @@ mod release_channel; mod attr; mod chains; -pub(crate) mod checkstyle; mod closures; mod comment; pub(crate) mod config; +mod emitter; mod expr; mod format_report_formatter; pub(crate) mod formatting; @@ -403,17 +404,21 @@ pub struct Session<'b, T: Write> { pub out: Option<&'b mut T>, pub(crate) errors: ReportedErrors, source_file: SourceFile, + emitter: Box, } impl<'b, T: Write + 'b> Session<'b, T> { - pub fn new(config: Config, out: Option<&'b mut T>) -> Session<'b, T> { - if config.emit_mode() == EmitMode::Checkstyle { - println!("{}", checkstyle::header()); + pub fn new(config: Config, mut out: Option<&'b mut T>) -> Session<'b, T> { + let emitter = create_emitter(&config); + + if let Some(ref mut out) = out { + let _ = emitter.emit_header(out); } Session { config, out, + emitter, errors: ReportedErrors::default(), source_file: SourceFile::new(), } @@ -469,10 +474,25 @@ impl<'b, T: Write + 'b> Session<'b, T> { } } +pub(crate) fn create_emitter<'a>(config: &Config) -> Box { + match config.emit_mode() { + EmitMode::Files if config.make_backup() => { + Box::new(emitter::FilesWithBackupEmitter::default()) + } + EmitMode::Files => Box::new(emitter::FilesEmitter::default()), + EmitMode::Stdout | EmitMode::Coverage => { + Box::new(emitter::StdoutEmitter::new(config.verbose())) + } + EmitMode::ModifiedLines => Box::new(emitter::ModifiedLinesEmitter::default()), + EmitMode::Checkstyle => Box::new(emitter::CheckstyleEmitter::default()), + EmitMode::Diff => Box::new(emitter::DiffEmitter::new(config.clone())), + } +} + impl<'b, T: Write + 'b> Drop for Session<'b, T> { fn drop(&mut self) { - if self.config.emit_mode() == EmitMode::Checkstyle { - println!("{}", checkstyle::footer()); + if let Some(ref mut out) = self.out { + let _ = self.emitter.emit_footer(out); } } } diff --git a/src/source_file.rs b/src/source_file.rs index a7e0074cd2f..074b7a7315f 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -4,10 +4,13 @@ use std::path::Path; use syntax::source_map::SourceMap; -use crate::checkstyle::output_checkstyle_file; -use crate::config::{Config, EmitMode, FileName, Verbosity}; -use crate::rustfmt_diff::{make_diff, print_diff, ModifiedLines}; +use crate::config::FileName; +use crate::emitter::{self, Emitter}; +#[cfg(test)] +use crate::config::Config; +#[cfg(test)] +use crate::create_emitter; #[cfg(test)] use crate::formatting::FileRecord; @@ -25,15 +28,13 @@ pub(crate) fn write_all_files( where T: Write, { - if config.emit_mode() == EmitMode::Checkstyle { - write!(out, "{}", crate::checkstyle::header())?; - } + let emitter = create_emitter(config); + + emitter.emit_header(out)?; for &(ref filename, ref text) in source_file { - write_file(None, filename, text, out, config)?; - } - if config.emit_mode() == EmitMode::Checkstyle { - write!(out, "{}", crate::checkstyle::footer())?; + write_file(None, filename, text, out, &*emitter)?; } + emitter.emit_footer(out)?; Ok(()) } @@ -43,8 +44,8 @@ pub(crate) fn write_file( filename: &FileName, formatted_text: &str, out: &mut T, - config: &Config, -) -> Result + emitter: &dyn Emitter, +) -> Result where T: Write, { @@ -75,59 +76,11 @@ where None => fs::read_to_string(ensure_real_path(filename))?, }; - match config.emit_mode() { - EmitMode::Files if config.make_backup() => { - let filename = ensure_real_path(filename); - if original_text != formatted_text { - // Do a little dance to make writing safer - write to a temp file - // rename the original to a .bk, then rename the temp file to the - // original. - let tmp_name = filename.with_extension("tmp"); - let bk_name = filename.with_extension("bk"); - - fs::write(&tmp_name, formatted_text)?; - fs::rename(filename, bk_name)?; - fs::rename(tmp_name, filename)?; - } - } - EmitMode::Files => { - // Write text directly over original file if there is a diff. - let filename = ensure_real_path(filename); - - if original_text != formatted_text { - fs::write(filename, formatted_text)?; - } - } - EmitMode::Stdout | EmitMode::Coverage => { - if config.verbose() != Verbosity::Quiet { - println!("{}:\n", filename); - } - write!(out, "{}", formatted_text)?; - } - EmitMode::ModifiedLines => { - let mismatch = make_diff(&original_text, formatted_text, 0); - let has_diff = !mismatch.is_empty(); - write!(out, "{}", ModifiedLines::from(mismatch))?; - return Ok(has_diff); - } - EmitMode::Checkstyle => { - let filename = ensure_real_path(filename); - - let diff = make_diff(&original_text, formatted_text, 3); - output_checkstyle_file(out, filename, diff)?; - } - EmitMode::Diff => { - let mismatch = make_diff(&original_text, formatted_text, 3); - let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename, line_num), - config, - ); - return Ok(has_diff); - } - } + let formatted_file = emitter::FormattedFile { + filename, + original_text: &original_text, + formatted_text, + }; - // when we are not in diff mode, don't indicate differing files - Ok(false) + emitter.emit_formatted_file(out, formatted_file) } diff --git a/src/test/mod.rs b/src/test/mod.rs index 96f6f2ce9ba..2830f9aeff1 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -9,7 +9,7 @@ use std::process::{Command, Stdio}; use std::str::Chars; use std::thread; -use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; +use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic, Verbosity}; use crate::formatting::{ReportedErrors, SourceFile}; use crate::is_nightly_channel; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; @@ -344,9 +344,9 @@ fn stdin_formatting_smoke_test() { } #[cfg(not(windows))] - assert_eq!(buf, "fn main() {}\n".as_bytes()); + assert_eq!(buf, "stdin:\n\nfn main() {}\n".as_bytes()); #[cfg(windows)] - assert_eq!(buf, "fn main() {}\r\n".as_bytes()); + assert_eq!(buf, "stdin:\n\nfn main() {}\r\n".as_bytes()); } #[test] @@ -838,6 +838,7 @@ impl ConfigCodeBlock { fn get_block_config(&self) -> Config { let mut config = Config::default(); + config.set().verbose(Verbosity::Quiet); if self.config_name.is_some() && self.config_value.is_some() { config.override_value( self.config_name.as_ref().unwrap(), -- cgit 1.4.1-3-g733a5 From a4eab17d7c4cdeee1d0e72ea2a8a5f6a377627f2 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 14 Jun 2019 14:08:19 +0900 Subject: Fix is_subpath --- src/test/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 2830f9aeff1..5ac0a1d4450 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -66,7 +66,11 @@ where P: AsRef, { (0..path.components().count()) - .map(|i| path.components().take(i)) + .map(|i| { + path.components() + .skip(i) + .take(subpath.as_ref().components().count()) + }) .any(|c| c.zip(subpath.as_ref().components()).all(|(a, b)| a == b)) } -- cgit 1.4.1-3-g733a5 From 944fc57e10222e5b0b57772c6a18b21392671c2a Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 16 Jun 2019 09:47:22 -0500 Subject: tests: ensure min number of system/idempotent tests ran (#3629) --- src/test/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 5ac0a1d4450..89bde8c0467 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -172,6 +172,11 @@ fn system_tests() { // Display results. println!("Ran {} system tests.", count); assert_eq!(fails, 0, "{} system tests failed", fails); + assert!( + count >= 300, + "Expected a minimum of {} system tests to be executed", + 300 + ) }); } @@ -292,6 +297,11 @@ fn idempotence_tests() { // Display results. println!("Ran {} idempotent tests.", count); assert_eq!(fails, 0, "{} idempotent tests failed", fails); + assert!( + count >= 400, + "Expected a minimum of {} idempotent tests to be executed", + 400 + ) }); } -- cgit 1.4.1-3-g733a5 From 84c23565901c0d9b7af41d372b9f2d1e2d6c6394 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 17 Jun 2019 01:53:17 +0200 Subject: handle unicode chars in closures (#3632) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `NotUnicode` branch was unecessarily put on a new line, although it was within max width: ```diff fn baz() { let our_error_b = result_b_from_func.or_else(|e| match e { NotPresent => Err(e).chain_err(|| "env var wasn't provided"), - NotUnicode(_) => Err(e).chain_err(|| "env var was very very very bork文字化ã"), + NotUnicode(_) => { + Err(e).chain_err(|| "env var was very very very bork文字化ã") + } }); } ``` --- src/expr.rs | 9 +++++++++ src/lists.rs | 9 ++++++--- src/matches.rs | 3 +++ tests/source/unicode.rs | 8 ++++++++ tests/target/unicode.rs | 8 ++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index b1ba99ba6e5..e87327fb3e7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2028,6 +2028,15 @@ fn shape_from_rhs_tactic( } } +/// Returns true if formatting next_line_rhs is better on a new line when compared to the +/// original's line formatting. +/// +/// It is considered better if: +/// 1. the tactic is ForceNextLineWithoutIndent +/// 2. next_line_rhs doesn't have newlines +/// 3. the original line has more newlines than next_line_rhs +/// 4. the original formatting of the first line ends with `(`, `{`, or `[` and next_line_rhs +/// doesn't pub(crate) fn prefer_next_line( orig_rhs: &str, next_line_rhs: &str, diff --git a/src/lists.rs b/src/lists.rs index 428a0eab9b0..4c31f670d4d 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -10,7 +10,10 @@ use crate::config::lists::*; use crate::config::{Config, IndentStyle}; use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; -use crate::utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline}; +use crate::utils::{ + count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline, + unicode_str_width, +}; use crate::visitor::SnippetProvider; pub(crate) struct ListFormatting<'a> { @@ -386,7 +389,7 @@ where result.push('\n'); result.push_str(indent_str); // This is the width of the item (without comments). - line_len = item.item.as_ref().map_or(0, String::len); + line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s)); } } else { result.push(' '); @@ -808,7 +811,7 @@ where pub(crate) fn total_item_width(item: &ListItem) -> usize { comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) + comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) - + item.item.as_ref().map_or(0, String::len) + + &item.item.as_ref().map_or(0, |s| unicode_str_width(&s)) } fn comment_len(comment: Option<&str>) -> usize { diff --git a/src/matches.rs b/src/matches.rs index 7c20ea06df0..2f542c3e1aa 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -468,6 +468,9 @@ fn rewrite_match_body( next_line_body_shape.width, ); match (orig_body, next_line_body) { + (Some(ref orig_str), Some(ref next_line_str)) if orig_str == next_line_str => { + combine_orig_body(orig_str) + } (Some(ref orig_str), Some(ref next_line_str)) if prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { diff --git a/tests/source/unicode.rs b/tests/source/unicode.rs index 8b46a437190..4c2119af575 100644 --- a/tests/source/unicode.rs +++ b/tests/source/unicode.rs @@ -23,3 +23,11 @@ pub fn bar(config: &Config) { csv.write_record(None::<&[u8]>).unwrap(); } } + +// The NotUnicode line is below 100 wrt chars but over it wrt String::len +fn baz() { + let our_error_b = result_b_from_func.or_else(|e| match e { + NotPresent => Err(e).chain_err(|| "env var wasn't provided"), + NotUnicode(_) => Err(e).chain_err(|| "env var was very very very bork文字化ã"), + }); +} diff --git a/tests/target/unicode.rs b/tests/target/unicode.rs index 00fb59d13db..34a4f463479 100644 --- a/tests/target/unicode.rs +++ b/tests/target/unicode.rs @@ -20,3 +20,11 @@ pub fn bar(config: &Config) { csv.write_record(None::<&[u8]>).unwrap(); } } + +// The NotUnicode line is below 100 wrt chars but over it wrt String::len +fn baz() { + let our_error_b = result_b_from_func.or_else(|e| match e { + NotPresent => Err(e).chain_err(|| "env var wasn't provided"), + NotUnicode(_) => Err(e).chain_err(|| "env var was very very very bork文字化ã"), + }); +} -- cgit 1.4.1-3-g733a5 From 1d19a08ed4743e3c95176fb639ebcd50f68a3313 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 17 Jun 2019 08:53:39 +0900 Subject: Format the last expression-statement as expression (#3631) --- src/expr.rs | 34 +-------- src/items.rs | 20 ++---- src/lib.rs | 1 + src/stmt.rs | 112 +++++++++++++++++++++++++++++ src/visitor.rs | 63 +++++++--------- tests/source/fn-single-line.rs | 79 -------------------- tests/source/fn-single-line/version_one.rs | 80 +++++++++++++++++++++ tests/source/fn-single-line/version_two.rs | 80 +++++++++++++++++++++ tests/target/fn-single-line.rs | 70 ------------------ tests/target/fn-single-line/version_one.rs | 71 ++++++++++++++++++ tests/target/fn-single-line/version_two.rs | 67 +++++++++++++++++ tests/target/issue-3614/version_one.rs | 15 ++++ tests/target/issue-3614/version_two.rs | 8 +++ 13 files changed, 464 insertions(+), 236 deletions(-) create mode 100644 src/stmt.rs delete mode 100644 tests/source/fn-single-line.rs create mode 100644 tests/source/fn-single-line/version_one.rs create mode 100644 tests/source/fn-single-line/version_two.rs delete mode 100644 tests/target/fn-single-line.rs create mode 100644 tests/target/fn-single-line/version_one.rs create mode 100644 tests/target/fn-single-line/version_two.rs create mode 100644 tests/target/issue-3614/version_one.rs create mode 100644 tests/target/issue-3614/version_two.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index e87327fb3e7..d7640bf98ca 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -33,7 +33,7 @@ use crate::types::{rewrite_path, PathContext}; use crate::utils::{ colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, - semicolon_for_expr, semicolon_for_stmt, unicode_str_width, wrap_str, + semicolon_for_expr, unicode_str_width, wrap_str, }; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; @@ -568,28 +568,6 @@ fn rewrite_block( result } -impl Rewrite for ast::Stmt { - fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - skip_out_of_file_lines_range!(context, self.span()); - - let result = match self.node { - ast::StmtKind::Local(ref local) => local.rewrite(context, shape), - ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { - let suffix = if semicolon_for_stmt(context, self) { - ";" - } else { - "" - }; - - let shape = shape.sub_width(suffix.len())?; - format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix) - } - ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, - }; - result.and_then(|res| recover_comment_removed(res, self.span(), context)) - } -} - // Rewrite condition if the given expression has one. pub(crate) fn rewrite_cond( context: &RewriteContext<'_>, @@ -1189,16 +1167,6 @@ pub(crate) fn stmt_is_expr(stmt: &ast::Stmt) -> bool { } } -pub(crate) fn stmt_is_if(stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::StmtKind::Expr(ref e) => match e.node { - ast::ExprKind::If(..) => true, - _ => false, - }, - _ => false, - } -} - pub(crate) fn is_unsafe_block(block: &ast::Block) -> bool { if let ast::BlockCheckMode::Unsafe(..) = block.rules { true diff --git a/src/items.rs b/src/items.rs index 14d386047f0..1b7ac780129 100644 --- a/src/items.rs +++ b/src/items.rs @@ -18,8 +18,7 @@ use crate::comment::{ use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle, Version}; use crate::expr::{ - format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, - ExprType, RhsTactics, + is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, RhsTactics, }; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::macros::{rewrite_macro, MacroPosition}; @@ -28,6 +27,7 @@ use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; +use crate::stmt::Stmt; use crate::utils::*; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; @@ -394,20 +394,8 @@ impl<'a> FmtVisitor<'a> { return None; } - let stmt = block.stmts.first()?; - let res = match stmt_expr(stmt) { - Some(e) => { - let suffix = if semicolon_for_expr(&self.get_context(), e) { - ";" - } else { - "" - }; - - format_expr(e, ExprType::Statement, &self.get_context(), self.shape()) - .map(|s| s + suffix)? - } - None => stmt.rewrite(&self.get_context(), self.shape())?, - }; + let res = Stmt::from_ast_node(block.stmts.first()?, true) + .rewrite(&self.get_context(), self.shape())?; let width = self.block_indent.width() + fn_str.len() + res.len() + 5; if !res.contains('\n') && width <= self.config.max_width() { diff --git a/src/lib.rs b/src/lib.rs index 14e2a6fe6e5..1b4ce663313 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,7 @@ mod shape; pub(crate) mod source_file; pub(crate) mod source_map; mod spanned; +mod stmt; mod string; #[cfg(test)] mod test; diff --git a/src/stmt.rs b/src/stmt.rs new file mode 100644 index 00000000000..dbda00f00ce --- /dev/null +++ b/src/stmt.rs @@ -0,0 +1,112 @@ +use syntax::ast; +use syntax_pos::Span; + +use crate::comment::recover_comment_removed; +use crate::config::Version; +use crate::expr::{format_expr, ExprType}; +use crate::rewrite::{Rewrite, RewriteContext}; +use crate::shape::Shape; +use crate::source_map::LineRangeUtils; +use crate::spanned::Spanned; +use crate::utils::semicolon_for_stmt; + +pub(crate) struct Stmt<'a> { + inner: &'a ast::Stmt, + is_last: bool, +} + +impl<'a> Spanned for Stmt<'a> { + fn span(&self) -> Span { + self.inner.span() + } +} + +impl<'a> Stmt<'a> { + pub(crate) fn as_ast_node(&self) -> &ast::Stmt { + self.inner + } + + pub(crate) fn to_item(&self) -> Option<&ast::Item> { + match self.inner.node { + ast::StmtKind::Item(ref item) => Some(&**item), + _ => None, + } + } + + pub(crate) fn from_ast_node(inner: &'a ast::Stmt, is_last: bool) -> Self { + Stmt { inner, is_last } + } + + pub(crate) fn from_ast_nodes(iter: I) -> Vec + where + I: Iterator, + { + let mut result = vec![]; + let mut iter = iter.peekable(); + while iter.peek().is_some() { + result.push(Stmt { + inner: iter.next().unwrap(), + is_last: iter.peek().is_none(), + }) + } + result + } + + fn is_last_expr(&self) -> bool { + if !self.is_last { + return false; + } + + match self.as_ast_node().node { + ast::StmtKind::Expr(ref expr) => match expr.node { + ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { + false + } + _ => true, + }, + _ => false, + } + } +} + +impl<'a> Rewrite for Stmt<'a> { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + let expr_type = if context.config.version() == Version::Two && self.is_last_expr() { + ExprType::SubExpression + } else { + ExprType::Statement + }; + format_stmt(context, shape, self.as_ast_node(), expr_type) + } +} + +impl Rewrite for ast::Stmt { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + format_stmt(context, shape, self, ExprType::Statement) + } +} + +fn format_stmt( + context: &RewriteContext<'_>, + shape: Shape, + stmt: &ast::Stmt, + expr_type: ExprType, +) -> Option { + skip_out_of_file_lines_range!(context, stmt.span()); + + let result = match stmt.node { + ast::StmtKind::Local(ref local) => local.rewrite(context, shape), + ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { + let suffix = if semicolon_for_stmt(context, stmt) { + ";" + } else { + "" + }; + + let shape = shape.sub_width(suffix.len())?; + format_expr(ex, expr_type, context, shape).map(|s| s + suffix) + } + ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, + }; + result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) +} diff --git a/src/visitor.rs b/src/visitor.rs index 0560cd2ff09..19200f9592c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -7,8 +7,7 @@ use syntax::{ast, visit}; use crate::attr::*; use crate::comment::{CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileName; -use crate::config::{BraceStyle, Config, Version}; -use crate::expr::{format_expr, ExprType}; +use crate::config::{BraceStyle, Config}; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, @@ -20,6 +19,7 @@ use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; +use crate::stmt::Stmt; use crate::utils::{ self, contains_skip, count_newlines, depr_skip_annotation, get_skip_macro_names, inner_attributes, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, @@ -89,23 +89,27 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Shape::indented(self.block_indent, self.config) } - fn visit_stmt(&mut self, stmt: &ast::Stmt) { + fn visit_stmt(&mut self, stmt: &Stmt<'_>) { debug!( "visit_stmt: {:?} {:?}", - self.source_map.lookup_char_pos(stmt.span.lo()), - self.source_map.lookup_char_pos(stmt.span.hi()) + self.source_map.lookup_char_pos(stmt.span().lo()), + self.source_map.lookup_char_pos(stmt.span().hi()) ); - match stmt.node { + match stmt.as_ast_node().node { ast::StmtKind::Item(ref item) => { self.visit_item(item); // Handle potential `;` after the item. - self.format_missing(stmt.span.hi()); + self.format_missing(stmt.span().hi()); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - let attrs = get_attrs_from_stmt(stmt); + let attrs = get_attrs_from_stmt(stmt.as_ast_node()); if contains_skip(attrs) { - self.push_skipped_with_span(attrs, stmt.span(), get_span_without_attrs(stmt)); + self.push_skipped_with_span( + attrs, + stmt.span(), + get_span_without_attrs(stmt.as_ast_node()), + ); } else { let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); @@ -115,11 +119,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::StmtKind::Mac(ref mac) => { let (ref mac, _macro_style, ref attrs) = **mac; if self.visit_attrs(attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(attrs, stmt.span(), get_span_without_attrs(stmt)); + self.push_skipped_with_span( + attrs, + stmt.span(), + get_span_without_attrs(stmt.as_ast_node()), + ); } else { self.visit_mac(mac, None, MacroPosition::Statement); } - self.format_missing(stmt.span.hi()); + self.format_missing(stmt.span().hi()); } } } @@ -717,14 +725,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); } - fn walk_stmts(&mut self, stmts: &[ast::Stmt]) { - fn to_stmt_item(stmt: &ast::Stmt) -> Option<&ast::Item> { - match stmt.node { - ast::StmtKind::Item(ref item) => Some(&**item), - _ => None, - } - } - + fn walk_stmts(&mut self, stmts: &[Stmt<'_>]) { if stmts.is_empty() { return; } @@ -732,27 +733,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Extract leading `use ...;`. let items: Vec<_> = stmts .iter() - .take_while(|stmt| to_stmt_item(stmt).map_or(false, is_use_item)) - .filter_map(|stmt| to_stmt_item(stmt)) + .take_while(|stmt| stmt.to_item().map_or(false, is_use_item)) + .filter_map(|stmt| stmt.to_item()) .collect(); if items.is_empty() { - // The `if` expression at the end of the block should be formatted in a single - // line if possible. - if self.config.version() == Version::Two - && stmts.len() == 1 - && crate::expr::stmt_is_if(&stmts[0]) - && !contains_skip(get_attrs_from_stmt(&stmts[0])) - { - let shape = self.shape(); - let rewrite = self.with_context(|ctx| { - format_expr(stmt_expr(&stmts[0])?, ExprType::SubExpression, ctx, shape) - }); - self.push_rewrite(stmts[0].span(), rewrite); - } else { - self.visit_stmt(&stmts[0]); - self.walk_stmts(&stmts[1..]); - } + self.visit_stmt(&stmts[0]); + self.walk_stmts(&stmts[1..]); } else { self.visit_items_with_reordering(&items); self.walk_stmts(&stmts[items.len()..]); @@ -760,7 +747,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } fn walk_block_stmts(&mut self, b: &ast::Block) { - self.walk_stmts(&b.stmts) + self.walk_stmts(&Stmt::from_ast_nodes(b.stmts.iter())) } fn format_mod( diff --git a/tests/source/fn-single-line.rs b/tests/source/fn-single-line.rs deleted file mode 100644 index 6d7f764d280..00000000000 --- a/tests/source/fn-single-line.rs +++ /dev/null @@ -1,79 +0,0 @@ -// rustfmt-fn_single_line: true -// Test single-line functions. - -fn foo_expr() { - 1 -} - -fn foo_stmt() { - foo(); -} - -fn foo_decl_local() { - let z = 5; - } - -fn foo_decl_item(x: &mut i32) { - x = 3; -} - - fn empty() { - -} - -fn foo_return() -> String { - "yay" -} - -fn foo_where() -> T where T: Sync { - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space () { - 1 -} - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) { - } -} - -trait CoolerTypes { fn dummy(&self) { -} -} - -fn Foo() where T: Bar { -} diff --git a/tests/source/fn-single-line/version_one.rs b/tests/source/fn-single-line/version_one.rs new file mode 100644 index 00000000000..469ab621567 --- /dev/null +++ b/tests/source/fn-single-line/version_one.rs @@ -0,0 +1,80 @@ +// rustfmt-fn_single_line: true +// rustfmt-version: One +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/tests/source/fn-single-line/version_two.rs b/tests/source/fn-single-line/version_two.rs new file mode 100644 index 00000000000..bf381ff1065 --- /dev/null +++ b/tests/source/fn-single-line/version_two.rs @@ -0,0 +1,80 @@ +// rustfmt-fn_single_line: true +// rustfmt-version: Two +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/tests/target/fn-single-line.rs b/tests/target/fn-single-line.rs deleted file mode 100644 index 3617506d89a..00000000000 --- a/tests/target/fn-single-line.rs +++ /dev/null @@ -1,70 +0,0 @@ -// rustfmt-fn_single_line: true -// Test single-line functions. - -fn foo_expr() { 1 } - -fn foo_stmt() { foo(); } - -fn foo_decl_local() { let z = 5; } - -fn foo_decl_item(x: &mut i32) { x = 3; } - -fn empty() {} - -fn foo_return() -> String { "yay" } - -fn foo_where() -> T -where - T: Sync, -{ - let x = 2; -} - -fn fooblock() { - { - "inner-block" - } -} - -fn fooblock2(x: i32) { - let z = match x { - _ => 2, - }; -} - -fn comment() { - // this is a test comment - 1 -} - -fn comment2() { - // multi-line comment - let z = 2; - 1 -} - -fn only_comment() { - // Keep this here -} - -fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { - let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; -} - -fn lots_of_space() { 1 } - -fn mac() -> Vec { vec![] } - -trait CoolTypes { - fn dummy(&self) {} -} - -trait CoolerTypes { - fn dummy(&self) {} -} - -fn Foo() -where - T: Bar, -{ -} diff --git a/tests/target/fn-single-line/version_one.rs b/tests/target/fn-single-line/version_one.rs new file mode 100644 index 00000000000..013b2cd7216 --- /dev/null +++ b/tests/target/fn-single-line/version_one.rs @@ -0,0 +1,71 @@ +// rustfmt-fn_single_line: true +// rustfmt-version: One +// Test single-line functions. + +fn foo_expr() { 1 } + +fn foo_stmt() { foo(); } + +fn foo_decl_local() { let z = 5; } + +fn foo_decl_item(x: &mut i32) { x = 3; } + +fn empty() {} + +fn foo_return() -> String { "yay" } + +fn foo_where() -> T +where + T: Sync, +{ + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space() { 1 } + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) {} +} + +trait CoolerTypes { + fn dummy(&self) {} +} + +fn Foo() +where + T: Bar, +{ +} diff --git a/tests/target/fn-single-line/version_two.rs b/tests/target/fn-single-line/version_two.rs new file mode 100644 index 00000000000..b8053d4c2f5 --- /dev/null +++ b/tests/target/fn-single-line/version_two.rs @@ -0,0 +1,67 @@ +// rustfmt-fn_single_line: true +// rustfmt-version: Two +// Test single-line functions. + +fn foo_expr() { 1 } + +fn foo_stmt() { foo(); } + +fn foo_decl_local() { let z = 5; } + +fn foo_decl_item(x: &mut i32) { x = 3; } + +fn empty() {} + +fn foo_return() -> String { "yay" } + +fn foo_where() -> T +where + T: Sync, +{ + let x = 2; +} + +fn fooblock() { { "inner-block" } } + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space() { 1 } + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) {} +} + +trait CoolerTypes { + fn dummy(&self) {} +} + +fn Foo() +where + T: Bar, +{ +} diff --git a/tests/target/issue-3614/version_one.rs b/tests/target/issue-3614/version_one.rs new file mode 100644 index 00000000000..8ab28304732 --- /dev/null +++ b/tests/target/issue-3614/version_one.rs @@ -0,0 +1,15 @@ +// rustfmt-version: One + +fn main() { + let toto = || { + if true { + 42 + } else { + 24 + } + }; + + { + T + } +} diff --git a/tests/target/issue-3614/version_two.rs b/tests/target/issue-3614/version_two.rs new file mode 100644 index 00000000000..5d6f8e7a313 --- /dev/null +++ b/tests/target/issue-3614/version_two.rs @@ -0,0 +1,8 @@ +// rustfmt-version: Two + +fn main() { + let toto = || { + if true { 42 } else { 24 } + }; + { T } +} -- cgit 1.4.1-3-g733a5 From 5b0ce0ed120d71c879848fdbbe8b8d05c442373d Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Sun, 23 Jun 2019 14:32:14 +0900 Subject: avoid not to truncate necessary chars (#3640) --- src/formatting.rs | 7 ++++++- src/visitor.rs | 15 ++++++++++++++- tests/source/issue-3636.rs | 10 ++++++++++ tests/target/issue-3636.rs | 8 ++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3636.rs create mode 100644 tests/target/issue-3636.rs (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 522de400840..a71de71acee 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -177,7 +177,12 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { visitor.format_separate_mod(module, &*source_file); }; - debug_assert_eq!(visitor.line_number, count_newlines(&visitor.buffer)); + debug_assert_eq!( + visitor.line_number, + count_newlines(&visitor.buffer), + "failed in format_file visitor.buffer:\n {:?}", + &visitor.buffer + ); // For some reason, the source_map does not include terminating // newlines so we must add one on for each file. This is sad. diff --git a/src/visitor.rs b/src/visitor.rs index 19200f9592c..641ff1b62fd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -257,7 +257,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { self.config.tab_spaces() }; - self.buffer.truncate(total_len - chars_too_many); + + // FIXME this is a temporaly fix + // should be remove truncate logic in close_block + // avoid not to truncate necessary chars + let truncate_start = total_len - chars_too_many; + let target_str = &self.buffer[truncate_start..total_len]; + let truncate_length = target_str.len() - target_str.trim().len(); + + if let Some(last_char) = target_str.chars().last() { + self.buffer.truncate(total_len - truncate_length); + if last_char == '\n' { + self.buffer.push_str("\n"); + } + } } self.push_str("}"); self.block_indent = self.block_indent.block_unindent(self.config); diff --git a/tests/source/issue-3636.rs b/tests/source/issue-3636.rs new file mode 100644 index 00000000000..80355bbd2ef --- /dev/null +++ b/tests/source/issue-3636.rs @@ -0,0 +1,10 @@ +// rustfmt-file_lines: [{"file":"tests/source/issue-3636.rs","range":[4,7]}] + +fn foo() { + let x = + 42; + let y = + 42; + let z = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let z = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; +} \ No newline at end of file diff --git a/tests/target/issue-3636.rs b/tests/target/issue-3636.rs new file mode 100644 index 00000000000..d8d78e88d0e --- /dev/null +++ b/tests/target/issue-3636.rs @@ -0,0 +1,8 @@ +// rustfmt-file_lines: [{"file":"tests/source/issue-3636.rs","range":[4,7]}] + +fn foo() { + let x = 42; + let y = 42; + let z = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + let z = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; +} -- cgit 1.4.1-3-g733a5 From 26d370e9e52f5c2727b7289e339499aef0b7b3ec Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Sun, 23 Jun 2019 16:24:41 +0900 Subject: remove unreachable!() (#3646) --- src/imports.rs | 3 +-- tests/target/issue-3645.rs | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-3645.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index dd506000a69..a85889884ca 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -451,11 +451,10 @@ impl UseTree { // Normalise foo::self as bar -> foo as bar. if let UseSegment::Slf(_) = last { match self.path.last() { - None => {} Some(UseSegment::Ident(_, None)) => { aliased_self = true; } - _ => unreachable!(), + _ => {} } } diff --git a/tests/target/issue-3645.rs b/tests/target/issue-3645.rs new file mode 100644 index 00000000000..14bf96e6383 --- /dev/null +++ b/tests/target/issue-3645.rs @@ -0,0 +1,3 @@ +mod x { + use super::self as x; +} -- cgit 1.4.1-3-g733a5 From 561653326d158e81c7cd1cd4d6ed34133a33b8fc Mon Sep 17 00:00:00 2001 From: Nootan Ghimire Date: Tue, 25 Jun 2019 12:44:14 +1000 Subject: Add newline after help text (#3650) --- src/cargo-fmt/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 3c4d1c08b08..674099aa57b 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -96,7 +96,8 @@ fn execute() -> i32 { fn print_usage_to_stderr(reason: &str) { eprintln!("{}", reason); let app = Opts::clap(); - app.write_help(&mut io::stderr()) + app.after_help("") + .write_help(&mut io::stderr()) .expect("failed to write to stderr"); } -- cgit 1.4.1-3-g733a5 From 9986b9d01184e9be6390c377942386c4451c22d9 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Tue, 25 Jun 2019 23:14:19 +0900 Subject: fix internal error for long closure types (#3653) --- src/types.rs | 8 ++++++-- tests/source/issue-3651.rs | 4 ++++ tests/target/issue-3651.rs | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3651.rs create mode 100644 tests/target/issue-3651.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index c15a580f1a8..95f8014f38a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -328,8 +328,9 @@ where Shape::legacy(budget, offset) }; + let is_inputs_empty = inputs.len() == 0; let list_lo = context.snippet_provider.span_after(span, "("); - let (list_str, tactic) = if inputs.len() == 0 { + let (list_str, tactic) = if is_inputs_empty { let tactic = get_tactics(&[], &output, shape); let list_hi = context.snippet_provider.span_before(span, ")"); let comment = context @@ -377,7 +378,10 @@ where (write_list(&item_vec, &fmt)?, tactic) }; - let args = if tactic == DefinitiveListTactic::Horizontal || !context.use_block_indent() { + let args = if tactic == DefinitiveListTactic::Horizontal + || !context.use_block_indent() + || is_inputs_empty + { format!("({})", list_str) } else { format!( diff --git a/tests/source/issue-3651.rs b/tests/source/issue-3651.rs new file mode 100644 index 00000000000..c153e99d0f0 --- /dev/null +++ b/tests/source/issue-3651.rs @@ -0,0 +1,4 @@ +fn f() -> Box< + dyn FnMut() -> Thing< WithType = LongItemName, Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger>, +>{ +} \ No newline at end of file diff --git a/tests/target/issue-3651.rs b/tests/target/issue-3651.rs new file mode 100644 index 00000000000..4a95a1712ee --- /dev/null +++ b/tests/target/issue-3651.rs @@ -0,0 +1,7 @@ +fn f() -> Box< + dyn FnMut() -> Thing< + WithType = LongItemName, + Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger, + >, +> { +} -- cgit 1.4.1-3-g733a5 From c955b5908e0c699500d1d3dea3481136dd16197d Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 25 Jun 2019 09:15:33 -0500 Subject: fix: run in sub dirs/workspace member dirs (#3652) --- src/cargo-fmt/main.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 674099aa57b..ec6344e0695 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -253,12 +253,25 @@ fn get_targets_root_only(targets: &mut BTreeSet) -> Result<(), io::Error let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; let in_workspace_root = workspace_root_path == current_dir; - for package in metadata.packages { - if in_workspace_root || PathBuf::from(&package.manifest_path) == current_dir_manifest { - for target in package.targets { - targets.insert(Target::from_target(&target)); - } - } + let package_targets = match metadata.packages.len() { + 1 => metadata.packages.into_iter().next().unwrap().targets, + _ => metadata + .packages + .into_iter() + .filter(|p| { + in_workspace_root + || PathBuf::from(&p.manifest_path) + .canonicalize() + .unwrap_or_default() + == current_dir_manifest + }) + .map(|p| p.targets) + .flatten() + .collect(), + }; + + for target in package_targets { + targets.insert(Target::from_target(&target)); } Ok(()) -- cgit 1.4.1-3-g733a5 From e0e2f0db537904b0efa78a106384e62852b806f0 Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Tue, 25 Jun 2019 21:51:11 -0400 Subject: Don't panic on license check errors (#3655) Without this case, an ErrorKind::LicenseCheck results in a panic: thread 'main' panicked at 'internal error: entered unreachable code', src/tools/rustfmt/src/formatting.rs:320:18 N.B.: errors of this type are only raised when the configuration file contains `license_tempate_path = "TEMPLATE_FILE"`. --- src/formatting.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index a71de71acee..0faeb5102f2 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -313,7 +313,8 @@ impl FormattingError { | ErrorKind::DeprecatedAttr | ErrorKind::BadIssue(_) | ErrorKind::BadAttr - | ErrorKind::LostComment => { + | ErrorKind::LostComment + | ErrorKind::LicenseCheck => { let trailing_ws_start = self .line_buffer .rfind(|c: char| !c.is_whitespace()) -- cgit 1.4.1-3-g733a5 From 731f7d5200f0045efbadeef74e3c6a6e7c1b1c81 Mon Sep 17 00:00:00 2001 From: calebcartwright Date: Fri, 28 Jun 2019 16:15:42 -0500 Subject: fix: handling of associated type bounds --- src/types.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 95f8014f38a..d09e8c01e38 100644 --- a/src/types.rs +++ b/src/types.rs @@ -168,14 +168,22 @@ impl<'a> Rewrite for SegmentParam<'a> { SegmentParam::LifeTime(lt) => lt.rewrite(context, shape), SegmentParam::Type(ty) => ty.rewrite(context, shape), SegmentParam::Binding(assoc_ty_constraint) => { - let mut result = match context.config.type_punctuation_density() { - TypeDensity::Wide => { - format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident)) + let mut result = match assoc_ty_constraint.kind { + ast::AssocTyConstraintKind::Bound { .. } => { + format!("{}: ", rewrite_ident(context, assoc_ty_constraint.ident)) } - TypeDensity::Compressed => { - format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident)) + ast::AssocTyConstraintKind::Equality { .. } => { + match context.config.type_punctuation_density() { + TypeDensity::Wide => { + format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident)) + } + TypeDensity::Compressed => { + format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident)) + } + } } }; + let budget = shape.width.checked_sub(result.len())?; let rewrite = assoc_ty_constraint .kind -- cgit 1.4.1-3-g733a5 From 1f06a8b361dda56defe67d7af56a406cd2fbae08 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sun, 30 Jun 2019 05:19:24 +0200 Subject: fix extraction of missing comments when rewriting an empty where clause (#3663) --- src/comment.rs | 6 ++++-- tests/source/issue-3639.rs | 5 +++++ tests/target/issue-3639.rs | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3639.rs create mode 100644 tests/target/issue-3639.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 232d3745e59..6222c34b1a2 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -859,7 +859,9 @@ pub(crate) fn rewrite_missing_comment( ) -> Option { let missing_snippet = context.snippet(span); let trimmed_snippet = missing_snippet.trim(); - if !trimmed_snippet.is_empty() { + // check the span starts with a comment + let pos = trimmed_snippet.find('/'); + if !trimmed_snippet.is_empty() && pos.is_some() { rewrite_comment(trimmed_snippet, false, shape, context.config) } else { Some(String::new()) @@ -880,7 +882,7 @@ pub(crate) fn recover_missing_comment_in_span( Some(String::new()) } else { let missing_snippet = context.snippet(span); - let pos = missing_snippet.find('/').unwrap_or(0); + let pos = missing_snippet.find('/')?; // 1 = ` ` let total_width = missing_comment.len() + used_width + 1; let force_new_line_before_comment = diff --git a/tests/source/issue-3639.rs b/tests/source/issue-3639.rs new file mode 100644 index 00000000000..7b16b2dfde0 --- /dev/null +++ b/tests/source/issue-3639.rs @@ -0,0 +1,5 @@ +trait Foo where {} +struct Bar where {} +struct Bax where; +struct Baz(String) where; +impl<> Foo<> for Bar<> where {} diff --git a/tests/target/issue-3639.rs b/tests/target/issue-3639.rs new file mode 100644 index 00000000000..e8fddce2de6 --- /dev/null +++ b/tests/target/issue-3639.rs @@ -0,0 +1,5 @@ +trait Foo {} +struct Bar {} +struct Bax; +struct Baz(String); +impl Foo for Bar {} -- cgit 1.4.1-3-g733a5 From 44149d6ba4054b80e9d7009431eb2c5e501bb1fe Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sun, 30 Jun 2019 13:12:13 +0900 Subject: Release 1.3.1 --- CHANGELOG.md | 17 +++++++++++++- Cargo.lock | 66 ++++++++++++++++++++++++++++++------------------------- Cargo.toml | 8 +++---- src/config/mod.rs | 2 +- 4 files changed, 57 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index fffabab5e36..07ddc87d170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,27 @@ ## [Unreleased] +## [1.3.1] 2019-06-30 + +### Added + +- Implement the `Display` trait on the types of `Config`. + +### Changed + +- `ignore` configuration option now only supports paths separated by `/`. Windows-style paths are not supported. +- Running `cargo fmt` in a sub-directory of a project is now supported. + +### Fixed + +- Fix bugs that may cause rustfmt to crash. + ## [1.3.0] 2019-06-09 ### Added - Format modules defined inside `cfg_if` macro calls #3600 -- + ### Changed - Change option `format_doc_comment` to `format_code_in_doc_comment`. diff --git a/Cargo.lock b/Cargo.lock index 5bd8d006b4f..d6c1cef8d84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -114,10 +114,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cargo_metadata" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", @@ -235,6 +235,26 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dirs" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dirs-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.2" @@ -260,15 +280,6 @@ dependencies = [ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "error-chain" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "failure" version = "0.1.5" @@ -818,7 +829,7 @@ dependencies = [ [[package]] name = "rustfmt-config_proc_macro" -version = "0.1.0" +version = "0.1.2" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -827,15 +838,15 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.3.0" +version = "1.3.1" dependencies = [ "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -848,10 +859,10 @@ dependencies = [ "rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-config_proc_macro 0.1.0", + "rustfmt-config_proc_macro 0.1.2", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -946,16 +957,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1073,11 +1084,6 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "walkdir" version = "2.2.7" @@ -1139,7 +1145,7 @@ dependencies = [ "checksum bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "59604ece62a407dc9164732e5adea02467898954c3a5811fd2dc140af14ef15b" "checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum cargo_metadata 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "178d62b240c34223f265a4c1e275e37d62da163d421fc8d7f7e3ee340f803c57" +"checksum cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "929766d993a2fde7a0ae962ee82429069cd7b68839cd9375b98efd719df65d3a" "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" @@ -1153,10 +1159,11 @@ dependencies = [ "checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" +"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" +"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" -"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" @@ -1231,8 +1238,8 @@ dependencies = [ "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c767a8971f53d7324583085deee2e230903be09e52fb27df9af94c5cb2b43c31" -"checksum structopt-derive 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c57a30c87454ced2186f62f940e981746e8cbbe026d52090c8c4352b636f8235" +"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" +"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" "checksum syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)" = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" @@ -1248,7 +1255,6 @@ dependencies = [ "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" diff --git a/Cargo.toml b/Cargo.toml index dd282f70a0b..99a0890574e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.3.0" +version = "1.3.1" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -47,7 +47,7 @@ log = "0.4" env_logger = "0.6" getopts = "0.2" derive-new = "0.5" -cargo_metadata = "0.7" +cargo_metadata = "0.8" rustc-ap-rustc_target = "491.0.0" rustc-ap-syntax = "491.0.0" rustc-ap-syntax_pos = "491.0.0" @@ -55,10 +55,10 @@ failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" unicode_categories = "0.1.1" -dirs = "1.0.4" +dirs = "2.0.1" ignore = "0.4.6" annotate-snippets = { version = "0.5.0", features = ["ansi_term"] } -structopt = "0.2.15" +structopt = "0.2.18" rustfmt-config_proc_macro = { version = "0.1", path = "config_proc_macro" } diff --git a/src/config/mod.rs b/src/config/mod.rs index 27044ee18d6..4b4f9921d80 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.3.0" +required_version = "1.3.1" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From ff49b806283050c9e095e0352560256522356c3b Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 6 Jul 2019 00:17:35 -0500 Subject: fix: handling of --all when dep name and dir name differ (#3664) --- src/cargo-fmt/main.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index ec6344e0695..c063d8eb419 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -247,7 +247,7 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Erro } fn get_targets_root_only(targets: &mut BTreeSet) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None)?; + let metadata = get_cargo_metadata(None, false)?; let current_dir = env::current_dir()?.canonicalize()?; let current_dir_manifest = current_dir.join("Cargo.toml"); let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; @@ -282,7 +282,8 @@ fn get_targets_recursive( mut targets: &mut BTreeSet, visited: &mut BTreeSet, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(manifest_path)?; + let metadata = get_cargo_metadata(manifest_path, false)?; + let metadata_with_deps = get_cargo_metadata(manifest_path, true)?; for package in metadata.packages { add_targets(&package.targets, &mut targets); @@ -293,11 +294,19 @@ fn get_targets_recursive( continue; } - let mut manifest_path = PathBuf::from(&package.manifest_path); - - manifest_path.pop(); - manifest_path.push(&dependency.name); - manifest_path.push("Cargo.toml"); + let dependency_package = metadata_with_deps + .packages + .iter() + .find(|p| p.name == dependency.name); + let manifest_path = if dependency_package.is_some() { + PathBuf::from(&dependency_package.unwrap().manifest_path) + } else { + let mut package_manifest_path = PathBuf::from(&package.manifest_path); + package_manifest_path.pop(); + package_manifest_path.push(&dependency.name); + package_manifest_path.push("Cargo.toml"); + package_manifest_path + }; if manifest_path.exists() { visited.insert(dependency.name); @@ -313,7 +322,7 @@ fn get_targets_with_hitlist( hitlist: &[String], targets: &mut BTreeSet, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None)?; + let metadata = get_cargo_metadata(None, false)?; let mut workspace_hitlist: BTreeSet<&String> = BTreeSet::from_iter(hitlist); @@ -399,9 +408,14 @@ fn run_rustfmt( .unwrap_or(SUCCESS)) } -fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result { +fn get_cargo_metadata( + manifest_path: Option<&Path>, + include_deps: bool, +) -> Result { let mut cmd = cargo_metadata::MetadataCommand::new(); - cmd.no_deps(); + if !include_deps { + cmd.no_deps(); + } if let Some(manifest_path) = manifest_path { cmd.manifest_path(manifest_path); } -- cgit 1.4.1-3-g733a5 From 3200af97857cf3712e10fed4113206c1ffe97524 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 6 Jul 2019 14:17:53 +0900 Subject: Do not consider macro-origin await as chain item (#3671) --- src/chains.rs | 6 ++++-- tests/source/async_fn.rs | 5 +++++ tests/target/async_fn.rs | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 6cac55c6e86..1ca0ac582b7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -168,7 +168,7 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), field.span.hi()); (kind, span) } - ast::ExprKind::Await(_, ref nested) => { + ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, ref nested) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } @@ -396,7 +396,9 @@ impl Chain { } ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) - | ast::ExprKind::Await(_, ref subexpr) => Some(Self::convert_try(subexpr, context)), + | ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, ref subexpr) => { + Some(Self::convert_try(subexpr, context)) + } _ => None, } } diff --git a/tests/source/async_fn.rs b/tests/source/async_fn.rs index f6c5f5e1c9a..b4dc9fac5b2 100644 --- a/tests/source/async_fn.rs +++ b/tests/source/async_fn.rs @@ -19,3 +19,8 @@ async unsafe fn rust() { Ok(()) } } + +async fn await_macro() { + await ! ( + something)?; +} diff --git a/tests/target/async_fn.rs b/tests/target/async_fn.rs index 7992e63c080..82be8c76785 100644 --- a/tests/target/async_fn.rs +++ b/tests/target/async_fn.rs @@ -18,3 +18,7 @@ async unsafe fn rust() { Ok(()) } } + +async fn await_macro() { + await!(something)?; +} -- cgit 1.4.1-3-g733a5 From 679c8d5f106e8442bf8c4a54609a63df9eb3863c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 6 Jul 2019 14:22:30 +0900 Subject: Release 1.3.2 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d6c1cef8d84..9568dbcfd56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,7 +838,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.3.1" +version = "1.3.2" dependencies = [ "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 99a0890574e..56815a1e5b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.3.1" +version = "1.3.2" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index 4b4f9921d80..01ce1df8a9a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.3.1" +required_version = "1.3.2" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From 17cbbd8cbc2d829e0ce07c619a2970a46a3b9b8c Mon Sep 17 00:00:00 2001 From: calebcartwright Date: Fri, 12 Jul 2019 20:59:29 -0500 Subject: feat: add --manifest-path support to cargo fmt --- src/cargo-fmt/main.rs | 67 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index c063d8eb419..f32f7b5f1be 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -41,6 +41,10 @@ pub struct Opts { #[structopt(short = "p", long = "package", value_name = "package")] packages: Vec, + /// Specify path to Cargo.toml + #[structopt(long = "manifest-path", value_name = "manifest-path")] + manifest_path: Option, + /// Options passed to rustfmt // 'raw = true' to make `--` explicit. #[structopt(name = "rustfmt_options", raw(raw = "true"))] @@ -90,7 +94,27 @@ fn execute() -> i32 { let strategy = CargoFmtStrategy::from_opts(&opts); - handle_command_status(format_crate(verbosity, &strategy, opts.rustfmt_options)) + if opts.manifest_path.is_some() { + let specified_manifest_path = opts.manifest_path.unwrap(); + if !specified_manifest_path.ends_with("Cargo.toml") { + print_usage_to_stderr("the manifest-path must be a path to a Cargo.toml file"); + return FAILURE; + } + let manifest_path = PathBuf::from(specified_manifest_path); + handle_command_status(format_crate( + verbosity, + &strategy, + opts.rustfmt_options, + Some(&manifest_path), + )) + } else { + handle_command_status(format_crate( + verbosity, + &strategy, + opts.rustfmt_options, + None, + )) + } } fn print_usage_to_stderr(reason: &str) { @@ -142,6 +166,7 @@ fn format_crate( verbosity: Verbosity, strategy: &CargoFmtStrategy, rustfmt_args: Vec, + manifest_path: Option<&Path>, ) -> Result { let targets = if rustfmt_args .iter() @@ -149,7 +174,7 @@ fn format_crate( { BTreeSet::new() } else { - get_targets(strategy)? + get_targets(strategy, manifest_path)? }; // Currently only bin and lib files get formatted. @@ -227,13 +252,20 @@ impl CargoFmtStrategy { } /// Based on the specified `CargoFmtStrategy`, returns a set of main source files. -fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Error> { +fn get_targets( + strategy: &CargoFmtStrategy, + manifest_path: Option<&Path>, +) -> Result, io::Error> { let mut targets = BTreeSet::new(); match *strategy { - CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?, - CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut BTreeSet::new())?, - CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?, + CargoFmtStrategy::Root => get_targets_root_only(manifest_path, &mut targets)?, + CargoFmtStrategy::All => { + get_targets_recursive(manifest_path, &mut targets, &mut BTreeSet::new())? + } + CargoFmtStrategy::Some(ref hitlist) => { + get_targets_with_hitlist(manifest_path, hitlist, &mut targets)? + } } if targets.is_empty() { @@ -246,12 +278,22 @@ fn get_targets(strategy: &CargoFmtStrategy) -> Result, io::Erro } } -fn get_targets_root_only(targets: &mut BTreeSet) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None, false)?; - let current_dir = env::current_dir()?.canonicalize()?; - let current_dir_manifest = current_dir.join("Cargo.toml"); +fn get_targets_root_only( + manifest_path: Option<&Path>, + targets: &mut BTreeSet, +) -> Result<(), io::Error> { + let metadata = get_cargo_metadata(manifest_path, false)?; let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; - let in_workspace_root = workspace_root_path == current_dir; + let (in_workspace_root, current_dir_manifest) = if manifest_path.is_some() { + let target_manifest = manifest_path.unwrap().canonicalize()?; + (workspace_root_path == target_manifest, target_manifest) + } else { + let current_dir = env::current_dir()?.canonicalize()?; + ( + workspace_root_path == current_dir, + current_dir.join("Cargo.toml"), + ) + }; let package_targets = match metadata.packages.len() { 1 => metadata.packages.into_iter().next().unwrap().targets, @@ -319,10 +361,11 @@ fn get_targets_recursive( } fn get_targets_with_hitlist( + manifest_path: Option<&Path>, hitlist: &[String], targets: &mut BTreeSet, ) -> Result<(), io::Error> { - let metadata = get_cargo_metadata(None, false)?; + let metadata = get_cargo_metadata(manifest_path, false)?; let mut workspace_hitlist: BTreeSet<&String> = BTreeSet::from_iter(hitlist); -- cgit 1.4.1-3-g733a5 From 37695b3c45ec8015974359a2f809aa98accd173c Mon Sep 17 00:00:00 2001 From: Ruben Schmidmeister Date: Sun, 14 Jul 2019 03:22:18 +0200 Subject: Extract configuration snippet tests into own module (#3667) * Extract configuration snippet tests into own module * Move helper function outside of test function --- src/test/configuration_snippet.rs | 286 ++++++++++++++++++++++++++++++++++++++ src/test/mod.rs | 284 +------------------------------------ 2 files changed, 291 insertions(+), 279 deletions(-) create mode 100644 src/test/configuration_snippet.rs (limited to 'src') diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs new file mode 100644 index 00000000000..55289f55537 --- /dev/null +++ b/src/test/configuration_snippet.rs @@ -0,0 +1,286 @@ +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::io::{BufRead, BufReader, Write}; +use std::iter::Enumerate; +use std::path::{Path, PathBuf}; + +use super::{print_mismatches, write_message, DIFF_CONTEXT_SIZE}; +use crate::config::{Config, EmitMode, Verbosity}; +use crate::rustfmt_diff::{make_diff, Mismatch}; +use crate::{Input, Session}; + +const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; + +// This enum is used to represent one of three text features in Configurations.md: a block of code +// with its starting line number, the name of a rustfmt configuration option, or the value of a +// rustfmt configuration option. +enum ConfigurationSection { + CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) + ConfigName(String), + ConfigValue(String), +} + +impl ConfigurationSection { + fn get_section>( + file: &mut Enumerate, + ) -> Option { + lazy_static! { + static ref CONFIG_NAME_REGEX: regex::Regex = + regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern"); + static ref CONFIG_VALUE_REGEX: regex::Regex = + regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) + .expect("failed creating configuration value pattern"); + } + + loop { + match file.next() { + Some((i, line)) => { + if line.starts_with("```rust") { + // Get the lines of the code block. + let lines: Vec = file + .map(|(_i, l)| l) + .take_while(|l| !l.starts_with("```")) + .collect(); + let block = format!("{}\n", lines.join("\n")); + + // +1 to translate to one-based indexing + // +1 to get to first line of code (line after "```") + let start_line = (i + 2) as u32; + + return Some(ConfigurationSection::CodeBlock((block, start_line))); + } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); + } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { + return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); + } + } + None => return None, // reached the end of the file + } + } + } +} + +// This struct stores the information about code blocks in the configurations +// file, formats the code blocks, and prints formatting errors. +struct ConfigCodeBlock { + config_name: Option, + config_value: Option, + code_block: Option, + code_block_start: Option, +} + +impl ConfigCodeBlock { + fn new() -> ConfigCodeBlock { + ConfigCodeBlock { + config_name: None, + config_value: None, + code_block: None, + code_block_start: None, + } + } + + fn set_config_name(&mut self, name: Option) { + self.config_name = name; + self.config_value = None; + } + + fn set_config_value(&mut self, value: Option) { + self.config_value = value; + } + + fn set_code_block(&mut self, code_block: String, code_block_start: u32) { + self.code_block = Some(code_block); + self.code_block_start = Some(code_block_start); + } + + fn get_block_config(&self) -> Config { + let mut config = Config::default(); + config.set().verbose(Verbosity::Quiet); + if self.config_name.is_some() && self.config_value.is_some() { + config.override_value( + self.config_name.as_ref().unwrap(), + self.config_value.as_ref().unwrap(), + ); + } + config + } + + fn code_block_valid(&self) -> bool { + // We never expect to not have a code block. + assert!(self.code_block.is_some() && self.code_block_start.is_some()); + + // See if code block begins with #![rustfmt::skip]. + let fmt_skip = self + .code_block + .as_ref() + .unwrap() + .lines() + .nth(0) + .unwrap_or("") + == "#![rustfmt::skip]"; + + if self.config_name.is_none() && !fmt_skip { + write_message(&format!( + "No configuration name for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + if self.config_value.is_none() && !fmt_skip { + write_message(&format!( + "No configuration value for {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return false; + } + true + } + + fn has_parsing_errors(&self, session: &Session<'_, T>) -> bool { + if session.has_parsing_errors() { + write_message(&format!( + "\u{261d}\u{1f3fd} Cannot format {}:{}", + CONFIGURATIONS_FILE_NAME, + self.code_block_start.unwrap() + )); + return true; + } + + false + } + + fn print_diff(&self, compare: Vec) { + let mut mismatches = HashMap::new(); + mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); + print_mismatches(mismatches, |line_num| { + format!( + "\nMismatch at {}:{}:", + CONFIGURATIONS_FILE_NAME, + line_num + self.code_block_start.unwrap() - 1 + ) + }); + } + + fn formatted_has_diff(&self, text: &str) -> bool { + let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); + if !compare.is_empty() { + self.print_diff(compare); + return true; + } + + false + } + + // Return a bool indicating if formatting this code block is an idempotent + // operation. This function also triggers printing any formatting failure + // messages. + fn formatted_is_idempotent(&self) -> bool { + // Verify that we have all of the expected information. + if !self.code_block_valid() { + return false; + } + + let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); + let mut config = self.get_block_config(); + config.set().emit_mode(EmitMode::Stdout); + let mut buf: Vec = vec![]; + + { + let mut session = Session::new(config, Some(&mut buf)); + session.format(input).unwrap(); + if self.has_parsing_errors(&session) { + return false; + } + } + + !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) + } + + // Extract a code block from the iterator. Behavior: + // - Rust code blocks are identifed by lines beginning with "```rust". + // - One explicit configuration setting is supported per code block. + // - Rust code blocks with no configuration setting are illegal and cause an + // assertion failure, unless the snippet begins with #![rustfmt::skip]. + // - Configuration names in Configurations.md must be in the form of + // "## `NAME`". + // - Configuration values in Configurations.md must be in the form of + // "#### `VALUE`". + fn extract>( + file: &mut Enumerate, + prev: Option<&ConfigCodeBlock>, + hash_set: &mut HashSet, + ) -> Option { + let mut code_block = ConfigCodeBlock::new(); + code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); + + loop { + match ConfigurationSection::get_section(file) { + Some(ConfigurationSection::CodeBlock((block, start_line))) => { + code_block.set_code_block(block, start_line); + break; + } + Some(ConfigurationSection::ConfigName(name)) => { + assert!( + Config::is_valid_name(&name), + "an unknown configuration option was found: {}", + name + ); + assert!( + hash_set.remove(&name), + "multiple configuration guides found for option {}", + name + ); + code_block.set_config_name(Some(name)); + } + Some(ConfigurationSection::ConfigValue(value)) => { + code_block.set_config_value(Some(value)); + } + None => return None, // end of file was reached + } + } + + Some(code_block) + } +} + +#[test] +fn configuration_snippet_tests() { + let blocks = get_code_blocks(); + let failures = blocks + .iter() + .map(ConfigCodeBlock::formatted_is_idempotent) + .fold(0, |acc, r| acc + (!r as u32)); + + // Display results. + println!("Ran {} configurations tests.", blocks.len()); + assert_eq!(failures, 0, "{} configurations tests failed", failures); +} + +// Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one +// entry for each Rust code block found. +fn get_code_blocks() -> Vec { + let mut file_iter = BufReader::new( + fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) + .unwrap_or_else(|_| panic!("couldn't read file {}", CONFIGURATIONS_FILE_NAME)), + ) + .lines() + .map(Result::unwrap) + .enumerate(); + let mut code_blocks: Vec = Vec::new(); + let mut hash_set = Config::hash_set(); + + while let Some(cb) = ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) + { + code_blocks.push(cb); + } + + for name in hash_set { + if !Config::is_hidden_option(&name) { + panic!("{} does not have a configuration guide", name); + } + } + + code_blocks +} diff --git a/src/test/mod.rs b/src/test/mod.rs index 89bde8c0467..10aad268a8d 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -1,23 +1,24 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::env; use std::fs; use std::io::{self, BufRead, BufReader, Read, Write}; -use std::iter::{Enumerate, Peekable}; +use std::iter::Peekable; use std::mem; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::str::Chars; use std::thread; -use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic, Verbosity}; +use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; use crate::formatting::{ReportedErrors, SourceFile}; use crate::is_nightly_channel; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session}; +mod configuration_snippet; + const DIFF_CONTEXT_SIZE: usize = 3; -const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; // A list of files on which we want to skip testing. const SKIP_FILE_WHITE_LIST: &[&str] = &[ @@ -768,281 +769,6 @@ fn string_eq_ignore_newline_repr_test() { assert!(!string_eq_ignore_newline_repr("a\r\nbcd", "a\nbcdefghijk")); } -// This enum is used to represent one of three text features in Configurations.md: a block of code -// with its starting line number, the name of a rustfmt configuration option, or the value of a -// rustfmt configuration option. -enum ConfigurationSection { - CodeBlock((String, u32)), // (String: block of code, u32: line number of code block start) - ConfigName(String), - ConfigValue(String), -} - -impl ConfigurationSection { - fn get_section>( - file: &mut Enumerate, - ) -> Option { - lazy_static! { - static ref CONFIG_NAME_REGEX: regex::Regex = - regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern"); - static ref CONFIG_VALUE_REGEX: regex::Regex = - regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#) - .expect("failed creating configuration value pattern"); - } - - loop { - match file.next() { - Some((i, line)) => { - if line.starts_with("```rust") { - // Get the lines of the code block. - let lines: Vec = file - .map(|(_i, l)| l) - .take_while(|l| !l.starts_with("```")) - .collect(); - let block = format!("{}\n", lines.join("\n")); - - // +1 to translate to one-based indexing - // +1 to get to first line of code (line after "```") - let start_line = (i + 2) as u32; - - return Some(ConfigurationSection::CodeBlock((block, start_line))); - } else if let Some(c) = CONFIG_NAME_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigName(String::from(&c[1]))); - } else if let Some(c) = CONFIG_VALUE_REGEX.captures(&line) { - return Some(ConfigurationSection::ConfigValue(String::from(&c[1]))); - } - } - None => return None, // reached the end of the file - } - } - } -} - -// This struct stores the information about code blocks in the configurations -// file, formats the code blocks, and prints formatting errors. -struct ConfigCodeBlock { - config_name: Option, - config_value: Option, - code_block: Option, - code_block_start: Option, -} - -impl ConfigCodeBlock { - fn new() -> ConfigCodeBlock { - ConfigCodeBlock { - config_name: None, - config_value: None, - code_block: None, - code_block_start: None, - } - } - - fn set_config_name(&mut self, name: Option) { - self.config_name = name; - self.config_value = None; - } - - fn set_config_value(&mut self, value: Option) { - self.config_value = value; - } - - fn set_code_block(&mut self, code_block: String, code_block_start: u32) { - self.code_block = Some(code_block); - self.code_block_start = Some(code_block_start); - } - - fn get_block_config(&self) -> Config { - let mut config = Config::default(); - config.set().verbose(Verbosity::Quiet); - if self.config_name.is_some() && self.config_value.is_some() { - config.override_value( - self.config_name.as_ref().unwrap(), - self.config_value.as_ref().unwrap(), - ); - } - config - } - - fn code_block_valid(&self) -> bool { - // We never expect to not have a code block. - assert!(self.code_block.is_some() && self.code_block_start.is_some()); - - // See if code block begins with #![rustfmt::skip]. - let fmt_skip = self - .code_block - .as_ref() - .unwrap() - .lines() - .nth(0) - .unwrap_or("") - == "#![rustfmt::skip]"; - - if self.config_name.is_none() && !fmt_skip { - write_message(&format!( - "No configuration name for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - if self.config_value.is_none() && !fmt_skip { - write_message(&format!( - "No configuration value for {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return false; - } - true - } - - fn has_parsing_errors(&self, session: &Session<'_, T>) -> bool { - if session.has_parsing_errors() { - write_message(&format!( - "\u{261d}\u{1f3fd} Cannot format {}:{}", - CONFIGURATIONS_FILE_NAME, - self.code_block_start.unwrap() - )); - return true; - } - - false - } - - fn print_diff(&self, compare: Vec) { - let mut mismatches = HashMap::new(); - mismatches.insert(PathBuf::from(CONFIGURATIONS_FILE_NAME), compare); - print_mismatches(mismatches, |line_num| { - format!( - "\nMismatch at {}:{}:", - CONFIGURATIONS_FILE_NAME, - line_num + self.code_block_start.unwrap() - 1 - ) - }); - } - - fn formatted_has_diff(&self, text: &str) -> bool { - let compare = make_diff(self.code_block.as_ref().unwrap(), text, DIFF_CONTEXT_SIZE); - if !compare.is_empty() { - self.print_diff(compare); - return true; - } - - false - } - - // Return a bool indicating if formatting this code block is an idempotent - // operation. This function also triggers printing any formatting failure - // messages. - fn formatted_is_idempotent(&self) -> bool { - // Verify that we have all of the expected information. - if !self.code_block_valid() { - return false; - } - - let input = Input::Text(self.code_block.as_ref().unwrap().to_owned()); - let mut config = self.get_block_config(); - config.set().emit_mode(EmitMode::Stdout); - let mut buf: Vec = vec![]; - - { - let mut session = Session::new(config, Some(&mut buf)); - session.format(input).unwrap(); - if self.has_parsing_errors(&session) { - return false; - } - } - - !self.formatted_has_diff(&String::from_utf8(buf).unwrap()) - } - - // Extract a code block from the iterator. Behavior: - // - Rust code blocks are identifed by lines beginning with "```rust". - // - One explicit configuration setting is supported per code block. - // - Rust code blocks with no configuration setting are illegal and cause an - // assertion failure, unless the snippet begins with #![rustfmt::skip]. - // - Configuration names in Configurations.md must be in the form of - // "## `NAME`". - // - Configuration values in Configurations.md must be in the form of - // "#### `VALUE`". - fn extract>( - file: &mut Enumerate, - prev: Option<&ConfigCodeBlock>, - hash_set: &mut HashSet, - ) -> Option { - let mut code_block = ConfigCodeBlock::new(); - code_block.config_name = prev.and_then(|cb| cb.config_name.clone()); - - loop { - match ConfigurationSection::get_section(file) { - Some(ConfigurationSection::CodeBlock((block, start_line))) => { - code_block.set_code_block(block, start_line); - break; - } - Some(ConfigurationSection::ConfigName(name)) => { - assert!( - Config::is_valid_name(&name), - "an unknown configuration option was found: {}", - name - ); - assert!( - hash_set.remove(&name), - "multiple configuration guides found for option {}", - name - ); - code_block.set_config_name(Some(name)); - } - Some(ConfigurationSection::ConfigValue(value)) => { - code_block.set_config_value(Some(value)); - } - None => return None, // end of file was reached - } - } - - Some(code_block) - } -} - -#[test] -fn configuration_snippet_tests() { - // Read Configurations.md and build a `Vec` of `ConfigCodeBlock` structs with one - // entry for each Rust code block found. - fn get_code_blocks() -> Vec { - let mut file_iter = BufReader::new( - fs::File::open(Path::new(CONFIGURATIONS_FILE_NAME)) - .unwrap_or_else(|_| panic!("couldn't read file {}", CONFIGURATIONS_FILE_NAME)), - ) - .lines() - .map(Result::unwrap) - .enumerate(); - let mut code_blocks: Vec = Vec::new(); - let mut hash_set = Config::hash_set(); - - while let Some(cb) = - ConfigCodeBlock::extract(&mut file_iter, code_blocks.last(), &mut hash_set) - { - code_blocks.push(cb); - } - - for name in hash_set { - if !Config::is_hidden_option(&name) { - panic!("{} does not have a configuration guide", name); - } - } - - code_blocks - } - - let blocks = get_code_blocks(); - let failures = blocks - .iter() - .map(ConfigCodeBlock::formatted_is_idempotent) - .fold(0, |acc, r| acc + (!r as u32)); - - // Display results. - println!("Ran {} configurations tests.", blocks.len()); - assert_eq!(failures, 0, "{} configurations tests failed", failures); -} - struct TempFile { path: PathBuf, } -- cgit 1.4.1-3-g733a5 From e55fc6be3b3cac1954e5c7d189c62021ef76622a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 13 Jul 2019 18:25:53 -0700 Subject: Fix using --help, --verbose, etc. (#3620) --- src/cargo-fmt/main.rs | 22 ++++++++-------- tests/cargo-fmt/main.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 tests/cargo-fmt/main.rs (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index c063d8eb419..b806ca7609b 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -85,7 +85,14 @@ fn execute() -> i32 { }; if opts.version { - return handle_command_status(get_version()); + return handle_command_status(get_rustfmt_info(&[String::from("--version")])); + } + if opts.rustfmt_options.iter().any(|s| { + ["--print-config", "-h", "--help", "-V", "--version"].contains(&s.as_str()) + || s.starts_with("--help=") + || s.starts_with("--print-config=") + }) { + return handle_command_status(get_rustfmt_info(&opts.rustfmt_options)); } let strategy = CargoFmtStrategy::from_opts(&opts); @@ -118,10 +125,10 @@ fn handle_command_status(status: Result) -> i32 { } } -fn get_version() -> Result { +fn get_rustfmt_info(args: &[String]) -> Result { let mut command = Command::new("rustfmt") .stdout(std::process::Stdio::inherit()) - .args(&[String::from("--version")]) + .args(args) .spawn() .map_err(|e| match e.kind() { io::ErrorKind::NotFound => io::Error::new( @@ -143,14 +150,7 @@ fn format_crate( strategy: &CargoFmtStrategy, rustfmt_args: Vec, ) -> Result { - let targets = if rustfmt_args - .iter() - .any(|s| ["--print-config", "-h", "--help", "-V", "--version"].contains(&s.as_str())) - { - BTreeSet::new() - } else { - get_targets(strategy)? - }; + let targets = get_targets(strategy)?; // Currently only bin and lib files get formatted. run_rustfmt(&targets, &rustfmt_args, verbosity) diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs new file mode 100644 index 00000000000..d1ba2e689b6 --- /dev/null +++ b/tests/cargo-fmt/main.rs @@ -0,0 +1,70 @@ +// Integration tests for cargo-fmt. + +use std::env; +use std::process::Command; + +/// Run the cargo-fmt executable and return its output. +fn cargo_fmt(args: &[&str]) -> (String, String) { + let mut bin_dir = env::current_exe().unwrap(); + bin_dir.pop(); // chop off test exe name + if bin_dir.ends_with("deps") { + bin_dir.pop(); + } + let cmd = bin_dir.join(format!("cargo-fmt{}", env::consts::EXE_SUFFIX)); + + // Ensure cargo-fmt runs the rustfmt binary from the local target dir. + let path = env::var_os("PATH").unwrap_or_default(); + let mut paths = env::split_paths(&path).collect::>(); + paths.insert(0, bin_dir); + let new_path = env::join_paths(paths).unwrap(); + + match Command::new(&cmd).args(args).env("PATH", new_path).output() { + Ok(output) => ( + String::from_utf8(output.stdout).expect("utf-8"), + String::from_utf8(output.stderr).expect("utf-8"), + ), + Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e), + } +} + +macro_rules! assert_that { + ($args:expr, $check:ident $check_args:tt) => { + let (stdout, stderr) = cargo_fmt($args); + if !stdout.$check$check_args { + panic!( + "Output not expected for cargo-fmt {:?}\n\ + expected: {}{}\n\ + actual stdout:\n{}\n\ + actual stderr:\n{}", + $args, + stringify!($check), + stringify!($check_args), + stdout, + stderr + ); + } + }; +} + +#[test] +fn version() { + assert_that!(&["--version"], starts_with("rustfmt ")); + assert_that!(&["--version"], starts_with("rustfmt ")); + assert_that!(&["--", "-V"], starts_with("rustfmt ")); + assert_that!(&["--", "--version"], starts_with("rustfmt ")); +} + +#[test] +fn print_config() { + assert_that!( + &["--", "--print-config", "current", "."], + contains("max_width = ") + ); +} + +#[test] +fn rustfmt_help() { + assert_that!(&["--", "--help"], contains("Format Rust code")); + assert_that!(&["--", "-h"], contains("Format Rust code")); + assert_that!(&["--", "--help=config"], contains("Configuration Options:")); +} -- cgit 1.4.1-3-g733a5 From 71289e1d230d19f223e45b0abe75ae976f567900 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Sun, 14 Jul 2019 22:16:47 +0900 Subject: fix 'extra comma inserted due to comment' (#3677) --- src/lists.rs | 6 +++++- tests/source/issue-3675.rs | 5 +++++ tests/target/issue-3675.rs | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-3675.rs create mode 100644 tests/target/issue-3675.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index 4c31f670d4d..ac83d7082c8 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -612,7 +612,11 @@ pub(crate) fn extract_post_comment( post_snippet[1..].trim_matches(white_space) } else if post_snippet.starts_with(separator) { post_snippet[separator.len()..].trim_matches(white_space) - } else if post_snippet.ends_with(',') && !post_snippet.trim().starts_with("//") { + } + // not comment or over two lines + else if post_snippet.ends_with(',') + && (!post_snippet.trim().starts_with("//") || post_snippet.trim().contains('\n')) + { post_snippet[..(post_snippet.len() - 1)].trim_matches(white_space) } else { post_snippet diff --git a/tests/source/issue-3675.rs b/tests/source/issue-3675.rs new file mode 100644 index 00000000000..f16efb2dcac --- /dev/null +++ b/tests/source/issue-3675.rs @@ -0,0 +1,5 @@ + fn main() { + println!("{}" + // comment + , 111); + } \ No newline at end of file diff --git a/tests/target/issue-3675.rs b/tests/target/issue-3675.rs new file mode 100644 index 00000000000..62d986e7734 --- /dev/null +++ b/tests/target/issue-3675.rs @@ -0,0 +1,6 @@ +fn main() { + println!( + "{}", // comment + 111 + ); +} -- cgit 1.4.1-3-g733a5 From 6f67f077529525cb5f96803f17295079656f4058 Mon Sep 17 00:00:00 2001 From: calebcartwright Date: Sun, 14 Jul 2019 09:56:07 -0500 Subject: refactor: simplify manifest_path option checks --- src/cargo-fmt/main.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 3a0d1cfddbd..7651a0ee437 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -101,8 +101,7 @@ fn execute() -> i32 { let strategy = CargoFmtStrategy::from_opts(&opts); - if opts.manifest_path.is_some() { - let specified_manifest_path = opts.manifest_path.unwrap(); + if let Some(specified_manifest_path) = opts.manifest_path { if !specified_manifest_path.ends_with("Cargo.toml") { print_usage_to_stderr("the manifest-path must be a path to a Cargo.toml file"); return FAILURE; @@ -284,9 +283,11 @@ fn get_targets_root_only( ) -> Result<(), io::Error> { let metadata = get_cargo_metadata(manifest_path, false)?; let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; - let (in_workspace_root, current_dir_manifest) = if manifest_path.is_some() { - let target_manifest = manifest_path.unwrap().canonicalize()?; - (workspace_root_path == target_manifest, target_manifest) + let (in_workspace_root, current_dir_manifest) = if let Some(target_manifest) = manifest_path { + ( + workspace_root_path == target_manifest, + target_manifest.canonicalize()?, + ) } else { let current_dir = env::current_dir()?.canonicalize()?; ( -- cgit 1.4.1-3-g733a5 From 6487422b3e0b93645e004c66c32fad5a7ab58b80 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 15 Jul 2019 13:58:54 +0200 Subject: fix print-config minimal option (#3687) --- src/bin/main.rs | 109 +++++++++++++++++++++++++++++--------------------- tests/rustfmt/main.rs | 77 +++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 45 deletions(-) create mode 100644 tests/rustfmt/main.rs (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 5b69a440b65..813504cdd6d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,6 +1,6 @@ use env_logger; -#[macro_use] -extern crate failure; +use failure::{err_msg, format_err, Error as FailureError, Fail}; +use io::Error as IoError; use rustfmt_nightly as rustfmt; @@ -10,12 +10,10 @@ use std::io::{self, stdout, Read, Write}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use failure::err_msg; - use getopts::{Matches, Options}; use crate::rustfmt::{ - load_config, CliOptions, Color, Config, Edition, EmitMode, ErrorKind, FileLines, FileName, + load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, FormatReportFormatterBuilder, Input, Session, Verbosity, }; @@ -49,20 +47,37 @@ enum Operation { }, /// Print the help message. Help(HelpOp), - // Print version information + /// Print version information Version, /// Output default config to a file, or stdout if None - ConfigOutputDefault { - path: Option, - }, + ConfigOutputDefault { path: Option }, /// Output current config (as if formatting to a file) to stdout - ConfigOutputCurrent { - path: Option, - }, + ConfigOutputCurrent { path: Option }, /// No file specified, read from stdin - Stdin { - input: String, - }, + Stdin { input: String }, +} + +/// Rustfmt operations errors. +#[derive(Fail, Debug)] +pub enum OperationError { + /// An unknown help topic was requested. + #[fail(display = "Unknown help topic: `{}`.", _0)] + UnknownHelpTopic(String), + /// An unknown print-config option was requested. + #[fail(display = "Unknown print-config option: `{}`.", _0)] + UnknownPrintConfigTopic(String), + /// Attempt to generate a minimal config from standard input. + #[fail(display = "The `--print-config=minimal` option doesn't work with standard input.")] + MinimalPathWithStdin, + /// An io error during reading or writing. + #[fail(display = "io error: {}", _0)] + IoError(IoError), +} + +impl From for OperationError { + fn from(e: IoError) -> OperationError { + OperationError::IoError(e) + } } /// Arguments to `--help` @@ -156,7 +171,7 @@ fn is_nightly() -> bool { } // Returned i32 is an exit code -fn execute(opts: &Options) -> Result { +fn execute(opts: &Options) -> Result { let matches = opts.parse(env::args().skip(1))?; let options = GetOptsOptions::from_matches(&matches)?; @@ -210,7 +225,7 @@ fn execute(opts: &Options) -> Result { } } -fn format_string(input: String, options: GetOptsOptions) -> Result { +fn format_string(input: String, options: GetOptsOptions) -> Result { // try to read config from local directory let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; @@ -243,7 +258,7 @@ fn format( files: Vec, minimal_config_path: Option, options: &GetOptsOptions, -) -> Result { +) -> Result { options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(options.clone()))?; @@ -385,7 +400,7 @@ fn print_version() { println!("rustfmt {}", version_info); } -fn determine_operation(matches: &Matches) -> Result { +fn determine_operation(matches: &Matches) -> Result { if matches.opt_present("h") { let topic = matches.opt_str("h"); if topic == None { @@ -395,22 +410,25 @@ fn determine_operation(matches: &Matches) -> Result { } else if topic == Some("file-lines".to_owned()) { return Ok(Operation::Help(HelpOp::FileLines)); } else { - println!("Unknown help topic: `{}`\n", topic.unwrap()); - return Ok(Operation::Help(HelpOp::None)); + return Err(OperationError::UnknownHelpTopic(topic.unwrap())); } } + let mut free_matches = matches.free.iter(); let mut minimal_config_path = None; - if let Some(ref kind) = matches.opt_str("print-config") { - let path = matches.free.get(0).cloned(); - if kind == "default" { - return Ok(Operation::ConfigOutputDefault { path }); - } else if kind == "current" { - return Ok(Operation::ConfigOutputCurrent { path }); - } else if kind == "minimal" { - minimal_config_path = path; - if minimal_config_path.is_none() { - println!("WARNING: PATH required for `--print-config minimal`"); + if let Some(kind) = matches.opt_str("print-config") { + let path = free_matches.next().cloned(); + match kind.as_str() { + "default" => return Ok(Operation::ConfigOutputDefault { path }), + "current" => return Ok(Operation::ConfigOutputCurrent { path }), + "minimal" => { + minimal_config_path = path; + if minimal_config_path.is_none() { + eprintln!("WARNING: PATH required for `--print-config minimal`."); + } + } + _ => { + return Err(OperationError::UnknownPrintConfigTopic(kind)); } } } @@ -419,17 +437,7 @@ fn determine_operation(matches: &Matches) -> Result { return Ok(Operation::Version); } - // if no file argument is supplied, read from stdin - if matches.free.is_empty() { - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - - return Ok(Operation::Stdin { input: buffer }); - } - - let files: Vec<_> = matches - .free - .iter() + let files: Vec<_> = free_matches .map(|s| { let p = PathBuf::from(s); // we will do comparison later, so here tries to canonicalize first @@ -438,6 +446,17 @@ fn determine_operation(matches: &Matches) -> Result { }) .collect(); + // if no file argument is supplied, read from stdin + if files.is_empty() { + if minimal_config_path.is_some() { + return Err(OperationError::MinimalPathWithStdin); + } + let mut buffer = String::new(); + io::stdin().read_to_string(&mut buffer)?; + + return Ok(Operation::Stdin { input: buffer }); + } + Ok(Operation::Format { files, minimal_config_path, @@ -464,7 +483,7 @@ struct GetOptsOptions { } impl GetOptsOptions { - pub fn from_matches(matches: &Matches) -> Result { + pub fn from_matches(matches: &Matches) -> Result { let mut options = GetOptsOptions::default(); options.verbose = matches.opt_present("verbose"); options.quiet = matches.opt_present("quiet"); @@ -598,7 +617,7 @@ impl CliOptions for GetOptsOptions { } } -fn edition_from_edition_str(edition_str: &str) -> Result { +fn edition_from_edition_str(edition_str: &str) -> Result { match edition_str { "2015" => Ok(Edition::Edition2015), "2018" => Ok(Edition::Edition2018), @@ -606,7 +625,7 @@ fn edition_from_edition_str(edition_str: &str) -> Result Result { +fn emit_mode_from_emit_str(emit_str: &str) -> Result { match emit_str { "files" => Ok(EmitMode::Files), "stdout" => Ok(EmitMode::Stdout), diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs new file mode 100644 index 00000000000..51f311cd08d --- /dev/null +++ b/tests/rustfmt/main.rs @@ -0,0 +1,77 @@ +//! Integration tests for rustfmt. + +use std::env; +use std::fs::remove_file; +use std::path::Path; +use std::process::Command; + +/// Run the rustfmt executable and return its output. +fn rustfmt(args: &[&str]) -> (String, String) { + let mut bin_dir = env::current_exe().unwrap(); + bin_dir.pop(); // chop off test exe name + if bin_dir.ends_with("deps") { + bin_dir.pop(); + } + let cmd = bin_dir.join(format!("rustfmt{}", env::consts::EXE_SUFFIX)); + + // Ensure the rustfmt binary runs from the local target dir. + let path = env::var_os("PATH").unwrap_or_default(); + let mut paths = env::split_paths(&path).collect::>(); + paths.insert(0, bin_dir); + let new_path = env::join_paths(paths).unwrap(); + + match Command::new(&cmd).args(args).env("PATH", new_path).output() { + Ok(output) => ( + String::from_utf8(output.stdout).expect("utf-8"), + String::from_utf8(output.stderr).expect("utf-8"), + ), + Err(e) => panic!("failed to run `{:?} {:?}`: {}", cmd, args, e), + } +} + +macro_rules! assert_that { + ($args:expr, $check:ident $check_args:tt) => { + let (stdout, stderr) = rustfmt($args); + if !stdout.$check$check_args && !stderr.$check$check_args { + panic!( + "Output not expected for rustfmt {:?}\n\ + expected: {}{}\n\ + actual stdout:\n{}\n\ + actual stderr:\n{}", + $args, + stringify!($check), + stringify!($check_args), + stdout, + stderr + ); + } + }; +} + +#[test] +fn print_config() { + assert_that!( + &["--print-config", "unknown"], + starts_with("Unknown print-config option") + ); + assert_that!(&["--print-config", "default"], contains("max_width = 100")); + assert_that!(&["--print-config", "minimal"], contains("PATH required")); + assert_that!( + &["--print-config", "minimal", "minimal-config"], + contains("doesn't work with standard input.") + ); + + let (stdout, stderr) = rustfmt(&[ + "--print-config", + "minimal", + "minimal-config", + "src/shape.rs", + ]); + assert!( + Path::new("minimal-config").exists(), + "stdout:\n{}\nstderr:\n{}", + stdout, + stderr + ); + remove_file("minimal-config").unwrap(); +} -- cgit 1.4.1-3-g733a5 From 89940e541f921b5b22c12a24f6c84e32c691a9a4 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 15 Jul 2019 22:41:56 +0900 Subject: Fix bugs related to file-lines (#3684) --- src/bin/main.rs | 2 +- src/config/file_lines.rs | 13 +++- src/missed_spans.rs | 50 ++++++-------- src/source_map.rs | 3 +- src/utils.rs | 17 ++++- src/visitor.rs | 140 +++++++++++++++++++++++----------------- tests/source/file-lines-7.rs | 24 +++++++ tests/source/issue-3494/crlf.rs | 8 +++ tests/source/issue-3494/lf.rs | 8 +++ tests/source/issue-3636.rs | 4 +- tests/target/file-lines-7.rs | 21 ++++++ tests/target/issue-3494/crlf.rs | 8 +++ tests/target/issue-3494/lf.rs | 8 +++ tests/target/issue-3636.rs | 4 +- 14 files changed, 211 insertions(+), 99 deletions(-) create mode 100644 tests/source/file-lines-7.rs create mode 100644 tests/source/issue-3494/crlf.rs create mode 100644 tests/source/issue-3494/lf.rs create mode 100644 tests/target/file-lines-7.rs create mode 100644 tests/target/issue-3494/crlf.rs create mode 100644 tests/target/issue-3494/lf.rs (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 813504cdd6d..70990aa798d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -167,7 +167,7 @@ fn make_opts() -> Options { } fn is_nightly() -> bool { - option_env!("CFG_RELEASE_CHANNEL").map_or(false, |c| c == "nightly" || c == "dev") + option_env!("CFG_RELEASE_CHANNEL").map_or(true, |c| c == "nightly" || c == "dev") } // Returned i32 is an exit code diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index f0dc6c66597..f58d3c16ac2 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -9,7 +9,7 @@ use std::{cmp, fmt, iter, str}; use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; -use syntax::source_map::{self, SourceFile}; +use syntax::source_map::{self, SourceFile, SourceMap, Span}; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { @@ -78,6 +78,17 @@ impl LineRange { pub fn file_name(&self) -> FileName { self.file.name.clone().into() } + + pub(crate) fn from_span(source_map: &SourceMap, span: Span) -> LineRange { + let lo_char_pos = source_map.lookup_char_pos(span.lo()); + let hi_char_pos = source_map.lookup_char_pos(span.hi()); + debug_assert!(lo_char_pos.file.name == hi_char_pos.file.name); + LineRange { + file: lo_char_pos.file.clone(), + lo: lo_char_pos.line, + hi: hi_char_pos.line, + } + } } /// A range that is inclusive of both ends. diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 84246e3ed51..8ac05457ec9 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -7,7 +7,7 @@ use crate::config::file_lines::FileLines; use crate::config::{EmitMode, FileName}; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; -use crate::utils::{count_newlines, last_line_width, mk_sp}; +use crate::utils::{count_lf_crlf, count_newlines, last_line_width, mk_sp}; use crate::visitor::FmtVisitor; struct SnippetStatus { @@ -157,7 +157,7 @@ impl<'a> FmtVisitor<'a> { fn write_snippet_inner( &mut self, big_snippet: &str, - mut big_diff: usize, + big_diff: usize, old_snippet: &str, span: Span, process_last_snippet: F, @@ -176,36 +176,26 @@ impl<'a> FmtVisitor<'a> { _ => Cow::from(old_snippet), }; - // if the snippet starts with a new line, then information about the lines needs to be - // adjusted since it is off by 1. - let snippet = if snippet.starts_with('\n') { - // this takes into account the blank_lines_* options - self.push_vertical_spaces(1); - // include the newline character into the big_diff - big_diff += 1; - status.cur_line += 1; - &snippet[1..] - } else { - snippet - }; - - let slice_within_file_lines_range = |file_lines: FileLines, cur_line, s| -> (usize, bool) { - let newline_count = count_newlines(s); - let within_file_lines_range = file_lines.contains_range( - file_name, - cur_line, - // if a newline character is at the end of the slice, then the number of newlines - // needs to be decreased by 1 so that the range checked against the file_lines is - // the visual range one would expect. - cur_line + newline_count - if s.ends_with('\n') { 1 } else { 0 }, - ); - (newline_count, within_file_lines_range) - }; + let slice_within_file_lines_range = + |file_lines: FileLines, cur_line, s| -> (usize, usize, bool) { + let (lf_count, crlf_count) = count_lf_crlf(s); + let newline_count = lf_count + crlf_count; + let within_file_lines_range = file_lines.contains_range( + file_name, + cur_line, + // if a newline character is at the end of the slice, then the number of + // newlines needs to be decreased by 1 so that the range checked against + // the file_lines is the visual range one would expect. + cur_line + newline_count - if s.ends_with('\n') { 1 } else { 0 }, + ); + (lf_count, crlf_count, within_file_lines_range) + }; for (kind, offset, subslice) in CommentCodeSlices::new(snippet) { debug!("{:?}: {:?}", kind, subslice); - let (newline_count, within_file_lines_range) = + let (lf_count, crlf_count, within_file_lines_range) = slice_within_file_lines_range(self.config.file_lines(), status.cur_line, subslice); + let newline_count = lf_count + crlf_count; if CodeCharKind::Comment == kind && within_file_lines_range { // 1: comment. self.process_comment( @@ -219,7 +209,7 @@ impl<'a> FmtVisitor<'a> { // 2: blank lines. self.push_vertical_spaces(newline_count); status.cur_line += newline_count; - status.line_start = offset + newline_count; + status.line_start = offset + lf_count + crlf_count * 2; } else { // 3: code which we failed to format or which is not within file-lines range. self.process_missing_code(&mut status, snippet, subslice, offset, file_name); @@ -227,7 +217,7 @@ impl<'a> FmtVisitor<'a> { } let last_snippet = &snippet[status.line_start..]; - let (_, within_file_lines_range) = + let (_, _, within_file_lines_range) = slice_within_file_lines_range(self.config.file_lines(), status.cur_line, last_snippet); if within_file_lines_range { process_last_snippet(self, last_snippet, snippet); diff --git a/src/source_map.rs b/src/source_map.rs index 757d5f57db3..b1ab83e7aba 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -5,6 +5,7 @@ use syntax::source_map::{BytePos, SourceMap, Span}; use crate::comment::FindUncommented; use crate::config::file_lines::LineRange; +use crate::utils::starts_with_newline; use crate::visitor::SnippetProvider; pub(crate) trait SpanUtils { @@ -95,7 +96,7 @@ impl LineRangeUtils for SourceMap { // in case the span starts with a newline, the line range is off by 1 without the // adjustment below - let offset = 1 + if snippet.starts_with('\n') { 1 } else { 0 }; + let offset = 1 + if starts_with_newline(&snippet) { 1 } else { 0 }; // Line numbers start at 1 LineRange { file: lo.sf.clone(), diff --git a/src/utils.rs b/src/utils.rs index afa64e6c045..26ee7317df5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -306,7 +306,22 @@ pub(crate) fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { } } -#[inline] +/// Returns the number of LF and CRLF respectively. +pub(crate) fn count_lf_crlf(input: &str) -> (usize, usize) { + let mut lf = 0; + let mut crlf = 0; + let mut is_crlf = false; + for c in input.as_bytes() { + match c { + b'\r' => is_crlf = true, + b'\n' if is_crlf => crlf += 1, + b'\n' => lf += 1, + _ => is_crlf = false, + } + } + (lf, crlf) +} + pub(crate) fn count_newlines(input: &str) -> usize { // Using bytes to omit UTF-8 decoding bytecount::count(input.as_bytes(), b'\n') diff --git a/src/visitor.rs b/src/visitor.rs index 641ff1b62fd..d145693b9aa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -6,7 +6,7 @@ use syntax::{ast, visit}; use crate::attr::*; use crate::comment::{CodeCharKind, CommentCodeSlices}; -use crate::config::file_lines::FileName; +use crate::config::file_lines::LineRange; use crate::config::{BraceStyle, Config}; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, @@ -89,6 +89,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Shape::indented(self.block_indent, self.config) } + fn next_span(&self, hi: BytePos) -> Span { + mk_sp(self.last_pos, hi) + } + fn visit_stmt(&mut self, stmt: &Stmt<'_>) { debug!( "visit_stmt: {:?} {:?}", @@ -132,31 +136,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub(crate) fn visit_block( + /// Remove spaces between the opening brace and the first statement or the inner attribute + /// of the block. + fn trim_spaces_after_opening_brace( &mut self, b: &ast::Block, inner_attrs: Option<&[ast::Attribute]>, - has_braces: bool, ) { - debug!( - "visit_block: {:?} {:?}", - self.source_map.lookup_char_pos(b.span.lo()), - self.source_map.lookup_char_pos(b.span.hi()) - ); - - // Check if this block has braces. - let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); - - self.last_pos = self.last_pos + brace_compensation; - self.block_indent = self.block_indent.block_indent(self.config); - self.push_str("{"); - if let Some(first_stmt) = b.stmts.first() { let hi = inner_attrs .and_then(|attrs| inner_attributes(attrs).first().map(|attr| attr.span.lo())) .unwrap_or_else(|| first_stmt.span().lo()); - - let snippet = self.snippet(mk_sp(self.last_pos, hi)); + let missing_span = self.next_span(hi); + let snippet = self.snippet(missing_span); let len = CommentCodeSlices::new(snippet) .nth(0) .and_then(|(kind, _, s)| { @@ -170,19 +162,57 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = self.last_pos + BytePos::from_usize(len); } } + } - // Format inner attributes if available. - let skip_rewrite = if let Some(attrs) = inner_attrs { - self.visit_attrs(attrs, ast::AttrStyle::Inner) - } else { - false - }; + /// Returns the total length of the spaces which should be trimmed between the last statement + /// and the closing brace of the block. + fn trimmed_spaces_width_before_closing_brace( + &mut self, + b: &ast::Block, + brace_compensation: BytePos, + ) -> usize { + match b.stmts.last() { + None => 0, + Some(..) => { + let span_after_last_stmt = self.next_span(b.span.hi() - brace_compensation); + let missing_snippet = self.snippet(span_after_last_stmt); + CommentCodeSlices::new(missing_snippet) + .last() + .and_then(|(kind, _, s)| { + if kind == CodeCharKind::Normal && s.trim().is_empty() { + Some(s.len()) + } else { + None + } + }) + .unwrap_or(0) + } + } + } - if skip_rewrite { - self.push_rewrite(b.span, None); - self.close_block(false, b.span); - self.last_pos = source!(self, b.span).hi(); - return; + pub(crate) fn visit_block( + &mut self, + b: &ast::Block, + inner_attrs: Option<&[ast::Attribute]>, + has_braces: bool, + ) { + debug!( + "visit_block: {:?} {:?}", + self.source_map.lookup_char_pos(b.span.lo()), + self.source_map.lookup_char_pos(b.span.hi()) + ); + + // Check if this block has braces. + let brace_compensation = BytePos(if has_braces { 1 } else { 0 }); + + self.last_pos = self.last_pos + brace_compensation; + self.block_indent = self.block_indent.block_indent(self.config); + self.push_str("{"); + self.trim_spaces_after_opening_brace(b, inner_attrs); + + // Format inner attributes if available. + if let Some(attrs) = inner_attrs { + self.visit_attrs(attrs, ast::AttrStyle::Inner); } self.walk_block_stmts(b); @@ -195,36 +225,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - let mut remove_len = BytePos(0); - if let Some(stmt) = b.stmts.last() { - let span_after_last_stmt = mk_sp( - stmt.span.hi(), - source!(self, b.span).hi() - brace_compensation, - ); - // if the span is outside of a file_lines range, then do not try to remove anything - if !out_of_file_lines_range!(self, span_after_last_stmt) { - let snippet = self.snippet(span_after_last_stmt); - let len = CommentCodeSlices::new(snippet) - .last() - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal && s.trim().is_empty() { - Some(s.len()) - } else { - None - } - }); - if let Some(len) = len { - remove_len = BytePos::from_usize(len); - } - } + let missing_span = self.next_span(b.span.hi()); + if out_of_file_lines_range!(self, missing_span) { + self.push_str(self.snippet(missing_span)); + self.block_indent = self.block_indent.block_unindent(self.config); + self.last_pos = source!(self, b.span).hi(); + return; } + let remove_len = BytePos::from_usize( + self.trimmed_spaces_width_before_closing_brace(b, brace_compensation), + ); let unindent_comment = self.is_if_else_block && !b.stmts.is_empty() && { let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); snippet.contains("//") || snippet.contains("/*") }; - // FIXME: we should compress any newlines here to just one if unindent_comment { self.block_indent = self.block_indent.block_unindent(self.config); } @@ -234,7 +250,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if unindent_comment { self.block_indent = self.block_indent.block_indent(self.config); } - self.close_block(unindent_comment, b.span); + self.close_block(unindent_comment, self.next_span(b.span.hi())); self.last_pos = source!(self, b.span).hi(); } @@ -243,12 +259,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // The closing brace itself, however, should be indented at a shallower // level. fn close_block(&mut self, unindent_comment: bool, span: Span) { - let file_name: FileName = self.source_map.span_to_filename(span).into(); let skip_this_line = !self .config .file_lines() - .contains_line(&file_name, self.line_number); - if !skip_this_line { + .contains(&LineRange::from_span(self.source_map, span)); + if skip_this_line { + self.push_str(self.snippet(span)); + } else { let total_len = self.buffer.len(); let chars_too_many = if unindent_comment { 0 @@ -271,8 +288,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.buffer.push_str("\n"); } } + self.push_str("}"); } - self.push_str("}"); self.block_indent = self.block_indent.block_unindent(self.config); } @@ -800,8 +817,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.visit_attrs(attrs, ast::AttrStyle::Inner); self.walk_mod_items(m); - self.format_missing_with_indent(source!(self, m.inner).hi() - BytePos(1)); - self.close_block(false, m.inner); + let missing_span = mk_sp(source!(self, m.inner).hi() - BytePos(1), m.inner.hi()); + self.format_missing_with_indent(missing_span.lo()); + self.close_block(false, missing_span); } self.last_pos = source!(self, m.inner).hi(); } else { @@ -823,9 +841,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) { while let Some(pos) = self .snippet_provider - .opt_span_after(mk_sp(self.last_pos, end_pos), "\n") + .opt_span_after(self.next_span(end_pos), "\n") { - if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) { + if let Some(snippet) = self.opt_snippet(self.next_span(pos)) { if snippet.trim().is_empty() { self.last_pos = pos; } else { diff --git a/tests/source/file-lines-7.rs b/tests/source/file-lines-7.rs new file mode 100644 index 00000000000..b227ac35dcc --- /dev/null +++ b/tests/source/file-lines-7.rs @@ -0,0 +1,24 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-7.rs","range":[8,15]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + + + + // test + let i = 12; + // test + } + + fn baz() { + + + + /// + let j = 15; + } +} diff --git a/tests/source/issue-3494/crlf.rs b/tests/source/issue-3494/crlf.rs new file mode 100644 index 00000000000..9ce457c7b06 --- /dev/null +++ b/tests/source/issue-3494/crlf.rs @@ -0,0 +1,8 @@ +// rustfmt-file_lines: [{"file":"tests/source/issue-3494/crlf.rs","range":[4,5]}] + +pub fn main() +{ +let world1 = "world"; println!("Hello, {}!", world1); +let world2 = "world"; println!("Hello, {}!", world2); +let world3 = "world"; println!("Hello, {}!", world3); +} diff --git a/tests/source/issue-3494/lf.rs b/tests/source/issue-3494/lf.rs new file mode 100644 index 00000000000..bdbe69cef4a --- /dev/null +++ b/tests/source/issue-3494/lf.rs @@ -0,0 +1,8 @@ +// rustfmt-file_lines: [{"file":"tests/source/issue-3494/lf.rs","range":[4,5]}] + +pub fn main() +{ +let world1 = "world"; println!("Hello, {}!", world1); +let world2 = "world"; println!("Hello, {}!", world2); +let world3 = "world"; println!("Hello, {}!", world3); +} diff --git a/tests/source/issue-3636.rs b/tests/source/issue-3636.rs index 80355bbd2ef..edfa03012f2 100644 --- a/tests/source/issue-3636.rs +++ b/tests/source/issue-3636.rs @@ -1,4 +1,4 @@ -// rustfmt-file_lines: [{"file":"tests/source/issue-3636.rs","range":[4,7]}] +// rustfmt-file_lines: [{"file":"tests/source/issue-3636.rs","range":[4,7]},{"file":"tests/target/issue-3636.rs","range":[3,6]}] fn foo() { let x = @@ -7,4 +7,4 @@ fn foo() { 42; let z = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; let z = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; -} \ No newline at end of file +} diff --git a/tests/target/file-lines-7.rs b/tests/target/file-lines-7.rs new file mode 100644 index 00000000000..62d913d8823 --- /dev/null +++ b/tests/target/file-lines-7.rs @@ -0,0 +1,21 @@ +// rustfmt-file_lines: [{"file":"tests/source/file-lines-7.rs","range":[8,15]}] + +struct A { + t: i64, +} + +mod foo { + fn bar() { + // test + let i = 12; + // test + } + + fn baz() { + + + + /// + let j = 15; + } +} diff --git a/tests/target/issue-3494/crlf.rs b/tests/target/issue-3494/crlf.rs new file mode 100644 index 00000000000..cae615a0666 --- /dev/null +++ b/tests/target/issue-3494/crlf.rs @@ -0,0 +1,8 @@ +// rustfmt-file_lines: [{"file":"tests/source/issue-3494/crlf.rs","range":[4,5]}] + +pub fn main() { + let world1 = "world"; + println!("Hello, {}!", world1); +let world2 = "world"; println!("Hello, {}!", world2); +let world3 = "world"; println!("Hello, {}!", world3); +} diff --git a/tests/target/issue-3494/lf.rs b/tests/target/issue-3494/lf.rs new file mode 100644 index 00000000000..60aafe19a02 --- /dev/null +++ b/tests/target/issue-3494/lf.rs @@ -0,0 +1,8 @@ +// rustfmt-file_lines: [{"file":"tests/source/issue-3494/lf.rs","range":[4,5]}] + +pub fn main() { + let world1 = "world"; + println!("Hello, {}!", world1); +let world2 = "world"; println!("Hello, {}!", world2); +let world3 = "world"; println!("Hello, {}!", world3); +} diff --git a/tests/target/issue-3636.rs b/tests/target/issue-3636.rs index d8d78e88d0e..d467ed7389f 100644 --- a/tests/target/issue-3636.rs +++ b/tests/target/issue-3636.rs @@ -1,8 +1,8 @@ -// rustfmt-file_lines: [{"file":"tests/source/issue-3636.rs","range":[4,7]}] +// rustfmt-file_lines: [{"file":"tests/source/issue-3636.rs","range":[4,7]},{"file":"tests/target/issue-3636.rs","range":[3,6]}] fn foo() { let x = 42; let y = 42; let z = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - let z = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + let z = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; } -- cgit 1.4.1-3-g733a5 From 65931cd09d5be3039d907015234c3fd5325c289d Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 15 Jul 2019 22:47:10 +0900 Subject: Release 1.3.3 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 9568dbcfd56..03468ecf517 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,7 +838,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.3.2" +version = "1.3.3" dependencies = [ "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 56815a1e5b1..0d55fb283d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.3.2" +version = "1.3.3" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index 01ce1df8a9a..2f006538d48 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.3.2" +required_version = "1.3.3" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From 66c27c9161b2aa70c2902807be12952bd4a0a62b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 16 Jul 2019 19:36:23 +0900 Subject: Add #[ignore] to test that runs external process (#3690) --- .travis.yml | 1 + appveyor.yml | 1 + src/chains.rs | 16 ++++++++-------- src/config/license.rs | 2 +- src/macros.rs | 2 +- src/utils.rs | 4 ++-- tests/cargo-fmt/main.rs | 3 +++ tests/rustfmt/main.rs | 1 + tests/source/issue-3055/original.rs | 2 +- tests/target/issue-3055/original.rs | 2 +- 10 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/.travis.yml b/.travis.yml index abf565453de..966b7d7bac4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,6 +49,7 @@ script: if [ -z ${INTEGRATION} ]; then cargo build cargo test + cargo test -- --ignored else ./ci/integration.sh fi diff --git a/appveyor.yml b/appveyor.yml index 87c1773ce8e..1d3b06152a9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,3 +50,4 @@ build: false test_script: - cargo build --verbose - cargo test + - cargo test -- --ignored diff --git a/src/chains.rs b/src/chains.rs index 1ca0ac582b7..c7acf19ee0c 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -16,7 +16,7 @@ //! following values of `chain_indent`: //! Block: //! -//! ```ignore +//! ```text //! let foo = { //! aaaa; //! bbb; @@ -27,7 +27,7 @@ //! //! Visual: //! -//! ```ignore +//! ```text //! let foo = { //! aaaa; //! bbb; @@ -41,7 +41,7 @@ //! the braces. //! Block: //! -//! ```ignore +//! ```text //! let a = foo.bar //! .baz() //! .qux @@ -49,7 +49,7 @@ //! //! Visual: //! -//! ```ignore +//! ```text //! let a = foo.bar //! .baz() //! .qux @@ -454,7 +454,7 @@ trait ChainFormatter { // Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`. // Root is the parent plus any other chain items placed on the first line to // avoid an orphan. E.g., - // ```ignore + // ```text // foo.bar // .baz() // ``` @@ -516,7 +516,7 @@ impl<'a> ChainFormatterShared<'a> { // know whether 'overflowing' the last child make a better formatting: // // A chain with overflowing the last child: - // ```ignore + // ```text // parent.child1.child2.last_child( // a, // b, @@ -525,7 +525,7 @@ impl<'a> ChainFormatterShared<'a> { // ``` // // A chain without overflowing the last child (in vertical layout): - // ```ignore + // ```text // parent // .child1 // .child2 @@ -534,7 +534,7 @@ impl<'a> ChainFormatterShared<'a> { // // In particular, overflowing is effective when the last child is a method with a multi-lined // block-like argument (e.g., closure): - // ```ignore + // ```text // parent.child1.child2.last_child(|a, b, c| { // let x = foo(a, b, c); // let y = bar(a, b, c); diff --git a/src/config/license.rs b/src/config/license.rs index 2eb23bbcec7..121a1b1c151 100644 --- a/src/config/license.rs +++ b/src/config/license.rs @@ -82,7 +82,7 @@ impl TemplateParser { /// /// # Examples /// - /// ```ignore + /// ```text /// assert_eq!( /// TemplateParser::parse( /// r" diff --git a/src/macros.rs b/src/macros.rs index ac00e4452a7..c42010f77b2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1417,7 +1417,7 @@ impl MacroBranch { /// /// # Expected syntax /// -/// ```ignore +/// ```text /// lazy_static! { /// [pub] static ref NAME_1: TYPE_1 = EXPR_1; /// [pub] static ref NAME_2: TYPE_2 = EXPR_2; diff --git a/src/utils.rs b/src/utils.rs index 26ee7317df5..1a4941aa72e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -507,7 +507,7 @@ pub(crate) fn remove_trailing_white_spaces(text: &str) -> String { /// Indent each line according to the specified `indent`. /// e.g. /// -/// ```rust,ignore +/// ```rust,compile_fail /// foo!{ /// x, /// y, @@ -521,7 +521,7 @@ pub(crate) fn remove_trailing_white_spaces(text: &str) -> String { /// /// will become /// -/// ```rust,ignore +/// ```rust,compile_fail /// foo!{ /// x, /// y, diff --git a/tests/cargo-fmt/main.rs b/tests/cargo-fmt/main.rs index d1ba2e689b6..5493b09e4aa 100644 --- a/tests/cargo-fmt/main.rs +++ b/tests/cargo-fmt/main.rs @@ -46,6 +46,7 @@ macro_rules! assert_that { }; } +#[ignore] #[test] fn version() { assert_that!(&["--version"], starts_with("rustfmt ")); @@ -54,6 +55,7 @@ fn version() { assert_that!(&["--", "--version"], starts_with("rustfmt ")); } +#[ignore] #[test] fn print_config() { assert_that!( @@ -62,6 +64,7 @@ fn print_config() { ); } +#[ignore] #[test] fn rustfmt_help() { assert_that!(&["--", "--help"], contains("Format Rust code")); diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 51f311cd08d..18ef9b60963 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -48,6 +48,7 @@ macro_rules! assert_that { }; } +#[ignore] #[test] fn print_config() { assert_that!( diff --git a/tests/source/issue-3055/original.rs b/tests/source/issue-3055/original.rs index ad505547ac0..45e58473a4a 100644 --- a/tests/source/issue-3055/original.rs +++ b/tests/source/issue-3055/original.rs @@ -17,7 +17,7 @@ /// ``` /// /// Should not format with ignore attribute -/// ```ignore +/// ```text /// .--------------. /// | v /// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot diff --git a/tests/target/issue-3055/original.rs b/tests/target/issue-3055/original.rs index de27ccfb344..2df6adbb5e2 100644 --- a/tests/target/issue-3055/original.rs +++ b/tests/target/issue-3055/original.rs @@ -18,7 +18,7 @@ /// ``` /// /// Should not format with ignore attribute -/// ```ignore +/// ```text /// .--------------. /// | v /// Park <- Idle -> Poll -> Probe -> Download -> Install -> Reboot -- cgit 1.4.1-3-g733a5 From 76e2ba25bd419beedbbc15aec6b4c6aef4deffaf Mon Sep 17 00:00:00 2001 From: Michele d'Amico Date: Wed, 17 Jul 2019 02:40:33 +0200 Subject: #3665: Implemented (#3689) --- CHANGELOG.md | 5 ++ README.md | 8 ++- src/attr.rs | 6 ++- src/formatting.rs | 7 +-- src/lib.rs | 1 + src/macros.rs | 5 +- src/rewrite.rs | 3 +- src/skip.rs | 73 +++++++++++++++++++++++++++ src/test/mod.rs | 1 + src/utils.rs | 20 -------- src/visitor.rs | 33 ++++-------- tests/source/issue-3665/lib.rs | 33 ++++++++++++ tests/source/issue-3665/not_skip_attribute.rs | 4 ++ tests/source/issue-3665/sub_mod.rs | 14 +++++ tests/target/issue-3665/lib.rs | 31 ++++++++++++ tests/target/issue-3665/not_skip_attribute.rs | 4 ++ tests/target/issue-3665/sub_mod.rs | 13 +++++ 17 files changed, 207 insertions(+), 54 deletions(-) create mode 100644 src/skip.rs create mode 100644 tests/source/issue-3665/lib.rs create mode 100644 tests/source/issue-3665/not_skip_attribute.rs create mode 100644 tests/source/issue-3665/sub_mod.rs create mode 100644 tests/target/issue-3665/lib.rs create mode 100644 tests/target/issue-3665/not_skip_attribute.rs create mode 100644 tests/target/issue-3665/sub_mod.rs (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index b15c6948fbc..77c6ed463bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +### Added + +- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt +from formatting an attribute #3665 + ## [1.3.3] 2019-07-15 ### Added diff --git a/README.md b/README.md index 381dc73209e..292fcf644d2 100644 --- a/README.md +++ b/README.md @@ -179,12 +179,16 @@ needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`. ## Tips * For things you do not want rustfmt to mangle, use `#[rustfmt::skip]` -* To prevent rustfmt from formatting a macro, - use `#[rustfmt::skip::macros(target_macro_name)]` +* To prevent rustfmt from formatting a macro or an attribute, + use `#[rustfmt::skip::macros(target_macro_name)]` or + `#[rustfmt::skip::attributes(target_attribute_name)]` Example: ```rust + #![rustfmt::skip::attributes(custom_attribute)] + + #[custom_attribute(formatting , here , should , be , Skipped)] #[rustfmt::skip::macros(html)] fn main() { let macro_result1 = html! {

diff --git a/src/attr.rs b/src/attr.rs index 8497917ab06..1c9092ea629 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -319,9 +319,13 @@ impl Rewrite for ast::Attribute { if self.is_sugared_doc { rewrite_doc_comment(snippet, shape.comment(context.config), context.config) } else { + let should_skip = self + .ident() + .map(|s| context.skip_context.skip_attribute(&s.name.as_str())) + .unwrap_or(false); let prefix = attr_prefix(self); - if contains_comment(snippet) { + if should_skip || contains_comment(snippet) { return Some(snippet.to_owned()); } diff --git a/src/formatting.rs b/src/formatting.rs index 0faeb5102f2..879ddc61b13 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -17,7 +17,7 @@ use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::ignore_path::IgnorePathSet; use crate::issues::BadIssueSeeker; -use crate::utils::{count_newlines, get_skip_macro_names}; +use crate::utils::count_newlines; use crate::visitor::{FmtVisitor, SnippetProvider}; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; @@ -158,10 +158,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { &snippet_provider, self.report.clone(), ); - visitor - .skip_macro_names - .borrow_mut() - .append(&mut get_skip_macro_names(&self.krate.attrs)); + visitor.skip_context.update_with_attrs(&self.krate.attrs); // Format inner attributes if available. if !self.krate.attrs.is_empty() && is_root { diff --git a/src/lib.rs b/src/lib.rs index 1b4ce663313..a672e2cc8aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,6 +69,7 @@ mod reorder; mod rewrite; pub(crate) mod rustfmt_diff; mod shape; +mod skip; pub(crate) mod source_file; pub(crate) mod source_map; mod spanned; diff --git a/src/macros.rs b/src/macros.rs index c42010f77b2..0fbc7521ad7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -211,9 +211,8 @@ pub(crate) fn rewrite_macro( position: MacroPosition, ) -> Option { let should_skip = context - .skip_macro_names - .borrow() - .contains(&context.snippet(mac.node.path.span).to_owned()); + .skip_context + .skip_macro(&context.snippet(mac.node.path.span).to_owned()); if should_skip { None } else { diff --git a/src/rewrite.rs b/src/rewrite.rs index 9a955dbd91b..606aafc9ebd 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -8,6 +8,7 @@ use syntax::source_map::{SourceMap, Span}; use crate::config::{Config, IndentStyle}; use crate::shape::Shape; +use crate::skip::SkipContext; use crate::visitor::SnippetProvider; use crate::FormatReport; @@ -39,7 +40,7 @@ pub(crate) struct RewriteContext<'a> { // Used for `format_snippet` pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, - pub(crate) skip_macro_names: RefCell>, + pub(crate) skip_context: SkipContext, } impl<'a> RewriteContext<'a> { diff --git a/src/skip.rs b/src/skip.rs new file mode 100644 index 00000000000..6b4e04a7173 --- /dev/null +++ b/src/skip.rs @@ -0,0 +1,73 @@ +//! Module that contains skip related stuffs. + +use syntax::ast; + +/// Take care of skip name stack. You can update it by attributes slice or +/// by other context. Query this context to know if you need skip a block. +#[derive(Default, Clone)] +pub(crate) struct SkipContext { + macros: Vec, + attributes: Vec, +} + +impl SkipContext { + pub(crate) fn update_with_attrs(&mut self, attrs: &[ast::Attribute]) { + self.macros.append(&mut get_skip_names("macros", attrs)); + self.attributes + .append(&mut get_skip_names("attributes", attrs)); + } + + pub(crate) fn update(&mut self, mut other: SkipContext) { + self.macros.append(&mut other.macros); + self.attributes.append(&mut other.attributes); + } + + pub(crate) fn skip_macro(&self, name: &str) -> bool { + self.macros.iter().any(|n| n == name) + } + + pub(crate) fn skip_attribute(&self, name: &str) -> bool { + self.attributes.iter().any(|n| n == name) + } +} + +static RUSTFMT: &'static str = "rustfmt"; +static SKIP: &'static str = "skip"; + +/// Say if you're playing with `rustfmt`'s skip attribute +pub(crate) fn is_skip_attr(segments: &[ast::PathSegment]) -> bool { + if segments.len() < 2 || segments[0].ident.to_string() != RUSTFMT { + return false; + } + match segments.len() { + 2 => segments[1].ident.to_string() == SKIP, + 3 => { + segments[1].ident.to_string() == SKIP + && ["macros", "attributes"] + .iter() + .any(|&n| n == &segments[2].ident.name.as_str()) + } + _ => false, + } +} + +fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec { + let mut skip_names = vec![]; + let path = format!("{}::{}::{}", RUSTFMT, SKIP, kind); + for attr in attrs { + // syntax::ast::Path is implemented partialEq + // but it is designed for segments.len() == 1 + if format!("{}", attr.path) != path { + continue; + } + + if let Some(list) = attr.meta_item_list() { + for nested_meta_item in list { + if let Some(name) = nested_meta_item.ident() { + skip_names.push(name.to_string()); + } + } + } + } + skip_names +} diff --git a/src/test/mod.rs b/src/test/mod.rs index 10aad268a8d..a7063c76f28 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -26,6 +26,7 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ // so we do not want to test this file directly. "configs/skip_children/foo/mod.rs", "issue-3434/no_entry.rs", + "issue-3665/sub_mod.rs", // These files and directory are a part of modules defined inside `cfg_if!`. "cfg_if/mod.rs", "cfg_if/detect", diff --git a/src/utils.rs b/src/utils.rs index 1a4941aa72e..9adc9390111 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -638,26 +638,6 @@ pub(crate) fn unicode_str_width(s: &str) -> usize { s.width() } -pub(crate) fn get_skip_macro_names(attrs: &[ast::Attribute]) -> Vec { - let mut skip_macro_names = vec![]; - for attr in attrs { - // syntax::ast::Path is implemented partialEq - // but it is designed for segments.len() == 1 - if format!("{}", attr.path) != "rustfmt::skip::macros" { - continue; - } - - if let Some(list) = attr.meta_item_list() { - for nested_meta_item in list { - if let Some(name) = nested_meta_item.ident() { - skip_macro_names.push(name.to_string()); - } - } - } - } - skip_macro_names -} - #[cfg(test)] mod test { use super::*; diff --git a/src/visitor.rs b/src/visitor.rs index d145693b9aa..35291cecfb5 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -17,12 +17,13 @@ use crate::items::{ use crate::macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; +use crate::skip::{is_skip_attr, SkipContext}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; use crate::utils::{ - self, contains_skip, count_newlines, depr_skip_annotation, get_skip_macro_names, - inner_attributes, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, + self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, mk_sp, + ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -67,7 +68,7 @@ pub(crate) struct FmtVisitor<'a> { pub(crate) skipped_range: Vec<(usize, usize)>, pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, - pub(crate) skip_macro_names: RefCell>, + pub(crate) skip_context: SkipContext, } impl<'a> Drop for FmtVisitor<'a> { @@ -347,10 +348,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // the AST lumps them all together. let filtered_attrs; let mut attrs = &item.attrs; - let temp_skip_macro_names = self.skip_macro_names.clone(); - self.skip_macro_names - .borrow_mut() - .append(&mut get_skip_macro_names(&attrs)); + let skip_context_saved = self.skip_context.clone(); + self.skip_context.update_with_attrs(&attrs); let should_visit_node_again = match item.node { // For use/extern crate items, skip rewriting attributes but check for a skip attribute. @@ -501,7 +500,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } }; } - self.skip_macro_names = temp_skip_macro_names; + self.skip_context = skip_context_saved; } pub(crate) fn visit_trait_item(&mut self, ti: &ast::TraitItem) { @@ -656,10 +655,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ctx.snippet_provider, ctx.report.clone(), ); - visitor - .skip_macro_names - .borrow_mut() - .append(&mut ctx.skip_macro_names.borrow().clone()); + visitor.skip_context.update(ctx.skip_context.clone()); visitor.set_parent_context(ctx); visitor } @@ -684,7 +680,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { skipped_range: vec![], macro_rewrite_failure: false, report, - skip_macro_names: RefCell::new(vec![]), + skip_context: Default::default(), } } @@ -741,14 +737,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if segments[0].ident.to_string() != "rustfmt" { return false; } - - match segments.len() { - 2 => segments[1].ident.to_string() != "skip", - 3 => { - segments[1].ident.to_string() != "skip" || segments[2].ident.to_string() != "macros" - } - _ => false, - } + !is_skip_attr(segments) } fn walk_mod_items(&mut self, m: &ast::Mod) { @@ -881,7 +870,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider: self.snippet_provider, macro_rewrite_failure: RefCell::new(false), report: self.report.clone(), - skip_macro_names: self.skip_macro_names.clone(), + skip_context: self.skip_context.clone(), } } } diff --git a/tests/source/issue-3665/lib.rs b/tests/source/issue-3665/lib.rs new file mode 100644 index 00000000000..e049fbc5680 --- /dev/null +++ b/tests/source/issue-3665/lib.rs @@ -0,0 +1,33 @@ +#![rustfmt::skip::attributes(skip_mod_attr)] + +mod sub_mod; + +#[rustfmt::skip::attributes(other, skip_attr)] +fn main() { + #[other(should, +skip, + this, format)] + struct S {} + + #[skip_attr(should, skip, +this, format,too)] + fn doesnt_mater() {} + + #[skip_mod_attr(should, skip, +this, format, + enerywhere)] + fn more() {} + + #[not_skip(not, +skip, me)] + struct B {} +} + +#[other(should, not, skip, +this, format, here)] +fn foo() {} + +#[skip_mod_attr(should, skip, +this, format,in, master, + and, sub, module)] +fn bar() {} diff --git a/tests/source/issue-3665/not_skip_attribute.rs b/tests/source/issue-3665/not_skip_attribute.rs new file mode 100644 index 00000000000..14985259a50 --- /dev/null +++ b/tests/source/issue-3665/not_skip_attribute.rs @@ -0,0 +1,4 @@ +#![this::is::not::skip::attribute(ouch)] + +#[ouch(not, skip, me)] +fn main() {} diff --git a/tests/source/issue-3665/sub_mod.rs b/tests/source/issue-3665/sub_mod.rs new file mode 100644 index 00000000000..75fb24b4a65 --- /dev/null +++ b/tests/source/issue-3665/sub_mod.rs @@ -0,0 +1,14 @@ +#[rustfmt::skip::attributes(more_skip)] +#[more_skip(should, + skip, +this, format)] +fn foo() {} + +#[skip_mod_attr(should, skip, +this, format,in, master, + and, sub, module)] +fn bar() {} + +#[skip_attr(should, not, + skip, this, attribute, here)] +fn baz() {} diff --git a/tests/target/issue-3665/lib.rs b/tests/target/issue-3665/lib.rs new file mode 100644 index 00000000000..c313f320368 --- /dev/null +++ b/tests/target/issue-3665/lib.rs @@ -0,0 +1,31 @@ +#![rustfmt::skip::attributes(skip_mod_attr)] + +mod sub_mod; + +#[rustfmt::skip::attributes(other, skip_attr)] +fn main() { + #[other(should, +skip, + this, format)] + struct S {} + + #[skip_attr(should, skip, +this, format,too)] + fn doesnt_mater() {} + + #[skip_mod_attr(should, skip, +this, format, + enerywhere)] + fn more() {} + + #[not_skip(not, skip, me)] + struct B {} +} + +#[other(should, not, skip, this, format, here)] +fn foo() {} + +#[skip_mod_attr(should, skip, +this, format,in, master, + and, sub, module)] +fn bar() {} diff --git a/tests/target/issue-3665/not_skip_attribute.rs b/tests/target/issue-3665/not_skip_attribute.rs new file mode 100644 index 00000000000..a4e8b948736 --- /dev/null +++ b/tests/target/issue-3665/not_skip_attribute.rs @@ -0,0 +1,4 @@ +#![this::is::not::skip::attribute(ouch)] + +#[ouch(not, skip, me)] +fn main() {} diff --git a/tests/target/issue-3665/sub_mod.rs b/tests/target/issue-3665/sub_mod.rs new file mode 100644 index 00000000000..30a2b0fd9d9 --- /dev/null +++ b/tests/target/issue-3665/sub_mod.rs @@ -0,0 +1,13 @@ +#[rustfmt::skip::attributes(more_skip)] +#[more_skip(should, + skip, +this, format)] +fn foo() {} + +#[skip_mod_attr(should, skip, +this, format,in, master, + and, sub, module)] +fn bar() {} + +#[skip_attr(should, not, skip, this, attribute, here)] +fn baz() {} -- cgit 1.4.1-3-g733a5 From c0e616bc1d19eb9b08a5db2f265b8332569e7259 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 17 Jul 2019 23:07:12 +0900 Subject: Implement closing-block procedure without relying on missed_span module (#3691) --- src/config/file_lines.rs | 13 +- src/coverage.rs | 15 ++ src/format-diff/main.rs | 1 - src/lib.rs | 1 + src/missed_spans.rs | 17 +- src/visitor.rs | 178 ++++++++++----------- .../source/configs/empty_item_single_line/false.rs | 1 - .../source/configs/empty_item_single_line/true.rs | 1 - tests/source/issue-977.rs | 1 - tests/target/assignment.rs | 2 +- tests/target/comment.rs | 3 +- tests/target/comments-fn.rs | 1 - .../target/configs/empty_item_single_line/false.rs | 1 - tests/target/fn.rs | 2 - tests/target/issue-977.rs | 4 +- tests/target/match.rs | 6 +- tests/target/mod-1.rs | 3 +- 17 files changed, 115 insertions(+), 135 deletions(-) create mode 100644 src/coverage.rs (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index f58d3c16ac2..f0dc6c66597 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -9,7 +9,7 @@ use std::{cmp, fmt, iter, str}; use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; -use syntax::source_map::{self, SourceFile, SourceMap, Span}; +use syntax::source_map::{self, SourceFile}; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { @@ -78,17 +78,6 @@ impl LineRange { pub fn file_name(&self) -> FileName { self.file.name.clone().into() } - - pub(crate) fn from_span(source_map: &SourceMap, span: Span) -> LineRange { - let lo_char_pos = source_map.lookup_char_pos(span.lo()); - let hi_char_pos = source_map.lookup_char_pos(span.hi()); - debug_assert!(lo_char_pos.file.name == hi_char_pos.file.name); - LineRange { - file: lo_char_pos.file.clone(), - lo: lo_char_pos.line, - hi: hi_char_pos.line, - } - } } /// A range that is inclusive of both ends. diff --git a/src/coverage.rs b/src/coverage.rs new file mode 100644 index 00000000000..f5a04974251 --- /dev/null +++ b/src/coverage.rs @@ -0,0 +1,15 @@ +use crate::{Config, EmitMode}; +use std::borrow::Cow; + +pub(crate) fn transform_missing_snippet<'a>(config: &Config, string: &'a str) -> Cow<'a, str> { + match config.emit_mode() { + EmitMode::Coverage => Cow::from(replace_chars(string)), + _ => Cow::from(string), + } +} + +fn replace_chars(s: &str) -> String { + s.chars() + .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) + .collect() +} diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 80815b5f1d9..5bfdcbd0420 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -292,5 +292,4 @@ mod cmd_line_tests { .is_err() ); } - } diff --git a/src/lib.rs b/src/lib.rs index a672e2cc8aa..e3e7f7f9244 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,7 @@ mod chains; mod closures; mod comment; pub(crate) mod config; +mod coverage; mod emitter; mod expr; mod format_report_formatter; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 8ac05457ec9..7bc81fdc844 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -1,10 +1,9 @@ -use std::borrow::Cow; - use syntax::source_map::{BytePos, Pos, Span}; use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileLines; -use crate::config::{EmitMode, FileName}; +use crate::config::FileName; +use crate::coverage::transform_missing_snippet; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; use crate::utils::{count_lf_crlf, count_newlines, last_line_width, mk_sp}; @@ -171,10 +170,7 @@ impl<'a> FmtVisitor<'a> { let file_name = &char_pos.file.name.clone().into(); let mut status = SnippetStatus::new(char_pos.line); - let snippet = &*match self.config.emit_mode() { - EmitMode::Coverage => Cow::from(replace_chars(old_snippet)), - _ => Cow::from(old_snippet), - }; + let snippet = &*transform_missing_snippet(self.config, old_snippet); let slice_within_file_lines_range = |file_lines: FileLines, cur_line, s| -> (usize, usize, bool) { @@ -333,10 +329,3 @@ impl<'a> FmtVisitor<'a> { } } } - -fn replace_chars(string: &str) -> String { - string - .chars() - .map(|ch| if ch.is_whitespace() { ch } else { 'X' }) - .collect() -} diff --git a/src/visitor.rs b/src/visitor.rs index 35291cecfb5..5526ed9e44d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -5,9 +5,9 @@ use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; use syntax::{ast, visit}; use crate::attr::*; -use crate::comment::{CodeCharKind, CommentCodeSlices}; -use crate::config::file_lines::LineRange; +use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::{BraceStyle, Config}; +use crate::coverage::transform_missing_snippet; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, @@ -22,8 +22,8 @@ use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; use crate::utils::{ - self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, mk_sp, - ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, + self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, last_line_width, + mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -165,32 +165,6 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - /// Returns the total length of the spaces which should be trimmed between the last statement - /// and the closing brace of the block. - fn trimmed_spaces_width_before_closing_brace( - &mut self, - b: &ast::Block, - brace_compensation: BytePos, - ) -> usize { - match b.stmts.last() { - None => 0, - Some(..) => { - let span_after_last_stmt = self.next_span(b.span.hi() - brace_compensation); - let missing_snippet = self.snippet(span_after_last_stmt); - CommentCodeSlices::new(missing_snippet) - .last() - .and_then(|(kind, _, s)| { - if kind == CodeCharKind::Normal && s.trim().is_empty() { - Some(s.len()) - } else { - None - } - }) - .unwrap_or(0) - } - } - } - pub(crate) fn visit_block( &mut self, b: &ast::Block, @@ -226,72 +200,99 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - let missing_span = self.next_span(b.span.hi()); - if out_of_file_lines_range!(self, missing_span) { - self.push_str(self.snippet(missing_span)); - self.block_indent = self.block_indent.block_unindent(self.config); - self.last_pos = source!(self, b.span).hi(); - return; - } - - let remove_len = BytePos::from_usize( - self.trimmed_spaces_width_before_closing_brace(b, brace_compensation), - ); - let unindent_comment = self.is_if_else_block && !b.stmts.is_empty() && { - let end_pos = source!(self, b.span).hi() - brace_compensation - remove_len; - let snippet = self.snippet(mk_sp(self.last_pos, end_pos)); - snippet.contains("//") || snippet.contains("/*") - }; - if unindent_comment { + let rest_span = self.next_span(b.span.hi()); + if out_of_file_lines_range!(self, rest_span) { + self.push_str(self.snippet(rest_span)); self.block_indent = self.block_indent.block_unindent(self.config); + } else { + // Ignore the closing brace. + let missing_span = self.next_span(b.span.hi() - brace_compensation); + self.close_block(missing_span, self.unindent_comment_on_closing_brace(b)); } - self.format_missing_with_indent( - source!(self, b.span).hi() - brace_compensation - remove_len, - ); - if unindent_comment { - self.block_indent = self.block_indent.block_indent(self.config); - } - self.close_block(unindent_comment, self.next_span(b.span.hi())); self.last_pos = source!(self, b.span).hi(); } - // FIXME: this is a terrible hack to indent the comments between the last - // item in the block and the closing brace to the block's level. - // The closing brace itself, however, should be indented at a shallower - // level. - fn close_block(&mut self, unindent_comment: bool, span: Span) { - let skip_this_line = !self - .config - .file_lines() - .contains(&LineRange::from_span(self.source_map, span)); - if skip_this_line { - self.push_str(self.snippet(span)); - } else { - let total_len = self.buffer.len(); - let chars_too_many = if unindent_comment { - 0 - } else if self.config.hard_tabs() { - 1 - } else { - self.config.tab_spaces() - }; + fn close_block(&mut self, span: Span, unindent_comment: bool) { + let config = self.config; - // FIXME this is a temporaly fix - // should be remove truncate logic in close_block - // avoid not to truncate necessary chars - let truncate_start = total_len - chars_too_many; - let target_str = &self.buffer[truncate_start..total_len]; - let truncate_length = target_str.len() - target_str.trim().len(); - - if let Some(last_char) = target_str.chars().last() { - self.buffer.truncate(total_len - truncate_length); - if last_char == '\n' { - self.buffer.push_str("\n"); + let mut last_hi = span.lo(); + let mut unindented = false; + let mut prev_ends_with_newline = false; + let mut extra_newline = false; + + let skip_normal = |s: &str| { + let trimmed = s.trim(); + trimmed.is_empty() || trimmed.chars().all(|c| c == ';') + }; + + for (kind, offset, sub_slice) in CommentCodeSlices::new(self.snippet(span)) { + let sub_slice = transform_missing_snippet(config, sub_slice); + + debug!("close_block: {:?} {:?} {:?}", kind, offset, sub_slice); + + match kind { + CodeCharKind::Comment => { + if !unindented && unindent_comment { + unindented = true; + self.block_indent = self.block_indent.block_unindent(config); + } + let span_in_between = mk_sp(last_hi, span.lo() + BytePos::from_usize(offset)); + let snippet_in_between = self.snippet(span_in_between); + let mut comment_on_same_line = !snippet_in_between.contains("\n"); + + let mut comment_shape = + Shape::indented(self.block_indent, config).comment(config); + if comment_on_same_line { + // 1 = a space before `//` + let offset_len = 1 + last_line_width(&self.buffer) + .saturating_sub(self.block_indent.width()); + match comment_shape + .visual_indent(offset_len) + .sub_width(offset_len) + { + Some(shp) => comment_shape = shp, + None => comment_on_same_line = false, + } + }; + + if comment_on_same_line { + self.push_str(" "); + } else { + if count_newlines(snippet_in_between) >= 2 || extra_newline { + self.push_str("\n"); + } + self.push_str(&self.block_indent.to_string_with_newline(config)); + } + + let comment_str = rewrite_comment(&sub_slice, false, comment_shape, config); + match comment_str { + Some(ref s) => self.push_str(s), + None => self.push_str(&sub_slice), + } + } + CodeCharKind::Normal if skip_normal(&sub_slice) => { + extra_newline = prev_ends_with_newline && sub_slice.contains('\n'); + continue; + } + CodeCharKind::Normal => { + self.push_str(&self.block_indent.to_string_with_newline(config)); + self.push_str(sub_slice.trim()); } } - self.push_str("}"); + prev_ends_with_newline = sub_slice.ends_with('\n'); + extra_newline = false; + last_hi = span.lo() + BytePos::from_usize(offset + sub_slice.len()); + } + if unindented { + self.block_indent = self.block_indent.block_indent(self.config); } self.block_indent = self.block_indent.block_unindent(self.config); + self.push_str(&self.block_indent.to_string_with_newline(config)); + self.push_str("}"); + } + + fn unindent_comment_on_closing_brace(&self, b: &ast::Block) -> bool { + self.is_if_else_block && !b.stmts.is_empty() } // Note that this only gets called for function definitions. Required methods @@ -806,9 +807,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); self.visit_attrs(attrs, ast::AttrStyle::Inner); self.walk_mod_items(m); - let missing_span = mk_sp(source!(self, m.inner).hi() - BytePos(1), m.inner.hi()); - self.format_missing_with_indent(missing_span.lo()); - self.close_block(false, missing_span); + let missing_span = self.next_span(m.inner.hi() - BytePos(1)); + self.close_block(missing_span, false); } self.last_pos = source!(self, m.inner).hi(); } else { diff --git a/tests/source/configs/empty_item_single_line/false.rs b/tests/source/configs/empty_item_single_line/false.rs index 8fa74f28802..9bfb2b964ea 100644 --- a/tests/source/configs/empty_item_single_line/false.rs +++ b/tests/source/configs/empty_item_single_line/false.rs @@ -13,5 +13,4 @@ fn lorem() { } fn lorem() { - } diff --git a/tests/source/configs/empty_item_single_line/true.rs b/tests/source/configs/empty_item_single_line/true.rs index 02e703d1904..8af8b88ffff 100644 --- a/tests/source/configs/empty_item_single_line/true.rs +++ b/tests/source/configs/empty_item_single_line/true.rs @@ -13,5 +13,4 @@ fn lorem() { } fn lorem() { - } diff --git a/tests/source/issue-977.rs b/tests/source/issue-977.rs index b028b36a055..fe16387b7b2 100644 --- a/tests/source/issue-977.rs +++ b/tests/source/issue-977.rs @@ -1,5 +1,4 @@ // rustfmt-normalize_comments: true -// FIXME(#919) trait NameC { /* comment */ } struct FooC { /* comment */ } diff --git a/tests/target/assignment.rs b/tests/target/assignment.rs index a33f3cb40ab..1a70d84813d 100644 --- a/tests/target/assignment.rs +++ b/tests/target/assignment.rs @@ -17,7 +17,7 @@ fn main() { single_lit_fit >>= 10; // #2791 - let x = 2;;;; + let x = 2; } fn break_meee() { diff --git a/tests/target/comment.rs b/tests/target/comment.rs index 4cccdab0e8b..b987c8a44f3 100644 --- a/tests/target/comment.rs +++ b/tests/target/comment.rs @@ -59,8 +59,7 @@ fn issue_1086() { // random comment -fn main() { - // Test +fn main() { // Test } // #1643 diff --git a/tests/target/comments-fn.rs b/tests/target/comments-fn.rs index 5a17f03089c..1f43bd93bb0 100644 --- a/tests/target/comments-fn.rs +++ b/tests/target/comments-fn.rs @@ -15,7 +15,6 @@ where F: Foo, // COmment after where-clause G: Goo, // final comment { - } fn bar() {} diff --git a/tests/target/configs/empty_item_single_line/false.rs b/tests/target/configs/empty_item_single_line/false.rs index b7886df2aa8..174fe330a8d 100644 --- a/tests/target/configs/empty_item_single_line/false.rs +++ b/tests/target/configs/empty_item_single_line/false.rs @@ -11,5 +11,4 @@ fn lorem() { } fn lorem() { - } diff --git a/tests/target/fn.rs b/tests/target/fn.rs index 66a6e9082de..0ad775ee1dd 100644 --- a/tests/target/fn.rs +++ b/tests/target/fn.rs @@ -21,7 +21,6 @@ fn foo( where T: Blah, { - } fn foo( @@ -32,7 +31,6 @@ where T: Blah, U: dsfasdfasdfasd, { - } fn foo B /* paren inside generics */>() {} diff --git a/tests/target/issue-977.rs b/tests/target/issue-977.rs index c4bc82d85d4..3784a387450 100644 --- a/tests/target/issue-977.rs +++ b/tests/target/issue-977.rs @@ -1,5 +1,4 @@ // rustfmt-normalize_comments: true -// FIXME(#919) trait NameC { // comment @@ -10,8 +9,7 @@ struct FooC { enum MooC { // comment } -mod BarC { - // comment +mod BarC { // comment } extern "C" { // comment diff --git a/tests/target/match.rs b/tests/target/match.rs index f45574ee46c..78bcd2aa053 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -126,8 +126,7 @@ fn issue339() { // collapsing here exceeds line length ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffg => { } - h => { - // comment above block + h => { // comment above block } i => {} // comment below block j => { @@ -148,8 +147,7 @@ fn issue339() { m => {} n => {} o => {} - p => { - // Don't collapse me + p => { // Don't collapse me } q => {} r => {} diff --git a/tests/target/mod-1.rs b/tests/target/mod-1.rs index a5d186c5df7..4118d123dd0 100644 --- a/tests/target/mod-1.rs +++ b/tests/target/mod-1.rs @@ -33,6 +33,5 @@ pub mod x { } } -mod y { - // sup boooooiiii +mod y { // sup boooooiiii } -- cgit 1.4.1-3-g733a5 From b0043297820488e50fae9c7c594052d49598431f Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 21 Jul 2019 13:26:41 +0900 Subject: Simplify code around visit_fn (#3698) --- src/items.rs | 95 +++++++++++++++++++++++++--------------------------------- src/visitor.rs | 28 ++++++++++------- 2 files changed, 58 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1b7ac780129..73b752dfe78 100644 --- a/src/items.rs +++ b/src/items.rs @@ -299,47 +299,28 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.hi(); } - pub(crate) fn rewrite_fn( + pub(crate) fn rewrite_fn_before_block( &mut self, indent: Indent, ident: ast::Ident, fn_sig: &FnSig<'_>, span: Span, - block: &ast::Block, - inner_attrs: Option<&[ast::Attribute]>, - ) -> Option { + ) -> Option<(String, FnBraceStyle)> { let context = self.get_context(); - let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause); - - let (mut result, force_newline_brace) = - rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?; + let mut fn_brace_style = newline_for_brace(self.config, &fn_sig.generics.where_clause); + let (result, force_newline_brace) = + rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style)?; // 2 = ` {` if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace || last_line_width(&result) + 2 > self.shape().width { - newline_brace = true; - } else if !result.contains('\n') { - newline_brace = false; + fn_brace_style = FnBraceStyle::NextLine } - if let rw @ Some(..) = self.single_line_fn(&result, block, inner_attrs) { - rw - } else { - // Prepare for the function body by possibly adding a newline and - // indent. - // FIXME we'll miss anything between the end of the signature and the - // start of the body, but we need more spans from the compiler to solve - // this. - if newline_brace { - result.push_str(&indent.to_string_with_newline(self.config)); - } else { - result.push(' '); - } - Some(result) - } + Some((result, fn_brace_style)) } pub(crate) fn rewrite_required_fn( @@ -360,8 +341,7 @@ impl<'a> FmtVisitor<'a> { ident, &FnSig::from_method_sig(sig, generics), span, - false, - false, + FnBraceStyle::None, )?; // Re-attach semicolon @@ -370,7 +350,7 @@ impl<'a> FmtVisitor<'a> { Some(result) } - fn single_line_fn( + pub(crate) fn single_line_fn( &self, fn_str: &str, block: &ast::Block, @@ -1980,6 +1960,13 @@ pub(crate) fn is_named_arg(arg: &ast::Arg) -> bool { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum FnBraceStyle { + SameLine, + NextLine, + None, +} + // Return type is (result, force_new_line_for_brace) fn rewrite_fn_base( context: &RewriteContext<'_>, @@ -1987,8 +1974,7 @@ fn rewrite_fn_base( ident: ast::Ident, fn_sig: &FnSig<'_>, span: Span, - newline_brace: bool, - has_body: bool, + fn_brace_style: FnBraceStyle, ) -> Option<(String, bool)> { let mut force_new_line_for_brace = false; @@ -2001,7 +1987,7 @@ fn rewrite_fn_base( result.push_str("fn "); // Generics. - let overhead = if has_body && !newline_brace { + let overhead = if let FnBraceStyle::SameLine = fn_brace_style { // 4 = `() {` 4 } else { @@ -2044,8 +2030,7 @@ fn rewrite_fn_base( &result, indent, ret_str_len, - newline_brace, - has_body, + fn_brace_style, multi_line_ret_str, )?; @@ -2237,7 +2222,7 @@ fn rewrite_fn_base( } else { WhereClauseSpace::Newline }; - let mut option = WhereClauseOption::new(!has_body, space); + let mut option = WhereClauseOption::new(fn_brace_style == FnBraceStyle::None, space); if is_args_multi_lined { option.veto_single_line(); } @@ -2412,30 +2397,25 @@ fn compute_budgets_for_args( result: &str, indent: Indent, ret_str_len: usize, - newline_brace: bool, - has_braces: bool, + fn_brace_style: FnBraceStyle, force_vertical_layout: bool, ) -> Option<((usize, usize, Indent))> { debug!( - "compute_budgets_for_args {} {:?}, {}, {}", + "compute_budgets_for_args {} {:?}, {}, {:?}", result.len(), indent, ret_str_len, - newline_brace + fn_brace_style, ); // Try keeping everything on the same line. if !result.contains('\n') && !force_vertical_layout { // 2 = `()`, 3 = `() `, space is before ret_string. let overhead = if ret_str_len == 0 { 2 } else { 3 }; let mut used_space = indent.width() + result.len() + ret_str_len + overhead; - if has_braces { - if !newline_brace { - // 2 = `{}` - used_space += 2; - } - } else { - // 1 = `;` - used_space += 1; + match fn_brace_style { + FnBraceStyle::None => used_space += 1, // 1 = `;` + FnBraceStyle::SameLine => used_space += 2, // 2 = `{}` + FnBraceStyle::NextLine => (), } let one_line_budget = context.budget(used_space); @@ -2448,7 +2428,10 @@ fn compute_budgets_for_args( } IndentStyle::Visual => { let indent = indent + result.len() + 1; - let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 }; + let multi_line_overhead = match fn_brace_style { + FnBraceStyle::SameLine => 4, + _ => 2, + } + indent.width(); (indent, context.budget(multi_line_overhead)) } }; @@ -2468,16 +2451,21 @@ fn compute_budgets_for_args( Some((0, context.budget(used_space), new_indent)) } -fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool { +fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> FnBraceStyle { let predicate_count = where_clause.predicates.len(); if config.where_single_line() && predicate_count == 1 { - return false; + return FnBraceStyle::SameLine; } let brace_style = config.brace_style(); - brace_style == BraceStyle::AlwaysNextLine - || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0) + let use_next_line = brace_style == BraceStyle::AlwaysNextLine + || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0); + if use_next_line { + FnBraceStyle::NextLine + } else { + FnBraceStyle::SameLine + } } fn rewrite_generics( @@ -2919,8 +2907,7 @@ impl Rewrite for ast::ForeignItem { self.ident, &FnSig::new(fn_decl, generics, self.vis.clone()), span, - false, - false, + FnBraceStyle::None, ) .map(|(s, _)| format!("{};", s)), ast::ForeignItemKind::Static(ref ty, mutability) => { diff --git a/src/visitor.rs b/src/visitor.rs index 5526ed9e44d..58a94b12dfd 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,8 +11,8 @@ use crate::coverage::transform_missing_snippet; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, - rewrite_existential_type, rewrite_extern_crate, rewrite_type_alias, FnSig, StaticParts, - StructParts, + rewrite_existential_type, rewrite_extern_crate, rewrite_type_alias, FnBraceStyle, FnSig, + StaticParts, StructParts, }; use crate::macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::rewrite::{Rewrite, RewriteContext}; @@ -311,32 +311,38 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite = match fk { visit::FnKind::ItemFn(ident, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { block = b; - self.rewrite_fn( + self.rewrite_fn_before_block( indent, ident, &FnSig::from_fn_kind(&fk, generics, fd, defaultness), mk_sp(s.lo(), b.span.lo()), - b, - inner_attrs, ) } visit::FnKind::Closure(_) => unreachable!(), }; - if let Some(fn_str) = rewrite { + if let Some((fn_str, fn_brace_style)) = rewrite { self.format_missing_with_indent(source!(self, s).lo()); + + if let Some(rw) = self.single_line_fn(&fn_str, block, inner_attrs) { + self.push_str(&rw); + self.last_pos = s.hi(); + return; + } + self.push_str(&fn_str); - if let Some(c) = fn_str.chars().last() { - if c == '}' { - self.last_pos = source!(self, block.span).hi(); - return; + match fn_brace_style { + FnBraceStyle::SameLine => self.push_str(" "), + FnBraceStyle::NextLine => { + self.push_str(&self.block_indent.to_string_with_newline(self.config)) } + _ => unreachable!(), } + self.last_pos = source!(self, block.span).lo(); } else { self.format_missing(source!(self, block.span).lo()); } - self.last_pos = source!(self, block.span).lo(); self.visit_block(block, inner_attrs, true) } -- cgit 1.4.1-3-g733a5 From 983a92c8727d8e6f8cdfa31d7ccf3dcd98dee850 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 29 Jul 2019 05:52:45 +0900 Subject: Update rustc-ap-* crates to 541.0.0 (#3707) --- Cargo.lock | 561 ++++++++++++++++++++++------------------- Cargo.toml | 10 +- src/closures.rs | 8 +- src/expr.rs | 60 ++--- src/format_report_formatter.rs | 2 +- src/macros.rs | 10 +- src/matches.rs | 16 +- src/overflow.rs | 2 - src/utils.rs | 13 +- tests/source/macros.rs | 3 - tests/target/issue-3439.rs | 6 - tests/target/macros.rs | 3 - 12 files changed, 335 insertions(+), 359 deletions(-) delete mode 100644 tests/target/issue-3439.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 03468ecf517..22ea29576c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,15 @@ # It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "annotate-snippets" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -35,7 +35,7 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -43,38 +43,36 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.30" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -87,16 +85,16 @@ name = "blake2-rfc" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bstr" -version = "0.1.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -109,24 +107,33 @@ dependencies = [ [[package]] name = "byteorder" -version = "1.3.1" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "c2-chacha" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cargo_metadata" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -140,7 +147,7 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -163,11 +170,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam-channel" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -184,7 +190,7 @@ name = "crossbeam-epoch" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -203,7 +209,7 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -212,12 +218,12 @@ dependencies = [ [[package]] name = "derive-new" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -225,16 +231,6 @@ name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "dirs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dirs" version = "2.0.1" @@ -250,7 +246,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -265,18 +261,18 @@ name = "ena" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -285,7 +281,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -295,8 +291,8 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -318,16 +314,25 @@ dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "getrandom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "globset" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -348,18 +353,18 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -383,22 +388,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "libc" -version = "0.2.58" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -412,7 +420,7 @@ dependencies = [ [[package]] name = "log" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -420,7 +428,7 @@ dependencies = [ [[package]] name = "memchr" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -435,17 +443,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.4.0" @@ -476,13 +479,18 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ppv-lite86" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -498,7 +506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -509,8 +517,8 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -522,15 +530,36 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -544,6 +573,14 @@ name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -552,6 +589,14 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -565,7 +610,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -577,7 +622,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -588,7 +633,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -610,17 +655,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.54" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "redox_users" version = "0.3.0" @@ -629,153 +666,147 @@ dependencies = [ "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.6" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.6" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-arena" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "491.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-ap-rustc_cratesio_shim" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "rustc-ap-rustc_data_structures" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_lexer" +version = "541.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-ap-rustc_macros" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "491.0.0" +version = "541.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -790,7 +821,7 @@ name = "rustc-hash" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -810,8 +841,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -832,38 +863,38 @@ name = "rustfmt-config_proc_macro" version = "0.1.2" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustfmt-nightly" version = "1.3.3" dependencies = [ - "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.1.2", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -872,12 +903,12 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -904,7 +935,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -914,35 +945,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.92" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.92" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "smallvec" -version = "0.6.9" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "spin" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -971,17 +1007,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.35" +version = "0.15.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -991,18 +1027,18 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1014,17 +1050,6 @@ dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "termion" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -1046,12 +1071,12 @@ name = "toml" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ucd-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1076,7 +1101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "utf8-ranges" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1086,10 +1111,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.7" +version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1131,131 +1156,135 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8bcdcd5b291ce85a78f2b9d082a8de9676c12b1840d386d67bc5eea6f9d2b4e" +"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" +"checksum annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" +"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum bstr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "59604ece62a407dc9164732e5adea02467898954c3a5811fd2dc140af14ef15b" +"checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" "checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum cargo_metadata 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "929766d993a2fde7a0ae962ee82429069cd7b68839cd9375b98efd719df65d3a" -"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cargo_metadata 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e904f164f39cae0c3a4f2713eb97a47ba64676a071e99a69ddfef4994694d2c" +"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum derive-new 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd04571b29c91cfbe1e7c9a228e069ac8635f180ffb4ccd6a6907617ee8bb0" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" "checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" -"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" +"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" -"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454" +"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" +"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002" +"checksum ignore 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c794c4736d7751238cc5f74f6a3a2a59698074672fe403620d53fecfd72e5d87" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b3d51e24009d966c8285d524dbaf6d60926636b2a89caee9ce0bd612494ddc16" +"checksum jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" +"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum rustc-ap-arena 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc0ad4318f3425229ed7b117275368b83269bec75f9609d4965dcb9752483c86" -"checksum rustc-ap-graphviz 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b80b7ea7902919f397c4bb12d102abe896fced7893d09d84bcac233e555bb388" -"checksum rustc-ap-rustc_cratesio_shim 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "752463d2b80039d23e42e667a9f6fe08213bd865f6ea301fb35f8068d94955ac" -"checksum rustc-ap-rustc_data_structures 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3d6a14181e11c132d0ef97a6c27e1bb1d4da09682d02222393875c10d1c364" -"checksum rustc-ap-rustc_errors 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55caea8426565de362e8df0df737e43b9f22d632e0e52710cbfe316acc6ce2f0" -"checksum rustc-ap-rustc_macros 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "071420d762d2c779d1d4972356f37f5d049dcdd6c49e78f1b037e04c5a0f1a19" -"checksum rustc-ap-rustc_target 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5464696d0748e3019b9e5daca5fcadc53889dc2bca1dc26bf42001fd1c4194f" -"checksum rustc-ap-serialize 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9464445c11c15cf32ef27815b3ec89315b0ed73c6c771cbcf8543be59a3c1502" -"checksum rustc-ap-syntax 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff53245ae370d8e8073dc9cc13f8921e6110d0ccd208b64c388c5653fa6b9c83" -"checksum rustc-ap-syntax_pos 491.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41896f0eb2eb2f4ddba406939aa6b07386160fa38bee8cde3f7f0d85663e3d47" +"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" +"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" +"checksum rustc-ap-arena 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4999a492d178380404acf4db84a5f963308abc6517c9d7e1c365b8a3f71b9c76" +"checksum rustc-ap-graphviz 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0487de365719ea61197aba6ff7d8ddbcbc7f405efabe45779531006eea8af2" +"checksum rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73123645a853dfe21d834e68a9794b7102dd8f853de1f4fb3afb6ab157a391f3" +"checksum rustc-ap-rustc_errors 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0054a08e965f4139a5b506b5c2ffeba0c8675e2644f6de8598b46430adbc31b5" +"checksum rustc-ap-rustc_lexer 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee482133f8d62afa26c5fc1bb0e5058fe20f2d8f4fd62e0b19b8573b79d46da" +"checksum rustc-ap-rustc_macros 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19a6a47f58ec7b082c706fa45d000bb32b68f69be4144d321346c5fcdf553e78" +"checksum rustc-ap-rustc_target 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6906ce7105780a97c9b3b0a8ca8d5fca098fa9ad63ff8d76db4196977991ed8" +"checksum rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ae328d35a0fe825d87e3a9d758aa7be6351da0da95a900b67bc725a2ff353f4" +"checksum rustc-ap-syntax 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8386699c409cc149144e2e97eb4afa6bc2443d8c32a2fb6815d31642c6b5ee97" +"checksum rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b0155cbc5e3cf2291da98d2dd7a0614595e3363cfde39c719c17c50a1a06668" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" "checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" "checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" -"checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" -"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" -"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72" +"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f" +"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" "checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" -"checksum syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)" = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" +"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" +"checksum term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd90505d5006a4422d3520b30c781d480b3f36768c2fa2187c3e950bc110464" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" -"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" diff --git a/Cargo.toml b/Cargo.toml index 0d55fb283d7..a7dbc62d74e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,23 +41,23 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" unicode-segmentation = "1.0.0" regex = "1.0" -term = "0.5" +term = "0.6" diff = "0.1" log = "0.4" env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -rustc-ap-rustc_target = "491.0.0" -rustc-ap-syntax = "491.0.0" -rustc-ap-syntax_pos = "491.0.0" +rustc-ap-rustc_target = "541.0.0" +rustc-ap-syntax = "541.0.0" +rustc-ap-syntax_pos = "541.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "2.0.1" ignore = "0.4.6" -annotate-snippets = { version = "0.5.0", features = ["ansi_term"] } +annotate-snippets = { version = "0.6", features = ["ansi_term"] } structopt = "0.2.18" rustfmt-config_proc_macro = { version = "0.1", path = "config_proc_macro" } diff --git a/src/closures.rs b/src/closures.rs index 72d010f12b3..c0ecc91db52 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -372,11 +372,7 @@ fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bo fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { match expr.node { - ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::ForLoop(..) => true, + ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true, ast::ExprKind::Loop(..) if version == Version::Two => true, ast::ExprKind::AddrOf(_, ref expr) | ast::ExprKind::Box(ref expr) @@ -398,11 +394,9 @@ fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { match e.node { ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) | ast::ExprKind::Match(..) | ast::ExprKind::Block(..) | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::TryBlock(..) => false, diff --git a/src/expr.rs b/src/expr.rs index d7640bf98ca..8c877fe3cea 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -110,12 +110,11 @@ pub(crate) fn format_expr( ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) } + ast::ExprKind::Let(..) => None, ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type) + | ast::ExprKind::While(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), ast::ExprKind::Block(ref block, opt_label) => { match expr_type { @@ -610,21 +609,21 @@ struct ControlFlow<'a> { span: Span, } +fn extract_pats_and_cond(expr: &ast::Expr) -> (Vec<&ast::Pat>, &ast::Expr) { + match expr.node { + ast::ExprKind::Let(ref pats, ref cond) => (ptr_vec_to_ref_vec(pats), cond), + _ => (vec![], expr), + } +} + +// FIXME: Refactor this. fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option> { match expr.node { - ast::ExprKind::If(ref cond, ref if_block, ref else_block) => Some(ControlFlow::new_if( - cond, - vec![], - if_block, - else_block.as_ref().map(|e| &**e), - expr_type == ExprType::SubExpression, - false, - expr.span, - )), - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => { + ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { + let (pats, cond) = extract_pats_and_cond(cond); Some(ControlFlow::new_if( cond, - ptr_vec_to_ref_vec(pat), + pats, if_block, else_block.as_ref().map(|e| &**e), expr_type == ExprType::SubExpression, @@ -638,16 +637,10 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { Some(ControlFlow::new_loop(block, label, expr.span)) } - ast::ExprKind::While(ref cond, ref block, label) => Some(ControlFlow::new_while( - vec![], - cond, - block, - label, - expr.span, - )), - ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => Some( - ControlFlow::new_while(ptr_vec_to_ref_vec(pat), cond, block, label, expr.span), - ), + ast::ExprKind::While(ref cond, ref block, label) => { + let (pats, cond) = extract_pats_and_cond(cond); + Some(ControlFlow::new_while(pats, cond, block, label, expr.span)) + } _ => None, } } @@ -1020,22 +1013,11 @@ impl<'a> Rewrite for ControlFlow<'a> { // from being formatted on a single line. // Note how we're passing the original shape, as the // cost of "else" should not cascade. - ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => { - ControlFlow::new_if( - cond, - ptr_vec_to_ref_vec(pat), - if_block, - next_else_block.as_ref().map(|e| &**e), - false, - true, - mk_sp(else_block.span.lo(), self.span.hi()), - ) - .rewrite(context, shape) - } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { + let (pats, cond) = extract_pats_and_cond(cond); ControlFlow::new_if( cond, - vec![], + pats, if_block, next_else_block.as_ref().map(|e| &**e), false, @@ -1332,11 +1314,9 @@ pub(crate) fn can_be_overflowed_expr( || context.config.overflow_delimited_expr() } ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Loop(..) - | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) => { + | ast::ExprKind::While(..) => { context.config.combine_control_expr() && context.use_block_indent() && args_len == 1 } diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs index 550380cdd2b..5f5d89faf39 100644 --- a/src/format_report_formatter.rs +++ b/src/format_report_formatter.rs @@ -48,7 +48,7 @@ pub struct FormatReportFormatter<'a> { impl<'a> Display for FormatReportFormatter<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let formatter = DisplayListFormatter::new(self.enable_colors); + let formatter = DisplayListFormatter::new(self.enable_colors, false); let errors_by_file = &self.report.internal.borrow().0; for (file, errors) in errors_by_file { diff --git a/src/macros.rs b/src/macros.rs index 0fbc7521ad7..b2146437f15 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -916,7 +916,7 @@ impl MacroArgParser { break; } TokenTree::Token(ref t) => { - buffer.push_str(&pprust::token_to_string(&t.kind)); + buffer.push_str(&pprust::token_to_string(&t)); hi = t.span.hi(); } _ => return None, @@ -945,13 +945,13 @@ impl MacroArgParser { self.lo = t.span.lo(); self.start_tok = t.clone(); } else { - let needs_space = match next_space(&self.last_tok) { + let needs_space = match next_space(&self.last_tok.kind) { SpaceState::Ident => ident_like(t), SpaceState::Punctuation => !ident_like(t), SpaceState::Always => true, SpaceState::Never => false, }; - if force_space_before(t) || needs_space { + if force_space_before(&t.kind) || needs_space { self.buf.push(' '); } } @@ -974,7 +974,7 @@ impl MacroArgParser { } } - if force_space_before(&self.start_tok) { + if force_space_before(&self.start_tok.kind) { return true; } @@ -1013,7 +1013,7 @@ impl MacroArgParser { TokenTree::Token(ref t) => self.update_buffer(t), TokenTree::Delimited(delimited_span, delimited, ref tts) => { if !self.buf.is_empty() { - if next_space(&self.last_tok) == SpaceState::Always { + if next_space(&self.last_tok.kind) == SpaceState::Always { self.add_separator(); } else { self.add_other(); diff --git a/src/matches.rs b/src/matches.rs index 2f542c3e1aa..b7a1c374323 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -488,18 +488,10 @@ fn rewrite_match_body( } } -impl Rewrite for ast::Guard { - fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - match self { - ast::Guard::If(ref expr) => expr.rewrite(context, shape), - } - } -} - // The `if ...` guard on a match arm. fn rewrite_guard( context: &RewriteContext<'_>, - guard: &Option, + guard: &Option>, shape: Shape, // The amount of space used up on this line for the pattern in // the arm (excludes offset). @@ -561,12 +553,10 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { match body.node { // We do not allow `if` to stay on the same line, since we could easily mistake // `pat => if cond { ... }` and `pat if cond => { ... }`. - ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false, + ast::ExprKind::If(..) => false, // We do not allow collapsing a block around expression with condition // to avoid it being cluttered with match arm. - ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) | ast::ExprKind::WhileLet(..) => { - false - } + ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) => false, ast::ExprKind::Loop(..) | ast::ExprKind::Match(..) | ast::ExprKind::Block(..) diff --git a/src/overflow.rs b/src/overflow.rs index 1731c3cf08e..d8e1d0e2590 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -414,11 +414,9 @@ impl<'a> Context<'a> { // When overflowing the expressions which consists of a control flow // expression, avoid condition to use multi line. ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) | ast::ExprKind::Match(..) => { let multi_line = rewrite_cond(self.context, expr, shape) .map_or(false, |cond| cond.contains('\n')); diff --git a/src/utils.rs b/src/utils.rs index 9adc9390111..498608d4179 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,7 +10,7 @@ use syntax::ast::{ use syntax::ptr; use syntax::source_map::{BytePos, Span, NO_EXPANSION}; use syntax::symbol::{sym, Symbol}; -use syntax_pos::Mark; +use syntax_pos::ExpnId; use unicode_width::UnicodeWidthStr; use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; @@ -284,10 +284,9 @@ pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) pub(crate) fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> bool { match stmt.node { ast::StmtKind::Semi(ref expr) => match expr.node { - ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) - | ast::ExprKind::Loop(..) - | ast::ExprKind::ForLoop(..) => false, + ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) => { + false + } ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => { context.config.trailing_semicolon() } @@ -453,9 +452,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Array(..) | ast::ExprKind::Struct(..) | ast::ExprKind::While(..) - | ast::ExprKind::WhileLet(..) | ast::ExprKind::If(..) - | ast::ExprKind::IfLet(..) | ast::ExprKind::Block(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) @@ -630,7 +627,7 @@ pub(crate) trait NodeIdExt { impl NodeIdExt for NodeId { fn root() -> NodeId { - NodeId::placeholder_from_mark(Mark::root()) + NodeId::placeholder_from_expn_id(ExpnId::root()) } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index ef5b1efa5b9..e5013634234 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -6,8 +6,6 @@ itemmacro!(really, long.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa itemmacro!{this, is.brace().formatted()} -peg_file! modname ("mygrammarfile.rustpeg"); - fn main() { foo! ( ); @@ -474,7 +472,6 @@ pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { // #3463 x ! {()} -x ! y {()} // #3583 foo!(|x = y|); diff --git a/tests/target/issue-3439.rs b/tests/target/issue-3439.rs deleted file mode 100644 index 835fae243ce..00000000000 --- a/tests/target/issue-3439.rs +++ /dev/null @@ -1,6 +0,0 @@ -use repro::my_macro; - -#[my_macro] -xyz! abc { - let a = 1; -} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index f19b5d11fee..a2406787461 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -11,8 +11,6 @@ itemmacro!( itemmacro! {this, is.brace().formatted()} -peg_file! modname("mygrammarfile.rustpeg"); - fn main() { foo!(); @@ -1051,7 +1049,6 @@ pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { // #3463 x! {()} -x! y {()} // #3583 foo!(|x = y|); -- cgit 1.4.1-3-g733a5 From 365461349d83e5b39bd3dcc704356f0822de0f65 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 29 Jul 2019 05:56:39 +0900 Subject: Release 1.4.0 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 22ea29576c4..d40380dbd68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -869,7 +869,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.3.3" +version = "1.4.0" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a7dbc62d74e..5ca4f765690 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.3.3" +version = "1.4.0" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index 2f006538d48..ffe76caf0f2 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.3.3" +required_version = "1.4.0" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From fe05e8883150ede9cd8efcff47374b5894d74eb7 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Tue, 30 Jul 2019 14:32:38 +0900 Subject: fix to build with rustc 1.38.0-nightly (4560cb830 2019-07-28) (#3712) --- Cargo.lock | 86 ++++++++++++++++---------------- Cargo.toml | 6 +-- src/patterns.rs | 121 +++++++++++++++------------------------------ tests/source/pattern.rs | 18 +++++-- tests/target/issue-1021.rs | 2 +- tests/target/issue-2936.rs | 2 +- tests/target/issue-3711.rs | 6 +++ tests/target/pattern.rs | 16 ++++-- 8 files changed, 120 insertions(+), 137 deletions(-) create mode 100644 tests/target/issue-3711.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d40380dbd68..dfaef1a7faa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,21 +691,21 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_data_structures" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -716,8 +716,8 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -727,27 +727,27 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_macros" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,19 +759,19 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -780,33 +780,33 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "541.0.0" +version = "542.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -886,9 +886,9 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.1.2", "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1238,16 +1238,16 @@ dependencies = [ "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" "checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" -"checksum rustc-ap-arena 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4999a492d178380404acf4db84a5f963308abc6517c9d7e1c365b8a3f71b9c76" -"checksum rustc-ap-graphviz 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0487de365719ea61197aba6ff7d8ddbcbc7f405efabe45779531006eea8af2" -"checksum rustc-ap-rustc_data_structures 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73123645a853dfe21d834e68a9794b7102dd8f853de1f4fb3afb6ab157a391f3" -"checksum rustc-ap-rustc_errors 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0054a08e965f4139a5b506b5c2ffeba0c8675e2644f6de8598b46430adbc31b5" -"checksum rustc-ap-rustc_lexer 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee482133f8d62afa26c5fc1bb0e5058fe20f2d8f4fd62e0b19b8573b79d46da" -"checksum rustc-ap-rustc_macros 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19a6a47f58ec7b082c706fa45d000bb32b68f69be4144d321346c5fcdf553e78" -"checksum rustc-ap-rustc_target 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6906ce7105780a97c9b3b0a8ca8d5fca098fa9ad63ff8d76db4196977991ed8" -"checksum rustc-ap-serialize 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ae328d35a0fe825d87e3a9d758aa7be6351da0da95a900b67bc725a2ff353f4" -"checksum rustc-ap-syntax 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8386699c409cc149144e2e97eb4afa6bc2443d8c32a2fb6815d31642c6b5ee97" -"checksum rustc-ap-syntax_pos 541.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b0155cbc5e3cf2291da98d2dd7a0614595e3363cfde39c719c17c50a1a06668" +"checksum rustc-ap-arena 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae3caf12a5dfa3181e12e813b090b0b41d43b91b193759ba9084520aeb2459" +"checksum rustc-ap-graphviz 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0113b8888a3f0a68825ed0dea6d3a1aa71b5d0cd6ff16854252c4faea253cf9b" +"checksum rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd9eec8c9fbdac20e631f995861c5c854b3f8b2347955614854571457117e51" +"checksum rustc-ap-rustc_errors 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f55baa0fa4a42a8b354f02015755e7db5619125ad3e625923865f6f1f5688753" +"checksum rustc-ap-rustc_lexer 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2875181a7886d83b727b1d08291ee430728c2d94c9a7e3f4359df2a14e6c462b" +"checksum rustc-ap-rustc_macros 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3cadcc9dd4fc3c94c89e103e91f8792f19a1466e0a127d9fb29a2c0ee069389" +"checksum rustc-ap-rustc_target 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bdcce1900404a6907785dd31a152ddd723766dfbe29bed6bcca255e7347abdd" +"checksum rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "550e295fa077784f7145ba77591aff952fad2279f3ce23a53cf8750fb366c622" +"checksum rustc-ap-syntax 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "594006d7e68bcff9b5356517667c4e9dd5ec925a2a08660d129b705d0b741ad7" +"checksum rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae6751bf44d949b430b151c81772b585686f0ff31e328b68eaa7d406590f848" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" diff --git a/Cargo.toml b/Cargo.toml index 5ca4f765690..2754fcf838e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -rustc-ap-rustc_target = "541.0.0" -rustc-ap-syntax = "541.0.0" -rustc-ap-syntax_pos = "541.0.0" +rustc-ap-rustc_target = "542.0.0" +rustc-ap-syntax = "542.0.0" +rustc-ap-syntax_pos = "542.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/patterns.rs b/src/patterns.rs index c26451f6d69..e7b7f8adbb2 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -37,15 +37,15 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { fn is_short_pattern_inner(pat: &ast::Pat) -> bool { match pat.node { - ast::PatKind::Wild | ast::PatKind::Lit(_) => true, + ast::PatKind::Rest | ast::PatKind::Wild | ast::PatKind::Lit(_) => true, ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) | ast::PatKind::Mac(..) | ast::PatKind::Slice(..) | ast::PatKind::Path(..) | ast::PatKind::Range(..) => false, - ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1, - ast::PatKind::TupleStruct(ref path, ref subpats, _) => { + ast::PatKind::Tuple(ref subpats) => subpats.len() <= 1, + ast::PatKind::TupleStruct(ref path, ref subpats) => { path.segments.len() <= 1 && subpats.len() <= 1 } ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => { @@ -88,6 +88,13 @@ impl Rewrite for Pat { None } } + PatKind::Rest => { + if 1 <= shape.width { + Some("..".to_owned()) + } else { + None + } + } PatKind::Range(ref lhs, ref rhs, ref end_kind) => { let infix = match end_kind.node { RangeEnd::Included(RangeSyntax::DotDotDot) => "...", @@ -112,42 +119,27 @@ impl Rewrite for Pat { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, shape) } - PatKind::Tuple(ref items, dotdot_pos) => { - rewrite_tuple_pat(items, dotdot_pos, None, self.span, context, shape) - } + PatKind::Tuple(ref items) => rewrite_tuple_pat(items, None, self.span, context, shape), PatKind::Path(ref q_self, ref path) => { rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape) } - PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => { + PatKind::TupleStruct(ref path, ref pat_vec) => { let path_str = rewrite_path(context, PathContext::Expr, None, path, shape)?; - rewrite_tuple_pat( - pat_vec, - dotdot_pos, - Some(path_str), - self.span, - context, - shape, - ) + rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape) } PatKind::Lit(ref expr) => expr.rewrite(context, shape), - PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => { - // Rewrite all the sub-patterns. - let prefix = prefix.iter().map(|p| p.rewrite(context, shape)); - let slice_pat = slice_pat - .as_ref() - .and_then(|p| p.rewrite(context, shape)) - .map(|rw| Some(format!("{}..", if rw == "_" { "" } else { &rw }))); - let suffix = suffix.iter().map(|p| p.rewrite(context, shape)); - - // Munge them together. - let pats: Option> = - prefix.chain(slice_pat.into_iter()).chain(suffix).collect(); - - // Check that all the rewrites succeeded, and if not return `None`. - let pats = pats?; - - // Unwrap all the sub-strings and join them with commas. - Some(format!("[{}]", pats.join(", "))) + PatKind::Slice(ref slice_pat) => { + let rw: Vec = slice_pat + .iter() + .map(|p| { + if let Some(rw) = p.rewrite(context, shape) { + format!("{}", if rw == "_" { "" } else { &rw }) + } else { + format!("{}", context.snippet(p.span)) + } + }) + .collect(); + Some(format!("[{}]", rw.join(", "))) } PatKind::Struct(ref path, ref fields, ellipsis) => { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) @@ -303,7 +295,6 @@ pub(crate) fn can_be_overflowed_pat( fn rewrite_tuple_pat( pats: &[ptr::P], - dotdot_pos: Option, path_str: Option, span: Span, context: &RewriteContext<'_>, @@ -311,52 +302,26 @@ fn rewrite_tuple_pat( ) -> Option { let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect(); - if let Some(pos) = dotdot_pos { - let prev = if pos == 0 { - span.lo() - } else { - pats[pos - 1].span().hi() - }; - let next = if pos + 1 >= pats.len() { - span.hi() - } else { - pats[pos + 1].span().lo() - }; - let dot_span = mk_sp(prev, next); - let snippet = context.snippet(dot_span); - let lo = dot_span.lo() + BytePos(snippet.find_uncommented("..").unwrap() as u32); - let dotdot = TuplePatField::Dotdot(Span::new( - lo, - // 2 == "..".len() - lo + BytePos(2), - source_map::NO_EXPANSION, - )); - pat_vec.insert(pos, dotdot); - } if pat_vec.is_empty() { return Some(format!("{}()", path_str.unwrap_or_default())); } let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape); - let (pat_vec, span, condensed) = - if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 { - let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; - let sp = pat_vec[new_item_count - 1].span(); - let snippet = context.snippet(sp); - let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); - ( - &pat_vec[..new_item_count], - mk_sp(span.lo(), lo + BytePos(1)), - true, - ) - } else { - (&pat_vec[..], span, false) - }; + let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2 + { + let new_item_count = 1 + pat_vec.len() - wildcard_suffix_len; + let sp = pat_vec[new_item_count - 1].span(); + let snippet = context.snippet(sp); + let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + ( + &pat_vec[..new_item_count], + mk_sp(span.lo(), lo + BytePos(1)), + ) + } else { + (&pat_vec[..], span) + }; - // add comma if `(x,)` - let add_comma = path_str.is_none() && pat_vec.len() == 1 && dotdot_pos.is_none() && !condensed; let path_str = path_str.unwrap_or_default(); - overflow::rewrite_with_parens( &context, &path_str, @@ -364,13 +329,7 @@ fn rewrite_tuple_pat( shape, span, context.config.max_width(), - if dotdot_pos.is_some() { - Some(SeparatorTactic::Never) - } else if add_comma { - Some(SeparatorTactic::Always) - } else { - None - }, + None, ) } diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index 184d23c8137..fc3b1455e0d 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -1,4 +1,7 @@ // rustfmt-normalize_comments: true +#![feature(exclusive_range_pattern)] +use core::u8::MAX; + fn main() { let z = match x { "pat1" => 1, @@ -16,9 +19,9 @@ fn main() { let foo@bar (f) = 42; let a::foo ( ..) = 42; let [ ] = 42; - let [a.., b,c ] = 42; - let [ a,b,c.. ] = 42; - let [a, b, c, d..,e,f, g] = 42; + let [a, b,c ] = 42; + let [ a,b,c ] = 42; + let [a, b, c, d,e,f, g] = 42; let foo { } = 42; let foo {..} = 42; let foo { x, y: ref foo, .. } = 42; @@ -26,6 +29,13 @@ fn main() { let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, } = 42; let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, .. }; let foo { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; + + match b"12" { + [0, + 1..MAX + ] => {} + _ => {} + } } impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> { @@ -67,7 +77,7 @@ fn combine_patterns() { fn slice_patterns() { match b"123" { [0, ..] => {} - [0, foo..] => {} + [0, foo] => {} _ => {} } } diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs index ba1029d4e61..94911d1f8ee 100644 --- a/tests/target/issue-1021.rs +++ b/tests/target/issue-1021.rs @@ -15,7 +15,7 @@ fn main() { (true, ..) => (), (.., true) => (), (..) => (), - (_,) => (), + (_) => (), (/* .. */ ..) => (), (/* .. */ .., true) => (), } diff --git a/tests/target/issue-2936.rs b/tests/target/issue-2936.rs index 876050a20f4..3d5207597c4 100644 --- a/tests/target/issue-2936.rs +++ b/tests/target/issue-2936.rs @@ -10,7 +10,7 @@ impl Something for AStruct { ContextualParseError::InvalidMediaRule(ref err) => { let err: &CStr = match err.kind { ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureName( - .. + .., )) => cstr!("PEMQExpectedFeatureName"), }; } diff --git a/tests/target/issue-3711.rs b/tests/target/issue-3711.rs new file mode 100644 index 00000000000..62d986e7734 --- /dev/null +++ b/tests/target/issue-3711.rs @@ -0,0 +1,6 @@ +fn main() { + println!( + "{}", // comment + 111 + ); +} diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index 79c8bbb90bf..d8a96d64920 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -1,4 +1,7 @@ // rustfmt-normalize_comments: true +#![feature(exclusive_range_pattern)] +use core::u8::MAX; + fn main() { let z = match x { "pat1" => 1, @@ -18,9 +21,9 @@ fn main() { let foo @ bar(f) = 42; let a::foo(..) = 42; let [] = 42; - let [a.., b, c] = 42; - let [a, b, c..] = 42; - let [a, b, c, d.., e, f, g] = 42; + let [a, b, c] = 42; + let [a, b, c] = 42; + let [a, b, c, d, e, f, g] = 42; let foo {} = 42; let foo { .. } = 42; let foo { x, y: ref foo, .. } = 42; @@ -42,6 +45,11 @@ fn main() { x, yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: ref foo, }; + + match b"12" { + [0, 1..MAX] => {} + _ => {} + } } impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { @@ -79,7 +87,7 @@ fn combine_patterns() { fn slice_patterns() { match b"123" { [0, ..] => {} - [0, foo..] => {} + [0, foo] => {} _ => {} } } -- cgit 1.4.1-3-g733a5 From 9e960e7d6a0c6b7c46c195acbd6f92ade6eec3ba Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 30 Jul 2019 14:39:07 +0900 Subject: Release v1.4.1 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index dfaef1a7faa..9add36978cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -869,7 +869,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.0" +version = "1.4.1" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 2754fcf838e..6eda8d05c54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.0" +version = "1.4.1" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index ffe76caf0f2..b53036d28c8 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.4.0" +required_version = "1.4.1" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From aeb3496f31a0dfa90fc511520d2023634e885260 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 31 Jul 2019 11:10:49 +0900 Subject: Release v1.4.2 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 9add36978cf..11698d94f77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -869,7 +869,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.1" +version = "1.4.2" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 3e3ef6672ed..f359379cf2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.1" +version = "1.4.2" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index b53036d28c8..fb3a10a7c21 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.4.1" +required_version = "1.4.2" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From 3b7a518144ef04c21db1e20a103e896021cc4c2d Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Wed, 31 Jul 2019 23:55:58 +0900 Subject: fix underscore in slice patterns are removed (#3719) --- src/patterns.rs | 2 +- tests/target/issue-3718.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-3718.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index e7b7f8adbb2..57051a286a7 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -133,7 +133,7 @@ impl Rewrite for Pat { .iter() .map(|p| { if let Some(rw) = p.rewrite(context, shape) { - format!("{}", if rw == "_" { "" } else { &rw }) + rw } else { format!("{}", context.snippet(p.span)) } diff --git a/tests/target/issue-3718.rs b/tests/target/issue-3718.rs new file mode 100644 index 00000000000..8ad21ffc708 --- /dev/null +++ b/tests/target/issue-3718.rs @@ -0,0 +1,7 @@ +fn main() { + let x: &[i32] = &[2, 2]; + match x { + [_a, _] => println!("Wrong username or password"), + _ => println!("Logged in"), + } +} -- cgit 1.4.1-3-g733a5 From 62a32e7b839a20a73870503a1cdff9879bb166e8 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 2 Aug 2019 16:54:39 +0200 Subject: Fix most recenty nightly breakage due to removed await! support (#3722) --- Cargo.lock | 86 ++++++++++++++++++++++++------------------------ Cargo.toml | 6 ++-- src/chains.rs | 6 ++-- src/expr.rs | 14 +------- tests/source/async_fn.rs | 8 +++-- tests/target/async_fn.rs | 4 +-- 6 files changed, 56 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 11698d94f77..79b5314e3ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,21 +691,21 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_data_structures" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -716,8 +716,8 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -727,27 +727,27 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_macros" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,19 +759,19 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -780,33 +780,33 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "542.0.0" +version = "546.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -886,9 +886,9 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.1.2", "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1238,16 +1238,16 @@ dependencies = [ "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" "checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" -"checksum rustc-ap-arena 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60ae3caf12a5dfa3181e12e813b090b0b41d43b91b193759ba9084520aeb2459" -"checksum rustc-ap-graphviz 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0113b8888a3f0a68825ed0dea6d3a1aa71b5d0cd6ff16854252c4faea253cf9b" -"checksum rustc-ap-rustc_data_structures 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd9eec8c9fbdac20e631f995861c5c854b3f8b2347955614854571457117e51" -"checksum rustc-ap-rustc_errors 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f55baa0fa4a42a8b354f02015755e7db5619125ad3e625923865f6f1f5688753" -"checksum rustc-ap-rustc_lexer 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2875181a7886d83b727b1d08291ee430728c2d94c9a7e3f4359df2a14e6c462b" -"checksum rustc-ap-rustc_macros 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3cadcc9dd4fc3c94c89e103e91f8792f19a1466e0a127d9fb29a2c0ee069389" -"checksum rustc-ap-rustc_target 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bdcce1900404a6907785dd31a152ddd723766dfbe29bed6bcca255e7347abdd" -"checksum rustc-ap-serialize 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "550e295fa077784f7145ba77591aff952fad2279f3ce23a53cf8750fb366c622" -"checksum rustc-ap-syntax 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "594006d7e68bcff9b5356517667c4e9dd5ec925a2a08660d129b705d0b741ad7" -"checksum rustc-ap-syntax_pos 542.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae6751bf44d949b430b151c81772b585686f0ff31e328b68eaa7d406590f848" +"checksum rustc-ap-arena 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc2e1e68b64268c543bfa6e63e3c0d9ea58074c71396f42f76931f35a9287f9" +"checksum rustc-ap-graphviz 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c108d647ce0dd46477b048eafff5a6273b5652e02d47424b0cd684147379c811" +"checksum rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656771744e0783cb8e4481e3b8b1f975687610aaf18833b898018111a0e0e582" +"checksum rustc-ap-rustc_errors 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e37064f6624bc799bfaa2968b61ee6880926dea2a8bba69f18aef6c8e69c9604" +"checksum rustc-ap-rustc_lexer 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5bc0a971823637ea23a857f0ef1467f44b1e05d71968821f83a0abe53e0fe3" +"checksum rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b90037e3336fe8835f468db44d0848ae10d9cc8533ae89b55828883f905b7e80" +"checksum rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cadf9ca07315eab3a7a21f63872f9cc81e250fd6ede0419c24f8926ade73a45d" +"checksum rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602" +"checksum rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84" +"checksum rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" diff --git a/Cargo.toml b/Cargo.toml index f359379cf2b..a5592d337ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -rustc-ap-rustc_target = "542.0.0" -rustc-ap-syntax = "542.0.0" -rustc-ap-syntax_pos = "542.0.0" +rustc-ap-rustc_target = "546.0.0" +rustc-ap-syntax = "546.0.0" +rustc-ap-syntax_pos = "546.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/chains.rs b/src/chains.rs index c7acf19ee0c..81708625acb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -168,7 +168,7 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), field.span.hi()); (kind, span) } - ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, ref nested) => { + ast::ExprKind::Await(ref nested) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } @@ -396,9 +396,7 @@ impl Chain { } ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) - | ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, ref subexpr) => { - Some(Self::convert_try(subexpr, context)) - } + | ast::ExprKind::Await(ref subexpr) => Some(Self::convert_try(subexpr, context)), _ => None, } } diff --git a/src/expr.rs b/src/expr.rs index 8c877fe3cea..9030d876b40 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; use std::cmp::min; -use std::iter; use itertools::Itertools; use syntax::parse::token::DelimToken; @@ -367,18 +366,7 @@ pub(crate) fn format_expr( )) } } - ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, _) => rewrite_chain(expr, context, shape), - ast::ExprKind::Await(ast::AwaitOrigin::MacroLike, ref nested) => { - overflow::rewrite_with_parens( - context, - "await!", - iter::once(nested), - shape, - expr.span, - context.config.max_width(), - None, - ) - } + ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape), ast::ExprKind::Err => None, }; diff --git a/tests/source/async_fn.rs b/tests/source/async_fn.rs index b4dc9fac5b2..c63cf5b0f51 100644 --- a/tests/source/async_fn.rs +++ b/tests/source/async_fn.rs @@ -20,7 +20,9 @@ async unsafe fn rust() { } } -async fn await_macro() { - await ! ( - something)?; +async fn await_try() { + something + .await + ? + ; } diff --git a/tests/target/async_fn.rs b/tests/target/async_fn.rs index 82be8c76785..ac151dddb25 100644 --- a/tests/target/async_fn.rs +++ b/tests/target/async_fn.rs @@ -19,6 +19,6 @@ async unsafe fn rust() { } } -async fn await_macro() { - await!(something)?; +async fn await_try() { + something.await?; } -- cgit 1.4.1-3-g733a5 From 3adfb08afe3cb6a8c055e581dea87808464d1381 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 3 Aug 2019 00:01:59 +0900 Subject: Release 1.4.3 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 79b5314e3ea..8f6bc9c13c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -869,7 +869,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.2" +version = "1.4.3" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a5592d337ea..2d84c74457d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.2" +version = "1.4.3" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index fb3a10a7c21..9ab0a8e1120 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.4.2" +required_version = "1.4.3" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From afc8fbd7018c1b5a31c2d0e97dc548b4da7dd25a Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 5 Aug 2019 10:33:59 -0500 Subject: fix: issue with --all when workspace member also exists in dep tree (#3726) --- src/cargo-fmt/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 7651a0ee437..410d62673ec 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -340,7 +340,7 @@ fn get_targets_recursive( let dependency_package = metadata_with_deps .packages .iter() - .find(|p| p.name == dependency.name); + .find(|p| p.name == dependency.name && p.source.is_none()); let manifest_path = if dependency_package.is_some() { PathBuf::from(&dependency_package.unwrap().manifest_path) } else { -- cgit 1.4.1-3-g733a5 From c0cb5eb5358c38c07c0b57217e691bc3ebbb5e85 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 6 Aug 2019 11:09:45 +0900 Subject: Fix broken tuple pattern (#3729) --- src/patterns.rs | 21 ++++++++++++++++++++- tests/source/pattern.rs | 7 +++++++ tests/target/issue-1021.rs | 2 +- tests/target/pattern.rs | 5 +++++ 4 files changed, 33 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index 57051a286a7..b5032eca6d5 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -272,6 +272,18 @@ impl<'a> Spanned for TuplePatField<'a> { } } +impl<'a> TuplePatField<'a> { + fn is_dotdot(&self) -> bool { + match self { + TuplePatField::Pat(pat) => match pat.node { + ast::PatKind::Rest => true, + _ => false, + }, + TuplePatField::Dotdot(_) => true, + } + } +} + pub(crate) fn can_be_overflowed_pat( context: &RewriteContext<'_>, pat: &TuplePatField<'_>, @@ -321,7 +333,10 @@ fn rewrite_tuple_pat( (&pat_vec[..], span) }; + let is_last_pat_dotdot = pat_vec.last().map_or(false, |p| p.is_dotdot()); + let add_comma = path_str.is_none() && pat_vec.len() == 1 && !is_last_pat_dotdot; let path_str = path_str.unwrap_or_default(); + overflow::rewrite_with_parens( &context, &path_str, @@ -329,7 +344,11 @@ fn rewrite_tuple_pat( shape, span, context.config.max_width(), - None, + if add_comma { + Some(SeparatorTactic::Always) + } else { + None + }, ) } diff --git a/tests/source/pattern.rs b/tests/source/pattern.rs index fc3b1455e0d..f06d03cadf2 100644 --- a/tests/source/pattern.rs +++ b/tests/source/pattern.rs @@ -81,3 +81,10 @@ fn slice_patterns() { _ => {} } } + +fn issue3728() { + let foo = | + (c,) + | c; + foo((1,)); +} diff --git a/tests/target/issue-1021.rs b/tests/target/issue-1021.rs index 94911d1f8ee..ba1029d4e61 100644 --- a/tests/target/issue-1021.rs +++ b/tests/target/issue-1021.rs @@ -15,7 +15,7 @@ fn main() { (true, ..) => (), (.., true) => (), (..) => (), - (_) => (), + (_,) => (), (/* .. */ ..) => (), (/* .. */ .., true) => (), } diff --git a/tests/target/pattern.rs b/tests/target/pattern.rs index d8a96d64920..576018ac623 100644 --- a/tests/target/pattern.rs +++ b/tests/target/pattern.rs @@ -91,3 +91,8 @@ fn slice_patterns() { _ => {} } } + +fn issue3728() { + let foo = |(c,)| c; + foo((1,)); +} -- cgit 1.4.1-3-g733a5 From 0462008de87d2757e8ef1dc26f2c54dd789a59a8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 6 Aug 2019 11:14:12 +0900 Subject: Release 1.4.4 --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 8f6bc9c13c9..d25644519f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -869,7 +869,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.3" +version = "1.4.4" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 2d84c74457d..4089a3dfa68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.3" +version = "1.4.4" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" diff --git a/src/config/mod.rs b/src/config/mod.rs index 9ab0a8e1120..d6a194c3198 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -519,7 +519,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.4.3" +required_version = "1.4.4" unstable_features = false disable_all_formatting = false skip_children = false -- cgit 1.4.1-3-g733a5 From ac150d016b760d06352e02adf030ce7e6c948005 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 10 Aug 2019 22:49:14 -0500 Subject: fix: remove trailing space with empty dyn macro arg (#3737) --- src/macros.rs | 4 ++-- src/overflow.rs | 1 + tests/source/issue-3709.rs | 10 ++++++++++ tests/target/issue-3709.rs | 10 ++++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3709.rs create mode 100644 tests/target/issue-3709.rs (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b2146437f15..de8e0651cd8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -303,9 +303,9 @@ fn rewrite_macro_inner( if DelimToken::Brace != style { loop { - if let Some(arg) = parse_macro_arg(&mut parser) { + if let Some(arg) = check_keyword(&mut parser) { arg_vec.push(arg); - } else if let Some(arg) = check_keyword(&mut parser) { + } else if let Some(arg) = parse_macro_arg(&mut parser) { arg_vec.push(arg); } else { return return_macro_parse_failure_fallback(context, shape.indent, mac.span); diff --git a/src/overflow.rs b/src/overflow.rs index d8e1d0e2590..fc0cf98ceba 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -122,6 +122,7 @@ impl<'a> OverflowableItem<'a> { pub(crate) fn is_simple(&self) -> bool { match self { OverflowableItem::Expr(expr) => is_simple_expr(expr), + OverflowableItem::MacroArg(MacroArg::Keyword(..)) => true, OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item { ast::NestedMetaItem::Literal(..) => true, diff --git a/tests/source/issue-3709.rs b/tests/source/issue-3709.rs new file mode 100644 index 00000000000..73c2a624e52 --- /dev/null +++ b/tests/source/issue-3709.rs @@ -0,0 +1,10 @@ +// rustfmt-edition: 2018 + +macro_rules! token { + ($t:tt) => {}; +} + +fn main() { + token!(dyn); + token!(dyn ); +} diff --git a/tests/target/issue-3709.rs b/tests/target/issue-3709.rs new file mode 100644 index 00000000000..0f3eae048d4 --- /dev/null +++ b/tests/target/issue-3709.rs @@ -0,0 +1,10 @@ +// rustfmt-edition: 2018 + +macro_rules! token { + ($t:tt) => {}; +} + +fn main() { + token!(dyn); + token!(dyn); +} -- cgit 1.4.1-3-g733a5 From 4871d6467a4babe8968c1e72c0551adfb1c9d5c5 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 13 Aug 2019 23:21:55 +0900 Subject: Use the correct BytePos for the opening brace position (#3742) --- src/items.rs | 9 +++++---- tests/source/issue-3740.rs | 10 ++++++++++ tests/target/issue-3740.rs | 8 ++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 tests/source/issue-3740.rs create mode 100644 tests/target/issue-3740.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 73b752dfe78..022fe4295a1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1,7 +1,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use std::borrow::Cow; -use std::cmp::{min, Ordering}; +use std::cmp::{max, min, Ordering}; use regex::Regex; use rustc_target::spec::abi; @@ -733,15 +733,16 @@ pub(crate) fn format_impl( } result.push('{'); - // this is an impl body snippet(impl SampleImple { /* here */ }) - let snippet = context.snippet(mk_sp(item.span.hi(), self_ty.span.hi())); + // this is an impl body snippet(impl SampleImpl { /* here */ }) + let lo = max(self_ty.span.hi(), generics.where_clause.span.hi()); + let snippet = context.snippet(mk_sp(lo, item.span.hi())); let open_pos = snippet.find_uncommented("{")? + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); let item_indent = offset.block_only().block_indent(context.config); visitor.block_indent = item_indent; - visitor.last_pos = self_ty.span.hi() + BytePos(open_pos as u32); + visitor.last_pos = lo + BytePos(open_pos as u32); visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); visitor.visit_impl_items(items); diff --git a/tests/source/issue-3740.rs b/tests/source/issue-3740.rs new file mode 100644 index 00000000000..2769a8cc9b1 --- /dev/null +++ b/tests/source/issue-3740.rs @@ -0,0 +1,10 @@ +impl IntoNormalized for Vector + where + Vector: Div>, + for<'a> &'a Vector: IntoLength, +{ + type Output = Vector; + fn into_normalized(self) -> Self::Output { + + } +} diff --git a/tests/target/issue-3740.rs b/tests/target/issue-3740.rs new file mode 100644 index 00000000000..995a6bee352 --- /dev/null +++ b/tests/target/issue-3740.rs @@ -0,0 +1,8 @@ +impl IntoNormalized for Vector +where + Vector: Div>, + for<'a> &'a Vector: IntoLength, +{ + type Output = Vector; + fn into_normalized(self) -> Self::Output {} +} -- cgit 1.4.1-3-g733a5 From 541d9a865989459337131f1e130e7d4732acd47f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 13 Aug 2019 18:02:30 -0500 Subject: tests: fix failing default config unit test (#3743) --- src/config/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index d6a194c3198..fa3a0b28e14 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -465,7 +465,8 @@ mod test { #[test] fn test_dump_default_config() { - const DEFAULT_CONFIG: &str = r#"max_width = 100 + let default_config = format!( + r#"max_width = 100 hard_tabs = false tab_spaces = 4 newline_style = "Auto" @@ -519,7 +520,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "1.4.4" +required_version = "{}" unstable_features = false disable_all_formatting = false skip_children = false @@ -531,9 +532,11 @@ report_fixme = "Never" ignore = [] emit_mode = "Files" make_backup = false -"#; +"#, + env!("CARGO_PKG_VERSION") + ); let toml = Config::default().all_options().to_toml().unwrap(); - assert_eq!(&toml, DEFAULT_CONFIG); + assert_eq!(&toml, &default_config); } // FIXME(#2183): these tests cannot be run in parallel because they use env vars. -- cgit 1.4.1-3-g733a5 From dfd27663dca6b9e0e84c04a4d7319ccf8a879909 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 15 Aug 2019 21:14:53 -0500 Subject: add json emit mode (#3735) --- README.md | 1 + src/bin/main.rs | 3 +- src/config/options.rs | 3 + src/emitter.rs | 4 +- src/emitter/checkstyle.rs | 2 +- src/emitter/diff.rs | 2 +- src/emitter/files.rs | 2 +- src/emitter/files_with_backup.rs | 2 +- src/emitter/json.rs | 349 +++++++++++++++++++++++++++++++++++++ src/emitter/modified_lines.rs | 2 +- src/emitter/stdout.rs | 2 +- src/formatting.rs | 3 +- src/lib.rs | 1 + src/source_file.rs | 6 +- src/test/mod.rs | 7 + tests/writemode/source/json.rs | 80 +++++++++ tests/writemode/target/output.json | 1 + 17 files changed, 458 insertions(+), 12 deletions(-) create mode 100644 src/emitter/json.rs create mode 100644 tests/writemode/source/json.rs create mode 100644 tests/writemode/target/output.json (limited to 'src') diff --git a/README.md b/README.md index 142e1f1d272..7a97d31bab9 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,7 @@ needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`. | stdout | writes output to stdout | No | | coverage | displays how much of the input file was processed | Yes | | checkstyle | emits in a checkstyle format | Yes | + | json | emits diffs in a json format | Yes | ## License diff --git a/src/bin/main.rs b/src/bin/main.rs index 70990aa798d..9d3be60ac8f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -98,7 +98,7 @@ fn make_opts() -> Options { ); let is_nightly = is_nightly(); let emit_opts = if is_nightly { - "[files|stdout|coverage|checkstyle]" + "[files|stdout|coverage|checkstyle|json]" } else { "[files|stdout]" }; @@ -631,6 +631,7 @@ fn emit_mode_from_emit_str(emit_str: &str) -> Result { "stdout" => Ok(EmitMode::Stdout), "coverage" => Ok(EmitMode::Coverage), "checkstyle" => Ok(EmitMode::Checkstyle), + "json" => Ok(EmitMode::Json), _ => Err(format_err!("Invalid value for `--emit`")), } } diff --git a/src/config/options.rs b/src/config/options.rs index cf1a328e9cd..d2063650ccb 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -119,6 +119,9 @@ pub enum EmitMode { Coverage, /// Unfancy stdout Checkstyle, + /// Writes the resulting diffs in a JSON format. Returns an empty array + /// `[]` if there were no diffs. + Json, /// Output the changed lines (for internal value only) ModifiedLines, /// Checks if a diff can be generated. If so, rustfmt outputs a diff and diff --git a/src/emitter.rs b/src/emitter.rs index 03ca1e35b72..dc2c99a301e 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -2,6 +2,7 @@ pub(crate) use self::checkstyle::*; pub(crate) use self::diff::*; pub(crate) use self::files::*; pub(crate) use self::files_with_backup::*; +pub(crate) use self::json::*; pub(crate) use self::modified_lines::*; pub(crate) use self::stdout::*; use crate::FileName; @@ -12,6 +13,7 @@ mod checkstyle; mod diff; mod files; mod files_with_backup; +mod json; mod modified_lines; mod stdout; @@ -28,7 +30,7 @@ pub(crate) struct EmitterResult { pub(crate) trait Emitter { fn emit_formatted_file( - &self, + &mut self, output: &mut dyn Write, formatted_file: FormattedFile<'_>, ) -> Result; diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs index eb1499985fd..e8f8ec86cf1 100644 --- a/src/emitter/checkstyle.rs +++ b/src/emitter/checkstyle.rs @@ -21,7 +21,7 @@ impl Emitter for CheckstyleEmitter { } fn emit_formatted_file( - &self, + &mut self, output: &mut dyn Write, FormattedFile { filename, diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs index 5e387395b5b..08a42b4679d 100644 --- a/src/emitter/diff.rs +++ b/src/emitter/diff.rs @@ -14,7 +14,7 @@ impl DiffEmitter { impl Emitter for DiffEmitter { fn emit_formatted_file( - &self, + &mut self, _output: &mut dyn Write, FormattedFile { filename, diff --git a/src/emitter/files.rs b/src/emitter/files.rs index 5b1dbce11c9..4538a8f4c49 100644 --- a/src/emitter/files.rs +++ b/src/emitter/files.rs @@ -6,7 +6,7 @@ pub(crate) struct FilesEmitter; impl Emitter for FilesEmitter { fn emit_formatted_file( - &self, + &mut self, _output: &mut dyn Write, FormattedFile { filename, diff --git a/src/emitter/files_with_backup.rs b/src/emitter/files_with_backup.rs index af3e0e2d91d..4c15f6fa5ec 100644 --- a/src/emitter/files_with_backup.rs +++ b/src/emitter/files_with_backup.rs @@ -6,7 +6,7 @@ pub(crate) struct FilesWithBackupEmitter; impl Emitter for FilesWithBackupEmitter { fn emit_formatted_file( - &self, + &mut self, _output: &mut dyn Write, FormattedFile { filename, diff --git a/src/emitter/json.rs b/src/emitter/json.rs new file mode 100644 index 00000000000..269dd2d4daf --- /dev/null +++ b/src/emitter/json.rs @@ -0,0 +1,349 @@ +use super::*; +use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch}; +use serde::Serialize; +use serde_json::to_string as to_json_string; +use std::io::{self, Write}; +use std::path::Path; + +#[derive(Debug, Default)] +pub(crate) struct JsonEmitter { + num_files: u32, +} + +#[derive(Debug, Default, Serialize)] +struct MismatchedBlock { + original_begin_line: u32, + original_end_line: u32, + expected_begin_line: u32, + expected_end_line: u32, + original: String, + expected: String, +} + +#[derive(Debug, Default, Serialize)] +struct MismatchedFile { + name: String, + mismatches: Vec, +} + +impl Emitter for JsonEmitter { + fn emit_header(&self, output: &mut dyn Write) -> Result<(), io::Error> { + write!(output, "[")?; + Ok(()) + } + + fn emit_footer(&self, output: &mut dyn Write) -> Result<(), io::Error> { + write!(output, "]")?; + Ok(()) + } + + fn emit_formatted_file( + &mut self, + output: &mut dyn Write, + FormattedFile { + filename, + original_text, + formatted_text, + }: FormattedFile<'_>, + ) -> Result { + const CONTEXT_SIZE: usize = 0; + let filename = ensure_real_path(filename); + let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE); + let has_diff = !diff.is_empty(); + + if has_diff { + output_json_file(output, filename, diff, self.num_files)?; + self.num_files += 1; + } + + Ok(EmitterResult { has_diff }) + } +} + +fn output_json_file( + mut writer: T, + filename: &Path, + diff: Vec, + num_emitted_files: u32, +) -> Result<(), io::Error> +where + T: Write, +{ + let mut mismatches = vec![]; + for mismatch in diff { + let original_begin_line = mismatch.line_number_orig; + let expected_begin_line = mismatch.line_number; + let mut original_end_line = original_begin_line; + let mut expected_end_line = expected_begin_line; + let mut original_line_counter = 0; + let mut expected_line_counter = 0; + let mut original_lines = vec![]; + let mut expected_lines = vec![]; + + for line in mismatch.lines { + match line { + DiffLine::Expected(msg) => { + expected_end_line = expected_begin_line + expected_line_counter; + expected_line_counter += 1; + expected_lines.push(msg) + } + DiffLine::Resulting(msg) => { + original_end_line = original_begin_line + original_line_counter; + original_line_counter += 1; + original_lines.push(msg) + } + DiffLine::Context(_) => continue, + } + } + + mismatches.push(MismatchedBlock { + original_begin_line, + original_end_line, + expected_begin_line, + expected_end_line, + original: original_lines.join("\n"), + expected: expected_lines.join("\n"), + }); + } + let json = to_json_string(&MismatchedFile { + name: String::from(filename.to_str().unwrap()), + mismatches, + })?; + let prefix = if num_emitted_files > 0 { "," } else { "" }; + write!(writer, "{}{}", prefix, &json)?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::FileName; + use std::path::PathBuf; + + #[test] + fn expected_line_range_correct_when_single_line_split() { + let file = "foo/bar.rs"; + let mismatched_file = MismatchedFile { + name: String::from(file), + mismatches: vec![MismatchedBlock { + original_begin_line: 79, + original_end_line: 79, + expected_begin_line: 79, + expected_end_line: 82, + original: String::from("fn Foo() where T: Bar {"), + expected: String::from("fn Foo()\nwhere\n T: Bar,\n{"), + }], + }; + let mismatch = Mismatch { + line_number: 79, + line_number_orig: 79, + lines: vec![ + DiffLine::Resulting(String::from("fn Foo() where T: Bar {")), + DiffLine::Expected(String::from("fn Foo()")), + DiffLine::Expected(String::from("where")), + DiffLine::Expected(String::from(" T: Bar,")), + DiffLine::Expected(String::from("{")), + ], + }; + + let mut writer = Vec::new(); + let exp_json = to_json_string(&mismatched_file).unwrap(); + let _ = output_json_file(&mut writer, &PathBuf::from(file), vec![mismatch], 0); + assert_eq!(&writer[..], format!("{}", exp_json).as_bytes()); + } + + #[test] + fn context_lines_ignored() { + let file = "src/lib.rs"; + let mismatched_file = MismatchedFile { + name: String::from(file), + mismatches: vec![MismatchedBlock { + original_begin_line: 5, + original_end_line: 5, + expected_begin_line: 5, + expected_end_line: 5, + original: String::from( + "fn foo(_x: &u64) -> Option<&(dyn::std::error::Error + 'static)> {", + ), + expected: String::from( + "fn foo(_x: &u64) -> Option<&(dyn ::std::error::Error + 'static)> {", + ), + }], + }; + let mismatch = Mismatch { + line_number: 5, + line_number_orig: 5, + lines: vec![ + DiffLine::Context(String::new()), + DiffLine::Resulting(String::from( + "fn foo(_x: &u64) -> Option<&(dyn::std::error::Error + 'static)> {", + )), + DiffLine::Context(String::new()), + DiffLine::Expected(String::from( + "fn foo(_x: &u64) -> Option<&(dyn ::std::error::Error + 'static)> {", + )), + DiffLine::Context(String::new()), + ], + }; + + let mut writer = Vec::new(); + let exp_json = to_json_string(&mismatched_file).unwrap(); + let _ = output_json_file(&mut writer, &PathBuf::from(file), vec![mismatch], 0); + assert_eq!(&writer[..], format!("{}", exp_json).as_bytes()); + } + + #[test] + fn emits_empty_array_on_no_diffs() { + let mut writer = Vec::new(); + let mut emitter = JsonEmitter::default(); + let _ = emitter.emit_header(&mut writer); + let result = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from("src/lib.rs")), + original_text: "fn empty() {}\n", + formatted_text: "fn empty() {}\n", + }, + ) + .unwrap(); + let _ = emitter.emit_footer(&mut writer); + assert_eq!(result.has_diff, false); + assert_eq!(&writer[..], "[]".as_bytes()); + } + + #[test] + fn emits_array_with_files_with_diffs() { + let file_name = "src/bin.rs"; + let original = vec![ + "fn main() {", + "println!(\"Hello, world!\");", + "}", + "", + "#[cfg(test)]", + "mod tests {", + "#[test]", + "fn it_works() {", + " assert_eq!(2 + 2, 4);", + "}", + "}", + ]; + let formatted = vec![ + "fn main() {", + " println!(\"Hello, world!\");", + "}", + "", + "#[cfg(test)]", + "mod tests {", + " #[test]", + " fn it_works() {", + " assert_eq!(2 + 2, 4);", + " }", + "}", + ]; + let mut writer = Vec::new(); + let mut emitter = JsonEmitter::default(); + let _ = emitter.emit_header(&mut writer); + let result = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(file_name)), + original_text: &original.join("\n"), + formatted_text: &formatted.join("\n"), + }, + ) + .unwrap(); + let _ = emitter.emit_footer(&mut writer); + let exp_json = to_json_string(&MismatchedFile { + name: String::from(file_name), + mismatches: vec![ + MismatchedBlock { + original_begin_line: 2, + original_end_line: 2, + expected_begin_line: 2, + expected_end_line: 2, + original: String::from("println!(\"Hello, world!\");"), + expected: String::from(" println!(\"Hello, world!\");"), + }, + MismatchedBlock { + original_begin_line: 7, + original_end_line: 10, + expected_begin_line: 7, + expected_end_line: 10, + original: String::from( + "#[test]\nfn it_works() {\n assert_eq!(2 + 2, 4);\n}", + ), + expected: String::from( + " #[test]\n fn it_works() {\n assert_eq!(2 + 2, 4);\n }", + ), + }, + ], + }) + .unwrap(); + assert_eq!(result.has_diff, true); + assert_eq!(&writer[..], format!("[{}]", exp_json).as_bytes()); + } + + #[test] + fn emits_valid_json_with_multiple_files() { + let bin_file = "src/bin.rs"; + let bin_original = vec!["fn main() {", "println!(\"Hello, world!\");", "}"]; + let bin_formatted = vec!["fn main() {", " println!(\"Hello, world!\");", "}"]; + let lib_file = "src/lib.rs"; + let lib_original = vec!["fn greet() {", "println!(\"Greetings!\");", "}"]; + let lib_formatted = vec!["fn greet() {", " println!(\"Greetings!\");", "}"]; + let mut writer = Vec::new(); + let mut emitter = JsonEmitter::default(); + let _ = emitter.emit_header(&mut writer); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(bin_file)), + original_text: &bin_original.join("\n"), + formatted_text: &bin_formatted.join("\n"), + }, + ) + .unwrap(); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(lib_file)), + original_text: &lib_original.join("\n"), + formatted_text: &lib_formatted.join("\n"), + }, + ) + .unwrap(); + let _ = emitter.emit_footer(&mut writer); + let exp_bin_json = to_json_string(&MismatchedFile { + name: String::from(bin_file), + mismatches: vec![MismatchedBlock { + original_begin_line: 2, + original_end_line: 2, + expected_begin_line: 2, + expected_end_line: 2, + original: String::from("println!(\"Hello, world!\");"), + expected: String::from(" println!(\"Hello, world!\");"), + }], + }) + .unwrap(); + let exp_lib_json = to_json_string(&MismatchedFile { + name: String::from(lib_file), + mismatches: vec![MismatchedBlock { + original_begin_line: 2, + original_end_line: 2, + expected_begin_line: 2, + expected_end_line: 2, + original: String::from("println!(\"Greetings!\");"), + expected: String::from(" println!(\"Greetings!\");"), + }], + }) + .unwrap(); + assert_eq!( + &writer[..], + format!("[{},{}]", exp_bin_json, exp_lib_json).as_bytes() + ); + } +} diff --git a/src/emitter/modified_lines.rs b/src/emitter/modified_lines.rs index 83736c47bd6..94ff570a8a9 100644 --- a/src/emitter/modified_lines.rs +++ b/src/emitter/modified_lines.rs @@ -7,7 +7,7 @@ pub(crate) struct ModifiedLinesEmitter; impl Emitter for ModifiedLinesEmitter { fn emit_formatted_file( - &self, + &mut self, output: &mut dyn Write, FormattedFile { original_text, diff --git a/src/emitter/stdout.rs b/src/emitter/stdout.rs index 968de68c741..9fddd515e49 100644 --- a/src/emitter/stdout.rs +++ b/src/emitter/stdout.rs @@ -15,7 +15,7 @@ impl StdoutEmitter { impl Emitter for StdoutEmitter { fn emit_formatted_file( - &self, + &mut self, output: &mut dyn Write, FormattedFile { filename, diff --git a/src/formatting.rs b/src/formatting.rs index 879ddc61b13..ee44549b2bc 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -235,7 +235,8 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { - match source_file::write_file(Some(source_map), &path, &result, out, &*self.emitter) { + match source_file::write_file(Some(source_map), &path, &result, out, &mut *self.emitter) + { Ok(ref result) if result.has_diff => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed diff --git a/src/lib.rs b/src/lib.rs index e3e7f7f9244..dbb7d2e0e17 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -486,6 +486,7 @@ pub(crate) fn create_emitter<'a>(config: &Config) -> Box { EmitMode::Stdout | EmitMode::Coverage => { Box::new(emitter::StdoutEmitter::new(config.verbose())) } + EmitMode::Json => Box::new(emitter::JsonEmitter::default()), EmitMode::ModifiedLines => Box::new(emitter::ModifiedLinesEmitter::default()), EmitMode::Checkstyle => Box::new(emitter::CheckstyleEmitter::default()), EmitMode::Diff => Box::new(emitter::DiffEmitter::new(config.clone())), diff --git a/src/source_file.rs b/src/source_file.rs index 074b7a7315f..28366ca2485 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -28,11 +28,11 @@ pub(crate) fn write_all_files( where T: Write, { - let emitter = create_emitter(config); + let mut emitter = create_emitter(config); emitter.emit_header(out)?; for &(ref filename, ref text) in source_file { - write_file(None, filename, text, out, &*emitter)?; + write_file(None, filename, text, out, &mut *emitter)?; } emitter.emit_footer(out)?; @@ -44,7 +44,7 @@ pub(crate) fn write_file( filename: &FileName, formatted_text: &str, out: &mut T, - emitter: &dyn Emitter, + emitter: &mut dyn Emitter, ) -> Result where T: Write, diff --git a/src/test/mod.rs b/src/test/mod.rs index a7063c76f28..bd6613e1488 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -200,6 +200,13 @@ fn checkstyle_test() { assert_output(Path::new(filename), Path::new(expected_filename)); } +#[test] +fn json_test() { + let filename = "tests/writemode/source/json.rs"; + let expected_filename = "tests/writemode/target/output.json"; + assert_output(Path::new(filename), Path::new(expected_filename)); +} + #[test] fn modified_test() { use std::io::BufRead; diff --git a/tests/writemode/source/json.rs b/tests/writemode/source/json.rs new file mode 100644 index 00000000000..89dcf694183 --- /dev/null +++ b/tests/writemode/source/json.rs @@ -0,0 +1,80 @@ +// rustfmt-fn_single_line: true +// rustfmt-emit_mode: json +// Test single-line functions. + +fn foo_expr() { + 1 +} + +fn foo_stmt() { + foo(); +} + +fn foo_decl_local() { + let z = 5; + } + +fn foo_decl_item(x: &mut i32) { + x = 3; +} + + fn empty() { + +} + +fn foo_return() -> String { + "yay" +} + +fn foo_where() -> T where T: Sync { + let x = 2; +} + +fn fooblock() { + { + "inner-block" + } +} + +fn fooblock2(x: i32) { + let z = match x { + _ => 2, + }; +} + +fn comment() { + // this is a test comment + 1 +} + +fn comment2() { + // multi-line comment + let z = 2; + 1 +} + +fn only_comment() { + // Keep this here +} + +fn aaaaaaaaaaaaaaaaa_looooooooooooooooooooooong_name() { + let z = "aaaaaaawwwwwwwwwwwwwwwwwwwwwwwwwwww"; +} + +fn lots_of_space () { + 1 +} + +fn mac() -> Vec { vec![] } + +trait CoolTypes { + fn dummy(&self) { + } +} + +trait CoolerTypes { fn dummy(&self) { +} +} + +fn Foo() where T: Bar { +} diff --git a/tests/writemode/target/output.json b/tests/writemode/target/output.json new file mode 100644 index 00000000000..b5f327b0a1c --- /dev/null +++ b/tests/writemode/target/output.json @@ -0,0 +1 @@ +[{"name":"tests/writemode/source/json.rs","mismatches":[{"original_begin_line":5,"original_end_line":7,"expected_begin_line":5,"expected_end_line":5,"original":"fn foo_expr() {\n 1\n}","expected":"fn foo_expr() { 1 }"},{"original_begin_line":9,"original_end_line":11,"expected_begin_line":7,"expected_end_line":7,"original":"fn foo_stmt() {\n foo();\n}","expected":"fn foo_stmt() { foo(); }"},{"original_begin_line":13,"original_end_line":15,"expected_begin_line":9,"expected_end_line":9,"original":"fn foo_decl_local() {\n let z = 5;\n }","expected":"fn foo_decl_local() { let z = 5; }"},{"original_begin_line":17,"original_end_line":19,"expected_begin_line":11,"expected_end_line":11,"original":"fn foo_decl_item(x: &mut i32) {\n x = 3;\n}","expected":"fn foo_decl_item(x: &mut i32) { x = 3; }"},{"original_begin_line":21,"original_end_line":21,"expected_begin_line":13,"expected_end_line":13,"original":" fn empty() {","expected":"fn empty() {}"},{"original_begin_line":23,"original_end_line":23,"expected_begin_line":15,"expected_end_line":15,"original":"}","expected":"fn foo_return() -> String { \"yay\" }"},{"original_begin_line":25,"original_end_line":29,"expected_begin_line":17,"expected_end_line":20,"original":"fn foo_return() -> String {\n \"yay\"\n}\n\nfn foo_where() -> T where T: Sync {","expected":"fn foo_where() -> T\nwhere\n T: Sync,\n{"},{"original_begin_line":64,"original_end_line":66,"expected_begin_line":55,"expected_end_line":55,"original":"fn lots_of_space () {\n 1 \n}","expected":"fn lots_of_space() { 1 }"},{"original_begin_line":71,"original_end_line":72,"expected_begin_line":60,"expected_end_line":60,"original":" fn dummy(&self) {\n }","expected":" fn dummy(&self) {}"},{"original_begin_line":75,"original_end_line":75,"expected_begin_line":63,"expected_end_line":64,"original":"trait CoolerTypes { fn dummy(&self) { ","expected":"trait CoolerTypes {\n fn dummy(&self) {}"},{"original_begin_line":77,"original_end_line":77,"expected_begin_line":66,"expected_end_line":66,"original":"}","expected":""},{"original_begin_line":79,"original_end_line":79,"expected_begin_line":67,"expected_end_line":70,"original":"fn Foo() where T: Bar {","expected":"fn Foo()\nwhere\n T: Bar,\n{"}]}] \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 1643d726ef1f363048d751e3655b1b302cd9a3c3 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 16 Aug 2019 11:15:28 +0900 Subject: Use correct indent when formatting complex fn type (#3731) --- src/items.rs | 66 ++++++++++++++++++++++++++++++------------ src/types.rs | 48 ++++++++++++++++++++++++++---- tests/source/issue-3701/one.rs | 12 ++++++++ tests/source/issue-3701/two.rs | 12 ++++++++ tests/target/issue-3701/one.rs | 12 ++++++++ tests/target/issue-3701/two.rs | 14 +++++++++ 6 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 tests/source/issue-3701/one.rs create mode 100644 tests/source/issue-3701/two.rs create mode 100644 tests/target/issue-3701/one.rs create mode 100644 tests/target/issue-3701/two.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 022fe4295a1..bdae2eaafc6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1822,9 +1822,17 @@ impl Rewrite for ast::FunctionRetTy { match *self { ast::FunctionRetTy::Default(_) => Some(String::new()), ast::FunctionRetTy::Ty(ref ty) => { - let inner_width = shape.width.checked_sub(3)?; - ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) - .map(|r| format!("-> {}", r)) + if context.config.version() == Version::One + || context.config.indent_style() == IndentStyle::Visual + { + let inner_width = shape.width.checked_sub(3)?; + return ty + .rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) + .map(|r| format!("-> {}", r)); + } + + ty.rewrite(context, shape.offset_left(3)?) + .map(|s| format!("-> {}", s)) } } } @@ -2147,20 +2155,39 @@ fn rewrite_fn_base( sig_length > context.config.max_width() } }; - let ret_indent = if ret_should_indent { - let indent = if arg_str.is_empty() { - // Aligning with non-existent args looks silly. - force_new_line_for_brace = true; - indent + 4 + let ret_shape = if ret_should_indent { + if context.config.version() == Version::One + || context.config.indent_style() == IndentStyle::Visual + { + let indent = if arg_str.is_empty() { + // Aligning with non-existent args looks silly. + force_new_line_for_brace = true; + indent + 4 + } else { + // FIXME: we might want to check that using the arg indent + // doesn't blow our budget, and if it does, then fallback to + // the where-clause indent. + arg_indent + }; + + result.push_str(&indent.to_string_with_newline(context.config)); + Shape::indented(indent, context.config) } else { - // FIXME: we might want to check that using the arg indent - // doesn't blow our budget, and if it does, then fallback to - // the where-clause indent. - arg_indent - }; + let mut ret_shape = Shape::indented(indent, context.config); + if arg_str.is_empty() { + // Aligning with non-existent args looks silly. + force_new_line_for_brace = true; + ret_shape = if context.use_block_indent() { + ret_shape.offset_left(4).unwrap_or(ret_shape) + } else { + ret_shape.indent = ret_shape.indent + 4; + ret_shape + }; + } - result.push_str(&indent.to_string_with_newline(context.config)); - indent + result.push_str(&ret_shape.indent.to_string_with_newline(context.config)); + ret_shape + } } else { if context.config.version() == Version::Two { if !arg_str.is_empty() || !no_args_and_over_max_width { @@ -2170,15 +2197,16 @@ fn rewrite_fn_base( result.push(' '); } - Indent::new(indent.block_indent, last_line_width(&result)) + let ret_shape = Shape::indented(indent, context.config); + ret_shape + .offset_left(last_line_width(&result)) + .unwrap_or(ret_shape) }; if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = fd - .output - .rewrite(context, Shape::indented(ret_indent, context.config))?; + let ret_str = fd.output.rewrite(context, ret_shape)?; result.push_str(&ret_str); } else { result.push_str(&ret_str); diff --git a/src/types.rs b/src/types.rs index d09e8c01e38..012cdba3192 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,7 +6,7 @@ use syntax::source_map::{self, BytePos, Span}; use syntax::symbol::kw; use crate::config::lists::*; -use crate::config::{IndentStyle, TypeDensity}; +use crate::config::{IndentStyle, TypeDensity, Version}; use crate::expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, @@ -678,9 +678,35 @@ impl Rewrite for ast::Ty { // FIXME: we drop any comments here, even though it's a silly place to put // comments. ast::TyKind::Paren(ref ty) => { - let budget = shape.width.checked_sub(2)?; - ty.rewrite(context, Shape::legacy(budget, shape.indent + 1)) - .map(|ty_str| format!("({})", ty_str)) + if context.config.version() == Version::One + || context.config.indent_style() == IndentStyle::Visual + { + let budget = shape.width.checked_sub(2)?; + return ty + .rewrite(context, Shape::legacy(budget, shape.indent + 1)) + .map(|ty_str| format!("({})", ty_str)); + } + + // 2 = () + if let Some(sh) = shape.sub_width(2) { + if let Some(ref s) = ty.rewrite(context, sh) { + if !s.contains('\n') { + return Some(format!("({})", s)); + } + } + } + + let indent_str = shape.indent.to_string_with_newline(context.config); + let shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); + let rw = ty.rewrite(context, shape)?; + Some(format!( + "({}{}{})", + shape.to_string_with_newline(context.config), + rw, + indent_str + )) } ast::TyKind::Slice(ref ty) => { let budget = shape.width.checked_sub(4)?; @@ -716,7 +742,15 @@ impl Rewrite for ast::Ty { ast::TyKind::ImplicitSelf => Some(String::from("")), ast::TyKind::ImplTrait(_, ref it) => { // Empty trait is not a parser error. - it.rewrite(context, shape).map(|it_str| { + if it.is_empty() { + return Some("impl".to_owned()); + } + let rw = if context.config.version() == Version::One { + it.rewrite(context, shape) + } else { + join_bounds(context, shape, it, false) + }; + rw.map(|it_str| { let space = if it_str.is_empty() { "" } else { " " }; format!("impl{}{}", space, it_str) }) @@ -818,7 +852,9 @@ fn join_bounds( // We need to use multiple lines. let (type_strs, offset) = if need_indent { // Rewrite with additional indentation. - let nested_shape = shape.block_indent(context.config.tab_spaces()); + let nested_shape = shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config); let type_strs = items .iter() .map(|item| item.rewrite(context, nested_shape)) diff --git a/tests/source/issue-3701/one.rs b/tests/source/issue-3701/one.rs new file mode 100644 index 00000000000..a7f0bd3aa17 --- /dev/null +++ b/tests/source/issue-3701/one.rs @@ -0,0 +1,12 @@ +// rustfmt-version: One + +fn build_sorted_static_get_entry_names( + mut entries: Vec<(u8, &'static str)>, +) -> (impl Fn( + AlphabeticalTraversal, + Box>, +) -> BoxFuture<'static, Result, Status>> + + Send + + Sync + + 'static) { +} diff --git a/tests/source/issue-3701/two.rs b/tests/source/issue-3701/two.rs new file mode 100644 index 00000000000..8e15c58b8b2 --- /dev/null +++ b/tests/source/issue-3701/two.rs @@ -0,0 +1,12 @@ +// rustfmt-version: Two + +fn build_sorted_static_get_entry_names( + mut entries: Vec<(u8, &'static str)>, +) -> (impl Fn( + AlphabeticalTraversal, + Box>, +) -> BoxFuture<'static, Result, Status>> + + Send + + Sync + + 'static) { +} diff --git a/tests/target/issue-3701/one.rs b/tests/target/issue-3701/one.rs new file mode 100644 index 00000000000..9d1ef9eed9a --- /dev/null +++ b/tests/target/issue-3701/one.rs @@ -0,0 +1,12 @@ +// rustfmt-version: One + +fn build_sorted_static_get_entry_names( + mut entries: Vec<(u8, &'static str)>, +) -> (impl Fn( + AlphabeticalTraversal, + Box>, +) -> BoxFuture<'static, Result, Status>> + + Send + + Sync + + 'static) { +} diff --git a/tests/target/issue-3701/two.rs b/tests/target/issue-3701/two.rs new file mode 100644 index 00000000000..62ffc9d823d --- /dev/null +++ b/tests/target/issue-3701/two.rs @@ -0,0 +1,14 @@ +// rustfmt-version: Two + +fn build_sorted_static_get_entry_names( + mut entries: Vec<(u8, &'static str)>, +) -> ( + impl Fn( + AlphabeticalTraversal, + Box>, + ) -> BoxFuture<'static, Result, Status>> + + Send + + Sync + + 'static +) { +} -- cgit 1.4.1-3-g733a5 From 73847d3986f9bc66dbd46989a8fc3b8c1aa23876 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Mon, 19 Aug 2019 10:56:32 +0900 Subject: Take the inner macro_use attr into acocunt while reordering (#3749) --- src/lib.rs | 4 +--- src/reorder.rs | 6 +----- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index dbb7d2e0e17..2e43b9d8c7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,9 +41,6 @@ pub use crate::rustfmt_diff::{ModifiedChunk, ModifiedLines}; #[macro_use] mod utils; -#[macro_use] -mod release_channel; - mod attr; mod chains; mod closures; @@ -66,6 +63,7 @@ pub(crate) mod modules; mod overflow; mod pairs; mod patterns; +mod release_channel; mod reorder; mod rewrite; pub(crate) mod rustfmt_diff; diff --git a/src/reorder.rs b/src/reorder.rs index a246772f648..43a788c6339 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -10,7 +10,6 @@ use std::cmp::{Ord, Ordering}; use syntax::{ast, attr, source_map::Span, symbol::sym}; -use crate::attr::filter_inline_attrs; use crate::config::Config; use crate::imports::{merge_use_trees, UseTree}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; @@ -149,10 +148,7 @@ fn rewrite_reorderable_items( } fn contains_macro_use_attr(item: &ast::Item) -> bool { - attr::contains_name( - &filter_inline_attrs(&item.attrs, item.span()), - sym::macro_use, - ) + attr::contains_name(&item.attrs, sym::macro_use) } /// A simplified version of `ast::ItemKind`. -- cgit 1.4.1-3-g733a5 From 62432fe31b396058767c71ed332b6d2eed3053ff Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 18 Aug 2019 21:04:40 -0500 Subject: add new flag to list names of misformatted files (#3747) --- Configurations.md | 4 +++ src/bin/main.rs | 14 +++++++++ src/config/mod.rs | 4 +++ src/emitter/diff.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/emitter/files.rs | 17 ++++++++-- src/lib.rs | 4 ++- 6 files changed, 121 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 9291da05d30..e1885aba836 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2445,3 +2445,7 @@ Internal option ## `make_backup` Internal option, use `--backup` + +## `print_misformatted_file_names` + +Internal option, use `-l` or `--files-with-diff` diff --git a/src/bin/main.rs b/src/bin/main.rs index 9d3be60ac8f..bb12169329a 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -126,6 +126,12 @@ fn make_opts() -> Options { `current` writes to stdout current config as if formatting the file at PATH.", "[default|minimal|current] PATH", ); + opts.optflag( + "l", + "files-with-diff", + "Prints the names of mismatched files that were formatted. Prints the names of \ + files that would be formated when used with `--check` mode. ", + ); if is_nightly { opts.optflag( @@ -480,6 +486,7 @@ struct GetOptsOptions { file_lines: FileLines, // Default is all lines in all files. unstable_features: bool, error_on_unformatted: Option, + print_misformatted_file_names: bool, } impl GetOptsOptions { @@ -547,6 +554,10 @@ impl GetOptsOptions { options.backup = true; } + if matches.opt_present("files-with-diff") { + options.print_misformatted_file_names = true; + } + if !rust_nightly { if !STABLE_EMIT_MODES.contains(&options.emit_mode) { return Err(format_err!( @@ -610,6 +621,9 @@ impl CliOptions for GetOptsOptions { if let Some(color) = self.color { config.set().color(color); } + if self.print_misformatted_file_names { + config.set().print_misformatted_file_names(true); + } } fn config_path(&self) -> Option<&Path> { diff --git a/src/config/mod.rs b/src/config/mod.rs index fa3a0b28e14..a4930b7c575 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -152,6 +152,9 @@ create_config! { emit_mode: EmitMode, EmitMode::Files, false, "What emit Mode to use when none is supplied"; make_backup: bool, false, false, "Backup changed files"; + print_misformatted_file_names: bool, false, true, + "Prints the names of mismatched files that were formatted. Prints the names of \ + files that would be formated when used with `--check` mode. "; } impl PartialConfig { @@ -161,6 +164,7 @@ impl PartialConfig { cloned.file_lines = None; cloned.verbose = None; cloned.width_heuristics = None; + cloned.print_misformatted_file_names = None; ::toml::to_string(&cloned).map_err(|e| format!("Could not output config: {}", e)) } diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs index 08a42b4679d..462a80946ee 100644 --- a/src/emitter/diff.rs +++ b/src/emitter/diff.rs @@ -15,7 +15,7 @@ impl DiffEmitter { impl Emitter for DiffEmitter { fn emit_formatted_file( &mut self, - _output: &mut dyn Write, + output: &mut dyn Write, FormattedFile { filename, original_text, @@ -25,11 +25,86 @@ impl Emitter for DiffEmitter { const CONTEXT_SIZE: usize = 3; let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE); let has_diff = !mismatch.is_empty(); - print_diff( - mismatch, - |line_num| format!("Diff in {} at line {}:", filename, line_num), - &self.config, - ); + + if has_diff { + if self.config.print_misformatted_file_names() { + writeln!(output, "{}", ensure_real_path(filename).display())?; + } else { + print_diff( + mismatch, + |line_num| format!("Diff in {} at line {}:", filename, line_num), + &self.config, + ); + } + } + return Ok(EmitterResult { has_diff }); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::config::Config; + use crate::FileName; + use std::path::PathBuf; + + #[test] + fn does_not_print_when_no_files_reformatted() { + let mut writer = Vec::new(); + let config = Config::default(); + let mut emitter = DiffEmitter::new(config); + let result = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from("src/lib.rs")), + original_text: "fn empty() {}\n", + formatted_text: "fn empty() {}\n", + }, + ) + .unwrap(); + assert_eq!(result.has_diff, false); + assert_eq!(writer.len(), 0); + } + + #[test] + fn prints_file_names_when_config_is_enabled() { + let bin_file = "src/bin.rs"; + let bin_original = "fn main() {\nprintln!(\"Hello, world!\");\n}"; + let bin_formatted = "fn main() {\n println!(\"Hello, world!\");\n}"; + let lib_file = "src/lib.rs"; + let lib_original = "fn greet() {\nprintln!(\"Greetings!\");\n}"; + let lib_formatted = "fn greet() {\n println!(\"Greetings!\");\n}"; + + let mut writer = Vec::new(); + let mut config = Config::default(); + config.set().print_misformatted_file_names(true); + let mut emitter = DiffEmitter::new(config); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(bin_file)), + original_text: bin_original, + formatted_text: bin_formatted, + }, + ) + .unwrap(); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(lib_file)), + original_text: lib_original, + formatted_text: lib_formatted, + }, + ) + .unwrap(); + + assert_eq!( + String::from_utf8(writer).unwrap(), + format!("{}\n{}\n", bin_file, lib_file), + ) + } +} diff --git a/src/emitter/files.rs b/src/emitter/files.rs index 4538a8f4c49..6360b73ee61 100644 --- a/src/emitter/files.rs +++ b/src/emitter/files.rs @@ -2,12 +2,22 @@ use super::*; use std::fs; #[derive(Debug, Default)] -pub(crate) struct FilesEmitter; +pub(crate) struct FilesEmitter { + print_misformatted_file_names: bool, +} + +impl FilesEmitter { + pub(crate) fn new(print_misformatted_file_names: bool) -> Self { + Self { + print_misformatted_file_names, + } + } +} impl Emitter for FilesEmitter { fn emit_formatted_file( &mut self, - _output: &mut dyn Write, + output: &mut dyn Write, FormattedFile { filename, original_text, @@ -18,6 +28,9 @@ impl Emitter for FilesEmitter { let filename = ensure_real_path(filename); if original_text != formatted_text { fs::write(filename, formatted_text)?; + if self.print_misformatted_file_names { + writeln!(output, "{}", filename.display())?; + } } Ok(EmitterResult::default()) } diff --git a/src/lib.rs b/src/lib.rs index 2e43b9d8c7e..31df6b1c72c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -480,7 +480,9 @@ pub(crate) fn create_emitter<'a>(config: &Config) -> Box { EmitMode::Files if config.make_backup() => { Box::new(emitter::FilesWithBackupEmitter::default()) } - EmitMode::Files => Box::new(emitter::FilesEmitter::default()), + EmitMode::Files => Box::new(emitter::FilesEmitter::new( + config.print_misformatted_file_names(), + )), EmitMode::Stdout | EmitMode::Coverage => { Box::new(emitter::StdoutEmitter::new(config.verbose())) } -- cgit 1.4.1-3-g733a5 From 9792ff05297c0a5c40942b346c9b0341b9e7c0ee Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 18 Aug 2019 21:11:35 -0500 Subject: Fix line numbers in checkstyle output (#3694) --- src/emitter/checkstyle.rs | 88 ++++++++++++++++++++++++++++++++++- tests/writemode/target/checkstyle.xml | 2 +- 2 files changed, 87 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs index e8f8ec86cf1..4448214f3ff 100644 --- a/src/emitter/checkstyle.rs +++ b/src/emitter/checkstyle.rs @@ -29,7 +29,7 @@ impl Emitter for CheckstyleEmitter { formatted_text, }: FormattedFile<'_>, ) -> Result { - const CONTEXT_SIZE: usize = 3; + const CONTEXT_SIZE: usize = 0; let filename = ensure_real_path(filename); let diff = make_diff(original_text, formatted_text, CONTEXT_SIZE); output_checkstyle_file(output, filename, diff)?; @@ -47,13 +47,18 @@ where { write!(writer, r#""#, filename.display())?; for mismatch in diff { + let begin_line = mismatch.line_number; + let mut current_line; + let mut line_counter = 0; for line in mismatch.lines { // Do nothing with `DiffLine::Context` and `DiffLine::Resulting`. if let DiffLine::Expected(message) = line { + current_line = begin_line + line_counter; + line_counter += 1; write!( writer, r#""#, - mismatch.line_number, + current_line, XmlEscaped(&message) )?; } @@ -62,3 +67,82 @@ where write!(writer, "")?; Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use std::path::PathBuf; + + #[test] + fn emits_empty_record_on_file_with_no_mismatches() { + let file_name = "src/well_formatted.rs"; + let mut writer = Vec::new(); + let _ = output_checkstyle_file(&mut writer, &PathBuf::from(file_name), vec![]); + assert_eq!( + &writer[..], + format!(r#""#, file_name).as_bytes() + ); + } + + // https://github.com/rust-lang/rustfmt/issues/1636 + #[test] + fn emits_single_xml_tree_containing_all_files() { + let bin_file = "src/bin.rs"; + let bin_original = vec!["fn main() {", "println!(\"Hello, world!\");", "}"]; + let bin_formatted = vec!["fn main() {", " println!(\"Hello, world!\");", "}"]; + let lib_file = "src/lib.rs"; + let lib_original = vec!["fn greet() {", "println!(\"Greetings!\");", "}"]; + let lib_formatted = vec!["fn greet() {", " println!(\"Greetings!\");", "}"]; + let mut writer = Vec::new(); + let mut emitter = CheckstyleEmitter::default(); + let _ = emitter.emit_header(&mut writer); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(bin_file)), + original_text: &bin_original.join("\n"), + formatted_text: &bin_formatted.join("\n"), + }, + ) + .unwrap(); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from(lib_file)), + original_text: &lib_original.join("\n"), + formatted_text: &lib_formatted.join("\n"), + }, + ) + .unwrap(); + let _ = emitter.emit_footer(&mut writer); + let exp_bin_xml = vec![ + format!(r#""#, bin_file), + format!( + r#""#, + XmlEscaped(&r#" println!("Hello, world!");"#), + ), + String::from(""), + ]; + let exp_lib_xml = vec![ + format!(r#""#, lib_file), + format!( + r#""#, + XmlEscaped(&r#" println!("Greetings!");"#), + ), + String::from(""), + ]; + assert_eq!( + String::from_utf8(writer).unwrap(), + vec![ + r#""#, + "\n", + r#""#, + &format!("{}{}", exp_bin_xml.join(""), exp_lib_xml.join("")), + "\n", + ] + .join(""), + ); + } +} diff --git a/tests/writemode/target/checkstyle.xml b/tests/writemode/target/checkstyle.xml index 30ab5ad7579..05bc3a2525d 100644 --- a/tests/writemode/target/checkstyle.xml +++ b/tests/writemode/target/checkstyle.xml @@ -1,2 +1,2 @@ - + -- cgit 1.4.1-3-g733a5 From c26c0e5abf6b7730a6614ee8b448b0018336a285 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 26 Aug 2019 19:27:32 -0500 Subject: feat: add support for --message-format option (#3752) --- src/cargo-fmt/main.rs | 159 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 152 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 410d62673ec..05ce9b5f241 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -45,6 +45,10 @@ pub struct Opts { #[structopt(long = "manifest-path", value_name = "manifest-path")] manifest_path: Option, + /// Specify message-format: short|json|human + #[structopt(long = "message-format", value_name = "message-format")] + message_format: Option, + /// Options passed to rustfmt // 'raw = true' to make `--` explicit. #[structopt(name = "rustfmt_options", raw(raw = "true"))] @@ -100,6 +104,14 @@ fn execute() -> i32 { } let strategy = CargoFmtStrategy::from_opts(&opts); + let mut rustfmt_args = opts.rustfmt_options; + if let Some(message_format) = opts.message_format { + if let Err(msg) = convert_message_format_to_rustfmt_args(&message_format, &mut rustfmt_args) + { + print_usage_to_stderr(&msg); + return FAILURE; + } + } if let Some(specified_manifest_path) = opts.manifest_path { if !specified_manifest_path.ends_with("Cargo.toml") { @@ -110,16 +122,61 @@ fn execute() -> i32 { handle_command_status(format_crate( verbosity, &strategy, - opts.rustfmt_options, + rustfmt_args, Some(&manifest_path), )) } else { - handle_command_status(format_crate( - verbosity, - &strategy, - opts.rustfmt_options, - None, - )) + handle_command_status(format_crate(verbosity, &strategy, rustfmt_args, None)) + } +} + +fn convert_message_format_to_rustfmt_args( + message_format: &str, + rustfmt_args: &mut Vec, +) -> Result<(), String> { + let mut contains_emit_mode = false; + let mut contains_check = false; + let mut contains_list_files = false; + for arg in rustfmt_args.iter() { + if arg.starts_with("--emit") { + contains_emit_mode = true; + } + if arg == "--check" { + contains_check = true; + } + if arg == "-l" || arg == "--files-with-diff" { + contains_list_files = true; + } + } + match message_format { + "short" => { + if !contains_list_files { + rustfmt_args.push(String::from("-l")); + } + Ok(()) + } + "json" => { + if contains_emit_mode { + return Err(String::from( + "cannot include --emit arg when --message-format is set to json", + )); + } + if contains_check { + return Err(String::from( + "cannot include --check arg when --message-format is set to json", + )); + } + rustfmt_args.push(String::from("--emit")); + rustfmt_args.push(String::from("json")); + Ok(()) + } + "human" => Ok(()), + _ => { + return Err(format!( + "invalid --message-format value: {}. Allowed values are: short|json|human", + message_format + )); + } } } @@ -483,6 +540,8 @@ mod cargo_fmt_tests { assert_eq!(empty, o.packages); assert_eq!(empty, o.rustfmt_options); assert_eq!(false, o.format_all); + assert_eq!(None, o.manifest_path); + assert_eq!(None, o.message_format); } #[test] @@ -494,6 +553,8 @@ mod cargo_fmt_tests { "p1", "-p", "p2", + "--message-format", + "short", "--", "--edition", "2018", @@ -504,6 +565,7 @@ mod cargo_fmt_tests { assert_eq!(vec!["p1", "p2"], o.packages); assert_eq!(vec!["--edition", "2018"], o.rustfmt_options); assert_eq!(false, o.format_all); + assert_eq!(Some(String::from("short")), o.message_format); } #[test] @@ -597,4 +659,87 @@ mod cargo_fmt_tests { .is_err() ); } + + mod convert_message_format_to_rustfmt_args_tests { + use super::*; + + #[test] + fn invalid_message_format() { + assert_eq!( + convert_message_format_to_rustfmt_args("awesome", &mut vec![]), + Err(String::from( + "invalid --message-format value: awesome. Allowed values are: short|json|human" + )), + ); + } + + #[test] + fn json_message_format_and_check_arg() { + let mut args = vec![String::from("--check")]; + assert_eq!( + convert_message_format_to_rustfmt_args("json", &mut args), + Err(String::from( + "cannot include --check arg when --message-format is set to json" + )), + ); + } + + #[test] + fn json_message_format_and_emit_arg() { + let mut args = vec![String::from("--emit"), String::from("checkstyle")]; + assert_eq!( + convert_message_format_to_rustfmt_args("json", &mut args), + Err(String::from( + "cannot include --emit arg when --message-format is set to json" + )), + ); + } + + #[test] + fn json_message_format() { + let mut args = vec![String::from("--edition"), String::from("2018")]; + assert!(convert_message_format_to_rustfmt_args("json", &mut args).is_ok()); + assert_eq!( + args, + vec![ + String::from("--edition"), + String::from("2018"), + String::from("--emit"), + String::from("json") + ] + ); + } + + #[test] + fn human_message_format() { + let exp_args = vec![String::from("--emit"), String::from("json")]; + let mut act_args = exp_args.clone(); + assert!(convert_message_format_to_rustfmt_args("human", &mut act_args).is_ok()); + assert_eq!(act_args, exp_args); + } + + #[test] + fn short_message_format() { + let mut args = vec![String::from("--check")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!(args, vec![String::from("--check"), String::from("-l")]); + } + + #[test] + fn short_message_format_included_short_list_files_flag() { + let mut args = vec![String::from("--check"), String::from("-l")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!(args, vec![String::from("--check"), String::from("-l")]); + } + + #[test] + fn short_message_format_included_long_list_files_flag() { + let mut args = vec![String::from("--check"), String::from("--files-with-diff")]; + assert!(convert_message_format_to_rustfmt_args("short", &mut args).is_ok()); + assert_eq!( + args, + vec![String::from("--check"), String::from("--files-with-diff")] + ); + } + } } -- cgit 1.4.1-3-g733a5 From ef00f74ce335e9f050c21a28126602454e78083e Mon Sep 17 00:00:00 2001 From: Valentine Valyaeff Date: Tue, 27 Aug 2019 05:23:55 +0300 Subject: Merge imports fix (#3753) --- src/imports.rs | 69 ++++++++++++++++++++++------------------------ tests/source/issue-3750.rs | 16 +++++++++++ tests/target/issue-3750.rs | 15 ++++++++++ 3 files changed, 64 insertions(+), 36 deletions(-) create mode 100644 tests/source/issue-3750.rs create mode 100644 tests/target/issue-3750.rs (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index a85889884ca..9fd541c61d8 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -573,56 +573,53 @@ impl UseTree { } fn merge(&mut self, other: &UseTree) { - let mut new_path = vec![]; - for (a, b) in self - .path - .clone() - .iter_mut() - .zip(other.path.clone().into_iter()) - { - if *a == b { - new_path.push(b); + let mut prefix = 0; + for (a, b) in self.path.iter().zip(other.path.iter()) { + if *a == *b { + prefix += 1; } else { break; } } - if let Some(merged) = merge_rest(&self.path, &other.path, new_path.len()) { - new_path.push(merged); + if let Some(new_path) = merge_rest(&self.path, &other.path, prefix) { + self.path = new_path; self.span = self.span.to(other.span); } - self.path = new_path; } } -fn merge_rest(a: &[UseSegment], b: &[UseSegment], len: usize) -> Option { - let a_rest = &a[len..]; - let b_rest = &b[len..]; - if a_rest.is_empty() && b_rest.is_empty() { +fn merge_rest(a: &[UseSegment], b: &[UseSegment], mut len: usize) -> Option> { + if a.len() == len && b.len() == len { return None; } - if a_rest.is_empty() { - return Some(UseSegment::List(vec![ - UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), - UseTree::from_path(b_rest.to_vec(), DUMMY_SP), - ])); - } - if b_rest.is_empty() { - return Some(UseSegment::List(vec![ - UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), - UseTree::from_path(a_rest.to_vec(), DUMMY_SP), - ])); - } - if let UseSegment::List(mut list) = a_rest[0].clone() { - merge_use_trees_inner(&mut list, UseTree::from_path(b_rest.to_vec(), DUMMY_SP)); - list.sort(); - return Some(UseSegment::List(list)); + if a.len() != len && b.len() != len { + if let UseSegment::List(mut list) = a[len].clone() { + merge_use_trees_inner(&mut list, UseTree::from_path(b[len..].to_vec(), DUMMY_SP)); + list.sort(); + let mut new_path = b[..len].to_vec(); + new_path.push(UseSegment::List(list)); + return Some(new_path); + } + } else if len == 1 { + let rest = if a.len() == len { &b[1..] } else { &a[1..] }; + return Some(vec![ + b[0].clone(), + UseSegment::List(vec![ + UseTree::from_path(vec![UseSegment::Slf(None)], DUMMY_SP), + UseTree::from_path(rest.to_vec(), DUMMY_SP), + ]), + ]); + } else { + len -= 1; } let mut list = vec![ - UseTree::from_path(a_rest.to_vec(), DUMMY_SP), - UseTree::from_path(b_rest.to_vec(), DUMMY_SP), + UseTree::from_path(a[len..].to_vec(), DUMMY_SP), + UseTree::from_path(b[len..].to_vec(), DUMMY_SP), ]; list.sort(); - Some(UseSegment::List(list)) + let mut new_path = b[..len].to_vec(); + new_path.push(UseSegment::List(list)); + Some(new_path) } impl PartialOrd for UseSegment { @@ -989,7 +986,7 @@ mod test { } test_merge!(["a::b::{c, d}", "a::b::{e, f}"], ["a::b::{c, d, e, f}"]); - test_merge!(["a::b::c", "a::b"], ["a::b::{self, c}"]); + test_merge!(["a::b::c", "a::b"], ["a::{b, b::c}"]); test_merge!(["a::b", "a::b"], ["a::b"]); test_merge!(["a", "a::b", "a::b::c"], ["a::{self, b::{self, c}}"]); test_merge!( diff --git a/tests/source/issue-3750.rs b/tests/source/issue-3750.rs new file mode 100644 index 00000000000..e11d9ab062a --- /dev/null +++ b/tests/source/issue-3750.rs @@ -0,0 +1,16 @@ +// rustfmt-merge_imports: true + +pub mod foo { + pub mod bar { + pub struct Bar; + } + + pub fn bar() {} +} + +use foo::bar; +use foo::bar::Bar; + +fn main() { + bar(); +} diff --git a/tests/target/issue-3750.rs b/tests/target/issue-3750.rs new file mode 100644 index 00000000000..93d4dc6df25 --- /dev/null +++ b/tests/target/issue-3750.rs @@ -0,0 +1,15 @@ +// rustfmt-merge_imports: true + +pub mod foo { + pub mod bar { + pub struct Bar; + } + + pub fn bar() {} +} + +use foo::{bar, bar::Bar}; + +fn main() { + bar(); +} -- cgit 1.4.1-3-g733a5 From a09ca681def98dcde966f5fe1f6c0af3bd8956ba Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Wed, 28 Aug 2019 20:50:02 +0900 Subject: fix the bug removing attrs (#3760) --- src/patterns.rs | 57 +++++++++++++++++++++++++++++++++++----------- tests/target/issue-3759.rs | 27 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 tests/target/issue-3759.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index b5032eca6d5..a0493be0f1c 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -2,7 +2,7 @@ use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSynt use syntax::ptr; use syntax::source_map::{self, BytePos, Span}; -use crate::comment::FindUncommented; +use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ @@ -179,7 +179,13 @@ fn rewrite_struct_pat( fields.iter(), terminator, ",", - |f| f.span.lo(), + |f| { + if f.node.attrs.is_empty() { + f.span.lo() + } else { + f.node.attrs.first().unwrap().span.lo() + } + }, |f| f.span.hi(), |f| f.node.rewrite(context, v_shape), context.snippet_provider.span_after(span, "{"), @@ -225,25 +231,50 @@ fn rewrite_struct_pat( impl Rewrite for FieldPat { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let pat = self.pat.rewrite(context, shape); + let hi_pos = if let Some(last) = self.attrs.last() { + last.span.hi() + } else { + self.pat.span.lo() + }; + + let attrs_str = if self.attrs.is_empty() { + String::from("") + } else { + self.attrs.rewrite(context, shape)? + }; + + let pat_str = self.pat.rewrite(context, shape)?; if self.is_shorthand { - pat + combine_strs_with_missing_comments( + context, + &attrs_str, + &pat_str, + mk_sp(hi_pos, self.pat.span.lo()), + shape, + false, + ) } else { - let pat_str = pat?; + let nested_shape = shape.block_indent(context.config.tab_spaces()); let id_str = rewrite_ident(context, self.ident); let one_line_width = id_str.len() + 2 + pat_str.len(); - if one_line_width <= shape.width { - Some(format!("{}: {}", id_str, pat_str)) + let pat_and_id_str = if one_line_width <= shape.width { + format!("{}: {}", id_str, pat_str) } else { - let nested_shape = shape.block_indent(context.config.tab_spaces()); - let pat_str = self.pat.rewrite(context, nested_shape)?; - Some(format!( + format!( "{}:\n{}{}", id_str, nested_shape.indent.to_string(context.config), - pat_str, - )) - } + self.pat.rewrite(context, nested_shape)? + ) + }; + combine_strs_with_missing_comments( + context, + &attrs_str, + &pat_and_id_str, + mk_sp(hi_pos, self.pat.span.lo()), + nested_shape, + false, + ) } } } diff --git a/tests/target/issue-3759.rs b/tests/target/issue-3759.rs new file mode 100644 index 00000000000..b53f5391a34 --- /dev/null +++ b/tests/target/issue-3759.rs @@ -0,0 +1,27 @@ +fn main() { + let Test { + #[cfg(feature = "test")] + x, + } = Test { + #[cfg(feature = "test")] + x: 1, + }; + + let Test { + #[cfg(feature = "test")] + // comment + x, + } = Test { + #[cfg(feature = "test")] + x: 1, + }; + + let Test { + // comment + #[cfg(feature = "test")] + x, + } = Test { + #[cfg(feature = "test")] + x: 1, + }; +} -- cgit 1.4.1-3-g733a5 From deb329a6bb1e6d2976cacd25333abdc976c1090d Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 28 Aug 2019 20:50:41 +0900 Subject: Forbid adding or removing a block from match arms inside macro calls (#3756) --- src/matches.rs | 38 +++++++++++++++++++++----------------- tests/source/macros.rs | 9 +++++++++ tests/target/macros.rs | 8 ++++++++ 3 files changed, 38 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index b7a1c374323..3cc7c45409f 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -278,6 +278,7 @@ fn block_can_be_flattened<'a>( match expr.node { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) + && !context.inside_macro() && is_simple_block(block, Some(&expr.attrs), context.source_map) => { Some(&*block) @@ -394,25 +395,26 @@ fn rewrite_match_body( } let indent_str = shape.indent.to_string_with_newline(context.config); - let (body_prefix, body_suffix) = if context.config.match_arm_blocks() { - let comma = if context.config.match_block_trailing_comma() { - "," - } else { - "" - }; - let semicolon = if context.config.version() == Version::One { - "" - } else { - if semicolon_for_expr(context, body) { - ";" + let (body_prefix, body_suffix) = + if context.config.match_arm_blocks() && !context.inside_macro() { + let comma = if context.config.match_block_trailing_comma() { + "," } else { "" - } + }; + let semicolon = if context.config.version() == Version::One { + "" + } else { + if semicolon_for_expr(context, body) { + ";" + } else { + "" + } + }; + ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) + } else { + ("", String::from(",")) }; - ("{", format!("{}{}}}{}", semicolon, indent_str, comma)) - } else { - ("", String::from(",")) - }; let block_sep = match context.config.control_brace_style() { ControlBraceStyle::AlwaysNextLine => format!("{}{}", alt_block_sep, body_prefix), @@ -468,7 +470,9 @@ fn rewrite_match_body( next_line_body_shape.width, ); match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) if orig_str == next_line_str => { + (Some(ref orig_str), Some(ref next_line_str)) + if orig_str == next_line_str || context.inside_macro() => + { combine_orig_body(orig_str) } (Some(ref orig_str), Some(ref next_line_str)) diff --git a/tests/source/macros.rs b/tests/source/macros.rs index e5013634234..3b286579ca8 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -473,5 +473,14 @@ pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { // #3463 x ! {()} +// #3746 +f!(match a { + 4 => + &[ + (3, false), // Missing + (4, true) // I-frame + ] [..], +}); + // #3583 foo!(|x = y|); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index a2406787461..e930b5037d9 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1050,5 +1050,13 @@ pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { // #3463 x! {()} +// #3746 +f!(match a { + 4 => &[ + (3, false), // Missing + (4, true) // I-frame + ][..], +}); + // #3583 foo!(|x = y|); -- cgit 1.4.1-3-g733a5 From ad5d9fba9b6d5482e504e4996e2aea54defb9ed6 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 2 Sep 2019 04:36:51 -0500 Subject: fix formatting mods inside cfg_if macro (#3763) --- src/modules.rs | 11 +++++++++-- src/modules/visitor.rs | 24 +++++++++++++++++++++--- src/test/mod.rs | 3 +++ tests/source/issue-3253/bar.rs | 4 ++++ tests/source/issue-3253/foo.rs | 6 ++++++ tests/source/issue-3253/lib.rs | 14 ++++++++++++++ tests/source/issue-3253/paths/bar_foo.rs | 3 +++ tests/source/issue-3253/paths/excluded.rs | 6 ++++++ tests/source/issue-3253/paths/foo_bar.rs | 4 ++++ tests/target/issue-3253/bar.rs | 2 ++ tests/target/issue-3253/foo.rs | 3 +++ tests/target/issue-3253/lib.rs | 14 ++++++++++++++ tests/target/issue-3253/paths/bar_foo.rs | 3 +++ tests/target/issue-3253/paths/excluded.rs | 17 +++++++++++++++++ tests/target/issue-3253/paths/foo_bar.rs | 5 +++++ 15 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 tests/source/issue-3253/bar.rs create mode 100644 tests/source/issue-3253/foo.rs create mode 100644 tests/source/issue-3253/lib.rs create mode 100644 tests/source/issue-3253/paths/bar_foo.rs create mode 100644 tests/source/issue-3253/paths/excluded.rs create mode 100644 tests/source/issue-3253/paths/foo_bar.rs create mode 100644 tests/target/issue-3253/bar.rs create mode 100644 tests/target/issue-3253/foo.rs create mode 100644 tests/target/issue-3253/lib.rs create mode 100644 tests/target/issue-3253/paths/bar_foo.rs create mode 100644 tests/target/issue-3253/paths/excluded.rs create mode 100644 tests/target/issue-3253/paths/foo_bar.rs (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 5f7e4310a07..655d17d47a0 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -105,7 +105,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.node { - self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod(&module_item.item, Cow::Owned(sub_mod.clone()))?; } } Ok(()) @@ -477,7 +477,14 @@ fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResu fn is_cfg_if(item: &ast::Item) -> bool { match item.node { - ast::ItemKind::Mac(..) if item.ident.name == Symbol::intern("cfg_if") => true, + ast::ItemKind::Mac(ref mac) => { + if let Some(first_segment) = mac.node.path.segments.first() { + if first_segment.ident.name == Symbol::intern("cfg_if") { + return true; + } + } + false + } _ => false, } } diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 3eb2e05b2d7..48b56d4d102 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -43,9 +43,27 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CfgIfVisitor<'a> { impl<'a, 'ast: 'a> CfgIfVisitor<'a> { fn visit_mac_inner(&mut self, mac: &'ast ast::Mac) -> Result<(), &'static str> { - if mac.node.path != Symbol::intern("cfg_if") { - return Err("Expected cfg_if"); - } + // Support both: + // ``` + // extern crate cfg_if; + // cfg_if::cfg_if! {..} + // ``` + // And: + // ``` + // #[macro_use] + // extern crate cfg_if; + // cfg_if! {..} + // ``` + match mac.node.path.segments.first() { + Some(first_segment) => { + if first_segment.ident.name != Symbol::intern("cfg_if") { + return Err("Expected cfg_if"); + } + } + None => { + return Err("Expected cfg_if"); + } + }; let mut parser = stream_to_parser_with_base_dir( self.parse_sess, diff --git a/src/test/mod.rs b/src/test/mod.rs index bd6613e1488..3793a98ab00 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -30,6 +30,9 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ // These files and directory are a part of modules defined inside `cfg_if!`. "cfg_if/mod.rs", "cfg_if/detect", + "issue-3253/foo.rs", + "issue-3253/bar.rs", + "issue-3253/paths", // These files and directory are a part of modules defined inside `cfg_attr(..)`. "cfg_mod/dir", "cfg_mod/bar.rs", diff --git a/tests/source/issue-3253/bar.rs b/tests/source/issue-3253/bar.rs new file mode 100644 index 00000000000..eaeffd3ad00 --- /dev/null +++ b/tests/source/issue-3253/bar.rs @@ -0,0 +1,4 @@ +// Empty + fn empty() { + +} diff --git a/tests/source/issue-3253/foo.rs b/tests/source/issue-3253/foo.rs new file mode 100644 index 00000000000..4ebe5326b3c --- /dev/null +++ b/tests/source/issue-3253/foo.rs @@ -0,0 +1,6 @@ +pub fn hello( ) + { +println!("Hello World!"); + + } + diff --git a/tests/source/issue-3253/lib.rs b/tests/source/issue-3253/lib.rs new file mode 100644 index 00000000000..3eef586bd67 --- /dev/null +++ b/tests/source/issue-3253/lib.rs @@ -0,0 +1,14 @@ +#[macro_use] +extern crate cfg_if; + +cfg_if! { + if #[cfg(target_family = "unix")] { + mod foo; + #[path = "paths/bar_foo.rs"] + mod bar_foo; + } else { + mod bar; + #[path = "paths/foo_bar.rs"] + mod foo_bar; + } +} diff --git a/tests/source/issue-3253/paths/bar_foo.rs b/tests/source/issue-3253/paths/bar_foo.rs new file mode 100644 index 00000000000..da19f9dfaa1 --- /dev/null +++ b/tests/source/issue-3253/paths/bar_foo.rs @@ -0,0 +1,3 @@ +fn foo_decl_item(x: &mut i32) { + x = 3; +} diff --git a/tests/source/issue-3253/paths/excluded.rs b/tests/source/issue-3253/paths/excluded.rs new file mode 100644 index 00000000000..5c63eb83203 --- /dev/null +++ b/tests/source/issue-3253/paths/excluded.rs @@ -0,0 +1,6 @@ +// This module is not imported in the cfg_if macro in lib.rs so it is ignored +// while the foo and bar mods are formatted. +// Check the corresponding file in tests/target/issue-3253/paths/excluded.rs +trait CoolerTypes { fn dummy(&self) { +} +} diff --git a/tests/source/issue-3253/paths/foo_bar.rs b/tests/source/issue-3253/paths/foo_bar.rs new file mode 100644 index 00000000000..fbb5d92c6e3 --- /dev/null +++ b/tests/source/issue-3253/paths/foo_bar.rs @@ -0,0 +1,4 @@ + + +fn Foo() where T: Bar { +} diff --git a/tests/target/issue-3253/bar.rs b/tests/target/issue-3253/bar.rs new file mode 100644 index 00000000000..6c6ab945b88 --- /dev/null +++ b/tests/target/issue-3253/bar.rs @@ -0,0 +1,2 @@ +// Empty +fn empty() {} diff --git a/tests/target/issue-3253/foo.rs b/tests/target/issue-3253/foo.rs new file mode 100644 index 00000000000..1a42a10159e --- /dev/null +++ b/tests/target/issue-3253/foo.rs @@ -0,0 +1,3 @@ +pub fn hello() { + println!("Hello World!"); +} diff --git a/tests/target/issue-3253/lib.rs b/tests/target/issue-3253/lib.rs new file mode 100644 index 00000000000..3eef586bd67 --- /dev/null +++ b/tests/target/issue-3253/lib.rs @@ -0,0 +1,14 @@ +#[macro_use] +extern crate cfg_if; + +cfg_if! { + if #[cfg(target_family = "unix")] { + mod foo; + #[path = "paths/bar_foo.rs"] + mod bar_foo; + } else { + mod bar; + #[path = "paths/foo_bar.rs"] + mod foo_bar; + } +} diff --git a/tests/target/issue-3253/paths/bar_foo.rs b/tests/target/issue-3253/paths/bar_foo.rs new file mode 100644 index 00000000000..f7e1de29a30 --- /dev/null +++ b/tests/target/issue-3253/paths/bar_foo.rs @@ -0,0 +1,3 @@ +fn foo_decl_item(x: &mut i32) { + x = 3; +} diff --git a/tests/target/issue-3253/paths/excluded.rs b/tests/target/issue-3253/paths/excluded.rs new file mode 100644 index 00000000000..9ab88414d46 --- /dev/null +++ b/tests/target/issue-3253/paths/excluded.rs @@ -0,0 +1,17 @@ +// This module is not imported in the cfg_if macro in lib.rs so it is ignored +// while the foo and bar mods are formatted. +// Check the corresponding file in tests/source/issue-3253/paths/excluded.rs + + + + + fn Foo() where T: Bar { +} + + + +trait CoolerTypes { fn dummy(&self) { +} +} + + diff --git a/tests/target/issue-3253/paths/foo_bar.rs b/tests/target/issue-3253/paths/foo_bar.rs new file mode 100644 index 00000000000..f52ac11b739 --- /dev/null +++ b/tests/target/issue-3253/paths/foo_bar.rs @@ -0,0 +1,5 @@ +fn Foo() +where + T: Bar, +{ +} -- cgit 1.4.1-3-g733a5 From 2bf67b6e5ca48479e5de9a14c49bd385d3d8285c Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Wed, 4 Sep 2019 23:00:26 +0900 Subject: fix TrailingWhitespace when using line breaks in macros arguments (#3768) --- src/formatting.rs | 4 ++-- src/macros.rs | 5 +++++ src/rewrite.rs | 2 ++ src/visitor.rs | 8 +++++--- tests/target/issue-2916.rs | 2 ++ 5 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 tests/target/issue-2916.rs (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index ee44549b2bc..b58911705c0 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -188,7 +188,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { format_lines( &mut visitor.buffer, &path, - &visitor.skipped_range, + &visitor.skipped_range.borrow(), &self.config, &self.report, ); @@ -203,7 +203,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { self.report.add_macro_format_failure(); } self.report - .add_non_formatted_ranges(visitor.skipped_range.clone()); + .add_non_formatted_ranges(visitor.skipped_range.borrow().clone()); self.handler.handle_formatted_file( self.parse_session.source_map(), diff --git a/src/macros.rs b/src/macros.rs index de8e0651cd8..583844f1c5d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -181,6 +181,11 @@ fn return_macro_parse_failure_fallback( return trim_left_preserve_layout(context.snippet(span), indent, &context.config); } + context.skipped_range.borrow_mut().push(( + context.source_map.lookup_line(span.lo()).unwrap().line, + context.source_map.lookup_line(span.hi()).unwrap().line, + )); + // Return the snippet unmodified if the macro is not block-like Some(context.snippet(span).to_owned()) } diff --git a/src/rewrite.rs b/src/rewrite.rs index 606aafc9ebd..6f79cb14c60 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -1,6 +1,7 @@ // A generic trait to abstract the rewriting of an element (of the AST). use std::cell::RefCell; +use std::rc::Rc; use syntax::parse::ParseSess; use syntax::ptr; @@ -41,6 +42,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) macro_rewrite_failure: RefCell, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, + pub(crate) skipped_range: Rc>>, } impl<'a> RewriteContext<'a> { diff --git a/src/visitor.rs b/src/visitor.rs index 58a94b12dfd..10c4e88756f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::rc::Rc; use syntax::parse::ParseSess; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; @@ -65,7 +66,7 @@ pub(crate) struct FmtVisitor<'a> { pub(crate) line_number: usize, /// List of 1-based line ranges which were annotated with skip /// Both bounds are inclusifs. - pub(crate) skipped_range: Vec<(usize, usize)>, + pub(crate) skipped_range: Rc>>, pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, @@ -652,7 +653,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let lo = std::cmp::min(attrs_end + 1, first_line); self.push_rewrite_inner(item_span, None); let hi = self.line_number + 1; - self.skipped_range.push((lo, hi)); + self.skipped_range.borrow_mut().push((lo, hi)); } pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { @@ -684,7 +685,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { is_if_else_block: false, snippet_provider, line_number: 0, - skipped_range: vec![], + skipped_range: Rc::new(RefCell::new(vec![])), macro_rewrite_failure: false, report, skip_context: Default::default(), @@ -877,6 +878,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { macro_rewrite_failure: RefCell::new(false), report: self.report.clone(), skip_context: self.skip_context.clone(), + skipped_range: self.skipped_range.clone(), } } } diff --git a/tests/target/issue-2916.rs b/tests/target/issue-2916.rs new file mode 100644 index 00000000000..5a6471ca863 --- /dev/null +++ b/tests/target/issue-2916.rs @@ -0,0 +1,2 @@ +a_macro!(name, +); -- cgit 1.4.1-3-g733a5 From 950b288d6fa3179d9a19c6762125be7fbc7c66e8 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 4 Sep 2019 17:01:04 +0300 Subject: do not remove discriminant value if exists (#3771) (#3772) --- src/items.rs | 32 ++++++++++++++------------------ tests/source/enum.rs | 8 ++++++++ tests/target/enum.rs | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index bdae2eaafc6..0943122b090 100644 --- a/src/items.rs +++ b/src/items.rs @@ -557,24 +557,20 @@ impl<'a> FmtVisitor<'a> { self.block_indent, Some(one_line_width), )?, - ast::VariantData::Unit(..) => { - if let Some(ref expr) = field.node.disr_expr { - let lhs = format!( - "{:1$} =", - rewrite_ident(&context, field.node.ident), - pad_discrim_ident_to - ); - rewrite_assign_rhs_with( - &context, - lhs, - &*expr.value, - shape, - RhsTactics::AllowOverflow, - )? - } else { - rewrite_ident(&context, field.node.ident).to_owned() - } - } + ast::VariantData::Unit(..) => rewrite_ident(&context, field.node.ident).to_owned(), + }; + + let variant_body = if let Some(ref expr) = field.node.disr_expr { + let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to); + rewrite_assign_rhs_with( + &context, + lhs, + &*expr.value, + shape, + RhsTactics::AllowOverflow, + )? + } else { + variant_body }; combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) diff --git a/tests/source/enum.rs b/tests/source/enum.rs index fd563206ae5..0ed9651abe7 100644 --- a/tests/source/enum.rs +++ b/tests/source/enum.rs @@ -202,3 +202,11 @@ enum PublishedFileVisibility { FriendsOnly = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityFriendsOnly, Private = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPrivate, } + +// #3771 +//#![feature(arbitrary_enum_discriminant)] +#[repr(u32)] +pub enum E { + A { a: u32 } = 0x100, + B { field1: u32, field2: u8, field3: m::M } = 0x300 // comment +} diff --git a/tests/target/enum.rs b/tests/target/enum.rs index 6af05cbed90..9a25126b44e 100644 --- a/tests/target/enum.rs +++ b/tests/target/enum.rs @@ -273,3 +273,17 @@ enum PublishedFileVisibility { Private = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPrivate, } + +// #3771 +//#![feature(arbitrary_enum_discriminant)] +#[repr(u32)] +pub enum E { + A { + a: u32, + } = 0x100, + B { + field1: u32, + field2: u8, + field3: m::M, + } = 0x300, // comment +} -- cgit 1.4.1-3-g733a5 From 15a28f79b8fc16f28aab5f7cc45b3e14ff7f7e47 Mon Sep 17 00:00:00 2001 From: Valentine Valyaeff Date: Wed, 4 Sep 2019 17:02:10 +0300 Subject: Another fix for `merge_imports` (#3769) --- src/imports.rs | 45 +++++++++++++++------- tests/target/configs/imports_layout/merge_mixed.rs | 5 +-- 2 files changed, 32 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 9fd541c61d8..61a359a498b 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -166,23 +166,16 @@ pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { } for flattened in use_tree.flatten() { - merge_use_trees_inner(&mut result, flattened); + if let Some(tree) = result.iter_mut().find(|tree| tree.share_prefix(&flattened)) { + tree.merge(&flattened); + } else { + result.push(flattened); + } } } result } -fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree) { - for tree in trees.iter_mut() { - if tree.share_prefix(&use_tree) { - tree.merge(&use_tree); - return; - } - } - - trees.push(use_tree); -} - impl fmt::Debug for UseTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) @@ -595,7 +588,6 @@ fn merge_rest(a: &[UseSegment], b: &[UseSegment], mut len: usize) -> Option Option, use_tree: UseTree) { + let similar_trees = trees.iter_mut().filter(|tree| tree.share_prefix(&use_tree)); + if use_tree.path.len() == 1 { + if let Some(tree) = similar_trees.min_by_key(|tree| tree.path.len()) { + if tree.path.len() == 1 { + return; + } + } + } else { + if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { + if tree.path.len() > 1 { + tree.merge(&use_tree); + return; + } + } + } + trees.push(use_tree); + trees.sort(); +} + impl PartialOrd for UseSegment { fn partial_cmp(&self, other: &UseSegment) -> Option { Some(self.cmp(other)) @@ -988,7 +1000,12 @@ mod test { test_merge!(["a::b::{c, d}", "a::b::{e, f}"], ["a::b::{c, d, e, f}"]); test_merge!(["a::b::c", "a::b"], ["a::{b, b::c}"]); test_merge!(["a::b", "a::b"], ["a::b"]); - test_merge!(["a", "a::b", "a::b::c"], ["a::{self, b::{self, c}}"]); + test_merge!(["a", "a::b", "a::b::c"], ["a::{self, b, b::c}"]); + test_merge!( + ["a", "a::b", "a::b::c", "a::b::c::d"], + ["a::{self, b, b::{c, c::d}}"] + ); + test_merge!(["a", "a::b", "a::b::c", "a::b"], ["a::{self, b, b::c}"]); test_merge!( ["a::{b::{self, c}, d::e}", "a::d::f"], ["a::{b::{self, c}, d::{e, f}}"] diff --git a/tests/target/configs/imports_layout/merge_mixed.rs b/tests/target/configs/imports_layout/merge_mixed.rs index 415a11211a1..2200d7dec6d 100644 --- a/tests/target/configs/imports_layout/merge_mixed.rs +++ b/tests/target/configs/imports_layout/merge_mixed.rs @@ -2,7 +2,4 @@ // rustfmt-merge_imports: true // rustfmt-imports_layout: Mixed -use std::{ - fmt, io, - str::{self, FromStr}, -}; +use std::{fmt, io, str, str::FromStr}; -- cgit 1.4.1-3-g733a5 From e81ec20af061d3a58216d4f23c20da87358d0d8a Mon Sep 17 00:00:00 2001 From: CreepySkeleton Date: Thu, 5 Sep 2019 05:15:19 +0300 Subject: Add --config command line option (#3767) --- config_proc_macro/src/item_enum.rs | 7 ++++++- src/bin/main.rs | 35 +++++++++++++++++++++++++++++++++++ src/config/config_type.rs | 10 ++++++++++ tests/rustfmt/main.rs | 34 +++++++++++++++++++++++++++++----- 4 files changed, 80 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/config_proc_macro/src/item_enum.rs b/config_proc_macro/src/item_enum.rs index d59c87d77bf..dcee77a8549 100644 --- a/config_proc_macro/src/item_enum.rs +++ b/config_proc_macro/src/item_enum.rs @@ -105,13 +105,18 @@ fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream { } } }); + let mut err_msg = String::from("Bad variant, expected one of:"); + for v in variants.iter().filter(|v| is_unit(v)) { + err_msg.push_str(&format!(" `{}`", v.ident)); + } + quote! { impl ::std::str::FromStr for #ident { type Err = &'static str; fn from_str(s: &str) -> Result { #if_patterns - return Err("Bad variant"); + return Err(#err_msg); } } } diff --git a/src/bin/main.rs b/src/bin/main.rs index bb12169329a..7290c2f30d5 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -4,6 +4,7 @@ use io::Error as IoError; use rustfmt_nightly as rustfmt; +use std::collections::HashMap; use std::env; use std::fs::File; use std::io::{self, stdout, Read, Write}; @@ -132,6 +133,12 @@ fn make_opts() -> Options { "Prints the names of mismatched files that were formatted. Prints the names of \ files that would be formated when used with `--check` mode. ", ); + opts.optmulti( + "", + "config", + "Set options from command line. These settings take priority over .rustfmt.toml", + "[key1=val1,key2=val2...]", + ); if is_nightly { opts.optflag( @@ -478,6 +485,7 @@ struct GetOptsOptions { quiet: bool, verbose: bool, config_path: Option, + inline_config: HashMap, emit_mode: EmitMode, backup: bool, check: bool, @@ -537,6 +545,29 @@ impl GetOptsOptions { options.config_path = matches.opt_str("config-path").map(PathBuf::from); + options.inline_config = matches + .opt_strs("config") + .iter() + .flat_map(|config| config.split(",")) + .map( + |key_val| match key_val.char_indices().find(|(_, ch)| *ch == '=') { + Some((middle, _)) => { + let (key, val) = (&key_val[..middle], &key_val[middle + 1..]); + if !Config::is_valid_key_val(key, val) { + Err(format_err!("invalid key=val pair: `{}`", key_val)) + } else { + Ok((key.to_string(), val.to_string())) + } + } + + None => Err(format_err!( + "--config expects comma-separated list of key=val pairs, found `{}`", + key_val + )), + }, + ) + .collect::, _>>()?; + options.check = matches.opt_present("check"); if let Some(ref emit_str) = matches.opt_str("emit") { if options.check { @@ -624,6 +655,10 @@ impl CliOptions for GetOptsOptions { if self.print_misformatted_file_names { config.set().print_misformatted_file_names(true); } + + for (key, val) in self.inline_config { + config.override_value(&key, &val); + } } fn config_path(&self) -> Option<&Path> { diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 7b91f54877d..7f7e8905fba 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -178,6 +178,16 @@ macro_rules! create_config { } } + #[allow(unreachable_pub)] + pub fn is_valid_key_val(key: &str, val: &str) -> bool { + match key { + $( + stringify!($i) => val.parse::<$ty>().is_ok(), + )+ + _ => false, + } + } + #[allow(unreachable_pub)] pub fn used_options(&self) -> PartialConfig { PartialConfig { diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 18ef9b60963..ccf2db120b3 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -30,17 +30,16 @@ fn rustfmt(args: &[&str]) -> (String, String) { } macro_rules! assert_that { - ($args:expr, $check:ident $check_args:tt) => { + ($args:expr, $($check:ident $check_args:tt)&&+) => { let (stdout, stderr) = rustfmt($args); - if !stdout.$check$check_args && !stderr.$check$check_args { + if $(!stdout.$check$check_args && !stderr.$check$check_args)||* { panic!( "Output not expected for rustfmt {:?}\n\ - expected: {}{}\n\ + expected: {}\n\ actual stdout:\n{}\n\ actual stderr:\n{}", $args, - stringify!($check), - stringify!($check_args), + stringify!($( $check$check_args )&&*), stdout, stderr ); @@ -76,3 +75,28 @@ fn print_config() { ); remove_file("minimal-config").unwrap(); } + +#[ignore] +#[test] +fn inline_config() { + // single invocation + assert_that!( + &[ + "--print-config", + "current", + ".", + "--config=color=Never,edition=2018" + ], + contains("color = \"Never\"") && contains("edition = \"2018\"") + ); + + // multiple overriding invocations + assert_that!( + &["--print-config", "current", ".", + "--config", "color=never,edition=2018", + "--config", "color=always,format_strings=true"], + contains("color = \"Always\"") && + contains("edition = \"2018\"") && + contains("format_strings = true") + ); +} -- cgit 1.4.1-3-g733a5 From 783948fcbbf9c30b810b702b0b73a227359a6804 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Thu, 5 Sep 2019 11:15:46 +0900 Subject: Fix handling of match arm's rewrite (#3775) --- src/macros.rs | 33 +++++++++++---------------------- src/matches.rs | 12 +++++------- src/rewrite.rs | 31 ++++++++++++++++++++++++++++++- src/visitor.rs | 2 +- tests/source/match.rs | 19 +++++++++++++++++++ tests/target/match.rs | 29 +++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 583844f1c5d..dfc27c5fa5a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -190,24 +190,6 @@ fn return_macro_parse_failure_fallback( Some(context.snippet(span).to_owned()) } -struct InsideMacroGuard<'a> { - context: &'a RewriteContext<'a>, - is_nested: bool, -} - -impl<'a> InsideMacroGuard<'a> { - fn inside_macro_context(context: &'a RewriteContext<'_>) -> InsideMacroGuard<'a> { - let is_nested = context.inside_macro.replace(true); - InsideMacroGuard { context, is_nested } - } -} - -impl<'a> Drop for InsideMacroGuard<'a> { - fn drop(&mut self) { - self.context.inside_macro.replace(self.is_nested); - } -} - pub(crate) fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, @@ -221,9 +203,16 @@ pub(crate) fn rewrite_macro( if should_skip { None } else { - let guard = InsideMacroGuard::inside_macro_context(context); + let guard = context.enter_macro(); let result = catch_unwind(AssertUnwindSafe(|| { - rewrite_macro_inner(mac, extra_ident, context, shape, position, guard.is_nested) + rewrite_macro_inner( + mac, + extra_ident, + context, + shape, + position, + guard.is_nested(), + ) })); match result { Err(..) | Ok(None) => { @@ -263,7 +252,7 @@ fn rewrite_macro_inner( ) -> Option { if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { - context.inside_macro.replace(false); + context.leave_macro(); return expr.rewrite(context, shape); } } @@ -412,7 +401,7 @@ fn rewrite_macro_inner( Some(SeparatorTactic::Never) }; if FORCED_BRACKET_MACROS.contains(macro_name) && !is_nested_macro { - context.inside_macro.replace(false); + context.leave_macro(); if context.use_block_indent() { force_trailing_comma = Some(SeparatorTactic::Vertical); }; diff --git a/src/matches.rs b/src/matches.rs index 3cc7c45409f..b608faded9e 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -19,7 +19,7 @@ use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - ptr_vec_to_ref_vec, semicolon_for_expr, trimmed_last_line_width, + ptr_vec_to_ref_vec, semicolon_for_expr, trimmed_last_line_width, unicode_str_width, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. @@ -452,7 +452,9 @@ fn rewrite_match_body( match rewrite { Some(ref body_str) - if is_block || (!body_str.contains('\n') && body_str.len() <= body_shape.width) => + if is_block + || (!body_str.contains('\n') + && unicode_str_width(body_str) <= body_shape.width) => { return combine_orig_body(body_str); } @@ -470,11 +472,6 @@ fn rewrite_match_body( next_line_body_shape.width, ); match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) - if orig_str == next_line_str || context.inside_macro() => - { - combine_orig_body(orig_str) - } (Some(ref orig_str), Some(ref next_line_str)) if prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { @@ -575,6 +572,7 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) + | ast::ExprKind::Index(ref expr, _) | ast::ExprKind::Cast(ref expr, _) => can_flatten_block_around_this(expr), _ => false, } diff --git a/src/rewrite.rs b/src/rewrite.rs index 6f79cb14c60..19b749dc8e1 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -29,7 +29,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) parse_session: &'a ParseSess, pub(crate) source_map: &'a SourceMap, pub(crate) config: &'a Config, - pub(crate) inside_macro: RefCell, + pub(crate) inside_macro: Rc>, // Force block indent style even if we are using visual indent style. pub(crate) use_block: RefCell, // When `is_if_else_block` is true, unindent the comment on top @@ -45,6 +45,23 @@ pub(crate) struct RewriteContext<'a> { pub(crate) skipped_range: Rc>>, } +pub(crate) struct InsideMacroGuard { + is_nested_macro_context: bool, + inside_macro_ref: Rc>, +} + +impl InsideMacroGuard { + pub(crate) fn is_nested(&self) -> bool { + self.is_nested_macro_context + } +} + +impl Drop for InsideMacroGuard { + fn drop(&mut self) { + self.inside_macro_ref.replace(self.is_nested_macro_context); + } +} + impl<'a> RewriteContext<'a> { pub(crate) fn snippet(&self, span: Span) -> &str { self.snippet_provider.span_to_snippet(span).unwrap() @@ -63,6 +80,18 @@ impl<'a> RewriteContext<'a> { *self.inside_macro.borrow() } + pub(crate) fn enter_macro(&self) -> InsideMacroGuard { + let is_nested_macro_context = self.inside_macro.replace(true); + InsideMacroGuard { + is_nested_macro_context, + inside_macro_ref: self.inside_macro.clone(), + } + } + + pub(crate) fn leave_macro(&self) { + self.inside_macro.replace(false); + } + pub(crate) fn is_if_else_block(&self) -> bool { *self.is_if_else_block.borrow() } diff --git a/src/visitor.rs b/src/visitor.rs index 10c4e88756f..074ee37d104 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -870,7 +870,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { parse_session: self.parse_session, source_map: self.source_map, config: self.config, - inside_macro: RefCell::new(false), + inside_macro: Rc::new(RefCell::new(false)), use_block: RefCell::new(false), is_if_else_block: RefCell::new(false), force_one_line_chain: RefCell::new(false), diff --git a/tests/source/match.rs b/tests/source/match.rs index b226d60b7c6..f54082f92eb 100644 --- a/tests/source/match.rs +++ b/tests/source/match.rs @@ -549,3 +549,22 @@ fn issue_3005() { }, } } + +// #3774 +fn issue_3774() { + { + { + { + match foo { + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreachab(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreacha!(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreachabl(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreachae!(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreachable(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreachable!(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => rrunreachable!(), + } + } + } + } +} diff --git a/tests/target/match.rs b/tests/target/match.rs index 78bcd2aa053..92abda9752e 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -574,3 +574,32 @@ fn issue_3005() { } } } + +// #3774 +fn issue_3774() { + { + { + { + match foo { + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreachab(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => unreacha!(), + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => { + unreachabl() + } + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => { + unreachae!() + } + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => { + unreachable() + } + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => { + unreachable!() + } + Lam(_, _, _) | Pi(_, _, _) | Let(_, _, _, _) | Embed(_) | Var(_) => { + rrunreachable!() + } + } + } + } + } +} -- cgit 1.4.1-3-g733a5 From 1ded995ee79c44069b7832e5aba00162fc2113fa Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Thu, 5 Sep 2019 19:38:00 +0900 Subject: fix 'left behind trailing whitespace' (#3761) --- src/visitor.rs | 2 +- tests/target/issue-3741.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-3741.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 074ee37d104..dec39489a5e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -623,7 +623,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_str(s); } else { let snippet = self.snippet(span); - self.push_str(snippet); + self.push_str(snippet.trim()); } self.last_pos = source!(self, span).hi(); } diff --git a/tests/target/issue-3741.rs b/tests/target/issue-3741.rs new file mode 100644 index 00000000000..34d22dc91eb --- /dev/null +++ b/tests/target/issue-3741.rs @@ -0,0 +1,5 @@ +pub enum PublishedFileVisibility { + Public = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPublic as i32, + FriendsOnly = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityFriendsOnly as i32, + Private = sys::ERemoteStoragePublishedFileVisibility_k_ERemoteStoragePublishedFileVisibilityPrivate as i32, +} -- cgit 1.4.1-3-g733a5 From 5baba86fe554424e8a58e3f1a3f29c258fce3296 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 6 Sep 2019 22:41:03 +0900 Subject: Update rustc-ap-* crates to 581.0.0 (#3783) --- Cargo.lock | 129 ++++++++++++++++++++++++++------------- Cargo.toml | 6 +- src/attr.rs | 2 +- src/expr.rs | 4 +- src/items.rs | 92 ++++++++++++++++++---------- src/macros.rs | 15 +++-- src/modules.rs | 4 +- src/modules/visitor.rs | 9 +-- src/patterns.rs | 41 ++++++++++--- src/spanned.rs | 2 +- src/utils.rs | 4 +- src/visitor.rs | 29 ++++++--- tests/source/existential_type.rs | 12 ++-- tests/source/issue-2863.rs | 4 +- tests/target/existential_type.rs | 12 ++-- tests/target/issue-2863.rs | 4 +- 16 files changed, 235 insertions(+), 134 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 260613753c9..9dcc509bba9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,6 +396,15 @@ dependencies = [ "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "1.3.0" @@ -691,21 +700,21 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_data_structures" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -716,8 +725,8 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -727,27 +736,31 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-ap-rustc_macros" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,19 +772,19 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -780,33 +793,33 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "546.0.0" +version = "581.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -886,9 +899,9 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.1.2", "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1042,6 +1055,16 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "term_size" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termcolor" version = "1.0.5" @@ -1094,6 +1117,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -1119,6 +1147,11 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.7" @@ -1128,6 +1161,11 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1203,6 +1241,7 @@ dependencies = [ "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" @@ -1238,16 +1277,16 @@ dependencies = [ "checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" "checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" "checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" -"checksum rustc-ap-arena 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc2e1e68b64268c543bfa6e63e3c0d9ea58074c71396f42f76931f35a9287f9" -"checksum rustc-ap-graphviz 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c108d647ce0dd46477b048eafff5a6273b5652e02d47424b0cd684147379c811" -"checksum rustc-ap-rustc_data_structures 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656771744e0783cb8e4481e3b8b1f975687610aaf18833b898018111a0e0e582" -"checksum rustc-ap-rustc_errors 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e37064f6624bc799bfaa2968b61ee6880926dea2a8bba69f18aef6c8e69c9604" -"checksum rustc-ap-rustc_lexer 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef5bc0a971823637ea23a857f0ef1467f44b1e05d71968821f83a0abe53e0fe3" -"checksum rustc-ap-rustc_macros 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b90037e3336fe8835f468db44d0848ae10d9cc8533ae89b55828883f905b7e80" -"checksum rustc-ap-rustc_target 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cadf9ca07315eab3a7a21f63872f9cc81e250fd6ede0419c24f8926ade73a45d" -"checksum rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602" -"checksum rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84" -"checksum rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979" +"checksum rustc-ap-arena 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4efec6ece174df54e4605c3c229b5a8885355f9f8988cabbc24aa99dbc27f27" +"checksum rustc-ap-graphviz 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b01d685fc49fb05676a8829c7a9fa1759c441f1430384c32c8b42462409535f3" +"checksum rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e43082631e0b3782c216d02d7d86a221b58834a1b3ba2b686aa84309bd65ed9" +"checksum rustc-ap-rustc_errors 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ad386fc563e7e5ab47d78eaf2ee37d430e1e6c0ca67a23df70fdee9c4bdf673" +"checksum rustc-ap-rustc_lexer 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3820240b53041ee8932c866aaf9c877e3a55af31a2f5c333077b853e9bed2ac" +"checksum rustc-ap-rustc_macros 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b0931fe770efb7bc659e1900ef80d7bc8efeb4a36af94c5a89bea9e0230989" +"checksum rustc-ap-rustc_target 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a3d9de9e308ba21add5f92bc2dfd014f3ea06932df7ba10ac23c83c0c9bc03" +"checksum rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9f98141be65d2cc0bc8eb11e89bda9d4cec9ddf69dd46120c8f3840f9b5adc" +"checksum rustc-ap-syntax 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5643c677373d8fa1f19c93ce7b42f5628818964d4d3d7dc6ac191b2b6170e91b" +"checksum rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1508b6dc46181580787b30876bc8cc1c76ca5851aec05d08e0065cd16c635736" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" @@ -1273,6 +1312,7 @@ dependencies = [ "checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd90505d5006a4422d3520b30c781d480b3f36768c2fa2187c3e950bc110464" +"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -1281,11 +1321,14 @@ dependencies = [ "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 3c623ff4edc..27cf07c1332 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,9 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -rustc-ap-rustc_target = "546.0.0" -rustc-ap-syntax = "546.0.0" -rustc-ap-syntax_pos = "546.0.0" +rustc-ap-rustc_target = "581.0.0" +rustc-ap-syntax = "581.0.0" +rustc-ap-syntax_pos = "581.0.0" failure = "0.1.3" bytecount = "0.5" unicode-width = "0.1.5" diff --git a/src/attr.rs b/src/attr.rs index 1c9092ea629..7270215ccbb 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -340,7 +340,7 @@ impl Rewrite for ast::Attribute { let literal_str = literal.as_str(); let doc_comment_formatter = - DocCommentFormatter::new(literal_str.get(), comment_style); + DocCommentFormatter::new(&*literal_str, comment_style); let doc_comment = format!("{}", doc_comment_formatter); return rewrite_doc_comment( &doc_comment, diff --git a/src/expr.rs b/src/expr.rs index 9030d876b40..02bf1fa20e4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1316,8 +1316,8 @@ pub(crate) fn can_be_overflowed_expr( context.config.overflow_delimited_expr() || (context.use_block_indent() && args_len == 1) } - ast::ExprKind::Mac(ref macro_) => { - match (macro_.node.delim, context.config.overflow_delimited_expr()) { + ast::ExprKind::Mac(ref mac) => { + match (mac.delim, context.config.overflow_delimited_expr()) { (ast::MacDelimiter::Bracket, true) | (ast::MacDelimiter::Brace, true) => true, _ => context.use_block_indent() && args_len == 1, } diff --git a/src/items.rs b/src/items.rs index 0943122b090..613f9b5b729 100644 --- a/src/items.rs +++ b/src/items.rs @@ -473,8 +473,8 @@ impl<'a> FmtVisitor<'a> { let discr_ident_lens: Vec = enum_def .variants .iter() - .filter(|var| var.node.disr_expr.is_some()) - .map(|var| rewrite_ident(&self.get_context(), var.node.ident).len()) + .filter(|var| var.disr_expr.is_some()) + .map(|var| rewrite_ident(&self.get_context(), var.ident).len()) .collect(); // cut the list at the point of longest discrim shorter than the threshold // All of the discrims under the threshold will get padded, and all above - left as is. @@ -491,8 +491,8 @@ impl<'a> FmtVisitor<'a> { "}", ",", |f| { - if !f.node.attrs.is_empty() { - f.node.attrs[0].span.lo() + if !f.attrs.is_empty() { + f.attrs[0].span.lo() } else { f.span.lo() } @@ -533,8 +533,8 @@ impl<'a> FmtVisitor<'a> { one_line_width: usize, pad_discrim_ident_to: usize, ) -> Option { - if contains_skip(&field.node.attrs) { - let lo = field.node.attrs[0].span.lo(); + if contains_skip(&field.attrs) { + let lo = field.attrs[0].span.lo(); let span = mk_sp(lo, field.span.hi()); return Some(self.snippet(span).to_owned()); } @@ -542,25 +542,24 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); // 1 = ',' let shape = self.shape().sub_width(1)?; - let attrs_str = field.node.attrs.rewrite(&context, shape)?; + let attrs_str = field.attrs.rewrite(&context, shape)?; let lo = field - .node .attrs .last() .map_or(field.span.lo(), |attr| attr.span.hi()); let span = mk_sp(lo, field.span.lo()); - let variant_body = match field.node.data { + let variant_body = match field.data { ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct( &context, &StructParts::from_variant(field), self.block_indent, Some(one_line_width), )?, - ast::VariantData::Unit(..) => rewrite_ident(&context, field.node.ident).to_owned(), + ast::VariantData::Unit(..) => rewrite_ident(&context, field.ident).to_owned(), }; - let variant_body = if let Some(ref expr) = field.node.disr_expr { + let variant_body = if let Some(ref expr) = field.disr_expr { let lhs = format!("{:1$} =", variant_body, pad_discrim_ident_to); rewrite_assign_rhs_with( &context, @@ -585,27 +584,27 @@ impl<'a> FmtVisitor<'a> { buffer.push((self.buffer.clone(), item.clone())); self.buffer.clear(); } - // type -> existential -> const -> macro -> method + // type -> opaque -> const -> macro -> method use crate::ast::ImplItemKind::*; fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { match (a, b) { - (Type(..), Type(..)) + (TyAlias(..), TyAlias(..)) | (Const(..), Const(..)) - | (Existential(..), Existential(..)) => false, + | (OpaqueTy(..), OpaqueTy(..)) => false, _ => true, } } buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { - (Type(..), Type(..)) + (TyAlias(..), TyAlias(..)) | (Const(..), Const(..)) | (Macro(..), Macro(..)) - | (Existential(..), Existential(..)) => a.ident.as_str().cmp(&b.ident.as_str()), + | (OpaqueTy(..), OpaqueTy(..)) => a.ident.as_str().cmp(&b.ident.as_str()), (Method(..), Method(..)) => a.span.lo().cmp(&b.span.lo()), - (Type(..), _) => Ordering::Less, - (_, Type(..)) => Ordering::Greater, - (Existential(..), _) => Ordering::Less, - (_, Existential(..)) => Ordering::Greater, + (TyAlias(..), _) => Ordering::Less, + (_, TyAlias(..)) => Ordering::Greater, + (OpaqueTy(..), _) => Ordering::Less, + (_, OpaqueTy(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, (_, Const(..)) => Ordering::Greater, (Macro(..), _) => Ordering::Less, @@ -920,9 +919,9 @@ impl<'a> StructParts<'a> { fn from_variant(variant: &'a ast::Variant) -> Self { StructParts { prefix: "", - ident: variant.node.ident, + ident: variant.ident, vis: &DEFAULT_VISIBILITY, - def: &variant.node.data, + def: &variant.data, generics: None, span: variant.span, } @@ -1517,7 +1516,7 @@ pub(crate) fn rewrite_type_alias( rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis) } -pub(crate) fn rewrite_existential_type( +pub(crate) fn rewrite_opaque_type( context: &RewriteContext<'_>, indent: Indent, ident: ast::Ident, @@ -1528,8 +1527,8 @@ pub(crate) fn rewrite_existential_type( rewrite_type_item( context, indent, - "existential type", - ":", + "type", + " =", ident, generic_bounds, generics, @@ -1786,15 +1785,42 @@ pub(crate) fn rewrite_associated_type( } } -pub(crate) fn rewrite_existential_impl_type( +struct OpaqueType<'a> { + bounds: &'a ast::GenericBounds, +} + +impl<'a> Rewrite for OpaqueType<'a> { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + let shape = shape.offset_left(5)?; // `impl ` + self.bounds + .rewrite(context, shape) + .map(|s| format!("impl {}", s)) + } +} + +pub(crate) fn rewrite_opaque_impl_type( context: &RewriteContext<'_>, ident: ast::Ident, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, indent: Indent, ) -> Option { - rewrite_associated_type(ident, None, generics, Some(generic_bounds), context, indent) - .map(|s| format!("existential {}", s)) + let ident_str = rewrite_ident(context, ident); + // 5 = "type " + let generics_shape = Shape::indented(indent, context.config).offset_left(5)?; + let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?; + let prefix = format!("type {} =", generics_str); + let rhs = OpaqueType { + bounds: generic_bounds, + }; + + rewrite_assign_rhs( + context, + &prefix, + &rhs, + Shape::indented(indent, context.config).sub_width(1)?, + ) + .map(|s| s + ";") } pub(crate) fn rewrite_associated_impl_type( @@ -1877,7 +1903,7 @@ fn get_missing_arg_comments( (comment_before_colon, comment_after_colon) } -impl Rewrite for ast::Arg { +impl Rewrite for ast::Param { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if let Some(ref explicit_self) = self.to_self() { rewrite_explicit_self(context, explicit_self) @@ -1941,7 +1967,7 @@ fn rewrite_explicit_self( } } -pub(crate) fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { +pub(crate) fn span_lo_for_arg(arg: &ast::Param) -> BytePos { if is_named_arg(arg) { arg.pat.span.lo() } else { @@ -1949,7 +1975,7 @@ pub(crate) fn span_lo_for_arg(arg: &ast::Arg) -> BytePos { } } -pub(crate) fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> BytePos { +pub(crate) fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Param) -> BytePos { match arg.ty.node { ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), @@ -1957,7 +1983,7 @@ pub(crate) fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Arg) -> B } } -pub(crate) fn is_named_arg(arg: &ast::Arg) -> bool { +pub(crate) fn is_named_arg(arg: &ast::Param) -> bool { if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { ident.name != symbol::kw::Invalid } else { @@ -2349,7 +2375,7 @@ impl WhereClauseOption { fn rewrite_args( context: &RewriteContext<'_>, - args: &[ast::Arg], + args: &[ast::Param], one_line_budget: usize, multi_line_budget: usize, indent: Indent, diff --git a/src/macros.rs b/src/macros.rs index dfc27c5fa5a..08f83b7e826 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -199,7 +199,7 @@ pub(crate) fn rewrite_macro( ) -> Option { let should_skip = context .skip_context - .skip_macro(&context.snippet(mac.node.path.span).to_owned()); + .skip_macro(&context.snippet(mac.path.span).to_owned()); if should_skip { None } else { @@ -235,7 +235,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { { parser.bump(); let macro_arg = - MacroArg::Keyword(ast::Ident::with_empty_ctxt(keyword), parser.prev_span); + MacroArg::Keyword(ast::Ident::with_dummy_span(keyword), parser.prev_span); return Some(macro_arg); } } @@ -259,7 +259,7 @@ fn rewrite_macro_inner( let original_style = macro_style(mac, context); - let macro_name = rewrite_macro_name(context, &mac.node.path, extra_ident); + let macro_name = rewrite_macro_name(context, &mac.path, extra_ident); let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) && !is_nested_macro { DelimToken::Bracket @@ -267,7 +267,7 @@ fn rewrite_macro_inner( original_style }; - let ts: TokenStream = mac.node.stream(); + let ts: TokenStream = mac.stream(); let has_comment = contains_comment(context.snippet(mac.span)); if ts.is_empty() && !has_comment { return match style { @@ -1190,8 +1190,8 @@ fn next_space(tok: &TokenKind) -> SpaceState { /// when the macro is not an instance of `try!` (or parsing the inner expression /// failed). pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { - if &mac.node.path.to_string() == "try" { - let ts: TokenStream = mac.node.tts.clone(); + if &mac.path.to_string() == "try" { + let ts: TokenStream = mac.tts.clone(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); Some(ast::Expr { @@ -1532,7 +1532,7 @@ fn rewrite_macro_with_items( Some(result) } -const RUST_KW: [Symbol; 60] = [ +const RUST_KW: [Symbol; 59] = [ kw::PathRoot, kw::DollarCrate, kw::Underscore, @@ -1591,6 +1591,5 @@ const RUST_KW: [Symbol; 60] = [ kw::Auto, kw::Catch, kw::Default, - kw::Existential, kw::Union, ]; diff --git a/src/modules.rs b/src/modules.rs index 655d17d47a0..0c1ea008f68 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -442,7 +442,7 @@ fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Ve } TokenKind::DocComment(s) => { // we need to get the position of this token before we bump. - let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, parser.token.span); + let attr = attr::mk_sugared_doc_attr(s, parser.token.span); if attr.style == ast::AttrStyle::Inner { attrs.push(attr); parser.bump(); @@ -478,7 +478,7 @@ fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResu fn is_cfg_if(item: &ast::Item) -> bool { match item.node { ast::ItemKind::Mac(ref mac) => { - if let Some(first_segment) = mac.node.path.segments.first() { + if let Some(first_segment) = mac.path.segments.first() { if first_segment.ident.name == Symbol::intern("cfg_if") { return true; } diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 48b56d4d102..34b7e346334 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -54,7 +54,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { // extern crate cfg_if; // cfg_if! {..} // ``` - match mac.node.path.segments.first() { + match mac.path.segments.first() { Some(first_segment) => { if first_segment.ident.name != Symbol::intern("cfg_if") { return Err("Expected cfg_if"); @@ -65,11 +65,8 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } }; - let mut parser = stream_to_parser_with_base_dir( - self.parse_sess, - mac.node.tts.clone(), - self.base_dir.clone(), - ); + let mut parser = + stream_to_parser_with_base_dir(self.parse_sess, mac.tts.clone(), self.base_dir.clone()); parser.cfg_mods = false; let mut process_if_cfg = true; diff --git a/src/patterns.rs b/src/patterns.rs index a0493be0f1c..96d45c6ac55 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,13 +1,13 @@ use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; use syntax::ptr; -use syntax::source_map::{self, BytePos, Span}; +use syntax::source_map::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ - itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, - write_list, + definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, + struct_lit_tactic, write_list, ListFormatting, Separator, }; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; @@ -51,12 +51,39 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) | ast::PatKind::Paren(ref p) => { is_short_pattern_inner(&*p) } + PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(p)), } } impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.node { + PatKind::Or(ref pats) => { + let pat_items = itemize_list( + context.snippet_provider, + pats.iter(), + "", + "|", + |pat| pat.span().lo(), + |pat| pat.span().hi(), + |pat| pat.rewrite(context, shape), + self.span.lo(), + self.span.hi(), + false, + ); + let pat_vec: Vec<_> = pat_items.collect(); + let tactic = definitive_tactic( + &pat_vec, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + shape.width, + ); + let fmt = ListFormatting::new(shape, context.config) + .tactic(tactic) + .trailing_separator(SeparatorTactic::Never) + .separator(" |"); + write_list(&pat_vec, &fmt) + } PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { @@ -154,7 +181,7 @@ impl Rewrite for Pat { fn rewrite_struct_pat( path: &ast::Path, - fields: &[source_map::Spanned], + fields: &[ast::FieldPat], ellipsis: bool, span: Span, context: &RewriteContext<'_>, @@ -180,14 +207,14 @@ fn rewrite_struct_pat( terminator, ",", |f| { - if f.node.attrs.is_empty() { + if f.attrs.is_empty() { f.span.lo() } else { - f.node.attrs.first().unwrap().span.lo() + f.attrs.first().unwrap().span.lo() } }, |f| f.span.hi(), - |f| f.node.rewrite(context, v_shape), + |f| f.rewrite(context, v_shape), context.snippet_provider.span_after(span, "{"), span.hi(), false, diff --git a/src/spanned.rs b/src/spanned.rs index 00dd24a0f06..bbdee6ccf4b 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -104,7 +104,7 @@ impl Spanned for ast::Arm { } } -impl Spanned for ast::Arg { +impl Spanned for ast::Param { fn span(&self) -> Span { if crate::items::is_named_arg(self) { mk_sp(self.pat.span.lo(), self.ty.span.hi()) diff --git a/src/utils.rs b/src/utils.rs index 498608d4179..5b0d94e4780 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,7 +8,7 @@ use syntax::ast::{ VisibilityKind, }; use syntax::ptr; -use syntax::source_map::{BytePos, Span, NO_EXPANSION}; +use syntax::source_map::{BytePos, Span, SyntaxContext}; use syntax::symbol::{sym, Symbol}; use syntax_pos::ExpnId; use unicode_width::UnicodeWidthStr; @@ -335,7 +335,7 @@ macro_rules! source { } pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span { - Span::new(lo, hi, NO_EXPANSION) + Span::new(lo, hi, SyntaxContext::root()) } // Returns `true` if the given span does not intersect with file lines. diff --git a/src/visitor.rs b/src/visitor.rs index dec39489a5e..831fd56819f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,8 +11,8 @@ use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type, - rewrite_existential_type, rewrite_extern_crate, rewrite_type_alias, FnBraceStyle, FnSig, + rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, + rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, }; use crate::macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; @@ -97,11 +97,20 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &Stmt<'_>) { debug!( - "visit_stmt: {:?} {:?}", + "visit_stmt: {:?} {:?} `{}`", self.source_map.lookup_char_pos(stmt.span().lo()), - self.source_map.lookup_char_pos(stmt.span().hi()) + self.source_map.lookup_char_pos(stmt.span().hi()), + self.snippet(stmt.span()), ); + // https://github.com/rust-lang/rust/issues/63679. + let is_all_semicolons = + |snippet: &str| snippet.chars().all(|c| c.is_whitespace() || c == ';'); + if is_all_semicolons(&self.snippet(stmt.span())) { + self.last_pos = stmt.span().hi(); + return; + } + match stmt.as_ast_node().node { ast::StmtKind::Item(ref item) => { self.visit_item(item); @@ -468,7 +477,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(&inner_attrs), ) } - ast::ItemKind::Ty(ref ty, ref generics) => { + ast::ItemKind::TyAlias(ref ty, ref generics) => { let rewrite = rewrite_type_alias( &self.get_context(), self.block_indent, @@ -479,8 +488,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } - ast::ItemKind::Existential(ref generic_bounds, ref generics) => { - let rewrite = rewrite_existential_type( + ast::ItemKind::OpaqueTy(ref generic_bounds, ref generics) => { + let rewrite = rewrite_opaque_type( &self.get_context(), self.block_indent, item.ident, @@ -576,7 +585,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::ImplItemKind::Type(ref ty) => { + ast::ImplItemKind::TyAlias(ref ty) => { let rewrite = rewrite_associated_impl_type( ii.ident, ii.defaultness, @@ -587,8 +596,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(ii.span, rewrite); } - ast::ImplItemKind::Existential(ref generic_bounds) => { - let rewrite = rewrite_existential_impl_type( + ast::ImplItemKind::OpaqueTy(ref generic_bounds) => { + let rewrite = rewrite_opaque_impl_type( &self.get_context(), ii.ident, &ii.generics, diff --git a/tests/source/existential_type.rs b/tests/source/existential_type.rs index cbffbd99fd8..92412fca879 100644 --- a/tests/source/existential_type.rs +++ b/tests/source/existential_type.rs @@ -1,15 +1,15 @@ -// Existential type. +// Opaque type. - #![feature(existential_type)] + #![feature(type_alias_impl_trait)] -pub existential type Adder +pub type Adder where T: Clone, F: Copy - : Fn(T) -> T; + = impl Fn(T) -> T; -pub existential type Adderrr: Fn( T ) -> T; +pub type Adderrr = impl Fn( T ) -> T; impl Foo for Bar { -existential type E : Trait; +type E = impl Trait; } diff --git a/tests/source/issue-2863.rs b/tests/source/issue-2863.rs index 792ffdbac24..1bda857be76 100644 --- a/tests/source/issue-2863.rs +++ b/tests/source/issue-2863.rs @@ -1,7 +1,7 @@ // rustfmt-reorder_impl_items: true impl IntoIterator for SafeVec { - existential type F: Trait; + type F = impl Trait; type IntoIter = self::IntoIter; type Item = T; // comment on foo() @@ -19,7 +19,7 @@ impl IntoIterator for SafeVec { fn foo6() {println!("hello, world");} fn foo7() {println!("hello, world");} type BarFoo = u32; - existential type E: Trait; + type E = impl Trait; const AnotherConst: i32 = 100; fn foo8() {println!("hello, world");} } diff --git a/tests/target/existential_type.rs b/tests/target/existential_type.rs index 806220502e0..869ffda2378 100644 --- a/tests/target/existential_type.rs +++ b/tests/target/existential_type.rs @@ -1,15 +1,15 @@ -// Existential type. +// Opaque type. -#![feature(existential_type)] +#![feature(type_alias_impl_trait)] -pub existential type Adder +pub type Adder where T: Clone, F: Copy, -: Fn(T) -> T; += Fn(T) -> T; -pub existential type Adderrr: Fn(T) -> T; +pub type Adderrr = Fn(T) -> T; impl Foo for Bar { - existential type E: Trait; + type E = impl Trait; } diff --git a/tests/target/issue-2863.rs b/tests/target/issue-2863.rs index a53628e3ea9..35a80f7a621 100644 --- a/tests/target/issue-2863.rs +++ b/tests/target/issue-2863.rs @@ -9,8 +9,8 @@ impl IntoIterator for SafeVec { type IntoIter = self::IntoIter; type Item = T; - existential type E: Trait; - existential type F: Trait; + type E = impl Trait; + type F = impl Trait; const AnotherConst: i32 = 100; const SomeConst: i32 = 100; -- cgit 1.4.1-3-g733a5 From ceca01465a0fe06749b3ac80ae52095f999e495a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 8 Sep 2019 23:33:21 +0900 Subject: Update deps (#3788) --- Cargo.lock | 612 ++++++++++++++++++++--------------------- Cargo.toml | 13 +- config_proc_macro/Cargo.lock | 50 ++-- config_proc_macro/Cargo.toml | 8 +- config_proc_macro/src/attrs.rs | 10 +- src/cargo-fmt/main.rs | 3 +- src/config/options.rs | 6 +- src/expr.rs | 90 ++---- src/format-diff/main.rs | 8 +- src/matches.rs | 15 +- src/patterns.rs | 48 ++-- src/rustfmt_diff.rs | 2 - src/spanned.rs | 2 +- src/utils.rs | 2 - 14 files changed, 401 insertions(+), 468 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 6609a4df3dd..9228acf7ee1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -21,17 +21,13 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "argon2rs" -version = "0.2.5" +name = "arrayref" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "arrayvec" @@ -46,24 +42,24 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.33" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -71,8 +67,16 @@ name = "backtrace-sys" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -81,17 +85,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "blake2-rfc" -version = "0.2.18" +name = "blake2b_simd" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bstr" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -99,7 +104,7 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -110,30 +115,20 @@ name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "c2-chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cargo_metadata" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.38" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -151,7 +146,7 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -165,7 +160,7 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -193,7 +188,7 @@ dependencies = [ "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -213,17 +208,17 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "derive-new" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -233,22 +228,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "dirs" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dirs-sys" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -261,7 +256,7 @@ name = "ena" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -271,8 +266,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -281,7 +276,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -292,7 +287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -308,19 +303,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.19" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.6" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -328,11 +324,11 @@ name = "globset" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -353,15 +349,15 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -370,7 +366,7 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -388,12 +384,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jobserver" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -407,15 +403,12 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -429,7 +422,7 @@ dependencies = [ [[package]] name = "log" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -455,7 +448,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -488,17 +481,22 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ppv-lite86" -version = "0.2.5" +name = "proc-macro-error" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "proc-macro2" @@ -508,6 +506,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -521,34 +527,30 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -556,40 +558,23 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rand_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_hc" version = "0.1.0" @@ -598,14 +583,6 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_isaac" version = "0.1.1" @@ -619,9 +596,9 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -631,10 +608,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -642,8 +619,8 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,64 +646,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redox_users" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.10" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rust-argon2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-arena" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_data_structures" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -736,23 +719,23 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -760,73 +743,73 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "581.0.0" +version = "583.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -853,8 +836,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -873,11 +856,11 @@ dependencies = [ [[package]] name = "rustfmt-config_proc_macro" -version = "0.1.2" +version = "0.2.0" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -885,32 +868,31 @@ name = "rustfmt-nightly" version = "1.4.7" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-config_proc_macro 0.1.2", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-config_proc_macro 0.2.0", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -932,11 +914,6 @@ name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "0.3.3" @@ -948,7 +925,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -958,20 +935,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -981,7 +958,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -989,11 +966,6 @@ name = "smallvec" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "spin" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1006,27 +978,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.2.18" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.2.18" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.42" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1034,6 +1007,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.2" @@ -1041,18 +1024,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1061,7 +1043,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1070,7 +1052,7 @@ name = "termcolor" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1078,7 +1060,7 @@ name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1086,22 +1068,17 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ucd-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "unicode-segmentation" version = "1.3.0" @@ -1109,7 +1086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1127,11 +1104,6 @@ name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "utf8-ranges" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "vec_map" version = "0.8.1" @@ -1143,10 +1115,15 @@ version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -1154,7 +1131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1176,7 +1153,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1186,44 +1163,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wincolor" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" -"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" -"checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c" +"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cargo_metadata 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e904f164f39cae0c3a4f2713eb97a47ba64676a071e99a69ddfef4994694d2c" -"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" +"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" +"checksum cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "a61c7bce55cd2fae6ec8cb935ebd76256c2959a1f95790f6118a441c2cd5b406" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum derive-new 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd04571b29c91cfbe1e7c9a228e069ac8635f180ffb4ccd6a6907617ee8bb0" +"checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1" -"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d" +"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" @@ -1231,21 +1208,21 @@ dependencies = [ "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450" -"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" +"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum ignore 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c794c4736d7751238cc5f74f6a3a2a59698074672fe403620d53fecfd72e5d87" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum ignore 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0ec16832258409d571aaef8273f3c3cc5b060d784e159d1a0f3b0017308f84a7" +"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jobserver 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "f74e73053eaf95399bf926e48fc7a2a3ce50bd0eaaa2357d391e95b2dcdd4f10" +"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" @@ -1254,19 +1231,17 @@ dependencies = [ "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" @@ -1274,20 +1249,21 @@ dependencies = [ "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" -"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" -"checksum rustc-ap-arena 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4efec6ece174df54e4605c3c229b5a8885355f9f8988cabbc24aa99dbc27f27" -"checksum rustc-ap-graphviz 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b01d685fc49fb05676a8829c7a9fa1759c441f1430384c32c8b42462409535f3" -"checksum rustc-ap-rustc_data_structures 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e43082631e0b3782c216d02d7d86a221b58834a1b3ba2b686aa84309bd65ed9" -"checksum rustc-ap-rustc_errors 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ad386fc563e7e5ab47d78eaf2ee37d430e1e6c0ca67a23df70fdee9c4bdf673" -"checksum rustc-ap-rustc_lexer 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3820240b53041ee8932c866aaf9c877e3a55af31a2f5c333077b853e9bed2ac" -"checksum rustc-ap-rustc_macros 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b0931fe770efb7bc659e1900ef80d7bc8efeb4a36af94c5a89bea9e0230989" -"checksum rustc-ap-rustc_target 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a3d9de9e308ba21add5f92bc2dfd014f3ea06932df7ba10ac23c83c0c9bc03" -"checksum rustc-ap-serialize 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9f98141be65d2cc0bc8eb11e89bda9d4cec9ddf69dd46120c8f3840f9b5adc" -"checksum rustc-ap-syntax 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5643c677373d8fa1f19c93ce7b42f5628818964d4d3d7dc6ac191b2b6170e91b" -"checksum rustc-ap-syntax_pos 581.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1508b6dc46181580787b30876bc8cc1c76ca5851aec05d08e0065cd16c635736" -"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" +"checksum rustc-ap-arena 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5" +"checksum rustc-ap-graphviz 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142" +"checksum rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36" +"checksum rustc-ap-rustc_errors 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333" +"checksum rustc-ap-rustc_lexer 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305" +"checksum rustc-ap-rustc_macros 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f" +"checksum rustc-ap-rustc_target 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2" +"checksum rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6" +"checksum rustc-ap-syntax 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9" +"checksum rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" "checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" @@ -1296,40 +1272,38 @@ dependencies = [ "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72" -"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" -"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" -"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" +"checksum structopt 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ac9d6e93dd792b217bf89cda5c14566e3043960c6f9da890c2ba5d09d07804c" +"checksum structopt-derive 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ae9e5165d463a0dea76967d021f8d0f9316057bf5163aa2a4843790e842ff37" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum term 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd90505d5006a4422d3520b30c781d480b3f36768c2fa2187c3e950bc110464" +"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" "checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039" -"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" +"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" diff --git a/Cargo.toml b/Cargo.toml index 50ee8a01d94..72eea003542 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,6 @@ rustfmt-format-diff = [] generic-simd = ["bytecount/generic-simd"] [dependencies] -atty = "0.2" itertools = "0.8" toml = "0.5" serde = { version = "1.0", features = ["derive"] } @@ -48,19 +47,19 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -rustc-ap-rustc_target = "581.0.0" -rustc-ap-syntax = "581.0.0" -rustc-ap-syntax_pos = "581.0.0" +rustc-ap-rustc_target = "583.0.0" +rustc-ap-syntax = "583.0.0" +rustc-ap-syntax_pos = "583.0.0" failure = "0.1.3" -bytecount = "0.5" +bytecount = "0.6" unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "2.0.1" ignore = "0.4.6" annotate-snippets = { version = "0.6", features = ["ansi_term"] } -structopt = "0.2.18" +structopt = "0.3" -rustfmt-config_proc_macro = { version = "0.1.2", path = "config_proc_macro" } +rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/config_proc_macro/Cargo.lock b/config_proc_macro/Cargo.lock index fa855b3140b..abcf9654e5d 100644 --- a/config_proc_macro/Cargo.lock +++ b/config_proc_macro/Cargo.lock @@ -2,67 +2,67 @@ # It is not intended for manual editing. [[package]] name = "proc-macro2" -version = "0.4.27" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "quote" -version = "0.6.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustfmt-config_proc_macro" version = "0.1.2" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.89" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.89" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "0.15.29" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-xid" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" -"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" -"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/config_proc_macro/Cargo.toml b/config_proc_macro/Cargo.toml index a2eb782e272..cc995571602 100644 --- a/config_proc_macro/Cargo.toml +++ b/config_proc_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfmt-config_proc_macro" -version = "0.1.2" +version = "0.2.0" authors = ["topecongiro "] edition = "2018" description = "A collection of procedural macros for rustfmt" @@ -12,9 +12,9 @@ repository = "https://github.com/rust-lang/rustfmt" proc-macro = true [dependencies] -proc-macro2 = "0.4" -quote = "0.6" -syn = { version = "0.15", features = ["full", "visit"] } +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "1.0", features = ["full", "visit"] } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index 0df68772ae6..0baba046f9e 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -39,19 +39,19 @@ pub fn is_config_value(attr: &syn::Attribute) -> bool { } fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool { - attr.interpret_meta().map_or(false, |meta| match meta { - syn::Meta::NameValue(syn::MetaNameValue { ref ident, .. }) if ident == name => true, + attr.parse_meta().ok().map_or(false, |meta| match meta { + syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident(name) => true, _ => false, }) } fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option { - attr.interpret_meta().and_then(|meta| match meta { + attr.parse_meta().ok().and_then(|meta| match meta { syn::Meta::NameValue(syn::MetaNameValue { - ref ident, + ref path, lit: syn::Lit::Str(ref lit_str), .. - }) if ident == name => Some(lit_str.value()), + }) if path.is_ident(name) => Some(lit_str.value()), _ => None, }) } diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 05ce9b5f241..c06df111566 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -20,7 +20,6 @@ use structopt::StructOpt; #[derive(StructOpt, Debug)] #[structopt( bin_name = "cargo fmt", - author = "", about = "This utility formats all bin and lib files of \ the current crate using rustfmt." )] @@ -51,7 +50,7 @@ pub struct Opts { /// Options passed to rustfmt // 'raw = true' to make `--` explicit. - #[structopt(name = "rustfmt_options", raw(raw = "true"))] + #[structopt(name = "rustfmt_options", raw(true))] rustfmt_options: Vec, /// Format all packages (only usable in workspaces) diff --git a/src/config/options.rs b/src/config/options.rs index d2063650ccb..4a136f4b180 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -2,7 +2,6 @@ use std::collections::{hash_set, HashSet}; use std::fmt; use std::path::{Path, PathBuf}; -use atty; use itertools::Itertools; use rustfmt_config_proc_macro::config_type; use serde::de::{SeqAccess, Visitor}; @@ -147,7 +146,7 @@ pub enum Color { pub enum Version { /// 1.x.y. When specified, rustfmt will format in the same style as 1.0.0. One, - /// 2.x.y. When specified, rustfmt will formatin the the latest style. + /// 2.x.y. When specified, rustfmt will format in the the latest style. Two, } @@ -155,9 +154,8 @@ impl Color { /// Whether we should use a coloured terminal. pub fn use_colored_tty(self) -> bool { match self { - Color::Always => true, + Color::Always | Color::Auto => true, Color::Never => false, - Color::Auto => atty::is(atty::Stream::Stdout), } } } diff --git a/src/expr.rs b/src/expr.rs index 02bf1fa20e4..36d7b91d102 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -16,13 +16,12 @@ use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, + struct_lit_tactic, write_list, ListFormatting, Separator, }; use crate::macros::{rewrite_macro, MacroPosition}; use crate::matches::rewrite_match; use crate::overflow::{self, IntoOverflowableItem, OverflowableItem}; use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; -use crate::patterns::is_short_pattern; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; @@ -31,8 +30,8 @@ use crate::string::{rewrite_string, StringFormat}; use crate::types::{rewrite_path, PathContext}; use crate::utils::{ colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, - semicolon_for_expr, unicode_str_width, wrap_str, + last_line_extendable, last_line_width, mk_sp, outer_attributes, semicolon_for_expr, + unicode_str_width, wrap_str, }; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; @@ -587,7 +586,7 @@ struct ControlFlow<'a> { block: &'a ast::Block, else_block: Option<&'a ast::Expr>, label: Option, - pats: Vec<&'a ast::Pat>, + pat: Option<&'a ast::Pat>, keyword: &'a str, matcher: &'a str, connector: &'a str, @@ -597,10 +596,10 @@ struct ControlFlow<'a> { span: Span, } -fn extract_pats_and_cond(expr: &ast::Expr) -> (Vec<&ast::Pat>, &ast::Expr) { +fn extract_pats_and_cond(expr: &ast::Expr) -> (Option<&ast::Pat>, &ast::Expr) { match expr.node { - ast::ExprKind::Let(ref pats, ref cond) => (ptr_vec_to_ref_vec(pats), cond), - _ => (vec![], expr), + ast::ExprKind::Let(ref pat, ref cond) => (Some(pat), cond), + _ => (None, expr), } } @@ -608,10 +607,10 @@ fn extract_pats_and_cond(expr: &ast::Expr) -> (Vec<&ast::Pat>, &ast::Expr) { fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option> { match expr.node { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { - let (pats, cond) = extract_pats_and_cond(cond); + let (pat, cond) = extract_pats_and_cond(cond); Some(ControlFlow::new_if( cond, - pats, + pat, if_block, else_block.as_ref().map(|e| &**e), expr_type == ExprType::SubExpression, @@ -626,34 +625,34 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option { - let (pats, cond) = extract_pats_and_cond(cond); - Some(ControlFlow::new_while(pats, cond, block, label, expr.span)) + let (pat, cond) = extract_pats_and_cond(cond); + Some(ControlFlow::new_while(pat, cond, block, label, expr.span)) } _ => None, } } -fn choose_matcher(pats: &[&ast::Pat]) -> &'static str { - if pats.is_empty() { "" } else { "let" } +fn choose_matcher(pat: Option<&ast::Pat>) -> &'static str { + pat.map_or("", |_| "let") } impl<'a> ControlFlow<'a> { fn new_if( cond: &'a ast::Expr, - pats: Vec<&'a ast::Pat>, + pat: Option<&'a ast::Pat>, block: &'a ast::Block, else_block: Option<&'a ast::Expr>, allow_single_line: bool, nested_if: bool, span: Span, ) -> ControlFlow<'a> { - let matcher = choose_matcher(&pats); + let matcher = choose_matcher(pat); ControlFlow { cond: Some(cond), block, else_block, label: None, - pats, + pat, keyword: "if", matcher, connector: " =", @@ -669,7 +668,7 @@ impl<'a> ControlFlow<'a> { block, else_block: None, label, - pats: vec![], + pat: None, keyword: "loop", matcher: "", connector: "", @@ -680,19 +679,19 @@ impl<'a> ControlFlow<'a> { } fn new_while( - pats: Vec<&'a ast::Pat>, + pat: Option<&'a ast::Pat>, cond: &'a ast::Expr, block: &'a ast::Block, label: Option, span: Span, ) -> ControlFlow<'a> { - let matcher = choose_matcher(&pats); + let matcher = choose_matcher(pat); ControlFlow { cond: Some(cond), block, else_block: None, label, - pats, + pat, keyword: "while", matcher, connector: " =", @@ -714,7 +713,7 @@ impl<'a> ControlFlow<'a> { block, else_block: None, label, - pats: vec![pat], + pat: Some(pat), keyword: "for", matcher: "", connector: " in", @@ -790,10 +789,10 @@ impl<'a> ControlFlow<'a> { shape: Shape, offset: usize, ) -> Option { - debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pats, expr); + debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pat, expr); let cond_shape = shape.offset_left(offset)?; - if !self.pats.is_empty() { + if !self.pat.is_none() { let matcher = if self.matcher.is_empty() { self.matcher.to_owned() } else { @@ -802,7 +801,11 @@ impl<'a> ControlFlow<'a> { let pat_shape = cond_shape .offset_left(matcher.len())? .sub_width(self.connector.len())?; - let pat_string = rewrite_multiple_patterns(context, &self.pats, pat_shape)?; + let pat_string = if let Some(pat) = self.pat { + pat.rewrite(context, pat_shape)? + } else { + "".to_owned() + }; let result = format!("{}{}{}", matcher, pat_string, self.connector); return rewrite_assign_rhs(context, result, expr, cond_shape); } @@ -906,10 +909,10 @@ impl<'a> ControlFlow<'a> { context .snippet_provider .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), - if self.pats.is_empty() { + if self.pat.is_none() { cond_span.lo() } else if self.matcher.is_empty() { - self.pats[0].span.lo() + self.pat.unwrap().span.lo() } else { context .snippet_provider @@ -1145,39 +1148,6 @@ pub(crate) fn is_unsafe_block(block: &ast::Block) -> bool { } } -pub(crate) fn rewrite_multiple_patterns( - context: &RewriteContext<'_>, - pats: &[&ast::Pat], - shape: Shape, -) -> Option { - let pat_strs = pats - .iter() - .map(|p| p.rewrite(context, shape)) - .collect::>>()?; - - let use_mixed_layout = pats - .iter() - .zip(pat_strs.iter()) - .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); - let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); - let tactic = if use_mixed_layout { - DefinitiveListTactic::Mixed - } else { - definitive_tactic( - &items, - ListTactic::HorizontalVertical, - Separator::VerticalBar, - shape.width, - ) - }; - let fmt = ListFormatting::new(shape, context.config) - .tactic(tactic) - .separator(" |") - .separator_place(context.config.binop_separator()) - .ends_with_newline(false); - write_list(&items, &fmt) -} - pub(crate) fn rewrite_literal( context: &RewriteContext<'_>, l: &ast::Lit, diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 5bfdcbd0420..afe1ec5d068 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -58,10 +58,8 @@ impl From for FormatDiffError { #[derive(StructOpt, Debug)] #[structopt( name = "rustfmt-format-diff", - author = "", - about = "", - raw(setting = "AppSettings::DisableVersion"), - raw(setting = "AppSettings::NextLineHelp") + setting = AppSettings::DisableVersion, + setting = AppSettings::NextLineHelp )] pub struct Opts { /// Skip the smallest prefix containing NUMBER slashes @@ -78,7 +76,7 @@ pub struct Opts { short = "f", long = "filter", value_name = "PATTERN", - raw(default_value = "DEFAULT_PATTERN") + default_value = DEFAULT_PATTERN )] filter: String, } diff --git a/src/matches.rs b/src/matches.rs index b608faded9e..e8ea5d6ad42 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -10,7 +10,7 @@ use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; use crate::expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, - rewrite_multiple_patterns, ExprType, RhsTactics, + ExprType, RhsTactics, }; use crate::lists::{itemize_list, write_list, ListFormatting}; use crate::rewrite::{Rewrite, RewriteContext}; @@ -19,7 +19,7 @@ use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - ptr_vec_to_ref_vec, semicolon_for_expr, trimmed_last_line_width, unicode_str_width, + semicolon_for_expr, trimmed_last_line_width, unicode_str_width, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. @@ -161,7 +161,7 @@ fn collect_beginning_verts( let mut beginning_verts = Vec::with_capacity(arms.len()); let mut lo = context.snippet_provider.span_after(span, "{"); for arm in arms { - let hi = arm.pats[0].span.lo(); + let hi = arm.pat.span.lo(); let missing_span = mk_sp(lo, hi); beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); lo = arm.span().hi(); @@ -225,10 +225,7 @@ fn rewrite_match_arm( arm_comma(context.config, body, is_last), )); } - let missing_span = mk_sp( - arm.attrs[arm.attrs.len() - 1].span.hi(), - arm.pats[0].span.lo(), - ); + let missing_span = mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi(), arm.pat.span.lo()); (missing_span, arm.attrs.rewrite(context, shape)?) } else { (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) @@ -237,7 +234,7 @@ fn rewrite_match_arm( // Patterns // 5 = ` => {` let pat_shape = shape.sub_width(5)?; - let pats_str = rewrite_multiple_patterns(context, &ptr_vec_to_ref_vec(&arm.pats), pat_shape)?; + let pats_str = arm.pat.rewrite(context, pat_shape)?; // Guard let block_like_pat = trimmed_last_line_width(&pats_str) <= context.config.tab_spaces(); @@ -259,7 +256,7 @@ fn rewrite_match_arm( false, )?; - let arrow_span = mk_sp(arm.pats.last().unwrap().span.hi(), arm.body.span().lo()); + let arrow_span = mk_sp(arm.pat.span.hi(), arm.body.span().lo()); rewrite_match_body( context, &arm.body, diff --git a/src/patterns.rs b/src/patterns.rs index 96d45c6ac55..9a89c8d192c 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -7,7 +7,7 @@ use crate::config::lists::*; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, Separator, + struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, }; use crate::macros::{rewrite_macro, MacroPosition}; use crate::overflow; @@ -59,30 +59,32 @@ impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.node { PatKind::Or(ref pats) => { - let pat_items = itemize_list( - context.snippet_provider, - pats.iter(), - "", - "|", - |pat| pat.span().lo(), - |pat| pat.span().hi(), - |pat| pat.rewrite(context, shape), - self.span.lo(), - self.span.hi(), - false, - ); - let pat_vec: Vec<_> = pat_items.collect(); - let tactic = definitive_tactic( - &pat_vec, - ListTactic::HorizontalVertical, - Separator::VerticalBar, - shape.width, - ); + let pat_strs = pats + .iter() + .map(|p| p.rewrite(context, shape)) + .collect::>>()?; + + let use_mixed_layout = pats + .iter() + .zip(pat_strs.iter()) + .all(|(pat, pat_str)| is_short_pattern(pat, pat_str)); + let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect(); + let tactic = if use_mixed_layout { + DefinitiveListTactic::Mixed + } else { + definitive_tactic( + &items, + ListTactic::HorizontalVertical, + Separator::VerticalBar, + shape.width, + ) + }; let fmt = ListFormatting::new(shape, context.config) .tactic(tactic) - .trailing_separator(SeparatorTactic::Never) - .separator(" |"); - write_list(&pat_vec, &fmt) + .separator(" |") + .separator_place(context.config.binop_separator()) + .ends_with_newline(false); + write_list(&items, &fmt) } PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(binding_mode, ident, ref sub_pat) => { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index fd332b12403..fc2c7d06e26 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -3,8 +3,6 @@ use std::fmt; use std::io; use std::io::Write; -use diff; - use crate::config::{Color, Config, Verbosity}; #[derive(Debug, PartialEq)] diff --git a/src/spanned.rs b/src/spanned.rs index bbdee6ccf4b..576085ae384 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -96,7 +96,7 @@ impl Spanned for ast::Ty { impl Spanned for ast::Arm { fn span(&self) -> Span { let lo = if self.attrs.is_empty() { - self.pats[0].span.lo() + self.pat.span.lo() } else { self.attrs[0].span.lo() }; diff --git a/src/utils.rs b/src/utils.rs index 5b0d94e4780..f2a2a3c6675 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,5 @@ use std::borrow::Cow; -use bytecount; - use rustc_target::spec::abi; use syntax::ast::{ self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NodeId, Path, Visibility, -- cgit 1.4.1-3-g733a5 From dfe87fe946839fa310d98e2a30cc32a681e28d31 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 10 Sep 2019 19:55:18 -0500 Subject: fix: async expression indentation (#3789) --- src/utils.rs | 22 +++++++++++++++++++++- tests/source/expr.rs | 18 ++++++++++++++++++ tests/target/expr.rs | 17 +++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils.rs b/src/utils.rs index f2a2a3c6675..bad9bc1d788 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -452,8 +452,10 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::While(..) | ast::ExprKind::If(..) | ast::ExprKind::Block(..) + | ast::ExprKind::Async(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) + | ast::ExprKind::TryBlock(..) | ast::ExprKind::Match(..) => repr.contains('\n'), ast::ExprKind::Paren(ref expr) | ast::ExprKind::Binary(_, _, ref expr) @@ -466,7 +468,25 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr ast::ExprKind::Lit(_) => { repr.contains('\n') && trimmed_last_line_width(repr) <= context.config.tab_spaces() } - _ => false, + ast::ExprKind::AddrOf(..) + | ast::ExprKind::Assign(..) + | ast::ExprKind::AssignOp(..) + | ast::ExprKind::Await(..) + | ast::ExprKind::Box(..) + | ast::ExprKind::Break(..) + | ast::ExprKind::Cast(..) + | ast::ExprKind::Continue(..) + | ast::ExprKind::Err + | ast::ExprKind::Field(..) + | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::Let(..) + | ast::ExprKind::Path(..) + | ast::ExprKind::Range(..) + | ast::ExprKind::Repeat(..) + | ast::ExprKind::Ret(..) + | ast::ExprKind::Tup(..) + | ast::ExprKind::Type(..) + | ast::ExprKind::Yield(None) => false, } } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index be87aca83a0..05af07f231b 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -545,3 +545,21 @@ fn overflow_with_attr() { foobar(x, y, #[cfg(feature = "zero")] {}); } + + +// https://github.com/rust-lang/rustfmt/issues/3765 +fn foo() { + async { + // Do + // some + // work + } + .await; + + async { + // Do + // some + // work + } + .await; +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index e63044ea913..c50693049a2 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -638,3 +638,20 @@ fn overflow_with_attr() { {}, ); } + +// https://github.com/rust-lang/rustfmt/issues/3765 +fn foo() { + async { + // Do + // some + // work + } + .await; + + async { + // Do + // some + // work + } + .await; +} -- cgit 1.4.1-3-g733a5 From 789a097a7142e098069e9203f9c2da16267d8826 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Sun, 15 Sep 2019 23:45:46 +0900 Subject: fix internal error when using rustfmt::skip with newline on stmt (#3785) --- src/expr.rs | 5 +++++ tests/target/issue-3717.rs | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/target/issue-3717.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 36d7b91d102..2a1d40c9564 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -516,6 +516,11 @@ pub(crate) fn rewrite_block_with_visitor( let inner_attrs = attrs.map(inner_attributes); let label_str = rewrite_label(label); visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); + let visitor_context = visitor.get_context(); + context + .skipped_range + .borrow_mut() + .append(&mut visitor_context.skipped_range.borrow_mut()); Some(format!("{}{}{}", prefix, label_str, visitor.buffer)) } diff --git a/tests/target/issue-3717.rs b/tests/target/issue-3717.rs new file mode 100644 index 00000000000..b769cd3ecce --- /dev/null +++ b/tests/target/issue-3717.rs @@ -0,0 +1,7 @@ +fn main() { + { + #[rustfmt::skip] + let _ = + [1]; + } +} -- cgit 1.4.1-3-g733a5 From ca78653d61b7f045ca6245bb39c48fb057651aaf Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 18 Sep 2019 22:37:08 +0900 Subject: Use Cell instead of RefCell (#3798) --- src/chains.rs | 2 +- src/macros.rs | 2 +- src/overflow.rs | 2 +- src/rewrite.rs | 20 ++++++++++---------- src/visitor.rs | 23 +++++++++-------------- 5 files changed, 22 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 81708625acb..56775c4b5ef 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -647,7 +647,7 @@ impl<'a> ChainFormatterShared<'a> { Cow::from("") } else { // Use new lines. - if *context.force_one_line_chain.borrow() { + if context.force_one_line_chain.get() { return None; } child_shape.to_string_with_newline(context.config) diff --git a/src/macros.rs b/src/macros.rs index 08f83b7e826..e92f02a1db1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -528,7 +528,7 @@ pub(crate) fn rewrite_macro_def( Some(v) => Some(v), // if the rewrite returned None because a macro could not be rewritten, then return the // original body - None if *context.macro_rewrite_failure.borrow() => { + None if context.macro_rewrite_failure.get() => { Some(context.snippet(branch.body).trim().to_string()) } None => None, diff --git a/src/overflow.rs b/src/overflow.rs index fc0cf98ceba..7c3f9d1a5eb 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -465,7 +465,7 @@ impl<'a> Context<'a> { // Replace the last item with its first line to see if it fits with // first arguments. let placeholder = if overflow_last { - let old_value = *self.context.force_one_line_chain.borrow(); + let old_value = self.context.force_one_line_chain.get(); match self.last_item() { Some(OverflowableItem::Expr(expr)) if !combine_arg_with_callee && is_method_call(expr) => diff --git a/src/rewrite.rs b/src/rewrite.rs index 19b749dc8e1..602512e87ce 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -1,6 +1,6 @@ // A generic trait to abstract the rewriting of an element (of the AST). -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::rc::Rc; use syntax::parse::ParseSess; @@ -29,17 +29,17 @@ pub(crate) struct RewriteContext<'a> { pub(crate) parse_session: &'a ParseSess, pub(crate) source_map: &'a SourceMap, pub(crate) config: &'a Config, - pub(crate) inside_macro: Rc>, + pub(crate) inside_macro: Rc>, // Force block indent style even if we are using visual indent style. - pub(crate) use_block: RefCell, + pub(crate) use_block: Cell, // When `is_if_else_block` is true, unindent the comment on top // of the `else` or `else if`. - pub(crate) is_if_else_block: RefCell, + pub(crate) is_if_else_block: Cell, // When rewriting chain, veto going multi line except the last element - pub(crate) force_one_line_chain: RefCell, + pub(crate) force_one_line_chain: Cell, pub(crate) snippet_provider: &'a SnippetProvider<'a>, // Used for `format_snippet` - pub(crate) macro_rewrite_failure: RefCell, + pub(crate) macro_rewrite_failure: Cell, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, pub(crate) skipped_range: Rc>>, @@ -47,7 +47,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) struct InsideMacroGuard { is_nested_macro_context: bool, - inside_macro_ref: Rc>, + inside_macro_ref: Rc>, } impl InsideMacroGuard { @@ -69,7 +69,7 @@ impl<'a> RewriteContext<'a> { /// Returns `true` if we should use block indent style for rewriting function call. pub(crate) fn use_block_indent(&self) -> bool { - self.config.indent_style() == IndentStyle::Block || *self.use_block.borrow() + self.config.indent_style() == IndentStyle::Block || self.use_block.get() } pub(crate) fn budget(&self, used_width: usize) -> usize { @@ -77,7 +77,7 @@ impl<'a> RewriteContext<'a> { } pub(crate) fn inside_macro(&self) -> bool { - *self.inside_macro.borrow() + self.inside_macro.get() } pub(crate) fn enter_macro(&self) -> InsideMacroGuard { @@ -93,6 +93,6 @@ impl<'a> RewriteContext<'a> { } pub(crate) fn is_if_else_block(&self) -> bool { - *self.is_if_else_block.borrow() + self.is_if_else_block.get() } } diff --git a/src/visitor.rs b/src/visitor.rs index 831fd56819f..49197682c14 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::rc::Rc; use syntax::parse::ParseSess; @@ -862,15 +862,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { where F: Fn(&RewriteContext<'_>) -> Option, { - // FIXME borrow checker fighting - can be simplified a lot with NLL. - let (result, mrf) = { - let context = self.get_context(); - let result = f(&context); - let mrf = &context.macro_rewrite_failure.borrow(); - (result, *std::ops::Deref::deref(mrf)) - }; + let context = self.get_context(); + let result = f(&context); - self.macro_rewrite_failure |= mrf; + self.macro_rewrite_failure |= context.macro_rewrite_failure.get(); result } @@ -879,12 +874,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { parse_session: self.parse_session, source_map: self.source_map, config: self.config, - inside_macro: Rc::new(RefCell::new(false)), - use_block: RefCell::new(false), - is_if_else_block: RefCell::new(false), - force_one_line_chain: RefCell::new(false), + inside_macro: Rc::new(Cell::new(false)), + use_block: Cell::new(false), + is_if_else_block: Cell::new(false), + force_one_line_chain: Cell::new(false), snippet_provider: self.snippet_provider, - macro_rewrite_failure: RefCell::new(false), + macro_rewrite_failure: Cell::new(false), report: self.report.clone(), skip_context: self.skip_context.clone(), skipped_range: self.skipped_range.clone(), -- cgit 1.4.1-3-g733a5 From 4449250539b7e8ab27d8c12a77ca38ce278eac51 Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Wed, 18 Sep 2019 22:39:27 +0900 Subject: fix the error with long string in raw string (#3800) --- src/expr.rs | 14 ++++++++++++-- tests/source/issue-3786.rs | 12 ++++++++++++ tests/target/issue-3786.rs | 9 +++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue-3786.rs create mode 100644 tests/target/issue-3786.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2a1d40c9564..93289b58282 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::cmp::min; use itertools::Itertools; -use syntax::parse::token::DelimToken; +use syntax::parse::token::{DelimToken, LitKind}; use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::{ast, ptr}; @@ -75,7 +75,17 @@ pub(crate) fn format_expr( choose_separator_tactic(context, expr.span), None, ), - ast::ExprKind::Lit(ref l) => rewrite_literal(context, l, shape), + ast::ExprKind::Lit(ref l) => { + if let Some(expr_rw) = rewrite_literal(context, l, shape) { + Some(expr_rw) + } else { + if let LitKind::StrRaw(_) = l.token.kind { + Some(context.snippet(l.span).trim().into()) + } else { + None + } + } + } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); let callee_str = callee.rewrite(context, shape)?; diff --git a/tests/source/issue-3786.rs b/tests/source/issue-3786.rs new file mode 100644 index 00000000000..54f8211ed4f --- /dev/null +++ b/tests/source/issue-3786.rs @@ -0,0 +1,12 @@ +fn main() { + let _ = +r#" +this is a very long string exceeded maximum width in this case maximum 100. (current this line width is about 115) +"#; + + let _with_newline = + +r#" +this is a very long string exceeded maximum width in this case maximum 100. (current this line width is about 115) +"#; +} diff --git a/tests/target/issue-3786.rs b/tests/target/issue-3786.rs new file mode 100644 index 00000000000..d90cba15d20 --- /dev/null +++ b/tests/target/issue-3786.rs @@ -0,0 +1,9 @@ +fn main() { + let _ = r#" +this is a very long string exceeded maximum width in this case maximum 100. (current this line width is about 115) +"#; + + let _with_newline = r#" +this is a very long string exceeded maximum width in this case maximum 100. (current this line width is about 115) +"#; +} -- cgit 1.4.1-3-g733a5 From 6b0a447150e6a1e41edecdd037013608769f1040 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 20 Sep 2019 02:11:52 -0500 Subject: feat: support parameter attributes (#3793) --- src/items.rs | 89 ++++++++++++++++++++++++++++++------- tests/source/fn-param-attributes.rs | 57 ++++++++++++++++++++++++ tests/target/fn-param-attributes.rs | 64 ++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 tests/source/fn-param-attributes.rs create mode 100644 tests/target/fn-param-attributes.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 613f9b5b729..d3937bbdb31 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1905,12 +1905,39 @@ fn get_missing_arg_comments( impl Rewrite for ast::Param { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + let param_attrs_result = self + .attrs + .rewrite(context, Shape::legacy(shape.width, shape.indent))?; + let (span, has_multiple_attr_lines) = if !self.attrs.is_empty() { + let num_attrs = self.attrs.len(); + ( + mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()), + param_attrs_result.matches("\n").count() > 0, + ) + } else { + (mk_sp(self.span.lo(), self.span.lo()), false) + }; + if let Some(ref explicit_self) = self.to_self() { - rewrite_explicit_self(context, explicit_self) + rewrite_explicit_self( + context, + explicit_self, + ¶m_attrs_result, + span, + shape, + has_multiple_attr_lines, + ) } else if is_named_arg(self) { - let mut result = self - .pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))?; + let mut result = combine_strs_with_missing_comments( + context, + ¶m_attrs_result, + &self + .pat + .rewrite(context, Shape::legacy(shape.width, shape.indent))?, + span, + shape, + !has_multiple_attr_lines, + )?; if !is_empty_infer(&*self.ty, self.pat.span) { let (before_comment, after_comment) = @@ -1936,6 +1963,10 @@ impl Rewrite for ast::Param { fn rewrite_explicit_self( context: &RewriteContext<'_>, explicit_self: &ast::ExplicitSelf, + param_attrs: &str, + span: Span, + shape: Shape, + has_multiple_attr_lines: bool, ) -> Option { match explicit_self.node { ast::SelfKind::Region(lt, m) => { @@ -1946,9 +1977,23 @@ fn rewrite_explicit_self( context, Shape::legacy(context.config.max_width(), Indent::empty()), )?; - Some(format!("&{} {}self", lifetime_str, mut_str)) + Some(combine_strs_with_missing_comments( + context, + ¶m_attrs, + &format!("&{} {}self", lifetime_str, mut_str), + span, + shape, + !has_multiple_attr_lines, + )?) } - None => Some(format!("&{}self", mut_str)), + None => Some(combine_strs_with_missing_comments( + context, + ¶m_attrs, + &format!("&{}self", mut_str), + span, + shape, + !has_multiple_attr_lines, + )?), } } ast::SelfKind::Explicit(ref ty, mutability) => { @@ -1957,21 +2002,35 @@ fn rewrite_explicit_self( Shape::legacy(context.config.max_width(), Indent::empty()), )?; - Some(format!( - "{}self: {}", - format_mutability(mutability), - type_str - )) + Some(combine_strs_with_missing_comments( + context, + ¶m_attrs, + &format!("{}self: {}", format_mutability(mutability), type_str), + span, + shape, + !has_multiple_attr_lines, + )?) } - ast::SelfKind::Value(mutability) => Some(format!("{}self", format_mutability(mutability))), + ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments( + context, + ¶m_attrs, + &format!("{}self", format_mutability(mutability)), + span, + shape, + !has_multiple_attr_lines, + )?), } } pub(crate) fn span_lo_for_arg(arg: &ast::Param) -> BytePos { - if is_named_arg(arg) { - arg.pat.span.lo() + if arg.attrs.is_empty() { + if is_named_arg(arg) { + arg.pat.span.lo() + } else { + arg.ty.span.lo() + } } else { - arg.ty.span.lo() + arg.attrs[0].span.lo() } } diff --git a/tests/source/fn-param-attributes.rs b/tests/source/fn-param-attributes.rs new file mode 100644 index 00000000000..3407a3b2ef2 --- /dev/null +++ b/tests/source/fn-param-attributes.rs @@ -0,0 +1,57 @@ +// https://github.com/rust-lang/rustfmt/issues/3623 + +fn foo(#[cfg(something)] x: i32, y: i32) -> i32 { + x + y +} + +fn foo_b(#[cfg(something)]x: i32, y: i32) -> i32 { + x + y +} + +fn add(#[cfg(something)]#[deny(C)] x: i32, y: i32) -> i32 { + x + y +} + +struct NamedSelfRefStruct {} +impl NamedSelfRefStruct { + fn foo( +#[cfg(something)] self: &Self, + ) {} +} + +struct MutStruct {} +impl MutStruct { + fn foo( + #[cfg(foo)]&mut self,#[deny(C)] b: i32, + ) {} +} + +fn main() { + let c = | + #[allow(C)]a: u32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))]#[deny(C)] c: i32, + | {}; + let _ = c(1, 2); +} + +pub fn bar( + /// bar +#[test] a: u32, + /// Bar + #[must_use] +/// Baz + #[no_mangle] b: i32, +) {} + + +fn abc( + #[foo] + #[bar] param: u32, +) { + // ... +} + +fn really_really_really_loooooooooooooooooooong(#[cfg(some_even_longer_config_feature_that_keeps_going_and_going_and_going_forever_and_ever_and_ever_on_and_on)] b: i32) { + // ... +} diff --git a/tests/target/fn-param-attributes.rs b/tests/target/fn-param-attributes.rs new file mode 100644 index 00000000000..829575518de --- /dev/null +++ b/tests/target/fn-param-attributes.rs @@ -0,0 +1,64 @@ +// https://github.com/rust-lang/rustfmt/issues/3623 + +fn foo(#[cfg(something)] x: i32, y: i32) -> i32 { + x + y +} + +fn foo_b(#[cfg(something)] x: i32, y: i32) -> i32 { + x + y +} + +fn add( + #[cfg(something)] + #[deny(C)] + x: i32, + y: i32, +) -> i32 { + x + y +} + +struct NamedSelfRefStruct {} +impl NamedSelfRefStruct { + fn foo(#[cfg(something)] self: &Self) {} +} + +struct MutStruct {} +impl MutStruct { + fn foo(#[cfg(foo)] &mut self, #[deny(C)] b: i32) {} +} + +fn main() { + let c = |#[allow(C)] a: u32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] + c: i32| {}; + let _ = c(1, 2); +} + +pub fn bar( + /// bar + #[test] + a: u32, + /// Bar + #[must_use] + /// Baz + #[no_mangle] + b: i32, +) { +} + +fn abc( + #[foo] + #[bar] + param: u32, +) { + // ... +} + +fn really_really_really_loooooooooooooooooooong( + #[cfg(some_even_longer_config_feature_that_keeps_going_and_going_and_going_forever_and_ever_and_ever_on_and_on)] + b: i32, +) { + // ... +} -- cgit 1.4.1-3-g733a5 From 3bb266180e63b5995a2dc6bc85d2b8fa19f429ee Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 23 Sep 2019 19:24:05 -0500 Subject: fix: handling of empty str for license template path (#3804) --- src/config/config_type.rs | 10 ++++++---- src/config/mod.rs | 14 ++++++++++++++ tests/config/issue-3802.toml | 2 ++ tests/license-template/lt.txt | 2 ++ tests/source/license-templates/empty_license_path.rs | 5 +++++ tests/source/license-templates/license.rs | 6 ++++++ tests/target/license-templates/empty_license_path.rs | 5 +++++ tests/target/license-templates/license.rs | 6 ++++++ 8 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tests/config/issue-3802.toml create mode 100644 tests/license-template/lt.txt create mode 100644 tests/source/license-templates/empty_license_path.rs create mode 100644 tests/source/license-templates/license.rs create mode 100644 tests/target/license-templates/empty_license_path.rs create mode 100644 tests/target/license-templates/license.rs (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 7f7e8905fba..2eff7561392 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -293,10 +293,12 @@ macro_rules! create_config { fn set_license_template(&mut self) { if self.was_set().license_template_path() { let lt_path = self.license_template_path(); - match license::load_and_compile_template(<_path) { - Ok(re) => self.license_template = Some(re), - Err(msg) => eprintln!("Warning for license template file {:?}: {}", - lt_path, msg), + if lt_path.len() > 0 { + match license::load_and_compile_template(<_path) { + Ok(re) => self.license_template = Some(re), + Err(msg) => eprintln!("Warning for license template file {:?}: {}", + lt_path, msg), + } } } } diff --git a/src/config/mod.rs b/src/config/mod.rs index a4930b7c575..1d0217f27b1 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -467,6 +467,20 @@ mod test { assert_eq!(s.contains("(unstable)"), true); } + #[test] + fn test_empty_string_license_template_path() { + let toml = r#"license_template_path = """#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert!(config.license_template.is_none()); + } + + #[test] + fn test_valid_license_template_path() { + let toml = r#"license_template_path = "tests/license-template/lt.txt""#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert!(config.license_template.is_some()); + } + #[test] fn test_dump_default_config() { let default_config = format!( diff --git a/tests/config/issue-3802.toml b/tests/config/issue-3802.toml new file mode 100644 index 00000000000..74ee8b010dd --- /dev/null +++ b/tests/config/issue-3802.toml @@ -0,0 +1,2 @@ +unstable_features = true +license_template_path = "" diff --git a/tests/license-template/lt.txt b/tests/license-template/lt.txt new file mode 100644 index 00000000000..ea4390371a0 --- /dev/null +++ b/tests/license-template/lt.txt @@ -0,0 +1,2 @@ +// rustfmt-license_template_path: tests/license-template/lt.txt +// Copyright {\d+} The rustfmt developers. diff --git a/tests/source/license-templates/empty_license_path.rs b/tests/source/license-templates/empty_license_path.rs new file mode 100644 index 00000000000..d3a91e4231d --- /dev/null +++ b/tests/source/license-templates/empty_license_path.rs @@ -0,0 +1,5 @@ +// rustfmt-config: issue-3802.toml + +fn main() { +println!("Hello world!"); +} diff --git a/tests/source/license-templates/license.rs b/tests/source/license-templates/license.rs new file mode 100644 index 00000000000..6816011c60d --- /dev/null +++ b/tests/source/license-templates/license.rs @@ -0,0 +1,6 @@ +// rustfmt-license_template_path: tests/license-template/lt.txt +// Copyright 2019 The rustfmt developers. + +fn main() { +println!("Hello world!"); +} diff --git a/tests/target/license-templates/empty_license_path.rs b/tests/target/license-templates/empty_license_path.rs new file mode 100644 index 00000000000..950f103ed39 --- /dev/null +++ b/tests/target/license-templates/empty_license_path.rs @@ -0,0 +1,5 @@ +// rustfmt-config: issue-3802.toml + +fn main() { + println!("Hello world!"); +} diff --git a/tests/target/license-templates/license.rs b/tests/target/license-templates/license.rs new file mode 100644 index 00000000000..7169c7b2576 --- /dev/null +++ b/tests/target/license-templates/license.rs @@ -0,0 +1,6 @@ +// rustfmt-license_template_path: tests/license-template/lt.txt +// Copyright 2019 The rustfmt developers. + +fn main() { + println!("Hello world!"); +} -- cgit 1.4.1-3-g733a5 From 9c2b375ba901822dc2c06de435ac45a74316f686 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 23 Sep 2019 19:25:19 -0500 Subject: refactor to use param naming where appropriate (#3803) --- src/closures.rs | 30 +++++------ src/items.rs | 165 ++++++++++++++++++++++++++++---------------------------- src/spanned.rs | 2 +- 3 files changed, 99 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index c0ecc91db52..c89ba4c5cdc 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -4,7 +4,7 @@ use syntax::{ast, ptr}; use crate::config::lists::*; use crate::config::Version; use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; -use crate::items::{span_hi_for_arg, span_lo_for_arg}; +use crate::items::{span_hi_for_param, span_lo_for_param}; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::overflow::OverflowableItem; use crate::rewrite::{Rewrite, RewriteContext}; @@ -232,24 +232,24 @@ fn rewrite_closure_fn_decl( .sub_width(4)?; // 1 = | - let argument_offset = nested_shape.indent + 1; - let arg_shape = nested_shape.offset_left(1)?.visual_indent(0); - let ret_str = fn_decl.output.rewrite(context, arg_shape)?; + let param_offset = nested_shape.indent + 1; + let param_shape = nested_shape.offset_left(1)?.visual_indent(0); + let ret_str = fn_decl.output.rewrite(context, param_shape)?; - let arg_items = itemize_list( + let param_items = itemize_list( context.snippet_provider, fn_decl.inputs.iter(), "|", ",", - |arg| span_lo_for_arg(arg), - |arg| span_hi_for_arg(context, arg), - |arg| arg.rewrite(context, arg_shape), + |param| span_lo_for_param(param), + |param| span_hi_for_param(context, param), + |param| param.rewrite(context, param_shape), context.snippet_provider.span_after(span, "|"), body.span.lo(), false, ); - let item_vec = arg_items.collect::>(); - // 1 = space between arguments and return type. + let item_vec = param_items.collect::>(); + // 1 = space between parameters and return type. let horizontal_budget = nested_shape.width.saturating_sub(ret_str.len() + 1); let tactic = definitive_tactic( &item_vec, @@ -257,12 +257,12 @@ fn rewrite_closure_fn_decl( Separator::Comma, horizontal_budget, ); - let arg_shape = match tactic { - DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?, - _ => arg_shape, + let param_shape = match tactic { + DefinitiveListTactic::Horizontal => param_shape.sub_width(ret_str.len() + 1)?, + _ => param_shape, }; - let fmt = ListFormatting::new(arg_shape, context.config) + let fmt = ListFormatting::new(param_shape, context.config) .tactic(tactic) .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; @@ -271,7 +271,7 @@ fn rewrite_closure_fn_decl( if !ret_str.is_empty() { if prefix.contains('\n') { prefix.push('\n'); - prefix.push_str(&argument_offset.to_string(context.config)); + prefix.push_str(¶m_offset.to_string(context.config)); } else { prefix.push(' '); } diff --git a/src/items.rs b/src/items.rs index d3937bbdb31..cdf9fa06eef 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1867,13 +1867,13 @@ fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool { } } -/// Recover any missing comments between the argument and the type. +/// Recover any missing comments between the param and the type. /// /// # Returns /// /// A 2-len tuple with the comment before the colon in first position, and the comment after the /// colon in second position. -fn get_missing_arg_comments( +fn get_missing_param_comments( context: &RewriteContext<'_>, pat_span: Span, ty_span: Span, @@ -1912,7 +1912,7 @@ impl Rewrite for ast::Param { let num_attrs = self.attrs.len(); ( mk_sp(self.attrs[num_attrs - 1].span.hi(), self.pat.span.lo()), - param_attrs_result.matches("\n").count() > 0, + param_attrs_result.contains("\n"), ) } else { (mk_sp(self.span.lo(), self.span.lo()), false) @@ -1927,7 +1927,7 @@ impl Rewrite for ast::Param { shape, has_multiple_attr_lines, ) - } else if is_named_arg(self) { + } else if is_named_param(self) { let mut result = combine_strs_with_missing_comments( context, ¶m_attrs_result, @@ -1941,7 +1941,7 @@ impl Rewrite for ast::Param { if !is_empty_infer(&*self.ty, self.pat.span) { let (before_comment, after_comment) = - get_missing_arg_comments(context, self.pat.span, self.ty.span, shape); + get_missing_param_comments(context, self.pat.span, self.ty.span, shape); result.push_str(&before_comment); result.push_str(colon_spaces(context.config)); result.push_str(&after_comment); @@ -2022,28 +2022,28 @@ fn rewrite_explicit_self( } } -pub(crate) fn span_lo_for_arg(arg: &ast::Param) -> BytePos { - if arg.attrs.is_empty() { - if is_named_arg(arg) { - arg.pat.span.lo() +pub(crate) fn span_lo_for_param(param: &ast::Param) -> BytePos { + if param.attrs.is_empty() { + if is_named_param(param) { + param.pat.span.lo() } else { - arg.ty.span.lo() + param.ty.span.lo() } } else { - arg.attrs[0].span.lo() + param.attrs[0].span.lo() } } -pub(crate) fn span_hi_for_arg(context: &RewriteContext<'_>, arg: &ast::Param) -> BytePos { - match arg.ty.node { - ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(), - ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(), - _ => arg.ty.span.hi(), +pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param) -> BytePos { + match param.ty.node { + ast::TyKind::Infer if context.snippet(param.ty.span) == "_" => param.ty.span.hi(), + ast::TyKind::Infer if is_named_param(param) => param.pat.span.hi(), + _ => param.ty.span.hi(), } } -pub(crate) fn is_named_arg(arg: &ast::Param) -> bool { - if let ast::PatKind::Ident(_, ident, _) = arg.pat.node { +pub(crate) fn is_named_param(param: &ast::Param) -> bool { + if let ast::PatKind::Ident(_, ident, _) = param.pat.node { ident.name != symbol::kw::Invalid } else { true @@ -2114,8 +2114,8 @@ fn rewrite_fn_base( let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; - // Args. - let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args( + // Params. + let (one_line_budget, multi_line_budget, mut param_indent) = compute_budgets_for_params( context, &result, indent, @@ -2125,8 +2125,8 @@ fn rewrite_fn_base( )?; debug!( - "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}", - one_line_budget, multi_line_budget, arg_indent + "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, param_indent: {:?}", + one_line_budget, multi_line_budget, param_indent ); result.push('('); @@ -2135,79 +2135,79 @@ fn rewrite_fn_base( && !snuggle_angle_bracket && context.config.indent_style() == IndentStyle::Visual { - result.push_str(&arg_indent.to_string_with_newline(context.config)); + result.push_str(¶m_indent.to_string_with_newline(context.config)); } // Skip `pub(crate)`. let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span); // A conservative estimation, to goal is to be over all parens in generics - let args_start = fn_sig + let params_start = fn_sig .generics .params .iter() .last() .map_or(lo_after_visibility, |param| param.span().hi()); - let args_end = if fd.inputs.is_empty() { + let params_end = if fd.inputs.is_empty() { context .snippet_provider - .span_after(mk_sp(args_start, span.hi()), ")") + .span_after(mk_sp(params_start, span.hi()), ")") } else { let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi()); context.snippet_provider.span_after(last_span, ")") }; - let args_span = mk_sp( + let params_span = mk_sp( context .snippet_provider - .span_after(mk_sp(args_start, span.hi()), "("), - args_end, + .span_after(mk_sp(params_start, span.hi()), "("), + params_end, ); - let arg_str = rewrite_args( + let param_str = rewrite_params( context, &fd.inputs, one_line_budget, multi_line_budget, indent, - arg_indent, - args_span, + param_indent, + params_span, fd.c_variadic, )?; - let put_args_in_block = match context.config.indent_style() { - IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget, + let put_params_in_block = match context.config.indent_style() { + IndentStyle::Block => param_str.contains('\n') || param_str.len() > one_line_budget, _ => false, } && !fd.inputs.is_empty(); - let mut args_last_line_contains_comment = false; - let mut no_args_and_over_max_width = false; + let mut params_last_line_contains_comment = false; + let mut no_params_and_over_max_width = false; - if put_args_in_block { - arg_indent = indent.block_indent(context.config); - result.push_str(&arg_indent.to_string_with_newline(context.config)); - result.push_str(&arg_str); + if put_params_in_block { + param_indent = indent.block_indent(context.config); + result.push_str(¶m_indent.to_string_with_newline(context.config)); + result.push_str(¶m_str); result.push_str(&indent.to_string_with_newline(context.config)); result.push(')'); } else { - result.push_str(&arg_str); + result.push_str(¶m_str); let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); // Put the closing brace on the next line if it overflows the max width. // 1 = `)` let closing_paren_overflow_max_width = fd.inputs.is_empty() && used_width + 1 > context.config.max_width(); - // If the last line of args contains comment, we cannot put the closing paren + // If the last line of params contains comment, we cannot put the closing paren // on the same line. - args_last_line_contains_comment = arg_str + params_last_line_contains_comment = param_str .lines() .last() .map_or(false, |last_line| last_line.contains("//")); if context.config.version() == Version::Two { result.push(')'); - if closing_paren_overflow_max_width || args_last_line_contains_comment { + if closing_paren_overflow_max_width || params_last_line_contains_comment { result.push_str(&indent.to_string_with_newline(context.config)); - no_args_and_over_max_width = true; + no_params_and_over_max_width = true; } } else { - if closing_paren_overflow_max_width || args_last_line_contains_comment { + if closing_paren_overflow_max_width || params_last_line_contains_comment { result.push_str(&indent.to_string_with_newline(context.config)); } result.push(')'); @@ -2217,14 +2217,14 @@ fn rewrite_fn_base( // Return type. if let ast::FunctionRetTy::Ty(..) = fd.output { let ret_should_indent = match context.config.indent_style() { - // If our args are block layout then we surely must have space. - IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false, - _ if args_last_line_contains_comment => false, + // If our params are block layout then we surely must have space. + IndentStyle::Block if put_params_in_block || fd.inputs.is_empty() => false, + _ if params_last_line_contains_comment => false, _ if result.contains('\n') || multi_line_ret_str => true, _ => { // If the return type would push over the max width, then put the return type on // a new line. With the +1 for the signature length an additional space between - // the closing parenthesis of the argument and the arrow '->' is considered. + // the closing parenthesis of the param and the arrow '->' is considered. let mut sig_length = result.len() + indent.width() + ret_str_len + 1; // If there is no where-clause, take into account the space after the return type @@ -2240,23 +2240,23 @@ fn rewrite_fn_base( if context.config.version() == Version::One || context.config.indent_style() == IndentStyle::Visual { - let indent = if arg_str.is_empty() { - // Aligning with non-existent args looks silly. + let indent = if param_str.is_empty() { + // Aligning with non-existent params looks silly. force_new_line_for_brace = true; indent + 4 } else { - // FIXME: we might want to check that using the arg indent + // FIXME: we might want to check that using the param indent // doesn't blow our budget, and if it does, then fallback to // the where-clause indent. - arg_indent + param_indent }; result.push_str(&indent.to_string_with_newline(context.config)); Shape::indented(indent, context.config) } else { let mut ret_shape = Shape::indented(indent, context.config); - if arg_str.is_empty() { - // Aligning with non-existent args looks silly. + if param_str.is_empty() { + // Aligning with non-existent params looks silly. force_new_line_for_brace = true; ret_shape = if context.use_block_indent() { ret_shape.offset_left(4).unwrap_or(ret_shape) @@ -2271,7 +2271,7 @@ fn rewrite_fn_base( } } else { if context.config.version() == Version::Two { - if !arg_str.is_empty() || !no_args_and_over_max_width { + if !param_str.is_empty() || !no_params_and_over_max_width { result.push(' '); } } else { @@ -2321,19 +2321,19 @@ fn rewrite_fn_base( } let pos_before_where = match fd.output { - ast::FunctionRetTy::Default(..) => args_span.hi(), + ast::FunctionRetTy::Default(..) => params_span.hi(), ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), }; - let is_args_multi_lined = arg_str.contains('\n'); + let is_params_multi_lined = param_str.contains('\n'); - let space = if put_args_in_block && ret_str.is_empty() { + let space = if put_params_in_block && ret_str.is_empty() { WhereClauseSpace::Space } else { WhereClauseSpace::Newline }; let mut option = WhereClauseOption::new(fn_brace_style == FnBraceStyle::None, space); - if is_args_multi_lined { + if is_params_multi_lined { option.veto_single_line(); } let where_clause_str = rewrite_where_clause( @@ -2348,11 +2348,11 @@ fn rewrite_fn_base( option, )?; // If there are neither where-clause nor return type, we may be missing comments between - // args and `{`. + // params and `{`. if where_clause_str.is_empty() { if let ast::FunctionRetTy::Default(ret_span) = fd.output { match recover_missing_comment_in_span( - mk_sp(args_span.hi(), ret_span.hi()), + mk_sp(params_span.hi(), ret_span.hi()), shape, context, last_line_width(&result), @@ -2369,7 +2369,7 @@ fn rewrite_fn_base( result.push_str(&where_clause_str); force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line(); + force_new_line_for_brace |= is_params_multi_lined && context.config.where_single_line(); Some((result, force_new_line_for_brace)) } @@ -2432,17 +2432,17 @@ impl WhereClauseOption { } } -fn rewrite_args( +fn rewrite_params( context: &RewriteContext<'_>, - args: &[ast::Param], + params: &[ast::Param], one_line_budget: usize, multi_line_budget: usize, indent: Indent, - arg_indent: Indent, + param_indent: Indent, span: Span, variadic: bool, ) -> Option { - if args.is_empty() { + if params.is_empty() { let comment = context .snippet(mk_sp( span.lo(), @@ -2452,16 +2452,17 @@ fn rewrite_args( .trim(); return Some(comment.to_owned()); } - let arg_items: Vec<_> = itemize_list( + let param_items: Vec<_> = itemize_list( context.snippet_provider, - args.iter(), + params.iter(), ")", ",", - |arg| span_lo_for_arg(arg), - |arg| arg.ty.span.hi(), - |arg| { - arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)) - .or_else(|| Some(context.snippet(arg.span()).to_owned())) + |param| span_lo_for_param(param), + |param| param.ty.span.hi(), + |param| { + param + .rewrite(context, Shape::legacy(multi_line_budget, param_indent)) + .or_else(|| Some(context.snippet(param.span()).to_owned())) }, span.lo(), span.hi(), @@ -2470,11 +2471,11 @@ fn rewrite_args( .collect(); let tactic = definitive_tactic( - &arg_items, + ¶m_items, context .config .fn_args_layout() - .to_list_tactic(arg_items.len()), + .to_list_tactic(param_items.len()), Separator::Comma, one_line_budget, ); @@ -2484,7 +2485,7 @@ fn rewrite_args( }; let indent = match context.config.indent_style() { IndentStyle::Block => indent.block_indent(context.config), - IndentStyle::Visual => arg_indent, + IndentStyle::Visual => param_indent, }; let trailing_separator = if variadic { SeparatorTactic::Never @@ -2499,10 +2500,10 @@ fn rewrite_args( .trailing_separator(trailing_separator) .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) .preserve_newline(true); - write_list(&arg_items, &fmt) + write_list(¶m_items, &fmt) } -fn compute_budgets_for_args( +fn compute_budgets_for_params( context: &RewriteContext<'_>, result: &str, indent: Indent, @@ -2511,7 +2512,7 @@ fn compute_budgets_for_args( force_vertical_layout: bool, ) -> Option<((usize, usize, Indent))> { debug!( - "compute_budgets_for_args {} {:?}, {}, {:?}", + "compute_budgets_for_params {} {:?}, {}, {:?}", result.len(), indent, ret_str_len, @@ -2550,7 +2551,7 @@ fn compute_budgets_for_args( } } - // Didn't work. we must force vertical layout and put args on a newline. + // Didn't work. we must force vertical layout and put params on a newline. let new_indent = indent.block_indent(context.config); let used_space = match context.config.indent_style() { // 1 = `,` diff --git a/src/spanned.rs b/src/spanned.rs index 576085ae384..de02b79550f 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -106,7 +106,7 @@ impl Spanned for ast::Arm { impl Spanned for ast::Param { fn span(&self) -> Span { - if crate::items::is_named_arg(self) { + if crate::items::is_named_param(self) { mk_sp(self.pat.span.lo(), self.ty.span.hi()) } else { self.ty.span -- cgit 1.4.1-3-g733a5 From 7c9c0d1a39a84b7bf3efdbfe030c08519a61d668 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 26 Sep 2019 20:02:41 -0500 Subject: fix: merge_imports handling of ::{self} --- src/imports.rs | 10 ++++++++++ tests/source/merge_imports.rs | 7 +++++++ tests/target/merge_imports.rs | 6 ++++++ 3 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/imports.rs b/src/imports.rs index 61a359a498b..8f6c261cf30 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -543,6 +543,12 @@ impl UseTree { } match self.path.clone().last().unwrap() { UseSegment::List(list) => { + if list.len() == 1 && list[0].path.len() == 1 { + match list[0].path[0] { + UseSegment::Slf(..) => return vec![self], + _ => (), + }; + } let prefix = &self.path[..self.path.len() - 1]; let mut result = vec![]; for nested_use_tree in list { @@ -1018,6 +1024,10 @@ mod test { ["a::{c, d, b}", "a::{d, e, b, a, f}", "a::{f, g, c}"], ["a::{a, b, c, d, e, f, g}"] ); + test_merge!( + ["a::{self}", "b::{self as foo}"], + ["a::{self}", "b::{self as foo}"] + ); } #[test] diff --git a/tests/source/merge_imports.rs b/tests/source/merge_imports.rs index 7a2c5ca8e24..ec8eeeb8f7e 100644 --- a/tests/source/merge_imports.rs +++ b/tests/source/merge_imports.rs @@ -22,3 +22,10 @@ use a::{b::{c::*}}; use a::{b::{c::{}}}; use a::{b::{c::d}}; use a::{b::{c::{xxx, yyy, zzz}}}; + +// https://github.com/rust-lang/rustfmt/issues/3808 +use d::{self}; +use e::{self as foo}; +use f::{self, b}; +use g::a; +use g::{self, b}; diff --git a/tests/target/merge_imports.rs b/tests/target/merge_imports.rs index 63e5baacaba..8166bcb682c 100644 --- a/tests/target/merge_imports.rs +++ b/tests/target/merge_imports.rs @@ -14,3 +14,9 @@ use foo::{a, b, c}; pub use foo::{bar, foobar}; use a::b::c::{d, xxx, yyy, zzz, *}; + +// https://github.com/rust-lang/rustfmt/issues/3808 +use d::{self}; +use e::{self as foo}; +use f::{self, b}; +use g::{self, a, b}; -- cgit 1.4.1-3-g733a5 From f4bc4941531fbdfde423779b60946060b7f7cae6 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 2 Oct 2019 09:56:20 -0500 Subject: add --offline mode fallback to cargo fmt (#3813) --- src/cargo-fmt/main.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index c06df111566..acaf81e0665 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -519,9 +519,16 @@ fn get_cargo_metadata( if let Some(manifest_path) = manifest_path { cmd.manifest_path(manifest_path); } + match cmd.exec() { Ok(metadata) => Ok(metadata), - Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())), + Err(_) => { + cmd.other_options(&[String::from("--offline")]); + match cmd.exec() { + Ok(metadata) => Ok(metadata), + Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())), + } + } } } -- cgit 1.4.1-3-g733a5 From dbd89363913b2a35110077fed113aaa82b741079 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Wed, 2 Oct 2019 16:58:25 +0200 Subject: fix rust code in comment with a line containing only a hash sign (#3818) --- src/comment.rs | 3 ++- tests/source/issue-3751.rs | 10 ++++++++++ tests/target/issue-3751.rs | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue-3751.rs create mode 100644 tests/target/issue-3751.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 6222c34b1a2..e725adea6ba 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -823,7 +823,8 @@ fn rewrite_comment_inner( const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### "; fn hide_sharp_behind_comment(s: &str) -> Cow<'_, str> { - if s.trim_start().starts_with("# ") { + let s_trimmed = s.trim(); + if s_trimmed.starts_with("# ") || s_trimmed == "#" { Cow::from(format!("{}{}", RUSTFMT_CUSTOM_COMMENT_PREFIX, s)) } else { Cow::from(s) diff --git a/tests/source/issue-3751.rs b/tests/source/issue-3751.rs new file mode 100644 index 00000000000..1343f80e66e --- /dev/null +++ b/tests/source/issue-3751.rs @@ -0,0 +1,10 @@ +// rustfmt-format_code_in_doc_comments: true + +//! Empty pound line +//! +//! ```rust +//! # +//! # fn main() { +//! foo ( ) ; +//! # } +//! ``` diff --git a/tests/target/issue-3751.rs b/tests/target/issue-3751.rs new file mode 100644 index 00000000000..e5a03956e9d --- /dev/null +++ b/tests/target/issue-3751.rs @@ -0,0 +1,10 @@ +// rustfmt-format_code_in_doc_comments: true + +//! Empty pound line +//! +//! ```rust +//! # +//! # fn main() { +//! foo(); +//! # } +//! ``` -- cgit 1.4.1-3-g733a5 From e28ae8b4a33487bfafd4e4bad2c9bc82f32aa54a Mon Sep 17 00:00:00 2001 From: Matthew Pomes Date: Thu, 3 Oct 2019 21:24:33 -0500 Subject: Init Logger for unit tests (#3829) Add `init_log()` function which attempts to init logger, and ignores failure. The function is called at the beginning of every test, and will fail if the logger is already initialized. The logger must be initialized in every test, becuase cargo runs the tests in parallel, with no garentees about the order and time each starts. --- src/test/configuration_snippet.rs | 1 + src/test/mod.rs | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs index 55289f55537..ef7dd0ddcd1 100644 --- a/src/test/configuration_snippet.rs +++ b/src/test/configuration_snippet.rs @@ -247,6 +247,7 @@ impl ConfigCodeBlock { #[test] fn configuration_snippet_tests() { + super::init_log(); let blocks = get_code_blocks(); let failures = blocks .iter() diff --git a/src/test/mod.rs b/src/test/mod.rs index 3793a98ab00..8931f62fa23 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -40,6 +40,10 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ "cfg_mod/wasm32.rs", ]; +fn init_log() { + let _ = env_logger::builder().is_test(true).try_init(); +} + struct TestSetting { /// The size of the stack of the thread that run tests. stack_size: usize, @@ -137,6 +141,7 @@ fn verify_config_used(path: &Path, config_name: &str) { #[test] fn verify_config_test_names() { + init_log(); for path in &[ Path::new("tests/source/configs"), Path::new("tests/target/configs"), @@ -169,6 +174,7 @@ fn write_message(msg: &str) { // exactly. #[test] fn system_tests() { + init_log(); run_test_with(&TestSetting::default(), || { // Get all files in the tests/source directory. let files = get_test_files(Path::new("tests/source"), true); @@ -189,6 +195,7 @@ fn system_tests() { // The only difference is the coverage mode. #[test] fn coverage_tests() { + init_log(); let files = get_test_files(Path::new("tests/coverage/source"), true); let (_reports, count, fails) = check_files(files, &None); @@ -198,6 +205,7 @@ fn coverage_tests() { #[test] fn checkstyle_test() { + init_log(); let filename = "tests/writemode/source/fn-single-line.rs"; let expected_filename = "tests/writemode/target/checkstyle.xml"; assert_output(Path::new(filename), Path::new(expected_filename)); @@ -205,6 +213,7 @@ fn checkstyle_test() { #[test] fn json_test() { + init_log(); let filename = "tests/writemode/source/json.rs"; let expected_filename = "tests/writemode/target/output.json"; assert_output(Path::new(filename), Path::new(expected_filename)); @@ -212,6 +221,7 @@ fn json_test() { #[test] fn modified_test() { + init_log(); use std::io::BufRead; // Test "modified" output @@ -297,6 +307,7 @@ fn assert_output(source: &Path, expected_filename: &Path) { // rustfmt. #[test] fn idempotence_tests() { + init_log(); run_test_with(&TestSetting::default(), || { // these tests require nightly if !is_nightly_channel!() { @@ -321,6 +332,7 @@ fn idempotence_tests() { // no warnings are emitted. #[test] fn self_tests() { + init_log(); // Issue-3443: these tests require nightly if !is_nightly_channel!() { return; @@ -359,6 +371,7 @@ fn self_tests() { #[test] fn stdin_formatting_smoke_test() { + init_log(); let input = Input::Text("fn main () {}".to_owned()); let mut config = Config::default(); config.set().emit_mode(EmitMode::Stdout); @@ -377,6 +390,7 @@ fn stdin_formatting_smoke_test() { #[test] fn stdin_parser_panic_caught() { + init_log(); // See issue #3239. for text in ["{", "}"].iter().cloned().map(String::from) { let mut buf = vec![]; @@ -391,6 +405,7 @@ fn stdin_parser_panic_caught() { /// when embedding Rustfmt (e.g. inside RLS). #[test] fn stdin_works_with_modified_lines() { + init_log(); let input = "\nfn\n some( )\n{\n}\nfn main () {}\n"; let output = "1 6 2\nfn some() {}\nfn main() {}\n"; @@ -413,6 +428,7 @@ fn stdin_works_with_modified_lines() { #[test] fn stdin_disable_all_formatting_test() { + init_log(); match option_env!("CFG_RELEASE_CHANNEL") { None | Some("nightly") => {} // These tests require nightly. @@ -441,6 +457,7 @@ fn stdin_disable_all_formatting_test() { #[test] fn format_lines_errors_are_reported() { + init_log(); let long_identifier = String::from_utf8(vec![b'a'; 239]).unwrap(); let input = Input::Text(format!("fn {}() {{}}", long_identifier)); let mut config = Config::default(); @@ -452,6 +469,7 @@ fn format_lines_errors_are_reported() { #[test] fn format_lines_errors_are_reported_with_tabs() { + init_log(); let long_identifier = String::from_utf8(vec![b'a'; 97]).unwrap(); let input = Input::Text(format!("fn a() {{\n\t{}\n}}", long_identifier)); let mut config = Config::default(); @@ -719,6 +737,7 @@ fn get_target(file_name: &Path, target: Option<&str>) -> PathBuf { #[test] fn rustfmt_diff_make_diff_tests() { + init_log(); let diff = make_diff("a\nb\nc\nd", "a\ne\nc\nd", 3); assert_eq!( diff, @@ -738,6 +757,7 @@ fn rustfmt_diff_make_diff_tests() { #[test] fn rustfmt_diff_no_diff_test() { + init_log(); let diff = make_diff("a\nb\nc\nd", "a\nb\nc\nd", 3); assert_eq!(diff, vec![]); } @@ -772,6 +792,7 @@ impl<'a> Iterator for CharsIgnoreNewlineRepr<'a> { #[test] fn string_eq_ignore_newline_repr_test() { + init_log(); assert!(string_eq_ignore_newline_repr("", "")); assert!(!string_eq_ignore_newline_repr("", "abc")); assert!(!string_eq_ignore_newline_repr("abc", "")); @@ -833,6 +854,7 @@ fn rustfmt() -> PathBuf { #[test] fn verify_check_works() { + init_log(); let temp_file = make_temp_file("temp_check.rs"); Command::new(rustfmt().to_str().unwrap()) -- cgit 1.4.1-3-g733a5 From 7926851bb015a31ca9174cde9214aa27aac0d7af Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Fri, 4 Oct 2019 11:25:17 +0900 Subject: stop to strip 'impl' from impl trait type alias (#3816) --- src/items.rs | 15 ++++++++++++++- tests/source/existential_type.rs | 8 ++++++++ tests/target/existential_type.rs | 12 ++++++++++-- tests/target/issue-3815.rs | 4 ++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 tests/target/issue-3815.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cdf9fa06eef..053e856b9f1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1118,6 +1118,18 @@ pub(crate) fn format_trait( } } +struct OpaqueTypeBounds<'a> { + generic_bounds: &'a ast::GenericBounds, +} + +impl<'a> Rewrite for OpaqueTypeBounds<'a> { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.generic_bounds + .rewrite(context, shape) + .map(|s| format!("impl {}", s)) + } +} + pub(crate) struct TraitAliasBounds<'a> { generic_bounds: &'a ast::GenericBounds, generics: &'a ast::Generics, @@ -1524,13 +1536,14 @@ pub(crate) fn rewrite_opaque_type( generics: &ast::Generics, vis: &ast::Visibility, ) -> Option { + let opaque_type_bounds = OpaqueTypeBounds { generic_bounds }; rewrite_type_item( context, indent, "type", " =", ident, - generic_bounds, + &opaque_type_bounds, generics, vis, ) diff --git a/tests/source/existential_type.rs b/tests/source/existential_type.rs index 92412fca879..33bb9a95159 100644 --- a/tests/source/existential_type.rs +++ b/tests/source/existential_type.rs @@ -13,3 +13,11 @@ pub type Adderrr = impl Fn( T ) -> T; impl Foo for Bar { type E = impl Trait; } + +pub type Adder_without_impl +where + T: Clone, + F: Copy + = Fn(T) -> T; + +pub type Adderrr_without_impl = Fn( T ) -> T; diff --git a/tests/target/existential_type.rs b/tests/target/existential_type.rs index 869ffda2378..ffc206875b5 100644 --- a/tests/target/existential_type.rs +++ b/tests/target/existential_type.rs @@ -6,10 +6,18 @@ pub type Adder where T: Clone, F: Copy, -= Fn(T) -> T; += impl Fn(T) -> T; -pub type Adderrr = Fn(T) -> T; +pub type Adderrr = impl Fn(T) -> T; impl Foo for Bar { type E = impl Trait; } + +pub type Adder_without_impl +where + T: Clone, + F: Copy, += Fn(T) -> T; + +pub type Adderrr_without_impl = Fn(T) -> T; diff --git a/tests/target/issue-3815.rs b/tests/target/issue-3815.rs new file mode 100644 index 00000000000..eff27e2de3c --- /dev/null +++ b/tests/target/issue-3815.rs @@ -0,0 +1,4 @@ +pub type Type = impl Deref; + +pub type Type = + impl VeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeryLongType; -- cgit 1.4.1-3-g733a5 From fb01dc857c2c073eedfa02ce37f6189a9972f838 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 4 Oct 2019 17:22:01 +0200 Subject: do not force comments to be indented with a comment trailing a line of code (#3833) --- src/missed_spans.rs | 42 +++++++++++++++++++--- src/utils.rs | 13 +++++-- src/visitor.rs | 73 +++++++++++++++++++++++++++------------ tests/source/trailing_comments.rs | 21 +++++++++++ tests/target/trailing_comments.rs | 30 ++++++++++++++++ 5 files changed, 150 insertions(+), 29 deletions(-) create mode 100644 tests/source/trailing_comments.rs create mode 100644 tests/target/trailing_comments.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 7bc81fdc844..a6800b15e61 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -3,10 +3,11 @@ use syntax::source_map::{BytePos, Pos, Span}; use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileLines; use crate::config::FileName; +use crate::config::Version; use crate::coverage::transform_missing_snippet; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; -use crate::utils::{count_lf_crlf, count_newlines, last_line_width, mk_sp}; +use crate::utils::{count_lf_crlf, count_newlines, last_line_indent, last_line_width, mk_sp}; use crate::visitor::FmtVisitor; struct SnippetStatus { @@ -238,6 +239,7 @@ impl<'a> FmtVisitor<'a> { .next(); let fix_indent = last_char.map_or(true, |rev_c| ['{', '\n'].contains(&rev_c)); + let mut on_same_line = false; let comment_indent = if fix_indent { if let Some('{') = last_char { @@ -246,6 +248,13 @@ impl<'a> FmtVisitor<'a> { let indent_str = self.block_indent.to_string(self.config); self.push_str(&indent_str); self.block_indent + } else if self.config.version() == Version::Two && !snippet.starts_with('\n') { + // The comment appears on the same line as the previous formatted code. + // Assuming that comment is logically associated with that code, we want to keep it on + // the same level and avoid mixing it with possible other comment. + on_same_line = true; + self.push_str(" "); + Indent::from_width(self.config, last_line_indent(&self.buffer)) } else { self.push_str(" "); Indent::from_width(self.config, last_line_width(&self.buffer)) @@ -256,9 +265,34 @@ impl<'a> FmtVisitor<'a> { self.config.max_width() - self.block_indent.width(), ); let comment_shape = Shape::legacy(comment_width, comment_indent); - let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) - .unwrap_or_else(|| String::from(subslice)); - self.push_str(&comment_str); + + if on_same_line { + match subslice.find("\n") { + None => { + self.push_str(subslice); + } + Some(offset) if offset + 1 == subslice.len() => { + self.push_str(&subslice[..offset]); + } + Some(offset) => { + // keep first line as is: if it were too long and wrapped, it may get mixed + // with the other lines. + let first_line = &subslice[..offset]; + self.push_str(first_line); + self.push_str(&comment_indent.to_string_with_newline(self.config)); + + let other_lines = &subslice[offset + 1..]; + let comment_str = + rewrite_comment(other_lines, false, comment_shape, self.config) + .unwrap_or_else(|| String::from(other_lines)); + self.push_str(&comment_str); + } + } + } else { + let comment_str = rewrite_comment(subslice, false, comment_shape, self.config) + .unwrap_or_else(|| String::from(subslice)); + self.push_str(&comment_str); + } status.last_wspace = None; status.line_start = offset + subslice.len(); diff --git a/src/utils.rs b/src/utils.rs index bad9bc1d788..76af95a8c7f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -193,19 +193,26 @@ pub(crate) fn is_attributes_extendable(attrs_str: &str) -> bool { !attrs_str.contains('\n') && !last_line_contains_single_line_comment(attrs_str) } -// The width of the first line in s. +/// The width of the first line in s. #[inline] pub(crate) fn first_line_width(s: &str) -> usize { unicode_str_width(s.splitn(2, '\n').next().unwrap_or("")) } -// The width of the last line in s. +/// The width of the last line in s. #[inline] pub(crate) fn last_line_width(s: &str) -> usize { unicode_str_width(s.rsplitn(2, '\n').next().unwrap_or("")) } -// The total used width of the last line. +/// The indent width of the last line in s. +#[inline] +pub(crate) fn last_line_indent(s: &str) -> usize { + let last_line = s.rsplitn(2, '\n').next().unwrap_or(""); + last_line.chars().take_while(|c| c.is_whitespace()).count() +} + +/// The total used width of the last line. #[inline] pub(crate) fn last_line_used_width(s: &str, offset: usize) -> usize { if s.contains('\n') { diff --git a/src/visitor.rs b/src/visitor.rs index 49197682c14..8a1b3cd71fe 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -7,6 +7,7 @@ use syntax::{ast, visit}; use crate::attr::*; use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::config::Version; use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; use crate::items::{ @@ -252,32 +253,60 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let mut comment_shape = Shape::indented(self.block_indent, config).comment(config); - if comment_on_same_line { - // 1 = a space before `//` - let offset_len = 1 + last_line_width(&self.buffer) - .saturating_sub(self.block_indent.width()); - match comment_shape - .visual_indent(offset_len) - .sub_width(offset_len) - { - Some(shp) => comment_shape = shp, - None => comment_on_same_line = false, - } - }; - - if comment_on_same_line { + if self.config.version() == Version::Two && comment_on_same_line { self.push_str(" "); + // put the first line of the comment on the same line as the + // block's last line + match sub_slice.find("\n") { + None => { + self.push_str(&sub_slice); + } + Some(offset) if offset + 1 == sub_slice.len() => { + self.push_str(&sub_slice[..offset]); + } + Some(offset) => { + let first_line = &sub_slice[..offset]; + self.push_str(first_line); + self.push_str(&self.block_indent.to_string_with_newline(config)); + + // put the other lines below it, shaping it as needed + let other_lines = &sub_slice[offset + 1..]; + let comment_str = + rewrite_comment(other_lines, false, comment_shape, config); + match comment_str { + Some(ref s) => self.push_str(s), + None => self.push_str(other_lines), + } + } + } } else { - if count_newlines(snippet_in_between) >= 2 || extra_newline { - self.push_str("\n"); + if comment_on_same_line { + // 1 = a space before `//` + let offset_len = 1 + last_line_width(&self.buffer) + .saturating_sub(self.block_indent.width()); + match comment_shape + .visual_indent(offset_len) + .sub_width(offset_len) + { + Some(shp) => comment_shape = shp, + None => comment_on_same_line = false, + } + }; + + if comment_on_same_line { + self.push_str(" "); + } else { + if count_newlines(snippet_in_between) >= 2 || extra_newline { + self.push_str("\n"); + } + self.push_str(&self.block_indent.to_string_with_newline(config)); } - self.push_str(&self.block_indent.to_string_with_newline(config)); - } - let comment_str = rewrite_comment(&sub_slice, false, comment_shape, config); - match comment_str { - Some(ref s) => self.push_str(s), - None => self.push_str(&sub_slice), + let comment_str = rewrite_comment(&sub_slice, false, comment_shape, config); + match comment_str { + Some(ref s) => self.push_str(s), + None => self.push_str(&sub_slice), + } } } CodeCharKind::Normal if skip_normal(&sub_slice) => { diff --git a/tests/source/trailing_comments.rs b/tests/source/trailing_comments.rs new file mode 100644 index 00000000000..7845f713b8a --- /dev/null +++ b/tests/source/trailing_comments.rs @@ -0,0 +1,21 @@ +// rustfmt-version: Two +// rustfmt-wrap_comments: true + +pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast +// Multicast using broadcst. add. + +pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE +pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE +pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX +//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX +//const SQ_GRANT: u16 = 0x0012; // GRANT +//const SQ_REVOKE: u16 = 0x0013; // REVOKE + +fn foo() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. In hac habitasse platea dictumst. Vivamus a orci at nulla tristique condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc. + let b = baz(); + + let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] + // TODO(emilio): It may make sense to make this range [.01, 10.0], to align with css-fonts-4's range of [1, 1000]. +} diff --git a/tests/target/trailing_comments.rs b/tests/target/trailing_comments.rs new file mode 100644 index 00000000000..eba943042ad --- /dev/null +++ b/tests/target/trailing_comments.rs @@ -0,0 +1,30 @@ +// rustfmt-version: Two +// rustfmt-wrap_comments: true + +pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast +// Multicast using broadcst. add. + +pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE +pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE +pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX +//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX +//const SQ_GRANT: u16 = 0x0012; // GRANT +//const SQ_REVOKE: u16 = 0x0013; // REVOKE + +fn foo() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis + // malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at + // nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci + // bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc + // suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a + // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. + // In hac habitasse platea dictumst. Vivamus a orci at nulla tristique + // condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit + // amet, ipsum. In pharetra sagittis nunc. + let b = baz(); + + let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] + // TODO(emilio): It may make sense to make this range [.01, 10.0], to align + // with css-fonts-4's range of [1, 1000]. +} -- cgit 1.4.1-3-g733a5 From 383306e5feaddf71314653a7a39018bbe03e080e Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sat, 5 Oct 2019 23:40:24 +0900 Subject: Update rustc-ap-* crates to 606.0.0 (#3835) --- Cargo.lock | 229 +++++++++++++++++-------------------------------- Cargo.toml | 16 +++- src/attr.rs | 8 +- src/chains.rs | 10 +-- src/closures.rs | 20 ++--- src/expr.rs | 32 +++---- src/formatting.rs | 18 ++-- src/imports.rs | 2 +- src/items.rs | 36 ++++---- src/macros.rs | 2 +- src/matches.rs | 12 +-- src/modules.rs | 8 +- src/modules/visitor.rs | 8 +- src/overflow.rs | 4 +- src/pairs.rs | 6 +- src/patterns.rs | 8 +- src/reorder.rs | 8 +- src/spanned.rs | 2 +- src/stmt.rs | 8 +- src/types.rs | 6 +- src/utils.rs | 14 +-- src/visitor.rs | 10 +-- 22 files changed, 202 insertions(+), 265 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 06bead7f25d..38d97a9c4eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,11 +46,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "autocfg" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "backtrace" version = "0.3.37" @@ -253,7 +248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ena" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -413,11 +408,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -451,14 +445,6 @@ dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "packed_simd" version = "0.3.3" @@ -469,20 +455,23 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -535,33 +524,6 @@ dependencies = [ "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -575,32 +537,6 @@ name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_os" version = "0.1.3" @@ -614,23 +550,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rdrand" version = "0.4.0" @@ -683,33 +602,34 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_data_structures" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -719,23 +639,32 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_index" +version = "606.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_lexer" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -743,7 +672,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -755,19 +684,20 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -776,33 +706,34 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -881,9 +812,9 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", @@ -919,6 +850,11 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "semver" version = "0.9.0" @@ -1177,7 +1113,6 @@ dependencies = [ "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" "checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" @@ -1202,7 +1137,7 @@ dependencies = [ "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" +"checksum ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" @@ -1221,48 +1156,41 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5" -"checksum rustc-ap-graphviz 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142" -"checksum rustc-ap-rustc_data_structures 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36" -"checksum rustc-ap-rustc_errors 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333" -"checksum rustc-ap-rustc_lexer 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305" -"checksum rustc-ap-rustc_macros 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f" -"checksum rustc-ap-rustc_target 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2" -"checksum rustc-ap-serialize 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6" -"checksum rustc-ap-syntax 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9" -"checksum rustc-ap-syntax_pos 583.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213" +"checksum rustc-ap-arena 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009" +"checksum rustc-ap-graphviz 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6" +"checksum rustc-ap-rustc_data_structures 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4" +"checksum rustc-ap-rustc_errors 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb" +"checksum rustc-ap-rustc_index 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea" +"checksum rustc-ap-rustc_lexer 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139" +"checksum rustc-ap-rustc_macros 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0" +"checksum rustc-ap-rustc_target 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1" +"checksum rustc-ap-serialize 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20" +"checksum rustc-ap-syntax 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e" +"checksum rustc-ap-syntax_pos 606.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" @@ -1273,6 +1201,7 @@ dependencies = [ "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" diff --git a/Cargo.toml b/Cargo.toml index 26427ed9a5a..080f1e8ff1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,9 +47,6 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -rustc-ap-rustc_target = "583.0.0" -rustc-ap-syntax = "583.0.0" -rustc-ap-syntax_pos = "583.0.0" failure = "0.1.3" bytecount = "0.6" unicode-width = "0.1.5" @@ -58,7 +55,6 @@ dirs = "2.0.1" ignore = "0.4.6" annotate-snippets = { version = "0.6", features = ["ansi_term"] } structopt = "0.3" - rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } # A noop dependency that changes in the Rust repository, it's a bit of a hack. @@ -66,5 +62,17 @@ rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } # for more information. rustc-workspace-hack = "1.0.0" +[dependencies.rustc_target] +package = "rustc-ap-rustc_target" +version = "606.0.0" + +[dependencies.syntax] +package = "rustc-ap-syntax" +version = "606.0.0" + +[dependencies.syntax_pos] +package = "rustc-ap-syntax_pos" +version = "606.0.0" + [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/attr.rs b/src/attr.rs index 7270215ccbb..63a01e56603 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -20,7 +20,7 @@ mod doc_comment; /// Returns attributes on the given statement. pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { - match stmt.node { + match stmt.kind { ast::StmtKind::Local(ref local) => &local.attrs, ast::StmtKind::Item(ref item) => &item.attrs, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, @@ -29,7 +29,7 @@ pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { } pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { - match stmt.node { + match stmt.kind { ast::StmtKind::Local(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, @@ -218,7 +218,7 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) { impl Rewrite for ast::MetaItem { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - Some(match self.node { + Some(match self.kind { ast::MetaItemKind::Word => { rewrite_path(context, PathContext::Type, None, &self.path, shape)? } @@ -495,7 +495,7 @@ fn attr_prefix(attr: &ast::Attribute) -> &'static str { pub(crate) trait MetaVisitor<'ast> { fn visit_meta_item(&mut self, meta_item: &'ast ast::MetaItem) { - match meta_item.node { + match meta_item.kind { ast::MetaItemKind::Word => self.visit_meta_word(meta_item), ast::MetaItemKind::List(ref list) => self.visit_meta_list(meta_item, list), ast::MetaItemKind::NameValue(ref lit) => self.visit_meta_name_value(meta_item, lit), diff --git a/src/chains.rs b/src/chains.rs index 56775c4b5ef..ff8d7214c54 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -135,7 +135,7 @@ impl ChainItemKind { } fn is_tup_field_access(expr: &ast::Expr) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::Field(_, ref field) => { field.name.to_string().chars().all(|c| c.is_digit(10)) } @@ -144,7 +144,7 @@ impl ChainItemKind { } fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) { - let (kind, span) = match expr.node { + let (kind, span) = match expr.kind { ast::ExprKind::MethodCall(ref segment, ref expressions) => { let types = if let Some(ref generic_args) = segment.args { if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { @@ -262,7 +262,7 @@ impl Chain { let mut rev_children = vec![]; let mut sub_tries = 0; for subexpr in &subexpr_list { - match subexpr.node { + match subexpr.kind { ast::ExprKind::Try(_) => sub_tries += 1, _ => { rev_children.push(ChainItem::new(context, subexpr, sub_tries)); @@ -390,7 +390,7 @@ impl Chain { // Returns the expression's subexpression, if it exists. When the subexpr // is a try! macro, we'll convert it to shorthand when the option is set. fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option { - match expr.node { + match expr.kind { ast::ExprKind::MethodCall(_, ref expressions) => { Some(Self::convert_try(&expressions[0], context)) } @@ -402,7 +402,7 @@ impl Chain { } fn convert_try(expr: &ast::Expr, context: &RewriteContext<'_>) -> ast::Expr { - match expr.node { + match expr.kind { ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { if let Some(subexpr) = convert_try_mac(mac, context) { subexpr diff --git a/src/closures.rs b/src/closures.rs index c89ba4c5cdc..1b877f5ef97 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -40,7 +40,7 @@ pub(crate) fn rewrite_closure( // 1 = space between `|...|` and body. let body_shape = shape.offset_left(extra_offset)?; - if let ast::ExprKind::Block(ref block, _) = body.node { + if let ast::ExprKind::Block(ref block, _) = body.kind { // The body of the closure is an empty block. if block.stmts.is_empty() && !block_contains_comment(block, context.source_map) { return body @@ -89,7 +89,7 @@ fn get_inner_expr<'a>( prefix: &str, context: &RewriteContext<'_>, ) -> &'a ast::Expr { - if let ast::ExprKind::Block(ref block, _) = expr.node { + if let ast::ExprKind::Block(ref block, _) = expr.kind { if !needs_block(block, prefix, context) { // block.stmts.len() == 1 if let Some(expr) = stmt_expr(&block.stmts[0]) { @@ -110,7 +110,7 @@ fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) - } fn veto_block(e: &ast::Expr) -> bool { - match e.node { + match e.kind { ast::ExprKind::Call(..) | ast::ExprKind::Binary(..) | ast::ExprKind::Cast(..) @@ -141,7 +141,7 @@ fn rewrite_closure_with_block( let block = ast::Block { stmts: vec![ast::Stmt { id: ast::NodeId::root(), - node: ast::StmtKind::Expr(ptr::P(body.clone())), + kind: ast::StmtKind::Expr(ptr::P(body.clone())), span: body.span, }], id: ast::NodeId::root(), @@ -161,7 +161,7 @@ fn rewrite_closure_expr( shape: Shape, ) -> Option { fn allow_multi_line(expr: &ast::Expr) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::Match(..) | ast::ExprKind::Block(..) | ast::ExprKind::TryBlock(..) @@ -291,9 +291,9 @@ pub(crate) fn rewrite_last_closure( shape: Shape, ) -> Option { if let ast::ExprKind::Closure(capture, ref is_async, movability, ref fn_decl, ref body, _) = - expr.node + expr.kind { - let body = match body.node { + let body = match body.kind { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() @@ -353,7 +353,7 @@ pub(crate) fn rewrite_last_closure( pub(crate) fn args_have_many_closure(args: &[OverflowableItem<'_>]) -> bool { args.iter() .filter_map(OverflowableItem::to_expr) - .filter(|expr| match expr.node { + .filter(|expr| match expr.kind { ast::ExprKind::Closure(..) => true, _ => false, }) @@ -371,7 +371,7 @@ fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bo } fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true, ast::ExprKind::Loop(..) if version == Version::Two => true, ast::ExprKind::AddrOf(_, ref expr) @@ -392,7 +392,7 @@ fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { /// isn't parsed as (if true {...} else {...} | x) | 5 // From https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/classify.rs. fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool { - match e.node { + match e.kind { ast::ExprKind::If(..) | ast::ExprKind::Match(..) | ast::ExprKind::Block(..) diff --git a/src/expr.rs b/src/expr.rs index 93289b58282..86bb98d3ea8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -65,7 +65,7 @@ pub(crate) fn format_expr( shape }; - let expr_rw = match expr.node { + let expr_rw = match expr.kind { ast::ExprKind::Array(ref expr_vec) => rewrite_array( "", expr_vec.iter(), @@ -250,8 +250,8 @@ pub(crate) fn format_expr( }; fn needs_space_before_range(context: &RewriteContext<'_>, lhs: &ast::Expr) -> bool { - match lhs.node { - ast::ExprKind::Lit(ref lit) => match lit.node { + match lhs.kind { + ast::ExprKind::Lit(ref lit) => match lit.kind { ast::LitKind::FloatUnsuffixed(..) => { context.snippet(lit.span).ends_with('.') } @@ -262,7 +262,7 @@ pub(crate) fn format_expr( } fn needs_space_after_range(rhs: &ast::Expr) -> bool { - match rhs.node { + match rhs.kind { // Don't format `.. ..` into `....`, which is invalid. // // This check is unnecessary for `lhs`, because a range @@ -575,7 +575,7 @@ pub(crate) fn rewrite_cond( expr: &ast::Expr, shape: Shape, ) -> Option { - match expr.node { + match expr.kind { ast::ExprKind::Match(ref cond, _) => { // `match `cond` {` let cond_shape = match context.config.indent_style() { @@ -612,7 +612,7 @@ struct ControlFlow<'a> { } fn extract_pats_and_cond(expr: &ast::Expr) -> (Option<&ast::Pat>, &ast::Expr) { - match expr.node { + match expr.kind { ast::ExprKind::Let(ref pat, ref cond) => (Some(pat), cond), _ => (None, expr), } @@ -620,7 +620,7 @@ fn extract_pats_and_cond(expr: &ast::Expr) -> (Option<&ast::Pat>, &ast::Expr) { // FIXME: Refactor this. fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option> { - match expr.node { + match expr.kind { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { let (pat, cond) = extract_pats_and_cond(cond); Some(ControlFlow::new_if( @@ -748,7 +748,7 @@ impl<'a> ControlFlow<'a> { let else_block = self.else_block?; let fixed_cost = self.keyword.len() + " { } else { }".len(); - if let ast::ExprKind::Block(ref else_node, _) = else_block.node { + if let ast::ExprKind::Block(ref else_node, _) = else_block.kind { if !is_simple_block(self.block, None, context.source_map) || !is_simple_block(else_node, None, context.source_map) || pat_expr_str.contains('\n') @@ -1014,7 +1014,7 @@ impl<'a> Rewrite for ControlFlow<'a> { if let Some(else_block) = self.else_block { let shape = Shape::indented(shape.indent, context.config); let mut last_in_chain = false; - let rewrite = match else_block.node { + let rewrite = match else_block.kind { // If the else expression is another if-else expression, prevent it // from being formatted on a single line. // Note how we're passing the original shape, as the @@ -1149,7 +1149,7 @@ pub(crate) fn is_empty_block( } pub(crate) fn stmt_is_expr(stmt: &ast::Stmt) -> bool { - match stmt.node { + match stmt.kind { ast::StmtKind::Expr(..) => true, _ => false, } @@ -1168,7 +1168,7 @@ pub(crate) fn rewrite_literal( l: &ast::Lit, shape: Shape, ) -> Option { - match l.node { + match l.kind { ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape), _ => wrap_str( context.snippet(l.span).to_owned(), @@ -1253,7 +1253,7 @@ pub(crate) fn rewrite_call( } pub(crate) fn is_simple_expr(expr: &ast::Expr) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, ast::ExprKind::AddrOf(_, ref expr) @@ -1279,7 +1279,7 @@ pub(crate) fn can_be_overflowed_expr( expr: &ast::Expr, args_len: usize, ) -> bool { - match expr.node { + match expr.kind { _ if !expr.attrs.is_empty() => false, ast::ExprKind::Match(..) => { (context.use_block_indent() && args_len == 1) @@ -1324,7 +1324,7 @@ pub(crate) fn can_be_overflowed_expr( } pub(crate) fn is_nested_call(expr: &ast::Expr) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, ast::ExprKind::AddrOf(_, ref expr) | ast::ExprKind::Box(ref expr) @@ -1380,7 +1380,7 @@ fn rewrite_paren( post_comment = rewrite_missing_comment(post_span, shape, context)?; // Remove nested parens if there are no comments. - if let ast::ExprKind::Paren(ref subsubexpr) = subexpr.node { + if let ast::ExprKind::Paren(ref subsubexpr) = subexpr.kind { if remove_nested_parens && pre_comment.is_empty() && post_comment.is_empty() { span = subexpr.span; subexpr = subsubexpr; @@ -1985,7 +1985,7 @@ fn rewrite_expr_addrof( } pub(crate) fn is_method_call(expr: &ast::Expr) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::MethodCall(..) => true, ast::ExprKind::AddrOf(_, ref expr) | ast::ExprKind::Box(ref expr) diff --git a/src/formatting.rs b/src/formatting.rs index b58911705c0..3635f078e96 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -8,7 +8,7 @@ use std::time::{Duration, Instant}; use syntax::ast; use syntax::errors::emitter::{ColorConfig, Emitter}; -use syntax::errors::{DiagnosticBuilder, Handler}; +use syntax::errors::{Diagnostic, DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; @@ -640,12 +640,6 @@ fn parse_crate( .map(|mut parser| { parser.recurse_into_file_modules = false; parser - }) - .map_err(|diags| { - diags - .into_iter() - .map(|d| DiagnosticBuilder::new_diagnostic(&parse_session.span_diagnostic, d)) - .collect::>() }), }; @@ -659,7 +653,13 @@ fn parse_crate( let mut parser = AssertUnwindSafe(parser); catch_unwind(move || parser.0.parse_crate_mod().map_err(|d| vec![d])) } - Err(db) => Ok(Err(db)), + Err(diagnostics) => { + for diagnostic in diagnostics { + parse_session.span_diagnostic.emit_diagnostic(&diagnostic); + } + report.add_parsing_error(); + return Err(ErrorKind::ParseError); + } }; match result { @@ -687,7 +687,7 @@ fn parse_crate( struct SilentEmitter; impl Emitter for SilentEmitter { - fn emit_diagnostic(&mut self, _db: &DiagnosticBuilder<'_>) {} + fn emit_diagnostic(&mut self, _db: &Diagnostic) {} } fn silent_emitter() -> Box { diff --git a/src/imports.rs b/src/imports.rs index 8f6c261cf30..139301f537a 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -287,7 +287,7 @@ impl UseTree { context: &RewriteContext<'_>, item: &ast::Item, ) -> Option { - match item.node { + match item.kind { ast::ItemKind::Use(ref use_tree) => Some( UseTree::from_ast( context, diff --git a/src/items.rs b/src/items.rs index 053e856b9f1..e10265df0ef 100644 --- a/src/items.rs +++ b/src/items.rs @@ -595,7 +595,7 @@ impl<'a> FmtVisitor<'a> { } } - buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { + buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) { (TyAlias(..), TyAlias(..)) | (Const(..), Const(..)) | (Macro(..), Macro(..)) @@ -616,14 +616,14 @@ impl<'a> FmtVisitor<'a> { // different impl items. if prev_kind .as_ref() - .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node)) + .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.kind)) { self.push_str("\n"); } let indent_str = self.block_indent.to_string_with_newline(self.config); self.push_str(&indent_str); self.push_str(buf.trim()); - prev_kind = Some(item.node.clone()); + prev_kind = Some(item.kind.clone()); } } else { for item in items { @@ -638,7 +638,7 @@ pub(crate) fn format_impl( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node { + if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.kind { let mut result = String::with_capacity(128); let ref_and_type = format_impl_ref_and_type(context, item, offset)?; let sep = offset.to_string_with_newline(context.config); @@ -794,7 +794,7 @@ fn format_impl_ref_and_type( ref trait_ref, ref self_ty, _, - ) = item.node + ) = item.kind { let mut result = String::with_capacity(128); @@ -928,7 +928,7 @@ impl<'a> StructParts<'a> { } pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (prefix, def, generics) = match item.node { + let (prefix, def, generics) = match item.kind { ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics), ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics), _ => unreachable!(), @@ -972,7 +972,7 @@ pub(crate) fn format_trait( ref generics, ref generic_bounds, ref trait_items, - ) = item.node + ) = item.kind { let mut result = String::with_capacity(128); let header = format!( @@ -1656,7 +1656,7 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (prefix, ty, mutability, expr) = match item.node { + let (prefix, ty, mutability, expr) = match item.kind { ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), ast::ItemKind::Const(ref ty, ref expr) => { ("const", ty, ast::Mutability::Immutable, expr) @@ -1676,7 +1676,7 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::TraitItem) -> Self { - let (ty, expr_opt) = match ti.node { + let (ty, expr_opt) = match ti.kind { ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), _ => unreachable!(), }; @@ -1693,7 +1693,7 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::ImplItem) -> Self { - let (ty, expr) = match ii.node { + let (ty, expr) = match ii.kind { ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), _ => unreachable!(), }; @@ -1874,7 +1874,7 @@ impl Rewrite for ast::FunctionRetTy { } fn is_empty_infer(ty: &ast::Ty, pat_span: Span) -> bool { - match ty.node { + match ty.kind { ast::TyKind::Infer => ty.span.hi() == pat_span.hi(), _ => false, } @@ -2048,7 +2048,7 @@ pub(crate) fn span_lo_for_param(param: &ast::Param) -> BytePos { } pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param) -> BytePos { - match param.ty.node { + match param.ty.kind { ast::TyKind::Infer if context.snippet(param.ty.span) == "_" => param.ty.span.hi(), ast::TyKind::Infer if is_named_param(param) => param.pat.span.hi(), _ => param.ty.span.hi(), @@ -2056,7 +2056,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param } pub(crate) fn is_named_param(param: &ast::Param) -> bool { - if let ast::PatKind::Ident(_, ident, _) = param.pat.node { + if let ast::PatKind::Ident(_, ident, _) = param.pat.kind { ident.name != symbol::kw::Invalid } else { true @@ -2182,7 +2182,7 @@ fn rewrite_fn_base( indent, param_indent, params_span, - fd.c_variadic, + fd.c_variadic(), )?; let put_params_in_block = match context.config.indent_style() { @@ -3024,7 +3024,7 @@ impl Rewrite for ast::ForeignItem { // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - let item_str = match self.node { + let item_str = match self.kind { ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => rewrite_fn_base( context, shape.indent, @@ -3146,21 +3146,21 @@ pub(crate) fn rewrite_extern_crate( /// Returns `true` for `mod foo;`, false for `mod foo { .. }`. pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { - match item.node { + match item.kind { ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), _ => false, } } pub(crate) fn is_use_item(item: &ast::Item) -> bool { - match item.node { + match item.kind { ast::ItemKind::Use(_) => true, _ => false, } } pub(crate) fn is_extern_crate(item: &ast::Item) -> bool { - match item.node { + match item.kind { ast::ItemKind::ExternCrate(..) => true, _ => false, } diff --git a/src/macros.rs b/src/macros.rs index e92f02a1db1..8f509dd12c8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1196,7 +1196,7 @@ pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> O Some(ast::Expr { id: ast::NodeId::root(), // dummy value - node: ast::ExprKind::Try(parser.parse_expr().ok()?), + kind: ast::ExprKind::Try(parser.parse_expr().ok()?), span: mac.span, // incorrect span, but shouldn't matter too much attrs: ThinVec::new(), }) diff --git a/src/matches.rs b/src/matches.rs index e8ea5d6ad42..fcfb8055f01 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -141,7 +141,7 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { "" } else if config.match_block_trailing_comma() { "," - } else if let ast::ExprKind::Block(ref block, _) = body.node { + } else if let ast::ExprKind::Block(ref block, _) = body.kind { if let ast::BlockCheckMode::Default = block.rules { "" } else { @@ -272,7 +272,7 @@ fn block_can_be_flattened<'a>( context: &RewriteContext<'_>, expr: &'a ast::Expr, ) -> Option<&'a ast::Block> { - match expr.node { + match expr.kind { ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() @@ -296,8 +296,8 @@ fn flatten_arm_body<'a>( |expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr); if let Some(ref block) = block_can_be_flattened(context, body) { - if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node { - if let ast::ExprKind::Block(..) = expr.node { + if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind { + if let ast::ExprKind::Block(..) = expr.kind { flatten_arm_body(context, expr, None) } else { let cond_becomes_muti_line = opt_shape @@ -331,7 +331,7 @@ fn rewrite_match_body( body, shape.offset_left(extra_offset(pats_str, shape) + 4), ); - let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.node { + let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.kind { ( true, is_empty_block(block, Some(&body.attrs), context.source_map), @@ -548,7 +548,7 @@ fn nop_block_collapse(block_str: Option, budget: usize) -> Option bool { - match body.node { + match body.kind { // We do not allow `if` to stay on the same line, since we could easily mistake // `pat => if cond { ... }` and `pat if cond => { ... }`. ast::ExprKind::If(..) => false, diff --git a/src/modules.rs b/src/modules.rs index 0c1ea008f68..568faa7194b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -104,7 +104,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { visitor::CfgIfVisitor::new(self.parse_sess, self.directory.to_syntax_directory()); visitor.visit_item(&item); for module_item in visitor.mods() { - if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.node { + if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { self.visit_sub_mod(&module_item.item, Cow::Owned(sub_mod.clone()))?; } } @@ -119,7 +119,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { continue; } - if let ast::ItemKind::Mod(ref sub_mod) = item.node { + if let ast::ItemKind::Mod(ref sub_mod) = item.kind { self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; } } @@ -133,7 +133,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.visit_cfg_if(Cow::Borrowed(item))?; } - if let ast::ItemKind::Mod(ref sub_mod) = item.node { + if let ast::ItemKind::Mod(ref sub_mod) = item.kind { self.visit_sub_mod(item, Cow::Borrowed(sub_mod))?; } } @@ -476,7 +476,7 @@ fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResu } fn is_cfg_if(item: &ast::Item) -> bool { - match item.node { + match item.kind { ast::ItemKind::Mac(ref mac) => { if let Some(first_segment) = mac.path.segments.first() { if first_segment.ident.name == Symbol::intern("cfg_if") { diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 34b7e346334..e9223ce9644 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -98,7 +98,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { ); } }; - if let ast::ItemKind::Mod(..) = item.node { + if let ast::ItemKind::Mod(..) = item.kind { self.mods.push(ModItem { item }); } } @@ -137,7 +137,7 @@ impl PathVisitor { impl<'ast> MetaVisitor<'ast> for PathVisitor { fn visit_meta_name_value(&mut self, meta_item: &'ast ast::MetaItem, lit: &'ast ast::Lit) { - if meta_item.check_name(Symbol::intern("path")) && lit.node.is_str() { + if meta_item.check_name(Symbol::intern("path")) && lit.kind.is_str() { self.paths.push(lit_to_str(lit)); } } @@ -145,7 +145,7 @@ impl<'ast> MetaVisitor<'ast> for PathVisitor { #[cfg(not(windows))] fn lit_to_str(lit: &ast::Lit) -> String { - match lit.node { + match lit.kind { ast::LitKind::Str(symbol, ..) => symbol.to_string(), _ => unreachable!(), } @@ -153,7 +153,7 @@ fn lit_to_str(lit: &ast::Lit) -> String { #[cfg(windows)] fn lit_to_str(lit: &ast::Lit) -> String { - match lit.node { + match lit.kind { ast::LitKind::Str(symbol, ..) => symbol.as_str().replace("/", "\\"), _ => unreachable!(), } diff --git a/src/overflow.rs b/src/overflow.rs index 7c3f9d1a5eb..3b85c0b8e57 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -126,7 +126,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item { ast::NestedMetaItem::Literal(..) => true, - ast::NestedMetaItem::MetaItem(ref meta_item) => match meta_item.node { + ast::NestedMetaItem::MetaItem(ref meta_item) => match meta_item.kind { ast::MetaItemKind::Word => true, _ => false, }, @@ -399,7 +399,7 @@ impl<'a> Context<'a> { let last_item = self.last_item()?; let rewrite = match last_item { OverflowableItem::Expr(ref expr) => { - match expr.node { + match expr.kind { // When overflowing the closure which consists of a single control flow // expression, force to use block if its condition uses multi line. ast::ExprKind::Closure(..) => { diff --git a/src/pairs.rs b/src/pairs.rs index 49a77c102f6..45132c1f9f6 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -254,7 +254,7 @@ impl FlattenPair for ast::Expr { context: &RewriteContext<'_>, shape: Shape, ) -> Option> { - let top_op = match self.node { + let top_op = match self.kind { ast::ExprKind::Binary(op, _, _) => op.node, _ => return None, }; @@ -285,7 +285,7 @@ impl FlattenPair for ast::Expr { let mut separators = vec![]; let mut node = self; loop { - match node.node { + match node.kind { ast::ExprKind::Binary(op, ref lhs, _) if op.node == top_op => { stack.push(node); node = lhs; @@ -295,7 +295,7 @@ impl FlattenPair for ast::Expr { let rw = default_rewrite(node, op_len, list.is_empty()); list.push((node, rw)); if let Some(pop) = stack.pop() { - match pop.node { + match pop.kind { ast::ExprKind::Binary(op, _, ref rhs) => { separators.push(op.node.to_string()); node = rhs; diff --git a/src/patterns.rs b/src/patterns.rs index 9a89c8d192c..e81631d1662 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -36,7 +36,7 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool { } fn is_short_pattern_inner(pat: &ast::Pat) -> bool { - match pat.node { + match pat.kind { ast::PatKind::Rest | ast::PatKind::Wild | ast::PatKind::Lit(_) => true, ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) @@ -57,7 +57,7 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - match self.node { + match self.kind { PatKind::Or(ref pats) => { let pat_strs = pats .iter() @@ -335,7 +335,7 @@ impl<'a> Spanned for TuplePatField<'a> { impl<'a> TuplePatField<'a> { fn is_dotdot(&self) -> bool { match self { - TuplePatField::Pat(pat) => match pat.node { + TuplePatField::Pat(pat) => match pat.kind { ast::PatKind::Rest => true, _ => false, }, @@ -350,7 +350,7 @@ pub(crate) fn can_be_overflowed_pat( len: usize, ) -> bool { match *pat { - TuplePatField::Pat(pat) => match pat.node { + TuplePatField::Pat(pat) => match pat.kind { ast::PatKind::Path(..) | ast::PatKind::Tuple(..) | ast::PatKind::Struct(..) diff --git a/src/reorder.rs b/src/reorder.rs index 43a788c6339..5a6a45118b9 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -23,7 +23,7 @@ use crate::visitor::FmtVisitor; /// Choose the ordering between the given two items. fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { - match (&a.node, &b.node) { + match (&a.kind, &b.kind) { (&ast::ItemKind::Mod(..), &ast::ItemKind::Mod(..)) => { a.ident.as_str().cmp(&b.ident.as_str()) } @@ -68,7 +68,7 @@ fn rewrite_reorderable_item( item: &ast::Item, shape: Shape, ) -> Option { - match item.node { + match item.kind { ast::ItemKind::ExternCrate(..) => rewrite_extern_crate(context, item, shape), ast::ItemKind::Mod(..) => rewrite_mod(context, item, shape), _ => None, @@ -83,7 +83,7 @@ fn rewrite_reorderable_items( shape: Shape, span: Span, ) -> Option { - match reorderable_items[0].node { + match reorderable_items[0].kind { // FIXME: Remove duplicated code. ast::ItemKind::Use(..) => { let mut normalized_items: Vec<_> = reorderable_items @@ -164,7 +164,7 @@ enum ReorderableItemKind { impl ReorderableItemKind { fn from(item: &ast::Item) -> Self { - match item.node { + match item.kind { _ if contains_macro_use_attr(item) | contains_skip(&item.attrs) => { ReorderableItemKind::Other } diff --git a/src/spanned.rs b/src/spanned.rs index de02b79550f..8872e6df2da 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -63,7 +63,7 @@ implement_spanned!(ast::ImplItem); impl Spanned for ast::Stmt { fn span(&self) -> Span { - match self.node { + match self.kind { ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { diff --git a/src/stmt.rs b/src/stmt.rs index dbda00f00ce..a7aa6de0b13 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -27,7 +27,7 @@ impl<'a> Stmt<'a> { } pub(crate) fn to_item(&self) -> Option<&ast::Item> { - match self.inner.node { + match self.inner.kind { ast::StmtKind::Item(ref item) => Some(&**item), _ => None, } @@ -57,8 +57,8 @@ impl<'a> Stmt<'a> { return false; } - match self.as_ast_node().node { - ast::StmtKind::Expr(ref expr) => match expr.node { + match self.as_ast_node().kind { + ast::StmtKind::Expr(ref expr) => match expr.kind { ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { false } @@ -94,7 +94,7 @@ fn format_stmt( ) -> Option { skip_out_of_file_lines_range!(context, stmt.span()); - let result = match stmt.node { + let result = match stmt.kind { ast::StmtKind::Local(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt) { diff --git a/src/types.rs b/src/types.rs index 012cdba3192..3efe80fdb81 100644 --- a/src/types.rs +++ b/src/types.rs @@ -613,7 +613,7 @@ impl Rewrite for ast::TraitRef { impl Rewrite for ast::Ty { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - match self.node { + match self.kind { ast::TyKind::TraitObject(ref bounds, tobj_syntax) => { // we have to consider 'dyn' keyword is used or not!!! let is_dyn = tobj_syntax == ast::TraitObjectSyntax::Dyn; @@ -800,7 +800,7 @@ fn rewrite_bare_fn( let rewrite = format_function_type( bare_fn.decl.inputs.iter(), &bare_fn.decl.output, - bare_fn.decl.c_variadic, + bare_fn.decl.c_variadic(), span, context, func_ty_shape, @@ -891,7 +891,7 @@ pub(crate) fn can_be_overflowed_type( ty: &ast::Ty, len: usize, ) -> bool { - match ty.node { + match ty.kind { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { can_be_overflowed_type(context, &*mutty.ty, len) diff --git a/src/utils.rs b/src/utils.rs index 76af95a8c7f..12e3d943417 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -248,7 +248,7 @@ pub(crate) fn last_line_extendable(s: &str) -> bool { #[inline] fn is_skip(meta_item: &MetaItem) -> bool { - match meta_item.node { + match meta_item.kind { MetaItemKind::Word => { let path_str = meta_item.path.to_string(); path_str == skip_annotation().as_str() || path_str == depr_skip_annotation().as_str() @@ -277,7 +277,7 @@ pub(crate) fn contains_skip(attrs: &[Attribute]) -> bool { #[inline] pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { context.config.trailing_semicolon() } @@ -287,8 +287,8 @@ pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) #[inline] pub(crate) fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) -> bool { - match stmt.node { - ast::StmtKind::Semi(ref expr) => match expr.node { + match stmt.kind { + ast::StmtKind::Semi(ref expr) => match expr.kind { ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) => { false } @@ -304,7 +304,7 @@ pub(crate) fn semicolon_for_stmt(context: &RewriteContext<'_>, stmt: &ast::Stmt) #[inline] pub(crate) fn stmt_expr(stmt: &ast::Stmt) -> Option<&ast::Expr> { - match stmt.node { + match stmt.kind { ast::StmtKind::Expr(ref expr) => Some(expr), _ => None, } @@ -422,7 +422,7 @@ pub(crate) fn colon_spaces(config: &Config) -> &'static str { #[inline] pub(crate) fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { - match e.node { + match e.kind { ast::ExprKind::Call(ref e, _) | ast::ExprKind::Binary(_, ref e, _) | ast::ExprKind::Cast(ref e, _) @@ -450,7 +450,7 @@ pub(crate) fn first_line_ends_with(s: &str, c: char) -> bool { // States whether an expression's last line exclusively consists of closing // parens, braces, and brackets in its idiomatic formatting. pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool { - match expr.node { + match expr.kind { ast::ExprKind::Mac(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) diff --git a/src/visitor.rs b/src/visitor.rs index 8a1b3cd71fe..15490798a6e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -112,7 +112,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { return; } - match stmt.as_ast_node().node { + match stmt.as_ast_node().kind { ast::StmtKind::Item(ref item) => { self.visit_item(item); // Handle potential `;` after the item. @@ -397,7 +397,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let skip_context_saved = self.skip_context.clone(); self.skip_context.update_with_attrs(&attrs); - let should_visit_node_again = match item.node { + let should_visit_node_again = match item.kind { // For use/extern crate items, skip rewriting attributes but check for a skip attribute. ast::ItemKind::Use(..) | ast::ItemKind::ExternCrate(_) => { if contains_skip(attrs) { @@ -439,7 +439,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { }; if should_visit_node_again { - match item.node { + match item.kind { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), ast::ItemKind::Impl(..) => { let block_indent = self.block_indent; @@ -557,7 +557,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { return; } - match ti.node { + match ti.kind { ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), ast::TraitItemKind::Method(ref sig, None) => { let indent = self.block_indent; @@ -601,7 +601,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { return; } - match ii.node { + match ii.kind { ast::ImplItemKind::Method(ref sig, ref body) => { let inner_attrs = inner_attributes(&ii.attrs); self.visit_fn( -- cgit 1.4.1-3-g733a5 From ed697c93479502ced4bd10d083237f0a05d263b1 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 5 Oct 2019 12:34:48 -0500 Subject: fix: support raw prefix identifiers in statics --- src/items.rs | 2 +- tests/target/raw_identifiers.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index e10265df0ef..fadf53a57fd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1722,7 +1722,7 @@ fn rewrite_static( static_parts.defaultness.map_or("", format_defaultness), static_parts.prefix, format_mutability(static_parts.mutability), - static_parts.ident, + rewrite_ident(context, static_parts.ident), colon, ); // 2 = " =".len() diff --git a/tests/target/raw_identifiers.rs b/tests/target/raw_identifiers.rs index 275d9515a92..6ab0fdf053b 100644 --- a/tests/target/raw_identifiers.rs +++ b/tests/target/raw_identifiers.rs @@ -6,6 +6,9 @@ use r#foo as r#alias_foo; +// https://github.com/rust-lang/rustfmt/issues/3837 +pub(crate) static r#break: &'static str = "foo"; + fn main() { #[r#attr] r#foo::r#bar(); -- cgit 1.4.1-3-g733a5 From ba4bf03d84d7d1bfe433555e56c628c5598fea74 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 6 Oct 2019 20:24:08 -0500 Subject: don't fail on recoverable parser errors in ignored files (#3782) --- src/formatting.rs | 83 +++++++++++++++++++++++++++++++++++++++--- src/test/mod.rs | 2 + tests/config/issue-3779.toml | 4 ++ tests/source/issue-3779/ice.rs | 3 ++ tests/source/issue-3779/lib.rs | 8 ++++ tests/target/issue-3779/ice.rs | 3 ++ tests/target/issue-3779/lib.rs | 8 ++++ 7 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 tests/config/issue-3779.toml create mode 100644 tests/source/issue-3779/ice.rs create mode 100644 tests/source/issue-3779/lib.rs create mode 100644 tests/target/issue-3779/ice.rs create mode 100644 tests/target/issue-3779/lib.rs (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 3635f078e96..eec33e6ba79 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -1,5 +1,6 @@ // High level formatting functions. +use std::cell::RefCell; use std::collections::HashMap; use std::io::{self, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -7,7 +8,7 @@ use std::rc::Rc; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::errors::emitter::{ColorConfig, Emitter}; +use syntax::errors::emitter::{ColorConfig, Emitter, EmitterWriter}; use syntax::errors::{Diagnostic, DiagnosticBuilder, Handler}; use syntax::parse::{self, ParseSess}; use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; @@ -67,7 +68,7 @@ fn format_project( let input_is_stdin = main_file == FileName::Stdin; let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(set) => set, + Ok(set) => Rc::new(set), Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), }; if config.skip_children() && ignore_path_set.is_match(&main_file) { @@ -75,8 +76,14 @@ fn format_project( } // Parse the crate. + let can_reset_parser_errors = Rc::new(RefCell::new(false)); let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let mut parse_session = make_parse_sess(source_map.clone(), config); + let mut parse_session = make_parse_sess( + source_map.clone(), + config, + Rc::clone(&ignore_path_set), + can_reset_parser_errors.clone(), + ); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); let krate = match parse_crate( @@ -85,6 +92,7 @@ fn format_project( config, &mut report, directory_ownership, + can_reset_parser_errors.clone(), ) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) @@ -620,6 +628,7 @@ fn parse_crate( config: &Config, report: &mut FormatReport, directory_ownership: Option, + can_reset_parser_errors: Rc>, ) -> Result { let input_is_stdin = input.is_text(); @@ -667,6 +676,15 @@ fn parse_crate( if !parse_session.span_diagnostic.has_errors() { return Ok(c); } + // This scenario occurs when the parser encountered errors + // but was still able to recover. If all of the parser errors + // occurred in files that are ignored, then reset + // the error count and continue. + // https://github.com/rust-lang/rustfmt/issues/3779 + if *can_reset_parser_errors.borrow() { + parse_session.span_diagnostic.reset_err_count(); + return Ok(c); + } } Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(DiagnosticBuilder::emit), Err(_) => { @@ -683,6 +701,40 @@ fn parse_crate( Err(ErrorKind::ParseError) } +struct SilentOnIgnoredFilesEmitter { + ignore_path_set: Rc, + source_map: Rc, + emitter: EmitterWriter, + has_non_ignorable_parser_errors: bool, + can_reset: Rc>, +} + +impl Emitter for SilentOnIgnoredFilesEmitter { + fn emit_diagnostic(&mut self, db: &Diagnostic) { + if let Some(primary_span) = &db.span.primary_span() { + let file_name = self.source_map.span_to_filename(*primary_span); + match file_name { + syntax_pos::FileName::Real(ref path) => { + if self + .ignore_path_set + .is_match(&FileName::Real(path.to_path_buf())) + { + if !self.has_non_ignorable_parser_errors { + *self.can_reset.borrow_mut() = true; + } + return; + } + } + _ => (), + }; + } + + self.has_non_ignorable_parser_errors = true; + *self.can_reset.borrow_mut() = false; + self.emitter.emit_diagnostic(db); + } +} + /// Emitter which discards every error. struct SilentEmitter; @@ -694,7 +746,12 @@ fn silent_emitter() -> Box { Box::new(SilentEmitter {}) } -fn make_parse_sess(source_map: Rc, config: &Config) -> ParseSess { +fn make_parse_sess( + source_map: Rc, + config: &Config, + ignore_path_set: Rc, + can_reset: Rc>, +) -> ParseSess { let tty_handler = if config.hide_parse_errors() { let silent_emitter = silent_emitter(); Handler::with_emitter(true, None, silent_emitter) @@ -705,7 +762,23 @@ fn make_parse_sess(source_map: Rc, config: &Config) -> ParseSess { } else { ColorConfig::Never }; - Handler::with_tty_emitter(color_cfg, true, None, Some(source_map.clone())) + + let emitter_writer = EmitterWriter::stderr( + color_cfg, + Some(source_map.clone()), + false, + false, + None, + false, + ); + let emitter = Box::new(SilentOnIgnoredFilesEmitter { + has_non_ignorable_parser_errors: false, + ignore_path_set: ignore_path_set, + source_map: Rc::clone(&source_map), + emitter: emitter_writer, + can_reset, + }); + Handler::with_emitter(true, None, emitter) }; ParseSess::with_span_handler(tty_handler, source_map) diff --git a/src/test/mod.rs b/src/test/mod.rs index 8931f62fa23..6b7a9365c6f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -27,6 +27,8 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ "configs/skip_children/foo/mod.rs", "issue-3434/no_entry.rs", "issue-3665/sub_mod.rs", + // Testing for issue-3779 + "issue-3779/ice.rs", // These files and directory are a part of modules defined inside `cfg_if!`. "cfg_if/mod.rs", "cfg_if/detect", diff --git a/tests/config/issue-3779.toml b/tests/config/issue-3779.toml new file mode 100644 index 00000000000..83505f409af --- /dev/null +++ b/tests/config/issue-3779.toml @@ -0,0 +1,4 @@ +unstable_features = true +ignore = [ + "tests/**/issue-3779/ice.rs" +] diff --git a/tests/source/issue-3779/ice.rs b/tests/source/issue-3779/ice.rs new file mode 100644 index 00000000000..cde21412d94 --- /dev/null +++ b/tests/source/issue-3779/ice.rs @@ -0,0 +1,3 @@ +pub fn bar() { + 1x; +} diff --git a/tests/source/issue-3779/lib.rs b/tests/source/issue-3779/lib.rs new file mode 100644 index 00000000000..d7c2ae28975 --- /dev/null +++ b/tests/source/issue-3779/lib.rs @@ -0,0 +1,8 @@ +// rustfmt-config: issue-3779.toml + +#[path = "ice.rs"] +mod ice; + +fn foo() { +println!("abc") ; + } diff --git a/tests/target/issue-3779/ice.rs b/tests/target/issue-3779/ice.rs new file mode 100644 index 00000000000..cde21412d94 --- /dev/null +++ b/tests/target/issue-3779/ice.rs @@ -0,0 +1,3 @@ +pub fn bar() { + 1x; +} diff --git a/tests/target/issue-3779/lib.rs b/tests/target/issue-3779/lib.rs new file mode 100644 index 00000000000..ebebce417d1 --- /dev/null +++ b/tests/target/issue-3779/lib.rs @@ -0,0 +1,8 @@ +// rustfmt-config: issue-3779.toml + +#[path = "ice.rs"] +mod ice; + +fn foo() { + println!("abc"); +} -- cgit 1.4.1-3-g733a5 From 160c3aafc53912352988887ed764ed4c862a14b2 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 7 Oct 2019 09:40:27 +0200 Subject: handle hard tabs when formatting trailing comments (#3836) --- src/missed_spans.rs | 4 ++-- src/utils.rs | 7 ------- tests/source/trailing_comments.rs | 21 -------------------- tests/source/trailing_comments/hard_tabs.rs | 21 ++++++++++++++++++++ tests/source/trailing_comments/soft_tabs.rs | 21 ++++++++++++++++++++ tests/target/trailing_comments.rs | 30 ----------------------------- tests/target/trailing_comments/hard_tabs.rs | 30 +++++++++++++++++++++++++++++ tests/target/trailing_comments/soft_tabs.rs | 30 +++++++++++++++++++++++++++++ 8 files changed, 104 insertions(+), 60 deletions(-) delete mode 100644 tests/source/trailing_comments.rs create mode 100644 tests/source/trailing_comments/hard_tabs.rs create mode 100644 tests/source/trailing_comments/soft_tabs.rs delete mode 100644 tests/target/trailing_comments.rs create mode 100644 tests/target/trailing_comments/hard_tabs.rs create mode 100644 tests/target/trailing_comments/soft_tabs.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index a6800b15e61..a957d3b3e30 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -7,7 +7,7 @@ use crate::config::Version; use crate::coverage::transform_missing_snippet; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; -use crate::utils::{count_lf_crlf, count_newlines, last_line_indent, last_line_width, mk_sp}; +use crate::utils::{count_lf_crlf, count_newlines, last_line_width, mk_sp}; use crate::visitor::FmtVisitor; struct SnippetStatus { @@ -254,7 +254,7 @@ impl<'a> FmtVisitor<'a> { // the same level and avoid mixing it with possible other comment. on_same_line = true; self.push_str(" "); - Indent::from_width(self.config, last_line_indent(&self.buffer)) + self.block_indent } else { self.push_str(" "); Indent::from_width(self.config, last_line_width(&self.buffer)) diff --git a/src/utils.rs b/src/utils.rs index 12e3d943417..47f9cd94b8d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -205,13 +205,6 @@ pub(crate) fn last_line_width(s: &str) -> usize { unicode_str_width(s.rsplitn(2, '\n').next().unwrap_or("")) } -/// The indent width of the last line in s. -#[inline] -pub(crate) fn last_line_indent(s: &str) -> usize { - let last_line = s.rsplitn(2, '\n').next().unwrap_or(""); - last_line.chars().take_while(|c| c.is_whitespace()).count() -} - /// The total used width of the last line. #[inline] pub(crate) fn last_line_used_width(s: &str, offset: usize) -> usize { diff --git a/tests/source/trailing_comments.rs b/tests/source/trailing_comments.rs deleted file mode 100644 index 7845f713b8a..00000000000 --- a/tests/source/trailing_comments.rs +++ /dev/null @@ -1,21 +0,0 @@ -// rustfmt-version: Two -// rustfmt-wrap_comments: true - -pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast -// Multicast using broadcst. add. - -pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE -pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE -pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX -//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX -//const SQ_GRANT: u16 = 0x0012; // GRANT -//const SQ_REVOKE: u16 = 0x0013; // REVOKE - -fn foo() { - let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. - // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. In hac habitasse platea dictumst. Vivamus a orci at nulla tristique condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc. - let b = baz(); - - let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] - // TODO(emilio): It may make sense to make this range [.01, 10.0], to align with css-fonts-4's range of [1, 1000]. -} diff --git a/tests/source/trailing_comments/hard_tabs.rs b/tests/source/trailing_comments/hard_tabs.rs new file mode 100644 index 00000000000..88249aa5fb9 --- /dev/null +++ b/tests/source/trailing_comments/hard_tabs.rs @@ -0,0 +1,21 @@ +// rustfmt-version: Two +// rustfmt-wrap_comments: true +// rustfmt-hard_tabs: true + +impl Foo { + fn foo() { + bar(); // comment 1 + // comment 2 + // comment 3 + baz(); + } +} + +fn lorem_ipsum() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. In hac habitasse platea dictumst. Vivamus a orci at nulla tristique condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc. + let b = baz(); + + let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] + // TODO(emilio): It may make sense to make this range [.01, 10.0], to align with css-fonts-4's range of [1, 1000]. +} diff --git a/tests/source/trailing_comments/soft_tabs.rs b/tests/source/trailing_comments/soft_tabs.rs new file mode 100644 index 00000000000..7845f713b8a --- /dev/null +++ b/tests/source/trailing_comments/soft_tabs.rs @@ -0,0 +1,21 @@ +// rustfmt-version: Two +// rustfmt-wrap_comments: true + +pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast +// Multicast using broadcst. add. + +pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE +pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE +pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX +//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX +//const SQ_GRANT: u16 = 0x0012; // GRANT +//const SQ_REVOKE: u16 = 0x0013; // REVOKE + +fn foo() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. In hac habitasse platea dictumst. Vivamus a orci at nulla tristique condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc. + let b = baz(); + + let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] + // TODO(emilio): It may make sense to make this range [.01, 10.0], to align with css-fonts-4's range of [1, 1000]. +} diff --git a/tests/target/trailing_comments.rs b/tests/target/trailing_comments.rs deleted file mode 100644 index eba943042ad..00000000000 --- a/tests/target/trailing_comments.rs +++ /dev/null @@ -1,30 +0,0 @@ -// rustfmt-version: Two -// rustfmt-wrap_comments: true - -pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast -// Multicast using broadcst. add. - -pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE -pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE -pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX -//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX -//const SQ_GRANT: u16 = 0x0012; // GRANT -//const SQ_REVOKE: u16 = 0x0013; // REVOKE - -fn foo() { - let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. - // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis - // malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at - // nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci - // bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc - // suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a - // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. - // In hac habitasse platea dictumst. Vivamus a orci at nulla tristique - // condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit - // amet, ipsum. In pharetra sagittis nunc. - let b = baz(); - - let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] - // TODO(emilio): It may make sense to make this range [.01, 10.0], to align - // with css-fonts-4's range of [1, 1000]. -} diff --git a/tests/target/trailing_comments/hard_tabs.rs b/tests/target/trailing_comments/hard_tabs.rs new file mode 100644 index 00000000000..35e72f1affd --- /dev/null +++ b/tests/target/trailing_comments/hard_tabs.rs @@ -0,0 +1,30 @@ +// rustfmt-version: Two +// rustfmt-wrap_comments: true +// rustfmt-hard_tabs: true + +impl Foo { + fn foo() { + bar(); // comment 1 + // comment 2 + // comment 3 + baz(); + } +} + +fn lorem_ipsum() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis + // malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at + // nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci + // bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc + // suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a + // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. + // In hac habitasse platea dictumst. Vivamus a orci at nulla tristique + // condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit + // amet, ipsum. In pharetra sagittis nunc. + let b = baz(); + + let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] + // TODO(emilio): It may make sense to make this range [.01, 10.0], to align + // with css-fonts-4's range of [1, 1000]. +} diff --git a/tests/target/trailing_comments/soft_tabs.rs b/tests/target/trailing_comments/soft_tabs.rs new file mode 100644 index 00000000000..eba943042ad --- /dev/null +++ b/tests/target/trailing_comments/soft_tabs.rs @@ -0,0 +1,30 @@ +// rustfmt-version: Two +// rustfmt-wrap_comments: true + +pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast +// Multicast using broadcst. add. + +pub const SQ_CRETAB: u16 = 0x000e; // CREATE TABLE +pub const SQ_DRPTAB: u16 = 0x000f; // DROP TABLE +pub const SQ_CREIDX: u16 = 0x0010; // CREATE INDEX +//const SQ_DRPIDX: u16 = 0x0011; // DROP INDEX +//const SQ_GRANT: u16 = 0x0012; // GRANT +//const SQ_REVOKE: u16 = 0x0013; // REVOKE + +fn foo() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + // Id turpis. Nam posuere lectus vitae nibh. Etiam tortor orci, sagittis + // malesuada, rhoncus quis, hendrerit eget, libero. Quisque commodo nulla at + // nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci + // bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc + // suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a + // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. + // In hac habitasse platea dictumst. Vivamus a orci at nulla tristique + // condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit + // amet, ipsum. In pharetra sagittis nunc. + let b = baz(); + + let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] + // TODO(emilio): It may make sense to make this range [.01, 10.0], to align + // with css-fonts-4's range of [1, 1000]. +} -- cgit 1.4.1-3-g733a5 From 80732444203b86f7c2967d43bf4a067a1b6269cb Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 7 Oct 2019 09:43:50 +0200 Subject: improve detection of URL inside a string that is being rewritten. (#3809) --- src/string.rs | 15 ++++++++------- tests/source/issue-3787.rs | 9 +++++++++ tests/target/issue-3787.rs | 13 +++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 tests/source/issue-3787.rs create mode 100644 tests/target/issue-3787.rs (limited to 'src') diff --git a/src/string.rs b/src/string.rs index 4898c9e425c..080c4f17788 100644 --- a/src/string.rs +++ b/src/string.rs @@ -153,21 +153,22 @@ pub(crate) fn rewrite_string<'a>( wrap_str(result, fmt.config.max_width(), fmt.shape) } -/// Returns the index to the end of the URL if the given string includes an -/// URL or alike. Otherwise, returns `None`; +/// Returns the index to the end of the URL if the split at index of the given string includes an +/// URL or alike. Otherwise, returns `None`. fn detect_url(s: &[&str], index: usize) -> Option { let start = match s[..=index].iter().rposition(|g| is_whitespace(g)) { Some(pos) => pos + 1, None => 0, }; + // 8 = minimum length for a string to contain a URL if s.len() < start + 8 { return None; } - let prefix = s[start..start + 8].concat(); - if prefix.starts_with("https://") - || prefix.starts_with("http://") - || prefix.starts_with("ftp://") - || prefix.starts_with("file://") + let split = s[start..].concat(); + if split.contains("https://") + || split.contains("http://") + || split.contains("ftp://") + || split.contains("file://") { match s[index..].iter().position(|g| is_whitespace(g)) { Some(pos) => Some(index + pos - 1), diff --git a/tests/source/issue-3787.rs b/tests/source/issue-3787.rs new file mode 100644 index 00000000000..bcdc131a05e --- /dev/null +++ b/tests/source/issue-3787.rs @@ -0,0 +1,9 @@ +// rustfmt-wrap_comments: true + +//! URLs in items +//! * [This is a link with a very loooooooooooooooooooooooooooooooooooooooooong URL.](https://example.com/This/is/a/link/with/a/very/loooooooooooooooooooooooooooooooooooooooooong/URL) +//! * This is a [link](https://example.com/This/is/a/link/with/a/very/loooooooooooooooooooooooooooooooooooooooooong/URL) with a very loooooooooooooooooooooooooooooooooooooooooong URL. +//! * there is no link here: In hac habitasse platea dictumst. Maecenas in ligula. Duis tincidunt odio sollicitudin quam. Nullam non mauris. Phasellus lacinia, velit sit amet bibendum euismod, leo diam interdum ligula, eu scelerisque sem purus in tellus. +fn main() { + println!("Hello, world!"); +} diff --git a/tests/target/issue-3787.rs b/tests/target/issue-3787.rs new file mode 100644 index 00000000000..32cf7e3d755 --- /dev/null +++ b/tests/target/issue-3787.rs @@ -0,0 +1,13 @@ +// rustfmt-wrap_comments: true + +//! URLs in items +//! * [This is a link with a very loooooooooooooooooooooooooooooooooooooooooong URL.](https://example.com/This/is/a/link/with/a/very/loooooooooooooooooooooooooooooooooooooooooong/URL) +//! * This is a [link](https://example.com/This/is/a/link/with/a/very/loooooooooooooooooooooooooooooooooooooooooong/URL) +//! with a very loooooooooooooooooooooooooooooooooooooooooong URL. +//! * there is no link here: In hac habitasse platea dictumst. Maecenas in +//! ligula. Duis tincidunt odio sollicitudin quam. Nullam non mauris. +//! Phasellus lacinia, velit sit amet bibendum euismod, leo diam interdum +//! ligula, eu scelerisque sem purus in tellus. +fn main() { + println!("Hello, world!"); +} -- cgit 1.4.1-3-g733a5 From 6dcbc5d78e89036b65cd57f50456c03dd3c19460 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 7 Oct 2019 20:12:21 -0500 Subject: fix: handle block comments with trailing line comments (#3842) --- src/lists.rs | 16 ++++++++++++---- tests/source/issue_3839.rs | 8 ++++++++ tests/target/issue_3839.rs | 8 ++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/source/issue_3839.rs create mode 100644 tests/target/issue_3839.rs (limited to 'src') diff --git a/src/lists.rs b/src/lists.rs index ac83d7082c8..077d08cb4e4 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -574,9 +574,17 @@ where pub(crate) fn extract_pre_comment(pre_snippet: &str) -> (Option, ListItemCommentStyle) { let trimmed_pre_snippet = pre_snippet.trim(); - let has_block_comment = trimmed_pre_snippet.ends_with("*/"); - let has_single_line_comment = trimmed_pre_snippet.starts_with("//"); - if has_block_comment { + // Both start and end are checked to support keeping a block comment inline with + // the item, even if there are preceeding line comments, while still supporting + // a snippet that starts with a block comment but also contains one or more + // trailing single line comments. + // https://github.com/rust-lang/rustfmt/issues/3025 + // https://github.com/rust-lang/rustfmt/pull/3048 + // https://github.com/rust-lang/rustfmt/issues/3839 + let starts_with_block_comment = trimmed_pre_snippet.starts_with("/*"); + let ends_with_block_comment = trimmed_pre_snippet.ends_with("*/"); + let starts_with_single_line_comment = trimmed_pre_snippet.starts_with("//"); + if ends_with_block_comment { let comment_end = pre_snippet.rfind(|c| c == '/').unwrap(); if pre_snippet[comment_end..].contains('\n') { ( @@ -589,7 +597,7 @@ pub(crate) fn extract_pre_comment(pre_snippet: &str) -> (Option, ListIte ListItemCommentStyle::SameLine, ) } - } else if has_single_line_comment { + } else if starts_with_single_line_comment || starts_with_block_comment { ( Some(trimmed_pre_snippet.to_owned()), ListItemCommentStyle::DifferentLine, diff --git a/tests/source/issue_3839.rs b/tests/source/issue_3839.rs new file mode 100644 index 00000000000..3933d31ee1a --- /dev/null +++ b/tests/source/issue_3839.rs @@ -0,0 +1,8 @@ +struct Foo { + a: i32, +/* +asd +*/ + // foo +b: i32, +} diff --git a/tests/target/issue_3839.rs b/tests/target/issue_3839.rs new file mode 100644 index 00000000000..b7bdf4c7579 --- /dev/null +++ b/tests/target/issue_3839.rs @@ -0,0 +1,8 @@ +struct Foo { + a: i32, + /* + asd + */ + // foo + b: i32, +} -- cgit 1.4.1-3-g733a5 From 207a58f365a1d6dd868e29a85a9e01e05c564374 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 7 Oct 2019 21:00:31 -0500 Subject: fix panic on closure with empty block expr (#3846) --- src/closures.rs | 5 +++-- tests/source/issue_3844.rs | 3 +++ tests/target/issue_3844.rs | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue_3844.rs create mode 100644 tests/target/issue_3844.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 1b877f5ef97..81253f4f904 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -91,8 +91,9 @@ fn get_inner_expr<'a>( ) -> &'a ast::Expr { if let ast::ExprKind::Block(ref block, _) = expr.kind { if !needs_block(block, prefix, context) { - // block.stmts.len() == 1 - if let Some(expr) = stmt_expr(&block.stmts[0]) { + // block.stmts.len() == 1 except with `|| {{}}`; + // https://github.com/rust-lang/rustfmt/issues/3844 + if let Some(expr) = block.stmts.first().and_then(stmt_expr) { return get_inner_expr(expr, prefix, context); } } diff --git a/tests/source/issue_3844.rs b/tests/source/issue_3844.rs new file mode 100644 index 00000000000..15441b2b05c --- /dev/null +++ b/tests/source/issue_3844.rs @@ -0,0 +1,3 @@ +fn main() { +|| {{}}; +} diff --git a/tests/target/issue_3844.rs b/tests/target/issue_3844.rs new file mode 100644 index 00000000000..81d2083463e --- /dev/null +++ b/tests/target/issue_3844.rs @@ -0,0 +1,3 @@ +fn main() { + || {}; +} -- cgit 1.4.1-3-g733a5 From 396a2af181abb9adbd9ea1e8db4ed6649844b2bd Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Thu, 10 Oct 2019 10:35:34 +0900 Subject: fix to swallow attribute on brace expression (#3848) --- src/closures.rs | 6 ++++++ tests/target/issue-3845.rs | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/target/issue-3845.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 81253f4f904..eaa42b991f2 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,6 +1,7 @@ use syntax::source_map::Span; use syntax::{ast, ptr}; +use crate::attr::get_attrs_from_stmt; use crate::config::lists::*; use crate::config::Version; use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; @@ -104,8 +105,13 @@ fn get_inner_expr<'a>( // Figure out if a block is necessary. fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) -> bool { + let has_attributes = block.stmts.first().map_or(false, |first_stmt| { + !get_attrs_from_stmt(first_stmt).is_empty() + }); + is_unsafe_block(block) || block.stmts.len() > 1 + || has_attributes || block_contains_comment(block, context.source_map) || prefix.contains('\n') } diff --git a/tests/target/issue-3845.rs b/tests/target/issue-3845.rs new file mode 100644 index 00000000000..877c05b86a9 --- /dev/null +++ b/tests/target/issue-3845.rs @@ -0,0 +1,8 @@ +fn main() { + || { + #[allow(deprecated)] + { + u8::max_value() + } + }; +} -- cgit 1.4.1-3-g733a5 From 8210cc1c133cd4201143ba1694d00b3e3fcc1183 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 11 Oct 2019 04:15:04 -0500 Subject: fix: handle lhs unary in range expression (#3855) --- src/expr.rs | 1 + tests/target/issue_3854.rs | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 tests/target/issue_3854.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 86bb98d3ea8..1d9625298c5 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -257,6 +257,7 @@ pub(crate) fn format_expr( } _ => false, }, + ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr), _ => false, } } diff --git a/tests/target/issue_3854.rs b/tests/target/issue_3854.rs new file mode 100644 index 00000000000..3051335c27d --- /dev/null +++ b/tests/target/issue_3854.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{:?}", -1. ..1.); +} -- cgit 1.4.1-3-g733a5 From a15e97f1e92b3621ab8c2f1585f27e8de583f74b Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Fri, 11 Oct 2019 11:19:44 +0200 Subject: do not indent impl generics (#3856) --- src/items.rs | 20 +++++++++--------- tests/source/issue-3840/version-one_hard-tabs.rs | 15 ++++++++++++++ tests/source/issue-3840/version-one_soft-tabs.rs | 13 ++++++++++++ tests/source/issue-3840/version-two_hard-tabs.rs | 16 +++++++++++++++ tests/source/issue-3840/version-two_soft-tabs.rs | 15 ++++++++++++++ tests/target/issue-3840/version-one_hard-tabs.rs | 25 +++++++++++++++++++++++ tests/target/issue-3840/version-one_soft-tabs.rs | 23 +++++++++++++++++++++ tests/target/issue-3840/version-two_hard-tabs.rs | 26 ++++++++++++++++++++++++ tests/target/issue-3840/version-two_soft-tabs.rs | 25 +++++++++++++++++++++++ 9 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 tests/source/issue-3840/version-one_hard-tabs.rs create mode 100644 tests/source/issue-3840/version-one_soft-tabs.rs create mode 100644 tests/source/issue-3840/version-two_hard-tabs.rs create mode 100644 tests/source/issue-3840/version-two_soft-tabs.rs create mode 100644 tests/target/issue-3840/version-one_hard-tabs.rs create mode 100644 tests/target/issue-3840/version-one_soft-tabs.rs create mode 100644 tests/target/issue-3840/version-two_hard-tabs.rs create mode 100644 tests/target/issue-3840/version-two_soft-tabs.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index fadf53a57fd..7092659158a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -802,11 +802,15 @@ fn format_impl_ref_and_type( result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); - let shape = generics_shape_from_config( - context.config, - Shape::indented(offset + last_line_width(&result), context.config), - 0, - )?; + let shape = if context.config.version() == Version::Two { + Shape::indented(offset + last_line_width(&result), context.config) + } else { + generics_shape_from_config( + context.config, + Shape::indented(offset + last_line_width(&result), context.config), + 0, + )? + }; let generics_str = rewrite_generics(context, "impl", generics, shape)?; result.push_str(&generics_str); @@ -2609,11 +2613,7 @@ fn rewrite_generics( overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span) } -pub(crate) fn generics_shape_from_config( - config: &Config, - shape: Shape, - offset: usize, -) -> Option { +fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { match config.indent_style() { IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2), IndentStyle::Block => { diff --git a/tests/source/issue-3840/version-one_hard-tabs.rs b/tests/source/issue-3840/version-one_hard-tabs.rs new file mode 100644 index 00000000000..bf7ea7da0eb --- /dev/null +++ b/tests/source/issue-3840/version-one_hard-tabs.rs @@ -0,0 +1,15 @@ +// rustfmt-hard_tabs: true + +impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/source/issue-3840/version-one_soft-tabs.rs b/tests/source/issue-3840/version-one_soft-tabs.rs new file mode 100644 index 00000000000..3fc26224d50 --- /dev/null +++ b/tests/source/issue-3840/version-one_soft-tabs.rs @@ -0,0 +1,13 @@ +impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/source/issue-3840/version-two_hard-tabs.rs b/tests/source/issue-3840/version-two_hard-tabs.rs new file mode 100644 index 00000000000..7b505fda87c --- /dev/null +++ b/tests/source/issue-3840/version-two_hard-tabs.rs @@ -0,0 +1,16 @@ +// rustfmt-hard_tabs: true +// rustfmt-version: Two + +impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/source/issue-3840/version-two_soft-tabs.rs b/tests/source/issue-3840/version-two_soft-tabs.rs new file mode 100644 index 00000000000..39c8ef31292 --- /dev/null +++ b/tests/source/issue-3840/version-two_soft-tabs.rs @@ -0,0 +1,15 @@ +// rustfmt-version: Two + +impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl + FromEvent, A: Widget2, B: Widget2, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/target/issue-3840/version-one_hard-tabs.rs b/tests/target/issue-3840/version-one_hard-tabs.rs new file mode 100644 index 00000000000..4aa905ce9e5 --- /dev/null +++ b/tests/target/issue-3840/version-one_hard-tabs.rs @@ -0,0 +1,25 @@ +// rustfmt-hard_tabs: true + +impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, + > Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, + > Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/target/issue-3840/version-one_soft-tabs.rs b/tests/target/issue-3840/version-one_soft-tabs.rs new file mode 100644 index 00000000000..099e6801823 --- /dev/null +++ b/tests/target/issue-3840/version-one_soft-tabs.rs @@ -0,0 +1,23 @@ +impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, + > Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, + > Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/target/issue-3840/version-two_hard-tabs.rs b/tests/target/issue-3840/version-two_hard-tabs.rs new file mode 100644 index 00000000000..084db3d1465 --- /dev/null +++ b/tests/target/issue-3840/version-two_hard-tabs.rs @@ -0,0 +1,26 @@ +// rustfmt-hard_tabs: true +// rustfmt-version: Two + +impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, +> Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, + > Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} diff --git a/tests/target/issue-3840/version-two_soft-tabs.rs b/tests/target/issue-3840/version-two_soft-tabs.rs new file mode 100644 index 00000000000..bc59b0baa56 --- /dev/null +++ b/tests/target/issue-3840/version-two_soft-tabs.rs @@ -0,0 +1,25 @@ +// rustfmt-version: Two + +impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, +> Widget2 for WidgetEventLifter +{ + type Ctx = C; + type Event = Vec; +} + +mod foo { + impl< + Target: FromEvent + FromEvent, + A: Widget2, + B: Widget2, + C: for<'a> CtxFamily<'a>, + > Widget2 for WidgetEventLifter + { + type Ctx = C; + type Event = Vec; + } +} -- cgit 1.4.1-3-g733a5 From 28be77915f5b6750f0390e233a44499f2c3f2547 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 17 Oct 2019 19:58:08 -0500 Subject: fix: nested comments in control flow condition pat --- src/patterns.rs | 73 ++++++++++++++++++++++++++++++++++++++++------ tests/source/issue_3853.rs | 35 ++++++++++++++++++++++ tests/target/issue_3853.rs | 31 ++++++++++++++++++++ 3 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 tests/source/issue_3853.rs create mode 100644 tests/target/issue_3853.rs (limited to 'src') diff --git a/src/patterns.rs b/src/patterns.rs index e81631d1662..baa39dbbce6 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -89,26 +89,81 @@ impl Rewrite for Pat { PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(binding_mode, ident, ref sub_pat) => { let (prefix, mutability) = match binding_mode { - BindingMode::ByRef(mutability) => ("ref ", mutability), + BindingMode::ByRef(mutability) => ("ref", mutability), BindingMode::ByValue(mutability) => ("", mutability), }; - let mut_infix = format_mutability(mutability); + let mut_infix = format_mutability(mutability).trim(); let id_str = rewrite_ident(context, ident); let sub_pat = match *sub_pat { Some(ref p) => { - // 3 - ` @ `. + // 2 - `@ `. let width = shape .width - .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 3)?; - format!( - " @ {}", - p.rewrite(context, Shape::legacy(width, shape.indent))? - ) + .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 2)?; + let lo = context.snippet_provider.span_after(self.span, "@"); + combine_strs_with_missing_comments( + context, + "@", + &p.rewrite(context, Shape::legacy(width, shape.indent))?, + mk_sp(lo, p.span.lo()), + shape, + true, + )? } None => "".to_owned(), }; - Some(format!("{}{}{}{}", prefix, mut_infix, id_str, sub_pat)) + // combine prefix and mut + let (first_lo, first) = if !prefix.is_empty() && !mut_infix.is_empty() { + let hi = context.snippet_provider.span_before(self.span, "mut"); + let lo = context.snippet_provider.span_after(self.span, "ref"); + ( + context.snippet_provider.span_after(self.span, "mut"), + combine_strs_with_missing_comments( + context, + prefix, + mut_infix, + mk_sp(lo, hi), + shape, + true, + )?, + ) + } else if !prefix.is_empty() { + ( + context.snippet_provider.span_after(self.span, "ref"), + prefix.to_owned(), + ) + } else if !mut_infix.is_empty() { + ( + context.snippet_provider.span_after(self.span, "mut"), + mut_infix.to_owned(), + ) + } else { + (self.span.lo(), "".to_owned()) + }; + + let next = if !sub_pat.is_empty() { + let hi = context.snippet_provider.span_before(self.span, "@"); + combine_strs_with_missing_comments( + context, + id_str, + &sub_pat, + mk_sp(ident.span.hi(), hi), + shape, + true, + )? + } else { + id_str.to_owned() + }; + + combine_strs_with_missing_comments( + context, + &first, + &next, + mk_sp(first_lo, ident.span.lo()), + shape, + true, + ) } PatKind::Wild => { if 1 <= shape.width { diff --git a/tests/source/issue_3853.rs b/tests/source/issue_3853.rs new file mode 100644 index 00000000000..d2cd9a98a1f --- /dev/null +++ b/tests/source/issue_3853.rs @@ -0,0 +1,35 @@ +fn by_ref_with_block_before_ident() { +if let Some(ref /*def*/ state)= foo{ + println!( + "asdfasdfasdf"); } +} + +fn mut_block_before_ident() { +if let Some(mut /*def*/ state ) =foo{ + println!( + "123" ); } +} + +fn ref_and_mut_blocks_before_ident() { +if let Some(ref /*abc*/ + mut /*def*/ state ) = foo { + println!( + "deefefefefefwea" ); } +} + +fn sub_pattern() { + let foo @ /*foo*/ +bar(f) = 42; +} + +fn no_prefix_block_before_ident() { +if let Some( + /*def*/ state ) = foo { + println!( + "129387123123" ); } +} + +fn issue_3853() { +if let Some(ref /*mut*/ state) = foo { + } +} diff --git a/tests/target/issue_3853.rs b/tests/target/issue_3853.rs new file mode 100644 index 00000000000..53b94d3fc00 --- /dev/null +++ b/tests/target/issue_3853.rs @@ -0,0 +1,31 @@ +fn by_ref_with_block_before_ident() { + if let Some(ref /*def*/ state) = foo { + println!("asdfasdfasdf"); + } +} + +fn mut_block_before_ident() { + if let Some(mut /*def*/ state) = foo { + println!("123"); + } +} + +fn ref_and_mut_blocks_before_ident() { + if let Some(ref /*abc*/ mut /*def*/ state) = foo { + println!("deefefefefefwea"); + } +} + +fn sub_pattern() { + let foo @ /*foo*/ bar(f) = 42; +} + +fn no_prefix_block_before_ident() { + if let Some(/*def*/ state) = foo { + println!("129387123123"); + } +} + +fn issue_3853() { + if let Some(ref /*mut*/ state) = foo {} +} -- cgit 1.4.1-3-g733a5 From fd6e960648b8a8d46e31bf4989928cae82e9684f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 17 Oct 2019 20:04:05 -0500 Subject: fix: comments between lhs and rhs --- src/comment.rs | 2 +- src/expr.rs | 41 +++++++++++++++++++++++++++++++++++------ tests/source/issue_3853.rs | 17 +++++++++++++++++ tests/target/issue_3853.rs | 16 ++++++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index e725adea6ba..c721f07d019 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -112,7 +112,7 @@ impl<'a> CommentStyle<'a> { } } -fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> { +pub(crate) fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle<'_> { if !normalize_comments { if orig.starts_with("/**") && !orig.starts_with("/**/") { CommentStyle::DoubleBullet diff --git a/src/expr.rs b/src/expr.rs index 1d9625298c5..176f78db92a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,8 +9,8 @@ use syntax::{ast, ptr}; use crate::chains::rewrite_chain; use crate::closures; use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, - rewrite_missing_comment, CharClasses, FindUncommented, + combine_strs_with_missing_comments, comment_style, contains_comment, recover_comment_removed, + rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, }; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; @@ -808,7 +808,7 @@ impl<'a> ControlFlow<'a> { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pat, expr); let cond_shape = shape.offset_left(offset)?; - if !self.pat.is_none() { + if let Some(pat) = self.pat { let matcher = if self.matcher.is_empty() { self.matcher.to_owned() } else { @@ -817,12 +817,41 @@ impl<'a> ControlFlow<'a> { let pat_shape = cond_shape .offset_left(matcher.len())? .sub_width(self.connector.len())?; - let pat_string = if let Some(pat) = self.pat { - pat.rewrite(context, pat_shape)? + let pat_string = pat.rewrite(context, pat_shape)?; + let comments_lo = context + .snippet_provider + .span_after(self.span, self.connector.trim()); + let missing_comments = if let Some(comment) = + rewrite_missing_comment(mk_sp(comments_lo, expr.span.lo()), cond_shape, context) + { + if !self.connector.is_empty() && !comment.is_empty() { + if comment_style(&comment, false).is_line_comment() || comment.contains("\n") { + let newline = &pat_shape + .indent + .block_indent(context.config) + .to_string_with_newline(context.config); + // An extra space is added when the lhs and rhs are joined + // so we need to remove one space from the end to ensure + // the comment and rhs are aligned. + let mut suffix = newline.as_ref().to_string(); + if !suffix.is_empty() { + suffix.truncate(suffix.len() - 1); + } + format!("{}{}{}", newline, comment, suffix) + } else { + format!(" {}", comment) + } + } else { + comment + } } else { "".to_owned() }; - let result = format!("{}{}{}", matcher, pat_string, self.connector); + + let result = format!( + "{}{}{}{}", + matcher, pat_string, self.connector, missing_comments + ); return rewrite_assign_rhs(context, result, expr, cond_shape); } diff --git a/tests/source/issue_3853.rs b/tests/source/issue_3853.rs index d2cd9a98a1f..c41309bc788 100644 --- a/tests/source/issue_3853.rs +++ b/tests/source/issue_3853.rs @@ -33,3 +33,20 @@ fn issue_3853() { if let Some(ref /*mut*/ state) = foo { } } + +fn double_slash_comment_between_lhs_and_rhs() { + if let Some(e) = + // self.foo.bar(e, tx) + packet.transaction.state.committed + { + // body + println!( + "a2304712836123"); + } +} + +fn block_comment_between_lhs_and_rhs() { +if let Some(ref /*def*/ mut /*abc*/ state)= /*abc*/foo{ + println!( + "asdfasdfasdf"); } +} diff --git a/tests/target/issue_3853.rs b/tests/target/issue_3853.rs index 53b94d3fc00..eae59eff94e 100644 --- a/tests/target/issue_3853.rs +++ b/tests/target/issue_3853.rs @@ -29,3 +29,19 @@ fn no_prefix_block_before_ident() { fn issue_3853() { if let Some(ref /*mut*/ state) = foo {} } + +fn double_slash_comment_between_lhs_and_rhs() { + if let Some(e) = + // self.foo.bar(e, tx) + packet.transaction.state.committed + { + // body + println!("a2304712836123"); + } +} + +fn block_comment_between_lhs_and_rhs() { + if let Some(ref /*def*/ mut /*abc*/ state) = /*abc*/ foo { + println!("asdfasdfasdf"); + } +} -- cgit 1.4.1-3-g733a5 From a5d16df9a4b294e3db339dacb0f83aab61f2acc5 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 19 Oct 2019 02:35:33 -0500 Subject: feat: use offline by default with cargo fmt (#3830) --- src/cargo-fmt/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index acaf81e0665..233a0f1d145 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -519,11 +519,12 @@ fn get_cargo_metadata( if let Some(manifest_path) = manifest_path { cmd.manifest_path(manifest_path); } + cmd.other_options(&[String::from("--offline")]); match cmd.exec() { Ok(metadata) => Ok(metadata), Err(_) => { - cmd.other_options(&[String::from("--offline")]); + cmd.other_options(vec![]); match cmd.exec() { Ok(metadata) => Ok(metadata), Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())), -- cgit 1.4.1-3-g733a5 From 5327c3633ff23f06cdf62ac2f98ef141731a3478 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Sat, 19 Oct 2019 09:56:32 +0200 Subject: handle field attributes when aligning a struct's fields (#3513) --- src/items.rs | 2 +- src/vertical.rs | 33 ++++++++--------- tests/source/issue-2869.rs | 41 ++++++++++++++++++++++ .../configs/struct_field_align_threshold/20.rs | 10 +++--- tests/target/issue-2869.rs | 41 ++++++++++++++++++++++ 5 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 tests/source/issue-2869.rs create mode 100644 tests/target/issue-2869.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 7092659158a..401cf78d721 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1617,7 +1617,7 @@ pub(crate) fn rewrite_struct_field( shape, attrs_extendable, )?; - let overhead = last_line_width(&attr_prefix); + let overhead = trimmed_last_line_width(&attr_prefix); let lhs_offset = lhs_max_width.saturating_sub(overhead); for _ in 0..lhs_offset { spacing.push(' '); diff --git a/src/vertical.rs b/src/vertical.rs index 62cc7d8b33d..59b03789fb5 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -6,7 +6,7 @@ use itertools::Itertools; use syntax::ast; use syntax::source_map::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, contains_comment}; +use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; use crate::expr::rewrite_field; use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix}; @@ -17,7 +17,9 @@ use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; -use crate::utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; +use crate::utils::{ + contains_skip, is_attributes_extendable, mk_sp, rewrite_ident, trimmed_last_line_width, +}; pub(crate) trait AlignedItem { fn skip(&self) -> bool; @@ -183,13 +185,9 @@ fn struct_field_prefix_max_min_width( fields .iter() .map(|field| { - field.rewrite_prefix(context, shape).and_then(|field_str| { - if field_str.contains('\n') { - None - } else { - Some(field_str.len()) - } - }) + field + .rewrite_prefix(context, shape) + .map(|field_str| trimmed_last_line_width(&field_str)) }) .fold_options((0, ::std::usize::MAX), |(max_len, min_len), len| { (cmp::max(max_len, len), cmp::min(min_len, len)) @@ -255,6 +253,9 @@ fn rewrite_aligned_items_inner( write_list(&items, &fmt) } +/// Returns the index in `fields` up to which a field belongs to the current group. +/// The returned string is the group separator to use when rewriting the fields. +/// Groups are defined by blank lines. fn group_aligned_items( context: &RewriteContext<'_>, fields: &[T], @@ -264,7 +265,6 @@ fn group_aligned_items( if fields[i].skip() { return ("", index); } - // See if there are comments or empty lines between fields. let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo()); let snippet = context .snippet(span) @@ -272,17 +272,12 @@ fn group_aligned_items( .skip(1) .collect::>() .join("\n"); - let spacings = if snippet + let has_blank_line = snippet .lines() .dropping_back(1) - .any(|l| l.trim().is_empty()) - { - "\n" - } else { - "" - }; - if contains_comment(&snippet) || snippet.lines().count() > 1 { - return (spacings, index); + .any(|l| l.trim().is_empty()); + if has_blank_line { + return ("\n", index); } index += 1; } diff --git a/tests/source/issue-2869.rs b/tests/source/issue-2869.rs new file mode 100644 index 00000000000..d18adfb462e --- /dev/null +++ b/tests/source/issue-2869.rs @@ -0,0 +1,41 @@ +// rustfmt-struct_field_align_threshold: 50 + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct AuditLog1 { + creation_time: String, + id: String, + operation: String, + organization_id: String, + record_type: u32, + result_status: Option, + #[serde(rename = "ClientIP")] + client_ip: Option, + object_id: String, + actor: Option>, + actor_context_id: Option, + actor_ip_address: Option, + azure_active_directory_event_type: Option, + + #[serde(rename = "very")] + aaaaa: String, + #[serde(rename = "cool")] + bb: i32, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct AuditLog2 { + creation_time: String, + id: String, + operation: String, + organization_id: String, + record_type: u32, + result_status: Option, + client_ip: Option, + object_id: String, + actor: Option>, + actor_context_id: Option, + actor_ip_address: Option, + azure_active_directory_event_type: Option, +} diff --git a/tests/target/configs/struct_field_align_threshold/20.rs b/tests/target/configs/struct_field_align_threshold/20.rs index 848abd3d3cf..12a523e9d83 100644 --- a/tests/target/configs/struct_field_align_threshold/20.rs +++ b/tests/target/configs/struct_field_align_threshold/20.rs @@ -38,12 +38,12 @@ fn main() { pub struct Foo { #[rustfmt::skip] f : SomeType, // Comment beside a field - f: SomeType, // Comment beside a field + f: SomeType, // Comment beside a field // Comment on a field #[AnAttribute] - g: SomeOtherType, + g: SomeOtherType, /// A doc comment on a field - h: AThirdType, + h: AThirdType, pub i: TypeForPublicField, } @@ -66,7 +66,7 @@ struct X { pub struct Writebatch { #[allow(dead_code)] // only used for holding the internal pointer writebatch: RawWritebatch, - marker: PhantomData, + marker: PhantomData, } struct Bar; @@ -323,7 +323,7 @@ fn main() { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante // hendrerit. Donec et mollis dolor. - first: item(), + first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. second: Item, diff --git a/tests/target/issue-2869.rs b/tests/target/issue-2869.rs new file mode 100644 index 00000000000..6a68c2d95fa --- /dev/null +++ b/tests/target/issue-2869.rs @@ -0,0 +1,41 @@ +// rustfmt-struct_field_align_threshold: 50 + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct AuditLog1 { + creation_time: String, + id: String, + operation: String, + organization_id: String, + record_type: u32, + result_status: Option, + #[serde(rename = "ClientIP")] + client_ip: Option, + object_id: String, + actor: Option>, + actor_context_id: Option, + actor_ip_address: Option, + azure_active_directory_event_type: Option, + + #[serde(rename = "very")] + aaaaa: String, + #[serde(rename = "cool")] + bb: i32, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "PascalCase")] +struct AuditLog2 { + creation_time: String, + id: String, + operation: String, + organization_id: String, + record_type: u32, + result_status: Option, + client_ip: Option, + object_id: String, + actor: Option>, + actor_context_id: Option, + actor_ip_address: Option, + azure_active_directory_event_type: Option, +} -- cgit 1.4.1-3-g733a5 From 3a073f177ca7466cf3e8327a7fc847d495d75fd7 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 19 Oct 2019 03:15:13 -0500 Subject: fix: handling of newline_style conflicts (#3850) --- src/emitter/diff.rs | 28 ++++++++++++++++++++++++++++ src/formatting.rs | 10 ++++++++-- src/source_file.rs | 37 ++++++++++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/emitter/diff.rs b/src/emitter/diff.rs index 462a80946ee..9be4fb28f99 100644 --- a/src/emitter/diff.rs +++ b/src/emitter/diff.rs @@ -36,6 +36,13 @@ impl Emitter for DiffEmitter { &self.config, ); } + } else if original_text != formatted_text { + // This occurs when the only difference between the original and formatted values + // is the newline style. This happens because The make_diff function compares the + // original and formatted values line by line, independent of line endings. + let file_path = ensure_real_path(filename); + writeln!(output, "Incorrect newline style in {}", file_path.display())?; + return Ok(EmitterResult { has_diff: true }); } return Ok(EmitterResult { has_diff }); @@ -107,4 +114,25 @@ mod tests { format!("{}\n{}\n", bin_file, lib_file), ) } + + #[test] + fn prints_newline_message_with_only_newline_style_diff() { + let mut writer = Vec::new(); + let config = Config::default(); + let mut emitter = DiffEmitter::new(config); + let _ = emitter + .emit_formatted_file( + &mut writer, + FormattedFile { + filename: &FileName::Real(PathBuf::from("src/lib.rs")), + original_text: "fn empty() {}\n", + formatted_text: "fn empty() {}\r\n", + }, + ) + .unwrap(); + assert_eq!( + String::from_utf8(writer).unwrap(), + String::from("Incorrect newline style in src/lib.rs\n") + ); + } } diff --git a/src/formatting.rs b/src/formatting.rs index eec33e6ba79..2822a331260 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -243,8 +243,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { - match source_file::write_file(Some(source_map), &path, &result, out, &mut *self.emitter) - { + match source_file::write_file( + Some(source_map), + &path, + &result, + out, + &mut *self.emitter, + self.config.newline_style(), + ) { Ok(ref result) if result.has_diff => report.add_diff(), Err(e) => { // Create a new error with path_str to help users see which files failed diff --git a/src/source_file.rs b/src/source_file.rs index 28366ca2485..b6764ee7464 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -6,6 +6,7 @@ use syntax::source_map::SourceMap; use crate::config::FileName; use crate::emitter::{self, Emitter}; +use crate::NewlineStyle; #[cfg(test)] use crate::config::Config; @@ -32,7 +33,14 @@ where emitter.emit_header(out)?; for &(ref filename, ref text) in source_file { - write_file(None, filename, text, out, &mut *emitter)?; + write_file( + None, + filename, + text, + out, + &mut *emitter, + config.newline_style(), + )?; } emitter.emit_footer(out)?; @@ -45,6 +53,7 @@ pub(crate) fn write_file( formatted_text: &str, out: &mut T, emitter: &mut dyn Emitter, + newline_style: NewlineStyle, ) -> Result where T: Write, @@ -65,15 +74,25 @@ where } } - // If parse session is around (cfg(not(test))) then try getting source from - // there instead of hitting the file system. This also supports getting + // SourceFile's in the SourceMap will always have Unix-style line endings + // See: https://github.com/rust-lang/rustfmt/issues/3850 + // So if the user has explicitly overridden the rustfmt `newline_style` + // config and `filename` is FileName::Real, then we must check the file system + // to get the original file value in order to detect newline_style conflicts. + // Otherwise, parse session is around (cfg(not(test))) and newline_style has been + // left as the default value, then try getting source from the parse session + // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. - let original_text = source_map - .and_then(|x| x.get_source_file(&filename.into())) - .and_then(|x| x.src.as_ref().map(ToString::to_string)); - let original_text = match original_text { - Some(ori) => ori, - None => fs::read_to_string(ensure_real_path(filename))?, + let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { + fs::read_to_string(ensure_real_path(filename))? + } else { + match source_map + .and_then(|x| x.get_source_file(&filename.into())) + .and_then(|x| x.src.as_ref().map(ToString::to_string)) + { + Some(ori) => ori, + None => fs::read_to_string(ensure_real_path(filename))?, + } }; let formatted_file = emitter::FormattedFile { -- cgit 1.4.1-3-g733a5 From 69c7dbcd5026b75dee78e4fd14fbe57ffd1d4e4e Mon Sep 17 00:00:00 2001 From: Rui Date: Sat, 19 Oct 2019 17:19:47 +0800 Subject: Try to solve issue3456. (#3556) --- src/expr.rs | 22 ++-------------------- src/utils.rs | 3 +-- tests/target/multiline_string_in_macro_def.rs | 14 ++++++++++++++ ...format_string_when_format_strings_is_not_set.rs | 16 ++++++++++++++++ 4 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 tests/target/multiline_string_in_macro_def.rs create mode 100644 tests/target/should_not_format_string_when_format_strings_is_not_set.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1d9625298c5..8665f2a7248 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1187,27 +1187,9 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> .lines() .dropping_back(1) .all(|line| line.ends_with('\\')) + && context.config.version() == Version::Two { - let new_indent = shape.visual_indent(1).indent; - let indented_string_lit = String::from( - string_lit - .lines() - .map(|line| { - format!( - "{}{}", - new_indent.to_string(context.config), - line.trim_start() - ) - }) - .collect::>() - .join("\n") - .trim_start(), - ); - return if context.config.version() == Version::Two { - Some(indented_string_lit) - } else { - wrap_str(indented_string_lit, context.config.max_width(), shape) - }; + return Some(string_lit.to_owned()); } else { return wrap_str(string_lit.to_owned(), context.config.max_width(), shape); } diff --git a/src/utils.rs b/src/utils.rs index 47f9cd94b8d..d01a0ff73ba 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -618,9 +618,8 @@ pub(crate) fn trim_left_preserve_layout( /// Based on the given line, determine if the next line can be indented or not. /// This allows to preserve the indentation of multi-line literals. -pub(crate) fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Config) -> bool { +pub(crate) fn indent_next_line(kind: FullCodeCharKind, _line: &str, config: &Config) -> bool { !(kind.is_string() || (config.version() == Version::Two && kind.is_commented_string())) - || line.ends_with('\\') } pub(crate) fn is_empty_line(s: &str) -> bool { diff --git a/tests/target/multiline_string_in_macro_def.rs b/tests/target/multiline_string_in_macro_def.rs new file mode 100644 index 00000000000..dafc738f8db --- /dev/null +++ b/tests/target/multiline_string_in_macro_def.rs @@ -0,0 +1,14 @@ +macro_rules! assert_approx_eq { + ($a:expr, $b:expr, $eps:expr) => {{ + let (a, b) = (&$a, &$b); + assert!( + (*a - *b).abs() < $eps, + "assertion failed: `(left !== right)` \ + (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)", + *a, + *b, + $eps, + (*a - *b).abs() + ); + }}; +} diff --git a/tests/target/should_not_format_string_when_format_strings_is_not_set.rs b/tests/target/should_not_format_string_when_format_strings_is_not_set.rs new file mode 100644 index 00000000000..efb755d4aea --- /dev/null +++ b/tests/target/should_not_format_string_when_format_strings_is_not_set.rs @@ -0,0 +1,16 @@ +// format_strings is false by default. + +println!( + "DirEntry {{ \ + binary_name: {:<64}, \ + context_id: {:>2}, \ + file_size: {:>6}, \ + offset: 0x {:>08X}, \ + actual_crc: 0x{:>08X} \ + }}", + dir_entry.binary_name, + dir_entry.context_id, + dir_entry.file_size, + dir_entry.offset, + dir_entry.actual_crc +); -- cgit 1.4.1-3-g733a5 From 233497aceb3542aaa40fd8011bb8e5339f5ed60f Mon Sep 17 00:00:00 2001 From: rChaser53 Date: Thu, 24 Oct 2019 22:16:56 +0900 Subject: fix Unparsable code when formmating (#3883) --- src/items.rs | 10 ++++++++-- tests/target/issue-3882.rs | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-3882.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 401cf78d721..64ed2d9294c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2218,10 +2218,16 @@ fn rewrite_fn_base( .map_or(false, |last_line| last_line.contains("//")); if context.config.version() == Version::Two { - result.push(')'); - if closing_paren_overflow_max_width || params_last_line_contains_comment { + if closing_paren_overflow_max_width { + result.push(')'); result.push_str(&indent.to_string_with_newline(context.config)); no_params_and_over_max_width = true; + } else if params_last_line_contains_comment { + result.push_str(&indent.to_string_with_newline(context.config)); + result.push(')'); + no_params_and_over_max_width = true; + } else { + result.push(')'); } } else { if closing_paren_overflow_max_width || params_last_line_contains_comment { diff --git a/tests/target/issue-3882.rs b/tests/target/issue-3882.rs new file mode 100644 index 00000000000..5eb442af974 --- /dev/null +++ b/tests/target/issue-3882.rs @@ -0,0 +1,4 @@ +// rustfmt-version: Two +fn bar(_t: T, // bar +) { +} -- cgit 1.4.1-3-g733a5 From 99f9f576d46607e74f07c25a860de499dbce5c4d Mon Sep 17 00:00:00 2001 From: Chris Emerson Date: Fri, 25 Oct 2019 07:05:24 +0100 Subject: Return an error if `--check` or `--emit json` are used with stdin. (#3875) --- src/bin/main.rs | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 7290c2f30d5..661502a2e0e 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -73,6 +73,14 @@ pub enum OperationError { /// An io error during reading or writing. #[fail(display = "io error: {}", _0)] IoError(IoError), + /// Attempt to use --check with stdin, which isn't currently + /// supported. + #[fail(display = "The `--check` option is not supported with standard input.")] + CheckWithStdin, + /// Attempt to use --emit=json with stdin, which isn't currently + /// supported. + #[fail(display = "Using `--emit` other than stdout is not supported with standard input.")] + EmitWithStdin, } impl From for OperationError { @@ -242,6 +250,14 @@ fn format_string(input: String, options: GetOptsOptions) -> Result, inline_config: HashMap, - emit_mode: EmitMode, + emit_mode: Option, backup: bool, check: bool, edition: Option, @@ -574,7 +590,7 @@ impl GetOptsOptions { return Err(format_err!("Invalid to use `--emit` and `--check`")); } - options.emit_mode = emit_mode_from_emit_str(emit_str)?; + options.emit_mode = Some(emit_mode_from_emit_str(emit_str)?); } if let Some(ref edition_str) = matches.opt_str("edition") { @@ -590,11 +606,13 @@ impl GetOptsOptions { } if !rust_nightly { - if !STABLE_EMIT_MODES.contains(&options.emit_mode) { - return Err(format_err!( - "Invalid value for `--emit` - using an unstable \ - value without `--unstable-features`", - )); + if let Some(ref emit_mode) = options.emit_mode { + if !STABLE_EMIT_MODES.contains(emit_mode) { + return Err(format_err!( + "Invalid value for `--emit` - using an unstable \ + value without `--unstable-features`", + )); + } } } @@ -643,8 +661,8 @@ impl CliOptions for GetOptsOptions { } if self.check { config.set().emit_mode(EmitMode::Diff); - } else { - config.set().emit_mode(self.emit_mode); + } else if let Some(emit_mode) = self.emit_mode { + config.set().emit_mode(emit_mode); } if self.backup { config.set().make_backup(true); -- cgit 1.4.1-3-g733a5 From 731f15551bbdf11e971b5a518d69c8f5772dfe9b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 3 Dec 2019 08:47:50 +0900 Subject: Do not add block around async closure (#3946) --- src/closures.rs | 1 + tests/target/async_closure.rs | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index eaa42b991f2..ed5c577d933 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -170,6 +170,7 @@ fn rewrite_closure_expr( fn allow_multi_line(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Match(..) + | ast::ExprKind::Async(..) | ast::ExprKind::Block(..) | ast::ExprKind::TryBlock(..) | ast::ExprKind::Loop(..) diff --git a/tests/target/async_closure.rs b/tests/target/async_closure.rs index db6405482c5..9364e7dcc67 100644 --- a/tests/target/async_closure.rs +++ b/tests/target/async_closure.rs @@ -15,4 +15,8 @@ fn main() { let x = 3; x }; + + let f = |x| async { + println!("hello, world"); + }; } -- cgit 1.4.1-3-g733a5 From c60416ed2167716dd6e7141573fbc6dde42e09e3 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 8 Feb 2020 22:21:37 -0600 Subject: deps: update rustc-ap to v642.0.0 --- Cargo.lock | 359 ++++++++++++++++++++++++++++++--------------- Cargo.toml | 36 ++++- src/attr.rs | 13 +- src/chains.rs | 2 +- src/closures.rs | 6 +- src/comment.rs | 2 +- src/config/file_lines.rs | 11 +- src/config/options.rs | 6 +- src/expr.rs | 33 +++-- src/formatting.rs | 35 +++-- src/imports.rs | 7 +- src/items.rs | 174 ++++++++++++++-------- src/lib.rs | 3 +- src/lists.rs | 2 +- src/macros.rs | 67 ++++----- src/matches.rs | 4 +- src/missed_spans.rs | 2 +- src/modules.rs | 35 +++-- src/modules/visitor.rs | 11 +- src/overflow.rs | 4 +- src/patterns.rs | 45 +++--- src/reorder.rs | 9 +- src/rewrite.rs | 4 +- src/skip.rs | 9 +- src/source_file.rs | 10 +- src/source_map.rs | 2 +- src/spanned.rs | 9 +- src/stmt.rs | 2 +- src/types.rs | 20 +-- src/utils.rs | 32 ++-- src/vertical.rs | 2 +- src/visitor.rs | 214 +++++++++++++++++---------- tests/source/issue-2916.rs | 2 + tests/target/issue-2916.rs | 2 +- 34 files changed, 736 insertions(+), 438 deletions(-) create mode 100644 tests/source/issue-2916.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 21517aa4b6d..094fcfd384b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,7 +42,7 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -58,7 +58,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -68,7 +68,7 @@ version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -165,10 +165,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "crossbeam-channel" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -210,6 +210,16 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive-new" version = "0.5.8" @@ -240,7 +250,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -314,7 +324,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -348,17 +358,17 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -390,19 +400,10 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -410,7 +411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.65" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -429,11 +430,31 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "measureme" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memoffset" version = "0.5.1" @@ -452,7 +473,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -480,7 +501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -538,7 +559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -596,23 +617,52 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "610.0.0" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "610.0.0" +version = "642.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-ap-rustc_ast_pretty" +version = "642.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-ap-rustc_attr" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-ap-rustc_data_structures" -version = "610.0.0" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -620,45 +670,63 @@ dependencies = [ "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "610.0.0" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-ap-rustc_feature" +version = "642.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_fs_util" +version = "642.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-ap-rustc_index" -version = "610.0.0" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "610.0.0" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -666,7 +734,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "610.0.0" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -677,59 +745,96 @@ dependencies = [ ] [[package]] -name = "rustc-ap-rustc_target" -version = "610.0.0" +name = "rustc-ap-rustc_parse" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc-ap-serialize" -version = "610.0.0" +name = "rustc-ap-rustc_session" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc-ap-syntax" -version = "610.0.0" +name = "rustc-ap-rustc_span" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc-ap-syntax_pos" -version = "610.0.0" +name = "rustc-ap-rustc_target" +version = "642.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-ap-serialize" +version = "642.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-ap-syntax" +version = "642.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -791,7 +896,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.11" +version = "1.4.12" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -802,14 +907,19 @@ dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -892,6 +1002,11 @@ name = "smallvec" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "smallvec" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -954,21 +1069,20 @@ dependencies = [ ] [[package]] -name = "term_size" -version = "0.3.1" +name = "termcolor" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "termcolor" -version = "1.0.5" +name = "termize" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -987,6 +1101,14 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "toml" version = "0.5.3" @@ -995,6 +1117,14 @@ dependencies = [ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-segmentation" version = "1.3.0" @@ -1035,11 +1165,6 @@ name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.3.8" @@ -1049,11 +1174,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1103,11 +1223,12 @@ dependencies = [ "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" @@ -1124,17 +1245,18 @@ dependencies = [ "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum ignore 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0ec16832258409d571aaef8273f3c3cc5b060d784e159d1a0f3b0017308f84a7" +"checksum ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" @@ -1154,17 +1276,23 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7475f4c707269b56eb7144c53591e3cd6369a5aa1d66434829ea11df96d5e7e3" -"checksum rustc-ap-graphviz 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e59a55520f140a70a3e0fad80a36e807caa85e9d7016167b91a5b521ea929be" -"checksum rustc-ap-rustc_data_structures 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6420857d5a088f680ec1ba736ffba4ee9c1964b0d397e6318f38d461f4f7d5cb" -"checksum rustc-ap-rustc_errors 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8abfca0960131262254a91d02ff4903526a261ede730d7a2c75b4234c867cdc0" -"checksum rustc-ap-rustc_index 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a395509dcb90a92c1479c085639594624e06b4ab3fc7c1b795b46a61f2d4f65" -"checksum rustc-ap-rustc_lexer 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64eac8a0e6efb8f55292aa24be0208c7c0538236c613e79952fd1fa3d54bcf8e" -"checksum rustc-ap-rustc_macros 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f99795e8be4877e9e05d59f201e1740c1cf673364655def5848606d9e25b75af" -"checksum rustc-ap-rustc_target 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f22e21fdd8e1c0030f507158fa79b9f1e080e6241aba994d0f97c14a0a07a826" -"checksum rustc-ap-serialize 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1cd6ef5135408d62559866e79986ca261f4c1333253d500e5e66fe66d1432e" -"checksum rustc-ap-syntax 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61fc1c901d2cbd24cae95d7bc5a58aa7661ec3dc5320c78c32830a52a685c33c" -"checksum rustc-ap-syntax_pos 610.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "230534f638255853bb9f13987537e00a818435a0cc54b68d97221b6822c8f1bc" +"checksum rustc-ap-arena 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea82fa3d9a8add7422228ca1a2cbba0784fa8861f56148ff64da08b3c7921b03" +"checksum rustc-ap-graphviz 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "638d0b2b3bcf99824e0cb5a25dbc547b61dc20942e11daf6a97e981918aa18e5" +"checksum rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d38bab04dd676dee6d2f9670506a18c31bfce38bf7f8420aa83eb1140ecde049" +"checksum rustc-ap-rustc_attr 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10b843ba8b1ed43739133047673b9f6a54d3b3b4d328d69c6ea89ff971395f35" +"checksum rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc3d1c6d0a80ab0c1df76405377cec0f3d5423fb5b0953a8eac70a2ad6c44df2" +"checksum rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4909a1eca29331332257230f29120a8ff68c9e37d868c564fcd599e430cf8914" +"checksum rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63ab887a181d795cf5fd3edadf367760deafb90aefb844f168ab5255266e3478" +"checksum rustc-ap-rustc_fs_util 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70814116df3c5fbec8f06f6a1d013ca481f620fd22a9475754e9bf3ee9ba70d8" +"checksum rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac1bf1d3cf3d119d41353d6fd229ef7272d5097bc0924de021c0294bf86d48bf" +"checksum rustc-ap-rustc_lexer 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4cda21a32cebdc11ec4f5393aa2fcde5ed1b2f673a8571e5a4dcdf07e4ae9cac" +"checksum rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75c47b48ea51910ecfd853c9248a9bf4c767bc823449ab6a1d864dff65fbae16" +"checksum rustc-ap-rustc_parse 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abd88e89cd5b5d28dcd3a347a3d534c08627d9455570dc1a2d402cb8437b9d30" +"checksum rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8487b4575fbb2d1fc6f1cd61225efd108a4d36817e6fb9b643d57fcae9cb12" +"checksum rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f69746c0d4c21bf20a5bb2bd247261a1aa8631f04202d7303352942dde70d987" +"checksum rustc-ap-rustc_target 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bbc6ae09b5d42ec66edd520e8412e0615c53a7c93607fe33dc4abab60ba7c8b" +"checksum rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e13a1ead0252fc3d96da4c336a95950be6795f2b00c84a67ccadf26142f8cb41" +"checksum rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f59f48ca3a2ec16a7e82e718ed5aadf9c9e08cf63015d28b4e774767524a6a" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" @@ -1181,6 +1309,7 @@ dependencies = [ "checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f66a4c0ddf7aee4677995697366de0749b0139057342eccbb609b12d0affc" @@ -1188,11 +1317,13 @@ dependencies = [ "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" "checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" -"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" +"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" @@ -1200,9 +1331,7 @@ dependencies = [ "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 4d190c6800a..1cfa80de8bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.11" +version = "1.4.12" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -52,7 +52,7 @@ bytecount = "0.6" unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "2.0.1" -ignore = "0.4.6" +ignore = "0.4.11" annotate-snippets = { version = "0.6", features = ["ansi_term"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } @@ -62,17 +62,37 @@ rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } # for more information. rustc-workspace-hack = "1.0.0" +[dependencies.rustc_ast_pretty] +package = "rustc-ap-rustc_ast_pretty" +version = "642.0.0" + +[dependencies.rustc_data_structures] +package = "rustc-ap-rustc_data_structures" +version = "642.0.0" + +[dependencies.rustc_errors] +package = "rustc-ap-rustc_errors" +version = "642.0.0" + +[dependencies.rustc_parse] +package = "rustc-ap-rustc_parse" +version = "642.0.0" + +[dependencies.rustc_session] +package = "rustc-ap-rustc_session" +version = "642.0.0" + +[dependencies.rustc_span] +package = "rustc-ap-rustc_span" +version = "642.0.0" + [dependencies.rustc_target] package = "rustc-ap-rustc_target" -version = "610.0.0" +version = "642.0.0" [dependencies.syntax] package = "rustc-ap-syntax" -version = "610.0.0" - -[dependencies.syntax_pos] -package = "rustc-ap-syntax_pos" -version = "610.0.0" +version = "642.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/attr.rs b/src/attr.rs index 63a01e56603..461f0ddf029 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,8 +1,7 @@ //! Format attributes and meta items. +use rustc_span::{symbol::sym, BytePos, Span, DUMMY_SP}; use syntax::ast; -use syntax::source_map::{BytePos, Span, DUMMY_SP}; -use syntax::symbol::sym; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; @@ -35,7 +34,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, ast::StmtKind::Mac(ref mac) => { let (ref mac, _, _) = **mac; - mac.span + mac.span() } } } @@ -168,7 +167,7 @@ fn rewrite_initial_doc_comments( return Some((0, None)); } // Rewrite doc comments - let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_sugared_doc); + let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_doc_comment()); if !sugared_docs.is_empty() { let snippet = sugared_docs .iter() @@ -316,7 +315,7 @@ where impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let snippet = context.snippet(self.span); - if self.is_sugared_doc { + if self.is_doc_comment() { rewrite_doc_comment(snippet, shape.comment(context.config), context.config) } else { let should_skip = self @@ -438,7 +437,7 @@ impl<'a> Rewrite for [ast::Attribute] { )?; result.push_str(&comment); if let Some(next) = attrs.get(derives.len()) { - if next.is_sugared_doc { + if next.is_doc_comment() { let snippet = context.snippet(missing_span); let (_, mlb) = has_newlines_before_after_comment(snippet); result.push_str(&mlb); @@ -471,7 +470,7 @@ impl<'a> Rewrite for [ast::Attribute] { )?; result.push_str(&comment); if let Some(next) = attrs.get(1) { - if next.is_sugared_doc { + if next.is_doc_comment() { let snippet = context.snippet(missing_span); let (_, mlb) = has_newlines_before_after_comment(snippet); result.push_str(&mlb); diff --git a/src/chains.rs b/src/chains.rs index ff8d7214c54..a7a9127cbbd 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -58,7 +58,7 @@ use std::borrow::Cow; use std::cmp::min; -use syntax::source_map::{BytePos, Span}; +use rustc_span::{BytePos, Span}; use syntax::{ast, ptr}; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; diff --git a/src/closures.rs b/src/closures.rs index ed5c577d933..18e867cabd1 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,4 +1,4 @@ -use syntax::source_map::Span; +use rustc_span::Span; use syntax::{ast, ptr}; use crate::attr::get_attrs_from_stmt; @@ -176,7 +176,7 @@ fn rewrite_closure_expr( | ast::ExprKind::Loop(..) | ast::ExprKind::Struct(..) => true, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) @@ -382,7 +382,7 @@ fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool { match expr.kind { ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true, ast::ExprKind::Loop(..) if version == Version::Two => true, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) diff --git a/src/comment.rs b/src/comment.rs index c721f07d019..5b46001ff7d 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -3,7 +3,7 @@ use std::{self, borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; -use syntax::source_map::Span; +use rustc_span::Span; use crate::config::Config; use crate::rewrite::RewriteContext; diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index f0dc6c66597..d0ef489e2ca 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -6,11 +6,10 @@ use std::path::PathBuf; use std::rc::Rc; use std::{cmp, fmt, iter, str}; +use rustc_span::{self, SourceFile}; use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; -use syntax::source_map::{self, SourceFile}; - /// A range of lines in a file, inclusive of both ends. pub struct LineRange { pub file: Rc, @@ -25,11 +24,11 @@ pub enum FileName { Stdin, } -impl From for FileName { - fn from(name: source_map::FileName) -> FileName { +impl From for FileName { + fn from(name: rustc_span::FileName) -> FileName { match name { - source_map::FileName::Real(p) => FileName::Real(p), - source_map::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, + rustc_span::FileName::Real(p) => FileName::Real(p), + rustc_span::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, _ => unreachable!(), } } diff --git a/src/config/options.rs b/src/config/options.rs index 4a136f4b180..c9d51a5a71a 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -385,10 +385,10 @@ impl Default for Edition { } impl Edition { - pub(crate) fn to_libsyntax_pos_edition(self) -> syntax_pos::edition::Edition { + pub(crate) fn to_libsyntax_pos_edition(self) -> rustc_span::edition::Edition { match self { - Edition::Edition2015 => syntax_pos::edition::Edition::Edition2015, - Edition::Edition2018 => syntax_pos::edition::Edition::Edition2018, + Edition::Edition2015 => rustc_span::edition::Edition::Edition2015, + Edition::Edition2018 => rustc_span::edition::Edition::Edition2018, } } } diff --git a/src/expr.rs b/src/expr.rs index 851e1f70709..a694cc69ac6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2,8 +2,8 @@ use std::borrow::Cow; use std::cmp::min; use itertools::Itertools; -use syntax::parse::token::{DelimToken, LitKind}; -use syntax::source_map::{BytePos, SourceMap, Span}; +use rustc_span::{source_map::SourceMap, BytePos, Span}; +use syntax::token::{DelimToken, LitKind}; use syntax::{ast, ptr}; use crate::chains::rewrite_chain; @@ -159,7 +159,7 @@ pub(crate) fn format_expr( ast::ExprKind::Path(ref qself, ref path) => { rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape) } - ast::ExprKind::Assign(ref lhs, ref rhs) => { + ast::ExprKind::Assign(ref lhs, ref rhs, _) => { rewrite_assignment(context, lhs, rhs, None, shape) } ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { @@ -213,8 +213,8 @@ pub(crate) fn format_expr( rewrite_unary_prefix(context, "return ", &**expr, shape) } ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape), - ast::ExprKind::AddrOf(mutability, ref expr) => { - rewrite_expr_addrof(context, mutability, expr, shape) + ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => { + rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape) } ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, @@ -252,7 +252,7 @@ pub(crate) fn format_expr( fn needs_space_before_range(context: &RewriteContext<'_>, lhs: &ast::Expr) -> bool { match lhs.kind { ast::ExprKind::Lit(ref lit) => match lit.kind { - ast::LitKind::FloatUnsuffixed(..) => { + ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) => { context.snippet(lit.span).ends_with('.') } _ => false, @@ -1268,7 +1268,7 @@ pub(crate) fn is_simple_expr(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Lit(..) => true, ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Field(ref expr, _) @@ -1314,8 +1314,12 @@ pub(crate) fn can_be_overflowed_expr( || (context.use_block_indent() && args_len == 1) } ast::ExprKind::Mac(ref mac) => { - match (mac.delim, context.config.overflow_delimited_expr()) { - (ast::MacDelimiter::Bracket, true) | (ast::MacDelimiter::Brace, true) => true, + match ( + syntax::ast::MacDelimiter::from_token(mac.args.delim()), + context.config.overflow_delimited_expr(), + ) { + (Some(ast::MacDelimiter::Bracket), true) + | (Some(ast::MacDelimiter::Brace), true) => true, _ => context.use_block_indent() && args_len == 1, } } @@ -1326,7 +1330,7 @@ pub(crate) fn can_be_overflowed_expr( } // Handle unary-like expressions - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) @@ -1338,7 +1342,7 @@ pub(crate) fn can_be_overflowed_expr( pub(crate) fn is_nested_call(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) @@ -1985,13 +1989,14 @@ pub(crate) fn prefer_next_line( fn rewrite_expr_addrof( context: &RewriteContext<'_>, + _borrow_kind: ast::BorrowKind, mutability: ast::Mutability, expr: &ast::Expr, shape: Shape, ) -> Option { let operator_str = match mutability { - ast::Mutability::Immutable => "&", - ast::Mutability::Mutable => "&mut ", + ast::Mutability::Not => "&", + ast::Mutability::Mut => "&mut ", }; rewrite_unary_prefix(context, operator_str, expr, shape) } @@ -1999,7 +2004,7 @@ fn rewrite_expr_addrof( pub(crate) fn is_method_call(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::MethodCall(..) => true, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Cast(ref expr, _) | ast::ExprKind::Try(ref expr) diff --git a/src/formatting.rs b/src/formatting.rs index 2822a331260..0c273400695 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -7,11 +7,15 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::rc::Rc; use std::time::{Duration, Instant}; +use rustc_data_structures::sync::{Lrc, Send}; +use rustc_errors::emitter::{Emitter, EmitterWriter}; +use rustc_errors::{ColorConfig, Diagnostic, DiagnosticBuilder, Handler, Level as DiagnosticLevel}; +use rustc_session::parse::ParseSess; +use rustc_span::{ + source_map::{FilePathMapping, SourceMap}, + Span, DUMMY_SP, +}; use syntax::ast; -use syntax::errors::emitter::{ColorConfig, Emitter, EmitterWriter}; -use syntax::errors::{Diagnostic, DiagnosticBuilder, Handler}; -use syntax::parse::{self, ParseSess}; -use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; @@ -108,7 +112,7 @@ fn format_project( let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( &context.parse_session, - directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(true)), + directory_ownership.unwrap_or(rustc_parse::DirectoryOwnership::UnownedViaMod), !(input_is_stdin || config.skip_children()), ) .visit_crate(&krate) @@ -159,7 +163,8 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { .lookup_char_pos(module.inner.lo()) .file; let big_snippet = source_file.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(source_file.start_pos, big_snippet); + let snippet_provider = + SnippetProvider::new(source_file.start_pos, source_file.end_pos, big_snippet); let mut visitor = FmtVisitor::from_source_map( &self.parse_session, &self.config, @@ -633,7 +638,7 @@ fn parse_crate( parse_session: &ParseSess, config: &Config, report: &mut FormatReport, - directory_ownership: Option, + directory_ownership: Option, can_reset_parser_errors: Rc>, ) -> Result { let input_is_stdin = input.is_text(); @@ -642,14 +647,14 @@ fn parse_crate( Input::File(ref file) => { // Use `new_sub_parser_from_file` when we the input is a submodule. Ok(if let Some(dir_own) = directory_ownership { - parse::new_sub_parser_from_file(parse_session, file, dir_own, None, DUMMY_SP) + rustc_parse::new_sub_parser_from_file(parse_session, file, dir_own, None, DUMMY_SP) } else { - parse::new_parser_from_file(parse_session, file) + rustc_parse::new_parser_from_file(parse_session, file) }) } - Input::Text(text) => parse::maybe_new_parser_from_source_str( + Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( parse_session, - syntax::source_map::FileName::Custom("stdin".to_owned()), + rustc_span::FileName::Custom("stdin".to_owned()), text, ) .map(|mut parser| { @@ -716,11 +721,14 @@ struct SilentOnIgnoredFilesEmitter { } impl Emitter for SilentOnIgnoredFilesEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } fn emit_diagnostic(&mut self, db: &Diagnostic) { if let Some(primary_span) = &db.span.primary_span() { let file_name = self.source_map.span_to_filename(*primary_span); match file_name { - syntax_pos::FileName::Real(ref path) => { + rustc_span::FileName::Real(ref path) => { if self .ignore_path_set .is_match(&FileName::Real(path.to_path_buf())) @@ -745,6 +753,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter { struct SilentEmitter; impl Emitter for SilentEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } fn emit_diagnostic(&mut self, _db: &Diagnostic) {} } diff --git a/src/imports.rs b/src/imports.rs index 139301f537a..9c914ce476d 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -2,9 +2,8 @@ use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; +use rustc_span::{source_map, symbol::sym, BytePos, Span, DUMMY_SP}; use syntax::ast::{self, UseTreeKind}; -use syntax::source_map::{self, BytePos, Span, DUMMY_SP}; -use syntax::symbol::sym; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; @@ -249,7 +248,7 @@ impl UseTree { let allow_extend = if attrs.len() == 1 { let line_len = attr_str.len() + 1 + use_str.len(); - !attrs.first().unwrap().is_sugared_doc + !attrs.first().unwrap().is_doc_comment() && context.config.inline_attribute_width() >= line_len } else { false @@ -849,7 +848,7 @@ impl Rewrite for UseTree { #[cfg(test)] mod test { use super::*; - use syntax::source_map::DUMMY_SP; + use rustc_span::DUMMY_SP; // Parse the path part of an import. This parser is not robust and is only // suitable for use in a test harness. diff --git a/src/items.rs b/src/items.rs index 64ed2d9294c..ed7b46c8e4f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -4,10 +4,9 @@ use std::borrow::Cow; use std::cmp::{max, min, Ordering}; use regex::Regex; -use rustc_target::spec::abi; -use syntax::source_map::{self, BytePos, Span}; +use rustc_span::{source_map, symbol, BytePos, Span, DUMMY_SP}; use syntax::visit; -use syntax::{ast, ptr, symbol}; +use syntax::{ast, ptr}; use crate::attr::filter_inline_attrs; use crate::comment::{ @@ -34,7 +33,7 @@ use crate::visitor::FmtVisitor; const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned { node: ast::VisibilityKind::Inherited, - span: source_map::DUMMY_SP, + span: DUMMY_SP, }; fn type_annotation_separator(config: &Config) -> &str { @@ -137,7 +136,11 @@ impl<'a> Item<'a> { fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { Item { keyword: "", - abi: format_abi(fm.abi, config.force_explicit_abi(), true), + abi: format_extern( + ast::Extern::from_abi(fm.abi), + config.force_explicit_abi(), + true, + ), vis: None, body: fm .items @@ -161,7 +164,7 @@ enum BodyElement<'a> { pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, - abi: abi::Abi, + ext: ast::Extern, is_async: Cow<'a, ast::IsAsync>, constness: ast::Constness, defaultness: ast::Defaultness, @@ -178,7 +181,7 @@ impl<'a> FnSig<'a> { FnSig { decl, generics, - abi: abi::Abi::Rust, + ext: ast::Extern::None, is_async: Cow::Owned(ast::IsAsync::NotAsync), constness: ast::Constness::NotConst, defaultness: ast::Defaultness::Final, @@ -188,7 +191,7 @@ impl<'a> FnSig<'a> { } pub(crate) fn from_method_sig( - method_sig: &'a ast::MethodSig, + method_sig: &'a ast::FnSig, generics: &'a ast::Generics, ) -> FnSig<'a> { FnSig { @@ -196,7 +199,7 @@ impl<'a> FnSig<'a> { is_async: Cow::Borrowed(&method_sig.header.asyncness.node), constness: method_sig.header.constness.node, defaultness: ast::Defaultness::Final, - abi: method_sig.header.abi, + ext: method_sig.header.ext, decl: &*method_sig.decl, generics, visibility: DEFAULT_VISIBILITY, @@ -210,24 +213,24 @@ impl<'a> FnSig<'a> { defaultness: ast::Defaultness, ) -> FnSig<'a> { match *fn_kind { - visit::FnKind::ItemFn(_, fn_header, visibility, _) => FnSig { - decl, - generics, - abi: fn_header.abi, - constness: fn_header.constness.node, - is_async: Cow::Borrowed(&fn_header.asyncness.node), - defaultness, - unsafety: fn_header.unsafety, - visibility: visibility.clone(), - }, - visit::FnKind::Method(_, method_sig, vis, _) => { - let mut fn_sig = FnSig::from_method_sig(method_sig, generics); - fn_sig.defaultness = defaultness; - if let Some(vis) = vis { + visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt { + visit::FnCtxt::Assoc(..) => { + let mut fn_sig = FnSig::from_method_sig(fn_sig, generics); + fn_sig.defaultness = defaultness; fn_sig.visibility = vis.clone(); + fn_sig } - fn_sig - } + _ => FnSig { + decl, + generics, + ext: fn_sig.header.ext, + constness: fn_sig.header.constness.node, + is_async: Cow::Borrowed(&fn_sig.header.asyncness.node), + defaultness, + unsafety: fn_sig.header.unsafety, + visibility: vis.clone(), + }, + }, _ => unreachable!(), } } @@ -240,8 +243,8 @@ impl<'a> FnSig<'a> { result.push_str(format_constness(self.constness)); result.push_str(format_async(&self.is_async)); result.push_str(format_unsafety(self.unsafety)); - result.push_str(&format_abi( - self.abi, + result.push_str(&format_extern( + self.ext, context.config.force_explicit_abi(), false, )); @@ -327,7 +330,7 @@ impl<'a> FmtVisitor<'a> { &mut self, indent: Indent, ident: ast::Ident, - sig: &ast::MethodSig, + sig: &ast::FnSig, generics: &ast::Generics, span: Span, ) -> Option { @@ -575,7 +578,7 @@ impl<'a> FmtVisitor<'a> { combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false) } - fn visit_impl_items(&mut self, items: &[ast::ImplItem]) { + fn visit_impl_items(&mut self, items: &[ptr::P]) { if self.get_context().config.reorder_impl_items() { // Create visitor for each items, then reorder them. let mut buffer = vec![]; @@ -584,27 +587,72 @@ impl<'a> FmtVisitor<'a> { buffer.push((self.buffer.clone(), item.clone())); self.buffer.clear(); } + + fn is_type(ty: &Option>) -> bool { + match ty { + None => true, + Some(lty) => match lty.kind.opaque_top_hack() { + None => true, + Some(_) => false, + }, + } + } + + fn is_opaque(ty: &Option>) -> bool { + match ty { + None => false, + Some(lty) => match lty.kind.opaque_top_hack() { + None => false, + Some(_) => true, + }, + } + } + + fn both_type( + a: &Option>, + b: &Option>, + ) -> bool { + is_type(a) && is_type(b) + } + + fn both_opaque( + a: &Option>, + b: &Option>, + ) -> bool { + is_opaque(a) && is_opaque(b) + } + + // In rustc-ap-v638 the `OpaqueTy` AssocItemKind variant was removed but + // we still need to differentiate to maintain sorting order. + // type -> opaque -> const -> macro -> method - use crate::ast::ImplItemKind::*; - fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { + use crate::ast::AssocItemKind::*; + fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool { match (a, b) { - (TyAlias(..), TyAlias(..)) - | (Const(..), Const(..)) - | (OpaqueTy(..), OpaqueTy(..)) => false, + (TyAlias(_, ref lty), TyAlias(_, ref rty)) + if both_type(lty, rty) || both_opaque(lty, rty) => + { + false + } + (Const(..), Const(..)) => false, _ => true, } } buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) { - (TyAlias(..), TyAlias(..)) - | (Const(..), Const(..)) - | (Macro(..), Macro(..)) - | (OpaqueTy(..), OpaqueTy(..)) => a.ident.as_str().cmp(&b.ident.as_str()), - (Method(..), Method(..)) => a.span.lo().cmp(&b.span.lo()), + (TyAlias(_, ref lty), TyAlias(_, ref rty)) + if both_type(lty, rty) || both_opaque(lty, rty) => + { + a.ident.as_str().cmp(&b.ident.as_str()) + } + (Const(..), Const(..)) | (Macro(..), Macro(..)) => { + a.ident.as_str().cmp(&b.ident.as_str()) + } + (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()), + (TyAlias(_, ref ty), _) if is_type(ty) => Ordering::Less, + (_, TyAlias(_, ref ty)) if is_type(ty) => Ordering::Greater, (TyAlias(..), _) => Ordering::Less, (_, TyAlias(..)) => Ordering::Greater, - (OpaqueTy(..), _) => Ordering::Less, - (_, OpaqueTy(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, (_, Const(..)) => Ordering::Greater, (Macro(..), _) => Ordering::Less, @@ -638,7 +686,13 @@ pub(crate) fn format_impl( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.kind { + if let ast::ItemKind::Impl { + ref generics, + ref self_ty, + ref items, + .. + } = item.kind + { let mut result = String::with_capacity(128); let ref_and_type = format_impl_ref_and_type(context, item, offset)?; let sep = offset.to_string_with_newline(context.config); @@ -695,7 +749,7 @@ pub(crate) fn format_impl( } } - if is_impl_single_line(context, items, &result, &where_clause_str, item)? { + if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? { result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { // if the where_clause contains extra comments AND @@ -764,7 +818,7 @@ pub(crate) fn format_impl( fn is_impl_single_line( context: &RewriteContext<'_>, - items: &[ast::ImplItem], + items: &[ptr::P], result: &str, where_clause_str: &str, item: &ast::Item, @@ -786,15 +840,15 @@ fn format_impl_ref_and_type( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl( + if let ast::ItemKind::Impl { unsafety, polarity, defaultness, ref generics, - ref trait_ref, + of_trait: ref trait_ref, ref self_ty, - _, - ) = item.kind + .. + } = item.kind { let mut result = String::with_capacity(128); @@ -1662,9 +1716,7 @@ impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { let (prefix, ty, mutability, expr) = match item.kind { ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), - ast::ItemKind::Const(ref ty, ref expr) => { - ("const", ty, ast::Mutability::Immutable, expr) - } + ast::ItemKind::Const(ref ty, ref expr) => ("const", ty, ast::Mutability::Not, expr), _ => unreachable!(), }; StaticParts { @@ -1679,9 +1731,9 @@ impl<'a> StaticParts<'a> { } } - pub(crate) fn from_trait_item(ti: &'a ast::TraitItem) -> Self { + pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { let (ty, expr_opt) = match ti.kind { - ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), + ast::AssocItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), _ => unreachable!(), }; StaticParts { @@ -1689,16 +1741,16 @@ impl<'a> StaticParts<'a> { vis: &DEFAULT_VISIBILITY, ident: ti.ident, ty, - mutability: ast::Mutability::Immutable, + mutability: ast::Mutability::Not, expr_opt: expr_opt.as_ref(), defaultness: None, span: ti.span, } } - pub(crate) fn from_impl_item(ii: &'a ast::ImplItem) -> Self { + pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { let (ty, expr) = match ii.kind { - ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr), + ast::AssocItemKind::Const(ref ty, ref expr) => (ty, expr), _ => unreachable!(), }; StaticParts { @@ -1706,8 +1758,8 @@ impl<'a> StaticParts<'a> { vis: &ii.vis, ident: ii.ident, ty, - mutability: ast::Mutability::Immutable, - expr_opt: Some(expr), + mutability: ast::Mutability::Not, + expr_opt: expr.as_ref(), defaultness: Some(ii.defaultness), span: ii.span, } @@ -3031,11 +3083,11 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.kind { - ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => rewrite_fn_base( + ast::ForeignItemKind::Fn(ref fn_sig, ref generics, _) => rewrite_fn_base( context, shape.indent, self.ident, - &FnSig::new(fn_decl, generics, self.vis.clone()), + &FnSig::new(&fn_sig.decl, generics, self.vis.clone()), span, FnBraceStyle::None, ) @@ -3101,7 +3153,7 @@ fn rewrite_attrs( let allow_extend = if attrs.len() == 1 { let line_len = attrs_str.len() + 1 + item_str.len(); - !attrs.first().unwrap().is_sugared_doc + !attrs.first().unwrap().is_doc_comment() && context.config.inline_attribute_width() >= line_len } else { false diff --git a/src/lib.rs b/src/lib.rs index 31df6b1c72c..f0783b2ca36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,8 @@ use std::rc::Rc; use failure::Fail; use ignore; -use syntax::{ast, parse::DirectoryOwnership}; +use rustc_parse::DirectoryOwnership; +use syntax::ast; use crate::comment::LineClasses; use crate::emitter::Emitter; diff --git a/src/lists.rs b/src/lists.rs index 077d08cb4e4..96a10924e25 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -3,7 +3,7 @@ use std::cmp; use std::iter::Peekable; -use syntax::source_map::BytePos; +use rustc_span::BytePos; use crate::comment::{find_comment_end, rewrite_comment, FindUncommented}; use crate::config::lists::*; diff --git a/src/macros.rs b/src/macros.rs index 8f509dd12c8..dea056928d9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -12,16 +12,12 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; -use syntax::parse::new_parser_from_tts; -use syntax::parse::parser::Parser; -use syntax::parse::token::{BinOpToken, DelimToken, Token, TokenKind}; -use syntax::print::pprust; -use syntax::source_map::{BytePos, Span}; -use syntax::symbol::kw; +use rustc_ast_pretty::pprust; +use rustc_parse::{new_parser_from_tts, parser::Parser}; +use rustc_span::{symbol::kw, BytePos, Span, Symbol, DUMMY_SP}; +use syntax::token::{BinOpToken, DelimToken, Token, TokenKind}; use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; -use syntax::ThinVec; -use syntax::{ast, parse, ptr}; -use syntax_pos::{Symbol, DUMMY_SP}; +use syntax::{ast, ptr}; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, @@ -85,7 +81,7 @@ impl Rewrite for MacroArg { MacroArg::Ty(ref ty) => ty.rewrite(context, shape), MacroArg::Pat(ref pat) => pat.rewrite(context, shape), MacroArg::Item(ref item) => item.rewrite(context, shape), - MacroArg::Keyword(ident, _) => Some(ident.to_string()), + MacroArg::Keyword(ident, _) => Some(ident.name.to_string()), } } } @@ -114,23 +110,23 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { parse_macro_arg!( Expr, - |parser: &mut parse::parser::Parser<'b>| parser.parse_expr(), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_expr(), |x: ptr::P| Some(x) ); parse_macro_arg!( Ty, - |parser: &mut parse::parser::Parser<'b>| parser.parse_ty(), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_ty(), |x: ptr::P| Some(x) ); parse_macro_arg!( Pat, - |parser: &mut parse::parser::Parser<'b>| parser.parse_pat(None), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat(None), |x: ptr::P| Some(x) ); // `parse_item` returns `Option>`. parse_macro_arg!( Item, - |parser: &mut parse::parser::Parser<'b>| parser.parse_item(), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(), |x: Option>| x ); @@ -147,7 +143,7 @@ fn rewrite_macro_name( // Avoid using pretty-printer in the common case. format!("{}!", rewrite_ident(context, path.segments[0].ident)) } else { - format!("{}!", path) + format!("{}!", pprust::path_to_string(path)) }; match extra_ident { Some(ident) if ident.name != kw::Invalid => format!("{} {}", name, ident), @@ -267,8 +263,8 @@ fn rewrite_macro_inner( original_style }; - let ts: TokenStream = mac.stream(); - let has_comment = contains_comment(context.snippet(mac.span)); + let ts = mac.args.inner_tokens(); + let has_comment = contains_comment(context.snippet(mac.span())); if ts.is_empty() && !has_comment { return match style { DelimToken::Paren if position == MacroPosition::Item => { @@ -302,7 +298,7 @@ fn rewrite_macro_inner( } else if let Some(arg) = parse_macro_arg(&mut parser) { arg_vec.push(arg); } else { - return return_macro_parse_failure_fallback(context, shape.indent, mac.span); + return return_macro_parse_failure_fallback(context, shape.indent, mac.span()); } match parser.token.kind { @@ -326,16 +322,16 @@ fn rewrite_macro_inner( return return_macro_parse_failure_fallback( context, shape.indent, - mac.span, + mac.span(), ); } } } } - return return_macro_parse_failure_fallback(context, shape.indent, mac.span); + return return_macro_parse_failure_fallback(context, shape.indent, mac.span()); } _ if arg_vec.last().map_or(false, MacroArg::is_item) => continue, - _ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span), + _ => return return_macro_parse_failure_fallback(context, shape.indent, mac.span()), } parser.bump(); @@ -355,7 +351,7 @@ fn rewrite_macro_inner( shape, style, position, - mac.span, + mac.span(), ); } @@ -372,7 +368,7 @@ fn rewrite_macro_inner( ¯o_name, arg_vec.iter(), shape, - mac.span, + mac.span(), context.config.width_heuristics().fn_call_width, if trailing_comma { Some(SeparatorTactic::Always) @@ -409,7 +405,7 @@ fn rewrite_macro_inner( let rewrite = rewrite_array( macro_name, arg_vec.iter(), - mac.span, + mac.span(), context, shape, force_trailing_comma, @@ -427,7 +423,7 @@ fn rewrite_macro_inner( // For macro invocations with braces, always put a space between // the `macro_name!` and `{ /* macro_body */ }` but skip modifying // anything in between the braces (for now). - let snippet = context.snippet(mac.span).trim_start_matches(|c| c != '{'); + let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{'); match trim_left_preserve_layout(snippet, shape.indent, &context.config) { Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)), None => Some(format!("{} {}", macro_name, snippet)), @@ -492,7 +488,8 @@ pub(crate) fn rewrite_macro_def( return snippet; } - let mut parser = MacroParser::new(def.stream().into_trees()); + let ts = def.body.inner_tokens(); + let mut parser = MacroParser::new(ts.into_trees()); let parsed_def = match parser.parse() { Some(def) => def, None => return snippet, @@ -1190,23 +1187,24 @@ fn next_space(tok: &TokenKind) -> SpaceState { /// when the macro is not an instance of `try!` (or parsing the inner expression /// failed). pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { - if &mac.path.to_string() == "try" { - let ts: TokenStream = mac.tts.clone(); + let path = &pprust::path_to_string(&mac.path); + if path == "try" || path == "r#try" { + let ts = mac.args.inner_tokens(); let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); Some(ast::Expr { id: ast::NodeId::root(), // dummy value kind: ast::ExprKind::Try(parser.parse_expr().ok()?), - span: mac.span, // incorrect span, but shouldn't matter too much - attrs: ThinVec::new(), + span: mac.span(), // incorrect span, but shouldn't matter too much + attrs: ast::AttrVec::new(), }) } else { None } } -fn macro_style(mac: &ast::Mac, context: &RewriteContext<'_>) -> DelimToken { - let snippet = context.snippet(mac.span); +pub(crate) fn macro_style(mac: &ast::Mac, context: &RewriteContext<'_>) -> DelimToken { + let snippet = context.snippet(mac.span()); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value()); @@ -1454,7 +1452,10 @@ fn format_lazy_static( while parser.token.kind != TokenKind::Eof { // Parse a `lazy_static!` item. - let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false)); + let vis = crate::utils::format_visibility( + context, + &parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No), + ); parser.eat_keyword(kw::Static); parser.eat_keyword(kw::Ref); let id = parse_or!(parse_ident); diff --git a/src/matches.rs b/src/matches.rs index fcfb8055f01..954db40ae52 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,7 +2,7 @@ use std::iter::repeat; -use syntax::source_map::{BytePos, Span}; +use rustc_span::{BytePos, Span}; use syntax::{ast, ptr}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; @@ -565,7 +565,7 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { | ast::ExprKind::Mac(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => true, - ast::ExprKind::AddrOf(_, ref expr) + ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Unary(_, ref expr) diff --git a/src/missed_spans.rs b/src/missed_spans.rs index a957d3b3e30..99595436f89 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -1,4 +1,4 @@ -use syntax::source_map::{BytePos, Pos, Span}; +use rustc_span::{BytePos, Pos, Span}; use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileLines; diff --git a/src/modules.rs b/src/modules.rs index 568faa7194b..92db42de13f 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -2,15 +2,14 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; +use rustc_errors::{Diagnostic, PResult}; +use rustc_parse::{new_sub_parser_from_file, parser, DirectoryOwnership}; +use rustc_session::parse::ParseSess; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{source_map, Span, DUMMY_SP}; use syntax::ast; -use syntax::attr; -use syntax::parse::{ - new_sub_parser_from_file, parser, token::TokenKind, DirectoryOwnership, PResult, ParseSess, -}; -use syntax::source_map::{self, Span}; -use syntax::symbol::sym; +use syntax::token::TokenKind; use syntax::visit::Visitor; -use syntax_pos::{self, symbol::Symbol, DUMMY_SP}; use crate::attr::MetaVisitor; use crate::config::FileName; @@ -36,8 +35,8 @@ struct Directory { } impl<'a> Directory { - fn to_syntax_directory(&'a self) -> syntax::parse::Directory<'a> { - syntax::parse::Directory { + fn to_syntax_directory(&'a self) -> rustc_parse::Directory<'a> { + rustc_parse::Directory { path: Cow::Borrowed(&self.path), ownership: self.ownership.clone(), } @@ -173,7 +172,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } else { // An internal module (`mod foo { /* ... */ }`); if let Some(path) = find_path_value(&item.attrs) { - let path = Path::new(&path.as_str()).to_path_buf(); + let path = Path::new(&*path.as_str()).to_path_buf(); Ok(Some(SubModKind::InternalWithPath(path))) } else { Ok(Some(SubModKind::Internal(item))) @@ -273,7 +272,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod(_) => None, + DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, }; match parser::Parser::default_submod_path( mod_name, @@ -305,7 +304,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn push_inline_mod_directory(&mut self, id: ast::Ident, attrs: &[ast::Attribute]) { if let Some(path) = find_path_value(attrs) { - self.directory.path.push(&path.as_str()); + self.directory.path.push(&*path.as_str()); self.directory.ownership = DirectoryOwnership::Owned { relative: None }; } else { // We have to push on the current module name in the case of relative @@ -317,10 +316,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership { if let Some(ident) = relative.take() { // remove the relative offset - self.directory.path.push(ident.as_str()); + self.directory.path.push(&*ident.as_str()); } } - self.directory.path.push(&id.as_str()); + self.directory.path.push(&*id.as_str()); } } @@ -357,7 +356,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if !actual_path.exists() { continue; } - let file_name = syntax_pos::FileName::Real(actual_path.clone()); + let file_name = rustc_span::FileName::Real(actual_path.clone()); if self .parse_sess .source_map() @@ -442,7 +441,11 @@ fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Ve } TokenKind::DocComment(s) => { // we need to get the position of this token before we bump. - let attr = attr::mk_sugared_doc_attr(s, parser.token.span); + let attr = syntax::attr::mk_doc_comment( + syntax::util::comments::doc_comment_style(&s.as_str()), + s, + parser.token.span, + ); if attr.style == ast::AttrStyle::Inner { attrs.push(attr); parser.bump(); diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index e9223ce9644..4ef1daf7475 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -1,9 +1,9 @@ +use rustc_parse::{stream_to_parser_with_base_dir, Directory}; +use rustc_session::parse::ParseSess; +use rustc_span::{symbol::kw, Symbol}; use syntax::ast; -use syntax::parse::token::{DelimToken, TokenKind}; -use syntax::parse::{stream_to_parser_with_base_dir, Directory, ParseSess}; -use syntax::symbol::kw; +use syntax::token::{DelimToken, TokenKind}; use syntax::visit::Visitor; -use syntax_pos::Symbol; use crate::attr::MetaVisitor; @@ -65,8 +65,9 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } }; + let ts = mac.args.inner_tokens(); let mut parser = - stream_to_parser_with_base_dir(self.parse_sess, mac.tts.clone(), self.base_dir.clone()); + stream_to_parser_with_base_dir(self.parse_sess, ts.clone(), self.base_dir.clone()); parser.cfg_mods = false; let mut process_if_cfg = true; diff --git a/src/overflow.rs b/src/overflow.rs index 3b85c0b8e57..0ef1db20fa1 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -3,8 +3,8 @@ use std::cmp::min; use itertools::Itertools; -use syntax::parse::token::DelimToken; -use syntax::source_map::Span; +use rustc_span::Span; +use syntax::token::DelimToken; use syntax::{ast, ptr}; use crate::closures; diff --git a/src/patterns.rs b/src/patterns.rs index baa39dbbce6..1ef3bd5337b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,6 +1,6 @@ +use rustc_span::{BytePos, Span}; use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; use syntax::ptr; -use syntax::source_map::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; @@ -179,26 +179,29 @@ impl Rewrite for Pat { None } } - PatKind::Range(ref lhs, ref rhs, ref end_kind) => { - let infix = match end_kind.node { - RangeEnd::Included(RangeSyntax::DotDotDot) => "...", - RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", - RangeEnd::Excluded => "..", - }; - let infix = if context.config.spaces_around_ranges() { - format!(" {} ", infix) - } else { - infix.to_owned() - }; - rewrite_pair( - &**lhs, - &**rhs, - PairParts::infix(&infix), - context, - shape, - SeparatorPlace::Front, - ) - } + PatKind::Range(ref lhs, ref rhs, ref end_kind) => match (lhs, rhs) { + (Some(lhs), Some(rhs)) => { + let infix = match end_kind.node { + RangeEnd::Included(RangeSyntax::DotDotDot) => "...", + RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", + RangeEnd::Excluded => "..", + }; + let infix = if context.config.spaces_around_ranges() { + format!(" {} ", infix) + } else { + infix.to_owned() + }; + rewrite_pair( + &**lhs, + &**rhs, + PairParts::infix(&infix), + context, + shape, + SeparatorPlace::Front, + ) + } + (_, _) => unimplemented!(), + }, PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, shape) diff --git a/src/reorder.rs b/src/reorder.rs index 5a6a45118b9..4b607812c00 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -8,7 +8,8 @@ use std::cmp::{Ord, Ordering}; -use syntax::{ast, attr, source_map::Span, symbol::sym}; +use rustc_span::{symbol::sym, Span}; +use syntax::{ast, attr}; use crate::config::Config; use crate::imports::{merge_use_trees, UseTree}; @@ -30,10 +31,8 @@ fn compare_items(a: &ast::Item, b: &ast::Item) -> Ordering { (&ast::ItemKind::ExternCrate(ref a_name), &ast::ItemKind::ExternCrate(ref b_name)) => { // `extern crate foo as bar;` // ^^^ Comparing this. - let a_orig_name = - a_name.map_or_else(|| a.ident.as_str(), syntax_pos::symbol::Symbol::as_str); - let b_orig_name = - b_name.map_or_else(|| b.ident.as_str(), syntax_pos::symbol::Symbol::as_str); + let a_orig_name = a_name.map_or_else(|| a.ident.as_str(), rustc_span::Symbol::as_str); + let b_orig_name = b_name.map_or_else(|| b.ident.as_str(), rustc_span::Symbol::as_str); let result = a_orig_name.cmp(&b_orig_name); if result != Ordering::Equal { return result; diff --git a/src/rewrite.rs b/src/rewrite.rs index 602512e87ce..fbae4bc7122 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -3,9 +3,9 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use syntax::parse::ParseSess; +use rustc_session::parse::ParseSess; +use rustc_span::{source_map::SourceMap, Span}; use syntax::ptr; -use syntax::source_map::{SourceMap, Span}; use crate::config::{Config, IndentStyle}; use crate::shape::Shape; diff --git a/src/skip.rs b/src/skip.rs index 6b4e04a7173..4972eb8c778 100644 --- a/src/skip.rs +++ b/src/skip.rs @@ -1,5 +1,6 @@ //! Module that contains skip related stuffs. +use rustc_ast_pretty::pprust; use syntax::ast; /// Take care of skip name stack. You can update it by attributes slice or @@ -45,7 +46,7 @@ pub(crate) fn is_skip_attr(segments: &[ast::PathSegment]) -> bool { segments[1].ident.to_string() == SKIP && ["macros", "attributes"] .iter() - .any(|&n| n == &segments[2].ident.name.as_str()) + .any(|&n| n == &pprust::path_segment_to_string(&segments[2])) } _ => false, } @@ -57,8 +58,10 @@ fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec { for attr in attrs { // syntax::ast::Path is implemented partialEq // but it is designed for segments.len() == 1 - if format!("{}", attr.path) != path { - continue; + if let ast::AttrKind::Normal(attr_item) = &attr.kind { + if pprust::path_to_string(&attr_item.path) != path { + continue; + } } if let Some(list) = attr.meta_item_list() { diff --git a/src/source_file.rs b/src/source_file.rs index b6764ee7464..4cb894e55b8 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -2,7 +2,7 @@ use std::fs; use std::io::{self, Write}; use std::path::Path; -use syntax::source_map::SourceMap; +use rustc_span::source_map::SourceMap; use crate::config::FileName; use crate::emitter::{self, Emitter}; @@ -65,11 +65,11 @@ where } } - impl From<&FileName> for syntax_pos::FileName { - fn from(filename: &FileName) -> syntax_pos::FileName { + impl From<&FileName> for rustc_span::FileName { + fn from(filename: &FileName) -> rustc_span::FileName { match filename { - FileName::Real(path) => syntax_pos::FileName::Real(path.to_owned()), - FileName::Stdin => syntax_pos::FileName::Custom("stdin".to_owned()), + FileName::Real(path) => rustc_span::FileName::Real(path.to_owned()), + FileName::Stdin => rustc_span::FileName::Custom("stdin".to_owned()), } } } diff --git a/src/source_map.rs b/src/source_map.rs index b1ab83e7aba..c3a549d3b84 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -1,7 +1,7 @@ //! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. -use syntax::source_map::{BytePos, SourceMap, Span}; +use rustc_span::{source_map::SourceMap, BytePos, Span}; use crate::comment::FindUncommented; use crate::config::file_lines::LineRange; diff --git a/src/spanned.rs b/src/spanned.rs index 8872e6df2da..b2a70dd5cec 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -1,9 +1,7 @@ use std::cmp::max; -use syntax::{ - ast, ptr, - source_map::{self, Span}, -}; +use rustc_span::{source_map, Span}; +use syntax::{ast, ptr}; use crate::macros::MacroArg; use crate::utils::{mk_sp, outer_attributes}; @@ -53,13 +51,12 @@ macro_rules! implement_spanned { } // Implement `Spanned` for structs with `attrs` field. +implement_spanned!(ast::AssocItem); implement_spanned!(ast::Expr); implement_spanned!(ast::Field); implement_spanned!(ast::ForeignItem); implement_spanned!(ast::Item); implement_spanned!(ast::Local); -implement_spanned!(ast::TraitItem); -implement_spanned!(ast::ImplItem); impl Spanned for ast::Stmt { fn span(&self) -> Span { diff --git a/src/stmt.rs b/src/stmt.rs index a7aa6de0b13..df22a5dfd02 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -1,5 +1,5 @@ +use rustc_span::Span; use syntax::ast; -use syntax_pos::Span; use crate::comment::recover_comment_removed; use crate::config::Version; diff --git a/src/types.rs b/src/types.rs index 3efe80fdb81..efc85efc5c4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,9 +1,8 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; +use rustc_span::{symbol::kw, BytePos, Span}; use syntax::ast::{self, FunctionRetTy, Mutability}; -use syntax::source_map::{self, BytePos, Span}; -use syntax::symbol::kw; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; @@ -19,7 +18,7 @@ use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ - colon_spaces, extra_offset, first_line_width, format_abi, format_mutability, + colon_spaces, extra_offset, first_line_width, format_extern, format_mutability, last_line_extendable, last_line_width, mk_sp, rewrite_ident, }; @@ -275,13 +274,9 @@ fn rewrite_segment( result.push_str(&generics_str) } ast::GenericArgs::Parenthesized(ref data) => { - let output = match data.output { - Some(ref ty) => FunctionRetTy::Ty(ty.clone()), - None => FunctionRetTy::Default(source_map::DUMMY_SP), - }; result.push_str(&format_function_type( data.inputs.iter().map(|x| &**x), - &output, + &data.output, false, data.span, context, @@ -528,6 +523,7 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::Maybe => poly_trait_ref .rewrite(context, shape.offset_left(1)?) .map(|s| format!("?{}", s)), + _ => unimplemented!(), }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } @@ -634,8 +630,8 @@ impl Rewrite for ast::Ty { } ast::TyKind::Ptr(ref mt) => { let prefix = match mt.mutbl { - Mutability::Mutable => "*mut ", - Mutability::Immutable => "*const ", + Mutability::Mut => "*mut ", + Mutability::Not => "*const ", }; rewrite_unary_prefix(context, prefix, &*mt.ty, shape) @@ -783,8 +779,8 @@ fn rewrite_bare_fn( result.push_str(crate::utils::format_unsafety(bare_fn.unsafety)); - result.push_str(&format_abi( - bare_fn.abi, + result.push_str(&format_extern( + bare_fn.ext, context.config.force_explicit_abi(), false, )); diff --git a/src/utils.rs b/src/utils.rs index d01a0ff73ba..e0971c7d1bf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,14 +1,13 @@ use std::borrow::Cow; +use rustc_ast_pretty::pprust; +use rustc_span::{sym, BytePos, ExpnId, Span, Symbol, SyntaxContext}; use rustc_target::spec::abi; use syntax::ast::{ self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NodeId, Path, Visibility, VisibilityKind, }; use syntax::ptr; -use syntax::source_map::{BytePos, Span, SyntaxContext}; -use syntax::symbol::{sym, Symbol}; -use syntax_pos::ExpnId; use unicode_width::UnicodeWidthStr; use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; @@ -44,7 +43,7 @@ pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { ( VisibilityKind::Restricted { path: p, .. }, VisibilityKind::Restricted { path: q, .. }, - ) => p.to_string() == q.to_string(), + ) => pprust::path_to_string(p) == pprust::path_to_string(q), (VisibilityKind::Public, VisibilityKind::Public) | (VisibilityKind::Inherited, VisibilityKind::Inherited) | ( @@ -129,13 +128,25 @@ pub(crate) fn format_auto(is_auto: ast::IsAuto) -> &'static str { #[inline] pub(crate) fn format_mutability(mutability: ast::Mutability) -> &'static str { match mutability { - ast::Mutability::Mutable => "mut ", - ast::Mutability::Immutable => "", + ast::Mutability::Mut => "mut ", + ast::Mutability::Not => "", } } #[inline] -pub(crate) fn format_abi(abi: abi::Abi, explicit_abi: bool, is_mod: bool) -> Cow<'static, str> { +pub(crate) fn format_extern( + ext: ast::Extern, + explicit_abi: bool, + is_mod: bool, +) -> Cow<'static, str> { + let abi = match ext { + ast::Extern::None => abi::Abi::Rust, + ast::Extern::Implicit => abi::Abi::C, + ast::Extern::Explicit(abi) => { + abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or(abi::Abi::Rust) + } + }; + if abi == abi::Abi::Rust && !is_mod { Cow::from("") } else if abi == abi::Abi::C && !explicit_abi { @@ -243,8 +254,9 @@ pub(crate) fn last_line_extendable(s: &str) -> bool { fn is_skip(meta_item: &MetaItem) -> bool { match meta_item.kind { MetaItemKind::Word => { - let path_str = meta_item.path.to_string(); - path_str == skip_annotation().as_str() || path_str == depr_skip_annotation().as_str() + let path_str = pprust::path_to_string(&meta_item.path); + path_str == &*skip_annotation().as_str() + || path_str == &*depr_skip_annotation().as_str() } MetaItemKind::List(ref l) => { meta_item.check_name(sym::cfg_attr) && l.len() == 2 && is_skip_nested(&l[1]) @@ -420,7 +432,7 @@ pub(crate) fn left_most_sub_expr(e: &ast::Expr) -> &ast::Expr { | ast::ExprKind::Binary(_, ref e, _) | ast::ExprKind::Cast(ref e, _) | ast::ExprKind::Type(ref e, _) - | ast::ExprKind::Assign(ref e, _) + | ast::ExprKind::Assign(ref e, _, _) | ast::ExprKind::AssignOp(_, ref e, _) | ast::ExprKind::Field(ref e, _) | ast::ExprKind::Index(ref e, _) diff --git a/src/vertical.rs b/src/vertical.rs index 59b03789fb5..b932b0afa17 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -3,8 +3,8 @@ use std::cmp; use itertools::Itertools; +use rustc_span::{BytePos, Span}; use syntax::ast; -use syntax::source_map::{BytePos, Span}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; diff --git a/src/visitor.rs b/src/visitor.rs index 15490798a6e..c6ae3b3be1e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,8 +1,12 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use syntax::parse::ParseSess; -use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; +use rustc_session::parse::ParseSess; +use rustc_span::{ + source_map::{self, SourceMap}, + BytePos, Pos, Span, +}; +use syntax::token::DelimToken; use syntax::{ast, visit}; use crate::attr::*; @@ -16,7 +20,7 @@ use crate::items::{ rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, }; -use crate::macros::{rewrite_macro, rewrite_macro_def, MacroPosition}; +use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::skip::{is_skip_attr, SkipContext}; @@ -35,6 +39,8 @@ pub(crate) struct SnippetProvider<'a> { big_snippet: &'a str, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, + /// A end position of the file that this snippet lives. + end_pos: usize, } impl<'a> SnippetProvider<'a> { @@ -44,13 +50,19 @@ impl<'a> SnippetProvider<'a> { Some(&self.big_snippet[start_index..end_index]) } - pub(crate) fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { + pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: &'a str) -> Self { let start_pos = start_pos.to_usize(); + let end_pos = end_pos.to_usize(); SnippetProvider { big_snippet, start_pos, + end_pos, } } + + pub(crate) fn end_pos(&self) -> BytePos { + BytePos::from_usize(self.end_pos) + } } pub(crate) struct FmtVisitor<'a> { @@ -348,7 +360,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let indent = self.block_indent; let block; let rewrite = match fk { - visit::FnKind::ItemFn(ident, _, _, b) | visit::FnKind::Method(ident, _, _, b) => { + visit::FnKind::Fn(_, ident, _, _, Some(ref b)) => { block = b; self.rewrite_fn_before_block( indent, @@ -357,7 +369,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { mk_sp(s.lo(), b.span.lo()), ) } - visit::FnKind::Closure(_) => unreachable!(), + _ => unreachable!(), }; if let Some((fn_str, fn_brace_style)) = rewrite { @@ -441,7 +453,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if should_visit_node_again { match item.kind { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), - ast::ItemKind::Impl(..) => { + ast::ItemKind::Impl { .. } => { let block_indent = self.block_indent; let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent)); self.push_rewrite(item.span, rw); @@ -495,39 +507,51 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::Fn(ref decl, ref fn_header, ref generics, ref body) => { + ast::ItemKind::Fn(ref fn_signature, ref generics, ref body) => { let inner_attrs = inner_attributes(&item.attrs); + let fn_ctxt = match fn_signature.header.ext { + ast::Extern::None => visit::FnCtxt::Free, + _ => visit::FnCtxt::Foreign, + }; self.visit_fn( - visit::FnKind::ItemFn(item.ident, fn_header, &item.vis, body), + visit::FnKind::Fn( + fn_ctxt, + item.ident, + &fn_signature, + &item.vis, + body.as_deref(), + ), generics, - decl, + &fn_signature.decl, item.span, ast::Defaultness::Final, Some(&inner_attrs), ) } - ast::ItemKind::TyAlias(ref ty, ref generics) => { - let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, - item.ident, - ty, - generics, - &item.vis, - ); - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::OpaqueTy(ref generic_bounds, ref generics) => { - let rewrite = rewrite_opaque_type( - &self.get_context(), - self.block_indent, - item.ident, - generic_bounds, - generics, - &item.vis, - ); - self.push_rewrite(item.span, rewrite); - } + ast::ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() { + None => { + let rewrite = rewrite_type_alias( + &self.get_context(), + self.block_indent, + item.ident, + ty, + generics, + &item.vis, + ); + self.push_rewrite(item.span, rewrite); + } + Some(generic_bounds) => { + let rewrite = rewrite_opaque_type( + &self.get_context(), + self.block_indent, + item.ident, + generic_bounds, + generics, + &item.vis, + ); + self.push_rewrite(item.span, rewrite); + } + }, ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); self.push_rewrite(item.span, snippet); @@ -549,7 +573,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.skip_context = skip_context_saved; } - pub(crate) fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { skip_out_of_file_lines_range_visitor!(self, ti.span); if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) { @@ -558,17 +582,19 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } match ti.kind { - ast::TraitItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), - ast::TraitItemKind::Method(ref sig, None) => { + ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), + ast::AssocItemKind::Fn(ref sig, None) => { let indent = self.block_indent; let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); self.push_rewrite(ti.span, rewrite); } - ast::TraitItemKind::Method(ref sig, Some(ref body)) => { + ast::AssocItemKind::Fn(ref sig, Some(ref body)) => { let inner_attrs = inner_attributes(&ti.attrs); + let vis = rustc_span::source_map::dummy_spanned(ast::VisibilityKind::Inherited); + let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); self.visit_fn( - visit::FnKind::Method(ti.ident, sig, None, body), + visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), &ti.generics, &sig.decl, ti.span, @@ -576,7 +602,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(&inner_attrs), ); } - ast::TraitItemKind::Type(ref generic_bounds, ref type_default) => { + ast::AssocItemKind::TyAlias(ref generic_bounds, ref type_default) => { let rewrite = rewrite_associated_type( ti.ident, type_default.as_ref(), @@ -587,25 +613,26 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(ti.span, rewrite); } - ast::TraitItemKind::Macro(ref mac) => { + ast::AssocItemKind::Macro(ref mac) => { self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); } } } - pub(crate) fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { skip_out_of_file_lines_range_visitor!(self, ii.span); if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) { - self.push_skipped_with_span(ii.attrs.as_slice(), ii.span(), ii.span()); + self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span); return; } match ii.kind { - ast::ImplItemKind::Method(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, Some(ref body)) => { let inner_attrs = inner_attributes(&ii.attrs); + let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl); self.visit_fn( - visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body), + visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)), &ii.generics, &sig.decl, ii.span, @@ -613,41 +640,73 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(&inner_attrs), ); } - ast::ImplItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::ImplItemKind::TyAlias(ref ty) => { - let rewrite = rewrite_associated_impl_type( - ii.ident, - ii.defaultness, - Some(ty), - &ii.generics, - &self.get_context(), - self.block_indent, - ); + ast::AssocItemKind::Fn(ref sig, None) => { + let indent = self.block_indent; + let rewrite = + self.rewrite_required_fn(indent, ii.ident, sig, &ii.generics, ii.span); self.push_rewrite(ii.span, rewrite); } - ast::ImplItemKind::OpaqueTy(ref generic_bounds) => { - let rewrite = rewrite_opaque_impl_type( - &self.get_context(), - ii.ident, - &ii.generics, - generic_bounds, - self.block_indent, - ); + ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), + ast::AssocItemKind::TyAlias(_, ref ty) => { + let rewrite_associated = || { + rewrite_associated_impl_type( + ii.ident, + ii.defaultness, + ty.as_ref(), + &ii.generics, + &self.get_context(), + self.block_indent, + ) + }; + let rewrite = match ty { + None => rewrite_associated(), + Some(ty) => match ty.kind.opaque_top_hack() { + Some(generic_bounds) => rewrite_opaque_impl_type( + &self.get_context(), + ii.ident, + &ii.generics, + generic_bounds, + self.block_indent, + ), + None => rewrite_associated(), + }, + }; self.push_rewrite(ii.span, rewrite); } - ast::ImplItemKind::Macro(ref mac) => { + ast::AssocItemKind::Macro(ref mac) => { self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); } } } fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { - skip_out_of_file_lines_range_visitor!(self, mac.span); + skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; let shape = self.shape().saturating_sub_width(1); let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); - self.push_rewrite(mac.span, rewrite); + // As of v638 of the rustc-ap-* crates, the associated span no longer includes + // the trailing semicolon. This determines the correct span to ensure scenarios + // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`) + // are formatted correctly. + let (span, rewrite) = match macro_style(mac, &self.get_context()) { + DelimToken::Bracket | DelimToken::Paren if MacroPosition::Item == pos => { + let search_span = mk_sp(mac.span().hi(), self.snippet_provider.end_pos()); + let hi = self.snippet_provider.span_before(search_span, ";"); + let target_span = mk_sp(mac.span().lo(), hi + BytePos(1)); + let rewrite = rewrite.map(|rw| { + if !rw.ends_with(";") { + format!("{};", rw) + } else { + rw + } + }); + (target_span, rewrite) + } + _ => (mac.span(), rewrite), + }; + + self.push_rewrite(span, rewrite); } pub(crate) fn push_str(&mut self, s: &str) { @@ -751,16 +810,23 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ErrorKind::DeprecatedAttr, )], ); - } else if self.is_unknown_rustfmt_attr(&attr.path.segments) { - let file_name = self.source_map.span_to_filename(attr.span).into(); - self.report.append( - file_name, - vec![FormattingError::from_span( - attr.span, - &self.source_map, - ErrorKind::BadAttr, - )], - ); + } else { + match &attr.kind { + ast::AttrKind::Normal(ref attribute_item) + if self.is_unknown_rustfmt_attr(&attribute_item.path.segments) => + { + let file_name = self.source_map.span_to_filename(attr.span).into(); + self.report.append( + file_name, + vec![FormattingError::from_span( + attr.span, + self.source_map, + ErrorKind::BadAttr, + )], + ); + } + _ => (), + } } } if contains_skip(attrs) { diff --git a/tests/source/issue-2916.rs b/tests/source/issue-2916.rs new file mode 100644 index 00000000000..ccb1f8486c5 --- /dev/null +++ b/tests/source/issue-2916.rs @@ -0,0 +1,2 @@ +a_macro!(name, +) ; diff --git a/tests/target/issue-2916.rs b/tests/target/issue-2916.rs index 5a6471ca863..fb07cc8065c 100644 --- a/tests/target/issue-2916.rs +++ b/tests/target/issue-2916.rs @@ -1,2 +1,2 @@ -a_macro!(name, +a_macro!(name, ); -- cgit 1.4.1-3-g733a5 From e72f307f15138a8bb4fd1ae9ef3256fe1fa9dd94 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 8 Feb 2020 22:47:48 -0600 Subject: fix: backport parse bug fix Backport the fix for the parser bug where the messages from fatal/non-recoverable parser errors were being silently eaten by rustfmt. --- src/formatting.rs | 251 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 215 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 0c273400695..bed87748253 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -715,37 +715,43 @@ fn parse_crate( struct SilentOnIgnoredFilesEmitter { ignore_path_set: Rc, source_map: Rc, - emitter: EmitterWriter, + emitter: Box, has_non_ignorable_parser_errors: bool, can_reset: Rc>, } +impl SilentOnIgnoredFilesEmitter { + fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { + self.has_non_ignorable_parser_errors = true; + *self.can_reset.borrow_mut() = false; + self.emitter.emit_diagnostic(db); + } +} + impl Emitter for SilentOnIgnoredFilesEmitter { fn source_map(&self) -> Option<&Lrc> { None } + fn emit_diagnostic(&mut self, db: &Diagnostic) { + if db.level == DiagnosticLevel::Fatal { + return self.handle_non_ignoreable_error(db); + } if let Some(primary_span) = &db.span.primary_span() { let file_name = self.source_map.span_to_filename(*primary_span); - match file_name { - rustc_span::FileName::Real(ref path) => { - if self - .ignore_path_set - .is_match(&FileName::Real(path.to_path_buf())) - { - if !self.has_non_ignorable_parser_errors { - *self.can_reset.borrow_mut() = true; - } - return; + if let rustc_span::FileName::Real(ref path) = file_name { + if self + .ignore_path_set + .is_match(&FileName::Real(path.to_path_buf())) + { + if !self.has_non_ignorable_parser_errors { + *self.can_reset.borrow_mut() = true; } + return; } - _ => (), }; } - - self.has_non_ignorable_parser_errors = true; - *self.can_reset.borrow_mut() = false; - self.emitter.emit_diagnostic(db); + self.handle_non_ignoreable_error(db); } } @@ -759,7 +765,7 @@ impl Emitter for SilentEmitter { fn emit_diagnostic(&mut self, _db: &Diagnostic) {} } -fn silent_emitter() -> Box { +fn silent_emitter() -> Box { Box::new(SilentEmitter {}) } @@ -769,36 +775,38 @@ fn make_parse_sess( ignore_path_set: Rc, can_reset: Rc>, ) -> ParseSess { - let tty_handler = if config.hide_parse_errors() { - let silent_emitter = silent_emitter(); - Handler::with_emitter(true, None, silent_emitter) + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; + ColorConfig::Never + }; - let emitter_writer = EmitterWriter::stderr( + let emitter = if config.hide_parse_errors() { + silent_emitter() + } else { + Box::new(EmitterWriter::stderr( color_cfg, Some(source_map.clone()), false, false, None, false, - ); - let emitter = Box::new(SilentOnIgnoredFilesEmitter { + )) + }; + let handler = Handler::with_emitter( + true, + None, + Box::new(SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, - ignore_path_set: ignore_path_set, - source_map: Rc::clone(&source_map), - emitter: emitter_writer, + source_map: source_map.clone(), + emitter, + ignore_path_set, can_reset, - }); - Handler::with_emitter(true, None, emitter) - }; + }), + ); - ParseSess::with_span_handler(tty_handler, source_map) + ParseSess::with_span_handler(handler, source_map) } fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) @@ -809,3 +817,174 @@ where f(); } } + +#[cfg(test)] +mod tests { + use super::*; + + mod emitter { + use super::*; + use crate::config::IgnoreList; + use crate::is_nightly_channel; + use crate::utils::mk_sp; + use rustc_span::{BytePos, FileName as SourceMapFileName, MultiSpan, DUMMY_SP}; + use std::path::{Path, PathBuf}; + + struct TestEmitter { + num_emitted_errors: Rc>, + } + + impl Emitter for TestEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } + fn emit_diagnostic(&mut self, _db: &Diagnostic) { + *self.num_emitted_errors.borrow_mut() += 1; + } + } + + fn build_diagnostic(level: DiagnosticLevel, span: Option) -> Diagnostic { + Diagnostic { + level, + code: None, + message: vec![], + children: vec![], + suggestions: vec![], + span: span.unwrap_or_else(MultiSpan::new), + sort_span: DUMMY_SP, + } + } + + fn build_emitter( + num_emitted_errors: Rc>, + can_reset: Rc>, + source_map: Option>, + ignore_list: Option, + ) -> SilentOnIgnoredFilesEmitter { + let emitter_writer = TestEmitter { num_emitted_errors }; + let source_map = + source_map.unwrap_or_else(|| Rc::new(SourceMap::new(FilePathMapping::empty()))); + let ignore_path_set = + Rc::new(IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap()); + SilentOnIgnoredFilesEmitter { + has_non_ignorable_parser_errors: false, + source_map, + emitter: Box::new(emitter_writer), + ignore_path_set, + can_reset, + } + } + + fn get_ignore_list(config: &str) -> IgnoreList { + Config::from_toml(config, Path::new("")).unwrap().ignore() + } + + #[test] + fn handles_fatal_parse_error_in_ignored_file() { + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source = + String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); + source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + Some(ignore_list), + ); + let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); + emitter.emit_diagnostic(&fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 1); + assert_eq!(*can_reset_errors.borrow(), false); + } + + #[test] + fn handles_recoverable_parse_error_in_ignored_file() { + if !is_nightly_channel!() { + return; + } + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source = String::from(r#"pub fn bar() { 1x; }"#); + source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + Some(ignore_list), + ); + let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); + emitter.emit_diagnostic(&non_fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 0); + assert_eq!(*can_reset_errors.borrow(), true); + } + + #[test] + fn handles_recoverable_parse_error_in_non_ignored_file() { + if !is_nightly_channel!() { + return; + } + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source = String::from(r#"pub fn bar() { 1x; }"#); + source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + None, + ); + let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); + emitter.emit_diagnostic(&non_fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 1); + assert_eq!(*can_reset_errors.borrow(), false); + } + + #[test] + fn handles_mix_of_recoverable_parse_error() { + if !is_nightly_channel!() { + return; + } + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); + let bar_source = String::from(r#"pub fn bar() { 1x; }"#); + let foo_source = String::from(r#"pub fn foo() { 1x; }"#); + let fatal_source = + String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); + source_map + .new_source_file(SourceMapFileName::Real(PathBuf::from("bar.rs")), bar_source); + source_map + .new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), foo_source); + source_map.new_source_file( + SourceMapFileName::Real(PathBuf::from("fatal.rs")), + fatal_source, + ); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + Some(ignore_list), + ); + let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22))); + let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); + let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); + let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); + emitter.emit_diagnostic(&bar_diagnostic); + emitter.emit_diagnostic(&foo_diagnostic); + emitter.emit_diagnostic(&fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 2); + assert_eq!(*can_reset_errors.borrow(), false); + } + } +} -- cgit 1.4.1-3-g733a5 From 760bb29feb90d30329de4394591ec2d02666735c Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 8 Feb 2020 22:54:37 -0600 Subject: chore: fix compile warnings --- src/expr.rs | 4 ++-- src/items.rs | 2 +- src/modules.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index a694cc69ac6..84f01f2a1a9 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1148,10 +1148,10 @@ pub(crate) fn is_simple_block( attrs: Option<&[ast::Attribute]>, source_map: &SourceMap, ) -> bool { - (block.stmts.len() == 1 + block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) && !block_contains_comment(block, source_map) - && attrs.map_or(true, |a| a.is_empty())) + && attrs.map_or(true, |a| a.is_empty()) } /// Checks whether a block contains at most one statement or expression, and no diff --git a/src/items.rs b/src/items.rs index ed7b46c8e4f..0316dc6f0c2 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2585,7 +2585,7 @@ fn compute_budgets_for_params( ret_str_len: usize, fn_brace_style: FnBraceStyle, force_vertical_layout: bool, -) -> Option<((usize, usize, Indent))> { +) -> Option<(usize, usize, Indent)> { debug!( "compute_budgets_for_params {} {:?}, {}, {:?}", result.len(), diff --git a/src/modules.rs b/src/modules.rs index 92db42de13f..e7a2e21179d 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; -use rustc_errors::{Diagnostic, PResult}; +use rustc_errors::PResult; use rustc_parse::{new_sub_parser_from_file, parser, DirectoryOwnership}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{sym, Symbol}; -- cgit 1.4.1-3-g733a5 From 7a76ec062deeb9b99a55982deb23597973d8dc21 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 26 Mar 2020 15:26:58 -0500 Subject: deps: bump to rustc v644 --- Cargo.lock | 201 ++++++++++++++++++++++++------------------------- Cargo.toml | 16 ++-- src/closures.rs | 6 +- src/items.rs | 34 ++++----- src/modules.rs | 4 +- src/modules/visitor.rs | 4 +- src/spanned.rs | 6 +- src/types.rs | 8 +- src/utils.rs | 18 ++--- 9 files changed, 148 insertions(+), 149 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 094fcfd384b..c127b4b7db9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -617,49 +617,49 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "642.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "644.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -672,9 +672,9 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -685,15 +685,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -702,31 +702,31 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -734,10 +734,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -746,75 +745,75 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_session" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -823,16 +822,16 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "642.0.0" +version = "644.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -912,14 +911,14 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1276,23 +1275,23 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea82fa3d9a8add7422228ca1a2cbba0784fa8861f56148ff64da08b3c7921b03" -"checksum rustc-ap-graphviz 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "638d0b2b3bcf99824e0cb5a25dbc547b61dc20942e11daf6a97e981918aa18e5" -"checksum rustc-ap-rustc_ast_pretty 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d38bab04dd676dee6d2f9670506a18c31bfce38bf7f8420aa83eb1140ecde049" -"checksum rustc-ap-rustc_attr 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10b843ba8b1ed43739133047673b9f6a54d3b3b4d328d69c6ea89ff971395f35" -"checksum rustc-ap-rustc_data_structures 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc3d1c6d0a80ab0c1df76405377cec0f3d5423fb5b0953a8eac70a2ad6c44df2" -"checksum rustc-ap-rustc_errors 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4909a1eca29331332257230f29120a8ff68c9e37d868c564fcd599e430cf8914" -"checksum rustc-ap-rustc_feature 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63ab887a181d795cf5fd3edadf367760deafb90aefb844f168ab5255266e3478" -"checksum rustc-ap-rustc_fs_util 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70814116df3c5fbec8f06f6a1d013ca481f620fd22a9475754e9bf3ee9ba70d8" -"checksum rustc-ap-rustc_index 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac1bf1d3cf3d119d41353d6fd229ef7272d5097bc0924de021c0294bf86d48bf" -"checksum rustc-ap-rustc_lexer 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4cda21a32cebdc11ec4f5393aa2fcde5ed1b2f673a8571e5a4dcdf07e4ae9cac" -"checksum rustc-ap-rustc_macros 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75c47b48ea51910ecfd853c9248a9bf4c767bc823449ab6a1d864dff65fbae16" -"checksum rustc-ap-rustc_parse 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abd88e89cd5b5d28dcd3a347a3d534c08627d9455570dc1a2d402cb8437b9d30" -"checksum rustc-ap-rustc_session 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8487b4575fbb2d1fc6f1cd61225efd108a4d36817e6fb9b643d57fcae9cb12" -"checksum rustc-ap-rustc_span 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f69746c0d4c21bf20a5bb2bd247261a1aa8631f04202d7303352942dde70d987" -"checksum rustc-ap-rustc_target 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bbc6ae09b5d42ec66edd520e8412e0615c53a7c93607fe33dc4abab60ba7c8b" -"checksum rustc-ap-serialize 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e13a1ead0252fc3d96da4c336a95950be6795f2b00c84a67ccadf26142f8cb41" -"checksum rustc-ap-syntax 642.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f59f48ca3a2ec16a7e82e718ed5aadf9c9e08cf63015d28b4e774767524a6a" +"checksum rustc-ap-arena 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80a4f7385e1a0bd8869b1c49738eb6a5c552d66cbea1b880d0481048588fc565" +"checksum rustc-ap-graphviz 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da134a8459132ec83aba664fbc791c5e409539534bcdeb9df3d29b6ca7c37a76" +"checksum rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41b1280428ae4a3e6b944f2045578a4737cf367db1ac1bdcf66e6e3f886ec981" +"checksum rustc-ap-rustc_attr 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3f27b42985109679eadcf07e0b0f227b9ba3d203173766b2c1a9ee0bbda05e4" +"checksum rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d3f4519ec1dad0b704129a4f891e7c75239850fa683765a63f163ea8ffa7b9" +"checksum rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e870484235e89654b66b10467862f3d60a698c0d5983aa51b42563733b77f71" +"checksum rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03e3e31e687890adfbc606e8f41e460408bc5b7a94c785d36e7cebc4c9193d00" +"checksum rustc-ap-rustc_fs_util 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23e0f0111c0b6ce58385784ecb4945f6b02c449591c13087dba5e82bbd900ac1" +"checksum rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "808d42ae6e32607870710ff7ac0faa89b4ce8f8a4aa0a0d875e8ea62e4911a6c" +"checksum rustc-ap-rustc_lexer 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1494650ca657dd164503e03ebe5a3172fdfe1750e427aa7e139fbda4460817e" +"checksum rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df5ad90674b7aac5606fc923d1aa8b804a11a4e65bf2fe850447b28a2bd9a011" +"checksum rustc-ap-rustc_parse 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb47830cfbb7b05eba5d5ec7c53dfb57dd76d09977e9a78eb7798a2b606bfec6" +"checksum rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d44935089371d9e4c91eb90c9a3358b44c0b59ef1b4552f05cecb8025b1971f0" +"checksum rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccd71ce20995448afe2af68c32d06b01ee160d55ef9e5eebe81a7ca085324dd0" +"checksum rustc-ap-rustc_target 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf8ba8d508f3e4e9e625566295bc1437d0327e7cd3c821e08f65e5801da6904" +"checksum rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b029cc11516918c37b55230edbfc693dabbe1481013cadc506bdd345e63587" +"checksum rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "478155ef59211e934a79bd1ed4dbbbb5d1226bd8921e2aa7edb23d8f5f8d1080" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" diff --git a/Cargo.toml b/Cargo.toml index 1cfa80de8bd..5f1aae6c8eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,35 +64,35 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "642.0.0" +version = "644.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "642.0.0" +version = "644.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "642.0.0" +version = "644.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "642.0.0" +version = "644.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "642.0.0" +version = "644.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "642.0.0" +version = "644.0.0" [dependencies.rustc_target] package = "rustc-ap-rustc_target" -version = "642.0.0" +version = "644.0.0" [dependencies.syntax] package = "rustc-ap-syntax" -version = "642.0.0" +version = "644.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/closures.rs b/src/closures.rs index 18e867cabd1..56bb19b7e54 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -25,7 +25,7 @@ use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; pub(crate) fn rewrite_closure( capture: ast::CaptureBy, - is_async: &ast::IsAsync, + is_async: &ast::Async, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, @@ -50,7 +50,7 @@ pub(crate) fn rewrite_closure( } let result = match fn_decl.output { - ast::FunctionRetTy::Default(_) if !context.inside_macro() => { + ast::FnRetTy::Default(_) if !context.inside_macro() => { try_rewrite_without_block(body, &prefix, context, shape, body_shape) } _ => None, @@ -214,7 +214,7 @@ fn rewrite_closure_block( // Return type is (prefix, extra_offset) fn rewrite_closure_fn_decl( capture: ast::CaptureBy, - asyncness: &ast::IsAsync, + asyncness: &ast::Async, movability: ast::Movability, fn_decl: &ast::FnDecl, body: &ast::Expr, diff --git a/src/items.rs b/src/items.rs index 0316dc6f0c2..b9622faef4a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -165,10 +165,10 @@ pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, generics: &'a ast::Generics, ext: ast::Extern, - is_async: Cow<'a, ast::IsAsync>, - constness: ast::Constness, + is_async: Cow<'a, ast::Async>, + constness: ast::Const, defaultness: ast::Defaultness, - unsafety: ast::Unsafety, + unsafety: ast::Unsafe, visibility: ast::Visibility, } @@ -182,10 +182,10 @@ impl<'a> FnSig<'a> { decl, generics, ext: ast::Extern::None, - is_async: Cow::Owned(ast::IsAsync::NotAsync), - constness: ast::Constness::NotConst, + is_async: Cow::Owned(ast::Async::No), + constness: ast::Const::No, defaultness: ast::Defaultness::Final, - unsafety: ast::Unsafety::Normal, + unsafety: ast::Unsafe::No, visibility: vis, } } @@ -196,8 +196,8 @@ impl<'a> FnSig<'a> { ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, - is_async: Cow::Borrowed(&method_sig.header.asyncness.node), - constness: method_sig.header.constness.node, + is_async: Cow::Borrowed(&method_sig.header.asyncness), + constness: method_sig.header.constness, defaultness: ast::Defaultness::Final, ext: method_sig.header.ext, decl: &*method_sig.decl, @@ -224,8 +224,8 @@ impl<'a> FnSig<'a> { decl, generics, ext: fn_sig.header.ext, - constness: fn_sig.header.constness.node, - is_async: Cow::Borrowed(&fn_sig.header.asyncness.node), + constness: fn_sig.header.constness, + is_async: Cow::Borrowed(&fn_sig.header.asyncness), defaultness, unsafety: fn_sig.header.unsafety, visibility: vis.clone(), @@ -1908,11 +1908,11 @@ pub(crate) fn rewrite_associated_impl_type( } } -impl Rewrite for ast::FunctionRetTy { +impl Rewrite for ast::FnRetTy { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match *self { - ast::FunctionRetTy::Default(_) => Some(String::new()), - ast::FunctionRetTy::Ty(ref ty) => { + ast::FnRetTy::Default(_) => Some(String::new()), + ast::FnRetTy::Ty(ref ty) => { if context.config.version() == Version::One || context.config.indent_style() == IndentStyle::Visual { @@ -2290,7 +2290,7 @@ fn rewrite_fn_base( } // Return type. - if let ast::FunctionRetTy::Ty(..) = fd.output { + if let ast::FnRetTy::Ty(..) = fd.output { let ret_should_indent = match context.config.indent_style() { // If our params are block layout then we surely must have space. IndentStyle::Block if put_params_in_block || fd.inputs.is_empty() => false, @@ -2396,8 +2396,8 @@ fn rewrite_fn_base( } let pos_before_where = match fd.output { - ast::FunctionRetTy::Default(..) => params_span.hi(), - ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(), + ast::FnRetTy::Default(..) => params_span.hi(), + ast::FnRetTy::Ty(ref ty) => ty.span.hi(), }; let is_params_multi_lined = param_str.contains('\n'); @@ -2425,7 +2425,7 @@ fn rewrite_fn_base( // If there are neither where-clause nor return type, we may be missing comments between // params and `{`. if where_clause_str.is_empty() { - if let ast::FunctionRetTy::Default(ret_span) = fd.output { + if let ast::FnRetTy::Default(ret_span) = fd.output { match recover_missing_comment_in_span( mk_sp(params_span.hi(), ret_span.hi()), shape, diff --git a/src/modules.rs b/src/modules.rs index e7a2e21179d..70d808047f8 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -35,9 +35,9 @@ struct Directory { } impl<'a> Directory { - fn to_syntax_directory(&'a self) -> rustc_parse::Directory<'a> { + fn to_syntax_directory(&'a self) -> rustc_parse::Directory { rustc_parse::Directory { - path: Cow::Borrowed(&self.path), + path: self.path.clone(), ownership: self.ownership.clone(), } } diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 4ef1daf7475..a2055b6f4ea 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -15,11 +15,11 @@ pub(crate) struct ModItem { pub(crate) struct CfgIfVisitor<'a> { parse_sess: &'a ParseSess, mods: Vec, - base_dir: Directory<'a>, + base_dir: Directory, } impl<'a> CfgIfVisitor<'a> { - pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: Directory<'a>) -> CfgIfVisitor<'a> { + pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: Directory) -> CfgIfVisitor<'a> { CfgIfVisitor { mods: vec![], parse_sess, diff --git a/src/spanned.rs b/src/spanned.rs index b2a70dd5cec..47ddac9b98b 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -151,11 +151,11 @@ impl Spanned for ast::WherePredicate { } } -impl Spanned for ast::FunctionRetTy { +impl Spanned for ast::FnRetTy { fn span(&self) -> Span { match *self { - ast::FunctionRetTy::Default(span) => span, - ast::FunctionRetTy::Ty(ref ty) => ty.span, + ast::FnRetTy::Default(span) => span, + ast::FnRetTy::Ty(ref ty) => ty.span, } } } diff --git a/src/types.rs b/src/types.rs index efc85efc5c4..d30693fd388 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,7 +2,7 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; use rustc_span::{symbol::kw, BytePos, Span}; -use syntax::ast::{self, FunctionRetTy, Mutability}; +use syntax::ast::{self, FnRetTy, Mutability}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; @@ -292,7 +292,7 @@ fn rewrite_segment( fn format_function_type<'a, I>( inputs: I, - output: &FunctionRetTy, + output: &FnRetTy, variadic: bool, span: Span, context: &RewriteContext<'_>, @@ -311,11 +311,11 @@ where IndentStyle::Visual => shape.block_left(4)?, }; let output = match *output { - FunctionRetTy::Ty(ref ty) => { + FnRetTy::Ty(ref ty) => { let type_str = ty.rewrite(context, ty_shape)?; format!(" -> {}", type_str) } - FunctionRetTy::Default(..) => String::new(), + FnRetTy::Default(..) => String::new(), }; let list_shape = if context.use_block_indent() { diff --git a/src/utils.rs b/src/utils.rs index e0971c7d1bf..f17dbd2561d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -86,18 +86,18 @@ pub(crate) fn format_visibility( } #[inline] -pub(crate) fn format_async(is_async: &ast::IsAsync) -> &'static str { +pub(crate) fn format_async(is_async: &ast::Async) -> &'static str { match is_async { - ast::IsAsync::Async { .. } => "async ", - ast::IsAsync::NotAsync => "", + ast::Async::Yes { .. } => "async ", + ast::Async::No => "", } } #[inline] -pub(crate) fn format_constness(constness: ast::Constness) -> &'static str { +pub(crate) fn format_constness(constness: ast::Const) -> &'static str { match constness { - ast::Constness::Const => "const ", - ast::Constness::NotConst => "", + ast::Const::Yes(..) => "const ", + ast::Const::No => "", } } @@ -110,10 +110,10 @@ pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str } #[inline] -pub(crate) fn format_unsafety(unsafety: ast::Unsafety) -> &'static str { +pub(crate) fn format_unsafety(unsafety: ast::Unsafe) -> &'static str { match unsafety { - ast::Unsafety::Unsafe => "unsafe ", - ast::Unsafety::Normal => "", + ast::Unsafe::Yes(..) => "unsafe ", + ast::Unsafe::No => "", } } -- cgit 1.4.1-3-g733a5 From 9699c96cf1e6a13e0cc12e17c55ca11d2f9a6bf2 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 26 Mar 2020 17:20:24 -0500 Subject: deps: bump to rustc v647 --- Cargo.lock | 218 ++++++++++++++++++++++++++++---------------------------- Cargo.toml | 18 ++--- src/attr.rs | 12 ++-- src/closures.rs | 10 ++- src/items.rs | 46 ++++++------ src/macros.rs | 2 +- src/modules.rs | 2 +- src/spanned.rs | 1 + src/stmt.rs | 2 +- src/utils.rs | 2 +- src/visitor.rs | 66 +++++++++-------- 11 files changed, 198 insertions(+), 181 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index c127b4b7db9..c0f4c0e6932 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -617,49 +617,65 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-ap-rustc_ast" +version = "647.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "644.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "647.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -672,9 +688,9 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -685,15 +701,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -702,31 +718,31 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -734,7 +750,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -745,97 +761,81 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_session" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "644.0.0" +version = "647.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-ap-syntax" -version = "644.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-demangle" version = "0.1.16" @@ -911,14 +911,14 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1275,23 +1275,23 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80a4f7385e1a0bd8869b1c49738eb6a5c552d66cbea1b880d0481048588fc565" -"checksum rustc-ap-graphviz 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da134a8459132ec83aba664fbc791c5e409539534bcdeb9df3d29b6ca7c37a76" -"checksum rustc-ap-rustc_ast_pretty 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41b1280428ae4a3e6b944f2045578a4737cf367db1ac1bdcf66e6e3f886ec981" -"checksum rustc-ap-rustc_attr 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3f27b42985109679eadcf07e0b0f227b9ba3d203173766b2c1a9ee0bbda05e4" -"checksum rustc-ap-rustc_data_structures 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d3f4519ec1dad0b704129a4f891e7c75239850fa683765a63f163ea8ffa7b9" -"checksum rustc-ap-rustc_errors 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e870484235e89654b66b10467862f3d60a698c0d5983aa51b42563733b77f71" -"checksum rustc-ap-rustc_feature 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03e3e31e687890adfbc606e8f41e460408bc5b7a94c785d36e7cebc4c9193d00" -"checksum rustc-ap-rustc_fs_util 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23e0f0111c0b6ce58385784ecb4945f6b02c449591c13087dba5e82bbd900ac1" -"checksum rustc-ap-rustc_index 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "808d42ae6e32607870710ff7ac0faa89b4ce8f8a4aa0a0d875e8ea62e4911a6c" -"checksum rustc-ap-rustc_lexer 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1494650ca657dd164503e03ebe5a3172fdfe1750e427aa7e139fbda4460817e" -"checksum rustc-ap-rustc_macros 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df5ad90674b7aac5606fc923d1aa8b804a11a4e65bf2fe850447b28a2bd9a011" -"checksum rustc-ap-rustc_parse 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb47830cfbb7b05eba5d5ec7c53dfb57dd76d09977e9a78eb7798a2b606bfec6" -"checksum rustc-ap-rustc_session 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d44935089371d9e4c91eb90c9a3358b44c0b59ef1b4552f05cecb8025b1971f0" -"checksum rustc-ap-rustc_span 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccd71ce20995448afe2af68c32d06b01ee160d55ef9e5eebe81a7ca085324dd0" -"checksum rustc-ap-rustc_target 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf8ba8d508f3e4e9e625566295bc1437d0327e7cd3c821e08f65e5801da6904" -"checksum rustc-ap-serialize 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b029cc11516918c37b55230edbfc693dabbe1481013cadc506bdd345e63587" -"checksum rustc-ap-syntax 644.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "478155ef59211e934a79bd1ed4dbbbb5d1226bd8921e2aa7edb23d8f5f8d1080" +"checksum rustc-ap-arena 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c144addf28721384a516382f1f7b7c518ebb87a330623dc9e2427b4ed01512" +"checksum rustc-ap-graphviz 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bdd6f563273576220a075afefae7b9e20953c70e7cfe4b664ce1c240f88841" +"checksum rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4b7aa06b8d9d6bf02075f91cdaf027cbce34aedd6ab5a6f4759de4c05de099" +"checksum rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb9a73b0f1c632fd09dd02444efe753445de17da8ffb1df28adc5766a581ada" +"checksum rustc-ap-rustc_attr 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a420a672006a07f51cfc603ab394a066ccaf51323862c6b6b44bb673812df32" +"checksum rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f224fd21a3c82b84e9914b4b1de31b0099e2083345c739285130017f5b2882" +"checksum rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "312120a27c404bae22ed957b8d4e9cca2b872998558d227130aca9f3ff4edce9" +"checksum rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7615aa561db78b1acacbedfa475e3ba5ed7071a33e5ede30d9660069be7b5e" +"checksum rustc-ap-rustc_fs_util 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ad7d6ee7fe47355214989c1638d9353344dfd2ac46eda5ac971533c543468d0" +"checksum rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a570533637a35eb7ed51de75a819a9f290fbd45b6cd4ca21e4ffe35ee2fcdf5" +"checksum rustc-ap-rustc_lexer 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47a9df68feec956275dfd12cdeadc46fc55e48859417e4301f2b330d680de96e" +"checksum rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "623e619c676c376f079c4504a6047f76630bb3d23d1a6c4a4beee79158082c74" +"checksum rustc-ap-rustc_parse 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "465685a06a0a897cacd3c6bc6e0f50c79e1347cca9eb061361b5fa90ce46fb62" +"checksum rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf21db47cebe929bcac82f66da0faa1f38ace2091d6a887acdd87dcdfb7a823d" +"checksum rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7bb21edcd0e2603efee36ffb1bc4c08b7288478fe107159dbffed0ec8a894a1" +"checksum rustc-ap-rustc_target 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e8cb1a2d38583099f392c6ea8d3f77b1fc8368e4edfce1978d94c249dc9a828" +"checksum rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25317d226bf1d0243d4df231edcc9bf1c0e40c503ef0290cc7aa5658d3819915" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" diff --git a/Cargo.toml b/Cargo.toml index 5f1aae6c8eb..893e4b599db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,35 +64,35 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "644.0.0" +version = "647.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "644.0.0" +version = "647.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "644.0.0" +version = "647.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "644.0.0" +version = "647.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "644.0.0" +version = "647.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "644.0.0" +version = "647.0.0" [dependencies.rustc_target] package = "rustc-ap-rustc_target" -version = "644.0.0" +version = "647.0.0" [dependencies.syntax] -package = "rustc-ap-syntax" -version = "644.0.0" +package = "rustc-ap-rustc_ast" +version = "647.0.0" [dev-dependencies] lazy_static = "1.0.0" diff --git a/src/attr.rs b/src/attr.rs index 461f0ddf029..b913d917b30 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -18,12 +18,13 @@ use crate::utils::{count_newlines, mk_sp}; mod doc_comment; /// Returns attributes on the given statement. -pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { +pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> Option<&[ast::Attribute]> { match stmt.kind { - ast::StmtKind::Local(ref local) => &local.attrs, - ast::StmtKind::Item(ref item) => &item.attrs, - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs, - ast::StmtKind::Mac(ref mac) => &mac.2, + ast::StmtKind::Local(ref local) => Some(&local.attrs), + ast::StmtKind::Item(ref item) => Some(&item.attrs), + ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(&expr.attrs), + ast::StmtKind::Mac(ref mac) => Some(&mac.2), + ast::StmtKind::Empty => None, } } @@ -36,6 +37,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { let (ref mac, _, _) = **mac; mac.span() } + ast::StmtKind::Empty => stmt.span, } } diff --git a/src/closures.rs b/src/closures.rs index 56bb19b7e54..396463083a8 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -105,9 +105,13 @@ fn get_inner_expr<'a>( // Figure out if a block is necessary. fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) -> bool { - let has_attributes = block.stmts.first().map_or(false, |first_stmt| { - !get_attrs_from_stmt(first_stmt).is_empty() - }); + let has_attributes = block + .stmts + .first() + .map_or(false, |first_stmt| match get_attrs_from_stmt(first_stmt) { + Some(attrs) => !attrs.is_empty(), + None => false, + }); is_unsafe_block(block) || block.stmts.len() > 1 diff --git a/src/items.rs b/src/items.rs index b9622faef4a..8c7be672cac 100644 --- a/src/items.rs +++ b/src/items.rs @@ -298,7 +298,7 @@ impl<'a> FmtVisitor<'a> { fn format_foreign_item(&mut self, item: &ast::ForeignItem) { let rewrite = item.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(item.span(), rewrite); + self.push_rewrite(item.span, rewrite); self.last_pos = item.span.hi(); } @@ -629,7 +629,7 @@ impl<'a> FmtVisitor<'a> { use crate::ast::AssocItemKind::*; fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool { match (a, b) { - (TyAlias(_, ref lty), TyAlias(_, ref rty)) + (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty)) if both_type(lty, rty) || both_opaque(lty, rty) => { false @@ -640,7 +640,7 @@ impl<'a> FmtVisitor<'a> { } buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) { - (TyAlias(_, ref lty), TyAlias(_, ref rty)) + (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty)) if both_type(lty, rty) || both_opaque(lty, rty) => { a.ident.as_str().cmp(&b.ident.as_str()) @@ -649,8 +649,8 @@ impl<'a> FmtVisitor<'a> { a.ident.as_str().cmp(&b.ident.as_str()) } (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()), - (TyAlias(_, ref ty), _) if is_type(ty) => Ordering::Less, - (_, TyAlias(_, ref ty)) if is_type(ty) => Ordering::Greater, + (TyAlias(_, _, _, ref ty), _) if is_type(ty) => Ordering::Less, + (_, TyAlias(_, _, _, ref ty)) if is_type(ty) => Ordering::Greater, (TyAlias(..), _) => Ordering::Less, (_, TyAlias(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, @@ -1714,9 +1714,13 @@ pub(crate) struct StaticParts<'a> { impl<'a> StaticParts<'a> { pub(crate) fn from_item(item: &'a ast::Item) -> Self { - let (prefix, ty, mutability, expr) = match item.kind { - ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr), - ast::ItemKind::Const(ref ty, ref expr) => ("const", ty, ast::Mutability::Not, expr), + let (defaultness, prefix, ty, mutability, expr) = match item.kind { + ast::ItemKind::Static(ref ty, mutability, ref expr) => { + (None, "static", ty, mutability, expr) + } + ast::ItemKind::Const(defaultness, ref ty, ref expr) => { + (Some(defaultness), "const", ty, ast::Mutability::Not, expr) + } _ => unreachable!(), }; StaticParts { @@ -1725,15 +1729,17 @@ impl<'a> StaticParts<'a> { ident: item.ident, ty, mutability, - expr_opt: Some(expr), - defaultness: None, + expr_opt: expr.as_ref(), + defaultness: defaultness, span: item.span, } } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem) -> Self { - let (ty, expr_opt) = match ti.kind { - ast::AssocItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt), + let (defaultness, ty, expr_opt) = match ti.kind { + ast::AssocItemKind::Const(defaultness, ref ty, ref expr_opt) => { + (defaultness, ty, expr_opt) + } _ => unreachable!(), }; StaticParts { @@ -1743,14 +1749,14 @@ impl<'a> StaticParts<'a> { ty, mutability: ast::Mutability::Not, expr_opt: expr_opt.as_ref(), - defaultness: None, + defaultness: Some(defaultness), span: ti.span, } } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem) -> Self { - let (ty, expr) = match ii.kind { - ast::AssocItemKind::Const(ref ty, ref expr) => (ty, expr), + let (defaultness, ty, expr) = match ii.kind { + ast::AssocItemKind::Const(defaultness, ref ty, ref expr) => (defaultness, ty, expr), _ => unreachable!(), }; StaticParts { @@ -1760,7 +1766,7 @@ impl<'a> StaticParts<'a> { ty, mutability: ast::Mutability::Not, expr_opt: expr.as_ref(), - defaultness: Some(ii.defaultness), + defaultness: Some(defaultness), span: ii.span, } } @@ -1903,7 +1909,7 @@ pub(crate) fn rewrite_associated_impl_type( let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?; match defaultness { - ast::Defaultness::Default => Some(format!("default {}", result)), + ast::Defaultness::Default(..) => Some(format!("default {}", result)), _ => Some(result), } } @@ -3083,7 +3089,7 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.kind { - ast::ForeignItemKind::Fn(ref fn_sig, ref generics, _) => rewrite_fn_base( + ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( context, shape.indent, self.ident, @@ -3092,7 +3098,7 @@ impl Rewrite for ast::ForeignItem { FnBraceStyle::None, ) .map(|(s, _)| format!("{};", s)), - ast::ForeignItemKind::Static(ref ty, mutability) => { + ast::ForeignItemKind::Static(ref ty, mutability, _) => { // FIXME(#21): we're dropping potential comments in between the // function kw here. let vis = format_visibility(context, &self.vis); @@ -3106,7 +3112,7 @@ impl Rewrite for ast::ForeignItem { // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { let vis = format_visibility(context, &self.vis); Some(format!( "{}type {};", diff --git a/src/macros.rs b/src/macros.rs index dea056928d9..858c2917aa9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -231,7 +231,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { { parser.bump(); let macro_arg = - MacroArg::Keyword(ast::Ident::with_dummy_span(keyword), parser.prev_span); + MacroArg::Keyword(ast::Ident::with_dummy_span(keyword), parser.prev_token.span); return Some(macro_arg); } } diff --git a/src/modules.rs b/src/modules.rs index 70d808047f8..99bd832997a 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -468,7 +468,7 @@ fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResu let hi = if parser.token.span.is_dummy() { inner_lo } else { - parser.prev_span + parser.prev_token.span }; Ok(ast::Mod { diff --git a/src/spanned.rs b/src/spanned.rs index 47ddac9b98b..324594f7760 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -74,6 +74,7 @@ impl Spanned for ast::Stmt { mk_sp(attrs[0].span.lo(), self.span.hi()) } } + ast::StmtKind::Empty => self.span, } } } diff --git a/src/stmt.rs b/src/stmt.rs index df22a5dfd02..c9bfe64d59d 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -106,7 +106,7 @@ fn format_stmt( let shape = shape.sub_width(suffix.len())?; format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } - ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None, + ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, }; result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) } diff --git a/src/utils.rs b/src/utils.rs index f17dbd2561d..de18b8e6d5f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -104,7 +104,7 @@ pub(crate) fn format_constness(constness: ast::Const) -> &'static str { #[inline] pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { match defaultness { - ast::Defaultness::Default => "default ", + ast::Defaultness::Default(..) => "default ", ast::Defaultness::Final => "", } } diff --git a/src/visitor.rs b/src/visitor.rs index c6ae3b3be1e..2073c8a1ef3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -131,13 +131,18 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.format_missing(stmt.span().hi()); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - let attrs = get_attrs_from_stmt(stmt.as_ast_node()); - if contains_skip(attrs) { - self.push_skipped_with_span( - attrs, - stmt.span(), - get_span_without_attrs(stmt.as_ast_node()), - ); + if let Some(attrs) = get_attrs_from_stmt(stmt.as_ast_node()) { + if contains_skip(attrs) { + self.push_skipped_with_span( + attrs, + stmt.span(), + get_span_without_attrs(stmt.as_ast_node()), + ); + } else { + let shape = self.shape(); + let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); + self.push_rewrite(stmt.span(), rewrite) + } } else { let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); @@ -157,6 +162,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } self.format_missing(stmt.span().hi()); } + ast::StmtKind::Empty => (), } } @@ -507,7 +513,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::Fn(ref fn_signature, ref generics, ref body) => { + ast::ItemKind::Fn(defaultness, ref fn_signature, ref generics, ref body) => { let inner_attrs = inner_attributes(&item.attrs); let fn_ctxt = match fn_signature.header.ext { ast::Extern::None => visit::FnCtxt::Free, @@ -524,23 +530,23 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { generics, &fn_signature.decl, item.span, - ast::Defaultness::Final, + defaultness, Some(&inner_attrs), ) } - ast::ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() { - None => { + ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty { + Some(ty) => { let rewrite = rewrite_type_alias( &self.get_context(), self.block_indent, item.ident, - ty, + &*ty, generics, &item.vis, ); self.push_rewrite(item.span, rewrite); } - Some(generic_bounds) => { + None => { let rewrite = rewrite_opaque_type( &self.get_context(), self.block_indent, @@ -583,30 +589,29 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { match ti.kind { ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), - ast::AssocItemKind::Fn(ref sig, None) => { + ast::AssocItemKind::Fn(_, ref sig, ref generics, None) => { let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ti.ident, sig, &ti.generics, ti.span); + let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, generics, ti.span); self.push_rewrite(ti.span, rewrite); } - ast::AssocItemKind::Fn(ref sig, Some(ref body)) => { + ast::AssocItemKind::Fn(defaultness, ref sig, ref generics, Some(ref body)) => { let inner_attrs = inner_attributes(&ti.attrs); let vis = rustc_span::source_map::dummy_spanned(ast::VisibilityKind::Inherited); let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); self.visit_fn( visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), - &ti.generics, + generics, &sig.decl, ti.span, - ast::Defaultness::Final, + defaultness, Some(&inner_attrs), ); } - ast::AssocItemKind::TyAlias(ref generic_bounds, ref type_default) => { + ast::AssocItemKind::TyAlias(_, ref generics, ref generic_bounds, ref type_default) => { let rewrite = rewrite_associated_type( ti.ident, type_default.as_ref(), - &ti.generics, + generics, Some(generic_bounds), &self.get_context(), self.block_indent, @@ -628,32 +633,31 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } match ii.kind { - ast::AssocItemKind::Fn(ref sig, Some(ref body)) => { + ast::AssocItemKind::Fn(defaultness, ref sig, ref generics, Some(ref body)) => { let inner_attrs = inner_attributes(&ii.attrs); let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl); self.visit_fn( visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)), - &ii.generics, + generics, &sig.decl, ii.span, - ii.defaultness, + defaultness, Some(&inner_attrs), ); } - ast::AssocItemKind::Fn(ref sig, None) => { + ast::AssocItemKind::Fn(_, ref sig, ref generics, None) => { let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ii.ident, sig, &ii.generics, ii.span); + let rewrite = self.rewrite_required_fn(indent, ii.ident, sig, generics, ii.span); self.push_rewrite(ii.span, rewrite); } ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::AssocItemKind::TyAlias(_, ref ty) => { + ast::AssocItemKind::TyAlias(defaultness, ref generics, _, ref ty) => { let rewrite_associated = || { rewrite_associated_impl_type( ii.ident, - ii.defaultness, + defaultness, ty.as_ref(), - &ii.generics, + &generics, &self.get_context(), self.block_indent, ) @@ -664,7 +668,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(generic_bounds) => rewrite_opaque_impl_type( &self.get_context(), ii.ident, - &ii.generics, + &generics, generic_bounds, self.block_indent, ), -- cgit 1.4.1-3-g733a5 From bd5dff4012a73ad4c5eb5db1dbb111bd92ed31dd Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 26 Mar 2020 21:25:34 -0500 Subject: refactor: backport syntux mod --- Cargo.toml | 4 +- src/closures.rs | 6 +- src/comment.rs | 4 +- src/expr.rs | 27 ++- src/formatting.rs | 458 +++++-------------------------------------------- src/items.rs | 6 +- src/lib.rs | 11 +- src/lists.rs | 4 +- src/macros.rs | 10 +- src/matches.rs | 7 +- src/missed_spans.rs | 25 ++- src/modules.rs | 170 +++--------------- src/modules/visitor.rs | 67 +------- src/reorder.rs | 4 +- src/rewrite.rs | 9 +- src/source_file.rs | 17 +- src/source_map.rs | 29 +--- src/syntux.rs | 4 + src/syntux/parser.rs | 348 +++++++++++++++++++++++++++++++++++++ src/syntux/session.rs | 440 +++++++++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 2 +- src/visitor.rs | 73 ++++---- 22 files changed, 959 insertions(+), 766 deletions(-) create mode 100644 src/syntux.rs create mode 100644 src/syntux/parser.rs create mode 100644 src/syntux/session.rs (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 893e4b599db..18d3df1fa7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ ignore = "0.4.11" annotate-snippets = { version = "0.6", features = ["ansi_term"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } +lazy_static = "1.0.0" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` @@ -93,6 +94,3 @@ version = "647.0.0" [dependencies.syntax] package = "rustc-ap-rustc_ast" version = "647.0.0" - -[dev-dependencies] -lazy_static = "1.0.0" diff --git a/src/closures.rs b/src/closures.rs index 396463083a8..625ef4a81f9 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -43,7 +43,7 @@ pub(crate) fn rewrite_closure( if let ast::ExprKind::Block(ref block, _) = body.kind { // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.source_map) { + if block.stmts.is_empty() && !block_contains_comment(context, block) { return body .rewrite(context, shape) .map(|s| format!("{} {}", prefix, s)); @@ -116,7 +116,7 @@ fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) - is_unsafe_block(block) || block.stmts.len() > 1 || has_attributes - || block_contains_comment(block, context.source_map) + || block_contains_comment(context, block) || prefix.contains('\n') } @@ -309,7 +309,7 @@ pub(crate) fn rewrite_last_closure( ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() - && is_simple_block(block, Some(&body.attrs), context.source_map) => + && is_simple_block(context, block, Some(&body.attrs)) => { stmt_expr(&block.stmts[0]).unwrap_or(body) } diff --git a/src/comment.rs b/src/comment.rs index 5b46001ff7d..518f2bcda0c 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1556,10 +1556,10 @@ pub(crate) fn recover_comment_removed( // We missed some comments. Warn and keep the original text. if context.config.error_on_unformatted() { context.report.append( - context.source_map.span_to_filename(span).into(), + context.parse_sess.span_to_filename(span), vec![FormattingError::from_span( span, - &context.source_map, + &context.parse_sess, ErrorKind::LostComment, )], ); diff --git a/src/expr.rs b/src/expr.rs index 84f01f2a1a9..608425b34bd 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::cmp::min; use itertools::Itertools; -use rustc_span::{source_map::SourceMap, BytePos, Span}; +use rustc_span::{BytePos, Span}; use syntax::token::{DelimToken, LitKind}; use syntax::{ast, ptr}; @@ -430,7 +430,7 @@ fn rewrite_empty_block( return None; } - if !block_contains_comment(block, context.source_map) && shape.width >= 2 { + if !block_contains_comment(context, block) && shape.width >= 2 { return Some(format!("{}{}{{}}", prefix, label_str)); } @@ -487,7 +487,7 @@ fn rewrite_single_line_block( label: Option, shape: Shape, ) -> Option { - if is_simple_block(block, attrs, context.source_map) { + if is_simple_block(context, block, attrs) { let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; let label_str = rewrite_label(label); @@ -750,8 +750,8 @@ impl<'a> ControlFlow<'a> { let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node, _) = else_block.kind { - if !is_simple_block(self.block, None, context.source_map) - || !is_simple_block(else_node, None, context.source_map) + if !is_simple_block(context, self.block, None) + || !is_simple_block(context, else_node, None) || pat_expr_str.contains('\n') { return None; @@ -1134,9 +1134,8 @@ fn extract_comment(span: Span, context: &RewriteContext<'_>, shape: Shape) -> Op } } -pub(crate) fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> bool { - let snippet = source_map.span_to_snippet(block.span).unwrap(); - contains_comment(&snippet) +pub(crate) fn block_contains_comment(context: &RewriteContext<'_>, block: &ast::Block) -> bool { + contains_comment(context.snippet(block.span)) } // Checks that a block contains no statements, an expression and no comments or @@ -1144,37 +1143,37 @@ pub(crate) fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) // FIXME: incorrectly returns false when comment is contained completely within // the expression. pub(crate) fn is_simple_block( + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, - source_map: &SourceMap, ) -> bool { block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, source_map) + && !block_contains_comment(context, block) && attrs.map_or(true, |a| a.is_empty()) } /// Checks whether a block contains at most one statement or expression, and no /// comments or attributes. pub(crate) fn is_simple_block_stmt( + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, - source_map: &SourceMap, ) -> bool { block.stmts.len() <= 1 - && !block_contains_comment(block, source_map) + && !block_contains_comment(context, block) && attrs.map_or(true, |a| a.is_empty()) } /// Checks whether a block contains no statements, expressions, comments, or /// inner attributes. pub(crate) fn is_empty_block( + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, - source_map: &SourceMap, ) -> bool { block.stmts.is_empty() - && !block_contains_comment(block, source_map) + && !block_contains_comment(context, block) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } diff --git a/src/formatting.rs b/src/formatting.rs index bed87748253..104e631f441 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -1,29 +1,20 @@ // High level formatting functions. -use std::cell::RefCell; use std::collections::HashMap; use std::io::{self, Write}; -use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::rc::Rc; use std::time::{Duration, Instant}; -use rustc_data_structures::sync::{Lrc, Send}; -use rustc_errors::emitter::{Emitter, EmitterWriter}; -use rustc_errors::{ColorConfig, Diagnostic, DiagnosticBuilder, Handler, Level as DiagnosticLevel}; -use rustc_session::parse::ParseSess; -use rustc_span::{ - source_map::{FilePathMapping, SourceMap}, - Span, DUMMY_SP, -}; +use rustc_span::Span; use syntax::ast; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; -use crate::ignore_path::IgnorePathSet; use crate::issues::BadIssueSeeker; +use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; +use crate::syntux::session::ParseSess; use crate::utils::count_newlines; -use crate::visitor::{FmtVisitor, SnippetProvider}; +use crate::visitor::FmtVisitor; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; mod newline_style; @@ -71,54 +62,41 @@ fn format_project( let main_file = input.file_name(); let input_is_stdin = main_file == FileName::Stdin; - let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(set) => Rc::new(set), - Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), - }; - if config.skip_children() && ignore_path_set.is_match(&main_file) { + let mut parse_session = ParseSess::new(config)?; + if config.skip_children() && parse_session.ignore_file(&main_file) { return Ok(FormatReport::new()); } // Parse the crate. - let can_reset_parser_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let mut parse_session = make_parse_sess( - source_map.clone(), - config, - Rc::clone(&ignore_path_set), - can_reset_parser_errors.clone(), - ); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); - let krate = match parse_crate( - input, - &parse_session, - config, - &mut report, - directory_ownership, - can_reset_parser_errors.clone(), - ) { + let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) - Err(ErrorKind::ParseError) => return Ok(report), - Err(e) => return Err(e), + Err(e) => { + let forbid_verbose = input_is_stdin || e != ParserError::ParsePanicError; + should_emit_verbose(forbid_verbose, config, || { + eprintln!("The Rust parser panicked"); + }); + report.add_parsing_error(); + return Ok(report); + } }; timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. - let silent_emitter = silent_emitter(); - parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter); + parse_session.set_silent_emitter(); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( &context.parse_session, - directory_ownership.unwrap_or(rustc_parse::DirectoryOwnership::UnownedViaMod), + directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), !(input_is_stdin || config.skip_children()), ) .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; for (path, module) in files { - let should_ignore = !input_is_stdin && ignore_path_set.is_match(&path); + let should_ignore = !input_is_stdin && context.ignore_file(&path); if (config.skip_children() && path != main_file) || should_ignore { continue; } @@ -150,6 +128,10 @@ struct FormatContext<'a, T: FormatHandler> { } impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { + fn ignore_file(&self, path: &FileName) -> bool { + self.parse_session.ignore_file(path) + } + // Formats a single file/module. fn format_file( &mut self, @@ -157,15 +139,8 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { module: &ast::Mod, is_root: bool, ) -> Result<(), ErrorKind> { - let source_file = self - .parse_session - .source_map() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = source_file.src.as_ref().unwrap(); - let snippet_provider = - SnippetProvider::new(source_file.start_pos, source_file.end_pos, big_snippet); - let mut visitor = FmtVisitor::from_source_map( + let snippet_provider = self.parse_session.snippet_provider(module.inner); + let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, &self.config, &snippet_provider, @@ -175,16 +150,16 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { // Format inner attributes if available. if !self.krate.attrs.is_empty() && is_root { - visitor.skip_empty_lines(source_file.end_pos); + visitor.skip_empty_lines(snippet_provider.end_pos()); if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); } else { - visitor.format_separate_mod(module, &*source_file); + visitor.format_separate_mod(module, snippet_provider.end_pos()); } } else { - visitor.last_pos = source_file.start_pos; - visitor.skip_empty_lines(source_file.end_pos); - visitor.format_separate_mod(module, &*source_file); + visitor.last_pos = snippet_provider.start_pos(); + visitor.skip_empty_lines(snippet_provider.end_pos()); + visitor.format_separate_mod(module, snippet_provider.end_pos()); }; debug_assert_eq!( @@ -209,7 +184,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { apply_newline_style( self.config.newline_style(), &mut visitor.buffer, - &big_snippet, + snippet_provider.entire_snippet(), ); if visitor.macro_rewrite_failure { @@ -219,7 +194,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { .add_non_formatted_ranges(visitor.skipped_range.borrow().clone()); self.handler.handle_formatted_file( - self.parse_session.source_map(), + &self.parse_session, path, visitor.buffer.to_owned(), &mut self.report, @@ -231,7 +206,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { trait FormatHandler { fn handle_formatted_file( &mut self, - source_map: &SourceMap, + parse_session: &ParseSess, path: FileName, result: String, report: &mut FormatReport, @@ -242,14 +217,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { // Called for each formatted file. fn handle_formatted_file( &mut self, - source_map: &SourceMap, + parse_session: &ParseSess, path: FileName, result: String, report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { match source_file::write_file( - Some(source_map), + Some(parse_session), &path, &result, out, @@ -282,23 +257,15 @@ pub(crate) struct FormattingError { impl FormattingError { pub(crate) fn from_span( span: Span, - source_map: &SourceMap, + parse_sess: &ParseSess, kind: ErrorKind, ) -> FormattingError { FormattingError { - line: source_map.lookup_char_pos(span.lo()).line, + line: parse_sess.line_of_byte_pos(span.lo()), is_comment: kind.is_comment(), kind, is_string: false, - line_buffer: source_map - .span_to_lines(span) - .ok() - .and_then(|fl| { - fl.file - .get_line(fl.lines[0].line_index) - .map(std::borrow::Cow::into_owned) - }) - .unwrap_or_else(String::new), + line_buffer: parse_sess.span_to_first_line_string(span), } } @@ -633,358 +600,11 @@ impl<'a> FormatLines<'a> { } } -fn parse_crate( - input: Input, - parse_session: &ParseSess, - config: &Config, - report: &mut FormatReport, - directory_ownership: Option, - can_reset_parser_errors: Rc>, -) -> Result { - let input_is_stdin = input.is_text(); - - let parser = match input { - Input::File(ref file) => { - // Use `new_sub_parser_from_file` when we the input is a submodule. - Ok(if let Some(dir_own) = directory_ownership { - rustc_parse::new_sub_parser_from_file(parse_session, file, dir_own, None, DUMMY_SP) - } else { - rustc_parse::new_parser_from_file(parse_session, file) - }) - } - Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( - parse_session, - rustc_span::FileName::Custom("stdin".to_owned()), - text, - ) - .map(|mut parser| { - parser.recurse_into_file_modules = false; - parser - }), - }; - - let result = match parser { - Ok(mut parser) => { - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - - let mut parser = AssertUnwindSafe(parser); - catch_unwind(move || parser.0.parse_crate_mod().map_err(|d| vec![d])) - } - Err(diagnostics) => { - for diagnostic in diagnostics { - parse_session.span_diagnostic.emit_diagnostic(&diagnostic); - } - report.add_parsing_error(); - return Err(ErrorKind::ParseError); - } - }; - - match result { - Ok(Ok(c)) => { - if !parse_session.span_diagnostic.has_errors() { - return Ok(c); - } - // This scenario occurs when the parser encountered errors - // but was still able to recover. If all of the parser errors - // occurred in files that are ignored, then reset - // the error count and continue. - // https://github.com/rust-lang/rustfmt/issues/3779 - if *can_reset_parser_errors.borrow() { - parse_session.span_diagnostic.reset_err_count(); - return Ok(c); - } - } - Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(DiagnosticBuilder::emit), - Err(_) => { - // Note that if you see this message and want more information, - // then run the `parse_crate_mod` function above without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(input_is_stdin, config, || { - println!("The Rust parser panicked") - }); - } - } - - report.add_parsing_error(); - Err(ErrorKind::ParseError) -} - -struct SilentOnIgnoredFilesEmitter { - ignore_path_set: Rc, - source_map: Rc, - emitter: Box, - has_non_ignorable_parser_errors: bool, - can_reset: Rc>, -} - -impl SilentOnIgnoredFilesEmitter { - fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { - self.has_non_ignorable_parser_errors = true; - *self.can_reset.borrow_mut() = false; - self.emitter.emit_diagnostic(db); - } -} - -impl Emitter for SilentOnIgnoredFilesEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - - fn emit_diagnostic(&mut self, db: &Diagnostic) { - if db.level == DiagnosticLevel::Fatal { - return self.handle_non_ignoreable_error(db); - } - if let Some(primary_span) = &db.span.primary_span() { - let file_name = self.source_map.span_to_filename(*primary_span); - if let rustc_span::FileName::Real(ref path) = file_name { - if self - .ignore_path_set - .is_match(&FileName::Real(path.to_path_buf())) - { - if !self.has_non_ignorable_parser_errors { - *self.can_reset.borrow_mut() = true; - } - return; - } - }; - } - self.handle_non_ignoreable_error(db); - } -} - -/// Emitter which discards every error. -struct SilentEmitter; - -impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} -} - -fn silent_emitter() -> Box { - Box::new(SilentEmitter {}) -} - -fn make_parse_sess( - source_map: Rc, - config: &Config, - ignore_path_set: Rc, - can_reset: Rc>, -) -> ParseSess { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - - let emitter = if config.hide_parse_errors() { - silent_emitter() - } else { - Box::new(EmitterWriter::stderr( - color_cfg, - Some(source_map.clone()), - false, - false, - None, - false, - )) - }; - let handler = Handler::with_emitter( - true, - None, - Box::new(SilentOnIgnoredFilesEmitter { - has_non_ignorable_parser_errors: false, - source_map: source_map.clone(), - emitter, - ignore_path_set, - can_reset, - }), - ); - - ParseSess::with_span_handler(handler, source_map) -} - -fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) +fn should_emit_verbose(forbid_verbose_output: bool, config: &Config, f: F) where F: Fn(), { - if config.verbose() == Verbosity::Verbose && !is_stdin { + if config.verbose() == Verbosity::Verbose && !forbid_verbose_output { f(); } } - -#[cfg(test)] -mod tests { - use super::*; - - mod emitter { - use super::*; - use crate::config::IgnoreList; - use crate::is_nightly_channel; - use crate::utils::mk_sp; - use rustc_span::{BytePos, FileName as SourceMapFileName, MultiSpan, DUMMY_SP}; - use std::path::{Path, PathBuf}; - - struct TestEmitter { - num_emitted_errors: Rc>, - } - - impl Emitter for TestEmitter { - fn source_map(&self) -> Option<&Lrc> { - None - } - fn emit_diagnostic(&mut self, _db: &Diagnostic) { - *self.num_emitted_errors.borrow_mut() += 1; - } - } - - fn build_diagnostic(level: DiagnosticLevel, span: Option) -> Diagnostic { - Diagnostic { - level, - code: None, - message: vec![], - children: vec![], - suggestions: vec![], - span: span.unwrap_or_else(MultiSpan::new), - sort_span: DUMMY_SP, - } - } - - fn build_emitter( - num_emitted_errors: Rc>, - can_reset: Rc>, - source_map: Option>, - ignore_list: Option, - ) -> SilentOnIgnoredFilesEmitter { - let emitter_writer = TestEmitter { num_emitted_errors }; - let source_map = - source_map.unwrap_or_else(|| Rc::new(SourceMap::new(FilePathMapping::empty()))); - let ignore_path_set = - Rc::new(IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap()); - SilentOnIgnoredFilesEmitter { - has_non_ignorable_parser_errors: false, - source_map, - emitter: Box::new(emitter_writer), - ignore_path_set, - can_reset, - } - } - - fn get_ignore_list(config: &str) -> IgnoreList { - Config::from_toml(config, Path::new("")).unwrap().ignore() - } - - #[test] - fn handles_fatal_parse_error_in_ignored_file() { - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let source = - String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); - source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); - let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), - Some(ignore_list), - ); - let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); - let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); - emitter.emit_diagnostic(&fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 1); - assert_eq!(*can_reset_errors.borrow(), false); - } - - #[test] - fn handles_recoverable_parse_error_in_ignored_file() { - if !is_nightly_channel!() { - return; - } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let source = String::from(r#"pub fn bar() { 1x; }"#); - source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); - let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), - Some(ignore_list), - ); - let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); - let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 0); - assert_eq!(*can_reset_errors.borrow(), true); - } - - #[test] - fn handles_recoverable_parse_error_in_non_ignored_file() { - if !is_nightly_channel!() { - return; - } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let source = String::from(r#"pub fn bar() { 1x; }"#); - source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); - let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), - None, - ); - let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); - let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 1); - assert_eq!(*can_reset_errors.borrow(), false); - } - - #[test] - fn handles_mix_of_recoverable_parse_error() { - if !is_nightly_channel!() { - return; - } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let bar_source = String::from(r#"pub fn bar() { 1x; }"#); - let foo_source = String::from(r#"pub fn foo() { 1x; }"#); - let fatal_source = - String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); - source_map - .new_source_file(SourceMapFileName::Real(PathBuf::from("bar.rs")), bar_source); - source_map - .new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), foo_source); - source_map.new_source_file( - SourceMapFileName::Real(PathBuf::from("fatal.rs")), - fatal_source, - ); - let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), - Some(ignore_list), - ); - let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); - let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22))); - let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); - let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); - let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); - emitter.emit_diagnostic(&bar_diagnostic); - emitter.emit_diagnostic(&foo_diagnostic); - emitter.emit_diagnostic(&fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 2); - assert_eq!(*can_reset_errors.borrow(), false); - } - } -} diff --git a/src/items.rs b/src/items.rs index 8c7be672cac..9bd254250cc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -363,17 +363,17 @@ impl<'a> FmtVisitor<'a> { return None; } - let source_map = self.get_context().source_map; + let context = self.get_context(); if self.config.empty_item_single_line() - && is_empty_block(block, None, source_map) + && is_empty_block(&context, block, None) && self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width() && !last_line_contains_single_line_comment(fn_str) { return Some(format!("{} {{}}", fn_str)); } - if !self.config.fn_single_line() || !is_simple_block_stmt(block, None, source_map) { + if !self.config.fn_single_line() || !is_simple_block_stmt(&context, block, None) { return None; } diff --git a/src/lib.rs b/src/lib.rs index f0783b2ca36..dbd9469908e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ #[macro_use] extern crate derive_new; -#[cfg(test)] #[macro_use] extern crate lazy_static; #[macro_use] @@ -20,7 +19,6 @@ use std::rc::Rc; use failure::Fail; use ignore; -use rustc_parse::DirectoryOwnership; use syntax::ast; use crate::comment::LineClasses; @@ -28,6 +26,7 @@ use crate::emitter::Emitter; use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use crate::issues::Issue; use crate::shape::Indent; +use crate::syntux::parser::DirectoryOwnership; use crate::utils::indent_next_line; pub use crate::config::{ @@ -75,6 +74,7 @@ pub(crate) mod source_map; mod spanned; mod stmt; mod string; +mod syntux; #[cfg(test)] mod test; mod types; @@ -509,13 +509,6 @@ pub enum Input { } impl Input { - fn is_text(&self) -> bool { - match *self { - Input::File(_) => false, - Input::Text(_) => true, - } - } - fn file_name(&self) -> FileName { match *self { Input::File(ref file) => FileName::Real(file.clone()), diff --git a/src/lists.rs b/src/lists.rs index 96a10924e25..bc55ef6686a 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -560,7 +560,7 @@ pub(crate) struct ListItems<'a, I, F1, F2, F3> where I: Iterator, { - snippet_provider: &'a SnippetProvider<'a>, + snippet_provider: &'a SnippetProvider, inner: Peekable, get_lo: F1, get_hi: F2, @@ -777,7 +777,7 @@ where #[allow(clippy::too_many_arguments)] // Creates an iterator over a list's items with associated comments. pub(crate) fn itemize_list<'a, T, I, F1, F2, F3>( - snippet_provider: &'a SnippetProvider<'_>, + snippet_provider: &'a SnippetProvider, inner: I, terminator: &'a str, separator: &'a str, diff --git a/src/macros.rs b/src/macros.rs index 858c2917aa9..482b680310c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -178,8 +178,8 @@ fn return_macro_parse_failure_fallback( } context.skipped_range.borrow_mut().push(( - context.source_map.lookup_line(span.lo()).unwrap().line, - context.source_map.lookup_line(span.hi()).unwrap().line, + context.parse_sess.line_of_byte_pos(span.lo()), + context.parse_sess.line_of_byte_pos(span.hi()), )); // Return the snippet unmodified if the macro is not block-like @@ -286,7 +286,7 @@ fn rewrite_macro_inner( } } - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); let mut arg_vec = Vec::new(); let mut vec_with_semi = false; let mut trailing_comma = false; @@ -1190,7 +1190,7 @@ pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> O let path = &pprust::path_to_string(&mac.path); if path == "try" || path == "r#try" { let ts = mac.args.inner_tokens(); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); Some(ast::Expr { id: ast::NodeId::root(), // dummy value @@ -1422,7 +1422,7 @@ fn format_lazy_static( ts: &TokenStream, ) -> Option { let mut result = String::with_capacity(1024); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); let nested_shape = shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config); diff --git a/src/matches.rs b/src/matches.rs index 954db40ae52..792b3bfd466 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -276,7 +276,7 @@ fn block_can_be_flattened<'a>( ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() - && is_simple_block(block, Some(&expr.attrs), context.source_map) => + && is_simple_block(context, block, Some(&expr.attrs)) => { Some(&*block) } @@ -332,10 +332,7 @@ fn rewrite_match_body( shape.offset_left(extra_offset(pats_str, shape) + 4), ); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.kind { - ( - true, - is_empty_block(block, Some(&body.attrs), context.source_map), - ) + (true, is_empty_block(context, block, Some(&body.attrs))) } else { (false, false) }; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 99595436f89..e6889ae9786 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -86,9 +86,8 @@ impl<'a> FmtVisitor<'a> { assert!( start < end, - "Request to format inverted span: {:?} to {:?}", - self.source_map.lookup_char_pos(start), - self.source_map.lookup_char_pos(end) + "Request to format inverted span: {}", + self.parse_sess.span_to_debug_info(mk_sp(start, end)), ); self.last_pos = end; @@ -139,26 +138,22 @@ impl<'a> FmtVisitor<'a> { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment // follows code on the same line, we won't touch it. - let big_span_lo = self.source_map.lookup_char_pos(span.lo()).file.start_pos; - let local_begin = self.source_map.lookup_byte_offset(big_span_lo); - let local_end = self.source_map.lookup_byte_offset(span.hi()); - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.sf.src.as_ref().unwrap()[start_index..end_index]; - + let big_span_lo = self.snippet_provider.start_pos(); + let big_snippet = self.snippet_provider.entire_snippet(); let big_diff = (span.lo() - big_span_lo).to_usize(); + let snippet = self.snippet(span); debug!("write_snippet `{}`", snippet); - self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); + self.write_snippet_inner(big_snippet, snippet, big_diff, span, process_last_snippet); } fn write_snippet_inner( &mut self, big_snippet: &str, - big_diff: usize, old_snippet: &str, + big_diff: usize, span: Span, process_last_snippet: F, ) where @@ -167,9 +162,9 @@ impl<'a> FmtVisitor<'a> { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. - let char_pos = self.source_map.lookup_char_pos(span.lo()); - let file_name = &char_pos.file.name.clone().into(); - let mut status = SnippetStatus::new(char_pos.line); + let line = self.parse_sess.line_of_byte_pos(span.lo()); + let file_name = &self.parse_sess.span_to_filename(span); + let mut status = SnippetStatus::new(line); let snippet = &*transform_missing_snippet(self.config, old_snippet); diff --git a/src/modules.rs b/src/modules.rs index 99bd832997a..bb0effedfa8 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -2,24 +2,25 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; -use rustc_errors::PResult; -use rustc_parse::{new_sub_parser_from_file, parser, DirectoryOwnership}; -use rustc_session::parse::ParseSess; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{source_map, Span, DUMMY_SP}; use syntax::ast; -use syntax::token::TokenKind; use syntax::visit::Visitor; use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; +use crate::syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser}; +use crate::syntux::session::ParseSess; use crate::utils::contains_skip; mod visitor; type FileModMap<'ast> = BTreeMap>; +lazy_static! { + static ref CFG_IF: Symbol = Symbol::intern("cfg_if"); +} + /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { parse_sess: &'sess ParseSess, @@ -28,21 +29,6 @@ pub(crate) struct ModResolver<'ast, 'sess> { recursive: bool, } -#[derive(Clone)] -struct Directory { - path: PathBuf, - ownership: DirectoryOwnership, -} - -impl<'a> Directory { - fn to_syntax_directory(&'a self) -> rustc_parse::Directory { - rustc_parse::Directory { - path: self.path.clone(), - ownership: self.ownership.clone(), - } - } -} - #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` @@ -78,12 +64,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mut self, krate: &'ast ast::Crate, ) -> Result, String> { - let root_filename = self.parse_sess.source_map().span_to_filename(krate.span); + let root_filename = self.parse_sess.span_to_filename(krate.span); self.directory.path = match root_filename { - source_map::FileName::Real(ref path) => path - .parent() - .expect("Parent directory should exists") - .to_path_buf(), + FileName::Real(ref p) => p.parent().unwrap_or(Path::new("")).to_path_buf(), _ => PathBuf::new(), }; @@ -93,14 +76,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } self.file_map - .insert(root_filename.into(), Cow::Borrowed(&krate.module)); + .insert(root_filename, Cow::Borrowed(&krate.module)); Ok(self.file_map) } /// Visit `cfg_if` macro and look for module declarations. fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { - let mut visitor = - visitor::CfgIfVisitor::new(self.parse_sess, self.directory.to_syntax_directory()); + let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess, &self.directory); visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { @@ -258,7 +240,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, ) -> Result, String> { - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &self.directory.path) { + if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) { return Ok(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, @@ -266,23 +248,18 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } // Look for nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. - let mut mods_outside_ast = self - .find_mods_ouside_of_ast(attrs, sub_mod) - .unwrap_or(vec![]); + let mut mods_outside_ast = self.find_mods_outside_of_ast(attrs, sub_mod); let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, }; - match parser::Parser::default_submod_path( - mod_name, - relative, - &self.directory.path, - self.parse_sess.source_map(), - ) - .result + match self + .parse_sess + .default_submod_path(mod_name, relative, &self.directory.path) + .result { - Ok(parser::ModulePathSuccess { + Ok(ModulePathSuccess { path, directory_ownership, .. @@ -323,21 +300,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } - fn find_mods_ouside_of_ast( - &self, - attrs: &[ast::Attribute], - sub_mod: &Cow<'ast, ast::Mod>, - ) -> Option)>> { - use std::panic::{catch_unwind, AssertUnwindSafe}; - Some( - catch_unwind(AssertUnwindSafe(|| { - self.find_mods_ouside_of_ast_inner(attrs, sub_mod) - })) - .ok()?, - ) - } - - fn find_mods_ouside_of_ast_inner( + fn find_mods_outside_of_ast( &self, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, @@ -356,14 +319,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if !actual_path.exists() { continue; } - let file_name = rustc_span::FileName::Real(actual_path.clone()); - if self - .parse_sess - .source_map() - .get_source_file(&file_name) - .is_some() - { - // If the specfied file is already parsed, then we just use that. + if self.parse_sess.is_file_parsed(&actual_path) { + // If the specified file is already parsed, then we just use that. result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, @@ -371,32 +328,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - let mut parser = new_sub_parser_from_file( + let m = match Parser::parse_file_as_module( + self.directory.ownership, self.parse_sess, &actual_path, - self.directory.ownership, - None, - DUMMY_SP, - ); - parser.cfg_mods = false; - let lo = parser.token.span; - // FIXME(topecongiro) Format inner attributes (#3606). - let _mod_attrs = match parse_inner_attributes(&mut parser) { - Ok(attrs) => attrs, - Err(mut e) => { - e.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - continue; - } - }; - let m = match parse_mod_items(&mut parser, lo) { - Ok(m) => m, - Err(mut e) => { - e.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - continue; - } + ) { + Some(m) => m, + None => continue, }; + result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, @@ -422,67 +362,11 @@ fn find_path_value(attrs: &[ast::Attribute]) -> Option { attrs.iter().flat_map(path_value).next() } -// FIXME(topecongiro) Use the method from libsyntax[1] once it become public. -// -// [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs -fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Vec> { - let mut attrs: Vec = vec![]; - loop { - match parser.token.kind { - TokenKind::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !parser.look_ahead(1, |t| t == &TokenKind::Not) { - break; - } - - let attr = parser.parse_attribute(true)?; - assert_eq!(attr.style, ast::AttrStyle::Inner); - attrs.push(attr); - } - TokenKind::DocComment(s) => { - // we need to get the position of this token before we bump. - let attr = syntax::attr::mk_doc_comment( - syntax::util::comments::doc_comment_style(&s.as_str()), - s, - parser.token.span, - ); - if attr.style == ast::AttrStyle::Inner { - attrs.push(attr); - parser.bump(); - } else { - break; - } - } - _ => break, - } - } - Ok(attrs) -} - -fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResult<'a, ast::Mod> { - let mut items = vec![]; - while let Some(item) = parser.parse_item()? { - items.push(item); - } - - let hi = if parser.token.span.is_dummy() { - inner_lo - } else { - parser.prev_token.span - }; - - Ok(ast::Mod { - inner: inner_lo.to(hi), - items, - inline: false, - }) -} - fn is_cfg_if(item: &ast::Item) -> bool { match item.kind { ast::ItemKind::Mac(ref mac) => { if let Some(first_segment) = mac.path.segments.first() { - if first_segment.ident.name == Symbol::intern("cfg_if") { + if first_segment.ident.name == *CFG_IF { return true; } } diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index a2055b6f4ea..ad9111f7a9f 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -1,11 +1,10 @@ -use rustc_parse::{stream_to_parser_with_base_dir, Directory}; -use rustc_session::parse::ParseSess; -use rustc_span::{symbol::kw, Symbol}; +use rustc_span::Symbol; use syntax::ast; -use syntax::token::{DelimToken, TokenKind}; use syntax::visit::Visitor; use crate::attr::MetaVisitor; +use crate::syntux::parser::{Directory, Parser}; +use crate::syntux::session::ParseSess; pub(crate) struct ModItem { pub(crate) item: ast::Item, @@ -15,11 +14,11 @@ pub(crate) struct ModItem { pub(crate) struct CfgIfVisitor<'a> { parse_sess: &'a ParseSess, mods: Vec, - base_dir: Directory, + base_dir: &'a Directory, } impl<'a> CfgIfVisitor<'a> { - pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: Directory) -> CfgIfVisitor<'a> { + pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: &'a Directory) -> CfgIfVisitor<'a> { CfgIfVisitor { mods: vec![], parse_sess, @@ -65,59 +64,9 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } }; - let ts = mac.args.inner_tokens(); - let mut parser = - stream_to_parser_with_base_dir(self.parse_sess, ts.clone(), self.base_dir.clone()); - parser.cfg_mods = false; - let mut process_if_cfg = true; - - while parser.token.kind != TokenKind::Eof { - if process_if_cfg { - if !parser.eat_keyword(kw::If) { - return Err("Expected `if`"); - } - parser - .parse_attribute(false) - .map_err(|_| "Failed to parse attributes")?; - } - - if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) { - return Err("Expected an opening brace"); - } - - while parser.token != TokenKind::CloseDelim(DelimToken::Brace) - && parser.token.kind != TokenKind::Eof - { - let item = match parser.parse_item() { - Ok(Some(item_ptr)) => item_ptr.into_inner(), - Ok(None) => continue, - Err(mut err) => { - err.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - return Err( - "Expected item inside cfg_if block, but failed to parse it as an item", - ); - } - }; - if let ast::ItemKind::Mod(..) = item.kind { - self.mods.push(ModItem { item }); - } - } - - if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) { - return Err("Expected a closing brace"); - } - - if parser.eat(&TokenKind::Eof) { - break; - } - - if !parser.eat_keyword(kw::Else) { - return Err("Expected `else`"); - } - - process_if_cfg = parser.token.is_keyword(kw::If); - } + let items = Parser::parse_cfg_if(self.parse_sess, mac, &self.base_dir)?; + self.mods + .append(&mut items.into_iter().map(|item| ModItem { item }).collect()); Ok(()) } diff --git a/src/reorder.rs b/src/reorder.rs index 4b607812c00..0235e552be7 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -207,13 +207,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item_kind: ReorderableItemKind, in_group: bool, ) -> usize { - let mut last = self.source_map.lookup_line_range(items[0].span()); + let mut last = self.parse_sess.lookup_line_range(items[0].span()); let item_length = items .iter() .take_while(|ppi| { item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.source_map.lookup_line_range(ppi.span()); + let current = self.parse_sess.lookup_line_range(ppi.span()); let in_same_group = current.lo < last.hi + 2; last = current; in_same_group diff --git a/src/rewrite.rs b/src/rewrite.rs index fbae4bc7122..f73602f09a2 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -3,13 +3,13 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_session::parse::ParseSess; -use rustc_span::{source_map::SourceMap, Span}; +use rustc_span::Span; use syntax::ptr; use crate::config::{Config, IndentStyle}; use crate::shape::Shape; use crate::skip::SkipContext; +use crate::syntux::session::ParseSess; use crate::visitor::SnippetProvider; use crate::FormatReport; @@ -26,8 +26,7 @@ impl Rewrite for ptr::P { #[derive(Clone)] pub(crate) struct RewriteContext<'a> { - pub(crate) parse_session: &'a ParseSess, - pub(crate) source_map: &'a SourceMap, + pub(crate) parse_sess: &'a ParseSess, pub(crate) config: &'a Config, pub(crate) inside_macro: Rc>, // Force block indent style even if we are using visual indent style. @@ -37,7 +36,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) is_if_else_block: Cell, // When rewriting chain, veto going multi line except the last element pub(crate) force_one_line_chain: Cell, - pub(crate) snippet_provider: &'a SnippetProvider<'a>, + pub(crate) snippet_provider: &'a SnippetProvider, // Used for `format_snippet` pub(crate) macro_rewrite_failure: Cell, pub(crate) report: FormatReport, diff --git a/src/source_file.rs b/src/source_file.rs index 4cb894e55b8..4f02d8224e2 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -2,10 +2,9 @@ use std::fs; use std::io::{self, Write}; use std::path::Path; -use rustc_span::source_map::SourceMap; - use crate::config::FileName; use crate::emitter::{self, Emitter}; +use crate::syntux::session::ParseSess; use crate::NewlineStyle; #[cfg(test)] @@ -14,6 +13,7 @@ use crate::config::Config; use crate::create_emitter; #[cfg(test)] use crate::formatting::FileRecord; +use std::rc::Rc; // Append a newline to the end of each file. pub(crate) fn append_newline(s: &mut String) { @@ -48,7 +48,7 @@ where } pub(crate) fn write_file( - source_map: Option<&SourceMap>, + parse_sess: Option<&ParseSess>, filename: &FileName, formatted_text: &str, out: &mut T, @@ -84,20 +84,17 @@ where // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { - fs::read_to_string(ensure_real_path(filename))? + Rc::new(fs::read_to_string(ensure_real_path(filename))?) } else { - match source_map - .and_then(|x| x.get_source_file(&filename.into())) - .and_then(|x| x.src.as_ref().map(ToString::to_string)) - { + match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { Some(ori) => ori, - None => fs::read_to_string(ensure_real_path(filename))?, + None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), } }; let formatted_file = emitter::FormattedFile { filename, - original_text: &original_text, + original_text: original_text.as_str(), formatted_text, }; diff --git a/src/source_map.rs b/src/source_map.rs index c3a549d3b84..76e0d24cf1e 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -1,11 +1,10 @@ //! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. -use rustc_span::{source_map::SourceMap, BytePos, Span}; +use rustc_span::{BytePos, Span}; use crate::comment::FindUncommented; use crate::config::file_lines::LineRange; -use crate::utils::starts_with_newline; use crate::visitor::SnippetProvider; pub(crate) trait SpanUtils { @@ -26,7 +25,7 @@ pub(crate) trait LineRangeUtils { fn lookup_line_range(&self, span: Span) -> LineRange; } -impl<'a> SpanUtils for SnippetProvider<'a> { +impl SpanUtils for SnippetProvider { fn span_after(&self, original: Span, needle: &str) -> BytePos { self.opt_span_after(original, needle).unwrap_or_else(|| { panic!( @@ -81,27 +80,3 @@ impl<'a> SpanUtils for SnippetProvider<'a> { Some(original.lo() + BytePos(offset as u32)) } } - -impl LineRangeUtils for SourceMap { - fn lookup_line_range(&self, span: Span) -> LineRange { - let snippet = self.span_to_snippet(span).unwrap_or_default(); - let lo = self.lookup_line(span.lo()).unwrap(); - let hi = self.lookup_line(span.hi()).unwrap(); - - debug_assert_eq!( - lo.sf.name, hi.sf.name, - "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, hi - ); - - // in case the span starts with a newline, the line range is off by 1 without the - // adjustment below - let offset = 1 + if starts_with_newline(&snippet) { 1 } else { 0 }; - // Line numbers start at 1 - LineRange { - file: lo.sf.clone(), - lo: lo.line + offset, - hi: hi.line + offset, - } - } -} diff --git a/src/syntux.rs b/src/syntux.rs new file mode 100644 index 00000000000..845576bd8d8 --- /dev/null +++ b/src/syntux.rs @@ -0,0 +1,4 @@ +//! This module defines a thin abstract layer on top of the rustc's parser and syntax libraries. + +pub(crate) mod parser; +pub(crate) mod session; diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs new file mode 100644 index 00000000000..6e3cd5e2375 --- /dev/null +++ b/src/syntux/parser.rs @@ -0,0 +1,348 @@ +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::path::{Path, PathBuf}; + +use rustc_errors::{Diagnostic, PResult}; +use rustc_parse::{new_sub_parser_from_file, parser::Parser as RawParser}; +use rustc_span::{symbol::kw, Span, DUMMY_SP}; +use syntax::ast; +use syntax::token::{DelimToken, TokenKind}; + +use crate::syntux::session::ParseSess; +use crate::{Config, Input}; + +pub(crate) type DirectoryOwnership = rustc_parse::DirectoryOwnership; +pub(crate) type ModulePathSuccess = rustc_parse::parser::ModulePathSuccess; + +#[derive(Clone)] +pub(crate) struct Directory { + pub(crate) path: PathBuf, + pub(crate) ownership: DirectoryOwnership, +} + +impl<'a> Directory { + fn to_syntax_directory(&'a self) -> rustc_parse::Directory { + rustc_parse::Directory { + path: self.path.clone(), + ownership: self.ownership, + } + } +} + +/// A parser for Rust source code. +pub(crate) struct Parser<'a> { + parser: RawParser<'a>, + sess: &'a ParseSess, +} + +/// A builder for the `Parser`. +#[derive(Default)] +pub(crate) struct ParserBuilder<'a> { + config: Option<&'a Config>, + sess: Option<&'a ParseSess>, + input: Option, + directory_ownership: Option, +} + +impl<'a> ParserBuilder<'a> { + pub(crate) fn input(mut self, input: Input) -> ParserBuilder<'a> { + self.input = Some(input); + self + } + + pub(crate) fn sess(mut self, sess: &'a ParseSess) -> ParserBuilder<'a> { + self.sess = Some(sess); + self + } + + pub(crate) fn config(mut self, config: &'a Config) -> ParserBuilder<'a> { + self.config = Some(config); + self + } + + pub(crate) fn directory_ownership( + mut self, + directory_ownership: Option, + ) -> ParserBuilder<'a> { + self.directory_ownership = directory_ownership; + self + } + + pub(crate) fn build(self) -> Result, ParserError> { + let config = self.config.ok_or(ParserError::NoConfig)?; + let sess = self.sess.ok_or(ParserError::NoParseSess)?; + let input = self.input.ok_or(ParserError::NoInput)?; + + let mut parser = match Self::parser(sess.inner(), input, self.directory_ownership) { + Ok(p) => p, + Err(db) => { + sess.emit_diagnostics(db); + return Err(ParserError::ParserCreationError); + } + }; + + parser.cfg_mods = false; + if config.skip_children() { + parser.recurse_into_file_modules = false; + } + + Ok(Parser { parser, sess }) + } + + fn parser( + sess: &'a rustc_session::parse::ParseSess, + input: Input, + directory_ownership: Option, + ) -> Result, Vec> { + match input { + Input::File(ref file) => Ok(if let Some(directory_ownership) = directory_ownership { + rustc_parse::new_sub_parser_from_file( + sess, + file, + directory_ownership, + None, + DUMMY_SP, + ) + } else { + rustc_parse::new_parser_from_file(sess, file) + }), + Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( + sess, + rustc_span::FileName::Custom("stdin".to_owned()), + text, + ) + .map(|mut parser| { + parser.recurse_into_file_modules = false; + parser + }), + } + } +} + +#[derive(Debug, PartialEq)] +pub(crate) enum ParserError { + NoConfig, + NoParseSess, + NoInput, + ParserCreationError, + ParseError, + ParsePanicError, +} + +impl<'a> Parser<'a> { + pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { + rustc_parse::parser::Parser::submod_path_from_attr(attrs, path) + } + + // FIXME(topecongiro) Use the method from libsyntax[1] once it become public. + // + // [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs + fn parse_inner_attrs(parser: &mut RawParser<'a>) -> PResult<'a, Vec> { + let mut attrs: Vec = vec![]; + loop { + match parser.token.kind { + TokenKind::Pound => { + // Don't even try to parse if it's not an inner attribute. + if !parser.look_ahead(1, |t| t == &TokenKind::Not) { + break; + } + + let attr = parser.parse_attribute(true)?; + assert_eq!(attr.style, ast::AttrStyle::Inner); + attrs.push(attr); + } + TokenKind::DocComment(s) => { + // we need to get the position of this token before we bump. + let attr = syntax::attr::mk_doc_comment( + syntax::util::comments::doc_comment_style(&s.as_str()), + s, + parser.token.span, + ); + if attr.style == ast::AttrStyle::Inner { + attrs.push(attr); + parser.bump(); + } else { + break; + } + } + _ => break, + } + } + Ok(attrs) + } + + fn parse_mod_items(parser: &mut RawParser<'a>, span: Span) -> PResult<'a, ast::Mod> { + let mut items = vec![]; + while let Some(item) = parser.parse_item()? { + items.push(item); + } + + let hi = if parser.token.span.is_dummy() { + span + } else { + parser.prev_token.span + }; + + Ok(ast::Mod { + inner: span.to(hi), + items, + inline: false, + }) + } + + pub(crate) fn parse_file_as_module( + directory_ownership: DirectoryOwnership, + sess: &'a ParseSess, + path: &Path, + ) -> Option { + let result = catch_unwind(AssertUnwindSafe(|| { + let mut parser = + new_sub_parser_from_file(sess.inner(), &path, directory_ownership, None, DUMMY_SP); + + parser.cfg_mods = false; + let lo = parser.token.span; + // FIXME(topecongiro) Format inner attributes (#3606). + match Parser::parse_inner_attrs(&mut parser) { + Ok(_attrs) => (), + Err(mut e) => { + e.cancel(); + sess.reset_errors(); + return None; + } + } + + match Parser::parse_mod_items(&mut parser, lo) { + Ok(m) => Some(m), + Err(mut db) => { + db.cancel(); + sess.reset_errors(); + None + } + } + })); + match result { + Ok(Some(m)) => Some(m), + _ => None, + } + } + + pub(crate) fn parse_crate( + config: &'a Config, + input: Input, + directory_ownership: Option, + sess: &'a ParseSess, + ) -> Result { + let mut parser = ParserBuilder::default() + .config(config) + .input(input) + .directory_ownership(directory_ownership) + .sess(sess) + .build()?; + + parser.parse_crate_inner() + } + + fn parse_crate_inner(&mut self) -> Result { + let mut parser = AssertUnwindSafe(&mut self.parser); + + match catch_unwind(move || parser.parse_crate_mod()) { + Ok(Ok(krate)) => { + if !self.sess.has_errors() { + return Ok(krate); + } + + if self.sess.can_reset_errors() { + self.sess.reset_errors(); + return Ok(krate); + } + + Err(ParserError::ParseError) + } + Ok(Err(mut db)) => { + db.emit(); + Err(ParserError::ParseError) + } + Err(_) => Err(ParserError::ParsePanicError), + } + } + + pub(crate) fn parse_cfg_if( + sess: &'a ParseSess, + mac: &'a ast::Mac, + base_dir: &Directory, + ) -> Result, &'static str> { + match catch_unwind(AssertUnwindSafe(|| { + Parser::parse_cfg_if_inner(sess, mac, base_dir) + })) { + Ok(Ok(items)) => Ok(items), + Ok(err @ Err(_)) => err, + Err(..) => Err("failed to parse cfg_if!"), + } + } + + fn parse_cfg_if_inner( + sess: &'a ParseSess, + mac: &'a ast::Mac, + base_dir: &Directory, + ) -> Result, &'static str> { + let token_stream = mac.args.inner_tokens(); + let mut parser = rustc_parse::stream_to_parser_with_base_dir( + sess.inner(), + token_stream.clone(), + base_dir.to_syntax_directory(), + ); + + parser.cfg_mods = false; + let mut items = vec![]; + let mut process_if_cfg = true; + + while parser.token.kind != TokenKind::Eof { + if process_if_cfg { + if !parser.eat_keyword(kw::If) { + return Err("Expected `if`"); + } + parser + .parse_attribute(false) + .map_err(|_| "Failed to parse attributes")?; + } + + if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) { + return Err("Expected an opening brace"); + } + + while parser.token != TokenKind::CloseDelim(DelimToken::Brace) + && parser.token.kind != TokenKind::Eof + { + let item = match parser.parse_item() { + Ok(Some(item_ptr)) => item_ptr.into_inner(), + Ok(None) => continue, + Err(mut err) => { + err.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + return Err( + "Expected item inside cfg_if block, but failed to parse it as an item", + ); + } + }; + if let ast::ItemKind::Mod(..) = item.kind { + items.push(item); + } + } + + if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) { + return Err("Expected a closing brace"); + } + + if parser.eat(&TokenKind::Eof) { + break; + } + + if !parser.eat_keyword(kw::Else) { + return Err("Expected `else`"); + } + + process_if_cfg = parser.token.is_keyword(kw::If); + } + + Ok(items) + } +} diff --git a/src/syntux/session.rs b/src/syntux/session.rs new file mode 100644 index 00000000000..9ec85efb109 --- /dev/null +++ b/src/syntux/session.rs @@ -0,0 +1,440 @@ +use std::cell::RefCell; +use std::path::Path; +use std::rc::Rc; + +use rustc_data_structures::sync::{Lrc, Send}; +use rustc_errors::emitter::{Emitter, EmitterWriter}; +use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; +use rustc_session::parse::ParseSess as RawParseSess; +use rustc_span::{ + source_map::{FilePathMapping, SourceMap}, + BytePos, Span, +}; +use syntax::ast; + +use crate::config::file_lines::LineRange; +use crate::ignore_path::IgnorePathSet; +use crate::source_map::LineRangeUtils; +use crate::utils::starts_with_newline; +use crate::visitor::SnippetProvider; +use crate::{Config, ErrorKind, FileName}; + +/// ParseSess holds structs necessary for constructing a parser. +pub(crate) struct ParseSess { + parse_sess: RawParseSess, + ignore_path_set: Rc, + can_reset_errors: Rc>, +} + +/// Emitter which discards every error. +struct SilentEmitter; + +impl Emitter for SilentEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } + fn emit_diagnostic(&mut self, _db: &Diagnostic) {} +} + +fn silent_emitter() -> Box { + Box::new(SilentEmitter {}) +} + +/// Emit errors against every files expect ones specified in the `ignore_path_set`. +struct SilentOnIgnoredFilesEmitter { + ignore_path_set: Rc, + source_map: Rc, + emitter: Box, + has_non_ignorable_parser_errors: bool, + can_reset: Rc>, +} + +impl SilentOnIgnoredFilesEmitter { + fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { + self.has_non_ignorable_parser_errors = true; + *self.can_reset.borrow_mut() = false; + self.emitter.emit_diagnostic(db); + } +} + +impl Emitter for SilentOnIgnoredFilesEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } + fn emit_diagnostic(&mut self, db: &Diagnostic) { + if db.level == DiagnosticLevel::Fatal { + return self.handle_non_ignoreable_error(db); + } + if let Some(primary_span) = &db.span.primary_span() { + let file_name = self.source_map.span_to_filename(*primary_span); + if let rustc_span::FileName::Real(ref path) = file_name { + if self + .ignore_path_set + .is_match(&FileName::Real(path.to_path_buf())) + { + if !self.has_non_ignorable_parser_errors { + *self.can_reset.borrow_mut() = true; + } + return; + } + }; + } + self.handle_non_ignoreable_error(db); + } +} + +fn default_handler( + source_map: Rc, + ignore_path_set: Rc, + can_reset: Rc>, + hide_parse_errors: bool, +) -> Handler { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + + let emitter = if hide_parse_errors { + silent_emitter() + } else { + Box::new(EmitterWriter::stderr( + color_cfg, + Some(source_map.clone()), + false, + false, + None, + false, + )) + }; + Handler::with_emitter( + true, + None, + Box::new(SilentOnIgnoredFilesEmitter { + has_non_ignorable_parser_errors: false, + source_map, + emitter, + ignore_path_set, + can_reset, + }), + ) +} + +impl ParseSess { + pub(crate) fn new(config: &Config) -> Result { + let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { + Ok(ignore_path_set) => Rc::new(ignore_path_set), + Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), + }; + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let can_reset_errors = Rc::new(RefCell::new(false)); + + let handler = default_handler( + Rc::clone(&source_map), + Rc::clone(&ignore_path_set), + Rc::clone(&can_reset_errors), + config.hide_parse_errors(), + ); + let parse_sess = RawParseSess::with_span_handler(handler, source_map); + + Ok(ParseSess { + parse_sess, + ignore_path_set, + can_reset_errors, + }) + } + + pub(crate) fn default_submod_path( + &self, + id: ast::Ident, + relative: Option, + dir_path: &Path, + ) -> rustc_parse::parser::ModulePath { + rustc_parse::parser::Parser::default_submod_path( + id, + relative, + dir_path, + self.parse_sess.source_map(), + ) + } + + pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { + self.parse_sess + .source_map() + .get_source_file(&rustc_span::FileName::Real(path.to_path_buf())) + .is_some() + } + + pub(crate) fn ignore_file(&self, path: &FileName) -> bool { + self.ignore_path_set.as_ref().is_match(&path) + } + + pub(crate) fn set_silent_emitter(&mut self) { + self.parse_sess.span_diagnostic = Handler::with_emitter(true, None, silent_emitter()); + } + + pub(crate) fn span_to_filename(&self, span: Span) -> FileName { + self.parse_sess.source_map().span_to_filename(span).into() + } + + pub(crate) fn span_to_first_line_string(&self, span: Span) -> String { + let file_lines = self.parse_sess.source_map().span_to_lines(span).ok(); + + match file_lines { + Some(fl) => fl + .file + .get_line(fl.lines[0].line_index) + .map_or_else(String::new, |s| s.to_string()), + None => String::new(), + } + } + + pub(crate) fn line_of_byte_pos(&self, pos: BytePos) -> usize { + self.parse_sess.source_map().lookup_char_pos(pos).line + } + + pub(crate) fn span_to_debug_info(&self, span: Span) -> String { + self.parse_sess.source_map().span_to_string(span) + } + + pub(crate) fn inner(&self) -> &RawParseSess { + &self.parse_sess + } + + pub(crate) fn snippet_provider(&self, span: Span) -> SnippetProvider { + let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file; + SnippetProvider::new( + source_file.start_pos, + source_file.end_pos, + Rc::clone(source_file.src.as_ref().unwrap()), + ) + } + + pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option> { + self.parse_sess + .source_map() + .get_source_file(&file_name.into()) + .and_then(|source_file| source_file.src.clone()) + } +} + +// Methods that should be restricted within the syntux module. +impl ParseSess { + pub(super) fn emit_diagnostics(&self, diagnostics: Vec) { + for diagnostic in diagnostics { + self.parse_sess.span_diagnostic.emit_diagnostic(&diagnostic); + } + } + + pub(super) fn can_reset_errors(&self) -> bool { + *self.can_reset_errors.borrow() + } + + pub(super) fn has_errors(&self) -> bool { + self.parse_sess.span_diagnostic.has_errors() + } + + pub(super) fn reset_errors(&self) { + self.parse_sess.span_diagnostic.reset_err_count(); + } +} + +impl LineRangeUtils for ParseSess { + fn lookup_line_range(&self, span: Span) -> LineRange { + let snippet = self + .parse_sess + .source_map() + .span_to_snippet(span) + .unwrap_or_default(); + let lo = self.parse_sess.source_map().lookup_line(span.lo()).unwrap(); + let hi = self.parse_sess.source_map().lookup_line(span.hi()).unwrap(); + + debug_assert_eq!( + lo.sf.name, hi.sf.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, hi + ); + + // in case the span starts with a newline, the line range is off by 1 without the + // adjustment below + let offset = 1 + if starts_with_newline(&snippet) { 1 } else { 0 }; + // Line numbers start at 1 + LineRange { + file: lo.sf.clone(), + lo: lo.line + offset, + hi: hi.line + offset, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + mod emitter { + use super::*; + use crate::config::IgnoreList; + use crate::is_nightly_channel; + use crate::utils::mk_sp; + use rustc_span::{FileName as SourceMapFileName, MultiSpan, DUMMY_SP}; + use std::path::PathBuf; + + struct TestEmitter { + num_emitted_errors: Rc>, + } + + impl Emitter for TestEmitter { + fn source_map(&self) -> Option<&Lrc> { + None + } + fn emit_diagnostic(&mut self, _db: &Diagnostic) { + *self.num_emitted_errors.borrow_mut() += 1; + } + } + + fn build_diagnostic(level: DiagnosticLevel, span: Option) -> Diagnostic { + Diagnostic { + level, + code: None, + message: vec![], + children: vec![], + suggestions: vec![], + span: span.unwrap_or_else(MultiSpan::new), + sort_span: DUMMY_SP, + } + } + + fn build_emitter( + num_emitted_errors: Rc>, + can_reset: Rc>, + source_map: Option>, + ignore_list: Option, + ) -> SilentOnIgnoredFilesEmitter { + let emitter_writer = TestEmitter { num_emitted_errors }; + let source_map = + source_map.unwrap_or_else(|| Rc::new(SourceMap::new(FilePathMapping::empty()))); + let ignore_path_set = + Rc::new(IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap()); + SilentOnIgnoredFilesEmitter { + has_non_ignorable_parser_errors: false, + source_map, + emitter: Box::new(emitter_writer), + ignore_path_set, + can_reset, + } + } + + fn get_ignore_list(config: &str) -> IgnoreList { + Config::from_toml(config, Path::new("")).unwrap().ignore() + } + + #[test] + fn handles_fatal_parse_error_in_ignored_file() { + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source = + String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); + source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + Some(ignore_list), + ); + let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); + emitter.emit_diagnostic(&fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 1); + assert_eq!(*can_reset_errors.borrow(), false); + } + + #[test] + fn handles_recoverable_parse_error_in_ignored_file() { + if !is_nightly_channel!() { + return; + } + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source = String::from(r#"pub fn bar() { 1x; }"#); + source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + Some(ignore_list), + ); + let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); + emitter.emit_diagnostic(&non_fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 0); + assert_eq!(*can_reset_errors.borrow(), true); + } + + #[test] + fn handles_recoverable_parse_error_in_non_ignored_file() { + if !is_nightly_channel!() { + return; + } + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source = String::from(r#"pub fn bar() { 1x; }"#); + source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + None, + ); + let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); + emitter.emit_diagnostic(&non_fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 1); + assert_eq!(*can_reset_errors.borrow(), false); + } + + #[test] + fn handles_mix_of_recoverable_parse_error() { + if !is_nightly_channel!() { + return; + } + let num_emitted_errors = Rc::new(RefCell::new(0)); + let can_reset_errors = Rc::new(RefCell::new(false)); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); + let bar_source = String::from(r#"pub fn bar() { 1x; }"#); + let foo_source = String::from(r#"pub fn foo() { 1x; }"#); + let fatal_source = + String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); + source_map + .new_source_file(SourceMapFileName::Real(PathBuf::from("bar.rs")), bar_source); + source_map + .new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), foo_source); + source_map.new_source_file( + SourceMapFileName::Real(PathBuf::from("fatal.rs")), + fatal_source, + ); + let mut emitter = build_emitter( + Rc::clone(&num_emitted_errors), + Rc::clone(&can_reset_errors), + Some(Rc::clone(&source_map)), + Some(ignore_list), + ); + let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); + let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22))); + let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); + let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); + let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); + emitter.emit_diagnostic(&bar_diagnostic); + emitter.emit_diagnostic(&foo_diagnostic); + emitter.emit_diagnostic(&fatal_diagnostic); + assert_eq!(*num_emitted_errors.borrow(), 2); + assert_eq!(*can_reset_errors.borrow(), false); + } + } +} diff --git a/src/utils.rs b/src/utils.rs index de18b8e6d5f..7e287a4b80a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -355,7 +355,7 @@ macro_rules! out_of_file_lines_range { && !$self .config .file_lines() - .intersects(&$self.source_map.lookup_line_range($span)) + .intersects(&$self.parse_sess.lookup_line_range($span)) }; } diff --git a/src/visitor.rs b/src/visitor.rs index 2073c8a1ef3..fe489f32a16 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,11 +1,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_session::parse::ParseSess; -use rustc_span::{ - source_map::{self, SourceMap}, - BytePos, Pos, Span, -}; +use rustc_span::{BytePos, Pos, Span}; use syntax::token::DelimToken; use syntax::{ast, visit}; @@ -27,6 +23,7 @@ use crate::skip::{is_skip_attr, SkipContext}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; +use crate::syntux::session::ParseSess; use crate::utils::{ self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, @@ -34,23 +31,23 @@ use crate::utils::{ use crate::{ErrorKind, FormatReport, FormattingError}; /// Creates a string slice corresponding to the specified span. -pub(crate) struct SnippetProvider<'a> { +pub(crate) struct SnippetProvider { /// A pointer to the content of the file we are formatting. - big_snippet: &'a str, + big_snippet: Rc, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, /// A end position of the file that this snippet lives. end_pos: usize, } -impl<'a> SnippetProvider<'a> { +impl SnippetProvider { pub(crate) fn span_to_snippet(&self, span: Span) -> Option<&str> { let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; Some(&self.big_snippet[start_index..end_index]) } - pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: &'a str) -> Self { + pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: Rc) -> Self { let start_pos = start_pos.to_usize(); let end_pos = end_pos.to_usize(); SnippetProvider { @@ -60,6 +57,14 @@ impl<'a> SnippetProvider<'a> { } } + pub(crate) fn entire_snippet(&self) -> &str { + self.big_snippet.as_str() + } + + pub(crate) fn start_pos(&self) -> BytePos { + BytePos::from_usize(self.start_pos) + } + pub(crate) fn end_pos(&self) -> BytePos { BytePos::from_usize(self.end_pos) } @@ -67,15 +72,14 @@ impl<'a> SnippetProvider<'a> { pub(crate) struct FmtVisitor<'a> { parent_context: Option<&'a RewriteContext<'a>>, - pub(crate) parse_session: &'a ParseSess, - pub(crate) source_map: &'a SourceMap, + pub(crate) parse_sess: &'a ParseSess, pub(crate) buffer: String, pub(crate) last_pos: BytePos, // FIXME: use an RAII util or closure for indenting pub(crate) block_indent: Indent, pub(crate) config: &'a Config, pub(crate) is_if_else_block: bool, - pub(crate) snippet_provider: &'a SnippetProvider<'a>, + pub(crate) snippet_provider: &'a SnippetProvider, pub(crate) line_number: usize, /// List of 1-based line ranges which were annotated with skip /// Both bounds are inclusifs. @@ -110,10 +114,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &Stmt<'_>) { debug!( - "visit_stmt: {:?} {:?} `{}`", - self.source_map.lookup_char_pos(stmt.span().lo()), - self.source_map.lookup_char_pos(stmt.span().hi()), - self.snippet(stmt.span()), + "visit_stmt: {}", + self.parse_sess.span_to_debug_info(stmt.span()) ); // https://github.com/rust-lang/rust/issues/63679. @@ -201,9 +203,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { has_braces: bool, ) { debug!( - "visit_block: {:?} {:?}", - self.source_map.lookup_char_pos(b.span.lo()), - self.source_map.lookup_char_pos(b.span.hi()) + "visit_block: {}", + self.parse_sess.span_to_debug_info(b.span), ); // Check if this block has braces. @@ -744,10 +745,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // do not take into account the lines with attributes as part of the skipped range let attrs_end = attrs .iter() - .map(|attr| self.source_map.lookup_char_pos(attr.span.hi()).line) + .map(|attr| self.parse_sess.line_of_byte_pos(attr.span.hi())) .max() .unwrap_or(1); - let first_line = self.source_map.lookup_char_pos(main_span.lo()).line; + let first_line = self.parse_sess.line_of_byte_pos(main_span.lo()); // Statement can start after some newlines and/or spaces // or it can be on the same line as the last attribute. // So here we need to take a minimum between the two. @@ -758,8 +759,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { - let mut visitor = FmtVisitor::from_source_map( - ctx.parse_session, + let mut visitor = FmtVisitor::from_parse_sess( + ctx.parse_sess, ctx.config, ctx.snippet_provider, ctx.report.clone(), @@ -769,16 +770,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { visitor } - pub(crate) fn from_source_map( + pub(crate) fn from_parse_sess( parse_session: &'a ParseSess, config: &'a Config, - snippet_provider: &'a SnippetProvider<'_>, + snippet_provider: &'a SnippetProvider, report: FormatReport, ) -> FmtVisitor<'a> { FmtVisitor { parent_context: None, - parse_session, - source_map: parse_session.source_map(), + parse_sess: parse_session, buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), last_pos: BytePos(0), block_indent: Indent::empty(), @@ -805,12 +805,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { if attr.check_name(depr_skip_annotation()) { - let file_name = self.source_map.span_to_filename(attr.span).into(); + let file_name = self.parse_sess.span_to_filename(attr.span); self.report.append( file_name, vec![FormattingError::from_span( attr.span, - &self.source_map, + self.parse_sess, ErrorKind::DeprecatedAttr, )], ); @@ -819,12 +819,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::AttrKind::Normal(ref attribute_item) if self.is_unknown_rustfmt_attr(&attribute_item.path.segments) => { - let file_name = self.source_map.span_to_filename(attr.span).into(); + let file_name = self.parse_sess.span_to_filename(attr.span); self.report.append( file_name, vec![FormattingError::from_span( attr.span, - self.source_map, + self.parse_sess, ErrorKind::BadAttr, )], ); @@ -932,14 +932,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub(crate) fn format_separate_mod( - &mut self, - m: &ast::Mod, - source_file: &source_map::SourceFile, - ) { + pub(crate) fn format_separate_mod(&mut self, m: &ast::Mod, end_pos: BytePos) { self.block_indent = Indent::empty(); self.walk_mod_items(m); - self.format_missing_with_indent(source_file.end_pos); + self.format_missing_with_indent(end_pos); } pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) { @@ -970,8 +966,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn get_context(&self) -> RewriteContext<'_> { RewriteContext { - parse_session: self.parse_session, - source_map: self.source_map, + parse_sess: self.parse_sess, config: self.config, inside_macro: Rc::new(Cell::new(false)), use_block: Cell::new(false), -- cgit 1.4.1-3-g733a5 From 9b0ed57af690bb46eb87de334c6cbef5bd27c174 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 26 Mar 2020 23:18:16 -0500 Subject: refactor: parse & mod resolver for rustc-ap v650 --- Cargo.lock | 241 +++++++++++++++++++++++++++++-------------------- Cargo.toml | 20 ++-- src/attr.rs | 4 +- src/chains.rs | 2 +- src/expr.rs | 6 +- src/formatting.rs | 3 +- src/items.rs | 17 ++-- src/macros.rs | 14 +-- src/matches.rs | 2 +- src/modules.rs | 125 ++++++++++++++++++------- src/modules/visitor.rs | 12 +-- src/patterns.rs | 4 +- src/spanned.rs | 2 +- src/stmt.rs | 2 +- src/syntux/parser.rs | 75 ++++----------- src/syntux/session.rs | 7 +- src/types.rs | 2 +- src/utils.rs | 2 +- src/visitor.rs | 12 +-- 19 files changed, 309 insertions(+), 243 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index c0f4c0e6932..2206da81730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -617,65 +617,82 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_ast" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_ast_passes" +version = "650.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "647.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "650.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -688,9 +705,9 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -701,48 +718,69 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_expand" +version = "650.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_passes 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-rustc_feature" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -750,7 +788,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -761,75 +799,75 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_session" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "647.0.0" +version = "650.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -911,14 +949,15 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_expand 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1275,23 +1314,25 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c144addf28721384a516382f1f7b7c518ebb87a330623dc9e2427b4ed01512" -"checksum rustc-ap-graphviz 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bdd6f563273576220a075afefae7b9e20953c70e7cfe4b664ce1c240f88841" -"checksum rustc-ap-rustc_ast 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4b7aa06b8d9d6bf02075f91cdaf027cbce34aedd6ab5a6f4759de4c05de099" -"checksum rustc-ap-rustc_ast_pretty 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb9a73b0f1c632fd09dd02444efe753445de17da8ffb1df28adc5766a581ada" -"checksum rustc-ap-rustc_attr 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a420a672006a07f51cfc603ab394a066ccaf51323862c6b6b44bb673812df32" -"checksum rustc-ap-rustc_data_structures 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f224fd21a3c82b84e9914b4b1de31b0099e2083345c739285130017f5b2882" -"checksum rustc-ap-rustc_errors 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "312120a27c404bae22ed957b8d4e9cca2b872998558d227130aca9f3ff4edce9" -"checksum rustc-ap-rustc_feature 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7615aa561db78b1acacbedfa475e3ba5ed7071a33e5ede30d9660069be7b5e" -"checksum rustc-ap-rustc_fs_util 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ad7d6ee7fe47355214989c1638d9353344dfd2ac46eda5ac971533c543468d0" -"checksum rustc-ap-rustc_index 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a570533637a35eb7ed51de75a819a9f290fbd45b6cd4ca21e4ffe35ee2fcdf5" -"checksum rustc-ap-rustc_lexer 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47a9df68feec956275dfd12cdeadc46fc55e48859417e4301f2b330d680de96e" -"checksum rustc-ap-rustc_macros 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "623e619c676c376f079c4504a6047f76630bb3d23d1a6c4a4beee79158082c74" -"checksum rustc-ap-rustc_parse 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "465685a06a0a897cacd3c6bc6e0f50c79e1347cca9eb061361b5fa90ce46fb62" -"checksum rustc-ap-rustc_session 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf21db47cebe929bcac82f66da0faa1f38ace2091d6a887acdd87dcdfb7a823d" -"checksum rustc-ap-rustc_span 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7bb21edcd0e2603efee36ffb1bc4c08b7288478fe107159dbffed0ec8a894a1" -"checksum rustc-ap-rustc_target 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e8cb1a2d38583099f392c6ea8d3f77b1fc8368e4edfce1978d94c249dc9a828" -"checksum rustc-ap-serialize 647.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25317d226bf1d0243d4df231edcc9bf1c0e40c503ef0290cc7aa5658d3819915" +"checksum rustc-ap-arena 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7ba8774d4d5c8d42727c74836f478c51e0a16daeeee80017c133f9e1ebf4f6f" +"checksum rustc-ap-graphviz 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "feba68cc05f42d227b258e07a84df7d690d1f20200593754a789ab39acb581e5" +"checksum rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "989d221c292a3c777fc4921f87e4962d8d89633cf52a3a82f6f34d5b3d66efc7" +"checksum rustc-ap-rustc_ast_passes 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "865c0bddabe735c8f8116cf14239b41d5789e5c38d1c503888779721b98bdd9e" +"checksum rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "595c0092a2fa00dd0e572739279f771d96242f7626fc3999b4b027f08664417f" +"checksum rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be021d73b25feb33dc0aa91f91ff37b939a0ef54f9620684bc2846278b5e637" +"checksum rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a41551e5393a1abb4401e82f4e4bb64e097facb7d0362a1736b117186c0966dd" +"checksum rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8715e95fd29d92a7799f9c65cb5583485bbf902dda17900c884fbb7956d593d8" +"checksum rustc-ap-rustc_expand 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ecc53789a88bb89caf81a6572db077b8679450b384fc03bf797d8453f86354b" +"checksum rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6304d5df6f803f43d15a71d1c4b4aa6b68a01fe587ad62fcdfb83049e3ec77" +"checksum rustc-ap-rustc_fs_util 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c05da9f8dfd5c086465ad0263749453c13739226233c0354de5fc93b20204a" +"checksum rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1c292880ff00cd1e61710396f9379b2c99a533cfb1bc9c3274d566ada2c6027" +"checksum rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51e5ac7071163642ff52dda1bc41ff7464fcd832b5ea3fabf162569d26969410" +"checksum rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e147f23b65b716b58bd8687170914d3e2d2bfd004ec3fc8d2749e9d601482c0" +"checksum rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c5e12622f831b7344899229f2f776ff2cdd14f7f82b257d6bbcb79c850996298" +"checksum rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18fb72a26080a34d35c8dd7ba5ac593812c1c3f97edffe6f1bf30c1ef5c4c550" +"checksum rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe2d8db305496f9dc5f43408044735a942eadeeb2a28d6da8dd6b23b5ef60f93" +"checksum rustc-ap-rustc_target 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2797ddd7911ba6681f500fa0d5af651635bdc74813363a1216bafc6156cb3d2" +"checksum rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8567212bd0f0a93bbf3675e1ae819937e4a57d48b705522462c31ff8efc0604" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" diff --git a/Cargo.toml b/Cargo.toml index 18d3df1fa7c..ca816035a2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,32 +65,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "647.0.0" +version = "650.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "647.0.0" +version = "650.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "647.0.0" +version = "650.0.0" + +[dependencies.rustc_expand] +package = "rustc-ap-rustc_expand" +version = "650.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "647.0.0" +version = "650.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "647.0.0" +version = "650.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "647.0.0" +version = "650.0.0" [dependencies.rustc_target] package = "rustc-ap-rustc_target" -version = "647.0.0" +version = "650.0.0" [dependencies.syntax] package = "rustc-ap-rustc_ast" -version = "647.0.0" +version = "650.0.0" diff --git a/src/attr.rs b/src/attr.rs index b913d917b30..74195eb2a94 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -23,7 +23,7 @@ pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> Option<&[ast::Attribute]> ast::StmtKind::Local(ref local) => Some(&local.attrs), ast::StmtKind::Item(ref item) => Some(&item.attrs), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(&expr.attrs), - ast::StmtKind::Mac(ref mac) => Some(&mac.2), + ast::StmtKind::MacCall(ref mac) => Some(&mac.2), ast::StmtKind::Empty => None, } } @@ -33,7 +33,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { ast::StmtKind::Local(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, - ast::StmtKind::Mac(ref mac) => { + ast::StmtKind::MacCall(ref mac) => { let (ref mac, _, _) = **mac; mac.span() } diff --git a/src/chains.rs b/src/chains.rs index a7a9127cbbd..e8becfbab8a 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -403,7 +403,7 @@ impl Chain { fn convert_try(expr: &ast::Expr, context: &RewriteContext<'_>) -> ast::Expr { match expr.kind { - ast::ExprKind::Mac(ref mac) if context.config.use_try_shorthand() => { + ast::ExprKind::MacCall(ref mac) if context.config.use_try_shorthand() => { if let Some(subexpr) = convert_try_mac(mac, context) { subexpr } else { diff --git a/src/expr.rs b/src/expr.rs index 608425b34bd..6a581e6c054 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -199,7 +199,7 @@ pub(crate) fn format_expr( ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => { rewrite_chain(expr, context, shape) } - ast::ExprKind::Mac(ref mac) => { + ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { wrap_str( context.snippet(expr.span).to_owned(), @@ -1312,7 +1312,7 @@ pub(crate) fn can_be_overflowed_expr( context.config.overflow_delimited_expr() || (context.use_block_indent() && args_len == 1) } - ast::ExprKind::Mac(ref mac) => { + ast::ExprKind::MacCall(ref mac) => { match ( syntax::ast::MacDelimiter::from_token(mac.args.delim()), context.config.overflow_delimited_expr(), @@ -1340,7 +1340,7 @@ pub(crate) fn can_be_overflowed_expr( pub(crate) fn is_nested_call(expr: &ast::Expr) -> bool { match expr.kind { - ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true, + ast::ExprKind::Call(..) | ast::ExprKind::MacCall(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) | ast::ExprKind::Box(ref expr) | ast::ExprKind::Try(ref expr) diff --git a/src/formatting.rs b/src/formatting.rs index 104e631f441..583d72272f2 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -91,10 +91,11 @@ fn format_project( let files = modules::ModResolver::new( &context.parse_session, directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), - !(input_is_stdin || config.skip_children()), + !input_is_stdin && !config.skip_children(), ) .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + for (path, module) in files { let should_ignore = !input_is_stdin && context.ignore_file(&path); if (config.skip_children() && path != main_file) || should_ignore { diff --git a/src/items.rs b/src/items.rs index 9bd254250cc..31c1c193c4b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -645,7 +645,7 @@ impl<'a> FmtVisitor<'a> { { a.ident.as_str().cmp(&b.ident.as_str()) } - (Const(..), Const(..)) | (Macro(..), Macro(..)) => { + (Const(..), Const(..)) | (MacCall(..), MacCall(..)) => { a.ident.as_str().cmp(&b.ident.as_str()) } (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()), @@ -655,8 +655,8 @@ impl<'a> FmtVisitor<'a> { (_, TyAlias(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, (_, Const(..)) => Ordering::Greater, - (Macro(..), _) => Ordering::Less, - (_, Macro(..)) => Ordering::Greater, + (MacCall(..), _) => Ordering::Less, + (_, MacCall(..)) => Ordering::Greater, }); let mut prev_kind = None; for (buf, item) in buffer { @@ -868,10 +868,9 @@ fn format_impl_ref_and_type( let generics_str = rewrite_generics(context, "impl", generics, shape)?; result.push_str(&generics_str); - let polarity_str = if polarity == ast::ImplPolarity::Negative { - "!" - } else { - "" + let polarity_str = match polarity { + ast::ImplPolarity::Negative(_) => "!", + ast::ImplPolarity::Positive => "", }; if let Some(ref trait_ref) = *trait_ref { @@ -1730,7 +1729,7 @@ impl<'a> StaticParts<'a> { ty, mutability, expr_opt: expr.as_ref(), - defaultness: defaultness, + defaultness, span: item.span, } } @@ -3120,7 +3119,7 @@ impl Rewrite for ast::ForeignItem { rewrite_ident(context, self.ident) )) } - ast::ForeignItemKind::Macro(ref mac) => { + ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) } }?; diff --git a/src/macros.rs b/src/macros.rs index 482b680310c..240a33773c0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -187,7 +187,7 @@ fn return_macro_parse_failure_fallback( } pub(crate) fn rewrite_macro( - mac: &ast::Mac, + mac: &ast::MacCall, extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, @@ -239,7 +239,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { } fn rewrite_macro_inner( - mac: &ast::Mac, + mac: &ast::MacCall, extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, @@ -495,7 +495,7 @@ pub(crate) fn rewrite_macro_def( None => return snippet, }; - let mut result = if def.legacy { + let mut result = if def.macro_rules { String::from("macro_rules!") } else { format!("{}macro", format_visibility(context, vis)) @@ -504,7 +504,7 @@ pub(crate) fn rewrite_macro_def( result += " "; result += rewrite_ident(context, ident); - let multi_branch_style = def.legacy || parsed_def.branches.len() != 1; + let multi_branch_style = def.macro_rules || parsed_def.branches.len() != 1; let arm_shape = if multi_branch_style { shape @@ -537,7 +537,7 @@ pub(crate) fn rewrite_macro_def( .collect::>(); let fmt = ListFormatting::new(arm_shape, context.config) - .separator(if def.legacy { ";" } else { "" }) + .separator(if def.macro_rules { ";" } else { "" }) .trailing_separator(SeparatorTactic::Always) .preserve_newline(true); @@ -1186,7 +1186,7 @@ fn next_space(tok: &TokenKind) -> SpaceState { /// Tries to convert a macro use into a short hand try expression. Returns `None` /// when the macro is not an instance of `try!` (or parsing the inner expression /// failed). -pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { +pub(crate) fn convert_try_mac(mac: &ast::MacCall, context: &RewriteContext<'_>) -> Option { let path = &pprust::path_to_string(&mac.path); if path == "try" || path == "r#try" { let ts = mac.args.inner_tokens(); @@ -1203,7 +1203,7 @@ pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> O } } -pub(crate) fn macro_style(mac: &ast::Mac, context: &RewriteContext<'_>) -> DelimToken { +pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> DelimToken { let snippet = context.snippet(mac.span()); let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value()); let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value()); diff --git a/src/matches.rs b/src/matches.rs index 792b3bfd466..5f2d9d9e85e 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -559,7 +559,7 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool { | ast::ExprKind::Array(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Mac(..) + | ast::ExprKind::MacCall(..) | ast::ExprKind::Struct(..) | ast::ExprKind::Tup(..) => true, ast::ExprKind::AddrOf(_, _, ref expr) diff --git a/src/modules.rs b/src/modules.rs index bb0effedfa8..b7e110d6013 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -32,7 +32,7 @@ pub(crate) struct ModResolver<'ast, 'sess> { #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` - External(PathBuf, DirectoryOwnership), + External(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>), /// `mod foo;` with multiple sources. MultiExternal(Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)>), /// `#[path = "..."] mod foo {}` @@ -82,7 +82,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Visit `cfg_if` macro and look for module declarations. fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { - let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess, &self.directory); + let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { @@ -150,7 +150,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { // mod foo; // Look for an extern file. self.find_external_module(item.ident, &item.attrs, sub_mod) - .map(Some) } else { // An internal module (`mod foo { /* ... */ }`); if let Some(path) = find_path_value(&item.attrs) { @@ -165,15 +164,19 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn insert_sub_mod( &mut self, sub_mod_kind: SubModKind<'c, 'ast>, - sub_mod: Cow<'ast, ast::Mod>, + _sub_mod: Cow<'ast, ast::Mod>, ) -> Result<(), String> { match sub_mod_kind { - SubModKind::External(mod_path, _) => { - self.file_map.insert(FileName::Real(mod_path), sub_mod); + SubModKind::External(mod_path, _, sub_mod) => { + self.file_map + .entry(FileName::Real(mod_path)) + .or_insert(sub_mod); } SubModKind::MultiExternal(mods) => { for (mod_path, _, sub_mod) in mods { - self.file_map.insert(FileName::Real(mod_path), sub_mod); + self.file_map + .entry(FileName::Real(mod_path)) + .or_insert(sub_mod); } } _ => (), @@ -187,7 +190,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { sub_mod_kind: SubModKind<'c, 'ast>, ) -> Result<(), String> { match sub_mod_kind { - SubModKind::External(mod_path, directory_ownership) => { + SubModKind::External(mod_path, directory_ownership, sub_mod) => { let directory = Directory { path: mod_path.parent().unwrap().to_path_buf(), ownership: directory_ownership, @@ -239,43 +242,97 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mod_name: ast::Ident, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, - ) -> Result, String> { + ) -> Result>, String> { + let relative = match self.directory.ownership { + DirectoryOwnership::Owned { relative } => relative, + DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + }; if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) { - return Ok(SubModKind::External( - path, - DirectoryOwnership::Owned { relative: None }, - )); + if self.parse_sess.is_file_parsed(&path) { + return Ok(None); + } + return match Parser::parse_file_as_module( + self.parse_sess, + &path, + sub_mod.inner, + ) { + Some(m) => Ok(Some(SubModKind::External( + path, + DirectoryOwnership::Owned { relative: None }, + Cow::Owned(m), + ))), + None => Err(format!( + "Failed to find module {} in {:?} {:?}", + mod_name, self.directory.path, relative, + )), + }; } // Look for nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. let mut mods_outside_ast = self.find_mods_outside_of_ast(attrs, sub_mod); - let relative = match self.directory.ownership { - DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, - }; match self .parse_sess .default_submod_path(mod_name, relative, &self.directory.path) .result { Ok(ModulePathSuccess { - path, - directory_ownership, - .. - }) => Ok(if mods_outside_ast.is_empty() { - SubModKind::External(path, directory_ownership) - } else { - mods_outside_ast.push((path, directory_ownership, sub_mod.clone())); - SubModKind::MultiExternal(mods_outside_ast) - }), - Err(_) if !mods_outside_ast.is_empty() => { - Ok(SubModKind::MultiExternal(mods_outside_ast)) + path, ownership, .. + }) => { + let outside_mods_empty = mods_outside_ast.is_empty(); + let should_insert = !mods_outside_ast + .iter() + .any(|(outside_path, _, _)| outside_path == &path); + if self.parse_sess.is_file_parsed(&path) { + if outside_mods_empty { + return Ok(None); + } else { + if should_insert { + mods_outside_ast.push((path, ownership, sub_mod.clone())); + } + return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); + } + } + match Parser::parse_file_as_module( + self.parse_sess, + &path, + sub_mod.inner, + ) { + Some(m) if outside_mods_empty => Ok(Some(SubModKind::External( + path, + ownership, + Cow::Owned(m), + ))), + Some(m) => { + mods_outside_ast.push((path.clone(), ownership, Cow::Owned(m))); + if should_insert { + mods_outside_ast.push((path, ownership, sub_mod.clone())); + } + Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) + } + None if outside_mods_empty => Err(format!( + "Failed to find module {} in {:?} {:?}", + mod_name, self.directory.path, relative, + )), + None => { + if should_insert { + mods_outside_ast.push((path, ownership, sub_mod.clone())); + } + Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) + }, + } + } + Err(mut e) if !mods_outside_ast.is_empty() => { + e.cancel(); + Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) + } + Err(mut e) => { + e.cancel(); + Err(format!( + "Failed to find module {} in {:?} {:?}", + mod_name, self.directory.path, relative, + )) } - Err(_) => Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )), } } @@ -329,9 +386,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { continue; } let m = match Parser::parse_file_as_module( - self.directory.ownership, self.parse_sess, &actual_path, + sub_mod.inner, ) { Some(m) => m, None => continue, @@ -364,7 +421,7 @@ fn find_path_value(attrs: &[ast::Attribute]) -> Option { fn is_cfg_if(item: &ast::Item) -> bool { match item.kind { - ast::ItemKind::Mac(ref mac) => { + ast::ItemKind::MacCall(ref mac) => { if let Some(first_segment) = mac.path.segments.first() { if first_segment.ident.name == *CFG_IF { return true; diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index ad9111f7a9f..b4d32747b17 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax::visit::Visitor; use crate::attr::MetaVisitor; -use crate::syntux::parser::{Directory, Parser}; +use crate::syntux::parser::Parser; use crate::syntux::session::ParseSess; pub(crate) struct ModItem { @@ -14,15 +14,13 @@ pub(crate) struct ModItem { pub(crate) struct CfgIfVisitor<'a> { parse_sess: &'a ParseSess, mods: Vec, - base_dir: &'a Directory, } impl<'a> CfgIfVisitor<'a> { - pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: &'a Directory) -> CfgIfVisitor<'a> { + pub(crate) fn new(parse_sess: &'a ParseSess) -> CfgIfVisitor<'a> { CfgIfVisitor { mods: vec![], parse_sess, - base_dir, } } @@ -32,7 +30,7 @@ impl<'a> CfgIfVisitor<'a> { } impl<'a, 'ast: 'a> Visitor<'ast> for CfgIfVisitor<'a> { - fn visit_mac(&mut self, mac: &'ast ast::Mac) { + fn visit_mac(&mut self, mac: &'ast ast::MacCall) { match self.visit_mac_inner(mac) { Ok(()) => (), Err(e) => debug!("{}", e), @@ -41,7 +39,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CfgIfVisitor<'a> { } impl<'a, 'ast: 'a> CfgIfVisitor<'a> { - fn visit_mac_inner(&mut self, mac: &'ast ast::Mac) -> Result<(), &'static str> { + fn visit_mac_inner(&mut self, mac: &'ast ast::MacCall) -> Result<(), &'static str> { // Support both: // ``` // extern crate cfg_if; @@ -64,7 +62,7 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } }; - let items = Parser::parse_cfg_if(self.parse_sess, mac, &self.base_dir)?; + let items = Parser::parse_cfg_if(self.parse_sess, mac)?; self.mods .append(&mut items.into_iter().map(|item| ModItem { item }).collect()); diff --git a/src/patterns.rs b/src/patterns.rs index 1ef3bd5337b..0c57f111761 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -40,7 +40,7 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { ast::PatKind::Rest | ast::PatKind::Wild | ast::PatKind::Lit(_) => true, ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Struct(..) - | ast::PatKind::Mac(..) + | ast::PatKind::MacCall(..) | ast::PatKind::Slice(..) | ast::PatKind::Path(..) | ast::PatKind::Range(..) => false, @@ -231,7 +231,7 @@ impl Rewrite for Pat { PatKind::Struct(ref path, ref fields, ellipsis) => { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } - PatKind::Mac(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), + PatKind::MacCall(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), PatKind::Paren(ref pat) => pat .rewrite(context, shape.offset_left(1)?.sub_width(1)?) .map(|inner_pat| format!("({})", inner_pat)), diff --git a/src/spanned.rs b/src/spanned.rs index 324594f7760..618a8b179fd 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -66,7 +66,7 @@ impl Spanned for ast::Stmt { ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo(), self.span.hi()) } - ast::StmtKind::Mac(ref mac) => { + ast::StmtKind::MacCall(ref mac) => { let (_, _, ref attrs) = **mac; if attrs.is_empty() { self.span diff --git a/src/stmt.rs b/src/stmt.rs index c9bfe64d59d..30006512906 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -106,7 +106,7 @@ fn format_stmt( let shape = shape.sub_width(suffix.len())?; format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } - ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, + ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, }; result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) } diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 6e3cd5e2375..7859c9e38aa 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -2,16 +2,16 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; use rustc_errors::{Diagnostic, PResult}; -use rustc_parse::{new_sub_parser_from_file, parser::Parser as RawParser}; -use rustc_span::{symbol::kw, Span, DUMMY_SP}; +use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; +use rustc_span::{symbol::kw, Span}; use syntax::ast; use syntax::token::{DelimToken, TokenKind}; use crate::syntux::session::ParseSess; use crate::{Config, Input}; -pub(crate) type DirectoryOwnership = rustc_parse::DirectoryOwnership; -pub(crate) type ModulePathSuccess = rustc_parse::parser::ModulePathSuccess; +pub(crate) type DirectoryOwnership = rustc_expand::module::DirectoryOwnership; +pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess; #[derive(Clone)] pub(crate) struct Directory { @@ -19,15 +19,6 @@ pub(crate) struct Directory { pub(crate) ownership: DirectoryOwnership, } -impl<'a> Directory { - fn to_syntax_directory(&'a self) -> rustc_parse::Directory { - rustc_parse::Directory { - path: self.path.clone(), - ownership: self.ownership, - } - } -} - /// A parser for Rust source code. pub(crate) struct Parser<'a> { parser: RawParser<'a>, @@ -68,11 +59,10 @@ impl<'a> ParserBuilder<'a> { } pub(crate) fn build(self) -> Result, ParserError> { - let config = self.config.ok_or(ParserError::NoConfig)?; let sess = self.sess.ok_or(ParserError::NoParseSess)?; let input = self.input.ok_or(ParserError::NoInput)?; - let mut parser = match Self::parser(sess.inner(), input, self.directory_ownership) { + let parser = match Self::parser(sess.inner(), input) { Ok(p) => p, Err(db) => { sess.emit_diagnostics(db); @@ -80,47 +70,26 @@ impl<'a> ParserBuilder<'a> { } }; - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - Ok(Parser { parser, sess }) } fn parser( sess: &'a rustc_session::parse::ParseSess, input: Input, - directory_ownership: Option, ) -> Result, Vec> { match input { - Input::File(ref file) => Ok(if let Some(directory_ownership) = directory_ownership { - rustc_parse::new_sub_parser_from_file( - sess, - file, - directory_ownership, - None, - DUMMY_SP, - ) - } else { - rustc_parse::new_parser_from_file(sess, file) - }), + Input::File(ref file) => Ok(new_parser_from_file(sess, file, None)), Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( sess, rustc_span::FileName::Custom("stdin".to_owned()), text, - ) - .map(|mut parser| { - parser.recurse_into_file_modules = false; - parser - }), + ), } } } #[derive(Debug, PartialEq)] pub(crate) enum ParserError { - NoConfig, NoParseSess, NoInput, ParserCreationError, @@ -130,7 +99,7 @@ pub(crate) enum ParserError { impl<'a> Parser<'a> { pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { - rustc_parse::parser::Parser::submod_path_from_attr(attrs, path) + rustc_expand::module::submod_path_from_attr(attrs, path) } // FIXME(topecongiro) Use the method from libsyntax[1] once it become public. @@ -176,6 +145,11 @@ impl<'a> Parser<'a> { items.push(item); } + // Handle extern mods that are empty files/files with only comments. + if items.is_empty() { + parser.parse_mod(&TokenKind::Eof)?; + } + let hi = if parser.token.span.is_dummy() { span } else { @@ -190,15 +164,13 @@ impl<'a> Parser<'a> { } pub(crate) fn parse_file_as_module( - directory_ownership: DirectoryOwnership, sess: &'a ParseSess, path: &Path, + span: Span, ) -> Option { - let result = catch_unwind(AssertUnwindSafe(|| { - let mut parser = - new_sub_parser_from_file(sess.inner(), &path, directory_ownership, None, DUMMY_SP); + let result = catch_unwind(AssertUnwindSafe(|| { + let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); - parser.cfg_mods = false; let lo = parser.token.span; // FIXME(topecongiro) Format inner attributes (#3606). match Parser::parse_inner_attrs(&mut parser) { @@ -267,11 +239,10 @@ impl<'a> Parser<'a> { pub(crate) fn parse_cfg_if( sess: &'a ParseSess, - mac: &'a ast::Mac, - base_dir: &Directory, + mac: &'a ast::MacCall, ) -> Result, &'static str> { match catch_unwind(AssertUnwindSafe(|| { - Parser::parse_cfg_if_inner(sess, mac, base_dir) + Parser::parse_cfg_if_inner(sess, mac) })) { Ok(Ok(items)) => Ok(items), Ok(err @ Err(_)) => err, @@ -281,17 +252,11 @@ impl<'a> Parser<'a> { fn parse_cfg_if_inner( sess: &'a ParseSess, - mac: &'a ast::Mac, - base_dir: &Directory, + mac: &'a ast::MacCall, ) -> Result, &'static str> { let token_stream = mac.args.inner_tokens(); - let mut parser = rustc_parse::stream_to_parser_with_base_dir( - sess.inner(), - token_stream.clone(), - base_dir.to_syntax_directory(), - ); + let mut parser = rustc_parse::stream_to_parser(sess.inner(),token_stream.clone(),Some("")); - parser.cfg_mods = false; let mut items = vec![]; let mut process_if_cfg = true; diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 9ec85efb109..0e6b0073793 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -150,12 +150,13 @@ impl ParseSess { id: ast::Ident, relative: Option, dir_path: &Path, - ) -> rustc_parse::parser::ModulePath { - rustc_parse::parser::Parser::default_submod_path( + ) -> rustc_expand::module::ModulePath<'_> { + rustc_expand::module::default_submod_path( + &self.parse_sess, id, + rustc_span::DUMMY_SP, relative, dir_path, - self.parse_sess.source_map(), ) } diff --git a/src/types.rs b/src/types.rs index d30693fd388..500ccaf6275 100644 --- a/src/types.rs +++ b/src/types.rs @@ -732,7 +732,7 @@ impl Rewrite for ast::Ty { } ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Some(String::from("!")), - ast::TyKind::Mac(ref mac) => { + ast::TyKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Some(String::from("")), diff --git a/src/utils.rs b/src/utils.rs index 7e287a4b80a..494d4d0e33f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -456,7 +456,7 @@ pub(crate) fn first_line_ends_with(s: &str, c: char) -> bool { // parens, braces, and brackets in its idiomatic formatting. pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool { match expr.kind { - ast::ExprKind::Mac(..) + ast::ExprKind::MacCall(..) | ast::ExprKind::Call(..) | ast::ExprKind::MethodCall(..) | ast::ExprKind::Array(..) diff --git a/src/visitor.rs b/src/visitor.rs index fe489f32a16..7dd594a304f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -151,7 +151,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(stmt.span(), rewrite) } } - ast::StmtKind::Mac(ref mac) => { + ast::StmtKind::MacCall(ref mac) => { let (ref mac, _macro_style, ref attrs) = **mac; if self.visit_attrs(attrs, ast::AttrStyle::Outer) { self.push_skipped_with_span( @@ -504,7 +504,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.format_missing_with_indent(source!(self, item.span).lo()); self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); } - ast::ItemKind::Mac(ref mac) => { + ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); } ast::ItemKind::ForeignMod(ref foreign_mod) => { @@ -619,7 +619,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(ti.span, rewrite); } - ast::AssocItemKind::Macro(ref mac) => { + ast::AssocItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(ti.ident), MacroPosition::Item); } } @@ -669,7 +669,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(generic_bounds) => rewrite_opaque_impl_type( &self.get_context(), ii.ident, - &generics, + generics, generic_bounds, self.block_indent, ), @@ -678,13 +678,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { }; self.push_rewrite(ii.span, rewrite); } - ast::AssocItemKind::Macro(ref mac) => { + ast::AssocItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(ii.ident), MacroPosition::Item); } } } - fn visit_mac(&mut self, mac: &ast::Mac, ident: Option, pos: MacroPosition) { + fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; -- cgit 1.4.1-3-g733a5 From bea7209d0a7e7cfe713f1dcd1250810348cb528e Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Mar 2020 21:47:03 -0500 Subject: chore: fix src formatting --- src/macros.rs | 5 ++++- src/modules.rs | 29 ++++++++--------------------- src/patterns.rs | 4 +++- src/syntux/parser.rs | 9 ++++----- 4 files changed, 19 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 240a33773c0..ffc6a7a66dc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1186,7 +1186,10 @@ fn next_space(tok: &TokenKind) -> SpaceState { /// Tries to convert a macro use into a short hand try expression. Returns `None` /// when the macro is not an instance of `try!` (or parsing the inner expression /// failed). -pub(crate) fn convert_try_mac(mac: &ast::MacCall, context: &RewriteContext<'_>) -> Option { +pub(crate) fn convert_try_mac( + mac: &ast::MacCall, + context: &RewriteContext<'_>, +) -> Option { let path = &pprust::path_to_string(&mac.path); if path == "try" || path == "r#try" { let ts = mac.args.inner_tokens(); diff --git a/src/modules.rs b/src/modules.rs index b7e110d6013..4ea41cd14f4 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -251,11 +251,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if self.parse_sess.is_file_parsed(&path) { return Ok(None); } - return match Parser::parse_file_as_module( - self.parse_sess, - &path, - sub_mod.inner, - ) { + return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { Some(m) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, @@ -293,16 +289,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module( - self.parse_sess, - &path, - sub_mod.inner, - ) { - Some(m) if outside_mods_empty => Ok(Some(SubModKind::External( - path, - ownership, - Cow::Owned(m), - ))), + match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { + Some(m) if outside_mods_empty => { + Ok(Some(SubModKind::External(path, ownership, Cow::Owned(m)))) + } Some(m) => { mods_outside_ast.push((path.clone(), ownership, Cow::Owned(m))); if should_insert { @@ -319,7 +309,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mods_outside_ast.push((path, ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) - }, + } } } Err(mut e) if !mods_outside_ast.is_empty() => { @@ -385,11 +375,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - let m = match Parser::parse_file_as_module( - self.parse_sess, - &actual_path, - sub_mod.inner, - ) { + let m = match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.inner) + { Some(m) => m, None => continue, }; diff --git a/src/patterns.rs b/src/patterns.rs index 0c57f111761..1f13fa6db60 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -231,7 +231,9 @@ impl Rewrite for Pat { PatKind::Struct(ref path, ref fields, ellipsis) => { rewrite_struct_pat(path, fields, ellipsis, self.span, context, shape) } - PatKind::MacCall(ref mac) => rewrite_macro(mac, None, context, shape, MacroPosition::Pat), + PatKind::MacCall(ref mac) => { + rewrite_macro(mac, None, context, shape, MacroPosition::Pat) + } PatKind::Paren(ref pat) => pat .rewrite(context, shape.offset_left(1)?.sub_width(1)?) .map(|inner_pat| format!("({})", inner_pat)), diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 7859c9e38aa..91f9def15cb 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -168,7 +168,7 @@ impl<'a> Parser<'a> { path: &Path, span: Span, ) -> Option { - let result = catch_unwind(AssertUnwindSafe(|| { + let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); let lo = parser.token.span; @@ -241,9 +241,7 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, mac: &'a ast::MacCall, ) -> Result, &'static str> { - match catch_unwind(AssertUnwindSafe(|| { - Parser::parse_cfg_if_inner(sess, mac) - })) { + match catch_unwind(AssertUnwindSafe(|| Parser::parse_cfg_if_inner(sess, mac))) { Ok(Ok(items)) => Ok(items), Ok(err @ Err(_)) => err, Err(..) => Err("failed to parse cfg_if!"), @@ -255,7 +253,8 @@ impl<'a> Parser<'a> { mac: &'a ast::MacCall, ) -> Result, &'static str> { let token_stream = mac.args.inner_tokens(); - let mut parser = rustc_parse::stream_to_parser(sess.inner(),token_stream.clone(),Some("")); + let mut parser = + rustc_parse::stream_to_parser(sess.inner(), token_stream.clone(), Some("")); let mut items = vec![]; let mut process_if_cfg = true; -- cgit 1.4.1-3-g733a5 From 537d746e08dc7feda17e07a3cf4442837aec0030 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Mar 2020 22:00:00 -0500 Subject: fix: use correct ForeignItem span --- src/items.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 31c1c193c4b..04bef1cef5f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -298,8 +298,14 @@ impl<'a> FmtVisitor<'a> { fn format_foreign_item(&mut self, item: &ast::ForeignItem) { let rewrite = item.rewrite(&self.get_context(), self.shape()); - self.push_rewrite(item.span, rewrite); - self.last_pos = item.span.hi(); + let hi = item.span.hi(); + let span = if item.attrs.is_empty() { + item.span + } else { + mk_sp(item.attrs[0].span.lo(), hi) + }; + self.push_rewrite(span, rewrite); + self.last_pos = hi; } pub(crate) fn rewrite_fn_before_block( -- cgit 1.4.1-3-g733a5 From c1a66e1e223db7687c28359d95f7a218283b796f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Mar 2020 22:13:46 -0500 Subject: fix: unreachable err on Fn with `None` block --- src/visitor.rs | 16 ++++++++++++++-- tests/source/issue_4057.rs | 15 +++++++++++++++ tests/target/issue-4068.rs | 3 +++ tests/target/issue_4057.rs | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/source/issue_4057.rs create mode 100644 tests/target/issue-4068.rs create mode 100644 tests/target/issue_4057.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index 7dd594a304f..593e3ac6a21 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -514,7 +514,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::Fn(defaultness, ref fn_signature, ref generics, ref body) => { + ast::ItemKind::Fn(defaultness, ref fn_signature, ref generics, Some(ref body)) => { let inner_attrs = inner_attributes(&item.attrs); let fn_ctxt = match fn_signature.header.ext { ast::Extern::None => visit::FnCtxt::Free, @@ -526,7 +526,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item.ident, &fn_signature, &item.vis, - body.as_deref(), + Some(body), ), generics, &fn_signature.decl, @@ -535,6 +535,18 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { Some(&inner_attrs), ) } + ast::ItemKind::Fn(_, ref fn_signature, ref generics, None) => { + let indent = self.block_indent; + let rewrite = self.rewrite_required_fn( + indent, + item.ident, + &fn_signature, + generics, + item.span, + ); + + self.push_rewrite(item.span, rewrite); + } ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty { Some(ty) => { let rewrite = rewrite_type_alias( diff --git a/tests/source/issue_4057.rs b/tests/source/issue_4057.rs new file mode 100644 index 00000000000..7cd80734bd9 --- /dev/null +++ b/tests/source/issue_4057.rs @@ -0,0 +1,15 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// # #[rustversion::since(1.36)] +/// # fn dox() { +/// # use std::pin::Pin; +/// # type Projection<'a> = &'a (); +/// # type ProjectionRef<'a> = &'a (); +/// # trait Dox { +/// fn project_ex (self: Pin<&mut Self>) -> Projection<'_>; +/// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>; +/// # } +/// # } +/// ``` +struct Foo; diff --git a/tests/target/issue-4068.rs b/tests/target/issue-4068.rs new file mode 100644 index 00000000000..cd8a1f2765f --- /dev/null +++ b/tests/target/issue-4068.rs @@ -0,0 +1,3 @@ +fn main() { + extern "C" fn packet_records_options_impl_layout_length_encoding_option_len_multiplier(); +} diff --git a/tests/target/issue_4057.rs b/tests/target/issue_4057.rs new file mode 100644 index 00000000000..467e67bca7c --- /dev/null +++ b/tests/target/issue_4057.rs @@ -0,0 +1,15 @@ +// rustfmt-format_code_in_doc_comments: true + +/// ``` +/// # #[rustversion::since(1.36)] +/// # fn dox() { +/// # use std::pin::Pin; +/// # type Projection<'a> = &'a (); +/// # type ProjectionRef<'a> = &'a (); +/// # trait Dox { +/// fn project_ex(self: Pin<&mut Self>) -> Projection<'_>; +/// fn project_ref(self: Pin<&Self>) -> ProjectionRef<'_>; +/// # } +/// # } +/// ``` +struct Foo; -- cgit 1.4.1-3-g733a5 From b173b42354ec8d77d1613de383c9a0ea801f9a9d Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Mar 2020 22:29:12 -0500 Subject: refactor: rename libsyntax --> rustc_ast --- Cargo.toml | 8 ++++---- src/attr.rs | 2 +- src/chains.rs | 2 +- src/closures.rs | 2 +- src/expr.rs | 6 +++--- src/formatting.rs | 4 ++-- src/imports.rs | 2 +- src/items.rs | 16 ++++++++-------- src/lib.rs | 2 +- src/macros.rs | 6 +++--- src/matches.rs | 2 +- src/modules.rs | 4 ++-- src/modules/visitor.rs | 4 ++-- src/overflow.rs | 4 ++-- src/pairs.rs | 2 +- src/patterns.rs | 4 ++-- src/reorder.rs | 2 +- src/rewrite.rs | 2 +- src/skip.rs | 4 ++-- src/spanned.rs | 2 +- src/stmt.rs | 2 +- src/syntux/parser.rs | 8 ++++---- src/syntux/session.rs | 2 +- src/types.rs | 4 ++-- src/utils.rs | 12 ++++++------ src/vertical.rs | 2 +- src/visitor.rs | 4 ++-- tests/source/imports.rs | 16 ++++++++-------- tests/target/imports.rs | 10 +++++----- 29 files changed, 70 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index ca816035a2a..cfb750c0a8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,6 +63,10 @@ lazy_static = "1.0.0" # for more information. rustc-workspace-hack = "1.0.0" +[dependencies.rustc_ast] +package = "rustc-ap-rustc_ast" +version = "650.0.0" + [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" version = "650.0.0" @@ -94,7 +98,3 @@ version = "650.0.0" [dependencies.rustc_target] package = "rustc-ap-rustc_target" version = "650.0.0" - -[dependencies.syntax] -package = "rustc-ap-rustc_ast" -version = "650.0.0" diff --git a/src/attr.rs b/src/attr.rs index 74195eb2a94..5221caf2fad 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,7 +1,7 @@ //! Format attributes and meta items. +use rustc_ast::ast; use rustc_span::{symbol::sym, BytePos, Span, DUMMY_SP}; -use syntax::ast; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; diff --git a/src/chains.rs b/src/chains.rs index e8becfbab8a..32bcf0e0999 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -58,8 +58,8 @@ use std::borrow::Cow; use std::cmp::min; +use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use syntax::{ast, ptr}; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use crate::config::IndentStyle; diff --git a/src/closures.rs b/src/closures.rs index 625ef4a81f9..55a96a5c68a 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,5 +1,5 @@ +use rustc_ast::{ast, ptr}; use rustc_span::Span; -use syntax::{ast, ptr}; use crate::attr::get_attrs_from_stmt; use crate::config::lists::*; diff --git a/src/expr.rs b/src/expr.rs index 6a581e6c054..d63961449f8 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -2,9 +2,9 @@ use std::borrow::Cow; use std::cmp::min; use itertools::Itertools; +use rustc_ast::token::{DelimToken, LitKind}; +use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use syntax::token::{DelimToken, LitKind}; -use syntax::{ast, ptr}; use crate::chains::rewrite_chain; use crate::closures; @@ -1314,7 +1314,7 @@ pub(crate) fn can_be_overflowed_expr( } ast::ExprKind::MacCall(ref mac) => { match ( - syntax::ast::MacDelimiter::from_token(mac.args.delim()), + rustc_ast::ast::MacDelimiter::from_token(mac.args.delim()), context.config.overflow_delimited_expr(), ) { (Some(ast::MacDelimiter::Bracket), true) diff --git a/src/formatting.rs b/src/formatting.rs index 583d72272f2..8178342f28c 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -4,8 +4,8 @@ use std::collections::HashMap; use std::io::{self, Write}; use std::time::{Duration, Instant}; +use rustc_ast::ast; use rustc_span::Span; -use syntax::ast; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; @@ -29,7 +29,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::VersionMismatch); } - syntax::with_globals(self.config.edition().to_libsyntax_pos_edition(), || { + rustc_ast::with_globals(self.config.edition().to_libsyntax_pos_edition(), || { if self.config.disable_all_formatting() { // When the input is from stdin, echo back the input. if let Input::Text(ref buf) = input { diff --git a/src/imports.rs b/src/imports.rs index 9c914ce476d..d8f963e1ec3 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -2,8 +2,8 @@ use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; +use rustc_ast::ast::{self, UseTreeKind}; use rustc_span::{source_map, symbol::sym, BytePos, Span, DUMMY_SP}; -use syntax::ast::{self, UseTreeKind}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; diff --git a/src/items.rs b/src/items.rs index 04bef1cef5f..baa993590ca 100644 --- a/src/items.rs +++ b/src/items.rs @@ -4,9 +4,9 @@ use std::borrow::Cow; use std::cmp::{max, min, Ordering}; use regex::Regex; +use rustc_ast::visit; +use rustc_ast::{ast, ptr}; use rustc_span::{source_map, symbol, BytePos, Span, DUMMY_SP}; -use syntax::visit; -use syntax::{ast, ptr}; use crate::attr::filter_inline_attrs; use crate::comment::{ @@ -594,7 +594,7 @@ impl<'a> FmtVisitor<'a> { self.buffer.clear(); } - fn is_type(ty: &Option>) -> bool { + fn is_type(ty: &Option>) -> bool { match ty { None => true, Some(lty) => match lty.kind.opaque_top_hack() { @@ -604,7 +604,7 @@ impl<'a> FmtVisitor<'a> { } } - fn is_opaque(ty: &Option>) -> bool { + fn is_opaque(ty: &Option>) -> bool { match ty { None => false, Some(lty) => match lty.kind.opaque_top_hack() { @@ -615,15 +615,15 @@ impl<'a> FmtVisitor<'a> { } fn both_type( - a: &Option>, - b: &Option>, + a: &Option>, + b: &Option>, ) -> bool { is_type(a) && is_type(b) } fn both_opaque( - a: &Option>, - b: &Option>, + a: &Option>, + b: &Option>, ) -> bool { is_opaque(a) && is_opaque(b) } diff --git a/src/lib.rs b/src/lib.rs index dbd9469908e..ecf19ebb586 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ use std::rc::Rc; use failure::Fail; use ignore; -use syntax::ast; +use rustc_ast::ast; use crate::comment::LineClasses; use crate::emitter::Emitter; diff --git a/src/macros.rs b/src/macros.rs index ffc6a7a66dc..400daa6a5aa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -12,12 +12,12 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; +use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; +use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; +use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::{new_parser_from_tts, parser::Parser}; use rustc_span::{symbol::kw, BytePos, Span, Symbol, DUMMY_SP}; -use syntax::token::{BinOpToken, DelimToken, Token, TokenKind}; -use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; -use syntax::{ast, ptr}; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, diff --git a/src/matches.rs b/src/matches.rs index 5f2d9d9e85e..c6b17122326 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,8 +2,8 @@ use std::iter::repeat; +use rustc_ast::{ast, ptr}; use rustc_span::{BytePos, Span}; -use syntax::{ast, ptr}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; diff --git a/src/modules.rs b/src/modules.rs index 4ea41cd14f4..9f8dabbfaf4 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -2,9 +2,9 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::path::{Path, PathBuf}; +use rustc_ast::ast; +use rustc_ast::visit::Visitor; use rustc_span::symbol::{sym, Symbol}; -use syntax::ast; -use syntax::visit::Visitor; use crate::attr::MetaVisitor; use crate::config::FileName; diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index b4d32747b17..942e70d0e88 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -1,6 +1,6 @@ +use rustc_ast::ast; +use rustc_ast::visit::Visitor; use rustc_span::Symbol; -use syntax::ast; -use syntax::visit::Visitor; use crate::attr::MetaVisitor; use crate::syntux::parser::Parser; diff --git a/src/overflow.rs b/src/overflow.rs index 0ef1db20fa1..566f0e36639 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -3,9 +3,9 @@ use std::cmp::min; use itertools::Itertools; +use rustc_ast::token::DelimToken; +use rustc_ast::{ast, ptr}; use rustc_span::Span; -use syntax::token::DelimToken; -use syntax::{ast, ptr}; use crate::closures; use crate::config::lists::*; diff --git a/src/pairs.rs b/src/pairs.rs index 45132c1f9f6..0f3d5e8f878 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -1,4 +1,4 @@ -use syntax::ast; +use rustc_ast::ast; use crate::config::lists::*; use crate::config::IndentStyle; diff --git a/src/patterns.rs b/src/patterns.rs index 1f13fa6db60..78292620232 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,6 +1,6 @@ +use rustc_ast::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; +use rustc_ast::ptr; use rustc_span::{BytePos, Span}; -use syntax::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; -use syntax::ptr; use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; use crate::config::lists::*; diff --git a/src/reorder.rs b/src/reorder.rs index 0235e552be7..3b9f2475acc 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -8,8 +8,8 @@ use std::cmp::{Ord, Ordering}; +use rustc_ast::{ast, attr}; use rustc_span::{symbol::sym, Span}; -use syntax::{ast, attr}; use crate::config::Config; use crate::imports::{merge_use_trees, UseTree}; diff --git a/src/rewrite.rs b/src/rewrite.rs index f73602f09a2..86b2e9ded1c 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -3,8 +3,8 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; +use rustc_ast::ptr; use rustc_span::Span; -use syntax::ptr; use crate::config::{Config, IndentStyle}; use crate::shape::Shape; diff --git a/src/skip.rs b/src/skip.rs index 4972eb8c778..fd48e67ee73 100644 --- a/src/skip.rs +++ b/src/skip.rs @@ -1,7 +1,7 @@ //! Module that contains skip related stuffs. +use rustc_ast::ast; use rustc_ast_pretty::pprust; -use syntax::ast; /// Take care of skip name stack. You can update it by attributes slice or /// by other context. Query this context to know if you need skip a block. @@ -56,7 +56,7 @@ fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec { let mut skip_names = vec![]; let path = format!("{}::{}::{}", RUSTFMT, SKIP, kind); for attr in attrs { - // syntax::ast::Path is implemented partialEq + // rustc_ast::ast::Path is implemented partialEq // but it is designed for segments.len() == 1 if let ast::AttrKind::Normal(attr_item) = &attr.kind { if pprust::path_to_string(&attr_item.path) != path { diff --git a/src/spanned.rs b/src/spanned.rs index 618a8b179fd..60a350524fa 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -1,7 +1,7 @@ use std::cmp::max; +use rustc_ast::{ast, ptr}; use rustc_span::{source_map, Span}; -use syntax::{ast, ptr}; use crate::macros::MacroArg; use crate::utils::{mk_sp, outer_attributes}; diff --git a/src/stmt.rs b/src/stmt.rs index 30006512906..807cd9e5fad 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -1,5 +1,5 @@ +use rustc_ast::ast; use rustc_span::Span; -use syntax::ast; use crate::comment::recover_comment_removed; use crate::config::Version; diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 91f9def15cb..04a6f7577a0 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -1,11 +1,11 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; +use rustc_ast::ast; +use rustc_ast::token::{DelimToken, TokenKind}; use rustc_errors::{Diagnostic, PResult}; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{symbol::kw, Span}; -use syntax::ast; -use syntax::token::{DelimToken, TokenKind}; use crate::syntux::session::ParseSess; use crate::{Config, Input}; @@ -121,8 +121,8 @@ impl<'a> Parser<'a> { } TokenKind::DocComment(s) => { // we need to get the position of this token before we bump. - let attr = syntax::attr::mk_doc_comment( - syntax::util::comments::doc_comment_style(&s.as_str()), + let attr = rustc_ast::attr::mk_doc_comment( + rustc_ast::util::comments::doc_comment_style(&s.as_str()), s, parser.token.span, ); diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 0e6b0073793..da8741c84e5 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::path::Path; use std::rc::Rc; +use rustc_ast::ast; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; @@ -10,7 +11,6 @@ use rustc_span::{ source_map::{FilePathMapping, SourceMap}, BytePos, Span, }; -use syntax::ast; use crate::config::file_lines::LineRange; use crate::ignore_path::IgnorePathSet; diff --git a/src/types.rs b/src/types.rs index 500ccaf6275..0708152b9ba 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,8 +1,8 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; +use rustc_ast::ast::{self, FnRetTy, Mutability}; use rustc_span::{symbol::kw, BytePos, Span}; -use syntax::ast::{self, FnRetTy, Mutability}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; @@ -551,7 +551,7 @@ impl Rewrite for ast::GenericParam { _ => (), } - if let syntax::ast::GenericParamKind::Const { ref ty } = &self.kind { + if let rustc_ast::ast::GenericParamKind::Const { ref ty } = &self.kind { result.push_str("const "); result.push_str(rewrite_ident(context, self.ident)); result.push_str(": "); diff --git a/src/utils.rs b/src/utils.rs index 494d4d0e33f..4f62dc363dd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,13 +1,13 @@ use std::borrow::Cow; -use rustc_ast_pretty::pprust; -use rustc_span::{sym, BytePos, ExpnId, Span, Symbol, SyntaxContext}; -use rustc_target::spec::abi; -use syntax::ast::{ +use rustc_ast::ast::{ self, Attribute, CrateSugar, MetaItem, MetaItemKind, NestedMetaItem, NodeId, Path, Visibility, VisibilityKind, }; -use syntax::ptr; +use rustc_ast::ptr; +use rustc_ast_pretty::pprust; +use rustc_span::{sym, BytePos, ExpnId, Span, Symbol, SyntaxContext}; +use rustc_target::spec::abi; use unicode_width::UnicodeWidthStr; use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; @@ -157,7 +157,7 @@ pub(crate) fn format_extern( } #[inline] -// Transform `Vec>` into `Vec<&T>` +// Transform `Vec>` into `Vec<&T>` pub(crate) fn ptr_vec_to_ref_vec(vec: &[ptr::P]) -> Vec<&T> { vec.iter().map(|x| &**x).collect::>() } diff --git a/src/vertical.rs b/src/vertical.rs index b932b0afa17..95d1d5c2d7e 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -3,8 +3,8 @@ use std::cmp; use itertools::Itertools; +use rustc_ast::ast; use rustc_span::{BytePos, Span}; -use syntax::ast; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; diff --git a/src/visitor.rs b/src/visitor.rs index 593e3ac6a21..27e4f6543b0 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,9 +1,9 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; +use rustc_ast::token::DelimToken; +use rustc_ast::{ast, visit}; use rustc_span::{BytePos, Pos, Span}; -use syntax::token::DelimToken; -use syntax::{ast, visit}; use crate::attr::*; use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; diff --git a/tests/source/imports.rs b/tests/source/imports.rs index d0bdeda595d..4dfc6ed94e3 100644 --- a/tests/source/imports.rs +++ b/tests/source/imports.rs @@ -3,7 +3,7 @@ // Imports. // Long import. -use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; +use rustc_ast::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl}; use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ItemA, ItemB}; @@ -15,30 +15,30 @@ use list::{ use test::{ Other /* C */ , /* A */ self /* B */ }; -use syntax::{self}; +use rustc_ast::{self}; use {/* Pre-comment! */ Foo, Bar /* comment */}; use Foo::{Bar, Baz}; -pub use syntax::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; +pub use rustc_ast::ast::{Expr_, Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath}; -use syntax::some::{}; +use rustc_ast::some::{}; use self; use std::io::{self}; use std::io::self; mod Foo { - pub use syntax::ast::{ + pub use rustc_ast::ast::{ ItemForeignMod, - ItemImpl, + ItemImpl, ItemMac, ItemMod, - ItemStatic, + ItemStatic, ItemDefaultImpl }; mod Foo2 { - pub use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; + pub use rustc_ast::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, self, ItemDefaultImpl}; } } diff --git a/tests/target/imports.rs b/tests/target/imports.rs index c497a375b59..87584d89f66 100644 --- a/tests/target/imports.rs +++ b/tests/target/imports.rs @@ -9,7 +9,7 @@ use exceedingly::loooooooooooooooooooooooooooooooooooooooooooooooooooooooong::im use exceedingly::looooooooooooooooooooooooooooooooooooooooooooooooooooooooooong::import::path::{ ItemA, ItemB, }; -use syntax::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; +use rustc_ast::ast::{ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; use list::{ // Another item @@ -22,8 +22,8 @@ use list::{ use test::{/* A */ self /* B */, Other /* C */}; -pub use syntax::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; -use syntax::{self}; +pub use rustc_ast::ast::{Expr, ExprAssign, ExprCall, ExprMethodCall, ExprPath, Expr_}; +use rustc_ast::{self}; use Foo::{Bar, Baz}; use {Bar /* comment */, /* Pre-comment! */ Foo}; @@ -31,12 +31,12 @@ use std::io; use std::io::{self}; mod Foo { - pub use syntax::ast::{ + pub use rustc_ast::ast::{ ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, }; mod Foo2 { - pub use syntax::ast::{ + pub use rustc_ast::ast::{ self, ItemDefaultImpl, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, }; } -- cgit 1.4.1-3-g733a5 From ac2d5b85a57e3f0b4c9d39e7ff053f95e0e4a5a8 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 30 Mar 2020 12:02:39 -0500 Subject: deps: bump rustc-ap* to v651 --- Cargo.lock | 279 +++++++++++++++++++++++++++++++--------------------------- Cargo.toml | 18 ++-- src/chains.rs | 10 ++- src/expr.rs | 2 +- src/types.rs | 14 +-- src/utils.rs | 2 +- 6 files changed, 180 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 2206da81730..d8b087503d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -494,6 +494,15 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.6.2" @@ -508,6 +517,19 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-error" version = "0.2.6" @@ -617,97 +639,97 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_ast" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "650.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "651.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -718,15 +740,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -735,52 +757,52 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_passes 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_passes 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_feature" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -788,7 +810,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -799,75 +821,74 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_session" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "650.0.0" +version = "651.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -949,15 +970,15 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_expand 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_expand 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1299,8 +1320,10 @@ dependencies = [ "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -1314,25 +1337,25 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7ba8774d4d5c8d42727c74836f478c51e0a16daeeee80017c133f9e1ebf4f6f" -"checksum rustc-ap-graphviz 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "feba68cc05f42d227b258e07a84df7d690d1f20200593754a789ab39acb581e5" -"checksum rustc-ap-rustc_ast 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "989d221c292a3c777fc4921f87e4962d8d89633cf52a3a82f6f34d5b3d66efc7" -"checksum rustc-ap-rustc_ast_passes 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "865c0bddabe735c8f8116cf14239b41d5789e5c38d1c503888779721b98bdd9e" -"checksum rustc-ap-rustc_ast_pretty 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "595c0092a2fa00dd0e572739279f771d96242f7626fc3999b4b027f08664417f" -"checksum rustc-ap-rustc_attr 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be021d73b25feb33dc0aa91f91ff37b939a0ef54f9620684bc2846278b5e637" -"checksum rustc-ap-rustc_data_structures 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a41551e5393a1abb4401e82f4e4bb64e097facb7d0362a1736b117186c0966dd" -"checksum rustc-ap-rustc_errors 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8715e95fd29d92a7799f9c65cb5583485bbf902dda17900c884fbb7956d593d8" -"checksum rustc-ap-rustc_expand 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ecc53789a88bb89caf81a6572db077b8679450b384fc03bf797d8453f86354b" -"checksum rustc-ap-rustc_feature 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf6304d5df6f803f43d15a71d1c4b4aa6b68a01fe587ad62fcdfb83049e3ec77" -"checksum rustc-ap-rustc_fs_util 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c05da9f8dfd5c086465ad0263749453c13739226233c0354de5fc93b20204a" -"checksum rustc-ap-rustc_index 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1c292880ff00cd1e61710396f9379b2c99a533cfb1bc9c3274d566ada2c6027" -"checksum rustc-ap-rustc_lexer 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51e5ac7071163642ff52dda1bc41ff7464fcd832b5ea3fabf162569d26969410" -"checksum rustc-ap-rustc_macros 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e147f23b65b716b58bd8687170914d3e2d2bfd004ec3fc8d2749e9d601482c0" -"checksum rustc-ap-rustc_parse 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c5e12622f831b7344899229f2f776ff2cdd14f7f82b257d6bbcb79c850996298" -"checksum rustc-ap-rustc_session 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18fb72a26080a34d35c8dd7ba5ac593812c1c3f97edffe6f1bf30c1ef5c4c550" -"checksum rustc-ap-rustc_span 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe2d8db305496f9dc5f43408044735a942eadeeb2a28d6da8dd6b23b5ef60f93" -"checksum rustc-ap-rustc_target 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2797ddd7911ba6681f500fa0d5af651635bdc74813363a1216bafc6156cb3d2" -"checksum rustc-ap-serialize 650.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8567212bd0f0a93bbf3675e1ae819937e4a57d48b705522462c31ff8efc0604" +"checksum rustc-ap-arena 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "632704fb93ca8148957191e5d2d827082f93c4aa20cdd242fb46d8cca57029da" +"checksum rustc-ap-graphviz 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bdd4689b814859c9f1b3e314ed2bde596acac428a256a16894635f600bed46b4" +"checksum rustc-ap-rustc_ast 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "101c1517d3fd19d083aaca5b113f9965e6ae353a0bb09c49959b0f62b95b75d9" +"checksum rustc-ap-rustc_ast_passes 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab3f5a7e939b37c99d8ca371f09b10bb5b5c85ad5d5b8d1d736ce8248c71be0" +"checksum rustc-ap-rustc_ast_pretty 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05046d3a2b8de22b20bcda9a1c063dc5c1f2f721f042b6c2809df2d23c64a13e" +"checksum rustc-ap-rustc_attr 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f00b7ccad6fc3628fb44950435772945a425575f9ea0b3708c536fe75623a6e8" +"checksum rustc-ap-rustc_data_structures 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c6121ab6766644fa76b711f65d4c39f2e335488ab768324567fed0ed191166e" +"checksum rustc-ap-rustc_errors 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adab84c842003ad1c8435fd71b8d0cc19bf0d702a8a2147d5be06e083db2d207" +"checksum rustc-ap-rustc_expand 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb001df541ea02b65c8e294252530010c6f90e3c6a5716e8e24e58c12dd1cd86" +"checksum rustc-ap-rustc_feature 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "446cc60613cc3b05d0bdbcab7feb02305790b5617fa43c532d51ae3223d677a4" +"checksum rustc-ap-rustc_fs_util 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ac99d6f67e7db3bb300895630e769ed41bd3e336c0e725870c70e676c1a5ff1" +"checksum rustc-ap-rustc_index 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5608c1cf50d2251b7e10a138cf6dd388e97f139b21c00b06a22d06f89c6591f6" +"checksum rustc-ap-rustc_lexer 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e9c1c6f5dc85977b3adb6fb556b2ff23354d1a12021da15eb1d36353458bde" +"checksum rustc-ap-rustc_macros 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3226b5ec864312a5d23eb40a5d621ee06bdc0754228d20d6eb76d4ddc4f2d4a1" +"checksum rustc-ap-rustc_parse 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba3b042344c2280b50d5df0058d11379028a8f016a407e575bb3ea8b6c798049" +"checksum rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff35ef4b5d9fbcb2fd539c7c908eb3cdd1f68ddbccd042945ef50ae65564f941" +"checksum rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e323b1f4a824039886eed8e33cad20ea4f492a9f9b3c9441009797c91de3e87a" +"checksum rustc-ap-rustc_target 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e161eb7b3a5b7993c6b480135296dc61476db80041d49dd446422742426e390b" +"checksum rustc-ap-serialize 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af510a659098d8c45a7303fb882fa780f4a87ec5f5d7a2053521e7d5d7f332c4" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" diff --git a/Cargo.toml b/Cargo.toml index cfb750c0a8f..de934e60b8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,36 +65,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "650.0.0" +version = "651.0.0" [dependencies.rustc_target] package = "rustc-ap-rustc_target" -version = "650.0.0" +version = "651.0.0" diff --git a/src/chains.rs b/src/chains.rs index 32bcf0e0999..40e4d483993 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -148,7 +148,15 @@ impl ChainItemKind { ast::ExprKind::MethodCall(ref segment, ref expressions) => { let types = if let Some(ref generic_args) = segment.args { if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { - data.args.clone() + data.args + .iter() + .filter_map(|x| match x { + ast::AngleBracketedArg::Arg(ref generic_arg) => { + Some(generic_arg.clone()) + } + _ => None, + }) + .collect::>() } else { vec![] } diff --git a/src/expr.rs b/src/expr.rs index d63961449f8..8545b0f6f29 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -322,7 +322,7 @@ pub(crate) fn format_expr( } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), + ast::ExprKind::LlvmInlineAsm(..) => Some(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) diff --git a/src/types.rs b/src/types.rs index 0708152b9ba..4f92ff6246f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -233,14 +233,18 @@ fn rewrite_segment( if let Some(ref args) = segment.args { match **args { - ast::GenericArgs::AngleBracketed(ref data) - if !data.args.is_empty() || !data.constraints.is_empty() => - { + ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => { let param_list = data .args .iter() - .map(SegmentParam::from_generic_arg) - .chain(data.constraints.iter().map(|x| SegmentParam::Binding(&*x))) + .map(|x| match x { + ast::AngleBracketedArg::Arg(generic_arg) => { + SegmentParam::from_generic_arg(generic_arg) + } + ast::AngleBracketedArg::Constraint(constraint) => { + SegmentParam::Binding(constraint) + } + }) .collect::>(); // HACK: squeeze out the span between the identifier and the parameters. diff --git a/src/utils.rs b/src/utils.rs index 4f62dc363dd..41400399ddd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -490,7 +490,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Continue(..) | ast::ExprKind::Err | ast::ExprKind::Field(..) - | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::LlvmInlineAsm(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) | ast::ExprKind::Range(..) -- cgit 1.4.1-3-g733a5 From 9714a140c99a8968b0becb5cf9227b1787768088 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 30 Mar 2020 13:11:00 -0500 Subject: refactor: use ast::attr:HasAttrs --- src/attr.rs | 11 +++-------- src/closures.rs | 10 +++------- src/visitor.rs | 19 +++++++------------ 3 files changed, 13 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 5221caf2fad..b9e160020fb 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,6 +1,7 @@ //! Format attributes and meta items. use rustc_ast::ast; +use rustc_ast::attr::HasAttrs; use rustc_span::{symbol::sym, BytePos, Span, DUMMY_SP}; use self::doc_comment::DocCommentFormatter; @@ -18,14 +19,8 @@ use crate::utils::{count_newlines, mk_sp}; mod doc_comment; /// Returns attributes on the given statement. -pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> Option<&[ast::Attribute]> { - match stmt.kind { - ast::StmtKind::Local(ref local) => Some(&local.attrs), - ast::StmtKind::Item(ref item) => Some(&item.attrs), - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(&expr.attrs), - ast::StmtKind::MacCall(ref mac) => Some(&mac.2), - ast::StmtKind::Empty => None, - } +pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { + stmt.attrs() } pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { diff --git a/src/closures.rs b/src/closures.rs index 55a96a5c68a..82c49d806b5 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -105,13 +105,9 @@ fn get_inner_expr<'a>( // Figure out if a block is necessary. fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) -> bool { - let has_attributes = block - .stmts - .first() - .map_or(false, |first_stmt| match get_attrs_from_stmt(first_stmt) { - Some(attrs) => !attrs.is_empty(), - None => false, - }); + let has_attributes = block.stmts.first().map_or(false, |first_stmt| { + !get_attrs_from_stmt(first_stmt).is_empty() + }); is_unsafe_block(block) || block.stmts.len() > 1 diff --git a/src/visitor.rs b/src/visitor.rs index 27e4f6543b0..346628c0b89 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -133,18 +133,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.format_missing(stmt.span().hi()); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - if let Some(attrs) = get_attrs_from_stmt(stmt.as_ast_node()) { - if contains_skip(attrs) { - self.push_skipped_with_span( - attrs, - stmt.span(), - get_span_without_attrs(stmt.as_ast_node()), - ); - } else { - let shape = self.shape(); - let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); - self.push_rewrite(stmt.span(), rewrite) - } + let attrs = get_attrs_from_stmt(stmt.as_ast_node()); + if contains_skip(attrs) { + self.push_skipped_with_span( + attrs, + stmt.span(), + get_span_without_attrs(stmt.as_ast_node()), + ); } else { let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); -- cgit 1.4.1-3-g733a5 From 00e199c974bd304695e6436fcb6b60bca5c8d6f4 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 31 Mar 2020 01:28:01 -0500 Subject: backport new syntax to rustfmt 1.x (#4105) * feat: support raw reference operator * feat: support const opt-out syntax * feat: support half open range syntax --- src/expr.rs | 10 ++-- src/patterns.rs | 58 ++++++++++++++-------- src/types.rs | 7 ++- tests/source/configs/spaces_around_ranges/false.rs | 12 +++++ tests/source/configs/spaces_around_ranges/true.rs | 12 +++++ tests/source/expr.rs | 4 ++ tests/source/type.rs | 27 ++++++++++ tests/target/configs/spaces_around_ranges/false.rs | 12 +++++ tests/target/configs/spaces_around_ranges/true.rs | 12 +++++ tests/target/expr.rs | 4 ++ tests/target/type.rs | 33 ++++++++++++ 11 files changed, 165 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 8545b0f6f29..ed10a54c2a3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1988,14 +1988,16 @@ pub(crate) fn prefer_next_line( fn rewrite_expr_addrof( context: &RewriteContext<'_>, - _borrow_kind: ast::BorrowKind, + borrow_kind: ast::BorrowKind, mutability: ast::Mutability, expr: &ast::Expr, shape: Shape, ) -> Option { - let operator_str = match mutability { - ast::Mutability::Not => "&", - ast::Mutability::Mut => "&mut ", + let operator_str = match (mutability, borrow_kind) { + (ast::Mutability::Not, ast::BorrowKind::Ref) => "&", + (ast::Mutability::Not, ast::BorrowKind::Raw) => "&raw const ", + (ast::Mutability::Mut, ast::BorrowKind::Ref) => "&mut ", + (ast::Mutability::Mut, ast::BorrowKind::Raw) => "&raw mut ", }; rewrite_unary_prefix(context, operator_str, expr, shape) } diff --git a/src/patterns.rs b/src/patterns.rs index 78292620232..5847bd08d80 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -55,6 +55,17 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool { } } +struct RangeOperand<'a>(&'a Option>); + +impl<'a> Rewrite for RangeOperand<'a> { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + match &self.0 { + None => Some("".to_owned()), + Some(ref exp) => exp.rewrite(context, shape), + } + } +} + impl Rewrite for Pat { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self.kind { @@ -179,29 +190,34 @@ impl Rewrite for Pat { None } } - PatKind::Range(ref lhs, ref rhs, ref end_kind) => match (lhs, rhs) { - (Some(lhs), Some(rhs)) => { - let infix = match end_kind.node { - RangeEnd::Included(RangeSyntax::DotDotDot) => "...", - RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", - RangeEnd::Excluded => "..", + PatKind::Range(ref lhs, ref rhs, ref end_kind) => { + let infix = match end_kind.node { + RangeEnd::Included(RangeSyntax::DotDotDot) => "...", + RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", + RangeEnd::Excluded => "..", + }; + let infix = if context.config.spaces_around_ranges() { + let lhs_spacing = match lhs { + None => "", + Some(_) => " ", }; - let infix = if context.config.spaces_around_ranges() { - format!(" {} ", infix) - } else { - infix.to_owned() + let rhs_spacing = match rhs { + None => "", + Some(_) => " ", }; - rewrite_pair( - &**lhs, - &**rhs, - PairParts::infix(&infix), - context, - shape, - SeparatorPlace::Front, - ) - } - (_, _) => unimplemented!(), - }, + format!("{}{}{}", lhs_spacing, infix, rhs_spacing) + } else { + infix.to_owned() + }; + rewrite_pair( + &RangeOperand(lhs), + &RangeOperand(rhs), + PairParts::infix(&infix), + context, + shape, + SeparatorPlace::Front, + ) + } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); rewrite_unary_prefix(context, &prefix, &**pat, shape) diff --git a/src/types.rs b/src/types.rs index 4f92ff6246f..96e331779c4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -527,7 +527,12 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::Maybe => poly_trait_ref .rewrite(context, shape.offset_left(1)?) .map(|s| format!("?{}", s)), - _ => unimplemented!(), + ast::TraitBoundModifier::MaybeConst => poly_trait_ref + .rewrite(context, shape.offset_left(7)?) + .map(|s| format!("?const {}", s)), + ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref + .rewrite(context, shape.offset_left(8)?) + .map(|s| format!("?const ?{}", s)), }; rewrite.map(|s| if has_paren { format!("({})", s) } else { s }) } diff --git a/tests/source/configs/spaces_around_ranges/false.rs b/tests/source/configs/spaces_around_ranges/false.rs index 11ca76b1345..1878c68a5a0 100644 --- a/tests/source/configs/spaces_around_ranges/false.rs +++ b/tests/source/configs/spaces_around_ranges/false.rs @@ -20,3 +20,15 @@ fn main() { _ => bar, } } + +fn half_open() { + match [5 .. 4, 99 .. 105, 43 .. 44] { + [_, 99 .., _] => {} + [_, .. 105, _] => {} + _ => {} + }; + + if let ..= 5 = 0 {} + if let .. 5 = 0 {} + if let 5 .. = 0 {} +} diff --git a/tests/source/configs/spaces_around_ranges/true.rs b/tests/source/configs/spaces_around_ranges/true.rs index 50170892130..0eadfb28515 100644 --- a/tests/source/configs/spaces_around_ranges/true.rs +++ b/tests/source/configs/spaces_around_ranges/true.rs @@ -20,3 +20,15 @@ fn main() { _ => bar, } } + +fn half_open() { + match [5..4, 99..105, 43..44] { + [_, 99.., _] => {} + [_, ..105, _] => {} + _ => {} + }; + + if let ..=5 = 0 {} + if let ..5 = 0 {} + if let 5.. = 0 {} +} diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 05af07f231b..8a6e6f1aa2b 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -218,6 +218,10 @@ fn returns() { fn addrof() { & mut(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); & (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + // raw reference operator + & raw const a; + & raw mut b; } fn casts() { diff --git a/tests/source/type.rs b/tests/source/type.rs index 27387c5bdca..eb4600e5bce 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -139,3 +139,30 @@ fn foo(a: SomeLongComplexType, b: SomeOtherLongComplexType) -> Box Box>; + +// Const opt-out + +trait T: ? const Super {} + +const fn maybe_const() -> i32 { ::CONST } + +struct S(std::marker::PhantomData); + +impl ? const T {} + +fn trait_object() -> &'static dyn ? const T { &S } + +fn i(_: impl IntoIterator>) {} + +fn apit(_: impl ?const T) {} + +fn rpit() -> impl ? const T { S } + +pub struct Foo(T); +impl Foo { + fn new(t: T) -> Self { + // not calling methods on `t`, so we opt out of requiring + // `` to have const methods via `?const` + Self(t) + } +} diff --git a/tests/target/configs/spaces_around_ranges/false.rs b/tests/target/configs/spaces_around_ranges/false.rs index 6319da98572..72b1be4804c 100644 --- a/tests/target/configs/spaces_around_ranges/false.rs +++ b/tests/target/configs/spaces_around_ranges/false.rs @@ -20,3 +20,15 @@ fn main() { _ => bar, } } + +fn half_open() { + match [5..4, 99..105, 43..44] { + [_, 99.., _] => {} + [_, ..105, _] => {} + _ => {} + }; + + if let ..=5 = 0 {} + if let ..5 = 0 {} + if let 5.. = 0 {} +} diff --git a/tests/target/configs/spaces_around_ranges/true.rs b/tests/target/configs/spaces_around_ranges/true.rs index 7bfcc23c8ea..c56fdbb02b6 100644 --- a/tests/target/configs/spaces_around_ranges/true.rs +++ b/tests/target/configs/spaces_around_ranges/true.rs @@ -20,3 +20,15 @@ fn main() { _ => bar, } } + +fn half_open() { + match [5 .. 4, 99 .. 105, 43 .. 44] { + [_, 99 .., _] => {} + [_, .. 105, _] => {} + _ => {} + }; + + if let ..= 5 = 0 {} + if let .. 5 = 0 {} + if let 5 .. = 0 {} +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index c50693049a2..5d9e972066c 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -253,6 +253,10 @@ fn addrof() { + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); &(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + // raw reference operator + &raw const a; + &raw mut b; } fn casts() { diff --git a/tests/target/type.rs b/tests/target/type.rs index 575bd3573bc..20e97440e7c 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -144,3 +144,36 @@ type MyFn = fn( a: SomeLongComplexType, b: SomeOtherLongComplexType, ) -> Box>; + +// Const opt-out + +trait T: ?const Super {} + +const fn maybe_const() -> i32 { + ::CONST +} + +struct S(std::marker::PhantomData); + +impl ?const T {} + +fn trait_object() -> &'static dyn ?const T { + &S +} + +fn i(_: impl IntoIterator>) {} + +fn apit(_: impl ?const T) {} + +fn rpit() -> impl ?const T { + S +} + +pub struct Foo(T); +impl Foo { + fn new(t: T) -> Self { + // not calling methods on `t`, so we opt out of requiring + // `` to have const methods via `?const` + Self(t) + } +} -- cgit 1.4.1-3-g733a5 From c1267303bc06408b4ce406175e8f9cddbbe11b92 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 31 Mar 2020 01:30:26 -0500 Subject: fix: formatting arbitrary extern abi (#4089) --- Cargo.lock | 3 +-- Cargo.toml | 6 +----- src/utils.rs | 15 ++++++--------- tests/source/issue_4086.rs | 2 ++ tests/target/issue_4086.rs | 2 ++ 5 files changed, 12 insertions(+), 16 deletions(-) create mode 100644 tests/source/issue_4086.rs create mode 100644 tests/target/issue_4086.rs (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index d8b087503d8..d52c24c9844 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -954,7 +954,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.12" +version = "1.4.13" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -978,7 +978,6 @@ dependencies = [ "rustc-ap-rustc_parse 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-rustc_session 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-rustc_span 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 651.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index de934e60b8f..a84ea4f9154 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.12" +version = "1.4.13" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -94,7 +94,3 @@ version = "651.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" version = "651.0.0" - -[dependencies.rustc_target] -package = "rustc-ap-rustc_target" -version = "651.0.0" diff --git a/src/utils.rs b/src/utils.rs index 41400399ddd..e029aa435c0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -7,7 +7,6 @@ use rustc_ast::ast::{ use rustc_ast::ptr; use rustc_ast_pretty::pprust; use rustc_span::{sym, BytePos, ExpnId, Span, Symbol, SyntaxContext}; -use rustc_target::spec::abi; use unicode_width::UnicodeWidthStr; use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; @@ -140,19 +139,17 @@ pub(crate) fn format_extern( is_mod: bool, ) -> Cow<'static, str> { let abi = match ext { - ast::Extern::None => abi::Abi::Rust, - ast::Extern::Implicit => abi::Abi::C, - ast::Extern::Explicit(abi) => { - abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or(abi::Abi::Rust) - } + ast::Extern::None => "Rust".to_owned(), + ast::Extern::Implicit => "C".to_owned(), + ast::Extern::Explicit(abi) => abi.symbol_unescaped.to_string(), }; - if abi == abi::Abi::Rust && !is_mod { + if abi == "Rust" && !is_mod { Cow::from("") - } else if abi == abi::Abi::C && !explicit_abi { + } else if abi == "C" && !explicit_abi { Cow::from("extern ") } else { - Cow::from(format!("extern {} ", abi)) + Cow::from(format!(r#"extern "{}" "#, abi)) } } diff --git a/tests/source/issue_4086.rs b/tests/source/issue_4086.rs new file mode 100644 index 00000000000..ffa6442e930 --- /dev/null +++ b/tests/source/issue_4086.rs @@ -0,0 +1,2 @@ +#[cfg(any())] +extern "C++" {} diff --git a/tests/target/issue_4086.rs b/tests/target/issue_4086.rs new file mode 100644 index 00000000000..959d3b3d468 --- /dev/null +++ b/tests/target/issue_4086.rs @@ -0,0 +1,2 @@ +#[cfg(any())] +extern "C++" {} -- cgit 1.4.1-3-g733a5 From 577ef8136faba1d4556aaf4663c17f097ffb010b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 19 May 2020 17:31:28 +0900 Subject: Update rustc-ap-* crates to 659.0.0 for rustfmt-1.4.15 (#4184) --- .travis.yml | 2 + Cargo.lock | 286 +++++++++++++++++++++++++++----------------------- Cargo.toml | 20 ++-- appveyor.yml | 2 + ci/integration.sh | 2 +- src/chains.rs | 8 +- src/imports.rs | 8 +- src/items.rs | 30 +++--- src/lib.rs | 3 +- src/macros.rs | 24 +++-- src/modules.rs | 6 +- src/syntux/session.rs | 7 +- src/utils.rs | 4 +- src/visitor.rs | 9 +- 14 files changed, 227 insertions(+), 184 deletions(-) (limited to 'src') diff --git a/.travis.yml b/.travis.yml index 966b7d7bac4..d699bd842ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,6 +47,8 @@ matrix: script: - | if [ -z ${INTEGRATION} ]; then + export CFG_RELEASE_CHANNEL=nightly + export CFG_RELEASE=nightly cargo build cargo test cargo test -- --ignored diff --git a/Cargo.lock b/Cargo.lock index 7864cf47314..81b56b87605 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -294,7 +294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ena" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -608,6 +608,14 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "psm" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -699,89 +707,88 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-graphviz" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_ast" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "654.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "659.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -789,28 +796,29 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-graphviz 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "stacker 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -819,52 +827,52 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_passes 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_passes 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_feature" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -872,7 +880,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -883,55 +891,54 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_session" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -939,21 +946,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "654.0.0" +version = "659.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1035,14 +1042,15 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_expand 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_expand 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1146,6 +1154,18 @@ name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "stacker" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "psm 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strsim" version = "0.8.0" @@ -1289,6 +1309,11 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.9" @@ -1377,7 +1402,7 @@ dependencies = [ "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" +"checksum ena 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" @@ -1414,6 +1439,7 @@ dependencies = [ "checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum psm 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -1425,25 +1451,25 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-arena 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81dfcfbb0ddfd533abf8c076e3b49d1e5042d1962526a12ce2c66d514b24cca3" -"checksum rustc-ap-graphviz 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7490bb07b014a7f9531bde33c905a805e08095dbefdb4c9988a1b19fe6d019fd" -"checksum rustc-ap-rustc_ast 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "189f16dbb8dd11089274c9ced58b0cae9e1ea3e434a58f3db683817eda849e58" -"checksum rustc-ap-rustc_ast_passes 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bbe619609b56a617fa986332b066d53270093c816d8ff8281fc90e1dbe74c1cc" -"checksum rustc-ap-rustc_ast_pretty 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26ab1495f7b420e937688749c1da5763aaabd6ebe8cacb758665a0b8481da094" -"checksum rustc-ap-rustc_attr 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e057495724c60729c1d1d9d49374e0b3ebd6d3481cd161b2871f52fe017b7b5" -"checksum rustc-ap-rustc_data_structures 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2130997667833692f4bec4681d0e73b066d5a01dac1d8a68f22068b82bf173a" -"checksum rustc-ap-rustc_errors 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "908e1ea187c6bb368af4ba6db980001e920515e67371ddc4086e749baabe6080" -"checksum rustc-ap-rustc_expand 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50066a75bca872ff933b0ee8a582d18ef1876c8054a392f60c39e538446bfb00" -"checksum rustc-ap-rustc_feature 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96fb53e1710e6de7c2e371ca56c857b79f9b399aba58aa6b6fbed6e2f677d3f6" -"checksum rustc-ap-rustc_fs_util 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f91357e5e468fc2729211571d769723c728a34e200d90a70164e945f881e09" -"checksum rustc-ap-rustc_index 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32220c3e6cdf226f38e4474b747dca15f3106bb680c74f10b299af3f6cdb1663" -"checksum rustc-ap-rustc_lexer 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b324d2a2bacad344e53e182e5ca04ffb74745b932849aa074f8f7fec8177da5" -"checksum rustc-ap-rustc_macros 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59686c56d5f1b3ed47d0f070c257ed35caf24ecf2d744dd11fe44b1014baee0f" -"checksum rustc-ap-rustc_parse 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfb0c11c591ec5f87bbadb10819795abc9035ff79a26703c1b6c9487ac51f49" -"checksum rustc-ap-rustc_session 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1a194b1a81d7233ee492847638dc9ebdb7d084300e5ade8dea0ceaa98f95b9" -"checksum rustc-ap-rustc_span 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a648146050fed6b58e681ec22488e728f60e16036bb7497c9815e3debd1e4242" -"checksum rustc-ap-rustc_target 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28cf28798f0988b808e3616713630e4098d68c6f1f41052a2f7e922e094da744" -"checksum rustc-ap-serialize 654.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "756e8f526ec7906e132188bf25e3c10a6ee42ab77294ecb3b3602647f0508eef" +"checksum rustc-ap-arena 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdaf0295fc40b10ec1091aad1a1760b4bb3b4e7c4f77d543d1a2e9d50a01e6b1" +"checksum rustc-ap-graphviz 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8028e8cdb4eb71810d0c22a5a5e1e3106c81123be63ce7f044b6d4ac100d8941" +"checksum rustc-ap-rustc_ast 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16e9e502bb3a5568433db1cf2fb1f1e1074934636069cf744ad7c77b58e1428e" +"checksum rustc-ap-rustc_ast_passes 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "faf35ffecab28f97f7ac01cf6a13afaca6408529d15eb95f317a43b2ffb88933" +"checksum rustc-ap-rustc_ast_pretty 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3684ed43dc552f1e030e3f7a5a300a7a834bdda4e9e00ab80284be4220d8c603" +"checksum rustc-ap-rustc_attr 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31b413927daa666983b3b49227f9ac218aa29254546abdb585f20cd71c391870" +"checksum rustc-ap-rustc_data_structures 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b1c6069e5c522657f1c6f5ab33074e097092f48e804cc896d337e319aacbd60" +"checksum rustc-ap-rustc_errors 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c374e89b3c9714869ef86076942155383804ba6778c26be2169d324563c31f9" +"checksum rustc-ap-rustc_expand 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "259d2a7aa7a12f3c99a4ce4123643ec065f1a26f8e89be1f9bedd9757ea53fdc" +"checksum rustc-ap-rustc_feature 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0296fbc29b629d5ae2ebee1bbf0407bb22de04d26d87216c20899b79579ccb3" +"checksum rustc-ap-rustc_fs_util 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34734f6cc681399630acd836a14207c6b5b9671a290cc7cad0354b0a4d71b3c9" +"checksum rustc-ap-rustc_index 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1e4508753d71d3523209c2ca5086db15a1413e71ebf17ad5412bb7ced5e44c2" +"checksum rustc-ap-rustc_lexer 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42b9fcd8407e322908a721262fbc0b35b5f3c35bb173a26dd1e0070bde336e33" +"checksum rustc-ap-rustc_macros 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d104115a689367d2e0bcd99f37e0ebd6b9c8c78bab0d9cbea5bae86323601b5" +"checksum rustc-ap-rustc_parse 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afaaab91853fc5a3916785ccae727a4433359d9787c260d42b96a2265fe5b287" +"checksum rustc-ap-rustc_session 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "86e756a57ce6ce1b868e35e64a7e10ab28d49ece80d7c661b07aff5afc6e5d2d" +"checksum rustc-ap-rustc_span 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21031c3396ee452f4c6e994b67513a633055c57c86d00336afd9d63149518f34" +"checksum rustc-ap-rustc_target 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff21badfbead5b0050391eaad8840f2e4fcb03b6b0fc6006f447443529e9ae6e" +"checksum rustc-ap-serialize 659.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "768b5a305669d934522712bc13502962edfde5128ea63b9e7db4000410be1dc6" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" @@ -1463,6 +1489,7 @@ dependencies = [ "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum stacker 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "72dd941b456e1c006d6b9f27c526d5b69281288aeea8cba82c19d3843d8ccdd2" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f66a4c0ddf7aee4677995697366de0749b0139057342eccbb609b12d0affc" "checksum structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe0c13e476b4e21ff7f5c4ace3818b6d7bdc16897c31c73862471bc1663acae" @@ -1482,6 +1509,7 @@ dependencies = [ "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" diff --git a/Cargo.toml b/Cargo.toml index bfffe94c505..b0e13269f0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,32 +65,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "654.0.0" +version = "659.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "654.0.0" +version = "659.0.0" + +[dependencies.rustc_attr] +package = "rustc-ap-rustc_attr" +version = "659.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "654.0.0" +version = "659.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "654.0.0" +version = "659.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "654.0.0" +version = "659.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "654.0.0" +version = "659.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "654.0.0" +version = "659.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "654.0.0" +version = "659.0.0" diff --git a/appveyor.yml b/appveyor.yml index 1d3b06152a9..7bfe696009f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -48,6 +48,8 @@ install: build: false test_script: + - set CFG_RELEASE_CHANNEL=nightly + - set CFG_RELEASE=nightly - cargo build --verbose - cargo test - cargo test -- --ignored diff --git a/ci/integration.sh b/ci/integration.sh index 4d5498b6ec7..13a3ecaa196 100755 --- a/ci/integration.sh +++ b/ci/integration.sh @@ -15,7 +15,7 @@ set -ex # it again. # #which cargo-fmt || cargo install --force -cargo install --path . --force +CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force echo "Integration tests for: ${INTEGRATION}" cargo fmt -- --version diff --git a/src/chains.rs b/src/chains.rs index 40e4d483993..ebf562c093d 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -59,7 +59,7 @@ use std::borrow::Cow; use std::cmp::min; use rustc_ast::{ast, ptr}; -use rustc_span::{BytePos, Span}; +use rustc_span::{symbol, BytePos, Span}; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use crate::config::IndentStyle; @@ -116,8 +116,8 @@ enum ChainItemKind { Vec, Vec>, ), - StructField(ast::Ident), - TupleField(ast::Ident, bool), + StructField(symbol::Ident), + TupleField(symbol::Ident, bool), Await, Comment(String, CommentPosition), } @@ -234,7 +234,7 @@ impl ChainItem { } fn rewrite_method_call( - method_name: ast::Ident, + method_name: symbol::Ident, types: &[ast::GenericArg], args: &[ptr::P], span: Span, diff --git a/src/imports.rs b/src/imports.rs index d8f963e1ec3..914b91a46ca 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -3,7 +3,11 @@ use std::cmp::Ordering; use std::fmt; use rustc_ast::ast::{self, UseTreeKind}; -use rustc_span::{source_map, symbol::sym, BytePos, Span, DUMMY_SP}; +use rustc_span::{ + source_map, + symbol::{self, sym}, + BytePos, Span, DUMMY_SP, +}; use crate::comment::combine_strs_with_missing_comments; use crate::config::lists::*; @@ -20,7 +24,7 @@ use crate::visitor::FmtVisitor; /// Returns a name imported by a `use` declaration. /// E.g., returns `Ordering` for `std::cmp::Ordering` and `self` for `std::cmp::self`. -pub(crate) fn path_to_imported_ident(path: &ast::Path) -> ast::Ident { +pub(crate) fn path_to_imported_ident(path: &ast::Path) -> symbol::Ident { path.segments.last().unwrap().ident } diff --git a/src/items.rs b/src/items.rs index baa993590ca..4a1af8e09a1 100644 --- a/src/items.rs +++ b/src/items.rs @@ -311,7 +311,7 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn rewrite_fn_before_block( &mut self, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, fn_sig: &FnSig<'_>, span: Span, ) -> Option<(String, FnBraceStyle)> { @@ -335,7 +335,7 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn rewrite_required_fn( &mut self, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, sig: &ast::FnSig, generics: &ast::Generics, span: Span, @@ -411,7 +411,7 @@ impl<'a> FmtVisitor<'a> { pub(crate) fn visit_enum( &mut self, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, @@ -967,7 +967,7 @@ fn rewrite_trait_ref( pub(crate) struct StructParts<'a> { prefix: &'a str, - ident: ast::Ident, + ident: symbol::Ident, vis: &'a ast::Visibility, def: &'a ast::VariantData, generics: Option<&'a ast::Generics>, @@ -1234,7 +1234,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { pub(crate) fn format_trait_alias( context: &RewriteContext<'_>, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, @@ -1513,7 +1513,7 @@ fn rewrite_type_prefix( context: &RewriteContext<'_>, indent: Indent, prefix: &str, - ident: ast::Ident, + ident: symbol::Ident, generics: &ast::Generics, ) -> Option { let mut result = String::with_capacity(128); @@ -1554,7 +1554,7 @@ fn rewrite_type_item( indent: Indent, prefix: &str, suffix: &str, - ident: ast::Ident, + ident: symbol::Ident, rhs: &R, generics: &ast::Generics, vis: &ast::Visibility, @@ -1583,7 +1583,7 @@ fn rewrite_type_item( pub(crate) fn rewrite_type_alias( context: &RewriteContext<'_>, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, ty: &ast::Ty, generics: &ast::Generics, vis: &ast::Visibility, @@ -1594,7 +1594,7 @@ pub(crate) fn rewrite_type_alias( pub(crate) fn rewrite_opaque_type( context: &RewriteContext<'_>, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, generic_bounds: &ast::GenericBounds, generics: &ast::Generics, vis: &ast::Visibility, @@ -1709,7 +1709,7 @@ pub(crate) fn rewrite_struct_field( pub(crate) struct StaticParts<'a> { prefix: &'a str, vis: &'a ast::Visibility, - ident: ast::Ident, + ident: symbol::Ident, ty: &'a ast::Ty, mutability: ast::Mutability, expr_opt: Option<&'a ptr::P>, @@ -1830,7 +1830,7 @@ fn rewrite_static( } pub(crate) fn rewrite_associated_type( - ident: ast::Ident, + ident: symbol::Ident, ty_opt: Option<&ptr::P>, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, @@ -1880,7 +1880,7 @@ impl<'a> Rewrite for OpaqueType<'a> { pub(crate) fn rewrite_opaque_impl_type( context: &RewriteContext<'_>, - ident: ast::Ident, + ident: symbol::Ident, generics: &ast::Generics, generic_bounds: &ast::GenericBounds, indent: Indent, @@ -1904,7 +1904,7 @@ pub(crate) fn rewrite_opaque_impl_type( } pub(crate) fn rewrite_associated_impl_type( - ident: ast::Ident, + ident: symbol::Ident, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, generics: &ast::Generics, @@ -2141,7 +2141,7 @@ pub(crate) enum FnBraceStyle { fn rewrite_fn_base( context: &RewriteContext<'_>, indent: Indent, - ident: ast::Ident, + ident: symbol::Ident, fn_sig: &FnSig<'_>, span: Span, fn_brace_style: FnBraceStyle, @@ -2969,7 +2969,7 @@ fn rewrite_comments_before_after_where( fn format_header( context: &RewriteContext<'_>, item_name: &str, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, ) -> String { format!( diff --git a/src/lib.rs b/src/lib.rs index ecf19ebb586..831eac8dc7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ use std::rc::Rc; use failure::Fail; use ignore; use rustc_ast::ast; +use rustc_span::symbol; use crate::comment::LineClasses; use crate::emitter::Emitter; @@ -524,7 +525,7 @@ impl Input { let file_stem = file.file_stem()?; if file.parent()?.to_path_buf().join(file_stem).is_dir() { Some(DirectoryOwnership::Owned { - relative: file_stem.to_str().map(ast::Ident::from_str), + relative: file_stem.to_str().map(symbol::Ident::from_str), }) } else { None diff --git a/src/macros.rs b/src/macros.rs index 400daa6a5aa..cec5d873693 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -17,7 +17,10 @@ use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::{new_parser_from_tts, parser::Parser}; -use rustc_span::{symbol::kw, BytePos, Span, Symbol, DUMMY_SP}; +use rustc_span::{ + symbol::{self, kw}, + BytePos, Span, Symbol, DUMMY_SP, +}; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, @@ -52,7 +55,7 @@ pub(crate) enum MacroArg { Ty(ptr::P), Pat(ptr::P), Item(ptr::P), - Keyword(ast::Ident, Span), + Keyword(symbol::Ident, Span), } impl MacroArg { @@ -137,7 +140,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { fn rewrite_macro_name( context: &RewriteContext<'_>, path: &ast::Path, - extra_ident: Option, + extra_ident: Option, ) -> String { let name = if path.segments.len() == 1 { // Avoid using pretty-printer in the common case. @@ -188,7 +191,7 @@ fn return_macro_parse_failure_fallback( pub(crate) fn rewrite_macro( mac: &ast::MacCall, - extra_ident: Option, + extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -230,9 +233,10 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { }) { parser.bump(); - let macro_arg = - MacroArg::Keyword(ast::Ident::with_dummy_span(keyword), parser.prev_token.span); - return Some(macro_arg); + return Some(MacroArg::Keyword( + symbol::Ident::with_dummy_span(keyword), + parser.prev_token.span, + )); } } None @@ -240,7 +244,7 @@ fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { fn rewrite_macro_inner( mac: &ast::MacCall, - extra_ident: Option, + extra_ident: Option, context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, @@ -479,7 +483,7 @@ pub(crate) fn rewrite_macro_def( shape: Shape, indent: Indent, def: &ast::MacroDef, - ident: ast::Ident, + ident: symbol::Ident, vis: &ast::Visibility, span: Span, ) -> Option { @@ -620,7 +624,7 @@ fn replace_names(input: &str) -> Option<(String, HashMap)> { #[derive(Debug, Clone)] enum MacroArgKind { /// e.g., `$x: expr`. - MetaVariable(ast::Name, String), + MetaVariable(Symbol, String), /// e.g., `$($foo: expr),*` Repeat( /// `()`, `[]` or `{}`. diff --git a/src/modules.rs b/src/modules.rs index 9f8dabbfaf4..747b186dae3 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::visit::Visitor; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{self, sym, Symbol}; use crate::attr::MetaVisitor; use crate::config::FileName; @@ -239,7 +239,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Find a file path in the filesystem which corresponds to the given module. fn find_external_module( &self, - mod_name: ast::Ident, + mod_name: symbol::Ident, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, ) -> Result>, String> { @@ -326,7 +326,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } - fn push_inline_mod_directory(&mut self, id: ast::Ident, attrs: &[ast::Attribute]) { + fn push_inline_mod_directory(&mut self, id: symbol::Ident, attrs: &[ast::Attribute]) { if let Some(path) = find_path_value(attrs) { self.directory.path.push(&*path.as_str()); self.directory.ownership = DirectoryOwnership::Owned { relative: None }; diff --git a/src/syntux/session.rs b/src/syntux/session.rs index da8741c84e5..00f12b32237 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -2,14 +2,13 @@ use std::cell::RefCell; use std::path::Path; use std::rc::Rc; -use rustc_ast::ast; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ source_map::{FilePathMapping, SourceMap}, - BytePos, Span, + symbol, BytePos, Span, }; use crate::config::file_lines::LineRange; @@ -147,8 +146,8 @@ impl ParseSess { pub(crate) fn default_submod_path( &self, - id: ast::Ident, - relative: Option, + id: symbol::Ident, + relative: Option, dir_path: &Path, ) -> rustc_expand::module::ModulePath<'_> { rustc_expand::module::default_submod_path( diff --git a/src/utils.rs b/src/utils.rs index e029aa435c0..f82bdd501cf 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,7 +6,7 @@ use rustc_ast::ast::{ }; use rustc_ast::ptr; use rustc_ast_pretty::pprust; -use rustc_span::{sym, BytePos, ExpnId, Span, Symbol, SyntaxContext}; +use rustc_span::{sym, symbol, BytePos, ExpnId, Span, Symbol, SyntaxContext}; use unicode_width::UnicodeWidthStr; use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; @@ -24,7 +24,7 @@ pub(crate) fn skip_annotation() -> Symbol { Symbol::intern("rustfmt::skip") } -pub(crate) fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: ast::Ident) -> &'a str { +pub(crate) fn rewrite_ident<'a>(context: &'a RewriteContext<'_>, ident: symbol::Ident) -> &'a str { context.snippet(ident.span) } diff --git a/src/visitor.rs b/src/visitor.rs index 346628c0b89..ef6a7ff7ba6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,9 +1,8 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_ast::token::DelimToken; -use rustc_ast::{ast, visit}; -use rustc_span::{BytePos, Pos, Span}; +use rustc_ast::{ast, token::DelimToken, visit}; +use rustc_span::{symbol, BytePos, Pos, Span}; use crate::attr::*; use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; @@ -691,7 +690,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { + fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; @@ -897,7 +896,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { m: &ast::Mod, vis: &ast::Visibility, s: Span, - ident: ast::Ident, + ident: symbol::Ident, attrs: &[ast::Attribute], is_internal: bool, ) { -- cgit 1.4.1-3-g733a5 From 08776ef3b4d88392608b21ec74440721bbbfa841 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 8 Jun 2020 10:31:25 +0900 Subject: Support module-level rustfmt::skip in sub-modules --- src/modules.rs | 11 ++++--- src/syntux/parser.rs | 81 +++------------------------------------------------- 2 files changed, 11 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 747b186dae3..915401c4682 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -252,7 +252,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(None); } return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { - Some(m) => Ok(Some(SubModKind::External( + Some((_, ref attrs)) if contains_skip(attrs) => Ok(None), + Some((m, _)) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, Cow::Owned(m), @@ -290,10 +291,11 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { - Some(m) if outside_mods_empty => { + Some((_, ref attrs)) if contains_skip(attrs) => Ok(None), + Some((m, _)) if outside_mods_empty => { Ok(Some(SubModKind::External(path, ownership, Cow::Owned(m)))) } - Some(m) => { + Some((m, _)) => { mods_outside_ast.push((path.clone(), ownership, Cow::Owned(m))); if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); @@ -377,7 +379,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } let m = match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.inner) { - Some(m) => m, + Some((_, ref attrs)) if contains_skip(attrs) => continue, + Some((m, _)) => m, None => continue, }; diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 04a6f7577a0..831554829e2 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; -use rustc_errors::{Diagnostic, PResult}; +use rustc_errors::Diagnostic; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{symbol::kw, Span}; @@ -102,91 +102,18 @@ impl<'a> Parser<'a> { rustc_expand::module::submod_path_from_attr(attrs, path) } - // FIXME(topecongiro) Use the method from libsyntax[1] once it become public. - // - // [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs - fn parse_inner_attrs(parser: &mut RawParser<'a>) -> PResult<'a, Vec> { - let mut attrs: Vec = vec![]; - loop { - match parser.token.kind { - TokenKind::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !parser.look_ahead(1, |t| t == &TokenKind::Not) { - break; - } - - let attr = parser.parse_attribute(true)?; - assert_eq!(attr.style, ast::AttrStyle::Inner); - attrs.push(attr); - } - TokenKind::DocComment(s) => { - // we need to get the position of this token before we bump. - let attr = rustc_ast::attr::mk_doc_comment( - rustc_ast::util::comments::doc_comment_style(&s.as_str()), - s, - parser.token.span, - ); - if attr.style == ast::AttrStyle::Inner { - attrs.push(attr); - parser.bump(); - } else { - break; - } - } - _ => break, - } - } - Ok(attrs) - } - - fn parse_mod_items(parser: &mut RawParser<'a>, span: Span) -> PResult<'a, ast::Mod> { - let mut items = vec![]; - while let Some(item) = parser.parse_item()? { - items.push(item); - } - - // Handle extern mods that are empty files/files with only comments. - if items.is_empty() { - parser.parse_mod(&TokenKind::Eof)?; - } - - let hi = if parser.token.span.is_dummy() { - span - } else { - parser.prev_token.span - }; - - Ok(ast::Mod { - inner: span.to(hi), - items, - inline: false, - }) - } - pub(crate) fn parse_file_as_module( sess: &'a ParseSess, path: &Path, span: Span, - ) -> Option { + ) -> Option<(ast::Mod, Vec)> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); - - let lo = parser.token.span; - // FIXME(topecongiro) Format inner attributes (#3606). - match Parser::parse_inner_attrs(&mut parser) { - Ok(_attrs) => (), + match parser.parse_mod(&TokenKind::Eof) { + Ok(result) => Some(result), Err(mut e) => { e.cancel(); sess.reset_errors(); - return None; - } - } - - match Parser::parse_mod_items(&mut parser, lo) { - Ok(m) => Some(m), - Err(mut db) => { - db.cancel(); - sess.reset_errors(); None } } -- cgit 1.4.1-3-g733a5 From b28fd5f91c296ea5004c65b02047656a3ad876c3 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 11 Jun 2020 13:22:37 -0500 Subject: deps: apply upstream rustc-* changes --- src/config/file_lines.rs | 2 +- src/expr.rs | 6 +++++- src/macros.rs | 1 + src/source_file.rs | 4 +++- src/syntux/session.rs | 38 +++++++++++++++++++++++++++----------- src/utils.rs | 1 + 6 files changed, 38 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index d0ef489e2ca..95fc4adec8d 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -27,7 +27,7 @@ pub enum FileName { impl From for FileName { fn from(name: rustc_span::FileName) -> FileName { match name { - rustc_span::FileName::Real(p) => FileName::Real(p), + rustc_span::FileName::Real(p) => FileName::Real(p.into_local_path()), rustc_span::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, _ => unreachable!(), } diff --git a/src/expr.rs b/src/expr.rs index ed10a54c2a3..ef7278a3a87 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -322,7 +322,11 @@ pub(crate) fn format_expr( } // We do not format these expressions yet, but they should still // satisfy our width restrictions. - ast::ExprKind::LlvmInlineAsm(..) => Some(context.snippet(expr.span).to_owned()), + // Style Guide RFC for InlineAsm variant pending + // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 + ast::ExprKind::LlvmInlineAsm(..) | ast::ExprKind::InlineAsm(..) => { + Some(context.snippet(expr.span).to_owned()) + } ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) diff --git a/src/macros.rs b/src/macros.rs index cec5d873693..77d670dca59 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1204,6 +1204,7 @@ pub(crate) fn convert_try_mac( kind: ast::ExprKind::Try(parser.parse_expr().ok()?), span: mac.span(), // incorrect span, but shouldn't matter too much attrs: ast::AttrVec::new(), + tokens: Some(ts), }) } else { None diff --git a/src/source_file.rs b/src/source_file.rs index 4f02d8224e2..1d22c25d922 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -68,7 +68,9 @@ where impl From<&FileName> for rustc_span::FileName { fn from(filename: &FileName) -> rustc_span::FileName { match filename { - FileName::Real(path) => rustc_span::FileName::Real(path.to_owned()), + FileName::Real(path) => { + rustc_span::FileName::Real(rustc_span::RealFileName::Named(path.to_owned())) + } FileName::Stdin => rustc_span::FileName::Custom("stdin".to_owned()), } } diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 00f12b32237..5045eab29dd 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -66,7 +66,8 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } if let Some(primary_span) = &db.span.primary_span() { let file_name = self.source_map.span_to_filename(*primary_span); - if let rustc_span::FileName::Real(ref path) = file_name { + if let rustc_span::FileName::Real(rustc_span::RealFileName::Named(ref path)) = file_name + { if self .ignore_path_set .is_match(&FileName::Real(path.to_path_buf())) @@ -162,7 +163,9 @@ impl ParseSess { pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { self.parse_sess .source_map() - .get_source_file(&rustc_span::FileName::Real(path.to_path_buf())) + .get_source_file(&rustc_span::FileName::Real( + rustc_span::RealFileName::Named(path.to_path_buf()), + )) .is_some() } @@ -277,7 +280,7 @@ mod tests { use crate::config::IgnoreList; use crate::is_nightly_channel; use crate::utils::mk_sp; - use rustc_span::{FileName as SourceMapFileName, MultiSpan, DUMMY_SP}; + use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP}; use std::path::PathBuf; struct TestEmitter { @@ -337,7 +340,10 @@ mod tests { let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); - source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + source_map.new_source_file( + SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + source, + ); let mut emitter = build_emitter( Rc::clone(&num_emitted_errors), Rc::clone(&can_reset_errors), @@ -361,7 +367,10 @@ mod tests { let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); - source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + source_map.new_source_file( + SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + source, + ); let mut emitter = build_emitter( Rc::clone(&num_emitted_errors), Rc::clone(&can_reset_errors), @@ -384,7 +393,10 @@ mod tests { let can_reset_errors = Rc::new(RefCell::new(false)); let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); - source_map.new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), source); + source_map.new_source_file( + SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + source, + ); let mut emitter = build_emitter( Rc::clone(&num_emitted_errors), Rc::clone(&can_reset_errors), @@ -411,12 +423,16 @@ mod tests { let foo_source = String::from(r#"pub fn foo() { 1x; }"#); let fatal_source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); - source_map - .new_source_file(SourceMapFileName::Real(PathBuf::from("bar.rs")), bar_source); - source_map - .new_source_file(SourceMapFileName::Real(PathBuf::from("foo.rs")), foo_source); source_map.new_source_file( - SourceMapFileName::Real(PathBuf::from("fatal.rs")), + SourceMapFileName::Real(RealFileName::Named(PathBuf::from("bar.rs"))), + bar_source, + ); + source_map.new_source_file( + SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + foo_source, + ); + source_map.new_source_file( + SourceMapFileName::Real(RealFileName::Named(PathBuf::from("fatal.rs"))), fatal_source, ); let mut emitter = build_emitter( diff --git a/src/utils.rs b/src/utils.rs index f82bdd501cf..bb0c6b7fb22 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -487,6 +487,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Continue(..) | ast::ExprKind::Err | ast::ExprKind::Field(..) + | ast::ExprKind::InlineAsm(..) | ast::ExprKind::LlvmInlineAsm(..) | ast::ExprKind::Let(..) | ast::ExprKind::Path(..) -- cgit 1.4.1-3-g733a5 From bc9a0b29743188899eef4dd7dfb5248d18e32e3b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 2 Dec 2019 16:20:17 -0800 Subject: Switch to std::error::Error for errors (#3948) --- Cargo.lock | 29 ++++++++++++++++++++++++++++- Cargo.toml | 3 ++- src/bin/main.rs | 37 +++++++++++++++++++------------------ src/config/file_lines.rs | 19 ++++++++++++++----- src/config/mod.rs | 9 +++++++-- src/format-diff/main.rs | 35 ++++++++--------------------------- src/lib.rs | 31 +++++++++++++++---------------- 7 files changed, 93 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 5760a47ef4a..1636734872b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayref" version = "0.3.5" @@ -1044,13 +1049,13 @@ name = "rustfmt-nightly" version = "1.4.17" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1072,6 +1077,7 @@ dependencies = [ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1262,6 +1268,24 @@ dependencies = [ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thiserror" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thiserror-impl 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread_local" version = "0.3.6" @@ -1385,6 +1409,7 @@ dependencies = [ "checksum annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" "checksum annotate-snippets 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" @@ -1516,6 +1541,8 @@ dependencies = [ "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cc6b305ec0e323c7b6cfff6098a22516e0063d0bb7c3d88660a890217dca099a" +"checksum thiserror-impl 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45ba8d810d9c48fc456b7ad54574e8bfb7c7918a57ad7a6e6a0985d7959e8597" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" diff --git a/Cargo.toml b/Cargo.toml index 9da63b39477..995e3adcb35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,6 @@ env_logger = "0.6" getopts = "0.2" derive-new = "0.5" cargo_metadata = "0.8" -failure = "0.1.3" bytecount = "0.6" unicode-width = "0.1.5" unicode_categories = "0.1.1" @@ -57,6 +56,8 @@ annotate-snippets = { version = "0.6", features = ["ansi_term"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } lazy_static = "1.0.0" +anyhow = "1.0" +thiserror = "1.0" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/bin/main.rs b/src/bin/main.rs index 661502a2e0e..4a62766a85d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,6 +1,7 @@ +use anyhow::{format_err, Result}; use env_logger; -use failure::{err_msg, format_err, Error as FailureError, Fail}; use io::Error as IoError; +use thiserror::Error; use rustfmt_nightly as rustfmt; @@ -59,27 +60,27 @@ enum Operation { } /// Rustfmt operations errors. -#[derive(Fail, Debug)] +#[derive(Error, Debug)] pub enum OperationError { /// An unknown help topic was requested. - #[fail(display = "Unknown help topic: `{}`.", _0)] + #[error("Unknown help topic: `{0}`.")] UnknownHelpTopic(String), /// An unknown print-config option was requested. - #[fail(display = "Unknown print-config option: `{}`.", _0)] + #[error("Unknown print-config option: `{0}`.")] UnknownPrintConfigTopic(String), /// Attempt to generate a minimal config from standard input. - #[fail(display = "The `--print-config=minimal` option doesn't work with standard input.")] + #[error("The `--print-config=minimal` option doesn't work with standard input.")] MinimalPathWithStdin, /// An io error during reading or writing. - #[fail(display = "io error: {}", _0)] + #[error("io error: {0}")] IoError(IoError), /// Attempt to use --check with stdin, which isn't currently /// supported. - #[fail(display = "The `--check` option is not supported with standard input.")] + #[error("The `--check` option is not supported with standard input.")] CheckWithStdin, /// Attempt to use --emit=json with stdin, which isn't currently /// supported. - #[fail(display = "Using `--emit` other than stdout is not supported with standard input.")] + #[error("Using `--emit` other than stdout is not supported with standard input.")] EmitWithStdin, } @@ -192,7 +193,7 @@ fn is_nightly() -> bool { } // Returned i32 is an exit code -fn execute(opts: &Options) -> Result { +fn execute(opts: &Options) -> Result { let matches = opts.parse(env::args().skip(1))?; let options = GetOptsOptions::from_matches(&matches)?; @@ -214,7 +215,7 @@ fn execute(opts: &Options) -> Result { Ok(0) } Operation::ConfigOutputDefault { path } => { - let toml = Config::default().all_options().to_toml().map_err(err_msg)?; + let toml = Config::default().all_options().to_toml()?; if let Some(path) = path { let mut file = File::create(path)?; file.write_all(toml.as_bytes())?; @@ -233,7 +234,7 @@ fn execute(opts: &Options) -> Result { let file = file.canonicalize().unwrap_or(file); let (config, _) = load_config(Some(file.parent().unwrap()), Some(options.clone()))?; - let toml = config.all_options().to_toml().map_err(err_msg)?; + let toml = config.all_options().to_toml()?; io::stdout().write_all(toml.as_bytes())?; Ok(0) @@ -246,7 +247,7 @@ fn execute(opts: &Options) -> Result { } } -fn format_string(input: String, options: GetOptsOptions) -> Result { +fn format_string(input: String, options: GetOptsOptions) -> Result { // try to read config from local directory let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?; @@ -287,7 +288,7 @@ fn format( files: Vec, minimal_config_path: Option, options: &GetOptsOptions, -) -> Result { +) -> Result { options.verify_file_lines(&files); let (config, config_path) = load_config(None, Some(options.clone()))?; @@ -335,7 +336,7 @@ fn format( // that were used during formatting as TOML. if let Some(path) = minimal_config_path { let mut file = File::create(path)?; - let toml = session.config.used_options().to_toml().map_err(err_msg)?; + let toml = session.config.used_options().to_toml()?; file.write_all(toml.as_bytes())?; } @@ -514,7 +515,7 @@ struct GetOptsOptions { } impl GetOptsOptions { - pub fn from_matches(matches: &Matches) -> Result { + pub fn from_matches(matches: &Matches) -> Result { let mut options = GetOptsOptions::default(); options.verbose = matches.opt_present("verbose"); options.quiet = matches.opt_present("quiet"); @@ -535,7 +536,7 @@ impl GetOptsOptions { options.error_on_unformatted = Some(true); } if let Some(ref file_lines) = matches.opt_str("file-lines") { - options.file_lines = file_lines.parse().map_err(err_msg)?; + options.file_lines = file_lines.parse()?; } } else { let mut unstable_options = vec![]; @@ -684,7 +685,7 @@ impl CliOptions for GetOptsOptions { } } -fn edition_from_edition_str(edition_str: &str) -> Result { +fn edition_from_edition_str(edition_str: &str) -> Result { match edition_str { "2015" => Ok(Edition::Edition2015), "2018" => Ok(Edition::Edition2018), @@ -692,7 +693,7 @@ fn edition_from_edition_str(edition_str: &str) -> Result } } -fn emit_mode_from_emit_str(emit_str: &str) -> Result { +fn emit_mode_from_emit_str(emit_str: &str) -> Result { match emit_str { "files" => Ok(EmitMode::Files), "stdout" => Ok(EmitMode::Stdout), diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 95fc4adec8d..18ae2fd2c47 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -9,6 +9,7 @@ use std::{cmp, fmt, iter, str}; use rustc_span::{self, SourceFile}; use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; +use thiserror::Error; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { @@ -287,12 +288,20 @@ fn canonicalize_path_string(file: &FileName) -> Option { } } +#[derive(Error, Debug)] +pub enum FileLinesError { + #[error("{0}")] + Json(json::Error), + #[error("Can't canonicalize {0}")] + CannotCanonicalize(FileName), +} + // This impl is needed for `Config::override_value` to work for use in tests. impl str::FromStr for FileLines { - type Err = String; + type Err = FileLinesError; - fn from_str(s: &str) -> Result { - let v: Vec = json::from_str(s).map_err(|e| e.to_string())?; + fn from_str(s: &str) -> Result { + let v: Vec = json::from_str(s).map_err(FileLinesError::Json)?; let mut m = HashMap::new(); for js in v { let (s, r) = JsonSpan::into_tuple(js)?; @@ -310,10 +319,10 @@ pub struct JsonSpan { } impl JsonSpan { - fn into_tuple(self) -> Result<(FileName, Range), String> { + fn into_tuple(self) -> Result<(FileName, Range), FileLinesError> { let (lo, hi) = self.range; let canonical = canonicalize_path_string(&self.file) - .ok_or_else(|| format!("Can't canonicalize {}", &self.file))?; + .ok_or_else(|| FileLinesError::CannotCanonicalize(self.file))?; Ok((canonical, Range::new(lo, hi))) } } diff --git a/src/config/mod.rs b/src/config/mod.rs index 1d0217f27b1..cf00eed0565 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use std::{env, fs}; use regex::Regex; +use thiserror::Error; use crate::config::config_type::ConfigType; #[allow(unreachable_pub)] @@ -157,8 +158,12 @@ create_config! { files that would be formated when used with `--check` mode. "; } +#[derive(Error, Debug)] +#[error("Could not output config: {0}")] +pub struct ToTomlError(toml::ser::Error); + impl PartialConfig { - pub fn to_toml(&self) -> Result { + pub fn to_toml(&self) -> Result { // Non-user-facing options can't be specified in TOML let mut cloned = self.clone(); cloned.file_lines = None; @@ -166,7 +171,7 @@ impl PartialConfig { cloned.width_heuristics = None; cloned.print_misformatted_file_names = None; - ::toml::to_string(&cloned).map_err(|e| format!("Could not output config: {}", e)) + ::toml::to_string(&cloned).map_err(ToTomlError) } } diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index afe1ec5d068..a73d2da4d03 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -6,12 +6,11 @@ use env_logger; #[macro_use] -extern crate failure; -#[macro_use] extern crate log; use regex; use serde::{Deserialize, Serialize}; use serde_json as json; +use thiserror::Error; use std::collections::HashSet; use std::io::{self, BufRead}; @@ -27,32 +26,14 @@ use structopt::StructOpt; /// We only want to format rust files by default. const DEFAULT_PATTERN: &str = r".*\.rs"; -#[derive(Fail, Debug)] +#[derive(Error, Debug)] enum FormatDiffError { - #[fail(display = "{}", _0)] - IncorrectOptions(#[cause] getopts::Fail), - #[fail(display = "{}", _0)] - IncorrectFilter(#[cause] regex::Error), - #[fail(display = "{}", _0)] - IoError(#[cause] io::Error), -} - -impl From for FormatDiffError { - fn from(fail: getopts::Fail) -> Self { - FormatDiffError::IncorrectOptions(fail) - } -} - -impl From for FormatDiffError { - fn from(err: regex::Error) -> Self { - FormatDiffError::IncorrectFilter(err) - } -} - -impl From for FormatDiffError { - fn from(fail: io::Error) -> Self { - FormatDiffError::IoError(fail) - } + #[error("{0}")] + IncorrectOptions(#[from] getopts::Fail), + #[error("{0}")] + IncorrectFilter(#[from] regex::Error), + #[error("{0}")] + IoError(#[from] io::Error), } #[derive(StructOpt, Debug)] diff --git a/src/lib.rs b/src/lib.rs index 831eac8dc7e..5693ee85958 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,10 +17,10 @@ use std::panic; use std::path::PathBuf; use std::rc::Rc; -use failure::Fail; use ignore; use rustc_ast::ast; use rustc_span::symbol; +use thiserror::Error; use crate::comment::LineClasses; use crate::emitter::Emitter; @@ -84,45 +84,44 @@ pub(crate) mod visitor; /// The various errors that can occur during formatting. Note that not all of /// these can currently be propagated to clients. -#[derive(Fail, Debug)] +#[derive(Error, Debug)] pub enum ErrorKind { /// Line has exceeded character limit (found, maximum). - #[fail( - display = "line formatted, but exceeded maximum width \ - (maximum: {} (see `max_width` option), found: {})", - _1, _0 + #[error( + "line formatted, but exceeded maximum width \ + (maximum: {1} (see `max_width` option), found: {0})" )] LineOverflow(usize, usize), /// Line ends in whitespace. - #[fail(display = "left behind trailing whitespace")] + #[error("left behind trailing whitespace")] TrailingWhitespace, /// TODO or FIXME item without an issue number. - #[fail(display = "found {}", _0)] + #[error("found {0}")] BadIssue(Issue), /// License check has failed. - #[fail(display = "license check failed")] + #[error("license check failed")] LicenseCheck, /// Used deprecated skip attribute. - #[fail(display = "`rustfmt_skip` is deprecated; use `rustfmt::skip`")] + #[error("`rustfmt_skip` is deprecated; use `rustfmt::skip`")] DeprecatedAttr, /// Used a rustfmt:: attribute other than skip or skip::macros. - #[fail(display = "invalid attribute")] + #[error("invalid attribute")] BadAttr, /// An io error during reading or writing. - #[fail(display = "io error: {}", _0)] + #[error("io error: {0}")] IoError(io::Error), /// Parse error occurred when parsing the input. - #[fail(display = "parse error")] + #[error("parse error")] ParseError, /// The user mandated a version and the current version of Rustfmt does not /// satisfy that requirement. - #[fail(display = "version mismatch")] + #[error("version mismatch")] VersionMismatch, /// If we had formatted the given node, then we would have lost a comment. - #[fail(display = "not formatted because a comment would be lost")] + #[error("not formatted because a comment would be lost")] LostComment, /// Invalid glob pattern in `ignore` configuration option. - #[fail(display = "Invalid glob pattern found in ignore list: {}", _0)] + #[error("Invalid glob pattern found in ignore list: {0}")] InvalidGlobPattern(ignore::Error), } -- cgit 1.4.1-3-g733a5 From dead3a807d6031972559c67ac5d30c61c50b0067 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 11 Jun 2020 21:11:18 -0500 Subject: fix: backport mod resolution error handling --- src/bin/main.rs | 2 +- src/format_report_formatter.rs | 1 + src/lib.rs | 4 ++ src/modules.rs | 95 ++++++++++++++++++++++++++++-------------- src/syntux/parser.rs | 8 ++-- src/test/mod.rs | 1 + tests/target/skip/foo.rs | 5 +++ tests/target/skip/main.rs | 5 +++ 8 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 tests/target/skip/foo.rs create mode 100644 tests/target/skip/main.rs (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 4a62766a85d..9101c015fb9 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -72,7 +72,7 @@ pub enum OperationError { #[error("The `--print-config=minimal` option doesn't work with standard input.")] MinimalPathWithStdin, /// An io error during reading or writing. - #[error("io error: {0}")] + #[error("{0}")] IoError(IoError), /// Attempt to use --check with stdin, which isn't currently /// supported. diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs index 5f5d89faf39..2fc6c4e8955 100644 --- a/src/format_report_formatter.rs +++ b/src/format_report_formatter.rs @@ -162,6 +162,7 @@ fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationTy ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace | ErrorKind::IoError(_) + | ErrorKind::ModuleResolutionError(_) | ErrorKind::ParseError | ErrorKind::LostComment | ErrorKind::LicenseCheck diff --git a/src/lib.rs b/src/lib.rs index 5693ee85958..2ba476466ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ use crate::comment::LineClasses; use crate::emitter::Emitter; use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use crate::issues::Issue; +use crate::modules::ModuleResolutionError; use crate::shape::Indent; use crate::syntux::parser::DirectoryOwnership; use crate::utils::indent_next_line; @@ -110,6 +111,9 @@ pub enum ErrorKind { /// An io error during reading or writing. #[error("io error: {0}")] IoError(io::Error), + /// Error during module resolution. + #[error("{0}")] + ModuleResolutionError(#[from] ModuleResolutionError), /// Parse error occurred when parsing the input. #[error("parse error")] ParseError, diff --git a/src/modules.rs b/src/modules.rs index 915401c4682..8ecb121f9e7 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -5,11 +5,14 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; +use thiserror::Error; use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; -use crate::syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser}; +use crate::syntux::parser::{ + Directory, DirectoryOwnership, ModulePathSuccess, Parser, ParserError, +}; use crate::syntux::session::ParseSess; use crate::utils::contains_skip; @@ -29,6 +32,24 @@ pub(crate) struct ModResolver<'ast, 'sess> { recursive: bool, } +/// Represents errors while trying to resolve modules. +#[error("failed to resolve mod `{module}`: {kind}")] +#[derive(Debug, Error)] +pub struct ModuleResolutionError { + module: String, + kind: ModuleResolutionErrorKind, +} + +#[derive(Debug, Error)] +pub(crate) enum ModuleResolutionErrorKind { + /// Find a file that cannot be parsed. + #[error("cannot parse {file}")] + ParseError { file: PathBuf }, + /// File cannot be found. + #[error("{file} does not exist")] + NotFound { file: PathBuf }, +} + #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` @@ -63,7 +84,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { pub(crate) fn visit_crate( mut self, krate: &'ast ast::Crate, - ) -> Result, String> { + ) -> Result, ModuleResolutionError> { let root_filename = self.parse_sess.span_to_filename(krate.span); self.directory.path = match root_filename { FileName::Real(ref p) => p.parent().unwrap_or(Path::new("")).to_path_buf(), @@ -81,7 +102,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit `cfg_if` macro and look for module declarations. - fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { + fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResolutionError> { let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); visitor.visit_item(&item); for module_item in visitor.mods() { @@ -93,7 +114,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit modules defined inside macro calls. - fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), String> { + fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), ModuleResolutionError> { for item in module.items { if is_cfg_if(&item) { self.visit_cfg_if(Cow::Owned(item.into_inner()))?; @@ -108,7 +129,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit modules from AST. - fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), String> { + fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), ModuleResolutionError> { for item in &module.items { if is_cfg_if(item) { self.visit_cfg_if(Cow::Borrowed(item))?; @@ -125,7 +146,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, item: &'c ast::Item, sub_mod: Cow<'ast, ast::Mod>, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { let old_directory = self.directory.clone(); let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?; if let Some(sub_mod_kind) = sub_mod_kind { @@ -141,7 +162,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &self, item: &'c ast::Item, sub_mod: &Cow<'ast, ast::Mod>, - ) -> Result>, String> { + ) -> Result>, ModuleResolutionError> { if contains_skip(&item.attrs) { return Ok(None); } @@ -165,7 +186,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, sub_mod_kind: SubModKind<'c, 'ast>, _sub_mod: Cow<'ast, ast::Mod>, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { match sub_mod_kind { SubModKind::External(mod_path, _, sub_mod) => { self.file_map @@ -188,7 +209,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, sub_mod: Cow<'ast, ast::Mod>, sub_mod_kind: SubModKind<'c, 'ast>, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { match sub_mod_kind { SubModKind::External(mod_path, directory_ownership, sub_mod) => { let directory = Directory { @@ -226,7 +247,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &mut self, sub_mod: Cow<'ast, ast::Mod>, directory: Option, - ) -> Result<(), String> { + ) -> Result<(), ModuleResolutionError> { if let Some(directory) = directory { self.directory = directory; } @@ -242,7 +263,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mod_name: symbol::Ident, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, - ) -> Result>, String> { + ) -> Result>, ModuleResolutionError> { let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, @@ -252,16 +273,20 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(None); } return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { - Some((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Some((m, _)) => Ok(Some(SubModKind::External( + Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), + Ok((m, _)) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, Cow::Owned(m), ))), - None => Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )), + Err(ParserError::ParseError) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::ParseError { file: path }, + }), + Err(..) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { file: path }, + }), }; } @@ -291,22 +316,26 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { - Some((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Some((m, _)) if outside_mods_empty => { + Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), + Ok((m, _)) if outside_mods_empty => { Ok(Some(SubModKind::External(path, ownership, Cow::Owned(m)))) } - Some((m, _)) => { + Ok((m, _)) => { mods_outside_ast.push((path.clone(), ownership, Cow::Owned(m))); if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } - None if outside_mods_empty => Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )), - None => { + Err(ParserError::ParseError) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::ParseError { file: path }, + }), + Err(..) if outside_mods_empty => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { file: path }, + }), + Err(..) => { if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); } @@ -320,10 +349,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } Err(mut e) => { e.cancel(); - Err(format!( - "Failed to find module {} in {:?} {:?}", - mod_name, self.directory.path, relative, - )) + Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { + file: self.directory.path.clone(), + }, + }) } } } @@ -379,9 +410,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } let m = match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.inner) { - Some((_, ref attrs)) if contains_skip(attrs) => continue, - Some((m, _)) => m, - None => continue, + Ok((_, ref attrs)) if contains_skip(attrs) => continue, + Ok((m, _)) => m, + Err(..) => continue, }; result.push(( diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 831554829e2..89db0f5553c 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -106,7 +106,7 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, path: &Path, span: Span, - ) -> Option<(ast::Mod, Vec)> { + ) -> Result<(ast::Mod, Vec), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); match parser.parse_mod(&TokenKind::Eof) { @@ -119,8 +119,10 @@ impl<'a> Parser<'a> { } })); match result { - Ok(Some(m)) => Some(m), - _ => None, + Ok(Some(m)) => Ok(m), + Ok(None) => Err(ParserError::ParseError), + Err(..) if path.exists() => Err(ParserError::ParseError), + Err(_) => Err(ParserError::ParsePanicError), } } diff --git a/src/test/mod.rs b/src/test/mod.rs index 6b7a9365c6f..e6497f48e0f 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -40,6 +40,7 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ "cfg_mod/bar.rs", "cfg_mod/foo.rs", "cfg_mod/wasm32.rs", + "skip/foo.rs", ]; fn init_log() { diff --git a/tests/target/skip/foo.rs b/tests/target/skip/foo.rs new file mode 100644 index 00000000000..776658f8fe5 --- /dev/null +++ b/tests/target/skip/foo.rs @@ -0,0 +1,5 @@ +#![rustfmt::skip] + +fn +foo() +{} diff --git a/tests/target/skip/main.rs b/tests/target/skip/main.rs new file mode 100644 index 00000000000..2d33bef9251 --- /dev/null +++ b/tests/target/skip/main.rs @@ -0,0 +1,5 @@ +mod foo; + +fn main() { + println!("Hello, world!"); +} -- cgit 1.4.1-3-g733a5 From ce1a3efff03a17af6f0f8f93c07e3abe9058762e Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 11 Jun 2020 21:49:40 -0500 Subject: fix: backport fix for submod parser errors --- src/formatting.rs | 14 +++++++------- src/modules.rs | 4 ++-- src/syntux/parser.rs | 12 +++++++++++- src/test/mod.rs | 34 ++++++++++++++++++++++++++++++++-- tests/parser/issue-4126/invalid.rs | 6 ++++++ tests/parser/issue-4126/lib.rs | 1 + 6 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 tests/parser/issue-4126/invalid.rs create mode 100644 tests/parser/issue-4126/lib.rs (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 8178342f28c..28d111ba623 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -62,7 +62,7 @@ fn format_project( let main_file = input.file_name(); let input_is_stdin = main_file == FileName::Stdin; - let mut parse_session = ParseSess::new(config)?; + let parse_session = ParseSess::new(config)?; if config.skip_children() && parse_session.ignore_file(&main_file) { return Ok(FormatReport::new()); } @@ -82,10 +82,6 @@ fn format_project( return Ok(report); } }; - timer = timer.done_parsing(); - - // Suppress error output if we have to do any further parsing. - parse_session.set_silent_emitter(); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( @@ -93,8 +89,12 @@ fn format_project( directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), !input_is_stdin && !config.skip_children(), ) - .visit_crate(&krate) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + .visit_crate(&krate)?; + + timer = timer.done_parsing(); + + // Suppress error output if we have to do any further parsing. + context.parse_session.set_silent_emitter(); for (path, module) in files { let should_ignore = !input_is_stdin && context.ignore_file(&path); diff --git a/src/modules.rs b/src/modules.rs index 8ecb121f9e7..cbe663cb412 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -36,8 +36,8 @@ pub(crate) struct ModResolver<'ast, 'sess> { #[error("failed to resolve mod `{module}`: {kind}")] #[derive(Debug, Error)] pub struct ModuleResolutionError { - module: String, - kind: ModuleResolutionErrorKind, + pub(crate) module: String, + pub(crate) kind: ModuleResolutionErrorKind, } #[derive(Debug, Error)] diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 89db0f5553c..decad02d049 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -119,7 +119,17 @@ impl<'a> Parser<'a> { } })); match result { - Ok(Some(m)) => Ok(m), + Ok(Some(m)) => { + if !sess.has_errors() { + return Ok(m); + } + + if sess.can_reset_errors() { + sess.reset_errors(); + return Ok(m); + } + Err(ParserError::ParseError) + } Ok(None) => Err(ParserError::ParseError), Err(..) if path.exists() => Err(ParserError::ParseError), Err(_) => Err(ParserError::ParsePanicError), diff --git a/src/test/mod.rs b/src/test/mod.rs index e6497f48e0f..57b5f2a78cd 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -11,10 +11,12 @@ use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; use crate::formatting::{ReportedErrors, SourceFile}; -use crate::is_nightly_channel; +use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; -use crate::{FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::{ + is_nightly_channel, ErrorKind, FormatReport, FormatReportFormatterBuilder, Input, Session, +}; mod configuration_snippet; @@ -483,6 +485,34 @@ fn format_lines_errors_are_reported_with_tabs() { assert!(session.has_formatting_errors()); } +#[test] +fn parser_errors_in_submods_are_surfaced() { + // See also https://github.com/rust-lang/rustfmt/issues/4126 + let filename = "tests/parser/issue-4126/lib.rs"; + let input_file = PathBuf::from(filename); + let exp_mod_name = "invalid"; + let config = read_config(&input_file); + let mut session = Session::::new(config, None); + if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) = + session.format(Input::File(filename.into())) + { + assert_eq!(&module, exp_mod_name); + if let ModuleResolutionErrorKind::ParseError { + file: unparseable_file, + } = kind + { + assert_eq!( + unparseable_file, + PathBuf::from("tests/parser/issue-4126/invalid.rs"), + ); + } else { + panic!("Expected parser error"); + } + } else { + panic!("Expected ModuleResolution operation error"); + } +} + // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: Vec, opt_config: &Option) -> (Vec, u32, u32) { diff --git a/tests/parser/issue-4126/invalid.rs b/tests/parser/issue-4126/invalid.rs new file mode 100644 index 00000000000..7709c848464 --- /dev/null +++ b/tests/parser/issue-4126/invalid.rs @@ -0,0 +1,6 @@ +fn foo() { + if bar && if !baz { + next_is_none = Some(true); + } + println!("foo"); +} diff --git a/tests/parser/issue-4126/lib.rs b/tests/parser/issue-4126/lib.rs new file mode 100644 index 00000000000..aac63e3557f --- /dev/null +++ b/tests/parser/issue-4126/lib.rs @@ -0,0 +1 @@ +mod invalid; -- cgit 1.4.1-3-g733a5 From 5db71529626ca7c8316b93c4763cf3b2f1989a95 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 11 Jun 2020 23:17:38 -0500 Subject: fix: backport fix for #4020 --- src/comment.rs | 10 ++++++---- tests/target/issue-4020.rs | 9 +++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 tests/target/issue-4020.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 518f2bcda0c..7a0183f59af 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -91,8 +91,9 @@ impl<'a> CommentStyle<'a> { | CommentStyle::TripleSlash | CommentStyle::Custom(..) | CommentStyle::Doc => "", - CommentStyle::DoubleBullet => " **/", - CommentStyle::SingleBullet | CommentStyle::Exclamation => " */", + CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation => { + " */" + } } } @@ -101,8 +102,9 @@ impl<'a> CommentStyle<'a> { CommentStyle::DoubleSlash => "// ", CommentStyle::TripleSlash => "/// ", CommentStyle::Doc => "//! ", - CommentStyle::SingleBullet | CommentStyle::Exclamation => " * ", - CommentStyle::DoubleBullet => " ** ", + CommentStyle::SingleBullet | CommentStyle::DoubleBullet | CommentStyle::Exclamation => { + " * " + } CommentStyle::Custom(opener) => opener, } } diff --git a/tests/target/issue-4020.rs b/tests/target/issue-4020.rs new file mode 100644 index 00000000000..f29ecec028b --- /dev/null +++ b/tests/target/issue-4020.rs @@ -0,0 +1,9 @@ +// rustfmt-wrap_comments: true + +/** foobar */ +const foo1: u32 = 0; + +/** + * foobar + */ +const foo2: u32 = 0; -- cgit 1.4.1-3-g733a5 From 796d6eafa40ae26e245be92c74709151eb343447 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 11 Jun 2020 23:29:51 -0500 Subject: fix: backport fix for #4079 --- src/comment.rs | 5 ++--- tests/source/issue-4079.rs | 8 ++++++++ tests/target/issue-4079.rs | 11 +++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/source/issue-4079.rs create mode 100644 tests/target/issue-4079.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 7a0183f59af..1da62d17681 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -529,7 +529,6 @@ impl<'a> CommentRewrite<'a> { .checked_sub(closer.len() + opener.len()) .unwrap_or(1); let indent_str = shape.indent.to_string_with_newline(config).to_string(); - let fmt_indent = shape.indent + (opener.len() - line_start.len()); let mut cr = CommentRewrite { result: String::with_capacity(orig.len() * 2), @@ -540,14 +539,14 @@ impl<'a> CommentRewrite<'a> { comment_line_separator: format!("{}{}", indent_str, line_start), max_width, indent_str, - fmt_indent, + fmt_indent: shape.indent, fmt: StringFormat { opener: "", closer: "", line_start, line_end: "", - shape: Shape::legacy(max_width, fmt_indent), + shape: Shape::legacy(max_width, shape.indent), trim_end: true, config, }, diff --git a/tests/source/issue-4079.rs b/tests/source/issue-4079.rs new file mode 100644 index 00000000000..eb1ce5ed2a5 --- /dev/null +++ b/tests/source/issue-4079.rs @@ -0,0 +1,8 @@ +// rustfmt-wrap_comments: true + +/*! + * Lorem ipsum dolor sit amet, consectetur adipiscing elit. In lacinia + * ullamcorper lorem, non hendrerit enim convallis ut. Curabitur id sem volutpat + */ + +/*! Lorem ipsum dolor sit amet, consectetur adipiscing elit. In lacinia ullamcorper lorem, non hendrerit enim convallis ut. Curabitur id sem volutpat */ diff --git a/tests/target/issue-4079.rs b/tests/target/issue-4079.rs new file mode 100644 index 00000000000..1871c5b8a13 --- /dev/null +++ b/tests/target/issue-4079.rs @@ -0,0 +1,11 @@ +// rustfmt-wrap_comments: true + +/*! + * Lorem ipsum dolor sit amet, consectetur adipiscing elit. In lacinia + * ullamcorper lorem, non hendrerit enim convallis ut. Curabitur id sem + * volutpat + */ + +/*! Lorem ipsum dolor sit amet, consectetur adipiscing elit. In lacinia + * ullamcorper lorem, non hendrerit enim convallis ut. Curabitur id sem + * volutpat */ -- cgit 1.4.1-3-g733a5 From a36e7c7981c2058474734887e83a04de43e741ac Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 22 Dec 2019 00:31:59 +0900 Subject: Use correct span for match arms with the leading pipe and attributes (#3975) --- src/matches.rs | 1 + tests/target/issue-3974.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 tests/target/issue-3974.rs (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index c6b17122326..b5ca49b38bc 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -45,6 +45,7 @@ impl<'a> ArmWrapper<'a> { impl<'a> Spanned for ArmWrapper<'a> { fn span(&self) -> Span { if let Some(lo) = self.beginning_vert { + let lo = std::cmp::min(lo, self.arm.span().lo()); mk_sp(lo, self.arm.span().hi()) } else { self.arm.span() diff --git a/tests/target/issue-3974.rs b/tests/target/issue-3974.rs new file mode 100644 index 00000000000..a9f992ebd5c --- /dev/null +++ b/tests/target/issue-3974.rs @@ -0,0 +1,10 @@ +fn emulate_foreign_item() { + match link_name { + // A comment here will duplicate the attribute + #[rustfmt::skip] + | "pthread_mutexattr_init" + | "pthread_mutexattr_settype" + | "pthread_mutex_init" + => {} + } +} -- cgit 1.4.1-3-g733a5 From da18032ba4756dfc670fff2232ca2269b94e24ff Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 27 Jun 2020 13:15:54 -0500 Subject: deps: bump rustc-ap* to v666 --- Cargo.lock | 260 ++++++++++++++++++++++++++++----------------------------- Cargo.toml | 18 ++-- src/chains.rs | 4 +- src/items.rs | 19 ++--- src/visitor.rs | 8 +- 5 files changed, 150 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 9f028ed24de..b1765938bde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -503,7 +503,7 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -739,79 +739,79 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "664.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "666.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -826,10 +826,10 @@ dependencies = [ "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_graphviz 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_graphviz 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -840,15 +840,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -857,57 +857,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_passes 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_passes 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_feature" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_graphviz" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -915,7 +915,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -926,25 +926,25 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -953,35 +953,36 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_arena 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_arena 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -989,16 +990,16 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "664.0.0" +version = "666.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1008,11 +1009,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-hash" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "rustc-rayon" @@ -1076,15 +1074,15 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_expand 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_expand 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1519,27 +1517,27 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-rustc_arena 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c6683b49209f8b132bec33dc6b6c8f9958c8c94eb3586d4cb495e092b61c1da" -"checksum rustc-ap-rustc_ast 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b21784d92fb2d584800f528866f00fe814f73abda794f406bfd1fbb2f1ca7f7" -"checksum rustc-ap-rustc_ast_passes 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "820c46fde7ef1df0432073090d775f097b7279ca75ea34ba954081ce4b884d4c" -"checksum rustc-ap-rustc_ast_pretty 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "013db7dd198fe95962d2cefa5bd0b350cf2028af77c169b17b4baa9c3bbf77d1" -"checksum rustc-ap-rustc_attr 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b5a85c90eb341eec543600ffdd9e262da5ea72a73a23ae4ca2f4ab8cd1a188" -"checksum rustc-ap-rustc_data_structures 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92e4c6cb6c43ee9031a71709dc12853b358253c2b41d12a26379994fab625e0" -"checksum rustc-ap-rustc_errors 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0aa79423260c1b9e2f856e144e040f606b0f5d43644408375becf9d7bcdf86" -"checksum rustc-ap-rustc_expand 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c07d76ba2a1b7d4325a2ed21d6345ccebd89ddc6666a1535a6edd489fb4cbc11" -"checksum rustc-ap-rustc_feature 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1bbd625705c1db42a0c7503736292813d7b76ada5da20578fb55c63228c80ab5" -"checksum rustc-ap-rustc_fs_util 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34cca6e2942fa0b059c582437ead666d5bcf20fa7c242599e2bbea9b609f29ae" -"checksum rustc-ap-rustc_graphviz 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13d6a029b81f5e02da85763f82c135507f278a4a0c776432c728520563059529" -"checksum rustc-ap-rustc_index 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bae50852d303e230b2781c994513788136dc6c2fe4ebe032959f0b990a425767" -"checksum rustc-ap-rustc_lexer 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b7186e74aa2d31bf0e2454325fefcdf0a3da77d9344134592144b9e40d45b15d" -"checksum rustc-ap-rustc_macros 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc1add04e9d2301164118660ee0bc3266e9a7b1973fc2303fdbe002a12e5401" -"checksum rustc-ap-rustc_parse 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9cd7fc4968bd60084f2fa4f280fa450b0cf98660a7983d6b93a7ae41b6d1d322" -"checksum rustc-ap-rustc_serialize 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00bf4c110271d9a2b7dfd2c6eb82e56fd80606a8bad6c102e158c54e44044046" -"checksum rustc-ap-rustc_session 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "431cf962de71d4c03fb877d54f331ec36eca77350b0539017abc40a4410d6501" -"checksum rustc-ap-rustc_span 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b912039640597624f4bcb75f1e1fcfa5710267d715a7f73a6336baef341b23d1" -"checksum rustc-ap-rustc_target 664.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51347a9dadc5ad0b5916cc12d42624b31955285ad13745dbe72f0140038b84e9" +"checksum rustc-ap-rustc_arena 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cee1cd09e7ade1ad3b8ab554aa339dcc47cdbb8782275eef92dcf50090865d97" +"checksum rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fe6eb9ce5def918609f3548ee5f96c1cd56e8caadb765d2611e414a0bdb52df" +"checksum rustc-ap-rustc_ast_passes 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b630662cc3812e757f6f0cc72f1c3b928ac231a50a0bd34ed7f460b5781f090b" +"checksum rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55ddb88f73c74d5e695ae5541aab044e69d608984acbbebd9a59f4a55dfee4f7" +"checksum rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f0668c1974f76ebd7e1cf566b62959ee7ea374a46e4136632b27ed6d80ead2" +"checksum rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5aa565bf5c940bfe1b9be9974e898cf90e01746186e17f6d103b40107804416" +"checksum rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f78e3c17e3d2e8fc004ebcf57fe5b688554635211c3346f8c70fe664545fa777" +"checksum rustc-ap-rustc_expand 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4ec52e2e7af6aef362fc9defaa3f618a84689d0f6865f9f322976cd8dab3112" +"checksum rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca4764c14f84aaede3eac0d2d546c3b5592705a1b8bf23ccf025de5bf98d0f" +"checksum rustc-ap-rustc_fs_util 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c19245e259a656c5bf8a51a94598db41c36563c9f7968c54ece91a8918bb71" +"checksum rustc-ap-rustc_graphviz 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd9fa221daaaf6828ee914b1fa4ef20839e8e8fcba9414205a0a3f06cec8a470" +"checksum rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "666e394504050d1242869fe1d4880ea6d856183927d999b739c8cd32c8f046f0" +"checksum rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e00c526f9f8430ea4cd2178d25b02bfc7debe6677350c57292f92f50e65d2fe" +"checksum rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4395519245c4a45193c2f15df08e6523188db7eafd29d21646dff99335ce50" +"checksum rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc28692867433a3201ce7f1505c2abfca689dcb7394ed1fc64e121485bf7ef3" +"checksum rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "026a99c3a6a3d477b69696102722806082913ea90f40f7bfc4b97c1ae0d60bbd" +"checksum rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55db1b56890f90b58f894b53e9fbe821b735a094f7e10f9e60dc1b9801c4f457" +"checksum rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e78345ae6f0905dded335db76cd082edfcf1b383f7e2c218f6f7d4f5583073c5" +"checksum rustc-ap-rustc_target 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98d935fb3584b36ace9e981d58a59efeda22d9439dce6ea9303f4fd24e45f954" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" +"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" "checksum rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" "checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" diff --git a/Cargo.toml b/Cargo.toml index 0b454f0103e..f33eb7244d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "664.0.0" +version = "666.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "664.0.0" +version = "666.0.0" diff --git a/src/chains.rs b/src/chains.rs index ebf562c093d..8a0b416632b 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -145,7 +145,7 @@ impl ChainItemKind { fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) { let (kind, span) = match expr.kind { - ast::ExprKind::MethodCall(ref segment, ref expressions) => { + ast::ExprKind::MethodCall(ref segment, ref expressions, _) => { let types = if let Some(ref generic_args) = segment.args { if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { data.args @@ -399,7 +399,7 @@ impl Chain { // is a try! macro, we'll convert it to shorthand when the option is set. fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option { match expr.kind { - ast::ExprKind::MethodCall(_, ref expressions) => { + ast::ExprKind::MethodCall(_, ref expressions, _) => { Some(Self::convert_try(&expressions[0], context)) } ast::ExprKind::Field(ref subexpr, _) diff --git a/src/items.rs b/src/items.rs index 4a1af8e09a1..e772164862d 100644 --- a/src/items.rs +++ b/src/items.rs @@ -595,23 +595,16 @@ impl<'a> FmtVisitor<'a> { } fn is_type(ty: &Option>) -> bool { - match ty { - None => true, - Some(lty) => match lty.kind.opaque_top_hack() { - None => true, - Some(_) => false, - }, + if let Some(lty) = ty { + if let ast::TyKind::ImplTrait(..) = lty.kind { + return false; + } } + true } fn is_opaque(ty: &Option>) -> bool { - match ty { - None => false, - Some(lty) => match lty.kind.opaque_top_hack() { - None => false, - Some(_) => true, - }, - } + !is_type(ty) } fn both_type( diff --git a/src/visitor.rs b/src/visitor.rs index ef6a7ff7ba6..39421491697 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -671,15 +671,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { }; let rewrite = match ty { None => rewrite_associated(), - Some(ty) => match ty.kind.opaque_top_hack() { - Some(generic_bounds) => rewrite_opaque_impl_type( + Some(ty) => match ty.kind { + ast::TyKind::ImplTrait(_, ref bounds) => rewrite_opaque_impl_type( &self.get_context(), ii.ident, generics, - generic_bounds, + bounds, self.block_indent, ), - None => rewrite_associated(), + _ => rewrite_associated(), }, }; self.push_rewrite(ii.span, rewrite); -- cgit 1.4.1-3-g733a5 From b243075d756e0b77e88a03fd839475b3b4ef5318 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 9 Jul 2020 23:15:08 -0500 Subject: deps: bump rustc-ap-* to v668 --- Cargo.lock | 248 +++++++++++++++++++++++++++++------------------------------ Cargo.toml | 18 ++--- src/types.rs | 2 +- 3 files changed, 134 insertions(+), 134 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index b1765938bde..5c28ad4412d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -739,79 +739,79 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "666.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "668.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -826,9 +826,9 @@ dependencies = [ "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_graphviz 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_graphviz 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -840,15 +840,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -857,57 +857,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_passes 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_passes 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_feature" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_graphviz" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -915,7 +915,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -926,25 +926,25 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -953,36 +953,36 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_arena 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_arena 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -990,16 +990,16 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "666.0.0" +version = "668.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1074,15 +1074,15 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_expand 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_expand 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1517,25 +1517,25 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-rustc_arena 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cee1cd09e7ade1ad3b8ab554aa339dcc47cdbb8782275eef92dcf50090865d97" -"checksum rustc-ap-rustc_ast 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0fe6eb9ce5def918609f3548ee5f96c1cd56e8caadb765d2611e414a0bdb52df" -"checksum rustc-ap-rustc_ast_passes 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b630662cc3812e757f6f0cc72f1c3b928ac231a50a0bd34ed7f460b5781f090b" -"checksum rustc-ap-rustc_ast_pretty 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55ddb88f73c74d5e695ae5541aab044e69d608984acbbebd9a59f4a55dfee4f7" -"checksum rustc-ap-rustc_attr 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f0668c1974f76ebd7e1cf566b62959ee7ea374a46e4136632b27ed6d80ead2" -"checksum rustc-ap-rustc_data_structures 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5aa565bf5c940bfe1b9be9974e898cf90e01746186e17f6d103b40107804416" -"checksum rustc-ap-rustc_errors 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f78e3c17e3d2e8fc004ebcf57fe5b688554635211c3346f8c70fe664545fa777" -"checksum rustc-ap-rustc_expand 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4ec52e2e7af6aef362fc9defaa3f618a84689d0f6865f9f322976cd8dab3112" -"checksum rustc-ap-rustc_feature 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca4764c14f84aaede3eac0d2d546c3b5592705a1b8bf23ccf025de5bf98d0f" -"checksum rustc-ap-rustc_fs_util 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c19245e259a656c5bf8a51a94598db41c36563c9f7968c54ece91a8918bb71" -"checksum rustc-ap-rustc_graphviz 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd9fa221daaaf6828ee914b1fa4ef20839e8e8fcba9414205a0a3f06cec8a470" -"checksum rustc-ap-rustc_index 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "666e394504050d1242869fe1d4880ea6d856183927d999b739c8cd32c8f046f0" -"checksum rustc-ap-rustc_lexer 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e00c526f9f8430ea4cd2178d25b02bfc7debe6677350c57292f92f50e65d2fe" -"checksum rustc-ap-rustc_macros 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4395519245c4a45193c2f15df08e6523188db7eafd29d21646dff99335ce50" -"checksum rustc-ap-rustc_parse 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc28692867433a3201ce7f1505c2abfca689dcb7394ed1fc64e121485bf7ef3" -"checksum rustc-ap-rustc_serialize 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "026a99c3a6a3d477b69696102722806082913ea90f40f7bfc4b97c1ae0d60bbd" -"checksum rustc-ap-rustc_session 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55db1b56890f90b58f894b53e9fbe821b735a094f7e10f9e60dc1b9801c4f457" -"checksum rustc-ap-rustc_span 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e78345ae6f0905dded335db76cd082edfcf1b383f7e2c218f6f7d4f5583073c5" -"checksum rustc-ap-rustc_target 666.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98d935fb3584b36ace9e981d58a59efeda22d9439dce6ea9303f4fd24e45f954" +"checksum rustc-ap-rustc_arena 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79b7d24b41029c11d1d79368f1c1c6e7acbb7ff40554da4f091964c3340eb794" +"checksum rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a42e3e05d840698e07e2052fe5bfb575f61e1160f11f0734c7209dd90fcbd17" +"checksum rustc-ap-rustc_ast_passes 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ab9f322794f18a44f71f3e20c4566e4f735a3badcc9a4ccf9b7cbd4ab1b9fd4" +"checksum rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5799f73bcac25f15037edbf1f4d6edbe24c9403a900067aacc48f362392c4b5c" +"checksum rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c275a20c4ddd0bbec902aeb7ea2aebf3b2323441459322675ce633356507cde6" +"checksum rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab8a1aef54b9321d653658f9c4e6b590943b5b89fa625fd865503a600ffc400" +"checksum rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f25b0fba0b1d4fa4c8f136e4d4acb8c35f18b6b8881f1a3cd4fbde34e8ea74f5" +"checksum rustc-ap-rustc_expand 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39e017224cea39e1b640935744cc1357570c764d7f2fff61621a5a45e23ad718" +"checksum rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "207325803daade8f890b761332a205424c104767f09d7bdf19adca4dc3ac14a2" +"checksum rustc-ap-rustc_fs_util 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f484c1a004b450ccf59d64efe990b316a3a57f4f39c5067879ddacc0828e4fb3" +"checksum rustc-ap-rustc_graphviz 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "947e7b4fa40dbe9a022df622ad496c21a5fac3b52d28ea136391c223e7bd2402" +"checksum rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3e3ed199bbaa7af3caf36f1531bade1bbd6731c0a33131f031cd0502620e776" +"checksum rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76cb944b7f9b2a38be799e47c901d422af0e1eb4a7bd63de06d1e6adc8288bd4" +"checksum rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8768562a84e6f4e1ae0eb150a10121aff84d132c54f62b8a7d286912d73f558f" +"checksum rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f0af9238c85a6e6c5cd3115b2d7b8767e5545ac537e5287e922d6275989ef27" +"checksum rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b783d2f4de0f3949107790a639d8857870887806b64e6a7e377c0c0679102a2" +"checksum rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb8ec18beea3488bc8f9812836e6a14f10987ea22d86c1d0f48ad03a1b70bc13" +"checksum rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9df93c4eec4329d96aea413056a98e2d6a907957249fd8c32ab259bea775c905" +"checksum rustc-ap-rustc_target 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fca772a06ad1d1489c061ea62b6f954e6dcc62b4e97717968eea711a28f8807c" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" diff --git a/Cargo.toml b/Cargo.toml index f33eb7244d5..982c4ea5856 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "666.0.0" +version = "668.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "666.0.0" +version = "668.0.0" diff --git a/src/types.rs b/src/types.rs index 96e331779c4..4e2b87ebfc8 100644 --- a/src/types.rs +++ b/src/types.rs @@ -560,7 +560,7 @@ impl Rewrite for ast::GenericParam { _ => (), } - if let rustc_ast::ast::GenericParamKind::Const { ref ty } = &self.kind { + if let rustc_ast::ast::GenericParamKind::Const { ref ty, .. } = &self.kind { result.push_str("const "); result.push_str(rewrite_ident(context, self.ident)); result.push_str(": "); -- cgit 1.4.1-3-g733a5 From 391cd3e3243c31d126597b2a3fb97897ae2cf607 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 14 Jul 2020 21:36:24 -0500 Subject: deps: bump rustc-ap to v669 --- Cargo.lock | 250 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 20 ++--- src/formatting.rs | 2 +- 3 files changed, 136 insertions(+), 136 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 5c28ad4412d..94dc996ec84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -739,79 +739,79 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_attr" -version = "668.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "669.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -826,9 +826,9 @@ dependencies = [ "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_graphviz 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_graphviz 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -840,15 +840,15 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "annotate-snippets 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -857,57 +857,57 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_passes 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_passes 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_feature" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_graphviz" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-rustc_index" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -915,7 +915,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_macros" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -926,25 +926,25 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_lexer 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -953,36 +953,36 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_feature 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_fs_util 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_span" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_arena 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_arena 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -990,16 +990,16 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "668.0.0" +version = "669.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_index 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_macros 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1058,7 +1058,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.18" +version = "1.4.19" dependencies = [ "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1074,15 +1074,15 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_expand 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast_pretty 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_attr 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_expand 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_parse 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_session 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustfmt-config_proc_macro 0.2.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1517,25 +1517,25 @@ dependencies = [ "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-rustc_arena 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79b7d24b41029c11d1d79368f1c1c6e7acbb7ff40554da4f091964c3340eb794" -"checksum rustc-ap-rustc_ast 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a42e3e05d840698e07e2052fe5bfb575f61e1160f11f0734c7209dd90fcbd17" -"checksum rustc-ap-rustc_ast_passes 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ab9f322794f18a44f71f3e20c4566e4f735a3badcc9a4ccf9b7cbd4ab1b9fd4" -"checksum rustc-ap-rustc_ast_pretty 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5799f73bcac25f15037edbf1f4d6edbe24c9403a900067aacc48f362392c4b5c" -"checksum rustc-ap-rustc_attr 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c275a20c4ddd0bbec902aeb7ea2aebf3b2323441459322675ce633356507cde6" -"checksum rustc-ap-rustc_data_structures 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab8a1aef54b9321d653658f9c4e6b590943b5b89fa625fd865503a600ffc400" -"checksum rustc-ap-rustc_errors 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f25b0fba0b1d4fa4c8f136e4d4acb8c35f18b6b8881f1a3cd4fbde34e8ea74f5" -"checksum rustc-ap-rustc_expand 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39e017224cea39e1b640935744cc1357570c764d7f2fff61621a5a45e23ad718" -"checksum rustc-ap-rustc_feature 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "207325803daade8f890b761332a205424c104767f09d7bdf19adca4dc3ac14a2" -"checksum rustc-ap-rustc_fs_util 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f484c1a004b450ccf59d64efe990b316a3a57f4f39c5067879ddacc0828e4fb3" -"checksum rustc-ap-rustc_graphviz 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "947e7b4fa40dbe9a022df622ad496c21a5fac3b52d28ea136391c223e7bd2402" -"checksum rustc-ap-rustc_index 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3e3ed199bbaa7af3caf36f1531bade1bbd6731c0a33131f031cd0502620e776" -"checksum rustc-ap-rustc_lexer 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76cb944b7f9b2a38be799e47c901d422af0e1eb4a7bd63de06d1e6adc8288bd4" -"checksum rustc-ap-rustc_macros 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8768562a84e6f4e1ae0eb150a10121aff84d132c54f62b8a7d286912d73f558f" -"checksum rustc-ap-rustc_parse 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f0af9238c85a6e6c5cd3115b2d7b8767e5545ac537e5287e922d6275989ef27" -"checksum rustc-ap-rustc_serialize 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b783d2f4de0f3949107790a639d8857870887806b64e6a7e377c0c0679102a2" -"checksum rustc-ap-rustc_session 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb8ec18beea3488bc8f9812836e6a14f10987ea22d86c1d0f48ad03a1b70bc13" -"checksum rustc-ap-rustc_span 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9df93c4eec4329d96aea413056a98e2d6a907957249fd8c32ab259bea775c905" -"checksum rustc-ap-rustc_target 668.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fca772a06ad1d1489c061ea62b6f954e6dcc62b4e97717968eea711a28f8807c" +"checksum rustc-ap-rustc_arena 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9cdd301e9dcb15ead384fc07196c850fd22829fae81d296b2ed6b4b10bf3278" +"checksum rustc-ap-rustc_ast 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7c0d0537ca69dfe4a49212035295dfb37a235b5df01aa877d50b247f4775b8" +"checksum rustc-ap-rustc_ast_passes 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4cf4dca95f55f70eeb193fb08554026d79d0628de771fd726bb609e36887b82" +"checksum rustc-ap-rustc_ast_pretty 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "202bd2886d0cfa48baa3711042c14843f1b4852555b7ee7e5376bf66b276cb8d" +"checksum rustc-ap-rustc_attr 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b11ee1d92b3214e8a8c7829eff84cc1b03925da0ea5c6900cefe05b99edb4682" +"checksum rustc-ap-rustc_data_structures 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a45d43b974d4cb9e32e5a15119c5eb7672c306ef09b064f2125b6a0399f6656" +"checksum rustc-ap-rustc_errors 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8cd895d440820aaa04e6dc5486105494920a1e9779b9b051e8dba4ca5c182f94" +"checksum rustc-ap-rustc_expand 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71a0cc7820860d6691bf0aa7a95cdbc60f6587b495c18e0fa15a888fdabbf171" +"checksum rustc-ap-rustc_feature 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5473d5106401aa46f881eb91772f0a41fd5f28ae6134cf4b450eb1370ea6af22" +"checksum rustc-ap-rustc_fs_util 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8da1d57ee7a7ef55f31a97d99c7f919f02fc9a60ab96faa8cf45a7ae3ab1ccbf" +"checksum rustc-ap-rustc_graphviz 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3af62b20460908378cd1d354917acd9553376c5363bbb4e465f949bd82bdef9" +"checksum rustc-ap-rustc_index 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3af7d4c456fe7647453d3fcd58335c9d512d1ff9a239a370b7ebdd353d69f66f" +"checksum rustc-ap-rustc_lexer 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "456af5f09c006cf6c22c1a433ee0232c4bb74bdc6c647a010166a47c94ed2a63" +"checksum rustc-ap-rustc_macros 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64f6acd192f313047759a346b892998b626466b93fe04f415da5f38906bb3b4c" +"checksum rustc-ap-rustc_parse 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c006e8117c1c55e42bb56386c86ce6f7e4b47349e0bec7888c1d24784272e61b" +"checksum rustc-ap-rustc_serialize 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "306ced69beaeebe4de9552ee751eb54ea25b5f34a73fe80f5f9cbbe15ccebc48" +"checksum rustc-ap-rustc_session 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dbff48435f5a476365e3ab5f49e07f98715cecb2d8c5bbcafeaf3aec638407be" +"checksum rustc-ap-rustc_span 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec4273af0abbe78fc4585316ab193445c848c555e9203ddc28af02330918bf30" +"checksum rustc-ap-rustc_target 669.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f9a2d6004ce6ad492a8eeacc2569b1c008169434b8828996d8dade4e5c6b6ee" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" "checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" diff --git a/Cargo.toml b/Cargo.toml index 982c4ea5856..f55b91df032 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.4.18" +version = "1.4.19" authors = ["Nicholas Cameron ", "The Rustfmt developers"] description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "668.0.0" +version = "669.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "668.0.0" +version = "669.0.0" diff --git a/src/formatting.rs b/src/formatting.rs index 28d111ba623..19affc3e3e1 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -29,7 +29,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::VersionMismatch); } - rustc_ast::with_globals(self.config.edition().to_libsyntax_pos_edition(), || { + rustc_ast::with_session_globals(self.config.edition().to_libsyntax_pos_edition(), || { if self.config.disable_all_formatting() { // When the input is from stdin, echo back the input. if let Input::Text(ref buf) = input { -- cgit 1.4.1-3-g733a5 From bf359c6ebc1be862ab2f91c5b5e5770963a3b786 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 15 Jul 2020 09:19:21 -0500 Subject: chore: backport 8157a3f0afe978d3e953420577f8344db7e905bf --- src/config/mod.rs | 3 +++ tests/config/issue-3779.toml | 1 - tests/source/issue-3779/lib.rs | 1 + tests/target/issue-3779/lib.rs | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index cf00eed0565..07c5612e26e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -481,6 +481,9 @@ mod test { #[test] fn test_valid_license_template_path() { + if !crate::is_nightly_channel!() { + return; + } let toml = r#"license_template_path = "tests/license-template/lt.txt""#; let config = Config::from_toml(toml, Path::new("")).unwrap(); assert!(config.license_template.is_some()); diff --git a/tests/config/issue-3779.toml b/tests/config/issue-3779.toml index 83505f409af..6ca52aee322 100644 --- a/tests/config/issue-3779.toml +++ b/tests/config/issue-3779.toml @@ -1,4 +1,3 @@ -unstable_features = true ignore = [ "tests/**/issue-3779/ice.rs" ] diff --git a/tests/source/issue-3779/lib.rs b/tests/source/issue-3779/lib.rs index d7c2ae28975..16e9d48337b 100644 --- a/tests/source/issue-3779/lib.rs +++ b/tests/source/issue-3779/lib.rs @@ -1,3 +1,4 @@ +// rustfmt-unstable: true // rustfmt-config: issue-3779.toml #[path = "ice.rs"] diff --git a/tests/target/issue-3779/lib.rs b/tests/target/issue-3779/lib.rs index ebebce417d1..a5673a4db7e 100644 --- a/tests/target/issue-3779/lib.rs +++ b/tests/target/issue-3779/lib.rs @@ -1,3 +1,4 @@ +// rustfmt-unstable: true // rustfmt-config: issue-3779.toml #[path = "ice.rs"] -- cgit 1.4.1-3-g733a5 From a17803127fdccecdf4a4c98a9e156c77479efcfa Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 9 Aug 2020 13:59:52 -0500 Subject: fix: inverted span on attrs within closure --- src/closures.rs | 11 +++++++++-- src/expr.rs | 12 +++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 82c49d806b5..00bd03026e6 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -155,8 +155,15 @@ fn rewrite_closure_with_block( rules: ast::BlockCheckMode::Default, span: body.span, }; - let block = - crate::expr::rewrite_block_with_visitor(context, "", &block, None, None, shape, false)?; + let block = crate::expr::rewrite_block_with_visitor( + context, + "", + &block, + Some(&body.attrs), + None, + shape, + false, + )?; Some(format!("{} {}", prefix, block)) } diff --git a/src/expr.rs b/src/expr.rs index ef7278a3a87..2b28e1ac92c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -525,7 +525,17 @@ pub(crate) fn rewrite_block_with_visitor( let open_pos = snippet.find_uncommented("{")?; visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) } - (ast::BlockCheckMode::Default, None) => visitor.last_pos = block.span.lo(), + (ast::BlockCheckMode::Default, None) => { + visitor.last_pos = block.span.lo(); + if let Some(attrs) = attrs { + if let Some(first) = attrs.first() { + let first_lo_span = first.span.lo(); + if first_lo_span < visitor.last_pos { + visitor.last_pos = first_lo_span; + } + } + } + } } let inner_attrs = attrs.map(inner_attributes); -- cgit 1.4.1-3-g733a5 From e4617e0e612206fda148bb7f1ba2388bdf3f68f3 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 2 Sep 2020 10:14:23 -0500 Subject: deps: bump rustc-ap to v672 --- Cargo.lock | 1206 +++++++++++++++++++++++++----------------------- Cargo.toml | 18 +- src/attr.rs | 2 +- src/modules/visitor.rs | 2 +- src/utils.rs | 2 +- 5 files changed, 630 insertions(+), 600 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 325a19210d9..852daba0d58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,1591 +4,1621 @@ name = "aho-corasick" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "annotate-snippets" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", ] [[package]] name = "annotate-snippets" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "anyhow" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" [[package]] name = "arrayref" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" [[package]] name = "arrayvec" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop", ] [[package]] name = "arrayvec" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi", ] [[package]] name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "backtrace" version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" dependencies = [ - "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", ] [[package]] name = "backtrace-sys" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayref", + "arrayvec 0.4.12", + "constant_time_eq", ] [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding", + "byte-tools", + "byteorder", + "generic-array", ] [[package]] name = "block-padding" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools", ] [[package]] name = "bstr" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" dependencies = [ - "packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "packed_simd", ] [[package]] name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" [[package]] name = "cargo_metadata" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", + "serde", + "serde_derive", + "serde_json", ] [[package]] name = "cc" version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", ] [[package]] name = "constant_time_eq" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" [[package]] name = "crossbeam-channel" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0", ] [[package]] name = "crossbeam-deque" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch", + "crossbeam-utils 0.6.5", ] [[package]] name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.12", + "cfg-if", + "crossbeam-utils 0.6.5", + "lazy_static", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-queue" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5", ] [[package]] name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "lazy_static", ] [[package]] name = "crossbeam-utils" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "cfg-if", + "lazy_static", ] [[package]] name = "derive-new" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array", ] [[package]] name = "dirs" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "dirs-sys", ] [[package]] name = "dirs-sys" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_users", + "winapi", ] [[package]] name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "ena" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log", ] [[package]] name = "env_logger" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "humantime", + "log", + "regex", + "termcolor", ] [[package]] name = "failure" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" dependencies = [ - "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "getopts" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "getrandom" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] name = "globset" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", ] [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ - "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "humantime" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error", ] [[package]] name = "ignore" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e" dependencies = [ - "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local 1.0.1", + "walkdir", + "winapi-util", ] [[package]] name = "indexmap" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", ] [[package]] name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" dependencies = [ - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" [[package]] name = "jobserver" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "log", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" [[package]] name = "lock_api" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard", ] [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "md-5" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer", + "digest", + "opaque-debug", ] [[package]] name = "measureme" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "memmap", + "parking_lot 0.9.0", + "rustc-hash", ] [[package]] name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" [[package]] name = "memmap" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi", ] [[package]] name = "memoffset" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "once_cell" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" dependencies = [ - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.10.2", ] [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api", + "parking_lot_core 0.6.2", + "rustc_version", ] [[package]] name = "parking_lot" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" dependencies = [ - "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api", + "parking_lot_core 0.7.2", ] [[package]] name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version", + "smallvec 0.6.10", + "winapi", ] [[package]] name = "parking_lot_core" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "smallvec 1.2.0", + "winapi", ] [[package]] name = "proc-macro-error" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" dependencies = [ - "proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", ] [[package]] name = "proc-macro-error-attr" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "syn-mid", + "version_check", ] [[package]] name = "proc-macro2" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "psm" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", ] [[package]] name = "quick-error" version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" [[package]] name = "quote" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "redox_users" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" dependencies = [ - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "rand_os", + "redox_syscall", + "rust-argon2", ] [[package]] name = "regex" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local 0.3.6", ] [[package]] name = "regex-syntax" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" [[package]] name = "rust-argon2" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "base64", + "blake2b_simd", + "crossbeam-utils 0.6.5", ] [[package]] name = "rustc-ap-rustc_arena" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d014a30376e84a36f01c68a1386044571b14e75de14877d272142795da4024c5" dependencies = [ - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures", + "smallvec 1.2.0", ] [[package]] name = "rustc-ap-rustc_ast" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e74889abc8ffe55885933943c90b04af8801955d47c118a3529ed16b3943578" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "scoped-tls", + "smallvec 1.2.0", + "tracing", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e56708a0e774acd0ba1c56c4eabf48139b4cfbdbbc486d507cb8cea38a0f72" dependencies = [ - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_attr", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_parse", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", + "tracing", ] [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a57a874e6dba1f7d4c87de70bdcad1b15ea74d4e231007e1fe18997217c58bcc" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_span", + "rustc-ap-rustc_target", + "tracing", ] [[package]] name = "rustc-ap-rustc_attr" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc89801730ad78380175d41e6bedd9223209db993c2d03210e99972e307eb674" dependencies = [ - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", + "version_check", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "671.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_graphviz 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stacker 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +version = "672.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f18fb0a1385d84ab6f49d1769ca166451117ec80876efc11c2dbec42bd84bf" +dependencies = [ + "bitflags", + "cfg-if", + "crossbeam-utils 0.7.0", + "ena", + "indexmap", + "jobserver", + "lazy_static", + "libc", + "measureme", + "once_cell", + "parking_lot 0.10.2", + "rustc-ap-rustc_graphviz", + "rustc-ap-rustc_index", + "rustc-ap-rustc_serialize", + "rustc-hash", + "rustc-rayon", + "rustc-rayon-core", + "smallvec 1.2.0", + "stable_deref_trait", + "stacker", + "tracing", + "winapi", ] [[package]] name = "rustc-ap-rustc_errors" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fedc37e3bb6d85cc874e5d634aa64e07f7bb66e9eeb13bb9dadf9dabc4d617" dependencies = [ - "annotate-snippets 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets 0.8.0", + "atty", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "termcolor", + "termize", + "tracing", + "unicode-width", + "winapi", ] [[package]] name = "rustc-ap-rustc_expand" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9e6185b77b83c9d0684546d7d60f4ba56eea25dca4e9c0dec8e42d8ee38424" dependencies = [ - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_passes 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_passes", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_attr", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_parse", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", + "smallvec 1.2.0", + "tracing", ] [[package]] name = "rustc-ap-rustc_feature" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea8df315724e0a8a1e2075bb5a50d2abd807e4506db3bbfdf77c2c5ad5e222a" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_span", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19673036a2c932af16a339c233957fcc2d06525f1f9bfb23c99198f715680e50" [[package]] name = "rustc-ap-rustc_graphviz" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ec959426514b5a868b407a25b4f0ad14b51f512b3ea05dc76877c47830ef36" [[package]] name = "rustc-ap-rustc_index" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cec39860362c156c0b76a14169f9d801329fad4742297204969a6493ec53ef8" dependencies = [ - "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1", + "rustc-ap-rustc_serialize", ] [[package]] name = "rustc-ap-rustc_lexer" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9829d5d33bafe9a3020c08b913f847c353456f734f5ac3bd58ae0eeead381a96" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8f887d758a4aea3db0352a1bc97ae316dcea8604d64b29f6225a0dd7502649" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "rustc-ap-rustc_parse" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ab2411011df24ba92f6b85c002c20e1dc12ab5af61880f2a48ce89f3cef42d" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_lexer 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", + "smallvec 1.2.0", + "tracing", + "unicode-normalization", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be9e2ff3e3e424c3a9faecfd94ffb68c0a4f569d9f1c599e624388c9d1935c9" dependencies = [ - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap", + "smallvec 1.2.0", ] [[package]] name = "rustc-ap-rustc_session" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbe999cfa5a54e251fa009723b691b4b0c6e5a3e741281c7ca6d336802e2a457" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_feature 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_fs_util 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "getopts", + "num_cpus", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_fs_util", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "rustc-ap-rustc_target", + "tracing", ] [[package]] name = "rustc-ap-rustc_span" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b3ab33f4bd27ca8df5fbea78713e2ac26a26df46a7beefa680c16cc7218e11" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_arena 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "md-5", + "rustc-ap-rustc_arena", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "scoped-tls", + "sha-1", + "tracing", + "unicode-width", ] [[package]] name = "rustc-ap-rustc_target" -version = "671.0.0" +version = "672.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c803ab67b63e5344f893d1d7c4bce2af26f9da245dc5b416a404da819454ff99" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_index 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_macros 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "tracing", ] [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-rayon" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "either", + "rustc-rayon-core", ] [[package]] name = "rustc-rayon-core" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils 0.6.5", + "lazy_static", + "num_cpus", ] [[package]] name = "rustc-workspace-hack" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] name = "rustfmt-config_proc_macro" version = "0.2.0" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "rustfmt-nightly" version = "1.4.20" dependencies = [ - "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_ast_pretty 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_attr 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_expand 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_parse 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_session 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-config_proc_macro 0.2.0", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets 0.6.1", + "anyhow", + "bytecount", + "cargo_metadata", + "derive-new", + "diff", + "dirs", + "env_logger", + "getopts", + "ignore", + "itertools", + "lazy_static", + "log", + "regex", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_attr", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_expand", + "rustc-ap-rustc_parse", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", + "rustc-workspace-hack", + "rustfmt-config_proc_macro", + "serde", + "serde_json", + "structopt", + "term", + "thiserror", + "toml", + "unicode-segmentation", + "unicode-width", + "unicode_categories", ] [[package]] name = "ryu" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" [[package]] name = "same-file" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" dependencies = [ - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", + "serde", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "sha-1" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", ] [[package]] name = "smallvec" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" [[package]] name = "smallvec" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" [[package]] name = "stacker" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd941b456e1c006d6b9f27c526d5b69281288aeea8cba82c19d3843d8ccdd2" dependencies = [ - "cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "psm 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "cfg-if", + "libc", + "psm", + "winapi", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "lazy_static", + "structopt-derive", ] [[package]] name = "structopt-derive" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "syn" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] name = "syn-mid" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "synstructure" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] name = "term" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" dependencies = [ - "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs", + "winapi", ] [[package]] name = "termcolor" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" dependencies = [ - "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor", ] [[package]] name = "termize" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thiserror" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b305ec0e323c7b6cfff6098a22516e0063d0bb7c3d88660a890217dca099a" dependencies = [ - "thiserror-impl 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ba8d810d9c48fc456b7ad54574e8bfb7c7918a57ad7a6e6a0985d7959e8597" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "toml" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" +dependencies = [ + "cfg-if", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f0e00789804e99b20f12bc7003ca416309d28a6f495d6af58d1e2c2842461b5" +dependencies = [ + "lazy_static", ] [[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-normalization" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0", ] [[package]] name = "unicode-segmentation" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" [[package]] name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "unicode_categories" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "version_check" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" [[package]] name = "walkdir" version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" dependencies = [ - "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file", + "winapi", + "winapi-util", ] [[package]] name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" [[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "wincolor" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -"checksum annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" -"checksum annotate-snippets 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" -"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" -"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum bytecount 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" -"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -"checksum derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" -"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" -"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum ena 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" -"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" -"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -"checksum failure_derive 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e" -"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jobserver 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" -"checksum measureme 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" -"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum parking_lot_core 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" -"checksum proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" -"checksum proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -"checksum psm 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" -"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" -"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" -"checksum rustc-ap-rustc_arena 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3941333c39ffa778611a34692244052fc9ba0f6b02dcf019c8d24925707dd6" -"checksum rustc-ap-rustc_ast 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27c579f7d89e6fc971b433e92bb2b8c65b716d7c797b21de8685945be9455610" -"checksum rustc-ap-rustc_ast_passes 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9914fadee461568d19ca2ebaec8699ff898f8ffec9928154659a57ee018e5fd" -"checksum rustc-ap-rustc_ast_pretty 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a78c5cc50a2f294d3c4e9131a15676724c9f136d3ed54e9ba419850b6025cb3" -"checksum rustc-ap-rustc_attr 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78ce08227d146949755175c0cf710280a4b5bf6ee504c0e3f7ccc30d66fbfd9" -"checksum rustc-ap-rustc_data_structures 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d5ac3735c38d2d0e95991ebcd7eb1618b60e784194a738e0ce2e8d39c39b809" -"checksum rustc-ap-rustc_errors 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5166a95afa6e3b78ccbece4c2f1e163634854297f1147c6fd90e2712ed3fede5" -"checksum rustc-ap-rustc_expand 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0586e83bdfe70eda8393429a8a38ecb529525dd252d787e479af075d3cab08" -"checksum rustc-ap-rustc_feature 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48fc3aa8de0737a8c5a4353e6948548f469150d2b5d3eac391843de32c6c6ca2" -"checksum rustc-ap-rustc_fs_util 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "59fd3380f4029020b693bbfd5a14ec8c893ec33c5c0063ad2e68e46d3fbd6a1f" -"checksum rustc-ap-rustc_graphviz 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b54bd98f70e04291bf611151d1fcd4d7770b35f7ec603d301c4aee0d1979cca4" -"checksum rustc-ap-rustc_index 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "335bfb187a2489a59ee8c67fcf5d1760e9dcdbe0f02025c199a74caa05096b15" -"checksum rustc-ap-rustc_lexer 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22e1221f3bfa2943c942cf8da319ab2346887f8757778c29c7f1822cd27b521f" -"checksum rustc-ap-rustc_macros 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b774df26c4ef513555b3a303cb209f44cf68a9e6a5481b41ac832301c6487cb" -"checksum rustc-ap-rustc_parse 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "065e632101bdd57a271f38ee7a4d72b5a3d0467ec845104346c284b2c6c69960" -"checksum rustc-ap-rustc_serialize 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8c0b704e3dedb97cbb1ac566bbc0ab397ec4a4743098326a8f2230463fd9f9" -"checksum rustc-ap-rustc_session 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dda99ede4e6e260712754f8548b0a175b615686ad393653a3bd11f6c5e41a04e" -"checksum rustc-ap-rustc_span 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53453791c2c0b501a921927ce8e305a801eef130920873f8da92d83dad595236" -"checksum rustc-ap-rustc_target 671.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac82006fdb31ef44e24e1623f8b72ac2b404ef15ba20b7ebec0df35e5d20bbef" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -"checksum rustc-rayon 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" -"checksum rustc-rayon-core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" -"checksum rustc-workspace-hack 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" -"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" -"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum stacker 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "72dd941b456e1c006d6b9f27c526d5b69281288aeea8cba82c19d3843d8ccdd2" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" -"checksum structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" -"checksum term 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0863a3345e70f61d613eab32ee046ccd1bcc5f9105fe402c61fcd0c13eeb8b5" -"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" -"checksum termize 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thiserror 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cc6b305ec0e323c7b6cfff6098a22516e0063d0bb7c3d88660a890217dca099a" -"checksum thiserror-impl 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45ba8d810d9c48fc456b7ad54574e8bfb7c7918a57ad7a6e6a0985d7959e8597" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" -"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" -"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" + "winapi", + "winapi-util", +] diff --git a/Cargo.toml b/Cargo.toml index 6caf337e9ec..bdd9e6e427c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "671.0.0" +version = "672.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "671.0.0" +version = "672.0.0" diff --git a/src/attr.rs b/src/attr.rs index b9e160020fb..6272cb31e4c 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -327,7 +327,7 @@ impl Rewrite for ast::Attribute { if let Some(ref meta) = self.meta() { // This attribute is possibly a doc attribute needing normalization to a doc comment - if context.config.normalize_doc_attributes() && meta.check_name(sym::doc) { + if context.config.normalize_doc_attributes() && meta.has_name(sym::doc) { if let Some(ref literal) = meta.value_str() { let comment_style = match self.style { ast::AttrStyle::Inner => CommentStyle::Doc, diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 942e70d0e88..42d5351080d 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -85,7 +85,7 @@ impl PathVisitor { impl<'ast> MetaVisitor<'ast> for PathVisitor { fn visit_meta_name_value(&mut self, meta_item: &'ast ast::MetaItem, lit: &'ast ast::Lit) { - if meta_item.check_name(Symbol::intern("path")) && lit.kind.is_str() { + if meta_item.has_name(Symbol::intern("path")) && lit.kind.is_str() { self.paths.push(lit_to_str(lit)); } } diff --git a/src/utils.rs b/src/utils.rs index bb0c6b7fb22..618172595eb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -256,7 +256,7 @@ fn is_skip(meta_item: &MetaItem) -> bool { || path_str == &*depr_skip_annotation().as_str() } MetaItemKind::List(ref l) => { - meta_item.check_name(sym::cfg_attr) && l.len() == 2 && is_skip_nested(&l[1]) + meta_item.has_name(sym::cfg_attr) && l.len() == 2 && is_skip_nested(&l[1]) } _ => false, } -- cgit 1.4.1-3-g733a5 From 637ddfb6da44655af419441f641d8f6285efaae8 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 2 Sep 2020 12:36:50 -0500 Subject: deps: bump rustc-ap to v673 --- Cargo.lock | 172 ++++++++++++++++++++++++++++++++++++++------------- Cargo.toml | 18 +++--- src/attr.rs | 12 +++- src/formatting.rs | 2 +- src/modules.rs | 2 +- src/reorder.rs | 4 +- src/syntux/parser.rs | 13 +++- src/visitor.rs | 2 +- 8 files changed, 164 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 852daba0d58..d5308866f12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,6 +76,12 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "backtrace" version = "0.3.40" @@ -287,7 +293,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ - "autocfg", + "autocfg 0.1.7", "cfg-if", "lazy_static", ] @@ -450,6 +456,15 @@ dependencies = [ "regex", ] +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "autocfg 1.0.1", +] + [[package]] name = "heck" version = "0.3.1" @@ -488,11 +503,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.3.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" +checksum = "4e47a3566dd4fd4eec714ae6ceabdee0caec795be835c223d92c2d40f1e8cf1c" dependencies = [ - "autocfg", + "autocfg 1.0.1", + "hashbrown", ] [[package]] @@ -688,6 +704,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "ppv-lite86" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" + [[package]] name = "proc-macro-error" version = "0.4.11" @@ -747,6 +769,29 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -762,6 +807,24 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rand_os" version = "0.1.3" @@ -821,6 +884,15 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "rust-argon2" version = "0.5.1" @@ -834,9 +906,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d014a30376e84a36f01c68a1386044571b14e75de14877d272142795da4024c5" +checksum = "8d8cf08094be6d414e18b63c6a7b4e67af12ebc4cd53e8f494cd034ba291995a" dependencies = [ "rustc-ap-rustc_data_structures", "smallvec 1.2.0", @@ -844,9 +916,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e74889abc8ffe55885933943c90b04af8801955d47c118a3529ed16b3943578" +checksum = "67fca3205094b69deaa6b46a710ee4ef5334d0239182a3c8a4f66a4ad4846842" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -855,16 +927,15 @@ dependencies = [ "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "scoped-tls", "smallvec 1.2.0", "tracing", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e56708a0e774acd0ba1c56c4eabf48139b4cfbdbbc486d507cb8cea38a0f72" +checksum = "14822e385bfdb567bf56ba836a83429f366797c55d2fdeb6ecb1b0a03bb06a64" dependencies = [ "itertools", "rustc-ap-rustc_ast", @@ -881,9 +952,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57a874e6dba1f7d4c87de70bdcad1b15ea74d4e231007e1fe18997217c58bcc" +checksum = "c5ecf1928ecde47c0a7361c6a358c0c5601993b5d01e6e6340b0c3ba51952e40" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -893,9 +964,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc89801730ad78380175d41e6bedd9223209db993c2d03210e99972e307eb674" +checksum = "303737c455baaddea493dbac5fe9422bc3276d80fc3e5dc6ae73dccb8b860201" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -911,9 +982,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33f18fb0a1385d84ab6f49d1769ca166451117ec80876efc11c2dbec42bd84bf" +checksum = "1a574533429da41799344e3b9923e8a24ead05ceb19a2fa7087eaf2c444fd35a" dependencies = [ "bitflags", "cfg-if", @@ -935,15 +1006,16 @@ dependencies = [ "smallvec 1.2.0", "stable_deref_trait", "stacker", + "tempfile", "tracing", "winapi", ] [[package]] name = "rustc-ap-rustc_errors" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fedc37e3bb6d85cc874e5d634aa64e07f7bb66e9eeb13bb9dadf9dabc4d617" +checksum = "2bd8464f7a94c5d2b0c95781be833a71f0ba429c92afabe4e0356c096510d805" dependencies = [ "annotate-snippets 0.8.0", "atty", @@ -959,9 +1031,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9e6185b77b83c9d0684546d7d60f4ba56eea25dca4e9c0dec8e42d8ee38424" +checksum = "11fe258f0c5e5d8cd3908730305b4e8c210fd49b8e432a63324fa25eea1c55e7" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -981,9 +1053,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea8df315724e0a8a1e2075bb5a50d2abd807e4506db3bbfdf77c2c5ad5e222a" +checksum = "12b69d30fedc30b09d860e7f713262b2a7cc90ab3f404e6d91e58856bf9895fb" dependencies = [ "lazy_static", "rustc-ap-rustc_data_structures", @@ -992,21 +1064,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19673036a2c932af16a339c233957fcc2d06525f1f9bfb23c99198f715680e50" +checksum = "0cc22a99d2cff4ec83f83a15821c4f0bdf967664fbd9747a7add65b541ed9302" [[package]] name = "rustc-ap-rustc_graphviz" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ec959426514b5a868b407a25b4f0ad14b51f512b3ea05dc76877c47830ef36" +checksum = "9bf58ebc2d96377e4f201cce875d3f160f548fad8d82efb831918577363d7c7d" [[package]] name = "rustc-ap-rustc_index" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cec39860362c156c0b76a14169f9d801329fad4742297204969a6493ec53ef8" +checksum = "4e9fd6db5f0467dd9d5ed4223fc95f20c633779a4b60e5228f4c1698a4ba42bb" dependencies = [ "arrayvec 0.5.1", "rustc-ap-rustc_serialize", @@ -1014,18 +1086,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9829d5d33bafe9a3020c08b913f847c353456f734f5ac3bd58ae0eeead381a96" +checksum = "f6b71fa1285bdefe5fb61e59b63d6cc246abf337f4acafdd620d721bc488e671" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8f887d758a4aea3db0352a1bc97ae316dcea8604d64b29f6225a0dd7502649" +checksum = "634c5155defd0288c1171c47ae0cadf8060669084e2bb5ce6eb22a878a7c5db5" dependencies = [ "proc-macro2", "quote", @@ -1035,9 +1107,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ab2411011df24ba92f6b85c002c20e1dc12ab5af61880f2a48ce89f3cef42d" +checksum = "bd507233a7e70fc2733b61a540940cb5519920021ae0df0a668418596ad78ba7" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -1055,9 +1127,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_serialize" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be9e2ff3e3e424c3a9faecfd94ffb68c0a4f569d9f1c599e624388c9d1935c9" +checksum = "dfb9d060a496e632afd6799c54db9f2798b24b34fa5e1927ab378e6dda1defd8" dependencies = [ "indexmap", "smallvec 1.2.0", @@ -1065,9 +1137,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbe999cfa5a54e251fa009723b691b4b0c6e5a3e741281c7ca6d336802e2a457" +checksum = "b4b8682f3989efc2b9217d334720f6777a1f1748f35a619839f98b93b51fa76d" dependencies = [ "bitflags", "getopts", @@ -1085,9 +1157,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b3ab33f4bd27ca8df5fbea78713e2ac26a26df46a7beefa680c16cc7218e11" +checksum = "3620042dbe0a2f8aaa463812fe6264253bfeaffab1ccacc809a732d36b4799b9" dependencies = [ "cfg-if", "md-5", @@ -1104,9 +1176,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "672.0.0" +version = "673.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c803ab67b63e5344f893d1d7c4bce2af26f9da245dc5b416a404da819454ff99" +checksum = "ab855d271ed80ef090fac4a8bcbc910b0f300d56a44f5ed6239675b33991cf6b" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -1398,6 +1470,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +dependencies = [ + "cfg-if", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "term" version = "0.6.1" diff --git a/Cargo.toml b/Cargo.toml index bdd9e6e427c..55dc5d15fae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "672.0.0" +version = "673.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "672.0.0" +version = "673.0.0" diff --git a/src/attr.rs b/src/attr.rs index 6272cb31e4c..3c3695bb564 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -2,7 +2,7 @@ use rustc_ast::ast; use rustc_ast::attr::HasAttrs; -use rustc_span::{symbol::sym, BytePos, Span, DUMMY_SP}; +use rustc_span::{symbol::sym, BytePos, Span, Symbol, DUMMY_SP}; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; @@ -18,6 +18,14 @@ use crate::utils::{count_newlines, mk_sp}; mod doc_comment; +pub(crate) fn contains_name(attrs: &[ast::Attribute], name: Symbol) -> bool { + attrs.iter().any(|attr| attr.has_name(name)) +} + +pub(crate) fn first_attr_value_str_by_name(attrs: &[ast::Attribute], name: Symbol) -> Option { + attrs.iter().find(|attr| attr.has_name(name)).and_then(|attr| attr.value_str()) +} + /// Returns attributes on the given statement. pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { stmt.attrs() @@ -49,7 +57,7 @@ pub(crate) fn filter_inline_attrs( } fn is_derive(attr: &ast::Attribute) -> bool { - attr.check_name(sym::derive) + attr.has_name(sym::derive) } /// Returns the arguments of `#[derive(...)]`. diff --git a/src/formatting.rs b/src/formatting.rs index 19affc3e3e1..1a0554b94ad 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -29,7 +29,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::VersionMismatch); } - rustc_ast::with_session_globals(self.config.edition().to_libsyntax_pos_edition(), || { + rustc_span::with_session_globals(self.config.edition().to_libsyntax_pos_edition(), || { if self.config.disable_all_formatting() { // When the input is from stdin, echo back the input. if let Input::Text(ref buf) = input { diff --git a/src/modules.rs b/src/modules.rs index cbe663cb412..29f7cb0ef91 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -426,7 +426,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } fn path_value(attr: &ast::Attribute) -> Option { - if attr.check_name(sym::path) { + if attr.has_name(sym::path) { attr.value_str() } else { None diff --git a/src/reorder.rs b/src/reorder.rs index 3b9f2475acc..2e73861a5a2 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -8,7 +8,7 @@ use std::cmp::{Ord, Ordering}; -use rustc_ast::{ast, attr}; +use rustc_ast::ast; use rustc_span::{symbol::sym, Span}; use crate::config::Config; @@ -147,7 +147,7 @@ fn rewrite_reorderable_items( } fn contains_macro_use_attr(item: &ast::Item) -> bool { - attr::contains_name(&item.attrs, sym::macro_use) + crate::attr::contains_name(&item.attrs, sym::macro_use) } /// A simplified version of `ast::ItemKind`. diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index decad02d049..675aa9b73fb 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -5,8 +5,9 @@ use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; use rustc_errors::Diagnostic; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; -use rustc_span::{symbol::kw, Span}; +use rustc_span::{symbol::kw, sym, Span}; +use crate::attr::first_attr_value_str_by_name; use crate::syntux::session::ParseSess; use crate::{Config, Input}; @@ -99,7 +100,15 @@ pub(crate) enum ParserError { impl<'a> Parser<'a> { pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { - rustc_expand::module::submod_path_from_attr(attrs, path) + let path_string = first_attr_value_str_by_name(attrs, sym::path)?.as_str(); + // On windows, the base path might have the form + // `\\?\foo\bar` in which case it does not tolerate + // mixed `/` and `\` separators, so canonicalize + // `/` to `\`. + #[cfg(windows)] + let path_string = path_string.replace("/", "\\"); + + Some(path.join(&*path_string)) } pub(crate) fn parse_file_as_module( diff --git a/src/visitor.rs b/src/visitor.rs index 39421491697..40783e1f95e 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -810,7 +810,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Returns true if we should skip the following item. pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { - if attr.check_name(depr_skip_annotation()) { + if attr.has_name(depr_skip_annotation()) { let file_name = self.parse_sess.span_to_filename(attr.span); self.report.append( file_name, -- cgit 1.4.1-3-g733a5 From aa11c27490046e3ad860cecd3b11660c5ca642f9 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 2 Sep 2020 12:59:58 -0500 Subject: chore: run rustfmt --- src/attr.rs | 10 ++++++++-- src/syntux/parser.rs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 3c3695bb564..b3ce47cf319 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -22,8 +22,14 @@ pub(crate) fn contains_name(attrs: &[ast::Attribute], name: Symbol) -> bool { attrs.iter().any(|attr| attr.has_name(name)) } -pub(crate) fn first_attr_value_str_by_name(attrs: &[ast::Attribute], name: Symbol) -> Option { - attrs.iter().find(|attr| attr.has_name(name)).and_then(|attr| attr.value_str()) +pub(crate) fn first_attr_value_str_by_name( + attrs: &[ast::Attribute], + name: Symbol, +) -> Option { + attrs + .iter() + .find(|attr| attr.has_name(name)) + .and_then(|attr| attr.value_str()) } /// Returns attributes on the given statement. diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 675aa9b73fb..2730ff37788 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -5,7 +5,7 @@ use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; use rustc_errors::Diagnostic; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; -use rustc_span::{symbol::kw, sym, Span}; +use rustc_span::{sym, symbol::kw, Span}; use crate::attr::first_attr_value_str_by_name; use crate::syntux::session::ParseSess; -- cgit 1.4.1-3-g733a5 From 89b7f5f38260437db50ece8d48418f90bf1e42ec Mon Sep 17 00:00:00 2001 From: mahkoh Date: Fri, 22 May 2020 11:55:34 +0200 Subject: Fix module resolution in inner modules with paths (#4194) --- src/modules.rs | 17 +---------------- tests/target/inner-module-path/b.rs | 1 + tests/target/inner-module-path/c/d.rs | 1 + tests/target/inner-module-path/lib.rs | 10 ++++++++++ 4 files changed, 13 insertions(+), 16 deletions(-) create mode 100644 tests/target/inner-module-path/b.rs create mode 100644 tests/target/inner-module-path/c/d.rs create mode 100644 tests/target/inner-module-path/lib.rs (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index 29f7cb0ef91..23e68a7d425 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -56,8 +56,6 @@ enum SubModKind<'a, 'ast> { External(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>), /// `mod foo;` with multiple sources. MultiExternal(Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)>), - /// `#[path = "..."] mod foo {}` - InternalWithPath(PathBuf), /// `mod foo {}` Internal(&'a ast::Item), } @@ -173,12 +171,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.find_external_module(item.ident, &item.attrs, sub_mod) } else { // An internal module (`mod foo { /* ... */ }`); - if let Some(path) = find_path_value(&item.attrs) { - let path = Path::new(&*path.as_str()).to_path_buf(); - Ok(Some(SubModKind::InternalWithPath(path))) - } else { - Ok(Some(SubModKind::Internal(item))) - } + Ok(Some(SubModKind::Internal(item))) } } @@ -218,14 +211,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { }; self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) } - SubModKind::InternalWithPath(mod_path) => { - // All `#[path]` files are treated as though they are a `mod.rs` file. - let directory = Directory { - path: mod_path, - ownership: DirectoryOwnership::Owned { relative: None }, - }; - self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) - } SubModKind::Internal(ref item) => { self.push_inline_mod_directory(item.ident, &item.attrs); self.visit_sub_mod_after_directory_update(sub_mod, None) diff --git a/tests/target/inner-module-path/b.rs b/tests/target/inner-module-path/b.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/inner-module-path/b.rs @@ -0,0 +1 @@ + diff --git a/tests/target/inner-module-path/c/d.rs b/tests/target/inner-module-path/c/d.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/target/inner-module-path/c/d.rs @@ -0,0 +1 @@ + diff --git a/tests/target/inner-module-path/lib.rs b/tests/target/inner-module-path/lib.rs new file mode 100644 index 00000000000..fb75d70cd93 --- /dev/null +++ b/tests/target/inner-module-path/lib.rs @@ -0,0 +1,10 @@ +// rustfmt-recursive: true + +#[path = "."] +mod a { + mod b; +} + +mod c { + mod d; +} -- cgit 1.4.1-3-g733a5 From 62dc7c5c6b7810e427f5bfe9ebf92f81e6696acf Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 2 Sep 2020 18:42:00 -0500 Subject: fix: inner attribute formatting --- src/formatting.rs | 29 +++------ src/modules.rs | 113 ++++++++++++++++++++++++---------- src/visitor.rs | 13 ++-- tests/target/inner-module-path/lib.rs | 2 - 4 files changed, 98 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 1a0554b94ad..4da89e760ad 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -11,6 +11,7 @@ use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::issues::BadIssueSeeker; +use crate::modules::Module; use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; use crate::syntux::session::ParseSess; use crate::utils::count_newlines; @@ -102,8 +103,7 @@ fn format_project( continue; } should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); - let is_root = path == main_file; - context.format_file(path, &module, is_root)?; + context.format_file(path, &module)?; } timer = timer.done_formatting(); @@ -134,13 +134,8 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { } // Formats a single file/module. - fn format_file( - &mut self, - path: FileName, - module: &ast::Mod, - is_root: bool, - ) -> Result<(), ErrorKind> { - let snippet_provider = self.parse_session.snippet_provider(module.inner); + fn format_file(&mut self, path: FileName, module: &Module<'_>) -> Result<(), ErrorKind> { + let snippet_provider = self.parse_session.snippet_provider(module.as_ref().inner); let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, &self.config, @@ -149,19 +144,9 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { ); visitor.skip_context.update_with_attrs(&self.krate.attrs); - // Format inner attributes if available. - if !self.krate.attrs.is_empty() && is_root { - visitor.skip_empty_lines(snippet_provider.end_pos()); - if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { - visitor.push_rewrite(module.inner, None); - } else { - visitor.format_separate_mod(module, snippet_provider.end_pos()); - } - } else { - visitor.last_pos = snippet_provider.start_pos(); - visitor.skip_empty_lines(snippet_provider.end_pos()); - visitor.format_separate_mod(module, snippet_provider.end_pos()); - }; + visitor.last_pos = snippet_provider.start_pos(); + visitor.skip_empty_lines(snippet_provider.end_pos()); + visitor.format_separate_mod(module, snippet_provider.end_pos()); debug_assert_eq!( visitor.line_number, diff --git a/src/modules.rs b/src/modules.rs index 23e68a7d425..b4d2f1fc822 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -3,6 +3,7 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use rustc_ast::ast; +use rustc_ast::attr::HasAttrs; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; use thiserror::Error; @@ -18,12 +19,48 @@ use crate::utils::contains_skip; mod visitor; -type FileModMap<'ast> = BTreeMap>; +type FileModMap<'ast> = BTreeMap>; lazy_static! { static ref CFG_IF: Symbol = Symbol::intern("cfg_if"); } +/// Represents module with its inner attributes. +#[derive(Debug, Clone)] +pub(crate) struct Module<'a> { + ast_mod: Cow<'a, ast::Mod>, + inner_attr: Vec, +} + +impl<'a> Module<'a> { + pub(crate) fn new(ast_mod: Cow<'a, ast::Mod>, attrs: &[ast::Attribute]) -> Self { + let inner_attr = attrs + .iter() + .filter(|attr| attr.style == ast::AttrStyle::Inner) + .cloned() + .collect(); + Module { + ast_mod, + inner_attr, + } + } +} + +impl<'a> HasAttrs for Module<'a> { + fn attrs(&self) -> &[ast::Attribute] { + &self.inner_attr + } + fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { + f(&mut self.inner_attr) + } +} + +impl<'a> AsRef for Module<'a> { + fn as_ref(&self) -> &ast::Mod { + &self.ast_mod + } +} + /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { parse_sess: &'sess ParseSess, @@ -53,9 +90,9 @@ pub(crate) enum ModuleResolutionErrorKind { #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` - External(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>), + External(PathBuf, DirectoryOwnership, Module<'ast>), /// `mod foo;` with multiple sources. - MultiExternal(Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)>), + MultiExternal(Vec<(PathBuf, DirectoryOwnership, Module<'ast>)>), /// `mod foo {}` Internal(&'a ast::Item), } @@ -94,8 +131,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.visit_mod_from_ast(&krate.module)?; } - self.file_map - .insert(root_filename, Cow::Borrowed(&krate.module)); + self.file_map.insert( + root_filename, + Module::new(Cow::Borrowed(&krate.module), &krate.attrs), + ); Ok(self.file_map) } @@ -105,7 +144,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { - self.visit_sub_mod(&module_item.item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod( + &module_item.item, + Module::new(Cow::Owned(sub_mod.clone()), &module_item.item.attrs), + )?; } } Ok(()) @@ -120,7 +162,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod(&item, Module::new(Cow::Owned(sub_mod.clone()), &item.attrs))?; } } Ok(()) @@ -134,7 +176,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(item, Cow::Borrowed(sub_mod))?; + self.visit_sub_mod(item, Module::new(Cow::Borrowed(sub_mod), &item.attrs))?; } } Ok(()) @@ -143,12 +185,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn visit_sub_mod( &mut self, item: &'c ast::Item, - sub_mod: Cow<'ast, ast::Mod>, + sub_mod: Module<'ast>, ) -> Result<(), ModuleResolutionError> { let old_directory = self.directory.clone(); let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?; if let Some(sub_mod_kind) = sub_mod_kind { - self.insert_sub_mod(sub_mod_kind.clone(), sub_mod.clone())?; + self.insert_sub_mod(sub_mod_kind.clone())?; self.visit_sub_mod_inner(sub_mod, sub_mod_kind)?; } self.directory = old_directory; @@ -159,7 +201,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn peek_sub_mod( &self, item: &'c ast::Item, - sub_mod: &Cow<'ast, ast::Mod>, + sub_mod: &Module<'ast>, ) -> Result>, ModuleResolutionError> { if contains_skip(&item.attrs) { return Ok(None); @@ -178,7 +220,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn insert_sub_mod( &mut self, sub_mod_kind: SubModKind<'c, 'ast>, - _sub_mod: Cow<'ast, ast::Mod>, ) -> Result<(), ModuleResolutionError> { match sub_mod_kind { SubModKind::External(mod_path, _, sub_mod) => { @@ -200,7 +241,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn visit_sub_mod_inner( &mut self, - sub_mod: Cow<'ast, ast::Mod>, + sub_mod: Module<'ast>, sub_mod_kind: SubModKind<'c, 'ast>, ) -> Result<(), ModuleResolutionError> { match sub_mod_kind { @@ -230,13 +271,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn visit_sub_mod_after_directory_update( &mut self, - sub_mod: Cow<'ast, ast::Mod>, + sub_mod: Module<'ast>, directory: Option, ) -> Result<(), ModuleResolutionError> { if let Some(directory) = directory { self.directory = directory; } - match sub_mod { + match sub_mod.ast_mod { Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod), Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod), } @@ -247,7 +288,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { &self, mod_name: symbol::Ident, attrs: &[ast::Attribute], - sub_mod: &Cow<'ast, ast::Mod>, + sub_mod: &Module<'ast>, ) -> Result>, ModuleResolutionError> { let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, @@ -257,12 +298,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if self.parse_sess.is_file_parsed(&path) { return Ok(None); } - return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { + return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) + { Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok((m, _)) => Ok(Some(SubModKind::External( + Ok(m) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, - Cow::Owned(m), + Module::new(Cow::Owned(m.0), &m.1), ))), Err(ParserError::ParseError) => Err(ModuleResolutionError { module: mod_name.to_string(), @@ -300,13 +342,19 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.inner) { + match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) { Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok((m, _)) if outside_mods_empty => { - Ok(Some(SubModKind::External(path, ownership, Cow::Owned(m)))) - } - Ok((m, _)) => { - mods_outside_ast.push((path.clone(), ownership, Cow::Owned(m))); + Ok(m) if outside_mods_empty => Ok(Some(SubModKind::External( + path, + ownership, + Module::new(Cow::Owned(m.0), &m.1), + ))), + Ok(m) => { + mods_outside_ast.push(( + path.clone(), + ownership, + Module::new(Cow::Owned(m.0), &m.1), + )); if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); } @@ -368,8 +416,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn find_mods_outside_of_ast( &self, attrs: &[ast::Attribute], - sub_mod: &Cow<'ast, ast::Mod>, - ) -> Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)> { + sub_mod: &Module<'ast>, + ) -> Vec<(PathBuf, DirectoryOwnership, Module<'ast>)> { // Filter nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. let mut path_visitor = visitor::PathVisitor::default(); for attr in attrs.iter() { @@ -393,17 +441,20 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - let m = match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.inner) - { + let m = match Parser::parse_file_as_module( + self.parse_sess, + &actual_path, + sub_mod.ast_mod.inner, + ) { Ok((_, ref attrs)) if contains_skip(attrs) => continue, - Ok((m, _)) => m, + Ok(m) => m, Err(..) => continue, }; result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, - Cow::Owned(m), + Module::new(Cow::Owned(m.0), &m.1), )) } result diff --git a/src/visitor.rs b/src/visitor.rs index 40783e1f95e..779a3a268ef 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,7 +1,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_ast::{ast, token::DelimToken, visit}; +use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit}; use rustc_span::{symbol, BytePos, Pos, Span}; use crate::attr::*; @@ -16,6 +16,7 @@ use crate::items::{ StaticParts, StructParts, }; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; +use crate::modules::Module; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::skip::{is_skip_attr, SkipContext}; @@ -938,10 +939,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub(crate) fn format_separate_mod(&mut self, m: &ast::Mod, end_pos: BytePos) { + pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) { self.block_indent = Indent::empty(); - self.walk_mod_items(m); - self.format_missing_with_indent(end_pos); + if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) { + self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner); + } else { + self.walk_mod_items(m.as_ref()); + self.format_missing_with_indent(end_pos); + } } pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) { diff --git a/tests/target/inner-module-path/lib.rs b/tests/target/inner-module-path/lib.rs index fb75d70cd93..60d246dd5fb 100644 --- a/tests/target/inner-module-path/lib.rs +++ b/tests/target/inner-module-path/lib.rs @@ -1,5 +1,3 @@ -// rustfmt-recursive: true - #[path = "."] mod a { mod b; -- cgit 1.4.1-3-g733a5 From 9ba373f822eea6bdb4f3672d93bfa94092bfa255 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 16 Sep 2020 08:37:14 -0500 Subject: deps: bump rustc-ap to v678 --- Cargo.lock | 78 ++++++++++++++++++++++++++++------------------------------ Cargo.toml | 18 +++++++------- src/attr.rs | 5 +--- src/macros.rs | 5 ++-- src/spanned.rs | 7 +++--- src/visitor.rs | 9 +++---- 6 files changed, 57 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 941888f7bbb..bd881f8cd01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -897,9 +897,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2958af0d6e0458434a25cd3a96f6e19f24f71bf50b900add520dec52e212866b" +checksum = "baa951ccfe33e3d46ad7b2922ddb935583e9e98029f428681b98afd74cc042b7" dependencies = [ "rustc-ap-rustc_data_structures", "smallvec 1.2.0", @@ -907,9 +907,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c82c2510460f2133548e62399e5acd30c25ae6ece30245baab3d1e00c2fefac" +checksum = "ffa7b3cf87d6249653c00f2fd338adf4e72c8bc617870dda9dfd421aba197a66" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -924,9 +924,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_passes" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83977da57f81c6edd89bad47e49136680eaa33288de4abb702e95358c2a0fc6c" +checksum = "3be435169657440d6287b07a929c9fcc6db04c8c4fc835e0ab5b0fa945a8c028" dependencies = [ "itertools", "rustc-ap-rustc_ast", @@ -943,9 +943,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "becf4ca1638b214694c71a8752192683048ab8bd47947cc481f57bd48157eeb9" +checksum = "38779f1e954d46303e72be59bb32033d920698ef55c3039266fef349d870fb9d" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -955,9 +955,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f21ca5dadce8a40d75a2756b77eab75b4c2d827f645c622dd93ee2285599640" +checksum = "24b419c0ae11c46e86b27e3ae0f5ee9ff2418870c6307f6fed30b02fe727526a" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -974,9 +974,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4cd204764727fde9abf75333eb661f058bfc7242062d91019440fe1b240688b" +checksum = "a1cf84a72b8aa2e6fe4172c2246d707969217d4da1e7a689e12db80d8d5b63d9" dependencies = [ "bitflags", "cfg-if", @@ -984,7 +984,6 @@ dependencies = [ "ena", "indexmap", "jobserver", - "lazy_static", "libc", "measureme", "parking_lot 0.10.2", @@ -1005,9 +1004,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58116f119e37f14c029f99077b347069621118e048a69df74695b98204e7c136" +checksum = "bd08b5d165336da31dfbf5fb1b829eec0bb8516c6e4b755ee659d297d22c5dba" dependencies = [ "annotate-snippets 0.8.0", "atty", @@ -1024,9 +1023,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e3c4bda9b64b92805bebe7431fdb8e24fd112b35a8c6d2174827441f10a6b2" +checksum = "603bb89221349eb78ae87d4f5680a62e4b98f30ce0effbef3b694b91643eeff9" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -1047,32 +1046,31 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b612bb67d3fc49f395b03fc4ea4384a0145b05afbadab725803074ec827632b" +checksum = "4056fa564cd0ec3a0456f69d863682863bcdc5f303bf4bf24886d82456c0ceca" dependencies = [ - "lazy_static", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", ] [[package]] name = "rustc-ap-rustc_fs_util" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7630ad1a73a8434ee920676148cb5440ac57509bd20e94ec41087fb0b1d11c28" +checksum = "626f3dc6ad181fa202994261d86e45db844fc5f30915d42df49d8ce270ed2543" [[package]] name = "rustc-ap-rustc_graphviz" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a603fca4817062eb4fb23ff129d475bd66a69fb32f34ed4362ae950cf814b49d" +checksum = "0615d11907c251a58e48e695653fb50a9c8efafddaeedfeb3291806bf9ae6127" [[package]] name = "rustc-ap-rustc_index" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9850c4a5d7c341513e10802bca9588bf8f452ceea2d5cfa87b934246a52622bc" +checksum = "c365a380a861aabebde64b519fd3766c978009baae7e4244d1f55c5b4cb509ae" dependencies = [ "arrayvec 0.5.1", "rustc-ap-rustc_macros", @@ -1081,18 +1079,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d86722e5a1a615b198327d0d794cd9cbc8b9db4542276fc51fe078924de68ea" +checksum = "3a4ceff9b806d9d7176a31a1d5e2bcb3d98b26b51f6abd136d76ce1d2825233a" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3fc8482e44cabdda7ac9a8e224aef62ebdf95274d629dac8db3b42321025fea" +checksum = "b0f520638ea4f2c80aa56347a3019d79b09bb4de80efb4dfbdc029cdd89a1ad4" dependencies = [ "proc-macro2", "quote", @@ -1102,9 +1100,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3716cdcd978a91dbd4a2788400e90e809527f841426fbeb92f882f9b8582f3ab" +checksum = "169d79f505ffd2c892c0def471eeb5f40c4ae25fff99f1ec3c46868ba47be3a8" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -1122,9 +1120,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_serialize" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68046d07988b349b2e1c8bc1c9664a1d06519354aa677b9df358c5c5c058da0" +checksum = "5b8c16fb186e7130223b1528ee6ea5b11acdcc185f86774f1c44b5b40c0964f2" dependencies = [ "indexmap", "smallvec 1.2.0", @@ -1132,9 +1130,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85735553501a4de0c8904e37b7ccef79cc1c585a7d7f2cfa02cc38e0d149f982" +checksum = "67bf5f3b6619c58f8ac45ca1f2fcc740494e958975565662e984d665a8fc462b" dependencies = [ "bitflags", "getopts", @@ -1153,9 +1151,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c49ae8a0d3b9e27c6ffe8febeaa30f899294fff012de70625f9ee81c54fda85" +checksum = "8ca3c82f0bb52a333385d21b6725e9e426625a754d104102e80eed42dca1b114" dependencies = [ "cfg-if", "md-5", @@ -1172,9 +1170,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "677.0.0" +version = "678.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1765f447594740c501c7b666b87639aa7c1dae2bf8c3166d5d2dca16646fd034" +checksum = "12c36eadab721da7d7e949cfe3043decde13fa9b91a57a309fdb6f1857646cc1" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", diff --git a/Cargo.toml b/Cargo.toml index 6abf2ead7de..84393d2ef3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "677.0.0" +version = "678.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "677.0.0" +version = "678.0.0" diff --git a/src/attr.rs b/src/attr.rs index b3ce47cf319..48c0685d2c1 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -42,10 +42,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { ast::StmtKind::Local(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, - ast::StmtKind::MacCall(ref mac) => { - let (ref mac, _, _) = **mac; - mac.span() - } + ast::StmtKind::MacCall(ref mac_stmt) => mac_stmt.mac.span(), ast::StmtKind::Empty => stmt.span, } } diff --git a/src/macros.rs b/src/macros.rs index 77d670dca59..51b0161244e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1178,8 +1178,7 @@ fn next_space(tok: &TokenKind) -> SpaceState { | TokenKind::Pound | TokenKind::Dollar | TokenKind::OpenDelim(_) - | TokenKind::CloseDelim(_) - | TokenKind::Whitespace => SpaceState::Never, + | TokenKind::CloseDelim(_) => SpaceState::Never, TokenKind::Literal(..) | TokenKind::Ident(..) | TokenKind::Lifetime(_) => SpaceState::Ident, @@ -1275,8 +1274,8 @@ impl MacroParser { span, })) = self.toks.look_ahead(0) { - self.toks.next(); hi = span.hi(); + self.toks.next(); } Some(MacroBranch { span: mk_sp(lo, hi), diff --git a/src/spanned.rs b/src/spanned.rs index 60a350524fa..7bf370c131e 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -66,12 +66,11 @@ impl Spanned for ast::Stmt { ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo(), self.span.hi()) } - ast::StmtKind::MacCall(ref mac) => { - let (_, _, ref attrs) = **mac; - if attrs.is_empty() { + ast::StmtKind::MacCall(ref mac_stmt) => { + if mac_stmt.attrs.is_empty() { self.span } else { - mk_sp(attrs[0].span.lo(), self.span.hi()) + mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi()) } } ast::StmtKind::Empty => self.span, diff --git a/src/visitor.rs b/src/visitor.rs index 779a3a268ef..31605a6601d 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -146,16 +146,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.push_rewrite(stmt.span(), rewrite) } } - ast::StmtKind::MacCall(ref mac) => { - let (ref mac, _macro_style, ref attrs) = **mac; - if self.visit_attrs(attrs, ast::AttrStyle::Outer) { + ast::StmtKind::MacCall(ref mac_stmt) => { + if self.visit_attrs(&mac_stmt.attrs, ast::AttrStyle::Outer) { self.push_skipped_with_span( - attrs, + &mac_stmt.attrs, stmt.span(), get_span_without_attrs(stmt.as_ast_node()), ); } else { - self.visit_mac(mac, None, MacroPosition::Statement); + self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement); } self.format_missing(stmt.span().hi()); } -- cgit 1.4.1-3-g733a5 From 8635a5ca4469e8bb75cb1cf6a41109b352dcfb2b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 22 Sep 2020 22:22:38 -0400 Subject: deps: bump rustc-ap to v679 --- Cargo.lock | 168 +++++++++++++++++++++++++++++++-------------------- Cargo.toml | 18 +++--- src/closures.rs | 2 + src/imports.rs | 9 ++- src/items.rs | 14 +++-- src/syntux/parser.rs | 2 +- src/utils.rs | 6 +- src/visitor.rs | 13 ++-- 8 files changed, 139 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index bd881f8cd01..cf043471bf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -229,6 +229,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "cloudabi" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" +dependencies = [ + "bitflags", +] + [[package]] name = "constant_time_eq" version = "0.1.4" @@ -511,6 +520,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" +dependencies = [ + "cfg-if", +] + [[package]] name = "itertools" version = "0.8.0" @@ -520,6 +538,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.4" @@ -545,9 +572,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" [[package]] name = "lock_api" @@ -558,6 +585,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lock_api" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.8" @@ -651,19 +687,20 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api", + "lock_api 0.3.4", "parking_lot_core 0.6.2", "rustc_version", ] [[package]] name = "parking_lot" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" dependencies = [ - "lock_api", - "parking_lot_core 0.7.2", + "instant", + "lock_api 0.4.1", + "parking_lot_core 0.8.0", ] [[package]] @@ -673,7 +710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ "cfg-if", - "cloudabi", + "cloudabi 0.0.3", "libc", "redox_syscall", "rustc_version", @@ -683,15 +720,16 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ "cfg-if", - "cloudabi", + "cloudabi 0.1.0", + "instant", "libc", "redox_syscall", - "smallvec 1.2.0", + "smallvec 1.4.2", "winapi", ] @@ -822,7 +860,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi", + "cloudabi 0.0.3", "fuchsia-cprng", "libc", "rand_core 0.4.2", @@ -897,19 +935,19 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa951ccfe33e3d46ad7b2922ddb935583e9e98029f428681b98afd74cc042b7" +checksum = "e8e941a8fc3878a111d2bbfe78e39522d884136f0b412b12592195f26f653476" dependencies = [ "rustc-ap-rustc_data_structures", - "smallvec 1.2.0", + "smallvec 1.4.2", ] [[package]] name = "rustc-ap-rustc_ast" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa7b3cf87d6249653c00f2fd338adf4e72c8bc617870dda9dfd421aba197a66" +checksum = "3b58b6b035710df7f339a2bf86f6dafa876efd95439540970e24609e33598ca6" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -918,17 +956,17 @@ dependencies = [ "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "smallvec 1.2.0", + "smallvec 1.4.2", "tracing", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be435169657440d6287b07a929c9fcc6db04c8c4fc835e0ab5b0fa945a8c028" +checksum = "3d379a900d6a1f098490d92ab83e87487dcee2e4ec3f04c3ac4512b5117b64e2" dependencies = [ - "itertools", + "itertools 0.9.0", "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", "rustc-ap-rustc_attr", @@ -943,9 +981,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38779f1e954d46303e72be59bb32033d920698ef55c3039266fef349d870fb9d" +checksum = "658d925c0da9e3c5cddc5e54f4fa8c03b41aff1fc6dc5e41837c1118ad010ac0" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -955,9 +993,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b419c0ae11c46e86b27e3ae0f5ee9ff2418870c6307f6fed30b02fe727526a" +checksum = "3f387037534f34c148aed753622677500e42d190a095670e7ac3fffc09811a59" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -974,9 +1012,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1cf84a72b8aa2e6fe4172c2246d707969217d4da1e7a689e12db80d8d5b63d9" +checksum = "14ffd17a37e00d77926a0713f191c59ff3aeb2b551a024c7cfffce14bab79be8" dependencies = [ "bitflags", "cfg-if", @@ -986,7 +1024,7 @@ dependencies = [ "jobserver", "libc", "measureme", - "parking_lot 0.10.2", + "parking_lot 0.11.0", "rustc-ap-rustc_graphviz", "rustc-ap-rustc_index", "rustc-ap-rustc_macros", @@ -994,7 +1032,7 @@ dependencies = [ "rustc-hash", "rustc-rayon", "rustc-rayon-core", - "smallvec 1.2.0", + "smallvec 1.4.2", "stable_deref_trait", "stacker", "tempfile", @@ -1004,9 +1042,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd08b5d165336da31dfbf5fb1b829eec0bb8516c6e4b755ee659d297d22c5dba" +checksum = "2b3263ddcfa9eb911e54a4e8088878dd9fd10e00d8b99b01033ba4a2733fe91d" dependencies = [ "annotate-snippets 0.8.0", "atty", @@ -1023,9 +1061,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "603bb89221349eb78ae87d4f5680a62e4b98f30ce0effbef3b694b91643eeff9" +checksum = "e1ab7e68cede8a2273fd8b8623002ce9dc832e061dfc3330e9bcc1fc2a722d73" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -1040,15 +1078,15 @@ dependencies = [ "rustc-ap-rustc_serialize", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.2.0", + "smallvec 1.4.2", "tracing", ] [[package]] name = "rustc-ap-rustc_feature" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4056fa564cd0ec3a0456f69d863682863bcdc5f303bf4bf24886d82456c0ceca" +checksum = "eea2dc95421bc19bbd4d939399833a882c46b684283b4267ad1fcf982fc043d9" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -1056,21 +1094,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626f3dc6ad181fa202994261d86e45db844fc5f30915d42df49d8ce270ed2543" +checksum = "1e44c1804f09635f83f6cf1e04c2e92f8aeb7b4e850ac6c53d373dab02c13053" [[package]] name = "rustc-ap-rustc_graphviz" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0615d11907c251a58e48e695653fb50a9c8efafddaeedfeb3291806bf9ae6127" +checksum = "dc491f2b9be6e928f6df6b287549b8d50c48e8eff8638345155f40fa2cfb785d" [[package]] name = "rustc-ap-rustc_index" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c365a380a861aabebde64b519fd3766c978009baae7e4244d1f55c5b4cb509ae" +checksum = "fa73f3fed413cdb6290738a10267da17b9ae8e02087334778b9a8c9491c5efc0" dependencies = [ "arrayvec 0.5.1", "rustc-ap-rustc_macros", @@ -1079,18 +1117,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a4ceff9b806d9d7176a31a1d5e2bcb3d98b26b51f6abd136d76ce1d2825233a" +checksum = "e993881244a92f3b44cf43c8f22ae2ca5cefe4f55a34e2b65b72ee66fe5ad077" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f520638ea4f2c80aa56347a3019d79b09bb4de80efb4dfbdc029cdd89a1ad4" +checksum = "4effe366556e1d75344764adf4d54cba7c2fad33dbd07588e96d0853831ddc7c" dependencies = [ "proc-macro2", "quote", @@ -1100,9 +1138,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "169d79f505ffd2c892c0def471eeb5f40c4ae25fff99f1ec3c46868ba47be3a8" +checksum = "0342675835251571471d3dca9ea1576a853a8dfa1f4b0084db283c861223cb60" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -1113,26 +1151,26 @@ dependencies = [ "rustc-ap-rustc_lexer", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.2.0", + "smallvec 1.4.2", "tracing", "unicode-normalization", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8c16fb186e7130223b1528ee6ea5b11acdcc185f86774f1c44b5b40c0964f2" +checksum = "438255ed968d73bf6573aa18d3b8d33c0a85ecdfd14160ef09ff813938e0606c" dependencies = [ "indexmap", - "smallvec 1.2.0", + "smallvec 1.4.2", ] [[package]] name = "rustc-ap-rustc_session" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67bf5f3b6619c58f8ac45ca1f2fcc740494e958975565662e984d665a8fc462b" +checksum = "7d61ff76dede8eb827f6805754900d1097a7046f938f950231b62b448f55bf78" dependencies = [ "bitflags", "getopts", @@ -1151,9 +1189,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca3c82f0bb52a333385d21b6725e9e426625a754d104102e80eed42dca1b114" +checksum = "1c267f15c3cfc82a8a441d2bf86bcccf299d1eb625822468e3d8ee6f7c5a1c89" dependencies = [ "cfg-if", "md-5", @@ -1170,9 +1208,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "678.0.0" +version = "679.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c36eadab721da7d7e949cfe3043decde13fa9b91a57a309fdb6f1857646cc1" +checksum = "8b1b4b266c4d44aac0f7f83b6741d8f0545b03d1ce32f3b5254f2014225cb96c" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -1257,7 +1295,7 @@ dependencies = [ "env_logger", "getopts", "ignore", - "itertools", + "itertools 0.8.0", "lazy_static", "log", "regex", @@ -1306,9 +1344,9 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" [[package]] name = "scopeguard" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" @@ -1377,9 +1415,9 @@ checksum = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" [[package]] name = "smallvec" -version = "1.2.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" +checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" [[package]] name = "stable_deref_trait" @@ -1606,7 +1644,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0", + "smallvec 1.4.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 84393d2ef3c..07edeb6b7ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "678.0.0" +version = "679.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "678.0.0" +version = "679.0.0" diff --git a/src/closures.rs b/src/closures.rs index 00bd03026e6..fe632323aa4 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -150,10 +150,12 @@ fn rewrite_closure_with_block( id: ast::NodeId::root(), kind: ast::StmtKind::Expr(ptr::P(body.clone())), span: body.span, + tokens: None, }], id: ast::NodeId::root(), rules: ast::BlockCheckMode::Default, span: body.span, + tokens: None, }; let block = crate::expr::rewrite_block_with_visitor( context, diff --git a/src/imports.rs b/src/imports.rs index 914b91a46ca..0b3d844ea14 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -4,7 +4,6 @@ use std::fmt; use rustc_ast::ast::{self, UseTreeKind}; use rustc_span::{ - source_map, symbol::{self, sym}, BytePos, Span, DUMMY_SP, }; @@ -509,16 +508,16 @@ impl UseTree { fn same_visibility(&self, other: &UseTree) -> bool { match (&self.visibility, &other.visibility) { ( - Some(source_map::Spanned { - node: ast::VisibilityKind::Inherited, + Some(ast::Visibility { + kind: ast::VisibilityKind::Inherited, .. }), None, ) | ( None, - Some(source_map::Spanned { - node: ast::VisibilityKind::Inherited, + Some(ast::Visibility { + kind: ast::VisibilityKind::Inherited, .. }), ) diff --git a/src/items.rs b/src/items.rs index e772164862d..415c21450d6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -6,7 +6,7 @@ use std::cmp::{max, min, Ordering}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{source_map, symbol, BytePos, Span, DUMMY_SP}; +use rustc_span::{symbol, BytePos, Span, DUMMY_SP}; use crate::attr::filter_inline_attrs; use crate::comment::{ @@ -31,9 +31,10 @@ use crate::utils::*; use crate::vertical::rewrite_with_alignment; use crate::visitor::FmtVisitor; -const DEFAULT_VISIBILITY: ast::Visibility = source_map::Spanned { - node: ast::VisibilityKind::Inherited, +const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility { + kind: ast::VisibilityKind::Inherited, span: DUMMY_SP, + tokens: None, }; fn type_annotation_separator(config: &Config) -> &str { @@ -125,7 +126,7 @@ impl Rewrite for ast::Local { // FIXME format modules in this style #[allow(dead_code)] struct Item<'a> { - keyword: &'static str, + unsafety: ast::Unsafe, abi: Cow<'static, str>, vis: Option<&'a ast::Visibility>, body: Vec>, @@ -135,7 +136,7 @@ struct Item<'a> { impl<'a> Item<'a> { fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> { Item { - keyword: "", + unsafety: fm.unsafety, abi: format_extern( ast::Extern::from_abi(fm.abi), config.force_explicit_abi(), @@ -254,6 +255,7 @@ impl<'a> FnSig<'a> { impl<'a> FmtVisitor<'a> { fn format_item(&mut self, item: &Item<'_>) { + self.buffer.push_str(format_unsafety(item.unsafety)); self.buffer.push_str(&item.abi); let snippet = self.snippet(item.span); @@ -1367,7 +1369,7 @@ pub(crate) fn format_struct_struct( } fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> BytePos { - match vis.node { + match vis.kind { ast::VisibilityKind::Crate(..) | ast::VisibilityKind::Restricted { .. } => vis.span.hi(), _ => default_span.lo(), } diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 2730ff37788..711dfc80c2c 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -118,7 +118,7 @@ impl<'a> Parser<'a> { ) -> Result<(ast::Mod, Vec), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); - match parser.parse_mod(&TokenKind::Eof) { + match parser.parse_mod(&TokenKind::Eof, ast::Unsafe::No) { Ok(result) => Some(result), Err(mut e) => { e.cancel(); diff --git a/src/utils.rs b/src/utils.rs index 618172595eb..a8427cf9bab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -38,11 +38,11 @@ pub(crate) fn extra_offset(text: &str, shape: Shape) -> usize { } pub(crate) fn is_same_visibility(a: &Visibility, b: &Visibility) -> bool { - match (&a.node, &b.node) { + match (&a.kind, &b.kind) { ( VisibilityKind::Restricted { path: p, .. }, VisibilityKind::Restricted { path: q, .. }, - ) => pprust::path_to_string(p) == pprust::path_to_string(q), + ) => pprust::path_to_string(&p) == pprust::path_to_string(&q), (VisibilityKind::Public, VisibilityKind::Public) | (VisibilityKind::Inherited, VisibilityKind::Inherited) | ( @@ -62,7 +62,7 @@ pub(crate) fn format_visibility( context: &RewriteContext<'_>, vis: &Visibility, ) -> Cow<'static, str> { - match vis.node { + match vis.kind { VisibilityKind::Public => Cow::from("pub "), VisibilityKind::Inherited => Cow::from(""), VisibilityKind::Crate(CrateSugar::PubCrate) => Cow::from("pub(crate) "), diff --git a/src/visitor.rs b/src/visitor.rs index 31605a6601d..e0e1c1354c6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -2,7 +2,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit}; -use rustc_span::{symbol, BytePos, Pos, Span}; +use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::attr::*; use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; @@ -25,8 +25,8 @@ use crate::spanned::Spanned; use crate::stmt::Stmt; use crate::syntux::session::ParseSess; use crate::utils::{ - self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, last_line_width, - mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, + self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes, + last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -603,7 +603,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } ast::AssocItemKind::Fn(defaultness, ref sig, ref generics, Some(ref body)) => { let inner_attrs = inner_attributes(&ti.attrs); - let vis = rustc_span::source_map::dummy_spanned(ast::VisibilityKind::Inherited); + let vis = ast::Visibility { + kind: ast::VisibilityKind::Inherited, + span: DUMMY_SP, + tokens: None, + }; let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); self.visit_fn( visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), @@ -902,6 +906,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) { let vis_str = utils::format_visibility(&self.get_context(), vis); self.push_str(&*vis_str); + self.push_str(format_unsafety(m.unsafety)); self.push_str("mod "); // Calling `to_owned()` to work around borrow checker. let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); -- cgit 1.4.1-3-g733a5 From d6a220b70a375ae722c7d6c1c069fbf6298b6260 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 23 Sep 2020 22:19:11 -0500 Subject: feat: support config. of leading match arm pipe --- src/config/mod.rs | 3 +++ src/config/options.rs | 11 +++++++++++ src/matches.rs | 23 +++++++++++++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index 07c5612e26e..bb86a379eb1 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -91,6 +91,8 @@ create_config! { "Align enum variants discrims, if their diffs fit within threshold"; match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \ the same line with the pattern of arms"; + match_arm_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true, + "Determines whether leading pipes are emitted on match arms"; force_multiline_blocks: bool, false, false, "Force multiline closure bodies and match arms to be wrapped in a block"; fn_args_layout: Density, Density::Tall, true, @@ -528,6 +530,7 @@ overflow_delimited_expr = false struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true +match_arm_leading_pipes = "Never" force_multiline_blocks = false fn_args_layout = "Tall" brace_style = "SameLineWhere" diff --git a/src/config/options.rs b/src/config/options.rs index c9d51a5a71a..028ad2d3757 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -392,3 +392,14 @@ impl Edition { } } } + +/// Controls how rustfmt should handle leading pipes on match arms. +#[config_type] +pub enum MatchArmLeadingPipe { + /// Place leading pipes on all match arms + Always, + /// Never emit leading pipes on match arms + Never, + /// Preserve any existing leading pipes + Preserve, +} diff --git a/src/matches.rs b/src/matches.rs index b5ca49b38bc..7b691bf6100 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -7,7 +7,7 @@ use rustc_span::{BytePos, Span}; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; -use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; +use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, Version}; use crate::expr::{ format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, ExprType, RhsTactics, @@ -55,7 +55,13 @@ impl<'a> Spanned for ArmWrapper<'a> { impl<'a> Rewrite for ArmWrapper<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - rewrite_match_arm(context, self.arm, shape, self.is_last) + rewrite_match_arm( + context, + self.arm, + shape, + self.is_last, + self.beginning_vert.is_some(), + ) } } @@ -215,6 +221,7 @@ fn rewrite_match_arm( arm: &ast::Arm, shape: Shape, is_last: bool, + has_leading_pipe: bool, ) -> Option { let (missing_span, attrs_str) = if !arm.attrs.is_empty() { if contains_skip(&arm.attrs) { @@ -232,9 +239,17 @@ fn rewrite_match_arm( (mk_sp(arm.span().lo(), arm.span().lo()), String::new()) }; + // Leading pipe offset + // 2 = `| ` + let (pipe_offset, pipe_str) = match context.config.match_arm_leading_pipes() { + MatchArmLeadingPipe::Never => (0, ""), + MatchArmLeadingPipe::Preserve if !has_leading_pipe => (0, ""), + MatchArmLeadingPipe::Preserve | MatchArmLeadingPipe::Always => (2, "| "), + }; + // Patterns // 5 = ` => {` - let pat_shape = shape.sub_width(5)?; + let pat_shape = shape.sub_width(5)?.offset_left(pipe_offset)?; let pats_str = arm.pat.rewrite(context, pat_shape)?; // Guard @@ -251,7 +266,7 @@ fn rewrite_match_arm( let lhs_str = combine_strs_with_missing_comments( context, &attrs_str, - &format!("{}{}", pats_str, guard_str), + &format!("{}{}{}", pipe_str, pats_str, guard_str), missing_span, shape, false, -- cgit 1.4.1-3-g733a5 From a15800a32778c35e32efe47f7e6889784e06ebcc Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 9 May 2020 15:19:48 -0700 Subject: Preserve and format type aliases in extern blocks Previously, non-trivial type aliases in extern blocks were dropped by rustfmt because only the type alias name would be passed to a rewritter. This commit fixes that by passing all type information (generics, bounds, and assignments) to a type alias rewritter, and consolidates `rewrite_type_alias` and `rewrite_associated_type` as one function. --- src/items.rs | 95 ++++++++++++++++++++++++++-------------------- src/visitor.rs | 16 ++++---- tests/target/issue-4159.rs | 18 +++++++++ 3 files changed, 81 insertions(+), 48 deletions(-) create mode 100644 tests/target/issue-4159.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 415c21450d6..2c4570a3a75 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1510,6 +1510,7 @@ fn rewrite_type_prefix( prefix: &str, ident: symbol::Ident, generics: &ast::Generics, + generic_bounds_opt: Option<&ast::GenericBounds>, ) -> Option { let mut result = String::with_capacity(128); result.push_str(prefix); @@ -1526,6 +1527,19 @@ fn rewrite_type_prefix( result.push_str(&generics_str); } + let type_bounds_str = if let Some(bounds) = generic_bounds_opt { + if bounds.is_empty() { + String::new() + } else { + // 2 = `: ` + let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?; + bounds.rewrite(context, shape).map(|s| format!(": {}", s))? + } + } else { + String::new() + }; + result.push_str(&type_bounds_str); + let where_budget = context.budget(last_line_width(&result)); let option = WhereClauseOption::snuggled(&result); let where_clause_str = rewrite_where_clause( @@ -1552,6 +1566,7 @@ fn rewrite_type_item( ident: symbol::Ident, rhs: &R, generics: &ast::Generics, + generic_bounds_opt: Option<&ast::GenericBounds>, vis: &ast::Visibility, ) -> Option { let mut result = String::with_capacity(128); @@ -1561,6 +1576,7 @@ fn rewrite_type_item( &format!("{}{} ", format_visibility(context, vis), prefix), ident, generics, + generic_bounds_opt, )?); if generics.where_clause.predicates.is_empty() { @@ -1575,17 +1591,6 @@ fn rewrite_type_item( rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";") } -pub(crate) fn rewrite_type_alias( - context: &RewriteContext<'_>, - indent: Indent, - ident: symbol::Ident, - ty: &ast::Ty, - generics: &ast::Generics, - vis: &ast::Visibility, -) -> Option { - rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis) -} - pub(crate) fn rewrite_opaque_type( context: &RewriteContext<'_>, indent: Indent, @@ -1603,6 +1608,7 @@ pub(crate) fn rewrite_opaque_type( ident, &opaque_type_bounds, generics, + Some(generic_bounds), vis, ) } @@ -1824,39 +1830,39 @@ fn rewrite_static( } } -pub(crate) fn rewrite_associated_type( +pub(crate) fn rewrite_type_alias( ident: symbol::Ident, ty_opt: Option<&ptr::P>, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, context: &RewriteContext<'_>, indent: Indent, + vis: &ast::Visibility, ) -> Option { - let ident_str = rewrite_ident(context, ident); - // 5 = "type " - let generics_shape = Shape::indented(indent, context.config).offset_left(5)?; - let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?; - let prefix = format!("type {}", generics_str); - - let type_bounds_str = if let Some(bounds) = generic_bounds_opt { - if bounds.is_empty() { - String::new() - } else { - // 2 = ": ".len() - let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?; - bounds.rewrite(context, shape).map(|s| format!(": {}", s))? - } - } else { - String::new() - }; + let mut prefix = rewrite_type_prefix( + context, + indent, + &format!("{}type ", format_visibility(context, vis)), + ident, + generics, + generic_bounds_opt, + )?; if let Some(ty) = ty_opt { // 1 = `;` let shape = Shape::indented(indent, context.config).sub_width(1)?; - let lhs = format!("{}{} =", prefix, type_bounds_str); + + // If there's a where clause, add a newline before the assignment. Otherwise just add a + // space. + if !generics.where_clause.predicates.is_empty() { + prefix.push_str(&indent.to_string_with_newline(context.config)); + } else { + prefix.push(' '); + } + let lhs = format!("{}=", prefix); rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") } else { - Some(format!("{}{};", prefix, type_bounds_str)) + Some(format!("{};", prefix)) } } @@ -1900,13 +1906,14 @@ pub(crate) fn rewrite_opaque_impl_type( pub(crate) fn rewrite_associated_impl_type( ident: symbol::Ident, + vis: &ast::Visibility, defaultness: ast::Defaultness, ty_opt: Option<&ptr::P>, generics: &ast::Generics, context: &RewriteContext<'_>, indent: Indent, ) -> Option { - let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?; + let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis)?; match defaultness { ast::Defaultness::Default(..) => Some(format!("default {}", result)), @@ -3088,7 +3095,7 @@ impl Rewrite for ast::ForeignItem { // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - let item_str = match self.kind { + let item_str: String = match self.kind { ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( context, shape.indent, @@ -3112,14 +3119,20 @@ impl Rewrite for ast::ForeignItem { // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } - ast::ForeignItemKind::TyAlias(..) => { - let vis = format_visibility(context, &self.vis); - Some(format!( - "{}type {};", - vis, - rewrite_ident(context, self.ident) - )) - } + ast::ForeignItemKind::TyAlias( + _, + ref generics, + ref generic_bounds, + ref type_default, + ) => rewrite_type_alias( + self.ident, + type_default.as_ref(), + generics, + Some(generic_bounds), + &context, + shape.indent, + &self.vis, + ), ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) } diff --git a/src/visitor.rs b/src/visitor.rs index e0e1c1354c6..523d4e9fea9 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -11,9 +11,8 @@ use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, - rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, - StaticParts, StructParts, + rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, + rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, }; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; use crate::modules::Module; @@ -544,11 +543,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty { Some(ty) => { let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, item.ident, - &*ty, + Some(&*ty), generics, + Some(generic_bounds), + &self.get_context(), + self.block_indent, &item.vis, ); self.push_rewrite(item.span, rewrite); @@ -619,13 +619,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } ast::AssocItemKind::TyAlias(_, ref generics, ref generic_bounds, ref type_default) => { - let rewrite = rewrite_associated_type( + let rewrite = rewrite_type_alias( ti.ident, type_default.as_ref(), generics, Some(generic_bounds), &self.get_context(), self.block_indent, + &ti.vis, ); self.push_rewrite(ti.span, rewrite); } @@ -666,6 +667,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let rewrite_associated = || { rewrite_associated_impl_type( ii.ident, + &ii.vis, defaultness, ty.as_ref(), &generics, diff --git a/tests/target/issue-4159.rs b/tests/target/issue-4159.rs new file mode 100644 index 00000000000..52abb132cae --- /dev/null +++ b/tests/target/issue-4159.rs @@ -0,0 +1,18 @@ +extern "C" { + type A: Ord; + + type A<'a> + where + 'a: 'static,; + + type A + where + T: 'static,; + + type A = u8; + + type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq + where + T: 'static + Copy, + = Vec; +} -- cgit 1.4.1-3-g733a5 From a9b0b057eb7c2ff6e764fadc36d94e90e64b5c90 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 9 May 2020 16:01:42 -0700 Subject: fixup! Preserve and format type aliases in extern blocks --- src/items.rs | 3 +++ tests/target/issue-4159.rs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 2c4570a3a75..4e10d0c4757 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1862,6 +1862,9 @@ pub(crate) fn rewrite_type_alias( let lhs = format!("{}=", prefix); rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") } else { + if !generics.where_clause.predicates.is_empty() { + prefix.push_str(&indent.to_string_with_newline(context.config)); + } Some(format!("{};", prefix)) } } diff --git a/tests/target/issue-4159.rs b/tests/target/issue-4159.rs index 52abb132cae..fed6095354a 100644 --- a/tests/target/issue-4159.rs +++ b/tests/target/issue-4159.rs @@ -3,11 +3,13 @@ extern "C" { type A<'a> where - 'a: 'static,; + 'a: 'static, + ; type A where - T: 'static,; + T: 'static, + ; type A = u8; -- cgit 1.4.1-3-g733a5 From 92ab76cfa7eae26f525d36ea1d7b08b267b804cc Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sun, 10 May 2020 10:06:23 -0700 Subject: fixup! Preserve and format type aliases in extern blocks --- src/items.rs | 107 ++++++++++++++------------------------------- tests/target/issue-4159.rs | 6 +-- 2 files changed, 36 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 4e10d0c4757..cfb3b249107 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1504,22 +1504,23 @@ fn format_tuple_struct( Some(result) } -fn rewrite_type_prefix( +fn rewrite_type( context: &RewriteContext<'_>, indent: Indent, - prefix: &str, ident: symbol::Ident, + vis: &ast::Visibility, generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, + rhs: Option<&R>, ) -> Option { let mut result = String::with_capacity(128); - result.push_str(prefix); + result.push_str(&format!("{}type ", format_visibility(context, vis))); let ident_str = rewrite_ident(context, ident); - // 2 = `= ` if generics.params.is_empty() { result.push_str(ident_str) } else { + // 2 = `= ` let g_shape = Shape::indented(indent, context.config) .offset_left(result.len())? .sub_width(2)?; @@ -1527,21 +1528,20 @@ fn rewrite_type_prefix( result.push_str(&generics_str); } - let type_bounds_str = if let Some(bounds) = generic_bounds_opt { - if bounds.is_empty() { - String::new() - } else { + if let Some(bounds) = generic_bounds_opt { + if !bounds.is_empty() { // 2 = `: ` let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?; - bounds.rewrite(context, shape).map(|s| format!(": {}", s))? + let type_bounds = bounds.rewrite(context, shape).map(|s| format!(": {}", s))?; + result.push_str(&type_bounds); } - } else { - String::new() - }; - result.push_str(&type_bounds_str); + } let where_budget = context.budget(last_line_width(&result)); - let option = WhereClauseOption::snuggled(&result); + let mut option = WhereClauseOption::snuggled(&result); + if rhs.is_none() { + option.suppress_comma(); + } let where_clause_str = rewrite_where_clause( context, &generics.where_clause, @@ -1555,40 +1555,22 @@ fn rewrite_type_prefix( )?; result.push_str(&where_clause_str); - Some(result) -} - -fn rewrite_type_item( - context: &RewriteContext<'_>, - indent: Indent, - prefix: &str, - suffix: &str, - ident: symbol::Ident, - rhs: &R, - generics: &ast::Generics, - generic_bounds_opt: Option<&ast::GenericBounds>, - vis: &ast::Visibility, -) -> Option { - let mut result = String::with_capacity(128); - result.push_str(&rewrite_type_prefix( - context, - indent, - &format!("{}{} ", format_visibility(context, vis), prefix), - ident, - generics, - generic_bounds_opt, - )?); + if let Some(ty) = rhs { + // If there's a where clause, add a newline before the assignment. Otherwise just add a + // space. + if !generics.where_clause.predicates.is_empty() { + result.push_str(&indent.to_string_with_newline(context.config)); + } else { + result.push(' '); + } + let lhs = format!("{}=", result); - if generics.where_clause.predicates.is_empty() { - result.push_str(suffix); + // 1 = `;` + let shape = Shape::indented(indent, context.config).sub_width(1)?; + rewrite_assign_rhs(context, lhs, &*ty, shape).map(|s| s + ";") } else { - result.push_str(&indent.to_string_with_newline(context.config)); - result.push_str(suffix.trim_start()); + Some(format!("{};", result)) } - - // 1 = ";" - let rhs_shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";") } pub(crate) fn rewrite_opaque_type( @@ -1600,16 +1582,14 @@ pub(crate) fn rewrite_opaque_type( vis: &ast::Visibility, ) -> Option { let opaque_type_bounds = OpaqueTypeBounds { generic_bounds }; - rewrite_type_item( + rewrite_type( context, indent, - "type", - " =", ident, - &opaque_type_bounds, + vis, generics, Some(generic_bounds), - vis, + Some(&opaque_type_bounds), ) } @@ -1839,34 +1819,15 @@ pub(crate) fn rewrite_type_alias( indent: Indent, vis: &ast::Visibility, ) -> Option { - let mut prefix = rewrite_type_prefix( + rewrite_type( context, indent, - &format!("{}type ", format_visibility(context, vis)), ident, + vis, generics, generic_bounds_opt, - )?; - - if let Some(ty) = ty_opt { - // 1 = `;` - let shape = Shape::indented(indent, context.config).sub_width(1)?; - - // If there's a where clause, add a newline before the assignment. Otherwise just add a - // space. - if !generics.where_clause.predicates.is_empty() { - prefix.push_str(&indent.to_string_with_newline(context.config)); - } else { - prefix.push(' '); - } - let lhs = format!("{}=", prefix); - rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";") - } else { - if !generics.where_clause.predicates.is_empty() { - prefix.push_str(&indent.to_string_with_newline(context.config)); - } - Some(format!("{};", prefix)) - } + ty_opt, + ) } struct OpaqueType<'a> { diff --git a/tests/target/issue-4159.rs b/tests/target/issue-4159.rs index fed6095354a..2f8cf20da2c 100644 --- a/tests/target/issue-4159.rs +++ b/tests/target/issue-4159.rs @@ -3,13 +3,11 @@ extern "C" { type A<'a> where - 'a: 'static, - ; + 'a: 'static; type A where - T: 'static, - ; + T: 'static; type A = u8; -- cgit 1.4.1-3-g733a5 From 2a8ff209f68f9b6ae8be746b4fcd94afe97984e3 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sun, 10 May 2020 10:11:36 -0700 Subject: fixup! Preserve and format type aliases in extern blocks --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cfb3b249107..1e2eac0c74b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3059,7 +3059,7 @@ impl Rewrite for ast::ForeignItem { // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); - let item_str: String = match self.kind { + let item_str = match self.kind { ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( context, shape.indent, -- cgit 1.4.1-3-g733a5 From 14d53f75c94c39d781190d9fd83a95fbcd14b38f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 16 Sep 2020 07:09:10 -0700 Subject: Use rustfmt given by RUSTFMT env var (#4419) --- config_proc_macro/src/utils.rs | 9 ++++++++- src/cargo-fmt/main.rs | 14 ++++++++++++-- src/format-diff/main.rs | 9 ++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/config_proc_macro/src/utils.rs b/config_proc_macro/src/utils.rs index fec6a8e4907..c6e6ad1aec8 100644 --- a/config_proc_macro/src/utils.rs +++ b/config_proc_macro/src/utils.rs @@ -1,5 +1,7 @@ use proc_macro2::TokenStream; use quote::{quote, ToTokens}; +use std::env; +use std::ffi::OsStr; pub fn fold_quote(input: impl Iterator, f: F) -> TokenStream where @@ -25,7 +27,12 @@ pub fn debug_with_rustfmt(input: &TokenStream) { use std::io::Write; use std::process::{Command, Stdio}; - let mut child = Command::new("rustfmt") + let rustfmt_var = env::var_os("RUSTFMT"); + let rustfmt = match &rustfmt_var { + Some(rustfmt) => rustfmt, + None => OsStr::new("rustfmt"), + }; + let mut child = Command::new(rustfmt) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 233a0f1d145..22aeceeb53b 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -7,6 +7,7 @@ use cargo_metadata; use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use std::env; +use std::ffi::OsStr; use std::fs; use std::hash::{Hash, Hasher}; use std::io::{self, Write}; @@ -129,6 +130,15 @@ fn execute() -> i32 { } } +fn rustfmt_command() -> Command { + let rustfmt_var = env::var_os("RUSTFMT"); + let rustfmt = match &rustfmt_var { + Some(rustfmt) => rustfmt, + None => OsStr::new("rustfmt"), + }; + Command::new(rustfmt) +} + fn convert_message_format_to_rustfmt_args( message_format: &str, rustfmt_args: &mut Vec, @@ -205,7 +215,7 @@ fn handle_command_status(status: Result) -> i32 { } fn get_rustfmt_info(args: &[String]) -> Result { - let mut command = Command::new("rustfmt") + let mut command = rustfmt_command() .stdout(std::process::Stdio::inherit()) .args(args) .spawn() @@ -484,7 +494,7 @@ fn run_rustfmt( println!(); } - let mut command = Command::new("rustfmt") + let mut command = rustfmt_command() .stdout(stdout) .args(files) .args(&["--edition", edition]) diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index a73d2da4d03..8a8bb9356ca 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -13,6 +13,8 @@ use serde_json as json; use thiserror::Error; use std::collections::HashSet; +use std::env; +use std::ffi::OsStr; use std::io::{self, BufRead}; use std::process; @@ -94,7 +96,12 @@ fn run_rustfmt(files: &HashSet, ranges: &[Range]) -> Result<(), FormatDi debug!("Files: {:?}", files); debug!("Ranges: {:?}", ranges); - let exit_status = process::Command::new("rustfmt") + let rustfmt_var = env::var_os("RUSTFMT"); + let rustfmt = match &rustfmt_var { + Some(rustfmt) => rustfmt, + None => OsStr::new("rustfmt"), + }; + let exit_status = process::Command::new(rustfmt) .args(files) .arg("--file-lines") .arg(ranges_as_json) -- cgit 1.4.1-3-g733a5 From c89638ae555934113d3ff73c8648ead09410b592 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 19 Oct 2020 20:26:36 -0500 Subject: deps: update macro parsing --- src/macros.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 51b0161244e..62cc5f9dcc5 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -16,7 +16,8 @@ use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; -use rustc_parse::{new_parser_from_tts, parser::Parser}; +use rustc_parse::parser::Parser; +use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS}; use rustc_span::{ symbol::{self, kw}, BytePos, Span, Symbol, DUMMY_SP, @@ -89,6 +90,14 @@ impl Rewrite for MacroArg { } } +fn build_parser<'a>(context: &RewriteContext<'a>, cursor: Cursor) -> Parser<'a> { + stream_to_parser( + context.parse_sess.inner(), + cursor.collect(), + MACRO_ARGUMENTS, + ) +} + fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { macro_rules! parse_macro_arg { ($macro_arg:ident, $parser:expr, $f:expr) => { @@ -290,7 +299,7 @@ fn rewrite_macro_inner( } } - let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); + let mut parser = build_parser(context, ts.trees()); let mut arg_vec = Vec::new(); let mut vec_with_semi = false; let mut trailing_comma = false; @@ -1196,7 +1205,7 @@ pub(crate) fn convert_try_mac( let path = &pprust::path_to_string(&mac.path); if path == "try" || path == "r#try" { let ts = mac.args.inner_tokens(); - let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); + let mut parser = build_parser(context, ts.trees()); Some(ast::Expr { id: ast::NodeId::root(), // dummy value @@ -1429,7 +1438,7 @@ fn format_lazy_static( ts: &TokenStream, ) -> Option { let mut result = String::with_capacity(1024); - let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); + let mut parser = build_parser(context, ts.trees()); let nested_shape = shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config); -- cgit 1.4.1-3-g733a5 From 31cef56779dbce430a4052df141cc3d1b5a36ec2 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 19 Oct 2020 20:26:56 -0500 Subject: feat: add initial support for ConstBlock expressions --- src/expr.rs | 3 +++ src/utils.rs | 1 + 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 2b28e1ac92c..6bc54ff8601 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -124,6 +124,9 @@ pub(crate) fn format_expr( | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) => to_control_flow(expr, expr_type) .and_then(|control_flow| control_flow.rewrite(context, shape)), + ast::ExprKind::ConstBlock(ref anon_const) => { + Some(format!("const {}", anon_const.rewrite(context, shape)?)) + } ast::ExprKind::Block(ref block, opt_label) => { match expr_type { ExprType::Statement => { diff --git a/src/utils.rs b/src/utils.rs index a8427cf9bab..f8867914937 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -461,6 +461,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::While(..) | ast::ExprKind::If(..) | ast::ExprKind::Block(..) + | ast::ExprKind::ConstBlock(..) | ast::ExprKind::Async(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) -- cgit 1.4.1-3-g733a5 From e70343a5f520c1a028336fc1ccd09479ef4084ae Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Tue, 25 Aug 2020 23:52:26 -0500 Subject: Correctly indent skipped-over code Closes #4398 --- src/missed_spans.rs | 1 + tests/source/issue-4398.rs | 19 +++++++++++++++++++ tests/target/issue-4398.rs | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/source/issue-4398.rs create mode 100644 tests/target/issue-4398.rs (limited to 'src') diff --git a/src/missed_spans.rs b/src/missed_spans.rs index e6889ae9786..17b11ed6cf4 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -353,6 +353,7 @@ impl<'a> FmtVisitor<'a> { let remaining = snippet[status.line_start..subslice.len() + offset].trim(); if !remaining.is_empty() { + self.push_str(&self.block_indent.to_string(self.config)); self.push_str(remaining); status.line_start = subslice.len() + offset; } diff --git a/tests/source/issue-4398.rs b/tests/source/issue-4398.rs new file mode 100644 index 00000000000..b0095aaac79 --- /dev/null +++ b/tests/source/issue-4398.rs @@ -0,0 +1,19 @@ +impl Struct { + /// Documentation for `foo` + #[rustfmt::skip] // comment on why use a skip here + pub fn foo(&self) {} +} + +impl Struct { + /// Documentation for `foo` + #[rustfmt::skip] // comment on why use a skip here + pub fn foo(&self) {} +} + +/// Documentation for `Struct` +#[rustfmt::skip] // comment +impl Struct { + /// Documentation for `foo` + #[rustfmt::skip] // comment on why use a skip here + pub fn foo(&self) {} +} diff --git a/tests/target/issue-4398.rs b/tests/target/issue-4398.rs new file mode 100644 index 00000000000..2ca894528e9 --- /dev/null +++ b/tests/target/issue-4398.rs @@ -0,0 +1,19 @@ +impl Struct { + /// Documentation for `foo` + #[rustfmt::skip] // comment on why use a skip here + pub fn foo(&self) {} +} + +impl Struct { + /// Documentation for `foo` + #[rustfmt::skip] // comment on why use a skip here + pub fn foo(&self) {} +} + +/// Documentation for `Struct` +#[rustfmt::skip] // comment +impl Struct { + /// Documentation for `foo` + #[rustfmt::skip] // comment on why use a skip here + pub fn foo(&self) {} +} -- cgit 1.4.1-3-g733a5 From 6a7824787e231485d93c9a08a13d229cbcd14ded Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Wed, 20 May 2020 10:39:34 -0500 Subject: Preserve comments in empty statements (#4180) * Preserve comments in empty statements Closes #4018 * fixup! Preserve comments in empty statements --- src/stmt.rs | 4 ++++ src/visitor.rs | 22 +++++++++++++++++----- tests/source/issue-4018.rs | 13 +++++++++++++ tests/target/issue-4018.rs | 11 +++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 tests/source/issue-4018.rs create mode 100644 tests/target/issue-4018.rs (limited to 'src') diff --git a/src/stmt.rs b/src/stmt.rs index 807cd9e5fad..0b3854425ea 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -52,6 +52,10 @@ impl<'a> Stmt<'a> { result } + pub(crate) fn is_empty(&self) -> bool { + matches!(self.inner.kind, ast::StmtKind::Empty) + } + fn is_last_expr(&self) -> bool { if !self.is_last { return false; diff --git a/src/visitor.rs b/src/visitor.rs index 523d4e9fea9..e7fa27aae0c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -25,7 +25,7 @@ use crate::stmt::Stmt; use crate::syntux::session::ParseSess; use crate::utils::{ self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes, - last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, + last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -117,10 +117,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.parse_sess.span_to_debug_info(stmt.span()) ); - // https://github.com/rust-lang/rust/issues/63679. - let is_all_semicolons = - |snippet: &str| snippet.chars().all(|c| c.is_whitespace() || c == ';'); - if is_all_semicolons(&self.snippet(stmt.span())) { + if stmt.is_empty() { + // If the statement is empty, just skip over it. Before that, make sure any comment + // snippet preceding the semicolon is picked up. + let snippet = self.snippet(mk_sp(self.last_pos, stmt.span().lo())); + let original_starts_with_newline = snippet + .find(|c| c != ' ') + .map_or(false, |i| starts_with_newline(&snippet[i..])); + let snippet = snippet.trim(); + if !snippet.is_empty() { + if original_starts_with_newline { + self.push_str("\n"); + } + self.push_str(&self.block_indent.to_string(self.config)); + self.push_str(snippet); + } + self.last_pos = stmt.span().hi(); return; } diff --git a/tests/source/issue-4018.rs b/tests/source/issue-4018.rs new file mode 100644 index 00000000000..9a91dd9a306 --- /dev/null +++ b/tests/source/issue-4018.rs @@ -0,0 +1,13 @@ +fn main() { + ; + /* extra comment */ ; +} + +fn main() { + println!(""); + // comment 1 + // comment 2 + // comment 3 + // comment 4 + ; +} diff --git a/tests/target/issue-4018.rs b/tests/target/issue-4018.rs new file mode 100644 index 00000000000..cef3be06148 --- /dev/null +++ b/tests/target/issue-4018.rs @@ -0,0 +1,11 @@ +fn main() { + /* extra comment */ +} + +fn main() { + println!(""); + // comment 1 + // comment 2 + // comment 3 + // comment 4 +} -- cgit 1.4.1-3-g733a5 From fa9d97499eabdb9f0d88d9389ba37da908136d81 Mon Sep 17 00:00:00 2001 From: Michael Müller Date: Sat, 24 Oct 2020 18:14:52 +0200 Subject: Fix overriding license header bug (#4488) * Override header to None when path len = 0 * Add regression test * Ensure nightly --- src/config/config_type.rs | 2 ++ src/config/mod.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 2eff7561392..d8fd8f78b38 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -299,6 +299,8 @@ macro_rules! create_config { Err(msg) => eprintln!("Warning for license template file {:?}: {}", lt_path, msg), } + } else { + self.license_template = None; } } } diff --git a/src/config/mod.rs b/src/config/mod.rs index bb86a379eb1..9abc9f9c331 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -491,6 +491,18 @@ mod test { assert!(config.license_template.is_some()); } + #[test] + fn test_override_existing_license_with_no_license() { + if !crate::is_nightly_channel!() { + return; + } + let toml = r#"license_template_path = "tests/license-template/lt.txt""#; + let mut config = Config::from_toml(toml, Path::new("")).unwrap(); + assert!(config.license_template.is_some()); + config.override_value("license_template_path", ""); + assert!(config.license_template.is_none()); + } + #[test] fn test_dump_default_config() { let default_config = format!( -- cgit 1.4.1-3-g733a5 From e131797b62fd52f48fb59296c4c700a97250dee4 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 27 Oct 2020 20:58:52 -0500 Subject: deps: bump rustc-ap to v686 --- Cargo.lock | 158 ++++++++++++++++++++-------------------------------------- Cargo.toml | 18 +++---- src/macros.rs | 6 ++- 3 files changed, 66 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ea03d6dbede..df5d17c6b32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,15 +576,6 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - [[package]] name = "lock_api" version = "0.4.1" @@ -616,14 +607,13 @@ dependencies = [ [[package]] name = "measureme" -version = "0.7.1" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef709d3257013bba7cff14fc504e07e80631d3fe0f6d38ce63b8f6510ccb932" +checksum = "22bf8d885d073610aee20e7fa205c4341ed32a761dbde96da5fd96301a8d3e82" dependencies = [ - "byteorder", - "memmap", - "parking_lot 0.9.0", + "parking_lot", "rustc-hash", + "smallvec", ] [[package]] @@ -632,16 +622,6 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "memoffset" version = "0.5.1" @@ -681,17 +661,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.6.2", - "rustc_version", -] - [[package]] name = "parking_lot" version = "0.11.0" @@ -699,23 +668,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" dependencies = [ "instant", - "lock_api 0.4.1", - "parking_lot_core 0.8.0", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if", - "cloudabi 0.0.3", - "libc", - "redox_syscall", - "rustc_version", - "smallvec 0.6.10", - "winapi", + "lock_api", + "parking_lot_core", ] [[package]] @@ -729,7 +683,7 @@ dependencies = [ "instant", "libc", "redox_syscall", - "smallvec 1.4.2", + "smallvec", "winapi", ] @@ -935,18 +889,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77be159a7d411e02ddf51a97cc2f98e88b93bf2856ac203dea737b8041ed23c" +checksum = "477085eefed2f12085c68577cc3827c8c39a31a4a750978aacb9af10f7903174" dependencies = [ - "smallvec 1.4.2", + "smallvec", ] [[package]] name = "rustc-ap-rustc_ast" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584ac06879fc46441feb444b6b6f55bf71489e3dc10a6a94222513f118468526" +checksum = "4d4ad5ec25f6b3d122354595be0d1b513f37fca3299d9b448b1db28f4a9e4b12" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -955,15 +909,15 @@ dependencies = [ "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", - "smallvec 1.4.2", + "smallvec", "tracing", ] [[package]] name = "rustc-ap-rustc_ast_passes" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155c1e648133f0df2848d899564aade8bd58ce2c82b03727e8437ec2523f420b" +checksum = "0c6d8635298d7736decdb3c6e92e784d3eccde557462a9c10ac11a34fec3d756" dependencies = [ "itertools 0.9.0", "rustc-ap-rustc_ast", @@ -980,9 +934,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3786235c5f1466ffd0f00cb1851e7cd8637f07d12efdeb206de3aa8cc285cf7" +checksum = "7a61bdb5252e1a95b7715038949e10f07ce770a436fcd497cdd9bc7255471de9" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -992,9 +946,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e02580ccbaf8d417c59d97a946b446b2a5332d68a0cf1eab74bb5dd33100e99" +checksum = "84520a16cb61bd31e9c27e87eca5d933a9c94ac84f25649bddcc19989275ab2a" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -1011,9 +965,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2a1c1a22021daef8354fb7504da4ed6df6e0aaf345af32c51e4ccf8afc07c0" +checksum = "b1cb2b6a38759cf7c0c1434c8b4cbfcab9cd24970d05f960f2ca01226ddb4d68" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -1024,7 +978,7 @@ dependencies = [ "jobserver", "libc", "measureme", - "parking_lot 0.11.0", + "parking_lot", "rustc-ap-rustc_graphviz", "rustc-ap-rustc_index", "rustc-ap-rustc_macros", @@ -1032,7 +986,7 @@ dependencies = [ "rustc-hash", "rustc-rayon", "rustc-rayon-core", - "smallvec 1.4.2", + "smallvec", "stable_deref_trait", "stacker", "tempfile", @@ -1042,9 +996,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81730d3ab322d96265163f9ab2ced6815d336a0441a85641d134c30d69d6660" +checksum = "46cfb19536426bf9252827a78552d635be207a4be74f4e92832aad82d7f2135c" dependencies = [ "annotate-snippets 0.8.0", "atty", @@ -1061,9 +1015,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325f40a43586a4fbd1d3837c3bb024db3729193146201d13f59b637d28e73ffe" +checksum = "6273e60042a0ef31f6cfe783c519873993eb426f055be2bc058a48b6ca3934d0" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -1078,15 +1032,15 @@ dependencies = [ "rustc-ap-rustc_serialize", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.4.2", + "smallvec", "tracing", ] [[package]] name = "rustc-ap-rustc_feature" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53e214c56bd3db863bf87e23a68cc9c7b2ccf1796dc63b5c795f75e1457654b" +checksum = "2936e8346157e2848305e509f38aa3ed4e97697975ef68027587f5db6a38703f" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -1094,21 +1048,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9783efc336cdb51ca8ed281040bf72bcb178a2a29867aade35893e4335f7ac01" +checksum = "9b4c3ae17776b5a5aa441ca510a650f75805e1f5569edd231caa8378552195a4" [[package]] name = "rustc-ap-rustc_graphviz" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb71e52620bcba8695271b90cb1d294ed16f1dcc81e85327e6dc67e6b5c3ef1d" +checksum = "5611bf0ac0ac49c2a22c959c7d8b17f85f69959293f0e8c4f753eca832fe7ad0" [[package]] name = "rustc-ap-rustc_index" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e73d13c4839873924d0c04fb885a4e3980b5c8416f8a96f925a8e5a4eb9c8e" +checksum = "ca67cf37c427057192e451c7f912e94ae9a8ca5ad69fd481c011fad3f86982cb" dependencies = [ "arrayvec 0.5.1", "rustc-ap-rustc_macros", @@ -1117,18 +1071,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5fb086575a381760a993126795222a49f3bab9faeb91dc67268dd19eab5c13" +checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_macros" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb3c133f618b5296c2ba57f05ee7b4c3fbec09d2779922083c2d16c5674f57c" +checksum = "61ec6d623853449acd3c65050d249d3674edab5f6e4d9f074c7bac183269f9c8" dependencies = [ "proc-macro2", "quote", @@ -1138,9 +1092,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cc8e42993c1ff89f56e2e00240a186c6eaaad6839a271ee3d534240a624ea5a" +checksum = "ca524bafce4b04d2b49fee2d40b4b26c3ebab9f1a4f731fdf561f00617862f02" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -1151,26 +1105,26 @@ dependencies = [ "rustc-ap-rustc_lexer", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "smallvec 1.4.2", + "smallvec", "tracing", "unicode-normalization", ] [[package]] name = "rustc-ap-rustc_serialize" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb88c78d4551e0243518d05ea3ab16388af97ec839e60de71c39147154a0303" +checksum = "c67920561e58f98c4de864407c92b2dd05ace5d5e5301e17444f10f742c005b7" dependencies = [ "indexmap", - "smallvec 1.4.2", + "smallvec", ] [[package]] name = "rustc-ap-rustc_session" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1362a5e57049bc7d722b06f5a8886fbf169e3a892ac793aedd8529ef60a8750" +checksum = "0762fd855792e06ef639327237898e4e092ad68150e6a8e19aeb7dc06276ad7a" dependencies = [ "bitflags", "getopts", @@ -1189,9 +1143,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67a086e3f81d54cb9d83974b11961ca8c4111a0955173124314e1ae99a1c2ad" +checksum = "0bf3db7b4ca5d21c14c45475df155e5e020c9a3760346945a662c9a9053b49c8" dependencies = [ "cfg-if", "md-5", @@ -1208,9 +1162,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "684.0.0" +version = "686.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "574c6a3e4495dfc522918103bd2cc77148a4716a58583ebed1a764963769151f" +checksum = "3aa6560bb9742b276064d67ab9edb5766ecb303f8ae3854835ad3fad4b432188" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -1407,12 +1361,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "smallvec" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" - [[package]] name = "smallvec" version = "1.4.2" @@ -1644,7 +1592,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.4.2", + "smallvec", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 58801ae281b..855f321a918 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,36 +66,36 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "684.0.0" +version = "686.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "684.0.0" +version = "686.0.0" diff --git a/src/macros.rs b/src/macros.rs index 62cc5f9dcc5..c4e2b6ac748 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,7 +13,9 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{ + Cursor, LazyTokenStream, LazyTokenStreamInner, TokenStream, TokenTree, +}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::parser::Parser; @@ -1212,7 +1214,7 @@ pub(crate) fn convert_try_mac( kind: ast::ExprKind::Try(parser.parse_expr().ok()?), span: mac.span(), // incorrect span, but shouldn't matter too much attrs: ast::AttrVec::new(), - tokens: Some(ts), + tokens: Some(LazyTokenStream::new(LazyTokenStreamInner::Ready(ts))), }) } else { None -- cgit 1.4.1-3-g733a5 From 9faba4539b24ac2db69edd385774d085bb0fd120 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 29 Oct 2020 22:50:25 -0500 Subject: fix(parser): better unclosed delims handling --- src/syntux/parser.rs | 40 ++++++++++++++---------- src/test/mod.rs | 34 ++------------------ src/test/parser.rs | 50 ++++++++++++++++++++++++++++++ tests/parser/unclosed-delims/issue_4466.rs | 11 +++++++ 4 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 src/test/parser.rs create mode 100644 tests/parser/unclosed-delims/issue_4466.rs (limited to 'src') diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 711dfc80c2c..78de08b993e 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -23,7 +23,6 @@ pub(crate) struct Directory { /// A parser for Rust source code. pub(crate) struct Parser<'a> { parser: RawParser<'a>, - sess: &'a ParseSess, } /// A builder for the `Parser`. @@ -71,7 +70,7 @@ impl<'a> ParserBuilder<'a> { } }; - Ok(Parser { parser, sess }) + Ok(Parser { parser }) } fn parser( @@ -150,6 +149,25 @@ impl<'a> Parser<'a> { input: Input, directory_ownership: Option, sess: &'a ParseSess, + ) -> Result { + let krate = Parser::parse_crate_inner(config, input, directory_ownership, sess)?; + if !sess.has_errors() { + return Ok(krate); + } + + if sess.can_reset_errors() { + sess.reset_errors(); + return Ok(krate); + } + + Err(ParserError::ParseError) + } + + fn parse_crate_inner( + config: &'a Config, + input: Input, + directory_ownership: Option, + sess: &'a ParseSess, ) -> Result { let mut parser = ParserBuilder::default() .config(config) @@ -157,26 +175,14 @@ impl<'a> Parser<'a> { .directory_ownership(directory_ownership) .sess(sess) .build()?; - - parser.parse_crate_inner() + parser.parse_crate_mod() } - fn parse_crate_inner(&mut self) -> Result { + fn parse_crate_mod(&mut self) -> Result { let mut parser = AssertUnwindSafe(&mut self.parser); match catch_unwind(move || parser.parse_crate_mod()) { - Ok(Ok(krate)) => { - if !self.sess.has_errors() { - return Ok(krate); - } - - if self.sess.can_reset_errors() { - self.sess.reset_errors(); - return Ok(krate); - } - - Err(ParserError::ParseError) - } + Ok(Ok(k)) => Ok(k), Ok(Err(mut db)) => { db.emit(); Err(ParserError::ParseError) diff --git a/src/test/mod.rs b/src/test/mod.rs index 57b5f2a78cd..9b3ca717152 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -11,14 +11,12 @@ use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic}; use crate::formatting::{ReportedErrors, SourceFile}; -use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; -use crate::{ - is_nightly_channel, ErrorKind, FormatReport, FormatReportFormatterBuilder, Input, Session, -}; +use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session}; mod configuration_snippet; +mod parser; const DIFF_CONTEXT_SIZE: usize = 3; @@ -485,34 +483,6 @@ fn format_lines_errors_are_reported_with_tabs() { assert!(session.has_formatting_errors()); } -#[test] -fn parser_errors_in_submods_are_surfaced() { - // See also https://github.com/rust-lang/rustfmt/issues/4126 - let filename = "tests/parser/issue-4126/lib.rs"; - let input_file = PathBuf::from(filename); - let exp_mod_name = "invalid"; - let config = read_config(&input_file); - let mut session = Session::::new(config, None); - if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) = - session.format(Input::File(filename.into())) - { - assert_eq!(&module, exp_mod_name); - if let ModuleResolutionErrorKind::ParseError { - file: unparseable_file, - } = kind - { - assert_eq!( - unparseable_file, - PathBuf::from("tests/parser/issue-4126/invalid.rs"), - ); - } else { - panic!("Expected parser error"); - } - } else { - panic!("Expected ModuleResolution operation error"); - } -} - // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: Vec, opt_config: &Option) -> (Vec, u32, u32) { diff --git a/src/test/parser.rs b/src/test/parser.rs new file mode 100644 index 00000000000..75aed32e68b --- /dev/null +++ b/src/test/parser.rs @@ -0,0 +1,50 @@ +use std::io; +use std::path::PathBuf; + +use super::read_config; + +use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind}; +use crate::{ErrorKind, Input, Session}; + +#[test] +fn parser_errors_in_submods_are_surfaced() { + // See also https://github.com/rust-lang/rustfmt/issues/4126 + let filename = "tests/parser/issue-4126/lib.rs"; + let input_file = PathBuf::from(filename); + let exp_mod_name = "invalid"; + let config = read_config(&input_file); + let mut session = Session::::new(config, None); + if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) = + session.format(Input::File(filename.into())) + { + assert_eq!(&module, exp_mod_name); + if let ModuleResolutionErrorKind::ParseError { + file: unparseable_file, + } = kind + { + assert_eq!( + unparseable_file, + PathBuf::from("tests/parser/issue-4126/invalid.rs"), + ); + } else { + panic!("Expected parser error"); + } + } else { + panic!("Expected ModuleResolution operation error"); + } +} + +fn assert_parser_error(filename: &str) { + let file = PathBuf::from(filename); + let config = read_config(&file); + let mut session = Session::::new(config, None); + let _ = session.format(Input::File(filename.into())).unwrap(); + assert!(session.has_parsing_errors()); +} + +#[test] +fn crate_parsing_errors_on_unclosed_delims() { + // See also https://github.com/rust-lang/rustfmt/issues/4466 + let filename = "tests/parser/unclosed-delims/issue_4466.rs"; + assert_parser_error(filename); +} diff --git a/tests/parser/unclosed-delims/issue_4466.rs b/tests/parser/unclosed-delims/issue_4466.rs new file mode 100644 index 00000000000..2c2c81c91d1 --- /dev/null +++ b/tests/parser/unclosed-delims/issue_4466.rs @@ -0,0 +1,11 @@ +fn main() { + if true { + println!("answer: {}", a_func(); + } else { + println!("don't think so."); + } +} + +fn a_func() -> i32 { + 42 +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 86a41bc80befae44ef8f59625c6225da9f955c83 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 26 Sep 2020 00:01:21 -0500 Subject: tests: add test for panic on new_parser_from_file --- src/test/mod.rs | 16 ++++++++++++++++ tests/parser/issue_4418.rs | 1 + 2 files changed, 17 insertions(+) create mode 100644 tests/parser/issue_4418.rs (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 9b3ca717152..7d2e8c18e9c 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -483,6 +483,22 @@ fn format_lines_errors_are_reported_with_tabs() { assert!(session.has_formatting_errors()); } +#[test] +fn parser_creation_errors_on_entry_new_parser_from_file_panic() { + // See also https://github.com/rust-lang/rustfmt/issues/4418 + let filename = "tests/parser/issue_4418.rs"; + let file = PathBuf::from(filename); + let (config, operation, _) = read_config(&file); + if let Err(OperationError::ParseError { input, is_panic }) = + format_file(&file, operation, config) + { + assert_eq!(input.as_path().unwrap(), file); + assert!(is_panic); + } else { + panic!("Expected ParseError operation error"); + } +} + // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: Vec, opt_config: &Option) -> (Vec, u32, u32) { diff --git a/tests/parser/issue_4418.rs b/tests/parser/issue_4418.rs new file mode 100644 index 00000000000..ff30235f076 --- /dev/null +++ b/tests/parser/issue_4418.rs @@ -0,0 +1 @@ +} \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 2b6226ce497ce9b3b9a0a3fe22a707fefcd8c2ee Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 26 Sep 2020 00:00:49 -0500 Subject: fix: resolve some parser related bugs --- src/syntux/parser.rs | 23 ++++++++++++++++------- src/syntux/session.rs | 11 +++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 78de08b993e..3a72fb6be88 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -65,8 +65,11 @@ impl<'a> ParserBuilder<'a> { let parser = match Self::parser(sess.inner(), input) { Ok(p) => p, Err(db) => { - sess.emit_diagnostics(db); - return Err(ParserError::ParserCreationError); + if let Some(diagnostics) = db { + sess.emit_diagnostics(diagnostics); + return Err(ParserError::ParserCreationError); + } + return Err(ParserError::ParsePanicError); } }; @@ -76,14 +79,18 @@ impl<'a> ParserBuilder<'a> { fn parser( sess: &'a rustc_session::parse::ParseSess, input: Input, - ) -> Result, Vec> { + ) -> Result, Option>> { match input { - Input::File(ref file) => Ok(new_parser_from_file(sess, file, None)), + Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || { + new_parser_from_file(sess, file, None) + })) + .map_err(|_| None), Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( sess, rustc_span::FileName::Custom("stdin".to_owned()), text, - ), + ) + .map_err(|db| Some(db)), } } } @@ -120,8 +127,10 @@ impl<'a> Parser<'a> { match parser.parse_mod(&TokenKind::Eof, ast::Unsafe::No) { Ok(result) => Some(result), Err(mut e) => { - e.cancel(); - sess.reset_errors(); + sess.emit_or_cancel_diagnostic(&mut e); + if sess.can_reset_errors() { + sess.reset_errors(); + } None } } diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 5045eab29dd..ef5ad62674e 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -230,6 +230,17 @@ impl ParseSess { } } + pub(crate) fn emit_or_cancel_diagnostic(&self, diagnostic: &mut Diagnostic) { + self.parse_sess.span_diagnostic.emit_diagnostic(diagnostic); + // The Handler will check whether the diagnostic should be emitted + // based on the user's rustfmt configuration and the originating file + // that caused the parser error. If the Handler determined it should skip + // emission then we need to ensure the diagnostic is cancelled. + if !diagnostic.cancelled() { + diagnostic.cancel(); + } + } + pub(super) fn can_reset_errors(&self) -> bool { *self.can_reset_errors.borrow() } -- cgit 1.4.1-3-g733a5 From 98975e1a64dbb8e00907a61cf642c02e76aa75a3 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 29 Oct 2020 22:59:45 -0500 Subject: tests: adjust some cherry-picekd tests --- src/test/mod.rs | 16 ---------------- src/test/parser.rs | 7 +++++++ 2 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/test/mod.rs b/src/test/mod.rs index 7d2e8c18e9c..9b3ca717152 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -483,22 +483,6 @@ fn format_lines_errors_are_reported_with_tabs() { assert!(session.has_formatting_errors()); } -#[test] -fn parser_creation_errors_on_entry_new_parser_from_file_panic() { - // See also https://github.com/rust-lang/rustfmt/issues/4418 - let filename = "tests/parser/issue_4418.rs"; - let file = PathBuf::from(filename); - let (config, operation, _) = read_config(&file); - if let Err(OperationError::ParseError { input, is_panic }) = - format_file(&file, operation, config) - { - assert_eq!(input.as_path().unwrap(), file); - assert!(is_panic); - } else { - panic!("Expected ParseError operation error"); - } -} - // For each file, run rustfmt and collect the output. // Returns the number of files checked and the number of failures. fn check_files(files: Vec, opt_config: &Option) -> (Vec, u32, u32) { diff --git a/src/test/parser.rs b/src/test/parser.rs index 75aed32e68b..ae4a4f94d92 100644 --- a/src/test/parser.rs +++ b/src/test/parser.rs @@ -42,6 +42,13 @@ fn assert_parser_error(filename: &str) { assert!(session.has_parsing_errors()); } +#[test] +fn parser_creation_errors_on_entry_new_parser_from_file_panic() { + // See also https://github.com/rust-lang/rustfmt/issues/4418 + let filename = "tests/parser/issue_4418.rs"; + assert_parser_error(filename); +} + #[test] fn crate_parsing_errors_on_unclosed_delims() { // See also https://github.com/rust-lang/rustfmt/issues/4466 -- cgit 1.4.1-3-g733a5 From 15854e5fd3acfefe0e31476a255f5ae3a8ef9ec3 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 30 Oct 2020 00:03:03 -0500 Subject: feat: v2 support for nested tuples w/o spaces --- src/chains.rs | 8 ++++++-- tests/source/tuple.rs | 11 +++++++++++ tests/source/tuple_v2.rs | 5 +++++ tests/target/tuple.rs | 11 +++++++++++ tests/target/tuple_v2.rs | 5 +++++ 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/source/tuple_v2.rs create mode 100644 tests/target/tuple_v2.rs (limited to 'src') diff --git a/src/chains.rs b/src/chains.rs index 8a0b416632b..ac14ec9e110 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -62,7 +62,7 @@ use rustc_ast::{ast, ptr}; use rustc_span::{symbol, BytePos, Span}; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; -use crate::config::IndentStyle; +use crate::config::{IndentStyle, Version}; use crate::expr::rewrite_call; use crate::lists::extract_pre_comment; use crate::macros::convert_try_mac; @@ -200,7 +200,11 @@ impl Rewrite for ChainItem { ChainItemKind::StructField(ident) => format!(".{}", rewrite_ident(context, ident)), ChainItemKind::TupleField(ident, nested) => format!( "{}.{}", - if nested { " " } else { "" }, + if nested && context.config.version() == Version::One { + " " + } else { + "" + }, rewrite_ident(context, ident) ), ChainItemKind::Await => ".await".to_owned(), diff --git a/tests/source/tuple.rs b/tests/source/tuple.rs index 6c3ec8f1115..9a0f979fbca 100644 --- a/tests/source/tuple.rs +++ b/tests/source/tuple.rs @@ -50,3 +50,14 @@ fn issue1725() { bench_antialiased_lines!(bench_draw_antialiased_line_segment_diagonal, (10, 10), (450, 450)); bench_antialiased_lines!(bench_draw_antialiased_line_segment_shallow, (10, 10), (450, 80)); } + +fn issue_4355() { + let _ = ((1,),).0.0; +} + +// https://github.com/rust-lang/rustfmt/issues/4410 +impl Drop for LockGuard { + fn drop(&mut self) { + LockMap::unlock(&self.0.0, &self.0.1); + } +} diff --git a/tests/source/tuple_v2.rs b/tests/source/tuple_v2.rs new file mode 100644 index 00000000000..9223033832b --- /dev/null +++ b/tests/source/tuple_v2.rs @@ -0,0 +1,5 @@ +// rustfmt-version: Two + +fn issue_4355() { + let _ = ((1,),).0 .0; +} diff --git a/tests/target/tuple.rs b/tests/target/tuple.rs index a22586284dc..68bb2f3bc28 100644 --- a/tests/target/tuple.rs +++ b/tests/target/tuple.rs @@ -87,3 +87,14 @@ fn issue1725() { (450, 80) ); } + +fn issue_4355() { + let _ = ((1,),).0 .0; +} + +// https://github.com/rust-lang/rustfmt/issues/4410 +impl Drop for LockGuard { + fn drop(&mut self) { + LockMap::unlock(&self.0 .0, &self.0 .1); + } +} diff --git a/tests/target/tuple_v2.rs b/tests/target/tuple_v2.rs new file mode 100644 index 00000000000..ba653291c2f --- /dev/null +++ b/tests/target/tuple_v2.rs @@ -0,0 +1,5 @@ +// rustfmt-version: Two + +fn issue_4355() { + let _ = ((1,),).0.0; +} -- cgit 1.4.1-3-g733a5 From 46ab14437e88aa9dd777596db378a8f30e062cda Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 27 Oct 2020 18:52:02 -0400 Subject: Don't flatten a block containing a single macro call We no longer flatten a block that looks like this: ```rust match val { pat => { macro_call!() } } ``` Currently, rust ignores trailing semicolons in macro expansion in expression position (see https://github.com/rust-lang/rust/issues/33953) If this is changed, flattening a block with a macro call may break the user's code - the trailing semicolon will no longer parse if the macro call occurs immediately on the right-hand side of the match arm (e.g. `pat => macro_call!()`) --- src/matches.rs | 14 +++++++++++++- tests/target/configs/match_arm_blocks/false.rs | 4 +++- tests/target/configs/match_arm_blocks/true.rs | 4 +++- tests/target/issue-2936.rs | 4 +++- tests/target/match.rs | 12 +++++++++--- 5 files changed, 31 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 7b691bf6100..3f02357a400 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -284,6 +284,15 @@ fn rewrite_match_arm( ) } +fn stmt_is_expr_mac(stmt: &ast::Stmt) -> bool { + if let ast::StmtKind::Expr(expr) = &stmt.kind { + if let ast::ExprKind::MacCall(_) = &expr.kind { + return true; + } + } + false +} + fn block_can_be_flattened<'a>( context: &RewriteContext<'_>, expr: &'a ast::Expr, @@ -292,7 +301,10 @@ fn block_can_be_flattened<'a>( ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() - && is_simple_block(context, block, Some(&expr.attrs)) => + && is_simple_block(context, block, Some(&expr.attrs)) + // Don't flatten a block containing a macro invocation, + // since it may expand to a statement + && !stmt_is_expr_mac(&block.stmts[0]) => { Some(&*block) } diff --git a/tests/target/configs/match_arm_blocks/false.rs b/tests/target/configs/match_arm_blocks/false.rs index 4d53a96a7b7..7a9834168c7 100644 --- a/tests/target/configs/match_arm_blocks/false.rs +++ b/tests/target/configs/match_arm_blocks/false.rs @@ -5,6 +5,8 @@ fn main() { match lorem { true => foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x), - false => println!("{}", sit), + false => { + println!("{}", sit) + } } } diff --git a/tests/target/configs/match_arm_blocks/true.rs b/tests/target/configs/match_arm_blocks/true.rs index d75ef03397a..eb9e34059c7 100644 --- a/tests/target/configs/match_arm_blocks/true.rs +++ b/tests/target/configs/match_arm_blocks/true.rs @@ -6,6 +6,8 @@ fn main() { true => { foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo(x) } - false => println!("{}", sit), + false => { + println!("{}", sit) + } } } diff --git a/tests/target/issue-2936.rs b/tests/target/issue-2936.rs index 3d5207597c4..1d6eb6d6052 100644 --- a/tests/target/issue-2936.rs +++ b/tests/target/issue-2936.rs @@ -11,7 +11,9 @@ impl Something for AStruct { let err: &CStr = match err.kind { ParseErrorKind::Custom(StyleParseErrorKind::MediaQueryExpectedFeatureName( .., - )) => cstr!("PEMQExpectedFeatureName"), + )) => { + cstr!("PEMQExpectedFeatureName") + } }; } }; diff --git a/tests/target/match.rs b/tests/target/match.rs index 92abda9752e..123c4c55f6a 100644 --- a/tests/target/match.rs +++ b/tests/target/match.rs @@ -166,9 +166,15 @@ fn issue355() { a => println!("a", b), b => vec![1, 2], c => vec![3; 4], - d => println!("a", b), - e => vec![1, 2], - f => vec![3; 4], + d => { + println!("a", b) + } + e => { + vec![1, 2] + } + f => { + vec![3; 4] + } h => println!("a", b), // h comment i => vec![1, 2], // i comment j => vec![3; 4], // j comment -- cgit 1.4.1-3-g733a5 From 1139e6e5ccbcaf22b853a0aa3dc5bebf862fabe6 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 5 Nov 2020 19:24:51 -0600 Subject: fix: remove comment from cherry-pick that v1.x doesn't handle --- src/matches.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/matches.rs b/src/matches.rs index 3f02357a400..a43aed09ef5 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -302,8 +302,6 @@ fn block_can_be_flattened<'a>( if !is_unsafe_block(block) && !context.inside_macro() && is_simple_block(context, block, Some(&expr.attrs)) - // Don't flatten a block containing a macro invocation, - // since it may expand to a statement && !stmt_is_expr_mac(&block.stmts[0]) => { Some(&*block) -- cgit 1.4.1-3-g733a5 From ae6b40e2f9292edd759a783de054bbbd5b873046 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 5 Nov 2020 19:30:56 -0600 Subject: fix: remove ignored depr attribute which now errors --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 2ba476466ab..c6a9654d4d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -273,7 +273,9 @@ impl FormatReport { } } -#[deprecated(note = "Use FormatReportFormatter instead")] +/// Deprecated - Use FormatReportFormatter instead +// https://github.com/rust-lang/rust/issues/78625 +// https://github.com/rust-lang/rust/issues/39935 impl fmt::Display for FormatReport { // Prints all the formatting errors. fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { -- cgit 1.4.1-3-g733a5 From a613c57521cbaee7b3bc0161f577208917f814ab Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 10 Nov 2020 20:07:42 -0600 Subject: feat: don't insert semi in macro_rules arm body --- src/comment.rs | 2 +- src/formatting.rs | 20 +++++++++++++++----- src/lib.rs | 24 ++++++++++++++---------- src/macros.rs | 4 ++-- src/rewrite.rs | 1 + src/utils.rs | 7 +++++++ src/visitor.rs | 3 +++ tests/target/macro_rules_semi.rs | 22 ++++++++++++++++++++++ 8 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 tests/target/macro_rules_semi.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 1da62d17681..9959ef7fd9e 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -659,7 +659,7 @@ impl<'a> CommentRewrite<'a> { config.set().wrap_comments(false); if config.format_code_in_doc_comments() { if let Some(s) = - crate::format_code_block(&self.code_block_buffer, &config) + crate::format_code_block(&self.code_block_buffer, &config, false) { trim_custom_comment_prefix(&s.snippet) } else { diff --git a/src/formatting.rs b/src/formatting.rs index 4da89e760ad..26ae494227d 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -25,7 +25,11 @@ pub(crate) type SourceFile = Vec; pub(crate) type FileRecord = (FileName, String); impl<'b, T: Write + 'b> Session<'b, T> { - pub(crate) fn format_input_inner(&mut self, input: Input) -> Result { + pub(crate) fn format_input_inner( + &mut self, + input: Input, + is_macro_def: bool, + ) -> Result { if !self.config.version_meets_requirement() { return Err(ErrorKind::VersionMismatch); } @@ -42,7 +46,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { } let config = &self.config.clone(); - let format_result = format_project(input, config, self); + let format_result = format_project(input, config, self, is_macro_def); format_result.map(|report| { self.errors.add(&report.internal.borrow().1); @@ -57,6 +61,7 @@ fn format_project( input: Input, config: &Config, handler: &mut T, + is_macro_def: bool, ) -> Result { let mut timer = Timer::start(); @@ -103,7 +108,7 @@ fn format_project( continue; } should_emit_verbose(input_is_stdin, config, || println!("Formatting {}", path)); - context.format_file(path, &module)?; + context.format_file(path, &module, is_macro_def)?; } timer = timer.done_formatting(); @@ -134,7 +139,12 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { } // Formats a single file/module. - fn format_file(&mut self, path: FileName, module: &Module<'_>) -> Result<(), ErrorKind> { + fn format_file( + &mut self, + path: FileName, + module: &Module<'_>, + is_macro_def: bool, + ) -> Result<(), ErrorKind> { let snippet_provider = self.parse_session.snippet_provider(module.as_ref().inner); let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, @@ -143,7 +153,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { self.report.clone(), ); visitor.skip_context.update_with_attrs(&self.krate.attrs); - + visitor.is_macro_def = is_macro_def; visitor.last_pos = snippet_provider.start_pos(); visitor.skip_empty_lines(snippet_provider.end_pos()); visitor.format_separate_mod(module, snippet_provider.end_pos()); diff --git a/src/lib.rs b/src/lib.rs index c6a9654d4d1..753840e065c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -286,7 +286,7 @@ impl fmt::Display for FormatReport { /// Format the given snippet. The snippet is expected to be *complete* code. /// When we cannot parse the given snippet, this function returns `None`. -fn format_snippet(snippet: &str, config: &Config) -> Option { +fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option { let mut config = config.clone(); panic::catch_unwind(|| { let mut out: Vec = Vec::with_capacity(snippet.len() * 2); @@ -297,7 +297,7 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { let (formatting_error, result) = { let input = Input::Text(snippet.into()); let mut session = Session::new(config, Some(&mut out)); - let result = session.format(input); + let result = session.format_input_inner(input, is_macro_def); ( session.errors.has_macro_format_failure || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() @@ -323,7 +323,11 @@ fn format_snippet(snippet: &str, config: &Config) -> Option { /// The code block may be incomplete (i.e., parser may be unable to parse it). /// To avoid panic in parser, we wrap the code block with a dummy function. /// The returned code block does **not** end with newline. -fn format_code_block(code_snippet: &str, config: &Config) -> Option { +fn format_code_block( + code_snippet: &str, + config: &Config, + is_macro_def: bool, +) -> Option { const FN_MAIN_PREFIX: &str = "fn main() {\n"; fn enclose_in_main_block(s: &str, config: &Config) -> String { @@ -356,7 +360,7 @@ fn format_code_block(code_snippet: &str, config: &Config) -> Option Session<'b, T> { /// The main entry point for Rustfmt. Formats the given input according to the /// given config. `out` is only necessary if required by the configuration. pub fn format(&mut self, input: Input) -> Result { - self.format_input_inner(input) + self.format_input_inner(input, false) } pub fn override_config(&mut self, mut config: Config, f: F) -> U @@ -550,15 +554,15 @@ mod unit_tests { // `format_snippet()` and `format_code_block()` should not panic // even when we cannot parse the given snippet. let snippet = "let"; - assert!(format_snippet(snippet, &Config::default()).is_none()); - assert!(format_code_block(snippet, &Config::default()).is_none()); + assert!(format_snippet(snippet, &Config::default(), false).is_none()); + assert!(format_code_block(snippet, &Config::default(), false).is_none()); } fn test_format_inner(formatter: F, input: &str, expected: &str) -> bool where - F: Fn(&str, &Config) -> Option, + F: Fn(&str, &Config, bool) -> Option, { - let output = formatter(input, &Config::default()); + let output = formatter(input, &Config::default(), false); output.is_some() && output.unwrap().snippet == expected } @@ -580,7 +584,7 @@ mod unit_tests { fn test_format_code_block_fail() { #[rustfmt::skip] let code_block = "this_line_is_100_characters_long_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(x, y, z);"; - assert!(format_code_block(code_block, &Config::default()).is_none()); + assert!(format_code_block(code_block, &Config::default(), false).is_none()); } #[test] diff --git a/src/macros.rs b/src/macros.rs index c4e2b6ac748..3bff059984f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1363,12 +1363,12 @@ impl MacroBranch { config.set().max_width(new_width); // First try to format as items, then as statements. - let new_body_snippet = match crate::format_snippet(&body_str, &config) { + let new_body_snippet = match crate::format_snippet(&body_str, &config, true) { Some(new_body) => new_body, None => { let new_width = new_width + config.tab_spaces(); config.set().max_width(new_width); - match crate::format_code_block(&body_str, &config) { + match crate::format_code_block(&body_str, &config, true) { Some(new_body) => new_body, None => return None, } diff --git a/src/rewrite.rs b/src/rewrite.rs index 86b2e9ded1c..c8abe70141b 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -39,6 +39,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) snippet_provider: &'a SnippetProvider, // Used for `format_snippet` pub(crate) macro_rewrite_failure: Cell, + pub(crate) is_macro_def: bool, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, pub(crate) skipped_range: Rc>>, diff --git a/src/utils.rs b/src/utils.rs index f8867914937..96d465608fa 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -279,6 +279,13 @@ pub(crate) fn contains_skip(attrs: &[Attribute]) -> bool { #[inline] pub(crate) fn semicolon_for_expr(context: &RewriteContext<'_>, expr: &ast::Expr) -> bool { + // Never try to insert semicolons on expressions when we're inside + // a macro definition - this can prevent the macro from compiling + // when used in expression position + if context.is_macro_def { + return false; + } + match expr.kind { ast::ExprKind::Ret(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Break(..) => { context.config.trailing_semicolon() diff --git a/src/visitor.rs b/src/visitor.rs index e7fa27aae0c..56d023d03a6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -86,6 +86,7 @@ pub(crate) struct FmtVisitor<'a> { pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, + pub(crate) is_macro_def: bool, } impl<'a> Drop for FmtVisitor<'a> { @@ -811,6 +812,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { snippet_provider, line_number: 0, skipped_range: Rc::new(RefCell::new(vec![])), + is_macro_def: false, macro_rewrite_failure: false, report, skip_context: Default::default(), @@ -1003,6 +1005,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { force_one_line_chain: Cell::new(false), snippet_provider: self.snippet_provider, macro_rewrite_failure: Cell::new(false), + is_macro_def: self.is_macro_def, report: self.report.clone(), skip_context: self.skip_context.clone(), skipped_range: self.skipped_range.clone(), diff --git a/tests/target/macro_rules_semi.rs b/tests/target/macro_rules_semi.rs new file mode 100644 index 00000000000..84e12d16e6e --- /dev/null +++ b/tests/target/macro_rules_semi.rs @@ -0,0 +1,22 @@ +macro_rules! expr { + (no_semi) => { + return true + }; + (semi) => { + return true; + }; +} + +fn foo() -> bool { + match true { + true => expr!(no_semi), + false if false => { + expr!(semi) + } + false => { + expr!(semi); + } + } +} + +fn main() {} -- cgit 1.4.1-3-g733a5 From ce13ff15c33da1e31931ba4bc692709be3a2cf30 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 15 Aug 2020 13:34:06 -0700 Subject: Correctly create artificial span for formatting closure body This commit partially reverts #3934, opting to create a span that covers the entire body of a closure when formatting a closure body with a block-formatting strategy, rather than having the block-formatting code determine if the visitor pointer should be rewound. The problem with rewinding the visitor pointer is it may be incorrect for other (i.e. non-artificial) AST nodes, as in the case of #4382. Closes #4382 --- src/closures.rs | 7 ++++++- src/expr.rs | 12 +----------- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index fe632323aa4..3cfaa4513eb 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -133,6 +133,7 @@ fn veto_block(e: &ast::Expr) -> bool { } // Rewrite closure with a single expression wrapping its body with block. +// || { #[attr] foo() } -> Block { #[attr] foo() } fn rewrite_closure_with_block( body: &ast::Expr, prefix: &str, @@ -154,8 +155,12 @@ fn rewrite_closure_with_block( }], id: ast::NodeId::root(), rules: ast::BlockCheckMode::Default, - span: body.span, tokens: None, + span: body + .attrs + .first() + .map(|attr| attr.span.to(body.span)) + .unwrap_or(body.span), }; let block = crate::expr::rewrite_block_with_visitor( context, diff --git a/src/expr.rs b/src/expr.rs index 6bc54ff8601..1ba879ccc1d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -528,17 +528,7 @@ pub(crate) fn rewrite_block_with_visitor( let open_pos = snippet.find_uncommented("{")?; visitor.last_pos = block.span.lo() + BytePos(open_pos as u32) } - (ast::BlockCheckMode::Default, None) => { - visitor.last_pos = block.span.lo(); - if let Some(attrs) = attrs { - if let Some(first) = attrs.first() { - let first_lo_span = first.span.lo(); - if first_lo_span < visitor.last_pos { - visitor.last_pos = first_lo_span; - } - } - } - } + (ast::BlockCheckMode::Default, None) => visitor.last_pos = block.span.lo(), } let inner_attrs = attrs.map(inner_attributes); -- cgit 1.4.1-3-g733a5 From faf97a67d678a42a8bc0f5b8e1ec808457acdfa2 Mon Sep 17 00:00:00 2001 From: WhizSid Date: Thu, 15 Oct 2020 07:38:58 +0530 Subject: Fixed 'Incorrect comment indent inside if/else' issue. (#4459) * Added test cases * Fixed if condition comment issue * Fixed extern C issue * Removed previous test case * Removed tmp file * honor the authors intent * Changed the file name to its original name * Removed extra whitespace --- src/items.rs | 26 +++++++++----- src/visitor.rs | 15 ++++++-- tests/source/issue-4120.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++ tests/target/issue-4120.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 12 deletions(-) create mode 100644 tests/source/issue-4120.rs create mode 100644 tests/target/issue-4120.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 1e2eac0c74b..01063b1f3bc 100644 --- a/src/items.rs +++ b/src/items.rs @@ -161,6 +161,14 @@ enum BodyElement<'a> { ForeignItem(&'a ast::ForeignItem), } +impl BodyElement<'_> { + pub(crate) fn span(&self) -> Span { + match self { + BodyElement::ForeignItem(fi) => fi.span(), + } + } +} + /// Represents a fn's signature. pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, @@ -268,19 +276,19 @@ impl<'a> FmtVisitor<'a> { self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1); self.block_indent = self.block_indent.block_indent(self.config); - if item.body.is_empty() { - self.format_missing_no_indent(item.span.hi() - BytePos(1)); - self.block_indent = self.block_indent.block_unindent(self.config); - let indent_str = self.block_indent.to_string(self.config); - self.push_str(&indent_str); - } else { + if !item.body.is_empty() { + // Advance to first item (statement or inner attribute) + // within the block. + self.last_pos = item.body[0].span().lo(); for item in &item.body { self.format_body_element(item); } - - self.block_indent = self.block_indent.block_unindent(self.config); - self.format_missing_with_indent(item.span.hi() - BytePos(1)); } + + self.format_missing_no_indent(item.span.hi() - BytePos(1)); + self.block_indent = self.block_indent.block_unindent(self.config); + let indent_str = self.block_indent.to_string(self.config); + self.push_str(&indent_str); } self.push_str("}"); diff --git a/src/visitor.rs b/src/visitor.rs index 56d023d03a6..a5f6ebfb67b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -5,7 +5,7 @@ use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit}; use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::attr::*; -use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::Version; use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; @@ -261,14 +261,23 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { trimmed.is_empty() || trimmed.chars().all(|c| c == ';') }; - for (kind, offset, sub_slice) in CommentCodeSlices::new(self.snippet(span)) { + let comment_snippet = self.snippet(span); + + let align_to_right = if unindent_comment && contains_comment(&comment_snippet) { + let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or(""); + last_line_width(first_lines) > last_line_width(&comment_snippet) + } else { + false + }; + + for (kind, offset, sub_slice) in CommentCodeSlices::new(comment_snippet) { let sub_slice = transform_missing_snippet(config, sub_slice); debug!("close_block: {:?} {:?} {:?}", kind, offset, sub_slice); match kind { CodeCharKind::Comment => { - if !unindented && unindent_comment { + if !unindented && unindent_comment && !align_to_right { unindented = true; self.block_indent = self.block_indent.block_unindent(config); } diff --git a/tests/source/issue-4120.rs b/tests/source/issue-4120.rs new file mode 100644 index 00000000000..c9ce838c51a --- /dev/null +++ b/tests/source/issue-4120.rs @@ -0,0 +1,85 @@ +fn main() { + let x = if true { + 1 + // In if + } else { + 0 + // In else + }; + + let x = if true { + 1 + /* In if */ + } else { + 0 + /* In else */ + }; + + let z = if true { + if true { + 1 + + // In if level 2 + } else { + 2 + } + } else { + 3 + }; + + let a = if true { + 1 + // In if + } else { + 0 + // In else + }; + + let a = if true { + 1 + + // In if + } else { + 0 + // In else + }; + + let b = if true { + 1 + + // In if + } else { + 0 + // In else + }; + + let c = if true { + 1 + + // In if + } else { + 0 + // In else + }; + for i in 0..2 { + println!("Something"); + // In for + } + + for i in 0..2 { + println!("Something"); + /* In for */ + } + + extern "C" { + fn first(); + + // In foreign mod + } + + extern "C" { + fn first(); + + /* In foreign mod */ + } +} diff --git a/tests/target/issue-4120.rs b/tests/target/issue-4120.rs new file mode 100644 index 00000000000..a7d461dcfdb --- /dev/null +++ b/tests/target/issue-4120.rs @@ -0,0 +1,85 @@ +fn main() { + let x = if true { + 1 + // In if + } else { + 0 + // In else + }; + + let x = if true { + 1 + /* In if */ + } else { + 0 + /* In else */ + }; + + let z = if true { + if true { + 1 + + // In if level 2 + } else { + 2 + } + } else { + 3 + }; + + let a = if true { + 1 + // In if + } else { + 0 + // In else + }; + + let a = if true { + 1 + + // In if + } else { + 0 + // In else + }; + + let b = if true { + 1 + + // In if + } else { + 0 + // In else + }; + + let c = if true { + 1 + + // In if + } else { + 0 + // In else + }; + for i in 0..2 { + println!("Something"); + // In for + } + + for i in 0..2 { + println!("Something"); + /* In for */ + } + + extern "C" { + fn first(); + + // In foreign mod + } + + extern "C" { + fn first(); + + /* In foreign mod */ + } +} -- cgit 1.4.1-3-g733a5 From 89f38304a7f9076fa00d48c7b654536af5f71912 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 16 Nov 2020 12:39:26 -0600 Subject: fix: don't drop leading comments in extern --- src/items.rs | 11 ----------- tests/source/issue_4528.rs | 8 ++++++++ tests/target/issue_4528.rs | 8 ++++++++ 3 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 tests/source/issue_4528.rs create mode 100644 tests/target/issue_4528.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 01063b1f3bc..d9f3361d8a3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -161,14 +161,6 @@ enum BodyElement<'a> { ForeignItem(&'a ast::ForeignItem), } -impl BodyElement<'_> { - pub(crate) fn span(&self) -> Span { - match self { - BodyElement::ForeignItem(fi) => fi.span(), - } - } -} - /// Represents a fn's signature. pub(crate) struct FnSig<'a> { decl: &'a ast::FnDecl, @@ -277,9 +269,6 @@ impl<'a> FmtVisitor<'a> { self.block_indent = self.block_indent.block_indent(self.config); if !item.body.is_empty() { - // Advance to first item (statement or inner attribute) - // within the block. - self.last_pos = item.body[0].span().lo(); for item in &item.body { self.format_body_element(item); } diff --git a/tests/source/issue_4528.rs b/tests/source/issue_4528.rs new file mode 100644 index 00000000000..85f6d8c0387 --- /dev/null +++ b/tests/source/issue_4528.rs @@ -0,0 +1,8 @@ +#![allow(clippy::no_effect)] + +extern "C" { + // N.B., mutability can be easily incorrect in FFI calls -- as + // in C, the default is mutable pointers. + fn ffi(c: *mut u8); + fn int_ffi(c: *mut i32); +} \ No newline at end of file diff --git a/tests/target/issue_4528.rs b/tests/target/issue_4528.rs new file mode 100644 index 00000000000..7828804b098 --- /dev/null +++ b/tests/target/issue_4528.rs @@ -0,0 +1,8 @@ +#![allow(clippy::no_effect)] + +extern "C" { + // N.B., mutability can be easily incorrect in FFI calls -- as + // in C, the default is mutable pointers. + fn ffi(c: *mut u8); + fn int_ffi(c: *mut i32); +} -- cgit 1.4.1-3-g733a5 From 073cc3891fa235e8968d42af4774d6c30a39032a Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 16 Nov 2020 18:24:03 -0500 Subject: Option to create groups for std, external crates, and other imports Backport of 17d90ca. --- Configurations.md | 50 ++++++++++ src/config/mod.rs | 3 + src/config/options.rs | 12 +++ src/reorder.rs | 105 ++++++++++++++++----- .../StdExternalCrate-merge_imports.rs | 17 ++++ .../group_imports/StdExternalCrate-nested.rs | 6 ++ .../group_imports/StdExternalCrate-no_reorder.rs | 17 ++++ .../configs/group_imports/StdExternalCrate.rs | 15 +++ .../StdExternalCrate-merge_imports.rs | 16 ++++ .../group_imports/StdExternalCrate-nested.rs | 7 ++ .../group_imports/StdExternalCrate-no_reorder.rs | 15 +++ .../configs/group_imports/StdExternalCrate.rs | 13 +++ 12 files changed, 254 insertions(+), 22 deletions(-) create mode 100644 tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs create mode 100644 tests/source/configs/group_imports/StdExternalCrate-nested.rs create mode 100644 tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs create mode 100644 tests/source/configs/group_imports/StdExternalCrate.rs create mode 100644 tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs create mode 100644 tests/target/configs/group_imports/StdExternalCrate-nested.rs create mode 100644 tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs create mode 100644 tests/target/configs/group_imports/StdExternalCrate.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index e7bbb4fa448..3b993f3fd48 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1889,6 +1889,56 @@ use dolor; use sit; ``` +## `group_imports` + +Controls the strategy for how imports are grouped together. + +- **Default value**: `Preserve` +- **Possible values**: `Preserve`, `StdExternalCrate` +- **Stable**: No + +#### `Preserve` (default): + +Preserve the source file's import groups. + +```rust +use super::update::convert_publish_payload; +use chrono::Utc; + +use alloc::alloc::Layout; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use crate::models::Event; +use core::f32; +``` + +#### `StdExternalCrate`: + +Discard existing import groups, and create three groups for: +1. `std`, `core` and `alloc`, +2. external crates, +3. `self`, `super` and `crate` imports. + +```rust +use alloc::alloc::Layout; +use core::f32; +use std::sync::Arc; + +use broker::database::PooledConnection; +use chrono::Utc; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; + +use super::schema::{Context, Payload}; +use super::update::convert_publish_payload; +use crate::models::Event; +``` ## `reorder_modules` diff --git a/src/config/mod.rs b/src/config/mod.rs index 9abc9f9c331..5b5aed4bc83 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -65,6 +65,8 @@ create_config! { imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; merge_imports: bool, false, false, "Merge imports"; + group_imports: GroupImportsTactic, GroupImportsTactic::Preserve, false, + "Controls the strategy for how imports are grouped together"; // Ordering reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically"; @@ -528,6 +530,7 @@ where_single_line = false imports_indent = "Block" imports_layout = "Mixed" merge_imports = false +group_imports = "Preserve" reorder_imports = true reorder_modules = true reorder_impl_items = false diff --git a/src/config/options.rs b/src/config/options.rs index 028ad2d3757..ae120a475f4 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -99,6 +99,18 @@ impl Density { } } +#[config_type] +/// Configuration for import groups, i.e. sets of imports separated by newlines. +pub enum GroupImportsTactic { + /// Keep groups as they are. + Preserve, + /// Discard existing groups, and create new groups for + /// 1. `std` / `core` / `alloc` imports + /// 2. other imports + /// 3. `self` / `crate` / `super` imports + StdExternalCrate, +} + #[config_type] pub enum ReportTactic { Always, diff --git a/src/reorder.rs b/src/reorder.rs index 2e73861a5a2..d6b6c1963bd 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -11,8 +11,8 @@ use std::cmp::{Ord, Ordering}; use rustc_ast::ast; use rustc_span::{symbol::sym, Span}; -use crate::config::Config; -use crate::imports::{merge_use_trees, UseTree}; +use crate::config::{Config, GroupImportsTactic}; +use crate::imports::{merge_use_trees, UseSegment, UseTree}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; use crate::rewrite::RewriteContext; @@ -74,9 +74,10 @@ fn rewrite_reorderable_item( } } -/// Rewrite a list of items with reordering. Every item in `items` must have -/// the same `ast::ItemKind`. -fn rewrite_reorderable_items( +/// Rewrite a list of items with reordering and/or regrouping. Every item +/// in `items` must have the same `ast::ItemKind`. Whether reordering, regrouping, +/// or both are done is determined from the `context`. +fn rewrite_reorderable_or_regroupable_items( context: &RewriteContext<'_>, reorderable_items: &[&ast::Item], shape: Shape, @@ -109,19 +110,35 @@ fn rewrite_reorderable_items( if context.config.merge_imports() { normalized_items = merge_use_trees(normalized_items); } - normalized_items.sort(); + + let mut regrouped_items = match context.config.group_imports() { + GroupImportsTactic::Preserve => vec![normalized_items], + GroupImportsTactic::StdExternalCrate => group_imports(normalized_items), + }; + + if context.config.reorder_imports() { + regrouped_items.iter_mut().for_each(|items| items.sort()) + } // 4 = "use ", 1 = ";" let nested_shape = shape.offset_left(4)?.sub_width(1)?; - let item_vec: Vec<_> = normalized_items + let item_vec: Vec<_> = regrouped_items .into_iter() - .map(|use_tree| ListItem { - item: use_tree.rewrite_top_level(context, nested_shape), - ..use_tree.list_item.unwrap_or_else(ListItem::empty) + .filter(|use_group| !use_group.is_empty()) + .map(|use_group| { + let item_vec: Vec<_> = use_group + .into_iter() + .map(|use_tree| ListItem { + item: use_tree.rewrite_top_level(context, nested_shape), + ..use_tree.list_item.unwrap_or_else(ListItem::empty) + }) + .collect(); + wrap_reorderable_items(context, &item_vec, nested_shape) }) - .collect(); + .collect::>>()?; - wrap_reorderable_items(context, &item_vec, nested_shape) + let join_string = format!("\n\n{}", shape.indent.to_string(context.config)); + Some(item_vec.join(&join_string)) } _ => { let list_items = itemize_list( @@ -150,6 +167,34 @@ fn contains_macro_use_attr(item: &ast::Item) -> bool { crate::attr::contains_name(&item.attrs, sym::macro_use) } +/// Divides imports into three groups, corresponding to standard, external +/// and local imports. Sorts each subgroup. +fn group_imports(uts: Vec) -> Vec> { + let mut std_imports = Vec::new(); + let mut external_imports = Vec::new(); + let mut local_imports = Vec::new(); + + for ut in uts.into_iter() { + if ut.path.is_empty() { + external_imports.push(ut); + continue; + } + match &ut.path[0] { + UseSegment::Ident(id, _) => match id.as_ref() { + "std" | "alloc" | "core" => std_imports.push(ut), + _ => external_imports.push(ut), + }, + UseSegment::Slf(_) | UseSegment::Super(_) | UseSegment::Crate(_) => { + local_imports.push(ut) + } + // These are probably illegal here + UseSegment::Glob | UseSegment::List(_) => external_imports.push(ut), + } + } + + vec![std_imports, external_imports, local_imports] +} + /// A simplified version of `ast::ItemKind`. #[derive(Debug, PartialEq, Eq, Copy, Clone)] enum ReorderableItemKind { @@ -187,21 +232,29 @@ impl ReorderableItemKind { } } - fn in_group(self) -> bool { + fn is_regroupable(self, config: &Config) -> bool { match self { ReorderableItemKind::ExternCrate | ReorderableItemKind::Mod - | ReorderableItemKind::Use => true, + | ReorderableItemKind::Other => false, + ReorderableItemKind::Use => config.group_imports() != GroupImportsTactic::Preserve, + } + } + + fn in_group(self, config: &Config) -> bool { + match self { + ReorderableItemKind::ExternCrate | ReorderableItemKind::Mod => true, + ReorderableItemKind::Use => config.group_imports() == GroupImportsTactic::Preserve, ReorderableItemKind::Other => false, } } } impl<'b, 'a: 'b> FmtVisitor<'a> { - /// Format items with the same item kind and reorder them. If `in_group` is - /// `true`, then the items separated by an empty line will not be reordered - /// together. - fn walk_reorderable_items( + /// Format items with the same item kind and reorder them, regroup them, or + /// both. If `in_group` is `true`, then the items separated by an empty line + /// will not be reordered together. + fn walk_reorderable_or_regroupable_items( &mut self, items: &[&ast::Item], item_kind: ReorderableItemKind, @@ -230,7 +283,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let lo = items.first().unwrap().span().lo(); let hi = items.last().unwrap().span().hi(); let span = mk_sp(lo, hi); - let rw = rewrite_reorderable_items(&self.get_context(), items, self.shape(), span); + let rw = rewrite_reorderable_or_regroupable_items( + &self.get_context(), + items, + self.shape(), + span, + ); self.push_rewrite(span, rw); } else { for item in items { @@ -249,9 +307,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // subsequent items that have the same item kind to be reordered within // `walk_reorderable_items`. Otherwise, just format the next item for output. let item_kind = ReorderableItemKind::from(items[0]); - if item_kind.is_reorderable(self.config) { - let visited_items_num = - self.walk_reorderable_items(items, item_kind, item_kind.in_group()); + if item_kind.is_reorderable(self.config) || item_kind.is_regroupable(self.config) { + let visited_items_num = self.walk_reorderable_or_regroupable_items( + items, + item_kind, + item_kind.in_group(self.config), + ); let (_, rest) = items.split_at(visited_items_num); items = rest; } else { diff --git a/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs b/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs new file mode 100644 index 00000000000..1a60126d2d1 --- /dev/null +++ b/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs @@ -0,0 +1,17 @@ +// rustfmt-group_imports: StdExternalCrate +// rustfmt-merge_imports: true +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; +use alloc::vec::Vec; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/source/configs/group_imports/StdExternalCrate-nested.rs b/tests/source/configs/group_imports/StdExternalCrate-nested.rs new file mode 100644 index 00000000000..08f4e07b704 --- /dev/null +++ b/tests/source/configs/group_imports/StdExternalCrate-nested.rs @@ -0,0 +1,6 @@ +// rustfmt-group_imports: StdExternalCrate +mod test { + use crate::foo::bar; + use std::path; + use crate::foo::bar2; +} diff --git a/tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs b/tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs new file mode 100644 index 00000000000..08c9a72ae61 --- /dev/null +++ b/tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs @@ -0,0 +1,17 @@ +// rustfmt-group_imports: StdExternalCrate +// rustfmt-reorder_imports: false + +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/source/configs/group_imports/StdExternalCrate.rs b/tests/source/configs/group_imports/StdExternalCrate.rs new file mode 100644 index 00000000000..d49c8941e6d --- /dev/null +++ b/tests/source/configs/group_imports/StdExternalCrate.rs @@ -0,0 +1,15 @@ +// rustfmt-group_imports: StdExternalCrate +use chrono::Utc; +use super::update::convert_publish_payload; + +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use alloc::alloc::Layout; + +use std::sync::Arc; + +use broker::database::PooledConnection; + +use super::schema::{Context, Payload}; +use core::f32; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs b/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs new file mode 100644 index 00000000000..a3d99eb907e --- /dev/null +++ b/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs @@ -0,0 +1,16 @@ +// rustfmt-group_imports: StdExternalCrate +// rustfmt-merge_imports: true +use alloc::{alloc::Layout, vec::Vec}; +use core::f32; +use std::sync::Arc; + +use broker::database::PooledConnection; +use chrono::Utc; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; + +use super::{ + schema::{Context, Payload}, + update::convert_publish_payload, +}; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/StdExternalCrate-nested.rs b/tests/target/configs/group_imports/StdExternalCrate-nested.rs new file mode 100644 index 00000000000..daf23375c0e --- /dev/null +++ b/tests/target/configs/group_imports/StdExternalCrate-nested.rs @@ -0,0 +1,7 @@ +// rustfmt-group_imports: StdExternalCrate +mod test { + use std::path; + + use crate::foo::bar; + use crate::foo::bar2; +} diff --git a/tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs b/tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs new file mode 100644 index 00000000000..76d3d6ccb95 --- /dev/null +++ b/tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs @@ -0,0 +1,15 @@ +// rustfmt-group_imports: StdExternalCrate +// rustfmt-reorder_imports: false + +use alloc::alloc::Layout; +use std::sync::Arc; +use core::f32; + +use chrono::Utc; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; +use broker::database::PooledConnection; + +use super::update::convert_publish_payload; +use super::schema::{Context, Payload}; +use crate::models::Event; diff --git a/tests/target/configs/group_imports/StdExternalCrate.rs b/tests/target/configs/group_imports/StdExternalCrate.rs new file mode 100644 index 00000000000..08025796898 --- /dev/null +++ b/tests/target/configs/group_imports/StdExternalCrate.rs @@ -0,0 +1,13 @@ +// rustfmt-group_imports: StdExternalCrate +use alloc::alloc::Layout; +use core::f32; +use std::sync::Arc; + +use broker::database::PooledConnection; +use chrono::Utc; +use juniper::{FieldError, FieldResult}; +use uuid::Uuid; + +use super::schema::{Context, Payload}; +use super::update::convert_publish_payload; +use crate::models::Event; -- cgit 1.4.1-3-g733a5 From 003786228d65135b9bae20a260caefc0248eb375 Mon Sep 17 00:00:00 2001 From: meiomorphism Date: Wed, 25 Nov 2020 04:31:10 -0800 Subject: fix: don't force a newline after an empty where clause Fixes #4547. --- src/items.rs | 3 ++- .../where_single_line/true-with-brace-style.rs | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/target/configs/where_single_line/true-with-brace-style.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index d9f3361d8a3..a11a02be2ae 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2418,7 +2418,8 @@ fn rewrite_fn_base( result.push_str(&where_clause_str); force_new_line_for_brace |= last_line_contains_single_line_comment(&result); - force_new_line_for_brace |= is_params_multi_lined && context.config.where_single_line(); + force_new_line_for_brace |= + is_params_multi_lined && context.config.where_single_line() && !where_clause_str.is_empty(); Some((result, force_new_line_for_brace)) } diff --git a/tests/target/configs/where_single_line/true-with-brace-style.rs b/tests/target/configs/where_single_line/true-with-brace-style.rs new file mode 100644 index 00000000000..ec7f79b689c --- /dev/null +++ b/tests/target/configs/where_single_line/true-with-brace-style.rs @@ -0,0 +1,22 @@ +// rustfmt-brace_style: SameLineWhere +// rustfmt-where_single_line: true + +fn lorem_multi_line_clauseless( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) -> T { + // body +} + +fn lorem_multi_line_clauseless( + a: Aaaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbbbb, + c: Ccccccccccccccccc, + d: Ddddddddddddddddddddddddd, + e: Eeeeeeeeeeeeeeeeeee, +) { + // body +} -- cgit 1.4.1-3-g733a5 From 581da523db1883247bd16f09a12ce9e480003dbd Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 20 Nov 2020 19:06:23 -0600 Subject: deps: bump rustc-ap to v687 --- Cargo.lock | 92 +++++++++++++++++++++++++++++++++++------------------------ Cargo.toml | 16 +++++------ src/macros.rs | 6 ++-- 3 files changed, 64 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 134fd08fbe5..d61421eb66d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -889,18 +889,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "477085eefed2f12085c68577cc3827c8c39a31a4a750978aacb9af10f7903174" +checksum = "d9548efd0207ba77afed061282bfc77dce9ffc4f416fa8cefcdea45412e7077b" dependencies = [ "smallvec", ] [[package]] name = "rustc-ap-rustc_ast" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4ad5ec25f6b3d122354595be0d1b513f37fca3299d9b448b1db28f4a9e4b12" +checksum = "253544514f2396fb2f496c447318ebe5c5b2f9063a8513a98dc5688fd06a42ef" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -915,9 +915,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_passes" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6d8635298d7736decdb3c6e92e784d3eccde557462a9c10ac11a34fec3d756" +checksum = "024fb10af71ff71c99f3a55e10ffdb2530012928296e1c348c656e982dbb4e64" dependencies = [ "itertools 0.9.0", "rustc-ap-rustc_ast", @@ -934,9 +934,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a61bdb5252e1a95b7715038949e10f07ce770a436fcd497cdd9bc7255471de9" +checksum = "c4dee265aca1ab9be8aace2da5a61eda9d78ff40058c83a0e5b6730bc9e761f9" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", @@ -946,9 +946,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_attr" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84520a16cb61bd31e9c27e87eca5d933a9c94ac84f25649bddcc19989275ab2a" +checksum = "d23bc65cb684abc717e4c098413d20e421af066507ee1b6f2b9321898d6ce777" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -965,9 +965,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1cb2b6a38759cf7c0c1434c8b4cbfcab9cd24970d05f960f2ca01226ddb4d68" +checksum = "4927c77def1139bab23e23c6b6ebfa701a2dcbaf13729edbe6d802f61c5621c4" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -996,13 +996,14 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46cfb19536426bf9252827a78552d635be207a4be74f4e92832aad82d7f2135c" +checksum = "bd9d2bfa60d9829dcb3db7e6885e22a21d6a76f7a5a46b06466aa14802a33c89" dependencies = [ "annotate-snippets 0.8.0", "atty", "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_lint_defs", "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", @@ -1015,9 +1016,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6273e60042a0ef31f6cfe783c519873993eb426f055be2bc058a48b6ca3934d0" +checksum = "e87c0700c0dca2ac330689bdcf38c74948df83abd1b36f23e4202995753b2857" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -1038,9 +1039,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2936e8346157e2848305e509f38aa3ed4e97697975ef68027587f5db6a38703f" +checksum = "aa77d05cc28c00ed1962a4d0798e377494cb0794e18b851b7fdaac7a6bf4a69c" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -1048,21 +1049,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4c3ae17776b5a5aa441ca510a650f75805e1f5569edd231caa8378552195a4" +checksum = "27cb1b1962503abdf9d1b384ed6c96312f5f5cc74c1765c13e38abc8cf87a0f3" [[package]] name = "rustc-ap-rustc_graphviz" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5611bf0ac0ac49c2a22c959c7d8b17f85f69959293f0e8c4f753eca832fe7ad0" +checksum = "2e3f43c9b6e397f1872340ff480b3f5061197816d63f5a6ca4f2c59f75a407eb" [[package]] name = "rustc-ap-rustc_index" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca67cf37c427057192e451c7f912e94ae9a8ca5ad69fd481c011fad3f86982cb" +checksum = "a2c695641f0e1f101511a489af5dab8f5bd7e491555928530bc74612a04d751d" dependencies = [ "arrayvec 0.5.1", "rustc-ap-rustc_macros", @@ -1071,18 +1072,32 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678" +checksum = "14dfb7a447eb4b54302c64cb28edd1c8a903876d58078ee3efed3e9e5388bebe" dependencies = [ "unicode-xid", ] +[[package]] +name = "rustc-ap-rustc_lint_defs" +version = "687.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59c169f74b94427a52ea2f13e2b141186dea96b2e02de22650728392b13bdb5a" +dependencies = [ + "rustc-ap-rustc_ast", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "tracing", +] + [[package]] name = "rustc-ap-rustc_macros" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ec6d623853449acd3c65050d249d3674edab5f6e4d9f074c7bac183269f9c8" +checksum = "7184879bb46b49e5477c53974a9fdd059d640232b265e2d09d77ad1999794f44" dependencies = [ "proc-macro2", "quote", @@ -1092,9 +1107,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca524bafce4b04d2b49fee2d40b4b26c3ebab9f1a4f731fdf561f00617862f02" +checksum = "202817bd5ed002b34276948c990025e9257ff121cd550fdac4a111732539c6a9" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -1112,9 +1127,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_serialize" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c67920561e58f98c4de864407c92b2dd05ace5d5e5301e17444f10f742c005b7" +checksum = "5d62c5c9e6757d4ebf4f02789aebe79c75520b9692fa852c9d2d6fa30cb68cb3" dependencies = [ "indexmap", "smallvec", @@ -1122,9 +1137,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0762fd855792e06ef639327237898e4e092ad68150e6a8e19aeb7dc06276ad7a" +checksum = "b8faa9b0da728e081df58c344e2a4103148184680c25e8889c4d31954fa63514" dependencies = [ "bitflags", "getopts", @@ -1134,6 +1149,7 @@ dependencies = [ "rustc-ap-rustc_errors", "rustc-ap-rustc_feature", "rustc-ap-rustc_fs_util", + "rustc-ap-rustc_lint_defs", "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", @@ -1143,9 +1159,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf3db7b4ca5d21c14c45475df155e5e020c9a3760346945a662c9a9053b49c8" +checksum = "96519323a26751576fb739a6e6f65bf9a1dd1898f835bea288a7de27f31931a2" dependencies = [ "cfg-if", "md-5", @@ -1162,9 +1178,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "686.0.0" +version = "687.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aa6560bb9742b276064d67ab9edb5766ecb303f8ae3854835ad3fad4b432188" +checksum = "b22730b097a9330120046d78e2da2c6bed2bf220cc3e2751f4c619f0702912bc" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", diff --git a/Cargo.toml b/Cargo.toml index 7d21b8df418..63c188a1c88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,11 +66,11 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" @@ -78,24 +78,24 @@ version = "686.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "686.0.0" +version = "687.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "686.0.0" +version = "687.0.0" diff --git a/src/macros.rs b/src/macros.rs index 3bff059984f..e5a28751988 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,9 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{ - Cursor, LazyTokenStream, LazyTokenStreamInner, TokenStream, TokenTree, -}; +use rustc_ast::tokenstream::{Cursor, LazyTokenStream, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::parser::Parser; @@ -1214,7 +1212,7 @@ pub(crate) fn convert_try_mac( kind: ast::ExprKind::Try(parser.parse_expr().ok()?), span: mac.span(), // incorrect span, but shouldn't matter too much attrs: ast::AttrVec::new(), - tokens: Some(LazyTokenStream::new(LazyTokenStreamInner::Ready(ts))), + tokens: Some(LazyTokenStream::new(ts)), }) } else { None -- cgit 1.4.1-3-g733a5 From 5b216029b5f8512934d279967a47a74732ca31a8 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 28 Nov 2020 14:58:10 -0600 Subject: deps: minor rustc_ast changes for v691 --- src/modules/visitor.rs | 2 +- src/skip.rs | 2 +- src/visitor.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 42d5351080d..d5acf3f1cbc 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -30,7 +30,7 @@ impl<'a> CfgIfVisitor<'a> { } impl<'a, 'ast: 'a> Visitor<'ast> for CfgIfVisitor<'a> { - fn visit_mac(&mut self, mac: &'ast ast::MacCall) { + fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) { match self.visit_mac_inner(mac) { Ok(()) => (), Err(e) => debug!("{}", e), diff --git a/src/skip.rs b/src/skip.rs index fd48e67ee73..6c500635a95 100644 --- a/src/skip.rs +++ b/src/skip.rs @@ -58,7 +58,7 @@ fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec { for attr in attrs { // rustc_ast::ast::Path is implemented partialEq // but it is designed for segments.len() == 1 - if let ast::AttrKind::Normal(attr_item) = &attr.kind { + if let ast::AttrKind::Normal(attr_item, _) = &attr.kind { if pprust::path_to_string(&attr_item.path) != path { continue; } diff --git a/src/visitor.rs b/src/visitor.rs index a5f6ebfb67b..ecf72833195 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -851,7 +851,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } else { match &attr.kind { - ast::AttrKind::Normal(ref attribute_item) + ast::AttrKind::Normal(ref attribute_item, _) if self.is_unknown_rustfmt_attr(&attribute_item.path.segments) => { let file_name = self.parse_sess.span_to_filename(attr.span); -- cgit 1.4.1-3-g733a5 From 4f32ce8434630ebb6e116bbb014f4a79a8af0dea Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Nov 2020 21:09:33 -0600 Subject: feat: support struct/slice destructuring --- src/expr.rs | 46 ++++++++++++++++++++++++++++------------------ tests/source/structs.rs | 11 +++++++++++ tests/target/structs.rs | 14 ++++++++++++++ 3 files changed, 53 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1ba879ccc1d..38543b70ae3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -106,11 +106,11 @@ pub(crate) fn format_expr( }) } ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( + ast::ExprKind::Struct(ref path, ref fields, ref struct_rest) => rewrite_struct_lit( context, path, fields, - base.as_ref().map(|e| &**e), + struct_rest, &expr.attrs, expr.span, shape, @@ -1510,19 +1510,15 @@ fn rewrite_index( } } -fn struct_lit_can_be_aligned(fields: &[ast::Field], base: Option<&ast::Expr>) -> bool { - if base.is_some() { - return false; - } - - fields.iter().all(|field| !field.is_shorthand) +fn struct_lit_can_be_aligned(fields: &[ast::Field], has_base: bool) -> bool { + !has_base && fields.iter().all(|field| !field.is_shorthand) } fn rewrite_struct_lit<'a>( context: &RewriteContext<'_>, path: &ast::Path, fields: &'a [ast::Field], - base: Option<&'a ast::Expr>, + struct_rest: &ast::StructRest, attrs: &[ast::Attribute], span: Span, shape: Shape, @@ -1532,22 +1528,29 @@ fn rewrite_struct_lit<'a>( enum StructLitField<'a> { Regular(&'a ast::Field), Base(&'a ast::Expr), + Rest(&'a Span), } // 2 = " {".len() let path_shape = shape.sub_width(2)?; let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - if fields.is_empty() && base.is_none() { - return Some(format!("{} {{}}", path_str)); - } + + let has_base = match struct_rest { + ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)), + ast::StructRest::Rest(_) if fields.is_empty() => { + return Some(format!("{} {{ .. }}", path_str)); + } + ast::StructRest::Base(_) => true, + _ => false, + }; // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, base) + let fields_str = if struct_lit_can_be_aligned(fields, has_base) && context.config.struct_field_align_threshold() > 0 { rewrite_with_alignment( @@ -1558,10 +1561,14 @@ fn rewrite_struct_lit<'a>( one_line_width, )? } else { - let field_iter = fields - .iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + let field_iter = fields.iter().map(StructLitField::Regular).chain( + match struct_rest { + ast::StructRest::Base(expr) => Some(StructLitField::Base(&**expr)), + ast::StructRest::Rest(span) => Some(StructLitField::Rest(span)), + ast::StructRest::None => None, + } + .into_iter(), + ); let span_lo = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => field.span().lo(), @@ -1571,10 +1578,12 @@ fn rewrite_struct_lit<'a>( let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) } + StructLitField::Rest(span) => span.lo(), }; let span_hi = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => field.span().hi(), StructLitField::Base(expr) => expr.span.hi(), + StructLitField::Rest(span) => span.hi(), }; let rewrite = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => { @@ -1586,6 +1595,7 @@ fn rewrite_struct_lit<'a>( expr.rewrite(context, v_shape.offset_left(2)?) .map(|s| format!("..{}", s)) } + StructLitField::Rest(_) => Some("..".to_owned()), }; let items = itemize_list( @@ -1612,7 +1622,7 @@ fn rewrite_struct_lit<'a>( nested_shape, tactic, context, - force_no_trailing_comma || base.is_some() || !context.use_block_indent(), + force_no_trailing_comma || has_base || !context.use_block_indent(), ); write_list(&item_vec, &fmt)? diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 711264a11d3..537151b276a 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -15,6 +15,17 @@ pub struct Foo { pub i: TypeForPublicField } +// Destructuring +fn foo() { + S { x: 5, + ..}; + Struct {..} = Struct { a: 1, b: 4 }; + Struct { a, .. } = Struct { a: 1, b: 2, c: 3}; + TupleStruct(a,.., b) = TupleStruct(1, 2); + TupleStruct( ..) = TupleStruct(3, 4); + TupleStruct(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, .., bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) = TupleStruct(1, 2); +} + // #1095 struct S { t: T, diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 0495ab3c81c..4948e37a5a3 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -15,6 +15,20 @@ pub struct Foo { pub i: TypeForPublicField, } +// Destructuring +fn foo() { + S { x: 5, .. }; + Struct { .. } = Struct { a: 1, b: 4 }; + Struct { a, .. } = Struct { a: 1, b: 2, c: 3 }; + TupleStruct(a, .., b) = TupleStruct(1, 2); + TupleStruct(..) = TupleStruct(3, 4); + TupleStruct( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + .., + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ) = TupleStruct(1, 2); +} + // #1095 struct S { t: T, -- cgit 1.4.1-3-g733a5 From 5c0673c371b4306e1e7fda8455af6fa3085a4627 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Nov 2020 21:30:27 -0600 Subject: refactor: update cfg_if attr parsing --- src/syntux/parser.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 3a72fb6be88..c8d427478dc 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -227,8 +227,16 @@ impl<'a> Parser<'a> { if !parser.eat_keyword(kw::If) { return Err("Expected `if`"); } + // Inner attributes are not actually syntactically permitted here, but we don't + // care about inner vs outer attributes in this position. Our purpose with this + // special case parsing of cfg_if macros is to ensure we can correctly resolve + // imported modules that may have a custom `path` defined. + // + // As such, we just need to advance the parser past the attribute and up to + // to the opening brace. + // See also https://github.com/rust-lang/rust/pull/79433 parser - .parse_attribute(false) + .parse_attribute(rustc_parse::parser::attr::InnerAttrPolicy::Permitted) .map_err(|_| "Failed to parse attributes")?; } -- cgit 1.4.1-3-g733a5 From 4d9fa00fd58373f4ee19b6a45ab37e4601a8dd93 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 27 Nov 2020 21:18:39 -0600 Subject: feat: support underscore expressions --- src/expr.rs | 1 + src/utils.rs | 3 ++- tests/source/expr.rs | 10 ++++++++++ tests/target/expr.rs | 10 ++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 38543b70ae3..fe348bc6028 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -384,6 +384,7 @@ pub(crate) fn format_expr( } } ast::ExprKind::Await(_) => rewrite_chain(expr, context, shape), + ast::ExprKind::Underscore => Some("_".to_owned()), ast::ExprKind::Err => None, }; diff --git a/src/utils.rs b/src/utils.rs index 96d465608fa..bd419b2998b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -504,7 +504,8 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Ret(..) | ast::ExprKind::Tup(..) | ast::ExprKind::Type(..) - | ast::ExprKind::Yield(None) => false, + | ast::ExprKind::Yield(None) + | ast::ExprKind::Underscore => false, } } diff --git a/tests/source/expr.rs b/tests/source/expr.rs index 8a6e6f1aa2b..21f8a4a4366 100644 --- a/tests/source/expr.rs +++ b/tests/source/expr.rs @@ -567,3 +567,13 @@ fn foo() { } .await; } + +fn underscore() { + _= 1; + _; + [ _,a,_ ] = [1, 2, 3]; + (a, _) = (8, 9); + TupleStruct( _, a) = TupleStruct(2, 2); + + let _ : usize = foo(_, _); +} diff --git a/tests/target/expr.rs b/tests/target/expr.rs index 5d9e972066c..84df802bc70 100644 --- a/tests/target/expr.rs +++ b/tests/target/expr.rs @@ -659,3 +659,13 @@ fn foo() { } .await; } + +fn underscore() { + _ = 1; + _; + [_, a, _] = [1, 2, 3]; + (a, _) = (8, 9); + TupleStruct(_, a) = TupleStruct(2, 2); + + let _: usize = foo(_, _); +} -- cgit 1.4.1-3-g733a5 From 48d30a4f7105c1ae2be50a0620237cd3c9ded978 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 28 Nov 2020 15:03:06 -0600 Subject: chore: run rustfmt against source --- src/expr.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index fe348bc6028..71446ce1ab0 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1536,7 +1536,6 @@ fn rewrite_struct_lit<'a>( let path_shape = shape.sub_width(2)?; let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - let has_base = match struct_rest { ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)), ast::StructRest::Rest(_) if fields.is_empty() => { -- cgit 1.4.1-3-g733a5 From 5ffccbb627c35d8d9c156d236e9599c0662f35dc Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Mon, 29 Jun 2020 19:36:31 -0700 Subject: Properly format function signature in extern blocks Closes #4288 And we get to drop a method, which I think is a win :) --- src/items.rs | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index a11a02be2ae..3c30de1a417 100644 --- a/src/items.rs +++ b/src/items.rs @@ -125,6 +125,7 @@ impl Rewrite for ast::Local { // FIXME convert to using rewrite style rather than visitor // FIXME format modules in this style #[allow(dead_code)] +#[derive(Debug)] struct Item<'a> { unsafety: ast::Unsafe, abi: Cow<'static, str>, @@ -153,6 +154,7 @@ impl<'a> Item<'a> { } } +#[derive(Debug)] enum BodyElement<'a> { // Stmt(&'a ast::Stmt), // Field(&'a ast::Field), @@ -174,26 +176,10 @@ pub(crate) struct FnSig<'a> { } impl<'a> FnSig<'a> { - pub(crate) fn new( - decl: &'a ast::FnDecl, - generics: &'a ast::Generics, - vis: ast::Visibility, - ) -> FnSig<'a> { - FnSig { - decl, - generics, - ext: ast::Extern::None, - is_async: Cow::Owned(ast::Async::No), - constness: ast::Const::No, - defaultness: ast::Defaultness::Final, - unsafety: ast::Unsafe::No, - visibility: vis, - } - } - pub(crate) fn from_method_sig( method_sig: &'a ast::FnSig, generics: &'a ast::Generics, + visibility: ast::Visibility, ) -> FnSig<'a> { FnSig { unsafety: method_sig.header.unsafety, @@ -203,7 +189,7 @@ impl<'a> FnSig<'a> { ext: method_sig.header.ext, decl: &*method_sig.decl, generics, - visibility: DEFAULT_VISIBILITY, + visibility, } } @@ -216,9 +202,8 @@ impl<'a> FnSig<'a> { match *fn_kind { visit::FnKind::Fn(fn_ctxt, _, fn_sig, vis, _) => match fn_ctxt { visit::FnCtxt::Assoc(..) => { - let mut fn_sig = FnSig::from_method_sig(fn_sig, generics); + let mut fn_sig = FnSig::from_method_sig(fn_sig, generics, vis.clone()); fn_sig.defaultness = defaultness; - fn_sig.visibility = vis.clone(); fn_sig } _ => FnSig { @@ -347,7 +332,7 @@ impl<'a> FmtVisitor<'a> { &context, indent, ident, - &FnSig::from_method_sig(sig, generics), + &FnSig::from_method_sig(sig, generics, DEFAULT_VISIBILITY), span, FnBraceStyle::None, )?; @@ -3062,7 +3047,7 @@ impl Rewrite for ast::ForeignItem { context, shape.indent, self.ident, - &FnSig::new(&fn_sig.decl, generics, self.vis.clone()), + &FnSig::from_method_sig(&fn_sig, generics, self.vis.clone()), span, FnBraceStyle::None, ) -- cgit 1.4.1-3-g733a5 From 3bf67c175dfa9b1bcb35f001da53b49c21e2179b Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Thu, 9 Jul 2020 19:56:46 -0700 Subject: Don't drop blocks on foreign functions A code like ```rust extern "C" { fn f() { fn g() {} } } ``` is incorrect and does not compile. Today rustfmt formats this in a way that is correct: ```rust extern "C" { fn f(); } ``` But this loses information, and doesn't have to be done because we know the content of the block if it is present. During development I don't think rustfmt should drop the block in this context. Closes #4313 --- src/items.rs | 18 +++++++++++++++++- src/visitor.rs | 2 +- tests/target/issue-4313.rs | 5 +++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-4313.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 3c30de1a417..039dd1e1ae0 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3043,7 +3043,23 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.kind { - ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base( + ast::ForeignItemKind::Fn(defaultness, ref fn_sig, ref generics, Some(ref body)) => { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = shape.indent; + visitor.last_pos = self.span.lo(); + let inner_attrs = inner_attributes(&self.attrs); + let fn_ctxt = visit::FnCtxt::Foreign; + visitor.visit_fn( + visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)), + generics, + &fn_sig.decl, + self.span, + defaultness, + Some(&inner_attrs), + ); + Some(visitor.buffer.to_owned()) + } + ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, None) => rewrite_fn_base( context, shape.indent, self.ident, diff --git a/src/visitor.rs b/src/visitor.rs index ecf72833195..3b9b0a2f967 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -370,7 +370,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. - fn visit_fn( + pub(crate) fn visit_fn( &mut self, fk: visit::FnKind<'_>, generics: &ast::Generics, diff --git a/tests/target/issue-4313.rs b/tests/target/issue-4313.rs new file mode 100644 index 00000000000..c390ee6ba30 --- /dev/null +++ b/tests/target/issue-4313.rs @@ -0,0 +1,5 @@ +extern "C" { + fn f() { + fn g() {} + } +} -- cgit 1.4.1-3-g733a5 From c77c6a405d9584a8b3b2d7b18bd9153d19ddb6ff Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sun, 10 May 2020 06:54:46 -0500 Subject: Compare code block line indentation with config whitespace (#4166) Previously the indetation of a line was compared with the configured number of spaces per tab, which could cause lines that were formatted with hard tabs not to be recognized as indented ("\t".len() < " ".len()). Closes #4152 --- src/lib.rs | 4 ++-- tests/target/issue-4152.rs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/target/issue-4152.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 753840e065c..da83b285a21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -371,6 +371,7 @@ fn format_code_block( .rfind('}') .unwrap_or_else(|| formatted.snippet.len()); let mut is_indented = true; + let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); for (kind, ref line) in LineClasses::new(&formatted.snippet[FN_MAIN_PREFIX.len()..block_len]) { if !is_first { result.push('\n'); @@ -385,9 +386,8 @@ fn format_code_block( // are too long, or we have failed to format code block. We will be // conservative and just return `None` in this case. return None; - } else if line.len() > config.tab_spaces() { + } else if line.len() > indent_str.len() { // Make sure that the line has leading whitespaces. - let indent_str = Indent::from_width(config, config.tab_spaces()).to_string(config); if line.starts_with(indent_str.as_ref()) { let offset = if config.hard_tabs() { 1 diff --git a/tests/target/issue-4152.rs b/tests/target/issue-4152.rs new file mode 100644 index 00000000000..80f9ff5e304 --- /dev/null +++ b/tests/target/issue-4152.rs @@ -0,0 +1,18 @@ +// rustfmt-hard_tabs: true + +macro_rules! bit { + ($bool:expr) => { + if $bool { + 1; + 1 + } else { + 0; + 0 + } + }; +} +macro_rules! add_one { + ($vec:expr) => {{ + $vec.push(1); + }}; +} -- cgit 1.4.1-3-g733a5 From 3df383aa3cc803ef000796b9221b084ffb1bd68a Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Tue, 21 Apr 2020 22:57:54 -0700 Subject: fixes #4115, #4029, #3898 --- src/attr.rs | 184 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 91 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 48c0685d2c1..9f77941e551 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -63,15 +63,6 @@ fn is_derive(attr: &ast::Attribute) -> bool { attr.has_name(sym::derive) } -/// Returns the arguments of `#[derive(...)]`. -fn get_derive_spans<'a>(attr: &'a ast::Attribute) -> Option + 'a> { - attr.meta_item_list().map(|meta_item_list| { - meta_item_list - .into_iter() - .map(|nested_meta_item| nested_meta_item.span()) - }) -} - // The shape of the arguments to a function-like attribute. fn argument_shape( left: usize, @@ -100,36 +91,104 @@ fn argument_shape( } fn format_derive( - derive_args: &[Span], - prefix: &str, + derives: &[ast::Attribute], shape: Shape, context: &RewriteContext<'_>, ) -> Option { - let mut result = String::with_capacity(128); - result.push_str(prefix); - result.push_str("[derive("); - - let argument_shape = argument_shape(10 + prefix.len(), 2, false, shape, context)?; - let item_str = format_arg_list( - derive_args.iter(), - |_| DUMMY_SP.lo(), - |_| DUMMY_SP.hi(), - |sp| Some(context.snippet(**sp).to_owned()), - DUMMY_SP, - context, - argument_shape, - // 10 = "[derive()]", 3 = "()" and "]" - shape.offset_left(10 + prefix.len())?.sub_width(3)?, - None, + // Collect all items from all attributes + let all_items = derives + .iter() + .map(|attr| { + // Parse the derive items and extract the span for each item; if any + // attribute is not parseable, none of the attributes will be + // reformatted. + let item_spans = attr.meta_item_list().map(|meta_item_list| { + meta_item_list + .into_iter() + .map(|nested_meta_item| nested_meta_item.span()) + })?; + + let items = itemize_list( + context.snippet_provider, + item_spans, + ")", + ",", + |span| span.lo(), + |span| span.hi(), + |span| Some(context.snippet(*span).to_owned()), + attr.span.lo(), + attr.span.hi(), + false, + ); + + Some(items) + }) + // Fail if any attribute failed. + .collect::>>()? + // Collect the results into a single, flat, Vec. + .into_iter() + .flatten() + .collect::>(); + + // Collect formatting parameters. + let prefix = attr_prefix(&derives[0]); + let argument_shape = argument_shape( + "[derive()]".len() + prefix.len(), + ")]".len(), false, + shape, + context, )?; + let one_line_shape = shape + .offset_left("[derive()]".len() + prefix.len())? + .sub_width("()]".len())?; + let one_line_budget = one_line_shape.width; - result.push_str(&item_str); - if item_str.starts_with('\n') { - result.push(','); + let tactic = definitive_tactic( + &all_items, + ListTactic::HorizontalVertical, + Separator::Comma, + argument_shape.width, + ); + let trailing_separator = match context.config.indent_style() { + // We always add the trailing comma and remove it if it is not needed. + IndentStyle::Block => SeparatorTactic::Always, + IndentStyle::Visual => SeparatorTactic::Never, + }; + + // Format the collection of items. + let fmt = ListFormatting::new(argument_shape, context.config) + .tactic(tactic) + .trailing_separator(trailing_separator) + .ends_with_newline(false); + let item_str = write_list(&all_items, &fmt)?; + + debug!("item_str: '{}'", item_str); + + // Determine if the result will be nested, i.e. if we're using the block + // indent style and either the items are on multiple lines or we've exceeded + // our budget to fit on a single line. + let nested = context.config.indent_style() == IndentStyle::Block + && (item_str.contains('\n') || item_str.len() > one_line_budget); + + // Format the final result. + let mut result = String::with_capacity(128); + result.push_str(prefix); + result.push_str("[derive("); + if nested { + let nested_indent = argument_shape.indent.to_string_with_newline(context.config); + result.push_str(&nested_indent); + result.push_str(&item_str); result.push_str(&shape.indent.to_string_with_newline(context.config)); + } else if let SeparatorTactic::Always = context.config.trailing_comma() { + // Retain the trailing comma. + result.push_str(&item_str); + } else { + // Remove the trailing comma. + result.push_str(&item_str[..item_str.len() - 1]); } result.push_str(")]"); + Some(result) } @@ -255,7 +314,7 @@ impl Rewrite for ast::MetaItem { // width. Since a literal is basically unformattable unless it // is a string literal (and only if `format_strings` is set), // we might be better off ignoring the fact that the attribute - // is longer than the max width and contiue on formatting. + // is longer than the max width and continue on formatting. // See #2479 for example. let value = rewrite_literal(context, literal, lit_shape) .unwrap_or_else(|| context.snippet(literal.span).to_owned()); @@ -265,61 +324,6 @@ impl Rewrite for ast::MetaItem { } } -fn format_arg_list( - list: I, - get_lo: F1, - get_hi: F2, - get_item_string: F3, - span: Span, - context: &RewriteContext<'_>, - shape: Shape, - one_line_shape: Shape, - one_line_limit: Option, - combine: bool, -) -> Option -where - I: Iterator, - F1: Fn(&T) -> BytePos, - F2: Fn(&T) -> BytePos, - F3: Fn(&T) -> Option, -{ - let items = itemize_list( - context.snippet_provider, - list, - ")", - ",", - get_lo, - get_hi, - get_item_string, - span.lo(), - span.hi(), - false, - ); - let item_vec = items.collect::>(); - let tactic = if let Some(limit) = one_line_limit { - ListTactic::LimitedHorizontalVertical(limit) - } else { - ListTactic::HorizontalVertical - }; - - let tactic = definitive_tactic(&item_vec, tactic, Separator::Comma, shape.width); - let fmt = ListFormatting::new(shape, context.config) - .tactic(tactic) - .ends_with_newline(false); - let item_str = write_list(&item_vec, &fmt)?; - - let one_line_budget = one_line_shape.width; - if context.config.indent_style() == IndentStyle::Visual - || combine - || (!item_str.contains('\n') && item_str.len() <= one_line_budget) - { - Some(item_str) - } else { - let nested_indent = shape.indent.to_string_with_newline(context.config); - Some(format!("{}{}", nested_indent, item_str)) - } -} - impl Rewrite for ast::Attribute { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let snippet = context.snippet(self.span); @@ -424,13 +428,7 @@ impl<'a> Rewrite for [ast::Attribute] { // Handle derives if we will merge them. if context.config.merge_derives() && is_derive(&attrs[0]) { let derives = take_while_with_pred(context, attrs, is_derive); - let derive_spans: Vec<_> = derives - .iter() - .filter_map(get_derive_spans) - .flatten() - .collect(); - let derive_str = - format_derive(&derive_spans, attr_prefix(&attrs[0]), shape, context)?; + let derive_str = format_derive(derives, shape, context)?; result.push_str(&derive_str); let missing_span = attrs -- cgit 1.4.1-3-g733a5 From fb7e604538bb45bf6119ca264c332c9aa634ef31 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 28 Nov 2020 18:03:48 -0600 Subject: tests: backport an additional test case --- src/attr.rs | 2 +- tests/target/issue_4545.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue_4545.rs (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 9f77941e551..dab9cabccdc 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -2,7 +2,7 @@ use rustc_ast::ast; use rustc_ast::attr::HasAttrs; -use rustc_span::{symbol::sym, BytePos, Span, Symbol, DUMMY_SP}; +use rustc_span::{symbol::sym, Span, Symbol}; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; diff --git a/tests/target/issue_4545.rs b/tests/target/issue_4545.rs new file mode 100644 index 00000000000..f87c8103657 --- /dev/null +++ b/tests/target/issue_4545.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Foo)] +enum Bar {} + +#[derive(Debug, , Default)] +struct Struct(i32); -- cgit 1.4.1-3-g733a5 From 5e7fb4553394e0d6439d0d2131dd9f65245d49a2 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sun, 7 Jun 2020 20:31:24 -0500 Subject: Pick up comments between visibility modifier and item name (#4239) * Pick up comments between visibility modifier and item name I don't think this hurts to fix. #2781, which surfaced this issue, has a number of comments relating to similar but slightly different issues (i.e. dropped comments in other places). I can mark #2781 as closed and then will open new issues for the comments that are not already resolved or tracked. Closes #2781 * fixup! Pick up comments between visibility modifier and item name * fixup! Pick up comments between visibility modifier and item name --- src/items.rs | 47 ++++++++++++++++++++++++++++++++++------------ tests/source/issue-2781.rs | 11 +++++++++++ tests/target/issue-2781.rs | 11 +++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 tests/source/issue-2781.rs create mode 100644 tests/target/issue-2781.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 039dd1e1ae0..cd8364fd686 100644 --- a/src/items.rs +++ b/src/items.rs @@ -401,7 +401,8 @@ impl<'a> FmtVisitor<'a> { generics: &ast::Generics, span: Span, ) { - let enum_header = format_header(&self.get_context(), "enum ", ident, vis); + let enum_header = + format_header(&self.get_context(), "enum ", ident, vis, self.block_indent); self.push_str(&enum_header); let enum_snippet = self.snippet(span); @@ -952,8 +953,8 @@ pub(crate) struct StructParts<'a> { } impl<'a> StructParts<'a> { - fn format_header(&self, context: &RewriteContext<'_>) -> String { - format_header(context, self.prefix, self.ident, self.vis) + fn format_header(&self, context: &RewriteContext<'_>, offset: Indent) -> String { + format_header(context, self.prefix, self.ident, self.vis, offset) } fn from_variant(variant: &'a ast::Variant) -> Self { @@ -1236,7 +1237,7 @@ fn format_unit_struct( p: &StructParts<'_>, offset: Indent, ) -> Option { - let header_str = format_header(context, p.prefix, p.ident, p.vis); + let header_str = format_header(context, p.prefix, p.ident, p.vis, offset); let generics_str = if let Some(generics) = p.generics { let hi = context.snippet_provider.span_before(p.span, ";"); format_generics( @@ -1265,7 +1266,7 @@ pub(crate) fn format_struct_struct( let mut result = String::with_capacity(1024); let span = struct_parts.span; - let header_str = struct_parts.format_header(context); + let header_str = struct_parts.format_header(context, offset); result.push_str(&header_str); let header_hi = struct_parts.ident.span.hi(); @@ -1401,7 +1402,7 @@ fn format_tuple_struct( let mut result = String::with_capacity(1024); let span = struct_parts.span; - let header_str = struct_parts.format_header(context); + let header_str = struct_parts.format_header(context, offset); result.push_str(&header_str); let body_lo = if fields.is_empty() { @@ -2920,13 +2921,35 @@ fn format_header( item_name: &str, ident: symbol::Ident, vis: &ast::Visibility, + offset: Indent, ) -> String { - format!( - "{}{}{}", - format_visibility(context, vis), - item_name, - rewrite_ident(context, ident) - ) + let mut result = String::with_capacity(128); + let shape = Shape::indented(offset, context.config); + + result.push_str(&format_visibility(context, vis).trim()); + + // Check for a missing comment between the visibility and the item name. + let after_vis = vis.span.hi(); + if let Some(before_item_name) = context + .snippet_provider + .opt_span_before(mk_sp(vis.span().lo(), ident.span.hi()), item_name.trim()) + { + let missing_span = mk_sp(after_vis, before_item_name); + if let Some(result_with_comment) = combine_strs_with_missing_comments( + context, + &result, + item_name, + missing_span, + shape, + /* allow_extend */ true, + ) { + result = result_with_comment; + } + } + + result.push_str(&rewrite_ident(context, ident)); + + result } #[derive(PartialEq, Eq, Clone, Copy)] diff --git a/tests/source/issue-2781.rs b/tests/source/issue-2781.rs new file mode 100644 index 00000000000..2c15b29b6dc --- /dev/null +++ b/tests/source/issue-2781.rs @@ -0,0 +1,11 @@ +pub // Oh, no. A line comment. +struct Foo {} + +pub /* Oh, no. A block comment. */ struct Foo {} + +mod inner { +pub // Oh, no. A line comment. +struct Foo {} + +pub /* Oh, no. A block comment. */ struct Foo {} +} diff --git a/tests/target/issue-2781.rs b/tests/target/issue-2781.rs new file mode 100644 index 00000000000..f144d716be9 --- /dev/null +++ b/tests/target/issue-2781.rs @@ -0,0 +1,11 @@ +pub // Oh, no. A line comment. +struct Foo {} + +pub /* Oh, no. A block comment. */ struct Foo {} + +mod inner { + pub // Oh, no. A line comment. + struct Foo {} + + pub /* Oh, no. A block comment. */ struct Foo {} +} -- cgit 1.4.1-3-g733a5 From ea712f1a2ca24b74fabe9a09b35caaaa46291695 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 28 Nov 2020 18:23:00 -0600 Subject: fix: apply rustc-ap updates to backported commit --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index cd8364fd686..57156aece33 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2932,7 +2932,7 @@ fn format_header( let after_vis = vis.span.hi(); if let Some(before_item_name) = context .snippet_provider - .opt_span_before(mk_sp(vis.span().lo(), ident.span.hi()), item_name.trim()) + .opt_span_before(mk_sp(vis.span.lo(), ident.span.hi()), item_name.trim()) { let missing_span = mk_sp(after_vis, before_item_name); if let Some(result_with_comment) = combine_strs_with_missing_comments( -- cgit 1.4.1-3-g733a5 From 6455e9de0e165ccd2874cf02f602844d2f63d355 Mon Sep 17 00:00:00 2001 From: WhizSid Date: Fri, 9 Oct 2020 05:57:04 +0530 Subject: Fixed 'Comment removed between type name and =' issue (#4448) * Fixed Comment removed between type name and = issue * Fixed where clause issue and pass the full span * has_where condition inline * Fixed indentation error on where clause * Removed tmp file --- src/items.rs | 41 ++++++++++++++++++++++++++++++++++++++--- src/visitor.rs | 4 ++++ tests/source/issue-4244.rs | 16 ++++++++++++++++ tests/target/issue-4244.rs | 20 ++++++++++++++++++++ 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 tests/source/issue-4244.rs create mode 100644 tests/target/issue-4244.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 57156aece33..6fdca90b12f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1495,6 +1495,7 @@ fn rewrite_type( generics: &ast::Generics, generic_bounds_opt: Option<&ast::GenericBounds>, rhs: Option<&R>, + span: Span, ) -> Option { let mut result = String::with_capacity(128); result.push_str(&format!("{}type ", format_visibility(context, vis))); @@ -1541,12 +1542,40 @@ fn rewrite_type( if let Some(ty) = rhs { // If there's a where clause, add a newline before the assignment. Otherwise just add a // space. - if !generics.where_clause.predicates.is_empty() { + let has_where = !generics.where_clause.predicates.is_empty(); + if has_where { result.push_str(&indent.to_string_with_newline(context.config)); } else { result.push(' '); } - let lhs = format!("{}=", result); + + let comment_span = context + .snippet_provider + .opt_span_before(span, "=") + .map(|op_lo| mk_sp(generics.where_clause.span.hi(), op_lo)); + + let lhs = match comment_span { + Some(comment_span) + if contains_comment(context.snippet_provider.span_to_snippet(comment_span)?) => + { + let comment_shape = if has_where { + Shape::indented(indent, context.config) + } else { + Shape::indented(indent, context.config) + .block_left(context.config.tab_spaces())? + }; + + combine_strs_with_missing_comments( + context, + result.trim_end(), + "=", + comment_span, + comment_shape, + true, + )? + } + _ => format!("{}=", result), + }; // 1 = `;` let shape = Shape::indented(indent, context.config).sub_width(1)?; @@ -1563,6 +1592,7 @@ pub(crate) fn rewrite_opaque_type( generic_bounds: &ast::GenericBounds, generics: &ast::Generics, vis: &ast::Visibility, + span: Span, ) -> Option { let opaque_type_bounds = OpaqueTypeBounds { generic_bounds }; rewrite_type( @@ -1573,6 +1603,7 @@ pub(crate) fn rewrite_opaque_type( generics, Some(generic_bounds), Some(&opaque_type_bounds), + span, ) } @@ -1801,6 +1832,7 @@ pub(crate) fn rewrite_type_alias( context: &RewriteContext<'_>, indent: Indent, vis: &ast::Visibility, + span: Span, ) -> Option { rewrite_type( context, @@ -1810,6 +1842,7 @@ pub(crate) fn rewrite_type_alias( generics, generic_bounds_opt, ty_opt, + span, ) } @@ -1859,8 +1892,9 @@ pub(crate) fn rewrite_associated_impl_type( generics: &ast::Generics, context: &RewriteContext<'_>, indent: Indent, + span: Span, ) -> Option { - let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis)?; + let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis, span)?; match defaultness { ast::Defaultness::Default(..) => Some(format!("default {}", result)), @@ -3118,6 +3152,7 @@ impl Rewrite for ast::ForeignItem { &context, shape.indent, &self.vis, + self.span, ), ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) diff --git a/src/visitor.rs b/src/visitor.rs index 3b9b0a2f967..fefeffac95c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -572,6 +572,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &self.get_context(), self.block_indent, &item.vis, + item.span, ); self.push_rewrite(item.span, rewrite); } @@ -583,6 +584,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { generic_bounds, generics, &item.vis, + item.span, ); self.push_rewrite(item.span, rewrite); } @@ -649,6 +651,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &self.get_context(), self.block_indent, &ti.vis, + ti.span, ); self.push_rewrite(ti.span, rewrite); } @@ -695,6 +698,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { &generics, &self.get_context(), self.block_indent, + ii.span, ) }; let rewrite = match ty { diff --git a/tests/source/issue-4244.rs b/tests/source/issue-4244.rs new file mode 100644 index 00000000000..34b51085e13 --- /dev/null +++ b/tests/source/issue-4244.rs @@ -0,0 +1,16 @@ +pub struct SS {} + +pub type A /* A Comment */ = SS; + +pub type B // Comment +// B += SS; + +pub type C + /* Comment C */ = SS; + +pub trait D { + type E /* Comment E */ = SS; +} + +type F<'a: 'static, T: Ord + 'static>: Eq + PartialEq where T: 'static + Copy /* x */ = Vec; diff --git a/tests/target/issue-4244.rs b/tests/target/issue-4244.rs new file mode 100644 index 00000000000..8958ba99e80 --- /dev/null +++ b/tests/target/issue-4244.rs @@ -0,0 +1,20 @@ +pub struct SS {} + +pub type A /* A Comment */ = SS; + +pub type B // Comment + // B + = SS; + +pub type C + /* Comment C */ + = SS; + +pub trait D { + type E /* Comment E */ = SS; +} + +type F<'a: 'static, T: Ord + 'static>: Eq + PartialEq +where + T: 'static + Copy, /* x */ += Vec; -- cgit 1.4.1-3-g733a5 From b7c38c9d50fcf48e40cf245b48ab9f36054f40d3 Mon Sep 17 00:00:00 2001 From: WhizSid Date: Tue, 3 Nov 2020 09:14:15 +0530 Subject: Fixed comment dropped between & and type issue (#4482) * Fixed comment dropped between & and type issue * Reduced nesting levels and avoided duplications * Removed extra allocations --- src/types.rs | 89 ++++++++++++++++++++++++++++++++-------------- tests/source/issue-4245.rs | 26 ++++++++++++++ tests/target/issue-4245.rs | 34 ++++++++++++++++++ 3 files changed, 122 insertions(+), 27 deletions(-) create mode 100644 tests/source/issue-4245.rs create mode 100644 tests/target/issue-4245.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 4e2b87ebfc8..4b936c1baf5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,7 +2,7 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability}; -use rustc_span::{symbol::kw, BytePos, Span}; +use rustc_span::{symbol::kw, BytePos, Pos, Span}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; @@ -648,37 +648,72 @@ impl Rewrite for ast::Ty { ast::TyKind::Rptr(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); - Some(match *lifetime { - Some(ref lifetime) => { - let lt_budget = shape.width.checked_sub(2 + mut_len)?; - let lt_str = lifetime.rewrite( + let mut result = String::with_capacity(128); + result.push_str("&"); + let ref_hi = context.snippet_provider.span_after(self.span(), "&"); + let mut cmnt_lo = ref_hi; + + if let Some(ref lifetime) = *lifetime { + let lt_budget = shape.width.checked_sub(2 + mut_len)?; + let lt_str = lifetime.rewrite( + context, + Shape::legacy(lt_budget, shape.indent + 2 + mut_len), + )?; + let before_lt_span = mk_sp(cmnt_lo, lifetime.ident.span.lo()); + if contains_comment(context.snippet(before_lt_span)) { + result = combine_strs_with_missing_comments( context, - Shape::legacy(lt_budget, shape.indent + 2 + mut_len), + &result, + <_str, + before_lt_span, + shape, + true, )?; - let lt_len = lt_str.len(); - let budget = shape.width.checked_sub(2 + mut_len + lt_len)?; - format!( - "&{} {}{}", - lt_str, - mut_str, - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 2 + mut_len + lt_len) - )? - ) + } else { + result.push_str(<_str); } - None => { - let budget = shape.width.checked_sub(1 + mut_len)?; - format!( - "&{}{}", + result.push_str(" "); + cmnt_lo = lifetime.ident.span.hi(); + } + + if ast::Mutability::Mut == mt.mutbl { + let mut_hi = context.snippet_provider.span_after(self.span(), "mut"); + let before_mut_span = mk_sp(cmnt_lo, mut_hi - BytePos::from_usize(3)); + if contains_comment(context.snippet(before_mut_span)) { + result = combine_strs_with_missing_comments( + context, + result.trim_end(), mut_str, - mt.ty.rewrite( - context, - Shape::legacy(budget, shape.indent + 1 + mut_len) - )? - ) + before_mut_span, + shape, + true, + )?; + } else { + result.push_str(mut_str); } - }) + cmnt_lo = mut_hi; + } + + let before_ty_span = mk_sp(cmnt_lo, mt.ty.span.lo()); + if contains_comment(context.snippet(before_ty_span)) { + result = combine_strs_with_missing_comments( + context, + result.trim_end(), + &mt.ty.rewrite(&context, shape)?, + before_ty_span, + shape, + true, + )?; + } else { + let used_width = last_line_width(&result); + let budget = shape.width.checked_sub(used_width)?; + let ty_str = mt + .ty + .rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?; + result.push_str(&ty_str); + } + + Some(result) } // FIXME: we drop any comments here, even though it's a silly place to put // comments. diff --git a/tests/source/issue-4245.rs b/tests/source/issue-4245.rs new file mode 100644 index 00000000000..57d7e192d0a --- /dev/null +++ b/tests/source/issue-4245.rs @@ -0,0 +1,26 @@ + + +fn a(a: & // Comment + // Another comment + 'a File) {} + +fn b(b: & /* Another Comment */'a File) {} + +fn c(c: &'a /*Comment */ mut /*Comment */ File){} + +fn d(c: & // Comment +'b // Multi Line +// Comment +mut // Multi Line +// Comment +File +) {} + +fn e(c: &// Comment +File) {} + +fn d(c: &// Comment +mut // Multi Line +// Comment +File +) {} diff --git a/tests/target/issue-4245.rs b/tests/target/issue-4245.rs new file mode 100644 index 00000000000..e3d40eb4267 --- /dev/null +++ b/tests/target/issue-4245.rs @@ -0,0 +1,34 @@ +fn a( + a: & // Comment + // Another comment + 'a File, +) { +} + +fn b(b: & /* Another Comment */ 'a File) {} + +fn c(c: &'a /*Comment */ mut /*Comment */ File) {} + +fn d( + c: & // Comment + 'b // Multi Line + // Comment + mut // Multi Line + // Comment + File, +) { +} + +fn e( + c: & // Comment + File, +) { +} + +fn d( + c: & // Comment + mut // Multi Line + // Comment + File, +) { +} -- cgit 1.4.1-3-g733a5 From 823c4f820a46159661d681b6f982c6457c5eb0f6 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 28 Nov 2020 18:30:28 -0600 Subject: fix: backport some imports for cherry-picked commit --- src/types.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 4b936c1baf5..e8bd74d5a12 100644 --- a/src/types.rs +++ b/src/types.rs @@ -4,6 +4,7 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability}; use rustc_span::{symbol::kw, BytePos, Pos, Span}; +use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; use crate::expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}; -- cgit 1.4.1-3-g733a5 From 7d9ee7558e5992bb0929302109c97a2e3c267c86 Mon Sep 17 00:00:00 2001 From: WhizSid Date: Sun, 18 Oct 2020 22:32:46 +0530 Subject: Comment between typebounds (#4474) * Test cases and get spans * Fixed type bounds * Fixed issue of test cases * Fixed first test case issue * Removed unwanted whitespaces * Removed tmp files --- src/types.rs | 162 +++++++++++++++++++++++++++++++++------------ tests/source/issue-4243.rs | 21 ++++++ tests/target/issue-4243.rs | 28 ++++++++ 3 files changed, 167 insertions(+), 44 deletions(-) create mode 100644 tests/source/issue-4243.rs create mode 100644 tests/target/issue-4243.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index e8bd74d5a12..7eeee2ac979 100644 --- a/src/types.rs +++ b/src/types.rs @@ -874,57 +874,131 @@ fn join_bounds( items: &[ast::GenericBound], need_indent: bool, ) -> Option { - debug_assert!(!items.is_empty()); - - // Try to join types in a single line - let joiner = match context.config.type_punctuation_density() { - TypeDensity::Compressed => "+", - TypeDensity::Wide => " + ", - }; - let type_strs = items - .iter() - .map(|item| item.rewrite(context, shape)) - .collect::>>()?; - let result = type_strs.join(joiner); - if items.len() <= 1 || (!result.contains('\n') && result.len() <= shape.width) { - return Some(result); - } + join_bounds_inner(context, shape, items, need_indent, false) +} - // We need to use multiple lines. - let (type_strs, offset) = if need_indent { - // Rewrite with additional indentation. - let nested_shape = shape - .block_indent(context.config.tab_spaces()) - .with_max_width(context.config); - let type_strs = items - .iter() - .map(|item| item.rewrite(context, nested_shape)) - .collect::>>()?; - (type_strs, nested_shape.indent) - } else { - (type_strs, shape.indent) - }; +fn join_bounds_inner( + context: &RewriteContext<'_>, + shape: Shape, + items: &[ast::GenericBound], + need_indent: bool, + force_newline: bool, +) -> Option { + debug_assert!(!items.is_empty()); + let generic_bounds_in_order = is_generic_bounds_in_order(items); let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b { ast::GenericBound::Outlives(..) => true, ast::GenericBound::Trait(..) => last_line_extendable(s), }; - let mut result = String::with_capacity(128); - result.push_str(&type_strs[0]); - let mut can_be_put_on_the_same_line = is_bound_extendable(&result, &items[0]); - let generic_bounds_in_order = is_generic_bounds_in_order(items); - for (bound, bound_str) in items[1..].iter().zip(type_strs[1..].iter()) { - if generic_bounds_in_order && can_be_put_on_the_same_line { - result.push_str(joiner); - } else { - result.push_str(&offset.to_string_with_newline(context.config)); - result.push_str("+ "); - } - result.push_str(bound_str); - can_be_put_on_the_same_line = is_bound_extendable(bound_str, bound); - } - Some(result) + let result = items.iter().enumerate().try_fold( + (String::new(), None, false), + |(strs, prev_trailing_span, prev_extendable), (i, item)| { + let trailing_span = if i < items.len() - 1 { + let hi = context + .snippet_provider + .span_before(mk_sp(items[i + 1].span().lo(), item.span().hi()), "+"); + + Some(mk_sp(item.span().hi(), hi)) + } else { + None + }; + let (leading_span, has_leading_comment) = if i > 0 { + let lo = context + .snippet_provider + .span_after(mk_sp(items[i - 1].span().hi(), item.span().lo()), "+"); + + let span = mk_sp(lo, item.span().lo()); + + let has_comments = contains_comment(context.snippet(span)); + + (Some(mk_sp(lo, item.span().lo())), has_comments) + } else { + (None, false) + }; + let prev_has_trailing_comment = match prev_trailing_span { + Some(ts) => contains_comment(context.snippet(ts)), + _ => false, + }; + + let shape = if i > 0 && need_indent && force_newline { + shape + .block_indent(context.config.tab_spaces()) + .with_max_width(context.config) + } else { + shape + }; + let whitespace = if force_newline && (!prev_extendable || !generic_bounds_in_order) { + shape + .indent + .to_string_with_newline(context.config) + .to_string() + } else { + String::from(" ") + }; + + let joiner = match context.config.type_punctuation_density() { + TypeDensity::Compressed => String::from("+"), + TypeDensity::Wide => whitespace + "+ ", + }; + let joiner = if has_leading_comment { + joiner.trim_end() + } else { + &joiner + }; + let joiner = if prev_has_trailing_comment { + joiner.trim_start() + } else { + joiner + }; + + let (trailing_str, extendable) = if i == 0 { + let bound_str = item.rewrite(context, shape)?; + let bound_str_clone = bound_str.clone(); + (bound_str, is_bound_extendable(&bound_str_clone, item)) + } else { + let bound_str = &item.rewrite(context, shape)?; + match leading_span { + Some(ls) if has_leading_comment => ( + combine_strs_with_missing_comments( + context, joiner, bound_str, ls, shape, true, + )?, + is_bound_extendable(bound_str, item), + ), + _ => ( + String::from(joiner) + bound_str, + is_bound_extendable(bound_str, item), + ), + } + }; + match prev_trailing_span { + Some(ts) if prev_has_trailing_comment => combine_strs_with_missing_comments( + context, + &strs, + &trailing_str, + ts, + shape, + true, + ) + .map(|v| (v, trailing_span, extendable)), + _ => Some(( + String::from(strs) + &trailing_str, + trailing_span, + extendable, + )), + } + }, + )?; + + if !force_newline + && items.len() > 1 + && (result.0.contains('\n') || result.0.len() > shape.width) + { + join_bounds_inner(context, shape, items, need_indent, true) + } else { + Some(result.0) + } } pub(crate) fn can_be_overflowed_type( diff --git a/tests/source/issue-4243.rs b/tests/source/issue-4243.rs new file mode 100644 index 00000000000..d8a27f7a4a4 --- /dev/null +++ b/tests/source/issue-4243.rs @@ -0,0 +1,21 @@ +fn main() { + type A: AA /*AA*/ + /*AB*/ AB ++ AC = AA +/*AA*/ + + /*AB*/ AB+AC; + + type B: BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/+/*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB + + BC = BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/ + /*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB+ BC; + + type C: CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +// CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + + + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CB + CC = CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + + + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CB+ CC; +} diff --git a/tests/target/issue-4243.rs b/tests/target/issue-4243.rs new file mode 100644 index 00000000000..67fa1d2a312 --- /dev/null +++ b/tests/target/issue-4243.rs @@ -0,0 +1,28 @@ +fn main() { + type A: AA /*AA*/ + /*AB*/ AB + AC = AA + /*AA*/ + + + /*AB*/ + AB + + AC; + + type B: BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/ + + /*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB + + BC = BA /*BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA*/ + + /*BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB*/ BB + + BC; + + type C: CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + + + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CB + + CC = CA // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + // CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + + + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + // CBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + CB + + CC; +} -- cgit 1.4.1-3-g733a5 From 96ee060529b507c10d14015de42becbd9ff0f639 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 30 Nov 2020 18:57:07 -0800 Subject: Preserve polarity on negative non-trait impl --- src/items.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 6fdca90b12f..7b1bb6ce7be 100644 --- a/src/items.rs +++ b/src/items.rs @@ -857,6 +857,8 @@ fn format_impl_ref_and_type( ast::ImplPolarity::Positive => "", }; + let polarity_overhead; + let trait_ref_overhead; if let Some(ref trait_ref) = *trait_ref { let result_len = last_line_width(&result); result.push_str(&rewrite_trait_ref( @@ -866,11 +868,14 @@ fn format_impl_ref_and_type( polarity_str, result_len, )?); + polarity_overhead = 0; // already written + trait_ref_overhead = " for".len(); + } else { + polarity_overhead = polarity_str.len(); + trait_ref_overhead = 0; } // Try to put the self type in a single line. - // ` for` - let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 }; let curly_brace_overhead = if generics.where_clause.predicates.is_empty() { // If there is no where-clause adapt budget for type formatting to take space and curly // brace into account. @@ -881,7 +886,10 @@ fn format_impl_ref_and_type( } else { 0 }; - let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; + let used_space = last_line_width(&result) + + polarity_overhead + + trait_ref_overhead + + curly_brace_overhead; // 1 = space before the type. let budget = context.budget(used_space + 1); if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { @@ -890,6 +898,7 @@ fn format_impl_ref_and_type( result.push_str(" for "); } else { result.push(' '); + result.push_str(polarity_str); } result.push_str(&self_ty_str); return Some(result); @@ -903,8 +912,10 @@ fn format_impl_ref_and_type( result.push_str(&new_line_offset.to_string(context.config)); if trait_ref.is_some() { result.push_str("for "); + } else { + result.push_str(polarity_str); } - let budget = context.budget(last_line_width(&result)); + let budget = context.budget(last_line_width(&result) + polarity_overhead); let type_offset = match context.config.indent_style() { IndentStyle::Visual => new_line_offset + trait_ref_overhead, IndentStyle::Block => new_line_offset, -- cgit 1.4.1-3-g733a5 From 4cfb9ef8f4436cb1150022897f900c461c9f581c Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 11 Dec 2020 12:19:30 -0600 Subject: fix: don't strip nonexistent comma in derive --- src/attr.rs | 4 +++- tests/source/issue_4584.rs | 19 +++++++++++++++++++ tests/target/issue_4584.rs | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue_4584.rs create mode 100644 tests/target/issue_4584.rs (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index dab9cabccdc..2d25c263277 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -183,9 +183,11 @@ fn format_derive( } else if let SeparatorTactic::Always = context.config.trailing_comma() { // Retain the trailing comma. result.push_str(&item_str); - } else { + } else if item_str.ends_with(",") { // Remove the trailing comma. result.push_str(&item_str[..item_str.len() - 1]); + } else { + result.push_str(&item_str); } result.push_str(")]"); diff --git a/tests/source/issue_4584.rs b/tests/source/issue_4584.rs new file mode 100644 index 00000000000..695c5590559 --- /dev/null +++ b/tests/source/issue_4584.rs @@ -0,0 +1,19 @@ +// rustfmt-indent_style: Visual + +#[derive(Debug,)] +pub enum Case { + Upper, + Lower +} + +#[derive(Debug, Clone, PartialEq, Eq,)] +pub enum Case { + Upper, + Lower +} + +// NB - This formatting looks potentially off the desired state, but is +// consistent with current behavior. Included here to provide a line wrapped +// derive case with the changes applied to resolve issue #4584 +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Mul,)] +struct Foo {} \ No newline at end of file diff --git a/tests/target/issue_4584.rs b/tests/target/issue_4584.rs new file mode 100644 index 00000000000..20255beadb2 --- /dev/null +++ b/tests/target/issue_4584.rs @@ -0,0 +1,32 @@ +// rustfmt-indent_style: Visual + +#[derive(Debug)] +pub enum Case { + Upper, + Lower, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Case { + Upper, + Lower, +} + +// NB - This formatting looks potentially off the desired state, but is +// consistent with current behavior. Included here to provide a line wrapped +// derive case with the changes applied to resolve issue #4584 +#[derive(Add, + Sub, + Mul, + Div, + Clone, + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, + Debug, + Hash, + Serialize, + Mul)] +struct Foo {} -- cgit 1.4.1-3-g733a5 From c536d80dc1c7c70c870ba5ec9d73943cd8e9e3f6 Mon Sep 17 00:00:00 2001 From: Stéphane Campinas Date: Mon, 7 Dec 2020 13:08:45 +0100 Subject: Fix rewrite of closures with a return type If the closure's body fits in a line, the block is removed but it is necessary if the closure has a return type. --- src/closures.rs | 23 +++++++++++++---------- tests/source/issue-4577.rs | 20 ++++++++++++++++++++ tests/target/issue-4577.rs | 15 +++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 tests/source/issue-4577.rs create mode 100644 tests/target/issue-4577.rs (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 3cfaa4513eb..71b07e4b9ee 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -339,18 +339,21 @@ pub(crate) fn rewrite_last_closure( if is_block_closure_forced(context, body) { return rewrite_closure_with_block(body, &prefix, context, body_shape).and_then( |body_str| { - // If the expression can fit in a single line, we need not force block closure. - if body_str.lines().count() <= 7 { - match rewrite_closure_expr(body, &prefix, context, shape) { - Some(ref single_line_body_str) - if !single_line_body_str.contains('\n') => - { - Some(single_line_body_str.clone()) + match fn_decl.output { + ast::FnRetTy::Default(..) if body_str.lines().count() <= 7 => { + // If the expression can fit in a single line, we need not force block + // closure. However, if the closure has a return type, then we must + // keep the blocks. + match rewrite_closure_expr(body, &prefix, context, shape) { + Some(ref single_line_body_str) + if !single_line_body_str.contains('\n') => + { + Some(single_line_body_str.clone()) + } + _ => Some(body_str), } - _ => Some(body_str), } - } else { - Some(body_str) + _ => Some(body_str), } }, ); diff --git a/tests/source/issue-4577.rs b/tests/source/issue-4577.rs new file mode 100644 index 00000000000..79975dd73ff --- /dev/null +++ b/tests/source/issue-4577.rs @@ -0,0 +1,20 @@ +fn main() { + let s: String = "ABAABBAA".chars() + .filter(|c| { + if *c == 'A' { + true + } + else { + false + } + }) + .map(|c| -> char { + if c == 'A' { + '0' + } else { + '1' + } + }).collect(); + + println!("{}", s); +} diff --git a/tests/target/issue-4577.rs b/tests/target/issue-4577.rs new file mode 100644 index 00000000000..1bd9eb6b806 --- /dev/null +++ b/tests/target/issue-4577.rs @@ -0,0 +1,15 @@ +fn main() { + let s: String = "ABAABBAA" + .chars() + .filter(|c| if *c == 'A' { true } else { false }) + .map(|c| -> char { + if c == 'A' { + '0' + } else { + '1' + } + }) + .collect(); + + println!("{}", s); +} -- cgit 1.4.1-3-g733a5 From 0d022d08d875c857ffcc4eab958b6be99528a98a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 9 Sep 2020 12:52:52 +0900 Subject: Format error and typeof types (#4416) * Add a test for #4357 * Format error and typeof types --- src/types.rs | 13 +++++++++++-- tests/source/type.rs | 6 ++++++ tests/target/type.rs | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 7eeee2ac979..6e1fc8fc387 100644 --- a/src/types.rs +++ b/src/types.rs @@ -7,7 +7,9 @@ use rustc_span::{symbol::kw, BytePos, Pos, Span}; use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; use crate::config::{IndentStyle, TypeDensity, Version}; -use crate::expr::{format_expr, rewrite_assign_rhs, rewrite_tuple, rewrite_unary_prefix, ExprType}; +use crate::expr::{ + format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType, +}; use crate::lists::{ definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, }; @@ -797,7 +799,14 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::Err | ast::TyKind::Typeof(..) => unreachable!(), + ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), + ast::TyKind::Typeof(ref anon_const) => rewrite_call( + context, + "typeof", + &[anon_const.value.clone()], + self.span, + shape, + ), } } } diff --git a/tests/source/type.rs b/tests/source/type.rs index eb4600e5bce..57f31dc901e 100644 --- a/tests/source/type.rs +++ b/tests/source/type.rs @@ -166,3 +166,9 @@ impl Foo { Self(t) } } + +// #4357 +type T = typeof( +1); +impl T for .. { +} \ No newline at end of file diff --git a/tests/target/type.rs b/tests/target/type.rs index 20e97440e7c..e7761251688 100644 --- a/tests/target/type.rs +++ b/tests/target/type.rs @@ -177,3 +177,7 @@ impl Foo { Self(t) } } + +// #4357 +type T = typeof(1); +impl T for .. {} -- cgit 1.4.1-3-g733a5 From 398d2f96c3f04ba0b1413eb4b47250c7a8f51884 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 1 Jan 2021 17:00:40 +0100 Subject: Add support for edition 2021. --- Configurations.md | 4 ++-- src/config/options.rs | 21 ++++++++++++++++----- src/formatting.rs | 2 +- src/imports.rs | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/Configurations.md b/Configurations.md index 3b993f3fd48..e9035c6ff24 100644 --- a/Configurations.md +++ b/Configurations.md @@ -497,8 +497,8 @@ Don't reformat anything Specifies which edition is used by the parser. -- **Default value**: `2015` -- **Possible values**: `2015`, `2018` +- **Default value**: `"2015"` +- **Possible values**: `"2015"`, `"2018"`, `"2021"` - **Stable**: Yes Rustfmt is able to pick up the edition used by reading the `Cargo.toml` file if executed diff --git a/src/config/options.rs b/src/config/options.rs index ae120a475f4..e7a6c414354 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -388,6 +388,10 @@ pub enum Edition { #[doc_hint = "2018"] /// Edition 2018. Edition2018, + #[value = "2021"] + #[doc_hint = "2021"] + /// Edition 2021. + Edition2021, } impl Default for Edition { @@ -396,15 +400,22 @@ impl Default for Edition { } } -impl Edition { - pub(crate) fn to_libsyntax_pos_edition(self) -> rustc_span::edition::Edition { - match self { - Edition::Edition2015 => rustc_span::edition::Edition::Edition2015, - Edition::Edition2018 => rustc_span::edition::Edition::Edition2018, +impl From for rustc_span::edition::Edition { + fn from(edition: Edition) -> Self { + match edition { + Edition::Edition2015 => Self::Edition2015, + Edition::Edition2018 => Self::Edition2018, + Edition::Edition2021 => Self::Edition2021, } } } +impl PartialOrd for Edition { + fn partial_cmp(&self, other: &Edition) -> Option { + rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into()) + } +} + /// Controls how rustfmt should handle leading pipes on match arms. #[config_type] pub enum MatchArmLeadingPipe { diff --git a/src/formatting.rs b/src/formatting.rs index 26ae494227d..289e58cf693 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -34,7 +34,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { return Err(ErrorKind::VersionMismatch); } - rustc_span::with_session_globals(self.config.edition().to_libsyntax_pos_edition(), || { + rustc_span::with_session_globals(self.config.edition().into(), || { if self.config.disable_all_formatting() { // When the input is from stdin, echo back the input. if let Input::Text(ref buf) = input { diff --git a/src/imports.rs b/src/imports.rs index 0b3d844ea14..d7082d50f88 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -331,7 +331,7 @@ impl UseTree { }; let leading_modsep = - context.config.edition() == Edition::Edition2018 && a.prefix.is_global(); + context.config.edition() >= Edition::Edition2018 && a.prefix.is_global(); let mut modsep = leading_modsep; -- cgit 1.4.1-3-g733a5 From 46444185565cf58f4a40efbd3f1592fd689fc73a Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 1 Jan 2021 17:00:52 +0100 Subject: Fixes for new rustc changes. --- src/closures.rs | 1 - src/items.rs | 2 +- src/macros.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/closures.rs b/src/closures.rs index 71b07e4b9ee..3d65077ddc2 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -151,7 +151,6 @@ fn rewrite_closure_with_block( id: ast::NodeId::root(), kind: ast::StmtKind::Expr(ptr::P(body.clone())), span: body.span, - tokens: None, }], id: ast::NodeId::root(), rules: ast::BlockCheckMode::Default, diff --git a/src/items.rs b/src/items.rs index 7b1bb6ce7be..9f079f15c15 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2118,7 +2118,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param pub(crate) fn is_named_param(param: &ast::Param) -> bool { if let ast::PatKind::Ident(_, ident, _) = param.pat.kind { - ident.name != symbol::kw::Invalid + ident.name != symbol::kw::Empty } else { true } diff --git a/src/macros.rs b/src/macros.rs index e5a28751988..119ae61d8dd 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -158,7 +158,7 @@ fn rewrite_macro_name( format!("{}!", pprust::path_to_string(path)) }; match extra_ident { - Some(ident) if ident.name != kw::Invalid => format!("{} {}", name, ident), + Some(ident) if ident.name != kw::Empty => format!("{} {}", name, ident), _ => name, } } -- cgit 1.4.1-3-g733a5 From 5bb17a0d368a6fc73adc2cec393d381da60577f6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 1 Jan 2021 20:47:30 +0100 Subject: Account for new ast::GenericParamKind::Const::default in rust_ast. --- src/spanned.rs | 9 ++++++++- src/types.rs | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/spanned.rs b/src/spanned.rs index 7bf370c131e..9e3658dd22f 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -113,7 +113,14 @@ impl Spanned for ast::Param { impl Spanned for ast::GenericParam { fn span(&self) -> Span { - let lo = if self.attrs.is_empty() { + let lo = if let ast::GenericParamKind::Const { + ty: _, + kw_span, + default: _, + } = self.kind + { + kw_span.lo() + } else if self.attrs.is_empty() { self.ident.span.lo() } else { self.attrs[0].span.lo() diff --git a/src/types.rs b/src/types.rs index 6e1fc8fc387..bedc29fbc1a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -563,7 +563,12 @@ impl Rewrite for ast::GenericParam { _ => (), } - if let rustc_ast::ast::GenericParamKind::Const { ref ty, .. } = &self.kind { + if let ast::GenericParamKind::Const { + ref ty, + kw_span: _, + default: _, + } = &self.kind + { result.push_str("const "); result.push_str(rewrite_ident(context, self.ident)); result.push_str(": "); -- cgit 1.4.1-3-g733a5 From 3571c5d6f7f5dd48056627ccc70047593ad84d5c Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 9 Jan 2021 11:23:36 -0600 Subject: fix: maintain redundant semis on items in statement pos --- src/visitor.rs | 57 +++++++++++++++++++++++++++++++++++----------- tests/source/statements.rs | 43 ++++++++++++++++++++++++++++++++++ tests/target/statements.rs | 42 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 tests/source/statements.rs create mode 100644 tests/target/statements.rs (limited to 'src') diff --git a/src/visitor.rs b/src/visitor.rs index fefeffac95c..15055d46d30 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -112,7 +112,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { mk_sp(self.last_pos, hi) } - fn visit_stmt(&mut self, stmt: &Stmt<'_>) { + fn visit_stmt(&mut self, stmt: &Stmt<'_>, include_empty_semi: bool) { debug!( "visit_stmt: {}", self.parse_sess.span_to_debug_info(stmt.span()) @@ -127,13 +127,23 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { .map_or(false, |i| starts_with_newline(&snippet[i..])); let snippet = snippet.trim(); if !snippet.is_empty() { - if original_starts_with_newline { - self.push_str("\n"); + // FIXME(calebcartwright 2021-01-03) - This exists strictly to maintain legacy + // formatting where rustfmt would preserve redundant semicolons on Items in a + // statement position. + // See comment within `walk_stmts` for more info + if include_empty_semi { + self.format_missing(stmt.span().hi()); + } else { + if original_starts_with_newline { + self.push_str("\n"); + } + + self.push_str(&self.block_indent.to_string(self.config)); + self.push_str(snippet); } - self.push_str(&self.block_indent.to_string(self.config)); - self.push_str(snippet); + } else if include_empty_semi { + self.push_str(";"); } - self.last_pos = stmt.span().hi(); return; } @@ -141,8 +151,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { match stmt.as_ast_node().kind { ast::StmtKind::Item(ref item) => { self.visit_item(item); - // Handle potential `;` after the item. - self.format_missing(stmt.span().hi()); + self.last_pos = stmt.span().hi(); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let attrs = get_attrs_from_stmt(stmt.as_ast_node()); @@ -899,7 +908,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); } - fn walk_stmts(&mut self, stmts: &[Stmt<'_>]) { + fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) { if stmts.is_empty() { return; } @@ -912,16 +921,38 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { .collect(); if items.is_empty() { - self.visit_stmt(&stmts[0]); - self.walk_stmts(&stmts[1..]); + self.visit_stmt(&stmts[0], include_current_empty_semi); + + // FIXME(calebcartwright 2021-01-03) - This exists strictly to maintain legacy + // formatting where rustfmt would preserve redundant semicolons on Items in a + // statement position. + // + // Starting in rustc-ap-* v692 (~2020-12-01) the rustc parser now parses this as + // two separate statements (Item and Empty kinds), whereas before it was parsed as + // a single statement with the statement's span including the redundant semicolon. + // + // rustfmt typically tosses unnecessary/redundant semicolons, and eventually we + // should toss these as well, but doing so at this time would + // break the Stability Guarantee + // N.B. This could be updated to utilize the version gates. + let include_next_empty = if stmts.len() > 1 { + match (&stmts[0].as_ast_node().kind, &stmts[1].as_ast_node().kind) { + (ast::StmtKind::Item(_), ast::StmtKind::Empty) => true, + _ => false, + } + } else { + false + }; + + self.walk_stmts(&stmts[1..], include_next_empty); } else { self.visit_items_with_reordering(&items); - self.walk_stmts(&stmts[items.len()..]); + self.walk_stmts(&stmts[items.len()..], false); } } fn walk_block_stmts(&mut self, b: &ast::Block) { - self.walk_stmts(&Stmt::from_ast_nodes(b.stmts.iter())) + self.walk_stmts(&Stmt::from_ast_nodes(b.stmts.iter()), false) } fn format_mod( diff --git a/tests/source/statements.rs b/tests/source/statements.rs new file mode 100644 index 00000000000..c840b8ce105 --- /dev/null +++ b/tests/source/statements.rs @@ -0,0 +1,43 @@ +// FIXME(calebcartwright) - Hopefully one day we can +// elide these redundant semis like we do in other contexts. +fn redundant_item_semis() { + impl Foo { + fn get(&self) -> usize { + 5 + } + }; + + impl Bar { + fn get(&self) -> usize { + 5 + } + } /*asdfsf*/; + + + impl Baz { + fn get(&self) -> usize { + 5 + } + } /*asdfsf*/ + + // why would someone do this + ; + + + impl Qux { + fn get(&self) -> usize { + 5 + } + } + + // why + ; + + impl Lorem { + fn get(&self) -> usize { + 5 + } + } + // oh why + ; +} \ No newline at end of file diff --git a/tests/target/statements.rs b/tests/target/statements.rs new file mode 100644 index 00000000000..c1e7dc464c2 --- /dev/null +++ b/tests/target/statements.rs @@ -0,0 +1,42 @@ +// FIXME(calebcartwright) - Hopefully one day we can +// elide these redundant semis like we do in other contexts. +fn redundant_item_semis() { + impl Foo { + fn get(&self) -> usize { + 5 + } + }; + + impl Bar { + fn get(&self) -> usize { + 5 + } + } /*asdfsf*/ + ; + + impl Baz { + fn get(&self) -> usize { + 5 + } + } /*asdfsf*/ + + // why would someone do this + ; + + impl Qux { + fn get(&self) -> usize { + 5 + } + } + + // why + ; + + impl Lorem { + fn get(&self) -> usize { + 5 + } + } + // oh why + ; +} -- cgit 1.4.1-3-g733a5 From b30cb2428652a43bba58ef190d9915c6a305c1ae Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 12 Jan 2021 17:39:03 -0600 Subject: fix: indentation issue on generic bounds --- src/types.rs | 2 +- tests/source/issue_4636.rs | 13 +++++++++++++ tests/target/issue_4636.rs | 13 +++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue_4636.rs create mode 100644 tests/target/issue_4636.rs (limited to 'src') diff --git a/src/types.rs b/src/types.rs index bedc29fbc1a..7ef0c39d578 100644 --- a/src/types.rs +++ b/src/types.rs @@ -936,7 +936,7 @@ fn join_bounds_inner( _ => false, }; - let shape = if i > 0 && need_indent && force_newline { + let shape = if need_indent && force_newline { shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config) diff --git a/tests/source/issue_4636.rs b/tests/source/issue_4636.rs new file mode 100644 index 00000000000..ea7079f6c73 --- /dev/null +++ b/tests/source/issue_4636.rs @@ -0,0 +1,13 @@ +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + fmt::Write + { + // + } \ No newline at end of file diff --git a/tests/target/issue_4636.rs b/tests/target/issue_4636.rs new file mode 100644 index 00000000000..a6465e29a02 --- /dev/null +++ b/tests/target/issue_4636.rs @@ -0,0 +1,13 @@ +pub trait PrettyPrinter<'tcx>: + Printer< + 'tcx, + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + DynExistential = Self, + Const = Self, + > + fmt::Write +{ + // +} -- cgit 1.4.1-3-g733a5 From c4d551cdf57bd7041ed95c81f10daee158a1fc7f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Tue, 12 Jan 2021 17:40:53 -0600 Subject: refactor: remove unneeded clone --- src/types.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/types.rs b/src/types.rs index 7ef0c39d578..cda17e13eeb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -967,22 +967,21 @@ fn join_bounds_inner( joiner }; - let (trailing_str, extendable) = if i == 0 { + let (extendable, trailing_str) = if i == 0 { let bound_str = item.rewrite(context, shape)?; - let bound_str_clone = bound_str.clone(); - (bound_str, is_bound_extendable(&bound_str_clone, item)) + (is_bound_extendable(&bound_str, item), bound_str) } else { let bound_str = &item.rewrite(context, shape)?; match leading_span { Some(ls) if has_leading_comment => ( + is_bound_extendable(bound_str, item), combine_strs_with_missing_comments( context, joiner, bound_str, ls, shape, true, )?, - is_bound_extendable(bound_str, item), ), _ => ( - String::from(joiner) + bound_str, is_bound_extendable(bound_str, item), + String::from(joiner) + bound_str, ), } }; -- cgit 1.4.1-3-g733a5 From 71863753bd53da50dd26bd8ab78a5da581e73f5c Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Tue, 15 Dec 2020 17:19:54 -0800 Subject: Rename `merge_imports` to `imports_granularity` and add a `Module` option. This renames the existing `true`/`false` options to `Crate`/`Never`, then adds a new `Module` option which causes imports to be grouped together by their originating module. --- Configurations.md | 47 +++++++- src/config/config_type.rs | 23 +++- src/config/mod.rs | 60 ++++++++++- src/config/options.rs | 14 ++- src/imports.rs | 118 +++++++++++++++------ src/reorder.rs | 14 ++- .../StdExternalCrate-merge_imports.rs | 2 +- tests/source/configs/imports_layout/merge_mixed.rs | 2 +- tests/source/imports_granularity_crate.rs | 37 +++++++ tests/source/imports_granularity_module.rs | 18 ++++ tests/source/issue-3750.rs | 2 +- tests/source/merge_imports.rs | 34 ------ tests/source/merge_imports_true_compat.rs | 4 + .../StdExternalCrate-merge_imports.rs | 2 +- tests/target/configs/imports_layout/merge_mixed.rs | 2 +- tests/target/imports_granularity_crate.rs | 28 +++++ tests/target/imports_granularity_module.rs | 20 ++++ tests/target/issue-3750.rs | 2 +- tests/target/merge_imports.rs | 25 ----- tests/target/merge_imports_true_compat.rs | 3 + 20 files changed, 348 insertions(+), 109 deletions(-) create mode 100644 tests/source/imports_granularity_crate.rs create mode 100644 tests/source/imports_granularity_module.rs delete mode 100644 tests/source/merge_imports.rs create mode 100644 tests/source/merge_imports_true_compat.rs create mode 100644 tests/target/imports_granularity_crate.rs create mode 100644 tests/target/imports_granularity_module.rs delete mode 100644 tests/target/merge_imports.rs create mode 100644 tests/target/merge_imports_true_compat.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index e9035c6ff24..07c8a442d41 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1615,13 +1615,56 @@ pub enum Foo {} pub enum Foo {} ``` +## `imports_granularity` + +Merge together related imports based on their paths. + +- **Default value**: `Preserve` +- **Possible values**: `Preserve`, `Crate`, `Module` +- **Stable**: No + +#### `Preserve` (default): + +Do not perform any merging and preserve the original structure written by the developer. + +```rust +use foo::b; +use foo::b::{f, g}; +use foo::{a, c, d::e}; +use qux::{h, i}; +``` + +#### `Crate`: + +Merge imports from the same crate into a single `use` statement. Conversely, imports from different crates are split into separate statements. + +```rust +use foo::{ + a, b, + b::{f, g}, + c, + d::e, +}; +use qux::{h, i}; +``` + +#### `Module`: + +Merge imports from the same module into a single `use` statement. Conversely, imports from different modules are split into separate statements. + +```rust +use foo::b::{f, g}; +use foo::d::e; +use foo::{a, b, c}; +use qux::{h, i}; +``` + ## `merge_imports` -Merge multiple imports into a single nested import. +This option is deprecated. Use `imports_granularity = "Crate"` instead. - **Default value**: `false` - **Possible values**: `true`, `false` -- **Stable**: No (tracking issue: #3362) #### `false` (default): diff --git a/src/config/config_type.rs b/src/config/config_type.rs index d8fd8f78b38..bd4a847e0f1 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -97,6 +97,7 @@ macro_rules! create_config { match stringify!($i) { "max_width" | "use_small_heuristics" => self.0.set_heuristics(), "license_template_path" => self.0.set_license_template(), + "merge_imports" => self.0.set_merge_imports(), &_ => (), } } @@ -156,6 +157,7 @@ macro_rules! create_config { self.set_heuristics(); self.set_license_template(); self.set_ignore(dir); + self.set_merge_imports(); self } @@ -230,14 +232,15 @@ macro_rules! create_config { match key { "max_width" | "use_small_heuristics" => self.set_heuristics(), "license_template_path" => self.set_license_template(), + "merge_imports" => self.set_merge_imports(), &_ => (), } } #[allow(unreachable_pub)] pub fn is_hidden_option(name: &str) -> bool { - const HIDE_OPTIONS: [&str; 4] = - ["verbose", "verbose_diff", "file_lines", "width_heuristics"]; + const HIDE_OPTIONS: [&str; 5] = + ["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"]; HIDE_OPTIONS.contains(&name) } @@ -309,6 +312,22 @@ macro_rules! create_config { self.ignore.2.add_prefix(dir); } + fn set_merge_imports(&mut self) { + if self.was_set().merge_imports() { + eprintln!( + "Warning: the `merge_imports` option is deprecated. \ + Use `imports_granularity=Crate` instead" + ); + if !self.was_set().imports_granularity() { + self.imports_granularity.2 = if self.merge_imports() { + ImportGranularity::Crate + } else { + ImportGranularity::Preserve + }; + } + } + } + #[allow(unreachable_pub)] /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { diff --git a/src/config/mod.rs b/src/config/mod.rs index 5b5aed4bc83..a5356fc257e 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -64,9 +64,11 @@ create_config! { // Imports imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports"; imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block"; - merge_imports: bool, false, false, "Merge imports"; + imports_granularity: ImportGranularity, ImportGranularity::Preserve, false, + "Merge or split imports to the provided granularity"; group_imports: GroupImportsTactic, GroupImportsTactic::Preserve, false, "Controls the strategy for how imports are grouped together"; + merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; // Ordering reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically"; @@ -174,6 +176,7 @@ impl PartialConfig { cloned.verbose = None; cloned.width_heuristics = None; cloned.print_misformatted_file_names = None; + cloned.merge_imports = None; ::toml::to_string(&cloned).map_err(ToTomlError) } @@ -407,6 +410,10 @@ mod test { via the --file-lines option"; width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, "'small' heuristic values"; + // merge_imports deprecation + imports_granularity: ImportGranularity, ImportGranularity::Preserve, false, + "Merge imports"; + merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; // Options that are used by the tests stable_option: bool, false, true, "A stable option"; @@ -529,7 +536,7 @@ fn_single_line = false where_single_line = false imports_indent = "Block" imports_layout = "Mixed" -merge_imports = false +imports_granularity = "Preserve" group_imports = "Preserve" reorder_imports = true reorder_modules = true @@ -615,4 +622,53 @@ make_backup = false // assert_eq!(config.unstable_features(), true); // ::std::env::set_var("CFG_RELEASE_CHANNEL", v); // } + + #[cfg(test)] + mod deprecated_option_merge_imports { + use super::*; + + #[test] + fn test_old_option_set() { + let toml = r#" + unstable_features = true + merge_imports = true + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.imports_granularity(), ImportGranularity::Crate); + } + + #[test] + fn test_both_set() { + let toml = r#" + unstable_features = true + merge_imports = true + imports_granularity = "Preserve" + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.imports_granularity(), ImportGranularity::Preserve); + } + + #[test] + fn test_new_overridden() { + let toml = r#" + unstable_features = true + merge_imports = true + "#; + let mut config = Config::from_toml(toml, Path::new("")).unwrap(); + config.override_value("imports_granularity", "Preserve"); + assert_eq!(config.imports_granularity(), ImportGranularity::Preserve); + } + + #[test] + fn test_old_overridden() { + let toml = r#" + unstable_features = true + imports_granularity = "Module" + "#; + let mut config = Config::from_toml(toml, Path::new("")).unwrap(); + config.override_value("merge_imports", "true"); + // no effect: the new option always takes precedence + assert_eq!(config.imports_granularity(), ImportGranularity::Module); + } + } } diff --git a/src/config/options.rs b/src/config/options.rs index e7a6c414354..690e0b73a3e 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,6 +1,7 @@ use std::collections::{hash_set, HashSet}; use std::fmt; use std::path::{Path, PathBuf}; +use std::str::FromStr; use itertools::Itertools; use rustfmt_config_proc_macro::config_type; @@ -111,6 +112,17 @@ pub enum GroupImportsTactic { StdExternalCrate, } +#[config_type] +/// How to merge imports. +pub enum ImportGranularity { + /// Do not merge imports. + Preserve, + /// Use one `use` statement per crate. + Crate, + /// Use one `use` statement per module. + Module, +} + #[config_type] pub enum ReportTactic { Always, @@ -362,7 +374,7 @@ impl IgnoreList { } } -impl ::std::str::FromStr for IgnoreList { +impl FromStr for IgnoreList { type Err = &'static str; fn from_str(_: &str) -> Result { diff --git a/src/imports.rs b/src/imports.rs index d7082d50f88..156bf6da5ab 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -159,7 +159,7 @@ impl UseSegment { } } -pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { +pub(crate) fn merge_use_trees(use_trees: Vec, merge_by: SharedPrefix) -> Vec { let mut result = Vec::with_capacity(use_trees.len()); for use_tree in use_trees { if use_tree.has_comment() || use_tree.attrs.is_some() { @@ -168,8 +168,11 @@ pub(crate) fn merge_use_trees(use_trees: Vec) -> Vec { } for flattened in use_tree.flatten() { - if let Some(tree) = result.iter_mut().find(|tree| tree.share_prefix(&flattened)) { - tree.merge(&flattened); + if let Some(tree) = result + .iter_mut() + .find(|tree| tree.share_prefix(&flattened, merge_by)) + { + tree.merge(&flattened, merge_by); } else { result.push(flattened); } @@ -527,7 +530,7 @@ impl UseTree { } } - fn share_prefix(&self, other: &UseTree) -> bool { + fn share_prefix(&self, other: &UseTree, shared_prefix: SharedPrefix) -> bool { if self.path.is_empty() || other.path.is_empty() || self.attrs.is_some() @@ -535,7 +538,12 @@ impl UseTree { { false } else { - self.path[0] == other.path[0] + match shared_prefix { + SharedPrefix::Crate => self.path[0] == other.path[0], + SharedPrefix::Module => { + self.path[..self.path.len() - 1] == other.path[..other.path.len() - 1] + } + } } } @@ -573,7 +581,7 @@ impl UseTree { } } - fn merge(&mut self, other: &UseTree) { + fn merge(&mut self, other: &UseTree, merge_by: SharedPrefix) { let mut prefix = 0; for (a, b) in self.path.iter().zip(other.path.iter()) { if *a == *b { @@ -582,20 +590,30 @@ impl UseTree { break; } } - if let Some(new_path) = merge_rest(&self.path, &other.path, prefix) { + if let Some(new_path) = merge_rest(&self.path, &other.path, prefix, merge_by) { self.path = new_path; self.span = self.span.to(other.span); } } } -fn merge_rest(a: &[UseSegment], b: &[UseSegment], mut len: usize) -> Option> { +fn merge_rest( + a: &[UseSegment], + b: &[UseSegment], + mut len: usize, + merge_by: SharedPrefix, +) -> Option> { if a.len() == len && b.len() == len { return None; } if a.len() != len && b.len() != len { - if let UseSegment::List(mut list) = a[len].clone() { - merge_use_trees_inner(&mut list, UseTree::from_path(b[len..].to_vec(), DUMMY_SP)); + if let UseSegment::List(ref list) = a[len] { + let mut list = list.clone(); + merge_use_trees_inner( + &mut list, + UseTree::from_path(b[len..].to_vec(), DUMMY_SP), + merge_by, + ); let mut new_path = b[..len].to_vec(); new_path.push(UseSegment::List(list)); return Some(new_path); @@ -622,20 +640,20 @@ fn merge_rest(a: &[UseSegment], b: &[UseSegment], mut len: usize) -> Option, use_tree: UseTree) { - let similar_trees = trees.iter_mut().filter(|tree| tree.share_prefix(&use_tree)); - if use_tree.path.len() == 1 { +fn merge_use_trees_inner(trees: &mut Vec, use_tree: UseTree, merge_by: SharedPrefix) { + let similar_trees = trees + .iter_mut() + .filter(|tree| tree.share_prefix(&use_tree, merge_by)); + if use_tree.path.len() == 1 && merge_by == SharedPrefix::Crate { if let Some(tree) = similar_trees.min_by_key(|tree| tree.path.len()) { if tree.path.len() == 1 { return; } } - } else { - if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { - if tree.path.len() > 1 { - tree.merge(&use_tree); - return; - } + } else if let Some(tree) = similar_trees.max_by_key(|tree| tree.path.len()) { + if tree.path.len() > 1 { + tree.merge(&use_tree, merge_by); + return; } } trees.push(use_tree); @@ -848,6 +866,12 @@ impl Rewrite for UseTree { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum SharedPrefix { + Crate, + Module, +} + #[cfg(test)] mod test { use super::*; @@ -994,44 +1018,72 @@ mod test { } } - #[test] - fn test_use_tree_merge() { - macro_rules! test_merge { - ([$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => { - assert_eq!( - merge_use_trees(parse_use_trees!($($input,)*)), - parse_use_trees!($($output,)*), - ); - } + macro_rules! test_merge { + ($by:ident, [$($input:expr),* $(,)*], [$($output:expr),* $(,)*]) => { + assert_eq!( + merge_use_trees(parse_use_trees!($($input,)*), SharedPrefix::$by), + parse_use_trees!($($output,)*), + ); } + } - test_merge!(["a::b::{c, d}", "a::b::{e, f}"], ["a::b::{c, d, e, f}"]); - test_merge!(["a::b::c", "a::b"], ["a::{b, b::c}"]); - test_merge!(["a::b", "a::b"], ["a::b"]); - test_merge!(["a", "a::b", "a::b::c"], ["a::{self, b, b::c}"]); + #[test] + fn test_use_tree_merge_crate() { test_merge!( + Crate, + ["a::b::{c, d}", "a::b::{e, f}"], + ["a::b::{c, d, e, f}"] + ); + test_merge!(Crate, ["a::b::c", "a::b"], ["a::{b, b::c}"]); + test_merge!(Crate, ["a::b", "a::b"], ["a::b"]); + test_merge!(Crate, ["a", "a::b", "a::b::c"], ["a::{self, b, b::c}"]); + test_merge!( + Crate, ["a", "a::b", "a::b::c", "a::b::c::d"], ["a::{self, b, b::{c, c::d}}"] ); - test_merge!(["a", "a::b", "a::b::c", "a::b"], ["a::{self, b, b::c}"]); test_merge!( + Crate, + ["a", "a::b", "a::b::c", "a::b"], + ["a::{self, b, b::c}"] + ); + test_merge!( + Crate, ["a::{b::{self, c}, d::e}", "a::d::f"], ["a::{b::{self, c}, d::{e, f}}"] ); test_merge!( + Crate, ["a::d::f", "a::{b::{self, c}, d::e}"], ["a::{b::{self, c}, d::{e, f}}"] ); test_merge!( + Crate, ["a::{c, d, b}", "a::{d, e, b, a, f}", "a::{f, g, c}"], ["a::{a, b, c, d, e, f, g}"] ); test_merge!( + Crate, ["a::{self}", "b::{self as foo}"], ["a::{self}", "b::{self as foo}"] ); } + #[test] + fn test_use_tree_merge_module() { + test_merge!( + Module, + ["foo::b", "foo::{a, c, d::e}"], + ["foo::{a, b, c}", "foo::d::e"] + ); + + test_merge!( + Module, + ["foo::{a::b, a::c, d::e, d::f}"], + ["foo::a::{b, c}", "foo::d::{e, f}"] + ); + } + #[test] fn test_use_tree_flatten() { assert_eq!( diff --git a/src/reorder.rs b/src/reorder.rs index d6b6c1963bd..3ac6bc5f5c4 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -11,8 +11,8 @@ use std::cmp::{Ord, Ordering}; use rustc_ast::ast; use rustc_span::{symbol::sym, Span}; -use crate::config::{Config, GroupImportsTactic}; -use crate::imports::{merge_use_trees, UseSegment, UseTree}; +use crate::config::{Config, GroupImportsTactic, ImportGranularity}; +use crate::imports::{merge_use_trees, SharedPrefix, UseSegment, UseTree}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; use crate::rewrite::RewriteContext; @@ -107,8 +107,14 @@ fn rewrite_reorderable_or_regroupable_items( for (item, list_item) in normalized_items.iter_mut().zip(list_items) { item.list_item = Some(list_item.clone()); } - if context.config.merge_imports() { - normalized_items = merge_use_trees(normalized_items); + match context.config.imports_granularity() { + ImportGranularity::Crate => { + normalized_items = merge_use_trees(normalized_items, SharedPrefix::Crate) + } + ImportGranularity::Module => { + normalized_items = merge_use_trees(normalized_items, SharedPrefix::Module) + } + ImportGranularity::Preserve => {} } let mut regrouped_items = match context.config.group_imports() { diff --git a/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs b/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs index 1a60126d2d1..ea7f6280a64 100644 --- a/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs +++ b/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs @@ -1,5 +1,5 @@ // rustfmt-group_imports: StdExternalCrate -// rustfmt-merge_imports: true +// rustfmt-imports_granularity: Crate use chrono::Utc; use super::update::convert_publish_payload; diff --git a/tests/source/configs/imports_layout/merge_mixed.rs b/tests/source/configs/imports_layout/merge_mixed.rs index bd09079a595..477c4aa1684 100644 --- a/tests/source/configs/imports_layout/merge_mixed.rs +++ b/tests/source/configs/imports_layout/merge_mixed.rs @@ -1,5 +1,5 @@ // rustfmt-imports_indent: Block -// rustfmt-merge_imports: true +// rustfmt-imports_granularity: Crate // rustfmt-imports_layout: Mixed use std::{fmt, io, str}; diff --git a/tests/source/imports_granularity_crate.rs b/tests/source/imports_granularity_crate.rs new file mode 100644 index 00000000000..d16681b01b5 --- /dev/null +++ b/tests/source/imports_granularity_crate.rs @@ -0,0 +1,37 @@ +// rustfmt-imports_granularity: Crate + +use a::{c,d,b}; +use a::{d, e, b, a, f}; +use a::{f, g, c}; + +#[doc(hidden)] +use a::b; +use a::c; +use a::d; + +use a::{c, d, e}; +#[doc(hidden)] +use a::b; +use a::d; + +pub use foo::bar; +use foo::{a, b, c}; +pub use foo::foobar; + +use a::{b::{c::*}}; +use a::{b::{c::{}}}; +use a::{b::{c::d}}; +use a::{b::{c::{xxx, yyy, zzz}}}; + +// https://github.com/rust-lang/rustfmt/issues/3808 +use d::{self}; +use e::{self as foo}; +use f::{self, b}; +use g::a; +use g::{self, b}; +use h::{a}; +use i::a::{self}; +use j::{a::{self}}; + +use {k::{a, b}, l::{a, b}}; +use {k::{c, d}, l::{c, d}}; diff --git a/tests/source/imports_granularity_module.rs b/tests/source/imports_granularity_module.rs new file mode 100644 index 00000000000..5a4fad5872b --- /dev/null +++ b/tests/source/imports_granularity_module.rs @@ -0,0 +1,18 @@ +// rustfmt-imports_granularity: Module + +use a::{b::c, d::e}; +use a::{f, g::{h, i}}; +use a::{j::{self, k::{self, l}, m}, n::{o::p, q}}; +pub use a::{r::s, t}; + +#[cfg(test)] +use foo::{a::b, c::d}; +use foo::e; + +use bar::{ + // comment + a::b, + // more comment + c::d, + e::f, +}; diff --git a/tests/source/issue-3750.rs b/tests/source/issue-3750.rs index e11d9ab062a..1189a99d2b6 100644 --- a/tests/source/issue-3750.rs +++ b/tests/source/issue-3750.rs @@ -1,4 +1,4 @@ -// rustfmt-merge_imports: true +// rustfmt-imports_granularity: Crate pub mod foo { pub mod bar { diff --git a/tests/source/merge_imports.rs b/tests/source/merge_imports.rs deleted file mode 100644 index 3838e2c2e07..00000000000 --- a/tests/source/merge_imports.rs +++ /dev/null @@ -1,34 +0,0 @@ -// rustfmt-merge_imports: true - -use a::{c,d,b}; -use a::{d, e, b, a, f}; -use a::{f, g, c}; - -#[doc(hidden)] -use a::b; -use a::c; -use a::d; - -use a::{c, d, e}; -#[doc(hidden)] -use a::b; -use a::d; - -pub use foo::bar; -use foo::{a, b, c}; -pub use foo::foobar; - -use a::{b::{c::*}}; -use a::{b::{c::{}}}; -use a::{b::{c::d}}; -use a::{b::{c::{xxx, yyy, zzz}}}; - -// https://github.com/rust-lang/rustfmt/issues/3808 -use d::{self}; -use e::{self as foo}; -use f::{self, b}; -use g::a; -use g::{self, b}; -use h::{a}; -use i::a::{self}; -use j::{a::{self}}; diff --git a/tests/source/merge_imports_true_compat.rs b/tests/source/merge_imports_true_compat.rs new file mode 100644 index 00000000000..bcea9435129 --- /dev/null +++ b/tests/source/merge_imports_true_compat.rs @@ -0,0 +1,4 @@ +// rustfmt-merge_imports: true + +use a::b; +use a::c; \ No newline at end of file diff --git a/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs b/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs index a3d99eb907e..5e4064dd811 100644 --- a/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs +++ b/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs @@ -1,5 +1,5 @@ // rustfmt-group_imports: StdExternalCrate -// rustfmt-merge_imports: true +// rustfmt-imports_granularity: Crate use alloc::{alloc::Layout, vec::Vec}; use core::f32; use std::sync::Arc; diff --git a/tests/target/configs/imports_layout/merge_mixed.rs b/tests/target/configs/imports_layout/merge_mixed.rs index 2200d7dec6d..bc0da92fffb 100644 --- a/tests/target/configs/imports_layout/merge_mixed.rs +++ b/tests/target/configs/imports_layout/merge_mixed.rs @@ -1,5 +1,5 @@ // rustfmt-imports_indent: Block -// rustfmt-merge_imports: true +// rustfmt-imports_granularity: Crate // rustfmt-imports_layout: Mixed use std::{fmt, io, str, str::FromStr}; diff --git a/tests/target/imports_granularity_crate.rs b/tests/target/imports_granularity_crate.rs new file mode 100644 index 00000000000..d75906d30f1 --- /dev/null +++ b/tests/target/imports_granularity_crate.rs @@ -0,0 +1,28 @@ +// rustfmt-imports_granularity: Crate + +use a::{a, b, c, d, e, f, g}; + +#[doc(hidden)] +use a::b; +use a::{c, d}; + +#[doc(hidden)] +use a::b; +use a::{c, d, e}; + +use foo::{a, b, c}; +pub use foo::{bar, foobar}; + +use a::b::c::{d, xxx, yyy, zzz, *}; + +// https://github.com/rust-lang/rustfmt/issues/3808 +use d::{self}; +use e::{self as foo}; +use f::{self, b}; +use g::{self, a, b}; +use h::a; +use i::a::{self}; +use j::a::{self}; + +use k::{a, b, c, d}; +use l::{a, b, c, d}; diff --git a/tests/target/imports_granularity_module.rs b/tests/target/imports_granularity_module.rs new file mode 100644 index 00000000000..9c1387c466a --- /dev/null +++ b/tests/target/imports_granularity_module.rs @@ -0,0 +1,20 @@ +// rustfmt-imports_granularity: Module + +use a::b::c; +use a::d::e; +use a::f; +use a::g::{h, i}; +use a::j::k::{self, l}; +use a::j::{self, m}; +use a::n::o::p; +use a::n::q; +pub use a::r::s; +pub use a::t; + +use foo::e; +#[cfg(test)] +use foo::{a::b, c::d}; + +use bar::a::b; +use bar::c::d; +use bar::e::f; diff --git a/tests/target/issue-3750.rs b/tests/target/issue-3750.rs index 93d4dc6df25..6875f8d3897 100644 --- a/tests/target/issue-3750.rs +++ b/tests/target/issue-3750.rs @@ -1,4 +1,4 @@ -// rustfmt-merge_imports: true +// rustfmt-imports_granularity: Crate pub mod foo { pub mod bar { diff --git a/tests/target/merge_imports.rs b/tests/target/merge_imports.rs deleted file mode 100644 index f20498212da..00000000000 --- a/tests/target/merge_imports.rs +++ /dev/null @@ -1,25 +0,0 @@ -// rustfmt-merge_imports: true - -use a::{a, b, c, d, e, f, g}; - -#[doc(hidden)] -use a::b; -use a::{c, d}; - -#[doc(hidden)] -use a::b; -use a::{c, d, e}; - -use foo::{a, b, c}; -pub use foo::{bar, foobar}; - -use a::b::c::{d, xxx, yyy, zzz, *}; - -// https://github.com/rust-lang/rustfmt/issues/3808 -use d::{self}; -use e::{self as foo}; -use f::{self, b}; -use g::{self, a, b}; -use h::a; -use i::a::{self}; -use j::a::{self}; diff --git a/tests/target/merge_imports_true_compat.rs b/tests/target/merge_imports_true_compat.rs new file mode 100644 index 00000000000..46cd0a3b8a0 --- /dev/null +++ b/tests/target/merge_imports_true_compat.rs @@ -0,0 +1,3 @@ +// rustfmt-merge_imports: true + +use a::{b, c}; -- cgit 1.4.1-3-g733a5 From 0d60a616abedfc7e509db0b0576601eb5be82763 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Sat, 9 Jan 2021 21:15:03 -0800 Subject: Disable deprecated_option_merge_imports tests on non-nightly --- src/config/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index a5356fc257e..dfce7977bfe 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -629,6 +629,9 @@ make_backup = false #[test] fn test_old_option_set() { + if !crate::is_nightly_channel!() { + return; + } let toml = r#" unstable_features = true merge_imports = true @@ -639,6 +642,9 @@ make_backup = false #[test] fn test_both_set() { + if !crate::is_nightly_channel!() { + return; + } let toml = r#" unstable_features = true merge_imports = true @@ -650,6 +656,9 @@ make_backup = false #[test] fn test_new_overridden() { + if !crate::is_nightly_channel!() { + return; + } let toml = r#" unstable_features = true merge_imports = true @@ -661,6 +670,9 @@ make_backup = false #[test] fn test_old_overridden() { + if !crate::is_nightly_channel!() { + return; + } let toml = r#" unstable_features = true imports_granularity = "Module" -- cgit 1.4.1-3-g733a5 From 269584634a7657d1026cee2db1c38d75cebbbd31 Mon Sep 17 00:00:00 2001 From: hafiz <20735482+ayazhafiz@users.noreply.github.com> Date: Sun, 31 May 2020 03:36:08 -0500 Subject: Include constness in impl blocks (#4215) Closes #4084 --- src/items.rs | 2 ++ src/utils.rs | 8 ++++++++ tests/source/impls.rs | 8 ++++++++ tests/target/impls.rs | 8 ++++++++ 4 files changed, 26 insertions(+) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 9f079f15c15..b5e38c58267 100644 --- a/src/items.rs +++ b/src/items.rs @@ -828,6 +828,7 @@ fn format_impl_ref_and_type( unsafety, polarity, defaultness, + constness, ref generics, of_trait: ref trait_ref, ref self_ty, @@ -851,6 +852,7 @@ fn format_impl_ref_and_type( }; let generics_str = rewrite_generics(context, "impl", generics, shape)?; result.push_str(&generics_str); + result.push_str(format_constness_right(constness)); let polarity_str = match polarity { ast::ImplPolarity::Negative(_) => "!", diff --git a/src/utils.rs b/src/utils.rs index bd419b2998b..a3d0ed050e3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -100,6 +100,14 @@ pub(crate) fn format_constness(constness: ast::Const) -> &'static str { } } +#[inline] +pub(crate) fn format_constness_right(constness: ast::Const) -> &'static str { + match constness { + ast::Const::Yes(..) => " const", + ast::Const::No => "", + } +} + #[inline] pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str { match defaultness { diff --git a/tests/source/impls.rs b/tests/source/impls.rs index fde7ad6d017..fb8701989fa 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -160,3 +160,11 @@ impl<'a, 'b, 'c> SomeThing for (&'a mut SomethingLong, &'b mut Someth // #2746 impl<'seq1, 'seq2, 'body, 'scope, Channel> Adc12< Dual, MasterRunningDma<'seq1, 'body, 'scope, Channel>, SlaveRunningDma<'seq2, 'body, 'scope>, > where Channel: DmaChannel, {} + +// #4084 +impl const std::default::Default for Struct { + #[inline] + fn default() -> Self { + Self { f: 12.5 } + } +} diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 0777a7ed249..bf63f924a33 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -234,3 +234,11 @@ where Channel: DmaChannel, { } + +// #4084 +impl const std::default::Default for Struct { + #[inline] + fn default() -> Self { + Self { f: 12.5 } + } +} -- cgit 1.4.1-3-g733a5 From c0fede355cf274cb6d71e1f870f752f30e0f23cd Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 27 May 2020 12:31:14 +0900 Subject: Use the span after generics and where clause (#4208) --- src/items.rs | 5 +++-- tests/source/const_generics.rs | 4 ++++ tests/target/const_generics.rs | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index b5e38c58267..70cd7faad8b 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1141,14 +1141,15 @@ pub(crate) fn format_trait( } result.push('{'); - let snippet = context.snippet(item.span); + let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi()); + let snippet = context.snippet(block_span); let open_pos = snippet.find_uncommented("{")? + 1; let outer_indent_str = offset.block_only().to_string_with_newline(context.config); if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = offset.block_only().block_indent(context.config); - visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); + visitor.last_pos = block_span.lo() + BytePos(open_pos as u32); for item in trait_items { visitor.visit_trait_item(item); diff --git a/tests/source/const_generics.rs b/tests/source/const_generics.rs index 420810b92ea..07ef99107a8 100644 --- a/tests/source/const_generics.rs +++ b/tests/source/const_generics.rs @@ -30,3 +30,7 @@ fn foo() { } type Foo = [i32; N + 1]; + +pub trait Foo: Bar<{Baz::COUNT}> { + const ASD: usize; +} diff --git a/tests/target/const_generics.rs b/tests/target/const_generics.rs index f60b7eb0880..f49c5a1bb10 100644 --- a/tests/target/const_generics.rs +++ b/tests/target/const_generics.rs @@ -22,3 +22,7 @@ fn foo() { } type Foo = [i32; N + 1]; + +pub trait Foo: Bar<{ Baz::COUNT }> { + const ASD: usize; +} -- cgit 1.4.1-3-g733a5 From f8deed3a3a1431bc40e7f9165c30de11ca9d2532 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Tue, 7 Jul 2020 07:31:09 -0700 Subject: Include const generic type bounds in their spans Closes #4310 --- src/items.rs | 3 +-- src/spanned.rs | 3 ++- tests/target/issue-4310.rs | 9 +++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 tests/target/issue-4310.rs (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 70cd7faad8b..f1d191783c9 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2217,11 +2217,10 @@ fn rewrite_fn_base( // Skip `pub(crate)`. let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span); - // A conservative estimation, to goal is to be over all parens in generics + // A conservative estimation, the goal is to be over all parens in generics let params_start = fn_sig .generics .params - .iter() .last() .map_or(lo_after_visibility, |param| param.span().hi()); let params_end = if fd.inputs.is_empty() { diff --git a/src/spanned.rs b/src/spanned.rs index 9e3658dd22f..1f6d0023e68 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -132,7 +132,8 @@ impl Spanned for ast::GenericParam { }; let ty_hi = if let ast::GenericParamKind::Type { default: Some(ref ty), - } = self.kind + } + | ast::GenericParamKind::Const { ref ty, .. } = self.kind { ty.span().hi() } else { diff --git a/tests/target/issue-4310.rs b/tests/target/issue-4310.rs new file mode 100644 index 00000000000..6cf494fc5b8 --- /dev/null +++ b/tests/target/issue-4310.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] + +fn foo< + const N: [u8; { + struct Inner<'a>(&'a ()); + 3 + }], +>() { +} -- cgit 1.4.1-3-g733a5 From 5e14f760c5064a3993c487198ad2cf4a748a2c96 Mon Sep 17 00:00:00 2001 From: Sean Klein Date: Tue, 19 Jan 2021 13:40:58 -0500 Subject: fix: Avoid incorrect global 'cfg_if' Symbol interning Fixes #4656 --- src/lib.rs | 1 + src/modules.rs | 6 +---- src/test/mod.rs | 38 +++++++++++++++++++++++++++++ tests/source/issue-4656/format_me_please.rs | 2 ++ tests/source/issue-4656/lib.rs | 7 ++++++ tests/source/issue-4656/lib2.rs | 3 +++ tests/target/issue-4656/format_me_please.rs | 1 + tests/target/issue-4656/lib.rs | 7 ++++++ tests/target/issue-4656/lib2.rs | 3 +++ 9 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 tests/source/issue-4656/format_me_please.rs create mode 100644 tests/source/issue-4656/lib.rs create mode 100644 tests/source/issue-4656/lib2.rs create mode 100644 tests/target/issue-4656/format_me_please.rs create mode 100644 tests/target/issue-4656/lib.rs create mode 100644 tests/target/issue-4656/lib2.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index da83b285a21..370b7eb6c4e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ #[macro_use] extern crate derive_new; +#[cfg(test)] #[macro_use] extern crate lazy_static; #[macro_use] diff --git a/src/modules.rs b/src/modules.rs index b4d2f1fc822..cadcd30a3d2 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -21,10 +21,6 @@ mod visitor; type FileModMap<'ast> = BTreeMap>; -lazy_static! { - static ref CFG_IF: Symbol = Symbol::intern("cfg_if"); -} - /// Represents module with its inner attributes. #[derive(Debug, Clone)] pub(crate) struct Module<'a> { @@ -480,7 +476,7 @@ fn is_cfg_if(item: &ast::Item) -> bool { match item.kind { ast::ItemKind::MacCall(ref mac) => { if let Some(first_segment) = mac.path.segments.first() { - if first_segment.ident.name == *CFG_IF { + if first_segment.ident.name == Symbol::intern("cfg_if") { return true; } } diff --git a/src/test/mod.rs b/src/test/mod.rs index 9b3ca717152..142de28f330 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -372,6 +372,44 @@ fn self_tests() { ); } +#[test] +fn format_files_find_new_files_via_cfg_if() { + init_log(); + run_test_with(&TestSetting::default(), || { + // To repro issue-4656, it is necessary that these files are parsed + // as a part of the same session (hence this separate test runner). + let files = vec![ + Path::new("tests/source/issue-4656/lib2.rs"), + Path::new("tests/source/issue-4656/lib.rs"), + ]; + + let config = Config::default(); + let mut session = Session::::new(config, None); + + let mut write_result = HashMap::new(); + for file in files { + assert!(file.exists()); + let result = session.format(Input::File(file.into())).unwrap(); + assert!(!session.has_formatting_errors()); + assert!(!result.has_warnings()); + let mut source_file = SourceFile::new(); + mem::swap(&mut session.source_file, &mut source_file); + + for (filename, text) in source_file { + if let FileName::Real(ref filename) = filename { + write_result.insert(filename.to_owned(), text); + } + } + } + assert_eq!( + 3, + write_result.len(), + "Should have uncovered an extra file (format_me_please.rs) via lib.rs" + ); + assert!(handle_result(write_result, None).is_ok()); + }); +} + #[test] fn stdin_formatting_smoke_test() { init_log(); diff --git a/tests/source/issue-4656/format_me_please.rs b/tests/source/issue-4656/format_me_please.rs new file mode 100644 index 00000000000..7de75301649 --- /dev/null +++ b/tests/source/issue-4656/format_me_please.rs @@ -0,0 +1,2 @@ + +pub fn hello( ) { } diff --git a/tests/source/issue-4656/lib.rs b/tests/source/issue-4656/lib.rs new file mode 100644 index 00000000000..5dac91b8aab --- /dev/null +++ b/tests/source/issue-4656/lib.rs @@ -0,0 +1,7 @@ +extern crate cfg_if; + +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod format_me_please; + } +} diff --git a/tests/source/issue-4656/lib2.rs b/tests/source/issue-4656/lib2.rs new file mode 100644 index 00000000000..b17fffc58e1 --- /dev/null +++ b/tests/source/issue-4656/lib2.rs @@ -0,0 +1,3 @@ +its_a_macro! { + // Contents +} diff --git a/tests/target/issue-4656/format_me_please.rs b/tests/target/issue-4656/format_me_please.rs new file mode 100644 index 00000000000..421e195a2fb --- /dev/null +++ b/tests/target/issue-4656/format_me_please.rs @@ -0,0 +1 @@ +pub fn hello() {} diff --git a/tests/target/issue-4656/lib.rs b/tests/target/issue-4656/lib.rs new file mode 100644 index 00000000000..5dac91b8aab --- /dev/null +++ b/tests/target/issue-4656/lib.rs @@ -0,0 +1,7 @@ +extern crate cfg_if; + +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod format_me_please; + } +} diff --git a/tests/target/issue-4656/lib2.rs b/tests/target/issue-4656/lib2.rs new file mode 100644 index 00000000000..b17fffc58e1 --- /dev/null +++ b/tests/target/issue-4656/lib2.rs @@ -0,0 +1,3 @@ +its_a_macro! { + // Contents +} -- cgit 1.4.1-3-g733a5 From 384ba68d649ae83ee9817d70742841f6e8f07a35 Mon Sep 17 00:00:00 2001 From: Michael Morgan Date: Tue, 12 Jan 2021 14:29:11 -0500 Subject: Add imports_granularity="Item". This option splits all imports into their own `use` statement. --- Configurations.md | 17 ++++++++++++++- src/config/options.rs | 2 ++ src/imports.rs | 37 ++++++++++++++++++++++++++++++++ src/reorder.rs | 15 ++++++------- tests/source/imports_granularity_item.rs | 6 ++++++ tests/target/imports_granularity_item.rs | 13 +++++++++++ 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 tests/source/imports_granularity_item.rs create mode 100644 tests/target/imports_granularity_item.rs (limited to 'src') diff --git a/Configurations.md b/Configurations.md index e4f84b23082..c92be5df010 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1620,7 +1620,7 @@ pub enum Foo {} How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity. - **Default value**: `Preserve` -- **Possible values**: `Preserve`, `Crate`, `Module` +- **Possible values**: `Preserve`, `Crate`, `Module`, `Item` - **Stable**: No #### `Preserve` (default): @@ -1659,6 +1659,21 @@ use foo::{a, b, c}; use qux::{h, i}; ``` +#### `Item`: + +Flatten imports so that each has its own `use` statement. + +```rust +use foo::a; +use foo::b; +use foo::b::f; +use foo::b::g; +use foo::c; +use foo::d::e; +use qux::h; +use qux::i; +``` + ## `merge_imports` This option is deprecated. Use `imports_granularity = "Crate"` instead. diff --git a/src/config/options.rs b/src/config/options.rs index 690e0b73a3e..c0491630c00 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -121,6 +121,8 @@ pub enum ImportGranularity { Crate, /// Use one `use` statement per module. Module, + /// Use one `use` statement per imported item. + Item, } #[config_type] diff --git a/src/imports.rs b/src/imports.rs index 156bf6da5ab..0f635fe1ccb 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -181,6 +181,24 @@ pub(crate) fn merge_use_trees(use_trees: Vec, merge_by: SharedPrefix) - result } +pub(crate) fn flatten_use_trees(use_trees: Vec) -> Vec { + use_trees + .into_iter() + .flat_map(UseTree::flatten) + .map(|mut tree| { + // If a path ends in `::self`, rewrite it to `::{self}`. + if let Some(UseSegment::Slf(..)) = tree.path.last() { + let self_segment = tree.path.pop().unwrap(); + tree.path.push(UseSegment::List(vec![UseTree::from_path( + vec![self_segment], + DUMMY_SP, + )])); + } + tree + }) + .collect() +} + impl fmt::Debug for UseTree { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) @@ -1084,6 +1102,25 @@ mod test { ); } + #[test] + fn test_flatten_use_trees() { + assert_eq!( + flatten_use_trees(parse_use_trees!["foo::{a::{b, c}, d::e}"]), + parse_use_trees!["foo::a::b", "foo::a::c", "foo::d::e"] + ); + + assert_eq!( + flatten_use_trees(parse_use_trees!["foo::{self, a, b::{c, d}, e::*}"]), + parse_use_trees![ + "foo::{self}", + "foo::a", + "foo::b::c", + "foo::b::d", + "foo::e::*" + ] + ); + } + #[test] fn test_use_tree_flatten() { assert_eq!( diff --git a/src/reorder.rs b/src/reorder.rs index 3ac6bc5f5c4..ac65ff2c108 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -12,7 +12,7 @@ use rustc_ast::ast; use rustc_span::{symbol::sym, Span}; use crate::config::{Config, GroupImportsTactic, ImportGranularity}; -use crate::imports::{merge_use_trees, SharedPrefix, UseSegment, UseTree}; +use crate::imports::{flatten_use_trees, merge_use_trees, SharedPrefix, UseSegment, UseTree}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; use crate::rewrite::RewriteContext; @@ -107,15 +107,14 @@ fn rewrite_reorderable_or_regroupable_items( for (item, list_item) in normalized_items.iter_mut().zip(list_items) { item.list_item = Some(list_item.clone()); } - match context.config.imports_granularity() { - ImportGranularity::Crate => { - normalized_items = merge_use_trees(normalized_items, SharedPrefix::Crate) - } + normalized_items = match context.config.imports_granularity() { + ImportGranularity::Crate => merge_use_trees(normalized_items, SharedPrefix::Crate), ImportGranularity::Module => { - normalized_items = merge_use_trees(normalized_items, SharedPrefix::Module) + merge_use_trees(normalized_items, SharedPrefix::Module) } - ImportGranularity::Preserve => {} - } + ImportGranularity::Item => flatten_use_trees(normalized_items), + ImportGranularity::Preserve => normalized_items, + }; let mut regrouped_items = match context.config.group_imports() { GroupImportsTactic::Preserve => vec![normalized_items], diff --git a/tests/source/imports_granularity_item.rs b/tests/source/imports_granularity_item.rs new file mode 100644 index 00000000000..d0e94df66ae --- /dev/null +++ b/tests/source/imports_granularity_item.rs @@ -0,0 +1,6 @@ +// rustfmt-imports_granularity: Item + +use a::{b, c, d}; +use a::{f::g, h::{i, j}}; +use a::{l::{self, m, n::o, p::*}}; +use a::q::{self}; diff --git a/tests/target/imports_granularity_item.rs b/tests/target/imports_granularity_item.rs new file mode 100644 index 00000000000..eace785e670 --- /dev/null +++ b/tests/target/imports_granularity_item.rs @@ -0,0 +1,13 @@ +// rustfmt-imports_granularity: Item + +use a::b; +use a::c; +use a::d; +use a::f::g; +use a::h::i; +use a::h::j; +use a::l::m; +use a::l::n::o; +use a::l::p::*; +use a::l::{self}; +use a::q::{self}; -- cgit 1.4.1-3-g733a5 From 3e613267161912f81e30fc413584e97b3e9c494a Mon Sep 17 00:00:00 2001 From: vallentin Date: Sun, 17 Jan 2021 18:33:47 +0100 Subject: Fixed semicolon getting moved into comment (fixes #4646) --- src/items.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index f1d191783c9..18688fe3344 100644 --- a/src/items.rs +++ b/src/items.rs @@ -302,7 +302,7 @@ impl<'a> FmtVisitor<'a> { let context = self.get_context(); let mut fn_brace_style = newline_for_brace(self.config, &fn_sig.generics.where_clause); - let (result, force_newline_brace) = + let (result, _, force_newline_brace) = rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style)?; // 2 = ` {` @@ -328,7 +328,7 @@ impl<'a> FmtVisitor<'a> { let span = mk_sp(span.lo(), span.hi() - BytePos(1)); let context = self.get_context(); - let (mut result, _) = rewrite_fn_base( + let (mut result, ends_with_comment, _) = rewrite_fn_base( &context, indent, ident, @@ -337,6 +337,11 @@ impl<'a> FmtVisitor<'a> { FnBraceStyle::None, )?; + // If `result` ends with a comment, then remember to add a newline + if ends_with_comment { + result.push_str(&indent.to_string_with_newline(context.config)); + } + // Re-attach semicolon result.push(';'); @@ -2142,7 +2147,7 @@ fn rewrite_fn_base( fn_sig: &FnSig<'_>, span: Span, fn_brace_style: FnBraceStyle, -) -> Option<(String, bool)> { +) -> Option<(String, bool, bool)> { let mut force_new_line_for_brace = false; let where_clause = &fn_sig.generics.where_clause; @@ -2450,10 +2455,11 @@ fn rewrite_fn_base( result.push_str(&where_clause_str); - force_new_line_for_brace |= last_line_contains_single_line_comment(&result); + let ends_with_comment = last_line_contains_single_line_comment(&result); + force_new_line_for_brace |= ends_with_comment; force_new_line_for_brace |= is_params_multi_lined && context.config.where_single_line() && !where_clause_str.is_empty(); - Some((result, force_new_line_for_brace)) + Some((result, ends_with_comment, force_new_line_for_brace)) } /// Kind of spaces to put before `where`. @@ -3137,7 +3143,7 @@ impl Rewrite for ast::ForeignItem { span, FnBraceStyle::None, ) - .map(|(s, _)| format!("{};", s)), + .map(|(s, _, _)| format!("{};", s)), ast::ForeignItemKind::Static(ref ty, mutability, _) => { // FIXME(#21): we're dropping potential comments in between the // function kw here. -- cgit 1.4.1-3-g733a5 From bd4dc36c4eb73a776143d51d15770d3060954d28 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 6 Jan 2021 20:25:11 -0600 Subject: refactor: cleanup block check for statements --- src/expr.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 71446ce1ab0..9c5876ce647 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1173,6 +1173,13 @@ pub(crate) fn is_simple_block_stmt( && attrs.map_or(true, |a| a.is_empty()) } +fn block_has_statements(block: &ast::Block) -> bool { + block + .stmts + .iter() + .any(|stmt| !matches!(stmt.kind, ast::StmtKind::Empty)) +} + /// Checks whether a block contains no statements, expressions, comments, or /// inner attributes. pub(crate) fn is_empty_block( @@ -1180,7 +1187,7 @@ pub(crate) fn is_empty_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, ) -> bool { - block.stmts.is_empty() + !block_has_statements(&block) && !block_contains_comment(context, block) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } -- cgit 1.4.1-3-g733a5 From c13d2452c058a32d9f9c97d4d44d45b644621d8b Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 27 Jan 2021 19:46:32 -0600 Subject: chore: backport some empty block check fixes --- src/expr.rs | 2 +- tests/source/issue_3868.rs | 13 +++++++++++++ tests/target/issue_3868.rs | 9 +++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue_3868.rs create mode 100644 tests/target/issue_3868.rs (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 9c5876ce647..7dfa4d57b13 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -429,7 +429,7 @@ fn rewrite_empty_block( prefix: &str, shape: Shape, ) -> Option { - if !block.stmts.is_empty() { + if block_has_statements(&block) { return None; } diff --git a/tests/source/issue_3868.rs b/tests/source/issue_3868.rs new file mode 100644 index 00000000000..6c46c3c9e18 --- /dev/null +++ b/tests/source/issue_3868.rs @@ -0,0 +1,13 @@ +fn foo() { + ; +} + +fn bar() { + for _ in 0..1 { + ; + } +} + +fn baz() { + (); + } \ No newline at end of file diff --git a/tests/target/issue_3868.rs b/tests/target/issue_3868.rs new file mode 100644 index 00000000000..06724135928 --- /dev/null +++ b/tests/target/issue_3868.rs @@ -0,0 +1,9 @@ +fn foo() {} + +fn bar() { + for _ in 0..1 {} +} + +fn baz() { + (); +} -- cgit 1.4.1-3-g733a5 From b8f318c303119c7048f898961f0b150e062f3a91 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 28 Jan 2021 19:14:44 -0600 Subject: fix: don't insert trailing comma on struct lit rest in mac def --- src/expr.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 7dfa4d57b13..33add30c7c6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1629,7 +1629,10 @@ fn rewrite_struct_lit<'a>( nested_shape, tactic, context, - force_no_trailing_comma || has_base || !context.use_block_indent(), + force_no_trailing_comma + || has_base + || !context.use_block_indent() + || matches!(struct_rest, ast::StructRest::Rest(_)), ); write_list(&item_vec, &fmt)? -- cgit 1.4.1-3-g733a5 From 58ac85b58e96d43e20f9cd9e00be62769b649927 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 31 Jan 2021 16:08:00 -0600 Subject: deps: bump rustc-ap crates to v701.0.0 --- Cargo.lock | 83 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 16 +++++----- src/macros.rs | 4 +-- src/syntux/parser.rs | 7 +++-- 4 files changed, 56 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ce45f679f11..1251dd4e378 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -878,18 +878,18 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_arena" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb953bea2006184c8f01a6fd3ed51658c73380992a9aefc113e8d32ece6b7516" +checksum = "3d38617318fc3f9e4af4337d0050fde5b84f9beddccb958848d792d4edde8778" dependencies = [ "smallvec", ] [[package]] name = "rustc-ap-rustc_ast" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94da60fa49b2f60d2539e8823cf2b4d4e61583ba4ee796b8289e12f017d3dc5b" +checksum = "766e6b4657e76f385df0ee3d8b5e2e9c69ee3f83f04d078c89481a698c8f681b" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", @@ -904,9 +904,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_passes" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9f9eaaee223832187a398abe0f9cb8bc4e5cd538322d8f3864aea65239c79e" +checksum = "3671911e1bcc6eb68d79513e9b7e19c451e809258a7216b31107c69bc62121fd" dependencies = [ "itertools 0.9.0", "rustc-ap-rustc_ast", @@ -923,21 +923,20 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_ast_pretty" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302b43429c62efc43b159b1f8ab94c8b517fb553cbae854c3fcf34e01c36accb" +checksum = "8626407c0f378925f9b30ab8712caf0ff27576895cb791d96ce0288790e739c5" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_span", - "rustc-ap-rustc_target", "tracing", ] [[package]] name = "rustc-ap-rustc_attr" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cbd78cb6f7ca0991478d7f1bc5646b6eca58c37ccbdf70b5d83c490a7c47be7" +checksum = "1fbd2c005491bc0c95300b5c7d7eed0a1239048018a1f73556ec14e5ebd3053a" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", @@ -949,14 +948,13 @@ dependencies = [ "rustc-ap-rustc_serialize", "rustc-ap-rustc_session", "rustc-ap-rustc_span", - "version_check", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b9ebd359b0f21086a88595a25d92dc7e8e5f7b111e41c52bb6c97e2d95fd0bb" +checksum = "6ba2102a9d877154fb276581cd67116899be5cef2119991e3c7be1dab514a665" dependencies = [ "arrayvec 0.5.1", "bitflags", @@ -985,9 +983,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b810fcac4d738c47d7793afe3e0f2e03d5193c36c698b0fbcebfb64e468c06b" +checksum = "ebf9bd7d872bd3179eeeebbcd7befed10abda976dcf0db7d3afc74e68ef9d8d0" dependencies = [ "annotate-snippets 0.8.0", "atty", @@ -1005,9 +1003,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_expand" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5b44aadd09c05a42a21a063e9f2241fd3d9c00c3dd6e474e22c3a3e8274c959" +checksum = "7895c9b0957d5793df4291076b6757fe660787e6cba3a0fa415498e1a31dcced" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", @@ -1028,9 +1026,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_feature" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f4121cb9718c8c1c6350a3aaea619fbbae38fb1aadd3d7305586460babb531" +checksum = "19ac44cfab6d4dc09f93a332556cd65be67be3675179b0583b6df831d7887a77" dependencies = [ "rustc-ap-rustc_data_structures", "rustc-ap-rustc_span", @@ -1038,21 +1036,21 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_fs_util" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb0f36e34fafb725795bef3ec6f414cac34e7ca98e6d25927be36d95ae1c6ac" +checksum = "8a6024b6e161a45c85e12950b939981e8d5235587332e9a703900e719520d8b2" [[package]] name = "rustc-ap-rustc_graphviz" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98402e20e2913016ed54f12aead5c987fe227a0fb31cc720e17ff51c6f32466" +checksum = "2ebcdd50bf977ce1c9b6f646f50fb8677d87c8fa66796fd3f5cb9c28079515c4" [[package]] name = "rustc-ap-rustc_index" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91408d727f73f682cd8ae836d762c8dab0ed4e81994ced03aa1edcee3b99a4" +checksum = "51286a5d6f25a31a2f258af12ade26e3d9e579b9661e0b153deec988a86dbde8" dependencies = [ "arrayvec 0.5.1", "rustc-ap-rustc_macros", @@ -1061,32 +1059,33 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_lexer" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67adbe260a0a11910624d6d28c0304fcf7b063e666682111005c83b09f73429d" +checksum = "3601c20fc378d11e965fb1f670cf8bad1ef5164fe4ec8cbb7c57fa9d656f2541" dependencies = [ "unicode-xid", ] [[package]] name = "rustc-ap-rustc_lint_defs" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf11d0646da7bd136fbca53834afcc3760fbfc20fa4875e139b3ada41ec53a5" +checksum = "d92f9f53a0f6976216bc94fd5380686d401852b8792c977ade52a6e9c3b0fcb9" dependencies = [ "rustc-ap-rustc_ast", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_macros", "rustc-ap-rustc_serialize", "rustc-ap-rustc_span", + "rustc-ap-rustc_target", "tracing", ] [[package]] name = "rustc-ap-rustc_macros" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c454b10b66750ffd9bfd7d53b0f30eaba1462356e9ac91f0d037cb0556dc7681" +checksum = "ff03d3d0e4edadc7beee5ee825b9503741ac021ce9d25999041a0947bb3a28e8" dependencies = [ "proc-macro2", "quote", @@ -1096,9 +1095,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_parse" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d03f423948137a8370a88447382a18015d47a273268e3ead2d0a987c3b14070" +checksum = "6e98331237f2b6e98bc239d2fc3b2b57e7299199dbd6d4bfaed9c2ef89d6c2ab" dependencies = [ "bitflags", "rustc-ap-rustc_ast", @@ -1116,9 +1115,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_serialize" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ed5df71bd37d1e179b4bbedf77db76c9e0eb2e03159c58a691adbf29f74682" +checksum = "277c75e732e238e36e3233da40be3ac865e5e076c2900a3ee3367cf1aceb90a2" dependencies = [ "indexmap", "smallvec", @@ -1126,9 +1125,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_session" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e3b92b51fad25a897b23ec98961126aea038abeab8d47989f774f7727016b5e" +checksum = "ac486189586c396b4c88b744f27e3f88776f1b9d1a6c0d612db56b54df0817d4" dependencies = [ "bitflags", "getopts", @@ -1148,9 +1147,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_span" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98273206d8a571c780f233f3391ea30e29c5e75ecdc60335ccef346046e1953" +checksum = "9414e05aeef20a513b9e042c9128772bde4db8cc972d5dc2fa126ca26f548e07" dependencies = [ "cfg-if 0.1.10", "md-5", @@ -1168,9 +1167,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "697.0.0" +version = "701.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ce81fe0130e61112db5f3b2db6b21d407e4b14ae467ab9637f4696cc340ad1" +checksum = "5f447c83857779edde1b11752e480563cd798e2284e8634864d31982b8e42de6" dependencies = [ "bitflags", "rustc-ap-rustc_data_structures", diff --git a/Cargo.toml b/Cargo.toml index 6ed7608eb18..2cb787f15b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,11 +66,11 @@ rustc-workspace-hack = "1.0.0" [dependencies.rustc_ast] package = "rustc-ap-rustc_ast" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_ast_pretty] package = "rustc-ap-rustc_ast_pretty" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" @@ -78,24 +78,24 @@ version = "697.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_errors] package = "rustc-ap-rustc_errors" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_expand] package = "rustc-ap-rustc_expand" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_parse] package = "rustc-ap-rustc_parse" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_session] package = "rustc-ap-rustc_session" -version = "697.0.0" +version = "701.0.0" [dependencies.rustc_span] package = "rustc-ap-rustc_span" -version = "697.0.0" +version = "701.0.0" diff --git a/src/macros.rs b/src/macros.rs index 119ae61d8dd..1abb1cd9e13 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -16,7 +16,7 @@ use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; use rustc_ast::tokenstream::{Cursor, LazyTokenStream, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{ForceCollect, Parser}; use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS}; use rustc_span::{ symbol::{self, kw}, @@ -138,7 +138,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { // `parse_item` returns `Option>`. parse_macro_arg!( Item, - |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_item(ForceCollect::No), |x: Option>| x ); diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index c8d427478dc..6b70d83ceb9 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -4,7 +4,10 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; use rustc_errors::Diagnostic; -use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; +use rustc_parse::{ + new_parser_from_file, + parser::{ForceCollect, Parser as RawParser}, +}; use rustc_span::{sym, symbol::kw, Span}; use crate::attr::first_attr_value_str_by_name; @@ -247,7 +250,7 @@ impl<'a> Parser<'a> { while parser.token != TokenKind::CloseDelim(DelimToken::Brace) && parser.token.kind != TokenKind::Eof { - let item = match parser.parse_item() { + let item = match parser.parse_item(ForceCollect::No) { Ok(Some(item_ptr)) => item_ptr.into_inner(), Ok(None) => continue, Err(mut err) => { -- cgit 1.4.1-3-g733a5 From 9ed75111e2e859fcc3511e58eb26416f436043a5 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 6 Feb 2021 15:13:14 -0600 Subject: deps: apply rustc-ap v705 changes to itemkind variants --- src/items.rs | 140 ++++++++++++++++++++-------------------- src/visitor.rs | 199 +++++++++++++++++++++++++++++++-------------------------- 2 files changed, 177 insertions(+), 162 deletions(-) (limited to 'src') diff --git a/src/items.rs b/src/items.rs index 18688fe3344..10654a2a5ac 100644 --- a/src/items.rs +++ b/src/items.rs @@ -618,8 +618,8 @@ impl<'a> FmtVisitor<'a> { use crate::ast::AssocItemKind::*; fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool { match (a, b) { - (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty)) - if both_type(lty, rty) || both_opaque(lty, rty) => + (TyAlias(lty), TyAlias(rty)) + if both_type(<y.3, &rty.3) || both_opaque(<y.3, &rty.3) => { false } @@ -629,8 +629,8 @@ impl<'a> FmtVisitor<'a> { } buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) { - (TyAlias(_, _, _, ref lty), TyAlias(_, _, _, ref rty)) - if both_type(lty, rty) || both_opaque(lty, rty) => + (TyAlias(lty), TyAlias(rty)) + if both_type(<y.3, &rty.3) || both_opaque(<y.3, &rty.3) => { a.ident.as_str().cmp(&b.ident.as_str()) } @@ -638,8 +638,8 @@ impl<'a> FmtVisitor<'a> { a.ident.as_str().cmp(&b.ident.as_str()) } (Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()), - (TyAlias(_, _, _, ref ty), _) if is_type(ty) => Ordering::Less, - (_, TyAlias(_, _, _, ref ty)) if is_type(ty) => Ordering::Greater, + (TyAlias(ty), _) if is_type(&ty.3) => Ordering::Less, + (_, TyAlias(ty)) if is_type(&ty.3) => Ordering::Greater, (TyAlias(..), _) => Ordering::Less, (_, TyAlias(..)) => Ordering::Greater, (Const(..), _) => Ordering::Less, @@ -675,13 +675,13 @@ pub(crate) fn format_impl( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl { - ref generics, - ref self_ty, - ref items, - .. - } = item.kind - { + if let ast::ItemKind::Impl(impl_kind) = &item.kind { + let ast::ImplKind { + ref generics, + ref self_ty, + ref items, + .. + } = **impl_kind; let mut result = String::with_capacity(128); let ref_and_type = format_impl_ref_and_type(context, item, offset)?; let sep = offset.to_string_with_newline(context.config); @@ -829,17 +829,17 @@ fn format_impl_ref_and_type( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Impl { - unsafety, - polarity, - defaultness, - constness, - ref generics, - of_trait: ref trait_ref, - ref self_ty, - .. - } = item.kind - { + if let ast::ItemKind::Impl(impl_kind) = &item.kind { + let ast::ImplKind { + unsafety, + polarity, + defaultness, + constness, + ref generics, + of_trait: ref trait_ref, + ref self_ty, + .. + } = **impl_kind; let mut result = String::with_capacity(128); result.push_str(&format_visibility(context, &item.vis)); @@ -1025,14 +1025,9 @@ pub(crate) fn format_trait( item: &ast::Item, offset: Indent, ) -> Option { - if let ast::ItemKind::Trait( - is_auto, - unsafety, - ref generics, - ref generic_bounds, - ref trait_items, - ) = item.kind - { + if let ast::ItemKind::Trait(trait_kind) = &item.kind { + let ast::TraitKind(is_auto, unsafety, ref generics, ref generic_bounds, ref trait_items) = + **trait_kind; let mut result = String::with_capacity(128); let header = format!( "{}{}{}trait ", @@ -3119,31 +3114,35 @@ impl Rewrite for ast::ForeignItem { let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); let item_str = match self.kind { - ast::ForeignItemKind::Fn(defaultness, ref fn_sig, ref generics, Some(ref body)) => { - let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = shape.indent; - visitor.last_pos = self.span.lo(); - let inner_attrs = inner_attributes(&self.attrs); - let fn_ctxt = visit::FnCtxt::Foreign; - visitor.visit_fn( - visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)), - generics, - &fn_sig.decl, - self.span, - defaultness, - Some(&inner_attrs), - ); - Some(visitor.buffer.to_owned()) + ast::ForeignItemKind::Fn(ref fn_kind) => { + let ast::FnKind(defaultness, ref fn_sig, ref generics, ref block) = **fn_kind; + if let Some(ref body) = block { + let mut visitor = FmtVisitor::from_context(context); + visitor.block_indent = shape.indent; + visitor.last_pos = self.span.lo(); + let inner_attrs = inner_attributes(&self.attrs); + let fn_ctxt = visit::FnCtxt::Foreign; + visitor.visit_fn( + visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)), + generics, + &fn_sig.decl, + self.span, + defaultness, + Some(&inner_attrs), + ); + Some(visitor.buffer.to_owned()) + } else { + rewrite_fn_base( + context, + shape.indent, + self.ident, + &FnSig::from_method_sig(&fn_sig, generics, self.vis.clone()), + span, + FnBraceStyle::None, + ) + .map(|(s, _, _)| format!("{};", s)) + } } - ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, None) => rewrite_fn_base( - context, - shape.indent, - self.ident, - &FnSig::from_method_sig(&fn_sig, generics, self.vis.clone()), - span, - FnBraceStyle::None, - ) - .map(|(s, _, _)| format!("{};", s)), ast::ForeignItemKind::Static(ref ty, mutability, _) => { // FIXME(#21): we're dropping potential comments in between the // function kw here. @@ -3158,21 +3157,20 @@ impl Rewrite for ast::ForeignItem { // 1 = ; rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";") } - ast::ForeignItemKind::TyAlias( - _, - ref generics, - ref generic_bounds, - ref type_default, - ) => rewrite_type_alias( - self.ident, - type_default.as_ref(), - generics, - Some(generic_bounds), - &context, - shape.indent, - &self.vis, - self.span, - ), + ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => { + let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) = + **ty_alias_kind; + rewrite_type_alias( + self.ident, + type_default.as_ref(), + generics, + Some(generic_bounds), + &context, + shape.indent, + &self.vis, + self.span, + ) + } ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) } diff --git a/src/visitor.rs b/src/visitor.rs index 15055d46d30..34e8536b7ee 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -481,6 +481,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } }; + // TODO(calebcartwright): consider enabling box_patterns feature gate if should_visit_node_again { match item.kind { ast::ItemKind::Use(ref tree) => self.format_import(item, tree), @@ -538,66 +539,72 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => { self.visit_static(&StaticParts::from_item(item)); } - ast::ItemKind::Fn(defaultness, ref fn_signature, ref generics, Some(ref body)) => { - let inner_attrs = inner_attributes(&item.attrs); - let fn_ctxt = match fn_signature.header.ext { - ast::Extern::None => visit::FnCtxt::Free, - _ => visit::FnCtxt::Foreign, - }; - self.visit_fn( - visit::FnKind::Fn( - fn_ctxt, - item.ident, - &fn_signature, - &item.vis, - Some(body), - ), - generics, - &fn_signature.decl, - item.span, - defaultness, - Some(&inner_attrs), - ) - } - ast::ItemKind::Fn(_, ref fn_signature, ref generics, None) => { - let indent = self.block_indent; - let rewrite = self.rewrite_required_fn( - indent, - item.ident, - &fn_signature, - generics, - item.span, - ); - - self.push_rewrite(item.span, rewrite); - } - ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty { - Some(ty) => { - let rewrite = rewrite_type_alias( - item.ident, - Some(&*ty), + ast::ItemKind::Fn(ref fn_kind) => { + let ast::FnKind(defaultness, ref fn_signature, ref generics, ref block) = + **fn_kind; + if let Some(ref body) = block { + let inner_attrs = inner_attributes(&item.attrs); + let fn_ctxt = match fn_signature.header.ext { + ast::Extern::None => visit::FnCtxt::Free, + _ => visit::FnCtxt::Foreign, + }; + self.visit_fn( + visit::FnKind::Fn( + fn_ctxt, + item.ident, + &fn_signature, + &item.vis, + Some(body), + ), generics, - Some(generic_bounds), - &self.get_context(), - self.block_indent, - &item.vis, + &fn_signature.decl, item.span, - ); - self.push_rewrite(item.span, rewrite); - } - None => { - let rewrite = rewrite_opaque_type( - &self.get_context(), - self.block_indent, + defaultness, + Some(&inner_attrs), + ) + } else { + let indent = self.block_indent; + let rewrite = self.rewrite_required_fn( + indent, item.ident, - generic_bounds, + &fn_signature, generics, - &item.vis, item.span, ); self.push_rewrite(item.span, rewrite); } - }, + } + ast::ItemKind::TyAlias(ref alias_kind) => { + let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref ty) = + **alias_kind; + match ty { + Some(ty) => { + let rewrite = rewrite_type_alias( + item.ident, + Some(&*ty), + generics, + Some(generic_bounds), + &self.get_context(), + self.block_indent, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + None => { + let rewrite = rewrite_opaque_type( + &self.get_context(), + self.block_indent, + item.ident, + generic_bounds, + generics, + &item.vis, + item.span, + ); + self.push_rewrite(item.span, rewrite); + } + } + } ast::ItemKind::GlobalAsm(..) => { let snippet = Some(self.snippet(item.span).to_owned()); self.push_rewrite(item.span, snippet); @@ -627,31 +634,37 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { return; } + // TODO(calebcartwright): consider enabling box_patterns feature gate match ti.kind { ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)), - ast::AssocItemKind::Fn(_, ref sig, ref generics, None) => { - let indent = self.block_indent; - let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, generics, ti.span); - self.push_rewrite(ti.span, rewrite); - } - ast::AssocItemKind::Fn(defaultness, ref sig, ref generics, Some(ref body)) => { - let inner_attrs = inner_attributes(&ti.attrs); - let vis = ast::Visibility { - kind: ast::VisibilityKind::Inherited, - span: DUMMY_SP, - tokens: None, - }; - let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); - self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), - generics, - &sig.decl, - ti.span, - defaultness, - Some(&inner_attrs), - ); + ast::AssocItemKind::Fn(ref fn_kind) => { + let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind; + if let Some(ref body) = block { + let inner_attrs = inner_attributes(&ti.attrs); + let vis = ast::Visibility { + kind: ast::VisibilityKind::Inherited, + span: DUMMY_SP, + tokens: None, + }; + let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); + self.visit_fn( + visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), + generics, + &sig.decl, + ti.span, + defaultness, + Some(&inner_attrs), + ); + } else { + let indent = self.block_indent; + let rewrite = + self.rewrite_required_fn(indent, ti.ident, sig, generics, ti.span); + self.push_rewrite(ti.span, rewrite); + } } - ast::AssocItemKind::TyAlias(_, ref generics, ref generic_bounds, ref type_default) => { + ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { + let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) = + **ty_alias_kind; let rewrite = rewrite_type_alias( ti.ident, type_default.as_ref(), @@ -679,25 +692,29 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } match ii.kind { - ast::AssocItemKind::Fn(defaultness, ref sig, ref generics, Some(ref body)) => { - let inner_attrs = inner_attributes(&ii.attrs); - let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl); - self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)), - generics, - &sig.decl, - ii.span, - defaultness, - Some(&inner_attrs), - ); - } - ast::AssocItemKind::Fn(_, ref sig, ref generics, None) => { - let indent = self.block_indent; - let rewrite = self.rewrite_required_fn(indent, ii.ident, sig, generics, ii.span); - self.push_rewrite(ii.span, rewrite); + ast::AssocItemKind::Fn(ref fn_kind) => { + let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind; + if let Some(ref body) = block { + let inner_attrs = inner_attributes(&ii.attrs); + let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl); + self.visit_fn( + visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)), + generics, + &sig.decl, + ii.span, + defaultness, + Some(&inner_attrs), + ); + } else { + let indent = self.block_indent; + let rewrite = + self.rewrite_required_fn(indent, ii.ident, sig, generics, ii.span); + self.push_rewrite(ii.span, rewrite); + } } ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)), - ast::AssocItemKind::TyAlias(defaultness, ref generics, _, ref ty) => { + ast::AssocItemKind::TyAlias(ref ty_alias_kind) => { + let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind; let rewrite_associated = || { rewrite_associated_impl_type( ii.ident, -- cgit 1.4.1-3-g733a5 From 61709488204bce4f82456d01482e5c31bb9e8b17 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 16 Feb 2021 23:26:01 -0500 Subject: Fix warnings - Fix nightly warning about `format!` - Remove unused functions and fields --- src/comment.rs | 3 ++- src/formatting.rs | 2 +- src/git-rustfmt/main.rs | 3 --- src/syntux/parser.rs | 36 ++++++------------------------------ src/test/mod.rs | 7 +++---- 5 files changed, 12 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 9959ef7fd9e..94d505a1465 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1674,7 +1674,8 @@ fn remove_comment_header(comment: &str) -> &str { } else { assert!( comment.starts_with("/*"), - format!("string '{}' is not a comment", comment) + "string '{}' is not a comment", + comment ); &comment[2..comment.len() - 2] } diff --git a/src/formatting.rs b/src/formatting.rs index 289e58cf693..185b53b3987 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -76,7 +76,7 @@ fn format_project( // Parse the crate. let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); - let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { + let krate = match Parser::parse_crate(input, &parse_session) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) Err(e) => { diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index c90eae3e649..936055e7722 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -127,7 +127,6 @@ fn make_opts() -> Options { struct Config { commits: String, uncommitted: bool, - check: bool, } impl Config { @@ -146,11 +145,9 @@ impl Config { let mut config = Config { commits: "1".to_owned(), uncommitted: false, - check: false, }; if matches.opt_present("c") { - config.check = true; unimplemented!(); } diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 6b70d83ceb9..5c555e06a80 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -12,7 +12,7 @@ use rustc_span::{sym, symbol::kw, Span}; use crate::attr::first_attr_value_str_by_name; use crate::syntux::session::ParseSess; -use crate::{Config, Input}; +use crate::Input; pub(crate) type DirectoryOwnership = rustc_expand::module::DirectoryOwnership; pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess; @@ -31,10 +31,8 @@ pub(crate) struct Parser<'a> { /// A builder for the `Parser`. #[derive(Default)] pub(crate) struct ParserBuilder<'a> { - config: Option<&'a Config>, sess: Option<&'a ParseSess>, input: Option, - directory_ownership: Option, } impl<'a> ParserBuilder<'a> { @@ -48,19 +46,6 @@ impl<'a> ParserBuilder<'a> { self } - pub(crate) fn config(mut self, config: &'a Config) -> ParserBuilder<'a> { - self.config = Some(config); - self - } - - pub(crate) fn directory_ownership( - mut self, - directory_ownership: Option, - ) -> ParserBuilder<'a> { - self.directory_ownership = directory_ownership; - self - } - pub(crate) fn build(self) -> Result, ParserError> { let sess = self.sess.ok_or(ParserError::NoParseSess)?; let input = self.input.ok_or(ParserError::NoInput)?; @@ -157,12 +142,10 @@ impl<'a> Parser<'a> { } pub(crate) fn parse_crate( - config: &'a Config, input: Input, - directory_ownership: Option, sess: &'a ParseSess, ) -> Result { - let krate = Parser::parse_crate_inner(config, input, directory_ownership, sess)?; + let krate = Parser::parse_crate_inner(input, sess)?; if !sess.has_errors() { return Ok(krate); } @@ -175,19 +158,12 @@ impl<'a> Parser<'a> { Err(ParserError::ParseError) } - fn parse_crate_inner( - config: &'a Config, - input: Input, - directory_ownership: Option, - sess: &'a ParseSess, - ) -> Result { - let mut parser = ParserBuilder::default() - .config(config) + fn parse_crate_inner(input: Input, sess: &'a ParseSess) -> Result { + ParserBuilder::default() .input(input) - .directory_ownership(directory_ownership) .sess(sess) - .build()?; - parser.parse_crate_mod() + .build()? + .parse_crate_mod() } fn parse_crate_mod(&mut self) -> Result { diff --git a/src/test/mod.rs b/src/test/mod.rs index 142de28f330..ce56a223f2b 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -133,10 +133,8 @@ fn verify_config_used(path: &Path, config_name: &str) { .map(Result::unwrap) .take_while(|l| l.starts_with("//")) .any(|l| l.starts_with(&format!("// rustfmt-{}", config_name))), - format!( - "config option file {} does not contain expected config name", - path.display() - ) + "config option file {} does not contain expected config name", + path.display() ); } } @@ -884,6 +882,7 @@ fn rustfmt() -> PathBuf { me.push("rustfmt"); assert!( me.is_file() || me.with_extension("exe").is_file(), + "{}", if cfg!(release) { "no rustfmt bin, try running `cargo build --release` before testing" } else { -- cgit 1.4.1-3-g733a5 From 4b0ed96f2eed2e49da2cceba550732ce9e7e461e Mon Sep 17 00:00:00 2001 From: David Bar-On Date: Tue, 16 Feb 2021 16:35:47 +0200 Subject: Fix for issue 4603 about extra macro body indentation (third version) --- src/formatting.rs | 4 ++++ src/lib.rs | 27 +++++++++++++++++++++----- tests/source/issue-4603.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++ tests/target/issue-4603.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 tests/source/issue-4603.rs create mode 100644 tests/target/issue-4603.rs (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index 185b53b3987..e42864a5055 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -331,6 +331,9 @@ pub(crate) struct ReportedErrors { /// Formatted code differs from existing code (--check only). pub(crate) has_diff: bool, + + /// Formatted code missed something, like lost comments or extra trailing space + pub(crate) has_unformatted_code_errors: bool, } impl ReportedErrors { @@ -342,6 +345,7 @@ impl ReportedErrors { self.has_macro_format_failure |= other.has_macro_format_failure; self.has_check_errors |= other.has_check_errors; self.has_diff |= other.has_diff; + self.has_unformatted_code_errors |= other.has_unformatted_code_errors; } } diff --git a/src/lib.rs b/src/lib.rs index 370b7eb6c4e..db48b52f440 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -210,14 +210,22 @@ impl FormatReport { if !new_errors.is_empty() { errs.has_formatting_errors = true; } - if errs.has_operational_errors && errs.has_check_errors { + if errs.has_operational_errors && errs.has_check_errors && errs.has_unformatted_code_errors + { return; } for err in new_errors { match err.kind { - ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace => { + ErrorKind::LineOverflow(..) => { errs.has_operational_errors = true; } + ErrorKind::TrailingWhitespace => { + errs.has_operational_errors = true; + errs.has_unformatted_code_errors = true; + } + ErrorKind::LostComment => { + errs.has_unformatted_code_errors = true; + } ErrorKind::BadIssue(_) | ErrorKind::LicenseCheck | ErrorKind::DeprecatedAttr @@ -294,6 +302,9 @@ fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option< config.set().emit_mode(config::EmitMode::Stdout); config.set().verbose(Verbosity::Quiet); config.set().hide_parse_errors(true); + if is_macro_def { + config.set().error_on_unformatted(true); + } let (formatting_error, result) = { let input = Input::Text(snippet.into()); @@ -302,7 +313,8 @@ fn format_snippet(snippet: &str, config: &Config, is_macro_def: bool) -> Option< ( session.errors.has_macro_format_failure || session.out.as_ref().unwrap().is_empty() && !snippet.is_empty() - || result.is_err(), + || result.is_err() + || (is_macro_def && session.has_unformatted_code_errors()), result, ) }; @@ -477,13 +489,18 @@ impl<'b, T: Write + 'b> Session<'b, T> { self.errors.has_diff } + pub fn has_unformatted_code_errors(&self) -> bool { + self.errors.has_unformatted_code_errors + } + pub fn has_no_errors(&self) -> bool { !(self.has_operational_errors() || self.has_parsing_errors() || self.has_formatting_errors() || self.has_check_errors() - || self.has_diff()) - || self.errors.has_macro_format_failure + || self.has_diff() + || self.has_unformatted_code_errors() + || self.errors.has_macro_format_failure) } } diff --git a/tests/source/issue-4603.rs b/tests/source/issue-4603.rs new file mode 100644 index 00000000000..ba0803e0eca --- /dev/null +++ b/tests/source/issue-4603.rs @@ -0,0 +1,47 @@ +// Formatting when original macro snippet is used + +// Original issue #4603 code +#![feature(or_patterns)] +macro_rules! t_or_f { + () => { + (true // some comment + | false) + }; +} + +// Other test cases variations +macro_rules! RULES { + () => { + ( + xxxxxxx // COMMENT + | yyyyyyy + ) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; +} + +fn main() { + macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; + } +} + +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ | yyyyyyy) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ + | yyyyyyy) + }; +} diff --git a/tests/target/issue-4603.rs b/tests/target/issue-4603.rs new file mode 100644 index 00000000000..e8c368a247f --- /dev/null +++ b/tests/target/issue-4603.rs @@ -0,0 +1,47 @@ +// Formatting when original macro snippet is used + +// Original issue #4603 code +#![feature(or_patterns)] +macro_rules! t_or_f { + () => { + (true // some comment + | false) + }; +} + +// Other test cases variations +macro_rules! RULES { + () => { + ( + xxxxxxx // COMMENT + | yyyyyyy + ) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; +} + +fn main() { + macro_rules! RULES { + () => { + (xxxxxxx // COMMENT + | yyyyyyy) + }; + } +} + +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ | yyyyyyy) + }; +} +macro_rules! RULES { + () => { + (xxxxxxx /* COMMENT */ + | yyyyyyy) + }; +} -- cgit 1.4.1-3-g733a5 From 432e09e89f7e30fd418b43b1473b87c146d90674 Mon Sep 17 00:00:00 2001 From: David Bar-On Date: Fri, 8 Jan 2021 15:56:05 +0200 Subject: Add the use of rewrite_assign_rhs_with_comments to 1.x --- src/comment.rs | 14 ++++++ src/expr.rs | 106 +++++++++++++++++++++++++++------------------ src/items.rs | 15 +++++-- tests/source/issue-4427.rs | 31 +++++++++++++ tests/target/issue-4427.rs | 30 +++++++++++++ 5 files changed, 152 insertions(+), 44 deletions(-) create mode 100644 tests/source/issue-4427.rs create mode 100644 tests/target/issue-4427.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 94d505a1465..0264a90c7d0 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -977,6 +977,7 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle<'_>) -> (&'a s pub(crate) trait FindUncommented { fn find_uncommented(&self, pat: &str) -> Option; + fn find_last_uncommented(&self, pat: &str) -> Option; } impl FindUncommented for str { @@ -1002,6 +1003,19 @@ impl FindUncommented for str { None => Some(self.len() - pat.len()), } } + + fn find_last_uncommented(&self, pat: &str) -> Option { + if let Some(left) = self.find_uncommented(pat) { + let mut result = left; + // add 1 to use find_last_uncommented for &str after pat + while let Some(next) = self[(result + 1)..].find_last_uncommented(pat) { + result += next + 1; + } + Some(result) + } else { + None + } + } } // Returns the first byte position after the first comment. The given string diff --git a/src/expr.rs b/src/expr.rs index 33add30c7c6..4589b57dacb 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -9,8 +9,8 @@ use rustc_span::{BytePos, Span}; use crate::chains::rewrite_chain; use crate::closures; use crate::comment::{ - combine_strs_with_missing_comments, comment_style, contains_comment, recover_comment_removed, - rewrite_comment, rewrite_missing_comment, CharClasses, FindUncommented, + combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, + rewrite_missing_comment, CharClasses, FindUncommented, }; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, Version}; @@ -829,38 +829,16 @@ impl<'a> ControlFlow<'a> { let comments_lo = context .snippet_provider .span_after(self.span, self.connector.trim()); - let missing_comments = if let Some(comment) = - rewrite_missing_comment(mk_sp(comments_lo, expr.span.lo()), cond_shape, context) - { - if !self.connector.is_empty() && !comment.is_empty() { - if comment_style(&comment, false).is_line_comment() || comment.contains("\n") { - let newline = &pat_shape - .indent - .block_indent(context.config) - .to_string_with_newline(context.config); - // An extra space is added when the lhs and rhs are joined - // so we need to remove one space from the end to ensure - // the comment and rhs are aligned. - let mut suffix = newline.as_ref().to_string(); - if !suffix.is_empty() { - suffix.truncate(suffix.len() - 1); - } - format!("{}{}{}", newline, comment, suffix) - } else { - format!(" {}", comment) - } - } else { - comment - } - } else { - "".to_owned() - }; - - let result = format!( - "{}{}{}{}", - matcher, pat_string, self.connector, missing_comments + let comments_span = mk_sp(comments_lo, expr.span.lo()); + return rewrite_assign_rhs_with_comments( + context, + &format!("{}{}{}", matcher, pat_string, self.connector), + expr, + cond_shape, + RhsTactics::Default, + comments_span, + true, ); - return rewrite_assign_rhs(context, result, expr, cond_shape); } let expr_rw = expr.rewrite(context, cond_shape); @@ -1899,14 +1877,13 @@ pub(crate) fn rewrite_assign_rhs, R: Rewrite>( rewrite_assign_rhs_with(context, lhs, ex, shape, RhsTactics::Default) } -pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( +pub(crate) fn rewrite_assign_rhs_expr( context: &RewriteContext<'_>, - lhs: S, + lhs: &str, ex: &R, shape: Shape, rhs_tactics: RhsTactics, ) -> Option { - let lhs = lhs.into(); let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') { shape.indent.width() } else { @@ -1918,22 +1895,67 @@ pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( offset: shape.offset + last_line_width + 1, ..shape }); - let rhs = choose_rhs( + let has_rhs_comment = if let Some(offset) = lhs.find_last_uncommented("=") { + lhs.trim_end().len() > offset + 1 + } else { + false + }; + + choose_rhs( context, ex, orig_shape, ex.rewrite(context, orig_shape), rhs_tactics, - )?; + has_rhs_comment, + ) +} + +pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( + context: &RewriteContext<'_>, + lhs: S, + ex: &R, + shape: Shape, + rhs_tactics: RhsTactics, +) -> Option { + let lhs = lhs.into(); + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?; Some(lhs + &rhs) } +pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite>( + context: &RewriteContext<'_>, + lhs: S, + ex: &R, + shape: Shape, + rhs_tactics: RhsTactics, + between_span: Span, + allow_extend: bool, +) -> Option { + let lhs = lhs.into(); + let contains_comment = contains_comment(context.snippet(between_span)); + let shape = if contains_comment { + shape.block_left(context.config.tab_spaces())? + } else { + shape + }; + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_tactics)?; + + if contains_comment { + let rhs = rhs.trim_start(); + combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend) + } else { + Some(lhs + &rhs) + } +} + fn choose_rhs( context: &RewriteContext<'_>, expr: &R, shape: Shape, orig_rhs: Option, rhs_tactics: RhsTactics, + has_rhs_comment: bool, ) -> Option { match orig_rhs { Some(ref new_str) @@ -1950,13 +1972,14 @@ fn choose_rhs( .indent .block_indent(context.config) .to_string_with_newline(context.config); + let before_space_str = if has_rhs_comment { "" } else { " " }; match (orig_rhs, new_rhs) { (Some(ref orig_rhs), Some(ref new_rhs)) if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape) .is_none() => { - Some(format!(" {}", orig_rhs)) + Some(format!("{}{}", before_space_str, orig_rhs)) } (Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => @@ -1966,10 +1989,11 @@ fn choose_rhs( (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), (None, None) if rhs_tactics == RhsTactics::AllowOverflow => { let shape = shape.infinite_width(); - expr.rewrite(context, shape).map(|s| format!(" {}", s)) + expr.rewrite(context, shape) + .map(|s| format!("{}{}", before_space_str, s)) } (None, None) => None, - (Some(orig_rhs), _) => Some(format!(" {}", orig_rhs)), + (Some(orig_rhs), _) => Some(format!("{}{}", before_space_str, orig_rhs)), } } } diff --git a/src/items.rs b/src/items.rs index 10654a2a5ac..6cdbb686ad8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -17,7 +17,8 @@ use crate::comment::{ use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle, Version}; use crate::expr::{ - is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, RhsTactics, + is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, + rewrite_assign_rhs_with_comments, RhsTactics, }; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; use crate::macros::{rewrite_macro, MacroPosition}; @@ -1822,14 +1823,22 @@ fn rewrite_static( }; if let Some(expr) = static_parts.expr_opt { + let comments_lo = context.snippet_provider.span_after(static_parts.span, "="); + let expr_lo = expr.span.lo(); + let comments_span = mk_sp(comments_lo, expr_lo); + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; let remaining_width = context.budget(offset.block_indent + 1); - rewrite_assign_rhs( + rewrite_assign_rhs_with_comments( context, - lhs, + &lhs, &**expr, Shape::legacy(remaining_width, offset.block_only()), + RhsTactics::Default, + comments_span, + true, ) .and_then(|res| recover_comment_removed(res, static_parts.span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) diff --git a/tests/source/issue-4427.rs b/tests/source/issue-4427.rs new file mode 100644 index 00000000000..e14e039b98f --- /dev/null +++ b/tests/source/issue-4427.rs @@ -0,0 +1,31 @@ +const A: usize = + // Some constant + 2; + +const B: usize = +/* constant */ +3; + +const C : usize + = /* foo */5; + +const D: usize = // baz +/* Some constant */ + /* ba */ + { 3 + // foo + }; +const E: usize= /* foo */5; +const F: usize = +{ + 7 + }; +const G: usize = /* foooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000xx00 */ 5; + const H: usize = /* asdfasdf */ match G > 1 { + true => 1, + false => 3, + }; + + pub static FOO_BAR: Vec = //f + { + vec![]}; diff --git a/tests/target/issue-4427.rs b/tests/target/issue-4427.rs new file mode 100644 index 00000000000..c8a37ead8cb --- /dev/null +++ b/tests/target/issue-4427.rs @@ -0,0 +1,30 @@ +const A: usize = + // Some constant + 2; + +const B: usize = + /* constant */ + 3; + +const C: usize = /* foo */ 5; + +const D: usize = // baz + /* Some constant */ + /* ba */ + { + 3 + // foo + }; +const E: usize = /* foo */ 5; +const F: usize = { 7 }; +const G: usize = + /* foooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000xx00 */ + 5; +const H: usize = /* asdfasdf */ + match G > 1 { + true => 1, + false => 3, + }; + +pub static FOO_BAR: Vec = //f + { vec![] }; -- cgit 1.4.1-3-g733a5 From c3a51111061e65a08ebce05c42e0d89ee1fae83a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 16 Feb 2021 23:33:20 -0500 Subject: Fix some clippy warnings This commit can be replicated with `cargo clippy --fix -Z unstable-options && cargo +nightly-2021-02-10 fmt`. --- src/bin/main.rs | 8 ++++---- src/cargo-fmt/main.rs | 2 -- src/format-diff/main.rs | 3 +-- src/git-rustfmt/main.rs | 1 - 4 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/bin/main.rs b/src/bin/main.rs index 9101c015fb9..56b07222212 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,5 +1,5 @@ use anyhow::{format_err, Result}; -use env_logger; + use io::Error as IoError; use thiserror::Error; @@ -233,7 +233,7 @@ fn execute(opts: &Options) -> Result { let file = PathBuf::from(path); let file = file.canonicalize().unwrap_or(file); - let (config, _) = load_config(Some(file.parent().unwrap()), Some(options.clone()))?; + let (config, _) = load_config(Some(file.parent().unwrap()), Some(options))?; let toml = config.all_options().to_toml()?; io::stdout().write_all(toml.as_bytes())?; @@ -565,7 +565,7 @@ impl GetOptsOptions { options.inline_config = matches .opt_strs("config") .iter() - .flat_map(|config| config.split(",")) + .flat_map(|config| config.split(',')) .map( |key_val| match key_val.char_indices().find(|(_, ch)| *ch == '=') { Some((middle, _)) => { @@ -681,7 +681,7 @@ impl CliOptions for GetOptsOptions { } fn config_path(&self) -> Option<&Path> { - self.config_path.as_ref().map(|p| &**p) + self.config_path.as_deref() } } diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 22aeceeb53b..9062a2952ec 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -2,8 +2,6 @@ #![deny(warnings)] -use cargo_metadata; - use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; use std::env; diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index 8a8bb9356ca..c751932273b 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -4,10 +4,9 @@ #![deny(warnings)] -use env_logger; #[macro_use] extern crate log; -use regex; + use serde::{Deserialize, Serialize}; use serde_json as json; use thiserror::Error; diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 936055e7722..16f5d1dd4f2 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -7,7 +7,6 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; -use env_logger; use getopts::{Matches, Options}; use rustfmt_nightly as rustfmt; -- cgit 1.4.1-3-g733a5 From ca4e9f47b9f6742d6822b85d848db1acc86492b3 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 18 Mar 2021 18:07:54 +0900 Subject: Fix a `legacy_derive_helpers` warning --- src/modules.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/modules.rs b/src/modules.rs index cadcd30a3d2..eaa889bcb3f 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -66,8 +66,8 @@ pub(crate) struct ModResolver<'ast, 'sess> { } /// Represents errors while trying to resolve modules. -#[error("failed to resolve mod `{module}`: {kind}")] #[derive(Debug, Error)] +#[error("failed to resolve mod `{module}`: {kind}")] pub struct ModuleResolutionError { pub(crate) module: String, pub(crate) kind: ModuleResolutionErrorKind, -- cgit 1.4.1-3-g733a5 From cbd83b80836a500ec3b6c5033d5742d504d04542 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 14 Mar 2021 13:15:48 -0500 Subject: chore: add span creation util function --- Cargo.lock | 426 ++++++++++++-------------------------------------------- Cargo.toml | 2 +- src/patterns.rs | 4 +- src/utils.rs | 4 + 4 files changed, 99 insertions(+), 337 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index 0bf7db5aa59..6689d6cfe01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -878,15 +878,6 @@ dependencies = [ "crossbeam-utils 0.6.5", ] -[[package]] -name = "rustc-ap-rustc_arena" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705baf7965088195f2e85d0bc548036d7e6a94973c309819f2ae4540e221ba15" -dependencies = [ - "smallvec", -] - [[package]] name = "rustc-ap-rustc_arena" version = "708.0.0" @@ -896,23 +887,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "rustc-ap-rustc_ast" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5579379dd7e34bb522cbab946df43921f3d6fa587fc9101358db0a26b177b24" -dependencies = [ - "bitflags", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_index 706.0.0", - "rustc-ap-rustc_lexer 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-ap-rustc_span 706.0.0", - "smallvec", - "tracing", -] - [[package]] name = "rustc-ap-rustc_ast" version = "708.0.0" @@ -920,12 +894,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5415b0026ca0198717b04d9a579c941ca34089bc921d3f02cff1b6cf63fa95c9" dependencies = [ "bitflags", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_index 708.0.0", - "rustc-ap-rustc_lexer 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", "smallvec", "tracing", ] @@ -937,26 +911,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1737c6420474739cb89f557ed8d1231f0b6068620fb3c0fd0a09f0dd79aebbb9" dependencies = [ "itertools 0.9.0", - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_ast_pretty 708.0.0", - "rustc-ap-rustc_attr 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_errors 708.0.0", - "rustc-ap-rustc_feature 708.0.0", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_attr", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", "rustc-ap-rustc_parse", - "rustc-ap-rustc_session 708.0.0", - "rustc-ap-rustc_span 708.0.0", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_pretty" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11fe1dbcfbb58ea768a9a05a9df27093b4a8fe03b715d3d96df84ae1093b3859" -dependencies = [ - "rustc-ap-rustc_ast 706.0.0", - "rustc-ap-rustc_span 706.0.0", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", "tracing", ] @@ -966,76 +929,27 @@ version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e86b6a279fd02e57590834a489eb4a4fe31d03c176f755072505977a4d5f202" dependencies = [ - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_span", "tracing", ] -[[package]] -name = "rustc-ap-rustc_attr" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9429e42aaf0b12e133b93411bb8205388fba4fe3dd819199ae52672ad21b81a0" -dependencies = [ - "rustc-ap-rustc_ast 706.0.0", - "rustc-ap-rustc_ast_pretty 706.0.0", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_errors 706.0.0", - "rustc-ap-rustc_feature 706.0.0", - "rustc-ap-rustc_lexer 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-ap-rustc_session 706.0.0", - "rustc-ap-rustc_span 706.0.0", -] - [[package]] name = "rustc-ap-rustc_attr" version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31de4bc77d5fc437a50451ac12d3e2459f6794d8e7f50bd6c0f48ec6744b96f" dependencies = [ - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_ast_pretty 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_errors 708.0.0", - "rustc-ap-rustc_feature 708.0.0", - "rustc-ap-rustc_lexer 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_session 708.0.0", - "rustc-ap-rustc_span 708.0.0", -] - -[[package]] -name = "rustc-ap-rustc_data_structures" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70bc6c6857800146381494c5247d5b86502e4a25a71fea67d2db58f14f22d6ce" -dependencies = [ - "arrayvec 0.5.1", - "bitflags", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.0", - "ena", - "indexmap", - "jobserver", - "libc", - "measureme", - "parking_lot", - "rustc-ap-rustc_graphviz 706.0.0", - "rustc-ap-rustc_index 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-hash", - "rustc-rayon", - "rustc-rayon-core", - "smallvec", - "stable_deref_trait", - "stacker", - "tempfile", - "tracing", - "winapi", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", ] [[package]] @@ -1054,10 +968,10 @@ dependencies = [ "libc", "measureme", "parking_lot", - "rustc-ap-rustc_graphviz 708.0.0", - "rustc-ap-rustc_index 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", + "rustc-ap-rustc_graphviz", + "rustc-ap-rustc_index", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", "rustc-hash", "rustc-rayon", "rustc-rayon-core", @@ -1069,26 +983,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rustc-ap-rustc_errors" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "988c7a3ecba53728d383c6bd8268c7a4c957244944c05a3f0e448795747d9db9" -dependencies = [ - "annotate-snippets 0.8.0", - "atty", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_lint_defs 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-ap-rustc_span 706.0.0", - "termcolor", - "termize", - "tracing", - "unicode-width", - "winapi", -] - [[package]] name = "rustc-ap-rustc_errors" version = "708.0.0" @@ -1097,11 +991,11 @@ checksum = "5973e5ebae02c6a22f19176946e7a5b520270f8e9caff7e97e2e1de95c06eb79" dependencies = [ "annotate-snippets 0.8.0", "atty", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_lint_defs 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_lint_defs", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", "termcolor", "termize", "tracing", @@ -1115,79 +1009,46 @@ version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d112553937beffff6c801441bed60ba07cce72ce40687de722fc54e2880cd63d" dependencies = [ - "rustc-ap-rustc_ast 708.0.0", + "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_passes", - "rustc-ap-rustc_ast_pretty 708.0.0", - "rustc-ap-rustc_attr 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_errors 708.0.0", - "rustc-ap-rustc_feature 708.0.0", - "rustc-ap-rustc_lexer 708.0.0", - "rustc-ap-rustc_lint_defs 708.0.0", - "rustc-ap-rustc_macros 708.0.0", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_attr", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_lint_defs", + "rustc-ap-rustc_macros", "rustc-ap-rustc_parse", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_session 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", "smallvec", "tracing", ] -[[package]] -name = "rustc-ap-rustc_feature" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10224171d523b2fb814e549b256ab53734abdb4d285f113cd0af887bc73150f3" -dependencies = [ - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_span 706.0.0", -] - [[package]] name = "rustc-ap-rustc_feature" version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0caa284fd8f72aaf8e04aad950ced072ba46aa88fcfa454f195e5fc02811b6b4" dependencies = [ - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_span", ] -[[package]] -name = "rustc-ap-rustc_fs_util" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05d63d5678f4e01bbf61189d86112783357d405a1fb63d52a70be03a8713395" - [[package]] name = "rustc-ap-rustc_fs_util" version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8aecdc1324ccbb7f67a015ee6fd6d267cc189045ff3779fb63880e4f51f58711" -[[package]] -name = "rustc-ap-rustc_graphviz" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f13a83a674d50c3a2400138e4aaecd4d712921f3b8925c22691c85ae2bde235" - [[package]] name = "rustc-ap-rustc_graphviz" version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21bff3ba32d853fbc930bebbc3c2c3bf66788873c2183a57160e2c9c7b9063d" -[[package]] -name = "rustc-ap-rustc_index" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469c83791194b83a480b18441da1f04dbd2671d062a9f2a1c6bc5369b2185360" -dependencies = [ - "arrayvec 0.5.1", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", -] - [[package]] name = "rustc-ap-rustc_index" version = "708.0.0" @@ -1195,17 +1056,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26daf768bf9ad1a492a6a93404d17c34aee58b692fd7515b6b654897e71704c5" dependencies = [ "arrayvec 0.5.1", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", -] - -[[package]] -name = "rustc-ap-rustc_lexer" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f76b414e6f4a136e04c5b2d79785fbf689b6c975f7f40c9fbe314dd9e4345a5" -dependencies = [ - "unicode-xid", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", ] [[package]] @@ -1217,48 +1069,21 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "rustc-ap-rustc_lint_defs" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10363995e377811d2bd42a4700c7ffe1b8fec88c7f207036fc4b797b01941ea4" -dependencies = [ - "rustc-ap-rustc_ast 706.0.0", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-ap-rustc_span 706.0.0", - "rustc-ap-rustc_target 706.0.0", - "tracing", -] - [[package]] name = "rustc-ap-rustc_lint_defs" version = "708.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "493863f3a69509b0cd53f337215ed13a459dd3687c3782fc79f7f02ad021b8d2" dependencies = [ - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_span 708.0.0", - "rustc-ap-rustc_target 708.0.0", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "rustc-ap-rustc_target", "tracing", ] -[[package]] -name = "rustc-ap-rustc_macros" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e106ab6d8fcd906b8e0efd48d14bca07cc7a591a938a0a8844badb8d253897" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - [[package]] name = "rustc-ap-rustc_macros" version = "708.0.0" @@ -1278,29 +1103,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d76291d0a578f974e4ef4d31db587b35db6613b057cb18e5717ed8d0781a678" dependencies = [ "bitflags", - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_ast_pretty 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_errors 708.0.0", - "rustc-ap-rustc_feature 708.0.0", - "rustc-ap-rustc_lexer 708.0.0", - "rustc-ap-rustc_session 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_lexer", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", "smallvec", "tracing", "unicode-normalization", ] -[[package]] -name = "rustc-ap-rustc_serialize" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5791d0d7b4b8f5ab89c80e0558aaae6cc3784b9cd1db5f239f7fa51e618e73" -dependencies = [ - "indexmap", - "smallvec", -] - [[package]] name = "rustc-ap-rustc_serialize" version = "708.0.0" @@ -1311,28 +1126,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "rustc-ap-rustc_session" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0662079826bfb6543f4c261049d497feb5686f71aabdba13befa2f6f41a628" -dependencies = [ - "bitflags", - "getopts", - "num_cpus", - "rustc-ap-rustc_ast 706.0.0", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_errors 706.0.0", - "rustc-ap-rustc_feature 706.0.0", - "rustc-ap-rustc_fs_util 706.0.0", - "rustc-ap-rustc_lint_defs 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-ap-rustc_span 706.0.0", - "rustc-ap-rustc_target 706.0.0", - "tracing", -] - [[package]] name = "rustc-ap-rustc_session" version = "708.0.0" @@ -1342,39 +1135,19 @@ dependencies = [ "bitflags", "getopts", "num_cpus", - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_errors 708.0.0", - "rustc-ap-rustc_feature 708.0.0", - "rustc-ap-rustc_fs_util 708.0.0", - "rustc-ap-rustc_lint_defs 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_span 708.0.0", - "rustc-ap-rustc_target 708.0.0", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", + "rustc-ap-rustc_feature", + "rustc-ap-rustc_fs_util", + "rustc-ap-rustc_lint_defs", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", + "rustc-ap-rustc_target", "tracing", ] -[[package]] -name = "rustc-ap-rustc_span" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12314b0cb62961245fb6f103095f0584877e54439a62cf66278a4c83d6133e1d" -dependencies = [ - "cfg-if 0.1.10", - "md-5", - "rustc-ap-rustc_arena 706.0.0", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_index 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "scoped-tls", - "sha-1", - "sha2", - "tracing", - "unicode-width", -] - [[package]] name = "rustc-ap-rustc_span" version = "708.0.0" @@ -1383,11 +1156,11 @@ checksum = "5c9af35a8e82b7445d5ce593bd93437aa3a93c97a34845c17395c85744531e82" dependencies = [ "cfg-if 0.1.10", "md-5", - "rustc-ap-rustc_arena 708.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_index 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", + "rustc-ap-rustc_arena", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", "scoped-tls", "sha-1", "sha2", @@ -1395,21 +1168,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "rustc-ap-rustc_target" -version = "706.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0b33190c2f2cb83aea78d78c90ee5b29404ecc46abb2d9ce7c270a7c0f132e1" -dependencies = [ - "bitflags", - "rustc-ap-rustc_data_structures 706.0.0", - "rustc-ap-rustc_index 706.0.0", - "rustc-ap-rustc_macros 706.0.0", - "rustc-ap-rustc_serialize 706.0.0", - "rustc-ap-rustc_span 706.0.0", - "tracing", -] - [[package]] name = "rustc-ap-rustc_target" version = "708.0.0" @@ -1417,11 +1175,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d7984c64589b94ba3b192fc97b288ed8c5d549176f264ffe11774c27cecf3fd" dependencies = [ "bitflags", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_index 708.0.0", - "rustc-ap-rustc_macros 708.0.0", - "rustc-ap-rustc_serialize 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", + "rustc-ap-rustc_macros", + "rustc-ap-rustc_serialize", + "rustc-ap-rustc_span", "tracing", ] @@ -1503,15 +1261,15 @@ dependencies = [ "lazy_static", "log", "regex", - "rustc-ap-rustc_ast 708.0.0", - "rustc-ap-rustc_ast_pretty 708.0.0", - "rustc-ap-rustc_attr 706.0.0", - "rustc-ap-rustc_data_structures 708.0.0", - "rustc-ap-rustc_errors 708.0.0", + "rustc-ap-rustc_ast", + "rustc-ap-rustc_ast_pretty", + "rustc-ap-rustc_attr", + "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_errors", "rustc-ap-rustc_expand", "rustc-ap-rustc_parse", - "rustc-ap-rustc_session 708.0.0", - "rustc-ap-rustc_span 708.0.0", + "rustc-ap-rustc_session", + "rustc-ap-rustc_span", "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", diff --git a/Cargo.toml b/Cargo.toml index 554fc70e8ec..84e0f0b5806 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ version = "708.0.0" [dependencies.rustc_attr] package = "rustc-ap-rustc_attr" -version = "706.0.0" +version = "708.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" diff --git a/src/patterns.rs b/src/patterns.rs index 5847bd08d80..f9a9388e4ab 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -17,7 +17,7 @@ use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::types::{rewrite_path, PathContext}; -use crate::utils::{format_mutability, mk_sp, rewrite_ident}; +use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident}; /// Returns `true` if the given pattern is "short". /// A short pattern is defined by the following grammar: @@ -460,7 +460,7 @@ fn rewrite_tuple_pat( let sp = pat_vec[new_item_count - 1].span(); let snippet = context.snippet(sp); let lo = sp.lo() + BytePos(snippet.find_uncommented("_").unwrap() as u32); - pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp(lo, lo + BytePos(1))); + pat_vec[new_item_count - 1] = TuplePatField::Dotdot(mk_sp_lo_plus_one(lo)); ( &pat_vec[..new_item_count], mk_sp(span.lo(), lo + BytePos(1)), diff --git a/src/utils.rs b/src/utils.rs index a3d0ed050e3..d3c349fb701 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -360,6 +360,10 @@ pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi, SyntaxContext::root()) } +pub(crate) fn mk_sp_lo_plus_one(lo: BytePos) -> Span { + Span::new(lo, lo + BytePos(1), SyntaxContext::root()) +} + // Returns `true` if the given span does not intersect with file lines. macro_rules! out_of_file_lines_range { ($self:ident, $span:expr) => { -- cgit 1.4.1-3-g733a5 From 2c6339571bfc97c5eb0516e20ab0d3b9543f87e5 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 14 Mar 2021 13:16:52 -0500 Subject: chore: apply pattern parsing changes --- src/macros.rs | 2 +- src/matches.rs | 21 +++++++++------------ 2 files changed, 10 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index 1abb1cd9e13..190f4b599b0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -132,7 +132,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { ); parse_macro_arg!( Pat, - |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat(None), + |parser: &mut rustc_parse::parser::Parser<'b>| parser.parse_pat_no_top_alt(None), |x: ptr::P| Some(x) ); // `parse_item` returns `Option>`. diff --git a/src/matches.rs b/src/matches.rs index a43aed09ef5..f33fedce92d 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -19,7 +19,7 @@ use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ contains_skip, extra_offset, first_line_width, inner_attributes, last_line_extendable, mk_sp, - semicolon_for_expr, trimmed_last_line_width, unicode_str_width, + mk_sp_lo_plus_one, semicolon_for_expr, trimmed_last_line_width, unicode_str_width, }; /// A simple wrapper type against `ast::Arm`. Used inside `write_list()`. @@ -163,17 +163,14 @@ fn arm_comma(config: &Config, body: &ast::Expr, is_last: bool) -> &'static str { fn collect_beginning_verts( context: &RewriteContext<'_>, arms: &[ast::Arm], - span: Span, ) -> Vec> { - let mut beginning_verts = Vec::with_capacity(arms.len()); - let mut lo = context.snippet_provider.span_after(span, "{"); - for arm in arms { - let hi = arm.pat.span.lo(); - let missing_span = mk_sp(lo, hi); - beginning_verts.push(context.snippet_provider.opt_span_before(missing_span, "|")); - lo = arm.span().hi(); - } - beginning_verts + arms.iter() + .map(|a| { + context + .snippet_provider + .opt_span_before(mk_sp_lo_plus_one(a.pat.span.lo()), "|") + }) + .collect() } fn rewrite_match_arms( @@ -191,7 +188,7 @@ fn rewrite_match_arms( let is_last_iter = repeat(false) .take(arm_len.saturating_sub(1)) .chain(repeat(true)); - let beginning_verts = collect_beginning_verts(context, arms, span); + let beginning_verts = collect_beginning_verts(context, arms); let items = itemize_list( context.snippet_provider, arms.iter() -- cgit 1.4.1-3-g733a5 From 612e8d5b9be72713a081370c85cc5bed30b6fae6 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 28 Mar 2021 16:25:30 -0500 Subject: refactor: apply rustc mod parsing changes --- src/formatting.rs | 2 +- src/items.rs | 4 +- src/modules.rs | 159 +++++++++++++++++++++++++++++++++++---------------- src/syntux/parser.rs | 6 +- src/visitor.rs | 29 +++++----- 5 files changed, 130 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index e42864a5055..2c38de04797 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -145,7 +145,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { module: &Module<'_>, is_macro_def: bool, ) -> Result<(), ErrorKind> { - let snippet_provider = self.parse_session.snippet_provider(module.as_ref().inner); + let snippet_provider = self.parse_session.snippet_provider(module.span); let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, &self.config, diff --git a/src/items.rs b/src/items.rs index 6cdbb686ad8..00757210ce5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3271,8 +3271,8 @@ pub(crate) fn rewrite_extern_crate( /// Returns `true` for `mod foo;`, false for `mod foo { .. }`. pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { match item.kind { - ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), - _ => false, + ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) => false, + _ => true, } } diff --git a/src/modules.rs b/src/modules.rs index eaa889bcb3f..2ee3639ffb1 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -6,6 +6,7 @@ use rustc_ast::ast; use rustc_ast::attr::HasAttrs; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; +use rustc_span::Span; use thiserror::Error; use crate::attr::MetaVisitor; @@ -24,20 +25,31 @@ type FileModMap<'ast> = BTreeMap>; /// Represents module with its inner attributes. #[derive(Debug, Clone)] pub(crate) struct Module<'a> { - ast_mod: Cow<'a, ast::Mod>, + ast_mod_kind: Option>, + pub(crate) items: Cow<'a, Vec>>, + attrs: Cow<'a, Vec>, inner_attr: Vec, + pub(crate) span: Span, } impl<'a> Module<'a> { - pub(crate) fn new(ast_mod: Cow<'a, ast::Mod>, attrs: &[ast::Attribute]) -> Self { - let inner_attr = attrs + pub(crate) fn new( + mod_span: Span, + ast_mod_kind: Option>, + mod_items: Cow<'a, Vec>>, + mod_attrs: Cow<'a, Vec>, + ) -> Self { + let inner_attr = mod_attrs .iter() .filter(|attr| attr.style == ast::AttrStyle::Inner) .cloned() .collect(); Module { - ast_mod, + items: mod_items, + attrs: mod_attrs, inner_attr, + span: mod_span, + ast_mod_kind, } } } @@ -51,12 +63,6 @@ impl<'a> HasAttrs for Module<'a> { } } -impl<'a> AsRef for Module<'a> { - fn as_ref(&self) -> &ast::Mod { - &self.ast_mod - } -} - /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { parse_sess: &'sess ParseSess, @@ -124,12 +130,17 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { // Skip visiting sub modules when the input is from stdin. if self.recursive { - self.visit_mod_from_ast(&krate.module)?; + self.visit_mod_from_ast(&krate.items)?; } self.file_map.insert( root_filename, - Module::new(Cow::Borrowed(&krate.module), &krate.attrs), + Module::new( + krate.span, + None, + Cow::Borrowed(&krate.items), + Cow::Borrowed(&krate.attrs), + ), ); Ok(self.file_map) } @@ -139,10 +150,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); visitor.visit_item(&item); for module_item in visitor.mods() { - if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind { self.visit_sub_mod( &module_item.item, - Module::new(Cow::Owned(sub_mod.clone()), &module_item.item.attrs), + Module::new( + module_item.item.span, + Some(Cow::Owned(sub_mod_kind.clone())), + Cow::Owned(vec![]), + Cow::Owned(vec![]), + ), )?; } } @@ -150,29 +166,53 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } /// Visit modules defined inside macro calls. - fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), ModuleResolutionError> { - for item in module.items { + fn visit_mod_outside_ast( + &mut self, + items: Vec>, + ) -> Result<(), ModuleResolutionError> { + for item in items { if is_cfg_if(&item) { self.visit_cfg_if(Cow::Owned(item.into_inner()))?; continue; } - if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(&item, Module::new(Cow::Owned(sub_mod.clone()), &item.attrs))?; + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + let span = item.span; + self.visit_sub_mod( + &item, + Module::new( + span, + Some(Cow::Owned(sub_mod_kind.clone())), + Cow::Owned(vec![]), + Cow::Owned(vec![]), + ), + )?; } } Ok(()) } /// Visit modules from AST. - fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), ModuleResolutionError> { - for item in &module.items { + fn visit_mod_from_ast( + &mut self, + items: &'ast Vec>, + ) -> Result<(), ModuleResolutionError> { + for item in items { if is_cfg_if(item) { self.visit_cfg_if(Cow::Borrowed(item))?; } - if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(item, Module::new(Cow::Borrowed(sub_mod), &item.attrs))?; + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + let span = item.span; + self.visit_sub_mod( + item, + Module::new( + span, + Some(Cow::Borrowed(sub_mod_kind)), + Cow::Owned(vec![]), + Cow::Borrowed(&item.attrs), + ), + )?; } } Ok(()) @@ -273,9 +313,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if let Some(directory) = directory { self.directory = directory; } - match sub_mod.ast_mod { - Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod), - Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod), + match (sub_mod.ast_mod_kind, sub_mod.items) { + (Some(Cow::Borrowed(ast::ModKind::Loaded(items, ast::Inline::No, _))), _) => { + self.visit_mod_from_ast(&items) + } + (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items), + (_, _) => Ok(()), } } @@ -294,13 +337,17 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if self.parse_sess.is_file_parsed(&path) { return Ok(None); } - return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) - { - Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok(m) => Ok(Some(SubModKind::External( + return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), + Ok((attrs, items, span)) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), ))), Err(ParserError::ParseError) => Err(ModuleResolutionError { module: mod_name.to_string(), @@ -338,18 +385,30 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) { - Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok(m) if outside_mods_empty => Ok(Some(SubModKind::External( - path, - ownership, - Module::new(Cow::Owned(m.0), &m.1), - ))), - Ok(m) => { + match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), + Ok((attrs, items, span)) if outside_mods_empty => { + Ok(Some(SubModKind::External( + path, + ownership, + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), + ))) + } + Ok((attrs, items, span)) => { mods_outside_ast.push(( path.clone(), ownership, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), )); if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); @@ -437,20 +496,22 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - let m = match Parser::parse_file_as_module( - self.parse_sess, - &actual_path, - sub_mod.ast_mod.inner, - ) { - Ok((_, ref attrs)) if contains_skip(attrs) => continue, - Ok(m) => m, - Err(..) => continue, - }; + let (attrs, items, span) = + match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => continue, + Ok(m) => m, + Err(..) => continue, + }; result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), )) } result diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 5c555e06a80..29248ced2ff 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -1,8 +1,8 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; -use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; +use rustc_ast::{ast, ptr}; use rustc_errors::Diagnostic; use rustc_parse::{ new_parser_from_file, @@ -109,10 +109,10 @@ impl<'a> Parser<'a> { sess: &'a ParseSess, path: &Path, span: Span, - ) -> Result<(ast::Mod, Vec), ParserError> { + ) -> Result<(Vec, Vec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); - match parser.parse_mod(&TokenKind::Eof, ast::Unsafe::No) { + match parser.parse_mod(&TokenKind::Eof) { Ok(result) => Some(result), Err(mut e) => { sess.emit_or_cancel_diagnostic(&mut e); diff --git a/src/visitor.rs b/src/visitor.rs index 34e8536b7ee..4cd6b8d56d1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -524,10 +524,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_enum(item.ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); } - ast::ItemKind::Mod(ref module) => { - let is_inline = !is_mod_decl(item); + ast::ItemKind::Mod(unsafety, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); + self.format_mod(mod_kind, unsafety, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -921,8 +920,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { !is_skip_attr(segments) } - fn walk_mod_items(&mut self, m: &ast::Mod) { - self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); + fn walk_mod_items(&mut self, items: &Vec>) { + self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items)); } fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) { @@ -974,22 +973,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn format_mod( &mut self, - m: &ast::Mod, + mod_kind: &ast::ModKind, + unsafety: ast::Unsafe, vis: &ast::Visibility, s: Span, ident: symbol::Ident, attrs: &[ast::Attribute], - is_internal: bool, ) { let vis_str = utils::format_visibility(&self.get_context(), vis); self.push_str(&*vis_str); - self.push_str(format_unsafety(m.unsafety)); + self.push_str(format_unsafety(unsafety)); self.push_str("mod "); // Calling `to_owned()` to work around borrow checker. let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); self.push_str(&ident_str); - if is_internal { + if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, inner_span) = mod_kind { match self.config.brace_style() { BraceStyle::AlwaysNextLine => { let indent_str = self.block_indent.to_string_with_newline(self.config); @@ -1001,7 +1000,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // Hackery to account for the closing }. let mod_lo = self.snippet_provider.span_after(source!(self, s), "{"); let body_snippet = - self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1))); + self.snippet(mk_sp(mod_lo, source!(self, inner_span).hi() - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { self.push_str("}"); @@ -1009,11 +1008,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); self.visit_attrs(attrs, ast::AttrStyle::Inner); - self.walk_mod_items(m); - let missing_span = self.next_span(m.inner.hi() - BytePos(1)); + self.walk_mod_items(items); + let missing_span = self.next_span(inner_span.hi() - BytePos(1)); self.close_block(missing_span, false); } - self.last_pos = source!(self, m.inner).hi(); + self.last_pos = source!(self, inner_span).hi(); } else { self.push_str(";"); self.last_pos = source!(self, s).hi(); @@ -1023,9 +1022,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) { self.block_indent = Indent::empty(); if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) { - self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner); + self.push_skipped_with_span(m.attrs(), m.span, m.span); } else { - self.walk_mod_items(m.as_ref()); + self.walk_mod_items(&m.items); self.format_missing_with_indent(end_pos); } } -- cgit 1.4.1-3-g733a5 From a1dc57ace12c2d530f062a52fad940153fafc93a Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 14 Mar 2021 13:44:02 -0500 Subject: chore: apply AST HasAttrs->AstLike changes --- Cargo.lock | 1 - Cargo.toml | 6 +++--- src/attr.rs | 2 +- src/formatting.rs | 2 +- src/modules.rs | 4 ++-- src/visitor.rs | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index fe1efb2ddf4..4d2b3eacb15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1285,7 +1285,6 @@ dependencies = [ "regex", "rustc-ap-rustc_ast", "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_errors", "rustc-ap-rustc_expand", diff --git a/Cargo.toml b/Cargo.toml index 26175a82cdd..4f114e6afa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,9 +72,9 @@ version = "709.0.0" package = "rustc-ap-rustc_ast_pretty" version = "709.0.0" -[dependencies.rustc_attr] -package = "rustc-ap-rustc_attr" -version = "708.0.0" +# [dependencies.rustc_attr] +# package = "rustc-ap-rustc_attr" +# version = "708.0.0" [dependencies.rustc_data_structures] package = "rustc-ap-rustc_data_structures" diff --git a/src/attr.rs b/src/attr.rs index 2d25c263277..015e9f9b252 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,7 +1,7 @@ //! Format attributes and meta items. use rustc_ast::ast; -use rustc_ast::attr::HasAttrs; +use rustc_ast::AstLike; use rustc_span::{symbol::sym, Span, Symbol}; use self::doc_comment::DocCommentFormatter; diff --git a/src/formatting.rs b/src/formatting.rs index 2c38de04797..ce28f6bfea3 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::io::{self, Write}; use std::time::{Duration, Instant}; -use rustc_ast::ast; +use rustc_ast::{ast, AstLike}; use rustc_span::Span; use self::newline_style::apply_newline_style; diff --git a/src/modules.rs b/src/modules.rs index 2ee3639ffb1..feffd6e4a77 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -3,8 +3,8 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use rustc_ast::ast; -use rustc_ast::attr::HasAttrs; use rustc_ast::visit::Visitor; +use rustc_ast::AstLike; use rustc_span::symbol::{self, sym, Symbol}; use rustc_span::Span; use thiserror::Error; @@ -54,7 +54,7 @@ impl<'a> Module<'a> { } } -impl<'a> HasAttrs for Module<'a> { +impl<'a> AstLike for Module<'a> { fn attrs(&self) -> &[ast::Attribute] { &self.inner_attr } diff --git a/src/visitor.rs b/src/visitor.rs index 4cd6b8d56d1..55cc9ec7f58 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,7 +1,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit}; +use rustc_ast::{ast, token::DelimToken, visit, AstLike}; use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::attr::*; -- cgit 1.4.1-3-g733a5 From 4c617e8fb32045e1d60940ba4c79942ef0301566 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Mon, 15 Mar 2021 20:07:44 -0500 Subject: deps: apply rustc module loading changes --- src/formatting.rs | 2 +- src/modules.rs | 57 +++++++++++++++++++++++++++------------------------ src/syntux/parser.rs | 3 ++- src/syntux/session.rs | 10 ++------- 4 files changed, 35 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/formatting.rs b/src/formatting.rs index ce28f6bfea3..caf24476e61 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -92,7 +92,7 @@ fn format_project( let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( &context.parse_session, - directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod), + directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaBlock), !input_is_stdin && !config.skip_children(), ) .visit_crate(&krate)?; diff --git a/src/modules.rs b/src/modules.rs index feffd6e4a77..ed4316974db 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -13,7 +13,7 @@ use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; use crate::syntux::parser::{ - Directory, DirectoryOwnership, ModulePathSuccess, Parser, ParserError, + Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError, }; use crate::syntux::session::ParseSess; use crate::utils::contains_skip; @@ -61,6 +61,9 @@ impl<'a> AstLike for Module<'a> { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { f(&mut self.inner_attr) } + fn tokens_mut(&mut self) -> Option<&mut Option> { + unimplemented!() + } } /// Maps each module to the corresponding file. @@ -331,7 +334,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { ) -> Result>, ModuleResolutionError> { let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + DirectoryOwnership::UnownedViaBlock => None, }; if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) { if self.parse_sess.is_file_parsed(&path) { @@ -366,31 +369,32 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { match self .parse_sess .default_submod_path(mod_name, relative, &self.directory.path) - .result { Ok(ModulePathSuccess { - path, ownership, .. + file_path, + dir_ownership, + .. }) => { let outside_mods_empty = mods_outside_ast.is_empty(); let should_insert = !mods_outside_ast .iter() - .any(|(outside_path, _, _)| outside_path == &path); - if self.parse_sess.is_file_parsed(&path) { + .any(|(outside_path, _, _)| outside_path == &file_path); + if self.parse_sess.is_file_parsed(&file_path) { if outside_mods_empty { return Ok(None); } else { if should_insert { - mods_outside_ast.push((path, ownership, sub_mod.clone())); + mods_outside_ast.push((file_path, dir_ownership, sub_mod.clone())); } return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + match Parser::parse_file_as_module(self.parse_sess, &file_path, sub_mod.span) { Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), Ok((attrs, items, span)) if outside_mods_empty => { Ok(Some(SubModKind::External( - path, - ownership, + file_path, + dir_ownership, Module::new( span, Some(Cow::Owned(ast::ModKind::Unloaded)), @@ -401,8 +405,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } Ok((attrs, items, span)) => { mods_outside_ast.push(( - path.clone(), - ownership, + file_path.clone(), + dir_ownership, Module::new( span, Some(Cow::Owned(ast::ModKind::Unloaded)), @@ -411,39 +415,38 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { ), )); if should_insert { - mods_outside_ast.push((path, ownership, sub_mod.clone())); + mods_outside_ast.push((file_path, dir_ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } Err(ParserError::ParseError) => Err(ModuleResolutionError { module: mod_name.to_string(), - kind: ModuleResolutionErrorKind::ParseError { file: path }, + kind: ModuleResolutionErrorKind::ParseError { file: file_path }, }), Err(..) if outside_mods_empty => Err(ModuleResolutionError { module: mod_name.to_string(), - kind: ModuleResolutionErrorKind::NotFound { file: path }, + kind: ModuleResolutionErrorKind::NotFound { file: file_path }, }), Err(..) => { if should_insert { - mods_outside_ast.push((path, ownership, sub_mod.clone())); + mods_outside_ast.push((file_path, dir_ownership, sub_mod.clone())); } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } } } - Err(mut e) if !mods_outside_ast.is_empty() => { - e.cancel(); + Err(mod_err) if !mods_outside_ast.is_empty() => { + if let ModError::ParserError(mut e) = mod_err { + e.cancel(); + } Ok(Some(SubModKind::MultiExternal(mods_outside_ast))) } - Err(mut e) => { - e.cancel(); - Err(ModuleResolutionError { - module: mod_name.to_string(), - kind: ModuleResolutionErrorKind::NotFound { - file: self.directory.path.clone(), - }, - }) - } + Err(_) => Err(ModuleResolutionError { + module: mod_name.to_string(), + kind: ModuleResolutionErrorKind::NotFound { + file: self.directory.path.clone(), + }, + }), } } diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 29248ced2ff..0b94749f3c6 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -14,8 +14,9 @@ use crate::attr::first_attr_value_str_by_name; use crate::syntux::session::ParseSess; use crate::Input; -pub(crate) type DirectoryOwnership = rustc_expand::module::DirectoryOwnership; +pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership; pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess; +pub(crate) type ModError<'a> = rustc_expand::module::ModError<'a>; #[derive(Clone)] pub(crate) struct Directory { diff --git a/src/syntux/session.rs b/src/syntux/session.rs index ef5ad62674e..374d08f7f23 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -150,14 +150,8 @@ impl ParseSess { id: symbol::Ident, relative: Option, dir_path: &Path, - ) -> rustc_expand::module::ModulePath<'_> { - rustc_expand::module::default_submod_path( - &self.parse_sess, - id, - rustc_span::DUMMY_SP, - relative, - dir_path, - ) + ) -> Result> { + rustc_expand::module::default_submod_path(&self.parse_sess, id, relative, dir_path) } pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { -- cgit 1.4.1-3-g733a5 From 49489116081f2a90ef2f51f04cf0048fbc1504a7 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 27 Mar 2021 12:19:05 -0500 Subject: deps: apply rustc-ap-* v712 changes --- src/expr.rs | 29 ++++++++++++++++------------- src/items.rs | 12 ++++++------ src/overflow.rs | 8 ++++---- src/patterns.rs | 6 +++--- src/spanned.rs | 4 ++-- src/vertical.rs | 4 ++-- 6 files changed, 33 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 4589b57dacb..1befea9c805 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -106,15 +106,18 @@ pub(crate) fn format_expr( }) } ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref struct_rest) => rewrite_struct_lit( - context, - path, - fields, - struct_rest, - &expr.attrs, - expr.span, - shape, - ), + ast::ExprKind::Struct(ref struct_expr) => { + let ast::StructExpr { ref fields, ref path, ref rest } = **struct_expr; + rewrite_struct_lit( + context, + path, + fields, + rest, + &expr.attrs, + expr.span, + shape, + ) + } ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) } @@ -1496,14 +1499,14 @@ fn rewrite_index( } } -fn struct_lit_can_be_aligned(fields: &[ast::Field], has_base: bool) -> bool { +fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool { !has_base && fields.iter().all(|field| !field.is_shorthand) } fn rewrite_struct_lit<'a>( context: &RewriteContext<'_>, path: &ast::Path, - fields: &'a [ast::Field], + fields: &'a [ast::ExprField], struct_rest: &ast::StructRest, attrs: &[ast::Attribute], span: Span, @@ -1512,7 +1515,7 @@ fn rewrite_struct_lit<'a>( debug!("rewrite_struct_lit: shape {:?}", shape); enum StructLitField<'a> { - Regular(&'a ast::Field), + Regular(&'a ast::ExprField), Base(&'a ast::Expr), Rest(&'a Span), } @@ -1668,7 +1671,7 @@ pub(crate) fn struct_lit_field_separator(config: &Config) -> &str { pub(crate) fn rewrite_field( context: &RewriteContext<'_>, - field: &ast::Field, + field: &ast::ExprField, shape: Shape, prefix_max_width: usize, ) -> Option { diff --git a/src/items.rs b/src/items.rs index 00757210ce5..61b49911e76 100644 --- a/src/items.rs +++ b/src/items.rs @@ -158,7 +158,7 @@ impl<'a> Item<'a> { #[derive(Debug)] enum BodyElement<'a> { // Stmt(&'a ast::Stmt), - // Field(&'a ast::Field), + // Field(&'a ast::ExprField), // Variant(&'a ast::Variant), // Item(&'a ast::Item), ForeignItem(&'a ast::ForeignItem), @@ -1274,7 +1274,7 @@ fn format_unit_struct( pub(crate) fn format_struct_struct( context: &RewriteContext<'_>, struct_parts: &StructParts<'_>, - fields: &[ast::StructField], + fields: &[ast::FieldDef], offset: Indent, one_line_width: Option, ) -> Option { @@ -1411,7 +1411,7 @@ fn format_empty_struct_or_tuple( fn format_tuple_struct( context: &RewriteContext<'_>, struct_parts: &StructParts<'_>, - fields: &[ast::StructField], + fields: &[ast::FieldDef], offset: Indent, ) -> Option { let mut result = String::with_capacity(1024); @@ -1631,7 +1631,7 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) { pub(crate) fn rewrite_struct_field_prefix( context: &RewriteContext<'_>, - field: &ast::StructField, + field: &ast::FieldDef, ) -> Option { let vis = format_visibility(context, &field.vis); let type_annotation_spacing = type_annotation_spacing(context.config); @@ -1646,7 +1646,7 @@ pub(crate) fn rewrite_struct_field_prefix( }) } -impl Rewrite for ast::StructField { +impl Rewrite for ast::FieldDef { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { rewrite_struct_field(context, self, shape, 0) } @@ -1654,7 +1654,7 @@ impl Rewrite for ast::StructField { pub(crate) fn rewrite_struct_field( context: &RewriteContext<'_>, - field: &ast::StructField, + field: &ast::FieldDef, shape: Shape, lhs_max_width: usize, ) -> Option { diff --git a/src/overflow.rs b/src/overflow.rs index 566f0e36639..f1b870101e5 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -74,7 +74,7 @@ pub(crate) enum OverflowableItem<'a> { MacroArg(&'a MacroArg), NestedMetaItem(&'a ast::NestedMetaItem), SegmentParam(&'a SegmentParam<'a>), - StructField(&'a ast::StructField), + FieldDef(&'a ast::FieldDef), TuplePatField(&'a TuplePatField<'a>), Ty(&'a ast::Ty), } @@ -96,7 +96,7 @@ impl<'a> OverflowableItem<'a> { match self { OverflowableItem::Expr(ast::Expr { attrs, .. }) | OverflowableItem::GenericParam(ast::GenericParam { attrs, .. }) => !attrs.is_empty(), - OverflowableItem::StructField(ast::StructField { attrs, .. }) => !attrs.is_empty(), + OverflowableItem::FieldDef(ast::FieldDef { attrs, .. }) => !attrs.is_empty(), OverflowableItem::MacroArg(MacroArg::Expr(expr)) => !expr.attrs.is_empty(), OverflowableItem::MacroArg(MacroArg::Item(item)) => !item.attrs.is_empty(), _ => false, @@ -113,7 +113,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::MacroArg(macro_arg) => f(*macro_arg), OverflowableItem::NestedMetaItem(nmi) => f(*nmi), OverflowableItem::SegmentParam(sp) => f(*sp), - OverflowableItem::StructField(sf) => f(*sf), + OverflowableItem::FieldDef(sf) => f(*sf), OverflowableItem::TuplePatField(pat) => f(*pat), OverflowableItem::Ty(ty) => f(*ty), } @@ -238,7 +238,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { } } -impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, StructField, Ty); +impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty); impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]); pub(crate) fn into_overflowable_list<'a, T>( diff --git a/src/patterns.rs b/src/patterns.rs index f9a9388e4ab..5d43d169d60 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,4 +1,4 @@ -use rustc_ast::ast::{self, BindingMode, FieldPat, Pat, PatKind, RangeEnd, RangeSyntax}; +use rustc_ast::ast::{self, BindingMode, PatField, Pat, PatKind, RangeEnd, RangeSyntax}; use rustc_ast::ptr; use rustc_span::{BytePos, Span}; @@ -259,7 +259,7 @@ impl Rewrite for Pat { fn rewrite_struct_pat( path: &ast::Path, - fields: &[ast::FieldPat], + fields: &[ast::PatField], ellipsis: bool, span: Span, context: &RewriteContext<'_>, @@ -334,7 +334,7 @@ fn rewrite_struct_pat( Some(format!("{} {{{}}}", path_str, fields_str)) } -impl Rewrite for FieldPat { +impl Rewrite for PatField { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let hi_pos = if let Some(last) = self.attrs.last() { last.span.hi() diff --git a/src/spanned.rs b/src/spanned.rs index 1f6d0023e68..7e3786b7cd9 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -53,7 +53,7 @@ macro_rules! implement_spanned { // Implement `Spanned` for structs with `attrs` field. implement_spanned!(ast::AssocItem); implement_spanned!(ast::Expr); -implement_spanned!(ast::Field); +implement_spanned!(ast::ExprField); implement_spanned!(ast::ForeignItem); implement_spanned!(ast::Item); implement_spanned!(ast::Local); @@ -143,7 +143,7 @@ impl Spanned for ast::GenericParam { } } -impl Spanned for ast::StructField { +impl Spanned for ast::FieldDef { fn span(&self) -> Span { span_with_attrs_lo_hi!(self, self.span.lo(), self.ty.span.hi()) } diff --git a/src/vertical.rs b/src/vertical.rs index 95d1d5c2d7e..c4208848c6c 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -33,7 +33,7 @@ pub(crate) trait AlignedItem { ) -> Option; } -impl AlignedItem for ast::StructField { +impl AlignedItem for ast::FieldDef { fn skip(&self) -> bool { contains_skip(&self.attrs) } @@ -72,7 +72,7 @@ impl AlignedItem for ast::StructField { } } -impl AlignedItem for ast::Field { +impl AlignedItem for ast::ExprField { fn skip(&self) -> bool { contains_skip(&self.attrs) } -- cgit 1.4.1-3-g733a5 From c32f2ec0153d364041eb0f7267210741ce7ca275 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 28 Mar 2021 17:30:53 -0500 Subject: chore: fmt and cleanup --- src/expr.rs | 12 ++---------- src/formatting.rs | 2 +- src/patterns.rs | 2 +- 3 files changed, 4 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/expr.rs b/src/expr.rs index 1befea9c805..d3fd22653b4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -107,16 +107,8 @@ pub(crate) fn format_expr( } ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref struct_expr) => { - let ast::StructExpr { ref fields, ref path, ref rest } = **struct_expr; - rewrite_struct_lit( - context, - path, - fields, - rest, - &expr.attrs, - expr.span, - shape, - ) + let ast::StructExpr { fields, path, rest } = &**struct_expr; + rewrite_struct_lit(context, path, fields, rest, &expr.attrs, expr.span, shape) } ast::ExprKind::Tup(ref items) => { rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) diff --git a/src/formatting.rs b/src/formatting.rs index caf24476e61..b69ecdc5cb8 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::io::{self, Write}; use std::time::{Duration, Instant}; -use rustc_ast::{ast, AstLike}; +use rustc_ast::ast; use rustc_span::Span; use self::newline_style::apply_newline_style; diff --git a/src/patterns.rs b/src/patterns.rs index 5d43d169d60..6824fc661ba 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,4 +1,4 @@ -use rustc_ast::ast::{self, BindingMode, PatField, Pat, PatKind, RangeEnd, RangeSyntax}; +use rustc_ast::ast::{self, BindingMode, Pat, PatField, PatKind, RangeEnd, RangeSyntax}; use rustc_ast::ptr; use rustc_span::{BytePos, Span}; -- cgit 1.4.1-3-g733a5 From 61ee1089f0286e86efc268e970df62a7bbe6636f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 16 Feb 2021 22:25:41 -0500 Subject: Use `rustc_private` instead of crates.io dependencies - Update rust-toolchain to also install `rustc-dev` component --- Cargo.toml | 32 +------------------------------- config_proc_macro/src/lib.rs | 2 -- rust-toolchain | 4 +++- src/attr.rs | 2 +- src/lib.rs | 11 +++++++++++ 5 files changed, 16 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index f02d205c049..184c553db1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,34 +64,4 @@ thiserror = "1.0" # for more information. rustc-workspace-hack = "1.0.0" -[dependencies.rustc_ast] -package = "rustc-ap-rustc_ast" -version = "712.0.0" - -[dependencies.rustc_ast_pretty] -package = "rustc-ap-rustc_ast_pretty" -version = "712.0.0" - -[dependencies.rustc_data_structures] -package = "rustc-ap-rustc_data_structures" -version = "712.0.0" - -[dependencies.rustc_errors] -package = "rustc-ap-rustc_errors" -version = "712.0.0" - -[dependencies.rustc_expand] -package = "rustc-ap-rustc_expand" -version = "712.0.0" - -[dependencies.rustc_parse] -package = "rustc-ap-rustc_parse" -version = "712.0.0" - -[dependencies.rustc_session] -package = "rustc-ap-rustc_session" -version = "712.0.0" - -[dependencies.rustc_span] -package = "rustc-ap-rustc_span" -version = "712.0.0" +# Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. diff --git a/config_proc_macro/src/lib.rs b/config_proc_macro/src/lib.rs index 66cfd3c727d..78e7e098ed9 100644 --- a/config_proc_macro/src/lib.rs +++ b/config_proc_macro/src/lib.rs @@ -2,8 +2,6 @@ #![recursion_limit = "256"] -extern crate proc_macro; - mod attrs; mod config_type; mod item_enum; diff --git a/rust-toolchain b/rust-toolchain index 0cb2de6a3fb..c06f7353dfb 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1,3 @@ -nightly-2021-03-26 +[toolchain] +channel = "nightly-2021-03-26" +components = ["rustc-dev"] diff --git a/src/attr.rs b/src/attr.rs index 015e9f9b252..0e8b3072017 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -376,7 +376,7 @@ impl Rewrite for ast::Attribute { } } -impl<'a> Rewrite for [ast::Attribute] { +impl Rewrite for [ast::Attribute] { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { if self.is_empty() { return Some(String::new()); diff --git a/src/lib.rs b/src/lib.rs index db48b52f440..8a798777e0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(rustc_private)] #![deny(rust_2018_idioms)] #![warn(unreachable_pub)] @@ -9,6 +10,16 @@ extern crate lazy_static; #[macro_use] extern crate log; +// N.B. these crates are loaded from the sysroot, so they need extern crate. +extern crate rustc_ast; +extern crate rustc_ast_pretty; +extern crate rustc_data_structures; +extern crate rustc_errors; +extern crate rustc_expand; +extern crate rustc_parse; +extern crate rustc_session; +extern crate rustc_span; + use std::cell::RefCell; use std::collections::HashMap; use std::fmt; -- cgit 1.4.1-3-g733a5 From 943b97c3aedb5f7ed7a585dc986687ef377e1a91 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 16 Feb 2021 23:50:30 -0500 Subject: Fix errors when `parallel_compiler` is enabled --- Cargo.lock | 862 +---------------------------------------------- src/config/file_lines.rs | 4 +- src/source_file.rs | 7 +- src/syntux/session.rs | 123 +++---- src/visitor.rs | 5 +- 5 files changed, 83 insertions(+), 918 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index ad5ed49e360..c89a9f0da1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,12 +20,6 @@ dependencies = [ "ansi_term", ] -[[package]] -name = "annotate-snippets" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" - [[package]] name = "ansi_term" version = "0.11.0" @@ -56,12 +50,6 @@ dependencies = [ "nodrop", ] -[[package]] -name = "arrayvec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" - [[package]] name = "atty" version = "0.2.13" @@ -78,12 +66,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - [[package]] name = "backtrace" version = "0.3.40" @@ -91,7 +73,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" dependencies = [ "backtrace-sys", - "cfg-if 0.1.10", + "cfg-if", "libc", "rustc-demangle", ] @@ -128,19 +110,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182" dependencies = [ "arrayref", - "arrayvec 0.4.12", + "arrayvec", "constant_time_eq", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "bstr" version = "0.2.8" @@ -189,12 +162,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "clap" version = "2.33.0" @@ -219,27 +186,12 @@ dependencies = [ "bitflags", ] -[[package]] -name = "cloudabi" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" -dependencies = [ - "bitflags", -] - [[package]] name = "constant_time_eq" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" -[[package]] -name = "cpuid-bool" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" - [[package]] name = "crossbeam-channel" version = "0.4.0" @@ -249,50 +201,13 @@ dependencies = [ "crossbeam-utils 0.7.0", ] -[[package]] -name = "crossbeam-deque" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils 0.7.0", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg 1.0.1", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.0", - "lazy_static", - "maybe-uninit", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.0", - "maybe-uninit", -] - [[package]] name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "lazy_static", ] @@ -302,8 +217,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" dependencies = [ - "autocfg 0.1.7", - "cfg-if 0.1.10", + "autocfg", + "cfg-if", "lazy_static", ] @@ -324,22 +239,13 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "dirs" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "dirs-sys", ] @@ -349,7 +255,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "libc", "redox_users", "winapi", @@ -361,15 +267,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -[[package]] -name = "ena" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" -dependencies = [ - "log", -] - [[package]] name = "env_logger" version = "0.6.2" @@ -417,16 +314,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -[[package]] -name = "generic-array" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "getopts" version = "0.2.21" @@ -436,17 +323,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "getrandom" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "wasi", -] - [[package]] name = "globset" version = "0.4.4" @@ -460,15 +336,6 @@ dependencies = [ "regex", ] -[[package]] -name = "hashbrown" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "autocfg 1.0.1", -] - [[package]] name = "heck" version = "0.3.1" @@ -505,25 +372,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "indexmap" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e47a3566dd4fd4eec714ae6ceabdee0caec795be835c223d92c2d40f1e8cf1c" -dependencies = [ - "autocfg 1.0.1", - "hashbrown", -] - -[[package]] -name = "instant" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "itertools" version = "0.8.0" @@ -533,32 +381,12 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -[[package]] -name = "jobserver" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b1d42ef453b30b7387e113da1c83ab1605d90c5b4e0eb8e96d016ed3b8c160" -dependencies = [ - "getrandom", - "libc", - "log", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -571,53 +399,13 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" -[[package]] -name = "lock_api" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.10", -] - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "md-5" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15" -dependencies = [ - "block-buffer", - "digest", - "opaque-debug", -] - -[[package]] -name = "measureme" -version = "9.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a98e07fe802486895addb2b5467f33f205e82c426bfaf350f5d8109b137767c" -dependencies = [ - "log", - "memmap", - "parking_lot", - "perf-event-open-sys", - "rustc-hash", - "smallvec", + "cfg-if", ] [[package]] @@ -626,96 +414,21 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "memoffset" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -dependencies = [ - "rustc_version", -] - [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -[[package]] -name = "num_cpus" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -dependencies = [ - "libc", -] - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "packed_simd" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220" dependencies = [ - "cfg-if 0.1.10", -] - -[[package]] -name = "parking_lot" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", + "cfg-if", ] -[[package]] -name = "parking_lot_core" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi 0.1.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "perf-event-open-sys" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce9bedf5da2c234fdf2391ede2b90fabf585355f33100689bc364a3ea558561a" -dependencies = [ - "libc", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" - [[package]] name = "proc-macro-error" version = "0.4.11" @@ -751,15 +464,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "psm" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "659ecfea2142a458893bb7673134bad50b752fea932349c213d6a23874ce3aa7" -dependencies = [ - "cc", -] - [[package]] name = "quick-error" version = "1.2.2" @@ -775,29 +479,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -813,31 +494,13 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3", + "cloudabi", "fuchsia-cprng", "libc", "rand_core 0.4.2", @@ -890,15 +553,6 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rust-argon2" version = "0.5.1" @@ -910,363 +564,18 @@ dependencies = [ "crossbeam-utils 0.6.6", ] -[[package]] -name = "rustc-ap-rustc_arena" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "259cca0e975ecb05fd289ace45280c30ff792efc04e856a7f18b7fc86a3cb610" -dependencies = [ - "rustc-ap-rustc_data_structures", - "smallvec", -] - -[[package]] -name = "rustc-ap-rustc_ast" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb9be435d50c88e94bbad6ea468c8680b52c5043bb298ab8058d05251717f8f8" -dependencies = [ - "bitflags", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "smallvec", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_passes" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75246dd1a95a57f7767e53bde3971baa2d948078e180564709f5ea46cf863ddd" -dependencies = [ - "itertools 0.9.0", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_ast_pretty" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79bede0b44bed453fd0034b7ba492840391f6486bf3e17a1af12922f0b98d4cc" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_span", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_attr" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a92a4a34b996694ca2dab70361c60d2d48c07adce57e8155b7ec75e069e3ea" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", -] - -[[package]] -name = "rustc-ap-rustc_data_structures" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbfa7f82517a1b2efe7106c864c3f930b1da8aff07a27fd317af2f36522fd2e" -dependencies = [ - "arrayvec 0.5.1", - "bitflags", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.0", - "ena", - "indexmap", - "jobserver", - "libc", - "measureme", - "parking_lot", - "rustc-ap-rustc_graphviz", - "rustc-ap-rustc_index", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-hash", - "rustc-rayon", - "rustc-rayon-core", - "smallvec", - "stable_deref_trait", - "stacker", - "tempfile", - "tracing", - "winapi", -] - -[[package]] -name = "rustc-ap-rustc_errors" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a272a5101843bcb40900cc9ccf80ecfec62830bb1f4a242986da4a34c0da89" -dependencies = [ - "annotate-snippets 0.8.0", - "atty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "termcolor", - "termize", - "tracing", - "unicode-width", - "winapi", -] - -[[package]] -name = "rustc-ap-rustc_expand" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bc7988f3facf2402fe057405ef0f7fbacc7e7a483da25e35a35ac09491fbbfb" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_passes", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_attr", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "smallvec", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_feature" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e931cd1580ae60c5737d3fa57633034935e885414e794d83b3e52a81021985c" -dependencies = [ - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_span", -] - -[[package]] -name = "rustc-ap-rustc_fs_util" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe9422e10d5b441d2a78202667bc85d7cf713a087b9ae6cdea0dfc825d79f07" - -[[package]] -name = "rustc-ap-rustc_graphviz" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffffffdef9fd51db69c1d4c045ced8aaab999be5627f2d3a0ce020d74c1f1e50" - -[[package]] -name = "rustc-ap-rustc_index" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6f53afc4f7111c82295cb7ea3878f520bbac6a2c5a12e125b4ca9156498cff" -dependencies = [ - "arrayvec 0.5.1", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", -] - -[[package]] -name = "rustc-ap-rustc_lexer" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8056b05346dff7e39164d0434c6ec443a14ab5fbf6221bd1a56e5abbeae5f60c" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "rustc-ap-rustc_lint_defs" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364c3fb7b3cbdfe3fbb21d4078ff2cb3c58df63cda27995f8b064d21ee6dede5" -dependencies = [ - "rustc-ap-rustc_ast", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "rustc-ap-rustc_target", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_macros" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4607d6879cae3bae4d0369ca4b3a7510fd6295ac32eec088ac975208ba96ca45" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "rustc-ap-rustc_parse" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78d22889bff7ca2346037c9df7ea55c66ffb714f5b50fb62b41975f8ac7a2d70" -dependencies = [ - "bitflags", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_lexer", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", - "smallvec", - "tracing", - "unicode-normalization", -] - -[[package]] -name = "rustc-ap-rustc_serialize" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d33c710120953c0214f47a6caf42064d7e241003b4af36c98a6d6156e70335f1" -dependencies = [ - "indexmap", - "smallvec", -] - -[[package]] -name = "rustc-ap-rustc_session" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d35919041429a90713c8f704fa5209ba159cb554ce74d95722cbc18ac4b4c6f" -dependencies = [ - "bitflags", - "getopts", - "num_cpus", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_feature", - "rustc-ap-rustc_fs_util", - "rustc-ap-rustc_lint_defs", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "rustc-ap-rustc_target", - "tracing", -] - -[[package]] -name = "rustc-ap-rustc_span" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b12170c69603c0bf4b50e5c25fd348aae13b8c6465aa0ef4389c9eaa568e51" -dependencies = [ - "cfg-if 0.1.10", - "md-5", - "rustc-ap-rustc_arena", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "scoped-tls", - "sha-1", - "sha2", - "tracing", - "unicode-width", -] - -[[package]] -name = "rustc-ap-rustc_target" -version = "712.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a8329d92e7dc24b974f759e6c6e97e2bbc47b18d0573343028f8135ca367200" -dependencies = [ - "bitflags", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_index", - "rustc-ap-rustc_macros", - "rustc-ap-rustc_serialize", - "rustc-ap-rustc_span", - "tracing", -] - [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-rayon" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7d6a39f8bfd4421ce720918234d1e672b83824c91345b47c93746839cf1629" -dependencies = [ - "crossbeam-deque", - "either", - "rustc-rayon-core", -] - -[[package]] -name = "rustc-rayon-core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94187d9ea3e8c38fafdbc38acb94eafa7ce155867f6ccb13830466a0d0db8c6" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils 0.7.0", - "lazy_static", - "num_cpus", -] - [[package]] name = "rustc-workspace-hack" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "rustfmt-config_proc_macro" version = "0.2.0" @@ -1280,7 +589,7 @@ dependencies = [ name = "rustfmt-nightly" version = "1.4.37" dependencies = [ - "annotate-snippets 0.6.1", + "annotate-snippets", "anyhow", "bytecount", "cargo_metadata", @@ -1290,18 +599,10 @@ dependencies = [ "env_logger", "getopts", "ignore", - "itertools 0.8.0", + "itertools", "lazy_static", "log", "regex", - "rustc-ap-rustc_ast", - "rustc-ap-rustc_ast_pretty", - "rustc-ap-rustc_data_structures", - "rustc-ap-rustc_errors", - "rustc-ap-rustc_expand", - "rustc-ap-rustc_parse", - "rustc-ap-rustc_session", - "rustc-ap-rustc_span", "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", @@ -1330,18 +631,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "semver" version = "0.9.0" @@ -1389,57 +678,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c" -dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpuid-bool", - "digest", - "opaque-debug", -] - -[[package]] -name = "sha2" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" -dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpuid-bool", - "digest", - "opaque-debug", -] - -[[package]] -name = "smallvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" - -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" - -[[package]] -name = "stacker" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ccb4c06ec57bc82d0f610f1a2963d7648700e43a6f513e564b9c89f7991786" -dependencies = [ - "cc", - "cfg-if 0.1.10", - "libc", - "psm", - "winapi", -] - [[package]] name = "strsim" version = "0.8.0" @@ -1504,20 +742,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "term" version = "0.6.1" @@ -1537,16 +761,6 @@ dependencies = [ "wincolor", ] -[[package]] -name = "termize" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1706be6b564323ce7092f5f7e6b118a14c8ef7ed0e69c8c5329c914a9f101295" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -1603,52 +817,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tracing" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c" -dependencies = [ - "cfg-if 0.1.10", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f0e00789804e99b20f12bc7003ca416309d28a6f495d6af58d1e2c2842461b5" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "typenum" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" - -[[package]] -name = "unicode-normalization" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -dependencies = [ - "smallvec", -] - [[package]] name = "unicode-segmentation" version = "1.3.0" @@ -1696,12 +864,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" - [[package]] name = "winapi" version = "0.3.8" diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 18ae2fd2c47..95e5d0c9153 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -3,9 +3,9 @@ use itertools::Itertools; use std::collections::HashMap; use std::path::PathBuf; -use std::rc::Rc; use std::{cmp, fmt, iter, str}; +use rustc_data_structures::sync::Lrc; use rustc_span::{self, SourceFile}; use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; use serde_json as json; @@ -13,7 +13,7 @@ use thiserror::Error; /// A range of lines in a file, inclusive of both ends. pub struct LineRange { - pub file: Rc, + pub file: Lrc, pub lo: usize, pub hi: usize, } diff --git a/src/source_file.rs b/src/source_file.rs index 1d22c25d922..052b0f9c5d6 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -13,7 +13,8 @@ use crate::config::Config; use crate::create_emitter; #[cfg(test)] use crate::formatting::FileRecord; -use std::rc::Rc; + +use rustc_data_structures::sync::Lrc; // Append a newline to the end of each file. pub(crate) fn append_newline(s: &mut String) { @@ -86,11 +87,11 @@ where // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { - Rc::new(fs::read_to_string(ensure_real_path(filename))?) + Lrc::new(fs::read_to_string(ensure_real_path(filename))?) } else { match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { Some(ori) => ori, - None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), + None => Lrc::new(fs::read_to_string(ensure_real_path(filename))?), } }; diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 374d08f7f23..b17a655c1cb 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -1,6 +1,5 @@ -use std::cell::RefCell; use std::path::Path; -use std::rc::Rc; +use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{Lrc, Send}; use rustc_errors::emitter::{Emitter, EmitterWriter}; @@ -21,8 +20,8 @@ use crate::{Config, ErrorKind, FileName}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { parse_sess: RawParseSess, - ignore_path_set: Rc, - can_reset_errors: Rc>, + ignore_path_set: Lrc, + can_reset_errors: Lrc, } /// Emitter which discards every error. @@ -41,17 +40,17 @@ fn silent_emitter() -> Box { /// Emit errors against every files expect ones specified in the `ignore_path_set`. struct SilentOnIgnoredFilesEmitter { - ignore_path_set: Rc, - source_map: Rc, + ignore_path_set: Lrc, + source_map: Lrc, emitter: Box, has_non_ignorable_parser_errors: bool, - can_reset: Rc>, + can_reset: Lrc, } impl SilentOnIgnoredFilesEmitter { fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { self.has_non_ignorable_parser_errors = true; - *self.can_reset.borrow_mut() = false; + self.can_reset.store(false, Ordering::Release); self.emitter.emit_diagnostic(db); } } @@ -73,7 +72,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { .is_match(&FileName::Real(path.to_path_buf())) { if !self.has_non_ignorable_parser_errors { - *self.can_reset.borrow_mut() = true; + self.can_reset.store(true, Ordering::Release); } return; } @@ -84,9 +83,9 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } fn default_handler( - source_map: Rc, - ignore_path_set: Rc, - can_reset: Rc>, + source_map: Lrc, + ignore_path_set: Lrc, + can_reset: Lrc, hide_parse_errors: bool, ) -> Handler { let supports_color = term::stderr().map_or(false, |term| term.supports_color()); @@ -124,16 +123,16 @@ fn default_handler( impl ParseSess { pub(crate) fn new(config: &Config) -> Result { let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(ignore_path_set) => Rc::new(ignore_path_set), + Ok(ignore_path_set) => Lrc::new(ignore_path_set), Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), }; - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let can_reset_errors = Rc::new(RefCell::new(false)); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); let handler = default_handler( - Rc::clone(&source_map), - Rc::clone(&ignore_path_set), - Rc::clone(&can_reset_errors), + Lrc::clone(&source_map), + Lrc::clone(&ignore_path_set), + Lrc::clone(&can_reset_errors), config.hide_parse_errors(), ); let parse_sess = RawParseSess::with_span_handler(handler, source_map); @@ -204,11 +203,11 @@ impl ParseSess { SnippetProvider::new( source_file.start_pos, source_file.end_pos, - Rc::clone(source_file.src.as_ref().unwrap()), + Lrc::clone(source_file.src.as_ref().unwrap()), ) } - pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option> { + pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option> { self.parse_sess .source_map() .get_source_file(&file_name.into()) @@ -236,7 +235,7 @@ impl ParseSess { } pub(super) fn can_reset_errors(&self) -> bool { - *self.can_reset_errors.borrow() + self.can_reset_errors.load(Ordering::Acquire) } pub(super) fn has_errors(&self) -> bool { @@ -287,9 +286,10 @@ mod tests { use crate::utils::mk_sp; use rustc_span::{FileName as SourceMapFileName, MultiSpan, RealFileName, DUMMY_SP}; use std::path::PathBuf; + use std::sync::atomic::AtomicU32; struct TestEmitter { - num_emitted_errors: Rc>, + num_emitted_errors: Lrc, } impl Emitter for TestEmitter { @@ -297,7 +297,7 @@ mod tests { None } fn emit_diagnostic(&mut self, _db: &Diagnostic) { - *self.num_emitted_errors.borrow_mut() += 1; + self.num_emitted_errors.fetch_add(1, Ordering::Release); } } @@ -314,16 +314,17 @@ mod tests { } fn build_emitter( - num_emitted_errors: Rc>, - can_reset: Rc>, - source_map: Option>, + num_emitted_errors: Lrc, + can_reset: Lrc, + source_map: Option>, ignore_list: Option, ) -> SilentOnIgnoredFilesEmitter { let emitter_writer = TestEmitter { num_emitted_errors }; let source_map = - source_map.unwrap_or_else(|| Rc::new(SourceMap::new(FilePathMapping::empty()))); - let ignore_path_set = - Rc::new(IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap()); + source_map.unwrap_or_else(|| Lrc::new(SourceMap::new(FilePathMapping::empty()))); + let ignore_path_set = Lrc::new( + IgnorePathSet::from_ignore_list(&ignore_list.unwrap_or_default()).unwrap(), + ); SilentOnIgnoredFilesEmitter { has_non_ignorable_parser_errors: false, source_map, @@ -339,10 +340,10 @@ mod tests { #[test] fn handles_fatal_parse_error_in_ignored_file() { - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); source_map.new_source_file( @@ -350,16 +351,16 @@ mod tests { source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), Some(ignore_list), ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); emitter.emit_diagnostic(&fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 1); - assert_eq!(*can_reset_errors.borrow(), false); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); + assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } #[test] @@ -367,26 +368,26 @@ mod tests { if !is_nightly_channel!() { return; } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file( SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), Some(ignore_list), ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); emitter.emit_diagnostic(&non_fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 0); - assert_eq!(*can_reset_errors.borrow(), true); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); + assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } #[test] @@ -394,25 +395,25 @@ mod tests { if !is_nightly_channel!() { return; } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file( SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), None, ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); emitter.emit_diagnostic(&non_fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 1); - assert_eq!(*can_reset_errors.borrow(), false); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); + assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } #[test] @@ -420,9 +421,9 @@ mod tests { if !is_nightly_channel!() { return; } - let num_emitted_errors = Rc::new(RefCell::new(0)); - let can_reset_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let num_emitted_errors = Lrc::new(AtomicU32::new(0)); + let can_reset_errors = Lrc::new(AtomicBool::new(false)); + let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#); let bar_source = String::from(r#"pub fn bar() { 1x; }"#); let foo_source = String::from(r#"pub fn foo() { 1x; }"#); @@ -441,9 +442,9 @@ mod tests { fatal_source, ); let mut emitter = build_emitter( - Rc::clone(&num_emitted_errors), - Rc::clone(&can_reset_errors), - Some(Rc::clone(&source_map)), + Lrc::clone(&num_emitted_errors), + Lrc::clone(&can_reset_errors), + Some(Lrc::clone(&source_map)), Some(ignore_list), ); let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); @@ -454,8 +455,8 @@ mod tests { emitter.emit_diagnostic(&bar_diagnostic); emitter.emit_diagnostic(&foo_diagnostic); emitter.emit_diagnostic(&fatal_diagnostic); - assert_eq!(*num_emitted_errors.borrow(), 2); - assert_eq!(*can_reset_errors.borrow(), false); + assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); + assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } } } diff --git a/src/visitor.rs b/src/visitor.rs index 55cc9ec7f58..079568630cf 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -2,6 +2,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; use rustc_ast::{ast, token::DelimToken, visit, AstLike}; +use rustc_data_structures::sync::Lrc; use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::attr::*; @@ -32,7 +33,7 @@ use crate::{ErrorKind, FormatReport, FormattingError}; /// Creates a string slice corresponding to the specified span. pub(crate) struct SnippetProvider { /// A pointer to the content of the file we are formatting. - big_snippet: Rc, + big_snippet: Lrc, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, /// A end position of the file that this snippet lives. @@ -46,7 +47,7 @@ impl SnippetProvider { Some(&self.big_snippet[start_index..end_index]) } - pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: Rc) -> Self { + pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: Lrc) -> Self { let start_pos = start_pos.to_usize(); let end_pos = end_pos.to_usize(); SnippetProvider { -- cgit 1.4.1-3-g733a5 From ea1611c06eabb6c77d002a6ddc06697604e5077f Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 22 Feb 2020 22:05:07 -0600 Subject: feat(config): expose all width heurstic options --- src/config/config_type.rs | 110 +++++++++++++++++++++++++++++++++++++++++----- src/config/mod.rs | 57 ++++++++++++++++++++---- src/config/options.rs | 6 ++- 3 files changed, 151 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index bd4a847e0f1..7407ac0c03c 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -95,7 +95,15 @@ macro_rules! create_config { pub fn $i(&mut self, value: $ty) { (self.0).$i.2 = value; match stringify!($i) { - "max_width" | "use_small_heuristics" => self.0.set_heuristics(), + "max_width" + | "use_small_heuristics" + | "fn_call_width" + | "single_line_if_else_max_width" + | "attr_fn_like_width" + | "struct_lit_width" + | "struct_variant_width" + | "array_width" + | "chain_width" => self.0.set_heuristics(), "license_template_path" => self.0.set_license_template(), "merge_imports" => self.0.set_merge_imports(), &_ => (), @@ -230,7 +238,15 @@ macro_rules! create_config { } match key { - "max_width" | "use_small_heuristics" => self.set_heuristics(), + "max_width" + | "use_small_heuristics" + | "fn_call_width" + | "single_line_if_else_max_width" + | "attr_fn_like_width" + | "struct_lit_width" + | "struct_variant_width" + | "array_width" + | "chain_width" => self.set_heuristics(), "license_template_path" => self.set_license_template(), "merge_imports" => self.set_merge_imports(), &_ => (), @@ -281,16 +297,88 @@ macro_rules! create_config { )+ } + fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) { + let max_width = self.max_width.2; + let get_width_value = | + was_set: bool, + override_value: usize, + heuristic_value: usize, + config_key: &str, + | -> usize { + if !was_set { + return heuristic_value; + } + if override_value > max_width { + panic!("`{}` cannot have a value that exceeds `max_width`", config_key); + } + override_value + }; + + let fn_call_width = get_width_value( + self.was_set().fn_call_width(), + self.fn_call_width.2, + heuristics.fn_call_width, + "fn_call_width", + ); + self.fn_call_width.2 = fn_call_width; + + let attr_fn_like_width = get_width_value( + self.was_set().attr_fn_like_width(), + self.attr_fn_like_width.2, + heuristics.attr_fn_like_width, + "attr_fn_like_width", + ); + self.attr_fn_like_width.2 = attr_fn_like_width; + + let struct_lit_width = get_width_value( + self.was_set().struct_lit_width(), + self.struct_lit_width.2, + heuristics.struct_lit_width, + "struct_lit_width", + ); + self.struct_lit_width.2 = struct_lit_width; + + let struct_variant_width = get_width_value( + self.was_set().struct_variant_width(), + self.struct_variant_width.2, + heuristics.struct_variant_width, + "struct_variant_width", + ); + self.struct_variant_width.2 = struct_variant_width; + + let array_width = get_width_value( + self.was_set().array_width(), + self.array_width.2, + heuristics.array_width, + "array_width", + ); + self.array_width.2 = array_width; + + let chain_width = get_width_value( + self.was_set().chain_width(), + self.chain_width.2, + heuristics.chain_width, + "chain_width", + ); + self.chain_width.2 = chain_width; + + let single_line_if_else_max_width = get_width_value( + self.was_set().single_line_if_else_max_width(), + self.single_line_if_else_max_width.2, + heuristics.single_line_if_else_max_width, + "single_line_if_else_max_width", + ); + self.single_line_if_else_max_width.2 = single_line_if_else_max_width; + } + fn set_heuristics(&mut self) { - if self.use_small_heuristics.2 == Heuristics::Default { - let max_width = self.max_width.2; - self.set().width_heuristics(WidthHeuristics::scaled(max_width)); - } else if self.use_small_heuristics.2 == Heuristics::Max { - let max_width = self.max_width.2; - self.set().width_heuristics(WidthHeuristics::set(max_width)); - } else { - self.set().width_heuristics(WidthHeuristics::null()); - } + let max_width = self.max_width.2; + match self.use_small_heuristics.2 { + Heuristics::Default => + self.set_width_heuristics(WidthHeuristics::scaled(max_width)), + Heuristics::Max => self.set_width_heuristics(WidthHeuristics::set(max_width)), + Heuristics::Off => self.set_width_heuristics(WidthHeuristics::null()), + }; } fn set_license_template(&mut self) { diff --git a/src/config/mod.rs b/src/config/mod.rs index dfce7977bfe..f16273423ff 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -35,9 +35,26 @@ create_config! { hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment"; tab_spaces: usize, 4, true, "Number of spaces per tab"; newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings"; + indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; + + // Width Heuristics use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \ formatting for items and expressions if they satisfy a heuristic notion of 'small'"; - indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items"; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; + fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \ + falling back to vertical formatting."; + attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \ + attributes before falling back to vertical formatting."; + struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \ + falling back to vertical formatting."; + struct_variant_width: usize, 35, true, "Maximum width in the body of a struct variant before \ + falling back to vertical formatting."; + array_width: usize, 60, true, "Maximum width of an array literal before falling \ + back to vertical formatting."; + chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; + single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \ + expressions. A value of zero means always break if-else expressions."; // Comments. macros, and strings wrap_comments: bool, false, false, "Break comments to fit on the line"; @@ -154,8 +171,6 @@ create_config! { file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; emit_mode: EmitMode, EmitMode::Files, false, "What emit Mode to use when none is supplied"; make_backup: bool, false, false, "Backup changed files"; @@ -394,9 +409,6 @@ mod test { create_config! { // Options that are used by the generated functions max_width: usize, 100, true, "Maximum width of each line"; - use_small_heuristics: Heuristics, Heuristics::Default, true, - "Whether to use different formatting for items and \ - expressions if they satisfy a heuristic notion of 'small'."; license_template_path: String, String::default(), false, "Beginning of file must match license template"; required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false, @@ -408,13 +420,33 @@ mod test { file_lines: FileLines, FileLines::all(), false, "Lines to format; this is not supported in rustfmt.toml, and can only be specified \ via the --file-lines option"; - width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, - "'small' heuristic values"; + // merge_imports deprecation imports_granularity: ImportGranularity, ImportGranularity::Preserve, false, "Merge imports"; merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)"; + // Width Heuristics + use_small_heuristics: Heuristics, Heuristics::Default, true, + "Whether to use different formatting for items and \ + expressions if they satisfy a heuristic notion of 'small'."; + width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false, + "'small' heuristic values"; + + fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \ + falling back to vertical formatting."; + attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \ + attributes before falling back to vertical formatting."; + struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \ + falling back to vertical formatting."; + struct_variant_width: usize, 35, true, "Maximum width in the body of a struct \ + variant before falling back to vertical formatting."; + array_width: usize, 60, true, "Maximum width of an array literal before falling \ + back to vertical formatting."; + chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line."; + single_line_if_else_max_width: usize, 50, true, "Maximum line length for single \ + line if-else expressions. A value of zero means always break if-else expressions."; + // Options that are used by the tests stable_option: bool, false, true, "A stable option"; unstable_option: bool, false, false, "An unstable option"; @@ -519,8 +551,15 @@ mod test { hard_tabs = false tab_spaces = 4 newline_style = "Auto" -use_small_heuristics = "Default" indent_style = "Block" +use_small_heuristics = "Default" +fn_call_width = 60 +attr_fn_like_width = 70 +struct_lit_width = 18 +struct_variant_width = 35 +array_width = 60 +chain_width = 60 +single_line_if_else_max_width = 50 wrap_comments = false format_code_in_doc_comments = false comment_width = 80 diff --git a/src/config/options.rs b/src/config/options.rs index c0491630c00..3b91021813c 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -79,13 +79,15 @@ pub enum TypeDensity { } #[config_type] -/// To what extent does rustfmt pursue its heuristics? +/// Heuristic settings that can be used to simply +/// the configuration of the granular width configurations +/// like `struct_lit_width`, `array_width`, etc. pub enum Heuristics { /// Turn off any heuristics Off, /// Turn on max heuristics Max, - /// Use Rustfmt's defaults + /// Use scaled values based on the value of `max_width` Default, } -- cgit 1.4.1-3-g733a5 From 1bcc1f8df5d3b21f4f41c1fe4f26e7f99fee8c6b Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 22 Feb 2020 22:07:50 -0600 Subject: refactor: apply heuristic config changes in lib --- src/attr.rs | 2 +- src/chains.rs | 2 +- src/expr.rs | 19 ++++--------------- src/items.rs | 6 +++--- src/lists.rs | 2 +- src/macros.rs | 2 +- src/overflow.rs | 2 +- tests/target/issue_4049.rs | 26 ++++++++++++++++++++++++++ 8 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 tests/target/issue_4049.rs (limited to 'src') diff --git a/src/attr.rs b/src/attr.rs index 0e8b3072017..c5ffb074ba5 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -300,7 +300,7 @@ impl Rewrite for ast::MetaItem { // 1 = "]" shape.sub_width(1)?, self.span, - context.config.width_heuristics().attr_fn_like_width, + context.config.attr_fn_like_width(), Some(if has_trailing_comma { SeparatorTactic::Always } else { diff --git a/src/chains.rs b/src/chains.rs index ac14ec9e110..8053f0e8fec 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -577,7 +577,7 @@ impl<'a> ChainFormatterShared<'a> { let one_line_budget = if self.child_count == 1 { shape.width } else { - min(shape.width, context.config.width_heuristics().chain_width) + min(shape.width, context.config.chain_width()) } .saturating_sub(almost_total); diff --git a/src/expr.rs b/src/expr.rs index d3fd22653b4..ced382c4915 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -899,22 +899,11 @@ impl<'a> ControlFlow<'a> { || last_line_offsetted(shape.used_width(), &pat_expr_string)); // Try to format if-else on single line. - if self.allow_single_line - && context - .config - .width_heuristics() - .single_line_if_else_max_width - > 0 - { + if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width); if let Some(cond_str) = trial { - if cond_str.len() - <= context - .config - .width_heuristics() - .single_line_if_else_max_width - { + if cond_str.len() <= context.config.single_line_if_else_max_width() { return Some((cond_str, 0)); } } @@ -1246,7 +1235,7 @@ pub(crate) fn rewrite_call( args.iter(), shape, span, - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), choose_separator_tactic(context, span), ) } @@ -1785,7 +1774,7 @@ pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>( items, shape, span, - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), force_tactic, ) } else { diff --git a/src/items.rs b/src/items.rs index 61b49911e76..ecbd0bd12ec 100644 --- a/src/items.rs +++ b/src/items.rs @@ -505,8 +505,8 @@ impl<'a> FmtVisitor<'a> { ) .collect() }; - let mut items: Vec<_> = - itemize_list_with(self.config.width_heuristics().struct_variant_width); + let mut items: Vec<_> = itemize_list_with(self.config.struct_variant_width()); + // If one of the variants use multiple lines, use multi-lined formatting for all variants. let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n')); let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n')); @@ -1479,7 +1479,7 @@ fn format_tuple_struct( fields.iter(), shape, span, - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), None, )?; } diff --git a/src/lists.rs b/src/lists.rs index bc55ef6686a..ccf8f784c04 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -863,7 +863,7 @@ pub(crate) fn struct_lit_shape( }; let shape_width = shape.width.checked_sub(prefix_width + suffix_width); if let Some(w) = shape_width { - let shape_width = cmp::min(w, context.config.width_heuristics().struct_lit_width); + let shape_width = cmp::min(w, context.config.struct_lit_width()); Some((Some(Shape::legacy(shape_width, shape.indent)), v_shape)) } else { Some((None, v_shape)) diff --git a/src/macros.rs b/src/macros.rs index 190f4b599b0..52534b216a6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -382,7 +382,7 @@ fn rewrite_macro_inner( arg_vec.iter(), shape, mac.span(), - context.config.width_heuristics().fn_call_width, + context.config.fn_call_width(), if trailing_comma { Some(SeparatorTactic::Always) } else { diff --git a/src/overflow.rs b/src/overflow.rs index f1b870101e5..d670b0a41e8 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -318,7 +318,7 @@ pub(crate) fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>> span, lhs, rhs, - context.config.width_heuristics().array_width, + context.config.array_width(), force_separator_tactic, Some(("[", "]")), ) diff --git a/tests/target/issue_4049.rs b/tests/target/issue_4049.rs new file mode 100644 index 00000000000..fe025a0f649 --- /dev/null +++ b/tests/target/issue_4049.rs @@ -0,0 +1,26 @@ +// rustfmt-max_width: 110 +// rustfmt-use_small_heuristics: Max +// rustfmt-hard_tabs: true +// rustfmt-use_field_init_shorthand: true +// rustfmt-overflow_delimited_expr: true + +// https://github.com/rust-lang/rustfmt/issues/4049 +fn foo() { + { + { + if let Some(MpcEv::PlayDrum(pitch, vel)) = + // self.mpc.handle_input(e, /*btn_ctrl_down,*/ tx_launch_to_daw, state_view) + self.mpc.handle_input(e, &mut MyBorrowedState { tx_launch_to_daw, state_view }) + { + println!("bar"); + } + + if let Some(e) = + // self.note_input.handle_input(e, /*btn_ctrl_down,*/ tx_launch_to_daw, state_view) + self.note_input.handle_input(e, &mut MyBorrowedState { tx_launch_to_daw, state_view }) + { + println!("baz"); + } + } + } +} -- cgit 1.4.1-3-g733a5 From a168d92f9a4744ba5ce33a9dac2040c8340e1cf5 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 22 Feb 2020 23:05:58 -0600 Subject: tests: augment heuristics tests --- src/config/mod.rs | 250 +++++++++++++++++++++ .../source/configs/use_small_heuristics/default.rs | 25 +++ tests/source/configs/use_small_heuristics/off.rs | 25 +++ .../target/configs/use_small_heuristics/default.rs | 26 +++ tests/target/configs/use_small_heuristics/off.rs | 25 +++ 5 files changed, 351 insertions(+) create mode 100644 tests/source/configs/use_small_heuristics/default.rs create mode 100644 tests/source/configs/use_small_heuristics/off.rs create mode 100644 tests/target/configs/use_small_heuristics/default.rs create mode 100644 tests/target/configs/use_small_heuristics/off.rs (limited to 'src') diff --git a/src/config/mod.rs b/src/config/mod.rs index f16273423ff..415a8c57a9d 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -722,4 +722,254 @@ make_backup = false assert_eq!(config.imports_granularity(), ImportGranularity::Module); } } + + #[cfg(test)] + mod use_small_heuristics { + use super::*; + + #[test] + fn test_default_sets_correct_widths() { + let toml = r#" + use_small_heuristics = "Default" + max_width = 200 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 120); + assert_eq!(config.attr_fn_like_width(), 140); + assert_eq!(config.chain_width(), 120); + assert_eq!(config.fn_call_width(), 120); + assert_eq!(config.single_line_if_else_max_width(), 100); + assert_eq!(config.struct_lit_width(), 36); + assert_eq!(config.struct_variant_width(), 70); + } + + #[test] + fn test_max_sets_correct_widths() { + let toml = r#" + use_small_heuristics = "Max" + max_width = 120 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 120); + assert_eq!(config.attr_fn_like_width(), 120); + assert_eq!(config.chain_width(), 120); + assert_eq!(config.fn_call_width(), 120); + assert_eq!(config.single_line_if_else_max_width(), 120); + assert_eq!(config.struct_lit_width(), 120); + assert_eq!(config.struct_variant_width(), 120); + } + + #[test] + fn test_off_sets_correct_widths() { + let toml = r#" + use_small_heuristics = "Off" + max_width = 100 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), usize::max_value()); + assert_eq!(config.attr_fn_like_width(), usize::max_value()); + assert_eq!(config.chain_width(), usize::max_value()); + assert_eq!(config.fn_call_width(), usize::max_value()); + assert_eq!(config.single_line_if_else_max_width(), 0); + assert_eq!(config.struct_lit_width(), 0); + assert_eq!(config.struct_variant_width(), 0); + } + + #[test] + fn test_override_works_with_default() { + let toml = r#" + use_small_heuristics = "Default" + array_width = 20 + attr_fn_like_width = 40 + chain_width = 20 + fn_call_width = 90 + single_line_if_else_max_width = 40 + struct_lit_width = 30 + struct_variant_width = 34 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 20); + assert_eq!(config.attr_fn_like_width(), 40); + assert_eq!(config.chain_width(), 20); + assert_eq!(config.fn_call_width(), 90); + assert_eq!(config.single_line_if_else_max_width(), 40); + assert_eq!(config.struct_lit_width(), 30); + assert_eq!(config.struct_variant_width(), 34); + } + + #[test] + fn test_override_with_max() { + let toml = r#" + use_small_heuristics = "Max" + array_width = 20 + attr_fn_like_width = 40 + chain_width = 20 + fn_call_width = 90 + single_line_if_else_max_width = 40 + struct_lit_width = 30 + struct_variant_width = 34 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 20); + assert_eq!(config.attr_fn_like_width(), 40); + assert_eq!(config.chain_width(), 20); + assert_eq!(config.fn_call_width(), 90); + assert_eq!(config.single_line_if_else_max_width(), 40); + assert_eq!(config.struct_lit_width(), 30); + assert_eq!(config.struct_variant_width(), 34); + } + + #[test] + fn test_override_with_off() { + let toml = r#" + use_small_heuristics = "Off" + array_width = 20 + attr_fn_like_width = 40 + chain_width = 20 + fn_call_width = 90 + single_line_if_else_max_width = 40 + struct_lit_width = 30 + struct_variant_width = 34 + "#; + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 20); + assert_eq!(config.attr_fn_like_width(), 40); + assert_eq!(config.chain_width(), 20); + assert_eq!(config.fn_call_width(), 90); + assert_eq!(config.single_line_if_else_max_width(), 40); + assert_eq!(config.struct_lit_width(), 30); + assert_eq!(config.struct_variant_width(), 34); + } + + #[test] + #[should_panic(expected = "`fn_call_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_fn_call_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + fn_call_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic( + expected = "`attr_fn_like_width` cannot have a value that exceeds `max_width" + )] + fn test_panics_when_attr_fn_like_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + attr_fn_like_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic(expected = "`struct_lit_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_struct_lit_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + struct_lit_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic( + expected = "`struct_variant_width` cannot have a value that exceeds `max_width" + )] + fn test_panics_when_struct_variant_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + struct_variant_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic(expected = "`array_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_array_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + array_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic(expected = "`chain_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_chain_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + chain_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic( + expected = "`single_line_if_else_max_width` cannot have a value that exceeds `max_width" + )] + fn test_panics_when_single_line_if_else_max_width_config_exceeds_max_width() { + let toml = r#" + max_width = 80 + single_line_if_else_max_width = 90 + "#; + Config::from_toml(toml, Path::new("")).unwrap(); + } + + #[test] + #[should_panic(expected = "`fn_call_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_fn_call_width_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("fn_call_width", "101"); + } + + #[test] + #[should_panic( + expected = "`attr_fn_like_width` cannot have a value that exceeds `max_width" + )] + fn test_panics_when_attr_fn_like_width_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("attr_fn_like_width", "101"); + } + + #[test] + #[should_panic(expected = "`struct_lit_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_struct_lit_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("struct_lit_width", "101"); + } + + #[test] + #[should_panic( + expected = "`struct_variant_width` cannot have a value that exceeds `max_width" + )] + fn test_panics_when_struct_variant_width_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("struct_variant_width", "101"); + } + + #[test] + #[should_panic(expected = "`array_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_array_width_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("array_width", "101"); + } + + #[test] + #[should_panic(expected = "`chain_width` cannot have a value that exceeds `max_width")] + fn test_panics_when_chain_width_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("chain_width", "101"); + } + + #[test] + #[should_panic( + expected = "`single_line_if_else_max_width` cannot have a value that exceeds `max_width" + )] + fn test_panics_when_single_line_if_else_max_width_override_exceeds_max_width() { + let mut config = Config::default(); + config.override_value("single_line_if_else_max_width", "101"); + } + } } diff --git a/tests/source/configs/use_small_heuristics/default.rs b/tests/source/configs/use_small_heuristics/default.rs new file mode 100644 index 00000000000..68bc40271a1 --- /dev/null +++ b/tests/source/configs/use_small_heuristics/default.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Default + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} diff --git a/tests/source/configs/use_small_heuristics/off.rs b/tests/source/configs/use_small_heuristics/off.rs new file mode 100644 index 00000000000..f76392d2404 --- /dev/null +++ b/tests/source/configs/use_small_heuristics/off.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Off + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} diff --git a/tests/target/configs/use_small_heuristics/default.rs b/tests/target/configs/use_small_heuristics/default.rs new file mode 100644 index 00000000000..d67bd9aafaf --- /dev/null +++ b/tests/target/configs/use_small_heuristics/default.rs @@ -0,0 +1,26 @@ +// rustfmt-use_small_heuristics: Default + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { amet: Consectetur, adipiscing: Elit }, +} + +fn main() { + lorem( + "lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + ); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { dolor } else { sit }; +} diff --git a/tests/target/configs/use_small_heuristics/off.rs b/tests/target/configs/use_small_heuristics/off.rs new file mode 100644 index 00000000000..f76392d2404 --- /dev/null +++ b/tests/target/configs/use_small_heuristics/off.rs @@ -0,0 +1,25 @@ +// rustfmt-use_small_heuristics: Off + +enum Lorem { + Ipsum, + Dolor(bool), + Sit { + amet: Consectetur, + adipiscing: Elit, + }, +} + +fn main() { + lorem("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing"); + + let lorem = Lorem { + ipsum: dolor, + sit: amet, + }; + + let lorem = if ipsum { + dolor + } else { + sit + }; +} -- cgit 1.4.1-3-g733a5 From 78b0728887bbc5ae68471eae72c4505c2aed9a6e Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Fri, 17 Apr 2020 22:39:44 -0500 Subject: refactor: remove panics on misconfigured widths --- src/config/config_type.rs | 7 +++- src/config/mod.rs | 94 +++++++++++++++++++++-------------------------- 2 files changed, 47 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 7407ac0c03c..2f567b25521 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -309,7 +309,12 @@ macro_rules! create_config { return heuristic_value; } if override_value > max_width { - panic!("`{}` cannot have a value that exceeds `max_width`", config_key); + eprintln!( + "`{0}` cannot have a value that exceeds `max_width`. \ + `{0}` will be set to the same value as `max_width`", + config_key, + ); + return max_width; } override_value }; diff --git a/src/config/mod.rs b/src/config/mod.rs index 415a8c57a9d..8c04363b1fd 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -842,134 +842,122 @@ make_backup = false } #[test] - #[should_panic(expected = "`fn_call_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_fn_call_width_config_exceeds_max_width() { + fn test_fn_call_width_config_exceeds_max_width() { let toml = r#" - max_width = 80 - fn_call_width = 90 + max_width = 90 + fn_call_width = 95 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.fn_call_width(), 90); } #[test] - #[should_panic( - expected = "`attr_fn_like_width` cannot have a value that exceeds `max_width" - )] - fn test_panics_when_attr_fn_like_width_config_exceeds_max_width() { + fn test_attr_fn_like_width_config_exceeds_max_width() { let toml = r#" max_width = 80 attr_fn_like_width = 90 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.attr_fn_like_width(), 80); } #[test] - #[should_panic(expected = "`struct_lit_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_struct_lit_config_exceeds_max_width() { + fn test_struct_lit_config_exceeds_max_width() { let toml = r#" - max_width = 80 + max_width = 78 struct_lit_width = 90 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.struct_lit_width(), 78); } #[test] - #[should_panic( - expected = "`struct_variant_width` cannot have a value that exceeds `max_width" - )] - fn test_panics_when_struct_variant_width_config_exceeds_max_width() { + fn test_struct_variant_width_config_exceeds_max_width() { let toml = r#" max_width = 80 struct_variant_width = 90 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.struct_variant_width(), 80); } #[test] - #[should_panic(expected = "`array_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_array_width_config_exceeds_max_width() { + fn test_array_width_config_exceeds_max_width() { let toml = r#" - max_width = 80 - array_width = 90 + max_width = 60 + array_width = 80 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.array_width(), 60); } #[test] - #[should_panic(expected = "`chain_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_chain_width_config_exceeds_max_width() { + fn test_chain_width_config_exceeds_max_width() { let toml = r#" max_width = 80 chain_width = 90 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.chain_width(), 80); } #[test] - #[should_panic( - expected = "`single_line_if_else_max_width` cannot have a value that exceeds `max_width" - )] - fn test_panics_when_single_line_if_else_max_width_config_exceeds_max_width() { + fn test_single_line_if_else_max_width_config_exceeds_max_width() { let toml = r#" - max_width = 80 + max_width = 70 single_line_if_else_max_width = 90 "#; - Config::from_toml(toml, Path::new("")).unwrap(); + let config = Config::from_toml(toml, Path::new("")).unwrap(); + assert_eq!(config.single_line_if_else_max_width(), 70); } #[test] - #[should_panic(expected = "`fn_call_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_fn_call_width_override_exceeds_max_width() { + fn test_override_fn_call_width_exceeds_max_width() { let mut config = Config::default(); config.override_value("fn_call_width", "101"); + assert_eq!(config.fn_call_width(), 100); } #[test] - #[should_panic( - expected = "`attr_fn_like_width` cannot have a value that exceeds `max_width" - )] - fn test_panics_when_attr_fn_like_width_override_exceeds_max_width() { + fn test_override_attr_fn_like_width_exceeds_max_width() { let mut config = Config::default(); config.override_value("attr_fn_like_width", "101"); + assert_eq!(config.attr_fn_like_width(), 100); } #[test] - #[should_panic(expected = "`struct_lit_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_struct_lit_override_exceeds_max_width() { + fn test_override_struct_lit_exceeds_max_width() { let mut config = Config::default(); config.override_value("struct_lit_width", "101"); + assert_eq!(config.struct_lit_width(), 100); } #[test] - #[should_panic( - expected = "`struct_variant_width` cannot have a value that exceeds `max_width" - )] - fn test_panics_when_struct_variant_width_override_exceeds_max_width() { + fn test_override_struct_variant_width_exceeds_max_width() { let mut config = Config::default(); config.override_value("struct_variant_width", "101"); + assert_eq!(config.struct_variant_width(), 100); } #[test] - #[should_panic(expected = "`array_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_array_width_override_exceeds_max_width() { + fn test_override_array_width_exceeds_max_width() { let mut config = Config::default(); config.override_value("array_width", "101"); + assert_eq!(config.array_width(), 100); } #[test] - #[should_panic(expected = "`chain_width` cannot have a value that exceeds `max_width")] - fn test_panics_when_chain_width_override_exceeds_max_width() { + fn test_override_chain_width_exceeds_max_width() { let mut config = Config::default(); config.override_value("chain_width", "101"); + assert_eq!(config.chain_width(), 100); } #[test] - #[should_panic( - expected = "`single_line_if_else_max_width` cannot have a value that exceeds `max_width" - )] - fn test_panics_when_single_line_if_else_max_width_override_exceeds_max_width() { + fn test_override_single_line_if_else_max_width_exceeds_max_width() { let mut config = Config::default(); config.override_value("single_line_if_else_max_width", "101"); + assert_eq!(config.single_line_if_else_max_width(), 100); } } } -- cgit 1.4.1-3-g733a5 From dac2423f3f6a24b81e157c54c8c08f7ccc151295 Mon Sep 17 00:00:00 2001 From: ChinYing-Li Date: Mon, 12 Apr 2021 17:26:18 +0800 Subject: Recognize when a block comment has been ended inside a string literal (#4312) --- src/comment.rs | 3 +++ tests/source/issue-4312.rs | 8 ++++++++ tests/target/issue-4312.rs | 8 ++++++++ 3 files changed, 19 insertions(+) create mode 100644 tests/source/issue-4312.rs create mode 100644 tests/target/issue-4312.rs (limited to 'src') diff --git a/src/comment.rs b/src/comment.rs index 0264a90c7d0..c71302fdd18 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1311,6 +1311,9 @@ where char_kind = FullCodeCharKind::InStringCommented; if chr == '"' { CharClassesStatus::BlockComment(deepness) + } else if chr == '*' && self.base.peek().map(RichChar::get_char) == Some('/') { + char_kind = FullCodeCharKind::InComment; + CharClassesStatus::BlockCommentClosing(deepness - 1) } else { CharClassesStatus::StringInBlockComment(deepness) } diff --git a/tests/source/issue-4312.rs b/tests/source/issue-4312.rs new file mode 100644 index 00000000000..6d00867beab --- /dev/null +++ b/tests/source/issue-4312.rs @@ -0,0 +1,8 @@ +fn main() { + /* " */ + println!("Hello, world!"); + /* abc " */ + println!("Hello, world!"); + /* " abc */ + println!("Hello, world!"); +} diff --git a/tests/target/issue-4312.rs b/tests/target/issue-4312.rs new file mode 100644 index 00000000000..6d00867beab --- /dev/null +++ b/tests/target/issue-4312.rs @@ -0,0 +1,8 @@ +fn main() { + /* " */ + println!("Hello, world!"); + /* abc " */ + println!("Hello, world!"); + /* " abc */ + println!("Hello, world!"); +} -- cgit 1.4.1-3-g733a5 From ddb224a173672a858d233d75fb52ce5967765b44 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 22 Apr 2021 22:33:36 +0900 Subject: Upgrade `annotate-snippets` to 0.8 (#4762) --- Cargo.lock | 15 ++++- Cargo.toml | 2 +- src/format_report_formatter.rs | 146 +++++++++++++++++------------------------ 3 files changed, 74 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/Cargo.lock b/Cargo.lock index c89a9f0da1c..0e12e81904c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,11 +13,11 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" +checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5" dependencies = [ - "ansi_term", + "yansi-term", ] [[package]] @@ -904,3 +904,12 @@ dependencies = [ "winapi", "winapi-util", ] + +[[package]] +name = "yansi-term" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" +dependencies = [ + "winapi", +] diff --git a/Cargo.toml b/Cargo.toml index 184c553db1d..24b3b79343b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ unicode-width = "0.1.5" unicode_categories = "0.1.1" dirs = "2.0.1" ignore = "0.4.11" -annotate-snippets = { version = "0.6", features = ["ansi_term"] } +annotate-snippets = { version = "0.8", features = ["color"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } lazy_static = "1.0.0" diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs index 2fc6c4e8955..c820259256c 100644 --- a/src/format_report_formatter.rs +++ b/src/format_report_formatter.rs @@ -1,8 +1,6 @@ -use crate::config::FileName; use crate::formatting::FormattingError; use crate::{ErrorKind, FormatReport}; -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; +use annotate_snippets::display_list::{DisplayList, FormatOptions}; use annotate_snippets::snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation}; use std::fmt::{self, Display}; @@ -48,91 +46,79 @@ pub struct FormatReportFormatter<'a> { impl<'a> Display for FormatReportFormatter<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let formatter = DisplayListFormatter::new(self.enable_colors, false); let errors_by_file = &self.report.internal.borrow().0; + let opt = FormatOptions { + color: self.enable_colors, + ..Default::default() + }; + for (file, errors) in errors_by_file { for error in errors { - let snippet = formatting_error_to_snippet(file, error); - writeln!(f, "{}\n", formatter.format(&DisplayList::from(snippet)))?; + let error_kind = error.kind.to_string(); + let title = Some(Annotation { + id: if error.is_internal() { + Some("internal") + } else { + None + }, + label: Some(&error_kind), + annotation_type: error_kind_to_snippet_annotation_type(&error.kind), + }); + + let message_suffix = error.msg_suffix(); + let footer = if !message_suffix.is_empty() { + Some(Annotation { + id: None, + label: Some(message_suffix), + annotation_type: AnnotationType::Note, + }) + } else { + None + }; + + let origin = format!("{}:{}", file, error.line); + let slice = Slice { + source: &error.line_buffer.clone(), + line_start: error.line, + origin: Some(origin.as_str()), + fold: false, + annotations: slice_annotation(error).into_iter().collect(), + }; + + let snippet = Snippet { + title, + footer: footer.into_iter().collect(), + slices: vec![slice], + opt, + }; + writeln!(f, "{}\n", DisplayList::from(snippet))?; } } if !errors_by_file.is_empty() { - let snippet = formatting_failure_snippet(self.report.warning_count()); - writeln!(f, "{}", formatter.format(&DisplayList::from(snippet)))?; + let label = format!( + "rustfmt has failed to format. See previous {} errors.", + self.report.warning_count() + ); + let snippet = Snippet { + title: Some(Annotation { + id: None, + label: Some(&label), + annotation_type: AnnotationType::Warning, + }), + footer: Vec::new(), + slices: Vec::new(), + opt, + }; + writeln!(f, "{}", DisplayList::from(snippet))?; } Ok(()) } } -fn formatting_failure_snippet(warning_count: usize) -> Snippet { - Snippet { - title: Some(Annotation { - id: None, - label: Some(format!( - "rustfmt has failed to format. See previous {} errors.", - warning_count - )), - annotation_type: AnnotationType::Warning, - }), - footer: Vec::new(), - slices: Vec::new(), - } -} - -fn formatting_error_to_snippet(file: &FileName, error: &FormattingError) -> Snippet { - let slices = vec![snippet_code_slice(file, error)]; - let title = Some(snippet_title(error)); - let footer = snippet_footer(error).into_iter().collect(); - - Snippet { - title, - footer, - slices, - } -} - -fn snippet_title(error: &FormattingError) -> Annotation { - let annotation_type = error_kind_to_snippet_annotation_type(&error.kind); - - Annotation { - id: title_annotation_id(error), - label: Some(error.kind.to_string()), - annotation_type, - } -} - -fn snippet_footer(error: &FormattingError) -> Option { - let message_suffix = error.msg_suffix(); - - if !message_suffix.is_empty() { - Some(Annotation { - id: None, - label: Some(message_suffix.to_string()), - annotation_type: AnnotationType::Note, - }) - } else { - None - } -} - -fn snippet_code_slice(file: &FileName, error: &FormattingError) -> Slice { - let annotations = slice_annotation(error).into_iter().collect(); - let origin = Some(format!("{}:{}", file, error.line)); - let source = error.line_buffer.clone(); - - Slice { - source, - line_start: error.line, - origin, - fold: false, - annotations, - } -} - -fn slice_annotation(error: &FormattingError) -> Option { +fn slice_annotation(error: &FormattingError) -> Option> { let (range_start, range_length) = error.format_len(); let range_end = range_start + range_length; @@ -140,23 +126,13 @@ fn slice_annotation(error: &FormattingError) -> Option { Some(SourceAnnotation { annotation_type: AnnotationType::Error, range: (range_start, range_end), - label: String::new(), + label: "", }) } else { None } } -fn title_annotation_id(error: &FormattingError) -> Option { - const INTERNAL_ERROR_ID: &str = "internal"; - - if error.is_internal() { - Some(INTERNAL_ERROR_ID.to_string()) - } else { - None - } -} - fn error_kind_to_snippet_annotation_type(error_kind: &ErrorKind) -> AnnotationType { match error_kind { ErrorKind::LineOverflow(..) -- cgit 1.4.1-3-g733a5 From f87414729fc4f18484ab6456701b4a430e5aafc1 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 2 May 2021 10:03:25 -0500 Subject: fix: backport changes for latest rustc api comaptibility --- rust-toolchain | 2 +- src/macros.rs | 6 +++--- src/modules.rs | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/rust-toolchain b/rust-toolchain index c06f7353dfb..d0654ca157b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-03-26" +channel = "nightly-2021-05-01" components = ["rustc-dev"] diff --git a/src/macros.rs b/src/macros.rs index 52534b216a6..bf4769b34aa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::panic::{catch_unwind, AssertUnwindSafe}; use rustc_ast::token::{BinOpToken, DelimToken, Token, TokenKind}; -use rustc_ast::tokenstream::{Cursor, LazyTokenStream, TokenStream, TokenTree}; +use rustc_ast::tokenstream::{Cursor, Spacing, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_parse::parser::{ForceCollect, Parser}; @@ -1212,7 +1212,7 @@ pub(crate) fn convert_try_mac( kind: ast::ExprKind::Try(parser.parse_expr().ok()?), span: mac.span(), // incorrect span, but shouldn't matter too much attrs: ast::AttrVec::new(), - tokens: Some(LazyTokenStream::new(ts)), + tokens: None, }) } else { None @@ -1259,7 +1259,7 @@ impl MacroParser { TokenTree::Token(..) => return None, TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d), }; - let args = tok.joint(); + let args = TokenStream::new(vec![(tok, Spacing::Joint)]); match self.toks.next()? { TokenTree::Token(Token { kind: TokenKind::FatArrow, diff --git a/src/modules.rs b/src/modules.rs index ed4316974db..c3f44068601 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -55,6 +55,7 @@ impl<'a> Module<'a> { } impl<'a> AstLike for Module<'a> { + const SUPPORTS_CUSTOM_INNER_ATTRS: bool = true; fn attrs(&self) -> &[ast::Attribute] { &self.inner_attr } -- cgit 1.4.1-3-g733a5 From 8526acee21b790538b2a1d6ef4413c2a3f765234 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Tue, 4 May 2021 12:06:02 +0100 Subject: Rename span_to_string to span_to_diagnostic_string --- src/syntux/session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/syntux/session.rs b/src/syntux/session.rs index b17a655c1cb..27e7ce5cec2 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -191,7 +191,7 @@ impl ParseSess { } pub(crate) fn span_to_debug_info(&self, span: Span) -> String { - self.parse_sess.source_map().span_to_string(span) + self.parse_sess.source_map().span_to_diagnostic_string(span) } pub(crate) fn inner(&self) -> &RawParseSess { -- cgit 1.4.1-3-g733a5 From e4b5621b0e67fcfc1ee5f912a93559411b345f7c Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Tue, 4 May 2021 13:34:19 +0100 Subject: Only deal with LocalPath in conversion --- src/config/file_lines.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index 95e5d0c9153..22dd091cb51 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -28,7 +28,7 @@ pub enum FileName { impl From for FileName { fn from(name: rustc_span::FileName) -> FileName { match name { - rustc_span::FileName::Real(p) => FileName::Real(p.into_local_path()), + rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(p)) => FileName::Real(p), rustc_span::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin, _ => unreachable!(), } -- cgit 1.4.1-3-g733a5 From ef3136176609785b77fece21d7cc0aca9208965b Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Tue, 4 May 2021 13:37:28 +0100 Subject: Rename `RealFileName::Named` to `LocalPath` --- src/source_file.rs | 2 +- src/syntux/session.rs | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/source_file.rs b/src/source_file.rs index 052b0f9c5d6..5a9a2cbd80c 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -70,7 +70,7 @@ where fn from(filename: &FileName) -> rustc_span::FileName { match filename { FileName::Real(path) => { - rustc_span::FileName::Real(rustc_span::RealFileName::Named(path.to_owned())) + rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(path.to_owned())) } FileName::Stdin => rustc_span::FileName::Custom("stdin".to_owned()), } diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 27e7ce5cec2..870f0acfe39 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -65,7 +65,8 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } if let Some(primary_span) = &db.span.primary_span() { let file_name = self.source_map.span_to_filename(*primary_span); - if let rustc_span::FileName::Real(rustc_span::RealFileName::Named(ref path)) = file_name + if let rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(ref path)) = + file_name { if self .ignore_path_set @@ -157,7 +158,7 @@ impl ParseSess { self.parse_sess .source_map() .get_source_file(&rustc_span::FileName::Real( - rustc_span::RealFileName::Named(path.to_path_buf()), + rustc_span::RealFileName::LocalPath(path.to_path_buf()), )) .is_some() } @@ -347,7 +348,7 @@ mod tests { let source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); source_map.new_source_file( - SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( @@ -374,7 +375,7 @@ mod tests { let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file( - SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( @@ -400,7 +401,7 @@ mod tests { let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let source = String::from(r#"pub fn bar() { 1x; }"#); source_map.new_source_file( - SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), source, ); let mut emitter = build_emitter( @@ -430,15 +431,15 @@ mod tests { let fatal_source = String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#); source_map.new_source_file( - SourceMapFileName::Real(RealFileName::Named(PathBuf::from("bar.rs"))), + SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("bar.rs"))), bar_source, ); source_map.new_source_file( - SourceMapFileName::Real(RealFileName::Named(PathBuf::from("foo.rs"))), + SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))), foo_source, ); source_map.new_source_file( - SourceMapFileName::Real(RealFileName::Named(PathBuf::from("fatal.rs"))), + SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("fatal.rs"))), fatal_source, ); let mut emitter = build_emitter( -- cgit 1.4.1-3-g733a5